summaryrefslogtreecommitdiff
path: root/tools/perf/scripts
diff options
context:
space:
mode:
authorSasha Neftin <sasha.neftin@intel.com>2020-07-01 14:30:43 +0300
committerTony Nguyen <anthony.l.nguyen@intel.com>2020-07-27 08:49:31 -0700
commit643e5c2e8c61fb21fe7a2221528016b9d712526b (patch)
tree33bce684e6b468817f1f11fdeca14c5d95c4f6d7 /tools/perf/scripts
parent94a5181f4bc418a5701e476b65aa347695f9dab3 (diff)
igc: Remove ledctl_ fields from the mac_info structure
LED control currently not implemented. Signed-off-by: Sasha Neftin <sasha.neftin@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Diffstat (limited to 'tools/perf/scripts')
0 files changed, 0 insertions, 0 deletions
'add' style='width: 0.1%;'/> -rw-r--r--Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu25
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio32
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio-adc-ad413046
-rw-r--r--Documentation/ABI/testing/sysfs-bus-pci11
-rw-r--r--Documentation/ABI/testing/sysfs-bus-platform-drivers-amd_x3d_vcache12
-rw-r--r--Documentation/ABI/testing/sysfs-class-firmware-attributes3
-rw-r--r--Documentation/ABI/testing/sysfs-class-typec27
-rw-r--r--Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs45
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-corsair-void38
-rw-r--r--Documentation/ABI/testing/sysfs-driver-spi-intel20
-rw-r--r--Documentation/ABI/testing/sysfs-fs-erofs11
-rw-r--r--Documentation/ABI/testing/sysfs-fs-f2fs13
-rw-r--r--Documentation/PCI/endpoint/pci-endpoint.rst29
-rw-r--r--Documentation/PCI/index.rst1
-rw-r--r--Documentation/PCI/pciebus-howto.rst14
-rw-r--r--Documentation/PCI/tph.rst132
-rw-r--r--Documentation/RCU/stallwarn.rst2
-rw-r--r--Documentation/admin-guide/LSM/apparmor.rst7
-rw-r--r--Documentation/admin-guide/blockdev/zram.rst2
-rw-r--r--Documentation/admin-guide/bug-bisect.rst21
-rw-r--r--Documentation/admin-guide/cgroup-v1/memory.rst82
-rw-r--r--Documentation/admin-guide/cgroup-v2.rst16
-rw-r--r--Documentation/admin-guide/kernel-parameters.rst37
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt85
-rw-r--r--Documentation/admin-guide/kernel-per-CPU-kthreads.rst2
-rw-r--r--Documentation/admin-guide/media/building.rst2
-rw-r--r--Documentation/admin-guide/media/index.rst5
-rw-r--r--Documentation/admin-guide/media/omap4_camera.rst62
-rw-r--r--Documentation/admin-guide/media/raspberrypi-rp1-cfe.dot27
-rw-r--r--Documentation/admin-guide/media/raspberrypi-rp1-cfe.rst78
-rw-r--r--Documentation/admin-guide/media/saa7134.rst2
-rw-r--r--Documentation/admin-guide/media/v4l-drivers.rst2
-rw-r--r--Documentation/admin-guide/mm/transhuge.rst37
-rw-r--r--Documentation/admin-guide/perf/index.rst1
-rw-r--r--Documentation/admin-guide/perf/mrvl-pem-pmu.rst56
-rw-r--r--Documentation/admin-guide/sysctl/fs.rst15
-rw-r--r--Documentation/admin-guide/sysctl/kernel.rst9
-rw-r--r--Documentation/arch/arm64/arm-cca.rst69
-rw-r--r--Documentation/arch/arm64/booting.rst38
-rw-r--r--Documentation/arch/arm64/cpu-feature-registers.rst2
-rw-r--r--Documentation/arch/arm64/elf_hwcaps.rst10
-rw-r--r--Documentation/arch/arm64/gcs.rst227
-rw-r--r--Documentation/arch/arm64/index.rst3
-rw-r--r--Documentation/arch/arm64/mops.rst44
-rw-r--r--Documentation/arch/arm64/silicon-errata.rst2
-rw-r--r--Documentation/arch/arm64/sme.rst4
-rw-r--r--Documentation/arch/arm64/sve.rst4
-rw-r--r--Documentation/arch/loongarch/irq-chip-model.rst64
-rw-r--r--Documentation/arch/powerpc/booting.rst4
-rw-r--r--Documentation/arch/riscv/hwprobe.rst19
-rw-r--r--Documentation/arch/riscv/uabi.rst16
-rw-r--r--Documentation/arch/x86/amd_hsmp.rst67
-rw-r--r--Documentation/arch/x86/boot.rst17
-rw-r--r--Documentation/arch/x86/buslock.rst3
-rw-r--r--Documentation/arch/x86/x86_64/boot-options.rst5
-rw-r--r--Documentation/arch/x86/x86_64/mm.rst35
-rw-r--r--Documentation/block/cmdline-partition.rst5
-rw-r--r--Documentation/block/ublk.rst24
-rw-r--r--Documentation/bpf/btf.rst77
-rw-r--r--Documentation/bpf/verifier.rst4
-rw-r--r--Documentation/core-api/cpu_hotplug.rst2
-rw-r--r--Documentation/core-api/gfp_mask-from-fs-io.rst20
-rw-r--r--Documentation/core-api/index.rst1
-rw-r--r--Documentation/core-api/min_heap.rst300
-rw-r--r--Documentation/core-api/packing.rst71
-rw-r--r--Documentation/core-api/printk-formats.rst20
-rw-r--r--Documentation/core-api/swiotlb.rst4
-rw-r--r--Documentation/core-api/workqueue.rst9
-rw-r--r--Documentation/crypto/api-akcipher.rst4
-rw-r--r--Documentation/crypto/api-sig.rst15
-rw-r--r--Documentation/crypto/api.rst1
-rw-r--r--Documentation/crypto/architecture.rst2
-rw-r--r--Documentation/dev-tools/autofdo.rst168
-rw-r--r--Documentation/dev-tools/checkpatch.rst2
-rw-r--r--Documentation/dev-tools/coccinelle.rst22
-rw-r--r--Documentation/dev-tools/gcov.rst2
-rw-r--r--Documentation/dev-tools/index.rst2
-rw-r--r--Documentation/dev-tools/kasan.rst23
-rw-r--r--Documentation/dev-tools/kgdb.rst20
-rw-r--r--Documentation/dev-tools/kmemleak.rst1
-rw-r--r--Documentation/dev-tools/kmsan.rst2
-rw-r--r--Documentation/dev-tools/kselftest.rst9
-rw-r--r--Documentation/dev-tools/propeller.rst162
-rw-r--r--Documentation/dev-tools/testing-devices.rst47
-rw-r--r--Documentation/devicetree/bindings/Makefile1
-rw-r--r--Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.yaml42
-rw-r--r--Documentation/devicetree/bindings/arm/apple.yaml160
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-at91.yaml6
-rw-r--r--Documentation/devicetree/bindings/arm/cpus.yaml12
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.yaml45
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml28
-rw-r--r--Documentation/devicetree/bindings/arm/pmu.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/qcom.yaml16
-rw-r--r--Documentation/devicetree/bindings/arm/rockchip.yaml47
-rw-r--r--Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml18
-rw-r--r--Documentation/devicetree/bindings/arm/sunxi.yaml6
-rw-r--r--Documentation/devicetree/bindings/arm/tegra.yaml5
-rw-r--r--Documentation/devicetree/bindings/arm/ti/k3.yaml8
-rw-r--r--Documentation/devicetree/bindings/ata/ahci-platform.yaml3
-rw-r--r--Documentation/devicetree/bindings/cache/l2c2x0.yaml5
-rw-r--r--Documentation/devicetree/bindings/cache/qcom,llcc.yaml68
-rw-r--r--Documentation/devicetree/bindings/clock/actions,owl-cmu.txt52
-rw-r--r--Documentation/devicetree/bindings/clock/actions,owl-cmu.yaml60
-rw-r--r--Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml22
-rw-r--r--Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml23
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,meson8-clkc.yaml45
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt51
-rw-r--r--Documentation/devicetree/bindings/clock/gated-fixed-clock.yaml49
-rw-r--r--Documentation/devicetree/bindings/clock/imx93-clock.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml48
-rw-r--r--Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml4
-rw-r--r--Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/mediatek,syscon.yaml4
-rw-r--r--Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml4
-rw-r--r--Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml13
-rw-r--r--Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml51
-rw-r--r--Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml5
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml4
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,ipq5332-gcc.yaml41
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,qcs8300-gcc.yaml66
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sa8775p-camcc.yaml62
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sa8775p-dispcc.yaml79
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sa8775p-videocc.yaml62
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sar2130p-gcc.yaml65
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml3
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,r9a08g045-vbattb.yaml84
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt58
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.yaml74
-rw-r--r--Documentation/devicetree/bindings/clock/samsung,exynos8895-clock.yaml239
-rw-r--r--Documentation/devicetree/bindings/clock/ti/composite.txt4
-rw-r--r--Documentation/devicetree/bindings/clock/ti/divider.txt115
-rw-r--r--Documentation/devicetree/bindings/clock/ti/interface.txt55
-rw-r--r--Documentation/devicetree/bindings/clock/ti/mux.txt78
-rw-r--r--Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml193
-rw-r--r--Documentation/devicetree/bindings/clock/ti/ti,interface-clock.yaml71
-rw-r--r--Documentation/devicetree/bindings/clock/ti/ti,mux-clock.yaml125
-rw-r--r--Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml6
-rw-r--r--Documentation/devicetree/bindings/connector/usb-connector.yaml46
-rw-r--r--Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml6
-rw-r--r--Documentation/devicetree/bindings/cpufreq/qemu,virtual-cpufreq.yaml48
-rw-r--r--Documentation/devicetree/bindings/crypto/qcom-qce.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml250
-rw-r--r--Documentation/devicetree/bindings/display/lvds-data-mapping.yaml31
-rw-r--r--Documentation/devicetree/bindings/display/lvds-dual-ports.yaml63
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml40
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml21
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml22
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml22
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml25
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml24
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml27
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml22
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml19
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,merge.yaml23
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,od.yaml22
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,ovl-2l.yaml22
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,ovl.yaml22
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,postmask.yaml21
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,rdma.yaml22
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,ufoe.yaml21
-rw-r--r--Documentation/devicetree/bindings/display/msm/dp-controller.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/msm/gmu.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml241
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml10
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-dpu.yaml122
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8150-dpu.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml99
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8350-dpu.yaml120
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml139
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8550-dpu.yaml133
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml14
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml20
-rw-r--r--Documentation/devicetree/bindings/display/samsung/samsung,exynos7-decon.yaml4
-rw-r--r--Documentation/devicetree/bindings/dma/dma-common.yaml7
-rw-r--r--Documentation/devicetree/bindings/dma/qcom,gpi.yaml1
-rw-r--r--Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml29
-rw-r--r--Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml15
-rw-r--r--Documentation/devicetree/bindings/dma/stm32/st,stm32-dma3.yaml6
-rw-r--r--Documentation/devicetree/bindings/dsp/fsl,dsp.yaml31
-rw-r--r--Documentation/devicetree/bindings/eeprom/at24.yaml2
-rw-r--r--Documentation/devicetree/bindings/example-schema.yaml1
-rw-r--r--Documentation/devicetree/bindings/firmware/arm,scmi.yaml17
-rw-r--r--Documentation/devicetree/bindings/firmware/qcom,scm.yaml6
-rw-r--r--Documentation/devicetree/bindings/fpga/altera-passive-serial.txt29
-rw-r--r--Documentation/devicetree/bindings/fpga/altr,fpga-passive-serial.yaml74
-rw-r--r--Documentation/devicetree/bindings/gpio/aspeed,ast2400-gpio.yaml19
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-mmio.yaml13
-rw-r--r--Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml1
-rw-r--r--Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml3
-rw-r--r--Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml2
-rw-r--r--Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.yaml66
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml148
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/mps,mp2975.yaml75
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml83
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/vicor,pli1209bc.yaml62
-rw-r--r--Documentation/devicetree/bindings/hwmon/pwm-fan.yaml10
-rw-r--r--Documentation/devicetree/bindings/hwmon/renesas,isl28022.yaml64
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml86
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml1
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml8
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-imx.yaml4
-rw-r--r--Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml1
-rw-r--r--Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml4
-rw-r--r--Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml19
-rw-r--r--Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml69
-rw-r--r--Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml18
-rw-r--r--Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml13
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adc.yaml4
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml120
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml199
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml176
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml110
-rw-r--r--Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml1
-rw-r--r--Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml86
-rw-r--r--Documentation/devicetree/bindings/iio/adc/sprd,sc2720-adc.yaml17
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml9
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml39
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml164
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml69
-rw-r--r--Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml79
-rw-r--r--Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml51
-rw-r--r--Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml7
-rw-r--r--Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml4
-rw-r--r--Documentation/devicetree/bindings/iio/light/veml6030.yaml64
-rw-r--r--Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml107
-rw-r--r--Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml21
-rw-r--r--Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml46
-rw-r--r--Documentation/devicetree/bindings/iio/pressure/bmp085.yaml22
-rw-r--r--Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml6
-rw-r--r--Documentation/devicetree/bindings/input/goodix,gt7986u-spifw.yaml69
-rw-r--r--Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml3
-rw-r--r--Documentation/devicetree/bindings/input/rotary-encoder.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/novatek,nvt-ts.yaml62
-rw-r--r--Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.txt22
-rw-r--r--Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.yaml36
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml2
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml73
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml72
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml117
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml12
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml86
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/atmel,aic.yaml1
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/fsl,mu-msi.yaml4
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml1
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/renesas,rzv2h-icu.yaml278
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml58
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.yaml1
-rw-r--r--Documentation/devicetree/bindings/iommu/arm,smmu.yaml5
-rw-r--r--Documentation/devicetree/bindings/iommu/riscv,iommu.yaml147
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt23
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.yaml36
-rw-r--r--Documentation/devicetree/bindings/leds/common.yaml16
-rw-r--r--Documentation/devicetree/bindings/leds/leds-bcm63138.yaml11
-rw-r--r--Documentation/devicetree/bindings/leds/leds-mt6323.txt63
-rw-r--r--Documentation/devicetree/bindings/leds/leds-pca955x.txt89
-rw-r--r--Documentation/devicetree/bindings/leds/leds-pwm.yaml6
-rw-r--r--Documentation/devicetree/bindings/leds/nxp,pca955x.yaml158
-rw-r--r--Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml31
-rw-r--r--Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml2
-rw-r--r--Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml13
-rw-r--r--Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml13
-rw-r--r--Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml2
-rw-r--r--Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml89
-rw-r--r--Documentation/devicetree/bindings/media/i2c/adv7180.yaml6
-rw-r--r--Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml10
-rw-r--r--Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml5
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml120
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov5648.yaml11
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov8865.yaml10
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml7
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml8
-rw-r--r--Documentation/devicetree/bindings/media/i2c/thine,thp7312.yaml3
-rw-r--r--Documentation/devicetree/bindings/media/qcom,msm8953-camss.yaml322
-rw-r--r--Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml93
-rw-r--r--Documentation/devicetree/bindings/media/renesas,csi2.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/renesas,isp.yaml4
-rw-r--r--Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml2
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml5
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ddr.yaml31
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml32
-rw-r--r--Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml90
-rw-r--r--Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml8
-rw-r--r--Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml598
-rw-r--r--Documentation/devicetree/bindings/mfd/mt6397.txt110
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml4
-rw-r--r--Documentation/devicetree/bindings/mfd/realtek,rtl9301-switch.yaml114
-rw-r--r--Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml13
-rw-r--r--Documentation/devicetree/bindings/mfd/samsung,s2dos05.yaml99
-rw-r--r--Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml252
-rw-r--r--Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt40
-rw-r--r--Documentation/devicetree/bindings/mfd/syscon.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/ti,twl.yaml32
-rw-r--r--Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml3
-rw-r--r--Documentation/devicetree/bindings/mfd/zii,rave-sp.txt39
-rw-r--r--Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml63
-rw-r--r--Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml3
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc-card.yaml52
-rw-r--r--Documentation/devicetree/bindings/mmc/mtk-sd.yaml24
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.yaml4
-rw-r--r--Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml8
-rw-r--r--Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml22
-rw-r--r--Documentation/devicetree/bindings/net/dsa/realtek.yaml46
-rw-r--r--Documentation/devicetree/bindings/net/ethernet-phy.yaml21
-rw-r--r--Documentation/devicetree/bindings/net/fsl,enetc-mdio.yaml11
-rw-r--r--Documentation/devicetree/bindings/net/fsl,enetc.yaml28
-rw-r--r--Documentation/devicetree/bindings/net/fsl,fec.yaml7
-rw-r--r--Documentation/devicetree/bindings/net/marvell,aquantia.yaml6
-rw-r--r--Documentation/devicetree/bindings/net/mdio-mux-gpio.yaml32
-rw-r--r--Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml20
-rw-r--r--Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml104
-rw-r--r--Documentation/devicetree/bindings/net/nxp,tja11xx.yaml16
-rw-r--r--Documentation/devicetree/bindings/net/qcom,ethqos.yaml19
-rw-r--r--Documentation/devicetree/bindings/net/renesas,ether.yaml4
-rw-r--r--Documentation/devicetree/bindings/net/sff,sfp.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/snps,dwmac.yaml5
-rw-r--r--Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml110
-rw-r--r--Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml9
-rw-r--r--Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml6
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml29
-rw-r--r--Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/xlnx,emaclite.yaml5
-rw-r--r--Documentation/devicetree/bindings/nvmem/renesas,rcar-efuse.yaml (renamed from Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml)35
-rw-r--r--Documentation/devicetree/bindings/nvmem/renesas,rcar-otp.yaml (renamed from Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml)17
-rw-r--r--Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt52
-rw-r--r--Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml68
-rw-r--r--Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml61
-rw-r--r--Documentation/devicetree/bindings/nvmem/sprd-efuse.txt39
-rw-r--r--Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt40
-rw-r--r--Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml54
-rw-r--r--Documentation/devicetree/bindings/opp/operating-points-v2-ti-cpu.yaml20
-rw-r--r--Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml5
-rw-r--r--Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml5
-rw-r--r--Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml11
-rw-r--r--Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml14
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml4
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml9
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie.yaml50
-rw-r--r--Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml1
-rw-r--r--Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml7
-rw-r--r--Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml4
-rw-r--r--Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml10
-rw-r--r--Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.yaml19
-rw-r--r--Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml42
-rw-r--r--Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/mediatek,tphy.yaml10
-rw-r--r--Documentation/devicetree/bindings/phy/microchip,sparx5-serdes.yaml17
-rw-r--r--Documentation/devicetree/bindings/phy/nxp,ptn3222.yaml55
-rw-r--r--Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/phy-rockchip-inno-hdmi.txt43
-rw-r--r--Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml7
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml3
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml49
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml1
-rw-r--r--Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml45
-rw-r--r--Documentation/devicetree/bindings/phy/rockchip,rk3228-hdmi-phy.yaml97
-rw-r--r--Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml119
-rw-r--r--Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml13
-rw-r--r--Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml400
-rw-r--r--Documentation/devicetree/bindings/pinctrl/amlogic,meson8-pinctrl-cbus.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml5
-rw-r--r--Documentation/devicetree/bindings/pinctrl/canaan,k230-pinctrl.yaml127
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt33
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.yaml (renamed from Documentation/devicetree/bindings/pinctrl/fsl,imx6ul-pinctrl.yaml)88
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx50-pinctrl.txt32
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt32
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt32
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt38
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt38
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt39
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx6sll-pinctrl.txt40
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imx6sx-pinctrl.txt36
-rw-r--r--Documentation/devicetree/bindings/pinctrl/microchip,mcp23s08.yaml161
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml27
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt148
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,ipq5424-tlmm.yaml114
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml3
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,qcs615-tlmm.yaml124
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,qcs8300-tlmm.yaml118
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml8
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sar2130p-tlmm.yaml138
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8650-lpass-lpi-pinctrl.yaml6
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8750-tlmm.yaml138
-rw-r--r--Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml23
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml3
-rw-r--r--Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml43
-rw-r--r--Documentation/devicetree/bindings/pinctrl/sophgo,cv1800-pinctrl.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml124
-rw-r--r--Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml176
-rw-r--r--Documentation/devicetree/bindings/pinctrl/xlnx,versal-pinctrl.yaml278
-rw-r--r--Documentation/devicetree/bindings/power/fsl,imx-gpc.yaml1
-rw-r--r--Documentation/devicetree/bindings/power/mediatek,power-controller.yaml1
-rw-r--r--Documentation/devicetree/bindings/power/qcom,rpmpd.yaml4
-rw-r--r--Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt20
-rw-r--r--Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml4
-rw-r--r--Documentation/devicetree/bindings/power/reset/qcom,pon.yaml7
-rw-r--r--Documentation/devicetree/bindings/power/reset/reboot-mode.yaml4
-rw-r--r--Documentation/devicetree/bindings/power/reset/syscon-reboot-mode.yaml4
-rw-r--r--Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml11
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml1
-rw-r--r--Documentation/devicetree/bindings/power/supply/sc2731-charger.yaml21
-rw-r--r--Documentation/devicetree/bindings/power/supply/sc27xx-fg.yaml43
-rw-r--r--Documentation/devicetree/bindings/power/supply/ti,twl6030-charger.yaml48
-rw-r--r--Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/airoha,en7581-pwm.yaml34
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml1
-rw-r--r--Documentation/devicetree/bindings/regulator/lltc,ltc3676.yaml167
-rw-r--r--Documentation/devicetree/bindings/regulator/ltc3676.txt94
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml12
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml2
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom-labibb-regulator.yaml7
-rw-r--r--Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml21
-rw-r--r--Documentation/devicetree/bindings/regulator/vctrl-regulator.yaml80
-rw-r--r--Documentation/devicetree/bindings/regulator/vctrl.txt49
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml3
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml48
-rw-r--r--Documentation/devicetree/bindings/reset/nuvoton,npcm750-reset.yaml18
-rw-r--r--Documentation/devicetree/bindings/riscv/extensions.yaml58
-rw-r--r--Documentation/devicetree/bindings/riscv/starfive.yaml1
-rw-r--r--Documentation/devicetree/bindings/rng/airoha,en7581-trng.yaml38
-rw-r--r--Documentation/devicetree/bindings/rng/brcm,bcm74110-rng.yaml35
-rw-r--r--Documentation/devicetree/bindings/rng/imx-rng.yaml2
-rw-r--r--Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml (renamed from Documentation/devicetree/bindings/rng/omap_rng.yaml)17
-rw-r--r--Documentation/devicetree/bindings/rng/st,stm32-rng.yaml28
-rw-r--r--Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml4
-rw-r--r--Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml63
-rw-r--r--Documentation/devicetree/bindings/rtc/microchip,mpfs-rtc.yaml (renamed from Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml)10
-rw-r--r--Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml84
-rw-r--r--Documentation/devicetree/bindings/rtc/rtc-mt6397.txt31
-rw-r--r--Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml16
-rw-r--r--Documentation/devicetree/bindings/serial/rs485.yaml19
-rw-r--r--Documentation/devicetree/bindings/serial/samsung_uart.yaml14
-rw-r--r--Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml13
-rw-r--r--Documentation/devicetree/bindings/serial/sprd-uart.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/imx/fsl,imx-anatop.yaml20
-rw-r--r--Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml83
-rw-r--r--Documentation/devicetree/bindings/soc/mediatek/scpsys.txt1
-rw-r--r--Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml20
-rw-r--r--Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml24
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml4
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml3
-rw-r--r--Documentation/devicetree/bindings/soc/rockchip/grf.yaml5
-rw-r--r--Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/adi,adau1373.yaml111
-rw-r--r--Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml53
-rw-r--r--Documentation/devicetree/bindings/sound/audio-graph.yaml6
-rw-r--r--Documentation/devicetree/bindings/sound/awinic,aw88395.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,cs42l84.yaml56
-rw-r--r--Documentation/devicetree/bindings/sound/everest,es8316.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/everest,es8326.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/everest,es8328.yaml4
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,esai.yaml28
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,spdif.yaml27
-rw-r--r--Documentation/devicetree/bindings/sound/inno-rk3036.txt20
-rw-r--r--Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml53
-rw-r--r--Documentation/devicetree/bindings/sound/loongson,ls2k1000-i2s.yaml68
-rw-r--r--Documentation/devicetree/bindings/sound/maxim,max98390.yaml8
-rw-r--r--Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml7
-rw-r--r--Documentation/devicetree/bindings/sound/mt6359.yaml10
-rw-r--r--Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml73
-rw-r--r--Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml70
-rw-r--r--Documentation/devicetree/bindings/sound/nxp,uda1342.yaml42
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,sm8250.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/realtek,rt5640.yaml146
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip,rk3036-codec.yaml58
-rw-r--r--Documentation/devicetree/bindings/sound/rt5640.txt97
-rw-r--r--Documentation/devicetree/bindings/sound/simple-audio-mux.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/simple-card.yaml12
-rw-r--r--Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml56
-rw-r--r--Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml47
-rw-r--r--Documentation/devicetree/bindings/sound/sprd-mcdt.txt19
-rw-r--r--Documentation/devicetree/bindings/sound/sprd-pcm.txt23
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml36
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-sai.yaml26
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml4
-rw-r--r--Documentation/devicetree/bindings/spi/apple,spi.yaml62
-rw-r--r--Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.txt38
-rw-r--r--Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.yaml53
-rw-r--r--Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml62
-rw-r--r--Documentation/devicetree/bindings/spi/samsung,spi.yaml4
-rw-r--r--Documentation/devicetree/bindings/spi/spi-sprd.txt33
-rw-r--r--Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml22
-rw-r--r--Documentation/devicetree/bindings/spi/sprd,sc9860-spi.yaml72
-rw-r--r--Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml1
-rw-r--r--Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml6
-rw-r--r--Documentation/devicetree/bindings/sram/qcom,imem.yaml1
-rw-r--r--Documentation/devicetree/bindings/sram/sram.yaml6
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-tsens.yaml2
-rw-r--r--Documentation/devicetree/bindings/timer/actions,owl-timer.txt21
-rw-r--r--Documentation/devicetree/bindings/timer/actions,owl-timer.yaml107
-rw-r--r--Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.yaml2
-rw-r--r--Documentation/devicetree/bindings/trivial-devices.yaml18
-rw-r--r--Documentation/devicetree/bindings/ufs/qcom,ufs.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml5
-rw-r--r--Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ehci.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ohci.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/genesys,gl850g.yaml9
-rw-r--r--Documentation/devicetree/bindings/usb/maxim,max33359.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml7
-rw-r--r--Documentation/devicetree/bindings/usb/qcom,dwc3.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/renesas,usbhs.yaml4
-rw-r--r--Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/ti,tusb1046.yaml49
-rw-r--r--Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml55
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml16
-rw-r--r--Documentation/devicetree/bindings/watchdog/apple,wdt.yaml5
-rw-r--r--Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml1
-rw-r--r--Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.txt39
-rw-r--r--Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.yaml47
-rw-r--r--Documentation/devicetree/bindings/writing-schema.rst30
-rw-r--r--Documentation/doc-guide/kernel-doc.rst1
-rw-r--r--Documentation/dontdiff271
-rw-r--r--Documentation/driver-api/auxiliary_bus.rst1
-rw-r--r--Documentation/driver-api/driver-model/devres.rst6
-rw-r--r--Documentation/driver-api/media/camera-sensor.rst8
-rw-r--r--Documentation/driver-api/media/drivers/ipu6.rst15
-rw-r--r--Documentation/driver-api/media/tx-rx.rst13
-rw-r--r--Documentation/driver-api/pci/pci.rst3
-rw-r--r--Documentation/driver-api/pwrseq.rst8
-rw-r--r--Documentation/fault-injection/fault-injection.rst40
-rw-r--r--Documentation/features/locking/queued-spinlocks/arch-support.txt2
-rw-r--r--Documentation/filesystems/autofs.rst2
-rw-r--r--Documentation/filesystems/dlmfs.rst2
-rw-r--r--Documentation/filesystems/f2fs.rst44
-rw-r--r--Documentation/filesystems/fsverity.rst2
-rw-r--r--Documentation/filesystems/index.rst1
-rw-r--r--Documentation/filesystems/iomap/operations.rst15
-rw-r--r--Documentation/filesystems/mount_api.rst3
-rw-r--r--Documentation/filesystems/multigrain-ts.rst125
-rw-r--r--Documentation/filesystems/nfs/exporting.rst7
-rw-r--r--Documentation/filesystems/overlayfs.rst17
-rw-r--r--Documentation/filesystems/path-lookup.rst2
-rw-r--r--Documentation/filesystems/path-lookup.txt2
-rw-r--r--Documentation/filesystems/porting.rst2
-rw-r--r--Documentation/filesystems/proc.rst2
-rw-r--r--Documentation/filesystems/ramfs-rootfs-initramfs.rst2
-rw-r--r--Documentation/filesystems/tmpfs.rst24
-rw-r--r--Documentation/gpu/amdgpu/index.rst1
-rw-r--r--Documentation/gpu/amdgpu/process-isolation.rst59
-rw-r--r--Documentation/gpu/amdgpu/thermal.rst12
-rw-r--r--Documentation/gpu/i915.rst4
-rw-r--r--Documentation/gpu/msm-preemption.rst99
-rw-r--r--Documentation/hwmon/f71882fg.rst9
-rw-r--r--Documentation/hwmon/ina2xx.rst46
-rw-r--r--Documentation/hwmon/index.rst2
-rw-r--r--Documentation/hwmon/isl28022.rst63
-rw-r--r--Documentation/hwmon/ltc2978.rst12
-rw-r--r--Documentation/hwmon/max31827.rst2
-rw-r--r--Documentation/hwmon/nct7363.rst35
-rw-r--r--Documentation/hwmon/pmbus-core.rst15
-rw-r--r--Documentation/hwmon/sch5627.rst2
-rw-r--r--Documentation/hwmon/sht4x.rst14
-rw-r--r--Documentation/hwmon/tmp108.rst8
-rw-r--r--Documentation/i2c/busses/i2c-i801.rst1
-rw-r--r--Documentation/i2c/busses/i2c-piix4.rst63
-rw-r--r--Documentation/i2c/writing-clients.rst3
-rw-r--r--Documentation/iio/ad7380.rst16
-rw-r--r--Documentation/iio/ad7606.rst144
-rw-r--r--Documentation/iio/ad7625.rst91
-rw-r--r--Documentation/iio/bno055.rst2
-rw-r--r--Documentation/iio/index.rst2
-rw-r--r--Documentation/input/input.rst2
-rw-r--r--Documentation/kbuild/kbuild.rst8
-rw-r--r--Documentation/kbuild/kconfig-language.rst4
-rw-r--r--Documentation/kbuild/llvm.rst3
-rw-r--r--Documentation/kbuild/makefiles.rst14
-rw-r--r--Documentation/kbuild/modules.rst29
-rw-r--r--Documentation/kernel-hacking/false-sharing.rst4
-rw-r--r--Documentation/kernel-hacking/hacking.rst2
-rw-r--r--Documentation/locking/percpu-rw-semaphore.rst4
-rw-r--r--Documentation/locking/seqlock.rst2
-rw-r--r--Documentation/maintainer/pull-requests.rst2
-rw-r--r--Documentation/mm/allocation-profiling.rst7
-rw-r--r--Documentation/mm/damon/index.rst6
-rw-r--r--Documentation/mm/page_tables.rst2
-rw-r--r--Documentation/mm/slub.rst9
-rw-r--r--Documentation/mm/split_page_table_lock.rst6
-rw-r--r--Documentation/netlink/specs/dpll.yaml41
-rw-r--r--Documentation/netlink/specs/ethtool.yaml11
-rw-r--r--Documentation/netlink/specs/mptcp_pm.yaml1
-rw-r--r--Documentation/netlink/specs/net_shaper.yaml362
-rw-r--r--Documentation/netlink/specs/netdev.yaml35
-rw-r--r--Documentation/netlink/specs/rt_link.yaml19
-rw-r--r--Documentation/netlink/specs/rt_neigh.yaml442
-rw-r--r--Documentation/netlink/specs/rt_rule.yaml242
-rw-r--r--Documentation/netlink/specs/tc.yaml2
-rw-r--r--Documentation/networking/bonding.rst11
-rw-r--r--Documentation/networking/cdc_mbim.rst2
-rw-r--r--Documentation/networking/device_drivers/ethernet/intel/ice.rst31
-rw-r--r--Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst91
-rw-r--r--Documentation/networking/device_drivers/ethernet/meta/fbnic.rst43
-rw-r--r--Documentation/networking/device_drivers/wwan/t7xx.rst64
-rw-r--r--Documentation/networking/devlink/octeontx2.rst21
-rw-r--r--Documentation/networking/devmem.rst9
-rw-r--r--Documentation/networking/diagnostic/index.rst17
-rw-r--r--Documentation/networking/diagnostic/twisted_pair_layer1_diagnostics.rst767
-rw-r--r--Documentation/networking/ethtool-netlink.rst3
-rw-r--r--Documentation/networking/index.rst1
-rw-r--r--Documentation/networking/j1939.rst2
-rw-r--r--Documentation/networking/kapi.rst3
-rw-r--r--Documentation/networking/napi.rst170
-rw-r--r--Documentation/networking/net_cachelines/inet_connection_sock.rst86
-rw-r--r--Documentation/networking/net_cachelines/inet_sock.rst74
-rw-r--r--Documentation/networking/net_cachelines/net_device.rst359
-rw-r--r--Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst300
-rw-r--r--Documentation/networking/net_cachelines/snmp.rst256
-rw-r--r--Documentation/networking/net_cachelines/tcp_sock.rst250
-rw-r--r--Documentation/networking/net_dim.rst2
-rw-r--r--Documentation/networking/timestamping.rst14
-rw-r--r--Documentation/networking/tipc.rst2
-rw-r--r--Documentation/networking/tls-offload.rst29
-rw-r--r--Documentation/process/5.Posting.rst5
-rw-r--r--Documentation/process/backporting.rst8
-rw-r--r--Documentation/process/changes.rst2
-rw-r--r--Documentation/process/code-of-conduct-interpretation.rst87
-rw-r--r--Documentation/process/debugging/driver_development_debugging_guide.rst223
-rw-r--r--Documentation/process/debugging/index.rst78
-rw-r--r--Documentation/process/debugging/media_specific_debugging_guide.rst180
-rw-r--r--Documentation/process/debugging/userspace_debugging_guide.rst280
-rw-r--r--Documentation/process/index.rst8
-rw-r--r--Documentation/process/kernel-docs.rst163
-rw-r--r--Documentation/process/license-rules.rst18
-rw-r--r--Documentation/process/maintainer-tip.rst4
-rw-r--r--Documentation/rust/coding-guidelines.rst146
-rw-r--r--Documentation/rust/index.rst3
-rw-r--r--Documentation/rust/quick-start.rst17
-rw-r--r--Documentation/scheduler/sched-ext.rst71
-rw-r--r--Documentation/security/landlock.rst14
-rw-r--r--Documentation/sound/designs/compress-accel.rst134
-rw-r--r--Documentation/sound/designs/index.rst1
-rw-r--r--Documentation/sound/hd-audio/notes.rst2
-rw-r--r--Documentation/sound/soc/clocking.rst12
-rw-r--r--Documentation/sound/soc/dapm.rst3
-rw-r--r--Documentation/sound/soc/dpcm.rst11
-rw-r--r--Documentation/sound/soc/machine.rst26
-rw-r--r--Documentation/staging/magic-number.rst6
-rw-r--r--Documentation/timers/delay_sleep_functions.rst121
-rw-r--r--Documentation/timers/index.rst2
-rw-r--r--Documentation/timers/timers-howto.rst115
-rw-r--r--Documentation/tools/rtla/common_timerlat_options.rst8
-rw-r--r--Documentation/trace/ftrace.rst7
-rw-r--r--Documentation/trace/histogram.rst2
-rw-r--r--Documentation/trace/index.rst1
-rw-r--r--Documentation/translations/it_IT/dev-tools/clang-format.rst (renamed from Documentation/translations/it_IT/process/clang-format.rst)0
-rw-r--r--Documentation/translations/it_IT/dev-tools/index.rst17
-rw-r--r--Documentation/translations/it_IT/i2c/summary.rst72
-rw-r--r--Documentation/translations/it_IT/index.rst8
-rw-r--r--Documentation/translations/it_IT/process/2.Process.rst6
-rw-r--r--Documentation/translations/it_IT/process/4.Coding.rst2
-rw-r--r--Documentation/translations/it_IT/process/5.Posting.rst5
-rw-r--r--Documentation/translations/it_IT/process/changes.rst33
-rw-r--r--Documentation/translations/it_IT/process/coding-style.rst37
-rw-r--r--Documentation/translations/it_IT/process/email-clients.rst33
-rw-r--r--Documentation/translations/it_IT/process/howto.rst10
-rw-r--r--Documentation/translations/it_IT/process/index.rst10
-rw-r--r--Documentation/translations/it_IT/process/submit-checklist.rst167
-rw-r--r--Documentation/translations/it_IT/process/submitting-patches.rst23
-rw-r--r--Documentation/translations/it_IT/staging/index.rst13
-rw-r--r--Documentation/translations/it_IT/staging/magic-number.rst (renamed from Documentation/translations/it_IT/process/magic-number.rst)0
-rw-r--r--Documentation/translations/ja_JP/process/howto.rst10
-rw-r--r--Documentation/translations/sp_SP/scheduler/index.rst1
-rw-r--r--Documentation/translations/sp_SP/scheduler/sched-bwc.rst287
-rw-r--r--Documentation/translations/zh_CN/arch/loongarch/irq-chip-model.rst55
-rw-r--r--Documentation/translations/zh_CN/dev-tools/gcov.rst8
-rw-r--r--Documentation/translations/zh_CN/dev-tools/index.rst2
-rw-r--r--Documentation/translations/zh_CN/dev-tools/kasan.rst20
-rw-r--r--Documentation/translations/zh_CN/dev-tools/kmsan.rst392
-rw-r--r--Documentation/translations/zh_CN/glossary.rst1
-rw-r--r--Documentation/translations/zh_CN/kbuild/index.rst9
-rw-r--r--Documentation/translations/zh_CN/kbuild/kbuild.rst304
-rw-r--r--Documentation/translations/zh_CN/kbuild/kconfig.rst259
-rw-r--r--Documentation/translations/zh_CN/kbuild/llvm.rst203
-rw-r--r--Documentation/translations/zh_CN/kbuild/reproducible-builds.rst114
-rw-r--r--Documentation/translations/zh_CN/mm/active_mm.rst5
-rw-r--r--Documentation/translations/zh_CN/mm/damon/faq.rst17
-rw-r--r--Documentation/translations/zh_CN/mm/hmm.rst8
-rw-r--r--Documentation/translations/zh_CN/mm/index.rst2
-rw-r--r--Documentation/translations/zh_CN/mm/overcommit-accounting.rst3
-rw-r--r--Documentation/translations/zh_CN/mm/page_owner.rst46
-rw-r--r--Documentation/translations/zh_CN/mm/page_table_check.rst13
-rw-r--r--Documentation/translations/zh_CN/mm/page_tables.rst221
-rw-r--r--Documentation/translations/zh_CN/mm/physical_memory.rst356
-rw-r--r--Documentation/translations/zh_CN/process/5.Posting.rst4
-rw-r--r--Documentation/translations/zh_CN/process/coding-style.rst11
-rw-r--r--Documentation/translations/zh_CN/process/email-clients.rst9
-rw-r--r--Documentation/translations/zh_CN/process/programming-language.rst78
-rw-r--r--Documentation/translations/zh_CN/process/submitting-patches.rst19
-rw-r--r--Documentation/translations/zh_TW/dev-tools/gcov.rst8
-rw-r--r--Documentation/translations/zh_TW/dev-tools/kasan.rst21
-rw-r--r--Documentation/translations/zh_TW/process/5.Posting.rst4
-rw-r--r--Documentation/userspace-api/ioctl/ioctl-number.rst2
-rw-r--r--Documentation/userspace-api/iommufd.rst226
-rw-r--r--Documentation/userspace-api/landlock.rst90
-rw-r--r--Documentation/userspace-api/media/rc/lirc-set-send-duty-cycle.rst2
-rw-r--r--Documentation/userspace-api/media/v4l/control.rst6
-rw-r--r--Documentation/userspace-api/media/v4l/meta-formats.rst1
-rw-r--r--Documentation/userspace-api/media/v4l/metafmt-pisp-fe.rst39
-rw-r--r--Documentation/userspace-api/media/v4l/pixfmt-y16i.rst73
-rw-r--r--Documentation/userspace-api/media/v4l/subdev-formats.rst156
-rw-r--r--Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst18
-rw-r--r--Documentation/userspace-api/media/v4l/yuv-formats.rst1
-rw-r--r--Documentation/userspace-api/media/videodev2.h.rst.exceptions1
-rw-r--r--Documentation/virt/kvm/api.rst190
-rw-r--r--Documentation/virt/kvm/locking.rst80
-rw-r--r--Documentation/virt/kvm/s390/s390-diag.rst35
-rw-r--r--Documentation/virt/kvm/x86/errata.rst12
-rw-r--r--Documentation/wmi/devices/alienware-wmi.rst397
-rw-r--r--Documentation/wmi/driver-development-guide.rst7
-rw-r--r--MAINTAINERS942
-rw-r--r--Makefile249
-rw-r--r--arch/Kconfig56
-rw-r--r--arch/alpha/configs/defconfig1
-rw-r--r--arch/alpha/include/asm/Kbuild1
-rw-r--r--arch/alpha/include/asm/io.h1
-rw-r--r--arch/alpha/include/asm/page.h8
-rw-r--r--arch/alpha/include/asm/spinlock_types.h2
-rw-r--r--arch/alpha/include/uapi/asm/mman.h3
-rw-r--r--arch/alpha/include/uapi/asm/socket.h2
-rw-r--r--arch/alpha/kernel/osf_sys.c5
-rw-r--r--arch/alpha/kernel/pci-sysfs.c6
-rw-r--r--arch/alpha/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/arc/include/asm/Kbuild1
-rw-r--r--arch/arc/include/asm/io.h3
-rw-r--r--arch/arc/include/uapi/asm/page.h7
-rw-r--r--arch/arc/kernel/devtree.c2
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/Kconfig.debug12
-rw-r--r--arch/arm/Makefile4
-rw-r--r--arch/arm/boot/dts/allwinner/Makefile5
-rw-r--r--arch/arm/boot/dts/allwinner/sun8i-a33-vstar-core1.dtsi96
-rw-r--r--arch/arm/boot/dts/allwinner/sun8i-a33-vstar.dts205
-rw-r--r--arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts4
-rw-r--r--arch/arm/boot/dts/amlogic/Makefile2
-rw-r--r--arch/arm/boot/dts/amlogic/meson6-atv1200.dts33
-rw-r--r--arch/arm/boot/dts/amlogic/meson6.dtsi73
-rw-r--r--arch/arm/boot/dts/amlogic/meson8-minix-neo-x8.dts5
-rw-r--r--arch/arm/boot/dts/amlogic/meson8.dtsi32
-rw-r--r--arch/arm/boot/dts/amlogic/meson8b-ec100.dts8
-rw-r--r--arch/arm/boot/dts/amlogic/meson8b-mxq.dts2
-rw-r--r--arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts4
-rw-r--r--arch/arm/boot/dts/amlogic/meson8b.dtsi32
-rw-r--r--arch/arm/boot/dts/amlogic/meson8m2-mxiii-plus.dts2
-rw-r--r--arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts4
-rw-r--r--arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts1
-rw-r--r--arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts2
-rw-r--r--arch/arm/boot/dts/microchip/Makefile3
-rw-r--r--arch/arm/boot/dts/microchip/aks-cdu.dts12
-rw-r--r--arch/arm/boot/dts/microchip/animeo_ip.dts8
-rw-r--r--arch/arm/boot/dts/microchip/at91-kizbox2-common.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sam9x60ek.dts37
-rw-r--r--arch/arm/boot/dts/microchip/at91-sam9x75_curiosity.dts324
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d27_som1.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts33
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama5d3_xplained.dts2
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts31
-rw-r--r--arch/arm/boot/dts/microchip/at91-sama7g5ek.dts33
-rw-r--r--arch/arm/boot/dts/microchip/at91rm9200ek.dts6
-rw-r--r--arch/arm/boot/dts/microchip/at91sam9260ek.dts6
-rw-r--r--arch/arm/boot/dts/microchip/at91sam9261ek.dts6
-rw-r--r--arch/arm/boot/dts/microchip/at91sam9263ek.dts6
-rw-r--r--arch/arm/boot/dts/microchip/at91sam9g20ek.dts4
-rw-r--r--arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/at91sam9g45.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/sam9x60.dtsi14
-rw-r--r--arch/arm/boot/dts/microchip/sam9x7.dtsi1220
-rw-r--r--arch/arm/boot/dts/microchip/sama5d2.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/sama5d3.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/sama5d34ek.dts2
-rw-r--r--arch/arm/boot/dts/microchip/sama5d3xcm_cmp.dtsi2
-rw-r--r--arch/arm/boot/dts/microchip/sama5d4.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/Makefile4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx35-eukrea-cpuimx35.dtsi62
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx35-eukrea-mbimxsd35-baseboard.dts88
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx35-pdk.dts38
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx35.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx50-evk.dts62
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx50.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-apf51.dts56
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts176
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-babbage.dts438
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-jsk.dts78
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi292
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-eukrea-cpuimx51.dtsi68
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51-eukrea-mbimxsd51-baseboard.dts192
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx51.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-ard.dts116
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-kp-ddc.dts62
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-kp.dtsi90
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-m53.dtsi64
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts268
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts320
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-mba53.dts114
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-qsb-common.dtsi274
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-qsrb.dts10
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-smd.dts242
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi274
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts112
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts62
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-tx53.dtsi460
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-voipac-bsb.dts110
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi124
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx53.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6-logicpd-baseboard.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-colibri-aster.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-pdk2.dts20
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-picoitx.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-eckelmann-ci4x10.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi446
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts360
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-arm2.dts198
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-ba16.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-dhcom-pdk2.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts232
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-gk802.dts92
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-h100.dts200
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-logicpd.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-lxr.dts87
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-mba6.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-novena.dts48
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-sbc6x.dts82
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010-comtft.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020-comtft.dts1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6q-utilite-pro.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos.dtsi428
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi6
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi136
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-dfi-fs700-m60.dtsi192
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-pdk2.dtsi21
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-som.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-ds.dtsi6
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi39
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi160
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2-emmc.dtsi30
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi456
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi14
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi354
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi506
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi406
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-wlbt-05.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pfla02.dtsi292
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-rex.dtsi274
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi554
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sabrelite.dtsi428
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi430
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-solidsense.dtsi78
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-brcm.dtsi86
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-emmc.dtsi30
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-ti.dtsi88
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som.dtsi96
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi1
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-mb7.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi3
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-udoo.dtsi224
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revb1.dtsi30
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revc1.dtsi32
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi78
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi247
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qp-sabreauto.dts40
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6qp-sabresd.dts58
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6s-dhcom-drc02.dts2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts480
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts16
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine3.dts16
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision5.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts208
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sl.dtsi11
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts12
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-a.dts23
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-b.dts23
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-common.dtsi511
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clarahd.dts16
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sll-kobo-librah2o.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sll.dtsi24
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts4
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi572
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts18
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6sx.dtsi11
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ul.dtsi16
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx6ull.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi2
-rw-r--r--arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi5
-rw-r--r--arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts2
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8064.dtsi38
-rw-r--r--arch/arm/boot/dts/qcom/qcom-apq8084.dtsi78
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi19
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts2
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8226.dtsi34
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8660.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8916-smp.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8960.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts2
-rw-r--r--arch/arm/boot/dts/qcom/qcom-msm8974.dtsi92
-rw-r--r--arch/arm/boot/dts/qcom/qcom-sdx55.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/qcom-sdx65.dtsi67
-rw-r--r--arch/arm/boot/dts/renesas/emev2-kzm9d.dts11
-rw-r--r--arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi3
-rw-r--r--arch/arm/boot/dts/renesas/iwg20d-q7-dbcm-ca.dtsi3
-rw-r--r--arch/arm/boot/dts/renesas/r7s72100-genmai.dts199
-rw-r--r--arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts14
-rw-r--r--arch/arm/boot/dts/renesas/r7s72100.dtsi37
-rw-r--r--arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a73a4.dtsi2
-rw-r--r--arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7742-iwg21m.dtsi3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7742.dtsi2
-rw-r--r--arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7743.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7744.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm-dbhd-ca.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7745.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a77470-iwg23s-sbc.dts6
-rw-r--r--arch/arm/boot/dts/renesas/r8a7778-bockw.dts5
-rw-r--r--arch/arm/boot/dts/renesas/r8a7778.dtsi2
-rw-r--r--arch/arm/boot/dts/renesas/r8a7779-marzen.dts9
-rw-r--r--arch/arm/boot/dts/renesas/r8a7779.dtsi2
-rw-r--r--arch/arm/boot/dts/renesas/r8a7790-lager.dts25
-rw-r--r--arch/arm/boot/dts/renesas/r8a7790-stout.dts15
-rw-r--r--arch/arm/boot/dts/renesas/r8a7790.dtsi2
-rw-r--r--arch/arm/boot/dts/renesas/r8a7791-koelsch.dts17
-rw-r--r--arch/arm/boot/dts/renesas/r8a7791-porter.dts12
-rw-r--r--arch/arm/boot/dts/renesas/r8a7791.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7792-blanche.dts9
-rw-r--r--arch/arm/boot/dts/renesas/r8a7792-wheat.dts3
-rw-r--r--arch/arm/boot/dts/renesas/r8a7792.dtsi2
-rw-r--r--arch/arm/boot/dts/renesas/r8a7793-gose.dts15
-rw-r--r--arch/arm/boot/dts/renesas/r8a7793.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/r8a7794-alt.dts14
-rw-r--r--arch/arm/boot/dts/renesas/r8a7794-silk.dts9
-rw-r--r--arch/arm/boot/dts/renesas/r8a7794.dtsi1
-rw-r--r--arch/arm/boot/dts/renesas/sh73a0-kzm9g.dts17
-rw-r--r--arch/arm/boot/dts/renesas/sh73a0.dtsi1
-rw-r--r--arch/arm/boot/dts/rockchip/Makefile1
-rw-r--r--arch/arm/boot/dts/rockchip/rk3036-kylin.dts6
-rw-r--r--arch/arm/boot/dts/rockchip/rk3036.dtsi14
-rw-r--r--arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts6
-rw-r--r--arch/arm/boot/dts/rockchip/rk3066a-mk808.dts12
-rw-r--r--arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts16
-rw-r--r--arch/arm/boot/dts/rockchip/rk3128-evb.dts4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts28
-rw-r--r--arch/arm/boot/dts/rockchip/rk3188-bqedison2qc.dts14
-rw-r--r--arch/arm/boot/dts/rockchip/rk3188-px3-evb.dts2
-rw-r--r--arch/arm/boot/dts/rockchip/rk3188-radxarock.dts8
-rw-r--r--arch/arm/boot/dts/rockchip/rk3228-evb.dts2
-rw-r--r--arch/arm/boot/dts/rockchip/rk3229-evb.dts16
-rw-r--r--arch/arm/boot/dts/rockchip/rk3229-xms6.dts16
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-evb-act8846.dts4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-evb.dtsi8
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-firefly-reload-core.dtsi2
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-firefly-reload.dts18
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-firefly.dtsi16
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-miqi.dts8
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-phycore-rdk.dts6
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-phycore-som.dtsi6
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-popmetal.dts10
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-r89.dts8
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-rock2-som.dtsi4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-rock2-square.dts6
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-veyron-brain.dts6
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi10
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-veyron-edp.dtsi4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-veyron-fievel.dts10
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-veyron-mickey.dts4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts4
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-veyron.dtsi8
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-vmarc-som.dtsi2
-rw-r--r--arch/arm/boot/dts/rockchip/rk3288-vyasa.dts18
-rw-r--r--arch/arm/boot/dts/rockchip/rockchip-radxa-dalang-carrier.dtsi8
-rw-r--r--arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts2
-rw-r--r--arch/arm/boot/dts/rockchip/rv1108-evb.dts2
-rw-r--r--arch/arm/boot/dts/rockchip/rv1109-relfor-saib.dts422
-rw-r--r--arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts6
-rw-r--r--arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2.dtsi2
-rw-r--r--arch/arm/boot/dts/rockchip/rv1126.dtsi8
-rw-r--r--arch/arm/boot/dts/st/spear1310-evb.dts2
-rw-r--r--arch/arm/boot/dts/st/spear1340-evb.dts2
-rw-r--r--arch/arm/boot/dts/st/ste-dbx5x0-pinctrl.dtsi49
-rw-r--r--arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts1
-rw-r--r--arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts27
-rw-r--r--arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi7
-rw-r--r--arch/arm/boot/dts/st/stm32mp135f-dk.dts52
-rw-r--r--arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi6
-rw-r--r--arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi7
-rw-r--r--arch/arm/boot/dts/st/stm32mp151.dtsi2
-rw-r--r--arch/arm/boot/dts/st/stm32mp157c-dk2.dts51
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi3
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi12
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-boneblue.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-pdu001.dts6
-rw-r--r--arch/arm/boot/dts/ti/omap/am335x-shc.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am3517-som.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/am3874-iceboard.dts8
-rw-r--r--arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/dm8148-evm.dts1
-rw-r--r--arch/arm/boot/dts/ti/omap/dm8168-evm.dts1
-rw-r--r--arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts1
-rw-r--r--arch/arm/boot/dts/ti/omap/dra7.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi3
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi2
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts1
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-evm.dts1
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi2
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts10
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-igep.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-ldp.dts1
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi2
-rw-r--r--arch/arm/boot/dts/ti/omap/omap3430-sdp.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/omap36xx.dtsi1
-rw-r--r--arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts211
-rw-r--r--arch/arm/boot/dts/ti/omap/omap4-kc1.dts6
-rw-r--r--arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts2
-rw-r--r--arch/arm/boot/dts/ti/omap/twl4030.dtsi2
-rw-r--r--arch/arm/configs/at91_dt_defconfig1
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig2
-rw-r--r--arch/arm/configs/multi_v7_defconfig3
-rw-r--r--arch/arm/configs/pxa_defconfig4
-rw-r--r--arch/arm/configs/sama5_defconfig1
-rw-r--r--arch/arm/configs/sama7_defconfig1
-rw-r--r--arch/arm/crypto/crct10dif-ce-core.S249
-rw-r--r--arch/arm/crypto/crct10dif-ce-glue.c55
-rw-r--r--arch/arm/include/asm/arm_pmuv3.h8
-rw-r--r--arch/arm/include/asm/div64.h13
-rw-r--r--arch/arm/include/asm/jump_label.h14
-rw-r--r--arch/arm/include/asm/memory.h6
-rw-r--r--arch/arm/include/asm/page.h5
-rw-r--r--arch/arm/include/asm/perf_event.h7
-rw-r--r--arch/arm/include/asm/spinlock_types.h2
-rw-r--r--arch/arm/include/asm/text-patching.h (renamed from arch/arm/include/asm/patch.h)0
-rw-r--r--arch/arm/include/asm/vdso/gettimeofday.h4
-rw-r--r--arch/arm/include/asm/vdso/vsyscall.h4
-rw-r--r--arch/arm/kernel/devtree.c2
-rw-r--r--arch/arm/kernel/entry-armv.S8
-rw-r--r--arch/arm/kernel/ftrace.c2
-rw-r--r--arch/arm/kernel/head.S12
-rw-r--r--arch/arm/kernel/irq.c5
-rw-r--r--arch/arm/kernel/jump_label.c2
-rw-r--r--arch/arm/kernel/kgdb.c2
-rw-r--r--arch/arm/kernel/patch.c2
-rw-r--r--arch/arm/kernel/perf_callchain.c17
-rw-r--r--arch/arm/kernel/psci_smp.c7
-rw-r--r--arch/arm/kernel/smp_twd.c1
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c10
-rw-r--r--arch/arm/kernel/traps.c3
-rw-r--r--arch/arm/kernel/vdso.c1
-rw-r--r--arch/arm/mach-bcm/Makefile1
-rw-r--r--arch/arm/mach-bcm/board_bcmbca.c31
-rw-r--r--arch/arm/mach-bcm/brcmstb.c6
-rw-r--r--arch/arm/mach-imx/Kconfig16
-rw-r--r--arch/arm/mach-imx/pm-imx6.c6
-rw-r--r--arch/arm/mach-zynq/common.h1
-rw-r--r--arch/arm/mm/dma-mapping-nommu.c2
-rw-r--r--arch/arm/mm/fault-armv.c53
-rw-r--r--arch/arm/mm/idmap.c7
-rw-r--r--arch/arm/mm/ioremap.c35
-rw-r--r--arch/arm/mm/mmu.c34
-rw-r--r--arch/arm/mm/proc-v7.S2
-rw-r--r--arch/arm/probes/kprobes/core.c2
-rw-r--r--arch/arm/probes/kprobes/opt-arm.c2
-rw-r--r--arch/arm/tools/syscall.tbl4
-rw-r--r--arch/arm/vdso/Makefile2
-rw-r--r--arch/arm/vdso/datapage.S16
-rw-r--r--arch/arm/vdso/vdso.lds.S3
-rw-r--r--arch/arm/vfp/vfpmodule.c74
-rw-r--r--arch/arm64/Kconfig59
-rw-r--r--arch/arm64/Kconfig.platforms4
-rw-r--r--arch/arm64/Makefile2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts18
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi185
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi21
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h313-tanix-tx1.dts5
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-r1s-h5.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi6
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts6
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi44
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h618-longanpi-3h.dts1
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts5
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h618-transpeed-8k618-t.dts6
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts13
-rw-r--r--arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts1
-rw-r--r--arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts1
-rw-r--r--arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi8
-rw-r--r--arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi364
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-a1.dtsi216
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/apm/apm-shadowcat.dtsi2
-rw-r--r--arch/arm64/boot/dts/apm/apm-storm.dtsi1
-rw-r--r--arch/arm64/boot/dts/apple/Makefile53
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-5s.dtsi51
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-air1.dtsi51
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-common.dtsi48
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j71.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j72.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j73.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j85.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j85m.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j86.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j86m.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j87.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-j87m.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-mini2.dtsi51
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-mini3.dtsi14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-n51.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x-n53.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s5l8960x.dtsi113
-rw-r--r--arch/arm64/boot/dts/apple/s800-0-3-common.dtsi48
-rw-r--r--arch/arm64/boot/dts/apple/s8000-j71s.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8000-j72s.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8000-n66.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8000-n69u.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8000-n71.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8000.dtsi144
-rw-r--r--arch/arm64/boot/dts/apple/s8001-common.dtsi48
-rw-r--r--arch/arm64/boot/dts/apple/s8001-j127.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s8001-j128.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s8001-j98a.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s8001-j99a.dts14
-rw-r--r--arch/arm64/boot/dts/apple/s8001-pro.dtsi44
-rw-r--r--arch/arm64/boot/dts/apple/s8001.dtsi133
-rw-r--r--arch/arm64/boot/dts/apple/s8003-j71t.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8003-j72t.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8003-n66m.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8003-n69.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8003-n71m.dts15
-rw-r--r--arch/arm64/boot/dts/apple/s8003.dtsi21
-rw-r--r--arch/arm64/boot/dts/apple/s800x-6s.dtsi49
-rw-r--r--arch/arm64/boot/dts/apple/s800x-ipad5.dtsi43
-rw-r--r--arch/arm64/boot/dts/apple/s800x-se.dtsi49
-rw-r--r--arch/arm64/boot/dts/apple/t7000-6.dtsi50
-rw-r--r--arch/arm64/boot/dts/apple/t7000-common.dtsi36
-rw-r--r--arch/arm64/boot/dts/apple/t7000-handheld.dtsi27
-rw-r--r--arch/arm64/boot/dts/apple/t7000-j42d.dts31
-rw-r--r--arch/arm64/boot/dts/apple/t7000-j96.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t7000-j97.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t7000-mini4.dtsi51
-rw-r--r--arch/arm64/boot/dts/apple/t7000-n102.dts48
-rw-r--r--arch/arm64/boot/dts/apple/t7000-n56.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t7000-n61.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t7000.dtsi125
-rw-r--r--arch/arm64/boot/dts/apple/t7001-air2.dtsi74
-rw-r--r--arch/arm64/boot/dts/apple/t7001-j81.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t7001-j82.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t7001.dtsi123
-rw-r--r--arch/arm64/boot/dts/apple/t8010-7.dtsi43
-rw-r--r--arch/arm64/boot/dts/apple/t8010-common.dtsi48
-rw-r--r--arch/arm64/boot/dts/apple/t8010-d10.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-d101.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-d11.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-d111.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-ipad6.dtsi44
-rw-r--r--arch/arm64/boot/dts/apple/t8010-ipad7.dtsi14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-j171.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-j172.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-j71b.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-j72b.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8010-n112.dts47
-rw-r--r--arch/arm64/boot/dts/apple/t8010.dtsi133
-rw-r--r--arch/arm64/boot/dts/apple/t8011-common.dtsi46
-rw-r--r--arch/arm64/boot/dts/apple/t8011-j105a.dts16
-rw-r--r--arch/arm64/boot/dts/apple/t8011-j120.dts16
-rw-r--r--arch/arm64/boot/dts/apple/t8011-j121.dts16
-rw-r--r--arch/arm64/boot/dts/apple/t8011-j207.dts16
-rw-r--r--arch/arm64/boot/dts/apple/t8011-j208.dts16
-rw-r--r--arch/arm64/boot/dts/apple/t8011-pro2.dtsi42
-rw-r--r--arch/arm64/boot/dts/apple/t8011.dtsi141
-rw-r--r--arch/arm64/boot/dts/apple/t8015-8.dtsi13
-rw-r--r--arch/arm64/boot/dts/apple/t8015-8plus.dtsi9
-rw-r--r--arch/arm64/boot/dts/apple/t8015-common.dtsi48
-rw-r--r--arch/arm64/boot/dts/apple/t8015-d20.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8015-d201.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8015-d21.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8015-d211.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8015-d22.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8015-d221.dts14
-rw-r--r--arch/arm64/boot/dts/apple/t8015-x.dtsi13
-rw-r--r--arch/arm64/boot/dts/apple/t8015.dtsi234
-rw-r--r--arch/arm64/boot/dts/exynos/Makefile2
-rw-r--r--arch/arm64/boot/dts/exynos/exynos8895-dreamlte.dts126
-rw-r--r--arch/arm64/boot/dts/exynos/exynos8895-pinctrl.dtsi1094
-rw-r--r--arch/arm64/boot/dts/exynos/exynos8895.dtsi386
-rw-r--r--arch/arm64/boot/dts/exynos/exynos990-c1s.dts115
-rw-r--r--arch/arm64/boot/dts/exynos/exynos990-pinctrl.dtsi2195
-rw-r--r--arch/arm64/boot/dts/exynos/exynos990.dtsi251
-rw-r--r--arch/arm64/boot/dts/exynos/exynosautov920.dtsi50
-rw-r--r--arch/arm64/boot/dts/freescale/Makefile25
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi3
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi169
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-eval-v1.2.dtsi69
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi31
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi31
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi31
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi135
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi19
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-hsio.dtsi123
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi12
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-evk.dts33
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-hsio.dtsi51
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts335
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts131
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-kontron-dl.dtso189
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dts5
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi7
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx.dtsi16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts7
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi471
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-ivy.dts18
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-ivy.dts18
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi9
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso29
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx.dts5
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-drc02.dts255
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-picoitx.dts176
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-evk-pcie-ep.dtso17
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-iota2-lumpy.dts423
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-kontron-bl-osm-s.dts305
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso111
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-kontron-osm-s.dtsi908
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc-eval-carrier.dts254
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc.dtsi280
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-navqp.dts47
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-som.dtsi348
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-universal-board.dts17
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts62
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts7
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx.dtsi16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx-2x.dts19
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx.dtsi533
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi512
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-ivy.dts18
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-ivy.dts18
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi12
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp.dtsi31
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-mek.dts89
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-hsio.dtsi209
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm.dtsi34
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-mek.dts298
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-ss-conn.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-ss-hsio.dtsi41
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8ulp-evk.dts70
-rw-r--r--arch/arm64/boot/dts/freescale/imx8ulp.dtsi216
-rw-r--r--arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts115
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-9x9-qsb-i3c.dtso72
-rw-r--r--arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts158
-rw-r--r--arch/arm64/boot/dts/freescale/imx93.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts86
-rw-r--r--arch/arm64/boot/dts/freescale/imx95.dtsi68
-rw-r--r--arch/arm64/boot/dts/freescale/mba8mx.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/s32g2.dtsi153
-rw-r--r--arch/arm64/boot/dts/freescale/s32g274a-evb.dts5
-rw-r--r--arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts13
-rw-r--r--arch/arm64/boot/dts/freescale/s32g3.dtsi153
-rw-r--r--arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts4
-rw-r--r--arch/arm64/boot/dts/lg/lg1312.dtsi8
-rw-r--r--arch/arm64/boot/dts/lg/lg1313.dtsi8
-rw-r--r--arch/arm64/boot/dts/marvell/armada-7040-db.dts1
-rw-r--r--arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts1
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-db.dts2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi1
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6358.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7988a.dtsi42
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi22
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi30
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku32.dts2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku38.dts2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi30
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts123
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183.dtsi21
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi21
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi14
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186.dtsi7
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8188-evb.dts2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8188.dtsi1124
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts11
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi6
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195.dtsi4
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts192
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts21
-rw-r--r--arch/arm64/boot/dts/nvidia/Makefile1
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi2
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210-smaug.dts27
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210.dtsi2
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts544
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0008.dts11
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701.dtsi547
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile11
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5018.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/ipq5332.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/ipq6018.dtsi26
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/ipq9574.dtsi52
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916.dtsi100
-rw-r--r--arch/arm64/boot/dts/qcom/msm8939.dtsi112
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953.dtsi68
-rw-r--r--arch/arm64/boot/dts/qcom/msm8976.dtsi34
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994.dtsi52
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi54
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi38
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts68
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998.dtsi220
-rw-r--r--arch/arm64/boot/dts/qcom/qcm2290.dtsi68
-rw-r--r--arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts40
-rw-r--r--arch/arm64/boot/dts/qcom/qcm6490-idp.dts30
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404.dtsi68
-rw-r--r--arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts127
-rw-r--r--arch/arm64/boot/dts/qcom/qcs8550.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/qcs9100-ride.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/qdu1000.dtsi89
-rw-r--r--arch/arm64/boot/dts/qcom/qrb2210-rb1.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/qrb4210-rb2.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dtso (renamed from arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dts)19
-rw-r--r--arch/arm64/boot/dts/qcom/qrb5165-rb5.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi121
-rw-r--r--arch/arm64/boot/dts/qcom/sa8775p.dtsi701
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-firmware-tfa.dtsi84
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180.dtsi366
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280.dtsi397
-rw-r--r--arch/arm64/boot/dts/qcom/sc8180x.dtsi168
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-crd.dts169
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts120
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-microsoft-arcata.dts1032
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp.dtsi211
-rw-r--r--arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts32
-rw-r--r--arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630.dtsi190
-rw-r--r--arch/arm64/boot/dts/qcom/sdm632.dtsi26
-rw-r--r--arch/arm64/boot/dts/qcom/sdm660.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670.dtsi159
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi74
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso (renamed from arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dts)23
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-db845c.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi179
-rw-r--r--arch/arm64/boot/dts/qcom/sdx75.dtsi90
-rw-r--r--arch/arm64/boot/dts/qcom/sm4250.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sm4450.dtsi160
-rw-r--r--arch/arm64/boot/dts/qcom/sm6115.dtsi154
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125.dtsi54
-rw-r--r--arch/arm64/boot/dts/qcom/sm6350.dtsi207
-rw-r--r--arch/arm64/boot/dts/qcom/sm6375.dtsi160
-rw-r--r--arch/arm64/boot/dts/qcom/sm7125.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sm7225.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts1260
-rw-r--r--arch/arm64/boot/dts/qcom/sm7325.dtsi17
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi371
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250.dtsi366
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-hdk.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350.dtsi353
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-hdk.dts161
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-qrd.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450.dtsi178
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8550.dtsi167
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650-hdk.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650-mtp.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650-qrd.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sm8650.dtsi162
-rw-r--r--arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts27
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts28
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-crd.dts80
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts875
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts41
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi106
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100-qcp.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/x1e80100.dtsi282
-rw-r--r--arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi10
-rw-r--r--arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi11
-rw-r--r--arch/arm64/boot/dts/renesas/cat875.dtsi3
-rw-r--r--arch/arm64/boot/dts/renesas/condor-common.dtsi6
-rw-r--r--arch/arm64/boot/dts/renesas/draak.dtsi6
-rw-r--r--arch/arm64/boot/dts/renesas/ebisu.dtsi17
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-common.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-rev2.dtsi3
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-rev4.dtsi3
-rw-r--r--arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi3
-rw-r--r--arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts9
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-eagle-function-expansion.dtso7
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-eagle.dts6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi3
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts3
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779a0.dtsi8
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi9
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0.dtsi8
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts6
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779g0.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts3
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts31
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779h0.dtsi72
-rw-r--r--arch/arm64/boot/dts/renesas/r9a08g045.dtsi34
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g057.dtsi131
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi21
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi3
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi18
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi3
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi51
-rw-r--r--arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi22
-rw-r--r--arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi9
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-common.dtsi11
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-x.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-xs.dtsi2
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb-kf.dtsi18
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb.dtsi8
-rw-r--r--arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi19
-rw-r--r--arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi6
-rw-r--r--arch/arm64/boot/dts/rockchip/Makefile11
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-engicam-common.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-engicam-px30-core.dtsi2
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-evb.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts10
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi40
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308-bpi-p2-pro.dts362
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308-evb.dts20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-gameforce-chi.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-a1.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-evb.dts10
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2.dtsi394
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts3
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts28
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dtsi35
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts399
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dtsi29
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts346
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dtsi358
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts379
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-roc-pc.dts3
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-roc.dtsi377
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts10
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328-rock64.dts8
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328.dtsi7
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi5
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts18
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368-r88.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-evb.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-firefly.dts18
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts30
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dts47
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dtsi60
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4b.dts3
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s-enterprise.dts3
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts124
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi131
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-op1.dtsi52
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts18
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts30
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts39
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi40
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-roc-pc-mezzanine.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts5
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi18
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi24
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-s.dtsi123
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi18
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3528.dtsi189
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg-arc.dtsi2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-base.dtsi35
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts15
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts554
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-pinetab2.dtsi22
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb20sx.dts89
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-powkiddy-x55.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3-io.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts18
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts10
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi8
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566.dtsi116
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566t.dtsi90
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts24
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts18
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts19
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dtsi20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts17
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts23
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts28
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso7
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5.dts14
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568.dtsi113
-rw-r--r--arch/arm64/boot/dts/rockchip/rk356x-base.dtsi (renamed from arch/arm64/boot/dts/rockchip/rk356x.dtsi)81
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts658
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi5775
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3576.dtsi1678
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-armsom-lm7.dtsi455
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts408
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi271
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-base.dtsi61
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-evb.dts59
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts63
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi8
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtsi8
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-wifi.dtso2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts71
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-fet3588-c.dtsi12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts49
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts95
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi103
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts16
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts95
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts17
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts40
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts65
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts67
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi35
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts21
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi145
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts67
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts1170
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts70
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts26
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi812
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts756
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts47
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts738
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi866
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts19
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts75
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dts920
-rw-r--r--arch/arm64/boot/dts/st/stm32mp251.dtsi95
-rw-r--r--arch/arm64/boot/dts/st/stm32mp257f-ev1.dts6
-rw-r--r--arch/arm64/boot/dts/ti/Makefile18
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-main.dtsi74
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi13
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi37
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-verdin-ivy.dtsi655
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi12
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi9
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts12
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-1-4-ghz-opp.dtso20
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-ivy.dts22
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-ivy.dts22
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a-main.dtsi27
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi5
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a7-phyboard-lyra-rdk.dts4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a7-sk.dts9
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a7.dtsi51
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi27
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi5
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p5-sk.dts9
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62p5.dtsi47
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi6
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi19
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-main.dtsi37
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi13
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi29
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm-pcie0-ep.dtso51
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm.dts22
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts5
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-sk.dts36
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-main.dtsi15
-rw-r--r--arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso1
-rw-r--r--arch/arm64/boot/dts/ti/k3-am654-idk.dtso2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts8
-rw-r--r--arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi5
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts15
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-evm-pcie1-ep.dtso53
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-main.dtsi40
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi17
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi6
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts16
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-main.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi16
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-sk.dts18
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi5
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts14
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi17
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi19
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi3
-rw-r--r--arch/arm64/boot/dts/ti/k3-j722s-main.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-j742s2-evm.dts26
-rw-r--r--arch/arm64/boot/dts/ti/k3-j742s2-main.dtsi45
-rw-r--r--arch/arm64/boot/dts/ti/k3-j742s2.dtsi98
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-evm.dts1480
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-j742s2-common.dtsi148
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi1481
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi2671
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-j742s2-mcu-wakeup-common.dtsi (renamed from arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi)12
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-j742s2-thermal-common.dtsi (renamed from arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi)0
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi2705
-rw-r--r--arch/arm64/boot/dts/ti/k3-j784s4.dtsi133
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts18
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts4
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts4
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts4
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts4
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp.dtsi101
-rw-r--r--arch/arm64/configs/defconfig7
-rw-r--r--arch/arm64/crypto/crct10dif-ce-core.S335
-rw-r--r--arch/arm64/crypto/crct10dif-ce-glue.c48
-rw-r--r--arch/arm64/include/asm/arm_pmuv3.h10
-rw-r--r--arch/arm64/include/asm/assembler.h7
-rw-r--r--arch/arm64/include/asm/cpu.h1
-rw-r--r--arch/arm64/include/asm/cpucaps.h7
-rw-r--r--arch/arm64/include/asm/cpufeature.h35
-rw-r--r--arch/arm64/include/asm/daifflags.h2
-rw-r--r--arch/arm64/include/asm/debug-monitors.h1
-rw-r--r--arch/arm64/include/asm/el2_setup.h44
-rw-r--r--arch/arm64/include/asm/esr.h28
-rw-r--r--arch/arm64/include/asm/exception.h3
-rw-r--r--arch/arm64/include/asm/ftrace.h21
-rw-r--r--arch/arm64/include/asm/gcs.h107
-rw-r--r--arch/arm64/include/asm/hugetlb.h8
-rw-r--r--arch/arm64/include/asm/hwcap.h7
-rw-r--r--arch/arm64/include/asm/insn.h6
-rw-r--r--arch/arm64/include/asm/io.h19
-rw-r--r--arch/arm64/include/asm/jump_label.h20
-rw-r--r--arch/arm64/include/asm/kernel-pgtable.h1
-rw-r--r--arch/arm64/include/asm/kvm_arm.h30
-rw-r--r--arch/arm64/include/asm/kvm_asm.h1
-rw-r--r--arch/arm64/include/asm/kvm_emulate.h9
-rw-r--r--arch/arm64/include/asm/kvm_host.h46
-rw-r--r--arch/arm64/include/asm/kvm_pgtable.h4
-rw-r--r--arch/arm64/include/asm/mem_encrypt.h9
-rw-r--r--arch/arm64/include/asm/memory.h8
-rw-r--r--arch/arm64/include/asm/mman.h38
-rw-r--r--arch/arm64/include/asm/mmu_context.h9
-rw-r--r--arch/arm64/include/asm/mte.h67
-rw-r--r--arch/arm64/include/asm/page-def.h5
-rw-r--r--arch/arm64/include/asm/perf_event.h4
-rw-r--r--arch/arm64/include/asm/pgalloc.h12
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h4
-rw-r--r--arch/arm64/include/asm/pgtable-prot.h19
-rw-r--r--arch/arm64/include/asm/pgtable.h31
-rw-r--r--arch/arm64/include/asm/probes.h11
-rw-r--r--arch/arm64/include/asm/processor.h57
-rw-r--r--arch/arm64/include/asm/ptrace.h22
-rw-r--r--arch/arm64/include/asm/rsi.h68
-rw-r--r--arch/arm64/include/asm/rsi_cmds.h160
-rw-r--r--arch/arm64/include/asm/rsi_smc.h193
-rw-r--r--arch/arm64/include/asm/scs.h8
-rw-r--r--arch/arm64/include/asm/set_memory.h4
-rw-r--r--arch/arm64/include/asm/spinlock_types.h2
-rw-r--r--arch/arm64/include/asm/stacktrace/common.h74
-rw-r--r--arch/arm64/include/asm/stacktrace/frame.h48
-rw-r--r--arch/arm64/include/asm/sysreg.h32
-rw-r--r--arch/arm64/include/asm/text-patching.h (renamed from arch/arm64/include/asm/patching.h)0
-rw-r--r--arch/arm64/include/asm/tlbflush.h43
-rw-r--r--arch/arm64/include/asm/topology.h4
-rw-r--r--arch/arm64/include/asm/uaccess.h40
-rw-r--r--arch/arm64/include/asm/vdso.h9
-rw-r--r--arch/arm64/include/asm/vdso/vsyscall.h3
-rw-r--r--arch/arm64/include/asm/vncr_mapping.h1
-rw-r--r--arch/arm64/include/uapi/asm/hwcap.h7
-rw-r--r--arch/arm64/include/uapi/asm/kvm.h6
-rw-r--r--arch/arm64/include/uapi/asm/ptrace.h8
-rw-r--r--arch/arm64/include/uapi/asm/sigcontext.h9
-rw-r--r--arch/arm64/kernel/Makefile3
-rw-r--r--arch/arm64/kernel/asm-offsets.c49
-rw-r--r--arch/arm64/kernel/cpufeature.c141
-rw-r--r--arch/arm64/kernel/cpuinfo.c4
-rw-r--r--arch/arm64/kernel/debug-monitors.c10
-rw-r--r--arch/arm64/kernel/efi.c12
-rw-r--r--arch/arm64/kernel/entry-common.c35
-rw-r--r--arch/arm64/kernel/entry.S16
-rw-r--r--arch/arm64/kernel/fpsimd.c3
-rw-r--r--arch/arm64/kernel/ftrace.c12
-rw-r--r--arch/arm64/kernel/head.S3
-rw-r--r--arch/arm64/kernel/hibernate.c6
-rw-r--r--arch/arm64/kernel/io.c87
-rw-r--r--arch/arm64/kernel/jump_label.c2
-rw-r--r--arch/arm64/kernel/kgdb.c2
-rw-r--r--arch/arm64/kernel/module.c10
-rw-r--r--arch/arm64/kernel/mte.c27
-rw-r--r--arch/arm64/kernel/patching.c2
-rw-r--r--arch/arm64/kernel/perf_callchain.c28
-rw-r--r--arch/arm64/kernel/pi/idreg-override.c12
-rw-r--r--arch/arm64/kernel/pi/map_range.c2
-rw-r--r--arch/arm64/kernel/pi/patch-scs.c93
-rw-r--r--arch/arm64/kernel/probes/decode-insn.c22
-rw-r--r--arch/arm64/kernel/probes/decode-insn.h2
-rw-r--r--arch/arm64/kernel/probes/kprobes.c41
-rw-r--r--arch/arm64/kernel/probes/simulate-insn.c6
-rw-r--r--arch/arm64/kernel/probes/simulate-insn.h1
-rw-r--r--arch/arm64/kernel/probes/uprobes.c12
-rw-r--r--arch/arm64/kernel/process.c101
-rw-r--r--arch/arm64/kernel/ptrace.c74
-rw-r--r--arch/arm64/kernel/rsi.c142
-rw-r--r--arch/arm64/kernel/setup.c9
-rw-r--r--arch/arm64/kernel/signal.c235
-rw-r--r--arch/arm64/kernel/smccc-call.S35
-rw-r--r--arch/arm64/kernel/stacktrace.c176
-rw-r--r--arch/arm64/kernel/traps.c20
-rw-r--r--arch/arm64/kernel/vdso.c44
-rw-r--r--arch/arm64/kernel/vdso/vdso.lds.S2
-rw-r--r--arch/arm64/kernel/vdso32/vdso.lds.S2
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S6
-rw-r--r--arch/arm64/kvm/arch_timer.c3
-rw-r--r--arch/arm64/kvm/arm.c26
-rw-r--r--arch/arm64/kvm/at.c470
-rw-r--r--arch/arm64/kvm/emulate-nested.c301
-rw-r--r--arch/arm64/kvm/guest.c30
-rw-r--r--arch/arm64/kvm/hyp/include/hyp/switch.h31
-rw-r--r--arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h11
-rw-r--r--arch/arm64/kvm/hyp/include/nvhe/trap_handler.h2
-rw-r--r--arch/arm64/kvm/hyp/nvhe/hyp-main.c12
-rw-r--r--arch/arm64/kvm/hyp/nvhe/pkvm.c116
-rw-r--r--arch/arm64/kvm/hyp/nvhe/psci-relay.c2
-rw-r--r--arch/arm64/kvm/hyp/nvhe/setup.c20
-rw-r--r--arch/arm64/kvm/hyp/nvhe/sysreg-sr.c2
-rw-r--r--arch/arm64/kvm/hyp/pgtable.c7
-rw-r--r--arch/arm64/kvm/hyp/vgic-v3-sr.c3
-rw-r--r--arch/arm64/kvm/hyp/vhe/sysreg-sr.c160
-rw-r--r--arch/arm64/kvm/hypercalls.c2
-rw-r--r--arch/arm64/kvm/mmio.c32
-rw-r--r--arch/arm64/kvm/mmu.c32
-rw-r--r--arch/arm64/kvm/nested.c84
-rw-r--r--arch/arm64/kvm/pmu-emul.c187
-rw-r--r--arch/arm64/kvm/psci.c44
-rw-r--r--arch/arm64/kvm/reset.c5
-rw-r--r--arch/arm64/kvm/sys_regs.c309
-rw-r--r--arch/arm64/kvm/vgic/vgic-debug.c5
-rw-r--r--arch/arm64/kvm/vgic/vgic-init.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-its.c93
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio-v2.c12
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio-v3.c13
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio.c38
-rw-r--r--arch/arm64/kvm/vgic/vgic-v2.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-v4.c4
-rw-r--r--arch/arm64/kvm/vgic/vgic.c43
-rw-r--r--arch/arm64/kvm/vgic/vgic.h4
-rw-r--r--arch/arm64/lib/Makefile2
-rw-r--r--arch/arm64/lib/clear_page.S13
-rw-r--r--arch/arm64/lib/copy_page.S13
-rw-r--r--arch/arm64/lib/crc32-glue.c82
-rw-r--r--arch/arm64/lib/crc32.S344
-rw-r--r--arch/arm64/lib/memcpy.S19
-rw-r--r--arch/arm64/lib/memset.S20
-rw-r--r--arch/arm64/mm/Makefile1
-rw-r--r--arch/arm64/mm/copypage.c27
-rw-r--r--arch/arm64/mm/fault.c42
-rw-r--r--arch/arm64/mm/fixmap.c9
-rw-r--r--arch/arm64/mm/gcs.c254
-rw-r--r--arch/arm64/mm/hugetlbpage.c21
-rw-r--r--arch/arm64/mm/init.c10
-rw-r--r--arch/arm64/mm/mmap.c9
-rw-r--r--arch/arm64/mm/mmu.c10
-rw-r--r--arch/arm64/mm/pageattr.c114
-rw-r--r--arch/arm64/mm/proc.S19
-rw-r--r--arch/arm64/mm/ptdump.c8
-rw-r--r--arch/arm64/net/bpf_jit_comp.c49
-rw-r--r--arch/arm64/tools/cpucaps4
-rw-r--r--arch/arm64/tools/syscall_32.tbl4
-rw-r--r--arch/arm64/tools/sysreg259
-rw-r--r--arch/csky/Kconfig4
-rw-r--r--arch/csky/include/asm/Kbuild1
-rw-r--r--arch/csky/include/asm/io.h11
-rw-r--r--arch/csky/include/asm/page.h11
-rw-r--r--arch/csky/include/asm/vdso/clocksource.h9
-rw-r--r--arch/csky/include/asm/vdso/gettimeofday.h114
-rw-r--r--arch/csky/include/asm/vdso/processor.h12
-rw-r--r--arch/csky/include/asm/vdso/vsyscall.h22
-rw-r--r--arch/csky/kernel/Makefile2
-rw-r--r--arch/csky/kernel/io.c91
-rw-r--r--arch/csky/kernel/setup.c4
-rw-r--r--arch/csky/kernel/vdso.c31
-rw-r--r--arch/csky/kernel/vdso/Makefile1
-rw-r--r--arch/csky/kernel/vdso/vdso.lds.S4
-rw-r--r--arch/csky/kernel/vdso/vgettimeofday.c30
-rw-r--r--arch/hexagon/Kconfig5
-rw-r--r--arch/hexagon/include/asm/Kbuild1
-rw-r--r--arch/hexagon/include/asm/io.h223
-rw-r--r--arch/hexagon/include/asm/page.h10
-rw-r--r--arch/hexagon/include/asm/spinlock_types.h2
-rw-r--r--arch/hexagon/lib/Makefile2
-rw-r--r--arch/hexagon/lib/io.c82
-rw-r--r--arch/loongarch/Kconfig6
-rw-r--r--arch/loongarch/Makefile4
-rw-r--r--arch/loongarch/boot/dts/loongson-2k1000.dtsi17
-rw-r--r--arch/loongarch/boot/dts/loongson-2k2000.dtsi22
-rw-r--r--arch/loongarch/configs/loongson3_defconfig93
-rw-r--r--arch/loongarch/include/asm/Kbuild1
-rw-r--r--arch/loongarch/include/asm/ftrace.h29
-rw-r--r--arch/loongarch/include/asm/hugetlb.h5
-rw-r--r--arch/loongarch/include/asm/io.h10
-rw-r--r--arch/loongarch/include/asm/irq.h1
-rw-r--r--arch/loongarch/include/asm/jump_label.h16
-rw-r--r--arch/loongarch/include/asm/kasan.h13
-rw-r--r--arch/loongarch/include/asm/kvm_eiointc.h123
-rw-r--r--arch/loongarch/include/asm/kvm_host.h18
-rw-r--r--arch/loongarch/include/asm/kvm_ipi.h45
-rw-r--r--arch/loongarch/include/asm/kvm_pch_pic.h62
-rw-r--r--arch/loongarch/include/asm/page.h15
-rw-r--r--arch/loongarch/include/asm/pgtable.h3
-rw-r--r--arch/loongarch/include/asm/set_memory.h1
-rw-r--r--arch/loongarch/include/asm/thread_info.h8
-rw-r--r--arch/loongarch/include/asm/vdso/getrandom.h3
-rw-r--r--arch/loongarch/include/asm/vdso/gettimeofday.h4
-rw-r--r--arch/loongarch/include/asm/vdso/vdso.h18
-rw-r--r--arch/loongarch/include/asm/vdso/vsyscall.h4
-rw-r--r--arch/loongarch/include/uapi/asm/kvm.h20
-rw-r--r--arch/loongarch/kernel/Makefile2
-rw-r--r--arch/loongarch/kernel/acpi.c81
-rw-r--r--arch/loongarch/kernel/asm-offsets.c9
-rw-r--r--arch/loongarch/kernel/ftrace_dyn.c2
-rw-r--r--arch/loongarch/kernel/io.c94
-rw-r--r--arch/loongarch/kernel/irq.c4
-rw-r--r--arch/loongarch/kernel/paravirt.c15
-rw-r--r--arch/loongarch/kernel/setup.c2
-rw-r--r--arch/loongarch/kernel/smp.c5
-rw-r--r--arch/loongarch/kernel/time.c6
-rw-r--r--arch/loongarch/kernel/vdso.c1
-rw-r--r--arch/loongarch/kvm/Kconfig5
-rw-r--r--arch/loongarch/kvm/Makefile4
-rw-r--r--arch/loongarch/kvm/exit.c82
-rw-r--r--arch/loongarch/kvm/intc/eiointc.c1027
-rw-r--r--arch/loongarch/kvm/intc/ipi.c475
-rw-r--r--arch/loongarch/kvm/intc/pch_pic.c519
-rw-r--r--arch/loongarch/kvm/irqfd.c89
-rw-r--r--arch/loongarch/kvm/main.c19
-rw-r--r--arch/loongarch/kvm/mmu.c40
-rw-r--r--arch/loongarch/kvm/vcpu.c3
-rw-r--r--arch/loongarch/kvm/vm.c21
-rw-r--r--arch/loongarch/mm/kasan_init.c46
-rw-r--r--arch/loongarch/mm/pageattr.c19
-rw-r--r--arch/loongarch/mm/tlb.c2
-rw-r--r--arch/loongarch/net/bpf_jit.c2
-rw-r--r--arch/loongarch/vdso/Makefile2
-rw-r--r--arch/loongarch/vdso/vdso.lds.S8
-rw-r--r--arch/loongarch/vdso/vgetcpu.c2
-rw-r--r--arch/m68k/Kconfig11
-rw-r--r--arch/m68k/Kconfig.cpu36
-rw-r--r--arch/m68k/Kconfig.machine25
-rw-r--r--arch/m68k/coldfire/device.c8
-rw-r--r--arch/m68k/configs/amiga_defconfig2
-rw-r--r--arch/m68k/configs/apollo_defconfig2
-rw-r--r--arch/m68k/configs/atari_defconfig2
-rw-r--r--arch/m68k/configs/bvme6000_defconfig2
-rw-r--r--arch/m68k/configs/hp300_defconfig2
-rw-r--r--arch/m68k/configs/mac_defconfig2
-rw-r--r--arch/m68k/configs/multi_defconfig3
-rw-r--r--arch/m68k/configs/mvme147_defconfig3
-rw-r--r--arch/m68k/configs/mvme16x_defconfig3
-rw-r--r--arch/m68k/configs/q40_defconfig2
-rw-r--r--arch/m68k/configs/sun3_defconfig2
-rw-r--r--arch/m68k/configs/sun3x_defconfig2
-rw-r--r--arch/m68k/include/asm/Kbuild1
-rw-r--r--arch/m68k/include/asm/irq.h4
-rw-r--r--arch/m68k/include/asm/mcfgpio.h2
-rw-r--r--arch/m68k/include/asm/mvme147hw.h23
-rw-r--r--arch/m68k/include/asm/mvme16xhw.h18
-rw-r--r--arch/m68k/include/asm/page.h6
-rw-r--r--arch/m68k/include/asm/page_no.h2
-rw-r--r--arch/m68k/include/asm/virtconvert.h3
-rw-r--r--arch/m68k/kernel/Makefile12
-rw-r--r--arch/m68k/kernel/early_printk.c5
-rw-r--r--arch/m68k/kernel/setup_mm.c6
-rw-r--r--arch/m68k/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/m68k/kernel/time.c4
-rw-r--r--arch/m68k/kernel/traps.c16
-rw-r--r--arch/m68k/mvme147/config.c75
-rw-r--r--arch/m68k/mvme147/mvme147.h6
-rw-r--r--arch/m68k/mvme16x/Makefile2
-rw-r--r--arch/m68k/mvme16x/config.c57
-rw-r--r--arch/m68k/mvme16x/rtc.c165
-rw-r--r--arch/microblaze/include/asm/Kbuild1
-rw-r--r--arch/microblaze/include/asm/page.h6
-rw-r--r--arch/microblaze/include/uapi/asm/setup.h3
-rw-r--r--arch/microblaze/kernel/cpu/mb.c10
-rw-r--r--arch/microblaze/kernel/microblaze_ksyms.c10
-rw-r--r--arch/microblaze/kernel/prom.c2
-rw-r--r--arch/microblaze/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/mips/Kconfig3
-rw-r--r--arch/mips/boot/dts/brcm/bcm6358.dtsi1
-rw-r--r--arch/mips/boot/dts/brcm/bcm6368.dtsi1
-rw-r--r--arch/mips/boot/dts/loongson/ls7a-pch.dtsi73
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi270
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq5.dtsi30
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts2
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi52
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq6h.dtsi73
-rw-r--r--arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts2
-rw-r--r--arch/mips/boot/dts/realtek/rtl9302c.dtsi15
-rw-r--r--arch/mips/boot/dts/realtek/rtl930x.dtsi42
-rw-r--r--arch/mips/configs/loongson3_defconfig32
-rw-r--r--arch/mips/configs/mtx1_defconfig1
-rw-r--r--arch/mips/crypto/crc32-mips.c6
-rw-r--r--arch/mips/include/asm/Kbuild1
-rw-r--r--arch/mips/include/asm/hugetlb.h5
-rw-r--r--arch/mips/include/asm/io.h5
-rw-r--r--arch/mips/include/asm/mips-cm.h2
-rw-r--r--arch/mips/include/asm/page.h7
-rw-r--r--arch/mips/include/asm/pgtable-64.h2
-rw-r--r--arch/mips/include/asm/switch_to.h2
-rw-r--r--arch/mips/include/asm/vdso/vsyscall.h1
-rw-r--r--arch/mips/include/asm/vga.h4
-rw-r--r--arch/mips/include/uapi/asm/mman.h3
-rw-r--r--arch/mips/include/uapi/asm/socket.h2
-rw-r--r--arch/mips/kernel/head.S1
-rw-r--r--arch/mips/kernel/proc.c17
-rw-r--r--arch/mips/kernel/prom.c2
-rw-r--r--arch/mips/kernel/relocate.c2
-rw-r--r--arch/mips/kernel/smp-cps.c46
-rw-r--r--arch/mips/kernel/syscalls/syscall_n32.tbl4
-rw-r--r--arch/mips/kernel/syscalls/syscall_n64.tbl4
-rw-r--r--arch/mips/kernel/syscalls/syscall_o32.tbl4
-rw-r--r--arch/mips/kernel/vdso.c1
-rw-r--r--arch/mips/kernel/vmlinux.lds.S1
-rw-r--r--arch/mips/kvm/mmu.c26
-rw-r--r--arch/mips/ralink/Kconfig7
-rw-r--r--arch/mips/ralink/Makefile2
-rw-r--r--arch/mips/sgi-ip22/ip22-gio.c7
-rw-r--r--arch/mips/vdso/genvdso.c4
-rw-r--r--arch/nios2/include/asm/Kbuild1
-rw-r--r--arch/nios2/include/asm/io.h3
-rw-r--r--arch/nios2/include/asm/page.h7
-rw-r--r--arch/nios2/kernel/prom.c4
-rw-r--r--arch/openrisc/Kconfig3
-rw-r--r--arch/openrisc/include/asm/Kbuild1
-rw-r--r--arch/openrisc/include/asm/fixmap.h21
-rw-r--r--arch/openrisc/include/asm/page.h13
-rw-r--r--arch/openrisc/kernel/prom.c2
-rw-r--r--arch/openrisc/mm/init.c37
-rw-r--r--arch/parisc/include/asm/hugetlb.h15
-rw-r--r--arch/parisc/include/asm/mman.h5
-rw-r--r--arch/parisc/include/asm/page.h5
-rw-r--r--arch/parisc/include/asm/text-patching.h (renamed from arch/parisc/include/asm/patch.h)0
-rw-r--r--arch/parisc/include/uapi/asm/mman.h3
-rw-r--r--arch/parisc/include/uapi/asm/socket.h2
-rw-r--r--arch/parisc/kernel/ftrace.c4
-rw-r--r--arch/parisc/kernel/jump_label.c2
-rw-r--r--arch/parisc/kernel/kgdb.c2
-rw-r--r--arch/parisc/kernel/kprobes.c2
-rw-r--r--arch/parisc/kernel/patch.c2
-rw-r--r--arch/parisc/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/parisc/lib/checksum.c13
-rw-r--r--arch/parisc/mm/hugetlbpage.c21
-rw-r--r--arch/powerpc/Kbuild2
-rw-r--r--arch/powerpc/Kconfig38
-rw-r--r--arch/powerpc/Kconfig.debug6
-rw-r--r--arch/powerpc/Makefile32
-rw-r--r--arch/powerpc/Makefile.postlink8
-rw-r--r--arch/powerpc/boot/.gitignore1
-rw-r--r--arch/powerpc/boot/Makefile3
-rwxr-xr-xarch/powerpc/boot/wrapper7
-rw-r--r--arch/powerpc/configs/maple_defconfig111
-rw-r--r--arch/powerpc/configs/ppc64_defconfig1
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig1
-rw-r--r--arch/powerpc/crypto/Kconfig2
-rw-r--r--arch/powerpc/crypto/aes-gcm-p10-glue.c141
-rw-r--r--arch/powerpc/crypto/aes-gcm-p10.S2421
-rw-r--r--arch/powerpc/include/asm/cputable.h11
-rw-r--r--arch/powerpc/include/asm/dtl.h4
-rw-r--r--arch/powerpc/include/asm/fadump.h9
-rw-r--r--arch/powerpc/include/asm/ftrace.h60
-rw-r--r--arch/powerpc/include/asm/hvcall.h1
-rw-r--r--arch/powerpc/include/asm/io.h12
-rw-r--r--arch/powerpc/include/asm/kfence.h8
-rw-r--r--arch/powerpc/include/asm/kprobes.h2
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h4
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h10
-rw-r--r--arch/powerpc/include/asm/kvm_host.h5
-rw-r--r--arch/powerpc/include/asm/machdep.h8
-rw-r--r--arch/powerpc/include/asm/module.h7
-rw-r--r--arch/powerpc/include/asm/page.h10
-rw-r--r--arch/powerpc/include/asm/perf_event_server.h6
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h14
-rw-r--r--arch/powerpc/include/asm/set_memory.h14
-rw-r--r--arch/powerpc/include/asm/simple_spinlock_types.h2
-rw-r--r--arch/powerpc/include/asm/spinlock_types.h2
-rw-r--r--arch/powerpc/include/asm/spu_priv1.h1
-rw-r--r--arch/powerpc/include/asm/sstep.h5
-rw-r--r--arch/powerpc/include/asm/systemcfg.h52
-rw-r--r--arch/powerpc/include/asm/text-patching.h (renamed from arch/powerpc/include/asm/code-patching.h)0
-rw-r--r--arch/powerpc/include/asm/udbg.h1
-rw-r--r--arch/powerpc/include/asm/vdso.h1
-rw-r--r--arch/powerpc/include/asm/vdso/getrandom.h16
-rw-r--r--arch/powerpc/include/asm/vdso/vsyscall.h4
-rw-r--r--arch/powerpc/include/asm/vdso_datapage.h85
-rw-r--r--arch/powerpc/include/asm/vga.h5
-rw-r--r--arch/powerpc/kernel/asm-offsets.c15
-rw-r--r--arch/powerpc/kernel/crash_dump.c2
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c2
-rw-r--r--arch/powerpc/kernel/epapr_paravirt.c2
-rw-r--r--arch/powerpc/kernel/fadump.c72
-rw-r--r--arch/powerpc/kernel/irq.c44
-rw-r--r--arch/powerpc/kernel/jump_label.c2
-rw-r--r--arch/powerpc/kernel/kgdb.c2
-rw-r--r--arch/powerpc/kernel/kprobes.c20
-rw-r--r--arch/powerpc/kernel/misc_64.S8
-rw-r--r--arch/powerpc/kernel/module_32.c2
-rw-r--r--arch/powerpc/kernel/module_64.c68
-rw-r--r--arch/powerpc/kernel/optprobes.c2
-rw-r--r--arch/powerpc/kernel/proc_powerpc.c37
-rw-r--r--arch/powerpc/kernel/process.c2
-rw-r--r--arch/powerpc/kernel/prom.c5
-rw-r--r--arch/powerpc/kernel/prom_init.c115
-rw-r--r--arch/powerpc/kernel/rtas.c21
-rw-r--r--arch/powerpc/kernel/secure_boot.c5
-rw-r--r--arch/powerpc/kernel/security.c2
-rw-r--r--arch/powerpc/kernel/setup-common.c11
-rw-r--r--arch/powerpc/kernel/setup_32.c2
-rw-r--r--arch/powerpc/kernel/setup_64.c3
-rw-r--r--arch/powerpc/kernel/smp.c11
-rw-r--r--arch/powerpc/kernel/static_call.c2
-rw-r--r--arch/powerpc/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/powerpc/kernel/sysfs.c1
-rw-r--r--arch/powerpc/kernel/time.c5
-rw-r--r--arch/powerpc/kernel/trace/Makefile11
-rw-r--r--arch/powerpc/kernel/trace/ftrace.c304
-rw-r--r--arch/powerpc/kernel/trace/ftrace_64_pg.c73
-rw-r--r--arch/powerpc/kernel/trace/ftrace_entry.S244
-rw-r--r--arch/powerpc/kernel/udbg.c3
-rw-r--r--arch/powerpc/kernel/udbg_16550.c23
-rw-r--r--arch/powerpc/kernel/vdso.c36
-rw-r--r--arch/powerpc/kernel/vdso/Makefile10
-rw-r--r--arch/powerpc/kernel/vdso/cacheflush.S2
-rw-r--r--arch/powerpc/kernel/vdso/datapage.S4
-rw-r--r--arch/powerpc/kernel/vdso/getrandom.S2
-rw-r--r--arch/powerpc/kernel/vdso/gettimeofday.S5
-rw-r--r--arch/powerpc/kernel/vdso/vdso32.lds.S2
-rw-r--r--arch/powerpc/kernel/vdso/vdso64.lds.S2
-rw-r--r--arch/powerpc/kernel/vdso/vgetrandom.c4
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S3
-rw-r--r--arch/powerpc/kexec/file_load_64.c9
-rw-r--r--arch/powerpc/kvm/book3s.c7
-rw-r--r--arch/powerpc/kvm/book3s_32_mmu_host.c7
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_host.c12
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c25
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_radix.c35
-rw-r--r--arch/powerpc/kvm/book3s_64_vio.c21
-rw-r--r--arch/powerpc/kvm/book3s_hv.c131
-rw-r--r--arch/powerpc/kvm/book3s_hv_nested.c20
-rw-r--r--arch/powerpc/kvm/book3s_hv_nestedv2.c4
-rw-r--r--arch/powerpc/kvm/book3s_hv_uvmem.c25
-rw-r--r--arch/powerpc/kvm/book3s_mmu_hpte.c8
-rw-r--r--arch/powerpc/kvm/book3s_pr.c14
-rw-r--r--arch/powerpc/kvm/book3s_xive_native.c2
-rw-r--r--arch/powerpc/kvm/e500_mmu_host.c19
-rw-r--r--arch/powerpc/kvm/powerpc.c27
-rw-r--r--arch/powerpc/kvm/trace_hv.h2
-rw-r--r--arch/powerpc/lib/code-patching.c2
-rw-r--r--arch/powerpc/lib/feature-fixups.c2
-rw-r--r--arch/powerpc/lib/sstep.c12
-rw-r--r--arch/powerpc/lib/test-code-patching.c2
-rw-r--r--arch/powerpc/lib/test_emulate_step.c2
-rw-r--r--arch/powerpc/mm/book3s32/mmu.c2
-rw-r--r--arch/powerpc/mm/book3s64/hash_utils.c366
-rw-r--r--arch/powerpc/mm/book3s64/pgtable.c13
-rw-r--r--arch/powerpc/mm/book3s64/radix_pgtable.c12
-rw-r--r--arch/powerpc/mm/book3s64/slb.c2
-rw-r--r--arch/powerpc/mm/book3s64/slice.c50
-rw-r--r--arch/powerpc/mm/fault.c10
-rw-r--r--arch/powerpc/mm/init-common.c1
-rw-r--r--arch/powerpc/mm/kasan/init_32.c2
-rw-r--r--arch/powerpc/mm/mem.c2
-rw-r--r--arch/powerpc/mm/nohash/44x.c2
-rw-r--r--arch/powerpc/mm/nohash/book3e_pgtable.c2
-rw-r--r--arch/powerpc/mm/nohash/tlb.c2
-rw-r--r--arch/powerpc/mm/nohash/tlb_64e.c2
-rw-r--r--arch/powerpc/mm/pgtable.c2
-rw-r--r--arch/powerpc/net/bpf_jit.h17
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c849
-rw-r--r--arch/powerpc/net/bpf_jit_comp32.c7
-rw-r--r--arch/powerpc/net/bpf_jit_comp64.c72
-rw-r--r--arch/powerpc/perf/8xx-pmu.c2
-rw-r--r--arch/powerpc/perf/Makefile2
-rw-r--r--arch/powerpc/perf/callchain.c2
-rw-r--r--arch/powerpc/perf/callchain_32.c2
-rw-r--r--arch/powerpc/perf/callchain_64.c2
-rw-r--r--arch/powerpc/perf/core-book3s.c6
-rw-r--r--arch/powerpc/perf/vpa-pmu.c203
-rw-r--r--arch/powerpc/platforms/44x/pci.c23
-rw-r--r--arch/powerpc/platforms/52xx/efika.c1
-rw-r--r--arch/powerpc/platforms/82xx/ep8248e.c2
-rw-r--r--arch/powerpc/platforms/82xx/km82xx.c6
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig21
-rw-r--r--arch/powerpc/platforms/85xx/smp.c2
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_smp.c2
-rw-r--r--arch/powerpc/platforms/Kconfig1
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c2
-rw-r--r--arch/powerpc/platforms/cell/iommu.c49
-rw-r--r--arch/powerpc/platforms/cell/smp.c2
-rw-r--r--arch/powerpc/platforms/cell/spu_syscalls.c68
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c4
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c1
-rw-r--r--arch/powerpc/platforms/embedded6xx/mvme5100.c1
-rw-r--r--arch/powerpc/platforms/maple/Kconfig19
-rw-r--r--arch/powerpc/platforms/maple/Makefile2
-rw-r--r--arch/powerpc/platforms/maple/maple.h14
-rw-r--r--arch/powerpc/platforms/maple/pci.c672
-rw-r--r--arch/powerpc/platforms/maple/setup.c363
-rw-r--r--arch/powerpc/platforms/maple/time.c170
-rw-r--r--arch/powerpc/platforms/powermac/backlight.c14
-rw-r--r--arch/powerpc/platforms/powermac/smp.c2
-rw-r--r--arch/powerpc/platforms/powernv/idle.c2
-rw-r--r--arch/powerpc/platforms/powernv/smp.c7
-rw-r--r--arch/powerpc/platforms/ps3/device-init.c2
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c2
-rw-r--r--arch/powerpc/platforms/ps3/repository.c2
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c5
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig14
-rw-r--r--arch/powerpc/platforms/pseries/dtl.c8
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c5
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c9
-rw-r--r--arch/powerpc/platforms/pseries/lparcfg.c5
-rw-r--r--arch/powerpc/platforms/pseries/msi.c1
-rw-r--r--arch/powerpc/platforms/pseries/papr_scm.c1
-rw-r--r--arch/powerpc/platforms/pseries/plpks.c2
-rw-r--r--arch/powerpc/platforms/pseries/smp.c2
-rw-r--r--arch/powerpc/platforms/pseries/svm.c1
-rw-r--r--arch/powerpc/sysdev/xive/common.c2
-rw-r--r--arch/powerpc/sysdev/xive/spapr.c1
-rw-r--r--arch/powerpc/tools/.gitignore (renamed from scripts/selinux/genheaders/.gitignore)2
-rw-r--r--arch/powerpc/tools/Makefile10
-rwxr-xr-xarch/powerpc/tools/ftrace-gen-ool-stubs.sh52
-rwxr-xr-xarch/powerpc/tools/ftrace_check.sh50
-rw-r--r--arch/powerpc/xmon/xmon.c8
-rw-r--r--arch/riscv/Kconfig145
-rw-r--r--arch/riscv/Makefile8
-rw-r--r--arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi4
-rw-r--r--arch/riscv/boot/dts/sophgo/Makefile1
-rw-r--r--arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts49
-rw-r--r--arch/riscv/boot/dts/sophgo/cv1800b.dtsi10
-rw-r--r--arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts23
-rw-r--r--arch/riscv/boot/dts/sophgo/cv1812h.dtsi11
-rw-r--r--arch/riscv/boot/dts/sophgo/cv181x.dtsi21
-rw-r--r--arch/riscv/boot/dts/sophgo/cv18xx.dtsi32
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2002-licheerv-nano-b.dts95
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2002.dtsi43
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts15
-rw-r--r--arch/riscv/boot/dts/sophgo/sg2042.dtsi6
-rw-r--r--arch/riscv/boot/dts/starfive/Makefile1
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-common.dtsi12
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-deepcomputing-fml13v01.dts17
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts22
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts25
-rw-r--r--arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi25
-rw-r--r--arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts177
-rw-r--r--arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi158
-rw-r--r--arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts30
-rw-r--r--arch/riscv/boot/dts/thead/th1520.dtsi120
-rw-r--r--arch/riscv/configs/defconfig3
-rw-r--r--arch/riscv/errata/andes/errata.c2
-rw-r--r--arch/riscv/errata/sifive/errata.c2
-rw-r--r--arch/riscv/errata/thead/errata.c2
-rw-r--r--arch/riscv/include/asm/Kbuild4
-rw-r--r--arch/riscv/include/asm/cmpxchg.h286
-rw-r--r--arch/riscv/include/asm/compat.h1
-rw-r--r--arch/riscv/include/asm/cpufeature-macros.h66
-rw-r--r--arch/riscv/include/asm/cpufeature.h73
-rw-r--r--arch/riscv/include/asm/csr.h17
-rw-r--r--arch/riscv/include/asm/entry-common.h1
-rw-r--r--arch/riscv/include/asm/ftrace.h22
-rw-r--r--arch/riscv/include/asm/hwcap.h9
-rw-r--r--arch/riscv/include/asm/hwprobe.h2
-rw-r--r--arch/riscv/include/asm/jump_label.h50
-rw-r--r--arch/riscv/include/asm/kvm_host.h10
-rw-r--r--arch/riscv/include/asm/kvm_nacl.h245
-rw-r--r--arch/riscv/include/asm/mmu.h7
-rw-r--r--arch/riscv/include/asm/mmu_context.h13
-rw-r--r--arch/riscv/include/asm/page.h7
-rw-r--r--arch/riscv/include/asm/perf_event.h3
-rw-r--r--arch/riscv/include/asm/pgtable.h32
-rw-r--r--arch/riscv/include/asm/processor.h9
-rw-r--r--arch/riscv/include/asm/sbi.h120
-rw-r--r--arch/riscv/include/asm/set_memory.h1
-rw-r--r--arch/riscv/include/asm/spinlock.h47
-rw-r--r--arch/riscv/include/asm/switch_to.h19
-rw-r--r--arch/riscv/include/asm/text-patching.h (renamed from arch/riscv/include/asm/patch.h)0
-rw-r--r--arch/riscv/include/asm/thread_info.h10
-rw-r--r--arch/riscv/include/asm/uaccess.h43
-rw-r--r--arch/riscv/include/asm/uprobes.h2
-rw-r--r--arch/riscv/include/asm/vdso/time_data.h (renamed from arch/riscv/include/asm/vdso/data.h)8
-rw-r--r--arch/riscv/include/asm/vdso/vsyscall.h4
-rw-r--r--arch/riscv/include/asm/vector.h2
-rw-r--r--arch/riscv/include/uapi/asm/hwprobe.h6
-rw-r--r--arch/riscv/include/uapi/asm/kvm.h4
-rw-r--r--arch/riscv/kernel/Makefile3
-rw-r--r--arch/riscv/kernel/alternative.c2
-rw-r--r--arch/riscv/kernel/asm-offsets.c28
-rw-r--r--arch/riscv/kernel/copy-unaligned.h5
-rw-r--r--arch/riscv/kernel/cpufeature.c31
-rw-r--r--arch/riscv/kernel/fpu.S4
-rw-r--r--arch/riscv/kernel/ftrace.c4
-rw-r--r--arch/riscv/kernel/jump_label.c2
-rw-r--r--arch/riscv/kernel/patch.c2
-rw-r--r--arch/riscv/kernel/perf_callchain.c10
-rw-r--r--arch/riscv/kernel/probes/kprobes.c2
-rw-r--r--arch/riscv/kernel/process.c154
-rw-r--r--arch/riscv/kernel/ptrace.c42
-rw-r--r--arch/riscv/kernel/setup.c39
-rw-r--r--arch/riscv/kernel/smpboot.c2
-rw-r--r--arch/riscv/kernel/suspend.c4
-rw-r--r--arch/riscv/kernel/sys_hwprobe.c46
-rw-r--r--arch/riscv/kernel/traps_misaligned.c139
-rw-r--r--arch/riscv/kernel/unaligned_access_speed.c156
-rw-r--r--arch/riscv/kernel/vdso.c52
-rw-r--r--arch/riscv/kernel/vdso/Makefile9
-rw-r--r--arch/riscv/kernel/vdso/hwprobe.c4
-rw-r--r--arch/riscv/kernel/vec-copy-unaligned.S58
-rw-r--r--arch/riscv/kernel/vector.c2
-rw-r--r--arch/riscv/kvm/Kconfig1
-rw-r--r--arch/riscv/kvm/Makefile27
-rw-r--r--arch/riscv/kvm/aia.c114
-rw-r--r--arch/riscv/kvm/aia_aplic.c3
-rw-r--r--arch/riscv/kvm/main.c63
-rw-r--r--arch/riscv/kvm/mmu.c13
-rw-r--r--arch/riscv/kvm/nacl.c152
-rw-r--r--arch/riscv/kvm/tlb.c57
-rw-r--r--arch/riscv/kvm/vcpu.c195
-rw-r--r--arch/riscv/kvm/vcpu_onereg.c19
-rw-r--r--arch/riscv/kvm/vcpu_sbi.c11
-rw-r--r--arch/riscv/kvm/vcpu_switch.S137
-rw-r--r--arch/riscv/kvm/vcpu_timer.c28
-rw-r--r--arch/riscv/mm/pageattr.c15
-rw-r--r--arch/riscv/net/bpf_jit_comp64.c2
-rw-r--r--arch/riscv/net/bpf_jit_core.c2
-rw-r--r--arch/s390/Kconfig15
-rw-r--r--arch/s390/boot/physmem_info.c83
-rw-r--r--arch/s390/boot/startup.c9
-rw-r--r--arch/s390/boot/uv.c7
-rw-r--r--arch/s390/configs/debug_defconfig2
-rw-r--r--arch/s390/configs/defconfig2
-rw-r--r--arch/s390/crypto/paes_s390.c413
-rw-r--r--arch/s390/crypto/prng.c14
-rw-r--r--arch/s390/include/asm/asm.h51
-rw-r--r--arch/s390/include/asm/atomic.h28
-rw-r--r--arch/s390/include/asm/atomic_ops.h75
-rw-r--r--arch/s390/include/asm/cmpxchg.h374
-rw-r--r--arch/s390/include/asm/cpacf.h2
-rw-r--r--arch/s390/include/asm/cpu_mf.h57
-rw-r--r--arch/s390/include/asm/debug.h8
-rw-r--r--arch/s390/include/asm/facility.h18
-rw-r--r--arch/s390/include/asm/ftrace.h29
-rw-r--r--arch/s390/include/asm/gmap.h7
-rw-r--r--arch/s390/include/asm/hugetlb.h77
-rw-r--r--arch/s390/include/asm/kexec.h3
-rw-r--r--arch/s390/include/asm/kvm_host.h21
-rw-r--r--arch/s390/include/asm/lowcore.h3
-rw-r--r--arch/s390/include/asm/page.h24
-rw-r--r--arch/s390/include/asm/pai.h10
-rw-r--r--arch/s390/include/asm/pci.h19
-rw-r--r--arch/s390/include/asm/pci_clp.h13
-rw-r--r--arch/s390/include/asm/pci_io.h6
-rw-r--r--arch/s390/include/asm/perf_event.h6
-rw-r--r--arch/s390/include/asm/pgtable.h119
-rw-r--r--arch/s390/include/asm/physmem_info.h3
-rw-r--r--arch/s390/include/asm/preempt.h31
-rw-r--r--arch/s390/include/asm/processor.h5
-rw-r--r--arch/s390/include/asm/ptrace.h2
-rw-r--r--arch/s390/include/asm/set_memory.h2
-rw-r--r--arch/s390/include/asm/sigp.h11
-rw-r--r--arch/s390/include/asm/sparsemem.h18
-rw-r--r--arch/s390/include/asm/spinlock.h20
-rw-r--r--arch/s390/include/asm/spinlock_types.h2
-rw-r--r--arch/s390/include/asm/stp.h1
-rw-r--r--arch/s390/include/asm/thread_info.h21
-rw-r--r--arch/s390/include/asm/timex.h38
-rw-r--r--arch/s390/include/asm/tlbflush.h5
-rw-r--r--arch/s390/include/asm/uv.h176
-rw-r--r--arch/s390/include/asm/vdso.h3
-rw-r--r--arch/s390/include/asm/vdso/data.h12
-rw-r--r--arch/s390/include/asm/vdso/time_data.h12
-rw-r--r--arch/s390/include/asm/vdso/vsyscall.h5
-rw-r--r--arch/s390/include/uapi/asm/dasd.h2
-rw-r--r--arch/s390/include/uapi/asm/kvm.h3
-rw-r--r--arch/s390/include/uapi/asm/pkey.h38
-rw-r--r--arch/s390/include/uapi/asm/uvdevice.h32
-rw-r--r--arch/s390/kernel/asm-offsets.c7
-rw-r--r--arch/s390/kernel/cpcmd.c10
-rw-r--r--arch/s390/kernel/crash_dump.c11
-rw-r--r--arch/s390/kernel/debug.c101
-rw-r--r--arch/s390/kernel/diag.c12
-rw-r--r--arch/s390/kernel/entry.S48
-rw-r--r--arch/s390/kernel/ftrace.c2
-rw-r--r--arch/s390/kernel/ipl.c84
-rw-r--r--arch/s390/kernel/irq.c13
-rw-r--r--arch/s390/kernel/kprobes.c6
-rw-r--r--arch/s390/kernel/nospec-sysfs.c10
-rw-r--r--arch/s390/kernel/os_info.c2
-rw-r--r--arch/s390/kernel/perf_cpum_cf.c14
-rw-r--r--arch/s390/kernel/perf_cpum_sf.c122
-rw-r--r--arch/s390/kernel/perf_event.c6
-rw-r--r--arch/s390/kernel/smp.c20
-rw-r--r--arch/s390/kernel/stacktrace.c2
-rw-r--r--arch/s390/kernel/sthyi.c10
-rw-r--r--arch/s390/kernel/syscalls/Makefile27
-rw-r--r--arch/s390/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/s390/kernel/time.c38
-rw-r--r--arch/s390/kernel/topology.c29
-rw-r--r--arch/s390/kernel/traps.c24
-rw-r--r--arch/s390/kernel/uv.c256
-rw-r--r--arch/s390/kernel/vdso32/vdso32.lds.S2
-rw-r--r--arch/s390/kernel/vdso64/vdso64.lds.S2
-rw-r--r--arch/s390/kvm/gaccess.c16
-rw-r--r--arch/s390/kvm/intercept.c4
-rw-r--r--arch/s390/kvm/interrupt.c25
-rw-r--r--arch/s390/kvm/kvm-s390.c203
-rw-r--r--arch/s390/kvm/kvm-s390.h8
-rw-r--r--arch/s390/kvm/pci.c7
-rw-r--r--arch/s390/kvm/vsie.c26
-rw-r--r--arch/s390/lib/spinlock.c46
-rw-r--r--arch/s390/lib/string.c10
-rw-r--r--arch/s390/lib/test_unwind.c4
-rw-r--r--arch/s390/mm/extmem.c14
-rw-r--r--arch/s390/mm/fault.c212
-rw-r--r--arch/s390/mm/gmap.c169
-rw-r--r--arch/s390/mm/hugetlbpage.c116
-rw-r--r--arch/s390/mm/mmap.c9
-rw-r--r--arch/s390/mm/pageattr.c28
-rw-r--r--arch/s390/mm/pgalloc.c4
-rw-r--r--arch/s390/mm/pgtable.c2
-rw-r--r--arch/s390/pci/pci.c125
-rw-r--r--arch/s390/pci/pci_bus.c50
-rw-r--r--arch/s390/pci/pci_bus.h5
-rw-r--r--arch/s390/pci/pci_clp.c46
-rw-r--r--arch/s390/pci/pci_debug.c10
-rw-r--r--arch/s390/pci/pci_event.c19
-rw-r--r--arch/s390/pci/pci_insn.c106
-rw-r--r--arch/s390/pci/pci_iov.h2
-rw-r--r--arch/s390/pci/pci_mmio.c90
-rw-r--r--arch/s390/pci/pci_sysfs.c6
-rw-r--r--arch/s390/purgatory/head.S2
-rw-r--r--arch/s390/tools/gen_facilities.c2
-rw-r--r--arch/sh/Kconfig3
-rw-r--r--arch/sh/configs/landisk_defconfig1
-rw-r--r--arch/sh/configs/titan_defconfig1
-rw-r--r--arch/sh/include/asm/Kbuild1
-rw-r--r--arch/sh/include/asm/hugetlb.h15
-rw-r--r--arch/sh/include/asm/page.h7
-rw-r--r--arch/sh/include/asm/spinlock_types.h2
-rw-r--r--arch/sh/include/asm/vga.h7
-rw-r--r--arch/sh/kernel/cpu/proc.c2
-rw-r--r--arch/sh/kernel/setup.c2
-rw-r--r--arch/sh/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/sparc/Makefile4
-rw-r--r--arch/sparc/include/asm/Kbuild1
-rw-r--r--arch/sparc/include/asm/hvtramp.h2
-rw-r--r--arch/sparc/include/asm/page.h2
-rw-r--r--arch/sparc/include/asm/page_32.h4
-rw-r--r--arch/sparc/include/asm/page_64.h4
-rw-r--r--arch/sparc/include/asm/vga.h60
-rw-r--r--arch/sparc/include/uapi/asm/socket.h2
-rw-r--r--arch/sparc/kernel/smp_64.c4
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c17
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c37
-rw-r--r--arch/sparc/kernel/syscalls/syscall.tbl4
-rw-r--r--arch/sparc/kernel/time_32.c1
-rw-r--r--arch/sparc/kernel/time_64.c1
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S5
-rw-r--r--arch/sparc/mm/hugetlbpage.c108
-rw-r--r--arch/sparc/vdso/Makefile2
-rw-r--r--arch/sparc/vdso/vclock_gettime.c28
-rw-r--r--arch/um/Kconfig24
-rw-r--r--arch/um/Makefile7
-rw-r--r--arch/um/Makefile-skas14
-rw-r--r--arch/um/configs/i386_defconfig2
-rw-r--r--arch/um/configs/x86_64_defconfig1
-rw-r--r--arch/um/drivers/chan_user.c2
-rw-r--r--arch/um/drivers/hostaudio_kern.c2
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--arch/um/drivers/ubd_kern.c5
-rw-r--r--arch/um/drivers/vector_kern.c3
-rw-r--r--arch/um/drivers/vhost_user.h4
-rw-r--r--arch/um/drivers/virtio_uml.c51
-rw-r--r--arch/um/include/asm/Kbuild1
-rw-r--r--arch/um/include/asm/current.h23
-rw-r--r--arch/um/include/asm/page.h39
-rw-r--r--arch/um/include/asm/pgalloc.h11
-rw-r--r--arch/um/include/asm/pgtable-2level.h2
-rw-r--r--arch/um/include/asm/pgtable-4level.h (renamed from arch/um/include/asm/pgtable-3level.h)59
-rw-r--r--arch/um/include/asm/pgtable.h85
-rw-r--r--arch/um/include/asm/processor-generic.h7
-rw-r--r--arch/um/include/asm/thread_info.h18
-rw-r--r--arch/um/include/asm/tlbflush.h4
-rw-r--r--arch/um/include/shared/as-layout.h10
-rw-r--r--arch/um/include/shared/common-offsets.h15
-rw-r--r--arch/um/include/shared/kern_util.h1
-rw-r--r--arch/um/include/shared/mem_user.h5
-rw-r--r--arch/um/include/shared/os.h15
-rw-r--r--arch/um/include/shared/registers.h6
-rw-r--r--arch/um/include/shared/skas/stub-data.h12
-rw-r--r--arch/um/include/shared/timetravel.h5
-rw-r--r--arch/um/include/shared/user.h2
-rw-r--r--arch/um/kernel/dtb.c3
-rw-r--r--arch/um/kernel/dyn.lds.S5
-rw-r--r--arch/um/kernel/initrd.c1
-rw-r--r--arch/um/kernel/irq.c112
-rw-r--r--arch/um/kernel/mem.c20
-rw-r--r--arch/um/kernel/physmem.c39
-rw-r--r--arch/um/kernel/process.c24
-rw-r--r--arch/um/kernel/skas/.gitignore2
-rw-r--r--arch/um/kernel/skas/Makefile38
-rw-r--r--arch/um/kernel/skas/mmu.c28
-rw-r--r--arch/um/kernel/skas/process.c4
-rw-r--r--arch/um/kernel/skas/stub.c10
-rw-r--r--arch/um/kernel/skas/stub_exe.c95
-rw-r--r--arch/um/kernel/skas/stub_exe_embed.S11
-rw-r--r--arch/um/kernel/sysrq.c8
-rw-r--r--arch/um/kernel/time.c20
-rw-r--r--arch/um/kernel/tlb.c74
-rw-r--r--arch/um/kernel/trap.c16
-rw-r--r--arch/um/kernel/um_arch.c91
-rw-r--r--arch/um/kernel/uml.lds.S2
-rw-r--r--arch/um/os-Linux/Makefile2
-rw-r--r--arch/um/os-Linux/file.c6
-rw-r--r--arch/um/os-Linux/main.c23
-rw-r--r--arch/um/os-Linux/mem.c14
-rw-r--r--arch/um/os-Linux/process.c88
-rw-r--r--arch/um/os-Linux/registers.c11
-rw-r--r--arch/um/os-Linux/sigio.c1
-rw-r--r--arch/um/os-Linux/signal.c55
-rw-r--r--arch/um/os-Linux/skas/mem.c21
-rw-r--r--arch/um/os-Linux/skas/process.c231
-rw-r--r--arch/um/os-Linux/umid.c2
-rw-r--r--arch/um/os-Linux/util.c4
-rw-r--r--arch/x86/Kconfig34
-rw-r--r--arch/x86/Makefile5
-rw-r--r--arch/x86/boot/boot.h1
-rw-r--r--arch/x86/boot/compressed/misc.c15
-rw-r--r--arch/x86/boot/string.c8
-rw-r--r--arch/x86/boot/string.h1
-rw-r--r--arch/x86/coco/sev/core.c269
-rw-r--r--arch/x86/coco/tdx/tdx.c138
-rw-r--r--arch/x86/crypto/Kconfig4
-rw-r--r--arch/x86/crypto/aegis128-aesni-asm.S532
-rw-r--r--arch/x86/crypto/aegis128-aesni-glue.c145
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c2
-rw-r--r--arch/x86/crypto/cast5-avx-x86_64-asm_64.S76
-rw-r--r--arch/x86/crypto/crc32c-intel_glue.c2
-rw-r--r--arch/x86/crypto/crc32c-pcl-intel-asm_64.S354
-rw-r--r--arch/x86/entry/entry.S16
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl4
-rw-r--r--arch/x86/entry/syscalls/syscall_64.tbl4
-rw-r--r--arch/x86/entry/vdso/vdso-layout.lds.S20
-rw-r--r--arch/x86/entry/vdso/vma.c95
-rw-r--r--arch/x86/events/amd/core.c10
-rw-r--r--arch/x86/events/amd/uncore.c5
-rw-r--r--arch/x86/events/core.c64
-rw-r--r--arch/x86/events/intel/core.c137
-rw-r--r--arch/x86/events/intel/ds.c21
-rw-r--r--arch/x86/events/intel/pt.c84
-rw-r--r--arch/x86/events/intel/pt.h6
-rw-r--r--arch/x86/events/perf_event.h34
-rw-r--r--arch/x86/events/rapl.c130
-rw-r--r--arch/x86/include/asm/alternative.h14
-rw-r--r--arch/x86/include/asm/asm-prototypes.h3
-rw-r--r--arch/x86/include/asm/atomic64_32.h3
-rw-r--r--arch/x86/include/asm/cmpxchg_32.h6
-rw-r--r--arch/x86/include/asm/cpu.h17
-rw-r--r--arch/x86/include/asm/cpufeatures.h7
-rw-r--r--arch/x86/include/asm/cpuid.h8
-rw-r--r--arch/x86/include/asm/ftrace.h30
-rw-r--r--arch/x86/include/asm/futex.h8
-rw-r--r--arch/x86/include/asm/intel-family.h7
-rw-r--r--arch/x86/include/asm/io.h5
-rw-r--r--arch/x86/include/asm/jump_label.h35
-rw-r--r--arch/x86/include/asm/kvm-x86-ops.h1
-rw-r--r--arch/x86/include/asm/kvm_host.h13
-rw-r--r--arch/x86/include/asm/mce.h36
-rw-r--r--arch/x86/include/asm/page.h2
-rw-r--r--arch/x86/include/asm/page_64.h2
-rw-r--r--arch/x86/include/asm/page_types.h5
-rw-r--r--arch/x86/include/asm/percpu.h7
-rw-r--r--arch/x86/include/asm/perf_event.h12
-rw-r--r--arch/x86/include/asm/pgtable.h37
-rw-r--r--arch/x86/include/asm/pgtable_64_types.h2
-rw-r--r--arch/x86/include/asm/processor.h18
-rw-r--r--arch/x86/include/asm/set_memory.h1
-rw-r--r--arch/x86/include/asm/sev-common.h27
-rw-r--r--arch/x86/include/asm/sev.h67
-rw-r--r--arch/x86/include/asm/shared/tdx.h13
-rw-r--r--arch/x86/include/asm/text-patching.h1
-rw-r--r--arch/x86/include/asm/thread_info.h6
-rw-r--r--arch/x86/include/asm/timer.h2
-rw-r--r--arch/x86/include/asm/tlb.h4
-rw-r--r--arch/x86/include/asm/topology.h14
-rw-r--r--arch/x86/include/asm/vdso/getrandom.h10
-rw-r--r--arch/x86/include/asm/vdso/gettimeofday.h12
-rw-r--r--arch/x86/include/asm/vdso/vsyscall.h15
-rw-r--r--arch/x86/include/asm/vvar.h71
-rw-r--r--arch/x86/include/uapi/asm/amd_hsmp.h3
-rw-r--r--arch/x86/include/uapi/asm/kvm.h1
-rw-r--r--arch/x86/include/uapi/asm/mce.h3
-rw-r--r--arch/x86/include/uapi/asm/mman.h3
-rw-r--r--arch/x86/kernel/acpi/boot.c6
-rw-r--r--arch/x86/kernel/acpi/cppc.c30
-rw-r--r--arch/x86/kernel/acpi/wakeup_64.S1
-rw-r--r--arch/x86/kernel/alternative.c181
-rw-r--r--arch/x86/kernel/apic/vector.c8
-rw-r--r--arch/x86/kernel/cpu/Makefile2
-rw-r--r--arch/x86/kernel/cpu/amd.c12
-rw-r--r--arch/x86/kernel/cpu/bus_lock.c406
-rw-r--r--arch/x86/kernel/cpu/common.c51
-rw-r--r--arch/x86/kernel/cpu/debugfs.c1
-rw-r--r--arch/x86/kernel/cpu/intel.c422
-rw-r--r--arch/x86/kernel/cpu/mce/amd.c30
-rw-r--r--arch/x86/kernel/cpu/mce/apei.c107
-rw-r--r--arch/x86/kernel/cpu/mce/core.c216
-rw-r--r--arch/x86/kernel/cpu/mce/dev-mcelog.c11
-rw-r--r--arch/x86/kernel/cpu/mce/genpool.c18
-rw-r--r--arch/x86/kernel/cpu/mce/inject.c6
-rw-r--r--arch/x86/kernel/cpu/mce/intel.c2
-rw-r--r--arch/x86/kernel/cpu/mce/internal.h4
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c25
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c10
-rw-r--r--arch/x86/kernel/cpu/proc.c10
-rw-r--r--arch/x86/kernel/cpu/resctrl/monitor.c3
-rw-r--r--arch/x86/kernel/cpu/resctrl/rdtgroup.c2
-rw-r--r--arch/x86/kernel/cpu/scattered.c56
-rw-r--r--arch/x86/kernel/cpu/sgx/main.c12
-rw-r--r--arch/x86/kernel/cpu/topology_amd.c3
-rw-r--r--arch/x86/kernel/cpu/topology_common.c34
-rw-r--r--arch/x86/kernel/devicetree.c2
-rw-r--r--arch/x86/kernel/early-quirks.c2
-rw-r--r--arch/x86/kernel/ftrace.c32
-rw-r--r--arch/x86/kernel/head_64.S1
-rw-r--r--arch/x86/kernel/kprobes/ftrace.c19
-rw-r--r--arch/x86/kernel/module.c45
-rw-r--r--arch/x86/kernel/smpboot.c5
-rw-r--r--arch/x86/kernel/sys_x86_64.c24
-rw-r--r--arch/x86/kernel/tsc.c5
-rw-r--r--arch/x86/kernel/unwind_orc.c2
-rw-r--r--arch/x86/kernel/vmlinux.lds.S49
-rw-r--r--arch/x86/kvm/Kconfig6
-rw-r--r--arch/x86/kvm/cpuid.c22
-rw-r--r--arch/x86/kvm/cpuid.h1
-rw-r--r--arch/x86/kvm/emulate.c15
-rw-r--r--arch/x86/kvm/kvm_cache_regs.h17
-rw-r--r--arch/x86/kvm/kvm_emulate.h5
-rw-r--r--arch/x86/kvm/lapic.c80
-rw-r--r--arch/x86/kvm/lapic.h11
-rw-r--r--arch/x86/kvm/mmu.h1
-rw-r--r--arch/x86/kvm/mmu/mmu.c444
-rw-r--r--arch/x86/kvm/mmu/mmu_internal.h10
-rw-r--r--arch/x86/kvm/mmu/paging_tmpl.h31
-rw-r--r--arch/x86/kvm/mmu/spte.c102
-rw-r--r--arch/x86/kvm/mmu/spte.h78
-rw-r--r--arch/x86/kvm/mmu/tdp_mmu.c276
-rw-r--r--arch/x86/kvm/mmu/tdp_mmu.h6
-rw-r--r--arch/x86/kvm/mtrr.c1
-rw-r--r--arch/x86/kvm/reverse_cpuid.h1
-rw-r--r--arch/x86/kvm/svm/nested.c4
-rw-r--r--arch/x86/kvm/svm/sev.c66
-rw-r--r--arch/x86/kvm/svm/svm.c13
-rw-r--r--arch/x86/kvm/vmx/hyperv.c1
-rw-r--r--arch/x86/kvm/vmx/main.c1
-rw-r--r--arch/x86/kvm/vmx/nested.c107
-rw-r--r--arch/x86/kvm/vmx/pmu_intel.c2
-rw-r--r--arch/x86/kvm/vmx/sgx.c5
-rw-r--r--arch/x86/kvm/vmx/vmx.c131
-rw-r--r--arch/x86/kvm/vmx/vmx.h3
-rw-r--r--arch/x86/kvm/vmx/vmx_ops.h16
-rw-r--r--arch/x86/kvm/x86.c141
-rw-r--r--arch/x86/kvm/x86.h48
-rw-r--r--arch/x86/kvm/xen.c12
-rw-r--r--arch/x86/mm/hugetlbpage.c101
-rw-r--r--arch/x86/mm/init.c60
-rw-r--r--arch/x86/mm/init_64.c30
-rw-r--r--arch/x86/mm/ioremap.c6
-rw-r--r--arch/x86/mm/kaslr.c16
-rw-r--r--arch/x86/mm/mem_encrypt_amd.c77
-rw-r--r--arch/x86/mm/mem_encrypt_identity.c11
-rw-r--r--arch/x86/mm/mmap.c5
-rw-r--r--arch/x86/mm/pat/set_memory.c8
-rw-r--r--arch/x86/mm/tlb.c5
-rw-r--r--arch/x86/net/bpf_jit_comp.c149
-rw-r--r--arch/x86/pci/acpi.c119
-rw-r--r--arch/x86/pci/fixup.c2
-rw-r--r--arch/x86/platform/efi/efi.c20
-rw-r--r--arch/x86/platform/efi/efi_64.c42
-rw-r--r--arch/x86/platform/efi/quirks.c3
-rw-r--r--arch/x86/platform/intel-mid/pwr.c14
-rw-r--r--arch/x86/platform/intel-quark/imr.c2
-rw-r--r--arch/x86/platform/intel-quark/imr_selftest.c2
-rw-r--r--arch/x86/platform/iris/iris.c2
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-pm.c4
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-sci.c2
-rw-r--r--arch/x86/platform/pvh/head.S50
-rw-r--r--arch/x86/tools/relocs.c2
-rw-r--r--arch/x86/um/Kconfig12
-rw-r--r--arch/x86/um/Makefile2
-rw-r--r--arch/x86/um/asm/elf.h2
-rw-r--r--arch/x86/um/asm/ptrace.h10
-rw-r--r--arch/x86/um/os-Linux/Makefile2
-rw-r--r--arch/x86/um/os-Linux/registers.c145
-rw-r--r--arch/x86/um/os-Linux/task_size.c151
-rw-r--r--arch/x86/um/ptrace.c267
-rw-r--r--arch/x86/um/ptrace_32.c84
-rw-r--r--arch/x86/um/ptrace_64.c43
-rw-r--r--arch/x86/um/shared/sysdep/ptrace.h8
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_32.h4
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_64.h4
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_user.h6
-rw-r--r--arch/x86/um/shared/sysdep/stub_32.h18
-rw-r--r--arch/x86/um/shared/sysdep/stub_64.h27
-rw-r--r--arch/x86/um/signal.c336
-rw-r--r--arch/x86/um/user-offsets.c8
-rw-r--r--arch/x86/um/vdso/Makefile5
-rw-r--r--arch/x86/um/vdso/checkundef.sh11
-rw-r--r--arch/x86/virt/svm/Makefile1
-rw-r--r--arch/x86/virt/svm/cmdline.c45
-rw-r--r--arch/x86/xen/xen-head.S6
-rw-r--r--arch/xtensa/include/asm/Kbuild1
-rw-r--r--arch/xtensa/include/asm/page.h27
-rw-r--r--arch/xtensa/include/asm/spinlock_types.h2
-rw-r--r--arch/xtensa/include/uapi/asm/mman.h3
-rw-r--r--arch/xtensa/kernel/setup.c2
-rw-r--r--arch/xtensa/kernel/syscalls/syscall.tbl4
-rw-r--r--block/bfq-cgroup.c1
-rw-r--r--block/bfq-iosched.c43
-rw-r--r--block/bio-integrity.c13
-rw-r--r--block/bio.c81
-rw-r--r--block/blk-core.c26
-rw-r--r--block/blk-crypto-fallback.c2
-rw-r--r--block/blk-integrity.c4
-rw-r--r--block/blk-ioc.c9
-rw-r--r--block/blk-merge.c108
-rw-r--r--block/blk-mq.c321
-rw-r--r--block/blk-mq.h15
-rw-r--r--block/blk-rq-qos.c4
-rw-r--r--block/blk-settings.c181
-rw-r--r--block/blk-sysfs.c86
-rw-r--r--block/blk-throttle.c76
-rw-r--r--block/blk-zoned.c82
-rw-r--r--block/blk.h52
-rw-r--r--block/elevator.c18
-rw-r--r--block/elevator.h4
-rw-r--r--block/fops.c25
-rw-r--r--block/genhd.c145
-rw-r--r--block/mq-deadline.c13
-rw-r--r--block/partitions/Kconfig9
-rw-r--r--block/partitions/Makefile1
-rw-r--r--block/partitions/check.h1
-rw-r--r--block/partitions/cmdline.c3
-rw-r--r--block/partitions/core.c8
-rw-r--r--block/partitions/of.c110
-rw-r--r--block/sed-opal.c26
-rw-r--r--crypto/Kconfig7
-rw-r--r--crypto/Makefile7
-rw-r--r--crypto/akcipher.c64
-rw-r--r--crypto/algapi.c6
-rw-r--r--crypto/asymmetric_keys/public_key.c58
-rw-r--r--crypto/asymmetric_keys/signature.c63
-rw-r--r--crypto/crc32_generic.c94
-rw-r--r--crypto/crc32c_generic.c94
-rw-r--r--crypto/drbg.c5
-rw-r--r--crypto/ecdsa-p1363.c159
-rw-r--r--crypto/ecdsa-x962.c237
-rw-r--r--crypto/ecdsa.c209
-rw-r--r--crypto/ecrdsa.c64
-rw-r--r--crypto/internal.h19
-rw-r--r--crypto/jitterentropy-testing.c31
-rw-r--r--crypto/jitterentropy.h4
-rw-r--r--crypto/pcrypt.c12
-rw-r--r--crypto/rsa-pkcs1pad.c371
-rw-r--r--crypto/rsa.c17
-rw-r--r--crypto/rsassa-pkcs1.c454
-rw-r--r--crypto/sig.c145
-rw-r--r--crypto/testmgr.c328
-rw-r--r--crypto/testmgr.h939
-rw-r--r--drivers/accessibility/speakup/Makefile4
-rw-r--r--drivers/acpi/Kconfig11
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/ac.c2
-rw-r--r--drivers/acpi/acpi_apd.c2
-rw-r--r--drivers/acpi/acpi_pad.c2
-rw-r--r--drivers/acpi/acpi_tad.c2
-rw-r--r--drivers/acpi/apei/einj-core.c2
-rw-r--r--drivers/acpi/apei/ghes.c2
-rw-r--r--drivers/acpi/arm64/agdi.c2
-rw-r--r--drivers/acpi/arm64/gtdt.c33
-rw-r--r--drivers/acpi/arm64/init.c2
-rw-r--r--drivers/acpi/arm64/iort.c13
-rw-r--r--drivers/acpi/battery.c34
-rw-r--r--drivers/acpi/bus.c5
-rw-r--r--drivers/acpi/cppc_acpi.c13
-rw-r--r--drivers/acpi/dptf/dptf_pch_fivr.c2
-rw-r--r--drivers/acpi/dptf/dptf_power.c2
-rw-r--r--drivers/acpi/ec.c4
-rw-r--r--drivers/acpi/event.c4
-rw-r--r--drivers/acpi/evged.c2
-rw-r--r--drivers/acpi/fan_core.c2
-rw-r--r--drivers/acpi/internal.h25
-rw-r--r--drivers/acpi/osl.c12
-rw-r--r--drivers/acpi/pci_link.c4
-rw-r--r--drivers/acpi/pci_root.c4
-rw-r--r--drivers/acpi/pfr_telemetry.c5
-rw-r--r--drivers/acpi/pfr_update.c2
-rw-r--r--drivers/acpi/power.c4
-rw-r--r--drivers/acpi/processor_driver.c9
-rw-r--r--drivers/acpi/processor_idle.c19
-rw-r--r--drivers/acpi/processor_perflib.c13
-rw-r--r--drivers/acpi/riscv/init.c2
-rw-r--r--drivers/acpi/sbs.c4
-rw-r--r--drivers/acpi/sbshc.c13
-rw-r--r--drivers/acpi/scan.c14
-rw-r--r--drivers/acpi/thermal.c6
-rw-r--r--drivers/acpi/video_detect.c16
-rw-r--r--drivers/acpi/x86/utils.c79
-rw-r--r--drivers/amba/bus.c6
-rw-r--r--drivers/android/binder.c64
-rw-r--r--drivers/android/binder_alloc.c8
-rw-r--r--drivers/android/binder_alloc.h2
-rw-r--r--drivers/ata/acard-ahci.c6
-rw-r--r--drivers/ata/ahci.c8
-rw-r--r--drivers/ata/ahci_brcm.c2
-rw-r--r--drivers/ata/ahci_ceva.c2
-rw-r--r--drivers/ata/ahci_da850.c2
-rw-r--r--drivers/ata/ahci_dm816.c2
-rw-r--r--drivers/ata/ahci_dwc.c2
-rw-r--r--drivers/ata/ahci_imx.c4
-rw-r--r--drivers/ata/ahci_mtk.c2
-rw-r--r--drivers/ata/ahci_mvebu.c2
-rw-r--r--drivers/ata/ahci_platform.c2
-rw-r--r--drivers/ata/ahci_qoriq.c2
-rw-r--r--drivers/ata/ahci_seattle.c2
-rw-r--r--drivers/ata/ahci_st.c2
-rw-r--r--drivers/ata/ahci_sunxi.c2
-rw-r--r--drivers/ata/ahci_tegra.c2
-rw-r--r--drivers/ata/ahci_xgene.c4
-rw-r--r--drivers/ata/libata-acpi.c4
-rw-r--r--drivers/ata/libata-scsi.c516
-rw-r--r--drivers/ata/pata_arasan_cf.c2
-rw-r--r--drivers/ata/pata_ep93xx.c2
-rw-r--r--drivers/ata/pata_falcon.c4
-rw-r--r--drivers/ata/pata_ftide010.c2
-rw-r--r--drivers/ata/pata_gayle.c6
-rw-r--r--drivers/ata/pata_imx.c2
-rw-r--r--drivers/ata/pata_it8213.c2
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c2
-rw-r--r--drivers/ata/pata_mpc52xx.c2
-rw-r--r--drivers/ata/pata_octeon_cf.c2
-rw-r--r--drivers/ata/pata_of_platform.c2
-rw-r--r--drivers/ata/pata_oldpiix.c2
-rw-r--r--drivers/ata/pata_platform.c2
-rw-r--r--drivers/ata/pata_pxa.c2
-rw-r--r--drivers/ata/pata_radisys.c2
-rw-r--r--drivers/ata/pata_rb532_cf.c2
-rw-r--r--drivers/ata/sata_dwc_460ex.c2
-rw-r--r--drivers/ata/sata_fsl.c2
-rw-r--r--drivers/ata/sata_gemini.c2
-rw-r--r--drivers/ata/sata_highbank.c12
-rw-r--r--drivers/ata/sata_mv.c2
-rw-r--r--drivers/ata/sata_rcar.c2
-rw-r--r--drivers/auxdisplay/cfag12864b.c12
-rw-r--r--drivers/auxdisplay/ht16k33.c10
-rw-r--r--drivers/auxdisplay/lcd2s.c2
-rw-r--r--drivers/base/arch_topology.c6
-rw-r--r--drivers/base/auxiliary.c31
-rw-r--r--drivers/base/cacheinfo.c15
-rw-r--r--drivers/base/class.c4
-rw-r--r--drivers/base/core.c192
-rw-r--r--drivers/base/firmware_loader/main.c7
-rw-r--r--drivers/base/node.c12
-rw-r--r--drivers/base/power/common.c21
-rw-r--r--drivers/base/power/qos.c1
-rw-r--r--drivers/base/power/sysfs.c17
-rw-r--r--drivers/base/regmap/internal.h1
-rw-r--r--drivers/base/regmap/regcache-maple.c3
-rw-r--r--drivers/base/regmap/regmap-irq.c9
-rw-r--r--drivers/base/regmap/regmap-kunit.c45
-rw-r--r--drivers/base/regmap/regmap.c1
-rw-r--r--drivers/base/topology.c40
-rw-r--r--drivers/base/trace.h6
-rw-r--r--drivers/block/Kconfig2
-rw-r--r--drivers/block/brd.c70
-rw-r--r--drivers/block/loop.c39
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c14
-rw-r--r--drivers/block/null_blk/main.c9
-rw-r--r--drivers/block/null_blk/zoned.c2
-rw-r--r--drivers/block/rbd.c1
-rw-r--r--drivers/block/rnull.rs4
-rw-r--r--drivers/block/ublk_drv.c210
-rw-r--r--drivers/block/virtio_blk.c55
-rw-r--r--drivers/block/zram/Kconfig1
-rw-r--r--drivers/block/zram/zram_drv.c384
-rw-r--r--drivers/block/zram/zram_drv.h3
-rw-r--r--drivers/bluetooth/Kconfig6
-rw-r--r--drivers/bluetooth/btbcm.c4
-rw-r--r--drivers/bluetooth/btintel.c113
-rw-r--r--drivers/bluetooth/btintel.h10
-rw-r--r--drivers/bluetooth/btintel_pcie.c387
-rw-r--r--drivers/bluetooth/btintel_pcie.h18
-rw-r--r--drivers/bluetooth/btmtk.c3
-rw-r--r--drivers/bluetooth/btmtksdio.c21
-rw-r--r--drivers/bluetooth/btmtkuart.c2
-rw-r--r--drivers/bluetooth/btnxpuart.c81
-rw-r--r--drivers/bluetooth/btrtl.c2
-rw-r--r--drivers/bluetooth/btusb.c76
-rw-r--r--drivers/bluetooth/hci_bcm.c25
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/bluetooth/hci_ll.c2
-rw-r--r--drivers/bluetooth/hci_nokia.c2
-rw-r--r--drivers/bluetooth/hci_qca.c32
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-bus.c2
-rw-r--r--drivers/bus/hisi_lpc.c2
-rw-r--r--drivers/bus/mhi/host/boot.c4
-rw-r--r--drivers/bus/mhi/host/internal.h2
-rw-r--r--drivers/bus/mhi/host/pci_generic.c6
-rw-r--r--drivers/bus/mhi/host/trace.h25
-rw-r--r--drivers/bus/omap-ocp2scp.c2
-rw-r--r--drivers/bus/omap_l3_smx.c2
-rw-r--r--drivers/bus/qcom-ssc-block-bus.c2
-rw-r--r--drivers/bus/simple-pm-bus.c2
-rw-r--r--drivers/bus/sun50i-de2.c2
-rw-r--r--drivers/bus/sunxi-rsb.c2
-rw-r--r--drivers/bus/tegra-aconnect.c2
-rw-r--r--drivers/bus/tegra-gmi.c2
-rw-r--r--drivers/bus/ti-pwmss.c2
-rw-r--r--drivers/bus/ti-sysc.c2
-rw-r--r--drivers/bus/ts-nbus.c2
-rw-r--r--drivers/cdx/cdx.c2
-rw-r--r--drivers/char/Kconfig1
-rw-r--r--drivers/char/hpet.c1
-rw-r--r--drivers/char/hw_random/Kconfig30
-rw-r--r--drivers/char/hw_random/Makefile2
-rw-r--r--drivers/char/hw_random/airoha-trng.c243
-rw-r--r--drivers/char/hw_random/atmel-rng.c2
-rw-r--r--drivers/char/hw_random/bcm74110-rng.c125
-rw-r--r--drivers/char/hw_random/cctrng.c2
-rw-r--r--drivers/char/hw_random/core.c11
-rw-r--r--drivers/char/hw_random/exynos-trng.c2
-rw-r--r--drivers/char/hw_random/histb-rng.c2
-rw-r--r--drivers/char/hw_random/ingenic-rng.c2
-rw-r--r--drivers/char/hw_random/ks-sa-rng.c2
-rw-r--r--drivers/char/hw_random/mxc-rnga.c2
-rw-r--r--drivers/char/hw_random/n2-drv.c2
-rw-r--r--drivers/char/hw_random/npcm-rng.c2
-rw-r--r--drivers/char/hw_random/omap-rng.c2
-rw-r--r--drivers/char/hw_random/stm32-rng.c78
-rw-r--r--drivers/char/hw_random/timeriomem-rng.c2
-rw-r--r--drivers/char/hw_random/xgene-rng.c2
-rw-r--r--drivers/char/powernv-op-panel.c2
-rw-r--r--drivers/char/sonypi.c2
-rw-r--r--drivers/char/tpm/Kconfig2
-rw-r--r--drivers/char/tpm/tpm-buf.c20
-rw-r--r--drivers/char/tpm/tpm-chip.c4
-rw-r--r--drivers/char/tpm/tpm-interface.c32
-rw-r--r--drivers/char/tpm/tpm2-cmd.c30
-rw-r--r--drivers/char/tpm/tpm2-sessions.c59
-rw-r--r--drivers/char/tpm/tpm_atmel.c63
-rw-r--r--drivers/char/tpm/tpm_atmel.h140
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c15
-rw-r--r--drivers/char/tpm/tpm_tis_i2c_cr50.c146
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c2
-rw-r--r--drivers/char/xillybus/xillybus_of.c2
-rw-r--r--drivers/clk/.kunitconfig1
-rw-r--r--drivers/clk/Kconfig25
-rw-r--r--drivers/clk/Makefile16
-rw-r--r--drivers/clk/clk-apple-nco.c3
-rw-r--r--drivers/clk/clk-axi-clkgen.c22
-rw-r--r--drivers/clk/clk-cdce706.c2
-rw-r--r--drivers/clk/clk-cdce925.c2
-rw-r--r--drivers/clk/clk-devres.c9
-rw-r--r--drivers/clk/clk-divider.c16
-rw-r--r--drivers/clk/clk-en7523.c309
-rw-r--r--drivers/clk/clk-eyeq.c859
-rw-r--r--drivers/clk/clk-fixed-factor.c11
-rw-r--r--drivers/clk/clk-gpio.c205
-rw-r--r--drivers/clk/clk-lan966x.c78
-rw-r--r--drivers/clk/clk-loongson2.c6
-rw-r--r--drivers/clk/clk-npcm8xx.c430
-rw-r--r--drivers/clk/clk-qoriq.c6
-rw-r--r--drivers/clk/clk-si514.c2
-rw-r--r--drivers/clk/clk-twl.c69
-rw-r--r--drivers/clk/clk.c8
-rw-r--r--drivers/clk/clk_kunit_helpers.c30
-rw-r--r--drivers/clk/clk_test.c321
-rw-r--r--drivers/clk/imx/clk-fracn-gppll.c10
-rw-r--r--drivers/clk/imx/clk-imx8-acm.c4
-rw-r--r--drivers/clk/imx/clk-imx93.c63
-rw-r--r--drivers/clk/imx/clk-imx95-blk-ctl.c20
-rw-r--r--drivers/clk/imx/clk-lpcg-scu.c41
-rw-r--r--drivers/clk/imx/clk-scu.c2
-rw-r--r--drivers/clk/kunit_clk_assigned_rates.h8
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_multiple.dtso16
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_multiple_consumer.dtso20
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_null.dtso14
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_null_consumer.dtso18
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_one.dtso14
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_one_consumer.dtso18
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_u64_multiple.dtso16
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_u64_multiple_consumer.dtso20
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_u64_one.dtso14
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_u64_one_consumer.dtso18
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_without.dtso13
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_without_consumer.dtso17
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_zero.dtso12
-rw-r--r--drivers/clk/kunit_clk_assigned_rates_zero_consumer.dtso16
-rw-r--r--drivers/clk/mediatek/Kconfig52
-rw-r--r--drivers/clk/mediatek/Makefile5
-rw-r--r--drivers/clk/mediatek/clk-mt6735-apmixedsys.c137
-rw-r--r--drivers/clk/mediatek/clk-mt6735-imgsys.c57
-rw-r--r--drivers/clk/mediatek/clk-mt6735-infracfg.c107
-rw-r--r--drivers/clk/mediatek/clk-mt6735-mfgcfg.c61
-rw-r--r--drivers/clk/mediatek/clk-mt6735-pericfg.c124
-rw-r--r--drivers/clk/mediatek/clk-mt6735-topckgen.c394
-rw-r--r--drivers/clk/mediatek/clk-mt6735-vdecsys.c79
-rw-r--r--drivers/clk/mediatek/clk-mt6735-vencsys.c53
-rw-r--r--drivers/clk/mediatek/clk-mt8188-topckgen.c9
-rw-r--r--drivers/clk/meson/Kconfig1
-rw-r--r--drivers/clk/meson/axg-audio.c109
-rw-r--r--drivers/clk/meson/axg.c6
-rw-r--r--drivers/clk/meson/c3-pll.c1
-rw-r--r--drivers/clk/meson/clk-mpll.c11
-rw-r--r--drivers/clk/meson/clk-mpll.h1
-rw-r--r--drivers/clk/meson/clk-pll.c8
-rw-r--r--drivers/clk/meson/clk-pll.h1
-rw-r--r--drivers/clk/meson/g12a.c6
-rw-r--r--drivers/clk/meson/gxbb.c6
-rw-r--r--drivers/clk/meson/meson8b.c10
-rw-r--r--drivers/clk/meson/s4-pll.c13
-rw-r--r--drivers/clk/mmp/Makefile2
-rw-r--r--drivers/clk/mmp/clk-frac.c57
-rw-r--r--drivers/clk/mmp/clk-of-mmp2.c26
-rw-r--r--drivers/clk/mmp/clk-of-pxa168.c4
-rw-r--r--drivers/clk/mmp/clk-of-pxa1928.c6
-rw-r--r--drivers/clk/mmp/clk-of-pxa910.c4
-rw-r--r--drivers/clk/mmp/clk-pxa1908-apbc.c130
-rw-r--r--drivers/clk/mmp/clk-pxa1908-apbcp.c82
-rw-r--r--drivers/clk/mmp/clk-pxa1908-apmu.c121
-rw-r--r--drivers/clk/mmp/clk-pxa1908-mpmu.c112
-rw-r--r--drivers/clk/mmp/clk.h10
-rw-r--r--drivers/clk/qcom/Kconfig88
-rw-r--r--drivers/clk/qcom/Makefile7
-rw-r--r--drivers/clk/qcom/camcc-sa8775p.c1868
-rw-r--r--drivers/clk/qcom/camcc-sm8450.c294
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c25
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h1
-rw-r--r--drivers/clk/qcom/clk-rcg.h1
-rw-r--r--drivers/clk/qcom/clk-rcg2.c48
-rw-r--r--drivers/clk/qcom/clk-rpmh.c13
-rw-r--r--drivers/clk/qcom/common.h2
-rw-r--r--drivers/clk/qcom/dispcc-sm8450.c66
-rw-r--r--drivers/clk/qcom/dispcc-sm8550.c18
-rw-r--r--drivers/clk/qcom/dispcc0-sa8775p.c1481
-rw-r--r--drivers/clk/qcom/dispcc1-sa8775p.c1481
-rw-r--r--drivers/clk/qcom/gcc-ipq5332.c382
-rw-r--r--drivers/clk/qcom/gcc-ipq5424.c3291
-rw-r--r--drivers/clk/qcom/gcc-ipq9574.c328
-rw-r--r--drivers/clk/qcom/gcc-qcs404.c1
-rw-r--r--drivers/clk/qcom/gcc-qcs8300.c3640
-rw-r--r--drivers/clk/qcom/gcc-sar2130p.c2366
-rw-r--r--drivers/clk/qcom/gcc-sm8450.c181
-rw-r--r--drivers/clk/qcom/gcc-x1e80100.c12
-rw-r--r--drivers/clk/qcom/gpucc-sar2130p.c502
-rw-r--r--drivers/clk/qcom/gpucc-sm8450.c50
-rw-r--r--drivers/clk/qcom/tcsrcc-sm8550.c18
-rw-r--r--drivers/clk/qcom/videocc-sa8775p.c576
-rw-r--r--drivers/clk/qcom/videocc-sm8350.c4
-rw-r--r--drivers/clk/qcom/videocc-sm8450.c48
-rw-r--r--drivers/clk/ralink/clk-mtmips.c56
-rw-r--r--drivers/clk/renesas/Kconfig5
-rw-r--r--drivers/clk/renesas/Makefile1
-rw-r--r--drivers/clk/renesas/clk-r8a73a4.c1
-rw-r--r--drivers/clk/renesas/clk-r8a7778.c1
-rw-r--r--drivers/clk/renesas/clk-vbattb.c205
-rw-r--r--drivers/clk/renesas/r8a779a0-cpg-mssr.c1
-rw-r--r--drivers/clk/renesas/r8a779h0-cpg-mssr.c10
-rw-r--r--drivers/clk/renesas/r9a08g045-cpg.c54
-rw-r--r--drivers/clk/renesas/r9a09g011-cpg.c1
-rw-r--r--drivers/clk/renesas/r9a09g057-cpg.c18
-rw-r--r--drivers/clk/renesas/rcar-cpg-lib.c1
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.c1
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c52
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.h10
-rw-r--r--drivers/clk/renesas/rzv2h-cpg.h5
-rw-r--r--drivers/clk/samsung/Makefile1
-rw-r--r--drivers/clk/samsung/clk-exynos-audss.c2
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c2
-rw-r--r--drivers/clk/samsung/clk-exynos4.c2
-rw-r--r--drivers/clk/samsung/clk-exynos4412-isp.c2
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c2
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c4
-rw-r--r--drivers/clk/samsung/clk-exynos5410.c2
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c6
-rw-r--r--drivers/clk/samsung/clk-exynos7.c2
-rw-r--r--drivers/clk/samsung/clk-exynos8895.c2803
-rw-r--r--drivers/clk/samsung/clk-exynosautov920.c289
-rw-r--r--drivers/clk/samsung/clk-fsd.c23
-rw-r--r--drivers/clk/samsung/clk-gs101.c10
-rw-r--r--drivers/clk/samsung/clk-pll.c2
-rw-r--r--drivers/clk/samsung/clk-pll.h2
-rw-r--r--drivers/clk/samsung/clk-s3c64xx.c2
-rw-r--r--drivers/clk/samsung/clk-s5pv210-audss.c2
-rw-r--r--drivers/clk/samsung/clk.c2
-rw-r--r--drivers/clk/sophgo/clk-sg2042-pll.c2
-rw-r--r--drivers/clk/starfive/clk-starfive-jh7110-pll.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun20i-d1.c4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun4i-a10.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a100.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-h6.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-h616.c46
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun5i.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun6i-a31.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun6i-rtc.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a23.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a33.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a83t.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-de2.c8
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-h3.c4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-r.c6
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-r40.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-v3s.c4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun9i-a80.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_common.h2
-rw-r--r--drivers/clk/sunxi-ng/ccu_reset.h2
-rw-r--r--drivers/clk/tegra/clk-bpmp.c2
-rw-r--r--drivers/clk/xilinx/clk-xlnx-clock-wizard.c281
-rw-r--r--drivers/clocksource/Kconfig12
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/arm_arch_timer.c4
-rw-r--r--drivers/clocksource/arm_global_timer.c1
-rw-r--r--drivers/clocksource/dw_apb_timer.c39
-rw-r--r--drivers/clocksource/exynos_mct.c1
-rw-r--r--drivers/clocksource/mips-gic-timer.c39
-rw-r--r--drivers/clocksource/timer-armada-370-xp.c1
-rw-r--r--drivers/clocksource/timer-gxp.c2
-rw-r--r--drivers/clocksource/timer-qcom.c1
-rw-r--r--drivers/clocksource/timer-ralink.c (renamed from arch/mips/ralink/cevt-rt3352.c)11
-rw-r--r--drivers/clocksource/timer-tegra.c1
-rw-r--r--drivers/clocksource/timer-ti-dm-systimer.c8
-rw-r--r--drivers/clocksource/timer-ti-dm.c8
-rw-r--r--drivers/comedi/comedi_fops.c12
-rw-r--r--drivers/counter/ftm-quaddec.c1
-rw-r--r--drivers/counter/intel-qep.c10
-rw-r--r--drivers/counter/stm32-timer-cnt.c17
-rw-r--r--drivers/counter/ti-ecap-capture.c7
-rw-r--r--drivers/cpufreq/Kconfig14
-rw-r--r--drivers/cpufreq/Kconfig.powerpc7
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c9
-rw-r--r--drivers/cpufreq/amd-pstate-ut.c6
-rw-r--r--drivers/cpufreq/amd-pstate.c231
-rw-r--r--drivers/cpufreq/brcmstb-avs-cpufreq.c6
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c136
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c1
-rw-r--r--drivers/cpufreq/cpufreq-dt.c2
-rw-r--r--drivers/cpufreq/cpufreq.c2
-rw-r--r--drivers/cpufreq/davinci-cpufreq.c2
-rw-r--r--drivers/cpufreq/imx-cpufreq-dt.c2
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c2
-rw-r--r--drivers/cpufreq/intel_pstate.c57
-rw-r--r--drivers/cpufreq/kirkwood-cpufreq.c2
-rw-r--r--drivers/cpufreq/loongson2_cpufreq.c4
-rw-r--r--drivers/cpufreq/loongson3_cpufreq.c9
-rw-r--r--drivers/cpufreq/maple-cpufreq.c242
-rw-r--r--drivers/cpufreq/mediatek-cpufreq-hw.c4
-rw-r--r--drivers/cpufreq/omap-cpufreq.c2
-rw-r--r--drivers/cpufreq/pcc-cpufreq.c2
-rw-r--r--drivers/cpufreq/qcom-cpufreq-hw.c2
-rw-r--r--drivers/cpufreq/qcom-cpufreq-nvmem.c84
-rw-r--r--drivers/cpufreq/qoriq-cpufreq.c2
-rw-r--r--drivers/cpufreq/raspberrypi-cpufreq.c2
-rw-r--r--drivers/cpufreq/scmi-cpufreq.c4
-rw-r--r--drivers/cpufreq/scpi-cpufreq.c2
-rw-r--r--drivers/cpufreq/sun50i-cpufreq-nvmem.c30
-rw-r--r--drivers/cpufreq/tegra186-cpufreq.c2
-rw-r--r--drivers/cpufreq/tegra194-cpufreq.c2
-rw-r--r--drivers/cpufreq/ti-cpufreq.c10
-rw-r--r--drivers/cpufreq/vexpress-spc-cpufreq.c2
-rw-r--r--drivers/cpufreq/virtual-cpufreq.c333
-rw-r--r--drivers/cpuidle/cpuidle-arm.c2
-rw-r--r--drivers/cpuidle/cpuidle-pseries.c1
-rw-r--r--drivers/cpuidle/cpuidle-qcom-spm.c2
-rw-r--r--drivers/cpuidle/cpuidle-riscv-sbi.c11
-rw-r--r--drivers/cpuidle/cpuidle.c12
-rw-r--r--drivers/cpuidle/driver.c4
-rw-r--r--drivers/cpuidle/governors/menu.c76
-rw-r--r--drivers/crypto/Kconfig21
-rw-r--r--drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c2
-rw-r--r--drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c2
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c58
-rw-r--r--drivers/crypto/amlogic/amlogic-gxl-core.c10
-rw-r--r--drivers/crypto/aspeed/aspeed-acry.c4
-rw-r--r--drivers/crypto/aspeed/aspeed-hace.c2
-rw-r--r--drivers/crypto/atmel-aes.c2
-rw-r--r--drivers/crypto/atmel-ecc.c2
-rw-r--r--drivers/crypto/atmel-sha.c2
-rw-r--r--drivers/crypto/atmel-sha204a.c4
-rw-r--r--drivers/crypto/atmel-tdes.c4
-rw-r--r--drivers/crypto/axis/artpec6_crypto.c2
-rw-r--r--drivers/crypto/bcm/cipher.c7
-rw-r--r--drivers/crypto/caam/caampkc.c11
-rw-r--r--drivers/crypto/caam/jr.c2
-rw-r--r--drivers/crypto/caam/qi.c7
-rw-r--r--drivers/crypto/cavium/cpt/cptpf_main.c6
-rw-r--r--drivers/crypto/cavium/cpt/cptvf_reqmanager.c4
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_lib.c2
-rw-r--r--drivers/crypto/ccp/sp-platform.c2
-rw-r--r--drivers/crypto/ccree/cc_aead.c4
-rw-r--r--drivers/crypto/ccree/cc_cipher.c2
-rw-r--r--drivers/crypto/ccree/cc_driver.c2
-rw-r--r--drivers/crypto/ccree/cc_hash.c2
-rw-r--r--drivers/crypto/chelsio/chcr_algo.c2
-rw-r--r--drivers/crypto/exynos-rng.c2
-rw-r--r--drivers/crypto/gemini/sl3516-ce-core.c2
-rw-r--r--drivers/crypto/hisilicon/hpre/hpre.h23
-rw-r--r--drivers/crypto/hisilicon/hpre/hpre_crypto.c2
-rw-r--r--drivers/crypto/hisilicon/hpre/hpre_main.c194
-rw-r--r--drivers/crypto/hisilicon/qm.c166
-rw-r--r--drivers/crypto/hisilicon/sec/sec_drv.c2
-rw-r--r--drivers/crypto/hisilicon/sec2/sec.h26
-rw-r--r--drivers/crypto/hisilicon/sec2/sec_crypto.c8
-rw-r--r--drivers/crypto/hisilicon/sec2/sec_main.c108
-rw-r--r--drivers/crypto/hisilicon/trng/trng.c2
-rw-r--r--drivers/crypto/hisilicon/zip/zip.h18
-rw-r--r--drivers/crypto/hisilicon/zip/zip_main.c153
-rw-r--r--drivers/crypto/img-hash.c2
-rw-r--r--drivers/crypto/inside-secure/safexcel.c2
-rw-r--r--drivers/crypto/inside-secure/safexcel_hash.c2
-rw-r--r--drivers/crypto/intel/iaa/iaa_crypto_main.c10
-rw-r--r--drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c2
-rw-r--r--drivers/crypto/intel/keembay/keembay-ocs-aes-core.c2
-rw-r--r--drivers/crypto/intel/keembay/keembay-ocs-ecc.c2
-rw-r--r--drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c2
-rw-r--r--drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c2
-rw-r--r--drivers/crypto/intel/qat/qat_420xx/adf_drv.c11
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c2
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_drv.c11
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_aer.c5
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_common_drv.h1
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_dbgfs.c13
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c10
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c18
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c4
-rw-r--r--drivers/crypto/intel/qat/qat_common/qat_hal.c2
-rw-r--r--drivers/crypto/marvell/Kconfig2
-rw-r--r--drivers/crypto/marvell/cesa/cesa.c54
-rw-r--r--drivers/crypto/marvell/cesa/cipher.c24
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c14
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c13
-rw-r--r--drivers/crypto/mxs-dcp.c22
-rw-r--r--drivers/crypto/n2_core.c4
-rw-r--r--drivers/crypto/nx/nx-common-pseries.c37
-rw-r--r--drivers/crypto/omap-aes.c2
-rw-r--r--drivers/crypto/omap-des.c2
-rw-r--r--drivers/crypto/omap-sham.c2
-rw-r--r--drivers/crypto/qce/core.c2
-rw-r--r--drivers/crypto/qcom-rng.c2
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto.c2
-rw-r--r--drivers/crypto/s5p-sss.c2
-rw-r--r--drivers/crypto/sa2ul.c4
-rw-r--r--drivers/crypto/sahara.c2
-rw-r--r--drivers/crypto/starfive/jh7110-cryp.c7
-rw-r--r--drivers/crypto/starfive/jh7110-rsa.c2
-rw-r--r--drivers/crypto/stm32/stm32-crc32.c2
-rw-r--r--drivers/crypto/stm32/stm32-cryp.c2
-rw-r--r--drivers/crypto/stm32/stm32-hash.c2
-rw-r--r--drivers/crypto/talitos.c2
-rw-r--r--drivers/crypto/tegra/tegra-se-aes.c2
-rw-r--r--drivers/crypto/tegra/tegra-se-main.c4
-rw-r--r--drivers/crypto/virtio/virtio_crypto_akcipher_algs.c65
-rw-r--r--drivers/crypto/xilinx/zynqmp-aes-gcm.c2
-rw-r--r--drivers/crypto/xilinx/zynqmp-sha.c2
-rw-r--r--drivers/cxl/core/cdat.c8
-rw-r--r--drivers/cxl/core/core.h5
-rw-r--r--drivers/cxl/core/hdm.c21
-rw-r--r--drivers/cxl/core/region.c28
-rw-r--r--drivers/cxl/core/regs.c58
-rw-r--r--drivers/cxl/cxl.h9
-rw-r--r--drivers/cxl/pci.c111
-rw-r--r--drivers/cxl/port.c2
-rw-r--r--drivers/dax/dax-private.h26
-rw-r--r--drivers/dax/pmem/Makefile7
-rw-r--r--drivers/dax/pmem/pmem.c10
-rw-r--r--drivers/dma/Kconfig28
-rw-r--r--drivers/dma/Makefile2
-rw-r--r--drivers/dma/acpi-dma.c43
-rw-r--r--drivers/dma/altera-msgdma.c2
-rw-r--r--drivers/dma/amd/qdma/qdma.c2
-rw-r--r--drivers/dma/apple-admac.c2
-rw-r--r--drivers/dma/at_hdmac.c2
-rw-r--r--drivers/dma/at_xdmac.c2
-rw-r--r--drivers/dma/bcm-sba-raid.c2
-rw-r--r--drivers/dma/bcm2835-dma.c2
-rw-r--r--drivers/dma/bestcomm/bestcomm.c2
-rw-r--r--drivers/dma/dma-jz4780.c2
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c2
-rw-r--r--drivers/dma/dw/platform.c2
-rw-r--r--drivers/dma/ep93xx_dma.c3
-rw-r--r--drivers/dma/fsl-edma-main.c2
-rw-r--r--drivers/dma/fsl-qdma.c2
-rw-r--r--drivers/dma/fsl_raid.c2
-rw-r--r--drivers/dma/fsldma.c2
-rw-r--r--drivers/dma/idma64.c2
-rw-r--r--drivers/dma/idxd/registers.h4
-rw-r--r--drivers/dma/img-mdc-dma.c2
-rw-r--r--drivers/dma/imx-dma.c2
-rw-r--r--drivers/dma/imx-sdma.c2
-rw-r--r--drivers/dma/k3dma.c2
-rw-r--r--drivers/dma/loongson2-apb-dma.c (renamed from drivers/dma/ls2x-apb-dma.c)6
-rw-r--r--drivers/dma/mcf-edma-main.c2
-rw-r--r--drivers/dma/mediatek/mtk-cqdma.c2
-rw-r--r--drivers/dma/mediatek/mtk-hsdma.c2
-rw-r--r--drivers/dma/mediatek/mtk-uart-apdma.c2
-rw-r--r--drivers/dma/milbeaut-hdmac.c2
-rw-r--r--drivers/dma/milbeaut-xdmac.c2
-rw-r--r--drivers/dma/mmp_pdma.c2
-rw-r--r--drivers/dma/mmp_tdma.c2
-rw-r--r--drivers/dma/moxart-dma.c2
-rw-r--r--drivers/dma/mpc512x_dma.c2
-rw-r--r--drivers/dma/mv_xor_v2.c4
-rw-r--r--drivers/dma/nbpfaxi.c2
-rw-r--r--drivers/dma/owl-dma.c2
-rw-r--r--drivers/dma/ppc4xx/adma.c2
-rw-r--r--drivers/dma/pxa_dma.c2
-rw-r--r--drivers/dma/qcom/bam_dma.c2
-rw-r--r--drivers/dma/qcom/hidma.c2
-rw-r--r--drivers/dma/qcom/qcom_adm.c2
-rw-r--r--drivers/dma/sa11x0-dma.c2
-rw-r--r--drivers/dma/sf-pdma/sf-pdma.c4
-rw-r--r--drivers/dma/sh/Kconfig8
-rw-r--r--drivers/dma/sh/rcar-dmac.c2
-rw-r--r--drivers/dma/sh/rz-dmac.c4
-rw-r--r--drivers/dma/sh/shdma-base.c2
-rw-r--r--drivers/dma/sh/shdmac.c2
-rw-r--r--drivers/dma/sh/usb-dmac.c4
-rw-r--r--drivers/dma/sprd-dma.c2
-rw-r--r--drivers/dma/st_fdma.c2
-rw-r--r--drivers/dma/stm32/stm32-dma3.c121
-rw-r--r--drivers/dma/sun4i-dma.c2
-rw-r--r--drivers/dma/sun6i-dma.c2
-rw-r--r--drivers/dma/tegra186-gpc-dma.c2
-rw-r--r--drivers/dma/tegra20-apb-dma.c2
-rw-r--r--drivers/dma/tegra210-adma.c2
-rw-r--r--drivers/dma/ti/cppi41.c2
-rw-r--r--drivers/dma/ti/edma.c2
-rw-r--r--drivers/dma/ti/omap-dma.c2
-rw-r--r--drivers/dma/timb_dma.c2
-rw-r--r--drivers/dma/txx9dmac.c4
-rw-r--r--drivers/dma/uniphier-mdmac.c2
-rw-r--r--drivers/dma/uniphier-xdmac.c2
-rw-r--r--drivers/dma/xgene-dma.c2
-rw-r--r--drivers/dma/xilinx/xdma.c2
-rw-r--r--drivers/dma/xilinx/xilinx_dma.c2
-rw-r--r--drivers/dma/xilinx/xilinx_dpdma.c2
-rw-r--r--drivers/dma/xilinx/zynqmp_dma.c4
-rw-r--r--drivers/dpll/dpll_netlink.c24
-rw-r--r--drivers/edac/Kconfig18
-rw-r--r--drivers/edac/Makefile2
-rw-r--r--drivers/edac/amd8111_edac.c596
-rw-r--r--drivers/edac/amd8111_edac.h118
-rw-r--r--drivers/edac/amd8131_edac.c358
-rw-r--r--drivers/edac/amd8131_edac.h107
-rw-r--r--drivers/edac/bluefield_edac.c170
-rw-r--r--drivers/edac/fsl_ddr_edac.c141
-rw-r--r--drivers/edac/fsl_ddr_edac.h13
-rw-r--r--drivers/edac/i10nm_base.c1
-rw-r--r--drivers/edac/ie31200_edac.c8
-rw-r--r--drivers/edac/igen6_edac.c49
-rw-r--r--drivers/edac/layerscape_edac.c1
-rw-r--r--drivers/edac/mce_amd.c22
-rw-r--r--drivers/edac/qcom_edac.c8
-rw-r--r--drivers/edac/skx_common.c57
-rw-r--r--drivers/edac/skx_common.h8
-rw-r--r--drivers/firewire/core-topology.c2
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/ohci.c11
-rw-r--r--drivers/firmware/arm_scmi/bus.c7
-rw-r--r--drivers/firmware/arm_scmi/common.h47
-rw-r--r--drivers/firmware/arm_scmi/driver.c54
-rw-r--r--drivers/firmware/arm_scmi/perf.c44
-rw-r--r--drivers/firmware/arm_scmi/shmem.c85
-rw-r--r--drivers/firmware/arm_scmi/transports/mailbox.c15
-rw-r--r--drivers/firmware/arm_scmi/transports/optee.c19
-rw-r--r--drivers/firmware/arm_scmi/transports/smc.c13
-rw-r--r--drivers/firmware/arm_scmi/transports/virtio.c15
-rw-r--r--drivers/firmware/arm_scpi.c5
-rw-r--r--drivers/firmware/efi/Kconfig10
-rw-r--r--drivers/firmware/efi/efi.c41
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c12
-rw-r--r--drivers/firmware/efi/libstub/efi-stub.c26
-rw-r--r--drivers/firmware/efi/libstub/efistub.h2
-rw-r--r--drivers/firmware/efi/libstub/file.c22
-rw-r--r--drivers/firmware/efi/libstub/tpm.c9
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c3
-rw-r--r--drivers/firmware/efi/memattr.c18
-rw-r--r--drivers/firmware/efi/tpm.c26
-rw-r--r--drivers/firmware/google/coreboot_table.c2
-rw-r--r--drivers/firmware/google/framebuffer-coreboot.c14
-rw-r--r--drivers/firmware/google/gsmi.c6
-rw-r--r--drivers/firmware/imx/imx-dsp.c2
-rw-r--r--drivers/firmware/memmap.c2
-rw-r--r--drivers/firmware/microchip/mpfs-auto-update.c44
-rw-r--r--drivers/firmware/mtk-adsp-ipc.c9
-rw-r--r--drivers/firmware/psci/psci.c45
-rw-r--r--drivers/firmware/qcom/qcom_scm.c47
-rw-r--r--drivers/firmware/qcom/qcom_scm.h1
-rw-r--r--drivers/firmware/qemu_fw_cfg.c2
-rw-r--r--drivers/firmware/raspberrypi.c2
-rw-r--r--drivers/firmware/smccc/smccc.c4
-rw-r--r--drivers/firmware/stratix10-rsu.c2
-rw-r--r--drivers/firmware/stratix10-svc.c2
-rw-r--r--drivers/firmware/sysfb.c19
-rw-r--r--drivers/firmware/tegra/bpmp.c14
-rw-r--r--drivers/firmware/ti_sci.c489
-rw-r--r--drivers/firmware/ti_sci.h143
-rw-r--r--drivers/firmware/turris-mox-rwtm.c23
-rw-r--r--drivers/firmware/xilinx/zynqmp-debug.c162
-rw-r--r--drivers/firmware/xilinx/zynqmp.c155
-rw-r--r--drivers/fpga/altera-fpga2sdram.c2
-rw-r--r--drivers/fpga/altera-freeze-bridge.c2
-rw-r--r--drivers/fpga/altera-hps2fpga.c2
-rw-r--r--drivers/fpga/dfl-afu-main.c8
-rw-r--r--drivers/fpga/dfl-fme-br.c8
-rw-r--r--drivers/fpga/dfl-fme-main.c8
-rw-r--r--drivers/fpga/dfl-fme-region.c8
-rw-r--r--drivers/fpga/dfl-pci.c16
-rw-r--r--drivers/fpga/intel-m10-bmc-sec-update.c2
-rw-r--r--drivers/fpga/of-fpga-region.c2
-rw-r--r--drivers/fpga/socfpga-a10.c2
-rw-r--r--drivers/fpga/stratix10-soc.c2
-rw-r--r--drivers/fpga/xilinx-pr-decoupler.c2
-rw-r--r--drivers/fpga/zynq-fpga.c2
-rw-r--r--drivers/gpio/Kconfig41
-rw-r--r--drivers/gpio/Makefile3
-rw-r--r--drivers/gpio/TODO4
-rw-r--r--drivers/gpio/gpio-74x164.c21
-rw-r--r--drivers/gpio/gpio-aggregator.c16
-rw-r--r--drivers/gpio/gpio-altera.c183
-rw-r--r--drivers/gpio/gpio-amdpt.c10
-rw-r--r--drivers/gpio/gpio-aspeed-sgpio.c2
-rw-r--r--drivers/gpio/gpio-aspeed.c620
-rw-r--r--drivers/gpio/gpio-brcmstb.c2
-rw-r--r--drivers/gpio/gpio-cadence.c2
-rw-r--r--drivers/gpio/gpio-cgbc.c196
-rw-r--r--drivers/gpio/gpio-davinci.c10
-rw-r--r--drivers/gpio/gpio-dln2.c2
-rw-r--r--drivers/gpio/gpio-dwapb.c5
-rw-r--r--drivers/gpio/gpio-eic-sprd.c4
-rw-r--r--drivers/gpio/gpio-ep93xx.c2
-rw-r--r--drivers/gpio/gpio-exar.c10
-rw-r--r--drivers/gpio/gpio-ftgpio010.c45
-rw-r--r--drivers/gpio/gpio-grgpio.c75
-rw-r--r--drivers/gpio/gpio-hlwd.c2
-rw-r--r--drivers/gpio/gpio-ljca.c17
-rw-r--r--drivers/gpio/gpio-lpc18xx.c2
-rw-r--r--drivers/gpio/gpio-max730x.c17
-rw-r--r--drivers/gpio/gpio-mb86s7x.c4
-rw-r--r--drivers/gpio/gpio-menz127.c58
-rw-r--r--drivers/gpio/gpio-merrifield.c15
-rw-r--r--drivers/gpio/gpio-mlxbf2.c2
-rw-r--r--drivers/gpio/gpio-mm-lantiq.c2
-rw-r--r--drivers/gpio/gpio-mpc5200.c4
-rw-r--r--drivers/gpio/gpio-mpc8xxx.c58
-rw-r--r--drivers/gpio/gpio-mpfs.c188
-rw-r--r--drivers/gpio/gpio-mpsse.c527
-rw-r--r--drivers/gpio/gpio-mvebu.c8
-rw-r--r--drivers/gpio/gpio-omap.c4
-rw-r--r--drivers/gpio/gpio-pca953x.c2
-rw-r--r--drivers/gpio/gpio-pci-idio-16.c17
-rw-r--r--drivers/gpio/gpio-pcie-idio-24.c19
-rw-r--r--drivers/gpio/gpio-pl061.c2
-rw-r--r--drivers/gpio/gpio-rcar.c2
-rw-r--r--drivers/gpio/gpio-rockchip.c28
-rw-r--r--drivers/gpio/gpio-sim.c7
-rw-r--r--drivers/gpio/gpio-sloppy-logic-analyzer.c2
-rw-r--r--drivers/gpio/gpio-tb10x.c2
-rw-r--r--drivers/gpio/gpio-tegra.c2
-rw-r--r--drivers/gpio/gpio-tegra186.c2
-rw-r--r--drivers/gpio/gpio-tqmx86.c2
-rw-r--r--drivers/gpio/gpio-ts4900.c6
-rw-r--r--drivers/gpio/gpio-ts5500.c2
-rw-r--r--drivers/gpio/gpio-uniphier.c2
-rw-r--r--drivers/gpio/gpio-vf610.c7
-rw-r--r--drivers/gpio/gpio-visconti.c2
-rw-r--r--drivers/gpio/gpio-xgene-sb.c39
-rw-r--r--drivers/gpio/gpio-xgs-iproc.c4
-rw-r--r--drivers/gpio/gpio-xilinx.c51
-rw-r--r--drivers/gpio/gpio-zevio.c6
-rw-r--r--drivers/gpio/gpio-zynq.c2
-rw-r--r--drivers/gpio/gpiolib-acpi.c4
-rw-r--r--drivers/gpio/gpiolib-cdev.c384
-rw-r--r--drivers/gpio/gpiolib-legacy.c3
-rw-r--r--drivers/gpio/gpiolib-of.c2
-rw-r--r--drivers/gpio/gpiolib-sysfs.c182
-rw-r--r--drivers/gpio/gpiolib.c202
-rw-r--r--drivers/gpio/gpiolib.h14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aldebaran.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c85
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c366
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c47
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c60
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c88
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c113
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c189
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c45
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c48
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h131
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v3_6.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3_cleaner_shader.asm118
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0_cleaner_shader.h56
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v11_0.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v12_0.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c32
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc21.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc24.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ta_ras_if.h9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c54
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c8
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c28
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c40
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c7
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c28
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c2
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig15
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c197
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c15
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_debug.c82
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_state.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_spl_translate.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c151
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_services.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_dchub_registers.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c32
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h13
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c60
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_status.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/link.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c33
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.c214
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c34
-rw-r--r--drivers/gpu/drm/amd/display/dmub/dmub_srv.h1
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h92
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c4
-rw-r--r--drivers/gpu/drm/amd/display/include/logger_interface.h4
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c307
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.h11
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c3
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c31
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h13
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h122
-rw-r--r--drivers/gpu/drm/amd/include/mes_v11_api_def.h43
-rw-r--r--drivers/gpu/drm/amd/include/mes_v12_api_def.h31
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c127
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c24
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c63
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c15
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c9
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c9
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c128
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c36
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c115
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c107
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c11
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h2
-rw-r--r--drivers/gpu/drm/bridge/Kconfig11
-rw-r--r--drivers/gpu/drm/bridge/Makefile1
-rw-r--r--drivers/gpu/drm/bridge/ite-it6263.c898
-rw-r--r--drivers/gpu/drm/bridge/ite-it6505.c8
-rw-r--r--drivers/gpu/drm/bridge/tc358768.c21
-rw-r--r--drivers/gpu/drm/ci/xfails/requirements.txt17
-rwxr-xr-xdrivers/gpu/drm/ci/xfails/update-xfails.py204
-rw-r--r--drivers/gpu/drm/display/drm_dp_aux_bus.c2
-rw-r--r--drivers/gpu/drm/drm_file.c2
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c2
-rw-r--r--drivers/gpu/drm/drm_of.c82
-rw-r--r--drivers/gpu/drm/drm_panel_orientation_quirks.c1
-rw-r--r--drivers/gpu/drm/drm_panic.c10
-rw-r--r--drivers/gpu/drm/drm_panic_qr.rs23
-rw-r--r--drivers/gpu/drm/drm_syncobj.c9
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_buffer.c3
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c4
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c21
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.c14
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.h5
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c64
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.c40
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.h1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_perfmon.c4
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_sched.c17
-rw-r--r--drivers/gpu/drm/etnaviv/state_hi.xml.h23
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c122
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c2
-rw-r--r--drivers/gpu/drm/exynos/regs-decon7.h15
-rw-r--r--drivers/gpu/drm/gma500/Kconfig2
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.c19
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.c9
-rw-r--r--drivers/gpu/drm/i915/display/hsw_ips.c47
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c445
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_backlight.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c46
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c65
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c673
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c213
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c466
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h7
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c97
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_de.h46
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c77
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h19
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_core.h5
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.c291
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.h206
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.c15
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.c98
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c77
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_map.c134
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.c114
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_trace.h206
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c163
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_hdcp.c97
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.c158
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.h22
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c36
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c96
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi_vbt.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c42
-rw-r--r--drivers/gpu/drm/i915/display/intel_fifo_underrun.c58
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c290
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.h15
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus_regs.h16
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c68
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c36
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug_irq.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.c89
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c330
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_display.c56
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_refclk.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_pfit.c554
-rw-r--r--drivers/gpu/drm/i915/display/intel_pfit.h15
-rw-r--r--drivers/gpu/drm/i915/display/intel_pmdemand.c71
-rw-r--r--drivers/gpu/drm/i915/display/intel_pmdemand.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_pps.c95
-rw-r--r--drivers/gpu/drm/i915/display/intel_pps.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c60
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr_regs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.c11
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.c11
-rw-r--r--drivers/gpu/drm/i915/display/intel_vga.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.h2
-rw-r--r--drivers/gpu/drm/i915/display/skl_scaler.c77
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c29
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane_regs.h1
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c20
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c1
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi_pll.c7
-rw-r--r--drivers/gpu/drm/i915/gt/gen7_renderclear.c3
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.c8
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_irq.c24
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c7
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c4
-rw-r--r--drivers/gpu/drm/i915/gt/shmem_utils.c2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c50
-rw-r--r--drivers/gpu/drm/i915/gvt/display.c4
-rw-r--r--drivers/gpu/drm/i915/gvt/display.h42
-rw-r--r--drivers/gpu/drm/i915/gvt/edid.c12
-rw-r--r--drivers/gpu/drm/i915/gvt/edid.h8
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c43
-rw-r--r--drivers/gpu/drm/i915/i915_active.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h40
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c6
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c36
-rw-r--r--drivers/gpu/drm/i915/i915_irq.h6
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c2
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h12
-rw-r--r--drivers/gpu/drm/i915/i915_request.c17
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c2
-rw-r--r--drivers/gpu/drm/i915/intel_clock_gating.c2
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c26
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.h4
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.h8
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_random.h2
-rw-r--r--drivers/gpu/drm/i915/selftests/scatterlist.c2
-rw-r--r--drivers/gpu/drm/imagination/pvr_context.c33
-rw-r--r--drivers/gpu/drm/imagination/pvr_context.h21
-rw-r--r--drivers/gpu/drm/imagination/pvr_device.h10
-rw-r--r--drivers/gpu/drm/imagination/pvr_drv.c3
-rw-r--r--drivers/gpu/drm/imagination/pvr_vm.c22
-rw-r--r--drivers/gpu/drm/imagination/pvr_vm.h1
-rw-r--r--drivers/gpu/drm/lib/drm_random.h2
-rw-r--r--drivers/gpu/drm/mediatek/Kconfig2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_drv.h1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c43
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c21
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c256
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.h2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c14
-rw-r--r--drivers/gpu/drm/msm/Makefile2
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_power.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_catalog.c61
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h1
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c246
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h170
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.c67
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_preempt.c456
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c13
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h27
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h210
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h187
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h218
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h338
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h12
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h485
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h46
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c25
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h27
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c45
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h38
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c179
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h107
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h90
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c37
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c250
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h33
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c121
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h17
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c52
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c12
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h11
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c37
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h34
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c293
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h31
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c46
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h50
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h18
-rw-r--r--drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c19
-rw-r--r--drivers/gpu/drm/msm/dp/dp_audio.c294
-rw-r--r--drivers/gpu/drm/msm/dp/dp_audio.h38
-rw-r--r--drivers/gpu/drm/msm/dp/dp_aux.c148
-rw-r--r--drivers/gpu/drm/msm/dp/dp_aux.h18
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.c734
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.h118
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c482
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.h40
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c68
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.h10
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c909
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.h18
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.c142
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.h22
-rw-r--r--drivers/gpu/drm/msm/dp/dp_link.c432
-rw-r--r--drivers/gpu/drm/msm/dp/dp_link.h44
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.c254
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.h42
-rw-r--r--drivers/gpu/drm/msm/dp/dp_utils.c20
-rw-r--r--drivers/gpu/drm/msm/dp/dp_utils.h8
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c7
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c4
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h18
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h11
-rw-r--r--drivers/gpu/drm/msm/msm_gpu_devfreq.c9
-rw-r--r--drivers/gpu/drm/msm/msm_gpu_trace.h28
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h6
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c46
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.c2
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.h18
-rw-r--r--drivers/gpu/drm/msm/msm_submitqueue.c7
-rw-r--r--drivers/gpu/drm/msm/registers/adreno/a6xx.xml7
-rw-r--r--drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml39
-rw-r--r--drivers/gpu/drm/msm/registers/display/mdp5.xml16
-rw-r--r--drivers/gpu/drm/msm/registers/display/mdss.xml29
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/tile.h63
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c129
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c59
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c59
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/fw.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c6
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c3
-rw-r--r--drivers/gpu/drm/omapdrm/dss/sdi.c3
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.c3
-rw-r--r--drivers/gpu/drm/panthor/panthor_devfreq.c17
-rw-r--r--drivers/gpu/drm/panthor/panthor_device.c4
-rw-r--r--drivers/gpu/drm/panthor/panthor_mmu.c4
-rw-r--r--drivers/gpu/drm/qxl/Kconfig2
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c3
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c8
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c23
-rw-r--r--drivers/gpu/drm/tegra/gr3d.c39
-rw-r--r--drivers/gpu/drm/tiny/bochs.c19
-rw-r--r--drivers/gpu/drm/tiny/cirrus.c2
-rw-r--r--drivers/gpu/drm/vkms/vkms_composer.c4
-rw-r--r--drivers/gpu/drm/vkms/vkms_crtc.c2
-rw-r--r--drivers/gpu/drm/vkms/vkms_output.c5
-rw-r--r--drivers/gpu/drm/vkms/vkms_writeback.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_object.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c2
-rw-r--r--drivers/gpu/drm/xe/Kconfig2
-rw-r--r--drivers/gpu/drm/xe/Makefile1
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h3
-rw-r--r--drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h8
-rw-r--r--drivers/gpu/drm/xe/display/ext/i915_irq.c8
-rw-r--r--drivers/gpu/drm/xe/display/xe_display.c4
-rw-r--r--drivers/gpu/drm/xe/display/xe_hdcp_gsc.c2
-rw-r--r--drivers/gpu/drm/xe/tests/xe_bo.c2
-rw-r--r--drivers/gpu/drm/xe/xe_pci.c53
-rw-r--r--drivers/greybus/interface.c2
-rw-r--r--drivers/hid/Kconfig13
-rw-r--r--drivers/hid/Makefile3
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.c9
-rw-r--r--drivers/hid/bpf/progs/Huion__Dial-2.bpf.c66
-rw-r--r--drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c60
-rw-r--r--drivers/hid/bpf/progs/Mistel__MD770.bpf.c154
-rw-r--r--drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c148
-rw-r--r--drivers/hid/bpf/progs/hid_report_helpers.h36
-rw-r--r--drivers/hid/hid-asus.c2
-rw-r--r--drivers/hid/hid-core.c173
-rw-r--r--drivers/hid/hid-corsair-void.c829
-rw-r--r--drivers/hid/hid-cp2112.c3
-rw-r--r--drivers/hid/hid-debug.c9
-rw-r--r--drivers/hid/hid-generic.c3
-rw-r--r--drivers/hid/hid-goodix-spi.c35
-rw-r--r--drivers/hid/hid-hyperv.c58
-rw-r--r--drivers/hid/hid-ids.h5
-rw-r--r--drivers/hid/hid-kysona.c248
-rw-r--r--drivers/hid/hid-lg4ff.c3
-rw-r--r--drivers/hid/hid-logitech-hidpp.c74
-rw-r--r--drivers/hid/hid-magicmouse.c56
-rw-r--r--drivers/hid/hid-multitouch.c30
-rw-r--r--drivers/hid/hid-picolcd_fb.c6
-rw-r--r--drivers/hid/hid-picolcd_lcd.c6
-rw-r--r--drivers/hid/hid-sensor-custom.c2
-rw-r--r--drivers/hid/hid-sony.c3
-rw-r--r--drivers/hid/hid-steam.c2
-rw-r--r--drivers/hid/hid-steelseries.c19
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of.c6
-rw-r--r--drivers/hid/intel-ish-hid/ipc/pci-ish.c45
-rw-r--r--drivers/hid/intel-ish-hid/ishtp-fw-loader.c2
-rw-r--r--drivers/hid/intel-ish-hid/ishtp-hid-client.c25
-rw-r--r--drivers/hid/intel-ish-hid/ishtp-hid.h11
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/client.c2
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h12
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/loader.c35
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/loader.h34
-rw-r--r--drivers/hid/usbhid/hid-core.c2
-rw-r--r--drivers/hid/wacom_wac.c11
-rw-r--r--drivers/hid/wacom_wac.h2
-rw-r--r--drivers/hwmon/Kconfig34
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/abituguru.c2
-rw-r--r--drivers/hwmon/abituguru3.c4
-rw-r--r--drivers/hwmon/acpi_power_meter.c3
-rw-r--r--drivers/hwmon/amc6821.c14
-rw-r--r--drivers/hwmon/aquacomputer_d5next.c2
-rw-r--r--drivers/hwmon/aspeed-g6-pwm-tach.c2
-rw-r--r--drivers/hwmon/cros_ec_hwmon.c1
-rw-r--r--drivers/hwmon/da9052-hwmon.c2
-rw-r--r--drivers/hwmon/dme1737.c2
-rw-r--r--drivers/hwmon/f71805f.c2
-rw-r--r--drivers/hwmon/f71882fg.c2
-rw-r--r--drivers/hwmon/gsc-hwmon.c9
-rw-r--r--drivers/hwmon/hwmon.c19
-rw-r--r--drivers/hwmon/i5500_temp.c8
-rw-r--r--drivers/hwmon/i5k_amb.c2
-rw-r--r--drivers/hwmon/ina2xx.c152
-rw-r--r--drivers/hwmon/intel-m10-bmc-hwmon.c9
-rw-r--r--drivers/hwmon/isl28022.c535
-rw-r--r--drivers/hwmon/jc42.c6
-rw-r--r--drivers/hwmon/max197.c2
-rw-r--r--drivers/hwmon/max6639.c83
-rw-r--r--drivers/hwmon/mc13783-adc.c2
-rw-r--r--drivers/hwmon/nct6775-core.c7
-rw-r--r--drivers/hwmon/nct6775-platform.c2
-rw-r--r--drivers/hwmon/nct7363.c447
-rw-r--r--drivers/hwmon/nzxt-kraken2.c9
-rw-r--r--drivers/hwmon/occ/p9_sbe.c4
-rw-r--r--drivers/hwmon/pc87360.c2
-rw-r--r--drivers/hwmon/pc87427.c2
-rw-r--r--drivers/hwmon/pmbus/Kconfig6
-rw-r--r--drivers/hwmon/pmbus/isl68137.c210
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c20
-rw-r--r--drivers/hwmon/pmbus/mp2891.c4
-rw-r--r--drivers/hwmon/pmbus/mp2993.c4
-rw-r--r--drivers/hwmon/pmbus/mp9941.c4
-rw-r--r--drivers/hwmon/pmbus/mpq8785.c2
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c16
-rw-r--r--drivers/hwmon/powerz.c8
-rw-r--r--drivers/hwmon/pwm-fan.c33
-rw-r--r--drivers/hwmon/raspberrypi-hwmon.c8
-rw-r--r--drivers/hwmon/sch5636.c2
-rw-r--r--drivers/hwmon/sg2042-mcu.c4
-rw-r--r--drivers/hwmon/sht15.c2
-rw-r--r--drivers/hwmon/sht4x.c184
-rw-r--r--drivers/hwmon/sis5595.c2
-rw-r--r--drivers/hwmon/sl28cpld-hwmon.c9
-rw-r--r--drivers/hwmon/smsc47m1.c2
-rw-r--r--drivers/hwmon/spd5118.c2
-rw-r--r--drivers/hwmon/surface_fan.c10
-rw-r--r--drivers/hwmon/tmp108.c70
-rw-r--r--drivers/hwmon/tps23861.c2
-rw-r--r--drivers/hwmon/ultra45_env.c2
-rw-r--r--drivers/hwmon/via-cputemp.c2
-rw-r--r--drivers/hwmon/via686a.c2
-rw-r--r--drivers/hwmon/vt1211.c2
-rw-r--r--drivers/hwmon/vt8231.c4
-rw-r--r--drivers/hwmon/w83627hf.c2
-rw-r--r--drivers/hwmon/w83781d.c2
-rw-r--r--drivers/hwmon/xgene-hwmon.c2
-rw-r--r--drivers/hwtracing/intel_th/pci.c9
-rw-r--r--drivers/i2c/Makefile7
-rw-r--r--drivers/i2c/busses/Kconfig75
-rw-r--r--drivers/i2c/busses/Makefile17
-rw-r--r--drivers/i2c/busses/i2c-altera.c2
-rw-r--r--drivers/i2c/busses/i2c-amd-asf-plat.c369
-rw-r--r--drivers/i2c/busses/i2c-amd-mp2-plat.c2
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c245
-rw-r--r--drivers/i2c/busses/i2c-amd756.c4
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c2
-rw-r--r--drivers/i2c/busses/i2c-at91-core.c2
-rw-r--r--drivers/i2c/busses/i2c-au1550.c2
-rw-r--r--drivers/i2c/busses/i2c-axxia.c2
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c2
-rw-r--r--drivers/i2c/busses/i2c-bcm-kona.c2
-rw-r--r--drivers/i2c/busses/i2c-bcm2835.c2
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c2
-rw-r--r--drivers/i2c/busses/i2c-cadence.c425
-rw-r--r--drivers/i2c/busses/i2c-cbus-gpio.c2
-rw-r--r--drivers/i2c/busses/i2c-cgbc.c406
-rw-r--r--drivers/i2c/busses/i2c-cht-wc.c2
-rw-r--r--drivers/i2c/busses/i2c-cpm.c2
-rw-r--r--drivers/i2c/busses/i2c-cros-ec-tunnel.c2
-rw-r--r--drivers/i2c/busses/i2c-davinci.c2
-rw-r--r--drivers/i2c/busses/i2c-designware-amdpsp.c10
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c79
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h19
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c40
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c39
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c56
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c6
-rw-r--r--drivers/i2c/busses/i2c-digicolor.c2
-rw-r--r--drivers/i2c/busses/i2c-dln2.c2
-rw-r--r--drivers/i2c/busses/i2c-emev2.c2
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c2
-rw-r--r--drivers/i2c/busses/i2c-gpio.c2
-rw-r--r--drivers/i2c/busses/i2c-gxp.c2
-rw-r--r--drivers/i2c/busses/i2c-highlander.c2
-rw-r--r--drivers/i2c/busses/i2c-hix5hd2.c2
-rw-r--r--drivers/i2c/busses/i2c-i801.c6
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c2
-rw-r--r--drivers/i2c/busses/i2c-img-scb.c2
-rw-r--r--drivers/i2c/busses/i2c-imx-lpi2c.c2
-rw-r--r--drivers/i2c/busses/i2c-imx.c409
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-isch.c317
-rw-r--r--drivers/i2c/busses/i2c-jz4780.c2
-rw-r--r--drivers/i2c/busses/i2c-kempld.c2
-rw-r--r--drivers/i2c/busses/i2c-lpc2k.c2
-rw-r--r--drivers/i2c/busses/i2c-meson.c2
-rw-r--r--drivers/i2c/busses/i2c-microchip-corei2c.c2
-rw-r--r--drivers/i2c/busses/i2c-mlxbf.c2
-rw-r--r--drivers/i2c/busses/i2c-mlxcpld.c2
-rw-r--r--drivers/i2c/busses/i2c-mpc.c2
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c2
-rw-r--r--drivers/i2c/busses/i2c-mt7621.c2
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-mxs.c2
-rw-r--r--drivers/i2c/busses/i2c-nforce2-s4985.c240
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c16
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c87
-rw-r--r--drivers/i2c/busses/i2c-npcm7xx.c24
-rw-r--r--drivers/i2c/busses/i2c-ocores.c2
-rw-r--r--drivers/i2c/busses/i2c-octeon-platdrv.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/i2c/busses/i2c-opal.c2
-rw-r--r--drivers/i2c/busses/i2c-pasemi-platform.c2
-rw-r--r--drivers/i2c/busses/i2c-pca-platform.c2
-rw-r--r--drivers/i2c/busses/i2c-piix4.c51
-rw-r--r--drivers/i2c/busses/i2c-piix4.h44
-rw-r--r--drivers/i2c/busses/i2c-pnx.c2
-rw-r--r--drivers/i2c/busses/i2c-powermac.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/busses/i2c-qcom-cci.c23
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c27
-rw-r--r--drivers/i2c/busses/i2c-qup.c6
-rw-r--r--drivers/i2c/busses/i2c-rcar.c2
-rw-r--r--drivers/i2c/busses/i2c-riic.c2
-rw-r--r--drivers/i2c/busses/i2c-rk3x.c2
-rw-r--r--drivers/i2c/busses/i2c-rtl9300.c423
-rw-r--r--drivers/i2c/busses/i2c-rzv2m.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c2
-rw-r--r--drivers/i2c/busses/i2c-scmi.c2
-rw-r--r--drivers/i2c/busses/i2c-sh7760.c2
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c2
-rw-r--r--drivers/i2c/busses/i2c-simtec.c2
-rw-r--r--drivers/i2c/busses/i2c-sprd.c2
-rw-r--r--drivers/i2c/busses/i2c-st.c2
-rw-r--r--drivers/i2c/busses/i2c-stm32f4.c2
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c2
-rw-r--r--drivers/i2c/busses/i2c-sun6i-p2wi.c2
-rw-r--r--drivers/i2c/busses/i2c-synquacer.c2
-rw-r--r--drivers/i2c/busses/i2c-tegra-bpmp.c2
-rw-r--r--drivers/i2c/busses/i2c-tegra.c2
-rw-r--r--drivers/i2c/busses/i2c-uniphier-f.c2
-rw-r--r--drivers/i2c/busses/i2c-uniphier.c2
-rw-r--r--drivers/i2c/busses/i2c-versatile.c2
-rw-r--r--drivers/i2c/busses/i2c-viai2c-wmt.c2
-rw-r--r--drivers/i2c/busses/i2c-viperboard.c2
-rw-r--r--drivers/i2c/busses/i2c-xgene-slimpro.c2
-rw-r--r--drivers/i2c/busses/i2c-xiic.c2
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c2
-rw-r--r--drivers/i2c/busses/scx200_acb.c2
-rw-r--r--drivers/i2c/i2c-core-of-prober.c415
-rw-r--r--drivers/i2c/i2c-core-smbus.c11
-rw-r--r--drivers/i2c/i2c-dev.c17
-rw-r--r--drivers/i2c/i2c-slave-testunit.c7
-rw-r--r--drivers/i2c/i2c-smbus.c22
-rw-r--r--drivers/i2c/muxes/i2c-arb-gpio-challenge.c2
-rw-r--r--drivers/i2c/muxes/i2c-demux-pinctrl.c2
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c2
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpmux.c2
-rw-r--r--drivers/i2c/muxes/i2c-mux-mlxcpld.c2
-rw-r--r--drivers/i2c/muxes/i2c-mux-mule.c4
-rw-r--r--drivers/i2c/muxes/i2c-mux-pinctrl.c2
-rw-r--r--drivers/i2c/muxes/i2c-mux-reg.c2
-rw-r--r--drivers/i3c/master.c100
-rw-r--r--drivers/i3c/master/dw-i3c-master.c34
-rw-r--r--drivers/i3c/master/dw-i3c-master.h1
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/core.c19
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/dma.c10
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/hci.h2
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/pio.c2
-rw-r--r--drivers/i3c/master/svc-i3c-master.c136
-rw-r--r--drivers/idle/intel_idle.c48
-rw-r--r--drivers/iio/accel/adxl355_core.c2
-rw-r--r--drivers/iio/accel/adxl367.c2
-rw-r--r--drivers/iio/accel/adxl372.c2
-rw-r--r--drivers/iio/accel/adxl380.c11
-rw-r--r--drivers/iio/accel/bma180.c3
-rw-r--r--drivers/iio/accel/bma220_spi.c1
-rw-r--r--drivers/iio/accel/bma400_core.c4
-rw-r--r--drivers/iio/accel/bmc150-accel-core.c2
-rw-r--r--drivers/iio/accel/bmc150-accel.h3
-rw-r--r--drivers/iio/accel/fxls8962af-core.c8
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c9
-rw-r--r--drivers/iio/accel/kionix-kx022a.c5
-rw-r--r--drivers/iio/accel/kxcjk-1013.c442
-rw-r--r--drivers/iio/accel/kxsd9.c3
-rw-r--r--drivers/iio/accel/mma7455_core.c3
-rw-r--r--drivers/iio/accel/mma8452.c5
-rw-r--r--drivers/iio/accel/mma9551.c27
-rw-r--r--drivers/iio/accel/mma9553.c46
-rw-r--r--drivers/iio/accel/msa311.c3
-rw-r--r--drivers/iio/accel/mxc4005.c3
-rw-r--r--drivers/iio/accel/sca3000.c6
-rw-r--r--drivers/iio/accel/stk8312.c3
-rw-r--r--drivers/iio/accel/stk8ba50.c3
-rw-r--r--drivers/iio/adc/Kconfig43
-rw-r--r--drivers/iio/adc/Makefile3
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c2
-rw-r--r--drivers/iio/adc/ad4000.c6
-rw-r--r--drivers/iio/adc/ad7091r-base.c3
-rw-r--r--drivers/iio/adc/ad7091r-base.h2
-rw-r--r--drivers/iio/adc/ad7173.c38
-rw-r--r--drivers/iio/adc/ad7192.c3
-rw-r--r--drivers/iio/adc/ad7266.c2
-rw-r--r--drivers/iio/adc/ad7280a.c14
-rw-r--r--drivers/iio/adc/ad7291.c2
-rw-r--r--drivers/iio/adc/ad7380.c178
-rw-r--r--drivers/iio/adc/ad7606.c1056
-rw-r--r--drivers/iio/adc/ad7606.h134
-rw-r--r--drivers/iio/adc/ad7606_par.c133
-rw-r--r--drivers/iio/adc/ad7606_spi.c195
-rw-r--r--drivers/iio/adc/ad7625.c684
-rw-r--r--drivers/iio/adc/ad7779.c914
-rw-r--r--drivers/iio/adc/ad7780.c2
-rw-r--r--drivers/iio/adc/ad7791.c4
-rw-r--r--drivers/iio/adc/ad7793.c2
-rw-r--r--drivers/iio/adc/ad7887.c4
-rw-r--r--drivers/iio/adc/ad7923.c4
-rw-r--r--drivers/iio/adc/ad7944.c4
-rw-r--r--drivers/iio/adc/ad799x.c2
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c4
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c2
-rw-r--r--drivers/iio/adc/at91_adc.c2
-rw-r--r--drivers/iio/adc/axp20x_adc.c62
-rw-r--r--drivers/iio/adc/axp288_adc.c2
-rw-r--r--drivers/iio/adc/bcm_iproc_adc.c8
-rw-r--r--drivers/iio/adc/da9150-gpadc.c26
-rw-r--r--drivers/iio/adc/dln2-adc.c2
-rw-r--r--drivers/iio/adc/ep93xx_adc.c2
-rw-r--r--drivers/iio/adc/exynos_adc.c2
-rw-r--r--drivers/iio/adc/gehc-pmc-adc.c228
-rw-r--r--drivers/iio/adc/hi8435.c2
-rw-r--r--drivers/iio/adc/imx8qxp-adc.c2
-rw-r--r--drivers/iio/adc/imx93_adc.c2
-rw-r--r--drivers/iio/adc/intel_mrfld_adc.c2
-rw-r--r--drivers/iio/adc/lp8788_adc.c18
-rw-r--r--drivers/iio/adc/ltc2497-core.c15
-rw-r--r--drivers/iio/adc/max1363.c5
-rw-r--r--drivers/iio/adc/max34408.c2
-rw-r--r--drivers/iio/adc/meson_saradc.c2
-rw-r--r--drivers/iio/adc/mp2629_adc.c4
-rw-r--r--drivers/iio/adc/mt6360-adc.c2
-rw-r--r--drivers/iio/adc/mxs-lradc-adc.c6
-rw-r--r--drivers/iio/adc/npcm_adc.c2
-rw-r--r--drivers/iio/adc/pac1921.c48
-rw-r--r--drivers/iio/adc/pac1934.c2
-rw-r--r--drivers/iio/adc/palmas_gpadc.c4
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c10
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c4
-rw-r--r--drivers/iio/adc/qcom-spmi-vadc.c7
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c2
-rw-r--r--drivers/iio/adc/rn5t618-adc.c2
-rw-r--r--drivers/iio/adc/stm32-adc-core.c2
-rw-r--r--drivers/iio/adc/stm32-adc.c2
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c2
-rw-r--r--drivers/iio/adc/stm32-dfsdm-core.c2
-rw-r--r--drivers/iio/adc/sun20i-gpadc-iio.c7
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c9
-rw-r--r--drivers/iio/adc/ti-ads1015.c5
-rw-r--r--drivers/iio/adc/ti-ads1119.c2
-rw-r--r--drivers/iio/adc/ti-ads1298.c2
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c10
-rw-r--r--drivers/iio/adc/twl4030-madc.c4
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c2
-rw-r--r--drivers/iio/adc/vf610_adc.c2
-rw-r--r--drivers/iio/adc/xilinx-ams.c2
-rw-r--r--drivers/iio/adc/xilinx-xadc-events.c4
-rw-r--r--drivers/iio/adc/xilinx-xadc.h2
-rw-r--r--drivers/iio/addac/ad74115.c18
-rw-r--r--drivers/iio/addac/ad74413r.c102
-rw-r--r--drivers/iio/cdc/ad7150.c2
-rw-r--r--drivers/iio/chemical/Kconfig2
-rw-r--r--drivers/iio/chemical/bme680.h11
-rw-r--r--drivers/iio/chemical/bme680_core.c366
-rw-r--r--drivers/iio/common/inv_sensors/inv_sensors_timestamp.c4
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c2
-rw-r--r--drivers/iio/dac/Kconfig32
-rw-r--r--drivers/iio/dac/Makefile3
-rw-r--r--drivers/iio/dac/ad3552r-common.c249
-rw-r--r--drivers/iio/dac/ad3552r-hs.c529
-rw-r--r--drivers/iio/dac/ad3552r-hs.h19
-rw-r--r--drivers/iio/dac/ad3552r.c557
-rw-r--r--drivers/iio/dac/ad3552r.h228
-rw-r--r--drivers/iio/dac/ad5380.c85
-rw-r--r--drivers/iio/dac/ad5421.c2
-rw-r--r--drivers/iio/dac/ad5446.c77
-rw-r--r--drivers/iio/dac/ad5504.c61
-rw-r--r--drivers/iio/dac/ad5624r.h1
-rw-r--r--drivers/iio/dac/ad5624r_spi.c71
-rw-r--r--drivers/iio/dac/ad5755.c11
-rw-r--r--drivers/iio/dac/ad5761.c109
-rw-r--r--drivers/iio/dac/ad5770r.c44
-rw-r--r--drivers/iio/dac/ad5791.c205
-rw-r--r--drivers/iio/dac/ad8460.c951
-rw-r--r--drivers/iio/dac/adi-axi-dac.c449
-rw-r--r--drivers/iio/dac/dpot-dac.c2
-rw-r--r--drivers/iio/dac/lpc18xx_dac.c6
-rw-r--r--drivers/iio/dac/m62332.c2
-rw-r--r--drivers/iio/dac/max517.c2
-rw-r--r--drivers/iio/dac/stm32-dac-core.c2
-rw-r--r--drivers/iio/dac/stm32-dac.c2
-rw-r--r--drivers/iio/dac/vf610_dac.c2
-rw-r--r--drivers/iio/dummy/iio_simple_dummy.h2
-rw-r--r--drivers/iio/dummy/iio_simple_dummy_events.c32
-rw-r--r--drivers/iio/frequency/ad9523.c2
-rw-r--r--drivers/iio/frequency/adf4350.c2
-rw-r--r--drivers/iio/frequency/adf4371.c63
-rw-r--r--drivers/iio/gyro/Kconfig2
-rw-r--r--drivers/iio/gyro/bmg160_core.c19
-rw-r--r--drivers/iio/gyro/bmg160_i2c.c6
-rw-r--r--drivers/iio/gyro/fxas21002c_core.c3
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c8
-rw-r--r--drivers/iio/gyro/mpu3050-core.c2
-rw-r--r--drivers/iio/humidity/hid-sensor-humidity.c4
-rw-r--r--drivers/iio/humidity/hts221_buffer.c3
-rw-r--r--drivers/iio/imu/Kconfig15
-rw-r--r--drivers/iio/imu/Makefile3
-rw-r--r--drivers/iio/imu/bmi160/bmi160_core.c11
-rw-r--r--drivers/iio/imu/bmi270/Kconfig33
-rw-r--r--drivers/iio/imu/bmi270/Makefile7
-rw-r--r--drivers/iio/imu/bmi270/bmi270.h38
-rw-r--r--drivers/iio/imu/bmi270/bmi270_core.c734
-rw-r--r--drivers/iio/imu/bmi270/bmi270_i2c.c66
-rw-r--r--drivers/iio/imu/bmi270/bmi270_spi.c92
-rw-r--r--drivers/iio/imu/bmi323/bmi323.h1
-rw-r--r--drivers/iio/imu/bmi323/bmi323_core.c18
-rw-r--r--drivers/iio/imu/fxos8700_core.c1
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c2
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_core.c10
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c3
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c17
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c17
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c11
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c38
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c10
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h4
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c10
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c1
-rw-r--r--drivers/iio/imu/kmx61.c27
-rw-r--r--drivers/iio/imu/smi240.c621
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c22
-rw-r--r--drivers/iio/industrialio-acpi.c48
-rw-r--r--drivers/iio/industrialio-backend.c82
-rw-r--r--drivers/iio/industrialio-core.c3
-rw-r--r--drivers/iio/industrialio-gts-helper.c4
-rw-r--r--drivers/iio/inkern.c9
-rw-r--r--drivers/iio/light/Kconfig18
-rw-r--r--drivers/iio/light/Makefile1
-rw-r--r--drivers/iio/light/adux1020.c12
-rw-r--r--drivers/iio/light/al3010.c11
-rw-r--r--drivers/iio/light/apds9300.c20
-rw-r--r--drivers/iio/light/apds9306.c7
-rw-r--r--drivers/iio/light/apds9960.c10
-rw-r--r--drivers/iio/light/bh1745.c50
-rw-r--r--drivers/iio/light/cm32181.c3
-rw-r--r--drivers/iio/light/cm3605.c2
-rw-r--r--drivers/iio/light/cm36651.c2
-rw-r--r--drivers/iio/light/gp2ap002.c2
-rw-r--r--drivers/iio/light/gp2ap020a00f.c2
-rw-r--r--drivers/iio/light/hid-sensor-als.c8
-rw-r--r--drivers/iio/light/hid-sensor-prox.c201
-rw-r--r--drivers/iio/light/iqs621-als.c2
-rw-r--r--drivers/iio/light/isl29018.c38
-rw-r--r--drivers/iio/light/lm3533-als.c8
-rw-r--r--drivers/iio/light/ltr390.c362
-rw-r--r--drivers/iio/light/ltr501.c35
-rw-r--r--drivers/iio/light/ltrf216a.c1
-rw-r--r--drivers/iio/light/max44009.c2
-rw-r--r--drivers/iio/light/opt3001.c191
-rw-r--r--drivers/iio/light/rpr0521.c14
-rw-r--r--drivers/iio/light/st_uvis25_core.c3
-rw-r--r--drivers/iio/light/stk3310.c5
-rw-r--r--drivers/iio/light/tcs3472.c2
-rw-r--r--drivers/iio/light/tsl2563.c2
-rw-r--r--drivers/iio/light/tsl2591.c2
-rw-r--r--drivers/iio/light/tsl2772.c6
-rw-r--r--drivers/iio/light/us5182d.c2
-rw-r--r--drivers/iio/light/vcnl4000.c5
-rw-r--r--drivers/iio/light/veml3235.c495
-rw-r--r--drivers/iio/light/veml6030.c537
-rw-r--r--drivers/iio/light/veml6070.c201
-rw-r--r--drivers/iio/light/vl6180.c255
-rw-r--r--drivers/iio/magnetometer/Kconfig13
-rw-r--r--drivers/iio/magnetometer/Makefile1
-rw-r--r--drivers/iio/magnetometer/af8133j.c3
-rw-r--r--drivers/iio/magnetometer/ak8974.c2
-rw-r--r--drivers/iio/magnetometer/als31300.c494
-rw-r--r--drivers/iio/magnetometer/bmc150_magn.c15
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_i2c.c9
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_spi.c9
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c6
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c8
-rw-r--r--drivers/iio/orientation/hid-sensor-rotation.c8
-rw-r--r--drivers/iio/position/hid-sensor-custom-intel-hinge.c8
-rw-r--r--drivers/iio/position/iqs624-pos.c2
-rw-r--r--drivers/iio/pressure/bmp280-core.c713
-rw-r--r--drivers/iio/pressure/bmp280-i2c.c4
-rw-r--r--drivers/iio/pressure/bmp280-spi.c4
-rw-r--r--drivers/iio/pressure/bmp280.h56
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c8
-rw-r--r--drivers/iio/pressure/rohm-bm1390.c3
-rw-r--r--drivers/iio/proximity/aw96103.c2
-rw-r--r--drivers/iio/proximity/cros_ec_mkbp_proximity.c4
-rw-r--r--drivers/iio/proximity/hx9023s.c4
-rw-r--r--drivers/iio/proximity/irsd200.c5
-rw-r--r--drivers/iio/proximity/srf04.c2
-rw-r--r--drivers/iio/proximity/sx9324.c20
-rw-r--r--drivers/iio/proximity/sx9360.c1
-rw-r--r--drivers/iio/proximity/sx9500.c6
-rw-r--r--drivers/iio/proximity/sx_common.c23
-rw-r--r--drivers/iio/proximity/sx_common.h6
-rw-r--r--drivers/iio/proximity/vcnl3020.c2
-rw-r--r--drivers/iio/proximity/vl53l0x-i2c.c174
-rw-r--r--drivers/iio/temperature/Kconfig2
-rw-r--r--drivers/iio/temperature/hid-sensor-temperature.c4
-rw-r--r--drivers/iio/temperature/mcp9600.c2
-rw-r--r--drivers/iio/temperature/tmp006.c134
-rw-r--r--drivers/iio/temperature/tmp007.c2
-rw-r--r--drivers/iio/trigger/iio-trig-interrupt.c2
-rw-r--r--drivers/iio/trigger/stm32-timer-trigger.c2
-rw-r--r--drivers/infiniband/core/addr.c2
-rw-r--r--drivers/infiniband/core/cm.c170
-rw-r--r--drivers/infiniband/core/device.c39
-rw-r--r--drivers/infiniband/core/nldev.c40
-rw-r--r--drivers/infiniband/core/rdma_core.c12
-rw-r--r--drivers/infiniband/core/roce_gid_mgmt.c30
-rw-r--r--drivers/infiniband/core/ucma.c19
-rw-r--r--drivers/infiniband/core/uverbs.h29
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c8
-rw-r--r--drivers/infiniband/core/uverbs_main.c43
-rw-r--r--drivers/infiniband/hw/bnxt_re/Makefile3
-rw-r--r--drivers/infiniband/hw/bnxt_re/bnxt_re.h47
-rw-r--r--drivers/infiniband/hw/bnxt_re/debugfs.c138
-rw-r--r--drivers/infiniband/hw/bnxt_re/debugfs.h21
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c130
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.h4
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c480
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.c73
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.h23
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c19
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.h2
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.h13
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.c35
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.h2
-rw-r--r--drivers/infiniband/hw/bnxt_re/roce_hsi.h57
-rw-r--r--drivers/infiniband/hw/efa/efa_admin_cmds_defs.h63
-rw-r--r--drivers/infiniband/hw/efa/efa_admin_defs.h4
-rw-r--r--drivers/infiniband/hw/efa/efa_com_cmd.c6
-rw-r--r--drivers/infiniband/hw/efa/efa_com_cmd.h4
-rw-r--r--drivers/infiniband/hw/efa/efa_io_defs.h106
-rw-r--r--drivers/infiniband/hw/efa/efa_verbs.c51
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c2
-rw-r--r--drivers/infiniband/hw/hfi1/chip.h1
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_cq.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_debugfs.c3
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_device.h14
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hem.c48
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c257
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.h8
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_main.c7
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_mr.c11
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_qp.c77
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_srq.c4
-rw-r--r--drivers/infiniband/hw/mlx5/devx.c93
-rw-r--r--drivers/infiniband/hw/mlx5/devx.h4
-rw-r--r--drivers/infiniband/hw/mlx5/mad.c8
-rw-r--r--drivers/infiniband/hw/mlx5/main.c78
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h3
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c51
-rw-r--r--drivers/infiniband/hw/qib/qib_sysfs.c2
-rw-r--r--drivers/infiniband/sw/rxe/rxe_qp.c1
-rw-r--r--drivers/infiniband/sw/rxe/rxe_req.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ethtool.c9
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c3
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c4
-rw-r--r--drivers/input/input.c15
-rw-r--r--drivers/input/joystick/db9.c30
-rw-r--r--drivers/input/joystick/gamecon.c22
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c48
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c57
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c36
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c13
-rw-r--r--drivers/input/joystick/n64joy.c35
-rw-r--r--drivers/input/joystick/turbografx.c22
-rw-r--r--drivers/input/joystick/xpad.c99
-rw-r--r--drivers/input/keyboard/adp5520-keys.c2
-rw-r--r--drivers/input/keyboard/adp5589-keys.c39
-rw-r--r--drivers/input/keyboard/applespi.c72
-rw-r--r--drivers/input/keyboard/atkbd.c8
-rw-r--r--drivers/input/keyboard/cap11xx.c12
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c2
-rw-r--r--drivers/input/keyboard/cypress-sf.c2
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c10
-rw-r--r--drivers/input/keyboard/gpio_keys.c10
-rw-r--r--drivers/input/keyboard/gpio_keys_polled.c12
-rw-r--r--drivers/input/keyboard/hilkbd.c4
-rw-r--r--drivers/input/keyboard/imx_keypad.c27
-rw-r--r--drivers/input/keyboard/ipaq-micro-keys.c12
-rw-r--r--drivers/input/keyboard/iqs62x-keys.c2
-rw-r--r--drivers/input/keyboard/lm8323.c49
-rw-r--r--drivers/input/keyboard/locomokbd.c5
-rw-r--r--drivers/input/keyboard/lpc32xx-keys.c18
-rw-r--r--drivers/input/keyboard/maple_keyb.c9
-rw-r--r--drivers/input/keyboard/matrix_keypad.c19
-rw-r--r--drivers/input/keyboard/mpr121_touchkey.c45
-rw-r--r--drivers/input/keyboard/mtk-pmic-keys.c17
-rw-r--r--drivers/input/keyboard/omap-keypad.c18
-rw-r--r--drivers/input/keyboard/omap4-keypad.c6
-rw-r--r--drivers/input/keyboard/pmic8xxx-keypad.c8
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c16
-rw-r--r--drivers/input/keyboard/samsung-keypad.c2
-rw-r--r--drivers/input/keyboard/sh_keysc.c2
-rw-r--r--drivers/input/keyboard/spear-keyboard.c9
-rw-r--r--drivers/input/keyboard/st-keyscan.c19
-rw-r--r--drivers/input/keyboard/stmpe-keypad.c2
-rw-r--r--drivers/input/keyboard/sun4i-lradc-keys.c8
-rw-r--r--drivers/input/keyboard/sunkbd.c5
-rw-r--r--drivers/input/misc/88pm80x_onkey.c2
-rw-r--r--drivers/input/misc/ad714x.c12
-rw-r--r--drivers/input/misc/ati_remote2.c57
-rw-r--r--drivers/input/misc/cm109.c167
-rw-r--r--drivers/input/misc/cma3000_d0x.c16
-rw-r--r--drivers/input/misc/cs40l50-vibra.c6
-rw-r--r--drivers/input/misc/da7280.c26
-rw-r--r--drivers/input/misc/da9052_onkey.c4
-rw-r--r--drivers/input/misc/da9055_onkey.c4
-rw-r--r--drivers/input/misc/drv260x.c50
-rw-r--r--drivers/input/misc/drv2665.c46
-rw-r--r--drivers/input/misc/drv2667.c46
-rw-r--r--drivers/input/misc/ibm-panel.c5
-rw-r--r--drivers/input/misc/ideapad_slidebar.c26
-rw-r--r--drivers/input/misc/ims-pcu.c2
-rw-r--r--drivers/input/misc/iqs269a.c55
-rw-r--r--drivers/input/misc/iqs626a.c22
-rw-r--r--drivers/input/misc/iqs7222.c30
-rw-r--r--drivers/input/misc/kxtj9.c16
-rw-r--r--drivers/input/misc/m68kspkr.c2
-rw-r--r--drivers/input/misc/max8997_haptic.c17
-rw-r--r--drivers/input/misc/mc13783-pwrbutton.c2
-rw-r--r--drivers/input/misc/palmas-pwrbutton.c2
-rw-r--r--drivers/input/misc/pcap_keys.c2
-rw-r--r--drivers/input/misc/pcf50633-input.c2
-rw-r--r--drivers/input/misc/pcspkr.c2
-rw-r--r--drivers/input/misc/pm8941-pwrkey.c2
-rw-r--r--drivers/input/misc/powermate.c11
-rw-r--r--drivers/input/misc/pwm-beeper.c12
-rw-r--r--drivers/input/misc/regulator-haptic.c24
-rw-r--r--drivers/input/misc/rotary_encoder.c23
-rw-r--r--drivers/input/misc/soc_button_array.c4
-rw-r--r--drivers/input/misc/sparcspkr.c59
-rw-r--r--drivers/input/misc/tps65219-pwrbutton.c2
-rw-r--r--drivers/input/misc/twl4030-vibra.c11
-rw-r--r--drivers/input/misc/twl6040-vibra.c8
-rw-r--r--drivers/input/misc/wistron_btns.c4
-rw-r--r--drivers/input/misc/wm831x-on.c2
-rw-r--r--drivers/input/misc/yealink.c4
-rw-r--r--drivers/input/mouse/alps.c4
-rw-r--r--drivers/input/mouse/amimouse.c2
-rw-r--r--drivers/input/mouse/byd.c5
-rw-r--r--drivers/input/mouse/elan_i2c_core.c228
-rw-r--r--drivers/input/mouse/elan_i2c_i2c.c14
-rw-r--r--drivers/input/mouse/psmouse-smbus.c28
-rw-r--r--drivers/input/mouse/synaptics.c6
-rw-r--r--drivers/input/mouse/synaptics.h2
-rw-r--r--drivers/input/rmi4/rmi_f03.c4
-rw-r--r--drivers/input/rmi4/rmi_f34.c37
-rw-r--r--drivers/input/serio/altera_ps2.c2
-rw-r--r--drivers/input/serio/ams_delta_serio.c2
-rw-r--r--drivers/input/serio/apbps2.c2
-rw-r--r--drivers/input/serio/arc_ps2.c2
-rw-r--r--drivers/input/serio/ct82c710.c2
-rw-r--r--drivers/input/serio/gscps2.c116
-rw-r--r--drivers/input/serio/hyperv-keyboard.c38
-rw-r--r--drivers/input/serio/i8042-acpipnpio.h2
-rw-r--r--drivers/input/serio/i8042-sparcio.h16
-rw-r--r--drivers/input/serio/i8042.c329
-rw-r--r--drivers/input/serio/ioc3kbd.c2
-rw-r--r--drivers/input/serio/libps2.c28
-rw-r--r--drivers/input/serio/maceps2.c2
-rw-r--r--drivers/input/serio/olpc_apsp.c2
-rw-r--r--drivers/input/serio/ps2-gpio.c6
-rw-r--r--drivers/input/serio/ps2mult.c25
-rw-r--r--drivers/input/serio/q40kbd.c12
-rw-r--r--drivers/input/serio/rpckbd.c2
-rw-r--r--drivers/input/serio/sa1111ps2.c8
-rw-r--r--drivers/input/serio/serio.c165
-rw-r--r--drivers/input/serio/serio_raw.c125
-rw-r--r--drivers/input/serio/serport.c27
-rw-r--r--drivers/input/serio/sun4i-ps2.c10
-rw-r--r--drivers/input/serio/userio.c139
-rw-r--r--drivers/input/serio/xilinx_ps2.c17
-rw-r--r--drivers/input/tablet/pegasus_notetaker.c86
-rw-r--r--drivers/input/touchscreen/88pm860x-ts.c20
-rw-r--r--drivers/input/touchscreen/Kconfig2
-rw-r--r--drivers/input/touchscreen/ads7846.c14
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c2
-rw-r--r--drivers/input/touchscreen/bcm_iproc_tsc.c2
-rw-r--r--drivers/input/touchscreen/da9052_tsi.c2
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c2
-rw-r--r--drivers/input/touchscreen/elo.c8
-rw-r--r--drivers/input/touchscreen/ili210x.c2
-rw-r--r--drivers/input/touchscreen/imagis.c2
-rw-r--r--drivers/input/touchscreen/mainstone-wm97xx.c2
-rw-r--r--drivers/input/touchscreen/mc13783_ts.c2
-rw-r--r--drivers/input/touchscreen/novatek-nvt-ts.c67
-rw-r--r--drivers/input/touchscreen/pcap_ts.c2
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c2
-rw-r--r--drivers/input/touchscreen/raspberrypi-ts.c4
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c4
-rw-r--r--drivers/input/touchscreen/stmpe-ts.c6
-rw-r--r--drivers/input/touchscreen/sun4i-ts.c4
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c4
-rw-r--r--drivers/input/touchscreen/ts4800-ts.c5
-rw-r--r--drivers/input/touchscreen/wm831x-ts.c2
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c6
-rw-r--r--drivers/interconnect/core.c4
-rw-r--r--drivers/interconnect/imx/imx8mm.c2
-rw-r--r--drivers/interconnect/imx/imx8mn.c2
-rw-r--r--drivers/interconnect/imx/imx8mp.c2
-rw-r--r--drivers/interconnect/imx/imx8mq.c2
-rw-r--r--drivers/interconnect/mediatek/mt8183.c2
-rw-r--r--drivers/interconnect/mediatek/mt8195.c2
-rw-r--r--drivers/interconnect/qcom/Kconfig29
-rw-r--r--drivers/interconnect/qcom/Makefile6
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.c5
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.h2
-rw-r--r--drivers/interconnect/qcom/msm8909.c2
-rw-r--r--drivers/interconnect/qcom/msm8916.c2
-rw-r--r--drivers/interconnect/qcom/msm8937.c10
-rw-r--r--drivers/interconnect/qcom/msm8939.c2
-rw-r--r--drivers/interconnect/qcom/msm8953.c2
-rw-r--r--drivers/interconnect/qcom/msm8974.c2
-rw-r--r--drivers/interconnect/qcom/msm8976.c2
-rw-r--r--drivers/interconnect/qcom/msm8996.c2
-rw-r--r--drivers/interconnect/qcom/osm-l3.c2
-rw-r--r--drivers/interconnect/qcom/qcm2290.c2
-rw-r--r--drivers/interconnect/qcom/qcs404.c2
-rw-r--r--drivers/interconnect/qcom/qcs615.c1563
-rw-r--r--drivers/interconnect/qcom/qcs615.h128
-rw-r--r--drivers/interconnect/qcom/qcs8300.c2088
-rw-r--r--drivers/interconnect/qcom/qcs8300.h177
-rw-r--r--drivers/interconnect/qcom/qdu1000.c2
-rw-r--r--drivers/interconnect/qcom/sa8775p.c2
-rw-r--r--drivers/interconnect/qcom/sar2130p.c1930
-rw-r--r--drivers/interconnect/qcom/sc7180.c2
-rw-r--r--drivers/interconnect/qcom/sc7280.c6
-rw-r--r--drivers/interconnect/qcom/sc8180x.c2
-rw-r--r--drivers/interconnect/qcom/sc8280xp.c2
-rw-r--r--drivers/interconnect/qcom/sdm660.c2
-rw-r--r--drivers/interconnect/qcom/sdm670.c2
-rw-r--r--drivers/interconnect/qcom/sdm845.c2
-rw-r--r--drivers/interconnect/qcom/sdx55.c2
-rw-r--r--drivers/interconnect/qcom/sdx65.c2
-rw-r--r--drivers/interconnect/qcom/sdx75.c2
-rw-r--r--drivers/interconnect/qcom/sm6115.c2
-rw-r--r--drivers/interconnect/qcom/sm6350.c2
-rw-r--r--drivers/interconnect/qcom/sm7150.c2
-rw-r--r--drivers/interconnect/qcom/sm8150.c2
-rw-r--r--drivers/interconnect/qcom/sm8250.c2
-rw-r--r--drivers/interconnect/qcom/sm8350.c2
-rw-r--r--drivers/interconnect/qcom/sm8450.c2
-rw-r--r--drivers/interconnect/qcom/sm8550.c2
-rw-r--r--drivers/interconnect/qcom/sm8650.c2
-rw-r--r--drivers/interconnect/qcom/smd-rpm.c2
-rw-r--r--drivers/interconnect/qcom/x1e80100.c2
-rw-r--r--drivers/interconnect/samsung/exynos.c2
-rw-r--r--drivers/iommu/Kconfig10
-rw-r--r--drivers/iommu/Makefile2
-rw-r--r--drivers/iommu/amd/amd_iommu.h11
-rw-r--r--drivers/iommu/amd/amd_iommu_types.h23
-rw-r--r--drivers/iommu/amd/init.c63
-rw-r--r--drivers/iommu/amd/io_pgtable.c11
-rw-r--r--drivers/iommu/amd/io_pgtable_v2.c3
-rw-r--r--drivers/iommu/amd/iommu.c502
-rw-r--r--drivers/iommu/amd/pasid.c6
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/Makefile1
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c401
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c5
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c164
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h94
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c7
-rw-r--r--drivers/iommu/arm/arm-smmu/arm-smmu.c27
-rw-r--r--drivers/iommu/intel/Kconfig2
-rw-r--r--drivers/iommu/intel/Makefile2
-rw-r--r--drivers/iommu/intel/dmar.c15
-rw-r--r--drivers/iommu/intel/iommu.c591
-rw-r--r--drivers/iommu/intel/iommu.h62
-rw-r--r--drivers/iommu/intel/irq_remapping.c4
-rw-r--r--drivers/iommu/intel/nested.c64
-rw-r--r--drivers/iommu/intel/pasid.c409
-rw-r--r--drivers/iommu/intel/pasid.h22
-rw-r--r--drivers/iommu/intel/prq.c396
-rw-r--r--drivers/iommu/intel/svm.c433
-rw-r--r--drivers/iommu/io-pgtable-arm-v7s.c149
-rw-r--r--drivers/iommu/io-pgtable-arm.c141
-rw-r--r--drivers/iommu/iommu-sysfs.c2
-rw-r--r--drivers/iommu/iommu.c263
-rw-r--r--drivers/iommu/iommufd/Kconfig4
-rw-r--r--drivers/iommu/iommufd/Makefile6
-rw-r--r--drivers/iommu/iommufd/driver.c53
-rw-r--r--drivers/iommu/iommufd/fault.c9
-rw-r--r--drivers/iommu/iommufd/hw_pagetable.c132
-rw-r--r--drivers/iommu/iommufd/io_pagetable.c105
-rw-r--r--drivers/iommu/iommufd/io_pagetable.h26
-rw-r--r--drivers/iommu/iommufd/ioas.c259
-rw-r--r--drivers/iommu/iommufd/iommufd_private.h58
-rw-r--r--drivers/iommu/iommufd/iommufd_test.h32
-rw-r--r--drivers/iommu/iommufd/main.c65
-rw-r--r--drivers/iommu/iommufd/pages.c319
-rw-r--r--drivers/iommu/iommufd/selftest.c363
-rw-r--r--drivers/iommu/iommufd/vfio_compat.c7
-rw-r--r--drivers/iommu/iommufd/viommu.c157
-rw-r--r--drivers/iommu/iova.c8
-rw-r--r--drivers/iommu/mtk_iommu.c2
-rw-r--r--drivers/iommu/omap-iommu.c26
-rw-r--r--drivers/iommu/riscv/Kconfig20
-rw-r--r--drivers/iommu/riscv/Makefile3
-rw-r--r--drivers/iommu/riscv/iommu-bits.h784
-rw-r--r--drivers/iommu/riscv/iommu-pci.c120
-rw-r--r--drivers/iommu/riscv/iommu-platform.c92
-rw-r--r--drivers/iommu/riscv/iommu.c1661
-rw-r--r--drivers/iommu/riscv/iommu.h88
-rw-r--r--drivers/iommu/s390-iommu.c73
-rw-r--r--drivers/irqchip/Kconfig20
-rw-r--r--drivers/irqchip/Makefile3
-rw-r--r--drivers/irqchip/irq-aspeed-intc.c139
-rw-r--r--drivers/irqchip/irq-atmel-aic5.c9
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c191
-rw-r--r--drivers/irqchip/irq-gic-v3.c7
-rw-r--r--drivers/irqchip/irq-gic.c2
-rw-r--r--drivers/irqchip/irq-imgpdc.c2
-rw-r--r--drivers/irqchip/irq-imx-intmux.c2
-rw-r--r--drivers/irqchip/irq-imx-irqsteer.c2
-rw-r--r--drivers/irqchip/irq-keystone.c2
-rw-r--r--drivers/irqchip/irq-loongson-eiointc.c108
-rw-r--r--drivers/irqchip/irq-ls-scfg-msi.c2
-rw-r--r--drivers/irqchip/irq-madera.c2
-rw-r--r--drivers/irqchip/irq-mips-gic.c269
-rw-r--r--drivers/irqchip/irq-mvebu-pic.c4
-rw-r--r--drivers/irqchip/irq-mvebu-sei.c2
-rw-r--r--drivers/irqchip/irq-pruss-intc.c2
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c2
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c2
-rw-r--r--drivers/irqchip/irq-renesas-rza1.c2
-rw-r--r--drivers/irqchip/irq-renesas-rzv2h.c513
-rw-r--r--drivers/irqchip/irq-riscv-aplic-main.c3
-rw-r--r--drivers/irqchip/irq-riscv-aplic-msi.c3
-rw-r--r--drivers/irqchip/irq-sifive-plic.c9
-rw-r--r--drivers/irqchip/irq-stm32mp-exti.c3
-rw-r--r--drivers/irqchip/irq-thead-c900-aclint-sswi.c176
-rw-r--r--drivers/irqchip/irq-ts4800.c2
-rw-r--r--drivers/irqchip/irq-versatile-fpga.c2
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c16
-rw-r--r--drivers/leds/blink/leds-bcm63138.c29
-rw-r--r--drivers/leds/blink/leds-lgm-sso.c2
-rw-r--r--drivers/leds/flash/leds-aat1290.c2
-rw-r--r--drivers/leds/flash/leds-ktd2692.c3
-rw-r--r--drivers/leds/flash/leds-max77693.c2
-rw-r--r--drivers/leds/flash/leds-mt6360.c5
-rw-r--r--drivers/leds/flash/leds-mt6370-flash.c11
-rw-r--r--drivers/leds/flash/leds-qcom-flash.c6
-rw-r--r--drivers/leds/flash/leds-rt8515.c2
-rw-r--r--drivers/leds/flash/leds-sgm3140.c2
-rw-r--r--drivers/leds/led-class-flash.c1
-rw-r--r--drivers/leds/led-class-multicolor.c2
-rw-r--r--drivers/leds/led-class.c26
-rw-r--r--drivers/leds/led-core.c6
-rw-r--r--drivers/leds/leds-88pm860x.c2
-rw-r--r--drivers/leds/leds-adp5520.c2
-rw-r--r--drivers/leds/leds-aw200xx.c7
-rw-r--r--drivers/leds/leds-bcm6328.c4
-rw-r--r--drivers/leds/leds-cht-wcove.c2
-rw-r--r--drivers/leds/leds-clevo-mail.c2
-rw-r--r--drivers/leds/leds-cr0014114.c4
-rw-r--r--drivers/leds/leds-da903x.c2
-rw-r--r--drivers/leds/leds-da9052.c2
-rw-r--r--drivers/leds/leds-el15203000.c14
-rw-r--r--drivers/leds/leds-gpio-register.c2
-rw-r--r--drivers/leds/leds-gpio.c20
-rw-r--r--drivers/leds/leds-lm3532.c18
-rw-r--r--drivers/leds/leds-lm3533.c2
-rw-r--r--drivers/leds/leds-lm3697.c18
-rw-r--r--drivers/leds/leds-lp50xx.c23
-rw-r--r--drivers/leds/leds-lp5562.c25
-rw-r--r--drivers/leds/leds-lp55xx-common.c3
-rw-r--r--drivers/leds/leds-max5970.c5
-rw-r--r--drivers/leds/leds-max77650.c18
-rw-r--r--drivers/leds/leds-mc13783.c2
-rw-r--r--drivers/leds/leds-mt6323.c2
-rw-r--r--drivers/leds/leds-ns2.c7
-rw-r--r--drivers/leds/leds-pca963x.c11
-rw-r--r--drivers/leds/leds-powernv.c4
-rw-r--r--drivers/leds/leds-pwm.c33
-rw-r--r--drivers/leds/leds-rb532.c2
-rw-r--r--drivers/leds/leds-regulator.c2
-rw-r--r--drivers/leds/leds-sc27xx-bltc.c2
-rw-r--r--drivers/leds/leds-ss4200.c2
-rw-r--r--drivers/leds/leds-sun50i-a100.c29
-rw-r--r--drivers/leds/leds-sunfire.c4
-rw-r--r--drivers/leds/leds-tca6507.c7
-rw-r--r--drivers/leds/leds-turris-omnia.c1
-rw-r--r--drivers/leds/leds-wm831x-status.c2
-rw-r--r--drivers/leds/leds-wm8350.c2
-rw-r--r--drivers/leds/rgb/leds-group-multicolor.c2
-rw-r--r--drivers/leds/rgb/leds-ktd202x.c8
-rw-r--r--drivers/leds/rgb/leds-mt6370-rgb.c39
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c2
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c2
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c2
-rw-r--r--drivers/macintosh/via-pmu-led.c19
-rw-r--r--drivers/mailbox/Kconfig13
-rw-r--r--drivers/mailbox/Makefile2
-rw-r--r--drivers/mailbox/arm_mhuv2.c8
-rw-r--r--drivers/mailbox/bcm-flexrm-mailbox.c2
-rw-r--r--drivers/mailbox/bcm-pdc-mailbox.c2
-rw-r--r--drivers/mailbox/imx-mailbox.c6
-rw-r--r--drivers/mailbox/mailbox-mpfs.c81
-rw-r--r--drivers/mailbox/mailbox-test.c4
-rw-r--r--drivers/mailbox/mailbox-th1520.c597
-rw-r--r--drivers/mailbox/mtk-cmdq-mailbox.c14
-rw-r--r--drivers/mailbox/omap-mailbox.c1
-rw-r--r--drivers/mailbox/pcc.c61
-rw-r--r--drivers/mailbox/qcom-apcs-ipc-mailbox.c2
-rw-r--r--drivers/mailbox/qcom-cpucp-mbox.c2
-rw-r--r--drivers/mailbox/qcom-ipcc.c2
-rw-r--r--drivers/mailbox/stm32-ipcc.c2
-rw-r--r--drivers/mailbox/sun6i-msgbox.c4
-rw-r--r--drivers/mailbox/tegra-hsp.c2
-rw-r--r--drivers/mailbox/ti-msgmgr.c2
-rw-r--r--drivers/mailbox/zynqmp-ipi-mailbox.c6
-rw-r--r--drivers/md/bcache/Kconfig1
-rw-r--r--drivers/md/bcache/alloc.c11
-rw-r--r--drivers/md/bcache/bset.c14
-rw-r--r--drivers/md/bcache/extents.c10
-rw-r--r--drivers/md/bcache/movinggc.c10
-rw-r--r--drivers/md/dm-bio-prison-v1.c35
-rw-r--r--drivers/md/dm-bio-prison-v1.h24
-rw-r--r--drivers/md/dm-bufio.c37
-rw-r--r--drivers/md/dm-cache-background-tracker.c31
-rw-r--r--drivers/md/dm-cache-background-tracker.h9
-rw-r--r--drivers/md/dm-cache-metadata.c33
-rw-r--r--drivers/md/dm-cache-metadata.h3
-rw-r--r--drivers/md/dm-cache-target.c88
-rw-r--r--drivers/md/dm-clone-target.c4
-rw-r--r--drivers/md/dm-ioctl.c4
-rw-r--r--drivers/md/dm-table.c5
-rw-r--r--drivers/md/dm-thin.c3
-rw-r--r--drivers/md/dm-unstripe.c4
-rw-r--r--drivers/md/dm-vdo/Kconfig1
-rw-r--r--drivers/md/dm-vdo/block-map.c2
-rw-r--r--drivers/md/dm-vdo/data-vio.c36
-rw-r--r--drivers/md/dm-vdo/data-vio.h5
-rw-r--r--drivers/md/dm-vdo/dedupe.c9
-rw-r--r--drivers/md/dm-vdo/encodings.c2
-rw-r--r--drivers/md/dm-vdo/indexer/index-layout.c26
-rw-r--r--drivers/md/dm-vdo/indexer/indexer.h4
-rw-r--r--drivers/md/dm-vdo/int-map.c28
-rw-r--r--drivers/md/dm-vdo/io-submitter.c2
-rw-r--r--drivers/md/dm-vdo/murmurhash3.c7
-rw-r--r--drivers/md/dm-vdo/packer.c3
-rw-r--r--drivers/md/dm-vdo/physical-zone.c2
-rw-r--r--drivers/md/dm-vdo/recovery-journal.c2
-rw-r--r--drivers/md/dm-vdo/repair.c2
-rw-r--r--drivers/md/dm-vdo/slab-depot.c19
-rw-r--r--drivers/md/dm-vdo/vdo.c4
-rw-r--r--drivers/md/dm-vdo/vio.c1
-rw-r--r--drivers/md/dm-verity-target.c15
-rw-r--r--drivers/md/dm-verity.h2
-rw-r--r--drivers/md/dm-zone.c4
-rw-r--r--drivers/md/dm-zoned-metadata.c50
-rw-r--r--drivers/md/dm-zoned.h2
-rw-r--r--drivers/md/dm.c65
-rw-r--r--drivers/md/dm.h2
-rw-r--r--drivers/md/md-bitmap.c1
-rw-r--r--drivers/md/md.c15
-rw-r--r--drivers/md/md.h24
-rw-r--r--drivers/md/persistent-data/dm-space-map-common.c2
-rw-r--r--drivers/md/raid0.c13
-rw-r--r--drivers/md/raid1.c128
-rw-r--r--drivers/md/raid10.c107
-rw-r--r--drivers/md/raid5-ppl.c2
-rw-r--r--drivers/md/raid5.c17
-rw-r--r--drivers/md/raid5.h2
-rw-r--r--drivers/media/cec/core/cec-core.c2
-rw-r--r--drivers/media/cec/platform/Kconfig2
-rw-r--r--drivers/media/cec/platform/cec-gpio/cec-gpio.c4
-rw-r--r--drivers/media/cec/platform/cros-ec/cros-ec-cec.c2
-rw-r--r--drivers/media/cec/platform/meson/ao-cec-g12a.c2
-rw-r--r--drivers/media/cec/platform/meson/ao-cec.c2
-rw-r--r--drivers/media/cec/platform/s5p/s5p_cec.c2
-rw-r--r--drivers/media/cec/platform/seco/seco-cec.c2
-rw-r--r--drivers/media/cec/platform/sti/stih-cec.c2
-rw-r--r--drivers/media/cec/platform/stm32/stm32-cec.c2
-rw-r--r--drivers/media/cec/platform/tegra/tegra_cec.c2
-rw-r--r--drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c6
-rw-r--r--drivers/media/cec/usb/pulse8/pulse8-cec.c2
-rw-r--r--drivers/media/common/saa7146/saa7146_vbi.c2
-rw-r--r--drivers/media/common/saa7146/saa7146_video.c2
-rw-r--r--drivers/media/common/siano/smsdvb-debugfs.c9
-rw-r--r--drivers/media/common/uvc.c8
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-core.c3
-rw-r--r--drivers/media/common/videobuf2/videobuf2-core.c77
-rw-r--r--drivers/media/common/videobuf2/videobuf2-v4l2.c2
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c4
-rw-r--r--drivers/media/dvb-core/dvb_vb2.c8
-rw-r--r--drivers/media/dvb-core/dvbdev.c16
-rw-r--r--drivers/media/dvb-frontends/bcm3510.c2
-rw-r--r--drivers/media/dvb-frontends/cx24116.c7
-rw-r--r--drivers/media/dvb-frontends/dib0090.c4
-rw-r--r--drivers/media/dvb-frontends/dib3000mb.c2
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c4
-rw-r--r--drivers/media/dvb-frontends/stb0899_algo.c2
-rw-r--r--drivers/media/dvb-frontends/stv6111.c2
-rw-r--r--drivers/media/dvb-frontends/tda18271c2dd.c2
-rw-r--r--drivers/media/dvb-frontends/ts2020.c8
-rw-r--r--drivers/media/dvb-frontends/zd1301_demod.c2
-rw-r--r--drivers/media/dvb-frontends/zl10036.c2
-rw-r--r--drivers/media/i2c/adv7180.c3
-rw-r--r--drivers/media/i2c/adv7511-v4l2.c91
-rw-r--r--drivers/media/i2c/adv7604.c123
-rw-r--r--drivers/media/i2c/adv7842.c135
-rw-r--r--drivers/media/i2c/alvium-csi2.c5
-rw-r--r--drivers/media/i2c/ar0521.c4
-rw-r--r--drivers/media/i2c/ds90ub953.c5
-rw-r--r--drivers/media/i2c/ds90ub960.c7
-rw-r--r--drivers/media/i2c/dw9768.c15
-rw-r--r--drivers/media/i2c/gc0308.c4
-rw-r--r--drivers/media/i2c/gc05a2.c10
-rw-r--r--drivers/media/i2c/gc08a3.c10
-rw-r--r--drivers/media/i2c/gc2145.c41
-rw-r--r--drivers/media/i2c/hi556.c2
-rw-r--r--drivers/media/i2c/imx219.c10
-rw-r--r--drivers/media/i2c/imx283.c10
-rw-r--r--drivers/media/i2c/imx290.c40
-rw-r--r--drivers/media/i2c/imx415.c3
-rw-r--r--drivers/media/i2c/max96717.c6
-rw-r--r--drivers/media/i2c/mt9p031.c96
-rw-r--r--drivers/media/i2c/ov01a10.c6
-rw-r--r--drivers/media/i2c/ov08x40.c181
-rw-r--r--drivers/media/i2c/ov2740.c7
-rw-r--r--drivers/media/i2c/ov5640.c2
-rw-r--r--drivers/media/i2c/ov5645.c278
-rw-r--r--drivers/media/i2c/ov5670.c2
-rw-r--r--drivers/media/i2c/ov5675.c4
-rw-r--r--drivers/media/i2c/ov64a40.c10
-rw-r--r--drivers/media/i2c/ov772x.c2
-rw-r--r--drivers/media/i2c/ov7740.c2
-rw-r--r--drivers/media/i2c/ov8856.c2
-rw-r--r--drivers/media/i2c/ov8858.c9
-rw-r--r--drivers/media/i2c/ov9650.c2
-rw-r--r--drivers/media/i2c/ov9734.c2
-rw-r--r--drivers/media/i2c/st-mipid02.c117
-rw-r--r--drivers/media/i2c/tc358743.c40
-rw-r--r--drivers/media/i2c/thp7312.c5
-rw-r--r--drivers/media/i2c/ths7303.c2
-rw-r--r--drivers/media/i2c/vgxy61.c2
-rw-r--r--drivers/media/i2c/video-i2c.c4
-rw-r--r--drivers/media/mc/mc-entity.c14
-rw-r--r--drivers/media/mc/mc-request.c20
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c2
-rw-r--r--drivers/media/pci/bt8xx/bttv-vbi.c2
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.c2
-rw-r--r--drivers/media/pci/cobalt/cobalt-v4l2.c2
-rw-r--r--drivers/media/pci/cx18/cx18-streams.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-417.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-vbi.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c2
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c2
-rw-r--r--drivers/media/pci/cx88/cx88-blackbird.c2
-rw-r--r--drivers/media/pci/cx88/cx88-dvb.c2
-rw-r--r--drivers/media/pci/cx88/cx88-vbi.c2
-rw-r--r--drivers/media/pci/cx88/cx88-video.c2
-rw-r--r--drivers/media/pci/dt3155/dt3155.c2
-rw-r--r--drivers/media/pci/intel/ipu3/ipu3-cio2.c2
-rw-r--r--drivers/media/pci/intel/ipu6/Kconfig10
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-bus.c6
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-buttress.c65
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-buttress.h6
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-cpd.c24
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-dma.c208
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-dma.h34
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-fw-com.c22
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c4
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys-queue.c66
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys-queue.h1
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys-video.c6
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys.c25
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys.h2
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-mmu.c310
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-mmu.h4
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h2
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6.c6
-rw-r--r--drivers/media/pci/mantis/mantis_core.h43
-rw-r--r--drivers/media/pci/mgb4/mgb4_cmt.c2
-rw-r--r--drivers/media/pci/mgb4/mgb4_core.c8
-rw-r--r--drivers/media/pci/mgb4/mgb4_core.h2
-rw-r--r--drivers/media/pci/mgb4/mgb4_vin.c57
-rw-r--r--drivers/media/pci/mgb4/mgb4_vin.h1
-rw-r--r--drivers/media/pci/mgb4/mgb4_vout.c27
-rw-r--r--drivers/media/pci/mgb4/mgb4_vout.h1
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_spi.c6
-rw-r--r--drivers/media/pci/saa7134/saa7134-empress.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-ts.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-vbi.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c2
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c2
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2.c2
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c2
-rw-r--r--drivers/media/pci/tw5864/tw5864-video.c2
-rw-r--r--drivers/media/pci/tw68/tw68-video.c2
-rw-r--r--drivers/media/pci/tw686x/tw686x-video.c2
-rw-r--r--drivers/media/pci/zoran/zoran_driver.c2
-rw-r--r--drivers/media/platform/allegro-dvt/allegro-core.c8
-rw-r--r--drivers/media/platform/amlogic/meson-ge2d/ge2d.c4
-rw-r--r--drivers/media/platform/amphion/venc.c12
-rw-r--r--drivers/media/platform/amphion/vpu_core.c2
-rw-r--r--drivers/media/platform/amphion/vpu_drv.c4
-rw-r--r--drivers/media/platform/amphion/vpu_v4l2.c4
-rw-r--r--drivers/media/platform/aspeed/aspeed-video.c4
-rw-r--r--drivers/media/platform/atmel/atmel-isi.c4
-rw-r--r--drivers/media/platform/broadcom/bcm2835-unicam.c4
-rw-r--r--drivers/media/platform/cadence/cdns-csi2rx.c2
-rw-r--r--drivers/media/platform/cadence/cdns-csi2tx.c2
-rw-r--r--drivers/media/platform/chips-media/coda/coda-common.c4
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-helper.c37
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-helper.h5
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-hw.c30
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c323
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c315
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpu.c52
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpu.h5
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpuapi.c33
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpuapi.h1
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h27
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5.h3
-rw-r--r--drivers/media/platform/imagination/e5010-jpeg-enc.c4
-rw-r--r--drivers/media/platform/intel/pxa_camera.c4
-rw-r--r--drivers/media/platform/m2m-deinterlace.c4
-rw-r--r--drivers/media/platform/marvell/mcam-core.c4
-rw-r--r--drivers/media/platform/marvell/mmp-driver.c2
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c16
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c11
-rw-r--r--drivers/media/platform/mediatek/mdp/mtk_mdp_core.c2
-rw-r--r--drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c2
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c2
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c2
-rw-r--r--drivers/media/platform/mediatek/vpu/mtk_vpu.c2
-rw-r--r--drivers/media/platform/microchip/microchip-csi2dc.c2
-rw-r--r--drivers/media/platform/microchip/microchip-isc-base.c2
-rw-r--r--drivers/media/platform/microchip/microchip-sama5d2-isc.c2
-rw-r--r--drivers/media/platform/microchip/microchip-sama7g5-isc.c2
-rw-r--r--drivers/media/platform/nuvoton/npcm-video.c4
-rw-r--r--drivers/media/platform/nvidia/tegra-vde/iommu.c7
-rw-r--r--drivers/media/platform/nvidia/tegra-vde/v4l2.c14
-rw-r--r--drivers/media/platform/nvidia/tegra-vde/vde.c2
-rw-r--r--drivers/media/platform/nxp/dw100/dw100.c6
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c19
-rw-r--r--drivers/media/platform/nxp/imx-mipi-csis.c2
-rw-r--r--drivers/media/platform/nxp/imx-pxp.c4
-rw-r--r--drivers/media/platform/nxp/imx7-media-csi.c4
-rw-r--r--drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c2
-rw-r--r--drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c2
-rw-r--r--drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c2
-rw-r--r--drivers/media/platform/nxp/imx8mq-mipi-csi2.c2
-rw-r--r--drivers/media/platform/nxp/mx2_emmaprp.c4
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy.c36
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy.h2
-rw-r--r--drivers/media/platform/qcom/camss/camss-ispif.c5
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-1.c10
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe.c1
-rw-r--r--drivers/media/platform/qcom/camss/camss-video.c2
-rw-r--r--drivers/media/platform/qcom/camss/camss.c223
-rw-r--r--drivers/media/platform/qcom/camss/camss.h7
-rw-r--r--drivers/media/platform/qcom/venus/core.c37
-rw-r--r--drivers/media/platform/qcom/venus/core.h12
-rw-r--r--drivers/media/platform/qcom/venus/pm_helpers.c44
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c15
-rw-r--r--drivers/media/platform/qcom/venus/vdec.h1
-rw-r--r--drivers/media/platform/qcom/venus/vdec_ctrls.c5
-rw-r--r--drivers/media/platform/qcom/venus/venc.c87
-rw-r--r--drivers/media/platform/qcom/venus/venc.h1
-rw-r--r--drivers/media/platform/qcom/venus/venc_ctrls.c131
-rw-r--r--drivers/media/platform/raspberrypi/Kconfig1
-rw-r--r--drivers/media/platform/raspberrypi/Makefile1
-rw-r--r--drivers/media/platform/raspberrypi/pisp_be/pisp_be.c2
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/Kconfig15
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/Makefile6
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h332
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace.h202
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/cfe.c2509
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/cfe.h43
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/csi2.c586
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/csi2.h89
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/dphy.c181
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/dphy.h27
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.c605
-rw-r--r--drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.h53
-rw-r--r--drivers/media/platform/renesas/rcar-csi2.c520
-rw-r--r--drivers/media/platform/renesas/rcar-fcp.c2
-rw-r--r--drivers/media/platform/renesas/rcar-isp.c6
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-core.c3
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-dma.c32
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c43
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-vin.h4
-rw-r--r--drivers/media/platform/renesas/rcar_drif.c6
-rw-r--r--drivers/media/platform/renesas/rcar_fdp1.c4
-rw-r--r--drivers/media/platform/renesas/rcar_jpu.c4
-rw-r--r--drivers/media/platform/renesas/renesas-ceu.c4
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c18
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru-regs.h80
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h34
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c41
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c85
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c305
-rw-r--r--drivers/media/platform/renesas/sh_vou.c4
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_drv.c2
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_histo.c2
-rw-r--r--drivers/media/platform/renesas/vsp1/vsp1_video.c2
-rw-r--r--drivers/media/platform/rockchip/rga/rga-buf.c2
-rw-r--r--drivers/media/platform/rockchip/rga/rga.c4
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c2
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c2
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-params.c2
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c2
-rw-r--r--drivers/media/platform/samsung/exynos-gsc/gsc-core.c2
-rw-r--r--drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-capture.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-core.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-is.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-lite.c4
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-m2m.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/media-dev.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/media-dev.h5
-rw-r--r--drivers/media/platform/samsung/exynos4-is/mipi-csis.c2
-rw-r--r--drivers/media/platform/samsung/s3c-camif/camif-capture.c2
-rw-r--r--drivers/media/platform/samsung/s3c-camif/camif-core.c2
-rw-r--r--drivers/media/platform/samsung/s5p-g2d/g2d.c4
-rw-r--r--drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c21
-rw-r--r--drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c5
-rw-r--r--drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h1
-rw-r--r--drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c19
-rw-r--r--drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h4
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c2
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c2
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c2
-rw-r--r--drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c4
-rw-r--r--drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c2
-rw-r--r--drivers/media/platform/st/sti/delta/delta-v4l2.c6
-rw-r--r--drivers/media/platform/st/sti/hva/hva-v4l2.c4
-rw-r--r--drivers/media/platform/st/stm32/dma2d/dma2d.c4
-rw-r--r--drivers/media/platform/st/stm32/stm32-dcmi.c4
-rw-r--r--drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c6
-rw-r--r--drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c2
-rw-r--r--drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c2
-rw-r--r--drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c2
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c2
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c2
-rw-r--r--drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c2
-rw-r--r--drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c2
-rw-r--r--drivers/media/platform/sunxi/sun8i-di/sun8i-di.c4
-rw-r--r--drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c4
-rw-r--r--drivers/media/platform/ti/am437x/am437x-vpfe.c4
-rw-r--r--drivers/media/platform/ti/cal/cal-video.c2
-rw-r--r--drivers/media/platform/ti/cal/cal.c2
-rw-r--r--drivers/media/platform/ti/davinci/vpif.c2
-rw-r--r--drivers/media/platform/ti/davinci/vpif_capture.c4
-rw-r--r--drivers/media/platform/ti/davinci/vpif_display.c4
-rw-r--r--drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c10
-rw-r--r--drivers/media/platform/ti/omap/omap_vout.c4
-rw-r--r--drivers/media/platform/ti/omap/omap_voutdef.h2
-rw-r--r--drivers/media/platform/ti/omap3isp/isp.c2
-rw-r--r--drivers/media/platform/ti/omap3isp/ispvideo.c18
-rw-r--r--drivers/media/platform/ti/vpe/vpe.c4
-rw-r--r--drivers/media/platform/verisilicon/hantro_drv.c2
-rw-r--r--drivers/media/platform/verisilicon/hantro_v4l2.c20
-rw-r--r--drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c3
-rw-r--r--drivers/media/platform/via/via-camera.c4
-rw-r--r--drivers/media/platform/video-mux.c8
-rw-r--r--drivers/media/platform/xilinx/xilinx-csi2rxss.c2
-rw-r--r--drivers/media/platform/xilinx/xilinx-dma.c2
-rw-r--r--drivers/media/platform/xilinx/xilinx-tpg.c16
-rw-r--r--drivers/media/platform/xilinx/xilinx-vipp.c2
-rw-r--r--drivers/media/platform/xilinx/xilinx-vtc.c2
-rw-r--r--drivers/media/radio/radio-aimslab.c2
-rw-r--r--drivers/media/radio/radio-gemtek.c2
-rw-r--r--drivers/media/radio/radio-isa.c2
-rw-r--r--drivers/media/radio/radio-isa.h2
-rw-r--r--drivers/media/radio/radio-miropcm20.c2
-rw-r--r--drivers/media/radio/radio-rtrack2.c2
-rw-r--r--drivers/media/radio/radio-si476x.c2
-rw-r--r--drivers/media/radio/radio-terratec.c2
-rw-r--r--drivers/media/radio/radio-timb.c2
-rw-r--r--drivers/media/radio/radio-wl1273.c2
-rw-r--r--drivers/media/radio/radio-zoltrix.c2
-rw-r--r--drivers/media/radio/si4713/radio-platform-si4713.c2
-rw-r--r--drivers/media/radio/wl128x/fmdrv_common.c3
-rw-r--r--drivers/media/rc/Kconfig1
-rw-r--r--drivers/media/rc/ati_remote.c6
-rw-r--r--drivers/media/rc/gpio-ir-recv.c2
-rw-r--r--drivers/media/rc/gpio-ir-tx.c4
-rw-r--r--drivers/media/rc/img-ir/img-ir-core.c2
-rw-r--r--drivers/media/rc/ir-hix5hd2.c2
-rw-r--r--drivers/media/rc/lirc_dev.c13
-rw-r--r--drivers/media/rc/meson-ir.c2
-rw-r--r--drivers/media/rc/mtk-cir.c2
-rw-r--r--drivers/media/rc/st_rc.c2
-rw-r--r--drivers/media/rc/sunxi-cir.c2
-rw-r--r--drivers/media/test-drivers/vicodec/vicodec-core.c29
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_bridge.c2
-rw-r--r--drivers/media/test-drivers/vim2m.c4
-rw-r--r--drivers/media/test-drivers/vimc/vimc-capture.c6
-rw-r--r--drivers/media/test-drivers/vimc/vimc-core.c2
-rw-r--r--drivers/media/test-drivers/visl/visl-core.c2
-rw-r--r--drivers/media/test-drivers/visl/visl-video.c22
-rw-r--r--drivers/media/test-drivers/vivid/vivid-core.c4
-rw-r--r--drivers/media/test-drivers/vivid/vivid-core.h4
-rw-r--r--drivers/media/test-drivers/vivid/vivid-ctrls.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-meta-cap.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-meta-out.c2
-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-cap.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-vbi-out.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-vid-cap.c20
-rw-r--r--drivers/media/test-drivers/vivid/vivid-vid-out.c2
-rw-r--r--drivers/media/tuners/it913x.c2
-rw-r--r--drivers/media/tuners/mt2063.c2
-rw-r--r--drivers/media/tuners/mxl301rf.c2
-rw-r--r--drivers/media/tuners/mxl5005s.c2
-rw-r--r--drivers/media/tuners/tda18271-fe.c4
-rw-r--r--drivers/media/tuners/tea5761.c4
-rw-r--r--drivers/media/tuners/tea5767.c4
-rw-r--r--drivers/media/usb/airspy/airspy.c4
-rw-r--r--drivers/media/usb/au0828/au0828-vbi.c2
-rw-r--r--drivers/media/usb/au0828/au0828-video.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-417.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-avcore.c59
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-cards.c6
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-vbi.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-video.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx.h5
-rw-r--r--drivers/media/usb/dvb-usb-v2/anysee.c17
-rw-r--r--drivers/media/usb/dvb-usb/cxusb-analog.c2
-rw-r--r--drivers/media/usb/em28xx/em28xx-vbi.c2
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c2
-rw-r--r--drivers/media/usb/go7007/go7007-v4l2.c2
-rw-r--r--drivers/media/usb/gspca/gspca.c2
-rw-r--r--drivers/media/usb/gspca/ov534.c2
-rw-r--r--drivers/media/usb/hackrf/hackrf.c6
-rw-r--r--drivers/media/usb/msi2500/msi2500.c8
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-io.c4
-rw-r--r--drivers/media/usb/pwc/pwc-if.c4
-rw-r--r--drivers/media/usb/s2255/s2255drv.c2
-rw-r--r--drivers/media/usb/stk1160/stk1160-v4l.c2
-rw-r--r--drivers/media/usb/usbtv/usbtv-video.c2
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c148
-rw-r--r--drivers/media/usb/uvc/uvc_queue.c4
-rw-r--r--drivers/media/usb/uvc/uvc_status.c63
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c22
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h10
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls-api.c17
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c16
-rw-r--r--drivers/media/v4l2-core/v4l2-dv-timings.c199
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c3
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c27
-rw-r--r--drivers/memstick/core/memstick.c4
-rw-r--r--drivers/memstick/core/ms_block.c8
-rw-r--r--drivers/memstick/core/mspro_block.c2
-rw-r--r--drivers/memstick/host/r592.c2
-rw-r--r--drivers/message/fusion/mptlan.h3
-rw-r--r--drivers/message/fusion/mptsas.c4
-rw-r--r--drivers/mfd/88pm886.c1
-rw-r--r--drivers/mfd/Kconfig14
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/ab8500-sysctrl.c2
-rw-r--r--drivers/mfd/atmel-flexcom.c2
-rw-r--r--drivers/mfd/atmel-smc.c4
-rw-r--r--drivers/mfd/axp20x-i2c.c1
-rw-r--r--drivers/mfd/axp20x.c58
-rw-r--r--drivers/mfd/cgbc-core.c420
-rw-r--r--drivers/mfd/cros_ec_dev.c27
-rw-r--r--drivers/mfd/cs42l43.c65
-rw-r--r--drivers/mfd/da9052-spi.c2
-rw-r--r--drivers/mfd/exynos-lpass.c4
-rw-r--r--drivers/mfd/fsl-imx25-tsadc.c2
-rw-r--r--drivers/mfd/hi655x-pmic.c8
-rw-r--r--drivers/mfd/intel-lpss-acpi.c2
-rw-r--r--drivers/mfd/intel_soc_pmic_bxtwc.c177
-rw-r--r--drivers/mfd/intel_soc_pmic_chtwc.c2
-rw-r--r--drivers/mfd/intel_soc_pmic_crc.c9
-rw-r--r--drivers/mfd/ipaq-micro.c1
-rw-r--r--drivers/mfd/kempld-core.c2
-rw-r--r--drivers/mfd/mcp-sa11x0.c2
-rw-r--r--drivers/mfd/mt6397-core.c32
-rw-r--r--drivers/mfd/mt6397-irq.c23
-rw-r--r--drivers/mfd/mxs-lradc.c2
-rw-r--r--drivers/mfd/omap-usb-host.c2
-rw-r--r--drivers/mfd/omap-usb-tll.c2
-rw-r--r--drivers/mfd/pcf50633-adc.c2
-rw-r--r--drivers/mfd/qcom-pm8xxx.c2
-rw-r--r--drivers/mfd/rk8xx-core.c6
-rw-r--r--drivers/mfd/rohm-bd71828.c12
-rw-r--r--drivers/mfd/rohm-bd96801.c277
-rw-r--r--drivers/mfd/rt5033.c4
-rw-r--r--drivers/mfd/sec-core.c11
-rw-r--r--drivers/mfd/sm501.c2
-rw-r--r--drivers/mfd/stm32-timers.c2
-rw-r--r--drivers/mfd/syscon.c5
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c2
-rw-r--r--drivers/mfd/tps65010.c8
-rw-r--r--drivers/mfd/tps65911-comparator.c2
-rw-r--r--drivers/mfd/tqmx86.c115
-rw-r--r--drivers/mfd/twl-core.c26
-rw-r--r--drivers/mfd/twl4030-audio.c2
-rw-r--r--drivers/mfd/wcd934x.c2
-rw-r--r--drivers/misc/Kconfig25
-rw-r--r--drivers/misc/Makefile4
-rw-r--r--drivers/misc/apds990x.c12
-rw-r--r--drivers/misc/atmel-ssc.c4
-rw-r--r--drivers/misc/cardreader/alcor_pci.c2
-rw-r--r--drivers/misc/cardreader/rtsx_usb.c6
-rw-r--r--drivers/misc/eeprom/Kconfig4
-rw-r--r--drivers/misc/eeprom/at24.c4
-rw-r--r--drivers/misc/eeprom/eeprom_93cx6.c15
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c2
-rw-r--r--drivers/misc/isl29020.c2
-rw-r--r--drivers/misc/keba/Kconfig13
-rw-r--r--drivers/misc/keba/Makefile1
-rw-r--r--drivers/misc/keba/cp500.c558
-rw-r--r--drivers/misc/keba/lan9252.c359
-rw-r--r--drivers/misc/lan966x_pci.c215
-rw-r--r--drivers/misc/lan966x_pci.dtso177
-rw-r--r--drivers/misc/lkdtm/bugs.c2
-rw-r--r--drivers/misc/mei/bus.c2
-rw-r--r--drivers/misc/mei/platform-vsc.c2
-rw-r--r--drivers/misc/mei/vsc-fw-loader.c26
-rw-r--r--drivers/misc/mei/vsc-tp.c2
-rw-r--r--drivers/misc/ocxl/sysfs.c2
-rw-r--r--drivers/misc/rpmb-core.c9
-rw-r--r--drivers/misc/ti-st/Kconfig19
-rw-r--r--drivers/misc/ti-st/Makefile7
-rw-r--r--drivers/misc/ti-st/st_core.c918
-rw-r--r--drivers/misc/ti-st/st_kim.c839
-rw-r--r--drivers/misc/ti-st/st_ll.c156
-rw-r--r--drivers/mmc/core/Makefile2
-rw-r--r--drivers/mmc/core/block.c94
-rw-r--r--drivers/mmc/core/bus.c42
-rw-r--r--drivers/mmc/core/card.h10
-rw-r--r--drivers/mmc/core/core.c73
-rw-r--r--drivers/mmc/core/core.h17
-rw-r--r--drivers/mmc/core/mmc_ops.c24
-rw-r--r--drivers/mmc/core/mmc_ops.h1
-rw-r--r--drivers/mmc/core/mmc_test.c6
-rw-r--r--drivers/mmc/core/pwrseq_emmc.c2
-rw-r--r--drivers/mmc/core/pwrseq_sd8787.c2
-rw-r--r--drivers/mmc/core/pwrseq_simple.c48
-rw-r--r--drivers/mmc/core/quirks.h9
-rw-r--r--drivers/mmc/core/regulator.c34
-rw-r--r--drivers/mmc/core/sd.c44
-rw-r--r--drivers/mmc/core/sd.h4
-rw-r--r--drivers/mmc/core/sd_ops.c24
-rw-r--r--drivers/mmc/core/sd_ops.h3
-rw-r--r--drivers/mmc/core/sd_uhs2.c1304
-rw-r--r--drivers/mmc/core/sdio.c2
-rw-r--r--drivers/mmc/host/Kconfig11
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/alcor.c2
-rw-r--r--drivers/mmc/host/atmel-mci.c4
-rw-r--r--drivers/mmc/host/au1xmmc.c4
-rw-r--r--drivers/mmc/host/bcm2835.c33
-rw-r--r--drivers/mmc/host/cavium-octeon.c4
-rw-r--r--drivers/mmc/host/cb710-mmc.c2
-rw-r--r--drivers/mmc/host/davinci_mmc.c25
-rw-r--r--drivers/mmc/host/dw_mmc-bluefield.c2
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c2
-rw-r--r--drivers/mmc/host/dw_mmc-hi3798cv200.c2
-rw-r--r--drivers/mmc/host/dw_mmc-hi3798mv200.c2
-rw-r--r--drivers/mmc/host/dw_mmc-k3.c2
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c2
-rw-r--r--drivers/mmc/host/dw_mmc-rockchip.c2
-rw-r--r--drivers/mmc/host/dw_mmc-starfive.c2
-rw-r--r--drivers/mmc/host/dw_mmc.c6
-rw-r--r--drivers/mmc/host/jz4740_mmc.c2
-rw-r--r--drivers/mmc/host/litex_mmc.c2
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c4
-rw-r--r--drivers/mmc/host/meson-mx-sdhc-mmc.c2
-rw-r--r--drivers/mmc/host/meson-mx-sdio.c2
-rw-r--r--drivers/mmc/host/mmc_spi.c9
-rw-r--r--drivers/mmc/host/mmci.h2
-rw-r--r--drivers/mmc/host/moxart-mmc.c2
-rw-r--r--drivers/mmc/host/mtk-sd.c292
-rw-r--r--drivers/mmc/host/mvsdio.c2
-rw-r--r--drivers/mmc/host/mxcmmc.c2
-rw-r--r--drivers/mmc/host/mxs-mmc.c2
-rw-r--r--drivers/mmc/host/omap.c2
-rw-r--r--drivers/mmc/host/omap_hsmmc.c2
-rw-r--r--drivers/mmc/host/owl-mmc.c2
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/renesas_sdhi_internal_dmac.c2
-rw-r--r--drivers/mmc/host/renesas_sdhi_sys_dmac.c2
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c2
-rw-r--r--drivers/mmc/host/rtsx_usb_sdmmc.c2
-rw-r--r--drivers/mmc/host/sdhci-acpi.c2
-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-cadence.c2
-rw-r--r--drivers/mmc/host/sdhci-dove.c2
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c31
-rw-r--r--drivers/mmc/host/sdhci-esdhc-mcf.c2
-rw-r--r--drivers/mmc/host/sdhci-iproc.c2
-rw-r--r--drivers/mmc/host/sdhci-milbeaut.c2
-rw-r--r--drivers/mmc/host/sdhci-msm.c4
-rw-r--r--drivers/mmc/host/sdhci-npcm.c2
-rw-r--r--drivers/mmc/host/sdhci-of-arasan.c20
-rw-r--r--drivers/mmc/host/sdhci-of-aspeed.c4
-rw-r--r--drivers/mmc/host/sdhci-of-at91.c2
-rw-r--r--drivers/mmc/host/sdhci-of-dwcmshc.c2
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c2
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c2
-rw-r--r--drivers/mmc/host/sdhci-of-ma35d1.c2
-rw-r--r--drivers/mmc/host/sdhci-of-sparx5.c2
-rw-r--r--drivers/mmc/host/sdhci-omap.c2
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c16
-rw-r--r--drivers/mmc/host/sdhci-pci-gli.c471
-rw-r--r--drivers/mmc/host/sdhci-pci.h3
-rw-r--r--drivers/mmc/host/sdhci-pic32.c2
-rw-r--r--drivers/mmc/host/sdhci-pxav2.c2
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c2
-rw-r--r--drivers/mmc/host/sdhci-s3c.c2
-rw-r--r--drivers/mmc/host/sdhci-spear.c2
-rw-r--r--drivers/mmc/host/sdhci-sprd.c2
-rw-r--r--drivers/mmc/host/sdhci-st.c2
-rw-r--r--drivers/mmc/host/sdhci-tegra.c2
-rw-r--r--drivers/mmc/host/sdhci-uhs2.c1250
-rw-r--r--drivers/mmc/host/sdhci-uhs2.h188
-rw-r--r--drivers/mmc/host/sdhci-xenon.c2
-rw-r--r--drivers/mmc/host/sdhci.c281
-rw-r--r--drivers/mmc/host/sdhci.h75
-rw-r--r--drivers/mmc/host/sdhci_am654.c32
-rw-r--r--drivers/mmc/host/sdhci_f_sdh30.c2
-rw-r--r--drivers/mmc/host/sh_mmcif.c7
-rw-r--r--drivers/mmc/host/sunplus-mmc.c2
-rw-r--r--drivers/mmc/host/sunxi-mmc.c8
-rw-r--r--drivers/mmc/host/uniphier-sd.c2
-rw-r--r--drivers/mmc/host/usdhi6rol0.c2
-rw-r--r--drivers/mmc/host/wbsd.c2
-rw-r--r--drivers/mmc/host/wmt-sdmmc.c2
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c4
-rw-r--r--drivers/mtd/devices/bcm47xxsflash.c2
-rw-r--r--drivers/mtd/devices/docg3.c2
-rw-r--r--drivers/mtd/devices/phram.c2
-rw-r--r--drivers/mtd/devices/powernv_flash.c2
-rw-r--r--drivers/mtd/devices/spear_smi.c2
-rw-r--r--drivers/mtd/devices/st_spi_fsm.c2
-rw-r--r--drivers/mtd/hyperbus/hbmc-am654.c2
-rw-r--r--drivers/mtd/hyperbus/rpc-if.c9
-rw-r--r--drivers/mtd/lpddr/lpddr2_nvm.c2
-rw-r--r--drivers/mtd/maps/lantiq-flash.c2
-rw-r--r--drivers/mtd/maps/physmap-core.c2
-rw-r--r--drivers/mtd/maps/plat-ram.c2
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c2
-rw-r--r--drivers/mtd/maps/sa1100-flash.c2
-rw-r--r--drivers/mtd/maps/sun_uflash.c2
-rw-r--r--drivers/mtd/nand/ecc-mxic.c8
-rw-r--r--drivers/mtd/nand/ecc-sw-bch.c2
-rw-r--r--drivers/mtd/nand/ecc-sw-hamming.c2
-rw-r--r--drivers/mtd/nand/onenand/generic.c2
-rw-r--r--drivers/mtd/nand/onenand/onenand_omap2.c2
-rw-r--r--drivers/mtd/nand/onenand/onenand_samsung.c2
-rw-r--r--drivers/mtd/nand/raw/ams-delta.c2
-rw-r--r--drivers/mtd/nand/raw/arasan-nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/atmel/nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.c8
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.h2
-rw-r--r--drivers/mtd/nand/raw/au1550nd.c2
-rw-r--r--drivers/mtd/nand/raw/bcm47xxnflash/main.c2
-rw-r--r--drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c2
-rw-r--r--drivers/mtd/nand/raw/brcmnand/bcma_nand.c2
-rw-r--r--drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c2
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmnand.c2
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c2
-rw-r--r--drivers/mtd/nand/raw/brcmnand/iproc_nand.c2
-rw-r--r--drivers/mtd/nand/raw/cadence-nand-controller.c4
-rw-r--r--drivers/mtd/nand/raw/cs553x_nand.c2
-rw-r--r--drivers/mtd/nand/raw/davinci_nand.c60
-rw-r--r--drivers/mtd/nand/raw/denali_dt.c2
-rw-r--r--drivers/mtd/nand/raw/fsl_elbc_nand.c2
-rw-r--r--drivers/mtd/nand/raw/fsl_ifc_nand.c2
-rw-r--r--drivers/mtd/nand/raw/fsl_upm.c2
-rw-r--r--drivers/mtd/nand/raw/fsmc_nand.c2
-rw-r--r--drivers/mtd/nand/raw/gpio.c2
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c69
-rw-r--r--drivers/mtd/nand/raw/hisi504_nand.c2
-rw-r--r--drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c2
-rw-r--r--drivers/mtd/nand/raw/intel-nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_mlc.c2
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_slc.c2
-rw-r--r--drivers/mtd/nand/raw/marvell_nand.c2
-rw-r--r--drivers/mtd/nand/raw/meson_nand.c2
-rw-r--r--drivers/mtd/nand/raw/mpc5121_nfc.c2
-rw-r--r--drivers/mtd/nand/raw/mtk_nand.c2
-rw-r--r--drivers/mtd/nand/raw/mxc_nand.c2
-rw-r--r--drivers/mtd/nand/raw/mxic_nand.c2
-rw-r--r--drivers/mtd/nand/raw/nand_macronix.c2
-rw-r--r--drivers/mtd/nand/raw/ndfc.c2
-rw-r--r--drivers/mtd/nand/raw/omap2.c2
-rw-r--r--drivers/mtd/nand/raw/omap_elm.c2
-rw-r--r--drivers/mtd/nand/raw/orion_nand.c2
-rw-r--r--drivers/mtd/nand/raw/pasemi_nand.c2
-rw-r--r--drivers/mtd/nand/raw/pl35x-nand-controller.c4
-rw-r--r--drivers/mtd/nand/raw/plat_nand.c2
-rw-r--r--drivers/mtd/nand/raw/qcom_nandc.c4
-rw-r--r--drivers/mtd/nand/raw/r852.c4
-rw-r--r--drivers/mtd/nand/raw/renesas-nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/rockchip-nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/s3c2410.c2
-rw-r--r--drivers/mtd/nand/raw/sh_flctl.c2
-rw-r--r--drivers/mtd/nand/raw/sharpsl.c2
-rw-r--r--drivers/mtd/nand/raw/sm_common.c4
-rw-r--r--drivers/mtd/nand/raw/socrates_nand.c2
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c2
-rw-r--r--drivers/mtd/nand/raw/sunxi_nand.c2
-rw-r--r--drivers/mtd/nand/raw/technologic-nand-controller.c2
-rw-r--r--drivers/mtd/nand/raw/tegra_nand.c2
-rw-r--r--drivers/mtd/nand/raw/txx9ndfmc.c2
-rw-r--r--drivers/mtd/nand/raw/vf610_nfc.c2
-rw-r--r--drivers/mtd/nand/raw/xway_nand.c2
-rw-r--r--drivers/mtd/nand/spi/core.c2
-rw-r--r--drivers/mtd/nand/spi/winbond.c85
-rw-r--r--drivers/mtd/spi-nor/controllers/hisi-sfc.c2
-rw-r--r--drivers/mtd/spi-nor/controllers/nxp-spifi.c2
-rw-r--r--drivers/mtd/spi-nor/core.c5
-rw-r--r--drivers/mtd/spi-nor/core.h1
-rw-r--r--drivers/mtd/spi-nor/macronix.c99
-rw-r--r--drivers/mtd/spi-nor/sfdp.c4
-rw-r--r--drivers/mtd/spi-nor/sfdp.h1
-rw-r--r--drivers/mtd/spi-nor/spansion.c1
-rw-r--r--drivers/mtd/spi-nor/sysfs.c2
-rw-r--r--drivers/mtd/spi-nor/winbond.c1
-rw-r--r--drivers/mtd/tests/oobtest.c2
-rw-r--r--drivers/mtd/tests/pagetest.c2
-rw-r--r--drivers/mtd/tests/subpagetest.c2
-rw-r--r--drivers/mtd/ubi/attach.c12
-rw-r--r--drivers/mtd/ubi/fastmap-wl.c19
-rw-r--r--drivers/mtd/ubi/nvmem.c2
-rw-r--r--drivers/mtd/ubi/ubi.h3
-rw-r--r--drivers/mtd/ubi/vmt.c2
-rw-r--r--drivers/mtd/ubi/wl.c32
-rw-r--r--drivers/mtd/ubi/wl.h3
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/amt.c12
-rw-r--r--drivers/net/bareudp.c16
-rw-r--r--drivers/net/bonding/bond_main.c32
-rw-r--r--drivers/net/bonding/bond_options.c82
-rw-r--r--drivers/net/can/c_can/c_can_main.c7
-rw-r--r--drivers/net/can/cc770/Kconfig2
-rw-r--r--drivers/net/can/m_can/m_can.c3
-rw-r--r--drivers/net/can/rockchip/Kconfig3
-rw-r--r--drivers/net/can/sja1000/Kconfig2
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c8
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c10
-rw-r--r--drivers/net/can/vxcan.c12
-rw-r--r--drivers/net/dsa/b53/b53_common.c3
-rw-r--r--drivers/net/dsa/b53/b53_mmap.c2
-rw-r--r--drivers/net/dsa/b53/b53_srab.c2
-rw-r--r--drivers/net/dsa/bcm_sf2.c15
-rw-r--r--drivers/net/dsa/bcm_sf2.h5
-rw-r--r--drivers/net/dsa/bcm_sf2_cfp.c22
-rw-r--r--drivers/net/dsa/dsa_loop.c3
-rw-r--r--drivers/net/dsa/hirschmann/hellcreek.c10
-rw-r--r--drivers/net/dsa/lantiq_gswip.c2
-rw-r--r--drivers/net/dsa/microchip/ksz9477.c4
-rw-r--r--drivers/net/dsa/microchip/ksz9477_i2c.c14
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c315
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h60
-rw-r--r--drivers/net/dsa/microchip/ksz_ptp.c2
-rw-r--r--drivers/net/dsa/microchip/ksz_spi.c7
-rw-r--r--drivers/net/dsa/microchip/lan937x.h2
-rw-r--r--drivers/net/dsa/microchip/lan937x_main.c226
-rw-r--r--drivers/net/dsa/microchip/lan937x_reg.h4
-rw-r--r--drivers/net/dsa/mt7530-mmio.c2
-rw-r--r--drivers/net/dsa/mt7530.c49
-rw-r--r--drivers/net/dsa/mt7530.h12
-rw-r--r--drivers/net/dsa/mv88e6xxx/Kconfig10
-rw-r--r--drivers/net/dsa/mv88e6xxx/Makefile1
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c133
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h22
-rw-r--r--drivers/net/dsa/mv88e6xxx/devlink.c11
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1_vtu.c3
-rw-r--r--drivers/net/dsa/mv88e6xxx/leds.c839
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c1
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h133
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.c14
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.h8
-rw-r--r--drivers/net/dsa/ocelot/ocelot_ext.c2
-rw-r--r--drivers/net/dsa/ocelot/seville_vsc9953.c2
-rw-r--r--drivers/net/dsa/qca/qca8k-8xxx.c2
-rw-r--r--drivers/net/dsa/realtek/realtek-mdio.c2
-rw-r--r--drivers/net/dsa/realtek/realtek-smi.c2
-rw-r--r--drivers/net/dsa/realtek/rtl8365mb.c2
-rw-r--r--drivers/net/dsa/realtek/rtl8366rb.c2
-rw-r--r--drivers/net/dsa/rzn1_a5psw.c8
-rw-r--r--drivers/net/dsa/sja1105/sja1105.h2
-rw-r--r--drivers/net/dsa/sja1105/sja1105_ethtool.c7
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c85
-rw-r--r--drivers/net/dsa/sja1105/sja1105_mdio.c28
-rw-r--r--drivers/net/dsa/vitesse-vsc73xx-platform.c2
-rw-r--r--drivers/net/dsa/xrs700x/xrs700x.c6
-rw-r--r--drivers/net/dummy.c17
-rw-r--r--drivers/net/ethernet/3com/3c59x.c2
-rw-r--r--drivers/net/ethernet/8390/ax88796.c2
-rw-r--r--drivers/net/ethernet/8390/mcf8390.c2
-rw-r--r--drivers/net/ethernet/8390/ne.c2
-rw-r--r--drivers/net/ethernet/actions/owl-emac.c2
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c2
-rw-r--r--drivers/net/ethernet/allwinner/sun4i-emac.c2
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c2
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_com.c58
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_com.h32
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_ethtool.c14
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c42
-rw-r--r--drivers/net/ethernet/amd/amd8111e.h1
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c2
-rw-r--r--drivers/net/ethernet/amd/sunlance.c2
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c22
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-platform.c2
-rw-r--r--drivers/net/ethernet/apm/xgene-v2/main.c2
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c2
-rw-r--r--drivers/net/ethernet/apple/macmace.c2
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c73
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h8
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_hw.h3
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c6
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c132
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c43
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h21
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h32
-rw-r--r--drivers/net/ethernet/arc/emac_main.c27
-rw-r--r--drivers/net/ethernet/arc/emac_mdio.c9
-rw-r--r--drivers/net/ethernet/arc/emac_rockchip.c2
-rw-r--r--drivers/net/ethernet/atheros/ag71xx.c37
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig3
-rw-r--r--drivers/net/ethernet/broadcom/asp2/bcmasp.c2
-rw-r--r--drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c7
-rw-r--r--drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c3
-rw-r--r--drivers/net/ethernet/broadcom/bcm4908_enet.c2
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c16
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c48
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.h23
-rw-r--r--drivers/net/ethernet/broadcom/bgmac-platform.c2
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c68
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c495
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h64
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c160
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h43
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c172
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h1
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h173
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c136
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h46
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c53
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h1
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c10
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c2
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c83
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h2
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.h1
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_debugfs.c31
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c28
-rw-r--r--drivers/net/ethernet/calxeda/xgmac.c2
-rw-r--r--drivers/net/ethernet/cavium/common/cavium_ptp.c7
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c169
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h2
-rw-r--r--drivers/net/ethernet/cavium/octeon/octeon_mgmt.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c39
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h23
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c12
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c98
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c19
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c16
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/srq.c58
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/srq.h2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h1
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c9
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c4
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c2
-rw-r--r--drivers/net/ethernet/cirrus/ep93xx_eth.c2
-rw-r--r--drivers/net/ethernet/cirrus/mac89x0.c2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h62
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_ethtool.c8
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c386
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_res.c42
-rw-r--r--drivers/net/ethernet/cortina/gemini.c4
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c2
-rw-r--r--drivers/net/ethernet/dlink/Kconfig20
-rw-r--r--drivers/net/ethernet/dlink/Makefile1
-rw-r--r--drivers/net/ethernet/dlink/sundance.c1985
-rw-r--r--drivers/net/ethernet/dnet.c2
-rw-r--r--drivers/net/ethernet/engleder/tsnep_main.c2
-rw-r--r--drivers/net/ethernet/ethoc.c2
-rw-r--r--drivers/net/ethernet/ezchip/nps_enet.c2
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c32
-rw-r--r--drivers/net/ethernet/faraday/ftmac100.c2
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth.c48
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h2
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c40
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c15
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c9
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h2
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c9
-rw-r--r--drivers/net/ethernet/freescale/enetc/Kconfig40
-rw-r--r--drivers/net/ethernet/freescale/enetc/Makefile9
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c271
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h30
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc4_hw.h155
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc4_pf.c756
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_ethtool.c70
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_hw.h53
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c31
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c332
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.h21
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf_common.c336
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf_common.h19
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_qos.c2
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_vf.c17
-rw-r--r--drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c445
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c2
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c2
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx_phy.c4
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c11
-rw-r--r--drivers/net/ethernet/freescale/fman/fman.c1
-rw-r--r--drivers/net/ethernet/freescale/fman/fman.h3
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_dtsec.c1
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_memac.c1
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_port.c2
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_tgec.c1
-rw-r--r--drivers/net/ethernet/freescale/fman/mac.c49
-rw-r--r--drivers/net/ethernet/freescale/fman/mac.h2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c4
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-fec.c2
-rw-r--r--drivers/net/ethernet/freescale/fsl_pq_mdio.c2
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c9
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c8
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c36
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth_ethtool.c21
-rw-r--r--drivers/net/ethernet/fungible/funcore/fun_queue.c65
-rw-r--r--drivers/net/ethernet/fungible/funcore/fun_queue.h1
-rw-r--r--drivers/net/ethernet/google/Kconfig1
-rw-r--r--drivers/net/ethernet/google/gve/Makefile3
-rw-r--r--drivers/net/ethernet/google/gve/gve.h36
-rw-r--r--drivers/net/ethernet/google/gve/gve_adminq.c4
-rw-r--r--drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c311
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c66
-rw-r--r--drivers/net/ethernet/google/gve/gve_rx_dqo.c314
-rw-r--r--drivers/net/ethernet/google/gve/gve_utils.c1
-rw-r--r--drivers/net/ethernet/hisilicon/Kconfig18
-rw-r--r--drivers/net/ethernet/hisilicon/Makefile1
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/Makefile8
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h131
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c17
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h11
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c271
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h59
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c127
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h11
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c253
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c222
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h12
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h143
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c409
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h39
-rw-r--r--drivers/net/ethernet/hisilicon/hip04_eth.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hisi_femac.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hix5hd2_gmac.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hnae.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c20
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c13
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h4
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c72
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c31
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c66
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ethtool.c67
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c11
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c63
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c87
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c95
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c9
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c46
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c9
-rw-r--r--drivers/net/ethernet/hisilicon/hns_mdio.c2
-rw-r--r--drivers/net/ethernet/i825xx/sni_82596.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c2
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c44
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.c90
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.c49
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.c49
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.c49
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c45
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.h3
-rw-r--r--drivers/net/ethernet/intel/Kconfig1
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c15
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c17
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c17
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c15
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf.h23
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c161
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_prototype.h3
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_txrx.h2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_virtchnl.c157
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h17
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adapter.c22
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adapter.h22
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h26
-rw-r--r--drivers/net/ethernet/intel/ice/ice_base.c39
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c21
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ddp.c302
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ddp.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch.c3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c187
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.h39
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_fdir.h4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_flex_pipe.h3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_gnss.c4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_hw_autogen.h11
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c68
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c1487
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.h143
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_consts.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.c125
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.h80
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sriov.c3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.c4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.h4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx_lib.h1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_type.h1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.c26
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.h8
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_mbx.c32
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_mbx.h9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl.c428
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl.h11
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c6
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf.h4
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_ethtool.c11
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lib.c5
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.c4
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.h3
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_virtchnl.c3
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.h1
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.h1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c8
-rw-r--r--drivers/net/ethernet/intel/igbvf/igbvf.h3
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c3
-rw-r--r--drivers/net/ethernet/intel/igc/igc_diag.c3
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ethtool.c13
-rw-r--r--drivers/net/ethernet/intel/igc/igc_hw.h1
-rw-r--r--drivers/net/ethernet/intel/igc/igc_mac.c316
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c1
-rw-r--r--drivers/net/ethernet/intel/igc/igc_phy.c24
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h16
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h15
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c1
-rw-r--r--drivers/net/ethernet/korina.c2
-rw-r--r--drivers/net/ethernet/lantiq_etop.c2
-rw-r--r--drivers/net/ethernet/lantiq_xrx200.c2
-rw-r--r--drivers/net/ethernet/litex/litex_liteeth.c2
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c42
-rw-r--r--drivers/net/ethernet/marvell/mvmdio.c13
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c6
-rw-r--r--drivers/net/ethernet/marvell/mvneta_bm.c2
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c41
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c31
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c31
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/Kconfig8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/Makefile3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c70
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.h5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/common.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h7
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mbox.h75
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.c87
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.h18
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.h39
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c45
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c41
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c35
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c49
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c132
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c50
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c468
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h26
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c20
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/Makefile2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c9
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c62
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h90
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c49
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c9
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c88
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c15
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c303
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c25
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c31
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c19
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/rep.c864
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/rep.h54
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c16
-rw-r--r--drivers/net/ethernet/marvell/skge.c3
-rw-r--r--drivers/net/ethernet/marvell/sky2.c3
-rw-r--r--drivers/net/ethernet/mediatek/airoha_eth.c141
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_cq.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile63
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cq.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/dpll.c81
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c99
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c127
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/diag/qos_tracepoint.h86
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c33
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c1072
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h34
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c387
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/smfs.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c32
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/qos.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/rl.c58
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_action.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_action.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_buddy.c)4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_buddy.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_cmd.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_cmd.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_context.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_context.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_debug.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_debug.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/internal.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_internal.h)36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_matcher.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_matcher.h)6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pat_arg.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pat_arg.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pool.c)4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pool.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_prm.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_rule.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_rule.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_table.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_table.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/vport.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_vport.c)2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/vport.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_vport.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_action.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_arg.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_arg.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_buddy.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_buddy.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_cmd.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_definer.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_definer.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_fw.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_matcher.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ptrn.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_rule.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v2.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_table.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_table.c)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_types.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c)35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr_ste_v1.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr_ste_v1.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h (renamed from drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h)0
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/wq.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c66
-rw-r--r--drivers/net/ethernet/meta/Kconfig1
-rw-r--r--drivers/net/ethernet/meta/fbnic/Makefile8
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic.h26
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_csr.c148
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_csr.h122
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c68
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c145
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_fw.h7
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c193
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h28
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c81
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_mac.c22
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_mac.h7
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_netdev.c92
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_netdev.h18
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_pci.c30
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_rpc.c141
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_rpc.h4
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_time.c303
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_txrx.c168
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_txrx.h3
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8851_common.c20
-rw-r--r--drivers/net/ethernet/micrel/ks8851_par.c2
-rw-r--r--drivers/net/ethernet/microchip/Kconfig1
-rw-r--r--drivers/net/ethernet/microchip/Makefile1
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_main.c2
-rw-r--r--drivers/net/ethernet/microchip/lan969x/Kconfig5
-rw-r--r--drivers/net/ethernet/microchip/lan969x/Makefile13
-rw-r--r--drivers/net/ethernet/microchip/lan969x/lan969x.c353
-rw-r--r--drivers/net/ethernet/microchip/lan969x/lan969x.h65
-rw-r--r--drivers/net/ethernet/microchip/lan969x/lan969x_calendar.c191
-rw-r--r--drivers/net/ethernet/microchip/lan969x/lan969x_regs.c222
-rw-r--r--drivers/net/ethernet/microchip/lan969x/lan969x_vcap_ag_api.c3843
-rw-r--r--drivers/net/ethernet/microchip/lan969x/lan969x_vcap_impl.c85
-rw-r--r--drivers/net/ethernet/microchip/sparx5/Makefile2
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c128
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c5
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c34
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c12
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c10
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main.c307
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main.h208
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h4603
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c10
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c39
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_packet.c24
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_pgid.c15
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_police.c3
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_port.c122
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_port.h23
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_psfp.c49
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c59
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_qos.c11
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_qos.h2
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_regs.c222
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_regs.h247
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_sdlb.c25
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c33
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_tc.c8
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c9
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_vcap_ag_api.h2
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c48
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h21
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c47
-rw-r--r--drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c17
-rw-r--r--drivers/net/ethernet/microsoft/mana/gdma_main.c43
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c105
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_ethtool.c66
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.c2
-rw-r--r--drivers/net/ethernet/mscc/ocelot_flower.c54
-rw-r--r--drivers/net/ethernet/mscc/ocelot_net.c4
-rw-r--r--drivers/net/ethernet/mscc/ocelot_vsc7514.c2
-rw-r--r--drivers/net/ethernet/natsemi/jazzsonic.c2
-rw-r--r--drivers/net/ethernet/natsemi/macsonic.c2
-rw-r--r--drivers/net/ethernet/natsemi/ns83820.c2
-rw-r--r--drivers/net/ethernet/natsemi/xtsonic.c2
-rw-r--r--drivers/net/ethernet/neterion/s2io.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfd3/dp.c4
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfdk/dp.c4
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c4
-rw-r--r--drivers/net/ethernet/ni/nixge.c2
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c2
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c1
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_txrx.c2
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c14
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_debug.c1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hw.c1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c45
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_ethtool.c34
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c60
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c4
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii.c22
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac.c2
-rw-r--r--drivers/net/ethernet/qualcomm/qca_debug.c4
-rw-r--r--drivers/net/ethernet/qualcomm/qca_spi.c30
-rw-r--r--drivers/net/ethernet/qualcomm/qca_spi.h2
-rw-r--r--drivers/net/ethernet/realtek/r8169.h1
-rw-r--r--drivers/net/ethernet/realtek/r8169_firmware.c6
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c436
-rw-r--r--drivers/net/ethernet/realtek/r8169_phy_config.c36
-rw-r--r--drivers/net/ethernet/realtek/rtase/rtase.h9
-rw-r--r--drivers/net/ethernet/realtek/rtase/rtase_main.c53
-rw-r--r--drivers/net/ethernet/renesas/ravb.h6
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c103
-rw-r--r--drivers/net/ethernet/renesas/rswitch.c2
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c2
-rw-r--r--drivers/net/ethernet/rocker/rocker_main.c2
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c2
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c2
-rw-r--r--drivers/net/ethernet/sfc/ef10.c2
-rw-r--r--drivers/net/ethernet/sfc/ef100_ethtool.c1
-rw-r--r--drivers/net/ethernet/sfc/ef100_nic.c2
-rw-r--r--drivers/net/ethernet/sfc/ef100_rx.c5
-rw-r--r--drivers/net/ethernet/sfc/efx.c117
-rw-r--r--drivers/net/ethernet/sfc/efx.h1
-rw-r--r--drivers/net/ethernet/sfc/efx_channels.c6
-rw-r--r--drivers/net/ethernet/sfc/efx_channels.h7
-rw-r--r--drivers/net/ethernet/sfc/efx_common.c16
-rw-r--r--drivers/net/ethernet/sfc/efx_common.h1
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c1
-rw-r--r--drivers/net/ethernet/sfc/ethtool_common.c49
-rw-r--r--drivers/net/ethernet/sfc/falcon/efx.c8
-rw-r--r--drivers/net/ethernet/sfc/falcon/efx.h1
-rw-r--r--drivers/net/ethernet/sfc/falcon/ethtool.c34
-rw-r--r--drivers/net/ethernet/sfc/falcon/falcon.c2
-rw-r--r--drivers/net/ethernet/sfc/falcon/farch.c22
-rw-r--r--drivers/net/ethernet/sfc/falcon/net_driver.h2
-rw-r--r--drivers/net/ethernet/sfc/falcon/nic.c20
-rw-r--r--drivers/net/ethernet/sfc/falcon/nic.h7
-rw-r--r--drivers/net/ethernet/sfc/falcon/tx.c8
-rw-r--r--drivers/net/ethernet/sfc/falcon/tx.h3
-rw-r--r--drivers/net/ethernet/sfc/mae.c11
-rw-r--r--drivers/net/ethernet/sfc/mae.h1
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c76
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h10
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h49
-rw-r--r--drivers/net/ethernet/sfc/nic.c9
-rw-r--r--drivers/net/ethernet/sfc/nic_common.h2
-rw-r--r--drivers/net/ethernet/sfc/ptp.c7
-rw-r--r--drivers/net/ethernet/sfc/ptp.h3
-rw-r--r--drivers/net/ethernet/sfc/rx.c5
-rw-r--r--drivers/net/ethernet/sfc/rx_common.c3
-rw-r--r--drivers/net/ethernet/sfc/siena/ethtool_common.c46
-rw-r--r--drivers/net/ethernet/sfc/siena/net_driver.h2
-rw-r--r--drivers/net/ethernet/sfc/siena/nic.c14
-rw-r--r--drivers/net/ethernet/sfc/siena/nic_common.h5
-rw-r--r--drivers/net/ethernet/sfc/siena/ptp.c2
-rw-r--r--drivers/net/ethernet/sfc/siena/ptp.h2
-rw-r--r--drivers/net/ethernet/sfc/siena/siena.c2
-rw-r--r--drivers/net/ethernet/sfc/tx.c14
-rw-r--r--drivers/net/ethernet/sfc/tx.h3
-rw-r--r--drivers/net/ethernet/sfc/tx_common.c33
-rw-r--r--drivers/net/ethernet/sfc/tx_common.h4
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c2
-rw-r--r--drivers/net/ethernet/sgi/meth.c2
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c2
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c2
-rw-r--r--drivers/net/ethernet/socionext/netsec.c2
-rw-r--r--drivers/net/ethernet/socionext/sni_ave.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c72
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c273
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000.h12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c101
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4.h10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac5.c150
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac5.h26
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c31
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.c22
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h20
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c8
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c413
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h33
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c26
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c169
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c38
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c4
-rw-r--r--drivers/net/ethernet/sun/niu.c2
-rw-r--r--drivers/net/ethernet/sun/sunbmac.c2
-rw-r--r--drivers/net/ethernet/sun/sunqe.c2
-rw-r--r--drivers/net/ethernet/sunplus/spl2sw_driver.c2
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-nuss.c273
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-nuss.h15
-rw-r--r--drivers/net/ethernet/ti/cpsw.c2
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.c66
-rw-r--r--drivers/net/ethernet/ti/cpsw_new.c2
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c2
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c2
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth.c60
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth.h12
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c2
-rw-r--r--drivers/net/ethernet/ti/netcp_core.c2
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c1
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.h1
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c2
-rw-r--r--drivers/net/ethernet/vertexcom/mse102x.c9
-rw-r--r--drivers/net/ethernet/via/via-rhine.c2
-rw-r--r--drivers/net/ethernet/via/via-velocity.c2
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c24
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_main.c1
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c188
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h2
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_type.h9
-rw-r--r--drivers/net/ethernet/wiznet/w5100.c2
-rw-r--r--drivers/net/ethernet/wiznet/w5300.c2
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c2
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c6
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c23
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c2
-rw-r--r--drivers/net/fjes/fjes_ethtool.c64
-rw-r--r--drivers/net/fjes/fjes_main.c2
-rw-r--r--drivers/net/geneve.c4
-rw-r--r--drivers/net/gtp.c16
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c1
-rw-r--r--drivers/net/hamradio/scc.c4
-rw-r--r--drivers/net/hyperv/netvsc.c13
-rw-r--r--drivers/net/hyperv/netvsc_drv.c2
-rw-r--r--drivers/net/hyperv/rndis_filter.c9
-rw-r--r--drivers/net/ieee802154/fakelb.c2
-rw-r--r--drivers/net/ieee802154/mac802154_hwsim.c2
-rw-r--r--drivers/net/ifb.c17
-rw-r--r--drivers/net/ipa/ipa_main.c2
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c3
-rw-r--r--drivers/net/ipvlan/ipvlan_l3s.c6
-rw-r--r--drivers/net/macsec.c70
-rw-r--r--drivers/net/macvlan.c6
-rw-r--r--drivers/net/mctp/mctp-i2c.c3
-rw-r--r--drivers/net/mctp/mctp-i3c.c2
-rw-r--r--drivers/net/mctp/mctp-serial.c5
-rw-r--r--drivers/net/mdio.c172
-rw-r--r--drivers/net/mdio/mdio-aspeed.c2
-rw-r--r--drivers/net/mdio/mdio-bcm-iproc.c2
-rw-r--r--drivers/net/mdio/mdio-bcm-unimac.c2
-rw-r--r--drivers/net/mdio/mdio-gpio.c2
-rw-r--r--drivers/net/mdio/mdio-hisi-femac.c2
-rw-r--r--drivers/net/mdio/mdio-ipq4019.c7
-rw-r--r--drivers/net/mdio/mdio-ipq8064.c2
-rw-r--r--drivers/net/mdio/mdio-moxart.c2
-rw-r--r--drivers/net/mdio/mdio-mscc-miim.c2
-rw-r--r--drivers/net/mdio/mdio-mux-bcm-iproc.c2
-rw-r--r--drivers/net/mdio/mdio-mux-bcm6368.c2
-rw-r--r--drivers/net/mdio/mdio-mux-gpio.c2
-rw-r--r--drivers/net/mdio/mdio-mux-meson-g12a.c2
-rw-r--r--drivers/net/mdio/mdio-mux-meson-gxl.c2
-rw-r--r--drivers/net/mdio/mdio-mux-mmioreg.c2
-rw-r--r--drivers/net/mdio/mdio-mux-multiplexer.c2
-rw-r--r--drivers/net/mdio/mdio-octeon.c2
-rw-r--r--drivers/net/mdio/mdio-sun4i.c2
-rw-r--r--drivers/net/mdio/mdio-thunder.c4
-rw-r--r--drivers/net/mdio/mdio-xgene.c2
-rw-r--r--drivers/net/netconsole.c197
-rw-r--r--drivers/net/netdevsim/ethtool.c2
-rw-r--r--drivers/net/netdevsim/ipsec.c23
-rw-r--r--drivers/net/netdevsim/macsec.c56
-rw-r--r--drivers/net/netdevsim/netdev.c45
-rw-r--r--drivers/net/netkit.c102
-rw-r--r--drivers/net/pcs/pcs-rzn1-miic.c2
-rw-r--r--drivers/net/pcs/pcs-xpcs-nxp.c24
-rw-r--r--drivers/net/pcs/pcs-xpcs-wx.c56
-rw-r--r--drivers/net/pcs/pcs-xpcs.c641
-rw-r--r--drivers/net/pcs/pcs-xpcs.h38
-rw-r--r--drivers/net/phy/Kconfig21
-rw-r--r--drivers/net/phy/Makefile3
-rw-r--r--drivers/net/phy/adin.c6
-rw-r--r--drivers/net/phy/aquantia/aquantia.h1
-rw-r--r--drivers/net/phy/aquantia/aquantia_leds.c19
-rw-r--r--drivers/net/phy/aquantia/aquantia_main.c116
-rw-r--r--drivers/net/phy/bcm-phy-lib.c5
-rw-r--r--drivers/net/phy/dp83822.c31
-rw-r--r--drivers/net/phy/dp83848.c2
-rw-r--r--drivers/net/phy/dp83869.c20
-rw-r--r--drivers/net/phy/icplus.c3
-rw-r--r--drivers/net/phy/intel-xway.c253
-rw-r--r--drivers/net/phy/marvell-88q2xxx.c124
-rw-r--r--drivers/net/phy/marvell.c26
-rw-r--r--drivers/net/phy/mediatek/Kconfig27
-rw-r--r--drivers/net/phy/mediatek/Makefile4
-rw-r--r--drivers/net/phy/mediatek/mtk-ge-soc.c (renamed from drivers/net/phy/mediatek-ge-soc.c)419
-rw-r--r--drivers/net/phy/mediatek/mtk-ge.c (renamed from drivers/net/phy/mediatek-ge.c)31
-rw-r--r--drivers/net/phy/mediatek/mtk-phy-lib.c270
-rw-r--r--drivers/net/phy/mediatek/mtk.h89
-rw-r--r--drivers/net/phy/micrel.c8
-rw-r--r--drivers/net/phy/microchip_t1.c233
-rw-r--r--drivers/net/phy/microchip_t1s.c300
-rw-r--r--drivers/net/phy/mscc/mscc_main.c3
-rw-r--r--drivers/net/phy/mxl-gpy.c227
-rw-r--r--drivers/net/phy/nxp-c45-tja11xx.c36
-rw-r--r--drivers/net/phy/nxp-c45-tja11xx.h1
-rw-r--r--drivers/net/phy/nxp-cbtx.c2
-rw-r--r--drivers/net/phy/phy-c45.c36
-rw-r--r--drivers/net/phy/phy-core.c52
-rw-r--r--drivers/net/phy/phy.c52
-rw-r--r--drivers/net/phy/phy_device.c47
-rw-r--r--drivers/net/phy/phylink.c249
-rw-r--r--drivers/net/phy/qcom/qca83xx.c6
-rw-r--r--drivers/net/phy/realtek.c121
-rw-r--r--drivers/net/phy/sfp.c5
-rw-r--r--drivers/net/phy/smsc.c5
-rw-r--r--drivers/net/team/team_core.c3
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/net/usb/lan78xx.c40
-rw-r--r--drivers/net/usb/sr9700.c10
-rw-r--r--drivers/net/veth.c18
-rw-r--r--drivers/net/virtio_net.c573
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c8
-rw-r--r--drivers/net/vrf.c2
-rw-r--r--drivers/net/vxlan/vxlan_core.c127
-rw-r--r--drivers/net/vxlan/vxlan_mdb.c4
-rw-r--r--drivers/net/wan/framer/pef2256/pef2256.c2
-rw-r--r--drivers/net/wan/fsl_qmc_hdlc.c2
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c2
-rw-r--r--drivers/net/wan/ixp4xx_hss.c2
-rw-r--r--drivers/net/wireguard/device.c3
-rw-r--r--drivers/net/wireguard/selftest/allowedips.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c105
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c20
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.c1
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c5
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c3
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.c39
-rw-r--r--drivers/net/wireless/ath/ath12k/Kconfig10
-rw-r--r--drivers/net/wireless/ath/ath12k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath12k/ce.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c9
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h110
-rw-r--r--drivers/net/wireless/ath/ath12k/coredump.c51
-rw-r--r--drivers/net/wireless/ath/ath12k/coredump.h80
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c1358
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h444
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.c58
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.h7
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_mon.c122
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c16
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.c9
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.c12
-rw-r--r--drivers/net/wireless/ath/ath12k/hal_rx.h53
-rw-r--r--drivers/net/wireless/ath/ath12k/hif.h6
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c1850
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.h11
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.c5
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/p2p.c17
-rw-r--r--drivers/net/wireless/ath/ath12k/p2p.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c200
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.c13
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.h4
-rw-r--r--drivers/net/wireless/ath/ath12k/rx_desc.h88
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c30
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h8
-rw-r--r--drivers/net/wireless/ath/ath12k/wow.c87
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c8
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_aic.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c16
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c52
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c8
-rw-r--r--drivers/net/wireless/ath/wcn36xx/wcn36xx.h2
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c29
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h9
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c55
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c22
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c3
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c9
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h2
-rw-r--r--drivers/net/wireless/intel/ipw2x00/Kconfig11
-rw-r--r--drivers/net/wireless/intel/ipw2x00/Makefile7
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c9
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.h2
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.c25
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.h4
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw.h114
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_crypto.c246
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c (renamed from net/wireless/lib80211_crypt_ccmp.c)76
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c (renamed from net/wireless/lib80211_crypt_tkip.c)106
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_crypto_wep.c (renamed from net/wireless/lib80211_crypt_wep.c)73
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_module.c36
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_rx.c19
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_spy.c (renamed from net/wireless/wext-spy.c)63
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_tx.c4
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_wx.c43
-rw-r--r--drivers/net/wireless/intel/iwlegacy/3945.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/bz.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/sc.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/binding.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/context.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h69
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dump.c27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/coex.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c179
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c66
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c63
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c89
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c30
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/offloading.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c57
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c4
-rw-r--r--drivers/net/wireless/intersil/p54/p54spi.c4
-rw-r--r--drivers/net/wireless/marvell/libertas/Kconfig1
-rw-r--r--drivers/net/wireless/marvell/libertas/cfg.c1
-rw-r--r--drivers/net/wireless/marvell/libertas/mesh.h1
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cmdevt.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/fw.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/ioctl.h2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/join.c11
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_event.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_ioctl.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/tdls.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/util.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/soc.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/soc.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/main.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/soc.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/main.c5
-rw-r--r--drivers/net/wireless/microchip/wilc1000/cfg80211.c113
-rw-r--r--drivers/net/wireless/microchip/wilc1000/cfg80211.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/netdev.c37
-rw-r--r--drivers/net/wireless/microchip/wilc1000/sdio.c99
-rw-r--r--drivers/net/wireless/microchip/wilc1000/spi.c8
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan.c444
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan.h53
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c2
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.h1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00usb.c2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/core.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c11
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c79
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h10
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/efuse.c11
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c18
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/Kconfig33
-rw-r--r--drivers/net/wireless/realtek/rtw88/Makefile15
-rw-r--r--drivers/net/wireless/realtek/rtw88/coex.c37
-rw-r--r--drivers/net/wireless/realtek/rtw88/coex.h11
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c46
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h17
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac.c15
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac.h3
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c35
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h52
-rw-r--r--drivers/net/wireless/realtek/rtw88/pci.c4
-rw-r--r--drivers/net/wireless/realtek/rtw88/phy.c82
-rw-r--r--drivers/net/wireless/realtek/rtw88/reg.h174
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8703b.c83
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.c70
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723x.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8812a.c1102
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8812a.h10
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8812a_table.c2812
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8812a_table.h26
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8812au.c28
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821a.c1197
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821a.h10
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821a_table.c2350
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821a_table.h21
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821au.c28
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.c87
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.h24
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.c73
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.h12
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c.c82
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw88xxa.c1989
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw88xxa.h175
-rw-r--r--drivers/net/wireless/realtek/rtw88/rx.c82
-rw-r--r--drivers/net/wireless/realtek/rtw88/rx.h64
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.c11
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.h4
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c14
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.c310
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.h48
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.c384
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.h23
-rw-r--r--drivers/net/wireless/realtek/rtw89/coex.c391
-rw-r--r--drivers/net/wireless/realtek/rtw89/coex.h6
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c1091
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h512
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c144
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.c150
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse_be.c52
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c896
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h284
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c761
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h128
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c663
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac_be.c73
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c105
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h39
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci_be.c77
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c702
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h13
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy_be.c12
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.c109
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.h14
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/regd.c111
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.c18
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851be.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c13
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852ae.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b.c18
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_common.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852be.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bt.c18
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bte.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c17
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852ce.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8922a.c121
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c61
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8922ae.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/sar.c6
-rw-r--r--drivers/net/wireless/realtek/rtw89/ser.c37
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c217
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.h10
-rw-r--r--drivers/net/wireless/silabs/wfx/main.c17
-rw-r--r--drivers/net/wireless/st/cw1200/cw1200_spi.c2
-rw-r--r--drivers/net/wireless/st/cw1200/queue.c27
-rw-r--r--drivers/net/wireless/st/cw1200/queue.h1
-rw-r--r--drivers/net/wireless/ti/wl1251/sdio.c4
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c5
-rw-r--r--drivers/net/wireless/ti/wlcore/sdio.c13
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c12
-rw-r--r--drivers/net/wwan/qcom_bam_dmux.c2
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c2
-rw-r--r--drivers/net/wwan/t7xx/t7xx_modem_ops.c1
-rw-r--r--drivers/net/wwan/t7xx/t7xx_pci.c60
-rw-r--r--drivers/net/wwan/t7xx/t7xx_pci.h1
-rw-r--r--drivers/net/wwan/t7xx/t7xx_port.h3
-rw-r--r--drivers/net/wwan/t7xx/t7xx_port_proxy.c51
-rw-r--r--drivers/net/wwan/t7xx/t7xx_port_proxy.h1
-rw-r--r--drivers/net/wwan/t7xx/t7xx_port_wwan.c8
-rw-r--r--drivers/net/wwan/wwan_core.c10
-rw-r--r--drivers/ntb/hw/idt/ntb_hw_idt.c13
-rw-r--r--drivers/nvdimm/dax_devs.c4
-rw-r--r--drivers/nvdimm/nd.h7
-rw-r--r--drivers/nvdimm/nd_virtio.c2
-rw-r--r--drivers/nvdimm/pfn_devs.c2
-rw-r--r--drivers/nvdimm/pmem.c2
-rw-r--r--drivers/nvdimm/virtio_pmem.c24
-rw-r--r--drivers/nvme/host/apple.c2
-rw-r--r--drivers/nvme/host/core.c81
-rw-r--r--drivers/nvme/host/ioctl.c33
-rw-r--r--drivers/nvme/host/multipath.c23
-rw-r--r--drivers/nvme/host/nvme.h11
-rw-r--r--drivers/nvme/host/pci.c265
-rw-r--r--drivers/nvme/host/pr.c122
-rw-r--r--drivers/nvme/host/rdma.c4
-rw-r--r--drivers/nvme/host/trace.c58
-rw-r--r--drivers/nvme/host/zns.c2
-rw-r--r--drivers/nvme/target/Makefile2
-rw-r--r--drivers/nvme/target/admin-cmd.c295
-rw-r--r--drivers/nvme/target/configfs.c27
-rw-r--r--drivers/nvme/target/core.c64
-rw-r--r--drivers/nvme/target/fabrics-cmd.c7
-rw-r--r--drivers/nvme/target/nvmet.h67
-rw-r--r--drivers/nvme/target/pr.c1156
-rw-r--r--drivers/nvme/target/trace.c108
-rw-r--r--drivers/nvme/target/zns.c21
-rw-r--r--drivers/nvmem/Kconfig11
-rw-r--r--drivers/nvmem/Makefile2
-rw-r--r--drivers/nvmem/brcm_nvram.c2
-rw-r--r--drivers/nvmem/core.c22
-rw-r--r--drivers/nvmem/imx-iim.c10
-rw-r--r--drivers/nvmem/lpc18xx_otp.c2
-rw-r--r--drivers/nvmem/microchip-otpc.c2
-rw-r--r--drivers/nvmem/rcar-efuse.c142
-rw-r--r--drivers/of/.kunitconfig1
-rw-r--r--drivers/of/Kconfig8
-rw-r--r--drivers/of/address.c36
-rw-r--r--drivers/of/base.c84
-rw-r--r--drivers/of/cpu.c2
-rw-r--r--drivers/of/dynamic.c48
-rw-r--r--drivers/of/fdt.c23
-rw-r--r--drivers/of/fdt_address.c4
-rw-r--r--drivers/of/irq.c4
-rw-r--r--drivers/of/kexec.c2
-rw-r--r--drivers/of/kobj.c8
-rw-r--r--drivers/of/module.c4
-rw-r--r--drivers/of/of_numa.c3
-rw-r--r--drivers/of/of_private.h15
-rw-r--r--drivers/of/of_reserved_mem.c227
-rw-r--r--drivers/of/overlay.c19
-rw-r--r--drivers/of/overlay_test.c2
-rw-r--r--drivers/of/property.c109
-rw-r--r--drivers/of/resolver.c12
-rw-r--r--drivers/opp/core.c199
-rw-r--r--drivers/opp/of.c39
-rw-r--r--drivers/opp/opp.h7
-rw-r--r--drivers/pci/Kconfig11
-rw-r--r--drivers/pci/Makefile3
-rw-r--r--drivers/pci/bus.c132
-rw-r--r--drivers/pci/controller/cadence/pci-j721e.c39
-rw-r--r--drivers/pci/controller/cadence/pcie-cadence.c4
-rw-r--r--drivers/pci/controller/dwc/pci-exynos.c2
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c57
-rw-r--r--drivers/pci/controller/dwc/pci-keystone.c14
-rw-r--r--drivers/pci/controller/dwc/pcie-bt1.c2
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c38
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-host.c4
-rw-r--r--drivers/pci/controller/dwc/pcie-histb.c2
-rw-r--r--drivers/pci/controller/dwc/pcie-intel-gw.c2
-rw-r--r--drivers/pci/controller/dwc/pcie-kirin.c2
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom-ep.c8
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c19
-rw-r--r--drivers/pci/controller/dwc/pcie-rcar-gen4.c2
-rw-r--r--drivers/pci/controller/dwc/pcie-tegra194.c9
-rw-r--r--drivers/pci/controller/pci-aardvark.c2
-rw-r--r--drivers/pci/controller/pci-host-generic.c2
-rw-r--r--drivers/pci/controller/pci-mvebu.c2
-rw-r--r--drivers/pci/controller/pci-tegra.c4
-rw-r--r--drivers/pci/controller/pci-thunder-pem.c4
-rw-r--r--drivers/pci/controller/pci-xgene-msi.c2
-rw-r--r--drivers/pci/controller/pcie-altera-msi.c2
-rw-r--r--drivers/pci/controller/pcie-altera.c6
-rw-r--r--drivers/pci/controller/pcie-brcmstb.c2
-rw-r--r--drivers/pci/controller/pcie-hisi-error.c2
-rw-r--r--drivers/pci/controller/pcie-iproc-platform.c2
-rw-r--r--drivers/pci/controller/pcie-mediatek-gen3.c77
-rw-r--r--drivers/pci/controller/pcie-mediatek.c2
-rw-r--r--drivers/pci/controller/pcie-mt7621.c2
-rw-r--r--drivers/pci/controller/pcie-rcar-host.c4
-rw-r--r--drivers/pci/controller/pcie-rockchip-ep.c440
-rw-r--r--drivers/pci/controller/pcie-rockchip-host.c6
-rw-r--r--drivers/pci/controller/pcie-rockchip.c21
-rw-r--r--drivers/pci/controller/pcie-rockchip.h24
-rw-r--r--drivers/pci/controller/pcie-xilinx-nwl.c2
-rw-r--r--drivers/pci/controller/plda/pcie-microchip-host.c126
-rw-r--r--drivers/pci/controller/plda/pcie-starfive.c12
-rw-r--r--drivers/pci/controller/vmd.c17
-rw-r--r--drivers/pci/devres.c67
-rw-r--r--drivers/pci/doe.c14
-rw-r--r--drivers/pci/ecam.c2
-rw-r--r--drivers/pci/endpoint/functions/pci-epf-mhi.c6
-rw-r--r--drivers/pci/endpoint/functions/pci-epf-test.c378
-rw-r--r--drivers/pci/endpoint/pci-epc-core.c193
-rw-r--r--drivers/pci/endpoint/pci-epc-mem.c9
-rw-r--r--drivers/pci/hotplug/Kconfig10
-rw-r--r--drivers/pci/hotplug/Makefile1
-rw-r--r--drivers/pci/hotplug/acpiphp_ampere_altra.c2
-rw-r--r--drivers/pci/hotplug/cpci_hotplug.h1
-rw-r--r--drivers/pci/hotplug/cpqphp_pci.c47
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c1
-rw-r--r--drivers/pci/hotplug/octep_hp.c427
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c8
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c5
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c2
-rw-r--r--drivers/pci/iov.c6
-rw-r--r--drivers/pci/of.c27
-rw-r--r--drivers/pci/of_property.c2
-rw-r--r--drivers/pci/p2pdma.c2
-rw-r--r--drivers/pci/pci-sysfs.c68
-rw-r--r--drivers/pci/pci.c80
-rw-r--r--drivers/pci/pci.h79
-rw-r--r--drivers/pci/pcie/Makefile2
-rw-r--r--drivers/pci/pcie/aer.c15
-rw-r--r--drivers/pci/pcie/aspm.c98
-rw-r--r--drivers/pci/pcie/bwctrl.c366
-rw-r--r--drivers/pci/pcie/portdrv.c9
-rw-r--r--drivers/pci/pcie/portdrv.h6
-rw-r--r--drivers/pci/probe.c77
-rw-r--r--drivers/pci/pwrctl/Makefile6
-rw-r--r--drivers/pci/pwrctl/core.c157
-rw-r--r--drivers/pci/pwrctrl/Kconfig (renamed from drivers/pci/pwrctl/Kconfig)0
-rw-r--r--drivers/pci/pwrctrl/Makefile6
-rw-r--r--drivers/pci/pwrctrl/core.c148
-rw-r--r--drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c (renamed from drivers/pci/pwrctl/pci-pwrctl-pwrseq.c)50
-rw-r--r--drivers/pci/quirks.c71
-rw-r--r--drivers/pci/remove.c37
-rw-r--r--drivers/pci/setup-bus.c41
-rw-r--r--drivers/pci/setup-res.c7
-rw-r--r--drivers/pci/slot.c24
-rw-r--r--drivers/pci/tph.c547
-rw-r--r--drivers/pci/vpd.c2
-rw-r--r--drivers/pcmcia/soc_common.c12
-rw-r--r--drivers/peci/controller/peci-npcm.c2
-rw-r--r--drivers/perf/Kconfig7
-rw-r--r--drivers/perf/Makefile1
-rw-r--r--drivers/perf/alibaba_uncore_drw_pmu.c2
-rw-r--r--drivers/perf/amlogic/meson_g12_ddr_pmu.c2
-rw-r--r--drivers/perf/arm-cci.c2
-rw-r--r--drivers/perf/arm-ccn.c2
-rw-r--r--drivers/perf/arm-cmn.c6
-rw-r--r--drivers/perf/arm-ni.c1
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.c2
-rw-r--r--drivers/perf/arm_dmc620_pmu.c2
-rw-r--r--drivers/perf/arm_dsu_pmu.c2
-rw-r--r--drivers/perf/arm_pmuv3.c32
-rw-r--r--drivers/perf/arm_smmuv3_pmu.c21
-rw-r--r--drivers/perf/arm_spe_pmu.c2
-rw-r--r--drivers/perf/cxl_pmu.c9
-rw-r--r--drivers/perf/dwc_pcie_pmu.c16
-rw-r--r--drivers/perf/fsl_imx8_ddr_perf.c2
-rw-r--r--drivers/perf/fsl_imx9_ddr_perf.c7
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c2
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c2
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_hha_pmu.c2
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c2
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_pa_pmu.c2
-rw-r--r--drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c2
-rw-r--r--drivers/perf/marvell_cn10k_ddr_pmu.c2
-rw-r--r--drivers/perf/marvell_cn10k_tad_pmu.c2
-rw-r--r--drivers/perf/marvell_pem_pmu.c425
-rw-r--r--drivers/perf/qcom_l2_pmu.c2
-rw-r--r--drivers/perf/riscv_pmu_sbi.c4
-rw-r--r--drivers/perf/thunderx2_pmu.c2
-rw-r--r--drivers/perf/xgene_pmu.c2
-rw-r--r--drivers/phy/Kconfig11
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c8
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb2.c54
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init.c435
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb.c2
-rw-r--r--drivers/phy/cadence/cdns-dphy.c2
-rw-r--r--drivers/phy/cadence/phy-cadence-sierra.c2
-rw-r--r--drivers/phy/cadence/phy-cadence-torrent.c4
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c6
-rw-r--r--drivers/phy/freescale/phy-fsl-lynx-28g.c6
-rw-r--r--drivers/phy/freescale/phy-fsl-samsung-hdmi.c608
-rw-r--r--drivers/phy/intel/phy-intel-lgm-combo.c2
-rw-r--r--drivers/phy/marvell/phy-mvebu-cp110-utmi.c16
-rw-r--r--drivers/phy/microchip/sparx5_serdes.c195
-rw-r--r--drivers/phy/microchip/sparx5_serdes.h44
-rw-r--r--drivers/phy/microchip/sparx5_serdes_regs.h746
-rw-r--r--drivers/phy/motorola/phy-cpcap-usb.c2
-rw-r--r--drivers/phy/motorola/phy-mapphone-mdm6600.c2
-rw-r--r--drivers/phy/phy-airoha-pcie-regs.h6
-rw-r--r--drivers/phy/phy-airoha-pcie.c8
-rw-r--r--drivers/phy/phy-lgm-usb.c2
-rw-r--r--drivers/phy/phy-nxp-ptn3222.c123
-rw-r--r--drivers/phy/qualcomm/phy-qcom-apq8064-sata.c10
-rw-r--r--drivers/phy/qualcomm/phy-qcom-edp.c74
-rw-r--r--drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c8
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-combo.c8
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcie.c214
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h25
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h19
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usb.c65
-rw-r--r--drivers/phy/realtek/phy-rtk-usb2.c4
-rw-r--r--drivers/phy/realtek/phy-rtk-usb3.c4
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-pcie.c8
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb2.c2
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb3.c8
-rw-r--r--drivers/phy/renesas/r8a779f0-ether-serdes.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-csidphy.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-hdmi.c4
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c200
-rw-r--r--drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c17
-rw-r--r--drivers/phy/rockchip/phy-rockchip-typec.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-usbdp.c41
-rw-r--r--drivers/phy/st/Kconfig11
-rw-r--r--drivers/phy/st/Makefile1
-rw-r--r--drivers/phy/st/phy-stm32-combophy.c598
-rw-r--r--drivers/phy/st/phy-stm32-usbphyc.c2
-rw-r--r--drivers/phy/tegra/xusb.c4
-rw-r--r--drivers/phy/ti/phy-am654-serdes.c2
-rw-r--r--drivers/phy/ti/phy-da8xx-usb.c4
-rw-r--r--drivers/phy/ti/phy-dm816x-usb.c2
-rw-r--r--drivers/phy/ti/phy-gmii-sel.c3
-rw-r--r--drivers/phy/ti/phy-j721e-wiz.c2
-rw-r--r--drivers/phy/ti/phy-omap-usb2.c2
-rw-r--r--drivers/phy/ti/phy-ti-pipe3.c2
-rw-r--r--drivers/phy/ti/phy-twl4030-usb.c2
-rw-r--r--drivers/phy/xilinx/phy-zynqmp.c2
-rw-r--r--drivers/pinctrl/Kconfig26
-rw-r--r--drivers/pinctrl/Makefile3
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c4
-rw-r--r--drivers/pinctrl/bcm/pinctrl-iproc-gpio.c2
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-madera-core.c2
-rw-r--r--drivers/pinctrl/core.c3
-rw-r--r--drivers/pinctrl/core.h1
-rw-r--r--drivers/pinctrl/freescale/Kconfig93
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c6
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx1.c228
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx27.c350
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-elkhartlake.c38
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c12
-rw-r--r--drivers/pinctrl/mediatek/Kconfig17
-rw-r--r--drivers/pinctrl/mediatek/Makefile1
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-airoha.c2971
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-37xx.c2
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.c2
-rw-r--r--drivers/pinctrl/nxp/pinctrl-s32g2.c52
-rw-r--r--drivers/pinctrl/pinctrl-amd.c4
-rw-r--r--drivers/pinctrl/pinctrl-amd.h4
-rw-r--r--drivers/pinctrl/pinctrl-artpec6.c2
-rw-r--r--drivers/pinctrl/pinctrl-aw9523.c63
-rw-r--r--drivers/pinctrl/pinctrl-cy8c95x0.c142
-rw-r--r--drivers/pinctrl/pinctrl-k210.c17
-rw-r--r--drivers/pinctrl/pinctrl-k230.c641
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08.c2
-rw-r--r--drivers/pinctrl/pinctrl-ocelot.c203
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c6
-rw-r--r--drivers/pinctrl/pinctrl-single.c3
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c4
-rw-r--r--drivers/pinctrl/pinctrl-sx150x.c4
-rw-r--r--drivers/pinctrl/pinctrl-tb10x.c2
-rw-r--r--drivers/pinctrl/pinctrl-th1520.c918
-rw-r--r--drivers/pinctrl/pinctrl-xway.c2
-rw-r--r--drivers/pinctrl/pinctrl-zynqmp.c98
-rw-r--r--drivers/pinctrl/pinmux.c173
-rw-r--r--drivers/pinctrl/qcom/Kconfig.msm39
-rw-r--r--drivers/pinctrl/qcom/Makefile5
-rw-r--r--drivers/pinctrl/qcom/pinctrl-apq8064.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-apq8084.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq4019.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5018.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5332.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq5424.c792
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq6018.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq8064.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq8074.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq9574.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-mdm9607.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-mdm9615.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8226.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8660.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8909.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8916.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8953.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8960.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8976.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8994.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8996.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8998.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8x74.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcm2290.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcs404.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcs615.c1107
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcs8300.c1246
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qdf2xxx.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qdu1000.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sa8775p.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sar2130p.c1505
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7180.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc7280.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8180x.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8280xp-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sc8280xp.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm660.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm670.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm845.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx55.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx65.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdx75.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm4250-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm4450.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6115-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6115.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6125.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6350.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm6375.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm7150.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8150.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8250.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8350.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8450-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8450.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8550-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8550.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8650-lpass-lpi.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8650.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sm8750.c1729
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c8
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-mpp.c3
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c4
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-x1e80100.c2
-rw-r--r--drivers/pinctrl/renesas/Kconfig1
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rza1.c7
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rza2.c3
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzg2l.c70
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzn1.c2
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos-arm64.c431
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.h10
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c6
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h3
-rw-r--r--drivers/pinctrl/sophgo/Kconfig2
-rw-r--r--drivers/pinctrl/spacemit/Kconfig17
-rw-r--r--drivers/pinctrl/spacemit/Makefile3
-rw-r--r--drivers/pinctrl/spacemit/pinctrl-k1.c1051
-rw-r--r--drivers/pinctrl/spacemit/pinctrl-k1.h40
-rw-r--r--drivers/pinctrl/sprd/pinctrl-sprd-sc9860.c2
-rw-r--r--drivers/platform/chrome/Kconfig11
-rw-r--r--drivers/platform/chrome/Makefile1
-rw-r--r--drivers/platform/chrome/chromeos_of_hw_prober.c154
-rw-r--r--drivers/platform/chrome/cros_ec_chardev.c2
-rw-r--r--drivers/platform/chrome/cros_ec_debugfs.c2
-rw-r--r--drivers/platform/chrome/cros_ec_i2c.c2
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c2
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c2
-rw-r--r--drivers/platform/chrome/cros_ec_sysfs.c2
-rw-r--r--drivers/platform/chrome/cros_ec_typec.c3
-rw-r--r--drivers/platform/chrome/cros_ec_vbc.c2
-rw-r--r--drivers/platform/chrome/cros_hps_i2c.c2
-rw-r--r--drivers/platform/chrome/cros_typec_switch.c2
-rw-r--r--drivers/platform/chrome/cros_usbpd_logger.c2
-rw-r--r--drivers/platform/chrome/cros_usbpd_notify.c4
-rw-r--r--drivers/platform/chrome/wilco_ec/core.c2
-rw-r--r--drivers/platform/chrome/wilco_ec/debugfs.c2
-rw-r--r--drivers/platform/chrome/wilco_ec/telemetry.c2
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-gpio.c4
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu.h42
-rw-r--r--drivers/platform/goldfish/goldfish_pipe.c3
-rw-r--r--drivers/platform/surface/surface_aggregator_registry.c19
-rw-r--r--drivers/platform/x86/Kconfig22
-rw-r--r--drivers/platform/x86/acer-wmi.c7
-rw-r--r--drivers/platform/x86/adv_swbutton.c2
-rw-r--r--drivers/platform/x86/amd/Kconfig18
-rw-r--r--drivers/platform/x86/amd/Makefile5
-rw-r--r--drivers/platform/x86/amd/hsmp.c988
-rw-r--r--drivers/platform/x86/amd/hsmp/Kconfig47
-rw-r--r--drivers/platform/x86/amd/hsmp/Makefile12
-rw-r--r--drivers/platform/x86/amd/hsmp/acpi.c378
-rw-r--r--drivers/platform/x86/amd/hsmp/hsmp.c408
-rw-r--r--drivers/platform/x86/amd/hsmp/hsmp.h66
-rw-r--r--drivers/platform/x86/amd/hsmp/plat.c338
-rw-r--r--drivers/platform/x86/amd/pmc/pmc.c7
-rw-r--r--drivers/platform/x86/amd/pmf/Kconfig1
-rw-r--r--drivers/platform/x86/amd/pmf/acpi.c46
-rw-r--r--drivers/platform/x86/amd/pmf/core.c11
-rw-r--r--drivers/platform/x86/amd/pmf/pmf.h6
-rw-r--r--drivers/platform/x86/amd/pmf/spc.c1
-rw-r--r--drivers/platform/x86/amd/pmf/tee-if.c8
-rw-r--r--drivers/platform/x86/amd/x3d_vcache.c176
-rw-r--r--drivers/platform/x86/amilo-rfkill.c6
-rw-r--r--drivers/platform/x86/asus-laptop.c4
-rw-r--r--drivers/platform/x86/asus-wmi.c90
-rw-r--r--drivers/platform/x86/barco-p50-gpio.c2
-rw-r--r--drivers/platform/x86/classmate-laptop.c7
-rw-r--r--drivers/platform/x86/compal-laptop.c61
-rw-r--r--drivers/platform/x86/dell/Kconfig2
-rw-r--r--drivers/platform/x86/dell/alienware-wmi.c577
-rw-r--r--drivers/platform/x86/dell/dcdbas.c13
-rw-r--r--drivers/platform/x86/dell/dell-smbios-base.c1
-rw-r--r--drivers/platform/x86/dell/dell-smo8800.c2
-rw-r--r--drivers/platform/x86/dell/dell-uart-backlight.c2
-rw-r--r--drivers/platform/x86/dell/dell-wmi-base.c6
-rw-r--r--drivers/platform/x86/eeepc-laptop.c9
-rw-r--r--drivers/platform/x86/hp/Kconfig1
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c11
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c2
-rw-r--r--drivers/platform/x86/hp/hp_accel.c2
-rw-r--r--drivers/platform/x86/hp/tc1100-wmi.c2
-rw-r--r--drivers/platform/x86/huawei-wmi.c2
-rw-r--r--drivers/platform/x86/ideapad-laptop.c5
-rw-r--r--drivers/platform/x86/intel/Kconfig2
-rw-r--r--drivers/platform/x86/intel/Makefile68
-rw-r--r--drivers/platform/x86/intel/bxtwc_tmu.c24
-rw-r--r--drivers/platform/x86/intel/bytcrc_pwrsrc.c2
-rw-r--r--drivers/platform/x86/intel/chtdc_ti_pwrbtn.c2
-rw-r--r--drivers/platform/x86/intel/chtwc_int33fe.c2
-rw-r--r--drivers/platform/x86/intel/hid.c9
-rw-r--r--drivers/platform/x86/intel/int0002_vgpio.c4
-rw-r--r--drivers/platform/x86/intel/int1092/intel_sar.c2
-rw-r--r--drivers/platform/x86/intel/int3472/discrete.c2
-rw-r--r--drivers/platform/x86/intel/mrfld_pwrbtn.c2
-rw-r--r--drivers/platform/x86/intel/plr_tpmi.c (renamed from drivers/platform/x86/intel/intel_plr_tpmi.c)0
-rw-r--r--drivers/platform/x86/intel/pmc/arl.c3
-rw-r--r--drivers/platform/x86/intel/pmc/cnp.c53
-rw-r--r--drivers/platform/x86/intel/pmc/core.c2
-rw-r--r--drivers/platform/x86/intel/pmc/lnl.c3
-rw-r--r--drivers/platform/x86/intel/pmc/mtl.c3
-rw-r--r--drivers/platform/x86/intel/pmt/class.c12
-rw-r--r--drivers/platform/x86/intel/pmt/class.h2
-rw-r--r--drivers/platform/x86/intel/pmt/telemetry.c2
-rw-r--r--drivers/platform/x86/intel/sdsi.c2
-rw-r--r--drivers/platform/x86/intel/telemetry/pltdrv.c2
-rw-r--r--drivers/platform/x86/intel/vbtn.c2
-rw-r--r--drivers/platform/x86/intel/vsec.c6
-rw-r--r--drivers/platform/x86/intel/vsec_tpmi.c (renamed from drivers/platform/x86/intel/tpmi.c)2
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c140
-rw-r--r--drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c2
-rw-r--r--drivers/platform/x86/lenovo-yogabook.c2
-rw-r--r--drivers/platform/x86/mlx-platform.c2
-rw-r--r--drivers/platform/x86/p2sb.c1
-rw-r--r--drivers/platform/x86/panasonic-laptop.c10
-rw-r--r--drivers/platform/x86/samsung-q10.c2
-rw-r--r--drivers/platform/x86/sel3350-platform.c2
-rw-r--r--drivers/platform/x86/serial-multi-instantiate.c2
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt-apollolake.c2
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt-elkhartlake.c2
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt-f7188x.c2
-rw-r--r--drivers/platform/x86/siemens/simatic-ipc-batt.c2
-rw-r--r--drivers/platform/x86/think-lmi.c149
-rw-r--r--drivers/platform/x86/think-lmi.h6
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c28
-rw-r--r--drivers/platform/x86/wmi.c98
-rw-r--r--drivers/platform/x86/x86-android-tablets/Kconfig4
-rw-r--r--drivers/platform/x86/x86-android-tablets/core.c60
-rw-r--r--drivers/platform/x86/x86-android-tablets/dmi.c10
-rw-r--r--drivers/platform/x86/x86-android-tablets/other.c165
-rw-r--r--drivers/platform/x86/x86-android-tablets/x86-android-tablets.h2
-rw-r--r--drivers/platform/x86/xo1-rfkill.c2
-rw-r--r--drivers/pmdomain/arm/scmi_perf_domain.c3
-rw-r--r--drivers/pmdomain/core.c125
-rw-r--r--drivers/pmdomain/imx/gpc.c4
-rw-r--r--drivers/pmdomain/imx/gpcv2.c4
-rw-r--r--drivers/pmdomain/imx/imx93-blk-ctrl.c4
-rw-r--r--drivers/pmdomain/mediatek/mt6735-pm-domains.h96
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c17
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.h2
-rw-r--r--drivers/pmdomain/qcom/rpmhpd.c87
-rw-r--r--drivers/pmdomain/ti/ti_sci_pm_domains.c25
-rw-r--r--drivers/power/reset/Kconfig1
-rw-r--r--drivers/power/reset/at91-poweroff.c2
-rw-r--r--drivers/power/reset/at91-reset.c2
-rw-r--r--drivers/power/reset/at91-sama5d2_shdwc.c2
-rw-r--r--drivers/power/reset/keystone-reset.c2
-rw-r--r--drivers/power/reset/ltc2952-poweroff.c2
-rw-r--r--drivers/power/reset/qnap-poweroff.c2
-rw-r--r--drivers/power/reset/syscon-reboot.c3
-rw-r--r--drivers/power/sequencing/Kconfig1
-rw-r--r--drivers/power/sequencing/pwrseq-qcom-wcn.c101
-rw-r--r--drivers/power/supply/88pm860x_battery.c4
-rw-r--r--drivers/power/supply/Kconfig10
-rw-r--r--drivers/power/supply/Makefile1
-rw-r--r--drivers/power/supply/ab8500_bmdata.c4
-rw-r--r--drivers/power/supply/ab8500_btemp.c4
-rw-r--r--drivers/power/supply/ab8500_chargalg.c2
-rw-r--r--drivers/power/supply/ab8500_charger.c2
-rw-r--r--drivers/power/supply/ab8500_fg.c2
-rw-r--r--drivers/power/supply/acer_a500_battery.c9
-rw-r--r--drivers/power/supply/act8945a_charger.c2
-rw-r--r--drivers/power/supply/adp5061.c2
-rw-r--r--drivers/power/supply/axp20x_battery.c33
-rw-r--r--drivers/power/supply/axp20x_usb_power.c33
-rw-r--r--drivers/power/supply/bq27xxx_battery.c40
-rw-r--r--drivers/power/supply/charger-manager.c7
-rw-r--r--drivers/power/supply/cpcap-battery.c2
-rw-r--r--drivers/power/supply/cpcap-charger.c2
-rw-r--r--drivers/power/supply/cros_usbpd-charger.c4
-rw-r--r--drivers/power/supply/da9030_battery.c6
-rw-r--r--drivers/power/supply/da9052-battery.c2
-rw-r--r--drivers/power/supply/da9150-charger.c2
-rw-r--r--drivers/power/supply/generic-adc-battery.c4
-rw-r--r--drivers/power/supply/ipaq_micro_battery.c2
-rw-r--r--drivers/power/supply/isp1704_charger.c2
-rw-r--r--drivers/power/supply/lenovo_yoga_c630_battery.c14
-rw-r--r--drivers/power/supply/lp8788-charger.c2
-rw-r--r--drivers/power/supply/max14577_charger.c2
-rw-r--r--drivers/power/supply/max77650-charger.c2
-rw-r--r--drivers/power/supply/max77693_charger.c2
-rw-r--r--drivers/power/supply/max77976_charger.c3
-rw-r--r--drivers/power/supply/max8925_power.c4
-rw-r--r--drivers/power/supply/pcf50633-charger.c2
-rw-r--r--drivers/power/supply/pmu_battery.c1
-rw-r--r--drivers/power/supply/power_supply.h22
-rw-r--r--drivers/power/supply/power_supply_core.c87
-rw-r--r--drivers/power/supply/power_supply_hwmon.c1
-rw-r--r--drivers/power/supply/power_supply_sysfs.c12
-rw-r--r--drivers/power/supply/qcom_battmgr.c2
-rw-r--r--drivers/power/supply/qcom_pmi8998_charger.c2
-rw-r--r--drivers/power/supply/qcom_smbb.c8
-rw-r--r--drivers/power/supply/rk817_charger.c112
-rw-r--r--drivers/power/supply/rt9471.c52
-rw-r--r--drivers/power/supply/samsung-sdi-battery.c10
-rw-r--r--drivers/power/supply/sc2731_charger.c2
-rw-r--r--drivers/power/supply/sc27xx_fuel_gauge.c12
-rw-r--r--drivers/power/supply/tps65090-charger.c2
-rw-r--r--drivers/power/supply/tps65217_charger.c2
-rw-r--r--drivers/power/supply/twl4030_charger.c2
-rw-r--r--drivers/power/supply/twl6030_charger.c581
-rw-r--r--drivers/power/supply/wm831x_power.c2
-rw-r--r--drivers/power/supply/wm8350_power.c2
-rw-r--r--drivers/power/supply/wm97xx_battery.c2
-rw-r--r--drivers/ps3/ps3-lpm.c2
-rw-r--r--drivers/ps3/ps3-sys-manager.c2
-rw-r--r--drivers/ps3/ps3-vuart.c4
-rw-r--r--drivers/ps3/sys-manager-core.c2
-rw-r--r--drivers/ptp/Kconfig28
-rw-r--r--drivers/ptp/Makefile2
-rw-r--r--drivers/ptp/ptp_fc3.c5
-rw-r--r--drivers/ptp/ptp_pch.c6
-rw-r--r--drivers/ptp/ptp_s390.c129
-rw-r--r--drivers/ptp/ptp_vmclock.c615
-rw-r--r--drivers/pwm/core.c885
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c4
-rw-r--r--drivers/pwm/pwm-axi-pwmgen.c179
-rw-r--r--drivers/pwm/pwm-imx-tpm.c4
-rw-r--r--drivers/pwm/pwm-imx27.c161
-rw-r--r--drivers/pwm/pwm-stm32.c612
-rw-r--r--drivers/ras/amd/atl/access.c8
-rw-r--r--drivers/regulator/arizona-ldo1.c12
-rw-r--r--drivers/regulator/axp20x-regulator.c13
-rw-r--r--drivers/regulator/bd9571mwv-regulator.c2
-rw-r--r--drivers/regulator/core.c124
-rw-r--r--drivers/regulator/db8500-prcmu.c2
-rw-r--r--drivers/regulator/devres.c39
-rw-r--r--drivers/regulator/internal.h18
-rw-r--r--drivers/regulator/isl6271a-regulator.c4
-rw-r--r--drivers/regulator/max5970-regulator.c21
-rw-r--r--drivers/regulator/of_regulator.c51
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c83
-rw-r--r--drivers/regulator/qcom_smd-regulator.c2
-rw-r--r--drivers/regulator/renesas-usb-vbus-regulator.c7
-rw-r--r--drivers/regulator/rk808-regulator.c43
-rw-r--r--drivers/regulator/rtq2208-regulator.c2
-rw-r--r--drivers/regulator/stm32-vrefbuf.c2
-rw-r--r--drivers/regulator/uniphier-regulator.c2
-rw-r--r--drivers/regulator/userspace-consumer.c2
-rw-r--r--drivers/regulator/virtual.c2
-rw-r--r--drivers/regulator/wm8350-regulator.c6
-rw-r--r--drivers/remoteproc/Kconfig12
-rw-r--r--drivers/remoteproc/da8xx_remoteproc.c31
-rw-r--r--drivers/remoteproc/imx_dsp_rproc.c2
-rw-r--r--drivers/remoteproc/imx_rproc.c2
-rw-r--r--drivers/remoteproc/keystone_remoteproc.c2
-rw-r--r--drivers/remoteproc/meson_mx_ao_arc.c2
-rw-r--r--drivers/remoteproc/mtk_scp.c2
-rw-r--r--drivers/remoteproc/pru_rproc.c2
-rw-r--r--drivers/remoteproc/qcom_q6v5_adsp.c30
-rw-r--r--drivers/remoteproc/qcom_q6v5_mss.c56
-rw-r--r--drivers/remoteproc/qcom_q6v5_pas.c51
-rw-r--r--drivers/remoteproc/qcom_q6v5_wcss.c114
-rw-r--r--drivers/remoteproc/qcom_wcnss.c2
-rw-r--r--drivers/remoteproc/qcom_wcnss_iris.c5
-rw-r--r--drivers/remoteproc/rcar_rproc.c2
-rw-r--r--drivers/remoteproc/remoteproc_core.c6
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c2
-rw-r--r--drivers/remoteproc/st_remoteproc.c2
-rw-r--r--drivers/remoteproc/stm32_rproc.c2
-rw-r--r--drivers/remoteproc/ti_k3_dsp_remoteproc.c10
-rw-r--r--drivers/remoteproc/ti_k3_m4_remoteproc.c6
-rw-r--r--drivers/remoteproc/ti_k3_r5_remoteproc.c83
-rw-r--r--drivers/remoteproc/wkup_m3_rproc.c2
-rw-r--r--drivers/reset/Kconfig20
-rw-r--r--drivers/reset/Makefile3
-rw-r--r--drivers/reset/amlogic/Kconfig27
-rw-r--r--drivers/reset/amlogic/Makefile4
-rw-r--r--drivers/reset/amlogic/reset-meson-audio-arb.c (renamed from drivers/reset/reset-meson-audio-arb.c)0
-rw-r--r--drivers/reset/amlogic/reset-meson-aux.c136
-rw-r--r--drivers/reset/amlogic/reset-meson-common.c142
-rw-r--r--drivers/reset/amlogic/reset-meson.c105
-rw-r--r--drivers/reset/amlogic/reset-meson.h28
-rw-r--r--drivers/reset/core.c119
-rw-r--r--drivers/reset/reset-meson.c159
-rw-r--r--drivers/reset/reset-microchip-sparx5.c38
-rw-r--r--drivers/reset/reset-npcm.c78
-rw-r--r--drivers/reset/reset-uniphier-glue.c24
-rw-r--r--drivers/rpmsg/qcom_glink_native.c13
-rw-r--r--drivers/rtc/Kconfig33
-rw-r--r--drivers/rtc/Makefile5
-rw-r--r--drivers/rtc/interface.c7
-rw-r--r--drivers/rtc/rtc-88pm80x.c2
-rw-r--r--drivers/rtc/rtc-88pm860x.c2
-rw-r--r--drivers/rtc/rtc-88pm886.c97
-rw-r--r--drivers/rtc/rtc-ab-eoz9.c11
-rw-r--r--drivers/rtc/rtc-ab8500.c2
-rw-r--r--drivers/rtc/rtc-abx80x.c2
-rw-r--r--drivers/rtc/rtc-ac100.c2
-rw-r--r--drivers/rtc/rtc-amlogic-a4.c465
-rw-r--r--drivers/rtc/rtc-asm9260.c2
-rw-r--r--drivers/rtc/rtc-at91rm9200.c2
-rw-r--r--drivers/rtc/rtc-at91sam9.c2
-rw-r--r--drivers/rtc/rtc-bd70528.c5
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c3
-rw-r--r--drivers/rtc/rtc-cadence.c2
-rw-r--r--drivers/rtc/rtc-cmos.c33
-rw-r--r--drivers/rtc/rtc-cros-ec.c2
-rw-r--r--drivers/rtc/rtc-ds1685.c2
-rw-r--r--drivers/rtc/rtc-ftrtc010.c2
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c2
-rw-r--r--drivers/rtc/rtc-imxdi.c2
-rw-r--r--drivers/rtc/rtc-isl12022.c269
-rw-r--r--drivers/rtc/rtc-loongson.c2
-rw-r--r--drivers/rtc/rtc-lpc24xx.c2
-rw-r--r--drivers/rtc/rtc-m48t59.c26
-rw-r--r--drivers/rtc/rtc-max77686.c2
-rw-r--r--drivers/rtc/rtc-mc13xxx.c2
-rw-r--r--drivers/rtc/rtc-mc146818-lib.c6
-rw-r--r--drivers/rtc/rtc-mpc5121.c2
-rw-r--r--drivers/rtc/rtc-mpfs.c2
-rw-r--r--drivers/rtc/rtc-mt6397.c29
-rw-r--r--drivers/rtc/rtc-mt7622.c2
-rw-r--r--drivers/rtc/rtc-mv.c2
-rw-r--r--drivers/rtc/rtc-mxc_v2.c2
-rw-r--r--drivers/rtc/rtc-nxp-bbnsm.c20
-rw-r--r--drivers/rtc/rtc-omap.c2
-rw-r--r--drivers/rtc/rtc-palmas.c2
-rw-r--r--drivers/rtc/rtc-pcf50633.c2
-rw-r--r--drivers/rtc/rtc-pcf8563.c212
-rw-r--r--drivers/rtc/rtc-pic32.c2
-rw-r--r--drivers/rtc/rtc-pm8xxx.c2
-rw-r--r--drivers/rtc/rtc-pxa.c2
-rw-r--r--drivers/rtc/rtc-rc5t583.c2
-rw-r--r--drivers/rtc/rtc-renesas-rtca3.c900
-rw-r--r--drivers/rtc/rtc-rtd119x.c2
-rw-r--r--drivers/rtc/rtc-rv3028.c6
-rw-r--r--drivers/rtc/rtc-rzn1.c92
-rw-r--r--drivers/rtc/rtc-s3c.c2
-rw-r--r--drivers/rtc/rtc-sa1100.c2
-rw-r--r--drivers/rtc/rtc-sh.c2
-rw-r--r--drivers/rtc/rtc-spear.c2
-rw-r--r--drivers/rtc/rtc-st-lpc.c5
-rw-r--r--drivers/rtc/rtc-stm32.c2
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c2
-rw-r--r--drivers/rtc/rtc-sunplus.c2
-rw-r--r--drivers/rtc/rtc-tegra.c2
-rw-r--r--drivers/rtc/rtc-tps6586x.c2
-rw-r--r--drivers/rtc/rtc-twl.c2
-rw-r--r--drivers/rtc/rtc-vt8500.c2
-rw-r--r--drivers/rtc/rtc-wm8350.c2
-rw-r--r--drivers/rtc/rtc-xgene.c2
-rw-r--r--drivers/rtc/rtc-zynqmp.c2
-rw-r--r--drivers/s390/block/dasd.c2
-rw-r--r--drivers/s390/block/dasd_devmap.c2
-rw-r--r--drivers/s390/block/dasd_diag.c15
-rw-r--r--drivers/s390/block/dasd_eckd.c2
-rw-r--r--drivers/s390/block/dasd_proc.c5
-rw-r--r--drivers/s390/block/dcssblk.c18
-rw-r--r--drivers/s390/char/con3215.c1
-rw-r--r--drivers/s390/char/con3270.c4
-rw-r--r--drivers/s390/char/sclp.h18
-rw-r--r--drivers/s390/char/sclp_cpi_sys.c8
-rw-r--r--drivers/s390/char/sclp_ocf.c4
-rw-r--r--drivers/s390/char/sclp_pci.c2
-rw-r--r--drivers/s390/char/tape_core.c16
-rw-r--r--drivers/s390/char/uvdevice.c153
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/char/vmur.c2
-rw-r--r--drivers/s390/cio/ccwgroup.c2
-rw-r--r--drivers/s390/cio/chp.c31
-rw-r--r--drivers/s390/cio/chp.h1
-rw-r--r--drivers/s390/cio/chsc.c31
-rw-r--r--drivers/s390/cio/chsc.h16
-rw-r--r--drivers/s390/cio/cio.c6
-rw-r--r--drivers/s390/cio/cio.h2
-rw-r--r--drivers/s390/cio/cmf.c15
-rw-r--r--drivers/s390/cio/css.c6
-rw-r--r--drivers/s390/cio/device.c40
-rw-r--r--drivers/s390/cio/ioasm.c107
-rw-r--r--drivers/s390/cio/qdio_main.c28
-rw-r--r--drivers/s390/cio/scm.c2
-rw-r--r--drivers/s390/crypto/Makefile4
-rw-r--r--drivers/s390/crypto/ap_bus.c2
-rw-r--r--drivers/s390/crypto/pkey_base.c14
-rw-r--r--drivers/s390/crypto/pkey_base.h36
-rw-r--r--drivers/s390/crypto/pkey_cca.c5
-rw-r--r--drivers/s390/crypto/pkey_ep11.c1
-rw-r--r--drivers/s390/crypto/pkey_pckmo.c239
-rw-r--r--drivers/s390/crypto/pkey_sysfs.c1
-rw-r--r--drivers/s390/crypto/pkey_uv.c284
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c77
-rw-r--r--drivers/s390/crypto/zcrypt_ccamisc.h1
-rw-r--r--drivers/s390/net/netiucv.c24
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c82
-rw-r--r--drivers/s390/virtio/virtio_ccw.c4
-rw-r--r--drivers/scsi/a3000.c6
-rw-r--r--drivers/scsi/a4000t.c6
-rw-r--r--drivers/scsi/aacraid/aacraid.h1
-rw-r--r--drivers/scsi/aacraid/commsup.c121
-rw-r--r--drivers/scsi/aha152x.c2
-rw-r--r--drivers/scsi/aic7xxx/aic7770.c15
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h2
-rw-r--r--drivers/scsi/atari_scsi.c2
-rw-r--r--drivers/scsi/bfa/bfa.h10
-rw-r--r--drivers/scsi/bfa/bfa_core.c35
-rw-r--r--drivers/scsi/bfa/bfa_defs_fcs.h22
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c9
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h1
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h12
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c142
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c36
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c21
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h2
-rw-r--r--drivers/scsi/bfa/bfa_modules.h1
-rw-r--r--drivers/scsi/bfa/bfa_svc.c72
-rw-r--r--drivers/scsi/bfa/bfa_svc.h5
-rw-r--r--drivers/scsi/bfa/bfad.c23
-rw-r--r--drivers/scsi/bfa/bfad_drv.h1
-rw-r--r--drivers/scsi/bfa/bfi.h2
-rw-r--r--drivers/scsi/bvme6000_scsi.c2
-rw-r--r--drivers/scsi/esas2r/esas2r.h4
-rw-r--r--drivers/scsi/esas2r/esas2r_vda.c17
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h1
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c31
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v1_hw.c20
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c20
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c187
-rw-r--r--drivers/scsi/jazz_esp.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c39
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h62
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c459
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c311
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c61
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c329
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c60
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c125
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c6
-rw-r--r--drivers/scsi/mac_esp.c2
-rw-r--r--drivers/scsi/mac_scsi.c2
-rw-r--r--drivers/scsi/mvme16x_scsi.c2
-rw-r--r--drivers/scsi/pm8001/pm8001_defs.h7
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c8
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c17
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h2
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c3
-rw-r--r--drivers/scsi/qedf/qedf_main.c6
-rw-r--r--drivers/scsi/qedi/qedi_main.c1
-rw-r--r--drivers/scsi/qlogicpti.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c2
-rw-r--r--drivers/scsi/sd.c6
-rw-r--r--drivers/scsi/sd_zbc.c5
-rw-r--r--drivers/scsi/sg.c9
-rw-r--r--drivers/scsi/sgiwd93.c2
-rw-r--r--drivers/scsi/sni_53c710.c2
-rw-r--r--drivers/scsi/st.c36
-rw-r--r--drivers/scsi/sun3_scsi.c10
-rw-r--r--drivers/scsi/sun3x_esp.c2
-rw-r--r--drivers/scsi/sun_esp.c2
-rw-r--r--drivers/sh/intc/core.c2
-rw-r--r--drivers/sh/intc/virq-debugfs.c1
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-ctrl.c2
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-snoop.c2
-rw-r--r--drivers/soc/aspeed/aspeed-p2a-ctrl.c2
-rw-r--r--drivers/soc/aspeed/aspeed-uart-routing.c2
-rw-r--r--drivers/soc/fsl/dpaa2-console.c2
-rw-r--r--drivers/soc/fsl/dpio/dpio-service.c2
-rw-r--r--drivers/soc/fsl/qe/qmc.c6
-rw-r--r--drivers/soc/fsl/qe/tsa.c30
-rw-r--r--drivers/soc/fsl/rcpm.c1
-rw-r--r--drivers/soc/fujitsu/a64fx-diag.c2
-rw-r--r--drivers/soc/hisilicon/Kconfig7
-rw-r--r--drivers/soc/hisilicon/kunpeng_hccs.c516
-rw-r--r--drivers/soc/hisilicon/kunpeng_hccs.h33
-rw-r--r--drivers/soc/imx/soc-imx8m.c174
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-npe.c2
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-qmgr.c2
-rw-r--r--drivers/soc/litex/litex_soc_ctrl.c2
-rw-r--r--drivers/soc/loongson/loongson2_guts.c2
-rw-r--r--drivers/soc/mediatek/Kconfig11
-rw-r--r--drivers/soc/mediatek/Makefile1
-rw-r--r--drivers/soc/mediatek/mtk-cmdq-helper.c230
-rw-r--r--drivers/soc/mediatek/mtk-devapc.c2
-rw-r--r--drivers/soc/mediatek/mtk-dvfsrc.c545
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.c2
-rw-r--r--drivers/soc/mediatek/mtk-regulator-coupler.c1
-rw-r--r--drivers/soc/mediatek/mtk-socinfo.c2
-rw-r--r--drivers/soc/mediatek/mtk-svs.c4
-rw-r--r--drivers/soc/microchip/mpfs-sys-controller.c2
-rw-r--r--drivers/soc/pxa/ssp.c2
-rw-r--r--drivers/soc/qcom/icc-bwmon.c2
-rw-r--r--drivers/soc/qcom/ice.c6
-rw-r--r--drivers/soc/qcom/llcc-qcom.c3268
-rw-r--r--drivers/soc/qcom/ocmem.c2
-rw-r--r--drivers/soc/qcom/pmic_glink.c27
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c3
-rw-r--r--drivers/soc/qcom/qcom-pbs.c22
-rw-r--r--drivers/soc/qcom/qcom_aoss.c2
-rw-r--r--drivers/soc/qcom/qcom_gsbi.c2
-rw-r--r--drivers/soc/qcom/qcom_pd_mapper.c1
-rw-r--r--drivers/soc/qcom/qcom_stats.c2
-rw-r--r--drivers/soc/qcom/qmi_interface.c2
-rw-r--r--drivers/soc/qcom/ramp_controller.c4
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c2
-rw-r--r--drivers/soc/qcom/rpm-proc.c2
-rw-r--r--drivers/soc/qcom/rpm_master_stats.c2
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c9
-rw-r--r--drivers/soc/qcom/smem.c18
-rw-r--r--drivers/soc/qcom/smem_state.c12
-rw-r--r--drivers/soc/qcom/smp2p.c11
-rw-r--r--drivers/soc/qcom/smsm.c6
-rw-r--r--drivers/soc/qcom/socinfo.c17
-rw-r--r--drivers/soc/renesas/Kconfig1
-rw-r--r--drivers/soc/rockchip/io-domain.c8
-rw-r--r--drivers/soc/samsung/exynos-chipid.c7
-rw-r--r--drivers/soc/tegra/cbb/tegra194-cbb.c2
-rw-r--r--drivers/soc/ti/k3-ringacc.c2
-rw-r--r--drivers/soc/ti/knav_dma.c4
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c8
-rw-r--r--drivers/soc/ti/pm33xx.c2
-rw-r--r--drivers/soc/ti/pruss.c4
-rw-r--r--drivers/soc/ti/smartreflex.c6
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c2
-rw-r--r--drivers/soc/xilinx/xlnx_event_manager.c6
-rw-r--r--drivers/soc/xilinx/zynqmp_power.c2
-rw-r--r--drivers/soundwire/Kconfig1
-rw-r--r--drivers/soundwire/amd_init.c13
-rw-r--r--drivers/soundwire/amd_manager.c99
-rw-r--r--drivers/soundwire/amd_manager.h16
-rw-r--r--drivers/soundwire/bus.c2
-rw-r--r--drivers/soundwire/cadence_master.c30
-rw-r--r--drivers/soundwire/cadence_master.h1
-rw-r--r--drivers/soundwire/intel_ace2x.c7
-rw-r--r--drivers/soundwire/intel_auxdevice.c12
-rw-r--r--drivers/soundwire/intel_bus_common.c6
-rw-r--r--drivers/soundwire/intel_init.c13
-rw-r--r--drivers/soundwire/mipi_disco.c144
-rw-r--r--drivers/soundwire/qcom.c2
-rw-r--r--drivers/soundwire/slave.c14
-rw-r--r--drivers/soundwire/sysfs_slave.c2
-rw-r--r--drivers/spi/Kconfig22
-rw-r--r--drivers/spi/Makefile2
-rw-r--r--drivers/spi/atmel-quadspi.c40
-rw-r--r--drivers/spi/spi-airoha-snfi.c154
-rw-r--r--drivers/spi/spi-amd.c325
-rw-r--r--drivers/spi/spi-apple.c529
-rw-r--r--drivers/spi/spi-ar934x.c2
-rw-r--r--drivers/spi/spi-aspeed-smc.c2
-rw-r--r--drivers/spi/spi-at91-usart.c2
-rw-r--r--drivers/spi/spi-ath79.c2
-rw-r--r--drivers/spi/spi-atmel.c2
-rw-r--r--drivers/spi/spi-au1550.c2
-rw-r--r--drivers/spi/spi-axi-spi-engine.c15
-rw-r--r--drivers/spi/spi-bcm2835.c2
-rw-r--r--drivers/spi/spi-bcm2835aux.c2
-rw-r--r--drivers/spi/spi-bcm63xx-hsspi.c2
-rw-r--r--drivers/spi/spi-bcm63xx.c2
-rw-r--r--drivers/spi/spi-bcmbca-hsspi.c2
-rw-r--r--drivers/spi/spi-brcmstb-qspi.c2
-rw-r--r--drivers/spi/spi-cadence-quadspi.c2
-rw-r--r--drivers/spi/spi-cadence.c2
-rw-r--r--drivers/spi/spi-cavium-octeon.c2
-rw-r--r--drivers/spi/spi-ch341.c2
-rw-r--r--drivers/spi/spi-coldfire-qspi.c2
-rw-r--r--drivers/spi/spi-cs42l43.c46
-rw-r--r--drivers/spi/spi-davinci.c2
-rw-r--r--drivers/spi/spi-dln2.c2
-rw-r--r--drivers/spi/spi-dw-bt1.c2
-rw-r--r--drivers/spi/spi-dw-mmio.c2
-rw-r--r--drivers/spi/spi-dw-pci.c9
-rw-r--r--drivers/spi/spi-ep93xx.c2
-rw-r--r--drivers/spi/spi-fsl-dspi.c10
-rw-r--r--drivers/spi/spi-fsl-espi.c2
-rw-r--r--drivers/spi/spi-fsl-lpspi.c29
-rw-r--r--drivers/spi/spi-fsl-qspi.c2
-rw-r--r--drivers/spi/spi-fsl-spi.c4
-rw-r--r--drivers/spi/spi-hisi-kunpeng.c2
-rw-r--r--drivers/spi/spi-hisi-sfc-v3xx.c2
-rw-r--r--drivers/spi/spi-img-spfi.c2
-rw-r--r--drivers/spi/spi-imx.c115
-rw-r--r--drivers/spi/spi-intel-pci.c1
-rw-r--r--drivers/spi/spi-intel-platform.c1
-rw-r--r--drivers/spi/spi-intel.c64
-rw-r--r--drivers/spi/spi-intel.h2
-rw-r--r--drivers/spi/spi-iproc-qspi.c2
-rw-r--r--drivers/spi/spi-lantiq-ssc.c4
-rw-r--r--drivers/spi/spi-loongson-pci.c5
-rw-r--r--drivers/spi/spi-mem.c3
-rw-r--r--drivers/spi/spi-meson-spicc.c2
-rw-r--r--drivers/spi/spi-meson-spifc.c2
-rw-r--r--drivers/spi/spi-microchip-core-qspi.c2
-rw-r--r--drivers/spi/spi-microchip-core.c2
-rw-r--r--drivers/spi/spi-mpc52xx-psc.c4
-rw-r--r--drivers/spi/spi-mpc52xx.c2
-rw-r--r--drivers/spi/spi-mt65xx.c2
-rw-r--r--drivers/spi/spi-mtk-nor.c2
-rw-r--r--drivers/spi/spi-mtk-snfi.c4
-rw-r--r--drivers/spi/spi-mxic.c29
-rw-r--r--drivers/spi/spi-mxs.c2
-rw-r--r--drivers/spi/spi-npcm-fiu.c8
-rw-r--r--drivers/spi/spi-npcm-pspi.c2
-rw-r--r--drivers/spi/spi-nxp-fspi.c2
-rw-r--r--drivers/spi/spi-oc-tiny.c2
-rw-r--r--drivers/spi/spi-omap-uwire.c2
-rw-r--r--drivers/spi/spi-omap2-mcspi.c2
-rw-r--r--drivers/spi/spi-orion.c2
-rw-r--r--drivers/spi/spi-pic32-sqi.c4
-rw-r--r--drivers/spi/spi-pic32.c2
-rw-r--r--drivers/spi/spi-pl022.c2
-rw-r--r--drivers/spi/spi-ppc4xx.c2
-rw-r--r--drivers/spi/spi-pxa2xx-pci.c8
-rw-r--r--drivers/spi/spi-pxa2xx-platform.c2
-rw-r--r--drivers/spi/spi-qcom-qspi.c4
-rw-r--r--drivers/spi/spi-qup.c2
-rw-r--r--drivers/spi/spi-rb4xx.c2
-rw-r--r--drivers/spi/spi-realtek-rtl-snand.c419
-rw-r--r--drivers/spi/spi-rockchip-sfc.c27
-rw-r--r--drivers/spi/spi-rockchip.c59
-rw-r--r--drivers/spi/spi-rpc-if.c2
-rw-r--r--drivers/spi/spi-rspi.c2
-rw-r--r--drivers/spi/spi-rzv2m-csi.c2
-rw-r--r--drivers/spi/spi-s3c64xx.c4
-rw-r--r--drivers/spi/spi-sh-hspi.c2
-rw-r--r--drivers/spi/spi-sh-msiof.c2
-rw-r--r--drivers/spi/spi-sh-sci.c2
-rw-r--r--drivers/spi/spi-sh.c2
-rw-r--r--drivers/spi/spi-sifive.c2
-rw-r--r--drivers/spi/spi-slave-mt27xx.c10
-rw-r--r--drivers/spi/spi-sn-f-ospi.c2
-rw-r--r--drivers/spi/spi-sprd.c4
-rw-r--r--drivers/spi/spi-st-ssc4.c2
-rw-r--r--drivers/spi/spi-stm32-qspi.c2
-rw-r--r--drivers/spi/spi-stm32.c2
-rw-r--r--drivers/spi/spi-sun4i.c2
-rw-r--r--drivers/spi/spi-sun6i.c2
-rw-r--r--drivers/spi/spi-sunplus-sp7021.c2
-rw-r--r--drivers/spi/spi-synquacer.c2
-rw-r--r--drivers/spi/spi-tegra114.c2
-rw-r--r--drivers/spi/spi-tegra20-sflash.c2
-rw-r--r--drivers/spi/spi-tegra20-slink.c4
-rw-r--r--drivers/spi/spi-tegra210-quad.c4
-rw-r--r--drivers/spi/spi-ti-qspi.c5
-rw-r--r--drivers/spi/spi-topcliff-pch.c2
-rw-r--r--drivers/spi/spi-uniphier.c2
-rw-r--r--drivers/spi/spi-xilinx.c2
-rw-r--r--drivers/spi/spi-xtensa-xtfpga.c2
-rw-r--r--drivers/spi/spi-zynq-qspi.c2
-rw-r--r--drivers/spi/spi-zynqmp-gqspi.c4
-rw-r--r--drivers/spi/spi.c36
-rw-r--r--drivers/spmi/spmi-pmic-arb.c3
-rw-r--r--drivers/staging/Kconfig18
-rw-r--r--drivers/staging/Makefile9
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c2
-rw-r--r--drivers/staging/fbtft/fbtft.h2
-rw-r--r--drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev31
-rw-r--r--drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev62
-rw-r--r--drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt71
-rw-r--r--drivers/staging/fieldbus/Documentation/fieldbus_dev.txt66
-rw-r--r--drivers/staging/fieldbus/Kconfig19
-rw-r--r--drivers/staging/fieldbus/Makefile7
-rw-r--r--drivers/staging/fieldbus/TODO5
-rw-r--r--drivers/staging/fieldbus/anybuss/Kconfig41
-rw-r--r--drivers/staging/fieldbus/anybuss/Makefile10
-rw-r--r--drivers/staging/fieldbus/anybuss/anybuss-client.h95
-rw-r--r--drivers/staging/fieldbus/anybuss/anybuss-controller.h47
-rw-r--r--drivers/staging/fieldbus/anybuss/arcx-anybus.c379
-rw-r--r--drivers/staging/fieldbus/anybuss/hms-profinet.c224
-rw-r--r--drivers/staging/fieldbus/anybuss/host.c1452
-rw-r--r--drivers/staging/fieldbus/dev_core.c344
-rw-r--r--drivers/staging/fieldbus/fieldbus_dev.h114
-rw-r--r--drivers/staging/gdm724x/Kconfig16
-rw-r--r--drivers/staging/gdm724x/Makefile8
-rw-r--r--drivers/staging/gdm724x/TODO16
-rw-r--r--drivers/staging/gdm724x/gdm_endian.c37
-rw-r--r--drivers/staging/gdm724x/gdm_endian.h30
-rw-r--r--drivers/staging/gdm724x/gdm_lte.c937
-rw-r--r--drivers/staging/gdm724x/gdm_lte.h71
-rw-r--r--drivers/staging/gdm724x/gdm_mux.c668
-rw-r--r--drivers/staging/gdm724x/gdm_mux.h85
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c316
-rw-r--r--drivers/staging/gdm724x/gdm_tty.h60
-rw-r--r--drivers/staging/gdm724x/gdm_usb.c1012
-rw-r--r--drivers/staging/gdm724x/gdm_usb.h99
-rw-r--r--drivers/staging/gdm724x/hci.h45
-rw-r--r--drivers/staging/gdm724x/hci_packet.h82
-rw-r--r--drivers/staging/gdm724x/netlink_k.c128
-rw-r--r--drivers/staging/gdm724x/netlink_k.h16
-rw-r--r--drivers/staging/gpib/Kconfig251
-rw-r--r--drivers/staging/gpib/Makefile20
-rw-r--r--drivers/staging/gpib/TODO21
-rw-r--r--drivers/staging/gpib/agilent_82350b/Makefile2
-rw-r--r--drivers/staging/gpib/agilent_82350b/agilent_82350b.c932
-rw-r--r--drivers/staging/gpib/agilent_82350b/agilent_82350b.h209
-rw-r--r--drivers/staging/gpib/agilent_82357a/Makefile4
-rw-r--r--drivers/staging/gpib/agilent_82357a/agilent_82357a.c1712
-rw-r--r--drivers/staging/gpib/agilent_82357a/agilent_82357a.h182
-rw-r--r--drivers/staging/gpib/cb7210/Makefile4
-rw-r--r--drivers/staging/gpib/cb7210/cb7210.c1556
-rw-r--r--drivers/staging/gpib/cb7210/cb7210.h251
-rw-r--r--drivers/staging/gpib/cec/Makefile3
-rw-r--r--drivers/staging/gpib/cec/cec.h53
-rw-r--r--drivers/staging/gpib/cec/cec_gpib.c385
-rw-r--r--drivers/staging/gpib/common/Makefile6
-rw-r--r--drivers/staging/gpib/common/gpib_os.c2328
-rw-r--r--drivers/staging/gpib/common/iblib.c740
-rw-r--r--drivers/staging/gpib/common/ibsys.h31
-rw-r--r--drivers/staging/gpib/eastwood/Makefile3
-rw-r--r--drivers/staging/gpib/eastwood/fluke_gpib.c1179
-rw-r--r--drivers/staging/gpib/eastwood/fluke_gpib.h143
-rw-r--r--drivers/staging/gpib/fmh_gpib/Makefile2
-rw-r--r--drivers/staging/gpib/fmh_gpib/fmh_gpib.c1725
-rw-r--r--drivers/staging/gpib/fmh_gpib/fmh_gpib.h177
-rw-r--r--drivers/staging/gpib/gpio/Makefile4
-rw-r--r--drivers/staging/gpib/gpio/gpib_bitbang.c1476
-rw-r--r--drivers/staging/gpib/hp_82335/Makefile4
-rw-r--r--drivers/staging/gpib/hp_82335/hp82335.c360
-rw-r--r--drivers/staging/gpib/hp_82335/hp82335.h85
-rw-r--r--drivers/staging/gpib/hp_82341/Makefile2
-rw-r--r--drivers/staging/gpib/hp_82341/hp_82341.c895
-rw-r--r--drivers/staging/gpib/hp_82341/hp_82341.h207
-rw-r--r--drivers/staging/gpib/include/amcc5920.h49
-rw-r--r--drivers/staging/gpib/include/amccs5933.h59
-rw-r--r--drivers/staging/gpib/include/gpibP.h50
-rw-r--r--drivers/staging/gpib/include/gpib_pci_ids.h23
-rw-r--r--drivers/staging/gpib/include/gpib_proto.h56
-rw-r--r--drivers/staging/gpib/include/gpib_state_machines.h23
-rw-r--r--drivers/staging/gpib/include/gpib_types.h353
-rw-r--r--drivers/staging/gpib/include/nec7210.h138
-rw-r--r--drivers/staging/gpib/include/nec7210_registers.h217
-rw-r--r--drivers/staging/gpib/include/plx9050.h72
-rw-r--r--drivers/staging/gpib/include/quancom_pci.h22
-rw-r--r--drivers/staging/gpib/include/tms9914.h274
-rw-r--r--drivers/staging/gpib/include/tnt4882_registers.h192
-rw-r--r--drivers/staging/gpib/ines/Makefile4
-rw-r--r--drivers/staging/gpib/ines/ines.h215
-rw-r--r--drivers/staging/gpib/ines/ines_gpib.c1464
-rw-r--r--drivers/staging/gpib/lpvo_usb_gpib/Makefile3
-rw-r--r--drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c2136
-rw-r--r--drivers/staging/gpib/nec7210/Makefile4
-rw-r--r--drivers/staging/gpib/nec7210/board.h19
-rw-r--r--drivers/staging/gpib/nec7210/nec7210.c1134
-rw-r--r--drivers/staging/gpib/ni_usb/Makefile4
-rw-r--r--drivers/staging/gpib/ni_usb/ni_usb_gpib.c2640
-rw-r--r--drivers/staging/gpib/ni_usb/ni_usb_gpib.h216
-rw-r--r--drivers/staging/gpib/pc2/Makefile5
-rw-r--r--drivers/staging/gpib/pc2/pc2_gpib.c656
-rw-r--r--drivers/staging/gpib/tms9914/Makefile6
-rw-r--r--drivers/staging/gpib/tms9914/tms9914.c910
-rw-r--r--drivers/staging/gpib/tnt4882/Makefile7
-rw-r--r--drivers/staging/gpib/tnt4882/mite.c219
-rw-r--r--drivers/staging/gpib/tnt4882/mite.h243
-rw-r--r--drivers/staging/gpib/tnt4882/tnt4882_gpib.c1874
-rw-r--r--drivers/staging/gpib/uapi/gpib_ioctl.h169
-rw-r--r--drivers/staging/gpib/uapi/gpib_user.h363
-rw-r--r--drivers/staging/greybus/arche-apb-ctrl.c2
-rw-r--r--drivers/staging/greybus/arche-platform.c2
-rw-r--r--drivers/staging/greybus/gpio.c33
-rw-r--r--drivers/staging/greybus/uart.c2
-rw-r--r--drivers/staging/iio/TODO5
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c6
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/atomisp/i2c/Kconfig10
-rw-r--r--drivers/staging/media/atomisp/i2c/Makefile2
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc0310.c10
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc2235.c10
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c211
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c24
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-ov2722.c10
-rw-r--r--drivers/staging/media/atomisp/i2c/gc2235.h13
-rw-r--r--drivers/staging/media/atomisp/i2c/mt9m114.h11
-rw-r--r--drivers/staging/media/atomisp/i2c/ov2722.h11
-rw-r--r--drivers/staging/media/atomisp/include/hmm/hmm.h11
-rw-r--r--drivers/staging/media/atomisp/include/hmm/hmm_bo.h15
-rw-r--r--drivers/staging/media/atomisp/include/hmm/hmm_common.h11
-rw-r--r--drivers/staging/media/atomisp/include/linux/atomisp.h11
-rw-r--r--drivers/staging/media/atomisp/include/linux/atomisp_gmin_platform.h9
-rw-r--r--drivers/staging/media/atomisp/include/linux/atomisp_platform.h11
-rw-r--r--drivers/staging/media/atomisp/include/linux/libmsrlisthelper.h28
-rw-r--r--drivers/staging/media/atomisp/include/mmu/isp_mmu.h11
-rw-r--r--drivers/staging/media/atomisp/include/mmu/sh_mmu_mrfld.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp-regs.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.c11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_common.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.c11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2.c11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_csi2.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_dfs_tables.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_drvfs.c11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_drvfs.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.c13
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_internal.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.c24
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.c11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_tables.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_trace_event.h11
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c13
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.h11
-rw-r--r--drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf.h9
-rw-r--r--drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_comm.h9
-rw-r--r--drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_desc.h9
-rw-r--r--drivers/staging/media/atomisp/pci/base/circbuf/src/circbuf.c9
-rw-r--r--drivers/staging/media/atomisp/pci/base/refcount/interface/ia_css_refcount.h9
-rw-r--r--drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c9
-rw-r--r--drivers/staging/media/atomisp/pci/bits.h9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/interface/ia_css_pipe_binarydesc.h9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/interface/ia_css_pipe_stagedesc.h9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/interface/ia_css_pipe_util.h9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_stagedesc.c9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_util.c9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/util/interface/ia_css_util.h9
-rw-r--r--drivers/staging/media/atomisp/pci/camera/util/src/util.c9
-rw-r--r--drivers/staging/media/atomisp/pci/cell_params.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/csi_rx_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/csi_rx.c9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/csi_rx_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/csi_rx_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/ibuf_ctrl.c9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/ibuf_ctrl_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_dma.c9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_dma_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq.c9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_stream2mmio.c9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_stream2mmio_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/isys_stream2mmio_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/pixelgen_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/pixelgen_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/hrt/PixelGen_SysBlock_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/hrt/ibuf_cntrl_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/hrt/mipi_backend_common_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/hrt/mipi_backend_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/hrt/rx_csi_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/hrt/stream2mmio_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/ibuf_ctrl_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/isys_dma_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/isys_irq_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/isys_stream2mmio_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/pixelgen_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_receiver_2400_common_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_receiver_2400_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/css_trace.h9
-rw-r--r--drivers/staging/media/atomisp/pci/dma_v2_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/gdc_v2_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/gp_timer_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/gpio_block_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/debug_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/dma_global.h10
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/event_fifo_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/fifo_monitor_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/gdc_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/gp_device_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/gp_timer_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/gpio_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/hmem_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/debug.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/debug_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/debug_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/dma.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/dma_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/dma_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/event_fifo.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/event_fifo_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/event_fifo_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/fifo_monitor.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/fifo_monitor_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/fifo_monitor_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gp_device.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gp_device_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gp_device_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gp_timer.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gp_timer_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gp_timer_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gpio_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/hmem.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/hmem_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/hmem_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_formatter.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_formatter_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_formatter_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c11
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/irq.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/irq_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/irq_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/isp_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/mmu.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/mmu_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/sp.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/sp_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/sp_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/timed_ctrl.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/timed_ctrl_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/timed_ctrl_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/vamem_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/vmem.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/vmem_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/host/vmem_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/input_formatter_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/irq_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/isp_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/mmu_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/sp_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/timed_ctrl_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/vamem_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_common/vmem_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/assert_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/bitop_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/csi_rx.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/debug.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/device_access/device_access.h8
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/dma.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/event_fifo.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/fifo_monitor.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/gdc_device.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/gp_device.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/gp_timer.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/hmem.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/csi_rx_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/debug_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/dma_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/event_fifo_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/fifo_monitor_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/gdc_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/gp_device_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/gp_timer_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/hmem_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/input_formatter_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/irq_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isp_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_dma_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_irq_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_stream2mmio_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/mmu_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/pixelgen_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/sp_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/tag_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/timed_ctrl_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/vamem_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/host/vmem_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/input_formatter.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/input_system.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/irq.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/isp.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/isys_irq.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/isys_stream2mmio.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/misc_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/mmu_device.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/pixelgen.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/platform_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/print_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/queue.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/resource.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/sp.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/tag.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/timed_ctrl.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/type_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/vamem.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_include/vmem.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/host/queue_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/host/queue_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/host/tag.c9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/host/tag_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/host/tag_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/queue_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/sw_event_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_shared/tag_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_isp_css_streaming_to_mipi_types_hrt.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hive_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/hmm/hmm.c11
-rw-r--r--drivers/staging/media/atomisp/pci/hmm/hmm_bo.c11
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_3a.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_acc_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_buffer.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_control.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_device_access.c9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_device_access.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_dvs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_env.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_err.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_event_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_firmware.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_frac.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_frame_format.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_frame_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_host_data.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_input_port.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_irq.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_isp_configs.c9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_isp_configs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_isp_params.c9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_isp_params.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_isp_states.c9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_isp_states.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_metadata.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_mipi.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_mmu.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_mmu_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_morph.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_pipe.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_pipe_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_prbs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_properties.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_shading.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_stream.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_stream_format.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_stream_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_timer.h8
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_version.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_version_data.h9
-rw-r--r--drivers/staging/media/atomisp/pci/if_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/input_formatter_subsystem_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/input_selector_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/input_switch_2400_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/input_system_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/irq_controller_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/irq_types_hrt.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/aa/aa_2/ia_css_aa2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/aa/aa_2/ia_css_aa2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/aa/aa_2/ia_css_aa2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/aa/aa_2/ia_css_aa2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_2/ia_css_anr2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_2/ia_css_anr2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_2/ia_css_anr2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_2/ia_css_anr2_table.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_2/ia_css_anr2_table.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_2/ia_css_anr2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnlm/ia_css_bnlm.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnlm/ia_css_bnlm.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnlm/ia_css_bnlm_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnlm/ia_css_bnlm_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnr/bnr2_2/ia_css_bnr2_2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnr/bnr2_2/ia_css_bnr2_2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnr/bnr2_2/ia_css_bnr2_2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnr/bnr2_2/ia_css_bnr2_2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnr/bnr_1.0/ia_css_bnr.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnr/bnr_1.0/ia_css_bnr.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/bnr/bnr_1.0/ia_css_bnr_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/cnr/cnr_1.0/ia_css_cnr.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/cnr/cnr_1.0/ia_css_cnr.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/cnr/cnr_1.0/ia_css_cnr_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/cnr/cnr_2/ia_css_cnr2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/cnr/cnr_2/ia_css_cnr2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/cnr/cnr_2/ia_css_cnr2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/cnr/cnr_2/ia_css_cnr2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/csc/csc_1.0/ia_css_csc.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/csc/csc_1.0/ia_css_csc.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/csc/csc_1.0/ia_css_csc_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/csc/csc_1.0/ia_css_csc_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc1_5/ia_css_ctc1_5.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc1_5/ia_css_ctc1_5.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc1_5/ia_css_ctc1_5_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc2/ia_css_ctc2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc2/ia_css_ctc2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc2/ia_css_ctc2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc2/ia_css_ctc2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc_1.0/ia_css_ctc.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc_1.0/ia_css_ctc.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc_1.0/ia_css_ctc_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc_1.0/ia_css_ctc_table.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc_1.0/ia_css_ctc_table.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ctc/ctc_1.0/ia_css_ctc_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_1.0/ia_css_de.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_1.0/ia_css_de.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_1.0/ia_css_de_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_1.0/ia_css_de_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_2/ia_css_de2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_2/ia_css_de2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_2/ia_css_de2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/de/de_2/ia_css_de2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dp/dp_1.0/ia_css_dp.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dp/dp_1.0/ia_css_dp.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dp/dp_1.0/ia_css_dp_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dp/dp_1.0/ia_css_dp_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dpc2/ia_css_dpc2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dpc2/ia_css_dpc2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dpc2/ia_css_dpc2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dpc2/ia_css_dpc2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fc/fc_1.0/ia_css_formats.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fc/fc_1.0/ia_css_formats.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fc/fc_1.0/ia_css_formats_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fc/fc_1.0/ia_css_formats_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fixedbds/fixedbds_1.0/ia_css_fixedbds_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_1.0/ia_css_gc.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_1.0/ia_css_gc.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_1.0/ia_css_gc_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_1.0/ia_css_gc_table.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_1.0/ia_css_gc_table.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_1.0/ia_css_gc_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_2/ia_css_gc2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_2/ia_css_gc2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_2/ia_css_gc2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_2/ia_css_gc2_table.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_2/ia_css_gc2_table.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/gc/gc_2/ia_css_gc2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_param.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_types.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_param.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_types.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/iterator/iterator_1.0/ia_css_iterator_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5_table.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5_table.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc_1.0/ia_css_macc.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc_1.0/ia_css_macc.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc_1.0/ia_css_macc_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc_1.0/ia_css_macc_table.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc_1.0/ia_css_macc_table.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc_1.0/ia_css_macc_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/norm/norm_1.0/ia_css_norm.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/norm/norm_1.0/ia_css_norm.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/norm/norm_1.0/ia_css_norm_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob2/ia_css_ob2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob2/ia_css_ob2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob2/ia_css_ob2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob2/ia_css_ob2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob_1.0/ia_css_ob.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob_1.0/ia_css_ob.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob_1.0/ia_css_ob_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ob/ob_1.0/ia_css_ob_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/raw_aa_binning/raw_aa_binning_1.0/ia_css_raa.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/raw_aa_binning/raw_aa_binning_1.0/ia_css_raa.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref_state.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/common/ia_css_sdis_common.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/common/ia_css_sdis_common_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_1.0/ia_css_sdis_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_2/ia_css_sdis2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_2/ia_css_sdis2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_2/ia_css_sdis2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tdf/tdf_1.0/ia_css_tdf_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tdf/tdf_1.0/ia_css_tdf_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr3/ia_css_tnr3_types.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr_state.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/uds/uds_1.0/ia_css_uds_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/wb/wb_1.0/ia_css_wb.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/wb/wb_1.0/ia_css_wb.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/wb/wb_1.0/ia_css_wb_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/wb/wb_1.0/ia_css_wb_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_1.0/ia_css_xnr.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_1.0/ia_css_xnr.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_1.0/ia_css_xnr_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_1.0/ia_css_xnr_table.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_1.0/ia_css_xnr_table.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_1.0/ia_css_xnr_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_2/ia_css_ynr2.host.c9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_2/ia_css_ynr2.host.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_2/ia_css_ynr2_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_2/ia_css_ynr2_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp/modes/interface/input_buf.isp.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h8
-rw-r--r--drivers/staging/media/atomisp/pci/isp/modes/interface/isp_types.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_public.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_support.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2401_input_system_global.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2401_input_system_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp2401_input_system_private.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp_acquisition_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/isp_capture_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/mamoiada_params.h9
-rw-r--r--drivers/staging/media/atomisp/pci/mmu/isp_mmu.c11
-rw-r--r--drivers/staging/media/atomisp/pci/mmu/sh_mmu_mrfld.c11
-rw-r--r--drivers/staging/media/atomisp/pci/mmu_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c11
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/bufq/interface/ia_css_bufq.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/bufq/interface/ia_css_bufq_comm.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/bufq/src/bufq.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug_internal.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug_pipe.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/event/interface/ia_css_event.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/event/src/event.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/eventq/interface/ia_css_eventq.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/eventq/src/eventq.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame_comm.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c11
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/ifmtr/interface/ia_css_ifmtr.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/ifmtr/src/ifmtr.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/inputfifo/interface/ia_css_inputfifo.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/inputfifo/src/inputfifo.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isp_param/interface/ia_css_isp_param.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isp_param/interface/ia_css_isp_param_types.h8
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isp_param/src/isp_param.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys_comm.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_init.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline_common.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/pipeline/src/pipeline.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue_comm.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr_vbuf.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/rmgr/src/rmgr.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/rmgr/src/rmgr_vbuf.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/spctrl/interface/ia_css_spctrl.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/spctrl/interface/ia_css_spctrl_comm.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/spctrl/src/spctrl.c9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/tagger/interface/ia_css_tagger_common.h9
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/timer/src/timer.c9
-rw-r--r--drivers/staging/media/atomisp/pci/scalar_processor_2400_params.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css.c12
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_firmware.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_firmware.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_frac.h15
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_host_data.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_hrt.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_hrt.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_internal.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_legacy.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_metrics.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_metrics.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_mipi.c11
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_mipi.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_mmu.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_param_dvs.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_param_dvs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_param_shading.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_param_shading.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_params.c11
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_params.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_params_internal.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_properties.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_sp.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_sp.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_stream_format.c9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_stream_format.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_struct.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_uds.h9
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_version.c9
-rw-r--r--drivers/staging/media/atomisp/pci/str2mem_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/streaming_to_mipi_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/system_local.c9
-rw-r--r--drivers/staging/media/atomisp/pci/system_local.h9
-rw-r--r--drivers/staging/media/atomisp/pci/timed_controller_defs.h9
-rw-r--r--drivers/staging/media/atomisp/pci/version.h9
-rw-r--r--drivers/staging/media/av7110/av7110.h4
-rw-r--r--drivers/staging/media/av7110/av7110_ca.c25
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-isc-base.c2
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c2
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c2
-rw-r--r--drivers/staging/media/imx/imx-media-capture.c2
-rw-r--r--drivers/staging/media/imx/imx-media-csc-scaler.c2
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c2
-rw-r--r--drivers/staging/media/imx/imx-media-dev.c2
-rw-r--r--drivers/staging/media/imx/imx6-mipi-csi2.c2
-rw-r--r--drivers/staging/media/ipu3/ipu3-css-params.c6
-rw-r--r--drivers/staging/media/ipu3/ipu3-v4l2.c2
-rw-r--r--drivers/staging/media/max96712/max96712.c56
-rw-r--r--drivers/staging/media/meson/vdec/vdec.c4
-rw-r--r--drivers/staging/media/omap4iss/Kconfig12
-rw-r--r--drivers/staging/media/omap4iss/Makefile9
-rw-r--r--drivers/staging/media/omap4iss/TODO3
-rw-r--r--drivers/staging/media/omap4iss/iss.c1354
-rw-r--r--drivers/staging/media/omap4iss/iss.h247
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c1379
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.h155
-rw-r--r--drivers/staging/media/omap4iss/iss_csiphy.c277
-rw-r--r--drivers/staging/media/omap4iss/iss_csiphy.h47
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipe.c579
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipe.h63
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.c844
-rw-r--r--drivers/staging/media/omap4iss/iss_ipipeif.h89
-rw-r--r--drivers/staging/media/omap4iss/iss_regs.h899
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.c884
-rw-r--r--drivers/staging/media/omap4iss/iss_resizer.h72
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c1274
-rw-r--r--drivers/staging/media/omap4iss/iss_video.h203
-rw-r--r--drivers/staging/media/rkvdec/rkvdec.c4
-rw-r--r--drivers/staging/media/starfive/camss/stf-camss.c2
-rw-r--r--drivers/staging/media/starfive/camss/stf-video.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_video.c2
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c2
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c2
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c2
-rw-r--r--drivers/staging/media/tegra-video/csi.c2
-rw-r--r--drivers/staging/media/tegra-video/vi.c4
-rw-r--r--drivers/staging/media/tegra-video/vip.c2
-rw-r--r--drivers/staging/most/TODO7
-rw-r--r--drivers/staging/most/dim2/dim2.c2
-rw-r--r--drivers/staging/most/i2c/i2c.c4
-rw-r--r--drivers/staging/nvec/nvec.c2
-rw-r--r--drivers/staging/nvec/nvec_kbd.c2
-rw-r--r--drivers/staging/nvec/nvec_power.c2
-rw-r--r--drivers/staging/nvec/nvec_ps2.c2
-rw-r--r--drivers/staging/octeon/ethernet-tx.c6
-rw-r--r--drivers/staging/octeon/ethernet.c2
-rw-r--r--drivers/staging/olpc_dcon/Kconfig17
-rw-r--r--drivers/staging/olpc_dcon/Makefile5
-rw-r--r--drivers/staging/olpc_dcon/TODO15
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c807
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.h112
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1.c201
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c204
-rw-r--r--drivers/staging/rtl8192e/Kconfig61
-rw-r--r--drivers/staging/rtl8192e/Makefile19
-rw-r--r--drivers/staging/rtl8192e/TODO18
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/Kconfig10
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/Makefile19
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_def.h266
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c198
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h17
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c79
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h12
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c1915
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h34
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c189
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h52
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h244
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c1110
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h55
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h773
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.c123
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.h25
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c2016
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h402
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c1856
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.h155
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c84
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h12
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c37
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pci.c79
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pci.h20
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pm.c89
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pm.h16
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.c230
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.h31
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c867
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.h13
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/table.c543
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/table.h27
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BA.h60
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BAProc.c544
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HT.h223
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HTProc.c699
-rw-r--r--drivers/staging/rtl8192e/rtl819x_Qos.h43
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TS.h50
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TSProc.c450
-rw-r--r--drivers/staging/rtl8192e/rtllib.h1799
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_ccmp.c411
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_tkip.c706
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_wep.c242
-rw-r--r--drivers/staging/rtl8192e/rtllib_module.c179
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c2564
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c2309
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c534
-rw-r--r--drivers/staging/rtl8192e/rtllib_tx.c901
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c752
-rw-r--r--drivers/staging/rtl8712/Kconfig21
-rw-r--r--drivers/staging/rtl8712/Makefile35
-rw-r--r--drivers/staging/rtl8712/TODO13
-rw-r--r--drivers/staging/rtl8712/basic_types.h28
-rw-r--r--drivers/staging/rtl8712/drv_types.h175
-rw-r--r--drivers/staging/rtl8712/ethernet.h21
-rw-r--r--drivers/staging/rtl8712/hal_init.c401
-rw-r--r--drivers/staging/rtl8712/ieee80211.c415
-rw-r--r--drivers/staging/rtl8712/ieee80211.h165
-rw-r--r--drivers/staging/rtl8712/mlme_linux.c160
-rw-r--r--drivers/staging/rtl8712/mlme_osdep.h31
-rw-r--r--drivers/staging/rtl8712/mp_custom_oid.h287
-rw-r--r--drivers/staging/rtl8712/os_intfs.c482
-rw-r--r--drivers/staging/rtl8712/osdep_intf.h32
-rw-r--r--drivers/staging/rtl8712/osdep_service.h60
-rw-r--r--drivers/staging/rtl8712/recv_linux.c139
-rw-r--r--drivers/staging/rtl8712/recv_osdep.h39
-rw-r--r--drivers/staging/rtl8712/rtl8712_bitdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c409
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.h231
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h95
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h41
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h32
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h65
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h24
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c563
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.h44
-rw-r--r--drivers/staging/rtl8712/rtl8712_event.h86
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h131
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h61
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_bitdef.h68
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_regdef.h29
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h142
-rw-r--r--drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h44
-rw-r--r--drivers/staging/rtl8712/rtl8712_io.c99
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c1830
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h31
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_regdef.h20
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_bitdef.h39
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_regdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h36
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h43
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c1075
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.h145
-rw-r--r--drivers/staging/rtl8712/rtl8712_regdef.h32
-rw-r--r--drivers/staging/rtl8712/rtl8712_security_bitdef.h34
-rw-r--r--drivers/staging/rtl8712/rtl8712_spec.h121
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h163
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_regdef.h42
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h49
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_regdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_bitdef.h49
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_regdef.h36
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c732
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.h108
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c750
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h750
-rw-r--r--drivers/staging/rtl8712/rtl871x_debug.h130
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.c220
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.h88
-rw-r--r--drivers/staging/rtl8712/rtl871x_event.h109
-rw-r--r--drivers/staging/rtl8712/rtl871x_ht.h33
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.c147
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.h236
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl.h94
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c2275
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.c519
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.h109
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c354
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.h45
-rw-r--r--drivers/staging/rtl8712/rtl871x_led.h118
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c1710
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.h205
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.c724
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.h275
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.c883
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.h328
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h1034
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.c234
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.h113
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c671
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.h208
-rw-r--r--drivers/staging/rtl8712/rtl871x_rf.h55
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.c1386
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.h218
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c263
-rw-r--r--drivers/staging/rtl8712/rtl871x_wlan_sme.h35
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c1056
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.h287
-rw-r--r--drivers/staging/rtl8712/sta_info.h132
-rw-r--r--drivers/staging/rtl8712/usb_halinit.c307
-rw-r--r--drivers/staging/rtl8712/usb_intf.c638
-rw-r--r--drivers/staging/rtl8712/usb_ops.c195
-rw-r--r--drivers/staging/rtl8712/usb_ops.h38
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c508
-rw-r--r--drivers/staging/rtl8712/usb_osintf.h35
-rw-r--r--drivers/staging/rtl8712/wifi.h196
-rw-r--r--drivers/staging/rtl8712/wlan_bssdef.h223
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c181
-rw-r--r--drivers/staging/rtl8712/xmit_osdep.h52
-rw-r--r--drivers/staging/rtl8723bs/TODO4
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_cmd.c6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_efuse.c94
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme_ext.c11
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_pwrctrl.c7
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_wlan_util.c68
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_xmit.c2
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com.c42
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_intf.c137
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.c14
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c550
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c15
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c4
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_halinit.c59
-rw-r--r--drivers/staging/rtl8723bs/include/drv_types.h10
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com.h4
-rw-r--r--drivers/staging/rtl8723bs/include/hal_intf.h95
-rw-r--r--drivers/staging/rtl8723bs/include/hal_phy_cfg.h5
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_intf.h3
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_recv.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_xmit.h2
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_efuse.h4
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mlme_ext.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mp.h4
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c12
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_linux.c17
-rw-r--r--drivers/staging/rtl8723bs/os_dep/os_intfs.c31
-rw-r--r--drivers/staging/rtl8723bs/os_dep/sdio_intf.c17
-rw-r--r--drivers/staging/rts5208/Kconfig9
-rw-r--r--drivers/staging/rts5208/Makefile5
-rw-r--r--drivers/staging/rts5208/TODO7
-rw-r--r--drivers/staging/rts5208/general.c25
-rw-r--r--drivers/staging/rts5208/general.h19
-rw-r--r--drivers/staging/rts5208/ms.c4311
-rw-r--r--drivers/staging/rts5208/ms.h214
-rw-r--r--drivers/staging/rts5208/rtsx.c987
-rw-r--r--drivers/staging/rts5208/rtsx.h164
-rw-r--r--drivers/staging/rts5208/rtsx_card.c1151
-rw-r--r--drivers/staging/rts5208/rtsx_card.h1087
-rw-r--r--drivers/staging/rts5208/rtsx_chip.c2161
-rw-r--r--drivers/staging/rts5208/rtsx_chip.h987
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.c3279
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.h131
-rw-r--r--drivers/staging/rts5208/rtsx_sys.h36
-rw-r--r--drivers/staging/rts5208/rtsx_transport.c768
-rw-r--r--drivers/staging/rts5208/rtsx_transport.h57
-rw-r--r--drivers/staging/rts5208/sd.c4717
-rw-r--r--drivers/staging/rts5208/sd.h289
-rw-r--r--drivers/staging/rts5208/spi.c906
-rw-r--r--drivers/staging/rts5208/spi.h52
-rw-r--r--drivers/staging/rts5208/xd.c2145
-rw-r--r--drivers/staging/rts5208/xd.h176
-rw-r--r--drivers/staging/sm750fb/TODO5
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c3
-rw-r--r--drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h7
-rw-r--r--drivers/staging/vc04_services/interface/TESTING4
-rw-r--r--drivers/staging/vc04_services/interface/TODO13
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c532
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h3
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c696
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h55
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h3
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c44
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h21
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c7
-rw-r--r--drivers/staging/vme_user/vme_bridge.h56
-rw-r--r--drivers/staging/vt6655/Kconfig6
-rw-r--r--drivers/staging/vt6655/Makefile15
-rw-r--r--drivers/staging/vt6655/TODO21
-rw-r--r--drivers/staging/vt6655/baseband.c2257
-rw-r--r--drivers/staging/vt6655/baseband.h72
-rw-r--r--drivers/staging/vt6655/card.c836
-rw-r--r--drivers/staging/vt6655/card.h62
-rw-r--r--drivers/staging/vt6655/channel.c135
-rw-r--r--drivers/staging/vt6655/channel.h17
-rw-r--r--drivers/staging/vt6655/desc.h249
-rw-r--r--drivers/staging/vt6655/device.h292
-rw-r--r--drivers/staging/vt6655/device_cfg.h44
-rw-r--r--drivers/staging/vt6655/device_main.c1868
-rw-r--r--drivers/staging/vt6655/dpc.c145
-rw-r--r--drivers/staging/vt6655/dpc.h21
-rw-r--r--drivers/staging/vt6655/key.c143
-rw-r--r--drivers/staging/vt6655/key.h51
-rw-r--r--drivers/staging/vt6655/mac.c851
-rw-r--r--drivers/staging/vt6655/mac.h580
-rw-r--r--drivers/staging/vt6655/power.c144
-rw-r--r--drivers/staging/vt6655/power.h29
-rw-r--r--drivers/staging/vt6655/rf.c535
-rw-r--r--drivers/staging/vt6655/rf.h71
-rw-r--r--drivers/staging/vt6655/rxtx.c1462
-rw-r--r--drivers/staging/vt6655/rxtx.h184
-rw-r--r--drivers/staging/vt6655/srom.c139
-rw-r--r--drivers/staging/vt6655/srom.h85
-rw-r--r--drivers/staging/vt6655/test9
-rw-r--r--drivers/staging/vt6656/Kconfig7
-rw-r--r--drivers/staging/vt6656/Makefile15
-rw-r--r--drivers/staging/vt6656/TODO18
-rw-r--r--drivers/staging/vt6656/baseband.c455
-rw-r--r--drivers/staging/vt6656/baseband.h75
-rw-r--r--drivers/staging/vt6656/card.c456
-rw-r--r--drivers/staging/vt6656/card.h44
-rw-r--r--drivers/staging/vt6656/channel.c77
-rw-r--r--drivers/staging/vt6656/channel.h21
-rw-r--r--drivers/staging/vt6656/desc.h91
-rw-r--r--drivers/staging/vt6656/device.h386
-rw-r--r--drivers/staging/vt6656/key.c142
-rw-r--r--drivers/staging/vt6656/key.h40
-rw-r--r--drivers/staging/vt6656/mac.c183
-rw-r--r--drivers/staging/vt6656/mac.h373
-rw-r--r--drivers/staging/vt6656/main_usb.c1121
-rw-r--r--drivers/staging/vt6656/power.c112
-rw-r--r--drivers/staging/vt6656/power.h23
-rw-r--r--drivers/staging/vt6656/rf.c443
-rw-r--r--drivers/staging/vt6656/rf.h46
-rw-r--r--drivers/staging/vt6656/rxtx.c730
-rw-r--r--drivers/staging/vt6656/rxtx.h178
-rw-r--r--drivers/staging/vt6656/usbpipe.c506
-rw-r--r--drivers/staging/vt6656/usbpipe.h67
-rw-r--r--drivers/staging/vt6656/wcmd.c185
-rw-r--r--drivers/staging/vt6656/wcmd.h48
-rw-r--r--drivers/target/target_core_pscsi.c2
-rw-r--r--drivers/tc/tc.c2
-rw-r--r--drivers/thermal/Kconfig9
-rw-r--r--drivers/thermal/Makefile3
-rw-r--r--drivers/thermal/amlogic_thermal.c2
-rw-r--r--drivers/thermal/armada_thermal.c2
-rw-r--r--drivers/thermal/broadcom/bcm2835_thermal.c2
-rw-r--r--drivers/thermal/broadcom/ns-thermal.c2
-rw-r--r--drivers/thermal/da9062-thermal.c6
-rw-r--r--drivers/thermal/dove_thermal.c2
-rw-r--r--drivers/thermal/gov_bang_bang.c15
-rw-r--r--drivers/thermal/gov_fair_share.c20
-rw-r--r--drivers/thermal/gov_power_allocator.c89
-rw-r--r--drivers/thermal/gov_step_wise.c22
-rw-r--r--drivers/thermal/hisi_thermal.c4
-rw-r--r--drivers/thermal/imx8mm_thermal.c2
-rw-r--r--drivers/thermal/imx_thermal.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3400_thermal.c20
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3401_thermal.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3402_thermal.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3403_thermal.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3406_thermal.c2
-rw-r--r--drivers/thermal/intel/intel_quark_dts_thermal.c2
-rw-r--r--drivers/thermal/k3_bandgap.c2
-rw-r--r--drivers/thermal/k3_j72xx_bandgap.c4
-rw-r--r--drivers/thermal/kirkwood_thermal.c2
-rw-r--r--drivers/thermal/mediatek/lvts_thermal.c6
-rw-r--r--drivers/thermal/pcie_cooling.c80
-rw-r--r--drivers/thermal/qcom/lmh.c7
-rw-r--r--drivers/thermal/qcom/qcom-spmi-adc-tm5.c7
-rw-r--r--drivers/thermal/qcom/tsens-v1.c21
-rw-r--r--drivers/thermal/qcom/tsens.c5
-rw-r--r--drivers/thermal/qcom/tsens.h2
-rw-r--r--drivers/thermal/renesas/rcar_gen3_thermal.c2
-rw-r--r--drivers/thermal/renesas/rcar_thermal.c2
-rw-r--r--drivers/thermal/renesas/rzg2l_thermal.c2
-rw-r--r--drivers/thermal/rockchip_thermal.c2
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c2
-rw-r--r--drivers/thermal/spear_thermal.c2
-rw-r--r--drivers/thermal/sprd_thermal.c2
-rw-r--r--drivers/thermal/st/st_thermal_memmap.c2
-rw-r--r--drivers/thermal/st/stm_thermal.c2
-rw-r--r--drivers/thermal/sun8i_thermal.c11
-rw-r--r--drivers/thermal/tegra/soctherm.c7
-rw-r--r--drivers/thermal/tegra/tegra-bpmp-thermal.c2
-rw-r--r--drivers/thermal/testing/zone.c41
-rw-r--r--drivers/thermal/thermal_core.c883
-rw-r--r--drivers/thermal/thermal_core.h41
-rw-r--r--drivers/thermal/thermal_debugfs.c50
-rw-r--r--drivers/thermal/thermal_helpers.c46
-rw-r--r--drivers/thermal/thermal_hwmon.c5
-rw-r--r--drivers/thermal/thermal_netlink.c253
-rw-r--r--drivers/thermal/thermal_netlink.h34
-rw-r--r--drivers/thermal/thermal_of.c71
-rw-r--r--drivers/thermal/thermal_sysfs.c132
-rw-r--r--drivers/thermal/thermal_thresholds.c240
-rw-r--r--drivers/thermal/thermal_thresholds.h19
-rw-r--r--drivers/thermal/thermal_trip.c48
-rw-r--r--drivers/thermal/ti-soc-thermal/dra752-bandgap.h4
-rw-r--r--drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h8
-rw-r--r--drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h4
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c2
-rw-r--r--drivers/thermal/uniphier_thermal.c2
-rw-r--r--drivers/thunderbolt/debugfs.c504
-rw-r--r--drivers/thunderbolt/nhi.c12
-rw-r--r--drivers/thunderbolt/retimer.c2
-rw-r--r--drivers/thunderbolt/sb_regs.h32
-rw-r--r--drivers/thunderbolt/tb.h16
-rw-r--r--drivers/thunderbolt/usb4.c20
-rw-r--r--drivers/tty/Kconfig4
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c2
-rw-r--r--drivers/tty/serial/8250/8250_bcm2835aux.c2
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c4
-rw-r--r--drivers/tty/serial/8250/8250_dw.c7
-rw-r--r--drivers/tty/serial/8250/8250_early.c4
-rw-r--r--drivers/tty/serial/8250/8250_em.c2
-rw-r--r--drivers/tty/serial/8250/8250_exar.c134
-rw-r--r--drivers/tty/serial/8250/8250_fintek.c16
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c2
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c2
-rw-r--r--drivers/tty/serial/8250/8250_ioc3.c2
-rw-r--r--drivers/tty/serial/8250/8250_lpc18xx.c2
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c6
-rw-r--r--drivers/tty/serial/8250/8250_of.c2
-rw-r--r--drivers/tty/serial/8250/8250_omap.c10
-rw-r--r--drivers/tty/serial/8250/8250_pci.c40
-rw-r--r--drivers/tty/serial/8250/8250_pcilib.c13
-rw-r--r--drivers/tty/serial/8250/8250_pcilib.h2
-rw-r--r--drivers/tty/serial/8250/8250_platform.c2
-rw-r--r--drivers/tty/serial/8250/8250_port.c29
-rw-r--r--drivers/tty/serial/8250/8250_pxa.c2
-rw-r--r--drivers/tty/serial/8250/8250_tegra.c2
-rw-r--r--drivers/tty/serial/8250/8250_uniphier.c2
-rw-r--r--drivers/tty/serial/8250/Kconfig5
-rw-r--r--drivers/tty/serial/Kconfig2
-rw-r--r--drivers/tty/serial/altera_jtaguart.c6
-rw-r--r--drivers/tty/serial/altera_uart.c6
-rw-r--r--drivers/tty/serial/amba-pl010.c2
-rw-r--r--drivers/tty/serial/amba-pl011.c11
-rw-r--r--drivers/tty/serial/ar933x_uart.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c16
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c2
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/tty/serial/cpm_uart.c4
-rw-r--r--drivers/tty/serial/digicolor-usart.c2
-rw-r--r--drivers/tty/serial/earlycon.c23
-rw-r--r--drivers/tty/serial/esp32_acm.c2
-rw-r--r--drivers/tty/serial/esp32_uart.c2
-rw-r--r--drivers/tty/serial/fsl_linflexuart.c2
-rw-r--r--drivers/tty/serial/fsl_lpuart.c23
-rw-r--r--drivers/tty/serial/imx.c137
-rw-r--r--drivers/tty/serial/lantiq.c2
-rw-r--r--drivers/tty/serial/liteuart.c2
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c2
-rw-r--r--drivers/tty/serial/ma35d1_serial.c2
-rw-r--r--drivers/tty/serial/mcf.c2
-rw-r--r--drivers/tty/serial/meson_uart.c2
-rw-r--r--drivers/tty/serial/milbeaut_usio.c2
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c2
-rw-r--r--drivers/tty/serial/msm_serial.c2
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/omap-serial.c2
-rw-r--r--drivers/tty/serial/owl-uart.c2
-rw-r--r--drivers/tty/serial/pic32_uart.c2
-rw-r--r--drivers/tty/serial/pmac_zilog.c2
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c2
-rw-r--r--drivers/tty/serial/rda-uart.c2
-rw-r--r--drivers/tty/serial/rp2.c12
-rw-r--r--drivers/tty/serial/sa1100.c2
-rw-r--r--drivers/tty/serial/samsung_tty.c15
-rw-r--r--drivers/tty/serial/sc16is7xx.c2
-rw-r--r--drivers/tty/serial/sccnxp.c2
-rw-r--r--drivers/tty/serial/serial-tegra.c2
-rw-r--r--drivers/tty/serial/serial_core.c2
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c2
-rw-r--r--drivers/tty/serial/sifive.c2
-rw-r--r--drivers/tty/serial/sprd_serial.c43
-rw-r--r--drivers/tty/serial/st-asc.c2
-rw-r--r--drivers/tty/serial/stm32-usart.c2
-rw-r--r--drivers/tty/serial/sunhv.c2
-rw-r--r--drivers/tty/serial/sunplus-uart.c2
-rw-r--r--drivers/tty/serial/sunsab.c2
-rw-r--r--drivers/tty/serial/sunsu.c2
-rw-r--r--drivers/tty/serial/sunzilog.c2
-rw-r--r--drivers/tty/serial/tegra-tcu.c2
-rw-r--r--drivers/tty/serial/timbuart.c2
-rw-r--r--drivers/tty/serial/uartlite.c2
-rw-r--r--drivers/tty/serial/ucc_uart.c4
-rw-r--r--drivers/tty/serial/xilinx_uartps.c2
-rw-r--r--drivers/tty/sysrq.c18
-rw-r--r--drivers/tty/tty_io.c2
-rw-r--r--drivers/ufs/core/ufs-mcq.c30
-rw-r--r--drivers/ufs/core/ufshcd.c581
-rw-r--r--drivers/ufs/host/tc-dwc-g210-pci.c8
-rw-r--r--drivers/ufs/host/ufs-exynos.c136
-rw-r--r--drivers/ufs/host/ufs-exynos.h2
-rw-r--r--drivers/ufs/host/ufs-mediatek.c10
-rw-r--r--drivers/ufs/host/ufs-qcom.c26
-rw-r--r--drivers/ufs/host/ufs-renesas.c9
-rw-r--r--drivers/ufs/host/ufshcd-pci.c8
-rw-r--r--drivers/uio/uio_dmem_genirq.c5
-rw-r--r--drivers/uio/uio_hv_generic.c2
-rw-r--r--drivers/uio/uio_pdrv_genirq.c5
-rw-r--r--drivers/usb/atm/ueagle-atm.c6
-rw-r--r--drivers/usb/atm/usbatm.c2
-rw-r--r--drivers/usb/c67x00/c67x00-drv.c2
-rw-r--r--drivers/usb/cdns3/cdns3-imx.c2
-rw-r--r--drivers/usb/cdns3/cdns3-pci-wrap.c4
-rw-r--r--drivers/usb/cdns3/cdns3-plat.c2
-rw-r--r--drivers/usb/cdns3/cdns3-starfive.c2
-rw-r--r--drivers/usb/cdns3/cdns3-ti.c2
-rw-r--r--drivers/usb/cdns3/cdnsp-pci.c26
-rw-r--r--drivers/usb/chipidea/ci.h2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c3
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_npcm.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_tegra.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_usb2.c2
-rw-r--r--drivers/usb/chipidea/core.c6
-rw-r--r--drivers/usb/chipidea/udc.c178
-rw-r--r--drivers/usb/chipidea/udc.h2
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c4
-rw-r--r--drivers/usb/common/common.c3
-rw-r--r--drivers/usb/common/usb-conn-gpio.c2
-rw-r--r--drivers/usb/core/config.c2
-rw-r--r--drivers/usb/core/devio.c5
-rw-r--r--drivers/usb/core/driver.c24
-rw-r--r--drivers/usb/core/endpoint.c11
-rw-r--r--drivers/usb/core/ledtrig-usbport.c3
-rw-r--r--drivers/usb/core/port.c11
-rw-r--r--drivers/usb/core/sysfs.c2
-rw-r--r--drivers/usb/core/usb.h2
-rw-r--r--drivers/usb/dwc2/Kconfig2
-rw-r--r--drivers/usb/dwc2/platform.c2
-rw-r--r--drivers/usb/dwc3/Kconfig2
-rw-r--r--drivers/usb/dwc3/core.c41
-rw-r--r--drivers/usb/dwc3/core.h14
-rw-r--r--drivers/usb/dwc3/dwc3-am62.c2
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c2
-rw-r--r--drivers/usb/dwc3/dwc3-imx8mp.c2
-rw-r--r--drivers/usb/dwc3/dwc3-keystone.c2
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c2
-rw-r--r--drivers/usb/dwc3/dwc3-octeon.c2
-rw-r--r--drivers/usb/dwc3/dwc3-of-simple.c2
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c4
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c4
-rw-r--r--drivers/usb/dwc3/dwc3-rtk.c2
-rw-r--r--drivers/usb/dwc3/dwc3-st.c2
-rw-r--r--drivers/usb/dwc3/dwc3-xilinx.c2
-rw-r--r--drivers/usb/dwc3/ep0.c4
-rw-r--r--drivers/usb/dwc3/gadget.c152
-rw-r--r--drivers/usb/dwc3/host.c2
-rw-r--r--drivers/usb/fotg210/fotg210-core.c2
-rw-r--r--drivers/usb/gadget/composite.c30
-rw-r--r--drivers/usb/gadget/config.c4
-rw-r--r--drivers/usb/gadget/configfs.c2
-rw-r--r--drivers/usb/gadget/function/Makefile4
-rw-r--r--drivers/usb/gadget/function/f_fs.c6
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c8
-rw-r--r--drivers/usb/gadget/function/f_midi.c8
-rw-r--r--drivers/usb/gadget/function/f_midi2.c4
-rw-r--r--drivers/usb/gadget/function/f_uvc.c4
-rw-r--r--drivers/usb/gadget/function/uvc.h13
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.c348
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.h16
-rw-r--r--drivers/usb/gadget/function/uvc_queue.c26
-rw-r--r--drivers/usb/gadget/function/uvc_queue.h2
-rw-r--r--drivers/usb/gadget/function/uvc_trace.c11
-rw-r--r--drivers/usb/gadget/function/uvc_trace.h60
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.c66
-rw-r--r--drivers/usb/gadget/function/uvc_video.c268
-rw-r--r--drivers/usb/gadget/legacy/hid.c2
-rw-r--r--drivers/usb/gadget/legacy/raw_gadget.c4
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/core.c2
-rw-r--r--drivers/usb/gadget/udc/aspeed_udc.c4
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c2
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bcm63xx_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c2
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-pci.c3
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c6
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c8
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c4
-rw-r--r--drivers/usb/gadget/udc/gr_udc.c2
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c2
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c2
-rw-r--r--drivers/usb/gadget/udc/mv_u3d_core.c2
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/net2272.c4
-rw-r--r--drivers/usb/gadget/udc/omap_udc.c6
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.c2
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.c9
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usbf.c4
-rw-r--r--drivers/usb/gadget/udc/rzv2m_usb3drd.c2
-rw-r--r--drivers/usb/gadget/udc/snps_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/snps_udc_plat.c2
-rw-r--r--drivers/usb/gadget/udc/tegra-xudc.c2
-rw-r--r--drivers/usb/gadget/udc/udc-xilinx.c2
-rw-r--r--drivers/usb/gadget/usbstring.c2
-rw-r--r--drivers/usb/host/bcma-hcd.c1
-rw-r--r--drivers/usb/host/ehci-atmel.c2
-rw-r--r--drivers/usb/host/ehci-brcm.c2
-rw-r--r--drivers/usb/host/ehci-exynos.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c2
-rw-r--r--drivers/usb/host/ehci-grlib.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-mv.c2
-rw-r--r--drivers/usb/host/ehci-npcm7xx.c2
-rw-r--r--drivers/usb/host/ehci-omap.c2
-rw-r--r--drivers/usb/host/ehci-orion.c2
-rw-r--r--drivers/usb/host/ehci-platform.c2
-rw-r--r--drivers/usb/host/ehci-ppc-of.c2
-rw-r--r--drivers/usb/host/ehci-sh.c2
-rw-r--r--drivers/usb/host/ehci-spear.c9
-rw-r--r--drivers/usb/host/ehci-st.c2
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/fhci-hcd.c2
-rw-r--r--drivers/usb/host/fhci-sched.c4
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/isp1362-hcd.c2
-rw-r--r--drivers/usb/host/octeon-hcd.c6
-rw-r--r--drivers/usb/host/ohci-at91.c2
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/ohci-exynos.c2
-rw-r--r--drivers/usb/host/ohci-nxp.c2
-rw-r--r--drivers/usb/host/ohci-omap.c4
-rw-r--r--drivers/usb/host/ohci-platform.c2
-rw-r--r--drivers/usb/host/ohci-ppc-of.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c2
-rw-r--r--drivers/usb/host/ohci-s3c2410.c2
-rw-r--r--drivers/usb/host/ohci-sm501.c2
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/ohci-st.c2
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c8
-rw-r--r--drivers/usb/host/r8a66597-hcd.c6
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/uhci-grlib.c2
-rw-r--r--drivers/usb/host/uhci-platform.c2
-rw-r--r--drivers/usb/host/xhci-dbgcap.c13
-rw-r--r--drivers/usb/host/xhci-debugfs.c10
-rw-r--r--drivers/usb/host/xhci-histb.c2
-rw-r--r--drivers/usb/host/xhci-hub.c6
-rw-r--r--drivers/usb/host/xhci-mem.c235
-rw-r--r--drivers/usb/host/xhci-mtk.c2
-rw-r--r--drivers/usb/host/xhci-pci.c45
-rw-r--r--drivers/usb/host/xhci-plat.c2
-rw-r--r--drivers/usb/host/xhci-rcar.c2
-rw-r--r--drivers/usb/host/xhci-ring.c302
-rw-r--r--drivers/usb/host/xhci-tegra.c2
-rw-r--r--drivers/usb/host/xhci-trace.h79
-rw-r--r--drivers/usb/host/xhci.c123
-rw-r--r--drivers/usb/host/xhci.h51
-rw-r--r--drivers/usb/isp1760/Kconfig2
-rw-r--r--drivers/usb/isp1760/isp1760-if.c2
-rw-r--r--drivers/usb/misc/chaoskey.c35
-rw-r--r--drivers/usb/misc/iowarrior.c50
-rw-r--r--drivers/usb/misc/onboard_usb_dev.c2
-rw-r--r--drivers/usb/misc/qcom_eud.c2
-rw-r--r--drivers/usb/misc/usb-ljca.c20
-rw-r--r--drivers/usb/misc/usb3503.c2
-rw-r--r--drivers/usb/misc/usbtest.c3
-rw-r--r--drivers/usb/misc/yurex.c5
-rw-r--r--drivers/usb/mon/mon_bin.c2
-rw-r--r--drivers/usb/mtu3/Kconfig2
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c4
-rw-r--r--drivers/usb/musb/Kconfig2
-rw-r--r--drivers/usb/musb/da8xx.c2
-rw-r--r--drivers/usb/musb/jz4740.c2
-rw-r--r--drivers/usb/musb/mediatek.c2
-rw-r--r--drivers/usb/musb/mpfs.c2
-rw-r--r--drivers/usb/musb/musb_core.c4
-rw-r--r--drivers/usb/musb/musb_dsps.c2
-rw-r--r--drivers/usb/musb/musb_gadget.c13
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c2
-rw-r--r--drivers/usb/musb/musb_host.c5
-rw-r--r--drivers/usb/musb/omap2430.c2
-rw-r--r--drivers/usb/musb/sunxi.c4
-rw-r--r--drivers/usb/musb/tusb6010.c2
-rw-r--r--drivers/usb/musb/ux500.c2
-rw-r--r--drivers/usb/phy/phy-ab8500-usb.c2
-rw-r--r--drivers/usb/phy/phy-am335x.c2
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c2
-rw-r--r--drivers/usb/phy/phy-generic.c2
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c2
-rw-r--r--drivers/usb/phy/phy-isp1301.c2
-rw-r--r--drivers/usb/phy/phy-keystone.c2
-rw-r--r--drivers/usb/phy/phy-mv-usb.c2
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c2
-rw-r--r--drivers/usb/phy/phy-tahvo.c2
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c2
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c2
-rw-r--r--drivers/usb/phy/phy.c2
-rw-r--r--drivers/usb/renesas_usbhs/common.c4
-rw-r--r--drivers/usb/roles/intel-xhci-usb-role-switch.c2
-rw-r--r--drivers/usb/serial/bus.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c10
-rw-r--r--drivers/usb/serial/option.c6
-rw-r--r--drivers/usb/serial/pl2303.c38
-rw-r--r--drivers/usb/serial/qcserial.c2
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/usb-serial.c4
-rw-r--r--drivers/usb/storage/ene_ub6250.c8
-rw-r--r--drivers/usb/storage/realtek_cr.c4
-rw-r--r--drivers/usb/storage/sddr09.c4
-rw-r--r--drivers/usb/storage/sddr55.c8
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/usb/typec/altmodes/displayport.c2
-rw-r--r--drivers/usb/typec/class.c205
-rw-r--r--drivers/usb/typec/class.h3
-rw-r--r--drivers/usb/typec/mux/Kconfig9
-rw-r--r--drivers/usb/typec/mux/Makefile1
-rw-r--r--drivers/usb/typec/mux/gpio-sbu-mux.c2
-rw-r--r--drivers/usb/typec/mux/intel_pmc_mux.c2
-rw-r--r--drivers/usb/typec/mux/tusb1046.c196
-rw-r--r--drivers/usb/typec/stusb160x.c7
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c2
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c8
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6360.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6370.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c96
-rw-r--r--drivers/usb/typec/tcpm/wcove.c6
-rw-r--r--drivers/usb/typec/ucsi/debugfs.c1
-rw-r--r--drivers/usb/typec/ucsi/psy.c28
-rw-r--r--drivers/usb/typec/ucsi/trace.h28
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c153
-rw-r--r--drivers/usb/typec/ucsi/ucsi.h241
-rw-r--r--drivers/usb/typec/ucsi/ucsi_acpi.c65
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c7
-rw-r--r--drivers/usb/typec/ucsi/ucsi_glink.c21
-rw-r--r--drivers/usb/usbip/vhci_hcd.c2
-rw-r--r--drivers/usb/usbip/vudc_main.c2
-rw-r--r--drivers/vdpa/ifcvf/ifcvf_base.c2
-rw-r--r--drivers/vdpa/mlx5/core/mr.c12
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.c21
-rw-r--r--drivers/vdpa/solidrun/snet_main.c14
-rw-r--r--drivers/vdpa/virtio_pci/vp_vdpa.c10
-rw-r--r--drivers/vfio/group.c6
-rw-r--r--drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c266
-rw-r--r--drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h19
-rw-r--r--drivers/vfio/pci/mlx5/cmd.c6
-rw-r--r--drivers/vfio/pci/mlx5/main.c35
-rw-r--r--drivers/vfio/pci/nvgrace-gpu/main.c2
-rw-r--r--drivers/vfio/pci/qat/main.c2
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c16
-rw-r--r--drivers/vfio/pci/virtio/Kconfig42
-rw-r--r--drivers/vfio/pci/virtio/Makefile3
-rw-r--r--drivers/vfio/pci/virtio/common.h127
-rw-r--r--drivers/vfio/pci/virtio/legacy_io.c418
-rw-r--r--drivers/vfio/pci/virtio/main.c476
-rw-r--r--drivers/vfio/pci/virtio/migrate.c1337
-rw-r--r--drivers/vfio/vfio_iommu_type1.c12
-rw-r--r--drivers/vfio/virqfd.c16
-rw-r--r--drivers/vhost/net.c2
-rw-r--r--drivers/video/backlight/88pm860x_bl.c5
-rw-r--r--drivers/video/backlight/backlight.c42
-rw-r--r--drivers/video/backlight/corgi_lcd.c17
-rw-r--r--drivers/video/backlight/hx8357.c2
-rw-r--r--drivers/video/backlight/ili922x.c7
-rw-r--r--drivers/video/backlight/ili9320.c15
-rw-r--r--drivers/video/backlight/jornada720_lcd.c10
-rw-r--r--drivers/video/backlight/ktz8866.c1
-rw-r--r--drivers/video/backlight/l4f00242t03.c32
-rw-r--r--drivers/video/backlight/lcd.c50
-rw-r--r--drivers/video/backlight/lms283gf05.c2
-rw-r--r--drivers/video/backlight/lms501kf03.c24
-rw-r--r--drivers/video/backlight/ltv350qv.c15
-rw-r--r--drivers/video/backlight/otm3225a.c2
-rw-r--r--drivers/video/backlight/platform_lcd.c20
-rw-r--r--drivers/video/backlight/tdo24m.c19
-rw-r--r--drivers/video/fbdev/clps711x-fb.c29
-rw-r--r--drivers/video/fbdev/imxfb.c32
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_spi.c6
-rw-r--r--drivers/video/fbdev/omap/lcd_ams_delta.c8
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/dispc.c27
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/dpi.c3
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/dss-of.c66
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/dss.c20
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/dss.h3
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/sdi.c3
-rw-r--r--drivers/video/fbdev/sh7760fb.c3
-rw-r--r--drivers/virt/acrn/irqfd.c13
-rw-r--r--drivers/virt/coco/Kconfig2
-rw-r--r--drivers/virt/coco/Makefile1
-rw-r--r--drivers/virt/coco/arm-cca-guest/Kconfig11
-rw-r--r--drivers/virt/coco/arm-cca-guest/Makefile2
-rw-r--r--drivers/virt/coco/arm-cca-guest/arm-cca-guest.c224
-rw-r--r--drivers/virt/coco/sev-guest/Kconfig4
-rw-r--r--drivers/virt/coco/sev-guest/sev-guest.c416
-rw-r--r--drivers/virtio/Kconfig12
-rw-r--r--drivers/virtio/virtio_pci_common.c24
-rw-r--r--drivers/virtio/virtio_pci_common.h20
-rw-r--r--drivers/virtio/virtio_pci_modern.c469
-rw-r--r--drivers/virtio/virtio_ring.c581
-rw-r--r--drivers/virtio/virtio_vdpa.c3
-rw-r--r--drivers/watchdog/Kconfig14
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/cgbc_wdt.c211
-rw-r--r--drivers/xen/events/events_base.c2
-rw-r--r--drivers/xen/privcmd.c28
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c8
-rw-r--r--fs/9p/v9fs.c21
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/Makefile1
-rw-r--r--fs/adfs/super.c186
-rw-r--r--fs/affs/super.c374
-rw-r--r--fs/aio.c3
-rw-r--r--fs/attr.c61
-rw-r--r--fs/backing-file.c54
-rw-r--r--fs/bcachefs/Kconfig1
-rw-r--r--fs/bcachefs/backpointers.c17
-rw-r--r--fs/bcachefs/bkey.c7
-rw-r--r--fs/bcachefs/btree_cache.c107
-rw-r--r--fs/bcachefs/btree_cache.h2
-rw-r--r--fs/bcachefs/btree_gc.c2
-rw-r--r--fs/bcachefs/btree_io.c6
-rw-r--r--fs/bcachefs/btree_node_scan.c2
-rw-r--r--fs/bcachefs/btree_update_interior.c33
-rw-r--r--fs/bcachefs/btree_write_buffer.c30
-rw-r--r--fs/bcachefs/btree_write_buffer.h1
-rw-r--r--fs/bcachefs/buckets.h19
-rw-r--r--fs/bcachefs/clock.c25
-rw-r--r--fs/bcachefs/ec.c19
-rw-r--r--fs/bcachefs/errcode.h1
-rw-r--r--fs/bcachefs/extents.c5
-rw-r--r--fs/bcachefs/io_read.c10
-rw-r--r--fs/bcachefs/io_write.c7
-rw-r--r--fs/bcachefs/journal_io.c5
-rw-r--r--fs/bcachefs/opts.c4
-rw-r--r--fs/bcachefs/recovery.c7
-rw-r--r--fs/bcachefs/recovery_passes.c12
-rw-r--r--fs/bcachefs/recovery_passes_types.h1
-rw-r--r--fs/bcachefs/sb-errors_format.h6
-rw-r--r--fs/bcachefs/sb-members.c4
-rw-r--r--fs/bcachefs/sb-members_format.h6
-rw-r--r--fs/bcachefs/super.c1
-rw-r--r--fs/bcachefs/tests.c5
-rw-r--r--fs/befs/linuxvfs.c199
-rw-r--r--fs/binfmt_elf.c8
-rw-r--r--fs/binfmt_elf_fdpic.c11
-rw-r--r--fs/binfmt_misc.c7
-rw-r--r--fs/btrfs/Kconfig26
-rw-r--r--fs/btrfs/Makefile3
-rw-r--r--fs/btrfs/backref.c3
-rw-r--r--fs/btrfs/bio.c2
-rw-r--r--fs/btrfs/block-group.c2
-rw-r--r--fs/btrfs/btrfs_inode.h15
-rw-r--r--fs/btrfs/compression.c14
-rw-r--r--fs/btrfs/compression.h2
-rw-r--r--fs/btrfs/ctree.c132
-rw-r--r--fs/btrfs/ctree.h13
-rw-r--r--fs/btrfs/delayed-inode.h2
-rw-r--r--fs/btrfs/delayed-ref.c329
-rw-r--r--fs/btrfs/delayed-ref.h64
-rw-r--r--fs/btrfs/dev-replace.c4
-rw-r--r--fs/btrfs/dir-item.c11
-rw-r--r--fs/btrfs/dir-item.h3
-rw-r--r--fs/btrfs/direct-io.c2
-rw-r--r--fs/btrfs/disk-io.c93
-rw-r--r--fs/btrfs/disk-io.h6
-rw-r--r--fs/btrfs/extent-tree.c104
-rw-r--r--fs/btrfs/extent_io.c118
-rw-r--r--fs/btrfs/extent_map.c122
-rw-r--r--fs/btrfs/extent_map.h3
-rw-r--r--fs/btrfs/fiemap.c6
-rw-r--r--fs/btrfs/file.c374
-rw-r--r--fs/btrfs/file.h7
-rw-r--r--fs/btrfs/free-space-cache.c22
-rw-r--r--fs/btrfs/fs.h16
-rw-r--r--fs/btrfs/inode.c505
-rw-r--r--fs/btrfs/ioctl.c483
-rw-r--r--fs/btrfs/ioctl.h2
-rw-r--r--fs/btrfs/locking.c15
-rw-r--r--fs/btrfs/locking.h1
-rw-r--r--fs/btrfs/lzo.c2
-rw-r--r--fs/btrfs/ordered-data.c14
-rw-r--r--fs/btrfs/qgroup.c90
-rw-r--r--fs/btrfs/qgroup.h17
-rw-r--r--fs/btrfs/raid-stripe-tree.c92
-rw-r--r--fs/btrfs/raid-stripe-tree.h5
-rw-r--r--fs/btrfs/raid56.c3
-rw-r--r--fs/btrfs/relocation.c2
-rw-r--r--fs/btrfs/scrub.c37
-rw-r--r--fs/btrfs/send.c61
-rw-r--r--fs/btrfs/send.h2
-rw-r--r--fs/btrfs/space-info.c12
-rw-r--r--fs/btrfs/subpage.c204
-rw-r--r--fs/btrfs/subpage.h39
-rw-r--r--fs/btrfs/super.c61
-rw-r--r--fs/btrfs/sysfs.c4
-rw-r--r--fs/btrfs/tests/btrfs-tests.c4
-rw-r--r--fs/btrfs/tests/btrfs-tests.h2
-rw-r--r--fs/btrfs/tests/raid-stripe-tree-tests.c538
-rw-r--r--fs/btrfs/transaction.c8
-rw-r--r--fs/btrfs/transaction.h2
-rw-r--r--fs/btrfs/tree-checker.c16
-rw-r--r--fs/btrfs/tree-checker.h4
-rw-r--r--fs/btrfs/tree-log.c3
-rw-r--r--fs/btrfs/tree-mod-log.c1
-rw-r--r--fs/btrfs/tree-mod-log.h1
-rw-r--r--fs/btrfs/volumes.c163
-rw-r--r--fs/btrfs/volumes.h11
-rw-r--r--fs/btrfs/xattr.c5
-rw-r--r--fs/btrfs/zlib.c2
-rw-r--r--fs/btrfs/zoned.c17
-rw-r--r--fs/btrfs/zstd.c4
-rw-r--r--fs/buffer.c13
-rw-r--r--fs/cachefiles/interface.c14
-rw-r--r--fs/cachefiles/namei.c5
-rw-r--r--fs/cachefiles/ondemand.c38
-rw-r--r--fs/ceph/addr.c22
-rw-r--r--fs/ceph/caps.c63
-rw-r--r--fs/ceph/crypto.h2
-rw-r--r--fs/ceph/debugfs.c2
-rw-r--r--fs/ceph/dir.c4
-rw-r--r--fs/ceph/export.c12
-rw-r--r--fs/ceph/inode.c2
-rw-r--r--fs/ceph/mds_client.c27
-rw-r--r--fs/ceph/mds_client.h2
-rw-r--r--fs/ceph/super.c12
-rw-r--r--fs/ceph/super.h3
-rw-r--r--fs/ceph/xattr.c2
-rw-r--r--fs/char_dev.c2
-rw-r--r--fs/compat_binfmt_elf.c10
-rw-r--r--fs/configfs/configfs_internal.h4
-rw-r--r--fs/configfs/dir.c42
-rw-r--r--fs/configfs/inode.c25
-rw-r--r--fs/coredump.c1
-rw-r--r--fs/crypto/keyring.c1
-rw-r--r--fs/dcache.c20
-rw-r--r--fs/debugfs/file.c100
-rw-r--r--fs/debugfs/inode.c63
-rw-r--r--fs/debugfs/internal.h6
-rw-r--r--fs/dlm/ast.c2
-rw-r--r--fs/dlm/config.c170
-rw-r--r--fs/dlm/config.h26
-rw-r--r--fs/dlm/lock.c73
-rw-r--r--fs/dlm/lowcomms.c8
-rw-r--r--fs/dlm/member.c2
-rw-r--r--fs/dlm/recover.c35
-rw-r--r--fs/dlm/recoverd.c2
-rw-r--r--fs/ecryptfs/crypto.c35
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h9
-rw-r--r--fs/ecryptfs/inode.c12
-rw-r--r--fs/ecryptfs/main.c401
-rw-r--r--fs/ecryptfs/mmap.c136
-rw-r--r--fs/ecryptfs/read_write.c50
-rw-r--r--fs/efs/super.c43
-rw-r--r--fs/erofs/data.c69
-rw-r--r--fs/erofs/inode.c12
-rw-r--r--fs/erofs/internal.h35
-rw-r--r--fs/erofs/super.c35
-rw-r--r--fs/erofs/sysfs.c17
-rw-r--r--fs/erofs/zdata.c221
-rw-r--r--fs/erofs/zmap.c17
-rw-r--r--fs/erofs/zutil.c155
-rw-r--r--fs/eventfd.c9
-rw-r--r--fs/eventpoll.c87
-rw-r--r--fs/exec.c35
-rw-r--r--fs/exfat/dir.c29
-rw-r--r--fs/exfat/exfat_fs.h6
-rw-r--r--fs/exfat/file.c10
-rw-r--r--fs/exfat/inode.c2
-rw-r--r--fs/exfat/namei.c194
-rw-r--r--fs/exportfs/expfs.c17
-rw-r--r--fs/ext4/balloc.c4
-rw-r--r--fs/ext4/dir.c7
-rw-r--r--fs/ext4/ext4.h22
-rw-r--r--fs/ext4/extents.c13
-rw-r--r--fs/ext4/extents_status.c8
-rw-r--r--fs/ext4/extents_status.h3
-rw-r--r--fs/ext4/fast_commit.c8
-rw-r--r--fs/ext4/file.c36
-rw-r--r--fs/ext4/fsmap.c54
-rw-r--r--fs/ext4/ialloc.c5
-rw-r--r--fs/ext4/indirect.c2
-rw-r--r--fs/ext4/inode.c109
-rw-r--r--fs/ext4/ioctl.c21
-rw-r--r--fs/ext4/mballoc.c22
-rw-r--r--fs/ext4/mballoc.h1
-rw-r--r--fs/ext4/mmp.c2
-rw-r--r--fs/ext4/move_extent.c2
-rw-r--r--fs/ext4/namei.c23
-rw-r--r--fs/ext4/page-io.c6
-rw-r--r--fs/ext4/resize.c2
-rw-r--r--fs/ext4/super.c113
-rw-r--r--fs/f2fs/acl.c5
-rw-r--r--fs/f2fs/checkpoint.c2
-rw-r--r--fs/f2fs/data.c123
-rw-r--r--fs/f2fs/debug.c111
-rw-r--r--fs/f2fs/extent_cache.c119
-rw-r--r--fs/f2fs/f2fs.h38
-rw-r--r--fs/f2fs/file.c86
-rw-r--r--fs/f2fs/gc.c19
-rw-r--r--fs/f2fs/gc.h1
-rw-r--r--fs/f2fs/inode.c23
-rw-r--r--fs/f2fs/node.c28
-rw-r--r--fs/f2fs/recovery.c9
-rw-r--r--fs/f2fs/segment.c161
-rw-r--r--fs/f2fs/segment.h72
-rw-r--r--fs/f2fs/super.c101
-rw-r--r--fs/f2fs/sysfs.c16
-rw-r--r--fs/fcntl.c49
-rw-r--r--fs/fhandle.c80
-rw-r--r--fs/file.c288
-rw-r--r--fs/file_table.c50
-rw-r--r--fs/freevxfs/vxfs_dir.h2
-rw-r--r--fs/fs-writeback.c40
-rw-r--r--fs/fs_parser.c21
-rw-r--r--fs/fsopen.c19
-rw-r--r--fs/fuse/Makefile1
-rw-r--r--fs/fuse/cuse.c29
-rw-r--r--fs/fuse/dax.c11
-rw-r--r--fs/fuse/dev.c72
-rw-r--r--fs/fuse/dir.c37
-rw-r--r--fs/fuse/file.c449
-rw-r--r--fs/fuse/fuse_i.h68
-rw-r--r--fs/fuse/inode.c67
-rw-r--r--fs/fuse/ioctl.c35
-rw-r--r--fs/fuse/passthrough.c32
-rw-r--r--fs/fuse/readdir.c33
-rw-r--r--fs/fuse/sysctl.c40
-rw-r--r--fs/fuse/virtio_fs.c90
-rw-r--r--fs/gfs2/export.c1
-rw-r--r--fs/gfs2/file.c2
-rw-r--r--fs/gfs2/glock.c119
-rw-r--r--fs/gfs2/glock.h7
-rw-r--r--fs/gfs2/glops.c11
-rw-r--r--fs/gfs2/incore.h4
-rw-r--r--fs/gfs2/inode.c1
-rw-r--r--fs/gfs2/inode.h2
-rw-r--r--fs/gfs2/lock_dlm.c29
-rw-r--r--fs/gfs2/quota.c2
-rw-r--r--fs/gfs2/rgrp.c6
-rw-r--r--fs/gfs2/super.c89
-rw-r--r--fs/hfs/super.c342
-rw-r--r--fs/hfsplus/hfsplus_fs.h7
-rw-r--r--fs/hfsplus/options.c263
-rw-r--r--fs/hfsplus/super.c84
-rw-r--r--fs/hfsplus/wrapper.c2
-rw-r--r--fs/hostfs/hostfs_kern.c5
-rw-r--r--fs/hpfs/super.c414
-rw-r--r--fs/hugetlbfs/inode.c113
-rw-r--r--fs/inode.c318
-rw-r--r--fs/internal.h18
-rw-r--r--fs/ioctl.c23
-rw-r--r--fs/iomap/buffered-io.c98
-rw-r--r--fs/iomap/direct-io.c43
-rw-r--r--fs/iomap/iter.c11
-rw-r--r--fs/iomap/trace.h3
-rw-r--r--fs/isofs/inode.c8
-rw-r--r--fs/jbd2/commit.c4
-rw-r--r--fs/jbd2/journal.c15
-rw-r--r--fs/jbd2/recovery.c311
-rw-r--r--fs/jffs2/compr_rtime.c3
-rw-r--r--fs/jffs2/compr_rubin.c5
-rw-r--r--fs/jffs2/erase.c7
-rw-r--r--fs/jffs2/gc.c2
-rw-r--r--fs/jffs2/nodemgmt.c17
-rw-r--r--fs/jffs2/readinode.c2
-rw-r--r--fs/jfs/jfs_dmap.c6
-rw-r--r--fs/jfs/jfs_dtree.c15
-rw-r--r--fs/jfs/jfs_filsys.h1
-rw-r--r--fs/jfs/super.c469
-rw-r--r--fs/jfs/xattr.c2
-rw-r--r--fs/kernel_read_file.c12
-rw-r--r--fs/libfs.c23
-rw-r--r--fs/lockd/clntxdr.c5
-rw-r--r--fs/lockd/svc4proc.c20
-rw-r--r--fs/lockd/svclock.c9
-rw-r--r--fs/lockd/svcproc.c15
-rw-r--r--fs/lockd/xdr4.c2
-rw-r--r--fs/locks.c15
-rw-r--r--fs/mpage.c2
-rw-r--r--fs/namei.c88
-rw-r--r--fs/namespace.c202
-rw-r--r--fs/netfs/buffered_read.c8
-rw-r--r--fs/netfs/buffered_write.c41
-rw-r--r--fs/netfs/fscache_io.c1
-rw-r--r--fs/netfs/fscache_volume.c3
-rw-r--r--fs/nfs/blocklayout/blocklayout.c15
-rw-r--r--fs/nfs/blocklayout/dev.c6
-rw-r--r--fs/nfs/client.c67
-rw-r--r--fs/nfs/direct.c21
-rw-r--r--fs/nfs/file.c14
-rw-r--r--fs/nfs/fs_context.c6
-rw-r--r--fs/nfs/inode.c70
-rw-r--r--fs/nfs/internal.h9
-rw-r--r--fs/nfs/io.c44
-rw-r--r--fs/nfs/localio.c99
-rw-r--r--fs/nfs/namespace.c2
-rw-r--r--fs/nfs/nfs.h4
-rw-r--r--fs/nfs/nfs42xattr.c4
-rw-r--r--fs/nfs/nfs4proc.c12
-rw-r--r--fs/nfs/nfs4state.c10
-rw-r--r--fs/nfs/super.c10
-rw-r--r--fs/nfs/write.c55
-rw-r--r--fs/nfs_common/nfslocalio.c31
-rw-r--r--fs/nfsd/export.c57
-rw-r--r--fs/nfsd/export.h7
-rw-r--r--fs/nfsd/filecache.c24
-rw-r--r--fs/nfsd/filecache.h2
-rw-r--r--fs/nfsd/lockd.c13
-rw-r--r--fs/nfsd/nfs4acl.c2
-rw-r--r--fs/nfsd/nfs4callback.c139
-rw-r--r--fs/nfsd/nfs4proc.c103
-rw-r--r--fs/nfsd/nfs4recover.c3
-rw-r--r--fs/nfsd/nfs4state.c146
-rw-r--r--fs/nfsd/nfs4xdr.c71
-rw-r--r--fs/nfsd/nfsfh.c41
-rw-r--r--fs/nfsd/nfsfh.h3
-rw-r--r--fs/nfsd/state.h40
-rw-r--r--fs/nfsd/trace.h29
-rw-r--r--fs/nfsd/vfs.c39
-rw-r--r--fs/nfsd/vfs.h6
-rw-r--r--fs/nfsd/xdr4.h8
-rw-r--r--fs/nilfs2/alloc.c148
-rw-r--r--fs/nilfs2/alloc.h4
-rw-r--r--fs/nilfs2/btnode.c2
-rw-r--r--fs/nilfs2/cpfile.c383
-rw-r--r--fs/nilfs2/dat.c98
-rw-r--r--fs/nilfs2/dir.c2
-rw-r--r--fs/nilfs2/gcinode.c4
-rw-r--r--fs/nilfs2/ifile.c10
-rw-r--r--fs/nilfs2/ifile.h4
-rw-r--r--fs/nilfs2/inode.c35
-rw-r--r--fs/nilfs2/mdt.c41
-rw-r--r--fs/nilfs2/page.c28
-rw-r--r--fs/nilfs2/page.h4
-rw-r--r--fs/nilfs2/recovery.c17
-rw-r--r--fs/nilfs2/segbuf.c17
-rw-r--r--fs/nilfs2/sufile.c160
-rw-r--r--fs/notify/dnotify/dnotify.c5
-rw-r--r--fs/notify/fanotify/Kconfig1
-rw-r--r--fs/notify/fanotify/fanotify.c1
-rw-r--r--fs/notify/fanotify/fanotify_user.c130
-rw-r--r--fs/notify/fsnotify.c23
-rw-r--r--fs/notify/inotify/inotify_user.c38
-rw-r--r--fs/notify/mark.c12
-rw-r--r--fs/ntfs3/attrib.c9
-rw-r--r--fs/ntfs3/bitmap.c62
-rw-r--r--fs/ntfs3/file.c34
-rw-r--r--fs/ntfs3/frecord.c104
-rw-r--r--fs/ntfs3/fsntfs.c2
-rw-r--r--fs/ntfs3/ntfs_fs.h3
-rw-r--r--fs/ntfs3/record.c16
-rw-r--r--fs/ntfs3/run.c40
-rw-r--r--fs/ocfs2/alloc.c2
-rw-r--r--fs/ocfs2/aops.h2
-rw-r--r--fs/ocfs2/cluster/heartbeat.c24
-rw-r--r--fs/ocfs2/cluster/quorum.c2
-rw-r--r--fs/ocfs2/dlm/dlmapi.h2
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c53
-rw-r--r--fs/ocfs2/export.c1
-rw-r--r--fs/ocfs2/file.c6
-rw-r--r--fs/ocfs2/quota.h1
-rw-r--r--fs/ocfs2/resize.c2
-rw-r--r--fs/ocfs2/super.c13
-rw-r--r--fs/ocfs2/xattr.c3
-rw-r--r--fs/open.c82
-rw-r--r--fs/overlayfs/copy_up.c3
-rw-r--r--fs/overlayfs/dir.c68
-rw-r--r--fs/overlayfs/file.c327
-rw-r--r--fs/overlayfs/inode.c37
-rw-r--r--fs/overlayfs/namei.c10
-rw-r--r--fs/overlayfs/overlayfs.h12
-rw-r--r--fs/overlayfs/params.c116
-rw-r--r--fs/overlayfs/readdir.c8
-rw-r--r--fs/overlayfs/util.c14
-rw-r--r--fs/overlayfs/xattrs.c9
-rw-r--r--fs/pidfs.c86
-rw-r--r--fs/posix_acl.c13
-rw-r--r--fs/proc/array.c2
-rw-r--r--fs/proc/base.c31
-rw-r--r--fs/proc/fd.c12
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/interrupts.c4
-rw-r--r--fs/proc/kcore.c11
-rw-r--r--fs/proc/meminfo.c2
-rw-r--r--fs/proc/proc_sysctl.c113
-rw-r--r--fs/proc/softirqs.c2
-rw-r--r--fs/proc/stat.c4
-rw-r--r--fs/proc/task_mmu.c6
-rw-r--r--fs/proc/vmcore.c9
-rw-r--r--fs/quota/Kconfig15
-rw-r--r--fs/quota/dquot.c1
-rw-r--r--fs/quota/quota.c12
-rw-r--r--fs/read_write.c161
-rw-r--r--fs/readdir.c28
-rw-r--r--fs/reiserfs/Kconfig91
-rw-r--r--fs/reiserfs/Makefile30
-rw-r--r--fs/reiserfs/README151
-rw-r--r--fs/reiserfs/acl.h78
-rw-r--r--fs/reiserfs/bitmap.c1476
-rw-r--r--fs/reiserfs/dir.c346
-rw-r--r--fs/reiserfs/do_balan.c1900
-rw-r--r--fs/reiserfs/file.c270
-rw-r--r--fs/reiserfs/fix_node.c2822
-rw-r--r--fs/reiserfs/hashes.c177
-rw-r--r--fs/reiserfs/ibalance.c1161
-rw-r--r--fs/reiserfs/inode.c3416
-rw-r--r--fs/reiserfs/ioctl.c221
-rw-r--r--fs/reiserfs/item_ops.c737
-rw-r--r--fs/reiserfs/journal.c4404
-rw-r--r--fs/reiserfs/lbalance.c1426
-rw-r--r--fs/reiserfs/lock.c101
-rw-r--r--fs/reiserfs/namei.c1725
-rw-r--r--fs/reiserfs/objectid.c216
-rw-r--r--fs/reiserfs/prints.c792
-rw-r--r--fs/reiserfs/procfs.c490
-rw-r--r--fs/reiserfs/reiserfs.h3419
-rw-r--r--fs/reiserfs/resize.c230
-rw-r--r--fs/reiserfs/stree.c2280
-rw-r--r--fs/reiserfs/super.c2646
-rw-r--r--fs/reiserfs/tail_conversion.c318
-rw-r--r--fs/reiserfs/xattr.c1039
-rw-r--r--fs/reiserfs/xattr.h117
-rw-r--r--fs/reiserfs/xattr_acl.c411
-rw-r--r--fs/reiserfs/xattr_security.c127
-rw-r--r--fs/reiserfs/xattr_trusted.c46
-rw-r--r--fs/reiserfs/xattr_user.c43
-rw-r--r--fs/remap_range.c11
-rw-r--r--fs/select.c48
-rw-r--r--fs/seq_file.c2
-rw-r--r--fs/signalfd.c9
-rw-r--r--fs/smb/client/cached_dir.c241
-rw-r--r--fs/smb/client/cached_dir.h6
-rw-r--r--fs/smb/client/cifs_spnego.c16
-rw-r--r--fs/smb/client/cifsacl.c54
-rw-r--r--fs/smb/client/cifsfs.c37
-rw-r--r--fs/smb/client/cifsfs.h4
-rw-r--r--fs/smb/client/cifsglob.h15
-rw-r--r--fs/smb/client/cifsproto.h15
-rw-r--r--fs/smb/client/cifssmb.c80
-rw-r--r--fs/smb/client/connect.c100
-rw-r--r--fs/smb/client/dfs.c193
-rw-r--r--fs/smb/client/dfs_cache.c12
-rw-r--r--fs/smb/client/fs_context.c124
-rw-r--r--fs/smb/client/fs_context.h11
-rw-r--r--fs/smb/client/inode.c30
-rw-r--r--fs/smb/client/ioctl.c11
-rw-r--r--fs/smb/client/reparse.c162
-rw-r--r--fs/smb/client/reparse.h6
-rw-r--r--fs/smb/client/sess.c5
-rw-r--r--fs/smb/client/smb1ops.c4
-rw-r--r--fs/smb/client/smb2file.c21
-rw-r--r--fs/smb/client/smb2inode.c6
-rw-r--r--fs/smb/client/smb2ops.c53
-rw-r--r--fs/smb/client/smb2pdu.c31
-rw-r--r--fs/smb/client/smb2proto.h11
-rw-r--r--fs/smb/client/smb2transport.c56
-rw-r--r--fs/smb/client/trace.h3
-rw-r--r--fs/smb/client/transport.c40
-rw-r--r--fs/smb/common/smb2pdu.h9
-rw-r--r--fs/smb/server/asn1.c6
-rw-r--r--fs/smb/server/auth.c19
-rw-r--r--fs/smb/server/connection.c8
-rw-r--r--fs/smb/server/connection.h1
-rw-r--r--fs/smb/server/crypto_ctx.c6
-rw-r--r--fs/smb/server/glob.h2
-rw-r--r--fs/smb/server/ksmbd_work.c10
-rw-r--r--fs/smb/server/mgmt/ksmbd_ida.c11
-rw-r--r--fs/smb/server/mgmt/share_config.c10
-rw-r--r--fs/smb/server/mgmt/tree_connect.c5
-rw-r--r--fs/smb/server/mgmt/user_config.c8
-rw-r--r--fs/smb/server/mgmt/user_session.c23
-rw-r--r--fs/smb/server/misc.c11
-rw-r--r--fs/smb/server/ndr.c10
-rw-r--r--fs/smb/server/oplock.c12
-rw-r--r--fs/smb/server/server.c28
-rw-r--r--fs/smb/server/smb2pdu.c76
-rw-r--r--fs/smb/server/smb_common.c14
-rw-r--r--fs/smb/server/smb_common.h2
-rw-r--r--fs/smb/server/smbacl.c23
-rw-r--r--fs/smb/server/transport_ipc.c6
-rw-r--r--fs/smb/server/transport_rdma.c13
-rw-r--r--fs/smb/server/transport_tcp.c18
-rw-r--r--fs/smb/server/unicode.c4
-rw-r--r--fs/smb/server/vfs.c12
-rw-r--r--fs/smb/server/vfs_cache.c10
-rw-r--r--fs/splice.c78
-rw-r--r--fs/stat.c98
-rw-r--r--fs/statfs.c12
-rw-r--r--fs/sync.c29
-rw-r--r--fs/sysfs/file.c30
-rw-r--r--fs/sysfs/group.c5
-rw-r--r--fs/sysfs/sysfs.h2
-rw-r--r--fs/timerfd.c44
-rw-r--r--fs/tracefs/inode.c12
-rw-r--r--fs/ubifs/ioctl.c6
-rw-r--r--fs/ubifs/journal.c13
-rw-r--r--fs/ubifs/lpt_commit.c4
-rw-r--r--fs/ubifs/orphan.c2
-rw-r--r--fs/ubifs/super.c407
-rw-r--r--fs/ubifs/tnc.c2
-rw-r--r--fs/ubifs/tnc_commit.c2
-rw-r--r--fs/ubifs/ubifs.h3
-rw-r--r--fs/ubifs/xattr.c45
-rw-r--r--fs/ufs/balloc.c107
-rw-r--r--fs/ufs/cylinder.c31
-rw-r--r--fs/ufs/dir.c29
-rw-r--r--fs/ufs/file.c1
-rw-r--r--fs/ufs/inode.c179
-rw-r--r--fs/ufs/namei.c39
-rw-r--r--fs/ufs/super.c49
-rw-r--r--fs/ufs/ufs.h12
-rw-r--r--fs/ufs/ufs_fs.h4
-rw-r--r--fs/ufs/util.c46
-rw-r--r--fs/ufs/util.h61
-rw-r--r--fs/unicode/README.utf8data8
-rw-r--r--fs/unicode/mkutf8data.c4
-rw-r--r--fs/unicode/utf8-core.c28
-rw-r--r--fs/unicode/utf8-selftest.c3
-rw-r--r--fs/unicode/utf8data.c_shipped2
-rw-r--r--fs/unicode/utf8n.h2
-rw-r--r--fs/utimes.c11
-rw-r--r--fs/xattr.c446
-rw-r--r--fs/xfs/Makefile8
-rw-r--r--fs/xfs/libxfs/xfs_ag.c256
-rw-r--r--fs/xfs/libxfs/xfs_ag.h205
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.c22
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c119
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h19
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c30
-rw-r--r--fs/xfs/libxfs/xfs_attr.c5
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c137
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h2
-rw-r--r--fs/xfs/libxfs/xfs_btree.c38
-rw-r--r--fs/xfs/libxfs/xfs_btree.h3
-rw-r--r--fs/xfs/libxfs/xfs_btree_mem.c6
-rw-r--r--fs/xfs/libxfs/xfs_defer.c6
-rw-r--r--fs/xfs/libxfs/xfs_defer.h1
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c190
-rw-r--r--fs/xfs/libxfs/xfs_format.h199
-rw-r--r--fs/xfs/libxfs/xfs_fs.h53
-rw-r--r--fs/xfs/libxfs/xfs_group.c225
-rw-r--r--fs/xfs/libxfs/xfs_group.h164
-rw-r--r--fs/xfs/libxfs/xfs_health.h89
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c175
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c31
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c90
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.h3
-rw-r--r--fs/xfs/libxfs/xfs_inode_util.c6
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h8
-rw-r--r--fs/xfs/libxfs/xfs_log_recover.h2
-rw-r--r--fs/xfs/libxfs/xfs_metadir.c481
-rw-r--r--fs/xfs/libxfs/xfs_metadir.h47
-rw-r--r--fs/xfs/libxfs/xfs_metafile.c52
-rw-r--r--fs/xfs/libxfs/xfs_metafile.h31
-rw-r--r--fs/xfs/libxfs/xfs_ondisk.h186
-rw-r--r--fs/xfs/libxfs/xfs_quota_defs.h43
-rw-r--r--fs/xfs/libxfs/xfs_refcount.c33
-rw-r--r--fs/xfs/libxfs/xfs_refcount.h2
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c17
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c42
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h6
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c28
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.c388
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.h247
-rw-r--r--fs/xfs/libxfs/xfs_rtgroup.c697
-rw-r--r--fs/xfs/libxfs/xfs_rtgroup.h284
-rw-r--r--fs/xfs/libxfs/xfs_sb.c276
-rw-r--r--fs/xfs/libxfs/xfs_sb.h6
-rw-r--r--fs/xfs/libxfs/xfs_shared.h4
-rw-r--r--fs/xfs/libxfs/xfs_trans_inode.c6
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c2
-rw-r--r--fs/xfs/libxfs/xfs_types.c44
-rw-r--r--fs/xfs/libxfs/xfs_types.h16
-rw-r--r--fs/xfs/scrub/agheader.c52
-rw-r--r--fs/xfs/scrub/agheader_repair.c42
-rw-r--r--fs/xfs/scrub/alloc.c2
-rw-r--r--fs/xfs/scrub/alloc_repair.c22
-rw-r--r--fs/xfs/scrub/bmap.c38
-rw-r--r--fs/xfs/scrub/bmap_repair.c11
-rw-r--r--fs/xfs/scrub/common.c149
-rw-r--r--fs/xfs/scrub/common.h40
-rw-r--r--fs/xfs/scrub/cow_repair.c21
-rw-r--r--fs/xfs/scrub/dir.c10
-rw-r--r--fs/xfs/scrub/dir_repair.c20
-rw-r--r--fs/xfs/scrub/dirtree.c32
-rw-r--r--fs/xfs/scrub/dirtree.h12
-rw-r--r--fs/xfs/scrub/findparent.c28
-rw-r--r--fs/xfs/scrub/fscounters.c35
-rw-r--r--fs/xfs/scrub/fscounters_repair.c9
-rw-r--r--fs/xfs/scrub/health.c54
-rw-r--r--fs/xfs/scrub/ialloc.c16
-rw-r--r--fs/xfs/scrub/ialloc_repair.c27
-rw-r--r--fs/xfs/scrub/inode.c35
-rw-r--r--fs/xfs/scrub/inode_repair.c39
-rw-r--r--fs/xfs/scrub/iscan.c4
-rw-r--r--fs/xfs/scrub/metapath.c689
-rw-r--r--fs/xfs/scrub/newbt.c52
-rw-r--r--fs/xfs/scrub/nlinks.c4
-rw-r--r--fs/xfs/scrub/nlinks_repair.c4
-rw-r--r--fs/xfs/scrub/orphanage.c4
-rw-r--r--fs/xfs/scrub/parent.c39
-rw-r--r--fs/xfs/scrub/parent_repair.c37
-rw-r--r--fs/xfs/scrub/quotacheck.c7
-rw-r--r--fs/xfs/scrub/reap.c10
-rw-r--r--fs/xfs/scrub/refcount.c3
-rw-r--r--fs/xfs/scrub/refcount_repair.c7
-rw-r--r--fs/xfs/scrub/repair.c61
-rw-r--r--fs/xfs/scrub/repair.h13
-rw-r--r--fs/xfs/scrub/rgsuper.c84
-rw-r--r--fs/xfs/scrub/rmap.c4
-rw-r--r--fs/xfs/scrub/rmap_repair.c25
-rw-r--r--fs/xfs/scrub/rtbitmap.c54
-rw-r--r--fs/xfs/scrub/rtsummary.c116
-rw-r--r--fs/xfs/scrub/rtsummary_repair.c22
-rw-r--r--fs/xfs/scrub/scrub.c52
-rw-r--r--fs/xfs/scrub/scrub.h17
-rw-r--r--fs/xfs/scrub/stats.c2
-rw-r--r--fs/xfs/scrub/tempfile.c105
-rw-r--r--fs/xfs/scrub/tempfile.h3
-rw-r--r--fs/xfs/scrub/trace.c1
-rw-r--r--fs/xfs/scrub/trace.h247
-rw-r--r--fs/xfs/xfs_bmap_item.c26
-rw-r--r--fs/xfs/xfs_bmap_util.c46
-rw-r--r--fs/xfs/xfs_buf.c9
-rw-r--r--fs/xfs/xfs_buf.h4
-rw-r--r--fs/xfs/xfs_buf_item_recover.c67
-rw-r--r--fs/xfs/xfs_discard.c308
-rw-r--r--fs/xfs/xfs_dquot.c38
-rw-r--r--fs/xfs/xfs_dquot.h18
-rw-r--r--fs/xfs/xfs_drain.c78
-rw-r--r--fs/xfs/xfs_drain.h22
-rw-r--r--fs/xfs/xfs_exchrange.c20
-rw-r--r--fs/xfs/xfs_extent_busy.c214
-rw-r--r--fs/xfs/xfs_extent_busy.h65
-rw-r--r--fs/xfs/xfs_extfree_item.c282
-rw-r--r--fs/xfs/xfs_file.c82
-rw-r--r--fs/xfs/xfs_filestream.c13
-rw-r--r--fs/xfs/xfs_fsmap.c363
-rw-r--r--fs/xfs/xfs_fsmap.h15
-rw-r--r--fs/xfs/xfs_fsops.c14
-rw-r--r--fs/xfs/xfs_handle.c16
-rw-r--r--fs/xfs/xfs_health.c278
-rw-r--r--fs/xfs/xfs_icache.c134
-rw-r--r--fs/xfs/xfs_inode.c33
-rw-r--r--fs/xfs/xfs_inode.h64
-rw-r--r--fs/xfs/xfs_inode_item.c7
-rw-r--r--fs/xfs/xfs_inode_item_recover.c2
-rw-r--r--fs/xfs/xfs_ioctl.c115
-rw-r--r--fs/xfs/xfs_iomap.c71
-rw-r--r--fs/xfs/xfs_iomap.h1
-rw-r--r--fs/xfs/xfs_iops.c47
-rw-r--r--fs/xfs/xfs_itable.c33
-rw-r--r--fs/xfs/xfs_itable.h3
-rw-r--r--fs/xfs/xfs_iunlink_item.c13
-rw-r--r--fs/xfs/xfs_iwalk.c116
-rw-r--r--fs/xfs/xfs_iwalk.h7
-rw-r--r--fs/xfs/xfs_log_cil.c3
-rw-r--r--fs/xfs/xfs_log_recover.c18
-rw-r--r--fs/xfs/xfs_message.c51
-rw-r--r--fs/xfs/xfs_message.h20
-rw-r--r--fs/xfs/xfs_mount.c61
-rw-r--r--fs/xfs/xfs_mount.h113
-rw-r--r--fs/xfs/xfs_pnfs.c3
-rw-r--r--fs/xfs/xfs_qm.c387
-rw-r--r--fs/xfs/xfs_qm_bhv.c36
-rw-r--r--fs/xfs/xfs_quota.h19
-rw-r--r--fs/xfs/xfs_refcount_item.c9
-rw-r--r--fs/xfs/xfs_reflink.c7
-rw-r--r--fs/xfs/xfs_rmap_item.c9
-rw-r--r--fs/xfs/xfs_rtalloc.c1025
-rw-r--r--fs/xfs/xfs_rtalloc.h6
-rw-r--r--fs/xfs/xfs_stats.c7
-rw-r--r--fs/xfs/xfs_super.c77
-rw-r--r--fs/xfs/xfs_trace.c5
-rw-r--r--fs/xfs/xfs_trace.h687
-rw-r--r--fs/xfs/xfs_trans.c97
-rw-r--r--fs/xfs/xfs_trans.h2
-rw-r--r--fs/xfs/xfs_trans_buf.c25
-rw-r--r--fs/xfs/xfs_trans_dquot.c17
-rw-r--r--fs/xfs/xfs_xattr.c3
-rw-r--r--include/acpi/actbl1.h2
-rw-r--r--include/acpi/actbl2.h3
-rw-r--r--include/acpi/pcc.h7
-rw-r--r--include/acpi/platform/aclinux.h2
-rw-r--r--include/acpi/processor.h2
-rw-r--r--include/asm-generic/audit_change_attr.h6
-rw-r--r--include/asm-generic/codetag.lds.h19
-rw-r--r--include/asm-generic/delay.h96
-rw-r--r--include/asm-generic/div64.h121
-rw-r--r--include/asm-generic/hugetlb.h15
-rw-r--r--include/asm-generic/io.h82
-rw-r--r--include/asm-generic/memory_model.h13
-rw-r--r--include/asm-generic/qspinlock.h2
-rw-r--r--include/asm-generic/spinlock.h87
-rw-r--r--include/asm-generic/spinlock_types.h12
-rw-r--r--include/asm-generic/text-patching.h5
-rw-r--r--include/asm-generic/ticket_spinlock.h105
-rw-r--r--include/asm-generic/vdso/vsyscall.h3
-rw-r--r--include/asm-generic/vga.h23
-rw-r--r--include/asm-generic/vmlinux.lds.h53
-rw-r--r--include/crypto/akcipher.h69
-rw-r--r--include/crypto/internal/akcipher.h4
-rw-r--r--include/crypto/internal/ecc.h14
-rw-r--r--include/crypto/internal/rsa.h29
-rw-r--r--include/crypto/internal/sig.h80
-rw-r--r--include/crypto/public_key.h3
-rw-r--r--include/crypto/sig.h152
-rw-r--r--include/drm/drm_of.h9
-rw-r--r--include/drm/intel/pciids.h (renamed from include/drm/intel/i915_pciids.h)49
-rw-r--r--include/dt-bindings/arm/qcom,ids.h7
-rw-r--r--include/dt-bindings/clock/aspeed,ast2700-scu.h163
-rw-r--r--include/dt-bindings/clock/fsd-clk.h7
-rw-r--r--include/dt-bindings/clock/imx93-clock.h6
-rw-r--r--include/dt-bindings/clock/marvell,pxa1908.h88
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-apmixedsys.h16
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-imgsys.h15
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-infracfg.h25
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-mfgcfg.h8
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-pericfg.h37
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-topckgen.h79
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-vdecsys.h9
-rw-r--r--include/dt-bindings/clock/mediatek,mt6735-vencsys.h11
-rw-r--r--include/dt-bindings/clock/mobileye,eyeq5-clk.h67
-rw-r--r--include/dt-bindings/clock/qcom,gcc-sm8450.h3
-rw-r--r--include/dt-bindings/clock/qcom,ipq5332-gcc.h20
-rw-r--r--include/dt-bindings/clock/qcom,ipq5424-gcc.h156
-rw-r--r--include/dt-bindings/clock/qcom,ipq9574-gcc.h18
-rw-r--r--include/dt-bindings/clock/qcom,qcs8300-gcc.h234
-rw-r--r--include/dt-bindings/clock/qcom,sa8775p-camcc.h108
-rw-r--r--include/dt-bindings/clock/qcom,sa8775p-dispcc.h87
-rw-r--r--include/dt-bindings/clock/qcom,sa8775p-videocc.h47
-rw-r--r--include/dt-bindings/clock/qcom,sar2130p-gcc.h185
-rw-r--r--include/dt-bindings/clock/qcom,sar2130p-gpucc.h33
-rw-r--r--include/dt-bindings/clock/r9a08g045-cpg.h1
-rw-r--r--include/dt-bindings/clock/renesas,r9a08g045-vbattb.h13
-rw-r--r--include/dt-bindings/clock/samsung,exynos8895.h453
-rw-r--r--include/dt-bindings/clock/samsung,exynosautov920.h47
-rw-r--r--include/dt-bindings/iio/adc/gehc,pmc-adc.h10
-rw-r--r--include/dt-bindings/interconnect/qcom,qcs615-rpmh.h136
-rw-r--r--include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h189
-rw-r--r--include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h137
-rw-r--r--include/dt-bindings/power/mediatek,mt6735-power-controller.h14
-rw-r--r--include/dt-bindings/power/qcom-rpmpd.h2
-rw-r--r--include/dt-bindings/reset/aspeed,ast2700-scu.h124
-rw-r--r--include/dt-bindings/reset/mediatek,mt6735-infracfg.h27
-rw-r--r--include/dt-bindings/reset/mediatek,mt6735-mfgcfg.h9
-rw-r--r--include/dt-bindings/reset/mediatek,mt6735-pericfg.h31
-rw-r--r--include/dt-bindings/reset/mediatek,mt6735-vdecsys.h9
-rw-r--r--include/dt-bindings/reset/qcom,ipq5424-gcc.h310
-rw-r--r--include/dt-bindings/reset/qcom,sar2130p-gpucc.h14
-rw-r--r--include/kunit/clk.h4
-rw-r--r--include/kunit/of.h14
-rw-r--r--include/kunit/skbuff.h5
-rw-r--r--include/kvm/arm_arch_timer.h3
-rw-r--r--include/kvm/arm_pmu.h18
-rw-r--r--include/kvm/arm_psci.h4
-rw-r--r--include/kvm/arm_vgic.h1
-rw-r--r--include/linux/acpi.h20
-rw-r--r--include/linux/acpi_dma.h9
-rw-r--r--include/linux/alarmtimer.h10
-rw-r--r--include/linux/alcor_pci.h1
-rw-r--r--include/linux/alloc_tag.h21
-rw-r--r--include/linux/amba/bus.h5
-rw-r--r--include/linux/arch_topology.h5
-rw-r--r--include/linux/arm-smccc.h32
-rw-r--r--include/linux/asn1_decoder.h1
-rw-r--r--include/linux/asn1_encoder.h1
-rw-r--r--include/linux/ath9k_platform.h51
-rw-r--r--include/linux/auxiliary_bus.h4
-rw-r--r--include/linux/avf/virtchnl.h120
-rw-r--r--include/linux/backing-file.h11
-rw-r--r--include/linux/backlight.h20
-rw-r--r--include/linux/bio-integrity.h4
-rw-r--r--include/linux/bio.h19
-rw-r--r--include/linux/blk-integrity.h5
-rw-r--r--include/linux/blk-mq.h115
-rw-r--r--include/linux/blkdev.h131
-rw-r--r--include/linux/bootmem_info.h35
-rw-r--r--include/linux/bpf-cgroup.h4
-rw-r--r--include/linux/bpf.h83
-rw-r--r--include/linux/bpf_local_storage.h12
-rw-r--r--include/linux/bpf_verifier.h67
-rw-r--r--include/linux/btf.h22
-rw-r--r--include/linux/btf_ids.h1
-rw-r--r--include/linux/ceph/ceph_fs.h4
-rw-r--r--include/linux/ceph/libceph.h6
-rw-r--r--include/linux/ceph/osd_client.h2
-rw-r--r--include/linux/ceph/pagelist.h12
-rw-r--r--include/linux/cfag12864b.h17
-rw-r--r--include/linux/cgroup-defs.h3
-rw-r--r--include/linux/cleanup.h71
-rw-r--r--include/linux/clk-provider.h37
-rw-r--r--include/linux/clk.h21
-rw-r--r--include/linux/clocksource.h1
-rw-r--r--include/linux/clocksource_ids.h1
-rw-r--r--include/linux/codetag.h40
-rw-r--r--include/linux/compiler-clang.h2
-rw-r--r--include/linux/compiler-gcc.h2
-rw-r--r--include/linux/compiler.h11
-rw-r--r--include/linux/compiler_attributes.h13
-rw-r--r--include/linux/compiler_types.h25
-rw-r--r--include/linux/cpuhotplug.h3
-rw-r--r--include/linux/cpuidle.h2
-rw-r--r--include/linux/cred.h18
-rw-r--r--include/linux/dax.h6
-rw-r--r--include/linux/debugfs.h62
-rw-r--r--include/linux/debugobjects.h12
-rw-r--r--include/linux/delay.h79
-rw-r--r--include/linux/dev_printk.h1
-rw-r--r--include/linux/dim.h5
-rw-r--r--include/linux/dma-map-ops.h2
-rw-r--r--include/linux/dma-mapping.h4
-rw-r--r--include/linux/dmar.h1
-rw-r--r--include/linux/dpll.h4
-rw-r--r--include/linux/dw_apb_timer.h3
-rw-r--r--include/linux/dynamic_queue_limits.h2
-rw-r--r--include/linux/eeprom_93cx6.h11
-rw-r--r--include/linux/efi.h17
-rw-r--r--include/linux/energy_model.h29
-rw-r--r--include/linux/entry-common.h3
-rw-r--r--include/linux/entry-kvm.h5
-rw-r--r--include/linux/ethtool.h4
-rw-r--r--include/linux/eventpoll.h2
-rw-r--r--include/linux/execmem.h49
-rw-r--r--include/linux/exportfs.h26
-rw-r--r--include/linux/f2fs_fs.h7
-rw-r--r--include/linux/fanotify.h1
-rw-r--r--include/linux/fb.h13
-rw-r--r--include/linux/fdtable.h5
-rw-r--r--include/linux/file.h8
-rw-r--r--include/linux/file_ref.h177
-rw-r--r--include/linux/filelock.h5
-rw-r--r--include/linux/filter.h1
-rw-r--r--include/linux/firmware/qcom/qcom_scm.h2
-rw-r--r--include/linux/firmware/xlnx-zynqmp.h40
-rw-r--r--include/linux/fs.h110
-rw-r--r--include/linux/fs_parser.h5
-rw-r--r--include/linux/fsl/netc_global.h19
-rw-r--r--include/linux/ftrace.h85
-rw-r--r--include/linux/ftrace_regs.h36
-rw-r--r--include/linux/gfp.h28
-rw-r--r--include/linux/gpio.h3
-rw-r--r--include/linux/hid-sensor-ids.h2
-rw-r--r--include/linux/hid.h21
-rw-r--r--include/linux/hid_bpf.h11
-rw-r--r--include/linux/highmem.h8
-rw-r--r--include/linux/hisi_acc_qm.h56
-rw-r--r--include/linux/hrtimer.h51
-rw-r--r--include/linux/huge_mm.h16
-rw-r--r--include/linux/hugetlb.h22
-rw-r--r--include/linux/hwmon.h5
-rw-r--r--include/linux/i2c-of-prober.h140
-rw-r--r--include/linux/i3c/master.h10
-rw-r--r--include/linux/ieee80211.h2
-rw-r--r--include/linux/if_ltalk.h8
-rw-r--r--include/linux/iio/backend.h17
-rw-r--r--include/linux/iio/driver.h5
-rw-r--r--include/linux/iio/events.h31
-rw-r--r--include/linux/iio/iio-opaque.h2
-rw-r--r--include/linux/iio/iio.h36
-rw-r--r--include/linux/inetdevice.h11
-rw-r--r--include/linux/input.h5
-rw-r--r--include/linux/intel_vsec.h3
-rw-r--r--include/linux/interrupt.h47
-rw-r--r--include/linux/io-pgtable.h2
-rw-r--r--include/linux/io_uring/cmd.h2
-rw-r--r--include/linux/io_uring_types.h90
-rw-r--r--include/linux/iomap.h5
-rw-r--r--include/linux/iommu.h120
-rw-r--r--include/linux/iommufd.h108
-rw-r--r--include/linux/iopoll.h52
-rw-r--r--include/linux/ioport.h32
-rw-r--r--include/linux/irqflags.h6
-rw-r--r--include/linux/irqnr.h36
-rw-r--r--include/linux/jbd2.h15
-rw-r--r--include/linux/jiffies.h15
-rw-r--r--include/linux/kasan.h12
-rw-r--r--include/linux/kfifo.h1
-rw-r--r--include/linux/khugepaged.h2
-rw-r--r--include/linux/kmemleak.h4
-rw-r--r--include/linux/ksm.h8
-rw-r--r--include/linux/kvm_host.h131
-rw-r--r--include/linux/lcd.h29
-rw-r--r--include/linux/leds.h3
-rw-r--r--include/linux/libata.h4
-rw-r--r--include/linux/list.h8
-rw-r--r--include/linux/list_lru.h26
-rw-r--r--include/linux/lockd/lockd.h6
-rw-r--r--include/linux/lockd/xdr.h2
-rw-r--r--include/linux/lockdep.h2
-rw-r--r--include/linux/logic_pio.h6
-rw-r--r--include/linux/lsm/apparmor.h17
-rw-r--r--include/linux/lsm/bpf.h16
-rw-r--r--include/linux/lsm/selinux.h16
-rw-r--r--include/linux/lsm/smack.h17
-rw-r--r--include/linux/lsm_hook_defs.h20
-rw-r--r--include/linux/maple_tree.h16
-rw-r--r--include/linux/mdio.h19
-rw-r--r--include/linux/memcontrol.h109
-rw-r--r--include/linux/mempolicy.h2
-rw-r--r--include/linux/memstick.h2
-rw-r--r--include/linux/mfd/88pm886.h9
-rw-r--r--include/linux/mfd/axp20x.h4
-rw-r--r--include/linux/mfd/cgbc.h44
-rw-r--r--include/linux/mfd/max5970.h12
-rw-r--r--include/linux/mfd/max77693-private.h11
-rw-r--r--include/linux/mfd/mt6328/core.h53
-rw-r--r--include/linux/mfd/mt6328/registers.h822
-rw-r--r--include/linux/mfd/mt6397/core.h11
-rw-r--r--include/linux/mfd/palmas.h4
-rw-r--r--include/linux/mfd/samsung/core.h1
-rw-r--r--include/linux/min_heap.h357
-rw-r--r--include/linux/misc/keba.h47
-rw-r--r--include/linux/mlx5/driver.h33
-rw-r--r--include/linux/mlx5/fs.h3
-rw-r--r--include/linux/mlx5/mlx5_ifc.h90
-rw-r--r--include/linux/mm.h95
-rw-r--r--include/linux/mm_inline.h27
-rw-r--r--include/linux/mm_types.h174
-rw-r--r--include/linux/mm_types_task.h21
-rw-r--r--include/linux/mman.h28
-rw-r--r--include/linux/mmc/card.h39
-rw-r--r--include/linux/mmc/core.h21
-rw-r--r--include/linux/mmc/host.h80
-rw-r--r--include/linux/mmc/sd.h4
-rw-r--r--include/linux/mmc/sd_uhs2.h240
-rw-r--r--include/linux/mmdebug.h6
-rw-r--r--include/linux/mmu_notifier.h7
-rw-r--r--include/linux/mmzone.h6
-rw-r--r--include/linux/module.h18
-rw-r--r--include/linux/moduleloader.h4
-rw-r--r--include/linux/mtd/nand-ecc-mxic.h4
-rw-r--r--include/linux/mtd/nand.h2
-rw-r--r--include/linux/netdevice.h100
-rw-r--r--include/linux/netlink.h7
-rw-r--r--include/linux/netpoll.h3
-rw-r--r--include/linux/nfs_xdr.h2
-rw-r--r--include/linux/nfslocalio.h21
-rw-r--r--include/linux/notifier.h2
-rw-r--r--include/linux/nvme.h149
-rw-r--r--include/linux/of.h41
-rw-r--r--include/linux/of_address.h6
-rw-r--r--include/linux/of_fdt.h5
-rw-r--r--include/linux/of_graph.h49
-rw-r--r--include/linux/of_irq.h4
-rw-r--r--include/linux/once.h4
-rw-r--r--include/linux/once_lite.h2
-rw-r--r--include/linux/oom.h1
-rw-r--r--include/linux/packing.h32
-rw-r--r--include/linux/page-flags-layout.h7
-rw-r--r--include/linux/page-flags.h22
-rw-r--r--include/linux/page-isolation.h8
-rw-r--r--include/linux/page_frag_cache.h61
-rw-r--r--include/linux/pagemap.h31
-rw-r--r--include/linux/pagewalk.h18
-rw-r--r--include/linux/pci-bwctrl.h28
-rw-r--r--include/linux/pci-epc.h38
-rw-r--r--include/linux/pci-pwrctrl.h (renamed from include/linux/pci-pwrctl.h)22
-rw-r--r--include/linux/pci-tph.h44
-rw-r--r--include/linux/pci.h70
-rw-r--r--include/linux/pci_ids.h7
-rw-r--r--include/linux/pcs/pcs-xpcs.h31
-rw-r--r--include/linux/percpu-defs.h21
-rw-r--r--include/linux/perf/arm_pmuv3.h1
-rw-r--r--include/linux/perf_event.h54
-rw-r--r--include/linux/pgalloc_tag.h202
-rw-r--r--include/linux/pgtable.h59
-rw-r--r--include/linux/phy.h40
-rw-r--r--include/linux/phy/phy-sun4i-usb.h2
-rw-r--r--include/linux/platform_data/asoc-s3c.h2
-rw-r--r--include/linux/platform_data/cros_ec_commands.h32
-rw-r--r--include/linux/platform_data/hwmon-s3c.h10
-rw-r--r--include/linux/platform_data/max6639.h15
-rw-r--r--include/linux/platform_data/media/omap4iss.h66
-rw-r--r--include/linux/platform_data/microchip-ksz.h1
-rw-r--r--include/linux/platform_data/sa11x0-serial.h1
-rw-r--r--include/linux/platform_data/x86/intel_scu_ipc.h4
-rw-r--r--include/linux/pm_domain.h15
-rw-r--r--include/linux/pm_opp.h42
-rw-r--r--include/linux/pm_wakeup.h2
-rw-r--r--include/linux/posix-timers.h72
-rw-r--r--include/linux/posix_acl.h6
-rw-r--r--include/linux/power_supply.h35
-rw-r--r--include/linux/prandom.h1
-rw-r--r--include/linux/preempt.h8
-rw-r--r--include/linux/printk.h11
-rw-r--r--include/linux/pwm.h66
-rw-r--r--include/linux/random.h7
-rw-r--r--include/linux/range.h17
-rw-r--r--include/linux/rbtree_latch.h20
-rw-r--r--include/linux/rcupdate.h2
-rw-r--r--include/linux/rcupdate_trace.h5
-rw-r--r--include/linux/rcutiny.h1
-rw-r--r--include/linux/rcutree.h1
-rw-r--r--include/linux/regmap.h63
-rw-r--r--include/linux/regulator/consumer.h37
-rw-r--r--include/linux/regulator/driver.h7
-rw-r--r--include/linux/regulator/machine.h5
-rw-r--r--include/linux/reset.h274
-rw-r--r--include/linux/rmap.h17
-rw-r--r--include/linux/rtc/m48t59.h3
-rw-r--r--include/linux/rtnetlink.h66
-rw-r--r--include/linux/rtsx_common.h1
-rw-r--r--include/linux/rtsx_usb.h4
-rw-r--r--include/linux/rwlock.h2
-rw-r--r--include/linux/rwlock_api_smp.h2
-rw-r--r--include/linux/rwlock_rt.h10
-rw-r--r--include/linux/scatterlist.h2
-rw-r--r--include/linux/sched.h36
-rw-r--r--include/linux/sched/coredump.h82
-rw-r--r--include/linux/sched/ext.h3
-rw-r--r--include/linux/sched/signal.h4
-rw-r--r--include/linux/sched/task_stack.h4
-rw-r--r--include/linux/seccomp.h5
-rw-r--r--include/linux/security.h98
-rw-r--r--include/linux/sed-opal.h1
-rw-r--r--include/linux/seqlock.h98
-rw-r--r--include/linux/serial_core.h4
-rw-r--r--include/linux/serio.h3
-rw-r--r--include/linux/set_memory.h6
-rw-r--r--include/linux/shmem_fs.h12
-rw-r--r--include/linux/skbuff.h65
-rw-r--r--include/linux/slab.h61
-rw-r--r--include/linux/soc/mediatek/dvfsrc.h36
-rw-r--r--include/linux/soc/mediatek/infracfg.h5
-rw-r--r--include/linux/soc/mediatek/mtk_sip_svc.h3
-rw-r--r--include/linux/soc/qcom/llcc-qcom.h14
-rw-r--r--include/linux/soc/ti/ti_sci_protocol.h30
-rw-r--r--include/linux/sockptr.h6
-rw-r--r--include/linux/soundwire/sdw.h250
-rw-r--r--include/linux/soundwire/sdw_amd.h13
-rw-r--r--include/linux/soundwire/sdw_intel.h8
-rw-r--r--include/linux/spi/spi-mem.h8
-rw-r--r--include/linux/spi/spi.h30
-rw-r--r--include/linux/spinlock_api_smp.h2
-rw-r--r--include/linux/spinlock_rt.h28
-rw-r--r--include/linux/spinlock_types_up.h2
-rw-r--r--include/linux/spinlock_up.h2
-rw-r--r--include/linux/srcu.h92
-rw-r--r--include/linux/srcutiny.h3
-rw-r--r--include/linux/srcutree.h67
-rw-r--r--include/linux/string.h1
-rw-r--r--include/linux/sunrpc/xdr.h21
-rw-r--r--include/linux/sunrpc/xdrgen/_defs.h9
-rw-r--r--include/linux/swapops.h24
-rw-r--r--include/linux/syscalls.h13
-rw-r--r--include/linux/sysctl.h18
-rw-r--r--include/linux/sysfb.h7
-rw-r--r--include/linux/sysfs.h99
-rw-r--r--include/linux/tcp.h3
-rw-r--r--include/linux/text-patching.h15
-rw-r--r--include/linux/thermal.h6
-rw-r--r--include/linux/thread_info.h21
-rw-r--r--include/linux/tick.h2
-rw-r--r--include/linux/timekeeper_internal.h114
-rw-r--r--include/linux/timekeeping.h7
-rw-r--r--include/linux/timex.h8
-rw-r--r--include/linux/tpm.h3
-rw-r--r--include/linux/tpm_eventlog.h2
-rw-r--r--include/linux/trace_events.h18
-rw-r--r--include/linux/tracepoint-defs.h14
-rw-r--r--include/linux/tracepoint.h197
-rw-r--r--include/linux/types.h3
-rw-r--r--include/linux/uaccess.h97
-rw-r--r--include/linux/udp.h11
-rw-r--r--include/linux/unicode.h4
-rw-r--r--include/linux/uprobes.h83
-rw-r--r--include/linux/usb.h7
-rw-r--r--include/linux/usb/chipidea.h1
-rw-r--r--include/linux/usb/storage.h2
-rw-r--r--include/linux/usb/typec.h22
-rw-r--r--include/linux/usb/uvc.h6
-rw-r--r--include/linux/user_namespace.h3
-rw-r--r--include/linux/util_macros.h56
-rw-r--r--include/linux/virtio.h14
-rw-r--r--include/linux/virtio_pci_admin.h11
-rw-r--r--include/linux/vm_event_item.h2
-rw-r--r--include/linux/vmalloc.h63
-rw-r--r--include/linux/vt_buffer.h24
-rw-r--r--include/linux/wait.h5
-rw-r--r--include/linux/wait_bit.h444
-rw-r--r--include/linux/wireless.h5
-rw-r--r--include/linux/wmi.h12
-rw-r--r--include/linux/workqueue.h2
-rw-r--r--include/linux/writeback.h32
-rw-r--r--include/linux/ww_mutex.h14
-rw-r--r--include/linux/wwan.h4
-rw-r--r--include/linux/xattr.h4
-rw-r--r--include/linux/zswap.h2
-rw-r--r--include/media/i2c/mt9p031.h18
-rw-r--r--include/media/i2c/ths7303.h2
-rw-r--r--include/media/media-entity.h10
-rw-r--r--include/media/media-request.h2
-rw-r--r--include/media/v4l2-dev.h15
-rw-r--r--include/media/v4l2-dv-timings.h66
-rw-r--r--include/media/v4l2-subdev.h17
-rw-r--r--include/net/act_api.h1
-rw-r--r--include/net/bluetooth/hci.h19
-rw-r--r--include/net/bluetooth/hci_core.h85
-rw-r--r--include/net/bluetooth/mgmt.h10
-rw-r--r--include/net/bond_options.h2
-rw-r--r--include/net/busy_poll.h3
-rw-r--r--include/net/caif/cfsrvl.h1
-rw-r--r--include/net/cfg80211.h23
-rw-r--r--include/net/checksum.h6
-rw-r--r--include/net/devlink.h13
-rw-r--r--include/net/dropreason-core.h66
-rw-r--r--include/net/dsa.h15
-rw-r--r--include/net/eee.h5
-rw-r--r--include/net/fib_notifier.h2
-rw-r--r--include/net/fib_rules.h2
-rw-r--r--include/net/flow_offload.h1
-rw-r--r--include/net/genetlink.h8
-rw-r--r--include/net/inet_connection_sock.h9
-rw-r--r--include/net/inet_sock.h12
-rw-r--r--include/net/ip.h13
-rw-r--r--include/net/ip6_fib.h8
-rw-r--r--include/net/ip_fib.h19
-rw-r--r--include/net/ip_tunnels.h23
-rw-r--r--include/net/iw_handler.h41
-rw-r--r--include/net/l3mdev.h2
-rw-r--r--include/net/lib80211.h122
-rw-r--r--include/net/mac80211.h80
-rw-r--r--include/net/mana/gdma.h6
-rw-r--r--include/net/mana/mana.h10
-rw-r--r--include/net/mctp.h18
-rw-r--r--include/net/mctpdevice.h4
-rw-r--r--include/net/neighbour.h27
-rw-r--r--include/net/neighbour_tables.h12
-rw-r--r--include/net/net_debug.h6
-rw-r--r--include/net/net_namespace.h4
-rw-r--r--include/net/net_shaper.h120
-rw-r--r--include/net/netfilter/nf_tables.h32
-rw-r--r--include/net/netlabel.h3
-rw-r--r--include/net/netlink.h263
-rw-r--r--include/net/netns/core.h1
-rw-r--r--include/net/netns/ipv4.h9
-rw-r--r--include/net/netns/xfrm.h1
-rw-r--r--include/net/nfc/nci.h2
-rw-r--r--include/net/nfc/nci_core.h4
-rw-r--r--include/net/nfc/nfc.h4
-rw-r--r--include/net/phonet/pn_dev.h8
-rw-r--r--include/net/pkt_cls.h1
-rw-r--r--include/net/route.h43
-rw-r--r--include/net/rtnetlink.h34
-rw-r--r--include/net/sock.h55
-rw-r--r--include/net/tcp.h26
-rw-r--r--include/net/tcp_ao.h3
-rw-r--r--include/net/tls.h12
-rw-r--r--include/net/udp.h137
-rw-r--r--include/net/xdp_sock_drv.h14
-rw-r--r--include/net/xfrm.h17
-rw-r--r--include/net/xsk_buff_pool.h23
-rw-r--r--include/rdma/ib_verbs.h17
-rw-r--r--include/rdma/uverbs_types.h33
-rw-r--r--include/scsi/libfcoe.h2
-rw-r--r--include/soc/amlogic/reset-meson-aux.h23
-rw-r--r--include/soc/fsl/qman.h2
-rw-r--r--include/soc/nuvoton/clock-npcm8xx.h18
-rw-r--r--include/sound/adau1373.h33
-rw-r--r--include/sound/compress_driver.h50
-rw-r--r--include/sound/hda-mlink.h4
-rw-r--r--include/sound/hda_register.h2
-rw-r--r--include/sound/pcm.h34
-rw-r--r--include/sound/sdca.h62
-rw-r--r--include/sound/sdca_function.h55
-rw-r--r--include/sound/soc-acpi.h8
-rw-r--r--include/sound/soc-dai.h11
-rw-r--r--include/sound/soc.h26
-rw-r--r--include/sound/soc_sdw_utils.h10
-rw-r--r--include/sound/sof/ext_manifest.h1
-rw-r--r--include/sound/tas2781.h1
-rw-r--r--include/trace/bpf_probe.h14
-rw-r--r--include/trace/define_trace.h17
-rw-r--r--include/trace/events/block.h6
-rw-r--r--include/trace/events/btrfs.h39
-rw-r--r--include/trace/events/dma.h213
-rw-r--r--include/trace/events/hugetlbfs.h156
-rw-r--r--include/trace/events/io_uring.h24
-rw-r--r--include/trace/events/kvm.h35
-rw-r--r--include/trace/events/mce.h49
-rw-r--r--include/trace/events/memcg.h106
-rw-r--r--include/trace/events/mmap_lock.h14
-rw-r--r--include/trace/events/netfs.h2
-rw-r--r--include/trace/events/preemptirq.h8
-rw-r--r--include/trace/events/pwm.h134
-rw-r--r--include/trace/events/rust_sample.h31
-rw-r--r--include/trace/events/rxrpc.h26
-rw-r--r--include/trace/events/sunrpc.h4
-rw-r--r--include/trace/events/syscalls.h4
-rw-r--r--include/trace/events/timestamp.h124
-rw-r--r--include/trace/events/vmscan.h45
-rw-r--r--include/trace/perf.h44
-rw-r--r--include/trace/stages/stage3_trace_output.h8
-rw-r--r--include/trace/stages/stage7_class_define.h1
-rw-r--r--include/trace/trace_events.h62
-rw-r--r--include/uapi/asm-generic/ioctl.h14
-rw-r--r--include/uapi/asm-generic/mman-common.h3
-rw-r--r--include/uapi/asm-generic/mman.h4
-rw-r--r--include/uapi/asm-generic/siginfo.h2
-rw-r--r--include/uapi/asm-generic/socket.h2
-rw-r--r--include/uapi/asm-generic/unistd.h11
-rw-r--r--include/uapi/drm/drm_fourcc.h1
-rw-r--r--include/uapi/drm/msm_drm.h5
-rw-r--r--include/uapi/linux/batadv_packet.h29
-rw-r--r--include/uapi/linux/bpf.h9
-rw-r--r--include/uapi/linux/btrfs.h25
-rw-r--r--include/uapi/linux/cryptouser.h5
-rw-r--r--include/uapi/linux/dpll.h24
-rw-r--r--include/uapi/linux/elf.h2
-rw-r--r--include/uapi/linux/ethtool.h7
-rw-r--r--include/uapi/linux/f2fs.h1
-rw-r--r--include/uapi/linux/fanotify.h1
-rw-r--r--include/uapi/linux/fcntl.h5
-rw-r--r--include/uapi/linux/if_link.h17
-rw-r--r--include/uapi/linux/iio/types.h1
-rw-r--r--include/uapi/linux/io_uring.h105
-rw-r--r--include/uapi/linux/iommufd.h224
-rw-r--r--include/uapi/linux/kfd_sysfs.h3
-rw-r--r--include/uapi/linux/kvm.h8
-rw-r--r--include/uapi/linux/media-bus-format.h4
-rw-r--r--include/uapi/linux/media/raspberrypi/pisp_fe_config.h273
-rw-r--r--include/uapi/linux/media/raspberrypi/pisp_fe_statistics.h64
-rw-r--r--include/uapi/linux/mount.h14
-rw-r--r--include/uapi/linux/net_shaper.h95
-rw-r--r--include/uapi/linux/netdev.h4
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h18
-rw-r--r--include/uapi/linux/nfc.h3
-rw-r--r--include/uapi/linux/nl80211.h10
-rw-r--r--include/uapi/linux/pci_regs.h38
-rw-r--r--include/uapi/linux/perf_event.h11
-rw-r--r--include/uapi/linux/pidfd.h50
-rw-r--r--include/uapi/linux/pkt_sched.h2
-rw-r--r--include/uapi/linux/prctl.h27
-rw-r--r--include/uapi/linux/psci.h5
-rw-r--r--include/uapi/linux/reiserfs_fs.h27
-rw-r--r--include/uapi/linux/reiserfs_xattr.h25
-rw-r--r--include/uapi/linux/rtnetlink.h2
-rw-r--r--include/uapi/linux/sed-opal.h1
-rw-r--r--include/uapi/linux/thermal.h29
-rw-r--r--include/uapi/linux/types.h1
-rw-r--r--include/uapi/linux/ublk_cmd.h18
-rw-r--r--include/uapi/linux/udp.h2
-rw-r--r--include/uapi/linux/usb/video.h58
-rw-r--r--include/uapi/linux/v4l2-dv-timings.h2
-rw-r--r--include/uapi/linux/vfio.h2
-rw-r--r--include/uapi/linux/videodev2.h6
-rw-r--r--include/uapi/linux/virtio_crypto.h1
-rw-r--r--include/uapi/linux/virtio_pci.h131
-rw-r--r--include/uapi/linux/vmclock-abi.h182
-rw-r--r--include/uapi/linux/xattr.h7
-rw-r--r--include/uapi/linux/xfrm.h2
-rw-r--r--include/uapi/rdma/efa-abi.h3
-rw-r--r--include/uapi/rdma/mlx5-abi.h5
-rw-r--r--include/uapi/rdma/rdma_netlink.h2
-rw-r--r--include/uapi/sound/compress_offload.h66
-rw-r--r--include/ufs/ufshcd.h21
-rw-r--r--include/vdso/datapage.h8
-rw-r--r--include/vdso/page.h31
-rw-r--r--include/video/omapfb_dss.h8
-rw-r--r--include/video/platform_lcd.h3
-rw-r--r--init/Kconfig11
-rw-r--r--init/init_task.c5
-rw-r--r--init/initramfs.c15
-rw-r--r--init/main.c5
-rw-r--r--io_uring/cancel.c20
-rw-r--r--io_uring/cancel.h1
-rw-r--r--io_uring/eventfd.c137
-rw-r--r--io_uring/fdinfo.c88
-rw-r--r--io_uring/filetable.c71
-rw-r--r--io_uring/filetable.h35
-rw-r--r--io_uring/futex.c4
-rw-r--r--io_uring/futex.h4
-rw-r--r--io_uring/io_uring.c516
-rw-r--r--io_uring/io_uring.h39
-rw-r--r--io_uring/memmap.c94
-rw-r--r--io_uring/memmap.h14
-rw-r--r--io_uring/msg_ring.c91
-rw-r--r--io_uring/msg_ring.h1
-rw-r--r--io_uring/napi.c184
-rw-r--r--io_uring/napi.h8
-rw-r--r--io_uring/net.c112
-rw-r--r--io_uring/nop.c51
-rw-r--r--io_uring/notif.c7
-rw-r--r--io_uring/opdef.c2
-rw-r--r--io_uring/poll.c181
-rw-r--r--io_uring/poll.h2
-rw-r--r--io_uring/register.c300
-rw-r--r--io_uring/rsrc.c657
-rw-r--r--io_uring/rsrc.h97
-rw-r--r--io_uring/rw.c109
-rw-r--r--io_uring/splice.c42
-rw-r--r--io_uring/splice.h1
-rw-r--r--io_uring/sqpoll.c32
-rw-r--r--io_uring/statx.c3
-rw-r--r--io_uring/tctx.c14
-rw-r--r--io_uring/timeout.c17
-rw-r--r--io_uring/timeout.h2
-rw-r--r--io_uring/uring_cmd.c33
-rw-r--r--io_uring/uring_cmd.h2
-rw-r--r--io_uring/waitid.c6
-rw-r--r--io_uring/waitid.h2
-rw-r--r--io_uring/xattr.c97
-rw-r--r--ipc/mqueue.c109
-rw-r--r--ipc/msg.c2
-rw-r--r--ipc/namespace.c4
-rw-r--r--kernel/Kconfig.kexec2
-rw-r--r--kernel/Kconfig.preempt27
-rw-r--r--kernel/audit.c23
-rw-r--r--kernel/audit.h7
-rw-r--r--kernel/auditfilter.c9
-rw-r--r--kernel/auditsc.c75
-rw-r--r--kernel/bpf/Makefile3
-rw-r--r--kernel/bpf/arena.c38
-rw-r--r--kernel/bpf/arraymap.c26
-rw-r--r--kernel/bpf/bpf_cgrp_storage.c4
-rw-r--r--kernel/bpf/bpf_inode_storage.c5
-rw-r--r--kernel/bpf/bpf_local_storage.c79
-rw-r--r--kernel/bpf/bpf_struct_ops.c115
-rw-r--r--kernel/bpf/bpf_task_storage.c8
-rw-r--r--kernel/bpf/btf.c57
-rw-r--r--kernel/bpf/cgroup.c2
-rw-r--r--kernel/bpf/core.c8
-rw-r--r--kernel/bpf/dispatcher.c3
-rw-r--r--kernel/bpf/hashtab.c56
-rw-r--r--kernel/bpf/helpers.c29
-rw-r--r--kernel/bpf/kmem_cache_iter.c238
-rw-r--r--kernel/bpf/memalloc.c5
-rw-r--r--kernel/bpf/range_tree.c272
-rw-r--r--kernel/bpf/range_tree.h21
-rw-r--r--kernel/bpf/syscall.c191
-rw-r--r--kernel/bpf/task_iter.c6
-rw-r--r--kernel/bpf/token.c1
-rw-r--r--kernel/bpf/trampoline.c60
-rw-r--r--kernel/bpf/verifier.c597
-rw-r--r--kernel/cgroup/cgroup.c42
-rw-r--r--kernel/cgroup/cpuset.c157
-rw-r--r--kernel/cgroup/freezer.c97
-rw-r--r--kernel/cgroup/rstat.c19
-rw-r--r--kernel/configs/debug.config1
-rw-r--r--kernel/cpu.c5
-rw-r--r--kernel/crash_core.c6
-rw-r--r--kernel/cred.c6
-rw-r--r--kernel/debug/kdb/kdb_bp.c6
-rw-r--r--kernel/debug/kdb/kdb_keyboard.c33
-rw-r--r--kernel/debug/kdb/kdb_main.c69
-rw-r--r--kernel/dma/Kconfig17
-rw-r--r--kernel/dma/coherent.c14
-rw-r--r--kernel/dma/debug.c99
-rw-r--r--kernel/dma/mapping.c37
-rw-r--r--kernel/entry/common.c2
-rw-r--r--kernel/entry/kvm.c4
-rw-r--r--kernel/events/core.c180
-rw-r--r--kernel/events/hw_breakpoint.c4
-rw-r--r--kernel/events/internal.h1
-rw-r--r--kernel/events/uprobes.c609
-rw-r--r--kernel/exit.c1
-rw-r--r--kernel/fork.c37
-rw-r--r--kernel/futex/core.c36
-rw-r--r--kernel/futex/futex.h59
-rw-r--r--kernel/futex/pi.c6
-rw-r--r--kernel/hung_task.c18
-rw-r--r--kernel/irq/devres.c3
-rw-r--r--kernel/irq/irqdesc.c30
-rw-r--r--kernel/irq/irqdomain.c2
-rw-r--r--kernel/irq/proc.c12
-rw-r--r--kernel/kcmp.c4
-rw-r--r--kernel/kcsan/debugfs.c77
-rw-r--r--kernel/kprobes.c91
-rw-r--r--kernel/kthread.c2
-rw-r--r--kernel/locking/lockdep.c46
-rw-r--r--kernel/locking/mutex.c59
-rw-r--r--kernel/locking/mutex.h27
-rw-r--r--kernel/locking/osq_lock.c3
-rw-r--r--kernel/locking/qspinlock_paravirt.h36
-rw-r--r--kernel/locking/rtmutex.c53
-rw-r--r--kernel/locking/rtmutex_api.c20
-rw-r--r--kernel/locking/rtmutex_common.h3
-rw-r--r--kernel/locking/rwbase_rt.c8
-rw-r--r--kernel/locking/rwsem.c4
-rw-r--r--kernel/locking/spinlock.c8
-rw-r--r--kernel/locking/spinlock_rt.c19
-rw-r--r--kernel/locking/test-ww_mutex.c8
-rw-r--r--kernel/locking/ww_mutex.h51
-rw-r--r--kernel/module/debug_kmemleak.c3
-rw-r--r--kernel/module/dups.c1
-rw-r--r--kernel/module/internal.h7
-rw-r--r--kernel/module/kmod.c1
-rw-r--r--kernel/module/main.c732
-rw-r--r--kernel/module/strict_rwx.c3
-rw-r--r--kernel/notifier.c8
-rw-r--r--kernel/nsproxy.c5
-rw-r--r--kernel/padata.c7
-rw-r--r--kernel/pid.c20
-rw-r--r--kernel/power/energy_model.c52
-rw-r--r--kernel/power/hibernate.c5
-rw-r--r--kernel/printk/internal.h3
-rw-r--r--kernel/printk/printk.c56
-rw-r--r--kernel/printk/printk_safe.c18
-rw-r--r--kernel/rcu/Kconfig28
-rw-r--r--kernel/rcu/rcu_segcblist.h1
-rw-r--r--kernel/rcu/rcuscale.c8
-rw-r--r--kernel/rcu/rcutorture.c92
-rw-r--r--kernel/rcu/refscale.c56
-rw-r--r--kernel/rcu/srcutiny.c2
-rw-r--r--kernel/rcu/srcutree.c133
-rw-r--r--kernel/rcu/tasks.h20
-rw-r--r--kernel/rcu/tree.c24
-rw-r--r--kernel/rcu/tree_nocb.h13
-rw-r--r--kernel/rcu/tree_plugin.h22
-rw-r--r--kernel/rcu/tree_stall.h57
-rw-r--r--kernel/reboot.c15
-rw-r--r--kernel/resource.c70
-rw-r--r--kernel/scftorture.c54
-rw-r--r--kernel/sched/core.c302
-rw-r--r--kernel/sched/cpufreq_schedutil.c3
-rw-r--r--kernel/sched/deadline.c57
-rw-r--r--kernel/sched/debug.c7
-rw-r--r--kernel/sched/ext.c1023
-rw-r--r--kernel/sched/fair.c42
-rw-r--r--kernel/sched/features.h3
-rw-r--r--kernel/sched/idle.c5
-rw-r--r--kernel/sched/pelt.c2
-rw-r--r--kernel/sched/rt.c67
-rw-r--r--kernel/sched/sched.h160
-rw-r--r--kernel/sched/stats.h29
-rw-r--r--kernel/sched/syscalls.c46
-rw-r--r--kernel/sched/wait_bit.c90
-rw-r--r--kernel/signal.c527
-rw-r--r--kernel/smp.c4
-rw-r--r--kernel/softirq.c83
-rw-r--r--kernel/sys.c45
-rw-r--r--kernel/sysctl.c1
-rw-r--r--kernel/taskstats.c18
-rw-r--r--kernel/time/Kconfig5
-rw-r--r--kernel/time/Makefile2
-rw-r--r--kernel/time/alarmtimer.c96
-rw-r--r--kernel/time/clockevents.c42
-rw-r--r--kernel/time/clocksource.c40
-rw-r--r--kernel/time/hrtimer.c234
-rw-r--r--kernel/time/itimer.c22
-rw-r--r--kernel/time/ntp.c842
-rw-r--r--kernel/time/posix-cpu-timers.c72
-rw-r--r--kernel/time/posix-timers.c267
-rw-r--r--kernel/time/posix-timers.h8
-rw-r--r--kernel/time/sched_clock.c34
-rw-r--r--kernel/time/sleep_timeout.c377
-rw-r--r--kernel/time/tick-internal.h3
-rw-r--r--kernel/time/tick-sched.c27
-rw-r--r--kernel/time/time.c20
-rw-r--r--kernel/time/timekeeping.c649
-rw-r--r--kernel/time/timekeeping_debug.c13
-rw-r--r--kernel/time/timekeeping_internal.h25
-rw-r--r--kernel/time/timer.c197
-rw-r--r--kernel/time/vsyscall.c7
-rw-r--r--kernel/trace/Kconfig10
-rw-r--r--kernel/trace/bpf_trace.c116
-rw-r--r--kernel/trace/fgraph.c155
-rw-r--r--kernel/trace/ftrace.c118
-rw-r--r--kernel/trace/ring_buffer.c111
-rw-r--r--kernel/trace/ring_buffer_benchmark.c4
-rw-r--r--kernel/trace/rv/rv.c2
-rw-r--r--kernel/trace/trace.c130
-rw-r--r--kernel/trace/trace.h22
-rw-r--r--kernel/trace/trace_branch.c10
-rw-r--r--kernel/trace/trace_clock.c2
-rw-r--r--kernel/trace/trace_entries.h29
-rw-r--r--kernel/trace/trace_event_perf.c6
-rw-r--r--kernel/trace/trace_events.c2
-rw-r--r--kernel/trace/trace_events_filter.c8
-rw-r--r--kernel/trace/trace_events_hist.c11
-rw-r--r--kernel/trace/trace_events_user.c4
-rw-r--r--kernel/trace/trace_functions.c36
-rw-r--r--kernel/trace/trace_functions_graph.c272
-rw-r--r--kernel/trace/trace_hwlat.c4
-rw-r--r--kernel/trace/trace_kdb.c13
-rw-r--r--kernel/trace/trace_mmiotrace.c8
-rw-r--r--kernel/trace/trace_osnoise.c12
-rw-r--r--kernel/trace/trace_output.c19
-rw-r--r--kernel/trace/trace_preemptirq.c26
-rw-r--r--kernel/trace/trace_sched_switch.c2
-rw-r--r--kernel/trace/trace_sched_wakeup.c8
-rw-r--r--kernel/trace/trace_selftest.c1
-rw-r--r--kernel/trace/trace_syscalls.c28
-rw-r--r--kernel/trace/trace_uprobe.c12
-rw-r--r--kernel/tracepoint.c75
-rw-r--r--kernel/ucount.c11
-rw-r--r--kernel/umh.c1
-rw-r--r--kernel/watch_queue.c6
-rw-r--r--kernel/watchdog.c11
-rw-r--r--kernel/workqueue.c22
-rw-r--r--lib/Kconfig18
-rw-r--r--lib/Kconfig.debug232
-rw-r--r--lib/Kconfig.kasan7
-rw-r--r--lib/Makefile8
-rw-r--r--lib/alloc_tag.c515
-rw-r--r--lib/checksum.c11
-rw-r--r--lib/codetag.c104
-rw-r--r--lib/crc16_kunit.c155
-rw-r--r--lib/crc32.c4
-rw-r--r--lib/crypto/Makefile2
-rw-r--r--lib/crypto/mpi/mpi-bit.c1
-rw-r--r--lib/crypto/simd.c11
-rw-r--r--lib/debugobjects.c849
-rw-r--r--lib/devres.c6
-rw-r--r--lib/dim/dim.c3
-rw-r--r--lib/dim/net_dim.c10
-rw-r--r--lib/dynamic_queue_limits.c2
-rw-r--r--lib/interval_tree_test.c2
-rw-r--r--lib/iomem_copy.c136
-rw-r--r--lib/iov_iter.c68
-rw-r--r--lib/kunit/debugfs.c9
-rw-r--r--lib/kunit/kunit-test.c2
-rw-r--r--lib/kunit/string-stream-test.c1
-rw-r--r--lib/list-test.c4
-rw-r--r--lib/list_sort.c3
-rw-r--r--lib/locking-selftest.c39
-rw-r--r--lib/logic_pio.c4
-rw-r--r--lib/maple_tree.c249
-rw-r--r--lib/math/test_div64.c85
-rw-r--r--lib/min_heap.c70
-rw-r--r--lib/objpool.c18
-rw-r--r--lib/overflow_kunit.c2
-rw-r--r--lib/packing.c322
-rw-r--r--lib/packing_test.c413
-rw-r--r--lib/percpu_test.c11
-rw-r--r--lib/random32.c2
-rw-r--r--lib/rbtree_test.c2
-rw-r--r--lib/scatterlist.c4
-rw-r--r--lib/slub_kunit.c42
-rw-r--r--lib/string.c23
-rw-r--r--lib/string_helpers.c2
-rw-r--r--lib/strncpy_from_user.c5
-rw-r--r--lib/test_bpf.c2
-rw-r--r--lib/test_maple_tree.c90
-rw-r--r--lib/test_min_heap.c16
-rw-r--r--lib/test_parman.c2
-rw-r--r--lib/test_printf.c61
-rw-r--r--lib/test_scanf.c2
-rw-r--r--lib/tests/Makefile1
-rw-r--r--lib/tests/module/.gitignore4
-rw-r--r--lib/tests/module/Makefile14
-rwxr-xr-xlib/tests/module/gen_test_kallsyms.sh134
-rw-r--r--lib/util_macros_kunit.c240
-rw-r--r--lib/vsprintf.c80
-rw-r--r--mm/Kconfig6
-rw-r--r--mm/Makefile1
-rw-r--r--mm/bootmem_info.c11
-rw-r--r--mm/cma.c12
-rw-r--r--mm/damon/Kconfig2
-rw-r--r--mm/damon/core.c47
-rw-r--r--mm/damon/tests/dbgfs-kunit.h2
-rw-r--r--mm/damon/tests/vaddr-kunit.h4
-rw-r--r--mm/damon/vaddr.c9
-rw-r--r--mm/execmem.c352
-rw-r--r--mm/fadvise.c10
-rw-r--r--mm/filemap.c26
-rw-r--r--mm/folio-compat.c6
-rw-r--r--mm/gup.c148
-rw-r--r--mm/huge_memory.c287
-rw-r--r--mm/hugetlb.c17
-rw-r--r--mm/internal.h109
-rw-r--r--mm/kasan/Makefile2
-rw-r--r--mm/kasan/generic.c7
-rw-r--r--mm/kasan/hw_tags.c7
-rw-r--r--mm/kasan/init.c12
-rw-r--r--mm/kasan/kasan.h2
-rw-r--r--mm/kasan/kasan_test_c.c118
-rw-r--r--mm/kasan/kasan_test_module.c81
-rw-r--r--mm/kasan/kasan_test_rust.rs3
-rw-r--r--mm/kasan/report.c19
-rw-r--r--mm/kasan/shadow.c14
-rw-r--r--mm/kfence/kfence_test.c17
-rw-r--r--mm/khugepaged.c31
-rw-r--r--mm/kmemleak.c41
-rw-r--r--mm/kmsan/kmsan_test.c17
-rw-r--r--mm/ksm.c110
-rw-r--r--mm/list_lru.c383
-rw-r--r--mm/maccess.c11
-rw-r--r--mm/madvise.c298
-rw-r--r--mm/memcontrol-v1.c1002
-rw-r--r--mm/memcontrol-v1.h6
-rw-r--r--mm/memcontrol.c223
-rw-r--r--mm/memory-failure.c32
-rw-r--r--mm/memory.c67
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/mempolicy.c7
-rw-r--r--mm/migrate.c11
-rw-r--r--mm/mlock.c9
-rw-r--r--mm/mm_init.c12
-rw-r--r--mm/mmap.c306
-rw-r--r--mm/mmap_lock.c39
-rw-r--r--mm/mprotect.c8
-rw-r--r--mm/mremap.c106
-rw-r--r--mm/mseal.c1
-rw-r--r--mm/nommu.c11
-rw-r--r--mm/oom_kill.c1
-rw-r--r--mm/page-writeback.c71
-rw-r--r--mm/page_alloc.c172
-rw-r--r--mm/page_frag_cache.c171
-rw-r--r--mm/page_io.c26
-rw-r--r--mm/page_vma_mapped.c32
-rw-r--r--mm/pagewalk.c246
-rw-r--r--mm/percpu.c11
-rw-r--r--mm/pgtable-generic.c41
-rw-r--r--mm/process_vm_access.c4
-rw-r--r--mm/readahead.c32
-rw-r--r--mm/rmap.c45
-rw-r--r--mm/shmem.c617
-rw-r--r--mm/show_mem.c3
-rw-r--r--mm/slab.h11
-rw-r--r--mm/slab_common.c153
-rw-r--r--mm/slub.c218
-rw-r--r--mm/sparse-vmemmap.c12
-rw-r--r--mm/sparse.c10
-rw-r--r--mm/swap.c49
-rw-r--r--mm/swap_state.c3
-rw-r--r--mm/swapfile.c24
-rw-r--r--mm/truncate.c119
-rw-r--r--mm/userfaultfd.c17
-rw-r--r--mm/util.c64
-rw-r--r--mm/vma.c461
-rw-r--r--mm/vma.h103
-rw-r--r--mm/vma_internal.h5
-rw-r--r--mm/vmalloc.c52
-rw-r--r--mm/vmscan.c72
-rw-r--r--mm/vmstat.c30
-rw-r--r--mm/workingset.c34
-rw-r--r--mm/zsmalloc.c86
-rw-r--r--mm/zswap.c249
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/8021q/vlan_netlink.c6
-rw-r--r--net/9p/Kconfig4
-rw-r--r--net/9p/trans_usbg.c4
-rw-r--r--net/9p/trans_xen.c9
-rw-r--r--net/Kconfig3
-rw-r--r--net/Kconfig.debug15
-rw-r--r--net/Makefile1
-rw-r--r--net/appletalk/Makefile2
-rw-r--r--net/appletalk/dev.c46
-rw-r--r--net/batman-adv/bat_iv_ogm.c4
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c8
-rw-r--r--net/batman-adv/main.h2
-rw-r--r--net/batman-adv/translation-table.c96
-rw-r--r--net/bluetooth/hci_conn.c230
-rw-r--r--net/bluetooth/hci_core.c28
-rw-r--r--net/bluetooth/hci_event.c49
-rw-r--r--net/bluetooth/hci_sync.c9
-rw-r--r--net/bluetooth/hci_sysfs.c15
-rw-r--r--net/bluetooth/iso.c121
-rw-r--r--net/bluetooth/l2cap_sock.c1
-rw-r--r--net/bluetooth/mgmt.c98
-rw-r--r--net/bluetooth/rfcomm/sock.c20
-rw-r--r--net/bluetooth/sco.c99
-rw-r--r--net/bridge/br_device.c2
-rw-r--r--net/bridge/br_fdb.c45
-rw-r--r--net/bridge/br_netfilter_hooks.c15
-rw-r--r--net/bridge/br_netlink.c6
-rw-r--r--net/bridge/br_private.h4
-rw-r--r--net/bridge/netfilter/Kconfig8
-rw-r--r--net/bridge/netfilter/nft_meta_bridge.c2
-rw-r--r--net/caif/cfsrvl.c6
-rw-r--r--net/can/af_can.c1
-rw-r--r--net/can/gw.c29
-rw-r--r--net/can/raw.c2
-rw-r--r--net/ceph/crypto.c12
-rw-r--r--net/ceph/crypto.h1
-rw-r--r--net/ceph/osd_client.c34
-rw-r--r--net/ceph/pagelist.c38
-rw-r--r--net/ceph/pagevec.c52
-rw-r--r--net/core/Makefile2
-rw-r--r--net/core/bpf_sk_storage.c6
-rw-r--r--net/core/dev.c143
-rw-r--r--net/core/dev.h123
-rw-r--r--net/core/dev_ioctl.c6
-rw-r--r--net/core/fib_notifier.c2
-rw-r--r--net/core/fib_rules.c34
-rw-r--r--net/core/filter.c154
-rw-r--r--net/core/lwt_bpf.c11
-rw-r--r--net/core/neighbour.c360
-rw-r--r--net/core/net-sysfs.c4
-rw-r--r--net/core/net_namespace.c36
-rw-r--r--net/core/netdev-genl-gen.c23
-rw-r--r--net/core/netdev-genl-gen.h1
-rw-r--r--net/core/netdev-genl.c75
-rw-r--r--net/core/netpoll.c49
-rw-r--r--net/core/page_pool.c2
-rw-r--r--net/core/pktgen.c2
-rw-r--r--net/core/rtnetlink.c1035
-rw-r--r--net/core/rtnl_net_debug.c125
-rw-r--r--net/core/skb_fault_injection.c106
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/core/skmsg.c4
-rw-r--r--net/core/sock.c76
-rw-r--r--net/core/sysctl_net_core.c56
-rw-r--r--net/dcb/dcbnl.c8
-rw-r--r--net/dccp/ipv6.c2
-rw-r--r--net/devlink/dev.c18
-rw-r--r--net/devlink/devl_internal.h7
-rw-r--r--net/devlink/dpipe.c18
-rw-r--r--net/devlink/health.c25
-rw-r--r--net/devlink/rate.c8
-rw-r--r--net/devlink/region.c15
-rw-r--r--net/devlink/resource.c101
-rw-r--r--net/devlink/trap.c34
-rw-r--r--net/dsa/devlink.c23
-rw-r--r--net/dsa/dsa.c8
-rw-r--r--net/dsa/port.c40
-rw-r--r--net/dsa/user.c94
-rw-r--r--net/ethtool/cmis.h16
-rw-r--r--net/ethtool/cmis_cdb.c94
-rw-r--r--net/ethtool/cmis_fw_update.c108
-rw-r--r--net/ethtool/common.c90
-rw-r--r--net/ethtool/common.h1
-rw-r--r--net/ethtool/ioctl.c13
-rw-r--r--net/ethtool/rss.c2
-rw-r--r--net/handshake/request.c1
-rw-r--r--net/hsr/hsr_device.c89
-rw-r--r--net/hsr/hsr_forward.c19
-rw-r--r--net/hsr/hsr_netlink.c11
-rw-r--r--net/ieee802154/nl-mac.c15
-rw-r--r--net/ieee802154/nl802154.c26
-rw-r--r--net/ieee802154/socket.c12
-rw-r--r--net/ipv4/af_inet.c22
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/devinet.c281
-rw-r--r--net/ipv4/esp4_offload.c6
-rw-r--r--net/ipv4/fib_frontend.c44
-rw-r--r--net/ipv4/fib_notifier.c10
-rw-r--r--net/ipv4/fib_rules.c2
-rw-r--r--net/ipv4/fib_semantics.c88
-rw-r--r--net/ipv4/fib_trie.c8
-rw-r--r--net/ipv4/fou_nl.c4
-rw-r--r--net/ipv4/icmp.c21
-rw-r--r--net/ipv4/igmp.c26
-rw-r--r--net/ipv4/inet_connection_sock.c8
-rw-r--r--net/ipv4/inet_diag.c10
-rw-r--r--net/ipv4/inetpeer.c9
-rw-r--r--net/ipv4/ip_fragment.c11
-rw-r--r--net/ipv4/ip_input.c20
-rw-r--r--net/ipv4/ip_options.c3
-rw-r--r--net/ipv4/ip_output.c26
-rw-r--r--net/ipv4/ipmr.c96
-rw-r--r--net/ipv4/ipmr_base.c3
-rw-r--r--net/ipv4/netfilter.c2
-rw-r--r--net/ipv4/netfilter/Kconfig16
-rw-r--r--net/ipv4/netfilter/ipt_rpfilter.c2
-rw-r--r--net/ipv4/netfilter/nf_dup_ipv4.c2
-rw-r--r--net/ipv4/netfilter/nft_fib_ipv4.c3
-rw-r--r--net/ipv4/nexthop.c44
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c256
-rw-r--r--net/ipv4/tcp.c9
-rw-r--r--net/ipv4/tcp_ao.c42
-rw-r--r--net/ipv4/tcp_cong.c3
-rw-r--r--net/ipv4/tcp_input.c4
-rw-r--r--net/ipv4/tcp_ipv4.c17
-rw-r--r--net/ipv4/tcp_output.c18
-rw-r--r--net/ipv4/tcp_timer.c19
-rw-r--r--net/ipv4/udp.c249
-rw-r--r--net/ipv4/xfrm4_input.c2
-rw-r--r--net/ipv4/xfrm4_policy.c3
-rw-r--r--net/ipv4/xfrm4_protocol.c2
-rw-r--r--net/ipv6/addrconf.c112
-rw-r--r--net/ipv6/addrlabel.c28
-rw-r--r--net/ipv6/af_inet6.c22
-rw-r--r--net/ipv6/anycast.c5
-rw-r--r--net/ipv6/esp6_offload.c6
-rw-r--r--net/ipv6/fib6_notifier.c2
-rw-r--r--net/ipv6/fib6_rules.c2
-rw-r--r--net/ipv6/ila/ila_xlat.c15
-rw-r--r--net/ipv6/ioam6.c14
-rw-r--r--net/ipv6/ioam6_iptunnel.c6
-rw-r--r--net/ipv6/ip6_fib.c41
-rw-r--r--net/ipv6/ip6_output.c24
-rw-r--r--net/ipv6/ip6_tunnel.c4
-rw-r--r--net/ipv6/ip6mr.c79
-rw-r--r--net/ipv6/netfilter/Kconfig9
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/route.c74
-rw-r--r--net/ipv6/seg6_local.c14
-rw-r--r--net/ipv6/tcp_ipv6.c21
-rw-r--r--net/ipv6/udp.c117
-rw-r--r--net/iucv/af_iucv.c26
-rw-r--r--net/kcm/kcmsock.c10
-rw-r--r--net/key/af_key.c7
-rw-r--r--net/l2tp/l2tp_core.c22
-rw-r--r--net/llc/af_llc.c2
-rw-r--r--net/mac80211/agg-rx.c94
-rw-r--r--net/mac80211/agg-tx.c33
-rw-r--r--net/mac80211/cfg.c186
-rw-r--r--net/mac80211/chan.c65
-rw-r--r--net/mac80211/debugfs.c28
-rw-r--r--net/mac80211/debugfs_key.c9
-rw-r--r--net/mac80211/debugfs_netdev.c3
-rw-r--r--net/mac80211/debugfs_sta.c9
-rw-r--r--net/mac80211/driver-ops.c16
-rw-r--r--net/mac80211/driver-ops.h18
-rw-r--r--net/mac80211/eht.c21
-rw-r--r--net/mac80211/ht.c2
-rw-r--r--net/mac80211/ibss.c7
-rw-r--r--net/mac80211/ieee80211_i.h25
-rw-r--r--net/mac80211/iface.c52
-rw-r--r--net/mac80211/link.c54
-rw-r--r--net/mac80211/mesh.c2
-rw-r--r--net/mac80211/mesh_hwmp.c6
-rw-r--r--net/mac80211/mesh_pathtbl.c10
-rw-r--r--net/mac80211/mesh_plink.c7
-rw-r--r--net/mac80211/mesh_sync.c2
-rw-r--r--net/mac80211/mlme.c118
-rw-r--r--net/mac80211/ocb.c4
-rw-r--r--net/mac80211/rate.c35
-rw-r--r--net/mac80211/rate.h10
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c2
-rw-r--r--net/mac80211/rx.c75
-rw-r--r--net/mac80211/scan.c22
-rw-r--r--net/mac80211/spectmgmt.c9
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/mac80211/status.c5
-rw-r--r--net/mac80211/tdls.c3
-rw-r--r--net/mac80211/tkip.c2
-rw-r--r--net/mac80211/trace.h34
-rw-r--r--net/mac80211/tx.c8
-rw-r--r--net/mac80211/util.c20
-rw-r--r--net/mac80211/vht.c29
-rw-r--r--net/mac80211/wpa.c3
-rw-r--r--net/mctp/device.c28
-rw-r--r--net/mpls/af_mpls.c7
-rw-r--r--net/mptcp/diag.c2
-rw-r--r--net/mptcp/mptcp_pm_gen.c3
-rw-r--r--net/mptcp/options.c4
-rw-r--r--net/mptcp/pm.c3
-rw-r--r--net/mptcp/pm_netlink.c50
-rw-r--r--net/mptcp/pm_userspace.c18
-rw-r--r--net/mptcp/protocol.c31
-rw-r--r--net/mptcp/protocol.h6
-rw-r--r--net/mptcp/sched.c2
-rw-r--r--net/mptcp/subflow.c17
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ip.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c5
-rw-r--r--net/netfilter/nf_bpf_link.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c2
-rw-r--r--net/netfilter/nf_nat_core.c6
-rw-r--r--net/netfilter/nf_tables_api.c558
-rw-r--r--net/netfilter/nfnetlink.c2
-rw-r--r--net/netfilter/nft_bitwise.c166
-rw-r--r--net/netfilter/nft_flow_offload.c8
-rw-r--r--net/netfilter/nft_set_bitmap.c10
-rw-r--r--net/netfilter/nft_set_hash.c3
-rw-r--r--net/netfilter/nft_tunnel.c5
-rw-r--r--net/netfilter/xt_IDLETIMER.c4
-rw-r--r--net/netlabel/netlabel_mgmt.c13
-rw-r--r--net/netlabel/netlabel_unlabeled.c2
-rw-r--r--net/netlabel/netlabel_user.c7
-rw-r--r--net/netlabel/netlabel_user.h2
-rw-r--r--net/netlink/af_netlink.c71
-rw-r--r--net/netlink/af_netlink.h2
-rw-r--r--net/netlink/genetlink.c4
-rw-r--r--net/nfc/nci/core.c13
-rw-r--r--net/nfc/nci/ntf.c32
-rw-r--r--net/nfc/netlink.c5
-rw-r--r--net/openvswitch/datapath.c10
-rw-r--r--net/openvswitch/flow_netlink.c2
-rw-r--r--net/openvswitch/vport-internal_dev.c1
-rw-r--r--net/packet/af_packet.c27
-rw-r--r--net/phonet/pn_dev.c74
-rw-r--r--net/phonet/pn_netlink.c127
-rw-r--r--net/rds/ib_rdma.c4
-rw-r--r--net/rfkill/rfkill-gpio.c8
-rw-r--r--net/rxrpc/af_rxrpc.c7
-rw-r--r--net/rxrpc/conn_client.c4
-rw-r--r--net/rxrpc/conn_object.c4
-rw-r--r--net/rxrpc/local_object.c4
-rw-r--r--net/rxrpc/sendmsg.c1
-rw-r--r--net/sched/act_api.c102
-rw-r--r--net/sched/act_ct.c10
-rw-r--r--net/sched/act_ctinfo.c8
-rw-r--r--net/sched/act_gate.c11
-rw-r--r--net/sched/act_mpls.c18
-rw-r--r--net/sched/act_police.c6
-rw-r--r--net/sched/cls_api.c72
-rw-r--r--net/sched/cls_u32.c18
-rw-r--r--net/sched/sch_api.c20
-rw-r--r--net/sched/sch_cbs.c2
-rw-r--r--net/sched/sch_choke.c2
-rw-r--r--net/sched/sch_fq.c42
-rw-r--r--net/sched/sch_gred.c2
-rw-r--r--net/sched/sch_htb.c4
-rw-r--r--net/sched/sch_netem.c1
-rw-r--r--net/sched/sch_qfq.c5
-rw-r--r--net/sched/sch_red.c2
-rw-r--r--net/sched/sch_sfq.c39
-rw-r--r--net/sched/sch_taprio.c2
-rw-r--r--net/sctp/ipv6.c21
-rw-r--r--net/sctp/protocol.c16
-rw-r--r--net/sctp/sm_statefuns.c2
-rw-r--r--net/shaper/Makefile8
-rw-r--r--net/shaper/shaper.c1438
-rw-r--r--net/shaper/shaper_nl_gen.c154
-rw-r--r--net/shaper/shaper_nl_gen.h44
-rw-r--r--net/smc/af_smc.c4
-rw-r--r--net/smc/smc.h2
-rw-r--r--net/smc/smc_clc.h2
-rw-r--r--net/smc/smc_core.c2
-rw-r--r--net/smc/smc_core.h4
-rw-r--r--net/smc/smc_ib.c8
-rw-r--r--net/smc/smc_pnet.c4
-rw-r--r--net/socket.c311
-rw-r--r--net/sunrpc/cache.c4
-rw-r--r--net/sunrpc/svcsock.c10
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma.c19
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c8
-rw-r--r--net/sunrpc/xprtsock.c19
-rw-r--r--net/vmw_vsock/af_vsock.c4
-rw-r--r--net/vmw_vsock/hyperv_transport.c1
-rw-r--r--net/vmw_vsock/virtio_transport_common.c10
-rw-r--r--net/wireless/Kconfig45
-rw-r--r--net/wireless/Makefile5
-rw-r--r--net/wireless/chan.c5
-rw-r--r--net/wireless/core.c66
-rw-r--r--net/wireless/core.h1
-rw-r--r--net/wireless/lib80211.c257
-rw-r--r--net/wireless/mlme.c6
-rw-r--r--net/wireless/nl80211.c161
-rw-r--r--net/wireless/radiotap.c2
-rw-r--r--net/wireless/rdev-ops.h5
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/scan.c12
-rw-r--r--net/wireless/trace.h10
-rw-r--r--net/wireless/util.c31
-rw-r--r--net/wireless/wext-compat.c13
-rw-r--r--net/wireless/wext-compat.h6
-rw-r--r--net/wireless/wext-core.c2
-rw-r--r--net/xdp/xsk.c49
-rw-r--r--net/xdp/xsk_buff_pool.c54
-rw-r--r--net/xdp/xsk_queue.h2
-rw-r--r--net/xfrm/xfrm_compat.c6
-rw-r--r--net/xfrm/xfrm_input.c2
-rw-r--r--net/xfrm/xfrm_policy.c28
-rw-r--r--net/xfrm/xfrm_state.c171
-rw-r--r--net/xfrm/xfrm_user.c83
-rw-r--r--rust/Makefile103
-rw-r--r--rust/bindgen_parameters5
-rw-r--r--rust/bindings/bindings_helper.h11
-rw-r--r--rust/bindings/lib.rs6
-rw-r--r--rust/exports.c7
-rw-r--r--rust/ffi.rs13
-rw-r--r--rust/helpers/build_bug.c1
-rw-r--r--rust/helpers/cred.c13
-rw-r--r--rust/helpers/err.c1
-rw-r--r--rust/helpers/fs.c12
-rw-r--r--rust/helpers/helpers.c6
-rw-r--r--rust/helpers/jump_label.c14
-rw-r--r--rust/helpers/kunit.c1
-rw-r--r--rust/helpers/mutex.c1
-rw-r--r--rust/helpers/pid_namespace.c26
-rw-r--r--rust/helpers/refcount.c1
-rw-r--r--rust/helpers/security.c20
-rw-r--r--rust/helpers/signal.c1
-rw-r--r--rust/helpers/slab.c6
-rw-r--r--rust/helpers/spinlock.c14
-rw-r--r--rust/helpers/task.c39
-rw-r--r--rust/helpers/vmalloc.c9
-rw-r--r--rust/helpers/wait.c1
-rw-r--r--rust/helpers/workqueue.c1
-rw-r--r--rust/kernel/.gitignore3
-rw-r--r--rust/kernel/alloc.rs150
-rw-r--r--rust/kernel/alloc/allocator.rs208
-rw-r--r--rust/kernel/alloc/allocator_test.rs95
-rw-r--r--rust/kernel/alloc/box_ext.rs89
-rw-r--r--rust/kernel/alloc/kbox.rs456
-rw-r--r--rust/kernel/alloc/kvec.rs913
-rw-r--r--rust/kernel/alloc/layout.rs91
-rw-r--r--rust/kernel/alloc/vec_ext.rs185
-rw-r--r--rust/kernel/block/mq/gen_disk.rs2
-rw-r--r--rust/kernel/block/mq/operations.rs18
-rw-r--r--rust/kernel/block/mq/raw_writer.rs2
-rw-r--r--rust/kernel/block/mq/request.rs67
-rw-r--r--rust/kernel/block/mq/tag_set.rs2
-rw-r--r--rust/kernel/cred.rs85
-rw-r--r--rust/kernel/device.rs319
-rw-r--r--rust/kernel/error.rs79
-rw-r--r--rust/kernel/fs.rs8
-rw-r--r--rust/kernel/fs/file.rs461
-rw-r--r--rust/kernel/generated_arch_static_branch_asm.rs.S7
-rw-r--r--rust/kernel/init.rs127
-rw-r--r--rust/kernel/init/__internal.rs13
-rw-r--r--rust/kernel/init/macros.rs18
-rw-r--r--rust/kernel/ioctl.rs2
-rw-r--r--rust/kernel/jump_label.rs74
-rw-r--r--rust/kernel/lib.rs76
-rw-r--r--rust/kernel/list.rs1
-rw-r--r--rust/kernel/list/arc.rs3
-rw-r--r--rust/kernel/list/arc_field.rs2
-rw-r--r--rust/kernel/miscdevice.rs256
-rw-r--r--rust/kernel/net/phy.rs32
-rw-r--r--rust/kernel/page.rs10
-rw-r--r--rust/kernel/pid_namespace.rs68
-rw-r--r--rust/kernel/prelude.rs7
-rw-r--r--rust/kernel/print.rs5
-rw-r--r--rust/kernel/rbtree.rs58
-rw-r--r--rust/kernel/security.rs74
-rw-r--r--rust/kernel/seq_file.rs52
-rw-r--r--rust/kernel/std_vendor.rs38
-rw-r--r--rust/kernel/str.rs46
-rw-r--r--rust/kernel/sync.rs2
-rw-r--r--rust/kernel/sync/arc.rs31
-rw-r--r--rust/kernel/sync/arc/std_vendor.rs2
-rw-r--r--rust/kernel/sync/condvar.rs7
-rw-r--r--rust/kernel/sync/lock.rs40
-rw-r--r--rust/kernel/sync/lock/global.rs301
-rw-r--r--rust/kernel/sync/lock/mutex.rs15
-rw-r--r--rust/kernel/sync/lock/spinlock.rs15
-rw-r--r--rust/kernel/sync/locked_by.rs2
-rw-r--r--rust/kernel/sync/poll.rs121
-rw-r--r--rust/kernel/task.rs243
-rw-r--r--rust/kernel/time.rs4
-rw-r--r--rust/kernel/tracepoint.rs49
-rw-r--r--rust/kernel/transmute.rs71
-rw-r--r--rust/kernel/types.rs223
-rw-r--r--rust/kernel/uaccess.rs25
-rw-r--r--rust/kernel/workqueue.rs29
-rw-r--r--rust/macros/lib.rs142
-rw-r--r--rust/macros/module.rs36
-rw-r--r--rust/macros/paste.rs15
-rw-r--r--rust/uapi/lib.rs6
-rw-r--r--samples/bpf/Makefile25
-rw-r--r--samples/bpf/sock_flags.bpf.c47
-rw-r--r--samples/bpf/syscall_nrs.c5
-rw-r--r--samples/bpf/tc_l2_redirect_kern.c6
-rw-r--r--samples/bpf/test_cgrp2_array_pin.c106
-rw-r--r--samples/bpf/test_cgrp2_attach.c177
-rw-r--r--samples/bpf/test_cgrp2_sock.c294
-rwxr-xr-xsamples/bpf/test_cgrp2_sock.sh137
-rw-r--r--samples/bpf/test_cgrp2_sock2.c95
-rwxr-xr-xsamples/bpf/test_cgrp2_sock2.sh103
-rw-r--r--samples/bpf/test_cgrp2_tc.bpf.c56
-rwxr-xr-xsamples/bpf/test_cgrp2_tc.sh187
-rw-r--r--samples/bpf/test_current_task_under_cgroup.bpf.c43
-rw-r--r--samples/bpf/test_current_task_under_cgroup_user.c115
-rw-r--r--samples/bpf/test_overhead_kprobe.bpf.c41
-rw-r--r--samples/bpf/test_overhead_raw_tp.bpf.c17
-rw-r--r--samples/bpf/test_overhead_tp.bpf.c23
-rw-r--r--samples/bpf/test_overhead_user.c225
-rwxr-xr-xsamples/bpf/test_override_return.sh16
-rw-r--r--samples/bpf/test_probe_write_user.bpf.c52
-rw-r--r--samples/bpf/test_probe_write_user_user.c108
-rw-r--r--samples/bpf/tracex7.bpf.c15
-rw-r--r--samples/bpf/tracex7_user.c56
-rw-r--r--samples/bpf/xdp2skb_meta_kern.c2
-rw-r--r--samples/bpf/xdp_adjust_tail_kern.c1
-rw-r--r--samples/ftrace/ftrace-direct-modify.c85
-rw-r--r--samples/ftrace/ftrace-direct-multi-modify.c101
-rw-r--r--samples/ftrace/ftrace-direct-multi.c79
-rw-r--r--samples/ftrace/ftrace-direct-too.c83
-rw-r--r--samples/ftrace/ftrace-direct.c69
-rw-r--r--samples/hw_breakpoint/data_breakpoint.c4
-rw-r--r--samples/kfifo/dma-example.c1
-rw-r--r--samples/landlock/sandboxer.c112
-rwxr-xr-xsamples/pktgen/pktgen_sample01_simple.sh2
-rw-r--r--samples/rust/Makefile3
-rw-r--r--samples/rust/rust_minimal.rs4
-rw-r--r--samples/rust/rust_print_events.c8
-rw-r--r--samples/rust/rust_print_main.rs (renamed from samples/rust/rust_print.rs)19
-rw-r--r--samples/trace_events/trace-events-sample.h7
-rw-r--r--samples/v4l/v4l2-pci-skeleton.c6
-rw-r--r--scripts/Kbuild.include2
-rw-r--r--scripts/Makefile.autofdo24
-rw-r--r--scripts/Makefile.btf6
-rw-r--r--scripts/Makefile.build70
-rw-r--r--scripts/Makefile.clang1
-rw-r--r--scripts/Makefile.clean2
-rw-r--r--scripts/Makefile.compiler2
-rw-r--r--scripts/Makefile.host8
-rw-r--r--scripts/Makefile.lib62
-rw-r--r--scripts/Makefile.modfinal31
-rw-r--r--scripts/Makefile.modinst8
-rw-r--r--scripts/Makefile.modpost24
-rw-r--r--scripts/Makefile.propeller39
-rw-r--r--scripts/Makefile.vmlinux58
-rwxr-xr-xscripts/bpf_doc.py53
-rwxr-xr-xscripts/checkpatch.pl47
-rwxr-xr-xscripts/coccicheck6
-rw-r--r--scripts/const_structs.checkpatch1
-rwxr-xr-xscripts/decode_stacktrace.sh7
-rwxr-xr-xscripts/depmod.sh4
-rwxr-xr-xscripts/export_report.pl186
-rwxr-xr-xscripts/faddr2line2
-rw-r--r--scripts/gdb/linux/modules.py3
-rw-r--r--scripts/gdb/linux/symbols.py3
-rwxr-xr-xscripts/generate_rust_analyzer.py11
-rw-r--r--scripts/genksyms/genksyms.c73
-rw-r--r--scripts/head-object-list.txt1
-rw-r--r--scripts/ipe/polgen/polgen.c12
-rw-r--r--scripts/kconfig/conf.c5
-rw-r--r--scripts/kconfig/lkc_proto.h1
-rw-r--r--scripts/kconfig/nconf.c2
-rw-r--r--scripts/kconfig/nconf.gui.c9
-rw-r--r--scripts/kconfig/parser.y28
-rw-r--r--scripts/kconfig/qconf.cc204
-rw-r--r--scripts/kconfig/qconf.h19
-rwxr-xr-xscripts/kconfig/streamline_config.pl18
-rw-r--r--scripts/kconfig/symbol.c26
-rwxr-xr-xscripts/kernel-doc49
-rwxr-xr-xscripts/link-vmlinux.sh23
-rw-r--r--scripts/mod/file2alias.c779
-rw-r--r--scripts/mod/modpost.c31
-rw-r--r--scripts/mod/modpost.h21
-rw-r--r--scripts/module.lds.S14
-rw-r--r--scripts/nsdeps10
-rwxr-xr-xscripts/package/builddeb22
-rwxr-xr-xscripts/package/install-extmod-build7
-rwxr-xr-xscripts/package/mkdebian2
-rwxr-xr-xscripts/remove-stale-files3
-rwxr-xr-xscripts/rust_is_available.sh15
-rw-r--r--scripts/rust_is_available_bindgen_libclang_concat.h3
-rwxr-xr-xscripts/rust_is_available_test.py34
-rw-r--r--scripts/selinux/Makefile2
-rw-r--r--scripts/selinux/genheaders/Makefile5
-rw-r--r--scripts/selinux/mdp/Makefile2
-rw-r--r--scripts/selinux/mdp/mdp.c7
-rwxr-xr-xscripts/setlocalversion58
-rw-r--r--scripts/spelling.txt33
-rw-r--r--scripts/syscall.tbl4
-rwxr-xr-xscripts/tags.sh42
-rw-r--r--security/apparmor/apparmorfs.c1
-rw-r--r--security/apparmor/audit.c4
-rw-r--r--security/apparmor/capability.c19
-rw-r--r--security/apparmor/domain.c67
-rw-r--r--security/apparmor/include/audit.h2
-rw-r--r--security/apparmor/include/label.h28
-rw-r--r--security/apparmor/include/lib.h1
-rw-r--r--security/apparmor/include/match.h8
-rw-r--r--security/apparmor/include/perms.h3
-rw-r--r--security/apparmor/include/policy.h1
-rw-r--r--security/apparmor/include/secid.h3
-rw-r--r--security/apparmor/label.c33
-rw-r--r--security/apparmor/lib.c84
-rw-r--r--security/apparmor/lsm.c17
-rw-r--r--security/apparmor/match.c99
-rw-r--r--security/apparmor/path.c2
-rw-r--r--security/apparmor/policy.c9
-rw-r--r--security/apparmor/policy_unpack.c5
-rw-r--r--security/apparmor/policy_unpack_test.c6
-rw-r--r--security/apparmor/secid.c35
-rw-r--r--security/integrity/evm/evm_main.c3
-rw-r--r--security/integrity/ima/ima.h8
-rw-r--r--security/integrity/ima/ima_api.c6
-rw-r--r--security/integrity/ima/ima_appraise.c6
-rw-r--r--security/integrity/ima/ima_main.c73
-rw-r--r--security/integrity/ima/ima_policy.c21
-rw-r--r--security/integrity/ima/ima_template_lib.c14
-rw-r--r--security/integrity/integrity.h4
-rw-r--r--security/keys/keyring.c7
-rw-r--r--security/keys/trusted-keys/trusted_dcp.c9
-rw-r--r--security/landlock/fs.c31
-rw-r--r--security/landlock/net.c28
-rw-r--r--security/landlock/ruleset.h74
-rw-r--r--security/landlock/syscalls.c47
-rw-r--r--security/landlock/task.c18
-rw-r--r--security/loadpin/loadpin.c8
-rw-r--r--security/lsm_audit.c4
-rw-r--r--security/security.c105
-rw-r--r--security/selinux/.gitignore1
-rw-r--r--security/selinux/Makefile7
-rw-r--r--security/selinux/genheaders.c (renamed from scripts/selinux/genheaders/genheaders.c)3
-rw-r--r--security/selinux/hooks.c100
-rw-r--r--security/selinux/include/audit.h5
-rw-r--r--security/selinux/include/classmap.h19
-rw-r--r--security/selinux/include/initial_sid_to_string.h4
-rw-r--r--security/selinux/include/policycap.h1
-rw-r--r--security/selinux/include/policycap_names.h1
-rw-r--r--security/selinux/include/security.h6
-rw-r--r--security/selinux/nlmsgtab.c297
-rw-r--r--security/selinux/selinuxfs.c6
-rw-r--r--security/selinux/ss/avtab.h5
-rw-r--r--security/selinux/ss/services.c84
-rw-r--r--security/smack/smack_lsm.c96
-rw-r--r--security/smack/smackfs.c4
-rw-r--r--sound/ac97/bus.c5
-rw-r--r--sound/arm/pxa2xx-ac97.c2
-rw-r--r--sound/atmel/ac97c.c2
-rw-r--r--sound/core/Kconfig3
-rw-r--r--sound/core/compress_offload.c358
-rw-r--r--sound/core/pcm_native.c28
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/sound_kunit.c11
-rw-r--r--sound/core/ump.c11
-rw-r--r--sound/drivers/mts64.c2
-rw-r--r--sound/drivers/pcmtest.c2
-rw-r--r--sound/drivers/portman2x4.c2
-rw-r--r--sound/firewire/cmp.c47
-rw-r--r--sound/firewire/cmp.h1
-rw-r--r--sound/firewire/tascam/amdtp-tascam.c2
-rw-r--r--sound/mips/hal2.c2
-rw-r--r--sound/mips/sgio2audio.c4
-rw-r--r--sound/oss/dmasound/dmasound_paula.c2
-rw-r--r--sound/pci/asihpi/asihpi.c2
-rw-r--r--sound/pci/hda/hda_auto_parser.c81
-rw-r--r--sound/pci/hda/hda_intel.c38
-rw-r--r--sound/pci/hda/hda_local.h28
-rw-r--r--sound/pci/hda/hda_tegra.c2
-rw-r--r--sound/pci/hda/patch_analog.c6
-rw-r--r--sound/pci/hda/patch_cirrus.c8
-rw-r--r--sound/pci/hda/patch_conexant.c38
-rw-r--r--sound/pci/hda/patch_cs8409-tables.c2
-rw-r--r--sound/pci/hda/patch_cs8409.h2
-rw-r--r--sound/pci/hda/patch_realtek.c300
-rw-r--r--sound/pci/hda/patch_sigmatel.c22
-rw-r--r--sound/pci/hda/patch_via.c2
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c63
-rw-r--r--sound/pci/ice1712/prodigy192.c9
-rw-r--r--sound/pci/korg1212/korg1212.c6
-rw-r--r--sound/ppc/powermac.c2
-rw-r--r--sound/sh/aica.c4
-rw-r--r--sound/sh/sh_dac_audio.c2
-rw-r--r--sound/soc/Kconfig3
-rw-r--r--sound/soc/Makefile3
-rw-r--r--sound/soc/amd/Kconfig1
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c20
-rw-r--r--sound/soc/amd/acp-es8336.c2
-rw-r--r--sound/soc/amd/acp/Kconfig29
-rw-r--r--sound/soc/amd/acp/Makefile4
-rw-r--r--sound/soc/amd/acp/acp-i2s.c38
-rw-r--r--sound/soc/amd/acp/acp-legacy-common.c24
-rw-r--r--sound/soc/amd/acp/acp-legacy-mach.c8
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c63
-rw-r--r--sound/soc/amd/acp/acp-mach.h12
-rw-r--r--sound/soc/amd/acp/acp-pci.c7
-rw-r--r--sound/soc/amd/acp/acp-pdm.c2
-rw-r--r--sound/soc/amd/acp/acp-platform.c18
-rw-r--r--sound/soc/amd/acp/acp-rembrandt.c4
-rw-r--r--sound/soc/amd/acp/acp-renoir.c4
-rw-r--r--sound/soc/amd/acp/acp-sdw-legacy-mach.c486
-rw-r--r--sound/soc/amd/acp/acp-sdw-mach-common.c64
-rw-r--r--sound/soc/amd/acp/acp-sdw-sof-mach.c104
-rw-r--r--sound/soc/amd/acp/acp-sof-mach.c6
-rw-r--r--sound/soc/amd/acp/acp63.c4
-rw-r--r--sound/soc/amd/acp/acp70.c14
-rw-r--r--sound/soc/amd/acp/acp_common.h19
-rw-r--r--sound/soc/amd/acp/amd-acp63-acpi-match.c54
-rw-r--r--sound/soc/amd/acp/amd.h9
-rw-r--r--sound/soc/amd/acp/soc_amd_sdw_common.h4
-rw-r--r--sound/soc/amd/acp3x-rt5682-max9836.c6
-rw-r--r--sound/soc/amd/mach-config.h1
-rw-r--r--sound/soc/amd/ps/acp63.h2
-rw-r--r--sound/soc/amd/ps/pci-ps.c6
-rw-r--r--sound/soc/amd/ps/ps-sdw-dma.c2
-rw-r--r--sound/soc/amd/vangogh/acp5x-mach.c6
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c53
-rw-r--r--sound/soc/apple/mca.c2
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c5
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c2
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c2
-rw-r--r--sound/soc/au1x/dbdma2.c2
-rw-r--r--sound/soc/au1x/dma.c2
-rw-r--r--sound/soc/bcm/bcm2835-i2s.c2
-rw-r--r--sound/soc/bcm/bcm63xx-pcm-whistler.c6
-rw-r--r--sound/soc/bcm/cygnus-pcm.c2
-rw-r--r--sound/soc/codecs/Kconfig69
-rw-r--r--sound/soc/codecs/Makefile20
-rw-r--r--sound/soc/codecs/adau1372-i2c.c1
-rw-r--r--sound/soc/codecs/adau1372-spi.c1
-rw-r--r--sound/soc/codecs/adau1372.c8
-rw-r--r--sound/soc/codecs/adau1372.h1
-rw-r--r--sound/soc/codecs/adau1373.c200
-rw-r--r--sound/soc/codecs/aw88081.c1087
-rw-r--r--sound/soc/codecs/aw88081.h286
-rw-r--r--sound/soc/codecs/aw88395/aw88395_device.c2
-rw-r--r--sound/soc/codecs/aw88395/aw88395_lib.c2
-rw-r--r--sound/soc/codecs/aw88399.c2
-rw-r--r--sound/soc/codecs/cpcap.c2
-rw-r--r--sound/soc/codecs/cs42l43.c42
-rw-r--r--sound/soc/codecs/cs42l84.c1111
-rw-r--r--sound/soc/codecs/cs42l84.h210
-rw-r--r--sound/soc/codecs/da7213.c27
-rw-r--r--sound/soc/codecs/da7213.h1
-rw-r--r--sound/soc/codecs/da7219.c9
-rw-r--r--sound/soc/codecs/es8323.c792
-rw-r--r--sound/soc/codecs/es8323.h78
-rw-r--r--sound/soc/codecs/es8326.c20
-rw-r--r--sound/soc/codecs/hdmi-codec.c140
-rw-r--r--sound/soc/codecs/max9768.c11
-rw-r--r--sound/soc/codecs/max98088.c86
-rw-r--r--sound/soc/codecs/nau8821.c9
-rw-r--r--sound/soc/codecs/ntp8835.c480
-rw-r--r--sound/soc/codecs/ntp8918.c397
-rw-r--r--sound/soc/codecs/ntpfw.c137
-rw-r--r--sound/soc/codecs/ntpfw.h23
-rw-r--r--sound/soc/codecs/pcm186x.c4
-rw-r--r--sound/soc/codecs/pcm5102a.c2
-rw-r--r--sound/soc/codecs/rt-sdw-common.c238
-rw-r--r--sound/soc/codecs/rt-sdw-common.h66
-rw-r--r--sound/soc/codecs/rt1320-sdw.c3668
-rw-r--r--sound/soc/codecs/rt1320-sdw.h6
-rw-r--r--sound/soc/codecs/rt712-sdca-sdw.c1
-rw-r--r--sound/soc/codecs/rt712-sdca.c38
-rw-r--r--sound/soc/codecs/rt712-sdca.h1
-rw-r--r--sound/soc/codecs/rt721-sdca-sdw.c546
-rw-r--r--sound/soc/codecs/rt721-sdca-sdw.h150
-rw-r--r--sound/soc/codecs/rt721-sdca.c1545
-rw-r--r--sound/soc/codecs/rt721-sdca.h269
-rw-r--r--sound/soc/codecs/rt722-sdca-sdw.c12
-rw-r--r--sound/soc/codecs/rt722-sdca.c15
-rw-r--r--sound/soc/codecs/simple-mux.c39
-rw-r--r--sound/soc/codecs/sma1307.c2049
-rw-r--r--sound/soc/codecs/sma1307.h444
-rw-r--r--sound/soc/codecs/spdif_receiver.c2
-rw-r--r--sound/soc/codecs/spdif_transmitter.c2
-rw-r--r--sound/soc/codecs/tas2781-fmwlib.c1
-rw-r--r--sound/soc/codecs/tas2781-i2c.c35
-rw-r--r--sound/soc/codecs/tas5805m.c2
-rw-r--r--sound/soc/codecs/tas6424.c2
-rw-r--r--sound/soc/codecs/tlv320adc3xxx.c2
-rw-r--r--sound/soc/codecs/twl4030.c12
-rw-r--r--sound/soc/codecs/uda1342.c347
-rw-r--r--sound/soc/codecs/uda1342.h78
-rw-r--r--sound/soc/codecs/wcd9335.c1
-rw-r--r--sound/soc/codecs/wcd937x.c1
-rw-r--r--sound/soc/fsl/Kconfig1
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c32
-rw-r--r--sound/soc/fsl/fsl_aud2htx.c2
-rw-r--r--sound/soc/fsl/fsl_easrc.c2
-rw-r--r--sound/soc/fsl/fsl_micfil.c51
-rw-r--r--sound/soc/fsl/fsl_mqs.c41
-rw-r--r--sound/soc/fsl/fsl_qmc_audio.c2
-rw-r--r--sound/soc/fsl/fsl_xcvr.c94
-rw-r--r--sound/soc/fsl/fsl_xcvr.h5
-rw-r--r--sound/soc/fsl/imx-audmix.c21
-rw-r--r--sound/soc/fsl/imx-card.c69
-rw-r--r--sound/soc/generic/audio-graph-card.c2
-rw-r--r--sound/soc/generic/audio-graph-card2.c109
-rw-r--r--sound/soc/generic/simple-card-utils.c16
-rw-r--r--sound/soc/generic/test-component.c5
-rw-r--r--sound/soc/intel/Kconfig8
-rw-r--r--sound/soc/intel/avs/boards/da7219.c2
-rw-r--r--sound/soc/intel/avs/boards/dmic.c4
-rw-r--r--sound/soc/intel/avs/boards/es8336.c2
-rw-r--r--sound/soc/intel/avs/boards/hdaudio.c4
-rw-r--r--sound/soc/intel/avs/boards/i2s_test.c2
-rw-r--r--sound/soc/intel/avs/boards/max98357a.c2
-rw-r--r--sound/soc/intel/avs/boards/max98373.c2
-rw-r--r--sound/soc/intel/avs/boards/max98927.c2
-rw-r--r--sound/soc/intel/avs/boards/nau8825.c2
-rw-r--r--sound/soc/intel/avs/boards/rt274.c2
-rw-r--r--sound/soc/intel/avs/boards/rt286.c2
-rw-r--r--sound/soc/intel/avs/boards/rt298.c2
-rw-r--r--sound/soc/intel/avs/boards/rt5514.c2
-rw-r--r--sound/soc/intel/avs/boards/rt5663.c2
-rw-r--r--sound/soc/intel/avs/boards/rt5682.c2
-rw-r--r--sound/soc/intel/avs/boards/ssm4567.c2
-rw-r--r--sound/soc/intel/avs/pcm.c2
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/bdw-rt5650.c4
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c4
-rw-r--r--sound/soc/intel/boards/bdw_rt286.c10
-rw-r--r--sound/soc/intel/boards/bytcht_cx2072x.c6
-rw-r--r--sound/soc/intel/boards/bytcht_da7213.c6
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c6
-rw-r--r--sound/soc/intel/boards/bytcht_nocodec.c6
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c6
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c6
-rw-r--r--sound/soc/intel/boards/bytcr_wm5102.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c6
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c6
-rw-r--r--sound/soc/intel/boards/ehl_rt5660.c14
-rw-r--r--sound/soc/intel/boards/hsw_rt5640.c10
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.c15
-rw-r--r--sound/soc/intel/boards/sof_es8336.c8
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c9
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c15
-rw-r--r--sound/soc/intel/boards/sof_sdw.c125
-rw-r--r--sound/soc/intel/boards/sof_wm8804.c2
-rw-r--r--sound/soc/intel/common/Makefile6
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-arl-match.c63
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-lnl-match.c65
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c58
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ptl-match.c75
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c42
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h14
-rw-r--r--sound/soc/intel/common/sst-dsp-priv.h101
-rw-r--r--sound/soc/intel/common/sst-dsp.c250
-rw-r--r--sound/soc/intel/common/sst-dsp.h61
-rw-r--r--sound/soc/intel/common/sst-ipc.c294
-rw-r--r--sound/soc/intel/common/sst-ipc.h86
-rw-r--r--sound/soc/loongson/Kconfig32
-rw-r--r--sound/soc/loongson/Makefile9
-rw-r--r--sound/soc/loongson/loongson_i2s.c5
-rw-r--r--sound/soc/loongson/loongson_i2s_plat.c185
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-cs42448.c20
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-wm8960.c6
-rw-r--r--sound/soc/mediatek/mt6797/mt6797-mt6351.c24
-rw-r--r--sound/soc/mediatek/mt7986/mt7986-wm8960.c6
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-max98090.c6
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c6
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c10
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-rt5650.c10
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c34
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-dai-i2s.c7
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c34
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366.c86
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-adda.c1
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-etdm.c5
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-mt6359.c67
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c82
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359.c69
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-dai-dmic.c6
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-dai-pcm.c2
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-mt6357.c14
-rw-r--r--sound/soc/meson/axg-card.c6
-rw-r--r--sound/soc/meson/axg-tdm-interface.c12
-rw-r--r--sound/soc/meson/axg-tdm.h2
-rw-r--r--sound/soc/meson/gx-card.c2
-rw-r--r--sound/soc/qcom/sc8280xp.c1
-rw-r--r--sound/soc/qcom/sm8250.c12
-rw-r--r--sound/soc/qcom/x1e80100.c40
-rw-r--r--sound/soc/renesas/Kconfig (renamed from sound/soc/sh/Kconfig)0
-rw-r--r--sound/soc/renesas/Makefile (renamed from sound/soc/sh/Makefile)0
-rw-r--r--sound/soc/renesas/dma-sh7760.c (renamed from sound/soc/sh/dma-sh7760.c)0
-rw-r--r--sound/soc/renesas/fsi.c (renamed from sound/soc/sh/fsi.c)0
-rw-r--r--sound/soc/renesas/hac.c (renamed from sound/soc/sh/hac.c)0
-rw-r--r--sound/soc/renesas/migor.c (renamed from sound/soc/sh/migor.c)0
-rw-r--r--sound/soc/renesas/rcar/Makefile (renamed from sound/soc/sh/rcar/Makefile)0
-rw-r--r--sound/soc/renesas/rcar/adg.c (renamed from sound/soc/sh/rcar/adg.c)0
-rw-r--r--sound/soc/renesas/rcar/cmd.c (renamed from sound/soc/sh/rcar/cmd.c)0
-rw-r--r--sound/soc/renesas/rcar/core.c (renamed from sound/soc/sh/rcar/core.c)32
-rw-r--r--sound/soc/renesas/rcar/ctu.c (renamed from sound/soc/sh/rcar/ctu.c)0
-rw-r--r--sound/soc/renesas/rcar/debugfs.c (renamed from sound/soc/sh/rcar/debugfs.c)0
-rw-r--r--sound/soc/renesas/rcar/dma.c (renamed from sound/soc/sh/rcar/dma.c)0
-rw-r--r--sound/soc/renesas/rcar/dvc.c (renamed from sound/soc/sh/rcar/dvc.c)0
-rw-r--r--sound/soc/renesas/rcar/gen.c (renamed from sound/soc/sh/rcar/gen.c)0
-rw-r--r--sound/soc/renesas/rcar/mix.c (renamed from sound/soc/sh/rcar/mix.c)0
-rw-r--r--sound/soc/renesas/rcar/rsnd.h (renamed from sound/soc/sh/rcar/rsnd.h)0
-rw-r--r--sound/soc/renesas/rcar/src.c (renamed from sound/soc/sh/rcar/src.c)0
-rw-r--r--sound/soc/renesas/rcar/ssi.c (renamed from sound/soc/sh/rcar/ssi.c)0
-rw-r--r--sound/soc/renesas/rcar/ssiu.c (renamed from sound/soc/sh/rcar/ssiu.c)0
-rw-r--r--sound/soc/renesas/rz-ssi.c (renamed from sound/soc/sh/rz-ssi.c)6
-rw-r--r--sound/soc/renesas/sh7760-ac97.c (renamed from sound/soc/sh/sh7760-ac97.c)0
-rw-r--r--sound/soc/renesas/siu.h (renamed from sound/soc/sh/siu.h)0
-rw-r--r--sound/soc/renesas/siu_dai.c (renamed from sound/soc/sh/siu_dai.c)0
-rw-r--r--sound/soc/renesas/siu_pcm.c (renamed from sound/soc/sh/siu_pcm.c)0
-rw-r--r--sound/soc/renesas/ssi.c (renamed from sound/soc/sh/ssi.c)0
-rw-r--r--sound/soc/samsung/odroid.c11
-rw-r--r--sound/soc/sdca/Kconfig11
-rw-r--r--sound/soc/sdca/Makefile5
-rw-r--r--sound/soc/sdca/sdca_device.c67
-rw-r--r--sound/soc/sdca/sdca_functions.c177
-rw-r--r--sound/soc/sdw_utils/Makefile3
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt712_sdca.c48
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt722_sdca.c41
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c90
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c8
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c80
-rw-r--r--sound/soc/soc-acpi.c30
-rw-r--r--sound/soc/soc-component.c14
-rw-r--r--sound/soc/soc-compress.c28
-rw-r--r--sound/soc/soc-core.c70
-rw-r--r--sound/soc/soc-dai.c14
-rw-r--r--sound/soc/soc-devres.c37
-rw-r--r--sound/soc/soc-link.c10
-rw-r--r--sound/soc/soc-pcm.c152
-rw-r--r--sound/soc/soc-topology-test.c2
-rw-r--r--sound/soc/soc-topology.c4
-rw-r--r--sound/soc/soc-utils.c4
-rw-r--r--sound/soc/sof/amd/acp-common.c3
-rw-r--r--sound/soc/sof/amd/acp.c11
-rw-r--r--sound/soc/sof/core.c64
-rw-r--r--sound/soc/sof/intel/hda-dai.c4
-rw-r--r--sound/soc/sof/intel/hda-dsp.c5
-rw-r--r--sound/soc/sof/intel/hda-loader.c100
-rw-r--r--sound/soc/sof/intel/hda-mlink.c18
-rw-r--r--sound/soc/sof/intel/hda-stream.c32
-rw-r--r--sound/soc/sof/intel/hda.c27
-rw-r--r--sound/soc/sof/intel/hda.h14
-rw-r--r--sound/soc/sof/intel/lnl.c10
-rw-r--r--sound/soc/sof/ipc3-loader.c3
-rw-r--r--sound/soc/sof/ipc3-topology.c26
-rw-r--r--sound/soc/sof/ipc3.c2
-rw-r--r--sound/soc/sof/ipc4-pcm.c3
-rw-r--r--sound/soc/sof/ipc4-topology.c376
-rw-r--r--sound/soc/sof/nocodec.c7
-rw-r--r--sound/soc/sof/ops.h8
-rw-r--r--sound/soc/sof/sof-acpi-dev.c4
-rw-r--r--sound/soc/sof/sof-client-probes-ipc4.c1
-rw-r--r--sound/soc/sof/sof-of-dev.c14
-rw-r--r--sound/soc/sof/sof-pci-dev.c12
-rw-r--r--sound/soc/stm/stm32_adfsdm.c4
-rw-r--r--sound/soc/stm/stm32_i2s.c211
-rw-r--r--sound/soc/stm/stm32_sai.c58
-rw-r--r--sound/soc/stm/stm32_sai.h6
-rw-r--r--sound/soc/stm/stm32_sai_sub.c152
-rw-r--r--sound/soc/stm/stm32_spdifrx.c2
-rw-r--r--sound/soc/sunxi/sun4i-codec.c298
-rw-r--r--sound/soc/tegra/tegra186_dspk.c3
-rw-r--r--sound/soc/tegra/tegra210_admaif.c11
-rw-r--r--sound/soc/tegra/tegra210_adx.c9
-rw-r--r--sound/soc/tegra/tegra210_amx.c9
-rw-r--r--sound/soc/tegra/tegra210_dmic.c7
-rw-r--r--sound/soc/tegra/tegra210_i2s.c14
-rw-r--r--sound/soc/tegra/tegra210_i2s.h9
-rw-r--r--sound/soc/tegra/tegra210_mixer.c9
-rw-r--r--sound/soc/tegra/tegra210_mvc.c9
-rw-r--r--sound/soc/tegra/tegra210_ope.c9
-rw-r--r--sound/soc/tegra/tegra210_sfc.c9
-rw-r--r--sound/soc/ti/rx51.c12
-rw-r--r--sound/soc/uniphier/aio-core.c25
-rw-r--r--sound/soc/uniphier/evea.c2
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c6
-rw-r--r--sound/sparc/cs4231.c2
-rw-r--r--sound/sparc/dbri.c4
-rw-r--r--sound/usb/6fire/chip.c10
-rw-r--r--sound/usb/caiaq/audio.c10
-rw-r--r--sound/usb/caiaq/audio.h1
-rw-r--r--sound/usb/caiaq/device.c19
-rw-r--r--sound/usb/caiaq/input.c12
-rw-r--r--sound/usb/caiaq/input.h1
-rw-r--r--sound/usb/clock.c24
-rw-r--r--sound/usb/mixer.c60
-rw-r--r--sound/usb/mixer_quirks.c68
-rw-r--r--sound/usb/mixer_scarlett2.c220
-rw-r--r--sound/usb/quirks-table.h71
-rw-r--r--sound/usb/quirks.c58
-rw-r--r--sound/usb/usbaudio.h4
-rw-r--r--sound/usb/usx2y/us122l.c21
-rw-r--r--sound/usb/usx2y/us122l.h2
-rw-r--r--sound/usb/usx2y/usbusx2y.c2
-rw-r--r--tools/arch/arm64/include/asm/brk-imm.h42
-rw-r--r--tools/arch/arm64/include/asm/esr.h455
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h3
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h2
-rw-r--r--tools/bpf/bpf_jit_disasm.c2
-rw-r--r--tools/bpf/bpftool/Makefile6
-rw-r--r--tools/bpf/bpftool/btf.c100
-rw-r--r--tools/bpf/bpftool/jit_disasm.c40
-rw-r--r--tools/bpf/bpftool/pids.c2
-rw-r--r--tools/bpf/resolve_btfids/main.c4
-rw-r--r--tools/bpf/runqslower/runqslower.bpf.c1
-rw-r--r--tools/build/Makefile.feature12
-rw-r--r--tools/build/feature/Makefile28
-rw-r--r--tools/build/feature/test-all.c16
-rw-r--r--tools/build/feature/test-dwarf.c11
-rw-r--r--tools/build/feature/test-dwarf_getcfi.c9
-rw-r--r--tools/build/feature/test-dwarf_getlocations.c13
-rw-r--r--tools/build/feature/test-libcpupower.c8
-rw-r--r--tools/build/feature/test-libdw-dwarf-unwind.c14
-rw-r--r--tools/build/feature/test-libdw.c56
-rw-r--r--tools/build/feature/test-libtraceevent.c2
-rw-r--r--tools/firewire/decode-fcp.c2
-rw-r--r--tools/firewire/nosy-dump.c6
-rw-r--r--tools/gpio/gpio-event-mon.c8
-rwxr-xr-xtools/gpio/gpio-sloppy-logic-analyzer.sh2
-rw-r--r--tools/iio/iio_event_monitor.c3
-rw-r--r--tools/include/linux/compiler-gcc.h2
-rw-r--r--tools/include/nolibc/arch-s390.h1
-rw-r--r--tools/include/nolibc/compiler.h6
-rw-r--r--tools/include/nolibc/stdio.h3
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h3
-rw-r--r--tools/include/uapi/asm-generic/socket.h2
-rw-r--r--tools/include/uapi/linux/bpf.h9
-rw-r--r--tools/include/uapi/linux/if_link.h554
-rw-r--r--tools/include/uapi/linux/netdev.h4
-rw-r--r--tools/lib/api/io.h1
-rw-r--r--tools/lib/bpf/Makefile3
-rw-r--r--tools/lib/bpf/bpf.c1
-rw-r--r--tools/lib/bpf/bpf_gen_internal.h1
-rw-r--r--tools/lib/bpf/bpf_helpers.h1
-rw-r--r--tools/lib/bpf/btf.c308
-rw-r--r--tools/lib/bpf/btf.h3
-rw-r--r--tools/lib/bpf/btf_dump.c7
-rw-r--r--tools/lib/bpf/btf_relocate.c2
-rw-r--r--tools/lib/bpf/elf.c4
-rw-r--r--tools/lib/bpf/features.c15
-rw-r--r--tools/lib/bpf/gen_loader.c190
-rw-r--r--tools/lib/bpf/hashmap.h20
-rw-r--r--tools/lib/bpf/libbpf.c526
-rw-r--r--tools/lib/bpf/libbpf.h4
-rw-r--r--tools/lib/bpf/libbpf.map5
-rw-r--r--tools/lib/bpf/libbpf_internal.h43
-rw-r--r--tools/lib/bpf/libbpf_version.h2
-rw-r--r--tools/lib/bpf/linker.c105
-rw-r--r--tools/lib/bpf/relo_core.c2
-rw-r--r--tools/lib/bpf/ringbuf.c34
-rw-r--r--tools/lib/bpf/skel_internal.h3
-rw-r--r--tools/lib/bpf/str_error.c71
-rw-r--r--tools/lib/bpf/str_error.h7
-rw-r--r--tools/lib/bpf/usdt.c32
-rw-r--r--tools/lib/bpf/zip.c2
-rw-r--r--tools/lib/list_sort.c2
-rw-r--r--tools/lib/perf/Documentation/Makefile2
-rw-r--r--tools/lib/perf/evsel.c48
-rw-r--r--tools/lib/perf/include/internal/evsel.h63
-rw-r--r--tools/lib/subcmd/parse-options.c2
-rw-r--r--tools/lib/subcmd/run-command.c33
-rw-r--r--tools/lib/subcmd/subcmd-util.h2
-rw-r--r--tools/lib/thermal/Makefile4
-rw-r--r--tools/lib/thermal/commands.c188
-rw-r--r--tools/lib/thermal/events.c55
-rw-r--r--tools/lib/thermal/include/thermal.h40
-rw-r--r--tools/lib/thermal/libthermal.map5
-rw-r--r--tools/lib/thermal/sampling.c2
-rw-r--r--tools/lib/thermal/thermal.c17
-rw-r--r--tools/mm/page-types.c2
-rw-r--r--tools/mm/page_owner_sort.c1
-rw-r--r--tools/mm/slabinfo.c10
-rwxr-xr-xtools/net/sunrpc/extract.sh11
-rw-r--r--tools/net/sunrpc/xdrgen/README17
-rw-r--r--tools/net/sunrpc/xdrgen/generators/__init__.py4
-rw-r--r--tools/net/sunrpc/xdrgen/generators/enum.py30
-rw-r--r--tools/net/sunrpc/xdrgen/generators/pointer.py26
-rw-r--r--tools/net/sunrpc/xdrgen/generators/struct.py26
-rw-r--r--tools/net/sunrpc/xdrgen/generators/typedef.py28
-rw-r--r--tools/net/sunrpc/xdrgen/generators/union.py52
-rw-r--r--tools/net/sunrpc/xdrgen/grammars/xdr.lark6
-rw-r--r--tools/net/sunrpc/xdrgen/subcmds/definitions.py24
-rw-r--r--tools/net/sunrpc/xdrgen/subcmds/source.py3
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/declaration/close.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j214
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/definition/close.j21
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/definition/close_be.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j214
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/maxsize/enum.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/maxsize/pointer.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/decoder/result.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/source_top/client.j29
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/maxsize/struct.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/definition/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/basic.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/fixed_length_opaque.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/string.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_array.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_opaque.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec_be.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/string.j2 (renamed from tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_string.j2)0
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec_be.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/maxsize/union.j23
-rw-r--r--tools/net/sunrpc/xdrgen/xdr_ast.py313
-rwxr-xr-xtools/net/sunrpc/xdrgen/xdrgen4
-rwxr-xr-xtools/net/ynl/cli.py19
-rwxr-xr-xtools/net/ynl/ethtool.py2
-rw-r--r--tools/net/ynl/generated/Makefile2
-rw-r--r--tools/net/ynl/lib/Makefile2
-rw-r--r--tools/net/ynl/lib/nlspec.py3
-rw-r--r--tools/net/ynl/lib/ynl.py28
-rw-r--r--tools/net/ynl/samples/Makefile2
-rw-r--r--tools/net/ynl/samples/page-pool.c2
-rwxr-xr-xtools/net/ynl/ynl-gen-c.py82
-rw-r--r--tools/objtool/Makefile1
-rw-r--r--tools/objtool/arch/x86/decode.c15
-rw-r--r--tools/objtool/check.c115
-rw-r--r--tools/objtool/elf.c15
-rw-r--r--tools/objtool/include/objtool/arch.h1
-rw-r--r--tools/objtool/noreturns.h1
-rw-r--r--tools/pci/pcitest.c10
-rw-r--r--tools/perf/.gitignore6
-rw-r--r--tools/perf/Documentation/itrace.txt2
-rw-r--r--tools/perf/Documentation/perf-arm-spe.txt2
-rw-r--r--tools/perf/Documentation/perf-check.txt6
-rw-r--r--tools/perf/Documentation/perf-config.txt13
-rw-r--r--tools/perf/Documentation/perf-list.txt17
-rw-r--r--tools/perf/Documentation/perf-report.txt8
-rw-r--r--tools/perf/Documentation/perf-sched.txt8
-rw-r--r--tools/perf/Documentation/perf-script-python.txt2
-rw-r--r--tools/perf/Documentation/perf-test.txt17
-rw-r--r--tools/perf/Makefile.config70
-rw-r--r--tools/perf/Makefile.perf9
-rw-r--r--tools/perf/arch/arc/annotate/instructions.c2
-rw-r--r--tools/perf/arch/arm/Makefile3
-rw-r--r--tools/perf/arch/arm/annotate/instructions.c2
-rw-r--r--tools/perf/arch/arm/util/Build2
-rw-r--r--tools/perf/arch/arm/util/dwarf-regs.c61
-rw-r--r--tools/perf/arch/arm64/Makefile4
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c2
-rw-r--r--tools/perf/arch/arm64/util/Build1
-rw-r--r--tools/perf/arch/arm64/util/arm-spe.c116
-rw-r--r--tools/perf/arch/arm64/util/dwarf-regs.c92
-rw-r--r--tools/perf/arch/arm64/util/header.c73
-rw-r--r--tools/perf/arch/arm64/util/pmu.c25
-rw-r--r--tools/perf/arch/csky/Makefile4
-rw-r--r--tools/perf/arch/csky/annotate/instructions.c7
-rw-r--r--tools/perf/arch/csky/util/Build1
-rw-r--r--tools/perf/arch/loongarch/Makefile4
-rw-r--r--tools/perf/arch/loongarch/annotate/instructions.c2
-rw-r--r--tools/perf/arch/loongarch/util/Build1
-rw-r--r--tools/perf/arch/loongarch/util/dwarf-regs.c44
-rw-r--r--tools/perf/arch/loongarch/util/header.c4
-rw-r--r--tools/perf/arch/mips/Makefile4
-rw-r--r--tools/perf/arch/mips/annotate/instructions.c2
-rw-r--r--tools/perf/arch/mips/util/Build1
-rw-r--r--tools/perf/arch/mips/util/dwarf-regs.c38
-rw-r--r--tools/perf/arch/powerpc/Makefile5
-rw-r--r--tools/perf/arch/powerpc/annotate/instructions.c6
-rw-r--r--tools/perf/arch/powerpc/util/Build3
-rw-r--r--tools/perf/arch/powerpc/util/dwarf-regs.c153
-rw-r--r--tools/perf/arch/powerpc/util/header.c36
-rw-r--r--tools/perf/arch/riscv/Makefile27
-rwxr-xr-xtools/perf/arch/riscv/entry/syscalls/mksyscalltbl47
-rw-r--r--tools/perf/arch/riscv/include/dwarf-regs-table.h42
-rw-r--r--tools/perf/arch/riscv/util/Build1
-rw-r--r--tools/perf/arch/riscv/util/dwarf-regs.c72
-rw-r--r--tools/perf/arch/riscv/util/header.c4
-rw-r--r--tools/perf/arch/riscv64/annotate/instructions.c2
-rw-r--r--tools/perf/arch/s390/Makefile4
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c2
-rw-r--r--tools/perf/arch/s390/util/Build1
-rw-r--r--tools/perf/arch/s390/util/dwarf-regs.c43
-rw-r--r--tools/perf/arch/s390/util/header.c6
-rw-r--r--tools/perf/arch/sh/Build1
-rw-r--r--tools/perf/arch/sh/Makefile4
-rw-r--r--tools/perf/arch/sh/util/Build1
-rw-r--r--tools/perf/arch/sh/util/dwarf-regs.c41
-rw-r--r--tools/perf/arch/sparc/Build1
-rw-r--r--tools/perf/arch/sparc/Makefile4
-rw-r--r--tools/perf/arch/sparc/annotate/instructions.c2
-rw-r--r--tools/perf/arch/sparc/util/Build1
-rw-r--r--tools/perf/arch/sparc/util/dwarf-regs.c39
-rw-r--r--tools/perf/arch/x86/Makefile4
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c5
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c128
-rw-r--r--tools/perf/arch/x86/tests/intel-pt-test.c4
-rw-r--r--tools/perf/arch/x86/util/Build4
-rw-r--r--tools/perf/arch/x86/util/auxtrace.c3
-rw-r--r--tools/perf/arch/x86/util/dwarf-regs.c153
-rw-r--r--tools/perf/arch/x86/util/env.c19
-rw-r--r--tools/perf/arch/x86/util/env.h7
-rw-r--r--tools/perf/arch/x86/util/evlist.c147
-rw-r--r--tools/perf/arch/x86/util/evsel.c38
-rw-r--r--tools/perf/arch/x86/util/header.c5
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c3
-rw-r--r--tools/perf/arch/x86/util/iostat.c2
-rw-r--r--tools/perf/arch/x86/util/pmu.c2
-rw-r--r--tools/perf/arch/x86/util/topdown.c43
-rw-r--r--tools/perf/arch/x86/util/topdown.h2
-rw-r--r--tools/perf/arch/x86/util/tsc.c18
-rw-r--r--tools/perf/arch/xtensa/Build1
-rw-r--r--tools/perf/arch/xtensa/Makefile4
-rw-r--r--tools/perf/arch/xtensa/util/Build1
-rw-r--r--tools/perf/arch/xtensa/util/dwarf-regs.c21
-rw-r--r--tools/perf/bench/numa.c53
-rw-r--r--tools/perf/bench/sched-pipe.c43
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-check.c6
-rw-r--r--tools/perf/builtin-diff.c6
-rw-r--r--tools/perf/builtin-ftrace.c2
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-kvm.c5
-rw-r--r--tools/perf/builtin-kwork.c2
-rw-r--r--tools/perf/builtin-list.c17
-rw-r--r--tools/perf/builtin-probe.c14
-rw-r--r--tools/perf/builtin-record.c4
-rw-r--r--tools/perf/builtin-report.c12
-rw-r--r--tools/perf/builtin-sched.c116
-rw-r--r--tools/perf/builtin-script.c9
-rw-r--r--tools/perf/builtin-stat.c396
-rw-r--r--tools/perf/builtin-timechart.c3
-rw-r--r--tools/perf/builtin-trace.c27
-rw-r--r--tools/perf/check-header_ignore_hunks/lib/list_sort.c11
-rw-r--r--tools/perf/dlfilters/dlfilter-test-api-v0.c2
-rw-r--r--tools/perf/dlfilters/dlfilter-test-api-v2.c2
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/pmu-events/arch/arm64/freescale/imx91/sys/ddrc.json9
-rw-r--r--tools/perf/pmu-events/arch/arm64/freescale/imx91/sys/metrics.json26
-rw-r--r--tools/perf/pmu-events/arch/arm64/freescale/imx95/sys/metrics.json8
-rw-r--r--tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json74
-rw-r--r--tools/perf/pmu-events/arch/common/common/tool.json74
-rw-r--r--tools/perf/pmu-events/arch/powerpc/compat/generic-events.json117
-rw-r--r--tools/perf/pmu-events/arch/powerpc/mapfile.csv1
-rw-r--r--tools/perf/pmu-events/arch/x86/amdzen5/data-fabric.json1634
-rw-r--r--tools/perf/pmu-events/arch/x86/amdzen5/load-store.json78
-rw-r--r--tools/perf/pmu-events/arch/x86/amdzen5/recommended.json112
-rw-r--r--tools/perf/pmu-events/empty-pmu-events.c249
-rwxr-xr-xtools/perf/pmu-events/jevents.py57
-rw-r--r--tools/perf/pmu-events/pmu-events.h2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c11
-rwxr-xr-xtools/perf/scripts/python/arm-cs-trace-disasm.py143
-rw-r--r--tools/perf/tests/Build4
-rw-r--r--tools/perf/tests/attr.c218
-rw-r--r--tools/perf/tests/builtin-test.c438
-rw-r--r--tools/perf/tests/demangle-java-test.c3
-rw-r--r--tools/perf/tests/event-times.c5
-rw-r--r--tools/perf/tests/evsel-tp-sched.c42
-rw-r--r--tools/perf/tests/expr.c5
-rw-r--r--tools/perf/tests/hwmon_pmu.c342
-rw-r--r--tools/perf/tests/make6
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c19
-rw-r--r--tools/perf/tests/parse-events.c32
-rw-r--r--tools/perf/tests/pmu.c3
-rwxr-xr-xtools/perf/tests/shell/annotate.sh10
-rwxr-xr-xtools/perf/tests/shell/attr.sh22
-rw-r--r--tools/perf/tests/shell/attr/README (renamed from tools/perf/tests/attr/README)2
-rw-r--r--tools/perf/tests/shell/attr/base-record (renamed from tools/perf/tests/attr/base-record)0
-rw-r--r--tools/perf/tests/shell/attr/base-record-spe (renamed from tools/perf/tests/attr/base-record-spe)0
-rw-r--r--tools/perf/tests/shell/attr/base-stat (renamed from tools/perf/tests/attr/base-stat)0
-rw-r--r--tools/perf/tests/shell/attr/system-wide-dummy (renamed from tools/perf/tests/attr/system-wide-dummy)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-C0 (renamed from tools/perf/tests/attr/test-record-C0)2
-rw-r--r--tools/perf/tests/shell/attr/test-record-basic (renamed from tools/perf/tests/attr/test-record-basic)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-any (renamed from tools/perf/tests/attr/test-record-branch-any)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-filter-any (renamed from tools/perf/tests/attr/test-record-branch-filter-any)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-filter-any_call (renamed from tools/perf/tests/attr/test-record-branch-filter-any_call)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-filter-any_ret (renamed from tools/perf/tests/attr/test-record-branch-filter-any_ret)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-filter-hv (renamed from tools/perf/tests/attr/test-record-branch-filter-hv)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-filter-ind_call (renamed from tools/perf/tests/attr/test-record-branch-filter-ind_call)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-filter-k (renamed from tools/perf/tests/attr/test-record-branch-filter-k)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-branch-filter-u (renamed from tools/perf/tests/attr/test-record-branch-filter-u)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-count (renamed from tools/perf/tests/attr/test-record-count)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-data (renamed from tools/perf/tests/attr/test-record-data)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-dummy-C0 (renamed from tools/perf/tests/attr/test-record-dummy-C0)4
-rw-r--r--tools/perf/tests/shell/attr/test-record-freq (renamed from tools/perf/tests/attr/test-record-freq)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-graph-default (renamed from tools/perf/tests/attr/test-record-graph-default)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-graph-default-aarch64 (renamed from tools/perf/tests/attr/test-record-graph-default-aarch64)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-graph-dwarf (renamed from tools/perf/tests/attr/test-record-graph-dwarf)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-graph-fp (renamed from tools/perf/tests/attr/test-record-graph-fp)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-graph-fp-aarch64 (renamed from tools/perf/tests/attr/test-record-graph-fp-aarch64)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-group-sampling (renamed from tools/perf/tests/attr/test-record-group-sampling)3
-rw-r--r--tools/perf/tests/shell/attr/test-record-group-sampling150
-rw-r--r--tools/perf/tests/shell/attr/test-record-group-sampling261
-rw-r--r--tools/perf/tests/shell/attr/test-record-group1 (renamed from tools/perf/tests/attr/test-record-group1)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-group2 (renamed from tools/perf/tests/attr/test-record-group2)1
-rw-r--r--tools/perf/tests/shell/attr/test-record-group331
-rw-r--r--tools/perf/tests/shell/attr/test-record-no-buffering (renamed from tools/perf/tests/attr/test-record-no-buffering)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-no-inherit (renamed from tools/perf/tests/attr/test-record-no-inherit)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-no-samples (renamed from tools/perf/tests/attr/test-record-no-samples)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-period (renamed from tools/perf/tests/attr/test-record-period)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-pfm-period (renamed from tools/perf/tests/attr/test-record-pfm-period)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-raw (renamed from tools/perf/tests/attr/test-record-raw)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-spe-period (renamed from tools/perf/tests/attr/test-record-spe-period)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-spe-period-term (renamed from tools/perf/tests/attr/test-record-spe-period-term)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-spe-physical-address (renamed from tools/perf/tests/attr/test-record-spe-physical-address)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-user-regs-no-sve-aarch64 (renamed from tools/perf/tests/attr/test-record-user-regs-no-sve-aarch64)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-user-regs-old-sve-aarch64 (renamed from tools/perf/tests/attr/test-record-user-regs-old-sve-aarch64)0
-rw-r--r--tools/perf/tests/shell/attr/test-record-user-regs-sve-aarch64 (renamed from tools/perf/tests/attr/test-record-user-regs-sve-aarch64)0
-rw-r--r--tools/perf/tests/shell/attr/test-stat-C0 (renamed from tools/perf/tests/attr/test-stat-C0)0
-rw-r--r--tools/perf/tests/shell/attr/test-stat-basic (renamed from tools/perf/tests/attr/test-stat-basic)0
-rw-r--r--tools/perf/tests/shell/attr/test-stat-default (renamed from tools/perf/tests/attr/test-stat-default)90
-rw-r--r--tools/perf/tests/shell/attr/test-stat-detailed-1 (renamed from tools/perf/tests/attr/test-stat-detailed-1)106
-rw-r--r--tools/perf/tests/shell/attr/test-stat-detailed-2 (renamed from tools/perf/tests/attr/test-stat-detailed-2)130
-rw-r--r--tools/perf/tests/shell/attr/test-stat-detailed-3 (renamed from tools/perf/tests/attr/test-stat-detailed-3)138
-rw-r--r--tools/perf/tests/shell/attr/test-stat-group1 (renamed from tools/perf/tests/attr/test-stat-group1)0
-rw-r--r--tools/perf/tests/shell/attr/test-stat-no-inherit (renamed from tools/perf/tests/attr/test-stat-no-inherit)0
-rwxr-xr-xtools/perf/tests/shell/coresight/asm_pure_loop.sh2
-rwxr-xr-xtools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh2
-rwxr-xr-xtools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh2
-rwxr-xr-xtools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh2
-rwxr-xr-xtools/perf/tests/shell/coresight/unroll_loop_thread_10.sh2
-rwxr-xr-xtools/perf/tests/shell/ftrace.sh4
-rw-r--r--tools/perf/tests/shell/lib/attr.py (renamed from tools/perf/tests/attr.py)18
-rw-r--r--tools/perf/tests/shell/lib/coresight.sh2
-rw-r--r--tools/perf/tests/shell/lib/perf_json_output_lint.py5
-rwxr-xr-xtools/perf/tests/shell/list.sh5
-rwxr-xr-xtools/perf/tests/shell/lock_contention.sh2
-rwxr-xr-xtools/perf/tests/shell/perftool-testsuite_report.sh2
-rwxr-xr-xtools/perf/tests/shell/pipe_test.sh1
-rwxr-xr-xtools/perf/tests/shell/probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh4
-rwxr-xr-xtools/perf/tests/shell/record+script_probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/record.sh75
-rwxr-xr-xtools/perf/tests/shell/record_lbr.sh2
-rwxr-xr-xtools/perf/tests/shell/record_offcpu.sh2
-rwxr-xr-xtools/perf/tests/shell/stat.sh65
-rwxr-xr-xtools/perf/tests/shell/stat_all_metricgroups.sh36
-rwxr-xr-xtools/perf/tests/shell/stat_all_metrics.sh87
-rwxr-xr-xtools/perf/tests/shell/stat_all_pmu.sh54
-rwxr-xr-xtools/perf/tests/shell/stat_bpf_counters.sh4
-rwxr-xr-xtools/perf/tests/shell/stat_bpf_counters_cgrp.sh13
-rwxr-xr-xtools/perf/tests/shell/test_arm_coresight.sh4
-rwxr-xr-xtools/perf/tests/shell/test_arm_coresight_disasm.sh65
-rwxr-xr-xtools/perf/tests/shell/test_arm_spe.sh4
-rwxr-xr-xtools/perf/tests/shell/test_arm_spe_fork.sh2
-rwxr-xr-xtools/perf/tests/shell/test_data_symbol.sh2
-rwxr-xr-xtools/perf/tests/shell/test_intel_pt.sh4
-rwxr-xr-xtools/perf/tests/shell/test_stat_intel_tpebs.sh13
-rwxr-xr-xtools/perf/tests/shell/trace+probe_vfs_getname.sh4
-rwxr-xr-xtools/perf/tests/shell/trace_exit_race.sh51
-rw-r--r--tools/perf/tests/task-exit.c9
-rw-r--r--tools/perf/tests/tests-scripts.c7
-rw-r--r--tools/perf/tests/tests.h11
-rw-r--r--tools/perf/tests/tool_pmu.c111
-rw-r--r--tools/perf/util/Build17
-rw-r--r--tools/perf/util/annotate-data.h8
-rw-r--r--tools/perf/util/annotate.c12
-rw-r--r--tools/perf/util/annotate.h6
-rw-r--r--tools/perf/util/arm-spe-decoder/arm-spe-decoder.h18
-rw-r--r--tools/perf/util/arm-spe.c321
-rw-r--r--tools/perf/util/arm-spe.h38
-rw-r--r--tools/perf/util/auxtrace.h3
-rw-r--r--tools/perf/util/bpf-filter.c2
-rw-r--r--tools/perf/util/bpf-prologue.h37
-rw-r--r--tools/perf/util/bpf_counter.c35
-rw-r--r--tools/perf/util/bpf_skel/bperf_follower.bpf.c98
-rw-r--r--tools/perf/util/bpf_skel/bperf_u.h5
-rw-r--r--tools/perf/util/color.c28
-rw-r--r--tools/perf/util/color.h11
-rw-r--r--tools/perf/util/config.c22
-rw-r--r--tools/perf/util/config.h1
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c7
-rw-r--r--tools/perf/util/cs-etm.c25
-rw-r--r--tools/perf/util/data-convert-bt.c2
-rw-r--r--tools/perf/util/data-convert-json.c2
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debuginfo.h6
-rw-r--r--tools/perf/util/disasm.c298
-rw-r--r--tools/perf/util/disasm.h8
-rw-r--r--tools/perf/util/dwarf-aux.c6
-rw-r--r--tools/perf/util/dwarf-aux.h54
-rw-r--r--tools/perf/util/dwarf-regs-csky.c (renamed from tools/perf/arch/csky/util/dwarf-regs.c)19
-rw-r--r--tools/perf/util/dwarf-regs-powerpc.c61
-rw-r--r--tools/perf/util/dwarf-regs-x86.c50
-rw-r--r--tools/perf/util/dwarf-regs.c38
-rw-r--r--tools/perf/util/env.c27
-rw-r--r--tools/perf/util/env.h4
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evlist.c83
-rw-r--r--tools/perf/util/evlist.h15
-rw-r--r--tools/perf/util/evsel.c886
-rw-r--r--tools/perf/util/evsel.h52
-rw-r--r--tools/perf/util/evsel_fprintf.c2
-rw-r--r--tools/perf/util/expr.c97
-rw-r--r--tools/perf/util/genelf.c4
-rw-r--r--tools/perf/util/genelf.h2
-rw-r--r--tools/perf/util/hashmap.h20
-rw-r--r--tools/perf/util/header.c84
-rw-r--r--tools/perf/util/header.h23
-rw-r--r--tools/perf/util/hist.c3
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/hwmon_pmu.c832
-rw-r--r--tools/perf/util/hwmon_pmu.h151
-rw-r--r--tools/perf/util/include/dwarf-regs.h124
-rw-r--r--tools/perf/util/intel-bts.c4
-rw-r--r--tools/perf/util/intel-pt.c4
-rw-r--r--tools/perf/util/machine.c2
-rw-r--r--tools/perf/util/mem-events.c8
-rw-r--r--tools/perf/util/metricgroup.c39
-rw-r--r--tools/perf/util/parse-events.c125
-rw-r--r--tools/perf/util/parse-events.h13
-rw-r--r--tools/perf/util/parse-events.l11
-rw-r--r--tools/perf/util/parse-events.y18
-rw-r--r--tools/perf/util/pfm.c4
-rw-r--r--tools/perf/util/pmu.c137
-rw-r--r--tools/perf/util/pmu.h18
-rw-r--r--tools/perf/util/pmus.c18
-rw-r--r--tools/perf/util/pmus.h3
-rw-r--r--tools/perf/util/print-events.c36
-rw-r--r--tools/perf/util/print-events.h1
-rw-r--r--tools/perf/util/probe-event.c182
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-file.c19
-rw-r--r--tools/perf/util/probe-file.h1
-rw-r--r--tools/perf/util/probe-finder.c42
-rw-r--r--tools/perf/util/probe-finder.h13
-rw-r--r--tools/perf/util/python.c2
-rw-r--r--tools/perf/util/s390-cpumsf.c2
-rw-r--r--tools/perf/util/s390-sample-raw.c8
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c11
-rw-r--r--tools/perf/util/session.c28
-rw-r--r--tools/perf/util/sort.c115
-rw-r--r--tools/perf/util/sort.h3
-rw-r--r--tools/perf/util/stat-display.c196
-rw-r--r--tools/perf/util/stat-shadow.c166
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/stat.h16
-rw-r--r--tools/perf/util/string.c100
-rw-r--r--tools/perf/util/string2.h2
-rw-r--r--tools/perf/util/symbol.c2
-rw-r--r--tools/perf/util/syscalltbl.c4
-rw-r--r--tools/perf/util/target.h1
-rw-r--r--tools/perf/util/threads.c4
-rw-r--r--tools/perf/util/tool_pmu.c505
-rw-r--r--tools/perf/util/tool_pmu.h56
-rw-r--r--tools/perf/util/trace-event-parse.c8
-rw-r--r--tools/perf/util/trace-event-read.c2
-rw-r--r--tools/perf/util/trace-event-scripting.c2
-rw-r--r--tools/perf/util/trace-event.c2
-rw-r--r--tools/perf/util/trace-event.h5
-rw-r--r--tools/perf/util/tsc.c2
-rw-r--r--tools/perf/util/tsc.h2
-rw-r--r--tools/perf/util/util.c95
-rw-r--r--tools/perf/util/util.h18
-rw-r--r--tools/power/cpupower/.gitignore3
-rw-r--r--tools/power/cpupower/Makefile26
-rw-r--r--tools/power/cpupower/bench/parse.c5
-rwxr-xr-xtools/power/cpupower/bindings/python/test_raw_pylibcpupower.py28
-rw-r--r--tools/power/cpupower/man/cpupower-set.138
-rw-r--r--tools/power/cpupower/po/zh_CN.po942
-rw-r--r--tools/power/pm-graph/sleepgraph.83
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py59
-rw-r--r--tools/power/x86/turbostat/turbostat.827
-rw-r--r--tools/power/x86/turbostat/turbostat.c425
-rw-r--r--tools/sched_ext/include/scx/common.bpf.h18
-rw-r--r--tools/sched_ext/include/scx/compat.bpf.h117
-rw-r--r--tools/sched_ext/scx_central.bpf.c14
-rw-r--r--tools/sched_ext/scx_flatcg.bpf.c20
-rw-r--r--tools/sched_ext/scx_qmap.bpf.c36
-rw-r--r--tools/sched_ext/scx_show_state.py4
-rw-r--r--tools/sched_ext/scx_simple.bpf.c16
-rw-r--r--tools/spi/spidev_test.c11
-rwxr-xr-xtools/testing/kunit/kunit.py28
-rw-r--r--tools/testing/kunit/kunit_kernel.py4
-rw-r--r--tools/testing/kunit/kunit_parser.py134
-rw-r--r--tools/testing/kunit/kunit_printer.py14
-rwxr-xr-xtools/testing/kunit/kunit_tool_test.py55
-rw-r--r--tools/testing/kunit/qemu_configs/loongarch.py21
-rw-r--r--tools/testing/radix-tree/maple.c22
-rw-r--r--tools/testing/selftests/Makefile3
-rw-r--r--tools/testing/selftests/alsa/.gitignore2
-rw-r--r--tools/testing/selftests/arm64/Makefile2
-rw-r--r--tools/testing/selftests/arm64/abi/hwcap.c25
-rw-r--r--tools/testing/selftests/arm64/abi/syscall-abi.c8
-rw-r--r--tools/testing/selftests/arm64/fp/assembler.h15
-rw-r--r--tools/testing/selftests/arm64/fp/fp-ptrace-asm.S41
-rw-r--r--tools/testing/selftests/arm64/fp/fp-ptrace.c161
-rw-r--r--tools/testing/selftests/arm64/fp/fp-ptrace.h12
-rw-r--r--tools/testing/selftests/arm64/fp/fp-stress.c49
-rw-r--r--tools/testing/selftests/arm64/fp/fpsimd-test.S6
-rw-r--r--tools/testing/selftests/arm64/fp/kernel-test.c4
-rw-r--r--tools/testing/selftests/arm64/fp/sme-inst.h2
-rw-r--r--tools/testing/selftests/arm64/fp/sve-ptrace.c16
-rw-r--r--tools/testing/selftests/arm64/fp/sve-test.S10
-rw-r--r--tools/testing/selftests/arm64/fp/za-ptrace.c8
-rw-r--r--tools/testing/selftests/arm64/fp/za-test.S15
-rw-r--r--tools/testing/selftests/arm64/fp/zt-ptrace.c8
-rw-r--r--tools/testing/selftests/arm64/fp/zt-test.S15
-rw-r--r--tools/testing/selftests/arm64/gcs/.gitignore7
-rw-r--r--tools/testing/selftests/arm64/gcs/Makefile30
-rw-r--r--tools/testing/selftests/arm64/gcs/asm-offsets.h0
-rw-r--r--tools/testing/selftests/arm64/gcs/basic-gcs.c357
-rw-r--r--tools/testing/selftests/arm64/gcs/gcs-locking.c200
-rw-r--r--tools/testing/selftests/arm64/gcs/gcs-stress-thread.S311
-rw-r--r--tools/testing/selftests/arm64/gcs/gcs-stress.c530
-rw-r--r--tools/testing/selftests/arm64/gcs/gcs-util.h100
-rw-r--r--tools/testing/selftests/arm64/gcs/gcspushm.S96
-rw-r--r--tools/testing/selftests/arm64/gcs/gcsstr.S99
-rw-r--r--tools/testing/selftests/arm64/gcs/libc-gcs.c728
-rw-r--r--tools/testing/selftests/arm64/mte/check_buffer_fill.c4
-rw-r--r--tools/testing/selftests/arm64/mte/check_hugetlb_options.c285
-rw-r--r--tools/testing/selftests/arm64/mte/check_prctl.c2
-rw-r--r--tools/testing/selftests/arm64/mte/check_tags_inclusion.c4
-rw-r--r--tools/testing/selftests/arm64/mte/mte_common_util.c29
-rw-r--r--tools/testing/selftests/arm64/mte/mte_common_util.h6
-rw-r--r--tools/testing/selftests/arm64/pauth/Makefile6
-rw-r--r--tools/testing/selftests/arm64/pauth/pac.c5
-rw-r--r--tools/testing/selftests/arm64/signal/.gitignore1
-rw-r--r--tools/testing/selftests/arm64/signal/Makefile2
-rw-r--r--tools/testing/selftests/arm64/signal/sve_helpers.h13
-rw-r--r--tools/testing/selftests/arm64/signal/test_signals.c17
-rw-r--r--tools/testing/selftests/arm64/signal/test_signals.h6
-rw-r--r--tools/testing/selftests/arm64/signal/test_signals_utils.c32
-rw-r--r--tools/testing/selftests/arm64/signal/test_signals_utils.h39
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/gcs_exception_fault.c62
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/gcs_frame.c88
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/gcs_write_fault.c67
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/ssve_regs.c5
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/testcases.c7
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/testcases.h1
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/za_regs.c5
-rw-r--r--tools/testing/selftests/bpf/.gitignore2
-rw-r--r--tools/testing/selftests/bpf/Makefile84
-rw-r--r--tools/testing/selftests/bpf/benchs/bench_trigger.c3
-rw-r--r--tools/testing/selftests/bpf/bpf_experimental.h6
-rw-r--r--tools/testing/selftests/bpf/bpf_testmod/bpf_testmod-events.h8
-rw-r--r--tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c108
-rw-r--r--tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h5
-rw-r--r--tools/testing/selftests/bpf/bpf_util.h12
-rw-r--r--tools/testing/selftests/bpf/config.vm7
-rw-r--r--tools/testing/selftests/bpf/io_helpers.c21
-rw-r--r--tools/testing/selftests/bpf/io_helpers.h7
-rw-r--r--tools/testing/selftests/bpf/map_tests/task_storage_map.c3
-rw-r--r--tools/testing/selftests/bpf/network_helpers.h1
-rw-r--r--tools/testing/selftests/bpf/prog_tests/bpf_cookie.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/bpf_iter.c14
-rw-r--r--tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c264
-rw-r--r--tools/testing/selftests/bpf/prog_tests/cb_refs.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/cgrp_local_storage.c10
-rw-r--r--tools/testing/selftests/bpf/prog_tests/core_reloc.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/iters.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/kmem_cache_iter.c126
-rw-r--r--tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/linked_funcs.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/log_buf.c3
-rw-r--r--tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/map_in_map.c132
-rw-r--r--tools/testing/selftests/bpf/prog_tests/mptcp.c155
-rw-r--r--tools/testing/selftests/bpf/prog_tests/netns_cookie.c29
-rw-r--r--tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/perf_link.c15
-rw-r--r--tools/testing/selftests/bpf/prog_tests/raw_tp_null.c25
-rw-r--r--tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/send_signal.c146
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sock_addr.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sock_create.c348
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sock_post_bind.c (renamed from tools/testing/selftests/bpf/test_sock.c)254
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_basic.c54
-rw-r--r--tools/testing/selftests/bpf/prog_tests/struct_ops_private_stack.c106
-rw-r--r--tools/testing/selftests/bpf/prog_tests/subskeleton.c76
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tailcalls.c128
-rw-r--r--tools/testing/selftests/bpf/prog_tests/task_kfunc.c80
-rw-r--r--tools/testing/selftests/bpf/prog_tests/task_local_storage.c286
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_netkit.c94
-rw-r--r--tools/testing/selftests/bpf/prog_tests/test_csum_diff.c408
-rw-r--r--tools/testing/selftests/bpf/prog_tests/timer_lockup.c6
-rw-r--r--tools/testing/selftests/bpf/prog_tests/token.c19
-rw-r--r--tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c361
-rw-r--r--tools/testing/selftests/bpf/prog_tests/verifier.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/xdp_cpumap_attach.c44
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter.h167
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_array_map.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_hash_map.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_link.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_map.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_percpu_array_map.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_percpu_hash_map.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_helpers.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_bpf_sk_storage_map.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_ipv6_route.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_ksym.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_netlink.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_setsockopt.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_setsockopt_unix.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_sockmap.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_task_btf.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_task_file.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_task_stack.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_task_vmas.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_tasks.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_tcp4.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_tcp6.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_test_kern3.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_test_kern4.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_test_kern5.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_test_kern6.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_test_kern_common.h2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_udp4.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_udp6.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_unix.c2
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_iter_vma_offset.c2
-rw-r--r--tools/testing/selftests/bpf/progs/cgroup_iter.c3
-rw-r--r--tools/testing/selftests/bpf/progs/cgrp_ls_sleepable.c3
-rw-r--r--tools/testing/selftests/bpf/progs/csum_diff_test.c42
-rw-r--r--tools/testing/selftests/bpf/progs/exceptions_fail.c4
-rw-r--r--tools/testing/selftests/bpf/progs/kmem_cache_iter.c108
-rw-r--r--tools/testing/selftests/bpf/progs/kprobe_multi_verifier.c31
-rw-r--r--tools/testing/selftests/bpf/progs/linked_funcs1.c8
-rw-r--r--tools/testing/selftests/bpf/progs/linked_funcs2.c8
-rw-r--r--tools/testing/selftests/bpf/progs/mptcp_bpf.h42
-rw-r--r--tools/testing/selftests/bpf/progs/mptcp_subflow.c128
-rw-r--r--tools/testing/selftests/bpf/progs/netns_cookie_prog.c10
-rw-r--r--tools/testing/selftests/bpf/progs/preempt_lock.c14
-rw-r--r--tools/testing/selftests/bpf/progs/raw_tp_null.c32
-rw-r--r--tools/testing/selftests/bpf/progs/struct_ops_detach.c12
-rw-r--r--tools/testing/selftests/bpf/progs/struct_ops_private_stack.c62
-rw-r--r--tools/testing/selftests/bpf/progs/struct_ops_private_stack_fail.c62
-rw-r--r--tools/testing/selftests/bpf/progs/struct_ops_private_stack_recur.c50
-rw-r--r--tools/testing/selftests/bpf/progs/tailcall_fail.c64
-rw-r--r--tools/testing/selftests/bpf/progs/task_kfunc_common.h1
-rw-r--r--tools/testing/selftests/bpf/progs/task_kfunc_failure.c14
-rw-r--r--tools/testing/selftests/bpf/progs/task_kfunc_success.c51
-rw-r--r--tools/testing/selftests/bpf/progs/task_ls_uptr.c63
-rw-r--r--tools/testing/selftests/bpf/progs/tc_bpf2bpf.c5
-rw-r--r--tools/testing/selftests/bpf/progs/test_btf_skc_cls_ingress.c82
-rw-r--r--tools/testing/selftests/bpf/progs/test_send_signal_kern.c35
-rw-r--r--tools/testing/selftests/bpf/progs/test_spin_lock_fail.c4
-rw-r--r--tools/testing/selftests/bpf/progs/test_tc_link.c12
-rw-r--r--tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c167
-rw-r--r--tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c6
-rw-r--r--tools/testing/selftests/bpf/progs/test_xdp_with_cpumap_helpers.c7
-rw-r--r--tools/testing/selftests/bpf/progs/update_map_in_htab.c30
-rw-r--r--tools/testing/selftests/bpf/progs/uprobe_multi_consumers.c6
-rw-r--r--tools/testing/selftests/bpf/progs/uprobe_multi_session.c71
-rw-r--r--tools/testing/selftests/bpf/progs/uprobe_multi_session_cookie.c48
-rw-r--r--tools/testing/selftests/bpf/progs/uprobe_multi_session_recursive.c44
-rw-r--r--tools/testing/selftests/bpf/progs/uprobe_multi_session_single.c44
-rw-r--r--tools/testing/selftests/bpf/progs/uprobe_multi_verifier.c31
-rw-r--r--tools/testing/selftests/bpf/progs/uptr_failure.c105
-rw-r--r--tools/testing/selftests/bpf/progs/uptr_map_failure.c27
-rw-r--r--tools/testing/selftests/bpf/progs/uptr_update_failure.c42
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_arena_large.c110
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_array_access.c3
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_bits_iter.c32
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_private_stack.c272
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_ref_tracking.c4
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_sock.c60
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_spin_lock.c2
-rw-r--r--tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c3
-rw-r--r--tools/testing/selftests/bpf/test_maps.c4
-rw-r--r--tools/testing/selftests/bpf/test_progs.c114
-rw-r--r--tools/testing/selftests/bpf/test_progs.h14
-rw-r--r--tools/testing/selftests/bpf/test_sockmap.c202
-rwxr-xr-xtools/testing/selftests/bpf/test_tcp_check_syncookie.sh85
-rw-r--r--tools/testing/selftests/bpf/test_tcp_check_syncookie_user.c213
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c4
-rw-r--r--tools/testing/selftests/bpf/uprobe_multi.c4
-rw-r--r--tools/testing/selftests/bpf/uptr_test_common.h63
-rw-r--r--tools/testing/selftests/bpf/veristat.c161
-rw-r--r--tools/testing/selftests/cgroup/test_cpu.c75
-rw-r--r--tools/testing/selftests/damon/_debugfs_common.sh7
-rw-r--r--tools/testing/selftests/damon/access_memory_even.c2
-rwxr-xr-xtools/testing/selftests/damon/debugfs_duplicate_context_creation.sh2
-rw-r--r--tools/testing/selftests/damon/huge_count_read_write.c4
-rw-r--r--tools/testing/selftests/drivers/net/Makefile1
-rwxr-xr-xtools/testing/selftests/drivers/net/bonding/bond_options.sh54
-rw-r--r--tools/testing/selftests/drivers/net/hw/.gitignore1
-rw-r--r--tools/testing/selftests/drivers/net/hw/Makefile11
-rwxr-xr-xtools/testing/selftests/drivers/net/hw/devmem.py45
-rw-r--r--tools/testing/selftests/drivers/net/hw/lib/py/__init__.py1
-rw-r--r--tools/testing/selftests/drivers/net/hw/lib/py/linkconfig.py222
-rw-r--r--tools/testing/selftests/drivers/net/hw/ncdevmem.c789
-rw-r--r--tools/testing/selftests/drivers/net/hw/nic_link_layer.py113
-rw-r--r--tools/testing/selftests/drivers/net/hw/nic_performance.py137
-rwxr-xr-xtools/testing/selftests/drivers/net/hw/rss_ctx.py107
-rw-r--r--tools/testing/selftests/drivers/net/lib/py/load.py20
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap.sh2
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh4
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh12
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh85
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_ipip.sh4
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_ipip6.sh4
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_vxlan.sh4
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/devlink_trap_tunnel_vxlan_ipv6.sh4
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/qos_ets_strict.sh167
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/qos_max_descriptors.sh118
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh138
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh10
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/sch_ets.sh26
-rw-r--r--tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh213
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh32
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/sch_red_root.sh18
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/tc_sample.sh4
-rwxr-xr-xtools/testing/selftests/drivers/net/netcons_basic.sh40
-rw-r--r--tools/testing/selftests/drivers/net/netdevsim/Makefile3
-rw-r--r--tools/testing/selftests/drivers/net/netdevsim/config1
-rw-r--r--tools/testing/selftests/drivers/net/netdevsim/ethtool-features.sh31
-rwxr-xr-xtools/testing/selftests/drivers/net/netdevsim/fib_notifications.sh6
-rwxr-xr-xtools/testing/selftests/drivers/net/netdevsim/macsec-offload.sh117
-rwxr-xr-xtools/testing/selftests/drivers/net/shaper.py461
-rw-r--r--tools/testing/selftests/filesystems/.gitignore1
-rw-r--r--tools/testing/selftests/filesystems/Makefile2
-rw-r--r--tools/testing/selftests/filesystems/binderfs/binderfs_test.c1
-rw-r--r--tools/testing/selftests/filesystems/file_stressor.c194
-rw-r--r--tools/testing/selftests/filesystems/overlayfs/.gitignore1
-rw-r--r--tools/testing/selftests/filesystems/overlayfs/Makefile2
-rw-r--r--tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c27
-rw-r--r--tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c217
-rw-r--r--tools/testing/selftests/filesystems/overlayfs/wrappers.h47
-rw-r--r--tools/testing/selftests/filesystems/statmount/statmount_test.c2
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/mount_options.tc101
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/test_ownership.tc16
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/fgraph-retval.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions25
-rw-r--r--tools/testing/selftests/hid/Makefile2
-rw-r--r--tools/testing/selftests/hid/hid_bpf.c77
-rw-r--r--tools/testing/selftests/hid/hid_common.h112
-rw-r--r--tools/testing/selftests/hid/hidraw.c36
-rw-r--r--tools/testing/selftests/iommu/Makefile1
-rw-r--r--tools/testing/selftests/iommu/iommufd.c606
-rw-r--r--tools/testing/selftests/iommu/iommufd_fail_nth.c54
-rw-r--r--tools/testing/selftests/iommu/iommufd_utils.h174
-rw-r--r--tools/testing/selftests/kvm/Makefile15
-rw-r--r--tools/testing/selftests/kvm/aarch64/debug-exceptions.c10
-rw-r--r--tools/testing/selftests/kvm/aarch64/mmio_abort.c159
-rw-r--r--tools/testing/selftests/kvm/aarch64/no-vgic-v3.c2
-rw-r--r--tools/testing/selftests/kvm/aarch64/page_fault_test.c4
-rw-r--r--tools/testing/selftests/kvm/aarch64/psci_test.c92
-rw-r--r--tools/testing/selftests/kvm/aarch64/set_id_regs.c99
-rw-r--r--tools/testing/selftests/kvm/aarch64/vpmu_counter_access.c12
-rw-r--r--tools/testing/selftests/kvm/guest_memfd_test.c2
-rw-r--r--tools/testing/selftests/kvm/hardware_disable_test.c1
-rw-r--r--tools/testing/selftests/kvm/include/aarch64/processor.h15
-rw-r--r--tools/testing/selftests/kvm/include/s390x/facility.h50
-rw-r--r--tools/testing/selftests/kvm/include/s390x/processor.h6
-rw-r--r--tools/testing/selftests/kvm/include/x86_64/processor.h5
-rw-r--r--tools/testing/selftests/kvm/lib/aarch64/processor.c6
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util.c10
-rw-r--r--tools/testing/selftests/kvm/lib/s390x/facility.c14
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/processor.c24
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/vmx.c2
-rw-r--r--tools/testing/selftests/kvm/memslot_perf_test.c2
-rw-r--r--tools/testing/selftests/kvm/riscv/get-reg-list.c16
-rw-r--r--tools/testing/selftests/kvm/s390x/cpumodel_subfuncs_test.c301
-rw-r--r--tools/testing/selftests/kvm/s390x/ucontrol_test.c322
-rw-r--r--tools/testing/selftests/kvm/x86_64/amx_test.c23
-rw-r--r--tools/testing/selftests/kvm/x86_64/cpuid_test.c69
-rw-r--r--tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c57
-rw-r--r--tools/testing/selftests/kvm/x86_64/debug_regs.c2
-rw-r--r--tools/testing/selftests/kvm/x86_64/feature_msrs_test.c113
-rw-r--r--tools/testing/selftests/kvm/x86_64/get_msr_index_features.c35
-rw-r--r--tools/testing/selftests/kvm/x86_64/platform_info_test.c2
-rw-r--r--tools/testing/selftests/kvm/x86_64/sev_smoke_test.c19
-rw-r--r--tools/testing/selftests/kvm/x86_64/state_test.c5
-rw-r--r--tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c23
-rw-r--r--tools/testing/selftests/kvm/x86_64/xcr0_cpuid_test.c11
-rw-r--r--tools/testing/selftests/livepatch/Makefile3
-rw-r--r--tools/testing/selftests/livepatch/functions.sh29
-rwxr-xr-xtools/testing/selftests/livepatch/test-callbacks.sh24
-rwxr-xr-xtools/testing/selftests/livepatch/test-ftrace.sh2
-rwxr-xr-xtools/testing/selftests/livepatch/test-kprobe.sh62
-rwxr-xr-xtools/testing/selftests/livepatch/test-livepatch.sh12
-rwxr-xr-xtools/testing/selftests/livepatch/test-state.sh8
-rwxr-xr-xtools/testing/selftests/livepatch/test-syscall.sh6
-rwxr-xr-xtools/testing/selftests/livepatch/test-sysfs.sh8
-rw-r--r--tools/testing/selftests/livepatch/test_modules/Makefile3
-rw-r--r--tools/testing/selftests/livepatch/test_modules/test_klp_kprobe.c38
-rw-r--r--tools/testing/selftests/mm/.gitignore4
-rw-r--r--tools/testing/selftests/mm/Makefile32
-rw-r--r--tools/testing/selftests/mm/guard-pages.c1243
-rw-r--r--tools/testing/selftests/mm/hugetlb_dio.c12
-rw-r--r--tools/testing/selftests/mm/hugetlb_fault_after_madv.c48
-rw-r--r--tools/testing/selftests/mm/page_frag/Makefile18
-rw-r--r--tools/testing/selftests/mm/page_frag/page_frag_test.c198
-rw-r--r--tools/testing/selftests/mm/pkey-arm64.h3
-rw-r--r--tools/testing/selftests/mm/pkey-helpers.h7
-rw-r--r--tools/testing/selftests/mm/pkey-x86.h2
-rw-r--r--tools/testing/selftests/mm/pkey_sighandler_tests.c115
-rwxr-xr-xtools/testing/selftests/mm/run_vmtests.sh18
-rwxr-xr-xtools/testing/selftests/mm/test_page_frag.sh175
-rw-r--r--tools/testing/selftests/mm/virtual_address_range.c4
-rw-r--r--tools/testing/selftests/module/Makefile12
-rw-r--r--tools/testing/selftests/module/config3
-rwxr-xr-xtools/testing/selftests/module/find_symbol.sh81
-rw-r--r--tools/testing/selftests/mount_setattr/mount_setattr_test.c2
-rw-r--r--tools/testing/selftests/net/.gitignore3
-rw-r--r--tools/testing/selftests/net/Makefile7
-rwxr-xr-xtools/testing/selftests/net/bpf_offload.py5
-rwxr-xr-xtools/testing/selftests/net/busy_poll_test.sh165
-rw-r--r--tools/testing/selftests/net/busy_poller.c346
-rwxr-xr-xtools/testing/selftests/net/drop_monitor_tests.sh2
-rwxr-xr-xtools/testing/selftests/net/fdb_notify.sh96
-rwxr-xr-xtools/testing/selftests/net/fib_tests.sh8
-rw-r--r--tools/testing/selftests/net/forwarding/Makefile3
-rw-r--r--tools/testing/selftests/net/forwarding/devlink_lib.sh2
-rw-r--r--tools/testing/selftests/net/forwarding/lib.sh200
-rwxr-xr-xtools/testing/selftests/net/forwarding/sch_ets.sh7
-rw-r--r--tools/testing/selftests/net/forwarding/sch_ets_core.sh81
-rw-r--r--tools/testing/selftests/net/forwarding/sch_ets_tests.sh14
-rwxr-xr-xtools/testing/selftests/net/forwarding/sch_red.sh103
-rw-r--r--tools/testing/selftests/net/forwarding/sch_tbf_core.sh91
-rw-r--r--tools/testing/selftests/net/forwarding/sch_tbf_etsprio.sh7
-rwxr-xr-xtools/testing/selftests/net/forwarding/sch_tbf_root.sh3
-rwxr-xr-xtools/testing/selftests/net/forwarding/tc_police.sh8
-rw-r--r--tools/testing/selftests/net/hsr/config1
-rw-r--r--tools/testing/selftests/net/hsr/hsr_common.sh4
-rwxr-xr-xtools/testing/selftests/net/hsr/hsr_ping.sh98
-rw-r--r--tools/testing/selftests/net/hsr/settings1
-rwxr-xr-xtools/testing/selftests/net/ioam6.sh1832
-rw-r--r--tools/testing/selftests/net/ioam6_parser.c1087
-rwxr-xr-xtools/testing/selftests/net/ipv6_route_update_soft_lockup.sh262
-rw-r--r--tools/testing/selftests/net/lib.sh226
-rw-r--r--tools/testing/selftests/net/lib/Makefile2
-rw-r--r--tools/testing/selftests/net/lib/csum.c12
-rw-r--r--tools/testing/selftests/net/lib/py/__init__.py1
-rw-r--r--tools/testing/selftests/net/lib/py/ynl.py5
-rw-r--r--tools/testing/selftests/net/lib/sh/defer.sh115
-rw-r--r--tools/testing/selftests/net/mptcp/Makefile2
-rw-r--r--tools/testing/selftests/net/ncdevmem.c570
-rw-r--r--tools/testing/selftests/net/netfilter/.gitignore1
-rw-r--r--tools/testing/selftests/net/netfilter/Makefile7
-rw-r--r--tools/testing/selftests/net/netfilter/conntrack_dump_flush.c6
-rwxr-xr-xtools/testing/selftests/net/netfilter/conntrack_dump_flush.sh3
-rwxr-xr-xtools/testing/selftests/net/netfilter/nft_queue.sh8
-rw-r--r--tools/testing/selftests/net/netlink-dumps.c239
-rwxr-xr-xtools/testing/selftests/net/pmtu.sh114
-rw-r--r--tools/testing/selftests/net/psock_fanout.c78
-rw-r--r--tools/testing/selftests/net/rds/Makefile5
-rwxr-xr-xtools/testing/selftests/net/rtnetlink.sh207
-rw-r--r--tools/testing/selftests/net/tcp_ao/lib/aolib.h1
-rw-r--r--tools/testing/selftests/net/tcp_ao/setsockopt-closed.c186
-rw-r--r--tools/testing/selftests/net/tls.c19
-rw-r--r--tools/testing/selftests/net/txtimestamp.c44
-rwxr-xr-xtools/testing/selftests/net/txtimestamp.sh12
-rwxr-xr-xtools/testing/selftests/net/veth.sh2
-rw-r--r--tools/testing/selftests/net/ynl.mk16
-rw-r--r--tools/testing/selftests/nolibc/Makefile4
-rw-r--r--tools/testing/selftests/pcie_bwctrl/Makefile2
-rwxr-xr-xtools/testing/selftests/pcie_bwctrl/set_pcie_cooling_state.sh122
-rwxr-xr-xtools/testing/selftests/pcie_bwctrl/set_pcie_speed.sh67
-rw-r--r--tools/testing/selftests/pidfd/pidfd_open_test.c82
-rw-r--r--tools/testing/selftests/powerpc/alignment/settings1
-rw-r--r--tools/testing/selftests/powerpc/cache_shape/settings1
-rw-r--r--tools/testing/selftests/powerpc/copyloops/settings1
-rw-r--r--tools/testing/selftests/powerpc/dexcr/settings1
-rw-r--r--tools/testing/selftests/powerpc/dscr/settings1
-rw-r--r--tools/testing/selftests/powerpc/lib/settings1
-rw-r--r--tools/testing/selftests/powerpc/math/settings1
-rw-r--r--tools/testing/selftests/powerpc/mce/settings1
-rw-r--r--tools/testing/selftests/powerpc/mm/settings1
-rw-r--r--tools/testing/selftests/powerpc/mm/stack_expansion_ldst.c2
-rw-r--r--tools/testing/selftests/powerpc/mm/subpage_prot.c4
-rw-r--r--tools/testing/selftests/powerpc/mm/tlbie_test.c10
-rw-r--r--tools/testing/selftests/powerpc/nx-gzip/settings1
-rw-r--r--tools/testing/selftests/powerpc/papr_attributes/settings1
-rw-r--r--tools/testing/selftests/powerpc/papr_sysparm/settings1
-rw-r--r--tools/testing/selftests/powerpc/papr_vpd/settings1
-rw-r--r--tools/testing/selftests/powerpc/pmu/count_stcx_fail.c3
-rw-r--r--tools/testing/selftests/powerpc/pmu/settings1
-rw-r--r--tools/testing/selftests/powerpc/primitives/settings1
-rw-r--r--tools/testing/selftests/powerpc/ptrace/settings1
-rw-r--r--tools/testing/selftests/powerpc/scripts/settings1
-rwxr-xr-xtools/testing/selftests/powerpc/security/mitigation-patching.sh8
-rw-r--r--tools/testing/selftests/powerpc/security/settings1
-rw-r--r--tools/testing/selftests/powerpc/signal/sigfuz.c2
-rw-r--r--tools/testing/selftests/powerpc/stringloops/settings1
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/settings1
-rw-r--r--tools/testing/selftests/powerpc/syscalls/settings1
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-force-tm.c2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-sigreturn-nt.c3
-rw-r--r--tools/testing/selftests/powerpc/vphn/settings1
-rw-r--r--tools/testing/selftests/ptp/testptp.c62
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run-batch.sh43
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh6
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFLIST1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-L10
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-L.boot3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE102
-rw-r--r--tools/testing/selftests/resctrl/cmt_test.c37
-rw-r--r--tools/testing/selftests/resctrl/fill_buf.c45
-rw-r--r--tools/testing/selftests/resctrl/mba_test.c54
-rw-r--r--tools/testing/selftests/resctrl/mbm_test.c37
-rw-r--r--tools/testing/selftests/resctrl/resctrl.h79
-rw-r--r--tools/testing/selftests/resctrl/resctrl_tests.c95
-rw-r--r--tools/testing/selftests/resctrl/resctrl_val.c447
-rw-r--r--tools/testing/selftests/resctrl/resctrlfs.c19
-rw-r--r--tools/testing/selftests/riscv/Makefile2
-rw-r--r--tools/testing/selftests/riscv/abi/.gitignore1
-rw-r--r--tools/testing/selftests/riscv/abi/Makefile10
-rw-r--r--tools/testing/selftests/riscv/abi/pointer_masking.c332
-rw-r--r--tools/testing/selftests/rtc/Makefile2
-rw-r--r--tools/testing/selftests/rtc/rtctest.c64
-rw-r--r--tools/testing/selftests/signal/.gitignore (renamed from tools/testing/selftests/sigaltstack/.gitignore)1
-rw-r--r--tools/testing/selftests/signal/Makefile (renamed from tools/testing/selftests/sigaltstack/Makefile)3
-rw-r--r--tools/testing/selftests/signal/current_stack_pointer.h (renamed from tools/testing/selftests/sigaltstack/current_stack_pointer.h)0
-rw-r--r--tools/testing/selftests/signal/mangle_uc_sigmask.c184
-rw-r--r--tools/testing/selftests/signal/sas.c (renamed from tools/testing/selftests/sigaltstack/sas.c)0
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/basic.json6
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/cgroup.json6
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/flow.json2
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/route.json2
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/u32.json24
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json98
-rw-r--r--tools/testing/selftests/timers/Makefile2
-rw-r--r--tools/testing/selftests/timers/adjtick.c6
-rw-r--r--tools/testing/selftests/timers/alarmtimer-suspend.c22
-rw-r--r--tools/testing/selftests/timers/inconsistency-check.c21
-rw-r--r--tools/testing/selftests/timers/leap-a-day.c2
-rw-r--r--tools/testing/selftests/timers/mqueue-lat.c2
-rw-r--r--tools/testing/selftests/timers/nanosleep.c21
-rw-r--r--tools/testing/selftests/timers/nsleep-lat.c22
-rw-r--r--tools/testing/selftests/timers/posix_timers.c15
-rw-r--r--tools/testing/selftests/timers/raw_skew.c4
-rw-r--r--tools/testing/selftests/timers/set-2038.c3
-rw-r--r--tools/testing/selftests/timers/set-timer-lat.c21
-rw-r--r--tools/testing/selftests/timers/valid-adjtimex.c4
-rw-r--r--tools/testing/selftests/vDSO/parse_vdso.c3
-rwxr-xr-xtools/testing/selftests/wireguard/netns.sh1
-rw-r--r--tools/testing/selftests/wireguard/qemu/debug.config1
-rw-r--r--tools/testing/shared/linux.c14
-rw-r--r--tools/testing/shared/shared.mk1
-rw-r--r--tools/testing/vma/vma.c2
-rw-r--r--tools/testing/vma/vma_internal.h115
-rw-r--r--tools/thermal/lib/Makefile2
-rw-r--r--tools/thermal/thermal-engine/thermal-engine.c105
-rw-r--r--tools/thermal/thermometer/thermometer.c7
-rw-r--r--tools/tracing/rtla/Makefile2
-rw-r--r--tools/tracing/rtla/Makefile.config10
-rw-r--r--tools/tracing/rtla/README.txt4
-rw-r--r--tools/tracing/rtla/sample/timerlat_load.py56
-rw-r--r--tools/tracing/rtla/src/osnoise_top.c2
-rw-r--r--tools/tracing/rtla/src/timerlat_hist.c64
-rw-r--r--tools/tracing/rtla/src/timerlat_top.c54
-rw-r--r--tools/tracing/rtla/src/utils.c186
-rw-r--r--tools/tracing/rtla/src/utils.h15
-rw-r--r--tools/verification/dot2/automata.py18
-rw-r--r--tools/verification/rv/src/in_kernel.c4
-rw-r--r--tools/verification/rv/src/trace.c2
-rw-r--r--tools/virtio/vringh_test.c2
-rw-r--r--virt/kvm/Kconfig4
-rw-r--r--virt/kvm/eventfd.c15
-rw-r--r--virt/kvm/guest_memfd.c28
-rw-r--r--virt/kvm/kvm_main.c842
-rw-r--r--virt/kvm/kvm_mm.h36
-rw-r--r--virt/kvm/pfncache.c20
-rw-r--r--virt/kvm/vfio.c16
12839 files changed, 474739 insertions, 305799 deletions
diff --git a/.clippy.toml b/.clippy.toml
new file mode 100644
index 000000000000..e4c4eef10b28
--- /dev/null
+++ b/.clippy.toml
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+check-private-items = true
+
+disallowed-macros = [
+ # The `clippy::dbg_macro` lint only works with `std::dbg!`, thus we simulate
+ # it here, see: https://github.com/rust-lang/rust-clippy/issues/11303.
+ { path = "kernel::dbg", reason = "the `dbg!` macro is intended as a debugging tool" },
+]
diff --git a/.get_maintainer.ignore b/.get_maintainer.ignore
index 7d1b30aae874..b458815f1d1b 100644
--- a/.get_maintainer.ignore
+++ b/.get_maintainer.ignore
@@ -3,3 +3,4 @@ Alan Cox <root@hraefn.swansea.linux.org.uk>
Christoph Hellwig <hch@lst.de>
Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Marc Gonzalez <marc.w.gonzalez@free.fr>
+Ralf Baechle <ralf@linux-mips.org>
diff --git a/.gitignore b/.gitignore
index 56972adb5031..6839cf84acda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -103,6 +103,7 @@ modules.order
# We don't want to ignore the following even if they are dot-files
#
!.clang-format
+!.clippy.toml
!.cocciconfig
!.editorconfig
!.get_maintainer.ignore
@@ -128,6 +129,7 @@ series
# ctags files
tags
+!tags/
TAGS
# cscope files
diff --git a/.mailmap b/.mailmap
index 5378f04b2566..5ff0e5d681e7 100644
--- a/.mailmap
+++ b/.mailmap
@@ -37,6 +37,7 @@ Alexei Avshalom Lazar <quic_ailizaro@quicinc.com> <ailizaro@codeaurora.org>
Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
+Alexey Klimov <alexey.klimov@linaro.org> <klimov.linux@gmail.com>
Alexey Makhalov <alexey.amakhalov@broadcom.com> <amakhalov@vmware.com>
Alex Elder <elder@kernel.org>
Alex Elder <elder@kernel.org> <aelder@sgi.com>
@@ -251,6 +252,8 @@ Guru Das Srinagesh <quic_gurus@quicinc.com> <gurus@codeaurora.org>
Gustavo Padovan <gustavo@las.ic.unicamp.br>
Gustavo Padovan <padovan@profusion.mobi>
Hanjun Guo <guohanjun@huawei.com> <hanjun.guo@linaro.org>
+Hans Verkuil <hverkuil@xs4all.nl> <hansverk@cisco.com>
+Hans Verkuil <hverkuil@xs4all.nl> <hverkuil-cisco@xs4all.nl>
Heiko Carstens <hca@linux.ibm.com> <h.carstens@de.ibm.com>
Heiko Carstens <hca@linux.ibm.com> <heiko.carstens@de.ibm.com>
Heiko Stuebner <heiko@sntech.de> <heiko.stuebner@bqreaders.com>
@@ -269,6 +272,7 @@ Jack Pham <quic_jackp@quicinc.com> <jackp@codeaurora.org>
Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@google.com>
Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk.kim@samsung.com>
Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@motorola.com>
+Jai Luthra <jai.luthra@linux.dev> <j-luthra@ti.com>
Jakub Kicinski <kuba@kernel.org> <jakub.kicinski@netronome.com>
James Bottomley <jejb@mulgrave.(none)>
James Bottomley <jejb@titanic.il.steeleye.com>
@@ -665,6 +669,7 @@ Tomeu Vizoso <tomeu@tomeuvizoso.net> <tomeu.vizoso@collabora.com>
Thomas Graf <tgraf@suug.ch>
Thomas Körper <socketcan@esd.eu> <thomas.koerper@esd.eu>
Thomas Pedersen <twp@codeaurora.org>
+Thorsten Blum <thorsten.blum@linux.dev> <thorsten.blum@toblux.com>
Tiezhu Yang <yangtiezhu@loongson.cn> <kernelpatch@126.com>
Tingwei Zhang <quic_tingwei@quicinc.com> <tingwei@codeaurora.org>
Tirupathi Reddy <quic_tirupath@quicinc.com> <tirupath@codeaurora.org>
@@ -729,6 +734,7 @@ Will Deacon <will@kernel.org> <will.deacon@arm.com>
Wolfram Sang <wsa@kernel.org> <w.sang@pengutronix.de>
Wolfram Sang <wsa@kernel.org> <wsa@the-dreams.de>
Yakir Yang <kuankuan.y@gmail.com> <ykk@rock-chips.com>
+Yanteng Si <si.yanteng@linux.dev> <siyanteng@loongson.cn>
Yusuke Goda <goda.yusuke@renesas.com>
Zack Rusin <zack.rusin@broadcom.com> <zackr@vmware.com>
Zhu Yanjun <zyjzyj2000@gmail.com> <yanjunz@nvidia.com>
diff --git a/CREDITS b/CREDITS
index 63f53feefa0a..b1777b53c63a 100644
--- a/CREDITS
+++ b/CREDITS
@@ -185,6 +185,11 @@ P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE C8 BA 9C FC 88 DE 32 C3
D: Linux/MIPS port
D: Linux/68k hacker
D: AX25 maintainer
+D: EDAC-CAVIUM OCTEON maintainer
+D: IOC3 ETHERNET DRIVER maintainer
+D: NETROM NETWORK LAYER maintainer
+D: ROSE NETWORK LAYER maintainer
+D: TURBOCHANNEL SUBSYSTEM maintainer
S: Hauptstrasse 19
S: 79837 St. Blasien
S: Germany
@@ -574,6 +579,9 @@ N: Zach Brown
E: zab@zabbo.net
D: maestro pci sound
+N: Zefan Li
+D: Contribution to control group stuff
+
N: David Brownell
D: Kernel engineer, mentor, and friend. Maintained USB EHCI and
D: gadget layers, SPI subsystem, GPIO subsystem, and more than a few
@@ -1204,6 +1212,10 @@ S: Dreisbachstrasse 24
S: D-57250 Netphen
S: Germany
+N: Florian Fainelli
+E: f.fainelli@gmail.com
+D: DSA
+
N: Rik Faith
E: faith@acm.org
D: Future Domain TMC-16x0 SCSI driver (author)
@@ -3791,6 +3803,10 @@ S: Department of Zoology, University of Washington
S: Seattle, WA 98195-1800
S: USA
+N: York Sun
+E: york.sun@nxp.com
+D: Freescale DDR EDAC
+
N: Eugene Surovegin
E: ebs@ebshome.net
W: https://kernel.ebshome.net/
diff --git a/Documentation/ABI/obsolete/sysfs-selinux-user b/Documentation/ABI/obsolete/sysfs-selinux-user
new file mode 100644
index 000000000000..8ab7557f283f
--- /dev/null
+++ b/Documentation/ABI/obsolete/sysfs-selinux-user
@@ -0,0 +1,12 @@
+What: /sys/fs/selinux/user
+Date: April 2005 (predates git)
+KernelVersion: 2.6.12-rc2 (predates git)
+Contact: selinux@vger.kernel.org
+Description:
+
+ The selinuxfs "user" node allows userspace to request a list
+ of security contexts that can be reached for a given SELinux
+ user from a given starting context. This was used by libselinux
+ when various login-style programs requested contexts for
+ users, but libselinux stopped using it in 2020.
+ Kernel support will be removed no sooner than Dec 2025.
diff --git a/Documentation/ABI/stable/sysfs-block b/Documentation/ABI/stable/sysfs-block
index cea8856f798d..0cceb2badc83 100644
--- a/Documentation/ABI/stable/sysfs-block
+++ b/Documentation/ABI/stable/sysfs-block
@@ -424,6 +424,13 @@ Description:
[RW] This file is used to control (on/off) the iostats
accounting of the disk.
+What: /sys/block/<disk>/queue/iostats_passthrough
+Date: October 2024
+Contact: linux-block@vger.kernel.org
+Description:
+ [RW] This file is used to control (on/off) the iostats
+ accounting of the disk for passthrough commands.
+
What: /sys/block/<disk>/queue/logical_block_size
Date: May 2009
@@ -594,6 +601,9 @@ Description:
[RW] Maximum number of kilobytes to read-ahead for filesystems
on this block device.
+ For MADV_HUGEPAGE, the readahead size may exceed this setting
+ since its granularity is based on the hugepage size.
+
What: /sys/block/<disk>/queue/rotational
Date: January 2009
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 4feb692c4c1d..b6720768d63d 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -342,6 +342,70 @@ Description: Specific uncompressed frame descriptors
support
========================= =====================================
+What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased
+Date: Sept 2024
+KernelVersion: 5.15
+Description: Framebased format descriptors
+
+What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name
+Date: Sept 2024
+KernelVersion: 5.15
+Description: Specific framebased format descriptors
+
+ ================== =======================================
+ bFormatIndex unique id for this format descriptor;
+ only defined after parent header is
+ linked into the streaming class;
+ read-only
+ bmaControls this format's data for bmaControls in
+ the streaming header
+ bmInterlaceFlags specifies interlace information,
+ read-only
+ bAspectRatioY the X dimension of the picture aspect
+ ratio, read-only
+ bAspectRatioX the Y dimension of the picture aspect
+ ratio, read-only
+ bDefaultFrameIndex optimum frame index for this stream
+ bBitsPerPixel number of bits per pixel used to
+ specify color in the decoded video
+ frame
+ guidFormat globally unique id used to identify
+ stream-encoding format
+ ================== =======================================
+
+What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name/name
+Date: Sept 2024
+KernelVersion: 5.15
+Description: Specific framebased frame descriptors
+
+ ========================= =====================================
+ bFrameIndex unique id for this framedescriptor;
+ only defined after parent format is
+ linked into the streaming header;
+ read-only
+ dwFrameInterval indicates how frame interval can be
+ programmed; a number of values
+ separated by newline can be specified
+ dwDefaultFrameInterval the frame interval the device would
+ like to use as default
+ dwBytesPerLine Specifies the number of bytes per line
+ of video for packed fixed frame size
+ formats, allowing the receiver to
+ perform stride alignment of the video.
+ If the bVariableSize value (above) is
+ TRUE (1), or if the format does not
+ permit such alignment, this value shall
+ be set to zero (0).
+ dwMaxBitRate the maximum bit rate at the shortest
+ frame interval in bps
+ dwMinBitRate the minimum bit rate at the longest
+ frame interval in bps
+ wHeight height of decoded bitmap frame in px
+ wWidth width of decoded bitmam frame in px
+ bmCapabilities still image support, fixed frame-rate
+ support
+ ========================= =====================================
+
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/header
Date: Dec 2014
KernelVersion: 4.0
diff --git a/Documentation/ABI/testing/debugfs-hisi-hpre b/Documentation/ABI/testing/debugfs-hisi-hpre
index d4e16ef9ac9a..29fb7d5ffc69 100644
--- a/Documentation/ABI/testing/debugfs-hisi-hpre
+++ b/Documentation/ABI/testing/debugfs-hisi-hpre
@@ -184,3 +184,10 @@ Date: Apr 2020
Contact: linux-crypto@vger.kernel.org
Description: Dump the total number of time out requests.
Available for both PF and VF, and take no other effect on HPRE.
+
+What: /sys/kernel/debug/hisi_hpre/<bdf>/cap_regs
+Date: Oct 2024
+Contact: linux-crypto@vger.kernel.org
+Description: Dump the values of the qm and hpre capability bit registers and
+ support the query of device specifications to facilitate fault locating.
+ Available for both PF and VF, and take no other effect on HPRE.
diff --git a/Documentation/ABI/testing/debugfs-hisi-migration b/Documentation/ABI/testing/debugfs-hisi-migration
new file mode 100644
index 000000000000..2c01b2d387dd
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-hisi-migration
@@ -0,0 +1,25 @@
+What: /sys/kernel/debug/vfio/<device>/migration/hisi_acc/dev_data
+Date: Jan 2025
+KernelVersion: 6.13
+Contact: Longfang Liu <liulongfang@huawei.com>
+Description: Read the configuration data and some status data
+ required for device live migration. These data include device
+ status data, queue configuration data, some task configuration
+ data and device attribute data. The output format of the data
+ is defined by the live migration driver.
+
+What: /sys/kernel/debug/vfio/<device>/migration/hisi_acc/migf_data
+Date: Jan 2025
+KernelVersion: 6.13
+Contact: Longfang Liu <liulongfang@huawei.com>
+Description: Read the data from the last completed live migration.
+ This data includes the same device status data as in "dev_data".
+ The migf_data is the dev_data that is migrated.
+
+What: /sys/kernel/debug/vfio/<device>/migration/hisi_acc/cmd_state
+Date: Jan 2025
+KernelVersion: 6.13
+Contact: Longfang Liu <liulongfang@huawei.com>
+Description: Used to obtain the device command sending and receiving
+ channel status. Returns failure or success logs based on the
+ results.
diff --git a/Documentation/ABI/testing/debugfs-hisi-sec b/Documentation/ABI/testing/debugfs-hisi-sec
index 6c6c9a6e150a..82bf4a0dc7f7 100644
--- a/Documentation/ABI/testing/debugfs-hisi-sec
+++ b/Documentation/ABI/testing/debugfs-hisi-sec
@@ -157,3 +157,10 @@ Contact: linux-crypto@vger.kernel.org
Description: Dump the total number of completed but marked error requests
to be received.
Available for both PF and VF, and take no other effect on SEC.
+
+What: /sys/kernel/debug/hisi_sec2/<bdf>/cap_regs
+Date: Oct 2024
+Contact: linux-crypto@vger.kernel.org
+Description: Dump the values of the qm and sec capability bit registers and
+ support the query of device specifications to facilitate fault locating.
+ Available for both PF and VF, and take no other effect on SEC.
diff --git a/Documentation/ABI/testing/debugfs-hisi-zip b/Documentation/ABI/testing/debugfs-hisi-zip
index a22dd6942219..0abd65d27e9b 100644
--- a/Documentation/ABI/testing/debugfs-hisi-zip
+++ b/Documentation/ABI/testing/debugfs-hisi-zip
@@ -158,3 +158,10 @@ Contact: linux-crypto@vger.kernel.org
Description: Dump the total number of BD type error requests
to be received.
Available for both PF and VF, and take no other effect on ZIP.
+
+What: /sys/kernel/debug/hisi_zip/<bdf>/cap_regs
+Date: Oct 2024
+Contact: linux-crypto@vger.kernel.org
+Description: Dump the values of the qm and zip capability bit registers and
+ support the query of device specifications to facilitate fault locating.
+ Available for both PF and VF, and take no other effect on ZIP.
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu b/Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu
new file mode 100644
index 000000000000..a116aee9709a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu
@@ -0,0 +1,25 @@
+What: /sys/bus/event_source/devices/vpa_pmu/format
+Date: November 2024
+Contact: Linux on PowerPC Developer List <linuxppc-dev@lists.ozlabs.org>
+Description: Read-only. Attribute group to describe the magic bits
+ that go into perf_event_attr.config for a particular pmu.
+ (See ABI/testing/sysfs-bus-event_source-devices-format).
+
+ Each attribute under this group defines a bit range of the
+ perf_event_attr.config. Supported attribute are listed
+ below::
+
+ event = "config:0-31" - event ID
+
+ For example::
+
+ l1_to_l2_lat = "event=0x1"
+
+What: /sys/bus/event_source/devices/vpa_pmu/events
+Date: November 2024
+Contact: Linux on PowerPC Developer List <linuxppc-dev@lists.ozlabs.org>
+Description: Read-only. Attribute group to describe performance monitoring
+ events for the Virtual Processor Area events. Each attribute
+ in this group describes a single performance monitoring event
+ supported by vpa_pmu. The name of the file is the name of
+ the event (See ABI/testing/sysfs-bus-event_source-devices-events).
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 89943c2d54e8..f83bd6829285 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -2268,6 +2268,30 @@ Description:
An example format is 16-bytes, 2-digits-per-byte, HEX-string
representing the sensor unique ID number.
+What: /sys/bus/iio/devices/iio:deviceX/filter_type_available
+What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_filter_mode_available
+KernelVersion: 6.1
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns a list with the possible filter modes. Options
+ for the attribute:
+
+ * "sinc3" - The digital sinc3 filter. Moderate 1st
+ conversion time. Good noise performance.
+ * "sinc4" - Sinc 4. Excellent noise performance. Long
+ 1st conversion time.
+ * "sinc5" - The digital sinc5 filter. Excellent noise
+ performance
+ * "sinc4+sinc1" - Sinc4 + averaging by 8. Low 1st conversion
+ time.
+ * "sinc3+rej60" - Sinc3 + 60Hz rejection.
+ * "sinc3+sinc1" - Sinc3 + averaging by 8. Low 1st conversion
+ time.
+ * "sinc3+pf1" - Sinc3 + device specific Post Filter 1.
+ * "sinc3+pf2" - Sinc3 + device specific Post Filter 2.
+ * "sinc3+pf3" - Sinc3 + device specific Post Filter 3.
+ * "sinc3+pf4" - Sinc3 + device specific Post Filter 4.
+
What: /sys/.../events/in_proximity_thresh_either_runningperiod
KernelVersion: 6.6
Contact: linux-iio@vger.kernel.org
@@ -2339,3 +2363,11 @@ KernelVersion: 6.10
Contact: linux-iio@vger.kernel.org
Description:
The value of current sense resistor in Ohms.
+
+What: /sys/.../iio:deviceX/in_attention_input
+KernelVersion: 6.13
+Contact: linux-iio@vger.kernel.org
+Description:
+ Value representing the user's attention to the system expressed
+ in units as percentage. This usually means if the user is
+ looking at the screen or not.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130 b/Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
deleted file mode 100644
index f24ed6687e90..000000000000
--- a/Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
+++ /dev/null
@@ -1,46 +0,0 @@
-What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_filter_mode_available
-KernelVersion: 6.2
-Contact: linux-iio@vger.kernel.org
-Description:
- Reading returns a list with the possible filter modes.
-
- * "sinc4" - Sinc 4. Excellent noise performance. Long
- 1st conversion time. No natural 50/60Hz rejection.
-
- * "sinc4+sinc1" - Sinc4 + averaging by 8. Low 1st conversion
- time.
-
- * "sinc3" - Sinc3. Moderate 1st conversion time.
- Good noise performance.
-
- * "sinc3+rej60" - Sinc3 + 60Hz rejection. At a sampling
- frequency of 50Hz, achieves simultaneous 50Hz and 60Hz
- rejection.
-
- * "sinc3+sinc1" - Sinc3 + averaging by 8. Low 1st conversion
- time. Best used with a sampling frequency of at least
- 216.19Hz.
-
- * "sinc3+pf1" - Sinc3 + Post Filter 1. 53dB rejection @
- 50Hz, 58dB rejection @ 60Hz.
-
- * "sinc3+pf2" - Sinc3 + Post Filter 2. 70dB rejection @
- 50Hz, 70dB rejection @ 60Hz.
-
- * "sinc3+pf3" - Sinc3 + Post Filter 3. 99dB rejection @
- 50Hz, 103dB rejection @ 60Hz.
-
- * "sinc3+pf4" - Sinc3 + Post Filter 4. 103dB rejection @
- 50Hz, 109dB rejection @ 60Hz.
-
-What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_filter_mode
-KernelVersion: 6.2
-Contact: linux-iio@vger.kernel.org
-Description:
- Set the filter mode of the differential channel. When the filter
- mode changes, the in_voltageY-voltageZ_sampling_frequency and
- in_voltageY-voltageZ_sampling_frequency_available attributes
- might also change to accommodate the new filter mode.
- If the current sampling frequency is out of range for the new
- filter mode, the sampling frequency will be changed to the
- closest valid one.
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 7f63c7e97773..5da6a14dc326 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -163,6 +163,17 @@ Description:
will be present in sysfs. Writing 1 to this file
will perform reset.
+What: /sys/bus/pci/devices/.../reset_subordinate
+Date: October 2024
+Contact: linux-pci@vger.kernel.org
+Description:
+ This is visible only for bridge devices. If you want to reset
+ all devices attached through the subordinate bus of a specific
+ bridge device, writing 1 to this will try to do it. This will
+ affect all devices attached to the system through this bridge
+ similiar to writing 1 to their individual "reset" file, so use
+ with caution.
+
What: /sys/bus/pci/devices/.../vpd
Date: February 2008
Contact: Ben Hutchings <bwh@kernel.org>
diff --git a/Documentation/ABI/testing/sysfs-bus-platform-drivers-amd_x3d_vcache b/Documentation/ABI/testing/sysfs-bus-platform-drivers-amd_x3d_vcache
new file mode 100644
index 000000000000..ac3431736f5c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-platform-drivers-amd_x3d_vcache
@@ -0,0 +1,12 @@
+What: /sys/bus/platform/drivers/amd_x3d_vcache/AMDI0101:00/amd_x3d_mode
+Date: November 2024
+KernelVersion: 6.13
+Contact: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+Description: (RW) AMD 3D V-Cache optimizer allows users to switch CPU core
+ rankings dynamically.
+
+ This file switches between these two modes:
+ - "frequency" cores within the faster CCD are prioritized before
+ those in the slower CCD.
+ - "cache" cores within the larger L3 CCD are prioritized before
+ those in the smaller L3 CCD.
diff --git a/Documentation/ABI/testing/sysfs-class-firmware-attributes b/Documentation/ABI/testing/sysfs-class-firmware-attributes
index 9c82c7b42ff8..2713efa509b4 100644
--- a/Documentation/ABI/testing/sysfs-class-firmware-attributes
+++ b/Documentation/ABI/testing/sysfs-class-firmware-attributes
@@ -193,7 +193,7 @@ Description:
mechanism:
The means of authentication. This attribute is mandatory.
- Only supported type currently is "password".
+ Supported types are "password" or "certificate".
max_password_length:
A file that can be read to obtain the
@@ -303,6 +303,7 @@ Description:
being configured allowing anyone to make changes.
After any of these operations the system must reboot for the changes to
take effect.
+ Admin and System certificates are supported from 2025 systems onward.
certificate_thumbprint:
Read only attribute used to display the MD5, SHA1 and SHA256 thumbprints
diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec
index 281b995beb05..38e101c17a00 100644
--- a/Documentation/ABI/testing/sysfs-class-typec
+++ b/Documentation/ABI/testing/sysfs-class-typec
@@ -149,6 +149,19 @@ Description:
advertise to the partner. The currently used capabilities are in
brackets. Selection happens by writing to the file.
+What: /sys/class/typec/<port>/usb_capability
+Date: November 2024
+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description: Lists the supported USB Modes. The default USB mode that is used
+ next time with the Enter_USB Message is in brackets. The default
+ mode can be changed by writing to the file when supported by the
+ driver.
+
+ Valid values:
+ - usb2 (USB 2.0)
+ - usb3 (USB 3.2)
+ - usb4 (USB4)
+
USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)
What: /sys/class/typec/<port>-partner/accessory_mode
@@ -220,6 +233,20 @@ Description:
directory exists, it will have an attribute file for every VDO
in Discover Identity command result.
+What: /sys/class/typec/<port>-partner/usb_mode
+Date: November 2024
+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description: The USB Modes that the partner device supports. The active mode
+ is displayed in brackets. The active USB mode can be changed by
+ writing to this file when the port driver is able to send Data
+ Reset Message to the partner. That requires USB Power Delivery
+ contract between the partner and the port.
+
+ Valid values:
+ - usb2 (USB 2.0)
+ - usb3 (USB 3.2)
+ - usb4 (USB4)
+
USB Type-C cable devices (eg. /sys/class/typec/port0-cable/)
Note: Electronically Marked Cables will have a device also for one cable plug
diff --git a/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs b/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs
index 1666340820f7..d1b3a95a5518 100644
--- a/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs
+++ b/Documentation/ABI/testing/sysfs-devices-platform-kunpeng_hccs
@@ -79,3 +79,48 @@ Description:
indicates a lane.
crc_err_cnt: (RO) CRC err count on this port.
============= ==== =============================================
+
+What: /sys/devices/platform/HISI04Bx:00/used_types
+Date: August 2024
+KernelVersion: 6.12
+Contact: Huisong Li <lihuisong@huawei.com>
+Description:
+ This interface is used to show all HCCS types used on the
+ platform, like, HCCS-v1, HCCS-v2 and so on.
+
+What: /sys/devices/platform/HISI04Bx:00/available_inc_dec_lane_types
+What: /sys/devices/platform/HISI04Bx:00/dec_lane_of_type
+What: /sys/devices/platform/HISI04Bx:00/inc_lane_of_type
+Date: August 2024
+KernelVersion: 6.12
+Contact: Huisong Li <lihuisong@huawei.com>
+Description:
+ These interfaces under /sys/devices/platform/HISI04Bx/ are
+ used to support the low power consumption feature of some
+ HCCS types by changing the number of lanes used. The interfaces
+ changing the number of lanes used are 'dec_lane_of_type' and
+ 'inc_lane_of_type' which require root privileges. These
+ interfaces aren't exposed if no HCCS type on platform support
+ this feature. Please note that decreasing lane number is only
+ allowed if all the specified HCCS ports are not busy.
+
+ The low power consumption interfaces are as follows:
+
+ ============================= ==== ================================
+ available_inc_dec_lane_types: (RO) available HCCS types (string) to
+ increase and decrease the number
+ of lane used, e.g. HCCS-v2.
+ dec_lane_of_type: (WO) input HCCS type supported
+ decreasing lane to decrease the
+ used lane number of all specified
+ HCCS type ports on platform to
+ the minimum.
+ You can query the 'cur_lane_num'
+ to get the minimum lane number
+ after executing successfully.
+ inc_lane_of_type: (WO) input HCCS type supported
+ increasing lane to increase the
+ used lane number of all specified
+ HCCS type ports on platform to
+ the full lane state.
+ ============================= ==== ================================
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-corsair-void b/Documentation/ABI/testing/sysfs-driver-hid-corsair-void
new file mode 100644
index 000000000000..83fa625c0025
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-corsair-void
@@ -0,0 +1,38 @@
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/fw_version_headset
+Date: January 2024
+KernelVersion: 6.13
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) The firmware version of the headset
+ * Returns -ENODATA if no version was reported
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/fw_version_receiver
+Date: January 2024
+KernelVersion: 6.13
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) The firmware version of the receiver
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/microphone_up
+Date: July 2023
+KernelVersion: 6.13
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) Get the physical position of the microphone
+ * 1 -> Microphone up
+ * 0 -> Microphone down
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/send_alert
+Date: July 2023
+KernelVersion: 6.13
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (W) Play a built-in notification from the headset (0 / 1)
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/set_sidetone
+Date: December 2023
+KernelVersion: 6.13
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (W) Set the sidetone volume (0 - sidetone_max)
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/sidetone_max
+Date: July 2024
+KernelVersion: 6.13
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) Report the maximum sidetone volume
diff --git a/Documentation/ABI/testing/sysfs-driver-spi-intel b/Documentation/ABI/testing/sysfs-driver-spi-intel
new file mode 100644
index 000000000000..d7c9139ddbf3
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-spi-intel
@@ -0,0 +1,20 @@
+What: /sys/devices/.../intel_spi_protected
+Date: Feb 2025
+KernelVersion: 6.13
+Contact: Alexander Usyskin <alexander.usyskin@intel.com>
+Description: This attribute allows the userspace to check if the
+ Intel SPI flash controller is write protected from the host.
+
+What: /sys/devices/.../intel_spi_locked
+Date: Feb 2025
+KernelVersion: 6.13
+Contact: Alexander Usyskin <alexander.usyskin@intel.com>
+Description: This attribute allows the user space to check if the
+ Intel SPI flash controller locks supported opcodes.
+
+What: /sys/devices/.../intel_spi_bios_locked
+Date: Feb 2025
+KernelVersion: 6.13
+Contact: Alexander Usyskin <alexander.usyskin@intel.com>
+Description: This attribute allows the user space to check if the
+ Intel SPI flash controller BIOS region is locked for writes.
diff --git a/Documentation/ABI/testing/sysfs-fs-erofs b/Documentation/ABI/testing/sysfs-fs-erofs
index 284224d1b56f..b134146d735b 100644
--- a/Documentation/ABI/testing/sysfs-fs-erofs
+++ b/Documentation/ABI/testing/sysfs-fs-erofs
@@ -16,3 +16,14 @@ Description: Control strategy of sync decompression:
readahead on atomic contexts only.
- 1 (force on): enable for readpage and readahead.
- 2 (force off): disable for all situations.
+
+What: /sys/fs/erofs/<disk>/drop_caches
+Date: November 2024
+Contact: "Guo Chunhai" <guochunhai@vivo.com>
+Description: Writing to this will drop compression-related caches,
+ currently used to drop in-memory pclusters and cached
+ compressed folios:
+
+ - 1 : invalidate cached compressed folios
+ - 2 : drop in-memory pclusters
+ - 3 : drop in-memory pclusters and cached compressed folios
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index fdedf1ea944b..3e1630c70d8a 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -311,10 +311,13 @@ Description: Do background GC aggressively when set. Set to 0 by default.
GC approach and turns SSR mode on.
gc urgent low(2): lowers the bar of checking I/O idling in
order to process outstanding discard commands and GC a
- little bit aggressively. uses cost benefit GC approach.
+ little bit aggressively. always uses cost benefit GC approach,
+ and will override age-threshold GC approach if ATGC is enabled
+ at the same time.
gc urgent mid(3): does GC forcibly in a period of given
gc_urgent_sleep_time and executes a mid level of I/O idling check.
- uses cost benefit GC approach.
+ always uses cost benefit GC approach, and will override
+ age-threshold GC approach if ATGC is enabled at the same time.
What: /sys/fs/f2fs/<disk>/gc_urgent_sleep_time
Date: August 2017
@@ -819,3 +822,9 @@ Description: It controls the valid block ratio threshold not to trigger excessiv
for zoned deivces. The initial value of it is 95(%). F2FS will stop the
background GC thread from intiating GC for sections having valid blocks
exceeding the ratio.
+
+What: /sys/fs/f2fs/<disk>/max_read_extent_count
+Date: November 2024
+Contact: "Chao Yu" <chao@kernel.org>
+Description: It controls max read extent count for per-inode, the value of threshold
+ is 10240 by default.
diff --git a/Documentation/PCI/endpoint/pci-endpoint.rst b/Documentation/PCI/endpoint/pci-endpoint.rst
index 21507e3cc238..35f82f2d45f5 100644
--- a/Documentation/PCI/endpoint/pci-endpoint.rst
+++ b/Documentation/PCI/endpoint/pci-endpoint.rst
@@ -117,6 +117,35 @@ by the PCI endpoint function driver.
The PCI endpoint function driver should use pci_epc_mem_free_addr() to
free the memory space allocated using pci_epc_mem_alloc_addr().
+* pci_epc_map_addr()
+
+ A PCI endpoint function driver should use pci_epc_map_addr() to map to a RC
+ PCI address the CPU address of local memory obtained with
+ pci_epc_mem_alloc_addr().
+
+* pci_epc_unmap_addr()
+
+ A PCI endpoint function driver should use pci_epc_unmap_addr() to unmap the
+ CPU address of local memory mapped to a RC address with pci_epc_map_addr().
+
+* pci_epc_mem_map()
+
+ A PCI endpoint controller may impose constraints on the RC PCI addresses that
+ can be mapped. The function pci_epc_mem_map() allows endpoint function
+ drivers to allocate and map controller memory while handling such
+ constraints. This function will determine the size of the memory that must be
+ allocated with pci_epc_mem_alloc_addr() for successfully mapping a RC PCI
+ address range. This function will also indicate the size of the PCI address
+ range that was actually mapped, which can be less than the requested size, as
+ well as the offset into the allocated memory to use for accessing the mapped
+ RC PCI address range.
+
+* pci_epc_mem_unmap()
+
+ A PCI endpoint function driver can use pci_epc_mem_unmap() to unmap and free
+ controller memory that was allocated and mapped using pci_epc_mem_map().
+
+
Other EPC APIs
~~~~~~~~~~~~~~
diff --git a/Documentation/PCI/index.rst b/Documentation/PCI/index.rst
index e73f84aebde3..5e7c4e6e726b 100644
--- a/Documentation/PCI/index.rst
+++ b/Documentation/PCI/index.rst
@@ -18,3 +18,4 @@ PCI Bus Subsystem
pcieaer-howto
endpoint/index
boot-interrupts
+ tph
diff --git a/Documentation/PCI/pciebus-howto.rst b/Documentation/PCI/pciebus-howto.rst
index f344452651e1..375d9ce171f6 100644
--- a/Documentation/PCI/pciebus-howto.rst
+++ b/Documentation/PCI/pciebus-howto.rst
@@ -217,8 +217,12 @@ capability structure except the PCI Express capability structure,
that is shared between many drivers including the service drivers.
RMW Capability accessors (pcie_capability_clear_and_set_word(),
pcie_capability_set_word(), and pcie_capability_clear_word()) protect
-a selected set of PCI Express Capability Registers (Link Control
-Register and Root Control Register). Any change to those registers
-should be performed using RMW accessors to avoid problems due to
-concurrent updates. For the up-to-date list of protected registers,
-see pcie_capability_clear_and_set_word().
+a selected set of PCI Express Capability Registers:
+
+* Link Control Register
+* Root Control Register
+* Link Control 2 Register
+
+Any change to those registers should be performed using RMW accessors to
+avoid problems due to concurrent updates. For the up-to-date list of
+protected registers, see pcie_capability_clear_and_set_word().
diff --git a/Documentation/PCI/tph.rst b/Documentation/PCI/tph.rst
new file mode 100644
index 000000000000..e8993be64fd6
--- /dev/null
+++ b/Documentation/PCI/tph.rst
@@ -0,0 +1,132 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+
+===========
+TPH Support
+===========
+
+:Copyright: 2024 Advanced Micro Devices, Inc.
+:Authors: - Eric van Tassell <eric.vantassell@amd.com>
+ - Wei Huang <wei.huang2@amd.com>
+
+
+Overview
+========
+
+TPH (TLP Processing Hints) is a PCIe feature that allows endpoint devices
+to provide optimization hints for requests that target memory space.
+These hints, in a format called Steering Tags (STs), are embedded in the
+requester's TLP headers, enabling the system hardware, such as the Root
+Complex, to better manage platform resources for these requests.
+
+For example, on platforms with TPH-based direct data cache injection
+support, an endpoint device can include appropriate STs in its DMA
+traffic to specify which cache the data should be written to. This allows
+the CPU core to have a higher probability of getting data from cache,
+potentially improving performance and reducing latency in data
+processing.
+
+
+How to Use TPH
+==============
+
+TPH is presented as an optional extended capability in PCIe. The Linux
+kernel handles TPH discovery during boot, but it is up to the device
+driver to request TPH enablement if it is to be utilized. Once enabled,
+the driver uses the provided API to obtain the Steering Tag for the
+target memory and to program the ST into the device's ST table.
+
+Enable TPH support in Linux
+---------------------------
+
+To support TPH, the kernel must be built with the CONFIG_PCIE_TPH option
+enabled.
+
+Manage TPH
+----------
+
+To enable TPH for a device, use the following function::
+
+ int pcie_enable_tph(struct pci_dev *pdev, int mode);
+
+This function enables TPH support for device with a specific ST mode.
+Current supported modes include:
+
+ * PCI_TPH_ST_NS_MODE - NO ST Mode
+ * PCI_TPH_ST_IV_MODE - Interrupt Vector Mode
+ * PCI_TPH_ST_DS_MODE - Device Specific Mode
+
+`pcie_enable_tph()` checks whether the requested mode is actually
+supported by the device before enabling. The device driver can figure out
+which TPH mode is supported and can be properly enabled based on the
+return value of `pcie_enable_tph()`.
+
+To disable TPH, use the following function::
+
+ void pcie_disable_tph(struct pci_dev *pdev);
+
+Manage ST
+---------
+
+Steering Tags are platform specific. PCIe spec does not specify where STs
+are from. Instead PCI Firmware Specification defines an ACPI _DSM method
+(see the `Revised _DSM for Cache Locality TPH Features ECN
+<https://members.pcisig.com/wg/PCI-SIG/document/15470>`_) for retrieving
+STs for a target memory of various properties. This method is what is
+supported in this implementation.
+
+To retrieve a Steering Tag for a target memory associated with a specific
+CPU, use the following function::
+
+ int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
+ unsigned int cpu_uid, u16 *tag);
+
+The `type` argument is used to specify the memory type, either volatile
+or persistent, of the target memory. The `cpu_uid` argument specifies the
+CPU where the memory is associated to.
+
+After the ST value is retrieved, the device driver can use the following
+function to write the ST into the device::
+
+ int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
+ u16 tag);
+
+The `index` argument is the ST table entry index the ST tag will be
+written into. `pcie_tph_set_st_entry()` will figure out the proper
+location of ST table, either in the MSI-X table or in the TPH Extended
+Capability space, and write the Steering Tag into the ST entry pointed by
+the `index` argument.
+
+It is completely up to the driver to decide how to use these TPH
+functions. For example a network device driver can use the TPH APIs above
+to update the Steering Tag when interrupt affinity of a RX/TX queue has
+been changed. Here is a sample code for IRQ affinity notifier:
+
+.. code-block:: c
+
+ static void irq_affinity_notified(struct irq_affinity_notify *notify,
+ const cpumask_t *mask)
+ {
+ struct drv_irq *irq;
+ unsigned int cpu_id;
+ u16 tag;
+
+ irq = container_of(notify, struct drv_irq, affinity_notify);
+ cpumask_copy(irq->cpu_mask, mask);
+
+ /* Pick a right CPU as the target - here is just an example */
+ cpu_id = cpumask_first(irq->cpu_mask);
+
+ if (pcie_tph_get_cpu_st(irq->pdev, TPH_MEM_TYPE_VM, cpu_id,
+ &tag))
+ return;
+
+ if (pcie_tph_set_st_entry(irq->pdev, irq->msix_nr, tag))
+ return;
+ }
+
+Disable TPH system-wide
+-----------------------
+
+There is a kernel command line option available to control TPH feature:
+ * "notph": TPH will be disabled for all endpoint devices.
diff --git a/Documentation/RCU/stallwarn.rst b/Documentation/RCU/stallwarn.rst
index ca7b7cd806a1..30080ff6f406 100644
--- a/Documentation/RCU/stallwarn.rst
+++ b/Documentation/RCU/stallwarn.rst
@@ -249,7 +249,7 @@ ticks this GP)" indicates that this CPU has not taken any scheduling-clock
interrupts during the current stalled grace period.
The "idle=" portion of the message prints the dyntick-idle state.
-The hex number before the first "/" is the low-order 12 bits of the
+The hex number before the first "/" is the low-order 16 bits of the
dynticks counter, which will have an even-numbered value if the CPU
is in dyntick-idle mode and an odd-numbered value otherwise. The hex
number between the two "/"s is the value of the nesting, which will be
diff --git a/Documentation/admin-guide/LSM/apparmor.rst b/Documentation/admin-guide/LSM/apparmor.rst
index 6cf81bbd7ce8..47939ee89d74 100644
--- a/Documentation/admin-guide/LSM/apparmor.rst
+++ b/Documentation/admin-guide/LSM/apparmor.rst
@@ -18,8 +18,11 @@ set ``CONFIG_SECURITY_APPARMOR=y``
If AppArmor should be selected as the default security module then set::
- CONFIG_DEFAULT_SECURITY="apparmor"
- CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
+ CONFIG_DEFAULT_SECURITY_APPARMOR=y
+
+The CONFIG_LSM parameter manages the order and selection of LSMs.
+Specify apparmor as the first "major" module (e.g. AppArmor, SELinux, Smack)
+in the list.
Build the kernel
diff --git a/Documentation/admin-guide/blockdev/zram.rst b/Documentation/admin-guide/blockdev/zram.rst
index 678d70d6e1c3..714a5171bfc0 100644
--- a/Documentation/admin-guide/blockdev/zram.rst
+++ b/Documentation/admin-guide/blockdev/zram.rst
@@ -47,6 +47,8 @@ The list of possible return codes:
-ENOMEM zram was not able to allocate enough memory to fulfil your
needs.
-EINVAL invalid input has been provided.
+-EAGAIN re-try operation later (e.g. when attempting to run recompress
+ and writeback simultaneously).
======== =============================================================
If you use 'echo', the returned value is set by the 'echo' utility,
diff --git a/Documentation/admin-guide/bug-bisect.rst b/Documentation/admin-guide/bug-bisect.rst
index 585630d14581..f4f867cabb17 100644
--- a/Documentation/admin-guide/bug-bisect.rst
+++ b/Documentation/admin-guide/bug-bisect.rst
@@ -108,6 +108,27 @@ a fully reliable and straight-forward way to reproduce the regression, too.*
With that the process is complete. Now report the regression as described by
Documentation/admin-guide/reporting-issues.rst.
+Bisecting linux-next
+--------------------
+
+If you face a problem only happening in linux-next, bisect between the
+linux-next branches 'stable' and 'master'. The following commands will start
+the process for a linux-next tree you added as a remote called 'next'::
+
+ git bisect start
+ git bisect good next/stable
+ git bisect bad next/master
+
+The 'stable' branch refers to the state of linux-mainline that the current
+linux-next release (found in the 'master' branch) is based on -- the former
+thus should be free of any problems that show up in -next, but not in Linus'
+tree.
+
+This will bisect across a wide range of changes, some of which you might have
+used in earlier linux-next releases without problems. Sadly there is no simple
+way to avoid checking them: bisecting from one linux-next release to a later
+one (say between 'next-20241020' and 'next-20241021') is impossible, as they
+share no common history.
Additional reading material
---------------------------
diff --git a/Documentation/admin-guide/cgroup-v1/memory.rst b/Documentation/admin-guide/cgroup-v1/memory.rst
index 270501db9f4e..286d16fc22eb 100644
--- a/Documentation/admin-guide/cgroup-v1/memory.rst
+++ b/Documentation/admin-guide/cgroup-v1/memory.rst
@@ -90,9 +90,7 @@ Brief summary of control files.
used.
memory.swappiness set/show swappiness parameter of vmscan
(See sysctl's vm.swappiness)
- memory.move_charge_at_immigrate set/show controls of moving charges
- This knob is deprecated and shouldn't be
- used.
+ memory.move_charge_at_immigrate This knob is deprecated.
memory.oom_control set/show oom controls.
This knob is deprecated and shouldn't be
used.
@@ -243,10 +241,6 @@ behind this approach is that a cgroup that aggressively uses a shared
page will eventually get charged for it (once it is uncharged from
the cgroup that brought it in -- this will happen on memory pressure).
-But see :ref:`section 8.2 <cgroup-v1-memory-movable-charges>` when moving a
-task to another cgroup, its pages may be recharged to the new cgroup, if
-move_charge_at_immigrate has been chosen.
-
2.4 Swap Extension
--------------------------------------
@@ -756,78 +750,8 @@ If we want to change this to 1G, we can at any time use::
THIS IS DEPRECATED!
-It's expensive and unreliable! It's better practice to launch workload
-tasks directly from inside their target cgroup. Use dedicated workload
-cgroups to allow fine-grained policy adjustments without having to
-move physical pages between control domains.
-
-Users can move charges associated with a task along with task migration, that
-is, uncharge task's pages from the old cgroup and charge them to the new cgroup.
-This feature is not supported in !CONFIG_MMU environments because of lack of
-page tables.
-
-8.1 Interface
--------------
-
-This feature is disabled by default. It can be enabled (and disabled again) by
-writing to memory.move_charge_at_immigrate of the destination cgroup.
-
-If you want to enable it::
-
- # echo (some positive value) > memory.move_charge_at_immigrate
-
-.. note::
- Each bits of move_charge_at_immigrate has its own meaning about what type
- of charges should be moved. See :ref:`section 8.2
- <cgroup-v1-memory-movable-charges>` for details.
-
-.. note::
- Charges are moved only when you move mm->owner, in other words,
- a leader of a thread group.
-
-.. note::
- If we cannot find enough space for the task in the destination cgroup, we
- try to make space by reclaiming memory. Task migration may fail if we
- cannot make enough space.
-
-.. note::
- It can take several seconds if you move charges much.
-
-And if you want disable it again::
-
- # echo 0 > memory.move_charge_at_immigrate
-
-.. _cgroup-v1-memory-movable-charges:
-
-8.2 Type of charges which can be moved
---------------------------------------
-
-Each bit in move_charge_at_immigrate has its own meaning about what type of
-charges should be moved. But in any case, it must be noted that an account of
-a page or a swap can be moved only when it is charged to the task's current
-(old) memory cgroup.
-
-+---+--------------------------------------------------------------------------+
-|bit| what type of charges would be moved ? |
-+===+==========================================================================+
-| 0 | A charge of an anonymous page (or swap of it) used by the target task. |
-| | You must enable Swap Extension (see 2.4) to enable move of swap charges. |
-+---+--------------------------------------------------------------------------+
-| 1 | A charge of file pages (normal file, tmpfs file (e.g. ipc shared memory) |
-| | and swaps of tmpfs file) mmapped by the target task. Unlike the case of |
-| | anonymous pages, file pages (and swaps) in the range mmapped by the task |
-| | will be moved even if the task hasn't done page fault, i.e. they might |
-| | not be the task's "RSS", but other task's "RSS" that maps the same file. |
-| | The mapcount of the page is ignored (the page can be moved independent |
-| | of the mapcount). You must enable Swap Extension (see 2.4) to |
-| | enable move of swap charges. |
-+---+--------------------------------------------------------------------------+
-
-8.3 TODO
---------
-
-- All of moving charge operations are done under cgroup_mutex. It's not good
- behavior to hold the mutex too long, so we may need some trick.
+Reading memory.move_charge_at_immigrate will always return 0 and writing
+to it will always return -EINVAL.
9. Memory thresholds
====================
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 69af2173555f..315ede811c9d 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -1599,6 +1599,15 @@ The following nested keys are defined.
pglazyfreed (npn)
Amount of reclaimed lazyfree pages
+ swpin_zero
+ Number of pages swapped into memory and filled with zero, where I/O
+ was optimized out because the page content was detected to be zero
+ during swapout.
+
+ swpout_zero
+ Number of zero-filled pages swapped out with I/O skipped due to the
+ content being detected as zero.
+
zswpin
Number of pages moved in to memory from zswap.
@@ -1646,6 +1655,11 @@ The following nested keys are defined.
pgdemote_khugepaged
Number of pages demoted by khugepaged.
+ hugetlb
+ Amount of memory used by hugetlb pages. This metric only shows
+ up if hugetlb usage is accounted for in memory.current (i.e.
+ cgroup is mounted with the memory_hugetlb_accounting option).
+
memory.numa_stat
A read-only nested-keyed file which exists on non-root cgroups.
@@ -2945,7 +2959,7 @@ following two functions.
a queue (device) has been associated with the bio and
before submission.
- wbc_account_cgroup_owner(@wbc, @page, @bytes)
+ wbc_account_cgroup_owner(@wbc, @folio, @bytes)
Should be called for each data segment being written out.
While this function doesn't care exactly when it's called
during the writeback session, it's the easiest and most
diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst
index fdea7c26ef80..59931f21c974 100644
--- a/Documentation/admin-guide/kernel-parameters.rst
+++ b/Documentation/admin-guide/kernel-parameters.rst
@@ -27,6 +27,16 @@ kernel command line (/proc/cmdline) and collects module parameters
when it loads a module, so the kernel command line can be used for
loadable modules too.
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+``echo -n ${value} > /sys/module/${modulename}/parameters/${parm}``.
+
+Special handling
+----------------
+
Hyphens (dashes) and underscores are equivalent in parameter names, so::
log_buf_len=1M print-fatal-signals=1
@@ -39,8 +49,8 @@ Double-quotes can be used to protect spaces in values, e.g.::
param="spaces in here"
-cpu lists:
-----------
+cpu lists
+~~~~~~~~~
Some kernel parameters take a list of CPUs as a value, e.g. isolcpus,
nohz_full, irqaffinity, rcu_nocbs. The format of this list is:
@@ -82,12 +92,17 @@ so that "nohz_full=all" is the equivalent of "nohz_full=0-N".
The semantics of "N" and "all" is supported on a level of bitmaps and holds for
all users of bitmap_parselist().
-This document may not be entirely up to date and comprehensive. The command
-"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
-module. Loadable modules, after being loaded into the running kernel, also
-reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
-parameters may be changed at runtime by the command
-``echo -n ${value} > /sys/module/${modulename}/parameters/${parm}``.
+Metric suffixes
+~~~~~~~~~~~~~~~
+
+The [KMG] suffix is commonly described after a number of kernel
+parameter values. 'K', 'M', 'G', 'T', 'P', and 'E' suffixes are allowed.
+These letters represent the _binary_ multipliers 'Kilo', 'Mega', 'Giga',
+'Tera', 'Peta', and 'Exa', equaling 2^10, 2^20, 2^30, 2^40, 2^50, and
+2^60 bytes respectively. Such letter suffixes can also be entirely omitted.
+
+Kernel Build Options
+--------------------
The parameters listed below are only valid if certain kernel build options
were enabled and if respective hardware is present. This list should be kept
@@ -159,6 +174,7 @@ is applicable::
SCSI Appropriate SCSI support is enabled.
A lot of drivers have their options described inside
the Documentation/scsi/ sub-directory.
+ SDW SoundWire support is enabled.
SECURITY Different security models are enabled.
SELINUX SELinux support is enabled.
SERIAL Serial support is enabled.
@@ -211,10 +227,5 @@ a fixed number of characters. This limit depends on the architecture
and is between 256 and 4096 characters. It is defined in the file
./include/uapi/asm-generic/setup.h as COMMAND_LINE_SIZE.
-Finally, the [KMG] suffix is commonly described after a number of kernel
-parameter values. These 'K', 'M', and 'G' letters represent the _binary_
-multipliers 'Kilo', 'Mega', and 'Giga', equaling 2^10, 2^20, and 2^30
-bytes respectively. Such letter suffixes can also be entirely omitted:
-
.. include:: kernel-parameters.txt
:literal:
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 1518343bbe22..dc663c0ca670 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -446,6 +446,9 @@
arm64.nobti [ARM64] Unconditionally disable Branch Target
Identification support
+ arm64.nogcs [ARM64] Unconditionally disable Guarded Control Stack
+ support
+
arm64.nomops [ARM64] Unconditionally disable Memory Copy and Memory
Set instructions support
@@ -918,12 +921,16 @@
the parameter has no effect.
crash_kexec_post_notifiers
- Run kdump after running panic-notifiers and dumping
- kmsg. This only for the users who doubt kdump always
- succeeds in any situation.
- Note that this also increases risks of kdump failure,
- because some panic notifiers can make the crashed
- kernel more unstable.
+ Only jump to kdump kernel after running the panic
+ notifiers and dumping kmsg. This option increases
+ the risks of a kdump failure, since some panic
+ notifiers can make the crashed kernel more unstable.
+ In configurations where kdump may not be reliable,
+ running the panic notifiers could allow collecting
+ more data on dmesg, like stack traces from other CPUS
+ or extra data dumped by panic_print. Note that some
+ configurations enable this option unconditionally,
+ like Hyper-V, PowerPC (fadump) and AMD SEV-SNP.
crashkernel=size[KMG][@offset[KMG]]
[KNL,EARLY] Using kexec, Linux can switch to a 'crash kernel'
@@ -1546,6 +1553,7 @@
failslab=
fail_usercopy=
fail_page_alloc=
+ fail_skb_realloc=
fail_make_request=[KNL]
General fault injection mechanism.
Format: <interval>,<probability>,<space>,<times>
@@ -4678,6 +4686,10 @@
nomio [S390] Do not use MIO instructions.
norid [S390] ignore the RID field and force use of
one PCI domain per PCI function
+ notph [PCIE] If the PCIE_TPH kernel config parameter
+ is enabled, this kernel boot option can be used
+ to disable PCIe TLP Processing Hints support
+ system-wide.
pcie_aspm= [PCIE] Forcibly enable or ignore PCIe Active State Power
Management.
@@ -5412,11 +5424,6 @@
Set time (jiffies) between CPU-hotplug operations,
or zero to disable CPU-hotplug testing.
- rcutorture.read_exit= [KNL]
- Set the number of read-then-exit kthreads used
- to test the interaction of RCU updaters and
- task-exit processing.
-
rcutorture.read_exit_burst= [KNL]
The number of times in a given read-then-exit
episode that a set of read-then-exit kthreads
@@ -5426,6 +5433,14 @@
The delay, in seconds, between successive
read-then-exit testing episodes.
+ rcutorture.reader_flavor= [KNL]
+ A bit mask indicating which readers to use.
+ If there is more than one bit set, the readers
+ are entered from low-order bit up, and are
+ exited in the opposite order. For SRCU, the
+ 0x1 bit is normal readers, 0x2 NMI-safe readers,
+ and 0x4 light-weight readers.
+
rcutorture.shuffle_interval= [KNL]
Set task-shuffle interval (s). Shuffling tasks
allows some CPUs to go into dyntick-idle mode
@@ -6060,6 +6075,10 @@
non-zero "wait" parameter. See weight_single
and weight_many.
+ sdw_mclk_divider=[SDW]
+ Specify the MCLK divider for Intel SoundWire buses in
+ case the BIOS does not provide the clock rate properly.
+
skew_tick= [KNL,EARLY] Offset the periodic timer tick per cpu to mitigate
xtime_lock contention on larger systems, and/or RCU lock
contention on all systems with CONFIG_MAXSMP set.
@@ -6147,6 +6166,16 @@
For more information see Documentation/mm/slub.rst.
(slub_nomerge legacy name also accepted for now)
+ slab_strict_numa [MM]
+ Support memory policies on a per object level
+ in the slab allocator. The default is for memory
+ policies to be applied at the folio level when
+ a new folio is needed or a partial folio is
+ retrieved from the lists. Increases overhead
+ in the slab fastpaths but gains more accurate
+ NUMA kernel object placement which helps with slow
+ interconnects in NUMA systems.
+
slram= [HW,MTD]
smart2= [HW]
@@ -6688,7 +6717,7 @@
0: no polling (default)
thp_anon= [KNL]
- Format: <size>,<size>[KMG]:<state>;<size>-<size>[KMG]:<state>
+ Format: <size>[KMG],<size>[KMG]:<state>;<size>[KMG]-<size>[KMG]:<state>
state is one of "always", "madvise", "never" or "inherit".
Control the default behavior of the system with respect
to anonymous transparent hugepages.
@@ -6700,6 +6729,16 @@
Force threading of all interrupt handlers except those
marked explicitly IRQF_NO_THREAD.
+ thp_shmem= [KNL]
+ Format: <size>[KMG],<size>[KMG]:<policy>;<size>[KMG]-<size>[KMG]:<policy>
+ Control the default policy of each hugepage size for the
+ internal shmem mount. <policy> is one of policies available
+ for the shmem mount ("always", "inherit", "never", "within_size",
+ and "advise").
+ It can be used multiple times for multiple shmem THP sizes.
+ See Documentation/admin-guide/mm/transhuge.rst for more
+ details.
+
topology= [S390,EARLY]
Format: {off | on}
Specify if the kernel should make use of the cpu
@@ -6727,6 +6766,15 @@
torture.verbose_sleep_duration= [KNL]
Duration of each verbose-printk() sleep in jiffies.
+ tpm.disable_pcr_integrity= [HW,TPM]
+ Do not protect PCR registers from unintended physical
+ access, or interposers in the bus by the means of
+ having an integrity protected session wrapped around
+ TPM2_PCR_Extend command. Consider this in a situation
+ where TPM is heavily utilized by IMA, thus protection
+ causing a major performance hit, and the space where
+ machines are deployed is by other means guarded.
+
tpm_suspend_pcr=[HW,TPM]
Format: integer pcr id
Specify that at suspend time, the tpm driver
@@ -6867,6 +6915,12 @@
reserve_mem=12M:4096:trace trace_instance=boot_map^traceoff^traceprintk@trace,sched,irq
+ Note, saving the trace buffer across reboots does require that the system
+ is set up to not wipe memory. For instance, CONFIG_RESET_ATTACK_MITIGATION
+ can force a memory reset on boot which will clear any trace that was stored.
+ This is just one of many ways that can clear memory. Make sure your system
+ keeps the content of memory across reboots before relying on this option.
+
See also Documentation/trace/debugging.rst
@@ -6926,6 +6980,13 @@
See Documentation/admin-guide/mm/transhuge.rst
for more details.
+ transparent_hugepage_shmem= [KNL]
+ Format: [always|within_size|advise|never|deny|force]
+ Can be used to control the hugepage allocation policy for
+ the internal shmem mount.
+ See Documentation/admin-guide/mm/transhuge.rst
+ for more details.
+
trusted.source= [KEYS]
Format: <string>
This parameter identifies the trust source as a backend
diff --git a/Documentation/admin-guide/kernel-per-CPU-kthreads.rst b/Documentation/admin-guide/kernel-per-CPU-kthreads.rst
index b6aeae3327ce..ea7fa2a8bbf0 100644
--- a/Documentation/admin-guide/kernel-per-CPU-kthreads.rst
+++ b/Documentation/admin-guide/kernel-per-CPU-kthreads.rst
@@ -315,7 +315,7 @@ To reduce its OS jitter, do at least one of the following:
to do.
Name:
- rcuop/%d and rcuos/%d
+ rcuop/%d, rcuos/%d, and rcuog/%d
Purpose:
Offload RCU callbacks from the corresponding CPU.
diff --git a/Documentation/admin-guide/media/building.rst b/Documentation/admin-guide/media/building.rst
index a06473429916..7a413ba07f93 100644
--- a/Documentation/admin-guide/media/building.rst
+++ b/Documentation/admin-guide/media/building.rst
@@ -15,7 +15,7 @@ Please notice, however, that, if:
you should use the main media development tree ``master`` branch:
- https://git.linuxtv.org/media_tree.git/
+ https://git.linuxtv.org/media.git/
In this case, you may find some useful information at the
`LinuxTv wiki pages <https://linuxtv.org/wiki>`_:
diff --git a/Documentation/admin-guide/media/index.rst b/Documentation/admin-guide/media/index.rst
index be7e0e4482ca..b11737ae6c04 100644
--- a/Documentation/admin-guide/media/index.rst
+++ b/Documentation/admin-guide/media/index.rst
@@ -20,6 +20,11 @@ Documentation/driver-api/media/index.rst
- for driver development information and Kernel APIs used by
media devices;
+Documentation/process/debugging/media_specific_debugging_guide.rst
+
+ - for advice about essential tools and techniques to debug drivers on this
+ subsystem
+
.. toctree::
:caption: Table of Contents
:maxdepth: 2
diff --git a/Documentation/admin-guide/media/omap4_camera.rst b/Documentation/admin-guide/media/omap4_camera.rst
deleted file mode 100644
index 2ada9b1e6897..000000000000
--- a/Documentation/admin-guide/media/omap4_camera.rst
+++ /dev/null
@@ -1,62 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-OMAP4 ISS Driver
-================
-
-Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
-
-Copyright (C) 2012, Texas Instruments
-
-Introduction
-------------
-
-The OMAP44XX family of chips contains the Imaging SubSystem (a.k.a. ISS),
-Which contains several components that can be categorized in 3 big groups:
-
-- Interfaces (2 Interfaces: CSI2-A & CSI2-B/CCP2)
-- ISP (Image Signal Processor)
-- SIMCOP (Still Image Coprocessor)
-
-For more information, please look in [#f1]_ for latest version of:
-"OMAP4430 Multimedia Device Silicon Revision 2.x"
-
-As of Revision AB, the ISS is described in detail in section 8.
-
-This driver is supporting **only** the CSI2-A/B interfaces for now.
-
-It makes use of the Media Controller framework [#f2]_, and inherited most of the
-code from OMAP3 ISP driver (found under drivers/media/platform/ti/omap3isp/\*),
-except that it doesn't need an IOMMU now for ISS buffers memory mapping.
-
-Supports usage of MMAP buffers only (for now).
-
-Tested platforms
-----------------
-
-- OMAP4430SDP, w/ ES2.1 GP & SEVM4430-CAM-V1-0 (Contains IMX060 & OV5640, in
- which only the last one is supported, outputting YUV422 frames).
-
-- TI Blaze MDP, w/ OMAP4430 ES2.2 EMU (Contains 1 IMX060 & 2 OV5650 sensors, in
- which only the OV5650 are supported, outputting RAW10 frames).
-
-- PandaBoard, Rev. A2, w/ OMAP4430 ES2.1 GP & OV adapter board, tested with
- following sensors:
- * OV5640
- * OV5650
-
-- Tested on mainline kernel:
-
- http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=summary
-
- Tag: v3.3 (commit c16fa4f2ad19908a47c63d8fa436a1178438c7e7)
-
-File list
----------
-drivers/staging/media/omap4iss/
-include/linux/platform_data/media/omap4iss.h
-
-References
-----------
-
-.. [#f1] http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?navigationId=12037&templateId=6123#62
-.. [#f2] http://lwn.net/Articles/420485/
diff --git a/Documentation/admin-guide/media/raspberrypi-rp1-cfe.dot b/Documentation/admin-guide/media/raspberrypi-rp1-cfe.dot
new file mode 100644
index 000000000000..7717f2291049
--- /dev/null
+++ b/Documentation/admin-guide/media/raspberrypi-rp1-cfe.dot
@@ -0,0 +1,27 @@
+digraph board {
+ rankdir=TB
+ n00000001 [label="{{<port0> 0} | csi2\n/dev/v4l-subdev0 | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
+ n00000001:port1 -> n00000011 [style=dashed]
+ n00000001:port1 -> n00000007:port0
+ n00000001:port2 -> n00000015
+ n00000001:port2 -> n00000007:port0 [style=dashed]
+ n00000001:port3 -> n00000019 [style=dashed]
+ n00000001:port3 -> n00000007:port0 [style=dashed]
+ n00000001:port4 -> n0000001d [style=dashed]
+ n00000001:port4 -> n00000007:port0 [style=dashed]
+ n00000007 [label="{{<port0> 0 | <port1> 1} | pisp-fe\n/dev/v4l-subdev1 | {<port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
+ n00000007:port2 -> n00000021
+ n00000007:port3 -> n00000025 [style=dashed]
+ n00000007:port4 -> n00000029
+ n0000000d [label="{imx219 6-0010\n/dev/v4l-subdev2 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
+ n0000000d:port0 -> n00000001:port0 [style=bold]
+ n00000011 [label="rp1-cfe-csi2-ch0\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
+ n00000015 [label="rp1-cfe-csi2-ch1\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
+ n00000019 [label="rp1-cfe-csi2-ch2\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
+ n0000001d [label="rp1-cfe-csi2-ch3\n/dev/video3", shape=box, style=filled, fillcolor=yellow]
+ n00000021 [label="rp1-cfe-fe-image0\n/dev/video4", shape=box, style=filled, fillcolor=yellow]
+ n00000025 [label="rp1-cfe-fe-image1\n/dev/video5", shape=box, style=filled, fillcolor=yellow]
+ n00000029 [label="rp1-cfe-fe-stats\n/dev/video6", shape=box, style=filled, fillcolor=yellow]
+ n0000002d [label="rp1-cfe-fe-config\n/dev/video7", shape=box, style=filled, fillcolor=yellow]
+ n0000002d -> n00000007:port1
+}
diff --git a/Documentation/admin-guide/media/raspberrypi-rp1-cfe.rst b/Documentation/admin-guide/media/raspberrypi-rp1-cfe.rst
new file mode 100644
index 000000000000..668d978a9875
--- /dev/null
+++ b/Documentation/admin-guide/media/raspberrypi-rp1-cfe.rst
@@ -0,0 +1,78 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================================
+Raspberry Pi PiSP Camera Front End (rp1-cfe)
+============================================
+
+The PiSP Camera Front End
+=========================
+
+The PiSP Camera Front End (CFE) is a module which combines a CSI-2 receiver with
+a simple ISP, called the Front End (FE).
+
+The CFE has four DMA engines and can write frames from four separate streams
+received from the CSI-2 to the memory. One of those streams can also be routed
+directly to the FE, which can do minimal image processing, write two versions
+(e.g. non-scaled and downscaled versions) of the received frames to memory and
+provide statistics of the received frames.
+
+The FE registers are documented in the `Raspberry Pi Image Signal Processor
+(ISP) Specification document
+<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_,
+and example code for FE can be found in `libpisp
+<https://github.com/raspberrypi/libpisp>`_.
+
+The rp1-cfe driver
+==================
+
+The Raspberry Pi PiSP Camera Front End (rp1-cfe) driver is located under
+drivers/media/platform/raspberrypi/rp1-cfe. It uses the `V4L2 API` to register
+a number of video capture and output devices, the `V4L2 subdev API` to register
+subdevices for the CSI-2 received and the FE that connects the video devices in
+a single media graph realized using the `Media Controller (MC) API`.
+
+The media topology registered by the `rp1-cfe` driver, in this particular
+example connected to an imx219 sensor, is the following one:
+
+.. _rp1-cfe-topology:
+
+.. kernel-figure:: raspberrypi-rp1-cfe.dot
+ :alt: Diagram of an example media pipeline topology
+ :align: center
+
+The media graph contains the following video device nodes:
+
+- rp1-cfe-csi2-ch0: capture device for the first CSI-2 stream
+- rp1-cfe-csi2-ch1: capture device for the second CSI-2 stream
+- rp1-cfe-csi2-ch2: capture device for the third CSI-2 stream
+- rp1-cfe-csi2-ch3: capture device for the fourth CSI-2 stream
+- rp1-cfe-fe-image0: capture device for the first FE output
+- rp1-cfe-fe-image1: capture device for the second FE output
+- rp1-cfe-fe-stats: capture device for the FE statistics
+- rp1-cfe-fe-config: output device for FE configuration
+
+rp1-cfe-csi2-chX
+----------------
+
+The rp1-cfe-csi2-chX capture devices are normal V4L2 capture devices which
+can be used to capture video frames or metadata received from the CSI-2.
+
+rp1-cfe-fe-image0, rp1-cfe-fe-image1
+------------------------------------
+
+The rp1-cfe-fe-image0 and rp1-cfe-fe-image1 capture devices are used to write
+the processed frames to memory.
+
+rp1-cfe-fe-stats
+----------------
+
+The format of the FE statistics buffer is defined by
+:c:type:`pisp_statistics` C structure and the meaning of each parameter is
+described in the `PiSP specification` document.
+
+rp1-cfe-fe-config
+-----------------
+
+The format of the FE configuration buffer is defined by
+:c:type:`pisp_fe_config` C structure and the meaning of each parameter is
+described in the `PiSP specification` document.
diff --git a/Documentation/admin-guide/media/saa7134.rst b/Documentation/admin-guide/media/saa7134.rst
index 51eae7eb5ab7..18d7cbc897db 100644
--- a/Documentation/admin-guide/media/saa7134.rst
+++ b/Documentation/admin-guide/media/saa7134.rst
@@ -67,7 +67,7 @@ Changes / Fixes
Please mail to linux-media AT vger.kernel.org unified diffs against
the linux media git tree:
- https://git.linuxtv.org/media_tree.git/
+ https://git.linuxtv.org/media.git/
This is done by committing a patch at a clone of the git tree and
submitting the patch using ``git send-email``. Don't forget to
diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst
index b6af448b9fe9..e8761561b2fe 100644
--- a/Documentation/admin-guide/media/v4l-drivers.rst
+++ b/Documentation/admin-guide/media/v4l-drivers.rst
@@ -20,12 +20,12 @@ Video4Linux (V4L) driver-specific documentation
ivtv
mgb4
omap3isp
- omap4_camera
philips
qcom_camss
raspberrypi-pisp-be
rcar-fdp1
rkisp1
+ raspberrypi-rp1-cfe
saa7134
si470x
si4713
diff --git a/Documentation/admin-guide/mm/transhuge.rst b/Documentation/admin-guide/mm/transhuge.rst
index cfdd16a52e39..5034915f4e8e 100644
--- a/Documentation/admin-guide/mm/transhuge.rst
+++ b/Documentation/admin-guide/mm/transhuge.rst
@@ -303,7 +303,7 @@ control by passing the parameter ``transparent_hugepage=always`` or
kernel command line.
Alternatively, each supported anonymous THP size can be controlled by
-passing ``thp_anon=<size>,<size>[KMG]:<state>;<size>-<size>[KMG]:<state>``,
+passing ``thp_anon=<size>[KMG],<size>[KMG]:<state>;<size>[KMG]-<size>[KMG]:<state>``,
where ``<size>`` is the THP size (must be a power of 2 of PAGE_SIZE and
supported anonymous THP) and ``<state>`` is one of ``always``, ``madvise``,
``never`` or ``inherit``.
@@ -326,6 +326,29 @@ PMD_ORDER THP policy will be overridden. If the policy for PMD_ORDER
is not defined within a valid ``thp_anon``, its policy will default to
``never``.
+Similarly to ``transparent_hugepage``, you can control the hugepage
+allocation policy for the internal shmem mount by using the kernel parameter
+``transparent_hugepage_shmem=<policy>``, where ``<policy>`` is one of the
+seven valid policies for shmem (``always``, ``within_size``, ``advise``,
+``never``, ``deny``, and ``force``).
+
+In the same manner as ``thp_anon`` controls each supported anonymous THP
+size, ``thp_shmem`` controls each supported shmem THP size. ``thp_shmem``
+has the same format as ``thp_anon``, but also supports the policy
+``within_size``.
+
+``thp_shmem=`` may be specified multiple times to configure all THP sizes
+as required. If ``thp_shmem=`` is specified at least once, any shmem THP
+sizes not explicitly configured on the command line are implicitly set to
+``never``.
+
+``transparent_hugepage_shmem`` setting only affects the global toggle. If
+``thp_shmem`` is not specified, PMD_ORDER hugepage will default to
+``inherit``. However, if a valid ``thp_shmem`` setting is provided by the
+user, the PMD_ORDER hugepage policy will be overridden. If the policy for
+PMD_ORDER is not defined within a valid ``thp_shmem``, its policy will
+default to ``never``.
+
Hugepages in tmpfs/shmem
========================
@@ -530,10 +553,18 @@ anon_fault_fallback_charge
instead falls back to using huge pages with lower orders or
small pages even though the allocation was successful.
-swpout
- is incremented every time a huge page is swapped out in one
+zswpout
+ is incremented every time a huge page is swapped out to zswap in one
piece without splitting.
+swpin
+ is incremented every time a huge page is swapped in from a non-zswap
+ swap device in one piece.
+
+swpout
+ is incremented every time a huge page is swapped out to a non-zswap
+ swap device in one piece without splitting.
+
swpout_fallback
is incremented if a huge page has to be split before swapout.
Usually because failed to allocate some continuous swap space
diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst
index 8502bc174640..a58bd3f7e190 100644
--- a/Documentation/admin-guide/perf/index.rst
+++ b/Documentation/admin-guide/perf/index.rst
@@ -26,3 +26,4 @@ Performance monitor support
meson-ddr-pmu
cxl
ampere_cspmu
+ mrvl-pem-pmu
diff --git a/Documentation/admin-guide/perf/mrvl-pem-pmu.rst b/Documentation/admin-guide/perf/mrvl-pem-pmu.rst
new file mode 100644
index 000000000000..c39007149b97
--- /dev/null
+++ b/Documentation/admin-guide/perf/mrvl-pem-pmu.rst
@@ -0,0 +1,56 @@
+=================================================================
+Marvell Odyssey PEM Performance Monitoring Unit (PMU UNCORE)
+=================================================================
+
+The PCI Express Interface Units(PEM) are associated with a corresponding
+monitoring unit. This includes performance counters to track various
+characteristics of the data that is transmitted over the PCIe link.
+
+The counters track inbound and outbound transactions which
+includes separate counters for posted/non-posted/completion TLPs.
+Also, inbound and outbound memory read requests along with their
+latencies can also be monitored. Address Translation Services(ATS)events
+such as ATS Translation, ATS Page Request, ATS Invalidation along with
+their corresponding latencies are also tracked.
+
+There are separate 64 bit counters to measure posted/non-posted/completion
+tlps in inbound and outbound transactions. ATS events are measured by
+different counters.
+
+The PMU driver exposes the available events and format options under sysfs,
+/sys/bus/event_source/devices/mrvl_pcie_rc_pmu_<>/events/
+/sys/bus/event_source/devices/mrvl_pcie_rc_pmu_<>/format/
+
+Examples::
+
+ # perf list | grep mrvl_pcie_rc_pmu
+ mrvl_pcie_rc_pmu_<>/ats_inv/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ats_inv_latency/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ats_pri/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ats_pri_latency/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ats_trans/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ats_trans_latency/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_inflight/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_reads/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_req_no_ro_ebus/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_req_no_ro_ncb/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_tlp_cpl_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_tlp_dwords_cpl_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_tlp_dwords_npr/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_tlp_dwords_pr/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_tlp_npr/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ib_tlp_pr/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_inflight_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_merges_cpl_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_merges_npr_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_merges_pr_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_reads_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_tlp_cpl_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_tlp_dwords_cpl_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_tlp_dwords_npr_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_tlp_dwords_pr_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_tlp_npr_partid/ [Kernel PMU event]
+ mrvl_pcie_rc_pmu_<>/ob_tlp_pr_partid/ [Kernel PMU event]
+
+
+ # perf stat -e ib_inflight,ib_reads,ib_req_no_ro_ebus,ib_req_no_ro_ncb <workload>
diff --git a/Documentation/admin-guide/sysctl/fs.rst b/Documentation/admin-guide/sysctl/fs.rst
index 47499a1742bd..f5ec6c9312e1 100644
--- a/Documentation/admin-guide/sysctl/fs.rst
+++ b/Documentation/admin-guide/sysctl/fs.rst
@@ -38,6 +38,11 @@ requests. ``aio-max-nr`` allows you to change the maximum value
``aio-max-nr`` does not result in the
pre-allocation or re-sizing of any kernel data structures.
+dentry-negative
+----------------------------
+
+Policy for negative dentries. Set to 1 to to always delete the dentry when a
+file is removed, and 0 to disable it. By default, this behavior is disabled.
dentry-state
------------
@@ -332,3 +337,13 @@ 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.
+
+5. /proc/sys/fs/fuse - Configuration options for FUSE filesystems
+=====================================================================
+
+This directory contains the following configuration options for FUSE
+filesystems:
+
+``/proc/sys/fs/fuse/max_pages_limit`` is a read/write file for
+setting/getting the maximum number of pages that can be used for servicing
+requests in FUSE.
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
index f8bc1630eba0..b2b36d0c3094 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -401,6 +401,15 @@ The upper bound on the number of tasks that are checked.
This file shows up if ``CONFIG_DETECT_HUNG_TASK`` is enabled.
+hung_task_detect_count
+======================
+
+Indicates the total number of tasks that have been detected as hung since
+the system boot.
+
+This file shows up if ``CONFIG_DETECT_HUNG_TASK`` is enabled.
+
+
hung_task_timeout_secs
======================
diff --git a/Documentation/arch/arm64/arm-cca.rst b/Documentation/arch/arm64/arm-cca.rst
new file mode 100644
index 000000000000..c48b7d4ab6bd
--- /dev/null
+++ b/Documentation/arch/arm64/arm-cca.rst
@@ -0,0 +1,69 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+Arm Confidential Compute Architecture
+=====================================
+
+Arm systems that support the Realm Management Extension (RME) contain
+hardware to allow a VM guest to be run in a way which protects the code
+and data of the guest from the hypervisor. It extends the older "two
+world" model (Normal and Secure World) into four worlds: Normal, Secure,
+Root and Realm. Linux can then also be run as a guest to a monitor
+running in the Realm world.
+
+The monitor running in the Realm world is known as the Realm Management
+Monitor (RMM) and implements the Realm Management Monitor
+specification[1]. The monitor acts a bit like a hypervisor (e.g. it runs
+in EL2 and manages the stage 2 page tables etc of the guests running in
+Realm world), however much of the control is handled by a hypervisor
+running in the Normal World. The Normal World hypervisor uses the Realm
+Management Interface (RMI) defined by the RMM specification to request
+the RMM to perform operations (e.g. mapping memory or executing a vCPU).
+
+The RMM defines an environment for guests where the address space (IPA)
+is split into two. The lower half is protected - any memory that is
+mapped in this half cannot be seen by the Normal World and the RMM
+restricts what operations the Normal World can perform on this memory
+(e.g. the Normal World cannot replace pages in this region without the
+guest's cooperation). The upper half is shared, the Normal World is free
+to make changes to the pages in this region, and is able to emulate MMIO
+devices in this region too.
+
+A guest running in a Realm may also communicate with the RMM using the
+Realm Services Interface (RSI) to request changes in its environment or
+to perform attestation about its environment. In particular it may
+request that areas of the protected address space are transitioned
+between 'RAM' and 'EMPTY' (in either direction). This allows a Realm
+guest to give up memory to be returned to the Normal World, or to
+request new memory from the Normal World. Without an explicit request
+from the Realm guest the RMM will otherwise prevent the Normal World
+from making these changes.
+
+Linux as a Realm Guest
+----------------------
+
+To run Linux as a guest within a Realm, the following must be provided
+either by the VMM or by a `boot loader` run in the Realm before Linux:
+
+ * All protected RAM described to Linux (by DT or ACPI) must be marked
+ RIPAS RAM before handing control over to Linux.
+
+ * MMIO devices must be either unprotected (e.g. emulated by the Normal
+ World) or marked RIPAS DEV.
+
+ * MMIO devices emulated by the Normal World and used very early in boot
+ (specifically earlycon) must be specified in the upper half of IPA.
+ For earlycon this can be done by specifying the address on the
+ command line, e.g. with an IPA size of 33 bits and the base address
+ of the emulated UART at 0x1000000: ``earlycon=uart,mmio,0x101000000``
+
+ * Linux will use bounce buffers for communicating with unprotected
+ devices. It will transition some protected memory to RIPAS EMPTY and
+ expect to be able to access unprotected pages at the same IPA address
+ but with the highest valid IPA bit set. The expectation is that the
+ VMM will remove the physical pages from the protected mapping and
+ provide those pages as unprotected pages.
+
+References
+----------
+[1] https://developer.arm.com/documentation/den0137/
diff --git a/Documentation/arch/arm64/booting.rst b/Documentation/arch/arm64/booting.rst
index b57776a68f15..3278fb4bf219 100644
--- a/Documentation/arch/arm64/booting.rst
+++ b/Documentation/arch/arm64/booting.rst
@@ -41,6 +41,9 @@ to automatically locate and size all RAM, or it may use knowledge of
the RAM in the machine, or any other method the boot loader designer
sees fit.)
+For Arm Confidential Compute Realms this includes ensuring that all
+protected RAM has a Realm IPA state (RIPAS) of "RAM".
+
2. Setup the device tree
-------------------------
@@ -385,6 +388,9 @@ Before jumping into the kernel, the following conditions must be met:
- HCRX_EL2.MSCEn (bit 11) must be initialised to 0b1.
+ - HCRX_EL2.MCE2 (bit 10) must be initialised to 0b1 and the hypervisor
+ must handle MOPS exceptions as described in :ref:`arm64_mops_hyp`.
+
For CPUs with the Extended Translation Control Register feature (FEAT_TCR2):
- If EL3 is present:
@@ -411,6 +417,38 @@ Before jumping into the kernel, the following conditions must be met:
- HFGRWR_EL2.nPIRE0_EL1 (bit 57) must be initialised to 0b1.
+ - For CPUs with Guarded Control Stacks (FEAT_GCS):
+
+ - GCSCR_EL1 must be initialised to 0.
+
+ - GCSCRE0_EL1 must be initialised to 0.
+
+ - If EL3 is present:
+
+ - SCR_EL3.GCSEn (bit 39) must be initialised to 0b1.
+
+ - If EL2 is present:
+
+ - GCSCR_EL2 must be initialised to 0.
+
+ - If the kernel is entered at EL1 and EL2 is present:
+
+ - HCRX_EL2.GCSEn must be initialised to 0b1.
+
+ - HFGITR_EL2.nGCSEPP (bit 59) must be initialised to 0b1.
+
+ - HFGITR_EL2.nGCSSTR_EL1 (bit 58) must be initialised to 0b1.
+
+ - HFGITR_EL2.nGCSPUSHM_EL1 (bit 57) must be initialised to 0b1.
+
+ - HFGRTR_EL2.nGCS_EL1 (bit 53) must be initialised to 0b1.
+
+ - HFGRTR_EL2.nGCS_EL0 (bit 52) must be initialised to 0b1.
+
+ - HFGWTR_EL2.nGCS_EL1 (bit 53) must be initialised to 0b1.
+
+ - HFGWTR_EL2.nGCS_EL0 (bit 52) must be initialised to 0b1.
+
The requirements described above for CPU mode, caches, MMUs, architected
timers, coherency and system registers apply to all CPUs. All CPUs must
enter the kernel in the same exception level. Where the values documented
diff --git a/Documentation/arch/arm64/cpu-feature-registers.rst b/Documentation/arch/arm64/cpu-feature-registers.rst
index 44f9bd78539d..253e9743de2f 100644
--- a/Documentation/arch/arm64/cpu-feature-registers.rst
+++ b/Documentation/arch/arm64/cpu-feature-registers.rst
@@ -152,6 +152,8 @@ infrastructure:
+------------------------------+---------+---------+
| DIT | [51-48] | y |
+------------------------------+---------+---------+
+ | MPAM | [43-40] | n |
+ +------------------------------+---------+---------+
| SVE | [35-32] | y |
+------------------------------+---------+---------+
| GIC | [27-24] | n |
diff --git a/Documentation/arch/arm64/elf_hwcaps.rst b/Documentation/arch/arm64/elf_hwcaps.rst
index 694f67fa07d1..2ff922a406ad 100644
--- a/Documentation/arch/arm64/elf_hwcaps.rst
+++ b/Documentation/arch/arm64/elf_hwcaps.rst
@@ -16,9 +16,9 @@ architected discovery mechanism available to userspace code at EL0. The
kernel exposes the presence of these features to userspace through a set
of flags called hwcaps, exposed in the auxiliary vector.
-Userspace software can test for features by acquiring the AT_HWCAP or
-AT_HWCAP2 entry of the auxiliary vector, and testing whether the relevant
-flags are set, e.g.::
+Userspace software can test for features by acquiring the AT_HWCAP,
+AT_HWCAP2 or AT_HWCAP3 entry of the auxiliary vector, and testing
+whether the relevant flags are set, e.g.::
bool floating_point_is_present(void)
{
@@ -170,6 +170,10 @@ HWCAP_PACG
ID_AA64ISAR1_EL1.GPI == 0b0001, as described by
Documentation/arch/arm64/pointer-authentication.rst.
+HWCAP_GCS
+ Functionality implied by ID_AA64PFR1_EL1.GCS == 0b1, as
+ described by Documentation/arch/arm64/gcs.rst.
+
HWCAP2_DCPODP
Functionality implied by ID_AA64ISAR1_EL1.DPB == 0b0010.
diff --git a/Documentation/arch/arm64/gcs.rst b/Documentation/arch/arm64/gcs.rst
new file mode 100644
index 000000000000..1f65a3193e77
--- /dev/null
+++ b/Documentation/arch/arm64/gcs.rst
@@ -0,0 +1,227 @@
+===============================================
+Guarded Control Stack support for AArch64 Linux
+===============================================
+
+This document outlines briefly the interface provided to userspace by Linux in
+order to support use of the ARM Guarded Control Stack (GCS) feature.
+
+This is an outline of the most important features and issues only and not
+intended to be exhaustive.
+
+
+
+1. General
+-----------
+
+* GCS is an architecture feature intended to provide greater protection
+ against return oriented programming (ROP) attacks and to simplify the
+ implementation of features that need to collect stack traces such as
+ profiling.
+
+* When GCS is enabled a separate guarded control stack is maintained by the
+ PE which is writeable only through specific GCS operations. This
+ stores the call stack only, when a procedure call instruction is
+ performed the current PC is pushed onto the GCS and on RET the
+ address in the LR is verified against that on the top of the GCS.
+
+* When active the current GCS pointer is stored in the system register
+ GCSPR_EL0. This is readable by userspace but can only be updated
+ via specific GCS instructions.
+
+* The architecture provides instructions for switching between guarded
+ control stacks with checks to ensure that the new stack is a valid
+ target for switching.
+
+* The functionality of GCS is similar to that provided by the x86 Shadow
+ Stack feature, due to sharing of userspace interfaces the ABI refers to
+ shadow stacks rather than GCS.
+
+* Support for GCS is reported to userspace via HWCAP_GCS in the aux vector
+ AT_HWCAP2 entry.
+
+* GCS is enabled per thread. While there is support for disabling GCS
+ at runtime this should be done with great care.
+
+* GCS memory access faults are reported as normal memory access faults.
+
+* GCS specific errors (those reported with EC 0x2d) will be reported as
+ SIGSEGV with a si_code of SEGV_CPERR (control protection error).
+
+* GCS is supported only for AArch64.
+
+* On systems where GCS is supported GCSPR_EL0 is always readable by EL0
+ regardless of the GCS configuration for the thread.
+
+* The architecture supports enabling GCS without verifying that return values
+ in LR match those in the GCS, the LR will be ignored. This is not supported
+ by Linux.
+
+
+
+2. Enabling and disabling Guarded Control Stacks
+-------------------------------------------------
+
+* GCS is enabled and disabled for a thread via the PR_SET_SHADOW_STACK_STATUS
+ prctl(), this takes a single flags argument specifying which GCS features
+ should be used.
+
+* When set PR_SHADOW_STACK_ENABLE flag allocates a Guarded Control Stack
+ and enables GCS for the thread, enabling the functionality controlled by
+ GCSCRE0_EL1.{nTR, RVCHKEN, PCRSEL}.
+
+* When set the PR_SHADOW_STACK_PUSH flag enables the functionality controlled
+ by GCSCRE0_EL1.PUSHMEn, allowing explicit GCS pushes.
+
+* When set the PR_SHADOW_STACK_WRITE flag enables the functionality controlled
+ by GCSCRE0_EL1.STREn, allowing explicit stores to the Guarded Control Stack.
+
+* Any unknown flags will cause PR_SET_SHADOW_STACK_STATUS to return -EINVAL.
+
+* PR_LOCK_SHADOW_STACK_STATUS is passed a bitmask of features with the same
+ values as used for PR_SET_SHADOW_STACK_STATUS. Any future changes to the
+ status of the specified GCS mode bits will be rejected.
+
+* PR_LOCK_SHADOW_STACK_STATUS allows any bit to be locked, this allows
+ userspace to prevent changes to any future features.
+
+* There is no support for a process to remove a lock that has been set for
+ it.
+
+* PR_SET_SHADOW_STACK_STATUS and PR_LOCK_SHADOW_STACK_STATUS affect only the
+ thread that called them, any other running threads will be unaffected.
+
+* New threads inherit the GCS configuration of the thread that created them.
+
+* GCS is disabled on exec().
+
+* The current GCS configuration for a thread may be read with the
+ PR_GET_SHADOW_STACK_STATUS prctl(), this returns the same flags that
+ are passed to PR_SET_SHADOW_STACK_STATUS.
+
+* If GCS is disabled for a thread after having previously been enabled then
+ the stack will remain allocated for the lifetime of the thread. At present
+ any attempt to reenable GCS for the thread will be rejected, this may be
+ revisited in future.
+
+* It should be noted that since enabling GCS will result in GCS becoming
+ active immediately it is not normally possible to return from the function
+ that invoked the prctl() that enabled GCS. It is expected that the normal
+ usage will be that GCS is enabled very early in execution of a program.
+
+
+
+3. Allocation of Guarded Control Stacks
+----------------------------------------
+
+* When GCS is enabled for a thread a new Guarded Control Stack will be
+ allocated for it of half the standard stack size or 2 gigabytes,
+ whichever is smaller.
+
+* When a new thread is created by a thread which has GCS enabled then a
+ new Guarded Control Stack will be allocated for the new thread with
+ half the size of the standard stack.
+
+* When a stack is allocated by enabling GCS or during thread creation then
+ the top 8 bytes of the stack will be initialised to 0 and GCSPR_EL0 will
+ be set to point to the address of this 0 value, this can be used to
+ detect the top of the stack.
+
+* Additional Guarded Control Stacks can be allocated using the
+ map_shadow_stack() system call.
+
+* Stacks allocated using map_shadow_stack() can optionally have an end of
+ stack marker and cap placed at the top of the stack. If the flag
+ SHADOW_STACK_SET_TOKEN is specified a cap will be placed on the stack,
+ if SHADOW_STACK_SET_MARKER is not specified the cap will be the top 8
+ bytes of the stack and if it is specified then the cap will be the next
+ 8 bytes. While specifying just SHADOW_STACK_SET_MARKER by itself is
+ valid since the marker is all bits 0 it has no observable effect.
+
+* Stacks allocated using map_shadow_stack() must have a size which is a
+ multiple of 8 bytes larger than 8 bytes and must be 8 bytes aligned.
+
+* An address can be specified to map_shadow_stack(), if one is provided then
+ it must be aligned to a page boundary.
+
+* When a thread is freed the Guarded Control Stack initially allocated for
+ that thread will be freed. Note carefully that if the stack has been
+ switched this may not be the stack currently in use by the thread.
+
+
+4. Signal handling
+--------------------
+
+* A new signal frame record gcs_context encodes the current GCS mode and
+ pointer for the interrupted context on signal delivery. This will always
+ be present on systems that support GCS.
+
+* The record contains a flag field which reports the current GCS configuration
+ for the interrupted context as PR_GET_SHADOW_STACK_STATUS would.
+
+* The signal handler is run with the same GCS configuration as the interrupted
+ context.
+
+* When GCS is enabled for the interrupted thread a signal handling specific
+ GCS cap token will be written to the GCS, this is an architectural GCS cap
+ with the token type (bits 0..11) all clear. The GCSPR_EL0 reported in the
+ signal frame will point to this cap token.
+
+* The signal handler will use the same GCS as the interrupted context.
+
+* When GCS is enabled on signal entry a frame with the address of the signal
+ return handler will be pushed onto the GCS, allowing return from the signal
+ handler via RET as normal. This will not be reported in the gcs_context in
+ the signal frame.
+
+
+5. Signal return
+-----------------
+
+When returning from a signal handler:
+
+* If there is a gcs_context record in the signal frame then the GCS flags
+ and GCSPR_EL0 will be restored from that context prior to further
+ validation.
+
+* If there is no gcs_context record in the signal frame then the GCS
+ configuration will be unchanged.
+
+* If GCS is enabled on return from a signal handler then GCSPR_EL0 must
+ point to a valid GCS signal cap record, this will be popped from the
+ GCS prior to signal return.
+
+* If the GCS configuration is locked when returning from a signal then any
+ attempt to change the GCS configuration will be treated as an error. This
+ is true even if GCS was not enabled prior to signal entry.
+
+* GCS may be disabled via signal return but any attempt to enable GCS via
+ signal return will be rejected.
+
+
+6. ptrace extensions
+---------------------
+
+* A new regset NT_ARM_GCS is defined for use with PTRACE_GETREGSET and
+ PTRACE_SETREGSET.
+
+* The GCS mode, including enable and disable, may be configured via ptrace.
+ If GCS is enabled via ptrace no new GCS will be allocated for the thread.
+
+* Configuration via ptrace ignores locking of GCS mode bits.
+
+
+7. ELF coredump extensions
+---------------------------
+
+* NT_ARM_GCS notes will be added to each coredump for each thread of the
+ dumped process. The contents will be equivalent to the data that would
+ have been read if a PTRACE_GETREGSET of the corresponding type were
+ executed for each thread when the coredump was generated.
+
+
+
+8. /proc extensions
+--------------------
+
+* Guarded Control Stack pages will include "ss" in their VmFlags in
+ /proc/<pid>/smaps.
diff --git a/Documentation/arch/arm64/index.rst b/Documentation/arch/arm64/index.rst
index 78544de0a8a9..6a012c98bdcd 100644
--- a/Documentation/arch/arm64/index.rst
+++ b/Documentation/arch/arm64/index.rst
@@ -10,16 +10,19 @@ ARM64 Architecture
acpi_object_usage
amu
arm-acpi
+ arm-cca
asymmetric-32bit
booting
cpu-feature-registers
cpu-hotplug
elf_hwcaps
+ gcs
hugetlbpage
kdump
legacy_instructions
memory
memory-tagging-extension
+ mops
perf
pointer-authentication
ptdump
diff --git a/Documentation/arch/arm64/mops.rst b/Documentation/arch/arm64/mops.rst
new file mode 100644
index 000000000000..2ef5b147f8dc
--- /dev/null
+++ b/Documentation/arch/arm64/mops.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================================
+Memory copy/set instructions (MOPS)
+===================================
+
+A MOPS memory copy/set operation consists of three consecutive CPY* or SET*
+instructions: a prologue, main and epilogue (for example: CPYP, CPYM, CPYE).
+
+A main or epilogue instruction can take a MOPS exception for various reasons,
+for example when a task is migrated to a CPU with a different MOPS
+implementation, or when the instruction's alignment and size requirements are
+not met. The software exception handler is then expected to reset the registers
+and restart execution from the prologue instruction. Normally this is handled
+by the kernel.
+
+For more details refer to "D1.3.5.7 Memory Copy and Memory Set exceptions" in
+the Arm Architecture Reference Manual DDI 0487K.a (Arm ARM).
+
+.. _arm64_mops_hyp:
+
+Hypervisor requirements
+-----------------------
+
+A hypervisor running a Linux guest must handle all MOPS exceptions from the
+guest kernel, as Linux may not be able to handle the exception at all times.
+For example, a MOPS exception can be taken when the hypervisor migrates a vCPU
+to another physical CPU with a different MOPS implementation.
+
+To do this, the hypervisor must:
+
+ - Set HCRX_EL2.MCE2 to 1 so that the exception is taken to the hypervisor.
+
+ - Have an exception handler that implements the algorithm from the Arm ARM
+ rules CNTMJ and MWFQH.
+
+ - Set the guest's PSTATE.SS to 0 in the exception handler, to handle a
+ potential step of the current instruction.
+
+ Note: Clearing PSTATE.SS is needed so that a single step exception is taken
+ on the next instruction (the prologue instruction). Otherwise prologue
+ would get silently stepped over and the single step exception taken on the
+ main instruction. Note that if the guest instruction is not being stepped
+ then clearing PSTATE.SS has no effect.
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index 65bfab1b1861..77db10e944f0 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -258,6 +258,8 @@ stable kernels.
| Hisilicon | Hip{08,09,10,10C| #162001900 | N/A |
| | ,11} SMMU PMCG | | |
+----------------+-----------------+-----------------+-----------------------------+
+| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 |
++----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
+----------------+-----------------+-----------------+-----------------------------+
diff --git a/Documentation/arch/arm64/sme.rst b/Documentation/arch/arm64/sme.rst
index be317d457417..b2fa01f85cb5 100644
--- a/Documentation/arch/arm64/sme.rst
+++ b/Documentation/arch/arm64/sme.rst
@@ -346,6 +346,10 @@ The regset data starts with struct user_za_header, containing:
* Writes to NT_ARM_ZT will set PSTATE.ZA to 1.
+* If any register data is provided along with SME_PT_VL_ONEXEC then the
+ registers data will be interpreted with the current vector length, not
+ the vector length configured for use on exec.
+
8. ELF coredump extensions
---------------------------
diff --git a/Documentation/arch/arm64/sve.rst b/Documentation/arch/arm64/sve.rst
index 8d8837fc39ec..28152492c29c 100644
--- a/Documentation/arch/arm64/sve.rst
+++ b/Documentation/arch/arm64/sve.rst
@@ -402,6 +402,10 @@ The regset data starts with struct user_sve_header, containing:
streaming mode and any SETREGSET of NT_ARM_SSVE will enter streaming mode
if the target was not in streaming mode.
+* If any register data is provided along with SVE_PT_VL_ONEXEC then the
+ registers data will be interpreted with the current vector length, not
+ the vector length configured for use on exec.
+
* The effect of writing a partial, incomplete payload is unspecified.
diff --git a/Documentation/arch/loongarch/irq-chip-model.rst b/Documentation/arch/loongarch/irq-chip-model.rst
index 6dd48256e39f..a7ecce11e445 100644
--- a/Documentation/arch/loongarch/irq-chip-model.rst
+++ b/Documentation/arch/loongarch/irq-chip-model.rst
@@ -85,6 +85,70 @@ to CPUINTC directly::
| Devices |
+---------+
+Virtual Extended IRQ model
+==========================
+
+In this model, IPI (Inter-Processor Interrupt) and CPU Local Timer interrupt
+go to CPUINTC directly, CPU UARTS interrupts go to PCH-PIC, while all other
+devices interrupts go to PCH-PIC/PCH-MSI and gathered by V-EIOINTC (Virtual
+Extended I/O Interrupt Controller), and then go to CPUINTC directly::
+
+ +-----+ +-------------------+ +-------+
+ | IPI |--> | CPUINTC(0-255vcpu)| <-- | Timer |
+ +-----+ +-------------------+ +-------+
+ ^
+ |
+ +-----------+
+ | V-EIOINTC |
+ +-----------+
+ ^ ^
+ | |
+ +---------+ +---------+
+ | PCH-PIC | | PCH-MSI |
+ +---------+ +---------+
+ ^ ^ ^
+ | | |
+ +--------+ +---------+ +---------+
+ | UARTs | | Devices | | Devices |
+ +--------+ +---------+ +---------+
+
+
+Description
+-----------
+V-EIOINTC (Virtual Extended I/O Interrupt Controller) is an extension of
+EIOINTC, it only works in VM mode which runs in KVM hypervisor. Interrupts can
+be routed to up to four vCPUs via standard EIOINTC, however with V-EIOINTC
+interrupts can be routed to up to 256 virtual cpus.
+
+With standard EIOINTC, interrupt routing setting includes two parts: eight
+bits for CPU selection and four bits for CPU IP (Interrupt Pin) selection.
+For CPU selection there is four bits for EIOINTC node selection, four bits
+for EIOINTC CPU selection. Bitmap method is used for CPU selection and
+CPU IP selection, so interrupt can only route to CPU0 - CPU3 and IP0-IP3 in
+one EIOINTC node.
+
+With V-EIOINTC it supports to route more CPUs and CPU IP (Interrupt Pin),
+there are two newly added registers with V-EIOINTC.
+
+EXTIOI_VIRT_FEATURES
+--------------------
+This register is read-only register, which indicates supported features with
+V-EIOINTC. Feature EXTIOI_HAS_INT_ENCODE and EXTIOI_HAS_CPU_ENCODE is added.
+
+Feature EXTIOI_HAS_INT_ENCODE is part of standard EIOINTC. If it is 1, it
+indicates that CPU Interrupt Pin selection can be normal method rather than
+bitmap method, so interrupt can be routed to IP0 - IP15.
+
+Feature EXTIOI_HAS_CPU_ENCODE is entension of V-EIOINTC. If it is 1, it
+indicates that CPU selection can be normal method rather than bitmap method,
+so interrupt can be routed to CPU0 - CPU255.
+
+EXTIOI_VIRT_CONFIG
+------------------
+This register is read-write register, for compatibility intterupt routed uses
+the default method which is the same with standard EIOINTC. If the bit is set
+with 1, it indicated HW to use normal method rather than bitmap method.
+
Advanced Extended IRQ model
===========================
diff --git a/Documentation/arch/powerpc/booting.rst b/Documentation/arch/powerpc/booting.rst
index 11aa440f98cc..472e97891aef 100644
--- a/Documentation/arch/powerpc/booting.rst
+++ b/Documentation/arch/powerpc/booting.rst
@@ -93,8 +93,8 @@ given platform based on the content of the device-tree. Thus, you
should:
a) add your platform support as a _boolean_ option in
- arch/powerpc/Kconfig, following the example of PPC_PSERIES,
- PPC_PMAC and PPC_MAPLE. The latter is probably a good
+ arch/powerpc/Kconfig, following the example of PPC_PSERIES
+ and PPC_PMAC. The latter is probably a good
example of a board support to start from.
b) create your main platform file as
diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
index 85b709257918..955fbcd19ce9 100644
--- a/Documentation/arch/riscv/hwprobe.rst
+++ b/Documentation/arch/riscv/hwprobe.rst
@@ -239,6 +239,9 @@ The following keys are defined:
ratified in commit 98918c844281 ("Merge pull request #1217 from
riscv/zawrs") of riscv-isa-manual.
+ * :c:macro:`RISCV_HWPROBE_EXT_SUPM`: The Supm extension is supported as
+ defined in version 1.0 of the RISC-V Pointer Masking extensions.
+
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: Deprecated. Returns similar values to
:c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was
mistakenly classified as a bitmask rather than a value.
@@ -274,3 +277,19 @@ The following keys are defined:
represent the highest userspace virtual address usable.
* :c:macro:`RISCV_HWPROBE_KEY_TIME_CSR_FREQ`: Frequency (in Hz) of `time CSR`.
+
+* :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF`: An enum value describing the
+ performance of misaligned vector accesses on the selected set of processors.
+
+ * :c:macro:`RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN`: The performance of misaligned
+ vector accesses is unknown.
+
+ * :c:macro:`RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW`: 32-bit misaligned accesses using vector
+ registers are slower than the equivalent quantity of byte accesses via vector registers.
+ Misaligned accesses may be supported directly in hardware, or trapped and emulated by software.
+
+ * :c:macro:`RISCV_HWPROBE_MISALIGNED_VECTOR_FAST`: 32-bit misaligned accesses using vector
+ registers are faster than the equivalent quantity of byte accesses via vector registers.
+
+ * :c:macro:`RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED`: Misaligned vector accesses are
+ not supported at all and will generate a misaligned address fault.
diff --git a/Documentation/arch/riscv/uabi.rst b/Documentation/arch/riscv/uabi.rst
index 2b420bab0527..243e40062e34 100644
--- a/Documentation/arch/riscv/uabi.rst
+++ b/Documentation/arch/riscv/uabi.rst
@@ -68,3 +68,19 @@ Misaligned accesses
Misaligned scalar accesses are supported in userspace, but they may perform
poorly. Misaligned vector accesses are only supported if the Zicclsm extension
is supported.
+
+Pointer masking
+---------------
+
+Support for pointer masking in userspace (the Supm extension) is provided via
+the ``PR_SET_TAGGED_ADDR_CTRL`` and ``PR_GET_TAGGED_ADDR_CTRL`` ``prctl()``
+operations. Pointer masking is disabled by default. To enable it, userspace
+must call ``PR_SET_TAGGED_ADDR_CTRL`` with the ``PR_PMLEN`` field set to the
+number of mask/tag bits needed by the application. ``PR_PMLEN`` is interpreted
+as a lower bound; if the kernel is unable to satisfy the request, the
+``PR_SET_TAGGED_ADDR_CTRL`` operation will fail. The actual number of tag bits
+is returned in ``PR_PMLEN`` by the ``PR_GET_TAGGED_ADDR_CTRL`` operation.
+
+Additionally, when pointer masking is enabled (``PR_PMLEN`` is greater than 0),
+a tagged address ABI is supported, with the same interface and behavior as
+documented for AArch64 (Documentation/arch/arm64/tagged-address-abi.rst).
diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 1e499ecf5f4e..2fd917638e42 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -4,8 +4,9 @@
AMD HSMP interface
============================================
-Newer Fam19h EPYC server line of processors from AMD support system
-management functionality via HSMP (Host System Management Port).
+Newer Fam19h(model 0x00-0x1f, 0x30-0x3f, 0x90-0x9f, 0xa0-0xaf),
+Fam1Ah(model 0x00-0x1f) EPYC server line of processors from AMD support
+system management functionality via HSMP (Host System Management Port).
The Host System Management Port (HSMP) is an interface to provide
OS-level software with access to system management functions via a
@@ -16,14 +17,25 @@ More details on the interface can be found in chapter
Eg: https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/55898_B1_pub_0_50.zip
-HSMP interface is supported on EPYC server CPU models only.
+HSMP interface is supported on EPYC line of server CPUs and MI300A (APU).
HSMP device
============================================
-amd_hsmp driver under the drivers/platforms/x86/ creates miscdevice
-/dev/hsmp to let user space programs run hsmp mailbox commands.
+amd_hsmp driver under drivers/platforms/x86/amd/hsmp/ has separate driver files
+for ACPI object based probing, platform device based probing and for the common
+code for these two drivers.
+
+Kconfig option CONFIG_AMD_HSMP_PLAT compiles plat.c and creates amd_hsmp.ko.
+Kconfig option CONFIG_AMD_HSMP_ACPI compiles acpi.c and creates hsmp_acpi.ko.
+Selecting any of these two configs automatically selects CONFIG_AMD_HSMP. This
+compiles common code hsmp.c and creates hsmp_common.ko module.
+
+Both the ACPI and plat drivers create the miscdevice /dev/hsmp to let
+user space programs run hsmp mailbox commands.
+
+The ACPI object format supported by the driver is defined below.
$ ls -al /dev/hsmp
crw-r--r-- 1 root root 10, 123 Jan 21 21:41 /dev/hsmp
@@ -59,6 +71,51 @@ Note: lseek() is not supported as entire metrics table is read.
Metrics table definitions will be documented as part of Public PPR.
The same is defined in the amd_hsmp.h header.
+ACPI device object format
+=========================
+The ACPI object format expected from the amd_hsmp driver
+for socket with ID00 is given below::
+
+ Device(HSMP)
+ {
+ Name(_HID, "AMDI0097")
+ Name(_UID, "ID00")
+ Name(HSE0, 0x00000001)
+ Name(RBF0, ResourceTemplate()
+ {
+ Memory32Fixed(ReadWrite, 0xxxxxxx, 0x00100000)
+ })
+ Method(_CRS, 0, NotSerialized)
+ {
+ Return(RBF0)
+ }
+ Method(_STA, 0, NotSerialized)
+ {
+ If(LEqual(HSE0, One))
+ {
+ Return(0x0F)
+ }
+ Else
+ {
+ Return(Zero)
+ }
+ }
+ Name(_DSD, Package(2)
+ {
+ Buffer(0x10)
+ {
+ 0x9D, 0x61, 0x4D, 0xB7, 0x07, 0x57, 0xBD, 0x48,
+ 0xA6, 0x9F, 0x4E, 0xA2, 0x87, 0x1F, 0xC2, 0xF6
+ },
+ Package(3)
+ {
+ Package(2) {"MsgIdOffset", 0x00010934},
+ Package(2) {"MsgRspOffset", 0x00010980},
+ Package(2) {"MsgArgOffset", 0x000109E0}
+ }
+ })
+ }
+
An example
==========
diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
index 4fd492cb4970..ad2d8ddad27f 100644
--- a/Documentation/arch/x86/boot.rst
+++ b/Documentation/arch/x86/boot.rst
@@ -896,10 +896,19 @@ Offset/size: 0x260/4
The kernel runtime start address is determined by the following algorithm::
- if (relocatable_kernel)
- runtime_start = align_up(load_address, kernel_alignment)
- else
- runtime_start = pref_address
+ if (relocatable_kernel) {
+ if (load_address < pref_address)
+ load_address = pref_address;
+ runtime_start = align_up(load_address, kernel_alignment);
+ } else {
+ runtime_start = pref_address;
+ }
+
+Hence the necessary memory window location and size can be estimated by
+a boot loader as::
+
+ memory_window_start = runtime_start;
+ memory_window_size = init_size;
============ ===============
Field name: handover_offset
diff --git a/Documentation/arch/x86/buslock.rst b/Documentation/arch/x86/buslock.rst
index 4c5a4822eeb7..31f1bfdff16f 100644
--- a/Documentation/arch/x86/buslock.rst
+++ b/Documentation/arch/x86/buslock.rst
@@ -26,7 +26,8 @@ Detection
=========
Intel processors may support either or both of the following hardware
-mechanisms to detect split locks and bus locks.
+mechanisms to detect split locks and bus locks. Some AMD processors also
+support bus lock detect.
#AC exception for split lock detection
--------------------------------------
diff --git a/Documentation/arch/x86/x86_64/boot-options.rst b/Documentation/arch/x86/x86_64/boot-options.rst
index 98d4805f0823..d69e3cfbdba5 100644
--- a/Documentation/arch/x86/x86_64/boot-options.rst
+++ b/Documentation/arch/x86/x86_64/boot-options.rst
@@ -305,3 +305,8 @@ The available options are:
debug
Enable debug messages.
+
+ nosnp
+ Do not enable SEV-SNP (applies to host/hypervisor only). Setting
+ 'nosnp' avoids the RMP check overhead in memory accesses when
+ users do not want to run SEV-SNP guests.
diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
index 35e5e18c83d0..f2db178b353f 100644
--- a/Documentation/arch/x86/x86_64/mm.rst
+++ b/Documentation/arch/x86/x86_64/mm.rst
@@ -29,15 +29,27 @@ Complete virtual memory map with 4-level page tables
Start addr | Offset | End addr | Size | VM area description
========================================================================================================================
| | | |
- 0000000000000000 | 0 | 00007fffffffffff | 128 TB | user-space virtual memory, different per mm
+ 0000000000000000 | 0 | 00007fffffffefff | ~128 TB | user-space virtual memory, different per mm
+ 00007ffffffff000 | ~128 TB | 00007fffffffffff | 4 kB | ... guard hole
__________________|____________|__________________|_________|___________________________________________________________
| | | |
- 0000800000000000 | +128 TB | ffff7fffffffffff | ~16M TB | ... huge, almost 64 bits wide hole of non-canonical
- | | | | virtual memory addresses up to the -128 TB
+ 0000800000000000 | +128 TB | 7fffffffffffffff | ~8 EB | ... huge, almost 63 bits wide hole of non-canonical
+ | | | | virtual memory addresses up to the -8 EB
| | | | starting offset of kernel mappings.
+ | | | |
+ | | | | LAM relaxes canonicallity check allowing to create aliases
+ | | | | for userspace memory here.
__________________|____________|__________________|_________|___________________________________________________________
|
| Kernel-space virtual memory, shared between all processes:
+ __________________|____________|__________________|_________|___________________________________________________________
+ | | | |
+ 8000000000000000 | -8 EB | ffff7fffffffffff | ~8 EB | ... huge, almost 63 bits wide hole of non-canonical
+ | | | | virtual memory addresses up to the -128 TB
+ | | | | starting offset of kernel mappings.
+ | | | |
+ | | | | LAM_SUP relaxes canonicallity check allowing to create
+ | | | | aliases for kernel memory here.
____________________________________________________________|___________________________________________________________
| | | |
ffff800000000000 | -128 TB | ffff87ffffffffff | 8 TB | ... guard hole, also reserved for hypervisor
@@ -88,16 +100,27 @@ Complete virtual memory map with 5-level page tables
Start addr | Offset | End addr | Size | VM area description
========================================================================================================================
| | | |
- 0000000000000000 | 0 | 00ffffffffffffff | 64 PB | user-space virtual memory, different per mm
+ 0000000000000000 | 0 | 00fffffffffff000 | ~64 PB | user-space virtual memory, different per mm
+ 00fffffffffff000 | ~64 PB | 00ffffffffffffff | 4 kB | ... guard hole
__________________|____________|__________________|_________|___________________________________________________________
| | | |
- 0100000000000000 | +64 PB | feffffffffffffff | ~16K PB | ... huge, still almost 64 bits wide hole of non-canonical
- | | | | virtual memory addresses up to the -64 PB
+ 0100000000000000 | +64 PB | 7fffffffffffffff | ~8 EB | ... huge, almost 63 bits wide hole of non-canonical
+ | | | | virtual memory addresses up to the -8EB TB
| | | | starting offset of kernel mappings.
+ | | | |
+ | | | | LAM relaxes canonicallity check allowing to create aliases
+ | | | | for userspace memory here.
__________________|____________|__________________|_________|___________________________________________________________
|
| Kernel-space virtual memory, shared between all processes:
____________________________________________________________|___________________________________________________________
+ 8000000000000000 | -8 EB | feffffffffffffff | ~8 EB | ... huge, almost 63 bits wide hole of non-canonical
+ | | | | virtual memory addresses up to the -64 PB
+ | | | | starting offset of kernel mappings.
+ | | | |
+ | | | | LAM_SUP relaxes canonicallity check allowing to create
+ | | | | aliases for kernel memory here.
+ ____________________________________________________________|___________________________________________________________
| | | |
ff00000000000000 | -64 PB | ff0fffffffffffff | 4 PB | ... guard hole, also reserved for hypervisor
ff10000000000000 | -60 PB | ff10ffffffffffff | 0.25 PB | LDT remap for PTI
diff --git a/Documentation/block/cmdline-partition.rst b/Documentation/block/cmdline-partition.rst
index 530bedff548a..526ba201dddc 100644
--- a/Documentation/block/cmdline-partition.rst
+++ b/Documentation/block/cmdline-partition.rst
@@ -39,13 +39,16 @@ blkdevparts=<blkdev-def>[;<blkdev-def>]
create a link to block device partition with the name "PARTNAME".
User space application can access partition by partition name.
+ro
+ read-only. Flag the partition as read-only.
+
Example:
eMMC disk names are "mmcblk0" and "mmcblk0boot0".
bootargs::
- 'blkdevparts=mmcblk0:1G(data0),1G(data1),-;mmcblk0boot0:1m(boot),-(kernel)'
+ 'blkdevparts=mmcblk0:1G(data0),1G(data1),-;mmcblk0boot0:1m(boot)ro,-(kernel)'
dmesg::
diff --git a/Documentation/block/ublk.rst b/Documentation/block/ublk.rst
index ff74b3ec4a98..51665a3e6a50 100644
--- a/Documentation/block/ublk.rst
+++ b/Documentation/block/ublk.rst
@@ -199,24 +199,36 @@ managing and controlling ublk devices with help of several control commands:
- user recovery feature description
- Two new features are added for user recovery: ``UBLK_F_USER_RECOVERY`` and
- ``UBLK_F_USER_RECOVERY_REISSUE``.
-
- With ``UBLK_F_USER_RECOVERY`` set, after one ubq_daemon(ublk server's io
+ Three new features are added for user recovery: ``UBLK_F_USER_RECOVERY``,
+ ``UBLK_F_USER_RECOVERY_REISSUE``, and ``UBLK_F_USER_RECOVERY_FAIL_IO``. To
+ enable recovery of ublk devices after the ublk server exits, the ublk server
+ should specify the ``UBLK_F_USER_RECOVERY`` flag when creating the device. The
+ ublk server may additionally specify at most one of
+ ``UBLK_F_USER_RECOVERY_REISSUE`` and ``UBLK_F_USER_RECOVERY_FAIL_IO`` to
+ modify how I/O is handled while the ublk server is dying/dead (this is called
+ the ``nosrv`` case in the driver code).
+
+ With just ``UBLK_F_USER_RECOVERY`` set, after one ubq_daemon(ublk server's io
handler) is dying, ublk does not delete ``/dev/ublkb*`` during the whole
recovery stage and ublk device ID is kept. It is ublk server's
responsibility to recover the device context by its own knowledge.
Requests which have not been issued to userspace are requeued. Requests
which have been issued to userspace are aborted.
- With ``UBLK_F_USER_RECOVERY_REISSUE`` set, after one ubq_daemon(ublk
- server's io handler) is dying, contrary to ``UBLK_F_USER_RECOVERY``,
+ With ``UBLK_F_USER_RECOVERY_REISSUE`` additionally set, after one ubq_daemon
+ (ublk server's io handler) is dying, contrary to ``UBLK_F_USER_RECOVERY``,
requests which have been issued to userspace are requeued and will be
re-issued to the new process after handling ``UBLK_CMD_END_USER_RECOVERY``.
``UBLK_F_USER_RECOVERY_REISSUE`` is designed for backends who tolerate
double-write since the driver may issue the same I/O request twice. It
might be useful to a read-only FS or a VM backend.
+ With ``UBLK_F_USER_RECOVERY_FAIL_IO`` additionally set, after the ublk server
+ exits, requests which have issued to userspace are failed, as are any
+ subsequently issued requests. Applications continuously issuing I/O against
+ devices with this flag set will see a stream of I/O errors until a new ublk
+ server recovers the device.
+
Unprivileged ublk device is supported by passing ``UBLK_F_UNPRIVILEGED_DEV``.
Once the flag is set, all control commands can be sent by unprivileged
user. Except for command of ``UBLK_CMD_ADD_DEV``, permission check on
diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
index 93060283b6fd..2478cef758f8 100644
--- a/Documentation/bpf/btf.rst
+++ b/Documentation/bpf/btf.rst
@@ -835,7 +835,7 @@ section named by ``btf_ext_info_sec->sec_name_off``.
See :ref:`Documentation/bpf/llvm_reloc.rst <btf-co-re-relocations>`
for more information on CO-RE relocations.
-4.2 .BTF_ids section
+4.3 .BTF_ids section
--------------------
The .BTF_ids section encodes BTF ID values that are used within the kernel.
@@ -896,6 +896,81 @@ and is used as a filter when resolving the BTF ID value.
All the BTF ID lists and sets are compiled in the .BTF_ids section and
resolved during the linking phase of kernel build by ``resolve_btfids`` tool.
+4.4 .BTF.base section
+---------------------
+Split BTF - where the .BTF section only contains types not in the associated
+base .BTF section - is an extremely efficient way to encode type information
+for kernel modules, since they generally consist of a few module-specific
+types along with a large set of shared kernel types. The former are encoded
+in split BTF, while the latter are encoded in base BTF, resulting in more
+compact representations. A type in split BTF that refers to a type in
+base BTF refers to it using its base BTF ID, and split BTF IDs start
+at last_base_BTF_ID + 1.
+
+The downside of this approach however is that this makes the split BTF
+somewhat brittle - when the base BTF changes, base BTF ID references are
+no longer valid and the split BTF itself becomes useless. The role of the
+.BTF.base section is to make split BTF more resilient for cases where
+the base BTF may change, as is the case for kernel modules not built every
+time the kernel is for example. .BTF.base contains named base types; INTs,
+FLOATs, STRUCTs, UNIONs, ENUM[64]s and FWDs. INTs and FLOATs are fully
+described in .BTF.base sections, while composite types like structs
+and unions are not fully defined - the .BTF.base type simply serves as
+a description of the type the split BTF referred to, so structs/unions
+have 0 members in the .BTF.base section. ENUM[64]s are similarly recorded
+with 0 members. Any other types are added to the split BTF. This
+distillation process then leaves us with a .BTF.base section with
+such minimal descriptions of base types and .BTF split section which refers
+to those base types. Later, we can relocate the split BTF using both the
+information stored in the .BTF.base section and the new .BTF base; the type
+information in the .BTF.base section allows us to update the split BTF
+references to point at the corresponding new base BTF IDs.
+
+BTF relocation happens on kernel module load when a kernel module has a
+.BTF.base section, and libbpf also provides a btf__relocate() API to
+accomplish this.
+
+As an example consider the following base BTF::
+
+ [1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
+ [2] STRUCT 'foo' size=8 vlen=2
+ 'f1' type_id=1 bits_offset=0
+ 'f2' type_id=1 bits_offset=32
+
+...and associated split BTF::
+
+ [3] PTR '(anon)' type_id=2
+
+i.e. split BTF describes a pointer to struct foo { int f1; int f2 };
+
+.BTF.base will consist of::
+
+ [1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
+ [2] STRUCT 'foo' size=8 vlen=0
+
+If we relocate the split BTF later using the following new base BTF::
+
+ [1] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
+ [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
+ [3] STRUCT 'foo' size=8 vlen=2
+ 'f1' type_id=2 bits_offset=0
+ 'f2' type_id=2 bits_offset=32
+
+...we can use our .BTF.base description to know that the split BTF reference
+is to struct foo, and relocation results in new split BTF::
+
+ [4] PTR '(anon)' type_id=3
+
+Note that we had to update BTF ID and start BTF ID for the split BTF.
+
+So we see how .BTF.base plays the role of facilitating later relocation,
+leading to more resilient split BTF.
+
+.BTF.base sections will be generated automatically for out-of-tree kernel module
+builds - i.e. where KBUILD_EXTMOD is set (as it would be for "make M=path/2/mod"
+cases). .BTF.base generation requires pahole support for the "distilled_base"
+BTF feature; this is available in pahole v1.28 and later.
+
5. Using BTF
============
diff --git a/Documentation/bpf/verifier.rst b/Documentation/bpf/verifier.rst
index d23761540002..95e6f80a407e 100644
--- a/Documentation/bpf/verifier.rst
+++ b/Documentation/bpf/verifier.rst
@@ -507,7 +507,7 @@ Notes:
from the parent state to the current state.
* Details about REG_LIVE_READ32 are omitted.
-
+
* Function ``propagate_liveness()`` (see section :ref:`read_marks_for_cache_hits`)
might override the first parent link. Please refer to the comments in the
``propagate_liveness()`` and ``mark_reg_read()`` source code for further
@@ -571,7 +571,7 @@ works::
are considered equivalent.
.. _read_marks_for_cache_hits:
-
+
Read marks propagation for cache hits
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/core-api/cpu_hotplug.rst b/Documentation/core-api/cpu_hotplug.rst
index a21dbf261be7..e1b0eeabbb5e 100644
--- a/Documentation/core-api/cpu_hotplug.rst
+++ b/Documentation/core-api/cpu_hotplug.rst
@@ -616,7 +616,7 @@ ONLINE section for notifications on online and offline operation::
....
cpuhp_remove_instance(state, &inst2->node);
....
- remove_multi_state(state);
+ cpuhp_remove_multi_state(state);
Testing of hotplug states
diff --git a/Documentation/core-api/gfp_mask-from-fs-io.rst b/Documentation/core-api/gfp_mask-from-fs-io.rst
index e7c32a8de126..858b2fbcb36c 100644
--- a/Documentation/core-api/gfp_mask-from-fs-io.rst
+++ b/Documentation/core-api/gfp_mask-from-fs-io.rst
@@ -55,14 +55,16 @@ scope.
What about __vmalloc(GFP_NOFS)
==============================
-vmalloc doesn't support GFP_NOFS semantic because there are hardcoded
-GFP_KERNEL allocations deep inside the allocator which are quite non-trivial
-to fix up. That means that calling ``vmalloc`` with GFP_NOFS/GFP_NOIO is
-almost always a bug. The good news is that the NOFS/NOIO semantic can be
-achieved by the scope API.
+Since v5.17, and specifically after the commit 451769ebb7e79 ("mm/vmalloc:
+alloc GFP_NO{FS,IO} for vmalloc"), GFP_NOFS/GFP_NOIO are now supported in
+``[k]vmalloc`` by implicitly using scope API.
+
+In earlier kernels ``vmalloc`` didn't support GFP_NOFS semantic because there
+were hardcoded GFP_KERNEL allocations deep inside the allocator. That means
+that calling ``vmalloc`` with GFP_NOFS/GFP_NOIO was almost always a bug.
In the ideal world, upper layers should already mark dangerous contexts
-and so no special care is required and vmalloc should be called without
-any problems. Sometimes if the context is not really clear or there are
-layering violations then the recommended way around that is to wrap ``vmalloc``
-by the scope API with a comment explaining the problem.
+and so no special care is required and ``vmalloc`` should be called without any
+problems. Sometimes if the context is not really clear or there are layering
+violations then the recommended way around that (on pre-v5.17 kernels) is to
+wrap ``vmalloc`` by the scope API with a comment explaining the problem.
diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index 6a875743dd4b..563b8fc0002f 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -52,6 +52,7 @@ Library functionality that is used throughout the kernel.
wrappers/atomic_bitops
floating-point
union_find
+ min_heap
Low level entry and exit
========================
diff --git a/Documentation/core-api/min_heap.rst b/Documentation/core-api/min_heap.rst
new file mode 100644
index 000000000000..0c636c8b7aa5
--- /dev/null
+++ b/Documentation/core-api/min_heap.rst
@@ -0,0 +1,300 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+Min Heap API
+============
+
+Introduction
+============
+
+The Min Heap API provides a set of functions and macros for managing min-heaps
+in the Linux kernel. A min-heap is a binary tree structure where the value of
+each node is less than or equal to the values of its children, ensuring that
+the smallest element is always at the root.
+
+This document provides a guide to the Min Heap API, detailing how to define and
+use min-heaps. Users should not directly call functions with **__min_heap_*()**
+prefixes, but should instead use the provided macro wrappers.
+
+In addition to the standard version of the functions, the API also includes a
+set of inline versions for performance-critical scenarios. These inline
+functions have the same names as their non-inline counterparts but include an
+**_inline** suffix. For example, **__min_heap_init_inline** and its
+corresponding macro wrapper **min_heap_init_inline**. The inline versions allow
+custom comparison and swap functions to be called directly, rather than through
+indirect function calls. This can significantly reduce overhead, especially
+when CONFIG_MITIGATION_RETPOLINE is enabled, as indirect function calls become
+more expensive. As with the non-inline versions, it is important to use the
+macro wrappers for inline functions instead of directly calling the functions
+themselves.
+
+Data Structures
+===============
+
+Min-Heap Definition
+-------------------
+
+The core data structure for representing a min-heap is defined using the
+**MIN_HEAP_PREALLOCATED** and **DEFINE_MIN_HEAP** macros. These macros allow
+you to define a min-heap with a preallocated buffer or dynamically allocated
+memory.
+
+Example:
+
+.. code-block:: c
+
+ #define MIN_HEAP_PREALLOCATED(_type, _name, _nr)
+ struct _name {
+ int nr; /* Number of elements in the heap */
+ int size; /* Maximum number of elements that can be held */
+ _type *data; /* Pointer to the heap data */
+ _type preallocated[_nr]; /* Static preallocated array */
+ }
+
+ #define DEFINE_MIN_HEAP(_type, _name) MIN_HEAP_PREALLOCATED(_type, _name, 0)
+
+A typical heap structure will include a counter for the number of elements
+(`nr`), the maximum capacity of the heap (`size`), and a pointer to an array of
+elements (`data`). Optionally, you can specify a static array for preallocated
+heap storage using **MIN_HEAP_PREALLOCATED**.
+
+Min Heap Callbacks
+------------------
+
+The **struct min_heap_callbacks** provides customization options for ordering
+elements in the heap and swapping them. It contains two function pointers:
+
+.. code-block:: c
+
+ struct min_heap_callbacks {
+ bool (*less)(const void *lhs, const void *rhs, void *args);
+ void (*swp)(void *lhs, void *rhs, void *args);
+ };
+
+- **less** is the comparison function used to establish the order of elements.
+- **swp** is a function for swapping elements in the heap. If swp is set to
+ NULL, the default swap function will be used, which swaps the elements based on their size
+
+Macro Wrappers
+==============
+
+The following macro wrappers are provided for interacting with the heap in a
+user-friendly manner. Each macro corresponds to a function that operates on the
+heap, and they abstract away direct calls to internal functions.
+
+Each macro accepts various parameters that are detailed below.
+
+Heap Initialization
+--------------------
+
+.. code-block:: c
+
+ min_heap_init(heap, data, size);
+
+- **heap**: A pointer to the min-heap structure to be initialized.
+- **data**: A pointer to the buffer where the heap elements will be stored. If
+ `NULL`, the preallocated buffer within the heap structure will be used.
+- **size**: The maximum number of elements the heap can hold.
+
+This macro initializes the heap, setting its initial state. If `data` is
+`NULL`, the preallocated memory inside the heap structure will be used for
+storage. Otherwise, the user-provided buffer is used. The operation is **O(1)**.
+
+**Inline Version:** min_heap_init_inline(heap, data, size)
+
+Accessing the Top Element
+-------------------------
+
+.. code-block:: c
+
+ element = min_heap_peek(heap);
+
+- **heap**: A pointer to the min-heap from which to retrieve the smallest
+ element.
+
+This macro returns a pointer to the smallest element (the root) of the heap, or
+`NULL` if the heap is empty. The operation is **O(1)**.
+
+**Inline Version:** min_heap_peek_inline(heap)
+
+Heap Insertion
+--------------
+
+.. code-block:: c
+
+ success = min_heap_push(heap, element, callbacks, args);
+
+- **heap**: A pointer to the min-heap into which the element should be inserted.
+- **element**: A pointer to the element to be inserted into the heap.
+- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
+ `less` and `swp` functions.
+- **args**: Optional arguments passed to the `less` and `swp` functions.
+
+This macro inserts an element into the heap. It returns `true` if the insertion
+was successful and `false` if the heap is full. The operation is **O(log n)**.
+
+**Inline Version:** min_heap_push_inline(heap, element, callbacks, args)
+
+Heap Removal
+------------
+
+.. code-block:: c
+
+ success = min_heap_pop(heap, callbacks, args);
+
+- **heap**: A pointer to the min-heap from which to remove the smallest element.
+- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
+ `less` and `swp` functions.
+- **args**: Optional arguments passed to the `less` and `swp` functions.
+
+This macro removes the smallest element (the root) from the heap. It returns
+`true` if the element was successfully removed, or `false` if the heap is
+empty. The operation is **O(log n)**.
+
+**Inline Version:** min_heap_pop_inline(heap, callbacks, args)
+
+Heap Maintenance
+----------------
+
+You can use the following macros to maintain the heap's structure:
+
+.. code-block:: c
+
+ min_heap_sift_down(heap, pos, callbacks, args);
+
+- **heap**: A pointer to the min-heap.
+- **pos**: The index from which to start sifting down.
+- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
+ `less` and `swp` functions.
+- **args**: Optional arguments passed to the `less` and `swp` functions.
+
+This macro restores the heap property by moving the element at the specified
+index (`pos`) down the heap until it is in the correct position. The operation
+is **O(log n)**.
+
+**Inline Version:** min_heap_sift_down_inline(heap, pos, callbacks, args)
+
+.. code-block:: c
+
+ min_heap_sift_up(heap, idx, callbacks, args);
+
+- **heap**: A pointer to the min-heap.
+- **idx**: The index of the element to sift up.
+- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
+ `less` and `swp` functions.
+- **args**: Optional arguments passed to the `less` and `swp` functions.
+
+This macro restores the heap property by moving the element at the specified
+index (`idx`) up the heap. The operation is **O(log n)**.
+
+**Inline Version:** min_heap_sift_up_inline(heap, idx, callbacks, args)
+
+.. code-block:: c
+
+ min_heapify_all(heap, callbacks, args);
+
+- **heap**: A pointer to the min-heap.
+- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
+ `less` and `swp` functions.
+- **args**: Optional arguments passed to the `less` and `swp` functions.
+
+This macro ensures that the entire heap satisfies the heap property. It is
+called when the heap is built from scratch or after many modifications. The
+operation is **O(n)**.
+
+**Inline Version:** min_heapify_all_inline(heap, callbacks, args)
+
+Removing Specific Elements
+--------------------------
+
+.. code-block:: c
+
+ success = min_heap_del(heap, idx, callbacks, args);
+
+- **heap**: A pointer to the min-heap.
+- **idx**: The index of the element to delete.
+- **callbacks**: A pointer to a `struct min_heap_callbacks` providing the
+ `less` and `swp` functions.
+- **args**: Optional arguments passed to the `less` and `swp` functions.
+
+This macro removes an element at the specified index (`idx`) from the heap and
+restores the heap property. The operation is **O(log n)**.
+
+**Inline Version:** min_heap_del_inline(heap, idx, callbacks, args)
+
+Other Utilities
+===============
+
+- **min_heap_full(heap)**: Checks whether the heap is full.
+ Complexity: **O(1)**.
+
+.. code-block:: c
+
+ bool full = min_heap_full(heap);
+
+- `heap`: A pointer to the min-heap to check.
+
+This macro returns `true` if the heap is full, otherwise `false`.
+
+**Inline Version:** min_heap_full_inline(heap)
+
+- **min_heap_empty(heap)**: Checks whether the heap is empty.
+ Complexity: **O(1)**.
+
+.. code-block:: c
+
+ bool empty = min_heap_empty(heap);
+
+- `heap`: A pointer to the min-heap to check.
+
+This macro returns `true` if the heap is empty, otherwise `false`.
+
+**Inline Version:** min_heap_empty_inline(heap)
+
+Example Usage
+=============
+
+An example usage of the min-heap API would involve defining a heap structure,
+initializing it, and inserting and removing elements as needed.
+
+.. code-block:: c
+
+ #include <linux/min_heap.h>
+
+ int my_less_function(const void *lhs, const void *rhs, void *args) {
+ return (*(int *)lhs < *(int *)rhs);
+ }
+
+ struct min_heap_callbacks heap_cb = {
+ .less = my_less_function, /* Comparison function for heap order */
+ .swp = NULL, /* Use default swap function */
+ };
+
+ void example_usage(void) {
+ /* Pre-populate the buffer with elements */
+ int buffer[5] = {5, 2, 8, 1, 3};
+ /* Declare a min-heap */
+ DEFINE_MIN_HEAP(int, my_heap);
+
+ /* Initialize the heap with preallocated buffer and size */
+ min_heap_init(&my_heap, buffer, 5);
+
+ /* Build the heap using min_heapify_all */
+ my_heap.nr = 5; /* Set the number of elements in the heap */
+ min_heapify_all(&my_heap, &heap_cb, NULL);
+
+ /* Peek at the top element (should be 1 in this case) */
+ int *top = min_heap_peek(&my_heap);
+ pr_info("Top element: %d\n", *top);
+
+ /* Pop the top element (1) and get the new top (2) */
+ min_heap_pop(&my_heap, &heap_cb, NULL);
+ top = min_heap_peek(&my_heap);
+ pr_info("New top element: %d\n", *top);
+
+ /* Insert a new element (0) and recheck the top */
+ int new_element = 0;
+ min_heap_push(&my_heap, &new_element, &heap_cb, NULL);
+ top = min_heap_peek(&my_heap);
+ pr_info("Top element after insertion: %d\n", *top);
+ }
diff --git a/Documentation/core-api/packing.rst b/Documentation/core-api/packing.rst
index 3ed13bc9a195..821691f23c54 100644
--- a/Documentation/core-api/packing.rst
+++ b/Documentation/core-api/packing.rst
@@ -151,6 +151,77 @@ the more significant 4-byte word.
We always think of our offsets as if there were no quirk, and we translate
them afterwards, before accessing the memory region.
+Note on buffer lengths not multiple of 4
+----------------------------------------
+
+To deal with memory layout quirks where groups of 4 bytes are laid out "little
+endian" relative to each other, but "big endian" within the group itself, the
+concept of groups of 4 bytes is intrinsic to the packing API (not to be
+confused with the memory access, which is performed byte by byte, though).
+
+With buffer lengths not multiple of 4, this means one group will be incomplete.
+Depending on the quirks, this may lead to discontinuities in the bit fields
+accessible through the buffer. The packing API assumes discontinuities were not
+the intention of the memory layout, so it avoids them by effectively logically
+shortening the most significant group of 4 octets to the number of octets
+actually available.
+
+Example with a 31 byte sized buffer given below. Physical buffer offsets are
+implicit, and increase from left to right within a group, and from top to
+bottom within a column.
+
+No quirks:
+
+::
+
+ 31 29 28 | Group 7 (most significant)
+ 27 26 25 24 | Group 6
+ 23 22 21 20 | Group 5
+ 19 18 17 16 | Group 4
+ 15 14 13 12 | Group 3
+ 11 10 9 8 | Group 2
+ 7 6 5 4 | Group 1
+ 3 2 1 0 | Group 0 (least significant)
+
+QUIRK_LSW32_IS_FIRST:
+
+::
+
+ 3 2 1 0 | Group 0 (least significant)
+ 7 6 5 4 | Group 1
+ 11 10 9 8 | Group 2
+ 15 14 13 12 | Group 3
+ 19 18 17 16 | Group 4
+ 23 22 21 20 | Group 5
+ 27 26 25 24 | Group 6
+ 30 29 28 | Group 7 (most significant)
+
+QUIRK_LITTLE_ENDIAN:
+
+::
+
+ 30 28 29 | Group 7 (most significant)
+ 24 25 26 27 | Group 6
+ 20 21 22 23 | Group 5
+ 16 17 18 19 | Group 4
+ 12 13 14 15 | Group 3
+ 8 9 10 11 | Group 2
+ 4 5 6 7 | Group 1
+ 0 1 2 3 | Group 0 (least significant)
+
+QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST:
+
+::
+
+ 0 1 2 3 | Group 0 (least significant)
+ 4 5 6 7 | Group 1
+ 8 9 10 11 | Group 2
+ 12 13 14 15 | Group 3
+ 16 17 18 19 | Group 4
+ 20 21 22 23 | Group 5
+ 24 25 26 27 | Group 6
+ 28 29 30 | Group 7 (most significant)
+
Intended use
------------
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index 14e093da3ccd..ecccc0473da9 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -209,12 +209,17 @@ Struct Resources
::
%pr [mem 0x60000000-0x6fffffff flags 0x2200] or
+ [mem 0x60000000 flags 0x2200] or
[mem 0x0000000060000000-0x000000006fffffff flags 0x2200]
+ [mem 0x0000000060000000 flags 0x2200]
%pR [mem 0x60000000-0x6fffffff pref] or
+ [mem 0x60000000 pref] or
[mem 0x0000000060000000-0x000000006fffffff pref]
+ [mem 0x0000000060000000 pref]
For printing struct resources. The ``R`` and ``r`` specifiers result in a
-printed resource with (R) or without (r) a decoded flags member.
+printed resource with (R) or without (r) a decoded flags member. If start is
+equal to end only print the start value.
Passed by reference.
@@ -231,6 +236,19 @@ width of the CPU data path.
Passed by reference.
+Struct Range
+------------
+
+::
+
+ %pra [range 0x0000000060000000-0x000000006fffffff] or
+ [range 0x0000000060000000]
+
+For printing struct range. struct range holds an arbitrary range of u64
+values. If start is equal to end only print the start value.
+
+Passed by reference.
+
DMA address types dma_addr_t
----------------------------
diff --git a/Documentation/core-api/swiotlb.rst b/Documentation/core-api/swiotlb.rst
index cf06bae44ff8..9e0fe027dd3b 100644
--- a/Documentation/core-api/swiotlb.rst
+++ b/Documentation/core-api/swiotlb.rst
@@ -295,9 +295,9 @@ slot set.
Fourth, the io_tlb_slot array keeps track of any "padding slots" allocated to
meet alloc_align_mask requirements described above. When
-swiotlb_tlb_map_single() allocates bounce buffer space to meet alloc_align_mask
+swiotlb_tbl_map_single() allocates bounce buffer space to meet alloc_align_mask
requirements, it may allocate pre-padding space across zero or more slots. But
-when swiotbl_tlb_unmap_single() is called with the bounce buffer address, the
+when swiotlb_tbl_unmap_single() is called with the bounce buffer address, the
alloc_align_mask value that governed the allocation, and therefore the
allocation of any padding slots, is not known. The "pad_slots" field records
the number of padding slots so that swiotlb_tbl_unmap_single() can free them.
diff --git a/Documentation/core-api/workqueue.rst b/Documentation/core-api/workqueue.rst
index 16f861c9791e..e295835fc116 100644
--- a/Documentation/core-api/workqueue.rst
+++ b/Documentation/core-api/workqueue.rst
@@ -245,8 +245,8 @@ CPU which can be assigned to the work items of a wq. For example, with
at the same time per CPU. This is always a per-CPU attribute, even for
unbound workqueues.
-The maximum limit for ``@max_active`` is 512 and the default value used
-when 0 is specified is 256. These values are chosen sufficiently high
+The maximum limit for ``@max_active`` is 2048 and the default value used
+when 0 is specified is 1024. These values are chosen sufficiently high
such that they are not the limiting factor while providing protection in
runaway cases.
@@ -357,6 +357,11 @@ Guidelines
difference in execution characteristics between using a dedicated wq
and a system wq.
+ Note: If something may generate more than @max_active outstanding
+ work items (do stress test your producers), it may saturate a system
+ wq and potentially lead to deadlock. It should utilize its own
+ dedicated workqueue rather than the system wq.
+
* Unless work items are expected to consume a huge amount of CPU
cycles, using a bound wq is usually beneficial due to the increased
level of locality in wq operations and work item execution.
diff --git a/Documentation/crypto/api-akcipher.rst b/Documentation/crypto/api-akcipher.rst
index 40aa8746e2a1..ca1ecdd4a7d3 100644
--- a/Documentation/crypto/api-akcipher.rst
+++ b/Documentation/crypto/api-akcipher.rst
@@ -8,10 +8,10 @@ Asymmetric Cipher API
---------------------
.. kernel-doc:: include/crypto/akcipher.h
- :doc: Generic Public Key API
+ :doc: Generic Public Key Cipher API
.. kernel-doc:: include/crypto/akcipher.h
- :functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt crypto_akcipher_sign crypto_akcipher_verify
+ :functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt
Asymmetric Cipher Request Handle
--------------------------------
diff --git a/Documentation/crypto/api-sig.rst b/Documentation/crypto/api-sig.rst
new file mode 100644
index 000000000000..aaec18e26d54
--- /dev/null
+++ b/Documentation/crypto/api-sig.rst
@@ -0,0 +1,15 @@
+Asymmetric Signature Algorithm Definitions
+------------------------------------------
+
+.. kernel-doc:: include/crypto/sig.h
+ :functions: sig_alg
+
+Asymmetric Signature API
+------------------------
+
+.. kernel-doc:: include/crypto/sig.h
+ :doc: Generic Public Key Signature API
+
+.. kernel-doc:: include/crypto/sig.h
+ :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_keysize crypto_sig_maxsize crypto_sig_digestsize crypto_sig_sign crypto_sig_verify
+
diff --git a/Documentation/crypto/api.rst b/Documentation/crypto/api.rst
index ff31c30561d4..8b2a90521886 100644
--- a/Documentation/crypto/api.rst
+++ b/Documentation/crypto/api.rst
@@ -10,4 +10,5 @@ Programming Interface
api-digest
api-rng
api-akcipher
+ api-sig
api-kpp
diff --git a/Documentation/crypto/architecture.rst b/Documentation/crypto/architecture.rst
index 646c3380a7ed..15dcd62fd22f 100644
--- a/Documentation/crypto/architecture.rst
+++ b/Documentation/crypto/architecture.rst
@@ -214,6 +214,8 @@ the aforementioned cipher types:
- CRYPTO_ALG_TYPE_AKCIPHER Asymmetric cipher
+- CRYPTO_ALG_TYPE_SIG Asymmetric signature
+
- CRYPTO_ALG_TYPE_PCOMPRESS Enhanced version of
CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression /
decompression instead of performing the operation on one segment
diff --git a/Documentation/dev-tools/autofdo.rst b/Documentation/dev-tools/autofdo.rst
new file mode 100644
index 000000000000..1f0a451e9ccd
--- /dev/null
+++ b/Documentation/dev-tools/autofdo.rst
@@ -0,0 +1,168 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================================
+Using AutoFDO with the Linux kernel
+===================================
+
+This enables AutoFDO build support for the kernel when using
+the Clang compiler. AutoFDO (Auto-Feedback-Directed Optimization)
+is a type of profile-guided optimization (PGO) used to enhance the
+performance of binary executables. It gathers information about the
+frequency of execution of various code paths within a binary using
+hardware sampling. This data is then used to guide the compiler's
+optimization decisions, resulting in a more efficient binary. AutoFDO
+is a powerful optimization technique, and data indicates that it can
+significantly improve kernel performance. It's especially beneficial
+for workloads affected by front-end stalls.
+
+For AutoFDO builds, unlike non-FDO builds, the user must supply a
+profile. Acquiring an AutoFDO profile can be done in several ways.
+AutoFDO profiles are created by converting hardware sampling using
+the "perf" tool. It is crucial that the workload used to create these
+perf files is representative; they must exhibit runtime
+characteristics similar to the workloads that are intended to be
+optimized. Failure to do so will result in the compiler optimizing
+for the wrong objective.
+
+The AutoFDO profile often encapsulates the program's behavior. If the
+performance-critical codes are architecture-independent, the profile
+can be applied across platforms to achieve performance gains. For
+instance, using the profile generated on Intel architecture to build
+a kernel for AMD architecture can also yield performance improvements.
+
+There are two methods for acquiring a representative profile:
+(1) Sample real workloads using a production environment.
+(2) Generate the profile using a representative load test.
+When enabling the AutoFDO build configuration without providing an
+AutoFDO profile, the compiler only modifies the dwarf information in
+the kernel without impacting runtime performance. It's advisable to
+use a kernel binary built with the same AutoFDO configuration to
+collect the perf profile. While it's possible to use a kernel built
+with different options, it may result in inferior performance.
+
+One can collect profiles using AutoFDO build for the previous kernel.
+AutoFDO employs relative line numbers to match the profiles, offering
+some tolerance for source changes. This mode is commonly used in a
+production environment for profile collection.
+
+In a profile collection based on a load test, the AutoFDO collection
+process consists of the following steps:
+
+#. Initial build: The kernel is built with AutoFDO options
+ without a profile.
+
+#. Profiling: The above kernel is then run with a representative
+ workload to gather execution frequency data. This data is
+ collected using hardware sampling, via perf. AutoFDO is most
+ effective on platforms supporting advanced PMU features like
+ LBR on Intel machines.
+
+#. AutoFDO profile generation: Perf output file is converted to
+ the AutoFDO profile via offline tools.
+
+The support requires a Clang compiler LLVM 17 or later.
+
+Preparation
+===========
+
+Configure the kernel with::
+
+ CONFIG_AUTOFDO_CLANG=y
+
+Customization
+=============
+
+The default CONFIG_AUTOFDO_CLANG setting covers kernel space objects for
+AutoFDO builds. One can, however, enable or disable AutoFDO build for
+individual files and directories by adding a line similar to the following
+to the respective kernel Makefile:
+
+- For enabling a single file (e.g. foo.o) ::
+
+ AUTOFDO_PROFILE_foo.o := y
+
+- For enabling all files in one directory ::
+
+ AUTOFDO_PROFILE := y
+
+- For disabling one file ::
+
+ AUTOFDO_PROFILE_foo.o := n
+
+- For disabling all files in one directory ::
+
+ AUTOFDO_PROFILE := n
+
+Workflow
+========
+
+Here is an example workflow for AutoFDO kernel:
+
+1) Build the kernel on the host machine with LLVM enabled,
+ for example, ::
+
+ $ make menuconfig LLVM=1
+
+ Turn on AutoFDO build config::
+
+ CONFIG_AUTOFDO_CLANG=y
+
+ With a configuration that with LLVM enabled, use the following command::
+
+ $ scripts/config -e AUTOFDO_CLANG
+
+ After getting the config, build with ::
+
+ $ make LLVM=1
+
+2) Install the kernel on the test machine.
+
+3) Run the load tests. The '-c' option in perf specifies the sample
+ event period. We suggest using a suitable prime number, like 500009,
+ for this purpose.
+
+ - For Intel platforms::
+
+ $ perf record -e BR_INST_RETIRED.NEAR_TAKEN:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+ - For AMD platforms:
+
+ The supported systems are: Zen3 with BRS, or Zen4 with amd_lbr_v2. To check,
+
+ For Zen3::
+
+ $ cat proc/cpuinfo | grep " brs"
+
+ For Zen4::
+
+ $ cat proc/cpuinfo | grep amd_lbr_v2
+
+ The following command generated the perf data file::
+
+ $ perf record --pfm-events RETIRED_TAKEN_BRANCH_INSTRUCTIONS:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+4) (Optional) Download the raw perf file to the host machine.
+
+5) To generate an AutoFDO profile, two offline tools are available:
+ create_llvm_prof and llvm_profgen. The create_llvm_prof tool is part
+ of the AutoFDO project and can be found on GitHub
+ (https://github.com/google/autofdo), version v0.30.1 or later.
+ The llvm_profgen tool is included in the LLVM compiler itself. It's
+ important to note that the version of llvm_profgen doesn't need to match
+ the version of Clang. It needs to be the LLVM 19 release of Clang
+ or later, or just from the LLVM trunk. ::
+
+ $ llvm-profgen --kernel --binary=<vmlinux> --perfdata=<perf_file> -o <profile_file>
+
+ or ::
+
+ $ create_llvm_prof --binary=<vmlinux> --profile=<perf_file> --format=extbinary --out=<profile_file>
+
+ Note that multiple AutoFDO profile files can be merged into one via::
+
+ $ llvm-profdata merge -o <profile_file> <profile_1> <profile_2> ... <profile_n>
+
+6) Rebuild the kernel using the AutoFDO profile file with the same config as step 1,
+ (Note CONFIG_AUTOFDO_CLANG needs to be enabled)::
+
+ $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<profile_file>
diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst
index a9fac978a525..abb3ff682076 100644
--- a/Documentation/dev-tools/checkpatch.rst
+++ b/Documentation/dev-tools/checkpatch.rst
@@ -470,8 +470,6 @@ API usage
usleep_range() should be preferred over udelay(). The proper way of
using usleep_range() is mentioned in the kernel docs.
- See: https://www.kernel.org/doc/html/latest/timers/timers-howto.html#delays-information-on-the-various-kernel-delay-sleep-mechanisms
-
Comments
--------
diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
index 535ce126fb4f..6e70a1e9a3c0 100644
--- a/Documentation/dev-tools/coccinelle.rst
+++ b/Documentation/dev-tools/coccinelle.rst
@@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
- Your directory from which spatch is called is processed next
- The directory provided with the ``--dir`` option is processed last, if used
-Since coccicheck runs through make, it naturally runs from the kernel
-proper dir; as such the second rule above would be implied for picking up a
-.cocciconfig when using ``make coccicheck``.
-
``make coccicheck`` also supports using M= targets. If you do not supply
any M= target, it is assumed you want to target the entire kernel.
The kernel coccicheck script has::
- if [ "$KBUILD_EXTMOD" = "" ] ; then
- OPTIONS="--dir $srctree $COCCIINCLUDE"
- else
- OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
- fi
-
-KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
-the spatch ``--dir`` argument is used, as such third rule applies when whether
-M= is used or not, and when M= is used the target directory can have its own
-.cocciconfig file. When M= is not passed as an argument to coccicheck the
-target directory is the same as the directory from where spatch was called.
+ OPTIONS="--dir $srcroot $COCCIINCLUDE"
+
+Here, $srcroot refers to the source directory of the target: it points to the
+external module's source directory when M= used, and otherwise, to the kernel
+source directory. The third rule ensures the spatch reads the .cocciconfig from
+the target directory, allowing external modules to have their own .cocciconfig
+file.
If not using the kernel's coccicheck target, keep the above precedence
order logic of .cocciconfig reading. If using the kernel's coccicheck target,
diff --git a/Documentation/dev-tools/gcov.rst b/Documentation/dev-tools/gcov.rst
index dbd26b02ff3c..075df6a4598d 100644
--- a/Documentation/dev-tools/gcov.rst
+++ b/Documentation/dev-tools/gcov.rst
@@ -23,7 +23,7 @@ Possible uses:
associated code is never run?)
.. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
-.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php
+.. _lcov: https://github.com/linux-test-project/lcov
Preparation
diff --git a/Documentation/dev-tools/index.rst b/Documentation/dev-tools/index.rst
index 53d4d124f9c5..3c0ac08b2709 100644
--- a/Documentation/dev-tools/index.rst
+++ b/Documentation/dev-tools/index.rst
@@ -34,6 +34,8 @@ Documentation/dev-tools/testing-overview.rst
ktap
checkuapi
gpio-sloppy-logic-analyzer
+ autofdo
+ propeller
.. only:: subproject and html
diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst
index d7de44f5339d..0a1418ab72fd 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -511,19 +511,14 @@ Tests
~~~~~
There are KASAN tests that allow verifying that KASAN works and can detect
-certain types of memory corruptions. The tests consist of two parts:
+certain types of memory corruptions.
-1. Tests that are integrated with the KUnit Test Framework. Enabled with
-``CONFIG_KASAN_KUNIT_TEST``. These tests can be run and partially verified
+All KASAN tests are integrated with the KUnit Test Framework and can be enabled
+via ``CONFIG_KASAN_KUNIT_TEST``. The tests can be run and partially verified
automatically in a few different ways; see the instructions below.
-2. Tests that are currently incompatible with KUnit. Enabled with
-``CONFIG_KASAN_MODULE_TEST`` and can only be run as a module. These tests can
-only be verified manually by loading the kernel module and inspecting the
-kernel log for KASAN reports.
-
-Each KUnit-compatible KASAN test prints one of multiple KASAN reports if an
-error is detected. Then the test prints its number and status.
+Each KASAN test prints one of multiple KASAN reports if an error is detected.
+Then the test prints its number and status.
When a test passes::
@@ -550,16 +545,16 @@ Or, if one of the tests failed::
not ok 1 - kasan
-There are a few ways to run KUnit-compatible KASAN tests.
+There are a few ways to run the KASAN tests.
1. Loadable module
- With ``CONFIG_KUNIT`` enabled, KASAN-KUnit tests can be built as a loadable
- module and run by loading ``kasan_test.ko`` with ``insmod`` or ``modprobe``.
+ With ``CONFIG_KUNIT`` enabled, the tests can be built as a loadable module
+ and run by loading ``kasan_test.ko`` with ``insmod`` or ``modprobe``.
2. Built-In
- With ``CONFIG_KUNIT`` built-in, KASAN-KUnit tests can be built-in as well.
+ With ``CONFIG_KUNIT`` built-in, the tests can be built-in as well.
In this case, the tests will run at boot as a late-init call.
3. Using kunit_tool
diff --git a/Documentation/dev-tools/kgdb.rst b/Documentation/dev-tools/kgdb.rst
index f83ba2601e55..cb626a7a000c 100644
--- a/Documentation/dev-tools/kgdb.rst
+++ b/Documentation/dev-tools/kgdb.rst
@@ -75,11 +75,11 @@ supports it for the architecture you are using, you can use hardware
breakpoints if you desire to run with the ``CONFIG_STRICT_KERNEL_RWX``
option turned on, else you need to turn off this option.
-Next you should choose one of more I/O drivers to interconnect debugging
+Next you should choose one or more I/O drivers to interconnect the debugging
host and debugged target. Early boot debugging requires a KGDB I/O
driver that supports early debugging and the driver must be built into
the kernel directly. Kgdb I/O driver configuration takes place via
-kernel or module parameters which you can learn more about in the in the
+kernel or module parameters which you can learn more about in the
section that describes the parameter kgdboc.
Here is an example set of ``.config`` symbols to enable or disable for kgdb::
@@ -201,8 +201,8 @@ Using loadable module or built-in
Configure kgdboc at runtime with sysfs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-At run time you can enable or disable kgdboc by echoing a parameters
-into the sysfs. Here are two examples:
+At run time you can enable or disable kgdboc by writing parameters
+into sysfs. Here are two examples:
1. Enable kgdboc on ttyS0::
@@ -329,7 +329,7 @@ ways to activate this feature.
2. Use sysfs before configuring an I/O driver::
- echo 1 > /sys/module/kgdb/parameters/kgdb_use_con
+ echo 1 > /sys/module/debug_core/parameters/kgdb_use_con
.. note::
@@ -374,10 +374,10 @@ default behavior is always set to 0.
Kernel parameter: ``nokaslr``
-----------------------------
-If the architecture that you are using enable KASLR by default,
+If the architecture that you are using enables KASLR by default,
you should consider turning it off. KASLR randomizes the
-virtual address where the kernel image is mapped and confuse
-gdb which resolve kernel symbol address from symbol table
+virtual address where the kernel image is mapped and confuses
+gdb which resolves addresses of kernel symbols from the symbol table
of vmlinux.
Using kdb
@@ -631,8 +631,6 @@ automatically changes into kgdb mode.
kgdb
- Now disconnect your terminal program and connect gdb in its place
-
2. At the kdb prompt, disconnect the terminal program and connect gdb in
its place.
@@ -749,7 +747,7 @@ The kernel debugger is organized into a number of components:
helper functions in some of the other kernel components to make it
possible for kdb to examine and report information about the kernel
without taking locks that could cause a kernel deadlock. The kdb core
- contains implements the following functionality.
+ implements the following functionality.
- A simple shell
diff --git a/Documentation/dev-tools/kmemleak.rst b/Documentation/dev-tools/kmemleak.rst
index 2cb00b53339f..7d784e03f3f9 100644
--- a/Documentation/dev-tools/kmemleak.rst
+++ b/Documentation/dev-tools/kmemleak.rst
@@ -161,6 +161,7 @@ See the include/linux/kmemleak.h header for the functions prototype.
- ``kmemleak_free_percpu`` - notify of a percpu memory block freeing
- ``kmemleak_update_trace`` - update object allocation stack trace
- ``kmemleak_not_leak`` - mark an object as not a leak
+- ``kmemleak_transient_leak`` - mark an object as a transient leak
- ``kmemleak_ignore`` - do not scan or report an object as leak
- ``kmemleak_scan_area`` - add scan areas inside a memory block
- ``kmemleak_no_scan`` - do not scan a memory block
diff --git a/Documentation/dev-tools/kmsan.rst b/Documentation/dev-tools/kmsan.rst
index 6a48d96c5c85..0dc668b183f6 100644
--- a/Documentation/dev-tools/kmsan.rst
+++ b/Documentation/dev-tools/kmsan.rst
@@ -133,7 +133,7 @@ KMSAN shadow memory
-------------------
KMSAN associates a metadata byte (also called shadow byte) with every byte of
-kernel memory. A bit in the shadow byte is set iff the corresponding bit of the
+kernel memory. A bit in the shadow byte is set if the corresponding bit of the
kernel memory byte is uninitialized. Marking the memory uninitialized (i.e.
setting its shadow bytes to ``0xff``) is called poisoning, marking it
initialized (setting the shadow bytes to ``0x00``) is called unpoisoning.
diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst
index f3766e326d1e..fdb1df86783a 100644
--- a/Documentation/dev-tools/kselftest.rst
+++ b/Documentation/dev-tools/kselftest.rst
@@ -31,6 +31,15 @@ kselftest runs as a userspace process. Tests that can be written/run in
userspace may wish to use the `Test Harness`_. Tests that need to be
run in kernel space may wish to use a `Test Module`_.
+Documentation on the tests
+==========================
+
+For documentation on the kselftests themselves, see:
+
+.. toctree::
+
+ testing-devices
+
Running the selftests (hotplug tests are run in limited mode)
=============================================================
diff --git a/Documentation/dev-tools/propeller.rst b/Documentation/dev-tools/propeller.rst
new file mode 100644
index 000000000000..92195958e3db
--- /dev/null
+++ b/Documentation/dev-tools/propeller.rst
@@ -0,0 +1,162 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+Using Propeller with the Linux kernel
+=====================================
+
+This enables Propeller build support for the kernel when using Clang
+compiler. Propeller is a profile-guided optimization (PGO) method used
+to optimize binary executables. Like AutoFDO, it utilizes hardware
+sampling to gather information about the frequency of execution of
+different code paths within a binary. Unlike AutoFDO, this information
+is then used right before linking phase to optimize (among others)
+block layout within and across functions.
+
+A few important notes about adopting Propeller optimization:
+
+#. Although it can be used as a standalone optimization step, it is
+ strongly recommended to apply Propeller on top of AutoFDO,
+ AutoFDO+ThinLTO or Instrument FDO. The rest of this document
+ assumes this paradigm.
+
+#. Propeller uses another round of profiling on top of
+ AutoFDO/AutoFDO+ThinLTO/iFDO. The whole build process involves
+ "build-afdo - train-afdo - build-propeller - train-propeller -
+ build-optimized".
+
+#. Propeller requires LLVM 19 release or later for Clang/Clang++
+ and the linker(ld.lld).
+
+#. In addition to LLVM toolchain, Propeller requires a profiling
+ conversion tool: https://github.com/google/autofdo with a release
+ after v0.30.1: https://github.com/google/autofdo/releases/tag/v0.30.1.
+
+The Propeller optimization process involves the following steps:
+
+#. Initial building: Build the AutoFDO or AutoFDO+ThinLTO binary as
+ you would normally do, but with a set of compile-time / link-time
+ flags, so that a special metadata section is created within the
+ kernel binary. The special section is only intend to be used by the
+ profiling tool, it is not part of the runtime image, nor does it
+ change kernel run time text sections.
+
+#. Profiling: The above kernel is then run with a representative
+ workload to gather execution frequency data. This data is collected
+ using hardware sampling, via perf. Propeller is most effective on
+ platforms supporting advanced PMU features like LBR on Intel
+ machines. This step is the same as profiling the kernel for AutoFDO
+ (the exact perf parameters can be different).
+
+#. Propeller profile generation: Perf output file is converted to a
+ pair of Propeller profiles via an offline tool.
+
+#. Optimized build: Build the AutoFDO or AutoFDO+ThinLTO optimized
+ binary as you would normally do, but with a compile-time /
+ link-time flag to pick up the Propeller compile time and link time
+ profiles. This build step uses 3 profiles - the AutoFDO profile,
+ the Propeller compile-time profile and the Propeller link-time
+ profile.
+
+#. Deployment: The optimized kernel binary is deployed and used
+ in production environments, providing improved performance
+ and reduced latency.
+
+Preparation
+===========
+
+Configure the kernel with::
+
+ CONFIG_AUTOFDO_CLANG=y
+ CONFIG_PROPELLER_CLANG=y
+
+Customization
+=============
+
+The default CONFIG_PROPELLER_CLANG setting covers kernel space objects
+for Propeller builds. One can, however, enable or disable Propeller build
+for individual files and directories by adding a line similar to the
+following to the respective kernel Makefile:
+
+- For enabling a single file (e.g. foo.o)::
+
+ PROPELLER_PROFILE_foo.o := y
+
+- For enabling all files in one directory::
+
+ PROPELLER_PROFILE := y
+
+- For disabling one file::
+
+ PROPELLER_PROFILE_foo.o := n
+
+- For disabling all files in one directory::
+
+ PROPELLER__PROFILE := n
+
+
+Workflow
+========
+
+Here is an example workflow for building an AutoFDO+Propeller kernel:
+
+1) Assuming an AutoFDO profile is already collected following
+ instructions in the AutoFDO document, build the kernel on the host
+ machine, with AutoFDO and Propeller build configs ::
+
+ CONFIG_AUTOFDO_CLANG=y
+ CONFIG_PROPELLER_CLANG=y
+
+ and ::
+
+ $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<autofdo-profile-name>
+
+2) Install the kernel on the test machine.
+
+3) Run the load tests. The '-c' option in perf specifies the sample
+ event period. We suggest using a suitable prime number, like 500009,
+ for this purpose.
+
+ - For Intel platforms::
+
+ $ perf record -e BR_INST_RETIRED.NEAR_TAKEN:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+ - For AMD platforms::
+
+ $ perf record --pfm-event RETIRED_TAKEN_BRANCH_INSTRUCTIONS:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+ Note you can repeat the above steps to collect multiple <perf_file>s.
+
+4) (Optional) Download the raw perf file(s) to the host machine.
+
+5) Use the create_llvm_prof tool (https://github.com/google/autofdo) to
+ generate Propeller profile. ::
+
+ $ create_llvm_prof --binary=<vmlinux> --profile=<perf_file>
+ --format=propeller --propeller_output_module_name
+ --out=<propeller_profile_prefix>_cc_profile.txt
+ --propeller_symorder=<propeller_profile_prefix>_ld_profile.txt
+
+ "<propeller_profile_prefix>" can be something like "/home/user/dir/any_string".
+
+ This command generates a pair of Propeller profiles:
+ "<propeller_profile_prefix>_cc_profile.txt" and
+ "<propeller_profile_prefix>_ld_profile.txt".
+
+ If there are more than 1 perf_file collected in the previous step,
+ you can create a temp list file "<perf_file_list>" with each line
+ containing one perf file name and run::
+
+ $ create_llvm_prof --binary=<vmlinux> --profile=@<perf_file_list>
+ --format=propeller --propeller_output_module_name
+ --out=<propeller_profile_prefix>_cc_profile.txt
+ --propeller_symorder=<propeller_profile_prefix>_ld_profile.txt
+
+6) Rebuild the kernel using the AutoFDO and Propeller
+ profiles. ::
+
+ CONFIG_AUTOFDO_CLANG=y
+ CONFIG_PROPELLER_CLANG=y
+
+ and ::
+
+ $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<profile_file> CLANG_PROPELLER_PROFILE_PREFIX=<propeller_profile_prefix>
diff --git a/Documentation/dev-tools/testing-devices.rst b/Documentation/dev-tools/testing-devices.rst
new file mode 100644
index 000000000000..ab26adb99051
--- /dev/null
+++ b/Documentation/dev-tools/testing-devices.rst
@@ -0,0 +1,47 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. Copyright (c) 2024 Collabora Ltd
+
+=============================
+Device testing with kselftest
+=============================
+
+
+There are a few different kselftests available for testing devices generically,
+with some overlap in coverage and different requirements. This document aims to
+give an overview of each one.
+
+Note: Paths in this document are relative to the kselftest folder
+(``tools/testing/selftests``).
+
+Device oriented kselftests:
+
+* Devicetree (``dt``)
+
+ * **Coverage**: Probe status for devices described in Devicetree
+ * **Requirements**: None
+
+* Error logs (``devices/error_logs``)
+
+ * **Coverage**: Error (or more critical) log messages presence coming from any
+ device
+ * **Requirements**: None
+
+* Discoverable bus (``devices/probe``)
+
+ * **Coverage**: Presence and probe status of USB or PCI devices that have been
+ described in the reference file
+ * **Requirements**: Manually describe the devices that should be tested in a
+ YAML reference file (see ``devices/probe/boards/google,spherion.yaml`` for
+ an example)
+
+* Exist (``devices/exist``)
+
+ * **Coverage**: Presence of all devices
+ * **Requirements**: Generate the reference (see ``devices/exist/README.rst``
+ for details) on a known-good kernel
+
+Therefore, the suggestion is to enable the error log and devicetree tests on all
+(DT-based) platforms, since they don't have any requirements. Then to greatly
+improve coverage, generate the reference for each platform and enable the exist
+test. The discoverable bus test can be used to verify the probe status of
+specific USB or PCI devices, but is probably not worth it for most cases.
diff --git a/Documentation/devicetree/bindings/Makefile b/Documentation/devicetree/bindings/Makefile
index bf7d64632e20..8390d6c00030 100644
--- a/Documentation/devicetree/bindings/Makefile
+++ b/Documentation/devicetree/bindings/Makefile
@@ -56,7 +56,6 @@ DT_DOCS = $(patsubst $(srctree)/%,%,$(shell $(find_all_cmd)))
override DTC_FLAGS := \
-Wno-avoid_unnecessary_addr_size \
-Wno-graph_child_address \
- -Wno-interrupt_provider \
-Wno-unique_unit_address \
-Wunique_unit_address_if_enabled
diff --git a/Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.yaml b/Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.yaml
new file mode 100644
index 000000000000..67c449d804c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/airoha,en7581-chip-scu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha Chip SCU Controller for EN7581 SoC
+
+maintainers:
+ - Lorenzo Bianconi <lorenzo@kernel.org>
+
+description:
+ The airoha chip-scu block provides a configuration interface for clock,
+ io-muxing and other functionalities used by multiple controllers (e.g. clock,
+ pinctrl, ecc) on EN7581 SoC.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - airoha,en7581-chip-scu
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ syscon@1fa20000 {
+ compatible = "airoha,en7581-chip-scu", "syscon";
+ reg = <0x0 0x1fa20000 0x0 0x388>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/arm/apple.yaml b/Documentation/devicetree/bindings/arm/apple.yaml
index 883fd67e3752..dc9aab19ff11 100644
--- a/Documentation/devicetree/bindings/arm/apple.yaml
+++ b/Documentation/devicetree/bindings/arm/apple.yaml
@@ -12,7 +12,58 @@ maintainers:
description: |
ARM platforms using SoCs designed by Apple Inc., branded "Apple Silicon".
- This currently includes devices based on the "M1" SoC:
+ This currently includes devices based on the "A7" SoC:
+
+ - iPhone 5s
+ - iPad Air (1)
+ - iPad mini 2
+ - iPad mini 3
+
+ Devices based on the "A8" SoC:
+
+ - iPhone 6
+ - iPhone 6 Plus
+ - iPad mini 4
+ - iPod touch 6
+ - Apple TV HD
+
+ Device based on the "A8X" SoC:
+
+ - iPad Air 2
+
+ Devices based on the "A9" SoC:
+
+ - iPhone 6s
+ - iPhone 6s Plus
+ - iPhone SE (2016)
+ - iPad 5
+
+ Devices based on the "A9X" SoC:
+
+ - iPad Pro (9.7-inch)
+ - iPad Pro (12.9-inch)
+
+ Devices based on the "A10" SoC:
+
+ - iPhone 7
+ - iPhone 7 Plus
+ - iPod touch 7
+ - iPad 6
+ - iPad 7
+
+ Devices based on the "A10X" SoC:
+
+ - Apple TV 4K (1st generation)
+ - iPad Pro (2nd Generation) (10.5 Inch)
+ - iPad Pro (2nd Generation) (12.9 Inch)
+
+ Devices based on the "A11" SoC:
+
+ - iPhone 8
+ - iPhone 8 Plus
+ - iPhone X
+
+ Devices based on the "M1" SoC:
- Mac mini (M1, 2020)
- MacBook Pro (13-inch, M1, 2020)
@@ -65,6 +116,113 @@ properties:
const: "/"
compatible:
oneOf:
+ - description: Apple A7 SoC based platforms
+ items:
+ - enum:
+ - apple,j71 # iPad Air (Wi-Fi)
+ - apple,j72 # iPad Air (Cellular)
+ - apple,j73 # iPad Air (Cellular, China)
+ - apple,j85 # iPad mini 2 (Wi-Fi)
+ - apple,j85m # iPad mini 3 (Wi-Fi)
+ - apple,j86 # iPad mini 2 (Cellular)
+ - apple,j86m # iPad mini 3 (Cellular)
+ - apple,j87 # iPad mini 2 (Cellular, China)
+ - apple,j87m # iPad mini 3 (Cellular, China)
+ - apple,n51 # iPhone 5s (GSM)
+ - apple,n53 # iPhone 5s (LTE)
+ - const: apple,s5l8960x
+ - const: apple,arm-platform
+
+ - description: Apple A8 SoC based platforms
+ items:
+ - enum:
+ - apple,j42d # Apple TV HD
+ - apple,j96 # iPad mini 4 (Wi-Fi)
+ - apple,j97 # iPad mini 4 (Cellular)
+ - apple,n56 # iPhone 6 Plus
+ - apple,n61 # iPhone 6
+ - apple,n102 # iPod touch 6
+ - const: apple,t7000
+ - const: apple,arm-platform
+
+ - description: Apple A8X SoC based platforms
+ items:
+ - enum:
+ - apple,j81 # iPad Air 2 (Wi-Fi)
+ - apple,j82 # iPad Air 2 (Cellular)
+ - const: apple,t7001
+ - const: apple,arm-platform
+
+ - description: Apple Samsung A9 SoC based platforms
+ items:
+ - enum:
+ - apple,j71s # iPad 5 (Wi-Fi) (S8000)
+ - apple,j72s # iPad 5 (Cellular) (S8000)
+ - apple,n66 # iPhone 6s Plus (S8000)
+ - apple,n69u # iPhone SE (S8000)
+ - apple,n71 # iPhone 6S (S8000)
+ - const: apple,s8000
+ - const: apple,arm-platform
+
+ - description: Apple TSMC A9 SoC based platforms
+ items:
+ - enum:
+ - apple,j71t # iPad 5 (Wi-Fi) (S8003)
+ - apple,j72t # iPad 5 (Cellular) (S8003)
+ - apple,n66m # iPhone 6s Plus (S8003)
+ - apple,n69 # iPhone SE (S8003)
+ - apple,n71m # iPhone 6S (S8003)
+ - const: apple,s8003
+ - const: apple,arm-platform
+
+ - description: Apple A9X SoC based platforms
+ items:
+ - enum:
+ - apple,j127 # iPad Pro (9.7-inch) (Wi-Fi)
+ - apple,j128 # iPad Pro (9.7-inch) (Cellular)
+ - apple,j98a # iPad Pro (12.9-inch) (Wi-Fi)
+ - apple,j99a # iPad Pro (12.9-inch) (Cellular)
+ - const: apple,s8001
+ - const: apple,arm-platform
+
+ - description: Apple A10 SoC based platforms
+ items:
+ - enum:
+ - apple,d10 # iPhone 7 (Qualcomm)
+ - apple,d11 # iPhone 7 (Intel)
+ - apple,d101 # iPhone 7 Plus (Qualcomm)
+ - apple,d111 # iPhone 7 Plus (Intel)
+ - apple,j71b # iPad 6 (Wi-Fi)
+ - apple,j72b # iPad 6 (Cellular)
+ - apple,j171 # iPad 7 (Wi-Fi)
+ - apple,j172 # iPad 7 (Cellular)
+ - apple,n112 # iPod touch 7
+ - const: apple,t8010
+ - const: apple,arm-platform
+
+ - description: Apple A10X SoC based platforms
+ items:
+ - enum:
+ - apple,j105a # Apple TV 4K (1st Generation)
+ - apple,j120 # iPad Pro 2 (12.9-inch) (Wi-Fi)
+ - apple,j121 # iPad Pro 2 (12.9-inch) (Cellular)
+ - apple,j207 # iPad Pro 2 (10.5-inch) (Wi-Fi)
+ - apple,j208 # iPad Pro 2 (10.5-inch) (Cellular)
+ - const: apple,t8011
+ - const: apple,arm-platform
+
+ - description: Apple A11 SoC based platforms
+ items:
+ - enum:
+ - apple,d20 # iPhone 8 (Global)
+ - apple,d21 # iPhone 8 Plus (Global)
+ - apple,d22 # iPhone X (Global)
+ - apple,d201 # iPhone 8 (GSM)
+ - apple,d211 # iPhone 8 Plus (GSM)
+ - apple,d221 # iPhone X (GSM)
+ - const: apple,t8015
+ - const: apple,arm-platform
+
- description: Apple M1 SoC based platforms
items:
- enum:
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.yaml b/Documentation/devicetree/bindings/arm/atmel-at91.yaml
index 82f37328cc69..7160ec80ac1b 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.yaml
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.yaml
@@ -106,6 +106,12 @@ properties:
- const: microchip,sam9x60
- const: atmel,at91sam9
+ - description: Microchip SAM9X7 Evaluation Boards
+ items:
+ - const: microchip,sam9x75-curiosity
+ - const: microchip,sam9x7
+ - const: atmel,at91sam9
+
- description: Nattis v2 board with Natte v2 power board
items:
- const: axentia,nattis-2
diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml
index f308ff6c3532..73dd73d2d4fa 100644
--- a/Documentation/devicetree/bindings/arm/cpus.yaml
+++ b/Documentation/devicetree/bindings/arm/cpus.yaml
@@ -87,8 +87,14 @@ properties:
enum:
- apple,avalanche
- apple,blizzard
- - apple,icestorm
+ - apple,cyclone
- apple,firestorm
+ - apple,hurricane-zephyr
+ - apple,icestorm
+ - apple,mistral
+ - apple,monsoon
+ - apple,twister
+ - apple,typhoon
- arm,arm710t
- arm,arm720t
- arm,arm740t
@@ -202,10 +208,14 @@ properties:
- qcom,kryo560
- qcom,kryo570
- qcom,kryo660
+ - qcom,kryo670
- qcom,kryo685
- qcom,kryo780
- qcom,oryon
- qcom,scorpion
+ - samsung,mongoose-m2
+ - samsung,mongoose-m3
+ - samsung,mongoose-m5
enable-method:
$ref: /schemas/types.yaml#/definitions/string
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index b39a7e031177..6e0dcf4307f1 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -379,7 +379,9 @@ properties:
- description: i.MX6Q PHYTEC phyFLEX-i.MX6
items:
- - const: phytec,imx6q-pbab01 # PHYTEC phyFLEX carrier board
+ - enum:
+ - comvetia,imx6q-lxr # Comvetia LXR board
+ - phytec,imx6q-pbab01 # PHYTEC phyFLEX carrier board
- const: phytec,imx6q-pfla02 # PHYTEC phyFLEX-i.MX6 Quad
- const: fsl,imx6q
@@ -523,9 +525,11 @@ properties:
- const: dfi,fs700e-m60
- const: fsl,imx6dl
- - description: i.MX6DL DHCOM PicoITX Board
+ - description: i.MX6DL DHCOM based Boards
items:
- - const: dh,imx6dl-dhcom-picoitx
+ - enum:
+ - dh,imx6dl-dhcom-pdk2 # i.MX6DL DHCOM SoM on PDK2 board
+ - dh,imx6dl-dhcom-picoitx # i.MX6DL DHCOM SoM on PicoITX board
- const: dh,imx6dl-dhcom-som
- const: fsl,imx6dl
@@ -620,6 +624,14 @@ properties:
- kobo,librah2o
- const: fsl,imx6sll
+ - description: i.MX6SLL Kobo Clara 2e Rev. A/B
+ items:
+ - enum:
+ - kobo,clara2e-a
+ - kobo,clara2e-b
+ - const: kobo,clara2e
+ - const: fsl,imx6sll
+
- description: i.MX6SX based Boards
items:
- enum:
@@ -995,6 +1007,7 @@ properties:
- menlo,mx8menlo # Verdin iMX8M Mini Module on i.MX8MM Menlo board
- toradex,verdin-imx8mm-nonwifi-dahlia # Verdin iMX8M Mini Module on Dahlia
- toradex,verdin-imx8mm-nonwifi-dev # Verdin iMX8M Mini Module on Verdin Development Board
+ - toradex,verdin-imx8mm-nonwifi-ivy # Verdin iMX8M Mini Module on Ivy
- toradex,verdin-imx8mm-nonwifi-mallow # Verdin iMX8M Mini Module on Mallow
- toradex,verdin-imx8mm-nonwifi-yavia # Verdin iMX8M Mini Module on Yavia
- const: toradex,verdin-imx8mm-nonwifi # Verdin iMX8M Mini Module without Wi-Fi / BT
@@ -1006,6 +1019,7 @@ properties:
- enum:
- toradex,verdin-imx8mm-wifi-dahlia # Verdin iMX8M Mini Wi-Fi / BT Module on Dahlia
- toradex,verdin-imx8mm-wifi-dev # Verdin iMX8M Mini Wi-Fi / BT M. on Verdin Development B.
+ - toradex,verdin-imx8mm-wifi-ivy # Verdin iMX8M Mini Wi-Fi / BT Module on Ivy
- toradex,verdin-imx8mm-wifi-mallow # Verdin iMX8M Mini Wi-Fi / BT Module on Mallow
- toradex,verdin-imx8mm-wifi-yavia # Verdin iMX8M Mini Wi-Fi / BT Module on Yavia
- const: toradex,verdin-imx8mm-wifi # Verdin iMX8M Mini Wi-Fi / BT Module
@@ -1082,12 +1096,14 @@ properties:
- gateworks,imx8mp-gw73xx-2x # i.MX8MP Gateworks Board
- gateworks,imx8mp-gw74xx # i.MX8MP Gateworks Board
- gateworks,imx8mp-gw75xx-2x # i.MX8MP Gateworks Board
+ - gateworks,imx8mp-gw82xx-2x # i.MX8MP Gateworks Board
- skov,imx8mp-skov-revb-hdmi # SKOV i.MX8MP climate control without panel
- skov,imx8mp-skov-revb-lt6 # SKOV i.MX8MP climate control with 7†panel
- skov,imx8mp-skov-revb-mi1010ait-1cp1 # SKOV i.MX8MP climate control with 10.1" panel
- toradex,verdin-imx8mp # Verdin iMX8M Plus Modules
- toradex,verdin-imx8mp-nonwifi # Verdin iMX8M Plus Modules without Wi-Fi / BT
- toradex,verdin-imx8mp-wifi # Verdin iMX8M Plus Wi-Fi / BT Modules
+ - ysoft,imx8mp-iota2-lumpy # Y Soft i.MX8MP IOTA2 Lumpy Board
- const: fsl,imx8mp
- description: Avnet (MSC Branded) Boards with SM2S i.MX8M Plus Modules
@@ -1097,11 +1113,19 @@ properties:
- const: avnet,sm2s-imx8mp # SM2S-IMX8PLUS SoM
- const: fsl,imx8mp
+ - description: Boundary Device Nitrogen8MP Universal SMARC Carrier Board
+ items:
+ - const: boundary,imx8mp-nitrogen-smarc-universal-board
+ - const: boundary,imx8mp-nitrogen-smarc-som
+ - const: fsl,imx8mp
+
- description: i.MX8MP DHCOM based Boards
items:
- enum:
+ - dh,imx8mp-dhcom-drc02 # i.MX8MP DHCOM SoM on DRC02 board
- dh,imx8mp-dhcom-pdk2 # i.MX8MP DHCOM SoM on PDK2 board
- dh,imx8mp-dhcom-pdk3 # i.MX8MP DHCOM SoM on PDK3 board
+ - dh,imx8mp-dhcom-picoitx # i.MX8MP DHCOM SoM on PicoITX board
- const: dh,imx8mp-dhcom-som # i.MX8MP DHCOM SoM
- const: fsl,imx8mp
@@ -1112,6 +1136,19 @@ properties:
- const: engicam,icore-mx8mp # i.MX8MP Engicam i.Core MX8M Plus SoM
- const: fsl,imx8mp
+ - description: Kontron i.MX8MP OSM-S SoM based Boards
+ items:
+ - const: kontron,imx8mp-bl-osm-s # Kontron BL i.MX8MP OSM-S Board
+ - const: kontron,imx8mp-osm-s # Kontron i.MX8MP OSM-S SoM
+ - const: fsl,imx8mp
+
+ - description: Kontron i.MX8MP SMARC based Boards
+ items:
+ - const: kontron,imx8mp-smarc-eval-carrier # Kontron i.MX8MP SMARC Eval Carrier
+ - const: kontron,imx8mp-smarc # Kontron i.MX8MP SMARC Module
+ - const: kontron,imx8mp-osm-s # Kontron i.MX8MP OSM-S SoM
+ - const: fsl,imx8mp
+
- description: PHYTEC phyCORE-i.MX8MP SoM based boards
items:
- const: phytec,imx8mp-phyboard-pollux-rdk # phyBOARD-Pollux RDK
@@ -1137,6 +1174,7 @@ properties:
- enum:
- toradex,verdin-imx8mp-nonwifi-dahlia # Verdin iMX8M Plus Module on Dahlia
- toradex,verdin-imx8mp-nonwifi-dev # Verdin iMX8M Plus Module on Verdin Development Board
+ - toradex,verdin-imx8mp-nonwifi-ivy # Verdin iMX8M Plus Module on Ivy
- toradex,verdin-imx8mp-nonwifi-mallow # Verdin iMX8M Plus Module on Mallow
- toradex,verdin-imx8mp-nonwifi-yavia # Verdin iMX8M Plus Module on Yavia
- const: toradex,verdin-imx8mp-nonwifi # Verdin iMX8M Plus Module without Wi-Fi / BT
@@ -1148,6 +1186,7 @@ properties:
- enum:
- toradex,verdin-imx8mp-wifi-dahlia # Verdin iMX8M Plus Wi-Fi / BT Module on Dahlia
- toradex,verdin-imx8mp-wifi-dev # Verdin iMX8M Plus Wi-Fi / BT M. on Verdin Development B.
+ - toradex,verdin-imx8mp-wifi-ivy # Verdin iMX8M Plus Wi-Fi / BT Module on Ivy
- toradex,verdin-imx8mp-wifi-mallow # Verdin iMX8M Plus Wi-Fi / BT Module on Mallow
- toradex,verdin-imx8mp-wifi-yavia # Verdin iMX8M Plus Wi-Fi / BT Module on Yavia
- const: toradex,verdin-imx8mp-wifi # Verdin iMX8M Plus Wi-Fi / BT Module
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
index b3c6888c1457..3f4262e93c78 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
@@ -93,6 +93,34 @@ properties:
'#reset-cells':
const: 1
+ port:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Output port node. This port connects the MMSYS/VDOSYS output to
+ the first component of one display pipeline, for example one of
+ the available OVL or RDMA blocks.
+ Some MediaTek SoCs support multiple display outputs per MMSYS.
+ properties:
+ endpoint@0:
+ $ref: /schemas/graph.yaml#/properties/endpoint
+ description: Output to the primary display pipeline
+
+ endpoint@1:
+ $ref: /schemas/graph.yaml#/properties/endpoint
+ description: Output to the secondary display pipeline
+
+ endpoint@2:
+ $ref: /schemas/graph.yaml#/properties/endpoint
+ description: Output to the tertiary display pipeline
+
+ anyOf:
+ - required:
+ - endpoint@0
+ - required:
+ - endpoint@1
+ - required:
+ - endpoint@2
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/arm/pmu.yaml b/Documentation/devicetree/bindings/arm/pmu.yaml
index 528544d0a161..a148ff54f2b8 100644
--- a/Documentation/devicetree/bindings/arm/pmu.yaml
+++ b/Documentation/devicetree/bindings/arm/pmu.yaml
@@ -74,6 +74,7 @@ properties:
- qcom,krait-pmu
- qcom,scorpion-pmu
- qcom,scorpion-mp-pmu
+ - samsung,mongoose-pmu
interrupts:
# Don't know how many CPUs, so no constraints to specify
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 5cb54d69af0b..9679fed7259b 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -45,6 +45,7 @@ description: |
qcs8550
qcm2290
qcm6490
+ qcs9100
qdu1000
qrb2210
qrb4210
@@ -76,6 +77,7 @@ description: |
sm6375
sm7125
sm7225
+ sm7325
sm8150
sm8250
sm8350
@@ -821,6 +823,7 @@ properties:
- items:
- enum:
- lenovo,thinkpad-x13s
+ - microsoft,arcata
- qcom,sc8280xp-crd
- qcom,sc8280xp-qrd
- const: qcom,sc8280xp
@@ -914,6 +917,13 @@ properties:
- items:
- enum:
+ - qcom,qcs9100-ride
+ - qcom,qcs9100-ride-r3
+ - const: qcom,qcs9100
+ - const: qcom,sa8775p
+
+ - items:
+ - enum:
- google,cheza
- google,cheza-rev1
- google,cheza-rev2
@@ -991,6 +1001,11 @@ properties:
- items:
- enum:
+ - nothing,spacewar
+ - const: qcom,sm7325
+
+ - items:
+ - enum:
- microsoft,surface-duo
- qcom,sm8150-hdk
- qcom,sm8150-mtp
@@ -1058,6 +1073,7 @@ properties:
- items:
- enum:
- asus,vivobook-s15
+ - dell,xps13-9345
- lenovo,yoga-slim7x
- microsoft,romulus13
- microsoft,romulus15
diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index 687823e58c22..753199a12923 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -49,11 +49,23 @@ properties:
- anbernic,rg-arc-s
- const: rockchip,rk3566
+ - description: ArmSoM Sige5 board
+ items:
+ - const: armsom,sige5
+ - const: rockchip,rk3576
+
- description: ArmSoM Sige7 board
items:
- const: armsom,sige7
- const: rockchip,rk3588
+ - description: ArmSoM LM7 SoM
+ items:
+ - enum:
+ - armsom,w3
+ - const: armsom,lm7
+ - const: rockchip,rk3588
+
- description: Asus Tinker board
items:
- const: asus,rk3288-tinker
@@ -232,6 +244,11 @@ properties:
- friendlyarm,nanopi-r2s-plus
- const: rockchip,rk3328
+ - description: FriendlyElec NanoPi R3S
+ items:
+ - const: friendlyarm,nanopi-r3s
+ - const: rockchip,rk3566
+
- description: FriendlyElec NanoPi4 series boards
items:
- enum:
@@ -760,6 +777,7 @@ properties:
items:
- enum:
- powkiddy,rgb10max3
+ - powkiddy,rgb20sx
- powkiddy,rgb30
- powkiddy,rk2023
- powkiddy,x55
@@ -789,6 +807,11 @@ properties:
- const: radxa,cm3i
- const: rockchip,rk3568
+ - description: Radxa E20C
+ items:
+ - const: radxa,e20c
+ - const: rockchip,rk3528
+
- description: Radxa Rock
items:
- const: radxa,rock
@@ -872,6 +895,11 @@ properties:
- const: radxa,rock-5b
- const: rockchip,rk3588
+ - description: Radxa ROCK 5C
+ items:
+ - const: radxa,rock-5c
+ - const: rockchip,rk3588s
+
- description: Radxa ROCK S0
items:
- const: radxa,rock-s0
@@ -884,6 +912,11 @@ properties:
- radxa,zero-3w
- const: rockchip,rk3566
+ - description: Relfor SAIB board
+ items:
+ - const: relfor,saib
+ - const: rockchip,rv1109
+
- description: Rikomagic MK808 v1
items:
- const: rikomagic,mk808
@@ -978,6 +1011,11 @@ properties:
- const: rockchip,rk3588-evb1-v10
- const: rockchip,rk3588
+ - description: Rockchip RK3588S Evaluation board
+ items:
+ - const: rockchip,rk3588s-evb1-v10
+ - const: rockchip,rk3588s
+
- description: Rockchip RV1108 Evaluation board
items:
- const: rockchip,rv1108-evb
@@ -1051,7 +1089,9 @@ properties:
- description: Xunlong Orange Pi 5
items:
- - const: xunlong,orangepi-5
+ - enum:
+ - xunlong,orangepi-5
+ - xunlong,orangepi-5b
- const: rockchip,rk3588s
- description: Zkmagic A95X Z2
@@ -1069,6 +1109,11 @@ properties:
- const: rockchip,rk3568-evb1-v10
- const: rockchip,rk3568
+ - description: Sinovoip RK3308 Banana Pi P2 Pro
+ items:
+ - const: sinovoip,rk3308-bpi-p2pro
+ - const: rockchip,rk3308
+
- description: Sinovoip RK3568 Banana Pi R2 Pro
items:
- const: sinovoip,rk3568-bpi-r2pro
diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml
index 01dcbd8aa703..b5ba5ffc36d6 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml
@@ -224,6 +224,24 @@ properties:
- winlink,e850-96 # WinLink E850-96
- const: samsung,exynos850
+ - description: Exynos8895 based boards
+ items:
+ - enum:
+ - samsung,dreamlte # Samsung Galaxy S8 (SM-G950F)
+ - const: samsung,exynos8895
+
+ - description: Exynos9810 based boards
+ items:
+ - enum:
+ - samsung,starlte # Samsung Galaxy S9 (SM-G960F)
+ - const: samsung,exynos9810
+
+ - description: Exynos990 based boards
+ items:
+ - enum:
+ - samsung,c1s # Samsung Galaxy Note20 5G (SM-N981B)
+ - const: samsung,exynos990
+
- description: Exynos Auto v9 based boards
items:
- enum:
diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 4aa15f3668e0..046536d02706 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -846,6 +846,12 @@ properties:
- const: allwinner,sun50i-h64
- const: allwinner,sun50i-a64
+ - description: RerVision A33-Vstar (with A33-Core1 SoM)
+ items:
+ - const: rervision,a33-vstar
+ - const: rervision,a33-core1
+ - const: allwinner,sun8i-a33
+
- description: RerVision H3-DVK
items:
- const: rervision,h3-dvk
diff --git a/Documentation/devicetree/bindings/arm/tegra.yaml b/Documentation/devicetree/bindings/arm/tegra.yaml
index 2889fd0e6592..65e0ff1fdf1e 100644
--- a/Documentation/devicetree/bindings/arm/tegra.yaml
+++ b/Documentation/devicetree/bindings/arm/tegra.yaml
@@ -217,6 +217,11 @@ properties:
- const: nvidia,p3737-0000+p3701-0000
- const: nvidia,p3701-0000
- const: nvidia,tegra234
+ - description: Jetson AGX Orin Developer Kit with Industrial Module
+ items:
+ - const: nvidia,p3737-0000+p3701-0008
+ - const: nvidia,p3701-0008
+ - const: nvidia,tegra234
- description: NVIDIA IGX Orin Development Kit
items:
- const: nvidia,p3740-0002+p3701-0008
diff --git a/Documentation/devicetree/bindings/arm/ti/k3.yaml b/Documentation/devicetree/bindings/arm/ti/k3.yaml
index 5df99e361c21..18f155cd06c8 100644
--- a/Documentation/devicetree/bindings/arm/ti/k3.yaml
+++ b/Documentation/devicetree/bindings/arm/ti/k3.yaml
@@ -56,6 +56,7 @@ properties:
- enum:
- toradex,verdin-am62-nonwifi-dahlia # Verdin AM62 Module on Dahlia
- toradex,verdin-am62-nonwifi-dev # Verdin AM62 Module on Verdin Development Board
+ - toradex,verdin-am62-nonwifi-ivy # Verdin AM62 Module on Ivy
- toradex,verdin-am62-nonwifi-mallow # Verdin AM62 Module on Mallow
- toradex,verdin-am62-nonwifi-yavia # Verdin AM62 Module on Yavia
- const: toradex,verdin-am62-nonwifi # Verdin AM62 Module without Wi-Fi / BT
@@ -67,6 +68,7 @@ properties:
- enum:
- toradex,verdin-am62-wifi-dahlia # Verdin AM62 Wi-Fi / BT Module on Dahlia
- toradex,verdin-am62-wifi-dev # Verdin AM62 Wi-Fi / BT M. on Verdin Development B.
+ - toradex,verdin-am62-wifi-ivy # Verdin AM62 Wi-Fi / BT Module on Ivy
- toradex,verdin-am62-wifi-mallow # Verdin AM62 Wi-Fi / BT Module on Mallow
- toradex,verdin-am62-wifi-yavia # Verdin AM62 Wi-Fi / BT Module on Yavia
- const: toradex,verdin-am62-wifi # Verdin AM62 Wi-Fi / BT Module
@@ -144,6 +146,12 @@ properties:
- ti,j722s-evm
- const: ti,j722s
+ - description: K3 J742S2 SoC
+ items:
+ - enum:
+ - ti,j742s2-evm
+ - const: ti,j742s2
+
- description: K3 J784s4 SoC
items:
- enum:
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
index ef19468e3022..cc35cdc02840 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
@@ -84,6 +84,9 @@ properties:
minItems: 1
maxItems: 3
+ iommus:
+ maxItems: 1
+
patternProperties:
"^sata-port@[0-9a-f]+$":
$ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
diff --git a/Documentation/devicetree/bindings/cache/l2c2x0.yaml b/Documentation/devicetree/bindings/cache/l2c2x0.yaml
index d7840a5c4037..10c1a900202f 100644
--- a/Documentation/devicetree/bindings/cache/l2c2x0.yaml
+++ b/Documentation/devicetree/bindings/cache/l2c2x0.yaml
@@ -100,9 +100,8 @@ properties:
filter. Addresses in the filter window are directed to the M1 port. Other
addresses will go to the M0 port.
$ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- minItems: 2
- maxItems: 2
+ minItems: 2
+ maxItems: 2
arm,io-coherent:
description: indicates that the system is operating in an hardware
diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
index 68ea5f70b75f..03b1941eaa33 100644
--- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
+++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml
@@ -20,8 +20,12 @@ description: |
properties:
compatible:
enum:
+ - qcom,qcs615-llcc
+ - qcom,qcs8300-llcc
- qcom,qdu1000-llcc
- qcom,sa8775p-llcc
+ - qcom,sar1130p-llcc
+ - qcom,sar2130p-llcc
- qcom,sc7180-llcc
- qcom,sc7280-llcc
- qcom,sc8180x-llcc
@@ -39,11 +43,11 @@ properties:
reg:
minItems: 2
- maxItems: 9
+ maxItems: 10
reg-names:
minItems: 2
- maxItems: 9
+ maxItems: 10
interrupts:
maxItems: 1
@@ -67,6 +71,33 @@ allOf:
compatible:
contains:
enum:
+ - qcom,sar1130p-llcc
+ - qcom,sar2130p-llcc
+ then:
+ properties:
+ reg:
+ items:
+ - description: LLCC0 base register region
+ - description: LLCC1 base register region
+ - description: LLCC broadcast OR register region
+ - description: LLCC broadcast AND register region
+ - description: LLCC scratchpad broadcast OR register region
+ - description: LLCC scratchpad broadcast AND register region
+ reg-names:
+ items:
+ - const: llcc0_base
+ - const: llcc1_base
+ - const: llcc_broadcast_base
+ - const: llcc_broadcast_and_base
+ - const: llcc_scratchpad_broadcast_base
+ - const: llcc_scratchpad_broadcast_and_base
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs615-llcc
- qcom,sc7180-llcc
- qcom,sm6350-llcc
then:
@@ -134,6 +165,36 @@ allOf:
- qcom,qdu1000-llcc
- qcom,sc8180x-llcc
- qcom,sc8280xp-llcc
+ then:
+ properties:
+ reg:
+ items:
+ - description: LLCC0 base register region
+ - description: LLCC1 base register region
+ - description: LLCC2 base register region
+ - description: LLCC3 base register region
+ - description: LLCC4 base register region
+ - description: LLCC5 base register region
+ - description: LLCC6 base register region
+ - description: LLCC7 base register region
+ - description: LLCC broadcast base register region
+ reg-names:
+ items:
+ - const: llcc0_base
+ - const: llcc1_base
+ - const: llcc2_base
+ - const: llcc3_base
+ - const: llcc4_base
+ - const: llcc5_base
+ - const: llcc6_base
+ - const: llcc7_base
+ - const: llcc_broadcast_base
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,x1e80100-llcc
then:
properties:
@@ -148,6 +209,7 @@ allOf:
- description: LLCC6 base register region
- description: LLCC7 base register region
- description: LLCC broadcast base register region
+ - description: LLCC broadcast AND register region
reg-names:
items:
- const: llcc0_base
@@ -159,12 +221,14 @@ allOf:
- const: llcc6_base
- const: llcc7_base
- const: llcc_broadcast_base
+ - const: llcc_broadcast_and_base
- if:
properties:
compatible:
contains:
enum:
+ - qcom,qcs8300-llcc
- qcom,sdm845-llcc
- qcom,sm8150-llcc
- qcom,sm8250-llcc
diff --git a/Documentation/devicetree/bindings/clock/actions,owl-cmu.txt b/Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
deleted file mode 100644
index d19885b7c73f..000000000000
--- a/Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-* Actions Semi Owl Clock Management Unit (CMU)
-
-The Actions Semi Owl Clock Management Unit generates and supplies clock
-to various controllers within the SoC. The clock binding described here is
-applicable to S900, S700 and S500 SoC's.
-
-Required Properties:
-
-- compatible: should be one of the following,
- "actions,s900-cmu"
- "actions,s700-cmu"
- "actions,s500-cmu"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- clocks: Reference to the parent clocks ("hosc", "losc")
-- #clock-cells: should be 1.
-- #reset-cells: should be 1.
-
-Each clock is assigned an identifier, and client nodes can use this identifier
-to specify the clock which they consume.
-
-All available clocks are defined as preprocessor macros in corresponding
-dt-bindings/clock/actions,s900-cmu.h or actions,s700-cmu.h or
-actions,s500-cmu.h header and can be used in device tree sources.
-
-External clocks:
-
-The hosc clock used as input for the plls is generated outside the SoC. It is
-expected that it is defined using standard clock bindings as "hosc".
-
-Actions Semi S900 CMU also requires one more clock:
- - "losc" - internal low frequency oscillator
-
-Example: Clock Management Unit node:
-
- cmu: clock-controller@e0160000 {
- compatible = "actions,s900-cmu";
- reg = <0x0 0xe0160000 0x0 0x1000>;
- clocks = <&hosc>, <&losc>;
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
-
-Example: UART controller node that consumes clock generated by the clock
-management unit:
-
- uart: serial@e012a000 {
- compatible = "actions,s900-uart", "actions,owl-uart";
- reg = <0x0 0xe012a000 0x0 0x2000>;
- interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cmu CLK_UART5>;
- };
diff --git a/Documentation/devicetree/bindings/clock/actions,owl-cmu.yaml b/Documentation/devicetree/bindings/clock/actions,owl-cmu.yaml
new file mode 100644
index 000000000000..28396441bc98
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/actions,owl-cmu.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/actions,owl-cmu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Actions Semi Owl Clock Management Unit (CMU)
+
+maintainers:
+ - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description: |
+ The Actions Semi Owl Clock Management Unit generates and supplies clock
+ to various controllers within the SoC.
+
+ See also:
+ include/dt-bindings/clock/actions,s500-cmu.h
+ include/dt-bindings/clock/actions,s700-cmu.h
+ include/dt-bindings/clock/actions,s900-cmu.h
+
+properties:
+ compatible:
+ enum:
+ - actions,s500-cmu
+ - actions,s700-cmu
+ - actions,s900-cmu
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Host oscillator source
+ - description: Internal low frequency oscillator source
+
+ "#clock-cells":
+ const: 1
+
+ "#reset-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - "#clock-cells"
+ - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ clock-controller@e0160000 {
+ compatible = "actions,s900-cmu";
+ reg = <0xe0160000 0x1000>;
+ clocks = <&hosc>, <&losc>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
index 5e942bccf277..2b2041818a0a 100644
--- a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
+++ b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
@@ -26,9 +26,21 @@ properties:
description:
Specifies the reference clock(s) from which the output frequency is
derived. This must either reference one clock if only the first clock
- input is connected or two if both clock inputs are connected.
- minItems: 1
- maxItems: 2
+ input is connected or two if both clock inputs are connected. The last
+ clock is the AXI bus clock that needs to be enabled so we can access the
+ core registers.
+ minItems: 2
+ maxItems: 3
+
+ clock-names:
+ oneOf:
+ - items:
+ - const: clkin1
+ - const: s_axi_aclk
+ - items:
+ - const: clkin1
+ - const: clkin2
+ - const: s_axi_aclk
'#clock-cells':
const: 0
@@ -40,6 +52,7 @@ required:
- compatible
- reg
- clocks
+ - clock-names
- '#clock-cells'
additionalProperties: false
@@ -50,5 +63,6 @@ examples:
compatible = "adi,axi-clkgen-2.00.a";
#clock-cells = <0>;
reg = <0xff000000 0x1000>;
- clocks = <&osc 1>;
+ clocks = <&osc 1>, <&clkc 15>;
+ clock-names = "clkin1", "s_axi_aclk";
};
diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
index 84353fd09428..fe2c5c1baf43 100644
--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
@@ -34,8 +34,10 @@ properties:
- airoha,en7581-scu
reg:
- minItems: 2
- maxItems: 4
+ items:
+ - description: scu base address
+ - description: misc scu base address
+ minItems: 1
"#clock-cells":
description:
@@ -60,9 +62,7 @@ allOf:
then:
properties:
reg:
- items:
- - description: scu base address
- - description: misc scu base address
+ minItems: 2
'#reset-cells': false
@@ -73,11 +73,7 @@ allOf:
then:
properties:
reg:
- items:
- - description: scu base address
- - description: misc scu base address
- - description: reset base address
- - description: pb scu base address
+ maxItems: 1
additionalProperties: false
@@ -96,12 +92,9 @@ examples:
#address-cells = <2>;
#size-cells = <2>;
- scuclk: clock-controller@1fa20000 {
+ scuclk: clock-controller@1fb00000 {
compatible = "airoha,en7581-scu";
- reg = <0x0 0x1fa20000 0x0 0x400>,
- <0x0 0x1fb00000 0x0 0x90>,
- <0x0 0x1fb00830 0x0 0x8>,
- <0x0 0x1fbe3400 0x0 0xfc>;
+ reg = <0x0 0x1fb00000 0x0 0x970>;
#clock-cells = <1>;
#reset-cells = <1>;
};
diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,meson8-clkc.yaml
new file mode 100644
index 000000000000..ab73d4654171
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,meson8-clkc.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,meson8-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Meson8, Meson8b and Meson8m2 Clock and Reset Controller
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - amlogic,meson8-clkc
+ - amlogic,meson8b-clkc
+ - items:
+ - const: amlogic,meson8m2-clkc
+ - const: amlogic,meson8-clkc
+
+ clocks:
+ minItems: 2
+ maxItems: 3
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: xtal
+ - const: ddr_pll
+ - const: clk_32k
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - '#reset-cells'
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
deleted file mode 100644
index cc51e4746b3b..000000000000
--- a/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-* Amlogic Meson8, Meson8b and Meson8m2 Clock and Reset Unit
-
-The Amlogic Meson8 / Meson8b / Meson8m2 clock controller generates and
-supplies clock to various controllers within the SoC.
-
-Required Properties:
-
-- compatible: must be one of:
- - "amlogic,meson8-clkc" for Meson8 (S802) SoCs
- - "amlogic,meson8b-clkc" for Meson8 (S805) SoCs
- - "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs
-- #clock-cells: should be 1.
-- #reset-cells: should be 1.
-- clocks: list of clock phandles, one for each entry in clock-names
-- clock-names: should contain the following:
- * "xtal": the 24MHz system oscillator
- * "ddr_pll": the DDR PLL clock
- * "clk_32k": (if present) the 32kHz clock signal from GPIOAO_6 (CLK_32K_IN)
-
-Parent node should have the following properties :
-- compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon"
-- reg: base address and size of the HHI system control register space.
-
-Each clock is assigned an identifier and client nodes can use this identifier
-to specify the clock which they consume. All available clocks are defined as
-preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
-used in device tree sources.
-
-Similarly a preprocessor macro for each reset line is defined in
-dt-bindings/reset/amlogic,meson8b-clkc-reset.h (which can be used from the
-device tree sources).
-
-
-Example: Clock controller node:
-
- clkc: clock-controller {
- compatible = "amlogic,meson8b-clkc";
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
-
-
-Example: UART controller node that consumes the clock generated by the clock
- controller:
-
- uart_AO: serial@c81004c0 {
- compatible = "amlogic,meson-uart";
- reg = <0xc81004c0 0x14>;
- interrupts = <0 90 1>;
- clocks = <&clkc CLKID_CLK81>;
- };
diff --git a/Documentation/devicetree/bindings/clock/gated-fixed-clock.yaml b/Documentation/devicetree/bindings/clock/gated-fixed-clock.yaml
new file mode 100644
index 000000000000..d3e0faf3c64d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/gated-fixed-clock.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/gated-fixed-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Gated Fixed clock
+
+maintainers:
+ - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+ compatible:
+ const: gated-fixed-clock
+
+ "#clock-cells":
+ const: 0
+
+ clock-frequency: true
+
+ clock-output-names:
+ maxItems: 1
+
+ enable-gpios:
+ description:
+ Contains a single GPIO specifier for the GPIO that enables and disables
+ the oscillator.
+ maxItems: 1
+
+ vdd-supply:
+ description: handle of the regulator that provides the supply voltage
+
+required:
+ - compatible
+ - "#clock-cells"
+ - clock-frequency
+ - vdd-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ clock-1000000000 {
+ compatible = "gated-fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000000>;
+ vdd-supply = <&reg_vdd>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/imx93-clock.yaml b/Documentation/devicetree/bindings/clock/imx93-clock.yaml
index ccb53c6b96c1..98c0800732ef 100644
--- a/Documentation/devicetree/bindings/clock/imx93-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/imx93-clock.yaml
@@ -16,6 +16,7 @@ description: |
properties:
compatible:
enum:
+ - fsl,imx91-ccm
- fsl,imx93-ccm
reg:
diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml b/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml
new file mode 100644
index 000000000000..4e78933232b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa1908.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/marvell,pxa1908.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell PXA1908 Clock Controllers
+
+maintainers:
+ - Duje Mihanović <duje.mihanovic@skole.hr>
+
+description: |
+ The PXA1908 clock subsystem generates and supplies clock to various
+ controllers within the PXA1908 SoC. The PXA1908 contains numerous clock
+ controller blocks, with the ones currently supported being APBC, APBCP, MPMU
+ and APMU roughly corresponding to internal buses.
+
+ All these clock identifiers could be found in <include/dt-bindings/marvell,pxa1908.h>.
+
+properties:
+ compatible:
+ enum:
+ - marvell,pxa1908-apbc
+ - marvell,pxa1908-apbcp
+ - marvell,pxa1908-mpmu
+ - marvell,pxa1908-apmu
+
+ reg:
+ maxItems: 1
+
+ '#clock-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+ # APMU block:
+ - |
+ clock-controller@d4282800 {
+ compatible = "marvell,pxa1908-apmu";
+ reg = <0xd4282800 0x400>;
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml b/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml
index db5f48e4dd15..591a9e862c7d 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml
@@ -12,7 +12,8 @@ maintainers:
description:
The Mediatek apmixedsys controller provides PLLs to the system.
- The clock values can be found in <dt-bindings/clock/mt*-clk.h>.
+ The clock values can be found in <dt-bindings/clock/mt*-clk.h>
+ and <dt-bindings/clock/mediatek,mt*-apmixedsys.h>.
properties:
compatible:
@@ -34,6 +35,7 @@ properties:
- enum:
- mediatek,mt2701-apmixedsys
- mediatek,mt2712-apmixedsys
+ - mediatek,mt6735-apmixedsys
- mediatek,mt6765-apmixedsys
- mediatek,mt6779-apmixed
- mediatek,mt6795-apmixedsys
diff --git a/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml b/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml
index 252c46d316ee..d1d30700d9b0 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml
@@ -11,9 +11,10 @@ maintainers:
description:
The Mediatek infracfg controller provides various clocks and reset outputs
- to the system. The clock values can be found in <dt-bindings/clock/mt*-clk.h>,
- and reset values in <dt-bindings/reset/mt*-reset.h> and
- <dt-bindings/reset/mt*-resets.h>.
+ to the system. The clock values can be found in <dt-bindings/clock/mt*-clk.h>
+ and <dt-bindings/clock/mediatek,mt*-infracfg.h>, and reset values in
+ <dt-bindings/reset/mt*-reset.h>, <dt-bindings/reset/mt*-resets.h> and
+ <dt-bindings/reset/mediatek,mt*-infracfg.h>.
properties:
compatible:
@@ -22,6 +23,7 @@ properties:
- enum:
- mediatek,mt2701-infracfg
- mediatek,mt2712-infracfg
+ - mediatek,mt6735-infracfg
- mediatek,mt6765-infracfg
- mediatek,mt6795-infracfg
- mediatek,mt6779-infracfg_ao
diff --git a/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml b/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml
index 2f06baecfd23..b98cf45efe2f 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml
@@ -20,6 +20,7 @@ properties:
- enum:
- mediatek,mt2701-pericfg
- mediatek,mt2712-pericfg
+ - mediatek,mt6735-pericfg
- mediatek,mt6765-pericfg
- mediatek,mt6795-pericfg
- mediatek,mt7622-pericfg
diff --git a/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml b/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml
index 10483e26878f..a86a64893c67 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml
@@ -28,6 +28,10 @@ properties:
- mediatek,mt2712-mfgcfg
- mediatek,mt2712-vdecsys
- mediatek,mt2712-vencsys
+ - mediatek,mt6735-imgsys
+ - mediatek,mt6735-mfgcfg
+ - mediatek,mt6735-vdecsys
+ - mediatek,mt6735-vencsys
- mediatek,mt6765-camsys
- mediatek,mt6765-imgsys
- mediatek,mt6765-mipi0a
diff --git a/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml b/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml
index bdf3b55bd56f..c080fb0a1618 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml
@@ -12,7 +12,8 @@ maintainers:
description:
The Mediatek topckgen controller provides various clocks to the system.
- The clock values can be found in <dt-bindings/clock/mt*-clk.h>.
+ The clock values can be found in <dt-bindings/clock/mt*-clk.h> and
+ <dt-bindings/clock/mediatek,mt*-topckgen.h>.
properties:
compatible:
@@ -31,6 +32,7 @@ properties:
- enum:
- mediatek,mt2701-topckgen
- mediatek,mt2712-topckgen
+ - mediatek,mt6735-topckgen
- mediatek,mt6765-topckgen
- mediatek,mt6779-topckgen
- mediatek,mt6795-topckgen
diff --git a/Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml b/Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml
index df2bec188706..16106e8b637f 100644
--- a/Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml
+++ b/Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml
@@ -16,7 +16,18 @@ description: |
properties:
compatible:
- const: microchip,lan966x-gck
+ oneOf:
+ - enum:
+ - microchip,lan966x-gck
+ - microchip,lan9691-gck
+ - items:
+ - enum:
+ - microchip,lan9698-gck
+ - microchip,lan9696-gck
+ - microchip,lan9694-gck
+ - microchip,lan9693-gck
+ - microchip,lan9692-gck
+ - const: microchip,lan9691-gck
reg:
minItems: 1
diff --git a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml b/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml
deleted file mode 100644
index 2d4f2cde1e58..000000000000
--- a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml
+++ /dev/null
@@ -1,51 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/clock/mobileye,eyeq5-clk.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Mobileye EyeQ5 clock controller
-
-description:
- The EyeQ5 clock controller handles 10 read-only PLLs derived from the main
- crystal clock. It also exposes one divider clock, a child of one of the PLLs.
- Its registers live in a shared region called OLB.
-
-maintainers:
- - Grégory Clement <gregory.clement@bootlin.com>
- - Théo Lebrun <theo.lebrun@bootlin.com>
- - Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
-
-properties:
- compatible:
- const: mobileye,eyeq5-clk
-
- reg:
- maxItems: 2
-
- reg-names:
- items:
- - const: plls
- - const: ospi
-
- "#clock-cells":
- const: 1
-
- clocks:
- maxItems: 1
- description:
- Input parent clock to all PLLs. Expected to be the main crystal.
-
- clock-names:
- items:
- - const: ref
-
-required:
- - compatible
- - reg
- - reg-names
- - "#clock-cells"
- - clocks
- - clock-names
-
-additionalProperties: false
diff --git a/Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml b/Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml
index 5dc360b2ea4b..d0291bfff23a 100644
--- a/Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml
+++ b/Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml
@@ -13,9 +13,10 @@ properties:
compatible:
items:
- enum:
- - nxp,imx95-lvds-csr
- - nxp,imx95-display-csr
- nxp,imx95-camera-csr
+ - nxp,imx95-display-csr
+ - nxp,imx95-hsio-blk-ctl
+ - nxp,imx95-lvds-csr
- nxp,imx95-netcmix-blk-ctrl
- nxp,imx95-vpu-csr
- const: syscon
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml
index d848361beeb3..77273aee5d52 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml
@@ -17,7 +17,9 @@ description: |
properties:
compatible:
- const: qcom,gcc-sm8450
+ enum:
+ - qcom,gcc-sm8450
+ - qcom,sm8475-gcc
clocks:
items:
diff --git a/Documentation/devicetree/bindings/clock/qcom,ipq5332-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,ipq5332-gcc.yaml
index 9193de681de2..1230183fc0a9 100644
--- a/Documentation/devicetree/bindings/clock/qcom,ipq5332-gcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq5332-gcc.yaml
@@ -4,31 +4,35 @@
$id: http://devicetree.org/schemas/clock/qcom,ipq5332-gcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller on IPQ5332
+title: Qualcomm Global Clock & Reset Controller on IPQ5332 and IPQ5424
maintainers:
- Bjorn Andersson <andersson@kernel.org>
description: |
Qualcomm global clock control module provides the clocks, resets and power
- domains on IPQ5332.
+ domains on IPQ5332 and IPQ5424.
- See also:: include/dt-bindings/clock/qcom,gcc-ipq5332.h
-
-allOf:
- - $ref: qcom,gcc.yaml#
+ See also:
+ include/dt-bindings/clock/qcom,gcc-ipq5332.h
+ include/dt-bindings/clock/qcom,gcc-ipq5424.h
properties:
compatible:
- const: qcom,ipq5332-gcc
+ enum:
+ - qcom,ipq5332-gcc
+ - qcom,ipq5424-gcc
clocks:
+ minItems: 5
items:
- description: Board XO clock source
- description: Sleep clock source
- description: PCIE 2lane PHY pipe clock source
- description: PCIE 2lane x1 PHY pipe clock source (For second lane)
- description: USB PCIE wrapper pipe clock source
+ - description: PCIE 2-lane PHY2 pipe clock source
+ - description: PCIE 2-lane PHY3 pipe clock source
'#power-domain-cells': false
'#interconnect-cells':
@@ -38,6 +42,29 @@ required:
- compatible
- clocks
+allOf:
+ - $ref: qcom,gcc.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: qcom,ipq5332-gcc
+ then:
+ properties:
+ clocks:
+ maxItems: 5
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: qcom,ipq5424-gcc
+ then:
+ properties:
+ clocks:
+ minItems: 7
+ maxItems: 7
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/clock/qcom,qcs8300-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcs8300-gcc.yaml
new file mode 100644
index 000000000000..081bc452081f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,qcs8300-gcc.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,qcs8300-gcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. Global Clock & Reset Controller on QCS8300
+
+maintainers:
+ - Taniya Das <quic_tdas@quicinc.com>
+ - Imran Shaik <quic_imrashai@quicinc.com>
+
+description: |
+ Qualcomm Technologies, Inc. Global clock control module provides the clocks, resets and
+ power domains on QCS8300
+
+ See also: include/dt-bindings/clock/qcom,qcs8300-gcc.h
+
+properties:
+ compatible:
+ const: qcom,qcs8300-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 Phy Auxiliary clock source
+ - description: First EMAC controller reference clock
+ - 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
+ - '#power-domain-cells'
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@100000 {
+ compatible = "qcom,qcs8300-gcc";
+ reg = <0x00100000 0xc7018>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&sleep_clk>,
+ <&pcie_0_pipe_clk>,
+ <&pcie_1_pipe_clk>,
+ <&pcie_phy_aux_clk>,
+ <&rxc0_ref_clk>,
+ <&ufs_phy_rx_symbol_0_clk>,
+ <&ufs_phy_rx_symbol_1_clk>,
+ <&ufs_phy_tx_symbol_0_clk>,
+ <&usb3_phy_wrapper_gcc_usb30_prim_pipe_clk>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
index ca857942ed6c..a561a306b947 100644
--- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
@@ -19,6 +19,7 @@ properties:
enum:
- qcom,qdu1000-rpmh-clk
- qcom,sa8775p-rpmh-clk
+ - qcom,sar2130p-rpmh-clk
- qcom,sc7180-rpmh-clk
- qcom,sc7280-rpmh-clk
- qcom,sc8180x-rpmh-clk
diff --git a/Documentation/devicetree/bindings/clock/qcom,sa8775p-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sa8775p-camcc.yaml
new file mode 100644
index 000000000000..36a60d8f5ae3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sa8775p-camcc.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,sa8775p-camcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Camera Clock & Reset Controller on SA8775P
+
+maintainers:
+ - Taniya Das <quic_tdas@quicinc.com>
+
+description: |
+ Qualcomm camera clock control module provides the clocks, resets and power
+ domains on SA8775p.
+
+ See also: include/dt-bindings/clock/qcom,sa8775p-camcc.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sa8775p-camcc
+
+ clocks:
+ items:
+ - description: Camera AHB clock from GCC
+ - description: Board XO source
+ - description: Board active XO source
+ - description: Sleep clock source
+
+ power-domains:
+ maxItems: 1
+ description: MMCX power domain
+
+required:
+ - compatible
+ - clocks
+ - power-domains
+ - '#power-domain-cells'
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+ #include <dt-bindings/clock/qcom,sa8775p-gcc.h>
+ clock-controller@ade0000 {
+ compatible = "qcom,sa8775p-camcc";
+ reg = <0x0ade0000 0x20000>;
+ clocks = <&gcc GCC_CAMERA_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&sleep_clk>;
+ power-domains = <&rpmhpd SA8775P_MMCX>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sa8775p-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sa8775p-dispcc.yaml
new file mode 100644
index 000000000000..ce61755e62d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sa8775p-dispcc.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sa8775p-dispcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display Clock & Reset Controller on SA8775P
+
+maintainers:
+ - Taniya Das <quic_tdas@quicinc.com>
+
+description: |
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SA8775P.
+
+ See also: include/dt-bindings/clock/qcom,sa8775p-dispcc.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sa8775p-dispcc0
+ - qcom,sa8775p-dispcc1
+
+ clocks:
+ items:
+ - description: GCC AHB clock source
+ - description: Board XO source
+ - description: Board XO_AO source
+ - description: Sleep clock source
+ - description: Link clock from DP0 PHY
+ - description: VCO DIV clock from DP0 PHY
+ - description: Link clock from DP1 PHY
+ - description: VCO DIV clock from DP1 PHY
+ - description: Byte clock from DSI0 PHY
+ - description: Pixel clock from DSI0 PHY
+ - description: Byte clock from DSI1 PHY
+ - description: Pixel clock from DSI1 PHY
+
+ power-domains:
+ maxItems: 1
+ description: MMCX power domain
+
+required:
+ - compatible
+ - clocks
+ - power-domains
+ - '#power-domain-cells'
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+ #include <dt-bindings/clock/qcom,sa8775p-gcc.h>
+ clock-controller@af00000 {
+ compatible = "qcom,sa8775p-dispcc0";
+ reg = <0x0af00000 0x20000>;
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&sleep_clk>,
+ <&dp_phy0 0>,
+ <&dp_phy0 1>,
+ <&dp_phy1 2>,
+ <&dp_phy1 3>,
+ <&dsi_phy0 0>,
+ <&dsi_phy0 1>,
+ <&dsi_phy1 2>,
+ <&dsi_phy1 3>;
+ power-domains = <&rpmhpd SA8775P_MMCX>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sa8775p-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sa8775p-videocc.yaml
new file mode 100644
index 000000000000..928131bff4c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sa8775p-videocc.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,sa8775p-videocc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Video Clock & Reset Controller on SA8775P
+
+maintainers:
+ - Taniya Das <quic_tdas@quicinc.com>
+
+description: |
+ Qualcomm video clock control module provides the clocks, resets and power
+ domains on SA8775P.
+
+ See also: include/dt-bindings/clock/qcom,sa8775p-videocc.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sa8775p-videocc
+
+ clocks:
+ items:
+ - description: Video AHB clock from GCC
+ - description: Board XO source
+ - description: Board active XO source
+ - description: Sleep Clock source
+
+ power-domains:
+ maxItems: 1
+ description: MMCX power domain
+
+required:
+ - compatible
+ - clocks
+ - power-domains
+ - '#power-domain-cells'
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+ #include <dt-bindings/clock/qcom,sa8775p-gcc.h>
+ videocc: clock-controller@abf0000 {
+ compatible = "qcom,sa8775p-videocc";
+ reg = <0x0abf0000 0x10000>;
+ clocks = <&gcc GCC_VIDEO_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&sleep_clk>;
+ power-domains = <&rpmhpd SA8775P_MMCX>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sar2130p-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sar2130p-gcc.yaml
new file mode 100644
index 000000000000..9a430bbd872a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sar2130p-gcc.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sar2130p-gcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller on sar2130p
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+description: |
+ Qualcomm global clock control module provides the clocks, resets and
+ power domains on sar2130p.
+
+ See also: include/dt-bindings/clock/qcom,sar2130p-gcc.h
+
+properties:
+ compatible:
+ const: qcom,sar2130p-gcc
+
+ clocks:
+ items:
+ - description: XO reference clock
+ - description: Sleep clock
+ - description: PCIe 0 pipe clock
+ - description: PCIe 1 pipe clock
+ - description: Primary USB3 PHY wrapper pipe clock
+
+ protected-clocks:
+ maxItems: 240
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - '#power-domain-cells'
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/power/qcom,rpmhpd.h>
+
+ gcc: clock-controller@100000 {
+ compatible = "qcom,sar2130p-gcc";
+ reg = <0x100000 0x1f4200>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&sleep_clk>,
+ <&pcie_0_pipe_clk>,
+ <&pcie_1_pipe_clk>,
+ <&usb_0_ssphy>;
+ power-domains = <&rpmhpd RPMHPD_CX>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
index 26afbbe65511..0766f66c7dc4 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
@@ -26,6 +26,7 @@ properties:
enum:
- qcom,sc8280xp-camcc
- qcom,sm8450-camcc
+ - qcom,sm8475-camcc
- qcom,sm8550-camcc
- qcom,sm8650-camcc
- qcom,x1e80100-camcc
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml
index 4794c53793a8..e9123bbfd491 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml
@@ -19,6 +19,7 @@ properties:
compatible:
enum:
- qcom,sm8450-dispcc
+ - qcom,sm8475-dispcc
clocks:
minItems: 3
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml
index 2d2c59aa8c6b..5c65f5ecf0f3 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml
@@ -14,6 +14,7 @@ description: |
domains on Qualcomm SoCs.
See also::
+ include/dt-bindings/clock/qcom,sar2130p-gpucc.h
include/dt-bindings/clock/qcom,sm4450-gpucc.h
include/dt-bindings/clock/qcom,sm8450-gpucc.h
include/dt-bindings/clock/qcom,sm8550-gpucc.h
@@ -24,8 +25,10 @@ description: |
properties:
compatible:
enum:
+ - qcom,sar2130p-gpucc
- qcom,sm4450-gpucc
- qcom,sm8450-gpucc
+ - qcom,sm8475-gpucc
- qcom,sm8550-gpucc
- qcom,sm8650-gpucc
- qcom,x1e80100-gpucc
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml
index 9829ba28fe0e..62714fa54db8 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml
@@ -22,6 +22,7 @@ properties:
compatible:
enum:
- qcom,sm8450-videocc
+ - qcom,sm8475-videocc
- qcom,sm8550-videocc
- qcom,sm8650-videocc
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
index c17035a180db..c57d55a9293c 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
@@ -22,6 +22,7 @@ description: |
properties:
compatible:
enum:
+ - qcom,sar2130p-dispcc
- qcom,sm8550-dispcc
- qcom,sm8650-dispcc
- qcom,x1e80100-dispcc
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml
index 48fdd562d743..3b546deb514a 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-tcsr.yaml
@@ -21,6 +21,7 @@ properties:
compatible:
items:
- enum:
+ - qcom,sar2130p-tcsr
- qcom,sm8550-tcsr
- qcom,sm8650-tcsr
- qcom,x1e80100-tcsr
diff --git a/Documentation/devicetree/bindings/clock/renesas,r9a08g045-vbattb.yaml b/Documentation/devicetree/bindings/clock/renesas,r9a08g045-vbattb.yaml
new file mode 100644
index 000000000000..3707e4118949
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/renesas,r9a08g045-vbattb.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/renesas,r9a08g045-vbattb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas Battery Backup Function (VBATTB)
+
+description:
+ Renesas VBATTB is an always on powered module (backed by battery) which
+ controls the RTC clock (VBATTCLK), tamper detection logic and a small
+ general usage memory (128B).
+
+maintainers:
+ - Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+properties:
+ compatible:
+ const: renesas,r9a08g045-vbattb
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: tamper detector interrupt
+
+ clocks:
+ items:
+ - description: VBATTB module clock
+ - description: RTC input clock (crystal or external clock device)
+
+ clock-names:
+ items:
+ - const: bclk
+ - const: rtx
+
+ '#clock-cells':
+ const: 1
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: VBATTB module reset
+
+ quartz-load-femtofarads:
+ description: load capacitance of the on board crystal
+ enum: [ 4000, 7000, 9000, 12500 ]
+ default: 4000
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - '#clock-cells'
+ - power-domains
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a08g045-cpg.h>
+ #include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ clock-controller@1005c000 {
+ compatible = "renesas,r9a08g045-vbattb";
+ reg = <0x1005c000 0x1000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD R9A08G045_VBAT_BCLK>, <&vbattb_xtal>;
+ clock-names = "bclk", "rtx";
+ assigned-clocks = <&vbattb VBATTB_MUX>;
+ assigned-clock-parents = <&vbattb VBATTB_XC>;
+ #clock-cells = <1>;
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_VBAT_BRESETN>;
+ quartz-load-femtofarads = <12500>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
deleted file mode 100644
index 904ae682ea90..000000000000
--- a/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-* Rockchip RK3328 Clock and Reset Unit
-
-The RK3328 clock controller generates and supplies clock to various
-controllers within the SoC and also implements a reset controller for SoC
-peripherals.
-
-Required Properties:
-
-- compatible: should be "rockchip,rk3328-cru"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- #clock-cells: should be 1.
-- #reset-cells: should be 1.
-
-Optional Properties:
-
-- rockchip,grf: phandle to the syscon managing the "general register files"
- If missing pll rates are not changeable, due to the missing pll lock status.
-
-Each clock is assigned an identifier and client nodes can use this identifier
-to specify the clock which they consume. All available clocks are defined as
-preprocessor macros in the dt-bindings/clock/rk3328-cru.h headers and can be
-used in device tree sources. Similar macros exist for the reset sources in
-these files.
-
-External clocks:
-
-There are several clocks that are generated outside the SoC. It is expected
-that they are defined using standard clock bindings with following
-clock-output-names:
- - "xin24m" - crystal input - required,
- - "clkin_i2s" - external I2S clock - optional,
- - "gmac_clkin" - external GMAC clock - optional
- - "phy_50m_out" - output clock of the pll in the mac phy
- - "hdmi_phy" - output clock of the hdmi phy pll - optional
-
-Example: Clock controller node:
-
- cru: clock-controller@ff440000 {
- compatible = "rockchip,rk3328-cru";
- reg = <0x0 0xff440000 0x0 0x1000>;
- rockchip,grf = <&grf>;
-
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
-
-Example: UART controller node that consumes the clock generated by the clock
- controller:
-
- uart0: serial@ff120000 {
- compatible = "snps,dw-apb-uart";
- reg = <0xff120000 0x100>;
- interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
- reg-shift = <2>;
- reg-io-width = <4>;
- clocks = <&cru SCLK_UART0>;
- };
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.yaml
new file mode 100644
index 000000000000..f079c7a2559b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/rockchip,rk3328-cru.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip RK3328 Clock and Reset Unit (CRU)
+
+maintainers:
+ - Elaine Zhang <zhangqing@rock-chips.com>
+ - Heiko Stuebner <heiko@sntech.de>
+
+description: |
+ The RK3328 clock controller generates and supplies clocks to various
+ controllers within the SoC and also implements a reset controller for SoC
+ peripherals.
+ Each clock is assigned an identifier and client nodes can use this identifier
+ to specify the clock which they consume. All available clocks are defined as
+ preprocessor macros in the dt-bindings/clock/rk3328-cru.h headers and can be
+ used in device tree sources. Similar macros exist for the reset sources in
+ these files.
+ There are several clocks that are generated outside the SoC. It is expected
+ that they are defined using standard clock bindings with following
+ clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "clkin_i2s" - external I2S clock - optional,
+ - "gmac_clkin" - external GMAC clock - optional
+ - "phy_50m_out" - output clock of the pll in the mac phy
+ - "hdmi_phy" - output clock of the hdmi phy pll - optional
+
+properties:
+ compatible:
+ enum:
+ - rockchip,rk3328-cru
+
+ reg:
+ maxItems: 1
+
+ "#clock-cells":
+ const: 1
+
+ "#reset-cells":
+ const: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: xin24m
+
+ rockchip,grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon managing the "general register files" (GRF),
+ if missing pll rates are not changeable, due to the missing pll
+ lock status.
+
+required:
+ - compatible
+ - reg
+ - "#clock-cells"
+ - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ cru: clock-controller@ff440000 {
+ compatible = "rockchip,rk3328-cru";
+ reg = <0xff440000 0x1000>;
+ rockchip,grf = <&grf>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos8895-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos8895-clock.yaml
new file mode 100644
index 000000000000..111de33ce00b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,exynos8895-clock.yaml
@@ -0,0 +1,239 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/samsung,exynos8895-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos8895 SoC clock controller
+
+maintainers:
+ - Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+ - Chanwoo Choi <cw00.choi@samsung.com>
+ - Krzysztof Kozlowski <krzk@kernel.org>
+
+description: |
+ Exynos8895 clock controller is comprised of several CMU units, generating
+ clocks for different domains. Those CMU units are modeled as separate device
+ tree nodes, and might depend on each other. The root clock in that root tree
+ is an external clock: OSCCLK (26 MHz). This external clock must be defined
+ as a fixed-rate clock in dts.
+
+ CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and
+ dividers; all other clocks of function blocks (other CMUs) are usually
+ derived from CMU_TOP.
+
+ Each clock is assigned an identifier and client nodes can use this identifier
+ to specify the clock which they consume. All clocks available for usage
+ in clock consumer nodes are defined as preprocessor macros in
+ 'include/dt-bindings/clock/samsung,exynos8895.h' header.
+
+properties:
+ compatible:
+ enum:
+ - samsung,exynos8895-cmu-fsys0
+ - samsung,exynos8895-cmu-fsys1
+ - samsung,exynos8895-cmu-peric0
+ - samsung,exynos8895-cmu-peric1
+ - samsung,exynos8895-cmu-peris
+ - samsung,exynos8895-cmu-top
+
+ clocks:
+ minItems: 1
+ maxItems: 16
+
+ clock-names:
+ minItems: 1
+ maxItems: 16
+
+ "#clock-cells":
+ const: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - reg
+ - "#clock-cells"
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos8895-cmu-fsys0
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: CMU_FSYS0 BUS clock (from CMU_TOP)
+ - description: CMU_FSYS0 DPGTC clock (from CMU_TOP)
+ - description: CMU_FSYS0 MMC_EMBD clock (from CMU_TOP)
+ - description: CMU_FSYS0 UFS_EMBD clock (from CMU_TOP)
+ - description: CMU_FSYS0 USBDRD30 clock (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: bus
+ - const: dpgtc
+ - const: mmc
+ - const: ufs
+ - const: usbdrd30
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos8895-cmu-fsys1
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: CMU_FSYS1 BUS clock (from CMU_TOP)
+ - description: CMU_FSYS1 PCIE clock (from CMU_TOP)
+ - description: CMU_FSYS1 UFS_CARD clock (from CMU_TOP)
+ - description: CMU_FSYS1 MMC_CARD clock (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: bus
+ - const: pcie
+ - const: ufs
+ - const: mmc
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos8895-cmu-peric0
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: CMU_PERIC0 BUS clock (from CMU_TOP)
+ - description: CMU_PERIC0 UART_DBG clock (from CMU_TOP)
+ - description: CMU_PERIC0 USI00 clock (from CMU_TOP)
+ - description: CMU_PERIC0 USI01 clock (from CMU_TOP)
+ - description: CMU_PERIC0 USI02 clock (from CMU_TOP)
+ - description: CMU_PERIC0 USI03 clock (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: bus
+ - const: uart
+ - const: usi0
+ - const: usi1
+ - const: usi2
+ - const: usi3
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos8895-cmu-peric1
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: CMU_PERIC1 BUS clock (from CMU_TOP)
+ - description: CMU_PERIC1 SPEEDY2 clock (from CMU_TOP)
+ - description: CMU_PERIC1 SPI_CAM0 clock (from CMU_TOP)
+ - description: CMU_PERIC1 SPI_CAM1 clock (from CMU_TOP)
+ - description: CMU_PERIC1 UART_BT clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI04 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI05 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI06 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI07 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI08 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI09 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI10 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI11 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI12 clock (from CMU_TOP)
+ - description: CMU_PERIC1 USI13 clock (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: bus
+ - const: speedy
+ - const: cam0
+ - const: cam1
+ - const: uart
+ - const: usi4
+ - const: usi5
+ - const: usi6
+ - const: usi7
+ - const: usi8
+ - const: usi9
+ - const: usi10
+ - const: usi11
+ - const: usi12
+ - const: usi13
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos8895-cmu-peris
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+ - description: CMU_PERIS BUS clock (from CMU_TOP)
+
+ clock-names:
+ items:
+ - const: oscclk
+ - const: bus
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: samsung,exynos8895-cmu-top
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External reference clock (26 MHz)
+
+ clock-names:
+ items:
+ - const: oscclk
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/samsung,exynos8895.h>
+
+ cmu_fsys1: clock-controller@11400000 {
+ compatible = "samsung,exynos8895-cmu-fsys1";
+ reg = <0x11400000 0x8000>;
+ #clock-cells = <1>;
+
+ clocks = <&oscclk>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_BUS>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_PCIE>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_UFS_CARD>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_MMC_CARD>;
+ clock-names = "oscclk", "bus", "pcie", "ufs", "mmc";
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/clock/ti/composite.txt b/Documentation/devicetree/bindings/clock/ti/composite.txt
index 6f7e1331b546..238e6f7d74f8 100644
--- a/Documentation/devicetree/bindings/clock/ti/composite.txt
+++ b/Documentation/devicetree/bindings/clock/ti/composite.txt
@@ -16,8 +16,8 @@ merged to this clock. The component clocks shall be of one of the
"ti,*composite*-clock" types.
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/clock/ti/mux.txt
-[3] Documentation/devicetree/bindings/clock/ti/divider.txt
+[2] Documentation/devicetree/bindings/clock/ti/ti,mux-clock.yaml
+[3] Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml
[4] Documentation/devicetree/bindings/clock/ti/gate.txt
Required properties:
diff --git a/Documentation/devicetree/bindings/clock/ti/divider.txt b/Documentation/devicetree/bindings/clock/ti/divider.txt
deleted file mode 100644
index 4d7c76f0b356..000000000000
--- a/Documentation/devicetree/bindings/clock/ti/divider.txt
+++ /dev/null
@@ -1,115 +0,0 @@
-Binding for TI divider clock
-
-This binding uses the common clock binding[1]. It assumes a
-register-mapped adjustable clock rate divider that does not gate and has
-only one input clock or parent. By default the value programmed into
-the register is one less than the actual divisor value. E.g:
-
-register value actual divisor value
-0 1
-1 2
-2 3
-
-This assumption may be modified by the following optional properties:
-
-ti,index-starts-at-one - valid divisor values start at 1, not the default
-of 0. E.g:
-register value actual divisor value
-1 1
-2 2
-3 3
-
-ti,index-power-of-two - valid divisor values are powers of two. E.g:
-register value actual divisor value
-0 1
-1 2
-2 4
-
-Additionally an array of valid dividers may be supplied like so:
-
- ti,dividers = <4>, <8>, <0>, <16>;
-
-Which will map the resulting values to a divisor table by their index:
-register value actual divisor value
-0 4
-1 8
-2 <invalid divisor, skipped>
-3 16
-
-Any zero value in this array means the corresponding bit-value is invalid
-and must not be used.
-
-The binding must also provide the register to control the divider and
-unless the divider array is provided, min and max dividers. Optionally
-the number of bits to shift that mask, if necessary. If the shift value
-is missing it is the same as supplying a zero shift.
-
-This binding can also optionally provide support to the hardware autoidle
-feature, see [2].
-
-[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/clock/ti/autoidle.txt
-
-Required properties:
-- compatible : shall be "ti,divider-clock" or "ti,composite-divider-clock".
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : link to phandle of parent clock
-- reg : offset for register controlling adjustable divider
-
-Optional properties:
-- clock-output-names : from common clock binding.
-- ti,dividers : array of integers defining divisors
-- ti,bit-shift : number of bits to shift the divider value, defaults to 0
-- ti,min-div : min divisor for dividing the input clock rate, only
- needed if the first divisor is offset from the default value (1)
-- ti,max-div : max divisor for dividing the input clock rate, only needed
- if ti,dividers is not defined.
-- ti,index-starts-at-one : valid divisor programming starts at 1, not zero,
- only valid if ti,dividers is not defined.
-- ti,index-power-of-two : valid divisor programming must be a power of two,
- only valid if ti,dividers is not defined.
-- ti,autoidle-shift : bit shift of the autoidle enable bit for the clock,
- see [2]
-- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0,
- see [2]
-- ti,set-rate-parent : clk_set_rate is propagated to parent
-- ti,latch-bit : latch the divider value to HW, only needed if the register
- access requires this. As an example dra76x DPLL_GMAC H14 divider implements
- such behavior.
-
-Examples:
-dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 {
- #clock-cells = <0>;
- compatible = "ti,divider-clock";
- clocks = <&dpll_usb_ck>;
- ti,max-div = <127>;
- reg = <0x190>;
- ti,index-starts-at-one;
-};
-
-aess_fclk: aess_fclk@4a004528 {
- #clock-cells = <0>;
- compatible = "ti,divider-clock";
- clocks = <&abe_clk>;
- ti,bit-shift = <24>;
- reg = <0x528>;
- ti,max-div = <2>;
-};
-
-dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck {
- #clock-cells = <0>;
- compatible = "ti,composite-divider-clock";
- clocks = <&dpll_core_x2_ck>;
- ti,max-div = <31>;
- reg = <0x0134>;
- ti,index-starts-at-one;
-};
-
-ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2 {
- #clock-cells = <0>;
- compatible = "ti,composite-divider-clock";
- clocks = <&corex2_fck>;
- ti,bit-shift = <8>;
- reg = <0x0a40>;
- ti,dividers = <0>, <1>, <2>, <3>, <4>, <0>, <6>, <0>, <8>;
-};
diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt
deleted file mode 100644
index 85fb1f2d2d28..000000000000
--- a/Documentation/devicetree/bindings/clock/ti/interface.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-Binding for Texas Instruments interface clock.
-
-This binding uses the common clock binding[1]. This clock is
-quite much similar to the basic gate-clock [2], however,
-it supports a number of additional features, including
-companion clock finding (match corresponding functional gate
-clock) and hardware autoidle enable / disable.
-
-[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
-
-Required properties:
-- compatible : shall be one of:
- "ti,omap3-interface-clock" - basic OMAP3 interface clock
- "ti,omap3-no-wait-interface-clock" - interface clock which has no hardware
- capability for waiting clock to be ready
- "ti,omap3-hsotgusb-interface-clock" - interface clock with USB specific HW
- handling
- "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling
- "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling
- "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling
- "ti,omap2430-interface-clock" - interface clock with OMAP2430 specific HW
- handling
-- #clock-cells : from common clock binding; shall be set to 0
-- clocks : link to phandle of parent clock
-- reg : base address for the control register
-
-Optional properties:
-- clock-output-names : from common clock binding.
-- ti,bit-shift : bit shift for the bit enabling/disabling the clock (default 0)
-
-Examples:
- aes1_ick: aes1_ick@48004a14 {
- #clock-cells = <0>;
- compatible = "ti,omap3-interface-clock";
- clocks = <&security_l4_ick2>;
- reg = <0x48004a14 0x4>;
- ti,bit-shift = <3>;
- };
-
- cam_ick: cam_ick@48004f10 {
- #clock-cells = <0>;
- compatible = "ti,omap3-no-wait-interface-clock";
- clocks = <&l4_ick>;
- reg = <0x48004f10 0x4>;
- ti,bit-shift = <0>;
- };
-
- ssi_ick_3430es2: ssi_ick_3430es2@48004a10 {
- #clock-cells = <0>;
- compatible = "ti,omap3-ssi-interface-clock";
- clocks = <&ssi_l4_ick>;
- reg = <0x48004a10 0x4>;
- ti,bit-shift = <0>;
- };
diff --git a/Documentation/devicetree/bindings/clock/ti/mux.txt b/Documentation/devicetree/bindings/clock/ti/mux.txt
deleted file mode 100644
index cd56d3c1c09f..000000000000
--- a/Documentation/devicetree/bindings/clock/ti/mux.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-Binding for TI mux clock.
-
-This binding uses the common clock binding[1]. It assumes a
-register-mapped multiplexer with multiple input clock signals or
-parents, one of which can be selected as output. This clock does not
-gate or adjust the parent rate via a divider or multiplier.
-
-By default the "clocks" property lists the parents in the same order
-as they are programmed into the register. E.g:
-
- clocks = <&foo_clock>, <&bar_clock>, <&baz_clock>;
-
-results in programming the register as follows:
-
-register value selected parent clock
-0 foo_clock
-1 bar_clock
-2 baz_clock
-
-Some clock controller IPs do not allow a value of zero to be programmed
-into the register, instead indexing begins at 1. The optional property
-"index-starts-at-one" modified the scheme as follows:
-
-register value selected clock parent
-1 foo_clock
-2 bar_clock
-3 baz_clock
-
-The binding must provide the register to control the mux. Optionally
-the number of bits to shift the control field in the register can be
-supplied. If the shift value is missing it is the same as supplying
-a zero shift.
-
-[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-
-Required properties:
-- compatible : shall be "ti,mux-clock" or "ti,composite-mux-clock".
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : link phandles of parent clocks
-- reg : register offset for register controlling adjustable mux
-
-Optional properties:
-- clock-output-names : from common clock binding.
-- ti,bit-shift : number of bits to shift the bit-mask, defaults to
- 0 if not present
-- ti,index-starts-at-one : valid input select programming starts at 1, not
- zero
-- ti,set-rate-parent : clk_set_rate is propagated to parent clock,
- not supported by the composite-mux-clock subtype
-- ti,latch-bit : latch the mux value to HW, only needed if the register
- access requires this. As an example, dra7x DPLL_GMAC H14 muxing
- implements such behavior.
-
-Examples:
-
-sys_clkin_ck: sys_clkin_ck@4a306110 {
- #clock-cells = <0>;
- compatible = "ti,mux-clock";
- clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
- reg = <0x0110>;
- ti,index-starts-at-one;
-};
-
-abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck@4a306108 {
- #clock-cells = <0>;
- compatible = "ti,mux-clock";
- clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
- ti,bit-shift = <24>;
- reg = <0x0108>;
-};
-
-mcbsp5_mux_fck: mcbsp5_mux_fck {
- #clock-cells = <0>;
- compatible = "ti,composite-mux-clock";
- clocks = <&core_96m_fck>, <&mcbsp_clks>;
- ti,bit-shift = <4>;
- reg = <0x02d8>;
-};
diff --git a/Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml b/Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml
new file mode 100644
index 000000000000..3fbe236eb565
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml
@@ -0,0 +1,193 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/ti/ti,divider-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments divider clock
+
+maintainers:
+ - Tero Kristo <kristo@kernel.org>
+
+description: |
+ This clock It assumes a register-mapped adjustable clock rate divider
+ that does not gate and has only one input clock or parent. By default the
+ value programmed into the register is one less than the actual divisor value.
+ E.g:
+
+ register value actual divisor value
+ 0 1
+ 1 2
+ 2 3
+
+ This assumption may be modified by the following optional properties:
+
+ ti,index-starts-at-one - valid divisor values start at 1, not the default
+ of 0. E.g:
+ register value actual divisor value
+ 1 1
+ 2 2
+ 3 3
+
+ ti,index-power-of-two - valid divisor values are powers of two. E.g:
+ register value actual divisor value
+ 0 1
+ 1 2
+ 2 4
+
+ Additionally an array of valid dividers may be supplied like so:
+
+ ti,dividers = <4>, <8>, <0>, <16>;
+
+ Which will map the resulting values to a divisor table by their index:
+ register value actual divisor value
+ 0 4
+ 1 8
+ 2 <invalid divisor, skipped>
+ 3 16
+
+ Any zero value in this array means the corresponding bit-value is invalid
+ and must not be used.
+
+ The binding must also provide the register to control the divider and
+ unless the divider array is provided, min and max dividers. Optionally
+ the number of bits to shift that mask, if necessary. If the shift value
+ is missing it is the same as supplying a zero shift.
+
+ This binding can also optionally provide support to the hardware autoidle
+ feature, see [1].
+
+ [1] Documentation/devicetree/bindings/clock/ti/autoidle.txt
+
+properties:
+ compatible:
+ enum:
+ - ti,divider-clock
+ - ti,composite-divider-clock
+
+ "#clock-cells":
+ const: 0
+
+ clocks:
+ maxItems: 1
+
+ clock-output-names:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+ ti,dividers:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ array of integers defining divisors
+
+ ti,bit-shift:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ number of bits to shift the divider value
+ maximum: 31
+ default: 0
+
+ ti,min-div:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ min divisor for dividing the input clock rate, only
+ needed if the first divisor is offset from the default value (1)
+ minimum: 1
+ default: 1
+
+
+ ti,max-div:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ max divisor for dividing the input clock rate, only needed
+ if ti,dividers is not defined.
+
+ ti,index-starts-at-one:
+ type: boolean
+ description:
+ valid divisor programming starts at 1, not zero,
+ only valid if ti,dividers is not defined
+
+ ti,index-power-of-two:
+ type: boolean
+ description:
+ valid divisor programming must be a power of two,
+ only valid if ti,dividers is not defined.
+
+ ti,autoidle-shift:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ bit shift of the autoidle enable bit for the clock,
+ see [1].
+ maximum: 31
+ default: 0
+
+ ti,invert-autoidle-bit:
+ type: boolean
+ description:
+ autoidle is enabled by setting the bit to 0,
+ see [1]
+
+ ti,set-rate-parent:
+ type: boolean
+ description:
+ clk_set_rate is propagated to parent |
+
+ ti,latch-bit:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ latch the divider value to HW, only needed if the register
+ compatible access requires this. As an example dra76x DPLL_GMAC
+ H14 divider implements such behavior.
+
+dependentSchemas:
+ ti,dividers:
+ properties:
+ ti,min-div: false
+ ti,max-div: false
+ ti,index-power-of-two: false
+ ti,index-starts-at-one: false
+
+required:
+ - compatible
+ - "#clock-cells"
+ - clocks
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clock-controller@190 {
+ #clock-cells = <0>;
+ compatible = "ti,divider-clock";
+ clocks = <&dpll_usb_ck>;
+ ti,max-div = <127>;
+ reg = <0x190>;
+ ti,index-starts-at-one;
+ };
+
+ clock-controller@528 {
+ #clock-cells = <0>;
+ compatible = "ti,divider-clock";
+ clocks = <&abe_clk>;
+ ti,bit-shift = <24>;
+ reg = <0x528>;
+ ti,max-div = <2>;
+ };
+
+ clock-controller@a40 {
+ #clock-cells = <0>;
+ compatible = "ti,composite-divider-clock";
+ clocks = <&corex2_fck>;
+ ti,bit-shift = <8>;
+ reg = <0x0a40>;
+ ti,dividers = <0>, <1>, <2>, <3>, <4>, <0>, <6>, <0>, <8>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/clock/ti/ti,interface-clock.yaml b/Documentation/devicetree/bindings/clock/ti/ti,interface-clock.yaml
new file mode 100644
index 000000000000..1eaf95d88e0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/ti,interface-clock.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/ti/ti,interface-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments interface clock.
+
+maintainers:
+ - Tero Kristo <kristo@kernel.org>
+
+description: |
+ This clock is quite much similar to the basic gate-clock[1], however,
+ it supports a number of additional features, including
+ companion clock finding (match corresponding functional gate
+ clock) and hardware autoidle enable / disable.
+
+ [1] Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
+
+properties:
+ compatible:
+ enum:
+ - ti,omap3-interface-clock # basic OMAP3 interface clock
+ - ti,omap3-no-wait-interface-clock # interface clock which has no hardware
+ # capability for waiting clock to be ready
+ - ti,omap3-hsotgusb-interface-clock # interface clock with USB specific HW handling
+ - ti,omap3-dss-interface-clock # interface clock with DSS specific HW handling
+ - ti,omap3-ssi-interface-clock # interface clock with SSI specific HW handling
+ - ti,am35xx-interface-clock # interface clock with AM35xx specific HW handling
+ - ti,omap2430-interface-clock # interface clock with OMAP2430 specific HW handling
+
+ "#clock-cells":
+ const: 0
+
+ clocks:
+ maxItems: 1
+
+ clock-output-names:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+ ti,bit-shift:
+ description:
+ bit shift for the bit enabling/disabling the clock
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+ maximum: 31
+
+required:
+ - compatible
+ - clocks
+ - '#clock-cells'
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ aes1_ick: clock-controller@3 {
+ #clock-cells = <0>;
+ compatible = "ti,omap3-interface-clock";
+ clocks = <&security_l4_ick2>;
+ reg = <3>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/clock/ti/ti,mux-clock.yaml b/Documentation/devicetree/bindings/clock/ti/ti,mux-clock.yaml
new file mode 100644
index 000000000000..485b6aae85d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/ti,mux-clock.yaml
@@ -0,0 +1,125 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/ti/ti,mux-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments mux clock
+
+maintainers:
+ - Tero Kristo <kristo@kernel.org>
+
+description: |
+ This clock assumes a register-mapped multiplexer with multiple inpt clock
+ signals or parents, one of which can be selected as output. This clock does
+ not gate or adjust the parent rate via a divider or multiplier.
+
+ By default the "clocks" property lists the parents in the same order
+ as they are programmed into the register. E.g:
+
+ clocks = <&foo_clock>, <&bar_clock>, <&baz_clock>;
+
+ Results in programming the register as follows:
+
+ register value selected parent clock
+ 0 foo_clock
+ 1 bar_clock
+ 2 baz_clock
+
+ Some clock controller IPs do not allow a value of zero to be programmed
+ into the register, instead indexing begins at 1. The optional property
+ "index-starts-at-one" modified the scheme as follows:
+
+ register value selected clock parent
+ 1 foo_clock
+ 2 bar_clock
+ 3 baz_clock
+
+ The binding must provide the register to control the mux. Optionally
+ the number of bits to shift the control field in the register can be
+ supplied. If the shift value is missing it is the same as supplying
+ a zero shift.
+
+properties:
+ compatible:
+ enum:
+ - ti,mux-clock
+ - ti,composite-mux-clock
+
+ "#clock-cells":
+ const: 0
+
+ clocks: true
+
+ clock-output-names:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+ ti,bit-shift:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Number of bits to shift the bit-mask
+ maximum: 31
+ default: 0
+
+ ti,index-starts-at-one:
+ type: boolean
+ description:
+ Valid input select programming starts at 1, not zero
+
+ ti,set-rate-parent:
+ type: boolean
+ description:
+ clk_set_rate is propagated to parent clock,
+ not supported by the composite-mux-clock subtype.
+
+ ti,latch-bit:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Latch the mux value to HW, only needed if the register
+ access requires this. As an example, dra7x DPLL_GMAC H14 muxing
+ implements such behavior.
+ maximum: 31
+
+if:
+ properties:
+ compatible:
+ contains:
+ const: ti,composite-mux-clock
+then:
+ properties:
+ ti,set-rate-parent: false
+
+required:
+ - compatible
+ - "#clock-cells"
+ - clocks
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clock-controller@110 {
+ compatible = "ti,mux-clock";
+ reg = <0x0110>;
+ #clock-cells = <0>;
+ clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>;
+ ti,index-starts-at-one;
+ ti,set-rate-parent;
+ };
+
+ clock-controller@120 {
+ compatible = "ti,composite-mux-clock";
+ reg = <0x0120>;
+ #clock-cells = <0>;
+ clocks = <&core_96m_fck>, <&mcbsp_clks>;
+ ti,bit-shift = <4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml
index 9d5324dc1027..b44a76a958f4 100644
--- a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml
+++ b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml
@@ -39,6 +39,11 @@ properties:
- const: clk_in1
- const: s_axi_aclk
+ xlnx,static-config:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicate whether the core has been configured without support for dynamic
+ runtime reconfguration of the clocking primitive MMCM/PLL.
xlnx,speed-grade:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -70,6 +75,7 @@ examples:
compatible = "xlnx,clocking-wizard";
reg = <0xb0000000 0x10000>;
#clock-cells = <1>;
+ xlnx,static-config;
xlnx,speed-grade = <1>;
xlnx,nr-outputs = <6>;
clock-names = "clk_in1", "s_axi_aclk";
diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml
index fb216ce68bb3..67700440e23b 100644
--- a/Documentation/devicetree/bindings/connector/usb-connector.yaml
+++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml
@@ -253,6 +253,46 @@ properties:
additionalProperties: false
+ sink-wait-cap-time-ms:
+ description: Represents the max time in ms that USB Type-C port (in sink
+ role) should wait for the port partner (source role) to send source caps.
+ SinkWaitCap timer starts when port in sink role attaches to the source.
+ This timer will stop when sink receives PD source cap advertisement before
+ timeout in which case it'll move to capability negotiation stage. A
+ timeout leads to a hard reset message by the port.
+ minimum: 310
+ maximum: 620
+ default: 310
+
+ ps-source-off-time-ms:
+ description: Represents the max time in ms that a DRP in source role should
+ take to turn off power after the PsSourceOff timer starts. PsSourceOff
+ timer starts when a sink's PHY layer receives EOP of the GoodCRC message
+ (corresponding to an Accept message sent in response to a PR_Swap or a
+ FR_Swap request). This timer stops when last bit of GoodCRC EOP
+ corresponding to the received PS_RDY message is transmitted by the PHY
+ layer. A timeout shall lead to error recovery in the type-c port.
+ minimum: 750
+ maximum: 920
+ default: 920
+
+ cc-debounce-time-ms:
+ description: Represents the max time in ms that a port shall wait to
+ determine if it's attached to a partner.
+ minimum: 100
+ maximum: 200
+ default: 200
+
+ sink-bc12-completion-time-ms:
+ description: Represents the max time in ms that a port in sink role takes
+ to complete Battery Charger (BC1.2) Detection. BC1.2 detection is a
+ hardware mechanism, which in some TCPC implementations, can run in
+ parallel once the Type-C connection state machine reaches the "potential
+ connect as sink" state. In TCPCs where this causes delays to respond to
+ the incoming PD messages, sink-bc12-completion-time-ms is used to delay
+ PD negotiation till BC1.2 detection completes.
+ default: 0
+
dependencies:
sink-vdos-v1: [ sink-vdos ]
sink-vdos: [ sink-vdos-v1 ]
@@ -380,7 +420,7 @@ examples:
};
# USB-C connector attached to a typec port controller(ptn5110), which has
- # power delivery support and enables drp.
+ # power delivery support, explicitly defines time properties and enables drp.
- |
#include <dt-bindings/usb/pd.h>
typec: ptn5110 {
@@ -393,6 +433,10 @@ examples:
sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
PDO_VAR(5000, 12000, 2000)>;
op-sink-microwatt = <10000000>;
+ sink-wait-cap-time-ms = <465>;
+ ps-source-off-time-ms = <835>;
+ cc-debounce-time-ms = <101>;
+ sink-bc12-completion-time-ms = <500>;
};
};
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
index 1e9797f96410..e937eb7355e7 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
@@ -23,6 +23,7 @@ properties:
- enum:
- qcom,qcm2290-cpufreq-hw
- qcom,sc7180-cpufreq-hw
+ - qcom,sc8180x-cpufreq-hw
- qcom,sdm670-cpufreq-hw
- qcom,sdm845-cpufreq-hw
- qcom,sm6115-cpufreq-hw
@@ -34,7 +35,9 @@ properties:
items:
- enum:
- qcom,qdu1000-cpufreq-epss
+ - qcom,sa8255p-cpufreq-epss
- qcom,sa8775p-cpufreq-epss
+ - qcom,sar2130p-cpufreq-epss
- qcom,sc7280-cpufreq-epss
- qcom,sc8280xp-cpufreq-epss
- qcom,sdx75-cpufreq-epss
@@ -107,6 +110,7 @@ allOf:
contains:
enum:
- qcom,qcm2290-cpufreq-hw
+ - qcom,sar2130p-cpufreq-epss
then:
properties:
reg:
@@ -130,7 +134,9 @@ allOf:
contains:
enum:
- qcom,qdu1000-cpufreq-epss
+ - qcom,sa8255p-cpufreq-epss
- qcom,sc7180-cpufreq-hw
+ - qcom,sc8180x-cpufreq-hw
- qcom,sc8280xp-cpufreq-epss
- qcom,sdm670-cpufreq-hw
- qcom,sdm845-cpufreq-hw
diff --git a/Documentation/devicetree/bindings/cpufreq/qemu,virtual-cpufreq.yaml b/Documentation/devicetree/bindings/cpufreq/qemu,virtual-cpufreq.yaml
new file mode 100644
index 000000000000..018d98bcdc82
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/qemu,virtual-cpufreq.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/cpufreq/qemu,virtual-cpufreq.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Virtual CPUFreq
+
+maintainers:
+ - David Dai <davidai@google.com>
+ - Saravana Kannan <saravanak@google.com>
+
+description:
+ Virtual CPUFreq is a virtualized driver in guest kernels that sends performance
+ selection of its vCPUs as a hint to the host through MMIO regions. Each vCPU
+ is associated with a performance domain which can be shared with other vCPUs.
+ Each performance domain has its own set of registers for performance controls.
+
+properties:
+ compatible:
+ const: qemu,virtual-cpufreq
+
+ reg:
+ maxItems: 1
+ description:
+ Address and size of region containing performance controls for each of the
+ performance domains. Regions for each performance domain is placed
+ contiguously and contain registers for controlling DVFS(Dynamic Frequency
+ and Voltage) characteristics. The size of the region is proportional to
+ total number of performance domains.
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpufreq@1040000 {
+ compatible = "qemu,virtual-cpufreq";
+ reg = <0x1040000 0x2000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml
index e285e382d4ec..c09be97434ac 100644
--- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml
+++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml
@@ -44,6 +44,7 @@ properties:
- items:
- enum:
+ - qcom,sa8775p-qce
- qcom,sc7280-qce
- qcom,sm6350-qce
- qcom,sm8250-qce
diff --git a/Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml b/Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml
new file mode 100644
index 000000000000..0a10e10d80ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml
@@ -0,0 +1,250 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/ite,it6263.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ITE IT6263 LVDS to HDMI converter
+
+maintainers:
+ - Liu Ying <victor.liu@nxp.com>
+
+description: |
+ The IT6263 is a high-performance single-chip De-SSC(De-Spread Spectrum) LVDS
+ to HDMI converter. Combined with LVDS receiver and HDMI 1.4a transmitter,
+ the IT6263 supports LVDS input and HDMI 1.4 output by conversion function.
+ The built-in LVDS receiver can support single-link and dual-link LVDS inputs,
+ and the built-in HDMI transmitter is fully compliant with HDMI 1.4a/3D, HDCP
+ 1.2 and backward compatible with DVI 1.0 specification.
+
+ The IT6263 also encodes and transmits up to 8 channels of I2S digital audio,
+ with sampling rate up to 192KHz and sample size up to 24 bits. In addition,
+ an S/PDIF input port takes in compressed audio of up to 192KHz frame rate.
+
+ The newly supported High-Bit Rate(HBR) audio by HDMI specifications v1.3 is
+ provided by the IT6263 in two interfaces: the four I2S input ports or the
+ S/PDIF input port. With both interfaces the highest possible HBR frame rate
+ is supported at up to 768KHz.
+
+allOf:
+ - $ref: /schemas/display/lvds-dual-ports.yaml#
+
+properties:
+ compatible:
+ const: ite,it6263
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+ description: audio master clock
+
+ clock-names:
+ const: mclk
+
+ data-mapping:
+ enum:
+ - jeida-18
+ - jeida-24
+ - jeida-30
+ - vesa-24
+ - vesa-30
+
+ reset-gpios:
+ maxItems: 1
+
+ ivdd-supply:
+ description: 1.8V digital logic power
+
+ ovdd-supply:
+ description: 3.3V I/O pin power
+
+ txavcc18-supply:
+ description: 1.8V HDMI analog frontend power
+
+ txavcc33-supply:
+ description: 3.3V HDMI analog frontend power
+
+ pvcc1-supply:
+ description: 1.8V HDMI frontend core PLL power
+
+ pvcc2-supply:
+ description: 1.8V HDMI frontend filter PLL power
+
+ avcc-supply:
+ description: 3.3V LVDS frontend power
+
+ anvdd-supply:
+ description: 1.8V LVDS frontend analog power
+
+ apvdd-supply:
+ description: 1.8V LVDS frontend PLL power
+
+ "#sound-dai-cells":
+ const: 0
+
+ ite,i2s-audio-fifo-sources:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 4
+ items:
+ enum: [0, 1, 2, 3]
+ description:
+ Each array element indicates the pin number of an I2S serial data input
+ line which is connected to an audio FIFO, from audio FIFO0 to FIFO3.
+
+ ite,rl-channel-swap-audio-sources:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 4
+ uniqueItems: true
+ items:
+ enum: [0, 1, 2, 3]
+ description:
+ Each array element indicates an audio source whose right channel and left
+ channel are swapped by this converter. For I2S, the element is the pin
+ number of an I2S serial data input line. For S/PDIF, the element is always
+ 0.
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0: true
+
+ port@1:
+ oneOf:
+ - required: [dual-lvds-odd-pixels]
+ - required: [dual-lvds-even-pixels]
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: video port for the HDMI output
+
+ port@3:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: sound input port
+
+ required:
+ - port@0
+ - port@2
+
+required:
+ - compatible
+ - reg
+ - data-mapping
+ - ivdd-supply
+ - ovdd-supply
+ - txavcc18-supply
+ - txavcc33-supply
+ - pvcc1-supply
+ - pvcc2-supply
+ - avcc-supply
+ - anvdd-supply
+ - apvdd-supply
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ /* single-link LVDS input */
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi@4c {
+ compatible = "ite,it6263";
+ reg = <0x4c>;
+ data-mapping = "jeida-24";
+ reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+ ivdd-supply = <&reg_buck5>;
+ ovdd-supply = <&reg_vext_3v3>;
+ txavcc18-supply = <&reg_buck5>;
+ txavcc33-supply = <&reg_vext_3v3>;
+ pvcc1-supply = <&reg_buck5>;
+ pvcc2-supply = <&reg_buck5>;
+ avcc-supply = <&reg_vext_3v3>;
+ anvdd-supply = <&reg_buck5>;
+ apvdd-supply = <&reg_buck5>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ it6263_lvds_link1: endpoint {
+ remote-endpoint = <&ldb_lvds_ch0>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ it6263_out: endpoint {
+ remote-endpoint = <&hdmi_in>;
+ };
+ };
+ };
+ };
+ };
+
+ - |
+ /* dual-link LVDS input */
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi@4c {
+ compatible = "ite,it6263";
+ reg = <0x4c>;
+ data-mapping = "jeida-24";
+ reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+ ivdd-supply = <&reg_buck5>;
+ ovdd-supply = <&reg_vext_3v3>;
+ txavcc18-supply = <&reg_buck5>;
+ txavcc33-supply = <&reg_vext_3v3>;
+ pvcc1-supply = <&reg_buck5>;
+ pvcc2-supply = <&reg_buck5>;
+ avcc-supply = <&reg_vext_3v3>;
+ anvdd-supply = <&reg_buck5>;
+ apvdd-supply = <&reg_buck5>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dual-lvds-odd-pixels;
+
+ it6263_lvds_link1_dual: endpoint {
+ remote-endpoint = <&ldb_lvds_ch0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dual-lvds-even-pixels;
+
+ it6263_lvds_link2_dual: endpoint {
+ remote-endpoint = <&ldb_lvds_ch1>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ it6263_out_dual: endpoint {
+ remote-endpoint = <&hdmi_in>;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/lvds-data-mapping.yaml b/Documentation/devicetree/bindings/display/lvds-data-mapping.yaml
index d68982fe2e9b..ab842594feb9 100644
--- a/Documentation/devicetree/bindings/display/lvds-data-mapping.yaml
+++ b/Documentation/devicetree/bindings/display/lvds-data-mapping.yaml
@@ -26,12 +26,17 @@ description: |
Device compatible with those specifications have been marketed under the
FPD-Link and FlatLink brands.
+ This bindings also supports 30-bit data mapping compatible with JEIDA and
+ VESA.
+
properties:
data-mapping:
enum:
- jeida-18
- jeida-24
+ - jeida-30
- vesa-24
+ - vesa-30
description: |
The color signals mapping order.
@@ -60,6 +65,19 @@ properties:
DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B7__><__B6__><__B5__><__B4__><
DATA3 ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
+ - "jeida-30" - 30-bit data mapping compatible with JEIDA and VESA. Data
+ are transferred as follows on 5 LVDS lanes.
+
+ Slot 0 1 2 3 4 5 6
+ ________________ _________________
+ Clock \_______________________/
+ ______ ______ ______ ______ ______ ______ ______
+ DATA0 ><__G4__><__R9__><__R8__><__R7__><__R6__><__R5__><__R4__><
+ DATA1 ><__B5__><__B4__><__G9__><__G8__><__G7__><__G6__><__G5__><
+ DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B9__><__B8__><__B7__><__B6__><
+ DATA3 ><_CTL3_><__B3__><__B2__><__G3__><__G2__><__R3__><__R2__><
+ DATA4 ><_CTL3_><__B1__><__B0__><__G1__><__G0__><__R1__><__R0__><
+
- "vesa-24" - 24-bit data mapping compatible with the [VESA] specification.
Data are transferred as follows on 4 LVDS lanes.
@@ -72,6 +90,19 @@ properties:
DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
DATA3 ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
+ - "vesa-30" - 30-bit data mapping compatible with VESA. Data are
+ transferred as follows on 5 LVDS lanes.
+
+ Slot 0 1 2 3 4 5 6
+ ________________ _________________
+ Clock \_______________________/
+ ______ ______ ______ ______ ______ ______ ______
+ DATA0 ><__G0__><__R5__><__R4__><__R3__><__R2__><__R1__><__R0__><
+ DATA1 ><__B1__><__B0__><__G5__><__G4__><__G3__><__G2__><__G1__><
+ DATA2 ><_CTL2_><_CTL1_><_CTL0_><__B5__><__B4__><__B3__><__B2__><
+ DATA3 ><_CTL3_><__B7__><__B6__><__G7__><__G6__><__R7__><__R6__><
+ DATA4 ><_CTL3_><__B9__><__B8__><__G9__><__G8__><__R9__><__R8__><
+
Control signals are mapped as follows.
CTL0: HSync
diff --git a/Documentation/devicetree/bindings/display/lvds-dual-ports.yaml b/Documentation/devicetree/bindings/display/lvds-dual-ports.yaml
new file mode 100644
index 000000000000..785701fe1590
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/lvds-dual-ports.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/lvds-dual-ports.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Dual-link LVDS Display Common Properties
+
+maintainers:
+ - Liu Ying <victor.liu@nxp.com>
+
+description: |
+ Common properties for LVDS displays with dual LVDS links. Extend LVDS display
+ common properties defined in lvds.yaml.
+
+ Dual-link LVDS displays receive odd pixels and even pixels separately from
+ the dual LVDS links. One link receives odd pixels and the other receives
+ even pixels. Some of those displays may also use only one LVDS link to
+ receive all pixels, being odd and even agnostic.
+
+allOf:
+ - $ref: lvds.yaml#
+
+properties:
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ patternProperties:
+ '^port@[01]$':
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: |
+ port@0 represents the first LVDS input link.
+ port@1 represents the second LVDS input link.
+
+ properties:
+ dual-lvds-odd-pixels:
+ type: boolean
+ description: LVDS input link for odd pixels
+
+ dual-lvds-even-pixels:
+ type: boolean
+ description: LVDS input link for even pixels
+
+ oneOf:
+ - required: [dual-lvds-odd-pixels]
+ - required: [dual-lvds-even-pixels]
+ - properties:
+ dual-lvds-odd-pixels: false
+ dual-lvds-even-pixels: false
+
+ anyOf:
+ - required:
+ - port@0
+ - required:
+ - port@1
+
+required:
+ - ports
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml
index cf24434854ff..47ddba5c41af 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml
@@ -62,6 +62,27 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: AAL input port
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ AAL output to the next component's input, for example could be one
+ of many gamma, overdrive or other blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
@@ -89,5 +110,24 @@ examples:
power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
clocks = <&mmsys CLK_MM_DISP_AAL>;
mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x5000 0x1000>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ aal0_in: endpoint {
+ remote-endpoint = <&ccorr0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ aal0_out: endpoint {
+ remote-endpoint = <&gamma0_in>;
+ };
+ };
+ };
};
};
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml
index 9f8366763831..fca8e7bb0cbc 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml
@@ -57,6 +57,27 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: CCORR input port
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ CCORR output to the input of the next desired component in the
+ display pipeline, usually only one of the available AAL blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml
index 7df786bbad20..6160439ce4d7 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml
@@ -65,6 +65,28 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: COLOR input port
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ COLOR output to the input of the next desired component in the
+ display pipeline, for example one of the available CCORR or AAL
+ blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml
index 6fceb1f95d2a..abaf27916d13 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml
@@ -56,6 +56,28 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: DITHER input, usually from a POSTMASK or GAMMA block.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ DITHER output to the input of the next desired component in the
+ display pipeline, for example one of the available DSC compressors,
+ DP_INTF, DSI, LVDS or others.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
index 497c0eb4ed0b..0f1e556dc8ef 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
@@ -81,13 +81,34 @@ properties:
Output port node. This port should be connected to the input port of an
attached HDMI, LVDS or DisplayPort encoder chip.
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: DPI input port
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: DPI output to an HDMI, LVDS or DisplayPort encoder input
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- - port
+
+oneOf:
+ - required:
+ - port
+ - required:
+ - ports
additionalProperties: false
@@ -96,7 +117,7 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/mt8173-clk.h>
- dpi0: dpi@1401d000 {
+ dpi: dpi@1401d000 {
compatible = "mediatek,mt8173-dpi";
reg = <0x1401d000 0x1000>;
interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml
index 2cbdd9ee449d..846de6c17d93 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml
@@ -49,6 +49,30 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Display Stream Compression input, usually from one of the DITHER
+ or MERGE blocks.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Display Stream Compression output to the input of the next desired
+ component in the display pipeline, for example to MERGE, DP_INTF,
+ DPI or DSI.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
index a7aa8fcb0dd1..27ffbccc2a08 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
@@ -77,6 +77,26 @@ properties:
Output port node. This port should be connected to the input
port of an attached DSI panel or DSI-to-eDP encoder chip.
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input ports can have multiple endpoints, each of those connects
+ to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: DSI input port, usually from DITHER, DSC or MERGE
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ DSI output to an attached DSI panel, or a DSI-to-X encoder chip
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
@@ -86,7 +106,12 @@ required:
- clock-names
- phys
- phy-names
- - port
+
+oneOf:
+ - required:
+ - port
+ - required:
+ - ports
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml
index 677882348ede..98db47894eeb 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml
@@ -110,6 +110,28 @@ properties:
include/dt-bindings/gce/<chip>-gce.h, mapping to the register of display
function block.
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: ETHDR input, usually from one of the MERGE blocks.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ ETHDR output to the input of the next desired component in the
+ display pipeline, for example one of the available MERGE blocks,
+ or others.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml
index 6823d3ce5049..48542dc7e784 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml
@@ -65,6 +65,25 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: GAMMA input, usually from one of the AAL blocks.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ GAMMA output to the input of the next desired component in the
+ display pipeline, for example one of the available DITHER or
+ POSTMASK blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,merge.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,merge.yaml
index dae839279950..0de9f64f3f84 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,merge.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,merge.yaml
@@ -77,6 +77,29 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ MERGE input port, usually from DITHER, DPI, DSC, DSI, MDP_RDMA,
+ ETHDR or even from a different MERGE block
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ MERGE output to a DSC, DPI, DP_INTF, DSI, ETHDR, Write DMA, or
+ a different MERGE block, or others.
+
+ required:
+ - port@0
+ - port@1
+
resets:
description: reset controller
See Documentation/devicetree/bindings/reset/reset.txt for details.
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,od.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,od.yaml
index 831c653caffd..71534febd49c 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,od.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,od.yaml
@@ -38,6 +38,28 @@ properties:
items:
- description: OD Clock
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: OD input port, usually from an AAL block
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ OD output to the input of the next desired component in the
+ display pipeline, for example one of the available RDMA or
+ other blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl-2l.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl-2l.yaml
index c7dd0ef02dcf..bacdfe7d08a6 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl-2l.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl-2l.yaml
@@ -57,6 +57,28 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: OVL input port from MMSYS, VDOSYS or other OVLs
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ OVL output to the input of the next desired component in the
+ display pipeline, for example one of the available COLOR, RDMA
+ or WDMA blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl.yaml
index d55611c7ce5e..9ea796a033b2 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ovl.yaml
@@ -75,6 +75,28 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: OVL input port from MMSYS or one of multiple VDOSYS
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ OVL output to the input of the next desired component in the
+ display pipeline, for example one of the available COLOR, RDMA
+ or WDMA blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,postmask.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,postmask.yaml
index 11fe32e50a59..fb6fe4742624 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,postmask.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,postmask.yaml
@@ -52,6 +52,27 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: POSTMASK input port, usually from GAMMA
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ POSTMASK output to the input of the next desired component in the
+ display pipeline, for example one of the available DITHER blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,rdma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,rdma.yaml
index 4cadb245d028..878f676b581f 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,rdma.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,rdma.yaml
@@ -87,6 +87,28 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: RDMA input port, usually from MMSYS, OD or OVL
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ RDMA output to the input of the next desired component in the
+ display pipeline, for example one of the available COLOR, DPI,
+ DSI, MERGE or UFOE blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,ufoe.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,ufoe.yaml
index 39e3e2d4a0db..61a5e22effbf 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,ufoe.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ufoe.yaml
@@ -43,6 +43,27 @@ properties:
items:
- description: UFOe Clock
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ Input and output ports can have multiple endpoints, each of those
+ connects to either the primary, secondary, etc, display pipeline.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: UFOE input, usually from one of the RDMA blocks.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ UFOE output to the input of the next desired component in the
+ display pipeline, usually one of the available DSI blocks.
+
+ required:
+ - port@0
+ - port@1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index 97993feda193..a212f335d5ff 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -17,6 +17,7 @@ properties:
compatible:
oneOf:
- enum:
+ - qcom,sa8775p-dp
- qcom,sc7180-dp
- qcom,sc7280-dp
- qcom,sc7280-edp
diff --git a/Documentation/devicetree/bindings/display/msm/gmu.yaml b/Documentation/devicetree/bindings/display/msm/gmu.yaml
index b1bd372996d5..ab884e236429 100644
--- a/Documentation/devicetree/bindings/display/msm/gmu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/gmu.yaml
@@ -125,6 +125,7 @@ allOf:
enum:
- qcom,adreno-gmu-635.0
- qcom,adreno-gmu-660.1
+ - qcom,adreno-gmu-663.0
then:
properties:
reg:
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
new file mode 100644
index 000000000000..58f8a01f29c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
@@ -0,0 +1,241 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sa8775p-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. SA87755P Display MDSS
+
+maintainers:
+ - Mahadevan <quic_mahap@quicinc.com>
+
+description:
+ SA8775P MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like
+ DPU display controller, DP interfaces and EDP etc.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sa8775p-mdss
+
+ clocks:
+ items:
+ - description: Display AHB
+ - description: Display hf AXI
+ - description: Display core
+
+ iommus:
+ maxItems: 1
+
+ interconnects:
+ maxItems: 3
+
+ interconnect-names:
+ maxItems: 3
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ additionalProperties: true
+
+ properties:
+ compatible:
+ const: qcom,sa8775p-dpu
+
+ "^displayport-controller@[0-9a-f]+$":
+ type: object
+ additionalProperties: true
+
+ properties:
+ compatible:
+ items:
+ - const: qcom,sa8775p-dp
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interconnect/qcom,icc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/qcom,sa8775p-gcc.h>
+ #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h>
+ #include <dt-bindings/power/qcom,rpmhpd.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-subsystem@ae00000 {
+ compatible = "qcom,sa8775p-mdss";
+ reg = <0x0ae00000 0x1000>;
+ reg-names = "mdss";
+
+ interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>,
+ <&mmss_noc MASTER_MDP1 &mc_virt SLAVE_EBI1>,
+ <&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_DISPLAY_CFG>;
+ interconnect-names = "mdp0-mem",
+ "mdp1-mem",
+ "cpu-cfg";
+
+
+ resets = <&dispcc_core_bcr>;
+ power-domains = <&dispcc_gdsc>;
+
+ clocks = <&dispcc_ahb_clk>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc_mdp_clk>;
+
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ iommus = <&apps_smmu 0x1000 0x402>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ display-controller@ae01000 {
+ compatible = "qcom,sa8775p-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc_ahb_clk>,
+ <&dispcc_mdp_lut_clk>,
+ <&dispcc_mdp_clk>,
+ <&dispcc_mdp_vsync_clk>;
+ clock-names = "nrt_bus",
+ "iface",
+ "lut",
+ "core",
+ "vsync";
+
+ assigned-clocks = <&dispcc_mdp_vsync_clk>;
+ assigned-clock-rates = <19200000>;
+
+ operating-points-v2 = <&mdss0_mdp_opp_table>;
+ power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+ interrupt-parent = <&mdss0>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf0_out: endpoint {
+ remote-endpoint = <&mdss0_dp0_in>;
+ };
+ };
+ };
+
+ mdss0_mdp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-375000000 {
+ opp-hz = /bits/ 64 <375000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+
+ opp-575000000 {
+ opp-hz = /bits/ 64 <575000000>;
+ required-opps = <&rpmhpd_opp_turbo>;
+ };
+
+ opp-650000000 {
+ opp-hz = /bits/ 64 <650000000>;
+ required-opps = <&rpmhpd_opp_turbo_l1>;
+ };
+ };
+ };
+
+ displayport-controller@af54000 {
+ compatible = "qcom,sa8775p-dp";
+
+ pinctrl-0 = <&dp_hot_plug_det>;
+ pinctrl-names = "default";
+
+ reg = <0xaf54000 0x104>,
+ <0xaf54200 0x0c0>,
+ <0xaf55000 0x770>,
+ <0xaf56000 0x09c>;
+
+ interrupt-parent = <&mdss0>;
+ interrupts = <12>;
+
+ clocks = <&dispcc_mdss_ahb_clk>,
+ <&dispcc_dptx0_aux_clk>,
+ <&dispcc_dptx0_link_clk>,
+ <&dispcc_dptx0_link_intf_clk>,
+ <&dispcc_dptx0_pixel0_clk>;
+ clock-names = "core_iface",
+ "core_aux",
+ "ctrl_link",
+ "ctrl_link_iface",
+ "stream_pixel";
+
+ assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
+ <&dispcc_mdss_dptx0_pixel0_clk_src>;
+ assigned-clock-parents = <&mdss0_edp_phy 0>, <&mdss0_edp_phy 1>;
+
+ phys = <&mdss0_edp_phy>;
+ phy-names = "dp";
+
+ operating-points-v2 = <&dp_opp_table>;
+ power-domains = <&rpmhpd SA8775P_MMCX>;
+
+ #sound-dai-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ mdss0_dp0_in: endpoint {
+ remote-endpoint = <&dpu_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ mdss0_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
index b0fbe86219d1..6902795b4e2c 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
@@ -7,13 +7,21 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Display DPU on SC7280
maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Neil Armstrong <neil.armstrong@linaro.org>
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
- Krishna Manikandan <quic_mkrishn@quicinc.com>
$ref: /schemas/display/msm/dpu-common.yaml#
properties:
compatible:
- const: qcom,sc7280-dpu
+ enum:
+ - qcom,sc7280-dpu
+ - qcom,sc8280xp-dpu
+ - qcom,sm8350-dpu
+ - qcom,sm8450-dpu
+ - qcom,sm8550-dpu
reg:
items:
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-dpu.yaml
deleted file mode 100644
index d19e3bec4600..000000000000
--- a/Documentation/devicetree/bindings/display/msm/qcom,sc8280xp-dpu.yaml
+++ /dev/null
@@ -1,122 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/qcom,sc8280xp-dpu.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm SC8280XP Display Processing Unit
-
-maintainers:
- - Bjorn Andersson <andersson@kernel.org>
-
-description:
- Device tree bindings for SC8280XP Display Processing Unit.
-
-$ref: /schemas/display/msm/dpu-common.yaml#
-
-properties:
- compatible:
- const: qcom,sc8280xp-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-sc8280xp.h>
- #include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/interconnect/qcom,sc8280xp.h>
- #include <dt-bindings/power/qcom-rpmpd.h>
-
- display-controller@ae01000 {
- compatible = "qcom,sc8280xp-dpu";
- reg = <0x0ae01000 0x8f000>,
- <0x0aeb0000 0x2008>;
- reg-names = "mdp", "vbif";
-
- clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
- <&gcc GCC_DISP_SF_AXI_CLK>,
- <&dispcc0 DISP_CC_MDSS_AHB_CLK>,
- <&dispcc0 DISP_CC_MDSS_MDP_LUT_CLK>,
- <&dispcc0 DISP_CC_MDSS_MDP_CLK>,
- <&dispcc0 DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "bus",
- "nrt_bus",
- "iface",
- "lut",
- "core",
- "vsync";
-
- assigned-clocks = <&dispcc0 DISP_CC_MDSS_MDP_CLK>,
- <&dispcc0 DISP_CC_MDSS_VSYNC_CLK>;
- assigned-clock-rates = <460000000>,
- <19200000>;
-
- operating-points-v2 = <&mdp_opp_table>;
- power-domains = <&rpmhpd SC8280XP_MMCX>;
-
- interrupt-parent = <&mdss0>;
- interrupts = <0>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- endpoint {
- remote-endpoint = <&mdss0_dp0_in>;
- };
- };
-
- port@4 {
- reg = <4>;
- endpoint {
- remote-endpoint = <&mdss0_dp1_in>;
- };
- };
-
- port@5 {
- reg = <5>;
- endpoint {
- remote-endpoint = <&mdss0_dp3_in>;
- };
- };
-
- port@6 {
- reg = <6>;
- endpoint {
- remote-endpoint = <&mdss0_dp2_in>;
- };
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-dpu.yaml
index 13146b3f053c..a88d22f30a60 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-dpu.yaml
@@ -13,7 +13,9 @@ $ref: /schemas/display/msm/dpu-common.yaml#
properties:
compatible:
- const: qcom,sm8150-dpu
+ enum:
+ - qcom,sm8150-dpu
+ - qcom,sm8250-dpu
reg:
items:
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml
deleted file mode 100644
index ffa5047e901f..000000000000
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml
+++ /dev/null
@@ -1,99 +0,0 @@
-# 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
-
-required:
- - compatible
- - reg
- - reg-names
- - clocks
- - clock-names
-
-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,rpmhpd.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 RPMHPD_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,sm8350-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8350-dpu.yaml
deleted file mode 100644
index 96ef2d9c3512..000000000000
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8350-dpu.yaml
+++ /dev/null
@@ -1,120 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/qcom,sm8350-dpu.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm SM8350 Display DPU
-
-maintainers:
- - Robert Foss <robert.foss@linaro.org>
-
-$ref: /schemas/display/msm/dpu-common.yaml#
-
-properties:
- compatible:
- const: qcom,sm8350-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-sm8350.h>
- #include <dt-bindings/clock/qcom,gcc-sm8350.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/interconnect/qcom,sm8350.h>
- #include <dt-bindings/power/qcom,rpmhpd.h>
-
- display-controller@ae01000 {
- compatible = "qcom,sm8350-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";
-
- assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- assigned-clock-rates = <19200000>;
-
- operating-points-v2 = <&mdp_opp_table>;
- power-domains = <&rpmhpd RPMHPD_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>;
- };
- };
- };
-
- 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>;
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml
deleted file mode 100644
index 2a5d3daed0e1..000000000000
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml
+++ /dev/null
@@ -1,139 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/qcom,sm8450-dpu.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm SM8450 Display DPU
-
-maintainers:
- - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
-
-$ref: /schemas/display/msm/dpu-common.yaml#
-
-properties:
- compatible:
- const: qcom,sm8450-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
- - description: Display sf axi
- - description: Display ahb
- - description: Display lut
- - description: Display core
- - description: Display vsync
-
- clock-names:
- items:
- - const: bus
- - const: nrt_bus
- - const: iface
- - const: lut
- - const: core
- - const: vsync
-
-required:
- - compatible
- - reg
- - reg-names
- - clocks
- - clock-names
-
-unevaluatedProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,sm8450-dispcc.h>
- #include <dt-bindings/clock/qcom,gcc-sm8450.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/interconnect/qcom,sm8450.h>
- #include <dt-bindings/power/qcom,rpmhpd.h>
-
- display-controller@ae01000 {
- compatible = "qcom,sm8450-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";
-
- assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- assigned-clock-rates = <19200000>;
-
- operating-points-v2 = <&mdp_opp_table>;
- power-domains = <&rpmhpd RPMHPD_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-172000000{
- opp-hz = /bits/ 64 <172000000>;
- required-opps = <&rpmhpd_opp_low_svs_d1>;
- };
-
- opp-200000000 {
- opp-hz = /bits/ 64 <200000000>;
- required-opps = <&rpmhpd_opp_low_svs>;
- };
-
- opp-325000000 {
- opp-hz = /bits/ 64 <325000000>;
- required-opps = <&rpmhpd_opp_svs>;
- };
-
- opp-375000000 {
- opp-hz = /bits/ 64 <375000000>;
- required-opps = <&rpmhpd_opp_svs_l1>;
- };
-
- opp-500000000 {
- opp-hz = /bits/ 64 <500000000>;
- required-opps = <&rpmhpd_opp_nom>;
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8550-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8550-dpu.yaml
deleted file mode 100644
index 16a541fca66f..000000000000
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8550-dpu.yaml
+++ /dev/null
@@ -1,133 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/qcom,sm8550-dpu.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm SM8550 Display DPU
-
-maintainers:
- - Neil Armstrong <neil.armstrong@linaro.org>
-
-$ref: /schemas/display/msm/dpu-common.yaml#
-
-properties:
- compatible:
- const: qcom,sm8550-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
- - description: Display hf axi
- - description: Display MDSS ahb
- - description: Display lut
- - description: Display core
- - description: Display vsync
-
- clock-names:
- items:
- - const: bus
- - const: nrt_bus
- - const: iface
- - const: lut
- - const: core
- - const: vsync
-
-required:
- - compatible
- - reg
- - reg-names
- - clocks
- - clock-names
-
-unevaluatedProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,sm8550-dispcc.h>
- #include <dt-bindings/clock/qcom,sm8550-gcc.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/power/qcom,rpmhpd.h>
-
- display-controller@ae01000 {
- compatible = "qcom,sm8550-dpu";
- reg = <0x0ae01000 0x8f000>,
- <0x0aeb0000 0x2008>;
- reg-names = "mdp", "vbif";
-
- clocks = <&gcc GCC_DISP_AHB_CLK>,
- <&gcc GCC_DISP_HF_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";
-
- assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- assigned-clock-rates = <19200000>;
-
- operating-points-v2 = <&mdp_opp_table>;
- power-domains = <&rpmhpd RPMHPD_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-325000000 {
- opp-hz = /bits/ 64 <325000000>;
- required-opps = <&rpmhpd_opp_svs>;
- };
-
- opp-375000000 {
- opp-hz = /bits/ 64 <375000000>;
- required-opps = <&rpmhpd_opp_svs_l1>;
- };
-
- opp-514000000 {
- opp-hz = /bits/ 64 <514000000>;
- required-opps = <&rpmhpd_opp_nom>;
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
index c4087cc5abbd..01cf79bd754b 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
@@ -14,6 +14,7 @@ $ref: /schemas/display/msm/dpu-common.yaml#
properties:
compatible:
enum:
+ - qcom,sa8775p-dpu
- qcom,sm8650-dpu
- qcom,x1e80100-dpu
diff --git a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
index 2e8dbdb5a3d5..05ca3b2385f8 100644
--- a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
+++ b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
@@ -20,6 +20,7 @@ description: |
dual-lvds-odd-pixels or dual-lvds-even-pixels).
allOf:
+ - $ref: /schemas/display/lvds-dual-ports.yaml#
- $ref: panel-common.yaml#
properties:
@@ -44,22 +45,10 @@ properties:
properties:
port@0:
- $ref: /schemas/graph.yaml#/$defs/port-base
- unevaluatedProperties: false
- description: The sink for odd pixels.
- properties:
- dual-lvds-odd-pixels: true
-
required:
- dual-lvds-odd-pixels
port@1:
- $ref: /schemas/graph.yaml#/$defs/port-base
- unevaluatedProperties: false
- description: The sink for even pixels.
- properties:
- dual-lvds-even-pixels: true
-
required:
- dual-lvds-even-pixels
@@ -75,7 +64,6 @@ required:
- height-mm
- data-mapping
- panel-timing
- - ports
examples:
- |+
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
index 10ed4b57232b..e80fc7006984 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
@@ -22,6 +22,7 @@ description: |
If the panel is more advanced a dedicated binding file is required.
allOf:
+ - $ref: /schemas/display/lvds-dual-ports.yaml#
- $ref: panel-common.yaml#
properties:
@@ -55,28 +56,10 @@ properties:
properties:
port@0:
- $ref: /schemas/graph.yaml#/$defs/port-base
- unevaluatedProperties: false
- description: The first sink port.
-
- properties:
- dual-lvds-odd-pixels:
- type: boolean
- description: The first sink port for odd pixels.
-
required:
- dual-lvds-odd-pixels
port@1:
- $ref: /schemas/graph.yaml#/$defs/port-base
- unevaluatedProperties: false
- description: The second sink port.
-
- properties:
- dual-lvds-even-pixels:
- type: boolean
- description: The second sink port for even pixels.
-
required:
- dual-lvds-even-pixels
@@ -88,7 +71,6 @@ unevaluatedProperties: false
required:
- compatible
- - ports
- power-supply
examples:
diff --git a/Documentation/devicetree/bindings/display/samsung/samsung,exynos7-decon.yaml b/Documentation/devicetree/bindings/display/samsung/samsung,exynos7-decon.yaml
index 992c23ca7a4e..53916e4c95d8 100644
--- a/Documentation/devicetree/bindings/display/samsung/samsung,exynos7-decon.yaml
+++ b/Documentation/devicetree/bindings/display/samsung/samsung,exynos7-decon.yaml
@@ -19,7 +19,9 @@ description: |
properties:
compatible:
- const: samsung,exynos7-decon
+ enum:
+ - samsung,exynos7-decon
+ - samsung,exynos7870-decon
clocks:
maxItems: 4
diff --git a/Documentation/devicetree/bindings/dma/dma-common.yaml b/Documentation/devicetree/bindings/dma/dma-common.yaml
index ea700f8ee6c6..fde5160b5d29 100644
--- a/Documentation/devicetree/bindings/dma/dma-common.yaml
+++ b/Documentation/devicetree/bindings/dma/dma-common.yaml
@@ -32,10 +32,9 @@ properties:
The first item in the array is for channels 0-31, the second is for
channels 32-63, etc.
$ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- minItems: 1
- # Should be enough
- maxItems: 255
+ minItems: 1
+ # Should be enough
+ maxItems: 255
dma-channels:
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/dma/qcom,gpi.yaml b/Documentation/devicetree/bindings/dma/qcom,gpi.yaml
index 4df4e61895d2..4ad56a409b9c 100644
--- a/Documentation/devicetree/bindings/dma/qcom,gpi.yaml
+++ b/Documentation/devicetree/bindings/dma/qcom,gpi.yaml
@@ -26,6 +26,7 @@ properties:
- enum:
- qcom,qcm2290-gpi-dma
- qcom,qdu1000-gpi-dma
+ - qcom,sar2130p-gpi-dma
- qcom,sc7280-gpi-dma
- qcom,sdx75-gpi-dma
- qcom,sm6115-gpi-dma
diff --git a/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml b/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
index ca24cf48769f..b356251de5a8 100644
--- a/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
+++ b/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
@@ -4,18 +4,16 @@
$id: http://devicetree.org/schemas/dma/renesas,rz-dmac.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Renesas RZ/{G2L,G2UL,V2L} DMA Controller
+title: Renesas RZ DMA Controller
maintainers:
- Biju Das <biju.das.jz@bp.renesas.com>
-allOf:
- - $ref: dma-controller.yaml#
-
properties:
compatible:
items:
- enum:
+ - renesas,r7s72100-dmac # RZ/A1H
- renesas,r9a07g043-dmac # RZ/G2UL and RZ/Five
- renesas,r9a07g044-dmac # RZ/G2{L,LC}
- renesas,r9a07g054-dmac # RZ/V2L
@@ -93,13 +91,26 @@ required:
- reg
- interrupts
- interrupt-names
- - clocks
- - clock-names
- '#dma-cells'
- dma-channels
- - power-domains
- - resets
- - reset-names
+
+allOf:
+ - $ref: dma-controller.yaml#
+
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - renesas,r7s72100-dmac
+ then:
+ required:
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+ - reset-names
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml b/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml
index 3b22183a1a37..609e38901434 100644
--- a/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml
+++ b/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml
@@ -27,11 +27,16 @@ allOf:
properties:
compatible:
- items:
- - enum:
- - microchip,mpfs-pdma
- - sifive,fu540-c000-pdma
- - const: sifive,pdma0
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-pdma
+ - const: microchip,mpfs-pdma
+ - const: sifive,pdma0
+ - items:
+ - enum:
+ - microchip,mpfs-pdma
+ - sifive,fu540-c000-pdma
+ - const: sifive,pdma0
description:
Should be "sifive,<chip>-pdma" and "sifive,pdma<version>".
Supported compatible strings are -
diff --git a/Documentation/devicetree/bindings/dma/stm32/st,stm32-dma3.yaml b/Documentation/devicetree/bindings/dma/stm32/st,stm32-dma3.yaml
index 7fdc44b2e646..36f9fe860eb9 100644
--- a/Documentation/devicetree/bindings/dma/stm32/st,stm32-dma3.yaml
+++ b/Documentation/devicetree/bindings/dma/stm32/st,stm32-dma3.yaml
@@ -96,6 +96,12 @@ properties:
including the update of the LLI if any
0x3: at channel level, the transfer complete event is generated at the
end of the last LLI
+ -bit 16: Prevent packing/unpacking mode
+ 0x0: pack/unpack enabled when source data width/burst != destination data width/burst
+ 0x1: memory data width/burst forced to peripheral data width/burst to prevent pack/unpack
+ -bit 17: Prevent additional transfers due to linked-list refactoring
+ 0x0: don't prevent additional transfers for optimal performance
+ 0x1: prevent additional transfer to accommodate user constraints such as single transfer
required:
- compatible
diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
index 9af40da5688e..ab93ffd3d2e5 100644
--- a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
+++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
@@ -99,14 +99,35 @@ allOf:
contains:
enum:
- fsl,imx8qxp-dsp
- - fsl,imx8qm-dsp
- fsl,imx8qxp-hifi4
+ then:
+ properties:
+ power-domains:
+ minItems: 2
+ maxItems: 2
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qm-dsp
- fsl,imx8qm-hifi4
then:
properties:
power-domains:
minItems: 4
- else:
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8mp-dsp
+ - fsl,imx8mp-hifi4
+ - fsl,imx8ulp-dsp
+ - fsl,imx8ulp-hifi4
+ then:
properties:
power-domains:
maxItems: 1
@@ -157,10 +178,8 @@ examples:
<&adma_lpcg IMX_ADMA_LPCG_OCRAM_IPG_CLK>,
<&adma_lpcg IMX_ADMA_LPCG_DSP_CORE_CLK>;
clock-names = "ipg", "ocram", "core";
- power-domains = <&pd IMX_SC_R_MU_13A>,
- <&pd IMX_SC_R_MU_13B>,
- <&pd IMX_SC_R_DSP>,
- <&pd IMX_SC_R_DSP_RAM>;
+ power-domains = <&pd IMX_SC_R_MU_13B>,
+ <&pd IMX_SC_R_MU_2A>;
mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
mboxes = <&lsio_mu13 2 0>, <&lsio_mu13 2 1>, <&lsio_mu13 3 0>, <&lsio_mu13 3 1>;
memory-region = <&dsp_reserved>;
diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml
index b6239ec3512b..590ba0ef5fa2 100644
--- a/Documentation/devicetree/bindings/eeprom/at24.yaml
+++ b/Documentation/devicetree/bindings/eeprom/at24.yaml
@@ -141,6 +141,8 @@ properties:
- const: microchip,24aa025e48
- items:
- const: microchip,24aa025e64
+ - items:
+ - const: st,24256e-wl
- pattern: '^atmel,24c(32|64)d-wl$' # Actual vendor is st
label:
diff --git a/Documentation/devicetree/bindings/example-schema.yaml b/Documentation/devicetree/bindings/example-schema.yaml
index a41f9b9a196b..484f8babcda4 100644
--- a/Documentation/devicetree/bindings/example-schema.yaml
+++ b/Documentation/devicetree/bindings/example-schema.yaml
@@ -262,4 +262,5 @@ examples:
reg-names = "core", "aux";
interrupts = <10>;
interrupt-controller;
+ #interrupt-cells = <2>;
};
diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
index 54d7d11bfed4..abbd62f1fed0 100644
--- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
+++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
@@ -124,13 +124,28 @@ properties:
atomic mode of operation, even if requested.
default: 0
- max-rx-timeout-ms:
+ arm,max-rx-timeout-ms:
description:
An optional time value, expressed in milliseconds, representing the
transport maximum timeout value for the receive channel. The value should
be a non-zero value if set.
minimum: 1
+ arm,max-msg-size:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ An optional value, expressed in bytes, representing the maximum size
+ allowed for the payload of messages transmitted on this transport.
+
+ arm,max-msg:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ An optional value representing the maximum number of concurrent in-flight
+ messages allowed by this transport; this number represents the maximum
+ number of concurrently outstanding messages that the server can handle on
+ this platform. If set, the value should be non-zero.
+ minimum: 1
+
arm,smc-id:
$ref: /schemas/types.yaml#/definitions/uint32
description:
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
index 2cc83771d8e7..2ee030000007 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
@@ -42,8 +42,11 @@ properties:
- qcom,scm-msm8996
- qcom,scm-msm8998
- qcom,scm-qcm2290
+ - qcom,scm-qcs8300
- qcom,scm-qdu1000
+ - qcom,scm-sa8255p
- qcom,scm-sa8775p
+ - qcom,scm-sar2130p
- qcom,scm-sc7180
- qcom,scm-sc7280
- qcom,scm-sc8180x
@@ -64,6 +67,7 @@ properties:
- qcom,scm-sm8450
- qcom,scm-sm8550
- qcom,scm-sm8650
+ - qcom,scm-sm8750
- qcom,scm-qcs404
- qcom,scm-x1e80100
- const: qcom,scm
@@ -195,6 +199,7 @@ allOf:
- qcom,scm-sm8450
- qcom,scm-sm8550
- qcom,scm-sm8650
+ - qcom,scm-sm8750
then:
properties:
interrupts: false
@@ -204,6 +209,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,scm-sa8255p
- qcom,scm-sa8775p
then:
properties:
diff --git a/Documentation/devicetree/bindings/fpga/altera-passive-serial.txt b/Documentation/devicetree/bindings/fpga/altera-passive-serial.txt
deleted file mode 100644
index 48478bc07e29..000000000000
--- a/Documentation/devicetree/bindings/fpga/altera-passive-serial.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Altera Passive Serial SPI FPGA Manager
-
-Altera FPGAs support a method of loading the bitstream over what is
-referred to as "passive serial".
-The passive serial link is not technically SPI, and might require extra
-circuits in order to play nicely with other SPI slaves on the same bus.
-
-See https://www.altera.com/literature/hb/cyc/cyc_c51013.pdf
-
-Required properties:
-- compatible: Must be one of the following:
- "altr,fpga-passive-serial",
- "altr,fpga-arria10-passive-serial"
-- reg: SPI chip select of the FPGA
-- nconfig-gpios: config pin (referred to as nCONFIG in the manual)
-- nstat-gpios: status pin (referred to as nSTATUS in the manual)
-
-Optional properties:
-- confd-gpios: confd pin (referred to as CONF_DONE in the manual)
-
-Example:
- fpga: fpga@0 {
- compatible = "altr,fpga-passive-serial";
- spi-max-frequency = <20000000>;
- reg = <0>;
- nconfig-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
- nstat-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;
- confd-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>;
- };
diff --git a/Documentation/devicetree/bindings/fpga/altr,fpga-passive-serial.yaml b/Documentation/devicetree/bindings/fpga/altr,fpga-passive-serial.yaml
new file mode 100644
index 000000000000..ffb7cc54556f
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altr,fpga-passive-serial.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fpga/altr,fpga-passive-serial.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Altera Passive Serial SPI FPGA Manager
+
+maintainers:
+ - Fabio Estevam <festevam@denx.de>
+
+description: |
+ Altera FPGAs support a method of loading the bitstream over what is
+ referred to as "passive serial".
+ The passive serial link is not technically SPI, and might require extra
+ circuits in order to play nicely with other SPI slaves on the same bus.
+
+ See https://www.altera.com/literature/hb/cyc/cyc_c51013.pdf
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - altr,fpga-passive-serial
+ - altr,fpga-arria10-passive-serial
+
+ spi-max-frequency:
+ maximum: 20000000
+
+ reg:
+ maxItems: 1
+
+ nconfig-gpios:
+ description:
+ Config pin (referred to as nCONFIG in the manual).
+ maxItems: 1
+
+ nstat-gpios:
+ description:
+ Status pin (referred to as nSTATUS in the manual).
+ maxItems: 1
+
+ confd-gpios:
+ description:
+ confd pin (referred to as CONF_DONE in the manual)
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - nconfig-gpios
+ - nstat-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fpga@0 {
+ compatible = "altr,fpga-passive-serial";
+ reg = <0>;
+ nconfig-gpios = <&gpio4 18 GPIO_ACTIVE_LOW>;
+ nstat-gpios = <&gpio4 19 GPIO_ACTIVE_LOW>;
+ confd-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/gpio/aspeed,ast2400-gpio.yaml b/Documentation/devicetree/bindings/gpio/aspeed,ast2400-gpio.yaml
index cf11aa7ec8c7..b9afd07a9d24 100644
--- a/Documentation/devicetree/bindings/gpio/aspeed,ast2400-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/aspeed,ast2400-gpio.yaml
@@ -15,6 +15,7 @@ properties:
- aspeed,ast2400-gpio
- aspeed,ast2500-gpio
- aspeed,ast2600-gpio
+ - aspeed,ast2700-gpio
reg:
maxItems: 1
@@ -25,7 +26,7 @@ properties:
gpio-controller: true
gpio-line-names:
- minItems: 36
+ minItems: 12
maxItems: 232
gpio-ranges: true
@@ -42,7 +43,7 @@ properties:
const: 2
ngpios:
- minimum: 36
+ minimum: 12
maximum: 232
required:
@@ -93,6 +94,20 @@ allOf:
enum: [ 36, 208 ]
required:
- ngpios
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: aspeed,ast2700-gpio
+ then:
+ properties:
+ gpio-line-names:
+ minItems: 12
+ maxItems: 216
+ ngpios:
+ enum: [ 12, 216 ]
+ required:
+ - ngpios
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
index b394e058256e..87e986386f32 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
@@ -37,7 +37,8 @@ properties:
description:
A list of registers in the controller. The width of each register is
determined by its size. All registers must have the same width. The number
- of GPIOs is set by the width, with bit 0 corresponding to GPIO 0.
+ of GPIOs is set by the width, with bit 0 corresponding to GPIO 0, unless
+ the ngpios property further restricts the number of used lines.
items:
- description:
Register to READ the value of the GPIO lines. If GPIO line is high,
@@ -74,6 +75,15 @@ properties:
native-endian: true
+ ngpios:
+ minimum: 1
+ maximum: 63
+ description:
+ If this property is present the number of usable GPIO lines are restricted
+ to the first 0 .. ngpios lines. This is useful when the GPIO MMIO register
+ has 32 bits for GPIO but only the first 12 are actually connected to
+ real electronics, and then we set ngpios to 12.
+
no-output:
$ref: /schemas/types.yaml#/definitions/flag
description:
@@ -111,6 +121,7 @@ examples:
compatible = "brcm,bcm6345-gpio";
reg-names = "dirout", "dat";
reg = <0xfffe0406 2>, <0xfffe040a 2>;
+ ngpios = <15>;
native-endian;
gpio-controller;
#gpio-cells = <2>;
diff --git a/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml b/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
index 38d37d8f7201..b3e8951959b5 100644
--- a/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
@@ -89,6 +89,7 @@ examples:
interrupts = <0 120 0x4>;
#gpio-cells = <2>;
gpio-controller;
+ #interrupt-cells = <2>;
interrupt-controller;
st,supports-sleepmode;
gpio-bank = <1>;
diff --git a/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml b/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml
index 780ccb5ee9b4..385aac7161a0 100644
--- a/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml
+++ b/Documentation/devicetree/bindings/hwinfo/samsung,exynos-chipid.yaml
@@ -23,6 +23,9 @@ properties:
- items:
- enum:
- samsung,exynos7885-chipid
+ - samsung,exynos8895-chipid
+ - samsung,exynos9810-chipid
+ - samsung,exynos990-chipid
- samsung,exynosautov9-chipid
- samsung,exynosautov920-chipid
- const: samsung,exynos850-chipid
diff --git a/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml b/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml
index 1f98da32f3fe..37e1dc9c7dd3 100644
--- a/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml
+++ b/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml
@@ -26,6 +26,7 @@ properties:
- lltc,ltc3886
- lltc,ltc3887
- lltc,ltc3889
+ - lltc,ltc7841
- lltc,ltc7880
- lltc,ltm2987
- lltc,ltm4664
@@ -50,6 +51,7 @@ properties:
* ltc2977, ltc2979, ltc2980, ltm2987 : vout0 - vout7
* ltc2978 : vout0 - vout7
* ltc3880, ltc3882, ltc3884, ltc3886, ltc3887, ltc3889 : vout0 - vout1
+ * ltc7841 : vout0
* ltc7880 : vout0 - vout1
* ltc3883 : vout0
* ltm4664 : vout0 - vout1
diff --git a/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.yaml b/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.yaml
new file mode 100644
index 000000000000..c1e5dedc2f6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/nuvoton,nct7363.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton NCT7363Y Hardware Monitoring IC
+
+maintainers:
+ - Ban Feng <kcfeng0@nuvoton.com>
+
+description: |
+ The NCT7363Y is a fan controller which provides up to 16 independent
+ FAN input monitors, and up to 16 independent PWM outputs with SMBus interface.
+
+ Datasheets: Available from Nuvoton upon request
+
+properties:
+ compatible:
+ enum:
+ - nuvoton,nct7363
+ - nuvoton,nct7362
+
+ reg:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 2
+
+patternProperties:
+ "^fan-[0-9]+$":
+ $ref: fan-common.yaml#
+ unevaluatedProperties: false
+ required:
+ - pwms
+ - tach-ch
+
+required:
+ - compatible
+ - reg
+ - "#pwm-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hwmon: hwmon@22 {
+ compatible = "nuvoton,nct7363";
+ reg = <0x22>;
+ #pwm-cells = <2>;
+
+ fan-0 {
+ pwms = <&hwmon 0 50000>;
+ tach-ch = /bits/ 8 <0x00>;
+ };
+ fan-1 {
+ pwms = <&hwmon 1 50000>;
+ tach-ch = /bits/ 8 <0x01>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml
new file mode 100644
index 000000000000..bac5f8e352aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml
@@ -0,0 +1,148 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/pmbus/isil,isl68137.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas Digital Multiphase Voltage Regulators with PMBus
+
+maintainers:
+ - Grant Peltier <grant.peltier.jg@renesas.com>
+
+description: |
+ Renesas digital multiphase voltage regulators with PMBus.
+ https://www.renesas.com/en/products/power-management/multiphase-power/multiphase-dcdc-switching-controllers
+
+properties:
+ compatible:
+ enum:
+ - isil,isl68137
+ - renesas,isl68220
+ - renesas,isl68221
+ - renesas,isl68222
+ - renesas,isl68223
+ - renesas,isl68224
+ - renesas,isl68225
+ - renesas,isl68226
+ - renesas,isl68227
+ - renesas,isl68229
+ - renesas,isl68233
+ - renesas,isl68239
+ - renesas,isl69222
+ - renesas,isl69223
+ - renesas,isl69224
+ - renesas,isl69225
+ - renesas,isl69227
+ - renesas,isl69228
+ - renesas,isl69234
+ - renesas,isl69236
+ - renesas,isl69239
+ - renesas,isl69242
+ - renesas,isl69243
+ - renesas,isl69247
+ - renesas,isl69248
+ - renesas,isl69254
+ - renesas,isl69255
+ - renesas,isl69256
+ - renesas,isl69259
+ - isil,isl69260
+ - renesas,isl69268
+ - isil,isl69269
+ - renesas,isl69298
+ - renesas,raa228000
+ - renesas,raa228004
+ - renesas,raa228006
+ - renesas,raa228228
+ - renesas,raa229001
+ - renesas,raa229004
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+patternProperties:
+ "^channel@([0-3])$":
+ type: object
+ description:
+ Container for properties specific to a particular channel (rail).
+
+ properties:
+ reg:
+ description: The channel (rail) index.
+ items:
+ minimum: 0
+ maximum: 3
+
+ vout-voltage-divider:
+ description: |
+ Resistances of a voltage divider placed between Vout and the voltage
+ sense (Vsense) pin for the given channel (rail). It has two numbers
+ representing the resistances of the voltage divider provided as
+ <Rout Rtotal> which yields an adjusted Vout as
+ Vout_adj = Vout * Rtotal / Rout given the original Vout as reported
+ by the Vsense pin. Given a circuit configuration similar to the one
+ below, Rtotal = R1 + Rout.
+
+ Vout ----.
+ |
+ .-----.
+ | R1 |
+ '-----'
+ |
+ +---- Vsense
+ |
+ .-----.
+ | Rout|
+ '-----'
+ |
+ GND
+
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 2
+ maxItems: 2
+
+ required:
+ - reg
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ isl68239@60 {
+ compatible = "isil,isl68137";
+ reg = <0x60>;
+ };
+ };
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ isl68239@60 {
+ compatible = "renesas,isl68239";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ vout-voltage-divider = <1000 2000>; // Reported Vout/Pout would be scaled by 2
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/mps,mp2975.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/mps,mp2975.yaml
new file mode 100644
index 000000000000..f7bc4f077929
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/mps,mp2975.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/pmbus/mps,mp2975.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MPS MP2975 Synchronous Buck Regulator
+
+maintainers:
+ - Naresh Solanki <naresh.solanki@9elements.com>
+
+description:
+ The MPS MP2971, MP2973 & MP2975 is a multi-phase voltage regulator
+ designed for use in high-performance computing and server
+ applications. It supports I2C/PMBus for control and monitoring.
+
+properties:
+ compatible:
+ enum:
+ - mps,mp2971
+ - mps,mp2973
+ - mps,mp2975
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ regulators:
+ type: object
+ description:
+ List of regulators provided by this controller.
+
+ patternProperties:
+ "^vout[0-1]$":
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ regulator@58 {
+ compatible = "mps,mp2973";
+ reg = <0x58>;
+
+ interrupt-parent = <&smb_pex_cpu1_event>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+
+ regulators {
+ vout0 {
+ regulator-name = "pvccin_cpu1";
+ regulator-enable-ramp-delay = <200>;
+ };
+ vout1 {
+ regulator-name = "pvccfa_ehv_fivra_cpu1";
+ regulator-enable-ramp-delay = <200>;
+ };
+ };
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml
new file mode 100644
index 000000000000..f4115870e450
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/pmbus/ti,tps25990.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TPS25990 Stackable eFuse
+
+maintainers:
+ - Jerome Brunet <jbrunet@baylibre.com>
+
+description:
+ The TI TPS25990 is an integrated, high-current circuit
+ protection and power management device with PMBUS interface
+
+properties:
+ compatible:
+ const: ti,tps25990
+
+ reg:
+ maxItems: 1
+
+ ti,rimon-micro-ohms:
+ description:
+ micro Ohms value of the resistance installed between the Imon pin
+ and the ground reference.
+
+ interrupts:
+ description: PMBUS SMB Alert Interrupt.
+ maxItems: 1
+
+ regulators:
+ type: object
+ description:
+ list of regulators provided by this controller.
+
+ properties:
+ vout:
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+
+ gpdac1:
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+
+ gpdac2:
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - ti,rimon-micro-ohms
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hw-monitor@46 {
+ compatible = "ti,tps25990";
+ reg = <0x46>;
+
+ interrupt-parent = <&gpio>;
+ interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+ ti,rimon-micro-ohms = <1370000000>;
+
+ regulators {
+ cpu0_vout: vout {
+ regulator-name = "main_cpu0";
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/vicor,pli1209bc.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/vicor,pli1209bc.yaml
new file mode 100644
index 000000000000..4aa62d67e1a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/vicor,pli1209bc.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/pmbus/vicor,pli1209bc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Vicor PLI1209BC Power Regulator
+
+maintainers:
+ - Marcello Sylvester Bauer <sylv@sylv.io>
+ - Naresh Solanki <naresh.solanki@9elements.com>
+
+description:
+ The Vicor PLI1209BC is a Digital Supervisor with Isolation for use
+ with BCM Bus Converter Modules.
+
+properties:
+ compatible:
+ enum:
+ - vicor,pli1209bc
+
+ reg:
+ maxItems: 1
+
+ regulators:
+ type: object
+ description:
+ List of regulators provided by this controller.
+
+ properties:
+ vout2:
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ regulator@5f {
+ compatible = "vicor,pli1209bc";
+ reg = <0x5f>;
+
+ regulators {
+ p12v_d: vout2 {
+ regulator-name = "bcm3";
+ regulator-boot-on;
+ };
+ };
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/hwmon/pwm-fan.yaml b/Documentation/devicetree/bindings/hwmon/pwm-fan.yaml
index 4e5abf7580cc..8b4ed5ee962f 100644
--- a/Documentation/devicetree/bindings/hwmon/pwm-fan.yaml
+++ b/Documentation/devicetree/bindings/hwmon/pwm-fan.yaml
@@ -31,6 +31,16 @@ properties:
it must be self resetting edge interrupts.
maxItems: 1
+ fan-stop-to-start-percent:
+ description:
+ Minimum fan RPM in percent to start when stopped.
+ minimum: 0
+ maximum: 100
+
+ fan-stop-to-start-us:
+ description:
+ Time to wait in microseconds after start when stopped.
+
pulses-per-revolution:
description:
Define the number of pulses per fan revolution for each tachometer
diff --git a/Documentation/devicetree/bindings/hwmon/renesas,isl28022.yaml b/Documentation/devicetree/bindings/hwmon/renesas,isl28022.yaml
new file mode 100644
index 000000000000..dd82a80e4115
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/renesas,isl28022.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/renesas,isl28022.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas ISL28022 power monitor
+
+maintainers:
+ - Carsten Spieß <mail@carsten-spiess.de>
+
+description: |
+ The ISL28022 is a power monitor with I2C interface. The device monitors
+ voltage, current via shunt resistor and calculated power.
+
+ Datasheets:
+ https://www.renesas.com/us/en/www/doc/datasheet/isl28022.pdf
+
+properties:
+ compatible:
+ const: renesas,isl28022
+
+ reg:
+ maxItems: 1
+
+ shunt-resistor-micro-ohms:
+ description:
+ Shunt resistor value in micro-Ohm
+ minimum: 800
+ default: 10000
+
+ renesas,shunt-range-microvolt:
+ description:
+ Maximal shunt voltage range of +/- 40 mV, 80 mV, 160 mV or 320 mV
+ default: 320000
+ enum: [40000, 80000, 160000, 320000]
+
+ renesas,average-samples:
+ description:
+ Number of samples to be used to report voltage, current and power values.
+ default: 1
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2, 4, 8, 16, 32, 64, 128]
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-monitor@40 {
+ compatible = "renesas,isl28022";
+ reg = <0x40>;
+ shunt-resistor-micro-ohms = <8000>;
+ renesas,shunt-range-microvolt = <40000>;
+ renesas,average-samples = <128>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml b/Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml
new file mode 100644
index 000000000000..5d33f1a23d03
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/ti,amc6821.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AMC6821 Intelligent Temperature Monitor and PWM Fan Controller
+
+maintainers:
+ - Farouk Bouabid <farouk.bouabid@cherry.de>
+ - Quentin Schulz <quentin.schulz@cherry.de>
+
+description:
+ Intelligent temperature monitor and pulse-width modulation (PWM) fan
+ controller.
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - const: tsd,mule
+ - const: ti,amc6821
+ - const: ti,amc6821
+
+ reg:
+ maxItems: 1
+
+ i2c-mux:
+ type: object
+
+required:
+ - compatible
+ - reg
+
+if:
+ properties:
+ compatible:
+ contains:
+ const: tsd,mule
+
+then:
+ required:
+ - i2c-mux
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fan@18 {
+ compatible = "ti,amc6821";
+ reg = <0x18>;
+ };
+ };
+
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fan@18 {
+ compatible = "tsd,mule", "ti,amc6821";
+ reg = <0x18>;
+
+ i2c-mux {
+ compatible = "tsd,mule-i2c-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
index 6ae961732e6b..05a9cb36cd82 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
@@ -20,6 +20,7 @@ description: |
properties:
compatible:
enum:
+ - silergy,sy24655
- ti,ina209
- ti,ina219
- ti,ina220
diff --git a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
index 0ad10d43fac0..a6f9319e068d 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
@@ -4,22 +4,26 @@
$id: http://devicetree.org/schemas/hwmon/ti,tmp108.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: TMP108 temperature sensor
+title: TMP108/P3T1085(NXP) temperature sensor
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description: |
- The TMP108 is a digital-output temperature sensor with a
+ The TMP108/P3T1085(NXP) is a digital-output temperature sensor with a
dynamically-programmable limit window, and under- and overtemperature
alert functions.
+ P3T1085(NXP) support I3C.
+
Datasheets:
https://www.ti.com/product/TMP108
+ https://www.nxp.com/docs/en/data-sheet/P3T1085UK.pdf
properties:
compatible:
enum:
+ - nxp,p3t1085
- ti,tmp108
interrupts:
diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx.yaml
index 85ee1282d6d2..0682a5a10d41 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-imx.yaml
+++ b/Documentation/devicetree/bindings/i2c/i2c-imx.yaml
@@ -18,6 +18,7 @@ properties:
- const: fsl,imx1-i2c
- const: fsl,imx21-i2c
- const: fsl,vf610-i2c
+ - const: nxp,s32g2-i2c
- items:
- enum:
- fsl,ls1012a-i2c
@@ -54,6 +55,9 @@ properties:
- fsl,imx8mn-i2c
- fsl,imx8mp-i2c
- const: fsl,imx21-i2c
+ - items:
+ - const: nxp,s32g3-i2c
+ - const: nxp,s32g2-i2c
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
index 984fc1ed3ec6..c4efcef59133 100644
--- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
@@ -33,6 +33,7 @@ properties:
- allwinner,sun50i-a100-i2c
- allwinner,sun50i-h616-i2c
- allwinner,sun50i-r329-i2c
+ - allwinner,sun55i-a523-i2c
- const: allwinner,sun8i-v536-i2c
- const: allwinner,sun6i-a31-i2c
- const: marvell,mv64xxx-i2c
diff --git a/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml b/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml
index afa3db726229..6ff58b64d496 100644
--- a/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml
@@ -16,7 +16,9 @@ properties:
compatible:
oneOf:
- items:
- - const: microchip,mpfs-i2c # Microchip PolarFire SoC compatible SoCs
+ - enum:
+ - microchip,pic64gx-i2c
+ - microchip,mpfs-i2c # Microchip PolarFire SoC compatible SoCs
- const: microchip,corei2c-rtl-v7 # Microchip Fabric based i2c IP core
- const: microchip,corei2c-rtl-v7 # Microchip Fabric based i2c IP core
diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
index 7dab3852c7f8..ef26ba6eda28 100644
--- a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
+++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
@@ -27,6 +27,7 @@ properties:
- enum:
- qcom,sc7280-cci
- qcom,sc8280xp-cci
+ - qcom,sdm670-cci
- qcom,sdm845-cci
- qcom,sm6350-cci
- qcom,sm8250-cci
@@ -144,6 +145,24 @@ allOf:
compatible:
contains:
enum:
+ - qcom,sdm670-cci
+ then:
+ properties:
+ clocks:
+ minItems: 4
+ maxItems: 4
+ clock-names:
+ items:
+ - const: camnoc_axi
+ - const: soc_ahb
+ - const: cpas_ahb
+ - const: cci
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,sdm845-cci
- qcom,sm6350-cci
then:
diff --git a/Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml b/Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml
new file mode 100644
index 000000000000..eddfd329c67b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/realtek,rtl9301-i2c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek RTL I2C Controller
+
+maintainers:
+ - Chris Packham <chris.packham@alliedtelesis.co.nz>
+
+description:
+ The RTL9300 SoC has two I2C controllers. Each of these has an SCL line (which
+ if not-used for SCL can be a GPIO). There are 8 common SDA lines that can be
+ assigned to either I2C controller.
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - realtek,rtl9302b-i2c
+ - realtek,rtl9302c-i2c
+ - realtek,rtl9303-i2c
+ - const: realtek,rtl9301-i2c
+ - const: realtek,rtl9301-i2c
+
+ reg:
+ description: Register offset and size this I2C controller.
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+patternProperties:
+ '^i2c@[0-7]$':
+ $ref: /schemas/i2c/i2c-controller.yaml
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description: The SDA pin associated with the I2C bus.
+ maxItems: 1
+
+ required:
+ - reg
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c@36c {
+ compatible = "realtek,rtl9301-i2c";
+ reg = <0x36c 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
index 60035a787e5c..e5d05263c45a 100644
--- a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
@@ -97,6 +97,22 @@ properties:
- const: tx
- const: rx
+ snps,bus-capacitance-pf:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ This property indicates the bus capacitance in picofarads (pF).
+ This value is used to compute the tHIGH and tLOW periods for high speed
+ mode.
+ enum: [100, 400]
+ default: 100
+
+ snps,clk-freq-optimized:
+ description:
+ This property indicates whether the hardware reduce its clock frequency
+ by reducing the internal latency required to generate the high period and
+ low period of SCL line.
+ type: boolean
+
unevaluatedProperties: false
required:
@@ -121,6 +137,8 @@ examples:
i2c-sda-hold-time-ns = <300>;
i2c-sda-falling-time-ns = <300>;
i2c-scl-falling-time-ns = <300>;
+ snps,bus-capacitance-pf = <400>;
+ snps,clk-freq-optimized;
};
- |
i2c@2000 {
diff --git a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
index 44c54b162bb1..012402debfeb 100644
--- a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
@@ -22,6 +22,7 @@ select:
enum:
- st,nomadik-i2c
- mobileye,eyeq5-i2c
+ - mobileye,eyeq6h-i2c
required:
- compatible
@@ -29,15 +30,15 @@ properties:
compatible:
oneOf:
- items:
- - const: st,nomadik-i2c
+ - enum:
+ - st,nomadik-i2c
+ - mobileye,eyeq5-i2c
+ - mobileye,eyeq6h-i2c
- const: arm,primecell
- items:
- const: stericsson,db8500-i2c
- const: st,nomadik-i2c
- const: arm,primecell
- - items:
- - const: mobileye,eyeq5-i2c
- - const: arm,primecell
reg:
maxItems: 1
@@ -54,7 +55,7 @@ properties:
- items:
- const: mclk
- const: apb_pclk
- # Clock name in DB8500 or EyeQ5
+ # Clock name in DB8500 or EyeQ
- items:
- const: i2cclk
- const: apb_pclk
@@ -67,7 +68,7 @@ properties:
clock-frequency:
minimum: 1
- maximum: 400000
+ maximum: 3400000
mobileye,olb:
$ref: /schemas/types.yaml#/definitions/phandle-array
diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index 8e7835cf36fd..b9bc02b5b07a 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -37,6 +37,10 @@ properties:
to both the positive and negative inputs of a differential ADC.
The first value specifies the positive input pin, the second
specifies the negative input pin.
+ There are also some ADCs, where the differential channel has dedicated
+ positive and negative inputs which can be used to measure differential
+ voltage levels. For those setups, this property can be configured with
+ the 'reg' property for both inputs (i.e. diff-channels = <reg reg>).
single-channel:
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml
index 17c5d39cc2c1..ad15cf9bc2ff 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml
@@ -28,6 +28,7 @@ description: |
Datasheets for supported chips:
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4111.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4112.pdf
+ <AD4113: not released yet>
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4114.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4115.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4116.pdf
@@ -44,6 +45,7 @@ properties:
enum:
- adi,ad4111
- adi,ad4112
+ - adi,ad4113
- adi,ad4114
- adi,ad4115
- adi,ad4116
@@ -331,6 +333,7 @@ allOf:
enum:
- adi,ad4111
- adi,ad4112
+ - adi,ad4113
- adi,ad4114
- adi,ad4115
- adi,ad4116
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
index 0065d6508824..ada08005b3cd 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
@@ -25,6 +25,8 @@ description: |
* https://www.analog.com/en/products/ad7386-4.html
* https://www.analog.com/en/products/ad7387-4.html
* https://www.analog.com/en/products/ad7388-4.html
+ * https://www.analog.com/en/products/adaq4370-4.html
+ * https://www.analog.com/en/products/adaq4380-4.html
$ref: /schemas/spi/spi-peripheral-props.yaml#
@@ -46,6 +48,8 @@ properties:
- adi,ad7386-4
- adi,ad7387-4
- adi,ad7388-4
+ - adi,adaq4370-4
+ - adi,adaq4380-4
reg:
maxItems: 1
@@ -70,6 +74,20 @@ properties:
refin-supply:
description:
A 2.5V to 3.3V supply for external reference voltage, for ad7380-4 only.
+ For adaq devices, a 5V supply voltage. A 3.3V internal reference is
+ derived from it. Connect to vs-p-supply for normal operation.
+
+ vs-p-supply:
+ description:
+ Amplifiers positive supply.
+
+ vs-n-supply:
+ description:
+ Amplifiers negative supply.
+
+ ldo-supply:
+ description:
+ LDO supply. Connect to vs-p-supply or a 3.6 to 5.5 V supply.
aina-supply:
description:
@@ -97,12 +115,45 @@ properties:
specify the ALERT interrupt.
maxItems: 1
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
required:
- compatible
- reg
- vcc-supply
- vlogic-supply
+patternProperties:
+ "^channel@[0-3]$":
+ $ref: adc.yaml
+ type: object
+
+ properties:
+ reg:
+ description:
+ The channel number. From 0 to 3 corresponding to channels A,B,C,D
+ minimum: 0
+ maximum: 3
+
+ adi,gain-milli:
+ description:
+ The hardware gain applied to the ADC input (in milli units).
+ If not present, default to 1000 (no actual gain applied).
+ Refer to the typical connection diagrams section of the datasheet for
+ pin wiring.
+ $ref: /schemas/types.yaml#/definitions/uint16
+ enum: [300, 600, 1000, 1600]
+ default: 1000
+
+ required:
+ - reg
+
+ additionalProperties: false
+
unevaluatedProperties: false
allOf:
@@ -140,6 +191,7 @@ allOf:
aind-supply: false
# ad7380-4 uses refin-supply as external reference.
+ # adaq devices use internal reference only, derived from refin-supply
# All other chips from ad738x family use refio as optional external reference.
# When refio-supply is omitted, internal reference is used.
- if:
@@ -147,6 +199,8 @@ allOf:
compatible:
enum:
- adi,ad7380-4
+ - adi,adaq4370-4
+ - adi,adaq4380-4
then:
properties:
refio-supply: false
@@ -156,6 +210,27 @@ allOf:
properties:
refin-supply: false
+ # adaq devices need more supplies and using channel to declare gain property
+ # only applies to adaq devices
+ - if:
+ properties:
+ compatible:
+ enum:
+ - adi,adaq4370-4
+ - adi,adaq4380-4
+ then:
+ required:
+ - vs-p-supply
+ - vs-n-supply
+ - ldo-supply
+ else:
+ properties:
+ vs-p-supply: false
+ vs-n-supply: false
+ ldo-supply: false
+ patternProperties:
+ "^channel@[0-3]$": false
+
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
@@ -180,3 +255,48 @@ examples:
refio-supply = <&supply_2_5V>;
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,adaq4380-4";
+ reg = <0>;
+
+ spi-cpol;
+ spi-cpha;
+ spi-max-frequency = <80000000>;
+
+ interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-parent = <&gpio0>;
+
+ vcc-supply = <&supply_3_3V>;
+ vlogic-supply = <&supply_3_3V>;
+ refin-supply = <&supply_5V>;
+ vs-p-supply = <&supply_5V>;
+ vs-n-supply = <&supply_0V>;
+ ldo-supply = <&supply_5V>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ adi,gain-milli = /bits/ 16 <300>;
+ };
+
+ channel@2 {
+ reg = <2>;
+ adi,gain-milli = /bits/ 16 <600>;
+ };
+
+ channel@3 {
+ reg = <3>;
+ adi,gain-milli = /bits/ 16 <1000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
index 69408cae3db9..ab5881d0d017 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
@@ -14,6 +14,11 @@ description: |
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7605-4.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606c-16.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606c-18.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7607.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7608.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7609.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf
properties:
@@ -24,11 +29,27 @@ properties:
- adi,ad7606-6
- adi,ad7606-8 # Referred to as AD7606 (without -8) in the datasheet
- adi,ad7606b
+ - adi,ad7606c-16
+ - adi,ad7606c-18
+ - adi,ad7607
+ - adi,ad7608
+ - adi,ad7609
- adi,ad7616
reg:
maxItems: 1
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ # According to the datasheet, "Data is clocked in from SDI on the falling
+ # edge of SCLK, while data is clocked out on DOUTA on the rising edge of
+ # SCLK". Also, even if not stated textually in the datasheet, it is made
+ # clear on the diagrams that sclk idles at high. Subsequently, in case SPI
+ # interface is used, the correct way is to only set spi-cpol.
spi-cpha: true
spi-cpol: true
@@ -114,18 +135,91 @@ properties:
assumed that the pins are hardwired to VDD.
type: boolean
+ pwms:
+ description:
+ In case the conversion is triggered by a PWM instead of a GPIO plugged to
+ the CONVST pin, the PWM must be referenced.
+ The first is the PWM connected to CONVST or CONVST1 for the chips with the
+ 2nd PWM connected to CONVST2, if CONVST2 is available and not shorted to
+ CONVST1.
+ minItems: 1
+ maxItems: 2
+
+ pwm-names:
+ items:
+ - const: convst1
+ - const: convst2
+
+ io-backends:
+ description:
+ A reference to the iio-backend, which is responsible handling the BUSY
+ pin's falling edge and communication.
+ An example of backend can be found at
+ http://analogdevicesinc.github.io/hdl/library/axi_ad7606x/index.html
+
+
+patternProperties:
+ "^channel@[1-8]$":
+ type: object
+ $ref: adc.yaml
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description:
+ The channel number, as specified in the datasheet (from 1 to 8).
+ minimum: 1
+ maximum: 8
+
+ diff-channels:
+ description:
+ Each channel can be configured as a bipolar differential channel.
+ The ADC uses the same positive and negative inputs for this.
+ This property must be specified as 'reg' (or the channel number) for
+ both positive and negative inputs (i.e. diff-channels = <reg reg>).
+ Since the configuration is bipolar differential, the 'bipolar'
+ property is required.
+ items:
+ minimum: 1
+ maximum: 8
+
+ bipolar:
+ description:
+ The ADC channels can be configured as
+ * Bipolar single-ended
+ * Unipolar single-ended
+ * Bipolar differential
+ Therefore in the DT, if no channel node is specified, it is considered
+ 'unipolar single-ended'. So for the other configurations the 'bipolar'
+ property must be specified. If 'diff-channels' is specified, it is
+ considered a bipolar differential channel. Otherwise it is bipolar
+ single-ended.
+
+ required:
+ - reg
+ - bipolar
+
required:
- compatible
- reg
- - spi-cpha
- avcc-supply
- vdrive-supply
- - interrupts
- - adi,conversion-start-gpios
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - oneOf:
+ - required:
+ - adi,conversion-start-gpios
+ - required:
+ - pwms
+
+ - oneOf:
+ - required:
+ - interrupts
+ - required:
+ - io-backends
+
- if:
properties:
compatible:
@@ -162,19 +256,68 @@ allOf:
- adi,ad7606-4
- adi,ad7606-6
- adi,ad7606-8
+ - adi,ad7607
+ - adi,ad7608
+ - adi,ad7609
then:
properties:
adi,sw-mode: false
else:
properties:
+ pwms:
+ maxItems: 1
+ pwm-names:
+ maxItems: 1
adi,conversion-start-gpios:
maxItems: 1
+ - if:
+ not:
+ required:
+ - adi,sw-mode
+ then:
+ patternProperties:
+ "^channel@[1-8]$": false
+
+ - if:
+ not:
+ properties:
+ compatible:
+ enum:
+ - adi,ad7606c-16
+ - adi,ad7606c-18
+ then:
+ patternProperties:
+ "^channel@[1-8]$": false
+
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
+ iio-backend {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ adi_adc@0 {
+ compatible = "adi,ad7606b";
+ reg = <0>;
+ pwms = <&axi_pwm_gen 0 0>;
+
+ avcc-supply = <&adc_vref>;
+ vdrive-supply = <&vdd_supply>;
+
+ reset-gpios = <&gpio0 91 GPIO_ACTIVE_HIGH>;
+ standby-gpios = <&gpio0 90 GPIO_ACTIVE_LOW>;
+ adi,range-gpios = <&gpio0 89 GPIO_ACTIVE_HIGH>;
+ adi,oversampling-ratio-gpios = <&gpio0 88 GPIO_ACTIVE_HIGH
+ &gpio0 87 GPIO_ACTIVE_HIGH
+ &gpio0 86 GPIO_ACTIVE_HIGH>;
+ io-backends = <&iio_backend>;
+ };
+ };
+
+ - |
+ #include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
spi {
#address-cells = <1>;
@@ -185,7 +328,6 @@ examples:
reg = <0>;
spi-max-frequency = <1000000>;
spi-cpol;
- spi-cpha;
avcc-supply = <&adc_vref>;
vdrive-supply = <&vdd_supply>;
@@ -202,4 +344,53 @@ examples:
standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
};
};
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,ad7606c-18";
+ reg = <0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spi-max-frequency = <1000000>;
+ spi-cpol;
+
+ avcc-supply = <&adc_vref>;
+ vdrive-supply = <&vdd_supply>;
+
+ interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-parent = <&gpio>;
+
+ adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
+ adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
+ standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
+
+ adi,sw-mode;
+
+ channel@1 {
+ reg = <1>;
+ diff-channels = <1 1>;
+ bipolar;
+ };
+
+ channel@3 {
+ reg = <3>;
+ bipolar;
+ };
+
+ channel@8 {
+ reg = <8>;
+ diff-channels = <8 8>;
+ bipolar;
+ };
+
+ };
+ };
...
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml
new file mode 100644
index 000000000000..8848562af28f
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/adi,ad7625.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices Fast PulSAR Analog to Digital Converters
+
+maintainers:
+ - Michael Hennerich <Michael.Hennerich@analog.com>
+ - Nuno Sá <nuno.sa@analog.com>
+
+description: |
+ A family of single channel differential analog to digital converters.
+
+ * https://www.analog.com/en/products/ad7625.html
+ * https://www.analog.com/en/products/ad7626.html
+ * https://www.analog.com/en/products/ad7960.html
+ * https://www.analog.com/en/products/ad7961.html
+
+properties:
+ compatible:
+ enum:
+ - adi,ad7625
+ - adi,ad7626
+ - adi,ad7960
+ - adi,ad7961
+
+ vdd1-supply: true
+ vdd2-supply: true
+ vio-supply: true
+
+ ref-supply:
+ description:
+ Voltage regulator for the external reference voltage (REF).
+
+ refin-supply:
+ description:
+ Voltage regulator for the reference buffer input (REFIN).
+
+ clocks:
+ description:
+ The clock connected to the CLK pins, gated by the clk_gate PWM.
+ maxItems: 1
+
+ pwms:
+ items:
+ - description: PWM connected to the CNV input on the ADC.
+ - description: PWM that gates the clock connected to the ADC's CLK input.
+
+ pwm-names:
+ items:
+ - const: cnv
+ - const: clk_gate
+
+ io-backends:
+ description:
+ The AXI ADC IP block connected to the D+/- and DCO+/- lines of the
+ ADC. An example backend can be found at
+ http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html.
+ maxItems: 1
+
+ adi,no-dco:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates the wiring of the DCO+/- lines. If true, then they are
+ grounded and the device is in self-clocked mode. If this is not
+ present, then the device is in echoed clock mode.
+
+ adi,en0-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN0 is hard-wired to the high state. If neither this
+ nor en0-gpios are present, then EN0 is hard-wired low.
+
+ adi,en1-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN1 is hard-wired to the high state. If neither this
+ nor en1-gpios are present, then EN1 is hard-wired low.
+
+ adi,en2-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN2 is hard-wired to the high state. If neither this
+ nor en2-gpios are present, then EN2 is hard-wired low.
+
+ adi,en3-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN3 is hard-wired to the high state. If neither this
+ nor en3-gpios are present, then EN3 is hard-wired low.
+
+ en0-gpios:
+ description:
+ Configurable EN0 pin.
+
+ en1-gpios:
+ description:
+ Configurable EN1 pin.
+
+ en2-gpios:
+ description:
+ Configurable EN2 pin.
+
+ en3-gpios:
+ description:
+ Configurable EN3 pin.
+
+required:
+ - compatible
+ - vdd1-supply
+ - vdd2-supply
+ - vio-supply
+ - clocks
+ - pwms
+ - pwm-names
+ - io-backends
+
+allOf:
+ - if:
+ required:
+ - ref-supply
+ then:
+ properties:
+ refin-supply: false
+ - if:
+ required:
+ - refin-supply
+ then:
+ properties:
+ ref-supply: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad7625
+ - adi,ad7626
+ then:
+ properties:
+ en2-gpios: false
+ en3-gpios: false
+ adi,en2-always-on: false
+ adi,en3-always-on: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad7960
+ - adi,ad7961
+ then:
+ # ad796x parts must have one of the two supplies
+ oneOf:
+ - required: [ref-supply]
+ - required: [refin-supply]
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ adc {
+ compatible = "adi,ad7625";
+ vdd1-supply = <&supply_5V>;
+ vdd2-supply = <&supply_2_5V>;
+ vio-supply = <&supply_2_5V>;
+ io-backends = <&axi_adc>;
+ clocks = <&ref_clk>;
+ pwms = <&axi_pwm_gen 0 0>, <&axi_pwm_gen 1 0>;
+ pwm-names = "cnv", "clk_gate";
+ en0-gpios = <&gpio0 86 GPIO_ACTIVE_HIGH>;
+ en1-gpios = <&gpio0 87 GPIO_ACTIVE_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml
new file mode 100644
index 000000000000..044f92f39cfa
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/adi,ad7779.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD777X family 8-Channel, 24-Bit, Simultaneous Sampling ADCs
+
+maintainers:
+ - Ramona Nechita <ramona.nechita@analog.com>
+
+description: |
+ The AD777X family consist of 8-channel, simultaneous sampling analog-to-
+ digital converter (ADC). Eight full Σ-Δ ADCs are on-chip. The
+ AD7771 provides an ultralow input current to allow direct sensor
+ connection. Each input channel has a programmable gain stage
+ allowing gains of 1, 2, 4, and 8 to map lower amplitude sensor
+ outputs into the full-scale ADC input range, maximizing the
+ dynamic range of the signal chain.
+
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7770.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7771.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7779.pdf
+
+$ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - adi,ad7770
+ - adi,ad7771
+ - adi,ad7779
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ clocks:
+ maxItems: 1
+
+ avdd1-supply:
+ description: Front-End analog supply AVDD1. Can be used as conversion ref.
+
+ avdd2-supply:
+ description: AVDD2 Analog Supply from 2.2 V to 3.6 V.
+
+ avdd4-supply:
+ description: AVDD4 SAR Analog Supply and Reference Source.
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: |
+ adc_rdy: Interrupt line for DRDY signal which indicates the end of
+ conversion independently of the interface selected to read back the
+ Σ-∆ conversion.
+ - description: |
+ Alert: The chip includes self diagnostic features to guarantee the
+ correct operation. If an error is detected, the ALERT pin is pulled
+ high to generate an external interruption to the controller.
+
+ interrupt-names:
+ minItems: 1
+ maxItems: 2
+ items:
+ enum:
+ - adc_rdy
+ - alert
+
+ start-gpios:
+ description:
+ Pin that controls start synchronization pulse.
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,ad7779";
+ reg = <0>;
+ start-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio0 93 GPIO_ACTIVE_LOW>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "adc_rdy";
+ clocks = <&adc_clk>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
index f748f3a60b35..b0962a4583ac 100644
--- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
@@ -98,6 +98,7 @@ allOf:
compatible:
contains:
enum:
+ - amlogic,meson8-saradc
- amlogic,meson8b-saradc
- amlogic,meson8m2-saradc
then:
diff --git a/Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml b/Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml
new file mode 100644
index 000000000000..2cea7c104a26
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/gehc,pmc-adc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GE HealthCare PMC Analog to Digital Converter (ADC)
+
+maintainers:
+ - Herve Codina <herve.codina@bootlin.com>
+
+description:
+ The GE HealthCare PMC ADC is a 16-Channel (voltage and current), 16-Bit ADC
+ with an I2C Interface.
+
+properties:
+ compatible:
+ const: gehc,pmc-adc
+
+ reg:
+ maxItems: 1
+
+ vdd-supply:
+ description:
+ Regulator for the VDD power supply.
+
+ vdda-supply:
+ description:
+ Regulator for the VDD analog (VDDA) power supply.
+
+ vddio-supply:
+ description:
+ Regulator for the VDD IO (VDDIO) power supply.
+
+ vref-supply:
+ description:
+ Regulator for the voltage reference power supply.
+
+ clocks:
+ maxItems: 1
+ description:
+ The component uses an external oscillator (osc) if an external oscillator
+ is connected to its clock pins. Otherwise, it uses an internal reference
+ clock.
+
+ clock-names:
+ items:
+ - const: osc
+
+ "#io-channel-cells":
+ const: 2
+ description: |
+ The first cell is the channel type (dt-bindings/iio/adc/gehc,pmc-adc.h
+ defines these values):
+ - 0: voltage
+ - 1: current
+ The second cell is the channel number from 0 to 15.
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vdda-supply
+ - vddio-supply
+ - vref-supply
+ - '#io-channel-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@14 {
+ compatible = "gehc,pmc-adc";
+ reg = <0x14>;
+ vdd-supply = <&reg_vdd>;
+ vdda-supply = <&reg_vdda>;
+ vddio-supply = <&reg_vddio>;
+ vref-supply = <&reg_vref>;
+ #io-channel-cells = <2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/adc/sprd,sc2720-adc.yaml b/Documentation/devicetree/bindings/iio/adc/sprd,sc2720-adc.yaml
index 8181cf9a8e07..a678323d78e3 100644
--- a/Documentation/devicetree/bindings/iio/adc/sprd,sc2720-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/sprd,sc2720-adc.yaml
@@ -85,23 +85,6 @@ examples:
pmic {
#address-cells = <1>;
#size-cells = <0>;
- adc@480 {
- compatible = "sprd,sc2731-adc";
- reg = <0x480>;
- interrupt-parent = <&sc2731_pmic>;
- interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
- #io-channel-cells = <1>;
- hwlocks = <&hwlock 4>;
- nvmem-cells = <&adc_big_scale>, <&adc_small_scale>;
- nvmem-cell-names = "big_scale_calib", "small_scale_calib";
- };
- };
-
- - |
- #include <dt-bindings/interrupt-controller/irq.h>
- pmic {
- #address-cells = <1>;
- #size-cells = <0>;
adc@504 {
compatible = "sprd,ump9620-adc";
reg = <0x504>;
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
index fc8b97f82077..2d2561a52683 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
@@ -30,7 +30,7 @@ properties:
maxItems: 1
spi-max-frequency:
- maximum: 30000000
+ maximum: 66000000
reset-gpios:
maxItems: 1
@@ -60,6 +60,12 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
+ io-backends:
+ description: The iio backend reference.
+ Device can be optionally connected to the "axi-ad3552r IP" fpga-based
+ QSPI + DDR (Double Data Rate) controller to reach high speed transfers.
+ maxItems: 1
+
'#address-cells':
const: 1
@@ -128,6 +134,7 @@ patternProperties:
- custom-output-range-config
allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
- if:
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
index c81285d84db7..79cb4b78a88a 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
@@ -26,16 +26,47 @@ properties:
vdd-supply: true
vss-supply: true
+ vcc-supply:
+ description:
+ Supply that powers the chip.
+
+ iovcc-supply:
+ description:
+ Supply for the digital interface.
+
+ vrefp-supply:
+ description:
+ Positive referance input voltage range. From 5v to (vdd - 2.5)
+
+ vrefn-supply:
+ description:
+ Negative referance input voltage range. From (vss + 2.5) to 0.
+
adi,rbuf-gain2-en:
description: Specify to allow an external amplifier to be connected in a
gain of two configuration.
type: boolean
+ reset-gpios:
+ maxItems: 1
+
+ clear-gpios:
+ maxItems: 1
+
+ ldac-gpios:
+ description:
+ LDAC pin to be used as a hardware trigger to update the DAC channels.
+ maxItems: 1
+
required:
- compatible
- reg
- vdd-supply
- vss-supply
+ - vcc-supply
+ - iovcc-supply
+ - vrefp-supply
+ - vrefn-supply
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
@@ -44,6 +75,7 @@ unevaluatedProperties: false
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
@@ -53,6 +85,13 @@ examples:
reg = <0>;
vss-supply = <&dac_vss>;
vdd-supply = <&dac_vdd>;
+ vcc-supply = <&dac_vcc>;
+ iovcc-supply = <&dac_iovcc>;
+ vrefp-supply = <&dac_vrefp>;
+ vrefn-supply = <&dac_vrefn>;
+ reset-gpios = <&gpio_bd 16 GPIO_ACTIVE_LOW>;
+ clear-gpios = <&gpio_bd 17 GPIO_ACTIVE_LOW>;
+ ldac-gpios = <&gpio_bd 18 GPIO_ACTIVE_HIGH>;
};
};
...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml
new file mode 100644
index 000000000000..b65928024e12
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml
@@ -0,0 +1,164 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2024 Analog Devices Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad8460.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD8460 DAC
+
+maintainers:
+ - Mariel Tinaco <mariel.tinaco@analog.com>
+
+description: |
+ Analog Devices AD8460 110 V High Voltage, 1 A High Current,
+ Arbitrary Waveform Generator with Integrated 14-Bit High Speed DAC
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad8460.pdf
+
+properties:
+ compatible:
+ enum:
+ - adi,ad8460
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ dmas:
+ maxItems: 1
+
+ dma-names:
+ items:
+ - const: tx
+
+ spi-max-frequency:
+ maximum: 20000000
+
+ hvcc-supply:
+ description: Positive high voltage power supply line
+
+ hvee-supply:
+ description: Negative high voltage power supply line
+
+ vcc-5v-supply:
+ description: Low voltage power supply
+
+ vref-5v-supply:
+ description: Reference voltage for analog low voltage
+
+ dvdd-3p3v-supply:
+ description: Digital supply bypass
+
+ avdd-3p3v-supply:
+ description: Analog supply bypass
+
+ refio-1p2v-supply:
+ description: Drive voltage in the range of 1.2V maximum to as low as
+ low as 0.12V through the REF_IO pin to adjust full scale output span
+
+ adi,external-resistor-ohms:
+ description: Specify value of external resistor connected to FS_ADJ pin
+ to establish internal HVDAC's reference current I_REF
+ minimum: 2000
+ maximum: 20000
+ default: 2000
+
+ adi,range-microvolt:
+ description: Voltage output range specified as <minimum, maximum>
+ items:
+ - minimum: -55000000
+ maximum: 0
+ default: 0
+ - minimum: 0
+ maximum: 55000000
+ default: 0
+
+ adi,range-microamp:
+ description: Current output range specified as <minimum, maximum>
+ items:
+ - minimum: -1000000
+ maximum: 0
+ default: 0
+ - minimum: 0
+ maximum: 1000000
+ default: 0
+
+ adi,max-millicelsius:
+ description: Overtemperature threshold
+ minimum: 0
+ maximum: 150000
+ default: 0
+
+ shutdown-reset-gpios:
+ description: Corresponds to SDN_RESET pin. To exit shutdown
+ or sleep mode, pulse SDN_RESET HIGH, then leave LOW.
+ maxItems: 1
+
+ reset-gpios:
+ description: Manual Power On Reset (POR). Pull this GPIO pin
+ LOW and then HIGH to reset all digital registers to default
+ maxItems: 1
+
+ shutdown-gpios:
+ description: Corresponds to SDN_IO pin. Shutdown may be
+ initiated by the user, by pulsing SDN_IO high. To exit shutdown,
+ pulse SDN_IO low, then float.
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - hvcc-supply
+ - hvee-supply
+ - vcc-5v-supply
+ - vref-5v-supply
+ - dvdd-3p3v-supply
+ - avdd-3p3v-supply
+ - refio-1p2v-supply
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad8460";
+ reg = <0>;
+ spi-max-frequency = <8000000>;
+
+ dmas = <&tx_dma 0>;
+ dma-names = "tx";
+
+ shutdown-reset-gpios = <&gpio 86 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio 91 GPIO_ACTIVE_LOW>;
+ shutdown-gpios = <&gpio 88 GPIO_ACTIVE_HIGH>;
+
+ clocks = <&sync_ext_clk>;
+
+ hvcc-supply = <&hvcc>;
+ hvee-supply = <&hvee>;
+ vcc-5v-supply = <&vcc_5>;
+ vref-5v-supply = <&vref_5>;
+ dvdd-3p3v-supply = <&dvdd_3_3>;
+ avdd-3p3v-supply = <&avdd_3_3>;
+ refio-1p2v-supply = <&refio_1_2>;
+
+ adi,external-resistor-ohms = <2000>;
+ adi,range-microvolt = <(-40000000) 40000000>;
+ adi,range-microamp = <0 50000>;
+ adi,max-millicelsius = <50000>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
index a55e9bfc66d7..1adba9aceeb1 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
@@ -19,11 +19,13 @@ description: |
memory via DMA into the DAC.
https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
+ https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
properties:
compatible:
enum:
- adi,axi-dac-9.1.b
+ - adi,axi-ad3552r
reg:
maxItems: 1
@@ -36,7 +38,14 @@ properties:
- const: tx
clocks:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: s_axi_aclk
+ - const: dac_clk
+ minItems: 1
'#io-backend-cells':
const: 0
@@ -47,7 +56,29 @@ required:
- reg
- clocks
-additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: adi,axi-ad3552r
+ then:
+ $ref: /schemas/spi/spi-controller.yaml#
+ properties:
+ clocks:
+ minItems: 2
+ clock-names:
+ minItems: 2
+ required:
+ - clock-names
+ else:
+ properties:
+ clocks:
+ maxItems: 1
+ clock-names:
+ maxItems: 1
+
+unevaluatedProperties: false
examples:
- |
@@ -57,6 +88,38 @@ examples:
dmas = <&tx_dma 0>;
dma-names = "tx";
#io-backend-cells = <0>;
- clocks = <&axi_clk>;
+ clocks = <&clkc 15>;
+ clock-names = "s_axi_aclk";
+ };
+
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ axi_dac: spi@44a70000 {
+ compatible = "adi,axi-ad3552r";
+ reg = <0x44a70000 0x1000>;
+ dmas = <&dac_tx_dma 0>;
+ dma-names = "tx";
+ #io-backend-cells = <0>;
+ clocks = <&clkc 15>, <&ref_clk>;
+ clock-names = "s_axi_aclk", "dac_clk";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad3552r";
+ reg = <0>;
+ reset-gpios = <&gpio0 92 GPIO_ACTIVE_HIGH>;
+ io-backends = <&axi_dac>;
+ spi-max-frequency = <20000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ adi,output-range-microvolt = <(-10000000) (10000000)>;
+ };
+ };
};
...
diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml
new file mode 100644
index 000000000000..7b0cde1c9b0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/bosch,bmi270.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Bosch BMI270 6-Axis IMU
+
+maintainers:
+ - Alex Lanzano <lanzano.alex@gmail.com>
+
+description: |
+ BMI270 is a 6-axis inertial measurement unit that can measure acceleration and
+ angular velocity. The sensor also supports configurable interrupt events such
+ as motion, step counter, and wrist motion gestures. The sensor can communicate
+ I2C or SPI.
+ https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi270/
+
+properties:
+ compatible:
+ enum:
+ - bosch,bmi260
+ - bosch,bmi270
+
+ reg:
+ maxItems: 1
+
+ vdd-supply: true
+ vddio-supply: true
+
+ interrupts:
+ minItems: 1
+ maxItems: 2
+
+ interrupt-names:
+ minItems: 1
+ maxItems: 2
+ items:
+ enum:
+ - INT1
+ - INT2
+
+ drive-open-drain:
+ description:
+ set if the specified interrupt pins should be configured as
+ open drain. If not set, defaults to push-pull.
+
+ mount-matrix:
+ description:
+ an optional 3x3 mounting rotation matrix.
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vddio-supply
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ imu@68 {
+ compatible = "bosch,bmi270";
+ reg = <0x68>;
+ vdd-supply = <&vdd>;
+ vddio-supply = <&vddio>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <16 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "INT1";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml
new file mode 100644
index 000000000000..58f1411728f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/bosch,smi240.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Bosch smi240 imu
+
+maintainers:
+ - Jianping Shen <Jianping.Shen@de.bosch.com>
+
+description:
+ Inertial Measurement Unit with Accelerometer and Gyroscope
+ with a measurement range of +/-300°/s and up to 16g.
+ https://www.bosch-semiconductors.com/mems-sensors/highly-automated-driving/smi240/
+
+properties:
+ compatible:
+ const: bosch,smi240
+
+ reg:
+ maxItems: 1
+
+ vdd-supply: true
+ vddio-supply: true
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vddio-supply
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ imu@0 {
+ compatible = "bosch,smi240";
+ reg = <0>;
+ vdd-supply = <&vdd>;
+ vddio-supply = <&vddio>;
+ spi-max-frequency = <10000000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
index 3769f8e8e98c..7e4492bbd027 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: InvenSense ICM-426xx Inertial Measurement Unit
maintainers:
- - Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+ - Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
description: |
6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
index 587ff2bced2d..f91954870a44 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device
maintainers:
- - Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+ - Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
description: |
These devices support both I2C and SPI bus interfaces.
@@ -36,6 +36,11 @@ properties:
- items:
- const: invensense,icm20608d
- const: invensense,icm20608
+ - items:
+ - enum:
+ - invensense,iam20680hp
+ - invensense,iam20680ht
+ - const: invensense,iam20680
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml b/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml
index 441e9343fc97..67ca8d08256a 100644
--- a/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml
+++ b/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml
@@ -15,7 +15,9 @@ description: |
properties:
compatible:
- const: ti,opt3001
+ enum:
+ - ti,opt3001
+ - ti,opt3002
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/light/veml6030.yaml b/Documentation/devicetree/bindings/iio/light/veml6030.yaml
deleted file mode 100644
index fb19a2d7a849..000000000000
--- a/Documentation/devicetree/bindings/iio/light/veml6030.yaml
+++ /dev/null
@@ -1,64 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/iio/light/veml6030.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: VEML6030 Ambient Light Sensor (ALS)
-
-maintainers:
- - Rishi Gupta <gupt21@gmail.com>
-
-description: |
- Bindings for the ambient light sensor veml6030 from Vishay
- Semiconductors over an i2c interface.
-
- Irrespective of whether interrupt is used or not, application
- can get the ALS and White channel reading from IIO raw interface.
-
- If the interrupts are used, application will receive an IIO event
- whenever configured threshold is crossed.
-
- Specifications about the sensor can be found at:
- https://www.vishay.com/docs/84366/veml6030.pdf
-
-properties:
- compatible:
- enum:
- - vishay,veml6030
-
- reg:
- description:
- I2C address of the device.
- enum:
- - 0x10 # ADDR pin pulled down
- - 0x48 # ADDR pin pulled up
-
- interrupts:
- description:
- interrupt mapping for IRQ. Configure with IRQ_TYPE_LEVEL_LOW.
- Refer to interrupt-controller/interrupts.txt for generic
- interrupt client node bindings.
- maxItems: 1
-
-required:
- - compatible
- - reg
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/interrupt-controller/irq.h>
-
- i2c {
- #address-cells = <1>;
- #size-cells = <0>;
-
- light-sensor@10 {
- compatible = "vishay,veml6030";
- reg = <0x10>;
- interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
new file mode 100644
index 000000000000..4ea69f1fdd63
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: GPL-2.0+
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/vishay,veml6030.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: VEML3235, VEML6030, VEML6035 and VEML7700 Ambient Light Sensors (ALS)
+
+maintainers:
+ - Rishi Gupta <gupt21@gmail.com>
+
+description: |
+ Bindings for the ambient light sensors veml6030 and veml6035 from
+ Vishay Semiconductors over an i2c interface.
+
+ Irrespective of whether interrupt is used or not, application
+ can get the ALS and White channel reading from IIO raw interface.
+
+ If the interrupts are used, application will receive an IIO event
+ whenever configured threshold is crossed.
+
+ Specifications about the sensors can be found at:
+ https://www.vishay.com/docs/80131/veml3235.pdf
+ https://www.vishay.com/docs/84366/veml6030.pdf
+ https://www.vishay.com/docs/84889/veml6035.pdf
+ https://www.vishay.com/docs/84286/veml7700.pdf
+
+properties:
+ compatible:
+ enum:
+ - vishay,veml3235
+ - vishay,veml6030
+ - vishay,veml6035
+ - vishay,veml7700
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ description:
+ interrupt mapping for IRQ. Configure with IRQ_TYPE_LEVEL_LOW.
+ Refer to interrupt-controller/interrupts.txt for generic
+ interrupt client node bindings.
+ maxItems: 1
+
+ vdd-supply: true
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml6030
+ then:
+ properties:
+ reg:
+ enum:
+ - 0x10 # ADDR pin pulled down
+ - 0x48 # ADDR pin pulled up
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml6035
+ then:
+ properties:
+ reg:
+ enum:
+ - 0x29
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml3235
+ - vishay,veml7700
+ then:
+ properties:
+ reg:
+ enum:
+ - 0x10
+ interrupts: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ light-sensor@10 {
+ compatible = "vishay,veml6030";
+ reg = <0x10>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <&vdd>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml b/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml
index ecf2339e02f6..d2effccbfb56 100644
--- a/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml
+++ b/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/iio/light/vishay,veml6075.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Vishay VEML6075 UVA/B and VEML6040 RGBW sensors
+title: Vishay VEML6070 UVA, VEML6075 UVA/B and VEML6040 RGBW sensors
maintainers:
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
@@ -16,11 +16,19 @@ properties:
compatible:
enum:
- vishay,veml6040
+ - vishay,veml6070
- vishay,veml6075
reg:
maxItems: 1
+ vishay,rset-ohms:
+ description:
+ Resistor used to select the integration time.
+ default: 270000
+ minimum: 75000
+ maximum: 1200000
+
vdd-supply: true
required:
@@ -28,6 +36,17 @@ required:
- reg
- vdd-supply
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml6040
+ - vishay,veml6075
+ then:
+ properties:
+ vishay,rset-ohms: false
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml b/Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml
new file mode 100644
index 000000000000..52e3781834ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/magnetometer/allegromicro,als31300.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allegro MicroSystems ALS31300 3-D Linear Hall Effect sensor
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+ $nodename:
+ pattern: '^magnetometer@[0-9a-f]+$'
+
+ compatible:
+ enum:
+ - allegromicro,als31300-500 # Factory configured at 500 Gauss input range
+ - allegromicro,als31300-1000 # Factory configured at 1000 Gauss input range
+ - allegromicro,als31300-2000 # Factory configured at 2000 Gauss input range
+
+ reg:
+ maxItems: 1
+
+ vcc-supply:
+ description: 5.5V supply
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ magnetometer@61 {
+ compatible = "allegromicro,als31300-500";
+ reg = <0x61>;
+ vcc-supply = <&hall_vcc>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
index 6fda887ee9d4..cb201cecfa1a 100644
--- a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
+++ b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
@@ -47,15 +47,33 @@ properties:
maxItems: 1
interrupts:
- description:
- interrupt mapping for IRQ (BMP085 only)
maxItems: 1
+ drive-open-drain:
+ description:
+ set if the interrupt pin should be configured as open drain.
+ If not set, defaults to push-pull configuration.
+ type: boolean
+
required:
- compatible
- vddd-supply
- vdda-supply
+allOf:
+ - if:
+ properties:
+ compatible:
+ not:
+ contains:
+ enum:
+ - bosch,bmp085
+ - bosch,bmp380
+ - bosch,bmp580
+ then:
+ properties:
+ interrupts: false
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml b/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml
index d43002b9bfdc..590f50ba3a31 100644
--- a/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml
+++ b/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml
@@ -23,6 +23,9 @@ properties:
vdd-supply:
description: provide VDD power to the sensor.
+ interrupts:
+ maxItems: 1
+
required:
- compatible
- reg
@@ -31,6 +34,7 @@ additionalProperties: false
examples:
- |
+ #include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
@@ -38,5 +42,7 @@ examples:
compatible = "ti,tmp006";
reg = <0x40>;
vdd-supply = <&ldo4_reg>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
};
};
diff --git a/Documentation/devicetree/bindings/input/goodix,gt7986u-spifw.yaml b/Documentation/devicetree/bindings/input/goodix,gt7986u-spifw.yaml
new file mode 100644
index 000000000000..92bd0041feba
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/goodix,gt7986u-spifw.yaml
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/goodix,gt7986u-spifw.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Goodix GT7986U SPI HID Touchscreen
+
+maintainers:
+ - Charles Wang <charles.goodix@gmail.com>
+
+description: |
+ Supports the Goodix GT7986U touchscreen.
+ This touch controller reports data packaged according to the HID protocol
+ over the SPI bus, but it is incompatible with Microsoft's HID-over-SPI protocol.
+
+ NOTE: these bindings are distinct from the bindings used with the
+ GT7986U when the chip is running I2C firmware. This is because there's
+ not a single device that talks over both I2C and SPI but rather
+ distinct touchscreens that happen to be built with the same ASIC but
+ that are distinct products running distinct firmware.
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - goodix,gt7986u-spifw
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ spi-max-frequency: true
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - reset-gpios
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ touchscreen@0 {
+ compatible = "goodix,gt7986u-spifw";
+ reg = <0>;
+ interrupt-parent = <&gpio>;
+ interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ spi-max-frequency = <10000000>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
index 70567d92c746..60f09caa0e4c 100644
--- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
+++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
@@ -19,7 +19,7 @@ description: |
by the PMIC that is defined as a Multi-Function Device (MFD).
For MediaTek MT6323/MT6397 PMIC bindings see
- Documentation/devicetree/bindings/mfd/mt6397.txt
+ Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
properties:
compatible:
@@ -28,6 +28,7 @@ properties:
- mediatek,mt6331-keys
- mediatek,mt6357-keys
- mediatek,mt6358-keys
+ - mediatek,mt6359-keys
- mediatek,mt6397-keys
power-off-time-sec: true
diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.yaml b/Documentation/devicetree/bindings/input/rotary-encoder.yaml
index e315aab7f584..f9332bb2343f 100644
--- a/Documentation/devicetree/bindings/input/rotary-encoder.yaml
+++ b/Documentation/devicetree/bindings/input/rotary-encoder.yaml
@@ -41,7 +41,7 @@ properties:
device, hence no steps need to be passed.
rotary-encoder,rollover:
- $ref: /schemas/types.yaml#/definitions/int32
+ $ref: /schemas/types.yaml#/definitions/flag
description:
Automatic rollover when the rotary value becomes
greater than the specified steps or smaller than 0. For absolute axis only.
diff --git a/Documentation/devicetree/bindings/input/touchscreen/novatek,nvt-ts.yaml b/Documentation/devicetree/bindings/input/touchscreen/novatek,nvt-ts.yaml
new file mode 100644
index 000000000000..bd6a60486d1f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/novatek,nvt-ts.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/novatek,nvt-ts.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Novatek NVT Touchscreen Controller
+
+maintainers:
+ - Hans de Goede <hdegoede@redhat.com>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ enum:
+ - novatek,nt11205-ts
+ - novatek,nt36672a-ts
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ vcc-supply: true
+ iovcc-supply: true
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ touchscreen@1 {
+ compatible = "novatek,nt36672a-ts";
+ reg = <0x01>;
+ interrupts-extended = <&tlmm 31 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vreg_l22a_2p85>;
+ iovcc-supply = <&vreg_l14a_1p8>;
+ pinctrl-0 = <&ts_int_default &ts_reset_default>;
+ pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
+ pinctrl-names = "default", "sleep";
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2246>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.txt b/Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.txt
deleted file mode 100644
index 43ef770dfeb9..000000000000
--- a/Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Zodiac Inflight Innovations RAVE Supervisory Processor Power Button Bindings
-
-RAVE SP input device is a "MFD cell" device corresponding to power
-button functionality of RAVE Supervisory Processor. It is expected
-that its Device Tree node is specified as a child of the node
-corresponding to the parent RAVE SP device (as documented in
-Documentation/devicetree/bindings/mfd/zii,rave-sp.txt)
-
-Required properties:
-
-- compatible: Should be "zii,rave-sp-pwrbutton"
-
-Example:
-
- rave-sp {
- compatible = "zii,rave-sp-rdu1";
- current-speed = <38400>;
-
- pwrbutton {
- compatible = "zii,rave-sp-pwrbutton";
- };
- }
diff --git a/Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.yaml b/Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.yaml
new file mode 100644
index 000000000000..b26e6fe174f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/zii,rave-sp-pwrbutton.yaml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/zii,rave-sp-pwrbutton.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zodiac Inflight Innovations RAVE Supervisory Processor Power Button
+
+maintainers:
+ - Frank Li <Frank.li@nxp.com>
+
+description:
+ RAVE SP input device is a "MFD cell" device corresponding to power
+ button functionality of RAVE Supervisory Processor. It is expected
+ that its Device Tree node is specified as a child of the node
+ corresponding to the parent RAVE SP device (as documented in
+ Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml)
+
+properties:
+ compatible:
+ const: zii,rave-sp-pwrbutton
+
+required:
+ - compatible
+
+allOf:
+ - $ref: input.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ pwrbutton {
+ compatible = "zii,rave-sp-pwrbutton";
+ };
+
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
index 189f5900ee50..251410aabf38 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
@@ -26,6 +26,7 @@ properties:
- items:
- enum:
- qcom,qcm2290-cpu-bwmon
+ - qcom,qcs8300-cpu-bwmon
- qcom,sa8775p-cpu-bwmon
- qcom,sc7180-cpu-bwmon
- qcom,sc7280-cpu-bwmon
@@ -40,6 +41,7 @@ properties:
- const: qcom,sdm845-bwmon # BWMON v4, unified register space
- items:
- enum:
+ - qcom,qcs8300-llcc-bwmon
- qcom,sa8775p-llcc-bwmon
- qcom,sc7180-llcc-bwmon
- qcom,sc8280xp-llcc-bwmon
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml
new file mode 100644
index 000000000000..9d762b2a1fcf
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,qcs615-rpmh.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect on QCS615
+
+maintainers:
+ - Raviteja Laggyshetty <quic_rlaggysh@quicinc.com>
+
+description: |
+ RPMh interconnect providers support system bandwidth requirements through
+ RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is
+ able to communicate with the BCM through the Resource State Coordinator (RSC)
+ associated with each execution environment. Provider nodes must point to at
+ least one RPMh device child node pertaining to their RSC and each provider
+ can map to multiple RPMh resources.
+
+ See also: include/dt-bindings/interconnect/qcom,qcs615-rpmh.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,qcs615-aggre1-noc
+ - qcom,qcs615-camnoc-virt
+ - qcom,qcs615-config-noc
+ - qcom,qcs615-dc-noc
+ - qcom,qcs615-gem-noc
+ - qcom,qcs615-ipa-virt
+ - qcom,qcs615-mc-virt
+ - qcom,qcs615-mmss-noc
+ - qcom,qcs615-system-noc
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+
+allOf:
+ - $ref: qcom,rpmh-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs615-camnoc-virt
+ - qcom,qcs615-ipa-virt
+ - qcom,qcs615-mc-virt
+ then:
+ properties:
+ reg: false
+ else:
+ required:
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ gem_noc: interconnect@9680000 {
+ compatible = "qcom,qcs615-gem-noc";
+ reg = <0x9680000 0x3e200>;
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
+ mc_virt: interconnect-2 {
+ compatible = "qcom,qcs615-mc-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml
new file mode 100644
index 000000000000..e9f528d6d9a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,qcs8300-rpmh.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect on QCS8300
+
+maintainers:
+ - Raviteja Laggyshetty <quic_rlaggysh@quicinc.com>
+
+description: |
+ RPMh interconnect providers support system bandwidth requirements through
+ RPMh hardware accelerators known as Bus Clock Manager (BCM).
+
+ See also: include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,qcs8300-aggre1-noc
+ - qcom,qcs8300-aggre2-noc
+ - qcom,qcs8300-clk-virt
+ - qcom,qcs8300-config-noc
+ - qcom,qcs8300-dc-noc
+ - qcom,qcs8300-gem-noc
+ - qcom,qcs8300-gpdsp-anoc
+ - qcom,qcs8300-lpass-ag-noc
+ - qcom,qcs8300-mc-virt
+ - qcom,qcs8300-mmss-noc
+ - qcom,qcs8300-nspa-noc
+ - qcom,qcs8300-pcie-anoc
+ - qcom,qcs8300-system-noc
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+
+allOf:
+ - $ref: qcom,rpmh-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs8300-clk-virt
+ - qcom,qcs8300-mc-virt
+ then:
+ properties:
+ reg: false
+ else:
+ required:
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ gem_noc: interconnect@9100000 {
+ compatible = "qcom,qcs8300-gem-noc";
+ reg = <0x9100000 0xf7080>;
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
+ clk_virt: interconnect-0 {
+ compatible = "qcom,qcs8300-clk-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml
new file mode 100644
index 000000000000..4647dac740e9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,sar2130p-rpmh.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect on SAR2130P
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+ - Georgi Djakov <djakov@kernel.org>
+
+description: |
+ RPMh interconnect providers support system bandwidth requirements through
+ RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is
+ able to communicate with the BCM through the Resource State Coordinator (RSC)
+ associated with each execution environment. Provider nodes must point to at
+ least one RPMh device child node pertaining to their RSC and each provider
+ can map to multiple RPMh resources.
+
+ See also:: include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sar2130p-clk-virt
+ - qcom,sar2130p-config-noc
+ - qcom,sar2130p-gem-noc
+ - qcom,sar2130p-lpass-ag-noc
+ - qcom,sar2130p-mc-virt
+ - qcom,sar2130p-mmss-noc
+ - qcom,sar2130p-nsp-noc
+ - qcom,sar2130p-pcie-anoc
+ - qcom,sar2130p-system-noc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ maxItems: 2
+
+required:
+ - compatible
+
+allOf:
+ - $ref: qcom,rpmh-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-clk-virt
+ - qcom,sar2130p-mc-virt
+ then:
+ properties:
+ reg: false
+ else:
+ required:
+ - reg
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-pcie-anoc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: aggre-NOC PCIe AXI clock
+ - description: cfg-NOC PCIe a-NOC AHB clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-system-noc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: aggre USB3 PRIM AXI clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-system-noc
+ - qcom,sar2130p-pcie-anoc
+ then:
+ required:
+ - clocks
+ else:
+ properties:
+ clocks: false
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ clk_virt: interconnect-0 {
+ compatible = "qcom,sar2130p-clk-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
+ aggre1_noc: interconnect@1680000 {
+ compatible = "qcom,sar2130p-system-noc";
+ reg = <0x01680000 0x29080>;
+ #interconnect-cells = <2>;
+ clocks = <&gcc_prim_axi_clk>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
index 5f051c666cbe..f3247a47f9ee 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
@@ -132,10 +132,9 @@ properties:
Address property. Base address of an alias of the GICD region containing
only the {SET,CLR}SPI registers to be used if isolation is required,
and if supported by the HW.
- $ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- minItems: 1
- maxItems: 2
+ oneOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32
+ - $ref: /schemas/types.yaml#/definitions/uint64
ppi-partitions:
type: object
@@ -223,9 +222,8 @@ patternProperties:
(u32, u32) tuple describing the untranslated
address and size of the pre-ITS window.
$ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- minItems: 2
- maxItems: 2
+ minItems: 2
+ maxItems: 2
required:
- compatible
diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml
new file mode 100644
index 000000000000..55636d06a674
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/aspeed,ast2700-intc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Aspeed AST2700 Interrupt Controller
+
+description:
+ This interrupt controller hardware is second level interrupt controller that
+ is hooked to a parent interrupt controller. It's useful to combine multiple
+ interrupt sources into 1 interrupt to parent interrupt controller.
+
+maintainers:
+ - Kevin Chen <kevin_chen@aspeedtech.com>
+
+properties:
+ compatible:
+ enum:
+ - aspeed,ast2700-intc-ic
+
+ reg:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+ description:
+ The first cell is the IRQ number, the second cell is the trigger
+ type as defined in interrupt.txt in this directory.
+
+ interrupts:
+ maxItems: 6
+ description: |
+ Depend to which INTC0 or INTC1 used.
+ INTC0 and INTC1 are two kinds of interrupt controller with enable and raw
+ status registers for use.
+ INTC0 is used to assert GIC if interrupt in INTC1 asserted.
+ INTC1 is used to assert INTC0 if interrupt of modules asserted.
+ +-----+ +-------+ +---------+---module0
+ | GIC |---| INTC0 |--+--| INTC1_0 |---module2
+ | | | | | | |---...
+ +-----+ +-------+ | +---------+---module31
+ |
+ | +---------+---module0
+ +---| INTC1_1 |---module2
+ | | |---...
+ | +---------+---module31
+ ...
+ | +---------+---module0
+ +---| INTC1_5 |---module2
+ | |---...
+ +---------+---module31
+
+
+required:
+ - compatible
+ - reg
+ - interrupt-controller
+ - '#interrupt-cells'
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ interrupt-controller@12101b00 {
+ compatible = "aspeed,ast2700-intc-ic";
+ reg = <0 0x12101b00 0 0x10>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.yaml
index d4658fe3867c..d671ed884c9e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.yaml
@@ -23,6 +23,7 @@ properties:
- atmel,sama5d3-aic
- atmel,sama5d4-aic
- microchip,sam9x60-aic
+ - microchip,sam9x7-aic
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,mu-msi.yaml b/Documentation/devicetree/bindings/interrupt-controller/fsl,mu-msi.yaml
index 799ae5c3e32a..b5282c857f44 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,mu-msi.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,mu-msi.yaml
@@ -62,8 +62,6 @@ properties:
- const: processor-a-side
- const: processor-b-side
- interrupt-controller: true
-
msi-controller: true
"#msi-cells":
@@ -73,7 +71,6 @@ required:
- compatible
- reg
- interrupts
- - interrupt-controller
- msi-controller
- "#msi-cells"
@@ -88,7 +85,6 @@ examples:
compatible = "fsl,imx6sx-mu-msi";
msi-controller;
#msi-cells = <0>;
- interrupt-controller;
reg = <0x5d270000 0x10000>, /* A side */
<0x5d300000 0x10000>; /* B side */
reg-names = "processor-a-side", "processor-b-side";
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
index b1ea08a41bb0..a54da66a89e7 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
@@ -29,6 +29,7 @@ properties:
- qcom,qdu1000-pdc
- qcom,sa8255p-pdc
- qcom,sa8775p-pdc
+ - qcom,sar2130p-pdc
- qcom,sc7180-pdc
- qcom,sc7280-pdc
- qcom,sc8180x-pdc
diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzv2h-icu.yaml b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzv2h-icu.yaml
new file mode 100644
index 000000000000..d7ef4f1323a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzv2h-icu.yaml
@@ -0,0 +1,278 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/renesas,rzv2h-icu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/V2H(P) Interrupt Control Unit
+
+maintainers:
+ - Fabrizio Castro <fabrizio.castro.jz@renesas.com>
+ - Geert Uytterhoeven <geert+renesas@glider.be>
+
+allOf:
+ - $ref: /schemas/interrupt-controller.yaml#
+
+description:
+ The Interrupt Control Unit (ICU) handles external interrupts (NMI, IRQ, and
+ TINT), error interrupts, DMAC requests, GPT interrupts, and internal
+ interrupts.
+
+properties:
+ compatible:
+ const: renesas,r9a09g057-icu # RZ/V2H(P)
+
+ '#interrupt-cells':
+ description: The first cell is the SPI number of the NMI or the
+ PORT_IRQ[0-15] interrupt, as per user manual. The second cell is used to
+ specify the flag.
+ const: 2
+
+ '#address-cells':
+ const: 0
+
+ interrupt-controller: true
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ minItems: 58
+ items:
+ - description: NMI interrupt
+ - description: PORT_IRQ0 interrupt
+ - description: PORT_IRQ1 interrupt
+ - description: PORT_IRQ2 interrupt
+ - description: PORT_IRQ3 interrupt
+ - description: PORT_IRQ4 interrupt
+ - description: PORT_IRQ5 interrupt
+ - description: PORT_IRQ6 interrupt
+ - description: PORT_IRQ7 interrupt
+ - description: PORT_IRQ8 interrupt
+ - description: PORT_IRQ9 interrupt
+ - description: PORT_IRQ10 interrupt
+ - description: PORT_IRQ11 interrupt
+ - description: PORT_IRQ12 interrupt
+ - description: PORT_IRQ13 interrupt
+ - description: PORT_IRQ14 interrupt
+ - description: PORT_IRQ15 interrupt
+ - description: GPIO interrupt, TINT0
+ - description: GPIO interrupt, TINT1
+ - description: GPIO interrupt, TINT2
+ - description: GPIO interrupt, TINT3
+ - description: GPIO interrupt, TINT4
+ - description: GPIO interrupt, TINT5
+ - description: GPIO interrupt, TINT6
+ - description: GPIO interrupt, TINT7
+ - description: GPIO interrupt, TINT8
+ - description: GPIO interrupt, TINT9
+ - description: GPIO interrupt, TINT10
+ - description: GPIO interrupt, TINT11
+ - description: GPIO interrupt, TINT12
+ - description: GPIO interrupt, TINT13
+ - description: GPIO interrupt, TINT14
+ - description: GPIO interrupt, TINT15
+ - description: GPIO interrupt, TINT16
+ - description: GPIO interrupt, TINT17
+ - description: GPIO interrupt, TINT18
+ - description: GPIO interrupt, TINT19
+ - description: GPIO interrupt, TINT20
+ - description: GPIO interrupt, TINT21
+ - description: GPIO interrupt, TINT22
+ - description: GPIO interrupt, TINT23
+ - description: GPIO interrupt, TINT24
+ - description: GPIO interrupt, TINT25
+ - description: GPIO interrupt, TINT26
+ - description: GPIO interrupt, TINT27
+ - description: GPIO interrupt, TINT28
+ - description: GPIO interrupt, TINT29
+ - description: GPIO interrupt, TINT30
+ - description: GPIO interrupt, TINT31
+ - description: Software interrupt, INTA55_0
+ - description: Software interrupt, INTA55_1
+ - description: Software interrupt, INTA55_2
+ - description: Software interrupt, INTA55_3
+ - description: Error interrupt to CA55
+ - description: GTCCRA compare match/input capture (U0)
+ - description: GTCCRB compare match/input capture (U0)
+ - description: GTCCRA compare match/input capture (U1)
+ - description: GTCCRB compare match/input capture (U1)
+
+ interrupt-names:
+ minItems: 58
+ items:
+ - const: nmi
+ - const: port_irq0
+ - const: port_irq1
+ - const: port_irq2
+ - const: port_irq3
+ - const: port_irq4
+ - const: port_irq5
+ - const: port_irq6
+ - const: port_irq7
+ - const: port_irq8
+ - const: port_irq9
+ - const: port_irq10
+ - const: port_irq11
+ - const: port_irq12
+ - const: port_irq13
+ - const: port_irq14
+ - const: port_irq15
+ - const: tint0
+ - const: tint1
+ - const: tint2
+ - const: tint3
+ - const: tint4
+ - const: tint5
+ - const: tint6
+ - const: tint7
+ - const: tint8
+ - const: tint9
+ - const: tint10
+ - const: tint11
+ - const: tint12
+ - const: tint13
+ - const: tint14
+ - const: tint15
+ - const: tint16
+ - const: tint17
+ - const: tint18
+ - const: tint19
+ - const: tint20
+ - const: tint21
+ - const: tint22
+ - const: tint23
+ - const: tint24
+ - const: tint25
+ - const: tint26
+ - const: tint27
+ - const: tint28
+ - const: tint29
+ - const: tint30
+ - const: tint31
+ - const: int-ca55-0
+ - const: int-ca55-1
+ - const: int-ca55-2
+ - const: int-ca55-3
+ - const: icu-error-ca55
+ - const: gpt-u0-gtciada
+ - const: gpt-u0-gtciadb
+ - const: gpt-u1-gtciada
+ - const: gpt-u1-gtciadb
+
+ clocks:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - '#interrupt-cells'
+ - '#address-cells'
+ - interrupt-controller
+ - interrupts
+ - interrupt-names
+ - clocks
+ - power-domains
+ - resets
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+ icu: interrupt-controller@10400000 {
+ compatible = "renesas,r9a09g057-icu";
+ reg = <0x10400000 0x10000>;
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ interrupt-controller;
+ 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>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 262 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 263 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 264 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 265 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "nmi",
+ "port_irq0", "port_irq1", "port_irq2",
+ "port_irq3", "port_irq4", "port_irq5",
+ "port_irq6", "port_irq7", "port_irq8",
+ "port_irq9", "port_irq10", "port_irq11",
+ "port_irq12", "port_irq13", "port_irq14",
+ "port_irq15",
+ "tint0", "tint1", "tint2", "tint3",
+ "tint4", "tint5", "tint6", "tint7",
+ "tint8", "tint9", "tint10", "tint11",
+ "tint12", "tint13", "tint14", "tint15",
+ "tint16", "tint17", "tint18", "tint19",
+ "tint20", "tint21", "tint22", "tint23",
+ "tint24", "tint25", "tint26", "tint27",
+ "tint28", "tint29", "tint30", "tint31",
+ "int-ca55-0", "int-ca55-1",
+ "int-ca55-2", "int-ca55-3",
+ "icu-error-ca55",
+ "gpt-u0-gtciada", "gpt-u0-gtciadb",
+ "gpt-u1-gtciada", "gpt-u1-gtciadb";
+ clocks = <&cpg CPG_MOD 0x5>;
+ power-domains = <&cpg>;
+ resets = <&cpg 0x36>;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml
new file mode 100644
index 000000000000..8d330906bbbd
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/thead,c900-aclint-sswi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: T-HEAD C900 ACLINT Supervisor-level Software Interrupt Device
+
+maintainers:
+ - Inochi Amaoto <inochiama@outlook.com>
+
+description:
+ The SSWI device is a part of the THEAD ACLINT device. It provides
+ supervisor-level IPI functionality for a set of HARTs on a THEAD
+ platform. It provides a register to set an IPI (SETSSIP) for each
+ HART connected to the SSWI device.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - sophgo,sg2044-aclint-sswi
+ - const: thead,c900-aclint-sswi
+
+ reg:
+ maxItems: 1
+
+ "#interrupt-cells":
+ const: 0
+
+ interrupt-controller: true
+
+ interrupts-extended:
+ minItems: 1
+ maxItems: 4095
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - "#interrupt-cells"
+ - interrupt-controller
+ - interrupts-extended
+
+examples:
+ - |
+ interrupt-controller@94000000 {
+ compatible = "sophgo,sg2044-aclint-sswi", "thead,c900-aclint-sswi";
+ reg = <0x94000000 0x00004000>;
+ #interrupt-cells = <0>;
+ interrupt-controller;
+ interrupts-extended = <&cpu1intc 1>,
+ <&cpu2intc 1>,
+ <&cpu3intc 1>,
+ <&cpu4intc 1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.yaml b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.yaml
index 6a49d74b992a..5449266f258a 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,sci-inta.yaml
@@ -109,6 +109,7 @@ examples:
compatible = "ti,sci-inta";
reg = <0x0 0x33d00000 0x0 0x100000>;
interrupt-controller;
+ #interrupt-cells = <0>;
msi-controller;
interrupt-parent = <&main_navss_intr>;
ti,sci = <&dmsc>;
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index 92d350b8e01a..c1e11bc6b7a0 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -36,10 +36,12 @@ properties:
items:
- enum:
- qcom,qcm2290-smmu-500
+ - qcom,qcs615-smmu-500
- qcom,qcs8300-smmu-500
- qcom,qdu1000-smmu-500
- qcom,sa8255p-smmu-500
- qcom,sa8775p-smmu-500
+ - qcom,sar2130p-smmu-500
- qcom,sc7180-smmu-500
- qcom,sc7280-smmu-500
- qcom,sc8180x-smmu-500
@@ -88,6 +90,7 @@ properties:
- qcom,qcm2290-smmu-500
- qcom,sa8255p-smmu-500
- qcom,sa8775p-smmu-500
+ - qcom,sar2130p-smmu-500
- qcom,sc7280-smmu-500
- qcom,sc8180x-smmu-500
- qcom,sc8280xp-smmu-500
@@ -524,6 +527,7 @@ allOf:
compatible:
items:
- enum:
+ - qcom,sar2130p-smmu-500
- qcom,sm8550-smmu-500
- qcom,sm8650-smmu-500
- qcom,x1e80100-smmu-500
@@ -555,6 +559,7 @@ allOf:
- cavium,smmu-v2
- marvell,ap806-smmu-500
- nvidia,smmu-500
+ - qcom,qcs615-smmu-500
- qcom,qcs8300-smmu-500
- qcom,qdu1000-smmu-500
- qcom,sa8255p-smmu-500
diff --git a/Documentation/devicetree/bindings/iommu/riscv,iommu.yaml b/Documentation/devicetree/bindings/iommu/riscv,iommu.yaml
new file mode 100644
index 000000000000..5d015eeb06d0
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/riscv,iommu.yaml
@@ -0,0 +1,147 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iommu/riscv,iommu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RISC-V IOMMU Architecture Implementation
+
+maintainers:
+ - Tomasz Jeznach <tjeznach@rivosinc.com>
+
+description: |
+ The RISC-V IOMMU provides memory address translation and isolation for
+ input and output devices, supporting per-device translation context,
+ shared process address spaces including the ATS and PRI components of
+ the PCIe specification, two stage address translation and MSI remapping.
+ It supports identical translation table format to the RISC-V address
+ translation tables with page level access and protection attributes.
+ Hardware uses in-memory command and fault reporting queues with wired
+ interrupt or MSI notifications.
+
+ Visit https://github.com/riscv-non-isa/riscv-iommu for more details.
+
+ For information on assigning RISC-V IOMMU to its peripheral devices,
+ see generic IOMMU bindings.
+
+properties:
+ # For PCIe IOMMU hardware compatible property should contain the vendor
+ # and device ID according to the PCI Bus Binding specification.
+ # Since PCI provides built-in identification methods, compatible is not
+ # actually required. For non-PCIe hardware implementations 'riscv,iommu'
+ # should be specified along with 'reg' property providing MMIO location.
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - qemu,riscv-iommu
+ - const: riscv,iommu
+ - items:
+ - enum:
+ - pci1efd,edf1
+ - const: riscv,pci-iommu
+
+ reg:
+ maxItems: 1
+ description:
+ For non-PCI devices this represents base address and size of for the
+ IOMMU memory mapped registers interface.
+ For PCI IOMMU hardware implementation this should represent an address
+ of the IOMMU, as defined in the PCI Bus Binding reference.
+
+ '#iommu-cells':
+ const: 1
+ description:
+ The single cell describes the requester id emitted by a master to the
+ IOMMU.
+
+ interrupts:
+ minItems: 1
+ maxItems: 4
+ description:
+ Wired interrupt vectors available for RISC-V IOMMU to notify the
+ RISC-V HARTS. The cause to interrupt vector is software defined
+ using IVEC IOMMU register.
+
+ msi-parent: true
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - '#iommu-cells'
+
+additionalProperties: false
+
+examples:
+ - |+
+ /* Example 1 (IOMMU device with wired interrupts) */
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ iommu1: iommu@1bccd000 {
+ compatible = "qemu,riscv-iommu", "riscv,iommu";
+ reg = <0x1bccd000 0x1000>;
+ interrupt-parent = <&aplic_smode>;
+ interrupts = <32 IRQ_TYPE_LEVEL_HIGH>,
+ <33 IRQ_TYPE_LEVEL_HIGH>,
+ <34 IRQ_TYPE_LEVEL_HIGH>,
+ <35 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ };
+
+ /* Device with two IOMMU device IDs, 0 and 7 */
+ master1 {
+ iommus = <&iommu1 0>, <&iommu1 7>;
+ };
+
+ - |+
+ /* Example 2 (IOMMU device with shared wired interrupt) */
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ iommu2: iommu@1bccd000 {
+ compatible = "qemu,riscv-iommu", "riscv,iommu";
+ reg = <0x1bccd000 0x1000>;
+ interrupt-parent = <&aplic_smode>;
+ interrupts = <32 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ };
+
+ - |+
+ /* Example 3 (IOMMU device with MSIs) */
+ iommu3: iommu@1bcdd000 {
+ compatible = "qemu,riscv-iommu", "riscv,iommu";
+ reg = <0x1bccd000 0x1000>;
+ msi-parent = <&imsics_smode>;
+ #iommu-cells = <1>;
+ };
+
+ - |+
+ /* Example 4 (IOMMU PCIe device with MSIs) */
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie@30000000 {
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ reg = <0x0 0x30000000 0x0 0x1000000>;
+ ranges = <0x02000000 0x0 0x41000000 0x0 0x41000000 0x0 0x0f000000>;
+
+ /*
+ * The IOMMU manages all functions in this PCI domain except
+ * itself. Omit BDF 00:01.0.
+ */
+ iommu-map = <0x0 &iommu0 0x0 0x8>,
+ <0x9 &iommu0 0x9 0xfff7>;
+
+ /* The IOMMU programming interface uses slot 00:01.0 */
+ iommu0: iommu@1,0 {
+ compatible = "pci1efd,edf1", "riscv,pci-iommu";
+ reg = <0x800 0 0 0 0>;
+ #iommu-cells = <1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt b/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt
deleted file mode 100644
index ff5c92138650..000000000000
--- a/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Zodiac Inflight Innovations RAVE Supervisory Processor Backlight Bindings
-
-RAVE SP backlight device is a "MFD cell" device corresponding to
-backlight functionality of RAVE Supervisory Processor. It is expected
-that its Device Tree node is specified as a child of the node
-corresponding to the parent RAVE SP device (as documented in
-Documentation/devicetree/bindings/mfd/zii,rave-sp.txt)
-
-Required properties:
-
-- compatible: Should be "zii,rave-sp-backlight"
-
-Example:
-
- rave-sp {
- compatible = "zii,rave-sp-rdu1";
- current-speed = <38400>;
-
- backlight {
- compatible = "zii,rave-sp-backlight";
- };
- }
-
diff --git a/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.yaml
new file mode 100644
index 000000000000..ee93a3e64852
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.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/backlight/zii,rave-sp-backlight.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zodiac Inflight Innovations RAVE Supervisory Processor Backlight
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+
+description:
+ RAVE SP backlight device is a "MFD cell" device corresponding to
+ backlight functionality of RAVE Supervisory Processor. It is expected
+ that its Device Tree node is specified as a child of the node
+ corresponding to the parent RAVE SP device (as documented in
+ Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml)
+
+properties:
+ compatible:
+ const: zii,rave-sp-backlight
+
+required:
+ - compatible
+
+allOf:
+ - $ref: common.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ backlight {
+ compatible = "zii,rave-sp-backlight";
+ };
+
diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml
index bf9a101e4d42..3e8319e44339 100644
--- a/Documentation/devicetree/bindings/leds/common.yaml
+++ b/Documentation/devicetree/bindings/leds/common.yaml
@@ -118,6 +118,8 @@ properties:
# No trigger assigned to the LED. This is the default mode
# if trigger is absent
- none
+ # LED indicates remote control feedback
+ - rc-feedback
# LED indicates camera torch state
- torch
# LED indicates USB gadget activity
@@ -202,6 +204,12 @@ properties:
#trigger-source-cells property in the source node.
$ref: /schemas/types.yaml#/definitions/phandle-array
+ active-high:
+ type: boolean
+ description:
+ Makes LED active high. To turn the LED ON, line needs to be
+ set to high voltage instead of low.
+
active-low:
type: boolean
description:
@@ -225,6 +233,14 @@ properties:
Maximum timeout in microseconds after which the flash LED is turned off.
Required for flash LED nodes with configurable timeout.
+allOf:
+ - if:
+ required:
+ - active-low
+ then:
+ properties:
+ active-high: false
+
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml b/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml
index bb20394fca5c..62326507c1aa 100644
--- a/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-bcm63138.yaml
@@ -41,6 +41,16 @@ properties:
"#size-cells":
const: 0
+ brcm,serial-shift-bits:
+ minimum: 1
+ maximum: 32
+ description:
+ This describes the number of 8-bit serial shifters connected to the LED
+ controller block. The hardware is typically using 8-bit shift registers
+ with 8 LEDs per shift register, so 4 shifters results in 32 LEDs or 2
+ shifters give 16 LEDs etc, but the hardware supports any odd number of
+ registers. If left unspecified, the hardware boot-time default is used.
+
patternProperties:
"^led@[a-f0-9]+$":
type: object
@@ -71,6 +81,7 @@ examples:
leds@ff800800 {
compatible = "brcm,bcm4908-leds", "brcm,bcm63138-leds";
reg = <0xff800800 0xdc>;
+ brcm,serial-shift-bits = <16>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/leds/leds-mt6323.txt b/Documentation/devicetree/bindings/leds/leds-mt6323.txt
deleted file mode 100644
index 052dccb8f2ce..000000000000
--- a/Documentation/devicetree/bindings/leds/leds-mt6323.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-Device Tree Bindings for LED support on MT6323 PMIC
-
-MT6323 LED controller is subfunction provided by MT6323 PMIC, so the LED
-controllers are defined as the subnode of the function node provided by MT6323
-PMIC controller that is being defined as one kind of Muti-Function Device (MFD)
-using shared bus called PMIC wrapper for each subfunction to access remote
-MT6323 PMIC hardware.
-
-For MT6323 MFD bindings see:
-Documentation/devicetree/bindings/mfd/mt6397.txt
-For MediaTek PMIC wrapper bindings see:
-Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml
-
-Required properties:
-- compatible : Must be one of
- - "mediatek,mt6323-led"
- - "mediatek,mt6331-led"
- - "mediatek,mt6332-led"
-- address-cells : Must be 1
-- size-cells : Must be 0
-
-Each led is represented as a child node of the mediatek,mt6323-led that
-describes the initial behavior for each LED physically and currently only four
-LED child nodes can be supported.
-
-Required properties for the LED child node:
-- reg : LED channel number (0..3)
-
-Optional properties for the LED child node:
-- label : See Documentation/devicetree/bindings/leds/common.txt
-- linux,default-trigger : See Documentation/devicetree/bindings/leds/common.txt
-- default-state: See Documentation/devicetree/bindings/leds/common.txt
-
-Example:
-
- mt6323: pmic {
- compatible = "mediatek,mt6323";
-
- ...
-
- mt6323led: leds {
- compatible = "mediatek,mt6323-led";
- #address-cells = <1>;
- #size-cells = <0>;
-
- led@0 {
- reg = <0>;
- label = "LED0";
- linux,default-trigger = "timer";
- default-state = "on";
- };
- led@1 {
- reg = <1>;
- label = "LED1";
- default-state = "off";
- };
- led@2 {
- reg = <2>;
- label = "LED2";
- default-state = "on";
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/leds/leds-pca955x.txt b/Documentation/devicetree/bindings/leds/leds-pca955x.txt
deleted file mode 100644
index 817f460f3a72..000000000000
--- a/Documentation/devicetree/bindings/leds/leds-pca955x.txt
+++ /dev/null
@@ -1,89 +0,0 @@
-* NXP - pca955x LED driver
-
-The PCA955x family of chips are I2C LED blinkers whose pins not used
-to control LEDs can be used as general purpose I/Os. The GPIO pins can
-be input or output, and output pins can also be pulse-width controlled.
-
-Required properties:
-- compatible : should be one of :
- "nxp,pca9550"
- "nxp,pca9551"
- "nxp,pca9552"
- "ibm,pca9552"
- "nxp,pca9553"
-- #address-cells: must be 1
-- #size-cells: must be 0
-- reg: I2C slave address. depends on the model.
-
-Optional properties:
-- gpio-controller: allows pins to be used as GPIOs.
-- #gpio-cells: must be 2.
-- gpio-line-names: define the names of the GPIO lines
-
-LED sub-node properties:
-- reg : number of LED line.
- from 0 to 1 for the pca9550
- from 0 to 7 for the pca9551
- from 0 to 15 for the pca9552
- from 0 to 3 for the pca9553
-- type: (optional) either
- PCA955X_TYPE_NONE
- PCA955X_TYPE_LED
- PCA955X_TYPE_GPIO
- see dt-bindings/leds/leds-pca955x.h (default to LED)
-- label : (optional)
- see Documentation/devicetree/bindings/leds/common.txt
-- linux,default-trigger : (optional)
- see Documentation/devicetree/bindings/leds/common.txt
-
-Examples:
-
-pca9552: pca9552@60 {
- compatible = "nxp,pca9552";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x60>;
-
- gpio-controller;
- #gpio-cells = <2>;
- gpio-line-names = "GPIO12", "GPIO13", "GPIO14", "GPIO15";
-
- 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>;
- };
-
- led@0 {
- label = "red:power";
- linux,default-trigger = "default-on";
- reg = <0>;
- type = <PCA955X_TYPE_LED>;
- };
- led@1 {
- label = "green:power";
- reg = <1>;
- type = <PCA955X_TYPE_LED>;
- };
- led@2 {
- label = "pca9552:yellow";
- reg = <2>;
- type = <PCA955X_TYPE_LED>;
- };
- led@3 {
- label = "pca9552:white";
- reg = <3>;
- type = <PCA955X_TYPE_LED>;
- };
-};
diff --git a/Documentation/devicetree/bindings/leds/leds-pwm.yaml b/Documentation/devicetree/bindings/leds/leds-pwm.yaml
index 113b7c218303..61b97e8bc36d 100644
--- a/Documentation/devicetree/bindings/leds/leds-pwm.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-pwm.yaml
@@ -34,6 +34,12 @@ patternProperties:
Maximum brightness possible for the LED
$ref: /schemas/types.yaml#/definitions/uint32
+ default-brightness:
+ description:
+ Brightness to be set if LED's default state is on. Used only during
+ initialization. If the option is not set then max brightness is used.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
required:
- pwms
- max-brightness
diff --git a/Documentation/devicetree/bindings/leds/nxp,pca955x.yaml b/Documentation/devicetree/bindings/leds/nxp,pca955x.yaml
new file mode 100644
index 000000000000..ae7384cc760c
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/nxp,pca955x.yaml
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/nxp,pca955x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCA955X LED controllers
+
+maintainers:
+ - Nate Case <ncase@xes-inc.com>
+
+description: |
+ The PCA955x family of chips are I2C LED blinkers whose pins not used
+ to control LEDs can be used as general purpose I/Os. The GPIO pins can
+ be input or output, and output pins can also be pulse-width controlled.
+
+ For more product information please see the link below:
+ - https://www.nxp.com/docs/en/data-sheet/PCA9552.pdf
+
+properties:
+ compatible:
+ enum:
+ - nxp,pca9550
+ - nxp,pca9551
+ - nxp,pca9552
+ - ibm,pca9552
+ - nxp,pca9553
+
+ reg:
+ maxItems: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ gpio-controller: true
+
+ gpio-line-names:
+ minItems: 1
+ maxItems: 16
+
+ "#gpio-cells":
+ const: 2
+
+patternProperties:
+ "^led@[0-9a-f]$":
+ type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ maxItems: 1
+ type:
+ description: |
+ Output configuration, see include/dt-bindings/leds/leds-pca955x.h
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+ minimum: 0
+ maximum: 2
+
+ required:
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nxp,pca9550
+ then:
+ patternProperties:
+ "^led@[0-9a-f]$":
+ properties:
+ reg:
+ maximum: 1
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nxp,pca9551
+ then:
+ patternProperties:
+ "^led@[0-9a-f]$":
+ properties:
+ reg:
+ maximum: 7
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nxp,pca9552
+ - ibm,pca9552
+ then:
+ patternProperties:
+ "^led@[0-9a-f]$":
+ properties:
+ reg:
+ maximum: 15
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nxp,pca9553
+ then:
+ patternProperties:
+ "^led@[0-9a-f]$":
+ properties:
+ reg:
+ maximum: 3
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/leds/leds-pca955x.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led-controller@60 {
+ compatible = "nxp,pca9552";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ label = "red:power";
+ linux,default-trigger = "default-on";
+ type = <PCA955X_TYPE_LED>;
+ };
+ led@1 {
+ reg = <1>;
+ label = "green:power";
+ type = <PCA955X_TYPE_LED>;
+ };
+ led@2 {
+ reg = <2>;
+ label = "pca9552:yellow";
+ type = <PCA955X_TYPE_LED>;
+ };
+ led@3 {
+ reg = <3>;
+ label = "pca9552:white";
+ type = <PCA955X_TYPE_LED>;
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml b/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml
index 5853410c7a45..97535d6dc47a 100644
--- a/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml
+++ b/Documentation/devicetree/bindings/leds/sprd,sc2731-bltc.yaml
@@ -50,35 +50,4 @@ required:
- '#size-cells'
additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/leds/common.h>
-
- pmic {
- #address-cells = <1>;
- #size-cells = <0>;
-
- led-controller@200 {
- compatible = "sprd,sc2731-bltc";
- reg = <0x200>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- led@0 {
- reg = <0x0>;
- color = <LED_COLOR_ID_RED>;
- };
-
- led@1 {
- reg = <0x1>;
- color = <LED_COLOR_ID_GREEN>;
- };
-
- led@2 {
- reg = <0x2>;
- color = <LED_COLOR_ID_BLUE>;
- };
- };
- };
...
diff --git a/Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
index a4f1fe63659a..02f06314d85f 100644
--- a/Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
+++ b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
@@ -197,7 +197,7 @@ examples:
reg = <0 0x596e8000 0 0x88000>;
clocks = <&adma_lpcg 0>, <&adma_lpcg 1>, <&adma_lpcg 2>;
clock-names = "ipg", "ocram", "core";
- power-domains = <&pd 0>, <&pd 1>, <&pd 2>, <&pd 3>;
+ power-domains = <&pd 0>, <&pd 1>;
mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
mboxes = <&mhu_tx 2 0>, //data-transfer protocol with 5 windows, mhu-tx
<&mhu_tx 3 0>, //data-transfer protocol with 7 windows, mhu-tx
diff --git a/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
index 404477910f02..1332aab9a888 100644
--- a/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
+++ b/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
@@ -16,6 +16,8 @@ properties:
reg:
oneOf:
- items:
+ - description: mailbox data registers
+ - items:
- description: mailbox control & data registers
- description: mailbox interrupt registers
deprecated: true
@@ -23,6 +25,7 @@ properties:
- description: mailbox control registers
- description: mailbox interrupt registers
- description: mailbox data registers
+ deprecated: true
interrupts:
maxItems: 1
@@ -41,12 +44,12 @@ additionalProperties: false
examples:
- |
soc {
- #address-cells = <2>;
- #size-cells = <2>;
- mbox: mailbox@37020000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mailbox@37020800 {
compatible = "microchip,mpfs-mailbox";
- reg = <0x0 0x37020000 0x0 0x58>, <0x0 0x2000318C 0x0 0x40>,
- <0x0 0x37020800 0x0 0x100>;
+ reg = <0x37020800 0x100>;
interrupt-parent = <&L1>;
interrupts = <96>;
#mbox-cells = <1>;
diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
index 982c741e6225..9d2dfd85b207 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
@@ -165,12 +165,13 @@ allOf:
- if:
properties:
compatible:
- enum:
- - qcom,msm8953-apcs-kpss-global
- - qcom,msm8994-apcs-kpss-global
- - qcom,msm8996-apcs-hmss-global
- - qcom,qcm2290-apcs-hmss-global
- - qcom,sdm845-apss-shared
+ contains:
+ enum:
+ - qcom,msm8953-apcs-kpss-global
+ - qcom,msm8994-apcs-kpss-global
+ - qcom,msm8996-apcs-hmss-global
+ - qcom,qcm2290-apcs-hmss-global
+ - qcom,sdm845-apss-shared
then:
properties:
clocks: false
diff --git a/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml b/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
index 2d66770ed361..f69c0ec5d19d 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom-ipcc.yaml
@@ -28,6 +28,7 @@ properties:
- qcom,qdu1000-ipcc
- qcom,sa8255p-ipcc
- qcom,sa8775p-ipcc
+ - qcom,sar2130p-ipcc
- qcom,sc7280-ipcc
- qcom,sc8280xp-ipcc
- qcom,sdx75-ipcc
@@ -38,6 +39,7 @@ properties:
- qcom,sm8450-ipcc
- qcom,sm8550-ipcc
- qcom,sm8650-ipcc
+ - qcom,sm8750-ipcc
- qcom,x1e80100-ipcc
- const: qcom,ipcc
diff --git a/Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml b/Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml
new file mode 100644
index 000000000000..0971fb97896e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/thead,th1520-mbox.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: T-head TH1520 Mailbox Controller
+
+description:
+ The T-head mailbox controller enables communication and coordination between
+ cores within the SoC by passing messages (e.g., data, status, and control)
+ through mailbox channels. It also allows one core to signal another processor
+ using interrupts via the Interrupt Controller Unit (ICU).
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+properties:
+ compatible:
+ const: thead,th1520-mbox
+
+ clocks:
+ items:
+ - description: Clock for the local mailbox
+ - description: Clock for remote ICU 0
+ - description: Clock for remote ICU 1
+ - description: Clock for remote ICU 2
+
+ clock-names:
+ items:
+ - const: clk-local
+ - const: clk-remote-icu0
+ - const: clk-remote-icu1
+ - const: clk-remote-icu2
+
+ reg:
+ items:
+ - description: Mailbox local base address
+ - description: Remote ICU 0 base address
+ - description: Remote ICU 1 base address
+ - description: Remote ICU 2 base address
+
+ reg-names:
+ items:
+ - const: local
+ - const: remote-icu0
+ - const: remote-icu1
+ - const: remote-icu2
+
+ interrupts:
+ maxItems: 1
+
+ '#mbox-cells':
+ const: 1
+ description:
+ The one and only cell describes destination CPU ID.
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - reg
+ - reg-names
+ - interrupts
+ - '#mbox-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/thead,th1520-clk-ap.h>
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ mailbox@ffffc38000 {
+ compatible = "thead,th1520-mbox";
+ reg = <0xff 0xffc38000 0x0 0x4000>,
+ <0xff 0xffc44000 0x0 0x1000>,
+ <0xff 0xffc4c000 0x0 0x1000>,
+ <0xff 0xffc54000 0x0 0x1000>;
+ reg-names = "local", "remote-icu0", "remote-icu1", "remote-icu2";
+ clocks = <&clk CLK_MBOX0>, <&clk CLK_MBOX1>, <&clk CLK_MBOX2>,
+ <&clk CLK_MBOX3>;
+ clock-names = "clk-local", "clk-remote-icu0", "clk-remote-icu1",
+ "clk-remote-icu2";
+ interrupts = <28>;
+ #mbox-cells = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7180.yaml b/Documentation/devicetree/bindings/media/i2c/adv7180.yaml
index c8d887eee3bb..4371a0ef2761 100644
--- a/Documentation/devicetree/bindings/media/i2c/adv7180.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/adv7180.yaml
@@ -39,6 +39,12 @@ properties:
maxItems: 1
adv,force-bt656-4:
+ deprecated: true
+ description:
+ Indicates that the output is a BT.656-4 compatible stream.
+ type: boolean
+
+ adi,force-bt656-4:
description:
Indicates that the output is a BT.656-4 compatible stream.
type: boolean
diff --git a/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml b/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
index 60f19e1152b3..1a57f2aa1982 100644
--- a/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/hynix,hi846.yaml
@@ -28,12 +28,6 @@ properties:
items:
- description: Reference to the mclk clock.
- assigned-clocks:
- maxItems: 1
-
- assigned-clock-rates:
- maxItems: 1
-
reset-gpios:
description: Reference to the GPIO connected to the RESETB pin. Active low.
maxItems: 1
@@ -82,8 +76,6 @@ required:
- compatible
- reg
- clocks
- - assigned-clocks
- - assigned-clock-rates
- vddio-supply
- vdda-supply
- vddd-supply
@@ -105,8 +97,6 @@ examples:
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_csi1>;
clocks = <&clk 0>;
- assigned-clocks = <&clk 0>;
- assigned-clock-rates = <25000000>;
vdda-supply = <&reg_camera_vdda>;
vddd-supply = <&reg_camera_vddd>;
vddio-supply = <&reg_camera_vddio>;
diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
index 6c72e77b927c..26f85151afbd 100644
--- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
@@ -25,7 +25,10 @@ description: |
properties:
compatible:
- const: maxim,max96712
+ items:
+ - enum:
+ - maxim,max96712
+ - maxim,max96724
reg:
description: I2C device address
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml
new file mode 100644
index 000000000000..552efdf8934f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml
@@ -0,0 +1,120 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (c) 2024 Linaro Ltd.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,ov08x40.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Omnivision OV08X40 CMOS Sensor
+
+maintainers:
+ - Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+
+description: |
+ The Omnivision OV08X40 is a 9.2 megapixel, CMOS image sensor which supports:
+ - Automatic black level calibration (ABLC)
+ - Programmable controls for frame rate, mirror and flip, binning, cropping
+ and windowing
+ - Output formats 10-bit 4C RGB RAW, 10-bit Bayer RAW
+ - 4-lane MIPI D-PHY TX @ 1 Gbps per lane
+ - 2-lane MPIP D-PHY TX @ 2 Gbps per lane
+ - Dynamic defect pixel cancellation
+ - Standard SCCB command interface
+
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
+properties:
+ compatible:
+ const: ovti,ov08x40
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ avdd-supply:
+ description: Analogue circuit voltage supply.
+
+ dovdd-supply:
+ description: I/O circuit voltage supply.
+
+ dvdd-supply:
+ description: Digital circuit voltage supply.
+
+ reset-gpios:
+ description: Active low GPIO connected to XSHUTDOWN pad of the sensor.
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ additionalProperties: false
+
+ properties:
+ data-lanes:
+ oneOf:
+ - items:
+ - const: 1
+ - const: 2
+ - items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+ link-frequencies: true
+ remote-endpoint: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+ - remote-endpoint
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ov08x40: camera@36 {
+ compatible = "ovti,ov08x40";
+ reg = <0x36>;
+
+ reset-gpios = <&tlmm 111 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam_rgb_defaultt>;
+
+ clocks = <&ov08x40_clk>;
+
+ assigned-clocks = <&ov08x40_clk>;
+ assigned-clock-parents = <&ov08x40_clk_parent>;
+ assigned-clock-rates = <19200000>;
+
+ avdd-supply = <&vreg_l7b_2p8>;
+ dvdd-supply = <&vreg_l7b_1p8>;
+ dovdd-supply = <&vreg_l3m_1p8>;
+
+ port {
+ ov08x40_ep: endpoint {
+ remote-endpoint = <&csiphy4_ep>;
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <400000000>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov5648.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov5648.yaml
index 1f497679168c..8028c8b107c4 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov5648.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov5648.yaml
@@ -20,12 +20,6 @@ properties:
items:
- description: XVCLK Clock
- assigned-clocks:
- maxItems: 1
-
- assigned-clock-rates:
- maxItems: 1
-
dvdd-supply:
description: Digital Domain Power Supply
@@ -68,8 +62,6 @@ required:
- compatible
- reg
- clocks
- - assigned-clocks
- - assigned-clock-rates
- dvdd-supply
- dovdd-supply
- port
@@ -93,9 +85,6 @@ examples:
avdd-supply = <&ov5648_avdd>;
dovdd-supply = <&ov5648_dovdd>;
clocks = <&ov5648_xvclk 0>;
- assigned-clocks = <&ov5648_xvclk 0>;
- assigned-clock-rates = <24000000>;
-
ov5648_out: port {
ov5648_out_mipi_csi2: endpoint {
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov8865.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov8865.yaml
index 8a70e23ba6ab..320b9aacbb8b 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov8865.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov8865.yaml
@@ -20,12 +20,6 @@ properties:
items:
- description: EXTCLK Clock
- assigned-clocks:
- maxItems: 1
-
- assigned-clock-rates:
- maxItems: 1
-
dvdd-supply:
description: Digital Domain Power Supply
@@ -68,8 +62,6 @@ required:
- compatible
- reg
- clocks
- - assigned-clocks
- - assigned-clock-rates
- dvdd-supply
- avdd-supply
- dovdd-supply
@@ -94,8 +86,6 @@ examples:
pinctrl-0 = <&csi_mclk_pin>;
clocks = <&ccu CLK_CSI_MCLK>;
- assigned-clocks = <&ccu CLK_CSI_MCLK>;
- assigned-clock-rates = <24000000>;
avdd-supply = <&reg_ov8865_avdd>;
dovdd-supply = <&reg_ov8865_dovdd>;
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
index 79a7658f6d05..401c8613f840 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
@@ -27,10 +27,6 @@ properties:
description: I2C address
maxItems: 1
- assigned-clocks: true
- assigned-clock-parents: true
- assigned-clock-rates: true
-
clocks:
description: Clock frequency from 6 to 27MHz
maxItems: 1
@@ -87,10 +83,6 @@ examples:
reg = <0x60>;
clocks = <&ov9282_clk>;
- assigned-clocks = <&ov9282_clk>;
- assigned-clock-parents = <&ov9282_clk_parent>;
- assigned-clock-rates = <24000000>;
-
port {
ov9282: endpoint {
remote-endpoint = <&cam>;
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
index c978abc0cdb3..975c1d77c8e5 100644
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
@@ -24,10 +24,6 @@ properties:
- sony,imx258
- sony,imx258-pdaf
- assigned-clocks: true
- assigned-clock-parents: true
- assigned-clock-rates: true
-
clocks:
description:
Clock frequency from 6 to 27 MHz.
@@ -125,9 +121,6 @@ examples:
reg = <0x6c>;
clocks = <&imx258_clk>;
- assigned-clocks = <&imx258_clk>;
- assigned-clock-rates = <19200000>;
-
port {
endpoint {
remote-endpoint = <&csi1_ep>;
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
index bce57b22f7b6..3842e5130463 100644
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
@@ -24,10 +24,6 @@ properties:
description: I2C address
maxItems: 1
- assigned-clocks: true
- assigned-clock-parents: true
- assigned-clock-rates: true
-
clocks:
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
maxItems: 1
@@ -74,10 +70,6 @@ examples:
reg = <0x1a>;
clocks = <&imx334_clk>;
- assigned-clocks = <&imx334_clk>;
- assigned-clock-parents = <&imx334_clk_parent>;
- assigned-clock-rates = <24000000>;
-
port {
imx334: endpoint {
remote-endpoint = <&cam>;
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
index 77bf3a4ee89d..80f879b6bd01 100644
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
@@ -24,10 +24,6 @@ properties:
description: I2C address
maxItems: 1
- assigned-clocks: true
- assigned-clock-parents: true
- assigned-clock-rates: true
-
clocks:
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
maxItems: 1
@@ -86,10 +82,6 @@ examples:
reg = <0x1a>;
clocks = <&imx335_clk>;
- assigned-clocks = <&imx335_clk>;
- assigned-clock-parents = <&imx335_clk_parent>;
- assigned-clock-rates = <24000000>;
-
avdd-supply = <&camera_vdda_2v9>;
ovdd-supply = <&camera_vddo_1v8>;
dvdd-supply = <&camera_vddd_1v2>;
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
index d9b7815650fd..5447ab0768a6 100644
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
@@ -26,10 +26,6 @@ properties:
description: I2C address
maxItems: 1
- assigned-clocks: true
- assigned-clock-parents: true
- assigned-clock-rates: true
-
clocks:
description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
maxItems: 1
@@ -86,10 +82,6 @@ examples:
reg = <0x1a>;
clocks = <&imx412_clk>;
- assigned-clocks = <&imx412_clk>;
- assigned-clock-parents = <&imx412_clk_parent>;
- assigned-clock-rates = <24000000>;
-
port {
imx412: endpoint {
remote-endpoint = <&cam>;
diff --git a/Documentation/devicetree/bindings/media/i2c/thine,thp7312.yaml b/Documentation/devicetree/bindings/media/i2c/thine,thp7312.yaml
index 535acf2b88a9..bc339a7374b2 100644
--- a/Documentation/devicetree/bindings/media/i2c/thine,thp7312.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/thine,thp7312.yaml
@@ -135,8 +135,7 @@ properties:
data-lanes:
$ref: /schemas/media/video-interfaces.yaml#/properties/data-lanes
- items:
- maxItems: 4
+ maxItems: 4
description:
This property is for lane reordering between the THP7312 and the imaging
sensor that it is connected to.
diff --git a/Documentation/devicetree/bindings/media/qcom,msm8953-camss.yaml b/Documentation/devicetree/bindings/media/qcom,msm8953-camss.yaml
new file mode 100644
index 000000000000..8856fba385b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/qcom,msm8953-camss.yaml
@@ -0,0 +1,322 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/qcom,msm8953-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8953 Camera Subsystem (CAMSS)
+
+maintainers:
+ - Barnabas Czeman <barnabas.czeman@mainlining.org>
+
+description:
+ The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms
+
+properties:
+ compatible:
+ const: qcom,msm8953-camss
+
+ clocks:
+ minItems: 30
+ maxItems: 30
+
+ clock-names:
+ items:
+ - const: ahb
+ - const: csi0
+ - const: csi0_ahb
+ - const: csi0_phy
+ - const: csi0_pix
+ - const: csi0_rdi
+ - const: csi1
+ - const: csi1_ahb
+ - const: csi1_phy
+ - const: csi1_pix
+ - const: csi1_rdi
+ - const: csi2
+ - const: csi2_ahb
+ - const: csi2_phy
+ - const: csi2_pix
+ - const: csi2_rdi
+ - const: csi_vfe0
+ - const: csi_vfe1
+ - const: csiphy0_timer
+ - const: csiphy1_timer
+ - const: csiphy2_timer
+ - const: ispif_ahb
+ - const: micro_ahb
+ - const: top_ahb
+ - const: vfe0
+ - const: vfe0_ahb
+ - const: vfe0_axi
+ - const: vfe1
+ - const: vfe1_ahb
+ - const: vfe1_axi
+
+ interrupts:
+ minItems: 9
+ maxItems: 9
+
+ interrupt-names:
+ items:
+ - const: csid0
+ - const: csid1
+ - const: csid2
+ - const: csiphy0
+ - const: csiphy1
+ - const: csiphy2
+ - const: ispif
+ - const: vfe0
+ - const: vfe1
+
+ iommus:
+ maxItems: 1
+
+ power-domains:
+ items:
+ - description: VFE0 GDSC - Video Front End, Global Distributed Switch Controller.
+ - description: VFE1 GDSC - Video Front End, Global Distributed Switch Controller.
+
+ power-domain-names:
+ items:
+ - const: vfe0
+ - const: vfe1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ description:
+ CSI input ports.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port for receiving CSI data.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description:
+ An array of physical data lanes indexes.
+ Position of an entry determines the logical
+ lane number, while the value of an entry
+ indicates physical lane index. Lane swapping
+ is supported. Physical lane indexes;
+ 0, 2, 3, 4.
+ minItems: 1
+ maxItems: 4
+
+ required:
+ - data-lanes
+
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port for receiving CSI data.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 4
+
+ required:
+ - data-lanes
+
+ port@2:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port for receiving CSI data.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 4
+
+ required:
+ - data-lanes
+
+ reg:
+ minItems: 13
+ maxItems: 13
+
+ reg-names:
+ items:
+ - const: csi_clk_mux
+ - const: csid0
+ - const: csid1
+ - const: csid2
+ - const: csiphy0
+ - const: csiphy0_clk_mux
+ - const: csiphy1
+ - const: csiphy1_clk_mux
+ - const: csiphy2
+ - const: csiphy2_clk_mux
+ - const: ispif
+ - const: vfe0
+ - const: vfe1
+
+ vdda-supply:
+ description:
+ Definition of the regulator used as analog power supply.
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+ - interrupts
+ - interrupt-names
+ - iommus
+ - power-domains
+ - power-domain-names
+ - vdda-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/qcom,gcc-msm8953.h>
+
+ camss: camss@1b00020 {
+ compatible = "qcom,msm8953-camss";
+
+ reg = <0x1b00020 0x10>,
+ <0x1b30000 0x100>,
+ <0x1b30400 0x100>,
+ <0x1b30800 0x100>,
+ <0x1b34000 0x1000>,
+ <0x1b00030 0x4>,
+ <0x1b35000 0x1000>,
+ <0x1b00038 0x4>,
+ <0x1b36000 0x1000>,
+ <0x1b00040 0x4>,
+ <0x1b31000 0x500>,
+ <0x1b10000 0x1000>,
+ <0x1b14000 0x1000>;
+ reg-names = "csi_clk_mux",
+ "csid0",
+ "csid1",
+ "csid2",
+ "csiphy0",
+ "csiphy0_clk_mux",
+ "csiphy1",
+ "csiphy1_clk_mux",
+ "csiphy2",
+ "csiphy2_clk_mux",
+ "ispif",
+ "vfe0",
+ "vfe1";
+
+ clocks = <&gcc GCC_CAMSS_AHB_CLK>,
+ <&gcc GCC_CAMSS_CSI0_CLK>,
+ <&gcc GCC_CAMSS_CSI0_AHB_CLK>,
+ <&gcc GCC_CAMSS_CSI0PHY_CLK>,
+ <&gcc GCC_CAMSS_CSI0PIX_CLK>,
+ <&gcc GCC_CAMSS_CSI0RDI_CLK>,
+ <&gcc GCC_CAMSS_CSI1_CLK>,
+ <&gcc GCC_CAMSS_CSI1_AHB_CLK>,
+ <&gcc GCC_CAMSS_CSI1PHY_CLK>,
+ <&gcc GCC_CAMSS_CSI1PIX_CLK>,
+ <&gcc GCC_CAMSS_CSI1RDI_CLK>,
+ <&gcc GCC_CAMSS_CSI2_CLK>,
+ <&gcc GCC_CAMSS_CSI2_AHB_CLK>,
+ <&gcc GCC_CAMSS_CSI2PHY_CLK>,
+ <&gcc GCC_CAMSS_CSI2PIX_CLK>,
+ <&gcc GCC_CAMSS_CSI2RDI_CLK>,
+ <&gcc GCC_CAMSS_CSI_VFE0_CLK>,
+ <&gcc GCC_CAMSS_CSI_VFE1_CLK>,
+ <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>,
+ <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>,
+ <&gcc GCC_CAMSS_CSI2PHYTIMER_CLK>,
+ <&gcc GCC_CAMSS_ISPIF_AHB_CLK>,
+ <&gcc GCC_CAMSS_MICRO_AHB_CLK>,
+ <&gcc GCC_CAMSS_TOP_AHB_CLK>,
+ <&gcc GCC_CAMSS_VFE0_CLK>,
+ <&gcc GCC_CAMSS_VFE0_AHB_CLK>,
+ <&gcc GCC_CAMSS_VFE0_AXI_CLK>,
+ <&gcc GCC_CAMSS_VFE1_CLK>,
+ <&gcc GCC_CAMSS_VFE1_AHB_CLK>,
+ <&gcc GCC_CAMSS_VFE1_AXI_CLK>;
+ clock-names = "ahb",
+ "csi0",
+ "csi0_ahb",
+ "csi0_phy",
+ "csi0_pix",
+ "csi0_rdi",
+ "csi1",
+ "csi1_ahb",
+ "csi1_phy",
+ "csi1_pix",
+ "csi1_rdi",
+ "csi2",
+ "csi2_ahb",
+ "csi2_phy",
+ "csi2_pix",
+ "csi2_rdi",
+ "csi_vfe0",
+ "csi_vfe1",
+ "csiphy0_timer",
+ "csiphy1_timer",
+ "csiphy2_timer",
+ "ispif_ahb",
+ "micro_ahb",
+ "top_ahb",
+ "vfe0",
+ "vfe0_ahb",
+ "vfe0_axi",
+ "vfe1",
+ "vfe1_ahb",
+ "vfe1_axi";
+
+ interrupts = <GIC_SPI 51 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 52 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 153 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 315 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 55 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 29 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "csid0",
+ "csid1",
+ "csid2",
+ "csiphy0",
+ "csiphy1",
+ "csiphy2",
+ "ispif",
+ "vfe0",
+ "vfe1";
+
+ iommus = <&apps_iommu 0x14>;
+
+ power-domains = <&gcc VFE0_GDSC>,
+ <&gcc VFE1_GDSC>;
+ power-domain-names = "vfe0", "vfe1";
+
+ vdda-supply = <&reg_2v8>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml b/Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml
new file mode 100644
index 000000000000..eba5394719b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/raspberrypi,rp1-cfe.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Raspberry Pi PiSP Camera Front End
+
+maintainers:
+ - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ - Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
+
+description: |
+ The Raspberry Pi PiSP Camera Front End is a module in Raspberrypi 5's RP1 I/O
+ controller, that contains:
+ - MIPI D-PHY
+ - MIPI CSI-2 receiver
+ - Simple image processor (called PiSP Front End, or FE)
+
+ The FE documentation is available at:
+ https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
+
+ The PHY and CSI-2 receiver part have no public documentation.
+
+properties:
+ compatible:
+ items:
+ - const: raspberrypi,rp1-cfe
+
+ reg:
+ items:
+ - description: CSI-2 registers
+ - description: D-PHY registers
+ - description: MIPI CFG (a simple top-level mux) registers
+ - description: FE registers
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+ description: CSI-2 RX Port
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 4
+
+ required:
+ - data-lanes
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ rp1 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ csi@110000 {
+ compatible = "raspberrypi,rp1-cfe";
+ reg = <0xc0 0x40110000 0x0 0x100>,
+ <0xc0 0x40114000 0x0 0x100>,
+ <0xc0 0x40120000 0x0 0x100>,
+ <0xc0 0x40124000 0x0 0x1000>;
+
+ interrupts = <42>;
+
+ clocks = <&rp1_clocks>;
+
+ port {
+ csi_ep: endpoint {
+ remote-endpoint = <&cam_endpoint>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/renesas,csi2.yaml b/Documentation/devicetree/bindings/media/renesas,csi2.yaml
index 977ab188d654..80b77875874d 100644
--- a/Documentation/devicetree/bindings/media/renesas,csi2.yaml
+++ b/Documentation/devicetree/bindings/media/renesas,csi2.yaml
@@ -32,6 +32,7 @@ properties:
- renesas,r8a77990-csi2 # R-Car E3
- renesas,r8a779a0-csi2 # R-Car V3U
- renesas,r8a779g0-csi2 # R-Car V4H
+ - renesas,r8a779h0-csi2 # R-Car V4M
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/media/renesas,isp.yaml b/Documentation/devicetree/bindings/media/renesas,isp.yaml
index 33650a1ea034..c4de4555b753 100644
--- a/Documentation/devicetree/bindings/media/renesas,isp.yaml
+++ b/Documentation/devicetree/bindings/media/renesas,isp.yaml
@@ -22,6 +22,8 @@ properties:
- enum:
- renesas,r8a779a0-isp # V3U
- renesas,r8a779g0-isp # V4H
+ - renesas,r8a779h0-isp # V4M
+ - const: renesas,rcar-gen4-isp # Generic R-Car Gen4
reg:
maxItems: 1
@@ -116,7 +118,7 @@ examples:
#include <dt-bindings/power/r8a779a0-sysc.h>
isp1: isp@fed20000 {
- compatible = "renesas,r8a779a0-isp";
+ compatible = "renesas,r8a779a0-isp", "renesas,rcar-gen4-isp";
reg = <0xfed20000 0x10000>;
interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 613>;
diff --git a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
index f762fdc05e4d..b9f033f2f3ce 100644
--- a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
+++ b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
@@ -13,7 +13,7 @@ description: |
CSI_RX_IF section.
maintainers:
- - Jai Luthra <j-luthra@ti.com>
+ - Jai Luthra <jai.luthra@linux.dev>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
index 10a2d97e5f8b..a5598ade399f 100644
--- a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.yaml
@@ -66,9 +66,8 @@ patternProperties:
samsung,srom-timing:
$ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- minItems: 6
- maxItems: 6
+ minItems: 6
+ maxItems: 6
description: |
Array of 6 integers, specifying bank timings in the following order:
Tacp, Tcah, Tcoh, Tacc, Tcos, Tacs.
diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ddr.yaml b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ddr.yaml
index 84f778a99546..e0786153eec7 100644
--- a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ddr.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ddr.yaml
@@ -40,6 +40,7 @@ properties:
- fsl,p1021-memory-controller
- fsl,p2020-memory-controller
- fsl,qoriq-memory-controller
+ - nxp,imx9-memory-controller
interrupts:
maxItems: 1
@@ -51,13 +52,41 @@ properties:
type: boolean
reg:
- maxItems: 1
+ items:
+ - description: Controller register space
+ - description: Inject register space
+ minItems: 1
+
+ reg-names:
+ items:
+ - const: ctrl
+ - const: inject
+ minItems: 1
required:
- compatible
- interrupts
- reg
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nxp,imx9-memory-controller
+ then:
+ properties:
+ reg:
+ minItems: 2
+ reg-names:
+ minItems: 2
+ else:
+ properties:
+ reg:
+ maxItems: 1
+ reg-names: false
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml
index d1c3421bee10..f7cf0f91c1c0 100644
--- a/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/fsl/fsl,ifc.yaml
@@ -58,17 +58,39 @@ properties:
access window as configured.
patternProperties:
- "^.*@[a-f0-9]+(,[a-f0-9]+)+$":
+ "^nand@[a-f0-9]+(,[a-f0-9]+)+$":
type: object
- description: |
- Child device nodes describe the devices connected to IFC such as NOR (e.g.
- cfi-flash) and NAND (fsl,ifc-nand). There might be board specific devices
- like FPGAs, CPLDs, etc.
+ properties:
+ compatible:
+ const: fsl,ifc-nand
+
+ reg:
+ maxItems: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ patternProperties:
+ "^partition@[0-9a-f]+":
+ $ref: /schemas/mtd/partitions/partition.yaml#
+ deprecated: true
required:
- compatible
- reg
+ additionalProperties: false
+
+ "(flash|fpga|board-control|cpld)@[a-f0-9]+(,[a-f0-9]+)+$":
+ type: object
+ oneOf:
+ - $ref: /schemas/board/fsl,fpga-qixis.yaml#
+ - $ref: /schemas/mtd/mtd-physmap.yaml#
+ unevaluatedProperties: false
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml
new file mode 100644
index 000000000000..4a81ed82ef34
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/airoha,en7581-gpio-sysctl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha EN7581 GPIO System Controller
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+ - Lorenzo Bianconi <lorenzo@kernel.org>
+
+description:
+ Airoha EN7581 SoC GPIO system controller which provided a register map
+ for controlling the GPIO, pins and PWM of the SoC.
+
+properties:
+ compatible:
+ items:
+ - const: airoha,en7581-gpio-sysctl
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ pinctrl:
+ type: object
+ $ref: /schemas/pinctrl/airoha,en7581-pinctrl.yaml
+ description:
+ Child node definition for EN7581 Pin controller
+
+ pwm:
+ type: object
+ $ref: /schemas/pwm/airoha,en7581-pwm.yaml
+ description:
+ Child node definition for EN7581 PWM controller
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ system-controller@1fbf0200 {
+ compatible = "airoha,en7581-gpio-sysctl", "syscon", "simple-mfd";
+ reg = <0x1fbf0200 0xc0>;
+
+ pinctrl {
+ compatible = "airoha,en7581-pinctrl";
+
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ mmc-pins {
+ mux {
+ function = "emmc";
+ groups = "emmc";
+ };
+ };
+
+ mdio-pins {
+ mux {
+ function = "mdio";
+ groups = "mdio";
+ };
+
+ conf {
+ pins = "gpio2";
+ output-enable;
+ };
+ };
+ };
+
+ pwm {
+ compatible = "airoha,en7581-pwm";
+
+ #pwm-cells = <3>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
index 86ee69c0f45b..c800d5e53b65 100644
--- a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
+++ b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
@@ -9,6 +9,8 @@ title: Aspeed System Control Unit
description:
The Aspeed System Control Unit manages the global behaviour of the SoC,
configuring elements such as clocks, pinmux, and reset.
+ In AST2700 SOC which has two soc connection, each soc have its own scu
+ register control, ast2700-scu0 for soc0, ast2700-scu1 for soc1.
maintainers:
- Joel Stanley <joel@jms.id.au>
@@ -21,6 +23,8 @@ properties:
- aspeed,ast2400-scu
- aspeed,ast2500-scu
- aspeed,ast2600-scu
+ - aspeed,ast2700-scu0
+ - aspeed,ast2700-scu1
- const: syscon
- const: simple-mfd
@@ -30,7 +34,8 @@ properties:
ranges: true
'#address-cells':
- const: 1
+ minimum: 1
+ maximum: 2
'#size-cells':
const: 1
@@ -76,6 +81,7 @@ patternProperties:
- aspeed,ast2400-silicon-id
- aspeed,ast2500-silicon-id
- aspeed,ast2600-silicon-id
+ - aspeed,ast2700-silicon-id
- const: aspeed,silicon-id
reg:
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
new file mode 100644
index 000000000000..86451f151a6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
@@ -0,0 +1,598 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/mediatek,mt6397.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6397/MT6323 PMIC
+
+maintainers:
+ - Sen Chu <sen.chu@mediatek.com>
+ - Macpaul Lin <macpaul.lin@mediatek.com>
+
+description: |
+ MT6397/MT6323 is a power management system chip.
+ Please see the sub-modules below for supported features.
+
+ MT6397/MT6323 is a multifunction device with the following sub modules:
+ - Regulators
+ - RTC
+ - ADC
+ - Audio codec
+ - GPIO
+ - Clock
+ - LED
+ - Keys
+ - Power controller
+
+ It is interfaced to host controller using SPI interface by a proprietary hardware
+ called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap.
+ See the following for pwrap node definitions:
+ Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - mediatek,mt6323
+ - mediatek,mt6331 # "mediatek,mt6331" for PMIC MT6331 and MT6332.
+ - mediatek,mt6358
+ - mediatek,mt6359
+ - mediatek,mt6397
+ - items:
+ - enum:
+ - mediatek,mt6366
+ - const: mediatek,mt6358
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ rtc:
+ type: object
+ $ref: /schemas/rtc/rtc.yaml#
+ unevaluatedProperties: false
+ description:
+ MT6397 Real Time Clock.
+
+ properties:
+ compatible:
+ oneOf:
+ - enum:
+ - mediatek,mt6323-rtc
+ - mediatek,mt6331-rtc
+ - mediatek,mt6358-rtc
+ - mediatek,mt6397-rtc
+ - items:
+ - enum:
+ - mediatek,mt6366-rtc
+ - const: mediatek,mt6358-rtc
+
+ start-year: true
+
+ required:
+ - compatible
+
+ regulators:
+ type: object
+ description:
+ List of child nodes that specify the regulators.
+ additionalProperties: true
+
+ properties:
+ compatible:
+ oneOf:
+ - enum:
+ - mediatek,mt6323-regulator
+ - mediatek,mt6358-regulator
+ - mediatek,mt6359-regulator
+ - mediatek,mt6397-regulator
+ - items:
+ - enum:
+ - mediatek,mt6366-regulator
+ - const: mediatek,mt6358-regulator
+
+ required:
+ - compatible
+
+ adc:
+ type: object
+ $ref: /schemas/iio/adc/mediatek,mt6359-auxadc.yaml#
+ unevaluatedProperties: false
+
+ audio-codec:
+ type: object
+ description:
+ Audio codec support with MT6358 and MT6397.
+ additionalProperties: true
+
+ properties:
+ compatible:
+ oneOf:
+ - enum:
+ - mediatek,mt6358-sound
+ - mediatek,mt6359-codec
+ - mediatek,mt6397-codec
+ - items:
+ - enum:
+ - mediatek,mt6366-sound
+ - const: mediatek,mt6358-sound
+
+ required:
+ - compatible
+
+ clocks:
+ type: object
+ additionalProperties: false
+ description:
+ This is a clock buffer node for mt6397. However, there are no sub nodes
+ or any public document exposed in public.
+
+ properties:
+ compatible:
+ const: mediatek,mt6397-clk
+
+ '#clock-cells':
+ const: 1
+
+ required:
+ - compatible
+
+ leds:
+ type: object
+ additionalProperties: false
+ description: |
+ MT6323 LED controller is subfunction provided by MT6323 PMIC, so the LED
+ controllers are defined as the subnode of the function node provided by MT6323
+ PMIC controller that is being defined as one kind of Muti-Function Device (MFD)
+ using shared bus called PMIC wrapper for each subfunction to access remote
+ MT6323 PMIC hardware.
+
+ Each led is represented as a child node of the mediatek,mt6323-led that
+ describes the initial behavior for each LED physically and currently only four
+ LED child nodes can be supported.
+
+ properties:
+ compatible:
+ enum:
+ - mediatek,mt6323-led
+ - mediatek,mt6331-led
+ - mediatek,mt6332-led
+
+ reg:
+ maxItems: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ patternProperties:
+ "^led@[0-3]$":
+ type: object
+ $ref: /schemas/leds/common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description:
+ LED channel number (0..3)
+ minimum: 0
+ maximum: 3
+
+ required:
+ - reg
+
+ required:
+ - compatible
+ - "#address-cells"
+ - "#size-cells"
+
+ keys:
+ type: object
+ $ref: /schemas/input/mediatek,pmic-keys.yaml
+ unevaluatedProperties: false
+ description:
+ Power and Home keys.
+
+ power-controller:
+ type: object
+ additionalProperties: false
+ description:
+ The power controller which could be found on PMIC is responsible for
+ externally powering off or on the remote MediaTek SoC through the
+ circuit BBPU (baseband power up).
+
+ properties:
+ compatible:
+ const: mediatek,mt6323-pwrc
+
+ '#power-domain-cells':
+ const: 0
+
+ pinctrl:
+ type: object
+ $ref: /schemas/pinctrl/mediatek,mt65xx-pinctrl.yaml
+ unevaluatedProperties: false
+ description:
+ Pin controller
+
+required:
+ - compatible
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/leds/common.h>
+
+ pmic {
+ compatible = "mediatek,mt6323";
+ interrupt-parent = <&pio>;
+ interrupts = <150 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ leds {
+ compatible = "mediatek,mt6323-led";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ regulators {
+ compatible = "mediatek,mt6323-regulator";
+
+ buck_vproc {
+ regulator-name = "vproc";
+ regulator-min-microvolt = < 700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck_vsys {
+ regulator-name = "vsys";
+ regulator-min-microvolt = <1400000>;
+ regulator-max-microvolt = <2987500>;
+ regulator-ramp-delay = <25000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck_vpa {
+ regulator-name = "vpa";
+ regulator-min-microvolt = < 500000>;
+ regulator-max-microvolt = <3650000>;
+ };
+
+ ldo_vtcxo {
+ regulator-name = "vtcxo";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <90>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo_vcn28 {
+ regulator-name = "vcn28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <185>;
+ };
+
+ ldo_vcn33_bt {
+ regulator-name = "vcn33_bt";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-enable-ramp-delay = <185>;
+ };
+
+ ldo_vcn33_wifi {
+ regulator-name = "vcn33_wifi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-enable-ramp-delay = <185>;
+ };
+
+ ldo_va {
+ regulator-name = "va";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <216>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo_vcama {
+ regulator-name = "vcama";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vio28 {
+ regulator-name = "vio28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <216>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo_vusb {
+ regulator-name = "vusb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <216>;
+ regulator-boot-on;
+ };
+
+ ldo_vmc {
+ regulator-name = "vmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <36>;
+ regulator-boot-on;
+ };
+
+ ldo_vmch {
+ regulator-name = "vmch";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <36>;
+ regulator-boot-on;
+ };
+
+ ldo_vemc3v3 {
+ regulator-name = "vemc3v3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <36>;
+ regulator-boot-on;
+ };
+
+ ldo_vgp1 {
+ regulator-name = "vgp1";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vgp2 {
+ regulator-name = "vgp2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vgp3 {
+ regulator-name = "vgp3";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vcn18 {
+ regulator-name = "vcn18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vsim1 {
+ regulator-name = "vsim1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vsim2 {
+ regulator-name = "vsim2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vrtc {
+ regulator-name = "vrtc";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo_vcamaf {
+ regulator-name = "vcamaf";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vibr {
+ regulator-name = "vibr";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <36>;
+ };
+
+ ldo_vrf18 {
+ regulator-name = "vrf18";
+ regulator-min-microvolt = <1825000>;
+ regulator-max-microvolt = <1825000>;
+ regulator-enable-ramp-delay = <187>;
+ };
+
+ ldo_vm {
+ regulator-name = "vm";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <216>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo_vio18 {
+ regulator-name = "vio18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <216>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo_vcamd {
+ regulator-name = "vcamd";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+
+ ldo_vcamio {
+ regulator-name = "vcamio";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <216>;
+ };
+ };
+
+ keys {
+ compatible = "mediatek,mt6323-keys";
+ mediatek,long-press-mode = <1>;
+ power-off-time-sec = <0>;
+
+ power {
+ linux,keycodes = <116>;
+ wakeup-source;
+ };
+
+ home {
+ linux,keycodes = <114>;
+ };
+ };
+
+ power-controller {
+ compatible = "mediatek,mt6323-pwrc";
+ #power-domain-cells = <0>;
+ };
+
+ rtc {
+ compatible = "mediatek,mt6323-rtc";
+ };
+ };
+
+ - |
+ #include <dt-bindings/input/input.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pmic {
+ compatible = "mediatek,mt6358";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ audio-codec {
+ compatible = "mediatek,mt6358-sound";
+ Avdd-supply = <&mt6358_vaud28_reg>;
+ mediatek,dmic-mode = <0>;
+ };
+
+ regulators {
+ compatible = "mediatek,mt6358-regulator";
+
+ buck_vdram1 {
+ regulator-name = "vdram1";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2087500>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <0>;
+ regulator-always-on;
+ regulator-allowed-modes = <0 1>;
+ };
+
+ // ...
+
+ ldo_vsim2 {
+ regulator-name = "vsim2";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <540>;
+ };
+ };
+
+ rtc {
+ compatible = "mediatek,mt6358-rtc";
+ };
+
+ keys {
+ compatible = "mediatek,mt6358-keys";
+
+ power {
+ linux,keycodes = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ home {
+ linux,keycodes = <KEY_HOME>;
+ };
+ };
+ };
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pmic {
+ compatible = "mediatek,mt6397";
+
+ interrupt-parent = <&pio>;
+ interrupts-extended = <&pio 222 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ audio-codec {
+ compatible = "mediatek,mt6397-codec";
+ };
+
+ clocks {
+ compatible = "mediatek,mt6397-clk";
+ #clock-cells = <1>;
+ };
+
+ pinctrl {
+ compatible = "mediatek,mt6397-pinctrl";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ regulators {
+ compatible = "mediatek,mt6397-regulator";
+
+ buck_vpca15 {
+ regulator-name = "vpca15";
+ regulator-min-microvolt = < 850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <200>;
+ };
+
+ // ...
+
+ ldo_vibr {
+ regulator-name = "vibr";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <218>;
+ };
+ };
+
+ rtc {
+ compatible = "mediatek,mt6397-rtc";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
deleted file mode 100644
index 10540aa7afa1..000000000000
--- a/Documentation/devicetree/bindings/mfd/mt6397.txt
+++ /dev/null
@@ -1,110 +0,0 @@
-MediaTek MT6397/MT6323 Multifunction Device Driver
-
-MT6397/MT6323 is a multifunction device with the following sub modules:
-- Regulator
-- RTC
-- Audio codec
-- GPIO
-- Clock
-- LED
-- Keys
-- Power controller
-
-It is interfaced to host controller using SPI interface by a proprietary hardware
-called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap.
-See the following for pwarp node definitions:
-../soc/mediatek/mediatek,pwrap.yaml
-
-This document describes the binding for MFD device and its sub module.
-
-Required properties:
-compatible:
- "mediatek,mt6323" for PMIC MT6323
- "mediatek,mt6331" for PMIC MT6331 and MT6332
- "mediatek,mt6357" for PMIC MT6357
- "mediatek,mt6358" for PMIC MT6358
- "mediatek,mt6359" for PMIC MT6359
- "mediatek,mt6366", "mediatek,mt6358" for PMIC MT6366
- "mediatek,mt6397" for PMIC MT6397
-
-Optional subnodes:
-
-- rtc
- Required properties: Should be one of follows
- - compatible: "mediatek,mt6323-rtc"
- - compatible: "mediatek,mt6331-rtc"
- - compatible: "mediatek,mt6358-rtc"
- - compatible: "mediatek,mt6397-rtc"
- For details, see ../rtc/rtc-mt6397.txt
-- regulators
- Required properties:
- - compatible: "mediatek,mt6323-regulator"
- see ../regulator/mt6323-regulator.txt
- - compatible: "mediatek,mt6358-regulator"
- - compatible: "mediatek,mt6366-regulator", "mediatek-mt6358-regulator"
- see ../regulator/mt6358-regulator.txt
- - compatible: "mediatek,mt6397-regulator"
- see ../regulator/mt6397-regulator.txt
-- codec
- Required properties:
- - compatible: "mediatek,mt6397-codec" or "mediatek,mt6358-sound"
-- clk
- Required properties:
- - compatible: "mediatek,mt6397-clk"
-- led
- Required properties:
- - compatible: "mediatek,mt6323-led"
- see ../leds/leds-mt6323.txt
-
-- keys
- Required properties: Should be one of the following
- - compatible: "mediatek,mt6323-keys"
- - compatible: "mediatek,mt6331-keys"
- - compatible: "mediatek,mt6397-keys"
- see ../input/mtk-pmic-keys.txt
-
-- power-controller
- Required properties:
- - compatible: "mediatek,mt6323-pwrc"
- For details, see ../power/reset/mt6323-poweroff.txt
-
-- pin-controller
- Required properties:
- - compatible: "mediatek,mt6397-pinctrl"
- For details, see ../pinctrl/pinctrl-mt65xx.txt
-
-Example:
- pwrap: pwrap@1000f000 {
- compatible = "mediatek,mt8135-pwrap";
-
- ...
-
- pmic {
- compatible = "mediatek,mt6397";
-
- codec: mt6397codec {
- compatible = "mediatek,mt6397-codec";
- };
-
- regulators {
- compatible = "mediatek,mt6397-regulator";
-
- mt6397_vpca15_reg: buck_vpca15 {
- regulator-compatible = "buck_vpca15";
- regulator-name = "vpca15";
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1400000>;
- regulator-ramp-delay = <12500>;
- regulator-always-on;
- };
-
- mt6397_vgp4_reg: ldo_vgp4 {
- regulator-compatible = "ldo_vgp4";
- regulator-name = "vgp4";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <3300000>;
- regulator-enable-ramp-delay = <218>;
- };
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index a2b2fbf77d5c..078a6886f8b1 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -76,12 +76,14 @@ properties:
- qcom,pmc8180
- qcom,pmc8180c
- qcom,pmc8380
+ - qcom,pmd8028
- qcom,pmd9635
- qcom,pmi632
- qcom,pmi8950
- qcom,pmi8962
- qcom,pmi8994
- qcom,pmi8998
+ - qcom,pmih0108
- qcom,pmk8002
- qcom,pmk8350
- qcom,pmk8550
diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
index 7d0b0b403150..79add913e35c 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
@@ -21,6 +21,9 @@ properties:
- qcom,msm8998-tcsr
- qcom,qcm2290-tcsr
- qcom,qcs404-tcsr
+ - qcom,qcs615-tcsr
+ - qcom,qcs8300-tcsr
+ - qcom,sa8255p-tcsr
- qcom,sa8775p-tcsr
- qcom,sc7180-tcsr
- qcom,sc7280-tcsr
@@ -47,6 +50,7 @@ properties:
- qcom,tcsr-msm8226
- qcom,tcsr-msm8660
- qcom,tcsr-msm8916
+ - qcom,tcsr-msm8917
- qcom,tcsr-msm8953
- qcom,tcsr-msm8960
- qcom,tcsr-msm8974
diff --git a/Documentation/devicetree/bindings/mfd/realtek,rtl9301-switch.yaml b/Documentation/devicetree/bindings/mfd/realtek,rtl9301-switch.yaml
new file mode 100644
index 000000000000..f053303ab1e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/realtek,rtl9301-switch.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/realtek,rtl9301-switch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek Switch with Internal CPU
+
+maintainers:
+ - Chris Packham <chris.packham@alliedtelesis.co.nz>
+
+description:
+ The RTL9300 is a series of is an Ethernet switches with an integrated CPU. A
+ number of different peripherals are accessed through a common register block,
+ represented here as a syscon node.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - realtek,rtl9301-switch
+ - realtek,rtl9302b-switch
+ - realtek,rtl9302c-switch
+ - realtek,rtl9303-switch
+ - const: syscon
+ - const: simple-mfd
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 1
+
+patternProperties:
+ 'reboot@[0-9a-f]+$':
+ $ref: /schemas/power/reset/syscon-reboot.yaml#
+
+ 'i2c@[0-9a-f]+$':
+ $ref: /schemas/i2c/realtek,rtl9301-i2c.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ ethernet-switch@1b000000 {
+ compatible = "realtek,rtl9301-switch", "syscon", "simple-mfd";
+ reg = <0x1b000000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ reboot@c {
+ compatible = "syscon-reboot";
+ reg = <0x0c 0x4>;
+ value = <0x01>;
+ };
+
+ i2c@36c {
+ compatible = "realtek,rtl9301-i2c";
+ reg = <0x36c 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpio@20 {
+ compatible = "nxp,pca9555";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x20>;
+ };
+ };
+
+ i2c@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpio@20 {
+ compatible = "nxp,pca9555";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x20>;
+ };
+ };
+ };
+
+ i2c@388 {
+ compatible = "realtek,rtl9301-i2c";
+ reg = <0x388 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@7 {
+ reg = <7>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpio@20 {
+ compatible = "nxp,pca9555";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x20>;
+ };
+ };
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
index fa17686a64f7..09e7d68e92bf 100644
--- a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml
@@ -55,14 +55,15 @@ properties:
minimum: 0
maximum: 1
- rohm,charger-sense-resistor-ohms:
- minimum: 10000000
- maximum: 50000000
+ rohm,charger-sense-resistor-micro-ohms:
+ minimum: 10000
+ maximum: 50000
+ default: 30000
description: |
BD71827 and BD71828 have SAR ADC for measuring charging currents.
External sense resistor (RSENSE in data sheet) should be used. If some
- other but 30MOhm resistor is used the resistance value should be given
- here in Ohms.
+ other but 30mOhm resistor is used the resistance value should be given
+ here in microohms.
regulators:
$ref: /schemas/regulator/rohm,bd71828-regulator.yaml
@@ -114,7 +115,7 @@ examples:
#gpio-cells = <2>;
gpio-reserved-ranges = <0 1>, <2 1>;
- rohm,charger-sense-resistor-ohms = <10000000>;
+ rohm,charger-sense-resistor-micro-ohms = <10000>;
regulators {
buck1: BUCK1 {
diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2dos05.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2dos05.yaml
new file mode 100644
index 000000000000..b85285720c16
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2dos05.yaml
@@ -0,0 +1,99 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/samsung,s2dos05.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S2DOS05 Power Management IC
+
+maintainers:
+ - Dzmitry Sankouski <dsankouski@gmail.com>
+
+description:
+ This is a device tree bindings for S2DOS family of Power Management IC (PMIC).
+
+ The S2DOS05 is a companion power management IC for the panel and touchscreen
+ in smart phones. Provides voltage regulators and
+ ADC for power/current measurements.
+
+ Regulator section has 4 LDO and 1 BUCK regulators and also
+ provides ELVDD, ELVSS, AVDD lines.
+
+properties:
+ compatible:
+ const: samsung,s2dos05
+
+ reg:
+ maxItems: 1
+
+ regulators:
+ patternProperties:
+ "^buck|ldo[1-4]$":
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
+
+ required:
+ - regulator-name
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@60 {
+ compatible = "samsung,s2dos05";
+ reg = <0x60>;
+
+ regulators {
+ ldo1 {
+ regulator-active-discharge = <1>;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-name = "ldo1";
+ };
+
+ ldo2 {
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "ldo2";
+ };
+
+ ldo3 {
+ regulator-active-discharge = <1>;
+ regulator-boot-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-name = "ldo3";
+ };
+
+ ldo4 {
+ regulator-active-discharge = <1>;
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3775000>;
+ regulator-name = "ldo4";
+ };
+
+ buck {
+ regulator-active-discharge = <1>;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-name = "buck";
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml b/Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml
new file mode 100644
index 000000000000..8beec7e8e4c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/sprd,sc2731.yaml
@@ -0,0 +1,252 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/sprd,sc2731.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum SC27xx PMIC
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+description: |
+ Spreadtrum PMICs belonging to the SC27xx series integrate all mobile handset
+ power management, audio codec, battery management and user interface support
+ functions in a single chip. They have 6 major functional blocks:
+ - DCDCs to support CPU, memory
+ - LDOs to support both internal and external requirements
+ - Battery management system, such as charger, fuel gauge
+ - Audio codec
+ - User interface functions, such as indicator, flash LED and so on
+ - IC level interface, such as power on/off control, RTC, typec and so on
+
+properties:
+ $nodename:
+ pattern: '^pmic@[0-9a-f]+$'
+
+ compatible:
+ enum:
+ - sprd,sc2720
+ - sprd,sc2721
+ - sprd,sc2723
+ - sprd,sc2730
+ - sprd,sc2731
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+ spi-max-frequency: true
+
+ '#address-cells':
+ const: 1
+
+ '#interrupt-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ regulators:
+ type: object
+ $ref: /schemas/regulator/sprd,sc2731-regulator.yaml#
+
+patternProperties:
+ "^adc@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/iio/adc/sprd,sc2720-adc.yaml#
+
+ "^charger@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/power/supply/sc2731-charger.yaml#
+
+ "^efuse@[0-9a-f]+$":
+ type: object
+ additionalProperties: true
+ properties:
+ compatible:
+ enum:
+ - sprd,sc2720-efuse
+ - sprd,sc2721-efuse
+ - sprd,sc2723-efuse
+ - sprd,sc2730-efuse
+ - sprd,sc2731-efuse
+
+ "^fuel-gauge@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/power/supply/sc27xx-fg.yaml#
+
+ "^gpio@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/gpio/sprd,gpio-eic.yaml#
+
+ "^led-controller@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/leds/sprd,sc2731-bltc.yaml#
+
+ "^rtc@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/rtc/sprd,sc2731-rtc.yaml#
+
+ "^vibrator@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/input/sprd,sc27xx-vibrator.yaml#
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-controller
+ - spi-max-frequency
+ - '#address-cells'
+ - '#interrupt-cells'
+ - '#size-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/leds/common.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sc2731_pmic: pmic@0 {
+ compatible = "sprd,sc2731";
+ reg = <0>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ spi-max-frequency = <26000000>;
+ #address-cells = <1>;
+ #interrupt-cells = <1>;
+ #size-cells = <0>;
+
+ charger@0 {
+ compatible = "sprd,sc2731-charger";
+ reg = <0x0>;
+ phys = <&ssphy>;
+ monitored-battery = <&bat>;
+ };
+
+ led-controller@200 {
+ compatible = "sprd,sc2731-bltc";
+ reg = <0x200>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0x0>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@1 {
+ reg = <0x1>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+
+ led@2 {
+ reg = <0x2>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+
+ rtc@280 {
+ compatible = "sprd,sc2731-rtc";
+ reg = <0x280>;
+ interrupt-parent = <&sc2731_pmic>;
+ interrupts = <2>;
+ };
+
+ pmic_eic: gpio@300 {
+ compatible = "sprd,sc2731-eic";
+ reg = <0x300>;
+ interrupt-parent = <&sc2731_pmic>;
+ interrupts = <5>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ efuse@380 {
+ compatible = "sprd,sc2731-efuse";
+ reg = <0x380>;
+ hwlocks = <&hwlock 12>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells */
+ fgu_calib: calib@6 {
+ reg = <0x6 0x2>;
+ bits = <0 9>;
+ };
+
+ adc_big_scale: calib@24 {
+ reg = <0x24 0x2>;
+ };
+
+ adc_small_scale: calib@26 {
+ reg = <0x26 0x2>;
+ };
+ };
+
+ adc@480 {
+ compatible = "sprd,sc2731-adc";
+ reg = <0x480>;
+ interrupt-parent = <&sc2731_pmic>;
+ interrupts = <0>;
+ #io-channel-cells = <1>;
+ hwlocks = <&hwlock 4>;
+ nvmem-cells = <&adc_big_scale>, <&adc_small_scale>;
+ nvmem-cell-names = "big_scale_calib", "small_scale_calib";
+ };
+
+ fuel-gauge@a00 {
+ compatible = "sprd,sc2731-fgu";
+ reg = <0xa00>;
+ battery-detect-gpios = <&pmic_eic 9 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&sc2731_pmic>;
+ interrupts = <4>;
+ io-channels = <&pmic_adc 5>, <&pmic_adc 14>;
+ io-channel-names = "bat-temp", "charge-vol";
+ nvmem-cells = <&fgu_calib>;
+ nvmem-cell-names = "fgu_calib";
+ monitored-battery = <&bat>;
+ sprd,calib-resistance-micro-ohms = <21500>;
+ };
+
+ vibrator@ec8 {
+ compatible = "sprd,sc2731-vibrator";
+ reg = <0xec8>;
+ };
+
+ regulators {
+ compatible = "sprd,sc2731-regulator";
+
+ BUCK_CPU0 {
+ regulator-name = "vddarm0";
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1996875>;
+ regulator-ramp-delay = <25000>;
+ regulator-always-on;
+ };
+
+ LDO_CAMA0 {
+ regulator-name = "vddcama0";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3750000>;
+ regulator-enable-ramp-delay = <100>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt b/Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt
deleted file mode 100644
index 21b9a897fca5..000000000000
--- a/Documentation/devicetree/bindings/mfd/sprd,sc27xx-pmic.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-Spreadtrum SC27xx Power Management Integrated Circuit (PMIC)
-
-The Spreadtrum SC27xx series PMICs contain SC2720, SC2721, SC2723, SC2730
-and SC2731. The Spreadtrum PMIC belonging to SC27xx series integrates all
-mobile handset power management, audio codec, battery management and user
-interface support function in a single chip. It has 6 major functional
-blocks:
-- DCDCs to support CPU, memory.
-- LDOs to support both internal and external requirement.
-- Battery management system, such as charger, fuel gauge.
-- Audio codec.
-- User interface function, such as indicator, flash LED and so on.
-- IC level interface, such as power on/off control, RTC and typec and so on.
-
-Required properties:
-- compatible: Should be one of the following:
- "sprd,sc2720"
- "sprd,sc2721"
- "sprd,sc2723"
- "sprd,sc2730"
- "sprd,sc2731"
-- reg: The address of the device chip select, should be 0.
-- spi-max-frequency: Typically set to 26000000.
-- interrupts: The interrupt line the device is connected to.
-- interrupt-controller: Marks the device node as an interrupt controller.
-- #interrupt-cells: The number of cells to describe an PMIC IRQ, must be 2.
-- #address-cells: Child device offset number of cells, must be 1.
-- #size-cells: Child device size number of cells, must be 0.
-
-Example:
-pmic@0 {
- compatible = "sprd,sc2731";
- reg = <0>;
- spi-max-frequency = <26000000>;
- interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <2>;
- #address-cells = <1>;
- #size-cells = <0>;
-};
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index cc9b17ad69f2..b414de4fa779 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -88,6 +88,7 @@ select:
- mediatek,mt8173-pctl-a-syscfg
- mediatek,mt8365-syscfg
- microchip,lan966x-cpu-syscon
+ - microchip,mpfs-sysreg-scb
- microchip,sam9x60-sfr
- microchip,sama7g5-ddr3phy
- mscc,ocelot-cpu-syscon
@@ -185,6 +186,7 @@ properties:
- mediatek,mt8173-pctl-a-syscfg
- mediatek,mt8365-syscfg
- microchip,lan966x-cpu-syscon
+ - microchip,mpfs-sysreg-scb
- microchip,sam9x60-sfr
- microchip,sama7g5-ddr3phy
- mscc,ocelot-cpu-syscon
diff --git a/Documentation/devicetree/bindings/mfd/ti,twl.yaml b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
index e94b0fd7af0f..f162ab60c09b 100644
--- a/Documentation/devicetree/bindings/mfd/ti,twl.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,twl.yaml
@@ -54,7 +54,7 @@ allOf:
$ref: /schemas/iio/adc/ti,twl4030-madc.yaml
unevaluatedProperties: false
- bci:
+ charger:
type: object
$ref: /schemas/power/supply/twl4030-charger.yaml
unevaluatedProperties: false
@@ -105,6 +105,11 @@ allOf:
regulator-initial-mode: false
properties:
+ charger:
+ type: object
+ properties:
+ compatible:
+ const: ti,twl6030-charger
gpadc:
type: object
properties:
@@ -136,6 +141,13 @@ allOf:
regulator-initial-mode: false
properties:
+ charger:
+ type: object
+ properties:
+ compatible:
+ items:
+ - const: ti,twl6032-charger
+ - const: ti,twl6030-charger
gpadc:
type: object
properties:
@@ -169,6 +181,14 @@ properties:
"#clock-cells":
const: 1
+ charger:
+ type: object
+ additionalProperties: true
+ properties:
+ compatible: true
+ required:
+ - compatible
+
rtc:
type: object
additionalProperties: false
@@ -222,6 +242,14 @@ examples:
interrupt-controller;
#interrupt-cells = <1>;
+ charger {
+ compatible = "ti,twl6030-charger";
+ interrupts = <2>, <5>;
+ io-channels = <&gpadc 10>;
+ io-channel-names = "vusb";
+ monitored-battery = <&bat>;
+ };
+
gpadc {
compatible = "ti,twl6030-gpadc";
interrupts = <6>;
@@ -259,7 +287,7 @@ examples:
interrupt-controller;
#interrupt-cells = <1>;
- bci {
+ charger {
compatible = "ti,twl4030-bci";
interrupts = <9>, <2>;
bci3v1-supply = <&vusb3v1>;
diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
index 14ab367fc887..3f7661bdd202 100644
--- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
+++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml
@@ -71,6 +71,7 @@ allOf:
- x-powers,axp15060
- x-powers,axp305
- x-powers,axp313a
+ - x-powers,axp323
then:
required:
@@ -82,6 +83,7 @@ allOf:
contains:
enum:
- x-powers,axp313a
+ - x-powers,axp323
- x-powers,axp15060
- x-powers,axp717
@@ -100,6 +102,7 @@ properties:
- x-powers,axp221
- x-powers,axp223
- x-powers,axp313a
+ - x-powers,axp323
- x-powers,axp717
- x-powers,axp803
- x-powers,axp806
diff --git a/Documentation/devicetree/bindings/mfd/zii,rave-sp.txt b/Documentation/devicetree/bindings/mfd/zii,rave-sp.txt
deleted file mode 100644
index e0f901edc063..000000000000
--- a/Documentation/devicetree/bindings/mfd/zii,rave-sp.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-Zodiac Inflight Innovations RAVE Supervisory Processor
-
-RAVE Supervisory Processor communicates with SoC over UART. It is
-expected that its Device Tree node is specified as a child of a node
-corresponding to UART controller used for communication.
-
-Required parent device properties:
-
- - compatible: Should be one of:
- - "zii,rave-sp-niu"
- - "zii,rave-sp-mezz"
- - "zii,rave-sp-esb"
- - "zii,rave-sp-rdu1"
- - "zii,rave-sp-rdu2"
-
- - current-speed: Should be set to baud rate SP device is using
-
-RAVE SP consists of the following sub-devices:
-
-Device Description
------- -----------
-rave-sp-wdt : Watchdog
-rave-sp-nvmem : Interface to onboard EEPROM
-rave-sp-backlight : Display backlight
-rave-sp-hwmon : Interface to onboard hardware sensors
-rave-sp-leds : Interface to onboard LEDs
-rave-sp-input : Interface to onboard power button
-
-Example of usage:
-
- rdu {
- compatible = "zii,rave-sp-rdu2";
- current-speed = <1000000>;
-
- watchdog {
- compatible = "zii,rave-sp-watchdog";
- };
- };
-
diff --git a/Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml b/Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml
new file mode 100644
index 000000000000..1d078c5ef168
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/zii,rave-sp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zodiac Inflight Innovations RAVE Supervisory Processor
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+
+description:
+ RAVE Supervisory Processor communicates with SoC over UART. It is
+ expected that its Device Tree node is specified as a child of a node
+ corresponding to UART controller used for communication.
+
+properties:
+ compatible:
+ enum:
+ - zii,rave-sp-niu
+ - zii,rave-sp-mezz
+ - zii,rave-sp-esb
+ - zii,rave-sp-rdu1
+ - zii,rave-sp-rdu2
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ watchdog:
+ $ref: /schemas/watchdog/zii,rave-sp-wdt.yaml
+
+ backlight:
+ $ref: /schemas/leds/backlight/zii,rave-sp-backlight.yaml
+
+ pwrbutton:
+ $ref: /schemas/input/zii,rave-sp-pwrbutton.yaml
+
+patternProperties:
+ '^eeprom@[0-9a-f]+$':
+ $ref: /schemas/nvmem/zii,rave-sp-eeprom.yaml
+
+required:
+ - compatible
+
+allOf:
+ - $ref: /schemas/serial/serial-peripheral-props.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mfd {
+ compatible = "zii,rave-sp-rdu2";
+ current-speed = <1000000>;
+
+ watchdog {
+ compatible = "zii,rave-sp-watchdog";
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml
index 6c40611405a0..0432cc96f7ca 100644
--- a/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml
@@ -15,6 +15,7 @@ properties:
- enum:
- amd,pensando-elba-sd4hc
- microchip,mpfs-sd4hc
+ - microchip,pic64gx-sd4hc
- socionext,uniphier-sd4hc
- const: cdns,sd4hc
@@ -120,7 +121,7 @@ required:
- clocks
allOf:
- - $ref: mmc-controller.yaml
+ - $ref: sdhci-common.yaml
- if:
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/mmc/mmc-card.yaml b/Documentation/devicetree/bindings/mmc/mmc-card.yaml
index fd347126449a..1d91d4272de0 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-card.yaml
+++ b/Documentation/devicetree/bindings/mmc/mmc-card.yaml
@@ -13,6 +13,10 @@ description: |
This documents describes the devicetree bindings for a mmc-host controller
child node describing a mmc-card / an eMMC.
+ It's possible to define a fixed partition table for an eMMC for the user
+ partition, the 2 BOOT partition (boot1/2) and the 4 GP (gp1/2/3/4) if supported
+ by the eMMC.
+
properties:
compatible:
const: mmc-card
@@ -26,6 +30,24 @@ properties:
Use this to indicate that the mmc-card has a broken hpi
implementation, and that hpi should not be used.
+patternProperties:
+ "^partitions(-boot[12]|-gp[14])?$":
+ $ref: /schemas/mtd/partitions/partitions.yaml
+
+ patternProperties:
+ "^partition@[0-9a-f]+$":
+ $ref: /schemas/mtd/partitions/partition.yaml
+
+ properties:
+ reg:
+ description: Must be multiple of 512 as it's converted
+ internally from bytes to SECTOR_SIZE (512 bytes)
+
+ required:
+ - reg
+
+ unevaluatedProperties: false
+
required:
- compatible
- reg
@@ -42,6 +64,36 @@ examples:
compatible = "mmc-card";
reg = <0>;
broken-hpi;
+
+ partitions {
+ compatible = "fixed-partitions";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "kernel"; /* Kernel */
+ reg = <0x0 0x2000000>; /* 32 MB */
+ };
+
+ partition@2000000 {
+ label = "rootfs";
+ reg = <0x2000000 0x40000000>; /* 1GB */
+ };
+ };
+
+ partitions-boot1 {
+ compatible = "fixed-partitions";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl";
+ reg = <0x0 0x2000000>; /* 32MB */
+ read-only;
+ };
+ };
};
};
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
index c532ec92d2d9..f86ebd81f5a5 100644
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
@@ -21,9 +21,11 @@ properties:
- mediatek,mt7620-mmc
- mediatek,mt7622-mmc
- mediatek,mt7986-mmc
+ - mediatek,mt7988-mmc
- mediatek,mt8135-mmc
- mediatek,mt8173-mmc
- mediatek,mt8183-mmc
+ - mediatek,mt8196-mmc
- mediatek,mt8516-mmc
- items:
- const: mediatek,mt7623-mmc
@@ -190,6 +192,7 @@ allOf:
- mediatek,mt8186-mmc
- mediatek,mt8188-mmc
- mediatek,mt8195-mmc
+ - mediatek,mt8196-mmc
- mediatek,mt8516-mmc
then:
properties:
@@ -266,6 +269,27 @@ allOf:
- if:
properties:
compatible:
+ contains:
+ enum:
+ - mediatek,mt7988-mmc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: source clock
+ - description: HCLK which used for host
+ - description: Advanced eXtensible Interface
+ - description: Advanced High-performance Bus clock
+ clock-names:
+ items:
+ - const: source
+ - const: hclk
+ - const: axi_cg
+ - const: ahb_cg
+
+ - if:
+ properties:
+ compatible:
enum:
- mediatek,mt8186-mmc
- mediatek,mt8188-mmc
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
index 11979b026d21..8b393e26e025 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
@@ -38,11 +38,14 @@ properties:
- enum:
- qcom,ipq5018-sdhci
- qcom,ipq5332-sdhci
+ - qcom,ipq5424-sdhci
- qcom,ipq6018-sdhci
- qcom,ipq9574-sdhci
- qcom,qcm2290-sdhci
- qcom,qcs404-sdhci
+ - qcom,qcs615-sdhci
- qcom,qdu1000-sdhci
+ - qcom,sar2130p-sdhci
- qcom,sc7180-sdhci
- qcom,sc7280-sdhci
- qcom,sc8280xp-sdhci
@@ -62,6 +65,7 @@ properties:
- qcom,sm8450-sdhci
- qcom,sm8550-sdhci
- qcom,sm8650-sdhci
+ - qcom,x1e80100-sdhci
- const: qcom,sdhci-msm-v5 # for sdcc version 5.0
reg:
diff --git a/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml
index 37a65badb448..0a2d7baf5db3 100644
--- a/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml
+++ b/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml
@@ -34,6 +34,12 @@ properties:
firmware-name:
maxItems: 1
+ device-wakeup-gpios:
+ maxItems: 1
+ description:
+ Host-To-Chip power save mechanism is driven by this GPIO
+ connected to BT_WAKE_IN pin of the NXP chipset.
+
required:
- compatible
@@ -41,10 +47,12 @@ additionalProperties: false
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
serial {
bluetooth {
compatible = "nxp,88w8987-bt";
fw-init-baudrate = <3000000>;
firmware-name = "uartuart8987_bt_v0.bin";
+ device-wakeup-gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
};
};
diff --git a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
index 30c0c3e6f37a..62ca63e8a26f 100644
--- a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
@@ -34,6 +34,7 @@ properties:
- microchip,ksz9563
- microchip,ksz8563
- microchip,ksz8567
+ - microchip,lan9646
reset-gpios:
description:
@@ -81,6 +82,26 @@ properties:
interrupts:
maxItems: 1
+ mdio:
+ $ref: /schemas/net/mdio.yaml#
+ unevaluatedProperties: false
+ properties:
+ mdio-parent-bus:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle pointing to the MDIO bus controller connected to the
+ secondary MDIO interface. This property should be used when
+ the internal MDIO bus is accessed via a secondary MDIO
+ interface rather than the primary management interface.
+
+ patternProperties:
+ "^ethernet-phy@[0-9a-f]$":
+ type: object
+ $ref: /schemas/net/ethernet-phy.yaml#
+ unevaluatedProperties: false
+ description:
+ Integrated PHY node
+
required:
- compatible
- reg
@@ -138,7 +159,6 @@ examples:
pinctrl-0 = <&pinctrl_spi_ksz>;
cs-gpios = <&pioC 25 0>;
- id = <1>;
ksz9477: switch@0 {
compatible = "microchip,ksz9477";
diff --git a/Documentation/devicetree/bindings/net/dsa/realtek.yaml b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
index 70b6bda3cf98..f348e66fb515 100644
--- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
@@ -147,7 +147,7 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
platform {
- switch {
+ ethernet-switch {
compatible = "realtek,rtl8366rb";
/* 22 = MDIO (has input reads), 21 = MDC (clock, output only) */
mdc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
@@ -163,35 +163,35 @@ examples:
#interrupt-cells = <1>;
};
- ports {
+ ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
- port@0 {
+ ethernet-port@0 {
reg = <0>;
label = "lan0";
phy-handle = <&phy0>;
};
- port@1 {
+ ethernet-port@1 {
reg = <1>;
label = "lan1";
phy-handle = <&phy1>;
};
- port@2 {
+ ethernet-port@2 {
reg = <2>;
label = "lan2";
phy-handle = <&phy2>;
};
- port@3 {
+ ethernet-port@3 {
reg = <3>;
label = "lan3";
phy-handle = <&phy3>;
};
- port@4 {
+ ethernet-port@4 {
reg = <4>;
label = "wan";
phy-handle = <&phy4>;
};
- port@5 {
+ ethernet-port@5 {
reg = <5>;
ethernet = <&gmac0>;
phy-mode = "rgmii";
@@ -241,7 +241,7 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
platform {
- switch {
+ ethernet-switch {
compatible = "realtek,rtl8365mb";
mdc-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
mdio-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
@@ -255,30 +255,30 @@ examples:
#interrupt-cells = <1>;
};
- ports {
+ ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
- port@0 {
+ ethernet-port@0 {
reg = <0>;
label = "swp0";
phy-handle = <&ethphy0>;
};
- port@1 {
+ ethernet-port@1 {
reg = <1>;
label = "swp1";
phy-handle = <&ethphy1>;
};
- port@2 {
+ ethernet-port@2 {
reg = <2>;
label = "swp2";
phy-handle = <&ethphy2>;
};
- port@3 {
+ ethernet-port@3 {
reg = <3>;
label = "swp3";
phy-handle = <&ethphy3>;
};
- port@6 {
+ ethernet-port@6 {
reg = <6>;
ethernet = <&fec1>;
phy-mode = "rgmii";
@@ -330,7 +330,7 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
- switch@29 {
+ ethernet-switch@29 {
compatible = "realtek,rtl8365mb";
reg = <29>;
@@ -344,36 +344,36 @@ examples:
#interrupt-cells = <1>;
};
- ports {
+ ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
- port@0 {
+ ethernet-port@0 {
reg = <0>;
label = "lan4";
};
- port@1 {
+ ethernet-port@1 {
reg = <1>;
label = "lan3";
};
- port@2 {
+ ethernet-port@2 {
reg = <2>;
label = "lan2";
};
- port@3 {
+ ethernet-port@3 {
reg = <3>;
label = "lan1";
};
- port@4 {
+ ethernet-port@4 {
reg = <4>;
label = "wan";
};
- port@7 {
+ ethernet-port@7 {
reg = <7>;
ethernet = <&ethernet>;
phy-mode = "rgmii";
diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
index d9b62741a225..2c71454ae8e3 100644
--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
@@ -158,6 +158,27 @@ properties:
Mark the corresponding energy efficient ethernet mode as
broken and request the ethernet to stop advertising it.
+ timing-role:
+ $ref: /schemas/types.yaml#/definitions/string
+ enum:
+ - forced-master
+ - forced-slave
+ - preferred-master
+ - preferred-slave
+ description: |
+ Specifies the timing role of the PHY in the network link. This property is
+ required for setups where the role must be explicitly assigned via the
+ device tree due to limitations in hardware strapping or incorrect strap
+ configurations.
+ It is applicable to Single Pair Ethernet (1000/100/10Base-T1) and other
+ PHY types, including 1000Base-T, where it controls whether the PHY should
+ be a master (clock source) or a slave (clock receiver).
+
+ - 'forced-master': The PHY is forced to operate as a master.
+ - 'forced-slave': The PHY is forced to operate as a slave.
+ - 'preferred-master': Prefer the PHY to be master but allow negotiation.
+ - 'preferred-slave': Prefer the PHY to be slave but allow negotiation.
+
pses:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/fsl,enetc-mdio.yaml b/Documentation/devicetree/bindings/net/fsl,enetc-mdio.yaml
index c1dd6aa04321..71c43ece8295 100644
--- a/Documentation/devicetree/bindings/net/fsl,enetc-mdio.yaml
+++ b/Documentation/devicetree/bindings/net/fsl,enetc-mdio.yaml
@@ -20,10 +20,13 @@ maintainers:
properties:
compatible:
- items:
- - enum:
- - pci1957,ee01
- - const: fsl,enetc-mdio
+ oneOf:
+ - items:
+ - enum:
+ - pci1957,ee01
+ - const: fsl,enetc-mdio
+ - items:
+ - const: pci1131,ee00
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/fsl,enetc.yaml b/Documentation/devicetree/bindings/net/fsl,enetc.yaml
index e152c93998fe..ca70f0050171 100644
--- a/Documentation/devicetree/bindings/net/fsl,enetc.yaml
+++ b/Documentation/devicetree/bindings/net/fsl,enetc.yaml
@@ -20,14 +20,25 @@ maintainers:
properties:
compatible:
- items:
+ oneOf:
+ - items:
+ - enum:
+ - pci1957,e100
+ - const: fsl,enetc
- enum:
- - pci1957,e100
- - const: fsl,enetc
+ - pci1131,e101
reg:
maxItems: 1
+ clocks:
+ items:
+ - description: MAC transmit/receive reference clock
+
+ clock-names:
+ items:
+ - const: ref
+
mdio:
$ref: mdio.yaml
unevaluatedProperties: false
@@ -40,6 +51,17 @@ required:
allOf:
- $ref: /schemas/pci/pci-device.yaml
- $ref: ethernet-controller.yaml
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - pci1131,e101
+ then:
+ properties:
+ clocks: false
+ clock-names: false
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/net/fsl,fec.yaml b/Documentation/devicetree/bindings/net/fsl,fec.yaml
index 5536c06139ca..24e863fdbdab 100644
--- a/Documentation/devicetree/bindings/net/fsl,fec.yaml
+++ b/Documentation/devicetree/bindings/net/fsl,fec.yaml
@@ -183,6 +183,13 @@ properties:
description:
Register bits of stop mode control, the format is <&gpr req_gpr req_bit>.
+ fsl,pps-channel:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+ description:
+ Specifies to which timer instance the PPS signal is routed.
+ enum: [0, 1, 2, 3]
+
mdio:
$ref: mdio.yaml#
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/net/marvell,aquantia.yaml b/Documentation/devicetree/bindings/net/marvell,aquantia.yaml
index 9854fab4c4db..f269615126d8 100644
--- a/Documentation/devicetree/bindings/net/marvell,aquantia.yaml
+++ b/Documentation/devicetree/bindings/net/marvell,aquantia.yaml
@@ -48,6 +48,12 @@ properties:
firmware-name:
description: specify the name of PHY firmware to load
+ marvell,mdi-cfg-order:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+ description:
+ force normal (0) or reverse (1) order of MDI pairs, overriding MDI_CFG bootstrap pin.
+
nvmem-cells:
description: phandle to the firmware nvmem cell
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/mdio-mux-gpio.yaml b/Documentation/devicetree/bindings/net/mdio-mux-gpio.yaml
index 71c25c4580ea..cc674b21588c 100644
--- a/Documentation/devicetree/bindings/net/mdio-mux-gpio.yaml
+++ b/Documentation/devicetree/bindings/net/mdio-mux-gpio.yaml
@@ -53,37 +53,21 @@ examples:
ethernet-phy@1 {
reg = <1>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <10 8>; /* Pin 10, active low */
};
ethernet-phy@2 {
reg = <2>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <10 8>; /* Pin 10, active low */
};
ethernet-phy@3 {
reg = <3>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <10 8>; /* Pin 10, active low */
};
ethernet-phy@4 {
reg = <4>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <10 8>; /* Pin 10, active low */
};
@@ -96,37 +80,21 @@ examples:
ethernet-phy@1 {
reg = <1>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
ethernet-phy@2 {
reg = <2>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
ethernet-phy@3 {
reg = <3>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
ethernet-phy@4 {
reg = <4>;
- marvell,reg-init = <3 0x10 0 0x5777>,
- <3 0x11 0 0x00aa>,
- <3 0x12 0 0x4105>,
- <3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
diff --git a/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml b/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml
index fcafef8d5a33..dedfad526666 100644
--- a/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml
+++ b/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml
@@ -9,6 +9,7 @@ title: Microchip Sparx5 Ethernet switch controller
maintainers:
- Steen Hegelund <steen.hegelund@microchip.com>
- Lars Povlsen <lars.povlsen@microchip.com>
+ - Daniel Machon <daniel.machon@microchip.com>
description: |
The SparX-5 Enterprise Ethernet switch family provides a rich set of
@@ -34,7 +35,24 @@ properties:
pattern: "^switch@[0-9a-f]+$"
compatible:
- const: microchip,sparx5-switch
+ oneOf:
+ - enum:
+ - microchip,lan9691-switch
+ - microchip,sparx5-switch
+ - items:
+ - enum:
+ - microchip,lan969c-switch
+ - microchip,lan969b-switch
+ - microchip,lan969a-switch
+ - microchip,lan9699-switch
+ - microchip,lan9698-switch
+ - microchip,lan9697-switch
+ - microchip,lan9696-switch
+ - microchip,lan9695-switch
+ - microchip,lan9694-switch
+ - microchip,lan9693-switch
+ - microchip,lan9692-switch
+ - const: microchip,lan9691-switch
reg:
items:
diff --git a/Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml b/Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
index 6924aff0b2c5..364b36151180 100644
--- a/Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
+++ b/Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
@@ -17,6 +17,7 @@ properties:
- enum:
- nxp,nq310
- nxp,pn547
+ - nxp,pn553
- const: nxp,nxp-nci-i2c
enable-gpios:
diff --git a/Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml b/Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
new file mode 100644
index 000000000000..97389fd5dbbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/nxp,netc-blk-ctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NETC Blocks Control
+
+description:
+ Usually, NETC has 2 blocks of 64KB registers, integrated endpoint register
+ block (IERB) and privileged register block (PRB). IERB is used for pre-boot
+ initialization for all NETC devices, such as ENETC, Timer, EMIDO and so on.
+ And PRB controls global reset and global error handling for NETC. Moreover,
+ for the i.MX platform, there is also a NETCMIX block for link configuration,
+ such as MII protocol, PCS protocol, etc.
+
+maintainers:
+ - Wei Fang <wei.fang@nxp.com>
+ - Clark Wang <xiaoning.wang@nxp.com>
+
+properties:
+ compatible:
+ enum:
+ - nxp,imx95-netc-blk-ctrl
+
+ reg:
+ maxItems: 3
+
+ reg-names:
+ items:
+ - const: ierb
+ - const: prb
+ - const: netcmix
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
+ ranges: true
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: ipg
+
+ power-domains:
+ maxItems: 1
+
+patternProperties:
+ "^pcie@[0-9a-f]+$":
+ $ref: /schemas/pci/host-generic-pci.yaml#
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ system-controller@4cde0000 {
+ compatible = "nxp,imx95-netc-blk-ctrl";
+ reg = <0x0 0x4cde0000 0x0 0x10000>,
+ <0x0 0x4cdf0000 0x0 0x10000>,
+ <0x0 0x4c81000c 0x0 0x18>;
+ reg-names = "ierb", "prb", "netcmix";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clocks = <&scmi_clk 98>;
+ clock-names = "ipg";
+ power-domains = <&scmi_devpd 18>;
+
+ pcie@4cb00000 {
+ compatible = "pci-host-ecam-generic";
+ reg = <0x0 0x4cb00000 0x0 0x100000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ bus-range = <0x1 0x1>;
+ ranges = <0x82000000 0x0 0x4cce0000 0x0 0x4cce0000 0x0 0x20000
+ 0xc2000000 0x0 0x4cd10000 0x0 0x4cd10000 0x0 0x10000>;
+
+ mdio@0,0 {
+ compatible = "pci1131,ee00";
+ reg = <0x010000 0 0 0 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml b/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml
index a754a61adc2d..5f9f7efff538 100644
--- a/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml
+++ b/Documentation/devicetree/bindings/net/nxp,tja11xx.yaml
@@ -62,6 +62,22 @@ allOf:
reference clock output when RMII mode enabled.
Only supported on TJA1100 and TJA1101.
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - ethernet-phy-id001b.b010
+ - ethernet-phy-id001b.b013
+ - ethernet-phy-id001b.b030
+ - ethernet-phy-id001b.b031
+
+ then:
+ properties:
+ nxp,rmii-refclk-out:
+ type: boolean
+ description: Enable 50MHz RMII reference clock output on REF_CLK pin.
+
patternProperties:
"^ethernet-phy@[0-9a-f]+$":
type: object
diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
index 6672327358bc..0bcd593a7bd0 100644
--- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
+++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
@@ -18,11 +18,20 @@ allOf:
properties:
compatible:
- enum:
- - qcom,qcs404-ethqos
- - qcom,sa8775p-ethqos
- - qcom,sc8280xp-ethqos
- - qcom,sm8150-ethqos
+ oneOf:
+ - items:
+ - enum:
+ - qcom,qcs8300-ethqos
+ - const: qcom,sa8775p-ethqos
+ - items:
+ - enum:
+ - qcom,qcs615-ethqos
+ - const: qcom,sm8150-ethqos
+ - enum:
+ - qcom,qcs404-ethqos
+ - qcom,sa8775p-ethqos
+ - qcom,sc8280xp-ethqos
+ - qcom,sm8150-ethqos
reg:
maxItems: 2
diff --git a/Documentation/devicetree/bindings/net/renesas,ether.yaml b/Documentation/devicetree/bindings/net/renesas,ether.yaml
index 29355ab98569..f0a52f47f95a 100644
--- a/Documentation/devicetree/bindings/net/renesas,ether.yaml
+++ b/Documentation/devicetree/bindings/net/renesas,ether.yaml
@@ -59,6 +59,9 @@ properties:
clocks:
maxItems: 1
+ iommus:
+ maxItems: 1
+
power-domains:
maxItems: 1
@@ -123,7 +126,6 @@ examples:
reg = <1>;
interrupt-parent = <&irqc0>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
- micrel,led-mode = <1>;
reset-gpios = <&gpio5 31 GPIO_ACTIVE_LOW>;
};
};
diff --git a/Documentation/devicetree/bindings/net/sff,sfp.yaml b/Documentation/devicetree/bindings/net/sff,sfp.yaml
index 90611b598d2b..15616ad737f5 100644
--- a/Documentation/devicetree/bindings/net/sff,sfp.yaml
+++ b/Documentation/devicetree/bindings/net/sff,sfp.yaml
@@ -132,7 +132,7 @@ examples:
pinctrl-names = "default";
pinctrl-0 = <&cpm_phy0_pins &cps_phy0_pins>;
reg = <0>;
- interrupt = <&cpm_gpio2 18 IRQ_TYPE_EDGE_FALLING>;
+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
sfp = <&sfp2>;
};
};
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 4e2ba1bf788c..eb1f3ae41ab9 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -26,6 +26,7 @@ select:
- snps,dwmac-3.610
- snps,dwmac-3.70a
- snps,dwmac-3.710
+ - snps,dwmac-3.72a
- snps,dwmac-4.00
- snps,dwmac-4.10a
- snps,dwmac-4.20a
@@ -90,6 +91,7 @@ properties:
- snps,dwmac-3.610
- snps,dwmac-3.70a
- snps,dwmac-3.710
+ - snps,dwmac-3.72a
- snps,dwmac-4.00
- snps,dwmac-4.10a
- snps,dwmac-4.20a
@@ -99,6 +101,7 @@ properties:
- snps,dwxgmac-2.10
- starfive,jh7100-dwmac
- starfive,jh7110-dwmac
+ - thead,th1520-gmac
reg:
minItems: 1
@@ -560,7 +563,7 @@ properties:
max read outstanding req. limit
snps,kbbe:
- $ref: /schemas/types.yaml#/definitions/uint32
+ $ref: /schemas/types.yaml#/definitions/flag
description:
do not cross 1KiB boundary.
diff --git a/Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml b/Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml
new file mode 100644
index 000000000000..6d9de3303762
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/thead,th1520-gmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: T-HEAD TH1520 GMAC Ethernet controller
+
+maintainers:
+ - Drew Fustini <dfustini@tenstorrent.com>
+
+description: |
+ The TH1520 GMAC is described in the TH1520 Peripheral Interface User Manual
+ https://git.beagleboard.org/beaglev-ahead/beaglev-ahead/-/tree/main/docs
+
+ Features include
+ - Compliant with IEEE802.3 Specification
+ - IEEE 1588-2008 standard for precision networked clock synchronization
+ - Supports 10/100/1000Mbps data transfer rate
+ - Supports RGMII/MII interface
+ - Preamble and start of frame data (SFD) insertion in Transmit path
+ - Preamble and SFD deletion in the Receive path
+ - Automatic CRC and pad generation options for receive frames
+ - MDIO master interface for PHY device configuration and management
+
+ The GMAC Registers consists of two parts
+ - APB registers are used to configure clock frequency/clock enable/clock
+ direction/PHY interface type.
+ - AHB registers are use to configure GMAC core (DesignWare Core part).
+ GMAC core register consists of DMA registers and GMAC registers.
+
+select:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - thead,th1520-gmac
+ required:
+ - compatible
+
+allOf:
+ - $ref: snps,dwmac.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - thead,th1520-gmac
+ - const: snps,dwmac-3.70a
+
+ reg:
+ items:
+ - description: DesignWare GMAC IP core registers
+ - description: GMAC APB registers
+
+ reg-names:
+ items:
+ - const: dwmac
+ - const: apb
+
+ clocks:
+ items:
+ - description: GMAC main clock
+ - description: Peripheral registers interface clock
+
+ clock-names:
+ items:
+ - const: stmmaceth
+ - const: pclk
+
+ interrupts:
+ items:
+ - description: Combined signal for various interrupt events
+
+ interrupt-names:
+ items:
+ - const: macirq
+
+required:
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ gmac0: ethernet@e7070000 {
+ compatible = "thead,th1520-gmac", "snps,dwmac-3.70a";
+ reg = <0xe7070000 0x2000>, <0xec003000 0x1000>;
+ reg-names = "dwmac", "apb";
+ clocks = <&clk 1>, <&clk 2>;
+ clock-names = "stmmaceth", "pclk";
+ interrupts = <66>;
+ interrupt-names = "macirq";
+ phy-mode = "rgmii-id";
+ snps,fixed-burst;
+ snps,axi-config = <&stmmac_axi_setup>;
+ snps,pbl = <32>;
+ phy-handle = <&phy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
index e564f20d8f41..a3607d55ef36 100644
--- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
@@ -53,6 +53,7 @@ properties:
- pci14e4,4488 # BCM4377
- pci14e4,4425 # BCM4378
- pci14e4,4433 # BCM4387
+ - pci14e4,449d # BCM43752
reg:
description: SDIO function number for the device (for most cases
@@ -121,6 +122,14 @@ properties:
NVRAM. This would normally be filled in by the bootloader from platform
configuration data.
+ clocks:
+ items:
+ - description: External Low Power Clock input (32.768KHz)
+
+ clock-names:
+ items:
+ - const: lpo
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
index 2460ccc08237..5d40f22765bb 100644
--- a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
@@ -16,7 +16,11 @@ description:
properties:
compatible:
- const: microchip,wilc1000
+ oneOf:
+ - items:
+ - const: microchip,wilc3000
+ - const: microchip,wilc1000
+ - const: microchip,wilc1000
reg: true
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml
index 8675d7d0215c..a71fdf05bc1e 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml
@@ -50,6 +50,9 @@ properties:
vddrfa1p7-supply:
description: VDD_RFA_1P7 supply regulator handle
+ vddrfa1p8-supply:
+ description: VDD_RFA_1P8 supply regulator handle
+
vddpcie0p9-supply:
description: VDD_PCIE_0P9 supply regulator handle
@@ -77,6 +80,22 @@ allOf:
- vddrfa1p7-supply
- vddpcie0p9-supply
- vddpcie1p8-supply
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: pci17cb,1103
+ then:
+ required:
+ - vddrfacmn-supply
+ - vddaon-supply
+ - vddwlcx-supply
+ - vddwlmx-supply
+ - vddrfa0p8-supply
+ - vddrfa1p2-supply
+ - vddrfa1p8-supply
+ - vddpcie0p9-supply
+ - vddpcie1p8-supply
additionalProperties: false
@@ -99,6 +118,16 @@ examples:
compatible = "pci17cb,1103";
reg = <0x10000 0x0 0x0 0x0 0x0>;
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+ vddaon-supply = <&vreg_pmu_aon_0p8>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+
qcom,ath11k-calibration-variant = "LE_X13S";
};
};
diff --git a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
index e95c21628281..fb02e579463c 100644
--- a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
+++ b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
@@ -61,7 +61,7 @@ properties:
- gmii
- rgmii
- sgmii
- - 1000BaseX
+ - 1000base-x
xlnx,phy-type:
description:
diff --git a/Documentation/devicetree/bindings/net/xlnx,emaclite.yaml b/Documentation/devicetree/bindings/net/xlnx,emaclite.yaml
index 92d8ade988f6..e16384aff557 100644
--- a/Documentation/devicetree/bindings/net/xlnx,emaclite.yaml
+++ b/Documentation/devicetree/bindings/net/xlnx,emaclite.yaml
@@ -29,6 +29,9 @@ properties:
interrupts:
maxItems: 1
+ clocks:
+ maxItems: 1
+
phy-handle: true
local-mac-address: true
@@ -45,6 +48,7 @@ required:
- compatible
- reg
- interrupts
+ - clocks
- phy-handle
additionalProperties: false
@@ -56,6 +60,7 @@ examples:
reg = <0x40e00000 0x10000>;
interrupt-parent = <&axi_intc_1>;
interrupts = <1>;
+ clocks = <&dummy>;
local-mac-address = [00 00 00 00 00 00];
phy-handle = <&phy0>;
xlnx,rx-ping-pong;
diff --git a/Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml b/Documentation/devicetree/bindings/nvmem/renesas,rcar-efuse.yaml
index d7e289244e72..ce7d65afa460 100644
--- a/Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/renesas,rcar-efuse.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/fuse/renesas,rcar-efuse.yaml#
+$id: http://devicetree.org/schemas/nvmem/renesas,rcar-efuse.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: R-Car E-FUSE connected to PFC
@@ -13,6 +13,9 @@ description:
The E-FUSE is a type of non-volatile memory, which is accessible through the
Pin Function Controller (PFC) on some R-Car Gen4 SoCs.
+allOf:
+ - $ref: nvmem.yaml#
+
properties:
compatible:
enum:
@@ -39,17 +42,27 @@ required:
- power-domains
- resets
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
- #include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
- #include <dt-bindings/power/r8a779a0-sysc.h>
-
- fuse: fuse@e6078800 {
- compatible = "renesas,r8a779a0-efuse";
- reg = <0xe6078800 0x100>;
- clocks = <&cpg CPG_MOD 916>;
- power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
- resets = <&cpg 916>;
+ #include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+ #include <dt-bindings/power/r8a779f0-sysc.h>
+
+ fuse@e6078800 {
+ compatible = "renesas,r8a779f0-efuse";
+ reg = <0xe6078800 0x200>;
+ clocks = <&cpg CPG_MOD 915>;
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 915>;
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ calib@144 {
+ reg = <0x144 0x08>;
+ };
+ };
};
diff --git a/Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml b/Documentation/devicetree/bindings/nvmem/renesas,rcar-otp.yaml
index d74872ae9ff3..3313c03ea68d 100644
--- a/Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/renesas,rcar-otp.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/fuse/renesas,rcar-otp.yaml#
+$id: http://devicetree.org/schemas/nvmem/renesas,rcar-otp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: R-Car E-FUSE connected to OTP_MEM
@@ -13,6 +13,9 @@ description:
The E-FUSE is a type of non-volatile memory, which is accessible through the
One-Time Programmable Memory (OTP_MEM) module on some R-Car Gen4 SoCs.
+allOf:
+ - $ref: nvmem.yaml#
+
properties:
compatible:
enum:
@@ -22,17 +25,19 @@ properties:
reg:
items:
- description: OTP_MEM_0
- - description: OTP_MEM_1
+ - description: OTP_MEM_1.
+ The addresses of cells defined under the optional nvmem-layout
+ subnode are relative to this register bank.
required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
- otp: otp@e61be000 {
- compatible = "renesas,r8a779g0-otp";
- reg = <0xe61be000 0x1000>, <0xe61bf000 0x1000>;
+ otp@e61be000 {
+ compatible = "renesas,r8a779g0-otp";
+ reg = <0xe61be000 0x1000>, <0xe61bf000 0x1000>;
};
diff --git a/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt b/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt
deleted file mode 100644
index 586c08286aa9..000000000000
--- a/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-= Spreadtrum SC27XX PMIC eFuse device tree bindings =
-
-Required properties:
-- compatible: Should be one of the following.
- "sprd,sc2720-efuse"
- "sprd,sc2721-efuse"
- "sprd,sc2723-efuse"
- "sprd,sc2730-efuse"
- "sprd,sc2731-efuse"
-- reg: Specify the address offset of efuse controller.
-- hwlocks: Reference to a phandle of a hwlock provider node.
-
-= Data cells =
-Are child nodes of eFuse, bindings of which as described in
-bindings/nvmem/nvmem.txt
-
-Example:
-
- sc2731_pmic: pmic@0 {
- compatible = "sprd,sc2731";
- reg = <0>;
- spi-max-frequency = <26000000>;
- interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <2>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- efuse@380 {
- compatible = "sprd,sc2731-efuse";
- reg = <0x380>;
- #address-cells = <1>;
- #size-cells = <1>;
- hwlocks = <&hwlock 12>;
-
- /* Data cells */
- thermal_calib: calib@10 {
- reg = <0x10 0x2>;
- };
- };
- };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells.
-
-Example:
-
- thermal {
- ...
- nvmem-cells = <&thermal_calib>;
- nvmem-cell-names = "calibration";
- };
diff --git a/Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml b/Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml
new file mode 100644
index 000000000000..dc25fe3d1841
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/sprd,sc2731-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum SC27XX PMIC eFuse
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+properties:
+ compatible:
+ enum:
+ - sprd,sc2720-efuse
+ - sprd,sc2721-efuse
+ - sprd,sc2723-efuse
+ - sprd,sc2730-efuse
+ - sprd,sc2731-efuse
+
+ reg:
+ maxItems: 1
+
+ hwlocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - hwlocks
+
+allOf:
+ - $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ efuse@380 {
+ compatible = "sprd,sc2731-efuse";
+ reg = <0x380>;
+ hwlocks = <&hwlock 12>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells */
+ fgu_calib: calib@6 {
+ reg = <0x6 0x2>;
+ bits = <0 9>;
+ };
+
+ adc_big_scale: calib@24 {
+ reg = <0x24 0x2>;
+ };
+
+ adc_small_scale: calib@26 {
+ reg = <0x26 0x2>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml b/Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml
new file mode 100644
index 000000000000..00e0fd1353a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/sprd,ums312-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum UMS312 eFuse
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+properties:
+ compatible:
+ const: sprd,ums312-efuse
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: enable
+
+ hwlocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - hwlocks
+
+allOf:
+ - $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/sprd,ums512-clk.h>
+
+ efuse@32240000 {
+ compatible = "sprd,ums312-efuse";
+ reg = <0x32240000 0x10000>;
+ clocks = <&aonapb_gate CLK_EFUSE_EB>;
+ clock-names = "enable";
+ hwlocks = <&hwlock 8>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells */
+ thermal_calib: calib@10 {
+ reg = <0x10 0x2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/nvmem/sprd-efuse.txt b/Documentation/devicetree/bindings/nvmem/sprd-efuse.txt
deleted file mode 100644
index 96b6feec27f0..000000000000
--- a/Documentation/devicetree/bindings/nvmem/sprd-efuse.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-= Spreadtrum eFuse device tree bindings =
-
-Required properties:
-- compatible: Should be "sprd,ums312-efuse".
-- reg: Specify the address offset of efuse controller.
-- clock-names: Should be "enable".
-- clocks: The phandle and specifier referencing the controller's clock.
-- hwlocks: Reference to a phandle of a hwlock provider node.
-
-= Data cells =
-Are child nodes of eFuse, bindings of which as described in
-bindings/nvmem/nvmem.txt
-
-Example:
-
- ap_efuse: efuse@32240000 {
- compatible = "sprd,ums312-efuse";
- reg = <0 0x32240000 0 0x10000>;
- clock-names = "enable";
- hwlocks = <&hwlock 8>;
- clocks = <&aonapb_gate CLK_EFUSE_EB>;
-
- /* Data cells */
- thermal_calib: calib@10 {
- reg = <0x10 0x2>;
- };
- };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells.
-
-Example:
-
- thermal {
- ...
-
- nvmem-cells = <&thermal_calib>;
- nvmem-cell-names = "calibration";
- };
diff --git a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt
deleted file mode 100644
index 0df79d9e07ec..000000000000
--- a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-Zodiac Inflight Innovations RAVE EEPROM Bindings
-
-RAVE SP EEPROM device is a "MFD cell" device exposing physical EEPROM
-attached to RAVE Supervisory Processor. It is expected that its Device
-Tree node is specified as a child of the node corresponding to the
-parent RAVE SP device (as documented in
-Documentation/devicetree/bindings/mfd/zii,rave-sp.txt)
-
-Required properties:
-
-- compatible: Should be "zii,rave-sp-eeprom"
-
-Optional properties:
-
-- zii,eeprom-name: Unique EEPROM identifier describing its function in the
- system. Will be used as created NVMEM deivce's name.
-
-Data cells:
-
-Data cells are child nodes of eerpom node, bindings for which are
-documented in Documentation/devicetree/bindings/nvmem/nvmem.txt
-
-Example:
-
- rave-sp {
- compatible = "zii,rave-sp-rdu1";
- current-speed = <38400>;
-
- eeprom@a4 {
- compatible = "zii,rave-sp-eeprom";
- reg = <0xa4 0x4000>;
- #address-cells = <1>;
- #size-cells = <1>;
- zii,eeprom-name = "main-eeprom";
-
- wdt_timeout: wdt-timeout@81 {
- reg = <0x81 2>;
- };
- };
- }
diff --git a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml
new file mode 100644
index 000000000000..d073c51c2b9a
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/zii,rave-sp-eeprom.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zodiac Inflight Innovations RAVE EEPROM
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+
+description:
+ RAVE SP EEPROM device is a "MFD cell" device exposing physical EEPROM
+ attached to RAVE Supervisory Processor. It is expected that its Device
+ Tree node is specified as a child of the node corresponding to the
+ parent RAVE SP device (as documented in
+ Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml)
+
+properties:
+ compatible:
+ const: zii,rave-sp-eeprom
+
+ reg:
+ maxItems: 1
+
+ zii,eeprom-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ Unique EEPROM identifier describing its function in the
+ system. Will be used as created NVMEM deivce's name.
+
+required:
+ - compatible
+
+allOf:
+ - $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ eeprom@a4 {
+ compatible = "zii,rave-sp-eeprom";
+ reg = <0xa4 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ zii,eeprom-name = "main-eeprom";
+
+ wdt-timeout@81 {
+ reg = <0x81 2>;
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/opp/operating-points-v2-ti-cpu.yaml b/Documentation/devicetree/bindings/opp/operating-points-v2-ti-cpu.yaml
index fd0c8d5c5f3e..624d1f3f1382 100644
--- a/Documentation/devicetree/bindings/opp/operating-points-v2-ti-cpu.yaml
+++ b/Documentation/devicetree/bindings/opp/operating-points-v2-ti-cpu.yaml
@@ -45,7 +45,25 @@ patternProperties:
clock-latency-ns: true
opp-hz: true
opp-microvolt: true
- opp-supported-hw: true
+ opp-supported-hw:
+ items:
+ items:
+ - description:
+ The revision of the SoC the OPP is supported by.
+ This can be easily obtained from the datasheet of the
+ part being ordered/used. For example, it will be 0x01 for SR1.0
+
+ - description:
+ The eFuse bits that indicate the particular OPP is available.
+ The device datasheet has a table talking about Device Speed Grades.
+ This table is to be sorted with only the unique elements of the
+ MAXIMUM OPERATING FREQUENCY starting from the first row which
+ tells the lowest OPP, to the highest. The corresponding bits
+ need to be set based on N elements of speed grade the device supports.
+ So, if there are 3 possible unique MAXIMUM OPERATING FREQUENCY
+ in the table, then BIT(0) | (1) | (2) will be set, which means
+ the value shall be 0x7.
+
opp-suspend: true
turbo-mode: true
diff --git a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
index 0925c520195a..2ad1652c2584 100644
--- a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
@@ -92,9 +92,8 @@ properties:
may have two component regions -- base and extended -- so
this information cannot be deduced from the dma-ranges.
$ref: /schemas/types.yaml#/definitions/uint64-array
- items:
- minItems: 1
- maxItems: 3
+ minItems: 1
+ maxItems: 3
resets:
minItems: 1
diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
index 898c1be2d6a4..f05aab2b1add 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
@@ -149,7 +149,7 @@ allOf:
then:
properties:
clocks:
- minItems: 4
+ minItems: 6
clock-names:
items:
@@ -178,7 +178,7 @@ allOf:
then:
properties:
clocks:
- minItems: 4
+ minItems: 6
clock-names:
items:
@@ -207,6 +207,7 @@ allOf:
properties:
clocks:
minItems: 4
+ maxItems: 4
clock-names:
items:
diff --git a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
index 612633ba59e2..2e1547569702 100644
--- a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
+++ b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
@@ -17,6 +17,12 @@ properties:
compatible:
const: microchip,pcie-host-1.0 # PolarFire
+ reg:
+ minItems: 3
+
+ reg-names:
+ minItems: 3
+
clocks:
description:
Fabric Interface Controllers, FICs, are the interface between the FPGA
@@ -62,8 +68,9 @@ examples:
pcie0: pcie@2030000000 {
compatible = "microchip,pcie-host-1.0";
reg = <0x0 0x70000000 0x0 0x08000000>,
- <0x0 0x43000000 0x0 0x00010000>;
- reg-names = "cfg", "apb";
+ <0x0 0x43008000 0x0 0x00002000>,
+ <0x0 0x4300a000 0x0 0x00002000>;
+ reg-names = "cfg", "bridge", "ctrl";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
diff --git a/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
index 7a57a80052a0..039eecdbd6aa 100644
--- a/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
+++ b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
@@ -18,12 +18,18 @@ allOf:
properties:
reg:
- maxItems: 2
+ maxItems: 3
+ minItems: 2
reg-names:
- items:
- - const: cfg
- - const: apb
+ oneOf:
+ - items:
+ - const: cfg
+ - const: apb
+ - items:
+ - const: cfg
+ - const: bridge
+ - const: ctrl
interrupts:
minItems: 1
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml
index e18900c41576..0480c58f7d99 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml
@@ -81,6 +81,10 @@ properties:
vddpe-3v3-supply:
description: PCIe endpoint power supply
+ operating-points-v2: true
+ opp-table:
+ type: object
+
required:
- reg
- reg-names
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml
index 46bd59eefadb..6e0a6d8f0ed0 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml
@@ -70,10 +70,6 @@ properties:
- const: msi7
- const: global
- operating-points-v2: true
- opp-table:
- type: object
-
resets:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml
index 24cb38673581..2b5498a35dcc 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml
@@ -20,6 +20,7 @@ properties:
- const: qcom,pcie-sm8550
- items:
- enum:
+ - qcom,sar2130p-pcie
- qcom,pcie-sm8650
- const: qcom,pcie-sm8550
@@ -39,7 +40,7 @@ properties:
clocks:
minItems: 7
- maxItems: 8
+ maxItems: 9
clock-names:
minItems: 7
@@ -52,6 +53,7 @@ properties:
- const: ddrss_sf_tbu # PCIe SF TBU clock
- const: noc_aggr # Aggre NoC PCIe AXI clock
- const: cnoc_sf_axi # Config NoC PCIe1 AXI clock
+ - const: qmip_pcie_ahb # QMIP PCIe AHB clock
interrupts:
minItems: 8
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml
index a9db0a231563..257068a18264 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml
@@ -47,9 +47,10 @@ properties:
interrupts:
minItems: 8
- maxItems: 8
+ maxItems: 9
interrupt-names:
+ minItems: 8
items:
- const: msi0
- const: msi1
@@ -59,6 +60,7 @@ properties:
- const: msi5
- const: msi6
- const: msi7
+ - const: global
resets:
minItems: 1
@@ -130,9 +132,10 @@ examples:
<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 148 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0", "msi1", "msi2", "msi3",
- "msi4", "msi5", "msi6", "msi7";
+ "msi4", "msi5", "msi6", "msi7", "global";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc 0 0 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
index ffabbac57fc1..bd87f6b49d68 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
@@ -26,6 +26,7 @@ properties:
- qcom,pcie-ipq8064-v2
- qcom,pcie-ipq8074
- qcom,pcie-ipq8074-gen3
+ - qcom,pcie-ipq9574
- qcom,pcie-msm8996
- qcom,pcie-qcs404
- qcom,pcie-sdm845
@@ -164,6 +165,7 @@ allOf:
enum:
- qcom,pcie-ipq6018
- qcom,pcie-ipq8074-gen3
+ - qcom,pcie-ipq9574
then:
properties:
reg:
@@ -405,6 +407,53 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pcie-ipq9574
+ then:
+ properties:
+ clocks:
+ minItems: 6
+ maxItems: 6
+ clock-names:
+ items:
+ - const: axi_m # AXI Master clock
+ - const: axi_s # AXI Slave clock
+ - const: axi_bridge
+ - const: rchng
+ - const: ahb
+ - const: aux
+
+ resets:
+ minItems: 8
+ maxItems: 8
+ reset-names:
+ items:
+ - const: pipe # PIPE reset
+ - const: sticky # Core Sticky reset
+ - const: axi_s_sticky # AXI Slave Sticky reset
+ - const: axi_s # AXI Slave reset
+ - const: axi_m_sticky # AXI Master Sticky reset
+ - const: axi_m # AXI Master reset
+ - const: aux # AUX Reset
+ - const: ahb # AHB Reset
+
+ interrupts:
+ minItems: 8
+ interrupt-names:
+ items:
+ - const: msi0
+ - const: msi1
+ - const: msi2
+ - const: msi3
+ - const: msi4
+ - const: msi5
+ - const: msi6
+ - const: msi7
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,pcie-qcs404
then:
properties:
@@ -510,6 +559,7 @@ allOf:
- qcom,pcie-ipq8064v2
- qcom,pcie-ipq8074
- qcom,pcie-ipq8074-gen3
+ - qcom,pcie-ipq9574
- qcom,pcie-qcs404
then:
required:
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
index 548f59d76ef2..205326fb2d75 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
@@ -230,7 +230,6 @@ examples:
interrupts = <25>, <24>;
interrupt-names = "msi", "hp";
- #interrupt-cells = <1>;
reset-gpios = <&port0 0 1>;
diff --git a/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml b/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
index 67151aaa3948..5f432452c815 100644
--- a/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
@@ -16,6 +16,13 @@ properties:
compatible:
const: starfive,jh7110-pcie
+
+ reg:
+ maxItems: 2
+
+ reg-names:
+ maxItems: 2
+
clocks:
items:
- description: NOC bus clock
diff --git a/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml b/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
index 37e8b98f2cdc..8597ea625edb 100644
--- a/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
+++ b/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
@@ -31,7 +31,9 @@ properties:
- const: fsl,imx8dxl-ddr-pmu
- const: fsl,imx8-ddr-pmu
- items:
- - const: fsl,imx95-ddr-pmu
+ - enum:
+ - fsl,imx91-ddr-pmu
+ - fsl,imx95-ddr-pmu
- const: fsl,imx93-ddr-pmu
reg:
diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
index f557feca9763..21209126ed00 100644
--- a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml
@@ -15,9 +15,13 @@ properties:
const: 1
compatible:
- enum:
- - allwinner,sun20i-d1-usb-phy
- - allwinner,sun50i-a64-usb-phy
+ oneOf:
+ - enum:
+ - allwinner,sun20i-d1-usb-phy
+ - allwinner,sun50i-a64-usb-phy
+ - items:
+ - const: allwinner,sun50i-a100-usb-phy
+ - const: allwinner,sun20i-d1-usb-phy
reg:
items:
diff --git a/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.yaml
index 426101530a21..d72c02ab55ae 100644
--- a/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.yaml
@@ -18,16 +18,8 @@ properties:
const: brcm,ns-usb2-phy
reg:
- anyOf:
- - maxItems: 1
- description: PHY control register
- - maxItems: 1
- description: iomem address range of DMU (Device Management Unit)
- deprecated: true
-
- reg-names:
- items:
- - const: dmu
+ maxItems: 1
+ description: PHY control register
brcm,syscon-clkset:
description: phandle to syscon for clkset register
@@ -50,12 +42,7 @@ required:
- clocks
- clock-names
- "#phy-cells"
-
-oneOf:
- - required:
- - brcm,syscon-clkset
- - required:
- - reg-names
+ - brcm,syscon-clkset
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
index dc3a3f709fea..6d6d211883ae 100644
--- a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
@@ -11,12 +11,17 @@ maintainers:
properties:
compatible:
- enum:
- - fsl,imx8mq-usb-phy
- - fsl,imx8mp-usb-phy
+ oneOf:
+ - enum:
+ - fsl,imx8mq-usb-phy
+ - fsl,imx8mp-usb-phy
+ - items:
+ - const: fsl,imx95-usb-phy
+ - const: fsl,imx8mp-usb-phy
reg:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
"#phy-cells":
const: 0
@@ -89,7 +94,34 @@ required:
- clocks
- clock-names
-additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx95-usb-phy
+ then:
+ properties:
+ reg:
+ items:
+ - description: USB PHY Control range
+ - description: USB PHY TCA Block range
+ else:
+ properties:
+ reg:
+ maxItems: 1
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx95-usb-phy
+ then:
+ $ref: /schemas/usb/usb-switch.yaml#
+
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml b/Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml
index ce665a2779b7..d01b7d187040 100644
--- a/Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml
+++ b/Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml
@@ -32,6 +32,7 @@ properties:
- enum:
- fsl,imx8dxl-usbphy
- fsl,imx8qm-usbphy
+ - fsl,imx8qxp-usbphy
- fsl,imx8ulp-usbphy
- const: fsl,imx7ulp-usbphy
diff --git a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
index 423b7c4e62f2..6be3aa4557e5 100644
--- a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
+++ b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
@@ -125,6 +125,16 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
default: 28
+ power-domains:
+ description:
+ The TPHY of MediaTek should exist within a power domain. The
+ developer should be aware that the hardware design of MediaTek TPHY
+ does not require the addition of MTCMOS. If the power to the TPHY
+ is turned off, it will impact other functions. From the current
+ perspective of USB hardware design, even if MTCMOS is added to the
+ TPHY, it should remain always on.
+ maxItems: 1
+
# Required child node:
patternProperties:
"^(usb|pcie|sata)-phy@[0-9a-f]+$":
diff --git a/Documentation/devicetree/bindings/phy/microchip,sparx5-serdes.yaml b/Documentation/devicetree/bindings/phy/microchip,sparx5-serdes.yaml
index bdbdb3bbddbe..fa0b02916dac 100644
--- a/Documentation/devicetree/bindings/phy/microchip,sparx5-serdes.yaml
+++ b/Documentation/devicetree/bindings/phy/microchip,sparx5-serdes.yaml
@@ -8,6 +8,7 @@ title: Microchip Sparx5 Serdes controller
maintainers:
- Steen Hegelund <steen.hegelund@microchip.com>
+ - Daniel Machon <daniel.machon@microchip.com>
description: |
The Sparx5 SERDES interfaces share the same basic functionality, but
@@ -62,12 +63,26 @@ description: |
* 10.3125 Gbps (10GBASE-R/10GBASE-KR/USXGMII)
* 25.78125 Gbps (25GBASE-KR/25GBASE-CR/25GBASE-SR/25GBASE-LR/25GBASE-ER)
+ lan969x has ten SERDES10G interfaces that share the same features, operating
+ modes and data rates as the equivalent Sparx5 SERDES10G interfaces.
+
properties:
$nodename:
pattern: "^serdes@[0-9a-f]+$"
compatible:
- const: microchip,sparx5-serdes
+ oneOf:
+ - enum:
+ - microchip,sparx5-serdes
+ - microchip,lan9691-serdes
+ - items:
+ - enum:
+ - microchip,lan9698-serdes
+ - microchip,lan9696-serdes
+ - microchip,lan9694-serdes
+ - microchip,lan9693-serdes
+ - microchip,lan9692-serdes
+ - const: microchip,lan9691-serdes
reg:
minItems: 1
diff --git a/Documentation/devicetree/bindings/phy/nxp,ptn3222.yaml b/Documentation/devicetree/bindings/phy/nxp,ptn3222.yaml
new file mode 100644
index 000000000000..acec5bb2391d
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/nxp,ptn3222.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/nxp,ptn3222.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PTN3222 1-port eUSB2 to USB2 redriver
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+properties:
+ compatible:
+ enum:
+ - nxp,ptn3222
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ const: 0
+
+ vdd1v8-supply:
+ description: power supply (1.8V)
+
+ vdd3v3-supply:
+ description: power supply (3.3V)
+
+ reset-gpios: true
+
+required:
+ - compatible
+ - reg
+ - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ redriver@4f {
+ compatible = "nxp,ptn3222";
+ reg = <0x4f>;
+ #phy-cells = <0>;
+ vdd3v3-supply = <&vreg_3p3>;
+ vdd1v8-supply = <&vreg_1p8>;
+ reset-gpios = <&gpio_reset GPIO_ACTIVE_LOW>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
index 37f028f7a095..137ac5703853 100644
--- a/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
@@ -96,7 +96,7 @@ patternProperties:
Specifies the type of PHY for which the group of PHY lanes is used.
Refer include/dt-bindings/phy/phy.h. Constants from the header should be used.
$ref: /schemas/types.yaml#/definitions/uint32
- enum: [2, 4]
+ enum: [2, 4, 8, 9]
cdns,num-lanes:
description:
diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-hdmi.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-hdmi.txt
deleted file mode 100644
index 710cccd5ee56..000000000000
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-hdmi.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-ROCKCHIP HDMI PHY WITH INNO IP BLOCK
-
-Required properties:
- - compatible : should be one of the listed compatibles:
- * "rockchip,rk3228-hdmi-phy",
- * "rockchip,rk3328-hdmi-phy";
- - reg : Address and length of the hdmi phy control register set
- - clocks : phandle + clock specifier for the phy clocks
- - clock-names : string, clock name, must contain "sysclk" for system
- control and register configuration, "refoclk" for crystal-
- oscillator reference PLL clock input and "refpclk" for pclk-
- based refeference PLL clock input.
- - #clock-cells: should be 0.
- - clock-output-names : shall be the name for the output clock.
- - interrupts : phandle + interrupt specified for the hdmiphy interrupt
- - #phy-cells : must be 0. See ./phy-bindings.txt for details.
-
-Optional properties for rk3328-hdmi-phy:
- - nvmem-cells = phandle + nvmem specifier for the cpu-version efuse
- - nvmem-cell-names : "cpu-version" to read the chip version, required
- for adjustment to some frequency settings
-
-Example:
- hdmi_phy: hdmi-phy@12030000 {
- compatible = "rockchip,rk3228-hdmi-phy";
- reg = <0x12030000 0x10000>;
- #phy-cells = <0>;
- clocks = <&cru PCLK_HDMI_PHY>, <&xin24m>, <&cru DCLK_HDMIPHY>;
- clock-names = "sysclk", "refoclk", "refpclk";
- #clock-cells = <0>;
- clock-output-names = "hdmi_phy";
- status = "disabled";
- };
-
-Then the PHY can be used in other nodes such as:
-
- hdmi: hdmi@200a0000 {
- compatible = "rockchip,rk3228-dw-hdmi";
- ...
- phys = <&hdmi_phy>;
- phy-names = "hdmi";
- ...
- };
diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
index 1f1f8863b80d..b42f1272903d 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
@@ -13,6 +13,7 @@ maintainers:
properties:
compatible:
enum:
+ - rockchip,rk3576-usbdp-phy
- rockchip,rk3588-usbdp-phy
reg:
diff --git a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
index 4e15d90d08b0..293fb6a9b1c3 100644
--- a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
@@ -17,6 +17,7 @@ description:
properties:
compatible:
enum:
+ - qcom,sa8775p-edp-phy
- qcom,sc7280-edp-phy
- qcom,sc8180x-edp-phy
- qcom,sc8280xp-dp-phy
diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml
index f1f4e4f83352..1636285fbe53 100644
--- a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml
@@ -18,6 +18,7 @@ properties:
enum:
- qcom,msm8998-qmp-usb3-phy
- qcom,qcm2290-qmp-usb3-phy
+ - qcom,qcs615-qmp-usb3-phy
- qcom,sdm660-qmp-usb3-phy
- qcom,sm6115-qmp-usb3-phy
@@ -96,6 +97,7 @@ allOf:
contains:
enum:
- qcom,msm8998-qmp-usb3-phy
+ - qcom,qcs615-qmp-usb3-phy
- qcom,sdm660-qmp-usb3-phy
then:
properties:
diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
index 95eecbaef05c..4aed4b5d65ec 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
@@ -25,6 +25,7 @@ properties:
- qcom,msm8996-qusb2-phy
- qcom,msm8998-qusb2-phy
- qcom,qcm2290-qusb2-phy
+ - qcom,qcs615-qusb2-phy
- qcom,sdm660-qusb2-phy
- qcom,sm4250-qusb2-phy
- qcom,sm6115-qusb2-phy
diff --git a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml
index b9107759b2a5..90fc8c039219 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml
@@ -15,7 +15,12 @@ description:
properties:
compatible:
- const: qcom,sa8775p-dwmac-sgmii-phy
+ oneOf:
+ - items:
+ - enum:
+ - qcom,qcs8300-dwmac-sgmii-phy
+ - const: qcom,sa8775p-dwmac-sgmii-phy
+ - const: qcom,sa8775p-dwmac-sgmii-phy
reg:
items:
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
index 380a9222a51d..13fdf5f1beba 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
@@ -41,6 +41,7 @@ properties:
- qcom,x1e80100-qmp-gen3x2-pcie-phy
- qcom,x1e80100-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen4x4-pcie-phy
+ - qcom,x1e80100-qmp-gen4x8-pcie-phy
reg:
minItems: 1
@@ -172,6 +173,7 @@ allOf:
- qcom,x1e80100-qmp-gen3x2-pcie-phy
- qcom,x1e80100-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen4x4-pcie-phy
+ - qcom,x1e80100-qmp-gen4x8-pcie-phy
then:
properties:
clocks:
@@ -202,6 +204,7 @@ allOf:
- qcom,sm8650-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen4x4-pcie-phy
+ - qcom,x1e80100-qmp-gen4x8-pcie-phy
then:
properties:
resets:
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
index f9cfbd0b2de6..72bed2933b03 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml
@@ -15,26 +15,35 @@ description:
properties:
compatible:
- enum:
- - qcom,msm8996-qmp-ufs-phy
- - qcom,msm8998-qmp-ufs-phy
- - qcom,sa8775p-qmp-ufs-phy
- - qcom,sc7180-qmp-ufs-phy
- - qcom,sc7280-qmp-ufs-phy
- - qcom,sc8180x-qmp-ufs-phy
- - qcom,sc8280xp-qmp-ufs-phy
- - qcom,sdm845-qmp-ufs-phy
- - qcom,sm6115-qmp-ufs-phy
- - qcom,sm6125-qmp-ufs-phy
- - qcom,sm6350-qmp-ufs-phy
- - qcom,sm7150-qmp-ufs-phy
- - qcom,sm8150-qmp-ufs-phy
- - qcom,sm8250-qmp-ufs-phy
- - qcom,sm8350-qmp-ufs-phy
- - qcom,sm8450-qmp-ufs-phy
- - qcom,sm8475-qmp-ufs-phy
- - qcom,sm8550-qmp-ufs-phy
- - qcom,sm8650-qmp-ufs-phy
+ oneOf:
+ - items:
+ - enum:
+ - qcom,qcs615-qmp-ufs-phy
+ - const: qcom,sm6115-qmp-ufs-phy
+ - items:
+ - enum:
+ - qcom,qcs8300-qmp-ufs-phy
+ - const: qcom,sa8775p-qmp-ufs-phy
+ - enum:
+ - qcom,msm8996-qmp-ufs-phy
+ - qcom,msm8998-qmp-ufs-phy
+ - qcom,sa8775p-qmp-ufs-phy
+ - qcom,sc7180-qmp-ufs-phy
+ - qcom,sc7280-qmp-ufs-phy
+ - qcom,sc8180x-qmp-ufs-phy
+ - qcom,sc8280xp-qmp-ufs-phy
+ - qcom,sdm845-qmp-ufs-phy
+ - qcom,sm6115-qmp-ufs-phy
+ - qcom,sm6125-qmp-ufs-phy
+ - qcom,sm6350-qmp-ufs-phy
+ - qcom,sm7150-qmp-ufs-phy
+ - qcom,sm8150-qmp-ufs-phy
+ - qcom,sm8250-qmp-ufs-phy
+ - qcom,sm8350-qmp-ufs-phy
+ - qcom,sm8450-qmp-ufs-phy
+ - qcom,sm8475-qmp-ufs-phy
+ - qcom,sm8550-qmp-ufs-phy
+ - qcom,sm8650-qmp-ufs-phy
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
index 0e0b6cae07bc..baf5134ea3d8 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml
@@ -20,6 +20,7 @@ properties:
- qcom,ipq8074-qmp-usb3-phy
- qcom,ipq9574-qmp-usb3-phy
- qcom,msm8996-qmp-usb3-phy
+ - qcom,qcs8300-qmp-usb3-uni-phy
- qcom,qdu1000-qmp-usb3-uni-phy
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8180x-qmp-usb3-uni-phy
@@ -111,6 +112,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,qcs8300-qmp-usb3-uni-phy
- qcom,qdu1000-qmp-usb3-uni-phy
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8180x-qmp-usb3-uni-phy
diff --git a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
index b82f7f5731ed..142b3c8839d6 100644
--- a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml
@@ -17,6 +17,7 @@ properties:
oneOf:
- items:
- enum:
+ - qcom,sar2130p-snps-eusb2-phy
- qcom,sdx75-snps-eusb2-phy
- qcom,sm8650-snps-eusb2-phy
- qcom,x1e80100-snps-eusb2-phy
diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
index 519c2b403f66..661759b25064 100644
--- a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml
@@ -22,6 +22,7 @@ properties:
- const: qcom,usb-snps-hs-5nm-phy
- items:
- enum:
+ - qcom,qcs8300-usb-hs-phy
- qcom,qdu1000-usb-hs-phy
- qcom,sc7280-usb-hs-phy
- qcom,sc8180x-usb-hs-phy
diff --git a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
index 5254413137c6..6a7ef556414c 100644
--- a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
+++ b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
@@ -20,6 +20,7 @@ properties:
- rockchip,rk3366-usb2phy
- rockchip,rk3399-usb2phy
- rockchip,rk3568-usb2phy
+ - rockchip,rk3576-usb2phy
- rockchip,rk3588-usb2phy
- rockchip,rv1108-usb2phy
@@ -34,10 +35,15 @@ properties:
const: 0
clocks:
- maxItems: 1
+ minItems: 1
+ maxItems: 3
clock-names:
- const: phyclk
+ minItems: 1
+ items:
+ - const: phyclk
+ - const: aclk
+ - const: aclk_slv
assigned-clocks:
description:
@@ -172,6 +178,41 @@ allOf:
- interrupts
- interrupt-names
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,px30-usb2phy
+ - rockchip,rk3128-usb2phy
+ - rockchip,rk3228-usb2phy
+ - rockchip,rk3308-usb2phy
+ - rockchip,rk3328-usb2phy
+ - rockchip,rk3366-usb2phy
+ - rockchip,rk3399-usb2phy
+ - rockchip,rk3568-usb2phy
+ - rockchip,rk3588-usb2phy
+ - rockchip,rv1108-usb2phy
+ then:
+ properties:
+ clocks:
+ maxItems: 1
+ clock-names:
+ maxItems: 1
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,rk3576-usb2phy
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ clock-names:
+ minItems: 3
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/phy/rockchip,rk3228-hdmi-phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,rk3228-hdmi-phy.yaml
new file mode 100644
index 000000000000..ac15bf857ef9
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/rockchip,rk3228-hdmi-phy.yaml
@@ -0,0 +1,97 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/rockchip,rk3228-hdmi-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip HDMI PHY with Innosilicon IP block
+
+maintainers:
+ - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+ compatible:
+ enum:
+ - rockchip,rk3228-hdmi-phy
+ - rockchip,rk3328-hdmi-phy
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 3
+
+ clock-names:
+ items:
+ - const: sysclk
+ - const: refoclk
+ - const: refpclk
+
+ clock-output-names:
+ description:
+ The hdmiphy output clock name, that gets fed back to the CRU.
+
+ "#clock-cells":
+ const: 0
+
+ interrupts:
+ maxItems: 1
+
+ nvmem-cells:
+ maxItems: 1
+ description: A phandle + nvmem specifier for the cpu-version efuse
+ for adjustment to some frequency settings, depending on cpu-version
+
+ nvmem-cell-names:
+ items:
+ - const: cpu-version
+
+ '#phy-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - clock-output-names
+ - '#clock-cells'
+ - '#phy-cells'
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3228-hdmi-phy
+
+ then:
+ properties:
+ interrupts: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3328-hdmi-phy
+
+ then:
+ required:
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+
+ #include <dt-bindings/clock/rk3228-cru.h>
+ hdmi_phy: phy@12030000 {
+ compatible = "rockchip,rk3228-hdmi-phy";
+ reg = <0x12030000 0x10000>;
+ #phy-cells = <0>;
+ clocks = <&cru PCLK_HDMI_PHY>, <&xin24m>, <&cru DCLK_HDMI_PHY>;
+ clock-names = "sysclk", "refoclk", "refpclk";
+ #clock-cells = <0>;
+
+ clock-output-names = "hdmi_phy";
+ };
diff --git a/Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml b/Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml
new file mode 100644
index 000000000000..a2e82c0bb56b
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml
@@ -0,0 +1,119 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/st,stm32mp25-combophy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STM32MP25 USB3/PCIe COMBOPHY
+
+maintainers:
+ - Christian Bruel <christian.bruel@foss.st.com>
+
+description:
+ Single lane PHY shared (exclusive) between the USB3 and PCIe controllers.
+ Supports 5Gbit/s for USB3 and PCIe gen2 or 2.5Gbit/s for PCIe gen1.
+
+properties:
+ compatible:
+ const: st,stm32mp25-combophy
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ const: 1
+
+ clocks:
+ minItems: 2
+ items:
+ - description: apb Bus clock mandatory to access registers.
+ - description: ker Internal RCC reference clock for USB3 or PCIe
+ - description: pad Optional on board clock input for PCIe only. Typically an
+ external 100Mhz oscillator wired on dedicated CLKIN pad. Used as reference
+ clock input instead of the ker
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: apb
+ - const: ker
+ - const: pad
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ const: phy
+
+ power-domains:
+ maxItems: 1
+
+ wakeup-source: true
+
+ interrupts:
+ maxItems: 1
+ description: interrupt used for wakeup
+
+ access-controllers:
+ maxItems: 1
+ description: Phandle to the rifsc device to check access right.
+
+ st,ssc-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ A property whose presence indicates that the Spread Spectrum Clocking is active.
+
+ st,rx-equalizer:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+ default: 2
+ description:
+ A 3 bit value to tune the RX fixed equalizer setting for optimal eye compliance
+
+ st,output-micro-ohms:
+ minimum: 3999000
+ maximum: 6090000
+ default: 4968000
+ description:
+ A value property to tune the Single Ended Output Impedance, simulations results
+ at 25C for a VDDP=0.8V. The hardware accepts discrete values in this range.
+
+ st,output-vswing-microvolt:
+ minimum: 442000
+ maximum: 803000
+ default: 803000
+ description:
+ A value property in microvolt to tune the Single Ended Output Voltage Swing to change the
+ Vlo, Vhi for a VDDP = 0.8V. The hardware accepts discrete values in this range.
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/st,stm32mp25-rcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/reset/st,stm32mp25-rcc.h>
+
+ phy@480c0000 {
+ compatible = "st,stm32mp25-combophy";
+ reg = <0x480c0000 0x1000>;
+ #phy-cells = <1>;
+ clocks = <&rcc CK_BUS_USB3PCIEPHY>, <&rcc CK_KER_USB3PCIEPHY>;
+ clock-names = "apb", "ker";
+ resets = <&rcc USB3PCIEPHY_R>;
+ reset-names = "phy";
+ access-controllers = <&rifsc 67>;
+ power-domains = <&CLUSTER_PD>;
+ wakeup-source;
+ interrupts-extended = <&exti1 45 IRQ_TYPE_EDGE_FALLING>;
+ };
diff --git a/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml b/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
index 79dad3e89aa6..4a8c3829d85d 100644
--- a/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
+++ b/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
@@ -14,10 +14,15 @@ properties:
pattern: "^can-phy"
compatible:
- enum:
- - nxp,tjr1443
- - ti,tcan1042
- - ti,tcan1043
+ oneOf:
+ - items:
+ - enum:
+ - microchip,ata6561
+ - const: ti,tcan1042
+ - enum:
+ - ti,tcan1042
+ - ti,tcan1043
+ - nxp,tjr1443
'#phy-cells':
const: 0
diff --git a/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
new file mode 100644
index 000000000000..b2601d698dcd
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
@@ -0,0 +1,400 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/airoha,en7581-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha EN7581 Pin Controller
+
+maintainers:
+ - Lorenzo Bianconi <lorenzo@kernel.org>
+
+description:
+ The Airoha's EN7581 Pin controller is used to control SoC pins.
+
+properties:
+ compatible:
+ const: airoha,en7581-pinctrl
+
+ interrupts:
+ maxItems: 1
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+allOf:
+ - $ref: pinctrl.yaml#
+
+required:
+ - compatible
+ - interrupts
+ - gpio-controller
+ - "#gpio-cells"
+ - interrupt-controller
+ - "#interrupt-cells"
+
+patternProperties:
+ '-pins$':
+ type: object
+
+ patternProperties:
+ '^mux(-|$)':
+ type: object
+
+ description:
+ pinmux configuration nodes.
+
+ $ref: /schemas/pinctrl/pinmux-node.yaml
+
+ properties:
+ function:
+ description:
+ A string containing the name of the function to mux to the group.
+ enum: [pon, tod_1pps, sipo, mdio, uart, i2c, jtag, pcm, spi,
+ pcm_spi, i2s, emmc, pnand, pcie_reset, pwm, phy1_led0,
+ phy2_led0, phy3_led0, phy4_led0, phy1_led1, phy2_led1,
+ phy3_led1, phy4_led1]
+
+ groups:
+ description:
+ An array of strings. Each string contains the name of a group.
+
+ required:
+ - function
+ - groups
+
+ allOf:
+ - if:
+ properties:
+ function:
+ const: pon
+ then:
+ properties:
+ groups:
+ enum: [pon]
+ - if:
+ properties:
+ function:
+ const: tod_1pps
+ then:
+ properties:
+ groups:
+ enum: [pon_tod_1pps, gsw_tod_1pps]
+ - if:
+ properties:
+ function:
+ const: sipo
+ then:
+ properties:
+ groups:
+ enum: [sipo, sipo_rclk]
+ - if:
+ properties:
+ function:
+ const: mdio
+ then:
+ properties:
+ groups:
+ enum: [mdio]
+ - if:
+ properties:
+ function:
+ const: uart
+ then:
+ properties:
+ groups:
+ items:
+ enum: [uart2, uart2_cts_rts, hsuart, hsuart_cts_rts,
+ uart4, uart5]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: i2c
+ then:
+ properties:
+ groups:
+ enum: [i2c1]
+ - if:
+ properties:
+ function:
+ const: jtag
+ then:
+ properties:
+ groups:
+ enum: [jtag_udi, jtag_dfd]
+ - if:
+ properties:
+ function:
+ const: pcm
+ then:
+ properties:
+ groups:
+ enum: [pcm1, pcm2]
+ - if:
+ properties:
+ function:
+ const: spi
+ then:
+ properties:
+ groups:
+ items:
+ enum: [spi_quad, spi_cs1]
+ maxItems: 2
+ - if:
+ properties:
+ function:
+ const: pcm_spi
+ then:
+ properties:
+ groups:
+ items:
+ enum: [pcm_spi, pcm_spi_int, pcm_spi_rst, pcm_spi_cs1,
+ pcm_spi_cs2_p156, pcm_spi_cs2_p128, pcm_spi_cs3,
+ pcm_spi_cs4]
+ maxItems: 7
+ - if:
+ properties:
+ function:
+ const: i2c
+ then:
+ properties:
+ groups:
+ enum: [i2s]
+ - if:
+ properties:
+ function:
+ const: emmc
+ then:
+ properties:
+ groups:
+ enum: [emmc]
+ - if:
+ properties:
+ function:
+ const: pnand
+ then:
+ properties:
+ groups:
+ enum: [pnand]
+ - if:
+ properties:
+ function:
+ const: pcie_reset
+ then:
+ properties:
+ groups:
+ enum: [pcie_reset0, pcie_reset1, pcie_reset2]
+ - if:
+ properties:
+ function:
+ const: pwm
+ then:
+ properties:
+ groups:
+ enum: [gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6,
+ gpio7, gpio8, gpio9, gpio10, gpio11, gpio12, gpio13,
+ gpio14, gpio15, gpio16, gpio17, gpio18, gpio19,
+ gpio20, gpio21, gpio22, gpio23, gpio24, gpio25,
+ gpio26, gpio27, gpio28, gpio29, gpio30, gpio31,
+ gpio36, gpio37, gpio38, gpio39, gpio40, gpio41,
+ gpio42, gpio43, gpio44, gpio45, gpio46, gpio47]
+ - if:
+ properties:
+ function:
+ const: phy1_led0
+ then:
+ properties:
+ groups:
+ enum: [gpio33, gpio34, gpio35, gpio42]
+ - if:
+ properties:
+ function:
+ const: phy2_led0
+ then:
+ properties:
+ groups:
+ enum: [gpio33, gpio34, gpio35, gpio42]
+ - if:
+ properties:
+ function:
+ const: phy3_led0
+ then:
+ properties:
+ groups:
+ enum: [gpio33, gpio34, gpio35, gpio42]
+ - if:
+ properties:
+ function:
+ const: phy4_led0
+ then:
+ properties:
+ groups:
+ enum: [gpio33, gpio34, gpio35, gpio42]
+ - if:
+ properties:
+ function:
+ const: phy1_led1
+ then:
+ properties:
+ groups:
+ enum: [gpio43, gpio44, gpio45, gpio46]
+ - if:
+ properties:
+ function:
+ const: phy2_led1
+ then:
+ properties:
+ groups:
+ enum: [gpio43, gpio44, gpio45, gpio46]
+ - if:
+ properties:
+ function:
+ const: phy3_led1
+ then:
+ properties:
+ groups:
+ enum: [gpio43, gpio44, gpio45, gpio46]
+ - if:
+ properties:
+ function:
+ const: phy4_led1
+ then:
+ properties:
+ groups:
+ enum: [gpio43, gpio44, gpio45, gpio46]
+
+ additionalProperties: false
+
+ '^conf(-|$)':
+ type: object
+
+ description:
+ pinconf configuration nodes.
+
+ $ref: /schemas/pinctrl/pincfg-node.yaml
+
+ properties:
+ pins:
+ description:
+ An array of strings. Each string contains the name of a pin.
+ items:
+ enum: [uart1_txd, uart1_rxd, i2c_scl, i2c_sda, spi_cs0, spi_clk,
+ spi_mosi, spi_miso, gpio0, gpio1, gpio2, gpio3, gpio4,
+ gpio5, gpio6, gpio7, gpio8, gpio9, gpio10, gpio11, gpio12,
+ gpio13, gpio14, gpio15, gpio16, gpio17, gpio18, gpio19,
+ gpio20, gpio21, gpio22, gpio23, gpio24, gpio25, gpio26,
+ gpio27, gpio28, gpio29, gpio30, gpio31, gpio32, gpio33,
+ gpio34, gpio35, gpio36, gpio37, gpio38, gpio39, gpio40,
+ gpio41, gpio42, gpio43, gpio44, gpio45, gpio46,
+ pcie_reset0, pcie_reset1, pcie_reset2]
+ minItems: 1
+ maxItems: 58
+
+ bias-disable: true
+
+ bias-pull-up: true
+
+ bias-pull-down: true
+
+ input-enable: true
+
+ output-enable: true
+
+ output-low: true
+
+ output-high: true
+
+ drive-open-drain: true
+
+ drive-strength:
+ description:
+ Selects the drive strength for MIO pins, in mA.
+ enum: [2, 4, 6, 8]
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+ additionalProperties: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pinctrl {
+ compatible = "airoha,en7581-pinctrl";
+
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ pcie1-rst-pins {
+ conf {
+ pins = "pcie_reset1";
+ drive-open-drain = <1>;
+ };
+ };
+
+ pwm-pins {
+ mux {
+ function = "pwm";
+ groups = "gpio18";
+ };
+ };
+
+ spi-pins {
+ mux {
+ function = "spi";
+ groups = "spi_quad", "spi_cs1";
+ };
+ };
+
+ uart2-pins {
+ mux {
+ function = "uart";
+ groups = "uart2", "uart2_cts_rts";
+ };
+ };
+
+ uar5-pins {
+ mux {
+ function = "uart";
+ groups = "uart5";
+ };
+ };
+
+ mmc-pins {
+ mux {
+ function = "emmc";
+ groups = "emmc";
+ };
+ };
+
+ mdio-pins {
+ mux {
+ function = "mdio";
+ groups = "mdio";
+ };
+
+ conf {
+ pins = "gpio2";
+ output-enable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/amlogic,meson8-pinctrl-cbus.yaml b/Documentation/devicetree/bindings/pinctrl/amlogic,meson8-pinctrl-cbus.yaml
index 412bbcc276f3..c954761e0150 100644
--- a/Documentation/devicetree/bindings/pinctrl/amlogic,meson8-pinctrl-cbus.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/amlogic,meson8-pinctrl-cbus.yaml
@@ -46,7 +46,7 @@ patternProperties:
- const: gpio
gpio-line-names:
- minItems: 86 # AXG
+ minItems: 83 # Meson8b
maxItems: 120 # Meson8
unevaluatedProperties:
diff --git a/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
index 9c07935919ea..63737d858944 100644
--- a/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
@@ -18,6 +18,11 @@ properties:
compatible:
items:
- enum:
+ - apple,s5l8960x-pinctrl
+ - apple,t7000-pinctrl
+ - apple,s8000-pinctrl
+ - apple,t8010-pinctrl
+ - apple,t8015-pinctrl
- apple,t8103-pinctrl
- apple,t8112-pinctrl
- apple,t6000-pinctrl
diff --git a/Documentation/devicetree/bindings/pinctrl/canaan,k230-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/canaan,k230-pinctrl.yaml
new file mode 100644
index 000000000000..0b462eb6dfe1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/canaan,k230-pinctrl.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/canaan,k230-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Canaan Kendryte K230 Pin Controller
+
+maintainers:
+ - Ze Huang <18771902331@163.com>
+
+description:
+ The Canaan Kendryte K230 platform includes 64 IO pins, each capable of
+ multiplexing up to 5 different functions. Pin function configuration is
+ performed on a per-pin basis.
+
+properties:
+ compatible:
+ const: canaan,k230-pinctrl
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ '-pins$':
+ type: object
+ additionalProperties: false
+ description:
+ A pinctrl node should contain at least one subnode representing the
+ pinctrl groups available on the machine.
+
+ patternProperties:
+ '-cfg$':
+ type: object
+ allOf:
+ - $ref: /schemas/pinctrl/pincfg-node.yaml
+ - $ref: /schemas/pinctrl/pinmux-node.yaml
+ additionalProperties: false
+ description:
+ Each subnode will list the pins it needs, and how they should
+ be configured, with regard to muxer configuration, bias, input
+ enable/disable, input schmitt trigger, slew-rate enable/disable,
+ slew-rate, drive strength.
+
+ properties:
+ pinmux:
+ description:
+ The list of GPIOs and their mux settings that properties in
+ the node apply to. This should be set with the macro
+ 'K230_PINMUX(pin, mode)'
+
+ bias-disable: true
+
+ bias-pull-up: true
+
+ bias-pull-down: true
+
+ drive-strength:
+ minimum: 0
+ maximum: 15
+
+ input-enable: true
+
+ output-enable: true
+
+ input-schmitt-enable: true
+
+ slew-rate:
+ description: |
+ slew rate control enable
+ 0: disable
+ 1: enable
+
+ enum: [0, 1]
+
+ power-source:
+ description: |
+ Specifies the power source voltage for the IO bank that the
+ pin belongs to. Each bank of IO pins operate at a specific,
+ fixed voltage levels. Incorrect voltage configuration can
+ damage the chip. The defined constants represent the
+ possible voltage configurations:
+
+ - K230_MSC_3V3 (value 0): 3.3V power supply
+ - K230_MSC_1V8 (value 1): 1.8V power supply
+
+ The following banks have the corresponding voltage
+ configurations:
+
+ - bank IO0 to IO1: Fixed at 1.8V
+ - bank IO2 to IO13: Fixed at 1.8V
+ - bank IO14 to IO25: Fixed at 1.8V
+ - bank IO26 to IO37: Fixed at 1.8V
+ - bank IO38 to IO49: Fixed at 1.8V
+ - bank IO50 to IO61: Fixed at 3.3V
+ - bank IO62 to IO63: Fixed at 1.8V
+
+ enum: [0, 1]
+
+ required:
+ - pinmux
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pinctrl@91105000 {
+ compatible = "canaan,k230-pinctrl";
+ reg = <0x91105000 0x100>;
+
+ uart2-pins {
+ uart2-pins-cfg {
+ pinmux = <0x503>, /* uart2 txd */
+ <0x603>; /* uart2 rxd */
+ slew-rate = <0>;
+ drive-strength = <4>;
+ power-source = <1>;
+ input-enable;
+ output-enable;
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
deleted file mode 100644
index c083dfd25db9..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-* Freescale IMX35 IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx35-iomuxc"
-- fsl,pins: two integers array, represents a group of pins mux and config
- setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
- pin working on a specific function, CONFIG is the pad setting value like
- pull-up for this pin. Please refer to imx35 datasheet for the valid pad
- config settings.
-
-CONFIG bits definition:
-PAD_CTL_DRIVE_VOLAGAGE_18 (1 << 13)
-PAD_CTL_DRIVE_VOLAGAGE_33 (0 << 13)
-PAD_CTL_HYS (1 << 8)
-PAD_CTL_PKE (1 << 7)
-PAD_CTL_PUE (1 << 6)
-PAD_CTL_PUS_100K_DOWN (0 << 4)
-PAD_CTL_PUS_47K_UP (1 << 4)
-PAD_CTL_PUS_100K_UP (2 << 4)
-PAD_CTL_PUS_22K_UP (3 << 4)
-PAD_CTL_ODE_CMOS (0 << 3)
-PAD_CTL_ODE_OPENDRAIN (1 << 3)
-PAD_CTL_DSE_NOMINAL (0 << 1)
-PAD_CTL_DSE_HIGH (1 << 1)
-PAD_CTL_DSE_MAX (2 << 1)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx35-pinfunc.h in device tree source folder for all available
-imx35 PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6ul-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.yaml
index 906b264a9e3c..265c43ab76f4 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx6ul-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.yaml
@@ -1,10 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/fsl,imx6ul-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/fsl,imx35-pinctrl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Freescale IMX6UL IOMUX Controller
+title: Freescale IMX35/IMX5x/IMX6 IOMUX Controller
maintainers:
- Dong Aisheng <aisheng.dong@nxp.com>
@@ -18,9 +18,21 @@ allOf:
properties:
compatible:
- enum:
- - fsl,imx6ul-iomuxc
- - fsl,imx6ull-iomuxc-snvs
+ oneOf:
+ - enum:
+ - fsl,imx35-iomuxc
+ - fsl,imx51-iomuxc
+ - fsl,imx53-iomuxc
+ - fsl,imx6dl-iomuxc
+ - fsl,imx6q-iomuxc
+ - fsl,imx6sl-iomuxc
+ - fsl,imx6sll-iomuxc
+ - fsl,imx6sx-iomuxc
+ - fsl,imx6ul-iomuxc
+ - fsl,imx6ull-iomuxc-snvs
+ - items:
+ - const: fsl,imx50-iomuxc
+ - const: fsl,imx53-iomuxc
reg:
maxItems: 1
@@ -39,9 +51,9 @@ 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 <arch/arm/boot/dts/imx6ul-pinfunc.h>. The last integer
+ be found in <arch/arm/boot/dts/nxp/imx/imx*-pinfunc.h>. The last integer
CONFIG is the pad setting value like pull-up on this pin. Please
- refer to i.MX6UL Reference Manual for detailed CONFIG settings.
+ refer to matching i.MX Reference Manual for detailed CONFIG settings.
$ref: /schemas/types.yaml#/definitions/uint32-matrix
items:
items:
@@ -56,7 +68,41 @@ patternProperties:
- description: |
"input_val" indicates the select input value to be applied.
- description: |
- "pad_setting" indicates the pad configuration value to be applied:
+ "pad_setting" indicates the pad configuration value to be applied.
+ Common i.MX35
+ PAD_CTL_DRIVE_VOLAGAGE_18 (1 << 13)
+ PAD_CTL_DRIVE_VOLAGAGE_33 (0 << 13)
+ PAD_CTL_HYS (1 << 8)
+ PAD_CTL_PKE (1 << 7)
+ PAD_CTL_PUE (1 << 6)
+ PAD_CTL_PUS_100K_DOWN (0 << 4)
+ PAD_CTL_PUS_47K_UP (1 << 4)
+ PAD_CTL_PUS_100K_UP (2 << 4)
+ PAD_CTL_PUS_22K_UP (3 << 4)
+ PAD_CTL_ODE_CMOS (0 << 3)
+ PAD_CTL_ODE_OPENDRAIN (1 << 3)
+ PAD_CTL_DSE_NOMINAL (0 << 1)
+ PAD_CTL_DSE_HIGH (1 << 1)
+ PAD_CTL_DSE_MAX (2 << 1)
+ PAD_CTL_SRE_FAST (1 << 0)
+ PAD_CTL_SRE_SLOW (0 << 0)
+ Common i.MX50/i.MX51/i.MX53 bits
+ PAD_CTL_HVE (1 << 13)
+ PAD_CTL_HYS (1 << 8)
+ PAD_CTL_PKE (1 << 7)
+ PAD_CTL_PUE (1 << 6)
+ PAD_CTL_PUS_100K_DOWN (0 << 4)
+ PAD_CTL_PUS_47K_UP (1 << 4)
+ PAD_CTL_PUS_100K_UP (2 << 4)
+ PAD_CTL_PUS_22K_UP (3 << 4)
+ PAD_CTL_ODE (1 << 3)
+ PAD_CTL_DSE_LOW (0 << 1)
+ PAD_CTL_DSE_MED (1 << 1)
+ PAD_CTL_DSE_HIGH (2 << 1)
+ PAD_CTL_DSE_MAX (3 << 1)
+ PAD_CTL_SRE_FAST (1 << 0)
+ PAD_CTL_SRE_SLOW (0 << 0)
+ Common i.MX6 bits
PAD_CTL_HYS (1 << 16)
PAD_CTL_PUS_100K_DOWN (0 << 14)
PAD_CTL_PUS_47K_UP (1 << 14)
@@ -69,6 +115,11 @@ patternProperties:
PAD_CTL_SPEED_MED (1 << 6)
PAD_CTL_SPEED_HIGH (3 << 6)
PAD_CTL_DSE_DISABLE (0 << 3)
+ PAD_CTL_SRE_FAST (1 << 0)
+ PAD_CTL_SRE_SLOW (0 << 0)
+ i.MX6SL/MX6SLL specific bits
+ PAD_CTL_LVE (1 << 22) (MX6SL/SLL only)
+ i.MX6SLL/i.MX6SX/i.MX6UL/i.MX6ULL specific bits
PAD_CTL_DSE_260ohm (1 << 3)
PAD_CTL_DSE_130ohm (2 << 3)
PAD_CTL_DSE_87ohm (3 << 3)
@@ -76,8 +127,14 @@ patternProperties:
PAD_CTL_DSE_52ohm (5 << 3)
PAD_CTL_DSE_43ohm (6 << 3)
PAD_CTL_DSE_37ohm (7 << 3)
- PAD_CTL_SRE_FAST (1 << 0)
- PAD_CTL_SRE_SLOW (0 << 0)
+ i.MX6DL/i.MX6Q/i.MX6SL specific bits
+ PAD_CTL_DSE_240ohm (1 << 3)
+ PAD_CTL_DSE_120ohm (2 << 3)
+ PAD_CTL_DSE_80ohm (3 << 3)
+ PAD_CTL_DSE_60ohm (4 << 3)
+ PAD_CTL_DSE_48ohm (5 << 3)
+ PAD_CTL_DSE_40ohm (6 << 3)
+ PAD_CTL_DSE_34ohm (7 << 3)
required:
- fsl,pins
@@ -114,3 +171,14 @@ examples:
>;
};
};
+ - |
+ iomuxc_mx6q: pinctrl@20e0000 {
+ compatible = "fsl,imx6q-iomuxc";
+ reg = <0x20e0000 0x4000>;
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins =
+ <0x288 0x658 0x000 0x3 0x0 0x140>,
+ <0x28c 0x65c 0x938 0x3 0x3 0x140>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx50-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx50-pinctrl.txt
deleted file mode 100644
index 6da01d619d33..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx50-pinctrl.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-* Freescale IMX50 IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx50-iomuxc"
-- fsl,pins: two integers array, represents a group of pins mux and config
- setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
- pin working on a specific function, CONFIG is the pad setting value like
- pull-up for this pin. Please refer to imx50 datasheet for the valid pad
- config settings.
-
-CONFIG bits definition:
-PAD_CTL_HVE (1 << 13)
-PAD_CTL_HYS (1 << 8)
-PAD_CTL_PKE (1 << 7)
-PAD_CTL_PUE (1 << 6)
-PAD_CTL_PUS_100K_DOWN (0 << 4)
-PAD_CTL_PUS_47K_UP (1 << 4)
-PAD_CTL_PUS_100K_UP (2 << 4)
-PAD_CTL_PUS_22K_UP (3 << 4)
-PAD_CTL_ODE (1 << 3)
-PAD_CTL_DSE_LOW (0 << 1)
-PAD_CTL_DSE_MED (1 << 1)
-PAD_CTL_DSE_HIGH (2 << 1)
-PAD_CTL_DSE_MAX (3 << 1)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx50-pinfunc.h in device tree source folder for all available
-imx50 PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt
deleted file mode 100644
index 4d1408fcc99c..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx51-pinctrl.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-* Freescale IMX51 IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx51-iomuxc"
-- fsl,pins: two integers array, represents a group of pins mux and config
- setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
- pin working on a specific function, CONFIG is the pad setting value like
- pull-up for this pin. Please refer to imx51 datasheet for the valid pad
- config settings.
-
-CONFIG bits definition:
-PAD_CTL_HVE (1 << 13)
-PAD_CTL_HYS (1 << 8)
-PAD_CTL_PKE (1 << 7)
-PAD_CTL_PUE (1 << 6)
-PAD_CTL_PUS_100K_DOWN (0 << 4)
-PAD_CTL_PUS_47K_UP (1 << 4)
-PAD_CTL_PUS_100K_UP (2 << 4)
-PAD_CTL_PUS_22K_UP (3 << 4)
-PAD_CTL_ODE (1 << 3)
-PAD_CTL_DSE_LOW (0 << 1)
-PAD_CTL_DSE_MED (1 << 1)
-PAD_CTL_DSE_HIGH (2 << 1)
-PAD_CTL_DSE_MAX (3 << 1)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx51-pinfunc.h in device tree source folder for all available
-imx51 PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt
deleted file mode 100644
index 25dcb77cfaf7..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx53-pinctrl.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-* Freescale IMX53 IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx53-iomuxc"
-- fsl,pins: two integers array, represents a group of pins mux and config
- setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
- pin working on a specific function, CONFIG is the pad setting value like
- pull-up for this pin. Please refer to imx53 datasheet for the valid pad
- config settings.
-
-CONFIG bits definition:
-PAD_CTL_HVE (1 << 13)
-PAD_CTL_HYS (1 << 8)
-PAD_CTL_PKE (1 << 7)
-PAD_CTL_PUE (1 << 6)
-PAD_CTL_PUS_100K_DOWN (0 << 4)
-PAD_CTL_PUS_47K_UP (1 << 4)
-PAD_CTL_PUS_100K_UP (2 << 4)
-PAD_CTL_PUS_22K_UP (3 << 4)
-PAD_CTL_ODE (1 << 3)
-PAD_CTL_DSE_LOW (0 << 1)
-PAD_CTL_DSE_MED (1 << 1)
-PAD_CTL_DSE_HIGH (2 << 1)
-PAD_CTL_DSE_MAX (3 << 1)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx53-pinfunc.h in device tree source folder for all available
-imx53 PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt
deleted file mode 100644
index 0ac5bee87505..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx6dl-pinctrl.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-* Freescale IMX6 DualLite/Solo IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx6dl-iomuxc"
-- fsl,pins: two integers array, represents a group of pins mux and config
- setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
- pin working on a specific function, CONFIG is the pad setting value like
- pull-up for this pin. Please refer to imx6dl datasheet for the valid pad
- config settings.
-
-CONFIG bits definition:
-PAD_CTL_HYS (1 << 16)
-PAD_CTL_PUS_100K_DOWN (0 << 14)
-PAD_CTL_PUS_47K_UP (1 << 14)
-PAD_CTL_PUS_100K_UP (2 << 14)
-PAD_CTL_PUS_22K_UP (3 << 14)
-PAD_CTL_PUE (1 << 13)
-PAD_CTL_PKE (1 << 12)
-PAD_CTL_ODE (1 << 11)
-PAD_CTL_SPEED_LOW (1 << 6)
-PAD_CTL_SPEED_MED (2 << 6)
-PAD_CTL_SPEED_HIGH (3 << 6)
-PAD_CTL_DSE_DISABLE (0 << 3)
-PAD_CTL_DSE_240ohm (1 << 3)
-PAD_CTL_DSE_120ohm (2 << 3)
-PAD_CTL_DSE_80ohm (3 << 3)
-PAD_CTL_DSE_60ohm (4 << 3)
-PAD_CTL_DSE_48ohm (5 << 3)
-PAD_CTL_DSE_40ohm (6 << 3)
-PAD_CTL_DSE_34ohm (7 << 3)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx6dl-pinfunc.h in device tree source folder for all available
-imx6dl PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
deleted file mode 100644
index 546610cf2ae7..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-* Freescale IMX6Q IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx6q-iomuxc"
-- fsl,pins: two integers array, represents a group of pins mux and config
- setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
- pin working on a specific function, CONFIG is the pad setting value like
- pull-up for this pin. Please refer to imx6q datasheet for the valid pad
- config settings.
-
-CONFIG bits definition:
-PAD_CTL_HYS (1 << 16)
-PAD_CTL_PUS_100K_DOWN (0 << 14)
-PAD_CTL_PUS_47K_UP (1 << 14)
-PAD_CTL_PUS_100K_UP (2 << 14)
-PAD_CTL_PUS_22K_UP (3 << 14)
-PAD_CTL_PUE (1 << 13)
-PAD_CTL_PKE (1 << 12)
-PAD_CTL_ODE (1 << 11)
-PAD_CTL_SPEED_LOW (1 << 6)
-PAD_CTL_SPEED_MED (2 << 6)
-PAD_CTL_SPEED_HIGH (3 << 6)
-PAD_CTL_DSE_DISABLE (0 << 3)
-PAD_CTL_DSE_240ohm (1 << 3)
-PAD_CTL_DSE_120ohm (2 << 3)
-PAD_CTL_DSE_80ohm (3 << 3)
-PAD_CTL_DSE_60ohm (4 << 3)
-PAD_CTL_DSE_48ohm (5 << 3)
-PAD_CTL_DSE_40ohm (6 << 3)
-PAD_CTL_DSE_34ohm (7 << 3)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx6q-pinfunc.h in device tree source folder for all available
-imx6q PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt
deleted file mode 100644
index e5f6d1f065a4..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx6sl-pinctrl.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-* Freescale IMX6 SoloLite IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx6sl-iomuxc"
-- fsl,pins: two integers array, represents a group of pins mux and config
- setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
- pin working on a specific function, CONFIG is the pad setting value like
- pull-up for this pin. Please refer to imx6sl datasheet for the valid pad
- config settings.
-
-CONFIG bits definition:
-PAD_CTL_LVE (1 << 22)
-PAD_CTL_HYS (1 << 16)
-PAD_CTL_PUS_100K_DOWN (0 << 14)
-PAD_CTL_PUS_47K_UP (1 << 14)
-PAD_CTL_PUS_100K_UP (2 << 14)
-PAD_CTL_PUS_22K_UP (3 << 14)
-PAD_CTL_PUE (1 << 13)
-PAD_CTL_PKE (1 << 12)
-PAD_CTL_ODE (1 << 11)
-PAD_CTL_SPEED_LOW (1 << 6)
-PAD_CTL_SPEED_MED (2 << 6)
-PAD_CTL_SPEED_HIGH (3 << 6)
-PAD_CTL_DSE_DISABLE (0 << 3)
-PAD_CTL_DSE_240ohm (1 << 3)
-PAD_CTL_DSE_120ohm (2 << 3)
-PAD_CTL_DSE_80ohm (3 << 3)
-PAD_CTL_DSE_60ohm (4 << 3)
-PAD_CTL_DSE_48ohm (5 << 3)
-PAD_CTL_DSE_40ohm (6 << 3)
-PAD_CTL_DSE_34ohm (7 << 3)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx6sl-pinfunc.h in device tree source folder for all available
-imx6sl PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6sll-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6sll-pinctrl.txt
deleted file mode 100644
index 175e8939a301..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx6sll-pinctrl.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-* Freescale i.MX6 SLL IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx6sll-iomuxc"
-- fsl,pins: 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
- imx6sll-pinfunc.h under device tree source folder. The last integer CONFIG is
- the pad setting value like pull-up on this pin. Please refer to i.MX6SLL
- Reference Manual for detailed CONFIG settings.
-
-CONFIG bits definition:
-PAD_CTL_LVE (1 << 22)
-PAD_CTL_HYS (1 << 16)
-PAD_CTL_PUS_100K_DOWN (0 << 14)
-PAD_CTL_PUS_47K_UP (1 << 14)
-PAD_CTL_PUS_100K_UP (2 << 14)
-PAD_CTL_PUS_22K_UP (3 << 14)
-PAD_CTL_PUE (1 << 13)
-PAD_CTL_PKE (1 << 12)
-PAD_CTL_ODE (1 << 11)
-PAD_CTL_SPEED_LOW (0 << 6)
-PAD_CTL_SPEED_MED (1 << 6)
-PAD_CTL_SPEED_HIGH (3 << 6)
-PAD_CTL_DSE_DISABLE (0 << 3)
-PAD_CTL_DSE_260ohm (1 << 3)
-PAD_CTL_DSE_130ohm (2 << 3)
-PAD_CTL_DSE_87ohm (3 << 3)
-PAD_CTL_DSE_65ohm (4 << 3)
-PAD_CTL_DSE_52ohm (5 << 3)
-PAD_CTL_DSE_43ohm (6 << 3)
-PAD_CTL_DSE_37ohm (7 << 3)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
-
-Refer to imx6sll-pinfunc.h in device tree source folder for all available
-imx6sll PIN_FUNC_ID.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx6sx-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx6sx-pinctrl.txt
deleted file mode 100644
index b1b595220f1b..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx6sx-pinctrl.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-* Freescale i.MX6 SoloX IOMUX Controller
-
-Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
-and usage.
-
-Required properties:
-- compatible: "fsl,imx6sx-iomuxc"
-- fsl,pins: 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
- imx6sx-pinfunc.h under device tree source folder. The last integer CONFIG is
- the pad setting value like pull-up on this pin. Please refer to i.MX6 SoloX
- Reference Manual for detailed CONFIG settings.
-
-CONFIG bits definition:
-PAD_CTL_HYS (1 << 16)
-PAD_CTL_PUS_100K_DOWN (0 << 14)
-PAD_CTL_PUS_47K_UP (1 << 14)
-PAD_CTL_PUS_100K_UP (2 << 14)
-PAD_CTL_PUS_22K_UP (3 << 14)
-PAD_CTL_PUE (1 << 13)
-PAD_CTL_PKE (1 << 12)
-PAD_CTL_ODE (1 << 11)
-PAD_CTL_SPEED_LOW (0 << 6)
-PAD_CTL_SPEED_MED (1 << 6)
-PAD_CTL_SPEED_HIGH (3 << 6)
-PAD_CTL_DSE_DISABLE (0 << 3)
-PAD_CTL_DSE_260ohm (1 << 3)
-PAD_CTL_DSE_130ohm (2 << 3)
-PAD_CTL_DSE_87ohm (3 << 3)
-PAD_CTL_DSE_65ohm (4 << 3)
-PAD_CTL_DSE_52ohm (5 << 3)
-PAD_CTL_DSE_43ohm (6 << 3)
-PAD_CTL_DSE_37ohm (7 << 3)
-PAD_CTL_SRE_FAST (1 << 0)
-PAD_CTL_SRE_SLOW (0 << 0)
diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,mcp23s08.yaml b/Documentation/devicetree/bindings/pinctrl/microchip,mcp23s08.yaml
new file mode 100644
index 000000000000..e07f4723de17
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/microchip,mcp23s08.yaml
@@ -0,0 +1,161 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/microchip,mcp23s08.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip I/O expander with serial interface (I2C/SPI)
+
+maintainers:
+ - Himanshu Bhavani <himanshu.bhavani@siliconsignals.io>
+
+description:
+ Microchip MCP23008, MCP23017, MCP23S08, MCP23S17, MCP23S18 GPIO expander
+ chips.These chips provide 8 or 16 GPIO pins with either I2C or SPI interface.
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - microchip,mcp23s08
+ - microchip,mcp23s17
+ - microchip,mcp23s18
+ - microchip,mcp23008
+ - microchip,mcp23017
+ - microchip,mcp23018
+
+ reg:
+ maxItems: 1
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ description: GPIO specifier for active-low reset pin.
+ maxItems: 1
+
+ microchip,spi-present-mask:
+ description:
+ Multiple SPI chips can share the same SPI chipselect. Set a bit in
+ bit0-7 in this mask to 1 if there is a chip connected with the
+ corresponding spi address set. For example if you have a chip with
+ address 3 connected, you have to set bit3 to 1, which is 0x08. mcp23s08
+ chip variant only supports bits 0-3. It is not possible to mix mcp23s08
+ and mcp23s17 on the same chipselect. Set at least one bit to 1 for SPI
+ chips.
+ $ref: /schemas/types.yaml#/definitions/uint8
+
+ microchip,irq-mirror:
+ type: boolean
+ description:
+ Sets the mirror flag in the IOCON register. Devices with two interrupt
+ outputs (these are the devices ending with 17 and those that have 16 IOs)
+ have two IO banks IO 0-7 form bank 1 and IO 8-15 are bank 2. These chips
+ have two different interrupt outputs One for bank 1 and another for
+ bank 2. If irq-mirror is set, both interrupts are generated regardless of
+ the bank that an input change occurred on. If it is not set,the interrupt
+ are only generated for the bank they belong to.
+
+ microchip,irq-active-high:
+ type: boolean
+ description:
+ Sets the INTPOL flag in the IOCON register.This configures the IRQ output
+ polarity as active high.
+
+ drive-open-drain:
+ type: boolean
+ description:
+ Sets the ODR flag in the IOCON register. This configures the IRQ output as
+ open drain active low.
+
+ pinmux:
+ type: object
+ properties:
+ pins:
+ description:
+ The list of GPIO pins controlled by this node. Each pin name
+ corresponds to a physical pin on the GPIO expander.
+ items:
+ pattern: '^gpio([0-9]|[1][0-5])$'
+ maxItems: 16
+
+ bias-pull-up:
+ type: boolean
+ description:
+ Configures pull-up resistors for the GPIO pins. Absence of this
+ property will leave the configuration in its default state.
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - '#gpio-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio@21 {
+ compatible = "microchip,mcp23017";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-parent = <&gpio1>;
+ interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ microchip,irq-mirror;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c_gpio0>, <&gpiopullups>;
+ reset-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+
+ gpiopullups: pinmux {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14", "gpio15";
+ bias-pull-up;
+ };
+ };
+ };
+
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio@0 {
+ compatible = "microchip,mcp23s17";
+ reg = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ spi-max-frequency = <1000000>;
+ microchip,spi-present-mask = /bits/ 8 <0x01>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml
index dbb3e1bd58c1..31bc30a81752 100644
--- a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml
@@ -12,14 +12,24 @@ maintainers:
properties:
compatible:
- enum:
- - microchip,lan966x-pinctrl
- - microchip,sparx5-pinctrl
- - mscc,jaguar2-pinctrl
- - mscc,luton-pinctrl
- - mscc,ocelot-pinctrl
- - mscc,serval-pinctrl
- - mscc,servalt-pinctrl
+ oneOf:
+ - enum:
+ - microchip,lan966x-pinctrl
+ - microchip,lan9691-pinctrl
+ - microchip,sparx5-pinctrl
+ - mscc,jaguar2-pinctrl
+ - mscc,luton-pinctrl
+ - mscc,ocelot-pinctrl
+ - mscc,serval-pinctrl
+ - mscc,servalt-pinctrl
+ - items:
+ - enum:
+ - microchip,lan9698-pinctrl
+ - microchip,lan9696-pinctrl
+ - microchip,lan9694-pinctrl
+ - microchip,lan9693-pinctrl
+ - microchip,lan9692-pinctrl
+ - const: microchip,lan9691-pinctrl
reg:
items:
@@ -85,6 +95,7 @@ allOf:
contains:
enum:
- microchip,lan966x-pinctrl
+ - microchip,lan9691-pinctrl
- microchip,sparx5-pinctrl
then:
properties:
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
deleted file mode 100644
index 2fa5edac7a35..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
+++ /dev/null
@@ -1,148 +0,0 @@
-Microchip MCP2308/MCP23S08/MCP23017/MCP23S17 driver for
-8-/16-bit I/O expander with serial interface (I2C/SPI)
-
-Required properties:
-- compatible : Should be
- - "mcp,mcp23s08" (DEPRECATED) for 8 GPIO SPI version
- - "mcp,mcp23s17" (DEPRECATED) for 16 GPIO SPI version
- - "mcp,mcp23008" (DEPRECATED) for 8 GPIO I2C version or
- - "mcp,mcp23017" (DEPRECATED) for 16 GPIO I2C version of the chip
-
- - "microchip,mcp23s08" for 8 GPIO SPI version
- - "microchip,mcp23s17" for 16 GPIO SPI version
- - "microchip,mcp23s18" for 16 GPIO SPI version
- - "microchip,mcp23008" for 8 GPIO I2C version or
- - "microchip,mcp23017" for 16 GPIO I2C version of the chip
- - "microchip,mcp23018" for 16 GPIO I2C version
- NOTE: Do not use the old mcp prefix any more. It is deprecated and will be
- removed.
-- #gpio-cells : Should be two.
- - first cell is the pin number
- - second cell is used to specify flags as described in
- 'Documentation/devicetree/bindings/gpio/gpio.txt'. Allowed values defined by
- 'include/dt-bindings/gpio/gpio.h' (e.g. GPIO_ACTIVE_LOW).
-- gpio-controller : Marks the device node as a GPIO controller.
-- reg : For an address on its bus. I2C uses this a the I2C address of the chip.
- SPI uses this to specify the chipselect line which the chip is
- connected to. The driver and the SPI variant of the chip support
- multiple chips on the same chipselect. Have a look at
- microchip,spi-present-mask below.
-
-Required device specific properties (only for SPI chips):
-- mcp,spi-present-mask (DEPRECATED)
-- microchip,spi-present-mask : This is a present flag, that makes only sense for SPI
- chips - as the name suggests. Multiple SPI chips can share the same
- SPI chipselect. Set a bit in bit0-7 in this mask to 1 if there is a
- chip connected with the corresponding spi address set. For example if
- you have a chip with address 3 connected, you have to set bit3 to 1,
- which is 0x08. mcp23s08 chip variant only supports bits 0-3. It is not
- possible to mix mcp23s08 and mcp23s17 on the same chipselect. Set at
- least one bit to 1 for SPI chips.
- NOTE: Do not use the old mcp prefix any more. It is deprecated and will be
- removed.
-- spi-max-frequency = The maximum frequency this chip is able to handle
-
-Optional properties:
-- #interrupt-cells : Should be two.
- - first cell is the pin number
- - second cell is used to specify flags.
-- interrupt-controller: Marks the device node as a interrupt controller.
-- drive-open-drain: Sets the ODR flag in the IOCON register. This configures
- the IRQ output as open drain active low.
-- reset-gpios: Corresponds to the active-low RESET# pin for the chip
-
-Optional device specific properties:
-- microchip,irq-mirror: Sets the mirror flag in the IOCON register. Devices
- with two interrupt outputs (these are the devices ending with 17 and
- those that have 16 IOs) have two IO banks: IO 0-7 form bank 1 and
- IO 8-15 are bank 2. These chips have two different interrupt outputs:
- One for bank 1 and another for bank 2. If irq-mirror is set, both
- interrupts are generated regardless of the bank that an input change
- occurred on. If it is not set, the interrupt are only generated for the
- bank they belong to.
- On devices with only one interrupt output this property is useless.
-- microchip,irq-active-high: Sets the INTPOL flag in the IOCON register. This
- configures the IRQ output polarity as active high.
-
-Example I2C (with interrupt):
-gpiom1: gpio@20 {
- compatible = "microchip,mcp23017";
- gpio-controller;
- #gpio-cells = <2>;
- reg = <0x20>;
-
- interrupt-parent = <&gpio1>;
- interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
- interrupt-controller;
- #interrupt-cells=<2>;
- microchip,irq-mirror;
-};
-
-Example SPI:
-gpiom1: gpio@0 {
- compatible = "microchip,mcp23s17";
- gpio-controller;
- #gpio-cells = <2>;
- microchip,spi-present-mask = <0x01>;
- reg = <0>;
- spi-max-frequency = <1000000>;
-};
-
-Pull-up configuration
-=====================
-
-If pins are used as output, they can also be configured with pull-ups. This is
-done with pinctrl.
-
-Please refer file <devicetree/bindings/pinctrl/pinctrl-bindings.txt>
-for details of the common pinctrl bindings used by client devices,
-including the meaning of the phrase "pin configuration node".
-
-Optional Pinmux properties:
---------------------------
-Following properties are required if default setting of pins are required
-at boot.
-- pinctrl-names: A pinctrl state named per <pinctrl-bindings.txt>.
-- pinctrl[0...n]: Properties to contain the phandle for pinctrl states per
- <pinctrl-bindings.txt>.
-
-The pin configurations are defined as child of the pinctrl states node. Each
-sub-node have following properties:
-
-Required properties:
-------------------
-- pins: List of pins. Valid values of pins properties are:
- gpio0 ... gpio7 for the devices with 8 GPIO pins and
- gpio0 ... gpio15 for the devices with 16 GPIO pins.
-
-Optional properties:
--------------------
-The following optional property is defined in the pinmux DT binding document
-<pinctrl-bindings.txt>. Absence of this property will leave the configuration
-in its default state.
- bias-pull-up
-
-Example with pinctrl to pull-up output pins:
-gpio21: gpio@21 {
- compatible = "microchip,mcp23017";
- gpio-controller;
- #gpio-cells = <0x2>;
- reg = <0x21>;
- interrupt-parent = <&socgpio>;
- interrupts = <0x17 0x8>;
- interrupt-names = "mcp23017@21 irq";
- interrupt-controller;
- #interrupt-cells = <0x2>;
- microchip,irq-mirror;
- pinctrl-names = "default";
- pinctrl-0 = <&i2cgpio0irq>, <&gpio21pullups>;
- reset-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
-
- gpio21pullups: pinmux {
- pins = "gpio0", "gpio1", "gpio2", "gpio3",
- "gpio4", "gpio5", "gpio6", "gpio7",
- "gpio8", "gpio9", "gpio10", "gpio11",
- "gpio12", "gpio13", "gpio14", "gpio15";
- bias-pull-up;
- };
-};
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml
index e02595316c9f..f83dbf32ad18 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml
@@ -33,6 +33,10 @@ properties:
- ti,omap5-padconf
- ti,j7200-padconf
- const: pinctrl-single
+ - items:
+ - enum:
+ - marvell,pxa1908-padconf
+ - const: pinconf-single
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq5424-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,ipq5424-tlmm.yaml
new file mode 100644
index 000000000000..5e64a232fc7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq5424-tlmm.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,ipq5424-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm IPQ5424 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm IPQ5424 SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,ipq5424-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 25
+
+ gpio-line-names:
+ maxItems: 50
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-ipq5424-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-ipq5424-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-ipq5424-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
+ unevaluatedProperties: false
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ pattern: "^gpio([0-9]|[1-4][0-9])$"
+ minItems: 1
+ maxItems: 50
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ atest_char, atest_char0, atest_char1, atest_char2, atest_char3,
+ atest_tic, audio_pri, audio_pri0, audio_pri1, audio_sec,
+ audio_sec0, audio_sec1, core_voltage, cri_trng0, cri_trng1,
+ cri_trng2, cri_trng3, cxc_clk, cxc_data, dbg_out, gcc_plltest,
+ gcc_tlmm, gpio, i2c0_scl, i2c0_sda, i2c1_scl, i2c1_sda, i2c11,
+ mac0, mac1, mdc_mst, mdc_slv, mdio_mst, mdio_slv, pcie0_clk,
+ pcie0_wake, pcie1_clk, pcie1_wake, pcie2_clk, pcie2_wake,
+ pcie3_clk, pcie3_wake, pll_test, prng_rosc0, prng_rosc1,
+ prng_rosc2, prng_rosc3, PTA0_0, PTA0_1, PTA0_2, PTA10, PTA11,
+ pwm0, pwm1, pwm2, qdss_cti_trig_in_a0, qdss_cti_trig_out_a0,
+ qdss_cti_trig_in_a1, qdss_cti_trig_out_a1, qdss_cti_trig_in_b0,
+ qdss_cti_trig_out_b0, qdss_cti_trig_in_b1, qdss_cti_trig_out_b1,
+ qdss_traceclk_a, qdss_tracectl_a, qdss_tracedata_a, qspi_clk,
+ qspi_cs, qspi_data, resout, rx0, rx1, rx2, sdc_clk, sdc_cmd,
+ sdc_data, spi0, spi1, spi10, spi11, tsens_max, uart0, uart1,
+ wci_txd, wci_rxd, wsi_clk, wsi_data ]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,ipq5424-tlmm";
+ reg = <0x01000000 0x300000>;
+ gpio-controller;
+ #gpio-cells = <0x2>;
+ gpio-ranges = <&tlmm 0 0 50>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <0x2>;
+
+ uart1_pins: uart1-state {
+ pins = "gpio43", "gpio44";
+ function = "uart1";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml
index c1b799167d81..055cea5452eb 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml
@@ -48,6 +48,7 @@ properties:
- qcom,pm8916-gpio
- qcom,pm8917-gpio
- qcom,pm8921-gpio
+ - qcom,pm8937-gpio
- qcom,pm8941-gpio
- qcom,pm8950-gpio
- qcom,pm8953-gpio
@@ -184,6 +185,7 @@ allOf:
- qcom,pm8226-gpio
- qcom,pm8350b-gpio
- qcom,pm8550ve-gpio
+ - qcom,pm8937-gpio
- qcom,pm8950-gpio
- qcom,pm8953-gpio
- qcom,pmi632-gpio
@@ -468,6 +470,7 @@ $defs:
- gpio1-gpio6 for pm8550vs
- gpio1-gpio38 for pm8917
- gpio1-gpio44 for pm8921
+ - gpio1-gpio8 for pm8937 (hole on gpio3, gpio4 and gpio6)
- gpio1-gpio36 for pm8941
- gpio1-gpio8 for pm8950 (hole on gpio3)
- gpio1-gpio8 for pm8953 (hole on gpio3 and gpio6)
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml
index 43146709e204..9364ae05f3e6 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml
@@ -22,6 +22,7 @@ properties:
- qcom,pm8226-mpp
- qcom,pm8841-mpp
- qcom,pm8916-mpp
+ - qcom,pm8937-mpp
- qcom,pm8941-mpp
- qcom,pm8950-mpp
- qcom,pmi8950-mpp
@@ -92,6 +93,7 @@ $defs:
this subnode. Valid pins are
- mpp1-mpp4 for pm8841
- mpp1-mpp4 for pm8916
+ - mpp1-mpp4 for pm8937
- mpp1-mpp8 for pm8941
- mpp1-mpp4 for pm8950
- mpp1-mpp4 for pmi8950
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcs615-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,qcs615-tlmm.yaml
new file mode 100644
index 000000000000..1ce4b5df584a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,qcs615-tlmm.yaml
@@ -0,0 +1,124 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,qcs615-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. QCS615 TLMM block
+
+maintainers:
+ - Lijuan Gao <quic_lijuang@quicinc.com>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm QCS615 SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,qcs615-tlmm
+
+ reg:
+ maxItems: 3
+
+ reg-names:
+ items:
+ - const: east
+ - const: west
+ - const: south
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 62
+
+ gpio-line-names:
+ maxItems: 123
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-qcs615-tlmm-state"
+ - type: object
+ patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-qcs615-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-qcs615-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
+ unevaluatedProperties: false
+
+ 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[0-2])$"
+ - 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, agera_pll, aoss_cti, atest_char, atest_tsens,
+ atest_usb, cam_mclk, cci_async, cci_i2c, cci_timer, copy_gp,
+ copy_phase, cri_trng, dbg_out_clk, ddr_bist, ddr_pxi, dp_hot,
+ edp_hot, edp_lcd, emac_gcc, emac_phy_intr, forced_usb, gcc_gp,
+ gp_pdm, gps_tx, hs0_mi2s, hs1_mi2s, jitter_bist, ldo_en,
+ ldo_update, m_voc, mclk1, mclk2, mdp_vsync, mdp_vsync0_out,
+ mdp_vsync1_out, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync4_out,
+ mdp_vsync5_out, mi2s_1, mss_lte, nav_pps_in, nav_pps_out,
+ pa_indicator_or, pcie_clk_req, pcie_ep_rst, phase_flag, pll_bist,
+ pll_bypassnl, pll_reset_n, prng_rosc, qdss_cti, qdss_gpio,
+ qlink_enable, qlink_request, qspi, qup0, qup1, rgmii,
+ sd_write_protect, sp_cmu, ter_mi2s, tgu_ch, uim1, uim2, usb0_hs,
+ usb1_hs, usb_phy_ps, vfr_1, vsense_trigger_mirnat, wlan, wsa_clk,
+ wsa_data ]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+ - reg-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@3000000 {
+ compatible = "qcom,qcs615-tlmm";
+ reg = <0x03100000 0x300000>,
+ <0x03500000 0x300000>,
+ <0x03c00000 0x300000>;
+ reg-names = "east", "west", "south";
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&tlmm 0 0 123>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ qup3-uart2-state {
+ pins ="gpio16", "gpio17";
+ function = "qup0";
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcs8300-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,qcs8300-tlmm.yaml
new file mode 100644
index 000000000000..bb0d7132886a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,qcs8300-tlmm.yaml
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,qcs8300-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. QCS8300 TLMM block
+
+maintainers:
+ - Jingyi Wang <quic_jingyw@quicinc.com>
+
+description: |
+ Top Level Mode Multiplexer pin controller in Qualcomm QCS8300 SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,qcs8300-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 67
+
+ gpio-line-names:
+ maxItems: 133
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-qcs8300-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-qcs8300-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-qcs8300-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
+ unevaluatedProperties: false
+
+ 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-2][0-9]|13[0-2])$"
+ - enum: [ ufs_reset, sdc1_rclk, sdc1_clk, sdc1_cmd, sdc1_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ aoss_cti, atest_char, atest_usb2, audio_ref, cam_mclk,
+ cci_async, cci_i2c_scl, cci_i2c_sda, cci_timer, cri_trng,
+ dbg_out, ddr_bist, ddr_pxi0, ddr_pxi1, ddr_pxi2, ddr_pxi3,
+ edp0_hot, edp0_lcd, edp1_lcd, egpio, emac0_mcg0, emac0_mcg1,
+ emac0_mcg2, emac0_mcg3, emac0_mdc, emac0_mdio, emac0_ptp_aux,
+ emac0_ptp_pps, gcc_gp1, gcc_gp2, gcc_gp3, gcc_gp4, gcc_gp5,
+ gpio, hs0_mi2s, hs1_mi2s, hs2_mi2s, ibi_i3c, jitter_bist,
+ mdp0_vsync0, mdp0_vsync1, mdp0_vsync3, mdp0_vsync6, mdp0_vsync7,
+ mdp_vsync, mi2s1_data0, mi2s1_data1, mi2s1_sck, mi2s1_ws,
+ mi2s2_data0, mi2s2_data1, mi2s2_sck, mi2s2_ws, mi2s_mclk0,
+ mi2s_mclk1, pcie0_clkreq, pcie1_clkreq, phase_flag, pll_bist,
+ pll_clk, prng_rosc0, prng_rosc1, prng_rosc2, prng_rosc3,
+ qdss_cti, qdss_gpio, qup0_se0, qup0_se1, qup0_se2, qup0_se3,
+ qup0_se4, qup0_se5, qup0_se6, qup0_se7, qup1_se0, qup1_se1,
+ qup1_se2, qup1_se3, qup1_se4, qup1_se5, qup1_se6, qup1_se7,
+ qup2_se0, sailss_emac0, sailss_ospi, sail_top, sgmii_phy,
+ tb_trig, tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3, tsense_pwm1,
+ tsense_pwm2, tsense_pwm3, tsense_pwm4, usb2phy_ac,
+ vsense_trigger ]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@f100000 {
+ compatible = "qcom,qcs8300-tlmm";
+ reg = <0x0f100000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 133>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ qup-uart7-state {
+ pins = "gpio43", "gpio44";
+ function = "qup0_se7";
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml
index e9abbf2c0689..749dbc563ac5 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sa8775p-tlmm.yaml
@@ -17,7 +17,13 @@ allOf:
properties:
compatible:
- const: qcom,sa8775p-tlmm
+ oneOf:
+ - items:
+ - enum:
+ - qcom,sa8255p-tlmm
+ - const: qcom,sa8775p-tlmm
+ - items:
+ - const: qcom,sa8775p-tlmm
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sar2130p-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sar2130p-tlmm.yaml
new file mode 100644
index 000000000000..b388380b1ce0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sar2130p-tlmm.yaml
@@ -0,0 +1,138 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sar2130p-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. SAR2130P TLMM block
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SAR2130P SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sar2130p-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 78
+
+ gpio-line-names:
+ maxItems: 156
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sar2130p-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sar2130p-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sar2130p-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
+ unevaluatedProperties: false
+
+ 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-5])$"
+ - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc1_rclk ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+ enum: [ aoss_cti, atest_char, atest_char0, atest_char1, atest_char2,
+ atest_char3, atest_usb0, atest_usb00, atest_usb01, atest_usb02,
+ atest_usb03, 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, dp0_hot, ext_mclk0, ext_mclk1,
+ gcc_gp1, gcc_gp2, gcc_gp3, gpio, host2wlan_sol, i2s0_data0,
+ i2s0_data1, i2s0_sck, i2s0_ws, ibi_i3c, jitter_bist, mdp_vsync,
+ mdp_vsync0, mdp_vsync1, mdp_vsync2, mdp_vsync3, pcie0_clkreqn,
+ pcie1_clkreqn, 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_bist, pll_clk, prng_rosc0, prng_rosc1,
+ prng_rosc2, prng_rosc3, qdss_cti, 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,
+ qspi0, qspi1, qspi2, qspi3, qspi_clk, qspi_cs0, qspi_cs1, qup0,
+ qup1, qup2, qup3, qup4, qup5, qup6, qup7, qup8, qup9, qup10,
+ qup11, tb_trig, tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3,
+ tmess_prng0, tmess_prng1, tmess_prng2, tmess_prng3,
+ tsense_pwm1, tsense_pwm2, usb0_phy, vsense_trigger ]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ pinctrl@f100000 {
+ compatible = "qcom,sar2130p-tlmm";
+ reg = <0x0f100000 0x300000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 156>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+
+ gpio-wo-state {
+ pins = "gpio1";
+ function = "gpio";
+ };
+
+ uart-w-state {
+ rx-pins {
+ pins = "gpio26";
+ function = "qup7";
+ bias-pull-up;
+ };
+
+ tx-pins {
+ pins = "gpio27";
+ function = "qup7";
+ bias-disable;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8650-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8650-lpass-lpi-pinctrl.yaml
index db7214362301..e90a5274647d 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8650-lpass-lpi-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8650-lpass-lpi-pinctrl.yaml
@@ -16,7 +16,11 @@ description:
properties:
compatible:
- const: qcom,sm8650-lpass-lpi-pinctrl
+ oneOf:
+ - const: qcom,sm8650-lpass-lpi-pinctrl
+ - items:
+ - const: qcom,sm8750-lpass-lpi-pinctrl
+ - const: qcom,sm8650-lpass-lpi-pinctrl
reg:
items:
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8750-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8750-tlmm.yaml
new file mode 100644
index 000000000000..7aecc97745a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8750-tlmm.yaml
@@ -0,0 +1,138 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm8750-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. SM8750 TLMM block
+
+maintainers:
+ - Melody Olvera <quic_molvera@quicinc.com>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SM8750 SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sm8750-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 108
+
+ gpio-line-names:
+ maxItems: 215
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sm8750-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sm8750-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sm8750-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
+ unevaluatedProperties: false
+
+ 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-9][0-9]|20[0-9]|21[0-4])$"
+ - 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: [ gpio, aoss_cti, atest_char, atest_usb, audio_ext_mclk0,
+ audio_ext_mclk1, audio_ref_clk, cam_aon_mclk2, cam_aon_mclk4,
+ cam_mclk, cci_async_in, cci_i2c_scl, cci_i2c_sda, cci_timer,
+ cmu_rng, coex_uart1_rx, coex_uart1_tx, coex_uart2_rx,
+ coex_uart2_tx, dbg_out_clk, ddr_bist_complete, ddr_bist_fail,
+ ddr_bist_start, ddr_bist_stop, ddr_pxi0, ddr_pxi1, ddr_pxi2,
+ ddr_pxi3, dp_hot, egpio, gcc_gp1, gcc_gp2, gcc_gp3, gnss_adc0,
+ gnss_adc1, i2chub0_se0, i2chub0_se1, i2chub0_se2, i2chub0_se3,
+ i2chub0_se4, i2chub0_se5, i2chub0_se6, i2chub0_se7, i2chub0_se8,
+ i2chub0_se9, i2s0_data0, i2s0_data1, i2s0_sck, i2s0_ws,
+ i2s1_data0, i2s1_data1, i2s1_sck, i2s1_ws, ibi_i3c, jitter_bist,
+ mdp_esync0_out, mdp_esync1_out, mdp_vsync, mdp_vsync0_out,
+ mdp_vsync1_out, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync5_out,
+ mdp_vsync_e, nav_gpio0, nav_gpio1, nav_gpio2, nav_gpio3,
+ pcie0_clk_req_n, phase_flag, pll_bist_sync, pll_clk_aux,
+ prng_rosc0, prng_rosc1, prng_rosc2, prng_rosc3, qdss_cti,
+ qlink_big_enable, qlink_big_request, qlink_little_enable,
+ qlink_little_request, qlink_wmss, qspi0, qspi1, qspi2, qspi3,
+ qspi_clk, qspi_cs, qup1_se0, qup1_se1, qup1_se2, qup1_se3,
+ qup1_se4, qup1_se5, qup1_se6, qup1_se7, qup2_se0, qup2_se1,
+ qup2_se2, qup2_se3, qup2_se4, qup2_se5, qup2_se6, qup2_se7,
+ sd_write_protect, sdc40, sdc41, sdc42, sdc43, sdc4_clk,
+ sdc4_cmd, tb_trig_sdc2, tb_trig_sdc4, tmess_prng0, tmess_prng1,
+ tmess_prng2, tmess_prng3, tsense_pwm1, tsense_pwm2, tsense_pwm3,
+ tsense_pwm4, uim0_clk, uim0_data, uim0_present, uim0_reset,
+ uim1_clk, uim1_data, uim1_present, uim1_reset, usb1_hs, usb_phy,
+ vfr_0, vfr_1, vsense_trigger_mirnat, wcn_sw, wcn_sw_ctrl ]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@f100000 {
+ compatible = "qcom,sm8750-tlmm";
+ reg = <0x0f100000 0x300000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 216>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+
+ gpio-wo-state {
+ pins = "gpio1";
+ function = "gpio";
+ };
+
+ uart-w-state {
+ rx-pins {
+ pins = "gpio60";
+ function = "qup1_se7";
+ bias-pull-up;
+ };
+
+ tx-pins {
+ pins = "gpio61";
+ function = "qup1_se7";
+ bias-disable;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
index 56d90c8e1fa3..a1805b6e3f63 100644
--- a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
@@ -119,6 +119,10 @@ additionalProperties:
bias-disable: true
bias-pull-down: true
bias-pull-up: true
+ input-schmitt-enable: true
+ input-schmitt-disable: true
+ drive-open-drain: true
+ drive-push-pull: true
renesas,output-impedance:
description:
Output impedance for pins on the RZ/V2H(P) SoC. The value provided by this
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml
index 4dfb49b0e07f..68ed714eb0a1 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml
@@ -42,10 +42,13 @@ properties:
- samsung,exynos5433-wakeup-eint
- samsung,exynos7885-wakeup-eint
- samsung,exynos850-wakeup-eint
+ - samsung,exynos8895-wakeup-eint
- const: samsung,exynos7-wakeup-eint
- items:
- enum:
- google,gs101-wakeup-eint
+ - samsung,exynos9810-wakeup-eint
+ - samsung,exynos990-wakeup-eint
- samsung,exynosautov9-wakeup-eint
- const: samsung,exynos850-wakeup-eint
- const: samsung,exynos7-wakeup-eint
@@ -91,14 +94,18 @@ allOf:
- if:
properties:
compatible:
- # Match without "contains", to skip newer variants which are still
- # compatible with samsung,exynos7-wakeup-eint
- enum:
- - samsung,s5pv210-wakeup-eint
- - samsung,exynos4210-wakeup-eint
- - samsung,exynos5433-wakeup-eint
- - samsung,exynos7-wakeup-eint
- - samsung,exynos7885-wakeup-eint
+ oneOf:
+ # Match without "contains", to skip newer variants which are still
+ # compatible with samsung,exynos7-wakeup-eint
+ - enum:
+ - samsung,exynos4210-wakeup-eint
+ - samsung,exynos7-wakeup-eint
+ - samsung,s5pv210-wakeup-eint
+ - contains:
+ enum:
+ - samsung,exynos5433-wakeup-eint
+ - samsung,exynos7885-wakeup-eint
+ - samsung,exynos8895-wakeup-eint
then:
properties:
interrupts:
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml
index 242dd13c276b..5296a9e4faae 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml
@@ -53,6 +53,9 @@ properties:
- samsung,exynos7-pinctrl
- samsung,exynos7885-pinctrl
- samsung,exynos850-pinctrl
+ - samsung,exynos8895-pinctrl
+ - samsung,exynos9810-pinctrl
+ - samsung,exynos990-pinctrl
- samsung,exynosautov9-pinctrl
- samsung,exynosautov920-pinctrl
- tesla,fsd-pinctrl
diff --git a/Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml b/Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml
index 4214d7311f6b..39d7dad3313b 100644
--- a/Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml
@@ -26,6 +26,10 @@ properties:
reg:
maxItems: 1
+ gpio-line-names:
+ minItems: 5
+ maxItems: 17
+
interrupts:
maxItems: 1
@@ -88,6 +92,45 @@ required:
allOf:
- $ref: pinctrl.yaml#
- if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - semtech,sx1501q
+ - semtech,sx1504q
+ - semtech,sx1507q
+ then:
+ properties:
+ gpio-line-names:
+ minItems: 5
+ maxItems: 5
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - semtech,sx1502q
+ - semtech,sx1505q
+ - semtech,sx1508q
+ then:
+ properties:
+ gpio-line-names:
+ minItems: 9
+ maxItems: 9
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - semtech,sx1503q
+ - semtech,sx1506q
+ - semtech,sx1509q
+ then:
+ properties:
+ gpio-line-names:
+ minItems: 17
+ maxItems: 17
+ - if:
not:
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/pinctrl/sophgo,cv1800-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/sophgo,cv1800-pinctrl.yaml
index 1e6a55afe26a..feb4785a3fac 100644
--- a/Documentation/devicetree/bindings/pinctrl/sophgo,cv1800-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/sophgo,cv1800-pinctrl.yaml
@@ -58,7 +58,7 @@ patternProperties:
pinmux:
description: |
The list of GPIOs and their mux settings that properties in the
- node apply to. This should be set using the GPIOMUX or GPIOMUX2
+ node apply to. This should be set using the PINMUX or PINMUX2
macro.
bias-pull-up:
diff --git a/Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml
new file mode 100644
index 000000000000..b01ecd83b71b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml
@@ -0,0 +1,124 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/spacemit,k1-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SpacemiT K1 SoC Pin Controller
+
+maintainers:
+ - Yixun Lan <dlan@gentoo.org>
+
+properties:
+ compatible:
+ const: spacemit,k1-pinctrl
+
+ reg:
+ items:
+ - description: pinctrl io memory base
+
+patternProperties:
+ '-cfg$':
+ type: object
+ additionalProperties: false
+
+ description:
+ A pinctrl node should contain at least one subnode representing the
+ pinctrl groups available on the machine.
+
+ patternProperties:
+ '-pins$':
+ type: object
+ additionalProperties: false
+
+ description:
+ Each subnode will list the pins it needs, and how they should
+ be configured, with regard to muxer configuration, bias pull,
+ drive strength, input schmitt trigger, slew rate, power source.
+
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: pinmux-node.yaml#
+
+ properties:
+ pinmux:
+ description:
+ The list of GPIOs and their mux settings that properties in the
+ node apply to. This should be set using the K1_PADCONF macro to
+ construct the value.
+
+ bias-disable: true
+
+ bias-pull-down: true
+
+ bias-pull-up:
+ description: |
+ typical value for selecting bias pull up or strong pull up.
+ 0: normal bias pull up
+ 1: strong bias pull up
+ enum: [ 0, 1 ]
+
+ drive-strength:
+ description: |
+ typical current when output high level.
+ 1.8V output: 11, 21, 32, 42 (mA)
+ 3.3V output: 7, 10, 13, 16, 19, 23, 26, 29 (mA)
+
+ input-schmitt:
+ description: |
+ typical threshold for schmitt trigger.
+ 0: buffer mode
+ 1: trigger mode
+ 2, 3: trigger mode
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1, 2, 3 ]
+
+ power-source:
+ description: external power supplies at 1.8v or 3.3v.
+ enum: [ 1800, 3300 ]
+
+ slew-rate:
+ description: |
+ slew rate for output buffer.
+ 0: disable it
+ 1: enable it (via bundled value from drive strength)
+ 2: slow speed 0
+ 3: slow speed 1
+ 4: medium speed
+ 5: fast speed
+ enum: [ 0, 1, 2, 3, 4, 5 ]
+
+ required:
+ - pinmux
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #define K1_PADCONF(pin, func) (((pin) << 16) | (func))
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pinctrl@d401e000 {
+ compatible = "spacemit,k1-pinctrl";
+ reg = <0x0 0xd401e000 0x0 0x400>;
+
+ uart0_2_cfg: uart0-2-cfg {
+ uart0-2-pins {
+ pinmux = <K1_PADCONF(68, 2)>,
+ <K1_PADCONF(69, 2)>;
+
+ bias-pull-up = <0>;
+ drive-strength = <32>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml
new file mode 100644
index 000000000000..21f86740a63d
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/thead,th1520-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/thead,th1520-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: T-Head TH1520 SoC pin controller
+
+maintainers:
+ - Emil Renner Berthing <emil.renner.berthing@canonical.com>
+
+description: |
+ Pinmux and pinconf controller in the T-Head TH1520 RISC-V SoC.
+
+ The TH1520 has 3 groups of pads each controlled from different memory ranges.
+ Confusingly the memory ranges are named
+ PADCTRL_AOSYS -> PAD Group 1
+ PADCTRL1_APSYS -> PAD Group 2
+ PADCTRL0_APSYS -> PAD Group 3
+
+ Each pad can be muxed individually to up to 6 different functions. For most
+ pads only a few of those 6 configurations are valid though, and a few pads in
+ group 1 does not support muxing at all.
+
+ Pinconf is fairly regular except for a few pads in group 1 that either can't
+ be configured or has some special functions. The rest have configurable drive
+ strength, input enable, schmitt trigger, slew rate, pull-up and pull-down in
+ addition to a special strong pull up.
+
+ Certain pads in group 1 can be muxed to AUDIO_PA0 - AUDIO_PA30 functions and
+ are then meant to be used by the audio co-processor. Each such pad can then
+ be further muxed to either audio GPIO or one of 4 functions such as UART, I2C
+ and I2S. If the audio pad is muxed to one of the 4 functions then pinconf is
+ also configured in different registers. All of this is done from a different
+ AUDIO_IOCTRL memory range and is left to the audio co-processor for now.
+
+properties:
+ compatible:
+ enum:
+ - thead,th1520-pinctrl
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ thead,pad-group:
+ description: |
+ Select the pad group that is associated with the pin controller instance.
+
+ Base Address Name Group
+ 0xFF_FFF4_A000 PADCTRL_AOSYS 1
+ 0xFF_E7F3_C000 PADCTRL1_APSYS 2
+ 0xFF_EC00_7000 PADCTRL0_APSYS 3
+
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2, 3]
+
+required:
+ - compatible
+ - reg
+ - clocks
+
+patternProperties:
+ '-[0-9]+$':
+ type: object
+ additionalProperties: false
+
+ patternProperties:
+ '-pins$':
+ type: object
+ allOf:
+ - $ref: /schemas/pinctrl/pincfg-node.yaml#
+ - $ref: /schemas/pinctrl/pinmux-node.yaml#
+
+ additionalProperties: false
+
+ description:
+ A pinctrl node should contain at least one subnode describing one
+ or more pads and their associated pinmux and pinconf settings.
+
+ properties:
+ pins:
+ description: List of pads that properties in the node apply to.
+
+ function:
+ enum: [ gpio, pwm, uart, ir, i2c, spi, qspi, sdio, audio, i2s,
+ gmac0, gmac1, dpu0, dpu1, isp, hdmi, bootsel, debug,
+ clock, jtag, iso7816, efuse, reset ]
+ description: The mux function to select for the given pins.
+
+ bias-disable: true
+
+ bias-pull-up:
+ oneOf:
+ - type: boolean
+ description: Enable the regular 48kOhm pull-up
+ - enum: [ 2100, 48000 ]
+ description: Enable the strong 2.1kOhm pull-up or regular 48kOhm pull-up
+
+ bias-pull-down:
+ oneOf:
+ - type: boolean
+ - const: 44000
+ description: Enable the regular 44kOhm pull-down
+
+ drive-strength:
+ enum: [ 1, 2, 3, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25 ]
+ description: Drive strength in mA
+
+ input-enable: true
+
+ input-disable: true
+
+ input-schmitt-enable: true
+
+ input-schmitt-disable: true
+
+ slew-rate:
+ maximum: 1
+
+ required:
+ - pins
+
+additionalProperties: false
+
+examples:
+ - |
+ padctrl0_apsys: pinctrl@ec007000 {
+ compatible = "thead,th1520-pinctrl";
+ reg = <0xec007000 0x1000>;
+ clocks = <&apb_clk>;
+ thead,pad-group = <3>;
+
+ uart0_pins: uart0-0 {
+ tx-pins {
+ pins = "UART0_TXD";
+ function = "uart";
+ bias-disable;
+ drive-strength = <3>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ rx-pins {
+ pins = "UART0_RXD";
+ function = "uart";
+ bias-disable;
+ drive-strength = <1>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+ };
+ };
+
+ padctrl1_apsys: pinctrl@e7f3c000 {
+ compatible = "thead,th1520-pinctrl";
+ reg = <0xe7f3c000 0x1000>;
+ clocks = <&apb_clk>;
+ thead,pad-group = <2>;
+
+ i2c5_pins: i2c5-0 {
+ i2c-pins {
+ pins = "QSPI1_CSN0", /* I2C5_SCL */
+ "QSPI1_D0_MOSI"; /* I2C5_SDA */
+ function = "i2c";
+ bias-pull-up = <2100>;
+ drive-strength = <7>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/xlnx,versal-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/xlnx,versal-pinctrl.yaml
new file mode 100644
index 000000000000..55ece6a8be5e
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/xlnx,versal-pinctrl.yaml
@@ -0,0 +1,278 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/xlnx,versal-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Versal Pinctrl
+
+maintainers:
+ - Sai Krishna Potthuri <sai.krishna.potthuri@amd.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".
+
+ Versal'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, slew rate, etc.
+
+ Each configuration node can consist of multiple nodes describing the pinmux and
+ pinconf options. Those nodes can be pinmux nodes or pinconf nodes.
+
+properties:
+ compatible:
+ const: xlnx,versal-pinctrl
+
+patternProperties:
+ '^(.*-)?(default|gpio-grp)$':
+ type: object
+ patternProperties:
+ '^mux':
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for pin muxes,
+ which in turn use below standard properties.
+ $ref: pinmux-node.yaml#
+
+ properties:
+ pins:
+ description:
+ List of pins to select (either this or "groups" must be specified)
+ $ref: "#/$defs/pins/properties/pins"
+
+ groups:
+ description:
+ List of groups to select (either this or "pins" must be
+ specified), available groups for this subnode.
+ anyOf:
+ - pattern: '^((LPD|PMC)_)MIO([0-9]|[1-6][0-9]|7[0-7])$'
+ - $ref: "#/$defs/pins/properties/groups"
+
+ function:
+ description:
+ Specify the alternative function to be configured for the
+ given pin groups.
+ enum: [spi0, spi0_ss, spi1, spi1_ss, can0, can1, i2c0, i2c1, i2c_pmc, ttc0_clk,
+ ttc0_wav, ttc1_clk, ttc1_wav, ttc2_clk, ttc2_wav, ttc3_clk, ttc3_wav, wwdt0,
+ wwdt1, sysmon_i2c0, sysmon_i2c0_alrt, uart0, uart0_ctrl, uart1, uart1_ctrl,
+ gpio0, gpio1, gpio2, emio0, gem0, gem1, trace0, trace0_clk, mdio0, mdio1, gem_tsu0,
+ pcie0, smap0, usb0, sd0, sd0_pc, sd0_cd, sd0_wp, sd1, sd1_pc, sd1_wp, sd1_cd,
+ ospi0, ospi0_ss, qspi0, qspi0_fbclk, qspi0_ss, test_clk, test_scan, tamper_trigger]
+
+ required:
+ - function
+
+ oneOf:
+ - required: [ groups ]
+ - required: [ pins ]
+
+ additionalProperties: false
+
+ '^conf':
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for pin configurations,
+ which in turn use the standard properties below.
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: "#/$defs/pins"
+
+ additionalProperties: false
+
+allOf:
+ - $ref: pinctrl.yaml#
+
+required:
+ - compatible
+
+additionalProperties: false
+
+$defs:
+ pins:
+ properties:
+ groups:
+ description:
+ List of pin groups to select in this subnode.
+ items:
+ enum: [spi0_0_grp, spi0_1_grp, spi0_2_grp, spi0_3_grp, spi0_4_grp, spi0_5_grp,
+ spi0_ss_0_grp, spi0_ss_1_grp, spi0_ss_2_grp, spi0_ss_3_grp, spi0_ss_4_grp,
+ spi0_ss_5_grp, spi0_ss_6_grp, spi0_ss_7_grp, spi0_ss_8_grp, spi0_ss_9_grp,
+ spi0_ss_10_grp, spi0_ss_11_grp, spi0_ss_12_grp, spi0_ss_13_grp, spi0_ss_14_grp,
+ spi0_ss_15_grp, spi0_ss_16_grp, spi0_ss_17_grp, spi1_0_grp, spi1_1_grp,
+ spi1_2_grp, spi1_3_grp, spi1_4_grp, spi1_5_grp, spi1_ss_0_grp, spi1_ss_1_grp,
+ spi1_ss_2_grp, spi1_ss_3_grp, spi1_ss_4_grp, spi1_ss_5_grp, spi1_ss_6_grp,
+ spi1_ss_7_grp, spi1_ss_8_grp, spi1_ss_9_grp, spi1_ss_10_grp, spi1_ss_11_grp,
+ spi1_ss_12_grp, spi1_ss_13_grp, spi1_ss_14_grp, spi1_ss_15_grp, spi1_ss_16_grp
+ spi1_ss_17_grp, can0_0_grp, can0_1_grp, can0_2_grp, can0_3_grp, can0_4_grp,
+ can0_5_grp, can0_6_grp, can0_7_grp, can0_8_grp, can0_9_grp, can0_10_grp,
+ can0_11_grp, can0_12_grp, can0_13_grp, can0_14_grp, can0_15_grp, can0_16_grp,
+ can0_17_grp, can1_0_grp, can1_1_grp, can1_2_grp, can1_3_grp, can1_4_grp,
+ can1_5_grp, can1_6_grp, can1_7_grp, can1_8_grp, can1_9_grp, can1_10_grp,
+ can1_11_grp, can1_12_grp, can1_13_grp, can1_14_grp, can1_15_grp, can1_16_grp,
+ can1_17_grp, can1_18_grp, i2c0_0_grp, i2c0_1_grp, i2c0_2_grp, i2c0_3_grp,
+ i2c0_4_grp, i2c0_5_grp, i2c0_6_grp, i2c0_7_grp, i2c0_8_grp, i2c0_9_grp,
+ i2c0_10_grp, i2c0_11_grp, i2c0_12_grp, i2c0_13_grp, i2c0_14_grp, i2c0_15_grp,
+ i2c0_16_grp, i2c0_17_grp, i2c1_0_grp, i2c1_1_grp, i2c1_2_grp, i2c1_3_grp,
+ i2c1_4_grp, i2c1_5_grp, i2c1_6_grp, i2c1_7_grp, i2c1_8_grp, i2c1_9_grp,
+ i2c1_10_grp, i2c1_11_grp, i2c1_12_grp, i2c1_13_grp, i2c1_14_grp, i2c1_15_grp,
+ i2c1_16_grp, i2c1_17_grp, i2c1_18_grp, i2c_pmc_0_grp, i2c_pmc_1_grp,
+ i2c_pmc_2_grp, i2c_pmc_3_grp, i2c_pmc_4_grp, i2c_pmc_5_grp, i2c_pmc_6_grp,
+ i2c_pmc_7_grp, i2c_pmc_8_grp, i2c_pmc_9_grp, i2c_pmc_10_grp, i2c_pmc_11_grp,
+ i2c_pmc_12_grp, ttc0_clk_0_grp, ttc0_clk_1_grp, ttc0_clk_2_grp, ttc0_clk_3_grp,
+ ttc0_clk_4_grp, ttc0_clk_5_grp, ttc0_clk_6_grp, ttc0_clk_7_grp, ttc0_clk_8_grp,
+ ttc0_wav_0_grp, ttc0_wav_1_grp, ttc0_wav_2_grp, ttc0_wav_3_grp, ttc0_wav_4_grp,
+ ttc0_wav_5_grp, ttc0_wav_6_grp, ttc0_wav_7_grp, ttc0_wav_8_grp, ttc1_clk_0_grp,
+ ttc1_clk_1_grp, ttc1_clk_2_grp, ttc1_clk_3_grp, ttc1_clk_4_grp, ttc1_clk_5_grp,
+ ttc1_clk_6_grp, ttc1_clk_7_grp, ttc1_clk_8_grp, ttc1_wav_0_grp, ttc1_wav_1_grp,
+ ttc1_wav_2_grp, ttc1_wav_3_grp, ttc1_wav_4_grp, ttc1_wav_5_grp, ttc1_wav_6_grp,
+ ttc1_wav_7_grp, ttc1_wav_8_grp, ttc2_clk_0_grp, ttc2_clk_1_grp, ttc2_clk_2_grp,
+ ttc2_clk_3_grp, ttc2_clk_4_grp, ttc2_clk_5_grp, ttc2_clk_6_grp, ttc2_clk_7_grp,
+ ttc2_clk_8_grp, ttc2_wav_0_grp, ttc2_wav_1_grp, ttc2_wav_2_grp, ttc2_wav_3_grp,
+ ttc2_wav_4_grp, ttc2_wav_5_grp, ttc2_wav_6_grp, ttc2_wav_7_grp, ttc2_wav_8_grp,
+ ttc3_clk_0_grp, ttc3_clk_1_grp, ttc3_clk_2_grp, ttc3_clk_3_grp, ttc3_clk_4_grp,
+ ttc3_clk_5_grp, ttc3_clk_6_grp, ttc3_clk_7_grp, ttc3_clk_8_grp, ttc3_wav_0_grp,
+ ttc3_wav_1_grp, ttc3_wav_2_grp, ttc3_wav_3_grp, ttc3_wav_4_grp, ttc3_wav_5_grp,
+ ttc3_wav_6_grp, ttc3_wav_7_grp, ttc3_wav_8_grp, wwdt0_0_grp, wwdt0_1_grp,
+ wwdt0_2_grp, wwdt0_3_grp, wwdt0_4_grp, wwdt0_5_grp, wwdt1_0_grp, wwdt1_1_grp,
+ wwdt1_2_grp, wwdt1_3_grp, wwdt1_4_grp, wwdt1_5_grp, sysmon_i2c0_0_grp,
+ sysmon_i2c0_1_grp, sysmon_i2c0_2_grp, sysmon_i2c0_3_grp, sysmon_i2c0_4_grp,
+ sysmon_i2c0_5_grp, sysmon_i2c0_6_grp, sysmon_i2c0_7_grp, sysmon_i2c0_8_grp,
+ sysmon_i2c0_9_grp, sysmon_i2c0_10_grp, sysmon_i2c0_11_grp, sysmon_i2c0_12_grp,
+ sysmon_i2c0_13_grp, sysmon_i2c0_14_grp, sysmon_i2c0_15_grp,
+ sysmon_i2c0_16_grp, sysmon_i2c0_17_grp, sysmon_i2c0_alrt_0_grp,
+ sysmon_i2c0_alrt_1_grp, sysmon_i2c0_alrt_2_grp, sysmon_i2c0_alrt_3_grp,
+ sysmon_i2c0_alrt_4_grp, sysmon_i2c0_alrt_5_grp, sysmon_i2c0_alrt_6_grp,
+ sysmon_i2c0_alrt_7_grp, sysmon_i2c0_alrt_8_grp, sysmon_i2c0_alrt_9_grp,
+ sysmon_i2c0_alrt_10_grp, sysmon_i2c0_alrt_11_grp, sysmon_i2c0_alrt_12_grp,
+ sysmon_i2c0_alrt_13_grp, sysmon_i2c0_alrt_14_grp, sysmon_i2c0_alrt_15_grp,
+ sysmon_i2c0_alrt_16_grp, sysmon_i2c0_alrt_17_grp, uart0_0_grp, uart0_1_grp,
+ uart0_2_grp, uart0_3_grp, uart0_4_grp, uart0_5_grp, uart0_6_grp, uart0_7_grp,
+ uart0_8_grp, uart0_ctrl_0_grp, uart0_ctrl_1_grp, uart0_ctrl_2_grp,
+ uart0_ctrl_3_grp, uart0_ctrl_4_grp, uart0_ctrl_5_grp, uart0_ctrl_6_grp,
+ uart0_ctrl_7_grp, uart0_ctrl_8_grp, uart1_0_grp, uart1_1_grp, uart1_2_grp,
+ uart1_3_grp, uart1_4_grp, uart1_5_grp, uart1_6_grp, uart1_7_grp, uart1_8_grp,
+ uart1_ctrl_0_grp, uart1_ctrl_1_grp, uart1_ctrl_2_grp, uart1_ctrl_3_grp,
+ uart1_ctrl_4_grp, uart1_ctrl_5_grp, uart1_ctrl_6_grp, uart1_ctrl_7_grp,
+ uart1_ctrl_8_grp, gpio0_0_grp, gpio0_1_grp, gpio0_2_grp, gpio0_3_grp,
+ gpio0_4_grp, gpio0_5_grp, gpio0_6_grp, gpio0_7_grp, gpio0_8_grp, gpio0_9_grp,
+ gpio0_10_grp, gpio0_11_grp, gpio0_12_grp, gpio0_13_grp, gpio0_14_grp,
+ gpio0_15_grp, gpio0_16_grp, gpio0_17_grp, gpio0_18_grp, gpio0_19_grp,
+ gpio0_20_grp, gpio0_21_grp, gpio0_22_grp, gpio0_23_grp, gpio0_24_grp,
+ gpio0_25_grp, gpio1_0_grp, gpio1_1_grp, gpio1_2_grp, gpio1_3_grp, gpio1_4_grp,
+ gpio1_5_grp, gpio1_6_grp, gpio1_7_grp, gpio1_8_grp, gpio1_9_grp,
+ gpio1_10_grp, gpio1_11_grp, gpio1_12_grp, gpio1_13_grp, gpio1_14_grp,
+ gpio1_15_grp, gpio1_16_grp, gpio1_17_grp, gpio1_18_grp, gpio1_19_grp,
+ gpio1_20_grp, gpio1_21_grp, gpio1_22_grp, gpio1_23_grp, gpio1_24_grp,
+ gpio1_25_grp, gpio2_0_grp, gpio2_1_grp, gpio2_2_grp, gpio2_3_grp, gpio2_4_grp,
+ gpio2_5_grp, gpio2_6_grp, gpio2_7_grp, gpio2_8_grp, gpio2_9_grp, gpio2_10_grp,
+ gpio2_11_grp, gpio2_12_grp, gpio2_13_grp, gpio2_14_grp, gpio2_15_grp,
+ gpio2_16_grp, gpio2_17_grp, gpio2_18_grp, gpio2_19_grp, gpio2_20_grp,
+ gpio2_21_grp, gpio2_22_grp, gpio2_23_grp, gpio2_24_grp, gpio2_25_grp,
+ emio0_0_grp, emio0_1_grp, emio0_2_grp, emio0_3_grp, emio0_4_grp, emio0_5_grp,
+ emio0_6_grp, emio0_7_grp, emio0_8_grp, emio0_9_grp, emio0_10_grp,
+ emio0_11_grp, emio0_12_grp, emio0_13_grp, emio0_14_grp, emio0_15_grp,
+ emio0_16_grp, emio0_17_grp, emio0_18_grp, emio0_19_grp, emio0_20_grp,
+ emio0_21_grp, emio0_22_grp, emio0_23_grp, emio0_24_grp, emio0_25_grp,
+ emio0_26_grp, emio0_27_grp, emio0_28_grp, emio0_29_grp, emio0_30_grp,
+ emio0_31_grp, emio0_32_grp, emio0_33_grp, emio0_34_grp, emio0_35_grp,
+ emio0_36_grp, emio0_37_grp, emio0_38_grp, emio0_39_grp, emio0_40_grp,
+ emio0_41_grp, emio0_42_grp, emio0_43_grp, emio0_44_grp, emio0_45_grp,
+ emio0_46_grp, emio0_47_grp, emio0_48_grp, emio0_49_grp, emio0_50_grp,
+ emio0_51_grp, emio0_52_grp, emio0_53_grp, emio0_54_grp, emio0_55_grp,
+ emio0_56_grp, emio0_57_grp, emio0_58_grp, emio0_59_grp, emio0_60_grp,
+ emio0_61_grp, emio0_62_grp, emio0_63_grp, emio0_64_grp, emio0_65_grp,
+ emio0_66_grp, emio0_67_grp, emio0_68_grp, emio0_69_grp, emio0_70_grp,
+ emio0_71_grp, emio0_72_grp, emio0_73_grp, emio0_74_grp, emio0_75_grp,
+ emio0_76_grp, emio0_77_grp, gem0_0_grp, gem0_1_grp, gem1_0_grp, gem1_1_grp,
+ trace0_0_grp, trace0_1_grp, trace0_2_grp, trace0_clk_0_grp, trace0_clk_1_grp,
+ trace0_clk_2_grp, mdio0_0_grp, mdio0_1_grp, mdio1_0_grp, mdio1_1_grp,
+ gem_tsu0_0_grp, gem_tsu0_1_grp, gem_tsu0_2_grp, gem_tsu0_3_grp, pcie0_0_grp,
+ pcie0_1_grp, pcie0_2_grp, smap0_0_grp, usb0_0_grp, sd0_0_grp, sd0_1_grp,
+ sd0_2_grp, sd0_3_grp, sd0_4_grp, sd0_5_grp, sd0_6_grp, sd0_7_grp, sd0_8_grp,
+ sd0_9_grp, sd0_10_grp, sd0_11_grp, sd0_12_grp, sd0_13_grp, sd0_14_grp,
+ sd0_15_grp, sd0_16_grp, sd0_17_grp, sd0_18_grp, sd0_19_grp, sd0_20_grp,
+ sd0_21_grp, sd0_pc_0_grp, sd0_pc_1_grp, sd0_cd_0_grp, sd0_cd_1_grp,
+ sd0_wp_0_grp, sd0_wp_1_grp, sd1_0_grp, sd1_1_grp, sd1_2_grp, sd1_3_grp,
+ sd1_4_grp, sd1_5_grp, sd1_6_grp, sd1_7_grp, sd1_8_grp, sd1_9_grp, sd1_10_grp,
+ sd1_11_grp, sd1_12_grp, sd1_13_grp, sd1_14_grp, sd1_15_grp, sd1_16_grp,
+ sd1_17_grp, sd1_18_grp, sd1_19_grp, sd1_20_grp, sd1_21_grp, sd1_pc_0_grp,
+ sd1_pc_1_grp, sd1_cd_0_grp, sd1_cd_1_grp, sd1_wp_0_grp, sd1_wp_1_grp,
+ ospi0_0_grp, ospi0_ss_0_grp, qspi0_0_grp, qspi0_fbclk_0_grp, qspi0_ss_0_grp,
+ test_clk_0_grp, test_scan_0_grp, tamper_trigger_0_grp]
+ minItems: 1
+ maxItems: 78
+
+ pins:
+ description:
+ List of pin names to select in this subnode.
+ items:
+ pattern: '^((LPD|PMC)_)MIO([0-9]|[1-6][0-9]|7[0-7])$'
+ minItems: 1
+ maxItems: 78
+
+ bias-pull-up: true
+ bias-pull-down: true
+ bias-disable: true
+ input-schmitt-enable: true
+ input-schmitt-disable: true
+ bias-high-impedance: true
+ low-power-enable: true
+ low-power-disable: true
+
+ slew-rate:
+ enum: [0, 1]
+
+ output-enable:
+ description:
+ This will internally disable the tri-state for MIO pins.
+
+ drive-strength:
+ description:
+ Selects the drive strength for MIO pins, in mA.
+ enum: [2, 4, 8, 12]
+
+ power-source:
+ enum: [0, 1]
+
+ oneOf:
+ - required: [ groups ]
+ - required: [ pins ]
+
+ additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+ pinctrl {
+ compatible = "xlnx,versal-pinctrl";
+
+ uart0-default {
+ mux {
+ groups = "uart0_4_grp", "uart0_5_grp";
+ function = "uart0";
+ };
+
+ conf {
+ groups = "uart0_4_grp";
+ slew-rate = <SLEW_RATE_SLOW>;
+ power-source = <IO_STANDARD_LVCMOS18>;
+ };
+
+ conf-rx {
+ pins = "PMC_MIO42";
+ bias-pull-up;
+ };
+
+ conf-tx {
+ pins = "PMC_MIO43";
+ bias-disable;
+ input-schmitt-disable;
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.yaml b/Documentation/devicetree/bindings/power/fsl,imx-gpc.yaml
index c21a66422d4f..9de3fe73c1eb 100644
--- a/Documentation/devicetree/bindings/power/fsl,imx-gpc.yaml
+++ b/Documentation/devicetree/bindings/power/fsl,imx-gpc.yaml
@@ -30,6 +30,7 @@ properties:
- enum:
- fsl,imx6qp-gpc
- fsl,imx6sl-gpc
+ - fsl,imx6sll-gpc
- fsl,imx6sx-gpc
- fsl,imx6ul-gpc
- const: fsl,imx6q-gpc
diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
index 8985e2df8a56..6d37c06b2f65 100644
--- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
+++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
@@ -23,6 +23,7 @@ properties:
compatible:
enum:
+ - mediatek,mt6735-power-controller
- mediatek,mt6795-power-controller
- mediatek,mt8167-power-controller
- mediatek,mt8173-power-controller
diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
index 929b7ef9c1bc..655687369a23 100644
--- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
@@ -32,11 +32,14 @@ properties:
- qcom,msm8998-rpmpd
- qcom,qcm2290-rpmpd
- qcom,qcs404-rpmpd
+ - qcom,qcs615-rpmhpd
+ - qcom,qcs8300-rpmhpd
- qcom,qdu1000-rpmhpd
- qcom,qm215-rpmpd
- qcom,sa8155p-rpmhpd
- qcom,sa8540p-rpmhpd
- qcom,sa8775p-rpmhpd
+ - qcom,sar2130p-rpmhpd
- qcom,sc7180-rpmhpd
- qcom,sc7280-rpmhpd
- qcom,sc8180x-rpmhpd
@@ -58,6 +61,7 @@ properties:
- qcom,sm8450-rpmhpd
- qcom,sm8550-rpmhpd
- qcom,sm8650-rpmhpd
+ - qcom,sm8750-rpmhpd
- qcom,x1e80100-rpmhpd
- items:
- enum:
diff --git a/Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt b/Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt
deleted file mode 100644
index 933f0c48e887..000000000000
--- a/Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Device Tree Bindings for Power Controller on MediaTek PMIC
-
-The power controller which could be found on PMIC is responsible for externally
-powering off or on the remote MediaTek SoC through the circuit BBPU.
-
-Required properties:
-- compatible: Should be one of follows
- "mediatek,mt6323-pwrc": for MT6323 PMIC
-
-Example:
-
- pmic {
- compatible = "mediatek,mt6323";
-
- ...
-
- power-controller {
- compatible = "mediatek,mt6323-pwrc";
- };
- }
diff --git a/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml b/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml
index 627f8a6078c2..7f5f94673e9c 100644
--- a/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml
+++ b/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml
@@ -31,6 +31,10 @@ properties:
allOf:
- $ref: reboot-mode.yaml#
+patternProperties:
+ "^mode-.*$":
+ maxItems: 1
+
required:
- compatible
- nvmem-cells
diff --git a/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml b/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml
index fc8105a7b9b2..3da3d02a6690 100644
--- a/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml
+++ b/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml
@@ -54,6 +54,10 @@ required:
- compatible
- reg
+patternProperties:
+ "^mode-.*$":
+ maxItems: 1
+
unevaluatedProperties: false
allOf:
@@ -75,6 +79,9 @@ allOf:
reg-names:
items:
- const: pon
+ else:
+ patternProperties:
+ "^mode-.*$": false
# Special case for pm8941, which doesn't store reset mode
- if:
diff --git a/Documentation/devicetree/bindings/power/reset/reboot-mode.yaml b/Documentation/devicetree/bindings/power/reset/reboot-mode.yaml
index ad0a0b95cec1..3ddac06cec72 100644
--- a/Documentation/devicetree/bindings/power/reset/reboot-mode.yaml
+++ b/Documentation/devicetree/bindings/power/reset/reboot-mode.yaml
@@ -28,13 +28,13 @@ description: |
properties:
mode-normal:
- $ref: /schemas/types.yaml#/definitions/uint32
+ $ref: /schemas/types.yaml#/definitions/uint32-array
description:
Default value to set on a reboot if no command was provided.
patternProperties:
"^mode-.*$":
- $ref: /schemas/types.yaml#/definitions/uint32
+ $ref: /schemas/types.yaml#/definitions/uint32-array
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/power/reset/syscon-reboot-mode.yaml b/Documentation/devicetree/bindings/power/reset/syscon-reboot-mode.yaml
index b6acff199cde..79ffc78b23ea 100644
--- a/Documentation/devicetree/bindings/power/reset/syscon-reboot-mode.yaml
+++ b/Documentation/devicetree/bindings/power/reset/syscon-reboot-mode.yaml
@@ -32,6 +32,10 @@ properties:
allOf:
- $ref: reboot-mode.yaml#
+patternProperties:
+ "^mode-.*$":
+ maxItems: 1
+
unevaluatedProperties: false
required:
diff --git a/Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml b/Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml
index 75061124d9a8..19d3093e6cd2 100644
--- a/Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml
+++ b/Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml
@@ -31,6 +31,10 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
description: Offset in the register map for the reboot register (in bytes).
+ reg:
+ maxItems: 1
+ description: Base address and size for the reboot register.
+
regmap:
$ref: /schemas/types.yaml#/definitions/phandle
deprecated: true
@@ -45,9 +49,14 @@ properties:
priority:
default: 192
+oneOf:
+ - required:
+ - offset
+ - required:
+ - reg
+
required:
- compatible
- - offset
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml b/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml
index 277c47e048b6..a0f9d49ff8fb 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml
+++ b/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml
@@ -60,7 +60,6 @@ examples:
pmic {
#address-cells = <1>;
#size-cells = <0>;
- #interrupt-cells = <4>;
charger@1000 {
compatible = "qcom,pmi8998-charger";
diff --git a/Documentation/devicetree/bindings/power/supply/sc2731-charger.yaml b/Documentation/devicetree/bindings/power/supply/sc2731-charger.yaml
index a846a4d14ca9..f5aa72502b4e 100644
--- a/Documentation/devicetree/bindings/power/supply/sc2731-charger.yaml
+++ b/Documentation/devicetree/bindings/power/supply/sc2731-charger.yaml
@@ -30,23 +30,4 @@ properties:
- constant-charge-voltage-max-microvolt: maximum constant input voltage.
additionalProperties: false
-
-examples:
- - |
- bat: battery {
- compatible = "simple-battery";
- charge-term-current-microamp = <120000>;
- constant-charge-voltage-max-microvolt = <4350000>;
- };
-
- pmic {
- #address-cells = <1>;
- #size-cells = <0>;
-
- battery@a00 {
- compatible = "sprd,sc2731-charger";
- reg = <0x0>;
- phys = <&ssphy>;
- monitored-battery = <&bat>;
- };
- };
+...
diff --git a/Documentation/devicetree/bindings/power/supply/sc27xx-fg.yaml b/Documentation/devicetree/bindings/power/supply/sc27xx-fg.yaml
index 9108a2841caf..c1de2c80291d 100644
--- a/Documentation/devicetree/bindings/power/supply/sc27xx-fg.yaml
+++ b/Documentation/devicetree/bindings/power/supply/sc27xx-fg.yaml
@@ -27,6 +27,11 @@ properties:
battery-detect-gpios:
maxItems: 1
+ bat-detect-gpio:
+ maxItems: 1
+ deprecated: true
+ description: use battery-detect-gpios instead
+
interrupts:
maxItems: 1
@@ -65,40 +70,4 @@ required:
- monitored-battery
additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/gpio/gpio.h>
- bat: battery {
- compatible = "simple-battery";
- charge-full-design-microamp-hours = <1900000>;
- constant-charge-voltage-max-microvolt = <4350000>;
- ocv-capacity-celsius = <20>;
- ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>,
- <4022000 85>, <3983000 80>, <3949000 75>,
- <3917000 70>, <3889000 65>, <3864000 60>,
- <3835000 55>, <3805000 50>, <3787000 45>,
- <3777000 40>, <3773000 35>, <3770000 30>,
- <3765000 25>, <3752000 20>, <3724000 15>,
- <3680000 10>, <3605000 5>, <3400000 0>;
- // ...
- };
-
- pmic {
- #address-cells = <1>;
- #size-cells = <0>;
-
- battery@a00 {
- compatible = "sprd,sc2731-fgu";
- reg = <0xa00>;
- battery-detect-gpios = <&pmic_eic 9 GPIO_ACTIVE_HIGH>;
- interrupt-parent = <&sc2731_pmic>;
- interrupts = <4>;
- io-channels = <&pmic_adc 5>, <&pmic_adc 14>;
- io-channel-names = "bat-temp", "charge-vol";
- nvmem-cells = <&fgu_calib>;
- nvmem-cell-names = "fgu_calib";
- monitored-battery = <&bat>;
- sprd,calib-resistance-micro-ohms = <21500>;
- };
- };
+...
diff --git a/Documentation/devicetree/bindings/power/supply/ti,twl6030-charger.yaml b/Documentation/devicetree/bindings/power/supply/ti,twl6030-charger.yaml
new file mode 100644
index 000000000000..fc604d8a469d
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/ti,twl6030-charger.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/ti,twl6030-charger.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TWL6030/32 BCI (Battery Charger Interface)
+
+description:
+ The battery charger needs to be configured to do any charging besides of
+ precharging. The GPADC in the PMIC has to be used to get the related
+ voltages.
+
+maintainers:
+ - Andreas Kemnade <andreas@kemnade.info>
+
+allOf:
+ - $ref: power-supply.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - const: ti,twl6030-charger
+ - items:
+ - const: ti,twl6032-charger
+ - const: ti,twl6030-charger
+
+ interrupts:
+ items:
+ - description: Charger Control Interrupt
+ - description: Charger Fault Interrupt
+
+ io-channels:
+ items:
+ - description: VBUS Voltage Channel
+
+ io-channel-names:
+ items:
+ - const: vusb
+
+ monitored-battery: true
+
+required:
+ - compatible
+ - interrupts
+ - monitored-battery
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml b/Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml
index ec6115d3796b..aa35209f74cf 100644
--- a/Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml
+++ b/Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml
@@ -27,7 +27,7 @@ properties:
maxItems: 1
"#pwm-cells":
- const: 2
+ const: 3
clocks:
maxItems: 1
@@ -44,5 +44,5 @@ examples:
compatible = "adi,axi-pwmgen-2.00.a";
reg = <0x44b00000 0x1000>;
clocks = <&spi_clk>;
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
};
diff --git a/Documentation/devicetree/bindings/pwm/airoha,en7581-pwm.yaml b/Documentation/devicetree/bindings/pwm/airoha,en7581-pwm.yaml
new file mode 100644
index 000000000000..f36387572a97
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/airoha,en7581-pwm.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/airoha,en7581-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha EN7581 PWM Controller
+
+maintainers:
+ - Lorenzo Bianconi <lorenzo@kernel.org>
+
+allOf:
+ - $ref: pwm.yaml#
+
+properties:
+ compatible:
+ const: airoha,en7581-pwm
+
+ "#pwm-cells":
+ const: 3
+
+required:
+ - compatible
+ - "#pwm-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ pwm {
+ compatible = "airoha,en7581-pwm";
+
+ #pwm-cells = <3>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml b/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml
index e021cf59421a..cc3ebd4deeb6 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml
+++ b/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml
@@ -39,6 +39,7 @@ properties:
- amlogic,meson-s4-pwm
- items:
- enum:
+ - amlogic,c3-pwm
- amlogic,meson-a1-pwm
- const: amlogic,meson-s4-pwm
- items:
diff --git a/Documentation/devicetree/bindings/regulator/lltc,ltc3676.yaml b/Documentation/devicetree/bindings/regulator/lltc,ltc3676.yaml
new file mode 100644
index 000000000000..f47eacf96cd6
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/lltc,ltc3676.yaml
@@ -0,0 +1,167 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/lltc,ltc3676.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Linear Technology LTC3676 8-output regulators
+
+maintainers:
+ - Tim Harvey <tharvey@gateworks.com>
+
+description: |
+ LTC3676 contains eight regulators, 4 switching SW1..SW4 and four LDO1..4 .
+
+properties:
+ compatible:
+ const: lltc,ltc3676
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ regulators:
+ type: object
+ additionalProperties: false
+ description: |
+ List of regulators provided by this controller, must be named
+ after their hardware counterparts (SW|LDO)[1-4].
+
+ patternProperties:
+ "^(sw[1-4]|ldo[24])$":
+ type: object
+ unevaluatedProperties: false
+ $ref: regulator.yaml#
+ description:
+ Properties for single SW or LDO regulator. Regulators SW1..SW4 can
+ regulate the feedback reference from 412.5mV to 800mV in 12.5 mV
+ steps. The output voltage thus ranges between 0.4125 * (1 + R1/R2) V
+ and 0.8 * (1 + R1/R2) V.
+ Regulators LDO1, LDO2, LDO4 have a fixed 0.725 V reference and thus
+ output 0.725 * (1 + R1/R2) V.
+ The LDO1 standby regulator can not be disabled and thus should have
+ the regulator-always-on property set.
+
+ properties:
+ lltc,fb-voltage-divider:
+ description:
+ An array of two integers containing the resistor values
+ R1 and R2 of the feedback voltage divider in ohms.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 2
+ maxItems: 2
+
+ required:
+ - lltc,fb-voltage-divider
+
+ properties:
+ ldo1:
+ type: object
+ unevaluatedProperties: false
+ $ref: regulator.yaml#
+ description:
+ The LDO1 standby regulator can not be disabled and thus should
+ have the regulator-always-on property set. See patternProperties
+ description above for the rest of the details.
+
+ properties:
+ lltc,fb-voltage-divider:
+ description:
+ An array of two integers containing the resistor values
+ R1 and R2 of the feedback voltage divider in ohms.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 2
+ maxItems: 2
+
+ required:
+ - lltc,fb-voltage-divider
+ - regulator-always-on
+
+ ldo3:
+ type: object
+ unevaluatedProperties: false
+ $ref: regulator.yaml#
+ description:
+ The LDO3 regulator is fixed to 1.8 V. See patternProperties
+ description above for the rest of the details.
+
+required:
+ - compatible
+ - reg
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@3c {
+ compatible = "lltc,ltc3676";
+ reg = <0x3c>;
+
+ regulators {
+ sw1_reg: sw1 {
+ regulator-min-microvolt = <674400>;
+ regulator-max-microvolt = <1308000>;
+ lltc,fb-voltage-divider = <127000 200000>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <1033310>;
+ regulator-max-microvolt = <200400>;
+ lltc,fb-voltage-divider = <301000 200000>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3_reg: sw3 {
+ regulator-min-microvolt = <674400>;
+ regulator-max-microvolt = <130800>;
+ lltc,fb-voltage-divider = <127000 200000>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <868310>;
+ regulator-max-microvolt = <168400>;
+ lltc,fb-voltage-divider = <221000 200000>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2_reg: ldo2 {
+ regulator-min-microvolt = <2490375>;
+ regulator-max-microvolt = <2490375>;
+ lltc,fb-voltage-divider = <487000 200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3_reg: ldo3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ ldo4_reg: ldo4 {
+ regulator-min-microvolt = <3023250>;
+ regulator-max-microvolt = <3023250>;
+ lltc,fb-voltage-divider = <634000 200000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/ltc3676.txt b/Documentation/devicetree/bindings/regulator/ltc3676.txt
deleted file mode 100644
index d4eb366ce18c..000000000000
--- a/Documentation/devicetree/bindings/regulator/ltc3676.txt
+++ /dev/null
@@ -1,94 +0,0 @@
-Linear Technology LTC3676 8-output regulators
-
-Required properties:
-- compatible: "lltc,ltc3676"
-- reg: I2C slave address
-
-Required child node:
-- regulators: Contains eight regulator child nodes sw1, sw2, sw3, sw4,
- ldo1, ldo2, ldo3, and ldo4, specifying the initialization data as
- documented in Documentation/devicetree/bindings/regulator/regulator.txt.
-
-Each regulator is defined using the standard binding for regulators. The
-nodes for sw1, sw2, sw3, sw4, ldo1, ldo2 and ldo4 additionally need to specify
-the resistor values of their external feedback voltage dividers:
-
-Required properties (not on ldo3):
-- lltc,fb-voltage-divider: An array of two integers containing the resistor
- values R1 and R2 of the feedback voltage divider in ohms.
-
-Regulators sw1, sw2, sw3, sw4 can regulate the feedback reference from:
-412.5mV to 800mV in 12.5 mV steps. The output voltage thus ranges between
-0.4125 * (1 + R1/R2) V and 0.8 * (1 + R1/R2) V.
-
-Regulators ldo1, ldo2, and ldo4 have a fixed 0.725 V reference and thus output
-0.725 * (1 + R1/R2) V. The ldo3 regulator is fixed to 1.8 V. The ldo1 standby
-regulator can not be disabled and thus should have the regulator-always-on
-property set.
-
-Example:
-
- ltc3676: pmic@3c {
- compatible = "lltc,ltc3676";
- reg = <0x3c>;
-
- regulators {
- sw1_reg: sw1 {
- regulator-min-microvolt = <674400>;
- regulator-max-microvolt = <1308000>;
- lltc,fb-voltage-divider = <127000 200000>;
- regulator-ramp-delay = <7000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- sw2_reg: sw2 {
- regulator-min-microvolt = <1033310>;
- regulator-max-microvolt = <200400>;
- lltc,fb-voltage-divider = <301000 200000>;
- regulator-ramp-delay = <7000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- sw3_reg: sw3 {
- regulator-min-microvolt = <674400>;
- regulator-max-microvolt = <130800>;
- lltc,fb-voltage-divider = <127000 200000>;
- regulator-ramp-delay = <7000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- sw4_reg: sw4 {
- regulator-min-microvolt = <868310>;
- regulator-max-microvolt = <168400>;
- lltc,fb-voltage-divider = <221000 200000>;
- regulator-ramp-delay = <7000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ldo2_reg: ldo2 {
- regulator-min-microvolt = <2490375>;
- regulator-max-microvolt = <2490375>;
- lltc,fb-voltage-divider = <487000 200000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ldo3_reg: ldo3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-boot-on;
- };
-
- ldo4_reg: ldo4 {
- regulator-min-microvolt = <3023250>;
- regulator-max-microvolt = <3023250>;
- lltc,fb-voltage-divider = <634000 200000>;
- regulator-boot-on;
- regulator-always-on;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
index 11ed04c95542..ca401a209cca 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
@@ -33,6 +33,12 @@ properties:
vddpmu-supply:
description: VDD_PMU supply regulator handle
+ vddpmumx-supply:
+ description: VDD_PMU_MX supply regulator handle
+
+ vddpmucx-supply:
+ description: VDD_PMU_CX supply regulator handle
+
vddio1p2-supply:
description: VDD_IO_1P2 supply regulator handle
@@ -72,6 +78,10 @@ properties:
maxItems: 1
description: GPIO line indicating the state of the clock supply to the BT module
+ xo-clk-gpios:
+ maxItems: 1
+ description: GPIO line allowing to select the XO clock configuration for the module
+
clocks:
maxItems: 1
description: Reference clock handle
@@ -119,6 +129,8 @@ allOf:
- vddio-supply
- vddaon-supply
- vddpmu-supply
+ - vddpmumx-supply
+ - vddpmucx-supply
- vddrfa0p95-supply
- vddrfa1p3-supply
- vddrfa1p9-supply
diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
index 27c6d5152413..3a5a0a6cf5cc 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
@@ -349,7 +349,6 @@ allOf:
properties:
compatible:
enum:
- - qcom,pm8550ve-rpmh-regulators
- qcom,pm8550vs-rpmh-regulators
then:
patternProperties:
@@ -385,6 +384,7 @@ allOf:
compatible:
enum:
- qcom,pmc8380-rpmh-regulators
+ - qcom,pm8550ve-rpmh-regulators
then:
patternProperties:
"^vdd-l[1-3]-supply$": true
diff --git a/Documentation/devicetree/bindings/regulator/qcom-labibb-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom-labibb-regulator.yaml
index e987c39b223e..83965076d6ab 100644
--- a/Documentation/devicetree/bindings/regulator/qcom-labibb-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom-labibb-regulator.yaml
@@ -16,7 +16,12 @@ description:
properties:
compatible:
- const: qcom,pmi8998-lab-ibb
+ oneOf:
+ - const: qcom,pmi8998-lab-ibb
+ - items:
+ - enum:
+ - qcom,pmi8950-lab-ibb
+ - const: qcom,pmi8998-lab-ibb
lab:
type: object
diff --git a/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
index ffb2924dde36..9bd752bab68e 100644
--- a/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/sprd,sc2731-regulator.yaml
@@ -43,25 +43,4 @@ required:
- compatible
additionalProperties: false
-
-examples:
- - |
- regulators {
- compatible = "sprd,sc2731-regulator";
-
- BUCK_CPU0 {
- regulator-name = "vddarm0";
- regulator-min-microvolt = <400000>;
- regulator-max-microvolt = <1996875>;
- regulator-ramp-delay = <25000>;
- regulator-always-on;
- };
-
- LDO_CAMA0 {
- regulator-name = "vddcama0";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <3750000>;
- regulator-enable-ramp-delay = <100>;
- };
- };
...
diff --git a/Documentation/devicetree/bindings/regulator/vctrl-regulator.yaml b/Documentation/devicetree/bindings/regulator/vctrl-regulator.yaml
new file mode 100644
index 000000000000..6132b8e5b498
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/vctrl-regulator.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/vctrl-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Voltage controlled regulators
+
+maintainers:
+ - Heiko Stuebner <heiko@sntech.de>
+
+allOf:
+ - $ref: regulator.yaml#
+
+properties:
+ compatible:
+ const: vctrl-regulator
+
+ ctrl-supply:
+ description: Regulator supplying the control voltage
+
+ ctrl-voltage-range:
+ description:
+ Array of two integer values describing the range (min/max) of the
+ control voltage. The values specify the control voltage needed to
+ generate the corresponding regulator-min/max-microvolt output
+ voltage.
+ minItems: 2
+ maxItems: 2
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+
+ min-slew-down-rate:
+ description:
+ Describes how slowly the regulator voltage will decay down in the
+ worst case (lightest expected load). Specified in uV / us (like
+ main regulator ramp rate). This value is required when
+ ovp-threshold-percent is specified.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ ovp-threshold-percent:
+ description:
+ Overvoltage protection (OVP) threshold of the regulator in percent.
+ Some regulators have an OVP circuitry which shuts down the regulator
+ when the actual output voltage deviates beyond a certain margin from
+ the expected value for a given control voltage. On larger voltage
+ decreases this can occur undesiredly since the output voltage does
+ not adjust immediately to changes in the control voltage. To avoid
+ this situation the vctrl driver breaks down larger voltage decreases
+ into multiple steps, where each step is within the OVP threshold.
+ minimum: 0
+ maximum: 100
+
+unevaluatedProperties: false
+
+dependencies:
+ ovp-threshold-percent: [ min-slew-down-rate ]
+
+required:
+ - compatible
+ - ctrl-supply
+ - ctrl-voltage-range
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+
+examples:
+ - |
+ vctrl-reg {
+ compatible = "vctrl-regulator";
+ regulator-name = "vctrl_reg";
+
+ ctrl-supply = <&ctrl_reg>;
+ ctrl-voltage-range = <200000 500000>;
+
+ min-slew-down-rate = <225>;
+ ovp-threshold-percent = <16>;
+
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1500000>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/regulator/vctrl.txt b/Documentation/devicetree/bindings/regulator/vctrl.txt
deleted file mode 100644
index e940377cfd69..000000000000
--- a/Documentation/devicetree/bindings/regulator/vctrl.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-Bindings for Voltage controlled regulators
-==========================================
-
-Required properties:
---------------------
-- compatible : must be "vctrl-regulator".
-- regulator-min-microvolt : smallest voltage consumers may set
-- regulator-max-microvolt : largest voltage consumers may set
-- ctrl-supply : The regulator supplying the control voltage.
-- ctrl-voltage-range : an array of two integer values describing the range
- (min/max) of the control voltage. The values specify
- the control voltage needed to generate the corresponding
- regulator-min/max-microvolt output voltage.
-
-Optional properties:
---------------------
-- ovp-threshold-percent : overvoltage protection (OVP) threshold of the
- regulator in percent. Some regulators have an OVP
- circuitry which shuts down the regulator when the
- actual output voltage deviates beyond a certain
- margin from the expected value for a given control
- voltage. On larger voltage decreases this can occur
- undesiredly since the output voltage does not adjust
- immediately to changes in the control voltage. To
- avoid this situation the vctrl driver breaks down
- larger voltage decreases into multiple steps, where
- each step is within the OVP threshold.
-- min-slew-down-rate : Describes how slowly the regulator voltage will decay
- down in the worst case (lightest expected load).
- Specified in uV / us (like main regulator ramp rate).
- This value is required when ovp-threshold-percent is
- specified.
-
-Example:
-
- vctrl-reg {
- compatible = "vctrl-regulator";
- regulator-name = "vctrl_reg";
-
- ctrl-supply = <&ctrl_reg>;
-
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <1500000>;
-
- ctrl-voltage-range = <200000 500000>;
-
- min-slew-down-rate = <225>;
- ovp-threshold-percent = <16>;
- };
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml
index 4b9fb74fb9e9..fd3423e6051b 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml
@@ -16,6 +16,7 @@ description:
properties:
compatible:
enum:
+ - qcom,sar2130p-adsp-pas
- qcom,sm8350-adsp-pas
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
@@ -61,6 +62,7 @@ allOf:
properties:
compatible:
enum:
+ - qcom,sar2130p-adsp-pas
- qcom,sm8350-adsp-pas
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
@@ -101,6 +103,7 @@ allOf:
properties:
compatible:
enum:
+ - qcom,sar2130p-adsp-pas
- qcom,sm8350-adsp-pas
- qcom,sm8350-slpi-pas
- qcom,sm8450-adsp-pas
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml
index d7fad7b3c2c6..a24cbb61bda7 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml
@@ -15,16 +15,20 @@ description:
properties:
compatible:
- enum:
- - qcom,sdx75-mpss-pas
- - qcom,sm8550-adsp-pas
- - qcom,sm8550-cdsp-pas
- - qcom,sm8550-mpss-pas
- - qcom,sm8650-adsp-pas
- - qcom,sm8650-cdsp-pas
- - qcom,sm8650-mpss-pas
- - qcom,x1e80100-adsp-pas
- - qcom,x1e80100-cdsp-pas
+ oneOf:
+ - enum:
+ - qcom,sdx75-mpss-pas
+ - qcom,sm8550-adsp-pas
+ - qcom,sm8550-cdsp-pas
+ - qcom,sm8550-mpss-pas
+ - qcom,sm8650-adsp-pas
+ - qcom,sm8650-cdsp-pas
+ - qcom,sm8650-mpss-pas
+ - qcom,x1e80100-adsp-pas
+ - qcom,x1e80100-cdsp-pas
+ - items:
+ - const: qcom,sm8750-adsp-pas
+ - const: qcom,sm8550-adsp-pas
reg:
maxItems: 1
@@ -85,6 +89,20 @@ allOf:
- if:
properties:
compatible:
+ contains:
+ enum:
+ - qcom,sm8750-adsp-pas
+ then:
+ properties:
+ interrupts:
+ maxItems: 6
+ interrupt-names:
+ maxItems: 6
+ memory-region:
+ maxItems: 2
+ - if:
+ properties:
+ compatible:
enum:
- qcom,sm8650-cdsp-pas
then:
@@ -129,10 +147,12 @@ allOf:
- if:
properties:
compatible:
- enum:
- - qcom,sm8550-adsp-pas
- - qcom,sm8650-adsp-pas
- - qcom,x1e80100-adsp-pas
+ contains:
+ enum:
+ - qcom,sm8550-adsp-pas
+ - qcom,sm8650-adsp-pas
+ - qcom,sm8750-adsp-pas
+ - qcom,x1e80100-adsp-pas
then:
properties:
power-domains:
diff --git a/Documentation/devicetree/bindings/reset/nuvoton,npcm750-reset.yaml b/Documentation/devicetree/bindings/reset/nuvoton,npcm750-reset.yaml
index d82e65e37cc0..72523f1bbc18 100644
--- a/Documentation/devicetree/bindings/reset/nuvoton,npcm750-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/nuvoton,npcm750-reset.yaml
@@ -21,6 +21,13 @@ properties:
'#reset-cells':
const: 2
+ '#clock-cells':
+ const: 1
+
+ clocks:
+ items:
+ - description: specify external 25MHz reference clock.
+
nuvoton,sysgcr:
$ref: /schemas/types.yaml#/definitions/phandle
description: a phandle to access GCR registers.
@@ -39,6 +46,17 @@ required:
- '#reset-cells'
- nuvoton,sysgcr
+if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nuvoton,npcm845-reset
+then:
+ required:
+ - '#clock-cells'
+ - clocks
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index 2cf2026cff57..9c7dd7e75e0c 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -128,6 +128,18 @@ properties:
changes to interrupts as frozen at commit ccbddab ("Merge pull
request #42 from riscv/jhauser-2023-RC4") of riscv-aia.
+ - const: smmpm
+ description: |
+ The standard Smmpm extension for M-mode pointer masking as
+ ratified at commit d70011dde6c2 ("Update to ratified state")
+ of riscv-j-extension.
+
+ - const: smnpm
+ description: |
+ The standard Smnpm extension for next-mode pointer masking as
+ ratified at commit d70011dde6c2 ("Update to ratified state")
+ of riscv-j-extension.
+
- const: smstateen
description: |
The standard Smstateen extension for controlling access to CSRs
@@ -147,12 +159,46 @@ properties:
and mode-based filtering as ratified at commit 01d1df0 ("Add ability
to manually trigger workflow. (#2)") of riscv-count-overflow.
+ - const: ssnpm
+ description: |
+ The standard Ssnpm extension for next-mode pointer masking as
+ ratified at commit d70011dde6c2 ("Update to ratified state")
+ of riscv-j-extension.
+
- const: sstc
description: |
The standard Sstc supervisor-level extension for time compare as
ratified at commit 3f9ed34 ("Add ability to manually trigger
workflow. (#2)") of riscv-time-compare.
+ - const: svade
+ description: |
+ The standard Svade supervisor-level extension for SW-managed PTE A/D
+ bit updates as ratified in the 20240213 version of the privileged
+ ISA specification.
+
+ Both Svade and Svadu extensions control the hardware behavior when
+ the PTE A/D bits need to be set. The default behavior for the four
+ possible combinations of these extensions in the device tree are:
+ 1) Neither Svade nor Svadu present in DT => It is technically
+ unknown whether the platform uses Svade or Svadu. Supervisor
+ software should be prepared to handle either hardware updating
+ of the PTE A/D bits or page faults when they need updated.
+ 2) Only Svade present in DT => Supervisor must assume Svade to be
+ always enabled.
+ 3) Only Svadu present in DT => Supervisor must assume Svadu to be
+ always enabled.
+ 4) Both Svade and Svadu present in DT => Supervisor must assume
+ Svadu turned-off at boot time. To use Svadu, supervisor must
+ explicitly enable it using the SBI FWFT extension.
+
+ - const: svadu
+ description: |
+ The standard Svadu supervisor-level extension for hardware updating
+ of PTE A/D bits as ratified in the 20240528 version of the
+ privileged ISA specification. Please refer to Svade dt-binding
+ description for more details.
+
- const: svinval
description:
The standard Svinval supervisor-level extension for fine-grained
@@ -178,6 +224,12 @@ properties:
as ratified at commit 4a69197e5617 ("Update to ratified state") of
riscv-svvptc.
+ - const: zabha
+ description: |
+ The Zabha extension for Byte and Halfword Atomic Memory Operations
+ as ratified at commit 49f49c842ff9 ("Update to Rafified state") of
+ riscv-zabha.
+
- const: zacas
description: |
The Zacas extension for Atomic Compare-and-Swap (CAS) instructions
@@ -290,6 +342,12 @@ properties:
in commit 64074bc ("Update version numbers for Zfh/Zfinx") of
riscv-isa-manual.
+ - const: ziccrse
+ description:
+ The standard Ziccrse extension which provides forward progress
+ guarantee on LR/SC sequences, as ratified in commit b1d806605f87
+ ("Updated to ratified state.") of the riscv profiles specification.
+
- const: zk
description:
The standard Zk Standard Scalar cryptography extension as ratified
diff --git a/Documentation/devicetree/bindings/riscv/starfive.yaml b/Documentation/devicetree/bindings/riscv/starfive.yaml
index 4d5c857b3cac..7ef85174353d 100644
--- a/Documentation/devicetree/bindings/riscv/starfive.yaml
+++ b/Documentation/devicetree/bindings/riscv/starfive.yaml
@@ -26,6 +26,7 @@ properties:
- items:
- enum:
+ - deepcomputing,fml13v01
- milkv,mars
- pine64,star64
- starfive,visionfive-2-v1.2a
diff --git a/Documentation/devicetree/bindings/rng/airoha,en7581-trng.yaml b/Documentation/devicetree/bindings/rng/airoha,en7581-trng.yaml
new file mode 100644
index 000000000000..dfc6d24ee7d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/rng/airoha,en7581-trng.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rng/airoha,en7581-trng.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha EN7851 True Random Number Generator
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+properties:
+ compatible:
+ const: airoha,en7581-trng
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ rng@1faa1000 {
+ compatible = "airoha,en7581-trng";
+ reg = <0x1faa1000 0x1000>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm74110-rng.yaml b/Documentation/devicetree/bindings/rng/brcm,bcm74110-rng.yaml
new file mode 100644
index 000000000000..8e89d4a70b53
--- /dev/null
+++ b/Documentation/devicetree/bindings/rng/brcm,bcm74110-rng.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rng/brcm,bcm74110-rng.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: BCM74110 Random number generator
+
+description:
+ Random number generator used on the BCM74110.
+
+maintainers:
+ - Markus Mayer <mmayer@broadcom.com>
+ - Florian Fainelli <florian.fainelli@broadcom.com>
+
+properties:
+ compatible:
+ enum:
+ - brcm,bcm74110-rng
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ rng@83ba000 {
+ compatible = "brcm,bcm74110-rng";
+ reg = <0x83ba000 0x14>;
+ };
diff --git a/Documentation/devicetree/bindings/rng/imx-rng.yaml b/Documentation/devicetree/bindings/rng/imx-rng.yaml
index 07f6ff89bcc1..252fa9a41abe 100644
--- a/Documentation/devicetree/bindings/rng/imx-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/imx-rng.yaml
@@ -14,8 +14,8 @@ properties:
oneOf:
- const: fsl,imx21-rnga
- const: fsl,imx25-rngb
+ - const: fsl,imx31-rnga
- items:
- - const: fsl,imx31-rnga
- const: fsl,imx21-rnga
- items:
- enum:
diff --git a/Documentation/devicetree/bindings/rng/omap_rng.yaml b/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml
index c0ac4f68ea54..0877eb44f9ed 100644
--- a/Documentation/devicetree/bindings/rng/omap_rng.yaml
+++ b/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml
@@ -1,20 +1,25 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/rng/omap_rng.yaml#
+$id: http://devicetree.org/schemas/rng/inside-secure,safexcel-eip76.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: OMAP SoC and Inside-Secure HWRNG Module
+title: Inside-Secure HWRNG Module
maintainers:
- Jayesh Choudhary <j-choudhary@ti.com>
properties:
compatible:
- enum:
- - ti,omap2-rng
- - ti,omap4-rng
- - inside-secure,safexcel-eip76
+ oneOf:
+ - enum:
+ - ti,omap2-rng
+ - ti,omap4-rng
+ - inside-secure,safexcel-eip76
+ - items:
+ - enum:
+ - marvell,armada-8k-rng
+ - const: inside-secure,safexcel-eip76
ti,hwmods:
const: rng
diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
index 340d01d481d1..7db65f49773b 100644
--- a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
@@ -18,12 +18,19 @@ properties:
enum:
- st,stm32-rng
- st,stm32mp13-rng
+ - st,stm32mp25-rng
reg:
maxItems: 1
clocks:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: core
+ - const: bus
resets:
maxItems: 1
@@ -57,6 +64,25 @@ allOf:
properties:
st,rng-lock-conf: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - st,stm32-rng
+ - st,stm32mp13-rng
+ then:
+ properties:
+ clocks:
+ maxItems: 1
+ clock-names: false
+ else:
+ properties:
+ clocks:
+ minItems: 2
+ required:
+ - clock-names
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index 4531eec568a6..9df5cdb6f63f 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -30,7 +30,9 @@ properties:
- const: allwinner,sun50i-a64-rtc
- const: allwinner,sun8i-h3-rtc
- items:
- - const: allwinner,sun20i-d1-rtc
+ - enum:
+ - allwinner,sun20i-d1-rtc
+ - allwinner,sun55i-a523-rtc
- const: allwinner,sun50i-r329-rtc
reg:
diff --git a/Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml b/Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml
new file mode 100644
index 000000000000..5d3ac737abcb
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2024 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/amlogic,a4-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic A4 and A5 RTC
+
+maintainers:
+ - Yiting Deng <yiting.deng@amlogic.com>
+ - Xianwei Zhao <xianwei.zhao@amlogic.com>
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ enum:
+ - amlogic,a4-rtc
+ - amlogic,a5-rtc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: RTC clock source, available 24M or 32K crystal
+ oscillator source. when using 24M, need to divide 24M into 32K.
+ - description: RTC module accesses the clock of the apb bus.
+
+ clock-names:
+ items:
+ - const: osc
+ - const: sys
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ apb {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ rtc@8e600 {
+ compatible = "amlogic,a4-rtc";
+ reg = <0x0 0x8e600 0x0 0x38>;
+ clocks = <&xtal_32k>, <&clkc_periphs 1>;
+ clock-names = "osc", "sys";
+ interrupts = <GIC_SPI 131 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml b/Documentation/devicetree/bindings/rtc/microchip,mpfs-rtc.yaml
index 7742465b9383..a3e60d9f8399 100644
--- a/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/microchip,mpfs-rtc.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/rtc/microchip,mfps-rtc.yaml#
+$id: http://devicetree.org/schemas/rtc/microchip,mpfs-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
@@ -12,12 +12,14 @@ allOf:
maintainers:
- Daire McNamara <daire.mcnamara@microchip.com>
- - Lewis Hanly <lewis.hanly@microchip.com>
properties:
compatible:
- enum:
- - microchip,mpfs-rtc
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-rtc
+ - const: microchip,mpfs-rtc
+ - const: microchip,mpfs-rtc
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml b/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml
new file mode 100644
index 000000000000..e70eeb66aa64
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/renesas,rz-rtca3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RTCA-3 Real Time Clock
+
+maintainers:
+ - Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a08g045-rtca3 # RZ/G3S
+ - const: renesas,rz-rtca3
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: Alarm interrupt
+ - description: Periodic interrupt
+ - description: Carry interrupt
+
+ interrupt-names:
+ items:
+ - const: alarm
+ - const: period
+ - const: carry
+
+ clocks:
+ items:
+ - description: RTC bus clock
+ - description: RTC counter clock
+
+ clock-names:
+ items:
+ - const: bus
+ - const: counter
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: VBATTB module reset
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a08g045-cpg.h>
+ #include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ rtc@1004ec00 {
+ compatible = "renesas,r9a08g045-rtca3", "renesas,rz-rtca3";
+ reg = <0x1004ec00 0x400>;
+ interrupts = <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "alarm", "period", "carry";
+ clocks = <&cpg CPG_MOD R9A08G045_VBAT_BCLK>, <&vbattclk VBATTB_VBATTCLK>;
+ clock-names = "bus", "counter";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_VBAT_BRESETN>;
+ };
diff --git a/Documentation/devicetree/bindings/rtc/rtc-mt6397.txt b/Documentation/devicetree/bindings/rtc/rtc-mt6397.txt
deleted file mode 100644
index 7212076a8f1b..000000000000
--- a/Documentation/devicetree/bindings/rtc/rtc-mt6397.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-Device-Tree bindings for MediaTek PMIC based RTC
-
-MediaTek PMIC based RTC is an independent function of MediaTek PMIC that works
-as a type of multi-function device (MFD). The RTC can be configured and set up
-with PMIC wrapper bus which is a common resource shared with the other
-functions found on the same PMIC.
-
-For MediaTek PMIC MFD bindings, see:
-../mfd/mt6397.txt
-
-For MediaTek PMIC wrapper bus bindings, see:
-../soc/mediatek/pwrap.txt
-
-Required properties:
-- compatible: Should be one of follows
- "mediatek,mt6323-rtc": for MT6323 PMIC
- "mediatek,mt6358-rtc": for MT6358 PMIC
- "mediatek,mt6366-rtc", "mediatek,mt6358-rtc": for MT6366 PMIC
- "mediatek,mt6397-rtc": for MT6397 PMIC
-
-Example:
-
- pmic {
- compatible = "mediatek,mt6323";
-
- ...
-
- rtc {
- compatible = "mediatek,mt6323-rtc";
- };
- };
diff --git a/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml b/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml
index f3d20e976965..5756f617df36 100644
--- a/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/sprd,sc2731-rtc.yaml
@@ -30,20 +30,4 @@ allOf:
- $ref: rtc.yaml#
unevaluatedProperties: false
-
-examples:
- - |
- #include <dt-bindings/interrupt-controller/irq.h>
-
- pmic {
- #address-cells = <1>;
- #size-cells = <0>;
-
- rtc@280 {
- compatible = "sprd,sc2731-rtc";
- reg = <0x280>;
- interrupt-parent = <&sc2731_pmic>;
- interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
- };
- };
...
diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml
index 9418fd66a8e9..b93254ad2a28 100644
--- a/Documentation/devicetree/bindings/serial/rs485.yaml
+++ b/Documentation/devicetree/bindings/serial/rs485.yaml
@@ -18,16 +18,15 @@ properties:
description: prop-encoded-array <a b>
$ref: /schemas/types.yaml#/definitions/uint32-array
items:
- items:
- - description: Delay between rts signal and beginning of data sent in
- milliseconds. It corresponds to the delay before sending data.
- default: 0
- maximum: 100
- - description: Delay between end of data sent and rts signal in milliseconds.
- It corresponds to the delay after sending data and actual release
- of the line.
- default: 0
- maximum: 100
+ - description: Delay between rts signal and beginning of data sent in
+ milliseconds. It corresponds to the delay before sending data.
+ default: 0
+ maximum: 100
+ - description: Delay between end of data sent and rts signal in milliseconds.
+ It corresponds to the delay after sending data and actual release
+ of the line.
+ default: 0
+ maximum: 100
rs485-rts-active-high:
description: drive RTS high when sending (this is the default).
diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.yaml b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
index 788c80e47831..070eba9f19d3 100644
--- a/Documentation/devicetree/bindings/serial/samsung_uart.yaml
+++ b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
@@ -27,6 +27,7 @@ properties:
- samsung,exynos4210-uart
- samsung,exynos5433-uart
- samsung,exynos850-uart
+ - samsung,exynos8895-uart
- items:
- enum:
- samsung,exynos7-uart
@@ -160,18 +161,27 @@ allOf:
contains:
enum:
- google,gs101-uart
+ - samsung,exynos8895-uart
then:
required:
- samsung,uart-fifosize
properties:
- reg-io-width: false
-
clocks:
maxItems: 2
clock-names:
maxItems: 2
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - google,gs101-uart
+ then:
+ properties:
+ reg-io-width: false
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index 4cdb0dcaccf3..1c163cb5dff1 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -37,6 +37,8 @@ properties:
- const: renesas,rzn1-uart
- items:
- enum:
+ - brcm,bcm11351-dw-apb-uart
+ - brcm,bcm21664-dw-apb-uart
- rockchip,px30-uart
- rockchip,rk1808-uart
- rockchip,rk3036-uart
@@ -48,18 +50,13 @@ properties:
- rockchip,rk3328-uart
- rockchip,rk3368-uart
- rockchip,rk3399-uart
+ - rockchip,rk3528-uart
- rockchip,rk3568-uart
+ - rockchip,rk3576-uart
- rockchip,rk3588-uart
- rockchip,rv1108-uart
- rockchip,rv1126-uart
- - const: snps,dw-apb-uart
- - items:
- - enum:
- - brcm,bcm11351-dw-apb-uart
- - brcm,bcm21664-dw-apb-uart
- - const: snps,dw-apb-uart
- - items:
- - enum:
+ - sophgo,sg2044-uart
- starfive,jh7100-hsuart
- starfive,jh7100-uart
- starfive,jh7110-uart
diff --git a/Documentation/devicetree/bindings/serial/sprd-uart.yaml b/Documentation/devicetree/bindings/serial/sprd-uart.yaml
index f4dbb6dc2b6e..a2a5056eba04 100644
--- a/Documentation/devicetree/bindings/serial/sprd-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/sprd-uart.yaml
@@ -17,6 +17,7 @@ properties:
oneOf:
- items:
- enum:
+ - sprd,sc9632-uart
- sprd,sc9860-uart
- sprd,sc9863a-uart
- sprd,ums512-uart
diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx-anatop.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx-anatop.yaml
index c4ae4f28422b..f40c157908aa 100644
--- a/Documentation/devicetree/bindings/soc/imx/fsl,imx-anatop.yaml
+++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx-anatop.yaml
@@ -36,6 +36,7 @@ properties:
- description: Temperature sensor event
- description: Brown-out event on either of the support regulators
- description: Brown-out event on either the core, gpu or soc regulators
+ minItems: 2
tempmon:
type: object
@@ -43,7 +44,7 @@ properties:
$ref: /schemas/thermal/imx-thermal.yaml
patternProperties:
- "regulator-((1p1)|(2p5)|(3p0)|(vddcore)|(vddpu)|(vddsoc))$":
+ "regulator-((1p1)|(2p5)|(3p0)|(vdd1p0d)|(vdd1p2)|(vddcore)|(vddpcie)|(vddpu)|(vddsoc))$":
type: object
unevaluatedProperties: false
$ref: /schemas/regulator/anatop-regulator.yaml
@@ -52,6 +53,23 @@ required:
- compatible
- reg
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx7d-anatop
+ then:
+ properties:
+ interrupts:
+ maxItems: 2
+ else:
+ properties:
+ interrupts:
+ minItems: 3
+ maxItems: 3
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml
new file mode 100644
index 000000000000..1ad5b61b249f
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mt8183-dvfsrc.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/mediatek/mediatek,mt8183-dvfsrc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Dynamic Voltage and Frequency Scaling Resource Collector (DVFSRC)
+
+description:
+ The Dynamic Voltage and Frequency Scaling Resource Collector (DVFSRC) is a
+ Hardware module used to collect all the requests from both software and the
+ various remote processors embedded into the SoC and decide about a minimum
+ operating voltage and a minimum DRAM frequency to fulfill those requests in
+ an effort to provide the best achievable performance per watt.
+ This hardware IP is capable of transparently performing direct register R/W
+ on all of the DVFSRC-controlled regulators and SoC bandwidth knobs.
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ - Henry Chen <henryc.chen@mediatek.com>
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - mediatek,mt8183-dvfsrc
+ - mediatek,mt8195-dvfsrc
+ - items:
+ - const: mediatek,mt8192-dvfsrc
+ - const: mediatek,mt8195-dvfsrc
+
+ reg:
+ maxItems: 1
+ description: DVFSRC common register address and length.
+
+ regulators:
+ type: object
+ $ref: /schemas/regulator/mediatek,mt6873-dvfsrc-regulator.yaml#
+
+ interconnect:
+ type: object
+ $ref: /schemas/interconnect/mediatek,mt8183-emi.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ system-controller@10012000 {
+ compatible = "mediatek,mt8195-dvfsrc";
+ reg = <0 0x10012000 0 0x1000>;
+
+ regulators {
+ compatible = "mediatek,mt8195-dvfsrc-regulator";
+
+ dvfsrc_vcore: dvfsrc-vcore {
+ regulator-name = "dvfsrc-vcore";
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <750000>;
+ regulator-always-on;
+ };
+
+ dvfsrc_vscp: dvfsrc-vscp {
+ regulator-name = "dvfsrc-vscp";
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <750000>;
+ regulator-always-on;
+ };
+ };
+
+ emi_icc: interconnect {
+ compatible = "mediatek,mt8195-emi";
+ #interconnect-cells = <1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index 2bc367793aec..3530a6668b48 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -20,6 +20,7 @@ Required properties:
- compatible: Should be one of:
- "mediatek,mt2701-scpsys"
- "mediatek,mt2712-scpsys"
+ - "mediatek,mt6735-scpsys"
- "mediatek,mt6765-scpsys"
- "mediatek,mt6797-scpsys"
- "mediatek,mt7622-scpsys"
diff --git a/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml b/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml
index a46411149571..2c7275c4503b 100644
--- a/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml
+++ b/Documentation/devicetree/bindings/soc/microchip/atmel,at91rm9200-tcb.yaml
@@ -15,13 +15,19 @@ description: |
properties:
compatible:
- items:
- - enum:
- - atmel,at91rm9200-tcb
- - atmel,at91sam9x5-tcb
- - atmel,sama5d2-tcb
- - const: simple-mfd
- - const: syscon
+ oneOf:
+ - items:
+ - enum:
+ - atmel,at91rm9200-tcb
+ - atmel,at91sam9x5-tcb
+ - atmel,sama5d2-tcb
+ - const: simple-mfd
+ - const: syscon
+ - items:
+ - const: microchip,sam9x7-tcb
+ - const: atmel,sama5d2-tcb
+ - const: simple-mfd
+ - const: syscon
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml
index f7e606d45ebc..6d11472ba5a7 100644
--- a/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml
+++ b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml
@@ -41,9 +41,7 @@ properties:
enum: [ 1, 2 ]
'#clock-cells':
- description:
- Cell is clock index. Optional if compatible has a single clock.
- enum: [ 0, 1 ]
+ const: 1
clocks:
maxItems: 1
@@ -312,26 +310,6 @@ allOf:
properties:
'#reset-cells': false
- # Compatibles exposing a single clock.
- - if:
- properties:
- compatible:
- contains:
- enum:
- - mobileye,eyeq6h-central-olb
- - mobileye,eyeq6h-east-olb
- - mobileye,eyeq6h-west-olb
- - mobileye,eyeq6h-ddr0-olb
- - mobileye,eyeq6h-ddr1-olb
- then:
- properties:
- '#clock-cells':
- const: 0
- else:
- properties:
- '#clock-cells':
- const: 1
-
# Only EyeQ5 has pinctrl in OLB.
- if:
not:
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
index 7afdb60edb22..e63f800c6caa 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
@@ -25,8 +25,11 @@ properties:
compatible:
items:
- enum:
+ - qcom,qcs8300-aoss-qmp
- qcom,qdu1000-aoss-qmp
+ - qcom,sa8255p-aoss-qmp
- qcom,sa8775p-aoss-qmp
+ - qcom,sar2130p-aoss-qmp
- qcom,sc7180-aoss-qmp
- qcom,sc7280-aoss-qmp
- qcom,sc8180x-aoss-qmp
@@ -40,6 +43,7 @@ properties:
- qcom,sm8450-aoss-qmp
- qcom,sm8550-aoss-qmp
- qcom,sm8650-aoss-qmp
+ - qcom,sm8750-aoss-qmp
- qcom,x1e80100-aoss-qmp
- const: qcom,aoss-qmp
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
index 141d666dc3f7..1ba1d419e83b 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
@@ -55,8 +55,7 @@ properties:
qcom,smem:
$ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- maxItems: 2
+ maxItems: 2
description:
Two identifiers of the inbound and outbound smem items used for this edge.
diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
index 50d727f4b76c..7eca9e1ad6a3 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
@@ -33,9 +33,11 @@ properties:
- rockchip,rk3576-usb-grf
- rockchip,rk3576-usbdpphy-grf
- rockchip,rk3576-vo0-grf
+ - rockchip,rk3576-vo1-grf
- rockchip,rk3576-vop-grf
- rockchip,rk3588-bigcore0-grf
- rockchip,rk3588-bigcore1-grf
+ - rockchip,rk3588-dcphy-grf
- rockchip,rk3588-hdptxphy-grf
- rockchip,rk3588-ioc
- rockchip,rk3588-php-grf
@@ -80,6 +82,7 @@ properties:
- rockchip,rk3568-pmugrf
- rockchip,rk3576-ioc-grf
- rockchip,rk3576-pmu0-grf
+ - rockchip,rk3576-usb2phy-grf
- rockchip,rk3588-usb2phy-grf
- rockchip,rv1108-grf
- rockchip,rv1108-pmugrf
@@ -233,6 +236,7 @@ allOf:
- rockchip,rk3308-usb2phy-grf
- rockchip,rk3328-usb2phy-grf
- rockchip,rk3399-grf
+ - rockchip,rk3576-usb2phy-grf
- rockchip,rk3588-usb2phy-grf
- rockchip,rv1108-grf
@@ -283,6 +287,7 @@ allOf:
compatible:
contains:
enum:
+ - rockchip,rk3576-vo1-grf
- rockchip,rk3588-vo-grf
- rockchip,rk3588-vo0-grf
- rockchip,rk3588-vo1-grf
diff --git a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
index 15fcd8f1d8bc..6cdfe7e059a3 100644
--- a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
+++ b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
@@ -53,6 +53,8 @@ properties:
- items:
- enum:
- samsung,exynos7885-pmu
+ - samsung,exynos8895-pmu
+ - samsung,exynos9810-pmu
- samsung,exynosautov9-pmu
- samsung,exynosautov920-pmu
- tesla,fsd-pmu
diff --git a/Documentation/devicetree/bindings/sound/adi,adau1373.yaml b/Documentation/devicetree/bindings/sound/adi,adau1373.yaml
new file mode 100644
index 000000000000..97552bf5d951
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/adi,adau1373.yaml
@@ -0,0 +1,111 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/adi,adau1373.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices ADAU1373 CODEC
+
+maintainers:
+ - Nuno Sá <nuno.sa@analog.com>
+
+description: |
+ Analog Devices ADAU1373 Low power codec with speaker and headphone amplifiers.
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1373.pdf
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - adi,adau1373
+
+ reg:
+ maxItems: 1
+
+ "#sound-dai-cells":
+ const: 0
+
+ powerdown-gpios:
+ description: GPIO used for hardware power-down.
+ maxItems: 1
+
+ adi,micbias1-microvolt:
+ description:
+ This property sets the microphone bias voltage for the first microphone.
+ enum: [1800000, 2200000, 2600000, 2900000]
+ default: 2900000
+
+ adi,micbias2-microvolt:
+ description:
+ This property sets the microphone bias voltage for the second microphone.
+ enum: [1800000, 2200000, 2600000, 2900000]
+ default: 2900000
+
+ adi,input1-differential:
+ description: This property sets the first analog input as differential.
+ type: boolean
+
+ adi,input2-differential:
+ description: This property sets the second analog input as differential.
+ type: boolean
+
+ adi,input3-differential:
+ description: This property sets the third analog input as differential.
+ type: boolean
+
+ adi,input4-differential:
+ description: This property sets the fourth analog input as differential.
+ type: boolean
+
+ adi,lineout-differential:
+ description: This property sets the line output as differential.
+ type: boolean
+
+ adi,lineout-gnd-sense:
+ description: This property enables the line output ground sense control.
+ type: boolean
+
+ adi,drc-settings:
+ description:
+ This setting is used to control the dynamic range of the signal. The
+ device provides a maximum of three full band DRCs with 13 entries each.
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ oneOf:
+ - minItems: 13
+ maxItems: 13
+ - minItems: 26
+ maxItems: 26
+ - minItems: 39
+ maxItems: 39
+
+required:
+ - "#sound-dai-cells"
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ audio-codec@1a {
+ compatible = "adi,adau1373";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ powerdown-gpios = <&gpio 100 GPIO_ACTIVE_LOW>;
+ adi,input2-differential;
+ adi,input1-differential;
+ adi,lineout-differential;
+ adi,micbias2-microvolt = <1800000>;
+ adi,drc-settings = /bits/ 8 <
+ 0xff 0xff 0x1 0x2 0xa 0xa 0xd 0x1 0xff 0xff 0x5 0xd 0xff
+ >;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
index 78273647f766..ebc9097f936a 100644
--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
@@ -22,6 +22,7 @@ properties:
- allwinner,sun8i-a23-codec
- allwinner,sun8i-h3-codec
- allwinner,sun8i-v3s-codec
+ - allwinner,sun50i-h616-codec
reg:
maxItems: 1
@@ -40,14 +41,20 @@ properties:
- const: codec
dmas:
- items:
- - description: RX DMA Channel
- - description: TX DMA Channel
+ oneOf:
+ - items:
+ - description: RX DMA Channel
+ - description: TX DMA Channel
+ - items:
+ - description: TX DMA Channel
dma-names:
- items:
- - const: rx
- - const: tx
+ oneOf:
+ - items:
+ - const: rx
+ - const: tx
+ - items:
+ - const: tx
resets:
maxItems: 1
@@ -229,6 +236,40 @@ allOf:
- Mic
- Speaker
+ - if:
+ properties:
+ compatible:
+ enum:
+ - allwinner,sun50i-h616-codec
+
+ then:
+ properties:
+ allwinner,audio-routing:
+ items:
+ enum:
+ - LINEOUT
+ - Line Out
+
+ dmas:
+ items:
+ - description: TX DMA Channel
+
+ dma-names:
+ items:
+ - const: tx
+
+ else:
+ properties:
+ dmas:
+ items:
+ - description: RX DMA Channel
+ - description: TX DMA Channel
+
+ dma-names:
+ items:
+ - const: rx
+ - const: tx
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/sound/audio-graph.yaml b/Documentation/devicetree/bindings/sound/audio-graph.yaml
index 71f52f7e55f6..9899d9d1958d 100644
--- a/Documentation/devicetree/bindings/sound/audio-graph.yaml
+++ b/Documentation/devicetree/bindings/sound/audio-graph.yaml
@@ -37,8 +37,14 @@ properties:
pa-gpios:
maxItems: 1
hp-det-gpio:
+ deprecated: true
+ maxItems: 1
+ hp-det-gpios:
maxItems: 1
mic-det-gpio:
+ deprecated: true
+ maxItems: 1
+ mic-det-gpios:
maxItems: 1
required:
diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
index ac5f2e0f42cb..3b0b743e49c4 100644
--- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
+++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml
@@ -17,8 +17,9 @@ description:
properties:
compatible:
enum:
- - awinic,aw88395
+ - awinic,aw88081
- awinic,aw88261
+ - awinic,aw88395
- awinic,aw88399
reg:
@@ -56,6 +57,7 @@ allOf:
compatible:
contains:
enum:
+ - awinic,aw88081
- awinic,aw88261
then:
properties:
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l84.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l84.yaml
new file mode 100644
index 000000000000..7f8338e8ae36
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l84.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/cirrus,cs42l84.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic CS42L84 audio CODEC
+
+maintainers:
+ - Martin Povišer <povik+lin@cutebit.org>
+
+description: |
+ The CS42L84 is a headphone jack codec made by Cirrus Logic and embedded
+ in personal computers sold by Apple. It was first seen in 2021 Macbook
+ Pro models. It has stereo DAC for playback, mono ADC for capture, and
+ is somewhat similar to CS42L42 but with a different regmap.
+
+properties:
+ compatible:
+ enum:
+ - cirrus,cs42l84
+
+ reg:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ jack_codec: codec@4b {
+ compatible = "cirrus,cs42l84";
+ reg = <0x4b>;
+ reset-gpios = <&pinctrl_nub 4 GPIO_ACTIVE_LOW>;
+ interrupts-extended = <&pinctrl_ap 180 IRQ_TYPE_LEVEL_LOW>;
+ #sound-dai-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.yaml b/Documentation/devicetree/bindings/sound/everest,es8316.yaml
index 214f135b7777..e4b2eb5fae2f 100644
--- a/Documentation/devicetree/bindings/sound/everest,es8316.yaml
+++ b/Documentation/devicetree/bindings/sound/everest,es8316.yaml
@@ -4,12 +4,13 @@
$id: http://devicetree.org/schemas/sound/everest,es8316.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Everest ES8311 and ES8316 audio CODECs
+title: Everest ES8311, ES8316 and ES8323 audio CODECs
maintainers:
- Daniel Drake <drake@endlessm.com>
- Katsuhiro Suzuki <katsuhiro@katsuster.net>
- Matteo Martelli <matteomartelli3@gmail.com>
+ - Binbin Zhou <zhoubinbin@loongson.cn>
allOf:
- $ref: dai-common.yaml#
@@ -19,6 +20,7 @@ properties:
enum:
- everest,es8311
- everest,es8316
+ - everest,es8323
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/sound/everest,es8326.yaml b/Documentation/devicetree/bindings/sound/everest,es8326.yaml
index d51431df7acf..b5594a9d508e 100644
--- a/Documentation/devicetree/bindings/sound/everest,es8326.yaml
+++ b/Documentation/devicetree/bindings/sound/everest,es8326.yaml
@@ -24,6 +24,10 @@ properties:
items:
- const: mclk
+ interrupts:
+ maxItems: 1
+ description: interrupt output for headset detection
+
"#sound-dai-cells":
const: 0
diff --git a/Documentation/devicetree/bindings/sound/everest,es8328.yaml b/Documentation/devicetree/bindings/sound/everest,es8328.yaml
index a0f4670fa38c..ed18e40dcaac 100644
--- a/Documentation/devicetree/bindings/sound/everest,es8328.yaml
+++ b/Documentation/devicetree/bindings/sound/everest,es8328.yaml
@@ -50,6 +50,10 @@ properties:
HPVDD-supply:
description: Regulator providing analog output voltage 3.3V
+ port:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+
required:
- compatible
- clocks
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.yaml b/Documentation/devicetree/bindings/sound/fsl,esai.yaml
index f99ed20fa684..27c34ce4c2e2 100644
--- a/Documentation/devicetree/bindings/sound/fsl,esai.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,esai.yaml
@@ -18,11 +18,15 @@ description:
properties:
compatible:
- enum:
- - fsl,imx35-esai
- - fsl,imx6ull-esai
- - fsl,imx8qm-esai
- - fsl,vf610-esai
+ oneOf:
+ - enum:
+ - fsl,imx35-esai
+ - fsl,imx6ull-esai
+ - fsl,vf610-esai
+ - items:
+ - enum:
+ - fsl,imx8qm-esai
+ - const: fsl,imx6ull-esai
reg:
maxItems: 1
@@ -65,6 +69,9 @@ properties:
- const: rx
- const: tx
+ power-domains:
+ maxItems: 1
+
fsl,fifo-depth:
$ref: /schemas/types.yaml#/definitions/uint32
default: 64
@@ -101,6 +108,17 @@ unevaluatedProperties: false
allOf:
- $ref: dai-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: fsl,imx8qm-esai
+ then:
+ required:
+ - power-domains
+ else:
+ properties:
+ power-domains: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
index 204f361cea27..5654e9f61aba 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml
@@ -16,16 +16,23 @@ description: |
properties:
compatible:
- enum:
- - fsl,imx35-spdif
- - fsl,vf610-spdif
- - fsl,imx6sx-spdif
- - fsl,imx8qm-spdif
- - fsl,imx8qxp-spdif
- - fsl,imx8mq-spdif
- - fsl,imx8mm-spdif
- - fsl,imx8mn-spdif
- - fsl,imx8ulp-spdif
+ oneOf:
+ - items:
+ - enum:
+ - fsl,imx35-spdif
+ - fsl,imx6sx-spdif
+ - fsl,imx8mm-spdif
+ - fsl,imx8mn-spdif
+ - fsl,imx8mq-spdif
+ - fsl,imx8qm-spdif
+ - fsl,imx8qxp-spdif
+ - fsl,imx8ulp-spdif
+ - fsl,vf610-spdif
+ - items:
+ - enum:
+ - fsl,imx6sl-spdif
+ - fsl,imx6sx-spdif
+ - const: fsl,imx35-spdif
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/sound/inno-rk3036.txt b/Documentation/devicetree/bindings/sound/inno-rk3036.txt
deleted file mode 100644
index 758de8e27561..000000000000
--- a/Documentation/devicetree/bindings/sound/inno-rk3036.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Inno audio codec for RK3036
-
-Inno audio codec is integrated inside RK3036 SoC.
-
-Required properties:
-- compatible : Should be "rockchip,rk3036-codec".
-- reg : The registers of codec.
-- clock-names : Should be "acodec_pclk".
-- clocks : The clock of codec.
-- rockchip,grf : The phandle of grf device node.
-
-Example:
-
- acodec: acodec-ana@20030000 {
- compatible = "rk3036-codec";
- reg = <0x20030000 0x4000>;
- rockchip,grf = <&grf>;
- clock-names = "acodec_pclk";
- clocks = <&cru ACLK_VCODEC>;
- };
diff --git a/Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml b/Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml
new file mode 100644
index 000000000000..1e2a038d0048
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/irondevice,sma1307.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/irondevice,sma1307.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Iron Device SMA1307 Audio Amplifier
+
+maintainers:
+ - Kiseok Jo <kiseok.jo@irondevice.com>
+
+description:
+ SMA1307 boosted digital speaker amplifier with feedback-loop.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - irondevice,sma1307a
+ - irondevice,sma1307aq
+ description:
+ If a 'q' is added, it indicated the product is AEC-Q100
+ qualified for automotive applications. SMA1307A supports
+ both WLCSP and QFN packages. However, SMA1307AQ only
+ supports the QFN package.
+
+ reg:
+ maxItems: 1
+
+ '#sound-dai-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - '#sound-dai-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ amplifier@1e {
+ compatible = "irondevice,sma1307a";
+ reg = <0x1e>;
+ #sound-dai-cells = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/loongson,ls2k1000-i2s.yaml b/Documentation/devicetree/bindings/sound/loongson,ls2k1000-i2s.yaml
new file mode 100644
index 000000000000..da79510bb2d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/loongson,ls2k1000-i2s.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/loongson,ls2k1000-i2s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-2K1000 I2S controller
+
+maintainers:
+ - Binbin Zhou <zhoubinbin@loongson.cn>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: loongson,ls2k1000-i2s
+
+ reg:
+ items:
+ - description: Loongson I2S controller Registers.
+ - description: APB DMA config register for Loongson I2S controller.
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ dmas:
+ maxItems: 2
+
+ dma-names:
+ items:
+ - const: tx
+ - const: rx
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - dmas
+ - dma-names
+ - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/loongson,ls2k-clk.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2s@1fe2d000 {
+ compatible = "loongson,ls2k1000-i2s";
+ reg = <0x1fe2d000 0x14>,
+ <0x1fe00438 0x8>;
+ interrupt-parent = <&liointc0>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk LOONGSON2_APB_CLK>;
+ dmas = <&apbdma2 0>, <&apbdma3 0>;
+ dma-names = "tx", "rx";
+ #sound-dai-cells = <0>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/sound/maxim,max98390.yaml b/Documentation/devicetree/bindings/sound/maxim,max98390.yaml
index deaa6886c42f..d35dd8408c61 100644
--- a/Documentation/devicetree/bindings/sound/maxim,max98390.yaml
+++ b/Documentation/devicetree/bindings/sound/maxim,max98390.yaml
@@ -9,6 +9,9 @@ title: Maxim Integrated MAX98390 Speaker Amplifier with Integrated Dynamic Speak
maintainers:
- Steve Lee <steves.lee@maximintegrated.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: maxim,max98390
@@ -32,11 +35,14 @@ properties:
reset-gpios:
maxItems: 1
+ '#sound-dai-cells':
+ const: 0
+
required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
index f94ad0715e32..ba482747f0e6 100644
--- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
@@ -29,6 +29,13 @@ properties:
$ref: /schemas/types.yaml#/definitions/phandle
description: The phandle of MT8188 ASoC platform.
+ mediatek,adsp:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ The phandle of the MT8188 ADSP platform, which is the optional Audio DSP
+ hardware that provides additional audio functionalities if present.
+ The AFE will link to ADSP when the phandle is provided.
+
patternProperties:
"^dai-link-[0-9]+$":
type: object
diff --git a/Documentation/devicetree/bindings/sound/mt6359.yaml b/Documentation/devicetree/bindings/sound/mt6359.yaml
index 23d411fc4200..128698630c86 100644
--- a/Documentation/devicetree/bindings/sound/mt6359.yaml
+++ b/Documentation/devicetree/bindings/sound/mt6359.yaml
@@ -23,8 +23,8 @@ properties:
Indicates how many data pins are used to transmit two channels of PDM
signal. 0 means two wires, 1 means one wire. Default value is 0.
enum:
- - 0 # one wire
- - 1 # two wires
+ - 0 # two wires
+ - 1 # one wire
mediatek,mic-type-0:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -53,9 +53,9 @@ additionalProperties: false
examples:
- |
- mt6359codec: mt6359codec {
- mediatek,dmic-mode = <0>;
- mediatek,mic-type-0 = <2>;
+ mt6359codec: audio-codec {
+ mediatek,dmic-mode = <0>;
+ mediatek,mic-type-0 = <2>;
};
...
diff --git a/Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml b/Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml
new file mode 100644
index 000000000000..44d72a2ddfc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/neofidelity,ntp8835.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/neofidelity,ntp8835.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NeoFidelity NTP8835/NTP8835C Amplifiers
+
+maintainers:
+ - Igor Prusov <ivprusov@salutedevices.com>
+
+description: |
+ The NTP8835 is a single chip full digital audio amplifier
+ including power stages for stereo amplifier systems.
+ NTP8835 is integrated with versatile digital audio signal
+ processing functions, high-performance, high-fidelity fully
+ digital PWM modulator and two high-power full-bridge MOSFET
+ power stages. NTP8835C has identical programming interface,
+ but has different output signal characteristics.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - neofidelity,ntp8835
+ - neofidelity,ntp8835c
+
+ reg:
+ enum:
+ - 0x2a
+ - 0x2b
+ - 0x2c
+ - 0x2d
+
+ reset-gpios:
+ maxItems: 1
+
+ '#sound-dai-cells':
+ const: 0
+
+ clocks:
+ maxItems: 4
+
+ clock-names:
+ items:
+ - const: wck
+ - const: bck
+ - const: scl
+ - const: mclk
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ audio-codec@2b {
+ compatible = "neofidelity,ntp8835";
+ #sound-dai-cells = <0>;
+ reg = <0x2b>;
+ reset-gpios = <&gpio 5 GPIO_ACTIVE_LOW>;
+ clocks = <&clkc 551>, <&clkc 552>, <&clkc 553>, <&clkc 554>;
+ clock-names = "wck", "bck", "scl", "mclk";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml b/Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml
new file mode 100644
index 000000000000..952768b35902
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/neofidelity,ntp8918.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/neofidelity,ntp8918.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NeoFidelity NTP8918 Amplifier
+
+maintainers:
+ - Igor Prusov <ivprusov@salutedevices.com>
+
+description:
+ The NTP8918 is a single chip full digital audio amplifier
+ including power stage for stereo amplifier system.
+ The NTP8918 is integrated with versatile digital audio signal
+ processing functions, high-performance, high-fidelity fully
+ digital PWM modulator and two high-power full-bridge MOSFET
+ power stages.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - neofidelity,ntp8918
+
+ reg:
+ enum:
+ - 0x2a
+ - 0x2b
+ - 0x2c
+ - 0x2d
+
+ reset-gpios:
+ maxItems: 1
+
+ '#sound-dai-cells':
+ const: 0
+
+ clocks:
+ maxItems: 3
+
+ clock-names:
+ items:
+ - const: wck
+ - const: scl
+ - const: bck
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ audio-codec@2a {
+ compatible = "neofidelity,ntp8918";
+ #sound-dai-cells = <0>;
+ reg = <0x2a>;
+ clocks = <&clkc 150>, <&clkc 151>, <&clkc 152>;
+ clock-names = "wck", "scl", "bck";
+ reset-gpios = <&gpio 5 GPIO_ACTIVE_LOW>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/nxp,uda1342.yaml b/Documentation/devicetree/bindings/sound/nxp,uda1342.yaml
new file mode 100644
index 000000000000..71c6a5a2f5bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nxp,uda1342.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/nxp,uda1342.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP uda1342 audio CODECs
+
+maintainers:
+ - Binbin Zhou <zhoubinbin@loongson.cn>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: nxp,uda1342
+
+ reg:
+ maxItems: 1
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ codec@1a {
+ compatible = "nxp,uda1342";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
index b8540b30741e..92f95eb74b19 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
@@ -21,6 +21,7 @@ properties:
- items:
- enum:
- qcom,sm8650-lpass-rx-macro
+ - qcom,sm8750-lpass-rx-macro
- qcom,x1e80100-lpass-rx-macro
- const: qcom,sm8550-lpass-rx-macro
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
index 3e2ae16c6aba..914798a89878 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
@@ -22,6 +22,7 @@ properties:
- items:
- enum:
- qcom,sm8650-lpass-tx-macro
+ - qcom,sm8750-lpass-tx-macro
- qcom,x1e80100-lpass-tx-macro
- const: qcom,sm8550-lpass-tx-macro
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml
index 6b483fa3c428..f41deaa6f4df 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml
@@ -21,6 +21,7 @@ properties:
- items:
- enum:
- qcom,sm8650-lpass-va-macro
+ - qcom,sm8750-lpass-va-macro
- qcom,x1e80100-lpass-va-macro
- const: qcom,sm8550-lpass-va-macro
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml
index 6f5644a89feb..9082e363c709 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml
@@ -21,6 +21,7 @@ properties:
- items:
- enum:
- qcom,sm8650-lpass-wsa-macro
+ - qcom,sm8750-lpass-wsa-macro
- qcom,x1e80100-lpass-wsa-macro
- const: qcom,sm8550-lpass-wsa-macro
diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
index 2e2e01493a5f..b9e33a7429b0 100644
--- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
@@ -25,6 +25,7 @@ properties:
- enum:
- qcom,sm8550-sndcard
- qcom,sm8650-sndcard
+ - qcom,sm8750-sndcard
- const: qcom,sm8450-sndcard
- enum:
- qcom,apq8096-sndcard
diff --git a/Documentation/devicetree/bindings/sound/realtek,rt5640.yaml b/Documentation/devicetree/bindings/sound/realtek,rt5640.yaml
new file mode 100644
index 000000000000..3f4f59287c1c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/realtek,rt5640.yaml
@@ -0,0 +1,146 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/realtek,rt5640.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RT5640/RT5639 audio CODEC
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+description: |
+ This device supports I2C only.
+
+ Pins on the device (for linking into audio routes) for RT5639/RT5640:
+ * DMIC1
+ * DMIC2
+ * MICBIAS1
+ * IN1P
+ * IN1N
+ * IN2P
+ * IN2N
+ * IN3P
+ * IN3N
+ * HPOL
+ * HPOR
+ * LOUTL
+ * LOUTR
+ * SPOLP
+ * SPOLN
+ * SPORP
+ * SPORN
+
+ Additional pins on the device for RT5640:
+ * MONOP
+ * MONON
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - realtek,rt5640
+ - realtek,rt5639
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+ description: The CODEC's interrupt output.
+
+ realtek,in1-differential:
+ description:
+ Indicate MIC1 input is differential, rather than single-ended.
+ type: boolean
+
+ realtek,in2-differential:
+ description:
+ Indicate MIC2 input is differential, rather than single-ended.
+ type: boolean
+
+ realtek,in3-differential:
+ description:
+ Indicate MIC3 input is differential, rather than single-ended.
+ type: boolean
+
+ realtek,lout-differential:
+ description:
+ Indicate LOUT output is differential, rather than single-ended.
+ type: boolean
+
+ realtek,dmic1-data-pin:
+ description: Specify which pin to be used as DMIC1 data pin.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum:
+ - 0 # dmic1 is not used
+ - 1 # using IN2P pin as dmic1 data pin
+ - 2 # using GPIO3 pin as dmic1 data pin
+
+ realtek,dmic2-data-pin:
+ description: Specify which pin to be used as DMIC2 data pin.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum:
+ - 0 # dmic2 is not used
+ - 1 # using IN2N pin as dmic2 data pin
+ - 2 # using GPIO4 pin as dmic2 data pin
+
+ realtek,jack-detect-source:
+ description: The Jack Detect source.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum:
+ - 0 # Jack Detect function is not used
+ - 1 # Use GPIO1 for jack-detect
+ - 2 # Use JD1_IN4P for jack-detect
+ - 3 # Use JD2_IN4N for jack-detect
+ - 4 # Use GPIO2 for jack-detect
+ - 5 # Use GPIO3 for jack-detect
+ - 6 # Use GPIO4 for jack-detect
+
+ realtek,jack-detect-not-inverted:
+ description:
+ Normal jack-detect switches give an inverted signal, set this bool
+ in the rare case you've a jack-detect switch which is not inverted.
+ type: boolean
+
+ realtek,over-current-threshold-microamp:
+ description: micbias over-current detection threshold in µA
+ enum:
+ - 600
+ - 1500
+ - 2000
+
+ realtek,over-current-scale-factor:
+ description: micbias over-current detection scale-factor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum:
+ - 0 # Scale current by 0.5
+ - 1 # Scale current by 0.75
+ - 2 # Scale current by 1.0
+ - 3 # Scale current by 1.5
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ codec@1a {
+ compatible = "realtek,rt5640";
+ reg = <0x1a>;
+ interrupt-parent = <&gpio>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
index dfd768b1ad7d..3f07b072d995 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
@@ -109,7 +109,7 @@ For more detail information, see below
- Register Description
- CTUn Scale Value exx Register (CTUn_SVxxR)
- ${LINUX}/sound/soc/sh/rcar/ctu.c
+ ${LINUX}/sound/soc/renesas/rcar/ctu.c
- comment of header
You need to use "simple-scu-audio-card" or "audio-graph-scu-card" for it.
diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3036-codec.yaml b/Documentation/devicetree/bindings/sound/rockchip,rk3036-codec.yaml
new file mode 100644
index 000000000000..7570cc1375ca
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,rk3036-codec.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/rockchip,rk3036-codec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip RK3036 internal codec
+
+maintainers:
+ - Heiko Stuebner <heiko@sntech.de>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: rockchip,rk3036-codec
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: clock for audio codec
+
+ clock-names:
+ items:
+ - const: acodec_pclk
+
+ rockchip,grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ The phandle of the syscon node for the GRF register.
+
+ "#sound-dai-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - rockchip,grf
+ - "#sound-dai-cells"
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/rk3036-cru.h>
+ acodec: audio-codec@20030000 {
+ compatible = "rockchip,rk3036-codec";
+ reg = <0x20030000 0x4000>;
+ rockchip,grf = <&grf>;
+ clock-names = "acodec_pclk";
+ clocks = <&cru ACLK_VCODEC>;
+ #sound-dai-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt
deleted file mode 100644
index 0c398581d52b..000000000000
--- a/Documentation/devicetree/bindings/sound/rt5640.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-RT5640/RT5639 audio CODEC
-
-This device supports I2C only.
-
-Required properties:
-
-- compatible : One of "realtek,rt5640" or "realtek,rt5639".
-
-- reg : The I2C address of the device.
-
-- interrupts : The CODEC's interrupt output.
-
-Optional properties:
-
-- clocks: The phandle of the master clock to the CODEC
-- clock-names: Should be "mclk"
-
-- realtek,in1-differential
-- realtek,in2-differential
-- realtek,in3-differential
- Boolean. Indicate MIC1/2/3 input are differential, rather than single-ended.
-
-- realtek,lout-differential
- Boolean. Indicate LOUT output is differential, rather than stereo.
-
-- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
-
-- realtek,dmic1-data-pin
- 0: dmic1 is not used
- 1: using IN1P pin as dmic1 data pin
- 2: using GPIO3 pin as dmic1 data pin
-
-- realtek,dmic2-data-pin
- 0: dmic2 is not used
- 1: using IN1N pin as dmic2 data pin
- 2: using GPIO4 pin as dmic2 data pin
-
-- realtek,jack-detect-source
- u32. Valid values:
- 0: jack-detect is not used
- 1: Use GPIO1 for jack-detect
- 2: Use JD1_IN4P for jack-detect
- 3: Use JD2_IN4N for jack-detect
- 4: Use GPIO2 for jack-detect
- 5: Use GPIO3 for jack-detect
- 6: Use GPIO4 for jack-detect
-
-- realtek,jack-detect-not-inverted
- bool. Normal jack-detect switches give an inverted signal, set this bool
- in the rare case you've a jack-detect switch which is not inverted.
-
-- realtek,over-current-threshold-microamp
- u32, micbias over-current detection threshold in µA, valid values are
- 600, 1500 and 2000µA.
-
-- realtek,over-current-scale-factor
- u32, micbias over-current detection scale-factor, valid values are:
- 0: Scale current by 0.5
- 1: Scale current by 0.75
- 2: Scale current by 1.0
- 3: Scale current by 1.5
-
-Pins on the device (for linking into audio routes) for RT5639/RT5640:
-
- * DMIC1
- * DMIC2
- * MICBIAS1
- * IN1P
- * IN1N
- * IN2P
- * IN2N
- * IN3P
- * IN3N
- * HPOL
- * HPOR
- * LOUTL
- * LOUTR
- * SPOLP
- * SPOLN
- * SPORP
- * SPORN
-
-Additional pins on the device for RT5640:
-
- * MONOP
- * MONON
-
-Example:
-
-rt5640 {
- compatible = "realtek,rt5640";
- reg = <0x1c>;
- interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_HIGH>;
- realtek,ldo1-en-gpios =
- <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
-};
diff --git a/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml b/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml
index 194ac1d4f4f5..9b1bda4852e1 100644
--- a/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml
+++ b/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml
@@ -29,6 +29,10 @@ properties:
$ref: /schemas/types.yaml#/definitions/string-array
maxItems: 2
+ idle-state:
+ description: If present specifies the state when the mux is powered down
+ $ref: /schemas/mux/mux-controller.yaml#/properties/idle-state
+
sound-name-prefix: true
required:
@@ -43,4 +47,5 @@ examples:
compatible = "simple-audio-mux";
mux-gpios = <&gpio 3 0>;
state-labels = "Label_A", "Label_B";
+ idle-state = <0>;
};
diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml
index 59ac2d1d1ccf..533d0a1da56e 100644
--- a/Documentation/devicetree/bindings/sound/simple-card.yaml
+++ b/Documentation/devicetree/bindings/sound/simple-card.yaml
@@ -207,8 +207,14 @@ properties:
simple-audio-card,pin-switches:
$ref: "#/definitions/pin-switches"
simple-audio-card,hp-det-gpio:
+ deprecated: true
+ maxItems: 1
+ simple-audio-card,hp-det-gpios:
maxItems: 1
simple-audio-card,mic-det-gpio:
+ deprecated: true
+ maxItems: 1
+ simple-audio-card,mic-det-gpios:
maxItems: 1
patternProperties:
@@ -256,8 +262,14 @@ patternProperties:
pin-switches:
$ref: "#/definitions/pin-switches"
hp-det-gpio:
+ deprecated: true
+ maxItems: 1
+ hp-det-gpios:
maxItems: 1
mic-det-gpio:
+ deprecated: true
+ maxItems: 1
+ mic-det-gpios:
maxItems: 1
patternProperties:
diff --git a/Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml b/Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml
new file mode 100644
index 000000000000..c15c01bbb884
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sprd,pcm-platform.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/sprd,pcm-platform.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum DMA platform
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+properties:
+ compatible:
+ const: sprd,pcm-platform
+
+ dmas:
+ maxItems: 10
+
+ dma-names:
+ items:
+ - const: normal_p_l
+ - const: normal_p_r
+ - const: normal_c_l
+ - const: normal_c_r
+ - const: voice_c
+ - const: fast_p
+ - const: loop_c
+ - const: loop_p
+ - const: voip_c
+ - const: voip_p
+
+required:
+ - compatible
+ - dmas
+ - dma-names
+
+additionalProperties: false
+
+examples:
+ - |
+ platform {
+ compatible = "sprd,pcm-platform";
+ dmas = <&agcp_dma 1 1>, <&agcp_dma 2 2>,
+ <&agcp_dma 3 3>, <&agcp_dma 4 4>,
+ <&agcp_dma 5 5>, <&agcp_dma 6 6>,
+ <&agcp_dma 7 7>, <&agcp_dma 8 8>,
+ <&agcp_dma 9 9>, <&agcp_dma 10 10>;
+ dma-names = "normal_p_l", "normal_p_r",
+ "normal_c_l", "normal_c_r",
+ "voice_c", "fast_p",
+ "loop_c", "loop_p",
+ "voip_c", "voip_p";
+ };
+...
diff --git a/Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml b/Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml
new file mode 100644
index 000000000000..3b66bedeff97
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sprd,sc9860-mcdt.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/sprd,sc9860-mcdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum Multi-Channel Data Transfer controller
+
+description:
+ The Multi-channel data transfer controller is used for sound stream
+ transmission between the audio subsystem and other AP/CP subsystem. It
+ supports 10 DAC channels and 10 ADC channels, and each channel can be
+ configured with DMA mode or interrupt mode.
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+properties:
+ compatible:
+ const: sprd,sc9860-mcdt
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mcdt@41490000 {
+ compatible = "sprd,sc9860-mcdt";
+ reg = <0x41490000 0x170>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/sound/sprd-mcdt.txt b/Documentation/devicetree/bindings/sound/sprd-mcdt.txt
deleted file mode 100644
index 274ba0acbfd6..000000000000
--- a/Documentation/devicetree/bindings/sound/sprd-mcdt.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Spreadtrum Multi-Channel Data Transfer Binding
-
-The Multi-channel data transfer controller is used for sound stream
-transmission between audio subsystem and other AP/CP subsystem. It
-supports 10 DAC channel and 10 ADC channel, and each channel can be
-configured with DMA mode or interrupt mode.
-
-Required properties:
-- compatible: Should be "sprd,sc9860-mcdt".
-- reg: Should contain registers address and length.
-- interrupts: Should contain one interrupt shared by all channel.
-
-Example:
-
-mcdt@41490000 {
- compatible = "sprd,sc9860-mcdt";
- reg = <0 0x41490000 0 0x170>;
- interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
-};
diff --git a/Documentation/devicetree/bindings/sound/sprd-pcm.txt b/Documentation/devicetree/bindings/sound/sprd-pcm.txt
deleted file mode 100644
index fbbcade2181d..000000000000
--- a/Documentation/devicetree/bindings/sound/sprd-pcm.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-* Spreadtrum DMA platform bindings
-
-Required properties:
-- compatible: Should be "sprd,pcm-platform".
-- dmas: Specify the list of DMA controller phandle and DMA request line ordered pairs.
-- dma-names: Identifier string for each DMA request line in the dmas property.
- These strings correspond 1:1 with the ordered pairs in dmas.
-
-Example:
-
- audio_platform:platform@0 {
- compatible = "sprd,pcm-platform";
- dmas = <&agcp_dma 1 1>, <&agcp_dma 2 2>,
- <&agcp_dma 3 3>, <&agcp_dma 4 4>,
- <&agcp_dma 5 5>, <&agcp_dma 6 6>,
- <&agcp_dma 7 7>, <&agcp_dma 8 8>,
- <&agcp_dma 9 9>, <&agcp_dma 10 10>;
- dma-names = "normal_p_l", "normal_p_r",
- "normal_c_l", "normal_c_r",
- "voice_c", "fast_p",
- "loop_c", "loop_p",
- "voip_c", "voip_p";
- };
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
index 8978f6bd63e5..b4f44f9c7c7d 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
@@ -13,13 +13,11 @@ 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:
- st,stm32h7-i2s
+ - st,stm32mp25-i2s
"#sound-dai-cells":
const: 0
@@ -33,6 +31,7 @@ properties:
- description: clock feeding the internal clock generator.
- description: I2S parent clock for sampling rates multiple of 8kHz.
- description: I2S parent clock for sampling rates multiple of 11.025kHz.
+ minItems: 2
clock-names:
items:
@@ -40,6 +39,7 @@ properties:
- const: i2sclk
- const: x8k
- const: x11k
+ minItems: 2
interrupts:
maxItems: 1
@@ -79,6 +79,36 @@ required:
- dmas
- dma-names
+allOf:
+ - $ref: dai-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,stm32h7-i2s
+
+ then:
+ properties:
+ clocks:
+ minItems: 4
+
+ clock-names:
+ minItems: 4
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,stm32mp25-i2s
+
+ then:
+ properties:
+ clocks:
+ maxItems: 2
+
+ clock-names:
+ maxItems: 2
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
index 68f97b462598..4a7129d0b157 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
@@ -20,6 +20,7 @@ properties:
enum:
- st,stm32f4-sai
- st,stm32h7-sai
+ - st,stm32mp25-sai
reg:
items:
@@ -43,9 +44,11 @@ properties:
const: 1
clocks:
+ minItems: 1
maxItems: 3
clock-names:
+ minItems: 1
maxItems: 3
access-controllers:
@@ -156,7 +159,13 @@ allOf:
items:
- const: x8k
- const: x11k
- else:
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,stm32mph7-sai
+ then:
properties:
clocks:
items:
@@ -170,6 +179,21 @@ allOf:
- const: x8k
- const: x11k
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,stm32mp25-sai
+ then:
+ properties:
+ clocks:
+ items:
+ - description: pclk feeds the peripheral bus interface.
+
+ clock-names:
+ items:
+ - const: pclk
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
index 3dedc81ec12f..56c5738ea4c5 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
@@ -50,6 +50,10 @@ properties:
resets:
maxItems: 1
+ port:
+ $ref: audio-graph-port.yaml#
+ unevaluatedProperties: false
+
access-controllers:
minItems: 1
maxItems: 2
diff --git a/Documentation/devicetree/bindings/spi/apple,spi.yaml b/Documentation/devicetree/bindings/spi/apple,spi.yaml
new file mode 100644
index 000000000000..7bef605a2963
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/apple,spi.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/apple,spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple ARM SoC SPI controller
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+maintainers:
+ - Hector Martin <marcan@marcan.st>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - apple,t8103-spi
+ - apple,t8112-spi
+ - apple,t6000-spi
+ - const: apple,spi
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/apple-aic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ spi@39b104000 {
+ compatible = "apple,t6000-spi", "apple,spi";
+ reg = <0x3 0x9b104000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1107 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clk>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.txt b/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.txt
deleted file mode 100644
index d7668f41b03b..000000000000
--- a/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-Broadcom BCM2835 auxiliary SPI1/2 controller
-
-The BCM2835 contains two forms of SPI master controller, one known simply as
-SPI0, and the other known as the "Universal SPI Master"; part of the
-auxiliary block. This binding applies to the SPI1/2 controller.
-
-Required properties:
-- compatible: Should be "brcm,bcm2835-aux-spi".
-- reg: Should contain register location and length for the spi block
-- interrupts: Should contain shared interrupt of the aux block
-- clocks: The clock feeding the SPI controller - needs to
- point to the auxiliary clock driver of the bcm2835,
- as this clock will enable the output gate for the specific
- clock.
-- cs-gpios: the cs-gpios (native cs is NOT supported)
- see also spi-bus.txt
-
-Example:
-
-spi1@7e215080 {
- compatible = "brcm,bcm2835-aux-spi";
- reg = <0x7e215080 0x40>;
- interrupts = <1 29>;
- clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI1>;
- #address-cells = <1>;
- #size-cells = <0>;
- cs-gpios = <&gpio 18>, <&gpio 17>, <&gpio 16>;
-};
-
-spi2@7e2150c0 {
- compatible = "brcm,bcm2835-aux-spi";
- reg = <0x7e2150c0 0x40>;
- interrupts = <1 29>;
- clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI2>;
- #address-cells = <1>;
- #size-cells = <0>;
- cs-gpios = <&gpio 43>, <&gpio 44>, <&gpio 45>;
-};
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.yaml b/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.yaml
new file mode 100644
index 000000000000..561319544ee3
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/brcm,bcm2835-aux-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM2835 Auxiliary SPI1/2 Controller
+
+maintainers:
+ - Karan Sanghavi <karansanghvi98@gmail.com>
+
+description:
+ The BCM2835 contains two forms of SPI master controller. One is known simply
+ as SPI0, and the other as the "Universal SPI Master," which is part of the
+ auxiliary block. This binding applies to the SPI1 and SPI2 auxiliary
+ controllers.
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+properties:
+ compatible:
+ enum:
+ - brcm,bcm2835-aux-spi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/bcm2835-aux.h>
+ spi@7e215080 {
+ compatible = "brcm,bcm2835-aux-spi";
+ reg = <0x7e215080 0x40>;
+ interrupts = <1 29>;
+ clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml b/Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml
new file mode 100644
index 000000000000..36d79a90552b
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/realtek,rtl9301-snand.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SPI-NAND Flash Controller for Realtek RTL9300 SoCs
+
+maintainers:
+ - Chris Packham <chris.packham@alliedtelesis.co.nz>
+
+description:
+ The Realtek RTL9300 SoCs have a built in SPI-NAND controller. It supports
+ typical SPI-NAND page cache operations in single, dual or quad IO mode.
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - realtek,rtl9302b-snand
+ - realtek,rtl9302c-snand
+ - realtek,rtl9303-snand
+ - const: realtek,rtl9301-snand
+ - const: realtek,rtl9301-snand
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+allOf:
+ - $ref: /schemas/spi/spi-controller.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi@1a400 {
+ compatible = "realtek,rtl9302c-snand", "realtek,rtl9301-snand";
+ reg = <0x1a400 0x44>;
+ interrupt-parent = <&intc>;
+ interrupts = <19>;
+ clocks = <&lx_clk>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ flash@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml
index f681372da81f..3c206a64d60a 100644
--- a/Documentation/devicetree/bindings/spi/samsung,spi.yaml
+++ b/Documentation/devicetree/bindings/spi/samsung,spi.yaml
@@ -26,6 +26,10 @@ properties:
- samsung,exynos850-spi
- samsung,exynosautov9-spi
- tesla,fsd-spi
+ - items:
+ - enum:
+ - samsung,exynos8895-spi
+ - const: samsung,exynos850-spi
- const: samsung,exynos7-spi
deprecated: true
diff --git a/Documentation/devicetree/bindings/spi/spi-sprd.txt b/Documentation/devicetree/bindings/spi/spi-sprd.txt
deleted file mode 100644
index 3c7eacce0ee3..000000000000
--- a/Documentation/devicetree/bindings/spi/spi-sprd.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-Spreadtrum SPI Controller
-
-Required properties:
-- compatible: Should be "sprd,sc9860-spi".
-- reg: Offset and length of SPI controller register space.
-- interrupts: Should contain SPI interrupt.
-- clock-names: Should contain following entries:
- "spi" for SPI clock,
- "source" for SPI source (parent) clock,
- "enable" for SPI module enable clock.
-- clocks: List of clock input name strings sorted in the same order
- as the clock-names property.
-- #address-cells: The number of cells required to define a chip select
- address on the SPI bus. Should be set to 1.
-- #size-cells: Should be set to 0.
-
-Optional properties:
-dma-names: Should contain names of the SPI used DMA channel.
-dmas: Should contain DMA channels and DMA slave ids which the SPI used
- sorted in the same order as the dma-names property.
-
-Example:
-spi0: spi@70a00000{
- compatible = "sprd,sc9860-spi";
- reg = <0 0x70a00000 0 0x1000>;
- interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "spi", "source","enable";
- clocks = <&clk_spi0>, <&ext_26m>, <&clk_ap_apb_gates 5>;
- dma-names = "rx_chn", "tx_chn";
- dmas = <&apdma 11 11>, <&apdma 12 12>;
- #address-cells = <1>;
- #size-cells = <0>;
-};
diff --git a/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml b/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml
index e5199b109dad..04d4d3b4916d 100644
--- a/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml
@@ -9,9 +9,6 @@ title: Xilinx Zynq UltraScale+ MPSoC GQSPI controller
maintainers:
- Michal Simek <michal.simek@amd.com>
-allOf:
- - $ref: spi-controller.yaml#
-
properties:
compatible:
enum:
@@ -19,6 +16,7 @@ properties:
- xlnx,zynqmp-qspi-1.0
reg:
+ minItems: 1
maxItems: 2
interrupts:
@@ -47,6 +45,24 @@ required:
unevaluatedProperties: false
+allOf:
+ - $ref: spi-controller.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: xlnx,zynqmp-qspi-1.0
+ then:
+ properties:
+ reg:
+ minItems: 2
+
+ else:
+ properties:
+ reg:
+ maxItems: 1
+
examples:
- |
#include <dt-bindings/clock/xlnx-zynqmp-clk.h>
diff --git a/Documentation/devicetree/bindings/spi/sprd,sc9860-spi.yaml b/Documentation/devicetree/bindings/spi/sprd,sc9860-spi.yaml
new file mode 100644
index 000000000000..d55c01e9a038
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/sprd,sc9860-spi.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/sprd,sc9860-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum SC9860 SPI Controller
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+properties:
+ compatible:
+ const: sprd,sc9860-spi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: SPI clock
+ - description: SPI source (parent) clock
+ - description: SPI module enable clock
+
+ clock-names:
+ items:
+ - const: spi
+ - const: source
+ - const: enable
+
+ dmas:
+ maxItems: 2
+
+ dma-names:
+ items:
+ - const: rx_chn
+ - const: tx_chn
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ spi@70a00000 {
+ compatible = "sprd,sc9860-spi";
+ reg = <0x70a00000 0x1000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_spi0>, <&ext_26m>, <&clk_ap_apb_gates 5>;
+ clock-names = "spi", "source", "enable";
+ dmas = <&apdma 11 11>, <&apdma 12 12>;
+ dma-names = "rx_chn", "tx_chn";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml b/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml
index ac99883a3f29..7f0be0ac644a 100644
--- a/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml
+++ b/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml
@@ -25,6 +25,7 @@ properties:
- items:
- enum:
- mediatek,mt8186-spmi
+ - mediatek,mt8188-spmi
- const: mediatek,mt8195-spmi
reg:
diff --git a/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml b/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
index a28b70fb330a..7c3cc20a80d6 100644
--- a/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
+++ b/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
@@ -19,7 +19,11 @@ description: |
properties:
compatible:
- const: qcom,x1e80100-spmi-pmic-arb
+ oneOf:
+ - items:
+ - const: qcom,sar2130p-spmi-pmic-arb
+ - const: qcom,x1e80100-spmi-pmic-arb
+ - const: qcom,x1e80100-spmi-pmic-arb
reg:
items:
diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml
index faef3d6e0a94..9b06bcd01957 100644
--- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml
+++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml
@@ -21,6 +21,7 @@ properties:
- qcom,msm8226-imem
- qcom,msm8974-imem
- qcom,qcs404-imem
+ - qcom,qcs8300-imem
- qcom,qdu1000-imem
- qcom,sa8775p-imem
- qcom,sc7180-imem
diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml
index 0922d1f71ba8..7c1337e159f2 100644
--- a/Documentation/devicetree/bindings/sram/sram.yaml
+++ b/Documentation/devicetree/bindings/sram/sram.yaml
@@ -101,6 +101,12 @@ patternProperties:
IO mem address range, relative to the SRAM range.
maxItems: 1
+ reg-io-width:
+ description:
+ The size (in bytes) of the IO accesses that should be performed on the
+ SRAM.
+ enum: [1, 2, 4, 8]
+
pool:
description:
Indicates that the particular reserved SRAM area is addressable
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
index a12fddc81955..ed5de0f92a9e 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
@@ -39,6 +39,7 @@ properties:
- description: v1 of TSENS
items:
- enum:
+ - qcom,msm8937-tsens
- qcom,msm8956-tsens
- qcom,msm8976-tsens
- qcom,qcs404-tsens
@@ -53,6 +54,7 @@ properties:
- qcom,qcm2290-tsens
- qcom,sa8255p-tsens
- qcom,sa8775p-tsens
+ - qcom,sar2130p-tsens
- qcom,sc7180-tsens
- qcom,sc7280-tsens
- qcom,sc8180x-tsens
diff --git a/Documentation/devicetree/bindings/timer/actions,owl-timer.txt b/Documentation/devicetree/bindings/timer/actions,owl-timer.txt
deleted file mode 100644
index 977054f87563..000000000000
--- a/Documentation/devicetree/bindings/timer/actions,owl-timer.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Actions Semi Owl Timer
-
-Required properties:
-- compatible : "actions,s500-timer" for S500
- "actions,s700-timer" for S700
- "actions,s900-timer" for S900
-- reg : Offset and length of the register set for the device.
-- interrupts : Should contain the interrupts.
-- interrupt-names : Valid names are: "2hz0", "2hz1",
- "timer0", "timer1", "timer2", "timer3"
- See ../resource-names.txt
-
-Example:
-
- timer@b0168000 {
- compatible = "actions,s500-timer";
- reg = <0xb0168000 0x100>;
- interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "timer0", "timer1";
- };
diff --git a/Documentation/devicetree/bindings/timer/actions,owl-timer.yaml b/Documentation/devicetree/bindings/timer/actions,owl-timer.yaml
new file mode 100644
index 000000000000..646c554a390a
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/actions,owl-timer.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/actions,owl-timer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Actions Semi Owl timer
+
+maintainers:
+ - Andreas Färber <afaerber@suse.de>
+
+description:
+ Actions Semi Owl SoCs provide 32bit and 2Hz timers.
+ The 32bit timers support dynamic irq, as well as one-shot mode.
+
+properties:
+ compatible:
+ enum:
+ - actions,s500-timer
+ - actions,s700-timer
+ - actions,s900-timer
+
+ clocks:
+ maxItems: 1
+
+ interrupts:
+ minItems: 1
+ maxItems: 6
+
+ interrupt-names:
+ minItems: 1
+ maxItems: 6
+ items:
+ enum:
+ - 2hz0
+ - 2hz1
+ - timer0
+ - timer1
+ - timer2
+ - timer3
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - interrupts
+ - interrupt-names
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - actions,s500-timer
+ then:
+ properties:
+ interrupts:
+ minItems: 4
+ maxItems: 4
+ interrupt-names:
+ items:
+ - const: 2hz0
+ - const: 2hz1
+ - const: timer0
+ - const: timer1
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - actions,s700-timer
+ - actions,s900-timer
+ then:
+ properties:
+ interrupts:
+ minItems: 1
+ maxItems: 1
+ interrupt-names:
+ items:
+ - const: timer1
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ timer@b0168000 {
+ compatible = "actions,s500-timer";
+ reg = <0xb0168000 0x100>;
+ clocks = <&hosc>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "2hz0", "2hz1", "timer0", "timer1";
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.yaml b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.yaml
index 774b7992a0ca..02d1c355808e 100644
--- a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.yaml
+++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.yaml
@@ -33,6 +33,7 @@ properties:
- samsung,exynos5420-mct
- samsung,exynos5433-mct
- samsung,exynos850-mct
+ - samsung,exynos8895-mct
- tesla,fsd-mct
- const: samsung,exynos4210-mct
@@ -133,6 +134,7 @@ allOf:
- samsung,exynos5420-mct
- samsung,exynos5433-mct
- samsung,exynos850-mct
+ - samsung,exynos8895-mct
then:
properties:
interrupts:
diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 9bf0fb17a05e..88abb5c174f3 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -153,12 +153,6 @@ properties:
- isil,isl29028
# Intersil ISL29030 Ambient Light and Proximity Sensor
- isil,isl29030
- # Intersil ISL68137 Digital Output Configurable PWM Controller
- - isil,isl68137
- # Intersil ISL69260 PMBus Voltage Regulator
- - isil,isl69260
- # Intersil ISL69269 PMBus Voltage Regulator
- - isil,isl69269
# Intersil ISL76682 Ambient Light Sensor
- isil,isl76682
# JEDEC JESD300 (SPD5118) Hub and Serial Presence Detect
@@ -279,12 +273,6 @@ properties:
- mps,mp2888
# Monolithic Power Systems Inc. multi-phase controller mp2891
- mps,mp2891
- # Monolithic Power Systems Inc. multi-phase controller mp2971
- - mps,mp2971
- # Monolithic Power Systems Inc. multi-phase controller mp2973
- - mps,mp2973
- # Monolithic Power Systems Inc. multi-phase controller mp2975
- - mps,mp2975
# Monolithic Power Systems Inc. multi-phase controller mp2993
- mps,mp2993
# Monolithic Power Systems Inc. multi-phase hot-swap controller mp5920
@@ -309,6 +297,8 @@ properties:
- nuvoton,w83773g
# OKI ML86V7667 video decoder
- oki,ml86v7667
+ # ON Semiconductor ADT7462 Temperature, Voltage Monitor and Fan Controller
+ - onnn,adt7462
# 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch
- plx,pex8648
# Pulsedlight LIDAR range-finding sensor
@@ -357,8 +347,6 @@ properties:
- swir,mangoh-iotport-spi
# Ambient Light Sensor with SMBUS/Two Wire Serial Interface
- taos,tsl2550
- # Temperature Monitoring and Fan Control
- - ti,amc6821
# Temperature and humidity sensor with i2c interface
- ti,hdc1000
# Temperature and humidity sensor with i2c interface
@@ -400,8 +388,6 @@ properties:
- ti,tps546d24
# I2C Touch-Screen Controller
- ti,tsc2003
- # Vicor Corporation Digital Supervisor
- - vicor,pli1209bc
# Winbond/Nuvoton H/W Monitor
- winbond,w83793
diff --git a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml
index 25a5edeea164..cde334e3206b 100644
--- a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml
+++ b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml
@@ -26,6 +26,7 @@ properties:
- qcom,msm8994-ufshc
- qcom,msm8996-ufshc
- qcom,msm8998-ufshc
+ - qcom,qcs8300-ufshc
- qcom,sa8775p-ufshc
- qcom,sc7180-ufshc
- qcom,sc7280-ufshc
@@ -146,6 +147,7 @@ allOf:
contains:
enum:
- qcom,msm8998-ufshc
+ - qcom,qcs8300-ufshc
- qcom,sa8775p-ufshc
- qcom,sc7280-ufshc
- qcom,sc8180x-ufshc
diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
index f972ce976e86..7ffcd236d7bb 100644
--- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
+++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
@@ -23,7 +23,9 @@ properties:
- enum:
- allwinner,sun8i-a83t-musb
- allwinner,sun20i-d1-musb
+ - allwinner,sun50i-a100-musb
- allwinner,sun50i-h6-musb
+ - allwinner,sun55i-a523-musb
- const: allwinner,sun8i-a33-musb
- items:
- const: allwinner,sun50i-h616-musb
diff --git a/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml b/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml
index 89fc9a434d05..0620d82508c1 100644
--- a/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml
+++ b/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml
@@ -61,18 +61,15 @@ additionalProperties: false
examples:
- |
- #include <dt-bindings/gpio/tegra194-gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
- #interrupt-cells = <2>;
typec@8 {
compatible = "cypress,cypd4226";
reg = <0x08>;
- interrupt-parent = <&gpio_aon>;
- interrupts = <TEGRA194_AON_GPIO(BB, 2) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
firmware-name = "nvidia,jetson-agx-xavier";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
index 9ea1e4cd0709..baf130669c38 100644
--- a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
@@ -12,7 +12,11 @@ maintainers:
properties:
compatible:
- const: fsl,imx8mp-dwc3
+ oneOf:
+ - items:
+ - const: fsl,imx95-dwc3
+ - const: fsl,imx8mp-dwc3
+ - const: fsl,imx8mp-dwc3
reg:
items:
diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
index 2ed178f16a78..223f2abd5e59 100644
--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
@@ -28,9 +28,11 @@ properties:
- items:
- enum:
- allwinner,sun4i-a10-ehci
+ - allwinner,sun50i-a100-ehci
- allwinner,sun50i-a64-ehci
- allwinner,sun50i-h6-ehci
- allwinner,sun50i-h616-ehci
+ - allwinner,sun55i-a523-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 b9576015736b..3ee1586fc8b9 100644
--- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
@@ -15,9 +15,11 @@ properties:
- items:
- enum:
- allwinner,sun4i-a10-ohci
+ - allwinner,sun50i-a100-ohci
- allwinner,sun50i-a64-ohci
- allwinner,sun50i-h6-ohci
- allwinner,sun50i-h616-ohci
+ - allwinner,sun55i-a523-ohci
- allwinner,sun5i-a13-ohci
- allwinner,sun6i-a31-ohci
- allwinner,sun7i-a20-ohci
diff --git a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
index fc833363cfb4..6fe2d356dcbd 100644
--- a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
+++ b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
@@ -62,7 +62,14 @@ allOf:
peer-hub: true
vdd-supply: true
-additionalProperties: false
+patternProperties:
+ "^.*@[0-9a-f]{1,2}$":
+ description: The hard wired USB devices
+ type: object
+ $ref: /schemas/usb/usb-device.yaml
+ additionalProperties: true
+
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml b/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
index 276bf7554215..20b62228371b 100644
--- a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
+++ b/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
@@ -69,6 +69,7 @@ examples:
PDO_FIXED_DATA_SWAP |
PDO_FIXED_DUAL_ROLE)
PDO_FIXED(9000, 2000, 0)>;
+ sink-bc12-completion-time-ms = <500>;
};
};
};
diff --git a/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml b/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
index 27b909de4992..a812317d8089 100644
--- a/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
+++ b/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
@@ -14,8 +14,11 @@ maintainers:
properties:
compatible:
- enum:
- - microchip,mpfs-musb
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-musb
+ - const: microchip,mpfs-musb
+ - const: microchip,mpfs-musb
dr_mode: true
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index 18758efb8d29..935e204b607b 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -26,8 +26,10 @@ properties:
- qcom,msm8998-dwc3
- qcom,qcm2290-dwc3
- qcom,qcs404-dwc3
+ - qcom,qcs8300-dwc3
- qcom,qdu1000-dwc3
- qcom,sa8775p-dwc3
+ - qcom,sar2130p-dwc3
- qcom,sc7180-dwc3
- qcom,sc7280-dwc3
- qcom,sc8180x-dwc3
@@ -201,6 +203,7 @@ allOf:
- qcom,msm8953-dwc3
- qcom,msm8996-dwc3
- qcom,msm8998-dwc3
+ - qcom,qcs8300-dwc3
- qcom,sa8775p-dwc3
- qcom,sc7180-dwc3
- qcom,sc7280-dwc3
@@ -338,6 +341,7 @@ allOf:
contains:
enum:
- qcom,qcm2290-dwc3
+ - qcom,sar2130p-dwc3
- qcom,sc8180x-dwc3
- qcom,sc8180x-dwc3-mp
- qcom,sm6115-dwc3
@@ -465,6 +469,7 @@ allOf:
- qcom,ipq4019-dwc3
- qcom,ipq8064-dwc3
- qcom,msm8994-dwc3
+ - qcom,qcs8300-dwc3
- qcom,qdu1000-dwc3
- qcom,sa8775p-dwc3
- qcom,sc7180-dwc3
@@ -490,6 +495,7 @@ allOf:
minItems: 4
maxItems: 5
interrupt-names:
+ minItems: 4
items:
- const: pwr_event
- const: hs_phy_irq
diff --git a/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml b/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
index c63db3ebd07b..b23ef29bf794 100644
--- a/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
+++ b/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
@@ -76,6 +76,10 @@ properties:
Integer to use BUSWAIT register.
renesas,enable-gpio:
+ deprecated: true
+ maxItems: 1
+
+ renesas,enable-gpios:
maxItems: 1
description: |
gpio specifier to check GPIO determining if USB function should be
diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
index c4924113f9bd..a21cc098542d 100644
--- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
@@ -27,6 +27,7 @@ select:
enum:
- rockchip,rk3328-dwc3
- rockchip,rk3568-dwc3
+ - rockchip,rk3576-dwc3
- rockchip,rk3588-dwc3
required:
- compatible
@@ -37,6 +38,7 @@ properties:
- enum:
- rockchip,rk3328-dwc3
- rockchip,rk3568-dwc3
+ - rockchip,rk3576-dwc3
- rockchip,rk3588-dwc3
- const: snps,dwc3
@@ -113,7 +115,9 @@ allOf:
properties:
compatible:
contains:
- const: rockchip,rk3568-dwc3
+ enum:
+ - rockchip,rk3568-dwc3
+ - rockchip,rk3576-dwc3
then:
properties:
clocks:
diff --git a/Documentation/devicetree/bindings/usb/ti,tusb1046.yaml b/Documentation/devicetree/bindings/usb/ti,tusb1046.yaml
new file mode 100644
index 000000000000..f713cac4a8ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ti,tusb1046.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/ti,tusb1046.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TUSB1046-DCI Type-C crosspoint switch
+
+maintainers:
+ - Romain Gantois <romain.gantois@bootlin.com>
+
+allOf:
+ - $ref: usb-switch.yaml#
+
+properties:
+ compatible:
+ const: ti,tusb1046
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ typec-mux@44 {
+ compatible = "ti,tusb1046";
+ reg = <0x44>;
+
+ mode-switch;
+ orientation-switch;
+
+ port {
+ endpoint {
+ remote-endpoint = <&typec_controller>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml b/Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml
new file mode 100644
index 000000000000..ddda734f36fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/ti,tusb73x0-pci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TUSB73x0 USB 3.0 xHCI Host Controller (PCIe)
+
+maintainers:
+ - Francesco Dolcini <francesco.dolcini@toradex.com>
+
+description:
+ TUSB73x0 USB 3.0 xHCI Host Controller via PCIe x1 Gen2 interface.
+ The TUSB7320 supports up to two downstream ports, the TUSB7340 supports up
+ to four downstream ports, both variants share the same PCI device ID.
+
+properties:
+ compatible:
+ const: pci104c,8241
+
+ reg:
+ maxItems: 1
+
+ ti,pwron-active-high:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Configure the polarity of the PWRONx# signals. When this is present, the
+ PWRONx# pins are active high and their internal pull-down resistors are
+ disabled. When this is absent, the PWRONx# pins are active low (default)
+ and their internal pull-down resistors are enabled.
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: usb-xhci.yaml
+
+additionalProperties: false
+
+examples:
+ - |
+ pcie@0 {
+ reg = <0x0 0x1000>;
+ ranges = <0x02000000 0x0 0x100000 0x10000000 0x0 0x0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+
+ usb@0 {
+ compatible = "pci104c,8241";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ ti,pwron-active-high;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 46901c8d7eb0..da01616802c7 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -83,6 +83,8 @@ patternProperties:
description: ALFA Network Inc.
"^allegro,.*":
description: Allegro DVT
+ "^allegromicro,.*":
+ description: Allegro MicroSystems, Inc.
"^alliedvision,.*":
description: Allied Vision Technologies GmbH
"^allo,.*":
@@ -312,6 +314,8 @@ patternProperties:
description: Colorful GRP, Shenzhen Xueyushi Technology Ltd.
"^compulab,.*":
description: CompuLab Ltd.
+ "^comvetia,.*":
+ description: ComVetia AG
"^congatec,.*":
description: congatec GmbH
"^coolpi,.*":
@@ -356,6 +360,8 @@ patternProperties:
description: DataImage, Inc.
"^davicom,.*":
description: DAVICOM Semiconductor, Inc.
+ "^deepcomputing,.*":
+ description: DeepComputing (HK) Limited
"^dell,.*":
description: Dell Inc.
"^delta,.*":
@@ -561,6 +567,8 @@ patternProperties:
description: GE Fanuc Intelligent Platforms Embedded Systems, Inc.
"^GEFanuc,.*":
description: GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ "^gehc,.*":
+ description: GE HealthCare
"^gemei,.*":
description: Gemei Digital Technology Co., Ltd.
"^gemtek,.*":
@@ -1015,6 +1023,8 @@ patternProperties:
description: Shanghai Neardi Technology Co., Ltd.
"^nec,.*":
description: NEC LCD Technologies, Ltd.
+ "^neofidelity,.*":
+ description: Neofidelity Inc.
"^neonode,.*":
description: Neonode Inc.
"^netgear,.*":
@@ -1047,6 +1057,8 @@ patternProperties:
description: Nokia
"^nordic,.*":
description: Nordic Semiconductor
+ "^nothing,.*":
+ description: Nothing Technology Limited
"^novatek,.*":
description: Novatek
"^novtech,.*":
@@ -1226,6 +1238,8 @@ patternProperties:
description: Unisoc Communications, Inc.
"^realtek,.*":
description: Realtek Semiconductor Corp.
+ "^relfor,.*":
+ description: Relfor Labs Pvt. Ltd.
"^remarkable,.*":
description: reMarkable AS
"^renesas,.*":
@@ -1388,6 +1402,8 @@ patternProperties:
description: Sophgo Technology Inc.
"^sourceparts,.*":
description: Source Parts Inc.
+ "^spacemit,.*":
+ description: SpacemiT (Hangzhou) Technology Co. Ltd
"^spansion,.*":
description: Spansion Inc.
"^sparkfun,.*":
diff --git a/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml b/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
index 21872e15916c..310832fa8c28 100644
--- a/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
@@ -16,6 +16,11 @@ properties:
compatible:
items:
- enum:
+ - apple,s5l8960x-wdt
+ - apple,t7000-wdt
+ - apple,s8000-wdt
+ - apple,t8010-wdt
+ - apple,t8015-wdt
- apple,t8103-wdt
- apple,t8112-wdt
- apple,t6000-wdt
diff --git a/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml b/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml
index b5a3dc377070..1efefd741c06 100644
--- a/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml
@@ -32,6 +32,7 @@ properties:
- rockchip,rk3576-wdt
- rockchip,rk3588-wdt
- rockchip,rv1108-wdt
+ - rockchip,rv1126-wdt
- const: snps,dw-wdt
reg:
diff --git a/Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.txt b/Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.txt
deleted file mode 100644
index 3de96186e92e..000000000000
--- a/Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-Zodiac Inflight Innovations RAVE Supervisory Processor Watchdog Bindings
-
-RAVE SP watchdog device is a "MFD cell" device corresponding to
-watchdog functionality of RAVE Supervisory Processor. It is expected
-that its Device Tree node is specified as a child of the node
-corresponding to the parent RAVE SP device (as documented in
-Documentation/devicetree/bindings/mfd/zii,rave-sp.txt)
-
-Required properties:
-
-- compatible: Depending on wire protocol implemented by RAVE SP
- firmware, should be one of:
- - "zii,rave-sp-watchdog"
- - "zii,rave-sp-watchdog-legacy"
-
-Optional properties:
-
-- wdt-timeout: Two byte nvmem cell specified as per
- Documentation/devicetree/bindings/nvmem/nvmem.txt
-
-Example:
-
- rave-sp {
- compatible = "zii,rave-sp-rdu1";
- current-speed = <38400>;
-
- eeprom {
- wdt_timeout: wdt-timeout@8E {
- reg = <0x8E 2>;
- };
- };
-
- watchdog {
- compatible = "zii,rave-sp-watchdog";
- nvmem-cells = <&wdt_timeout>;
- nvmem-cell-names = "wdt-timeout";
- };
- }
-
diff --git a/Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.yaml b/Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.yaml
new file mode 100644
index 000000000000..de0d56725dd4
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/zii,rave-sp-wdt.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/zii,rave-sp-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zodiac Inflight Innovations RAVE Supervisory Processor Watchdog
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+
+description:
+ RAVE SP watchdog device is a "MFD cell" device corresponding to
+ watchdog functionality of RAVE Supervisory Processor. It is expected
+ that its Device Tree node is specified as a child of the node
+ corresponding to the parent RAVE SP device (as documented in
+ Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml)
+
+properties:
+ compatible:
+ enum:
+ - zii,rave-sp-watchdog
+ - zii,rave-sp-watchdog-legacy
+
+ nvmem-cell-names:
+ items:
+ - const: wdt_timeout
+
+ nvmem-cells:
+ maxItems: 1
+
+required:
+ - compatible
+
+allOf:
+ - $ref: watchdog.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ watchdog {
+ compatible = "zii,rave-sp-watchdog";
+ nvmem-cells = <&wdt_timeout>;
+ nvmem-cell-names = "wdt_timeout";
+ };
+
diff --git a/Documentation/devicetree/bindings/writing-schema.rst b/Documentation/devicetree/bindings/writing-schema.rst
index 7e71cdd1d6de..eb8ced400c7e 100644
--- a/Documentation/devicetree/bindings/writing-schema.rst
+++ b/Documentation/devicetree/bindings/writing-schema.rst
@@ -43,6 +43,36 @@ description
or device does, standards the device conforms to, and links to datasheets for
more information.
+ The YAML format has several options for defining the formatting of the text
+ block. The options are controlled with indicator characters following the key
+ (e.g. "description: \|"). The minimum formatting needed for a block should be
+ used. The formatting controls can not only affect whether the YAML can be
+ parsed correctly, but are important when the text blocks are rendered to
+ another form. The options are as follows.
+
+ The default without any indicators is flowed, plain scalar style where single
+ line breaks and leading whitespace are stripped. Paragraphs are delimited by
+ blank lines (i.e. double line break). This style cannot contain ": " in it as
+ it will be interpretted as a key. Any " #" sequence will be interpretted as
+ a comment. There's other restrictions on characters as well. Most
+ restrictions are on what the first character can be.
+
+ The second style is folded which is indicated by ">" character. In addition
+ to maintaining line breaks on double line breaks, the folded style also
+ maintains leading whitespace beyond indentation of the first line. The line
+ breaks on indented lines are also maintained.
+
+ The third style is literal which is indicated by "\|" character. The literal
+ style maintains all line breaks and whitespace (beyond indentation of the
+ first line).
+
+ The above is not a complete description of YAML text blocks. More details on
+ multi-line YAML text blocks can be found online:
+
+ https://yaml-multiline.info/
+
+ https://www.yaml.info/learn/quote.html
+
select
Optional. A json-schema used to match nodes for applying the
schema. By default, without 'select', nodes are matched against their possible
diff --git a/Documentation/doc-guide/kernel-doc.rst b/Documentation/doc-guide/kernel-doc.rst
index e6ffd59bb8f0..af9697e60165 100644
--- a/Documentation/doc-guide/kernel-doc.rst
+++ b/Documentation/doc-guide/kernel-doc.rst
@@ -533,6 +533,7 @@ identifiers: *[ function/type ...]*
Include documentation for each *function* and *type* in *source*.
If no *function* is specified, the documentation for all functions
and types in the *source* will be included.
+ *type* can be a struct, union, enum, or typedef identifier.
Examples::
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
deleted file mode 100644
index de2cb8de6112..000000000000
--- a/Documentation/dontdiff
+++ /dev/null
@@ -1,271 +0,0 @@
-*.a
-*.aux
-*.bc
-*.bin
-*.bz2
-*.c.[012]*.*
-*.cis
-*.cpio
-*.csp
-*.dsp
-*.dvi
-*.elf
-*.eps
-*.fw
-*.gcno
-*.gcov
-*.gen.S
-*.gif
-*.grep
-*.grp
-*.gz
-*.html
-*.i
-*.jpeg
-*.ko
-*.ll
-*.log
-*.lst
-*.lzma
-*.lzo
-*.mo
-*.moc
-*.mod
-*.mod.c
-*.o
-*.o.*
-*.order
-*.orig
-*.out
-*.patch
-*.pdf
-*.plist
-*.png
-*.pot
-*.ps
-*.rej
-*.s
-*.sgml
-*.so
-*.so.dbg
-*.symtypes
-*.tab.c
-*.tab.h
-*.tex
-*.ver
-*.xml
-*.xz
-*.zst
-*_MODULES
-*_vga16.c
-*~
-\#*#
-*.9
-.*
-.*.d
-.mm
-53c700_d.h
-CVS
-ChangeSet
-GPATH
-GRTAGS
-GSYMS
-GTAGS
-Image
-Module.markers
-Module.symvers
-PENDING
-SCCS
-System.map*
-TAGS
-aconf
-af_names.h
-aic7*reg.h*
-aic7*reg_print.c*
-aic7*seq.h*
-aicasm
-aicdb.h*
-altivec*.c
-asm-offsets.h
-asm_offsets.h
-autoconf.h*
-av_permissions.h
-bbootsect
-binkernel.spec
-bootsect
-bounds.h
-bsetup
-btfixupprep
-build
-bvmlinux
-bzImage*
-capability_names.h
-capflags.c
-classlist.h*
-comp*.log
-compile.h*
-conf
-config
-config-*
-config.mak
-config.mak.autogen
-conmakehash
-consolemap_deftbl.c*
-cpustr.h
-crc32table.h*
-cscope.*
-defkeymap.c
-devlist.h*
-devicetable-offsets.h
-dnotify_test
-dslm
-dtc
-elf2ecoff
-elfconfig.h*
-evergreen_reg_safe.h
-fixdep
-flask.h
-fore200e_mkfirm
-fore200e_pca_fw.c*
-gconf
-gconf-cfg
-gen-devlist
-gen_crc32table
-gen_init_cpio
-generated
-genheaders
-genksyms
-*_gray256.c
-hpet_example
-hugepage-mmap
-hugepage-shm
-ihex2fw
-inat-tables.c
-initramfs_list
-int16.c
-int1.c
-int2.c
-int32.c
-int4.c
-int8.c
-kallsyms
-keywords.c
-ksym.c*
-ksym.h*
-*lex.c
-*lex.*.c
-linux
-logo_*.c
-logo_*_clut224.c
-logo_*_mono.c
-mach-types
-mach-types.h
-machtypes.h
-map
-map_hugetlb
-mconf
-mconf-cfg
-miboot*
-mk_elfconfig
-mkboot
-mkbugboot
-mkcpustr
-mkdep
-mkprep
-mkregtable
-mktables
-mktree
-mkutf8data
-modpost
-modules-only.symvers
-modules.builtin
-modules.builtin.modinfo
-modules.builtin.ranges
-modules.nsdeps
-modules.order
-modversions.h*
-nconf
-nconf-cfg
-ncscope.*
-offset.h
-oui.c*
-page-types
-parse.c
-parse.h
-patches*
-pca200e.bin
-pca200e_ecd.bin2
-perf.data
-perf.data.old
-perf-archive
-piggyback
-piggy.gzip
-piggy.S
-pnmtologo
-ppc_defs.h*
-pss_boot.h
-qconf
-qconf-cfg
-r100_reg_safe.h
-r200_reg_safe.h
-r300_reg_safe.h
-r420_reg_safe.h
-r600_reg_safe.h
-randstruct.seed
-randomize_layout_hash.h
-randomize_layout_seed.h
-recordmcount
-relocs
-rlim_names.h
-rn50_reg_safe.h
-rs600_reg_safe.h
-rv515_reg_safe.h
-series
-setup
-setup.bin
-setup.elf
-sortextable
-sImage
-sm_tbl*
-split-include
-syscalltab.h
-tables.c
-tags
-test_get_len
-tftpboot.img
-timeconst.h
-times.h*
-trix_boot.h
-utsrelease.h*
-vdso-syms.lds
-vdso.lds
-vdso32-int80-syms.lds
-vdso32-syms.lds
-vdso32-syscall-syms.lds
-vdso32-sysenter-syms.lds
-vdso32.lds
-vdso32.so.dbg
-vdso64.lds
-vdso64.so.dbg
-version.h*
-vmImage
-vmlinux
-vmlinux-*
-vmlinux.aout
-vmlinux.bin.all
-vmlinux.lds
-vmlinux.map
-vmlinux.symvers
-vmlinuz
-voffset.h
-vsyscall.lds
-vsyscall_32.lds
-wanxlfw.inc
-uImage
-unifdef
-utf8data.c
-wakeup.bin
-wakeup.elf
-wakeup.lds
-zImage*
-zoffset.h
diff --git a/Documentation/driver-api/auxiliary_bus.rst b/Documentation/driver-api/auxiliary_bus.rst
index cec84908fbc0..b236de773e1d 100644
--- a/Documentation/driver-api/auxiliary_bus.rst
+++ b/Documentation/driver-api/auxiliary_bus.rst
@@ -24,7 +24,6 @@ Auxiliary Device Creation
.. kernel-doc:: drivers/base/auxiliary.c
:identifiers: auxiliary_device_init __auxiliary_device_add
- auxiliary_find_device
Auxiliary Device Memory Model and Lifespan
------------------------------------------
diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
index 5f2ee8d717b1..d594d0ea0e9d 100644
--- a/Documentation/driver-api/driver-model/devres.rst
+++ b/Documentation/driver-api/driver-model/devres.rst
@@ -394,7 +394,6 @@ PCI
pcim_enable_device() : after success, some PCI ops become managed
pcim_iomap() : do iomap() on a single BAR
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
- pcim_iomap_regions_request_all() : do request_region() on all and iomap() on multiple BARs
pcim_iomap_table() : array of mapped addresses indexed by BAR
pcim_iounmap() : do iounmap() on a single BAR
pcim_iounmap_regions() : do iounmap() and release_region() on multiple BARs
@@ -459,11 +458,10 @@ SERDEV
SLAVE DMA ENGINE
devm_acpi_dma_controller_register()
- devm_acpi_dma_controller_free()
SPI
- devm_spi_alloc_master()
- devm_spi_alloc_slave()
+ devm_spi_alloc_host()
+ devm_spi_alloc_target()
devm_spi_optimize_message()
devm_spi_register_controller()
devm_spi_register_host()
diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst
index b4920b34cebc..c290833165e6 100644
--- a/Documentation/driver-api/media/camera-sensor.rst
+++ b/Documentation/driver-api/media/camera-sensor.rst
@@ -81,10 +81,10 @@ restart when the system is resumed. This requires coordination between the
camera sensor and the rest of the camera pipeline. Bridge drivers are
responsible for this coordination, and instruct camera sensors to stop and
restart streaming by calling the appropriate subdev operations
-(``.s_stream()``, ``.enable_streams()`` or ``.disable_streams()``). Camera
-sensor drivers shall therefore **not** keep track of the streaming state to
-stop streaming in the PM suspend handler and restart it in the resume handler.
-Drivers should in general not implement the system PM handlers.
+(``.enable_streams()`` or ``.disable_streams()``). Camera sensor drivers shall
+therefore **not** keep track of the streaming state to stop streaming in the PM
+suspend handler and restart it in the resume handler. Drivers should in general
+not implement the system PM handlers.
Camera sensor drivers shall **not** implement the subdev ``.s_power()``
operation, as it is deprecated. While this operation is implemented in some
diff --git a/Documentation/driver-api/media/drivers/ipu6.rst b/Documentation/driver-api/media/drivers/ipu6.rst
index 6e1dd19b36fb..88f6498e74db 100644
--- a/Documentation/driver-api/media/drivers/ipu6.rst
+++ b/Documentation/driver-api/media/drivers/ipu6.rst
@@ -98,21 +98,6 @@ The IPU6 driver exports its own DMA operations. The IPU6 driver will update the
page table entries for each DMA operation and invalidate the MMU TLB after each
unmap and free.
-.. code-block:: none
-
- const struct dma_map_ops ipu6_dma_ops = {
- .alloc = ipu6_dma_alloc,
- .free = ipu6_dma_free,
- .mmap = ipu6_dma_mmap,
- .map_sg = ipu6_dma_map_sg,
- .unmap_sg = ipu6_dma_unmap_sg,
- ...
- };
-
-.. Note:: IPU6 MMU works behind IOMMU so for each IPU6 DMA ops, driver will call
- generic PCI DMA ops to ask IOMMU to do the additional mapping if VT-d
- enabled.
-
Firmware file format
====================
diff --git a/Documentation/driver-api/media/tx-rx.rst b/Documentation/driver-api/media/tx-rx.rst
index 29d66a47b56e..dd09484df1d3 100644
--- a/Documentation/driver-api/media/tx-rx.rst
+++ b/Documentation/driver-api/media/tx-rx.rst
@@ -49,11 +49,14 @@ Link frequency
The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the
receiver the frequency of the bus (i.e. it is not the same as the symbol rate).
-``.s_stream()`` callback
-^^^^^^^^^^^^^^^^^^^^^^^^
+``.enable_streams()`` and ``.disable_streams()`` callbacks
+^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The struct struct v4l2_subdev_video_ops->s_stream() callback is used by the
-receiver driver to control the transmitter driver's streaming state.
+The struct v4l2_subdev_pad_ops->enable_streams() and struct
+v4l2_subdev_pad_ops->disable_streams() callbacks are used by the receiver driver
+to control the transmitter driver's streaming state. These callbacks may not be
+called directly, but by using ``v4l2_subdev_enable_streams()`` and
+``v4l2_subdev_disable_streams()``.
CSI-2 transmitter drivers
@@ -127,7 +130,7 @@ Stopping the transmitter
^^^^^^^^^^^^^^^^^^^^^^^^
A transmitter stops sending the stream of images as a result of
-calling the ``.s_stream()`` callback. Some transmitters may stop the
+calling the ``.disable_streams()`` callback. Some transmitters may stop the
stream at a frame boundary whereas others stop immediately,
effectively leaving the current frame unfinished. The receiver driver
should not make assumptions either way, but function properly in both
diff --git a/Documentation/driver-api/pci/pci.rst b/Documentation/driver-api/pci/pci.rst
index aa40b1cc243b..59d86e827198 100644
--- a/Documentation/driver-api/pci/pci.rst
+++ b/Documentation/driver-api/pci/pci.rst
@@ -46,6 +46,9 @@ PCI Support Library
.. kernel-doc:: drivers/pci/pci-sysfs.c
:internal:
+.. kernel-doc:: drivers/pci/tph.c
+ :export:
+
PCI Hotplug Support Library
---------------------------
diff --git a/Documentation/driver-api/pwrseq.rst b/Documentation/driver-api/pwrseq.rst
index a644084ded17..ad18b2326b68 100644
--- a/Documentation/driver-api/pwrseq.rst
+++ b/Documentation/driver-api/pwrseq.rst
@@ -11,7 +11,7 @@ Introduction
============
This framework is designed to abstract complex power-up sequences that are
-shared between multiple logical devices in the linux kernel.
+shared between multiple logical devices in the Linux kernel.
The intention is to allow consumers to obtain a power sequencing handle
exposed by the power sequence provider and delegate the actual requesting and
@@ -25,7 +25,7 @@ The power sequencing API uses a number of terms specific to the subsystem:
Unit
- A unit is a discreet chunk of a power sequence. For instance one unit may
+ A unit is a discrete chunk of a power sequence. For instance one unit may
enable a set of regulators, another may enable a specific GPIO. Units can
define dependencies in the form of other units that must be enabled before
it itself can be.
@@ -62,7 +62,7 @@ Provider interface
The provider API is admittedly not nearly as straightforward as the one for
consumers but it makes up for it in flexibility.
-Each provider can logically split the power-up sequence into descrete chunks
+Each provider can logically split the power-up sequence into discrete chunks
(units) and define their dependencies. They can then expose named targets that
consumers may use as the final point in the sequence that they wish to reach.
@@ -72,7 +72,7 @@ register with the pwrseq subsystem by calling pwrseq_device_register().
Dynamic consumer matching
-------------------------
-The main difference between pwrseq and other linux kernel providers is the
+The main difference between pwrseq and other Linux kernel providers is the
mechanism for dynamic matching of consumers and providers. Every power sequence
provider driver must implement the `match()` callback and pass it to the pwrseq
core when registering with the subsystems.
diff --git a/Documentation/fault-injection/fault-injection.rst b/Documentation/fault-injection/fault-injection.rst
index 8b8aeea71c68..1c14ba08fbfc 100644
--- a/Documentation/fault-injection/fault-injection.rst
+++ b/Documentation/fault-injection/fault-injection.rst
@@ -45,6 +45,32 @@ Available fault injection capabilities
ALLOW_ERROR_INJECTION() macro, by setting debugfs entries
under /sys/kernel/debug/fail_function. No boot option supported.
+- fail_skb_realloc
+
+ inject skb (socket buffer) reallocation events into the network path. The
+ primary goal is to identify and prevent issues related to pointer
+ mismanagement in the network subsystem. By forcing skb reallocation at
+ strategic points, this feature creates scenarios where existing pointers to
+ skb headers become invalid.
+
+ When the fault is injected and the reallocation is triggered, cached pointers
+ to skb headers and data no longer reference valid memory locations. This
+ deliberate invalidation helps expose code paths where proper pointer updating
+ is neglected after a reallocation event.
+
+ By creating these controlled fault scenarios, the system can catch instances
+ where stale pointers are used, potentially leading to memory corruption or
+ system instability.
+
+ To select the interface to act on, write the network name to
+ /sys/kernel/debug/fail_skb_realloc/devname.
+ If this field is left empty (which is the default value), skb reallocation
+ will be forced on all network interfaces.
+
+ The effectiveness of this fault detection is enhanced when KASAN is
+ enabled, as it helps identify invalid memory references and use-after-free
+ (UAF) issues.
+
- NVMe fault injection
inject NVMe status code and retry flag on devices permitted by setting
@@ -216,6 +242,19 @@ configuration of fault-injection capabilities.
use a negative errno, you better use 'printf' instead of 'echo', e.g.:
$ printf %#x -12 > retval
+- /sys/kernel/debug/fail_skb_realloc/devname:
+
+ Specifies the network interface on which to force SKB reallocation. If
+ left empty, SKB reallocation will be applied to all network interfaces.
+
+ Example usage::
+
+ # Force skb reallocation on eth0
+ echo "eth0" > /sys/kernel/debug/fail_skb_realloc/devname
+
+ # Clear the selection and force skb reallocation on all interfaces
+ echo "" > /sys/kernel/debug/fail_skb_realloc/devname
+
Boot option
^^^^^^^^^^^
@@ -227,6 +266,7 @@ use the boot option::
fail_usercopy=
fail_make_request=
fail_futex=
+ fail_skb_realloc=
mmc_core.fail_request=<interval>,<probability>,<space>,<times>
proc entries
diff --git a/Documentation/features/locking/queued-spinlocks/arch-support.txt b/Documentation/features/locking/queued-spinlocks/arch-support.txt
index 22f2990392ff..cf26042480e2 100644
--- a/Documentation/features/locking/queued-spinlocks/arch-support.txt
+++ b/Documentation/features/locking/queued-spinlocks/arch-support.txt
@@ -20,7 +20,7 @@
| openrisc: | ok |
| parisc: | TODO |
| powerpc: | ok |
- | riscv: | TODO |
+ | riscv: | ok |
| s390: | TODO |
| sh: | TODO |
| sparc: | ok |
diff --git a/Documentation/filesystems/autofs.rst b/Documentation/filesystems/autofs.rst
index 1ac576458c69..5eb02394fcc3 100644
--- a/Documentation/filesystems/autofs.rst
+++ b/Documentation/filesystems/autofs.rst
@@ -442,7 +442,7 @@ which can be used to communicate directly with the autofs filesystem.
It requires CAP_SYS_ADMIN for access.
The 'ioctl's that can be used on this device are described in a separate
-document `autofs-mount-control.txt`, and are summarised briefly here.
+document `autofs-mount-control.rst`, and are summarised briefly here.
Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure::
struct autofs_dev_ioctl {
diff --git a/Documentation/filesystems/dlmfs.rst b/Documentation/filesystems/dlmfs.rst
index 7e2b1fd471d7..70d4e48242c3 100644
--- a/Documentation/filesystems/dlmfs.rst
+++ b/Documentation/filesystems/dlmfs.rst
@@ -36,7 +36,7 @@ None
Usage
=====
-If you're just interested in OCFS2, then please see ocfs2.txt. The
+If you're just interested in OCFS2, then please see ocfs2.rst. The
rest of this document will be geared towards those who want to use
dlmfs for easy to setup and easy to use clustered locking in
userspace.
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index 68a0885fb5e6..fb7d2ee022bc 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -943,3 +943,47 @@ NVMe Zoned Namespace devices
can start before the zone-capacity and span across zone-capacity boundary.
Such spanning segments are also considered as usable segments. All blocks
past the zone-capacity are considered unusable in these segments.
+
+Device aliasing feature
+-----------------------
+
+f2fs can utilize a special file called a "device aliasing file." This file allows
+the entire storage device to be mapped with a single, large extent, not using
+the usual f2fs node structures. This mapped area is pinned and primarily intended
+for holding the space.
+
+Essentially, this mechanism allows a portion of the f2fs area to be temporarily
+reserved and used by another filesystem or for different purposes. Once that
+external usage is complete, the device aliasing file can be deleted, releasing
+the reserved space back to F2FS for its own use.
+
+<use-case>
+
+# ls /dev/vd*
+/dev/vdb (32GB) /dev/vdc (32GB)
+# mkfs.ext4 /dev/vdc
+# mkfs.f2fs -c /dev/vdc@vdc.file /dev/vdb
+# mount /dev/vdb /mnt/f2fs
+# ls -l /mnt/f2fs
+vdc.file
+# df -h
+/dev/vdb 64G 33G 32G 52% /mnt/f2fs
+
+# mount -o loop /dev/vdc /mnt/ext4
+# df -h
+/dev/vdb 64G 33G 32G 52% /mnt/f2fs
+/dev/loop7 32G 24K 30G 1% /mnt/ext4
+# umount /mnt/ext4
+
+# f2fs_io getflags /mnt/f2fs/vdc.file
+get a flag on /mnt/f2fs/vdc.file ret=0, flags=nocow(pinned),immutable
+# f2fs_io setflags noimmutable /mnt/f2fs/vdc.file
+get a flag on noimmutable ret=0, flags=800010
+set a flag on /mnt/f2fs/vdc.file ret=0, flags=noimmutable
+# rm /mnt/f2fs/vdc.file
+# df -h
+/dev/vdb 64G 753M 64G 2% /mnt/f2fs
+
+So, the key idea is, user can do any file operations on /dev/vdc, and
+reclaim the space after the use, while the space is counted as /data.
+That doesn't require modifying partition size and filesystem format.
diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst
index 0e2fac7a16da..76e538217868 100644
--- a/Documentation/filesystems/fsverity.rst
+++ b/Documentation/filesystems/fsverity.rst
@@ -16,7 +16,7 @@ btrfs filesystems. Like fscrypt, not too much filesystem-specific
code is needed to support fs-verity.
fs-verity is similar to `dm-verity
-<https://www.kernel.org/doc/Documentation/device-mapper/verity.txt>`_
+<https://www.kernel.org/doc/Documentation/admin-guide/device-mapper/verity.rst>`_
but works on files rather than block devices. On regular files on
filesystems supporting fs-verity, userspace can execute an ioctl that
causes the filesystem to build a Merkle tree for the file and persist
diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst
index e8e496d23e1d..44e9e77ffe0d 100644
--- a/Documentation/filesystems/index.rst
+++ b/Documentation/filesystems/index.rst
@@ -29,6 +29,7 @@ algorithms work.
fiemap
files
locks
+ multigrain-ts
mount_api
quota
seq_file
diff --git a/Documentation/filesystems/iomap/operations.rst b/Documentation/filesystems/iomap/operations.rst
index b93115ab8748..ef082e5a4e0c 100644
--- a/Documentation/filesystems/iomap/operations.rst
+++ b/Documentation/filesystems/iomap/operations.rst
@@ -513,6 +513,21 @@ IOMAP_WRITE`` with any combination of the following enhancements:
if the mapping is unwritten and the filesystem cannot handle zeroing
the unaligned regions without exposing stale contents.
+ * ``IOMAP_ATOMIC``: This write is being issued with torn-write
+ protection.
+ Only a single bio can be created for the write, and the write must
+ not be split into multiple I/O requests, i.e. flag REQ_ATOMIC must be
+ set.
+ The file range to write must be aligned to satisfy the requirements
+ of both the filesystem and the underlying block device's atomic
+ commit capabilities.
+ If filesystem metadata updates are required (e.g. unwritten extent
+ conversion or copy on write), all updates for the entire file range
+ must be committed atomically as well.
+ Only one space mapping is allowed per untorn write.
+ Untorn writes must be aligned to, and must not be longer than, a
+ single file block.
+
Callers commonly hold ``i_rwsem`` in shared or exclusive mode before
calling this function.
diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst
index 317934c9e8fc..d92c276f1575 100644
--- a/Documentation/filesystems/mount_api.rst
+++ b/Documentation/filesystems/mount_api.rst
@@ -770,7 +770,8 @@ process the parameters it is given.
* ::
- bool fs_validate_description(const struct fs_parameter_description *desc);
+ bool fs_validate_description(const char *name,
+ const struct fs_parameter_description *desc);
This performs some validation checks on a parameter description. It
returns true if the description is good and false if it is not. It will
diff --git a/Documentation/filesystems/multigrain-ts.rst b/Documentation/filesystems/multigrain-ts.rst
new file mode 100644
index 000000000000..c779e47284e8
--- /dev/null
+++ b/Documentation/filesystems/multigrain-ts.rst
@@ -0,0 +1,125 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================
+Multigrain Timestamps
+=====================
+
+Introduction
+============
+Historically, the kernel has always used coarse time values to stamp inodes.
+This value is updated every jiffy, so any change that happens within that jiffy
+will end up with the same timestamp.
+
+When the kernel goes to stamp an inode (due to a read or write), it first gets
+the current time and then compares it to the existing timestamp(s) to see
+whether anything will change. If nothing changed, then it can avoid updating
+the inode's metadata.
+
+Coarse timestamps are therefore good from a performance standpoint, since they
+reduce the need for metadata updates, but bad from the standpoint of
+determining whether anything has changed, since a lot of things can happen in a
+jiffy.
+
+They are particularly troublesome with NFSv3, where unchanging timestamps can
+make it difficult to tell whether to invalidate caches. NFSv4 provides a
+dedicated change attribute that should always show a visible change, but not
+all filesystems implement this properly, causing the NFS server to substitute
+the ctime in many cases.
+
+Multigrain timestamps aim to remedy this by selectively using fine-grained
+timestamps when a file has had its timestamps queried recently, and the current
+coarse-grained time does not cause a change.
+
+Inode Timestamps
+================
+There are currently 3 timestamps in the inode that are updated to the current
+wallclock time on different activity:
+
+ctime:
+ The inode change time. This is stamped with the current time whenever
+ the inode's metadata is changed. Note that this value is not settable
+ from userland.
+
+mtime:
+ The inode modification time. This is stamped with the current time
+ any time a file's contents change.
+
+atime:
+ The inode access time. This is stamped whenever an inode's contents are
+ read. Widely considered to be a terrible mistake. Usually avoided with
+ options like noatime or relatime.
+
+Updating the mtime always implies a change to the ctime, but updating the
+atime due to a read request does not.
+
+Multigrain timestamps are only tracked for the ctime and the mtime. atimes are
+not affected and always use the coarse-grained value (subject to the floor).
+
+Inode Timestamp Ordering
+========================
+
+In addition to just providing info about changes to individual files, file
+timestamps also serve an important purpose in applications like "make". These
+programs measure timestamps in order to determine whether source files might be
+newer than cached objects.
+
+Userland applications like make can only determine ordering based on
+operational boundaries. For a syscall those are the syscall entry and exit
+points. For io_uring or nfsd operations, that's the request submission and
+response. In the case of concurrent operations, userland can make no
+determination about the order in which things will occur.
+
+For instance, if a single thread modifies one file, and then another file in
+sequence, the second file must show an equal or later mtime than the first. The
+same is true if two threads are issuing similar operations that do not overlap
+in time.
+
+If however, two threads have racing syscalls that overlap in time, then there
+is no such guarantee, and the second file may appear to have been modified
+before, after or at the same time as the first, regardless of which one was
+submitted first.
+
+Note that the above assumes that the system doesn't experience a backward jump
+of the realtime clock. If that occurs at an inopportune time, then timestamps
+can appear to go backward, even on a properly functioning system.
+
+Multigrain Timestamp Implementation
+===================================
+Multigrain timestamps are aimed at ensuring that changes to a single file are
+always recognizable, without violating the ordering guarantees when multiple
+different files are modified. This affects the mtime and the ctime, but the
+atime will always use coarse-grained timestamps.
+
+It uses an unused bit in the i_ctime_nsec field to indicate whether the mtime
+or ctime has been queried. If either or both have, then the kernel takes
+special care to ensure the next timestamp update will display a visible change.
+This ensures tight cache coherency for use-cases like NFS, without sacrificing
+the benefits of reduced metadata updates when files aren't being watched.
+
+The Ctime Floor Value
+=====================
+It's not sufficient to simply use fine or coarse-grained timestamps based on
+whether the mtime or ctime has been queried. A file could get a fine grained
+timestamp, and then a second file modified later could get a coarse-grained one
+that appears earlier than the first, which would break the kernel's timestamp
+ordering guarantees.
+
+To mitigate this problem, maintain a global floor value that ensures that
+this can't happen. The two files in the above example may appear to have been
+modified at the same time in such a case, but they will never show the reverse
+order. To avoid problems with realtime clock jumps, the floor is managed as a
+monotonic ktime_t, and the values are converted to realtime clock values as
+needed.
+
+Implementation Notes
+====================
+Multigrain timestamps are intended for use by local filesystems that get
+ctime values from the local clock. This is in contrast to network filesystems
+and the like that just mirror timestamp values from a server.
+
+For most filesystems, it's sufficient to just set the FS_MGTIME flag in the
+fstype->fs_flags in order to opt-in, providing the ctime is only ever set via
+inode_set_ctime_current(). If the filesystem has a ->getattr routine that
+doesn't call generic_fillattr, then it should call fill_mg_cmtime() to
+fill those values. For setattr, it should use setattr_copy() to update the
+timestamps, or otherwise mimic its behavior.
diff --git a/Documentation/filesystems/nfs/exporting.rst b/Documentation/filesystems/nfs/exporting.rst
index f04ce1215a03..de64d2d002a2 100644
--- a/Documentation/filesystems/nfs/exporting.rst
+++ b/Documentation/filesystems/nfs/exporting.rst
@@ -238,10 +238,3 @@ following flags are defined:
all of an inode's dirty data on last close. Exports that behave this
way should set EXPORT_OP_FLUSH_ON_CLOSE so that NFSD knows to skip
waiting for writeback when closing such files.
-
- EXPORT_OP_ASYNC_LOCK - Indicates a capable filesystem to do async lock
- requests from lockd. Only set EXPORT_OP_ASYNC_LOCK if the filesystem has
- it's own ->lock() functionality as core posix_lock_file() implementation
- has no async lock request handling yet. For more information about how to
- indicate an async lock request from a ->lock() file_operations struct, see
- fs/locks.c and comment for the function vfs_lock_file().
diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst
index 343644712340..4c8387e1c880 100644
--- a/Documentation/filesystems/overlayfs.rst
+++ b/Documentation/filesystems/overlayfs.rst
@@ -440,6 +440,23 @@ For example::
fsconfig(fs_fd, FSCONFIG_SET_STRING, "datadir+", "/do2", 0);
+Specifying layers via file descriptors
+--------------------------------------
+
+Since kernel v6.13, overlayfs supports specifying layers via file descriptors in
+addition to specifying them as paths. This feature is available for the
+"datadir+", "lowerdir+", "upperdir", and "workdir+" mount options with the
+fsconfig syscall from the new mount api::
+
+ fsconfig(fs_fd, FSCONFIG_SET_FD, "lowerdir+", NULL, fd_lower1);
+ fsconfig(fs_fd, FSCONFIG_SET_FD, "lowerdir+", NULL, fd_lower2);
+ fsconfig(fs_fd, FSCONFIG_SET_FD, "lowerdir+", NULL, fd_lower3);
+ fsconfig(fs_fd, FSCONFIG_SET_FD, "datadir+", NULL, fd_data1);
+ fsconfig(fs_fd, FSCONFIG_SET_FD, "datadir+", NULL, fd_data2);
+ fsconfig(fs_fd, FSCONFIG_SET_FD, "workdir", NULL, fd_work);
+ fsconfig(fs_fd, FSCONFIG_SET_FD, "upperdir", NULL, fd_upper);
+
+
fs-verity support
-----------------
diff --git a/Documentation/filesystems/path-lookup.rst b/Documentation/filesystems/path-lookup.rst
index 2b2df6aa5432..9ced1135608e 100644
--- a/Documentation/filesystems/path-lookup.rst
+++ b/Documentation/filesystems/path-lookup.rst
@@ -531,7 +531,7 @@ this retry process in the next article.
Automount points are locations in the filesystem where an attempt to
lookup a name can trigger changes to how that lookup should be
handled, in particular by mounting a filesystem there. These are
-covered in greater detail in autofs.txt in the Linux documentation
+covered in greater detail in autofs.rst in the Linux documentation
tree, but a few notes specifically related to path lookup are in order
here.
diff --git a/Documentation/filesystems/path-lookup.txt b/Documentation/filesystems/path-lookup.txt
index 1aa7ce099f6f..d2cf2852e1f8 100644
--- a/Documentation/filesystems/path-lookup.txt
+++ b/Documentation/filesystems/path-lookup.txt
@@ -379,4 +379,4 @@ Papers and other documentation on dcache locking
2. http://lse.sourceforge.net/locking/dcache/dcache.html
-3. path-lookup.md in this directory.
+3. path-lookup.rst in this directory.
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 92bffcc6747a..9ab2a3d6f2b4 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -177,7 +177,7 @@ settles down a bit.
**mandatory**
s_export_op is now required for exporting a filesystem.
-isofs, ext2, ext3, reiserfs, fat
+isofs, ext2, ext3, fat
can be used as examples of very different filesystems.
---
diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
index e834779d9611..6a882c57a7e7 100644
--- a/Documentation/filesystems/proc.rst
+++ b/Documentation/filesystems/proc.rst
@@ -579,7 +579,7 @@ encoded manner. The codes are the following:
mt arm64 MTE allocation tags are enabled
um userfaultfd missing tracking
uw userfaultfd wr-protect tracking
- ss shadow stack page
+ ss shadow/guarded control stack page
sl sealed
== =======================================
diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.rst b/Documentation/filesystems/ramfs-rootfs-initramfs.rst
index 447f767c6462..fa4f81099cb4 100644
--- a/Documentation/filesystems/ramfs-rootfs-initramfs.rst
+++ b/Documentation/filesystems/ramfs-rootfs-initramfs.rst
@@ -315,7 +315,7 @@ the above threads) is:
2) The cpio archive format chosen by the kernel is simpler and cleaner (and
thus easier to create and parse) than any of the (literally dozens of)
various tar archive formats. The complete initramfs archive format is
- explained in buffer-format.txt, created in usr/gen_init_cpio.c, and
+ explained in buffer-format.rst, created in usr/gen_init_cpio.c, and
extracted in init/initramfs.c. All three together come to less than 26k
total of human-readable text.
diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst
index 56a26c843dbe..d677e0428c3f 100644
--- a/Documentation/filesystems/tmpfs.rst
+++ b/Documentation/filesystems/tmpfs.rst
@@ -241,6 +241,28 @@ So 'mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs'
will give you tmpfs instance on /mytmpfs which can allocate 10GB
RAM/SWAP in 10240 inodes and it is only accessible by root.
+tmpfs has the following mounting options for case-insensitive lookup support:
+
+================= ==============================================================
+casefold Enable casefold support at this mount point using the given
+ argument as the encoding standard. Currently only UTF-8
+ encodings are supported. If no argument is used, it will load
+ the latest UTF-8 encoding available.
+strict_encoding Enable strict encoding at this mount point (disabled by
+ default). In this mode, the filesystem refuses to create file
+ and directory with names containing invalid UTF-8 characters.
+================= ==============================================================
+
+This option doesn't render the entire filesystem case-insensitive. One needs to
+still set the casefold flag per directory, by flipping the +F attribute in an
+empty directory. Nevertheless, new directories will inherit the attribute. The
+mountpoint itself cannot be made case-insensitive.
+
+Example::
+
+ $ mount -t tmpfs -o casefold=utf8-12.1.0,strict_encoding fs_name /mytmpfs
+ $ mount -t tmpfs -o casefold fs_name /mytmpfs
+
:Author:
Christoph Rohland <cr@sap.com>, 1.12.01
@@ -250,3 +272,5 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
KOSAKI Motohiro, 16 Mar 2010
:Updated:
Chris Down, 13 July 2020
+:Updated:
+ André Almeida, 23 Aug 2024
diff --git a/Documentation/gpu/amdgpu/index.rst b/Documentation/gpu/amdgpu/index.rst
index 847e04924030..302d039928ee 100644
--- a/Documentation/gpu/amdgpu/index.rst
+++ b/Documentation/gpu/amdgpu/index.rst
@@ -16,4 +16,5 @@ Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures.
thermal
driver-misc
debugging
+ process-isolation
amdgpu-glossary
diff --git a/Documentation/gpu/amdgpu/process-isolation.rst b/Documentation/gpu/amdgpu/process-isolation.rst
new file mode 100644
index 000000000000..6b6d70e357a7
--- /dev/null
+++ b/Documentation/gpu/amdgpu/process-isolation.rst
@@ -0,0 +1,59 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================
+ AMDGPU Process Isolation
+=========================
+
+The AMDGPU driver includes a feature that enables automatic process isolation on the graphics engine. This feature serializes access to the graphics engine and adds a cleaner shader which clears the Local Data Store (LDS) and General Purpose Registers (GPRs) between jobs. All processes using the GPU, including both graphics and compute workloads, are serialized when this feature is enabled. On GPUs that support partitionable graphics engines, this feature can be enabled on a per-partition basis.
+
+In addition, there is an interface to manually run the cleaner shader when the use of the GPU is complete. This may be preferable in some use cases, such as a single-user system where the login manager triggers the cleaner shader when the user logs out.
+
+Process Isolation
+=================
+
+The `run_cleaner_shader` and `enforce_isolation` sysfs interfaces allow users to manually execute the cleaner shader and control the process isolation feature, respectively.
+
+Partition Handling
+------------------
+
+The `enforce_isolation` file in sysfs can be used to enable process isolation and automatic shader cleanup between processes. On GPUs that support graphics engine partitioning, this can be enabled per partition. The partition and its current setting (0 disabled, 1 enabled) can be read from sysfs. On GPUs that do not support graphics engine partitioning, only a single partition will be present. Writing 1 to the partition position enables enforce isolation, writing 0 disables it.
+
+Example of enabling enforce isolation on a GPU with multiple partitions:
+
+.. code-block:: console
+
+ $ echo 1 0 1 0 > /sys/class/drm/card0/device/enforce_isolation
+ $ cat /sys/class/drm/card0/device/enforce_isolation
+ 1 0 1 0
+
+The output indicates that enforce isolation is enabled on zeroth and second parition and disabled on first and fourth parition.
+
+For devices with a single partition or those that do not support partitions, there will be only one element:
+
+.. code-block:: console
+
+ $ echo 1 > /sys/class/drm/card0/device/enforce_isolation
+ $ cat /sys/class/drm/card0/device/enforce_isolation
+ 1
+
+Cleaner Shader Execution
+========================
+
+The driver can trigger a cleaner shader to clean up the LDS and GPR state on the graphics engine. When process isolation is enabled, this happens automatically between processes. In addition, there is a sysfs file to manually trigger cleaner shader execution.
+
+To manually trigger the execution of the cleaner shader, write `0` to the `run_cleaner_shader` sysfs file:
+
+.. code-block:: console
+
+ $ echo 0 > /sys/class/drm/card0/device/run_cleaner_shader
+
+For multi-partition devices, you can specify the partition index when triggering the cleaner shader:
+
+.. code-block:: console
+
+ $ echo 0 > /sys/class/drm/card0/device/run_cleaner_shader # For partition 0
+ $ echo 1 > /sys/class/drm/card0/device/run_cleaner_shader # For partition 1
+ $ echo 2 > /sys/class/drm/card0/device/run_cleaner_shader # For partition 2
+ # ... and so on for each partition
+
+This command initiates the cleaner shader, which will run and complete before any new tasks are scheduled on the GPU.
diff --git a/Documentation/gpu/amdgpu/thermal.rst b/Documentation/gpu/amdgpu/thermal.rst
index 6d942b5c58f0..1768a106aab1 100644
--- a/Documentation/gpu/amdgpu/thermal.rst
+++ b/Documentation/gpu/amdgpu/thermal.rst
@@ -100,6 +100,18 @@ fan_minimum_pwm
.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
:doc: fan_minimum_pwm
+fan_zero_rpm_enable
+----------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+ :doc: fan_zero_rpm_enable
+
+fan_zero_rpm_stop_temperature
+-----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
+ :doc: fan_zero_rpm_stop_temperature
+
GFXOFF
======
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index ad59ae579237..7a469df675d8 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -35,10 +35,10 @@ Interrupt Handling
:functions: intel_irq_init intel_irq_init_hw intel_hpd_init
.. kernel-doc:: drivers/gpu/drm/i915/i915_irq.c
- :functions: intel_runtime_pm_disable_interrupts
+ :functions: intel_irq_suspend
.. kernel-doc:: drivers/gpu/drm/i915/i915_irq.c
- :functions: intel_runtime_pm_enable_interrupts
+ :functions: intel_irq_resume
Intel GVT-g Guest Support(vGPU)
-------------------------------
diff --git a/Documentation/gpu/msm-preemption.rst b/Documentation/gpu/msm-preemption.rst
new file mode 100644
index 000000000000..d768ca09fdec
--- /dev/null
+++ b/Documentation/gpu/msm-preemption.rst
@@ -0,0 +1,99 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+:orphan:
+
+==============
+MSM Preemption
+==============
+
+Preemption allows Adreno GPUs to switch to a higher priority ring when work is
+pushed to it, reducing latency for high priority submissions.
+
+When preemption is enabled 4 rings are initialized, corresponding to different
+priority levels. Having multiple rings is purely a software concept as the GPU
+only has registers to keep track of one graphics ring.
+The kernel is able to switch which ring is currently being processed by
+requesting preemption. When certain conditions are met, depending on the
+priority level, the GPU will save its current state in a series of buffers,
+then restores state from a similar set of buffers specified by the kernel. It
+then resumes execution and fires an IRQ to let the kernel know the context
+switch has completed.
+
+This mechanism can be used by the kernel to switch between rings. Whenever a
+submission occurs the kernel finds the highest priority ring which isn't empty
+and preempts to it if said ring is not the one being currently executed. This is
+also done whenever a submission completes to make sure execution resumes on a
+lower priority ring when a higher priority ring is done.
+
+Preemption levels
+-----------------
+
+Preemption can only occur at certain boundaries. The exact conditions can be
+configured by changing the preemption level, this allows to compromise between
+latency (ie. the time that passes between when the kernel requests preemption
+and when the SQE begins saving state) and overhead (the amount of state that
+needs to be saved).
+
+The GPU offers 3 levels:
+
+Level 0
+ Preemption only occurs at the submission level. This requires the least amount
+ of state to be saved as the execution of userspace submitted IBs is never
+ interrupted, however it offers very little benefit compared to not enabling
+ preemption of any kind.
+
+Level 1
+ Preemption occurs at either bin level, if using GMEM rendering, or draw level
+ in the sysmem rendering case.
+
+Level 2
+ Preemption occurs at draw level.
+
+Level 1 is the mode that is used by the msm driver.
+
+Additionally the GPU allows to specify a `skip_save_restore` option. This
+disables the saving and restoring of all registers except those relating to the
+operation of the SQE itself, reducing overhead. Saving and restoring is only
+skipped when using GMEM with Level 1 preemption. When enabling this userspace is
+expected to set the state that isn't preserved whenever preemption occurs which
+is done by specifying preamble and postambles. Those are IBs that are executed
+before and after preemption.
+
+Preemption buffers
+------------------
+
+A series of buffers are necessary to store the state of rings while they are not
+being executed. There are different kinds of preemption records and most of
+those require one buffer per ring. This is because preemption never occurs
+between submissions on the same ring, which always run in sequence when the ring
+is active. This means that only one context per ring is effectively active.
+
+SMMU_INFO
+ This buffer contains info about the current SMMU configuration such as the
+ ttbr0 register. The SQE firmware isn't actually able to save this record.
+ As a result SMMU info must be saved manually from the CP to a buffer and the
+ SMMU record updated with info from said buffer before triggering
+ preemption.
+
+NON_SECURE
+ This is the main preemption record where most state is saved. It is mostly
+ opaque to the kernel except for the first few words that must be initialized
+ by the kernel.
+
+SECURE
+ This saves state related to the GPU's secure mode.
+
+NON_PRIV
+ The intended purpose of this record is unknown. The SQE firmware actually
+ ignores it and therefore msm doesn't handle it.
+
+COUNTER
+ This record is used to save and restore performance counters.
+
+Handling the permissions of those buffers is critical for security. All but the
+NON_PRIV records need to be inaccessible from userspace, so they must be mapped
+in the kernel address space with the MSM_BO_MAP_PRIV flag.
+For example, making the NON_SECURE record accessible from userspace would allow
+any process to manipulate a saved ring's RPTR which can be used to skip the
+execution of some packets in a ring and execute user commands with higher
+privileges.
diff --git a/Documentation/hwmon/f71882fg.rst b/Documentation/hwmon/f71882fg.rst
index 38e30fbd4806..53d32bf06b70 100644
--- a/Documentation/hwmon/f71882fg.rst
+++ b/Documentation/hwmon/f71882fg.rst
@@ -178,10 +178,11 @@ Writing an unsupported mode will result in an invalid parameter error.
available on the F71858FG / F8000 if the fan channel is in RPM mode.
* 2: Normal auto mode
- You can define a number of temperature/fan speed trip points, which % the
- fan should run at at this temp and which temp a fan should follow using the
- standard sysfs interface. The number and type of trip points is chip
- depended, see which files are available in sysfs.
+ You can define a number of temperature/fan speed trip points that specify
+ the percentage at which the fan should run at each temperature, and which
+ temperature sensor a fan should follow, using the standard sysfs interface.
+ The number and type of trip points are chip dependent - see the available
+ files in sysfs.
Fan/PWM channel 3 of the F8000 is always in this mode!
* 3: Thermostat mode (Only available on the F8000 when in duty cycle mode)
diff --git a/Documentation/hwmon/ina2xx.rst b/Documentation/hwmon/ina2xx.rst
index 7f1939b40f74..a3860aae444c 100644
--- a/Documentation/hwmon/ina2xx.rst
+++ b/Documentation/hwmon/ina2xx.rst
@@ -53,6 +53,27 @@ Supported chips:
https://www.ti.com/
+ * Texas Instruments INA260
+
+ Prefix: 'ina260'
+
+ Addresses: I2C 0x40 - 0x4f
+
+ Datasheet: Publicly available at the Texas Instruments website
+
+ https://www.ti.com/
+
+ * Silergy SY24655
+
+ Prefix: 'sy24655'
+
+ Addresses: I2C 0x40 - 0x4f
+
+ Datasheet: Publicly available at the Silergy website
+
+ https://us1.silergy.com/
+
+
Author: Lothar Felten <lothar.felten@gmail.com>
Description
@@ -72,6 +93,14 @@ INA230 and INA231 are high or low side current shunt and power monitors
with an I2C interface. The chips monitor both a shunt voltage drop and
bus supply voltage.
+INA260 is a high or low side current and power monitor with integrated shunt
+resistor.
+
+The SY24655 is a high- and low-side current shunt and power monitor with an I2C
+interface. The SY24655 supports both shunt drop and supply voltage, with
+programmable calibration value and conversion times. The SY24655 can also
+calculate average power for use in energy conversion.
+
The shunt value in micro-ohms can be set via platform data or device tree at
compile-time or via the shunt_resistor attribute in sysfs at run-time. Please
refer to the Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml for bindings
@@ -87,16 +116,16 @@ The actual programmed interval may vary from the desired value.
General sysfs entries
---------------------
-======================= ===============================
+======================= ===============================================
in0_input Shunt voltage(mV) channel
in1_input Bus voltage(mV) channel
curr1_input Current(mA) measurement channel
power1_input Power(uW) measurement channel
-shunt_resistor Shunt resistance(uOhm) channel
-======================= ===============================
+shunt_resistor Shunt resistance(uOhm) channel (not for ina260)
+======================= ===============================================
-Sysfs entries for ina226, ina230 and ina231 only
-------------------------------------------------
+Additional sysfs entries for ina226, ina230, ina231, ina260, and sy24655
+------------------------------------------------------------------------
======================= ====================================================
curr1_lcrit Critical low current
@@ -117,6 +146,13 @@ update_interval data conversion time; affects number of samples used
to average results for shunt and bus voltages.
======================= ====================================================
+Sysfs entries for sy24655 only
+------------------------------
+
+======================= ====================================================
+power1_average average power from last reading to the present.
+======================= ====================================================
+
.. note::
- Configure `shunt_resistor` before configure `power1_crit`, because power
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index ea3b5be8fe4f..55f1111594b2 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -96,6 +96,7 @@ Hardware Monitoring Kernel Drivers
ir35221
ir38064
ir36021
+ isl28022
isl68137
it87
jc42
@@ -174,6 +175,7 @@ Hardware Monitoring Kernel Drivers
mpq8785
nct6683
nct6775
+ nct7363
nct7802
nct7904
npcm750-pwm-fan
diff --git a/Documentation/hwmon/isl28022.rst b/Documentation/hwmon/isl28022.rst
new file mode 100644
index 000000000000..8d4422a2dacd
--- /dev/null
+++ b/Documentation/hwmon/isl28022.rst
@@ -0,0 +1,63 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver isl28022
+======================
+
+Supported chips:
+
+ * Renesas ISL28022
+
+ Prefix: 'isl28022'
+
+ Addresses scanned: none
+
+ Datasheet: Publicly available at the Renesas website
+
+ https://www.renesas.com/us/en/www/doc/datasheet/isl28022.pdf
+
+Author:
+ Carsten Spieß <mail@carsten-spiess.de>
+
+Description
+-----------
+
+The ISL28022 is a power monitor with I2C interface. The device monitors
+voltage, current via shunt resistor and calculated power.
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+device explicitly. Please see Documentation/i2c/instantiating-devices.rst for
+details.
+
+The shunt value in micro-ohms, shunt voltage range and averaging can be set
+with device properties.
+Please refer to the Documentation/devicetree/bindings/hwmon/isl,isl28022.yaml
+for bindings if the device tree is used.
+
+The driver supports only shunt and bus continuous ADC mode at 15bit resolution.
+Averaging can be set from 1 to 128 samples (power of 2) on both channels.
+Shunt voltage range of 40, 80, 160 or 320mV is allowed
+The bus voltage range is 60V fixed.
+
+Sysfs entries
+-------------
+
+The following attributes are supported. All attributes are read-only.
+
+======================= =======================================================
+in0_input bus voltage (milli Volt)
+
+curr1_input current (milli Ampere)
+power1_input power (micro Watt)
+======================= =======================================================
+
+Debugfs entries
+---------------
+
+The following attributes are supported. All attributes are read-only.
+
+======================= =======================================================
+shunt_voltage shunt voltage (micro Volt)
+======================= =======================================================
diff --git a/Documentation/hwmon/ltc2978.rst b/Documentation/hwmon/ltc2978.rst
index edf24e5e1e11..651ca4904c66 100644
--- a/Documentation/hwmon/ltc2978.rst
+++ b/Documentation/hwmon/ltc2978.rst
@@ -1,3 +1,5 @@
+.. SPDX-License-Identifier: GPL-2.0
+
Kernel driver ltc2978
=====================
@@ -117,6 +119,14 @@ Supported chips:
Datasheet: https://www.analog.com/en/products/ltc3889
+ * Linear Technology LTC7841
+
+ Prefix: 'ltc7841'
+
+ Addresses scanned: -
+
+ Datasheet: https://www.analog.com/en/products/ltc7841
+
* Linear Technology LTC7880
Prefix: 'ltc7880'
@@ -290,6 +300,7 @@ in[N]_label "vout[1-8]".
LTC7880, LTM4644, LTM4675, LTM4676, LTM4677, LTM4678,
LTM4680, LTM4700: N=2-3
- LTC3883: N=2
+ - LTC7841: N=2
in[N]_input Measured output voltage.
@@ -420,6 +431,7 @@ curr[N]_label "iout[1-4]".
LTM4664, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680,
LTM4700: N=2-3
- LTC3883: N=2
+ - LTC7841: N=2
curr[N]_input Measured output current.
diff --git a/Documentation/hwmon/max31827.rst b/Documentation/hwmon/max31827.rst
index 9c11a9518c67..6cc5088b26b7 100644
--- a/Documentation/hwmon/max31827.rst
+++ b/Documentation/hwmon/max31827.rst
@@ -136,7 +136,7 @@ PEC Support
When reading a register value, the PEC byte is computed and sent by the chip.
-PEC on word data transaction respresents a signifcant increase in bandwitdh
+PEC on word data transaction represents a significant increase in bandwidth
usage (+33% for both write and reads) in normal conditions.
Since this operation implies there will be an extra delay to each
diff --git a/Documentation/hwmon/nct7363.rst b/Documentation/hwmon/nct7363.rst
new file mode 100644
index 000000000000..623cb4f0c8ce
--- /dev/null
+++ b/Documentation/hwmon/nct7363.rst
@@ -0,0 +1,35 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver nct7363
+=====================
+
+Supported chip:
+
+ * Nuvoton NCT7363Y
+
+ Prefix: nct7363
+
+ Addresses: I2C 0x20, 0x21, 0x22, 0x23
+
+Author: Ban Feng <kcfeng0@nuvoton.com>
+
+
+Description
+-----------
+
+The NCT7363Y is a fan controller which provides up to 16 independent
+FAN input monitors, and up to 16 independent PWM outputs with SMBus interface.
+
+
+Sysfs entries
+-------------
+
+Currently, the driver supports the following features:
+
+========== ==========================================
+fanX_input provide current fan rotation value in RPM
+fanX_alarm report fan low speed real status
+fanX_min get or set fan count threshold
+
+pwmX get or set PWM fan control value.
+========== ==========================================
diff --git a/Documentation/hwmon/pmbus-core.rst b/Documentation/hwmon/pmbus-core.rst
index 1eaf2b015837..686a00265bf7 100644
--- a/Documentation/hwmon/pmbus-core.rst
+++ b/Documentation/hwmon/pmbus-core.rst
@@ -308,6 +308,10 @@ currently provides a flags field with four bits used::
#define PMBUS_READ_STATUS_AFTER_FAILED_CHECK BIT(3)
+ #define PMBUS_NO_WRITE_PROTECT BIT(4)
+
+ #define PMBUS_USE_COEFFICIENTS_CMD BIT(5)
+
struct pmbus_platform_data {
u32 flags; /* Device specific flags */
@@ -358,3 +362,14 @@ This can be done by reading a known register. By setting this flag the
driver will try to read the STATUS register after each failed
register check. This read may fail, but it will put the chip into a
known state.
+
+PMBUS_NO_WRITE_PROTECT
+
+Some PMBus chips respond with invalid data when reading the WRITE_PROTECT
+register. For such chips, this flag should be set so that the PMBus core
+driver doesn't use the WRITE_PROTECT command to determine its behavior.
+
+PMBUS_USE_COEFFICIENTS_CMD
+
+When this flag is set the PMBus core driver will use the COEFFICIENTS
+register to initialize the coefficients for the direct mode format.
diff --git a/Documentation/hwmon/sch5627.rst b/Documentation/hwmon/sch5627.rst
index 8639dff234fc..5f521c6e90ab 100644
--- a/Documentation/hwmon/sch5627.rst
+++ b/Documentation/hwmon/sch5627.rst
@@ -39,7 +39,7 @@ Controlling fan speed
---------------------
The SCH5627 allows for partially controlling the fan speed. If a temperature
-channel excedes tempX_max, all fans are forced to maximum speed. The same is not
+channel exceeds tempX_max, all fans are forced to maximum speed. The same is not
true for tempX_crit, presumably some other measures to cool down the system are
take in this case.
In which way the value of fanX_min affects the fan speed is currently unknown.
diff --git a/Documentation/hwmon/sht4x.rst b/Documentation/hwmon/sht4x.rst
index daf21e763425..ba094ad0e281 100644
--- a/Documentation/hwmon/sht4x.rst
+++ b/Documentation/hwmon/sht4x.rst
@@ -42,4 +42,18 @@ humidity1_input Measured humidity in %H
update_interval The minimum interval for polling the sensor,
in milliseconds. Writable. Must be at least
2000.
+heater_power The requested heater power, in milliwatts.
+ Available values: 20, 110, 200 (default: 200).
+heater_time The requested operating time of the heater,
+ in milliseconds.
+ Available values: 100, 1000 (default 1000).
+heater_enable Enable the heater with the selected power
+ and for the selected time in order to remove
+ condensed water from the sensor surface. The
+ heater cannot be manually turned off once
+ enabled (it will automatically turn off
+ after completing its operation).
+
+ - 0: turned off (read-only value)
+ - 1: turn on
=============== ============================================
diff --git a/Documentation/hwmon/tmp108.rst b/Documentation/hwmon/tmp108.rst
index 6df7cf1b42f4..bc4941d98268 100644
--- a/Documentation/hwmon/tmp108.rst
+++ b/Documentation/hwmon/tmp108.rst
@@ -3,6 +3,14 @@ Kernel driver tmp108
Supported chips:
+ * NXP P3T1085
+
+ Prefix: 'p3t1085'
+
+ Addresses scanned: none
+
+ Datasheet: https://www.nxp.com/docs/en/data-sheet/P3T1085UK.pdf
+
* Texas Instruments TMP108
Prefix: 'tmp108'
diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst
index c840b597912c..47e8ac5b7099 100644
--- a/Documentation/i2c/busses/i2c-i801.rst
+++ b/Documentation/i2c/busses/i2c-i801.rst
@@ -49,6 +49,7 @@ Supported adapters:
* Intel Meteor Lake (SOC and PCH)
* Intel Birch Stream (SOC)
* Intel Arrow Lake (SOC)
+ * Intel Panther Lake (SOC)
Datasheets: Publicly available at the Intel website
diff --git a/Documentation/i2c/busses/i2c-piix4.rst b/Documentation/i2c/busses/i2c-piix4.rst
index 07fe6f6f4b18..94e20b18c59a 100644
--- a/Documentation/i2c/busses/i2c-piix4.rst
+++ b/Documentation/i2c/busses/i2c-piix4.rst
@@ -109,3 +109,66 @@ which can easily get corrupted due to a state machine bug. These are mostly
Thinkpad laptops, but desktop systems may also be affected. We have no list
of all affected systems, so the only safe solution was to prevent access to
the SMBus on all IBM systems (detected using DMI data.)
+
+
+Description in the ACPI code
+----------------------------
+
+Device driver for the PIIX4 chip creates a separate I2C bus for each of its
+ports::
+
+ $ i2cdetect -l
+ ...
+ i2c-7 unknown SMBus PIIX4 adapter port 0 at 0b00 N/A
+ i2c-8 unknown SMBus PIIX4 adapter port 2 at 0b00 N/A
+ i2c-9 unknown SMBus PIIX4 adapter port 1 at 0b20 N/A
+ ...
+
+Therefore if you want to access one of these busses in the ACPI code, port
+subdevices are needed to be declared inside the PIIX device::
+
+ Scope (\_SB_.PCI0.SMBS)
+ {
+ Name (_ADR, 0x00140000)
+
+ Device (SMB0) {
+ Name (_ADR, 0)
+ }
+ Device (SMB1) {
+ Name (_ADR, 1)
+ }
+ Device (SMB2) {
+ Name (_ADR, 2)
+ }
+ }
+
+If this is not the case for your UEFI firmware and you don't have access to the
+source code, you can use ACPI SSDT Overlays to provide the missing parts. Just
+keep in mind that in this case you would need to load your extra SSDT table
+before the piix4 driver starts, i.e. you should provide SSDT via initrd or EFI
+variable methods and not via configfs.
+
+As an example of usage here is the ACPI snippet code that would assign jc42
+driver to the 0x1C device on the I2C bus created by the PIIX port 0::
+
+ Device (JC42) {
+ Name (_HID, "PRP0001")
+ Name (_DDN, "JC42 Temperature sensor")
+ Name (_CRS, ResourceTemplate () {
+ I2cSerialBusV2 (
+ 0x001c,
+ ControllerInitiated,
+ 100000,
+ AddressingMode7Bit,
+ "\\_SB.PCI0.SMBS.SMB0",
+ 0
+ )
+ })
+
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () { "compatible", Package() { "jedec,jc-42.4-temp" } },
+ }
+ })
+ }
diff --git a/Documentation/i2c/writing-clients.rst b/Documentation/i2c/writing-clients.rst
index 0b8439ea954c..121e618e72ec 100644
--- a/Documentation/i2c/writing-clients.rst
+++ b/Documentation/i2c/writing-clients.rst
@@ -31,12 +31,11 @@ driver model device node, and its I2C address.
::
- static struct i2c_device_id foo_idtable[] = {
+ static const struct i2c_device_id foo_idtable[] = {
{ "foo", my_id_for_foo },
{ "bar", my_id_for_bar },
{ }
};
-
MODULE_DEVICE_TABLE(i2c, foo_idtable);
static struct i2c_driver foo_driver = {
diff --git a/Documentation/iio/ad7380.rst b/Documentation/iio/ad7380.rst
index 6f70b49b9ef2..c46127700e14 100644
--- a/Documentation/iio/ad7380.rst
+++ b/Documentation/iio/ad7380.rst
@@ -27,6 +27,8 @@ The following chips are supported by this driver:
* `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
* `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_
+* `ADAQ4370-4 <https://www.analog.com/en/products/adaq4370-4.html>`_
+* `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_
Supported features
@@ -47,6 +49,12 @@ ad7380-4
ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be
declared in the device tree as ``refin-supply``.
+ADAQ devices
+~~~~~~~~~~~~
+
+adaq4370-4 and adaq4380-4 don't have an external reference, but use a 3.3V
+internal reference derived from one of its supplies (``refin-supply``)
+
All other devices from ad738x family
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -121,6 +129,14 @@ Example for AD7386/7/8 (2 channels parts):
When enabling sequencer mode, the effective sampling rate is divided by two.
+Gain (ADAQ devices only)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+ADAQ devices have a pin selectable gain in front of each ADC. The appropriate
+gain is selectable from device tree using the ``adi,gain-milli`` property.
+Refer to the typical connection diagrams section of the datasheet for pin
+wiring.
+
Unimplemented features
----------------------
diff --git a/Documentation/iio/ad7606.rst b/Documentation/iio/ad7606.rst
new file mode 100644
index 000000000000..930199e03c67
--- /dev/null
+++ b/Documentation/iio/ad7606.rst
@@ -0,0 +1,144 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+=============
+AD7606 driver
+=============
+
+ADC driver for Analog Devices Inc. AD7606 and similar devices. The module name
+is ``ad7606``.
+
+Supported devices
+=================
+
+The following chips are supported by this driver:
+
+* `AD7605 <https://www.analog.com/en/products/ad7605.html>`_
+* `AD7606 <https://www.analog.com/en/products/ad7606.html>`_
+* `AD7606B <https://www.analog.com/en/products/ad7606b.html>`_
+* `AD7616 <https://www.analog.com/en/products/ad7616.html>`_
+
+Supported features
+==================
+
+SPI wiring modes
+----------------
+
+These ADCs can output data on several SDO lines (1/2/4/8). The driver
+currently supports only 1 SDO line.
+
+Parallel wiring mode
+--------------------
+
+There is also a parallel interface, with 16 lines (that can be reduced to 8 in
+byte mode). The parallel interface is selected by declaring the device as
+platform in the device tree (with no io-backends node defined, see below).
+
+IIO-backend mode
+----------------
+
+This mode allows to reach the best sample rates, but it requires an external
+hardware (eg HDL or APU) to handle the low level communication.
+The backend mode is enabled when through the definition of the "io-backends"
+property in the device tree.
+
+The reference configuration for the current implementation of IIO-backend mode
+is the HDL reference provided by ADI:
+https://wiki.analog.com/resources/eval/user-guides/ad7606x-fmc/hdl
+
+This implementation embeds an IIO-backend compatible IP (adi-axi-adc) and a PWM
+connected to the conversion trigger pin.
+
+.. code-block::
+
+ +---+ +----------------------------
+ | | +-------+ |AD76xx
+ | A | controls | | |
+ | D |-------------->| PWM |-------------->| cnvst
+ | 7 | | | |
+ | 6 | +-------+ |
+ | 0 | controls +-----------+-----------+ |
+ | 6 |---------->| | |<--| frstdata
+ | | | Backend | Backend |<--| busy
+ | D | | Driver | | |
+ | R | | | |-->| clk
+ | I | requests |+---------+| DMA | |
+ | V |----------->| Buffer ||<---- |<=>| DATA
+ | E | |+---------+| | |
+ | R | +-----------+-----------+ |
+ | |-------------------------------------->| reset/configuration gpios
+ +---+ +-----------------------------
+
+
+Software and hardware modes
+---------------------------
+
+While all the AD7606/AD7616 series parts can be configured using GPIOs, some of
+them can be configured using register.
+
+The chips that support software mode have more values available for configuring
+the device, as well as more settings, and allow to control the range and
+calibration per channel.
+
+The following settings are available per channel in software mode:
+ - Scale
+
+Also, there is a broader choice of oversampling ratios in software mode.
+
+Conversion triggering
+---------------------
+
+The conversion can be triggered by two distinct ways:
+
+ - A GPIO is connected to the conversion trigger pin, and this GPIO is controlled
+ by the driver directly. In this configuration, the driver sets back the
+ conversion trigger pin to high as soon as it has read all the conversions.
+
+ - An external source is connected to the conversion trigger pin. In the
+ current implementation, it must be a PWM. In this configuration, the driver
+ does not control directly the conversion trigger pin. Instead, it can
+ control the PWM's frequency. This trigger is enabled only for iio-backend.
+
+Reference voltage
+-----------------
+
+2 possible reference voltage sources are supported:
+
+ - Internal reference (2.5V)
+ - External reference (2.5V)
+
+The source is determined by the device tree. If ``refin-supply`` is present,
+then the external reference is used, otherwise the internal reference is used.
+
+Oversampling
+------------
+
+This family supports oversampling to improve SNR.
+In software mode, the following ratios are available:
+1 (oversampling disabled)/2/4/8/16/32/64/128/256.
+
+Unimplemented features
+----------------------
+
+- 2/4/8 SDO lines
+- CRC indication
+- Calibration
+
+Device buffers
+==============
+
+IIO triggered buffer
+--------------------
+
+This driver supports IIO triggered buffers, with a "built in" trigger, i.e the
+trigger is allocated and linked by the driver, and a new conversion is triggered
+as soon as the samples are transferred, and a timestamp channel is added to make
+up for the potential jitter induced by the delays in the interrupt handling.
+
+IIO backend buffer
+------------------
+
+When IIO backend is used, the trigger is not needed, and the sample rate is
+considered as stable. There is no timestamp channel. The communication is
+delegated to an external logic, called a backend, and the backend's driver
+handles the buffer. When this mode is enabled, the driver cannot control the
+conversion pin, because the busy pin is bound to the backend.
diff --git a/Documentation/iio/ad7625.rst b/Documentation/iio/ad7625.rst
new file mode 100644
index 000000000000..61761e3b75c3
--- /dev/null
+++ b/Documentation/iio/ad7625.rst
@@ -0,0 +1,91 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+====================
+AD7625 driver
+====================
+
+ADC driver for Analog Devices Inc. AD7625, AD7626, AD7960, and AD7961
+devices. The module name is ``ad7625``.
+
+Supported devices
+=================
+
+The following chips are supported by this driver:
+
+* `AD7625 <https://www.analog.com/AD7625>`_
+* `AD7626 <https://www.analog.com/AD7626>`_
+* `AD7960 <https://www.analog.com/AD7960>`_
+* `AD7961 <https://www.analog.com/AD7961>`_
+
+The driver requires use of the Pulsar LVDS HDL project:
+
+* `Pulsar LVDS HDL <http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html>`_
+
+To trigger conversions and enable subsequent data transfer, the devices
+require coupled PWM signals with a phase offset.
+
+Supported features
+==================
+
+Conversion control modes
+------------------------
+
+The driver currently supports one of two possible LVDS conversion control methods.
+
+Echoed-Clock interface mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ +----------------+
+ +xxxxxxxxxxxxxxxxxxxxxxxxxx| CNV |
+ X | |
+ v | HOST |
+ +----------------------------+ | |
+ | CNV+/CNV- DCO+/DCO- |xxxxxxx>| CLK_IN |
+ | | | |
+ | | | |
+ | AD7625 D+/D- |xxxxxxx>| DATA_IN |
+ | | | |
+ | | | |
+ | CLK+/CLK- |<xxxxxxx| CLK & CLK_GATE |
+ +----------------------------+ | |
+ +----------------+
+
+Reference voltage
+-----------------
+
+Three possible reference voltage sources are supported:
+
+- Internal reference (only available on AD7625 and AD7626)
+- External reference and internal buffer
+- External reference
+
+The source is determined by the device tree. If ``ref-supply`` is present, then
+the external reference is used. If ``refin-supply`` is present, then the internal
+buffer is used. If neither is present, then the internal reference is used.
+
+Unimplemented features
+----------------------
+
+- Self-clocked mode
+
+
+Device attributes
+=================
+
+The AD762x is a fully-differential ADC and has the following attributes:
+
++---------------------------------------+--------------------------------------------------------------+
+| Attribute | Description |
++=======================================+==============================================================+
+| ``scale`` | Scale factor to convert raw value from buffered reads to mV. |
++---------------------------------------+--------------------------------------------------------------+
+
+
+Device buffers
+==============
+
+This driver supports IIO triggered buffers.
+
+See :doc:`iio_devbuf` for more information.
diff --git a/Documentation/iio/bno055.rst b/Documentation/iio/bno055.rst
index 9a489a79d8f5..f1111ff3fe2e 100644
--- a/Documentation/iio/bno055.rst
+++ b/Documentation/iio/bno055.rst
@@ -22,7 +22,7 @@ This driver supports also IIO buffers.
The IMU continuously performs an autocalibration procedure if (and only if)
operating in fusion mode. The magnetometer autocalibration can however be
-disabled writing 0 in the sysfs in_magn_calibration_fast_enable attribute.
+disabled by writing 0 in the sysfs in_magn_calibration_fast_enable attribute.
The driver provides access to autocalibration flags (i.e. you can known if
the IMU has successfully autocalibrated) and to the calibration data blob.
diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst
index dfcf9618568a..074dbbf7ba0a 100644
--- a/Documentation/iio/index.rst
+++ b/Documentation/iio/index.rst
@@ -21,6 +21,8 @@ Industrial I/O Kernel Drivers
ad4000
ad4695
ad7380
+ ad7606
+ ad7625
ad7944
adis16475
adis16480
diff --git a/Documentation/input/input.rst b/Documentation/input/input.rst
index 2c67fa904adc..d9a6de87d02d 100644
--- a/Documentation/input/input.rst
+++ b/Documentation/input/input.rst
@@ -264,7 +264,7 @@ events on a read. Their layout is::
struct timeval time;
unsigned short type;
unsigned short code;
- unsigned int value;
+ int value;
};
``time`` is the timestamp, it returns the time at which the event happened.
diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst
index 1796b3eba37b..17c9f920f03d 100644
--- a/Documentation/kbuild/kbuild.rst
+++ b/Documentation/kbuild/kbuild.rst
@@ -137,12 +137,18 @@ Specify the output directory when building the kernel.
This variable can also be used to point to the kernel output directory when
building external modules against a pre-built kernel in a separate build
directory. Please note that this does NOT specify the output directory for the
-external modules themselves.
+external modules themselves. (Use KBUILD_EXTMOD_OUTPUT for that purpose.)
The output directory can also be specified using "O=...".
Setting "O=..." takes precedence over KBUILD_OUTPUT.
+KBUILD_EXTMOD_OUTPUT
+--------------------
+Specify the output directory for external modules.
+
+Setting "MO=..." takes precedence over KBUILD_EXTMOD_OUTPUT.
+
KBUILD_EXTRA_WARN
-----------------
Specify the extra build checks. The same value can be assigned by passing
diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
index 43037be96a16..2619fdf56e68 100644
--- a/Documentation/kbuild/kconfig-language.rst
+++ b/Documentation/kbuild/kconfig-language.rst
@@ -412,8 +412,8 @@ choices::
<choice block>
"endchoice"
-This defines a choice group and accepts any of the above attributes as
-options.
+This defines a choice group and accepts "prompt", "default", "depends on", and
+"help" attributes as options.
A choice only allows a single config entry to be selected.
diff --git a/Documentation/kbuild/llvm.rst b/Documentation/kbuild/llvm.rst
index 6dc66b4f31a7..bc8a283bc44b 100644
--- a/Documentation/kbuild/llvm.rst
+++ b/Documentation/kbuild/llvm.rst
@@ -179,6 +179,9 @@ yet. Bug reports are always welcome at the issue tracker below!
* - s390
- Maintained
- ``LLVM=1`` (LLVM >= 18.1.0), ``CC=clang`` (LLVM < 18.1.0)
+ * - sparc (sparc64 only)
+ - Maintained
+ - ``CC=clang LLVM_IAS=0`` (LLVM >= 20)
* - um (User Mode)
- Maintained
- ``LLVM=1``
diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
index 7964e0c245ae..d36519f194dc 100644
--- a/Documentation/kbuild/makefiles.rst
+++ b/Documentation/kbuild/makefiles.rst
@@ -449,6 +449,20 @@ $(obj)
to prerequisites are referenced with $(src) (because they are not
generated files).
+$(srcroot)
+ $(srcroot) refers to the root of the source you are building, which can be
+ either the kernel source or the external modules source, depending on whether
+ KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
+ if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
+
+$(srctree)
+ $(srctree) refers to the root of the kernel source tree. When building the
+ kernel, this is the same as $(srcroot).
+
+$(objtree)
+ $(objtree) refers to the root of the kernel object tree. It is ``.`` when
+ building the kernel, but it is different when building external modules.
+
$(kecho)
echoing information to user in a rule is often a good practice
but when execution ``make -s`` one does not expect to see any output
diff --git a/Documentation/kbuild/modules.rst b/Documentation/kbuild/modules.rst
index cd5a54d91e6d..101de236cd0c 100644
--- a/Documentation/kbuild/modules.rst
+++ b/Documentation/kbuild/modules.rst
@@ -59,6 +59,12 @@ Command Syntax
$ make -C /lib/modules/`uname -r`/build M=$PWD modules_install
+ Starting from Linux 6.13, you can use the -f option instead of -C. This
+ will avoid unnecessary change of the working directory. The external
+ module will be output to the directory where you invoke make.
+
+ $ make -f /lib/modules/`uname -r`/build/Makefile M=$PWD
+
Options
-------
@@ -66,7 +72,10 @@ Options
of the kernel output directory if the kernel was built in a separate
build directory.)
- make -C $KDIR M=$PWD
+ You can optionally pass MO= option if you want to build the modules in
+ a separate directory.
+
+ make -C $KDIR M=$PWD [MO=$BUILD_DIR]
-C $KDIR
The directory that contains the kernel and relevant build
@@ -80,6 +89,9 @@ Options
directory where the external module (kbuild file) is
located.
+ MO=$BUILD_DIR
+ Specifies a separate output directory for the external module.
+
Targets
-------
@@ -215,6 +227,21 @@ Separate Kbuild File and Makefile
consisting of several hundred lines, and here it really pays
off to separate the kbuild part from the rest.
+ Linux 6.13 and later support another way. The external module Makefile
+ can include the kernel Makefile directly, rather than invoking sub Make.
+
+ Example 3::
+
+ --> filename: Kbuild
+ obj-m := 8123.o
+ 8123-y := 8123_if.o 8123_pci.o
+
+ --> filename: Makefile
+ KDIR ?= /lib/modules/$(shell uname -r)/build
+ export KBUILD_EXTMOD := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
+ include $(KDIR)/Makefile
+
+
Building Multiple Modules
-------------------------
diff --git a/Documentation/kernel-hacking/false-sharing.rst b/Documentation/kernel-hacking/false-sharing.rst
index 122b0e124656..eb0596734e55 100644
--- a/Documentation/kernel-hacking/false-sharing.rst
+++ b/Documentation/kernel-hacking/false-sharing.rst
@@ -196,9 +196,9 @@ the hotspot switches to a new place.
Miscellaneous
=============
-One open issue is that kernel has an optional data structure
+One open issue is that the kernel has an optional data structure
randomization mechanism, which also randomizes the situation of cache
-line sharing of data members.
+line sharing among data members.
.. [1] https://en.wikipedia.org/wiki/False_sharing
diff --git a/Documentation/kernel-hacking/hacking.rst b/Documentation/kernel-hacking/hacking.rst
index 1717348a4404..0042776a9e17 100644
--- a/Documentation/kernel-hacking/hacking.rst
+++ b/Documentation/kernel-hacking/hacking.rst
@@ -587,7 +587,7 @@ Defined in ``include/linux/export.h``
Similar to :c:func:`EXPORT_SYMBOL()` except that the symbols
exported by :c:func:`EXPORT_SYMBOL_GPL()` can only be seen by
-modules with a :c:func:`MODULE_LICENSE()` that specifies a GPL
+modules with a :c:func:`MODULE_LICENSE()` that specifies a GPLv2
compatible license. It implies that the function is considered an
internal implementation issue, and not really an interface. Some
maintainers and developers may however require EXPORT_SYMBOL_GPL()
diff --git a/Documentation/locking/percpu-rw-semaphore.rst b/Documentation/locking/percpu-rw-semaphore.rst
index 247de6410855..a105bf2dd812 100644
--- a/Documentation/locking/percpu-rw-semaphore.rst
+++ b/Documentation/locking/percpu-rw-semaphore.rst
@@ -16,8 +16,8 @@ writing is very expensive, it calls synchronize_rcu() that can take
hundreds of milliseconds.
The lock is declared with "struct percpu_rw_semaphore" type.
-The lock is initialized percpu_init_rwsem, it returns 0 on success and
--ENOMEM on allocation failure.
+The lock is initialized with percpu_init_rwsem, it returns 0 on success
+and -ENOMEM on allocation failure.
The lock must be freed with percpu_free_rwsem to avoid memory leak.
The lock is locked for read with percpu_down_read, percpu_up_read and
diff --git a/Documentation/locking/seqlock.rst b/Documentation/locking/seqlock.rst
index bfda1a5fecad..ec6411d02ac8 100644
--- a/Documentation/locking/seqlock.rst
+++ b/Documentation/locking/seqlock.rst
@@ -153,7 +153,7 @@ Use seqcount_latch_t when the write side sections cannot be protected
from interruption by readers. This is typically the case when the read
side can be invoked from NMI handlers.
-Check `raw_write_seqcount_latch()` for more information.
+Check `write_seqcount_latch()` for more information.
.. _seqlock_t:
diff --git a/Documentation/maintainer/pull-requests.rst b/Documentation/maintainer/pull-requests.rst
index 00b200facf67..0d63d9d7e347 100644
--- a/Documentation/maintainer/pull-requests.rst
+++ b/Documentation/maintainer/pull-requests.rst
@@ -50,7 +50,7 @@ so outline what is contained here, why it should be merged, and what, if
any, testing has been done. All of this information will end up in the tag
itself, and then in the merge commit that the maintainer makes if/when they
merge the pull request. So write it up well, as it will be in the kernel
-tree for forever.
+tree forever.
As said by Linus::
diff --git a/Documentation/mm/allocation-profiling.rst b/Documentation/mm/allocation-profiling.rst
index ffd6655b7be2..316311240e6a 100644
--- a/Documentation/mm/allocation-profiling.rst
+++ b/Documentation/mm/allocation-profiling.rst
@@ -18,12 +18,17 @@ kconfig options:
missing annotation
Boot parameter:
- sysctl.vm.mem_profiling=0|1|never
+ sysctl.vm.mem_profiling={0|1|never}[,compressed]
When set to "never", memory allocation profiling overhead is minimized and it
cannot be enabled at runtime (sysctl becomes read-only).
When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=y, default value is "1".
When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=n, default value is "never".
+ "compressed" optional parameter will try to store page tag references in a
+ compact format, avoiding page extensions. This results in improved performance
+ and memory consumption, however it might fail depending on system configuration.
+ If compression fails, a warning is issued and memory allocation profiling gets
+ disabled.
sysctl:
/proc/sys/vm/mem_profiling
diff --git a/Documentation/mm/damon/index.rst b/Documentation/mm/damon/index.rst
index dafd6d028924..5a3359704cce 100644
--- a/Documentation/mm/damon/index.rst
+++ b/Documentation/mm/damon/index.rst
@@ -37,3 +37,9 @@ with no code but simple configurations.
To utilize and control DAMON from the user-space, please refer to the
administration :doc:`guide </admin-guide/mm/damon/index>`.
+
+If you prefer academic papers for reading and citations, please use the papers
+from `HPDC'22 <https://dl.acm.org/doi/abs/10.1145/3502181.3531466>`_ and
+`Middleware19 Industry <https://dl.acm.org/doi/abs/10.1145/3366626.3368125>`_ .
+Note that those cover DAMON implementations in Linux v5.16 and v5.15,
+respectively.
diff --git a/Documentation/mm/page_tables.rst b/Documentation/mm/page_tables.rst
index be47b192a596..e7c69cc32493 100644
--- a/Documentation/mm/page_tables.rst
+++ b/Documentation/mm/page_tables.rst
@@ -29,7 +29,7 @@ address.
With a page granularity of 4KB and a address range of 32 bits, pfn 0 is at
address 0x00000000, pfn 1 is at address 0x00001000, pfn 2 is at 0x00002000
and so on until we reach pfn 0xfffff at 0xfffff000. With 16KB pages pfs are
-at 0x00004000, 0x00008000 ... 0xffffc000 and pfn goes from 0 to 0x3fffff.
+at 0x00004000, 0x00008000 ... 0xffffc000 and pfn goes from 0 to 0x3ffff.
As you can see, with 4KB pages the page base address uses bits 12-31 of the
address, and this is why `PAGE_SHIFT` in this case is defined as 12 and
diff --git a/Documentation/mm/slub.rst b/Documentation/mm/slub.rst
index 60d350d08362..84ca1dc94e5e 100644
--- a/Documentation/mm/slub.rst
+++ b/Documentation/mm/slub.rst
@@ -175,6 +175,15 @@ can be influenced by kernel parameters:
``slab_max_order`` to 0, what cause minimum possible order of
slabs allocation.
+``slab_strict_numa``
+ Enables the application of memory policies on each
+ allocation. This results in more accurate placement of
+ objects which may result in the reduction of accesses
+ to remote nodes. The default is to only apply memory
+ policies at the folio level when a new folio is acquired
+ or a folio is retrieved from the lists. Enabling this
+ option reduces the fastpath performance of the slab allocator.
+
SLUB Debug output
=================
diff --git a/Documentation/mm/split_page_table_lock.rst b/Documentation/mm/split_page_table_lock.rst
index e4f6972eb6c0..581446d4a4eb 100644
--- a/Documentation/mm/split_page_table_lock.rst
+++ b/Documentation/mm/split_page_table_lock.rst
@@ -16,9 +16,13 @@ There are helpers to lock/unlock a table and other accessor functions:
- pte_offset_map_lock()
maps PTE and takes PTE table lock, returns pointer to PTE with
pointer to its PTE table lock, or returns NULL if no PTE table;
- - pte_offset_map_nolock()
+ - pte_offset_map_ro_nolock()
maps PTE, returns pointer to PTE with pointer to its PTE table
lock (not taken), or returns NULL if no PTE table;
+ - pte_offset_map_rw_nolock()
+ maps PTE, returns pointer to PTE with pointer to its PTE table
+ lock (not taken) and the value of its pmd entry, or returns NULL
+ if no PTE table;
- pte_offset_map()
maps PTE, returns pointer to PTE, or returns NULL if no PTE table;
- pte_unmap()
diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
index f2894ca35de8..8feefeae5376 100644
--- a/Documentation/netlink/specs/dpll.yaml
+++ b/Documentation/netlink/specs/dpll.yaml
@@ -86,6 +86,36 @@ definitions:
locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT.
render-max: true
-
+ type: enum
+ name: clock-quality-level
+ doc: |
+ level of quality of a clock device. This mainly applies when
+ the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER.
+ The current list is defined according to the table 11-7 contained
+ in ITU-T G.8264/Y.1364 document. One may extend this list freely
+ by other ITU-T defined clock qualities, or different ones defined
+ by another standardization body (for those, please use
+ different prefix).
+ entries:
+ -
+ name: itu-opt1-prc
+ value: 1
+ -
+ name: itu-opt1-ssu-a
+ -
+ name: itu-opt1-ssu-b
+ -
+ name: itu-opt1-eec1
+ -
+ name: itu-opt1-prtc
+ -
+ name: itu-opt1-eprtc
+ -
+ name: itu-opt1-eeec
+ -
+ name: itu-opt1-eprc
+ render-max: true
+ -
type: const
name: temp-divider
value: 1000
@@ -252,6 +282,17 @@ attribute-sets:
name: lock-status-error
type: u32
enum: lock-status-error
+ -
+ name: clock-quality-level
+ type: u32
+ enum: clock-quality-level
+ multi-attr: true
+ doc: |
+ Level of quality of a clock device. This mainly applies when
+ the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. This could
+ be put to message multiple times to indicate possible parallel
+ quality levels (e.g. one specified by ITU option 1 and another
+ one specified by option 2).
-
name: pin
enum-name: dpll_a_pin
diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml
index 6a050d755b9c..93369f0eb816 100644
--- a/Documentation/netlink/specs/ethtool.yaml
+++ b/Documentation/netlink/specs/ethtool.yaml
@@ -96,7 +96,12 @@ attribute-sets:
name: bits
type: nest
nested-attributes: bitset-bits
-
+ -
+ name: value
+ type: binary
+ -
+ name: mask
+ type: binary
-
name: string
attributes:
@@ -1951,3 +1956,7 @@ operations:
- upstream-sfp-name
- downstream-sfp-name
dump: *phy-get-op
+ -
+ name: phy-ntf
+ doc: Notification for change in PHY devices.
+ notify: phy-get
diff --git a/Documentation/netlink/specs/mptcp_pm.yaml b/Documentation/netlink/specs/mptcp_pm.yaml
index 30d8342cacc8..dc190bf838fe 100644
--- a/Documentation/netlink/specs/mptcp_pm.yaml
+++ b/Documentation/netlink/specs/mptcp_pm.yaml
@@ -293,7 +293,6 @@ operations:
doc: Get endpoint information
attribute-set: attr
dont-validate: [ strict ]
- flags: [ uns-admin-perm ]
do: &get-addr-attrs
request:
attributes:
diff --git a/Documentation/netlink/specs/net_shaper.yaml b/Documentation/netlink/specs/net_shaper.yaml
new file mode 100644
index 000000000000..8ebad0d02904
--- /dev/null
+++ b/Documentation/netlink/specs/net_shaper.yaml
@@ -0,0 +1,362 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+name: net-shaper
+
+doc: |
+ Networking HW rate limiting configuration.
+
+ This API allows configuring HW shapers available on the network
+ devices at different levels (queues, network device) and allows
+ arbitrary manipulation of the scheduling tree of the involved
+ shapers.
+
+ Each @shaper is identified within the given device, by a @handle,
+ comprising both a @scope and an @id.
+
+ Depending on the @scope value, the shapers are attached to specific
+ HW objects (queues, devices) or, for @node scope, represent a
+ scheduling group, that can be placed in an arbitrary location of
+ the scheduling tree.
+
+ Shapers can be created with two different operations: the @set
+ operation, to create and update a single "attached" shaper, and
+ the @group operation, to create and update a scheduling
+ group. Only the @group operation can create @node scope shapers.
+
+ Existing shapers can be deleted/reset via the @delete operation.
+
+ The user can query the running configuration via the @get operation.
+
+ Different devices can provide different feature sets, e.g. with no
+ support for complex scheduling hierarchy, or for some shaping
+ parameters. The user can introspect the HW capabilities via the
+ @cap-get operation.
+
+definitions:
+ -
+ type: enum
+ name: scope
+ doc: Defines the shaper @id interpretation.
+ render-max: true
+ entries:
+ - name: unspec
+ doc: The scope is not specified.
+ -
+ name: netdev
+ doc: The main shaper for the given network device.
+ -
+ name: queue
+ doc: |
+ The shaper is attached to the given device queue,
+ the @id represents the queue number.
+ -
+ name: node
+ doc: |
+ The shaper allows grouping of queues or other
+ node shapers; can be nested in either @netdev
+ shapers or other @node shapers, allowing placement
+ in any location of the scheduling tree, except
+ leaves and root.
+ -
+ type: enum
+ name: metric
+ doc: Different metric supported by the shaper.
+ entries:
+ -
+ name: bps
+ doc: Shaper operates on a bits per second basis.
+ -
+ name: pps
+ doc: Shaper operates on a packets per second basis.
+
+attribute-sets:
+ -
+ name: net-shaper
+ attributes:
+ -
+ name: handle
+ type: nest
+ nested-attributes: handle
+ doc: Unique identifier for the given shaper inside the owning device.
+ -
+ name: metric
+ type: u32
+ enum: metric
+ doc: Metric used by the given shaper for bw-min, bw-max and burst.
+ -
+ name: bw-min
+ type: uint
+ doc: Guaranteed bandwidth for the given shaper.
+ -
+ name: bw-max
+ type: uint
+ doc: Maximum bandwidth for the given shaper or 0 when unlimited.
+ -
+ name: burst
+ type: uint
+ doc: |
+ Maximum burst-size for shaping. Should not be interpreted
+ as a quantum.
+ -
+ name: priority
+ type: u32
+ doc: |
+ Scheduling priority for the given shaper. The priority
+ scheduling is applied to sibling shapers.
+ -
+ name: weight
+ type: u32
+ doc: |
+ Relative weight for round robin scheduling of the
+ given shaper.
+ The scheduling is applied to all sibling shapers
+ with the same priority.
+ -
+ name: ifindex
+ type: u32
+ doc: Interface index owning the specified shaper.
+ -
+ name: parent
+ type: nest
+ nested-attributes: handle
+ doc: |
+ Identifier for the parent of the affected shaper.
+ Only needed for @group operation.
+ -
+ name: leaves
+ type: nest
+ multi-attr: true
+ nested-attributes: leaf-info
+ doc: |
+ Describes a set of leaves shapers for a @group operation.
+ -
+ name: handle
+ attributes:
+ -
+ name: scope
+ type: u32
+ enum: scope
+ doc: Defines the shaper @id interpretation.
+ -
+ name: id
+ type: u32
+ doc: |
+ Numeric identifier of a shaper. The id semantic depends on
+ the scope. For @queue scope it's the queue id and for @node
+ scope it's the node identifier.
+ -
+ name: leaf-info
+ subset-of: net-shaper
+ attributes:
+ -
+ name: handle
+ -
+ name: priority
+ -
+ name: weight
+ -
+ name: caps
+ attributes:
+ -
+ name: ifindex
+ type: u32
+ doc: Interface index queried for shapers capabilities.
+ -
+ name: scope
+ type: u32
+ enum: scope
+ doc: The scope to which the queried capabilities apply.
+ -
+ name: support-metric-bps
+ type: flag
+ doc: The device accepts 'bps' metric for bw-min, bw-max and burst.
+ -
+ name: support-metric-pps
+ type: flag
+ doc: The device accepts 'pps' metric for bw-min, bw-max and burst.
+ -
+ name: support-nesting
+ type: flag
+ doc: |
+ The device supports nesting shaper belonging to this scope
+ below 'node' scoped shapers. Only 'queue' and 'node'
+ scope can have flag 'support-nesting'.
+ -
+ name: support-bw-min
+ type: flag
+ doc: The device supports a minimum guaranteed B/W.
+ -
+ name: support-bw-max
+ type: flag
+ doc: The device supports maximum B/W shaping.
+ -
+ name: support-burst
+ type: flag
+ doc: The device supports a maximum burst size.
+ -
+ name: support-priority
+ type: flag
+ doc: The device supports priority scheduling.
+ -
+ name: support-weight
+ type: flag
+ doc: The device supports weighted round robin scheduling.
+
+operations:
+ list:
+ -
+ name: get
+ doc: |
+ Get information about a shaper for a given device.
+ attribute-set: net-shaper
+
+ do:
+ pre: net-shaper-nl-pre-doit
+ post: net-shaper-nl-post-doit
+ request:
+ attributes: &ns-binding
+ - ifindex
+ - handle
+ reply:
+ attributes: &ns-attrs
+ - ifindex
+ - parent
+ - handle
+ - metric
+ - bw-min
+ - bw-max
+ - burst
+ - priority
+ - weight
+
+ dump:
+ pre: net-shaper-nl-pre-dumpit
+ post: net-shaper-nl-post-dumpit
+ request:
+ attributes:
+ - ifindex
+ reply:
+ attributes: *ns-attrs
+ -
+ name: set
+ doc: |
+ Create or update the specified shaper.
+ The set operation can't be used to create a @node scope shaper,
+ use the @group operation instead.
+ attribute-set: net-shaper
+ flags: [ admin-perm ]
+
+ do:
+ pre: net-shaper-nl-pre-doit
+ post: net-shaper-nl-post-doit
+ request:
+ attributes:
+ - ifindex
+ - handle
+ - metric
+ - bw-min
+ - bw-max
+ - burst
+ - priority
+ - weight
+
+ -
+ name: delete
+ doc: |
+ Clear (remove) the specified shaper. When deleting
+ a @node shaper, reattach all the node's leaves to the
+ deleted node's parent.
+ If, after the removal, the parent shaper has no more
+ leaves and the parent shaper scope is @node, the parent
+ node is deleted, recursively.
+ When deleting a @queue shaper or a @netdev shaper,
+ the shaper disappears from the hierarchy, but the
+ queue/device can still send traffic: it has an implicit
+ node with infinite bandwidth. The queue's implicit node
+ feeds an implicit RR node at the root of the hierarchy.
+ attribute-set: net-shaper
+ flags: [ admin-perm ]
+
+ do:
+ pre: net-shaper-nl-pre-doit
+ post: net-shaper-nl-post-doit
+ request:
+ attributes: *ns-binding
+
+ -
+ name: group
+ doc: |
+ Create or update a scheduling group, attaching the specified
+ @leaves shapers under the specified node identified by @handle.
+ The @leaves shapers scope must be @queue and the node shaper
+ scope must be either @node or @netdev.
+ When the node shaper has @node scope, if the @handle @id is not
+ specified, a new shaper of such scope is created, otherwise the
+ specified node must already exist.
+ When updating an existing node shaper, the specified @leaves are
+ added to the existing node; such node will also retain any preexisting
+ leave.
+ The @parent handle for a new node shaper defaults to the parent
+ of all the leaves, provided all the leaves share the same parent.
+ Otherwise @parent handle must be specified.
+ The user can optionally provide shaping attributes for the node
+ shaper.
+ The operation is atomic, on failure no change is applied to
+ the device shaping configuration, otherwise the @node shaper
+ full identifier, comprising @binding and @handle, is provided
+ as the reply.
+ attribute-set: net-shaper
+ flags: [ admin-perm ]
+
+ do:
+ pre: net-shaper-nl-pre-doit
+ post: net-shaper-nl-post-doit
+ request:
+ attributes:
+ - ifindex
+ - parent
+ - handle
+ - metric
+ - bw-min
+ - bw-max
+ - burst
+ - priority
+ - weight
+ - leaves
+ reply:
+ attributes: *ns-binding
+
+ -
+ name: cap-get
+ doc: |
+ Get the shaper capabilities supported by the given device
+ for the specified scope.
+ attribute-set: caps
+
+ do:
+ pre: net-shaper-nl-cap-pre-doit
+ post: net-shaper-nl-cap-post-doit
+ request:
+ attributes:
+ - ifindex
+ - scope
+ reply:
+ attributes: &cap-attrs
+ - ifindex
+ - scope
+ - support-metric-bps
+ - support-metric-pps
+ - support-nesting
+ - support-bw-min
+ - support-bw-max
+ - support-burst
+ - support-priority
+ - support-weight
+
+ dump:
+ pre: net-shaper-nl-cap-pre-dumpit
+ post: net-shaper-nl-cap-post-dumpit
+ request:
+ attributes:
+ - ifindex
+ reply:
+ attributes: *cap-attrs
diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index 08412c279297..cbb544bd6c84 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -248,6 +248,26 @@ attribute-sets:
threaded mode. If NAPI is not in threaded mode (i.e. uses normal
softirq context), the attribute will be absent.
type: u32
+ -
+ name: defer-hard-irqs
+ doc: The number of consecutive empty polls before IRQ deferral ends
+ and hardware IRQs are re-enabled.
+ type: u32
+ checks:
+ max: s32-max
+ -
+ name: gro-flush-timeout
+ doc: The timeout, in nanoseconds, of when to trigger the NAPI watchdog
+ timer which schedules NAPI processing. Additionally, a non-zero
+ value will also prevent GRO from flushing recent super-frames at
+ the end of a NAPI cycle. This may add receive latency in exchange
+ for reducing the number of frames processed by the network stack.
+ type: uint
+ -
+ name: irq-suspend-timeout
+ doc: The timeout, in nanoseconds, of how long to suspend irq
+ processing, if event polling finds events
+ type: uint
-
name: queue
attributes:
@@ -636,6 +656,9 @@ operations:
- ifindex
- irq
- pid
+ - defer-hard-irqs
+ - gro-flush-timeout
+ - irq-suspend-timeout
dump:
request:
attributes:
@@ -676,6 +699,18 @@ operations:
reply:
attributes:
- id
+ -
+ name: napi-set
+ doc: Set configurable NAPI instance settings.
+ attribute-set: napi
+ flags: [ admin-perm ]
+ do:
+ request:
+ attributes:
+ - id
+ - defer-hard-irqs
+ - gro-flush-timeout
+ - irq-suspend-timeout
kernel-family:
headers: [ "linux/list.h"]
diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml
index 0c4d5d40cae9..9ffa13b77dcf 100644
--- a/Documentation/netlink/specs/rt_link.yaml
+++ b/Documentation/netlink/specs/rt_link.yaml
@@ -920,6 +920,13 @@ definitions:
- name: l2
- name: l3
+ -
+ name: netkit-scrub
+ type: enum
+ entries:
+ - name: none
+ - name: default
+
attribute-sets:
-
name: link-attrs
@@ -1137,6 +1144,10 @@ attribute-sets:
name: dpll-pin
type: nest
nested-attributes: link-dpll-pin-attrs
+ -
+ name: max-pacing-offload-horizon
+ type: uint
+ doc: EDT offload horizon supported by the device (in nsec).
-
name: af-spec-attrs
attributes:
@@ -2147,6 +2158,14 @@ attribute-sets:
name: mode
type: u32
enum: netkit-mode
+ -
+ name: scrub
+ type: u32
+ enum: netkit-scrub
+ -
+ name: peer-scrub
+ type: u32
+ enum: netkit-scrub
sub-messages:
-
diff --git a/Documentation/netlink/specs/rt_neigh.yaml b/Documentation/netlink/specs/rt_neigh.yaml
new file mode 100644
index 000000000000..e670b6dc07be
--- /dev/null
+++ b/Documentation/netlink/specs/rt_neigh.yaml
@@ -0,0 +1,442 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+
+name: rt-neigh
+protocol: netlink-raw
+protonum: 0
+
+doc:
+ IP neighbour management over rtnetlink.
+
+definitions:
+ -
+ name: ndmsg
+ type: struct
+ members:
+ -
+ name: family
+ type: u8
+ -
+ name: pad
+ type: pad
+ len: 3
+ -
+ name: ifindex
+ type: s32
+ -
+ name: state
+ type: u16
+ enum: nud-state
+ -
+ name: flags
+ type: u8
+ enum: ntf-flags
+ -
+ name: type
+ type: u8
+ enum: rtm-type
+ -
+ name: ndtmsg
+ type: struct
+ members:
+ -
+ name: family
+ type: u8
+ -
+ name: pad
+ type: pad
+ len: 3
+ -
+ name: nud-state
+ type: flags
+ entries:
+ - incomplete
+ - reachable
+ - stale
+ - delay
+ - probe
+ - failed
+ - noarp
+ - permanent
+ -
+ name: ntf-flags
+ type: flags
+ entries:
+ - use
+ - self
+ - master
+ - proxy
+ - ext-learned
+ - offloaded
+ - sticky
+ - router
+ -
+ name: ntf-ext-flags
+ type: flags
+ entries:
+ - managed
+ - locked
+ -
+ name: rtm-type
+ type: enum
+ entries:
+ - unspec
+ - unicast
+ - local
+ - broadcast
+ - anycast
+ - multicast
+ - blackhole
+ - unreachable
+ - prohibit
+ - throw
+ - nat
+ - xresolve
+ -
+ name: nda-cacheinfo
+ type: struct
+ members:
+ -
+ name: confirmed
+ type: u32
+ -
+ name: used
+ type: u32
+ -
+ name: updated
+ type: u32
+ -
+ name: refcnt
+ type: u32
+ -
+ name: ndt-config
+ type: struct
+ members:
+ -
+ name: key-len
+ type: u16
+ -
+ name: entry-size
+ type: u16
+ -
+ name: entries
+ type: u32
+ -
+ name: last-flush
+ type: u32
+ -
+ name: last-rand
+ type: u32
+ -
+ name: hash-rnd
+ type: u32
+ -
+ name: hash-mask
+ type: u32
+ -
+ name: hash-chain-gc
+ type: u32
+ -
+ name: proxy-qlen
+ type: u32
+ -
+ name: ndt-stats
+ type: struct
+ members:
+ -
+ name: allocs
+ type: u64
+ -
+ name: destroys
+ type: u64
+ -
+ name: hash-grows
+ type: u64
+ -
+ name: res-failed
+ type: u64
+ -
+ name: lookups
+ type: u64
+ -
+ name: hits
+ type: u64
+ -
+ name: rcv-probes-mcast
+ type: u64
+ -
+ name: rcv-probes-ucast
+ type: u64
+ -
+ name: periodic-gc-runs
+ type: u64
+ -
+ name: forced-gc-runs
+ type: u64
+ -
+ name: table-fulls
+ type: u64
+
+attribute-sets:
+ -
+ name: neighbour-attrs
+ attributes:
+ -
+ name: unspec
+ type: binary
+ value: 0
+ -
+ name: dst
+ type: binary
+ display-hint: ipv4
+ -
+ name: lladr
+ type: binary
+ display-hint: mac
+ -
+ name: cacheinfo
+ type: binary
+ struct: nda-cacheinfo
+ -
+ name: probes
+ type: u32
+ -
+ name: vlan
+ type: u16
+ -
+ name: port
+ type: u16
+ -
+ name: vni
+ type: u32
+ -
+ name: ifindex
+ type: u32
+ -
+ name: master
+ type: u32
+ -
+ name: link-netnsid
+ type: s32
+ -
+ name: src-vni
+ type: u32
+ -
+ name: protocol
+ type: u8
+ -
+ name: nh-id
+ type: u32
+ -
+ name: fdb-ext-attrs
+ type: binary
+ -
+ name: flags-ext
+ type: u32
+ enum: ntf-ext-flags
+ -
+ name: ndm-state-mask
+ type: u16
+ -
+ name: ndm-flags-mask
+ type: u8
+ -
+ name: ndt-attrs
+ attributes:
+ -
+ name: name
+ type: string
+ -
+ name: thresh1
+ type: u32
+ -
+ name: thresh2
+ type: u32
+ -
+ name: thresh3
+ type: u32
+ -
+ name: config
+ type: binary
+ struct: ndt-config
+ -
+ name: parms
+ type: nest
+ nested-attributes: ndtpa-attrs
+ -
+ name: stats
+ type: binary
+ struct: ndt-stats
+ -
+ name: gc-interval
+ type: u64
+ -
+ name: pad
+ type: pad
+ -
+ name: ndtpa-attrs
+ attributes:
+ -
+ name: ifindex
+ type: u32
+ -
+ name: refcnt
+ type: u32
+ -
+ name: reachable-time
+ type: u64
+ -
+ name: base-reachable-time
+ type: u64
+ -
+ name: retrans-time
+ type: u64
+ -
+ name: gc-staletime
+ type: u64
+ -
+ name: delay-probe-time
+ type: u64
+ -
+ name: queue-len
+ type: u32
+ -
+ name: app-probes
+ type: u32
+ -
+ name: ucast-probes
+ type: u32
+ -
+ name: mcast-probes
+ type: u32
+ -
+ name: anycast-delay
+ type: u64
+ -
+ name: proxy-delay
+ type: u64
+ -
+ name: proxy-qlen
+ type: u32
+ -
+ name: locktime
+ type: u64
+ -
+ name: queue-lenbytes
+ type: u32
+ -
+ name: mcast-reprobes
+ type: u32
+ -
+ name: pad
+ type: pad
+ -
+ name: interval-probe-time-ms
+ type: u64
+
+operations:
+ enum-model: directional
+ list:
+ -
+ name: newneigh
+ doc: Add new neighbour entry
+ fixed-header: ndmsg
+ attribute-set: neighbour-attrs
+ do:
+ request:
+ value: 28
+ attributes: &neighbour-all
+ - dst
+ - lladdr
+ - probes
+ - vlan
+ - port
+ - vni
+ - ifindex
+ - master
+ - protocol
+ - nh-id
+ - flags-ext
+ - fdb-ext-attrs
+ -
+ name: delneigh
+ doc: Remove an existing neighbour entry
+ fixed-header: ndmsg
+ attribute-set: neighbour-attrs
+ do:
+ request:
+ value: 29
+ attributes:
+ - dst
+ - ifindex
+ -
+ name: delneigh-ntf
+ doc: Notify a neighbour deletion
+ value: 29
+ notify: delneigh
+ fixed-header: ndmsg
+ -
+ name: getneigh
+ doc: Get or dump neighbour entries
+ fixed-header: ndmsg
+ attribute-set: neighbour-attrs
+ do:
+ request:
+ value: 30
+ attributes:
+ - dst
+ reply:
+ value: 28
+ attributes: *neighbour-all
+ dump:
+ request:
+ attributes:
+ - ifindex
+ - master
+ reply:
+ attributes: *neighbour-all
+ -
+ name: newneigh-ntf
+ doc: Notify a neighbour creation
+ value: 28
+ notify: getneigh
+ fixed-header: ndmsg
+ -
+ name: getneightbl
+ doc: Get or dump neighbour tables
+ fixed-header: ndtmsg
+ attribute-set: ndt-attrs
+ dump:
+ request:
+ value: 66
+ reply:
+ value: 64
+ attributes:
+ - name
+ - thresh1
+ - thresh2
+ - thresh3
+ - config
+ - parms
+ - stats
+ - gc-interval
+ -
+ name: setneightbl
+ doc: Set neighbour tables
+ fixed-header: ndtmsg
+ attribute-set: ndt-attrs
+ do:
+ request:
+ value: 67
+ attributes:
+ - name
+ - thresh1
+ - thresh2
+ - thresh3
+ - parms
+ - gc-interval
+
+mcast-groups:
+ list:
+ -
+ name: rtnlgrp-neigh
+ value: 3
diff --git a/Documentation/netlink/specs/rt_rule.yaml b/Documentation/netlink/specs/rt_rule.yaml
new file mode 100644
index 000000000000..03a8eef7952e
--- /dev/null
+++ b/Documentation/netlink/specs/rt_rule.yaml
@@ -0,0 +1,242 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+
+name: rt-rule
+protocol: netlink-raw
+protonum: 0
+
+doc:
+ FIB rule management over rtnetlink.
+
+definitions:
+ -
+ name: rtgenmsg
+ type: struct
+ members:
+ -
+ name: family
+ type: u8
+ -
+ name: pad
+ type: pad
+ len: 3
+ -
+ name: fib-rule-hdr
+ type: struct
+ members:
+ -
+ name: family
+ type: u8
+ -
+ name: dst-len
+ type: u8
+ -
+ name: src-len
+ type: u8
+ -
+ name: tos
+ type: u8
+ -
+ name: table
+ type: u8
+ -
+ name: res1
+ type: pad
+ len: 1
+ -
+ name: res2
+ type: pad
+ len: 1
+ -
+ name: action
+ type: u8
+ enum: fr-act
+ -
+ name: flags
+ type: u32
+ -
+ name: fr-act
+ type: enum
+ entries:
+ - unspec
+ - to-tbl
+ - goto
+ - nop
+ - res3
+ - res4
+ - blackhole
+ - unreachable
+ - prohibit
+ -
+ name: fib-rule-port-range
+ type: struct
+ members:
+ -
+ name: start
+ type: u16
+ -
+ name: end
+ type: u16
+ -
+ name: fib-rule-uid-range
+ type: struct
+ members:
+ -
+ name: start
+ type: u32
+ -
+ name: end
+ type: u32
+
+attribute-sets:
+ -
+ name: fib-rule-attrs
+ attributes:
+ -
+ name: dst
+ type: u32
+ -
+ name: src
+ type: u32
+ -
+ name: iifname
+ type: string
+ -
+ name: goto
+ type: u32
+ -
+ name: unused2
+ type: pad
+ -
+ name: priority
+ type: u32
+ -
+ name: unused3
+ type: pad
+ -
+ name: unused4
+ type: pad
+ -
+ name: unused5
+ type: pad
+ -
+ name: fwmark
+ type: u32
+ display-hint: hex
+ -
+ name: flow
+ type: u32
+ -
+ name: tun-id
+ type: u64
+ -
+ name: suppress-ifgroup
+ type: u32
+ -
+ name: suppress-prefixlen
+ type: u32
+ display-hint: hex
+ -
+ name: table
+ type: u32
+ -
+ name: fwmask
+ type: u32
+ display-hint: hex
+ -
+ name: oifname
+ type: string
+ -
+ name: pad
+ type: pad
+ -
+ name: l3mdev
+ type: u8
+ -
+ name: uid-range
+ type: binary
+ struct: fib-rule-uid-range
+ -
+ name: protocol
+ type: u8
+ -
+ name: ip-proto
+ type: u8
+ -
+ name: sport-range
+ type: binary
+ struct: fib-rule-port-range
+ -
+ name: dport-range
+ type: binary
+ struct: fib-rule-port-range
+ -
+ name: dscp
+ type: u8
+
+operations:
+ enum-model: directional
+ fixed-header: fib-rule-hdr
+ list:
+ -
+ name: newrule
+ doc: Add new FIB rule
+ attribute-set: fib-rule-attrs
+ do:
+ request:
+ value: 32
+ attributes: &fib-rule-all
+ - iifname
+ - oifname
+ - priority
+ - fwmark
+ - flow
+ - tun-id
+ - fwmask
+ - table
+ - suppress-prefixlen
+ - suppress-ifgroup
+ - goto
+ - l3mdev
+ - uid-range
+ - protocol
+ - ip-proto
+ - sport-range
+ - dport-range
+ - dscp
+ -
+ name: newrule-ntf
+ doc: Notify a rule creation
+ value: 32
+ notify: newrule
+ -
+ name: delrule
+ doc: Remove an existing FIB rule
+ attribute-set: fib-rule-attrs
+ do:
+ request:
+ value: 33
+ attributes: *fib-rule-all
+ -
+ name: delrule-ntf
+ doc: Notify a rule deletion
+ value: 33
+ notify: delrule
+ -
+ name: getrule
+ doc: Dump all FIB rules
+ attribute-set: fib-rule-attrs
+ dump:
+ request:
+ value: 34
+ reply:
+ value: 32
+ attributes: *fib-rule-all
+
+mcast-groups:
+ list:
+ -
+ name: rtnlgrp-ipv4-rule
+ value: 8
+ -
+ name: rtnlgrp-ipv6-rule
+ value: 19
diff --git a/Documentation/netlink/specs/tc.yaml b/Documentation/netlink/specs/tc.yaml
index b02d59a0349c..aacccea5dfe4 100644
--- a/Documentation/netlink/specs/tc.yaml
+++ b/Documentation/netlink/specs/tc.yaml
@@ -622,7 +622,7 @@ definitions:
-
name: max-P
type: u32
- doc: probabilty, high resolution
+ doc: probability, high resolution
-
name: stats
type: binary
diff --git a/Documentation/networking/bonding.rst b/Documentation/networking/bonding.rst
index e774b48de9f5..7c8d22d68682 100644
--- a/Documentation/networking/bonding.rst
+++ b/Documentation/networking/bonding.rst
@@ -2916,6 +2916,17 @@ from the bond (``ifenslave -d bond0 eth0``). The bonding driver will
then restore the MAC addresses that the slaves had before they were
enslaved.
+9. What bonding modes support native XDP?
+------------------------------------------
+
+ * balance-rr (0)
+ * active-backup (1)
+ * balance-xor (2)
+ * 802.3ad (4)
+
+Note that the vlan+srcmac hash policy does not support native XDP.
+For other bonding modes, the XDP program must be loaded with generic mode.
+
16. Resources and Links
=======================
diff --git a/Documentation/networking/cdc_mbim.rst b/Documentation/networking/cdc_mbim.rst
index 37f968acc473..8404a3f794f3 100644
--- a/Documentation/networking/cdc_mbim.rst
+++ b/Documentation/networking/cdc_mbim.rst
@@ -51,7 +51,7 @@ Such userspace applications includes, but are not limited to:
- mbimcli (included with the libmbim [3] library), and
- ModemManager [4]
-Establishing a MBIM IP session reequires at least these actions by the
+Establishing a MBIM IP session requires at least these actions by the
management application:
- open the control channel
diff --git a/Documentation/networking/device_drivers/ethernet/intel/ice.rst b/Documentation/networking/device_drivers/ethernet/intel/ice.rst
index 934752f675ba..3c46a48d99ba 100644
--- a/Documentation/networking/device_drivers/ethernet/intel/ice.rst
+++ b/Documentation/networking/device_drivers/ethernet/intel/ice.rst
@@ -101,6 +101,37 @@ example, if Rx packets are 10 and Netdev (software statistics) displays
rx_bytes as "X", then ethtool (hardware statistics) will display rx_bytes as
"X+40" (4 bytes CRC x 10 packets).
+ethtool reset
+-------------
+The driver supports 3 types of resets:
+
+- PF reset - resets only components associated with the given PF, does not
+ impact other PFs
+
+- CORE reset - whole adapter is affected, reset all PFs
+
+- GLOBAL reset - same as CORE but mac and phy components are also reinitialized
+
+These are mapped to ethtool reset flags as follow:
+
+- PF reset:
+
+ # ethtool --reset <ethX> irq dma filter offload
+
+- CORE reset:
+
+ # ethtool --reset <ethX> irq-shared dma-shared filter-shared offload-shared \
+ ram-shared
+
+- GLOBAL reset:
+
+ # ethtool --reset <ethX> irq-shared dma-shared filter-shared offload-shared \
+ mac-shared phy-shared ram-shared
+
+In switchdev mode you can reset a VF using port representor:
+
+ # ethtool --reset <repr> irq dma filter offload
+
Viewing Link Messages
---------------------
diff --git a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
index 1e196cb9ce25..af7db0e91f6b 100644
--- a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
+++ b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
@@ -14,6 +14,7 @@ Contents
- `Basic packet flow`_
- `Devlink health reporters`_
- `Quality of service`_
+- `RVU representors`_
Overview
========
@@ -340,3 +341,93 @@ Setup HTB offload
# tc class add dev <interface> parent 1: classid 1:2 htb rate 10Gbit prio 2 quantum 188416
# tc class add dev <interface> parent 1: classid 1:3 htb rate 10Gbit prio 2 quantum 32768
+
+
+RVU Representors
+================
+
+RVU representor driver adds support for creation of representor devices for
+RVU PFs' VFs in the system. Representor devices are created when user enables
+the switchdev mode.
+Switchdev mode can be enabled either before or after setting up SRIOV numVFs.
+All representor devices share a single NIXLF but each has a dedicated Rx/Tx
+queues. RVU PF representor driver registers a separate netdev for each
+Rx/Tx queue pair.
+
+Current HW does not support built-in switch which can do L2 learning and
+forwarding packets between representee and representor. Hence, packet path
+between representee and it's representor is achieved by setting up appropriate
+NPC MCAM filters.
+Transmit packets matching these filters will be loopbacked through hardware
+loopback channel/interface (i.e, instead of sending them out of MAC interface).
+Which will again match the installed filters and will be forwarded.
+This way representee => representor and representor => representee packet
+path is achieved. These rules get installed when representors are created
+and gets active/deactivate based on the representor/representee interface state.
+
+Usage example:
+
+ - Change device to switchdev mode::
+
+ # devlink dev eswitch set pci/0002:1c:00.0 mode switchdev
+
+ - List of representor devices on the system::
+
+ # ip link show
+ Rpf1vf0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000 link/ether f6:43:83:ee:26:21 brd ff:ff:ff:ff:ff:ff
+ Rpf1vf1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000 link/ether 12:b2:54:0e:24:54 brd ff:ff:ff:ff:ff:ff
+ Rpf1vf2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000 link/ether 4a:12:c4:4c:32:62 brd ff:ff:ff:ff:ff:ff
+ Rpf1vf3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000 link/ether ca:cb:68:0e:e2:6e brd ff:ff:ff:ff:ff:ff
+ Rpf2vf0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000 link/ether 06:cc:ad:b4:f0:93 brd ff:ff:ff:ff:ff:ff
+
+
+To delete the representors devices from the system. Change the device to legacy mode.
+
+ - Change device to legacy mode::
+
+ # devlink dev eswitch set pci/0002:1c:00.0 mode legacy
+
+RVU representors can be managed using devlink ports
+(see :ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`) interface.
+
+ - Show devlink ports of representors::
+
+ # devlink port
+ pci/0002:1c:00.0/0: type eth netdev Rpf1vf0 flavour physical port 0 splittable false
+ pci/0002:1c:00.0/1: type eth netdev Rpf1vf1 flavour pcivf controller 0 pfnum 1 vfnum 1 external false splittable false
+ pci/0002:1c:00.0/2: type eth netdev Rpf1vf2 flavour pcivf controller 0 pfnum 1 vfnum 2 external false splittable false
+ pci/0002:1c:00.0/3: type eth netdev Rpf1vf3 flavour pcivf controller 0 pfnum 1 vfnum 3 external false splittable false
+
+Function attributes
+===================
+
+The RVU representor support function attributes for representors.
+Port function configuration of the representors are supported through devlink eswitch port.
+
+MAC address setup
+-----------------
+
+RVU representor driver support devlink port function attr mechanism to setup MAC
+address. (refer to Documentation/networking/devlink/devlink-port.rst)
+
+ - To setup MAC address for port 2::
+
+ # devlink port function set pci/0002:1c:00.0/2 hw_addr 5c:a1:1b:5e:43:11
+ # devlink port show pci/0002:1c:00.0/2
+ pci/0002:1c:00.0/2: type eth netdev Rpf1vf2 flavour pcivf controller 0 pfnum 1 vfnum 2 external false splittable false
+ function:
+ hw_addr 5c:a1:1b:5e:43:11
+
+
+TC offload
+==========
+
+The rvu representor driver implements support for offloading tc rules using port representors.
+
+ - Drop packets with vlan id 3::
+
+ # tc filter add dev Rpf1vf0 protocol 802.1Q parent ffff: flower vlan_id 3 vlan_ethtype ipv4 skip_sw action drop
+
+ - Redirect packets with vlan id 5 and IPv4 packets to eth1, after stripping vlan header.::
+
+ # tc filter add dev Rpf1vf0 ingress protocol 802.1Q flower vlan_id 5 vlan_ethtype ipv4 skip_sw action vlan pop action mirred ingress redirect dev eth1
diff --git a/Documentation/networking/device_drivers/ethernet/meta/fbnic.rst b/Documentation/networking/device_drivers/ethernet/meta/fbnic.rst
index 32ff114f5c26..04e0595bb0a7 100644
--- a/Documentation/networking/device_drivers/ethernet/meta/fbnic.rst
+++ b/Documentation/networking/device_drivers/ethernet/meta/fbnic.rst
@@ -27,3 +27,46 @@ driver takes over.
devlink dev info provides version information for all three components. In
addition to the version the hg commit hash of the build is included as a
separate entry.
+
+Statistics
+----------
+
+RPC (Rx parser)
+~~~~~~~~~~~~~~~
+
+ - ``rpc_unkn_etype``: frames containing unknown EtherType
+ - ``rpc_unkn_ext_hdr``: frames containing unknown IPv6 extension header
+ - ``rpc_ipv4_frag``: frames containing IPv4 fragment
+ - ``rpc_ipv6_frag``: frames containing IPv6 fragment
+ - ``rpc_ipv4_esp``: frames with IPv4 ESP encapsulation
+ - ``rpc_ipv6_esp``: frames with IPv6 ESP encapsulation
+ - ``rpc_tcp_opt_err``: frames which encountered TCP option parsing error
+ - ``rpc_out_of_hdr_err``: frames where header was larger than parsable region
+ - ``ovr_size_err``: oversized frames
+
+PCIe
+~~~~
+
+The fbnic driver exposes PCIe hardware performance statistics through debugfs
+(``pcie_stats``). These statistics provide insights into PCIe transaction
+behavior and potential performance bottlenecks.
+
+1. PCIe Transaction Counters:
+
+ These counters track PCIe transaction activity:
+ - ``pcie_ob_rd_tlp``: Outbound read Transaction Layer Packets count
+ - ``pcie_ob_rd_dword``: DWORDs transferred in outbound read transactions
+ - ``pcie_ob_wr_tlp``: Outbound write Transaction Layer Packets count
+ - ``pcie_ob_wr_dword``: DWORDs transferred in outbound write
+ transactions
+ - ``pcie_ob_cpl_tlp``: Outbound completion TLP count
+ - ``pcie_ob_cpl_dword``: DWORDs transferred in outbound completion TLPs
+
+2. PCIe Resource Monitoring:
+
+ These counters indicate PCIe resource exhaustion events:
+ - ``pcie_ob_rd_no_tag``: Read requests dropped due to tag unavailability
+ - ``pcie_ob_rd_no_cpl_cred``: Read requests dropped due to completion
+ credit exhaustion
+ - ``pcie_ob_rd_no_np_cred``: Read requests dropped due to non-posted
+ credit exhaustion
diff --git a/Documentation/networking/device_drivers/wwan/t7xx.rst b/Documentation/networking/device_drivers/wwan/t7xx.rst
index f346f5f85f15..e07de7700dfc 100644
--- a/Documentation/networking/device_drivers/wwan/t7xx.rst
+++ b/Documentation/networking/device_drivers/wwan/t7xx.rst
@@ -7,12 +7,13 @@
============================================
t7xx driver for MTK PCIe based T700 5G modem
============================================
-The t7xx driver is a WWAN PCIe host driver developed for linux or Chrome OS platforms
-for data exchange over PCIe interface between Host platform & MediaTek's T700 5G modem.
-The driver exposes an interface conforming to the MBIM protocol [1]. Any front end
-application (e.g. Modem Manager) could easily manage the MBIM interface to enable
-data communication towards WWAN. The driver also provides an interface to interact
-with the MediaTek's modem via AT commands.
+The t7xx driver is a WWAN PCIe host driver developed for linux or Chrome OS
+platforms for data exchange over PCIe interface between Host platform &
+MediaTek's T700 5G modem.
+The driver exposes an interface conforming to the MBIM protocol [1]. Any front
+end application (e.g. Modem Manager) could easily manage the MBIM interface to
+enable data communication towards WWAN. The driver also provides an interface
+to interact with the MediaTek's modem via AT commands.
Basic usage
===========
@@ -45,8 +46,8 @@ The driver provides sysfs interfaces to userspace.
t7xx_mode
---------
-The sysfs interface provides userspace with access to the device mode, this interface
-supports read and write operations.
+The sysfs interface provides userspace with access to the device mode, this
+interface supports read and write operations.
Device mode:
@@ -67,6 +68,28 @@ Write from userspace to set the device mode.
::
$ echo fastboot_switching > /sys/bus/pci/devices/${bdf}/t7xx_mode
+t7xx_debug_ports
+----------------
+The sysfs interface provides userspace with access to enable/disable the debug
+ports, this interface supports read and write operations.
+
+Debug port status:
+
+- ``1`` represents enable debug ports
+- ``0`` represents disable debug ports
+
+Currently supported debug ports (ADB/MIPC).
+
+Read from userspace to get the current debug ports status.
+
+::
+ $ cat /sys/bus/pci/devices/${bdf}/t7xx_debug_ports
+
+Write from userspace to set the debug ports status.
+
+::
+ $ echo 1 > /sys/bus/pci/devices/${bdf}/t7xx_debug_ports
+
Management application development
==================================
The driver and userspace interfaces are described below. The MBIM protocol is
@@ -139,6 +162,25 @@ Please note that driver needs to be reloaded to export /dev/wwan0fastboot0
port, because device needs a cold reset after enter ``fastboot_switching``
mode.
+ADB port userspace ABI
+----------------------
+
+/dev/wwan0adb0 character device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driver exposes a ADB protocol interface by implementing ADB WWAN Port.
+The userspace end of the ADB channel pipe is a /dev/wwan0adb0 character device.
+Application shall use this interface for ADB protocol communication.
+
+MIPC port userspace ABI
+-----------------------
+
+/dev/wwan0mipc0 character device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driver exposes a diagnostic interface by implementing MIPC (Modem
+Information Process Center) WWAN Port. The userspace end of the MIPC channel
+pipe is a /dev/wwan0mipc0 character device.
+Application shall use this interface for MTK modem diagnostic communication.
+
The MediaTek's T700 modem supports the 3GPP TS 27.007 [4] specification.
References
@@ -164,3 +206,9 @@ speak the Mobile Interface Broadband Model (MBIM) protocol"*
[5] *fastboot "a mechanism for communicating with bootloaders"*
- https://android.googlesource.com/platform/system/core/+/refs/heads/main/fastboot/README.md
+
+[6] *ADB (Android Debug Bridge) "a mechanism to keep track of Android devices
+and emulators instances connected to or running on a given host developer
+machine with ADB protocol"*
+
+- https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/README.md
diff --git a/Documentation/networking/devlink/octeontx2.rst b/Documentation/networking/devlink/octeontx2.rst
index d33a90dd44bf..84206537aedb 100644
--- a/Documentation/networking/devlink/octeontx2.rst
+++ b/Documentation/networking/devlink/octeontx2.rst
@@ -40,6 +40,27 @@ The ``octeontx2 AF`` driver implements the following driver-specific parameters.
- runtime
- Use to set the quantum which hardware uses for scheduling among transmit queues.
Hardware uses weighted DWRR algorithm to schedule among all transmit queues.
+ * - ``npc_mcam_high_zone_percent``
+ - u8
+ - runtime
+ - Use to set the number of high priority zone entries in NPC MCAM that can be allocated
+ by a user, out of the three priority zone categories high, mid and low.
+ * - ``npc_def_rule_cntr``
+ - bool
+ - runtime
+ - Use to enable or disable hit counters for the default rules in NPC MCAM.
+ Its not guaranteed that counters gets enabled and mapped to all the default rules,
+ since the counters are scarce and driver follows a best effort approach.
+ The default rule serves as the primary packet steering rule for a specific PF or VF,
+ based on its DMAC address which is installed by AF driver as part of its initialization.
+ Sample command to read hit counters for default rule from debugfs is as follows,
+ cat /sys/kernel/debug/cn10k/npc/mcam_rules
+ * - ``nix_maxlf``
+ - u16
+ - runtime
+ - Use to set the maximum number of LFs in NIX hardware block. This would be useful
+ to increase the availability of default resources allocated to enabled LFs like
+ MCAM entries for example.
The ``octeontx2 PF`` driver implements the following driver-specific parameters.
diff --git a/Documentation/networking/devmem.rst b/Documentation/networking/devmem.rst
index a55bf21f671c..d95363645331 100644
--- a/Documentation/networking/devmem.rst
+++ b/Documentation/networking/devmem.rst
@@ -225,6 +225,15 @@ The user must ensure the tokens are returned to the kernel in a timely manner.
Failure to do so will exhaust the limited dmabuf that is bound to the RX queue
and will lead to packet drops.
+The user must pass no more than 128 tokens, with no more than 1024 total frags
+among the token->token_count across all the tokens. If the user provides more
+than 1024 frags, the kernel will free up to 1024 frags and return early.
+
+The kernel returns the number of actual frags freed. The number of frags freed
+can be less than the tokens provided by the user in case of:
+
+(a) an internal kernel leak bug.
+(b) the user passed more than 1024 frags.
Implementation & Caveats
========================
diff --git a/Documentation/networking/diagnostic/index.rst b/Documentation/networking/diagnostic/index.rst
new file mode 100644
index 000000000000..86488aa46b48
--- /dev/null
+++ b/Documentation/networking/diagnostic/index.rst
@@ -0,0 +1,17 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================
+Networking Diagnostics
+======================
+
+.. toctree::
+ :maxdepth: 2
+
+ twisted_pair_layer1_diagnostics.rst
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/networking/diagnostic/twisted_pair_layer1_diagnostics.rst b/Documentation/networking/diagnostic/twisted_pair_layer1_diagnostics.rst
new file mode 100644
index 000000000000..c9be5cc7e113
--- /dev/null
+++ b/Documentation/networking/diagnostic/twisted_pair_layer1_diagnostics.rst
@@ -0,0 +1,767 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Diagnostic Concept for Investigating Twisted Pair Ethernet Variants at OSI Layer 1
+==================================================================================
+
+Introduction
+------------
+
+This documentation is designed for two primary audiences:
+
+1. **Users and System Administrators**: For those dealing with real-world
+ Ethernet issues, this guide provides a practical, step-by-step
+ troubleshooting flow to help identify and resolve common problems in Twisted
+ Pair Ethernet at OSI Layer 1. If you're facing unstable links, speed drops,
+ or mysterious network issues, jump right into the step-by-step guide and
+ follow it through to find your solution.
+
+2. **Kernel Developers**: For developers working with network drivers and PHY
+ support, this documentation outlines the diagnostic process and highlights
+ areas where the Linux kernel’s diagnostic interfaces could be extended or
+ improved. By understanding the diagnostic flow, developers can better
+ prioritize future enhancements.
+
+Step-by-Step Diagnostic Guide from Linux (General Ethernet)
+-----------------------------------------------------------
+
+This diagnostic guide covers common Ethernet troubleshooting scenarios,
+focusing on **link stability and detection** across different Ethernet
+environments, including **Single-Pair Ethernet (SPE)** and **Multi-Pair
+Ethernet (MPE)**, as well as power delivery technologies like **PoDL** (Power
+over Data Line) and **PoE** (Clause 33 PSE).
+
+The guide is designed to help users diagnose physical layer (Layer 1) issues on
+systems running **Linux kernel version 6.11 or newer**, utilizing **ethtool
+version 6.10 or later** and **iproute2 version 6.4.0 or later**.
+
+In this guide, we assume that users may have **limited or no access to the link
+partner** and will focus on diagnosing issues locally.
+
+Diagnostic Scenarios
+~~~~~~~~~~~~~~~~~~~~
+
+- **Link is up and stable, but no data transfer**: If the link is stable but
+ there are issues with data transmission, refer to the **OSI Layer 2
+ Troubleshooting Guide**.
+
+- **Link is unstable**: Link resets, speed drops, or other fluctuations
+ indicate potential issues at the hardware or physical layer.
+
+- **No link detected**: The interface is up, but no link is established.
+
+Verify Interface Status
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Begin by verifying the status of the Ethernet interface to check if it is
+administratively up. Unlike `ethtool`, which provides information on the link
+and PHY status, it does not show the **administrative state** of the interface.
+To check this, you should use the `ip` command, which describes the interface
+state within the angle brackets `"<>"` in its output.
+
+For example, in the output `<NO-CARRIER,BROADCAST,MULTICAST,UP>`, the important
+keywords are:
+
+- **UP**: The interface is in the administrative "UP" state.
+- **NO-CARRIER**: The interface is administratively up, but no physical link is
+ detected.
+
+If the output shows `<BROADCAST,MULTICAST>`, this indicates the interface is in
+the administrative "DOWN" state.
+
+- **Command:** `ip link show dev <interface>`
+
+- **Expected Output:**
+
+ .. code-block:: bash
+
+ 4: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 ...
+ link/ether 88:14:2b:00:96:f2 brd ff:ff:ff:ff:ff:ff
+
+- **Interpreting the Output:**
+
+ - **Administrative UP State**:
+
+ - If the output contains **"UP"**, the interface is administratively up,
+ and the system is trying to establish a physical link.
+
+ - If you also see **"NO-CARRIER"**, it means the physical link has not been
+ detected, indicating potential Layer 1 issues like a cable fault,
+ misconfiguration, or no connection at the link partner. In this case,
+ proceed to the **Inspect Link Status and PHY Configuration** section.
+
+ - **Administrative DOWN State**:
+
+ - If the output lacks **"UP"** and shows only states like
+ **"<BROADCAST,MULTICAST>"**, it means the interface is administratively
+ down. In this case, bring the interface up using the following command:
+
+ .. code-block:: bash
+
+ ip link set dev <interface> up
+
+- **Next Steps**:
+
+ - If the interface is **administratively up** but shows **NO-CARRIER**,
+ proceed to the **Inspect Link Status and PHY Configuration** section to
+ troubleshoot potential physical layer issues.
+
+ - If the interface was **administratively down** and you have brought it up,
+ ensure to **repeat this verification step** to confirm the new state of the
+ interface before proceeding
+
+ - **If the interface is up and the link is detected**:
+
+ - If the output shows **"UP"** and there is **no `NO-CARRIER`**, the
+ interface is administratively up, and the physical link has been
+ successfully established. If everything is working as expected, the Layer
+ 1 diagnostics are complete, and no further action is needed.
+
+ - If the interface is up and the link is detected but **no data is being
+ transferred**, the issue is likely beyond Layer 1, and you should proceed
+ with diagnosing the higher layers of the OSI model. This may involve
+ checking Layer 2 configurations (such as VLANs or MAC address issues),
+ Layer 3 settings (like IP addresses, routing, or ARP), or Layer 4 and
+ above (firewalls, services, etc.).
+
+ - If the **link is unstable** or **frequently resetting or dropping**, this
+ may indicate a physical layer issue such as a faulty cable, interference,
+ or power delivery problems. In this case, proceed with the next step in
+ this guide.
+
+Inspect Link Status and PHY Configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use `ethtool -I` to check the link status, PHY configuration, supported link
+modes, and additional statistics such as the **Link Down Events** counter. This
+step is essential for diagnosing Layer 1 problems such as speed mismatches,
+duplex issues, and link instability.
+
+For both **Single-Pair Ethernet (SPE)** and **Multi-Pair Ethernet (MPE)**
+devices, you will use this step to gather key details about the link. **SPE**
+links generally support a single speed and mode without autonegotiation (with
+the exception of **10BaseT1L**), while **MPE** devices typically support
+multiple link modes and autonegotiation.
+
+- **Command:** `ethtool -I <interface>`
+
+- **Example Output for SPE Interface (Non-autonegotiation)**:
+
+ .. code-block:: bash
+
+ Settings for spe4:
+ Supported ports: [ TP ]
+ Supported link modes: 100baseT1/Full
+ Supported pause frame use: No
+ Supports auto-negotiation: No
+ Supported FEC modes: Not reported
+ Advertised link modes: Not applicable
+ Advertised pause frame use: No
+ Advertised auto-negotiation: No
+ Advertised FEC modes: Not reported
+ Speed: 100Mb/s
+ Duplex: Full
+ Auto-negotiation: off
+ master-slave cfg: forced slave
+ master-slave status: slave
+ Port: Twisted Pair
+ PHYAD: 6
+ Transceiver: external
+ MDI-X: Unknown
+ Supports Wake-on: d
+ Wake-on: d
+ Link detected: yes
+ SQI: 7/7
+ Link Down Events: 2
+
+- **Example Output for MPE Interface (Autonegotiation)**:
+
+ .. code-block:: bash
+
+ Settings for eth1:
+ Supported ports: [ TP MII ]
+ Supported link modes: 10baseT/Half 10baseT/Full
+ 100baseT/Half 100baseT/Full
+ Supported pause frame use: Symmetric Receive-only
+ Supports auto-negotiation: Yes
+ Supported FEC modes: Not reported
+ Advertised link modes: 10baseT/Half 10baseT/Full
+ 100baseT/Half 100baseT/Full
+ Advertised pause frame use: Symmetric Receive-only
+ Advertised auto-negotiation: Yes
+ Advertised FEC modes: Not reported
+ Link partner advertised link modes: 10baseT/Half 10baseT/Full
+ 100baseT/Half 100baseT/Full
+ Link partner advertised pause frame use: Symmetric Receive-only
+ Link partner advertised auto-negotiation: Yes
+ Link partner advertised FEC modes: Not reported
+ Speed: 100Mb/s
+ Duplex: Full
+ Auto-negotiation: on
+ Port: Twisted Pair
+ PHYAD: 10
+ Transceiver: internal
+ MDI-X: Unknown
+ Supports Wake-on: pg
+ Wake-on: p
+ Link detected: yes
+ Link Down Events: 1
+
+- **Next Steps**:
+
+ - Record the output provided by `ethtool`, particularly noting the
+ **master-slave status**, **speed**, **duplex**, and other relevant fields.
+ This information will be useful for further analysis or troubleshooting.
+ Once the **ethtool** output has been collected and stored, move on to the
+ next diagnostic step.
+
+Check Power Delivery (PoDL or PoE)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If it is known that **PoDL** or **PoE** is **not implemented** on the system,
+or the **PSE** (Power Sourcing Equipment) is managed by proprietary user-space
+software or external tools, you can skip this step. In such cases, verify power
+delivery through alternative methods, such as checking hardware indicators
+(LEDs), using multimeters, or consulting vendor-specific software for
+monitoring power status.
+
+If **PoDL** or **PoE** is implemented and managed directly by Linux, follow
+these steps to ensure power is being delivered correctly:
+
+- **Command:** `ethtool --show-pse <interface>`
+
+- **Expected Output Examples**:
+
+ 1. **PSE Not Supported**:
+
+ If no PSE is attached or the interface does not support PSE, the following
+ output is expected:
+
+ .. code-block:: bash
+
+ netlink error: No PSE is attached
+ netlink error: Operation not supported
+
+ 2. **PoDL (Single-Pair Ethernet)**:
+
+ When PoDL is implemented, you might see the following attributes:
+
+ .. code-block:: bash
+
+ PSE attributes for eth1:
+ PoDL PSE Admin State: enabled
+ PoDL PSE Power Detection Status: delivering power
+
+ 3. **PoE (Clause 33 PSE)**:
+
+ For standard PoE, the output may look like this:
+
+ .. code-block:: bash
+
+ PSE attributes for eth1:
+ Clause 33 PSE Admin State: enabled
+ Clause 33 PSE Power Detection Status: delivering power
+ Clause 33 PSE Available Power Limit: 18000
+
+- **Adjust Power Limit (if needed)**:
+
+ - Sometimes, the available power limit may not be sufficient for the link
+ partner. You can increase the power limit as needed.
+
+ - **Command:** `ethtool --set-pse <interface> c33-pse-avail-pw-limit <limit>`
+
+ Example:
+
+ .. code-block:: bash
+
+ ethtool --set-pse eth1 c33-pse-avail-pw-limit 18000
+ ethtool --show-pse eth1
+
+ **Expected Output** after adjusting the power limit:
+
+ .. code-block:: bash
+
+ Clause 33 PSE Available Power Limit: 18000
+
+
+- **Next Steps**:
+
+ - **PoE or PoDL Not Used**: If **PoE** or **PoDL** is not implemented or used
+ on the system, proceed to the next diagnostic step, as power delivery is
+ not relevant for this setup.
+
+ - **PoE or PoDL Controlled Externally**: If **PoE** or **PoDL** is used but
+ is not managed by the Linux kernel's **PSE-PD** framework (i.e., it is
+ controlled by proprietary user-space software or external tools), this part
+ is out of scope for this documentation. Please consult vendor-specific
+ documentation or external tools for monitoring and managing power delivery.
+
+ - **PSE Admin State Disabled**:
+
+ - If the `PSE Admin State:` is **disabled**, enable it by running one of
+ the following commands:
+
+ .. code-block:: bash
+
+ ethtool --set-pse <devname> podl-pse-admin-control enable
+
+ or, for Clause 33 PSE (PoE):
+
+ ethtool --set-pse <devname> c33-pse-admin-control enable
+
+ - After enabling the PSE Admin State, return to the start of the **Check
+ Power Delivery (PoDL or PoE)** step to recheck the power delivery status.
+
+ - **Power Not Delivered**: If the `Power Detection Status` shows something
+ other than "delivering power" (e.g., `over current`), troubleshoot the
+ **PSE**. Check for potential issues such as a short circuit in the cable,
+ insufficient power delivery, or a fault in the PSE itself.
+
+ - **Power Delivered but No Link**: If power is being delivered but no link is
+ established, proceed with further diagnostics by performing **Cable
+ Diagnostics** or reviewing the **Inspect Link Status and PHY
+ Configuration** steps to identify any underlying issues with the physical
+ link or settings.
+
+Cable Diagnostics
+~~~~~~~~~~~~~~~~~
+
+Use `ethtool` to test for physical layer issues such as cable faults. The test
+results can vary depending on the cable's condition, the technology in use, and
+the state of the link partner. The results from the cable test will help in
+diagnosing issues like open circuits, shorts, impedance mismatches, and
+noise-related problems.
+
+- **Command:** `ethtool --cable-test <interface>`
+
+The following are the typical outputs for **Single-Pair Ethernet (SPE)** and
+**Multi-Pair Ethernet (MPE)**:
+
+- **For Single-Pair Ethernet (SPE)**:
+ - **Expected Output (SPE)**:
+
+ .. code-block:: bash
+
+ Cable test completed for device eth1.
+ Pair A, fault length: 25.00m
+ Pair A code Open Circuit
+
+ This indicates an open circuit or cable fault at the reported distance, but
+ results can be influenced by the link partner's state. Refer to the
+ **"Troubleshooting Based on Cable Test Results"** section for further
+ interpretation of these results.
+
+- **For Multi-Pair Ethernet (MPE)**:
+ - **Expected Output (MPE)**:
+
+ .. code-block:: bash
+
+ Cable test completed for device eth0.
+ Pair A code OK
+ Pair B code OK
+ Pair C code Open Circuit
+
+ Here, Pair C is reported as having an open circuit, while Pairs A and B are
+ functioning correctly. However, if autonegotiation is in use on Pairs A and
+ B, the cable test may be disrupted. Refer to the **"Troubleshooting Based on
+ Cable Test Results"** section for a detailed explanation of these issues and
+ how to resolve them.
+
+For detailed descriptions of the different possible cable test results, please
+refer to the **"Troubleshooting Based on Cable Test Results"** section.
+
+Troubleshooting Based on Cable Test Results
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+After running the cable test, the results can help identify specific issues in
+the physical connection. However, it is important to note that **cable testing
+results heavily depend on the capabilities and characteristics of both the
+local hardware and the link partner**. The accuracy and reliability of the
+results can vary significantly between different hardware implementations.
+
+In some cases, this can introduce **blind spots** in the current cable testing
+implementation, where certain results may not accurately reflect the actual
+physical state of the cable. For example:
+
+- An **Open Circuit** result might not only indicate a damaged or disconnected
+ cable but also occur if the cable is properly attached to a powered-down link
+ partner.
+
+- Some PHYs may report a **Short within Pair** if the link partner is in
+ **forced slave mode**, even though there is no actual short in the cable.
+
+To help users interpret the results more effectively, it could be beneficial to
+extend the **kernel UAPI** (User API) to provide additional context or
+**possible variants** of issues based on the hardware’s characteristics. Since
+these quirks are often hardware-specific, the **kernel driver** would be an
+ideal source of such information. By providing flags or hints related to
+potential false positives for each test result, users would have a better
+understanding of what to verify and where to investigate further.
+
+Until such improvements are made, users should be aware of these limitations
+and manually verify cable issues as needed. Physical inspections may help
+resolve uncertainties related to false positive results.
+
+The results can be one of the following:
+
+- **OK**:
+
+ - The cable is functioning correctly, and no issues were detected.
+
+ - **Next Steps**: If you are still experiencing issues, it might be related
+ to higher-layer problems, such as duplex mismatches or speed negotiation,
+ which are not physical-layer issues.
+
+ - **Special Case for `BaseT1` (1000/100/10BaseT1)**: In `BaseT1` systems, an
+ "OK" result typically also means that the link is up and likely in **slave
+ mode**, since cable tests usually only pass in this mode. For some
+ **10BaseT1L** PHYs, an "OK" result may occur even if the cable is too long
+ for the PHY's configured range (for example, when the range is configured
+ for short-distance mode).
+
+- **Open Circuit**:
+
+ - An **Open Circuit** result typically indicates that the cable is damaged or
+ disconnected at the reported fault length. Consider these possibilities:
+
+ - If the link partner is in **admin down** state or powered off, you might
+ still get an "Open Circuit" result even if the cable is functional.
+
+ - **Next Steps**: Inspect the cable at the fault length for visible damage
+ or loose connections. Verify the link partner is powered on and in the
+ correct mode.
+
+- **Short within Pair**:
+
+ - A **Short within Pair** indicates an unintended connection within the same
+ pair of wires, typically caused by physical damage to the cable.
+
+ - **Next Steps**: Replace or repair the cable and check for any physical
+ damage or improperly crimped connectors.
+
+- **Short to Another Pair**:
+
+ - A **Short to Another Pair** means the wires from different pairs are
+ shorted, which could occur due to physical damage or incorrect wiring.
+
+ - **Next Steps**: Replace or repair the damaged cable. Inspect the cable for
+ incorrect terminations or pinched wiring.
+
+- **Impedance Mismatch**:
+
+ - **Impedance Mismatch** indicates a reflection caused by an impedance
+ discontinuity in the cable. This can happen when a part of the cable has
+ abnormal impedance (e.g., when different cable types are spliced together
+ or when there is a defect in the cable).
+
+ - **Next Steps**: Check the cable quality and ensure consistent impedance
+ throughout its length. Replace any sections of the cable that do not meet
+ specifications.
+
+- **Noise**:
+
+ - **Noise** means that the Time Domain Reflectometry (TDR) test could not
+ complete due to excessive noise on the cable, which can be caused by
+ interference from electromagnetic sources.
+
+ - **Next Steps**: Identify and eliminate sources of electromagnetic
+ interference (EMI) near the cable. Consider using shielded cables or
+ rerouting the cable away from noise sources.
+
+- **Resolution Not Possible**:
+
+ - **Resolution Not Possible** means that the TDR test could not detect the
+ issue due to the resolution limitations of the test or because the fault is
+ beyond the distance that the test can measure.
+
+ - **Next Steps**: Inspect the cable manually if possible, or use alternative
+ diagnostic tools that can handle greater distances or higher resolution.
+
+- **Unknown**:
+
+ - An **Unknown** result may occur when the test cannot classify the fault or
+ when a specific issue is outside the scope of the tool's detection
+ capabilities.
+
+ - **Next Steps**: Re-run the test, verify the link partner's state, and inspect
+ the cable manually if necessary.
+
+Verify Link Partner PHY Configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the cable test passes but the link is still not functioning correctly, it’s
+essential to verify the configuration of the link partner’s PHY. Mismatches in
+speed, duplex settings, or master-slave roles can cause connection issues.
+
+Autonegotiation Mismatch
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+- If both link partners support autonegotiation, ensure that autonegotiation is
+ enabled on both sides and that all supported link modes are advertised. A
+ mismatch can lead to connectivity problems or sub optimal performance.
+
+- **Quick Fix:** Reset autonegotiation to the default settings, which will
+ advertise all default link modes:
+
+ .. code-block:: bash
+
+ ethtool -s <interface> autoneg on
+
+- **Command to check configuration:** `ethtool <interface>`
+
+- **Expected Output:** Ensure that both sides advertise compatible link modes.
+ If autonegotiation is off, verify that both link partners are configured for
+ the same speed and duplex.
+
+ The following example shows a case where the local PHY advertises fewer link
+ modes than it supports. This will reduce the number of overlapping link modes
+ with the link partner. In the worst case, there will be no common link modes,
+ and the link will not be created:
+
+ .. code-block:: bash
+
+ Settings for eth0:
+ Supported link modes: 1000baseT/Full, 100baseT/Full
+ Advertised link modes: 1000baseT/Full
+ Speed: 1000Mb/s
+ Duplex: Full
+ Auto-negotiation: on
+
+Combined Mode Mismatch (Autonegotiation on One Side, Forced on the Other)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- One possible issue occurs when one side is using **autonegotiation** (as in
+ most modern systems), and the other side is set to a **forced link mode**
+ (e.g., older hardware with single-speed hubs). In such cases, modern PHYs
+ will attempt to detect the forced mode on the other side. If the link is
+ established, you may notice:
+
+ - **No or empty "Link partner advertised link modes"**.
+
+ - **"Link partner advertised auto-negotiation:"** will be **"no"** or not
+ present.
+
+- This type of detection does not always work reliably:
+
+ - Typically, the modern PHY will default to **Half Duplex**, even if the link
+ partner is actually configured for **Full Duplex**.
+
+ - Some PHYs may not work reliably if the link partner switches from one
+ forced mode to another. In this case, only a down/up cycle may help.
+
+- **Next Steps**: Set both sides to the same fixed speed and duplex mode to
+ avoid potential detection issues.
+
+ .. code-block:: bash
+
+ ethtool -s <interface> speed 1000 duplex full autoneg off
+
+Master/Slave Role Mismatch (BaseT1 and 1000BaseT PHYs)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- In **BaseT1** systems (e.g., 1000BaseT1, 100BaseT1), link establishment
+ requires that one device is configured as **master** and the other as
+ **slave**. A mismatch in this master-slave configuration can prevent the link
+ from being established. However, **1000BaseT** also supports configurable
+ master/slave roles and can face similar issues.
+
+- **Role Preference in 1000BaseT**: The **1000BaseT** specification allows link
+ partners to negotiate master-slave roles or role preferences during
+ autonegotiation. Some PHYs have hardware limitations or bugs that prevent
+ them from functioning properly in certain roles. In such cases, drivers may
+ force these PHYs into a specific role (e.g., **forced master** or **forced
+ slave**) or try a weaker option by setting preferences. If both link partners
+ have the same issue and are forced into the same mode (e.g., both forced into
+ master mode), they will not be able to establish a link.
+
+- **Next Steps**: Ensure that one side is configured as **master** and the
+ other as **slave** to avoid this issue, particularly when hardware
+ limitations are involved, or try the weaker **preferred** option instead of
+ **forced**. Check for any driver-related restrictions or forced modes.
+
+- **Command to force master/slave mode**:
+
+ .. code-block:: bash
+
+ ethtool -s <interface> master-slave forced-master
+
+ or:
+
+ .. code-block:: bash
+
+ ethtool -s <interface> master-slave forced-master speed 1000 duplex full autoneg off
+
+
+- **Check the current master/slave status**:
+
+ .. code-block:: bash
+
+ ethtool <interface>
+
+ Example Output:
+
+ .. code-block:: bash
+
+ master-slave cfg: forced-master
+ master-slave status: master
+
+- **Hardware Bugs and Driver Forcing**: If a known hardware issue forces the
+ PHY into a specific mode, it’s essential to check the driver source code or
+ hardware documentation for details. Ensure that the roles are compatible
+ across both link partners, and if both PHYs are forced into the same mode,
+ adjust one side accordingly to resolve the mismatch.
+
+Monitor Link Resets and Speed Drops
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the link is unstable, showing frequent resets or speed drops, this may
+indicate issues with the cable, PHY configuration, or environmental factors.
+While there is still no completely unified way in Linux to directly monitor
+downshift events or link speed changes via user space tools, both the Linux
+kernel logs and `ethtool` can provide valuable insights, especially if the
+driver supports reporting such events.
+
+- **Monitor Kernel Logs for Link Resets and Speed Drops**:
+
+ - The Linux kernel will print link status changes, including downshift
+ events, in the system logs. These messages typically include speed changes,
+ duplex mode, and downshifted link speed (if the driver supports it).
+
+ - **Command to monitor kernel logs in real-time:**
+
+ .. code-block:: bash
+
+ dmesg -w | grep "Link is Up\|Link is Down"
+
+ - Example Output (if a downshift occurs):
+
+ .. code-block:: bash
+
+ eth0: Link is Up - 100Mbps/Full (downshifted) - flow control rx/tx
+ eth0: Link is Down
+
+ This indicates that the link has been established but has downshifted from
+ a higher speed.
+
+ - **Note**: Not all drivers or PHYs support downshift reporting, so you may
+ not see this information for all devices.
+
+- **Monitor Link Down Events Using `ethtool`**:
+
+ - Starting with the latest kernel and `ethtool` versions, you can track
+ **Link Down Events** using the `ethtool -I` command. This will provide
+ counters for link drops, helping to diagnose link instability issues if
+ supported by the driver.
+
+ - **Command to monitor link down events:**
+
+ .. code-block:: bash
+
+ ethtool -I <interface>
+
+ - Example Output (if supported):
+
+ .. code-block:: bash
+
+ PSE attributes for eth1:
+ Link Down Events: 5
+
+ This indicates that the link has dropped 5 times. Frequent link down events
+ may indicate cable or environmental issues that require further
+ investigation.
+
+- **Check Link Status and Speed**:
+
+ - Even though downshift counts or events are not easily tracked, you can
+ still use `ethtool` to manually check the current link speed and status.
+
+ - **Command:** `ethtool <interface>`
+
+ - **Expected Output:**
+
+ .. code-block:: bash
+
+ Speed: 1000Mb/s
+ Duplex: Full
+ Auto-negotiation: on
+ Link detected: yes
+
+ Any inconsistencies in the expected speed or duplex setting could indicate
+ an issue.
+
+- **Disable Energy-Efficient Ethernet (EEE) for Diagnostics**:
+
+ - **EEE** (Energy-Efficient Ethernet) can be a source of link instability due
+ to transitions in and out of low-power states. For diagnostic purposes, it
+ may be useful to **temporarily** disable EEE to determine if it is
+ contributing to link instability. This is **not a generic recommendation**
+ for disabling power management.
+
+ - **Next Steps**: Disable EEE and monitor if the link becomes stable. If
+ disabling EEE resolves the issue, report the bug so that the driver can be
+ fixed.
+
+ - **Command:**
+
+ .. code-block:: bash
+
+ ethtool --set-eee <interface> eee off
+
+ - **Important**: If disabling EEE resolves the instability, the issue should
+ be reported to the maintainers as a bug, and the driver should be corrected
+ to handle EEE properly without causing instability. Disabling EEE
+ permanently should not be seen as a solution.
+
+- **Monitor Error Counters**:
+
+ - While some NIC drivers and PHYs provide error counters, there is no unified
+ set of PHY-specific counters across all hardware. Additionally, not all
+ PHYs provide useful information related to errors like CRC errors, frame
+ drops, or link flaps. Therefore, this step is dependent on the specific
+ hardware and driver support.
+
+ - **Next Steps**: Use `ethtool -S <interface>` to check if your driver
+ provides useful error counters. In some cases, counters may provide
+ information about errors like link flaps or physical layer problems (e.g.,
+ excessive CRC errors), but results can vary significantly depending on the
+ PHY.
+
+ - **Command:** `ethtool -S <interface>`
+
+ - **Example Output (if supported)**:
+
+ .. code-block:: bash
+
+ rx_crc_errors: 123
+ tx_errors: 45
+ rx_frame_errors: 78
+
+ - **Note**: If no meaningful error counters are available or if counters are
+ not supported, you may need to rely on physical inspections (e.g., cable
+ condition) or kernel log messages (e.g., link up/down events) to further
+ diagnose the issue.
+
+When All Else Fails...
+~~~~~~~~~~~~~~~~~~~~~~
+
+So you've checked the cables, monitored the logs, disabled EEE, and still...
+nothing? Don’t worry, you’re not alone. Sometimes, Ethernet gremlins just don’t
+want to cooperate.
+
+But before you throw in the towel (or the Ethernet cable), take a deep breath.
+It’s always possible that:
+
+1. Your PHY has a unique, undocumented personality.
+
+2. The problem is lying dormant, waiting for just the right moment to magically
+ resolve itself (hey, it happens!).
+
+3. Or, it could be that the ultimate solution simply hasn’t been invented yet.
+
+If none of the above bring you comfort, there’s one final step: contribute! If
+you've uncovered new or unusual issues, or have creative diagnostic methods,
+feel free to share your findings and extend this documentation. Together, we
+can hunt down every elusive network issue - one twisted pair at a time.
+
+Remember: sometimes the solution is just a reboot away, but if not, it’s time to
+dig deeper - or report that bug!
+
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
index 295563e91082..b25926071ece 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -236,6 +236,7 @@ Userspace to kernel:
``ETHTOOL_MSG_MM_GET`` get MAC merge layer state
``ETHTOOL_MSG_MM_SET`` set MAC merge layer parameters
``ETHTOOL_MSG_MODULE_FW_FLASH_ACT`` flash transceiver module firmware
+ ``ETHTOOL_MSG_PHY_GET`` get Ethernet PHY information
===================================== =================================
Kernel to userspace:
@@ -283,6 +284,8 @@ Kernel to userspace:
``ETHTOOL_MSG_PLCA_NTF`` PLCA RS parameters
``ETHTOOL_MSG_MM_GET_REPLY`` MAC merge layer status
``ETHTOOL_MSG_MODULE_FW_FLASH_NTF`` transceiver module flash updates
+ ``ETHTOOL_MSG_PHY_GET_REPLY`` Ethernet PHY information
+ ``ETHTOOL_MSG_PHY_NTF`` Ethernet PHY information change
======================================== =================================
``GET`` requests are sent by userspace applications to retrieve device
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index 803dfc1efb75..46c178e564b3 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -14,6 +14,7 @@ Contents:
can
can_ucan_protocol
device_drivers/index
+ diagnostic/index
dsa/index
devlink/index
caif/index
diff --git a/Documentation/networking/j1939.rst b/Documentation/networking/j1939.rst
index e4bd7aa1f5aa..544bad175aae 100644
--- a/Documentation/networking/j1939.rst
+++ b/Documentation/networking/j1939.rst
@@ -121,7 +121,7 @@ format, the Group Extension is set in the PS-field.
On the other hand, when using PDU1 format, the PS-field contains a so-called
Destination Address, which is _not_ part of the PGN. When communicating a PGN
-from user space to kernel (or vice versa) and PDU2 format is used, the PS-field
+from user space to kernel (or vice versa) and PDU1 format is used, the PS-field
of the PGN shall be set to zero. The Destination Address shall be set
elsewhere.
diff --git a/Documentation/networking/kapi.rst b/Documentation/networking/kapi.rst
index ea55f462cefa..98682b9a13ee 100644
--- a/Documentation/networking/kapi.rst
+++ b/Documentation/networking/kapi.rst
@@ -104,6 +104,9 @@ Driver Support
.. kernel-doc:: include/linux/netdevice.h
:internal:
+.. kernel-doc:: include/net/net_shaper.h
+ :internal:
+
PHY Support
-----------
diff --git a/Documentation/networking/napi.rst b/Documentation/networking/napi.rst
index dfa5d549be9c..02720dd71a76 100644
--- a/Documentation/networking/napi.rst
+++ b/Documentation/networking/napi.rst
@@ -192,6 +192,33 @@ is reused to control the delay of the timer, while
``napi_defer_hard_irqs`` controls the number of consecutive empty polls
before NAPI gives up and goes back to using hardware IRQs.
+The above parameters can also be set on a per-NAPI basis using netlink via
+netdev-genl. When used with netlink and configured on a per-NAPI basis, the
+parameters mentioned above use hyphens instead of underscores:
+``gro-flush-timeout`` and ``napi-defer-hard-irqs``.
+
+Per-NAPI configuration can be done programmatically in a user application
+or by using a script included in the kernel source tree:
+``tools/net/ynl/cli.py``.
+
+For example, using the script:
+
+.. code-block:: bash
+
+ $ kernel-source/tools/net/ynl/cli.py \
+ --spec Documentation/netlink/specs/netdev.yaml \
+ --do napi-set \
+ --json='{"id": 345,
+ "defer-hard-irqs": 111,
+ "gro-flush-timeout": 11111}'
+
+Similarly, the parameter ``irq-suspend-timeout`` can be set using netlink
+via netdev-genl. There is no global sysfs parameter for this value.
+
+``irq-suspend-timeout`` is used to determine how long an application can
+completely suspend IRQs. It is used in combination with SO_PREFER_BUSY_POLL,
+which can be set on a per-epoll context basis with ``EPIOCSPARAMS`` ioctl.
+
.. _poll:
Busy polling
@@ -207,6 +234,46 @@ selected sockets or using the global ``net.core.busy_poll`` and
``net.core.busy_read`` sysctls. An io_uring API for NAPI busy polling
also exists.
+epoll-based busy polling
+------------------------
+
+It is possible to trigger packet processing directly from calls to
+``epoll_wait``. In order to use this feature, a user application must ensure
+all file descriptors which are added to an epoll context have the same NAPI ID.
+
+If the application uses a dedicated acceptor thread, the application can obtain
+the NAPI ID of the incoming connection using SO_INCOMING_NAPI_ID and then
+distribute that file descriptor to a worker thread. The worker thread would add
+the file descriptor to its epoll context. This would ensure each worker thread
+has an epoll context with FDs that have the same NAPI ID.
+
+Alternatively, if the application uses SO_REUSEPORT, a bpf or ebpf program can
+be inserted to distribute incoming connections to threads such that each thread
+is only given incoming connections with the same NAPI ID. Care must be taken to
+carefully handle cases where a system may have multiple NICs.
+
+In order to enable busy polling, there are two choices:
+
+1. ``/proc/sys/net/core/busy_poll`` can be set with a time in useconds to busy
+ loop waiting for events. This is a system-wide setting and will cause all
+ epoll-based applications to busy poll when they call epoll_wait. This may
+ not be desirable as many applications may not have the need to busy poll.
+
+2. Applications using recent kernels can issue an ioctl on the epoll context
+ file descriptor to set (``EPIOCSPARAMS``) or get (``EPIOCGPARAMS``) ``struct
+ epoll_params``:, which user programs can define as follows:
+
+.. code-block:: c
+
+ struct epoll_params {
+ uint32_t busy_poll_usecs;
+ uint16_t busy_poll_budget;
+ uint8_t prefer_busy_poll;
+
+ /* pad the struct to a multiple of 64bits */
+ uint8_t __pad;
+ };
+
IRQ mitigation
---------------
@@ -222,12 +289,111 @@ Such applications can pledge to the kernel that they will perform a busy
polling operation periodically, and the driver should keep the device IRQs
permanently masked. This mode is enabled by using the ``SO_PREFER_BUSY_POLL``
socket option. To avoid system misbehavior the pledge is revoked
-if ``gro_flush_timeout`` passes without any busy poll call.
+if ``gro_flush_timeout`` passes without any busy poll call. For epoll-based
+busy polling applications, the ``prefer_busy_poll`` field of ``struct
+epoll_params`` can be set to 1 and the ``EPIOCSPARAMS`` ioctl can be issued to
+enable this mode. See the above section for more details.
The NAPI budget for busy polling is lower than the default (which makes
sense given the low latency intention of normal busy polling). This is
not the case with IRQ mitigation, however, so the budget can be adjusted
-with the ``SO_BUSY_POLL_BUDGET`` socket option.
+with the ``SO_BUSY_POLL_BUDGET`` socket option. For epoll-based busy polling
+applications, the ``busy_poll_budget`` field can be adjusted to the desired value
+in ``struct epoll_params`` and set on a specific epoll context using the ``EPIOCSPARAMS``
+ioctl. See the above section for more details.
+
+It is important to note that choosing a large value for ``gro_flush_timeout``
+will defer IRQs to allow for better batch processing, but will induce latency
+when the system is not fully loaded. Choosing a small value for
+``gro_flush_timeout`` can cause interference of the user application which is
+attempting to busy poll by device IRQs and softirq processing. This value
+should be chosen carefully with these tradeoffs in mind. epoll-based busy
+polling applications may be able to mitigate how much user processing happens
+by choosing an appropriate value for ``maxevents``.
+
+Users may want to consider an alternate approach, IRQ suspension, to help deal
+with these tradeoffs.
+
+IRQ suspension
+--------------
+
+IRQ suspension is a mechanism wherein device IRQs are masked while epoll
+triggers NAPI packet processing.
+
+While application calls to epoll_wait successfully retrieve events, the kernel will
+defer the IRQ suspension timer. If the kernel does not retrieve any events
+while busy polling (for example, because network traffic levels subsided), IRQ
+suspension is disabled and the IRQ mitigation strategies described above are
+engaged.
+
+This allows users to balance CPU consumption with network processing
+efficiency.
+
+To use this mechanism:
+
+ 1. The per-NAPI config parameter ``irq-suspend-timeout`` should be set to the
+ maximum time (in nanoseconds) the application can have its IRQs
+ suspended. This is done using netlink, as described above. This timeout
+ serves as a safety mechanism to restart IRQ driver interrupt processing if
+ the application has stalled. This value should be chosen so that it covers
+ the amount of time the user application needs to process data from its
+ call to epoll_wait, noting that applications can control how much data
+ they retrieve by setting ``max_events`` when calling epoll_wait.
+
+ 2. The sysfs parameter or per-NAPI config parameters ``gro_flush_timeout``
+ and ``napi_defer_hard_irqs`` can be set to low values. They will be used
+ to defer IRQs after busy poll has found no data.
+
+ 3. The ``prefer_busy_poll`` flag must be set to true. This can be done using
+ the ``EPIOCSPARAMS`` ioctl as described above.
+
+ 4. The application uses epoll as described above to trigger NAPI packet
+ processing.
+
+As mentioned above, as long as subsequent calls to epoll_wait return events to
+userland, the ``irq-suspend-timeout`` is deferred and IRQs are disabled. This
+allows the application to process data without interference.
+
+Once a call to epoll_wait results in no events being found, IRQ suspension is
+automatically disabled and the ``gro_flush_timeout`` and
+``napi_defer_hard_irqs`` mitigation mechanisms take over.
+
+It is expected that ``irq-suspend-timeout`` will be set to a value much larger
+than ``gro_flush_timeout`` as ``irq-suspend-timeout`` should suspend IRQs for
+the duration of one userland processing cycle.
+
+While it is not stricly necessary to use ``napi_defer_hard_irqs`` and
+``gro_flush_timeout`` to use IRQ suspension, their use is strongly
+recommended.
+
+IRQ suspension causes the system to alternate between polling mode and
+irq-driven packet delivery. During busy periods, ``irq-suspend-timeout``
+overrides ``gro_flush_timeout`` and keeps the system busy polling, but when
+epoll finds no events, the setting of ``gro_flush_timeout`` and
+``napi_defer_hard_irqs`` determine the next step.
+
+There are essentially three possible loops for network processing and
+packet delivery:
+
+1) hardirq -> softirq -> napi poll; basic interrupt delivery
+2) timer -> softirq -> napi poll; deferred irq processing
+3) epoll -> busy-poll -> napi poll; busy looping
+
+Loop 2 can take control from Loop 1, if ``gro_flush_timeout`` and
+``napi_defer_hard_irqs`` are set.
+
+If ``gro_flush_timeout`` and ``napi_defer_hard_irqs`` are set, Loops 2
+and 3 "wrestle" with each other for control.
+
+During busy periods, ``irq-suspend-timeout`` is used as timer in Loop 2,
+which essentially tilts network processing in favour of Loop 3.
+
+If ``gro_flush_timeout`` and ``napi_defer_hard_irqs`` are not set, Loop 3
+cannot take control from Loop 1.
+
+Therefore, setting ``gro_flush_timeout`` and ``napi_defer_hard_irqs`` is
+the recommended usage, because otherwise setting ``irq-suspend-timeout``
+might not have any discernible effect.
.. _threaded:
diff --git a/Documentation/networking/net_cachelines/inet_connection_sock.rst b/Documentation/networking/net_cachelines/inet_connection_sock.rst
index 7a911dc95652..4a15627fc93b 100644
--- a/Documentation/networking/net_cachelines/inet_connection_sock.rst
+++ b/Documentation/networking/net_cachelines/inet_connection_sock.rst
@@ -5,46 +5,48 @@
inet_connection_sock struct fast path usage breakdown
=====================================================
+=================================== ====================== =================== =================== ========================================================================================================================================================
Type Name fastpath_tx_access fastpath_rx_access comment
-..struct ..inet_connection_sock
-struct_inet_sock icsk_inet read_mostly read_mostly tcp_init_buffer_space,tcp_init_transfer,tcp_finish_connect,tcp_connect,tcp_send_rcvq,tcp_send_syn_data
-struct_request_sock_queue icsk_accept_queue - -
-struct_inet_bind_bucket icsk_bind_hash read_mostly - tcp_set_state
-struct_inet_bind2_bucket icsk_bind2_hash read_mostly - tcp_set_state,inet_put_port
-unsigned_long icsk_timeout read_mostly - inet_csk_reset_xmit_timer,tcp_connect
-struct_timer_list icsk_retransmit_timer read_mostly - inet_csk_reset_xmit_timer,tcp_connect
-struct_timer_list icsk_delack_timer read_mostly - inet_csk_reset_xmit_timer,tcp_connect
-u32 icsk_rto read_write - tcp_cwnd_validate,tcp_schedule_loss_probe,tcp_connect_init,tcp_connect,tcp_write_xmit,tcp_push_one
-u32 icsk_rto_min - -
-u32 icsk_delack_max - -
-u32 icsk_pmtu_cookie read_write - tcp_sync_mss,tcp_current_mss,tcp_send_syn_data,tcp_connect_init,tcp_connect
-struct_tcp_congestion_ops icsk_ca_ops read_write - tcp_cwnd_validate,tcp_tso_segs,tcp_ca_dst_init,tcp_connect_init,tcp_connect,tcp_write_xmit
-struct_inet_connection_sock_af_ops icsk_af_ops read_mostly - tcp_finish_connect,tcp_send_syn_data,tcp_mtup_init,tcp_mtu_check_reprobe,tcp_mtu_probe,tcp_connect_init,tcp_connect,__tcp_transmit_skb
-struct_tcp_ulp_ops* icsk_ulp_ops - -
-void* icsk_ulp_data - -
-u8:5 icsk_ca_state read_write - tcp_cwnd_application_limited,tcp_set_ca_state,tcp_enter_cwr,tcp_tso_should_defer,tcp_mtu_probe,tcp_schedule_loss_probe,tcp_write_xmit,__tcp_transmit_skb
-u8:1 icsk_ca_initialized read_write - tcp_init_transfer,tcp_init_congestion_control,tcp_init_transfer,tcp_finish_connect,tcp_connect
-u8:1 icsk_ca_setsockopt - -
-u8:1 icsk_ca_dst_locked write_mostly - tcp_ca_dst_init,tcp_connect_init,tcp_connect
-u8 icsk_retransmits write_mostly - tcp_connect_init,tcp_connect
-u8 icsk_pending read_write - inet_csk_reset_xmit_timer,tcp_connect,tcp_check_probe_timer,__tcp_push_pending_frames,tcp_rearm_rto,tcp_event_new_data_sent,tcp_event_new_data_sent
-u8 icsk_backoff write_mostly - tcp_write_queue_purge,tcp_connect_init
-u8 icsk_syn_retries - -
-u8 icsk_probes_out - -
-u16 icsk_ext_hdr_len read_mostly - __tcp_mtu_to_mss,tcp_mtu_to_rss,tcp_mtu_probe,tcp_write_xmit,tcp_mtu_to_mss,
-struct_icsk_ack_u8 pending read_write read_write inet_csk_ack_scheduled,__tcp_cleanup_rbuf,tcp_cleanup_rbuf,inet_csk_clear_xmit_timer,tcp_event_ack-sent,inet_csk_reset_xmit_timer
-struct_icsk_ack_u8 quick read_write write_mostly tcp_dec_quickack_mode,tcp_event_ack_sent,__tcp_transmit_skb,__tcp_select_window,__tcp_cleanup_rbuf
-struct_icsk_ack_u8 pingpong - -
-struct_icsk_ack_u8 retry write_mostly read_write inet_csk_clear_xmit_timer,tcp_rearm_rto,tcp_event_new_data_sent,tcp_write_xmit,__tcp_send_ack,tcp_send_ack,
-struct_icsk_ack_u8 ato read_mostly write_mostly tcp_dec_quickack_mode,tcp_event_ack_sent,__tcp_transmit_skb,__tcp_send_ack,tcp_send_ack
-struct_icsk_ack_unsigned_long timeout read_write read_write inet_csk_reset_xmit_timer,tcp_connect
-struct_icsk_ack_u32 lrcvtime read_write - tcp_finish_connect,tcp_connect,tcp_event_data_sent,__tcp_transmit_skb
-struct_icsk_ack_u16 rcv_mss write_mostly read_mostly __tcp_select_window,__tcp_cleanup_rbuf,tcp_initialize_rcv_mss,tcp_connect_init
-struct_icsk_mtup_int search_high read_write - tcp_mtup_init,tcp_sync_mss,tcp_connect_init,tcp_mtu_check_reprobe,tcp_write_xmit
-struct_icsk_mtup_int search_low read_write - tcp_mtu_probe,tcp_mtu_check_reprobe,tcp_write_xmit,tcp_sync_mss,tcp_connect_init,tcp_mtup_init
-struct_icsk_mtup_u32:31 probe_size read_write - tcp_mtup_init,tcp_connect_init,__tcp_transmit_skb
-struct_icsk_mtup_u32:1 enabled read_write - tcp_mtup_init,tcp_sync_mss,tcp_connect_init,tcp_mtu_probe,tcp_write_xmit
-struct_icsk_mtup_u32 probe_timestamp read_write - tcp_mtup_init,tcp_connect_init,tcp_mtu_check_reprobe,tcp_mtu_probe
-u32 icsk_probes_tstamp - -
-u32 icsk_user_timeout - -
-u64[104/sizeof(u64)] icsk_ca_priv - -
+=================================== ====================== =================== =================== ========================================================================================================================================================
+struct inet_sock icsk_inet read_mostly read_mostly tcp_init_buffer_space,tcp_init_transfer,tcp_finish_connect,tcp_connect,tcp_send_rcvq,tcp_send_syn_data
+struct request_sock_queue icsk_accept_queue
+struct inet_bind_bucket icsk_bind_hash read_mostly tcp_set_state
+struct inet_bind2_bucket icsk_bind2_hash read_mostly tcp_set_state,inet_put_port
+unsigned_long icsk_timeout read_mostly inet_csk_reset_xmit_timer,tcp_connect
+struct timer_list icsk_retransmit_timer read_mostly inet_csk_reset_xmit_timer,tcp_connect
+struct timer_list icsk_delack_timer read_mostly inet_csk_reset_xmit_timer,tcp_connect
+u32 icsk_rto read_write tcp_cwnd_validate,tcp_schedule_loss_probe,tcp_connect_init,tcp_connect,tcp_write_xmit,tcp_push_one
+u32 icsk_rto_min
+u32 icsk_delack_max
+u32 icsk_pmtu_cookie read_write tcp_sync_mss,tcp_current_mss,tcp_send_syn_data,tcp_connect_init,tcp_connect
+struct tcp_congestion_ops icsk_ca_ops read_write tcp_cwnd_validate,tcp_tso_segs,tcp_ca_dst_init,tcp_connect_init,tcp_connect,tcp_write_xmit
+struct inet_connection_sock_af_ops icsk_af_ops read_mostly tcp_finish_connect,tcp_send_syn_data,tcp_mtup_init,tcp_mtu_check_reprobe,tcp_mtu_probe,tcp_connect_init,tcp_connect,__tcp_transmit_skb
+struct tcp_ulp_ops* icsk_ulp_ops
+void* icsk_ulp_data
+u8:5 icsk_ca_state read_write tcp_cwnd_application_limited,tcp_set_ca_state,tcp_enter_cwr,tcp_tso_should_defer,tcp_mtu_probe,tcp_schedule_loss_probe,tcp_write_xmit,__tcp_transmit_skb
+u8:1 icsk_ca_initialized read_write tcp_init_transfer,tcp_init_congestion_control,tcp_init_transfer,tcp_finish_connect,tcp_connect
+u8:1 icsk_ca_setsockopt
+u8:1 icsk_ca_dst_locked write_mostly tcp_ca_dst_init,tcp_connect_init,tcp_connect
+u8 icsk_retransmits write_mostly tcp_connect_init,tcp_connect
+u8 icsk_pending read_write inet_csk_reset_xmit_timer,tcp_connect,tcp_check_probe_timer,__tcp_push_pending_frames,tcp_rearm_rto,tcp_event_new_data_sent,tcp_event_new_data_sent
+u8 icsk_backoff write_mostly tcp_write_queue_purge,tcp_connect_init
+u8 icsk_syn_retries
+u8 icsk_probes_out
+u16 icsk_ext_hdr_len read_mostly __tcp_mtu_to_mss,tcp_mtu_to_rss,tcp_mtu_probe,tcp_write_xmit,tcp_mtu_to_mss,
+struct icsk_ack_u8 pending read_write read_write inet_csk_ack_scheduled,__tcp_cleanup_rbuf,tcp_cleanup_rbuf,inet_csk_clear_xmit_timer,tcp_event_ack-sent,inet_csk_reset_xmit_timer
+struct icsk_ack_u8 quick read_write write_mostly tcp_dec_quickack_mode,tcp_event_ack_sent,__tcp_transmit_skb,__tcp_select_window,__tcp_cleanup_rbuf
+struct icsk_ack_u8 pingpong
+struct icsk_ack_u8 retry write_mostly read_write inet_csk_clear_xmit_timer,tcp_rearm_rto,tcp_event_new_data_sent,tcp_write_xmit,__tcp_send_ack,tcp_send_ack,
+struct icsk_ack_u8 ato read_mostly write_mostly tcp_dec_quickack_mode,tcp_event_ack_sent,__tcp_transmit_skb,__tcp_send_ack,tcp_send_ack
+struct icsk_ack_unsigned_long timeout read_write read_write inet_csk_reset_xmit_timer,tcp_connect
+struct icsk_ack_u32 lrcvtime read_write tcp_finish_connect,tcp_connect,tcp_event_data_sent,__tcp_transmit_skb
+struct icsk_ack_u16 rcv_mss write_mostly read_mostly __tcp_select_window,__tcp_cleanup_rbuf,tcp_initialize_rcv_mss,tcp_connect_init
+struct icsk_mtup_int search_high read_write tcp_mtup_init,tcp_sync_mss,tcp_connect_init,tcp_mtu_check_reprobe,tcp_write_xmit
+struct icsk_mtup_int search_low read_write tcp_mtu_probe,tcp_mtu_check_reprobe,tcp_write_xmit,tcp_sync_mss,tcp_connect_init,tcp_mtup_init
+struct icsk_mtup_u32:31 probe_size read_write tcp_mtup_init,tcp_connect_init,__tcp_transmit_skb
+struct icsk_mtup_u32:1 enabled read_write tcp_mtup_init,tcp_sync_mss,tcp_connect_init,tcp_mtu_probe,tcp_write_xmit
+struct icsk_mtup_u32 probe_timestamp read_write tcp_mtup_init,tcp_connect_init,tcp_mtu_check_reprobe,tcp_mtu_probe
+u32 icsk_probes_tstamp
+u32 icsk_user_timeout
+u64[104/sizeof(u64)] icsk_ca_priv
+=================================== ====================== =================== =================== ========================================================================================================================================================
diff --git a/Documentation/networking/net_cachelines/inet_sock.rst b/Documentation/networking/net_cachelines/inet_sock.rst
index 595d7ef5fc8b..b11bf48fa2b3 100644
--- a/Documentation/networking/net_cachelines/inet_sock.rst
+++ b/Documentation/networking/net_cachelines/inet_sock.rst
@@ -5,40 +5,42 @@
inet_sock struct fast path usage breakdown
==========================================
+======================= ===================== =================== =================== ======================================================================================================
Type Name fastpath_tx_access fastpath_rx_access comment
-..struct ..inet_sock
-struct_sock sk read_mostly read_mostly tcp_init_buffer_space,tcp_init_transfer,tcp_finish_connect,tcp_connect,tcp_send_rcvq,tcp_send_syn_data
-struct_ipv6_pinfo* pinet6 - -
-be16 inet_sport read_mostly - __tcp_transmit_skb
-be32 inet_daddr read_mostly - ip_select_ident_segs
-be32 inet_rcv_saddr - -
-be16 inet_dport read_mostly - __tcp_transmit_skb
-u16 inet_num - -
-be32 inet_saddr - -
-s16 uc_ttl read_mostly - __ip_queue_xmit/ip_select_ttl
-u16 cmsg_flags - -
-struct_ip_options_rcu* inet_opt read_mostly - __ip_queue_xmit
-u16 inet_id read_mostly - ip_select_ident_segs
-u8 tos read_mostly - ip_queue_xmit
-u8 min_ttl - -
-u8 mc_ttl - -
-u8 pmtudisc - -
-u8:1 recverr - -
-u8:1 is_icsk - -
-u8:1 freebind - -
-u8:1 hdrincl - -
-u8:1 mc_loop - -
-u8:1 transparent - -
-u8:1 mc_all - -
-u8:1 nodefrag - -
-u8:1 bind_address_no_port - -
-u8:1 recverr_rfc4884 - -
-u8:1 defer_connect read_mostly - tcp_sendmsg_fastopen
-u8 rcv_tos - -
-u8 convert_csum - -
-int uc_index - -
-int mc_index - -
-be32 mc_addr - -
-struct_ip_mc_socklist* mc_list - -
-struct_inet_cork_full cork read_mostly - __tcp_transmit_skb
-struct local_port_range - -
+======================= ===================== =================== =================== ======================================================================================================
+struct sock sk read_mostly read_mostly tcp_init_buffer_space,tcp_init_transfer,tcp_finish_connect,tcp_connect,tcp_send_rcvq,tcp_send_syn_data
+struct ipv6_pinfo* pinet6
+be16 inet_sport read_mostly __tcp_transmit_skb
+be32 inet_daddr read_mostly ip_select_ident_segs
+be32 inet_rcv_saddr
+be16 inet_dport read_mostly __tcp_transmit_skb
+u16 inet_num
+be32 inet_saddr
+s16 uc_ttl read_mostly __ip_queue_xmit/ip_select_ttl
+u16 cmsg_flags
+struct ip_options_rcu* inet_opt read_mostly __ip_queue_xmit
+u16 inet_id read_mostly ip_select_ident_segs
+u8 tos read_mostly ip_queue_xmit
+u8 min_ttl
+u8 mc_ttl
+u8 pmtudisc
+u8:1 recverr
+u8:1 is_icsk
+u8:1 freebind
+u8:1 hdrincl
+u8:1 mc_loop
+u8:1 transparent
+u8:1 mc_all
+u8:1 nodefrag
+u8:1 bind_address_no_port
+u8:1 recverr_rfc4884
+u8:1 defer_connect read_mostly tcp_sendmsg_fastopen
+u8 rcv_tos
+u8 convert_csum
+int uc_index
+int mc_index
+be32 mc_addr
+struct ip_mc_socklist* mc_list
+struct inet_cork_full cork read_mostly __tcp_transmit_skb
+struct local_port_range
+======================= ===================== =================== =================== ======================================================================================================
diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Documentation/networking/net_cachelines/net_device.rst
index 22b07c814f4a..15e31ece675f 100644
--- a/Documentation/networking/net_cachelines/net_device.rst
+++ b/Documentation/networking/net_cachelines/net_device.rst
@@ -5,181 +5,188 @@
net_device struct fast path usage breakdown
===========================================
-Type Name fastpath_tx_access fastpath_rx_access Comments
-..struct ..net_device
-unsigned_long:32 priv_flags read_mostly - __dev_queue_xmit(tx)
-unsigned_long:1 lltx read_mostly - HARD_TX_LOCK,HARD_TX_TRYLOCK,HARD_TX_UNLOCK(tx)
-char name[16] - -
-struct_netdev_name_node* name_node
-struct_dev_ifalias* ifalias
-unsigned_long mem_end
-unsigned_long mem_start
-unsigned_long base_addr
-unsigned_long state read_mostly read_mostly netif_running(dev)
-struct_list_head dev_list
-struct_list_head napi_list
-struct_list_head unreg_list
-struct_list_head close_list
-struct_list_head ptype_all read_mostly - dev_nit_active(tx)
-struct_list_head ptype_specific read_mostly deliver_ptype_list_skb/__netif_receive_skb_core(rx)
-struct adj_list
-unsigned_int flags read_mostly read_mostly __dev_queue_xmit,__dev_xmit_skb,ip6_output,__ip6_finish_output(tx);ip6_rcv_core(rx)
-xdp_features_t xdp_features
-struct_net_device_ops* netdev_ops read_mostly - netdev_core_pick_tx,netdev_start_xmit(tx)
-struct_xdp_metadata_ops* xdp_metadata_ops
-int ifindex - read_mostly ip6_rcv_core
-unsigned_short gflags
-unsigned_short hard_header_len read_mostly read_mostly ip6_xmit(tx);gro_list_prepare(rx)
-unsigned_int mtu read_mostly - ip_finish_output2
-unsigned_short needed_headroom read_mostly - LL_RESERVED_SPACE/ip_finish_output2
-unsigned_short needed_tailroom
-netdev_features_t features read_mostly read_mostly HARD_TX_LOCK,netif_skb_features,sk_setup_caps(tx);netif_elide_gro(rx)
-netdev_features_t hw_features
-netdev_features_t wanted_features
-netdev_features_t vlan_features
-netdev_features_t hw_enc_features - - netif_skb_features
-netdev_features_t mpls_features
-netdev_features_t gso_partial_features read_mostly gso_features_check
-unsigned_int min_mtu
-unsigned_int max_mtu
-unsigned_short type
-unsigned_char min_header_len
-unsigned_char name_assign_type
-int group
-struct_net_device_stats stats
-struct_net_device_core_stats* core_stats
-atomic_t carrier_up_count
-atomic_t carrier_down_count
-struct_iw_handler_def* wireless_handlers
-struct_iw_public_data* wireless_data
-struct_ethtool_ops* ethtool_ops
-struct_l3mdev_ops* l3mdev_ops
-struct_ndisc_ops* ndisc_ops
-struct_xfrmdev_ops* xfrmdev_ops
-struct_tlsdev_ops* tlsdev_ops
-struct_header_ops* header_ops read_mostly - ip_finish_output2,ip6_finish_output2(tx)
-unsigned_char operstate
-unsigned_char link_mode
-unsigned_char if_port
-unsigned_char dma
-unsigned_char perm_addr[32]
-unsigned_char addr_assign_type
-unsigned_char addr_len
-unsigned_char upper_level
-unsigned_char lower_level
-unsigned_short neigh_priv_len
-unsigned_short padded
-unsigned_short dev_id
-unsigned_short dev_port
-spinlock_t addr_list_lock
-int irq
-struct_netdev_hw_addr_list uc
-struct_netdev_hw_addr_list mc
-struct_netdev_hw_addr_list dev_addrs
-struct_kset* queues_kset
-struct_list_head unlink_list
-unsigned_int promiscuity
-unsigned_int allmulti
-bool uc_promisc
-unsigned_char nested_level
-struct_in_device* ip_ptr read_mostly read_mostly __in_dev_get
-struct_inet6_dev* ip6_ptr read_mostly read_mostly __in6_dev_get
-struct_vlan_info* vlan_info
-struct_dsa_port* dsa_ptr
-struct_tipc_bearer* tipc_ptr
-void* atalk_ptr
-void* ax25_ptr
-struct_wireless_dev* ieee80211_ptr
-struct_wpan_dev* ieee802154_ptr
-struct_mpls_dev* mpls_ptr
-struct_mctp_dev* mctp_ptr
-unsigned_char* dev_addr
-struct_netdev_queue* _rx read_mostly - netdev_get_rx_queue(rx)
-unsigned_int num_rx_queues
-unsigned_int real_num_rx_queues - read_mostly get_rps_cpu
-struct_bpf_prog* xdp_prog - read_mostly netif_elide_gro()
-unsigned_long gro_flush_timeout - read_mostly napi_complete_done
-u32 napi_defer_hard_irqs - read_mostly napi_complete_done
-unsigned_int gro_max_size - read_mostly skb_gro_receive
-unsigned_int gro_ipv4_max_size - read_mostly skb_gro_receive
-rx_handler_func_t* rx_handler read_mostly - __netif_receive_skb_core
-void* rx_handler_data read_mostly -
-struct_netdev_queue* ingress_queue read_mostly -
-struct_bpf_mprog_entry tcx_ingress - read_mostly sch_handle_ingress
-struct_nf_hook_entries* nf_hooks_ingress
-unsigned_char broadcast[32]
-struct_cpu_rmap* rx_cpu_rmap
-struct_hlist_node index_hlist
-struct_netdev_queue* _tx read_mostly - netdev_get_tx_queue(tx)
-unsigned_int num_tx_queues - -
-unsigned_int real_num_tx_queues read_mostly - skb_tx_hash,netdev_core_pick_tx(tx)
-unsigned_int tx_queue_len
-spinlock_t tx_global_lock
-struct_xdp_dev_bulk_queue__percpu* xdp_bulkq
-struct_xps_dev_maps* xps_maps[2] read_mostly - __netif_set_xps_queue
-struct_bpf_mprog_entry tcx_egress read_mostly - sch_handle_egress
-struct_nf_hook_entries* nf_hooks_egress read_mostly -
-struct_hlist_head qdisc_hash[16]
-struct_timer_list watchdog_timer
-int watchdog_timeo
-u32 proto_down_reason
-struct_list_head todo_list
-int__percpu* pcpu_refcnt
-refcount_t dev_refcnt
-struct_ref_tracker_dir refcnt_tracker
-struct_list_head link_watch_list
-enum:8 reg_state
-bool dismantle
-enum:16 rtnl_link_state
-bool needs_free_netdev
-void*priv_destructor struct_net_device
-struct_netpoll_info* npinfo - read_mostly napi_poll/napi_poll_lock
-possible_net_t nd_net - read_mostly (dev_net)napi_busy_loop,tcp_v(4/6)_rcv,ip(v6)_rcv,ip(6)_input,ip(6)_input_finish
-void* ml_priv
-enum_netdev_ml_priv_type ml_priv_type
-struct_pcpu_lstats__percpu* lstats read_mostly dev_lstats_add()
-struct_pcpu_sw_netstats__percpu* tstats read_mostly dev_sw_netstats_tx_add()
-struct_pcpu_dstats__percpu* dstats
-struct_garp_port* garp_port
-struct_mrp_port* mrp_port
-struct_dm_hw_stat_delta* dm_private
-struct_device dev - -
-struct_attribute_group* sysfs_groups[4]
-struct_attribute_group* sysfs_rx_queue_group
-struct_rtnl_link_ops* rtnl_link_ops
-unsigned_int gso_max_size read_mostly - sk_dst_gso_max_size
-unsigned_int tso_max_size
-u16 gso_max_segs read_mostly - gso_max_segs
-u16 tso_max_segs
-unsigned_int gso_ipv4_max_size read_mostly - sk_dst_gso_max_size
-struct_dcbnl_rtnl_ops* dcbnl_ops
-s16 num_tc read_mostly - skb_tx_hash
-struct_netdev_tc_txq tc_to_txq[16] read_mostly - skb_tx_hash
-u8 prio_tc_map[16]
-unsigned_int fcoe_ddp_xid
-struct_netprio_map* priomap
-struct_phy_device* phydev
-struct_sfp_bus* sfp_bus
-struct_lock_class_key* qdisc_tx_busylock
-bool proto_down
-unsigned:1 wol_enabled
-unsigned:1 threaded - - napi_poll(napi_enable,dev_set_threaded)
-unsigned_long:1 see_all_hwtstamp_requests
-unsigned_long:1 change_proto_down
-unsigned_long:1 netns_local
-unsigned_long:1 fcoe_mtu
-struct_list_head net_notifier_list
-struct_macsec_ops* macsec_ops
-struct_udp_tunnel_nic_info* udp_tunnel_nic_info
-struct_udp_tunnel_nic* udp_tunnel_nic
-unsigned_int xdp_zc_max_segs
-struct_bpf_xdp_entity xdp_state[3]
-u8 dev_addr_shadow[32]
-netdevice_tracker linkwatch_dev_tracker
-netdevice_tracker watchdog_dev_tracker
-netdevice_tracker dev_registered_tracker
-struct_rtnl_hw_stats64* offload_xstats_l3
-struct_devlink_port* devlink_port
-struct_dpll_pin* dpll_pin
+=================================== =========================== =================== =================== ===================================================================================
+Type Name fastpath_tx_access fastpath_rx_access Comments
+=================================== =========================== =================== =================== ===================================================================================
+unsigned_long:32 priv_flags read_mostly __dev_queue_xmit(tx)
+unsigned_long:1 lltx read_mostly HARD_TX_LOCK,HARD_TX_TRYLOCK,HARD_TX_UNLOCK(tx)
+char name[16]
+struct netdev_name_node* name_node
+struct dev_ifalias* ifalias
+unsigned_long mem_end
+unsigned_long mem_start
+unsigned_long base_addr
+unsigned_long state read_mostly read_mostly netif_running(dev)
+struct list_head dev_list
+struct list_head napi_list
+struct list_head unreg_list
+struct list_head close_list
+struct list_head ptype_all read_mostly dev_nit_active(tx)
+struct list_head ptype_specific read_mostly deliver_ptype_list_skb/__netif_receive_skb_core(rx)
+struct adj_list
+unsigned_int flags read_mostly read_mostly __dev_queue_xmit,__dev_xmit_skb,ip6_output,__ip6_finish_output(tx);ip6_rcv_core(rx)
+xdp_features_t xdp_features
+struct net_device_ops* netdev_ops read_mostly netdev_core_pick_tx,netdev_start_xmit(tx)
+struct xdp_metadata_ops* xdp_metadata_ops
+int ifindex read_mostly ip6_rcv_core
+unsigned_short gflags
+unsigned_short hard_header_len read_mostly read_mostly ip6_xmit(tx);gro_list_prepare(rx)
+unsigned_int mtu read_mostly ip_finish_output2
+unsigned_short needed_headroom read_mostly LL_RESERVED_SPACE/ip_finish_output2
+unsigned_short needed_tailroom
+netdev_features_t features read_mostly read_mostly HARD_TX_LOCK,netif_skb_features,sk_setup_caps(tx);netif_elide_gro(rx)
+netdev_features_t hw_features
+netdev_features_t wanted_features
+netdev_features_t vlan_features
+netdev_features_t hw_enc_features netif_skb_features
+netdev_features_t mpls_features
+netdev_features_t gso_partial_features read_mostly gso_features_check
+unsigned_int min_mtu
+unsigned_int max_mtu
+unsigned_short type
+unsigned_char min_header_len
+unsigned_char name_assign_type
+int group
+struct net_device_stats stats
+struct net_device_core_stats* core_stats
+atomic_t carrier_up_count
+atomic_t carrier_down_count
+struct iw_handler_def* wireless_handlers
+struct ethtool_ops* ethtool_ops
+struct l3mdev_ops* l3mdev_ops
+struct ndisc_ops* ndisc_ops
+struct xfrmdev_ops* xfrmdev_ops
+struct tlsdev_ops* tlsdev_ops
+struct header_ops* header_ops read_mostly ip_finish_output2,ip6_finish_output2(tx)
+unsigned_char operstate
+unsigned_char link_mode
+unsigned_char if_port
+unsigned_char dma
+unsigned_char perm_addr[32]
+unsigned_char addr_assign_type
+unsigned_char addr_len
+unsigned_char upper_level
+unsigned_char lower_level
+unsigned_short neigh_priv_len
+unsigned_short padded
+unsigned_short dev_id
+unsigned_short dev_port
+spinlock_t addr_list_lock
+int irq
+struct netdev_hw_addr_list uc
+struct netdev_hw_addr_list mc
+struct netdev_hw_addr_list dev_addrs
+struct kset* queues_kset
+struct list_head unlink_list
+unsigned_int promiscuity
+unsigned_int allmulti
+bool uc_promisc
+unsigned_char nested_level
+struct in_device* ip_ptr read_mostly read_mostly __in_dev_get
+struct hlist_head fib_nh_head
+struct inet6_dev* ip6_ptr read_mostly read_mostly __in6_dev_get
+struct vlan_info* vlan_info
+struct dsa_port* dsa_ptr
+struct tipc_bearer* tipc_ptr
+void* atalk_ptr
+void* ax25_ptr
+struct wireless_dev* ieee80211_ptr
+struct wpan_dev* ieee802154_ptr
+struct mpls_dev* mpls_ptr
+struct mctp_dev* mctp_ptr
+unsigned_char* dev_addr
+struct netdev_queue* _rx read_mostly netdev_get_rx_queue(rx)
+unsigned_int num_rx_queues
+unsigned_int real_num_rx_queues read_mostly get_rps_cpu
+struct bpf_prog* xdp_prog read_mostly netif_elide_gro()
+unsigned_long gro_flush_timeout read_mostly napi_complete_done
+u32 napi_defer_hard_irqs read_mostly napi_complete_done
+unsigned_int gro_max_size read_mostly skb_gro_receive
+unsigned_int gro_ipv4_max_size read_mostly skb_gro_receive
+rx_handler_func_t* rx_handler read_mostly __netif_receive_skb_core
+void* rx_handler_data read_mostly
+struct netdev_queue* ingress_queue read_mostly
+struct bpf_mprog_entry tcx_ingress read_mostly sch_handle_ingress
+struct nf_hook_entries* nf_hooks_ingress
+unsigned_char broadcast[32]
+struct cpu_rmap* rx_cpu_rmap
+struct hlist_node index_hlist
+struct netdev_queue* _tx read_mostly netdev_get_tx_queue(tx)
+unsigned_int num_tx_queues
+unsigned_int real_num_tx_queues read_mostly skb_tx_hash,netdev_core_pick_tx(tx)
+unsigned_int tx_queue_len
+spinlock_t tx_global_lock
+struct xdp_dev_bulk_queue__percpu* xdp_bulkq
+struct xps_dev_maps* xps_maps[2] read_mostly __netif_set_xps_queue
+struct bpf_mprog_entry tcx_egress read_mostly sch_handle_egress
+struct nf_hook_entries* nf_hooks_egress read_mostly
+struct hlist_head qdisc_hash[16]
+struct timer_list watchdog_timer
+int watchdog_timeo
+u32 proto_down_reason
+struct list_head todo_list
+int__percpu* pcpu_refcnt
+refcount_t dev_refcnt
+struct ref_tracker_dir refcnt_tracker
+struct list_head link_watch_list
+enum:8 reg_state
+bool dismantle
+enum:16 rtnl_link_state
+bool needs_free_netdev
+void*priv_destructor struct net_device
+struct netpoll_info* npinfo read_mostly napi_poll/napi_poll_lock
+possible_net_t nd_net read_mostly (dev_net)napi_busy_loop,tcp_v(4/6)_rcv,ip(v6)_rcv,ip(6)_input,ip(6)_input_finish
+void* ml_priv
+enum_netdev_ml_priv_type ml_priv_type
+struct pcpu_lstats__percpu* lstats read_mostly dev_lstats_add()
+struct pcpu_sw_netstats__percpu* tstats read_mostly dev_sw_netstats_tx_add()
+struct pcpu_dstats__percpu* dstats
+struct garp_port* garp_port
+struct mrp_port* mrp_port
+struct dm_hw_stat_delta* dm_private
+struct device dev
+struct attribute_group* sysfs_groups[4]
+struct attribute_group* sysfs_rx_queue_group
+struct rtnl_link_ops* rtnl_link_ops
+unsigned_int gso_max_size read_mostly sk_dst_gso_max_size
+unsigned_int tso_max_size
+u16 gso_max_segs read_mostly gso_max_segs
+u16 tso_max_segs
+unsigned_int gso_ipv4_max_size read_mostly sk_dst_gso_max_size
+struct dcbnl_rtnl_ops* dcbnl_ops
+s16 num_tc read_mostly skb_tx_hash
+struct netdev_tc_txq tc_to_txq[16] read_mostly skb_tx_hash
+u8 prio_tc_map[16]
+unsigned_int fcoe_ddp_xid
+struct netprio_map* priomap
+struct phy_device* phydev
+struct sfp_bus* sfp_bus
+struct lock_class_key* qdisc_tx_busylock
+bool proto_down
+unsigned:1 wol_enabled
+unsigned:1 threaded napi_poll(napi_enable,dev_set_threaded)
+unsigned_long:1 see_all_hwtstamp_requests
+unsigned_long:1 change_proto_down
+unsigned_long:1 netns_local
+unsigned_long:1 fcoe_mtu
+struct list_head net_notifier_list
+struct macsec_ops* macsec_ops
+struct udp_tunnel_nic_info* udp_tunnel_nic_info
+struct udp_tunnel_nic* udp_tunnel_nic
+unsigned_int xdp_zc_max_segs
+struct bpf_xdp_entity xdp_state[3]
+u8 dev_addr_shadow[32]
+netdevice_tracker linkwatch_dev_tracker
+netdevice_tracker watchdog_dev_tracker
+netdevice_tracker dev_registered_tracker
+struct rtnl_hw_stats64* offload_xstats_l3
+struct devlink_port* devlink_port
+struct dpll_pin* dpll_pin
struct hlist_head page_pools
struct dim_irq_moder* irq_moder
+u64 max_pacing_offload_horizon
+struct_napi_config* napi_config
+unsigned_long gro_flush_timeout
+u32 napi_defer_hard_irqs
+struct hlist_head neighbours[2]
+=================================== =========================== =================== =================== ===================================================================================
diff --git a/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst b/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
index 9b87089a84c6..629da6dc6d74 100644
--- a/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
+++ b/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
@@ -5,154 +5,156 @@
netns_ipv4 struct fast path usage breakdown
===========================================
+=============================== ============================================ =================== =================== =================================================
Type Name fastpath_tx_access fastpath_rx_access comment
-..struct ..netns_ipv4
-struct_inet_timewait_death_row tcp_death_row
-struct_udp_table* udp_table
-struct_ctl_table_header* forw_hdr
-struct_ctl_table_header* frags_hdr
-struct_ctl_table_header* ipv4_hdr
-struct_ctl_table_header* route_hdr
-struct_ctl_table_header* xfrm4_hdr
-struct_ipv4_devconf* devconf_all
-struct_ipv4_devconf* devconf_dflt
-struct_ip_ra_chain ra_chain
-struct_mutex ra_mutex
-struct_fib_rules_ops* rules_ops
-struct_fib_table fib_main
-struct_fib_table fib_default
-unsigned_int fib_rules_require_fldissect
-bool fib_has_custom_rules
-bool fib_has_custom_local_routes
-bool fib_offload_disabled
-atomic_t fib_num_tclassid_users
-struct_hlist_head* fib_table_hash
-struct_sock* fibnl
-struct_sock* mc_autojoin_sk
-struct_inet_peer_base* peers
-struct_fqdir* fqdir
-u8 sysctl_icmp_echo_ignore_all
-u8 sysctl_icmp_echo_enable_probe
-u8 sysctl_icmp_echo_ignore_broadcasts
-u8 sysctl_icmp_ignore_bogus_error_responses
-u8 sysctl_icmp_errors_use_inbound_ifaddr
-int sysctl_icmp_ratelimit
-int sysctl_icmp_ratemask
-u32 ip_rt_min_pmtu - -
-int ip_rt_mtu_expires - -
-int ip_rt_min_advmss - -
-struct_local_ports ip_local_ports - -
-u8 sysctl_tcp_ecn - -
-u8 sysctl_tcp_ecn_fallback - -
-u8 sysctl_ip_default_ttl - - ip4_dst_hoplimit/ip_select_ttl
-u8 sysctl_ip_no_pmtu_disc - -
-u8 sysctl_ip_fwd_use_pmtu read_mostly - ip_dst_mtu_maybe_forward/ip_skb_dst_mtu
-u8 sysctl_ip_fwd_update_priority - - ip_forward
-u8 sysctl_ip_nonlocal_bind - -
-u8 sysctl_ip_autobind_reuse - -
-u8 sysctl_ip_dynaddr - -
-u8 sysctl_ip_early_demux - read_mostly ip(6)_rcv_finish_core
-u8 sysctl_raw_l3mdev_accept - -
-u8 sysctl_tcp_early_demux - read_mostly ip(6)_rcv_finish_core
-u8 sysctl_udp_early_demux
-u8 sysctl_nexthop_compat_mode - -
-u8 sysctl_fwmark_reflect - -
-u8 sysctl_tcp_fwmark_accept - -
-u8 sysctl_tcp_l3mdev_accept - -
-u8 sysctl_tcp_mtu_probing - -
-int sysctl_tcp_mtu_probe_floor - -
-int sysctl_tcp_base_mss - -
-int sysctl_tcp_min_snd_mss read_mostly - __tcp_mtu_to_mss(tcp_write_xmit)
-int sysctl_tcp_probe_threshold - - tcp_mtu_probe(tcp_write_xmit)
-u32 sysctl_tcp_probe_interval - - tcp_mtu_check_reprobe(tcp_write_xmit)
-int sysctl_tcp_keepalive_time - -
-int sysctl_tcp_keepalive_intvl - -
-u8 sysctl_tcp_keepalive_probes - -
-u8 sysctl_tcp_syn_retries - -
-u8 sysctl_tcp_synack_retries - -
-u8 sysctl_tcp_syncookies - - generated_on_syn
-u8 sysctl_tcp_migrate_req - - reuseport
-u8 sysctl_tcp_comp_sack_nr - - __tcp_ack_snd_check
-int sysctl_tcp_reordering - read_mostly tcp_may_raise_cwnd/tcp_cong_control
-u8 sysctl_tcp_retries1 - -
-u8 sysctl_tcp_retries2 - -
-u8 sysctl_tcp_orphan_retries - -
-u8 sysctl_tcp_tw_reuse - - timewait_sock_ops
-int sysctl_tcp_fin_timeout - - TCP_LAST_ACK/tcp_rcv_state_process
-unsigned_int sysctl_tcp_notsent_lowat read_mostly - tcp_notsent_lowat/tcp_stream_memory_free
-u8 sysctl_tcp_sack - - tcp_syn_options
-u8 sysctl_tcp_window_scaling - - tcp_syn_options,tcp_parse_options
-u8 sysctl_tcp_timestamps
-u8 sysctl_tcp_early_retrans read_mostly - tcp_schedule_loss_probe(tcp_write_xmit)
-u8 sysctl_tcp_recovery - - tcp_fastretrans_alert
-u8 sysctl_tcp_thin_linear_timeouts - - tcp_retrans_timer(on_thin_streams)
-u8 sysctl_tcp_slow_start_after_idle - - unlikely(tcp_cwnd_validate-network-not-starved)
-u8 sysctl_tcp_retrans_collapse - -
-u8 sysctl_tcp_stdurg - - unlikely(tcp_check_urg)
-u8 sysctl_tcp_rfc1337 - -
-u8 sysctl_tcp_abort_on_overflow - -
-u8 sysctl_tcp_fack - -
-int sysctl_tcp_max_reordering - - tcp_check_sack_reordering
-int sysctl_tcp_adv_win_scale - - tcp_init_buffer_space
-u8 sysctl_tcp_dsack - - partial_packet_or_retrans_in_tcp_data_queue
-u8 sysctl_tcp_app_win - - tcp_win_from_space
-u8 sysctl_tcp_frto - - tcp_enter_loss
-u8 sysctl_tcp_nometrics_save - - TCP_LAST_ACK/tcp_update_metrics
-u8 sysctl_tcp_no_ssthresh_metrics_save - - TCP_LAST_ACK/tcp_(update/init)_metrics
+=============================== ============================================ =================== =================== =================================================
+struct_inet_timewait_death_row tcp_death_row
+struct_udp_table* udp_table
+struct_ctl_table_header* forw_hdr
+struct_ctl_table_header* frags_hdr
+struct_ctl_table_header* ipv4_hdr
+struct_ctl_table_header* route_hdr
+struct_ctl_table_header* xfrm4_hdr
+struct_ipv4_devconf* devconf_all
+struct_ipv4_devconf* devconf_dflt
+struct_ip_ra_chain ra_chain
+struct_mutex ra_mutex
+struct_fib_rules_ops* rules_ops
+struct_fib_table fib_main
+struct_fib_table fib_default
+unsigned_int fib_rules_require_fldissect
+bool fib_has_custom_rules
+bool fib_has_custom_local_routes
+bool fib_offload_disabled
+atomic_t fib_num_tclassid_users
+struct_hlist_head* fib_table_hash
+struct_sock* fibnl
+struct_sock* mc_autojoin_sk
+struct_inet_peer_base* peers
+struct_fqdir* fqdir
+u8 sysctl_icmp_echo_ignore_all
+u8 sysctl_icmp_echo_enable_probe
+u8 sysctl_icmp_echo_ignore_broadcasts
+u8 sysctl_icmp_ignore_bogus_error_responses
+u8 sysctl_icmp_errors_use_inbound_ifaddr
+int sysctl_icmp_ratelimit
+int sysctl_icmp_ratemask
+u32 ip_rt_min_pmtu
+int ip_rt_mtu_expires
+int ip_rt_min_advmss
+struct_local_ports ip_local_ports
+u8 sysctl_tcp_ecn
+u8 sysctl_tcp_ecn_fallback
+u8 sysctl_ip_default_ttl ip4_dst_hoplimit/ip_select_ttl
+u8 sysctl_ip_no_pmtu_disc
+u8 sysctl_ip_fwd_use_pmtu read_mostly ip_dst_mtu_maybe_forward/ip_skb_dst_mtu
+u8 sysctl_ip_fwd_update_priority ip_forward
+u8 sysctl_ip_nonlocal_bind
+u8 sysctl_ip_autobind_reuse
+u8 sysctl_ip_dynaddr
+u8 sysctl_ip_early_demux read_mostly ip(6)_rcv_finish_core
+u8 sysctl_raw_l3mdev_accept
+u8 sysctl_tcp_early_demux read_mostly ip(6)_rcv_finish_core
+u8 sysctl_udp_early_demux
+u8 sysctl_nexthop_compat_mode
+u8 sysctl_fwmark_reflect
+u8 sysctl_tcp_fwmark_accept
+u8 sysctl_tcp_l3mdev_accept read_mostly __inet6_lookup_established/inet_request_bound_dev_if
+u8 sysctl_tcp_mtu_probing
+int sysctl_tcp_mtu_probe_floor
+int sysctl_tcp_base_mss
+int sysctl_tcp_min_snd_mss read_mostly __tcp_mtu_to_mss(tcp_write_xmit)
+int sysctl_tcp_probe_threshold tcp_mtu_probe(tcp_write_xmit)
+u32 sysctl_tcp_probe_interval tcp_mtu_check_reprobe(tcp_write_xmit)
+int sysctl_tcp_keepalive_time
+int sysctl_tcp_keepalive_intvl
+u8 sysctl_tcp_keepalive_probes
+u8 sysctl_tcp_syn_retries
+u8 sysctl_tcp_synack_retries
+u8 sysctl_tcp_syncookies generated_on_syn
+u8 sysctl_tcp_migrate_req reuseport
+u8 sysctl_tcp_comp_sack_nr __tcp_ack_snd_check
+int sysctl_tcp_reordering read_mostly tcp_may_raise_cwnd/tcp_cong_control
+u8 sysctl_tcp_retries1
+u8 sysctl_tcp_retries2
+u8 sysctl_tcp_orphan_retries
+u8 sysctl_tcp_tw_reuse timewait_sock_ops
+int sysctl_tcp_fin_timeout TCP_LAST_ACK/tcp_rcv_state_process
+unsigned_int sysctl_tcp_notsent_lowat read_mostly tcp_notsent_lowat/tcp_stream_memory_free
+u8 sysctl_tcp_sack tcp_syn_options
+u8 sysctl_tcp_window_scaling tcp_syn_options,tcp_parse_options
+u8 sysctl_tcp_timestamps
+u8 sysctl_tcp_early_retrans read_mostly tcp_schedule_loss_probe(tcp_write_xmit)
+u8 sysctl_tcp_recovery tcp_fastretrans_alert
+u8 sysctl_tcp_thin_linear_timeouts tcp_retrans_timer(on_thin_streams)
+u8 sysctl_tcp_slow_start_after_idle unlikely(tcp_cwnd_validate-network-not-starved)
+u8 sysctl_tcp_retrans_collapse
+u8 sysctl_tcp_stdurg unlikely(tcp_check_urg)
+u8 sysctl_tcp_rfc1337
+u8 sysctl_tcp_abort_on_overflow
+u8 sysctl_tcp_fack
+int sysctl_tcp_max_reordering tcp_check_sack_reordering
+int sysctl_tcp_adv_win_scale tcp_init_buffer_space
+u8 sysctl_tcp_dsack partial_packet_or_retrans_in_tcp_data_queue
+u8 sysctl_tcp_app_win tcp_win_from_space
+u8 sysctl_tcp_frto tcp_enter_loss
+u8 sysctl_tcp_nometrics_save TCP_LAST_ACK/tcp_update_metrics
+u8 sysctl_tcp_no_ssthresh_metrics_save TCP_LAST_ACK/tcp_(update/init)_metrics
u8 sysctl_tcp_moderate_rcvbuf read_mostly read_mostly tcp_tso_should_defer(tx);tcp_rcv_space_adjust(rx)
-u8 sysctl_tcp_tso_win_divisor read_mostly - tcp_tso_should_defer(tcp_write_xmit)
-u8 sysctl_tcp_workaround_signed_windows - - tcp_select_window
-int sysctl_tcp_limit_output_bytes read_mostly - tcp_small_queue_check(tcp_write_xmit)
-int sysctl_tcp_challenge_ack_limit - -
-int sysctl_tcp_min_rtt_wlen read_mostly - tcp_ack_update_rtt
-u8 sysctl_tcp_min_tso_segs - - unlikely(icsk_ca_ops-written)
-u8 sysctl_tcp_tso_rtt_log read_mostly - tcp_tso_autosize
-u8 sysctl_tcp_autocorking read_mostly - tcp_push/tcp_should_autocork
-u8 sysctl_tcp_reflect_tos - - tcp_v(4/6)_send_synack
-int sysctl_tcp_invalid_ratelimit - -
-int sysctl_tcp_pacing_ss_ratio - - default_cong_cont(tcp_update_pacing_rate)
-int sysctl_tcp_pacing_ca_ratio - - default_cong_cont(tcp_update_pacing_rate)
-int sysctl_tcp_wmem[3] read_mostly - tcp_wmem_schedule(sendmsg/sendpage)
-int sysctl_tcp_rmem[3] - read_mostly __tcp_grow_window(tx),tcp_rcv_space_adjust(rx)
-unsigned_int sysctl_tcp_child_ehash_entries
-unsigned_long sysctl_tcp_comp_sack_delay_ns - - __tcp_ack_snd_check
-unsigned_long sysctl_tcp_comp_sack_slack_ns - - __tcp_ack_snd_check
-int sysctl_max_syn_backlog - -
-int sysctl_tcp_fastopen - -
-struct_tcp_congestion_ops tcp_congestion_control - - init_cc
-struct_tcp_fastopen_context tcp_fastopen_ctx - -
-unsigned_int sysctl_tcp_fastopen_blackhole_timeout - -
-atomic_t tfo_active_disable_times - -
-unsigned_long tfo_active_disable_stamp - -
-u32 tcp_challenge_timestamp - -
-u32 tcp_challenge_count - -
-u8 sysctl_tcp_plb_enabled - -
-u8 sysctl_tcp_plb_idle_rehash_rounds - -
-u8 sysctl_tcp_plb_rehash_rounds - -
-u8 sysctl_tcp_plb_suspend_rto_sec - -
-int sysctl_tcp_plb_cong_thresh - -
-int sysctl_udp_wmem_min
-int sysctl_udp_rmem_min
-u8 sysctl_fib_notify_on_flag_change
-u8 sysctl_udp_l3mdev_accept
-u8 sysctl_igmp_llm_reports
-int sysctl_igmp_max_memberships
-int sysctl_igmp_max_msf
-int sysctl_igmp_qrv
-struct_ping_group_range ping_group_range
-atomic_t dev_addr_genid
-unsigned_int sysctl_udp_child_hash_entries
-unsigned_long* sysctl_local_reserved_ports
-int sysctl_ip_prot_sock
-struct_mr_table* mrt
-struct_list_head mr_tables
-struct_fib_rules_ops* mr_rules_ops
-u32 sysctl_fib_multipath_hash_fields
-u8 sysctl_fib_multipath_use_neigh
-u8 sysctl_fib_multipath_hash_policy
-struct_fib_notifier_ops* notifier_ops
-unsigned_int fib_seq
-struct_fib_notifier_ops* ipmr_notifier_ops
-unsigned_int ipmr_seq
-atomic_t rt_genid
-siphash_key_t ip_id_key
+u8 sysctl_tcp_tso_win_divisor read_mostly tcp_tso_should_defer(tcp_write_xmit)
+u8 sysctl_tcp_workaround_signed_windows tcp_select_window
+int sysctl_tcp_limit_output_bytes read_mostly tcp_small_queue_check(tcp_write_xmit)
+int sysctl_tcp_challenge_ack_limit
+int sysctl_tcp_min_rtt_wlen read_mostly tcp_ack_update_rtt
+u8 sysctl_tcp_min_tso_segs unlikely(icsk_ca_ops-written)
+u8 sysctl_tcp_tso_rtt_log read_mostly tcp_tso_autosize
+u8 sysctl_tcp_autocorking read_mostly tcp_push/tcp_should_autocork
+u8 sysctl_tcp_reflect_tos tcp_v(4/6)_send_synack
+int sysctl_tcp_invalid_ratelimit
+int sysctl_tcp_pacing_ss_ratio default_cong_cont(tcp_update_pacing_rate)
+int sysctl_tcp_pacing_ca_ratio default_cong_cont(tcp_update_pacing_rate)
+int sysctl_tcp_wmem[3] read_mostly tcp_wmem_schedule(sendmsg/sendpage)
+int sysctl_tcp_rmem[3] read_mostly __tcp_grow_window(tx),tcp_rcv_space_adjust(rx)
+unsigned_int sysctl_tcp_child_ehash_entries
+unsigned_long sysctl_tcp_comp_sack_delay_ns __tcp_ack_snd_check
+unsigned_long sysctl_tcp_comp_sack_slack_ns __tcp_ack_snd_check
+int sysctl_max_syn_backlog
+int sysctl_tcp_fastopen
+struct_tcp_congestion_ops tcp_congestion_control init_cc
+struct_tcp_fastopen_context tcp_fastopen_ctx
+unsigned_int sysctl_tcp_fastopen_blackhole_timeout
+atomic_t tfo_active_disable_times
+unsigned_long tfo_active_disable_stamp
+u32 tcp_challenge_timestamp
+u32 tcp_challenge_count
+u8 sysctl_tcp_plb_enabled
+u8 sysctl_tcp_plb_idle_rehash_rounds
+u8 sysctl_tcp_plb_rehash_rounds
+u8 sysctl_tcp_plb_suspend_rto_sec
+int sysctl_tcp_plb_cong_thresh
+int sysctl_udp_wmem_min
+int sysctl_udp_rmem_min
+u8 sysctl_fib_notify_on_flag_change
+u8 sysctl_udp_l3mdev_accept
+u8 sysctl_igmp_llm_reports
+int sysctl_igmp_max_memberships
+int sysctl_igmp_max_msf
+int sysctl_igmp_qrv
+struct_ping_group_range ping_group_range
+atomic_t dev_addr_genid
+unsigned_int sysctl_udp_child_hash_entries
+unsigned_long* sysctl_local_reserved_ports
+int sysctl_ip_prot_sock
+struct_mr_table* mrt
+struct_list_head mr_tables
+struct_fib_rules_ops* mr_rules_ops
+u32 sysctl_fib_multipath_hash_fields
+u8 sysctl_fib_multipath_use_neigh
+u8 sysctl_fib_multipath_hash_policy
+struct_fib_notifier_ops* notifier_ops
+unsigned_int fib_seq
+struct_fib_notifier_ops* ipmr_notifier_ops
+unsigned_int ipmr_seq
+atomic_t rt_genid
+siphash_key_t ip_id_key
+=============================== ============================================ =================== =================== =================================================
diff --git a/Documentation/networking/net_cachelines/snmp.rst b/Documentation/networking/net_cachelines/snmp.rst
index 6a071538566c..90ca2d92547d 100644
--- a/Documentation/networking/net_cachelines/snmp.rst
+++ b/Documentation/networking/net_cachelines/snmp.rst
@@ -5,131 +5,133 @@
netns_ipv4 enum fast path usage breakdown
===========================================
+============== ===================================== =================== =================== ==================================================
Type Name fastpath_tx_access fastpath_rx_access comment
-..enum
-unsigned_long LINUX_MIB_TCPKEEPALIVE write_mostly - tcp_keepalive_timer
-unsigned_long LINUX_MIB_DELAYEDACKS write_mostly - tcp_delack_timer_handler,tcp_delack_timer
-unsigned_long LINUX_MIB_DELAYEDACKLOCKED write_mostly - tcp_delack_timer_handler,tcp_delack_timer
-unsigned_long LINUX_MIB_TCPAUTOCORKING write_mostly - tcp_push,tcp_sendmsg_locked
-unsigned_long LINUX_MIB_TCPFROMZEROWINDOWADV write_mostly - tcp_select_window,tcp_transmit-skb
-unsigned_long LINUX_MIB_TCPTOZEROWINDOWADV write_mostly - tcp_select_window,tcp_transmit-skb
-unsigned_long LINUX_MIB_TCPWANTZEROWINDOWADV write_mostly - tcp_select_window,tcp_transmit-skb
-unsigned_long LINUX_MIB_TCPORIGDATASENT write_mostly - tcp_write_xmit
-unsigned_long LINUX_MIB_TCPHPHITS - write_mostly tcp_rcv_established,tcp_v4_do_rcv,tcp_v6_do_rcv
-unsigned_long LINUX_MIB_TCPRCVCOALESCE - write_mostly tcp_try_coalesce,tcp_queue_rcv,tcp_rcv_established
-unsigned_long LINUX_MIB_TCPPUREACKS - write_mostly tcp_ack,tcp_rcv_established
-unsigned_long LINUX_MIB_TCPHPACKS - write_mostly tcp_ack,tcp_rcv_established
-unsigned_long LINUX_MIB_TCPDELIVERED - write_mostly tcp_newly_delivered,tcp_ack,tcp_rcv_established
-unsigned_long LINUX_MIB_SYNCOOKIESSENT
-unsigned_long LINUX_MIB_SYNCOOKIESRECV
-unsigned_long LINUX_MIB_SYNCOOKIESFAILED
-unsigned_long LINUX_MIB_EMBRYONICRSTS
-unsigned_long LINUX_MIB_PRUNECALLED
-unsigned_long LINUX_MIB_RCVPRUNED
-unsigned_long LINUX_MIB_OFOPRUNED
-unsigned_long LINUX_MIB_OUTOFWINDOWICMPS
-unsigned_long LINUX_MIB_LOCKDROPPEDICMPS
-unsigned_long LINUX_MIB_ARPFILTER
-unsigned_long LINUX_MIB_TIMEWAITED
-unsigned_long LINUX_MIB_TIMEWAITRECYCLED
-unsigned_long LINUX_MIB_TIMEWAITKILLED
-unsigned_long LINUX_MIB_PAWSACTIVEREJECTED
-unsigned_long LINUX_MIB_PAWSESTABREJECTED
-unsigned_long LINUX_MIB_DELAYEDACKLOST
-unsigned_long LINUX_MIB_LISTENOVERFLOWS
-unsigned_long LINUX_MIB_LISTENDROPS
-unsigned_long LINUX_MIB_TCPRENORECOVERY
-unsigned_long LINUX_MIB_TCPSACKRECOVERY
-unsigned_long LINUX_MIB_TCPSACKRENEGING
-unsigned_long LINUX_MIB_TCPSACKREORDER
-unsigned_long LINUX_MIB_TCPRENOREORDER
-unsigned_long LINUX_MIB_TCPTSREORDER
-unsigned_long LINUX_MIB_TCPFULLUNDO
-unsigned_long LINUX_MIB_TCPPARTIALUNDO
-unsigned_long LINUX_MIB_TCPDSACKUNDO
-unsigned_long LINUX_MIB_TCPLOSSUNDO
-unsigned_long LINUX_MIB_TCPLOSTRETRANSMIT
-unsigned_long LINUX_MIB_TCPRENOFAILURES
-unsigned_long LINUX_MIB_TCPSACKFAILURES
-unsigned_long LINUX_MIB_TCPLOSSFAILURES
-unsigned_long LINUX_MIB_TCPFASTRETRANS
-unsigned_long LINUX_MIB_TCPSLOWSTARTRETRANS
-unsigned_long LINUX_MIB_TCPTIMEOUTS
-unsigned_long LINUX_MIB_TCPLOSSPROBES
-unsigned_long LINUX_MIB_TCPLOSSPROBERECOVERY
-unsigned_long LINUX_MIB_TCPRENORECOVERYFAIL
-unsigned_long LINUX_MIB_TCPSACKRECOVERYFAIL
-unsigned_long LINUX_MIB_TCPRCVCOLLAPSED
-unsigned_long LINUX_MIB_TCPDSACKOLDSENT
-unsigned_long LINUX_MIB_TCPDSACKOFOSENT
-unsigned_long LINUX_MIB_TCPDSACKRECV
-unsigned_long LINUX_MIB_TCPDSACKOFORECV
-unsigned_long LINUX_MIB_TCPABORTONDATA
-unsigned_long LINUX_MIB_TCPABORTONCLOSE
-unsigned_long LINUX_MIB_TCPABORTONMEMORY
-unsigned_long LINUX_MIB_TCPABORTONTIMEOUT
-unsigned_long LINUX_MIB_TCPABORTONLINGER
-unsigned_long LINUX_MIB_TCPABORTFAILED
-unsigned_long LINUX_MIB_TCPMEMORYPRESSURES
-unsigned_long LINUX_MIB_TCPMEMORYPRESSURESCHRONO
-unsigned_long LINUX_MIB_TCPSACKDISCARD
-unsigned_long LINUX_MIB_TCPDSACKIGNOREDOLD
-unsigned_long LINUX_MIB_TCPDSACKIGNOREDNOUNDO
-unsigned_long LINUX_MIB_TCPSPURIOUSRTOS
-unsigned_long LINUX_MIB_TCPMD5NOTFOUND
-unsigned_long LINUX_MIB_TCPMD5UNEXPECTED
-unsigned_long LINUX_MIB_TCPMD5FAILURE
-unsigned_long LINUX_MIB_SACKSHIFTED
-unsigned_long LINUX_MIB_SACKMERGED
-unsigned_long LINUX_MIB_SACKSHIFTFALLBACK
-unsigned_long LINUX_MIB_TCPBACKLOGDROP
-unsigned_long LINUX_MIB_PFMEMALLOCDROP
-unsigned_long LINUX_MIB_TCPMINTTLDROP
-unsigned_long LINUX_MIB_TCPDEFERACCEPTDROP
-unsigned_long LINUX_MIB_IPRPFILTER
-unsigned_long LINUX_MIB_TCPTIMEWAITOVERFLOW
-unsigned_long LINUX_MIB_TCPREQQFULLDOCOOKIES
-unsigned_long LINUX_MIB_TCPREQQFULLDROP
-unsigned_long LINUX_MIB_TCPRETRANSFAIL
-unsigned_long LINUX_MIB_TCPBACKLOGCOALESCE
-unsigned_long LINUX_MIB_TCPOFOQUEUE
-unsigned_long LINUX_MIB_TCPOFODROP
-unsigned_long LINUX_MIB_TCPOFOMERGE
-unsigned_long LINUX_MIB_TCPCHALLENGEACK
-unsigned_long LINUX_MIB_TCPSYNCHALLENGE
-unsigned_long LINUX_MIB_TCPFASTOPENACTIVE
-unsigned_long LINUX_MIB_TCPFASTOPENACTIVEFAIL
-unsigned_long LINUX_MIB_TCPFASTOPENPASSIVE
-unsigned_long LINUX_MIB_TCPFASTOPENPASSIVEFAIL
-unsigned_long LINUX_MIB_TCPFASTOPENLISTENOVERFLOW
-unsigned_long LINUX_MIB_TCPFASTOPENCOOKIEREQD
-unsigned_long LINUX_MIB_TCPFASTOPENBLACKHOLE
-unsigned_long LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES
-unsigned_long LINUX_MIB_BUSYPOLLRXPACKETS
-unsigned_long LINUX_MIB_TCPSYNRETRANS
-unsigned_long LINUX_MIB_TCPHYSTARTTRAINDETECT
-unsigned_long LINUX_MIB_TCPHYSTARTTRAINCWND
-unsigned_long LINUX_MIB_TCPHYSTARTDELAYDETECT
-unsigned_long LINUX_MIB_TCPHYSTARTDELAYCWND
-unsigned_long LINUX_MIB_TCPACKSKIPPEDSYNRECV
-unsigned_long LINUX_MIB_TCPACKSKIPPEDPAWS
-unsigned_long LINUX_MIB_TCPACKSKIPPEDSEQ
-unsigned_long LINUX_MIB_TCPACKSKIPPEDFINWAIT2
-unsigned_long LINUX_MIB_TCPACKSKIPPEDTIMEWAIT
-unsigned_long LINUX_MIB_TCPACKSKIPPEDCHALLENGE
-unsigned_long LINUX_MIB_TCPWINPROBE
-unsigned_long LINUX_MIB_TCPMTUPFAIL
-unsigned_long LINUX_MIB_TCPMTUPSUCCESS
-unsigned_long LINUX_MIB_TCPDELIVEREDCE
-unsigned_long LINUX_MIB_TCPACKCOMPRESSED
-unsigned_long LINUX_MIB_TCPZEROWINDOWDROP
-unsigned_long LINUX_MIB_TCPRCVQDROP
-unsigned_long LINUX_MIB_TCPWQUEUETOOBIG
-unsigned_long LINUX_MIB_TCPFASTOPENPASSIVEALTKEY
-unsigned_long LINUX_MIB_TCPTIMEOUTREHASH
-unsigned_long LINUX_MIB_TCPDUPLICATEDATAREHASH
-unsigned_long LINUX_MIB_TCPDSACKRECVSEGS
-unsigned_long LINUX_MIB_TCPDSACKIGNOREDDUBIOUS
-unsigned_long LINUX_MIB_TCPMIGRATEREQSUCCESS
-unsigned_long LINUX_MIB_TCPMIGRATEREQFAILURE
-unsigned_long __LINUX_MIB_MAX
+============== ===================================== =================== =================== ==================================================
+unsigned_long LINUX_MIB_TCPKEEPALIVE write_mostly tcp_keepalive_timer
+unsigned_long LINUX_MIB_DELAYEDACKS write_mostly tcp_delack_timer_handler,tcp_delack_timer
+unsigned_long LINUX_MIB_DELAYEDACKLOCKED write_mostly tcp_delack_timer_handler,tcp_delack_timer
+unsigned_long LINUX_MIB_TCPAUTOCORKING write_mostly tcp_push,tcp_sendmsg_locked
+unsigned_long LINUX_MIB_TCPFROMZEROWINDOWADV write_mostly tcp_select_window,tcp_transmit-skb
+unsigned_long LINUX_MIB_TCPTOZEROWINDOWADV write_mostly tcp_select_window,tcp_transmit-skb
+unsigned_long LINUX_MIB_TCPWANTZEROWINDOWADV write_mostly tcp_select_window,tcp_transmit-skb
+unsigned_long LINUX_MIB_TCPORIGDATASENT write_mostly tcp_write_xmit
+unsigned_long LINUX_MIB_TCPHPHITS write_mostly tcp_rcv_established,tcp_v4_do_rcv,tcp_v6_do_rcv
+unsigned_long LINUX_MIB_TCPRCVCOALESCE write_mostly tcp_try_coalesce,tcp_queue_rcv,tcp_rcv_established
+unsigned_long LINUX_MIB_TCPPUREACKS write_mostly tcp_ack,tcp_rcv_established
+unsigned_long LINUX_MIB_TCPHPACKS write_mostly tcp_ack,tcp_rcv_established
+unsigned_long LINUX_MIB_TCPDELIVERED write_mostly tcp_newly_delivered,tcp_ack,tcp_rcv_established
+unsigned_long LINUX_MIB_SYNCOOKIESSENT
+unsigned_long LINUX_MIB_SYNCOOKIESRECV
+unsigned_long LINUX_MIB_SYNCOOKIESFAILED
+unsigned_long LINUX_MIB_EMBRYONICRSTS
+unsigned_long LINUX_MIB_PRUNECALLED
+unsigned_long LINUX_MIB_RCVPRUNED
+unsigned_long LINUX_MIB_OFOPRUNED
+unsigned_long LINUX_MIB_OUTOFWINDOWICMPS
+unsigned_long LINUX_MIB_LOCKDROPPEDICMPS
+unsigned_long LINUX_MIB_ARPFILTER
+unsigned_long LINUX_MIB_TIMEWAITED
+unsigned_long LINUX_MIB_TIMEWAITRECYCLED
+unsigned_long LINUX_MIB_TIMEWAITKILLED
+unsigned_long LINUX_MIB_PAWSACTIVEREJECTED
+unsigned_long LINUX_MIB_PAWSESTABREJECTED
+unsigned_long LINUX_MIB_DELAYEDACKLOST
+unsigned_long LINUX_MIB_LISTENOVERFLOWS
+unsigned_long LINUX_MIB_LISTENDROPS
+unsigned_long LINUX_MIB_TCPRENORECOVERY
+unsigned_long LINUX_MIB_TCPSACKRECOVERY
+unsigned_long LINUX_MIB_TCPSACKRENEGING
+unsigned_long LINUX_MIB_TCPSACKREORDER
+unsigned_long LINUX_MIB_TCPRENOREORDER
+unsigned_long LINUX_MIB_TCPTSREORDER
+unsigned_long LINUX_MIB_TCPFULLUNDO
+unsigned_long LINUX_MIB_TCPPARTIALUNDO
+unsigned_long LINUX_MIB_TCPDSACKUNDO
+unsigned_long LINUX_MIB_TCPLOSSUNDO
+unsigned_long LINUX_MIB_TCPLOSTRETRANSMIT
+unsigned_long LINUX_MIB_TCPRENOFAILURES
+unsigned_long LINUX_MIB_TCPSACKFAILURES
+unsigned_long LINUX_MIB_TCPLOSSFAILURES
+unsigned_long LINUX_MIB_TCPFASTRETRANS
+unsigned_long LINUX_MIB_TCPSLOWSTARTRETRANS
+unsigned_long LINUX_MIB_TCPTIMEOUTS
+unsigned_long LINUX_MIB_TCPLOSSPROBES
+unsigned_long LINUX_MIB_TCPLOSSPROBERECOVERY
+unsigned_long LINUX_MIB_TCPRENORECOVERYFAIL
+unsigned_long LINUX_MIB_TCPSACKRECOVERYFAIL
+unsigned_long LINUX_MIB_TCPRCVCOLLAPSED
+unsigned_long LINUX_MIB_TCPDSACKOLDSENT
+unsigned_long LINUX_MIB_TCPDSACKOFOSENT
+unsigned_long LINUX_MIB_TCPDSACKRECV
+unsigned_long LINUX_MIB_TCPDSACKOFORECV
+unsigned_long LINUX_MIB_TCPABORTONDATA
+unsigned_long LINUX_MIB_TCPABORTONCLOSE
+unsigned_long LINUX_MIB_TCPABORTONMEMORY
+unsigned_long LINUX_MIB_TCPABORTONTIMEOUT
+unsigned_long LINUX_MIB_TCPABORTONLINGER
+unsigned_long LINUX_MIB_TCPABORTFAILED
+unsigned_long LINUX_MIB_TCPMEMORYPRESSURES
+unsigned_long LINUX_MIB_TCPMEMORYPRESSURESCHRONO
+unsigned_long LINUX_MIB_TCPSACKDISCARD
+unsigned_long LINUX_MIB_TCPDSACKIGNOREDOLD
+unsigned_long LINUX_MIB_TCPDSACKIGNOREDNOUNDO
+unsigned_long LINUX_MIB_TCPSPURIOUSRTOS
+unsigned_long LINUX_MIB_TCPMD5NOTFOUND
+unsigned_long LINUX_MIB_TCPMD5UNEXPECTED
+unsigned_long LINUX_MIB_TCPMD5FAILURE
+unsigned_long LINUX_MIB_SACKSHIFTED
+unsigned_long LINUX_MIB_SACKMERGED
+unsigned_long LINUX_MIB_SACKSHIFTFALLBACK
+unsigned_long LINUX_MIB_TCPBACKLOGDROP
+unsigned_long LINUX_MIB_PFMEMALLOCDROP
+unsigned_long LINUX_MIB_TCPMINTTLDROP
+unsigned_long LINUX_MIB_TCPDEFERACCEPTDROP
+unsigned_long LINUX_MIB_IPRPFILTER
+unsigned_long LINUX_MIB_TCPTIMEWAITOVERFLOW
+unsigned_long LINUX_MIB_TCPREQQFULLDOCOOKIES
+unsigned_long LINUX_MIB_TCPREQQFULLDROP
+unsigned_long LINUX_MIB_TCPRETRANSFAIL
+unsigned_long LINUX_MIB_TCPBACKLOGCOALESCE
+unsigned_long LINUX_MIB_TCPOFOQUEUE
+unsigned_long LINUX_MIB_TCPOFODROP
+unsigned_long LINUX_MIB_TCPOFOMERGE
+unsigned_long LINUX_MIB_TCPCHALLENGEACK
+unsigned_long LINUX_MIB_TCPSYNCHALLENGE
+unsigned_long LINUX_MIB_TCPFASTOPENACTIVE
+unsigned_long LINUX_MIB_TCPFASTOPENACTIVEFAIL
+unsigned_long LINUX_MIB_TCPFASTOPENPASSIVE
+unsigned_long LINUX_MIB_TCPFASTOPENPASSIVEFAIL
+unsigned_long LINUX_MIB_TCPFASTOPENLISTENOVERFLOW
+unsigned_long LINUX_MIB_TCPFASTOPENCOOKIEREQD
+unsigned_long LINUX_MIB_TCPFASTOPENBLACKHOLE
+unsigned_long LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES
+unsigned_long LINUX_MIB_BUSYPOLLRXPACKETS
+unsigned_long LINUX_MIB_TCPSYNRETRANS
+unsigned_long LINUX_MIB_TCPHYSTARTTRAINDETECT
+unsigned_long LINUX_MIB_TCPHYSTARTTRAINCWND
+unsigned_long LINUX_MIB_TCPHYSTARTDELAYDETECT
+unsigned_long LINUX_MIB_TCPHYSTARTDELAYCWND
+unsigned_long LINUX_MIB_TCPACKSKIPPEDSYNRECV
+unsigned_long LINUX_MIB_TCPACKSKIPPEDPAWS
+unsigned_long LINUX_MIB_TCPACKSKIPPEDSEQ
+unsigned_long LINUX_MIB_TCPACKSKIPPEDFINWAIT2
+unsigned_long LINUX_MIB_TCPACKSKIPPEDTIMEWAIT
+unsigned_long LINUX_MIB_TCPACKSKIPPEDCHALLENGE
+unsigned_long LINUX_MIB_TCPWINPROBE
+unsigned_long LINUX_MIB_TCPMTUPFAIL
+unsigned_long LINUX_MIB_TCPMTUPSUCCESS
+unsigned_long LINUX_MIB_TCPDELIVEREDCE
+unsigned_long LINUX_MIB_TCPACKCOMPRESSED
+unsigned_long LINUX_MIB_TCPZEROWINDOWDROP
+unsigned_long LINUX_MIB_TCPRCVQDROP
+unsigned_long LINUX_MIB_TCPWQUEUETOOBIG
+unsigned_long LINUX_MIB_TCPFASTOPENPASSIVEALTKEY
+unsigned_long LINUX_MIB_TCPTIMEOUTREHASH
+unsigned_long LINUX_MIB_TCPDUPLICATEDATAREHASH
+unsigned_long LINUX_MIB_TCPDSACKRECVSEGS
+unsigned_long LINUX_MIB_TCPDSACKIGNOREDDUBIOUS
+unsigned_long LINUX_MIB_TCPMIGRATEREQSUCCESS
+unsigned_long LINUX_MIB_TCPMIGRATEREQFAILURE
+unsigned_long __LINUX_MIB_MAX
+============== ===================================== =================== =================== ==================================================
diff --git a/Documentation/networking/net_cachelines/tcp_sock.rst b/Documentation/networking/net_cachelines/tcp_sock.rst
index 1c154cbd1848..1f79765072b1 100644
--- a/Documentation/networking/net_cachelines/tcp_sock.rst
+++ b/Documentation/networking/net_cachelines/tcp_sock.rst
@@ -5,153 +5,155 @@
tcp_sock struct fast path usage breakdown
=========================================
+============================= ======================= =================== =================== ==================================================================================================================================================================================================================
Type Name fastpath_tx_access fastpath_rx_access Comments
-..struct ..tcp_sock
-struct_inet_connection_sock inet_conn
+============================= ======================= =================== =================== ==================================================================================================================================================================================================================
+struct inet_connection_sock inet_conn
u16 tcp_header_len read_mostly read_mostly tcp_bound_to_half_wnd,tcp_current_mss(tx);tcp_rcv_established(rx)
-u16 gso_segs read_mostly - tcp_xmit_size_goal
+u16 gso_segs read_mostly tcp_xmit_size_goal
__be32 pred_flags read_write read_mostly tcp_select_window(tx);tcp_rcv_established(rx)
-u64 bytes_received - read_write tcp_rcv_nxt_update(rx)
-u32 segs_in - read_write tcp_v6_rcv(rx)
-u32 data_segs_in - read_write tcp_v6_rcv(rx)
+u64 bytes_received read_write tcp_rcv_nxt_update(rx)
+u32 segs_in read_write tcp_v6_rcv(rx)
+u32 data_segs_in read_write tcp_v6_rcv(rx)
u32 rcv_nxt read_mostly read_write tcp_cleanup_rbuf,tcp_send_ack,tcp_inq_hint,tcp_transmit_skb,tcp_receive_window(tx);tcp_v6_do_rcv,tcp_rcv_established,tcp_data_queue,tcp_receive_window,tcp_rcv_nxt_update(write)(rx)
-u32 copied_seq - read_mostly tcp_cleanup_rbuf,tcp_rcv_space_adjust,tcp_inq_hint
-u32 rcv_wup - read_write __tcp_cleanup_rbuf,tcp_receive_window,tcp_receive_established
+u32 copied_seq read_mostly tcp_cleanup_rbuf,tcp_rcv_space_adjust,tcp_inq_hint
+u32 rcv_wup read_write __tcp_cleanup_rbuf,tcp_receive_window,tcp_receive_established
u32 snd_nxt read_write read_mostly tcp_rate_check_app_limited,__tcp_transmit_skb,tcp_event_new_data_sent(write)(tx);tcp_rcv_established,tcp_ack,tcp_clean_rtx_queue(rx)
-u32 segs_out read_write - __tcp_transmit_skb
-u32 data_segs_out read_write - __tcp_transmit_skb,tcp_update_skb_after_send
-u64 bytes_sent read_write - __tcp_transmit_skb
-u64 bytes_acked - read_write tcp_snd_una_update/tcp_ack
-u32 dsack_dups
+u32 segs_out read_write __tcp_transmit_skb
+u32 data_segs_out read_write __tcp_transmit_skb,tcp_update_skb_after_send
+u64 bytes_sent read_write __tcp_transmit_skb
+u64 bytes_acked read_write tcp_snd_una_update/tcp_ack
+u32 dsack_dups
u32 snd_una read_mostly read_write tcp_wnd_end,tcp_urg_mode,tcp_minshall_check,tcp_cwnd_validate(tx);tcp_ack,tcp_may_update_window,tcp_clean_rtx_queue(write),tcp_ack_tstamp(rx)
-u32 snd_sml read_write - tcp_minshall_check,tcp_minshall_update
-u32 rcv_tstamp - read_mostly tcp_ack
-u32 lsndtime read_write - tcp_slow_start_after_idle_check,tcp_event_data_sent
-u32 last_oow_ack_time
-u32 compressed_ack_rcv_nxt
+u32 snd_sml read_write tcp_minshall_check,tcp_minshall_update
+u32 rcv_tstamp read_mostly tcp_ack
+u32 lsndtime read_write tcp_slow_start_after_idle_check,tcp_event_data_sent
+u32 last_oow_ack_time
+u32 compressed_ack_rcv_nxt
u32 tsoffset read_mostly read_mostly tcp_established_options(tx);tcp_fast_parse_options(rx)
-struct_list_head tsq_node - -
-struct_list_head tsorted_sent_queue read_write - tcp_update_skb_after_send
-u32 snd_wl1 - read_mostly tcp_may_update_window
+struct list_head tsq_node
+struct list_head tsorted_sent_queue read_write tcp_update_skb_after_send
+u32 snd_wl1 read_mostly tcp_may_update_window
u32 snd_wnd read_mostly read_mostly tcp_wnd_end,tcp_tso_should_defer(tx);tcp_fast_path_on(rx)
-u32 max_window read_mostly - tcp_bound_to_half_wnd,forced_push
+u32 max_window read_mostly tcp_bound_to_half_wnd,forced_push
u32 mss_cache read_mostly read_mostly tcp_rate_check_app_limited,tcp_current_mss,tcp_sync_mss,tcp_sndbuf_expand,tcp_tso_should_defer(tx);tcp_update_pacing_rate,tcp_clean_rtx_queue(rx)
u32 window_clamp read_mostly read_write tcp_rcv_space_adjust,__tcp_select_window
-u32 rcv_ssthresh read_mostly - __tcp_select_window
+u32 rcv_ssthresh read_mostly __tcp_select_window
u8 scaling_ratio read_mostly read_mostly tcp_win_from_space
-struct tcp_rack
-u16 advmss - read_mostly tcp_rcv_space_adjust
-u8 compressed_ack
-u8:2 dup_ack_counter
-u8:1 tlp_retrans
+struct tcp_rack
+u16 advmss read_mostly tcp_rcv_space_adjust
+u8 compressed_ack
+u8:2 dup_ack_counter
+u8:1 tlp_retrans
u8:1 tcp_usec_ts read_mostly read_mostly
-u32 chrono_start read_write - tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
-u32[3] chrono_stat read_write - tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
-u8:2 chrono_type read_write - tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
-u8:1 rate_app_limited - read_write tcp_rate_gen
-u8:1 fastopen_connect
-u8:1 fastopen_no_cookie
-u8:1 is_sack_reneg - read_mostly tcp_skb_entail,tcp_ack
-u8:2 fastopen_client_fail
-u8:4 nonagle read_write - tcp_skb_entail,tcp_push_pending_frames
-u8:1 thin_lto
-u8:1 recvmsg_inq
-u8:1 repair read_mostly - tcp_write_xmit
-u8:1 frto
-u8 repair_queue - -
-u8:2 save_syn
-u8:1 syn_data
-u8:1 syn_fastopen
-u8:1 syn_fastopen_exp
-u8:1 syn_fastopen_ch
-u8:1 syn_data_acked
-u8:1 is_cwnd_limited read_mostly - tcp_cwnd_validate,tcp_is_cwnd_limited
-u32 tlp_high_seq - read_mostly tcp_ack
-u32 tcp_tx_delay
-u64 tcp_wstamp_ns read_write - tcp_pacing_check,tcp_tso_should_defer,tcp_update_skb_after_send
+u32 chrono_start read_write tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
+u32[3] chrono_stat read_write tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
+u8:2 chrono_type read_write tcp_chrono_start/stop(tcp_write_xmit,tcp_cwnd_validate,tcp_send_syn_data)
+u8:1 rate_app_limited read_write tcp_rate_gen
+u8:1 fastopen_connect
+u8:1 fastopen_no_cookie
+u8:1 is_sack_reneg read_mostly tcp_skb_entail,tcp_ack
+u8:2 fastopen_client_fail
+u8:4 nonagle read_write tcp_skb_entail,tcp_push_pending_frames
+u8:1 thin_lto
+u8:1 recvmsg_inq
+u8:1 repair read_mostly tcp_write_xmit
+u8:1 frto
+u8 repair_queue
+u8:2 save_syn
+u8:1 syn_data
+u8:1 syn_fastopen
+u8:1 syn_fastopen_exp
+u8:1 syn_fastopen_ch
+u8:1 syn_data_acked
+u8:1 is_cwnd_limited read_mostly tcp_cwnd_validate,tcp_is_cwnd_limited
+u32 tlp_high_seq read_mostly tcp_ack
+u32 tcp_tx_delay
+u64 tcp_wstamp_ns read_write tcp_pacing_check,tcp_tso_should_defer,tcp_update_skb_after_send
u64 tcp_clock_cache read_write read_write tcp_mstamp_refresh(tcp_write_xmit/tcp_rcv_space_adjust),__tcp_transmit_skb,tcp_tso_should_defer;timer
u64 tcp_mstamp read_write read_write tcp_mstamp_refresh(tcp_write_xmit/tcp_rcv_space_adjust)(tx);tcp_rcv_space_adjust,tcp_rate_gen,tcp_clean_rtx_queue,tcp_ack_update_rtt/tcp_time_stamp(rx);timer
u32 srtt_us read_mostly read_write tcp_tso_should_defer(tx);tcp_update_pacing_rate,__tcp_set_rto,tcp_rtt_estimator(rx)
-u32 mdev_us read_write - tcp_rtt_estimator
-u32 mdev_max_us
-u32 rttvar_us - read_mostly __tcp_set_rto
+u32 mdev_us read_write tcp_rtt_estimator
+u32 mdev_max_us
+u32 rttvar_us read_mostly __tcp_set_rto
u32 rtt_seq read_write tcp_rtt_estimator
-struct_minmax rtt_min - read_mostly tcp_min_rtt/tcp_rate_gen,tcp_min_rtttcp_update_rtt_min
+struct minmax rtt_min read_mostly tcp_min_rtt/tcp_rate_gen,tcp_min_rtttcp_update_rtt_min
u32 packets_out read_write read_write tcp_packets_in_flight(tx/rx);tcp_slow_start_after_idle_check,tcp_nagle_check,tcp_rate_skb_sent,tcp_event_new_data_sent,tcp_cwnd_validate,tcp_write_xmit(tx);tcp_ack,tcp_clean_rtx_queue,tcp_update_pacing_rate(rx)
-u32 retrans_out - read_mostly tcp_packets_in_flight,tcp_rate_check_app_limited
-u32 max_packets_out - read_write tcp_cwnd_validate
-u32 cwnd_usage_seq - read_write tcp_cwnd_validate
-u16 urg_data - read_mostly tcp_fast_path_check
-u8 ecn_flags read_write - tcp_ecn_send
-u8 keepalive_probes
-u32 reordering read_mostly - tcp_sndbuf_expand
-u32 reord_seen
+u32 retrans_out read_mostly tcp_packets_in_flight,tcp_rate_check_app_limited
+u32 max_packets_out read_write tcp_cwnd_validate
+u32 cwnd_usage_seq read_write tcp_cwnd_validate
+u16 urg_data read_mostly tcp_fast_path_check
+u8 ecn_flags read_write tcp_ecn_send
+u8 keepalive_probes
+u32 reordering read_mostly tcp_sndbuf_expand
+u32 reord_seen
u32 snd_up read_write read_mostly tcp_mark_urg,tcp_urg_mode,__tcp_transmit_skb(tx);tcp_clean_rtx_queue(rx)
-struct_tcp_options_received rx_opt read_mostly read_write tcp_established_options(tx);tcp_fast_path_on,tcp_ack_update_window,tcp_is_sack,tcp_data_queue,tcp_rcv_established,tcp_ack_update_rtt(rx)
-u32 snd_ssthresh - read_mostly tcp_update_pacing_rate
+struct tcp_options_received rx_opt read_mostly read_write tcp_established_options(tx);tcp_fast_path_on,tcp_ack_update_window,tcp_is_sack,tcp_data_queue,tcp_rcv_established,tcp_ack_update_rtt(rx)
+u32 snd_ssthresh read_mostly tcp_update_pacing_rate
u32 snd_cwnd read_mostly read_mostly tcp_snd_cwnd,tcp_rate_check_app_limited,tcp_tso_should_defer(tx);tcp_update_pacing_rate
-u32 snd_cwnd_cnt
-u32 snd_cwnd_clamp
-u32 snd_cwnd_used
-u32 snd_cwnd_stamp
-u32 prior_cwnd
-u32 prr_delivered
+u32 snd_cwnd_cnt
+u32 snd_cwnd_clamp
+u32 snd_cwnd_used
+u32 snd_cwnd_stamp
+u32 prior_cwnd
+u32 prr_delivered
u32 prr_out read_mostly read_mostly tcp_rate_skb_sent,tcp_newly_delivered(tx);tcp_ack,tcp_rate_gen,tcp_clean_rtx_queue(rx)
u32 delivered read_mostly read_write tcp_rate_skb_sent, tcp_newly_delivered(tx);tcp_ack, tcp_rate_gen, tcp_clean_rtx_queue (rx)
u32 delivered_ce read_mostly read_write tcp_rate_skb_sent(tx);tcp_rate_gen(rx)
-u32 lost - read_mostly tcp_ack
+u32 lost read_mostly tcp_ack
u32 app_limited read_write read_mostly tcp_rate_check_app_limited,tcp_rate_skb_sent(tx);tcp_rate_gen(rx)
-u64 first_tx_mstamp read_write - tcp_rate_skb_sent
-u64 delivered_mstamp read_write - tcp_rate_skb_sent
-u32 rate_delivered - read_mostly tcp_rate_gen
-u32 rate_interval_us - read_mostly rate_delivered,rate_app_limited
+u64 first_tx_mstamp read_write tcp_rate_skb_sent
+u64 delivered_mstamp read_write tcp_rate_skb_sent
+u32 rate_delivered read_mostly tcp_rate_gen
+u32 rate_interval_us read_mostly rate_delivered,rate_app_limited
u32 rcv_wnd read_write read_mostly tcp_select_window,tcp_receive_window,tcp_fast_path_check
-u32 write_seq read_write - tcp_rate_check_app_limited,tcp_write_queue_empty,tcp_skb_entail,forced_push,tcp_mark_push
-u32 notsent_lowat read_mostly - tcp_stream_memory_free
-u32 pushed_seq read_write - tcp_mark_push,forced_push
+u32 write_seq read_write tcp_rate_check_app_limited,tcp_write_queue_empty,tcp_skb_entail,forced_push,tcp_mark_push
+u32 notsent_lowat read_mostly tcp_stream_memory_free
+u32 pushed_seq read_write tcp_mark_push,forced_push
u32 lost_out read_mostly read_mostly tcp_left_out(tx);tcp_packets_in_flight(tx/rx);tcp_rate_check_app_limited(rx)
u32 sacked_out read_mostly read_mostly tcp_left_out(tx);tcp_packets_in_flight(tx/rx);tcp_clean_rtx_queue(rx)
-struct_hrtimer pacing_timer
-struct_hrtimer compressed_ack_timer
-struct_sk_buff* lost_skb_hint read_mostly tcp_clean_rtx_queue
-struct_sk_buff* retransmit_skb_hint read_mostly - tcp_clean_rtx_queue
-struct_rb_root out_of_order_queue - read_mostly tcp_data_queue,tcp_fast_path_check
-struct_sk_buff* ooo_last_skb
-struct_tcp_sack_block[1] duplicate_sack
-struct_tcp_sack_block[4] selective_acks
-struct_tcp_sack_block[4] recv_sack_cache
-struct_sk_buff* highest_sack read_write - tcp_event_new_data_sent
-int lost_cnt_hint
-u32 prior_ssthresh
-u32 high_seq
-u32 retrans_stamp
-u32 undo_marker
-int undo_retrans
-u64 bytes_retrans
-u32 total_retrans
-u32 rto_stamp
-u16 total_rto
-u16 total_rto_recoveries
-u32 total_rto_time
-u32 urg_seq - -
-unsigned_int keepalive_time
-unsigned_int keepalive_intvl
-int linger2
-u8 bpf_sock_ops_cb_flags
-u8:1 bpf_chg_cc_inprogress
-u16 timeout_rehash
-u32 rcv_ooopack
-u32 rcv_rtt_last_tsecr
-struct rcv_rtt_est - read_write tcp_rcv_space_adjust,tcp_rcv_established
-struct rcvq_space - read_write tcp_rcv_space_adjust
-struct mtu_probe
-u32 plb_rehash
-u32 mtu_info
-bool is_mptcp
-bool smc_hs_congested
-bool syn_smc
-struct_tcp_sock_af_ops* af_specific
-struct_tcp_md5sig_info* md5sig_info
-struct_tcp_fastopen_request* fastopen_req
-struct_request_sock* fastopen_rsk
-struct_saved_syn* saved_syn \ No newline at end of file
+struct hrtimer pacing_timer
+struct hrtimer compressed_ack_timer
+struct sk_buff* lost_skb_hint read_mostly tcp_clean_rtx_queue
+struct sk_buff* retransmit_skb_hint read_mostly tcp_clean_rtx_queue
+struct rb_root out_of_order_queue read_mostly tcp_data_queue,tcp_fast_path_check
+struct sk_buff* ooo_last_skb
+struct tcp_sack_block[1] duplicate_sack
+struct tcp_sack_block[4] selective_acks
+struct tcp_sack_block[4] recv_sack_cache
+struct sk_buff* highest_sack read_write tcp_event_new_data_sent
+int lost_cnt_hint
+u32 prior_ssthresh
+u32 high_seq
+u32 retrans_stamp
+u32 undo_marker
+int undo_retrans
+u64 bytes_retrans
+u32 total_retrans
+u32 rto_stamp
+u16 total_rto
+u16 total_rto_recoveries
+u32 total_rto_time
+u32 urg_seq
+unsigned_int keepalive_time
+unsigned_int keepalive_intvl
+int linger2
+u8 bpf_sock_ops_cb_flags
+u8:1 bpf_chg_cc_inprogress
+u16 timeout_rehash
+u32 rcv_ooopack
+u32 rcv_rtt_last_tsecr
+struct rcv_rtt_est read_write tcp_rcv_space_adjust,tcp_rcv_established
+struct rcvq_space read_write tcp_rcv_space_adjust
+struct mtu_probe
+u32 plb_rehash
+u32 mtu_info
+bool is_mptcp
+bool smc_hs_congested
+bool syn_smc
+struct tcp_sock_af_ops* af_specific
+struct tcp_md5sig_info* md5sig_info
+struct tcp_fastopen_request* fastopen_req
+struct request_sock* fastopen_rsk
+struct saved_syn* saved_syn
+============================= ======================= =================== =================== ==================================================================================================================================================================================================================
diff --git a/Documentation/networking/net_dim.rst b/Documentation/networking/net_dim.rst
index 8908fd7b0a8d..4377998e6826 100644
--- a/Documentation/networking/net_dim.rst
+++ b/Documentation/networking/net_dim.rst
@@ -156,7 +156,7 @@ usage is not complete but it should make the outline of the usage clear.
my_entity->bytes,
&dim_sample);
/* Call net DIM */
- net_dim(&my_entity->dim, dim_sample);
+ net_dim(&my_entity->dim, &dim_sample);
...
}
diff --git a/Documentation/networking/timestamping.rst b/Documentation/networking/timestamping.rst
index 8199e6917671..b37bfbfc7d79 100644
--- a/Documentation/networking/timestamping.rst
+++ b/Documentation/networking/timestamping.rst
@@ -194,6 +194,20 @@ SOF_TIMESTAMPING_OPT_ID:
among all possibly concurrently outstanding timestamp requests for
that socket.
+ The process can optionally override the default generated ID, by
+ passing a specific ID with control message SCM_TS_OPT_ID (not
+ supported for TCP sockets)::
+
+ struct msghdr *msg;
+ ...
+ cmsg = CMSG_FIRSTHDR(msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_TS_OPT_ID;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(__u32));
+ *((__u32 *) CMSG_DATA(cmsg)) = opt_id;
+ err = sendmsg(fd, msg, 0);
+
+
SOF_TIMESTAMPING_OPT_ID_TCP:
Pass this modifier along with SOF_TIMESTAMPING_OPT_ID for new TCP
timestamping applications. SOF_TIMESTAMPING_OPT_ID defines how the
diff --git a/Documentation/networking/tipc.rst b/Documentation/networking/tipc.rst
index ab63d298cca2..9b375b9b9981 100644
--- a/Documentation/networking/tipc.rst
+++ b/Documentation/networking/tipc.rst
@@ -112,7 +112,7 @@ More Information
- How to contribute to TIPC:
-- http://tipc.io/contacts.html
+ http://tipc.io/contacts.html
- More details about TIPC specification:
diff --git a/Documentation/networking/tls-offload.rst b/Documentation/networking/tls-offload.rst
index 5f0dea3d571e..7354d48cdf92 100644
--- a/Documentation/networking/tls-offload.rst
+++ b/Documentation/networking/tls-offload.rst
@@ -51,7 +51,7 @@ and send them to the device for encryption and transmission.
RX
--
-On the receive side if the device handled decryption and authentication
+On the receive side, if the device handled decryption and authentication
successfully, the driver will set the decrypted bit in the associated
:c:type:`struct sk_buff <sk_buff>`. The packets reach the TCP stack and
are handled normally. ``ktls`` is informed when data is queued to the socket
@@ -120,8 +120,9 @@ before installing the connection state in the kernel.
RX
--
-In RX direction local networking stack has little control over the segmentation,
-so the initial records' TCP sequence number may be anywhere inside the segment.
+In the RX direction, the local networking stack has little control over
+segmentation, so the initial records' TCP sequence number may be anywhere
+inside the segment.
Normal operation
================
@@ -138,8 +139,8 @@ There are no guarantees on record length or record segmentation. In particular
segments may start at any point of a record and contain any number of records.
Assuming segments are received in order, the device should be able to perform
crypto operations and authentication regardless of segmentation. For this
-to be possible device has to keep small amount of segment-to-segment state.
-This includes at least:
+to be possible, the device has to keep a small amount of segment-to-segment
+state. This includes at least:
* partial headers (if a segment carried only a part of the TLS header)
* partial data block
@@ -175,12 +176,12 @@ and packet transformation functions) the device validates the Layer 4
checksum and performs a 5-tuple lookup to find any TLS connection the packet
may belong to (technically a 4-tuple
lookup is sufficient - IP addresses and TCP port numbers, as the protocol
-is always TCP). If connection is matched device confirms if the TCP sequence
-number is the expected one and proceeds to TLS handling (record delineation,
-decryption, authentication for each record in the packet). The device leaves
-the record framing unmodified, the stack takes care of record decapsulation.
-Device indicates successful handling of TLS offload in the per-packet context
-(descriptor) passed to the host.
+is always TCP). If the packet is matched to a connection, the device confirms
+if the TCP sequence number is the expected one and proceeds to TLS handling
+(record delineation, decryption, authentication for each record in the packet).
+The device leaves the record framing unmodified, the stack takes care of record
+decapsulation. Device indicates successful handling of TLS offload in the
+per-packet context (descriptor) passed to the host.
Upon reception of a TLS offloaded packet, the driver sets
the :c:member:`decrypted` mark in :c:type:`struct sk_buff <sk_buff>`
@@ -439,7 +440,7 @@ by the driver:
* ``rx_tls_resync_req_end`` - number of times the TLS async resync request
properly ended with providing the HW tracked tcp-seq.
* ``rx_tls_resync_req_skip`` - number of times the TLS async resync request
- procedure was started by not properly ended.
+ procedure was started but not properly ended.
* ``rx_tls_resync_res_ok`` - number of times the TLS resync response call to
the driver was successfully handled.
* ``rx_tls_resync_res_skip`` - number of times the TLS resync response call to
@@ -507,8 +508,8 @@ in packets as seen on the wire.
Transport layer transparency
----------------------------
-The device should not modify any packet headers for the purpose
-of the simplifying TLS offload.
+For the purpose of simplifying TLS offload, the device should not modify any
+packet headers.
The device should not depend on any packet headers beyond what is strictly
necessary for TLS offload.
diff --git a/Documentation/process/5.Posting.rst b/Documentation/process/5.Posting.rst
index de4edd42d5c0..b3eff03ea249 100644
--- a/Documentation/process/5.Posting.rst
+++ b/Documentation/process/5.Posting.rst
@@ -191,11 +191,6 @@ change to a revision control system. It will be followed by:
option to diff will associate function names with changes, making the
resulting patch easier for others to read.
-You should avoid including changes to irrelevant files (those generated by
-the build process, for example, or editor backup files) in the patch. The
-file "dontdiff" in the Documentation directory can help in this regard;
-pass it to diff with the "-X" option.
-
The tags already briefly mentioned above are used to provide insights how
the patch came into being. They are described in detail in the
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
diff --git a/Documentation/process/backporting.rst b/Documentation/process/backporting.rst
index a71480fcf3b4..c42779fbcd33 100644
--- a/Documentation/process/backporting.rst
+++ b/Documentation/process/backporting.rst
@@ -74,7 +74,7 @@ your source tree. Don't forget to cherry-pick with ``-x`` if you want a
written record of where the patch came from!
Note that if you are submitting a patch for stable, the format is
-slightly different; the first line after the subject line needs tobe
+slightly different; the first line after the subject line needs to be
either::
commit <upstream commit> upstream
@@ -553,7 +553,7 @@ Submitting backports to stable
==============================
As the stable maintainers try to cherry-pick mainline fixes onto their
-stable kernels, they may send out emails asking for backports when when
+stable kernels, they may send out emails asking for backports when
encountering conflicts, see e.g.
<https://lore.kernel.org/stable/2023101528-jawed-shelving-071a@gregkh/>.
These emails typically include the exact steps you need to cherry-pick
@@ -563,9 +563,9 @@ One thing to make sure is that your changelog conforms to the expected
format::
<original patch title>
-
+
[ Upstream commit <mainline rev> ]
-
+
<rest of the original changelog>
[ <summary of the conflicts and their resolutions> ]
Signed-off-by: <your name and email>
diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst
index 00f1ed7c59c3..82b5e378eebf 100644
--- a/Documentation/process/changes.rst
+++ b/Documentation/process/changes.rst
@@ -46,7 +46,7 @@ jfsutils 1.1.3 fsck.jfs -V
reiserfsprogs 3.6.3 reiserfsck -V
xfsprogs 2.6.0 xfs_db -V
squashfs-tools 4.0 mksquashfs -version
-btrfs-progs 0.18 btrfsck
+btrfs-progs 0.18 btrfs --version
pcmciautils 004 pccardctl -V
quota-tools 3.09 quota -V
PPP 2.4.0 pppd --version
diff --git a/Documentation/process/code-of-conduct-interpretation.rst b/Documentation/process/code-of-conduct-interpretation.rst
index 66b07f14714c..1d1150954be3 100644
--- a/Documentation/process/code-of-conduct-interpretation.rst
+++ b/Documentation/process/code-of-conduct-interpretation.rst
@@ -156,3 +156,90 @@ overridden decisions including complete and identifiable voting details.
Because how we interpret and enforce the Code of Conduct will evolve over
time, this document will be updated when necessary to reflect any
changes.
+
+Enforcement for Unacceptable Behavior Code of Conduct Violations
+----------------------------------------------------------------
+
+The Code of Conduct committee works to ensure that our community continues
+to be inclusive and fosters diverse discussions and viewpoints, and works
+to improve those characteristics over time. A majority of the reports the
+Code of Conduct Committee receives stem from incorrect understanding regarding
+the development process and maintainers' roles, responsibilities, and their
+right to make decisions on code acceptance. These are resolved through
+clarification of the development process and the scope of the Code of Conduct.
+
+Unacceptable behaviors could interrupt respectful collaboration for a short
+period of time and negatively impact the health of the community longer term.
+Unacceptable behaviors often get resolved when individuals acknowledge their
+behavior and make amends for it in the setting the violation has taken place.
+
+The Code of Conduct Committee receives reports about unacceptable behaviors
+when they don't get resolved through community discussions. The Code of
+Conduct committee takes measures to restore productive and respectful
+collaboration when an unacceptable behavior has negatively impacted that
+relationship.
+
+The Code of Conduct Committee has the obligation to keep the reports and
+reporters' information private. Reports could come from injured parties
+and community members who are observers of unacceptable behaviors. The
+Code of Conduct Committee has the responsibility to investigate and resolve
+these reports, working with all involved parties.
+
+The Code of Conduct Committee works with the individual to bring about
+change in their understanding of the importance to repair the damage caused
+by their behavior to the injured party and the long term negative impact
+on the community.
+
+The goal is to reach a resolution which is agreeable to all parties. If
+working with the individual fails to bring about the desired outcome, the
+Code of Conduct Committee will evaluate other measures such as seeking
+public apology to repair the damage.
+
+Seek public apology for the violation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Code of Conduct Committee publicly calls out the behavior in the
+setting in which the violation has taken place, seeking public apology
+for the violation.
+
+A public apology for the violation is the first step towards rebuilding
+the trust. Trust is essential for the continued success and health of the
+community which operates on trust and respect.
+
+Remedial measures if there is no public apology for the violation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Code of Conduct Committee determines the next course of action to restore
+the healthy collaboration by recommending remedial measure(s) to the TAB for
+approval.
+
+- Ban violator from participating in the kernel development process for
+ a period of up to a full kernel development cycle. The Code of Conduct
+ Committee could require public apology as a condition for lifting the
+ ban.
+
+The scope of the ban for a period of time could include:
+
+ a. denying patch contributions and pull requests
+ b. pausing collaboration with the violator by ignoring their
+ contributions and/or blocking their email account(s)
+ c. restricting their ability to communicate via kernel.org platforms,
+ such as mailing lists and social media sites
+
+Once the TAB approves one or more of the measures outlined in the scope of
+the ban by a two-thirds vote, the Code of Conduct Committee will enforce
+the TAB approved measure(s) in collaboration with the community, maintainers,
+sub-maintainers, and kernel.org administrators.
+
+The Code of Conduct Committee is mindful of the negative impact of seeking
+public apology and instituting ban could have on individuals. It is also
+mindful of the longer term harm to the community that could result from
+not taking action when such serious public violations occur.
+
+The effectiveness of the remedial measure(s) approved by the TAB depends
+on the trust and cooperation from the community, maintainers, sub-maintainers,
+and kernel.org administrators in enforcing them.
+
+The Code of Conduct Committee sincerely hopes that unacceptable behaviors
+that require seeking public apologies continue to be exceedingly rare
+occurrences in the future.
diff --git a/Documentation/process/debugging/driver_development_debugging_guide.rst b/Documentation/process/debugging/driver_development_debugging_guide.rst
new file mode 100644
index 000000000000..aef204094205
--- /dev/null
+++ b/Documentation/process/debugging/driver_development_debugging_guide.rst
@@ -0,0 +1,223 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========================================
+Debugging advice for driver development
+========================================
+
+This document serves as a general starting point and lookup for debugging
+device drivers.
+While this guide focuses on debugging that requires re-compiling the
+module/kernel, the :doc:`userspace debugging guide
+</process/debugging/userspace_debugging_guide>` will guide
+you through tools like dynamic debug, ftrace and other tools useful for
+debugging issues and behavior.
+For general debugging advice, see the :doc:`general advice document
+</process/debugging/index>`.
+
+.. contents::
+ :depth: 3
+
+The following sections show you the available tools.
+
+printk() & friends
+------------------
+
+These are derivatives of printf() with varying destinations and support for
+being dynamically turned on or off, or lack thereof.
+
+Simple printk()
+~~~~~~~~~~~~~~~
+
+The classic, can be used to great effect for quick and dirty development
+of new modules or to extract arbitrary necessary data for troubleshooting.
+
+Prerequisite: ``CONFIG_PRINTK`` (usually enabled by default)
+
+**Pros**:
+
+- No need to learn anything, simple to use
+- Easy to modify exactly to your needs (formatting of the data (See:
+ :doc:`/core-api/printk-formats`), visibility in the log)
+- Can cause delays in the execution of the code (beneficial to confirm whether
+ timing is a factor)
+
+**Cons**:
+
+- Requires rebuilding the kernel/module
+- Can cause delays in the execution of the code (which can cause issues to be
+ not reproducible)
+
+For the full documentation see :doc:`/core-api/printk-basics`
+
+Trace_printk
+~~~~~~~~~~~~
+
+Prerequisite: ``CONFIG_DYNAMIC_FTRACE`` & ``#include <linux/ftrace.h>``
+
+It is a tiny bit less comfortable to use than printk(), because you will have
+to read the messages from the trace file (See: :ref:`read_ftrace_log`
+instead of from the kernel log, but very useful when printk() adds unwanted
+delays into the code execution, causing issues to be flaky or hidden.)
+
+If the processing of this still causes timing issues then you can try
+trace_puts().
+
+For the full Documentation see trace_printk()
+
+dev_dbg
+~~~~~~~
+
+Print statement, which can be targeted by
+:ref:`process/debugging/userspace_debugging_guide:dynamic debug` that contains
+additional information about the device used within the context.
+
+**When is it appropriate to leave a debug print in the code?**
+
+Permanent debug statements have to be useful for a developer to troubleshoot
+driver misbehavior. Judging that is a bit more of an art than a science, but
+some guidelines are in the :ref:`Coding style guidelines
+<process/coding-style:13) printing kernel messages>`. In almost all cases the
+debug statements shouldn't be upstreamed, as a working driver is supposed to be
+silent.
+
+Custom printk
+~~~~~~~~~~~~~
+
+Example::
+
+ #define core_dbg(fmt, arg...) do { \
+ if (core_debug) \
+ printk(KERN_DEBUG pr_fmt("core: " fmt), ## arg); \
+ } while (0)
+
+**When should you do this?**
+
+It is better to just use a pr_debug(), which can later be turned on/off with
+dynamic debug. Additionally, a lot of drivers activate these prints via a
+variable like ``core_debug`` set by a module parameter. However, Module
+parameters `are not recommended anymore
+<https://lore.kernel.org/all/2024032757-surcharge-grime-d3dd@gregkh>`_.
+
+Ftrace
+------
+
+Creating a custom Ftrace tracepoint
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A tracepoint adds a hook into your code that will be called and logged when the
+tracepoint is enabled. This can be used, for example, to trace hitting a
+conditional branch or to dump the internal state at specific points of the code
+flow during a debugging session.
+
+Here is a basic description of :ref:`how to implement new tracepoints
+<trace/tracepoints:usage>`.
+
+For the full event tracing documentation see :doc:`/trace/events`
+
+For the full Ftrace documentation see :doc:`/trace/ftrace`
+
+DebugFS
+-------
+
+Prerequisite: ``CONFIG_DEBUG_FS` & `#include <linux/debugfs.h>``
+
+DebugFS differs from the other approaches of debugging, as it doesn't write
+messages to the kernel log nor add traces to the code. Instead it allows the
+developer to handle a set of files.
+With these files you can either store values of variables or make
+register/memory dumps or you can make these files writable and modify
+values/settings in the driver.
+
+Possible use-cases among others:
+
+- Store register values
+- Keep track of variables
+- Store errors
+- Store settings
+- Toggle a setting like debug on/off
+- Error injection
+
+This is especially useful, when the size of a data dump would be hard to digest
+as part of the general kernel log (for example when dumping raw bitstream data)
+or when you are not interested in all the values all the time, but with the
+possibility to inspect them.
+
+The general idea is:
+
+- Create a directory during probe (``struct dentry *parent =
+ debugfs_create_dir("my_driver", NULL);``)
+- Create a file (``debugfs_create_u32("my_value", 444, parent, &my_variable);``)
+
+ - In this example the file is found in
+ ``/sys/kernel/debug/my_driver/my_value`` (with read permissions for
+ user/group/all)
+ - any read of the file will return the current contents of the variable
+ ``my_variable``
+
+- Clean up the directory when removing the device
+ (``debugfs_remove_recursive(parent);``)
+
+For the full documentation see :doc:`/filesystems/debugfs`.
+
+KASAN, UBSAN, lockdep and other error checkers
+----------------------------------------------
+
+KASAN (Kernel Address Sanitizer)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Prerequisite: ``CONFIG_KASAN``
+
+KASAN is a dynamic memory error detector that helps to find use-after-free and
+out-of-bounds bugs. It uses compile-time instrumentation to check every memory
+access.
+
+For the full documentation see :doc:`/dev-tools/kasan`.
+
+UBSAN (Undefined Behavior Sanitizer)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Prerequisite: ``CONFIG_UBSAN``
+
+UBSAN relies on compiler instrumentation and runtime checks to detect undefined
+behavior. It is designed to find a variety of issues, including signed integer
+overflow, array index out of bounds, and more.
+
+For the full documentation see :doc:`/dev-tools/ubsan`
+
+lockdep (Lock Dependency Validator)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Prerequisite: ``CONFIG_DEBUG_LOCKDEP``
+
+lockdep is a runtime lock dependency validator that detects potential deadlocks
+and other locking-related issues in the kernel.
+It tracks lock acquisitions and releases, building a dependency graph that is
+analyzed for potential deadlocks.
+lockdep is especially useful for validating the correctness of lock ordering in
+the kernel.
+
+PSI (Pressure stall information tracking)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Prerequisite: ``CONFIG_PSI``
+
+PSI is a measurement tool to identify excessive overcommits on hardware
+resources, that can cause performance disruptions or even OOM kills.
+
+device coredump
+---------------
+
+Prerequisite: ``#include <linux/devcoredump.h>``
+
+Provides the infrastructure for a driver to provide arbitrary data to userland.
+It is most often used in conjunction with udev or similar userland application
+to listen for kernel uevents, which indicate that the dump is ready. Udev has
+rules to copy that file somewhere for long-term storage and analysis, as by
+default, the data for the dump is automatically cleaned up after 5 minutes.
+That data is analyzed with driver-specific tools or GDB.
+
+You can find an example implementation at:
+`drivers/media/platform/qcom/venus/core.c
+<https://elixir.bootlin.com/linux/v6.11.6/source/drivers/media/platform/qcom/venus/core.c#L30>`__
+
+**Copyright** ©2024 : Collabora
diff --git a/Documentation/process/debugging/index.rst b/Documentation/process/debugging/index.rst
new file mode 100644
index 000000000000..f6e4a00dfee3
--- /dev/null
+++ b/Documentation/process/debugging/index.rst
@@ -0,0 +1,78 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================================
+Debugging advice for Linux Kernel developers
+============================================
+
+general guides
+--------------
+
+.. toctree::
+ :maxdepth: 1
+
+ driver_development_debugging_guide
+ userspace_debugging_guide
+
+.. only:: subproject and html
+
+subsystem specific guides
+-------------------------
+
+.. toctree::
+ :maxdepth: 1
+
+ media_specific_debugging_guide
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
+
+General debugging advice
+========================
+
+Depending on the issue, a different set of tools is available to track down the
+problem or even to realize whether there is one in the first place.
+
+As a first step you have to figure out what kind of issue you want to debug.
+Depending on the answer, your methodology and choice of tools may vary.
+
+Do I need to debug with limited access?
+---------------------------------------
+
+Do you have limited access to the machine or are you unable to stop the running
+execution?
+
+In this case your debugging capability depends on built-in debugging support of
+provided distribution kernel.
+The :doc:`/process/debugging/userspace_debugging_guide` provides a brief
+overview over a range of possible debugging tools in that situation. You can
+check the capability of your kernel, in most cases, by looking into config file
+within the /boot directory.
+
+Do I have root access to the system?
+------------------------------------
+
+Are you easily able to replace the module in question or to install a new
+kernel?
+
+In that case your range of available tools is a lot bigger, you can find the
+tools in the :doc:`/process/debugging/driver_development_debugging_guide`.
+
+Is timing a factor?
+-------------------
+
+It is important to understand if the problem you want to debug manifests itself
+consistently (i.e. given a set of inputs you always get the same, incorrect
+output), or inconsistently. If it manifests itself inconsistently, some timing
+factor might be at play. If inserting delays into the code does change the
+behavior, then quite likely timing is a factor.
+
+When timing does alter the outcome of the code execution using a simple
+printk() for debugging purposes may not work, a similar alternative is to use
+trace_printk() , which logs the debug messages to the trace file instead of the
+kernel log.
+
+**Copyright** ©2024 : Collabora
diff --git a/Documentation/process/debugging/media_specific_debugging_guide.rst b/Documentation/process/debugging/media_specific_debugging_guide.rst
new file mode 100644
index 000000000000..c5a93bafaf67
--- /dev/null
+++ b/Documentation/process/debugging/media_specific_debugging_guide.rst
@@ -0,0 +1,180 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================================
+Debugging and tracing in the media subsystem
+============================================
+
+This document serves as a starting point and lookup for debugging device
+drivers in the media subsystem and to debug these drivers from userspace.
+
+.. contents::
+ :depth: 3
+
+General debugging advice
+------------------------
+
+For general advice see the :doc:`general advice document
+</process/debugging/index>`.
+
+The following sections show you some of the available tools.
+
+dev_debug module parameter
+--------------------------
+
+Every video device provides a ``dev_debug`` parameter, which allows to get
+further insights into the IOCTLs in the background.::
+
+ # cat /sys/class/video4linux/video3/name
+ rkvdec
+ # echo 0xff > /sys/class/video4linux/video3/dev_debug
+ # dmesg -wH
+ [...] videodev: v4l2_open: video3: open (0)
+ [ +0.000036] video3: VIDIOC_QUERYCAP: driver=rkvdec, card=rkvdec,
+ bus=platform:rkvdec, version=0x00060900, capabilities=0x84204000,
+ device_caps=0x04204000
+
+For the full documentation see :ref:`driver-api/media/v4l2-dev:video device
+debugging`
+
+dev_dbg() / v4l2_dbg()
+----------------------
+
+Two debug print statements, which are specific for devices and for the v4l2
+subsystem, avoid adding these to your final submission unless they have
+long-term value for investigations.
+
+For a general overview please see the
+:ref:`process/debugging/driver_development_debugging_guide:printk() & friends`
+guide.
+
+- Difference between both?
+
+ - v4l2_dbg() utilizes v4l2_printk() under the hood, which further uses
+ printk() directly, thus it cannot be targeted by dynamic debug
+ - dev_dbg() can be targeted by dynamic debug
+ - v4l2_dbg() has a more specific prefix format for the media subsystem, while
+ dev_dbg only highlights the driver name and the location of the log
+
+Dynamic debug
+-------------
+
+A method to trim down the debug output to your needs.
+
+For general advice see the
+:ref:`process/debugging/userspace_debugging_guide:dynamic debug` guide.
+
+Here is one example, that enables all available pr_debug()'s within the file::
+
+ $ alias ddcmd='echo $* > /proc/dynamic_debug/control'
+ $ ddcmd '-p; file v4l2-h264.c +p'
+ $ grep =p /proc/dynamic_debug/control
+ drivers/media/v4l2-core/v4l2-h264.c:372 [v4l2_h264]print_ref_list_b =p
+ "ref_pic_list_b%u (cur_poc %u%c) %s"
+ drivers/media/v4l2-core/v4l2-h264.c:333 [v4l2_h264]print_ref_list_p =p
+ "ref_pic_list_p (cur_poc %u%c) %s\n"
+
+Ftrace
+------
+
+An internal kernel tracer that can trace static predefined events, function
+calls, etc. Very useful for debugging problems without changing the kernel and
+understanding the behavior of subsystems.
+
+For general advice see the
+:ref:`process/debugging/userspace_debugging_guide:ftrace` guide.
+
+DebugFS
+-------
+
+This tool allows you to dump or modify internal values of your driver to files
+in a custom filesystem.
+
+For general advice see the
+:ref:`process/debugging/driver_development_debugging_guide:debugfs` guide.
+
+Perf & alternatives
+-------------------
+
+Tools to measure the various stats on a running system to diagnose issues.
+
+For general advice see the
+:ref:`process/debugging/userspace_debugging_guide:perf & alternatives` guide.
+
+Example for media devices:
+
+Gather statistics data for a decoding job: (This example is on a RK3399 SoC
+with the rkvdec codec driver using the `fluster test suite
+<https://github.com/fluendo/fluster>`__)::
+
+ perf stat -d python3 fluster.py run -d GStreamer-H.264-V4L2SL-Gst1.0 -ts
+ JVT-AVC_V1 -tv AUD_MW_E -j1
+ ...
+ Performance counter stats for 'python3 fluster.py run -d
+ GStreamer-H.264-V4L2SL-Gst1.0 -ts JVT-AVC_V1 -tv AUD_MW_E -j1 -v':
+
+ 7794.23 msec task-clock:u # 0.697 CPUs utilized
+ 0 context-switches:u # 0.000 /sec
+ 0 cpu-migrations:u # 0.000 /sec
+ 11901 page-faults:u # 1.527 K/sec
+ 882671556 cycles:u # 0.113 GHz (95.79%)
+ 711708695 instructions:u # 0.81 insn per cycle (95.79%)
+ 10581935 branches:u # 1.358 M/sec (15.13%)
+ 6871144 branch-misses:u # 64.93% of all branches (95.79%)
+ 281716547 L1-dcache-loads:u # 36.144 M/sec (95.79%)
+ 9019581 L1-dcache-load-misses:u # 3.20% of all L1-dcache accesses (95.79%)
+ <not supported> LLC-loads:u
+ <not supported> LLC-load-misses:u
+
+ 11.180830431 seconds time elapsed
+
+ 1.502318000 seconds user
+ 6.377221000 seconds sys
+
+The availability of events and metrics depends on the system you are running.
+
+Error checking & panic analysis
+-------------------------------
+
+Various Kernel configuration options to enhance error detection of the Linux
+Kernel with the cost of lowering performance.
+
+For general advice see the
+:ref:`process/debugging/driver_development_debugging_guide:kasan, ubsan,
+lockdep and other error checkers` guide.
+
+Driver verification with v4l2-compliance
+----------------------------------------
+
+To verify, that a driver adheres to the v4l2 API, the tool v4l2-compliance is
+used, which is part of the `v4l_utils
+<https://git.linuxtv.org/v4l-utils.git>`__, a suite of userspace tools to work
+with the media subsystem.
+
+To see the detailed media topology (and check it) use::
+
+ v4l2-compliance -M /dev/mediaX --verbose
+
+You can also run a full compliance check for all devices referenced in the
+media topology with::
+
+ v4l2-compliance -m /dev/mediaX
+
+Debugging problems with receiving video
+---------------------------------------
+
+Implementing vidioc_log_status in the driver: this can log the current status
+to the kernel log. It's called by v4l2-ctl --log-status. Very useful for
+debugging problems with receiving video (TV/S-Video/HDMI/etc) since the video
+signal is external (so unpredictable). Less useful with camera sensor inputs
+since you have control over what the camera sensor does.
+
+Usually you can just assign the default::
+
+ .vidioc_log_status = v4l2_ctrl_log_status,
+
+But you can also create your own callback, to create a custom status log.
+
+You can find an example in the cobalt driver
+(`drivers/media/pci/cobalt/cobalt-v4l2.c <https://elixir.bootlin.com/linux/v6.11.6/source/drivers/media/pci/cobalt/cobalt-v4l2.c#L567>`__).
+
+**Copyright** ©2024 : Collabora
diff --git a/Documentation/process/debugging/userspace_debugging_guide.rst b/Documentation/process/debugging/userspace_debugging_guide.rst
new file mode 100644
index 000000000000..db7396261e07
--- /dev/null
+++ b/Documentation/process/debugging/userspace_debugging_guide.rst
@@ -0,0 +1,280 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========================
+Userspace debugging advice
+==========================
+
+This document provides a brief overview of common tools to debug the Linux
+Kernel from userspace.
+For debugging advice aimed at driver developers go :doc:`here
+</process/debugging/driver_development_debugging_guide>`.
+For general debugging advice, see :doc:`general advice document
+</process/debugging/index>`.
+
+.. contents::
+ :depth: 3
+
+The following sections show you the available tools.
+
+Dynamic debug
+-------------
+
+Mechanism to filter what ends up in the kernel log by dis-/en-abling log
+messages.
+
+Prerequisite: ``CONFIG_DYNAMIC_DEBUG``
+
+Dynamic debug is only able to target:
+
+- pr_debug()
+- dev_dbg()
+- print_hex_dump_debug()
+- print_hex_dump_bytes()
+
+Therefore the usability of this tool is, as of now, quite limited as there is
+no uniform rule for adding debug prints to the codebase, resulting in a variety
+of ways these prints are implemented.
+
+Also, note that most debug statements are implemented as a variation of
+dprintk(), which have to be activated via a parameter in respective module,
+dynamic debug is unable to do that step for you.
+
+Here is one example, that enables all available pr_debug()'s within the file::
+
+ $ alias ddcmd='echo $* > /proc/dynamic_debug/control'
+ $ ddcmd '-p; file v4l2-h264.c +p'
+ $ grep =p /proc/dynamic_debug/control
+ drivers/media/v4l2-core/v4l2-h264.c:372 [v4l2_h264]print_ref_list_b =p
+ "ref_pic_list_b%u (cur_poc %u%c) %s"
+ drivers/media/v4l2-core/v4l2-h264.c:333 [v4l2_h264]print_ref_list_p =p
+ "ref_pic_list_p (cur_poc %u%c) %s\n"
+
+**When should you use this over Ftrace ?**
+
+- When the code contains one of the valid print statements (see above) or when
+ you have added multiple pr_debug() statements during development
+- When timing is not an issue, meaning if multiple pr_debug() statements in
+ the code won't cause delays
+- When you care more about receiving specific log messages than tracing the
+ pattern of how a function is called
+
+For the full documentation see :doc:`/admin-guide/dynamic-debug-howto`
+
+Ftrace
+------
+
+Prerequisite: ``CONFIG_DYNAMIC_FTRACE``
+
+This tool uses the tracefs file system for the control files and output files.
+That file system will be mounted as a ``tracing`` directory, which can be found
+in either ``/sys/kernel/`` or ``/sys/debug/kernel/``.
+
+Some of the most important operations for debugging are:
+
+- You can perform a function trace by adding a function name to the
+ ``set_ftrace_filter`` file (which accepts any function name found within the
+ ``available_filter_functions`` file) or you can specifically disable certain
+ functions by adding their names to the ``set_ftrace_notrace`` file (more info
+ at: :ref:`trace/ftrace:dynamic ftrace`).
+- In order to find out where calls originate from you can activate the
+ ``func_stack_trace`` option under ``options/func_stack_trace``.
+- Tracing the children of a function call and showing the return values are
+ possible by adding the desired function in the ``set_graph_function`` file
+ (requires config ``FUNCTION_GRAPH_RETVAL``); more info at
+ :ref:`trace/ftrace:dynamic ftrace with the function graph tracer`.
+
+For the full Ftrace documentation see :doc:`/trace/ftrace`
+
+Or you could also trace for specific events by :ref:`using event tracing
+<trace/events:2. using event tracing>`, which can be defined as described here:
+:ref:`Creating a custom Ftrace tracepoint
+<process/debugging/driver_development_debugging_guide:ftrace>`.
+
+For the full Ftrace event tracing documentation see :doc:`/trace/events`
+
+.. _read_ftrace_log:
+
+Reading the ftrace log
+~~~~~~~~~~~~~~~~~~~~~~
+
+The ``trace`` file can be read just like any other file (``cat``, ``tail``,
+``head``, ``vim``, etc.), the size of the file is limited by the
+``buffer_size_kb`` (``echo 1000 > buffer_size_kb``). The
+:ref:`trace/ftrace:trace_pipe` will behave similarly to the ``trace`` file, but
+whenever you read from the file the content is consumed.
+
+Kernelshark
+~~~~~~~~~~~
+
+A GUI interface to visualize the traces as a graph and list view from the
+output of the `trace-cmd
+<https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/>`__ application.
+
+For the full documentation see `<https://kernelshark.org/Documentation.html>`__
+
+Perf & alternatives
+-------------------
+
+The tools mentioned above provide ways to inspect kernel code, results,
+variable values, etc. Sometimes you have to find out first where to look and
+for those cases, a box of performance tracking tools can help you to frame the
+issue.
+
+Why should you do a performance analysis?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A performance analysis is a good first step when among other reasons:
+
+- you cannot define the issue
+- you do not know where it occurs
+- the running system should not be interrupted or it is a remote system, where
+ you cannot install a new module/kernel
+
+How to do a simple analysis with linux tools?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For the start of a performance analysis, you can start with the usual tools
+like:
+
+- ``top`` / ``htop`` / ``atop`` (*get an overview of the system load, see
+ spikes on specific processes*)
+- ``mpstat -P ALL`` (*look at the load distribution among CPUs*)
+- ``iostat -x`` (*observe input and output devices utilization and performance*)
+- ``vmstat`` (*overview of memory usage on the system*)
+- ``pidstat`` (*similar to* ``vmstat`` *but per process, to dial it down to the
+ target*)
+- ``strace -tp $PID`` (*once you know the process, you can figure out how it
+ communicates with the Kernel*)
+
+These should help to narrow down the areas to look at sufficiently.
+
+Diving deeper with perf
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The **perf** tool provides a series of metrics and events to further dial down
+on issues.
+
+Prerequisite: build or install perf on your system
+
+Gather statistics data for finding all files starting with ``gcc`` in ``/usr``::
+
+ # perf stat -d find /usr -name 'gcc*' | wc -l
+
+ Performance counter stats for 'find /usr -name gcc*':
+
+ 1277.81 msec task-clock # 0.997 CPUs utilized
+ 9 context-switches # 7.043 /sec
+ 1 cpu-migrations # 0.783 /sec
+ 704 page-faults # 550.943 /sec
+ 766548897 cycles # 0.600 GHz (97.15%)
+ 798285467 instructions # 1.04 insn per cycle (97.15%)
+ 57582731 branches # 45.064 M/sec (2.85%)
+ 3842573 branch-misses # 6.67% of all branches (97.15%)
+ 281616097 L1-dcache-loads # 220.390 M/sec (97.15%)
+ 4220975 L1-dcache-load-misses # 1.50% of all L1-dcache accesses (97.15%)
+ <not supported> LLC-loads
+ <not supported> LLC-load-misses
+
+ 1.281746009 seconds time elapsed
+
+ 0.508796000 seconds user
+ 0.773209000 seconds sys
+
+
+ 52
+
+The availability of events and metrics depends on the system you are running.
+
+For the full documentation see
+`<https://perf.wiki.kernel.org/index.php/Main_Page>`__
+
+Perfetto
+~~~~~~~~
+
+A set of tools to measure and analyze how well applications and systems perform.
+You can use it to:
+
+* identify bottlenecks
+* optimize code
+* make software run faster and more efficiently.
+
+**What is the difference between perfetto and perf?**
+
+* perf is tool as part of and specialized for the Linux Kernel and has CLI user
+ interface.
+* perfetto cross-platform performance analysis stack, has extended
+ functionality into userspace and provides a WEB user interface.
+
+For the full documentation see `<https://perfetto.dev/docs/>`__
+
+Kernel panic analysis tools
+---------------------------
+
+ To capture the crash dump please use ``Kdump`` & ``Kexec``. Below you can find
+ some advice for analysing the data.
+
+ For the full documentation see the :doc:`/admin-guide/kdump/kdump`
+
+ In order to find the corresponding line in the code you can use `faddr2line
+ <https://elixir.bootlin.com/linux/v6.11.6/source/scripts/faddr2line>`__; note
+ that you need to enable ``CONFIG_DEBUG_INFO`` for that to work.
+
+ An alternative to using ``faddr2line`` is the use of ``objdump`` (and its
+ derivatives for the different platforms like ``aarch64-linux-gnu-objdump``).
+ Take this line as an example:
+
+ ``[ +0.000240] rkvdec_device_run+0x50/0x138 [rockchip_vdec]``.
+
+ We can find the corresponding line of code by executing::
+
+ aarch64-linux-gnu-objdump -dS drivers/staging/media/rkvdec/rockchip-vdec.ko | grep rkvdec_device_run\>: -A 40
+ 0000000000000ac8 <rkvdec_device_run>:
+ ac8: d503201f nop
+ acc: d503201f nop
+ {
+ ad0: d503233f paciasp
+ ad4: a9bd7bfd stp x29, x30, [sp, #-48]!
+ ad8: 910003fd mov x29, sp
+ adc: a90153f3 stp x19, x20, [sp, #16]
+ ae0: a9025bf5 stp x21, x22, [sp, #32]
+ const struct rkvdec_coded_fmt_desc *desc = ctx->coded_fmt_desc;
+ ae4: f9411814 ldr x20, [x0, #560]
+ struct rkvdec_dev *rkvdec = ctx->dev;
+ ae8: f9418015 ldr x21, [x0, #768]
+ if (WARN_ON(!desc))
+ aec: b4000654 cbz x20, bb4 <rkvdec_device_run+0xec>
+ ret = pm_runtime_resume_and_get(rkvdec->dev);
+ af0: f943d2b6 ldr x22, [x21, #1952]
+ ret = __pm_runtime_resume(dev, RPM_GET_PUT);
+ af4: aa0003f3 mov x19, x0
+ af8: 52800081 mov w1, #0x4 // #4
+ afc: aa1603e0 mov x0, x22
+ b00: 94000000 bl 0 <__pm_runtime_resume>
+ if (ret < 0) {
+ b04: 37f80340 tbnz w0, #31, b6c <rkvdec_device_run+0xa4>
+ dev_warn(rkvdec->dev, "Not good\n");
+ b08: f943d2a0 ldr x0, [x21, #1952]
+ b0c: 90000001 adrp x1, 0 <rkvdec_try_ctrl-0x8>
+ b10: 91000021 add x1, x1, #0x0
+ b14: 94000000 bl 0 <_dev_warn>
+ *bad = 1;
+ b18: d2800001 mov x1, #0x0 // #0
+ ...
+
+ Meaning, in this line from the crash dump::
+
+ [ +0.000240] rkvdec_device_run+0x50/0x138 [rockchip_vdec]
+
+ I can take the ``0x50`` as offset, which I have to add to the base address
+ of the corresponding function, which I find in this line::
+
+ 0000000000000ac8 <rkvdec_device_run>:
+
+ The result of ``0xac8 + 0x50 = 0xb18``
+ And when I search for that address within the function I get the
+ following line::
+
+ *bad = 1;
+ b18: d2800001 mov x1, #0x0
+
+**Copyright** ©2024 : Collabora
diff --git a/Documentation/process/index.rst b/Documentation/process/index.rst
index 6455eba3ef0c..aa12f2660194 100644
--- a/Documentation/process/index.rst
+++ b/Documentation/process/index.rst
@@ -72,13 +72,15 @@ beyond).
Dealing with bugs
-----------------
-Bugs are a fact of life; it is important that we handle them properly.
-The documents below describe our policies around the handling of a couple
-of special classes of bugs: regressions and security problems.
+Bugs are a fact of life; it is important that we handle them properly. The
+documents below provide general advice about debugging and describe our
+policies around the handling of a couple of special classes of bugs:
+regressions and security problems.
.. toctree::
:maxdepth: 1
+ debugging/index
handling-regressions
security-bugs
cve
diff --git a/Documentation/process/kernel-docs.rst b/Documentation/process/kernel-docs.rst
index 55552ec4b043..3b5b5983fea8 100644
--- a/Documentation/process/kernel-docs.rst
+++ b/Documentation/process/kernel-docs.rst
@@ -72,17 +72,6 @@ On-line docs
programming. Lots of examples. Currently the new version is being
actively maintained at https://github.com/sysprog21/lkmpg.
- * Title: **Rust for Linux**
-
- :Author: various
- :URL: https://rust-for-linux.com/
- :Date: rolling version
- :Keywords: glossary, terms, linux-kernel.
- :Description: From the website: "Rust for Linux is the project adding
- support for the Rust language to the Linux kernel. This website is
- intended as a hub of links, documentation and resources related to
- the project".
-
Published books
---------------
@@ -220,6 +209,158 @@ Miscellaneous
other original research and content related to Linux and software
development.
+Rust
+----
+
+ * Title: **Rust for Linux**
+
+ :Author: various
+ :URL: https://rust-for-linux.com/
+ :Date: rolling version
+ :Keywords: glossary, terms, linux-kernel, rust.
+ :Description: From the website: "Rust for Linux is the project adding
+ support for the Rust language to the Linux kernel. This website is
+ intended as a hub of links, documentation and resources related to
+ the project".
+
+ * Title: **Learn Rust the Dangerous Way**
+
+ :Author: Cliff L. Biffle
+ :URL: https://cliffle.com/p/dangerust/
+ :Date: Accessed Sep 11 2024
+ :Keywords: rust, blog.
+ :Description: From the website: "LRtDW is a series of articles
+ putting Rust features in context for low-level C programmers who
+ maybe don’t have a formal CS background — the sort of people who
+ work on firmware, game engines, OS kernels, and the like.
+ Basically, people like me.". It illustrates line-by-line
+ conversions from C to Rust.
+
+ * Title: **The Rust Book**
+
+ :Author: Steve Klabnik and Carol Nichols, with contributions from the
+ Rust community
+ :URL: https://doc.rust-lang.org/book/
+ :Date: Accessed Sep 11 2024
+ :Keywords: rust, book.
+ :Description: From the website: "This book fully embraces the
+ potential of Rust to empower its users. It’s a friendly and
+ approachable text intended to help you level up not just your
+ knowledge of Rust, but also your reach and confidence as a
+ programmer in general. So dive in, get ready to learn—and welcome
+ to the Rust community!".
+
+ * Title: **Rust for the Polyglot Programmer**
+
+ :Author: Ian Jackson
+ :URL: https://www.chiark.greenend.org.uk/~ianmdlvl/rust-polyglot/index.html
+ :Date: December 2022
+ :Keywords: rust, blog, tooling.
+ :Description: From the website: "There are many guides and
+ introductions to Rust. This one is something different: it is
+ intended for the experienced programmer who already knows many
+ other programming languages. I try to be comprehensive enough to be
+ a starting point for any area of Rust, but to avoid going into too
+ much detail except where things are not as you might expect. Also
+ this guide is not entirely free of opinion, including
+ recommendations of libraries (crates), tooling, etc.".
+
+ * Title: **Fasterthanli.me**
+
+ :Author: Amos Wenger
+ :URL: https://fasterthanli.me/
+ :Date: Accessed Sep 11 2024
+ :Keywords: rust, blog, news.
+ :Description: From the website: "I make articles and videos about how
+ computers work. My content is long-form, didactic and exploratory
+ — and often an excuse to teach Rust!".
+
+ * Title: **Comprehensive Rust**
+
+ :Author: Android team at Google
+ :URL: https://google.github.io/comprehensive-rust/
+ :Date: Accessed Sep 13 2024
+ :Keywords: rust, blog.
+ :Description: From the website: "The course covers the full spectrum
+ of Rust, from basic syntax to advanced topics like generics and
+ error handling".
+
+ * Title: **The Embedded Rust Book**
+
+ :Author: Multiple contributors, mostly Jorge Aparicio
+ :URL: https://docs.rust-embedded.org/book/
+ :Date: Accessed Sep 13 2024
+ :Keywords: rust, blog.
+ :Description: From the website: "An introductory book about using
+ the Rust Programming Language on "Bare Metal" embedded systems,
+ such as Microcontrollers".
+
+ * Title: **Experiment: Improving the Rust Book**
+
+ :Author: Cognitive Engineering Lab at Brown University
+ :URL: https://rust-book.cs.brown.edu/
+ :Date: Accessed Sep 22 2024
+ :Keywords: rust, blog.
+ :Description: From the website: "The goal of this experiment is to
+ evaluate and improve the content of the Rust Book to help people
+ learn Rust more effectively.".
+
+ * Title: **New Rustacean** (podcast)
+
+ :Author: Chris Krycho
+ :URL: https://newrustacean.com/
+ :Date: Accessed Sep 22 2024
+ :Keywords: rust, podcast.
+ :Description: From the website: "This is a podcast about learning
+ the programming language Rust—from scratch! Apart from this spiffy
+ landing page, all the site content is built with Rust's own
+ documentation tools.".
+
+ * Title: **Opsem-team** (repository)
+
+ :Author: Operational semantics team
+ :URL: https://github.com/rust-lang/opsem-team/tree/main
+ :Date: Accessed Sep 22 2024
+ :Keywords: rust, repository.
+ :Description: From the README: "The opsem team is the successor of
+ the unsafe-code-guidelines working group and responsible for
+ answering many of the difficult questions about the semantics of
+ unsafe Rust".
+
+ * Title: **You Can't Spell Trust Without Rust**
+
+ :Author: Alexis Beingessner
+ :URL: https://repository.library.carleton.ca/downloads/1j92g820w?locale=en
+ :Date: 2015
+ :Keywords: rust, master, thesis.
+ :Description: This thesis focuses on Rust's ownership system, which
+ ensures memory safety by controlling data manipulation and
+ lifetime, while also highlighting its limitations and comparing it
+ to similar systems in Cyclone and C++.
+
+ * Name: **Linux Plumbers (LPC) 2024 Rust presentations**
+
+ :Title: Rust microconference
+ :URL: https://lpc.events/event/18/sessions/186/#20240918
+ :Title: Rust for Linux
+ :URL: https://lpc.events/event/18/contributions/1912/
+ :Title: Journey of a C kernel engineer starting a Rust driver project
+ :URL: https://lpc.events/event/18/contributions/1911/
+ :Title: Crafting a Linux kernel scheduler that runs in user-space
+ using Rust
+ :URL: https://lpc.events/event/18/contributions/1723/
+ :Title: openHCL: A Linux and Rust based paravisor
+ :URL: https://lpc.events/event/18/contributions/1956/
+ :Keywords: rust, lpc, presentations.
+ :Description: A number of LPC talks related to Rust.
+
+ * Name: **The Rustacean Station Podcast**
+
+ :URL: https://rustacean-station.org/
+ :Keywords: rust, podcasts.
+ :Description: A community project for creating podcast content for
+ the Rust programming language.
+
-------
This document was originally based on:
diff --git a/Documentation/process/license-rules.rst b/Documentation/process/license-rules.rst
index 2ef44ada3f11..59a7832df7d0 100644
--- a/Documentation/process/license-rules.rst
+++ b/Documentation/process/license-rules.rst
@@ -471,14 +471,16 @@ _`MODULE_LICENSE`
source files.
"Proprietary" The module is under a proprietary license.
- This string is solely for proprietary third
- party modules and cannot be used for modules
- which have their source code in the kernel
- tree. Modules tagged that way are tainting
- the kernel with the 'P' flag when loaded and
- the kernel module loader refuses to link such
- modules against symbols which are exported
- with EXPORT_SYMBOL_GPL().
+ "Proprietary" is to be understood only as
+ "The license is not compatible to GPLv2".
+ This string is solely for non-GPL2 compatible
+ third party modules and cannot be used for
+ modules which have their source code in the
+ kernel tree. Modules tagged that way are
+ tainting the kernel with the 'P' flag when
+ loaded and the kernel module loader refuses
+ to link such modules against symbols which
+ are exported with EXPORT_SYMBOL_GPL().
============================= =============================================
diff --git a/Documentation/process/maintainer-tip.rst b/Documentation/process/maintainer-tip.rst
index 349a27a53343..e374b67b3277 100644
--- a/Documentation/process/maintainer-tip.rst
+++ b/Documentation/process/maintainer-tip.rst
@@ -7,7 +7,7 @@ What is the tip tree?
---------------------
The tip tree is a collection of several subsystems and areas of
-development. The tip tree is both a direct development tree and a
+development. The tip tree is both a direct development tree and an
aggregation tree for several sub-maintainer trees. The tip tree gitweb URL
is: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
@@ -121,7 +121,7 @@ The tip tree preferred format for patch subject prefixes is
prefix. 'git log path/to/file' should give you a reasonable hint in most
cases.
-The condensed patch description in the subject line should start with a
+The condensed patch description in the subject line should start with an
uppercase letter and should be written in imperative tone.
diff --git a/Documentation/rust/coding-guidelines.rst b/Documentation/rust/coding-guidelines.rst
index 329b070a1d47..a2e326b42410 100644
--- a/Documentation/rust/coding-guidelines.rst
+++ b/Documentation/rust/coding-guidelines.rst
@@ -227,3 +227,149 @@ The equivalent in Rust may look like (ignoring documentation):
That is, the equivalent of ``GPIO_LINE_DIRECTION_IN`` would be referred to as
``gpio::LineDirection::In``. In particular, it should not be named
``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN``.
+
+
+Lints
+-----
+
+In Rust, it is possible to ``allow`` particular warnings (diagnostics, lints)
+locally, making the compiler ignore instances of a given warning within a given
+function, module, block, etc.
+
+It is similar to ``#pragma GCC diagnostic push`` + ``ignored`` + ``pop`` in C
+[#]_:
+
+.. code-block:: c
+
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+ static void f(void) {}
+ #pragma GCC diagnostic pop
+
+.. [#] In this particular case, the kernel's ``__{always,maybe}_unused``
+ attributes (C23's ``[[maybe_unused]]``) may be used; however, the example
+ is meant to reflect the equivalent lint in Rust discussed afterwards.
+
+But way less verbose:
+
+.. code-block:: rust
+
+ #[allow(dead_code)]
+ fn f() {}
+
+By that virtue, it makes it possible to comfortably enable more diagnostics by
+default (i.e. outside ``W=`` levels). In particular, those that may have some
+false positives but that are otherwise quite useful to keep enabled to catch
+potential mistakes.
+
+On top of that, Rust provides the ``expect`` attribute which takes this further.
+It makes the compiler warn if the warning was not produced. For instance, the
+following will ensure that, when ``f()`` is called somewhere, we will have to
+remove the attribute:
+
+.. code-block:: rust
+
+ #[expect(dead_code)]
+ fn f() {}
+
+If we do not, we get a warning from the compiler::
+
+ warning: this lint expectation is unfulfilled
+ --> x.rs:3:10
+ |
+ 3 | #[expect(dead_code)]
+ | ^^^^^^^^^
+ |
+ = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+
+This means that ``expect``\ s do not get forgotten when they are not needed, which
+may happen in several situations, e.g.:
+
+- Temporary attributes added while developing.
+
+- Improvements in lints in the compiler, Clippy or custom tools which may
+ remove a false positive.
+
+- When the lint is not needed anymore because it was expected that it would be
+ removed at some point, such as the ``dead_code`` example above.
+
+It also increases the visibility of the remaining ``allow``\ s and reduces the
+chance of misapplying one.
+
+Thus prefer ``expect`` over ``allow`` unless:
+
+- Conditional compilation triggers the warning in some cases but not others.
+
+ If there are only a few cases where the warning triggers (or does not
+ trigger) compared to the total number of cases, then one may consider using
+ a conditional ``expect`` (i.e. ``cfg_attr(..., expect(...))``). Otherwise,
+ it is likely simpler to just use ``allow``.
+
+- Inside macros, when the different invocations may create expanded code that
+ triggers the warning in some cases but not in others.
+
+- When code may trigger a warning for some architectures but not others, such
+ as an ``as`` cast to a C FFI type.
+
+As a more developed example, consider for instance this program:
+
+.. code-block:: rust
+
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+Here, function ``g()`` is dead code if ``CONFIG_X`` is not set. Can we use
+``expect`` here?
+
+.. code-block:: rust
+
+ #[expect(dead_code)]
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+This would emit a lint if ``CONFIG_X`` is set, since it is not dead code in that
+configuration. Therefore, in cases like this, we cannot use ``expect`` as-is.
+
+A simple possibility is using ``allow``:
+
+.. code-block:: rust
+
+ #[allow(dead_code)]
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+An alternative would be using a conditional ``expect``:
+
+.. code-block:: rust
+
+ #[cfg_attr(not(CONFIG_X), expect(dead_code))]
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+This would ensure that, if someone introduces another call to ``g()`` somewhere
+(e.g. unconditionally), then it would be spotted that it is not dead code
+anymore. However, the ``cfg_attr`` is more complex than a simple ``allow``.
+
+Therefore, it is likely that it is not worth using conditional ``expect``\ s when
+more than one or two configurations are involved or when the lint may be
+triggered due to non-local changes (such as ``dead_code``).
+
+For more information about diagnostics in Rust, please see:
+
+ https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html
diff --git a/Documentation/rust/index.rst b/Documentation/rust/index.rst
index 55dcde9e9e7e..ec62001c7d8c 100644
--- a/Documentation/rust/index.rst
+++ b/Documentation/rust/index.rst
@@ -56,6 +56,9 @@ more details.
arch-support
testing
+You can also find learning materials for Rust in its section in
+:doc:`../process/kernel-docs`.
+
.. only:: subproject and html
Indices
diff --git a/Documentation/rust/quick-start.rst b/Documentation/rust/quick-start.rst
index 2d107982c87b..4aa50e5fcb8c 100644
--- a/Documentation/rust/quick-start.rst
+++ b/Documentation/rust/quick-start.rst
@@ -87,6 +87,23 @@ they should generally work out of the box, e.g.::
zypper install rust rust1.79-src rust-bindgen clang
+Ubuntu
+******
+
+Ubuntu LTS and non-LTS (interim) releases provide recent Rust releases and thus
+they should generally work out of the box, e.g.::
+
+ apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 rust-1.80-clippy
+
+``RUST_LIB_SRC`` needs to be set when using the versioned packages, e.g.::
+
+ RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library
+
+In addition, ``bindgen-0.65`` is available in newer releases (24.04 LTS and
+24.10), but it may not be available in older ones (20.04 LTS and 22.04 LTS),
+thus ``bindgen`` may need to be built manually (please see below).
+
+
Requirements: Building
----------------------
diff --git a/Documentation/scheduler/sched-ext.rst b/Documentation/scheduler/sched-ext.rst
index 7b59bbd2e564..6cb8b676ce03 100644
--- a/Documentation/scheduler/sched-ext.rst
+++ b/Documentation/scheduler/sched-ext.rst
@@ -130,7 +130,7 @@ optional. The following modified excerpt is from
* Decide which CPU a task should be migrated to before being
* enqueued (either at wakeup, fork time, or exec time). If an
* idle core is found by the default ops.select_cpu() implementation,
- * then dispatch the task directly to SCX_DSQ_LOCAL and skip the
+ * then insert the task directly into SCX_DSQ_LOCAL and skip the
* ops.enqueue() callback.
*
* Note that this implementation has exactly the same behavior as the
@@ -148,15 +148,15 @@ optional. The following modified excerpt is from
cpu = scx_bpf_select_cpu_dfl(p, prev_cpu, wake_flags, &direct);
if (direct)
- scx_bpf_dispatch(p, SCX_DSQ_LOCAL, SCX_SLICE_DFL, 0);
+ scx_bpf_dsq_insert(p, SCX_DSQ_LOCAL, SCX_SLICE_DFL, 0);
return cpu;
}
/*
- * Do a direct dispatch of a task to the global DSQ. This ops.enqueue()
- * callback will only be invoked if we failed to find a core to dispatch
- * to in ops.select_cpu() above.
+ * Do a direct insertion of a task to the global DSQ. This ops.enqueue()
+ * callback will only be invoked if we failed to find a core to insert
+ * into in ops.select_cpu() above.
*
* Note that this implementation has exactly the same behavior as the
* default ops.enqueue implementation, which just dispatches the task
@@ -166,7 +166,7 @@ optional. The following modified excerpt is from
*/
void BPF_STRUCT_OPS(simple_enqueue, struct task_struct *p, u64 enq_flags)
{
- scx_bpf_dispatch(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
+ scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
}
s32 BPF_STRUCT_OPS_SLEEPABLE(simple_init)
@@ -202,14 +202,13 @@ and one local dsq per CPU (``SCX_DSQ_LOCAL``). The BPF scheduler can manage
an arbitrary number of dsq's using ``scx_bpf_create_dsq()`` and
``scx_bpf_destroy_dsq()``.
-A CPU always executes a task from its local DSQ. A task is "dispatched" to a
-DSQ. A non-local DSQ is "consumed" to transfer a task to the consuming CPU's
-local DSQ.
+A CPU always executes a task from its local DSQ. A task is "inserted" into a
+DSQ. A task in a non-local DSQ is "move"d into the target CPU's local DSQ.
When a CPU is looking for the next task to run, if the local DSQ is not
-empty, the first task is picked. Otherwise, the CPU tries to consume the
-global DSQ. If that doesn't yield a runnable task either, ``ops.dispatch()``
-is invoked.
+empty, the first task is picked. Otherwise, the CPU tries to move a task
+from the global DSQ. If that doesn't yield a runnable task either,
+``ops.dispatch()`` is invoked.
Scheduling Cycle
----------------
@@ -229,26 +228,26 @@ The following briefly shows how a waking task is scheduled and executed.
scheduler can wake up any cpu using the ``scx_bpf_kick_cpu()`` helper,
using ``ops.select_cpu()`` judiciously can be simpler and more efficient.
- A task can be immediately dispatched to a DSQ from ``ops.select_cpu()`` by
- calling ``scx_bpf_dispatch()``. If the task is dispatched to
- ``SCX_DSQ_LOCAL`` from ``ops.select_cpu()``, it will be dispatched to the
+ A task can be immediately inserted into a DSQ from ``ops.select_cpu()``
+ by calling ``scx_bpf_dsq_insert()``. If the task is inserted into
+ ``SCX_DSQ_LOCAL`` from ``ops.select_cpu()``, it will be inserted into the
local DSQ of whichever CPU is returned from ``ops.select_cpu()``.
- Additionally, dispatching directly from ``ops.select_cpu()`` will cause the
+ Additionally, inserting directly from ``ops.select_cpu()`` will cause the
``ops.enqueue()`` callback to be skipped.
Note that the scheduler core will ignore an invalid CPU selection, for
example, if it's outside the allowed cpumask of the task.
2. Once the target CPU is selected, ``ops.enqueue()`` is invoked (unless the
- task was dispatched directly from ``ops.select_cpu()``). ``ops.enqueue()``
+ task was inserted directly from ``ops.select_cpu()``). ``ops.enqueue()``
can make one of the following decisions:
- * Immediately dispatch the task to either the global or local DSQ by
- calling ``scx_bpf_dispatch()`` with ``SCX_DSQ_GLOBAL`` or
+ * Immediately insert the task into either the global or local DSQ by
+ calling ``scx_bpf_dsq_insert()`` with ``SCX_DSQ_GLOBAL`` or
``SCX_DSQ_LOCAL``, respectively.
- * Immediately dispatch the task to a custom DSQ by calling
- ``scx_bpf_dispatch()`` with a DSQ ID which is smaller than 2^63.
+ * Immediately insert the task into a custom DSQ by calling
+ ``scx_bpf_dsq_insert()`` with a DSQ ID which is smaller than 2^63.
* Queue the task on the BPF side.
@@ -257,23 +256,23 @@ The following briefly shows how a waking task is scheduled and executed.
run, ``ops.dispatch()`` is invoked which can use the following two
functions to populate the local DSQ.
- * ``scx_bpf_dispatch()`` dispatches a task to a DSQ. Any target DSQ can
- be used - ``SCX_DSQ_LOCAL``, ``SCX_DSQ_LOCAL_ON | cpu``,
- ``SCX_DSQ_GLOBAL`` or a custom DSQ. While ``scx_bpf_dispatch()``
+ * ``scx_bpf_dsq_insert()`` inserts a task to a DSQ. Any target DSQ can be
+ used - ``SCX_DSQ_LOCAL``, ``SCX_DSQ_LOCAL_ON | cpu``,
+ ``SCX_DSQ_GLOBAL`` or a custom DSQ. While ``scx_bpf_dsq_insert()``
currently can't be called with BPF locks held, this is being worked on
- and will be supported. ``scx_bpf_dispatch()`` schedules dispatching
+ and will be supported. ``scx_bpf_dsq_insert()`` schedules insertion
rather than performing them immediately. There can be up to
``ops.dispatch_max_batch`` pending tasks.
- * ``scx_bpf_consume()`` tranfers a task from the specified non-local DSQ
- to the dispatching DSQ. This function cannot be called with any BPF
- locks held. ``scx_bpf_consume()`` flushes the pending dispatched tasks
- before trying to consume the specified DSQ.
+ * ``scx_bpf_move_to_local()`` moves a task from the specified non-local
+ DSQ to the dispatching DSQ. This function cannot be called with any BPF
+ locks held. ``scx_bpf_move_to_local()`` flushes the pending insertions
+ tasks before trying to move from the specified DSQ.
4. After ``ops.dispatch()`` returns, if there are tasks in the local DSQ,
the CPU runs the first one. If empty, the following steps are taken:
- * Try to consume the global DSQ. If successful, run the task.
+ * Try to move from the global DSQ. If successful, run the task.
* If ``ops.dispatch()`` has dispatched any tasks, retry #3.
@@ -286,14 +285,14 @@ Note that the BPF scheduler can always choose to dispatch tasks immediately
in ``ops.enqueue()`` as illustrated in the above simple example. If only the
built-in DSQs are used, there is no need to implement ``ops.dispatch()`` as
a task is never queued on the BPF scheduler and both the local and global
-DSQs are consumed automatically.
+DSQs are executed automatically.
-``scx_bpf_dispatch()`` queues the task on the FIFO of the target DSQ. Use
-``scx_bpf_dispatch_vtime()`` for the priority queue. Internal DSQs such as
+``scx_bpf_dsq_insert()`` inserts the task on the FIFO of the target DSQ. Use
+``scx_bpf_dsq_insert_vtime()`` for the priority queue. Internal DSQs such as
``SCX_DSQ_LOCAL`` and ``SCX_DSQ_GLOBAL`` do not support priority-queue
-dispatching, and must be dispatched to with ``scx_bpf_dispatch()``. See the
-function documentation and usage in ``tools/sched_ext/scx_simple.bpf.c`` for
-more information.
+dispatching, and must be dispatched to with ``scx_bpf_dsq_insert()``. See
+the function documentation and usage in ``tools/sched_ext/scx_simple.bpf.c``
+for more information.
Where to Look
=============
diff --git a/Documentation/security/landlock.rst b/Documentation/security/landlock.rst
index 36f26501fd15..59ecdb1c0d4d 100644
--- a/Documentation/security/landlock.rst
+++ b/Documentation/security/landlock.rst
@@ -11,18 +11,18 @@ Landlock LSM: kernel documentation
Landlock's goal is to create scoped access-control (i.e. sandboxing). To
harden a whole system, this feature should be available to any process,
-including unprivileged ones. Because such process may be compromised or
+including unprivileged ones. Because such a process may be compromised or
backdoored (i.e. untrusted), Landlock's features must be safe to use from the
kernel and other processes point of view. Landlock's interface must therefore
expose a minimal attack surface.
Landlock is designed to be usable by unprivileged processes while following the
system security policy enforced by other access control mechanisms (e.g. DAC,
-LSM). Indeed, a Landlock rule shall not interfere with other access-controls
-enforced on the system, only add more restrictions.
+LSM). A Landlock rule shall not interfere with other access-controls enforced
+on the system, only add more restrictions.
Any user can enforce Landlock rulesets on their processes. They are merged and
-evaluated according to the inherited ones in a way that ensures that only more
+evaluated against inherited rulesets in a way that ensures that only more
constraints can be added.
User space documentation can be found here:
@@ -43,7 +43,7 @@ Guiding principles for safe access controls
only impact the processes requesting them.
* Resources (e.g. file descriptors) directly obtained from the kernel by a
sandboxed process shall retain their scoped accesses (at the time of resource
- acquisition) whatever process use them.
+ acquisition) whatever process uses them.
Cf. `File descriptor access rights`_.
Design choices
@@ -71,7 +71,7 @@ the same results, when they are executed under the same Landlock domain.
Taking the ``LANDLOCK_ACCESS_FS_TRUNCATE`` right as an example, it may be
allowed to open a file for writing without being allowed to
:manpage:`ftruncate` the resulting file descriptor if the related file
-hierarchy doesn't grant such access right. The following sequences of
+hierarchy doesn't grant that access right. The following sequences of
operations have the same semantic and should then have the same result:
* ``truncate(path);``
@@ -81,7 +81,7 @@ Similarly to file access modes (e.g. ``O_RDWR``), Landlock access rights
attached to file descriptors are retained even if they are passed between
processes (e.g. through a Unix domain socket). Such access rights will then be
enforced even if the receiving process is not sandboxed by Landlock. Indeed,
-this is required to keep a consistent access control over the whole system, and
+this is required to keep access controls consistent over the whole system, and
this avoids unattended bypasses through file descriptor passing (i.e. confused
deputy attack).
diff --git a/Documentation/sound/designs/compress-accel.rst b/Documentation/sound/designs/compress-accel.rst
new file mode 100644
index 000000000000..c9c1744b94c2
--- /dev/null
+++ b/Documentation/sound/designs/compress-accel.rst
@@ -0,0 +1,134 @@
+==================================
+ALSA Co-processor Acceleration API
+==================================
+
+Jaroslav Kysela <perex@perex.cz>
+
+
+Overview
+========
+
+There is a requirement to expose the audio hardware that accelerates various
+tasks for user space such as sample rate converters, compressed
+stream decoders, etc.
+
+This is description for the API extension for the compress ALSA API which
+is able to handle "tasks" that are not bound to real-time operations
+and allows for the serialization of operations.
+
+Requirements
+============
+
+The main requirements are:
+
+- serialization of multiple tasks for user space to allow multiple
+ operations without user space intervention
+
+- separate buffers (input + output) for each operation
+
+- expose buffers using mmap to user space
+
+- signal user space when the task is finished (standard poll mechanism)
+
+Design
+======
+
+A new direction SND_COMPRESS_ACCEL is introduced to identify
+the passthrough API.
+
+The API extension shares device enumeration and parameters handling from
+the main compressed API. All other realtime streaming ioctls are deactivated
+and a new set of task related ioctls are introduced. The standard
+read/write/mmap I/O operations are not supported in the passthrough device.
+
+Device ("stream") state handling is reduced to OPEN/SETUP. All other
+states are not available for the passthrough mode.
+
+Data I/O mechanism is using standard dma-buf interface with all advantages
+like mmap, standard I/O, buffer sharing etc. One buffer is used for the
+input data and second (separate) buffer is used for the output data. Each task
+have separate I/O buffers.
+
+For the buffering parameters, the fragments means a limit of allocated tasks
+for given device. The fragment_size limits the input buffer size for the given
+device. The output buffer size is determined by the driver (may be different
+from the input buffer size).
+
+State Machine
+=============
+
+The passthrough audio stream state machine is described below::
+
+ +----------+
+ | |
+ | OPEN |
+ | |
+ +----------+
+ |
+ |
+ | compr_set_params()
+ |
+ v
+ all passthrough task ops +----------+
+ +------------------------------------| |
+ | | SETUP |
+ | |
+ | +----------+
+ | |
+ +------------------------------------------+
+
+
+Passthrough operations (ioctls)
+===============================
+
+All operations are protected using stream->device->lock (mutex).
+
+CREATE
+------
+Creates a set of input/output buffers. The input buffer size is
+fragment_size. Allocates unique seqno.
+
+The hardware drivers allocate internal 'struct dma_buf' for both input and
+output buffers (using 'dma_buf_export()' function). The anonymous
+file descriptors for those buffers are passed to user space.
+
+FREE
+----
+Free a set of input/output buffers. If a task is active, the stop
+operation is executed before. If seqno is zero, operation is executed for all
+tasks.
+
+START
+-----
+Starts (queues) a task. There are two cases of the task start - right after
+the task is created. In this case, origin_seqno must be zero.
+The second case is for reusing of already finished task. The origin_seqno
+must identify the task to be reused. In both cases, a new seqno value
+is allocated and returned to user space.
+
+The prerequisite is that application filled input dma buffer with
+new source data and set input_size to pass the real data size to the driver.
+
+The order of data processing is preserved (first started job must be
+finished at first).
+
+If the multiple tasks require a state handling (e.g. resampling operation),
+the user space may set SND_COMPRESS_TFLG_NEW_STREAM flag to mark the
+start of the new stream data. It is useful to keep the allocated buffers
+for the new operation rather using open/close mechanism.
+
+STOP
+----
+Stop (dequeues) a task. If seqno is zero, operation is executed for all
+tasks.
+
+STATUS
+------
+Obtain the task status (active, finished). Also, the driver will set
+the real output data size (valid area in the output buffer).
+
+Credits
+=======
+- Shengjiu Wang <shengjiu.wang@gmail.com>
+- Takashi Iwai <tiwai@suse.de>
+- Vinod Koul <vkoul@kernel.org>
diff --git a/Documentation/sound/designs/index.rst b/Documentation/sound/designs/index.rst
index b79db9ad8732..6b825c5617fc 100644
--- a/Documentation/sound/designs/index.rst
+++ b/Documentation/sound/designs/index.rst
@@ -6,6 +6,7 @@ Designs and Implementations
control-names
channel-mapping-api
+ compress-accel
compress-offload
timestamping
jack-controls
diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst
index e199131bf5ab..f81e94d8f145 100644
--- a/Documentation/sound/hd-audio/notes.rst
+++ b/Documentation/sound/hd-audio/notes.rst
@@ -42,7 +42,7 @@ If you are interested in the deep debugging of HD-audio, read the
HD-audio specification at first. The specification is found on
Intel's web page, for example:
-* https://www.intel.com/standards/hdaudio/
+* https://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html
HD-Audio Controller
diff --git a/Documentation/sound/soc/clocking.rst b/Documentation/sound/soc/clocking.rst
index 32122d6877a3..25d016ea8b65 100644
--- a/Documentation/sound/soc/clocking.rst
+++ b/Documentation/sound/soc/clocking.rst
@@ -42,5 +42,17 @@ rate, number of channels and word size) to save on power.
It is also desirable to use the codec (if possible) to drive (or master) the
audio clocks as it usually gives more accurate sample rates than the CPU.
+ASoC provided clock APIs
+------------------------
+.. kernel-doc:: sound/soc/soc-dai.c
+ :identifiers: snd_soc_dai_set_sysclk
+.. kernel-doc:: sound/soc/soc-dai.c
+ :identifiers: snd_soc_dai_set_clkdiv
+
+.. kernel-doc:: sound/soc/soc-dai.c
+ :identifiers: snd_soc_dai_set_pll
+
+.. kernel-doc:: sound/soc/soc-dai.c
+ :identifiers: snd_soc_dai_set_bclk_ratio
diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst
index 14c4dc026e6b..73a42d5a9f30 100644
--- a/Documentation/sound/soc/dapm.rst
+++ b/Documentation/sound/soc/dapm.rst
@@ -35,6 +35,9 @@ The graph for the STM32MP1-DK1 sound card is shown in picture:
:alt: Example DAPM graph
:align: center
+You can also generate compatible graph for your sound card using
+`tools/sound/dapm-graph` utility.
+
DAPM power domains
==================
diff --git a/Documentation/sound/soc/dpcm.rst b/Documentation/sound/soc/dpcm.rst
index 2d7ad1d91504..02419a6f8213 100644
--- a/Documentation/sound/soc/dpcm.rst
+++ b/Documentation/sound/soc/dpcm.rst
@@ -157,15 +157,13 @@ FE DAI links are defined as follows :-
.codec_dai_name = "snd-soc-dummy-dai",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
- .dpcm_playback = 1,
},
.....< other FE and BE DAI links here >
};
This FE DAI link is pretty similar to a regular DAI link except that we also
-set the DAI link to a DPCM FE with the ``dynamic = 1``. The supported FE stream
-directions should also be set with the ``dpcm_playback`` and ``dpcm_capture``
-flags. There is also an option to specify the ordering of the trigger call for
+set the DAI link to a DPCM FE with the ``dynamic = 1``.
+There is also an option to specify the ordering of the trigger call for
each FE. This allows the ASoC core to trigger the DSP before or after the other
components (as some DSPs have strong requirements for the ordering DAI/DSP
start and stop sequences).
@@ -189,15 +187,12 @@ The BE DAIs are configured as follows :-
.ignore_pmdown_time = 1,
.be_hw_params_fixup = hswult_ssp0_fixup,
.ops = &haswell_ops,
- .dpcm_playback = 1,
- .dpcm_capture = 1,
},
.....< other BE DAI links here >
};
This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets
-the ``no_pcm`` flag to mark it has a BE and sets flags for supported stream
-directions using ``dpcm_playback`` and ``dpcm_capture`` above.
+the ``no_pcm`` flag to mark it has a BE.
The BE has also flags set for ignoring suspend and PM down time. This allows
the BE to work in a hostless mode where the host CPU is not transferring data
diff --git a/Documentation/sound/soc/machine.rst b/Documentation/sound/soc/machine.rst
index 515c9444deaf..9db132bc0070 100644
--- a/Documentation/sound/soc/machine.rst
+++ b/Documentation/sound/soc/machine.rst
@@ -71,6 +71,18 @@ struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
.ops = &corgi_ops,
};
+In the above struct, dai’s are registered using names but you can pass
+either dai name or device tree node but not both. Also, names used here
+for cpu/codec/platform dais should be globally unique.
+
+Additionaly below example macro can be used to register cpu, codec and
+platform dai::
+
+ SND_SOC_DAILINK_DEFS(wm2200_cpu_dsp,
+ DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
+ DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
+ DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
+
struct snd_soc_card then sets up the machine with its DAIs. e.g.
::
@@ -81,6 +93,10 @@ struct snd_soc_card then sets up the machine with its DAIs. e.g.
.num_links = 1,
};
+Following this, ``devm_snd_soc_register_card`` can be used to register
+the sound card. During the registration, the individual components
+such as the codec, CPU, and platform are probed. If all these components
+are successfully probed, the sound card gets registered.
Machine Power Map
-----------------
@@ -95,3 +111,13 @@ Machine Controls
----------------
Machine specific audio mixer controls can be added in the DAI init function.
+
+
+Clocking Controls
+-----------------
+
+As previously noted, clock configuration is handled within the machine driver.
+For details on the clock APIs that the machine driver can utilize for
+setup, please refer to Documentation/sound/soc/clocking.rst. However, the
+callback needs to be registered by the CPU/Codec/Platform drivers to configure
+the clocks that is needed for the corresponding device operation.
diff --git a/Documentation/staging/magic-number.rst b/Documentation/staging/magic-number.rst
index 7029c3c084ee..79afddf0e692 100644
--- a/Documentation/staging/magic-number.rst
+++ b/Documentation/staging/magic-number.rst
@@ -68,11 +68,11 @@ Changelog::
===================== ================ ======================== ==========================================
Magic Name Number Structure File
===================== ================ ======================== ==========================================
-PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/pg.h``
+PG_MAGIC 'P' pg_{read,write}_hdr ``include/uapi/linux/pg.h``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
-SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
-BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``
+SLIP_MAGIC 0x5302 slip ``drivers/net/slip/slip.h``
+BAYCOM_MAGIC 19730510 baycom_state ``drivers/net/hamradio/baycom_epp.c``
HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h``
KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h``
CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``
diff --git a/Documentation/timers/delay_sleep_functions.rst b/Documentation/timers/delay_sleep_functions.rst
new file mode 100644
index 000000000000..49d603a3f113
--- /dev/null
+++ b/Documentation/timers/delay_sleep_functions.rst
@@ -0,0 +1,121 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Delay and sleep mechanisms
+==========================
+
+This document seeks to answer the common question: "What is the
+RightWay (TM) to insert a delay?"
+
+This question is most often faced by driver writers who have to
+deal with hardware delays and who may not be the most intimately
+familiar with the inner workings of the Linux Kernel.
+
+The following table gives a rough overview about the existing function
+'families' and their limitations. This overview table does not replace the
+reading of the function description before usage!
+
+.. list-table::
+ :widths: 20 20 20 20 20
+ :header-rows: 2
+
+ * -
+ - `*delay()`
+ - `usleep_range*()`
+ - `*sleep()`
+ - `fsleep()`
+ * -
+ - busy-wait loop
+ - hrtimers based
+ - timer list timers based
+ - combines the others
+ * - Usage in atomic Context
+ - yes
+ - no
+ - no
+ - no
+ * - precise on "short intervals"
+ - yes
+ - yes
+ - depends
+ - yes
+ * - precise on "long intervals"
+ - Do not use!
+ - yes
+ - max 12.5% slack
+ - yes
+ * - interruptible variant
+ - no
+ - yes
+ - yes
+ - no
+
+A generic advice for non atomic contexts could be:
+
+#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
+ others)
+#. Use `*sleep()` whenever possible
+#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
+#. Use `*delay()` for very, very short delays
+
+Find some more detailed information about the function 'families' in the next
+sections.
+
+`*delay()` family of functions
+------------------------------
+
+These functions use the jiffy estimation of clock speed and will busy wait for
+enough loop cycles to achieve the desired delay. udelay() is the basic
+implementation and ndelay() as well as mdelay() are variants.
+
+These functions are mainly used to add a delay in atomic context. Please make
+sure to ask yourself before adding a delay in atomic context: Is this really
+required?
+
+.. kernel-doc:: include/asm-generic/delay.h
+ :identifiers: udelay ndelay
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: mdelay
+
+
+`usleep_range*()` and `*sleep()` family of functions
+----------------------------------------------------
+
+These functions use hrtimers or timer list timers to provide the requested
+sleeping duration. In order to decide which function is the right one to use,
+take some basic information into account:
+
+#. hrtimers are more expensive as they are using an rb-tree (instead of hashing)
+#. hrtimers are more expensive when the requested sleeping duration is the first
+ timer which means real hardware has to be programmed
+#. timer list timers always provide some sort of slack as they are jiffy based
+
+The generic advice is repeated here:
+
+#. Use `fsleep()` whenever unsure (as it combines all the advantages of the
+ others)
+#. Use `*sleep()` whenever possible
+#. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient
+
+First check fsleep() function description and to learn more about accuracy,
+please check msleep() function description.
+
+
+`usleep_range*()`
+~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: usleep_range usleep_range_idle
+
+.. kernel-doc:: kernel/time/sleep_timeout.c
+ :identifiers: usleep_range_state
+
+
+`*sleep()`
+~~~~~~~~~~
+
+.. kernel-doc:: kernel/time/sleep_timeout.c
+ :identifiers: msleep msleep_interruptible
+
+.. kernel-doc:: include/linux/delay.h
+ :identifiers: ssleep fsleep
diff --git a/Documentation/timers/index.rst b/Documentation/timers/index.rst
index 983f91f8f023..4e88116e4dcf 100644
--- a/Documentation/timers/index.rst
+++ b/Documentation/timers/index.rst
@@ -12,7 +12,7 @@ Timers
hrtimers
no_hz
timekeeping
- timers-howto
+ delay_sleep_functions
.. only:: subproject and html
diff --git a/Documentation/timers/timers-howto.rst b/Documentation/timers/timers-howto.rst
deleted file mode 100644
index ef7a4652ccc9..000000000000
--- a/Documentation/timers/timers-howto.rst
+++ /dev/null
@@ -1,115 +0,0 @@
-===================================================================
-delays - Information on the various kernel delay / sleep mechanisms
-===================================================================
-
-This document seeks to answer the common question: "What is the
-RightWay (TM) to insert a delay?"
-
-This question is most often faced by driver writers who have to
-deal with hardware delays and who may not be the most intimately
-familiar with the inner workings of the Linux Kernel.
-
-
-Inserting Delays
-----------------
-
-The first, and most important, question you need to ask is "Is my
-code in an atomic context?" This should be followed closely by "Does
-it really need to delay in atomic context?" If so...
-
-ATOMIC CONTEXT:
- You must use the `*delay` family of functions. These
- functions use the jiffy estimation of clock speed
- and will busy wait for enough loop cycles to achieve
- the desired delay:
-
- ndelay(unsigned long nsecs)
- udelay(unsigned long usecs)
- mdelay(unsigned long msecs)
-
- udelay is the generally preferred API; ndelay-level
- precision may not actually exist on many non-PC devices.
-
- mdelay is macro wrapper around udelay, to account for
- possible overflow when passing large arguments to udelay.
- In general, use of mdelay is discouraged and code should
- be refactored to allow for the use of msleep.
-
-NON-ATOMIC CONTEXT:
- You should use the `*sleep[_range]` family of functions.
- There are a few more options here, while any of them may
- work correctly, using the "right" sleep function will
- help the scheduler, power management, and just make your
- driver better :)
-
- -- Backed by busy-wait loop:
-
- udelay(unsigned long usecs)
-
- -- Backed by hrtimers:
-
- usleep_range(unsigned long min, unsigned long max)
-
- -- Backed by jiffies / legacy_timers
-
- msleep(unsigned long msecs)
- msleep_interruptible(unsigned long msecs)
-
- Unlike the `*delay` family, the underlying mechanism
- driving each of these calls varies, thus there are
- quirks you should be aware of.
-
-
- SLEEPING FOR "A FEW" USECS ( < ~10us? ):
- * Use udelay
-
- - Why not usleep?
- On slower systems, (embedded, OR perhaps a speed-
- stepped PC!) the overhead of setting up the hrtimers
- for usleep *may* not be worth it. Such an evaluation
- will obviously depend on your specific situation, but
- it is something to be aware of.
-
- SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
- * Use usleep_range
-
- - Why not msleep for (1ms - 20ms)?
- Explained originally here:
- https://lore.kernel.org/r/15327.1186166232@lwn.net
-
- msleep(1~20) may not do what the caller intends, and
- will often sleep longer (~20 ms actual sleep for any
- value given in the 1~20ms range). In many cases this
- is not the desired behavior.
-
- - Why is there no "usleep" / What is a good range?
- Since usleep_range is built on top of hrtimers, the
- wakeup will be very precise (ish), thus a simple
- usleep function would likely introduce a large number
- of undesired interrupts.
-
- With the introduction of a range, the scheduler is
- free to coalesce your wakeup with any other wakeup
- that may have happened for other reasons, or at the
- worst case, fire an interrupt for your upper bound.
-
- The larger a range you supply, the greater a chance
- that you will not trigger an interrupt; this should
- be balanced with what is an acceptable upper bound on
- delay / performance for your specific code path. Exact
- tolerances here are very situation specific, thus it
- is left to the caller to determine a reasonable range.
-
- SLEEPING FOR LARGER MSECS ( 10ms+ )
- * Use msleep or possibly msleep_interruptible
-
- - What's the difference?
- msleep sets the current task to TASK_UNINTERRUPTIBLE
- whereas msleep_interruptible sets the current task to
- TASK_INTERRUPTIBLE before scheduling the sleep. In
- short, the difference is whether the sleep can be ended
- early by a signal. In general, just use msleep unless
- you know you have a need for the interruptible variant.
-
- FLEXIBLE SLEEPING (any delay, uninterruptible)
- * Use fsleep
diff --git a/Documentation/tools/rtla/common_timerlat_options.rst b/Documentation/tools/rtla/common_timerlat_options.rst
index cef6651f1435..10dc802f8d65 100644
--- a/Documentation/tools/rtla/common_timerlat_options.rst
+++ b/Documentation/tools/rtla/common_timerlat_options.rst
@@ -31,6 +31,14 @@
*cyclictest* sets this value to *0* by default, use **--dma-latency** *0* to have
similar results.
+**--deepest-idle-state** *n*
+ Disable idle states higher than *n* for cpus that are running timerlat threads to
+ reduce exit from idle latencies. If *n* is -1, all idle states are disabled.
+ On exit from timerlat, the idle state setting is restored to its original state
+ before running timerlat.
+
+ Requires rtla to be built with libcpupower.
+
**-k**, **--kernel-threads**
Use timerlat kernel-space threads, in contrast of **-u**.
diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index 4073ca48af4a..272464bb7c60 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -1031,14 +1031,15 @@ explains which is which.
CPU#: The CPU which the process was running on.
irqs-off: 'd' interrupts are disabled. '.' otherwise.
- .. caution:: If the architecture does not support a way to
- read the irq flags variable, an 'X' will always
- be printed here.
need-resched:
+ - 'B' all, TIF_NEED_RESCHED, PREEMPT_NEED_RESCHED and TIF_RESCHED_LAZY is set,
- 'N' both TIF_NEED_RESCHED and PREEMPT_NEED_RESCHED is set,
- 'n' only TIF_NEED_RESCHED is set,
- 'p' only PREEMPT_NEED_RESCHED is set,
+ - 'L' both PREEMPT_NEED_RESCHED and TIF_RESCHED_LAZY is set,
+ - 'b' both TIF_NEED_RESCHED and TIF_RESCHED_LAZY is set,
+ - 'l' only TIF_RESCHED_LAZY is set
- '.' otherwise.
hardirq/softirq:
diff --git a/Documentation/trace/histogram.rst b/Documentation/trace/histogram.rst
index 3c9b263de9c2..0aada18c38c6 100644
--- a/Documentation/trace/histogram.rst
+++ b/Documentation/trace/histogram.rst
@@ -81,7 +81,7 @@ Documentation written by Tom Zanussi
.usecs display a common_timestamp in microseconds
.percent display a number of percentage value
.graph display a bar-graph of a value
- .stacktrace display as a stacktrace (must by a long[] type)
+ .stacktrace display as a stacktrace (must be a long[] type)
============= =================================================
Note that in general the semantics of a given field aren't
diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst
index 0b300901fd75..2c991dc96ace 100644
--- a/Documentation/trace/index.rst
+++ b/Documentation/trace/index.rst
@@ -24,6 +24,7 @@ Linux Tracing Technologies
histogram
histogram-design
boottime-trace
+ debugging
hwlat_detector
osnoise-tracer
timerlat-tracer
diff --git a/Documentation/translations/it_IT/process/clang-format.rst b/Documentation/translations/it_IT/dev-tools/clang-format.rst
index 6fab07772da0..6fab07772da0 100644
--- a/Documentation/translations/it_IT/process/clang-format.rst
+++ b/Documentation/translations/it_IT/dev-tools/clang-format.rst
diff --git a/Documentation/translations/it_IT/dev-tools/index.rst b/Documentation/translations/it_IT/dev-tools/index.rst
new file mode 100644
index 000000000000..3d3ed9d15ea1
--- /dev/null
+++ b/Documentation/translations/it_IT/dev-tools/index.rst
@@ -0,0 +1,17 @@
+.. include:: ../disclaimer-ita.rst
+
+:Original: Documentation/dev-tools/index.rst
+
+===================================
+Strumenti di sviluppo per il kernel
+===================================
+
+Qui raccogliamo i vari documenti riguardanti gli strumenti di sviluppo che
+possono essere usati per lavorare col kernel . Per ora, questa è una raccolta
+senza un particolare struttura; si accettano patch!
+
+.. toctree::
+ :caption: Tabella dei contenuti
+ :maxdepth: 2
+
+ clang-format
diff --git a/Documentation/translations/it_IT/i2c/summary.rst b/Documentation/translations/it_IT/i2c/summary.rst
index 1535e13a32e2..99a5b36cfb44 100644
--- a/Documentation/translations/it_IT/i2c/summary.rst
+++ b/Documentation/translations/it_IT/i2c/summary.rst
@@ -3,21 +3,17 @@ Introduzione a I2C e SMBus
==========================
I²C (letteralmente "I al quadrato C" e scritto I2C nella documentazione del
-kernel) è un protocollo sviluppato da Philips. É un protocollo lento a 2 fili
-(a velocità variabile, al massimo 400KHz), con un'estensione per le velocità
-elevate (3.4 MHz). Questo protocollo offre un bus a basso costo per collegare
-dispositivi di vario genere a cui si accede sporadicamente e utilizzando
-poca banda. Alcuni sistemi usano varianti che non rispettano i requisiti
-originali, per cui non sono indicati come I2C, ma hanno nomi diversi, per
-esempio TWI (Interfaccia a due fili), IIC.
+kernel) è un protocollo sviluppato da Philips. É un protocollo a 2 fili (a
+velocità variabile, solitamente fino a 400KHz, e in modalità alta velocità fino
+a 5 MHz). Questo protocollo offre un bus a basso costo per collegare dispositivi
+di vario genere a cui si accede sporadicamente e utilizzando poca banda. I2C è
+ampiamente usato nei sistemi integrati. Alcuni sistemi usano varianti che non
+rispettano i requisiti originali, per cui non sono indicati come I2C, ma hanno
+nomi diversi, per esempio TWI (Interfaccia a due fili), IIC.
L'ultima specifica ufficiale I2C è la `"Specifica I2C-bus e manuale utente"
-(UM10204) <https://www.nxp.com/webapp/Download?colCode=UM10204>`_
-pubblicata da NXP Semiconductors. Tuttavia, è necessario effettuare il login
-al sito per accedere al PDF. Una versione precedente della specifica
-(revisione 6) è archiviata
-`qui <https://web.archive.org/web/20210813122132/
-https://www.nxp.com/docs/en/user-guide/UM10204.pdf>`_.
+(UM10204) <https://www.nxp.com/docs/en/user-guide/UM10204.pdf>`_ pubblicata da
+NXP Semiconductors, al momento della scrittura si tratta della versione 7
SMBus (Bus per la gestione del sistema) si basa sul protocollo I2C ed è
principalmente un sottoinsieme di protocolli e segnali I2C. Molti dispositivi
@@ -27,38 +23,62 @@ SMBus. I più comuni dispositivi collegati tramite SMBus sono moduli RAM
configurati utilizzando EEPROM I2C, e circuiti integrati di monitoraggio
hardware.
-Poiché SMBus è principalmente un sottoinsieme del bus I2C,
-possiamo farne uso su molti sistemi I2C. Ci sono però sistemi che non
-soddisfano i vincoli elettrici sia di SMBus che di I2C; e altri che non possono
-implementare tutta la semantica o messaggi comuni del protocollo SMBus.
+Poiché SMBus è principalmente un sottoinsieme del bus I2C, possiamo farne uso su
+molti sistemi I2C. Ci sono però sistemi che non soddisfano i vincoli elettrici
+sia di SMBus che di I2C; e altri che non possono implementare tutta la semantica
+o messaggi comuni del protocollo SMBus.
Terminologia
============
-Utilizzando la terminologia della documentazione ufficiale, il bus I2C connette
-uno o più circuiti integrati *master* e uno o più circuiti integrati *slave*.
+Il bus I2C connette uno o più circuiti integrati controllori a dei dispositivi.
.. kernel-figure:: ../../../i2c/i2c_bus.svg
- :alt: Un semplice bus I2C con un master e 3 slave
+ :alt: Un semplice bus I2C con un controllore e 3 dispositivi
Un semplice Bus I2C
-Un circuito integrato **master** è un nodo che inizia le comunicazioni con gli
-slave. Nell'implementazione del kernel Linux è chiamato **adattatore** o bus. I
-driver degli adattatori si trovano nella sottocartella ``drivers/i2c/busses/``.
+Un circuito integrato **controllore** (*controller*) è un nodo che inizia le
+comunicazioni con i dispositivi (*targets*). Nell'implementazione del kernel
+Linux è chiamato **adattatore** o bus. I driver degli adattatori si trovano
+nella sottocartella ``drivers/i2c/busses/``.
Un **algoritmo** contiene codice generico che può essere utilizzato per
implementare una intera classe di adattatori I2C. Ciascun driver dell'
adattatore specifico dipende da un driver dell'algoritmo nella sottocartella
``drivers/i2c/algos/`` o include la propria implementazione.
-Un circuito integrato **slave** è un nodo che risponde alle comunicazioni
-quando indirizzato dal master. In Linux è chiamato **client** (dispositivo). I
-driver dei dispositivi sono contenuti in una cartella specifica per la
+Un circuito integrato **dispositivo** è un nodo che risponde alle comunicazioni
+quando indirizzato dal controllore. In Linux è chiamato **client**. Nonostante i
+dispositivi siano circuiti integrati esterni al sistema, Linux può agire come
+dispositivo (se l'hardware lo permette) e rispondere alla richieste di altri
+controllori sul bus. Questo verrà chiamato **dispositivo locale** (*local
+target*). Negli altri casi si parla di **dispositivo remoto** (*remote target*).
+
+I driver dei dispositivi sono contenuti in una cartella specifica per la
funzionalità che forniscono, ad esempio ``drivers/media/gpio/`` per espansori
GPIO e ``drivers/media/i2c/`` per circuiti integrati relativi ai video.
Per la configurazione di esempio in figura, avrai bisogno di un driver per il
tuo adattatore I2C e driver per i tuoi dispositivi I2C (solitamente un driver
per ciascuno dispositivo).
+
+Sinonimi
+--------
+
+Come menzionato precedentemente, per ragioni storiche l'implementazione I2C del
+kernel Linux usa "adatattore" (*adapter*) per i controllori e "client" per i
+dispositivi. Un certo numero di strutture dati usano questi sinonimi nei loro
+nomi. Dunque, durante le discussioni riguardanti l'implementazione dovrete
+essere a coscienza anche di questi termini. Tuttavia si preferiscono i termini
+ufficiali.
+
+Terminologia obsoleta
+---------------------
+
+Nelle prime specifiche di I2C, il controllore veniva chiamato "master" ed i
+dispositivi "slave". Questi termini sono stati resi obsoleti con la versione 7
+della specifica. Inoltre, il loro uso viene scoraggiato dal codice di condotta
+del kernel Linux. Tuttavia, potreste ancora trovare questi termini in pagine non
+aggiornate. In generale si cerca di usare i termini controllore e dispositivo.
diff --git a/Documentation/translations/it_IT/index.rst b/Documentation/translations/it_IT/index.rst
index 9220f65e30d1..afa680607750 100644
--- a/Documentation/translations/it_IT/index.rst
+++ b/Documentation/translations/it_IT/index.rst
@@ -103,9 +103,11 @@ sviluppatori del kernel.
.. toctree::
:maxdepth: 1
- process/license-rules
- doc-guide/index
- kernel-hacking/index
+ Regole sulle licenze <process/license-rules>
+ Scrivere la documentazione <doc-guide/index>
+ Strumenti di sviluppo <dev-tools/index>
+ La guida all'*hacking*<kernel-hacking/index>
+
Documentazione per gli utenti
=============================
diff --git a/Documentation/translations/it_IT/process/2.Process.rst b/Documentation/translations/it_IT/process/2.Process.rst
index 0a62c0f33faf..6262c3908665 100644
--- a/Documentation/translations/it_IT/process/2.Process.rst
+++ b/Documentation/translations/it_IT/process/2.Process.rst
@@ -424,10 +424,10 @@ o entrambi.
Molte delle liste di discussione del Kernel girano su vger.kernel.org;
l'elenco principale lo si trova sul sito:
- http://vger.kernel.org/vger-lists.html
+ https://subspace.kernel.org
-Esistono liste gestite altrove; un certo numero di queste sono in
-redhat.com/mailman/listinfo.
+Tuttavia, esistono liste gestite altrove; controllare il file MAINTAINERS per
+trovare la lista relativa ad un sottosistema specifico.
La lista di discussione principale per lo sviluppo del kernel è, ovviamente,
linux-kernel. Questa lista è un luogo ostile dove trovarsi; i volumi possono
diff --git a/Documentation/translations/it_IT/process/4.Coding.rst b/Documentation/translations/it_IT/process/4.Coding.rst
index ec874a8dfb9d..3126342c4b4a 100644
--- a/Documentation/translations/it_IT/process/4.Coding.rst
+++ b/Documentation/translations/it_IT/process/4.Coding.rst
@@ -69,7 +69,7 @@ e per revisionare interi file per individuare errori nello stile di codifica,
refusi e possibili miglioramenti. Inoltre è utile anche per classificare gli
``#includes``, per allineare variabili/macro, per testi derivati ed altri
compiti del genere. Consultate il file
-:ref:`Documentation/translations/it_IT/process/clang-format.rst <clangformat>`
+:ref:`Documentation/translations/it_IT/dev-tools/clang-format.rst <clangformat>`
per maggiori dettagli
Se utilizzate un programma compatibile con EditorConfig, allora alcune
diff --git a/Documentation/translations/it_IT/process/5.Posting.rst b/Documentation/translations/it_IT/process/5.Posting.rst
index a61d9e6f7433..3b9b4db6fb9a 100644
--- a/Documentation/translations/it_IT/process/5.Posting.rst
+++ b/Documentation/translations/it_IT/process/5.Posting.rst
@@ -208,11 +208,6 @@ di commit in un sistema di controllo di versione. Sarà seguito da:
l'opzione "-p" assocerà alla modifica il nome della funzione alla quale
si riferisce, rendendo il risultato più facile da leggere per gli altri.
-Dovreste evitare di includere nelle patch delle modifiche per file
-irrilevanti (quelli generati dal processo di generazione, per esempio, o i file
-di backup del vostro editor). Il file "dontdiff" nella cartella Documentation
-potrà esservi d'aiuto su questo punto; passatelo a diff con l'opzione "-X".
-
Le etichette sopracitate danno un'idea di come una patch prende vita e sono
descritte nel dettaglio nel documento
:ref:`Documentation/translations/it_IT/process/submitting-patches.rst <it_submittingpatches>`.
diff --git a/Documentation/translations/it_IT/process/changes.rst b/Documentation/translations/it_IT/process/changes.rst
index 0bcf8423cc80..c7d05e2fff15 100644
--- a/Documentation/translations/it_IT/process/changes.rst
+++ b/Documentation/translations/it_IT/process/changes.rst
@@ -34,9 +34,9 @@ PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils.
====================== ================= ========================================
GNU C 5.1 gcc --version
Clang/LLVM (optional) 13.0.0 clang --version
-Rust (opzionale) 1.76.0 rustc --version
+Rust (opzionale) 1.78.0 rustc --version
bindgen (opzionale) 0.65.1 bindgen --version
-GNU make 3.81 make --version
+GNU make 4.0 make --version
bash 4.2 bash --version
binutils 2.25 ld -v
flex 2.5.35 flex --version
@@ -65,6 +65,8 @@ Sphinx\ [#f1]_ 2.4.4 sphinx-build --version
cpio any cpio --version
GNU tar 1.28 tar --version
gtags (opzionale) 6.6.5 gtags --version
+mkimage (opzionale) 2017.01 mkimage --version
+Python (opzionale) 3.5.x python3 --version
====================== ================= ========================================
.. [#f1] Sphinx è necessario solo per produrre la documentazione del Kernel
@@ -88,10 +90,25 @@ potremmo rimuovere gli espedienti che abbiamo implementato per farli
funzionare. Per maggiori informazioni
:ref:`Building Linux with Clang/LLVM <kbuild_llvm>`.
+Rust (opzionale)
+----------------
+
+È necessaria una versione recente del compilatore Rust.
+
+Verificate le istruzioni Documentation/rust/quick-start.rst su come soddisfare i
+requisiti per compilare code Rust. In particolare, la regola ``rustavailable``
+nel ``Makefile`` è utile per verificare perché gli strumenti di compilazione non
+vengono trovati.
+
+bindgen (opzionale)
+-------------------
+
+``bindgen`` viene usato per generare il collegamento (binding) da Rust al lato C del kernel. Dipende da ``libclang``.
+
Make
----
-Per compilare il kernel vi servirà GNU make 3.81 o successivo.
+Per compilare il kernel vi servirà GNU make 4.0 o successivo.
Bash
----
@@ -168,6 +185,16 @@ Il programma GNU GLOBAL versione 6.6.5, o successiva, è necessario quando si
vuole eseguire ``make gtags`` e generare i relativi indici. Internamente si fa
uso del parametro gtags ``-C (--directory)`` che compare in questa versione.
+mkimage
+-------
+
+Questo strumento viene usato per produrre un *Flat Image Tree* (FIT),
+tipicamente usato su sistemi ARM. Questo strumento è disponibile tramite il
+pacchetto ``u-boot-tools`` oppure può essere compilato dal codice sorgente di
+U-Boot. Consultate le istruzioni
+https://docs.u-boot.org/en/latest/build/tools.html#building-tools-for-linux
+
+
Strumenti di sistema
********************
diff --git a/Documentation/translations/it_IT/process/coding-style.rst b/Documentation/translations/it_IT/process/coding-style.rst
index a4b9f44081da..c0dc786b8474 100644
--- a/Documentation/translations/it_IT/process/coding-style.rst
+++ b/Documentation/translations/it_IT/process/coding-style.rst
@@ -620,18 +620,6 @@ Lo stile preferito per i commenti più lunghi (multi-riga) è:
* with beginning and ending almost-blank lines.
*/
-Per i file in net/ e in drivers/net/ lo stile preferito per i commenti
-più lunghi (multi-riga) è leggermente diverso.
-
-.. code-block:: c
-
- /* The preferred comment style for files in net/ and drivers/net
- * looks like this.
- *
- * It is nearly the same as the generally preferred comment style,
- * but there is no initial almost-blank line.
- */
-
È anche importante commentare i dati, sia per i tipi base che per tipi
derivati. A questo scopo, dichiarate un dato per riga (niente virgole
per una dichiarazione multipla). Questo vi lascerà spazio per un piccolo
@@ -726,7 +714,7 @@ di stile, refusi e possibilmente anche delle migliorie. È anche utile per
ordinare gli ``#include``, per allineare variabili/macro, per ridistribuire
il testo e altre cose simili.
Per maggiori dettagli, consultate il file
-:ref:`Documentation/translations/it_IT/process/clang-format.rst <it_clangformat>`.
+:ref:`Documentation/translations/it_IT/dev-tools/clang-format.rst <it_clangformat>`.
Se utilizzate un programma compatibile con EditorConfig, allora alcune
configurazioni basilari come l'indentazione e la fine delle righe verranno
@@ -827,6 +815,29 @@ blocco do - while:
do_this(b, c); \
} while (0)
+Le macro che sembrano funzioni con parametri non usati dovrebbero essere
+sostituite da funzioni inline per evitare il problema.
+
+.. code-block:: c
+
+ static inline void fun(struct foo *foo)
+ {
+ }
+
+Per motivi storici, molti file usano ancora l'approccio "cast a (void)" per
+valutare i parametri. Tuttavia, non è raccomandato. Le funzioni inline risolvono
+i problemi di "espressioni con effetti avversi valutate più di una volta",
+variabili non utilizzate, e in genere per qualche motivo sono documentate
+meglio.
+
+.. code-block:: c
+
+ /*
+ * Avoid doing this whenever possible and instead opt for static
+ * inline functions
+ */
+ #define macrofun(foo) do { (void) (foo); } while (0)
+
Cose da evitare quando si usano le macro:
1) le macro che hanno effetti sul flusso del codice:
diff --git a/Documentation/translations/it_IT/process/email-clients.rst b/Documentation/translations/it_IT/process/email-clients.rst
index 76ca3226c8cd..97173746d8c9 100644
--- a/Documentation/translations/it_IT/process/email-clients.rst
+++ b/Documentation/translations/it_IT/process/email-clients.rst
@@ -228,7 +228,7 @@ Mutt è molto personalizzabile. Qui di seguito trovate la configurazione minima
per iniziare ad usare Mutt per inviare patch usando Gmail::
# .muttrc
- # ================ IMAP ====================
+ # ================ IMAP ====================
set imap_user = 'yourusername@gmail.com'
set imap_pass = 'yourpassword'
set spoolfile = imaps://imap.gmail.com/INBOX
@@ -365,27 +365,12 @@ un editor esterno.
Un altro problema è che Gmail usa la codifica base64 per tutti quei messaggi
che contengono caratteri non ASCII. Questo include cose tipo i nomi europei.
-Proton Mail
-***********
+HacKerMaiL (TUI)
+****************
-Il servizio Proton Mail ha una funzionalità che cripta tutti i messaggi verso
-ogni destinatario per cui è possibile trovare una chiave usando il *Web Key
-Directory* (WKD). Il servizio kernel.org pubblica il WKD per ogni sviluppatore
-in possesso di un conto kernel.org. Di conseguenza, tutti i messaggi inviati
-usando Proton Mail verso indirizzi kernel.org verranno criptati.
-
-Proton Mail non fornisce alcun meccanismo per disabilitare questa funzionalità
-perché verrebbe considerato un problema per la riservatezza. Questa funzionalità
-è attiva anche quando si inviano messaggi usando il Proton Mail Bridge. Dunque
-tutta la posta in uscita verrà criptata, incluse le patch inviate con ``git
-send-email``.
-
-I messaggi criptati sono una fonte di problemi; altri sviluppatori potrebbero
-non aver configurato i loro programmi, o strumenti, per gestire messaggi
-criptati; inoltre, alcuni programmi di posta elettronica potrebbero criptare le
-risposte a messaggi criptati per tutti i partecipanti alla discussione, inclusa
-la lista di discussione stessa.
-
-A meno che non venga introdotta una maniera per disabilitare questa
-funzionalità, non è consigliato usare Proton Mail per contribuire allo sviluppo
-del kernel.
+HacKerMaiL (hkml) è una semplice casella pubblica per la gestione dei messaggi
+di posta che non richiede alcuna sottoscrizione ad una lista di discussione.
+Viene sviluppato e mantenuto dal manutentore di DAMON e si pone come obiettivo
+quello di gestire il processo di sviluppo semplice come quello di DAMON e più in
+generale i sottosistemi del kernel. Per maggiori dettagli, fate riferimento al
+documento README (https://github.com/sjp38/hackermail/blob/master/README.md).
diff --git a/Documentation/translations/it_IT/process/howto.rst b/Documentation/translations/it_IT/process/howto.rst
index 090941a0a898..f51288602ee3 100644
--- a/Documentation/translations/it_IT/process/howto.rst
+++ b/Documentation/translations/it_IT/process/howto.rst
@@ -344,7 +344,7 @@ principale 4.x, sarà necessario un test d'integrazione.
A tale scopo, esiste un repositorio speciale di test nel quale virtualmente
tutti i rami dei sottosistemi vengono inclusi su base quotidiana:
- https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+ https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
In questo modo, i kernel -next offrono uno sguardo riassuntivo su quello che
ci si aspetterà essere nel kernel principale nel successivo periodo
@@ -389,12 +389,12 @@ sviluppatori del kernel partecipano alla lista di discussione Linux Kernel.
I dettagli su come iscriversi e disiscriversi dalla lista possono essere
trovati al sito:
- http://vger.kernel.org/vger-lists.html#linux-kernel
+ https://subspace.kernel.org/subscribing.html
Ci sono diversi archivi della lista di discussione. Usate un qualsiasi motore
di ricerca per trovarli. Per esempio:
- https://lore.kernel.org/lkml/
+ https://lore.kernel.org/linux-kernel/
É caldamente consigliata una ricerca in questi archivi sul tema che volete
sollevare, prima di pubblicarlo sulla lista. Molte cose sono già state
@@ -407,13 +407,13 @@ discussione e il loro uso.
Molte di queste liste sono gestite su kernel.org. Per informazioni consultate
la seguente pagina:
- http://vger.kernel.org/vger-lists.html
+ https://subspace.kernel.org
Per favore ricordatevi della buona educazione quando utilizzate queste liste.
Sebbene sia un pò dozzinale, il seguente URL contiene alcune semplici linee
guida per interagire con la lista (o con qualsiasi altra lista):
- http://www.albion.com/netiquette/
+ https://subspace.kernel.org/etiquette.html
Se diverse persone rispondo alla vostra mail, la lista dei riceventi (copia
conoscenza) potrebbe diventare abbastanza lunga. Non cancellate nessuno dalla
diff --git a/Documentation/translations/it_IT/process/index.rst b/Documentation/translations/it_IT/process/index.rst
index c24500f74660..5a5214f5fd72 100644
--- a/Documentation/translations/it_IT/process/index.rst
+++ b/Documentation/translations/it_IT/process/index.rst
@@ -99,16 +99,6 @@ degli sviluppatori:
kernel-docs
-Ed infine, qui ci sono alcune guide più tecniche che son state messe qua solo
-perché non si è trovato un posto migliore.
-
-.. toctree::
- :maxdepth: 1
-
- magic-number
- clang-format
- ../arch/riscv/patch-acceptance
-
.. only:: subproject and html
Indices
diff --git a/Documentation/translations/it_IT/process/submit-checklist.rst b/Documentation/translations/it_IT/process/submit-checklist.rst
index 2fc09cc1f0be..692be4af9c9b 100644
--- a/Documentation/translations/it_IT/process/submit-checklist.rst
+++ b/Documentation/translations/it_IT/process/submit-checklist.rst
@@ -5,8 +5,9 @@
.. _it_submitchecklist:
+============================================================================
Lista delle verifiche da fare prima di inviare una patch per il kernel Linux
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+============================================================================
Qui troverete una lista di cose che uno sviluppatore dovrebbe fare per
vedere le proprie patch accettate più rapidamente.
@@ -15,118 +16,126 @@ Tutti questi punti integrano la documentazione fornita riguardo alla
sottomissione delle patch, in particolare
:ref:`Documentation/translations/it_IT/process/submitting-patches.rst <it_submittingpatches>`.
+Revisiona il tuo codice
+=======================
+
1) Se state usando delle funzionalità del kernel allora includete (#include)
i file che le dichiarano/definiscono. Non dipendente dal fatto che un file
d'intestazione include anche quelli usati da voi.
-2) Compilazione pulita:
-
- a) con le opzioni ``CONFIG`` negli stati ``=y``, ``=m`` e ``=n``. Nessun
- avviso/errore di ``gcc`` e nessun avviso/errore dal linker.
-
- b) con ``allnoconfig``, ``allmodconfig``
-
- c) quando si usa ``O=builddir``
-
- d) Qualsiasi modifica in Documentation/ deve compilare con successo senza
- avvisi o errori. Usare ``make htmldocs`` o ``make pdfdocs`` per verificare
- e correggere i problemi
-
-3) Compilare per diverse architetture di processore usando strumenti per
- la cross-compilazione o altri.
+2) Controllate lo stile del codice della vostra patch secondo le direttive
+ scritte in :ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`.
-4) Una buona architettura per la verifica della cross-compilazione è la ppc64
- perché tende ad usare ``unsigned long`` per le quantità a 64-bit.
+3) Tutte le barriere di sincronizzazione {per esempio, ``barrier()``,
+ ``rmb()``, ``wmb()``} devono essere accompagnate da un commento nei
+ sorgenti che ne spieghi la logica: cosa fanno e perché.
-5) Controllate lo stile del codice della vostra patch secondo le direttive
- scritte in :ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`.
- Prima dell'invio della patch, usate il verificatore di stile
- (``script/checkpatch.pl``) per scovare le violazioni più semplici.
- Dovreste essere in grado di giustificare tutte le violazioni rimanenti nella
- vostra patch.
+Revisionate i cambiamenti a Kconfig
+===================================
-6) Le opzioni ``CONFIG``, nuove o modificate, non scombussolano il menu
+1) Le opzioni ``CONFIG``, nuove o modificate, non scombussolano il menu
di configurazione e sono preimpostate come disabilitate a meno che non
soddisfino i criteri descritti in ``Documentation/kbuild/kconfig-language.rst``
alla punto "Voci di menu: valori predefiniti".
-7) Tutte le nuove opzioni ``Kconfig`` hanno un messaggio di aiuto.
+2) Tutte le nuove opzioni ``Kconfig`` hanno un messaggio di aiuto.
-8) La patch è stata accuratamente revisionata rispetto alle più importanti
+3) La patch è stata accuratamente revisionata rispetto alle più importanti
configurazioni ``Kconfig``. Questo è molto difficile da fare
correttamente - un buono lavoro di testa sarà utile.
-9) Verificare con sparse.
+Fornite documentazione
+======================
-10) Usare ``make checkstack`` e correggere tutti i problemi rilevati.
+1) Includete :ref:`kernel-doc <kernel_doc>` per documentare API globali del
+ kernel.
- .. note::
+2) Tutti i nuovi elementi in ``/proc`` sono documentati in ``Documentation/``.
- ``checkstack`` non evidenzia esplicitamente i problemi, ma una funzione
- che usa più di 512 byte sullo stack è una buona candidata per una
- correzione.
+3) Tutti i nuovi parametri d'avvio del kernel sono documentati in
+ ``Documentation/admin-guide/kernel-parameters.rst``.
-11) Includete commenti :ref:`kernel-doc <kernel_doc>` per documentare API
- globali del kernel. Usate ``make htmldocs`` o ``make pdfdocs`` per
- verificare i commenti :ref:`kernel-doc <kernel_doc>` ed eventualmente
- correggerli.
+4) Tutti i nuovi parametri dei moduli sono documentati con ``MODULE_PARM_DESC()``.
-12) La patch è stata verificata con le seguenti opzioni abilitate
- contemporaneamente: ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
- ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
- ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
- ``CONFIG_PROVE_RCU`` e ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``.
+5) Tutte le nuove interfacce verso lo spazio utente sono documentate in
+ ``Documentation/ABI/``. Leggete ``Documentation/ABI/README`` per maggiori
+ informazioni. Le patch che modificano le interfacce utente dovrebbero
+ essere inviate in copia anche a linux-api@vger.kernel.org.
-13) La patch è stata compilata e verificata in esecuzione con, e senza,
- le opzioni ``CONFIG_SMP`` e ``CONFIG_PREEMPT``.
+6) Se la patch aggiunge nuove chiamate ioctl, allora aggiornate
+ ``Documentation/userspace-api/ioctl/ioctl-number.rst``.
-14) Se la patch ha effetti sull'IO dei dischi, eccetera: allora dev'essere
- verificata con, e senza, l'opzione ``CONFIG_LBDAF``.
+Verificate il vostro codice con gli strumenti
+=============================================
-15) Tutti i percorsi del codice sono stati verificati con tutte le funzionalità
- di lockdep abilitate.
+1) Prima dell'invio della patch, usate il verificatore di stile
+ (``script/checkpatch.pl``) per scovare le violazioni più semplici.
+ Dovreste essere in grado di giustificare tutte le violazioni rimanenti nella
+ vostra patch.
-16) Tutti i nuovi elementi in ``/proc`` sono documentati in ``Documentation/``.
+2) Verificare il codice con sparse.
-17) Tutti i nuovi parametri d'avvio del kernel sono documentati in
- ``Documentation/admin-guide/kernel-parameters.rst``.
-18) Tutti i nuovi parametri dei moduli sono documentati con ``MODULE_PARM_DESC()``.
+3) Usare ``make checkstack`` e correggere tutti i problemi rilevati. Da notare
+ che ``checkstack`` non evidenzia esplicitamente i problemi, ma una funzione
+ che usa più di 512 byte sullo stack è una buona candidata per una correzione.
-19) Tutte le nuove interfacce verso lo spazio utente sono documentate in
- ``Documentation/ABI/``. Leggete ``Documentation/ABI/README`` per maggiori
- informazioni. Le patch che modificano le interfacce utente dovrebbero
- essere inviate in copia anche a linux-api@vger.kernel.org.
+Compilare il codice
+===================
+
+1) Compilazione pulita:
+
+ a) con le opzioni ``CONFIG`` negli stati ``=y``, ``=m`` e ``=n``. Nessun
+ avviso/errore di ``gcc`` e nessun avviso/errore dal linker.
-20) La patch è stata verificata con l'iniezione di fallimenti in slab e
- nell'allocazione di pagine. Vedere ``Documentation/fault-injection/``.
+ b) con ``allnoconfig``, ``allmodconfig``
+
+ c) quando si usa ``O=builddir``
- Se il nuovo codice è corposo, potrebbe essere opportuno aggiungere
- l'iniezione di fallimenti specifici per il sottosistema.
+ d) Qualsiasi modifica in Documentation/ deve compilare con successo senza
+ avvisi o errori. Usare ``make htmldocs`` o ``make pdfdocs`` per verificare
+ e correggere i problemi
-21) Il nuovo codice è stato compilato con ``gcc -W`` (usate
+2) Compilare per diverse architetture di processore usando strumenti per la
+ cross-compilazione o altri. Una buona architettura per la verifica della
+ cross-compilazione è la ppc64 perché tende ad usare ``unsigned long`` per le
+ quantità a 64-bit.
+
+3) Il nuovo codice è stato compilato con ``gcc -W`` (usate
``make KCFLAGS=-W``). Questo genererà molti avvisi, ma è ottimo
per scovare bachi come "warning: comparison between signed and unsigned".
-22) La patch è stata verificata dopo essere stata inclusa nella serie di patch
- -mm; questo al fine di assicurarsi che continui a funzionare assieme a
- tutte le altre patch in coda e i vari cambiamenti nei sottosistemi VM, VFS
- e altri.
+4) Se il codice che avete modificato dipende o usa una qualsiasi interfaccia o
+ funzionalità del kernel che è associata a uno dei seguenti simboli
+ ``Kconfig``, allora verificate che il kernel compili con diverse
+ configurazioni dove i simboli sono disabilitati e/o ``=m`` (se c'è la
+ possibilità) [non tutti contemporaneamente, solo diverse combinazioni
+ casuali]:
-23) Tutte le barriere di sincronizzazione {per esempio, ``barrier()``,
- ``rmb()``, ``wmb()``} devono essere accompagnate da un commento nei
- sorgenti che ne spieghi la logica: cosa fanno e perché.
+ ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``,
+ ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+ ``CONFIG_NET``, ``CONFIG_INET=n`` (ma l'ultimo con ``CONFIG_NET=y``).
-24) Se la patch aggiunge nuove chiamate ioctl, allora aggiornate
- ``Documentation/userspace-api/ioctl/ioctl-number.rst``.
+Verificate il vostro codice
+===========================
+
+1) La patch è stata verificata con le seguenti opzioni abilitate
+ contemporaneamente: ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+ ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+ ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+ ``CONFIG_PROVE_RCU`` e ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``.
+
+2) La patch è stata compilata e verificata in esecuzione con, e senza,
+ le opzioni ``CONFIG_SMP`` e ``CONFIG_PREEMPT``.
+
+3) Tutti i percorsi del codice sono stati verificati con tutte le funzionalità
+ di lockdep abilitate.
-25) Se il codice che avete modificato dipende o usa una qualsiasi interfaccia o
- funzionalità del kernel che è associata a uno dei seguenti simboli
- ``Kconfig``, allora verificate che il kernel compili con diverse
- configurazioni dove i simboli sono disabilitati e/o ``=m`` (se c'è la
- possibilità) [non tutti contemporaneamente, solo diverse combinazioni
- casuali]:
+4) La patch è stata verificata con l'iniezione di fallimenti in slab e
+ nell'allocazione di pagine. Vedere ``Documentation/fault-injection/``.
+ Se il nuovo codice è corposo, potrebbe essere opportuno aggiungere
+ l'iniezione di fallimenti specifici per il sottosistema.
- ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``,
- ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
- ``CONFIG_NET``, ``CONFIG_INET=n`` (ma l'ultimo con ``CONFIG_NET=y``).
+5) La patch è stata verificata sul tag più recente di linux-next per assicurarsi
+ che funzioni assieme a tutte le altre patch in coda, assieme ai vari
+ cambiamenti nei sottosistemi VM, VFS e altri.
diff --git a/Documentation/translations/it_IT/process/submitting-patches.rst b/Documentation/translations/it_IT/process/submitting-patches.rst
index a7252e73937a..1cc4808139ce 100644
--- a/Documentation/translations/it_IT/process/submitting-patches.rst
+++ b/Documentation/translations/it_IT/process/submitting-patches.rst
@@ -137,10 +137,10 @@ questione.
Quando volete fare riferimento ad una lista di discussione, preferite il
servizio d'archiviazione lore.kernel.org. Per create un collegamento URL è
-sufficiente usare il campo ``Message-Id``, presente nell'intestazione del
+sufficiente usare il campo ``Message-ID``, presente nell'intestazione del
messaggio, senza parentesi angolari. Per esempio::
- Link: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
+ Link: https://lore.kernel.org/30th.anniversary.repost@klaava.Helsinki.FI
Prima d'inviare il messaggio ricordatevi di verificare che il collegamento così
creato funzioni e che indirizzi verso il messaggio desiderato.
@@ -275,11 +275,9 @@ patch riceverà molta più attenzione. Tuttavia, per favore, non spammate le lis
di discussione che non sono interessate al vostro lavoro.
Molte delle liste di discussione relative al kernel vengono ospitate su
-vger.kernel.org; potete trovare un loro elenco alla pagina
-http://vger.kernel.org/vger-lists.html. Tuttavia, ci sono altre liste di
-discussione ospitate altrove.
-
-Non inviate più di 15 patch alla volta sulle liste di discussione vger!!!
+kernel.org; potete trovare un loro elenco alla pagina
+https://subspace.kernel.org. Tuttavia, ci sono altre liste di discussione
+ospitate altrove.
L'ultimo giudizio sull'integrazione delle modifiche accettate spetta a
Linux Torvalds. Il suo indirizzo e-mail è <torvalds@linux-foundation.org>.
@@ -891,6 +889,14 @@ Assicuratevi che il commit si basi su sorgenti ufficiali del
manutentore/mainline e non su sorgenti interni, accessibile solo a voi,
altrimenti sarebbe inutile.
+Strumenti
+---------
+
+Molti degli aspetti più tecnici di questo processo possono essere automatizzati
+usando b4, la cui documentazione è disponibile all'indirizzo
+<https://b4.docs.kernel.org/en/latest/>. Può aiutare a tracciare la dipendenze,
+eseguire checkpatch e con la formattazione e l'invio di messaggi di posta.
+
Riferimenti
-----------
@@ -913,9 +919,6 @@ Greg Kroah-Hartman, "Come scocciare un manutentore di un sottosistema"
<http://www.kroah.com/log/linux/maintainer-06.html>
-No!!!! Basta gigantesche bombe patch alle persone sulla lista linux-kernel@vger.kernel.org!
- <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
-
Kernel Documentation/translations/it_IT/process/coding-style.rst.
E-mail di Linus Torvalds sul formato canonico di una patch:
diff --git a/Documentation/translations/it_IT/staging/index.rst b/Documentation/translations/it_IT/staging/index.rst
new file mode 100644
index 000000000000..6b56707f3a3a
--- /dev/null
+++ b/Documentation/translations/it_IT/staging/index.rst
@@ -0,0 +1,13 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-ita.rst
+
+:Original: :ref:`Documentation/staging/index.rst <process_index>`
+
+Documenti in ordine sparso
+==========================
+
+.. toctree::
+ :maxdepth: 2
+
+ magic-number
diff --git a/Documentation/translations/it_IT/process/magic-number.rst b/Documentation/translations/it_IT/staging/magic-number.rst
index cd8f23571835..cd8f23571835 100644
--- a/Documentation/translations/it_IT/process/magic-number.rst
+++ b/Documentation/translations/it_IT/staging/magic-number.rst
diff --git a/Documentation/translations/ja_JP/process/howto.rst b/Documentation/translations/ja_JP/process/howto.rst
index 872876c67896..d9ba40588e46 100644
--- a/Documentation/translations/ja_JP/process/howto.rst
+++ b/Documentation/translations/ja_JP/process/howto.rst
@@ -361,7 +361,7 @@ https://patchwork.kernel.org/ ã§ãƒªã‚¹ãƒˆã•れã¦ã„ã¾ã™ã€‚
全サブシステムツリーã‹ã‚‰ã»ã¼æ¯Žæ—¥ãƒ—ルã•れã¦ã§ãる特別ãªãƒ†ã‚¹ãƒˆç”¨ã®ãƒªãƒã‚¸
トリãŒå­˜åœ¨ã—ã¾ã™-
- https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+ https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
ã“ã®ã‚„り方ã«ã‚ˆã£ã¦ã€linux-next ã¯æ¬¡ã®ãƒžãƒ¼ã‚¸æ©Ÿä¼šã§ã©ã‚“ãªã‚‚ã®ãŒãƒ¡ã‚¤ãƒ³
ラインã«ãƒžãƒ¼ã‚¸ã•れるã‹ã€ãŠãŠã¾ã‹ãªå±•望をæä¾›ã—ã¾ã™ã€‚
@@ -401,12 +401,12 @@ https://bugzilla.kernel.org ã§ãƒã‚°å ±å‘Šã‚’調ã¹ã‚ˆã†ã¨ã™ã‚‹äººã‚‚ã„ã‚‹ã
㯠Linux kernel メーリングリストã«å‚加ã—ã¦ã„ã¾ã™ã€‚ã“ã®ãƒªã‚¹ãƒˆã®ç™»éŒ²/脱
é€€ã®æ–¹æ³•ã«ã¤ã„ã¦ã¯ä»¥ä¸‹ã‚’å‚ç…§ã—ã¦ãã ã•ã„-
- http://vger.kernel.org/vger-lists.html#linux-kernel
+ https://subspace.kernel.org/subscribing.html
ã“ã®ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–㯠web 上ã®å¤šæ•°ã®å ´æ‰€ã«å­˜åœ¨ã—ã¾ã™ã€‚ã“
れらã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–を探ã™ã«ã¯ã‚µãƒ¼ãƒã‚¨ãƒ³ã‚¸ãƒ³ã‚’使ã„ã¾ã—ょã†ã€‚例ãˆã°-
- https://lore.kernel.org/lkml/
+ https://lore.kernel.org/linux-kernel/
ãƒªã‚¹ãƒˆã«æŠ•ç¨¿ã™ã‚‹å‰ã«ã™ã§ã«ãã®è©±é¡ŒãŒã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã«å­˜åœ¨ã™ã‚‹ã‹ã©ã†ã‹ã‚’検索
ã™ã‚‹ã“ã¨ã‚’是éžã‚„ã£ã¦ãã ã•ã„。多数ã®äº‹ãŒã™ã§ã«è©³ç´°ã«æ¸¡ã£ã¦è­°è«–ã•れã¦ãŠ
@@ -419,13 +419,13 @@ MAINTAINERS ファイルã«ãƒªã‚¹ãƒˆãŒã‚りã¾ã™ã®ã§å‚ç…§ã—ã¦ãã ã•ã
多ãã®ãƒªã‚¹ãƒˆã¯ kernel.org ã§ãƒ›ã‚¹ãƒˆã•れã¦ã„ã¾ã™ã€‚ã“ã‚Œã‚‰ã®æƒ…å ±ã¯ä»¥ä¸‹ã«ã‚
りã¾ã™ -
- http://vger.kernel.org/vger-lists.html
+ https://subspace.kernel.org
メーリングリストを使ã†å ´åˆã€è‰¯ã„行動習慣ã«å¾“ã†ã‚ˆã†ã«ã—ã¾ã—ょã†ã€‚å°‘ã—安ã£
ã½ã„ãŒã€ä»¥ä¸‹ã® URL ã¯ä¸Šã®ãƒªã‚¹ãƒˆ(ã‚„ä»–ã®ãƒªã‚¹ãƒˆ)ã§ä¼šè©±ã™ã‚‹å ´åˆã®ã‚·ãƒ³ãƒ—ル
ãªã‚¬ã‚¤ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’示ã—ã¦ã„ã¾ã™ -
- http://www.albion.com/netiquette/
+ https://subspace.kernel.org/etiquette.html
ã‚‚ã—複数ã®äººãŒã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã«è¿”事をã—ãŸå ´åˆã€CC: ã§å—ã‘る人ã®ãƒªã‚¹ãƒˆã¯
ã ã„ã¶å¤šããªã‚‹ã§ã—ょã†ã€‚正当ãªç†ç”±ãŒãªã„é™ã‚Šã€CC: リストã‹ã‚‰èª°ã‹ã‚’削除
diff --git a/Documentation/translations/sp_SP/scheduler/index.rst b/Documentation/translations/sp_SP/scheduler/index.rst
index 32f9fd7517b2..4ca74f985d27 100644
--- a/Documentation/translations/sp_SP/scheduler/index.rst
+++ b/Documentation/translations/sp_SP/scheduler/index.rst
@@ -7,3 +7,4 @@
sched-design-CFS
sched-eevdf
+ sched-bwc
diff --git a/Documentation/translations/sp_SP/scheduler/sched-bwc.rst b/Documentation/translations/sp_SP/scheduler/sched-bwc.rst
new file mode 100644
index 000000000000..eec5a127839d
--- /dev/null
+++ b/Documentation/translations/sp_SP/scheduler/sched-bwc.rst
@@ -0,0 +1,287 @@
+.. include:: ../disclaimer-sp.rst
+
+:Original: :ref:`Documentation/scheduler/sched-design-CFS.rst <sched_design_CFS>`
+:Translator: Sergio González Collado <sergio.collado@gmail.com>
+
+.. _sp_sched_bwc:
+
+=================================
+CFS con control de ancho de banda
+=================================
+
+.. note::
+ Este documento únicamente trata el control de ancho de banda de CPUs
+ para SCHED_NORMAL. El caso de SCHED_RT se trata en Documentation/scheduler/sched-rt-group.rst
+
+El control de ancho de banda es una extensión CONFIG_FAIR_GROUP_SCHED que
+permite especificar el máximo uso disponible de CPU para un grupo o una jerarquía.
+
+El ancho de banda permitido para un grupo de tareas se especifica usando una
+cuota y un periodo. Dentro de un "periodo" (microsegundos), a un grupo
+de tareas se le asigna hasta su "cuota" de tiempo de uso de CPU en
+microsegundos. Esa cuota es asignada para cada CPU en colas de ejecución
+en porciones de tiempo de ejecución en la CPU según los hilos de ejecución
+del grupo de tareas van siendo candidatos a ejecutarse. Una vez toda la cuota
+ha sido asignada cualquier petición adicional de cuota resultará en esos hilos
+de ejecución siendo limitados/estrangulados. Los hilos de ejecución limitados
+no serán capaces de ejecutarse de nuevo hasta el siguiente periodo cuando
+la cuota sea restablecida.
+
+La cuota sin asignar de un grupo es monitorizada globalmente, siendo
+restablecidas cfs_quota unidades al final de cada periodo. Según los
+hilos de ejecución van consumiendo este ancho de banda, este se
+transfiere a los "silos" de las cpu-locales en base a la demanda. La
+cantidad transferida en cada una de esas actualizaciones es ajustable y
+es descrito como un "slice".
+
+Característica de ráfaga
+--------------------------
+
+Esta característica toma prestado tiempo ahora, que en un futuro tendrá que
+devolver, con el coste de una mayor interferencia hacia los otros usuarios
+del sistema. Todo acotado perfectamente.
+
+El tradicional control de ancho de banda (UP-EDF) es algo como:
+
+ (U = \Sum u_i) <= 1
+
+Esto garantiza dos cosas: que cada tiempo límite de ejecución es cumplido
+y que el sistema es estable. De todas formas, si U fuese > 1, entonces
+por cada segundo de tiempo de reloj de una tarea, tendríamos que
+ejecutar más de un segundo y obviamente no se cumpliría con el tiempo
+límite de ejecución de la tarea, pero en el siguiente periodo de ejecución
+el tiempo límite de la tarea estaría todavía más lejos, y nunca se tendría
+tiempo de alcanzar la ejecución, cayendo así en un fallo no acotado.
+
+La característica de ráfaga implica que el trabajo de una tarea no siempre
+consuma totalmente la cuota; esto permite que se pueda describir u_i
+como una distribución estadística.
+
+Por ejemplo, se tiene u_i = {x,e}_i, donde x es el p(95) y x+e p(100)
+(el tradicional WCET (WCET:Worst Case Execution Time: son las siglas
+en inglés para "peor tiempo de ejecución")). Esto efectivamente permite
+a u ser más pequeño, aumentando la eficiencia (podemos ejecutar más
+tareas en el sistema), pero al coste de perder el instante límite de
+finalización deseado de la tarea, cuando coincidan las peores
+probabilidades. De todas formas, si se mantiene la estabilidad, ya que
+cada sobre-ejecución se empareja con una infra-ejecución en tanto x esté
+por encima de la media.
+
+Es decir, supóngase que se tienen 2 tareas, ambas específicamente
+con p(95), entonces tenemos p(95)*p(95) = 90.25% de probabilidad de
+que ambas tareas se ejecuten dentro de su cuota asignada y todo
+salga bien. Al mismo tiempo se tiene que p(5)*p(5) = 0.25% de
+probabilidad que ambas tareas excedan su cuota de ejecución (fallo
+garantizado de su tiempo final de ejecución). En algún punto por
+en medio, hay un umbral donde una tarea excede su tiempo límite de
+ejecución y la otra no, de forma que se compensan; esto depende de la
+función de probabilidad acumulada específica de la tarea.
+
+Al mismo tiempo, se puede decir que el peor caso de sobrepasar el
+tiempo límite de ejecución será \Sum e_i; esto es una retraso acotado
+(asumiendo que x+e es de hecho el WCET).
+
+La interferencia cuando se usa una ráfaga se evalúa por las posibilidades
+de fallar en el cumplimiento del tiempo límite y el promedio de WCET.
+Los resultados de los tests han mostrado que cuando hay muchos cgroups o
+una CPU está infrautilizada, la interferencia es más limitada. Más detalles
+se aportan en: https://lore.kernel.org/lkml/5371BD36-55AE-4F71-B9D7-B86DC32E3D2B@linux.alibaba.com/
+
+Gestión:
+--------
+
+Cuota, periodo y ráfaga se gestionan dentro del subsistema de cpu por medio
+de cgroupfs.
+
+.. note::
+ Los archivos cgroupfs descritos en esta sección solo se aplican al cgroup
+ v1. Para cgroup v2, ver :ref:`Documentation/admin-guide/cgroup-v2.rst <cgroup-v2-cpu>`.
+
+- cpu.cfs_quota_us: tiempo de ejecución que se refresca cada periodo (en microsegundos)
+- cpu.cfs_period_us: la duración del periodo (en microsegundos)
+- cpu.stat: exporta las estadísticas de limitación [explicado a continuación]
+- cpu.cfs_burst_us: el máximo tiempo de ejecución acumulado (en microsegundos)
+
+Los valores por defecto son::
+
+ cpu.cfs_period_us=100ms
+ cpu.cfs_quota_us=-1
+ cpu.cfs_burst_us=0
+
+Un valor de -1 para cpu.cfs_quota_us indica que el grupo no tiene ninguna
+restricción de ancho de banda aplicado, ese grupo se describe como un grupo
+con ancho de banda sin restringir. Esto representa el comportamiento
+tradicional para CFS.
+
+Asignar cualquier valor (válido) y positivo no menor que cpu.cfs_burst_us
+definirá el límite del ancho de banda. La cuota mínima permitida para
+la cuota o periodo es 1ms. Hay también un límite superior en la duración del
+periodo de 1s. Existen restricciones adicionales cuando los límites de
+ancho de banda se usan de manera jerárquica, estos se explican en mayor
+detalle más adelante.
+
+Asignar cualquier valor negativo a cpu.cfs_quota_us eliminará el límite de
+ancho de banda y devolverá de nuevo al grupo a un estado sin restricciones.
+
+Un valor de 0 para cpu.cfs_burst_us indica que el grupo no puede acumular
+ningún ancho de banda sin usar. Esto hace que el control del comportamiento
+tradicional del ancho de banda para CFS no cambie. Definir cualquier valor
+(válido) positivo no mayor que cpu.cfs_quota_us en cpu.cgs_burst_us definirá
+el límite con el ancho de banda acumulado no usado.
+
+Cualquier actualización a las especificaciones del ancho de banda usado
+por un grupo resultará en que se deje de limitar si está en un estado
+restringido.
+
+Ajustes globales del sistema
+----------------------------
+
+Por eficiencia el tiempo de ejecución es transferido en lotes desde una reserva
+global y el "silo" de una CPU local. Esto reduce en gran medida la presión
+por la contabilidad en grandes sistemas. La cantidad transferida cada vez
+que se requiere una actualización se describe como "slice".
+
+Esto es ajustable vía procfs::
+
+ /proc/sys/kernel/sched_cfs_bandwidth_slice_us (valor por defecto=5ms)
+
+Valores de "slice" más grandes reducirán el costo de transferencia, mientras
+que valores más pequeños permitirán un control más fino del consumo.
+
+Estadísticas
+------------
+
+Las estadísticas del ancho de banda de un grupo se exponen en 5 campos en cpu.stat.
+
+cpu.stat:
+
+- nr_periods: Número de intervalos aplicados que han pasado.
+- nr_throttled: Número de veces que el grupo ha sido restringido/limitado.
+- throttled_time: La duración de tiempo total (en nanosegundos) en las
+ que las entidades del grupo han sido limitadas.
+- nr_bursts: Número de periodos en que ha ocurrido una ráfaga.
+- burst_time: Tiempo acumulado (en nanosegundos) en la que una CPU ha
+ usado más de su cuota en los respectivos periodos.
+
+Este interfaz es de solo lectura.
+
+Consideraciones jerárquicas
+---------------------------
+
+La interfaz refuerza que el ancho de banda de una entidad individual
+sea siempre factible, esto es: max(c_i) <= C. De todas maneras,
+la sobre-suscripción en el caso agregado está explícitamente permitida
+para hacer posible semánticas de conservación de trabajo dentro de una
+jerarquia.
+
+ e.g. \Sum (c_i) puede superar C
+
+[ Donde C es el ancho de banda de el padre, y c_i el de su hijo ]
+
+Hay dos formas en las que un grupo puede ser limitado:
+
+ a. este consume totalmente su propia cuota en un periodo.
+ b. la cuota del padre es consumida totalmente en su periodo.
+
+En el caso b) anterior, incluso si el hijo pudiera tener tiempo de
+ejecución restante, este no le será permitido hasta que el tiempo de
+ejecución del padre sea actualizado.
+
+Advertencias sobre el CFS con control de cuota de ancho de banda
+----------------------------------------------------------------
+
+Una vez una "slice" se asigna a una cpu esta no expira. A pesar de eso todas,
+excepto las "slices" menos las de 1ms, puede ser devueltas a la reserva global
+si todos los hilos en esa cpu pasan a ser no ejecutables. Esto se configura
+en el tiempo de compilación por la variable min_cfs_rq_runtime. Esto es un
+ajuste en la eficacia que ayuda a prevenir añadir bloqueos en el candado global.
+
+El hecho de que las "slices" de una cpu local no expiren tiene como resultado
+algunos casos extremos interesantes que debieran ser comprendidos.
+
+Para una aplicación que es un cgroup y que está limitada en su uso de cpu
+es un punto discutible ya que de forma natural consumirá toda su parte
+de cuota así como también la totalidad de su cuota en cpu locales en cada
+periodo. Como resultado se espera que nr_periods sea aproximadamente igual
+a nr_throttled, y que cpuacct.usage se incremente aproximadamente igual
+a cfs_quota_us en cada periodo.
+
+Para aplicaciones que tienen un gran número de hilos de ejecución y que no
+estan ligadas a una cpu, este matiz de la no-expiración permite que las
+aplicaciones brevemente sobrepasen su cuota límite en la cantidad que
+no ha sido usada en cada cpu en la que el grupo de tareas se está ejecutando
+(típicamente como mucho 1ms por cada cpu o lo que se ha definido como
+min_cfs_rq_runtime). Este pequeño sobreuso únicamente tiene lugar si
+la cuota que ha sido asignada a una cpu y no ha sido completamente usada
+o devuelta en periodos anteriores. Esta cantidad de sobreuso no será
+transferida entre núcleos. Como resultado, este mecanismo todavía cumplirá
+estrictamente los límites de la tarea de grupo en el promedio del uso,
+pero sobre una ventana de tiempo mayor que un único periodo. Esto
+también limita la habilidad de un sobreuso a no más de 1ms por cada cpu.
+Esto provee de una experiencia de uso más predecible para aplicaciones
+con muchos hilos y con límites de cuota pequeños en máquinas con muchos
+núcleos. Esto también elimina la propensión a limitar estas
+aplicaciones mientras que simultáneamente usan menores cuotas
+de uso por cpu. Otra forma de decir esto es que permitiendo que
+la parte no usada de una "slice" permanezca válida entre periodos
+disminuye la posibilidad de malgastare cuota que va a expirar en
+las reservas de la cpu locales que no necesitan una "slice" completa
+de tiempo de ejecución de cpu.
+
+La interacción entre las aplicaciones ligadas a una CPU y las que no están
+ligadas a ninguna cpu ha de ser también considerada, especialmente cuando
+un único núcleo tiene un uso del 100%. Si se da a cada una de esas
+aplicaciones la mitad de la capacidad de una CPU-núcleo y ambas
+están gestionadas en la misma CPU es teóricamente posible que la aplicación
+no ligada a ninguna CPU use su 1ms adicional de cuota en algunos periodos,
+y por tanto evite que la aplicación ligada a una CPU pueda usar su
+cuota completa por esa misma cantidad. En esos caso el algoritmo CFS (vea
+sched-design-CFS.rst) el que decida qué aplicación es la elegida para
+ejecutarse, ya que ambas serán candidatas a ser ejecutadas y tienen
+cuota restante. Esta discrepancia en el tiempo de ejecución se compensará
+en los periodos siguientes cuando el sistema esté inactivo.
+
+Ejemplos
+---------
+
+1. Un grupo limitado a 1 CPU de tiempo de ejecución.
+
+ Si el periodo son 250ms y la cuota son 250ms el grupo de tareas tendrá el tiempo
+ de ejecución de 1 CPU cada 250ms::
+
+ # echo 250000 > cpu.cfs_quota_us /* cuota = 250ms */
+ # echo 250000 > cpu.cfs_period_us /* periodo = 250ms */
+
+2. Un grupo limitado al tiempo de ejecución de 2 CPUs en una máquina varias CPUs.
+
+ Con un periodo de 500ms y una cuota de 1000ms el grupo de tareas tiene el tiempo
+ de ejecución de 2 CPUs cada 500ms::
+
+ # echo 1000000 > cpu.cfs_quota_us /* cuota = 1000ms */
+ # echo 500000 > cpu.cfs_period_us /* periodo = 500ms */
+
+ El periodo más largo aquí permite una capacidad de ráfaga mayor.
+
+3. Un grupo limitado a un 20% de 1 CPU.
+
+ Con un periodo de 50ms, 10ms de cuota son equivalentes al 20% de 1 CPUs::
+
+ # echo 10000 > cpu.cfs_quota_us /* cuota = 10ms */
+ # echo 50000 > cpu.cfs_period_us /* periodo = 50ms */
+
+ Usando un periodo pequeño aquí nos aseguramos una respuesta de
+ la latencia consistente a expensas de capacidad de ráfaga.
+
+4. Un grupo limitado al 40% de 1 CPU, y permite acumular adicionalmente
+ hasta un 20% de 1 CPU.
+
+ Con un periodo de 50ms, 20ms de cuota son equivalentes al 40% de
+ 1 CPU. Y 10ms de ráfaga, son equivalentes a un 20% de 1 CPU::
+
+ # echo 20000 > cpu.cfs_quota_us /* cuota = 20ms */
+ # echo 50000 > cpu.cfs_period_us /* periodo = 50ms */
+ # echo 10000 > cpu.cfs_burst_us /* ráfaga = 10ms */
+
+ Un ajuste mayor en la capacidad de almacenamiento (no mayor que la cuota)
+ permite una mayor capacidad de ráfaga.
+
diff --git a/Documentation/translations/zh_CN/arch/loongarch/irq-chip-model.rst b/Documentation/translations/zh_CN/arch/loongarch/irq-chip-model.rst
index 472761938682..d4ff80de47b6 100644
--- a/Documentation/translations/zh_CN/arch/loongarch/irq-chip-model.rst
+++ b/Documentation/translations/zh_CN/arch/loongarch/irq-chip-model.rst
@@ -87,6 +87,61 @@ PCH-LPC/PCH-MSI,然åŽè¢«EIOINTC统一收集,å†ç›´æŽ¥åˆ°è¾¾CPUINTC::
| Devices |
+---------+
+虚拟扩展IRQ模型
+===============
+
+åœ¨è¿™ç§æ¨¡åž‹é‡Œé¢, IPI(Inter-Processor Interrupt) å’ŒCPU本地时钟中断直接å‘é€åˆ°CPUINTC,
+CPUä¸²å£ (UARTs) 中断å‘é€åˆ°PCH-PIC, 而其他所有设备的中断则分别å‘é€åˆ°æ‰€è¿žæŽ¥çš„PCH_PIC/
+PCH-MSI, ç„¶åŽV-EIOINTC统一收集,å†ç›´æŽ¥åˆ°è¾¾CPUINTC::
+
+ +-----+ +-------------------+ +-------+
+ | IPI |--> | CPUINTC(0-255vcpu)| <-- | Timer |
+ +-----+ +-------------------+ +-------+
+ ^
+ |
+ +-----------+
+ | V-EIOINTC |
+ +-----------+
+ ^ ^
+ | |
+ +---------+ +---------+
+ | PCH-PIC | | PCH-MSI |
+ +---------+ +---------+
+ ^ ^ ^
+ | | |
+ +--------+ +---------+ +---------+
+ | UARTs | | Devices | | Devices |
+ +--------+ +---------+ +---------+
+
+V-EIOINTC 是EIOINTC的扩展, 仅工作在虚拟机模å¼ä¸‹, 中断ç»EIOINTC最多å¯ä¸ªè·¯ç”±åˆ°
+4个虚拟CPU. 但中断ç»V-EIOINTC最多å¯ä¸ªè·¯ç”±åˆ°256个虚拟CPU.
+
+传统的EIOINTC中断控制器,中断路由分为两个部分:8比特用于控制路由到哪个CPU,
+4比特用于控制路由到特定CPU的哪个中断管脚。控制CPU路由的8比特å‰4比特用于控制
+路由到哪个EIOINTC节点,åŽ4比特用于控制此节点哪个CPU。中断路由在选择CPU路由
+å’ŒCPU中断管脚路由时,使用bitmapç¼–ç æ–¹å¼è€Œä¸æ˜¯æ­£å¸¸ç¼–ç æ–¹å¼ï¼Œæ‰€ä»¥å¯¹äºŽä¸€ä¸ª
+EIOINTC中断控制器节点,中断åªèƒ½è·¯ç”±åˆ°CPU0 - CPU3,中断管脚IP0-IP3。
+
+V-EIOINTC新增了两个寄存器,支æŒä¸­æ–­è·¯ç”±åˆ°æ›´å¤šCPU个和中断管脚。
+
+V-EIOINTC功能寄存器
+-------------------
+功能寄存器是åªè¯»å¯„存器,用于显示V-EIOINTC支æŒçš„特性,目å‰ä¸¤ä¸ªæ”¯æŒä¸¤ä¸ªç‰¹æ€§
+EXTIOI_HAS_INT_ENCODE 和 EXTIOI_HAS_CPU_ENCODE。
+
+特性EXTIOI_HAS_INT_ENCODE是传统EIOINTC中断控制器的一个特性,如果此比特为1,
+显示CPUä¸­æ–­ç®¡è„šè·¯ç”±æ–¹å¼æ”¯æŒæ­£å¸¸ç¼–ç ï¼Œè€Œä¸æ˜¯bitmapç¼–ç ï¼Œæ‰€ä»¥ä¸­æ–­å¯ä»¥è·¯ç”±åˆ°
+管脚IP0 - IP15。
+
+特性EXTIOI_HAS_CPU_ENCODE是V-EIOINTC新增特性,如果此比特为1,表示CPU路由
+æ–¹å¼æ”¯æŒæ­£å¸¸ç¼–ç ï¼Œè€Œä¸æ˜¯bitmapç¼–ç ï¼Œæ‰€ä»¥ä¸­æ–­å¯ä»¥è·¯ç”±åˆ°CPU0 - CPU255。
+
+V-EIOINTCé…置寄存器
+-------------------
+é…置寄存器是å¯è¯»å†™å¯„存器,为了兼容性考虑,如果ä¸å†™æ­¤å¯„存器,中断路由采用
+和传统EIOINTC相åŒçš„路由设置。如果对应比特设置为1,表示采用正常路由方å¼è€Œ
+䏿˜¯bitmapç¼–ç çš„路由方å¼ã€‚
+
高级扩展IRQ模型
===============
diff --git a/Documentation/translations/zh_CN/dev-tools/gcov.rst b/Documentation/translations/zh_CN/dev-tools/gcov.rst
index 3158c9da1318..ea8f94852f41 100644
--- a/Documentation/translations/zh_CN/dev-tools/gcov.rst
+++ b/Documentation/translations/zh_CN/dev-tools/gcov.rst
@@ -120,7 +120,7 @@ gcovçš„å†…æ ¸åˆ†æžæ’桩支æŒå†…核的编译和è¿è¡Œæ˜¯åœ¨åŒä¸€å°æœºå™¨ä¸Šï
如果内核编译和è¿è¡Œæ˜¯ä¸åŒçš„æœºå™¨ï¼Œé‚£ä¹ˆéœ€è¦é¢å¤–的准备工作,这å–决于gcov工具
是在哪里使用的:
-.. _gcov-test_zh:
+.. _gcov-test_zh_CN:
a) è‹¥gcovè¿è¡Œåœ¨æµ‹è¯•机上
@@ -140,7 +140,7 @@ a) è‹¥gcovè¿è¡Œåœ¨æµ‹è¯•机上
å¦‚æžœæ–‡ä»¶æ˜¯è½¯é“¾æŽ¥ï¼Œéœ€è¦æ›¿æ¢æˆçœŸæ­£çš„目录文件(这是由make的当å‰å·¥ä½œ
目录å˜é‡CURDIR引起的)。
-.. _gcov-build_zh:
+.. _gcov-build_zh_CN:
b) è‹¥gcovè¿è¡Œåœ¨ç¼–译机上
@@ -205,7 +205,7 @@ kconfig会根æ®ç¼–译工具链的检查自动选择åˆé€‚çš„gcovæ ¼å¼ã€‚
--------------------------
用于在编译机上收集覆盖率元文件的示例脚本
-ï¼ˆè§ :ref:`编译机和测试机分离 a. <gcov-test_zh>` )
+ï¼ˆè§ :ref:`编译机和测试机分离 a. <gcov-test_zh_CN>` )
.. code-block:: sh
@@ -238,7 +238,7 @@ kconfig会根æ®ç¼–译工具链的检查自动选择åˆé€‚çš„gcovæ ¼å¼ã€‚
-------------------------
ç”¨äºŽåœ¨æµ‹è¯•æœºä¸Šæ”¶é›†è¦†ç›–çŽ‡æ•°æ®æ–‡ä»¶çš„示例脚本
-ï¼ˆè§ :ref:`编译机和测试机分离 b. <gcov-build_zh>` )
+ï¼ˆè§ :ref:`编译机和测试机分离 b. <gcov-build_zh_CN>` )
.. code-block:: sh
diff --git a/Documentation/translations/zh_CN/dev-tools/index.rst b/Documentation/translations/zh_CN/dev-tools/index.rst
index 6a8c637c0be1..7b37194217b0 100644
--- a/Documentation/translations/zh_CN/dev-tools/index.rst
+++ b/Documentation/translations/zh_CN/dev-tools/index.rst
@@ -22,6 +22,7 @@ Documentation/translations/zh_CN/dev-tools/testing-overview.rst
sparse
kcov
kcsan
+ kmsan
gcov
kasan
ubsan
@@ -32,7 +33,6 @@ Todolist:
- checkpatch
- coccinelle
- - kmsan
- kfence
- kgdb
- kselftest
diff --git a/Documentation/translations/zh_CN/dev-tools/kasan.rst b/Documentation/translations/zh_CN/dev-tools/kasan.rst
index 4491ad2830ed..fd2e3afbdfad 100644
--- a/Documentation/translations/zh_CN/dev-tools/kasan.rst
+++ b/Documentation/translations/zh_CN/dev-tools/kasan.rst
@@ -422,16 +422,12 @@ KASAN连接到vmapåŸºç¡€æž¶æž„ä»¥æ‡’æ¸…ç†æœªä½¿ç”¨çš„å½±å­å†…存。
~~~~
有一些KASAN测试å¯ä»¥éªŒè¯KASANæ˜¯å¦æ­£å¸¸å·¥ä½œå¹¶å¯ä»¥æ£€æµ‹æŸäº›ç±»åž‹çš„内存æŸå。
-测试由两部分组æˆ:
-1. 与KUnit测试框架集æˆçš„æµ‹è¯•。使用 ``CONFIG_KASAN_KUNIT_TEST`` å¯ç”¨ã€‚
-这些测试å¯ä»¥é€šè¿‡å‡ ç§ä¸åŒçš„æ–¹å¼è‡ªåЍè¿è¡Œå’Œéƒ¨åˆ†éªŒè¯ï¼›è¯·å‚阅下é¢çš„说明。
+所有 KASAN 测试都与 KUnit 测试框架集æˆï¼Œå¯é€šè¿‡ ``CONFIG_KASAN_KUNIT_TEST`` å¯ç”¨ã€‚
+测试å¯ä»¥é€šè¿‡å‡ ç§ä¸åŒçš„æ–¹å¼è‡ªåЍè¿è¡Œå’Œéƒ¨åˆ†éªŒè¯ï¼›è¯·å‚阅以下说明。
-2. 与KUnitä¸å…¼å®¹çš„æµ‹è¯•。使用 ``CONFIG_KASAN_MODULE_TEST`` å¯ç”¨å¹¶ä¸”åªèƒ½ä½œä¸ºæ¨¡å—
-è¿è¡Œã€‚这些测试åªèƒ½é€šè¿‡åŠ è½½å†…æ ¸æ¨¡å—并检查内核日志以获å–KASANæŠ¥å‘Šæ¥æ‰‹åŠ¨éªŒè¯ã€‚
-
-如果检测到错误,æ¯ä¸ªKUnit兼容的KASAN测试都会打å°å¤šä¸ªKASANæŠ¥å‘Šä¹‹ä¸€ï¼Œç„¶åŽæµ‹è¯•打å°
-å…¶ç¼–å·å’Œçжæ€ã€‚
+如果检测到错误,æ¯ä¸ª KASAN 测试都会打å°å¤šä»½ KASAN 报告中的一份。
+ç„¶åŽæµ‹è¯•会打å°å…¶ç¼–å·å’Œçжæ€ã€‚
当测试通过::
@@ -458,16 +454,16 @@ KASAN连接到vmapåŸºç¡€æž¶æž„ä»¥æ‡’æ¸…ç†æœªä½¿ç”¨çš„å½±å­å†…存。
not ok 1 - kasan
-æœ‰å‡ ç§æ–¹æ³•å¯ä»¥è¿è¡Œä¸ŽKUnit兼容的KASAN测试。
+æœ‰å‡ ç§æ–¹æ³•å¯ä»¥è¿è¡Œ KASAN 测试。
1. å¯åŠ è½½æ¨¡å—
- å¯ç”¨ ``CONFIG_KUNIT`` åŽï¼ŒKASAN-KUnit测试å¯ä»¥æž„建为å¯åŠ è½½æ¨¡å—,并通过使用
- ``insmod`` 或 ``modprobe`` 加载 ``kasan_test.ko`` æ¥è¿è¡Œã€‚
+ å¯ç”¨ ``CONFIG_KUNIT`` åŽï¼Œå¯ä»¥å°†æµ‹è¯•构建为å¯åŠ è½½æ¨¡å—
+ 并通过使用 ``insmod`` 或 ``modprobe`` 加载 ``kasan_test.ko`` æ¥è¿è¡Œã€‚
2. 内置
- 通过内置 ``CONFIG_KUNIT`` ,也å¯ä»¥å†…ç½®KASAN-KUnitæµ‹è¯•ã€‚åœ¨è¿™ç§æƒ…况下,
+ 通过内置 ``CONFIG_KUNIT``,测试也å¯ä»¥å†…置。
测试将在å¯åŠ¨æ—¶ä½œä¸ºåŽæœŸåˆå§‹åŒ–调用è¿è¡Œã€‚
3. 使用kunit_tool
diff --git a/Documentation/translations/zh_CN/dev-tools/kmsan.rst b/Documentation/translations/zh_CN/dev-tools/kmsan.rst
new file mode 100644
index 000000000000..b1ddb47bd6c4
--- /dev/null
+++ b/Documentation/translations/zh_CN/dev-tools/kmsan.rst
@@ -0,0 +1,392 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/dev-tools/kmsan.rst
+:Translator: 刘浩阳 Haoyang Liu <tttturtleruss@hust.edu.cn>
+
+=======================
+内核内存消毒剂(KMSAN)
+=======================
+
+KMSAN 是一个动æ€é”™è¯¯æ£€æµ‹å™¨ï¼Œæ—¨åœ¨æŸ¥æ‰¾æœªåˆå§‹åŒ–å€¼çš„ä½¿ç”¨ã€‚å®ƒåŸºäºŽç¼–è¯‘å™¨æ’æ¡©ï¼Œç±»ä¼¼äºŽç”¨
+户空间的 `MemorySanitizer tool`_。
+
+éœ€è¦æ³¨æ„的是 KMSAN å¹¶ä¸é€‚åˆç”Ÿäº§çŽ¯å¢ƒï¼Œå› ä¸ºå®ƒä¼šå¤§å¹…å¢žåŠ å†…æ ¸å†…å­˜å ç”¨å¹¶é™ä½Žç³»ç»Ÿè¿è¡Œé€Ÿåº¦ã€‚
+
+使用方法
+========
+
+构建内核
+--------
+
+è¦æž„建带有 KMSAN 的内核,你需è¦ä¸€ä¸ªè¾ƒæ–°çš„ Clang (14.0.6+)。
+请å‚阅 `LLVM documentation`_ 了解如何构建 Clang。
+
+现在é…置并构建一个å¯ç”¨ CONFIG_KMSAN 的内核。
+
+示例报告
+--------
+
+以下是一个 KMSAN 报告的示例::
+
+ =====================================================
+ BUG: KMSAN: uninit-value in test_uninit_kmsan_check_memory+0x1be/0x380 [kmsan_test]
+ test_uninit_kmsan_check_memory+0x1be/0x380 mm/kmsan/kmsan_test.c:273
+ kunit_run_case_internal lib/kunit/test.c:333
+ kunit_try_run_case+0x206/0x420 lib/kunit/test.c:374
+ kunit_generic_run_threadfn_adapter+0x6d/0xc0 lib/kunit/try-catch.c:28
+ kthread+0x721/0x850 kernel/kthread.c:327
+ ret_from_fork+0x1f/0x30 ??:?
+
+ Uninit was stored to memory at:
+ do_uninit_local_array+0xfa/0x110 mm/kmsan/kmsan_test.c:260
+ test_uninit_kmsan_check_memory+0x1a2/0x380 mm/kmsan/kmsan_test.c:271
+ kunit_run_case_internal lib/kunit/test.c:333
+ kunit_try_run_case+0x206/0x420 lib/kunit/test.c:374
+ kunit_generic_run_threadfn_adapter+0x6d/0xc0 lib/kunit/try-catch.c:28
+ kthread+0x721/0x850 kernel/kthread.c:327
+ ret_from_fork+0x1f/0x30 ??:?
+
+ Local variable uninit created at:
+ do_uninit_local_array+0x4a/0x110 mm/kmsan/kmsan_test.c:256
+ test_uninit_kmsan_check_memory+0x1a2/0x380 mm/kmsan/kmsan_test.c:271
+
+ Bytes 4-7 of 8 are uninitialized
+ Memory access of size 8 starts at ffff888083fe3da0
+
+ CPU: 0 PID: 6731 Comm: kunit_try_catch Tainted: G B E 5.16.0-rc3+ #104
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
+ =====================================================
+
+报告指出本地å˜é‡ ``uninit`` 在 ``do_uninit_local_array()`` 中未åˆå§‹åŒ–。
+第三个堆栈跟踪对应于该å˜é‡åˆ›å»ºçš„ä½ç½®ã€‚
+
+第一个堆栈跟踪显示了未åˆå§‹åŒ–值的使用ä½ç½®ï¼ˆåœ¨
+``test_uninit_kmsan_check_memory()``)。
+工具显示了局部å˜é‡ä¸­æœªåˆå§‹åŒ–的字节åŠå…¶è¢«å¤åˆ¶åˆ°å…¶ä»–内存ä½ç½®å‰çš„堆栈。
+
+KMSAN 会在以下情况下报告未åˆå§‹åŒ–的值 ``v``:
+
+ - 在æ¡ä»¶åˆ¤æ–­ä¸­ï¼Œä¾‹å¦‚ ``if (v) { ... }``ï¼›
+ - 在索引或指针解引用中,例如 ``array[v]`` 或 ``*v``;
+ - 当它被å¤åˆ¶åˆ°ç”¨æˆ·ç©ºé—´æˆ–硬件时,例如 ``copy_to_user(..., &v, ...)``ï¼›
+ - å½“å®ƒä½œä¸ºå‡½æ•°å‚æ•°ä¼ é€’,并且å¯ç”¨ ``CONFIG_KMSAN_CHECK_PARAM_RETVAL`` 时(è§ä¸‹æ–‡ï¼‰ã€‚
+
+这些情况(除了å¤åˆ¶æ•°æ®åˆ°ç”¨æˆ·ç©ºé—´æˆ–硬件外,这是一个安全问题)被视为 C11 标准下的未定义行为。
+
+ç¦ç”¨æ’æ¡©
+--------
+
+å¯ä»¥ç”¨ ``__no_kmsan_checks`` 标记函数。这样,KMSAN 会忽略该函数中的未åˆå§‹åŒ–值,
+并将其输出标记为已åˆå§‹åŒ–。如此,用户ä¸ä¼šæ”¶åˆ°ä¸Žè¯¥å‡½æ•°ç›¸å…³çš„ KMSAN 报告。
+
+KMSAN è¿˜æ”¯æŒ ``__no_sanitize_memory`` 函数属性。KMSAN ä¸ä¼šå¯¹æ‹¥æœ‰è¯¥å±žæ€§çš„函数进行
+æ’æ¡©ï¼Œè¿™åœ¨æˆ‘们ä¸å¸Œæœ›ç¼–译器干扰æŸäº›åº•层代ç ï¼ˆä¾‹å¦‚标记为 ``noinstr`` 的代ç ï¼Œè¯¥
+代ç éšå¼æ·»åŠ äº† ``__no_sanitize_memory``)时å¯èƒ½å¾ˆæœ‰ç”¨ã€‚
+
+然而,这会有代价:此类函数的栈分é…å°†å…·æœ‰ä¸æ­£ç¡®çš„å½±å­/åˆå§‹å€¼ï¼Œå¯èƒ½å¯¼è‡´è¯¯æŠ¥ã€‚æ¥
+è‡ªéžæ’桩代ç çš„函数也å¯èƒ½æŽ¥æ”¶åˆ°ä¸æ­£ç¡®çš„元数æ®ã€‚
+
+
+作为ç»éªŒä¹‹è°ˆï¼Œé¿å…显å¼ä½¿ç”¨ ``__no_sanitize_memory``。
+
+也å¯ä»¥é€šè¿‡ Makefile ç¦ç”¨ KMSAN 对æŸä¸ªæ–‡ä»¶ï¼ˆä¾‹å¦‚ main.o)的作用::
+
+ KMSAN_SANITIZE_main.o := n
+
+或者对整个目录::
+
+ KMSAN_SANITIZE := n
+
+将其应用到文件或目录中的æ¯ä¸ªå‡½æ•°ã€‚大多数用户ä¸ä¼šéœ€è¦ KMSAN_SANITIZE,
+除éžä»–们的代ç è¢« KMSAN ç ´å(例如在早期å¯åŠ¨æ—¶è¿è¡Œçš„代ç ï¼‰ã€‚
+
+还å¯ä»¥é€šè¿‡è°ƒç”¨ ``kmsan_disable_current()`` å’Œ ``kmsan_enable_current()``
+暂时对当å‰ä»»åŠ¡ç¦ç”¨ KMSAN 检查。æ¯ä¸ª ``kmsan_enable_current()`` 必须在
+``kmsan_disable_current()`` 之åŽè°ƒç”¨ï¼›è¿™äº›è°ƒç”¨å¯¹å¯ä»¥åµŒå¥—ã€‚åœ¨è°ƒç”¨æ—¶éœ€è¦æ³¨æ„ä¿æŒ
+嵌套区域简短,并且尽å¯èƒ½ä½¿ç”¨å…¶ä»–方法ç¦ç”¨æ’桩。
+
+支æŒ
+====
+
+为了使用 KMSAN,内核必须使用 Clang 构建,到目å‰ä¸ºæ­¢ï¼ŒClang æ˜¯å”¯ä¸€æ”¯æŒ KMSAN
+çš„ç¼–è¯‘å™¨ã€‚å†…æ ¸æ’æ¡©è¿‡ç¨‹åŸºäºŽç”¨æˆ·ç©ºé—´çš„ `MemorySanitizer tool`_。
+
+ç›®å‰è¿è¡Œæ—¶åº“ä»…æ”¯æŒ x86_64 架构。
+
+KMSAN 的工作原ç†
+================
+
+KMSAN 阴影内存
+--------------
+
+KMSAN 将一个元数æ®å­—节(也称为阴影字节)与æ¯ä¸ªå†…核内存字节关è”。仅当内核内存字节
+çš„ç›¸åº”ä½æœªåˆå§‹åŒ–æ—¶ï¼Œé˜´å½±å­—èŠ‚ä¸­çš„ä¸€ä¸ªæ¯”ç‰¹ä½æ‰ä¼šè¢«è®¾ç½®ã€‚将内存标记为未åˆå§‹åŒ–(å³
+将其阴影字节设置为 ``0xff``)称为中毒,将其标记为已åˆå§‹åŒ–(将阴影字节设置为
+``0x00``)称为解毒。
+
+å½“åœ¨æ ˆä¸Šåˆ†é…æ–°å˜é‡æ—¶ï¼Œé»˜è®¤æƒ…况下它会中毒,这由编译器æ’å…¥çš„æ’æ¡©ä»£ç å®Œæˆï¼ˆé™¤éžå®ƒ
+是立å³åˆå§‹åŒ–的栈å˜é‡ï¼‰ã€‚任何未使用 ``__GFP_ZERO`` 的堆分é…也会中毒。
+
+ç¼–è¯‘å™¨æ’æ¡©è¿˜è·Ÿè¸ªé˜´å½±å€¼åœ¨ä»£ç ä¸­çš„ä½¿ç”¨ã€‚å½“éœ€è¦æ—¶ï¼Œæ’桩代ç ä¼šè°ƒç”¨ ``mm/kmsan/`` 中
+çš„è¿è¡Œæ—¶åº“以æŒä¹…化阴影值。
+
+基本或å¤åˆç±»åž‹çš„阴影值是长度相åŒçš„字节数组。当常é‡å€¼å†™å…¥å†…存时,该内存会被解毒
+。当从内存读å–值时,其阴影内存也会被获å–,并传递到所有使用该值的æ“作中。对于æ¯
+个需è¦ä¸€ä¸ªæˆ–多个值的指令,编译器会生æˆä»£ç æ ¹æ®è¿™äº›å€¼åŠå…¶é˜´å½±æ¥è®¡ç®—结果的阴影。
+
+
+示例::
+
+ int a = 0xff; // i.e. 0x000000ff
+ int b;
+ int c = a | b;
+
+åœ¨è¿™ç§æƒ…况下, ``a`` 的阴影为 ``0``, ``b`` 的阴影为 ``0xffffffff``,
+``c`` 的阴影为 ``0xffffff00``。这æ„å‘³ç€ ``c`` 的高三个字节未åˆå§‹åŒ–,而低字节已
+åˆå§‹åŒ–。
+
+èµ·æºè·Ÿè¸ª
+--------
+
+æ¯å››å­—节的内核内存都有一个所谓的æºç‚¹ä¸Žä¹‹æ˜ å°„。这个æºç‚¹æè¿°äº†åœ¨ç¨‹åºæ‰§è¡Œä¸­ï¼Œæœªåˆ
+始化值的创建点。æ¯ä¸ªæºç‚¹éƒ½ä¸Žå®Œæ•´çš„åˆ†é…æ ˆï¼ˆå¯¹äºŽå †åˆ†é…çš„å†…å­˜ï¼‰æˆ–åŒ…å«æœªåˆå§‹åŒ–å˜
+é‡çš„函数(对于局部å˜é‡ï¼‰ç›¸å…³è”。
+
+当一个未åˆå§‹åŒ–çš„å˜é‡åœ¨æ ˆæˆ–å †ä¸Šåˆ†é…æ—¶ï¼Œä¼šåˆ›å»ºä¸€ä¸ªæ–°çš„æºç‚¹å€¼ï¼Œå¹¶å°†è¯¥å˜é‡çš„åˆå§‹å€¼
+填充为这个值。当从内存中读å–一个值时,其åˆå§‹å€¼ä¹Ÿä¼šè¢«è¯»å–并与阴影一起ä¿ç•™ã€‚对于
+æ¯ä¸ªæŽ¥å—一个或多个值的指令,结果的æºç‚¹æ˜¯ä¸Žä»»ä½•未åˆå§‹åŒ–输入相对应的æºç‚¹ä¹‹ä¸€ã€‚如
+果一个污染值被写入内存,其起æºä¹Ÿä¼šè¢«å†™å…¥ç›¸åº”的存储中。
+
+示例 1::
+
+ int a = 42;
+ int b;
+ int c = a + b;
+
+åœ¨è¿™ç§æƒ…况下, ``b`` çš„æºç‚¹æ˜¯åœ¨å‡½æ•°å…¥å£æ—¶ç”Ÿæˆçš„,并在加法结果写入内存之å‰å­˜å‚¨åˆ°
+``c`` çš„æºç‚¹ä¸­ã€‚
+
+如果几个å˜é‡å…±äº«ç›¸åŒçš„æºç‚¹åœ°å€ï¼Œåˆ™å®ƒä»¬è¢«å­˜å‚¨åœ¨åŒä¸€ä¸ªå››å­—节å—ä¸­ã€‚åœ¨è¿™ç§æƒ…况下,
+对任何å˜é‡çš„æ¯æ¬¡å†™å…¥éƒ½ä¼šæ›´æ–°æ‰€æœ‰å˜é‡çš„æºç‚¹ã€‚åœ¨è¿™ç§æƒ…况下我们必须牺牲精度,因
+为为å•独的ä½ï¼ˆç”šè‡³å­—节)存储æºç‚¹æˆæœ¬è¿‡é«˜ã€‚
+
+示例 2::
+
+ int combine(short a, short b) {
+ union ret_t {
+ int i;
+ short s[2];
+ } ret;
+ ret.s[0] = a;
+ ret.s[1] = b;
+ return ret.i;
+ }
+
+如果 ``a`` å·²åˆå§‹åŒ–而 ``b`` 未åˆå§‹åŒ–,则结果的阴影为 0xffff0000,结果的æºç‚¹ä¸º
+``b`` çš„æºç‚¹ã€‚ ``ret.s[0]`` 会有相åŒçš„èµ·æºï¼Œä½†å®ƒä¸ä¼šè¢«ä½¿ç”¨ï¼Œå› ä¸ºè¯¥å˜é‡å·²åˆå§‹åŒ–。
+
+å¦‚æžœä¸¤ä¸ªå‡½æ•°å‚æ•°éƒ½æœªåˆå§‹åŒ–,则åªä¿ç•™ç¬¬äºŒä¸ªå‚æ•°çš„æºç‚¹ã€‚
+
+æºç‚¹é“¾
+~~~~~~
+
+为了便于调试,KMSAN åœ¨æ¯æ¬¡å°†æœªåˆå§‹åŒ–值存储到内存时都会创建一个新的æºç‚¹ã€‚æ–°çš„æºç‚¹
+引用了其创建栈以åŠå€¼çš„å‰ä¸€ä¸ªèµ·æºã€‚è¿™å¯èƒ½å¯¼è‡´å†…存消耗增加,因此我们在è¿è¡Œæ—¶é™åˆ¶
+了æºç‚¹é“¾çš„长度。
+
+Clang æ’æ¡© API
+--------------
+
+Clang æ’æ¡©é€šè¿‡åœ¨å†…核代ç ä¸­æ’入定义在 ``mm/kmsan/instrumentation.c`` 中的函数调用
+æ¥å®žçŽ°ã€‚
+
+
+阴影æ“作
+~~~~~~~~
+
+å¯¹äºŽæ¯æ¬¡å†…存访问,编译器都会å‘出一个函数调用,该函数返回一对指针,指å‘给定内存
+的阴影和原始地å€::
+
+ typedef struct {
+ void *shadow, *origin;
+ } shadow_origin_ptr_t
+
+ shadow_origin_ptr_t __msan_metadata_ptr_for_load_{1,2,4,8}(void *addr)
+ shadow_origin_ptr_t __msan_metadata_ptr_for_store_{1,2,4,8}(void *addr)
+ shadow_origin_ptr_t __msan_metadata_ptr_for_load_n(void *addr, uintptr_t size)
+ shadow_origin_ptr_t __msan_metadata_ptr_for_store_n(void *addr, uintptr_t size)
+
+函数åä¾èµ–于内存访问的大å°ã€‚
+
+编译器确ä¿å¯¹äºŽæ¯ä¸ªåŠ è½½çš„å€¼ï¼Œå…¶é˜´å½±å’ŒåŽŸå§‹å€¼éƒ½ä»Žå†…å­˜ä¸­è¯»å–。当一个值存储到内存时
+ï¼Œå…¶é˜´å½±å’ŒåŽŸå§‹å€¼ä¹Ÿä¼šé€šè¿‡å…ƒæ•°æ®æŒ‡é’ˆè¿›è¡Œå­˜å‚¨ã€‚
+
+处ç†å±€éƒ¨å˜é‡
+~~~~~~~~~~~~
+
+一个特殊的函数用于为局部å˜é‡åˆ›å»ºä¸€ä¸ªæ–°çš„原始值,并将该å˜é‡çš„原始值设置为该值::
+
+ void __msan_poison_alloca(void *addr, uintptr_t size, char *descr)
+
+访问æ¯ä¸ªä»»åŠ¡æ•°æ®
+~~~~~~~~~~~~~~~~
+
+在æ¯ä¸ªæ’桩函数的开始处,KMSAN æ’入一个对 ``__msan_get_context_state()`` 的调用
+::
+
+ kmsan_context_state *__msan_get_context_state(void)
+
+``kmsan_context_state`` 在 ``include/linux/kmsan.h`` 中声明::
+
+ struct kmsan_context_state {
+ char param_tls[KMSAN_PARAM_SIZE];
+ char retval_tls[KMSAN_RETVAL_SIZE];
+ char va_arg_tls[KMSAN_PARAM_SIZE];
+ char va_arg_origin_tls[KMSAN_PARAM_SIZE];
+ u64 va_arg_overflow_size_tls;
+ char param_origin_tls[KMSAN_PARAM_SIZE];
+ depot_stack_handle_t retval_origin_tls;
+ };
+
+KMSAN ä½¿ç”¨æ­¤ç»“æž„ä½“åœ¨æ’æ¡©å‡½æ•°ä¹‹é—´ä¼ é€’傿•°é˜´å½±å’ŒåŽŸå§‹å€¼ï¼ˆé™¤éžç«‹åˆ»é€šè¿‡
+ ``CONFIG_KMSAN_CHECK_PARAM_RETVAL`` æ£€æŸ¥å‚æ•°ï¼‰ã€‚
+
+将未åˆå§‹åŒ–的值传递给函数
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Clang çš„ MemorySanitizer æ’æ¡©æœ‰ä¸€ä¸ªé€‰é¡¹ ``-fsanitize-memory-param-retval``,该
+é€‰é¡¹ä½¿ç¼–è¯‘å™¨æ£€æŸ¥æŒ‰å€¼ä¼ é€’çš„å‡½æ•°å‚æ•°ï¼Œä»¥åŠå‡½æ•°è¿”回值。
+
+该选项由 ``CONFIG_KMSAN_CHECK_PARAM_RETVAL`` 控制,默认å¯ç”¨ä»¥ä¾¿ KMSAN 更早报告
+未åˆå§‹åŒ–的值。有关更多细节,请å‚考 `LKML discussion`_。
+
+由于 LLVM 中的实现检查的方å¼ï¼ˆå®ƒä»¬ä»…应用于标记为 ``noundef`` çš„å‚æ•°ï¼‰ï¼Œå¹¶ä¸æ˜¯æ‰€
+æœ‰å‚æ•°éƒ½èƒ½ä¿è¯è¢«æ£€æŸ¥ï¼Œå› æ­¤æˆ‘们ä¸èƒ½æ”¾å¼ƒ ``kmsan_context_state`` 中的元数æ®å­˜å‚¨
+。
+
+字符串函数
+~~~~~~~~~~~
+
+编译器将对 ``memcpy()``/``memmove()``/``memset()`` 的调用替æ¢ä¸ºä»¥ä¸‹å‡½æ•°ã€‚这些函
+数在数æ®ç»“æž„åˆå§‹åŒ–或å¤åˆ¶æ—¶ä¹Ÿä¼šè¢«è°ƒç”¨ï¼Œç¡®ä¿é˜´å½±å’ŒåŽŸå§‹å€¼ä¸Žæ•°æ®ä¸€èµ·å¤åˆ¶::
+
+ void *__msan_memcpy(void *dst, void *src, uintptr_t n)
+ void *__msan_memmove(void *dst, void *src, uintptr_t n)
+ void *__msan_memset(void *dst, int c, uintptr_t n)
+
+错误报告
+~~~~~~~~
+
+对于æ¯ä¸ªå€¼çš„使用,编译器å‘出一个阴影检查,在值中毒的情况下调用
+``__msan_warning()``::
+
+ void __msan_warning(u32 origin)
+
+``__msan_warning()`` 使 KMSAN è¿è¡Œæ—¶æ‰“å°é”™è¯¯æŠ¥å‘Šã€‚
+
+å†…è”æ±‡ç¼–æ’æ¡©
+~~~~~~~~~~~~
+
+KMSAN 对æ¯ä¸ªå†…è”æ±‡ç¼–è¾“å‡ºè¿›è¡Œæ’æ¡©ï¼Œè°ƒç”¨::
+
+ void __msan_instrument_asm_store(void *addr, uintptr_t size)
+
+,该函数解除内存区域的污染。
+
+è¿™ç§æ–¹æ³•å¯èƒ½ä¼šæŽ©ç›–æŸäº›é”™è¯¯ï¼Œä½†ä¹Ÿæœ‰åŠ©äºŽé¿å…è®¸å¤šä½æ“作ã€åŽŸå­æ“作等中的å‡é˜³æ€§ã€‚
+
+æœ‰æ—¶ä¼ é€’ç»™å†…è”æ±‡ç¼–çš„æŒ‡é’ˆä¸æŒ‡å‘æœ‰æ•ˆå†…å­˜ã€‚åœ¨è¿™ç§æƒ…况下,它们在è¿è¡Œæ—¶è¢«å¿½ç•¥ã€‚
+
+
+è¿è¡Œæ—¶åº“
+--------
+
+代ç ä½äºŽ ``mm/kmsan/``。
+
+æ¯ä¸ªä»»åŠ¡ KMSAN 状æ€
+~~~~~~~~~~~~~~~~~~~
+
+æ¯ä¸ª task_struct 都有一个关è”çš„ KMSAN 任务状æ€ï¼Œå®ƒä¿å­˜ KMSAN
+上下文(è§ä¸Šæ–‡ï¼‰å’Œä¸€ä¸ªæ¯ä¸ªä»»åŠ¡è®¡æ•°å™¨ä»¥ç¦æ­¢ KMSAN 报告::
+
+ struct kmsan_context {
+ ...
+ unsigned int depth;
+ struct kmsan_context_state cstate;
+ ...
+ }
+
+ struct task_struct {
+ ...
+ struct kmsan_context kmsan;
+ ...
+ }
+
+KMSAN 上下文
+~~~~~~~~~~~~
+
+在内核任务上下文中è¿è¡Œæ—¶ï¼ŒKMSAN 使用 ``current->kmsan.cstate`` æ¥
+ä¿å­˜å‡½æ•°å‚数和返回值的元数æ®ã€‚
+
+但在内核è¿è¡ŒäºŽä¸­æ–­ã€softirq 或 NMI 上下文中, ``current`` ä¸å¯ç”¨æ—¶ï¼Œ
+KMSAN 切æ¢åˆ°æ¯ CPU 中断状æ€::
+
+ DEFINE_PER_CPU(struct kmsan_ctx, kmsan_percpu_ctx);
+
+元数æ®åˆ†é…
+~~~~~~~~~~
+
+内核中有多个地方存储元数æ®ã€‚
+
+1. æ¯ä¸ª ``struct page`` 实例包å«ä¸¤ä¸ªæŒ‡å‘å…¶å½±å­å’Œå†…存页é¢çš„æŒ‡é’ˆ
+::
+
+ struct page {
+ ...
+ struct page *shadow, *origin;
+ ...
+ };
+
+在å¯åŠ¨æ—¶ï¼Œå†…æ ¸ä¸ºæ¯ä¸ªå¯ç”¨çš„内核页é¢åˆ†é…å½±å­å’Œæºé¡µé¢ã€‚这是在内核地å€ç©ºé—´å·²ç»ç¢Žç‰‡
+化时åŽå®Œæˆçš„,完æˆçš„相当晚,因此普通数æ®é¡µé¢å¯èƒ½ä¸Žå…ƒæ•°æ®é¡µé¢ä»»æ„交错。
+
+è¿™æ„味ç€é€šå¸¸ä¸¤ä¸ªç›¸é‚»çš„内存页é¢ï¼Œå®ƒä»¬çš„å½±å­/æºé¡µé¢å¯èƒ½ä¸æ˜¯è¿žç»­çš„。因此,如果内存
+访问跨越内存å—的边界,访问影å­/æºå†…å­˜å¯èƒ½ä¼šç ´å其他页颿ˆ–从中读å–错误的值。
+
+å®žé™…ä¸Šï¼Œç”±ç›¸åŒ ``alloc_pages()`` 调用返回的连续内存页é¢å°†å…·æœ‰è¿žç»­çš„元数æ®ï¼Œè€Œ
+如果这些页é¢å±žäºŽä¸¤ä¸ªä¸åŒçš„分é…,它们的元数æ®é¡µé¢å¯èƒ½ä¼šè¢«ç¢Žç‰‡åŒ–。
+
+对于内核数æ®ï¼ˆ ``.data``〠``.bss`` ç­‰ï¼‰å’Œæ¯ CPU 内存区域,也没有对元数æ®è¿žç»­
+性的ä¿è¯ã€‚
+
+在 ``__msan_metadata_ptr_for_XXX_YYY()`` é‡åˆ°ä¸¤ä¸ªé¡µé¢ä¹‹é—´çš„
+éžè¿žç»­å…ƒæ•°æ®è¾¹ç•Œæ—¶ï¼Œå®ƒè¿”回指å‘å‡å½±å­/æºåŒºåŸŸçš„æŒ‡é’ˆ::
+
+ char dummy_load_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+ char dummy_store_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+
+``dummy_load_page`` 被åˆå§‹åŒ–为零,因此读å–它始终返回零。对 ``dummy_store_page`` çš„
+所有写入都被忽略。
+
+2. 对于 vmalloc 内存和模å—,内存范围ã€å½±å­å’Œæºä¹‹é—´æœ‰ä¸€ä¸ªç›´æŽ¥æ˜ å°„。KMSAN å°†
+vmalloc 区域缩å°äº† 3/4,仅使å‰å››åˆ†ä¹‹ä¸€å¯ç”¨äºŽ ``vmalloc()``。vmalloc
+区域的第二个四分之一包å«ç¬¬ä¸€ä¸ªå››åˆ†ä¹‹ä¸€çš„å½±å­å†…存,第三个四分之一ä¿å­˜æºã€‚第四个
+四分之一的å°éƒ¨åˆ†åŒ…å«å†…核模å—的影å­å’Œæºã€‚有关更多详细信æ¯ï¼Œè¯·å‚阅
+``arch/x86/include/asm/pgtable_64_types.h``。
+
+å½“ä¸€ç³»åˆ—é¡µé¢æ˜ å°„到一个连续的虚拟内存空间时,它们的影å­å’Œæºé¡µé¢ä¹Ÿä»¥è¿žç»­åŒºåŸŸçš„æ–¹
+弿˜ å°„。
+
+å‚考文献
+========
+
+E. Stepanov, K. Serebryany. `MemorySanitizer: fast detector of uninitialized
+memory use in C++
+<https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43308.pdf>`_.
+In Proceedings of CGO 2015.
+
+.. _MemorySanitizer tool: https://clang.llvm.org/docs/MemorySanitizer.html
+.. _LLVM documentation: https://llvm.org/docs/GettingStarted.html
+.. _LKML discussion: https://lore.kernel.org/all/20220614144853.3693273-1-glider@google.com/
diff --git a/Documentation/translations/zh_CN/glossary.rst b/Documentation/translations/zh_CN/glossary.rst
index 24f094df97cd..5975b0426f3d 100644
--- a/Documentation/translations/zh_CN/glossary.rst
+++ b/Documentation/translations/zh_CN/glossary.rst
@@ -34,3 +34,4 @@
* semaphores: ä¿¡å·é‡ã€‚
* spinlock: 自旋é”。
* watermark: æ°´ä½ï¼Œä¸€èˆ¬æŒ‡é¡µè¡¨çš„æ¶ˆè€—水平。
+* PTE: 页表项。(Page Table Entry)
diff --git a/Documentation/translations/zh_CN/kbuild/index.rst b/Documentation/translations/zh_CN/kbuild/index.rst
index b51655d981f6..3f9ab52fa5bb 100644
--- a/Documentation/translations/zh_CN/kbuild/index.rst
+++ b/Documentation/translations/zh_CN/kbuild/index.rst
@@ -12,20 +12,21 @@
.. toctree::
:maxdepth: 1
+ kconfig
headers_install
gcc-plugins
+ kbuild
+ reproducible-builds
+ llvm
TODO:
- kconfig-language
- kconfig-macro-language
-- kbuild
-- kconfig
- makefiles
- modules
- issues
-- reproducible-builds
-- llvm
+
.. only:: subproject and html
diff --git a/Documentation/translations/zh_CN/kbuild/kbuild.rst b/Documentation/translations/zh_CN/kbuild/kbuild.rst
new file mode 100644
index 000000000000..e5e2aebe1ebc
--- /dev/null
+++ b/Documentation/translations/zh_CN/kbuild/kbuild.rst
@@ -0,0 +1,304 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/kbuild/kbuild.rst
+:Translator: 慕冬亮 Dongliang Mu <dzm91@hust.edu.cn>
+
+======
+Kbuild
+======
+
+
+输出文件
+========
+
+modules.order
+-------------
+该文件记录模å—在 Makefile 中出现的顺åºã€‚modprobe 使用该文件æ¥ç¡®å®šæ€§
+è§£æžåŒ¹é…多个模å—的别å。
+
+modules.builtin
+---------------
+该文件列出了所有内置到内核中的模å—。modprobe 使用该文件æ¥é¿å…å°è¯•加载
+å†…ç½®æ¨¡å—æ—¶å‡ºé”™ã€‚
+
+modules.builtin.modinfo
+-----------------------
+è¯¥æ–‡ä»¶åŒ…å«æ‰€æœ‰å†…置模å—çš„ modinfo。与å•独模å—çš„ modinfo ä¸åŒï¼Œæ‰€æœ‰å­—段
+都带有模å—åç§°å‰ç¼€ã€‚
+
+modules.builtin.ranges
+----------------------
+è¯¥æ–‡ä»¶åŒ…å«æ‰€æœ‰å†…核内置模å—的地å€å移范围(æ¯ä¸ª ELF èŠ‚ï¼‰ã€‚ç»“åˆ System.map
+文件,它å¯ä»¥ç”¨æ¥å°†æ¨¡å—å称与符å·å…³è”èµ·æ¥ã€‚
+
+环境å˜é‡
+========
+
+KCPPFLAGS
+---------
+åœ¨é¢„å¤„ç†æ—¶ä¼ é€’çš„é¢å¤–选项。kbuild 进行所有预处ç†ï¼ˆåŒ…括构建 C 文件和汇编文件)
+时,都会使用这些预处ç†é€‰é¡¹ã€‚
+
+KAFLAGS
+-------
+传递给汇编器的é¢å¤–选项(适用于内置模å—和外部模å—)。
+
+AFLAGS_MODULE
+-------------
+外部模å—çš„é¢å¤–汇编选项。
+
+AFLAGS_KERNEL
+-------------
+内置模å—çš„é¢å¤–汇编选项。
+
+KCFLAGS
+-------
+传递给 C 编译器的é¢å¤–选项(适用于内置模å—和外部模å—)。
+
+KRUSTFLAGS
+----------
+传递给 Rust 编译器的é¢å¤–选项(适用于内置模å—和外部模å—)。
+
+CFLAGS_KERNEL
+-------------
+åœ¨ç¼–è¯‘å†…ç½®ä»£ç æ—¶ï¼Œä¼ é€’ç»™ $(CC) çš„é¢å¤–选项。
+
+CFLAGS_MODULE
+-------------
+ç¼–è¯‘å¤–éƒ¨æ¨¡å—æ—¶ï¼Œä¼ é€’ç»™ $(CC) çš„é¢å¤–模å—特定选项。
+
+RUSTFLAGS_KERNEL
+----------------
+åœ¨ç¼–è¯‘å†…ç½®ä»£ç æ—¶ï¼Œä¼ é€’ç»™ $(RUSTC) çš„é¢å¤–选项。
+
+RUSTFLAGS_MODULE
+----------------
+用于 $(RUSTC) çš„é¢å¤–模å—特定选项。
+
+LDFLAGS_MODULE
+--------------
+用于 $(LD) é“¾æŽ¥æ¨¡å—æ—¶çš„é¢å¤–选项。
+
+HOSTCFLAGS
+----------
+åœ¨æž„å»ºä¸»æœºç¨‹åºæ—¶ä¼ é€’ç»™ $(HOSTCC) çš„é¢å¤–标志。
+
+HOSTCXXFLAGS
+------------
+åœ¨æž„å»ºä¸»æœºç¨‹åºæ—¶ä¼ é€’ç»™ $(HOSTCXX) çš„é¢å¤–标志。
+
+HOSTRUSTFLAGS
+-------------
+åœ¨æž„å»ºä¸»æœºç¨‹åºæ—¶ä¼ é€’ç»™ $(HOSTRUSTC) çš„é¢å¤–标志。
+
+HOSTLDFLAGS
+-----------
+é“¾æŽ¥ä¸»æœºç¨‹åºæ—¶ä¼ é€’çš„é¢å¤–选项。
+
+HOSTLDLIBS
+----------
+åœ¨æž„å»ºä¸»æœºç¨‹åºæ—¶é“¾æŽ¥çš„é¢å¤–库。
+
+.. _zh_cn_userkbuildflags:
+
+USERCFLAGS
+----------
+用于 $(CC) 编译用户程åºï¼ˆuserprogs)时的é¢å¤–选项。
+
+USERLDFLAGS
+-----------
+用于 $(LD) é“¾æŽ¥ç”¨æˆ·ç¨‹åºæ—¶çš„é¢å¤–选项。用户程åºï¼ˆuserprogs)是使用 CC 链接的,
+å› æ­¤ $(USERLDFLAGS) 应该根æ®éœ€è¦åŒ…å« "-Wl," å‰ç¼€ã€‚
+
+KBUILD_KCONFIG
+--------------
+将顶级 Kconfig 文件设置为此环境å˜é‡çš„值。默认å称为 "Kconfig"。
+
+KBUILD_VERBOSE
+--------------
+设置 kbuild 的详细程度。å¯ä»¥åˆ†é…与 "V=..." 相åŒçš„值。
+
+有关完整列表,请å‚è§ `make help`。
+
+设置 "V=..." 优先于 KBUILD_VERBOSE。
+
+KBUILD_EXTMOD
+-------------
+åœ¨æž„å»ºå¤–éƒ¨æ¨¡å—æ—¶è®¾ç½®å†…æ ¸æºä»£ç çš„æœç´¢ç›®å½•ã€‚
+
+设置 "M=..." 优先于 KBUILD_EXTMOD。
+
+KBUILD_OUTPUT
+-------------
+指定内核构建的输出目录。
+
+在å•ç‹¬çš„æž„å»ºç›®å½•ä¸­ä¸ºé¢„æž„å»ºå†…æ ¸æž„å»ºå¤–éƒ¨æ¨¡å—æ—¶ï¼Œè¿™ä¸ªå˜é‡ä¹Ÿå¯ä»¥æŒ‡å‘内核输出目录。请注æ„,
+è¿™å¹¶ä¸æŒ‡å®šå¤–éƒ¨æ¨¡å—æœ¬èº«çš„输出目录。
+
+输出目录也å¯ä»¥ä½¿ç”¨ "O=..." 指定。
+
+设置 "O=..." 优先于 KBUILD_OUTPUT。
+
+KBUILD_EXTRA_WARN
+-----------------
+指定é¢å¤–的构建检查。也å¯ä»¥é€šè¿‡åœ¨å‘½ä»¤è¡Œä¼ é€’ "W=..." æ¥è®¾ç½®ç›¸åŒçš„值。
+
+请å‚阅 `make help` 了解支æŒçš„值列表。
+
+设置 "W=..." 优先于 KBUILD_EXTRA_WARN。
+
+KBUILD_DEBARCH
+--------------
+对于 deb-pkg 目标,å…许覆盖 deb-pkg 部署的正常å¯å‘弿–¹æ³•。通常 deb-pkg å°è¯•æ ¹æ®
+UTS_MACHINE å˜é‡ï¼ˆåœ¨æŸäº›æž¶æž„中还包括内核é…置)æ¥çŒœæµ‹æ­£ç¡®çš„æž¶æž„。KBUILD_DEBARCH
+的值å‡å®šï¼ˆä¸æ£€æŸ¥ï¼‰ä¸ºæœ‰æ•ˆçš„ Debian 架构。
+
+KDOCFLAGS
+---------
+指定在构建过程中用于 kernel-doc 检查的é¢å¤–(警告/错误)标志,查看
+scripts/kernel-doc 了解支æŒçš„æ ‡å¿—。请注æ„,这目å‰ä¸é€‚用于文档构建。
+
+ARCH
+----
+设置 ARCH ä¸ºè¦æž„建的架构。
+
+在大多数情况下,架构的å称与 arch/ 目录中的å­ç›®å½•å称相åŒã€‚
+
+但æŸäº›æž¶æž„(如 x86 å’Œ sparc)有别å。
+
+- x86: i386 表示 32 ä½ï¼Œx86_64 表示 64 ä½
+- parisc: parisc64 表示 64 ä½
+- sparc: sparc32 表示 32 ä½ï¼Œsparc64 表示 64 ä½
+
+CROSS_COMPILE
+-------------
+指定 binutils 文件åçš„å¯é€‰å›ºå®šéƒ¨åˆ†ã€‚CROSS_COMPILE å¯ä»¥æ˜¯æ–‡ä»¶å的一部分或完整路径。
+
+在æŸäº›è®¾ç½®ä¸­ï¼ŒCROSS_COMPILE 也用于 ccache。
+
+CF
+--
+用于 sparse çš„é¢å¤–选项。
+
+CF 通常在命令行中如下所示使用::
+
+ make CF=-Wbitwise C=2
+
+INSTALL_PATH
+------------
+INSTALL_PATH 指定放置更新åŽçš„内核和系统映åƒçš„路径。默认值是 /boot,但你å¯ä»¥è®¾ç½®
+为其他值。
+
+INSTALLKERNEL
+-------------
+使用 "make install" 时调用的安装脚本。
+默认å称是 "installkernel"。
+
+è¯¥è„šæœ¬å°†ä¼šä»¥ä»¥ä¸‹å‚æ•°è°ƒç”¨ï¼š
+
+ - $1 - 内核版本
+ - $2 - å†…æ ¸æ˜ åƒæ–‡ä»¶
+ - $3 - 内核映射文件
+ - $4 - 默认安装路径(如果为空,则使用根目录)
+
+"make install" 的实现是架构特定的,å¯èƒ½ä¸Žä¸Šè¿°æœ‰æ‰€ä¸åŒã€‚
+
+æä¾› INSTALLKERNEL 以便在交å‰ç¼–译内核时å¯ä»¥æŒ‡å®šè‡ªå®šä¹‰å®‰è£…程åºã€‚
+
+MODLIB
+------
+指定模å—的安装ä½ç½®ã€‚
+默认值为::
+
+ $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+
+该值å¯ä»¥è¢«è¦†ç›–ï¼Œåœ¨è¿™ç§æƒ…况下将忽略默认值。
+
+INSTALL_MOD_PATH
+----------------
+INSTALL_MOD_PATH 指定了模å—目录é‡å®šä½æ—¶ MODLIB çš„å‰ç¼€ï¼Œé€šå¸¸ç”±æž„建根
+(build roots)所需。它没有在 makefile 中定义,但如果需è¦ï¼Œå¯ä»¥ä½œä¸º
+傿•°ä¼ é€’ç»™ make。
+
+INSTALL_MOD_STRIP
+-----------------
+如果 INSTALL_MOD_STRIP 被定义,内核模å—在安装åŽä¼šè¢«å‰¥ç¦»ã€‚如果
+INSTALL_MOD_STRIP 的值为 '1',则会使用默认选项 --strip-debug。å¦åˆ™ï¼Œ
+INSTALL_MOD_STRIP 的值将作为 strip 命令的选项。
+
+INSTALL_HDR_PATH
+----------------
+INSTALL_HDR_PATH 指定了执行 "make headers_*" 时,用户空间头文件的安装ä½ç½®ã€‚
+
+默认值为::
+
+ $(objtree)/usr
+
+$(objtree) 是ä¿å­˜è¾“出文件的目录。
+输出目录通常使用命令行中的 "O=..." 进行设置。
+
+该值å¯ä»¥è¢«è¦†ç›–ï¼Œåœ¨è¿™ç§æƒ…况下将忽略默认值。
+
+INSTALL_DTBS_PATH
+-----------------
+INSTALL_DTBS_PATH 指定了设备树二进制文件的安装ä½ç½®ï¼Œé€šå¸¸ç”±æž„建根(build roots)所需。
+它没有在 makefile 中定义,但如果需è¦ï¼Œå¯ä»¥ä½œä¸ºå‚数传递给 make。
+
+KBUILD_ABS_SRCTREE
+--------------------------------------------------
+Kbuild 在å¯èƒ½çš„æƒ…å†µä¸‹ä½¿ç”¨ç›¸å¯¹è·¯å¾„æŒ‡å‘æºä»£ç æ ‘。例如,在æºä»£ç æ ‘中构建时,æºä»£ç æ ‘路径是
+'.'。
+
+设置该标志请求 Kbuild 使用æºä»£ç æ ‘çš„ç»å¯¹è·¯å¾„。
+在æŸäº›æƒ…况下这是有用的,例如在生æˆå¸¦æœ‰ç»å¯¹è·¯å¾„æ¡ç›®çš„æ ‡ç­¾æ–‡ä»¶æ—¶ç­‰ã€‚
+
+KBUILD_SIGN_PIN
+---------------
+å½“ç­¾ç½²å†…æ ¸æ¨¡å—æ—¶ï¼Œå¦‚æžœç§é’¥éœ€è¦å¯†ç æˆ– PIN,此å˜é‡å…è®¸å°†å¯†ç æˆ– PIN 传递给 sign-file 工具。
+
+KBUILD_MODPOST_WARN
+-------------------
+KBUILD_MODPOST_WARN å¯ä»¥è®¾ç½®ä¸ºåœ¨æœ€ç»ˆæ¨¡å—é“¾æŽ¥é˜¶æ®µå‡ºçŽ°æœªå®šä¹‰ç¬¦å·æ—¶é¿å…错误。它将这些错误
+转为警告。
+
+KBUILD_MODPOST_NOFINAL
+----------------------
+KBUILD_MODPOST_NOFINAL å¯ä»¥è®¾ç½®ä¸ºè·³è¿‡æ¨¡å—的最终链接。这仅在加速编译测试时有用。
+
+KBUILD_EXTRA_SYMBOLS
+--------------------
+用于ä¾èµ–其他模å—符å·çš„æ¨¡å—ã€‚è¯¦è§ modules.rst。
+
+ALLSOURCE_ARCHS
+---------------
+对于 tags/TAGS/cscope 目标,å¯ä»¥æŒ‡å®šåŒ…å«åœ¨æ•°æ®åº“中的多个架构,用空格分隔。例如::
+
+ $ make ALLSOURCE_ARCHS="x86 mips arm" tags
+
+è¦èŽ·å–æ‰€æœ‰å¯ç”¨æž¶æž„,也å¯ä»¥æŒ‡å®š all。例如::
+
+ $ make ALLSOURCE_ARCHS=all tags
+
+IGNORE_DIRS
+-----------
+对于 tags/TAGS/cscope 目标,å¯ä»¥é€‰æ‹©ä¸åŒ…å«åœ¨æ•°æ®åº“中的目录,用空格分隔。例如::
+
+ $ make IGNORE_DIRS="drivers/gpu/drm/radeon tools" cscope
+
+KBUILD_BUILD_TIMESTAMP
+----------------------
+将该环境å˜é‡è®¾ç½®ä¸ºæ—¥æœŸå­—符串,å¯ä»¥è¦†ç›–在 UTS_VERSION 定义中使用的时间戳
+(è¿è¡Œå†…核时的 uname -v)。该值必须是一个å¯ä»¥ä¼ é€’ç»™ date -d 的字符串。默认值是
+内核构建æŸä¸ªæ—¶åˆ»çš„ date 命令输出。
+
+KBUILD_BUILD_USER, KBUILD_BUILD_HOST
+------------------------------------
+这两个å˜é‡å…许覆盖å¯åŠ¨æ—¶æ˜¾ç¤ºçš„ user@host å­—ç¬¦ä¸²ä»¥åŠ /proc/version 中的信æ¯ã€‚
+默认值分别是 whoami 和 host 命令的输出。
+
+LLVM
+----
+如果该å˜é‡è®¾ç½®ä¸º 1,Kbuild 将使用 Clang å’Œ LLVM å·¥å…·ï¼Œè€Œä¸æ˜¯ GCC å’Œ GNU
+binutils æ¥æž„建内核。
diff --git a/Documentation/translations/zh_CN/kbuild/kconfig.rst b/Documentation/translations/zh_CN/kbuild/kconfig.rst
new file mode 100644
index 000000000000..3b06d8913dbf
--- /dev/null
+++ b/Documentation/translations/zh_CN/kbuild/kconfig.rst
@@ -0,0 +1,259 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/kbuild/kconfig.rst
+:Translator: 慕冬亮 Dongliang Mu <dzm91@hust.edu.cn>
+
+================
+é…置目标和编辑器
+================
+
+本文件包å«ä½¿ç”¨ ``make *config`` 的一些帮助。
+
+使用 ``make help`` 列出所有å¯èƒ½çš„é…置目标。
+
+xconfig('qconf')ã€menuconfig('mconf')和 nconfig('nconf')程åºä¹ŸåŒ…å«
+内嵌的帮助文本。请务必查看这些帮助文本以获å–å¯¼èˆªã€æœç´¢å’Œå…¶ä»–帮助信æ¯ã€‚
+
+gconfig('gconf')程åºçš„帮助文本较少。
+
+
+通用信æ¯
+========
+
+新的内核版本通常会引入新的é…置符å·ã€‚æ›´é‡è¦çš„æ˜¯ï¼Œæ–°çš„内核版本å¯èƒ½ä¼šé‡å‘½åé…置符å·ã€‚
+å½“è¿™ç§æƒ…况å‘ç”Ÿæ—¶ï¼Œä½¿ç”¨ä¹‹å‰æ­£å¸¸å·¥ä½œçš„ .config 文件并è¿è¡Œ "make oldconfig"
+ä¸ä¸€å®šä¼šç”Ÿæˆä¸€ä¸ªå¯æ­£å¸¸å·¥ä½œçš„æ–°å†…核,因此,你å¯èƒ½éœ€è¦æŸ¥çœ‹å“ªäº›æ–°çš„内核符å·è¢«å¼•入。
+
+è¦æŸ¥çœ‹æ–°é…置符å·çš„列表,请使用::
+
+ cp user/some/old.config .config
+ make listnewconfig
+
+é…置程åºå°†åˆ—出所有新é…置符å·ï¼Œæ¯è¡Œä¸€ä¸ªã€‚
+
+或者,你å¯ä»¥ä½¿ç”¨æš´åŠ›ç ´è§£æ–¹æ³•::
+
+ make oldconfig
+ scripts/diffconfig .config.old .config | less
+
+
+环境å˜é‡
+========
+
+``*config`` 的环境å˜é‡ï¼š
+
+``KCONFIG_CONFIG``
+ 该环境å˜é‡å¯ç”¨äºŽæŒ‡å®šä¸€ä¸ªé»˜è®¤çš„内核é…置文件å,以覆盖默认的 ".config"。
+
+``KCONFIG_DEFCONFIG_LIST``
+ 该环境å˜é‡æŒ‡å®šäº†ä¸€ä¸ªé…置文件列表,当 .config ä¸å­˜åœ¨æ—¶ï¼Œè¿™äº›æ–‡ä»¶å¯ç”¨ä½œåŸºç¡€é…置。
+ 列表中的æ¡ç›®ä»¥ç©ºæ ¼åˆ†éš”ï¼Œåªæœ‰ç¬¬ä¸€ä¸ªå­˜åœ¨çš„æ–‡ä»¶ä¼šè¢«ä½¿ç”¨ã€‚
+
+``KCONFIG_OVERWRITECONFIG``
+ 如果该环境å˜é‡è¢«è®¾ç½®ï¼Œå½“ .config 是指å‘å…¶ä»–ä½ç½®çš„符å·é“¾æŽ¥æ—¶ï¼ŒKconfig ä¸ä¼š
+ ç ´å符å·é“¾æŽ¥ã€‚
+
+``KCONFIG_WARN_UNKNOWN_SYMBOLS``
+ 该环境å˜é‡ä½¿ Kconfig 对é…置输入中所有无法识别的符å·å‘出警告。
+
+``KCONFIG_WERROR``
+ 如果该环境å˜é‡è¢«è®¾ç½®ï¼ŒKconfig 将所有警告视为错误。
+
+``CONFIG_``
+ 如果该环境å˜é‡è¢«è®¾ç½®ï¼ŒKconfig 将在ä¿å­˜é…ç½®æ—¶ï¼Œä¸ºæ‰€æœ‰ç¬¦å·æ·»åŠ å…¶å€¼ä½œä¸ºå‰ç¼€ï¼Œ
+ è€Œä¸æ˜¯ä½¿ç”¨é»˜è®¤å€¼ã€‚
+
+``{allyes/allmod/allno/rand}config`` 的环境å˜é‡ï¼š
+
+``KCONFIG_ALLCONFIG``
+ allyesconfig/allmodconfig/allnoconfig/randconfig 这些å˜ä½“也å¯ä»¥ä½¿ç”¨çŽ¯å¢ƒ
+ å˜é‡ KCONFIG_ALLCONFIG 作为标志或包å«ç”¨æˆ·è¦æ±‚设置为特定值的é…置符å·çš„æ–‡ä»¶å。
+ 如果 KCONFIG_ALLCONFIG 未指定文件åï¼Œå³ KCONFIG_ALLCONFIG == "" 或
+ KCONFIG_ALLCONFIG == "1",则 ``make *config`` 将查找å为
+ "all{yes/mod/no/def/random}.config" 的文件(对应于所使用的 ``*config``
+ 命令)以强制符å·å€¼ã€‚如果找ä¸åˆ°æ­¤æ–‡ä»¶ï¼Œå®ƒä¼šæŸ¥æ‰¾å为 "all.config" 的文件以包å«
+ 强制值。
+
+ è¿™å¯ä»¥åˆ›å»ºâ€œå¾®åž‹â€é…置(miniconfig)或自定义é…ç½®æ–‡ä»¶ï¼Œå…¶ä¸­ä»…åŒ…å«æ„Ÿå…´è¶£çš„é…置符å·ã€‚
+ ç„¶åŽï¼Œå†…æ ¸é…置系统将生æˆå®Œæ•´çš„ .config 文件,包括 miniconfig 文件中的符å·ã€‚
+
+ ``KCONFIG_ALLCONFIG`` 文件包å«è®¸å¤šé¢„设é…置符å·ï¼ˆé€šå¸¸æ˜¯æ‰€æœ‰ç¬¦å·çš„å­é›†ï¼‰ã€‚
+ 这些å˜é‡è®¾ç½®ä»éœ€éµå®ˆæ­£å¸¸çš„ä¾èµ–性检查。
+
+ 示例::
+
+ KCONFIG_ALLCONFIG=custom-notebook.config make allnoconfig
+
+ 或::
+
+ KCONFIG_ALLCONFIG=mini.config make allnoconfig
+
+ 或::
+
+ make KCONFIG_ALLCONFIG=mini.config allnoconfig
+
+ 这些示例将ç¦ç”¨å¤§å¤šæ•°é…置选项(allnoconfig),但å¯ç”¨æˆ–ç¦ç”¨ miniconfig 文件
+ 中显å¼åˆ—出的选项。
+
+``randconfig`` 的环境å˜é‡ï¼š
+
+``KCONFIG_SEED``
+ 如果你想调试 kconfig è§£æžå™¨/å‰ç«¯çš„行为,你å¯ä»¥å°†æ­¤å˜é‡è®¾ç½®æ•´æ•°å€¼ï¼Œç”¨äºŽåˆå§‹åŒ–
+ éšæœºæ•°ç”Ÿæˆå™¨ã€‚å¦‚æžœæœªè®¾ç½®ï¼Œå°†ä½¿ç”¨å½“å‰æ—¶é—´ã€‚
+
+``KCONFIG_PROBABILITY``
+ 该å˜é‡å¯ç”¨äºŽå€¾æ–œæ¦‚率分布。此å˜é‡å¯ä¸è®¾ç½®æˆ–设置为空,或设置为以下三ç§ä¸åŒæ ¼å¼ï¼š
+
+ ======================= ================== =====================
+ KCONFIG_PROBABILITY y:n åˆ†é… y:m:n 分é…
+ ======================= ================== =====================
+ 未设置或设置为空 50 : 50 33 : 33 : 34
+ N N : 100-N N/2 : N/2 : 100-N
+ [1] N:M N+M : 100-(N+M) N : M : 100-(N+M)
+ [2] N:M:L N : 100-N M : L : 100-(M+L)
+ ======================= ================== =====================
+
+其中 Nã€M å’Œ L 是范围在 [0,100] 内的整数(以å进制表示),并且需满足:
+
+ [1] N+M 的范围在 [0,100] 之间
+
+ [2] M+L 的范围在 [0,100] 之间
+
+示例::
+
+ KCONFIG_PROBABILITY=10
+ 10% 的布尔值将设置为 'y',90% 设置为 'n'
+ 5% 的三æ€å€¼å°†è®¾ç½®ä¸º 'y',5% 设置为 'm',90% 设置为 'n'
+ KCONFIG_PROBABILITY=15:25
+ 40% 的布尔值将设置为 'y',60% 设置为 'n'
+ 15% 的三æ€å€¼å°†è®¾ç½®ä¸º 'y',25% 设置为 'm',60% 设置为 'n'
+ KCONFIG_PROBABILITY=10:15:15
+ 10% 的布尔值将设置为 'y',90% 设置为 'n'
+ 15% 的三æ€å€¼å°†è®¾ç½®ä¸º 'y',15% 设置为 'm',70% 设置为 'n'
+
+``syncconfig`` 的环境å˜é‡ï¼š
+
+``KCONFIG_NOSILENTUPDATE``
+ 如果该å˜é‡éžç©ºï¼Œå®ƒå°†é˜»æ­¢é™é»˜çš„内核é…ç½®æ›´æ–°ï¼ˆéœ€è¦æ˜Žç¡®æ›´æ–°ï¼‰ã€‚
+
+``KCONFIG_AUTOCONFIG``
+ 该环境å˜é‡å¯ä»¥è®¾ç½®ä¸º "auto.conf" 文件的路径和å称。默认值为
+ "include/config/auto.conf"。
+
+``KCONFIG_AUTOHEADER``
+ 该环境å˜é‡å¯ä»¥è®¾ç½®ä¸º "autoconf.h" 头文件的路径和å称。默认值为
+ "include/generated/autoconf.h"。
+
+menuconfig
+==========
+
+在 menuconfig 中æœç´¢ï¼š
+
+ æœç´¢åŠŸèƒ½ä¼šæœç´¢å†…æ ¸é…置符å·åç§°ï¼Œå› æ­¤ä½ å¿…é¡»çŸ¥é“æ¬²æœç´¢å†…容的大致å称。
+
+ 示例::
+
+ /hotplug
+ è¿™ä¼šåˆ—å‡ºæ‰€æœ‰åŒ…å« "hotplug" çš„é…置符å·ï¼Œä¾‹å¦‚,HOTPLUG_CPU,
+ MEMORY_HOTPLUG。
+
+ è‹¥éœ€è¦æœç´¢å¸®åŠ©ï¼Œè¾“å…¥ / åŽè·Ÿ TAB-TAB(高亮显示 <Help>)并按回车键。
+ 这说明你还å¯ä»¥åœ¨æœç´¢å­—符串中使用正则表达å¼ï¼ˆregex),所以如果你对
+ MEMORY_HOTPLUG 䏿„Ÿå…´è¶£ï¼Œä½ å¯ä»¥å°è¯•::
+
+ /^hotplug
+
+ 在æœç´¢æ—¶ï¼Œç¬¦å·å°†æŒ‰ä»¥ä¸‹é¡ºåºæŽ’åºï¼š
+
+ - 首先,完全匹é…的符å·ï¼ŒæŒ‰å­—æ¯é¡ºåºæŽ’åˆ—ï¼ˆå®Œå…¨åŒ¹é…æ˜¯æŒ‡æœç´¢ä¸Žç¬¦å·å称完全匹é…);
+ - ç„¶åŽæ˜¯å…¶ä»–匹é…项,按字æ¯é¡ºåºæŽ’列。
+
+ 例如,^ATH.K 匹é…::
+
+ ATH5K ATH9K ATH5K_AHB ATH5K_DEBUG [...] ATH6KL ATH6KL_DEBUG
+ [...] ATH9K_AHB ATH9K_BTCOEX_SUPPORT ATH9K_COMMON [...]
+
+ å…¶ä¸­åªæœ‰ ATH5K å’Œ ATH9K 完全匹é…,因此它们排在å‰é¢ï¼ˆæŒ‰å­—æ¯é¡ºåºï¼‰ï¼Œ
+ æŽ¥ä¸‹æ¥æ˜¯å…¶ä»–符å·ï¼ŒåŒæ ·æŒ‰å­—æ¯é¡ºåºæŽ’列。
+
+ 在此èœå•中,按下以 (#) 为å‰ç¼€çš„键将直接跳转到该ä½ç½®ã€‚退出此新èœå•åŽï¼Œ
+ 你将返回当å‰çš„æœç´¢ç»“æžœã€‚
+
+'menuconfig' 的用户界é¢é€‰é¡¹ï¼š
+
+``MENUCONFIG_COLOR``
+ å¯ä»¥ä½¿ç”¨å˜é‡ MENUCONFIG_COLOR 选择ä¸åŒçš„é…色主题。使用以下命令选择主题::
+
+ make MENUCONFIG_COLOR=<theme> menuconfig
+
+ å¯ç”¨çš„主题有::
+
+ - mono => 选择适åˆå•色显示器的颜色
+ - blackbg => 选择具有黑色背景的é…色方案
+ - classic => ç»å…¸å¤–观,è“色背景
+ - bluetitle => ç»å…¸å¤–è§‚çš„ LCD å‹å¥½ç‰ˆæœ¬ï¼ˆé»˜è®¤ï¼‰
+
+``MENUCONFIG_MODE``
+ 此模å¼ä¼šå°†æ‰€æœ‰å­èœå•显示为一个大树状结构。
+
+ 示例::
+
+ make MENUCONFIG_MODE=single_menu menuconfig
+
+nconfig
+=======
+
+nconfig 是一个替代的基于文本的é…置工具。它在终端(窗å£ï¼‰åº•部列出功能键,用于执行
+命令。除éžä½ åœ¨æ•°æ®è¾“入窗å£ä¸­ï¼Œå¦åˆ™ä½ ä¹Ÿå¯ä»¥ç›´æŽ¥ä½¿ç”¨ç›¸åº”çš„æ•°å­—é”®æ¥æ‰§è¡Œå‘½ä»¤ã€‚例如,你
+å¯ä»¥ç›´æŽ¥æŒ‰ 6ï¼Œè€Œéž F6 进行ä¿å­˜ã€‚
+
+使用 F1 获å–全局帮助或 F3 打开简短帮助èœå•。
+
+在 nconfig 中æœç´¢ï¼š
+
+ ä½ å¯ä»¥åœ¨èœå•项“æç¤ºâ€å­—符串中或é…置符å·ä¸­è¿›è¡Œæœç´¢ã€‚
+
+ 使用 / 开始在èœå•项中æœç´¢ã€‚è¿™ä¸æ”¯æŒæ­£åˆ™è¡¨è¾¾å¼ã€‚使用 <Down> 或 <Up>
+ 分别为下一个命中项和上一个命中项。使用 <Esc> 退出æœç´¢æ¨¡å¼ã€‚
+
+ F8(SymSearch)在é…置符å·ä¸­æœç´¢ç»™å®šçš„字符串或正则表达å¼ï¼ˆregex)。
+
+ 在 SymSearch 中,按下 (#) å‰ç¼€çš„键会直接跳转到该ä½ç½®ã€‚退出该新èœå•åŽï¼Œ
+ 你将返回到当å‰çš„æœç´¢ç»“æžœã€‚
+
+环境å˜é‡ï¼š
+
+``NCONFIG_MODE``
+ 此模å¼ä¼šå°†æ‰€æœ‰å­èœå•显示为一个大型树结构。
+
+ 示例::
+
+ make NCONFIG_MODE=single_menu nconfig
+
+xconfig
+=======
+
+在 xconfig 中æœç´¢ï¼š
+
+ æœç´¢åŠŸèƒ½ä¼šæœç´¢å†…æ ¸é…置符å·åç§°ï¼Œå› æ­¤ä½ å¿…é¡»çŸ¥é“æ¬²æœç´¢å†…容的大致å称。
+
+ 示例::
+
+ Ctrl-F hotplug
+
+ 或::
+
+ èœå•:File, Search, hotplug
+
+ 列出所有符å·åç§°ä¸­åŒ…å« "hotplug" çš„é…置符å·é¡¹ã€‚在此æœç´¢å¯¹è¯æ¡†ä¸­ï¼Œ
+ ä½ å¯ä»¥æ›´æ”¹ä»»ä½•æœªç°æ˜¾æ¡ç›®çš„é…置设置。你还å¯ä»¥è¾“å…¥ä¸åŒçš„æœç´¢å­—ç¬¦ä¸²ï¼Œ
+ 而无需返回主èœå•。
+
+gconfig
+=======
+
+在 gconfig 中æœç´¢ï¼š
+
+ gconfig 中没有æœç´¢å‘½ä»¤ã€‚然而,gconfig 具有几ç§ä¸åŒçš„æŸ¥çœ‹é€‰æ‹©ã€æ¨¡å¼å’Œé€‰é¡¹ã€‚
diff --git a/Documentation/translations/zh_CN/kbuild/llvm.rst b/Documentation/translations/zh_CN/kbuild/llvm.rst
new file mode 100644
index 000000000000..f87e0181d8e7
--- /dev/null
+++ b/Documentation/translations/zh_CN/kbuild/llvm.rst
@@ -0,0 +1,203 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/kbuild/llvm.rst
+:Translator: 慕冬亮 Dongliang Mu <dzm91@hust.edu.cn>
+
+==========================
+使用 Clang/LLVM 构建 Linux
+==========================
+
+本文档介ç»å¦‚何使用 Clang å’Œ LLVM 工具构建 Linux 内核。
+
+关于
+----
+
+Linux 内核传统上一直使用 GNU 工具链(如 GCC å’Œ binutils)进行编译。æŒç»­çš„工作使得
+`Clang <https://clang.llvm.org/>`_ å’Œ `LLVM <https://llvm.org/>`_ 工具å¯
+作为å¯è¡Œçš„æ›¿ä»£å“。一些å‘行版,如 `Android <https://www.android.com/>`_ã€
+`ChromeOS <https://www.chromium.org/chromium-os>`_ã€`OpenMandriva
+<https://www.openmandriva.org/>`_ 和 `Chimera Linux
+<https://chimera-linux.org/>`_ 使用 Clang 编译的内核。谷歌和 Meta 的数æ®ä¸­å¿ƒ
+集群也è¿è¡Œç”± Clang 编译的内核。
+
+`LLVM 是由 C++ å¯¹è±¡å®žçŽ°çš„å·¥å…·é“¾ç»„ä»¶é›†åˆ <https://www.aosabook.org/en/llvm.html>`_。
+Clang 是 LLVM çš„å‰ç«¯ï¼Œæ”¯æŒ C 语言和内核所需的 GNU C 扩展,其å‘音为 "klang",而éž
+"see-lang"。
+
+使用 LLVM 构建
+--------------
+
+通过以下命令调用 ``make``::
+
+ make LLVM=1
+
+为主机目标进行编译。对于交å‰ç¼–译::
+
+ make LLVM=1 ARCH=arm64
+
+LLVM= 傿•°
+----------
+
+LLVM 有 GNU binutils 工具的替代å“。这些工具å¯ä»¥å•独å¯ç”¨ã€‚以下是支æŒçš„ make å˜é‡
+完整列表::
+
+ make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \
+ OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \
+ HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld
+
+``LLVM=1`` 扩展为上述命令。
+
+如果你的 LLVM 工具ä¸åœ¨ PATH 中,你å¯ä»¥ä½¿ç”¨ä»¥æ–œæ ç»“尾的 LLVM å˜é‡æä¾›å®ƒä»¬çš„ä½ç½®::
+
+ make LLVM=/path/to/llvm/
+
+这将使用 ``/path/to/llvm/clang``ã€``/path/to/llvm/ld.lld`` 等工具。也å¯ä»¥
+使用以下命令::
+
+ PATH=/path/to/llvm:$PATH make LLVM=1
+
+如果你的 LLVM 工具带有版本åŽç¼€ï¼Œå¹¶ä¸”ä½ å¸Œæœ›æµ‹è¯•è¯¥ç‰¹å®šç‰ˆæœ¬è€Œéžæ— åŽç¼€çš„坿‰§è¡Œæ–‡ä»¶ï¼Œ
+类似于 ``LLVM=1``,你å¯ä»¥ä½¿ç”¨ ``LLVM`` å˜é‡ä¼ é€’该åŽç¼€::
+
+ make LLVM=-14
+
+这将使用 ``clang-14``ã€``ld.lld-14`` 等工具。为了支æŒå¸¦æœ‰ç‰ˆæœ¬åŽç¼€çš„æ ‘外路径组åˆï¼Œ
+我们建议::
+
+ PATH=/path/to/llvm/:$PATH make LLVM=-14
+
+``LLVM=0`` 与çœç•¥ ``LLVM`` 完全ä¸åŒï¼Œå®ƒå°†è¡¨çŽ°å¾—åƒ ``LLVM=1``。如果你åªå¸Œæœ›ä½¿ç”¨
+æŸäº› LLVM 工具,请使用它们å„自的 make å˜é‡ã€‚
+
+在通过ä¸åŒå‘½ä»¤é…ç½®å’Œæž„å»ºæ—¶ï¼Œåº”ä¸ºæ¯æ¬¡è°ƒç”¨ ``make`` 设置相åŒçš„ ``LLVM=`` 值。如果
+è¿è¡Œçš„脚本最终会调用 ``make``,则还应将 ``LLVM=`` 设置为环境å˜é‡ã€‚
+
+交å‰ç¼–译
+--------
+
+å•个 Clang 编译器二进制文件(åŠå…¶å¯¹åº”çš„ LLVM å·¥å…·ï¼‰é€šå¸¸ä¼šåŒ…å«æ‰€æœ‰æ”¯æŒçš„åŽç«¯ï¼Œè¿™å¯ä»¥
+简化交å‰ç¼–译,尤其是使用 ``LLVM=1`` 时。如果仅使用 LLVM 工具,``CROSS_COMPILE``
+或目标三元组å‰ç¼€å°±å˜å¾—ä¸å¿…è¦ã€‚示例::
+
+ make LLVM=1 ARCH=arm64
+
+ä½œä¸ºæ··åˆ LLVM å’Œ GNU å·¥å…·çš„ç¤ºä¾‹ï¼Œå¯¹äºŽåƒ ``ARCH=s390`` 这样目å‰å°šä¸æ”¯æŒ
+``ld.lld`` 或 ``llvm-objcopy`` 的目标,你å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼è°ƒç”¨ ``make``::
+
+ make LLVM=1 ARCH=s390 LD=s390x-linux-gnu-ld.bfd \
+ OBJCOPY=s390x-linux-gnu-objcopy
+
+此示例将调用 ``s390x-linux-gnu-ld.bfd`` 作为链接器和
+``s390x-linux-gnu-objcopy``,因此请确ä¿å®ƒä»¬åœ¨ä½ çš„ ``$PATH`` 中。
+
+当 ``LLVM=1`` 未设置时,``CROSS_COMPILE`` ä¸ä¼šç”¨äºŽç»™ Clang 编译器二进制文件
+(或相应的 LLVM 工具)添加å‰ç¼€ï¼Œè€Œ GNU 工具则需è¦è¿™æ ·åšã€‚
+
+LLVM_IAS= 傿•°
+--------------
+
+Clang å¯ä»¥ç¼–译汇编代ç ã€‚ä½ å¯ä»¥ä¼ é€’ ``LLVM_IAS=0`` ç¦ç”¨æ­¤è¡Œä¸ºï¼Œä½¿ Clang 调用
+相应的éžé›†æˆæ±‡ç¼–器。示例::
+
+ make LLVM=1 LLVM_IAS=0
+
+在交å‰ç¼–译时,你需è¦ä½¿ç”¨ ``CROSS_COMPILE`` 与 ``LLVM_IAS=0``,从而设置
+``--prefix=`` 使得编译器å¯ä»¥å¯¹åº”çš„éžé›†æˆæ±‡ç¼–器(通常,在é¢å‘å¦ä¸€ç§æž¶æž„时,
+你䏿ƒ³ä½¿ç”¨ç³»ç»Ÿæ±‡ç¼–器)。例如::
+
+ make LLVM=1 ARCH=arm LLVM_IAS=0 CROSS_COMPILE=arm-linux-gnueabi-
+
+Ccache
+------
+
+``ccache`` å¯ä»¥ä¸Ž ``clang`` 一起使用,以改善åŽç»­æž„建(尽管在ä¸åŒæž„建之间
+KBUILD_BUILD_TIMESTAMP_ 应设置为åŒä¸€ç¡®å®šå€¼ï¼Œä»¥é¿å… 100% 的缓存未命中,
+è¯¦è§ Reproducible_builds_ èŽ·å–æ›´å¤šä¿¡æ¯ï¼‰::
+
+ KBUILD_BUILD_TIMESTAMP='' make LLVM=1 CC="ccache clang"
+
+.. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp
+.. _Reproducible_builds: reproducible-builds.html#timestamps
+
+支æŒçš„æž¶æž„
+----------
+
+LLVM 并䏿”¯æŒ Linux å†…æ ¸æ‰€æœ‰å¯æ”¯æŒçš„æž¶æž„ï¼ŒåŒæ ·ï¼Œå³ä½¿ LLVM æ”¯æŒæŸä¸€æž¶æž„ï¼Œä¹Ÿå¹¶ä¸æ„味ç€åœ¨
+该架构下内核å¯ä»¥æ­£å¸¸æž„å»ºæˆ–å·¥ä½œã€‚ä»¥ä¸‹æ˜¯å½“å‰ ``CC=clang`` 或 ``LLVM=1`` 支æŒçš„æž¶æž„总结。
+支æŒçº§åˆ«å¯¹åº”于 MAINTAINERS 文件中的 "S" 值。如果æŸä¸ªæž¶æž„未列出,则表示 LLVM 䏿”¯æŒå®ƒ
+或存在已知问题。使用最新的稳定版 LLVM 或甚至开å‘版本通常会得到最佳结果。一个架构的
+``defconfig`` 通常预期能够良好工作,但æŸäº›é…ç½®å¯èƒ½å­˜åœ¨å°šæœªå‘现的问题。欢迎在以下
+问题跟踪器中æäº¤é”™è¯¯æŠ¥å‘Šï¼
+
+.. list-table::
+ :widths: 10 10 10
+ :header-rows: 1
+
+ * - æž¶æž„
+ - 支æŒçº§åˆ«
+ - ``make`` 命令
+ * - arm
+ - 支æŒ
+ - ``LLVM=1``
+ * - arm64
+ - 支æŒ
+ - ``LLVM=1``
+ * - hexagon
+ - 维护
+ - ``LLVM=1``
+ * - loongarch
+ - 维护
+ - ``LLVM=1``
+ * - mips
+ - 维护
+ - ``LLVM=1``
+ * - powerpc
+ - 维护
+ - ``LLVM=1``
+ * - riscv
+ - 支æŒ
+ - ``LLVM=1``
+ * - s390
+ - 维护
+ - ``LLVM=1`` (LLVM >= 18.1.0),``CC=clang`` (LLVM < 18.1.0)
+ * - um (用户模å¼)
+ - 维护
+ - ``LLVM=1``
+ * - x86
+ - 支æŒ
+ - ``LLVM=1``
+
+获å–帮助
+--------
+
+- `网站 <https://clangbuiltlinux.github.io/>`_
+- `邮件列表 <https://lore.kernel.org/llvm/>`_: <llvm@lists.linux.dev>
+- `旧邮件列表档案 <https://groups.google.com/g/clang-built-linux>`_
+- `问题跟踪器 <https://github.com/ClangBuiltLinux/linux/issues>`_
+- IRC: #clangbuiltlinux 在 irc.libera.chat
+- `Telegram <https://t.me/ClangBuiltLinux>`_: @ClangBuiltLinux
+- `维基 <https://github.com/ClangBuiltLinux/linux/wiki>`_
+- `åˆå­¦è€…问题 <https://github.com/ClangBuiltLinux/linux/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22>`_
+
+.. _zh_cn_getting_llvm:
+
+èŽ·å– LLVM
+---------
+
+我们在 `kernel.org <https://kernel.org/pub/tools/llvm/>`_ æä¾›é¢„编译的稳定版 LLVM。
+这些版本已ç»é’ˆå¯¹ Linux 内核构建,使用é…置文件数æ®è¿›è¡Œä¼˜åŒ–。相较于其他å‘行版中的 LLVM,它们应该
+能æé«˜å†…核构建效率。
+
+以下是一些有助于从æºä»£ç æž„建 LLVM 或通过å‘行版的包管ç†å™¨èŽ·å– LLVM 的链接。
+
+- https://releases.llvm.org/download.html
+- https://github.com/llvm/llvm-project
+- https://llvm.org/docs/GettingStarted.html
+- https://llvm.org/docs/CMake.html
+- https://apt.llvm.org/
+- https://www.archlinux.org/packages/extra/x86_64/llvm/
+- https://github.com/ClangBuiltLinux/tc-build
+- https://github.com/ClangBuiltLinux/linux/wiki/Building-Clang-from-source
+- https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86/
diff --git a/Documentation/translations/zh_CN/kbuild/reproducible-builds.rst b/Documentation/translations/zh_CN/kbuild/reproducible-builds.rst
new file mode 100644
index 000000000000..5f27ebf2fbfc
--- /dev/null
+++ b/Documentation/translations/zh_CN/kbuild/reproducible-builds.rst
@@ -0,0 +1,114 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/kbuild/reproducible-builds.rst
+
+:Translator: 慕冬亮 Dongliang Mu <dzm91@hust.edu.cn>
+
+============
+å¯é‡çŽ°çš„æž„å»º
+============
+
+通常希望使用相åŒå·¥å…·é›†æž„å»ºç›¸åŒæºä»£ç æ˜¯å¯é‡çŽ°çš„ï¼Œå³ï¼Œè¾“出始终完全相åŒã€‚这使得能够验è¯
+äºŒè¿›åˆ¶åˆ†å‘æˆ–嵌入å¼ç³»ç»Ÿçš„æž„å»ºåŸºç¡€è®¾æ–½æœªè¢«ç¯¡æ”¹ã€‚è¿™æ ·ä¹Ÿæ›´å®¹æ˜“éªŒè¯æºä»£ç æˆ–工具的更改ä¸ä¼š
+影哿œ€ç»ˆç”Ÿæˆçš„二进制文件。
+
+`å¯é‡çŽ°æž„å»ºé¡¹ç›®`_ æä¾›äº†æœ‰å…³è¯¥ä¸»é¢˜çš„æ›´å¤šä¿¡æ¯ã€‚本文档涵盖了构建内核å¯èƒ½ä¸å¯é‡çŽ°çš„
+å„ç§åŽŸå› ï¼Œä»¥åŠå¦‚何é¿å…这些问题。
+
+时间戳
+------
+
+内核在三个地方嵌入时间戳:
+
+* 通过 ``uname()`` 显示与包å«åœ¨ ``/proc/version`` 中的版本字符串
+
+* initramfs 中的文件时间戳
+
+* 如果å¯åЍ ``CONFIG_IKHEADERS``,内核或相应模å—中嵌入的内核头文件的时间戳,
+ 通过 ``/sys/kernel/kheaders.tar.xz`` 显示
+
+é»˜è®¤æƒ…å†µä¸‹ï¼Œæ—¶é—´æˆ³ä¸ºå½“å‰æ—¶é—´æˆ–内核头文件的修改时间。这个内容必须使用
+`KBUILD_BUILD_TIMESTAMP`_ å˜é‡è¿›è¡Œè¦†ç›–。如果你从æŸä¸ª git æäº¤è¿›è¡Œæž„建,
+å¯ä»¥ä½¿ç”¨å…¶æäº¤æ—¥æœŸã€‚
+
+内核 *ä¸* 使用 ``__DATE__`` å’Œ ``__TIME__`` å®ï¼Œå¹¶åœ¨ä½¿ç”¨è¿™äº›å®æ—¶å¯ç”¨è­¦å‘Šã€‚
+如果你åˆå¹¶çš„外部代ç ä½¿ç”¨è¿™äº›å®ï¼Œåˆ™å¿…须通过设置 `SOURCE_DATE_EPOCH`_ 环境
+å˜é‡æ¥è¦†ç›–它们对应的时间戳。
+
+用户,主机
+----------
+
+内核在 ``/proc/version`` 中嵌入构建用户和主机å。必须使用
+`KBUILD_BUILD_USER å’Œ KBUILD_BUILD_HOST`_ å˜é‡æ¥è¦†ç›–这些设置。如果
+您从æŸä¸ª git æäº¤è¿›è¡Œæž„建,å¯ä»¥ä½¿ç”¨å…¶æäº¤è€…地å€ã€‚
+
+ç»å¯¹æ–‡ä»¶å
+----------
+
+当内核在树外构建时,调试信æ¯å¯èƒ½åŒ…æ‹¬æºæ–‡ä»¶çš„ç»å¯¹æ–‡ä»¶å。这些信æ¯å¿…须通过在
+`KCFLAGS`_ å˜é‡ä¸­åŒ…å« ``-fdebug-prefix-map`` 选项æ¥è¦†ç›–。
+
+æ ¹æ®ä½¿ç”¨çš„编译器,``__FILE__`` å®åœ¨æ ‘外构建中也å¯èƒ½æ‰©å±•为ç»å¯¹æ–‡ä»¶å。Kbuild
+自动使用 ``-fmacro-prefix-map`` 选项æ¥é˜²æ­¢è¿™ç§æƒ…å†µï¼Œå‰ææ˜¯å®ƒè¢«æ”¯æŒã€‚
+
+å¯é‡çŽ°æž„å»ºç½‘ç«™æä¾›äº†æœ‰å…³è¿™äº› `prefix-map 选项`_ 的更多信æ¯ã€‚
+
+在æºåŒ…ä¸­çš„ç”Ÿæˆæ–‡ä»¶
+------------------
+
+在 ``tools/`` å­ç›®å½•下,一些程åºçš„æž„建过程并ä¸å®Œå…¨æ”¯æŒæ ‘外构建。这å¯èƒ½å¯¼è‡´åŽç»­
+使用如 ``make rpm-pkg`` 构建的æºç åŒ…包å«ç”Ÿæˆçš„æ–‡ä»¶ã€‚在构建æºç åŒ…之å‰ï¼Œæ‚¨åº”该通过
+è¿è¡Œ ``make mrproper`` 或 ``git clean -d -f -x`` æ¥ç¡®ä¿æºç æ ‘是干净的。
+
+模å—ç­¾å
+--------
+
+如果你å¯ç”¨ ``CONFIG_MODULE_SIG_ALL``ï¼Œé»˜è®¤è¡Œä¸ºæ˜¯ä¸ºæ¯æ¬¡æž„建生æˆä¸åŒçš„临时密钥,
+从而导致模å—ä¸å¯é‡çŽ°ã€‚ç„¶è€Œï¼Œå°†ç­¾å密钥包å«åœ¨æºä»£ç ä¸­æ˜¾ç„¶ä¼šè¿èƒŒç­¾å模å—的目的。
+
+ä¸€ç§æ–¹æ³•是将构建过程分为几个部分,以便ä¸å¯é‡çŽ°çš„éƒ¨åˆ†å¯ä»¥ä½œä¸ºæºå¤„ç†ï¼š
+
+1. 生æˆä¸€ä¸ªæŒä¹…的签å密钥。将该密钥的è¯ä¹¦æ·»åŠ åˆ°å†…æ ¸æºä»£ç ä¸­ã€‚
+
+2. å°† ``CONFIG_SYSTEM_TRUSTED_KEYS`` 符å·è®¾ç½®ä¸ºåŒ…括签å密钥的è¯ä¹¦ï¼Œå°†
+``CONFIG_MODULE_SIG_KEY`` 设置为空字符串,并ç¦ç”¨ ``CONFIG_MODULE_SIG_ALL``。
+最åŽï¼Œæž„建内核和模å—。
+
+3. 为模å—创建分离的签å,并将它们作为æºå‘布。
+
+4. 附加模å—ç­¾å并进行第二次构建。这å¯ä»¥é‡å»ºæ¨¡å—,或使用步骤 2 的输出。
+
+ç»“æž„éšæœºåŒ–
+----------
+
+如果你å¯ç”¨ ``CONFIG_RANDSTRUCT``,则需è¦åœ¨ ``scripts/basic/randstruct.seed``
+中预生æˆéšæœºç§å­ï¼Œä»¥ä¾¿æ¯æ¬¡æž„建都使用相åŒçš„值。有关详细信æ¯ï¼Œè¯·å‚è§
+``scripts/gen-randstruct-seed.sh``。
+
+调试信æ¯å†²çª
+------------
+
+è¿™å¹¶éžæ˜¯ä¸ªä¸å¯é‡çŽ°æ€§çš„é—®é¢˜ï¼Œè€Œæ˜¯ç”Ÿæˆçš„æ–‡ä»¶ *过于* å¯é‡çŽ°çš„é—®é¢˜ã€‚
+
+一旦你设置了所有必è¦çš„å˜é‡æ¥å¼€å±•å¯é‡çŽ°æž„å»ºï¼ŒvDSO 的调试信æ¯å¯èƒ½å³ä½¿å¯¹äºŽä¸åŒçš„内核版
+本也是相åŒçš„。这会导致ä¸åŒå†…核版本的调试信æ¯è½¯ä»¶åŒ…之间å‘生文件冲çªã€‚
+
+为了é¿å…è¿™ç§æƒ…况,你å¯ä»¥é€šè¿‡åœ¨ vDSO 中包å«ä¸€ä¸ªä»»æ„çš„ salt 字符串,使其对于ä¸åŒçš„
+内核版本是ä¸åŒçš„ã€‚è¿™ç§æœºåˆ¶ç”± Kconfig ç¬¦å· ``CONFIG_BUILD_SALT`` 指定。
+
+Git
+---
+
+未æäº¤çš„æ›´æ”¹æˆ– Git 中的ä¸åŒæäº¤ ID 也å¯èƒ½å¯¼è‡´ä¸åŒçš„编译结果。例如,在执行
+``git reset HEAD^`` åŽï¼Œå³ä½¿ä»£ç ç›¸åŒï¼Œç¼–译期间生æˆçš„
+``include/config/kernel.release`` 也会ä¸åŒï¼Œå¯¼è‡´æœ€ç»ˆç”Ÿæˆçš„二进制文件也ä¸å°½ç›¸åŒã€‚
+有关详细信æ¯ï¼Œè¯·å‚è§ ``scripts/setlocalversion``。
+
+.. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp
+.. _KBUILD_BUILD_USER 和 KBUILD_BUILD_HOST: kbuild.html#kbuild-build-user-kbuild-build-host
+.. _KCFLAGS: kbuild.html#kcflags
+.. _prefix-map 选项: https://reproducible-builds.org/docs/build-path/
+.. _å¯é‡çŽ°æž„å»ºé¡¹ç›®: https://reproducible-builds.org/
+.. _SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/
diff --git a/Documentation/translations/zh_CN/mm/active_mm.rst b/Documentation/translations/zh_CN/mm/active_mm.rst
index c2816f523bd7..b3352668c4c8 100644
--- a/Documentation/translations/zh_CN/mm/active_mm.rst
+++ b/Documentation/translations/zh_CN/mm/active_mm.rst
@@ -13,6 +13,11 @@
Active MM
=========
+注æ„,在é…置了 CONFIG_MMU_LAZY_TLB_REFCOUNT=n 的内核中,mm_count 引用计数
+å¯èƒ½ä¸å†åŒ…括“懒惰â€ç”¨æˆ·ï¼ˆè¿è¡Œä»»åС䏭 ->active_mm == mm && ->mm == NULL)。
+获å–和释放这些懒惰引用必须使用 mmgrab_lazy_tlb() å’Œ mmdrop_lazy_tlb() è¿™
+两个辅助函数,它们抽象了这个é…置选项。
+
这是一å°linux之父回å¤å¼€å‘者的一å°é‚®ä»¶ï¼Œæ‰€ä»¥ç¿»è¯‘时我尽é‡ä¿æŒé‚®ä»¶æ ¼å¼çš„完整。
::
diff --git a/Documentation/translations/zh_CN/mm/damon/faq.rst b/Documentation/translations/zh_CN/mm/damon/faq.rst
index de4be417494a..234d63f4f072 100644
--- a/Documentation/translations/zh_CN/mm/damon/faq.rst
+++ b/Documentation/translations/zh_CN/mm/damon/faq.rst
@@ -13,23 +13,6 @@
常è§é—®é¢˜
========
-为什么是一个新的å­ç³»ç»Ÿï¼Œè€Œä¸æ˜¯æ‰©å±•perf或其他用户空间工具?
-==========================================================
-
-首先,因为它需è¦å°½å¯èƒ½çš„è½»é‡çº§ï¼Œä»¥ä¾¿å¯ä»¥åœ¨çº¿ä½¿ç”¨ï¼Œæ‰€ä»¥åº”该é¿å…任何ä¸å¿…è¦çš„开销,如内核-用户
-ç©ºé—´çš„ä¸Šä¸‹æ–‡åˆ‡æ¢æˆæœ¬ã€‚第二,DAMONçš„ç›®æ ‡æ˜¯è¢«åŒ…æ‹¬å†…æ ¸åœ¨å†…çš„å…¶ä»–ç¨‹åºæ‰€ä½¿ç”¨ã€‚因此,对特定工具
-(如perf)的ä¾èµ–性是ä¸å¯å–的。这就是DAMON在内核空间实现的两个最大的原因。
-
-
-“闲置页é¢è·Ÿè¸ªâ€ 或 “perf mem†å¯ä»¥æ›¿ä»£DAMONå—?
-==============================================
-
-闲置页跟踪是物ç†åœ°å€ç©ºé—´è®¿é—®æ£€æŸ¥çš„一个低层次的原始方法。“perf memâ€ä¹Ÿæ˜¯ç±»ä¼¼çš„,尽管它å¯ä»¥
-使用采样æ¥å‡å°‘开销。å¦ä¸€æ–¹é¢ï¼ŒDAMON是一个更高层次的框架,用于监控å„ç§åœ°å€ç©ºé—´ã€‚它专注于内
-存管ç†ä¼˜åŒ–,并æä¾›å¤æ‚的精度/å¼€é”€å¤„ç†æœºåˆ¶ã€‚因此,“空闲页é¢è·Ÿè¸ªâ€ å’Œ “perf mem†å¯ä»¥æä¾›
-DAMON输出的一个å­é›†ï¼Œä½†ä¸èƒ½æ›¿ä»£DAMON。
-
-
DAMON是å¦åªæ”¯æŒè™šæ‹Ÿå†…存?
=========================
diff --git a/Documentation/translations/zh_CN/mm/hmm.rst b/Documentation/translations/zh_CN/mm/hmm.rst
index babbbe756c0f..0669f947d0bc 100644
--- a/Documentation/translations/zh_CN/mm/hmm.rst
+++ b/Documentation/translations/zh_CN/mm/hmm.rst
@@ -129,13 +129,7 @@ struct pageå¯ä»¥ä¸ŽçŽ°æœ‰çš„ mm 机制进行最简å•ã€æœ€å¹²å‡€çš„集æˆã€‚å†
int hmm_range_fault(struct hmm_range *range);
如果请求写访问,它将在丢失或åªè¯»æ¡ç›®ä¸Šè§¦å‘缺页异常(è§ä¸‹æ–‡ï¼‰ã€‚缺页异常使用通用的 mm 缺
-页异常代ç è·¯å¾„ï¼Œå°±åƒ CPU 缺页异常一样。
-
-这两个函数都将 CPU 页表æ¡ç›®å¤åˆ¶åˆ°å®ƒä»¬çš„ pfns æ•°ç»„å‚æ•°ä¸­ã€‚该数组中的æ¯ä¸ªæ¡ç›®å¯¹åº”于虚拟
-范围中的一个地å€ã€‚HMM æä¾›äº†ä¸€ç»„标志æ¥å¸®åŠ©é©±åŠ¨ç¨‹åºè¯†åˆ«ç‰¹æ®Šçš„ CPU 页表项。
-
-在 sync_cpu_device_pagetables() 回调中é”定是驱动程åºå¿…须尊é‡çš„æœ€é‡è¦çš„æ–¹é¢ï¼Œä»¥ä¿
-æŒäº‹ç‰©æ­£ç¡®åŒæ­¥ã€‚ä½¿ç”¨æ¨¡å¼æ˜¯::
+页异常代ç è·¯å¾„ï¼Œå°±åƒ CPU ç¼ºé¡µå¼‚å¸¸ä¸€æ ·ã€‚ä½¿ç”¨æ¨¡å¼æ˜¯::
int driver_populate_range(...)
{
diff --git a/Documentation/translations/zh_CN/mm/index.rst b/Documentation/translations/zh_CN/mm/index.rst
index b950dd118be7..c8726bce8f74 100644
--- a/Documentation/translations/zh_CN/mm/index.rst
+++ b/Documentation/translations/zh_CN/mm/index.rst
@@ -53,6 +53,8 @@ Linuxå†…å­˜ç®¡ç†æ–‡æ¡£
page_migration
page_owner
page_table_check
+ page_tables
+ physical_memory
remap_file_pages
split_page_table_lock
vmalloced-kernel-stacks
diff --git a/Documentation/translations/zh_CN/mm/overcommit-accounting.rst b/Documentation/translations/zh_CN/mm/overcommit-accounting.rst
index d8452d8b7fbb..f136a8b81859 100644
--- a/Documentation/translations/zh_CN/mm/overcommit-accounting.rst
+++ b/Documentation/translations/zh_CN/mm/overcommit-accounting.rst
@@ -16,8 +16,7 @@ Linux内核支æŒä¸‹åˆ—è¶…é‡ä½¿ç”¨å¤„ç†æ¨¡å¼
0
å¯å‘å¼è¶…é‡ä½¿ç”¨å¤„ç†ã€‚æ‹’ç»æ˜Žæ˜¾çš„地å€ç©ºé—´è¶…é‡ä½¿ç”¨ã€‚用于一个典型的系统。
- 它确ä¿ä¸¥é‡çš„疯狂分é…å¤±è´¥ï¼ŒåŒæ—¶å…许超é‡ä½¿ç”¨ä»¥å‡å°‘swapçš„ä½¿ç”¨ã€‚åœ¨è¿™ç§æ¨¡å¼ä¸‹ï¼Œ
- å…许root分é…ç¨å¤šçš„内存。这是默认的。
+ 它确ä¿ä¸¥é‡çš„疯狂分é…å¤±è´¥ï¼ŒåŒæ—¶å…许超é‡ä½¿ç”¨ä»¥å‡å°‘swap的使用。这是默认的。
1
总是超é‡ä½¿ç”¨ã€‚适用于一些科学应用。ç»å…¸çš„例孿˜¯ä½¿ç”¨ç¨€ç–数组的代ç ï¼Œåªæ˜¯ä¾èµ–
几乎完全由零页组æˆçš„虚拟内存
diff --git a/Documentation/translations/zh_CN/mm/page_owner.rst b/Documentation/translations/zh_CN/mm/page_owner.rst
index b72a972271d9..c0d1ca4b9695 100644
--- a/Documentation/translations/zh_CN/mm/page_owner.rst
+++ b/Documentation/translations/zh_CN/mm/page_owner.rst
@@ -26,6 +26,9 @@ page owner是用æ¥è¿½è¸ªè°åˆ†é…çš„æ¯ä¸€ä¸ªé¡µé¢ã€‚它å¯ä»¥ç”¨æ¥è°ƒè¯•内å
页颿‰€æœ‰è€…也å¯ä»¥ç”¨äºŽå„ç§ç›®çš„。例如,å¯ä»¥é€šè¿‡æ¯ä¸ªé¡µé¢çš„gfp标志信æ¯èŽ·å¾—ç²¾ç¡®çš„ç¢Žç‰‡
统计。如果å¯ç”¨äº†page owner,它就已ç»å®žçŽ°å¹¶æ¿€æ´»äº†ã€‚æˆ‘ä»¬éžå¸¸æ¬¢è¿Žå…¶ä»–用途。
+它也å¯ä»¥ç”¨æ¥æ˜¾ç¤ºæ‰€æœ‰çš„æ ˆä»¥åŠå®ƒä»¬å½“å‰åˆ†é…çš„åŸºç¡€é¡µé¢æ•°ï¼Œè¿™è®©æˆ‘们能够快速了解内存的
+使用情况,而无需æµè§ˆæ‰€æœ‰é¡µé¢å¹¶åŒ¹é…分é…和释放æ“作。
+
page owner在默认情况下是ç¦ç”¨çš„。所以,如果你想使用它,你需è¦åœ¨ä½ çš„å¯åЍcmdline
中加入"page_owner=on"。如果内核是用page owner构建的,并且由于没有å¯ç”¨å¯åЍ
选项而在è¿è¡Œæ—¶ç¦ç”¨page owner,那么è¿è¡Œæ—¶çš„开销是很å°çš„。如果在è¿è¡Œæ—¶ç¦ç”¨ï¼Œå®ƒä¸
@@ -60,6 +63,49 @@ page owner在默认情况下是ç¦ç”¨çš„。所以,如果你想使用它,你é
4) åˆ†æžæ¥è‡ªé¡µé¢æ‰€æœ‰è€…的信æ¯::
+ cat /sys/kernel/debug/page_owner_stacks/show_stacks > stacks.txt
+ cat stacks.txt
+ post_alloc_hook+0x177/0x1a0
+ get_page_from_freelist+0xd01/0xd80
+ __alloc_pages+0x39e/0x7e0
+ allocate_slab+0xbc/0x3f0
+ ___slab_alloc+0x528/0x8a0
+ kmem_cache_alloc+0x224/0x3b0
+ sk_prot_alloc+0x58/0x1a0
+ sk_alloc+0x32/0x4f0
+ inet_create+0x427/0xb50
+ __sock_create+0x2e4/0x650
+ inet_ctl_sock_create+0x30/0x180
+ igmp_net_init+0xc1/0x130
+ ops_init+0x167/0x410
+ setup_net+0x304/0xa60
+ copy_net_ns+0x29b/0x4a0
+ create_new_namespaces+0x4a1/0x820
+ nr_base_pages: 16
+ ...
+ ...
+ echo 7000 > /sys/kernel/debug/page_owner_stacks/count_threshold
+ cat /sys/kernel/debug/page_owner_stacks/show_stacks> stacks_7000.txt
+ cat stacks_7000.txt
+ post_alloc_hook+0x177/0x1a0
+ get_page_from_freelist+0xd01/0xd80
+ __alloc_pages+0x39e/0x7e0
+ alloc_pages_mpol+0x22e/0x490
+ folio_alloc+0xd5/0x110
+ filemap_alloc_folio+0x78/0x230
+ page_cache_ra_order+0x287/0x6f0
+ filemap_get_pages+0x517/0x1160
+ filemap_read+0x304/0x9f0
+ xfs_file_buffered_read+0xe6/0x1d0 [xfs]
+ xfs_file_read_iter+0x1f0/0x380 [xfs]
+ __kernel_read+0x3b9/0x730
+ kernel_read_file+0x309/0x4d0
+ __do_sys_finit_module+0x381/0x730
+ do_syscall_64+0x8d/0x150
+ entry_SYSCALL_64_after_hwframe+0x62/0x6a
+ nr_base_pages: 20824
+ ...
+
cat /sys/kernel/debug/page_owner > page_owner_full.txt
./page_owner_sort page_owner_full.txt sorted_page_owner.txt
diff --git a/Documentation/translations/zh_CN/mm/page_table_check.rst b/Documentation/translations/zh_CN/mm/page_table_check.rst
index e8077310a76c..dc34570dceff 100644
--- a/Documentation/translations/zh_CN/mm/page_table_check.rst
+++ b/Documentation/translations/zh_CN/mm/page_table_check.rst
@@ -54,3 +54,16 @@
å¯ä»¥é€‰æ‹©ç”¨PAGE_TABLE_CHECK_ENFORCEDæ¥æž„建内核,以便在没有é¢å¤–çš„å†…æ ¸å‚æ•°çš„æƒ…况下获得页表
支æŒã€‚
+
+实现注æ„事项
+============
+
+我们特æ„决定ä¸ä½¿ç”¨ VMA ä¿¡æ¯ï¼Œä»¥é¿å…ä¾èµ–于 MM 状æ€ï¼ˆé™¤äº†æœ‰é™çš„ “struct page†信æ¯ï¼‰ã€‚页表检查
+独立于 Linux-MM çŠ¶æ€æœºï¼Œå®ƒéªŒè¯ç”¨æˆ·å¯è®¿é—®çš„页é¢ä¸ä¼šè¢«é”™è¯¯åœ°å…±äº«ã€‚
+
+PAGE_TABLE_CHECK ä¾èµ–于 EXCLUSIVE_SYSTEM_RAM。原因在于,若没有 EXCLUSIVE_SYSTEM_RAM,
+用户被å…许通过 /dev/mem 将任æ„物ç†å†…å­˜åŒºåŸŸæ˜ å°„åˆ°ç”¨æˆ·ç©ºé—´ã€‚åŒæ—¶ï¼Œé¡µé¢å¯èƒ½åœ¨æ˜ å°„到用户空间期间
+改å˜è‡ªå·±çš„属性(例如,从匿å页é¢å˜ä¸ºå‘½å页é¢ï¼‰ï¼Œå¯¼è‡´é¡µè¡¨æ£€æŸ¥æ£€æµ‹åˆ°â€œæŸåâ€ã€‚
+
+å³ä½¿æœ‰ EXCLUSIVE_SYSTEM_RAM,I/O 页é¢å¯èƒ½ä»ç„¶è¢«å…许通过 /dev/mem 映射。然而,这些页é¢å§‹ç»ˆ
+被视为命å页é¢ï¼Œæ‰€ä»¥å®ƒä»¬ä¸ä¼šç ´å页表检查中使用的逻辑。
diff --git a/Documentation/translations/zh_CN/mm/page_tables.rst b/Documentation/translations/zh_CN/mm/page_tables.rst
new file mode 100644
index 000000000000..c9f750fc5298
--- /dev/null
+++ b/Documentation/translations/zh_CN/mm/page_tables.rst
@@ -0,0 +1,221 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/mm/page_tables.rst
+
+:翻译:
+
+ å¼ é¹å®‡ Pengyu Zhang <zpenya1314@gmail.com>
+
+:校译:
+
+====
+页表
+====
+
+分页虚拟内存是éšè™šæ‹Ÿå†…存的概念一起于 1962 年在 Ferranti Atlas 计算机上被æå‡ºçš„,
+è¿™æ˜¯ç¬¬ä¸€å°æœ‰åˆ†é¡µè™šæ‹Ÿå†…存的计算机。éšç€æ—¶é—´æŽ¨ç§»ï¼Œè¿™ä¸ªç‰¹æ€§è¢«è¿ç§»åˆ°æ›´æ–°çš„计算机上,
+并且æˆä¸ºæ‰€æœ‰ç±» Unix 系统实际的特性。在 1985 年,这个特性被包å«åœ¨äº†è‹±ç‰¹å°” 80386
+中,也就是è¿è¡Œ Linux 1.0 çš„CPU。
+
+页表将 CPU çœ‹åˆ°çš„è™šæ‹Ÿåœ°å€æ˜ å°„到外部内存总线上看到的物ç†åœ°å€ã€‚
+
+Linux å°†é¡µè¡¨å®šä¹‰ä¸ºä¸€ä¸ªåˆ†çº§ç»“æž„ï¼Œç›®å‰æœ‰äº”级。对于支æŒçš„æ¯ç§æž¶æž„,其代ç ä¼šæ ¹æ®ç¡¬ä»¶
+é™åˆ¶å¯¹è¿™ä¸ªå±‚级结构进行映射。
+
+虚拟地å€å¯¹åº”的物ç†åœ°å€é€šå¸¸ç”±åº•层物ç†é¡µå¸§å¼•用。 **页帧å·(page frame number,pfn)**
+是页的物ç†åœ°å€ï¼ˆåœ¨å¤–部内存总线看到的地å€ï¼‰é™¤ä»¥ `PAGE_SIZE` 得到的值。
+
+物ç†å†…å­˜åœ°å€ 0 对应 *pfn 0*,而最大的 pfn 对应处ç†å™¨å¤–éƒ¨åœ°å€æ€»çº¿æ‰€èƒ½å¯»å€ç‰©ç†åœ°å€
+的最åŽä¸€é¡µã€‚
+
+在页粒度为 4KB 且地å€èŒƒå›´ä¸º32ä½çš„æƒ…况下,pfn 0 对应地å€0x00000000,pfn 1 对应
+地å€0x00001000,pfn 2 å¯¹åº”åœ°å€ 0x00002000,以此类推,直到 pfn 0xfffff 对应
+0xfffff000。如果页粒度为 16KB,则 pfn åˆ†åˆ«å¯¹åº”åœ°å€ 0x00004000ã€0x00008000
+... 0xffffc000,pfn 的范围从 0 到 0x3ffff。
+
+如你所è§ï¼Œå¯¹äºŽ 4KB 页é¢ç²’度,页基å€ä½¿ç”¨åœ°å€çš„ 12-31 ä½ï¼Œè¿™å°±æ˜¯ä¸ºä»€ä¹ˆåœ¨è¿™ç§æƒ…况下
+`PAGE_SHIFT` 被定义为 12,并且 `PAGE_SIZE` 通常由页å移定义,为 `(1 << PAGE_SHIFT)`。
+
+éšç€å†…存容é‡çš„å¢žåŠ ï¼Œä¹…è€Œä¹…ä¹‹å±‚çº§ç»“æž„é€æ¸åŠ æ·±ã€‚Linux 最åˆä½¿ç”¨ 4KB 页é¢å’Œä¸€ä¸ªå为
+`swapper_pg_dir` 的页表,该页表拥有 1024 个表项(entries),覆盖 4MB 的内存,
+事实上Torvald 的第一å°è®¡ç®—机正好就有 4MB 物ç†å†…存。表项在这张表中被称为 *PTE*:s
+- 页表项(page table entries)。
+
+è½¯ä»¶é¡µè¡¨å±‚çº§ç»“æž„åæ˜ äº†é¡µè¡¨ç¡¬ä»¶å·²ç»å˜å¾—分层化的事实,而这ç§åˆ†å±‚化的目的是为了节çœ
+é¡µè¡¨å†…å­˜å¹¶åŠ å¿«åœ°å€æ˜ å°„速度。
+
+当然,人们å¯ä»¥æƒ³è±¡ä¸€å¼ æ‹¥æœ‰å¤§é‡è¡¨é¡¹çš„å•一线性的页表将整个内存分为一个个页。而且,
+这样的页表会éžå¸¸ç¨€ç–,因为虚拟内存中大部分ä½ç½®é€šå¸¸æ˜¯æœªä½¿ç”¨çš„。通过页表分层,虚拟
+内存中的大é‡ç©ºæ´žä¸ä¼šæµªè´¹å®è´µçš„页表内存,因为åªéœ€è¦åœ¨ä¸Šå±‚页表中将大å—的区域标记为
+未映射å³å¯ã€‚
+
+å¦å¤–,在现代处ç†å™¨ä¸­ï¼Œä¸Šå±‚页表项å¯ä»¥ç›´æŽ¥æŒ‡å‘一个物ç†åœ°å€èŒƒå›´ï¼Œè¿™ä½¿å¾—å•个上层
+页表项å¯ä»¥è¿žç»­æ˜ å°„几兆字节甚至几åƒå…†å­—节的内存范围,从而快æ·åœ°å®žçŽ°è™šæ‹Ÿåœ°å€åˆ°
+物ç†åœ°å€çš„æ˜ å°„:当你找到一个åƒè¿™æ ·çš„大型映射范围时,无需在层级结构中进一步é历。
+
+页表的层级结构目å‰å‘展为如下所示::
+
+ +-----+
+ | PGD |
+ +-----+
+ |
+ | +-----+
+ +-->| P4D |
+ +-----+
+ |
+ | +-----+
+ +-->| PUD |
+ +-----+
+ |
+ | +-----+
+ +-->| PMD |
+ +-----+
+ |
+ | +-----+
+ +-->| PTE |
+ +-----+
+
+
+ä¸åŒé¡µè¡¨å±‚级的符å·å«ä¹‰ä»Žæœ€åº•层开始如下:
+
+- **pte**, `pte_t`, `pteval_t` = **页表项** - å‰é¢æåˆ°è¿‡ã€‚*pte* 是一个由
+ `PTRS_PER_PTE` 个 `pteval_t` 类型元素组æˆçš„æ•°ç»„,æ¯ä¸ªå…ƒç´ å°†ä¸€ä¸ªè™šæ‹Ÿå†…存页
+ 映射到一个物ç†å†…存页。体系结构定义了 `pteval_t` 的大å°å’Œå†…容。
+
+ ä¸€ä¸ªå…¸åž‹çš„ä¾‹å­æ˜¯ `pteval_t` 是一个 32 或者 64 ä½çš„å€¼ï¼Œå…¶ä¸­é«˜ä½æ˜¯ **pfn**,
+ 而低ä½åˆ™ä¸€äº›ç‰¹å®šä½“系架构相关的ä½ï¼Œå¦‚å†…å­˜ä¿æŠ¤ã€‚
+
+ 这个 **表项(entry)** 有点令人困惑,因为在 Linux 1.0 中它确实指的是å•层顶级
+ 页表中的å•ä¸ªé¡µè¡¨é¡¹ï¼Œä½†åœ¨é¦–æ¬¡å¼•å…¥äºŒçº§é¡µè¡¨æ—¶ï¼Œå®ƒè¢«é‡æ–°å®šä¹‰ä¸ºæ˜ å°„元素的数组。
+ 因此,*pte* 现在指的是最底层的页 *表*ï¼Œè€Œä¸æ˜¯ä¸€ä¸ªé¡µè¡¨ *项*。
+
+- **pmd**, `pmd_t`, `pmdval_t` = **页中间目录(Page Middle Directory)**,
+ ä½äºŽ *pte* ä¹‹ä¸Šçš„å±‚çº§ç»“æž„ï¼ŒåŒ…å« `PTRS_PER_PMD` ä¸ªæŒ‡å‘ *pte* 的引用。
+
+- **pud**, `pud_t`, `pudval_t` = **页上级目录(Page Upper Directory)**
+ 是在其他层级之åŽå¼•入的,用于处ç†å››çº§é¡µè¡¨ã€‚它å¯èƒ½æœªè¢«ä½¿ç”¨ï¼Œæˆ–è€…åƒæˆ‘们ç¨åŽ
+ 讨论的那样被“折å â€ã€‚
+
+- **p4d**, `p4d_t`, `p4dval_t` = **页四级目录(Page Level 4 Directory)**
+ 是在 *pud* 之åŽç”¨äºŽå¤„ç†äº”级页表引入的。至此,显然需è¦ç”¨æ•°å­—æ¥æ›¿ä»£ *pgd*ã€
+ *pmd*ã€*pud* 等目录层级的å称,ä¸èƒ½å†ç»§ç»­ä½¿ç”¨ä¸´æ—¶çš„命忖¹å¼ã€‚这个目录层级
+ åªåœ¨å®žé™…拥有五级页表的系统上使用,å¦åˆ™å®ƒä¼šè¢«æŠ˜å ã€‚
+
+- **pgd**, `pgd_t`, `pgdval_t` = **页全局目录(Page Global Directory)** -
+ Linux 内核用于处ç†å†…核内存的 *PGD* 主页表ä»ç„¶ä½äºŽ `swapper_pg_dir`。
+ 但系统中的æ¯ä¸ªç”¨æˆ·ç©ºé—´è¿›ç¨‹ä¹Ÿæœ‰è‡ªå·±çš„内存上下文,因此也有自己的 *pgd*,
+ 它ä½äºŽ `struct mm_struct` 中,而 `struct mm_struct` åˆåœ¨æ¯ä¸ª `struct task_struct`
+ 中有引用。所以,任务(进程)存在一个形å¼ä¸º `struct mm_struct` 的内存上下文,
+ è€Œè¿™ä¸ªç»“æž„ä½“ä¸­æœ‰ä¸€ä¸ªæŒ‡å‘æŒ‡å‘相应的页全局目录 `struct pgt_t *pgd` 指针。
+
+é‡ç”³ä¸€ä¸‹ï¼šé¡µè¡¨å±‚级结构中的æ¯ä¸€å±‚都是一个 *指针数组*,所以 *pgd* åŒ…å« `PTRS_PER_PGD`
+个指å‘下一层的指针,*p4d* åŒ…å« `PTRS_PER_P4D` ä¸ªæŒ‡å‘ *pud* é¡¹çš„æŒ‡é’ˆï¼Œä¾æ­¤ç±»æŽ¨ã€‚
+æ¯ä¸€å±‚的指针数é‡ç”±ä½“系结构定义。::
+
+ PMD
+ --> +-----+ PTE
+ | ptr |-------> +-----+
+ | ptr |- | ptr |-------> PAGE
+ | ptr | \ | ptr |
+ | ptr | \ ...
+ | ... | \
+ | ptr | \ PTE
+ +-----+ +----> +-----+
+ | ptr |-------> PAGE
+ | ptr |
+ ...
+
+页表折å 
+========
+
+如果架构ä¸ä½¿ç”¨æ‰€æœ‰çš„页表层级,那么这些层级å¯ä»¥è¢« *折å *,也就是说被跳过。在
+访问下一层时,所有在页表上执行的æ“作都会在编译时增强,以跳过这一层。
+
+与架构无关的页表处ç†ä»£ç ï¼ˆä¾‹å¦‚虚拟内存管ç†å™¨ï¼‰éœ€è¦ç¼–写得能够é历当å‰çš„æ‰€æœ‰äº”个
+层级。对于特定架构的代ç ï¼Œä¹Ÿåº”优先采用这ç§é£Žæ ¼ï¼Œä»¥ä¾¿å¯¹æœªæ¥çš„å˜åŒ–具有更好的适应性。
+
+MMU,TLB 和缺页异常
+===================
+
+`内存管ç†å•å…ƒ(MMU)` 是处ç†è™šæ‹Ÿåœ°å€åˆ°ç‰©ç†åœ°å€è½¬æ¢çš„硬件组件。它å¯èƒ½ä¼šä½¿ç”¨ç›¸å¯¹è¾ƒå°
+的硬件缓存,如 `转æ¢åŽå¤‡ç¼“冲区(TLB)` å’Œ `页é历缓存`,以加快这些地å€ç¿»è¯‘过程。
+
+当 CPU è®¿å­˜æ—¶ï¼Œå®ƒä¼šå‘ MMU æä¾›ä¸€ä¸ªè™šæ‹Ÿåœ°å€ã€‚MMU 会首先检查 TLB 或者页é历缓存
+(在支æŒçš„æž¶æž„上)是å¦å­˜åœ¨å¯¹åº”的转æ¢ç»“果。如果没有,MMU 会通过é历æ¥ç¡®å®šç‰©ç†åœ°å€
+并且建立映射。
+
+当页é¢è¢«å†™å…¥æ—¶ï¼Œè¯¥é¡µçš„è„ä½ä¼šè¢«è®¾ç½®ï¼ˆå³æ‰“开)。æ¯ä¸ªå†…存页é¢éƒ½æœ‰ç›¸å…³çš„æƒé™ä½å’Œè„ä½ã€‚
+åŽè€…è¡¨æ˜Žè¿™ä¸ªé¡µè‡ªä»Žè¢«åŠ è½½åˆ°å†…å­˜ä»¥æ¥æ˜¯å¦è¢«ä¿®æ”¹ã€‚
+
+如果没有任何阻ç¢ï¼Œç‰©ç†å†…存到头æ¥å¯ä»¥è¢«ä»»æ„访问并且对物ç†å¸§è¿›è¡Œè¯·æ±‚çš„æ“作。
+
+MMU 无法找到æŸäº›è½¬æ¢æœ‰å¤šç§åŽŸå› ã€‚æœ‰å¯èƒ½æ˜¯ CPU 试图去访问当å‰è¿›ç¨‹æ²¡æœ‰æƒé™è®¿é—®çš„
+内存,或者因为访问的数æ®è¿˜ä¸åœ¨ç‰©ç†å†…存中。
+
+当这些情况å‘生时,MMU 会触å‘缺页异常,这是一ç§å¼‚常类型,用于通知 CPU æš‚åœå½“å‰
+执行并è¿è¡Œä¸€ä¸ªç‰¹æ®Šçš„函数去处ç†è¿™äº›å¼‚常。
+
+缺页异常有一些常è§ä¸”预期的原因。这些因素是由称为“懒加载â€å’Œâ€œå†™æ—¶å¤åˆ¶â€çš„进程管ç†
+优化技术æ¥è§¦å‘的。缺页异常也å¯èƒ½å‘生在当页帧被交æ¢åˆ°æŒä¹…存储(交æ¢åˆ†åŒºæˆ–者文件)
+并从其物ç†åœ°å€ç§»å‡ºæ—¶ã€‚
+
+这些技术æé«˜äº†å†…存效率,å‡å°‘了延迟,并且最å°åŒ–了空间å ç”¨ã€‚本文档ä¸ä¼šæ·±å…¥è®¨è®º
+“懒加载â€å’Œâ€œå†™æ—¶å¤åˆ¶â€çš„细节,因为这些的主题属于进程地å€ç®¡ç†èŒƒç•´ï¼Œè¶…出了本文范围。
+
+äº¤æ¢æŠ€æœ¯å’Œå‰é¢æåˆ°çš„其他技术ä¸åŒï¼Œå› ä¸ºå®ƒæ˜¯åœ¨åŽ‹åŠ›è¿‡å¤§ä¸‹æƒ…å†µä¸‹å‡å°‘内存消耗的一ç§
+è¿«ä¸å¾—已的手段,因此是ä¸å—欢迎的。
+
+交æ¢ä¸é€‚ç”¨äºŽç”±å†…æ ¸é€»è¾‘åœ°å€æ˜ å°„çš„å†…å­˜ã€‚è¿™äº›åœ°å€æ˜¯å†…核虚拟地å€ç©ºé—´çš„å­é›†ï¼Œç›´æŽ¥æ˜ å°„
+一段连续的物ç†å†…存。对于æä¾›çš„ä»»æ„逻辑地å€ï¼Œå®ƒçš„物ç†åœ°å€å¯ä»¥é€šè¿‡å¯¹åç§»é‡è¿›è¡Œç®€å•
+的算数è¿ç®—æ¥ç¡®å®šã€‚对逻辑地å€çš„访问很快,因为这é¿å…äº†å¤æ‚的页表查找,但代价是这些
+内存ä¸èƒ½è¢«é©±é€æˆ–ç½®æ¢ã€‚
+
+如果内核无法为必须存在于物ç†å¸§ä¸­çš„æ•°æ®è…¾å‡ºç©ºé—´ï¼Œé‚£ä¹ˆå®ƒä¼šè°ƒç”¨å†…å­˜ä¸è¶³(out-of-memory,
+OOM)æ€æ‰‹ï¼Œé€šè¿‡æ€æŽ‰ä½Žä¼˜å…ˆçº§çš„进程æ¥è…¾å‡ºç©ºé—´ï¼Œç›´åˆ°å†…存压力下é™åˆ°å®‰å…¨é˜ˆå€¼ä¹‹ä¸‹ã€‚
+
+å¦å¤–ï¼Œä»£ç æ¼æ´žæˆ–指示 CPU è®¿é—®çš„ç²¾å¿ƒåˆ¶ä½œçš„æ¶æ„地å€ä¹Ÿå¯èƒ½å¯¼è‡´ç¼ºé¡µå¼‚常。一个进程的
+线程å¯ä»¥åˆ©ç”¨æŒ‡ä»¤æ¥è®¿é—®ä¸å±žäºŽå…¶åœ°å€ç©ºé—´çš„(éžå…±äº«ï¼‰å†…存,或者试图执行写入åªè¯»ä½ç½®
+的指令。
+
+如果上述情况å‘生在用户æ€ï¼Œå†…核会å‘当å‰çº¿ç¨‹å‘é€ `段错误` (SIGSEGV)ä¿¡å·ã€‚该信å·
+通常导致线程åŠå…¶æ‰€å±žçš„进程终止。
+
+本文将简化并概述 Linux 内核如何处ç†è¿™äº›ç¼ºé¡µä¸­æ–­ã€åˆ›å»ºè¡¨å’Œè¡¨é¡¹ã€æ£€æŸ¥å†…存是å¦å­˜åœ¨ï¼Œ
+以åŠå½“内存ä¸å­˜åœ¨æ—¶ï¼Œå¦‚何请求从æŒä¹…存储或其他设备加载数æ®ï¼Œå¹¶æ›´æ–° MMU åŠå…¶ç¼“存。
+
+最åˆçš„æ­¥éª¤ä¾èµ–于架构。大多是架构跳转到 `do_page_fault()`,而 x86 中断处ç†ç¨‹åºæ˜¯ç”±
+`DEFINE_IDTENTRY_RAW_ERRORCODE()` å®å®šä¹‰çš„,该å®è°ƒç”¨ `handle_page_fault()`。
+
+无论调用路径如何,所有架构最终都会调用 `handle_mm_fault()`,该函数通常会调用
+`__handle_mm_fault()` æ¥æ‰§è¡Œå®žé™…分é…页表的任务。
+
+如果ä¸å¹¸æ— æ³•调用 `__handle_mm_fault()` 则æ„味ç€è™šæ‹Ÿåœ°å€æŒ‡å‘了无æƒè®¿é—®çš„物ç†
+内存区域(至少对于当å‰ä¸Šä¸‹æ–‡å¦‚æ­¤ï¼‰ã€‚è¿™ç§æƒ…况会导致内核å‘该进程å‘é€ä¸Šè¿°çš„ SIGSEGV
+ä¿¡å·ï¼Œå¹¶å¼•å‘å‰é¢æåˆ°çš„åŽæžœã€‚
+
+这些用于查找åç§»é‡çš„函数å称通常以 `*_offset()` 结尾,其中“\*â€å¯ä»¥æ˜¯ pgd,p4d,
+pud,pmd 或者 pte;而分é…相应层级页表的函数å称是 `*_alloc`,它们按照上述命å
+约定以对应页表层级的类型命å。
+
+页表é历å¯èƒ½åœ¨ä¸­é—´æˆ–者上层结æŸ(PMD,PUD)。
+
+Linux æ”¯æŒæ¯”通常 4KB 更大的页é¢ï¼ˆå³æ‰€è°“çš„ `巨页`)。当使用这ç§è¾ƒå¤§çš„页颿—¶ï¼Œæ²¡æœ‰
+å¿…è¦ä½¿ç”¨æ›´ä½Žå±‚的页表项(PTE)ã€‚å·¨é¡µé€šå¸¸åŒ…å« 2MB 到 1GB 的大å—连续物ç†åŒºåŸŸï¼Œåˆ†åˆ«ç”±
+PMD 和 PUD 页表项映射。
+
+巨页带æ¥è®¸å¤šå¥½å¤„,如å‡å°‘ TLB 压力,å‡å°‘页表开销,æé«˜å†…å­˜åˆ†é…æ•ˆçŽ‡ï¼Œä»¥åŠæ”¹å–„
+特定工作负载的性能。然而,这些好处也伴éšç€æƒè¡¡ï¼Œå¦‚内存浪费和分é…难度增加。
+
+在é历和分é…的最åŽï¼Œå¦‚果没有返回错误,`__handle_mm_fault()` 最终调用 `handle_pte_fault()`
+通过 `do_fault()` 执行 `do_read_fault()`〠`do_cow_fault()` 和 `do_shared_fault()`。
+“readâ€ï¼Œâ€œcowâ€å’Œâ€œsharedâ€åˆ†åˆ«æš—示了它处ç†é”™è¯¯çš„类型和原因。
+
+实际的工作æµç¨‹å®žçŽ°æ˜¯éžå¸¸å¤æ‚的。其设计å…许 Linux æ ¹æ®æ¯ç§æž¶æž„的特定特性处ç†ç¼ºé¡µ
+å¼‚å¸¸ï¼ŒåŒæ—¶ä»ç„¶å…±äº«ä¸€ä¸ªé€šç”¨çš„æ•´ä½“结构。
+
+为了总结 Linux 如何处ç†ç¼ºé¡µä¸­æ–­çš„æ¦‚述,需è¦è¡¥å……的是,缺页异常处ç†ç¨‹åºå¯ä»¥é€šè¿‡
+`pagefault_disable()` å’Œ `pagefault_enable()` 分别ç¦ç”¨å’Œå¯ç”¨ã€‚
+
+许多代ç è·¯å¾„使用了这两个函数,因为它们需è¦ç¦æ­¢é™·å…¥ç¼ºé¡µå¼‚常处ç†ç¨‹åºï¼Œä¸»è¦æ˜¯ä¸ºäº†
+防止死é”。
diff --git a/Documentation/translations/zh_CN/mm/physical_memory.rst b/Documentation/translations/zh_CN/mm/physical_memory.rst
new file mode 100644
index 000000000000..4594d15cefec
--- /dev/null
+++ b/Documentation/translations/zh_CN/mm/physical_memory.rst
@@ -0,0 +1,356 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/mm/physical_memory.rst
+
+:翻译:
+
+ 王亚鑫 Yaxin Wang <wang.yaxin@zte.com.cn>
+
+========
+物ç†å†…å­˜
+========
+
+Linuxå¯ç”¨äºŽå¤šç§æž¶æž„,因此需è¦ä¸€ä¸ªä¸Žæž¶æž„无关的抽象æ¥è¡¨ç¤ºç‰©ç†å†…存。本章æè¿°
+了管ç†è¿è¡Œç³»ç»Ÿä¸­ç‰©ç†å†…存的结构。
+
+第一个与内存管ç†ç›¸å…³çš„ä¸»è¦æ¦‚念是 `éžä¸€è‡´æ€§å†…存访问(NUMA)
+<https://en.wikipedia.org/wiki/Non-uniform_memory_access>`
+
+åœ¨å¤šæ ¸å’Œå¤šæ’æ§½æœºå™¨ä¸­ï¼Œå†…å­˜å¯èƒ½è¢«ç»„织æˆä¸åŒçš„存储区,这些存储区根æ®ä¸Žå¤„ç†å™¨
+çš„è·ç¦»â€œä¸åŒâ€è€Œæœ‰ä¸åŒçš„访问开销。例如,å¯èƒ½ä¸ºæ¯ä¸ªCPU分é…内存存储区,或者为
+外围设备在附近分é…一个éžå¸¸é€‚åˆDMA的内存存储区。
+
+æ¯ä¸ªå­˜å‚¨åŒºè¢«ç§°ä¸ºä¸€ä¸ªèŠ‚ç‚¹ï¼ŒèŠ‚ç‚¹åœ¨Linux中表示为 ``struct pglist_data``,
+å³ä½¿æ˜¯åœ¨UMA架构中也是这样表示。该结构总是通过 ``pg_data_t`` æ¥å¼•用。特
+定节点的 ``pg_data_t`` 结构体å¯ä»¥é€šè¿‡NODE_DATA(nid)引用,其中nid被称
+为该节点的ID。
+
+对于éžä¸€è‡´æ€§å†…存访问(NUMA)架构,节点数æ®ç»“æž„åœ¨å¼•å¯¼æ—¶ç”±ç‰¹å®šäºŽæž¶æž„çš„ä»£ç æ—©
+期分é…。通常,这些结构在其所在的内存区上本地分é…。对于一致性内存访问(UMA)
+架构,åªä½¿ç”¨ä¸€ä¸ªé™æ€çš„ ``pg_data_t`` 结构体,称为 ``contig_page_data``。
+节点将会在 :ref:`节点 <nodes>` 章节中进一步讨论。
+
+整个物ç†å†…存被划分为一个或多个被称为区域的å—,这些区域表示内存的范围。这
+些范围通常由访问内存的架构é™åˆ¶æ¥å†³å®šã€‚在节点内,与特定区域对应的内存范围
+ç”± ``struct zone`` 结构体æè¿°ï¼Œè¯¥ç»“构被定义为 ``zone_t``,æ¯ç§åŒºåŸŸéƒ½
+属于以下æè¿°ç±»åž‹çš„一ç§ã€‚
+
+* ``ZONE_DMA`` å’Œ ``ZONE_DMA32`` 在历å²ä¸Šä»£è¡¨é€‚用于DMA的内存,这些
+ 内存由那些ä¸èƒ½è®¿é—®æ‰€æœ‰å¯å¯»å€å†…存的外设访问。多年æ¥ï¼Œå·²ç»æœ‰äº†æ›´å¥½ã€æ›´ç¨³
+ å›ºçš„æŽ¥å£æ¥èŽ·å–æ»¡è¶³ç‰¹å®šDMA需求的内存(这些接å£ç”±
+ Documentation/core-api/dma-api.rst 文档æè¿°ï¼‰ï¼Œä½†æ˜¯ ``ZONE_DMA``
+ å’Œ ``ZONE_DMA32`` ä»ç„¶è¡¨ç¤ºè®¿é—®å—é™çš„内存范围。
+
+å–决于架构的ä¸åŒï¼Œè¿™ä¸¤ç§åŒºåŸŸå¯ä»¥åœ¨æž„建时通过关闭 ``CONFIG_ZONE_DMA`` å’Œ
+``CONFIG_ZONE_DMA32`` é…置选项æ¥ç¦ç”¨ã€‚一些64ä½çš„å¹³å°å¯èƒ½éœ€è¦è¿™ä¸¤ç§åŒºåŸŸï¼Œ
+因为他们支æŒå…·æœ‰ä¸åŒDMA寻å€é™åˆ¶çš„外设。
+
+* ``ZONE_NORMAL`` 是普通内存的区域,这ç§å†…å­˜å¯ä»¥è¢«å†…æ ¸éšæ—¶è®¿é—®ã€‚如果DMA
+ 设备支æŒå°†æ•°æ®ä¼ è¾“到所有å¯å¯»å€çš„内存区域,那么å¯åœ¨è¯¥åŒºåŸŸçš„页é¢ä¸Šæ‰§è¡ŒDMA
+ æ“作。``ZONE_NORMAL`` 总是开å¯çš„。
+
+* ``ZONE_HIGHMEM`` 是指那些没有在内核页表中永久映射的物ç†å†…存部分。该区
+ 域的内存åªèƒ½é€šè¿‡ä¸´æ—¶æ˜ å°„被内核访问。该区域åªåœ¨æŸäº›32使ž¶æž„上å¯ç”¨ï¼Œå¹¶ä¸”是
+ 通过 ``CONFIG_HIGHMEM`` 选项开å¯ã€‚
+
+* ``ZONE_MOVABLE`` 是指å¯è®¿é—®çš„æ™®é€šå†…å­˜åŒºåŸŸï¼Œå°±åƒ ``ZONE_NORMAL``
+ 一样。ä¸åŒä¹‹å¤„在于 ``ZONE_MOVABLE`` 中的大多数页é¢å†…容是å¯ç§»åŠ¨çš„ã€‚
+ è¿™æ„味ç€è¿™äº›é¡µé¢çš„虚拟地å€ä¸ä¼šæ”¹å˜ï¼Œä½†å®ƒä»¬çš„内容å¯èƒ½ä¼šåœ¨ä¸åŒçš„物ç†é¡µé¢
+ ä¹‹é—´ç§»åŠ¨ã€‚é€šå¸¸ï¼Œåœ¨å†…å­˜çƒ­æ’æ‹”期间填充 ``ZONE_MOVABLE``,在å¯åŠ¨æ—¶ä¹Ÿå¯
+ 以使用 ``kernelcore``ã€``movablecore`` å’Œ ``movable_node``
+ è¿™äº›å†…æ ¸å‘½ä»¤è¡Œå‚æ•°æ¥å¡«å……。更多详细信æ¯ï¼Œè¯·å‚阅内核文档
+ Documentation/mm/page_migration.rst 和
+ Documentation/admin-guide/mm/memory-hotplug.rst。
+
+* ``ZONE_DEVICE`` 表示ä½äºŽæŒä¹…性内存(PMEM)和图形处ç†å•元(GPU)
+ 等设备上的内存。它与RAM区域类型有ä¸åŒçš„特性,并且它的存在是为了æä¾›
+ :ref:`struct page<Pages>` 结构和内存映射æœåŠ¡ï¼Œä»¥ä¾¿è®¾å¤‡é©±åŠ¨ç¨‹åºèƒ½
+ 识别物ç†åœ°å€èŒƒå›´ã€‚``ZONE_DEVICE`` 通过 ``CONFIG_ZONE_DEVICE``
+ 选项开å¯ã€‚
+
+éœ€è¦æ³¨æ„的是,许多内核æ“作åªèƒ½ä½¿ç”¨ ``ZONE_NORMAL`` æ¥æ‰§è¡Œï¼Œå› æ­¤å®ƒæ˜¯
+性能最关键区域。区域在 :ref:`区域 <zones>` 章节中有更详细的讨论。
+
+节点和区域范围之间的关系由固件报告的物ç†å†…存映射决定,å¦å¤–也由内存寻å€
+的架构约æŸä»¥åŠå†…核命令行中的æŸäº›å‚数决定。
+
+例如,在具有2GB RAMçš„x86统一内存架构(UMA)机器上è¿è¡Œ32ä½å†…核时,整
+个内存将ä½äºŽèŠ‚ç‚¹0,并且将有三个区域: ``ZONE_DMA``〠``ZONE_NORMAL``
+和 ``ZONE_HIGHMEM``::
+
+ 0 2G
+ +-------------------------------------------------------------+
+ | node 0 |
+ +-------------------------------------------------------------+
+
+ 0 16M 896M 2G
+ +----------+-----------------------+--------------------------+
+ | ZONE_DMA | ZONE_NORMAL | ZONE_HIGHMEM |
+ +----------+-----------------------+--------------------------+
+
+
+在内核构建时关闭 ``ZONE_DMA`` å¼€å¯ ``ZONE_DMA32``,并且具有16GB
+RAMå¹³å‡åˆ†é…在两个节点上的arm64机器上,使用 ``movablecore=80%`` 傿•°
+å¯åŠ¨æ—¶ï¼Œ``ZONE_DMA32``ã€``ZONE_NORMAL`` å’Œ ``ZONE_MOVABLE``
+ä½äºŽèŠ‚ç‚¹0,而 ``ZONE_NORMAL`` å’Œ ``ZONE_MOVABLE`` ä½äºŽèŠ‚ç‚¹1::
+
+
+ 1G 9G 17G
+ +--------------------------------+ +--------------------------+
+ | node 0 | | node 1 |
+ +--------------------------------+ +--------------------------+
+
+ 1G 4G 4200M 9G 9320M 17G
+ +---------+----------+-----------+ +------------+-------------+
+ | DMA32 | NORMAL | MOVABLE | | NORMAL | MOVABLE |
+ +---------+----------+-----------+ +------------+-------------+
+
+
+内存存储区å¯èƒ½ä½äºŽäº¤é”™çš„节点。在下é¢çš„例å­ä¸­ï¼Œä¸€å°x86机器有16GBçš„RAM分
+布在4ä¸ªå†…å­˜å­˜å‚¨åŒºä¸Šï¼Œå¶æ•°ç¼–å·çš„内存存储区属于节点0,奇数编å·çš„内存æ¡å±žäºŽ
+节点1::
+
+ 0 4G 8G 12G 16G
+ +-------------+ +-------------+ +-------------+ +-------------+
+ | node 0 | | node 1 | | node 0 | | node 1 |
+ +-------------+ +-------------+ +-------------+ +-------------+
+
+ 0 16M 4G
+ +-----+-------+ +-------------+ +-------------+ +-------------+
+ | DMA | DMA32 | | NORMAL | | NORMAL | | NORMAL |
+ +-----+-------+ +-------------+ +-------------+ +-------------+
+
+åœ¨è¿™ç§æƒ…况下,节点0将覆盖从0到12GB的内存范围,而节点1将覆盖从4GB到16GB
+的内存范围。
+
+.. _nodes_zh_CN:
+
+节点
+====
+
+正如我们所æåˆ°çš„,内存中的æ¯ä¸ªèŠ‚ç‚¹ç”± ``pg_data_t`` æè¿°ï¼Œé€šè¿‡
+``struct pglist_data`` 结构体的类型定义。在分é…页颿—¶ï¼Œé»˜è®¤æƒ…况下,Linux
+使用节点本地分é…策略,从离当å‰è¿è¡ŒCPU的最近节点分é…内存。由于进程倾å‘于在åŒ
+一个CPU上è¿è¡Œï¼Œå¾ˆå¯èƒ½ä¼šä½¿ç”¨å½“å‰èŠ‚ç‚¹çš„å†…å­˜ã€‚åˆ†é…ç­–ç•¥å¯ä»¥ç”±ç”¨æˆ·æŽ§åˆ¶ï¼Œå¦‚内核文
+档 Documentation/admin-guide/mm/numa_memory_policy.rst 中所述。
+
+大多数NUMA(éžç»Ÿä¸€å†…存访问)架构维护了一个指å‘节点结构的指针数组。这些实际
+的结构在å¯åŠ¨è¿‡ç¨‹ä¸­çš„æ—©æœŸè¢«åˆ†é…,这时特定于架构的代ç è§£æžäº†å›ºä»¶æŠ¥å‘Šçš„物ç†å†…
+存映射。节点åˆå§‹åŒ–的大部分工作是在由free_area_init()实现的å¯åŠ¨è¿‡ç¨‹ä¹‹åŽ
+完æˆï¼Œè¯¥å‡½æ•°åœ¨åŽé¢çš„å°èŠ‚ :ref:`åˆå§‹åŒ– <initialization>` 中有详细æè¿°ã€‚
+
+除了节点结构,内核还维护了一个å为 ``node_states`` çš„ ``nodemask_t``
+ä½æŽ©ç æ•°ç»„。这个数组中的æ¯ä¸ªä½æŽ©ç ä»£è¡¨ä¸€ç»„特定属性的节点,这些属性由
+``enum node_states`` 定义,定义如下:
+
+``N_POSSIBLE``
+节点å¯èƒ½åœ¨æŸä¸ªæ—¶åˆ»ä¸Šçº¿ã€‚
+
+``N_ONLINE``
+节点已ç»ä¸Šçº¿ã€‚
+
+``N_NORMAL_MEMORY``
+节点拥有普通内存。
+
+``N_HIGH_MEMORY``
+节点拥有普通或高端内存。当关闭 ``CONFIG_HIGHMEM`` é…置时,
+也å¯ä»¥ç§°ä¸º ``N_NORMAL_MEMORY``。
+
+``N_MEMORY``
+节点拥有(普通ã€é«˜ç«¯ã€å¯ç§»åŠ¨ï¼‰å†…å­˜ã€‚
+
+``N_CPU``
+节点拥有一个或多个CPU。
+
+对于具有上述属性的æ¯ä¸ªèŠ‚ç‚¹ï¼Œ``node_states[<property>]``
+掩ç ä¸­å¯¹åº”于节点IDçš„ä½ä¼šè¢«ç½®ä½ã€‚
+
+例如,对于具有常规内存和CPU的节点2,第二个bit将被设置::
+
+ node_states[N_POSSIBLE]
+ node_states[N_ONLINE]
+ node_states[N_NORMAL_MEMORY]
+ node_states[N_HIGH_MEMORY]
+ node_states[N_MEMORY]
+ node_states[N_CPU]
+
+有关使用节点掩ç ï¼ˆnodemasks)å¯èƒ½è¿›è¡Œçš„å„ç§æ“作,请å‚考
+``include/linux/nodemask.h``。
+
+除此之外,节点掩ç ï¼ˆnodemasks)æä¾›ç”¨äºŽé历节点的å®ï¼Œå³
+``for_each_node()`` 和 ``for_each_online_node()``。
+
+例如,è¦ä¸ºæ¯ä¸ªåœ¨çº¿èŠ‚ç‚¹è°ƒç”¨å‡½æ•° foo(),å¯ä»¥è¿™æ ·æ“作::
+
+ for_each_online_node(nid) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+
+ foo(pgdat);
+ }
+
+节点数æ®ç»“æž„
+------------
+
+节点结构 ``struct pglist_data`` 在 ``include/linux/mmzone.h``
+ä¸­å£°æ˜Žã€‚è¿™é‡Œæˆ‘ä»¬å°†ç®€è¦æè¿°è¿™ä¸ªç»“æž„ä½“çš„å­—æ®µï¼š
+
+通用字段
+~~~~~~~~
+
+``node_zones``
+è¡¨ç¤ºè¯¥èŠ‚ç‚¹çš„åŒºåŸŸåˆ—è¡¨ã€‚å¹¶éžæ‰€æœ‰åŒºåŸŸéƒ½å¯èƒ½è¢«å¡«å……,但这是
+完整的列表。它被该节点的node_zonelists以åŠå…¶å®ƒèŠ‚ç‚¹çš„
+node_zonelists引用。
+
+``node_zonelists``
+表示所有节点中所有区域的列表。此列表定义了分é…内存时首选的区域
+顺åºã€‚``node_zonelists`` 在核心内存管ç†ç»“æž„åˆå§‹åŒ–期间,
+由 ``mm/page_alloc.c`` 中的 ``build_zonelists()``
+函数设置。
+
+``nr_zones``
+表示此节点中已填充区域的数é‡ã€‚
+
+``node_mem_map``
+对于使用FLATMEM内存模型的UMA系统,0å·èŠ‚ç‚¹çš„ ``node_mem_map``
+表示æ¯ä¸ªç‰©ç†å¸§çš„struct pages数组。
+
+``node_page_ext``
+对于使用FLATMEM内存模型的UMA系统,0å·èŠ‚ç‚¹çš„ ``node_page_ext``
+是struct pagesçš„æ‰©å±•æ•°ç»„ã€‚åªæœ‰åœ¨æž„建时开å¯äº† ``CONFIG_PAGE_EXTENSION``
+选项的内核中æ‰å¯ç”¨ã€‚
+
+``node_start_pfn``
+表示此节点中起始页é¢å¸§çš„页é¢å¸§å·ã€‚
+
+``node_present_pages``
+表示此节点中存在的物ç†é¡µé¢çš„æ€»æ•°ã€‚
+
+``node_spanned_pages``
+表示包括空洞在内的物ç†é¡µé¢èŒƒå›´çš„æ€»å¤§å°ã€‚
+
+``node_size_lock``
+ä¸€ä¸ªä¿æŠ¤å®šä¹‰èŠ‚ç‚¹èŒƒå›´å­—æ®µçš„é”。仅在开å¯äº† ``CONFIG_MEMORY_HOTPLUG`` 或
+``CONFIG_DEFERRED_STRUCT_PAGE_INIT`` é…置选项中的æŸä¸€ä¸ªæ—¶æ‰å®šä¹‰ã€‚æ
+供了 ``pgdat_resize_lock()`` å’Œ ``pgdat_resize_unlock()`` ç”¨æ¥æ“作
+``node_size_lock``,而无需检查 ``CONFIG_MEMORY_HOTPLUG`` 或
+``CONFIG_DEFERRED_STRUCT_PAGE_INIT`` 选项。
+
+``node_id``
+节点的节点ID(NID),从0开始。
+
+``totalreserve_pages``
+这是æ¯ä¸ªèŠ‚ç‚¹ä¿ç•™çš„页é¢ï¼Œè¿™äº›é¡µé¢ä¸å¯ç”¨äºŽç”¨æˆ·ç©ºé—´åˆ†é…。
+
+``first_deferred_pfn``
+如果大型机器上的内存åˆå§‹åŒ–被推迟,那么第一个PFN(页帧å·ï¼‰æ˜¯éœ€è¦åˆå§‹åŒ–的。
+在开å¯äº† ``CONFIG_DEFERRED_STRUCT_PAGE_INIT`` 选项时定义。
+
+``deferred_split_queue``
+æ¯ä¸ªèŠ‚ç‚¹çš„å¤§é¡µé˜Ÿåˆ—ï¼Œè¿™äº›å¤§é¡µçš„æ‹†åˆ†è¢«æŽ¨è¿Ÿäº†ã€‚ä»…åœ¨å¼€å¯äº† ``CONFIG_TRANSPARENT_HUGEPAGE``
+é…置选项时定义。
+
+``__lruvec``
+æ¯ä¸ªèŠ‚ç‚¹çš„lruvecæŒæœ‰LRUï¼ˆæœ€è¿‘æœ€å°‘ä½¿ç”¨ï¼‰åˆ—è¡¨å’Œç›¸å…³å‚æ•°ã€‚仅在ç¦ç”¨äº†å†…å­˜
+控制组(cgroups)时使用。它ä¸åº”该直接访问,而应该使用 ``mem_cgroup_lruvec()``
+æ¥æŸ¥æ‰¾lruvecs。
+
+回收控制
+~~~~~~~~
+
+å¦è§å†…核文档 Documentation/mm/page_reclaim.rst 文件。
+
+``kswapd``
+æ¯ä¸ªèŠ‚ç‚¹çš„kswapd内核线程实例。
+
+``kswapd_wait``, ``pfmemalloc_wait``, ``reclaim_wait``
+åŒæ­¥å†…存回收任务的工作队列。
+
+``nr_writeback_throttled``
+等待写回è„页时,被é™åˆ¶çš„任务数é‡ã€‚
+
+``kswapd_order``
+控制kswapdå°è¯•回收的order。
+
+``kswapd_highest_zoneidx``
+kswapd线程å¯ä»¥å›žæ”¶çš„æœ€é«˜åŒºåŸŸç´¢å¼•。
+
+``kswapd_failures``
+kswapd无法回收任何页é¢çš„è¿è¡Œæ¬¡æ•°ã€‚
+
+``min_unmapped_pages``
+无法回收的未映射文件支æŒçš„æœ€å°é¡µé¢æ•°é‡ã€‚ç”± ``vm.min_unmapped_ratio``
+系统控制å°ï¼ˆsysctlï¼‰å‚æ•°å†³å®šã€‚åœ¨å¼€å¯ ``CONFIG_NUMA`` é…置时定义。
+
+``min_slab_pages``
+无法回收的SLAB页é¢çš„æœ€å°‘æ•°é‡ã€‚ç”± ``vm.min_slab_ratio`` 系统控制å°
+(sysctlï¼‰å‚æ•°å†³å®šã€‚åœ¨å¼€å¯ ``CONFIG_NUMA`` 时定义。
+
+``flags``
+控制回收行为的标志ä½ã€‚
+
+内存压缩控制
+~~~~~~~~~~~~
+
+``kcompactd_max_order``
+kcompactd应å°è¯•实现的页é¢order。
+
+``kcompactd_highest_zoneidx``
+kcompactdå¯ä»¥åŽ‹ç¼©çš„æœ€é«˜åŒºåŸŸç´¢å¼•ã€‚
+
+``kcompactd_wait``
+åŒæ­¥å†…存压缩任务的工作队列。
+
+``kcompactd``
+æ¯ä¸ªèŠ‚ç‚¹çš„kcompactd内核线程实例。
+
+``proactive_compact_trigger``
+决定是å¦ä½¿ç”¨ä¸»åŠ¨åŽ‹ç¼©ã€‚ç”± ``vm.compaction_proactiveness`` 系统控
+制å°ï¼ˆsysctlï¼‰å‚æ•°æŽ§åˆ¶ã€‚
+
+统计信æ¯
+~~~~~~~~
+
+``per_cpu_nodestats``
+表示节点的Per-CPU虚拟内存统计信æ¯ã€‚
+
+``vm_stat``
+表示节点的虚拟内存统计数æ®ã€‚
+
+.. _zones_zh_CN:
+
+区域
+====
+
+.. admonition:: Stub
+
+ 本节内容ä¸å®Œæ•´ã€‚请列出并æè¿°ç›¸åº”的字段。
+
+.. _pages_zh_CN:
+
+页
+====
+
+.. admonition:: Stub
+
+ 本节内容ä¸å®Œæ•´ã€‚请列出并æè¿°ç›¸åº”的字段。
+
+.. _folios_zh_CN:
+
+页ç 
+====
+
+.. admonition:: Stub
+
+ 本节内容ä¸å®Œæ•´ã€‚请列出并æè¿°ç›¸åº”的字段。
+
+.. _initialization_zh_CN:
+
+åˆå§‹åŒ–
+======
+
+.. admonition:: Stub
+
+ 本节内容ä¸å®Œæ•´ã€‚请列出并æè¿°ç›¸åº”的字段。
diff --git a/Documentation/translations/zh_CN/process/5.Posting.rst b/Documentation/translations/zh_CN/process/5.Posting.rst
index 6a469e1c7deb..6c83a8f40310 100644
--- a/Documentation/translations/zh_CN/process/5.Posting.rst
+++ b/Documentation/translations/zh_CN/process/5.Posting.rst
@@ -146,10 +146,6 @@
- è¡¥ä¸æœ¬èº«ï¼Œé‡‡ç”¨ç»Ÿä¸€çš„(“-uâ€ï¼‰è¡¥ä¸æ ¼å¼ã€‚使用“-pâ€é€‰é¡¹æ¥diff将使函数å与
更改相关è”ï¼Œä»Žè€Œä½¿ç»“æžœè¡¥ä¸æ›´å®¹æ˜“被其他人读å–。
-您应该é¿å…在补ä¸ä¸­åŒ…括与更改ä¸ç›¸å…³æ–‡ä»¶ï¼ˆä¾‹å¦‚,构建过程生æˆçš„æ–‡ä»¶æˆ–编辑器
-备份文件)。文档目录中的“dontdiffâ€æ–‡ä»¶åœ¨è¿™æ–¹é¢æœ‰å¸®åŠ©ï¼›ä½¿ç”¨â€œ-Xâ€é€‰é¡¹å°†
-其传递给diff。
-
ä¸Šé¢æåˆ°çš„æ ‡ç­¾ï¼ˆtag)用于æè¿°å„ç§å¼€å‘人员如何与这个补ä¸çš„å¼€å‘相关è”。
:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>`
文档中对它们进行了详细æè¿°ï¼›ä¸‹é¢æ˜¯ä¸€ä¸ªç®€çŸ­çš„æ€»ç»“。æ¯ä¸€è¡Œçš„æ ¼å¼å¦‚下:
diff --git a/Documentation/translations/zh_CN/process/coding-style.rst b/Documentation/translations/zh_CN/process/coding-style.rst
index 10b9cb4f6a65..0484d0c65c25 100644
--- a/Documentation/translations/zh_CN/process/coding-style.rst
+++ b/Documentation/translations/zh_CN/process/coding-style.rst
@@ -560,17 +560,6 @@ Documentation/translations/zh_CN/doc-guide/index.rst 和 scripts/kernel-doc 。
* with beginning and ending almost-blank lines.
*/
-对于在 net/ å’Œ drivers/net/ 的文件,首选的长 (多行) 注释风格有些ä¸åŒã€‚
-
-.. code-block:: c
-
- /* The preferred comment style for files in net/ and drivers/net
- * looks like this.
- *
- * It is nearly the same as the generally preferred comment style,
- * but there is no initial almost-blank line.
- */
-
注释数æ®ä¹Ÿæ˜¯å¾ˆé‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬ç±»åž‹è¿˜æ˜¯è¡ç”Ÿç±»åž‹ã€‚为了方便实现这一点,æ¯ä¸€è¡Œ
应åªå£°æ˜Žä¸€ä¸ªæ•°æ® (ä¸è¦ä½¿ç”¨é€—å·æ¥ä¸€æ¬¡å£°æ˜Žå¤šä¸ªæ•°æ®)。这样你就有空间æ¥ä¸ºæ¯ä¸ªæ•°æ®
å†™ä¸€æ®µå°æ³¨é‡Šæ¥è§£é‡Šå®ƒä»¬çš„用途了。
diff --git a/Documentation/translations/zh_CN/process/email-clients.rst b/Documentation/translations/zh_CN/process/email-clients.rst
index 34d51cdadc7b..a70393089df3 100644
--- a/Documentation/translations/zh_CN/process/email-clients.rst
+++ b/Documentation/translations/zh_CN/process/email-clients.rst
@@ -197,7 +197,7 @@ Muttä¸è‡ªå¸¦ç¼–辑器,所以ä¸ç®¡ä½ ä½¿ç”¨ä»€ä¹ˆç¼–辑器,ä¸è‡ªåŠ¨æ–­è¡Œå
Mutt 是高度å¯é…置的。 这里是个使用mutt通过 Gmail å‘é€çš„è¡¥ä¸çš„æœ€å°é…ç½®::
# .muttrc
- # ================ IMAP ====================
+ # ================ IMAP ====================
set imap_user = 'yourusername@gmail.com'
set imap_pass = 'yourpassword'
set spoolfile = imaps://imap.gmail.com/INBOX
@@ -325,3 +325,10 @@ Gmail网页客户端自动地把制表符转æ¢ä¸ºç©ºæ ¼ã€‚
å¦ä¸€ä¸ªé—®é¢˜æ˜¯Gmailè¿˜ä¼šæŠŠä»»ä½•å«æœ‰éžASCIIçš„å­—ç¬¦çš„æ¶ˆæ¯æ”¹ç”¨base64ç¼–ç ï¼Œå¦‚欧洲人的
å字。
+HacKerMaiL (TUI)
+****************
+
+HacKerMaiL (hkml) 是一个基于公共收件箱的简å•邮件管ç†å·¥å…·ï¼Œå®ƒä¸éœ€è¦è®¢é˜…邮件列表。
+该工具由 DAMON 维护者开å‘å’Œç»´æŠ¤ï¼Œæ—¨åœ¨æ”¯æŒ DAMON 和通用内核å­ç³»ç»Ÿçš„基本开å‘工作
+æµç¨‹ã€‚详细信æ¯å¯å‚考 HacKerMaiL çš„ README 文件
+(https://github.com/sjp38/hackermail/blob/master/README.md)。
diff --git a/Documentation/translations/zh_CN/process/programming-language.rst b/Documentation/translations/zh_CN/process/programming-language.rst
index fabdc338dbfb..95aa4829d78f 100644
--- a/Documentation/translations/zh_CN/process/programming-language.rst
+++ b/Documentation/translations/zh_CN/process/programming-language.rst
@@ -3,25 +3,22 @@
:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
:Translator: Alex Shi <alex.shi@linux.alibaba.com>
-.. _cn_programming_language:
-
程åºè®¾è®¡è¯­è¨€
============
-内核是用C语言 :ref:`c-language <cn_c-language>` 编写的。更准确地说,内核通常是用 :ref:`gcc <cn_gcc>`
-在 ``-std=gnu11`` :ref:`gcc-c-dialect-options <cn_gcc-c-dialect-options>` 下编译的:ISO C11的 GNU 方言
-
-è¿™ç§æ–¹è¨€åŒ…å«å¯¹è¯­è¨€ :ref:`gnu-extensions <cn_gnu-extensions>` 的许多扩展,当然,它们许多都在内核中使用。
+内核是用 C 编程语言编写的 [zh_cn_c-language]_。更准确地说,内核通常使用 ``gcc`` [zh_cn_gcc]_ 编译,
+并且使用 ``-std=gnu11`` [zh_cn_gcc-c-dialect-options]_:这是 ISO C11 的 GNU 方言。
+``clang`` [zh_cn_clang]_ 也得到了支æŒï¼Œè¯¦è§æ–‡æ¡£ï¼š
+:ref:`使用 Clang/LLVM 构建 Linux <kbuild_llvm>`。
-对于一些体系结构,有一些使用 :ref:`clang <cn_clang>` 和 :ref:`icc <cn_icc>` 编译内核
-的支æŒï¼Œå°½ç®¡åœ¨ç¼–写此文档时还没有完æˆï¼Œä»éœ€è¦ç¬¬ä¸‰æ–¹è¡¥ä¸ã€‚
+è¿™ç§æ–¹è¨€åŒ…å«å¯¹ C 语言的许多扩展 [zh_cn_gnu-extensions]_,当然,它们许多都在内核中使用。
属性
----
-åœ¨æ•´ä¸ªå†…æ ¸ä¸­ä½¿ç”¨çš„ä¸€ä¸ªå¸¸è§æ‰©å±•是属性(attributes) :ref:`gcc-attribute-syntax <cn_gcc-attribute-syntax>`
+åœ¨æ•´ä¸ªå†…æ ¸ä¸­ä½¿ç”¨çš„ä¸€ä¸ªå¸¸è§æ‰©å±•是属性(attributes) [zh_cn_gcc-attribute-syntax]_。
属性å…许将实现定义的语义引入语言实体(如å˜é‡ã€å‡½æ•°æˆ–类型),而无需对语言进行
-é‡å¤§çš„语法更改(例如添加新关键字) :ref:`n2049 <cn_n2049>`
+é‡å¤§çš„语法更改(例如添加新关键字) [zh_cn_n2049]_。
在æŸäº›æƒ…况下,属性是å¯é€‰çš„(å³ä¸æ”¯æŒè¿™äº›å±žæ€§çš„编译器ä»ç„¶åº”è¯¥ç”Ÿæˆæ­£ç¡®çš„代ç ï¼Œ
å³ä½¿å…¶é€Ÿåº¦è¾ƒæ…¢æˆ–执行的编译时检查/诊断次数ä¸å¤Ÿï¼‰
@@ -30,42 +27,27 @@
``__attribute__((__pure__))`` ),以检测å¯ä»¥ä½¿ç”¨å“ªäº›å…³é”®å­—å’Œ/或缩短代ç , 具体
请å‚阅 ``include/linux/compiler_attributes.h``
-.. _cn_c-language:
-
-c-language
- http://www.open-std.org/jtc1/sc22/wg14/www/standards
-
-.. _cn_gcc:
-
-gcc
- https://gcc.gnu.org
-
-.. _cn_clang:
-
-clang
- https://clang.llvm.org
-
-.. _cn_icc:
-
-icc
- https://software.intel.com/en-us/c-compilers
-
-.. _cn_gcc-c-dialect-options:
-
-c-dialect-options
- https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
-
-.. _cn_gnu-extensions:
-
-gnu-extensions
- https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
-
-.. _cn_gcc-attribute-syntax:
-
-gcc-attribute-syntax
- https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
-
-.. _cn_n2049:
+Rust
+----
-n2049
- http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+内核对 Rust 编程语言 [zh_cn_rust-language]_ çš„æ”¯æŒæ˜¯å®žéªŒæ€§çš„,并且å¯ä»¥é€šè¿‡é…置选项
+``CONFIG_RUST`` æ¥å¯ç”¨ã€‚Rust 代ç ä½¿ç”¨ ``rustc`` [zh_cn_rustc]_ 编译器在
+``--edition=2021`` [zh_cn_rust-editions]_ 选项下进行编译。版本(Editions)是一ç§
+在语言中引入éžåŽå‘兼容的å°åž‹å˜æ›´çš„æ–¹å¼ã€‚
+
+除此之外,内核中还使用了一些ä¸ç¨³å®šçš„特性 [zh_cn_rust-unstable-features]_。这些ä¸ç¨³å®š
+的特性将æ¥å¯èƒ½ä¼šå‘生å˜åŒ–,因此,一个é‡è¦çš„目标是达到仅使用稳定特性的程度。
+
+具体请å‚阅 Documentation/rust/index.rst
+
+.. [zh_cn_c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards
+.. [zh_cn_gcc] https://gcc.gnu.org
+.. [zh_cn_clang] https://clang.llvm.org
+.. [zh_cn_gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+.. [zh_cn_gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+.. [zh_cn_gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+.. [zh_cn_n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+.. [zh_cn_rust-language] https://www.rust-lang.org
+.. [zh_cn_rustc] https://doc.rust-lang.org/rustc/
+.. [zh_cn_rust-editions] https://doc.rust-lang.org/edition-guide/editions/
+.. [zh_cn_rust-unstable-features] https://github.com/Rust-for-Linux/linux/issues/2
diff --git a/Documentation/translations/zh_CN/process/submitting-patches.rst b/Documentation/translations/zh_CN/process/submitting-patches.rst
index 7ca16bda3709..f7ae584a439e 100644
--- a/Documentation/translations/zh_CN/process/submitting-patches.rst
+++ b/Documentation/translations/zh_CN/process/submitting-patches.rst
@@ -105,7 +105,7 @@ xyzzy do frotzâ€æˆ–“[I]changed xyzzy to do frotzâ€ï¼Œå°±å¥½åƒä½ åœ¨å‘½ä»¤ä»
当链接到邮件列表存档时,请首选lore.kernel.org邮件存档æœåŠ¡ã€‚ç”¨é‚®ä»¶ä¸­çš„
``Message-ID`` 头(去掉尖括å·ï¼‰å¯ä»¥åˆ›å»ºé“¾æŽ¥URL。例如::
- Link: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
+ Link: https://lore.kernel.org/30th.anniversary.repost@klaava.Helsinki.FI
请检查该链接以确ä¿å¯ç”¨ä¸”æŒ‡å‘æ­£ç¡®çš„邮件。
@@ -195,11 +195,8 @@ scripts/get_maintainer.pl在这个步骤中éžå¸¸æœ‰ç”¨ã€‚如果您找ä¸åˆ°æ­£å
在MAINTAINERS文件中查找å­ç³»ç»Ÿç‰¹å®šçš„列表;您的补ä¸å¯èƒ½ä¼šåœ¨é‚£é‡Œå¾—到更多的关注。
ä¸è¿‡ï¼Œè¯·ä¸è¦å‘é€åžƒåœ¾é‚®ä»¶åˆ°æ— å…³çš„列表。
-许多与内核相关的列表托管在vger.kernel.org上;您å¯ä»¥åœ¨
-http://vger.kernel.org/vger-lists.html 上找到它们的列表。ä¸è¿‡ï¼Œä¹Ÿæœ‰ä¸Žå†…核相关
-的列表托管在其他地方。
-
-ä¸è¦ä¸€æ¬¡å‘é€è¶…过15个补ä¸åˆ°vger邮件列表ï¼ï¼ï¼ï¼
+许多与内核相关的列表托管在 kernel.org 上;您å¯ä»¥åœ¨ https://subspace.kernel.org
+上找到它们的列表。ä¸è¿‡ï¼Œä¹Ÿæœ‰ä¸Žå†…核相关的列表托管在其他地方。
Linus Torvalds是决定改动能å¦è¿›å…¥ Linux 内核的最终è£å†³è€…ã€‚ä»–çš„é‚®ä»¶åœ°å€æ˜¯
torvalds@linux-foundation.org 。他收到的邮件很多,所以一般æ¥è¯´æœ€å¥½ **别**
@@ -621,6 +618,13 @@ Fixes: 指示补ä¸ä¿®å¤äº†ä¹‹å‰æäº¤çš„一个问题。它å¯ä»¥ä¾¿äºŽç¡®å®šé
的工作所基于的树的æäº¤å“ˆå¸Œã€‚你应该在å°é¢é‚®ä»¶æˆ–系列的第一个补ä¸ä¸­æ·»åŠ å®ƒï¼Œå®ƒåº”
该放在 ``---`` è¡Œçš„ä¸‹é¢æˆ–所有其他内容之åŽï¼Œå³åªåœ¨ä½ çš„电å­é‚®ä»¶ç­¾å之å‰ã€‚
+工具
+----
+
+这个过程的许多技术方é¢å¯ä»¥ä½¿ç”¨ b4 自动完æˆï¼Œå…¶æ–‡æ¡£å¯åœ¨
+https://b4.docs.kernel.org/en/latest/ 查看。该工具å¯å¸®åЩ处ç†è¯¸å¦‚追踪ä¾èµ–项ã€è¿è¡Œ
+checkpatch ä»¥åŠæ ¼å¼åŒ–å’Œå‘é€é‚®ä»¶ç­‰äº‹åŠ¡ã€‚
+
å‚考文献
--------
@@ -643,9 +647,6 @@ Greg Kroah-Hartman,“如何惹æ¼å†…æ ¸å­ç³»ç»Ÿç»´æŠ¤äººå‘˜â€
<http://www.kroah.com/log/linux/maintainer-06.html>
-ä¸ï¼ï¼ï¼åˆ«å†å‘巨型补ä¸ç‚¸å¼¹ç»™linux-kernel@vger.kernel.org的人们了ï¼
- <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
-
内核 Documentation/translations/zh_CN/process/coding-style.rst
Linus Torvaldså…³äºŽæ ‡å‡†è¡¥ä¸æ ¼å¼çš„邮件
diff --git a/Documentation/translations/zh_TW/dev-tools/gcov.rst b/Documentation/translations/zh_TW/dev-tools/gcov.rst
index ce1c9a97de16..39ac3fff44cd 100644
--- a/Documentation/translations/zh_TW/dev-tools/gcov.rst
+++ b/Documentation/translations/zh_TW/dev-tools/gcov.rst
@@ -120,7 +120,7 @@ gcovçš„å…§æ ¸åˆ†æžæ’æ¨æ”¯æŒå…§æ ¸çš„編譯和é‹è¡Œæ˜¯åœ¨åŒä¸€è‡ºæ©Ÿå™¨ä¸Šï
如果內核編譯和é‹è¡Œæ˜¯ä¸åŒçš„æ©Ÿå™¨ï¼Œé‚£éº¼éœ€è¦é¡å¤–çš„æº–å‚™å·¥ä½œï¼Œé€™å–æ±ºæ–¼gcov工具
是在哪è£ä½¿ç”¨çš„:
-.. _gcov-test_zh:
+.. _gcov-test_zh_TW:
a) è‹¥gcové‹è¡Œåœ¨æ¸¬è©¦æ©Ÿä¸Š
@@ -140,7 +140,7 @@ a) è‹¥gcové‹è¡Œåœ¨æ¸¬è©¦æ©Ÿä¸Š
å¦‚æžœæ–‡ä»¶æ˜¯è»ŸéˆæŽ¥ï¼Œéœ€è¦æ›¿æ›æˆçœŸæ­£çš„目錄文件(這是由make的當å‰å·¥ä½œ
目錄變é‡CURDIR引起的)。
-.. _gcov-build_zh:
+.. _gcov-build_zh_TW:
b) è‹¥gcové‹è¡Œåœ¨ç·¨è­¯æ©Ÿä¸Š
@@ -205,7 +205,7 @@ kconfig會根據編譯工具éˆçš„æª¢æŸ¥è‡ªå‹•鏿“‡åˆé©çš„gcovæ ¼å¼ã€‚
--------------------------
用於在編譯機上收集覆蓋率元文件的示例腳本
-(見 :ref:`編譯機和測試機分離 a. <gcov-test_zh>` )
+(見 :ref:`編譯機和測試機分離 a. <gcov-test_zh_TW>` )
.. code-block:: sh
@@ -238,7 +238,7 @@ kconfig會根據編譯工具éˆçš„æª¢æŸ¥è‡ªå‹•鏿“‡åˆé©çš„gcovæ ¼å¼ã€‚
-------------------------
用於在測試機上收集覆蓋率數據文件的示例腳本
-(見 :ref:`編譯機和測試機分離 b. <gcov-build_zh>` )
+(見 :ref:`編譯機和測試機分離 b. <gcov-build_zh_TW>` )
.. code-block:: sh
diff --git a/Documentation/translations/zh_TW/dev-tools/kasan.rst b/Documentation/translations/zh_TW/dev-tools/kasan.rst
index ed342e67d8ed..27fb7645174d 100644
--- a/Documentation/translations/zh_TW/dev-tools/kasan.rst
+++ b/Documentation/translations/zh_TW/dev-tools/kasan.rst
@@ -404,16 +404,13 @@ KASAN連接到vmapåŸºç¤Žæž¶æ§‹ä»¥æ‡¶æ¸…ç†æœªä½¿ç”¨çš„å½±å­å…§å­˜ã€‚
~~~~
有一些KASAN測試å¯ä»¥é©—è­‰KASANæ˜¯å¦æ­£å¸¸å·¥ä½œä¸¦å¯ä»¥æª¢æ¸¬æŸäº›é¡žåž‹çš„å…§å­˜æå£žã€‚
-測試由兩部分組æˆ:
-1. 與KUnit測試框架集æˆçš„æ¸¬è©¦ã€‚使用 ``CONFIG_KASAN_KUNIT_TEST`` 啓用。
-這些測試å¯ä»¥é€šéŽå¹¾ç¨®ä¸åŒçš„æ–¹å¼è‡ªå‹•é‹è¡Œå’Œéƒ¨åˆ†é©—證;請åƒé–±ä¸‹é¢çš„說明。
+所有 KASAN 測試å‡èˆ‡ KUnit 測試框架集æˆï¼Œä¸¦ä¸”å¯ä»¥å•Ÿç”¨
+é€éŽ ``CONFIG_KASAN_KUNIT_TEST``。å¯ä»¥é‹è¡Œæ¸¬è©¦ä¸¦é€²è¡Œéƒ¨åˆ†é©—è­‰
+以幾種ä¸åŒçš„æ–¹å¼è‡ªå‹•進行;請åƒé–±ä¸‹é¢çš„說明。
-2. 與KUnitä¸å…¼å®¹çš„æ¸¬è©¦ã€‚使用 ``CONFIG_KASAN_MODULE_TEST`` 啓用並且åªèƒ½ä½œçˆ²æ¨¡å¡Š
-é‹è¡Œã€‚這些測試åªèƒ½é€šéŽåŠ è¼‰å…§æ ¸æ¨¡å¡Šä¸¦æª¢æŸ¥å…§æ ¸æ—¥èªŒä»¥ç²å–KASAN報告來手動驗證。
-
-如果檢測到錯誤,æ¯å€‹KUnit兼容的KASAN測試都會打å°å¤šå€‹KASAN報告之一,然後測試打å°
-其編號和狀態。
+å¦‚æžœåµæ¸¬åˆ°éŒ¯èª¤ï¼Œæ¯å€‹ KASAN 測試都會列å°å¤šå€‹ KASAN 報告之一。
+然後測試列å°å…¶ç·¨è™Ÿå’Œç‹€æ…‹ã€‚
當測試通éŽ::
@@ -440,16 +437,16 @@ KASAN連接到vmapåŸºç¤Žæž¶æ§‹ä»¥æ‡¶æ¸…ç†æœªä½¿ç”¨çš„å½±å­å…§å­˜ã€‚
not ok 1 - kasan
-有幾種方法å¯ä»¥é‹è¡Œèˆ‡KUnit兼容的KASAN測試。
+有幾種方法å¯ä»¥åŸ·è¡Œ KASAN 測試。
1. å¯åŠ è¼‰æ¨¡å¡Š
- 啓用 ``CONFIG_KUNIT`` 後,KASAN-KUnit測試å¯ä»¥æ§‹å»ºçˆ²å¯åŠ è¼‰æ¨¡å¡Šï¼Œä¸¦é€šéŽä½¿ç”¨
- ``insmod`` 或 ``modprobe`` 加載 ``kasan_test.ko`` 來é‹è¡Œã€‚
+ 啟用 ``CONFIG_KUNIT`` 後,測試å¯ä»¥å»ºç½®ç‚ºå¯è¼‰å…¥æ¨¡çµ„
+ 並且é€éŽä½¿ç”¨ ``insmod`` 或 ``modprobe`` 來載入 ``kasan_test.ko`` 來é‹ä½œã€‚
2. å…§ç½®
- 通éŽå…§ç½® ``CONFIG_KUNIT`` ,也å¯ä»¥å…§ç½®KASAN-KUnit測試。在這種情æ³ä¸‹ï¼Œ
+ é€éŽå…§å»º ``CONFIG_KUNIT``,測試也å¯ä»¥å…§å»ºã€‚
測試將在啓動時作爲後期åˆå§‹åŒ–調用é‹è¡Œã€‚
3. 使用kunit_tool
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
index 7d66a1c638be..38f3a6d618eb 100644
--- a/Documentation/translations/zh_TW/process/5.Posting.rst
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -149,10 +149,6 @@
- è£œä¸æœ¬èº«ï¼ŒæŽ¡ç”¨çµ±ä¸€çš„(“-uâ€ï¼‰è£œä¸æ ¼å¼ã€‚使用“-pâ€é¸é …來diff將使函數å與
更改相關è¯ï¼Œå¾žè€Œä½¿çµæžœè£œä¸æ›´å®¹æ˜“被其他人讀å–。
-您應該é¿å…在補ä¸ä¸­åŒ…括與更改ä¸ç›¸é—œæ–‡ä»¶ï¼ˆä¾‹å¦‚,構建éŽç¨‹ç”Ÿæˆçš„æ–‡ä»¶æˆ–編輯器
-備份文件)。文檔目錄中的“dontdiffâ€æ–‡ä»¶åœ¨é€™æ–¹é¢æœ‰å¹«åŠ©ï¼›ä½¿ç”¨â€œ-Xâ€é¸é …å°‡
-其傳éžçµ¦diff。
-
ä¸Šé¢æåˆ°çš„æ¨™ç±¤ï¼ˆtag)用於æè¿°å„種開發人員如何與這個補ä¸çš„開發相關è¯ã€‚
:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <tw_submittingpatches>`
文檔中å°å®ƒå€‘進行了詳細æè¿°ï¼›ä¸‹é¢æ˜¯ä¸€å€‹ç°¡çŸ­çš„總çµã€‚æ¯ä¸€è¡Œçš„æ ¼å¼å¦‚下:
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index e4be1378ba26..243f1f1b554a 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -375,7 +375,7 @@ Code Seq# Include File Comments
0xCB 00-1F CBM serial IEC bus in development:
<mailto:michael.klein@puffin.lb.shuttle.de>
0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver
-0xCD 01 linux/reiserfs_fs.h
+0xCD 01 linux/reiserfs_fs.h Dead since 6.13
0xCE 01-02 uapi/linux/cxl_mem.h Compute Express Link Memory Devices
0xCF 02 fs/smb/client/cifs_ioctl.h
0xDB 00-0F drivers/char/mwave/mwavepub.h
diff --git a/Documentation/userspace-api/iommufd.rst b/Documentation/userspace-api/iommufd.rst
index aa004faed5fd..70289d6815d2 100644
--- a/Documentation/userspace-api/iommufd.rst
+++ b/Documentation/userspace-api/iommufd.rst
@@ -41,46 +41,133 @@ Following IOMMUFD objects are exposed to userspace:
- IOMMUFD_OBJ_DEVICE, representing a device that is bound to iommufd by an
external driver.
-- IOMMUFD_OBJ_HW_PAGETABLE, representing an actual hardware I/O page table
- (i.e. a single struct iommu_domain) managed by the iommu driver.
-
- The IOAS has a list of HW_PAGETABLES that share the same IOVA mapping and
- it will synchronize its mapping with each member HW_PAGETABLE.
+- IOMMUFD_OBJ_HWPT_PAGING, representing an actual hardware I/O page table
+ (i.e. a single struct iommu_domain) managed by the iommu driver. "PAGING"
+ primarly indicates this type of HWPT should be linked to an IOAS. It also
+ indicates that it is backed by an iommu_domain with __IOMMU_DOMAIN_PAGING
+ feature flag. This can be either an UNMANAGED stage-1 domain for a device
+ running in the user space, or a nesting parent stage-2 domain for mappings
+ from guest-level physical addresses to host-level physical addresses.
+
+ The IOAS has a list of HWPT_PAGINGs that share the same IOVA mapping and
+ it will synchronize its mapping with each member HWPT_PAGING.
+
+- IOMMUFD_OBJ_HWPT_NESTED, representing an actual hardware I/O page table
+ (i.e. a single struct iommu_domain) managed by user space (e.g. guest OS).
+ "NESTED" indicates that this type of HWPT should be linked to an HWPT_PAGING.
+ It also indicates that it is backed by an iommu_domain that has a type of
+ IOMMU_DOMAIN_NESTED. This must be a stage-1 domain for a device running in
+ the user space (e.g. in a guest VM enabling the IOMMU nested translation
+ feature.) As such, it must be created with a given nesting parent stage-2
+ domain to associate to. This nested stage-1 page table managed by the user
+ space usually has mappings from guest-level I/O virtual addresses to guest-
+ level physical addresses.
+
+- IOMMUFD_OBJ_VIOMMU, representing a slice of the physical IOMMU instance,
+ passed to or shared with a VM. It may be some HW-accelerated virtualization
+ features and some SW resources used by the VM. For examples:
+
+ * Security namespace for guest owned ID, e.g. guest-controlled cache tags
+ * Non-device-affiliated event reporting, e.g. invalidation queue errors
+ * Access to a sharable nesting parent pagetable across physical IOMMUs
+ * Virtualization of various platforms IDs, e.g. RIDs and others
+ * Delivery of paravirtualized invalidation
+ * Direct assigned invalidation queues
+ * Direct assigned interrupts
+
+ Such a vIOMMU object generally has the access to a nesting parent pagetable
+ to support some HW-accelerated virtualization features. So, a vIOMMU object
+ must be created given a nesting parent HWPT_PAGING object, and then it would
+ encapsulate that HWPT_PAGING object. Therefore, a vIOMMU object can be used
+ to allocate an HWPT_NESTED object in place of the encapsulated HWPT_PAGING.
+
+ .. note::
+
+ The name "vIOMMU" isn't necessarily identical to a virtualized IOMMU in a
+ VM. A VM can have one giant virtualized IOMMU running on a machine having
+ multiple physical IOMMUs, in which case the VMM will dispatch the requests
+ or configurations from this single virtualized IOMMU instance to multiple
+ vIOMMU objects created for individual slices of different physical IOMMUs.
+ In other words, a vIOMMU object is always a representation of one physical
+ IOMMU, not necessarily of a virtualized IOMMU. For VMMs that want the full
+ virtualization features from physical IOMMUs, it is suggested to build the
+ same number of virtualized IOMMUs as the number of physical IOMMUs, so the
+ passed-through devices would be connected to their own virtualized IOMMUs
+ backed by corresponding vIOMMU objects, in which case a guest OS would do
+ the "dispatch" naturally instead of VMM trappings.
+
+- IOMMUFD_OBJ_VDEVICE, representing a virtual device for an IOMMUFD_OBJ_DEVICE
+ against an IOMMUFD_OBJ_VIOMMU. This virtual device holds the device's virtual
+ information or attributes (related to the vIOMMU) in a VM. An immediate vDATA
+ example can be the virtual ID of the device on a vIOMMU, which is a unique ID
+ that VMM assigns to the device for a translation channel/port of the vIOMMU,
+ e.g. vSID of ARM SMMUv3, vDeviceID of AMD IOMMU, and vRID of Intel VT-d to a
+ Context Table. Potential use cases of some advanced security information can
+ be forwarded via this object too, such as security level or realm information
+ in a Confidential Compute Architecture. A VMM should create a vDEVICE object
+ to forward all the device information in a VM, when it connects a device to a
+ vIOMMU, which is a separate ioctl call from attaching the same device to an
+ HWPT_PAGING that the vIOMMU holds.
All user-visible objects are destroyed via the IOMMU_DESTROY uAPI.
-The diagram below shows relationship between user-visible objects and kernel
+The diagrams below show relationships between user-visible objects and kernel
datastructures (external to iommufd), with numbers referred to operations
creating the objects and links::
- _________________________________________________________
- | iommufd |
- | [1] |
- | _________________ |
- | | | |
- | | | |
- | | | |
- | | | |
- | | | |
- | | | |
- | | | [3] [2] |
- | | | ____________ __________ |
- | | IOAS |<--| |<------| | |
- | | | |HW_PAGETABLE| | DEVICE | |
- | | | |____________| |__________| |
- | | | | | |
- | | | | | |
- | | | | | |
- | | | | | |
- | | | | | |
- | |_________________| | | |
- | | | | |
- |_________|___________________|___________________|_______|
- | | |
- | _____v______ _______v_____
- | PFN storage | | | |
- |------------>|iommu_domain| |struct device|
- |____________| |_____________|
+ _______________________________________________________________________
+ | iommufd (HWPT_PAGING only) |
+ | |
+ | [1] [3] [2] |
+ | ________________ _____________ ________ |
+ | | | | | | | |
+ | | IOAS |<---| HWPT_PAGING |<---------------------| DEVICE | |
+ | |________________| |_____________| |________| |
+ | | | | |
+ |_________|____________________|__________________________________|_____|
+ | | |
+ | ______v_____ ___v__
+ | PFN storage | (paging) | |struct|
+ |------------>|iommu_domain|<-----------------------|device|
+ |____________| |______|
+
+ _______________________________________________________________________
+ | iommufd (with HWPT_NESTED) |
+ | |
+ | [1] [3] [4] [2] |
+ | ________________ _____________ _____________ ________ |
+ | | | | | | | | | |
+ | | IOAS |<---| HWPT_PAGING |<---| HWPT_NESTED |<--| DEVICE | |
+ | |________________| |_____________| |_____________| |________| |
+ | | | | | |
+ |_________|____________________|__________________|_______________|_____|
+ | | | |
+ | ______v_____ ______v_____ ___v__
+ | PFN storage | (paging) | | (nested) | |struct|
+ |------------>|iommu_domain|<----|iommu_domain|<----|device|
+ |____________| |____________| |______|
+
+ _______________________________________________________________________
+ | iommufd (with vIOMMU/vDEVICE) |
+ | |
+ | [5] [6] |
+ | _____________ _____________ |
+ | | | | | |
+ | |----------------| vIOMMU |<---| vDEVICE |<----| |
+ | | | | |_____________| | |
+ | | | | | |
+ | | [1] | | [4] | [2] |
+ | | ______ | | _____________ _|______ |
+ | | | | | [3] | | | | | |
+ | | | IOAS |<---|(HWPT_PAGING)|<---| HWPT_NESTED |<--| DEVICE | |
+ | | |______| |_____________| |_____________| |________| |
+ | | | | | | |
+ |______|________|______________|__________________|_______________|_____|
+ | | | | |
+ ______v_____ | ______v_____ ______v_____ ___v__
+ | struct | | PFN | (paging) | | (nested) | |struct|
+ |iommu_device| |------>|iommu_domain|<----|iommu_domain|<----|device|
+ |____________| storage|____________| |____________| |______|
1. IOMMUFD_OBJ_IOAS is created via the IOMMU_IOAS_ALLOC uAPI. An iommufd can
hold multiple IOAS objects. IOAS is the most generic object and does not
@@ -94,21 +181,63 @@ creating the objects and links::
device. The driver must also set the driver_managed_dma flag and must not
touch the device until this operation succeeds.
-3. IOMMUFD_OBJ_HW_PAGETABLE is created when an external driver calls the IOMMUFD
- kAPI to attach a bound device to an IOAS. Similarly the external driver uAPI
- allows userspace to initiate the attaching operation. If a compatible
- pagetable already exists then it is reused for the attachment. Otherwise a
- new pagetable object and iommu_domain is created. Successful completion of
- this operation sets up the linkages among IOAS, device and iommu_domain. Once
- this completes the device could do DMA.
-
- Every iommu_domain inside the IOAS is also represented to userspace as a
- HW_PAGETABLE object.
+3. IOMMUFD_OBJ_HWPT_PAGING can be created in two ways:
+
+ * IOMMUFD_OBJ_HWPT_PAGING is automatically created when an external driver
+ calls the IOMMUFD kAPI to attach a bound device to an IOAS. Similarly the
+ external driver uAPI allows userspace to initiate the attaching operation.
+ If a compatible member HWPT_PAGING object exists in the IOAS's HWPT_PAGING
+ list, then it will be reused. Otherwise a new HWPT_PAGING that represents
+ an iommu_domain to userspace will be created, and then added to the list.
+ Successful completion of this operation sets up the linkages among IOAS,
+ device and iommu_domain. Once this completes the device could do DMA.
+
+ * IOMMUFD_OBJ_HWPT_PAGING can be manually created via the IOMMU_HWPT_ALLOC
+ uAPI, provided an ioas_id via @pt_id to associate the new HWPT_PAGING to
+ the corresponding IOAS object. The benefit of this manual allocation is to
+ allow allocation flags (defined in enum iommufd_hwpt_alloc_flags), e.g. it
+ allocates a nesting parent HWPT_PAGING if the IOMMU_HWPT_ALLOC_NEST_PARENT
+ flag is set.
+
+4. IOMMUFD_OBJ_HWPT_NESTED can be only manually created via the IOMMU_HWPT_ALLOC
+ uAPI, provided an hwpt_id or a viommu_id of a vIOMMU object encapsulating a
+ nesting parent HWPT_PAGING via @pt_id to associate the new HWPT_NESTED object
+ to the corresponding HWPT_PAGING object. The associating HWPT_PAGING object
+ must be a nesting parent manually allocated via the same uAPI previously with
+ an IOMMU_HWPT_ALLOC_NEST_PARENT flag, otherwise the allocation will fail. The
+ allocation will be further validated by the IOMMU driver to ensure that the
+ nesting parent domain and the nested domain being allocated are compatible.
+ Successful completion of this operation sets up linkages among IOAS, device,
+ and iommu_domains. Once this completes the device could do DMA via a 2-stage
+ translation, a.k.a nested translation. Note that multiple HWPT_NESTED objects
+ can be allocated by (and then associated to) the same nesting parent.
.. note::
- Future IOMMUFD updates will provide an API to create and manipulate the
- HW_PAGETABLE directly.
+ Either a manual IOMMUFD_OBJ_HWPT_PAGING or an IOMMUFD_OBJ_HWPT_NESTED is
+ created via the same IOMMU_HWPT_ALLOC uAPI. The difference is at the type
+ of the object passed in via the @pt_id field of struct iommufd_hwpt_alloc.
+
+5. IOMMUFD_OBJ_VIOMMU can be only manually created via the IOMMU_VIOMMU_ALLOC
+ uAPI, provided a dev_id (for the device's physical IOMMU to back the vIOMMU)
+ and an hwpt_id (to associate the vIOMMU to a nesting parent HWPT_PAGING). The
+ iommufd core will link the vIOMMU object to the struct iommu_device that the
+ struct device is behind. And an IOMMU driver can implement a viommu_alloc op
+ to allocate its own vIOMMU data structure embedding the core-level structure
+ iommufd_viommu and some driver-specific data. If necessary, the driver can
+ also configure its HW virtualization feature for that vIOMMU (and thus for
+ the VM). Successful completion of this operation sets up the linkages between
+ the vIOMMU object and the HWPT_PAGING, then this vIOMMU object can be used
+ as a nesting parent object to allocate an HWPT_NESTED object described above.
+
+6. IOMMUFD_OBJ_VDEVICE can be only manually created via the IOMMU_VDEVICE_ALLOC
+ uAPI, provided a viommu_id for an iommufd_viommu object and a dev_id for an
+ iommufd_device object. The vDEVICE object will be the binding between these
+ two parent objects. Another @virt_id will be also set via the uAPI providing
+ the iommufd core an index to store the vDEVICE object to a vDEVICE array per
+ vIOMMU. If necessary, the IOMMU driver may choose to implement a vdevce_alloc
+ op to init its HW for virtualization feature related to a vDEVICE. Successful
+ completion of this operation sets up the linkages between vIOMMU and device.
A device can only bind to an iommufd due to DMA ownership claim and attach to at
most one IOAS object (no support of PASID yet).
@@ -120,7 +249,10 @@ User visible objects are backed by following datastructures:
- iommufd_ioas for IOMMUFD_OBJ_IOAS.
- iommufd_device for IOMMUFD_OBJ_DEVICE.
-- iommufd_hw_pagetable for IOMMUFD_OBJ_HW_PAGETABLE.
+- iommufd_hwpt_paging for IOMMUFD_OBJ_HWPT_PAGING.
+- iommufd_hwpt_nested for IOMMUFD_OBJ_HWPT_NESTED.
+- iommufd_viommu for IOMMUFD_OBJ_VIOMMU.
+- iommufd_vdevice for IOMMUFD_OBJ_VDEVICE.
Several terminologies when looking at these datastructures:
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index c8d3e46badc5..d639c61cb472 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -8,13 +8,13 @@ Landlock: unprivileged access control
=====================================
:Author: Mickaël Salaün
-:Date: September 2024
+:Date: October 2024
-The goal of Landlock is to enable to restrict ambient rights (e.g. global
+The goal of Landlock is to enable restriction of ambient rights (e.g. global
filesystem or network access) for a set of processes. Because Landlock
-is a stackable LSM, it makes possible to create safe security sandboxes as new
-security layers in addition to the existing system-wide access-controls. This
-kind of sandbox is expected to help mitigate the security impact of bugs or
+is a stackable LSM, it makes it possible to create safe security sandboxes as
+new security layers in addition to the existing system-wide access-controls.
+This kind of sandbox is expected to help mitigate the security impact of bugs or
unexpected/malicious behaviors in user space applications. Landlock empowers
any process, including unprivileged ones, to securely restrict themselves.
@@ -86,8 +86,8 @@ to be explicit about the denied-by-default access rights.
LANDLOCK_SCOPE_SIGNAL,
};
-Because we may not know on which kernel version an application will be
-executed, it is safer to follow a best-effort security approach. Indeed, we
+Because we may not know which kernel version an application will be executed
+on, it is safer to follow a best-effort security approach. Indeed, we
should try to protect users as much as possible whatever the kernel they are
using.
@@ -129,7 +129,7 @@ version, and only use the available subset of access rights:
LANDLOCK_SCOPE_SIGNAL);
}
-This enables to create an inclusive ruleset that will contain our rules.
+This enables the creation of an inclusive ruleset that will contain our rules.
.. code-block:: c
@@ -219,42 +219,41 @@ If the ``landlock_restrict_self`` system call succeeds, the current thread is
now restricted and this policy will be enforced on all its subsequently created
children as well. Once a thread is landlocked, there is no way to remove its
security policy; only adding more restrictions is allowed. These threads are
-now in a new Landlock domain, merge of their parent one (if any) with the new
-ruleset.
+now in a new Landlock domain, which is a merger of their parent one (if any)
+with the new ruleset.
Full working code can be found in `samples/landlock/sandboxer.c`_.
Good practices
--------------
-It is recommended setting access rights to file hierarchy leaves as much as
+It is recommended to set access rights to file hierarchy leaves as much as
possible. For instance, it is better to be able to have ``~/doc/`` as a
read-only hierarchy and ``~/tmp/`` as a read-write hierarchy, compared to
``~/`` as a read-only hierarchy and ``~/tmp/`` as a read-write hierarchy.
Following this good practice leads to self-sufficient hierarchies that do not
depend on their location (i.e. parent directories). This is particularly
relevant when we want to allow linking or renaming. Indeed, having consistent
-access rights per directory enables to change the location of such directory
+access rights per directory enables changing the location of such directories
without relying on the destination directory access rights (except those that
are required for this operation, see ``LANDLOCK_ACCESS_FS_REFER``
documentation).
Having self-sufficient hierarchies also helps to tighten the required access
rights to the minimal set of data. This also helps avoid sinkhole directories,
-i.e. directories where data can be linked to but not linked from. However,
+i.e. directories where data can be linked to but not linked from. However,
this depends on data organization, which might not be controlled by developers.
In this case, granting read-write access to ``~/tmp/``, instead of write-only
-access, would potentially allow to move ``~/tmp/`` to a non-readable directory
+access, would potentially allow moving ``~/tmp/`` to a non-readable directory
and still keep the ability to list the content of ``~/tmp/``.
Layers of file path access rights
---------------------------------
Each time a thread enforces a ruleset on itself, it updates its Landlock domain
-with a new layer of policy. Indeed, this complementary policy is stacked with
-the potentially other rulesets already restricting this thread. A sandboxed
-thread can then safely add more constraints to itself with a new enforced
-ruleset.
+with a new layer of policy. This complementary policy is stacked with any
+other rulesets potentially already restricting this thread. A sandboxed thread
+can then safely add more constraints to itself with a new enforced ruleset.
One policy layer grants access to a file path if at least one of its rules
encountered on the path grants the access. A sandboxed thread can only access
@@ -265,7 +264,7 @@ etc.).
Bind mounts and OverlayFS
-------------------------
-Landlock enables to restrict access to file hierarchies, which means that these
+Landlock enables restricting access to file hierarchies, which means that these
access rights can be propagated with bind mounts (cf.
Documentation/filesystems/sharedsubtree.rst) but not with
Documentation/filesystems/overlayfs.rst.
@@ -278,21 +277,21 @@ access to multiple file hierarchies at the same time, whether these hierarchies
are the result of bind mounts or not.
An OverlayFS mount point consists of upper and lower layers. These layers are
-combined in a merge directory, result of the mount point. This merge hierarchy
-may include files from the upper and lower layers, but modifications performed
-on the merge hierarchy only reflects on the upper layer. From a Landlock
-policy point of view, each OverlayFS layers and merge hierarchies are
-standalone and contains their own set of files and directories, which is
-different from bind mounts. A policy restricting an OverlayFS layer will not
-restrict the resulted merged hierarchy, and vice versa. Landlock users should
-then only think about file hierarchies they want to allow access to, regardless
-of the underlying filesystem.
+combined in a merge directory, and that merged directory becomes available at
+the mount point. This merge hierarchy may include files from the upper and
+lower layers, but modifications performed on the merge hierarchy only reflect
+on the upper layer. From a Landlock policy point of view, all OverlayFS layers
+and merge hierarchies are standalone and each contains their own set of files
+and directories, which is different from bind mounts. A policy restricting an
+OverlayFS layer will not restrict the resulted merged hierarchy, and vice versa.
+Landlock users should then only think about file hierarchies they want to allow
+access to, regardless of the underlying filesystem.
Inheritance
-----------
Every new thread resulting from a :manpage:`clone(2)` inherits Landlock domain
-restrictions from its parent. This is similar to the seccomp inheritance (cf.
+restrictions from its parent. This is similar to seccomp inheritance (cf.
Documentation/userspace-api/seccomp_filter.rst) or any other LSM dealing with
task's :manpage:`credentials(7)`. For instance, one process's thread may apply
Landlock rules to itself, but they will not be automatically applied to other
@@ -311,8 +310,8 @@ Ptrace restrictions
A sandboxed process has less privileges than a non-sandboxed process and must
then be subject to additional restrictions when manipulating another process.
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.
+process, a sandboxed process should have a superset of the target process's
+access rights, which means the tracee must be in a sub-domain of the tracer.
IPC scoping
-----------
@@ -322,7 +321,7 @@ interactions between sandboxes. Each Landlock domain can be explicitly scoped
for a set of actions by specifying it on a ruleset. For example, if a
sandboxed process should not be able to :manpage:`connect(2)` to a
non-sandboxed process through abstract :manpage:`unix(7)` sockets, we can
-specify such restriction with ``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET``.
+specify such a restriction with ``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET``.
Moreover, if a sandboxed process should not be able to send a signal to a
non-sandboxed process, we can specify this restriction with
``LANDLOCK_SCOPE_SIGNAL``.
@@ -394,7 +393,7 @@ Backward and forward compatibility
Landlock is designed to be compatible with past and future versions of the
kernel. This is achieved thanks to the system call attributes and the
associated bitflags, particularly the ruleset's ``handled_access_fs``. Making
-handled access right explicit enables the kernel and user space to have a clear
+handled access rights explicit enables the kernel and user space to have a clear
contract with each other. This is required to make sure sandboxing will not
get stricter with a system update, which could break applications.
@@ -563,33 +562,34 @@ 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.
-Network support (ABI < 4)
--------------------------
+TCP bind and connect (ABI < 4)
+------------------------------
Starting with the Landlock ABI version 4, it is now possible to restrict TCP
bind and connect actions to only a set of allowed ports thanks to the new
``LANDLOCK_ACCESS_NET_BIND_TCP`` and ``LANDLOCK_ACCESS_NET_CONNECT_TCP``
access rights.
-IOCTL (ABI < 5)
----------------
+Device IOCTL (ABI < 5)
+----------------------
IOCTL operations could not be denied before the fifth Landlock ABI, so
:manpage:`ioctl(2)` is always allowed when using a kernel that only supports an
earlier ABI.
Starting with the Landlock ABI version 5, it is possible to restrict the use of
-:manpage:`ioctl(2)` using the new ``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right.
+:manpage:`ioctl(2)` on character and block devices using the new
+``LANDLOCK_ACCESS_FS_IOCTL_DEV`` right.
-Abstract UNIX socket scoping (ABI < 6)
---------------------------------------
+Abstract UNIX socket (ABI < 6)
+------------------------------
Starting with the Landlock ABI version 6, it is possible to restrict
connections to an abstract :manpage:`unix(7)` socket by setting
``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET`` to the ``scoped`` ruleset attribute.
-Signal scoping (ABI < 6)
-------------------------
+Signal (ABI < 6)
+----------------
Starting with the Landlock ABI version 6, it is possible to restrict
:manpage:`signal(7)` sending by setting ``LANDLOCK_SCOPE_SIGNAL`` to the
@@ -605,9 +605,9 @@ Build time configuration
Landlock was first introduced in Linux 5.13 but it must be configured at build
time with ``CONFIG_SECURITY_LANDLOCK=y``. Landlock must also be enabled at boot
-time as the other security modules. The list of security modules enabled by
+time like other security modules. The list of security modules enabled by
default is set with ``CONFIG_LSM``. The kernel configuration should then
-contains ``CONFIG_LSM=landlock,[...]`` with ``[...]`` as the list of other
+contain ``CONFIG_LSM=landlock,[...]`` with ``[...]`` as the list of other
potentially useful security modules for the running system (see the
``CONFIG_LSM`` help).
@@ -669,7 +669,7 @@ Questions and answers
What about user space sandbox managers?
---------------------------------------
-Using user space process to enforce restrictions on kernel resources can lead
+Using user space processes to enforce restrictions on kernel resources can lead
to race conditions or inconsistent evaluations (i.e. `Incorrect mirroring of
the OS code and state
<https://www.ndss-symposium.org/ndss2003/traps-and-pitfalls-practical-problems-system-call-interposition-based-security-tools/>`_).
diff --git a/Documentation/userspace-api/media/rc/lirc-set-send-duty-cycle.rst b/Documentation/userspace-api/media/rc/lirc-set-send-duty-cycle.rst
index 2979752acbcd..a94750d00898 100644
--- a/Documentation/userspace-api/media/rc/lirc-set-send-duty-cycle.rst
+++ b/Documentation/userspace-api/media/rc/lirc-set-send-duty-cycle.rst
@@ -27,7 +27,7 @@ Arguments
File descriptor returned by open().
``duty_cycle``
- Duty cicle, describing the pulse width in percent (from 1 to 99) of
+ Duty cycle, describing the pulse width in percent (from 1 to 99) of
the total cycle. Values 0 and 100 are reserved.
Description
diff --git a/Documentation/userspace-api/media/v4l/control.rst b/Documentation/userspace-api/media/v4l/control.rst
index 57893814a1e5..9253cc946f02 100644
--- a/Documentation/userspace-api/media/v4l/control.rst
+++ b/Documentation/userspace-api/media/v4l/control.rst
@@ -290,13 +290,15 @@ Control IDs
This is a read-only control that can be read by the application and
used as a hint to determine the number of CAPTURE buffers to pass to
REQBUFS. The value is the minimum number of CAPTURE buffers that is
- necessary for hardware to work.
+ necessary for hardware to work. This control is required for stateful
+ decoders.
``V4L2_CID_MIN_BUFFERS_FOR_OUTPUT`` ``(integer)``
This is a read-only control that can be read by the application and
used as a hint to determine the number of OUTPUT buffers to pass to
REQBUFS. The value is the minimum number of OUTPUT buffers that is
- necessary for hardware to work.
+ necessary for hardware to work. This control is required for stateful
+ encoders.
.. _v4l2-alpha-component:
diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst
index c6e56b5888bc..86ffb3bc8ade 100644
--- a/Documentation/userspace-api/media/v4l/meta-formats.rst
+++ b/Documentation/userspace-api/media/v4l/meta-formats.rst
@@ -16,6 +16,7 @@ These formats are used for the :ref:`metadata` interface only.
metafmt-generic
metafmt-intel-ipu3
metafmt-pisp-be
+ metafmt-pisp-fe
metafmt-rkisp1
metafmt-uvc
metafmt-vivid
diff --git a/Documentation/userspace-api/media/v4l/metafmt-pisp-fe.rst b/Documentation/userspace-api/media/v4l/metafmt-pisp-fe.rst
new file mode 100644
index 000000000000..fddeada83e4a
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/metafmt-pisp-fe.rst
@@ -0,0 +1,39 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _v4l2-meta-fmt-rpi-fe-cfg:
+
+************************
+V4L2_META_FMT_RPI_FE_CFG
+************************
+
+Raspberry Pi PiSP Front End configuration format
+================================================
+
+The Raspberry Pi PiSP Front End image signal processor is configured by
+userspace by providing a buffer of configuration parameters to the
+`rp1-cfe-fe-config` output video device node using the
+:c:type:`v4l2_meta_format` interface.
+
+The `Raspberry Pi PiSP technical specification
+<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
+provide detailed description of the Front End configuration and programming
+model.
+
+.. _v4l2-meta-fmt-rpi-fe-stats:
+
+**************************
+V4L2_META_FMT_RPI_FE_STATS
+**************************
+
+Raspberry Pi PiSP Front End statistics format
+=============================================
+
+The Raspberry Pi PiSP Front End image signal processor provides statistics data
+by writing to a buffer provided via the `rp1-cfe-fe-stats` capture video device
+node using the
+:c:type:`v4l2_meta_format` interface.
+
+The `Raspberry Pi PiSP technical specification
+<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
+provide detailed description of the Front End configuration and programming
+model.
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-y16i.rst b/Documentation/userspace-api/media/v4l/pixfmt-y16i.rst
new file mode 100644
index 000000000000..74ba9e910a38
--- /dev/null
+++ b/Documentation/userspace-api/media/v4l/pixfmt-y16i.rst
@@ -0,0 +1,73 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+
+.. _V4L2-PIX-FMT-Y16I:
+
+**************************
+V4L2_PIX_FMT_Y16I ('Y16I')
+**************************
+
+Interleaved grey-scale image, e.g. from a stereo-pair
+
+
+Description
+===========
+
+This is a grey-scale image with a depth of 16 bits per pixel, but with pixels
+from 2 sources interleaved and unpacked. Each pixel is stored in a 16-bit word
+in the little-endian order. The first pixel is from the left source.
+
+**Pixel unpacked representation.**
+Left/Right pixels 16-bit unpacked - 16-bit for each interleaved pixel.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - Y'\ :sub:`0L[7:0]`
+ - Y'\ :sub:`0L[15:8]`
+ - Y'\ :sub:`0R[7:0]`
+ - Y'\ :sub:`0R[15:8]`
+
+**Byte Order.**
+Each cell is one byte.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - Y'\ :sub:`00Llow`
+ - Y'\ :sub:`00Lhigh`
+ - Y'\ :sub:`00Rlow`
+ - Y'\ :sub:`00Rhigh`
+ - Y'\ :sub:`01Llow`
+ - Y'\ :sub:`01Lhigh`
+ - Y'\ :sub:`01Rlow`
+ - Y'\ :sub:`01Rhigh`
+ * - start + 8:
+ - Y'\ :sub:`10Llow`
+ - Y'\ :sub:`10Lhigh`
+ - Y'\ :sub:`10Rlow`
+ - Y'\ :sub:`10Rhigh`
+ - Y'\ :sub:`11Llow`
+ - Y'\ :sub:`11Lhigh`
+ - Y'\ :sub:`11Rlow`
+ - Y'\ :sub:`11Rhigh`
+ * - start + 16:
+ - Y'\ :sub:`20Llow`
+ - Y'\ :sub:`20Lhigh`
+ - Y'\ :sub:`20Rlow`
+ - Y'\ :sub:`20Rhigh`
+ - Y'\ :sub:`21Llow`
+ - Y'\ :sub:`21Lhigh`
+ - Y'\ :sub:`21Rlow`
+ - Y'\ :sub:`21Rhigh`
+ * - start + 24:
+ - Y'\ :sub:`30Llow`
+ - Y'\ :sub:`30Lhigh`
+ - Y'\ :sub:`30Rlow`
+ - Y'\ :sub:`30Rhigh`
+ - Y'\ :sub:`31Llow`
+ - Y'\ :sub:`31Lhigh`
+ - Y'\ :sub:`31Rlow`
+ - Y'\ :sub:`31Rhigh`
diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index d2a6cd2e1eb2..2a94371448dc 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -2225,7 +2225,7 @@ The following table list existing packed 48bit wide RGB formats.
\endgroup
On LVDS buses, usually each sample is transferred serialized in seven
-time slots per pixel clock, on three (18-bit) or four (24-bit)
+time slots per pixel clock, on three (18-bit) or four (24-bit) or five (30-bit)
differential data pairs at the same time. The remaining bits are used
for control signals as defined by SPWG/PSWG/VESA or JEIDA standards. The
24-bit RGB format serialized in seven time slots on four lanes using
@@ -2246,11 +2246,12 @@ JEIDA defined bit mapping will be named
- Code
-
-
- - :cspan:`3` Data organization
+ - :cspan:`4` Data organization
* -
-
- Timeslot
- Lane
+ - 4
- 3
- 2
- 1
@@ -2262,6 +2263,7 @@ JEIDA defined bit mapping will be named
- 0
-
-
+ -
- d
- b\ :sub:`1`
- g\ :sub:`0`
@@ -2270,6 +2272,7 @@ JEIDA defined bit mapping will be named
- 1
-
-
+ -
- d
- b\ :sub:`0`
- r\ :sub:`5`
@@ -2278,6 +2281,7 @@ JEIDA defined bit mapping will be named
- 2
-
-
+ -
- d
- g\ :sub:`5`
- r\ :sub:`4`
@@ -2286,6 +2290,7 @@ JEIDA defined bit mapping will be named
- 3
-
-
+ -
- b\ :sub:`5`
- g\ :sub:`4`
- r\ :sub:`3`
@@ -2294,6 +2299,7 @@ JEIDA defined bit mapping will be named
- 4
-
-
+ -
- b\ :sub:`4`
- g\ :sub:`3`
- r\ :sub:`2`
@@ -2302,6 +2308,7 @@ JEIDA defined bit mapping will be named
- 5
-
-
+ -
- b\ :sub:`3`
- g\ :sub:`2`
- r\ :sub:`1`
@@ -2310,6 +2317,7 @@ JEIDA defined bit mapping will be named
- 6
-
-
+ -
- b\ :sub:`2`
- g\ :sub:`1`
- r\ :sub:`0`
@@ -2319,6 +2327,7 @@ JEIDA defined bit mapping will be named
- 0x1011
- 0
-
+ -
- d
- d
- b\ :sub:`1`
@@ -2327,6 +2336,7 @@ JEIDA defined bit mapping will be named
-
- 1
-
+ -
- b\ :sub:`7`
- d
- b\ :sub:`0`
@@ -2335,6 +2345,7 @@ JEIDA defined bit mapping will be named
-
- 2
-
+ -
- b\ :sub:`6`
- d
- g\ :sub:`5`
@@ -2343,6 +2354,7 @@ JEIDA defined bit mapping will be named
-
- 3
-
+ -
- g\ :sub:`7`
- b\ :sub:`5`
- g\ :sub:`4`
@@ -2351,6 +2363,7 @@ JEIDA defined bit mapping will be named
-
- 4
-
+ -
- g\ :sub:`6`
- b\ :sub:`4`
- g\ :sub:`3`
@@ -2359,6 +2372,7 @@ JEIDA defined bit mapping will be named
-
- 5
-
+ -
- r\ :sub:`7`
- b\ :sub:`3`
- g\ :sub:`2`
@@ -2367,6 +2381,7 @@ JEIDA defined bit mapping will be named
-
- 6
-
+ -
- r\ :sub:`6`
- b\ :sub:`2`
- g\ :sub:`1`
@@ -2377,6 +2392,7 @@ JEIDA defined bit mapping will be named
- 0x1012
- 0
-
+ -
- d
- d
- b\ :sub:`3`
@@ -2385,6 +2401,7 @@ JEIDA defined bit mapping will be named
-
- 1
-
+ -
- b\ :sub:`1`
- d
- b\ :sub:`2`
@@ -2393,6 +2410,7 @@ JEIDA defined bit mapping will be named
-
- 2
-
+ -
- b\ :sub:`0`
- d
- g\ :sub:`7`
@@ -2401,6 +2419,7 @@ JEIDA defined bit mapping will be named
-
- 3
-
+ -
- g\ :sub:`1`
- b\ :sub:`7`
- g\ :sub:`6`
@@ -2409,6 +2428,7 @@ JEIDA defined bit mapping will be named
-
- 4
-
+ -
- g\ :sub:`0`
- b\ :sub:`6`
- g\ :sub:`5`
@@ -2417,6 +2437,7 @@ JEIDA defined bit mapping will be named
-
- 5
-
+ -
- r\ :sub:`1`
- b\ :sub:`5`
- g\ :sub:`4`
@@ -2425,10 +2446,141 @@ JEIDA defined bit mapping will be named
-
- 6
-
+ -
+ - r\ :sub:`0`
+ - b\ :sub:`4`
+ - g\ :sub:`3`
+ - r\ :sub:`2`
+ * .. _MEDIA-BUS-FMT-RGB101010-1X7X5-SPWG:
+
+ - MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG
+ - 0x1026
+ - 0
+ -
+ - d
+ - d
+ - d
+ - b\ :sub:`1`
+ - g\ :sub:`0`
+ * -
+ -
+ - 1
+ -
+ - b\ :sub:`9`
+ - b\ :sub:`7`
+ - d
+ - b\ :sub:`0`
+ - r\ :sub:`5`
+ * -
+ -
+ - 2
+ -
+ - b\ :sub:`8`
+ - b\ :sub:`6`
+ - d
+ - g\ :sub:`5`
+ - r\ :sub:`4`
+ * -
+ -
+ - 3
+ -
+ - g\ :sub:`9`
+ - g\ :sub:`7`
+ - b\ :sub:`5`
+ - g\ :sub:`4`
+ - r\ :sub:`3`
+ * -
+ -
+ - 4
+ -
+ - g\ :sub:`8`
+ - g\ :sub:`6`
+ - b\ :sub:`4`
+ - g\ :sub:`3`
+ - r\ :sub:`2`
+ * -
+ -
+ - 5
+ -
+ - r\ :sub:`9`
+ - r\ :sub:`7`
+ - b\ :sub:`3`
+ - g\ :sub:`2`
+ - r\ :sub:`1`
+ * -
+ -
+ - 6
+ -
+ - r\ :sub:`8`
+ - r\ :sub:`6`
+ - b\ :sub:`2`
+ - g\ :sub:`1`
- r\ :sub:`0`
+ * .. _MEDIA-BUS-FMT-RGB101010-1X7X5-JEIDA:
+
+ - MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA
+ - 0x1027
+ - 0
+ -
+ - d
+ - d
+ - d
+ - b\ :sub:`5`
+ - g\ :sub:`4`
+ * -
+ -
+ - 1
+ -
+ - b\ :sub:`1`
+ - b\ :sub:`3`
+ - d
- b\ :sub:`4`
+ - r\ :sub:`9`
+ * -
+ -
+ - 2
+ -
+ - b\ :sub:`0`
+ - b\ :sub:`2`
+ - d
+ - g\ :sub:`9`
+ - r\ :sub:`8`
+ * -
+ -
+ - 3
+ -
+ - g\ :sub:`1`
- g\ :sub:`3`
+ - b\ :sub:`9`
+ - g\ :sub:`8`
+ - r\ :sub:`7`
+ * -
+ -
+ - 4
+ -
+ - g\ :sub:`0`
+ - g\ :sub:`2`
+ - b\ :sub:`8`
+ - g\ :sub:`7`
+ - r\ :sub:`6`
+ * -
+ -
+ - 5
+ -
+ - r\ :sub:`1`
+ - r\ :sub:`3`
+ - b\ :sub:`7`
+ - g\ :sub:`6`
+ - r\ :sub:`5`
+ * -
+ -
+ - 6
+ -
+ - r\ :sub:`0`
- r\ :sub:`2`
+ - b\ :sub:`6`
+ - g\ :sub:`5`
+ - r\ :sub:`4`
.. raw:: latex
diff --git a/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst b/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst
index 3adb3d205531..0f69aa04607f 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst
@@ -85,7 +85,17 @@ the ``mbus_code`` field is handled differently:
* - __u32
- ``index``
- Number of the format in the enumeration, set by the application.
- This is in no way related to the ``pixelformat`` field.
+ This is in no way related to the ``pixelformat`` field.
+ When the index is ORed with ``V4L2_FMTDESC_FLAG_ENUM_ALL`` the
+ driver clears the flag and enumerates all the possible formats,
+ ignoring any limitations from the current configuration. Drivers
+ which do not support this flag always return an ``EINVAL``
+ error code without clearing this flag.
+ Formats enumerated when using ``V4L2_FMTDESC_FLAG_ENUM_ALL`` flag
+ shouldn't be used when calling :c:func:`VIDIOC_ENUM_FRAMESIZES`
+ or :c:func:`VIDIOC_ENUM_FRAMEINTERVALS`.
+ ``V4L2_FMTDESC_FLAG_ENUM_ALL`` should only be used by drivers that
+ can return different format list depending on this flag.
* - __u32
- ``type``
- Type of the data stream, set by the application. Only these types
@@ -234,6 +244,12 @@ the ``mbus_code`` field is handled differently:
valid. The buffer consists of ``height`` lines, each having ``width``
Data Units of data and the offset (in bytes) between the beginning of
each two consecutive lines is ``bytesperline``.
+ * - ``V4L2_FMTDESC_FLAG_ENUM_ALL``
+ - 0x80000000
+ - When the applications ORs ``index`` with ``V4L2_FMTDESC_FLAG_ENUM_ALL`` flag
+ the driver enumerates all the possible pixel formats without taking care
+ of any already set configuration. Drivers which do not support this flag,
+ always return ``EINVAL`` without clearing this flag.
Return Value
============
diff --git a/Documentation/userspace-api/media/v4l/yuv-formats.rst b/Documentation/userspace-api/media/v4l/yuv-formats.rst
index 24b34cdfa6fe..78ee406d7647 100644
--- a/Documentation/userspace-api/media/v4l/yuv-formats.rst
+++ b/Documentation/userspace-api/media/v4l/yuv-formats.rst
@@ -269,5 +269,6 @@ image.
pixfmt-yuv-luma
pixfmt-y8i
pixfmt-y12i
+ pixfmt-y16i
pixfmt-uv8
pixfmt-m420
diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
index d67fd4038d22..429b5cdf05c3 100644
--- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions
+++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
@@ -217,6 +217,7 @@ replace define V4L2_FMT_FLAG_CSC_YCBCR_ENC fmtdesc-flags
replace define V4L2_FMT_FLAG_CSC_HSV_ENC fmtdesc-flags
replace define V4L2_FMT_FLAG_CSC_QUANTIZATION fmtdesc-flags
replace define V4L2_FMT_FLAG_META_LINE_BASED fmtdesc-flags
+replace define V4L2_FMTDESC_FLAG_ENUM_ALL fmtdesc-flags
# V4L2 timecode types
replace define V4L2_TC_TYPE_24FPS timecode-type
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index edc070c6e19b..454c2aaa155e 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -7,8 +7,19 @@ The Definitive KVM (Kernel-based Virtual Machine) API Documentation
1. General description
======================
-The kvm API is a set of ioctls that are issued to control various aspects
-of a virtual machine. The ioctls belong to the following classes:
+The kvm API is centered around different kinds of file descriptors
+and ioctls that can be issued to these file descriptors. An initial
+open("/dev/kvm") obtains a handle to the kvm subsystem; this handle
+can be used to issue system ioctls. A KVM_CREATE_VM ioctl on this
+handle will create a VM file descriptor which can be used to issue VM
+ioctls. A KVM_CREATE_VCPU or KVM_CREATE_DEVICE ioctl on a VM fd will
+create a virtual cpu or device and return a file descriptor pointing to
+the new resource.
+
+In other words, the kvm API is a set of ioctls that are issued to
+different kinds of file descriptor in order to control various aspects of
+a virtual machine. Depending on the file descriptor that accepts them,
+ioctls belong to the following classes:
- System ioctls: These query and set global attributes which affect the
whole kvm subsystem. In addition a system ioctl is used to create
@@ -35,18 +46,19 @@ of a virtual machine. The ioctls belong to the following classes:
device ioctls must be issued from the same process (address space) that
was used to create the VM.
-2. File descriptors
-===================
+While most ioctls are specific to one kind of file descriptor, in some
+cases the same ioctl can belong to more than one class.
+
+The KVM API grew over time. For this reason, KVM defines many constants
+of the form ``KVM_CAP_*``, each corresponding to a set of functionality
+provided by one or more ioctls. Availability of these "capabilities" can
+be checked with :ref:`KVM_CHECK_EXTENSION <KVM_CHECK_EXTENSION>`. Some
+capabilities also need to be enabled for VMs or VCPUs where their
+functionality is desired (see :ref:`cap_enable` and :ref:`cap_enable_vm`).
-The kvm API is centered around file descriptors. An initial
-open("/dev/kvm") obtains a handle to the kvm subsystem; this handle
-can be used to issue system ioctls. A KVM_CREATE_VM ioctl on this
-handle will create a VM file descriptor which can be used to issue VM
-ioctls. A KVM_CREATE_VCPU or KVM_CREATE_DEVICE ioctl on a VM fd will
-create a virtual cpu or device and return a file descriptor pointing to
-the new resource. Finally, ioctls on a vcpu or device fd can be used
-to control the vcpu or device. For vcpus, this includes the important
-task of actually running guest code.
+
+2. Restrictions
+===============
In general file descriptors can be migrated among processes by means
of fork() and the SCM_RIGHTS facility of unix domain socket. These
@@ -96,12 +108,9 @@ description:
Capability:
which KVM extension provides this ioctl. Can be 'basic',
which means that is will be provided by any kernel that supports
- API version 12 (see section 4.1), a KVM_CAP_xyz constant, which
- means availability needs to be checked with KVM_CHECK_EXTENSION
- (see section 4.4), or 'none' which means that while not all kernels
- support this ioctl, there's no capability bit to check its
- availability: for kernels that don't support the ioctl,
- the ioctl returns -ENOTTY.
+ API version 12 (see :ref:`KVM_GET_API_VERSION <KVM_GET_API_VERSION>`),
+ or a KVM_CAP_xyz constant that can be checked with
+ :ref:`KVM_CHECK_EXTENSION <KVM_CHECK_EXTENSION>`.
Architectures:
which instruction set architectures provide this ioctl.
@@ -118,6 +127,8 @@ description:
are not detailed, but errors with specific meanings are.
+.. _KVM_GET_API_VERSION:
+
4.1 KVM_GET_API_VERSION
-----------------------
@@ -246,6 +257,8 @@ This list also varies by kvm version and host processor, but does not change
otherwise.
+.. _KVM_CHECK_EXTENSION:
+
4.4 KVM_CHECK_EXTENSION
-----------------------
@@ -288,7 +301,7 @@ the VCPU file descriptor can be mmap-ed, including:
- if KVM_CAP_DIRTY_LOG_RING is available, a number of pages at
KVM_DIRTY_LOG_PAGE_OFFSET * PAGE_SIZE. For more information on
- KVM_CAP_DIRTY_LOG_RING, see section 8.3.
+ KVM_CAP_DIRTY_LOG_RING, see :ref:`KVM_CAP_DIRTY_LOG_RING`.
4.7 KVM_CREATE_VCPU
@@ -338,8 +351,8 @@ KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
cpu's hardware control block.
-4.8 KVM_GET_DIRTY_LOG (vm ioctl)
---------------------------------
+4.8 KVM_GET_DIRTY_LOG
+---------------------
:Capability: basic
:Architectures: all
@@ -1298,7 +1311,7 @@ See KVM_GET_VCPU_EVENTS for the data structure.
:Capability: KVM_CAP_DEBUGREGS
:Architectures: x86
-:Type: vm ioctl
+:Type: vcpu ioctl
:Parameters: struct kvm_debugregs (out)
:Returns: 0 on success, -1 on error
@@ -1320,7 +1333,7 @@ Reads debug registers from the vcpu.
:Capability: KVM_CAP_DEBUGREGS
:Architectures: x86
-:Type: vm ioctl
+:Type: vcpu ioctl
:Parameters: struct kvm_debugregs (in)
:Returns: 0 on success, -1 on error
@@ -1429,6 +1442,8 @@ because of a quirk in the virtualization implementation (see the internals
documentation when it pops into existence).
+.. _KVM_ENABLE_CAP:
+
4.37 KVM_ENABLE_CAP
-------------------
@@ -2116,8 +2131,8 @@ TLB, prior to calling KVM_RUN on the associated vcpu.
The "bitmap" field is the userspace address of an array. This array
consists of a number of bits, equal to the total number of TLB entries as
-determined by the last successful call to KVM_CONFIG_TLB, rounded up to the
-nearest multiple of 64.
+determined by the last successful call to ``KVM_ENABLE_CAP(KVM_CAP_SW_TLB)``,
+rounded up to the nearest multiple of 64.
Each bit corresponds to one TLB entry, ordered the same as in the shared TLB
array.
@@ -2170,42 +2185,6 @@ userspace update the TCE table directly which is useful in some
circumstances.
-4.63 KVM_ALLOCATE_RMA
----------------------
-
-:Capability: KVM_CAP_PPC_RMA
-:Architectures: powerpc
-:Type: vm ioctl
-:Parameters: struct kvm_allocate_rma (out)
-:Returns: file descriptor for mapping the allocated RMA
-
-This allocates a Real Mode Area (RMA) from the pool allocated at boot
-time by the kernel. An RMA is a physically-contiguous, aligned region
-of memory used on older POWER processors to provide the memory which
-will be accessed by real-mode (MMU off) accesses in a KVM guest.
-POWER processors support a set of sizes for the RMA that usually
-includes 64MB, 128MB, 256MB and some larger powers of two.
-
-::
-
- /* for KVM_ALLOCATE_RMA */
- struct kvm_allocate_rma {
- __u64 rma_size;
- };
-
-The return value is a file descriptor which can be passed to mmap(2)
-to map the allocated RMA into userspace. The mapped area can then be
-passed to the KVM_SET_USER_MEMORY_REGION ioctl to establish it as the
-RMA for a virtual machine. The size of the RMA in bytes (which is
-fixed at host kernel boot time) is returned in the rma_size field of
-the argument structure.
-
-The KVM_CAP_PPC_RMA capability is 1 or 2 if the KVM_ALLOCATE_RMA ioctl
-is supported; 2 if the processor requires all virtual machines to have
-an RMA, or 1 if the processor can use an RMA but doesn't require it,
-because it supports the Virtual RMA (VRMA) facility.
-
-
4.64 KVM_NMI
------------
@@ -2602,7 +2581,7 @@ Specifically:
======================= ========= ===== =======================================
.. [1] These encodings are not accepted for SVE-enabled vcpus. See
- KVM_ARM_VCPU_INIT.
+ :ref:`KVM_ARM_VCPU_INIT`.
The equivalent register content can be accessed via bits [127:0] of
the corresponding SVE Zn registers instead for vcpus that have SVE
@@ -3593,6 +3572,27 @@ Errors:
This ioctl returns the guest registers that are supported for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
+Note that s390 does not support KVM_GET_REG_LIST for historical reasons
+(read: nobody cared). The set of registers in kernels 4.x and newer is:
+
+- KVM_REG_S390_TODPR
+
+- KVM_REG_S390_EPOCHDIFF
+
+- KVM_REG_S390_CPU_TIMER
+
+- KVM_REG_S390_CLOCK_COMP
+
+- KVM_REG_S390_PFTOKEN
+
+- KVM_REG_S390_PFCOMPARE
+
+- KVM_REG_S390_PFSELECT
+
+- KVM_REG_S390_PP
+
+- KVM_REG_S390_GBEA
+
4.85 KVM_ARM_SET_DEVICE_ADDR (deprecated)
-----------------------------------------
@@ -4956,8 +4956,8 @@ Coalesced pio is based on coalesced mmio. There is little difference
between coalesced mmio and pio except that coalesced pio records accesses
to I/O ports.
-4.117 KVM_CLEAR_DIRTY_LOG (vm ioctl)
-------------------------------------
+4.117 KVM_CLEAR_DIRTY_LOG
+-------------------------
:Capability: KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
:Architectures: x86, arm64, mips
@@ -5093,8 +5093,8 @@ Recognised values for feature:
Finalizes the configuration of the specified vcpu feature.
The vcpu must already have been initialised, enabling the affected feature, by
-means of a successful KVM_ARM_VCPU_INIT call with the appropriate flag set in
-features[].
+means of a successful :ref:`KVM_ARM_VCPU_INIT <KVM_ARM_VCPU_INIT>` call with the
+appropriate flag set in features[].
For affected vcpu features, this is a mandatory step that must be performed
before the vcpu is fully usable.
@@ -5266,7 +5266,7 @@ the cpu reset definition in the POP (Principles Of Operation).
4.123 KVM_S390_INITIAL_RESET
----------------------------
-:Capability: none
+:Capability: basic
:Architectures: s390
:Type: vcpu ioctl
:Parameters: none
@@ -6205,7 +6205,7 @@ applied.
.. _KVM_ARM_GET_REG_WRITABLE_MASKS:
4.139 KVM_ARM_GET_REG_WRITABLE_MASKS
--------------------------------------------
+------------------------------------
:Capability: KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES
:Architectures: arm64
@@ -6443,6 +6443,8 @@ the capability to be present.
`flags` must currently be zero.
+.. _kvm_run:
+
5. The kvm_run structure
========================
@@ -6855,6 +6857,10 @@ the first `ndata` items (possibly zero) of the data array are valid.
the guest issued a SYSTEM_RESET2 call according to v1.1 of the PSCI
specification.
+ - for arm64, data[0] is set to KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2
+ if the guest issued a SYSTEM_OFF2 call according to v1.3 of the PSCI
+ specification.
+
- for RISC-V, data[0] is set to the value of the second argument of the
``sbi_system_reset`` call.
@@ -6888,6 +6894,12 @@ either:
- Deny the guest request to suspend the VM. See ARM DEN0022D.b 5.19.2
"Caller responsibilities" for possible return values.
+Hibernation using the PSCI SYSTEM_OFF2 call is enabled when PSCI v1.3
+is enabled. If a guest invokes the PSCI SYSTEM_OFF2 function, KVM will
+exit to userspace with the KVM_SYSTEM_EVENT_SHUTDOWN event type and with
+data[0] set to KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2. The only
+supported hibernate type for the SYSTEM_OFF2 function is HIBERNATE_OFF.
+
::
/* KVM_EXIT_IOAPIC_EOI */
@@ -7162,11 +7174,15 @@ primary storage for certain register types. Therefore, the kernel may use the
values in kvm_run even if the corresponding bit in kvm_dirty_regs is not set.
+.. _cap_enable:
+
6. Capabilities that can be enabled on vCPUs
============================================
There are certain capabilities that change the behavior of the virtual CPU or
-the virtual machine when enabled. To enable them, please see section 4.37.
+the virtual machine when enabled. To enable them, please see
+:ref:`KVM_ENABLE_CAP`.
+
Below you can find a list of capabilities and what their effect on the vCPU or
the virtual machine is when enabling them.
@@ -7375,7 +7391,7 @@ KVM API and also from the guest.
sets are supported
(bitfields defined in arch/x86/include/uapi/asm/kvm.h).
-As described above in the kvm_sync_regs struct info in section 5 (kvm_run):
+As described above in the kvm_sync_regs struct info in section :ref:`kvm_run`,
KVM_CAP_SYNC_REGS "allow[s] userspace to access certain guest registers
without having to call SET/GET_*REGS". This reduces overhead by eliminating
repeated ioctl calls for setting and/or getting register values. This is
@@ -7421,13 +7437,15 @@ Unused bitfields in the bitarrays must be set to zero.
This capability connects the vcpu to an in-kernel XIVE device.
+.. _cap_enable_vm:
+
7. Capabilities that can be enabled on VMs
==========================================
There are certain capabilities that change the behavior of the virtual
-machine when enabled. To enable them, please see section 4.37. Below
-you can find a list of capabilities and what their effect on the VM
-is when enabling them.
+machine when enabled. To enable them, please see section
+:ref:`KVM_ENABLE_CAP`. Below you can find a list of capabilities and
+what their effect on the VM is when enabling them.
The following information is provided along with the description:
@@ -8107,6 +8125,28 @@ KVM_X86_QUIRK_SLOT_ZAP_ALL By default, for KVM_X86_DEFAULT_VM VMs, KVM
or moved memslot isn't reachable, i.e KVM
_may_ invalidate only SPTEs related to the
memslot.
+
+KVM_X86_QUIRK_STUFF_FEATURE_MSRS By default, at vCPU creation, KVM sets the
+ vCPU's MSR_IA32_PERF_CAPABILITIES (0x345),
+ MSR_IA32_ARCH_CAPABILITIES (0x10a),
+ MSR_PLATFORM_INFO (0xce), and all VMX MSRs
+ (0x480..0x492) to the maximal capabilities
+ supported by KVM. KVM also sets
+ MSR_IA32_UCODE_REV (0x8b) to an arbitrary
+ value (which is different for Intel vs.
+ AMD). Lastly, when guest CPUID is set (by
+ userspace), KVM modifies select VMX MSR
+ fields to force consistency between guest
+ CPUID and L2's effective ISA. When this
+ quirk is disabled, KVM zeroes the vCPU's MSR
+ values (with two exceptions, see below),
+ i.e. treats the feature MSRs like CPUID
+ leaves and gives userspace full control of
+ the vCPU model definition. This quirk does
+ not affect VMX MSRs CR0/CR4_FIXED1 (0x487
+ and 0x489), as KVM does now allow them to
+ be set by userspace (KVM sets them based on
+ guest CPUID, for safety purposes).
=================================== ============================================
7.32 KVM_CAP_MAX_VCPU_ID
@@ -8588,6 +8628,8 @@ guest according to the bits in the KVM_CPUID_FEATURES CPUID leaf
(0x40000001). Otherwise, a guest may use the paravirtual features
regardless of what has actually been exposed through the CPUID leaf.
+.. _KVM_CAP_DIRTY_LOG_RING:
+
8.29 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL
----------------------------------------------------------
diff --git a/Documentation/virt/kvm/locking.rst b/Documentation/virt/kvm/locking.rst
index 1bedd56e2fe3..c56d5f26c750 100644
--- a/Documentation/virt/kvm/locking.rst
+++ b/Documentation/virt/kvm/locking.rst
@@ -135,8 +135,8 @@ We dirty-log for gfn1, that means gfn2 is lost in dirty-bitmap.
For direct sp, we can easily avoid it since the spte of direct sp is fixed
to gfn. For indirect sp, we disabled fast page fault for simplicity.
-A solution for indirect sp could be to pin the gfn, for example via
-gfn_to_pfn_memslot_atomic, before the cmpxchg. After the pinning:
+A solution for indirect sp could be to pin the gfn before the cmpxchg. After
+the pinning:
- We have held the refcount of pfn; that means the pfn can not be freed and
be reused for another gfn.
@@ -147,49 +147,51 @@ Then, we can ensure the dirty bitmaps is correctly set for a gfn.
2) Dirty bit tracking
-In the origin code, the spte can be fast updated (non-atomically) if the
+In the original code, the spte can be fast updated (non-atomically) if the
spte is read-only and the Accessed bit has already been set since the
Accessed bit and Dirty bit can not be lost.
But it is not true after fast page fault since the spte can be marked
writable between reading spte and updating spte. Like below case:
-+------------------------------------------------------------------------+
-| At the beginning:: |
-| |
-| spte.W = 0 |
-| spte.Accessed = 1 |
-+------------------------------------+-----------------------------------+
-| CPU 0: | CPU 1: |
-+------------------------------------+-----------------------------------+
-| In mmu_spte_clear_track_bits():: | |
-| | |
-| old_spte = *spte; | |
-| | |
-| | |
-| /* 'if' condition is satisfied. */| |
-| if (old_spte.Accessed == 1 && | |
-| old_spte.W == 0) | |
-| spte = 0ull; | |
-+------------------------------------+-----------------------------------+
-| | on fast page fault path:: |
-| | |
-| | spte.W = 1 |
-| | |
-| | memory write on the spte:: |
-| | |
-| | spte.Dirty = 1 |
-+------------------------------------+-----------------------------------+
-| :: | |
-| | |
-| else | |
-| old_spte = xchg(spte, 0ull) | |
-| if (old_spte.Accessed == 1) | |
-| kvm_set_pfn_accessed(spte.pfn);| |
-| if (old_spte.Dirty == 1) | |
-| kvm_set_pfn_dirty(spte.pfn); | |
-| OOPS!!! | |
-+------------------------------------+-----------------------------------+
++-------------------------------------------------------------------------+
+| At the beginning:: |
+| |
+| spte.W = 0 |
+| spte.Accessed = 1 |
++-------------------------------------+-----------------------------------+
+| CPU 0: | CPU 1: |
++-------------------------------------+-----------------------------------+
+| In mmu_spte_update():: | |
+| | |
+| old_spte = *spte; | |
+| | |
+| | |
+| /* 'if' condition is satisfied. */ | |
+| if (old_spte.Accessed == 1 && | |
+| old_spte.W == 0) | |
+| spte = new_spte; | |
++-------------------------------------+-----------------------------------+
+| | on fast page fault path:: |
+| | |
+| | spte.W = 1 |
+| | |
+| | memory write on the spte:: |
+| | |
+| | spte.Dirty = 1 |
++-------------------------------------+-----------------------------------+
+| :: | |
+| | |
+| else | |
+| old_spte = xchg(spte, new_spte);| |
+| if (old_spte.Accessed && | |
+| !new_spte.Accessed) | |
+| flush = true; | |
+| if (old_spte.Dirty && | |
+| !new_spte.Dirty) | |
+| flush = true; | |
+| OOPS!!! | |
++-------------------------------------+-----------------------------------+
The Dirty bit is lost in this case.
diff --git a/Documentation/virt/kvm/s390/s390-diag.rst b/Documentation/virt/kvm/s390/s390-diag.rst
index ca85f030eb0b..3e4f9e3bef81 100644
--- a/Documentation/virt/kvm/s390/s390-diag.rst
+++ b/Documentation/virt/kvm/s390/s390-diag.rst
@@ -35,20 +35,24 @@ DIAGNOSE function codes not specific to KVM, please refer to the
documentation for the s390 hypervisors defining them.
-DIAGNOSE function code 'X'500' - KVM virtio functions
------------------------------------------------------
+DIAGNOSE function code 'X'500' - KVM functions
+----------------------------------------------
-If the function code specifies 0x500, various virtio-related functions
-are performed.
+If the function code specifies 0x500, various KVM-specific functions
+are performed, including virtio functions.
-General register 1 contains the virtio subfunction code. Supported
-virtio subfunctions depend on KVM's userspace. Generally, userspace
-provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3).
+General register 1 contains the subfunction code. Supported subfunctions
+depend on KVM's userspace. Regarding virtio subfunctions, generally
+userspace provides either s390-virtio (subcodes 0-2) or virtio-ccw
+(subcode 3).
Upon completion of the DIAGNOSE instruction, general register 2 contains
the function's return code, which is either a return code or a subcode
specific value.
+If the specified subfunction is not supported, a SPECIFICATION exception
+will be triggered.
+
Subcode 0 - s390-virtio notification and early console printk
Handled by userspace.
@@ -76,6 +80,23 @@ Subcode 3 - virtio-ccw notification
See also the virtio standard for a discussion of this hypercall.
+Subcode 4 - storage-limit
+ Handled by userspace.
+
+ After completion of the DIAGNOSE call, general register 2 will
+ contain the storage limit: the maximum physical address that might be
+ used for storage throughout the lifetime of the VM.
+
+ The storage limit does not indicate currently usable storage, it may
+ include holes, standby storage and areas reserved for other means, such
+ as memory hotplug or virtio-mem devices. Other interfaces for detecting
+ actually usable storage, such as SCLP, must be used in conjunction with
+ this subfunction.
+
+ Note that the storage limit can be larger, but never smaller than the
+ maximum storage address indicated by SCLP via the "maximum storage
+ increment" and the "increment size".
+
DIAGNOSE function code 'X'501 - KVM breakpoint
----------------------------------------------
diff --git a/Documentation/virt/kvm/x86/errata.rst b/Documentation/virt/kvm/x86/errata.rst
index 4116045a8744..37c79362a48f 100644
--- a/Documentation/virt/kvm/x86/errata.rst
+++ b/Documentation/virt/kvm/x86/errata.rst
@@ -33,6 +33,18 @@ Note however that any software (e.g ``WIN87EM.DLL``) expecting these features
to be present likely predates these CPUID feature bits, and therefore
doesn't know to check for them anyway.
+``KVM_SET_VCPU_EVENTS`` issue
+-----------------------------
+
+Invalid KVM_SET_VCPU_EVENTS input with respect to error codes *may* result in
+failed VM-Entry on Intel CPUs. Pre-CET Intel CPUs require that exception
+injection through the VMCS correctly set the "error code valid" flag, e.g.
+require the flag be set when injecting a #GP, clear when injecting a #UD,
+clear when injecting a soft exception, etc. Intel CPUs that enumerate
+IA32_VMX_BASIC[56] as '1' relax VMX's consistency checks, and AMD CPUs have no
+restrictions whatsoever. KVM_SET_VCPU_EVENTS doesn't sanity check the vector
+versus "has_error_code", i.e. KVM's ABI follows AMD behavior.
+
Nested virtualization features
------------------------------
diff --git a/Documentation/wmi/devices/alienware-wmi.rst b/Documentation/wmi/devices/alienware-wmi.rst
new file mode 100644
index 000000000000..ddc5e561960e
--- /dev/null
+++ b/Documentation/wmi/devices/alienware-wmi.rst
@@ -0,0 +1,397 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+==============================================
+Dell AWCC WMI interface driver (alienware-wmi)
+==============================================
+
+Introduction
+============
+
+The WMI device WMAX has been implemented for many Alienware and Dell's G-Series
+models. Throughout these models, two implementations have been identified. The
+first one, used by older systems, deals with HDMI, brightness, RGB, amplifier
+and deep sleep control. The second one used by newer systems deals primarily
+with thermal, overclocking, and GPIO control.
+
+It is suspected that the latter is used by Alienware Command Center (AWCC) to
+manage manufacturer predefined thermal profiles. The alienware-wmi driver
+exposes Thermal_Information and Thermal_Control methods through the Platform
+Profile API to mimic AWCC's behavior.
+
+This newer interface, named AWCCMethodFunction has been reverse engineered, as
+Dell has not provided any official documentation. We will try to describe to the
+best of our ability its discovered inner workings.
+
+.. note::
+ The following method description may be incomplete and some operations have
+ different implementations between devices.
+
+WMI interface description
+-------------------------
+
+The WMI interface description can be decoded from the embedded binary MOF (bmof)
+data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility:
+
+::
+
+ [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{A70591CE-A997-11DA-B012-B622A1EF5492}")]
+ class AWCCWmiMethodFunction {
+ [key, read] string InstanceName;
+ [read] boolean Active;
+
+ [WmiMethodId(13), Implemented, read, write, Description("Return Overclocking Report.")] void Return_OverclockingReport([out] uint32 argr);
+ [WmiMethodId(14), Implemented, read, write, Description("Set OCUIBIOS Control.")] void Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(15), Implemented, read, write, Description("Clear OC FailSafe Flag.")] void Clear_OCFailSafeFlag([out] uint32 argr);
+ [WmiMethodId(19), Implemented, read, write, Description("Get Fan Sensors.")] void GetFanSensors([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(20), Implemented, read, write, Description("Thermal Information.")] void Thermal_Information([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(21), Implemented, read, write, Description("Thermal Control.")] void Thermal_Control([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(23), Implemented, read, write, Description("MemoryOCControl.")] void MemoryOCControl([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(26), Implemented, read, write, Description("System Information.")] void SystemInformation([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(28), Implemented, read, write, Description("Power Information.")] void PowerInformation([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(32), Implemented, read, write, Description("FW Update GPIO toggle.")] void FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(33), Implemented, read, write, Description("Read Total of GPIOs.")] void ReadTotalofGPIOs([out] uint32 argr);
+ [WmiMethodId(34), Implemented, read, write, Description("Read GPIO pin Status.")] void ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(35), Implemented, read, write, Description("Read Chassis Color.")] void ReadChassisColor([out] uint32 argr);
+ [WmiMethodId(36), Implemented, read, write, Description("Read Platform Properties.")] void ReadPlatformProperties([out] uint32 argr);
+ [WmiMethodId(37), Implemented, read, write, Description("Game Shift Status.")] void GameShiftStatus([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(128), Implemented, read, write, Description("Caldera SW installation.")] void CalderaSWInstallation([out] uint32 argr);
+ [WmiMethodId(129), Implemented, read, write, Description("Caldera SW is released.")] void CalderaSWReleased([out] uint32 argr);
+ [WmiMethodId(130), Implemented, read, write, Description("Caldera Connection Status.")] void CalderaConnectionStatus([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(131), Implemented, read, write, Description("Surprise Unplugged Flag Status.")] void SurpriseUnpluggedFlagStatus([out] uint32 argr);
+ [WmiMethodId(132), Implemented, read, write, Description("Clear Surprise Unplugged Flag.")] void ClearSurpriseUnpluggedFlag([out] uint32 argr);
+ [WmiMethodId(133), Implemented, read, write, Description("Cancel Undock Request.")] void CancelUndockRequest([out] uint32 argr);
+ [WmiMethodId(135), Implemented, read, write, Description("Devices in Caldera.")] void DevicesInCaldera([in] uint32 arg2, [out] uint32 argr);
+ [WmiMethodId(136), Implemented, read, write, Description("Notify BIOS for SW ready to disconnect Caldera.")] void NotifyBIOSForSWReadyToDisconnectCaldera([out] uint32 argr);
+ [WmiMethodId(160), Implemented, read, write, Description("Tobii SW installation.")] void TobiiSWinstallation([out] uint32 argr);
+ [WmiMethodId(161), Implemented, read, write, Description("Tobii SW Released.")] void TobiiSWReleased([out] uint32 argr);
+ [WmiMethodId(162), Implemented, read, write, Description("Tobii Camera Power Reset.")] void TobiiCameraPowerReset([out] uint32 argr);
+ [WmiMethodId(163), Implemented, read, write, Description("Tobii Camera Power On.")] void TobiiCameraPowerOn([out] uint32 argr);
+ [WmiMethodId(164), Implemented, read, write, Description("Tobii Camera Power Off.")] void TobiiCameraPowerOff([out] uint32 argr);
+ };
+
+Some of these methods get quite intricate so we will describe them using
+pseudo-code that vaguely resembles the original ASL code.
+
+Methods not described in the following document have unknown behavior.
+
+Argument Structure
+------------------
+
+All input arguments have type **uint32** and their structure is very similar
+between methods. Usually, the first byte corresponds to a specific *operation*
+the method performs, and the subsequent bytes correspond to *arguments* passed
+to this *operation*. For example, if an operation has code 0x01 and requires an
+ID 0xA0, the argument you would pass to the method is 0xA001.
+
+
+Thermal Methods
+===============
+
+WMI method Thermal_Information([in] uint32 arg2, [out] uint32 argr)
+-------------------------------------------------------------------
+
+::
+
+ if BYTE_0(arg2) == 0x01:
+ argr = 1
+
+ if BYTE_0(arg2) == 0x02:
+ argr = SYSTEM_DESCRIPTION
+
+ if BYTE_0(arg2) == 0x03:
+ if BYTE_1(arg2) == 0x00:
+ argr = FAN_ID_0
+
+ if BYTE_1(arg2) == 0x01:
+ argr = FAN_ID_1
+
+ if BYTE_1(arg2) == 0x02:
+ argr = FAN_ID_2
+
+ if BYTE_1(arg2) == 0x03:
+ argr = FAN_ID_3
+
+ if BYTE_1(arg2) == 0x04:
+ argr = SENSOR_ID_CPU | 0x0100
+
+ if BYTE_1(arg2) == 0x05:
+ argr = SENSOR_ID_GPU | 0x0100
+
+ if BYTE_1(arg2) == 0x06:
+ argr = THERMAL_MODE_QUIET_ID
+
+ if BYTE_1(arg2) == 0x07:
+ argr = THERMAL_MODE_BALANCED_ID
+
+ if BYTE_1(arg2) == 0x08:
+ argr = THERMAL_MODE_BALANCED_PERFORMANCE_ID
+
+ if BYTE_1(arg2) == 0x09:
+ argr = THERMAL_MODE_PERFORMANCE_ID
+
+ if BYTE_1(arg2) == 0x0A:
+ argr = THERMAL_MODE_LOW_POWER_ID
+
+ if BYTE_1(arg2) == 0x0B:
+ argr = THERMAL_MODE_GMODE_ID
+
+ else:
+ argr = 0xFFFFFFFF
+
+ if BYTE_0(arg2) == 0x04:
+ if is_valid_sensor(BYTE_1(arg2)):
+ argr = SENSOR_TEMP_C
+ else:
+ argr = 0xFFFFFFFF
+
+ if BYTE_0(arg2) == 0x05:
+ if is_valid_fan(BYTE_1(arg2)):
+ argr = FAN_RPM()
+
+ if BYTE_0(arg2) == 0x06:
+ skip
+
+ if BYTE_0(arg2) == 0x07:
+ argr = 0
+
+ If BYTE_0(arg2) == 0x08:
+ if is_valid_fan(BYTE_1(arg2)):
+ argr = 0
+ else:
+ argr = 0xFFFFFFFF
+
+ if BYTE_0(arg2) == 0x09:
+ if is_valid_fan(BYTE_1(arg2)):
+ argr = FAN_UNKNOWN_STAT_0()
+
+ else:
+ argr = 0xFFFFFFFF
+
+ if BYTE_0(arg2) == 0x0A:
+ argr = THERMAL_MODE_BALANCED_ID
+
+ if BYTE_0(arg2) == 0x0B:
+ argr = CURRENT_THERMAL_MODE()
+
+ if BYTE_0(arg2) == 0x0C:
+ if is_valid_fan(BYTE_1(arg2)):
+ argr = FAN_UNKNOWN_STAT_1()
+ else:
+ argr = 0xFFFFFFFF
+
+Operation 0x02 returns a *system description* buffer with the following
+structure:
+
+::
+
+ out[0] -> Number of fans
+ out[1] -> Number of sensors
+ out[2] -> 0x00
+ out[3] -> Number of thermal modes
+
+Operation 0x03 list all available fan IDs, sensor IDs and thermal profile
+codes in order, but different models may have different number of fans and
+thermal profiles. These are the known ranges:
+
+* Fan IDs: from 2 up to 4
+* Sensor IDs: 2
+* Thermal profile codes: from 1 up to 7
+
+In total BYTE_1(ARG2) may range from 0x5 up to 0xD depending on the model.
+
+WMI method Thermal_Control([in] uint32 arg2, [out] uint32 argr)
+---------------------------------------------------------------
+
+::
+
+ if BYTE_0(arg2) == 0x01:
+ if is_valid_thermal_profile(BYTE_1(arg2)):
+ SET_THERMAL_PROFILE(BYTE_1(arg2))
+ argr = 0
+
+ if BYTE_0(arg2) == 0x02:
+ if is_valid_fan(BYTE_1(arg2)):
+ SET_FAN_SPEED_MULTIPLIER(BYTE_2(arg2))
+ argr = 0
+ else:
+ argr = 0xFFFFFFFF
+
+.. note::
+ While you can manually change the fan speed multiplier with this method,
+ Dell's BIOS tends to overwrite this changes anyway.
+
+These are the known thermal profile codes:
+
+::
+
+ CUSTOM 0x00
+
+ BALANCED_USTT 0xA0
+ BALANCED_PERFORMANCE_USTT 0xA1
+ COOL_USTT 0xA2
+ QUIET_USTT 0xA3
+ PERFORMANCE_USTT 0xA4
+ LOW_POWER_USTT 0xA5
+
+ QUIET 0x96
+ BALANCED 0x97
+ BALANCED_PERFORMANCE 0x98
+ PERFORMANCE 0x99
+
+ GMODE 0xAB
+
+Usually if a model doesn't support the first four profiles they will support
+the User Selectable Thermal Tables (USTT) profiles and vice-versa.
+
+GMODE replaces PERFORMANCE in G-Series laptops.
+
+WMI method GameShiftStatus([in] uint32 arg2, [out] uint32 argr)
+---------------------------------------------------------------
+
+::
+
+ if BYTE_0(arg2) == 0x1:
+ TOGGLE_GAME_SHIFT()
+ argr = GET_GAME_SHIFT_STATUS()
+
+ if BYTE_0(arg2) == 0x2:
+ argr = GET_GAME_SHIFT_STATUS()
+
+Game Shift Status does not change the fan speed profile but it could be some
+sort of CPU/GPU power profile. Benchmarks have not been done.
+
+This method is only present on Dell's G-Series laptops and it's implementation
+implies GMODE thermal profile is available, even if operation 0x03 of
+Thermal_Information does not list it.
+
+G-key on Dell's G-Series laptops also changes Game Shift status, so both are
+directly related.
+
+WMI method GetFanSensors([in] uint32 arg2, [out] uint32 argr)
+-------------------------------------------------------------
+
+::
+
+ if BYTE_0(arg2) == 0x1:
+ if is_valid_fan(BYTE_1(arg2)):
+ argr = 1
+ else:
+ argr = 0
+
+ if BYTE_0(arg2) == 0x2:
+ if is_valid_fan(BYTE_1(arg2)):
+ if BYTE_2(arg2) == 0:
+ argr == SENSOR_ID
+ else
+ argr == 0xFFFFFFFF
+ else:
+ argr = 0
+
+Overclocking Methods
+====================
+
+.. warning::
+ These methods have not been tested and are only partially reverse
+ engineered.
+
+WMI method Return_OverclockingReport([out] uint32 argr)
+-------------------------------------------------------
+
+::
+
+ CSMI (0xE3, 0x99)
+ argr = 0
+
+CSMI is an unknown operation.
+
+WMI method Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr)
+-------------------------------------------------------------------
+
+::
+
+ CSMI (0xE3, 0x99)
+ argr = 0
+
+CSMI is an unknown operation.
+
+WMI method Clear_OCFailSafeFlag([out] uint32 argr)
+--------------------------------------------------
+
+::
+
+ CSMI (0xE3, 0x99)
+ argr = 0
+
+CSMI is an unknown operation.
+
+
+WMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr)
+---------------------------------------------------------------
+
+AWCC supports memory overclocking, but this method is very intricate and has
+not been deciphered yet.
+
+GPIO methods
+============
+
+These methods are probably related to some kind of firmware update system,
+through a GPIO device.
+
+.. warning::
+ These methods have not been tested and are only partially reverse
+ engineered.
+
+WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr)
+------------------------------------------------------------------
+
+::
+
+ if BYTE_0(arg2) == 0:
+ if BYTE_1(arg2) == 1:
+ SET_PIN_A_HIGH()
+ else:
+ SET_PIN_A_LOW()
+
+ if BYTE_0(arg2) == 1:
+ if BYTE_1(arg2) == 1:
+ SET_PIN_B_HIGH()
+
+ else:
+ SET_PIN_B_LOW()
+
+ else:
+ argr = 1
+
+WMI method ReadTotalofGPIOs([out] uint32 argr)
+----------------------------------------------
+
+::
+
+ argr = 0x02
+
+WMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr)
+------------------------------------------------------------------
+
+::
+
+ if BYTE_0(arg2) == 0:
+ argr = PIN_A_STATUS
+
+ if BYTE_0(arg2) == 1:
+ argr = PIN_B_STATUS
+
+Other information Methods
+=========================
+
+WMI method ReadChassisColor([out] uint32 argr)
+----------------------------------------------
+
+::
+
+ argr = CHASSIS_COLOR_ID
+
+Acknowledgements
+================
+
+Kudos to `AlexIII <https://github.com/AlexIII/tcc-g15>`_ for documenting
+and testing available thermal profile codes.
diff --git a/Documentation/wmi/driver-development-guide.rst b/Documentation/wmi/driver-development-guide.rst
index 429137b2f632..676873c98680 100644
--- a/Documentation/wmi/driver-development-guide.rst
+++ b/Documentation/wmi/driver-development-guide.rst
@@ -64,6 +64,7 @@ to matching WMI devices using a struct wmi_device_id table:
.id_table = foo_id_table,
.probe = foo_probe,
.remove = foo_remove, /* optional, devres is preferred */
+ .shutdown = foo_shutdown, /* optional, called during shutdown */
.notify = foo_notify, /* optional, for event handling */
.no_notify_data = true, /* optional, enables events containing no additional data */
.no_singleton = true, /* required for new WMI drivers */
@@ -79,6 +80,10 @@ to unregister interfaces to other kernel subsystems and release resources, devre
This simplifies error handling during probe and often allows to omit this callback entirely, see
Documentation/driver-api/driver-model/devres.rst for details.
+The shutdown() callback is called during shutdown, reboot or kexec. Its sole purpose is to disable
+the WMI device and put it in a well-known state for the WMI driver to pick up later after reboot
+or kexec. Most WMI drivers need no special shutdown handling and can thus omit this callback.
+
Please note that new WMI drivers are required to be able to be instantiated multiple times,
and are forbidden from using any deprecated GUID-based WMI functions. This means that the
WMI driver should be prepared for the scenario that multiple matching WMI devices are present
@@ -123,7 +128,7 @@ ACPI object is being done by the WMI subsystem, not the driver.
The WMI driver core will take care that the notify() callback will only be called after
the probe() callback has been called, and that no events are being received by the driver
-right before and after calling its remove() callback.
+right before and after calling its remove() or shutdown() callback.
However WMI driver developers should be aware that multiple WMI events can be received concurrently,
so any locking (if necessary) needs to be provided by the WMI driver itself.
diff --git a/MAINTAINERS b/MAINTAINERS
index 3779b3cc138e..1e930c7a58b1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -701,7 +701,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-aimslab*
AIO
@@ -786,6 +786,7 @@ F: drivers/perf/alibaba_uncore_drw_pmu.c
ALIENWARE WMI DRIVER
L: Dell.Client.Kernel@dell.com
S: Maintained
+F: Documentation/wmi/devices/alienware-wmi.rst
F: drivers/platform/x86/dell/alienware-wmi.c
ALLEGRO DVT VIDEO IP CORE DRIVER
@@ -809,7 +810,7 @@ ALLWINNER A10 CSI DRIVER
M: Maxime Ripard <mripard@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
F: drivers/media/platform/sunxi/sun4i-csi/
@@ -818,7 +819,7 @@ 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
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
F: drivers/media/platform/sunxi/sun6i-csi/
@@ -826,7 +827,7 @@ 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
+T: git git://linuxtv.org/media.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
@@ -835,7 +836,7 @@ ALLWINNER A31 MIPI CSI-2 BRIDGE DRIVER
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml
F: drivers/media/platform/sunxi/sun6i-mipi-csi2/
@@ -965,6 +966,14 @@ Q: https://patchwork.kernel.org/project/linux-rdma/list/
F: drivers/infiniband/hw/efa/
F: include/uapi/rdma/efa-abi.h
+AMD 3D V-CACHE PERFORMANCE OPTIMIZER DRIVER
+M: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+R: Mario Limonciello <mario.limonciello@amd.com>
+L: platform-driver-x86@vger.kernel.org
+S: Supported
+F: Documentation/ABI/testing/sysfs-bus-platform-drivers-amd_x3d_vcache
+F: drivers/platform/x86/amd/x3d_vcache.c
+
AMD ADDRESS TRANSLATION LIBRARY (ATL)
M: Yazen Ghannam <Yazen.Ghannam@amd.com>
L: linux-edac@vger.kernel.org
@@ -1074,7 +1083,7 @@ S: Maintained
F: Documentation/arch/x86/amd_hsmp.rst
F: arch/x86/include/asm/amd_hsmp.h
F: arch/x86/include/uapi/asm/amd_hsmp.h
-F: drivers/platform/x86/amd/hsmp.c
+F: drivers/platform/x86/amd/hsmp/
AMD IOMMU (AMD-VI)
M: Joerg Roedel <joro@8bytes.org>
@@ -1106,6 +1115,12 @@ L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-amd-mp2*
+AMD ASF I2C DRIVER
+M: Shyam Sundar S K <shyam-sundar.s-k@amd.com>
+L: linux-i2c@vger.kernel.org
+S: Supported
+F: drivers/i2c/busses/i2c-amd-asf-plat.c
+
AMD PDS CORE DRIVER
M: Shannon Nelson <shannon.nelson@amd.com>
M: Brett Creeley <brett.creeley@amd.com>
@@ -1124,7 +1139,7 @@ F: drivers/platform/x86/amd/pmc/
AMD PMF DRIVER
M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
L: platform-driver-x86@vger.kernel.org
-S: Maintained
+S: Supported
F: Documentation/ABI/testing/sysfs-amd-pmf
F: drivers/platform/x86/amd/pmf/
@@ -1174,8 +1189,9 @@ F: Documentation/hid/amd-sfh*
F: drivers/hid/amd-sfh-hid/
AMD SPI DRIVER
-M: Sanjay R Mehta <sanju.mehta@amd.com>
-S: Maintained
+M: Raju Rangoju <Raju.Rangoju@amd.com>
+L: linux-spi@vger.kernel.org
+S: Supported
F: drivers/spi/spi-amd.c
AMD XGBE DRIVER
@@ -1202,6 +1218,14 @@ F: Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml
F: drivers/perf/amlogic/
F: include/soc/amlogic/
+AMLOGIC RTC DRIVER
+M: Yiting Deng <yiting.deng@amlogic.com>
+M: Xianwei Zhao <xianwei.zhao@amlogic.com>
+L: linux-amlogic@lists.infradead.org
+S: Maintained
+F: Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml
+F: drivers/rtc/rtc-amlogic-a4.c
+
AMPHENOL CHIPCAP 2 HUMIDITY-TEMPERATURE IIO DRIVER
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
L: linux-hwmon@vger.kernel.org
@@ -1255,7 +1279,6 @@ M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
-F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
F: drivers/iio/adc/ad4130.c
@@ -1320,6 +1343,17 @@ F: Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
F: drivers/iio/addac/ad74413r.c
F: include/dt-bindings/iio/addac/adi,ad74413r.h
+ANALOG DEVICES INC AD7625 DRIVER
+M: Michael Hennerich <Michael.Hennerich@analog.com>
+M: Nuno Sá <nuno.sa@analog.com>
+R: Trevor Gamblin <tgamblin@baylibre.com>
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+W: http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html
+F: Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml
+F: Documentation/iio/ad7625.rst
+F: drivers/iio/adc/ad7625.c
+
ANALOG DEVICES INC AD7768-1 DRIVER
M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-iio@vger.kernel.org
@@ -1347,6 +1381,14 @@ F: Documentation/ABI/testing/debugfs-iio-ad9467
F: Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
F: drivers/iio/adc/ad9467.c
+ANALOG DEVICES INC AD8460 DRIVER
+M: Mariel Tinaco <Mariel.Tinaco@analog.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+F: Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml
+F: drivers/iio/dac/ad8460.c
+
ANALOG DEVICES INC AD9739a DRIVER
M: Nuno Sa <nuno.sa@analog.com>
M: Dragos Bogdan <dragos.bogdan@analog.com>
@@ -1514,6 +1556,7 @@ L: linux-sound@vger.kernel.org
S: Supported
W: http://wiki.analog.com/
W: https://ez.analog.com/linux-software-drivers
+F: Documentation/devicetree/bindings/sound/adi,*
F: sound/soc/codecs/ad1*
F: sound/soc/codecs/ad7*
F: sound/soc/codecs/adau*
@@ -1546,6 +1589,7 @@ F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
F: Documentation/devicetree/bindings/iio/*/adi,*
F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml
F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
+F: Documentation/iio/ad7606.rst
F: drivers/iio/*/ad*
F: drivers/iio/adc/ltc249*
F: drivers/iio/amplifiers/hmc425a.c
@@ -1989,7 +2033,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-actions@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/arm/actions.yaml
-F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
+F: Documentation/devicetree/bindings/clock/actions,owl-cmu.yaml
F: Documentation/devicetree/bindings/dma/owl-dma.yaml
F: Documentation/devicetree/bindings/i2c/i2c-owl.yaml
F: Documentation/devicetree/bindings/interrupt-controller/actions,owl-sirq.yaml
@@ -1997,7 +2041,7 @@ F: Documentation/devicetree/bindings/mmc/owl-mmc.yaml
F: Documentation/devicetree/bindings/net/actions,owl-emac.yaml
F: Documentation/devicetree/bindings/pinctrl/actions,*
F: Documentation/devicetree/bindings/power/actions,owl-sps.txt
-F: Documentation/devicetree/bindings/timer/actions,owl-timer.txt
+F: Documentation/devicetree/bindings/timer/actions,owl-timer.yaml
F: arch/arm/boot/dts/actions/
F: arch/arm/mach-actions/
F: arch/arm64/boot/dts/actions/
@@ -2125,9 +2169,11 @@ L: asahi@lists.linux.dev
L: linux-sound@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/sound/adi,ssm3515.yaml
+F: Documentation/devicetree/bindings/sound/cirrus,cs42l84.yaml
F: Documentation/devicetree/bindings/sound/apple,*
F: sound/soc/apple/*
F: sound/soc/codecs/cs42l83-i2c.c
+F: sound/soc/codecs/cs42l84.*
F: sound/soc/codecs/ssm3515.c
ARM/APPLE MACHINE SUPPORT
@@ -2194,7 +2240,7 @@ F: drivers/mmc/host/usdhi6rol0.c
F: drivers/pinctrl/pinctrl-artpec*
ARM/ASPEED I2C DRIVER
-M: Brendan Higgins <brendanhiggins@google.com>
+M: Ryan Chen <ryan_chen@aspeedtech.com>
R: Benjamin Herrenschmidt <benh@kernel.crashing.org>
R: Joel Stanley <joel@jms.id.au>
L: linux-i2c@vger.kernel.org
@@ -2805,6 +2851,7 @@ F: arch/arm64/boot/dts/qcom/sdm845-cheza*
ARM/QUALCOMM MAILING LIST
L: linux-arm-msm@vger.kernel.org
+C: irc://irc.oftc.net/linux-msm
F: Documentation/devicetree/bindings/*/qcom*
F: Documentation/devicetree/bindings/soc/qcom/
F: arch/arm/boot/dts/qcom/
@@ -2846,13 +2893,14 @@ M: Bjorn Andersson <andersson@kernel.org>
M: Konrad Dybcio <konradybcio@kernel.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
+C: irc://irc.oftc.net/linux-msm
T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
F: Documentation/devicetree/bindings/arm/qcom-soc.yaml
F: Documentation/devicetree/bindings/arm/qcom.yaml
F: Documentation/devicetree/bindings/bus/qcom*
F: Documentation/devicetree/bindings/cache/qcom,llcc.yaml
F: Documentation/devicetree/bindings/firmware/qcom,scm.yaml
-F: Documentation/devicetree/bindings/reserved-memory/qcom
+F: Documentation/devicetree/bindings/reserved-memory/qcom*
F: Documentation/devicetree/bindings/soc/qcom/
F: arch/arm/boot/dts/qcom/
F: arch/arm/configs/qcom_defconfig
@@ -2903,6 +2951,7 @@ 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/hwinfo/renesas,prr.yaml
+F: Documentation/devicetree/bindings/nvmem/renesas,*
F: Documentation/devicetree/bindings/soc/renesas/
F: arch/arm/boot/dts/renesas/
F: arch/arm/configs/shmobile_defconfig
@@ -2910,6 +2959,7 @@ F: arch/arm/include/debug/renesas-scif.S
F: arch/arm/mach-shmobile/
F: arch/arm64/boot/dts/renesas/
F: arch/riscv/boot/dts/renesas/
+F: drivers/nvmem/rcar-efuse.c
F: drivers/pmdomain/renesas/
F: drivers/soc/renesas/
F: include/linux/soc/renesas/
@@ -3347,7 +3397,7 @@ ASAHI KASEI AK7375 LENS VOICE COIL DRIVER
M: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/asahi-kasei,ak7375.yaml
F: drivers/media/i2c/ak7375.c
@@ -3665,6 +3715,13 @@ F: kernel/audit*
F: lib/*audit.c
K: \baudit_[a-z_0-9]\+\b
+AUTOFDO BUILD
+M: Rong Xu <xur@google.com>
+M: Han Shen <shenhan@google.com>
+S: Supported
+F: Documentation/dev-tools/autofdo.rst
+F: scripts/Makefile.autofdo
+
AUXILIARY BUS DRIVER
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
R: Dave Ertman <david.m.ertman@intel.com>
@@ -3745,6 +3802,7 @@ F: drivers/spi/spi-axi-spi-engine.c
AXI PWM GENERATOR
M: Michael Hennerich <michael.hennerich@analog.com>
M: Nuno Sá <nuno.sa@analog.com>
+R: Trevor Gamblin <tgamblin@baylibre.com>
L: linux-pwm@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
@@ -3763,7 +3821,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/dvb-usb-v2/az6007.c
AZTECH FM RADIO RECEIVER DRIVER
@@ -3771,7 +3829,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-aztech*
B43 WIRELESS DRIVER
@@ -3790,7 +3848,7 @@ F: drivers/net/wireless/broadcom/b43legacy/
BACKLIGHT CLASS/SUBSYSTEM
M: Lee Jones <lee@kernel.org>
-M: Daniel Thompson <daniel.thompson@linaro.org>
+M: Daniel Thompson <danielt@kernel.org>
M: Jingoo Han <jingoohan1@gmail.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
@@ -3855,7 +3913,7 @@ M: Fabien Dessenne <fabien.dessenne@foss.st.com>
L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/platform/st/sti/bdisp
BECKHOFF CX5020 ETHERCAT MASTER DRIVER
@@ -4014,6 +4072,13 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
F: drivers/iio/accel/bma400*
+BOSCH SENSORTEC BMI270 IMU IIO DRIVER
+M: Alex Lanzano <lanzano.alex@gmail.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml
+F: drivers/iio/imu/bmi270/
+
BOSCH SENSORTEC BMI323 IMU IIO DRIVER
M: Jagath Jog J <jagathjog1996@gmail.com>
L: linux-iio@vger.kernel.org
@@ -4863,7 +4928,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Odd fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/driver-api/media/drivers/bttv*
F: drivers/media/pci/bt8xx/bttv*
@@ -4977,13 +5042,13 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-cadet*
CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/admin-guide/media/cafe_ccic*
F: drivers/media/platform/marvell/
@@ -5167,7 +5232,7 @@ M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Supported
W: http://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/ABI/testing/debugfs-cec-error-inj
F: Documentation/devicetree/bindings/media/cec/cec-common.yaml
F: Documentation/driver-api/media/cec-core.rst
@@ -5184,7 +5249,7 @@ M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Supported
W: http://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/cec/cec-gpio.yaml
F: drivers/media/cec/platform/cec-gpio/
@@ -5391,7 +5456,7 @@ CHRONTEL CH7322 CEC DRIVER
M: Joe Tessler <jrt@google.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/chrontel,ch7322.yaml
F: drivers/media/cec/i2c/ch7322.c
@@ -5580,7 +5645,7 @@ M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/pci/cobalt/
COCCINELLE/Semantic Patches (SmPL)
@@ -5739,6 +5804,15 @@ F: fs/configfs/
F: include/linux/configfs.h
F: samples/configfs/
+CONGATEC BOARD CONTROLLER MFD DRIVER
+M: Thomas Richard <thomas.richard@bootlin.com>
+S: Maintained
+F: drivers/gpio/gpio-cgbc.c
+F: drivers/i2c/busses/i2c-cgbc.c
+F: drivers/mfd/cgbc-core.c
+F: drivers/watchdog/cgbc_wdt.c
+F: include/linux/mfd/cgbc.h
+
CONSOLE SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Supported
@@ -5754,7 +5828,6 @@ F: kernel/context_tracking.c
CONTROL GROUP (CGROUP)
M: Tejun Heo <tj@kernel.org>
-M: Zefan Li <lizefan.x@bytedance.com>
M: Johannes Weiner <hannes@cmpxchg.org>
M: Michal Koutný <mkoutny@suse.com>
L: cgroups@vger.kernel.org
@@ -5783,7 +5856,6 @@ F: include/linux/blk-cgroup.h
CONTROL GROUP - CPUSET
M: Waiman Long <longman@redhat.com>
-M: Zefan Li <lizefan.x@bytedance.com>
L: cgroups@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
@@ -6024,7 +6096,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: http://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/cs3308.c
CS5535 Audio ALSA driver
@@ -6055,7 +6127,7 @@ M: Andy Walls <awalls@md.metrocast.net>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/pci/cx18/
F: include/uapi/linux/ivtv*
@@ -6064,7 +6136,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/common/cx2341x*
F: include/media/drv-intf/cx2341x.h
@@ -6082,7 +6154,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Odd fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/driver-api/media/drivers/cx88*
F: drivers/media/pci/cx88/
@@ -6299,7 +6371,6 @@ DECSTATION PLATFORM SUPPORT
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
L: linux-mips@vger.kernel.org
S: Maintained
-W: http://www.linux-mips.org/wiki/DECstation
F: arch/mips/dec/
F: arch/mips/include/asm/dec/
F: arch/mips/include/asm/mach-dec/
@@ -6318,7 +6389,7 @@ DEINTERLACE DRIVERS FOR ALLWINNER H3
M: Jernej Skrabec <jernej.skrabec@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
F: drivers/media/platform/sunxi/sun8i-di/
@@ -6445,7 +6516,7 @@ M: Hugues Fruchet <hugues.fruchet@foss.st.com>
L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/platform/st/sti/delta
DENALI NAND DRIVER
@@ -6853,7 +6924,7 @@ DONGWOON DW9714 LENS VOICE COIL DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.yaml
F: drivers/media/i2c/dw9714.c
@@ -6861,13 +6932,13 @@ DONGWOON DW9719 LENS VOICE COIL DRIVER
M: Daniel Scally <djrscally@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/dw9719.c
DONGWOON DW9768 LENS VOICE COIL DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml
F: drivers/media/i2c/dw9768.c
@@ -6875,7 +6946,7 @@ DONGWOON DW9807 LENS VOICE COIL DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.yaml
F: drivers/media/i2c/dw9807-vcm.c
@@ -7448,7 +7519,6 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: drivers/gpu/drm/udl/
DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
-M: Maíra Canal <mairacanal@riseup.net>
M: Louis Chauvet <louis.chauvet@bootlin.com>
R: Haneen Mohammed <hamohammed.sa@gmail.com>
R: Simona Vetter <simona@ffwll.ch>
@@ -7867,10 +7937,10 @@ F: Documentation/gpu/automated_testing.rst
F: drivers/gpu/drm/ci/
DSBR100 USB FM RADIO DRIVER
-M: Alexey Klimov <klimov.linux@gmail.com>
+M: Alexey Klimov <alexey.klimov@linaro.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/dsbr100.c
DT3155 MEDIA DRIVER
@@ -7878,7 +7948,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/pci/dt3155/
DVB_USB_AF9015 MEDIA DRIVER
@@ -7923,7 +7993,7 @@ S: Maintained
W: https://linuxtv.org
W: http://github.com/mkrufky
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/dvb-usb/cxusb*
DVB_USB_EC168 MEDIA DRIVER
@@ -8071,10 +8141,10 @@ S: Maintained
F: drivers/edac/highbank*
EDAC-CAVIUM OCTEON
-M: Ralf Baechle <ralf@linux-mips.org>
+M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
L: linux-edac@vger.kernel.org
L: linux-mips@vger.kernel.org
-S: Supported
+S: Maintained
F: drivers/edac/octeon_edac*
EDAC-CAVIUM THUNDERX
@@ -8114,7 +8184,8 @@ S: Maintained
F: drivers/edac/e7xxx_edac.c
EDAC-FSL_DDR
-M: York Sun <york.sun@nxp.com>
+R: Frank Li <Frank.Li@nxp.com>
+L: imx@lists.linux.dev
L: linux-edac@vger.kernel.org
S: Maintained
F: drivers/edac/fsl_ddr_edac.*
@@ -8292,7 +8363,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/admin-guide/media/em28xx*
F: drivers/media/usb/em28xx/
@@ -8588,7 +8659,7 @@ EXTRON DA HD 4K PLUS CEC DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/cec/usb/extron-da-hd-4k-plus/
EXYNOS DP DRIVER
@@ -9008,9 +9079,16 @@ F: drivers/dma/fsl-edma*.*
FREESCALE ENETC ETHERNET DRIVERS
M: Claudiu Manoil <claudiu.manoil@nxp.com>
M: Vladimir Oltean <vladimir.oltean@nxp.com>
+M: Wei Fang <wei.fang@nxp.com>
+M: Clark Wang <xiaoning.wang@nxp.com>
+L: imx@lists.linux.dev
L: netdev@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/net/fsl,enetc*.yaml
+F: Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
F: drivers/net/ethernet/freescale/enetc/
+F: include/linux/fsl/enetc_mdio.h
+F: include/linux/fsl/netc_global.h
FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
M: Claudiu Manoil <claudiu.manoil@nxp.com>
@@ -9021,6 +9099,7 @@ F: drivers/net/ethernet/freescale/gianfar*
FREESCALE GPMI NAND DRIVER
M: Han Xu <han.xu@nxp.com>
+L: imx@lists.linux.dev
L: linux-mtd@lists.infradead.org
S: Maintained
F: drivers/mtd/nand/raw/gpmi-nand/*
@@ -9410,7 +9489,7 @@ GALAXYCORE GC2145 SENSOR DRIVER
M: Alain Volmat <alain.volmat@foss.st.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc2145.yaml
F: drivers/media/i2c/gc2145.c
@@ -9447,6 +9526,14 @@ M: Kieran Bingham <kbingham@kernel.org>
S: Supported
F: scripts/gdb/
+GE HEALTHCARE PMC ADC DRIVER
+M: Herve Codina <herve.codina@bootlin.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml
+F: drivers/iio/adc/gehc-pmc-adc.c
+F: include/dt-bindings/iio/adc/gehc,pmc-adc.h
+
GEMINI CRYPTO DRIVER
M: Corentin Labbe <clabbe@baylibre.com>
L: linux-crypto@vger.kernel.org
@@ -9458,7 +9545,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-gemtek*
GENERIC ARCHITECTURE TOPOLOGY
@@ -9682,6 +9769,11 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/gpd-pocket-fan.c
+GPIB DRIVERS
+M: Dave Penkler <dpenkler@gmail.com>
+S: Maintained
+F: drivers/staging/gpib/
+
GPIO ACPI SUPPORT
M: Mika Westerberg <mika.westerberg@linux.intel.com>
M: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
@@ -9840,56 +9932,56 @@ GS1662 VIDEO SERIALIZER
M: Charles-Antoine Couret <charles-antoine.couret@nexvision.fr>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/spi/gs1662.c
GSPCA FINEPIX SUBDRIVER
M: Frank Zago <frank@zago.net>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/gspca/finepix.c
GSPCA GL860 SUBDRIVER
M: Olivier Lorin <o.lorin@laposte.net>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/gspca/gl860/
GSPCA M5602 SUBDRIVER
M: Erik Andren <erik.andren@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/gspca/m5602/
GSPCA PAC207 SONIXB SUBDRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/gspca/pac207.c
GSPCA SN9C20X SUBDRIVER
M: Brian Johnson <brijohn@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/gspca/sn9c20x.c
GSPCA T613 SUBDRIVER
M: Leandro Costantino <lcostantino@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/gspca/t613.c
GSPCA USB WEBCAM DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/gspca/
GTP (GPRS Tunneling Protocol)
@@ -10006,7 +10098,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/hdpvr/
HEWLETT PACKARD ENTERPRISE ILO CHIF DRIVER
@@ -10148,10 +10240,12 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
F: Documentation/timers/
F: include/linux/clockchips.h
+F: include/linux/delay.h
F: include/linux/hrtimer.h
F: include/linux/timer.h
F: kernel/time/clockevents.c
F: kernel/time/hrtimer.c
+F: kernel/time/sleep_timeout.c
F: kernel/time/timer.c
F: kernel/time/timer_list.c
F: kernel/time/timer_migration.*
@@ -10261,6 +10355,12 @@ S: Maintained
W: http://www.hisilicon.com
F: drivers/net/ethernet/hisilicon/hns3/
+HISILICON NETWORK HIBMCGE DRIVER
+M: Jijie Shao <shaojijie@huawei.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/ethernet/hisilicon/hibmcge/
+
HISILICON NETWORK SUBSYSTEM DRIVER
M: Jian Shen <shenjian15@huawei.com>
M: Salil Mehta <salil.mehta@huawei.com>
@@ -10503,6 +10603,7 @@ F: Documentation/mm/hugetlbfs_reserv.rst
F: Documentation/mm/vmemmap_dedup.rst
F: fs/hugetlbfs/
F: include/linux/hugetlb.h
+F: include/trace/events/hugetlbfs.h
F: mm/hugetlb.c
F: mm/hugetlb_vmemmap.c
F: mm/hugetlb_vmemmap.h
@@ -10513,7 +10614,7 @@ M: Jean-Christophe Trotin <jean-christophe.trotin@foss.st.com>
L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/platform/st/sti/hva
HWPOISON MEMORY FAILURE HANDLING
@@ -10541,7 +10642,7 @@ HYNIX HI556 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/hi556.c
HYNIX HI846 SENSOR DRIVER
@@ -10657,6 +10758,14 @@ S: Maintained
F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
F: drivers/i2c/busses/i2c-mv64xxx.c
+I2C OF COMPONENT PROBER
+M: Chen-Yu Tsai <wenst@chromium.org>
+L: linux-i2c@vger.kernel.org
+L: devicetree@vger.kernel.org
+S: Maintained
+F: drivers/i2c/i2c-core-of-prober.c
+F: include/linux/i2c-of-prober.h
+
I2C OVER PARALLEL PORT
M: Jean Delvare <jdelvare@suse.com>
L: linux-i2c@vger.kernel.org
@@ -10726,14 +10835,12 @@ F: Documentation/i2c/busses/i2c-viapro.rst
F: drivers/i2c/busses/i2c-ali1535.c
F: drivers/i2c/busses/i2c-ali1563.c
F: drivers/i2c/busses/i2c-ali15x3.c
-F: drivers/i2c/busses/i2c-amd756-s4882.c
F: drivers/i2c/busses/i2c-amd756.c
F: drivers/i2c/busses/i2c-amd8111.c
F: drivers/i2c/busses/i2c-i801.c
F: drivers/i2c/busses/i2c-isch.c
-F: drivers/i2c/busses/i2c-nforce2-s4985.c
F: drivers/i2c/busses/i2c-nforce2.c
-F: drivers/i2c/busses/i2c-piix4.c
+F: drivers/i2c/busses/i2c-piix4.*
F: drivers/i2c/busses/i2c-sis5595.c
F: drivers/i2c/busses/i2c-sis630.c
F: drivers/i2c/busses/i2c-sis96x.c
@@ -11457,7 +11564,7 @@ Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
F: drivers/dma/ioat*
INTEL IAA CRYPTO DRIVER
-M: Tom Zanussi <tom.zanussi@linux.intel.com>
+M: Kristen Accardi <kristen.c.accardi@intel.com>
L: linux-crypto@vger.kernel.org
S: Supported
F: Documentation/driver-api/crypto/iaa/iaa-crypto.rst
@@ -11512,7 +11619,7 @@ M: Dan Scally <djrscally@gmail.com>
R: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst
F: drivers/media/pci/intel/ipu3/
@@ -11533,12 +11640,12 @@ M: Bingbu Cao <bingbu.cao@intel.com>
R: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/admin-guide/media/ipu6-isys.rst
F: drivers/media/pci/intel/ipu6/
INTEL ISHTP ECLITE DRIVER
-M: Sumesh K Naduvalath <sumesh.k.naduvalath@intel.com>
+M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
F: drivers/platform/x86/intel/ishtp_eclite.c
@@ -11598,7 +11705,7 @@ F: drivers/usb/misc/usb-ljca.c
F: include/linux/usb/ljca.h
INTEL MANAGEMENT ENGINE (mei)
-M: Tomas Winkler <tomas.winkler@intel.com>
+M: Alexander Usyskin <alexander.usyskin@intel.com>
L: linux-kernel@vger.kernel.org
S: Supported
F: Documentation/driver-api/mei/*
@@ -11771,7 +11878,7 @@ M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/debugfs-tpmi
-F: drivers/platform/x86/intel/tpmi.c
+F: drivers/platform/x86/intel/vsec_tpmi.c
F: include/linux/intel_tpmi.h
INTEL UNCORE FREQUENCY CONTROL
@@ -11879,7 +11986,7 @@ F: Documentation/devicetree/bindings/media/i2c/isil,isl79987.yaml
F: drivers/media/i2c/isl7998x.c
INVENSENSE ICM-426xx IMU DRIVER
-M: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+M: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
L: linux-iio@vger.kernel.org
S: Maintained
W: https://invensense.tdk.com/
@@ -11894,8 +12001,16 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml
F: drivers/iio/gyro/mpu3050*
+INVENSENSE MPU-6050 IMU DRIVER
+M: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+W: https://invensense.tdk.com/
+F: Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
+F: drivers/iio/imu/inv_mpu6050/
+
IOC3 ETHERNET DRIVER
-M: Ralf Baechle <ralf@linux-mips.org>
+M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
L: linux-mips@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/sgi/ioc3-eth.c
@@ -12046,7 +12161,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-isa*
ISAPNP
@@ -12114,6 +12229,14 @@ F: drivers/isdn/Makefile
F: drivers/isdn/hardware/
F: drivers/isdn/mISDN/
+ISL28022 HARDWARE MONITORING DRIVER
+M: Carsten Spieß <mail@carsten-spiess.de>
+L: linux-hwmon@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/hwmon/renesas,isl28022.yaml
+F: Documentation/hwmon/isl28022.rst
+F: drivers/hwmon/isl28022.c
+
ISOFS FILESYSTEM
M: Jan Kara <jack@suse.cz>
L: linux-fsdevel@vger.kernel.org
@@ -12135,6 +12258,14 @@ W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/tuners/it913x*
+ITE IT6263 LVDS TO HDMI BRIDGE DRIVER
+M: Liu Ying <victor.liu@nxp.com>
+L: dri-devel@lists.freedesktop.org
+S: Maintained
+T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
+F: Documentation/devicetree/bindings/display/bridge/ite,it6263.yaml
+F: drivers/gpu/drm/bridge/ite-it6263.c
+
ITE IT66121 HDMI BRIDGE DRIVER
M: Phong LE <ple@baylibre.com>
M: Neil Armstrong <neil.armstrong@linaro.org>
@@ -12148,7 +12279,7 @@ M: Andy Walls <awalls@md.metrocast.net>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/admin-guide/media/ivtv*
F: drivers/media/pci/ivtv/
F: include/uapi/linux/ivtv*
@@ -12296,7 +12427,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-keene*
KERNEL AUTOMOUNTER
@@ -12344,7 +12475,7 @@ F: mm/usercopy.c
F: security/Kconfig.hardening
K: \b(add|choose)_random_kstack_offset\b
K: \b__check_(object_size|heap_object)\b
-K: \b__counted_by\b
+K: \b__counted_by(_le|_be)?\b
KERNEL JANITORS
L: kernel-janitors@vger.kernel.org
@@ -12377,6 +12508,7 @@ F: include/trace/misc/sunrpc.h
F: include/uapi/linux/nfsd/
F: include/uapi/linux/sunrpc/
F: net/sunrpc/
+F: tools/net/sunrpc/
KERNEL PACMAN PACKAGING (in addition to generic KERNEL BUILD)
M: Thomas Weißschuh <linux@weissschuh.net>
@@ -12415,7 +12547,7 @@ F: fs/smb/common/
F: fs/smb/server/
KERNEL UNIT TESTING FRAMEWORK (KUnit)
-M: Brendan Higgins <brendanhiggins@google.com>
+M: Brendan Higgins <brendan.higgins@linux.dev>
M: David Gow <davidgow@google.com>
R: Rae Moar <rmoar@google.com>
L: linux-kselftest@vger.kernel.org
@@ -12671,7 +12803,7 @@ F: samples/kfifo/
KGDB / KDB /debug_core
M: Jason Wessel <jason.wessel@windriver.com>
-M: Daniel Thompson <daniel.thompson@linaro.org>
+M: Daniel Thompson <danielt@kernel.org>
R: Douglas Anderson <dianders@chromium.org>
L: kgdb-bugreport@lists.sourceforge.net
S: Maintained
@@ -13081,7 +13213,7 @@ M: Michael Ellerman <mpe@ellerman.id.au>
R: Nicholas Piggin <npiggin@gmail.com>
R: Christophe Leroy <christophe.leroy@csgroup.eu>
R: Naveen N Rao <naveen@kernel.org>
-R: Madhavan Srinivasan <maddy@linux.ibm.com>
+M: Madhavan Srinivasan <maddy@linux.ibm.com>
L: linuxppc-dev@lists.ozlabs.org
S: Supported
W: https://github.com/linuxppc/wiki/wiki
@@ -13348,12 +13480,12 @@ S: Maintained
F: Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
F: drivers/gpio/gpio-loongson-64bit.c
-LOONGSON LS2X APB DMA DRIVER
+LOONGSON-2 APB DMA DRIVER
M: Binbin Zhou <zhoubinbin@loongson.cn>
L: dmaengine@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/dma/loongson,ls2x-apbdma.yaml
-F: drivers/dma/ls2x-apb-dma.c
+F: drivers/dma/loongson2-apb-dma.c
LOONGSON LS2X I2C DRIVER
M: Binbin Zhou <zhoubinbin@loongson.cn>
@@ -13580,10 +13712,10 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/m88rs2000*
MA901 MASTERKIT USB FM RADIO DRIVER
-M: Alexey Klimov <klimov.linux@gmail.com>
+M: Alexey Klimov <alexey.klimov@linaro.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-ma901.c
MAC80211
@@ -13685,6 +13817,7 @@ F: Documentation/devicetree/bindings/mfd/marvell,88pm886-a1.yaml
F: drivers/input/misc/88pm886-onkey.c
F: drivers/mfd/88pm886.c
F: drivers/regulator/88pm886-regulator.c
+F: drivers/rtc/rtc-88pm886.c
F: include/linux/mfd/88pm886.h
MARVELL ARMADA 3700 PHY DRIVERS
@@ -13826,6 +13959,12 @@ S: Supported
F: Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
F: drivers/net/ethernet/marvell/octeontx2/af/
+MARVELL PEM PMU DRIVER
+M: Linu Cherian <lcherian@marvell.com>
+M: Gowthami Thiagarajan <gthiagarajan@marvell.com>
+S: Supported
+F: drivers/perf/marvell_pem_pmu.c
+
MARVELL PRESTERA ETHERNET SWITCH DRIVER
M: Taras Chornyi <taras.chornyi@plvision.eu>
S: Supported
@@ -13861,6 +14000,12 @@ R: schalla@marvell.com
R: vattunuru@marvell.com
F: drivers/vdpa/octeon_ep/
+MARVELL OCTEON HOTPLUG DRIVER
+R: Shijith Thotton <sthotton@marvell.com>
+R: Vamsi Attunuru <vattunuru@marvell.com>
+S: Supported
+F: drivers/pci/hotplug/octep_hp.c
+
MATROX FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
@@ -13878,7 +14023,7 @@ MAX2175 SDR TUNER DRIVER
M: Ramesh Shanmugasundaram <rashanmu@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/max2175.txt
F: Documentation/userspace-api/media/drivers/max2175.rst
F: drivers/media/i2c/max2175*
@@ -14058,7 +14203,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-maxiradio*
MAXLINEAR ETHERNET PHY DRIVER
@@ -14141,7 +14286,7 @@ M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Supported
W: https://www.linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/mc/
F: include/media/media-*.h
F: include/uapi/linux/media.h
@@ -14150,7 +14295,7 @@ MEDIA DRIVER FOR FREESCALE IMX PXP
M: Philipp Zabel <p.zabel@pengutronix.de>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/platform/nxp/imx-pxp.[ch]
MEDIA DRIVERS FOR ASCOT2E
@@ -14159,7 +14304,7 @@ L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
W: http://netup.tv/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/ascot2e*
MEDIA DRIVERS FOR CXD2099AR CI CONTROLLERS
@@ -14167,7 +14312,7 @@ M: Jasmin Jessich <jasmin@anw.at>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/cxd2099*
MEDIA DRIVERS FOR CXD2841ER
@@ -14176,7 +14321,7 @@ L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
W: http://netup.tv/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/cxd2841er*
MEDIA DRIVERS FOR CXD2880
@@ -14184,7 +14329,7 @@ M: Yasunari Takiguchi <Yasunari.Takiguchi@sony.com>
L: linux-media@vger.kernel.org
S: Supported
W: http://linuxtv.org/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/cxd2880/*
F: drivers/media/spi/cxd2880*
@@ -14192,7 +14337,7 @@ MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES
L: linux-media@vger.kernel.org
S: Orphan
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/pci/ddbridge/*
MEDIA DRIVERS FOR FREESCALE IMX
@@ -14200,7 +14345,7 @@ M: Steve Longerbeam <slongerbeam@gmail.com>
M: Philipp Zabel <p.zabel@pengutronix.de>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/admin-guide/media/imx.rst
F: Documentation/devicetree/bindings/media/imx.txt
F: drivers/staging/media/imx/
@@ -14214,7 +14359,7 @@ M: Martin Kepplinger <martin.kepplinger@puri.sm>
R: Purism Kernel Team <kernel@puri.sm>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
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
@@ -14229,7 +14374,7 @@ L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
W: http://netup.tv/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/helene*
MEDIA DRIVERS FOR HORUS3A
@@ -14238,7 +14383,7 @@ L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
W: http://netup.tv/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/horus3a*
MEDIA DRIVERS FOR LNBH25
@@ -14247,14 +14392,14 @@ L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
W: http://netup.tv/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/lnbh25*
MEDIA DRIVERS FOR MXL5XX TUNER DEMODULATORS
L: linux-media@vger.kernel.org
S: Orphan
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/mxl5xx*
MEDIA DRIVERS FOR NETUP PCI UNIVERSAL DVB devices
@@ -14263,7 +14408,7 @@ L: linux-media@vger.kernel.org
S: Supported
W: https://linuxtv.org
W: http://netup.tv/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/pci/netup_unidvb/*
MEDIA DRIVERS FOR NVIDIA TEGRA - VDE
@@ -14271,7 +14416,7 @@ M: Dmitry Osipenko <digetx@gmail.com>
L: linux-media@vger.kernel.org
L: linux-tegra@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
F: drivers/media/platform/nvidia/tegra-vde/
@@ -14280,7 +14425,7 @@ M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/renesas,ceu.yaml
F: drivers/media/platform/renesas/renesas-ceu.c
F: include/media/drv-intf/renesas-ceu.h
@@ -14290,7 +14435,7 @@ M: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/renesas,drif.yaml
F: drivers/media/platform/renesas/rcar_drif.c
@@ -14299,7 +14444,7 @@ M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/renesas,fcp.yaml
F: drivers/media/platform/renesas/rcar-fcp.c
F: include/media/rcar-fcp.h
@@ -14309,7 +14454,7 @@ M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/renesas,fdp1.yaml
F: drivers/media/platform/renesas/rcar_fdp1.c
@@ -14318,7 +14463,7 @@ M: Niklas Söderlund <niklas.soderlund@ragnatech.se>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/renesas,csi2.yaml
F: Documentation/devicetree/bindings/media/renesas,isp.yaml
F: Documentation/devicetree/bindings/media/renesas,vin.yaml
@@ -14332,7 +14477,7 @@ M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/renesas,vsp1.yaml
F: drivers/media/platform/renesas/vsp1/
@@ -14340,14 +14485,14 @@ MEDIA DRIVERS FOR ST STV0910 DEMODULATOR ICs
L: linux-media@vger.kernel.org
S: Orphan
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/stv0910*
MEDIA DRIVERS FOR ST STV6111 TUNER ICs
L: linux-media@vger.kernel.org
S: Orphan
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/stv6111*
MEDIA DRIVERS FOR STM32 - DCMI / DCMIPP
@@ -14355,7 +14500,7 @@ M: Hugues Fruchet <hugues.fruchet@foss.st.com>
M: Alain Volmat <alain.volmat@foss.st.com>
L: linux-media@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
F: Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
F: drivers/media/platform/st/stm32/stm32-dcmi.c
@@ -14367,7 +14512,7 @@ L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
Q: http://patchwork.kernel.org/project/linux-media/list/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/admin-guide/media/
F: Documentation/devicetree/bindings/media/
F: Documentation/driver-api/media/
@@ -14394,10 +14539,12 @@ F: Documentation/devicetree/bindings/net/bluetooth/mediatek,mt7921s-bluetooth.ya
F: drivers/bluetooth/btmtkuart.c
MEDIATEK BOARD LEVEL SHUTDOWN DRIVERS
+M: Sen Chu <sen.chu@mediatek.com>
M: Sean Wang <sean.wang@mediatek.com>
+M: Macpaul Lin <macpaul.lin@mediatek.com>
L: linux-pm@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt
+F: Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
F: drivers/power/reset/mt6323-poweroff.c
MEDIATEK CIR DRIVER
@@ -14437,8 +14584,10 @@ M: Qingfang Deng <dqfext@gmail.com>
M: SkyLake Huang <SkyLake.Huang@mediatek.com>
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/phy/mediatek-ge-soc.c
-F: drivers/net/phy/mediatek-ge.c
+F: drivers/net/phy/mediatek/mtk-ge-soc.c
+F: drivers/net/phy/mediatek/mtk-phy-lib.c
+F: drivers/net/phy/mediatek/mtk-ge.c
+F: drivers/net/phy/mediatek/mtk.h
F: drivers/phy/mediatek/phy-mtk-xfi-tphy.c
MEDIATEK I2C CONTROLLER DRIVER
@@ -14502,6 +14651,32 @@ S: Maintained
F: Documentation/devicetree/bindings/mmc/mtk-sd.yaml
F: drivers/mmc/host/mtk-sd.c
+MEDIATEK MT6735 CLOCK & RESET DRIVERS
+M: Yassine Oudjana <y.oudjana@protonmail.com>
+L: linux-clk@vger.kernel.org
+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/clk/mediatek/clk-mt6735-apmixedsys.c
+F: drivers/clk/mediatek/clk-mt6735-imgsys.c
+F: drivers/clk/mediatek/clk-mt6735-infracfg.c
+F: drivers/clk/mediatek/clk-mt6735-mfgcfg.c
+F: drivers/clk/mediatek/clk-mt6735-pericfg.c
+F: drivers/clk/mediatek/clk-mt6735-topckgen.c
+F: drivers/clk/mediatek/clk-mt6735-vdecsys.c
+F: drivers/clk/mediatek/clk-mt6735-vencsys.c
+F: include/dt-bindings/clock/mediatek,mt6735-apmixedsys.h
+F: include/dt-bindings/clock/mediatek,mt6735-imgsys.h
+F: include/dt-bindings/clock/mediatek,mt6735-infracfg.h
+F: include/dt-bindings/clock/mediatek,mt6735-mfgcfg.h
+F: include/dt-bindings/clock/mediatek,mt6735-pericfg.h
+F: include/dt-bindings/clock/mediatek,mt6735-topckgen.h
+F: include/dt-bindings/clock/mediatek,mt6735-vdecsys.h
+F: include/dt-bindings/clock/mediatek,mt6735-vencsys.h
+F: include/dt-bindings/reset/mediatek,mt6735-infracfg.h
+F: include/dt-bindings/reset/mediatek,mt6735-mfgcfg.h
+F: include/dt-bindings/reset/mediatek,mt6735-pericfg.h
+F: include/dt-bindings/reset/mediatek,mt6735-vdecsys.h
+
MEDIATEK MT76 WIRELESS LAN DRIVER
M: Felix Fietkau <nbd@nbd.name>
M: Lorenzo Bianconi <lorenzo@kernel.org>
@@ -14558,9 +14733,11 @@ F: Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml
F: drivers/mtd/nand/raw/mtk_*
MEDIATEK PMIC LED DRIVER
+M: Sen Chu <sen.chu@mediatek.com>
M: Sean Wang <sean.wang@mediatek.com>
+M: Macpaul Lin <macpaul.lin@mediatek.com>
S: Maintained
-F: Documentation/devicetree/bindings/leds/leds-mt6323.txt
+F: Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml
F: drivers/leds/leds-mt6323.c
MEDIATEK RANDOM NUMBER GENERATOR SUPPORT
@@ -14860,6 +15037,8 @@ S: Maintained
W: http://www.linux-mm.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
T: quilt git://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new
+F: Documentation/admin-guide/mm/
+F: Documentation/mm/
F: include/linux/gfp.h
F: include/linux/gfp_types.h
F: include/linux/memfd.h
@@ -14943,7 +15122,7 @@ L: linux-media@vger.kernel.org
L: linux-amlogic@lists.infradead.org
S: Supported
W: http://linux-meson.com/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/cec/amlogic,meson-gx-ao-cec.yaml
F: drivers/media/cec/platform/meson/ao-cec-g12a.c
F: drivers/media/cec/platform/meson/ao-cec.c
@@ -14953,7 +15132,7 @@ M: Neil Armstrong <neil.armstrong@linaro.org>
L: linux-media@vger.kernel.org
L: linux-amlogic@lists.infradead.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml
F: drivers/media/platform/amlogic/meson-ge2d/
@@ -14969,7 +15148,7 @@ M: Neil Armstrong <neil.armstrong@linaro.org>
L: linux-media@vger.kernel.org
L: linux-amlogic@lists.infradead.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml
F: drivers/staging/media/meson/vdec/
@@ -15153,6 +15332,19 @@ S: Maintained
F: Documentation/devicetree/bindings/interrupt-controller/microchip,lan966x-oic.yaml
F: drivers/irqchip/irq-lan966x-oic.c
+MICROCHIP LAN966X PCI DRIVER
+M: Herve Codina <herve.codina@bootlin.com>
+S: Maintained
+F: drivers/misc/lan966x_pci.c
+F: drivers/misc/lan966x_pci.dtso
+
+MICROCHIP LAN969X ETHERNET DRIVER
+M: Daniel Machon <daniel.machon@microchip.com>
+M: UNGLinuxDriver@microchip.com
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/ethernet/microchip/lan969x/*
+
MICROCHIP LCDFB DRIVER
M: Nicolas Ferre <nicolas.ferre@microchip.com>
L: linux-fbdev@vger.kernel.org
@@ -15473,6 +15665,15 @@ F: arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s.dts
F: arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s-bit.dts
F: arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s.dts
+MIN HEAP
+M: Kuan-Wei Chiu <visitorckw@gmail.com>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: Documentation/core-api/min_heap.rst
+F: include/linux/min_heap.h
+F: lib/min_heap.c
+F: lib/test_min_heap.c
+
MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
@@ -15490,7 +15691,6 @@ MIPS
M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
L: linux-mips@vger.kernel.org
S: Maintained
-W: http://www.linux-mips.org/
Q: https://patchwork.kernel.org/project/linux-mips/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
F: Documentation/devicetree/bindings/mips/
@@ -15567,7 +15767,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-miropcm20*
MITSUMI MM8013 FG DRIVER
@@ -15716,10 +15916,10 @@ F: Documentation/hwmon/mp9941.rst
F: drivers/hwmon/pmbus/mp9941.c
MR800 AVERMEDIA USB FM RADIO DRIVER
-M: Alexey Klimov <klimov.linux@gmail.com>
+M: Alexey Klimov <alexey.klimov@linaro.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-mr800.c
MRF24J40 IEEE 802.15.4 RADIO DRIVER
@@ -15786,7 +15986,7 @@ MT9M114 ONSEMI SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/onnn,mt9m114.yaml
F: drivers/media/i2c/mt9m114.c
@@ -15794,16 +15994,15 @@ MT9P031 APTINA CAMERA SENSOR
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/aptina,mt9p031.yaml
F: drivers/media/i2c/mt9p031.c
-F: include/media/i2c/mt9p031.h
MT9T112 APTINA CAMERA SENSOR
M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
S: Odd Fixes
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/mt9t112.c
F: include/media/i2c/mt9t112.h
@@ -15811,7 +16010,7 @@ MT9V032 APTINA CAMERA SENSOR
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/mt9v032.txt
F: drivers/media/i2c/mt9v032.c
F: include/media/i2c/mt9v032.h
@@ -15820,7 +16019,7 @@ MT9V111 APTINA CAMERA SENSOR
M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml
F: drivers/media/i2c/mt9v111.c
@@ -15952,6 +16151,14 @@ S: Maintained
F: Documentation/devicetree/bindings/hwmon/nuvoton,nct6775.yaml
F: drivers/hwmon/nct6775-i2c.c
+NCT7363 HARDWARE MONITOR DRIVER
+M: Ban Feng <kcfeng0@nuvoton.com>
+L: linux-hwmon@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/hwmon/nuvoton,nct7363.yaml
+F: Documentation/hwmon/nct7363.rst
+F: drivers/hwmon/nct7363.c
+
NETCONSOLE
M: Breno Leitao <leitao@debian.org>
S: Maintained
@@ -16003,9 +16210,8 @@ F: net/netfilter/
F: tools/testing/selftests/net/netfilter/
NETROM NETWORK LAYER
-M: Ralf Baechle <ralf@linux-mips.org>
L: linux-hams@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linux-ax25.in-berlin.de
F: include/net/netrom.h
F: include/uapi/linux/netrom.h
@@ -16075,10 +16281,13 @@ F: include/linux/platform_data/wiznet.h
F: include/uapi/linux/cn_proc.h
F: include/uapi/linux/ethtool_netlink.h
F: include/uapi/linux/if_*
+F: include/uapi/linux/net_shaper.h
F: include/uapi/linux/netdev*
F: tools/testing/selftests/drivers/net/
X: Documentation/devicetree/bindings/net/bluetooth/
+X: Documentation/devicetree/bindings/net/can/
X: Documentation/devicetree/bindings/net/wireless/
+X: drivers/net/can/
X: drivers/net/wireless/
NETWORKING DRIVERS (WIRELESS)
@@ -16094,7 +16303,6 @@ F: drivers/net/wireless/
NETWORKING [DSA]
M: Andrew Lunn <andrew@lunn.ch>
-M: Florian Fainelli <f.fainelli@gmail.com>
M: Vladimir Oltean <olteanv@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/net/dsa/
@@ -16168,6 +16376,8 @@ X: include/net/mac80211.h
X: include/net/wext.h
X: net/9p/
X: net/bluetooth/
+X: net/can/
+X: net/ceph/
X: net/mac80211/
X: net/rfkill/
X: net/wireless/
@@ -16256,7 +16466,7 @@ F: include/net/mptcp.h
F: include/trace/events/mptcp.h
F: include/uapi/linux/mptcp*.h
F: net/mptcp/
-F: tools/testing/selftests/bpf/*/*mptcp*.c
+F: tools/testing/selftests/bpf/*/*mptcp*.[ch]
F: tools/testing/selftests/net/mptcp/
NETWORKING [TCP]
@@ -16450,6 +16660,7 @@ NOVATEK NVT-TS I2C TOUCHSCREEN DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/input/touchscreen/novatek,nvt-ts.yaml
F: drivers/input/touchscreen/novatek-nvt-ts.c
NSDEPS
@@ -16750,13 +16961,6 @@ S: Maintained
F: Documentation/hwmon/nzxt-kraken3.rst
F: drivers/hwmon/nzxt-kraken3.c
-NZXT-SMART2 HARDWARE MONITORING DRIVER
-M: Aleksandr Mezin <mezin.alexander@gmail.com>
-L: linux-hwmon@vger.kernel.org
-S: Maintained
-F: Documentation/hwmon/nzxt-smart2.rst
-F: drivers/hwmon/nzxt-smart2.c
-
OBJAGG
M: Jiri Pirko <jiri@resnulli.us>
L: netdev@vger.kernel.org
@@ -16898,14 +17102,6 @@ S: Maintained
F: Documentation/devicetree/bindings/i2c/ti,omap4-i2c.yaml
F: drivers/i2c/busses/i2c-omap.c
-OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS)
-M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-L: linux-media@vger.kernel.org
-S: Maintained
-F: Documentation/devicetree/bindings/media/ti,omap3isp.txt
-F: drivers/media/platform/ti/omap3isp/
-F: drivers/staging/media/omap4iss/
-
OMAP MMC SUPPORT
M: Aaro Koskinen <aaro.koskinen@iki.fi>
L: linux-omap@vger.kernel.org
@@ -17016,13 +17212,13 @@ OMNIVISION OV01A10 SENSOR DRIVER
M: Bingbu Cao <bingbu.cao@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov01a10.c
OMNIVISION OV02A10 SENSOR DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml
F: drivers/media/i2c/ov02a10.c
@@ -17030,28 +17226,29 @@ OMNIVISION OV08D10 SENSOR DRIVER
M: Jimmy Su <jimmy.su@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.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
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov08x40.c
+F: Documentation/devicetree/bindings/media/i2c/ovti,ov08x40.yaml
OMNIVISION OV13858 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov13858.c
OMNIVISION OV13B10 SENSOR DRIVER
M: Arec Kao <arec.kao@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov13b10.c
OMNIVISION OV2680 SENSOR DRIVER
@@ -17059,7 +17256,7 @@ M: Rui Miguel Silva <rmfrfs@gmail.com>
M: Hans de Goede <hansg@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml
F: drivers/media/i2c/ov2680.c
@@ -17067,7 +17264,7 @@ OMNIVISION OV2685 SENSOR DRIVER
M: Shunqian Zheng <zhengsq@rock-chips.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml
F: drivers/media/i2c/ov2685.c
@@ -17077,14 +17274,14 @@ R: Sakari Ailus <sakari.ailus@linux.intel.com>
R: Bingbu Cao <bingbu.cao@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.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
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
F: drivers/media/i2c/ov4689.c
@@ -17092,7 +17289,7 @@ OMNIVISION OV5640 SENSOR DRIVER
M: Steve Longerbeam <slongerbeam@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov5640.c
OMNIVISION OV5647 SENSOR DRIVER
@@ -17100,7 +17297,7 @@ M: Dave Stevenson <dave.stevenson@raspberrypi.com>
M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov5647.yaml
F: drivers/media/i2c/ov5647.c
@@ -17108,7 +17305,7 @@ OMNIVISION OV5670 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov5670.yaml
F: drivers/media/i2c/ov5670.c
@@ -17116,7 +17313,7 @@ OMNIVISION OV5675 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov5675.yaml
F: drivers/media/i2c/ov5675.c
@@ -17124,7 +17321,7 @@ OMNIVISION OV5693 SENSOR DRIVER
M: Daniel Scally <djrscally@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml
F: drivers/media/i2c/ov5693.c
@@ -17132,21 +17329,21 @@ OMNIVISION OV5695 SENSOR DRIVER
M: Shunqian Zheng <zhengsq@rock-chips.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov5695.c
OMNIVISION OV64A40 SENSOR DRIVER
M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov64a40.yaml
F: drivers/media/i2c/ov64a40.c
OMNIVISION OV7670 SENSOR DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ov7670.txt
F: drivers/media/i2c/ov7670.c
@@ -17154,7 +17351,7 @@ OMNIVISION OV772x SENSOR DRIVER
M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
S: Odd fixes
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml
F: drivers/media/i2c/ov772x.c
F: include/media/i2c/ov772x.h
@@ -17162,7 +17359,7 @@ F: include/media/i2c/ov772x.h
OMNIVISION OV7740 SENSOR DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ov7740.txt
F: drivers/media/i2c/ov7740.c
@@ -17170,7 +17367,7 @@ OMNIVISION OV8856 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov8856.yaml
F: drivers/media/i2c/ov8856.c
@@ -17179,7 +17376,7 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
M: Nicholas Roth <nicholas@rothemail.net>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov8858.yaml
F: drivers/media/i2c/ov8858.c
@@ -17187,7 +17384,7 @@ OMNIVISION OV9282 SENSOR DRIVER
M: Dave Stevenson <dave.stevenson@raspberrypi.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
F: drivers/media/i2c/ov9282.c
@@ -17203,7 +17400,7 @@ R: Akinobu Mita <akinobu.mita@gmail.com>
R: Sylwester Nawrocki <s.nawrocki@samsung.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/ov9650.txt
F: drivers/media/i2c/ov9650.c
@@ -17212,7 +17409,7 @@ M: Tianshu Qiu <tian.shu.qiu@intel.com>
R: Bingbu Cao <bingbu.cao@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/ov9734.c
ONBOARD USB HUB DRIVER
@@ -17437,6 +17634,7 @@ S: Supported
F: Documentation/core-api/packing.rst
F: include/linux/packing.h
F: lib/packing.c
+F: lib/packing_test.c
PADATA PARALLEL EXECUTION MECHANISM
M: Steffen Klassert <steffen.klassert@secunet.com>
@@ -17876,8 +18074,8 @@ M: Bartosz Golaszewski <brgl@bgdev.pl>
L: linux-pci@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
-F: drivers/pci/pwrctl/*
-F: include/linux/pci-pwrctl.h
+F: drivers/pci/pwrctrl/*
+F: include/linux/pci-pwrctrl.h
PCI SUBSYSTEM
M: Bjorn Helgaas <bhelgaas@google.com>
@@ -17899,6 +18097,15 @@ F: include/linux/of_pci.h
F: include/linux/pci*
F: include/uapi/linux/pci*
+PCIE BANDWIDTH CONTROLLER
+M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+L: linux-pci@vger.kernel.org
+S: Supported
+F: drivers/pci/pcie/bwctrl.c
+F: drivers/thermal/pcie_cooling.c
+F: include/linux/pci-bwctrl.h
+F: tools/testing/selftests/pcie_bwctrl/
+
PCIE DRIVER FOR AMAZON ANNAPURNA LABS
M: Jonathan Chocron <jonnyc@amazon.com>
L: linux-pci@vger.kernel.org
@@ -18198,6 +18405,13 @@ F: drivers/pinctrl/
F: include/dt-bindings/pinctrl/
F: include/linux/pinctrl/
+PIN CONTROLLER - AIROHA
+M: Lorenzo Bianconi <lorenzo@kernel.org>
+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml
+F: drivers/pinctrl/mediatek/pinctrl-airoha.c
+
PIN CONTROLLER - AMD
M: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
@@ -18274,6 +18488,7 @@ PIN CONTROLLER - QUALCOMM
M: Bjorn Andersson <andersson@kernel.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
+C: irc://irc.oftc.net/linux-msm
F: Documentation/devicetree/bindings/pinctrl/qcom,*
F: drivers/pinctrl/qcom/
@@ -18508,6 +18723,13 @@ S: Maintained
F: include/linux/psi*
F: kernel/sched/psi.c
+PROPELLER BUILD
+M: Rong Xu <xur@google.com>
+M: Han Shen <shenhan@google.com>
+S: Supported
+F: Documentation/dev-tools/propeller.rst
+F: scripts/Makefile.propeller
+
PRINTK
M: Petr Mladek <pmladek@suse.com>
R: Steven Rostedt <rostedt@goodmis.org>
@@ -18535,7 +18757,6 @@ F: include/linux/proc_fs.h
F: tools/testing/selftests/proc/
PROC SYSCTL
-M: Luis Chamberlain <mcgrof@kernel.org>
M: Kees Cook <kees@kernel.org>
M: Joel Granados <joel.granados@kernel.org>
L: linux-kernel@vger.kernel.org
@@ -18641,6 +18862,13 @@ S: Maintained
F: drivers/ptp/ptp_vclock.c
F: net/ethtool/phc_vclocks.c
+PTP VMCLOCK SUPPORT
+M: David Woodhouse <dwmw2@infradead.org>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/ptp/ptp_vmclock.c
+F: include/uapi/linux/vmclock-abi.h
+
PTRACE SUPPORT
M: Oleg Nesterov <oleg@redhat.com>
S: Maintained
@@ -18657,7 +18885,7 @@ PULSE8-CEC DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/cec/usb/pulse8/
PURELIFI PLFXLC DRIVER
@@ -18672,7 +18900,7 @@ L: pvrusb2@isely.net (subscribers-only)
L: linux-media@vger.kernel.org
S: Maintained
W: http://www.isely.net/pvrusb2/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/driver-api/media/drivers/pvrusb2*
F: drivers/media/usb/pvrusb2/
@@ -18680,7 +18908,7 @@ PWC WEBCAM DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/pwc/*
F: include/trace/events/pwc.h
@@ -19184,7 +19412,7 @@ R: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
L: linux-media@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/*venus*
F: drivers/media/platform/qcom/venus/
@@ -19229,14 +19457,14 @@ RADIOSHARK RADIO DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-shark.c
RADIOSHARK2 RADIO DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-shark2.c
F: drivers/media/radio/radio-tea5777.c
@@ -19260,7 +19488,7 @@ RAINSHADOW-CEC DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/cec/usb/rainshadow/
RALINK MIPS ARCHITECTURE
@@ -19339,12 +19567,19 @@ F: Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
F: drivers/media/platform/raspberrypi/pisp_be/
F: include/uapi/linux/media/raspberrypi/
+RASPBERRY PI PISP CAMERA FRONT END
+M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+M: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
+S: Maintained
+F: Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml
+F: drivers/media/platform/raspberrypi/rp1-cfe/
+
RC-CORE / LIRC FRAMEWORK
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org
S: Maintained
W: http://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/driver-api/media/rc-core.rst
F: Documentation/userspace-api/media/rc/
F: drivers/media/rc/
@@ -19501,6 +19736,12 @@ S: Maintained
F: Documentation/devicetree/bindings/net/dsa/realtek.yaml
F: drivers/net/dsa/realtek/*
+REALTEK SPI-NAND
+M: Chris Packham <chris.packham@alliedtelesis.co.nz>
+S: Maintained
+F: Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml
+F: drivers/spi/spi-realtek-rtl-snand.c
+
REALTEK WIRELESS DRIVER (rtlwifi family)
M: Ping-Ke Shih <pkshih@realtek.com>
L: linux-wireless@vger.kernel.org
@@ -19536,11 +19777,6 @@ F: Documentation/devicetree/bindings/regmap/
F: drivers/base/regmap/
F: include/linux/regmap.h
-REISERFS FILE SYSTEM
-L: reiserfs-devel@vger.kernel.org
-S: Obsolete
-F: fs/reiserfs/
-
REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
M: Bjorn Andersson <andersson@kernel.org>
M: Mathieu Poirier <mathieu.poirier@linaro.org>
@@ -19590,6 +19826,17 @@ S: Supported
F: Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml
F: drivers/i2c/busses/i2c-emev2.c
+RENESAS ETHERNET AVB DRIVER
+M: Paul Barker <paul.barker.ct@bp.renesas.com>
+M: Niklas Söderlund <niklas.soderlund@ragnatech.se>
+L: netdev@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/net/renesas,etheravb.yaml
+F: drivers/net/ethernet/renesas/Kconfig
+F: drivers/net/ethernet/renesas/Makefile
+F: drivers/net/ethernet/renesas/ravb*
+
RENESAS ETHERNET SWITCH DRIVER
R: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
L: netdev@vger.kernel.org
@@ -19615,6 +19862,17 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/renesas,idt821034.yaml
F: sound/soc/codecs/idt821034.c
+RENESAS R-CAR & FSI AUDIO (ASoC) DRIVERS
+M: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+L: linux-sound@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/sound/renesas,rsnd.*
+F: Documentation/devicetree/bindings/sound/renesas,fsi.yaml
+F: sound/soc/renesas/rcar/
+F: sound/soc/renesas/fsi.c
+F: include/sound/sh_fsi.h
+
RENESAS R-CAR GEN3 & RZ/N1 NAND CONTROLLER DRIVER
M: Miquel Raynal <miquel.raynal@bootlin.com>
L: linux-mtd@lists.infradead.org
@@ -19639,6 +19897,14 @@ F: Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml
F: drivers/i2c/busses/i2c-rcar.c
F: drivers/i2c/busses/i2c-sh_mobile.c
+RENESAS R-CAR SATA DRIVER
+M: Geert Uytterhoeven <geert+renesas@glider.be>
+L: linux-ide@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/ata/renesas,rcar-sata.yaml
+F: drivers/ata/sata_rcar.c
+
RENESAS R-CAR THERMAL DRIVERS
M: Niklas Söderlund <niklas.soderlund@ragnatech.se>
L: linux-renesas-soc@vger.kernel.org
@@ -19655,6 +19921,15 @@ S: Supported
F: Documentation/devicetree/bindings/i2c/renesas,riic.yaml
F: drivers/i2c/busses/i2c-riic.c
+RENESAS RZ AUDIO (ASoC) DRIVER
+M: Biju Das <biju.das.jz@bp.renesas.com>
+M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+L: linux-sound@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
+F: sound/soc/renesas/rz-ssi.c
+
RENESAS RZ/G2L A/D DRIVER
M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
L: linux-iio@vger.kernel.org
@@ -19671,6 +19946,14 @@ S: Supported
F: Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
F: drivers/counter/rz-mtu3-cnt.c
+RENESAS RTCA-3 RTC DRIVER
+M: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+L: linux-rtc@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml
+F: drivers/rtc/rtc-renesas-rtca3.c
+
RENESAS RZ/N1 A5PSW SWITCH DRIVER
M: Clément Léger <clement.leger@bootlin.com>
L: linux-renesas-soc@vger.kernel.org
@@ -19714,6 +19997,17 @@ S: Supported
F: Documentation/devicetree/bindings/i2c/renesas,rzv2m.yaml
F: drivers/i2c/busses/i2c-rzv2m.c
+RENESAS SUPERH ETHERNET DRIVER
+M: Niklas Söderlund <niklas.soderlund@ragnatech.se>
+L: netdev@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/net/renesas,ether.yaml
+F: drivers/net/ethernet/renesas/Kconfig
+F: drivers/net/ethernet/renesas/Makefile
+F: drivers/net/ethernet/renesas/sh_eth*
+F: include/linux/sh_eth.h
+
RENESAS USB PHY DRIVER
M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
L: linux-renesas-soc@vger.kernel.org
@@ -19821,6 +20115,15 @@ F: arch/riscv/
N: riscv
K: riscv
+RISC-V IOMMU
+M: Tomasz Jeznach <tjeznach@rivosinc.com>
+L: iommu@lists.linux.dev
+L: linux-riscv@lists.infradead.org
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux.git
+F: Documentation/devicetree/bindings/iommu/riscv,iommu.yaml
+F: drivers/iommu/riscv/
+
RISC-V MICROCHIP FPGA SUPPORT
M: Conor Dooley <conor.dooley@microchip.com>
M: Daire McNamara <daire.mcnamara@microchip.com>
@@ -19840,6 +20143,7 @@ F: arch/riscv/boot/dts/microchip/
F: drivers/char/hw_random/mpfs-rng.c
F: drivers/clk/microchip/clk-mpfs*.c
F: drivers/firmware/microchip/mpfs-auto-update.c
+F: drivers/gpio/gpio-mpfs.c
F: drivers/i2c/busses/i2c-microchip-corei2c.c
F: drivers/mailbox/mailbox-mpfs.c
F: drivers/pci/controller/plda/pcie-microchip-host.c
@@ -19858,12 +20162,10 @@ L: linux-riscv@lists.infradead.org
S: Maintained
Q: https://patchwork.kernel.org/project/linux-riscv/list/
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
-F: Documentation/devicetree/bindings/riscv/
-F: arch/riscv/boot/dts/
-X: arch/riscv/boot/dts/allwinner/
-X: arch/riscv/boot/dts/renesas/
-X: arch/riscv/boot/dts/sophgo/
-X: arch/riscv/boot/dts/thead/
+F: arch/riscv/boot/dts/canaan/
+F: arch/riscv/boot/dts/microchip/
+F: arch/riscv/boot/dts/sifive/
+F: arch/riscv/boot/dts/starfive/
RISC-V PMU DRIVERS
M: Atish Patra <atishp@atishpatra.org>
@@ -19882,8 +20184,14 @@ L: linux-riscv@lists.infradead.org
S: Maintained
T: git https://github.com/pdp7/linux.git
F: Documentation/devicetree/bindings/clock/thead,th1520-clk-ap.yaml
+F: Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml
+F: Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml
+F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml
F: arch/riscv/boot/dts/thead/
F: drivers/clk/thead/clk-th1520-ap.c
+F: drivers/mailbox/mailbox-th1520.c
+F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
+F: drivers/pinctrl/pinctrl-th1520.c
F: include/dt-bindings/clock/thead,th1520-clk-ap.h
RNBD BLOCK DRIVERS
@@ -20048,9 +20356,8 @@ F: include/linux/mfd/rohm-generic.h
F: include/linux/mfd/rohm-shared.h
ROSE NETWORK LAYER
-M: Ralf Baechle <ralf@linux-mips.org>
L: linux-hams@vger.kernel.org
-S: Maintained
+S: Orphan
W: https://linux-ax25.in-berlin.de
F: include/net/rose.h
F: include/uapi/linux/rose.h
@@ -20060,7 +20367,7 @@ ROTATION DRIVER FOR ALLWINNER A83T
M: Jernej Skrabec <jernej.skrabec@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml
F: drivers/media/platform/sunxi/sun8i-rotate/
@@ -20124,6 +20431,13 @@ S: Maintained
T: git https://github.com/pkshih/rtw.git
F: drivers/net/wireless/realtek/rtl8xxxu/
+RTL9300 I2C DRIVER (rtl9300-i2c)
+M: Chris Packham <chris.packham@alliedtelesis.co.nz>
+L: linux-i2c@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml
+F: drivers/i2c/busses/i2c-rtl9300.c
+
RTRS TRANSPORT DRIVERS
M: Md. Haris Iqbal <haris.iqbal@ionos.com>
M: Jack Wang <jinpu.wang@ionos.com>
@@ -20158,13 +20472,22 @@ B: https://github.com/Rust-for-Linux/linux/issues
C: zulip://rust-for-linux.zulipchat.com
P: https://rust-for-linux.com/contributing
T: git https://github.com/Rust-for-Linux/linux.git rust-next
+F: .clippy.toml
F: Documentation/rust/
+F: include/trace/events/rust_sample.h
F: rust/
F: samples/rust/
F: scripts/*rust*
F: tools/testing/selftests/rust/
K: \b(?i:rust)\b
+RUST [ALLOC]
+M: Danilo Krummrich <dakr@kernel.org>
+L: rust-for-linux@vger.kernel.org
+S: Maintained
+F: rust/kernel/alloc.rs
+F: rust/kernel/alloc/
+
RXRPC SOCKETS (AF_RXRPC)
M: David Howells <dhowells@redhat.com>
M: Marc Dionne <marc.dionne@auristor.com>
@@ -20206,6 +20529,16 @@ L: linux-s390@vger.kernel.org
S: Supported
F: drivers/s390/cio/
+S390 CRYPTO MODULES, PRNG DRIVER, ARCH RANDOM
+M: Harald Freudenberger <freude@linux.ibm.com>
+M: Holger Dengler <dengler@linux.ibm.com>
+L: linux-crypto@vger.kernel.org
+L: linux-s390@vger.kernel.org
+S: Supported
+F: arch/s390/crypto/
+F: arch/s390/include/asm/archrandom.h
+F: arch/s390/include/asm/cpacf.h
+
S390 DASD DRIVER
M: Stefan Haberland <sth@linux.ibm.com>
M: Jan Hoeppner <hoeppner@linux.ibm.com>
@@ -20215,6 +20548,14 @@ F: block/partitions/ibm.c
F: drivers/s390/block/dasd*
F: include/linux/dasd_mod.h
+S390 HWRANDOM TRNG DRIVER
+M: Harald Freudenberger <freude@linux.ibm.com>
+M: Holger Dengler <dengler@linux.ibm.com>
+L: linux-crypto@vger.kernel.org
+L: linux-s390@vger.kernel.org
+S: Supported
+F: drivers/char/hw_random/s390-trng.c
+
S390 IOMMU (PCI)
M: Niklas Schnelle <schnelle@linux.ibm.com>
M: Matthew Rosato <mjrosato@linux.ibm.com>
@@ -20259,6 +20600,12 @@ F: Documentation/arch/s390/pci.rst
F: arch/s390/pci/
F: drivers/pci/hotplug/s390_pci_hpc.c
+S390 PTP DRIVER
+M: Sven Schnelle <svens@linux.ibm.com>
+L: linux-s390@vger.kernel.org
+S: Supported
+F: drivers/ptp/ptp_s390.c
+
S390 SCM DRIVER
M: Vineeth Vijayan <vneethv@linux.ibm.com>
L: linux-s390@vger.kernel.org
@@ -20296,10 +20643,16 @@ F: arch/s390/kvm/pci*
F: drivers/vfio/pci/vfio_pci_zdev.c
F: include/uapi/linux/vfio_zdev.h
-S390 ZCRYPT DRIVER
+S390 ZCRYPT AND PKEY DRIVER AND AP BUS
M: Harald Freudenberger <freude@linux.ibm.com>
+M: Holger Dengler <dengler@linux.ibm.com>
L: linux-s390@vger.kernel.org
S: Supported
+F: arch/s390/include/asm/ap.h
+F: arch/s390/include/asm/pkey.h
+F: arch/s390/include/asm/trace/zcrypt.h
+F: arch/s390/include/uapi/asm/pkey.h
+F: arch/s390/include/uapi/asm/zcrypt.h
F: drivers/s390/crypto/
S390 ZFCP DRIVER
@@ -20314,7 +20667,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/saa6588*
SAA7134 VIDEO4LINUX DRIVER
@@ -20322,7 +20675,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Odd fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/driver-api/media/drivers/saa7134*
F: drivers/media/pci/saa7134/
@@ -20330,7 +20683,7 @@ SAA7146 VIDEO4LINUX-2 DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/common/saa7146/
F: drivers/media/pci/saa7146/
F: include/media/drv-intf/saa7146*
@@ -20401,7 +20754,7 @@ L: linux-samsung-soc@vger.kernel.org
S: Maintained
B: mailto:linux-samsung-soc@vger.kernel.org
F: Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml
-F: Documentation/devicetree/bindings/mfd/samsung,s2m*.yaml
+F: Documentation/devicetree/bindings/mfd/samsung,s2*.yaml
F: Documentation/devicetree/bindings/mfd/samsung,s5m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s2m*.yaml
F: Documentation/devicetree/bindings/regulator/samsung,s5m*.yaml
@@ -20786,6 +21139,7 @@ Q: https://patchwork.kernel.org/project/linux-security-module/list
B: mailto:linux-security-module@vger.kernel.org
P: https://github.com/LinuxSecurityModule/kernel/blob/main/README.md
T: git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
+F: include/linux/lsm/
F: include/linux/lsm_audit.h
F: include/linux/lsm_hook_defs.h
F: include/linux/lsm_hooks.h
@@ -20932,6 +21286,7 @@ M: Jan Karcher <jaka@linux.ibm.com>
R: D. Wythe <alibuda@linux.alibaba.com>
R: Tony Lu <tonylu@linux.alibaba.com>
R: Wen Gu <guwen@linux.alibaba.com>
+L: linux-rdma@vger.kernel.org
L: linux-s390@vger.kernel.org
S: Supported
F: net/smc/
@@ -20948,7 +21303,7 @@ SHARP RJ54N1CB0C SENSOR DRIVER
M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
S: Odd fixes
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/rj54n1cb0c.c
F: include/media/i2c/rj54n1cb0c.h
@@ -20998,7 +21353,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/silabs,si470x.yaml
F: drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -21007,7 +21362,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/si470x/radio-si470x-common.c
F: drivers/media/radio/si470x/radio-si470x-usb.c
F: drivers/media/radio/si470x/radio-si470x.h
@@ -21017,7 +21372,7 @@ M: Eduardo Valentin <edubezval@gmail.com>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/si4713/si4713.?
SI4713 FM RADIO TRANSMITTER PLATFORM DRIVER
@@ -21025,7 +21380,7 @@ M: Eduardo Valentin <edubezval@gmail.com>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/si4713/radio-platform-si4713.c
SI4713 FM RADIO TRANSMITTER USB DRIVER
@@ -21033,7 +21388,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/si4713/radio-usb-si4713.c
SIANO DVB DRIVER
@@ -21041,23 +21396,23 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Odd fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/common/siano/
F: drivers/media/mmc/siano/
F: drivers/media/usb/siano/
F: drivers/media/usb/siano/
SIEMENS IPC LED DRIVERS
-M: Gerd Haeussler <gerd.haeussler.ext@siemens.com>
-M: Xing Tong Wu <xingtong.wu@siemens.com>
+M: Bao Cheng Su <baocheng.su@siemens.com>
+M: Benedikt Niedermayr <benedikt.niedermayr@siemens.com>
M: Tobias Schaffner <tobias.schaffner@siemens.com>
L: linux-leds@vger.kernel.org
S: Maintained
F: drivers/leds/simple/
SIEMENS IPC PLATFORM DRIVERS
-M: Gerd Haeussler <gerd.haeussler.ext@siemens.com>
-M: Xing Tong Wu <xingtong.wu@siemens.com>
+M: Bao Cheng Su <baocheng.su@siemens.com>
+M: Benedikt Niedermayr <benedikt.niedermayr@siemens.com>
M: Tobias Schaffner <tobias.schaffner@siemens.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
@@ -21066,8 +21421,8 @@ F: include/linux/platform_data/x86/simatic-ipc-base.h
F: include/linux/platform_data/x86/simatic-ipc.h
SIEMENS IPC WATCHDOG DRIVERS
-M: Gerd Haeussler <gerd.haeussler.ext@siemens.com>
-M: Xing Tong Wu <xingtong.wu@siemens.com>
+M: Bao Cheng Su <baocheng.su@siemens.com>
+M: Benedikt Niedermayr <benedikt.niedermayr@siemens.com>
M: Tobias Schaffner <tobias.schaffner@siemens.com>
L: linux-watchdog@vger.kernel.org
S: Maintained
@@ -21375,11 +21730,11 @@ F: include/linux/property.h
SOFTWARE RAID (Multiple Disks) SUPPORT
M: Song Liu <song@kernel.org>
-R: Yu Kuai <yukuai3@huawei.com>
+M: Yu Kuai <yukuai3@huawei.com>
L: linux-raid@vger.kernel.org
S: Supported
Q: https://patchwork.kernel.org/project/linux-raid/list/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/song/md.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux.git
F: drivers/md/Kconfig
F: drivers/md/Makefile
F: drivers/md/md*
@@ -21417,14 +21772,14 @@ SONY IMX208 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/imx208.c
SONY IMX214 SENSOR DRIVER
M: Ricardo Ribalda <ribalda@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml
F: drivers/media/i2c/imx214.c
@@ -21432,7 +21787,7 @@ SONY IMX219 SENSOR DRIVER
M: Dave Stevenson <dave.stevenson@raspberrypi.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/imx219.yaml
F: drivers/media/i2c/imx219.c
@@ -21440,7 +21795,7 @@ SONY IMX258 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
F: drivers/media/i2c/imx258.c
@@ -21448,7 +21803,7 @@ SONY IMX274 SENSOR DRIVER
M: Leon Luo <leonl@leopardimaging.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml
F: drivers/media/i2c/imx274.c
@@ -21457,7 +21812,7 @@ M: Kieran Bingham <kieran.bingham@ideasonboard.com>
M: Umang Jain <umang.jain@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml
F: drivers/media/i2c/imx283.c
@@ -21465,7 +21820,7 @@ SONY IMX290 SENSOR DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml
F: drivers/media/i2c/imx290.c
@@ -21474,7 +21829,7 @@ M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx296.yaml
F: drivers/media/i2c/imx296.c
@@ -21482,20 +21837,20 @@ SONY IMX319 SENSOR DRIVER
M: Bingbu Cao <bingbu.cao@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/imx319.c
SONY IMX334 SENSOR DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
F: drivers/media/i2c/imx334.c
SONY IMX335 SENSOR DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
F: drivers/media/i2c/imx335.c
@@ -21503,13 +21858,13 @@ SONY IMX355 SENSOR DRIVER
M: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/imx355.c
SONY IMX412 SENSOR DRIVER
L: linux-media@vger.kernel.org
S: Orphan
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c
@@ -21517,7 +21872,7 @@ SONY IMX415 SENSOR DRIVER
M: Michael Riesch <michael.riesch@wolfvision.net>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
F: drivers/media/i2c/imx415.c
@@ -21630,6 +21985,15 @@ S: Supported
W: https://github.com/thesofproject/linux/
F: sound/soc/sof/
+SOUND - GENERIC SOUND CARD (Simple-Audio-Card, Audio-Graph-Card)
+M: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+S: Supported
+L: linux-sound@vger.kernel.org
+F: sound/soc/generic/
+F: include/sound/simple_card*
+F: Documentation/devicetree/bindings/sound/simple-card.yaml
+F: Documentation/devicetree/bindings/sound/audio-graph*.yaml
+
SOUNDWIRE SUBSYSTEM
M: Vinod Koul <vkoul@kernel.org>
M: Bard Liao <yung-chuan.liao@linux.intel.com>
@@ -21797,7 +22161,7 @@ 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
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml
F: drivers/media/i2c/st-mipid02.c
@@ -21833,7 +22197,7 @@ 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
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml
F: Documentation/userspace-api/media/drivers/vgxy61.rst
F: drivers/media/i2c/vgxy61.c
@@ -21860,17 +22224,6 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/staging/media/atomisp/
-STAGING - FIELDBUS SUBSYSTEM
-M: Sven Van Asbroeck <TheSven73@gmail.com>
-S: Maintained
-F: drivers/staging/fieldbus/*
-F: drivers/staging/fieldbus/Documentation/
-
-STAGING - HMS ANYBUS-S BUS
-M: Sven Van Asbroeck <TheSven73@gmail.com>
-S: Maintained
-F: drivers/staging/fieldbus/anybuss/
-
STAGING - INDUSTRIAL IO
M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org
@@ -21885,18 +22238,6 @@ L: linux-tegra@vger.kernel.org
S: Maintained
F: drivers/staging/nvec/
-STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
-M: Jens Frederich <jfrederich@gmail.com>
-M: Jon Nettleton <jon.nettleton@gmail.com>
-S: Maintained
-W: http://wiki.laptop.org/go/DCON
-F: drivers/staging/olpc_dcon/
-
-STAGING - REALTEK RTL8712U DRIVERS
-M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
-S: Odd Fixes
-F: drivers/staging/rtl8712/
-
STAGING - SEPS525 LCD CONTROLLER DRIVERS
M: Michael Hennerich <michael.hennerich@analog.com>
L: linux-fbdev@vger.kernel.org
@@ -21912,11 +22253,6 @@ L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/staging/sm750fb/
-STAGING - VIA VT665X DRIVERS
-M: Philipp Hortmann <philipp.g.hortmann@gmail.com>
-S: Odd Fixes
-F: drivers/staging/vt665?/
-
STAGING SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-staging@lists.linux.dev
@@ -22123,7 +22459,7 @@ STK1160 USB VIDEO CAPTURE DRIVER
M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/stk1160/
STM32 AUDIO (ASoC) DRIVERS
@@ -22153,6 +22489,12 @@ F: drivers/*/stm32-*timer*
F: drivers/pwm/pwm-stm32*
F: include/linux/*/stm32-*tim*
+STM32MP25 USB3/PCIE COMBOPHY DRIVER
+M: Christian Bruel <christian.bruel@foss.st.com>
+S: Maintained
+F: Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml
+F: drivers/phy/st/phy-stm32-combophy.c
+
STMMAC ETHERNET DRIVER
M: Alexandre Torgue <alexandre.torgue@foss.st.com>
M: Jose Abreu <joabreu@synopsys.com>
@@ -22183,12 +22525,6 @@ S: Maintained
F: Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
F: drivers/input/keyboard/sun4i-lradc-keys.c
-SUNDANCE NETWORK DRIVER
-M: Denis Kirjanov <kda@linux-powerpc.org>
-L: netdev@vger.kernel.org
-S: Maintained
-F: drivers/net/ethernet/dlink/sundance.c
-
SUNPLUS ETHERNET DRIVER
M: Wells Lu <wellslutw@gmail.com>
L: netdev@vger.kernel.org
@@ -22560,7 +22896,7 @@ L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/tuners/tda18250*
TDA18271 MEDIA DRIVER
@@ -22606,7 +22942,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/tda9840*
TEA5761 TUNER DRIVER
@@ -22614,7 +22950,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Odd fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/tuners/tea5761.*
TEA5767 TUNER DRIVER
@@ -22622,7 +22958,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/tuners/tea5767.*
TEA6415C MEDIA DRIVER
@@ -22630,7 +22966,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/tea6415c*
TEA6420 MEDIA DRIVER
@@ -22638,7 +22974,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/i2c/tea6420*
TEAM DRIVER
@@ -22874,6 +23210,12 @@ F: include/linux/dma/k3-udma-glue.h
F: include/linux/dma/ti-cppi5.h
X: drivers/dma/ti/cppi41.c
+TEXAS INSTRUMENTS TPS25990 HARDWARE MONITOR DRIVER
+M: Jerome Brunet <jbrunet@baylibre.com>
+L: linux-hwmon@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml
+
TEXAS INSTRUMENTS TPS23861 PoE PSE DRIVER
M: Robert Marko <robert.marko@sartura.hr>
M: Luka Perkov <luka.perkov@sartura.hr>
@@ -22926,7 +23268,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/radio/radio-raremono.c
THERMAL
@@ -23002,7 +23344,7 @@ M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Paul Elder <paul.elder@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/i2c/thine,thp7312.yaml
F: Documentation/userspace-api/media/drivers/thp7312.rst
F: drivers/media/i2c/thp7312.c
@@ -23181,7 +23523,7 @@ F: Documentation/devicetree/bindings/net/ti,icss*.yaml
F: drivers/net/ethernet/ti/icssg/*
TI J721E CSI2RX DRIVER
-M: Jai Luthra <j-luthra@ti.com>
+M: Jai Luthra <jai.luthra@linux.dev>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
@@ -23559,10 +23901,9 @@ F: drivers/net/tun.c
TURBOCHANNEL SUBSYSTEM
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
-M: Ralf Baechle <ralf@linux-mips.org>
L: linux-mips@vger.kernel.org
S: Maintained
-Q: http://patchwork.linux-mips.org/project/linux-mips/list/
+Q: https://patchwork.kernel.org/project/linux-mips/list/
F: drivers/tc/
F: include/linux/tc.h
@@ -23589,7 +23930,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Odd Fixes
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/pci/tw68/
TW686X VIDEO4LINUX DRIVER
@@ -23597,7 +23938,7 @@ M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
L: linux-media@vger.kernel.org
S: Maintained
W: http://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/pci/tw686x/
U-BOOT ENVIRONMENT VARIABLES
@@ -23699,6 +24040,7 @@ UNICODE SUBSYSTEM
M: Gabriel Krisman Bertazi <krisman@kernel.org>
L: linux-fsdevel@vger.kernel.org
S: Supported
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/krisman/unicode.git
F: fs/unicode/
UNIFDEF
@@ -23742,7 +24084,9 @@ F: drivers/ufs/host/*dwc*
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER EXYNOS HOOKS
M: Alim Akhtar <alim.akhtar@samsung.com>
+R: Peter Griffin <peter.griffin@linaro.org>
L: linux-scsi@vger.kernel.org
+L: linux-samsung-soc@vger.kernel.org
S: Maintained
F: drivers/ufs/host/ufs-exynos*
@@ -24069,6 +24413,13 @@ L: linux-usb@vger.kernel.org
S: Orphan
F: drivers/usb/typec/tcpm/
+USB TYPEC TUSB1046 MUX DRIVER
+M: Romain Gantois <romain.gantois@bootlin.com>
+L: linux-usb@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/usb/ti,tusb1046.yaml
+F: drivers/usb/typec/mux/tusb1046.c
+
USB UHCI DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org
@@ -24077,10 +24428,11 @@ F: drivers/usb/host/uhci*
USB VIDEO CLASS
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+M: Hans de Goede <hdegoede@redhat.com>
L: linux-media@vger.kernel.org
S: Maintained
W: http://www.ideasonboard.org/uvc/
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/usb/uvc/
F: include/uapi/linux/uvcvideo.h
@@ -24187,7 +24539,7 @@ V4L2 ASYNC AND FWNODE FRAMEWORKS
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/v4l2-core/v4l2-async.c
F: drivers/media/v4l2-core/v4l2-fwnode.c
F: include/media/v4l2-async.h
@@ -24353,7 +24705,7 @@ M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/test-drivers/vicodec/*
VIDEO I2C POLLING DRIVER
@@ -24381,7 +24733,7 @@ M: Daniel W. S. Almeida <dwlsalmeida@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/test-drivers/vidtv/*
VIMC VIRTUAL MEDIA CONTROLLER DRIVER
@@ -24390,7 +24742,7 @@ R: Kieran Bingham <kieran.bingham@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/test-drivers/vimc/*
VIRT LIB
@@ -24621,6 +24973,18 @@ S: Maintained
F: drivers/input/serio/userio.c
F: include/uapi/linux/userio.h
+VISHAY VEML3235 AMBIENT LIGHT SENSOR DRIVER
+M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+S: Maintained
+F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
+F: drivers/iio/light/veml3235.c
+
+VISHAY VEML6030 AMBIENT LIGHT SENSOR DRIVER
+M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+S: Maintained
+F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
+F: drivers/iio/light/veml6030.c
+
VISHAY VEML6075 UVA AND UVB LIGHT SENSOR DRIVER
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
S: Maintained
@@ -24638,7 +25002,7 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/test-drivers/vivid/*
VM SOCKETS (AF_VSOCK)
@@ -25192,7 +25556,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
W: https://linuxtv.org
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: drivers/media/tuners/xc2028.*
XDP (eXpress Data Path)
@@ -25416,7 +25780,7 @@ XILINX VIDEO IP CORES
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Supported
-T: git git://linuxtv.org/media_tree.git
+T: git git://linuxtv.org/media.git
F: Documentation/devicetree/bindings/media/xilinx/
F: drivers/media/platform/xilinx/
F: include/uapi/linux/xilinx-v4l2-controls.h
diff --git a/Makefile b/Makefile
index b8efbfe9da94..93ab62cef244 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
-PATCHLEVEL = 12
+PATCHLEVEL = 13
SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc1
NAME = Baby Opossum Posse
# *DOCUMENTATION*
@@ -40,7 +40,7 @@ __all:
this-makefile := $(lastword $(MAKEFILE_LIST))
abs_srctree := $(realpath $(dir $(this-makefile)))
-abs_objtree := $(CURDIR)
+abs_output := $(CURDIR)
ifneq ($(sub_make_done),1)
@@ -134,6 +134,10 @@ ifeq ("$(origin M)", "command line")
KBUILD_EXTMOD := $(M)
endif
+ifeq ("$(origin MO)", "command line")
+ KBUILD_EXTMOD_OUTPUT := $(MO)
+endif
+
$(if $(word 2, $(KBUILD_EXTMOD)), \
$(error building multiple external modules is not supported))
@@ -176,18 +180,41 @@ export KBUILD_EXTRA_WARN
# The O= assignment takes precedence over the KBUILD_OUTPUT environment
# variable.
-# Do we want to change the working directory?
ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
-ifneq ($(KBUILD_OUTPUT),)
+ifdef KBUILD_EXTMOD
+ ifdef KBUILD_OUTPUT
+ objtree := $(realpath $(KBUILD_OUTPUT))
+ $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
+ else
+ objtree := $(abs_srctree)
+ endif
+ # If Make is invoked from the kernel directory (either kernel
+ # source directory or kernel build directory), external modules
+ # are built in $(KBUILD_EXTMOD) for backward compatibility,
+ # otherwise, built in the current directory.
+ output := $(or $(KBUILD_EXTMOD_OUTPUT),$(if $(filter $(CURDIR),$(objtree) $(abs_srctree)),$(KBUILD_EXTMOD)))
+ # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
+ # Make changes the working directory.
+ srcroot := $(realpath $(KBUILD_EXTMOD))
+ $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
+else
+ objtree := .
+ output := $(KBUILD_OUTPUT)
+endif
+
+export objtree srcroot
+
+# Do we want to change the working directory?
+ifneq ($(output),)
# $(realpath ...) gets empty if the path does not exist. Run 'mkdir -p' first.
-$(shell mkdir -p "$(KBUILD_OUTPUT)")
+$(shell mkdir -p "$(output)")
# $(realpath ...) resolves symlinks
-abs_objtree := $(realpath $(KBUILD_OUTPUT))
-$(if $(abs_objtree),,$(error failed to create output directory "$(KBUILD_OUTPUT)"))
-endif # ifneq ($(KBUILD_OUTPUT),)
+abs_output := $(realpath $(output))
+$(if $(abs_output),,$(error failed to create output directory "$(output)"))
+endif
ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
$(error source directory cannot contain spaces or colons)
@@ -197,7 +224,7 @@ export sub_make_done := 1
endif # sub_make_done
-ifeq ($(abs_objtree),$(CURDIR))
+ifeq ($(abs_output),$(CURDIR))
# Suppress "Entering directory ..." if we are at the final work directory.
no-print-directory := --no-print-directory
else
@@ -221,43 +248,41 @@ $(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make
# Invoke a second make in the output directory, passing relevant variables
__sub-make:
- $(Q)$(MAKE) $(no-print-directory) -C $(abs_objtree) \
+ $(Q)$(MAKE) $(no-print-directory) -C $(abs_output) \
-f $(abs_srctree)/Makefile $(MAKECMDGOALS)
else # need-sub-make
# We process the rest of the Makefile if this is the final invocation of make
-ifeq ($(abs_srctree),$(abs_objtree))
- # building in the source tree
- srctree := .
- building_out_of_srctree :=
-else
- ifeq ($(abs_srctree)/,$(dir $(abs_objtree)))
- # building in a subdirectory of the source tree
- srctree := ..
- else
- srctree := $(abs_srctree)
- endif
- building_out_of_srctree := 1
+ifndef KBUILD_EXTMOD
+srcroot := $(abs_srctree)
endif
-ifneq ($(KBUILD_ABS_SRCTREE),)
-srctree := $(abs_srctree)
+ifeq ($(srcroot),$(CURDIR))
+building_out_of_srctree :=
+else
+export building_out_of_srctree := 1
endif
-objtree := .
+ifdef KBUILD_ABS_SRCTREE
+ # Do nothing. Use the absolute path.
+else ifeq ($(srcroot),$(CURDIR))
+ # Building in the source.
+ srcroot := .
+else ifeq ($(srcroot)/,$(dir $(CURDIR)))
+ # Building in a subdirectory of the source.
+ srcroot := ..
+endif
-VPATH :=
+export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
-ifeq ($(KBUILD_EXTMOD),)
ifdef building_out_of_srctree
-VPATH := $(srctree)
-endif
+export VPATH := $(srcroot)
+else
+VPATH :=
endif
-export building_out_of_srctree srctree objtree VPATH
-
# To make sure we do not include .config for any of the *config targets
# catch them early, and hand them over to scripts/kconfig/Makefile
# It is allowed to specify more targets when calling make, including
@@ -276,7 +301,7 @@ no-dot-config-targets := $(clean-targets) \
outputmakefile rustavailable rustfmt rustfmtcheck
no-sync-config-targets := $(no-dot-config-targets) %install modules_sign kernelrelease \
image_name
-single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %.symtypes %/
+single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %/
config-build :=
mixed-build :=
@@ -354,7 +379,7 @@ else # !mixed-build
include $(srctree)/scripts/Kbuild.include
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
-KERNELRELEASE = $(call read-file, include/config/kernel.release)
+KERNELRELEASE = $(call read-file, $(objtree)/include/config/kernel.release)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
@@ -446,18 +471,23 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
export rust_common_flags := --edition=2021 \
-Zbinary_dep_depinfo=y \
-Astable_features \
- -Dunsafe_op_in_unsafe_fn \
-Dnon_ascii_idents \
+ -Dunsafe_op_in_unsafe_fn \
+ -Wmissing_docs \
-Wrust_2018_idioms \
-Wunreachable_pub \
- -Wmissing_docs \
- -Wrustdoc::missing_crate_level_docs \
-Wclippy::all \
+ -Wclippy::ignored_unit_patterns \
-Wclippy::mut_mut \
-Wclippy::needless_bitwise_bool \
-Wclippy::needless_continue \
+ -Aclippy::needless_lifetimes \
-Wclippy::no_mangle_with_rust_abi \
- -Wclippy::dbg_macro
+ -Wclippy::undocumented_unsafe_blocks \
+ -Wclippy::unnecessary_safety_comment \
+ -Wclippy::unnecessary_safety_doc \
+ -Wrustdoc::missing_crate_level_docs \
+ -Wrustdoc::unescaped_backticks
KBUILD_HOSTCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(HOST_LFS_CFLAGS) \
$(HOSTCFLAGS) -I $(srctree)/scripts/include
@@ -508,7 +538,7 @@ KGZIP = gzip
KBZIP2 = bzip2
KLZOP = lzop
LZMA = lzma
-LZ4 = lz4c
+LZ4 = lz4
XZ = xz
ZSTD = zstd
@@ -538,7 +568,7 @@ USERINCLUDE := \
LINUXINCLUDE := \
-I$(srctree)/arch/$(SRCARCH)/include \
-I$(objtree)/arch/$(SRCARCH)/include/generated \
- $(if $(building_out_of_srctree),-I$(srctree)/include) \
+ -I$(srctree)/include \
-I$(objtree)/include \
$(USERINCLUDE)
@@ -582,6 +612,9 @@ endif
# Allows the usage of unstable features in stable compilers.
export RUSTC_BOOTSTRAP := 1
+# Allows finding `.clippy.toml` in out-of-srctree builds.
+export CLIPPY_CONF_DIR := $(srctree)
+
export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN
export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
@@ -621,13 +654,25 @@ ifdef building_out_of_srctree
# At the same time when output Makefile generated, generate .gitignore to
# ignore whole output directory
+ifdef KBUILD_EXTMOD
+print_env_for_makefile = \
+ echo "export KBUILD_OUTPUT = $(objtree)"; \
+ echo "export KBUILD_EXTMOD = $(realpath $(srcroot))" ; \
+ echo "export KBUILD_EXTMOD_OUTPUT = $(CURDIR)"
+else
+print_env_for_makefile = \
+ echo "export KBUILD_OUTPUT = $(CURDIR)"
+endif
+
quiet_cmd_makefile = GEN Makefile
cmd_makefile = { \
- echo "\# Automatically generated by $(srctree)/Makefile: don't edit"; \
- echo "include $(srctree)/Makefile"; \
+ echo "\# Automatically generated by $(abs_srctree)/Makefile: don't edit"; \
+ $(print_env_for_makefile); \
+ echo "include $(abs_srctree)/Makefile"; \
} > Makefile
outputmakefile:
+ifeq ($(KBUILD_EXTMOD),)
@if [ -f $(srctree)/.config -o \
-d $(srctree)/include/config -o \
-d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \
@@ -637,7 +682,16 @@ outputmakefile:
echo >&2 "***"; \
false; \
fi
- $(Q)ln -fsn $(srctree) source
+else
+ @if [ -f $(srcroot)/modules.order ]; then \
+ echo >&2 "***"; \
+ echo >&2 "*** The external module source tree is not clean."; \
+ echo >&2 "*** Please run 'make -C $(abs_srctree) M=$(realpath $(srcroot)) clean'"; \
+ echo >&2 "***"; \
+ false; \
+ fi
+endif
+ $(Q)ln -fsn $(srcroot) source
$(call cmd,makefile)
$(Q)test -e .gitignore || \
{ echo "# this is build directory, ignore it"; echo "*"; } > .gitignore
@@ -709,7 +763,7 @@ endif
# in addition to whatever we do anyway.
# Just "make" or "make all" shall build modules as well
-ifneq ($(filter all modules nsdeps %compile_commands.json clang-%,$(MAKECMDGOALS)),)
+ifneq ($(filter all modules nsdeps compile_commands.json clang-%,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1
endif
@@ -720,7 +774,7 @@ endif
export KBUILD_MODULES KBUILD_BUILTIN
ifdef need-config
-include include/config/auto.conf
+include $(objtree)/include/config/auto.conf
endif
ifeq ($(KBUILD_EXTMOD),)
@@ -781,17 +835,22 @@ $(KCONFIG_CONFIG):
else # !may-sync-config
# External modules and some install targets need include/generated/autoconf.h
# and include/config/auto.conf but do not care if they are up-to-date.
-# Use auto.conf to trigger the test
-PHONY += include/config/auto.conf
-
-include/config/auto.conf:
- @test -e include/generated/autoconf.h -a -e $@ || ( \
- echo >&2; \
- echo >&2 " ERROR: Kernel configuration is invalid."; \
- echo >&2 " include/generated/autoconf.h or $@ are missing.";\
- echo >&2 " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
- echo >&2 ; \
- /bin/false)
+# Use auto.conf to show the error message
+
+checked-configs := $(addprefix $(objtree)/, include/generated/autoconf.h include/generated/rustc_cfg include/config/auto.conf)
+missing-configs := $(filter-out $(wildcard $(checked-configs)), $(checked-configs))
+
+ifdef missing-configs
+PHONY += $(objtree)/include/config/auto.conf
+
+$(objtree)/include/config/auto.conf:
+ @echo >&2 '***'
+ @echo >&2 '*** ERROR: Kernel configuration is invalid. The following files are missing:'
+ @printf >&2 '*** - %s\n' $(missing-configs)
+ @echo >&2 '*** Run "make oldconfig && make prepare" on kernel source to fix it.'
+ @echo >&2 '***'
+ @/bin/false
+endif
endif # may-sync-config
endif # need-config
@@ -1005,8 +1064,10 @@ ifdef CONFIG_CC_IS_GCC
KBUILD_CFLAGS += -fconserve-stack
endif
-# change __FILE__ to the relative path from the srctree
-KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
+# change __FILE__ to the relative path to the source directory
+ifdef building_out_of_srctree
+KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srcroot)/=)
+endif
# include additional Makefiles when needed
include-y := scripts/Makefile.extrawarn
@@ -1018,6 +1079,8 @@ include-$(CONFIG_KMSAN) += scripts/Makefile.kmsan
include-$(CONFIG_UBSAN) += scripts/Makefile.ubsan
include-$(CONFIG_KCOV) += scripts/Makefile.kcov
include-$(CONFIG_RANDSTRUCT) += scripts/Makefile.randstruct
+include-$(CONFIG_AUTOFDO_CLANG) += scripts/Makefile.autofdo
+include-$(CONFIG_PROPELLER_CLANG) += scripts/Makefile.propeller
include-$(CONFIG_GCC_PLUGINS) += scripts/Makefile.gcc-plugins
include $(addprefix $(srctree)/, $(include-y))
@@ -1098,10 +1161,6 @@ export MODLIB
PHONY += prepare0
-export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
-export MODORDER := $(extmod_prefix)modules.order
-export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
-
ifeq ($(KBUILD_EXTMOD),)
build-dir := .
@@ -1196,7 +1255,8 @@ PHONY += prepare archprepare
archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \
asm-generic $(version_h) include/generated/utsrelease.h \
- include/generated/compile.h include/generated/autoconf.h remove-stale-files
+ include/generated/compile.h include/generated/autoconf.h \
+ include/generated/rustc_cfg remove-stale-files
prepare0: archprepare
$(Q)$(MAKE) $(build)=scripts/mod
@@ -1427,6 +1487,10 @@ ifdef CONFIG_OF_EARLY_FLATTREE
all: dtbs
endif
+ifdef CONFIG_GENERIC_BUILTIN_DTB
+vmlinux: dtbs
+endif
+
endif
PHONY += scripts_dtc
@@ -1494,7 +1558,8 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
modules.builtin modules.builtin.modinfo modules.nsdeps \
modules.builtin.ranges vmlinux.o.map \
compile_commands.json rust/test \
- rust-project.json .vmlinux.objs .vmlinux.export.c
+ rust-project.json .vmlinux.objs .vmlinux.export.c \
+ .builtin-dtbs-list .builtin-dtb.S
# Directories & files removed with 'make mrproper'
MRPROPER_FILES += include/config include/generated \
@@ -1602,7 +1667,6 @@ help:
@echo ' with a stack size larger than MINSTACKSIZE (default: 100)'
@echo ' versioncheck - Sanity check on version.h usage'
@echo ' includecheck - Check for duplicate included header files'
- @echo ' export_report - List the usages of all exported symbols'
@echo ' headerdep - Detect inclusion cycles in headers'
@echo ' coccicheck - Check with Coccinelle'
@echo ' clang-analyzer - Check with clang static analyzer'
@@ -1743,18 +1807,9 @@ rusttest: prepare
# Formatting targets
PHONY += rustfmt rustfmtcheck
-# We skip `rust/alloc` since we want to minimize the diff w.r.t. upstream.
-#
-# We match using absolute paths since `find` does not resolve them
-# when matching, which is a problem when e.g. `srctree` is `..`.
-# We `grep` afterwards in order to remove the directory entry itself.
rustfmt:
- $(Q)find $(abs_srctree) -type f -name '*.rs' \
- -o -path $(abs_srctree)/rust/alloc -prune \
- -o -path $(abs_objtree)/rust/test -prune \
- | grep -Fv $(abs_srctree)/rust/alloc \
- | grep -Fv $(abs_objtree)/rust/test \
- | grep -Fv generated \
+ $(Q)find $(srctree) $(RCS_FIND_IGNORE) \
+ -type f -a -name '*.rs' -a ! -name '*generated*' -print \
| xargs $(RUSTFMT) $(rustfmt_flags)
rustfmtcheck: rustfmt_flags = --check
@@ -1793,14 +1848,10 @@ filechk_kernel.release = echo $(KERNELRELEASE)
KBUILD_BUILTIN :=
KBUILD_MODULES := 1
-build-dir := $(KBUILD_EXTMOD)
+build-dir := .
-compile_commands.json: $(extmod_prefix)compile_commands.json
-PHONY += compile_commands.json
-
-clean-dirs := $(KBUILD_EXTMOD)
-clean: private rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
- $(KBUILD_EXTMOD)/compile_commands.json
+clean-dirs := .
+clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
PHONY += prepare
# now expand this into a simple variable to reduce the cost of shell evaluations
@@ -1859,7 +1910,7 @@ endif
ifdef CONFIG_MODULES
-$(MODORDER): $(build-dir)
+modules.order: $(build-dir)
@:
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
@@ -1870,7 +1921,7 @@ ifneq ($(KBUILD_MODPOST_NOFINAL),1)
endif
PHONY += modules_check
-modules_check: $(MODORDER)
+modules_check: modules.order
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh $<
else # CONFIG_MODULES
@@ -1911,15 +1962,15 @@ $(single-ko): single_modules
$(single-no-ko): $(build-dir)
@:
-# Remove MODORDER when done because it is not the real one.
+# Remove modules.order when done because it is not the real one.
PHONY += single_modules
single_modules: $(single-no-ko) modules_prepare
- $(Q){ $(foreach m, $(single-ko), echo $(extmod_prefix)$(m:%.ko=%.o);) } > $(MODORDER)
+ $(Q){ $(foreach m, $(single-ko), echo $(m:%.ko=%.o);) } > modules.order
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
endif
- $(Q)rm -f $(MODORDER)
+ $(Q)rm -f modules.order
single-goals := $(addprefix $(build-dir)/, $(single-no-ko))
@@ -1927,6 +1978,8 @@ KBUILD_MODULES := 1
endif
+prepare: outputmakefile
+
# Preset locale variables to speed up the build process. Limit locale
# tweaks to this spot to avoid wrong language settings when running
# make menuconfig etc.
@@ -1942,7 +1995,7 @@ $(clean-dirs):
clean: $(clean-dirs)
$(call cmd,rmfiles)
- @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+ @find . $(RCS_FIND_IGNORE) \
\( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '*.ko.*' \
-o -name '*.dtb' -o -name '*.dtbo' \
@@ -1975,7 +2028,12 @@ tags TAGS cscope gtags: FORCE
PHONY += rust-analyzer
rust-analyzer:
+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
+ifdef KBUILD_EXTMOD
+# FIXME: external modules must not descend into a sub-directory of the kernel
+ $(Q)$(MAKE) $(build)=$(objtree)/rust src=$(srctree)/rust $@
+else
$(Q)$(MAKE) $(build)=rust $@
+endif
# Script to generate missing namespace dependencies
# ---------------------------------------------------------------------------
@@ -1991,12 +2049,12 @@ nsdeps: modules
quiet_cmd_gen_compile_commands = GEN $@
cmd_gen_compile_commands = $(PYTHON3) $< -a $(AR) -o $@ $(filter-out $<, $(real-prereqs))
-$(extmod_prefix)compile_commands.json: $(srctree)/scripts/clang-tools/gen_compile_commands.py \
+compile_commands.json: $(srctree)/scripts/clang-tools/gen_compile_commands.py \
$(if $(KBUILD_EXTMOD),, vmlinux.a $(KBUILD_VMLINUX_LIBS)) \
- $(if $(CONFIG_MODULES), $(MODORDER)) FORCE
+ $(if $(CONFIG_MODULES), modules.order) FORCE
$(call if_changed,gen_compile_commands)
-targets += $(extmod_prefix)compile_commands.json
+targets += compile_commands.json
PHONY += clang-tidy clang-analyzer
@@ -2004,7 +2062,7 @@ ifdef CONFIG_CC_IS_CLANG
quiet_cmd_clang_tools = CHECK $<
cmd_clang_tools = $(PYTHON3) $(srctree)/scripts/clang-tools/run-clang-tools.py $@ $<
-clang-tidy clang-analyzer: $(extmod_prefix)compile_commands.json
+clang-tidy clang-analyzer: compile_commands.json
$(call cmd,clang_tools)
else
clang-tidy clang-analyzer:
@@ -2015,7 +2073,7 @@ endif
# Scripts to check various things for consistency
# ---------------------------------------------------------------------------
-PHONY += includecheck versioncheck coccicheck export_report
+PHONY += includecheck versioncheck coccicheck
includecheck:
find $(srctree)/* $(RCS_FIND_IGNORE) \
@@ -2030,9 +2088,6 @@ versioncheck:
coccicheck:
$(Q)$(BASH) $(srctree)/scripts/$@
-export_report:
- $(PERL) $(srctree)/scripts/export_report.pl
-
PHONY += checkstack kernelrelease kernelversion image_name
# UML needs a little special treatment here. It wants to use the host
diff --git a/arch/Kconfig b/arch/Kconfig
index bd9f095d69fa..6682b2a53e34 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -135,6 +135,7 @@ config KPROBES_ON_FTRACE
config UPROBES
def_bool n
depends on ARCH_SUPPORTS_UPROBES
+ select TASKS_TRACE_RCU
help
Uprobes is the user-space counterpart to kprobes: they
enable instrumentation applications (such as 'perf probe')
@@ -811,6 +812,45 @@ config LTO_CLANG_THIN
If unsure, say Y.
endchoice
+config ARCH_SUPPORTS_AUTOFDO_CLANG
+ bool
+
+config AUTOFDO_CLANG
+ bool "Enable Clang's AutoFDO build (EXPERIMENTAL)"
+ depends on ARCH_SUPPORTS_AUTOFDO_CLANG
+ depends on CC_IS_CLANG && CLANG_VERSION >= 170000
+ help
+ This option enables Clang’s AutoFDO build. When
+ an AutoFDO profile is specified in variable
+ CLANG_AUTOFDO_PROFILE during the build process,
+ Clang uses the profile to optimize the kernel.
+
+ If no profile is specified, AutoFDO options are
+ still passed to Clang to facilitate the collection
+ of perf data for creating an AutoFDO profile in
+ subsequent builds.
+
+ If unsure, say N.
+
+config ARCH_SUPPORTS_PROPELLER_CLANG
+ bool
+
+config PROPELLER_CLANG
+ bool "Enable Clang's Propeller build"
+ depends on ARCH_SUPPORTS_PROPELLER_CLANG
+ depends on CC_IS_CLANG && CLANG_VERSION >= 190000
+ help
+ This option enables Clang’s Propeller build. When the Propeller
+ profiles is specified in variable CLANG_PROPELLER_PROFILE_PREFIX
+ during the build process, Clang uses the profiles to optimize
+ the kernel.
+
+ If no profile is specified, Propeller options are still passed
+ to Clang to facilitate the collection of perf data for creating
+ the Propeller profiles in subsequent builds.
+
+ If unsure, say N.
+
config ARCH_SUPPORTS_CFI_CLANG
bool
help
@@ -1024,6 +1064,14 @@ config ARCH_WANTS_EXECMEM_LATE
enough entropy for module space randomization, for instance
arm64.
+config ARCH_HAS_EXECMEM_ROX
+ bool
+ depends on MMU && !HIGHMEM
+ help
+ For architectures that support allocations of executable memory
+ with read-only execute permissions. Architecture must implement
+ execmem_fill_trapping_insns() callback to enable this.
+
config HAVE_IRQ_EXIT_ON_IRQ_STACK
bool
help
@@ -1528,7 +1576,7 @@ config HAVE_SPARSE_SYSCALL_NR
entries at 4000, 5000 and 6000 locations. This option turns on syscall
related optimizations for a given architecture.
-config ARCH_HAS_VDSO_DATA
+config ARCH_HAS_VDSO_TIME_DATA
bool
config HAVE_STATIC_CALL
@@ -1682,4 +1730,10 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT
config ARCH_NEED_CMPXCHG_1_EMU
bool
+config ARCH_WANTS_PRE_LINK_VMLINUX
+ bool
+ help
+ An architecture can select this if it provides arch/<arch>/tools/Makefile
+ with .arch.vmlinux.o target to be linked into vmlinux.
+
endmenu
diff --git a/arch/alpha/configs/defconfig b/arch/alpha/configs/defconfig
index 1816c1dc22b1..3280bd9e6578 100644
--- a/arch/alpha/configs/defconfig
+++ b/arch/alpha/configs/defconfig
@@ -51,7 +51,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_EXT2_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_ISO9660_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 396caece6d6d..483965c5a4de 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -5,3 +5,4 @@ generic-y += agp.h
generic-y += asm-offsets.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
+generic-y += text-patching.h
diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h
index b191d87f89c4..65fe1e54c6da 100644
--- a/arch/alpha/include/asm/io.h
+++ b/arch/alpha/include/asm/io.h
@@ -88,7 +88,6 @@ static inline void * phys_to_virt(unsigned long address)
#define virt_to_phys virt_to_phys
#define phys_to_virt phys_to_virt
-#define page_to_phys(page) page_to_pa(page)
/* Maximum PIO space address supported? */
#define IO_SPACE_LIMIT 0xffff
diff --git a/arch/alpha/include/asm/page.h b/arch/alpha/include/asm/page.h
index 70419e6be1a3..5ec4c77e432e 100644
--- a/arch/alpha/include/asm/page.h
+++ b/arch/alpha/include/asm/page.h
@@ -4,11 +4,7 @@
#include <linux/const.h>
#include <asm/pal.h>
-
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#ifndef __ASSEMBLY__
@@ -18,7 +14,7 @@ extern void clear_page(void *page);
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define vma_alloc_zeroed_movable_folio(vma, vaddr) \
- vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr, false)
+ vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr)
extern void copy_page(void * _to, void * _from);
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
diff --git a/arch/alpha/include/asm/spinlock_types.h b/arch/alpha/include/asm/spinlock_types.h
index 2526fd3be5fd..05a444d77c53 100644
--- a/arch/alpha/include/asm/spinlock_types.h
+++ b/arch/alpha/include/asm/spinlock_types.h
@@ -3,7 +3,7 @@
#define _ALPHA_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
typedef struct {
diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h
index 763929e814e9..1e700468a685 100644
--- a/arch/alpha/include/uapi/asm/mman.h
+++ b/arch/alpha/include/uapi/asm/mman.h
@@ -78,6 +78,9 @@
#define MADV_COLLAPSE 25 /* Synchronous hugepage collapse */
+#define MADV_GUARD_INSTALL 102 /* fatal signal on access to range */
+#define MADV_GUARD_REMOVE 103 /* unguard range */
+
/* compatibility flags */
#define MAP_FILE 0
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index 251b73c5481e..302507bf9b5d 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -146,6 +146,8 @@
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
#define SO_DEVMEM_DONTNEED 80
+#define SCM_TS_OPT_ID 81
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index c0424de9e7cd..86185021f75a 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -152,7 +152,7 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
long __user *, basep)
{
int error;
- struct fd arg = fdget_pos(fd);
+ CLASS(fd_pos, arg)(fd);
struct osf_dirent_callback buf = {
.ctx.actor = osf_filldir,
.dirent = dirent,
@@ -160,7 +160,7 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
.count = count
};
- if (!fd_file(arg))
+ if (fd_empty(arg))
return -EBADF;
error = iterate_dir(fd_file(arg), &buf.ctx);
@@ -169,7 +169,6 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
if (count != buf.count)
error = count - buf.count;
- fdput_pos(arg);
return error;
}
diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c
index 5808a66e2a81..3048758304b5 100644
--- a/arch/alpha/kernel/pci-sysfs.c
+++ b/arch/alpha/kernel/pci-sysfs.c
@@ -64,7 +64,7 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num,
* Return: %0 on success, negative error code otherwise
*/
static int pci_mmap_resource(struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma, int sparse)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
@@ -93,14 +93,14 @@ static int pci_mmap_resource(struct kobject *kobj,
}
static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 1);
}
static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 0);
diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
index 74720667fe09..c59d53d6d3f3 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
@@ -502,3 +502,7 @@
570 common lsm_set_self_attr sys_lsm_set_self_attr
571 common lsm_list_modules sys_lsm_list_modules
572 common mseal sys_mseal
+573 common setxattrat sys_setxattrat
+574 common getxattrat sys_getxattrat
+575 common listxattrat sys_listxattrat
+576 common removexattrat sys_removexattrat
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 49285a3ce239..4c69522e0328 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -6,3 +6,4 @@ generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += user.h
+generic-y += text-patching.h
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index f57cb5a6b624..00171a212b3c 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -42,9 +42,6 @@ static inline void ioport_unmap(void __iomem *addr)
#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force u16)cpu_to_be16(v), p); })
#define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force u32)cpu_to_be32(v), p); })
-/* Change struct page to physical address */
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
diff --git a/arch/arc/include/uapi/asm/page.h b/arch/arc/include/uapi/asm/page.h
index 7fd9e741b527..4606a326af5c 100644
--- a/arch/arc/include/uapi/asm/page.h
+++ b/arch/arc/include/uapi/asm/page.h
@@ -14,7 +14,7 @@
/* PAGE_SHIFT determines the page size */
#ifdef __KERNEL__
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
+#include <vdso/page.h>
#else
/*
* Default 8k
@@ -24,11 +24,10 @@
* not available
*/
#define PAGE_SHIFT 13
+#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */
+#define PAGE_MASK (~(PAGE_SIZE-1))
#endif
-#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */
#define PAGE_OFFSET _AC(0x80000000, UL) /* Kernel starts at 2G onwrds */
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
#endif /* _UAPI__ASM_ARC_PAGE_H */
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index 4c9e61457b2f..cc6ac7d128aa 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -62,7 +62,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
const struct machine_desc *mdesc;
unsigned long dt_root;
- if (!early_init_dt_scan(dt))
+ if (!early_init_dt_scan(dt, __pa(dt)))
return NULL;
mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 749179a1d162..202397be76d8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1598,6 +1598,9 @@ config ATAGS_PROC
config ARCH_SUPPORTS_CRASH_DUMP
def_bool y
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
config AUTO_ZRELADDR
bool "Auto calculation of the decompressed kernel image address" if !ARCH_MULTIPLATFORM
default !(ARCH_FOOTBRIDGE || ARCH_RPC || ARCH_SA1100)
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 7f47b4f335c3..366f162e147d 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -242,6 +242,10 @@ choice
depends on ARCH_BCM_5301X || ARCH_BCM_NSP
select DEBUG_UART_8250
+ config DEBUG_BCMBCA
+ bool "Kernel low-level debugging on BCMBCA UART0"
+ depends on ARCH_BCMBCA
+
config DEBUG_BCM_HR2
bool "Kernel low-level debugging on Hurricane 2 UART2"
depends on ARCH_BCM_HR2
@@ -1526,7 +1530,7 @@ config DEBUG_LL_INCLUDE
default "debug/vf.S" if DEBUG_VF_UART
default "debug/vt8500.S" if DEBUG_VT8500_UART0
default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
- default "debug/bcm63xx.S" if DEBUG_BCM63XX_UART
+ default "debug/bcm63xx.S" if DEBUG_BCM63XX_UART || DEBUG_BCMBCA
default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0
default "debug/brcmstb.S" if DEBUG_BRCMSTB_UART
default "mach/debug-macro.S"
@@ -1640,6 +1644,7 @@ config DEBUG_UART_PHYS
default 0xfe531000 if DEBUG_STIH41X_SBC_ASC1
default 0xfed32000 if DEBUG_STIH41X_ASC2
default 0xff690000 if DEBUG_RK32_UART2
+ default 0xff800640 if DEBUG_BCMBCA
default 0xffc02000 if DEBUG_SOCFPGA_UART0
default 0xffc02100 if DEBUG_SOCFPGA_ARRIA10_UART1
default 0xffc03000 if DEBUG_SOCFPGA_CYCLONE5_UART1
@@ -1664,7 +1669,7 @@ config DEBUG_UART_PHYS
DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
DEBUG_RMOBILE_SCIFA4 || \
DEBUG_S3C64XX_UART || \
- DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
+ DEBUG_BCM63XX_UART || DEBUG_BCMBCA || DEBUG_ASM9260_UART || \
DEBUG_DIGICOLOR_UA0 || \
DEBUG_AT91_UART || DEBUG_STM32_UART || \
DEBUG_STIH41X_ASC2 || DEBUG_STIH41X_SBC_ASC1 || \
@@ -1734,6 +1739,7 @@ config DEBUG_UART_VIRT
default 0xfe018000 if DEBUG_MMP_UART3
default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
default 0xfe300000 if DEBUG_BCM_KONA_UART
+ default 0xfe300640 if DEBUG_BCMBCA
default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HIX5HD2_UART
default 0xfeb24000 if DEBUG_RK3X_UART0
default 0xfeb26000 if DEBUG_RK3X_UART1
@@ -1765,7 +1771,7 @@ config DEBUG_UART_VIRT
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
DEBUG_QCOM_UARTDM || \
DEBUG_S3C64XX_UART || \
- DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
+ DEBUG_BCM63XX_UART || DEBUG_BCMBCA || DEBUG_ASM9260_UART || \
DEBUG_DIGICOLOR_UA0 || \
DEBUG_AT91_UART || DEBUG_STM32_UART || \
DEBUG_STIH41X_ASC2 || DEBUG_STIH41X_SBC_ASC1 || \
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index aafebf145738..00ca7886b18e 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -264,13 +264,13 @@ stack_protector_prepare: prepare0
-mstack-protector-guard=tls \
-mstack-protector-guard-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
else
stack_protector_prepare: prepare0
$(eval SSP_PLUGIN_CFLAGS := \
-fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
$(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS))
$(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
endif
diff --git a/arch/arm/boot/dts/allwinner/Makefile b/arch/arm/boot/dts/allwinner/Makefile
index cd0d044882cf..48666f73e638 100644
--- a/arch/arm/boot/dts/allwinner/Makefile
+++ b/arch/arm/boot/dts/allwinner/Makefile
@@ -215,6 +215,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-a33-olinuxino.dtb \
sun8i-a33-q8-tablet.dtb \
sun8i-a33-sinlinx-sina33.dtb \
+ sun8i-a33-vstar.dtb \
sun8i-a83t-allwinner-h8homlet-v2.dtb \
sun8i-a83t-bananapi-m3.dtb \
sun8i-a83t-cubietruck-plus.dtb \
@@ -268,7 +269,3 @@ dtb-$(CONFIG_MACH_SUNIV) += \
suniv-f1c100s-licheepi-nano.dtb \
suniv-f1c200s-lctech-pi.dtb \
suniv-f1c200s-popstick-v1.1.dtb
-dtb-$(CONFIG_MACH_SUNIV) += \
- suniv-f1c100s-licheepi-nano.dtb \
- suniv-f1c200s-lctech-pi.dtb \
- suniv-f1c200s-popstick-v1.1.dtb
diff --git a/arch/arm/boot/dts/allwinner/sun8i-a33-vstar-core1.dtsi b/arch/arm/boot/dts/allwinner/sun8i-a33-vstar-core1.dtsi
new file mode 100644
index 000000000000..ba794b842ec4
--- /dev/null
+++ b/arch/arm/boot/dts/allwinner/sun8i-a33-vstar-core1.dtsi
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2024 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include "sun8i-a33.dtsi"
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_8bit_pins>;
+ vmmc-supply = <&reg_dcdc1>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ status = "okay";
+};
+
+&mmc2_8bit_pins {
+ /* Increase drive strength for DDR modes */
+ drive-strength = <40>;
+};
+
+&r_rsb {
+ status = "okay";
+
+ axp22x: pmic@3a3 {
+ compatible = "x-powers,axp223";
+ reg = <0x3a3>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_LOW>;
+ eldoin-supply = <&reg_dcdc1>;
+ x-powers,drive-vbus-en;
+ };
+};
+
+#include "axp223.dtsi"
+
+&reg_aldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-io";
+};
+
+&reg_aldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <2350000>;
+ regulator-max-microvolt = <2650000>;
+ regulator-name = "vdd-dll";
+};
+
+&reg_aldo3 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-avcc";
+};
+
+&reg_dc5ldo {
+ regulator-always-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-cpus";
+};
+
+&reg_dcdc1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-sys";
+};
+
+&reg_dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc5 {
+ regulator-always-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-name = "vcc-dram";
+};
+
+&reg_rtc_ldo {
+ regulator-name = "vcc-rtc";
+};
diff --git a/arch/arm/boot/dts/allwinner/sun8i-a33-vstar.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-vstar.dts
new file mode 100644
index 000000000000..9f5c29b3df46
--- /dev/null
+++ b/arch/arm/boot/dts/allwinner/sun8i-a33-vstar.dts
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2024 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+/dts-v1/;
+#include "sun8i-a33-vstar-core1.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Rervision A33-Vstar";
+ compatible = "rervision,a33-vstar",
+ "rervision,a33-core1",
+ "allwinner,sun8i-a33";
+
+ aliases {
+ serial0 = &uart0;
+ ethernet0 = &r8152;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reg_usb1_vbus: regulator-usb1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2 */
+ };
+
+ wifi_pwrseq: pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&r_pio 0 6 GPIO_ACTIVE_LOW>; /* PL6 */
+ clocks = <&rtc CLK_OSC32K_FANOUT>;
+ clock-names = "ext_clock";
+ };
+};
+
+&ac_power_supply {
+ status = "okay";
+};
+
+&codec {
+ status = "okay";
+};
+
+&dai {
+ status = "okay";
+};
+
+&ehci0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ hub@1 {
+ /* Onboard GL850G hub which needs no extra power sequence */
+ compatible = "usb5e3,608";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ r8152: ethernet@4 {
+ /*
+ * Onboard Realtek RTL8152 USB Ethernet,
+ * with no MAC address programmed
+ */
+ compatible = "usbbda,8152";
+ reg = <4>;
+ };
+ };
+};
+
+&lradc {
+ vref-supply = <&reg_aldo3>;
+ status = "okay";
+
+ button-191 {
+ label = "V+";
+ linux,code = <KEY_VOLUMEUP>;
+ channel = <0>;
+ voltage = <191011>;
+ };
+
+ button-391 {
+ label = "V-";
+ linux,code = <KEY_VOLUMEDOWN>;
+ channel = <0>;
+ voltage = <391304>;
+ };
+
+ button-600 {
+ label = "BACK";
+ linux,code = <KEY_BACK>;
+ channel = <0>;
+ voltage = <600000>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_dcdc1>;
+ bus-width = <4>;
+ cd-gpios = <&pio 1 4 GPIO_ACTIVE_LOW>; /* PB4 */
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pg_pins>;
+ vmmc-supply = <&reg_dldo1>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ interrupt-parent = <&r_pio>;
+ interrupts = <0 7 IRQ_TYPE_LEVEL_LOW>; /* PL7 */
+ interrupt-names = "host-wake";
+ };
+};
+
+/*
+ * Our WiFi chip needs both DLDO1 and DLDO2 to be powered at the same
+ * time, with the two being in sync. Since this is not really
+ * supported right now, just use the two as always on, and we will fix
+ * it later.
+ */
+&reg_dldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-wifi0";
+};
+
+&reg_dldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-wifi1";
+};
+
+&reg_drivevbus {
+ regulator-name = "usb0-vbus";
+ status = "okay";
+};
+
+&sound {
+ /* TODO: on-board microphone */
+
+ simple-audio-card,widgets = "Headphone", "Headphone Jack";
+ simple-audio-card,routing =
+ "Left DAC", "DACL",
+ "Right DAC", "DACR",
+ "Headphone Jack", "HP";
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pb_pins>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pg_pins>, <&uart1_cts_rts_pg_pins>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ clocks = <&rtc CLK_OSC32K_FANOUT>;
+ clock-names = "lpo";
+ vbat-supply = <&reg_dldo1>;
+ device-wakeup-gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+ host-wakeup-gpios = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */
+ shutdown-gpios = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+ };
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usb_power_supply {
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* PH8 */
+ usb0_vbus_power-supply = <&usb_power_supply>;
+ usb0_vbus-supply = <&reg_drivevbus>;
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts
index c8ca8cb7f5c9..52ad95a2063a 100644
--- a/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts
+++ b/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts
@@ -280,8 +280,8 @@
reg_dcdc5: dcdc5 {
regulator-always-on;
- regulator-min-microvolt = <1425000>;
- regulator-max-microvolt = <1575000>;
+ regulator-min-microvolt = <1450000>;
+ regulator-max-microvolt = <1550000>;
regulator-name = "vcc-dram";
};
diff --git a/arch/arm/boot/dts/amlogic/Makefile b/arch/arm/boot/dts/amlogic/Makefile
index a84310780ea3..504c533b1173 100644
--- a/arch/arm/boot/dts/amlogic/Makefile
+++ b/arch/arm/boot/dts/amlogic/Makefile
@@ -1,6 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_MACH_MESON6) += \
- meson6-atv1200.dtb
dtb-$(CONFIG_MACH_MESON8) += \
meson8-minix-neo-x8.dtb \
meson8b-ec100.dtb \
diff --git a/arch/arm/boot/dts/amlogic/meson6-atv1200.dts b/arch/arm/boot/dts/amlogic/meson6-atv1200.dts
deleted file mode 100644
index 98e1c94c0261..000000000000
--- a/arch/arm/boot/dts/amlogic/meson6-atv1200.dts
+++ /dev/null
@@ -1,33 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0 OR MIT
-/*
- * Copyright 2014 Carlo Caione <carlo@caione.org>
- */
-
-/dts-v1/;
-#include "meson6.dtsi"
-
-/ {
- model = "Geniatech ATV1200";
- compatible = "geniatech,atv1200", "amlogic,meson6";
-
- aliases {
- serial0 = &uart_AO;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- memory {
- device_type = "memory";
- reg = <0x40000000 0x80000000>;
- };
-};
-
-&uart_AO {
- status = "okay";
-};
-
-&ethmac {
- status = "okay";
-};
diff --git a/arch/arm/boot/dts/amlogic/meson6.dtsi b/arch/arm/boot/dts/amlogic/meson6.dtsi
deleted file mode 100644
index 4716030a48d0..000000000000
--- a/arch/arm/boot/dts/amlogic/meson6.dtsi
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0 OR MIT
-/*
- * Copyright 2014 Carlo Caione <carlo@caione.org>
- */
-
-#include "meson.dtsi"
-
-/ {
- model = "Amlogic Meson6 SoC";
- compatible = "amlogic,meson6";
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu@200 {
- device_type = "cpu";
- compatible = "arm,cortex-a9";
- next-level-cache = <&L2>;
- reg = <0x200>;
- };
-
- cpu@201 {
- device_type = "cpu";
- compatible = "arm,cortex-a9";
- next-level-cache = <&L2>;
- reg = <0x201>;
- };
- };
-
- apb2: bus@d0000000 {
- compatible = "simple-bus";
- reg = <0xd0000000 0x40000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x0 0xd0000000 0x40000>;
- };
-
- clk81: clk@0 {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <200000000>;
- };
-}; /* end of / */
-
-&efuse {
- status = "disabled";
-};
-
-&timer_abcde {
- clocks = <&xtal>, <&clk81>;
- clock-names = "xtal", "pclk";
-};
-
-&uart_AO {
- clocks = <&xtal>, <&clk81>, <&clk81>;
- clock-names = "xtal", "pclk", "baud";
-};
-
-&uart_A {
- clocks = <&xtal>, <&clk81>, <&clk81>;
- clock-names = "xtal", "pclk", "baud";
-};
-
-&uart_B {
- clocks = <&xtal>, <&clk81>, <&clk81>;
- clock-names = "xtal", "pclk", "baud";
-};
-
-&uart_C {
- clocks = <&xtal>, <&clk81>, <&clk81>;
- clock-names = "xtal", "pclk", "baud";
-};
diff --git a/arch/arm/boot/dts/amlogic/meson8-minix-neo-x8.dts b/arch/arm/boot/dts/amlogic/meson8-minix-neo-x8.dts
index c6d1c5a8a3bf..62987eadc747 100644
--- a/arch/arm/boot/dts/amlogic/meson8-minix-neo-x8.dts
+++ b/arch/arm/boot/dts/amlogic/meson8-minix-neo-x8.dts
@@ -19,7 +19,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@40000000 {
device_type = "memory";
reg = <0x40000000 0x80000000>;
};
@@ -93,5 +93,6 @@
&ethmac {
status = "okay";
pinctrl-0 = <&eth_pins>;
- pnictrl-names = "default";
+ pinctrl-names = "default";
+ phy-mode = "rmii";
};
diff --git a/arch/arm/boot/dts/amlogic/meson8.dtsi b/arch/arm/boot/dts/amlogic/meson8.dtsi
index f57be9ae150f..9ff142d9fe3f 100644
--- a/arch/arm/boot/dts/amlogic/meson8.dtsi
+++ b/arch/arm/boot/dts/amlogic/meson8.dtsi
@@ -196,7 +196,7 @@
};
thermal-zones {
- soc {
+ soc-thermal {
polling-delay-passive = <250>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
thermal-sensors = <&thermal_sensor>;
@@ -346,17 +346,16 @@
reg = <0xe0 0x18>;
};
- pinctrl_aobus: pinctrl@84 {
+ pinctrl_aobus: pinctrl@14 {
compatible = "amlogic,meson8-aobus-pinctrl";
- reg = <0x84 0xc>;
#address-cells = <1>;
#size-cells = <1>;
- ranges;
+ ranges = <0x0 0x14 0x1c>;
- gpio_ao: ao-bank@14 {
- reg = <0x14 0x4>,
- <0x2c 0x4>,
- <0x24 0x8>;
+ gpio_ao: bank@0 {
+ reg = <0x0 0x4>,
+ <0x18 0x4>,
+ <0x10 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
@@ -461,18 +460,17 @@
reg = <0x8758 0x1c>;
};
- pinctrl_cbus: pinctrl@9880 {
+ pinctrl_cbus: pinctrl@8030 {
compatible = "amlogic,meson8-cbus-pinctrl";
- reg = <0x9880 0x10>;
#address-cells = <1>;
#size-cells = <1>;
- ranges;
+ ranges = <0x0 0x8030 0x108>;
- gpio: banks@80b0 {
- reg = <0x80b0 0x28>,
- <0x80e8 0x18>,
- <0x8120 0x18>,
- <0x8030 0x30>;
+ gpio: bank@80 {
+ reg = <0x80 0x28>,
+ <0xb8 0x18>,
+ <0xf0 0x18>,
+ <0x00 0x30>;
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
@@ -589,7 +587,7 @@
};
&ahb_sram {
- ao_arc_sram: ao-arc-sram@0 {
+ ao_arc_sram: aoarc-sram@0 {
compatible = "amlogic,meson8-ao-arc-sram";
reg = <0x0 0x8000>;
pool;
diff --git a/arch/arm/boot/dts/amlogic/meson8b-ec100.dts b/arch/arm/boot/dts/amlogic/meson8b-ec100.dts
index 49890eb12781..18ea6592b7d7 100644
--- a/arch/arm/boot/dts/amlogic/meson8b-ec100.dts
+++ b/arch/arm/boot/dts/amlogic/meson8b-ec100.dts
@@ -22,7 +22,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@40000000 {
device_type = "memory";
reg = <0x40000000 0x40000000>;
};
@@ -98,6 +98,10 @@
compatible = "amlogic,gx-sound-card";
model = "M8B-EC100";
+ clocks = <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>,
+ <&clkc CLKID_MPLL2>;
+
assigned-clocks = <&clkc CLKID_MPLL0>,
<&clkc CLKID_MPLL1>,
<&clkc CLKID_MPLL2>;
@@ -427,7 +431,7 @@
"NAND_CS1 (EMMC)", "NAND_CS2 iNAND_RS1 (EMMC)",
"NAND_nR/B iNAND_CMD (EMMC)", "NAND_ALE (EMMC)",
"NAND_CLE (EMMC)", "nRE_S1 NAND_nRE (EMMC)",
- "nWE_S1 NAND_nWE (EMMC)", "", "", "SPI_CS",
+ "nWE_S1 NAND_nWE (EMMC)", "", "", "", "SPI_CS",
/* Bank DIF */
"RMII_RXD1", "RMII_RXD0", "RMII_CRS_DV",
"RMII_50M_IN", "GPIODIF_4", "GPIODIF_5",
diff --git a/arch/arm/boot/dts/amlogic/meson8b-mxq.dts b/arch/arm/boot/dts/amlogic/meson8b-mxq.dts
index 7adedd3258c3..fb28cb330f17 100644
--- a/arch/arm/boot/dts/amlogic/meson8b-mxq.dts
+++ b/arch/arm/boot/dts/amlogic/meson8b-mxq.dts
@@ -22,7 +22,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@40000000 {
device_type = "memory";
reg = <0x40000000 0x40000000>;
};
diff --git a/arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts b/arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts
index 941682844faf..2aa012f38a3b 100644
--- a/arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts
@@ -22,7 +22,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@40000000 {
device_type = "memory";
reg = <0x40000000 0x40000000>;
};
@@ -378,6 +378,6 @@
compatible = "usb5e3,610";
reg = <1>;
vdd-supply = <&p5v0>;
- reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm/boot/dts/amlogic/meson8b.dtsi b/arch/arm/boot/dts/amlogic/meson8b.dtsi
index 2d9d24d3a95d..9e02a97f86a0 100644
--- a/arch/arm/boot/dts/amlogic/meson8b.dtsi
+++ b/arch/arm/boot/dts/amlogic/meson8b.dtsi
@@ -173,7 +173,7 @@
};
thermal-zones {
- soc {
+ soc-thermal {
polling-delay-passive = <250>; /* milliseconds */
polling-delay = <1000>; /* milliseconds */
thermal-sensors = <&thermal_sensor>;
@@ -308,17 +308,16 @@
reg = <0xe0 0x18>;
};
- pinctrl_aobus: pinctrl@84 {
+ pinctrl_aobus: pinctrl@14 {
compatible = "amlogic,meson8b-aobus-pinctrl";
- reg = <0x84 0xc>;
#address-cells = <1>;
#size-cells = <1>;
- ranges;
+ ranges = <0x0 0x14 0x1c>;
- gpio_ao: ao-bank@14 {
- reg = <0x14 0x4>,
- <0x2c 0x4>,
- <0x24 0x8>;
+ gpio_ao: bank@0 {
+ reg = <0x0 0x4>,
+ <0x18 0x4>,
+ <0x10 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
@@ -415,18 +414,17 @@
reg = <0x8758 0x1c>;
};
- pinctrl_cbus: pinctrl@9880 {
+ pinctrl_cbus: pinctrl@8030 {
compatible = "amlogic,meson8b-cbus-pinctrl";
- reg = <0x9880 0x10>;
#address-cells = <1>;
#size-cells = <1>;
- ranges;
+ ranges = <0x0 0x8030 0x108>;
- gpio: banks@80b0 {
- reg = <0x80b0 0x28>,
- <0x80e8 0x18>,
- <0x8120 0x18>,
- <0x8030 0x38>;
+ gpio: bank@80 {
+ reg = <0x80 0x28>,
+ <0xb8 0x18>,
+ <0xf0 0x18>,
+ <0x00 0x38>;
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
@@ -535,7 +533,7 @@
};
&ahb_sram {
- ao_arc_sram: ao-arc-sram@0 {
+ ao_arc_sram: aoarc-sram@0 {
compatible = "amlogic,meson8b-ao-arc-sram";
reg = <0x0 0x8000>;
pool;
diff --git a/arch/arm/boot/dts/amlogic/meson8m2-mxiii-plus.dts b/arch/arm/boot/dts/amlogic/meson8m2-mxiii-plus.dts
index aa4d4bf70629..08aa661e17ad 100644
--- a/arch/arm/boot/dts/amlogic/meson8m2-mxiii-plus.dts
+++ b/arch/arm/boot/dts/amlogic/meson8m2-mxiii-plus.dts
@@ -26,7 +26,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@40000000 {
device_type = "memory";
reg = <0x40000000 0x80000000>;
};
diff --git a/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts
index 84f39dec3c42..170c1ae441a6 100644
--- a/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts
+++ b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts
@@ -135,7 +135,7 @@
reg = <0x48>;
};
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c01";
pagesize = <8>;
reg = <0x50>;
@@ -211,7 +211,7 @@
status = "okay";
clock-frequency = <100000>;
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
pagesize = <8>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts
index 43202890c959..83fe00abd652 100644
--- a/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts
+++ b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts
@@ -251,6 +251,7 @@
led-controller@2b {
compatible = "cznic,turris-omnia-leds";
reg = <0x2b>;
+ interrupts-extended = <&mcu 11 IRQ_TYPE_NONE>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
diff --git a/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts
index 9c438f10f737..2bc4b68bd723 100644
--- a/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts
+++ b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts
@@ -44,7 +44,7 @@
i2c@11100 {
status = "okay";
- s24c02: s24c02@50 {
+ s24c02: eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
};
diff --git a/arch/arm/boot/dts/microchip/Makefile b/arch/arm/boot/dts/microchip/Makefile
index 0c45c8d17468..470fe46433a9 100644
--- a/arch/arm/boot/dts/microchip/Makefile
+++ b/arch/arm/boot/dts/microchip/Makefile
@@ -2,6 +2,7 @@
# Enables support for device-tree overlays
DTC_FLAGS_at91-sam9x60_curiosity := -@
DTC_FLAGS_at91-sam9x60ek := -@
+DTC_FLAGS_at91-sam9x75_curiosity := -@
DTC_FLAGS_at91-sama5d27_som1_ek := -@
DTC_FLAGS_at91-sama5d27_wlsom1_ek := -@
DTC_FLAGS_at91-sama5d29_curiosity := -@
@@ -60,6 +61,8 @@ dtb-$(CONFIG_SOC_AT91SAM9) += \
dtb-$(CONFIG_SOC_SAM9X60) += \
at91-sam9x60_curiosity.dtb \
at91-sam9x60ek.dtb
+dtb-$(CONFIG_SOC_SAM9X7) += \
+ at91-sam9x75_curiosity.dtb
dtb-$(CONFIG_SOC_SAM_V7) += \
at91-kizbox2-2.dtb \
at91-kizbox3-hs.dtb \
diff --git a/arch/arm/boot/dts/microchip/aks-cdu.dts b/arch/arm/boot/dts/microchip/aks-cdu.dts
index 742fcf525e1b..b65f80e1ef05 100644
--- a/arch/arm/boot/dts/microchip/aks-cdu.dts
+++ b/arch/arm/boot/dts/microchip/aks-cdu.dts
@@ -98,23 +98,27 @@
leds {
compatible = "gpio-leds";
- red {
+ led-red {
+ label = "red";
gpios = <&pioC 10 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "none";
};
- green {
+ led-green {
+ label = "green";
gpios = <&pioA 5 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
default-state = "on";
};
- yellow {
+ led-yellow {
+ label = "yellow";
gpios = <&pioB 20 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- blue {
+ led-blue {
+ label = "blue";
gpios = <&pioB 21 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
diff --git a/arch/arm/boot/dts/microchip/animeo_ip.dts b/arch/arm/boot/dts/microchip/animeo_ip.dts
index 29936bfbeeb7..7f527622d3f2 100644
--- a/arch/arm/boot/dts/microchip/animeo_ip.dts
+++ b/arch/arm/boot/dts/microchip/animeo_ip.dts
@@ -146,23 +146,23 @@
leds {
compatible = "gpio-leds";
- power_green {
+ led-power-green {
label = "power_green";
gpios = <&pioC 17 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
- power_red {
+ led-power-red {
label = "power_red";
gpios = <&pioA 2 GPIO_ACTIVE_HIGH>;
};
- tx_green {
+ led-tx-green {
label = "tx_green";
gpios = <&pioC 19 GPIO_ACTIVE_HIGH>;
};
- tx_red {
+ led-tx-red {
label = "tx_red";
gpios = <&pioC 18 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/microchip/at91-kizbox2-common.dtsi b/arch/arm/boot/dts/microchip/at91-kizbox2-common.dtsi
index e5e21dff882f..a44d92305dbb 100644
--- a/arch/arm/boot/dts/microchip/at91-kizbox2-common.dtsi
+++ b/arch/arm/boot/dts/microchip/at91-kizbox2-common.dtsi
@@ -85,7 +85,7 @@
&i2c1 {
status = "okay";
- pmic: act8865@5b {
+ act8865: pmic@5b {
compatible = "active-semi,act8865";
reg = <0x5b>;
status = "okay";
diff --git a/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts b/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts
index 3b38707d736e..cdc56b53299d 100644
--- a/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts
@@ -53,17 +53,17 @@
pinctrl-0 = <&pinctrl_gpio_leds>;
status = "okay"; /* Conflict with pwm0. */
- red {
+ led-red {
label = "red";
gpios = <&pioB 11 GPIO_ACTIVE_HIGH>;
};
- green {
+ led-green {
label = "green";
gpios = <&pioB 12 GPIO_ACTIVE_HIGH>;
};
- blue {
+ led-blue {
label = "blue";
gpios = <&pioB 13 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
@@ -260,6 +260,37 @@
i2c-digital-filter-width-ns = <35>;
status = "okay";
+ power-monitor@17 {
+ compatible = "microchip,pac1934";
+ reg = <0x17>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@1 {
+ reg = <0x1>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDIOM";
+ };
+
+ channel@2 {
+ reg = <0x2>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDCORE";
+ };
+
+ channel@3 {
+ reg = <0x3>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDD3V3_MPU";
+ };
+
+ channel@4 {
+ reg = <0x4>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDD3V3";
+ };
+ };
+
gpio_exp: mcp23008@20 {
compatible = "microchip,mcp23008";
reg = <0x20>;
diff --git a/arch/arm/boot/dts/microchip/at91-sam9x75_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sam9x75_curiosity.dts
new file mode 100644
index 000000000000..87b6ea97590b
--- /dev/null
+++ b/arch/arm/boot/dts/microchip/at91-sam9x75_curiosity.dts
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * at91-sam9x75_curiosity.dts - Device Tree file for Microchip SAM9X75 Curiosity board
+ *
+ * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Varshini Rajendran <varshini.rajendran@microchip.com>
+ */
+/dts-v1/;
+#include "sam9x7.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Microchip SAM9X75 Curiosity";
+ compatible = "microchip,sam9x75-curiosity", "microchip,sam9x7", "atmel,at91sam9";
+
+ aliases {
+ i2c0 = &i2c6;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_key_gpio_default>;
+
+ button-user {
+ label = "USER";
+ gpios = <&pioC 9 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_0>;
+ wakeup-source;
+ };
+ };
+
+ led-controller {
+ compatible = "gpio-leds";
+
+ led_red: led-red {
+ label = "red";
+ gpios = <&pioC 14 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&pinctrl_red_led_gpio_default>;
+ };
+
+ led_green: led-green {
+ label = "green";
+ gpios = <&pioC 21 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&pinctrl_green_led_gpio_default>;
+ };
+
+ led_blue: led-blue {
+ label = "blue";
+ gpios = <&pioC 20 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&pinctrl_blue_led_gpio_default>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ memory@20000000 {
+ reg = <0x20000000 0x10000000>;
+ device_type = "memory";
+ };
+};
+
+&classd {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_classd_default>;
+ atmel,pwm-type = "diff";
+ atmel,non-overlap-time = <10>;
+ status = "okay";
+};
+
+&dbgu {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu_default>;
+ status = "okay";
+};
+
+&dma0 {
+ status = "okay";
+};
+
+&flx6 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+ status = "okay";
+};
+
+&i2c6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flx6_default>;
+ i2c-analog-filter;
+ i2c-digital-filter;
+ i2c-digital-filter-width-ns = <35>;
+ status = "okay";
+
+ pmic@5b {
+ compatible = "microchip,mcp16502";
+ reg = <0x5b>;
+
+ regulators {
+ vdd_3v3: VDD_IO {
+ regulator-name = "VDD_IO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-mode = <4>;
+ };
+ };
+
+ vddioddr: VDD_DDR {
+ regulator-name = "VDD_DDR";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+ };
+
+ vddcore: VDD_CORE {
+ regulator-name = "VDD_CORE";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-mode = <4>;
+ };
+ };
+
+ dcdc4: VDD_OTHER {
+ regulator-name = "VDD_OTHER";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-initial-mode = <2>;
+ regulator-allowed-modes = <2>, <4>;
+ regulator-ramp-delay = <3125>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ regulator-mode = <4>;
+ };
+
+ regulator-state-mem {
+ regulator-mode = <4>;
+ };
+ };
+
+ vldo1: LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vldo2: LDO2 {
+ regulator-name = "LDO2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2s {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2s_default>;
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
+
+&main_xtal {
+ clock-frequency = <24000000>;
+};
+
+&pinctrl {
+ classd {
+ pinctrl_classd_default: classd-default {
+ atmel,pins =
+ <AT91_PIOA 18 AT91_PERIPH_C AT91_PINCTRL_PULL_UP>,
+ <AT91_PIOA 19 AT91_PERIPH_C AT91_PINCTRL_PULL_DOWN>;
+ };
+ };
+
+ dbgu {
+ pinctrl_dbgu_default: dbgu-default {
+ atmel,pins = <AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
+ <AT91_PIOA 27 AT91_PERIPH_A AT91_PINCTRL_NONE>;
+ };
+ };
+
+ flexcom {
+ pinctrl_flx6_default: flx6-default {
+ atmel,pins =
+ <AT91_PIOA 24 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
+ <AT91_PIOA 25 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
+ };
+ };
+
+ gpio-keys {
+ pinctrl_key_gpio_default: key-gpio-default {
+ atmel,pins = <AT91_PIOC 9 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ };
+
+ i2s {
+ pinctrl_i2s_default: i2s-default {
+ atmel,pins =
+ <AT91_PIOB 26 AT91_PERIPH_D AT91_PINCTRL_NONE>, /* I2SCK */
+ <AT91_PIOB 15 AT91_PERIPH_D AT91_PINCTRL_NONE>, /* I2SWS */
+ <AT91_PIOB 16 AT91_PERIPH_D AT91_PINCTRL_NONE>, /* I2SDIN */
+ <AT91_PIOB 17 AT91_PERIPH_D AT91_PINCTRL_NONE>, /* I2SDOUT */
+ <AT91_PIOB 25 AT91_PERIPH_D AT91_PINCTRL_NONE>; /* I2SMCK */
+ };
+ };
+
+ led-controller {
+ pinctrl_red_led_gpio_default: red-led-gpio-default {
+ atmel,pins = <AT91_PIOC 14 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ pinctrl_green_led_gpio_default: green-led-gpio-default {
+ atmel,pins = <AT91_PIOC 21 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ pinctrl_blue_led_gpio_default: blue-led-gpio-default {
+ atmel,pins = <AT91_PIOC 20 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+ };
+ };
+
+ sdmmc0 {
+ pinctrl_sdmmc0_default: sdmmc0-default {
+ atmel,pins =
+ <AT91_PIOA 2 AT91_PERIPH_A (AT91_PINCTRL_DRIVE_STRENGTH_HI | AT91_PINCTRL_SLEWRATE_ENA)>, /* PA2 CK periph A with pullup */
+ <AT91_PIOA 1 AT91_PERIPH_A (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DRIVE_STRENGTH_HI | AT91_PINCTRL_SLEWRATE_ENA)>, /* PA1 CMD periph A with pullup */
+ <AT91_PIOA 0 AT91_PERIPH_A (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DRIVE_STRENGTH_HI | AT91_PINCTRL_SLEWRATE_ENA)>, /* PA0 DAT0 periph A */
+ <AT91_PIOA 3 AT91_PERIPH_A (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DRIVE_STRENGTH_HI | AT91_PINCTRL_SLEWRATE_ENA)>, /* PA3 DAT1 periph A with pullup */
+ <AT91_PIOA 4 AT91_PERIPH_A (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DRIVE_STRENGTH_HI | AT91_PINCTRL_SLEWRATE_ENA)>, /* PA4 DAT2 periph A with pullup */
+ <AT91_PIOA 5 AT91_PERIPH_A (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DRIVE_STRENGTH_HI | AT91_PINCTRL_SLEWRATE_ENA)>; /* PA5 DAT3 periph A with pullup */
+ };
+ };
+}; /* pinctrl */
+
+&poweroff {
+ debounce-delay-us = <976>;
+ status = "okay";
+
+ input@0 {
+ reg = <0>;
+ };
+};
+
+&rtt {
+ atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdmmc0_default>;
+ cd-gpios = <&pioA 23 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ status = "okay";
+};
+
+&slow_xtal {
+ clock-frequency = <32768>;
+};
+
+&tcb {
+ timer0: timer@0 {
+ compatible = "atmel,tcb-timer";
+ reg = <0>;
+ };
+
+ timer1: timer@1 {
+ compatible = "atmel,tcb-timer";
+ reg = <1>;
+ };
+};
+
+&trng {
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d27_som1.dtsi b/arch/arm/boot/dts/microchip/at91-sama5d27_som1.dtsi
index 95ecb7d040a8..8ac85dac5a96 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d27_som1.dtsi
+++ b/arch/arm/boot/dts/microchip/at91-sama5d27_som1.dtsi
@@ -106,7 +106,7 @@
scl-gpios = <&pioA PIN_PD22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <8>;
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi b/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi
index c173f49cb910..ef11606a82b3 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi
+++ b/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi
@@ -75,7 +75,7 @@
scl-gpios = <&pioA PIN_PD20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
- mcp16502@5b {
+ pmic@5b {
compatible = "microchip,mcp16502";
reg = <0x5b>;
lvin-supply = <&reg_5v>;
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
index 951a0c97d3c6..b6684bf67d3e 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts
@@ -149,7 +149,7 @@
i2c-sda-hold-time-ns = <350>;
status = "okay";
- mcp16502@5b {
+ pmic@5b {
compatible = "microchip,mcp16502";
reg = <0x5b>;
lvin-supply = <&reg_5v>;
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts b/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts
index 5e2bb517a480..9fa6f1395aa6 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts
@@ -195,7 +195,38 @@
i2c-digital-filter-width-ns = <35>;
status = "okay";
- mcp16502@5b {
+ power-monitor@10 {
+ compatible = "microchip,pac1934";
+ reg = <0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@1 {
+ reg = <0x1>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDD3V3_1";
+ };
+
+ channel@2 {
+ reg = <0x2>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDD3V3_2";
+ };
+
+ channel@3 {
+ reg = <0x3>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDCORE";
+ };
+
+ channel@4 {
+ reg = <0x4>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDIODDR";
+ };
+ };
+
+ pmic@5b {
compatible = "microchip,mcp16502";
reg = <0x5b>;
lvin-supply = <&reg_5v>;
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts b/arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts
index 200b20515ab1..e4ae60ef5f8a 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts
@@ -231,7 +231,7 @@
scl-gpios = <&pioA PIN_PC7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <8>;
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts
index 6680031387e8..4bab3f25b855 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts
@@ -411,7 +411,7 @@
scl-gpios = <&pioA PIN_PD5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
- at24@54 {
+ eeprom@54 {
compatible = "atmel,24c02";
reg = <0x54>;
pagesize = <16>;
diff --git a/arch/arm/boot/dts/microchip/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/microchip/at91-sama5d3_xplained.dts
index 820033727088..5662992cf213 100644
--- a/arch/arm/boot/dts/microchip/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama5d3_xplained.dts
@@ -87,7 +87,7 @@
i2c1: i2c@f0018000 {
status = "okay";
- pmic: act8865@5b {
+ act8865: pmic@5b {
compatible = "active-semi,act8865";
reg = <0x5b>;
status = "disabled";
diff --git a/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts
index 645e49fdb7fe..2dec2218f32c 100644
--- a/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts
@@ -186,6 +186,37 @@
i2c-digital-filter-width-ns = <35>;
status = "okay";
+ power-monitor@1f {
+ compatible = "microchip,pac1934";
+ reg = <0x1f>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@1 {
+ reg = <0x1>;
+ shunt-resistor-micro-ohms = <47000>;
+ label = "VDD3V3";
+ };
+
+ channel@2 {
+ reg = <0x2>;
+ shunt-resistor-micro-ohms = <47000>;
+ label = "VDDIODDR";
+ };
+
+ channel@3 {
+ reg = <0x3>;
+ shunt-resistor-micro-ohms = <47000>;
+ label = "VDDCORE";
+ };
+
+ channel@4 {
+ reg = <0x4>;
+ shunt-resistor-micro-ohms = <47000>;
+ label = "VDDCPU";
+ };
+ };
+
eeprom@51 {
compatible = "atmel,24c02";
reg = <0x51>;
diff --git a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
index ed75d491a246..0f5e6ad438dd 100644
--- a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
+++ b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
@@ -244,7 +244,38 @@
i2c-digital-filter-width-ns = <35>;
status = "okay";
- mcp16502@5b {
+ power-monitor@10 {
+ compatible = "microchip,pac1934";
+ reg = <0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@1 {
+ reg = <0x1>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDD3V3";
+ };
+
+ channel@2 {
+ reg = <0x2>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDIODDR";
+ };
+
+ channel@3 {
+ reg = <0x3>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDCORE";
+ };
+
+ channel@4 {
+ reg = <0x4>;
+ shunt-resistor-micro-ohms = <10000>;
+ label = "VDDCPU";
+ };
+ };
+
+ pmic@5b {
compatible = "microchip,mcp16502";
reg = <0x5b>;
lvin-supply = <&reg_5v>;
diff --git a/arch/arm/boot/dts/microchip/at91rm9200ek.dts b/arch/arm/boot/dts/microchip/at91rm9200ek.dts
index 4624a6f076f8..0bf472b157a5 100644
--- a/arch/arm/boot/dts/microchip/at91rm9200ek.dts
+++ b/arch/arm/boot/dts/microchip/at91rm9200ek.dts
@@ -127,19 +127,19 @@
leds {
compatible = "gpio-leds";
- ds2 {
+ led-ds2 {
label = "green";
gpios = <&pioB 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "mmc0";
};
- ds4 {
+ led-ds4 {
label = "yellow";
gpios = <&pioB 1 GPIO_ACTIVE_LOW>;
linux,default-trigger = "heartbeat";
};
- ds6 {
+ led-ds6 {
label = "red";
gpios = <&pioB 2 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/microchip/at91sam9260ek.dts b/arch/arm/boot/dts/microchip/at91sam9260ek.dts
index 720c15472c4a..e8e65e60564d 100644
--- a/arch/arm/boot/dts/microchip/at91sam9260ek.dts
+++ b/arch/arm/boot/dts/microchip/at91sam9260ek.dts
@@ -165,7 +165,7 @@
i2c-gpio-0 {
status = "okay";
- 24c512@50 {
+ eeprom@50 {
compatible = "atmel,24c512";
reg = <0x50>;
};
@@ -174,13 +174,13 @@
leds {
compatible = "gpio-leds";
- ds1 {
+ led-ds1 {
label = "ds1";
gpios = <&pioA 9 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
- ds5 {
+ led-ds5 {
label = "ds5";
gpios = <&pioA 6 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/microchip/at91sam9261ek.dts b/arch/arm/boot/dts/microchip/at91sam9261ek.dts
index 045cb253f23a..a8f523131cd6 100644
--- a/arch/arm/boot/dts/microchip/at91sam9261ek.dts
+++ b/arch/arm/boot/dts/microchip/at91sam9261ek.dts
@@ -192,19 +192,19 @@
leds {
compatible = "gpio-leds";
- ds8 {
+ led-ds8 {
label = "ds8";
gpios = <&pioA 13 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- ds7 {
+ led-ds7 {
label = "ds7";
gpios = <&pioA 14 GPIO_ACTIVE_LOW>;
linux,default-trigger = "nand-disk";
};
- ds1 {
+ led-ds1 {
label = "ds1";
gpios = <&pioA 23 GPIO_ACTIVE_LOW>;
linux,default-trigger = "heartbeat";
diff --git a/arch/arm/boot/dts/microchip/at91sam9263ek.dts b/arch/arm/boot/dts/microchip/at91sam9263ek.dts
index ce8baff6a9f4..f25692543d71 100644
--- a/arch/arm/boot/dts/microchip/at91sam9263ek.dts
+++ b/arch/arm/boot/dts/microchip/at91sam9263ek.dts
@@ -219,13 +219,13 @@
leds {
compatible = "gpio-leds";
- d3 {
+ led-d3 {
label = "d3";
gpios = <&pioB 7 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
- d2 {
+ led-d2 {
label = "d2";
gpios = <&pioC 29 GPIO_ACTIVE_LOW>;
linux,default-trigger = "nand-disk";
@@ -253,7 +253,7 @@
i2c-gpio-0 {
status = "okay";
- 24c512@50 {
+ eeprom@50 {
compatible = "atmel,24c512";
reg = <0x50>;
pagesize = <128>;
diff --git a/arch/arm/boot/dts/microchip/at91sam9g20ek.dts b/arch/arm/boot/dts/microchip/at91sam9g20ek.dts
index 6de7a7cd3c07..1e62fd371ddb 100644
--- a/arch/arm/boot/dts/microchip/at91sam9g20ek.dts
+++ b/arch/arm/boot/dts/microchip/at91sam9g20ek.dts
@@ -14,13 +14,13 @@
leds {
compatible = "gpio-leds";
- ds1 {
+ led-ds1 {
label = "ds1";
gpios = <&pioA 9 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
- ds5 {
+ led-ds5 {
label = "ds5";
gpios = <&pioA 6 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi
index 565b99e79c52..4e7cfbbd4241 100644
--- a/arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi
@@ -220,7 +220,7 @@
i2c-gpio-0 {
status = "okay";
- 24c512@50 {
+ eeprom@50 {
compatible = "atmel,24c512";
reg = <0x50>;
vcc-supply = <&reg_3v3>;
diff --git a/arch/arm/boot/dts/microchip/at91sam9g45.dtsi b/arch/arm/boot/dts/microchip/at91sam9g45.dtsi
index c54eb21d5cba..157d306ef5c9 100644
--- a/arch/arm/boot/dts/microchip/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/microchip/at91sam9g45.dtsi
@@ -753,7 +753,7 @@
status = "disabled";
};
- trng@fffcc000 {
+ trng: rng@fffcc000 {
compatible = "atmel,at91sam9g45-trng";
reg = <0xfffcc000 0x100>;
interrupts = <6 IRQ_TYPE_LEVEL_HIGH 0>;
diff --git a/arch/arm/boot/dts/microchip/sam9x60.dtsi b/arch/arm/boot/dts/microchip/sam9x60.dtsi
index 04a6d716ecaf..36944e18a329 100644
--- a/arch/arm/boot/dts/microchip/sam9x60.dtsi
+++ b/arch/arm/boot/dts/microchip/sam9x60.dtsi
@@ -186,6 +186,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 13>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -388,6 +389,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 32>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -439,6 +441,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 33>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -486,7 +489,7 @@
clock-names = "sha_clk";
};
- trng: trng@f0030000 {
+ trng: rng@f0030000 {
compatible = "microchip,sam9x60-trng";
reg = <0xf0030000 0x100>;
interrupts = <38 IRQ_TYPE_LEVEL_HIGH 0>;
@@ -598,6 +601,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 9>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -649,6 +653,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 10>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -700,6 +705,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 11>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -751,6 +757,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -821,6 +828,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 6>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -891,6 +899,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 7>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -961,6 +970,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 8>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -1086,6 +1096,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 15>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
@@ -1137,6 +1148,7 @@
dma-names = "tx", "rx";
clocks = <&pmc PMC_TYPE_PERIPHERAL 16>;
clock-names = "usart";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
atmel,use-dma-rx;
atmel,use-dma-tx;
atmel,fifo-size = <16>;
diff --git a/arch/arm/boot/dts/microchip/sam9x7.dtsi b/arch/arm/boot/dts/microchip/sam9x7.dtsi
new file mode 100644
index 000000000000..beb1f34b38d3
--- /dev/null
+++ b/arch/arm/boot/dts/microchip/sam9x7.dtsi
@@ -0,0 +1,1220 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * sam9x7.dtsi - Device Tree Include file for Microchip SAM9X7 SoC family
+ *
+ * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Varshini Rajendran <varshini.rajendran@microchip.com>
+ */
+
+#include <dt-bindings/clock/at91.h>
+#include <dt-bindings/dma/at91.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/mfd/at91-usart.h>
+#include <dt-bindings/mfd/atmel-flexcom.h>
+#include <dt-bindings/pinctrl/at91.h>
+
+/ {
+ model = "Microchip SAM9X7 SoC";
+ compatible = "microchip,sam9x7";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&aic>;
+
+ aliases {
+ serial0 = &dbgu;
+ gpio0 = &pioA;
+ gpio1 = &pioB;
+ gpio2 = &pioC;
+ gpio3 = &pioD;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,arm926ej-s";
+ reg = <0>;
+ device_type = "cpu";
+ };
+ };
+
+ clocks {
+ slow_xtal: clock-slowxtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ main_xtal: clock-mainxtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+ };
+
+ sram: sram@300000 {
+ compatible = "mmio-sram";
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ sdmmc0: mmc@80000000 {
+ compatible = "microchip,sam9x7-sdhci", "microchip,sam9x60-sdhci";
+ reg = <0x80000000 0x300>;
+ interrupts = <12 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 12>, <&pmc PMC_TYPE_GCK 12>;
+ clock-names = "hclock", "multclk";
+ assigned-clocks = <&pmc PMC_TYPE_GCK 12>;
+ assigned-clock-rates = <100000000>;
+ status = "disabled";
+ };
+
+ sdmmc1: mmc@90000000 {
+ compatible = "microchip,sam9x7-sdhci", "microchip,sam9x60-sdhci";
+ reg = <0x90000000 0x300>;
+ interrupts = <26 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 26>, <&pmc PMC_TYPE_GCK 26>;
+ clock-names = "hclock", "multclk";
+ assigned-clocks = <&pmc PMC_TYPE_GCK 26>;
+ assigned-clock-rates = <100000000>;
+ status = "disabled";
+ };
+ };
+
+ apb {
+ compatible = "simple-bus";
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ flx4: flexcom@f0000000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf0000000 0x200>;
+ ranges = <0x0 0xf0000000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 13>;
+ status = "disabled";
+
+ uart4: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 13>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(8))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(9))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ spi4: spi@400 {
+ compatible = "microchip,sam9x7-spi", "atmel,at91rm9200-spi";
+ reg = <0x400 0x200>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 13>;
+ clock-names = "spi_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(8))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(9))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 13>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(8))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(9))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx5: flexcom@f0004000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf0004000 0x200>;
+ ranges = <0x0 0xf0004000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 14>;
+ status = "disabled";
+
+ uart5: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 14>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(10))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(11))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ spi5: spi@400 {
+ compatible = "microchip,sam9x7-spi", "atmel,at91rm9200-spi";
+ reg = <0x400 0x200>;
+ interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 14>;
+ clock-names = "spi_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(10))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(11))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 14>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(10))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(11))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ dma0: dma-controller@f0008000 {
+ compatible = "microchip,sam9x7-dma", "atmel,sama5d4-dma";
+ reg = <0xf0008000 0x1000>;
+ interrupts = <20 IRQ_TYPE_LEVEL_HIGH 0>;
+ #dma-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 20>;
+ clock-names = "dma_clk";
+ status = "disabled";
+ };
+
+ ssc: ssc@f0010000 {
+ compatible = "microchip,sam9x7-ssc", "atmel,at91sam9g45-ssc";
+ reg = <0xf0010000 0x4000>;
+ interrupts = <28 IRQ_TYPE_LEVEL_HIGH 5>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 28>;
+ clock-names = "pclk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(38))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(39))>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2s: i2s@f001c000 {
+ compatible = "microchip,sam9x7-i2smcc", "microchip,sam9x60-i2smcc";
+ reg = <0xf001c000 0x100>;
+ interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 34>, <&pmc PMC_TYPE_GCK 34>;
+ clock-names = "pclk", "gclk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(36))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(37))>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ flx11: flexcom@f0020000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf0020000 0x200>;
+ ranges = <0x0 0xf0020000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 32>;
+ status = "disabled";
+
+ uart11: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 32>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(22))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(23))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ i2c11: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 32>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(22))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(23))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx12: flexcom@f0024000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf0024000 0x200>;
+ ranges = <0x0 0xf0024000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 33>;
+ status = "disabled";
+
+ uart12: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 33>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(24))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(25))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ i2c12: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 33>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(24))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(25))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ pit64b0: timer@f0028000 {
+ compatible = "microchip,sam9x7-pit64b", "microchip,sam9x60-pit64b";
+ reg = <0xf0028000 0x100>;
+ interrupts = <37 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 37>, <&pmc PMC_TYPE_GCK 37>;
+ clock-names = "pclk", "gclk";
+ };
+
+ sha: crypto@f002c000 {
+ compatible = "microchip,sam9x7-sha", "atmel,at91sam9g46-sha";
+ reg = <0xf002c000 0x100>;
+ interrupts = <41 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 41>;
+ clock-names = "sha_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(34))>;
+ dma-names = "tx";
+ };
+
+ trng: rng@f0030000 {
+ compatible = "microchip,sam9x7-trng", "microchip,sam9x60-trng";
+ reg = <0xf0030000 0x100>;
+ interrupts = <38 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 38>;
+ status = "disabled";
+ };
+
+ aes: crypto@f0034000 {
+ compatible = "microchip,sam9x7-aes", "atmel,at91sam9g46-aes";
+ reg = <0xf0034000 0x100>;
+ interrupts = <39 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 39>;
+ clock-names = "aes_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(32))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(33))>;
+ dma-names = "tx", "rx";
+ };
+
+ tdes: crypto@f0038000 {
+ compatible = "microchip,sam9x7-tdes", "atmel,at91sam9g46-tdes";
+ reg = <0xf0038000 0x100>;
+ interrupts = <40 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 40>;
+ clock-names = "tdes_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(31))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(30))>;
+ dma-names = "tx", "rx";
+ };
+
+ classd: sound@f003c000 {
+ compatible = "microchip,sam9x7-classd", "atmel,sama5d2-classd";
+ reg = <0xf003c000 0x100>;
+ interrupts = <42 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 42>, <&pmc PMC_TYPE_GCK 42>;
+ clock-names = "pclk", "gclk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(35))>;
+ dma-names = "tx";
+ status = "disabled";
+ };
+
+ pit64b1: timer@f0040000 {
+ compatible = "microchip,sam9x7-pit64b", "microchip,sam9x60-pit64b";
+ reg = <0xf0040000 0x100>;
+ interrupts = <58 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 58>, <&pmc PMC_TYPE_GCK 58>;
+ clock-names = "pclk", "gclk";
+ };
+
+ can0: can@f8000000 {
+ compatible = "bosch,m_can";
+ reg = <0xf8000000 0x100>, <0x300000 0x7800>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <29 IRQ_TYPE_LEVEL_HIGH 0>,
+ <68 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "int0", "int1";
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 29>, <&pmc PMC_TYPE_GCK 29>;
+ clock-names = "hclk", "cclk";
+ assigned-clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>, <&pmc PMC_TYPE_GCK 29>;
+ assigned-clock-rates = <480000000>, <40000000>;
+ assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>, <&pmc PMC_TYPE_CORE PMC_UTMI>;
+ bosch,mram-cfg = <0x3400 0 0 64 0 0 32 32>;
+ status = "disabled";
+ };
+
+ can1: can@f8004000 {
+ compatible = "bosch,m_can";
+ reg = <0xf8004000 0x100>, <0x300000 0xbc00>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <30 IRQ_TYPE_LEVEL_HIGH 0>,
+ <69 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "int0", "int1";
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 30>, <&pmc PMC_TYPE_GCK 30>;
+ clock-names = "hclk", "cclk";
+ assigned-clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>, <&pmc PMC_TYPE_GCK 30>;
+ assigned-clock-rates = <480000000>, <40000000>;
+ assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>, <&pmc PMC_TYPE_CORE PMC_UTMI>;
+ bosch,mram-cfg = <0x7800 0 0 64 0 0 32 32>;
+ status = "disabled";
+ };
+
+ tcb: timer@f8008000 {
+ compatible = "microchip,sam9x7-tcb","atmel,sama5d2-tcb", "simple-mfd", "syscon";
+ reg = <0xf8008000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <17 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 17>, <&pmc PMC_TYPE_GCK 17>, <&clk32k 0>;
+ clock-names = "t0_clk", "gclk", "slow_clk";
+ };
+
+ flx6: flexcom@f8010000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8010000 0x200>;
+ ranges = <0x0 0xf8010000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 9>;
+ status = "disabled";
+
+ uart6: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 9>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(12))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(13))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ i2c6: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 9>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(12))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(13))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx7: flexcom@f8014000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8014000 0x200>;
+ ranges = <0x0 0xf8014000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 10>;
+ status = "disabled";
+
+ uart7: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 10>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(14))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(15))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ i2c7: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 10>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(14))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(15))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx8: flexcom@f8018000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8018000 0x200>;
+ ranges = <0x0 0xf8018000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 11>;
+ status = "disabled";
+
+ uart8: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 11>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(16))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(17))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ i2c8: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 11>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(16))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(17))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx0: flexcom@f801c000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf801c000 0x200>;
+ ranges = <0x0 0xf801c000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
+ status = "disabled";
+
+ uart0: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(0))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(1))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ spi0: spi@400 {
+ compatible = "microchip,sam9x7-spi", "atmel,at91rm9200-spi";
+ reg = <0x400 0x200>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
+ clock-names = "spi_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(0))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(1))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(0))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(1))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx1: flexcom@f8020000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8020000 0x200>;
+ ranges = <0x0 0xf8020000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 6>;
+ status = "disabled";
+
+ uart1: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 6>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(2))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(3))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ spi1: spi@400 {
+ compatible = "microchip,sam9x7-spi", "atmel,at91rm9200-spi";
+ reg = <0x400 0x200>;
+ interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 6>;
+ clock-names = "spi_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(2))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(3))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 6>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(2))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(3))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx2: flexcom@f8024000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8024000 0x200>;
+ ranges = <0x0 0xf8024000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 7>;
+ status = "disabled";
+
+ uart2: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 7>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(4))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(5))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ spi2: spi@400 {
+ compatible = "microchip,sam9x7-spi", "atmel,at91rm9200-spi";
+ reg = <0x400 0x200>;
+ interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 7>;
+ clock-names = "spi_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(4))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(5))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 7>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(4))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(5))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx3: flexcom@f8028000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8028000 0x200>;
+ ranges = <0x0 0xf8028000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 8>;
+ status = "disabled";
+
+ uart3: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 8>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(6))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(7))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ spi3: spi@400 {
+ compatible = "microchip,sam9x7-spi", "atmel,at91rm9200-spi";
+ reg = <0x400 0x200>;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 8>;
+ clock-names = "spi_clk";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(6))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(7))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 8>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(6))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(7))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ gmac: ethernet@f802c000 {
+ compatible = "microchip,sam9x7-gem", "microchip,sama7g5-gem";
+ reg = <0xf802c000 0x1000>;
+ interrupts = <24 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 0 */
+ <60 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 1 */
+ <61 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 2 */
+ <62 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 3 */
+ <63 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 4 */
+ <64 IRQ_TYPE_LEVEL_HIGH 3>; /* Queue 5 */
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>, <&pmc PMC_TYPE_GCK 67>;
+ clock-names = "hclk", "pclk", "tx_clk", "tsu_clk";
+ assigned-clocks = <&pmc PMC_TYPE_GCK 67>;
+ assigned-clock-rates = <266666666>;
+ status = "disabled";
+ };
+
+ pwm0: pwm@f8034000 {
+ compatible = "microchip,sam9x7-pwm", "microchip,sam9x60-pwm";
+ reg = <0xf8034000 0x300>;
+ interrupts = <18 IRQ_TYPE_LEVEL_HIGH 4>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 18>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ flx9: flexcom@f8040000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8040000 0x200>;
+ ranges = <0x0 0xf8040000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 15>;
+ status = "disabled";
+
+ uart9: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 15>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(18))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(19))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ i2c9: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 15>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(18))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(19))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ flx10: flexcom@f8044000 {
+ compatible = "microchip,sam9x7-flexcom", "atmel,sama5d2-flexcom";
+ reg = <0xf8044000 0x200>;
+ ranges = <0x0 0xf8044000 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 16>;
+ status = "disabled";
+
+ uart10: serial@200 {
+ compatible = "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0x200 0x200>;
+ interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 16>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(20))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(21))>;
+ dma-names = "tx", "rx";
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ atmel,fifo-size = <16>;
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ i2c10: i2c@600 {
+ compatible = "microchip,sam9x7-i2c", "microchip,sam9x60-i2c";
+ reg = <0x600 0x200>;
+ interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 16>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(20))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) |
+ AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(21))>;
+ dma-names = "tx", "rx";
+ atmel,fifo-size = <16>;
+ status = "disabled";
+ };
+ };
+
+ matrix: matrix@ffffde00 {
+ compatible = "microchip,sam9x7-matrix", "atmel,at91sam9x5-matrix", "syscon";
+ reg = <0xffffde00 0x200>;
+ };
+
+ pmecc: ecc-engine@ffffe000 {
+ compatible = "microchip,sam9x7-pmecc", "atmel,at91sam9g45-pmecc";
+ reg = <0xffffe000 0x300>, <0xffffe600 0x100>;
+ };
+
+ mpddrc: mpddrc@ffffe800 {
+ compatible = "microchip,sam9x7-ddramc", "atmel,sama5d3-ddramc";
+ reg = <0xffffe800 0x200>;
+ clocks = <&pmc PMC_TYPE_SYSTEM 2>, <&pmc PMC_TYPE_CORE PMC_MCK>;
+ clock-names = "ddrck", "mpddr";
+ };
+
+ smc: smc@ffffea00 {
+ compatible = "microchip,sam9x7-smc", "atmel,at91sam9260-smc", "syscon";
+ reg = <0xffffea00 0x100>;
+ };
+
+ aic: interrupt-controller@fffff100 {
+ compatible = "microchip,sam9x7-aic";
+ reg = <0xfffff100 0x100>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ atmel,external-irqs = <31>;
+ };
+
+ dbgu: serial@fffff200 {
+ compatible = "microchip,sam9x7-dbgu", "atmel,at91sam9260-dbgu", "microchip,sam9x7-usart", "atmel,at91sam9260-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <47 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 47>;
+ clock-names = "usart";
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(28))>,
+ <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(29))>;
+ dma-names = "tx", "rx";
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
+ status = "disabled";
+ };
+
+ pinctrl: pinctrl@fffff400 {
+ compatible = "microchip,sam9x7-pinctrl", "microchip,sam9x60-pinctrl", "simple-mfd";
+ ranges = <0xfffff400 0xfffff400 0x800>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* mux-mask corresponding to sam9x7 SoC in TFBGA228L package */
+ atmel,mux-mask = <
+ /* A B C D */
+ 0xffffffff 0xffffefc0 0xc0ffd000 0x00000000 /* pioA */
+ 0x07ffffff 0x0805fe7f 0x01ff9f81 0x06078000 /* pioB */
+ 0xffffffff 0x07dfffff 0xfa3fffff 0x00000000 /* pioC */
+ 0x00003fff 0x00003fe0 0x0000003f 0x00000000 /* pioD */
+ >;
+
+ pioA: gpio@fffff400 {
+ compatible = "microchip,sam9x7-gpio", "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH 1>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ gpio-controller;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 2>;
+ };
+
+ pioB: gpio@fffff600 {
+ compatible = "microchip,sam9x7-gpio", "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x200>;
+ interrupts = <3 IRQ_TYPE_LEVEL_HIGH 1>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ gpio-controller;
+ #gpio-lines = <26>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 3>;
+ };
+
+ pioC: gpio@fffff800 {
+ compatible = "microchip,sam9x7-gpio", "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x200>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH 1>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ gpio-controller;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 4>;
+ };
+
+ pioD: gpio@fffffa00 {
+ compatible = "microchip,sam9x7-gpio", "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x200>;
+ interrupts = <44 IRQ_TYPE_LEVEL_HIGH 1>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ gpio-controller;
+ #gpio-lines = <22>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 44>;
+ };
+ };
+
+ pmc: clock-controller@fffffc00 {
+ compatible = "microchip,sam9x7-pmc", "syscon";
+ reg = <0xfffffc00 0x200>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ #clock-cells = <2>;
+ clocks = <&clk32k 1>, <&clk32k 0>, <&main_xtal>;
+ clock-names = "td_slck", "md_slck", "main_xtal";
+ };
+
+ reset_controller: reset-controller@fffffe00 {
+ compatible = "microchip,sam9x7-rstc", "microchip,sam9x60-rstc";
+ reg = <0xfffffe00 0x10>;
+ clocks = <&clk32k 0>;
+ };
+
+ poweroff: poweroff@fffffe10 {
+ compatible = "microchip,sam9x7-shdwc", "microchip,sam9x60-shdwc";
+ reg = <0xfffffe10 0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clk32k 0>;
+ atmel,wakeup-rtc-timer;
+ atmel,wakeup-rtt-timer;
+ status = "disabled";
+ };
+
+ rtt: rtc@fffffe20 {
+ compatible = "microchip,sam9x7-rtt", "atmel,at91sam9260-rtt";
+ reg = <0xfffffe20 0x20>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&clk32k 0>;
+ };
+
+ clk32k: clock-controller@fffffe50 {
+ compatible = "microchip,sam9x7-sckc", "microchip,sam9x60-sckc";
+ reg = <0xfffffe50 0x4>;
+ clocks = <&slow_xtal>;
+ #clock-cells = <1>;
+ };
+
+ gpbr: syscon@fffffe60 {
+ compatible = "microchip,sam9x7-gpbr", "atmel,at91sam9260-gpbr", "syscon";
+ reg = <0xfffffe60 0x10>;
+ };
+
+ rtc: rtc@fffffea8 {
+ compatible = "microchip,sam9x7-rtc", "microchip,sam9x60-rtc";
+ reg = <0xfffffea8 0x100>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&clk32k 0>;
+ };
+
+ watchdog: watchdog@ffffff80 {
+ compatible = "microchip,sam9x7-wdt", "microchip,sam9x60-wdt";
+ reg = <0xffffff80 0x24>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/microchip/sama5d2.dtsi b/arch/arm/boot/dts/microchip/sama5d2.dtsi
index 5f8e297e19ed..3f99451aef83 100644
--- a/arch/arm/boot/dts/microchip/sama5d2.dtsi
+++ b/arch/arm/boot/dts/microchip/sama5d2.dtsi
@@ -1019,7 +1019,7 @@
};
};
- trng@fc01c000 {
+ trng: rng@fc01c000 {
compatible = "atmel,at91sam9g45-trng";
reg = <0xfc01c000 0x100>;
interrupts = <47 IRQ_TYPE_LEVEL_HIGH 0>;
diff --git a/arch/arm/boot/dts/microchip/sama5d3.dtsi b/arch/arm/boot/dts/microchip/sama5d3.dtsi
index 39865133aa56..70f380c399ce 100644
--- a/arch/arm/boot/dts/microchip/sama5d3.dtsi
+++ b/arch/arm/boot/dts/microchip/sama5d3.dtsi
@@ -419,7 +419,7 @@
clock-names = "tdes_clk";
};
- trng@f8040000 {
+ trng: rng@f8040000 {
compatible = "atmel,at91sam9g45-trng";
reg = <0xf8040000 0x100>;
interrupts = <45 IRQ_TYPE_LEVEL_HIGH 0>;
diff --git a/arch/arm/boot/dts/microchip/sama5d34ek.dts b/arch/arm/boot/dts/microchip/sama5d34ek.dts
index bffd61397cb5..18943b873fff 100644
--- a/arch/arm/boot/dts/microchip/sama5d34ek.dts
+++ b/arch/arm/boot/dts/microchip/sama5d34ek.dts
@@ -36,7 +36,7 @@
i2c1: i2c@f0018000 {
status = "okay";
- 24c256@50 {
+ eeprom@50 {
compatible = "atmel,24c256";
reg = <0x50>;
pagesize = <64>;
diff --git a/arch/arm/boot/dts/microchip/sama5d3xcm_cmp.dtsi b/arch/arm/boot/dts/microchip/sama5d3xcm_cmp.dtsi
index 830a0954ba1b..362806afef44 100644
--- a/arch/arm/boot/dts/microchip/sama5d3xcm_cmp.dtsi
+++ b/arch/arm/boot/dts/microchip/sama5d3xcm_cmp.dtsi
@@ -79,7 +79,7 @@
};
i2c1: i2c@f0018000 {
- pmic: act8865@5b {
+ act8865: pmic@5b {
compatible = "active-semi,act8865";
reg = <0x5b>;
status = "disabled";
diff --git a/arch/arm/boot/dts/microchip/sama5d4.dtsi b/arch/arm/boot/dts/microchip/sama5d4.dtsi
index b253ba33fc38..355132628604 100644
--- a/arch/arm/boot/dts/microchip/sama5d4.dtsi
+++ b/arch/arm/boot/dts/microchip/sama5d4.dtsi
@@ -658,7 +658,7 @@
status = "disabled";
};
- trng@fc030000 {
+ trng: rng@fc030000 {
compatible = "atmel,at91sam9g45-trng";
reg = <0xfc030000 0x100>;
interrupts = <53 IRQ_TYPE_LEVEL_HIGH 0>;
diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile
index 92e291603ea1..39a153536d2a 100644
--- a/arch/arm/boot/dts/nxp/imx/Makefile
+++ b/arch/arm/boot/dts/nxp/imx/Makefile
@@ -73,6 +73,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-cubox-i-emmc-som-v15.dtb \
imx6dl-cubox-i-som-v15.dtb \
imx6dl-dfi-fs700-m60.dtb \
+ imx6dl-dhcom-pdk2.dtb \
imx6dl-dhcom-picoitx.dtb \
imx6dl-eckelmann-ci4x10.dtb \
imx6dl-emcon-avari.dtb \
@@ -211,6 +212,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-kontron-samx6i-ads2.dtb \
imx6q-kp-tpc.dtb \
imx6q-logicpd.dtb \
+ imx6q-lxr.dtb \
imx6q-marsboard.dtb \
imx6q-mba6a.dtb \
imx6q-mba6b.dtb \
@@ -290,6 +292,8 @@ dtb-$(CONFIG_SOC_IMX6SL) += \
dtb-$(CONFIG_SOC_IMX6SLL) += \
imx6sll-evk.dtb \
imx6sll-kobo-clarahd.dtb \
+ imx6sll-kobo-clara2e-a.dtb \
+ imx6sll-kobo-clara2e-b.dtb \
imx6sll-kobo-librah2o.dtb
dtb-$(CONFIG_SOC_IMX6SX) += \
imx6sx-nitrogen6sx.dtb \
diff --git a/arch/arm/boot/dts/nxp/imx/imx35-eukrea-cpuimx35.dtsi b/arch/arm/boot/dts/nxp/imx/imx35-eukrea-cpuimx35.dtsi
index 17bd2a97609a..ef546525e2ec 100644
--- a/arch/arm/boot/dts/nxp/imx/imx35-eukrea-cpuimx35.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx35-eukrea-cpuimx35.dtsi
@@ -44,40 +44,38 @@
};
&iomuxc {
- imx35-eukrea {
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX35_PAD_FEC_TX_CLK__FEC_TX_CLK 0x80000000
- MX35_PAD_FEC_RX_CLK__FEC_RX_CLK 0x80000000
- MX35_PAD_FEC_RX_DV__FEC_RX_DV 0x80000000
- MX35_PAD_FEC_COL__FEC_COL 0x80000000
- MX35_PAD_FEC_RDATA0__FEC_RDATA_0 0x80000000
- MX35_PAD_FEC_TDATA0__FEC_TDATA_0 0x80000000
- MX35_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
- MX35_PAD_FEC_MDC__FEC_MDC 0x80000000
- MX35_PAD_FEC_MDIO__FEC_MDIO 0x80000000
- MX35_PAD_FEC_TX_ERR__FEC_TX_ERR 0x80000000
- MX35_PAD_FEC_RX_ERR__FEC_RX_ERR 0x80000000
- MX35_PAD_FEC_CRS__FEC_CRS 0x80000000
- MX35_PAD_FEC_RDATA1__FEC_RDATA_1 0x80000000
- MX35_PAD_FEC_TDATA1__FEC_TDATA_1 0x80000000
- MX35_PAD_FEC_RDATA2__FEC_RDATA_2 0x80000000
- MX35_PAD_FEC_TDATA2__FEC_TDATA_2 0x80000000
- MX35_PAD_FEC_RDATA3__FEC_RDATA_3 0x80000000
- MX35_PAD_FEC_TDATA3__FEC_TDATA_3 0x80000000
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX35_PAD_FEC_TX_CLK__FEC_TX_CLK 0x80000000
+ MX35_PAD_FEC_RX_CLK__FEC_RX_CLK 0x80000000
+ MX35_PAD_FEC_RX_DV__FEC_RX_DV 0x80000000
+ MX35_PAD_FEC_COL__FEC_COL 0x80000000
+ MX35_PAD_FEC_RDATA0__FEC_RDATA_0 0x80000000
+ MX35_PAD_FEC_TDATA0__FEC_TDATA_0 0x80000000
+ MX35_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
+ MX35_PAD_FEC_MDC__FEC_MDC 0x80000000
+ MX35_PAD_FEC_MDIO__FEC_MDIO 0x80000000
+ MX35_PAD_FEC_TX_ERR__FEC_TX_ERR 0x80000000
+ MX35_PAD_FEC_RX_ERR__FEC_RX_ERR 0x80000000
+ MX35_PAD_FEC_CRS__FEC_CRS 0x80000000
+ MX35_PAD_FEC_RDATA1__FEC_RDATA_1 0x80000000
+ MX35_PAD_FEC_TDATA1__FEC_TDATA_1 0x80000000
+ MX35_PAD_FEC_RDATA2__FEC_RDATA_2 0x80000000
+ MX35_PAD_FEC_TDATA2__FEC_TDATA_2 0x80000000
+ MX35_PAD_FEC_RDATA3__FEC_RDATA_3 0x80000000
+ MX35_PAD_FEC_TDATA3__FEC_TDATA_3 0x80000000
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX35_PAD_I2C1_CLK__I2C1_SCL 0x80000000
- MX35_PAD_I2C1_DAT__I2C1_SDA 0x80000000
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX35_PAD_I2C1_CLK__I2C1_SCL 0x80000000
+ MX35_PAD_I2C1_DAT__I2C1_SDA 0x80000000
+ >;
+ };
- pinctrl_tsc2007_1: tsc2007grp-1 {
- fsl,pins = <MX35_PAD_ATA_DA2__GPIO3_2 0x80000000>;
- };
+ pinctrl_tsc2007_1: tsc2007-1-grp {
+ fsl,pins = <MX35_PAD_ATA_DA2__GPIO3_2 0x80000000>;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx35-eukrea-mbimxsd35-baseboard.dts b/arch/arm/boot/dts/nxp/imx/imx35-eukrea-mbimxsd35-baseboard.dts
index 7f4f812b0811..e7835a769bbc 100644
--- a/arch/arm/boot/dts/nxp/imx/imx35-eukrea-mbimxsd35-baseboard.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx35-eukrea-mbimxsd35-baseboard.dts
@@ -69,57 +69,55 @@
};
&iomuxc {
- imx35-eukrea {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS 0x80000000
- MX35_PAD_STXD4__AUDMUX_AUD4_TXD 0x80000000
- MX35_PAD_SRXD4__AUDMUX_AUD4_RXD 0x80000000
- MX35_PAD_SCK4__AUDMUX_AUD4_TXC 0x80000000
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS 0x80000000
+ MX35_PAD_STXD4__AUDMUX_AUD4_TXD 0x80000000
+ MX35_PAD_SRXD4__AUDMUX_AUD4_RXD 0x80000000
+ MX35_PAD_SCK4__AUDMUX_AUD4_TXC 0x80000000
+ >;
+ };
- pinctrl_bp1: bp1grp {
- fsl,pins = <MX35_PAD_LD19__GPIO3_25 0x80000000>;
- };
+ pinctrl_bp1: bp1grp {
+ fsl,pins = <MX35_PAD_LD19__GPIO3_25 0x80000000>;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX35_PAD_SD1_CMD__ESDHC1_CMD 0x80000000
- MX35_PAD_SD1_CLK__ESDHC1_CLK 0x80000000
- MX35_PAD_SD1_DATA0__ESDHC1_DAT0 0x80000000
- MX35_PAD_SD1_DATA1__ESDHC1_DAT1 0x80000000
- MX35_PAD_SD1_DATA2__ESDHC1_DAT2 0x80000000
- MX35_PAD_SD1_DATA3__ESDHC1_DAT3 0x80000000
- MX35_PAD_LD18__GPIO3_24 0x80000000 /* CD */
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX35_PAD_SD1_CMD__ESDHC1_CMD 0x80000000
+ MX35_PAD_SD1_CLK__ESDHC1_CLK 0x80000000
+ MX35_PAD_SD1_DATA0__ESDHC1_DAT0 0x80000000
+ MX35_PAD_SD1_DATA1__ESDHC1_DAT1 0x80000000
+ MX35_PAD_SD1_DATA2__ESDHC1_DAT2 0x80000000
+ MX35_PAD_SD1_DATA3__ESDHC1_DAT3 0x80000000
+ MX35_PAD_LD18__GPIO3_24 0x80000000 /* CD */
+ >;
+ };
- pinctrl_led1: led1grp {
- fsl,pins = <MX35_PAD_LD23__GPIO3_29 0x80000000>;
- };
+ pinctrl_led1: led1grp {
+ fsl,pins = <MX35_PAD_LD23__GPIO3_29 0x80000000>;
+ };
- pinctrl_reg_lcd_3v3: reg-lcd-3v3 {
- fsl,pins = <MX35_PAD_D3_CLS__GPIO1_4 0x80000000>;
- };
+ pinctrl_reg_lcd_3v3: reg-lcd-3v3grp {
+ fsl,pins = <MX35_PAD_D3_CLS__GPIO1_4 0x80000000>;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX35_PAD_TXD1__UART1_TXD_MUX 0x1c5
- MX35_PAD_RXD1__UART1_RXD_MUX 0x1c5
- MX35_PAD_CTS1__UART1_CTS 0x1c5
- MX35_PAD_RTS1__UART1_RTS 0x1c5
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX35_PAD_TXD1__UART1_TXD_MUX 0x1c5
+ MX35_PAD_RXD1__UART1_RXD_MUX 0x1c5
+ MX35_PAD_CTS1__UART1_CTS 0x1c5
+ MX35_PAD_RTS1__UART1_RTS 0x1c5
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX35_PAD_RXD2__UART2_RXD_MUX 0x1c5
- MX35_PAD_TXD2__UART2_TXD_MUX 0x1c5
- MX35_PAD_RTS2__UART2_RTS 0x1c5
- MX35_PAD_CTS2__UART2_CTS 0x1c5
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX35_PAD_RXD2__UART2_RXD_MUX 0x1c5
+ MX35_PAD_TXD2__UART2_TXD_MUX 0x1c5
+ MX35_PAD_RTS2__UART2_RTS 0x1c5
+ MX35_PAD_CTS2__UART2_CTS 0x1c5
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx35-pdk.dts b/arch/arm/boot/dts/nxp/imx/imx35-pdk.dts
index ddce0a844758..a2baf8202f94 100644
--- a/arch/arm/boot/dts/nxp/imx/imx35-pdk.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx35-pdk.dts
@@ -24,26 +24,24 @@
};
&iomuxc {
- imx35-pdk {
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX35_PAD_SD1_CMD__ESDHC1_CMD 0x80000000
- MX35_PAD_SD1_CLK__ESDHC1_CLK 0x80000000
- MX35_PAD_SD1_DATA0__ESDHC1_DAT0 0x80000000
- MX35_PAD_SD1_DATA1__ESDHC1_DAT1 0x80000000
- MX35_PAD_SD1_DATA2__ESDHC1_DAT2 0x80000000
- MX35_PAD_SD1_DATA3__ESDHC1_DAT3 0x80000000
- >;
- };
-
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX35_PAD_TXD1__UART1_TXD_MUX 0x1c5
- MX35_PAD_RXD1__UART1_RXD_MUX 0x1c5
- MX35_PAD_CTS1__UART1_CTS 0x1c5
- MX35_PAD_RTS1__UART1_RTS 0x1c5
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX35_PAD_SD1_CMD__ESDHC1_CMD 0x80000000
+ MX35_PAD_SD1_CLK__ESDHC1_CLK 0x80000000
+ MX35_PAD_SD1_DATA0__ESDHC1_DAT0 0x80000000
+ MX35_PAD_SD1_DATA1__ESDHC1_DAT1 0x80000000
+ MX35_PAD_SD1_DATA2__ESDHC1_DAT2 0x80000000
+ MX35_PAD_SD1_DATA3__ESDHC1_DAT3 0x80000000
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX35_PAD_TXD1__UART1_TXD_MUX 0x1c5
+ MX35_PAD_RXD1__UART1_RXD_MUX 0x1c5
+ MX35_PAD_CTS1__UART1_CTS 0x1c5
+ MX35_PAD_RTS1__UART1_RTS 0x1c5
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx35.dtsi b/arch/arm/boot/dts/nxp/imx/imx35.dtsi
index 442dc15677b8..30beb39e0162 100644
--- a/arch/arm/boot/dts/nxp/imx/imx35.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx35.dtsi
@@ -156,7 +156,7 @@
status = "disabled";
};
- iomuxc: iomuxc@43fac000 {
+ iomuxc: pinctrl@43fac000 {
compatible = "fsl,imx35-iomuxc";
reg = <0x43fac000 0x4000>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx50-evk.dts b/arch/arm/boot/dts/nxp/imx/imx50-evk.dts
index 3f45c01d9cce..f40b0d5fdb85 100644
--- a/arch/arm/boot/dts/nxp/imx/imx50-evk.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx50-evk.dts
@@ -52,40 +52,38 @@
};
&iomuxc {
- imx50-evk {
- pinctrl_cspi: cspigrp {
- fsl,pins = <
- MX50_PAD_CSPI_SCLK__CSPI_SCLK 0x00
- MX50_PAD_CSPI_MISO__CSPI_MISO 0x00
- MX50_PAD_CSPI_MOSI__CSPI_MOSI 0x00
- MX50_PAD_CSPI_SS0__GPIO4_11 0xc4
- MX50_PAD_ECSPI1_MOSI__GPIO4_13 0x84
- >;
- };
+ pinctrl_cspi: cspigrp {
+ fsl,pins = <
+ MX50_PAD_CSPI_SCLK__CSPI_SCLK 0x00
+ MX50_PAD_CSPI_MISO__CSPI_MISO 0x00
+ MX50_PAD_CSPI_MOSI__CSPI_MOSI 0x00
+ MX50_PAD_CSPI_SS0__GPIO4_11 0xc4
+ MX50_PAD_ECSPI1_MOSI__GPIO4_13 0x84
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX50_PAD_SSI_RXFS__FEC_MDC 0x80
- MX50_PAD_SSI_RXC__FEC_MDIO 0x80
- MX50_PAD_DISP_D0__FEC_TX_CLK 0x80
- MX50_PAD_DISP_D1__FEC_RX_ERR 0x80
- MX50_PAD_DISP_D2__FEC_RX_DV 0x80
- MX50_PAD_DISP_D3__FEC_RDATA_1 0x80
- MX50_PAD_DISP_D4__FEC_RDATA_0 0x80
- MX50_PAD_DISP_D5__FEC_TX_EN 0x80
- MX50_PAD_DISP_D6__FEC_TDATA_1 0x80
- MX50_PAD_DISP_D7__FEC_TDATA_0 0x80
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX50_PAD_SSI_RXFS__FEC_MDC 0x80
+ MX50_PAD_SSI_RXC__FEC_MDIO 0x80
+ MX50_PAD_DISP_D0__FEC_TX_CLK 0x80
+ MX50_PAD_DISP_D1__FEC_RX_ERR 0x80
+ MX50_PAD_DISP_D2__FEC_RX_DV 0x80
+ MX50_PAD_DISP_D3__FEC_RDATA_1 0x80
+ MX50_PAD_DISP_D4__FEC_RDATA_0 0x80
+ MX50_PAD_DISP_D5__FEC_TX_EN 0x80
+ MX50_PAD_DISP_D6__FEC_TDATA_1 0x80
+ MX50_PAD_DISP_D7__FEC_TDATA_0 0x80
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX50_PAD_UART1_TXD__UART1_TXD_MUX 0x1e4
- MX50_PAD_UART1_RXD__UART1_RXD_MUX 0x1e4
- MX50_PAD_UART1_RTS__UART1_RTS 0x1e4
- MX50_PAD_UART1_CTS__UART1_CTS 0x1e4
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX50_PAD_UART1_TXD__UART1_TXD_MUX 0x1e4
+ MX50_PAD_UART1_RXD__UART1_RXD_MUX 0x1e4
+ MX50_PAD_UART1_RTS__UART1_RTS 0x1e4
+ MX50_PAD_UART1_CTS__UART1_CTS 0x1e4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx50.dtsi b/arch/arm/boot/dts/nxp/imx/imx50.dtsi
index c5b25d2f6264..1b6f444443dd 100644
--- a/arch/arm/boot/dts/nxp/imx/imx50.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx50.dtsi
@@ -283,7 +283,7 @@
clock-names = "ipg", "per";
};
- iomuxc: iomuxc@53fa8000 {
+ iomuxc: pinctrl@53fa8000 {
compatible = "fsl,imx50-iomuxc", "fsl,imx53-iomuxc";
reg = <0x53fa8000 0x4000>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-apf51.dts b/arch/arm/boot/dts/nxp/imx/imx51-apf51.dts
index ba28ffe06fe2..670e13136f1f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-apf51.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-apf51.dts
@@ -37,36 +37,34 @@
};
&iomuxc {
- imx51-apf51 {
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX51_PAD_DI_GP3__FEC_TX_ER 0x80000000
- MX51_PAD_DI2_PIN4__FEC_CRS 0x80000000
- MX51_PAD_DI2_PIN2__FEC_MDC 0x80000000
- MX51_PAD_DI2_PIN3__FEC_MDIO 0x80000000
- MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
- MX51_PAD_DI_GP4__FEC_RDATA2 0x80000000
- MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x80000000
- MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x80000000
- MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x80000000
- MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x80000000
- MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x80000000
- MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x80000000
- MX51_PAD_DISP2_DAT10__FEC_COL 0x80000000
- MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x80000000
- MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x80000000
- MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x80000000
- MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x80000000
- MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x80000000
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX51_PAD_DI_GP3__FEC_TX_ER 0x80000000
+ MX51_PAD_DI2_PIN4__FEC_CRS 0x80000000
+ MX51_PAD_DI2_PIN2__FEC_MDC 0x80000000
+ MX51_PAD_DI2_PIN3__FEC_MDIO 0x80000000
+ MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
+ MX51_PAD_DI_GP4__FEC_RDATA2 0x80000000
+ MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x80000000
+ MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x80000000
+ MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x80000000
+ MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x80000000
+ MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x80000000
+ MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x80000000
+ MX51_PAD_DISP2_DAT10__FEC_COL 0x80000000
+ MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x80000000
+ MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x80000000
+ MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x80000000
+ MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x80000000
+ MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x80000000
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
- MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
+ MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts b/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts
index de6b7607510a..6ebd80e30683 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts
@@ -113,102 +113,100 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx51-apf51dev {
- pinctrl_backlight: backlightgrp {
- fsl,pins = <
- MX51_PAD_DI1_D1_CS__GPIO3_4 0x1F5
- >;
- };
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX51_PAD_DI1_D1_CS__GPIO3_4 0x1F5
+ >;
+ };
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX51_PAD_EIM_EB2__GPIO2_22 0x0C5
- MX51_PAD_EIM_EB3__GPIO2_23 0x0C5
- MX51_PAD_EIM_CS4__GPIO2_29 0x100
- MX51_PAD_NANDF_D13__GPIO3_27 0x0C5
- MX51_PAD_NANDF_D12__GPIO3_28 0x0C5
- MX51_PAD_CSPI1_SS0__GPIO4_24 0x0C5
- MX51_PAD_CSPI1_SS1__GPIO4_25 0x0C5
- MX51_PAD_GPIO1_2__GPIO1_2 0x0C5
- MX51_PAD_GPIO1_3__GPIO1_3 0x0C5
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX51_PAD_EIM_EB2__GPIO2_22 0x0C5
+ MX51_PAD_EIM_EB3__GPIO2_23 0x0C5
+ MX51_PAD_EIM_CS4__GPIO2_29 0x100
+ MX51_PAD_NANDF_D13__GPIO3_27 0x0C5
+ MX51_PAD_NANDF_D12__GPIO3_28 0x0C5
+ MX51_PAD_CSPI1_SS0__GPIO4_24 0x0C5
+ MX51_PAD_CSPI1_SS1__GPIO4_25 0x0C5
+ MX51_PAD_GPIO1_2__GPIO1_2 0x0C5
+ MX51_PAD_GPIO1_3__GPIO1_3 0x0C5
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
- MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
- MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
+ >;
+ };
- pinctrl_ecspi2: ecspi2grp {
- fsl,pins = <
- MX51_PAD_NANDF_RB3__ECSPI2_MISO 0x185
- MX51_PAD_NANDF_D15__ECSPI2_MOSI 0x185
- MX51_PAD_NANDF_RB2__ECSPI2_SCLK 0x185
- >;
- };
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX51_PAD_NANDF_RB3__ECSPI2_MISO 0x185
+ MX51_PAD_NANDF_D15__ECSPI2_MOSI 0x185
+ MX51_PAD_NANDF_RB2__ECSPI2_SCLK 0x185
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
- MX51_PAD_SD1_CLK__SD1_CLK 0x20d5
- MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
- MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
- MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
- MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
+ MX51_PAD_SD1_CLK__SD1_CLK 0x20d5
+ MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
+ MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
+ MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
+ MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
+ >;
+ };
- pinctrl_esdhc2: esdhc2grp {
- fsl,pins = <
- MX51_PAD_SD2_CMD__SD2_CMD 0x400020d5
- MX51_PAD_SD2_CLK__SD2_CLK 0x20d5
- MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
- MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
- MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
- MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
- >;
- };
+ pinctrl_esdhc2: esdhc2grp {
+ fsl,pins = <
+ MX51_PAD_SD2_CMD__SD2_CMD 0x400020d5
+ MX51_PAD_SD2_CLK__SD2_CLK 0x20d5
+ MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
+ MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
+ MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
+ MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX51_PAD_EIM_D27__I2C2_SCL 0x400001ed
- MX51_PAD_EIM_D24__I2C2_SDA 0x400001ed
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX51_PAD_EIM_D27__I2C2_SCL 0x400001ed
+ MX51_PAD_EIM_D24__I2C2_SDA 0x400001ed
+ >;
+ };
- pinctrl_ipu_disp1: ipudisp1grp {
- fsl,pins = <
- MX51_PAD_DISP1_DAT0__DISP1_DAT0 0x5
- MX51_PAD_DISP1_DAT1__DISP1_DAT1 0x5
- MX51_PAD_DISP1_DAT2__DISP1_DAT2 0x5
- MX51_PAD_DISP1_DAT3__DISP1_DAT3 0x5
- MX51_PAD_DISP1_DAT4__DISP1_DAT4 0x5
- MX51_PAD_DISP1_DAT5__DISP1_DAT5 0x5
- MX51_PAD_DISP1_DAT6__DISP1_DAT6 0x5
- MX51_PAD_DISP1_DAT7__DISP1_DAT7 0x5
- MX51_PAD_DISP1_DAT8__DISP1_DAT8 0x5
- MX51_PAD_DISP1_DAT9__DISP1_DAT9 0x5
- MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
- MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
- MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
- MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
- MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
- MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
- MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
- MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
- MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
- MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
- MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
- MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
- MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
- MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
- MX51_PAD_DI1_PIN2__DI1_PIN2 0x5
- MX51_PAD_DI1_PIN3__DI1_PIN3 0x5
- >;
- };
+ pinctrl_ipu_disp1: ipudisp1grp {
+ fsl,pins = <
+ MX51_PAD_DISP1_DAT0__DISP1_DAT0 0x5
+ MX51_PAD_DISP1_DAT1__DISP1_DAT1 0x5
+ MX51_PAD_DISP1_DAT2__DISP1_DAT2 0x5
+ MX51_PAD_DISP1_DAT3__DISP1_DAT3 0x5
+ MX51_PAD_DISP1_DAT4__DISP1_DAT4 0x5
+ MX51_PAD_DISP1_DAT5__DISP1_DAT5 0x5
+ MX51_PAD_DISP1_DAT6__DISP1_DAT6 0x5
+ MX51_PAD_DISP1_DAT7__DISP1_DAT7 0x5
+ MX51_PAD_DISP1_DAT8__DISP1_DAT8 0x5
+ MX51_PAD_DISP1_DAT9__DISP1_DAT9 0x5
+ MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
+ MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
+ MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
+ MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
+ MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
+ MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
+ MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
+ MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
+ MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
+ MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
+ MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
+ MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
+ MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
+ MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
+ MX51_PAD_DI1_PIN2__DI1_PIN2 0x5
+ MX51_PAD_DI1_PIN3__DI1_PIN3 0x5
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts b/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts
index f4a47e8348b2..1b6ec55f9068 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts
@@ -474,246 +474,244 @@
};
&iomuxc {
- imx51-babbage {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000
- MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000
- MX51_PAD_AUD3_BB_CK__AUD3_TXC 0x80000000
- MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000
+ MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000
+ MX51_PAD_AUD3_BB_CK__AUD3_TXC 0x80000000
+ MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000
+ >;
+ };
- pinctrl_clk26mhz_audio: clk26mhzaudiocgrp {
- fsl,pins = <
- MX51_PAD_CSPI1_RDY__GPIO4_26 0x85
- >;
- };
+ pinctrl_clk26mhz_audio: clk26mhzaudiocgrp {
+ fsl,pins = <
+ MX51_PAD_CSPI1_RDY__GPIO4_26 0x85
+ >;
+ };
- pinctrl_clk26mhz_osc: clk26mhzoscgrp {
- fsl,pins = <
- MX51_PAD_DI1_PIN12__GPIO3_1 0x85
- >;
- };
+ pinctrl_clk26mhz_osc: clk26mhzoscgrp {
+ fsl,pins = <
+ MX51_PAD_DI1_PIN12__GPIO3_1 0x85
+ >;
+ };
- pinctrl_clk26mhz_usb: clk26mhzusbgrp {
- fsl,pins = <
- MX51_PAD_EIM_D17__GPIO2_1 0x85
- >;
- };
+ pinctrl_clk26mhz_usb: clk26mhzusbgrp {
+ fsl,pins = <
+ MX51_PAD_EIM_D17__GPIO2_1 0x85
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
- MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
- MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
- MX51_PAD_CSPI1_SS0__GPIO4_24 0x85 /* CS0 */
- MX51_PAD_CSPI1_SS1__GPIO4_25 0x85 /* CS1 */
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
+ MX51_PAD_CSPI1_SS0__GPIO4_24 0x85 /* CS0 */
+ MX51_PAD_CSPI1_SS1__GPIO4_25 0x85 /* CS1 */
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
- MX51_PAD_SD1_CLK__SD1_CLK 0x20d5
- MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
- MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
- MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
- MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
- MX51_PAD_GPIO1_0__GPIO1_0 0x100
- MX51_PAD_GPIO1_1__GPIO1_1 0x100
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
+ MX51_PAD_SD1_CLK__SD1_CLK 0x20d5
+ MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
+ MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
+ MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
+ MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
+ MX51_PAD_GPIO1_0__GPIO1_0 0x100
+ MX51_PAD_GPIO1_1__GPIO1_1 0x100
+ >;
+ };
- pinctrl_esdhc2: esdhc2grp {
- fsl,pins = <
- MX51_PAD_SD2_CMD__SD2_CMD 0x400020d5
- MX51_PAD_SD2_CLK__SD2_CLK 0x20d5
- MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
- MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
- MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
- MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
- MX51_PAD_GPIO1_5__GPIO1_5 0x100 /* WP */
- MX51_PAD_GPIO1_6__GPIO1_6 0x100 /* CD */
- >;
- };
+ pinctrl_esdhc2: esdhc2grp {
+ fsl,pins = <
+ MX51_PAD_SD2_CMD__SD2_CMD 0x400020d5
+ MX51_PAD_SD2_CLK__SD2_CLK 0x20d5
+ MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
+ MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
+ MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
+ MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
+ MX51_PAD_GPIO1_5__GPIO1_5 0x100 /* WP */
+ MX51_PAD_GPIO1_6__GPIO1_6 0x100 /* CD */
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX51_PAD_EIM_EB2__FEC_MDIO 0x000001f5
- MX51_PAD_EIM_EB3__FEC_RDATA1 0x00000085
- MX51_PAD_EIM_CS2__FEC_RDATA2 0x00000085
- MX51_PAD_EIM_CS3__FEC_RDATA3 0x00000085
- MX51_PAD_EIM_CS4__FEC_RX_ER 0x00000180
- MX51_PAD_EIM_CS5__FEC_CRS 0x00000180
- MX51_PAD_NANDF_RB2__FEC_COL 0x00000180
- MX51_PAD_NANDF_RB3__FEC_RX_CLK 0x00000180
- MX51_PAD_NANDF_D9__FEC_RDATA0 0x00002180
- MX51_PAD_NANDF_D8__FEC_TDATA0 0x00002004
- MX51_PAD_NANDF_CS2__FEC_TX_ER 0x00002004
- MX51_PAD_NANDF_CS3__FEC_MDC 0x00002004
- MX51_PAD_NANDF_CS4__FEC_TDATA1 0x00002004
- MX51_PAD_NANDF_CS5__FEC_TDATA2 0x00002004
- MX51_PAD_NANDF_CS6__FEC_TDATA3 0x00002004
- MX51_PAD_NANDF_CS7__FEC_TX_EN 0x00002004
- MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 0x00002180
- MX51_PAD_NANDF_D11__FEC_RX_DV 0x000020a4
- MX51_PAD_EIM_A20__GPIO2_14 0x00000085 /* Phy Reset */
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX51_PAD_EIM_EB2__FEC_MDIO 0x000001f5
+ MX51_PAD_EIM_EB3__FEC_RDATA1 0x00000085
+ MX51_PAD_EIM_CS2__FEC_RDATA2 0x00000085
+ MX51_PAD_EIM_CS3__FEC_RDATA3 0x00000085
+ MX51_PAD_EIM_CS4__FEC_RX_ER 0x00000180
+ MX51_PAD_EIM_CS5__FEC_CRS 0x00000180
+ MX51_PAD_NANDF_RB2__FEC_COL 0x00000180
+ MX51_PAD_NANDF_RB3__FEC_RX_CLK 0x00000180
+ MX51_PAD_NANDF_D9__FEC_RDATA0 0x00002180
+ MX51_PAD_NANDF_D8__FEC_TDATA0 0x00002004
+ MX51_PAD_NANDF_CS2__FEC_TX_ER 0x00002004
+ MX51_PAD_NANDF_CS3__FEC_MDC 0x00002004
+ MX51_PAD_NANDF_CS4__FEC_TDATA1 0x00002004
+ MX51_PAD_NANDF_CS5__FEC_TDATA2 0x00002004
+ MX51_PAD_NANDF_CS6__FEC_TDATA3 0x00002004
+ MX51_PAD_NANDF_CS7__FEC_TX_EN 0x00002004
+ MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 0x00002180
+ MX51_PAD_NANDF_D11__FEC_RX_DV 0x000020a4
+ MX51_PAD_EIM_A20__GPIO2_14 0x00000085 /* Phy Reset */
+ >;
+ };
- pinctrl_gpio_keys: gpiokeysgrp {
- fsl,pins = <
- MX51_PAD_EIM_A27__GPIO2_21 0x5
- >;
- };
+ pinctrl_gpio_keys: gpiokeysgrp {
+ fsl,pins = <
+ MX51_PAD_EIM_A27__GPIO2_21 0x5
+ >;
+ };
- pinctrl_gpio_leds: gpioledsgrp {
- fsl,pins = <
- MX51_PAD_EIM_D22__GPIO2_6 0x80000000
- >;
- };
+ pinctrl_gpio_leds: gpioledsgrp {
+ fsl,pins = <
+ MX51_PAD_EIM_D22__GPIO2_6 0x80000000
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX51_PAD_EIM_D19__I2C1_SCL 0x400001ed
- MX51_PAD_EIM_D16__I2C1_SDA 0x400001ed
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX51_PAD_EIM_D19__I2C1_SCL 0x400001ed
+ MX51_PAD_EIM_D16__I2C1_SDA 0x400001ed
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX51_PAD_KEY_COL4__I2C2_SCL 0x400001ed
- MX51_PAD_KEY_COL5__I2C2_SDA 0x400001ed
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX51_PAD_KEY_COL4__I2C2_SCL 0x400001ed
+ MX51_PAD_KEY_COL5__I2C2_SDA 0x400001ed
+ >;
+ };
- pinctrl_ipu_disp1: ipudisp1grp {
- fsl,pins = <
- MX51_PAD_DISP1_DAT0__DISP1_DAT0 0x5
- MX51_PAD_DISP1_DAT1__DISP1_DAT1 0x5
- MX51_PAD_DISP1_DAT2__DISP1_DAT2 0x5
- MX51_PAD_DISP1_DAT3__DISP1_DAT3 0x5
- MX51_PAD_DISP1_DAT4__DISP1_DAT4 0x5
- MX51_PAD_DISP1_DAT5__DISP1_DAT5 0x5
- MX51_PAD_DISP1_DAT6__DISP1_DAT6 0x5
- MX51_PAD_DISP1_DAT7__DISP1_DAT7 0x5
- MX51_PAD_DISP1_DAT8__DISP1_DAT8 0x5
- MX51_PAD_DISP1_DAT9__DISP1_DAT9 0x5
- MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
- MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
- MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
- MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
- MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
- MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
- MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
- MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
- MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
- MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
- MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
- MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
- MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
- MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
- MX51_PAD_DI1_PIN2__DI1_PIN2 0x5
- MX51_PAD_DI1_PIN3__DI1_PIN3 0x5
- >;
- };
+ pinctrl_ipu_disp1: ipudisp1grp {
+ fsl,pins = <
+ MX51_PAD_DISP1_DAT0__DISP1_DAT0 0x5
+ MX51_PAD_DISP1_DAT1__DISP1_DAT1 0x5
+ MX51_PAD_DISP1_DAT2__DISP1_DAT2 0x5
+ MX51_PAD_DISP1_DAT3__DISP1_DAT3 0x5
+ MX51_PAD_DISP1_DAT4__DISP1_DAT4 0x5
+ MX51_PAD_DISP1_DAT5__DISP1_DAT5 0x5
+ MX51_PAD_DISP1_DAT6__DISP1_DAT6 0x5
+ MX51_PAD_DISP1_DAT7__DISP1_DAT7 0x5
+ MX51_PAD_DISP1_DAT8__DISP1_DAT8 0x5
+ MX51_PAD_DISP1_DAT9__DISP1_DAT9 0x5
+ MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
+ MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
+ MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
+ MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
+ MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
+ MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
+ MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
+ MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
+ MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
+ MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
+ MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
+ MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
+ MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
+ MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
+ MX51_PAD_DI1_PIN2__DI1_PIN2 0x5
+ MX51_PAD_DI1_PIN3__DI1_PIN3 0x5
+ >;
+ };
- pinctrl_ipu_disp2: ipudisp2grp {
- fsl,pins = <
- MX51_PAD_DISP2_DAT0__DISP2_DAT0 0x5
- MX51_PAD_DISP2_DAT1__DISP2_DAT1 0x5
- MX51_PAD_DISP2_DAT2__DISP2_DAT2 0x5
- MX51_PAD_DISP2_DAT3__DISP2_DAT3 0x5
- MX51_PAD_DISP2_DAT4__DISP2_DAT4 0x5
- MX51_PAD_DISP2_DAT5__DISP2_DAT5 0x5
- MX51_PAD_DISP2_DAT6__DISP2_DAT6 0x5
- MX51_PAD_DISP2_DAT7__DISP2_DAT7 0x5
- MX51_PAD_DISP2_DAT8__DISP2_DAT8 0x5
- MX51_PAD_DISP2_DAT9__DISP2_DAT9 0x5
- MX51_PAD_DISP2_DAT10__DISP2_DAT10 0x5
- MX51_PAD_DISP2_DAT11__DISP2_DAT11 0x5
- MX51_PAD_DISP2_DAT12__DISP2_DAT12 0x5
- MX51_PAD_DISP2_DAT13__DISP2_DAT13 0x5
- MX51_PAD_DISP2_DAT14__DISP2_DAT14 0x5
- MX51_PAD_DISP2_DAT15__DISP2_DAT15 0x5
- MX51_PAD_DI2_PIN2__DI2_PIN2 0x5
- MX51_PAD_DI2_PIN3__DI2_PIN3 0x5
- MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x5
- MX51_PAD_DI_GP4__DI2_PIN15 0x5
- >;
- };
+ pinctrl_ipu_disp2: ipudisp2grp {
+ fsl,pins = <
+ MX51_PAD_DISP2_DAT0__DISP2_DAT0 0x5
+ MX51_PAD_DISP2_DAT1__DISP2_DAT1 0x5
+ MX51_PAD_DISP2_DAT2__DISP2_DAT2 0x5
+ MX51_PAD_DISP2_DAT3__DISP2_DAT3 0x5
+ MX51_PAD_DISP2_DAT4__DISP2_DAT4 0x5
+ MX51_PAD_DISP2_DAT5__DISP2_DAT5 0x5
+ MX51_PAD_DISP2_DAT6__DISP2_DAT6 0x5
+ MX51_PAD_DISP2_DAT7__DISP2_DAT7 0x5
+ MX51_PAD_DISP2_DAT8__DISP2_DAT8 0x5
+ MX51_PAD_DISP2_DAT9__DISP2_DAT9 0x5
+ MX51_PAD_DISP2_DAT10__DISP2_DAT10 0x5
+ MX51_PAD_DISP2_DAT11__DISP2_DAT11 0x5
+ MX51_PAD_DISP2_DAT12__DISP2_DAT12 0x5
+ MX51_PAD_DISP2_DAT13__DISP2_DAT13 0x5
+ MX51_PAD_DISP2_DAT14__DISP2_DAT14 0x5
+ MX51_PAD_DISP2_DAT15__DISP2_DAT15 0x5
+ MX51_PAD_DI2_PIN2__DI2_PIN2 0x5
+ MX51_PAD_DI2_PIN3__DI2_PIN3 0x5
+ MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x5
+ MX51_PAD_DI_GP4__DI2_PIN15 0x5
+ >;
+ };
- pinctrl_kpp: kppgrp {
- fsl,pins = <
- MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0
- MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0
- MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0
- MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0
- MX51_PAD_KEY_COL0__KEY_COL0 0xe8
- MX51_PAD_KEY_COL1__KEY_COL1 0xe8
- MX51_PAD_KEY_COL2__KEY_COL2 0xe8
- MX51_PAD_KEY_COL3__KEY_COL3 0xe8
- >;
- };
+ pinctrl_kpp: kppgrp {
+ fsl,pins = <
+ MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0
+ MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0
+ MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0
+ MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0
+ MX51_PAD_KEY_COL0__KEY_COL0 0xe8
+ MX51_PAD_KEY_COL1__KEY_COL1 0xe8
+ MX51_PAD_KEY_COL2__KEY_COL2 0xe8
+ MX51_PAD_KEY_COL3__KEY_COL3 0xe8
+ >;
+ };
- pinctrl_pmic: pmicgrp {
- fsl,pins = <
- MX51_PAD_GPIO1_8__GPIO1_8 0xe5 /* IRQ */
- >;
- };
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_8__GPIO1_8 0xe5 /* IRQ */
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
- MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
- MX51_PAD_UART1_RTS__UART1_RTS 0x1c5
- MX51_PAD_UART1_CTS__UART1_CTS 0x1c5
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
+ MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
+ MX51_PAD_UART1_RTS__UART1_RTS 0x1c5
+ MX51_PAD_UART1_CTS__UART1_CTS 0x1c5
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX51_PAD_UART2_RXD__UART2_RXD 0x1c5
- MX51_PAD_UART2_TXD__UART2_TXD 0x1c5
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX51_PAD_UART2_RXD__UART2_RXD 0x1c5
+ MX51_PAD_UART2_TXD__UART2_TXD 0x1c5
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX51_PAD_EIM_D25__UART3_RXD 0x1c5
- MX51_PAD_EIM_D26__UART3_TXD 0x1c5
- MX51_PAD_EIM_D27__UART3_RTS 0x1c5
- MX51_PAD_EIM_D24__UART3_CTS 0x1c5
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX51_PAD_EIM_D25__UART3_RXD 0x1c5
+ MX51_PAD_EIM_D26__UART3_TXD 0x1c5
+ MX51_PAD_EIM_D27__UART3_RTS 0x1c5
+ MX51_PAD_EIM_D24__UART3_CTS 0x1c5
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- MX51_PAD_USBH1_CLK__USBH1_CLK 0x80000000
- MX51_PAD_USBH1_DIR__USBH1_DIR 0x80000000
- MX51_PAD_USBH1_NXT__USBH1_NXT 0x80000000
- MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x80000000
- MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x80000000
- MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x80000000
- MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x80000000
- MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x80000000
- MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x80000000
- MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x80000000
- MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x80000000
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ MX51_PAD_USBH1_CLK__USBH1_CLK 0x80000000
+ MX51_PAD_USBH1_DIR__USBH1_DIR 0x80000000
+ MX51_PAD_USBH1_NXT__USBH1_NXT 0x80000000
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x80000000
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x80000000
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x80000000
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x80000000
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x80000000
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x80000000
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x80000000
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x80000000
+ >;
+ };
- pinctrl_usbh1reg: usbh1reggrp {
- fsl,pins = <
- MX51_PAD_EIM_D21__GPIO2_5 0x85
- >;
- };
+ pinctrl_usbh1reg: usbh1reggrp {
+ fsl,pins = <
+ MX51_PAD_EIM_D21__GPIO2_5 0x85
+ >;
+ };
- pinctrl_usbotgreg: usbotgreggrp {
- fsl,pins = <
- MX51_PAD_GPIO1_7__GPIO1_7 0x85
- >;
- };
+ pinctrl_usbotgreg: usbotgreggrp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_7__GPIO1_7 0x85
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-jsk.dts b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-jsk.dts
index 10cae7c3a879..9750b5f93330 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-jsk.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-jsk.dts
@@ -78,49 +78,47 @@
};
&iomuxc {
- imx51-digi-connectcore-jsk {
- pinctrl_owire: owiregrp {
- fsl,pins = <
- MX51_PAD_OWIRE_LINE__OWIRE_LINE 0x40000000
- >;
- };
+ pinctrl_owire: owiregrp {
+ fsl,pins = <
+ MX51_PAD_OWIRE_LINE__OWIRE_LINE 0x40000000
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
- MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
+ MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX51_PAD_UART2_RXD__UART2_RXD 0x1c5
- MX51_PAD_UART2_TXD__UART2_TXD 0x1c5
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX51_PAD_UART2_RXD__UART2_RXD 0x1c5
+ MX51_PAD_UART2_TXD__UART2_TXD 0x1c5
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
- MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
+ MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x1e5
- MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x1e5
- MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x1e5
- MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x1e5
- MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x1e5
- MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x1e5
- MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x1e5
- MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x1e5
- MX51_PAD_USBH1_CLK__USBH1_CLK 0x1e5
- MX51_PAD_USBH1_DIR__USBH1_DIR 0x1e5
- MX51_PAD_USBH1_NXT__USBH1_NXT 0x1e5
- MX51_PAD_USBH1_STP__USBH1_STP 0x1e5
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x1e5
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x1e5
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x1e5
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x1e5
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x1e5
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x1e5
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x1e5
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x1e5
+ MX51_PAD_USBH1_CLK__USBH1_CLK 0x1e5
+ MX51_PAD_USBH1_DIR__USBH1_DIR 0x1e5
+ MX51_PAD_USBH1_NXT__USBH1_NXT 0x1e5
+ MX51_PAD_USBH1_STP__USBH1_STP 0x1e5
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
index f0809a16a2ce..dc72a2d14960 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi
@@ -215,162 +215,160 @@
};
&iomuxc {
- imx51-digi-connectcore-som {
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
- MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
- MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
- MX51_PAD_CSPI1_SS0__GPIO4_24 0x85 /* CS0 */
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
+ MX51_PAD_CSPI1_SS0__GPIO4_24 0x85 /* CS0 */
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX51_PAD_SD1_CLK__SD1_CLK 0x400021d5
- MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
- MX51_PAD_SD1_DATA0__SD1_DATA0 0x400020d5
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX51_PAD_SD1_CLK__SD1_CLK 0x400021d5
+ MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
+ MX51_PAD_SD1_DATA0__SD1_DATA0 0x400020d5
+ >;
+ };
- pinctrl_esdhc2: esdhc2grp {
- fsl,pins = <
- MX51_PAD_SD2_CMD__SD2_CMD 0x400020d5
- MX51_PAD_SD2_CLK__SD2_CLK 0x20d5
- MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
- MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
- MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
- MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
- >;
- };
+ pinctrl_esdhc2: esdhc2grp {
+ fsl,pins = <
+ MX51_PAD_SD2_CMD__SD2_CMD 0x400020d5
+ MX51_PAD_SD2_CLK__SD2_CLK 0x20d5
+ MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
+ MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
+ MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
+ MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX51_PAD_DI_GP3__FEC_TX_ER 0x80000000
- MX51_PAD_DI2_PIN4__FEC_CRS 0x80000000
- MX51_PAD_DI2_PIN2__FEC_MDC 0x80000000
- MX51_PAD_DI2_PIN3__FEC_MDIO 0x80000000
- MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
- MX51_PAD_DI_GP4__FEC_RDATA2 0x80000000
- MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x80000000
- MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x80000000
- MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x80000000
- MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x80000000
- MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x80000000
- MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x80000000
- MX51_PAD_DISP2_DAT10__FEC_COL 0x80000000
- MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x80000000
- MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x80000000
- MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x80000000
- MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x80000000
- MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x80000000
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX51_PAD_DI_GP3__FEC_TX_ER 0x80000000
+ MX51_PAD_DI2_PIN4__FEC_CRS 0x80000000
+ MX51_PAD_DI2_PIN2__FEC_MDC 0x80000000
+ MX51_PAD_DI2_PIN3__FEC_MDIO 0x80000000
+ MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
+ MX51_PAD_DI_GP4__FEC_RDATA2 0x80000000
+ MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x80000000
+ MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x80000000
+ MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x80000000
+ MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x80000000
+ MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x80000000
+ MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x80000000
+ MX51_PAD_DISP2_DAT10__FEC_COL 0x80000000
+ MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x80000000
+ MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x80000000
+ MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x80000000
+ MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x80000000
+ MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x80000000
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX51_PAD_GPIO1_2__I2C2_SCL 0x400001ed
- MX51_PAD_GPIO1_3__I2C2_SDA 0x400001ed
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_2__I2C2_SCL 0x400001ed
+ MX51_PAD_GPIO1_3__I2C2_SDA 0x400001ed
+ >;
+ };
- pinctrl_i2c2_gpio: i2c2gpiogrp {
- fsl,pins = <
- MX51_PAD_GPIO1_2__GPIO1_2 0x400001ed
- MX51_PAD_GPIO1_3__GPIO1_3 0x400001ed
- >;
- };
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_2__GPIO1_2 0x400001ed
+ MX51_PAD_GPIO1_3__GPIO1_3 0x400001ed
+ >;
+ };
- pinctrl_nfc: nfcgrp {
- fsl,pins = <
- MX51_PAD_NANDF_D0__NANDF_D0 0x80000000
- MX51_PAD_NANDF_D1__NANDF_D1 0x80000000
- MX51_PAD_NANDF_D2__NANDF_D2 0x80000000
- MX51_PAD_NANDF_D3__NANDF_D3 0x80000000
- MX51_PAD_NANDF_D4__NANDF_D4 0x80000000
- MX51_PAD_NANDF_D5__NANDF_D5 0x80000000
- MX51_PAD_NANDF_D6__NANDF_D6 0x80000000
- MX51_PAD_NANDF_D7__NANDF_D7 0x80000000
- MX51_PAD_NANDF_ALE__NANDF_ALE 0x80000000
- MX51_PAD_NANDF_CLE__NANDF_CLE 0x80000000
- MX51_PAD_NANDF_RE_B__NANDF_RE_B 0x80000000
- MX51_PAD_NANDF_WE_B__NANDF_WE_B 0x80000000
- MX51_PAD_NANDF_WP_B__NANDF_WP_B 0x80000000
- MX51_PAD_NANDF_CS0__NANDF_CS0 0x80000000
- MX51_PAD_NANDF_RB0__NANDF_RB0 0x80000000
- >;
- };
+ pinctrl_nfc: nfcgrp {
+ fsl,pins = <
+ MX51_PAD_NANDF_D0__NANDF_D0 0x80000000
+ MX51_PAD_NANDF_D1__NANDF_D1 0x80000000
+ MX51_PAD_NANDF_D2__NANDF_D2 0x80000000
+ MX51_PAD_NANDF_D3__NANDF_D3 0x80000000
+ MX51_PAD_NANDF_D4__NANDF_D4 0x80000000
+ MX51_PAD_NANDF_D5__NANDF_D5 0x80000000
+ MX51_PAD_NANDF_D6__NANDF_D6 0x80000000
+ MX51_PAD_NANDF_D7__NANDF_D7 0x80000000
+ MX51_PAD_NANDF_ALE__NANDF_ALE 0x80000000
+ MX51_PAD_NANDF_CLE__NANDF_CLE 0x80000000
+ MX51_PAD_NANDF_RE_B__NANDF_RE_B 0x80000000
+ MX51_PAD_NANDF_WE_B__NANDF_WE_B 0x80000000
+ MX51_PAD_NANDF_WP_B__NANDF_WP_B 0x80000000
+ MX51_PAD_NANDF_CS0__NANDF_CS0 0x80000000
+ MX51_PAD_NANDF_RB0__NANDF_RB0 0x80000000
+ >;
+ };
- pinctrl_lan9221: lan9221grp {
- fsl,pins = <
- MX51_PAD_GPIO1_9__GPIO1_9 0xe5 /* IRQ */
- >;
- };
+ pinctrl_lan9221: lan9221grp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_9__GPIO1_9 0xe5 /* IRQ */
+ >;
+ };
- pinctrl_mc13892: mc13892grp {
- fsl,pins = <
- MX51_PAD_GPIO1_5__GPIO1_5 0xe5 /* IRQ */
- >;
- };
+ pinctrl_mc13892: mc13892grp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_5__GPIO1_5 0xe5 /* IRQ */
+ >;
+ };
- pinctrl_mma7455l: mma7455lgrp {
- fsl,pins = <
- MX51_PAD_GPIO1_7__GPIO1_7 0xe5 /* IRQ1 */
- MX51_PAD_GPIO1_6__GPIO1_6 0xe5 /* IRQ2 */
- >;
- };
+ pinctrl_mma7455l: mma7455lgrp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_7__GPIO1_7 0xe5 /* IRQ1 */
+ MX51_PAD_GPIO1_6__GPIO1_6 0xe5 /* IRQ2 */
+ >;
+ };
- pinctrl_weim: weimgrp {
- fsl,pins = <
- MX51_PAD_EIM_DA0__EIM_DA0 0x80000000
- MX51_PAD_EIM_DA1__EIM_DA1 0x80000000
- MX51_PAD_EIM_DA2__EIM_DA2 0x80000000
- MX51_PAD_EIM_DA3__EIM_DA3 0x80000000
- MX51_PAD_EIM_DA4__EIM_DA4 0x80000000
- MX51_PAD_EIM_DA5__EIM_DA5 0x80000000
- MX51_PAD_EIM_DA6__EIM_DA6 0x80000000
- MX51_PAD_EIM_DA7__EIM_DA7 0x80000000
- MX51_PAD_EIM_DA8__EIM_DA8 0x80000000
- MX51_PAD_EIM_DA9__EIM_DA9 0x80000000
- MX51_PAD_EIM_DA10__EIM_DA10 0x80000000
- MX51_PAD_EIM_DA11__EIM_DA11 0x80000000
- MX51_PAD_EIM_DA12__EIM_DA12 0x80000000
- MX51_PAD_EIM_DA13__EIM_DA13 0x80000000
- MX51_PAD_EIM_DA14__EIM_DA14 0x80000000
- MX51_PAD_EIM_DA15__EIM_DA15 0x80000000
- MX51_PAD_EIM_A16__EIM_A16 0x80000000
- MX51_PAD_EIM_A17__EIM_A17 0x80000000
- MX51_PAD_EIM_A18__EIM_A18 0x80000000
- MX51_PAD_EIM_A19__EIM_A19 0x80000000
- MX51_PAD_EIM_A20__EIM_A20 0x80000000
- MX51_PAD_EIM_A21__EIM_A21 0x80000000
- MX51_PAD_EIM_A22__EIM_A22 0x80000000
- MX51_PAD_EIM_A23__EIM_A23 0x80000000
- MX51_PAD_EIM_A24__EIM_A24 0x80000000
- MX51_PAD_EIM_A25__EIM_A25 0x80000000
- MX51_PAD_EIM_A26__EIM_A26 0x80000000
- MX51_PAD_EIM_A27__EIM_A27 0x80000000
- MX51_PAD_EIM_D16__EIM_D16 0x80000000
- MX51_PAD_EIM_D17__EIM_D17 0x80000000
- MX51_PAD_EIM_D18__EIM_D18 0x80000000
- MX51_PAD_EIM_D19__EIM_D19 0x80000000
- MX51_PAD_EIM_D20__EIM_D20 0x80000000
- MX51_PAD_EIM_D21__EIM_D21 0x80000000
- MX51_PAD_EIM_D22__EIM_D22 0x80000000
- MX51_PAD_EIM_D23__EIM_D23 0x80000000
- MX51_PAD_EIM_D24__EIM_D24 0x80000000
- MX51_PAD_EIM_D25__EIM_D25 0x80000000
- MX51_PAD_EIM_D26__EIM_D26 0x80000000
- MX51_PAD_EIM_D27__EIM_D27 0x80000000
- MX51_PAD_EIM_D28__EIM_D28 0x80000000
- MX51_PAD_EIM_D29__EIM_D29 0x80000000
- MX51_PAD_EIM_D30__EIM_D30 0x80000000
- MX51_PAD_EIM_D31__EIM_D31 0x80000000
- MX51_PAD_EIM_OE__EIM_OE 0x80000000
- MX51_PAD_EIM_DTACK__EIM_DTACK 0x80000000
- MX51_PAD_EIM_LBA__EIM_LBA 0x80000000
- MX51_PAD_EIM_CS5__EIM_CS5 0x80000000 /* CS5 */
- >;
- };
+ pinctrl_weim: weimgrp {
+ fsl,pins = <
+ MX51_PAD_EIM_DA0__EIM_DA0 0x80000000
+ MX51_PAD_EIM_DA1__EIM_DA1 0x80000000
+ MX51_PAD_EIM_DA2__EIM_DA2 0x80000000
+ MX51_PAD_EIM_DA3__EIM_DA3 0x80000000
+ MX51_PAD_EIM_DA4__EIM_DA4 0x80000000
+ MX51_PAD_EIM_DA5__EIM_DA5 0x80000000
+ MX51_PAD_EIM_DA6__EIM_DA6 0x80000000
+ MX51_PAD_EIM_DA7__EIM_DA7 0x80000000
+ MX51_PAD_EIM_DA8__EIM_DA8 0x80000000
+ MX51_PAD_EIM_DA9__EIM_DA9 0x80000000
+ MX51_PAD_EIM_DA10__EIM_DA10 0x80000000
+ MX51_PAD_EIM_DA11__EIM_DA11 0x80000000
+ MX51_PAD_EIM_DA12__EIM_DA12 0x80000000
+ MX51_PAD_EIM_DA13__EIM_DA13 0x80000000
+ MX51_PAD_EIM_DA14__EIM_DA14 0x80000000
+ MX51_PAD_EIM_DA15__EIM_DA15 0x80000000
+ MX51_PAD_EIM_A16__EIM_A16 0x80000000
+ MX51_PAD_EIM_A17__EIM_A17 0x80000000
+ MX51_PAD_EIM_A18__EIM_A18 0x80000000
+ MX51_PAD_EIM_A19__EIM_A19 0x80000000
+ MX51_PAD_EIM_A20__EIM_A20 0x80000000
+ MX51_PAD_EIM_A21__EIM_A21 0x80000000
+ MX51_PAD_EIM_A22__EIM_A22 0x80000000
+ MX51_PAD_EIM_A23__EIM_A23 0x80000000
+ MX51_PAD_EIM_A24__EIM_A24 0x80000000
+ MX51_PAD_EIM_A25__EIM_A25 0x80000000
+ MX51_PAD_EIM_A26__EIM_A26 0x80000000
+ MX51_PAD_EIM_A27__EIM_A27 0x80000000
+ MX51_PAD_EIM_D16__EIM_D16 0x80000000
+ MX51_PAD_EIM_D17__EIM_D17 0x80000000
+ MX51_PAD_EIM_D18__EIM_D18 0x80000000
+ MX51_PAD_EIM_D19__EIM_D19 0x80000000
+ MX51_PAD_EIM_D20__EIM_D20 0x80000000
+ MX51_PAD_EIM_D21__EIM_D21 0x80000000
+ MX51_PAD_EIM_D22__EIM_D22 0x80000000
+ MX51_PAD_EIM_D23__EIM_D23 0x80000000
+ MX51_PAD_EIM_D24__EIM_D24 0x80000000
+ MX51_PAD_EIM_D25__EIM_D25 0x80000000
+ MX51_PAD_EIM_D26__EIM_D26 0x80000000
+ MX51_PAD_EIM_D27__EIM_D27 0x80000000
+ MX51_PAD_EIM_D28__EIM_D28 0x80000000
+ MX51_PAD_EIM_D29__EIM_D29 0x80000000
+ MX51_PAD_EIM_D30__EIM_D30 0x80000000
+ MX51_PAD_EIM_D31__EIM_D31 0x80000000
+ MX51_PAD_EIM_OE__EIM_OE 0x80000000
+ MX51_PAD_EIM_DTACK__EIM_DTACK 0x80000000
+ MX51_PAD_EIM_LBA__EIM_LBA 0x80000000
+ MX51_PAD_EIM_CS5__EIM_CS5 0x80000000 /* CS5 */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-eukrea-cpuimx51.dtsi b/arch/arm/boot/dts/nxp/imx/imx51-eukrea-cpuimx51.dtsi
index c2a929ba8ceb..0a150c91d30f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-eukrea-cpuimx51.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51-eukrea-cpuimx51.dtsi
@@ -44,43 +44,41 @@
};
&iomuxc {
- imx51-eukrea {
- pinctrl_tsc2007_1: tsc2007grp-1 {
- fsl,pins = <
- MX51_PAD_GPIO_NAND__GPIO_NAND 0x1f5
- MX51_PAD_NANDF_D8__GPIO4_0 0x1f5
- >;
- };
+ pinctrl_tsc2007_1: tsc2007-1-grp {
+ fsl,pins = <
+ MX51_PAD_GPIO_NAND__GPIO_NAND 0x1f5
+ MX51_PAD_NANDF_D8__GPIO4_0 0x1f5
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX51_PAD_DI_GP3__FEC_TX_ER 0x80000000
- MX51_PAD_DI2_PIN4__FEC_CRS 0x80000000
- MX51_PAD_DI2_PIN2__FEC_MDC 0x80000000
- MX51_PAD_DI2_PIN3__FEC_MDIO 0x80000000
- MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
- MX51_PAD_DI_GP4__FEC_RDATA2 0x80000000
- MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x80000000
- MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x80000000
- MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x80000000
- MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x80000000
- MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x80000000
- MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x80000000
- MX51_PAD_DISP2_DAT10__FEC_COL 0x80000000
- MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x80000000
- MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x80000000
- MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x80000000
- MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x80000000
- MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x80000000
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX51_PAD_DI_GP3__FEC_TX_ER 0x80000000
+ MX51_PAD_DI2_PIN4__FEC_CRS 0x80000000
+ MX51_PAD_DI2_PIN2__FEC_MDC 0x80000000
+ MX51_PAD_DI2_PIN3__FEC_MDIO 0x80000000
+ MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
+ MX51_PAD_DI_GP4__FEC_RDATA2 0x80000000
+ MX51_PAD_DISP2_DAT0__FEC_RDATA3 0x80000000
+ MX51_PAD_DISP2_DAT1__FEC_RX_ER 0x80000000
+ MX51_PAD_DISP2_DAT6__FEC_TDATA1 0x80000000
+ MX51_PAD_DISP2_DAT7__FEC_TDATA2 0x80000000
+ MX51_PAD_DISP2_DAT8__FEC_TDATA3 0x80000000
+ MX51_PAD_DISP2_DAT9__FEC_TX_EN 0x80000000
+ MX51_PAD_DISP2_DAT10__FEC_COL 0x80000000
+ MX51_PAD_DISP2_DAT11__FEC_RX_CLK 0x80000000
+ MX51_PAD_DISP2_DAT12__FEC_RX_DV 0x80000000
+ MX51_PAD_DISP2_DAT13__FEC_TX_CLK 0x80000000
+ MX51_PAD_DISP2_DAT14__FEC_RDATA0 0x80000000
+ MX51_PAD_DISP2_DAT15__FEC_TDATA0 0x80000000
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX51_PAD_SD2_CMD__I2C1_SCL 0x400001ed
- MX51_PAD_SD2_CLK__I2C1_SDA 0x400001ed
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX51_PAD_SD2_CMD__I2C1_SCL 0x400001ed
+ MX51_PAD_SD2_CLK__I2C1_SDA 0x400001ed
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51-eukrea-mbimxsd51-baseboard.dts b/arch/arm/boot/dts/nxp/imx/imx51-eukrea-mbimxsd51-baseboard.dts
index aff380e999c7..0e0b9a811b96 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51-eukrea-mbimxsd51-baseboard.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx51-eukrea-mbimxsd51-baseboard.dts
@@ -112,117 +112,115 @@
};
&iomuxc {
- imx51-eukrea {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000
- MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000
- MX51_PAD_AUD3_BB_CK__AUD3_TXC 0x80000000
- MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000
+ MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000
+ MX51_PAD_AUD3_BB_CK__AUD3_TXC 0x80000000
+ MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000
+ >;
+ };
- pinctrl_can: cangrp {
- fsl,pins = <
- MX51_PAD_CSI2_PIXCLK__GPIO4_15 0x80000000 /* nReset */
- MX51_PAD_GPIO1_1__GPIO1_1 0x80000000 /* IRQ */
- >;
- };
+ pinctrl_can: cangrp {
+ fsl,pins = <
+ MX51_PAD_CSI2_PIXCLK__GPIO4_15 0x80000000 /* nReset */
+ MX51_PAD_GPIO1_1__GPIO1_1 0x80000000 /* IRQ */
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
- MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
- MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
- MX51_PAD_CSPI1_SS0__GPIO4_24 0x80000000 /* CS0 */
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
+ MX51_PAD_CSPI1_SS0__GPIO4_24 0x80000000 /* CS0 */
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
- MX51_PAD_SD1_CLK__SD1_CLK 0x20d5
- MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
- MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
- MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
- MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX51_PAD_SD1_CMD__SD1_CMD 0x400020d5
+ MX51_PAD_SD1_CLK__SD1_CLK 0x20d5
+ MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
+ MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
+ MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
+ MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
- MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
+ MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
- MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
+ MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
+ >;
+ };
- pinctrl_uart3_rtscts: uart3rtsctsgrp {
- fsl,pins = <
- MX51_PAD_KEY_COL4__UART3_RTS 0x1c5
- MX51_PAD_KEY_COL5__UART3_CTS 0x1c5
- >;
- };
+ pinctrl_uart3_rtscts: uart3rtsctsgrp {
+ fsl,pins = <
+ MX51_PAD_KEY_COL4__UART3_RTS 0x1c5
+ MX51_PAD_KEY_COL5__UART3_CTS 0x1c5
+ >;
+ };
- pinctrl_backlight_1: backlightgrp-1 {
- fsl,pins = <
- MX51_PAD_DI1_D1_CS__GPIO3_4 0x1f5
- >;
- };
+ pinctrl_backlight_1: backlight1grp {
+ fsl,pins = <
+ MX51_PAD_DI1_D1_CS__GPIO3_4 0x1f5
+ >;
+ };
- pinctrl_esdhc1_cd: esdhc1_cd {
- fsl,pins = <
- MX51_PAD_GPIO1_0__GPIO1_0 0xd5
- >;
- };
+ pinctrl_esdhc1_cd: esdhc1_cdgrp {
+ fsl,pins = <
+ MX51_PAD_GPIO1_0__GPIO1_0 0xd5
+ >;
+ };
- pinctrl_gpiokeys_1: gpiokeysgrp-1 {
- fsl,pins = <
- MX51_PAD_NANDF_D9__GPIO3_31 0x1f5
- >;
- };
+ pinctrl_gpiokeys_1: gpiokeys1grp {
+ fsl,pins = <
+ MX51_PAD_NANDF_D9__GPIO3_31 0x1f5
+ >;
+ };
- pinctrl_gpioled: gpioledgrp-1 {
- fsl,pins = <
- MX51_PAD_NANDF_D10__GPIO3_30 0x80000000
- >;
- };
+ pinctrl_gpioled: gpioled1grp {
+ fsl,pins = <
+ MX51_PAD_NANDF_D10__GPIO3_30 0x80000000
+ >;
+ };
- pinctrl_reg_lcd_3v3: reg_lcd_3v3 {
- fsl,pins = <
- MX51_PAD_CSI1_D9__GPIO3_13 0x1f5
- >;
- };
+ pinctrl_reg_lcd_3v3: reg_lcd_3v3grp {
+ fsl,pins = <
+ MX51_PAD_CSI1_D9__GPIO3_13 0x1f5
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- MX51_PAD_USBH1_CLK__USBH1_CLK 0x1e5
- MX51_PAD_USBH1_DIR__USBH1_DIR 0x1e5
- MX51_PAD_USBH1_NXT__USBH1_NXT 0x1e5
- MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x1e5
- MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x1e5
- MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x1e5
- MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x1e5
- MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x1e5
- MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x1e5
- MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x1e5
- MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x1e5
- MX51_PAD_USBH1_STP__USBH1_STP 0x1e5
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ MX51_PAD_USBH1_CLK__USBH1_CLK 0x1e5
+ MX51_PAD_USBH1_DIR__USBH1_DIR 0x1e5
+ MX51_PAD_USBH1_NXT__USBH1_NXT 0x1e5
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x1e5
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x1e5
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x1e5
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x1e5
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x1e5
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x1e5
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x1e5
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x1e5
+ MX51_PAD_USBH1_STP__USBH1_STP 0x1e5
+ >;
+ };
- pinctrl_usbh1_vbus: usbh1-vbusgrp {
- fsl,pins = <
- MX51_PAD_EIM_CS3__GPIO2_28 0x1f5
- >;
- };
+ pinctrl_usbh1_vbus: usbh1-vbusgrp {
+ fsl,pins = <
+ MX51_PAD_EIM_CS3__GPIO2_28 0x1f5
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx51.dtsi b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
index 4efce49022e4..cc88da4d7785 100644
--- a/arch/arm/boot/dts/nxp/imx/imx51.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx51.dtsi
@@ -399,7 +399,7 @@
clock-names = "ipg", "per";
};
- iomuxc: iomuxc@73fa8000 {
+ iomuxc: pinctrl@73fa8000 {
compatible = "fsl,imx51-iomuxc";
reg = <0x73fa8000 0x4000>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-ard.dts b/arch/arm/boot/dts/nxp/imx/imx53-ard.dts
index 165e1b00b721..e580427660b1 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-ard.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-ard.dts
@@ -101,67 +101,65 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-ard {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX53_PAD_GPIO_1__GPIO1_1 0x80000000
- MX53_PAD_GPIO_9__GPIO1_9 0x80000000
- MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
- MX53_PAD_GPIO_10__GPIO4_0 0x80000000
- MX53_PAD_DISP0_DAT16__GPIO5_10 0x80000000
- MX53_PAD_DISP0_DAT17__GPIO5_11 0x80000000
- MX53_PAD_DISP0_DAT18__GPIO5_12 0x80000000
- MX53_PAD_DISP0_DAT19__GPIO5_13 0x80000000
- MX53_PAD_EIM_D16__EMI_WEIM_D_16 0x80000000
- MX53_PAD_EIM_D17__EMI_WEIM_D_17 0x80000000
- MX53_PAD_EIM_D18__EMI_WEIM_D_18 0x80000000
- MX53_PAD_EIM_D19__EMI_WEIM_D_19 0x80000000
- MX53_PAD_EIM_D20__EMI_WEIM_D_20 0x80000000
- MX53_PAD_EIM_D21__EMI_WEIM_D_21 0x80000000
- MX53_PAD_EIM_D22__EMI_WEIM_D_22 0x80000000
- MX53_PAD_EIM_D23__EMI_WEIM_D_23 0x80000000
- MX53_PAD_EIM_D24__EMI_WEIM_D_24 0x80000000
- MX53_PAD_EIM_D25__EMI_WEIM_D_25 0x80000000
- MX53_PAD_EIM_D26__EMI_WEIM_D_26 0x80000000
- MX53_PAD_EIM_D27__EMI_WEIM_D_27 0x80000000
- MX53_PAD_EIM_D28__EMI_WEIM_D_28 0x80000000
- MX53_PAD_EIM_D29__EMI_WEIM_D_29 0x80000000
- MX53_PAD_EIM_D30__EMI_WEIM_D_30 0x80000000
- MX53_PAD_EIM_D31__EMI_WEIM_D_31 0x80000000
- MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 0x80000000
- MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 0x80000000
- MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 0x80000000
- MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 0x80000000
- MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 0x80000000
- MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 0x80000000
- MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 0x80000000
- MX53_PAD_EIM_OE__EMI_WEIM_OE 0x80000000
- MX53_PAD_EIM_RW__EMI_WEIM_RW 0x80000000
- MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 0x80000000
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_1__GPIO1_1 0x80000000
+ MX53_PAD_GPIO_9__GPIO1_9 0x80000000
+ MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
+ MX53_PAD_GPIO_10__GPIO4_0 0x80000000
+ MX53_PAD_DISP0_DAT16__GPIO5_10 0x80000000
+ MX53_PAD_DISP0_DAT17__GPIO5_11 0x80000000
+ MX53_PAD_DISP0_DAT18__GPIO5_12 0x80000000
+ MX53_PAD_DISP0_DAT19__GPIO5_13 0x80000000
+ MX53_PAD_EIM_D16__EMI_WEIM_D_16 0x80000000
+ MX53_PAD_EIM_D17__EMI_WEIM_D_17 0x80000000
+ MX53_PAD_EIM_D18__EMI_WEIM_D_18 0x80000000
+ MX53_PAD_EIM_D19__EMI_WEIM_D_19 0x80000000
+ MX53_PAD_EIM_D20__EMI_WEIM_D_20 0x80000000
+ MX53_PAD_EIM_D21__EMI_WEIM_D_21 0x80000000
+ MX53_PAD_EIM_D22__EMI_WEIM_D_22 0x80000000
+ MX53_PAD_EIM_D23__EMI_WEIM_D_23 0x80000000
+ MX53_PAD_EIM_D24__EMI_WEIM_D_24 0x80000000
+ MX53_PAD_EIM_D25__EMI_WEIM_D_25 0x80000000
+ MX53_PAD_EIM_D26__EMI_WEIM_D_26 0x80000000
+ MX53_PAD_EIM_D27__EMI_WEIM_D_27 0x80000000
+ MX53_PAD_EIM_D28__EMI_WEIM_D_28 0x80000000
+ MX53_PAD_EIM_D29__EMI_WEIM_D_29 0x80000000
+ MX53_PAD_EIM_D30__EMI_WEIM_D_30 0x80000000
+ MX53_PAD_EIM_D31__EMI_WEIM_D_31 0x80000000
+ MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 0x80000000
+ MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 0x80000000
+ MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 0x80000000
+ MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 0x80000000
+ MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 0x80000000
+ MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 0x80000000
+ MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 0x80000000
+ MX53_PAD_EIM_OE__EMI_WEIM_OE 0x80000000
+ MX53_PAD_EIM_RW__EMI_WEIM_RW 0x80000000
+ MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 0x80000000
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
- MX53_PAD_PATA_DATA8__ESDHC1_DAT4 0x1d5
- MX53_PAD_PATA_DATA9__ESDHC1_DAT5 0x1d5
- MX53_PAD_PATA_DATA10__ESDHC1_DAT6 0x1d5
- MX53_PAD_PATA_DATA11__ESDHC1_DAT7 0x1d5
- MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
- MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
+ MX53_PAD_PATA_DATA8__ESDHC1_DAT4 0x1d5
+ MX53_PAD_PATA_DATA9__ESDHC1_DAT5 0x1d5
+ MX53_PAD_PATA_DATA10__ESDHC1_DAT6 0x1d5
+ MX53_PAD_PATA_DATA11__ESDHC1_DAT7 0x1d5
+ MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
+ MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
- MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-kp-ddc.dts b/arch/arm/boot/dts/nxp/imx/imx53-kp-ddc.dts
index f6f116366643..9c480e4d27ce 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-kp-ddc.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-kp-ddc.dts
@@ -102,38 +102,36 @@
};
&iomuxc {
- imx53-kp-ddc {
- pinctrl_disp: dispgrp {
- fsl,pins = <
- MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK 0x4
- MX53_PAD_EIM_DA10__IPU_DI1_PIN15 0x4
- MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 0x4
- MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 0x4
- MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 0x4
- MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 0x4
- MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 0x4
- MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 0x4
- MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 0x4
- MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 0x4
- MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 0x4
- MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 0x4
- MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 0x4
- MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 0x4
- MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 0x4
- MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 0x4
- MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 0x4
- MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 0x4
- MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 0x4
- MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 0x4
- MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 0x4
- MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 0x4
- MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 0x4
- MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 0x4
- MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 0x4
- MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 0x4
- MX53_PAD_GPIO_1__PWM2_PWMO 0x4
- >;
- };
+ pinctrl_disp: dispgrp {
+ fsl,pins = <
+ MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK 0x4
+ MX53_PAD_EIM_DA10__IPU_DI1_PIN15 0x4
+ MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 0x4
+ MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 0x4
+ MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 0x4
+ MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 0x4
+ MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 0x4
+ MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 0x4
+ MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 0x4
+ MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 0x4
+ MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 0x4
+ MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 0x4
+ MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 0x4
+ MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 0x4
+ MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 0x4
+ MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 0x4
+ MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 0x4
+ MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 0x4
+ MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 0x4
+ MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 0x4
+ MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 0x4
+ MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 0x4
+ MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 0x4
+ MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 0x4
+ MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 0x4
+ MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 0x4
+ MX53_PAD_GPIO_1__PWM2_PWMO 0x4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-kp.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-kp.dtsi
index ae5f87b8612d..ebbd4d93e460 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-kp.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53-kp.dtsi
@@ -98,56 +98,54 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_kp_common>;
- imx53-kp-common {
- pinctrl_buzzer: buzzergrp {
- fsl,pins = <
- MX53_PAD_SD1_DATA3__PWM1_PWMO 0x1e4
- >;
- };
+ pinctrl_buzzer: buzzergrp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA3__PWM1_PWMO 0x1e4
+ >;
+ };
- pinctrl_gpiobuttons: gpiobuttonsgrp {
- fsl,pins = <
- MX53_PAD_EIM_RW__GPIO2_26 0x1e4
- MX53_PAD_EIM_D22__GPIO3_22 0x1e4
- >;
- };
+ pinctrl_gpiobuttons: gpiobuttonsgrp {
+ fsl,pins = <
+ MX53_PAD_EIM_RW__GPIO2_26 0x1e4
+ MX53_PAD_EIM_D22__GPIO3_22 0x1e4
+ >;
+ };
- pinctrl_kp_common: kpcommongrp {
- fsl,pins = <
- MX53_PAD_EIM_CS0__GPIO2_23 0x1e4
- MX53_PAD_GPIO_19__GPIO4_5 0x1e4
- MX53_PAD_PATA_DATA6__GPIO2_6 0x1e4
- MX53_PAD_PATA_DATA7__GPIO2_7 0xe0
- MX53_PAD_CSI0_DAT14__GPIO6_0 0x1e4
- MX53_PAD_CSI0_DAT16__GPIO6_2 0x1e4
- MX53_PAD_CSI0_DAT18__GPIO6_4 0x1e4
- MX53_PAD_EIM_D17__GPIO3_17 0x1e4
- MX53_PAD_EIM_D18__GPIO3_18 0x1e4
- MX53_PAD_EIM_D21__GPIO3_21 0x1e4
- MX53_PAD_EIM_D29__GPIO3_29 0x1e4
- MX53_PAD_EIM_DA11__GPIO3_11 0x1e4
- MX53_PAD_EIM_DA13__GPIO3_13 0x1e4
- MX53_PAD_EIM_DA14__GPIO3_14 0x1e4
- MX53_PAD_SD1_DATA0__GPIO1_16 0x1e4
- MX53_PAD_SD1_CMD__GPIO1_18 0x1e4
- MX53_PAD_SD1_CLK__GPIO1_20 0x1e4
- >;
- };
+ pinctrl_kp_common: kpcommongrp {
+ fsl,pins = <
+ MX53_PAD_EIM_CS0__GPIO2_23 0x1e4
+ MX53_PAD_GPIO_19__GPIO4_5 0x1e4
+ MX53_PAD_PATA_DATA6__GPIO2_6 0x1e4
+ MX53_PAD_PATA_DATA7__GPIO2_7 0xe0
+ MX53_PAD_CSI0_DAT14__GPIO6_0 0x1e4
+ MX53_PAD_CSI0_DAT16__GPIO6_2 0x1e4
+ MX53_PAD_CSI0_DAT18__GPIO6_4 0x1e4
+ MX53_PAD_EIM_D17__GPIO3_17 0x1e4
+ MX53_PAD_EIM_D18__GPIO3_18 0x1e4
+ MX53_PAD_EIM_D21__GPIO3_21 0x1e4
+ MX53_PAD_EIM_D29__GPIO3_29 0x1e4
+ MX53_PAD_EIM_DA11__GPIO3_11 0x1e4
+ MX53_PAD_EIM_DA13__GPIO3_13 0x1e4
+ MX53_PAD_EIM_DA14__GPIO3_14 0x1e4
+ MX53_PAD_SD1_DATA0__GPIO1_16 0x1e4
+ MX53_PAD_SD1_CMD__GPIO1_18 0x1e4
+ MX53_PAD_SD1_CLK__GPIO1_20 0x1e4
+ >;
+ };
- pinctrl_leds: ledgrp {
- fsl,pins = <
- MX53_PAD_EIM_EB2__GPIO2_30 0x1d4
- MX53_PAD_EIM_D28__GPIO3_28 0x1d4
- MX53_PAD_EIM_WAIT__GPIO5_0 0x1d4
- >;
- };
+ pinctrl_leds: ledgrp {
+ fsl,pins = <
+ MX53_PAD_EIM_EB2__GPIO2_30 0x1d4
+ MX53_PAD_EIM_D28__GPIO3_28 0x1d4
+ MX53_PAD_EIM_WAIT__GPIO5_0 0x1d4
+ >;
+ };
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT12__UART4_TXD_MUX 0x1e4
- MX53_PAD_CSI0_DAT13__UART4_RXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT12__UART4_TXD_MUX 0x1e4
+ MX53_PAD_CSI0_DAT13__UART4_RXD_MUX 0x1e4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-m53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-m53.dtsi
index 00b8d7ca41a2..df543b4751e0 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-m53.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53-m53.dtsi
@@ -77,41 +77,39 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-m53evk {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
- MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
- MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
+ MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
+ MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX53_PAD_EIM_D16__I2C2_SDA 0xc0000000
- MX53_PAD_EIM_EB2__I2C2_SCL 0xc0000000
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D16__I2C2_SDA 0xc0000000
+ MX53_PAD_EIM_EB2__I2C2_SCL 0xc0000000
+ >;
+ };
- pinctrl_nand: nandgrp {
- fsl,pins = <
- MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
- MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
- MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
- MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
- MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
- MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
- MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
- MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 0xa4
- MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 0xa4
- MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 0xa4
- MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 0xa4
- MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 0xa4
- MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 0xa4
- MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 0xa4
- MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 0xa4
- >;
- };
+ pinctrl_nand: nandgrp {
+ fsl,pins = <
+ MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
+ MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
+ MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
+ MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
+ MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
+ MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
+ MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
+ MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 0xa4
+ MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 0xa4
+ MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 0xa4
+ MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 0xa4
+ MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 0xa4
+ MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 0xa4
+ MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 0xa4
+ MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 0xa4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts
index ba0c62994f75..eb3d66305395 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts
@@ -156,155 +156,153 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-m53evk {
- pinctrl_usb: usbgrp {
- fsl,pins = <
- MX53_PAD_GPIO_2__GPIO1_2 0x80000000
- MX53_PAD_GPIO_3__USBOH3_USBH1_OC 0x80000000
- >;
- };
+ pinctrl_usb: usbgrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_2__GPIO1_2 0x80000000
+ MX53_PAD_GPIO_3__USBOH3_USBH1_OC 0x80000000
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX53_PAD_GPIO_4__GPIO1_4 0x000b0
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_4__GPIO1_4 0x000b0
+ >;
+ };
- led_pin_gpio: led_gpio {
- fsl,pins = <
- MX53_PAD_PATA_DATA8__GPIO2_8 0x80000000
- MX53_PAD_PATA_DATA9__GPIO2_9 0x80000000
- >;
- };
+ led_pin_gpio: ledgpiogrp {
+ fsl,pins = <
+ MX53_PAD_PATA_DATA8__GPIO2_8 0x80000000
+ MX53_PAD_PATA_DATA9__GPIO2_9 0x80000000
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC 0x80000000
- MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD 0x80000000
- MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS 0x80000000
- MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD 0x80000000
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC 0x80000000
+ MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD 0x80000000
+ MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS 0x80000000
+ MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD 0x80000000
+ >;
+ };
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX53_PAD_GPIO_7__CAN1_TXCAN 0x80000000
- MX53_PAD_GPIO_8__CAN1_RXCAN 0x80000000
- >;
- };
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_7__CAN1_TXCAN 0x80000000
+ MX53_PAD_GPIO_8__CAN1_RXCAN 0x80000000
+ >;
+ };
- pinctrl_can2: can2grp {
- fsl,pins = <
- MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
- MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
- >;
- };
+ pinctrl_can2: can2grp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
+ MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
- MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
- MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
+ MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
+ MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
- MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
- MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
- MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
- MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
- MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
- MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
- MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
+ MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX53_PAD_EIM_D21__I2C1_SCL 0xc0000000
- MX53_PAD_EIM_D28__I2C1_SDA 0xc0000000
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D21__I2C1_SCL 0xc0000000
+ MX53_PAD_EIM_D28__I2C1_SDA 0xc0000000
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
- MX53_PAD_GPIO_5__I2C3_SCL 0xc0000000
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
+ MX53_PAD_GPIO_5__I2C3_SCL 0xc0000000
+ >;
+ };
- pinctrl_ipu_disp1: ipudisp1grp {
- fsl,pins = <
- MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 0x5
- MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 0x5
- MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 0x5
- MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 0x5
- MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 0x5
- MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 0x5
- MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 0x5
- MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 0x5
- MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 0x5
- MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 0x5
- MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 0x5
- MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 0x5
- MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 0x5
- MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 0x5
- MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 0x5
- MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 0x5
- MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 0x5
- MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 0x5
- MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 0x5
- MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 0x5
- MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 0x5
- MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 0x5
- MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 0x5
- MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 0x5
- MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK 0x5
- MX53_PAD_EIM_DA13__IPU_DI1_D0_CS 0x5
- MX53_PAD_EIM_DA14__IPU_DI1_D1_CS 0x5
- MX53_PAD_EIM_DA15__IPU_DI1_PIN1 0x5
- MX53_PAD_EIM_DA11__IPU_DI1_PIN2 0x5
- MX53_PAD_EIM_DA12__IPU_DI1_PIN3 0x5
- MX53_PAD_EIM_A25__IPU_DI1_PIN12 0x5
- MX53_PAD_EIM_DA10__IPU_DI1_PIN15 0x5
- >;
- };
+ pinctrl_ipu_disp1: ipudisp1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 0x5
+ MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 0x5
+ MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 0x5
+ MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 0x5
+ MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 0x5
+ MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 0x5
+ MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 0x5
+ MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 0x5
+ MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 0x5
+ MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 0x5
+ MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 0x5
+ MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 0x5
+ MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 0x5
+ MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 0x5
+ MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 0x5
+ MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 0x5
+ MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 0x5
+ MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 0x5
+ MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 0x5
+ MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 0x5
+ MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 0x5
+ MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 0x5
+ MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 0x5
+ MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 0x5
+ MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK 0x5
+ MX53_PAD_EIM_DA13__IPU_DI1_D0_CS 0x5
+ MX53_PAD_EIM_DA14__IPU_DI1_D1_CS 0x5
+ MX53_PAD_EIM_DA15__IPU_DI1_PIN1 0x5
+ MX53_PAD_EIM_DA11__IPU_DI1_PIN2 0x5
+ MX53_PAD_EIM_DA12__IPU_DI1_PIN3 0x5
+ MX53_PAD_EIM_A25__IPU_DI1_PIN12 0x5
+ MX53_PAD_EIM_DA10__IPU_DI1_PIN15 0x5
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <
- MX53_PAD_DISP0_DAT8__PWM1_PWMO 0x5
- >;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX53_PAD_DISP0_DAT8__PWM1_PWMO 0x5
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
- MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
- MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
- MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
- MX53_PAD_PATA_DA_1__UART3_CTS 0x1e4
- MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
+ MX53_PAD_PATA_DA_1__UART3_CTS 0x1e4
+ MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
index 558751e730f3..6210673f93be 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
@@ -278,186 +278,184 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-m53evk {
- hoggrp {
- fsl,pins = <
- MX53_PAD_GPIO_19__CCM_CLKO 0x1e4
- MX53_PAD_CSI0_DATA_EN__GPIO5_20 0x1e4
- MX53_PAD_CSI0_DAT4__GPIO5_22 0x1e4
- MX53_PAD_CSI0_DAT5__GPIO5_23 0x1c4
- MX53_PAD_CSI0_DAT6__GPIO5_24 0x1e4
- MX53_PAD_CSI0_DAT7__GPIO5_25 0x1e4
- MX53_PAD_CSI0_DAT8__GPIO5_26 0x1e4
- MX53_PAD_CSI0_DAT9__GPIO5_27 0x1c4
- MX53_PAD_CSI0_DAT10__GPIO5_28 0x1e4
- MX53_PAD_CSI0_DAT11__GPIO5_29 0x1e4
- MX53_PAD_PATA_DATA11__GPIO2_11 0x1e4
- MX53_PAD_EIM_D24__GPIO3_24 0x1e4
- MX53_PAD_EIM_D25__GPIO3_25 0x1e4
- MX53_PAD_EIM_D29__GPIO3_29 0x1e4
- MX53_PAD_CSI0_PIXCLK__GPIO5_18 0x1e4
- MX53_PAD_CSI0_VSYNC__GPIO5_21 0x1e4
- MX53_PAD_CSI0_DAT18__GPIO6_4 0x1c4
- MX53_PAD_PATA_DATA8__GPIO2_8 0x1e4
- >;
- };
+ hoggrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_19__CCM_CLKO 0x1e4
+ MX53_PAD_CSI0_DATA_EN__GPIO5_20 0x1e4
+ MX53_PAD_CSI0_DAT4__GPIO5_22 0x1e4
+ MX53_PAD_CSI0_DAT5__GPIO5_23 0x1c4
+ MX53_PAD_CSI0_DAT6__GPIO5_24 0x1e4
+ MX53_PAD_CSI0_DAT7__GPIO5_25 0x1e4
+ MX53_PAD_CSI0_DAT8__GPIO5_26 0x1e4
+ MX53_PAD_CSI0_DAT9__GPIO5_27 0x1c4
+ MX53_PAD_CSI0_DAT10__GPIO5_28 0x1e4
+ MX53_PAD_CSI0_DAT11__GPIO5_29 0x1e4
+ MX53_PAD_PATA_DATA11__GPIO2_11 0x1e4
+ MX53_PAD_EIM_D24__GPIO3_24 0x1e4
+ MX53_PAD_EIM_D25__GPIO3_25 0x1e4
+ MX53_PAD_EIM_D29__GPIO3_29 0x1e4
+ MX53_PAD_CSI0_PIXCLK__GPIO5_18 0x1e4
+ MX53_PAD_CSI0_VSYNC__GPIO5_21 0x1e4
+ MX53_PAD_CSI0_DAT18__GPIO6_4 0x1c4
+ MX53_PAD_PATA_DATA8__GPIO2_8 0x1e4
+ >;
+ };
- pinctrl_led: ledgrp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT15__GPIO6_1 0x1c4
- MX53_PAD_CSI0_DAT16__GPIO6_2 0x1c4
- >;
- };
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT15__GPIO6_1 0x1c4
+ MX53_PAD_CSI0_DAT16__GPIO6_2 0x1c4
+ >;
+ };
- pinctrl_beeper: beepergrp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT17__GPIO6_3 0x1c4
- >;
- };
+ pinctrl_beeper: beepergrp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT17__GPIO6_3 0x1c4
+ >;
+ };
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX53_PAD_GPIO_7__CAN1_TXCAN 0x1c4
- MX53_PAD_GPIO_8__CAN1_RXCAN 0x1c4
- >;
- };
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_7__CAN1_TXCAN 0x1c4
+ MX53_PAD_GPIO_8__CAN1_RXCAN 0x1c4
+ >;
+ };
- pinctrl_can2: can2grp {
- fsl,pins = <
- MX53_PAD_KEY_COL4__CAN2_TXCAN 0x1e4
- MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x1c4
- >;
- };
+ pinctrl_can2: can2grp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL4__CAN2_TXCAN 0x1e4
+ MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x1c4
+ >;
+ };
- pinctrl_display_gpio: display-gpiogrp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT12__GPIO5_30 0x1c4 /* Reset */
- MX53_PAD_CSI0_MCLK__GPIO5_19 0x1e4 /* Int-K */
- MX53_PAD_CSI0_DAT13__GPIO5_31 0x1c4 /* Int-I */
+ pinctrl_display_gpio: display-gpiogrp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT12__GPIO5_30 0x1c4 /* Reset */
+ MX53_PAD_CSI0_MCLK__GPIO5_19 0x1e4 /* Int-K */
+ MX53_PAD_CSI0_DAT13__GPIO5_31 0x1c4 /* Int-I */
- MX53_PAD_CSI0_DAT14__GPIO6_0 0x1c4 /* Power down */
- >;
- };
+ MX53_PAD_CSI0_DAT14__GPIO6_0 0x1c4 /* Power down */
+ >;
+ };
- pinctrl_edt_ft5x06: edt-ft5x06grp {
- fsl,pins = <
- MX53_PAD_PATA_DATA9__GPIO2_9 0x1e4 /* Reset */
- MX53_PAD_CSI0_DAT19__GPIO6_5 0x1c4 /* Interrupt */
- MX53_PAD_PATA_DATA10__GPIO2_10 0x1e4 /* Wake */
- >;
- };
+ pinctrl_edt_ft5x06: edt-ft5x06grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DATA9__GPIO2_9 0x1e4 /* Reset */
+ MX53_PAD_CSI0_DAT19__GPIO6_5 0x1c4 /* Interrupt */
+ MX53_PAD_PATA_DATA10__GPIO2_10 0x1e4 /* Wake */
+ >;
+ };
- pinctrl_ecspi2: ecspi2grp {
- fsl,pins = <
- MX53_PAD_EIM_CS0__ECSPI2_SCLK 0xe4
- MX53_PAD_EIM_OE__ECSPI2_MISO 0xe4
- MX53_PAD_EIM_CS1__ECSPI2_MOSI 0xe4
- MX53_PAD_EIM_RW__GPIO2_26 0xe4
- MX53_PAD_EIM_LBA__GPIO2_27 0xe4
- >;
- };
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX53_PAD_EIM_CS0__ECSPI2_SCLK 0xe4
+ MX53_PAD_EIM_OE__ECSPI2_MISO 0xe4
+ MX53_PAD_EIM_CS1__ECSPI2_MOSI 0xe4
+ MX53_PAD_EIM_RW__GPIO2_26 0xe4
+ MX53_PAD_EIM_LBA__GPIO2_27 0xe4
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1e4
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1e4
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1e4
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1e4
- MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1e4
- MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1e4
- MX53_PAD_GPIO_1__GPIO1_1 0x1c4
- MX53_PAD_GPIO_9__GPIO1_9 0x1e4
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1e4
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1e4
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1e4
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1e4
+ MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1e4
+ MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1e4
+ MX53_PAD_GPIO_1__GPIO1_1 0x1c4
+ MX53_PAD_GPIO_9__GPIO1_9 0x1e4
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX53_PAD_FEC_MDC__FEC_MDC 0x1e4
- MX53_PAD_FEC_MDIO__FEC_MDIO 0x1e4
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x1e4
- MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x1e4
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x1e4
- MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x1e4
- MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x1e4
- MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x1c4
- MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x1e4
- MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x1e4
- MX53_PAD_PATA_DA_1__GPIO7_7 0x1e4
- MX53_PAD_EIM_EB3__GPIO2_31 0x1e4
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX53_PAD_FEC_MDC__FEC_MDC 0x1e4
+ MX53_PAD_FEC_MDIO__FEC_MDIO 0x1e4
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x1e4
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x1e4
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x1e4
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x1e4
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x1e4
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x1c4
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x1e4
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x1e4
+ MX53_PAD_PATA_DA_1__GPIO7_7 0x1e4
+ MX53_PAD_EIM_EB3__GPIO2_31 0x1e4
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX53_PAD_EIM_D21__I2C1_SCL 0x400001e4
- MX53_PAD_EIM_D28__I2C1_SDA 0x400001e4
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D21__I2C1_SCL 0x400001e4
+ MX53_PAD_EIM_D28__I2C1_SDA 0x400001e4
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX53_PAD_GPIO_6__I2C3_SDA 0x400001e4
- MX53_PAD_GPIO_5__I2C3_SCL 0x400001e4
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_6__I2C3_SDA 0x400001e4
+ MX53_PAD_GPIO_5__I2C3_SCL 0x400001e4
+ >;
+ };
- pinctrl_lvds0: lvds0grp {
- /* LVDS pins only have pin mux configuration */
- fsl,pins = <
- MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
- MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
- MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
- MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
- MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
- >;
- };
+ pinctrl_lvds0: lvds0grp {
+ /* LVDS pins only have pin mux configuration */
+ fsl,pins = <
+ MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
+ MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
+ MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
+ MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
+ MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
+ >;
+ };
- pinctrl_power_button: powerbutgrp {
- fsl,pins = <
- MX53_PAD_SD2_DATA0__GPIO1_15 0x1e4
- >;
- };
+ pinctrl_power_button: powerbutgrp {
+ fsl,pins = <
+ MX53_PAD_SD2_DATA0__GPIO1_15 0x1e4
+ >;
+ };
- pinctrl_power_out: poweroutgrp {
- fsl,pins = <
- MX53_PAD_SD2_DATA2__GPIO1_13 0x1e4
- >;
- };
+ pinctrl_power_out: poweroutgrp {
+ fsl,pins = <
+ MX53_PAD_SD2_DATA2__GPIO1_13 0x1e4
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
- MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
- MX53_PAD_PATA_IORDY__UART1_RTS 0x1e4
- MX53_PAD_PATA_RESET_B__UART1_CTS 0x1e4
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
+ MX53_PAD_PATA_IORDY__UART1_RTS 0x1e4
+ MX53_PAD_PATA_RESET_B__UART1_CTS 0x1e4
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
- MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
- MX53_PAD_PATA_DIOR__UART2_RTS 0x1e4
- MX53_PAD_PATA_INTRQ__UART2_CTS 0x1e4
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DIOR__UART2_RTS 0x1e4
+ MX53_PAD_PATA_INTRQ__UART2_CTS 0x1e4
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
- MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
- MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
+ >;
+ };
- pinctrl_usb: usbgrp {
- fsl,pins = <
- MX53_PAD_GPIO_2__GPIO1_2 0x1c4
- MX53_PAD_GPIO_3__USBOH3_USBH1_OC 0x1c4
- MX53_PAD_GPIO_4__GPIO1_4 0x1c4
- MX53_PAD_GPIO_18__GPIO7_13 0x1c4
- >;
- };
+ pinctrl_usb: usbgrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_2__GPIO1_2 0x1c4
+ MX53_PAD_GPIO_3__USBOH3_USBH1_OC 0x1c4
+ MX53_PAD_GPIO_4__GPIO1_4 0x1c4
+ MX53_PAD_GPIO_18__GPIO7_13 0x1c4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts b/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts
index 0d336cbdb451..c14eb7280f09 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts
@@ -75,71 +75,65 @@
};
&iomuxc {
- lvds1 {
- pinctrl_lvds1_1: lvds1-grp1 {
- fsl,pins = <
- MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
- MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
- MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
- MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
- MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
- >;
- };
+ pinctrl_lvds1_1: lvds1-1-grp {
+ fsl,pins = <
+ MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
+ MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
+ MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
+ MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
+ MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
+ >;
+ };
- pinctrl_lvds1_2: lvds1-grp2 {
- fsl,pins = <
- MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 0x80000000
- MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 0x80000000
- MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 0x80000000
- MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 0x80000000
- MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 0x80000000
- >;
- };
+ pinctrl_lvds1_2: lvds1-2-grp {
+ fsl,pins = <
+ MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 0x80000000
+ MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 0x80000000
+ MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 0x80000000
+ MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 0x80000000
+ MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 0x80000000
+ >;
};
- disp1 {
- pinctrl_disp1_1: disp1-grp1 {
- fsl,pins = <
- MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK 0x80000000 /* DISP1_CLK */
- MX53_PAD_EIM_DA10__IPU_DI1_PIN15 0x80000000 /* DISP1_DRDY */
- MX53_PAD_EIM_D23__IPU_DI1_PIN2 0x80000000 /* DISP1_HSYNC */
- MX53_PAD_EIM_EB3__IPU_DI1_PIN3 0x80000000 /* DISP1_VSYNC */
- MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 0x80000000
- MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 0x80000000
- MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 0x80000000
- MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 0x80000000
- MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 0x80000000
- MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 0x80000000
- MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 0x80000000
- MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 0x80000000
- MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 0x80000000
- MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 0x80000000
- MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 0x80000000
- MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 0x80000000
- MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 0x80000000
- MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 0x80000000
- MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 0x80000000
- MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 0x80000000
- MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 0x80000000
- MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 0x80000000
- MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 0x80000000
- MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 0x80000000
- MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 0x80000000
- MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 0x80000000
- MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 0x80000000
- MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 0x80000000
- >;
- };
+ pinctrl_disp1_1: disp1-1-grp {
+ fsl,pins = <
+ MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK 0x80000000 /* DISP1_CLK */
+ MX53_PAD_EIM_DA10__IPU_DI1_PIN15 0x80000000 /* DISP1_DRDY */
+ MX53_PAD_EIM_D23__IPU_DI1_PIN2 0x80000000 /* DISP1_HSYNC */
+ MX53_PAD_EIM_EB3__IPU_DI1_PIN3 0x80000000 /* DISP1_VSYNC */
+ MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 0x80000000
+ MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 0x80000000
+ MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 0x80000000
+ MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 0x80000000
+ MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 0x80000000
+ MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 0x80000000
+ MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 0x80000000
+ MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 0x80000000
+ MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 0x80000000
+ MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 0x80000000
+ MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 0x80000000
+ MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 0x80000000
+ MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 0x80000000
+ MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 0x80000000
+ MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 0x80000000
+ MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 0x80000000
+ MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 0x80000000
+ MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 0x80000000
+ MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 0x80000000
+ MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 0x80000000
+ MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 0x80000000
+ MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 0x80000000
+ MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 0x80000000
+ MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 0x80000000
+ >;
};
- tve {
- pinctrl_vga_sync_1: vgasync-grp1 {
- fsl,pins = <
- /* VGA_VSYNC, HSYNC with max drive strength */
- MX53_PAD_EIM_CS1__IPU_DI1_PIN6 0xe6
- MX53_PAD_EIM_DA15__IPU_DI1_PIN4 0xe6
- >;
- };
+ pinctrl_vga_sync_1: vgasync-1-grp {
+ fsl,pins = <
+ /* VGA_VSYNC, HSYNC with max drive strength */
+ MX53_PAD_EIM_CS1__IPU_DI1_PIN6 0xe6
+ MX53_PAD_EIM_DA15__IPU_DI1_PIN4 0xe6
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-qsb-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-qsb-common.dtsi
index 05d7a462ea25..1869ad86baf2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-qsb-common.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53-qsb-common.dtsi
@@ -170,157 +170,155 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-qsb {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX53_PAD_GPIO_8__GPIO1_8 0x80000000
- MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000
- MX53_PAD_PATA_DATA15__GPIO2_15 0x80000000
- MX53_PAD_EIM_DA11__GPIO3_11 0x80000000
- MX53_PAD_EIM_DA12__GPIO3_12 0x80000000
- MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
- MX53_PAD_PATA_DA_2__GPIO7_8 0x80000000
- MX53_PAD_GPIO_16__GPIO7_11 0x80000000
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_8__GPIO1_8 0x80000000
+ MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000
+ MX53_PAD_PATA_DATA15__GPIO2_15 0x80000000
+ MX53_PAD_EIM_DA11__GPIO3_11 0x80000000
+ MX53_PAD_EIM_DA12__GPIO3_12 0x80000000
+ MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
+ MX53_PAD_PATA_DA_2__GPIO7_8 0x80000000
+ MX53_PAD_GPIO_16__GPIO7_11 0x80000000
+ >;
+ };
- led_pin_gpio7_7: led_gpio7_7 {
- fsl,pins = <
- MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
- >;
- };
+ led_pin_gpio7_7: led_gpio7-7-grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
- MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
- MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
- MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
+ MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
+ MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
+ MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
+ >;
+ };
- pinctrl_codec: codecgrp {
- fsl,pins = <
- MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x1c4
- >;
- };
+ pinctrl_codec: codecgrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x1c4
+ >;
+ };
- pinctrl_display_power: displaypowergrp {
- fsl,pins = <
- MX53_PAD_EIM_D24__GPIO3_24 0x1e4
- >;
- };
+ pinctrl_display_power: displaypowergrp {
+ fsl,pins = <
+ MX53_PAD_EIM_D24__GPIO3_24 0x1e4
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
- MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
- MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
- MX53_PAD_EIM_DA13__GPIO3_13 0xe4
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
+ MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
+ MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
+ MX53_PAD_EIM_DA13__GPIO3_13 0xe4
+ >;
+ };
- pinctrl_esdhc3: esdhc3grp {
- fsl,pins = <
- MX53_PAD_PATA_DATA8__ESDHC3_DAT0 0x1d5
- MX53_PAD_PATA_DATA9__ESDHC3_DAT1 0x1d5
- MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
- MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
- MX53_PAD_PATA_DATA0__ESDHC3_DAT4 0x1d5
- MX53_PAD_PATA_DATA1__ESDHC3_DAT5 0x1d5
- MX53_PAD_PATA_DATA2__ESDHC3_DAT6 0x1d5
- MX53_PAD_PATA_DATA3__ESDHC3_DAT7 0x1d5
- MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
- MX53_PAD_PATA_IORDY__ESDHC3_CLK 0x1d5
- >;
- };
+ pinctrl_esdhc3: esdhc3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DATA8__ESDHC3_DAT0 0x1d5
+ MX53_PAD_PATA_DATA9__ESDHC3_DAT1 0x1d5
+ MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
+ MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
+ MX53_PAD_PATA_DATA0__ESDHC3_DAT4 0x1d5
+ MX53_PAD_PATA_DATA1__ESDHC3_DAT5 0x1d5
+ MX53_PAD_PATA_DATA2__ESDHC3_DAT6 0x1d5
+ MX53_PAD_PATA_DATA3__ESDHC3_DAT7 0x1d5
+ MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
+ MX53_PAD_PATA_IORDY__ESDHC3_CLK 0x1d5
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX53_PAD_FEC_MDC__FEC_MDC 0x4
- MX53_PAD_FEC_MDIO__FEC_MDIO 0x1fc
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x180
- MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x180
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x180
- MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x180
- MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x180
- MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x4
- MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x4
- MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x4
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX53_PAD_FEC_MDC__FEC_MDC 0x4
+ MX53_PAD_FEC_MDIO__FEC_MDIO 0x1fc
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x180
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x180
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x180
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x180
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x180
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x4
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x4
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x4
+ >;
+ };
- /* open drain */
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT8__I2C1_SDA 0x400001ec
- MX53_PAD_CSI0_DAT9__I2C1_SCL 0x400001ec
- >;
- };
+ /* open drain */
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT8__I2C1_SDA 0x400001ec
+ MX53_PAD_CSI0_DAT9__I2C1_SCL 0x400001ec
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
- MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
+ MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
+ >;
+ };
- pinctrl_ipu_disp0: ipudisp0grp {
- fsl,pins = <
- MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK 0x5
- MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 0x5
- MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 0x5
- MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 0x5
- MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 0x5
- MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 0x5
- MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 0x5
- MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 0x5
- MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 0x5
- MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 0x5
- MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 0x5
- MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 0x5
- MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 0x5
- MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 0x5
- MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 0x5
- MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 0x5
- MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 0x5
- MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 0x5
- MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 0x5
- MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 0x5
- MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 0x5
- MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 0x5
- MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 0x5
- MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 0x5
- MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 0x5
- MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 0x5
- MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 0x5
- MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 0x5
- >;
- };
+ pinctrl_ipu_disp0: ipudisp0grp {
+ fsl,pins = <
+ MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK 0x5
+ MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 0x5
+ MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 0x5
+ MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 0x5
+ MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 0x5
+ MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 0x5
+ MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 0x5
+ MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 0x5
+ MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 0x5
+ MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 0x5
+ MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 0x5
+ MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 0x5
+ MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 0x5
+ MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 0x5
+ MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 0x5
+ MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 0x5
+ MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 0x5
+ MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 0x5
+ MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 0x5
+ MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 0x5
+ MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 0x5
+ MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 0x5
+ MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 0x5
+ MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 0x5
+ MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 0x5
+ MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 0x5
+ MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 0x5
+ MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 0x5
+ >;
+ };
- pinctrl_pwm2: pwm2grp {
- fsl,pins = <
- MX53_PAD_GPIO_1__PWM2_PWMO 0x5
- >;
- };
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_1__PWM2_PWMO 0x5
+ >;
+ };
- pinctrl_vga_sync: vgasync-grp {
- fsl,pins = <
- /* VGA_HSYNC, VSYNC with max drive strength */
- MX53_PAD_EIM_OE__IPU_DI1_PIN7 0xe6
- MX53_PAD_EIM_RW__IPU_DI1_PIN8 0xe6
- >;
- };
+ pinctrl_vga_sync: vgasync-grp {
+ fsl,pins = <
+ /* VGA_HSYNC, VSYNC with max drive strength */
+ MX53_PAD_EIM_OE__IPU_DI1_PIN7 0xe6
+ MX53_PAD_EIM_RW__IPU_DI1_PIN8 0xe6
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
- MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
+ MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-qsrb.dts b/arch/arm/boot/dts/nxp/imx/imx53-qsrb.dts
index 1bbf24ad308a..2f06ad61a766 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-qsrb.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-qsrb.dts
@@ -13,12 +13,10 @@
};
&iomuxc {
- imx53-qsrb {
- pinctrl_pmic: pmicgrp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT5__GPIO5_23 0x1c4 /* IRQ */
- >;
- };
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT5__GPIO5_23 0x1c4 /* IRQ */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-smd.dts b/arch/arm/boot/dts/nxp/imx/imx53-smd.dts
index 55435dfdff8a..386371c816f4 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-smd.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-smd.dts
@@ -98,140 +98,138 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-smd {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000
- MX53_PAD_PATA_DATA15__GPIO2_15 0x80000000
- MX53_PAD_EIM_EB2__GPIO2_30 0x80000000
- MX53_PAD_EIM_DA13__GPIO3_13 0x80000000
- MX53_PAD_EIM_D19__GPIO3_19 0x80000000
- MX53_PAD_KEY_ROW2__GPIO4_11 0x80000000
- MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000
+ MX53_PAD_PATA_DATA15__GPIO2_15 0x80000000
+ MX53_PAD_EIM_EB2__GPIO2_30 0x80000000
+ MX53_PAD_EIM_DA13__GPIO3_13 0x80000000
+ MX53_PAD_EIM_D19__GPIO3_19 0x80000000
+ MX53_PAD_KEY_ROW2__GPIO4_11 0x80000000
+ MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
- MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
- MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
+ MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
+ MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
+ >;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
- MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
- MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
+ MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
+ MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
+ >;
+ };
- pinctrl_esdhc2: esdhc2grp {
- fsl,pins = <
- MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
- MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
- MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
- MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
- MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
- MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
- >;
- };
+ pinctrl_esdhc2: esdhc2grp {
+ fsl,pins = <
+ MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
+ MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
+ MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
+ MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
+ MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
+ MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
+ >;
+ };
- pinctrl_esdhc3: esdhc3grp {
- fsl,pins = <
- MX53_PAD_PATA_DATA8__ESDHC3_DAT0 0x1d5
- MX53_PAD_PATA_DATA9__ESDHC3_DAT1 0x1d5
- MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
- MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
- MX53_PAD_PATA_DATA0__ESDHC3_DAT4 0x1d5
- MX53_PAD_PATA_DATA1__ESDHC3_DAT5 0x1d5
- MX53_PAD_PATA_DATA2__ESDHC3_DAT6 0x1d5
- MX53_PAD_PATA_DATA3__ESDHC3_DAT7 0x1d5
- MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
- MX53_PAD_PATA_IORDY__ESDHC3_CLK 0x1d5
- >;
- };
+ pinctrl_esdhc3: esdhc3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DATA8__ESDHC3_DAT0 0x1d5
+ MX53_PAD_PATA_DATA9__ESDHC3_DAT1 0x1d5
+ MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
+ MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
+ MX53_PAD_PATA_DATA0__ESDHC3_DAT4 0x1d5
+ MX53_PAD_PATA_DATA1__ESDHC3_DAT5 0x1d5
+ MX53_PAD_PATA_DATA2__ESDHC3_DAT6 0x1d5
+ MX53_PAD_PATA_DATA3__ESDHC3_DAT7 0x1d5
+ MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
+ MX53_PAD_PATA_IORDY__ESDHC3_CLK 0x1d5
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
- MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
- MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
- MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
- MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
- MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
- MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
- MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
+ MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT8__I2C1_SDA 0xc0000000
- MX53_PAD_CSI0_DAT9__I2C1_SCL 0xc0000000
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT8__I2C1_SDA 0xc0000000
+ MX53_PAD_CSI0_DAT9__I2C1_SCL 0xc0000000
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
- MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
+ MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
+ >;
+ };
- pinctrl_ipu_csi0: ipucsi0grp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 0x1c4
- MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 0x1c4
- MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 0x1c4
- MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 0x1c4
- MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 0x1c4
- MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 0x1c4
- MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 0x1c4
- MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 0x1c4
- MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK 0x1e4
- MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC 0x1e4
- MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC 0x1e4
- MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN 0x1e4
- >;
- };
+ pinctrl_ipu_csi0: ipucsi0grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 0x1c4
+ MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 0x1c4
+ MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 0x1c4
+ MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 0x1c4
+ MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 0x1c4
+ MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 0x1c4
+ MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 0x1c4
+ MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 0x1c4
+ MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK 0x1e4
+ MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC 0x1e4
+ MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC 0x1e4
+ MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN 0x1e4
+ >;
+ };
- pinctrl_ov5642: ov5642grp {
- fsl,pins = <
- MX53_PAD_NANDF_WP_B__GPIO6_9 0x1e4
- MX53_PAD_NANDF_RB0__GPIO6_10 0x1e4
- MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x1c4
- >;
- };
+ pinctrl_ov5642: ov5642grp {
+ fsl,pins = <
+ MX53_PAD_NANDF_WP_B__GPIO6_9 0x1e4
+ MX53_PAD_NANDF_RB0__GPIO6_10 0x1e4
+ MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x1c4
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
- MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
+ MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
- MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
- MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
- MX53_PAD_PATA_DA_1__UART3_CTS 0x1e4
- MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
+ MX53_PAD_PATA_DA_1__UART3_CTS 0x1e4
+ MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi
index c34ee84bd716..0f0245df380f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi
@@ -61,144 +61,142 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-tqma53 {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000 /* SSI_MCLK */
- MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000 /* LCD_BLT_EN */
- MX53_PAD_PATA_DA_2__GPIO7_8 0x80000000 /* LCD_RESET */
- MX53_PAD_PATA_DATA5__GPIO2_5 0x80000000 /* LCD_POWER */
- MX53_PAD_PATA_DATA6__GPIO2_6 0x80000000 /* PMIC_INT */
- MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000 /* CSI_RST */
- MX53_PAD_PATA_DATA15__GPIO2_15 0x80000000 /* CSI_PWDN */
- MX53_PAD_GPIO_19__GPIO4_5 0x80000000 /* #SYSTEM_DOWN */
- MX53_PAD_GPIO_3__GPIO1_3 0x80000000
- MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000 /* #PHY_RESET */
- MX53_PAD_GPIO_1__PWM2_PWMO 0x80000000 /* LCD_CONTRAST */
- >;
- };
-
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
- MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
- MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
- MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
- >;
- };
-
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX53_PAD_KEY_COL2__CAN1_TXCAN 0x80000000
- MX53_PAD_KEY_ROW2__CAN1_RXCAN 0x80000000
- >;
- };
-
- pinctrl_can2: can2grp {
- fsl,pins = <
- MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
- MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
- >;
- };
-
- pinctrl_cspi: cspigrp {
- fsl,pins = <
- MX53_PAD_SD1_DATA0__CSPI_MISO 0x1d5
- MX53_PAD_SD1_CMD__CSPI_MOSI 0x1d5
- MX53_PAD_SD1_CLK__CSPI_SCLK 0x1d5
- >;
- };
-
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
- MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
- MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
- >;
- };
-
- pinctrl_esdhc2: esdhc2grp {
- fsl,pins = <
- MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
- MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
- MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
- MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
- MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
- MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
- >;
- };
-
- pinctrl_esdhc2_cdwp: esdhc2cdwp {
- fsl,pins = <
- MX53_PAD_GPIO_4__GPIO1_4 0x80000000 /* SD2_CD */
- MX53_PAD_GPIO_2__GPIO1_2 0x80000000 /* SD2_WP */
- >;
- };
-
- pinctrl_esdhc3: esdhc3grp {
- fsl,pins = <
- MX53_PAD_PATA_DATA8__ESDHC3_DAT0 0x1d5
- MX53_PAD_PATA_DATA9__ESDHC3_DAT1 0x1d5
- MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
- MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
- MX53_PAD_PATA_DATA0__ESDHC3_DAT4 0x1d5
- MX53_PAD_PATA_DATA1__ESDHC3_DAT5 0x1d5
- MX53_PAD_PATA_DATA2__ESDHC3_DAT6 0x1d5
- MX53_PAD_PATA_DATA3__ESDHC3_DAT7 0x1d5
- MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
- MX53_PAD_PATA_IORDY__ESDHC3_CLK 0x1d5
- >;
- };
-
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
- MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
- MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
- MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
- MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
- MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
- MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
- MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
- >;
- };
-
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
- MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
- >;
- };
-
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
- MX53_PAD_GPIO_5__I2C3_SCL 0xc0000000
- >;
- };
-
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
- MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
- >;
- };
-
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
- MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
- >;
- };
-
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
- MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000 /* SSI_MCLK */
+ MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000 /* LCD_BLT_EN */
+ MX53_PAD_PATA_DA_2__GPIO7_8 0x80000000 /* LCD_RESET */
+ MX53_PAD_PATA_DATA5__GPIO2_5 0x80000000 /* LCD_POWER */
+ MX53_PAD_PATA_DATA6__GPIO2_6 0x80000000 /* PMIC_INT */
+ MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000 /* CSI_RST */
+ MX53_PAD_PATA_DATA15__GPIO2_15 0x80000000 /* CSI_PWDN */
+ MX53_PAD_GPIO_19__GPIO4_5 0x80000000 /* #SYSTEM_DOWN */
+ MX53_PAD_GPIO_3__GPIO1_3 0x80000000
+ MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000 /* #PHY_RESET */
+ MX53_PAD_GPIO_1__PWM2_PWMO 0x80000000 /* LCD_CONTRAST */
+ >;
+ };
+
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
+ MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
+ MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
+ MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
+ >;
+ };
+
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL2__CAN1_TXCAN 0x80000000
+ MX53_PAD_KEY_ROW2__CAN1_RXCAN 0x80000000
+ >;
+ };
+
+ pinctrl_can2: can2grp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
+ MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
+ >;
+ };
+
+ pinctrl_cspi: cspigrp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA0__CSPI_MISO 0x1d5
+ MX53_PAD_SD1_CMD__CSPI_MOSI 0x1d5
+ MX53_PAD_SD1_CLK__CSPI_SCLK 0x1d5
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
+ MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
+ MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
+ >;
+ };
+
+ pinctrl_esdhc2: esdhc2grp {
+ fsl,pins = <
+ MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
+ MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
+ MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
+ MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
+ MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
+ MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
+ >;
+ };
+
+ pinctrl_esdhc2_cdwp: esdhc2cdwpgrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_4__GPIO1_4 0x80000000 /* SD2_CD */
+ MX53_PAD_GPIO_2__GPIO1_2 0x80000000 /* SD2_WP */
+ >;
+ };
+
+ pinctrl_esdhc3: esdhc3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DATA8__ESDHC3_DAT0 0x1d5
+ MX53_PAD_PATA_DATA9__ESDHC3_DAT1 0x1d5
+ MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
+ MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
+ MX53_PAD_PATA_DATA0__ESDHC3_DAT4 0x1d5
+ MX53_PAD_PATA_DATA1__ESDHC3_DAT5 0x1d5
+ MX53_PAD_PATA_DATA2__ESDHC3_DAT6 0x1d5
+ MX53_PAD_PATA_DATA3__ESDHC3_DAT7 0x1d5
+ MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
+ MX53_PAD_PATA_IORDY__ESDHC3_CLK 0x1d5
+ >;
+ };
+
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
+ MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
+ MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
+ MX53_PAD_GPIO_5__I2C3_SCL 0xc0000000
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1e4
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
index a02d77bb5672..5f62c99909c5 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
@@ -262,66 +262,64 @@
};
&iomuxc {
- imx53-tx53-x03x {
- pinctrl_edt_ft5x06_1: edt-ft5x06grp-1 {
- fsl,pins = <
- MX53_PAD_NANDF_CS2__GPIO6_15 0x1f0 /* Interrupt */
- MX53_PAD_EIM_A16__GPIO2_22 0x04 /* Reset */
- MX53_PAD_EIM_A17__GPIO2_21 0x04 /* Wake */
- >;
- };
+ pinctrl_edt_ft5x06_1: edt-ft5x06-1-grp {
+ fsl,pins = <
+ MX53_PAD_NANDF_CS2__GPIO6_15 0x1f0 /* Interrupt */
+ MX53_PAD_EIM_A16__GPIO2_22 0x04 /* Reset */
+ MX53_PAD_EIM_A17__GPIO2_21 0x04 /* Wake */
+ >;
+ };
- pinctrl_kpp: kppgrp {
- fsl,pins = <
- MX53_PAD_GPIO_9__KPP_COL_6 0x1f4
- MX53_PAD_GPIO_4__KPP_COL_7 0x1f4
- MX53_PAD_KEY_COL2__KPP_COL_2 0x1f4
- MX53_PAD_KEY_COL3__KPP_COL_3 0x1f4
- MX53_PAD_GPIO_2__KPP_ROW_6 0x1f4
- MX53_PAD_GPIO_5__KPP_ROW_7 0x1f4
- MX53_PAD_KEY_ROW2__KPP_ROW_2 0x1f4
- MX53_PAD_KEY_ROW3__KPP_ROW_3 0x1f4
- >;
- };
+ pinctrl_kpp: kppgrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_9__KPP_COL_6 0x1f4
+ MX53_PAD_GPIO_4__KPP_COL_7 0x1f4
+ MX53_PAD_KEY_COL2__KPP_COL_2 0x1f4
+ MX53_PAD_KEY_COL3__KPP_COL_3 0x1f4
+ MX53_PAD_GPIO_2__KPP_ROW_6 0x1f4
+ MX53_PAD_GPIO_5__KPP_ROW_7 0x1f4
+ MX53_PAD_KEY_ROW2__KPP_ROW_2 0x1f4
+ MX53_PAD_KEY_ROW3__KPP_ROW_3 0x1f4
+ >;
+ };
- pinctrl_rgb24_vga1: rgb24-vgagrp1 {
- fsl,pins = <
- MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK 0x5
- MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 0x5
- MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 0x5
- MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 0x5
- MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 0x5
- MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 0x5
- MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 0x5
- MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 0x5
- MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 0x5
- MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 0x5
- MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 0x5
- MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 0x5
- MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 0x5
- MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 0x5
- MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 0x5
- MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 0x5
- MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 0x5
- MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 0x5
- MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 0x5
- MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 0x5
- MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 0x5
- MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 0x5
- MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 0x5
- MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 0x5
- MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 0x5
- MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 0x5
- MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 0x5
- MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 0x5
- >;
- };
+ pinctrl_rgb24_vga1: rgb24-vga1grp {
+ fsl,pins = <
+ MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK 0x5
+ MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 0x5
+ MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 0x5
+ MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 0x5
+ MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 0x5
+ MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 0x5
+ MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 0x5
+ MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 0x5
+ MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 0x5
+ MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 0x5
+ MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 0x5
+ MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 0x5
+ MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 0x5
+ MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 0x5
+ MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 0x5
+ MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 0x5
+ MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 0x5
+ MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 0x5
+ MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 0x5
+ MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 0x5
+ MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 0x5
+ MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 0x5
+ MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 0x5
+ MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 0x5
+ MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 0x5
+ MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 0x5
+ MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 0x5
+ MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 0x5
+ >;
+ };
- pinctrl_tsc2007: tsc2007grp {
- fsl,pins = <
- MX53_PAD_EIM_D26__GPIO3_26 0x1f0 /* Interrupt */
- >;
- };
+ pinctrl_tsc2007: tsc2007grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D26__GPIO3_26 0x1f0 /* Interrupt */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts
index e10c179dbdb3..9c9122da3737 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts
@@ -139,42 +139,40 @@
};
&iomuxc {
- imx53-tx53-x13x {
- pinctrl_lvds0: lvds0grp {
- fsl,pins = <
- MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
- MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
- MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
- MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
- MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
- >;
- };
+ pinctrl_lvds0: lvds0grp {
+ fsl,pins = <
+ MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 0x80000000
+ MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK 0x80000000
+ MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 0x80000000
+ MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 0x80000000
+ MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 0x80000000
+ >;
+ };
- pinctrl_lvds1: lvds1grp {
- fsl,pins = <
- MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 0x80000000
- MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 0x80000000
- MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 0x80000000
- MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 0x80000000
- MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 0x80000000
- >;
- };
+ pinctrl_lvds1: lvds1grp {
+ fsl,pins = <
+ MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 0x80000000
+ MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 0x80000000
+ MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK 0x80000000
+ MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 0x80000000
+ MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 0x80000000
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <MX53_PAD_GPIO_9__PWM1_PWMO 0x04>;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <MX53_PAD_GPIO_9__PWM1_PWMO 0x04>;
+ };
- pinctrl_eeti1: eeti1grp {
- fsl,pins = <
- MX53_PAD_EIM_D22__GPIO3_22 0x1f0 /* Interrupt */
- >;
- };
+ pinctrl_eeti1: eeti1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D22__GPIO3_22 0x1f0 /* Interrupt */
+ >;
+ };
- pinctrl_eeti2: eeti2grp {
- fsl,pins = <
- MX53_PAD_EIM_D23__GPIO3_23 0x1f0 /* Interrupt */
- >;
- };
+ pinctrl_eeti2: eeti2grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D23__GPIO3_23 0x1f0 /* Interrupt */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-tx53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-tx53.dtsi
index a439a47fb65a..29e3f5f37c25 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-tx53.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53-tx53.dtsi
@@ -257,261 +257,259 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-tx53 {
- pinctrl_hog: hoggrp {
- /* pins not in use by any device on the Starterkit board series */
- fsl,pins = <
- /* CMOS Sensor Interface */
- MX53_PAD_CSI0_DAT12__GPIO5_30 0x1f4
- MX53_PAD_CSI0_DAT13__GPIO5_31 0x1f4
- MX53_PAD_CSI0_DAT14__GPIO6_0 0x1f4
- MX53_PAD_CSI0_DAT15__GPIO6_1 0x1f4
- MX53_PAD_CSI0_DAT16__GPIO6_2 0x1f4
- MX53_PAD_CSI0_DAT17__GPIO6_3 0x1f4
- MX53_PAD_CSI0_DAT18__GPIO6_4 0x1f4
- MX53_PAD_CSI0_DAT19__GPIO6_5 0x1f4
- MX53_PAD_CSI0_MCLK__GPIO5_19 0x1f4
- MX53_PAD_CSI0_VSYNC__GPIO5_21 0x1f4
- MX53_PAD_CSI0_PIXCLK__GPIO5_18 0x1f4
- MX53_PAD_GPIO_0__GPIO1_0 0x1f4
- /* Module Specific Signal */
- /* MX53_PAD_NANDF_CS2__GPIO6_15 0x1f4 maybe used by EDT-FT5x06 */
- /* MX53_PAD_EIM_A16__GPIO2_22 0x1f4 maybe used by EDT-FT5x06 */
- MX53_PAD_EIM_D29__GPIO3_29 0x1f4
- MX53_PAD_EIM_EB3__GPIO2_31 0x1f4
- /* MX53_PAD_EIM_A17__GPIO2_21 0x1f4 maybe used by EDT-FT5x06 */
- /* MX53_PAD_EIM_A18__GPIO2_20 0x1f4 used by LED */
- MX53_PAD_EIM_A19__GPIO2_19 0x1f4
- MX53_PAD_EIM_A20__GPIO2_18 0x1f4
- MX53_PAD_EIM_A21__GPIO2_17 0x1f4
- MX53_PAD_EIM_A22__GPIO2_16 0x1f4
- MX53_PAD_EIM_A23__GPIO6_6 0x1f4
- MX53_PAD_EIM_A24__GPIO5_4 0x1f4
- MX53_PAD_CSI0_DAT8__GPIO5_26 0x1f4
- MX53_PAD_CSI0_DAT9__GPIO5_27 0x1f4
- MX53_PAD_CSI0_DAT10__GPIO5_28 0x1f4
- MX53_PAD_CSI0_DAT11__GPIO5_29 0x1f4
- /* MX53_PAD_EIM_D22__GPIO3_22 0x1f4 maybe used by EETI touchpanel driver */
- /* MX53_PAD_EIM_D23__GPIO3_23 0x1f4 maybe used by EETI touchpanel driver */
- MX53_PAD_GPIO_13__GPIO4_3 0x1f4
- MX53_PAD_EIM_CS0__GPIO2_23 0x1f4
- MX53_PAD_EIM_CS1__GPIO2_24 0x1f4
- MX53_PAD_CSI0_DATA_EN__GPIO5_20 0x1f4
- MX53_PAD_EIM_WAIT__GPIO5_0 0x1f4
- MX53_PAD_EIM_EB0__GPIO2_28 0x1f4
- MX53_PAD_EIM_EB1__GPIO2_29 0x1f4
- MX53_PAD_EIM_OE__GPIO2_25 0x1f4
- MX53_PAD_EIM_LBA__GPIO2_27 0x1f4
- MX53_PAD_EIM_RW__GPIO2_26 0x1f4
- MX53_PAD_EIM_DA8__GPIO3_8 0x1f4
- MX53_PAD_EIM_DA9__GPIO3_9 0x1f4
- MX53_PAD_EIM_DA10__GPIO3_10 0x1f4
- MX53_PAD_EIM_DA11__GPIO3_11 0x1f4
- MX53_PAD_EIM_DA12__GPIO3_12 0x1f4
- MX53_PAD_EIM_DA13__GPIO3_13 0x1f4
- MX53_PAD_EIM_DA14__GPIO3_14 0x1f4
- MX53_PAD_EIM_DA15__GPIO3_15 0x1f4
- >;
- };
-
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX53_PAD_GPIO_7__CAN1_TXCAN 0x80000000
- MX53_PAD_GPIO_8__CAN1_RXCAN 0x80000000
+ pinctrl_hog: hoggrp {
+ /* pins not in use by any device on the Starterkit board series */
+ fsl,pins = <
+ /* CMOS Sensor Interface */
+ MX53_PAD_CSI0_DAT12__GPIO5_30 0x1f4
+ MX53_PAD_CSI0_DAT13__GPIO5_31 0x1f4
+ MX53_PAD_CSI0_DAT14__GPIO6_0 0x1f4
+ MX53_PAD_CSI0_DAT15__GPIO6_1 0x1f4
+ MX53_PAD_CSI0_DAT16__GPIO6_2 0x1f4
+ MX53_PAD_CSI0_DAT17__GPIO6_3 0x1f4
+ MX53_PAD_CSI0_DAT18__GPIO6_4 0x1f4
+ MX53_PAD_CSI0_DAT19__GPIO6_5 0x1f4
+ MX53_PAD_CSI0_MCLK__GPIO5_19 0x1f4
+ MX53_PAD_CSI0_VSYNC__GPIO5_21 0x1f4
+ MX53_PAD_CSI0_PIXCLK__GPIO5_18 0x1f4
+ MX53_PAD_GPIO_0__GPIO1_0 0x1f4
+ /* Module Specific Signal */
+ /* MX53_PAD_NANDF_CS2__GPIO6_15 0x1f4 maybe used by EDT-FT5x06 */
+ /* MX53_PAD_EIM_A16__GPIO2_22 0x1f4 maybe used by EDT-FT5x06 */
+ MX53_PAD_EIM_D29__GPIO3_29 0x1f4
+ MX53_PAD_EIM_EB3__GPIO2_31 0x1f4
+ /* MX53_PAD_EIM_A17__GPIO2_21 0x1f4 maybe used by EDT-FT5x06 */
+ /* MX53_PAD_EIM_A18__GPIO2_20 0x1f4 used by LED */
+ MX53_PAD_EIM_A19__GPIO2_19 0x1f4
+ MX53_PAD_EIM_A20__GPIO2_18 0x1f4
+ MX53_PAD_EIM_A21__GPIO2_17 0x1f4
+ MX53_PAD_EIM_A22__GPIO2_16 0x1f4
+ MX53_PAD_EIM_A23__GPIO6_6 0x1f4
+ MX53_PAD_EIM_A24__GPIO5_4 0x1f4
+ MX53_PAD_CSI0_DAT8__GPIO5_26 0x1f4
+ MX53_PAD_CSI0_DAT9__GPIO5_27 0x1f4
+ MX53_PAD_CSI0_DAT10__GPIO5_28 0x1f4
+ MX53_PAD_CSI0_DAT11__GPIO5_29 0x1f4
+ /* MX53_PAD_EIM_D22__GPIO3_22 0x1f4 maybe used by EETI touchpanel driver */
+ /* MX53_PAD_EIM_D23__GPIO3_23 0x1f4 maybe used by EETI touchpanel driver */
+ MX53_PAD_GPIO_13__GPIO4_3 0x1f4
+ MX53_PAD_EIM_CS0__GPIO2_23 0x1f4
+ MX53_PAD_EIM_CS1__GPIO2_24 0x1f4
+ MX53_PAD_CSI0_DATA_EN__GPIO5_20 0x1f4
+ MX53_PAD_EIM_WAIT__GPIO5_0 0x1f4
+ MX53_PAD_EIM_EB0__GPIO2_28 0x1f4
+ MX53_PAD_EIM_EB1__GPIO2_29 0x1f4
+ MX53_PAD_EIM_OE__GPIO2_25 0x1f4
+ MX53_PAD_EIM_LBA__GPIO2_27 0x1f4
+ MX53_PAD_EIM_RW__GPIO2_26 0x1f4
+ MX53_PAD_EIM_DA8__GPIO3_8 0x1f4
+ MX53_PAD_EIM_DA9__GPIO3_9 0x1f4
+ MX53_PAD_EIM_DA10__GPIO3_10 0x1f4
+ MX53_PAD_EIM_DA11__GPIO3_11 0x1f4
+ MX53_PAD_EIM_DA12__GPIO3_12 0x1f4
+ MX53_PAD_EIM_DA13__GPIO3_13 0x1f4
+ MX53_PAD_EIM_DA14__GPIO3_14 0x1f4
+ MX53_PAD_EIM_DA15__GPIO3_15 0x1f4
>;
- };
+ };
- pinctrl_can2: can2grp {
- fsl,pins = <
- MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
- MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
- >;
- };
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_7__CAN1_TXCAN 0x80000000
+ MX53_PAD_GPIO_8__CAN1_RXCAN 0x80000000
+ >;
+ };
- pinctrl_can_xcvr: can-xcvrgrp {
- fsl,pins = <MX53_PAD_DISP0_DAT0__GPIO4_21 0xe0>; /* Flexcan XCVR enable */
- };
+ pinctrl_can2: can2grp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
+ MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
+ >;
+ };
- pinctrl_ds1339: ds1339grp {
- fsl,pins = <MX53_PAD_DI0_PIN4__GPIO4_20 0xe0>;
- };
+ pinctrl_can_xcvr: can-xcvrgrp {
+ fsl,pins = <MX53_PAD_DISP0_DAT0__GPIO4_21 0xe0>; /* Flexcan XCVR enable */
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX53_PAD_GPIO_19__ECSPI1_RDY 0x80000000
- MX53_PAD_EIM_EB2__ECSPI1_SS0 0x80000000
- MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
- MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
- MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
- MX53_PAD_EIM_D19__ECSPI1_SS1 0x80000000
- >;
- };
+ pinctrl_ds1339: ds1339grp {
+ fsl,pins = <MX53_PAD_DI0_PIN4__GPIO4_20 0xe0>;
+ };
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
- MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
- MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
- MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
- MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
- MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
- MX53_PAD_EIM_D24__GPIO3_24 0x1f0
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_19__ECSPI1_RDY 0x80000000
+ MX53_PAD_EIM_EB2__ECSPI1_SS0 0x80000000
+ MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
+ MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
+ MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
+ MX53_PAD_EIM_D19__ECSPI1_SS1 0x80000000
+ >;
+ };
- pinctrl_esdhc2: esdhc2grp {
- fsl,pins = <
- MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
- MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
- MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
- MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
- MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
- MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
- MX53_PAD_EIM_D25__GPIO3_25 0x1f0
- >;
- };
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
+ MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
+ MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
+ MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
+ MX53_PAD_SD1_CMD__ESDHC1_CMD 0x1d5
+ MX53_PAD_SD1_CLK__ESDHC1_CLK 0x1d5
+ MX53_PAD_EIM_D24__GPIO3_24 0x1f0
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
- MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
- MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
- MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
- MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
- MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
- MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
- MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
- >;
- };
+ pinctrl_esdhc2: esdhc2grp {
+ fsl,pins = <
+ MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
+ MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
+ MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
+ MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
+ MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
+ MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
+ MX53_PAD_EIM_D25__GPIO3_25 0x1f0
+ >;
+ };
- pinctrl_gpio_key: gpio-keygrp {
- fsl,pins = <MX53_PAD_EIM_A25__GPIO5_2 0x1f4>;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
+ MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX53_PAD_EIM_D21__I2C1_SCL 0x400001e4
- MX53_PAD_EIM_D28__I2C1_SDA 0x400001e4
- >;
- };
+ pinctrl_gpio_key: gpio-keygrp {
+ fsl,pins = <MX53_PAD_EIM_A25__GPIO5_2 0x1f4>;
+ };
- pinctrl_i2c1_gpio: i2c1-gpiogrp {
- fsl,pins = <
- MX53_PAD_EIM_D21__GPIO3_21 0x400001e6
- MX53_PAD_EIM_D28__GPIO3_28 0x400001e6
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D21__I2C1_SCL 0x400001e4
+ MX53_PAD_EIM_D28__I2C1_SDA 0x400001e4
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX53_PAD_GPIO_3__I2C3_SCL 0x400001e4
- MX53_PAD_GPIO_6__I2C3_SDA 0x400001e4
- >;
- };
+ pinctrl_i2c1_gpio: i2c1-gpiogrp {
+ fsl,pins = <
+ MX53_PAD_EIM_D21__GPIO3_21 0x400001e6
+ MX53_PAD_EIM_D28__GPIO3_28 0x400001e6
+ >;
+ };
- pinctrl_i2c3_gpio: i2c3-gpiogrp {
- fsl,pins = <
- MX53_PAD_GPIO_3__GPIO1_3 0x400001e6
- MX53_PAD_GPIO_6__GPIO1_6 0x400001e6
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_3__I2C3_SCL 0x400001e4
+ MX53_PAD_GPIO_6__I2C3_SDA 0x400001e4
+ >;
+ };
- pinctrl_nand: nandgrp {
- fsl,pins = <
- MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
- MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
- MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
- MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
- MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
- MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
- MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
- MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 0xa4
- MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 0xa4
- MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 0xa4
- MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 0xa4
- MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 0xa4
- MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 0xa4
- MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 0xa4
- MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 0xa4
- >;
- };
+ pinctrl_i2c3_gpio: i2c3-gpiogrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_3__GPIO1_3 0x400001e6
+ MX53_PAD_GPIO_6__GPIO1_6 0x400001e6
+ >;
+ };
- pinctrl_pwm2: pwm2grp {
- fsl,pins = <
- MX53_PAD_GPIO_1__PWM2_PWMO 0x80000000
- >;
- };
+ pinctrl_nand: nandgrp {
+ fsl,pins = <
+ MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
+ MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
+ MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
+ MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
+ MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
+ MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
+ MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
+ MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 0xa4
+ MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 0xa4
+ MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 0xa4
+ MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 0xa4
+ MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 0xa4
+ MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 0xa4
+ MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 0xa4
+ MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 0xa4
+ >;
+ };
- pinctrl_ssi1: ssi1grp {
- fsl,pins = <
- MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
- MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
- MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
- MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
- >;
- };
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_1__PWM2_PWMO 0x80000000
+ >;
+ };
- pinctrl_ssi2: ssi2grp {
- fsl,pins = <
- MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC 0x80000000
- MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD 0x80000000
- MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS 0x80000000
- MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD 0x80000000
- MX53_PAD_EIM_D27__GPIO3_27 0x1f0
- >;
- };
+ pinctrl_ssi1: ssi1grp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
+ MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
+ MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
+ MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
+ >;
+ };
- pinctrl_stk5led: stk5ledgrp {
- fsl,pins = <MX53_PAD_EIM_A18__GPIO2_20 0xc0>;
- };
+ pinctrl_ssi2: ssi2grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC 0x80000000
+ MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD 0x80000000
+ MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS 0x80000000
+ MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD 0x80000000
+ MX53_PAD_EIM_D27__GPIO3_27 0x1f0
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
- MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
- MX53_PAD_PATA_RESET_B__UART1_CTS 0x1c5
- MX53_PAD_PATA_IORDY__UART1_RTS 0x1c5
- >;
- };
+ pinctrl_stk5led: stk5ledgrp {
+ fsl,pins = <MX53_PAD_EIM_A18__GPIO2_20 0xc0>;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1c5
- MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1c5
- MX53_PAD_PATA_DIOR__UART2_RTS 0x1c5
- MX53_PAD_PATA_INTRQ__UART2_CTS 0x1c5
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
+ MX53_PAD_PATA_RESET_B__UART1_CTS 0x1c5
+ MX53_PAD_PATA_IORDY__UART1_RTS 0x1c5
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
- MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
- MX53_PAD_PATA_DA_1__UART3_CTS 0x1e4
- MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1c5
+ MX53_PAD_PATA_DMARQ__UART2_TXD_MUX 0x1c5
+ MX53_PAD_PATA_DIOR__UART2_RTS 0x1c5
+ MX53_PAD_PATA_INTRQ__UART2_CTS 0x1c5
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- MX53_PAD_EIM_D30__GPIO3_30 0x100 /* OC */
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
+ MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
+ MX53_PAD_PATA_DA_1__UART3_CTS 0x1e4
+ MX53_PAD_PATA_DA_2__UART3_RTS 0x1e4
+ >;
+ };
- pinctrl_usbh1_vbus: usbh1-vbusgrp {
- fsl,pins = <
- MX53_PAD_EIM_D31__GPIO3_31 0xe0 /* VBUS ENABLE */
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D30__GPIO3_30 0x100 /* OC */
+ >;
+ };
- pinctrl_usbotg_vbus: usbotg-vbusgrp {
- fsl,pins = <
- MX53_PAD_GPIO_7__GPIO1_7 0xe0 /* VBUS ENABLE */
- MX53_PAD_GPIO_8__GPIO1_8 0x100 /* OC */
- >;
- };
+ pinctrl_usbh1_vbus: usbh1-vbusgrp {
+ fsl,pins = <
+ MX53_PAD_EIM_D31__GPIO3_31 0xe0 /* VBUS ENABLE */
+ >;
+ };
+
+ pinctrl_usbotg_vbus: usbotg-vbusgrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_7__GPIO1_7 0xe0 /* VBUS ENABLE */
+ MX53_PAD_GPIO_8__GPIO1_8 0x100 /* OC */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-voipac-bsb.dts b/arch/arm/boot/dts/nxp/imx/imx53-voipac-bsb.dts
index ae53d178a683..ae9cc04f23eb 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-voipac-bsb.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-voipac-bsb.dts
@@ -40,67 +40,65 @@
&iomuxc {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
-
- imx53-voipac {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- /* SD2_CD */
- MX53_PAD_EIM_D25__GPIO3_25 0x80000000
- /* SD2_WP */
- MX53_PAD_EIM_A19__GPIO2_19 0x80000000
- >;
- };
+ pinctrl-0 = <&pinctrl_hogbsb>;
+
+ pinctrl_hogbsb: hogbsbgrp {
+ fsl,pins = <
+ /* SD2_CD */
+ MX53_PAD_EIM_D25__GPIO3_25 0x80000000
+ /* SD2_WP */
+ MX53_PAD_EIM_A19__GPIO2_19 0x80000000
+ >;
+ };
- led_pin_gpio: led_gpio {
- fsl,pins = <
- MX53_PAD_EIM_D29__GPIO3_29 0x80000000
- MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
- >;
- };
+ led_pin_gpio: ledgpiogrp {
+ fsl,pins = <
+ MX53_PAD_EIM_D29__GPIO3_29 0x80000000
+ MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
+ >;
+ };
- /* Keyboard controller */
- pinctrl_kpp_1: kppgrp-1 {
- fsl,pins = <
- MX53_PAD_GPIO_9__KPP_COL_6 0xe8
- MX53_PAD_GPIO_4__KPP_COL_7 0xe8
- MX53_PAD_KEY_COL2__KPP_COL_2 0xe8
- MX53_PAD_KEY_COL3__KPP_COL_3 0xe8
- MX53_PAD_KEY_COL4__KPP_COL_4 0xe8
- MX53_PAD_GPIO_2__KPP_ROW_6 0xe0
- MX53_PAD_GPIO_5__KPP_ROW_7 0xe0
- MX53_PAD_KEY_ROW2__KPP_ROW_2 0xe0
- MX53_PAD_KEY_ROW3__KPP_ROW_3 0xe0
- MX53_PAD_KEY_ROW4__KPP_ROW_4 0xe0
- >;
- };
+ /* Keyboard controller */
+ pinctrl_kpp_1: kpp1grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_9__KPP_COL_6 0xe8
+ MX53_PAD_GPIO_4__KPP_COL_7 0xe8
+ MX53_PAD_KEY_COL2__KPP_COL_2 0xe8
+ MX53_PAD_KEY_COL3__KPP_COL_3 0xe8
+ MX53_PAD_KEY_COL4__KPP_COL_4 0xe8
+ MX53_PAD_GPIO_2__KPP_ROW_6 0xe0
+ MX53_PAD_GPIO_5__KPP_ROW_7 0xe0
+ MX53_PAD_KEY_ROW2__KPP_ROW_2 0xe0
+ MX53_PAD_KEY_ROW3__KPP_ROW_3 0xe0
+ MX53_PAD_KEY_ROW4__KPP_ROW_4 0xe0
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
- MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
- MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
- MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x80000000
+ MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x80000000
+ MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
+ MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x80000000
+ >;
+ };
- pinctrl_esdhc2: esdhc2grp {
- fsl,pins = <
- MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
- MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
- MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
- MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
- MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
- MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
- >;
- };
+ pinctrl_esdhc2: esdhc2grp {
+ fsl,pins = <
+ MX53_PAD_SD2_CMD__ESDHC2_CMD 0x1d5
+ MX53_PAD_SD2_CLK__ESDHC2_CLK 0x1d5
+ MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
+ MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
+ MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
+ MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX53_PAD_GPIO_3__I2C3_SCL 0xc0000000
- MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX53_PAD_GPIO_3__I2C3_SCL 0xc0000000
+ MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi
index c0622cf7188c..6dc70a92d831 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi
@@ -37,74 +37,72 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx53-voipac {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- /* Make DA9053 regulator functional */
- MX53_PAD_GPIO_16__GPIO7_11 0x80000000
- /* FEC Power enable */
- MX53_PAD_GPIO_11__GPIO4_1 0x80000000
- /* FEC RST */
- MX53_PAD_GPIO_12__GPIO4_2 0x80000000
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* Make DA9053 regulator functional */
+ MX53_PAD_GPIO_16__GPIO7_11 0x80000000
+ /* FEC Power enable */
+ MX53_PAD_GPIO_11__GPIO4_1 0x80000000
+ /* FEC RST */
+ MX53_PAD_GPIO_12__GPIO4_2 0x80000000
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
- MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
- MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
+ MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
+ MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
- MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
- MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
- MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
- MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
- MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
- MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
- MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
- MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
- MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX53_PAD_FEC_MDC__FEC_MDC 0x80000000
+ MX53_PAD_FEC_MDIO__FEC_MDIO 0x80000000
+ MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER 0x80000000
+ MX53_PAD_FEC_CRS_DV__FEC_RX_DV 0x80000000
+ MX53_PAD_FEC_RXD1__FEC_RDATA_1 0x80000000
+ MX53_PAD_FEC_RXD0__FEC_RDATA_0 0x80000000
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN 0x80000000
+ MX53_PAD_FEC_TXD1__FEC_TDATA_1 0x80000000
+ MX53_PAD_FEC_TXD0__FEC_TDATA_0 0x80000000
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX53_PAD_EIM_D21__I2C1_SCL 0xc0000000
- MX53_PAD_EIM_D28__I2C1_SDA 0xc0000000
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D21__I2C1_SCL 0xc0000000
+ MX53_PAD_EIM_D28__I2C1_SDA 0xc0000000
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
- MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_PATA_DIOW__UART1_TXD_MUX 0x1e4
+ MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
+ >;
+ };
- pinctrl_nand: nandgrp {
- fsl,pins = <
- MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
- MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
- MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
- MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
- MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
- MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
- MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
- MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 0xa4
- MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 0xa4
- MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 0xa4
- MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 0xa4
- MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 0xa4
- MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 0xa4
- MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 0xa4
- MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 0xa4
- >;
- };
+ pinctrl_nand: nandgrp {
+ fsl,pins = <
+ MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
+ MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
+ MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
+ MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
+ MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
+ MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
+ MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
+ MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 0xa4
+ MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 0xa4
+ MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 0xa4
+ MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 0xa4
+ MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 0xa4
+ MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 0xa4
+ MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 0xa4
+ MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 0xa4
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
index 07658e477095..845e2bf8460a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53.dtsi
@@ -458,7 +458,7 @@
clocks = <&clks IMX5_CLK_SRTC_GATE>;
};
- iomuxc: iomuxc@53fa8000 {
+ iomuxc: pinctrl@53fa8000 {
compatible = "fsl,imx53-iomuxc";
reg = <0x53fa8000 0x4000>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6-logicpd-baseboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6-logicpd-baseboard.dtsi
index d477a937b47a..1e0a588b2a15 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6-logicpd-baseboard.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6-logicpd-baseboard.dtsi
@@ -534,7 +534,7 @@
>;
};
- pinctrl_usdhc2_100mhz: h100-usdhc2-100mhz {
+ pinctrl_usdhc2_100mhz: h100-usdhc2-100mhzgrp {
fsl,pins = <
MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* CD */
MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9
@@ -546,7 +546,7 @@
>;
};
- pinctrl_usdhc2_200mhz: h100-usdhc2-200mhz {
+ pinctrl_usdhc2_200mhz: h100-usdhc2-200mhzgrp {
fsl,pins = <
MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* CD */
MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-aster.dts
index 82a0d1a28d12..987058ab0a9b 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-aster.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-aster.dts
@@ -52,7 +52,7 @@
&pinctrl_weim_gpio_5
>;
- pinctrl_gpio_aster: gpioaster {
+ pinctrl_gpio_aster: gpioastergrp {
fsl,pins = <
MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x1b0b0
MX6QDL_PAD_KEY_ROW2__GPIO4_IO11 0x1b0b0
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-pdk2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-pdk2.dts
new file mode 100644
index 000000000000..38235925257a
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-pdk2.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Marek Vasut <marex@denx.de>
+ *
+ * DHCOM iMX6 variant:
+ * DHCM-iMX6DL-C080-R102-F0819-E-SD-RTC-T-HS-I-01D2
+ * DHCOM PCB number: 493-400 or newer
+ * PDK2 PCB number: 516-400 or newer
+ */
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-dhcom-som.dtsi"
+#include "imx6qdl-dhcom-pdk2.dtsi"
+
+/ {
+ model = "DH electronics i.MX6DL DHCOM on Premium Developer Kit (2)";
+ compatible = "dh,imx6dl-dhcom-pdk2", "dh,imx6dl-dhcom-som",
+ "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-picoitx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-picoitx.dts
index 038bb0025556..775caf8208c5 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-picoitx.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-picoitx.dts
@@ -3,7 +3,7 @@
* Copyright (C) 2021 DH electronics GmbH
*
* DHCOM iMX6 variant:
- * DHCM-iMX6DL-C0800-R102-F0819-E-SD-RTC-T-HS-I-01D2
+ * DHCM-iMX6DL-C080-R102-F0819-E-SD-RTC-T-HS-I-01D2
* DHCOM PCB number: 493-300 or newer
* PicoITX PCB number: 487-600 or newer
*/
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-eckelmann-ci4x10.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-eckelmann-ci4x10.dts
index 33825b5a8f26..5ed55f74b398 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-eckelmann-ci4x10.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-eckelmann-ci4x10.dts
@@ -139,7 +139,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- pinctrl_hog: hog {
+ pinctrl_hog: hoggrp {
fsl,pins = <
MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x00000018 /* buzzer */
MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x00000018 /* OUT_1 */
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts
index 72ee236d2f5e..ec5a9bf40677 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts
@@ -395,7 +395,7 @@
>;
};
- pinctrl_ipu1_lcdif: pinctrlipu1lcdif { /* parallel port 24-bit */
+ pinctrl_ipu1_lcdif: pinctrlipu1lcdifgrp { /* parallel port 24-bit */
fsl,pins = <
MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 /* VDOUT_PCLK */
MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts
index 773a84a5739d..0b1275a8891f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts
@@ -773,7 +773,7 @@
>;
};
- pinctrl_pca9539: pca9539 {
+ pinctrl_pca9539: pca9539grp {
fsl,pins = <
MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts
index 36b031236e47..e543c4f2bc94 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts
@@ -133,7 +133,7 @@
};
&iomuxc {
- pinctrl_can1phy: can1phy {
+ pinctrl_can1phy: can1phygrp {
fsl,pins = <
/* CAN1_SR */
MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x13070
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts
index 568e98cb62aa..29dc6875ab66 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts
@@ -507,7 +507,7 @@
>;
};
- pinctrl_can1phy: can1phy {
+ pinctrl_can1phy: can1phygrp {
fsl,pins = <
/* CAN1_SR */
MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x13070
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi
index 8a637fdff073..de80ca141bca 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi
@@ -352,261 +352,259 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- qmx6mux: imx6qdl-qmx6 {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_DI0_PIN2__AUD6_TXD 0x110b0 /* Q7[67] HDA_SDO */
- MX6QDL_PAD_DI0_PIN3__AUD6_TXFS 0x30b0 /* Q7[59] HDA_SYNC */
- MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x30b0 /* Q7[65] HDA_SDI */
- MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x30b0 /* Q7[63] HDA_BITCLK */
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_PIN2__AUD6_TXD 0x110b0 /* Q7[67] HDA_SDO */
+ MX6QDL_PAD_DI0_PIN3__AUD6_TXFS 0x30b0 /* Q7[59] HDA_SYNC */
+ MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x30b0 /* Q7[65] HDA_SDI */
+ MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x30b0 /* Q7[63] HDA_BITCLK */
+ >;
+ };
- /* PHY is on System on Module, Q7[3-15] have Ethernet lines */
- pinctrl_enet: enet {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
- >;
- };
+ /* PHY is on System on Module, Q7[3-15] have Ethernet lines */
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ >;
+ };
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* PCIE_WAKE_B */
- MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x80000000 /* I2C multiplexer */
- MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x80000000 /* SD4_CD# */
- MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x80000000 /* SD4_WP */
- MX6QDL_PAD_CSI0_MCLK__CCM_CLKO1 0x80000000 /* Camera MCLK */
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* PCIE_WAKE_B */
+ MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x80000000 /* I2C multiplexer */
+ MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x80000000 /* SD4_CD# */
+ MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x80000000 /* SD4_WP */
+ MX6QDL_PAD_CSI0_MCLK__CCM_CLKO1 0x80000000 /* Camera MCLK */
+ >;
+ };
- pinctrl_i2c1: i2c1 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 /* Q7[66] I2C_CLK */
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 /* Q7[68] I2C_DAT */
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 /* Q7[66] I2C_CLK */
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 /* Q7[68] I2C_DAT */
+ >;
+ };
- pinctrl_i2c1_gpio: i2c1-gpio {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x1b0b0 /* Q7[66] I2C_CLK */
- MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b0 /* Q7[68] I2C_DAT */
- >;
- };
+ pinctrl_i2c1_gpio: i2c1-gpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x1b0b0 /* Q7[66] I2C_CLK */
+ MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b0 /* Q7[68] I2C_DAT */
+ >;
+ };
- pinctrl_i2c2: i2c2 {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 /* Q7[152] SDVO_CTRL_CLK */
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 /* Q7[150] SDVO_CTRL_DAT */
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 /* Q7[152] SDVO_CTRL_CLK */
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 /* Q7[150] SDVO_CTRL_DAT */
+ >;
+ };
- pinctrl_i2c2_gpio: i2c2-gpio {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x1b0b0 /* Q7[152] SDVO_CTRL_CLK */
- MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x1b0b0 /* Q7[150] SDVO_CTRL_DAT */
- >;
- };
+ pinctrl_i2c2_gpio: i2c2-gpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x1b0b0 /* Q7[152] SDVO_CTRL_CLK */
+ MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x1b0b0 /* Q7[150] SDVO_CTRL_DAT */
+ >;
+ };
- pinctrl_i2c3: i2c3 {
- fsl,pins = <
- MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 /* Q7[60] SMB_CLK */
- MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 /* Q7[62] SMB_DAT */
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 /* Q7[60] SMB_CLK */
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 /* Q7[62] SMB_DAT */
+ >;
+ };
- pinctrl_i2c3_gpio: i2c3-gpio {
- fsl,pins = <
- MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b0 /* Q7[60] SMB_CLK */
- MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0 /* Q7[62] SMB_DAT */
- >;
- };
+ pinctrl_i2c3_gpio: i2c3-gpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b0 /* Q7[60] SMB_CLK */
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0 /* Q7[62] SMB_DAT */
+ >;
+ };
- pinctrl_phy_reset: phy-reset {
- fsl,pins = <
- MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x1b0b0 /* RGMII Phy Reset */
- >;
- };
+ pinctrl_phy_reset: phy-resetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x1b0b0 /* RGMII Phy Reset */
+ >;
+ };
- pinctrl_pwm4: pwm4 {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 /* Q7[123] LVDS_BLT_CTRL */
- >;
- };
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 /* Q7[123] LVDS_BLT_CTRL */
+ >;
+ };
- pinctrl_q7_backlight_enable: q7-backlight-enable {
- fsl,pins = <
- MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 /* Q7[112] LVDS_BLEN */
- >;
- };
+ pinctrl_q7_backlight_enable: q7-backlight-enablegrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 /* Q7[112] LVDS_BLEN */
+ >;
+ };
- pinctrl_q7_gpio0: q7-gpio0 {
- fsl,pins = <
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0 /* Q7[185] GPIO0 */
- >;
- };
+ pinctrl_q7_gpio0: q7-gpio0grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0 /* Q7[185] GPIO0 */
+ >;
+ };
- pinctrl_q7_gpio1: q7-gpio1 {
- fsl,pins = <
- MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0 /* Q7[186] GPIO1 */
- >;
- };
+ pinctrl_q7_gpio1: q7-gpio1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0 /* Q7[186] GPIO1 */
+ >;
+ };
- pinctrl_q7_gpio2: q7-gpio2 {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x1b0b0 /* Q7[187] GPIO2 */
- >;
- };
+ pinctrl_q7_gpio2: q7-gpio2grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x1b0b0 /* Q7[187] GPIO2 */
+ >;
+ };
- pinctrl_q7_gpio3: q7-gpio3 {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27 0x1b0b0 /* Q7[188] GPIO3 */
- >;
- };
+ pinctrl_q7_gpio3: q7-gpio3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27 0x1b0b0 /* Q7[188] GPIO3 */
+ >;
+ };
- pinctrl_q7_gpio4: q7-gpio4 {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0 /* Q7[189] GPIO4 */
- >;
- };
+ pinctrl_q7_gpio4: q7-gpio4grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0 /* Q7[189] GPIO4 */
+ >;
+ };
- pinctrl_q7_gpio5: q7-gpio5 {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x1b0b0 /* Q7[190] GPIO5 */
- >;
- };
+ pinctrl_q7_gpio5: q7-gpio5grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x1b0b0 /* Q7[190] GPIO5 */
+ >;
+ };
- pinctrl_q7_gpio6: q7-gpio6 {
- fsl,pins = <
- MX6QDL_PAD_GPIO_16__GPIO7_IO11 0x1b0b0 /* Q7[191] GPIO6 */
- >;
- };
+ pinctrl_q7_gpio6: q7-gpio6grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_16__GPIO7_IO11 0x1b0b0 /* Q7[191] GPIO6 */
+ >;
+ };
- pinctrl_q7_gpio7: q7-gpio7 {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0 /* Q7[192] GPIO7 */
- >;
- };
+ pinctrl_q7_gpio7: q7-gpio7grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0 /* Q7[192] GPIO7 */
+ >;
+ };
- pinctrl_q7_hda_reset: q7-hda-reset {
- fsl,pins = <
- MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x1b0b0 /* Q7[61] HDA_RST_N */
- >;
- };
+ pinctrl_q7_hda_reset: q7-hda-resetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x1b0b0 /* Q7[61] HDA_RST_N */
+ >;
+ };
- pinctrl_q7_lcd_power: lcd-power {
- fsl,pins = <
- MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* Q7[111] LVDS_PPEN */
- >;
- };
+ pinctrl_q7_lcd_power: lcd-powergrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* Q7[111] LVDS_PPEN */
+ >;
+ };
- pinctrl_q7_sdio_power: q7-sdio-power {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0 /* Q7[47] SDIO_PWR# */
- >;
- };
+ pinctrl_q7_sdio_power: q7-sdio-powergrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0 /* Q7[47] SDIO_PWR# */
+ >;
+ };
- pinctrl_q7_sleep_button: q7-sleep-button {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x1b0b0 /* Q7[21] SLP_BTN# */
- >;
- };
+ pinctrl_q7_sleep_button: q7-sleep-buttongrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x1b0b0 /* Q7[21] SLP_BTN# */
+ >;
+ };
- pinctrl_q7_spi_cs1: spi-cs1 {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x1b0b0 /* Q7[202] SPI_CS1# */
- >;
- };
+ pinctrl_q7_spi_cs1: spi-cs1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x1b0b0 /* Q7[202] SPI_CS1# */
+ >;
+ };
- /* SPI1 bus does not leave System on Module */
- pinctrl_spi1: spi1 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0
- >;
- };
+ /* SPI1 bus does not leave System on Module */
+ pinctrl_spi1: spi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0
+ >;
+ };
- /* Debug connector on Q7 module */
- pinctrl_uart2: uart2 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ /* Debug connector on Q7 module */
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart3: uart3 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 /* Q7[177] UART0_RX */
- MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 /* Q7[171] UART0_TX */
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 /* Q7[177] UART0_RX */
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 /* Q7[171] UART0_TX */
+ >;
+ };
- pinctrl_usbotg: usbotg {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 /* Q7[92] USB_ID */
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 /* Q7[92] USB_ID */
+ >;
+ };
- /* µSD card slot on Q7 module */
- pinctrl_usdhc2: usdhc2 {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* SD2_CD */
- >;
- };
+ /* µSD card slot on Q7 module */
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* SD2_CD */
+ >;
+ };
- /* eMMC module on Q7 module */
- pinctrl_usdhc3: usdhc3 {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- >;
- };
+ /* eMMC module on Q7 module */
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ >;
+ };
- pinctrl_usdhc4: usdhc4 {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 /* Q7[45] SDIO_CMD */
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x17059 /* Q7[42] SDIO_CLK */
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 /* Q7[48] SDIO_DAT1 */
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 /* Q7[49] SDIO_DAT0 */
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 /* Q7[50] SDIO_DAT3 */
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 /* Q7[51] SDIO_DAT2 */
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 /* Q7[45] SDIO_CMD */
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x17059 /* Q7[42] SDIO_CLK */
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 /* Q7[48] SDIO_DAT1 */
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 /* Q7[49] SDIO_DAT0 */
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 /* Q7[50] SDIO_DAT3 */
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 /* Q7[51] SDIO_DAT2 */
+ >;
+ };
- pinctrl_wdog: wdog {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT8__WDOG1_B 0x1b0b0 /* Watchdog output signal */
- >;
- };
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT8__WDOG1_B 0x1b0b0 /* Watchdog output signal */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts
index 114739d10447..e9ac4768f36c 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts
@@ -391,208 +391,206 @@
&iomuxc {
pinctrl-names = "default";
- imx6-riotboard {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* CAM_MCLK */
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* CAM_MCLK */
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x000b1 /* CS0 */
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x000b1 /* CS0 */
+ >;
+ };
- pinctrl_ecspi2: ecspi2grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 0x000b1 /* CS1 */
- MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI 0x100b1
- MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO 0x100b1
- MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x000b1 /* CS0 */
- MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK 0x100b1
- >;
- };
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 0x000b1 /* CS1 */
+ MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x000b1 /* CS0 */
+ MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK 0x100b1
+ >;
+ };
- pinctrl_ecspi3: ecspi3grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
- MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
- MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
- MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x000b1 /* CS0 */
- MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x000b1 /* CS1 */
- >;
- };
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x000b1 /* CS0 */
+ MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x000b1 /* CS1 */
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1 /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030 /* AR8035 pin strapping: IO voltage: pull up */
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030 /* AR8035 pin strapping: PHYADDR#0: pull down */
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030 /* AR8035 pin strapping: PHYADDR#1: pull down */
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030 /* AR8035 pin strapping: MODE#1: pull up */
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 /* AR8035 pin strapping: MODE#3: pull up */
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0 /* AR8035 pin strapping: MODE#0: pull down */
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 /* GPIO16 -> AR8035 25MHz */
- MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0 /* RGMII_nRST */
- MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x180b0 /* AR8035 interrupt */
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1 /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030 /* AR8035 pin strapping: IO voltage: pull up */
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030 /* AR8035 pin strapping: PHYADDR#0: pull down */
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030 /* AR8035 pin strapping: PHYADDR#1: pull down */
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030 /* AR8035 pin strapping: MODE#1: pull up */
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 /* AR8035 pin strapping: MODE#3: pull up */
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0 /* AR8035 pin strapping: MODE#0: pull down */
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 /* GPIO16 -> AR8035 25MHz */
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0 /* RGMII_nRST */
+ MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x180b0 /* AR8035 interrupt */
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
- MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c4: i2c4grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_7__I2C4_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_8__I2C4_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__I2C4_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_8__I2C4_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_led: ledgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* user led0 */
- MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b1 /* user led1 */
- >;
- };
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* user led0 */
+ MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b1 /* user led1 */
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm2: pwm2grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT9__PWM2_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT9__PWM2_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm3: pwm3grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm4: pwm4grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart5: uart5grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0 /* MX6QDL_PAD_EIM_D22__USB_OTG_PWR */
- MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0 /* MX6QDL_PAD_EIM_D22__USB_OTG_PWR */
+ MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* SD2 CD */
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1f0b0 /* SD2 WP */
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* SD2 CD */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1f0b0 /* SD2 WP */
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* SD3 CD */
- MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* SD3 WP */
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* SD3 CD */
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* SD3 WP */
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x17059 /* SD4 RST (eMMC) */
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x17059 /* SD4 RST (eMMC) */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dts
index 51a9bb9d6bc2..7436626673fc 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dts
@@ -51,7 +51,6 @@
&backlight {
pwms = <&pwm2 0 500000 0>;
- /delete-property/ turn-on-delay-ms;
};
&can1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi
index c32ea040fecd..8bc6376d0dc1 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi
@@ -506,7 +506,7 @@
>;
};
- pinctrl_usbh1_vbus: usbh1-vbus {
+ pinctrl_usbh1_vbus: usbh1-vbusgrp {
fsl,pins = <
MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x98
>;
@@ -519,7 +519,7 @@
>;
};
- pinctrl_usbotg_vbus: usbotg-vbus {
+ pinctrl_usbotg_vbus: usbotg-vbusgrp {
fsl,pins = <
MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x98
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi
index bcf4d9c870ec..2f42c56c21f6 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi
@@ -500,7 +500,7 @@
>;
};
- pinctrl_usbh1_vbus: usbh1-vbus {
+ pinctrl_usbh1_vbus: usbh1-vbusgrp {
fsl,pins = <
MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x98
>;
@@ -513,7 +513,7 @@
>;
};
- pinctrl_usbotg_vbus: usbotg-vbus {
+ pinctrl_usbotg_vbus: usbotg-vbusgrp {
fsl,pins = <
MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x98
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-arm2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-arm2.dts
index 631d6d690959..235148c1edf1 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-arm2.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-arm2.dts
@@ -55,114 +55,112 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6q-arm2 {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
- pinctrl_gpmi_nand: gpminandgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- >;
- };
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
- MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
+ >;
+ };
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ >;
+ };
- pinctrl_usdhc3_cdwp: usdhc3cdwp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
- MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
- >;
- };
+ pinctrl_usdhc3_cdwp: usdhc3cdwpgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ba16.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-ba16.dtsi
index 09d9ca0cb332..d77472519086 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-ba16.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-ba16.dtsi
@@ -623,7 +623,7 @@
>;
};
- pinctrl_usdhc3_reset: usdhc3grp-reset {
+ pinctrl_usdhc3_reset: usdhc3-resetgrp {
fsl,pins = <
MX6QDL_PAD_SD3_RST__SD3_RESET 0x170F9
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-dhcom-pdk2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-dhcom-pdk2.dts
index d4d57370615d..6efd7e9fc1b1 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-dhcom-pdk2.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-dhcom-pdk2.dts
@@ -4,7 +4,7 @@
* Copyright (C) 2018 Marek Vasut <marex@denx.de>
*
* DHCOM iMX6 variant:
- * DHCM-iMX6Q-C0800-R102-F0819-E-SD-RTC-T-HS-I-01D2
+ * DHCM-iMX6Q-C080-R102-F0819-E-SD-RTC-T-HS-I-01D2
* DHCOM PCB number: 493-300 or newer
* PDK2 PCB number: 516-400 or newer
*/
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts
index 9f7ac7158c46..c5525b2c1dbd 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts
@@ -283,138 +283,136 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6q-dmo-edmqmx6 {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x80000000
- MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x80000000
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x80000000
+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x80000000
+ >;
+ };
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
- MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0
- >;
- };
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0
+ >;
+ };
- pinctrl_ecspi5: ecspi5rp-1 {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x80000000
- MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI 0x80000000
- MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x80000000
- MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x80000000
- >;
- };
+ pinctrl_ecspi5: ecspi5rp-1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x80000000
+ MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI 0x80000000
+ MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x80000000
+ MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x80000000
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b0b0
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_pcie: pciegrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x100b1
- >;
- };
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x100b1
+ >;
+ };
- pinctrl_pfuze: pfuze100grp1 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000
- >;
- };
+ pinctrl_pfuze: pfuze100grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000
+ >;
+ };
- pinctrl_stmpe1: stmpe1grp {
- fsl,pins = <MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x80000000>;
- };
+ pinctrl_stmpe1: stmpe1grp {
+ fsl,pins = <MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x80000000>;
+ };
- pinctrl_stmpe2: stmpe2grp {
- fsl,pins = <MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000>;
- };
+ pinctrl_stmpe2: stmpe2grp {
+ fsl,pins = <MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000>;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-gk802.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gk802.dts
index ce55c9558679..e0d29b07fbb1 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-gk802.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-gk802.dts
@@ -70,58 +70,56 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6q-gk802 {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- /* Recovery button, active-low */
- MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x100b1
- /* RTL8192CU enable GPIO, active-low */
- MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* Recovery button, active-low */
+ MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x100b1
+ /* RTL8192CU enable GPIO, active-low */
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-h100.dts b/arch/arm/boot/dts/nxp/imx/imx6q-h100.dts
index a603562ea49a..46e011a363e8 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-h100.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-h100.dts
@@ -217,120 +217,118 @@
};
&iomuxc {
- h100 {
- pinctrl_h100_hdmi: h100-hdmi {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- >;
- };
+ pinctrl_h100_hdmi: h100-hdmigrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
- pinctrl_h100_i2c1: h100-i2c1 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_h100_i2c1: h100-i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_h100_i2c2: h100-i2c2 {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_h100_i2c2: h100-i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_h100_leds: pinctrl-h100-leds {
- fsl,pins = <
- MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x1b0b0
- MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x1b0b0
- MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x1b0b0
- >;
- };
+ pinctrl_h100_leds: pinctrl-h100-ledsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x1b0b0
+ MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x1b0b0
+ MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x1b0b0
+ >;
+ };
- pinctrl_h100_reg_hdmi: h100-reg-hdmi {
- fsl,pins = <
- MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b0
- >;
- };
+ pinctrl_h100_reg_hdmi: h100-reg-hdmigrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b0
+ >;
+ };
- pinctrl_h100_sgtl5000: h100-sgtl5000 {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
- MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
- MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
- MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
- MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
- >;
- };
+ pinctrl_h100_sgtl5000: h100-sgtl5000grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+ MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
+ MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
+ MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
+ MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
+ >;
+ };
- pinctrl_h100_tc358743: h100-tc358743 {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0
- >;
- };
+ pinctrl_h100_tc358743: h100-tc358743grp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0
+ >;
+ };
- pinctrl_h100_uart2: h100-uart2 {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- >;
- };
+ pinctrl_h100_uart2: h100-uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_h100_usbh1_vbus: hummingboard-usbh1-vbus {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0
- >;
- };
+ pinctrl_h100_usbh1_vbus: hummingboard-usbh1-vbusgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0
+ >;
+ };
- pinctrl_h100_usbotg_id: hummingboard-usbotg-id {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
- >;
- };
+ pinctrl_h100_usbotg_id: hummingboard-usbotg-idgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
+ >;
+ };
- pinctrl_h100_usbotg_vbus: hummingboard-usbotg-vbus {
- fsl,pins = <
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0
- >;
- };
+ pinctrl_h100_usbotg_vbus: hummingboard-usbotg-vbusgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0
+ >;
+ };
- pinctrl_h100_usdhc2: h100-usdhc2 {
- fsl,pins = <
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b0b0
- >;
- };
+ pinctrl_h100_usdhc2: h100-usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
+ MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b0b0
+ >;
+ };
- pinctrl_h100_usdhc2_100mhz: h100-usdhc2-100mhz {
- fsl,pins = <
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
- MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b0b0
- >;
- };
+ pinctrl_h100_usdhc2_100mhz: h100-usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
+ MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b0b0
+ >;
+ };
- pinctrl_h100_usdhc2_200mhz: h100-usdhc2-200mhz {
- fsl,pins = <
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
- MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b0b0
- >;
- };
+ pinctrl_h100_usdhc2_200mhz: h100-usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
+ MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-logicpd.dts b/arch/arm/boot/dts/nxp/imx/imx6q-logicpd.dts
index 46a4ddedb423..86b813a57c1e 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-logicpd.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-logicpd.dts
@@ -110,13 +110,13 @@
};
&iomuxc {
- pinctrl_lcd_reg: lcdreg {
+ pinctrl_lcd_reg: lcdreggrp {
fsl,pins = <
MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x100b0 /* R_LCD_PANEL_PWR */
>;
};
- pinctrl_lcd_reset: lcdreset {
+ pinctrl_lcd_reset: lcdresetgrp {
fsl,pins = <
MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x100b0 /* LCD_nRESET */
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-lxr.dts b/arch/arm/boot/dts/nxp/imx/imx6q-lxr.dts
new file mode 100644
index 000000000000..ae4f8eeb105d
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-lxr.dts
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+//
+// Copyright 2024 Comvetia AG
+
+/dts-v1/;
+#include "imx6q-phytec-pfla02.dtsi"
+
+/ {
+ model = "COMVETIA QSoIP LXR-2";
+ compatible = "comvetia,imx6q-lxr", "phytec,imx6q-pfla02", "fsl,imx6q";
+
+ chosen {
+ stdout-path = &uart4;
+ };
+
+ spi {
+ compatible = "spi-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi_gpio>;
+ sck-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>;
+ mosi-gpios = <&gpio5 7 GPIO_ACTIVE_HIGH>;
+ num-chipselects = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fpga@0 {
+ compatible = "altr,fpga-passive-serial";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fpga>;
+ nconfig-gpios = <&gpio4 18 GPIO_ACTIVE_LOW>;
+ nstat-gpios = <&gpio4 19 GPIO_ACTIVE_LOW>;
+ confd-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+ };
+ };
+};
+
+&ecspi3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3>;
+ cs-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ };
+};
+
+&fec {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&usdhc3 {
+ no-1-8-v;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_fpga: fpgagrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
+ MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b0
+ MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b0
+ >;
+ };
+
+ pinctrl_spi_gpio: spigpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08 0x1b0b0
+ MX6QDL_PAD_DISP0_DAT13__GPIO5_IO07 0x1b0b0
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-mba6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-mba6.dtsi
index 0d7be4567291..1e5eb837fd80 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-mba6.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-mba6.dtsi
@@ -32,7 +32,7 @@
};
&iomuxc {
- pinctrl_ecspi5_mba6x: ecspi5grp-mba6x {
+ pinctrl_ecspi5_mba6x: ecspi5-mba6xgrp {
fsl,pins = <
/* HYS, SPEED = MED, 100k up, DSE = 011, SRE_FAST */
MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x1b099
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts b/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts
index d392b5bd2eea..8c3a9ea8d5b3 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts
@@ -530,7 +530,7 @@
};
&iomuxc {
- pinctrl_audmux_novena: audmuxgrp-novena {
+ pinctrl_audmux_novena: audmux-novenagrp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
@@ -539,7 +539,7 @@
>;
};
- pinctrl_backlight_novena: backlightgrp-novena {
+ pinctrl_backlight_novena: backlight-novenagrp {
fsl,pins = <
MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0
MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28 0x1b0b1
@@ -547,7 +547,7 @@
>;
};
- pinctrl_ecspi3_novena: ecspi3grp-novena {
+ pinctrl_ecspi3_novena: ecspi3-novenagrp {
fsl,pins = <
MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
@@ -555,7 +555,7 @@
>;
};
- pinctrl_enet_novena: enetgrp-novena {
+ pinctrl_enet_novena: enet-novenagrp {
fsl,pins = <
MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
@@ -578,7 +578,7 @@
>;
};
- pinctrl_fpga_gpio: fpgagpiogrp-novena {
+ pinctrl_fpga_gpio: fpgagpio-novenagrp {
fsl,pins = <
/* FPGA power */
MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b0b1
@@ -614,7 +614,7 @@
>;
};
- pinctrl_fpga_eim: fpgaeimgrp-novena {
+ pinctrl_fpga_eim: fpgaeim-novenagrp {
fsl,pins = <
/* FPGA power */
MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b0b1
@@ -650,7 +650,7 @@
>;
};
- pinctrl_gpio_keys_novena: gpiokeysgrp-novena {
+ pinctrl_gpio_keys_novena: gpiokeys-novenagrp {
fsl,pins = <
/* User button */
MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0
@@ -661,35 +661,35 @@
>;
};
- pinctrl_hdmi_novena: hdmigrp-novena {
+ pinctrl_hdmi_novena: hdmi-novenagrp {
fsl,pins = <
MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x1b0b1
>;
};
- pinctrl_i2c1_novena: i2c1grp-novena {
+ pinctrl_i2c1_novena: i2c1-novenagrp {
fsl,pins = <
MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
>;
};
- pinctrl_i2c2_novena: i2c2grp-novena {
+ pinctrl_i2c2_novena: i2c2-novenagrp {
fsl,pins = <
MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
>;
};
- pinctrl_i2c3_novena: i2c3grp-novena {
+ pinctrl_i2c3_novena: i2c3-novenagrp {
fsl,pins = <
MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
>;
};
- pinctrl_kpp_novena: kppgrp-novena {
+ pinctrl_kpp_novena: kpp-novenagrp {
fsl,pins = <
/* Front panel button */
MX6QDL_PAD_KEY_ROW1__KEY_ROW1 0x1b0b1
@@ -698,13 +698,13 @@
>;
};
- pinctrl_leds_novena: ledsgrp-novena {
+ pinctrl_leds_novena: leds-novenagrp {
fsl,pins = <
MX6QDL_PAD_SD1_DAT3__GPIO1_IO21 0x1b0b1
>;
};
- pinctrl_pcie_novena: pciegrp-novena {
+ pinctrl_pcie_novena: pcie-novenagrp {
fsl,pins = <
/* Reset */
MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b1
@@ -715,13 +715,13 @@
>;
};
- pinctrl_sata_novena: satagrp-novena {
+ pinctrl_sata_novena: sata-novenagrp {
fsl,pins = <
MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x1b0b1
>;
};
- pinctrl_senoko_novena: senokogrp-novena {
+ pinctrl_senoko_novena: senoko-novenagrp {
fsl,pins = <
/* Senoko IRQ line */
MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x13048
@@ -730,7 +730,7 @@
>;
};
- pinctrl_sound_novena: soundgrp-novena {
+ pinctrl_sound_novena: sound-novenagrp {
fsl,pins = <
/* Audio power regulator */
MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x1b0b1
@@ -740,41 +740,41 @@
>;
};
- pinctrl_stmpe_novena: stmpegrp-novena {
+ pinctrl_stmpe_novena: stmpe-novenagrp {
fsl,pins = <
/* Touchscreen interrupt */
MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13 0x1b0b1
>;
};
- pinctrl_uart2_novena: uart2grp-novena {
+ pinctrl_uart2_novena: uart2-novenagrp {
fsl,pins = <
MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
>;
};
- pinctrl_uart3_novena: uart3grp-novena {
+ pinctrl_uart3_novena: uart3-novenagrp {
fsl,pins = <
MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
>;
};
- pinctrl_uart4_novena: uart4grp-novena {
+ pinctrl_uart4_novena: uart4-novenagrp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
>;
};
- pinctrl_usbotg_novena: usbotggrp-novena {
+ pinctrl_usbotg_novena: usbotg-novenagrp {
fsl,pins = <
MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
>;
};
- pinctrl_usdhc2_novena: usdhc2grp-novena {
+ pinctrl_usdhc2_novena: usdhc2-novenagrp {
fsl,pins = <
MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9
MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9
@@ -789,7 +789,7 @@
>;
};
- pinctrl_usdhc3_novena: usdhc3grp-novena {
+ pinctrl_usdhc3_novena: usdhc3-novenagrp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts b/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts
index 8d2b608e0b90..fb81bd8ba035 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts
@@ -546,7 +546,7 @@
>;
};
- pinctrl_wifi_npd: wifinpd {
+ pinctrl_wifi_npd: wifinpdgrp {
fsl,pins = <
MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b8b0
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts
index 792b8903d345..0e02e448db10 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts
@@ -133,7 +133,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb_eth_chg>;
- pinctrl_can1phy: can1phy {
+ pinctrl_can1phy: can1phygrp {
fsl,pins = <
/* CAN1_SR */
MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x13070
@@ -187,7 +187,7 @@
>;
};
- pinctrl_wifi_npd: wifinpd {
+ pinctrl_wifi_npd: wifinpdgrp {
fsl,pins = <
/* WL_REG_ON */
MX6QDL_PAD_NANDF_RB0__GPIO6_IO10 0x13069
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-sbc6x.dts b/arch/arm/boot/dts/nxp/imx/imx6q-sbc6x.dts
index 9054c1d58b9d..84fbcd129179 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-sbc6x.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-sbc6x.dts
@@ -25,51 +25,49 @@
};
&iomuxc {
- imx6q-sbc6x {
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010-comtft.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010-comtft.dts
index ac3050a835e5..393bfec58e2f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010-comtft.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010-comtft.dts
@@ -51,7 +51,6 @@
&backlight {
pwms = <&pwm2 0 500000 0>;
- /delete-property/ turn-on-delay-ms;
};
&can1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020-comtft.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020-comtft.dts
index a773f252816c..1ab175ffa238 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020-comtft.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020-comtft.dts
@@ -51,7 +51,6 @@
&backlight {
pwms = <&pwm2 0 500000 0>;
- /delete-property/ turn-on-delay-ms;
};
&can1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-utilite-pro.dts b/arch/arm/boot/dts/nxp/imx/imx6q-utilite-pro.dts
index ad59b23ef27a..aae81feee00d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-utilite-pro.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-utilite-pro.dts
@@ -296,7 +296,7 @@
>;
};
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170B9
MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100B9
@@ -307,7 +307,7 @@
>;
};
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170F9
MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100F9
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi
index edf55760a5c1..1c72da417011 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi
@@ -191,7 +191,7 @@
"MIC_IN", "Mic Jack",
"Mic Jack", "Mic Bias",
"Headphone Jack", "HP_OUT";
- model = "imx6q-apalis-sgtl5000";
+ model = "apalis-imx6";
mux-ext-port = <4>;
mux-int-port = <1>;
ssi-controller = <&ssi1>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos.dtsi
index baa197c90060..acb404c6828b 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos.dtsi
@@ -179,230 +179,228 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog &pinctrl_gpio>;
- imx6qdl-aristainetos {
- pinctrl_aristainetos_usbh1_vbus: aristainetos-usbh1-vbus {
- fsl,pins = <MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0>;
- };
-
- pinctrl_aristainetos_usbotg_vbus: aristainetos-usbotg-vbus {
- fsl,pins = <MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0>;
- };
-
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x1b0b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x1b0b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x1b0b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x1b0b0
- >;
- };
+ pinctrl_aristainetos_usbh1_vbus: aristainetos-usbh1-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0>;
+ };
- pinctrl_backlight: backlightgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b0
- MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b0
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
- >;
- };
-
- pinctrl_ecspi2: ecspi2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1
- MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1
- MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1
- MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x100b1
- >;
- };
-
- pinctrl_ecspi4: ecspi4grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x100b1
- MX6QDL_PAD_EIM_D22__ECSPI4_MISO 0x100b1
- MX6QDL_PAD_EIM_D28__ECSPI4_MOSI 0x100b1
- MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x100b1
- MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0 /* WP pin */
- >;
- };
-
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
- MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
- MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
- MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
- MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
- MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
- MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
- >;
- };
+ pinctrl_aristainetos_usbotg_vbus: aristainetos-usbotg-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0>;
+ };
- pinctrl_flexcan1: flexcan1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
- >;
- };
-
- pinctrl_flexcan2: flexcan2grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX 0x1b0b0
- MX6QDL_PAD_SD3_DAT1__FLEXCAN2_RX 0x1b0b0
- >;
- };
-
- pinctrl_gpio: gpiogrp {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x1b0b0
- MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b0
- MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0
- MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x1b0b0
- MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b0
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
- MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0
- MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
- MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0
- MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0
- MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x1b0b0
- >;
- };
-
- pinctrl_gpmi_nand: gpminandgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x1b0b0
+ >;
+ };
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x10
- >;
- };
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b0
+ MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b0
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
- MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
- >;
- };
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1
+ MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x100b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_ecspi4: ecspi4grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D22__ECSPI4_MISO 0x100b1
+ MX6QDL_PAD_EIM_D28__ECSPI4_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x100b1
+ MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0 /* WP pin */
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- >;
- };
-
- pinctrl_ipu_disp: ipudisp1grp {
- fsl,pins = <
- MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
- MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
- MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
- MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
- MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x20000
- MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
- MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
- MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
- MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
- MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
- MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
- MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
- MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
- MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
- MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
- MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
- MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
- MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
- MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
- MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
- MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
- MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
- MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
- MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
- MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
- MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
- MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
- MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
- MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
- >;
- };
-
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
-
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
- MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
+ >;
+ };
- pinctrl_uart5: uart5grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- >;
- };
-
- pinctrl_usdhc1: usdhc1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x1b0b0
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX 0x1b0b0
+ MX6QDL_PAD_SD3_DAT1__FLEXCAN2_RX 0x1b0b0
>;
- };
-
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x1b0b0
+ };
+
+ pinctrl_gpio: gpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x1b0b0
+ MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b0
+ MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0
+ MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x1b0b0
+ MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b0
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
+ MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0
+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x1b0b0
+ >;
+ };
+
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
+ >;
+ };
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x10
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_ipu_disp: ipudisp1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x20000
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
>;
- };
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x1b0b0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x1b0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi
index f7fac86f0a6b..7cc7ae195988 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi
@@ -413,7 +413,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio>;
- pinctrl_audmux: audmux {
+ pinctrl_audmux: audmuxgrp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x1b0b0
MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x1b0b0
@@ -599,11 +599,11 @@
>;
};
- pinctrl_aristainetos2_usbh1_vbus: aristainetos-usbh1-vbus {
+ pinctrl_aristainetos2_usbh1_vbus: aristainetos-usbh1-vbusgrp {
fsl,pins = <MX6QDL_PAD_GPIO_0__USB_H1_PWR 0x130b0>;
};
- pinctrl_aristainetos2_usbotg_vbus: aristainetos-usbotg-vbus {
+ pinctrl_aristainetos2_usbotg_vbus: aristainetos-usbotg-vbusgrp {
fsl,pins = <MX6QDL_PAD_KEY_ROW4__USB_OTG_PWR 0x130b0>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi
index b01670cdd52c..9f33419c260b 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi
@@ -136,7 +136,7 @@
"LINE_IN", "Line In Jack",
"MIC_IN", "Mic Jack",
"Mic Jack", "Mic Bias";
- model = "imx6dl-colibri-sgtl5000";
+ model = "colibri-imx6";
mux-int-port = <1>;
mux-ext-port = <5>;
ssi-controller = <&ssi1>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi
index bd66430c1d78..41d073f5bfe7 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi
@@ -153,87 +153,85 @@
};
&iomuxc {
- cubox_i {
- pinctrl_cubox_i_hdmi: cubox-i-hdmi {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- >;
- };
+ pinctrl_cubox_i_hdmi: cubox-i-hdmigrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
- pinctrl_cubox_i_i2c2: cubox-i-i2c2 {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_cubox_i_i2c2: cubox-i-i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_cubox_i_i2c3: cubox-i-i2c3 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_cubox_i_i2c3: cubox-i-i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_cubox_i_ir: cubox-i-ir {
- fsl,pins = <
- MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
- >;
- };
+ pinctrl_cubox_i_ir: cubox-i-irgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
+ >;
+ };
- pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led {
- fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>;
- };
+ pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-ledgrp {
+ fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>;
+ };
- pinctrl_cubox_i_spdif: cubox-i-spdif {
- fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
- };
+ pinctrl_cubox_i_spdif: cubox-i-spdifgrp {
+ fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
+ };
- pinctrl_cubox_i_usbh1: cubox-i-usbh1 {
- fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
- };
+ pinctrl_cubox_i_usbh1: cubox-i-usbh1grp {
+ fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
+ };
- pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
- fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
- };
+ pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
+ };
- pinctrl_cubox_i_usbotg: cubox-i-usbotg {
- /*
- * The Cubox-i pulls ID low, but as it's pointless
- * leaving it as a pull-up, even if it is just 10uA.
- */
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
- MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- >;
- };
+ pinctrl_cubox_i_usbotg: cubox-i-usbotggrp {
+ /*
+ * The Cubox-i pulls ID low, but as it's pointless
+ * leaving it as a pull-up, even if it is just 10uA.
+ */
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+ >;
+ };
- pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
- fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x4001b0b0>;
- };
+ pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x4001b0b0>;
+ };
- pinctrl_cubox_i_usdhc2_aux: cubox-i-usdhc2-aux {
- fsl,pins = <
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
- >;
- };
+ pinctrl_cubox_i_usdhc2_aux: cubox-i-usdhc2-auxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
+ MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
+ >;
+ };
- pinctrl_cubox_i_usdhc2: cubox-i-usdhc2 {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- >;
- };
+ pinctrl_cubox_i_usdhc2: cubox-i-usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
+ >;
+ };
- pinctrl_gpio_key: gpio-key {
- fsl,pins = <
- MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x17059
- >;
- };
+ pinctrl_gpio_key: gpio-keygrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-dfi-fs700-m60.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dfi-fs700-m60.dtsi
index 0a6c3a092b34..f560a6b7779a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-dfi-fs700-m60.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-dfi-fs700-m60.dtsi
@@ -47,103 +47,101 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6qdl-dfi-fs700-m60 {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
- MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x80000000 /* PMIC irq */
- MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000 /* MAX11801 irq */
- MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000030b0 /* Backlight enable */
- >;
- };
-
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- >;
- };
-
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
- >;
- };
-
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- >;
- };
-
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- >;
- };
-
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000 /* card detect */
- >;
- };
-
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- >;
- };
-
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- >;
- };
-
- pinctrl_ecspi3: ecspi3grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
- MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
- MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
- MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x80000000 /* PMIC irq */
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000 /* MAX11801 irq */
+ MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000030b0 /* Backlight enable */
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000 /* card detect */
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+ MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-pdk2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-pdk2.dtsi
index 6248b126b557..d7c2b30aecfd 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-pdk2.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-pdk2.dtsi
@@ -56,7 +56,6 @@
};
gpio-keys {
- #size-cells = <0>;
compatible = "gpio-keys";
button-0 {
@@ -144,6 +143,7 @@
panel {
backlight = <&display_bl>;
compatible = "edt,etm0700g0edh6";
+ power-supply = <&reg_panel_3v3>;
port {
lcd_panel_in: endpoint {
@@ -152,6 +152,25 @@
};
};
+ /* Filtered supply voltage */
+ reg_pdk2_24v: regulator-pdk2-24v {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-max-microvolt = <24000000>;
+ regulator-min-microvolt = <24000000>;
+ regulator-name = "24V_PDK2";
+ };
+
+ /* 560-200 U1 */
+ reg_panel_3v3: regulator-panel-3v3 {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "3V3_PANEL";
+ vin-supply = <&reg_pdk2_24v>;
+ };
+
sound {
audio-codec = <&sgtl5000>;
audio-routing =
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-som.dtsi
index eaa87b333164..af0d95396cd5 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-som.dtsi
@@ -256,7 +256,6 @@
regulator-max-microvolt = <1527272>;
regulator-min-microvolt = <787500>;
regulator-ramp-delay = <7000>;
- regulator-suspend-mem-microvolt = <1040000>;
};
sw2_reg: sw2 {
@@ -275,7 +274,6 @@
regulator-max-microvolt = <1527272>;
regulator-min-microvolt = <787500>;
regulator-ramp-delay = <7000>;
- regulator-suspend-mem-microvolt = <980000>;
};
sw4_reg: sw4 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-ds.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ds.dtsi
index f7e517555697..99ebd4dd63e8 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-ds.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-ds.dtsi
@@ -253,7 +253,7 @@
>;
};
- pinctrl_ecspi1_gpio: ecspi1grpgpiogrp {
+ pinctrl_ecspi1_gpio: ecspi1gpiogrp {
fsl,pins = <
MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x1b0b0
MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x1b0b0
@@ -349,7 +349,7 @@
>;
};
- pinctrl_usdhc1_gpio: usdhc1grpgpiogrp {
+ pinctrl_usdhc1_gpio: usdhc1gpiogrp {
fsl,pins = <
MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b0
>;
@@ -366,7 +366,7 @@
>;
};
- pinctrl_usdhc2_gpio: usdhc2grpgpiogrp {
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
fsl,pins = <
MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi
index a308a3584b62..97763db3959f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi
@@ -330,7 +330,6 @@
};
&iomuxc {
-
pinctrl_audmux: audmuxgrp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
@@ -382,79 +381,79 @@
>;
};
- pinctrl_emcon_gpio1: emcongpio1 {
+ pinctrl_emcon_gpio1: emcongpio1grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x0b0b1
>;
};
- pinctrl_emcon_gpio2: emcongpio2 {
+ pinctrl_emcon_gpio2: emcongpio2grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x0b0b1
>;
};
- pinctrl_emcon_gpio3: emcongpio3 {
+ pinctrl_emcon_gpio3: emcongpio3grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x0b0b1
>;
};
- pinctrl_emcon_gpio4: emcongpio4 {
+ pinctrl_emcon_gpio4: emcongpio4grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x0b0b1
>;
};
- pinctrl_emcon_gpio5: emcongpio5 {
+ pinctrl_emcon_gpio5: emcongpio5grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x0b0b1
>;
};
- pinctrl_emcon_gpio6: emcongpio6 {
+ pinctrl_emcon_gpio6: emcongpio6grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x0b0b1
>;
};
- pinctrl_emcon_gpio7: emcongpio7 {
+ pinctrl_emcon_gpio7: emcongpio7grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x0b0b1
>;
};
- pinctrl_emcon_gpio8: emcongpio8 {
+ pinctrl_emcon_gpio8: emcongpio8grp {
fsl,pins = <
MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x0b0b1
>;
};
- pinctrl_emcon_irq_a: emconirqa {
+ pinctrl_emcon_irq_a: emconirqagrp {
fsl,pins = <
MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x0b0b1
>;
};
- pinctrl_emcon_irq_b: emconirqb {
+ pinctrl_emcon_irq_b: emconirqbgrp {
fsl,pins = <
MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x0b0b1
>;
};
- pinctrl_emcon_irq_c: emconirqc {
+ pinctrl_emcon_irq_c: emconirqcgrp {
fsl,pins = <
MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x0b0b1
>;
};
- pinctrl_emcon_irq_pwr: emconirqpwr {
+ pinctrl_emcon_irq_pwr: emconirqpwrgrp {
fsl,pins = <
MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x0b0b1
>;
};
- pinctrl_emcon_wake: emconwake {
+ pinctrl_emcon_wake: emconwakegrp {
fsl,pins = <
MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x1b0b1
>;
@@ -503,13 +502,13 @@
>;
};
- pinctrl_irq_touch1: irqtouch1 {
+ pinctrl_irq_touch1: irqtouch1grp {
fsl,pins = <
MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x0b0b1
>;
};
- pinctrl_irq_touch2: irqtouch2 {
+ pinctrl_irq_touch2: irqtouch2grp {
fsl,pins = <
MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x0b0b1
>;
@@ -552,7 +551,7 @@
>;
};
- pinctrl_pwm_fan: pwmfan {
+ pinctrl_pwm_fan: pwmfangrp {
fsl,pins = <
MX6QDL_PAD_SD4_DAT2__PWM4_OUT 0x0b0b1
>;
@@ -565,7 +564,7 @@
>;
};
- pinctrl_rgb_bl_en: rgbenable {
+ pinctrl_rgb_bl_en: rgbenablegrp {
fsl,pins = <
MX6QDL_PAD_SD4_CMD__GPIO7_IO09 0x0b0b1
>;
@@ -617,13 +616,13 @@
>;
};
- pinctrl_spdif_in: spdifin {
+ pinctrl_spdif_in: spdifingrp {
fsl,pins = <
MX6QDL_PAD_GPIO_16__SPDIF_IN 0x1b0b0
>;
};
- pinctrl_spdif_out: spdifout {
+ pinctrl_spdif_out: spdifoutgrp {
fsl,pins = <
MX6QDL_PAD_GPIO_19__SPDIF_OUT 0x13091
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi
index 0ed6d25024a2..94f1d1ae59aa 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi
@@ -770,14 +770,14 @@
>;
};
- pinctrl_pwm4_backlight: pwm4grpbacklight {
+ pinctrl_pwm4_backlight: pwm4backlightgrp {
fsl,pins = <
/* LVDS_PWM J6.5 */
MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
>;
};
- pinctrl_pwm4_dio: pwm4grpdio {
+ pinctrl_pwm4_dio: pwm4diogrp {
fsl,pins = <
/* DIO3 J16.4 */
MX6QDL_PAD_SD4_DAT2__PWM4_OUT 0x1b0b1
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi
index d1ad65ab6b72..54d4bced2395 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi
@@ -223,100 +223,98 @@
};
&iomuxc {
- hummingboard {
- pinctrl_hummingboard_flexcan1: hummingboard-flexcan1 {
- fsl,pins = <
- MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX 0x80000000
- MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX 0x80000000
- >;
- };
+ pinctrl_hummingboard_flexcan1: hummingboard-flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX 0x80000000
+ MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX 0x80000000
+ >;
+ };
- pinctrl_hummingboard_gpio3_5: hummingboard-gpio3_5 {
- fsl,pins = <
- MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x1b0b1
- >;
- };
+ pinctrl_hummingboard_gpio3_5: hummingboard-gpio3_5grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x1b0b1
+ >;
+ };
- pinctrl_hummingboard_hdmi: hummingboard-hdmi {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- >;
- };
+ pinctrl_hummingboard_hdmi: hummingboard-hdmigrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
- pinctrl_hummingboard_i2c1: hummingboard-i2c1 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_hummingboard_i2c1: hummingboard-i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_hummingboard_i2c2: hummingboard-i2c2 {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_hummingboard_i2c2: hummingboard-i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_hummingboard_pcie_reset: hummingboard-pcie-reset {
- fsl,pins = <
- MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x1b0b1
- >;
- };
+ pinctrl_hummingboard_pcie_reset: hummingboard-pcie-resetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x1b0b1
+ >;
+ };
- pinctrl_hummingboard_pwm1: pwm1grp {
- fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1>;
- };
+ pinctrl_hummingboard_pwm1: pwm1grp {
+ fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1>;
+ };
- pinctrl_hummingboard_sgtl5000: hummingboard-sgtl5000 {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
- MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
- MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
- MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
- MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
- >;
- };
+ pinctrl_hummingboard_sgtl5000: hummingboard-sgtl5000grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+ MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
+ MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
+ MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
+ MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
+ >;
+ };
- pinctrl_hummingboard_spdif: hummingboard-spdif {
- fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
- };
+ pinctrl_hummingboard_spdif: hummingboard-spdifgrp {
+ fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
+ };
- pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus {
- fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
- };
+ pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
+ };
- pinctrl_hummingboard_usbotg_id: hummingboard-usbotg-id {
- /*
- * We want it pulled down for a fixed host connection.
- */
- fsl,pins = <MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x13059>;
- };
+ pinctrl_hummingboard_usbotg_id: hummingboard-usbotg-idgrp {
+ /*
+ * We want it pulled down for a fixed host connection.
+ */
+ fsl,pins = <MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x13059>;
+ };
- pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbus {
- fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
- };
+ pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
+ };
- pinctrl_hummingboard_usdhc2_aux: hummingboard-usdhc2-aux {
- fsl,pins = <
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- >;
- };
+ pinctrl_hummingboard_usdhc2_aux: hummingboard-usdhc2-auxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
+ >;
+ };
- pinctrl_hummingboard_usdhc2: hummingboard-usdhc2 {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- >;
- };
- pinctrl_hummingboard_vmmc: hummingboard-vmmc {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
- >;
- };
+ pinctrl_hummingboard_usdhc2: hummingboard-usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
+ >;
+ };
+ pinctrl_hummingboard_vmmc: hummingboard-vmmcgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2-emmc.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2-emmc.dtsi
index f400405381a7..c3efb001c515 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2-emmc.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2-emmc.dtsi
@@ -42,22 +42,20 @@
*/
&iomuxc {
- hummingboard2 {
- pinctrl_hummingboard2_usdhc3: hummingboard2-usdhc3 {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- MX6QDL_PAD_SD3_RST__SD3_RESET 0x17059
- >;
- };
+ pinctrl_hummingboard2_usdhc3: hummingboard2-usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ MX6QDL_PAD_SD3_RST__SD3_RESET 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi
index e6017f9bf640..3069e1738ba2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi
@@ -261,258 +261,256 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- hummingboard2 {
- pinctrl_hog: hoggrp {
+ pinctrl_hog: hoggrp {
fsl,pins = <
- /*
- * 36 pin headers GPIO description. The pins
- * numbering as following -
- *
- * 3.2v 5v 74 75
- * 73 72 71 70
- * 69 68 67 66
- *
- * 77 78 79 76
- * 65 64 61 60
- * 53 52 51 50
- * 49 48 166 132
- * 95 94 90 91
- * GND 54 24 204
- *
- * The GPIO numbers can be extracted using
- * signal name from below.
- * Example -
- * MX6QDL_PAD_EIM_DA10__GPIO3_IO10 is
- * GPIO(3,10) which is (3-1)*32+10 = gpio 74
- *
- * i.e. The mapping of GPIO(X,Y) to Linux gpio
- * number is : gpio number = (X-1) * 32 + Y
- */
- /* DI1_PIN15 */
- MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x400130b1
- /* DI1_PIN02 */
- MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x400130b1
- /* DISP1_DATA00 */
- MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x400130b1
- /* DISP1_DATA01 */
- MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x400130b1
- /* DISP1_DATA02 */
- MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x400130b1
- /* DISP1_DATA03 */
- MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x400130b1
- /* DISP1_DATA04 */
- MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x400130b1
- /* DISP1_DATA05 */
- MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x400130b1
- /* DISP1_DATA06 */
- MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x400130b1
- /* DISP1_DATA07 */
- MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x400130b1
- /* DI1_D0_CS */
- MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x400130b1
- /* DI1_D1_CS */
- MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x400130b1
- /* DI1_PIN01 */
- MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x400130b1
- /* DI1_PIN03 */
- MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x400130b1
- /* DISP1_DATA08 */
- MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x400130b1
- /* DISP1_DATA09 */
- MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x400130b1
- /* DISP1_DATA10 */
- MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x400130b1
- /* DISP1_DATA11 */
- MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x400130b1
- /* DISP1_DATA12 */
- MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x400130b1
- /* DISP1_DATA13 */
- MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x400130b1
- /* DISP1_DATA14 */
- MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x400130b1
- /* DISP1_DATA15 */
- MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x400130b1
- /* DISP1_DATA16 */
- MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x400130b1
- /* DISP1_DATA17 */
- MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x400130b1
- /* DISP1_DATA18 */
- MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x400130b1
- /* DISP1_DATA19 */
- MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x400130b1
- /* DISP1_DATA20 */
- MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x400130b1
- /* DISP1_DATA21 */
- MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x400130b1
- /* DISP1_DATA22 */
- MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x400130b1
- /* DISP1_DATA23 */
- MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x400130b1
- /* DI1_DISP_CLK */
- MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x400130b1
- /* SPDIF_IN */
- MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24 0x400130b1
- /* SPDIF_OUT */
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x400130b1
-
- /* MikroBUS GPIO pin number 10 */
- MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x400130b1
- >;
- };
+ /*
+ * 36 pin headers GPIO description. The pins
+ * numbering as following -
+ *
+ * 3.2v 5v 74 75
+ * 73 72 71 70
+ * 69 68 67 66
+ *
+ * 77 78 79 76
+ * 65 64 61 60
+ * 53 52 51 50
+ * 49 48 166 132
+ * 95 94 90 91
+ * GND 54 24 204
+ *
+ * The GPIO numbers can be extracted using
+ * signal name from below.
+ * Example -
+ * MX6QDL_PAD_EIM_DA10__GPIO3_IO10 is
+ * GPIO(3,10) which is (3-1)*32+10 = gpio 74
+ *
+ * i.e. The mapping of GPIO(X,Y) to Linux gpio
+ * number is : gpio number = (X-1) * 32 + Y
+ */
+ /* DI1_PIN15 */
+ MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x400130b1
+ /* DI1_PIN02 */
+ MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x400130b1
+ /* DISP1_DATA00 */
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x400130b1
+ /* DISP1_DATA01 */
+ MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x400130b1
+ /* DISP1_DATA02 */
+ MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x400130b1
+ /* DISP1_DATA03 */
+ MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x400130b1
+ /* DISP1_DATA04 */
+ MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x400130b1
+ /* DISP1_DATA05 */
+ MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x400130b1
+ /* DISP1_DATA06 */
+ MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x400130b1
+ /* DISP1_DATA07 */
+ MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x400130b1
+ /* DI1_D0_CS */
+ MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x400130b1
+ /* DI1_D1_CS */
+ MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x400130b1
+ /* DI1_PIN01 */
+ MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x400130b1
+ /* DI1_PIN03 */
+ MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x400130b1
+ /* DISP1_DATA08 */
+ MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x400130b1
+ /* DISP1_DATA09 */
+ MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x400130b1
+ /* DISP1_DATA10 */
+ MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x400130b1
+ /* DISP1_DATA11 */
+ MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x400130b1
+ /* DISP1_DATA12 */
+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x400130b1
+ /* DISP1_DATA13 */
+ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x400130b1
+ /* DISP1_DATA14 */
+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x400130b1
+ /* DISP1_DATA15 */
+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x400130b1
+ /* DISP1_DATA16 */
+ MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x400130b1
+ /* DISP1_DATA17 */
+ MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x400130b1
+ /* DISP1_DATA18 */
+ MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x400130b1
+ /* DISP1_DATA19 */
+ MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x400130b1
+ /* DISP1_DATA20 */
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x400130b1
+ /* DISP1_DATA21 */
+ MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x400130b1
+ /* DISP1_DATA22 */
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x400130b1
+ /* DISP1_DATA23 */
+ MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x400130b1
+ /* DI1_DISP_CLK */
+ MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x400130b1
+ /* SPDIF_IN */
+ MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24 0x400130b1
+ /* SPDIF_OUT */
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x400130b1
+
+ /* MikroBUS GPIO pin number 10 */
+ MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x400130b1
+ >;
+ };
- pinctrl_hummingboard2_ecspi2: hummingboard2-ecspi2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1
- MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1
- MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1
- MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x000b1 /* CS */
- >;
- };
+ pinctrl_hummingboard2_ecspi2: hummingboard2-ecspi2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1
+ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x000b1 /* CS */
+ >;
+ };
- pinctrl_hummingboard2_gpio7_9: hummingboard2-gpio7_9 {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__GPIO7_IO09 0x80000000
- >;
- };
+ pinctrl_hummingboard2_gpio7_9: hummingboard2-gpio7_9grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__GPIO7_IO09 0x80000000
+ >;
+ };
- pinctrl_hummingboard2_hdmi: hummingboard2-hdmi {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- >;
- };
+ pinctrl_hummingboard2_hdmi: hummingboard2-hdmigrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
- pinctrl_hummingboard2_i2c1: hummingboard2-i2c1 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_hummingboard2_i2c1: hummingboard2-i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_hummingboard2_i2c2: hummingboard2-i2c2 {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_hummingboard2_i2c2: hummingboard2-i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_hummingboard2_i2c3: hummingboard2-i2c3 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_hummingboard2_i2c3: hummingboard2-i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_hummingboard2_mipi: hummingboard2_mipi {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x4001b8b1
- MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x4001b8b1
- MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
- >;
- };
+ pinctrl_hummingboard2_mipi: hummingboard2_mipigrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x4001b8b1
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x4001b8b1
+ MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
+ >;
+ };
- pinctrl_hummingboard2_pcie_reset: hummingboard2-pcie-reset {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b1
- >;
- };
+ pinctrl_hummingboard2_pcie_reset: hummingboard2-pcie-resetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b1
+ >;
+ };
- pinctrl_hummingboard2_pwm1: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1
- >;
- };
+ pinctrl_hummingboard2_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1
+ >;
+ };
- pinctrl_hummingboard2_pwm3: pwm3grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
- >;
- };
+ pinctrl_hummingboard2_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
+ >;
+ };
- pinctrl_hummingboard2_sgtl5000: hummingboard2-sgtl5000 {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
- MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
- MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
- MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
- MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
- >;
- };
+ pinctrl_hummingboard2_sgtl5000: hummingboard2-sgtl5000grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+ MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
+ MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
+ MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
+ MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
+ >;
+ };
- pinctrl_hummingboard2_usbh1_vbus: hummingboard2-usbh1-vbus {
- fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
- };
+ pinctrl_hummingboard2_usbh1_vbus: hummingboard2-usbh1-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
+ };
- pinctrl_hummingboard2_usbh2_vbus: hummingboard2-usbh2-vbus {
- fsl,pins = <MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x1b0b0>;
- };
+ pinctrl_hummingboard2_usbh2_vbus: hummingboard2-usbh2-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x1b0b0>;
+ };
- pinctrl_hummingboard2_usbh3_vbus: hummingboard2-usbh3-vbus {
- fsl,pins = <MX6QDL_PAD_SD4_CLK__GPIO7_IO10 0x1b0b0>;
- };
+ pinctrl_hummingboard2_usbh3_vbus: hummingboard2-usbh3-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_SD4_CLK__GPIO7_IO10 0x1b0b0>;
+ };
- pinctrl_hummingboard2_usbotg_id: hummingboard2-usbotg-id {
- /*
- * We want it pulled down for a fixed host connection.
- */
- fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
- };
+ pinctrl_hummingboard2_usbotg_id: hummingboard2-usbotg-idgrp {
+ /*
+ * We want it pulled down for a fixed host connection.
+ */
+ fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+ };
- pinctrl_hummingboard2_usbotg_vbus: hummingboard2-usbotg-vbus {
- fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
- };
+ pinctrl_hummingboard2_usbotg_vbus: hummingboard2-usbotg-vbusgrp {
+ fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
+ };
- pinctrl_hummingboard2_usdhc2_aux: hummingboard2-usdhc2-aux {
- fsl,pins = <
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
- MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
- >;
- };
+ pinctrl_hummingboard2_usdhc2_aux: hummingboard2-usdhc2-auxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
+ MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
+ >;
+ };
- pinctrl_hummingboard2_usdhc2: hummingboard2-usdhc2 {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- >;
- };
+ pinctrl_hummingboard2_usdhc2: hummingboard2-usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
+ >;
+ };
- pinctrl_hummingboard2_usdhc2_100mhz: hummingboard2-usdhc2-100mhz {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
- >;
- };
+ pinctrl_hummingboard2_usdhc2_100mhz: hummingboard2-usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
+ >;
+ };
- pinctrl_hummingboard2_usdhc2_200mhz: hummingboard2-usdhc2-200mhz {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
- >;
- };
+ pinctrl_hummingboard2_usdhc2_200mhz: hummingboard2-usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
+ >;
+ };
- pinctrl_hummingboard2_vmmc: hummingboard2-vmmc {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
- >;
- };
+ pinctrl_hummingboard2_vmmc: hummingboard2-vmmcgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
+ >;
+ };
- pinctrl_hummingboard2_uart3: hummingboard2-uart3 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D25__UART3_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D24__UART3_RX_DATA 0x40013000
- >;
- };
+ pinctrl_hummingboard2_uart3: hummingboard2-uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D25__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D24__UART3_RX_DATA 0x40013000
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi
index 99b5e78458aa..c771f87b10df 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi
@@ -728,7 +728,7 @@
>;
};
- pinctrl_wdog1: wdog1rp {
+ pinctrl_wdog1: wdog1grp {
fsl,pins = <
MX6QDL_PAD_GPIO_9__WDOG1_B 0x1b0b0
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi
index 60aa1e947f62..8cefda70db63 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi
@@ -106,6 +106,20 @@
vin-supply = <&reg_mba6_3p3v>;
};
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x14000000>;
+ alloc-ranges = <0x10000000 0x20000000>;
+ linux,cma-default;
+ };
+ };
+
sound {
compatible = "fsl,imx-audio-tlv320aic32x4";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi
index a30cf0d06206..8ee65f9858c0 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi
@@ -276,205 +276,203 @@
pinctrl-0 = <&pinctrl_j10>;
pinctrl-1 = <&pinctrl_j28>;
- imx6dl-nit6xlite {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- /* Phy reset */
- MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x0f0b0
- MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b0
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ /* Phy reset */
+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x0f0b0
+ MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b0
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
- pinctrl_gpio_keys: gpio-keysgrp {
- fsl,pins = <
- /* Home Button: J14 pin 5 */
- MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
- /* Back Button: J14 pin 7 */
- MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
- >;
- };
+ pinctrl_gpio_keys: gpio-keysgrp {
+ fsl,pins = <
+ /* Home Button: J14 pin 5 */
+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
+ /* Back Button: J14 pin 7 */
+ MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- /* Touch IRQ: J7 pin 4 */
- MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
- /* tcs2004 IRQ */
- MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x1b0b0
- /* tsc2004 reset */
- MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x0b0b0
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ /* Touch IRQ: J7 pin 4 */
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
+ /* tcs2004 IRQ */
+ MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x1b0b0
+ /* tsc2004 reset */
+ MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x0b0b0
+ >;
+ };
- pinctrl_j10: j10grp {
- fsl,pins = <
- /* Broadcom WiFi module pins */
- MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
- MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
- MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x0b0b0
- MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x1b0b0
- MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x000b0
- >;
- };
+ pinctrl_j10: j10grp {
+ fsl,pins = <
+ /* Broadcom WiFi module pins */
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
+ MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x0b0b0
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x1b0b0
+ MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x000b0
+ >;
+ };
- pinctrl_j28: j28grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
- >;
- };
+ pinctrl_j28: j28grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
+ >;
+ };
- pinctrl_leds: ledsgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x0b0b0
- MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x0b0b0
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x030b0
- MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x0b0b0
- MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x0b0b0
- >;
- };
+ pinctrl_leds: ledsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x0b0b0
+ MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x0b0b0
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x030b0
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x0b0b0
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x0b0b0
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm3: pwm3grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm4: pwm4grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+ >;
+ };
- pinctrl_wlan_vmmc: wlan-vmmcgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x030b0
- >;
- };
+ pinctrl_wlan_vmmc: wlan-vmmcgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x030b0
+ >;
+ };
- pinctrl_rtc: rtcgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b0b0
- >;
- };
+ pinctrl_rtc: rtcgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b0b0
+ >;
+ };
- pinctrl_sgtl5000: sgtl5000grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000b0
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0
- >;
- };
+ pinctrl_sgtl5000: sgtl5000grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000b0
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
- MX6QDL_PAD_EIM_D31__UART3_RTS_B 0x1b0b1
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D31__UART3_RTS_B 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- /* power enable, high active */
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
index 33174febf410..43d474bbf55d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
@@ -411,287 +411,285 @@
};
&iomuxc {
- imx6q-nitrogen6-max {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
- >;
- };
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ >;
+ };
- pinctrl_can_xcvr: can-xcvrgrp {
- fsl,pins = <
- /* Flexcan XCVR enable */
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
- >;
- };
+ pinctrl_can_xcvr: can-xcvrgrp {
+ fsl,pins = <
+ /* Flexcan XCVR enable */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x10030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x10030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x10030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x10030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x10030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x10030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- /* Phy reset */
- MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x0f0b0
- MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b0
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x10030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x10030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x10030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x10030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x10030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x10030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ /* Phy reset */
+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x0f0b0
+ MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b0
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
- pinctrl_gpio_keys: gpio-keysgrp {
- fsl,pins = <
- /* Power Button */
- MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
- /* Menu Button */
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- /* Home Button */
- MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
- /* Back Button */
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- /* Volume Up Button */
- MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
- /* Volume Down Button */
- MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b0
- >;
- };
+ pinctrl_gpio_keys: gpio-keysgrp {
+ fsl,pins = <
+ /* Power Button */
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ /* Menu Button */
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
+ /* Home Button */
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
+ /* Back Button */
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ /* Volume Up Button */
+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
+ /* Volume Down Button */
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2mux: i2c2muxgrp {
- fsl,pins = <
- /* ov5642 camera i2c enable */
- MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x000b0
- /* ov5640_mipi camera i2c enable */
- MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x000b0
- >;
- };
+ pinctrl_i2c2mux: i2c2muxgrp {
+ fsl,pins = <
+ /* ov5642 camera i2c enable */
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x000b0
+ /* ov5640_mipi camera i2c enable */
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x000b0
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
+ >;
+ };
- pinctrl_i2c3mux: i2c3muxgrp {
- fsl,pins = <
- /* PCIe I2C enable */
- MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x000b0
- >;
- };
+ pinctrl_i2c3mux: i2c3muxgrp {
+ fsl,pins = <
+ /* PCIe I2C enable */
+ MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x000b0
+ >;
+ };
- pinctrl_j15: j15grp {
- fsl,pins = <
- MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
- MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
- MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
- MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
- MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
- MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
- MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
- MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
- MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
- MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
- MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
- MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
- MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
- MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
- MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
- MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
- MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
- MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
- MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
- MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
- MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
- MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
- MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
- MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
- MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
- MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
- MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
- MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
- >;
- };
+ pinctrl_j15: j15grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
- pinctrl_pcie: pciegrp {
- fsl,pins = <
- /* PCIe reset */
- MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x000b0
- >;
- };
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ /* PCIe reset */
+ MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x000b0
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm2: pwm2grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT2__PWM2_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT2__PWM2_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm3: pwm3grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm4: pwm4grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+ >;
+ };
- pinctrl_rv4162: rv4162grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x1b0b0
- >;
- };
+ pinctrl_rv4162: rv4162grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x1b0b0
+ >;
+ };
- pinctrl_sgtl5000: sgtl5000grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000b0
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0
- >;
- };
+ pinctrl_sgtl5000: sgtl5000grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000b0
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart5: uart5grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x130b1
- MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x030b1
- /* RS485 RX Enable: pull up */
- MX6QDL_PAD_NANDF_RB0__GPIO6_IO10 0x1b0b1
- /* RS485 DEN: pull down */
- MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x030b1
- /* RS485/!RS232 Select: pull down (rs232) */
- MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x030b1
- /* ON: pull down */
- MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x030b1
- >;
- };
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x130b1
+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x030b1
+ /* RS485 RX Enable: pull up */
+ MX6QDL_PAD_NANDF_RB0__GPIO6_IO10 0x1b0b1
+ /* RS485 DEN: pull down */
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x030b1
+ /* RS485/!RS232 Select: pull down (rs232) */
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x030b1
+ /* ON: pull down */
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x030b1
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x0b0b0
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x0b0b0
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- /* power enable, high active */
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_NANDF_CS1__SD3_VSELECT 0x100b0
- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_NANDF_CS1__SD3_VSELECT 0x100b0
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
+ };
- pinctrl_wlan_vmmc: wlan-vmmcgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x100b0
- MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x000b0
- MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x000b0
- MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x000b0
- >;
- };
+ pinctrl_wlan_vmmc: wlan-vmmcgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x100b0
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x000b0
+ MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x000b0
+ MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x000b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi
index 121177273dd0..8a0bfc387a59 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi
@@ -343,231 +343,229 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6q-nitrogen6x {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- /* SGTL5000 sys_mclk */
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
- MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* SGTL5000 sys_mclk */
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
- >;
- };
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ >;
+ };
- pinctrl_can_xcvr: can-xcvrgrp {
- fsl,pins = <
- /* Flexcan XCVR enable */
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
- >;
- };
+ pinctrl_can_xcvr: can-xcvrgrp {
+ fsl,pins = <
+ /* Flexcan XCVR enable */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x10030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x10030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x10030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x10030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x10030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x10030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- /* Phy reset */
- MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x000b0
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x10030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x10030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x10030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x10030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x10030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x10030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ /* Phy reset */
+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x000b0
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
- pinctrl_gpio_keys: gpio-keysgrp {
- fsl,pins = <
- /* Power Button */
- MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
- /* Menu Button */
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- /* Home Button */
- MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
- /* Back Button */
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- /* Volume Up Button */
- MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
- /* Volume Down Button */
- MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
- >;
- };
+ pinctrl_gpio_keys: gpio-keysgrp {
+ fsl,pins = <
+ /* Power Button */
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ /* Menu Button */
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
+ /* Home Button */
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
+ /* Back Button */
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ /* Volume Up Button */
+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
+ /* Volume Down Button */
+ MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_j15: j15grp {
- fsl,pins = <
- MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
- MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
- MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
- MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
- MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
- MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
- MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
- MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
- MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
- MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
- MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
- MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
- MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
- MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
- MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
- MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
- MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
- MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
- MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
- MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
- MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
- MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
- MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
- MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
- MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
- MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
- MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
- MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
- >;
- };
+ pinctrl_j15: j15grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm3: pwm3grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm4: pwm4grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x030b0
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x030b0
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- /* power enable, high active */
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17071
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10071
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17071
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17071
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17071
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17071
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17071
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10071
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17071
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17071
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17071
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17071
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */
+ >;
+ };
- pinctrl_wlan_vmmc: wlan-vmmcgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x100b0
- MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x000b0
- MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x000b0
- MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x000b0
- >;
- };
+ pinctrl_wlan_vmmc: wlan-vmmcgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x100b0
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x000b0
+ MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x000b0
+ MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x000b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-wlbt-05.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-wlbt-05.dtsi
index 84f884d6e55b..08b2dd06580a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-wlbt-05.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-wlbt-05.dtsi
@@ -54,7 +54,7 @@
};
&iomuxc {
- pinctrl_uart3_bt: uart3grp-bt {
+ pinctrl_uart3_bt: uart3-btgrp {
fsl,pins = <
MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
@@ -66,7 +66,7 @@
>;
};
- pinctrl_usdhc3_wl: usdhc3grp-wl {
+ pinctrl_usdhc3_wl: usdhc3-wlgrp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pfla02.dtsi
index c0c47adc5866..aa9a442852f4 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pfla02.dtsi
@@ -227,170 +227,168 @@
};
&iomuxc {
- imx6q-phytec-pfla02 {
- pinctrl_ecspi3: ecspi3grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
- MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
- MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
- MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* CS0 */
- >;
- };
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+ MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* CS0 */
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
- MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 /* Reset GPIO */
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 /* Reset GPIO */
+ >;
+ };
- pinctrl_flexcan1: flexcan1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
- >;
- };
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ >;
+ };
- pinctrl_gpmi_nand: gpminandgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- >;
- };
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_leds: ledsgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* Green LED */
- MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000 /* Red LED */
- >;
- };
+ pinctrl_leds: ledsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* Green LED */
+ MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000 /* Red LED */
+ >;
+ };
- pinctrl_pcie: pciegrp {
- fsl,pins = <MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000>;
- };
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000>;
+ };
- pinctrl_pmic: pmicgrp {
- fsl,pins = <MX6QDL_PAD_SD4_DAT1__GPIO2_IO09 0x80000000>; /* PMIC interrupt */
- };
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <MX6QDL_PAD_SD4_DAT1__GPIO2_IO09 0x80000000>; /* PMIC interrupt */
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D31__UART3_RTS_B 0x1b0b1
- MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D31__UART3_RTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1
+ >;
+ };
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbh1_vbus: usbh1vbusgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0
- >;
- };
+ pinctrl_usbh1_vbus: usbh1vbusgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc3_cdwp: usdhc3cdwp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
- >;
- };
+ pinctrl_usdhc3_cdwp: usdhc3cdwpgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x130b0
- MX6QDL_PAD_DISP0_DAT17__AUD5_TXD 0x110b0
- MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x130b0
- MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x130b0
+ MX6QDL_PAD_DISP0_DAT17__AUD5_TXD 0x110b0
+ MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x130b0
+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-rex.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-rex.dtsi
index eba698d04243..64ded5e5559c 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-rex.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-rex.dtsi
@@ -154,159 +154,157 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6qdl-rex {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- /* SGTL5000 sys_mclk */
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* SGTL5000 sys_mclk */
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
- pinctrl_ecspi2: ecspi2grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
- MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
- MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
- /* CS */
- MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x000b1
- >;
- };
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+ /* CS */
+ MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x000b1
+ >;
+ };
- pinctrl_ecspi3: ecspi3grp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO 0x100b1
- MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI 0x100b1
- MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK 0x100b1
- /* CS */
- MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x000b1
- >;
- };
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK 0x100b1
+ /* CS */
+ MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x000b1
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- /* Phy reset */
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x000b0
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ /* Phy reset */
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x000b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
- MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_led: ledgrp {
- fsl,pins = <
- /* user led */
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
- >;
- };
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ /* user led */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
+ >;
+ };
- pinctrl_pca9535: pca9535grp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x17059
- >;
- };
+ pinctrl_pca9535: pca9535grp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x17059
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- /* power enable, high active */
- MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x10b0
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x10b0
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0
- /* power enable, high active */
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x10b0
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x10b0
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- /* CD */
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- /* WP */
- MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1f0b0
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ /* CD */
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ /* WP */
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1f0b0
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- /* CD */
- MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
- /* WP */
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1f0b0
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ /* CD */
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
+ /* WP */
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1f0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
index 35b6bec7a3fa..a381cb224c1e 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
@@ -472,312 +472,310 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6qdl-sabreauto {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
- MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x80000000
- MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
+ MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x80000000
+ MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ >;
+ };
- pinctrl_ecspi1_cs: ecspi1cs {
- fsl,pins = <
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
- >;
- };
+ pinctrl_ecspi1_cs: ecspi1csgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
+ >;
+ };
- pinctrl_egalax_int: egalax-intgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0xb0b1
- >;
- };
+ pinctrl_egalax_int: egalax-intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0xb0b1
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
+ };
- pinctrl_esai: esaigrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
- MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030
- MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
- MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3 0x1b030
- MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030
- MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030
- MX6QDL_PAD_GPIO_17__ESAI_TX0 0x1b030
- MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030
- MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK 0x1b030
- MX6QDL_PAD_GPIO_9__ESAI_RX_FS 0x1b030
- >;
- };
+ pinctrl_esai: esaigrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
+ MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030
+ MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
+ MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3 0x1b030
+ MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030
+ MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030
+ MX6QDL_PAD_GPIO_17__ESAI_TX0 0x1b030
+ MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030
+ MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK 0x1b030
+ MX6QDL_PAD_GPIO_9__ESAI_RX_FS 0x1b030
+ >;
+ };
- pinctrl_flexcan1: flexcan1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x17059
- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x17059
- >;
- };
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x17059
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x17059
+ >;
+ };
- pinctrl_flexcan2: flexcan2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x17059
- MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x17059
- >;
- };
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x17059
+ MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x17059
+ >;
+ };
- pinctrl_gpio_keys: gpiokeysgrp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0
- MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x1b0b0
- MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0
- MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0
- MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 0x1b0b0
- >;
- };
+ pinctrl_gpio_keys: gpiokeysgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0
+ MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x1b0b0
+ MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0
+ MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0
+ MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 0x1b0b0
+ >;
+ };
- pinctrl_gpio_leds: gpioledsgrp {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000
- >;
- };
+ pinctrl_gpio_leds: gpioledsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000
+ >;
+ };
- pinctrl_gpmi_nand: gpminandgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
- MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
- MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
- MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
- MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
- MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
- MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
- MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
- MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
- MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
- MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
- MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
- MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
- MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
- MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
- MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
- MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
- >;
- };
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
+ >;
+ };
- pinctrl_hdmi_cec: hdmicecgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0
- >;
- };
+ pinctrl_hdmi_cec: hdmicecgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3mux: i2c3muxgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x0b0b1
- >;
- };
+ pinctrl_i2c3mux: i2c3muxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x0b0b1
+ >;
+ };
- pinctrl_ipu1_csi0: ipu1csi0grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
- MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
- MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
- MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
- MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
- MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
- MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
- MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
- MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x1b0b0
- MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
- MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
- >;
- };
+ pinctrl_ipu1_csi0: ipu1csi0grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
+ MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x1b0b0
+ MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
+ MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
+ >;
+ };
- pinctrl_max7310: max7310grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x1b0b0
- >;
- };
+ pinctrl_max7310: max7310grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x1b0b0
+ >;
+ };
- pinctrl_mma8451_int: mma8451intgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0xb0b1
- >;
- };
+ pinctrl_mma8451_int: mma8451intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0xb0b1
+ >;
+ };
- pinctrl_pwm3: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm3: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
+ >;
+ };
- pinctrl_gpt_input_capture0: gptinputcapture0grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT0__GPT_CAPTURE1 0x1b0b0
- >;
- };
+ pinctrl_gpt_input_capture0: gptinputcapture0grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT0__GPT_CAPTURE1 0x1b0b0
+ >;
+ };
- pinctrl_gpt_input_capture1: gptinputcapture1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT1__GPT_CAPTURE2 0x1b0b0
- >;
- };
+ pinctrl_gpt_input_capture1: gptinputcapture1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT1__GPT_CAPTURE2 0x1b0b0
+ >;
+ };
- pinctrl_spdif: spdifgrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
- >;
- };
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
+ >;
+ };
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ >;
+ };
- pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
- >;
- };
+ pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
+ >;
+ };
- pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
- >;
- };
+ pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
+ >;
+ };
- pinctrl_weim_cs0: weimcs0grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0xb0b1
- >;
- };
+ pinctrl_weim_cs0: weimcs0grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0xb0b1
+ >;
+ };
- pinctrl_weim_nor: weimnorgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_OE__EIM_OE_B 0xb0b1
- MX6QDL_PAD_EIM_RW__EIM_RW 0xb0b1
- MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
- MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
- MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
- MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
- MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
- MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
- MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
- MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
- MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
- MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
- MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
- MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
- MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
- MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
- MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
- MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
- MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
- MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
- MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
- MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
- MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
- MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
- MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
- MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
- MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
- MX6QDL_PAD_EIM_DA15__EIM_AD15 0xb0b1
- MX6QDL_PAD_EIM_DA14__EIM_AD14 0xb0b1
- MX6QDL_PAD_EIM_DA13__EIM_AD13 0xb0b1
- MX6QDL_PAD_EIM_DA12__EIM_AD12 0xb0b1
- MX6QDL_PAD_EIM_DA11__EIM_AD11 0xb0b1
- MX6QDL_PAD_EIM_DA10__EIM_AD10 0xb0b1
- MX6QDL_PAD_EIM_DA9__EIM_AD09 0xb0b1
- MX6QDL_PAD_EIM_DA8__EIM_AD08 0xb0b1
- MX6QDL_PAD_EIM_DA7__EIM_AD07 0xb0b1
- MX6QDL_PAD_EIM_DA6__EIM_AD06 0xb0b1
- MX6QDL_PAD_EIM_DA5__EIM_AD05 0xb0b1
- MX6QDL_PAD_EIM_DA4__EIM_AD04 0xb0b1
- MX6QDL_PAD_EIM_DA3__EIM_AD03 0xb0b1
- MX6QDL_PAD_EIM_DA2__EIM_AD02 0xb0b1
- MX6QDL_PAD_EIM_DA1__EIM_AD01 0xb0b1
- MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0b1
- >;
- };
+ pinctrl_weim_nor: weimnorgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_OE__EIM_OE_B 0xb0b1
+ MX6QDL_PAD_EIM_RW__EIM_RW 0xb0b1
+ MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
+ MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
+ MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
+ MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
+ MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
+ MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
+ MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
+ MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
+ MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
+ MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
+ MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
+ MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
+ MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
+ MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
+ MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
+ MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
+ MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
+ MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
+ MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
+ MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
+ MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
+ MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
+ MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
+ MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
+ MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
+ MX6QDL_PAD_EIM_DA15__EIM_AD15 0xb0b1
+ MX6QDL_PAD_EIM_DA14__EIM_AD14 0xb0b1
+ MX6QDL_PAD_EIM_DA13__EIM_AD13 0xb0b1
+ MX6QDL_PAD_EIM_DA12__EIM_AD12 0xb0b1
+ MX6QDL_PAD_EIM_DA11__EIM_AD11 0xb0b1
+ MX6QDL_PAD_EIM_DA10__EIM_AD10 0xb0b1
+ MX6QDL_PAD_EIM_DA9__EIM_AD09 0xb0b1
+ MX6QDL_PAD_EIM_DA8__EIM_AD08 0xb0b1
+ MX6QDL_PAD_EIM_DA7__EIM_AD07 0xb0b1
+ MX6QDL_PAD_EIM_DA6__EIM_AD06 0xb0b1
+ MX6QDL_PAD_EIM_DA5__EIM_AD05 0xb0b1
+ MX6QDL_PAD_EIM_DA4__EIM_AD04 0xb0b1
+ MX6QDL_PAD_EIM_DA3__EIM_AD03 0xb0b1
+ MX6QDL_PAD_EIM_DA2__EIM_AD02 0xb0b1
+ MX6QDL_PAD_EIM_DA1__EIM_AD01 0xb0b1
+ MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0b1
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabrelite.dtsi
index 9c502bf77d0b..bdef7e642d3c 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabrelite.dtsi
@@ -389,243 +389,241 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6q-sabrelite {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- /* SGTL5000 sys_mclk */
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* SGTL5000 sys_mclk */
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0
- MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0
- MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0
- MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0
+ MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0
+ MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0
+ MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0
+ >;
+ };
- pinctrl_can1: can1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
- >;
- };
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ >;
+ };
- pinctrl_can_xcvr: can-xcvrgrp {
- fsl,pins = <
- /* Flexcan XCVR enable */
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
- >;
- };
+ pinctrl_can_xcvr: can-xcvrgrp {
+ fsl,pins = <
+ /* Flexcan XCVR enable */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x10030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x10030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x10030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x10030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x10030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x10030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- /* Phy reset */
- MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x000b0
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x10030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x10030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x10030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x10030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x10030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x10030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ /* Phy reset */
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x000b0
+ >;
+ };
- pinctrl_gpio_keys: gpio-keysgrp {
- fsl,pins = <
- /* Power Button */
- MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
- /* Menu Button */
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- /* Home Button */
- MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
- /* Back Button */
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- /* Volume Up Button */
- MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
- /* Volume Down Button */
- MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
- >;
- };
+ pinctrl_gpio_keys: gpio-keysgrp {
+ fsl,pins = <
+ /* Power Button */
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ /* Menu Button */
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
+ /* Home Button */
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0
+ /* Back Button */
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ /* Volume Up Button */
+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0
+ /* Volume Down Button */
+ MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_ipu1_csi0: ipu1csi0grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
- MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
- MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
- MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
- MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
- MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
- MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
- MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
- MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x1b0b0
- MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
- MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
- MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x1b0b0
- >;
- };
+ pinctrl_ipu1_csi0: ipu1csi0grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
+ MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x1b0b0
+ MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
+ MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
+ MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x1b0b0
+ >;
+ };
- pinctrl_j15: j15grp {
- fsl,pins = <
- MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
- MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
- MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
- MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
- MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
- MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
- MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
- MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
- MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
- MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
- MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
- MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
- MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
- MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
- MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
- MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
- MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
- MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
- MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
- MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
- MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
- MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
- MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
- MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
- MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
- MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
- MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
- MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
- >;
- };
+ pinctrl_j15: j15grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
- pinctrl_ov5640: ov5640grp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000b0
- MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x0b0b0
- >;
- };
+ pinctrl_ov5640: ov5640grp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000b0
+ MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x0b0b0
+ >;
+ };
- pinctrl_ov5642: ov5642grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x1b0b0
- MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
- MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x130b0
- MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x000b0
- >;
- };
+ pinctrl_ov5642: ov5642grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x1b0b0
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x130b0
+ MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x000b0
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm3: pwm3grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1
+ >;
+ };
- pinctrl_pwm4: pwm4grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbh1: usbh1grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x030b0
- >;
- };
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x030b0
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
- /* power enable, high active */
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */
- MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* WP */
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* WP */
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi
index 8f4f5fba68cc..dc8298f6db34 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi
@@ -480,251 +480,247 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6qdl-sabresd {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
- MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
- MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
- MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
- MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x1b0b0
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b0b0
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b0b0
+ >;
+ };
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
- MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
- MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
- MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x1b0b0
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x1b0b0
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
- pinctrl_gpio_keys: gpio_keysgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
- MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0
- >;
- };
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
+ MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0
+ >;
+ };
- pinctrl_hdmi_cec: hdmicecgrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
- >;
- };
+ pinctrl_hdmi_cec: hdmicecgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
- pinctrl_hp: hpgrp {
- fsl,pins = <
- MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x1b0b0
- MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
- >;
- };
+ pinctrl_hp: hpgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x1b0b0
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
- MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
- pinctrl_i2c1_mma8451_int: i2c1mma8451intgrp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0xb0b1
- >;
- };
+ pinctrl_i2c1_mma8451_int: i2c1mma8451intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0xb0b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2_egalax_int: i2c2egalaxintgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x1b0b0
- >;
- };
+ pinctrl_i2c2_egalax_int: i2c2egalaxintgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x1b0b0
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3_isl29023_int: i2c3isl29023intgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0xb0b1
- >;
- };
+ pinctrl_i2c3_isl29023_int: i2c3isl29023intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0xb0b1
+ >;
+ };
- pinctrl_i2c3_mag3110_int: i2c3mag3110intgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D16__GPIO3_IO16 0xb0b1
- >;
- };
+ pinctrl_i2c3_mag3110_int: i2c3mag3110intgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D16__GPIO3_IO16 0xb0b1
+ >;
+ };
- pinctrl_ipu1_csi0: ipu1csi0grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
- MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
- MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
- MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
- MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
- MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
- MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
- MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
- MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x1b0b0
- MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
- MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
- >;
- };
+ pinctrl_ipu1_csi0: ipu1csi0grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
+ MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x1b0b0
+ MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
+ MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
+ >;
+ };
- pinctrl_ov5640: ov5640grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT2__GPIO1_IO19 0x1b0b0
- MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x1b0b0
- >;
- };
+ pinctrl_ov5640: ov5640grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT2__GPIO1_IO19 0x1b0b0
+ MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x1b0b0
+ >;
+ };
- pinctrl_ov5642: ov5642grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x1b0b0
- MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b0b0
- >;
- };
+ pinctrl_ov5642: ov5642grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x1b0b0
+ MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b0b0
+ >;
+ };
- pinctrl_pcie: pciegrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
- >;
- };
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
+ >;
+ };
- pinctrl_pcie_reg: pciereggrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0
- >;
- };
+ pinctrl_pcie_reg: pciereggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0
+ >;
+ };
- pinctrl_pwm1: pwm1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
- >;
- };
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+ >;
+ };
- pinctrl_sensors_reg: sensorsreggrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b0
- >;
- };
+ pinctrl_sensors_reg: sensorsreggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b0
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
- MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
- MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
- MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
+ MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
+ MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
+ MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
- MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
- MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
- MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
+ };
- pinctrl_wdog: wdoggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__WDOG2_B 0x1b0b0
- >;
- };
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__WDOG2_B 0x1b0b0
+ >;
};
- gpio_leds {
- pinctrl_gpio_leds: gpioledsgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
- >;
- };
+ pinctrl_gpio_leds: gpioledsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-solidsense.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-solidsense.dtsi
index 234827e554d0..60e446ba8f52 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-solidsense.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-solidsense.dtsi
@@ -93,49 +93,47 @@
&iomuxc {
pinctrl-0 = <&pinctrl_hog>, <&pinctrl_solidsense_hog>;
- solidsense {
- pinctrl_solidsense_hog: solidsense-hog {
- fsl,pins = <
- /* Nordic RESET_N */
- MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x400130b1
- /* Nordic Chip 1 SWDIO - GPIO 125 */
- MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29 0x400130b1
- /* Nordic Chip 1 SWDCLK - GPIO 59 */
- /* already claimed in the HB2 hogs */
- /* MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x400130b1 */
- /* Nordic Chip 2 SWDIO - GPIO 81 */
- MX6QDL_PAD_EIM_D17__GPIO3_IO17 0x400130b1
- /* Nordic Chip 2 SWCLK - GPIO 82 */
- MX6QDL_PAD_EIM_D18__GPIO3_IO18 0x400130b1
- >;
- };
+ pinctrl_solidsense_hog: solidsense-hoggrp {
+ fsl,pins = <
+ /* Nordic RESET_N */
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x400130b1
+ /* Nordic Chip 1 SWDIO - GPIO 125 */
+ MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29 0x400130b1
+ /* Nordic Chip 1 SWDCLK - GPIO 59 */
+ /* already claimed in the HB2 hogs */
+ /* MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x400130b1 */
+ /* Nordic Chip 2 SWDIO - GPIO 81 */
+ MX6QDL_PAD_EIM_D17__GPIO3_IO17 0x400130b1
+ /* Nordic Chip 2 SWCLK - GPIO 82 */
+ MX6QDL_PAD_EIM_D18__GPIO3_IO18 0x400130b1
+ >;
+ };
- pinctrl_solidsense_leds: solidsense-leds {
- fsl,pins = <
- /* Red LED 1 - GPIO 58 */
- MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x400130b1
- /* Green LED 1 - GPIO 55 */
- MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x400130b1
- /* Red LED 2 - GPIO 57 */
- MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x400130b1
- /* Green LED 2 - GPIO 56 */
- MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x400130b1
- >;
- };
+ pinctrl_solidsense_leds: solidsense-ledsgrp {
+ fsl,pins = <
+ /* Red LED 1 - GPIO 58 */
+ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x400130b1
+ /* Green LED 1 - GPIO 55 */
+ MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x400130b1
+ /* Red LED 2 - GPIO 57 */
+ MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x400130b1
+ /* Green LED 2 - GPIO 56 */
+ MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x400130b1
+ >;
+ };
- pinctrl_solidsense_uart2: solidsense-uart2 {
- fsl,pins = <
- MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_solidsense_uart2: solidsense-uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_solidsense_uart3: solidsense-uart3 {
- fsl,pins = <
- MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_solidsense_uart3: solidsense-uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-brcm.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-brcm.dtsi
index b55af61dfeca..e491f5c9d455 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-brcm.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-brcm.dtsi
@@ -70,55 +70,53 @@
};
&iomuxc {
- microsom {
- pinctrl_microsom_brcm_bt: microsom-brcm-bt {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070
- MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x40013070
- MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070
- >;
- };
+ pinctrl_microsom_brcm_bt: microsom-brcm-btgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070
+ MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x40013070
+ MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070
+ >;
+ };
- pinctrl_microsom_brcm_osc: microsom-brcm-osc {
- fsl,pins = <
- MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070
- >;
- };
+ pinctrl_microsom_brcm_osc: microsom-brcm-oscgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070
+ >;
+ };
- pinctrl_microsom_brcm_reg: microsom-brcm-reg {
- fsl,pins = <
- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070
- >;
- };
+ pinctrl_microsom_brcm_reg: microsom-brcm-reggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070
+ >;
+ };
- pinctrl_microsom_brcm_wifi: microsom-brcm-wifi {
- fsl,pins = <
- MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0
- MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x40013070
- MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070
- MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x40013070
- >;
- };
+ pinctrl_microsom_brcm_wifi: microsom-brcm-wifigrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0
+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x40013070
+ MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070
+ MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x40013070
+ >;
+ };
- pinctrl_microsom_uart4: microsom-uart4 {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
- MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
- >;
- };
+ pinctrl_microsom_uart4: microsom-uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
+ >;
+ };
- pinctrl_microsom_usdhc1: microsom-usdhc1 {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- >;
- };
+ pinctrl_microsom_usdhc1: microsom-usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-emmc.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-emmc.dtsi
index 5f3b8baab20f..ddca24414d26 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-emmc.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-emmc.dtsi
@@ -40,22 +40,20 @@
*/
&iomuxc {
- microsom {
- pinctrl_microsom_usdhc3: microsom-usdhc3 {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- MX6QDL_PAD_SD3_RST__SD3_RESET 0x17059
- >;
- };
+ pinctrl_microsom_usdhc3: microsom-usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ MX6QDL_PAD_SD3_RST__SD3_RESET 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-ti.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-ti.dtsi
index 352ac585ca6b..cd1e682f11ad 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-ti.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-ti.dtsi
@@ -76,56 +76,54 @@
};
&iomuxc {
- microsom {
- pinctrl_microsom_ti_bt: microsom-ti-bt {
- fsl,pins = <
- /* BT_EN_SOC */
- MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070
- >;
- };
+ pinctrl_microsom_ti_bt: microsom-ti-btgrp {
+ fsl,pins = <
+ /* BT_EN_SOC */
+ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070
+ >;
+ };
- pinctrl_microsom_ti_clk: microsom-ti-clk {
- fsl,pins = <
- /* EXT_32K */
- MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0
- /* WL_XTAL_PU (unrouted) */
- MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070
- >;
- };
+ pinctrl_microsom_ti_clk: microsom-ti-clkgrp {
+ fsl,pins = <
+ /* EXT_32K */
+ MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0
+ /* WL_XTAL_PU (unrouted) */
+ MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070
+ >;
+ };
- pinctrl_microsom_ti_wifi_en: microsom-ti-wifi-en {
- fsl,pins = <
- /* WLAN_EN_SOC */
- MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070
- >;
- };
+ pinctrl_microsom_ti_wifi_en: microsom-ti-wifi-engrp {
+ fsl,pins = <
+ /* WLAN_EN_SOC */
+ MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070
+ >;
+ };
- pinctrl_microsom_ti_wifi_irq: microsom-ti-wifi-irq {
- fsl,pins = <
- /* WLAN_IRQ */
- MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070
- >;
- };
+ pinctrl_microsom_ti_wifi_irq: microsom-ti-wifi-irqgrp {
+ fsl,pins = <
+ /* WLAN_IRQ */
+ MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070
+ >;
+ };
- pinctrl_microsom_uart4: microsom-uart4 {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
- MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
- >;
- };
+ pinctrl_microsom_uart4: microsom-uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
+ >;
+ };
- pinctrl_microsom_usdhc1: microsom-usdhc1 {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- >;
- };
+ pinctrl_microsom_usdhc1: microsom-usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som.dtsi
index ce543e325cd3..7af74b203e39 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som.dtsi
@@ -97,57 +97,55 @@
};
&iomuxc {
- microsom {
- pinctrl_microsom_enet_ar8035: microsom-enet-ar8035 {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b8b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- /* AR8035 reset */
- MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0
- /* AR8035 interrupt */
- MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b0
- /* GPIO16 -> AR8035 25MHz */
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x13030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1
- /* AR8035 pin strapping: IO voltage: pull up */
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- /* AR8035 pin strapping: PHYADDR#0: pull down */
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030
- /* AR8035 pin strapping: PHYADDR#1: pull down */
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030
- /* AR8035 pin strapping: MODE#1: pull up */
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- /* AR8035 pin strapping: MODE#3: pull up */
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- /* AR8035 pin strapping: MODE#0: pull down */
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x13030
+ pinctrl_microsom_enet_ar8035: microsom-enet-ar8035grp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b8b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ /* AR8035 reset */
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0
+ /* AR8035 interrupt */
+ MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b0
+ /* GPIO16 -> AR8035 25MHz */
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x13030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1
+ /* AR8035 pin strapping: IO voltage: pull up */
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ /* AR8035 pin strapping: PHYADDR#0: pull down */
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030
+ /* AR8035 pin strapping: PHYADDR#1: pull down */
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030
+ /* AR8035 pin strapping: MODE#1: pull up */
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ /* AR8035 pin strapping: MODE#3: pull up */
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ /* AR8035 pin strapping: MODE#0: pull down */
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x13030
- /*
- * As the RMII pins are also connected to RGMII
- * so that an AR8030 can be placed, set these
- * to high-z with the same pulls as above.
- * Use the GPIO settings to avoid changing the
- * input select registers.
- */
- MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x03000
- MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x03000
- MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x03000
- >;
- };
+ /*
+ * As the RMII pins are also connected to RGMII
+ * so that an AR8030 can be placed, set these
+ * to high-z with the same pulls as above.
+ * Use the GPIO settings to avoid changing the
+ * input select registers.
+ */
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x03000
+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x03000
+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x03000
+ >;
+ };
- pinctrl_microsom_uart1: microsom-uart1 {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_microsom_uart1: microsom-uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi
index e2db875b61c4..11c70431feec 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi
@@ -265,7 +265,7 @@
>;
};
- pinctrl_ecspi2: ecspi2 {
+ pinctrl_ecspi2: ecspi2grp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK 0x100b1
MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI 0x100b1
@@ -280,7 +280,7 @@
>;
};
- pinctrl_enet: enet {
+ pinctrl_enet: enetgrp {
fsl,pins = <
MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi
index ded241a39906..77594546ef37 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi
@@ -51,7 +51,6 @@
pinctrl-0 = <&pinctrl_lcd1_pwr>;
enable-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;
power-supply = <&reg_3v3>;
- turn-on-delay-ms = <35>;
/*
* a poor man's way to create a 1:1 relationship between
* the PWM value and the actual duty cycle
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-mb7.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-mb7.dtsi
index 99ec7a838f8d..bae7313d729d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-mb7.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-mb7.dtsi
@@ -42,13 +42,11 @@
/ {
backlight0 {
pwms = <&pwm1 0 500000 PWM_POLARITY_INVERTED>;
- turn-on-delay-ms = <35>;
power-supply = <&reg_lcd1_pwr>;
};
backlight1 {
pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
- turn-on-delay-ms = <35>;
power-supply = <&reg_lcd1_pwr>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
index 5a194f4c0cb9..2fa37d1b16cc 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
@@ -70,9 +70,8 @@
#address-cells = <1>;
#size-cells = <0>;
- mclk: clock@0 {
+ mclk: clock {
compatible = "fixed-clock";
- reg = <0>;
#clock-cells = <0>;
clock-frequency = <26000000>;
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-udoo.dtsi
index 14272b42f9a1..2be7dc4a9781 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-udoo.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-udoo.dtsi
@@ -117,132 +117,130 @@
};
&iomuxc {
- imx6q-udoo {
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001f8b1
- MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001f8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001f8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001f8b1
+ >;
+ };
- pinctrl_panel: panelgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x70
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x70
- >;
- };
+ pinctrl_panel: panelgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x70
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x70
+ >;
+ };
- pinctrl_power_off: poweroffgrp {
- fsl,pins = <
- MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x30
- >;
- };
+ pinctrl_power_off: poweroffgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x30
+ >;
+ };
- pinctrl_touchscreenp7: touchscreenp7grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x70
- MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x1b0b0
- >;
- };
+ pinctrl_touchscreenp7: touchscreenp7grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x70
+ MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x1b0b0
+ >;
+ };
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart4: uart4grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbh: usbhgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
- MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
- >;
- };
+ pinctrl_usbh: usbhgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
+ MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
+ >;
+ };
- pinctrl_usbotg: usbotg {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- MX6QDL_PAD_EIM_D22__USB_OTG_PWR 0x17059
- MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x17059
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_EIM_D22__USB_OTG_PWR 0x17059
+ MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0
+ >;
+ };
- pinctrl_ac97_running: ac97running {
- fsl,pins = <
- MX6QDL_PAD_DI0_PIN2__AUD6_TXD 0x1b0b0
- MX6QDL_PAD_DI0_PIN3__AUD6_TXFS 0x1b0b0
- MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x13080
- MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x13080
- MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
- >;
- };
+ pinctrl_ac97_running: ac97runninggrp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_PIN2__AUD6_TXD 0x1b0b0
+ MX6QDL_PAD_DI0_PIN3__AUD6_TXFS 0x1b0b0
+ MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x13080
+ MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x13080
+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
+ >;
+ };
- pinctrl_ac97_warm_reset: ac97warmreset {
- fsl,pins = <
- MX6QDL_PAD_DI0_PIN2__AUD6_TXD 0x1b0b0
- MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b0
- MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x13080
- MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x13080
- MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
- >;
- };
+ pinctrl_ac97_warm_reset: ac97warmresetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_PIN2__AUD6_TXD 0x1b0b0
+ MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b0
+ MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x13080
+ MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x13080
+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
+ >;
+ };
- pinctrl_ac97_reset: ac97reset {
- fsl,pins = <
- MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b0
- MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b0
- MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x13080
- MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x13080
- MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
- >;
- };
+ pinctrl_ac97_reset: ac97resetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b0
+ MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b0
+ MX6QDL_PAD_DI0_PIN4__AUD6_RXD 0x13080
+ MX6QDL_PAD_DI0_PIN15__AUD6_TXC 0x13080
+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi
index d8283eade43e..7749074e438d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi
@@ -194,7 +194,7 @@
};
&iomuxc {
- pinctrl_audmux: audmux {
+ pinctrl_audmux: audmuxgrp {
fsl,pins = <
MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
@@ -205,7 +205,7 @@
>;
};
- pinctrl_bt: bt {
+ pinctrl_bt: btgrp {
fsl,pins = <
/* Bluetooth enable */
MX6QDL_PAD_SD3_DAT6__GPIO6_IO18 0x1b0b1
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi
index 59833e8d11d8..2bff5f92242a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi
@@ -529,11 +529,11 @@
};
&usbphy1 {
- fsl,tx-d-cal = <0x5>;
+ fsl,tx-d-cal = <106>;
};
&usbphy2 {
- fsl,tx-d-cal = <0x5>;
+ fsl,tx-d-cal = <106>;
};
&usdhc1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revb1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revb1.dtsi
index e781a45785ed..3a21ae942273 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revb1.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revb1.dtsi
@@ -9,22 +9,20 @@
&iomuxc {
pinctrl-0 = <&pinctrl_hog>;
- imx6qdl-wandboard {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
- MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
- MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x0f0b0 /* WL_REF_ON */
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x0f0b0 /* WL_RST_N */
- MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x000b0 /* WL_REG_ON */
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE */
- MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE */
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 /* RGMII_nRST */
- MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x80000000 /* BT_ON */
- MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x80000000 /* BT_WAKE */
- MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x80000000 /* BT_HOST_WAKE */
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
+ MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x0f0b0 /* WL_REF_ON */
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x0f0b0 /* WL_RST_N */
+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x000b0 /* WL_REG_ON */
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE */
+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE */
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 /* RGMII_nRST */
+ MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x80000000 /* BT_ON */
+ MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x80000000 /* BT_WAKE */
+ MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x80000000 /* BT_HOST_WAKE */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revc1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revc1.dtsi
index 3874e74703f0..cc707972f548 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revc1.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revc1.dtsi
@@ -7,24 +7,22 @@
#include "imx6qdl-wandboard.dtsi"
&iomuxc {
- pinctrl-0 = <&pinctrl_hog>;
+ pinctrl-0 = <&pinctrl_hog_c1>;
- imx6qdl-wandboard {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
- MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
- MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x0f0b0 /* WIFI_ON (reset, active low) */
- MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x000b0 /* WL_REG_ON (unused) */
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE, input */
- MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x0f0b0 /* GPIO5_IO31 (Wifi Power Enable) */
- MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE (unused) */
- MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x80000000 /* BT_ON */
- MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x80000000 /* BT_WAKE */
- MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x80000000 /* BT_HOST_WAKE */
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 /* RGMII_nRST */
- >;
- };
+ pinctrl_hog_c1: hogc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
+ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x0f0b0 /* WIFI_ON (reset, active low) */
+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x000b0 /* WL_REG_ON (unused) */
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE, input */
+ MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x0f0b0 /* GPIO5_IO31 (Wifi Power Enable) */
+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE (unused) */
+ MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x80000000 /* BT_ON */
+ MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x80000000 /* BT_WAKE */
+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x80000000 /* BT_HOST_WAKE */
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 /* RGMII_nRST */
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi
index 9b8c9c23ab54..8d44e758f1f3 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi
@@ -137,49 +137,47 @@
};
&iomuxc {
- pinctrl-0 = <&pinctrl_hog>;
-
- imx6qdl-wandboard {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* USDHC1 CD */
- MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1f0b1 /* RGMII PHY reset */
- >;
- };
+ pinctrl-0 = <&pinctrl_hog_d1>;
+
+ pinctrl_hog_d1: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* USDHC1 CD */
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1f0b1 /* RGMII PHY reset */
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- >;
- };
+ enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_spdif: spdifgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_19__SPDIF_OUT 0x1b0b0
- >;
- };
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_19__SPDIF_OUT 0x1b0b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
index 7130b9c3b3aa..26489eccd5fb 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi
@@ -157,146 +157,143 @@
&iomuxc {
pinctrl-names = "default";
- imx6qdl-wandboard {
-
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c1_gpio: i2c1gpiogrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x4001b8b0
- MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x4001b8b0
- >;
- };
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x4001b8b0
+ MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x4001b8b0
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2_gpio: i2c2gpiogrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b8b0
- MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b8b0
- >;
- };
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b8b0
+ MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b8b0
+ >;
+ };
- pinctrl_mclk: mclkgrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
- >;
- };
+ pinctrl_mclk: mclkgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ >;
+ };
- pinctrl_ov5645: ov5645grp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x000b0
- MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
- MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0
- >;
- };
+ pinctrl_ov5645: ov5645grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x000b0
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0
+ >;
+ };
- pinctrl_spdif: spdifgrp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
- >;
- };
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
- MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
- MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
- >;
- };
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
+ >;
+ };
- pinctrl_usbotg: usbotggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
- >;
- };
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
- pinctrl_usbotgvbus: usbotgvbusgrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x130b0
- >;
- };
+ pinctrl_usbotgvbus: usbotgvbusgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x130b0
+ >;
+ };
- pinctrl_usdhc1: usdhc1grp {
- fsl,pins = <
- MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
- MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
- MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts
index ae00d538a4df..fbe260c9872e 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts
@@ -548,7 +548,7 @@
>;
};
- pinctrl_wifi_npd: wifinpd {
+ pinctrl_wifi_npd: wifinpdgrp {
fsl,pins = <
/* WL_REG_ON */
MX6QDL_PAD_NANDF_RB0__GPIO6_IO10 0x13069
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qp-sabreauto.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-sabreauto.dts
index 2bb3bfb18ec3..c5b220aeaefd 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qp-sabreauto.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6qp-sabreauto.dts
@@ -22,27 +22,25 @@
};
&iomuxc {
- imx6qdl-sabreauto {
- pinctrl_enet: enetgrp {
- fsl,pins = <
- MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
- MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b018
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b018
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b018
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b018
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b018
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b018
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b018
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b018
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b018
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b018
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b018
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b018
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
- MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
- >;
- };
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b018
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b018
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b018
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b018
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b018
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b018
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b018
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b018
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b018
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b018
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b018
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b018
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qp-sabresd.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-sabresd.dts
index f69eec18d865..792697bd4551 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qp-sabresd.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6qp-sabresd.dts
@@ -17,36 +17,34 @@
};
&iomuxc {
- imx6qdl-sabresd {
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10071
- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
- MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
- MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
- MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
- >;
- };
-
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10071
- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10071
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
+ MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
+ MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
+ MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10071
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6s-dhcom-drc02.dts b/arch/arm/boot/dts/nxp/imx/imx6s-dhcom-drc02.dts
index 4077b607c29e..e42c274a9014 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6s-dhcom-drc02.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6s-dhcom-drc02.dts
@@ -3,7 +3,7 @@
* Copyright (C) 2021 DH electronics GmbH
*
* DHCOM iMX6 variant:
- * DHCM-iMX6S-C0800-R102-F0409-E-CAN2-RTC-I-01D2
+ * DHCM-iMX6S-C080-R102-F0409-E-CAN2-RTC-I-01D2
* DHCOM PCB number: 493-400 or newer
* DRC02 PCB number: 568-100 or newer
*/
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts
index 7c899291ab0d..55cdfa7ea206 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts
@@ -287,271 +287,269 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
- imx6sl-evk {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6SL_PAD_KEY_ROW7__GPIO4_IO07 0x17059
- MX6SL_PAD_KEY_COL7__GPIO4_IO06 0x17059
- MX6SL_PAD_SD2_DAT7__GPIO5_IO00 0x17059
- MX6SL_PAD_SD2_DAT6__GPIO4_IO29 0x17059
- MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
- MX6SL_PAD_KEY_COL4__GPIO4_IO00 0x80000000
- MX6SL_PAD_KEY_COL5__GPIO4_IO02 0x80000000
- MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
- >;
- };
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6SL_PAD_KEY_ROW7__GPIO4_IO07 0x17059
+ MX6SL_PAD_KEY_COL7__GPIO4_IO06 0x17059
+ MX6SL_PAD_SD2_DAT7__GPIO5_IO00 0x17059
+ MX6SL_PAD_SD2_DAT6__GPIO4_IO29 0x17059
+ MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
+ MX6SL_PAD_KEY_COL4__GPIO4_IO00 0x80000000
+ MX6SL_PAD_KEY_COL5__GPIO4_IO02 0x80000000
+ MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+ >;
+ };
- pinctrl_audmux3: audmux3grp {
- fsl,pins = <
- MX6SL_PAD_AUD_RXD__AUD3_RXD 0x4130b0
- MX6SL_PAD_AUD_TXC__AUD3_TXC 0x4130b0
- MX6SL_PAD_AUD_TXD__AUD3_TXD 0x4110b0
- MX6SL_PAD_AUD_TXFS__AUD3_TXFS 0x4130b0
- >;
- };
+ pinctrl_audmux3: audmux3grp {
+ fsl,pins = <
+ MX6SL_PAD_AUD_RXD__AUD3_RXD 0x4130b0
+ MX6SL_PAD_AUD_TXC__AUD3_TXC 0x4130b0
+ MX6SL_PAD_AUD_TXD__AUD3_TXD 0x4110b0
+ MX6SL_PAD_AUD_TXFS__AUD3_TXFS 0x4130b0
+ >;
+ };
- pinctrl_ecspi1: ecspi1grp {
- fsl,pins = <
- MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
- MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
- MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
- MX6SL_PAD_ECSPI1_SS0__GPIO4_IO11 0x80000000
- >;
- };
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
+ MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
+ MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
+ MX6SL_PAD_ECSPI1_SS0__GPIO4_IO11 0x80000000
+ >;
+ };
- pinctrl_fec: fecgrp {
- fsl,pins = <
- MX6SL_PAD_FEC_MDC__FEC_MDC 0x1b0b0
- MX6SL_PAD_FEC_MDIO__FEC_MDIO 0x1b0b0
- MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV 0x1b0b0
- MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0 0x1b0b0
- MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1 0x1b0b0
- MX6SL_PAD_FEC_TX_EN__FEC_TX_EN 0x1b0b0
- MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0 0x1b0b0
- MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1 0x1b0b0
- MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8
- >;
- };
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX6SL_PAD_FEC_MDC__FEC_MDC 0x1b0b0
+ MX6SL_PAD_FEC_MDIO__FEC_MDIO 0x1b0b0
+ MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV 0x1b0b0
+ MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0 0x1b0b0
+ MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1 0x1b0b0
+ MX6SL_PAD_FEC_TX_EN__FEC_TX_EN 0x1b0b0
+ MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0 0x1b0b0
+ MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1 0x1b0b0
+ MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8
+ >;
+ };
- pinctrl_fec_sleep: fecgrp-sleep {
- fsl,pins = <
- MX6SL_PAD_FEC_MDC__GPIO4_IO23 0x3080
- MX6SL_PAD_FEC_CRS_DV__GPIO4_IO25 0x3080
- MX6SL_PAD_FEC_RXD0__GPIO4_IO17 0x3080
- MX6SL_PAD_FEC_RXD1__GPIO4_IO18 0x3080
- MX6SL_PAD_FEC_TX_EN__GPIO4_IO22 0x3080
- MX6SL_PAD_FEC_TXD0__GPIO4_IO24 0x3080
- MX6SL_PAD_FEC_TXD1__GPIO4_IO16 0x3080
- MX6SL_PAD_FEC_REF_CLK__GPIO4_IO26 0x3080
- >;
- };
+ pinctrl_fec_sleep: fec-sleep-grp {
+ fsl,pins = <
+ MX6SL_PAD_FEC_MDC__GPIO4_IO23 0x3080
+ MX6SL_PAD_FEC_CRS_DV__GPIO4_IO25 0x3080
+ MX6SL_PAD_FEC_RXD0__GPIO4_IO17 0x3080
+ MX6SL_PAD_FEC_RXD1__GPIO4_IO18 0x3080
+ MX6SL_PAD_FEC_TX_EN__GPIO4_IO22 0x3080
+ MX6SL_PAD_FEC_TXD0__GPIO4_IO24 0x3080
+ MX6SL_PAD_FEC_TXD1__GPIO4_IO16 0x3080
+ MX6SL_PAD_FEC_REF_CLK__GPIO4_IO26 0x3080
+ >;
+ };
- pinctrl_hp: hpgrp {
- fsl,pins = <
- MX6SL_PAD_FEC_RX_ER__GPIO4_IO19 0x1b0b0
- >;
- };
+ pinctrl_hp: hpgrp {
+ fsl,pins = <
+ MX6SL_PAD_FEC_RX_ER__GPIO4_IO19 0x1b0b0
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
- MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
+ MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x4001b8b1
- MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x4001b8b1
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x4001b8b1
+ MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x4001b8b1
+ >;
+ };
- pinctrl_kpp: kppgrp {
- fsl,pins = <
- MX6SL_PAD_KEY_ROW0__KEY_ROW0 0x1b010
- MX6SL_PAD_KEY_ROW1__KEY_ROW1 0x1b010
- MX6SL_PAD_KEY_ROW2__KEY_ROW2 0x1b0b0
- MX6SL_PAD_KEY_COL0__KEY_COL0 0x110b0
- MX6SL_PAD_KEY_COL1__KEY_COL1 0x110b0
- MX6SL_PAD_KEY_COL2__KEY_COL2 0x110b0
- >;
- };
+ pinctrl_kpp: kppgrp {
+ fsl,pins = <
+ MX6SL_PAD_KEY_ROW0__KEY_ROW0 0x1b010
+ MX6SL_PAD_KEY_ROW1__KEY_ROW1 0x1b010
+ MX6SL_PAD_KEY_ROW2__KEY_ROW2 0x1b0b0
+ MX6SL_PAD_KEY_COL0__KEY_COL0 0x110b0
+ MX6SL_PAD_KEY_COL1__KEY_COL1 0x110b0
+ MX6SL_PAD_KEY_COL2__KEY_COL2 0x110b0
+ >;
+ };
- pinctrl_lcd: lcdgrp {
- fsl,pins = <
- MX6SL_PAD_LCD_DAT0__LCD_DATA00 0x1b0b0
- MX6SL_PAD_LCD_DAT1__LCD_DATA01 0x1b0b0
- MX6SL_PAD_LCD_DAT2__LCD_DATA02 0x1b0b0
- MX6SL_PAD_LCD_DAT3__LCD_DATA03 0x1b0b0
- MX6SL_PAD_LCD_DAT4__LCD_DATA04 0x1b0b0
- MX6SL_PAD_LCD_DAT5__LCD_DATA05 0x1b0b0
- MX6SL_PAD_LCD_DAT6__LCD_DATA06 0x1b0b0
- MX6SL_PAD_LCD_DAT7__LCD_DATA07 0x1b0b0
- MX6SL_PAD_LCD_DAT8__LCD_DATA08 0x1b0b0
- MX6SL_PAD_LCD_DAT9__LCD_DATA09 0x1b0b0
- MX6SL_PAD_LCD_DAT10__LCD_DATA10 0x1b0b0
- MX6SL_PAD_LCD_DAT11__LCD_DATA11 0x1b0b0
- MX6SL_PAD_LCD_DAT12__LCD_DATA12 0x1b0b0
- MX6SL_PAD_LCD_DAT13__LCD_DATA13 0x1b0b0
- MX6SL_PAD_LCD_DAT14__LCD_DATA14 0x1b0b0
- MX6SL_PAD_LCD_DAT15__LCD_DATA15 0x1b0b0
- MX6SL_PAD_LCD_DAT16__LCD_DATA16 0x1b0b0
- MX6SL_PAD_LCD_DAT17__LCD_DATA17 0x1b0b0
- MX6SL_PAD_LCD_DAT18__LCD_DATA18 0x1b0b0
- MX6SL_PAD_LCD_DAT19__LCD_DATA19 0x1b0b0
- MX6SL_PAD_LCD_DAT20__LCD_DATA20 0x1b0b0
- MX6SL_PAD_LCD_DAT21__LCD_DATA21 0x1b0b0
- MX6SL_PAD_LCD_DAT22__LCD_DATA22 0x1b0b0
- MX6SL_PAD_LCD_DAT23__LCD_DATA23 0x1b0b0
- MX6SL_PAD_LCD_CLK__LCD_CLK 0x1b0b0
- MX6SL_PAD_LCD_ENABLE__LCD_ENABLE 0x1b0b0
- MX6SL_PAD_LCD_HSYNC__LCD_HSYNC 0x1b0b0
- MX6SL_PAD_LCD_VSYNC__LCD_VSYNC 0x1b0b0
- >;
- };
+ pinctrl_lcd: lcdgrp {
+ fsl,pins = <
+ MX6SL_PAD_LCD_DAT0__LCD_DATA00 0x1b0b0
+ MX6SL_PAD_LCD_DAT1__LCD_DATA01 0x1b0b0
+ MX6SL_PAD_LCD_DAT2__LCD_DATA02 0x1b0b0
+ MX6SL_PAD_LCD_DAT3__LCD_DATA03 0x1b0b0
+ MX6SL_PAD_LCD_DAT4__LCD_DATA04 0x1b0b0
+ MX6SL_PAD_LCD_DAT5__LCD_DATA05 0x1b0b0
+ MX6SL_PAD_LCD_DAT6__LCD_DATA06 0x1b0b0
+ MX6SL_PAD_LCD_DAT7__LCD_DATA07 0x1b0b0
+ MX6SL_PAD_LCD_DAT8__LCD_DATA08 0x1b0b0
+ MX6SL_PAD_LCD_DAT9__LCD_DATA09 0x1b0b0
+ MX6SL_PAD_LCD_DAT10__LCD_DATA10 0x1b0b0
+ MX6SL_PAD_LCD_DAT11__LCD_DATA11 0x1b0b0
+ MX6SL_PAD_LCD_DAT12__LCD_DATA12 0x1b0b0
+ MX6SL_PAD_LCD_DAT13__LCD_DATA13 0x1b0b0
+ MX6SL_PAD_LCD_DAT14__LCD_DATA14 0x1b0b0
+ MX6SL_PAD_LCD_DAT15__LCD_DATA15 0x1b0b0
+ MX6SL_PAD_LCD_DAT16__LCD_DATA16 0x1b0b0
+ MX6SL_PAD_LCD_DAT17__LCD_DATA17 0x1b0b0
+ MX6SL_PAD_LCD_DAT18__LCD_DATA18 0x1b0b0
+ MX6SL_PAD_LCD_DAT19__LCD_DATA19 0x1b0b0
+ MX6SL_PAD_LCD_DAT20__LCD_DATA20 0x1b0b0
+ MX6SL_PAD_LCD_DAT21__LCD_DATA21 0x1b0b0
+ MX6SL_PAD_LCD_DAT22__LCD_DATA22 0x1b0b0
+ MX6SL_PAD_LCD_DAT23__LCD_DATA23 0x1b0b0
+ MX6SL_PAD_LCD_CLK__LCD_CLK 0x1b0b0
+ MX6SL_PAD_LCD_ENABLE__LCD_ENABLE 0x1b0b0
+ MX6SL_PAD_LCD_HSYNC__LCD_HSYNC 0x1b0b0
+ MX6SL_PAD_LCD_VSYNC__LCD_VSYNC 0x1b0b0
+ >;
+ };
- pinctrl_led: ledgrp {
- fsl,pins = <
- MX6SL_PAD_HSIC_STROBE__GPIO3_IO20 0x17059
- >;
- };
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ MX6SL_PAD_HSIC_STROBE__GPIO3_IO20 0x17059
+ >;
+ };
- pinctrl_pwm1: pwmgrp {
- fsl,pins = <
- MX6SL_PAD_PWM1__PWM1_OUT 0x110b0
- >;
- };
+ pinctrl_pwm1: pwmgrp {
+ fsl,pins = <
+ MX6SL_PAD_PWM1__PWM1_OUT 0x110b0
+ >;
+ };
- pinctrl_reg_lcd_3v3: reglcd3v3grp {
- fsl,pins = <
- MX6SL_PAD_KEY_ROW5__GPIO4_IO03 0x17059
- >;
- };
+ pinctrl_reg_lcd_3v3: reglcd3v3grp {
+ fsl,pins = <
+ MX6SL_PAD_KEY_ROW5__GPIO4_IO03 0x17059
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
- MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
+ MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1
+ >;
+ };
- pinctrl_usbotg1: usbotg1grp {
- fsl,pins = <
- MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
- >;
- };
+ pinctrl_usbotg1: usbotg1grp {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
+ >;
+ };
- pinctrl_usdhc1: usdhc1grp {
- fsl,pins = <
- MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059
- MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059
- MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
- MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
- MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
- MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
- MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059
- MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059
- MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059
- MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059
- >;
- };
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059
+ MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059
+ MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059
+ MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059
+ >;
+ };
- pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9
- MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9
- MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9
- MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9
- MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9
- MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9
- MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9
- MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9
- MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9
- MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9
- >;
- };
+ pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9
+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9
+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9
+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9
+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9
+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9
+ MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9
+ MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9
+ MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9
+ MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9
+ >;
+ };
- pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9
- MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9
- MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
- MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
- MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
- MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
- MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9
- MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9
- MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9
- MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9
- >;
- };
+ pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9
+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9
+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
+ MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9
+ MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9
+ MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9
+ MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6SL_PAD_SD2_CMD__SD2_CMD 0x17059
- MX6SL_PAD_SD2_CLK__SD2_CLK 0x10059
- 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: usdhc2grp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x10059
+ 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-100mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9
- MX6SL_PAD_SD2_CLK__SD2_CLK 0x100b9
- 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_100mhz: usdhc2-100mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x100b9
+ 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-200mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9
- MX6SL_PAD_SD2_CLK__SD2_CLK 0x100f9
- 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_200mhz: usdhc2-200mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x100f9
+ 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_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059
- MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059
- MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
- MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059
- MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059
- MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9
- MX6SL_PAD_SD3_CLK__SD3_CLK 0x100b9
- 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_100mhz: usdhc3-100mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x100b9
+ 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-200mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9
- MX6SL_PAD_SD3_CLK__SD3_CLK 0x100f9
- 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_200mhz: usdhc3-200mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x100f9
+ 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
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts
index 03d6965f0149..56040da0bd25 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts
@@ -382,7 +382,7 @@
>;
};
- pinctrl_i2c1_sleep: i2c1grp-sleep {
+ pinctrl_i2c1_sleep: i2c1sleep-grp {
fsl,pins = <
MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x400108b1
MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x400108b1
@@ -396,7 +396,7 @@
>;
};
- pinctrl_i2c2_sleep: i2c2grp-sleep {
+ pinctrl_i2c2_sleep: i2c2sleep-grp {
fsl,pins = <
MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x400108b1
MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x400108b1
@@ -456,7 +456,7 @@
>;
};
- pinctrl_usdhc2_100mhz: usdhc2grp-100mhz {
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
fsl,pins = <
MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9
MX6SL_PAD_SD2_CLK__SD2_CLK 0x130b9
@@ -467,7 +467,7 @@
>;
};
- pinctrl_usdhc2_200mhz: usdhc2grp-200mhz {
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
fsl,pins = <
MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9
MX6SL_PAD_SD2_CLK__SD2_CLK 0x130f9
@@ -478,7 +478,7 @@
>;
};
- pinctrl_usdhc2_sleep: usdhc2grp-sleep {
+ pinctrl_usdhc2_sleep: usdhc2sleep-grp {
fsl,pins = <
MX6SL_PAD_SD2_CMD__GPIO5_IO04 0x100f9
MX6SL_PAD_SD2_CLK__GPIO5_IO05 0x100f9
@@ -500,7 +500,7 @@
>;
};
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
fsl,pins = <
MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9
MX6SL_PAD_SD3_CLK__SD3_CLK 0x170b9
@@ -511,7 +511,7 @@
>;
};
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
fsl,pins = <
MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9
MX6SL_PAD_SD3_CLK__SD3_CLK 0x170f9
@@ -522,7 +522,7 @@
>;
};
- pinctrl_usdhc3_sleep: usdhc3grp-sleep {
+ pinctrl_usdhc3_sleep: usdhc3sleep-grp {
fsl,pins = <
MX6SL_PAD_SD3_CMD__GPIO5_IO21 0x100c1
MX6SL_PAD_SD3_CLK__GPIO5_IO18 0x100c1
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine3.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine3.dts
index db5d8509935f..5ba6f15e9ed5 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine3.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine3.dts
@@ -111,7 +111,7 @@
>;
};
- pinctrl_i2c1_sleep: i2c1grp-sleep {
+ pinctrl_i2c1_sleep: i2c1sleep-grp {
fsl,pins = <
MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x400108b1
MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x400108b1
@@ -125,7 +125,7 @@
>;
};
- pinctrl_i2c2_sleep: i2c2grp-sleep {
+ pinctrl_i2c2_sleep: i2c2sleep-grp {
fsl,pins = <
MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x400108b1
MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x400108b1
@@ -190,7 +190,7 @@
>;
};
- pinctrl_usdhc2_100mhz: usdhc2grp-100mhz {
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
fsl,pins = <
MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9
MX6SL_PAD_SD2_CLK__SD2_CLK 0x130b9
@@ -201,7 +201,7 @@
>;
};
- pinctrl_usdhc2_200mhz: usdhc2grp-200mhz {
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
fsl,pins = <
MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9
MX6SL_PAD_SD2_CLK__SD2_CLK 0x130f9
@@ -212,7 +212,7 @@
>;
};
- pinctrl_usdhc2_sleep: usdhc2grp-sleep {
+ pinctrl_usdhc2_sleep: usdhc2sleep-grp {
fsl,pins = <
MX6SL_PAD_SD2_CMD__GPIO5_IO04 0x100f9
MX6SL_PAD_SD2_CLK__GPIO5_IO05 0x100f9
@@ -234,7 +234,7 @@
>;
};
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
fsl,pins = <
MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9
MX6SL_PAD_SD3_CLK__SD3_CLK 0x170b9
@@ -245,7 +245,7 @@
>;
};
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
fsl,pins = <
MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9
MX6SL_PAD_SD3_CLK__SD3_CLK 0x170f9
@@ -256,7 +256,7 @@
>;
};
- pinctrl_usdhc3_sleep: usdhc3grp-sleep {
+ pinctrl_usdhc3_sleep: usdhc3sleep-grp {
fsl,pins = <
MX6SL_PAD_SD3_CMD__GPIO5_IO21 0x100c1
MX6SL_PAD_SD3_CLK__GPIO5_IO18 0x100c1
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision5.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision5.dts
index 6bc342035e2b..a2534c422a52 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision5.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision5.dts
@@ -111,7 +111,7 @@
>;
};
- pinctrl_i2c1_sleep: i2c1grp-sleep {
+ pinctrl_i2c1_sleep: i2c1sleep-grp {
fsl,pins = <
MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x400108b1
MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x400108b1
@@ -125,7 +125,7 @@
>;
};
- pinctrl_i2c2_sleep: i2c2grp-sleep {
+ pinctrl_i2c2_sleep: i2c2sleep-grp {
fsl,pins = <
MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x400108b1
MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x400108b1
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts
index 2545c0fe47c8..a5d48c382314 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts
@@ -125,110 +125,108 @@
};
&iomuxc {
- imx6sl-warp {
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x41b0b1
- MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x41b0b1
- >;
- };
-
-
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX6SL_PAD_AUD_RXC__UART3_RX_DATA 0x41b0b1
- MX6SL_PAD_AUD_RXC__UART3_TX_DATA 0x41b0b1
- >;
- };
-
- pinctrl_uart5: uart5grp {
- fsl,pins = <
- MX6SL_PAD_ECSPI1_SCLK__UART5_RX_DATA 0x41b0b1
- MX6SL_PAD_ECSPI1_MOSI__UART5_TX_DATA 0x41b0b1
- MX6SL_PAD_ECSPI1_MISO__UART5_RTS_B 0x4130b1
- MX6SL_PAD_ECSPI1_SS0__UART5_CTS_B 0x4130b1
- >;
- };
-
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6SL_PAD_SD2_CMD__SD2_CMD 0x417059
- MX6SL_PAD_SD2_CLK__SD2_CLK 0x410059
- MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x417059
- MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x417059
- MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x417059
- MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x417059
- MX6SL_PAD_SD2_DAT4__SD2_DATA4 0x417059
- MX6SL_PAD_SD2_DAT5__SD2_DATA5 0x417059
- MX6SL_PAD_SD2_DAT6__SD2_DATA6 0x417059
- MX6SL_PAD_SD2_DAT7__SD2_DATA7 0x417059
- MX6SL_PAD_SD2_RST__SD2_RESET 0x417059
- >;
- };
-
- pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD2_CMD__SD2_CMD 0x4170b9
- MX6SL_PAD_SD2_CLK__SD2_CLK 0x4100b9
- MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x4170b9
- MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x4170b9
- MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x4170b9
- MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x4170b9
- MX6SL_PAD_SD2_DAT4__SD2_DATA4 0x4170b9
- MX6SL_PAD_SD2_DAT5__SD2_DATA5 0x4170b9
- MX6SL_PAD_SD2_DAT6__SD2_DATA6 0x4170b9
- MX6SL_PAD_SD2_DAT7__SD2_DATA7 0x4170b9
- MX6SL_PAD_SD2_RST__SD2_RESET 0x4170b9
- >;
- };
-
- pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD2_CMD__SD2_CMD 0x4170f9
- MX6SL_PAD_SD2_CLK__SD2_CLK 0x4100f9
- MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x4170f9
- MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x4170f9
- MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x4170f9
- MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x4170f9
- MX6SL_PAD_SD2_DAT4__SD2_DATA4 0x4170f9
- MX6SL_PAD_SD2_DAT5__SD2_DATA5 0x4170f9
- MX6SL_PAD_SD2_DAT6__SD2_DATA6 0x4170f9
- MX6SL_PAD_SD2_DAT7__SD2_DATA7 0x4170f9
- MX6SL_PAD_SD2_RST__SD2_RESET 0x4170f9
- >;
- };
-
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6SL_PAD_SD3_CMD__SD3_CMD 0x417059
- MX6SL_PAD_SD3_CLK__SD3_CLK 0x410059
- MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x417059
- MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x417059
- MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x417059
- MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x417059
- >;
- };
-
- pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD3_CMD__SD3_CMD 0x4170b9
- MX6SL_PAD_SD3_CLK__SD3_CLK 0x4100b9
- MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x4170b9
- MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x4170b9
- MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x4170b9
- MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x4170b9
- >;
- };
-
- pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp {
- fsl,pins = <
- MX6SL_PAD_SD3_CMD__SD3_CMD 0x4170f9
- MX6SL_PAD_SD3_CLK__SD3_CLK 0x4100f9
- MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x4170f9
- MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x4170f9
- MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x4170f9
- MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x4170f9
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x41b0b1
+ MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x41b0b1
+ >;
+ };
+
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6SL_PAD_AUD_RXC__UART3_RX_DATA 0x41b0b1
+ MX6SL_PAD_AUD_RXC__UART3_TX_DATA 0x41b0b1
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6SL_PAD_ECSPI1_SCLK__UART5_RX_DATA 0x41b0b1
+ MX6SL_PAD_ECSPI1_MOSI__UART5_TX_DATA 0x41b0b1
+ MX6SL_PAD_ECSPI1_MISO__UART5_RTS_B 0x4130b1
+ MX6SL_PAD_ECSPI1_SS0__UART5_CTS_B 0x4130b1
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x417059
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x410059
+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x417059
+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x417059
+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x417059
+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x417059
+ MX6SL_PAD_SD2_DAT4__SD2_DATA4 0x417059
+ MX6SL_PAD_SD2_DAT5__SD2_DATA5 0x417059
+ MX6SL_PAD_SD2_DAT6__SD2_DATA6 0x417059
+ MX6SL_PAD_SD2_DAT7__SD2_DATA7 0x417059
+ MX6SL_PAD_SD2_RST__SD2_RESET 0x417059
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x4170b9
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x4100b9
+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x4170b9
+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x4170b9
+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x4170b9
+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x4170b9
+ MX6SL_PAD_SD2_DAT4__SD2_DATA4 0x4170b9
+ MX6SL_PAD_SD2_DAT5__SD2_DATA5 0x4170b9
+ MX6SL_PAD_SD2_DAT6__SD2_DATA6 0x4170b9
+ MX6SL_PAD_SD2_DAT7__SD2_DATA7 0x4170b9
+ MX6SL_PAD_SD2_RST__SD2_RESET 0x4170b9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x4170f9
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x4100f9
+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x4170f9
+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x4170f9
+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x4170f9
+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x4170f9
+ MX6SL_PAD_SD2_DAT4__SD2_DATA4 0x4170f9
+ MX6SL_PAD_SD2_DAT5__SD2_DATA5 0x4170f9
+ MX6SL_PAD_SD2_DAT6__SD2_DATA6 0x4170f9
+ MX6SL_PAD_SD2_DAT7__SD2_DATA7 0x4170f9
+ MX6SL_PAD_SD2_RST__SD2_RESET 0x4170f9
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x417059
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x410059
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x417059
+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x417059
+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x417059
+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x417059
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x4170b9
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x4100b9
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x4170b9
+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x4170b9
+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x4170b9
+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x4170b9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x4170f9
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x4100f9
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x4170f9
+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x4170f9
+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x4170f9
+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x4170f9
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sl.dtsi
index 6aa61235e39e..941a2f185056 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sl.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6sl.dtsi
@@ -378,7 +378,7 @@
};
gpt: timer@2098000 {
- compatible = "fsl,imx6sl-gpt";
+ compatible = "fsl,imx6sl-gpt", "fsl,imx6dl-gpt";
reg = <0x02098000 0x4000>;
interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_GPT>,
@@ -631,6 +631,7 @@
nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>;
nvmem-cell-names = "calib", "temp_grade";
clocks = <&clks IMX6SL_CLK_PLL3_USB_OTG>;
+ #thermal-sensor-cells = <0>;
};
};
@@ -859,7 +860,7 @@
};
usdhc1: mmc@2190000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
+ compatible = "fsl,imx6sl-usdhc";
reg = <0x02190000 0x4000>;
interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_USDHC1>,
@@ -871,7 +872,7 @@
};
usdhc2: mmc@2194000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
+ compatible = "fsl,imx6sl-usdhc";
reg = <0x02194000 0x4000>;
interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_USDHC2>,
@@ -883,7 +884,7 @@
};
usdhc3: mmc@2198000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
+ compatible = "fsl,imx6sl-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_USDHC3>,
@@ -895,7 +896,7 @@
};
usdhc4: mmc@219c000 {
- compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
+ compatible = "fsl,imx6sl-usdhc";
reg = <0x0219c000 0x4000>;
interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_USDHC4>,
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts
index febc2dd9967d..05d6827ea2af 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts
@@ -461,7 +461,7 @@
>;
};
- pinctrl_usdhc1_100mhz: usdhc1grp-100mhz {
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170b9
MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130b9
@@ -472,7 +472,7 @@
>;
};
- pinctrl_usdhc1_200mhz: usdhc1grp-200mhz {
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170f9
MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130f9
@@ -499,7 +499,7 @@
>;
};
- pinctrl_usdhc2_100mhz: usdhc2grp-100mhz {
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170b9
MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130b9
@@ -515,7 +515,7 @@
>;
};
- pinctrl_usdhc2_200mhz: usdhc2grp-200mhz {
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170f9
MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130f9
@@ -549,7 +549,7 @@
>;
};
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170a1
MX6SLL_PAD_SD3_CLK__SD3_CLK 0x130a1
@@ -561,7 +561,7 @@
>;
};
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170e9
MX6SLL_PAD_SD3_CLK__SD3_CLK 0x130f9
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-a.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-a.dts
new file mode 100644
index 000000000000..33756d6de7aa
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-a.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0)
+/*
+ * Device tree for the Kobo Clara 2E rev A ebook reader
+ *
+ * Name on mainboard is: 37NB-E60K2M+4A2
+ * Serials start with: E60K2M (a number also seen in
+ * vendor kernel sources)
+ *
+ * Copyright 2024 Andreas Kemnade
+ */
+
+/dts-v1/;
+
+#include "imx6sll-kobo-clara2e-common.dtsi"
+
+/ {
+ model = "Kobo Clara 2E";
+ compatible = "kobo,clara2e-b", "kobo,clara2e", "fsl,imx6sll";
+};
+
+&i2c2 {
+ /* EPD PMIC SY7636 at 0x62 */
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-b.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-b.dts
new file mode 100644
index 000000000000..f81aeacf5142
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-b.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0)
+/*
+ * Device tree for the Kobo Clara 2E rev B ebook reader
+ *
+ * Name on mainboard is: 37NB-E60K2M+4B0
+ * Serials start with: E60K2M (a number also seen in
+ * vendor kernel sources)
+ *
+ * Copyright 2024 Andreas Kemnade
+ */
+
+/dts-v1/;
+
+#include "imx6sll-kobo-clara2e-common.dtsi"
+
+/ {
+ model = "Kobo Clara 2E";
+ compatible = "kobo,clara2e-b", "kobo,clara2e", "fsl,imx6sll";
+};
+
+&i2c2 {
+ /* EPD PMIC JD9930 at 0x18 */
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-common.dtsi
new file mode 100644
index 000000000000..6f2deb366e02
--- /dev/null
+++ b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clara2e-common.dtsi
@@ -0,0 +1,511 @@
+// SPDX-License-Identifier: (GPL-2.0)
+/*
+ * Common part for Kobo Clara 2e device tree
+ * Copyright 2024 Andreas Kemnade
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "imx6sll.dtsi"
+
+/ {
+ aliases {
+ mmc0 = &usdhc2;
+ mmc1 = &usdhc3;
+ };
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ key-cover {
+ label = "Cover";
+ gpios = <&gpio4 23 GPIO_ACTIVE_LOW>;
+ linux,code = <SW_LID>;
+ linux,input-type = <EV_SW>;
+ wakeup-source;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led>;
+
+ led {
+ color = <LED_COLOR_ID_WHITE>;
+ function = LED_FUNCTION_POWER;
+ gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "timer";
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>;
+ };
+
+ reg_wifi: regulator-wifi {
+ compatible = "regulator-fixed";
+ regulator-name = "SD3_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&clks {
+ assigned-clocks = <&clks IMX6SLL_CLK_PLL4_AUDIO_DIV>;
+ assigned-clock-rates = <393216000>;
+};
+
+&cpu0 {
+ arm-supply = <&buck1>;
+ soc-supply = <&buck2>;
+};
+
+&i2c1 {
+ pinctrl-names = "default","sleep";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_sleep>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ /* backlight aw99703 at 0x36 */
+};
+
+&i2c2 {
+ pinctrl-names = "default","sleep";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_sleep>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ /* backlight aw99703 at 0x36 */
+
+ touchscreen@38 {
+ compatible = "focaltech,ft5426";
+ reg = <0x38>;
+ pinctrl-names = "default", "suspend";
+ pinctrl-0 = <&pinctrl_touch_gpio>;
+ pinctrl-1 = <&pinctrl_touch_gpio_sleep>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&gpio4 18 GPIO_ACTIVE_LOW>;
+ touchscreen-size-x = <1072>;
+ touchscreen-size-y = <1448>;
+ touchscreen-swapped-x-y;
+ };
+};
+
+&i2c3 {
+ /* Bus seems to be in bad state after boot, allow full recovery */
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ sda-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ pmic@4b {
+ compatible = "rohm,bd71879", "rohm,bd71828";
+ reg = <0x4b>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_bd71828>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
+ system-power-controller;
+ clocks = <&clks 0>;
+ #clock-cells = <0>;
+ clock-output-names = "bd71828-32k-out";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-reserved-ranges = <0 1>, <2 1>;
+
+ /* charge sense resistor is 30 milli-ohm */
+
+ regulators {
+ LDO1 {
+ name = "LDO1";
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ LDO2 {
+ name = "LDO2";
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ LDO3 {
+ name = "LDO3";
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo4: LDO4 {
+ name = "LDO4";
+ regulator-name = "ldo4";
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ LDO5 {
+ name = "LDO5";
+ regulator-name = "ldo5";
+ regulator-always-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ LDO6 {
+ name = "LDO6";
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ LDO7 {
+ name = "LDO7";
+ regulator-name = "ldo7";
+ regulator-always-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ buck1: BUCK1 {
+ name = "BUCK1";
+ regulator-name = "buck1";
+ regulator-always-on;
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ };
+
+ buck2: BUCK2 {
+ name = "BUCK2";
+ regulator-name = "buck2";
+ regulator-always-on;
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-boot-on;
+ };
+
+ BUCK3 {
+ name = "BUCK3";
+ regulator-name = "buck3";
+ regulator-always-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ BUCK4 {
+ name = "BUCK4";
+ regulator-name = "buck4";
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ };
+
+ BUCK5 {
+ name = "BUCK5";
+ regulator-name = "buck5";
+ regulator-always-on;
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ BUCK6 {
+ name = "BUCK6";
+ regulator-name = "buck6";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ BUCK7 {
+ name = "BUCK7";
+ regulator-name = "buck7";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2000000>;
+ };
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl_bd71828: bd71828-gpiogrp {
+ fsl,pins = <
+ MX6SLL_PAD_KEY_COL0__GPIO3_IO24 0x1b8b1
+ MX6SLL_PAD_GPIO4_IO19__GPIO4_IO19 0x1b8b1
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio-keysgrp {
+ fsl,pins = <
+ MX6SLL_PAD_GPIO4_IO25__GPIO4_IO25 0x17059 /* PWR_SW */
+ MX6SLL_PAD_GPIO4_IO23__GPIO4_IO23 0x17059 /* HALL_EN */
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x4001f8b1
+ MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x4001f8b1
+ >;
+ };
+
+ pinctrl_i2c1_sleep: i2c1-sleepgrp {
+ fsl,pins = <
+ MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x400108b1
+ MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x400108b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6SLL_PAD_I2C2_SCL__I2C2_SCL 0x4001f8b1
+ MX6SLL_PAD_I2C2_SDA__I2C2_SDA 0x4001f8b1
+ >;
+ };
+
+ pinctrl_i2c2_sleep: i2c2-sleepgrp {
+ fsl,pins = <
+ MX6SLL_PAD_I2C2_SCL__I2C2_SCL 0x400108b1
+ MX6SLL_PAD_I2C2_SDA__I2C2_SDA 0x400108b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SLL_PAD_REF_CLK_24M__I2C3_SCL 0x4001f8b1
+ MX6SLL_PAD_REF_CLK_32K__I2C3_SDA 0x4001f8b1
+ >;
+ };
+
+ pinctrl_i2c3_gpio: i2c3-gpiogrp {
+ fsl,pins = <
+ MX6SLL_PAD_REF_CLK_24M__GPIO3_IO21 0x4001f8b1
+ MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22 0x4001f8b1
+ >;
+ };
+
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ MX6SLL_PAD_GPIO4_IO17__GPIO4_IO17 0x10059
+ >;
+ };
+
+ pinctrl_touch_gpio: touch-gpiogrp {
+ fsl,pins = <
+ MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x17059 /* TP_INT */
+ MX6SLL_PAD_GPIO4_IO18__GPIO4_IO18 0x10059 /* TP_RST */
+ >;
+ };
+
+ pinctrl_touch_gpio_sleep: touch-gpio-sleepgrp {
+ fsl,pins = <
+ MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24 0x10059 /* TP_INT */
+ MX6SLL_PAD_GPIO4_IO18__GPIO4_IO18 0x10059 /* TP_RST */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SLL_PAD_UART1_TXD__UART1_DCE_TX 0x1b0b1
+ MX6SLL_PAD_UART1_RXD__UART1_DCE_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_ENABLE__UART2_DCE_RX 0x41b0b1
+ MX6SLL_PAD_LCD_HSYNC__UART2_DCE_TX 0x41b0b1
+ MX6SLL_PAD_LCD_VSYNC__UART2_DCE_RTS 0x41b0b1
+ MX6SLL_PAD_LCD_RESET__UART2_DCE_CTS 0x41b0b1
+ >;
+ };
+
+ pinctrl_uart2_sleep: uart2-sleepgrp {
+ fsl,pins = <
+ MX6SLL_PAD_LCD_ENABLE__GPIO2_IO16 0x10059
+ MX6SLL_PAD_LCD_HSYNC__GPIO2_IO17 0x10059
+ MX6SLL_PAD_LCD_VSYNC__GPIO2_IO18 0x10059
+ MX6SLL_PAD_LCD_RESET__GPIO2_IO19 0x10059
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1grp {
+ fsl,pins = <
+ MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6SLL_PAD_SD2_CLK__SD2_CLK 0x13059
+ MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x17059
+ MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x17059
+ MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x17059
+ MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170b9
+ MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130b9
+ MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x170b9
+ MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x170b9
+ MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x170b9
+ MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170f9
+ MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130f9
+ MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x170f9
+ MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x170f9
+ MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x170f9
+ MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc2_sleep: usdhc2-sleepgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_CMD__GPIO5_IO04 0x100f9
+ MX6SLL_PAD_SD2_CLK__GPIO5_IO05 0x100f9
+ MX6SLL_PAD_SD2_DATA0__GPIO5_IO01 0x100f9
+ MX6SLL_PAD_SD2_DATA1__GPIO4_IO30 0x100f9
+ MX6SLL_PAD_SD2_DATA2__GPIO5_IO03 0x100f9
+ MX6SLL_PAD_SD2_DATA3__GPIO4_IO28 0x100f9
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x11059
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x11059
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x11059
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x11059
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x11059
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x11059
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170b9
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x170b9
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x170b9
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x170b9
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x170b9
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6SLL_PAD_SD3_CLK__SD3_CLK 0x170f9
+ MX6SLL_PAD_SD3_DATA0__SD3_DATA0 0x170f9
+ MX6SLL_PAD_SD3_DATA1__SD3_DATA1 0x170f9
+ MX6SLL_PAD_SD3_DATA2__SD3_DATA2 0x170f9
+ MX6SLL_PAD_SD3_DATA3__SD3_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc3_sleep: usdhc3-sleepgrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD3_CMD__GPIO5_IO21 0x100c1
+ MX6SLL_PAD_SD3_CLK__GPIO5_IO18 0x100c1
+ MX6SLL_PAD_SD3_DATA0__GPIO5_IO19 0x100c1
+ MX6SLL_PAD_SD3_DATA1__GPIO5_IO20 0x100c1
+ MX6SLL_PAD_SD3_DATA2__GPIO5_IO16 0x100c1
+ MX6SLL_PAD_SD3_DATA3__GPIO5_IO17 0x100c1
+ >;
+ };
+
+ pinctrl_wifi_power: wifi-powergrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD2_DATA6__GPIO4_IO29 0x10059
+ >;
+ };
+};
+
+&snvs_rtc {
+ /* we are using the rtc in the pmic, not disabled in imx6sll.dtsi */
+ status = "disabled";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_uart2>;
+ pinctrl-1 = <&pinctrl_uart2_sleep>;
+ status = "okay";
+
+ /* requires LDO4 + power enable gpio */
+ bluetooth {
+ compatible = "nxp,88w8987-bt";
+ fw-init-baudrate = <1500000>;
+ };
+};
+
+&usbotg1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ 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";
+};
+
+&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>;
+ /* card requires also ldo4 */
+ vmmc-supply = <&reg_wifi>;
+ cap-power-off-card;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clarahd.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clarahd.dts
index c7cfe0b70f04..18c9ac8f7560 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clarahd.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clarahd.dts
@@ -121,7 +121,7 @@
>;
};
- pinctrl_i2c1_sleep: i2c1grp-sleep {
+ pinctrl_i2c1_sleep: i2c1sleep-grp {
fsl,pins = <
MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x400108b1
MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x400108b1
@@ -135,7 +135,7 @@
>;
};
- pinctrl_i2c2_sleep: i2c2grp-sleep {
+ pinctrl_i2c2_sleep: i2c2sleep-grp {
fsl,pins = <
MX6SLL_PAD_I2C2_SCL__I2C2_SCL 0x400108b1
MX6SLL_PAD_I2C2_SDA__I2C2_SDA 0x400108b1
@@ -200,7 +200,7 @@
>;
};
- pinctrl_usdhc2_100mhz: usdhc2grp-100mhz {
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170b9
MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130b9
@@ -211,7 +211,7 @@
>;
};
- pinctrl_usdhc2_200mhz: usdhc2grp-200mhz {
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170f9
MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130f9
@@ -222,7 +222,7 @@
>;
};
- pinctrl_usdhc2_sleep: usdhc2grp-sleep {
+ pinctrl_usdhc2_sleep: usdhc2sleep-grp {
fsl,pins = <
MX6SLL_PAD_SD2_CMD__GPIO5_IO04 0x100f9
MX6SLL_PAD_SD2_CLK__GPIO5_IO05 0x100f9
@@ -244,7 +244,7 @@
>;
};
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170b9
MX6SLL_PAD_SD3_CLK__SD3_CLK 0x170b9
@@ -255,7 +255,7 @@
>;
};
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
fsl,pins = <
MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170f9
MX6SLL_PAD_SD3_CLK__SD3_CLK 0x170f9
@@ -266,7 +266,7 @@
>;
};
- pinctrl_usdhc3_sleep: usdhc3grp-sleep {
+ pinctrl_usdhc3_sleep: usdhc3sleep-grp {
fsl,pins = <
MX6SLL_PAD_SD3_CMD__GPIO5_IO21 0x100c1
MX6SLL_PAD_SD3_CLK__GPIO5_IO18 0x100c1
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-librah2o.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-librah2o.dts
index 7e4f38dd11e2..660620d226f7 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-librah2o.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-librah2o.dts
@@ -121,7 +121,7 @@
>;
};
- pinctrl_i2c1_sleep: i2c1grp-sleep {
+ pinctrl_i2c1_sleep: i2c1sleep-grp {
fsl,pins = <
MX6SLL_PAD_I2C1_SCL__I2C1_SCL 0x400108b1
MX6SLL_PAD_I2C1_SDA__I2C1_SDA 0x400108b1
@@ -135,7 +135,7 @@
>;
};
- pinctrl_i2c2_sleep: i2c2grp-sleep {
+ pinctrl_i2c2_sleep: i2c2sleep-grp {
fsl,pins = <
MX6SLL_PAD_I2C2_SCL__I2C2_SCL 0x400108b1
MX6SLL_PAD_I2C2_SDA__I2C2_SDA 0x400108b1
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi
index ddeb5b37fb78..8c5ca4f9b87f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi
@@ -173,7 +173,7 @@
"rxtx1", "rxtx2",
"rxtx3", "rxtx4",
"rxtx5", "rxtx6",
- "rxtx7", "dma";
+ "rxtx7", "spba";
status = "disabled";
};
@@ -358,7 +358,7 @@
};
gpt1: timer@2098000 {
- compatible = "fsl,imx6sl-gpt";
+ compatible = "fsl,imx6sl-gpt", "fsl,imx6dl-gpt";
reg = <0x02098000 0x4000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_GPT_BUS>,
@@ -507,12 +507,9 @@
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- reg_3p0: regulator-3p0@20c8120 {
+ reg_3p0: regulator-3p0 {
compatible = "fsl,anatop-regulator";
- reg = <0x20c8120>;
regulator-name = "vdd3p0";
regulator-min-microvolt = <2625000>;
regulator-max-microvolt = <3400000>;
@@ -525,7 +522,7 @@
anatop-enable-bit = <0>;
};
- tempmon: temperature-sensor {
+ tempmon: tempmon {
compatible = "fsl,imx6sll-tempmon", "fsl,imx6sx-tempmon";
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gpc>;
@@ -533,6 +530,7 @@
nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>;
nvmem-cell-names = "calib", "temp_grade";
clocks = <&clks IMX6SLL_CLK_PLL3_USB_OTG>;
+ #thermal-sensor-cells = <0>;
};
};
@@ -601,6 +599,18 @@
#interrupt-cells = <3>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&intc>;
+ clocks = <&clks IMX6SLL_CLK_IPG>;
+ clock-names = "ipg";
+
+ pgc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@0 {
+ reg = <0>;
+ #power-domain-cells = <0>;
+ };
+ };
};
iomuxc: pinctrl@20e0000 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts
index dfbfb8119bf3..033700e052b3 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts
@@ -333,7 +333,7 @@
>;
};
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
fsl,pins = <
MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
@@ -348,7 +348,7 @@
>;
};
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
fsl,pins = <
MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
index 277a6e039045..1beac42c1a27 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
@@ -399,323 +399,321 @@
};
&iomuxc {
- imx6x-sdb {
- pinctrl_audmux: audmuxgrp {
- fsl,pins = <
- MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130b0
- MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130b0
- MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120b0
- MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130b0
- MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
- >;
- };
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130b0
+ MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130b0
+ MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120b0
+ MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130b0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
+ >;
+ };
- pinctrl_enet1: enet1grp {
- fsl,pins = <
- MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
- MX6SX_PAD_ENET1_MDC__ENET1_MDC 0xa0b1
- MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0xa0b1
- MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0xa0b1
- MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0xa0b1
- MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0xa0b1
- MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
- MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
- MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
- MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
- MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
- MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
- MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
- MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
- MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x91
- /* phy reset */
- MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 0x10b0
- >;
- };
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_ENET1_MDC__ENET1_MDC 0xa0b1
+ MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0xa0b1
+ MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x91
+ /* phy reset */
+ MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 0x10b0
+ >;
+ };
- pinctrl_enet_3v3: enet3v3grp {
- fsl,pins = <
- MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0x80000000
- >;
- };
+ pinctrl_enet_3v3: enet3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0x80000000
+ >;
+ };
- pinctrl_enet2: enet2grp {
- fsl,pins = <
- MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
- MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
- MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
- MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
- MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
- MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
- MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
- MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
- MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
- MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
- MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
- MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
- >;
- };
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
+ >;
+ };
- pinctrl_flexcan1: flexcan1grp {
- fsl,pins = <
- MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b020
- MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b020
- >;
- };
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x1b020
+ MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x1b020
+ >;
+ };
- pinctrl_flexcan2: flexcan2grp {
- fsl,pins = <
- MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b020
- MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b020
- >;
- };
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x1b020
+ MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x1b020
+ >;
+ };
- pinctrl_gpio_keys: gpio_keysgrp {
- fsl,pins = <
- MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
- MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
- >;
- };
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
+ MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
+ >;
+ };
- pinctrl_hp: hpgrp {
- fsl,pins = <
- MX6SX_PAD_CSI_DATA03__GPIO1_IO_17 0x17059
- >;
- };
+ pinctrl_hp: hpgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA03__GPIO1_IO_17 0x17059
+ >;
+ };
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1
- MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1
- >;
- };
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1
+ >;
+ };
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
- MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
- pinctrl_i2c4: i2c4grp {
- fsl,pins = <
- MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1
- MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1
- >;
- };
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1
+ >;
+ };
- pinctrl_lcd: lcdgrp {
- fsl,pins = <
- MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
- MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
- MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
- MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
- MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
- MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
- MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
- MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
- MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
- MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
- MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
- MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
- MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
- MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
- MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
- MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
- MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
- MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
- MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
- MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
- MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
- MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
- MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
- MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
- MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x4001b0b0
- MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
- MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
- MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
- MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0
- >;
- };
+ pinctrl_lcd: lcdgrp {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
+ MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x4001b0b0
+ MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
+ MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0
+ >;
+ };
- pinctrl_mqs: mqsgrp {
- fsl,pins = <
- MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x120b0
- MX6SX_PAD_SD2_CMD__MQS_LEFT 0x120b0
- >;
- };
+ pinctrl_mqs: mqsgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x120b0
+ MX6SX_PAD_SD2_CMD__MQS_LEFT 0x120b0
+ >;
+ };
- pinctrl_pcie: pciegrp {
- fsl,pins = <
- MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x10b0
- >;
- };
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x10b0
+ >;
+ };
- pinctrl_pcie_reg: pciereggrp {
- fsl,pins = <
- MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 0x10b0
- >;
- };
+ pinctrl_pcie_reg: pciereggrp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 0x10b0
+ >;
+ };
- pinctrl_peri_3v3: peri3v3grp {
- fsl,pins = <
- MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x80000000
- >;
- };
+ pinctrl_peri_3v3: peri3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x80000000
+ >;
+ };
- pinctrl_pwm3: pwm3grp-1 {
- fsl,pins = <
- MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
- >;
- };
+ pinctrl_pwm3: pwm3-1grp {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
+ >;
+ };
- pinctrl_qspi2: qspi2grp {
- fsl,pins = <
- MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70f1
- MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70f1
- MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70f1
- MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70f1
- MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70f1
- MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70f1
- MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70f1
- MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70f1
- MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70f1
- MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70f1
- MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70f1
- MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70f1
- >;
- };
+ pinctrl_qspi2: qspi2grp {
+ fsl,pins = <
+ MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70f1
+ MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70f1
+ MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70f1
+ MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70f1
+ MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70f1
+ MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70f1
+ MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70f1
+ MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70f1
+ MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70f1
+ MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70f1
+ MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70f1
+ MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70f1
+ >;
+ };
- pinctrl_vcc_sd3: vccsd3grp {
- fsl,pins = <
- MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
- >;
- };
+ pinctrl_vcc_sd3: vccsd3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
+ >;
+ };
- pinctrl_sai1: sai1grp {
- fsl,pins = <
- MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130b0
- MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x130b0
- MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x120b0
- MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x130b0
- MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
- >;
- };
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130b0
+ MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x130b0
+ MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x120b0
+ MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x130b0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
+ >;
+ };
- pinctrl_spdif: spdifgrp {
- fsl,pins = <
- MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
- >;
- };
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
+ >;
+ };
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX 0x1b0b1
- MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX 0x1b0b1
- >;
- };
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO04__UART1_DCE_TX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO05__UART1_DCE_RX 0x1b0b1
+ >;
+ };
- pinctrl_uart5: uart5grp {
- fsl,pins = <
- MX6SX_PAD_KEY_ROW3__UART5_DCE_RX 0x1b0b1
- MX6SX_PAD_KEY_COL3__UART5_DCE_TX 0x1b0b1
- MX6SX_PAD_KEY_ROW2__UART5_DCE_CTS 0x1b0b1
- MX6SX_PAD_KEY_COL2__UART5_DCE_RTS 0x1b0b1
- >;
- };
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW3__UART5_DCE_RX 0x1b0b1
+ MX6SX_PAD_KEY_COL3__UART5_DCE_TX 0x1b0b1
+ MX6SX_PAD_KEY_ROW2__UART5_DCE_CTS 0x1b0b1
+ MX6SX_PAD_KEY_COL2__UART5_DCE_RTS 0x1b0b1
+ >;
+ };
- pinctrl_usb_otg1: usbotg1grp {
- fsl,pins = <
- MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x10b0
- >;
- };
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x10b0
+ >;
+ };
- pinctrl_usb_otg1_id: usbotg1idgrp {
- fsl,pins = <
- MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
- >;
- };
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
+ >;
+ };
- pinctrl_usb_otg2: usbot2ggrp {
- fsl,pins = <
- MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12 0x10b0
- >;
- };
+ pinctrl_usb_otg2: usbot2ggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12 0x10b0
+ >;
+ };
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <
- MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
- MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
- MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
- MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059
- MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059
- MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059
- >;
- };
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059
+ MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059
+ MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
- MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
- MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
- MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
- MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
- MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
- MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
- MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
- MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
- MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
- MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
- MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
- >;
- };
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
+ >;
+ };
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
- fsl,pins = <
- MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
- MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
- MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
- MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
- MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
- MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
- MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
- MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
- MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
- MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
- >;
- };
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
+ >;
+ };
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
- fsl,pins = <
- MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
- MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
- MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
- MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
- MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
- MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
- MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
- MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
- MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
- MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
- >;
- };
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
- MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
- MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059
- MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059
- MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059
- MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059
- MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */
- MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */
- >;
- };
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059
+ MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */
+ MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */
+ >;
+ };
- pinctrl_wdog: wdoggrp {
- fsl,pins = <
- MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x30b0
- >;
- };
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x30b0
+ >;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts
index f999eb244373..2ffbe2df4776 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts
@@ -358,21 +358,21 @@
>;
};
- pinctrl_pwm1: pwm1grp-1 {
+ pinctrl_pwm1: pwm1-1grp {
fsl,pins = <
/* blue LED */
MX6SX_PAD_RGMII2_RD3__PWM1_OUT 0x1b0b1
>;
};
- pinctrl_pwm2: pwm2grp-1 {
+ pinctrl_pwm2: pwm2-1grp {
fsl,pins = <
/* green LED */
MX6SX_PAD_RGMII2_RD2__PWM2_OUT 0x1b0b1
>;
};
- pinctrl_pwm6: pwm6grp-1 {
+ pinctrl_pwm6: pwm6-1grp {
fsl,pins = <
/* red LED */
MX6SX_PAD_RGMII2_TD2__PWM6_OUT 0x1b0b1
@@ -414,7 +414,7 @@
>;
};
- pinctrl_usdhc2_50mhz: usdhc2grp-50mhz {
+ pinctrl_usdhc2_50mhz: usdhc2-50mhzgrp {
fsl,pins = <
MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
@@ -427,7 +427,7 @@
>;
};
- pinctrl_usdhc2_100mhz: usdhc2grp-100mhz {
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
fsl,pins = <
MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x100b9
MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x170b9
@@ -438,7 +438,7 @@
>;
};
- pinctrl_usdhc2_200mhz: usdhc2grp-200mhz {
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
fsl,pins = <
MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x100f9
MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x170f9
@@ -449,7 +449,7 @@
>;
};
- pinctrl_usdhc4_50mhz: usdhc4grp-50mhz {
+ pinctrl_usdhc4_50mhz: usdhc4-50mhzgrp {
fsl,pins = <
MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
@@ -465,7 +465,7 @@
>;
};
- pinctrl_usdhc4_100mhz: usdhc4-100mhz {
+ pinctrl_usdhc4_100mhz: usdhc4-100mhzgrp {
fsl,pins = <
MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x100b9
MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x170b9
@@ -480,7 +480,7 @@
>;
};
- pinctrl_usdhc4_200mhz: usdhc4-200mhz {
+ pinctrl_usdhc4_200mhz: usdhc4-200mhzgrp {
fsl,pins = <
MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x100f9
MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x170f9
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx.dtsi
index b386448486df..a9550f115f82 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sx.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6sx.dtsi
@@ -715,13 +715,14 @@
};
tempmon: tempmon {
- compatible = "fsl,imx6sx-tempmon", "fsl,imx6q-tempmon";
+ compatible = "fsl,imx6sx-tempmon";
interrupt-parent = <&gpc>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
fsl,tempmon = <&anatop>;
nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>;
nvmem-cell-names = "calib", "temp_grade";
clocks = <&clks IMX6SX_CLK_PLL3_USB_OTG>;
+ #thermal-sensor-cells = <0>;
};
};
@@ -998,7 +999,7 @@
};
usdhc1: mmc@2190000 {
- compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ compatible = "fsl,imx6sx-usdhc";
reg = <0x02190000 0x4000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_USDHC1>,
@@ -1012,7 +1013,7 @@
};
usdhc2: mmc@2194000 {
- compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ compatible = "fsl,imx6sx-usdhc";
reg = <0x02194000 0x4000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_USDHC2>,
@@ -1026,7 +1027,7 @@
};
usdhc3: mmc@2198000 {
- compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ compatible = "fsl,imx6sx-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_USDHC3>,
@@ -1040,7 +1041,7 @@
};
usdhc4: mmc@219c000 {
- compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ compatible = "fsl,imx6sx-usdhc";
reg = <0x0219c000 0x4000>;
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_USDHC4>,
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi
index 118df2a457c9..4c09bb312696 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi
@@ -322,7 +322,7 @@
>;
};
- pinctrl_stmpe: stmpegrp {
+ pinctrl_stmpe: stmpegrp {
fsl,pins = <
MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b0b0
>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul.dtsi
index 235aa676618b..6de224dd2bb9 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul.dtsi
@@ -274,6 +274,8 @@
clocks = <&clks IMX6UL_CLK_UART7_IPG>,
<&clks IMX6UL_CLK_UART7_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 43 4 0>, <&sdma 44 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -285,6 +287,8 @@
clocks = <&clks IMX6UL_CLK_UART1_IPG>,
<&clks IMX6UL_CLK_UART1_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -296,6 +300,8 @@
clocks = <&clks IMX6UL_CLK_UART8_IPG>,
<&clks IMX6UL_CLK_UART8_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 45 4 0>, <&sdma 46 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1075,6 +1081,8 @@
clocks = <&clks IMX6UL_CLK_UART2_IPG>,
<&clks IMX6UL_CLK_UART2_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1086,6 +1094,8 @@
clocks = <&clks IMX6UL_CLK_UART3_IPG>,
<&clks IMX6UL_CLK_UART3_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1097,6 +1107,8 @@
clocks = <&clks IMX6UL_CLK_UART4_IPG>,
<&clks IMX6UL_CLK_UART4_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1108,6 +1120,8 @@
clocks = <&clks IMX6UL_CLK_UART5_IPG>,
<&clks IMX6UL_CLK_UART5_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -1129,6 +1143,8 @@
clocks = <&clks IMX6UL_CLK_UART6_IPG>,
<&clks IMX6UL_CLK_UART6_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 0 4 0>, <&sdma 47 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull.dtsi
index 8a1776067ecc..db0c339022ac 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ull.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ull.dtsi
@@ -88,6 +88,8 @@
clocks = <&clks IMX6UL_CLK_UART8_IPG>,
<&clks IMX6UL_CLK_UART8_SERIAL>;
clock-names = "ipg", "per";
+ dmas = <&sdma 45 4 0>, <&sdma 46 4 0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi
index 62e41edcaf1d..8666dcd7fe97 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi
@@ -120,7 +120,7 @@
simple-audio-card,bitclock-master = <&dailink_master>;
simple-audio-card,format = "i2s";
simple-audio-card,frame-master = <&dailink_master>;
- simple-audio-card,name = "imx7-sgtl5000";
+ simple-audio-card,name = "colibri-imx7";
simple-audio-card,cpu {
sound-dai = <&sai1>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi b/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi
index ac338320ac1d..3c6ef7bfba60 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi
@@ -214,10 +214,11 @@
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pcc2 IMX7ULP_CLK_USB_PHY>;
#phy-cells = <0>;
+ nxp,sim = <&sim>;
};
usdhc0: mmc@40370000 {
- compatible = "fsl,imx7ulp-usdhc", "fsl,imx6sx-usdhc";
+ compatible = "fsl,imx7ulp-usdhc";
reg = <0x40370000 0x10000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>,
@@ -231,7 +232,7 @@
};
usdhc1: mmc@40380000 {
- compatible = "fsl,imx7ulp-usdhc", "fsl,imx6sx-usdhc";
+ compatible = "fsl,imx7ulp-usdhc";
reg = <0x40380000 0x10000>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>,
diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts b/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts
index 4c4ea91c286f..0d845ca81e89 100644
--- a/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts
+++ b/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts
@@ -116,7 +116,7 @@
};
pcf8563: rtc@51 {
- compatible = "phg,pcf8563";
+ compatible = "nxp,pcf8563";
reg = <0x51>;
};
};
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
index ac7494ed633e..5f1a6b4b7644 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi
@@ -36,58 +36,58 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <0>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <1>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <2>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc2>;
qcom,saw = <&saw2>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <3>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc3>;
qcom,saw = <&saw3>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
idle-states {
- CPU_SPC: cpu-spc {
+ cpu_spc: cpu-spc {
compatible = "qcom,idle-state-spc",
"arm,idle-state";
entry-latency-us = <400>;
@@ -675,7 +675,7 @@
tsens_calib: calib@404 {
reg = <0x404 0x10>;
};
- tsens_backup: backup_calib@414 {
+ tsens_backup: backup-calib@414 {
reg = <0x414 0x10>;
};
};
@@ -1625,7 +1625,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
out-ports {
port {
@@ -1643,7 +1643,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
out-ports {
port {
@@ -1661,7 +1661,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
out-ports {
port {
@@ -1679,7 +1679,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
out-ports {
port {
diff --git a/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi
index 014e6c5ee889..cee0694ef127 100644
--- a/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi
@@ -17,7 +17,7 @@
#size-cells = <1>;
ranges;
- smem_mem: smem_region@fa00000 {
+ smem_mem: smem-region@fa00000 {
reg = <0xfa00000 0x200000>;
no-map;
};
@@ -32,10 +32,10 @@
compatible = "qcom,krait";
reg = <0>;
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
cpu@1 {
@@ -43,10 +43,10 @@
compatible = "qcom,krait";
reg = <1>;
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
cpu@2 {
@@ -54,10 +54,10 @@
compatible = "qcom,krait";
reg = <2>;
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc2>;
qcom,saw = <&saw2>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
cpu@3 {
@@ -65,13 +65,13 @@
compatible = "qcom,krait";
reg = <3>;
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc3>;
qcom,saw = <&saw3>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -79,7 +79,7 @@
};
idle-states {
- CPU_SPC: cpu-spc {
+ cpu_spc: cpu-spc {
compatible = "qcom,idle-state-spc",
"arm,idle-state";
entry-latency-us = <150>;
@@ -311,7 +311,7 @@
bits = <0 6>;
};
- tsens_s10_p1: s10_p1@d8 {
+ tsens_s10_p1: s10-p1@d8 {
reg = <0xd8 0x2>;
bits = <6 6>;
};
@@ -371,137 +371,137 @@
bits = <4 6>;
};
- tsens_s10_p2: s10_p2@e2 {
+ tsens_s10_p2: s10-p2@e2 {
reg = <0xe2 0x2>;
bits = <2 6>;
};
- tsens_s5_p2_backup: s5-p2_backup@e3 {
+ tsens_s5_p2_backup: s5-p2-backup@e3 {
reg = <0xe3 0x2>;
bits = <0 6>;
};
- tsens_mode_backup: mode_backup@e3 {
+ tsens_mode_backup: mode-backup@e3 {
reg = <0xe3 0x1>;
bits = <6 2>;
};
- tsens_s6_p2_backup: s6-p2_backup@e4 {
+ tsens_s6_p2_backup: s6-p2-backup@e4 {
reg = <0xe4 0x1>;
bits = <0 6>;
};
- tsens_s7_p2_backup: s7-p2_backup@e4 {
+ tsens_s7_p2_backup: s7-p2-backup@e4 {
reg = <0xe4 0x2>;
bits = <6 6>;
};
- tsens_s8_p2_backup: s8-p2_backup@e5 {
+ tsens_s8_p2_backup: s8-p2-backup@e5 {
reg = <0xe5 0x2>;
bits = <4 6>;
};
- tsens_s9_p2_backup: s9-p2_backup@e6 {
+ tsens_s9_p2_backup: s9-p2-backup@e6 {
reg = <0xe6 0x2>;
bits = <2 6>;
};
- tsens_s10_p2_backup: s10_p2_backup@e7 {
+ tsens_s10_p2_backup: s10-p2-backup@e7 {
reg = <0xe7 0x1>;
bits = <0 6>;
};
- tsens_base1_backup: base1_backup@440 {
+ tsens_base1_backup: base1-backup@440 {
reg = <0x440 0x1>;
bits = <0 8>;
};
- tsens_s0_p1_backup: s0-p1_backup@441 {
+ tsens_s0_p1_backup: s0-p1-backup@441 {
reg = <0x441 0x1>;
bits = <0 6>;
};
- tsens_s1_p1_backup: s1-p1_backup@442 {
+ tsens_s1_p1_backup: s1-p1-backup@442 {
reg = <0x441 0x2>;
bits = <6 6>;
};
- tsens_s2_p1_backup: s2-p1_backup@442 {
+ tsens_s2_p1_backup: s2-p1-backup@442 {
reg = <0x442 0x2>;
bits = <4 6>;
};
- tsens_s3_p1_backup: s3-p1_backup@443 {
+ tsens_s3_p1_backup: s3-p1-backup@443 {
reg = <0x443 0x1>;
bits = <2 6>;
};
- tsens_s4_p1_backup: s4-p1_backup@444 {
+ tsens_s4_p1_backup: s4-p1-backup@444 {
reg = <0x444 0x1>;
bits = <0 6>;
};
- tsens_s5_p1_backup: s5-p1_backup@444 {
+ tsens_s5_p1_backup: s5-p1-backup@444 {
reg = <0x444 0x2>;
bits = <6 6>;
};
- tsens_s6_p1_backup: s6-p1_backup@445 {
+ tsens_s6_p1_backup: s6-p1-backup@445 {
reg = <0x445 0x2>;
bits = <4 6>;
};
- tsens_s7_p1_backup: s7-p1_backup@446 {
+ tsens_s7_p1_backup: s7-p1-backup@446 {
reg = <0x446 0x1>;
bits = <2 6>;
};
- tsens_use_backup: use_backup@447 {
+ tsens_use_backup: use-backup@447 {
reg = <0x447 0x1>;
bits = <5 3>;
};
- tsens_s8_p1_backup: s8-p1_backup@448 {
+ tsens_s8_p1_backup: s8-p1-backup@448 {
reg = <0x448 0x1>;
bits = <0 6>;
};
- tsens_s9_p1_backup: s9-p1_backup@448 {
+ tsens_s9_p1_backup: s9-p1-backup@448 {
reg = <0x448 0x2>;
bits = <6 6>;
};
- tsens_s10_p1_backup: s10_p1_backup@449 {
+ tsens_s10_p1_backup: s10-p1-backup@449 {
reg = <0x449 0x2>;
bits = <4 6>;
};
- tsens_base2_backup: base2_backup@44a {
+ tsens_base2_backup: base2-backup@44a {
reg = <0x44a 0x2>;
bits = <2 8>;
};
- tsens_s0_p2_backup: s0-p2_backup@44b {
+ tsens_s0_p2_backup: s0-p2-backup@44b {
reg = <0x44b 0x3>;
bits = <2 6>;
};
- tsens_s1_p2_backup: s1-p2_backup@44c {
+ tsens_s1_p2_backup: s1-p2-backup@44c {
reg = <0x44c 0x1>;
bits = <0 6>;
};
- tsens_s2_p2_backup: s2-p2_backup@44c {
+ tsens_s2_p2_backup: s2-p2-backup@44c {
reg = <0x44c 0x2>;
bits = <6 6>;
};
- tsens_s3_p2_backup: s3-p2_backup@44d {
+ tsens_s3_p2_backup: s3-p2-backup@44d {
reg = <0x44d 0x2>;
bits = <4 6>;
};
- tsens_s4_p2_backup: s4-p2_backup@44e {
+ tsens_s4_p2_backup: s4-p2-backup@44e {
reg = <0x44e 0x1>;
bits = <2 6>;
};
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi
index 0d23c03fae33..a6d4390efa7c 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi
@@ -166,16 +166,19 @@
label = "ART";
reg = <0x00170000 0x00010000>;
read-only;
- compatible = "nvmem-cells";
- #address-cells = <1>;
- #size-cells = <1>;
- precal_art_1000: precal@1000 {
- reg = <0x1000 0x2f20>;
- };
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ precal_art_1000: precal@1000 {
+ reg = <0x1000 0x2f20>;
+ };
- precal_art_5000: precal@5000 {
- reg = <0x5000 0x2f20>;
+ precal_art_5000: precal@5000 {
+ reg = <0x5000 0x2f20>;
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts b/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts
index ac3b30072a22..6640ea7b6acb 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts
+++ b/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts
@@ -25,7 +25,7 @@
};
};
- serial_pins: serial-state{
+ serial_pins: serial-state {
pins = "gpio60", "gpio61";
function = "blsp_uart0";
bias-disable;
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi
index 56415ab34083..06b20c196faf 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi
@@ -47,7 +47,7 @@
device_type = "cpu";
compatible = "arm,cortex-a7";
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
reg = <0x0>;
@@ -61,7 +61,7 @@
device_type = "cpu";
compatible = "arm,cortex-a7";
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
reg = <0x1>;
@@ -75,7 +75,7 @@
device_type = "cpu";
compatible = "arm,cortex-a7";
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc2>;
qcom,saw = <&saw2>;
reg = <0x2>;
@@ -89,7 +89,7 @@
device_type = "cpu";
compatible = "arm,cortex-a7";
enable-method = "qcom,kpss-acc-v2";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc3>;
qcom,saw = <&saw3>;
reg = <0x3>;
@@ -99,7 +99,7 @@
operating-points-v2 = <&cpu0_opp_table>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
diff --git a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
index 759a59c2bdbc..96e973501535 100644
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
@@ -27,7 +27,7 @@
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <0>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
};
@@ -37,12 +37,12 @@
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <1>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -383,7 +383,7 @@
tsens_calib: calib@400 {
reg = <0x400 0xb>;
};
- tsens_calib_backup: calib_backup@410 {
+ tsens_calib_backup: calib-backup@410 {
reg = <0x410 0xb>;
};
};
diff --git a/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
index 573feb3218c3..7de8d6c55016 100644
--- a/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi
@@ -30,7 +30,7 @@
compatible = "arm,cortex-a5";
reg = <0>;
device_type = "cpu";
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
};
};
@@ -61,7 +61,7 @@
ranges;
compatible = "simple-bus";
- L2: cache-controller@2040000 {
+ l2: cache-controller@2040000 {
compatible = "arm,pl310-cache";
reg = <0x02040000 0x1000>;
arm,data-latency = <2 2 0>;
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
index 3a685ff7e8cc..64c8ac94f352 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi
@@ -39,12 +39,12 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
compatible = "arm,cortex-a7";
enable-method = "qcom,msm8226-smp";
device_type = "cpu";
reg = <0>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
qcom,acc = <&acc0>;
@@ -52,12 +52,12 @@
#cooling-cells = <2>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
compatible = "arm,cortex-a7";
enable-method = "qcom,msm8226-smp";
device_type = "cpu";
reg = <1>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
qcom,acc = <&acc1>;
@@ -65,12 +65,12 @@
#cooling-cells = <2>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
compatible = "arm,cortex-a7";
enable-method = "qcom,msm8226-smp";
device_type = "cpu";
reg = <2>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
qcom,acc = <&acc2>;
@@ -78,12 +78,12 @@
#cooling-cells = <2>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
compatible = "arm,cortex-a7";
enable-method = "qcom,msm8226-smp";
device_type = "cpu";
reg = <3>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
qcom,acc = <&acc3>;
@@ -91,7 +91,7 @@
#cooling-cells = <2>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -1264,10 +1264,10 @@
cooling-maps {
map0 {
trip = <&cpu_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
@@ -1295,10 +1295,10 @@
cooling-maps {
map0 {
trip = <&cpu_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi
index a66c474cd1aa..3f69b98d0041 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi
@@ -22,7 +22,7 @@
enable-method = "qcom,gcc-msm8660";
device_type = "cpu";
reg = <0>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
};
cpu@1 {
@@ -30,10 +30,10 @@
enable-method = "qcom,gcc-msm8660";
device_type = "cpu";
reg = <1>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8916-smp.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8916-smp.dtsi
index 1ba403b83cb1..94b7694eeeff 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8916-smp.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8916-smp.dtsi
@@ -25,7 +25,7 @@
};
};
-&CPU_SLEEP_0 {
+&cpu_sleep_0 {
compatible = "qcom,idle-state-spc", "arm,idle-state";
};
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
index ebc43c5c6e5f..865fe7cc3951 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi
@@ -25,7 +25,7 @@
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <0>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
};
@@ -35,12 +35,12 @@
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
reg = <1>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts b/arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts
index fdb6e22986cf..261044fdfee8 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts
@@ -167,7 +167,7 @@
status = "okay";
clock-frequency = <100000>;
- avago_apds993@39 {
+ sensor@39 {
compatible = "avago,apds9930";
reg = <0x39>;
interrupts-extended = <&tlmm 61 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
index 1bd87170252d..e3f9c56a778c 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
@@ -35,51 +35,51 @@
#size-cells = <0>;
interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v2";
device_type = "cpu";
reg = <0>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v2";
device_type = "cpu";
reg = <1>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v2";
device_type = "cpu";
reg = <2>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc2>;
qcom,saw = <&saw2>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v2";
device_type = "cpu";
reg = <3>;
- next-level-cache = <&L2>;
+ next-level-cache = <&l2>;
qcom,acc = <&acc3>;
qcom,saw = <&saw3>;
- cpu-idle-states = <&CPU_SPC>;
+ cpu-idle-states = <&cpu_spc>;
};
- L2: l2-cache {
+ l2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -87,7 +87,7 @@
};
idle-states {
- CPU_SPC: cpu-spc {
+ cpu_spc: cpu-spc {
compatible = "qcom,idle-state-spc",
"arm,idle-state";
entry-latency-us = <150>;
@@ -960,7 +960,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
out-ports {
port {
@@ -978,7 +978,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
out-ports {
port {
@@ -996,7 +996,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
out-ports {
port {
@@ -1014,7 +1014,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
out-ports {
port {
@@ -1299,7 +1299,7 @@
bits = <0 6>;
};
- tsens_s10_p1: s10_p1@d8 {
+ tsens_s10_p1: s10-p1@d8 {
reg = <0xd8 0x2>;
bits = <6 6>;
};
@@ -1359,137 +1359,137 @@
bits = <4 6>;
};
- tsens_s10_p2: s10_p2@e2 {
+ tsens_s10_p2: s10-p2@e2 {
reg = <0xe2 0x2>;
bits = <2 6>;
};
- tsens_s5_p2_backup: s5-p2_backup@e3 {
+ tsens_s5_p2_backup: s5-p2-backup@e3 {
reg = <0xe3 0x2>;
bits = <0 6>;
};
- tsens_mode_backup: mode_backup@e3 {
+ tsens_mode_backup: mode-backup@e3 {
reg = <0xe3 0x1>;
bits = <6 2>;
};
- tsens_s6_p2_backup: s6-p2_backup@e4 {
+ tsens_s6_p2_backup: s6-p2-backup@e4 {
reg = <0xe4 0x1>;
bits = <0 6>;
};
- tsens_s7_p2_backup: s7-p2_backup@e4 {
+ tsens_s7_p2_backup: s7-p2-backup@e4 {
reg = <0xe4 0x2>;
bits = <6 6>;
};
- tsens_s8_p2_backup: s8-p2_backup@e5 {
+ tsens_s8_p2_backup: s8-p2-backup@e5 {
reg = <0xe5 0x2>;
bits = <4 6>;
};
- tsens_s9_p2_backup: s9-p2_backup@e6 {
+ tsens_s9_p2_backup: s9-p2-backup@e6 {
reg = <0xe6 0x2>;
bits = <2 6>;
};
- tsens_s10_p2_backup: s10_p2_backup@e7 {
+ tsens_s10_p2_backup: s10-p2-backup@e7 {
reg = <0xe7 0x1>;
bits = <0 6>;
};
- tsens_base1_backup: base1_backup@440 {
+ tsens_base1_backup: base1-backup@440 {
reg = <0x440 0x1>;
bits = <0 8>;
};
- tsens_s0_p1_backup: s0-p1_backup@441 {
+ tsens_s0_p1_backup: s0-p1-backup@441 {
reg = <0x441 0x1>;
bits = <0 6>;
};
- tsens_s1_p1_backup: s1-p1_backup@442 {
+ tsens_s1_p1_backup: s1-p1-backup@442 {
reg = <0x441 0x2>;
bits = <6 6>;
};
- tsens_s2_p1_backup: s2-p1_backup@442 {
+ tsens_s2_p1_backup: s2-p1-backup@442 {
reg = <0x442 0x2>;
bits = <4 6>;
};
- tsens_s3_p1_backup: s3-p1_backup@443 {
+ tsens_s3_p1_backup: s3-p1-backup@443 {
reg = <0x443 0x1>;
bits = <2 6>;
};
- tsens_s4_p1_backup: s4-p1_backup@444 {
+ tsens_s4_p1_backup: s4-p1-backup@444 {
reg = <0x444 0x1>;
bits = <0 6>;
};
- tsens_s5_p1_backup: s5-p1_backup@444 {
+ tsens_s5_p1_backup: s5-p1-backup@444 {
reg = <0x444 0x2>;
bits = <6 6>;
};
- tsens_s6_p1_backup: s6-p1_backup@445 {
+ tsens_s6_p1_backup: s6-p1-backup@445 {
reg = <0x445 0x2>;
bits = <4 6>;
};
- tsens_s7_p1_backup: s7-p1_backup@446 {
+ tsens_s7_p1_backup: s7-p1-backup@446 {
reg = <0x446 0x1>;
bits = <2 6>;
};
- tsens_use_backup: use_backup@447 {
+ tsens_use_backup: use-backup@447 {
reg = <0x447 0x1>;
bits = <5 3>;
};
- tsens_s8_p1_backup: s8-p1_backup@448 {
+ tsens_s8_p1_backup: s8-p1-backup@448 {
reg = <0x448 0x1>;
bits = <0 6>;
};
- tsens_s9_p1_backup: s9-p1_backup@448 {
+ tsens_s9_p1_backup: s9-p1-backup@448 {
reg = <0x448 0x2>;
bits = <6 6>;
};
- tsens_s10_p1_backup: s10_p1_backup@449 {
+ tsens_s10_p1_backup: s10-p1-backup@449 {
reg = <0x449 0x2>;
bits = <4 6>;
};
- tsens_base2_backup: base2_backup@44a {
+ tsens_base2_backup: base2-backup@44a {
reg = <0x44a 0x2>;
bits = <2 8>;
};
- tsens_s0_p2_backup: s0-p2_backup@44b {
+ tsens_s0_p2_backup: s0-p2-backup@44b {
reg = <0x44b 0x3>;
bits = <2 6>;
};
- tsens_s1_p2_backup: s1-p2_backup@44c {
+ tsens_s1_p2_backup: s1-p2-backup@44c {
reg = <0x44c 0x1>;
bits = <0 6>;
};
- tsens_s2_p2_backup: s2-p2_backup@44c {
+ tsens_s2_p2_backup: s2-p2-backup@44c {
reg = <0x44c 0x2>;
bits = <6 6>;
};
- tsens_s3_p2_backup: s3-p2_backup@44d {
+ tsens_s3_p2_backup: s3-p2-backup@44d {
reg = <0x44d 0x2>;
bits = <4 6>;
};
- tsens_s4_p2_backup: s4-p2_backup@44e {
+ tsens_s4_p2_backup: s4-p2-backup@44e {
reg = <0x44e 0x1>;
bits = <2 6>;
};
diff --git a/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi
index 68fa5859d263..d0f6120b665d 100644
--- a/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi
@@ -437,6 +437,7 @@
phy-names = "pciephy";
max-link-speed = <3>;
num-lanes = <2>;
+ linux,pci-domain = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi b/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi
index a949454212e9..3bc67bb8c1eb 100644
--- a/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi
@@ -345,6 +345,7 @@
max-link-speed = <3>;
num-lanes = <2>;
+ linux,pci-domain = <0>;
status = "disabled";
};
@@ -592,39 +593,39 @@
reg = <0x15000000 0x40000>;
#iommu-cells = <2>;
#global-interrupts = <1>;
- interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 73 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 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 303 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>,
- <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 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 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 303 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>,
+ <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
};
intc: interrupt-controller@17800000 {
diff --git a/arch/arm/boot/dts/renesas/emev2-kzm9d.dts b/arch/arm/boot/dts/renesas/emev2-kzm9d.dts
index 89495dd37358..9b64f98310f3 100644
--- a/arch/arm/boot/dts/renesas/emev2-kzm9d.dts
+++ b/arch/arm/boot/dts/renesas/emev2-kzm9d.dts
@@ -31,28 +31,28 @@
gpio_keys {
compatible = "gpio-keys";
- one {
+ key-1 {
debounce-interval = <50>;
wakeup-source;
label = "DSW2-1";
linux,code = <KEY_1>;
gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
};
- two {
+ key-2 {
debounce-interval = <50>;
wakeup-source;
label = "DSW2-2";
linux,code = <KEY_2>;
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
- three {
+ key-3 {
debounce-interval = <50>;
wakeup-source;
label = "DSW2-3";
linux,code = <KEY_3>;
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
};
- four {
+ key-4 {
debounce-interval = <50>;
wakeup-source;
label = "DSW2-4";
@@ -83,8 +83,7 @@
compatible = "smsc,lan9221", "smsc,lan9115";
reg = <0x20000000 0x10000>;
phy-mode = "mii";
- interrupt-parent = <&gpio0>;
- interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+ interrupts-extended = <&gpio0 1 IRQ_TYPE_EDGE_RISING>;
reg-io-width = <4>;
smsc,irq-active-high;
smsc,irq-push-pull;
diff --git a/arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi b/arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi
index 4351c5a02fa5..2cc2908b48ca 100644
--- a/arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi
+++ b/arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi
@@ -219,8 +219,7 @@
touch: touchpanel@38 {
compatible = "edt,edt-ft5406";
reg = <0x38>;
- interrupt-parent = <&gpio2>;
- interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio2 12 IRQ_TYPE_EDGE_FALLING>;
vcc-supply = <&vcc_3v3_tft1>;
};
};
diff --git a/arch/arm/boot/dts/renesas/iwg20d-q7-dbcm-ca.dtsi b/arch/arm/boot/dts/renesas/iwg20d-q7-dbcm-ca.dtsi
index de52218ceaa4..ca58ea93f58f 100644
--- a/arch/arm/boot/dts/renesas/iwg20d-q7-dbcm-ca.dtsi
+++ b/arch/arm/boot/dts/renesas/iwg20d-q7-dbcm-ca.dtsi
@@ -73,8 +73,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio0>;
- interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio0 13 IRQ_TYPE_LEVEL_LOW>;
clocks = <&cec_clock>;
clock-names = "cec";
diff --git a/arch/arm/boot/dts/renesas/r7s72100-genmai.dts b/arch/arm/boot/dts/renesas/r7s72100-genmai.dts
index 29ba098f5dd5..c81840dfb7da 100644
--- a/arch/arm/boot/dts/renesas/r7s72100-genmai.dts
+++ b/arch/arm/boot/dts/renesas/r7s72100-genmai.dts
@@ -9,6 +9,7 @@
/dts-v1/;
#include "r7s72100.dtsi"
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/r7s72100-pinctrl.h>
/ {
@@ -24,11 +25,6 @@
stdout-path = "serial0:115200n8";
};
- memory@8000000 {
- device_type = "memory";
- reg = <0x08000000 0x08000000>;
- };
-
flash@18000000 {
compatible = "mtd-rom";
reg = <0x18000000 0x08000000>;
@@ -53,13 +49,29 @@
partition@4000000 {
label = "user1";
- reg = <0x04000000 0x40000000>;
+ reg = <0x04000000 0x04000000>;
};
};
};
+ keyboard {
+ compatible = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&keyboard_pins>;
+
+ key-1 {
+ /* JP3 must be set to 1-2 (default) */
+ interrupts-extended = <&irqc 6 IRQ_TYPE_EDGE_BOTH>;
+ linux,code = <KEY_1>;
+ label = "SW6,SW7";
+ wakeup-source;
+ };
+ };
+
leds {
- status = "okay";
+ /* Needs SDHI0 to be disabled */
+ status = "disabled";
compatible = "gpio-leds";
led1 {
@@ -70,47 +82,22 @@
gpios = <&port4 11 GPIO_ACTIVE_LOW>;
};
};
-};
-
-&pinctrl {
-
- scif2_pins: serial2 {
- /* P3_0 as TxD2; P3_2 as RxD2 */
- pinmux = <RZA1_PINMUX(3, 0, 6)>, <RZA1_PINMUX(3, 2, 4)>;
- };
- i2c2_pins: i2c2 {
- /* RIIC2: P1_4 as SCL, P1_5 as SDA */
- pinmux = <RZA1_PINMUX(1, 4, 1)>, <RZA1_PINMUX(1, 5, 1)>;
+ memory@8000000 {
+ device_type = "memory";
+ reg = <0x08000000 0x08000000>;
};
- ether_pins: ether {
- /* Ethernet on Ports 1,2,3,5 */
- pinmux = <RZA1_PINMUX(1, 14, 4)>,/* P1_14 = ET_COL */
- <RZA1_PINMUX(5, 9, 2)>, /* P5_9 = ET_MDC */
- <RZA1_PINMUX(3, 3, 2)>, /* P3_3 = ET_MDIO */
- <RZA1_PINMUX(3, 4, 2)>, /* P3_4 = ET_RXCLK */
- <RZA1_PINMUX(3, 5, 2)>, /* P3_5 = ET_RXER */
- <RZA1_PINMUX(3, 6, 2)>, /* P3_6 = ET_RXDV */
- <RZA1_PINMUX(2, 0, 2)>, /* P2_0 = ET_TXCLK */
- <RZA1_PINMUX(2, 1, 2)>, /* P2_1 = ET_TXER */
- <RZA1_PINMUX(2, 2, 2)>, /* P2_2 = ET_TXEN */
- <RZA1_PINMUX(2, 3, 2)>, /* P2_3 = ET_CRS */
- <RZA1_PINMUX(2, 4, 2)>, /* P2_4 = ET_TXD0 */
- <RZA1_PINMUX(2, 5, 2)>, /* P2_5 = ET_TXD1 */
- <RZA1_PINMUX(2, 6, 2)>, /* P2_6 = ET_TXD2 */
- <RZA1_PINMUX(2, 7, 2)>, /* P2_7 = ET_TXD3 */
- <RZA1_PINMUX(2, 8, 2)>, /* P2_8 = ET_RXD0 */
- <RZA1_PINMUX(2, 9, 2)>, /* P2_9 = ET_RXD1 */
- <RZA1_PINMUX(2, 10, 2)>,/* P2_10 = ET_RXD2 */
- <RZA1_PINMUX(2, 11, 2)>;/* P2_11 = ET_RXD3 */
+ cvcc2: regulator-mmc {
+ compatible = "regulator-fixed";
+ regulator-name = "Cvcc2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
};
};
-&extal_clk {
- clock-frequency = <13330000>;
-};
-
&bsc {
flash@0 {
compatible = "cfi-flash";
@@ -167,18 +154,6 @@
};
};
-&usb_x1_clk {
- clock-frequency = <48000000>;
-};
-
-&rtc_x1_clk {
- clock-frequency = <32768>;
-};
-
-&mtu2 {
- status = "okay";
-};
-
&ether {
pinctrl-names = "default";
pinctrl-0 = <&ether_pins>;
@@ -194,6 +169,10 @@
};
};
+&extal_clk {
+ clock-frequency = <13330000>;
+};
+
&i2c2 {
status = "okay";
clock-frequency = <400000>;
@@ -208,6 +187,98 @@
};
};
+&mmcif {
+ pinctrl-0 = <&mmcif_pins>;
+ pinctrl-names = "default";
+ cd-gpios = <&port3 8 GPIO_ACTIVE_LOW>;
+
+ vmmc-supply = <&cvcc2>;
+ vqmmc-supply = <&cvcc2>;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&mtu2 {
+ status = "okay";
+};
+
+&ostm0 {
+ status = "okay";
+};
+
+&ostm1 {
+ status = "okay";
+};
+
+&pinctrl {
+ ether_pins: ether {
+ /* Ethernet on Ports 1,2,3,5 */
+ pinmux = <RZA1_PINMUX(1, 14, 4)>,/* P1_14 = ET_COL */
+ <RZA1_PINMUX(5, 9, 2)>, /* P5_9 = ET_MDC */
+ <RZA1_PINMUX(3, 3, 2)>, /* P3_3 = ET_MDIO */
+ <RZA1_PINMUX(3, 4, 2)>, /* P3_4 = ET_RXCLK */
+ <RZA1_PINMUX(3, 5, 2)>, /* P3_5 = ET_RXER */
+ <RZA1_PINMUX(3, 6, 2)>, /* P3_6 = ET_RXDV */
+ <RZA1_PINMUX(2, 0, 2)>, /* P2_0 = ET_TXCLK */
+ <RZA1_PINMUX(2, 1, 2)>, /* P2_1 = ET_TXER */
+ <RZA1_PINMUX(2, 2, 2)>, /* P2_2 = ET_TXEN */
+ <RZA1_PINMUX(2, 3, 2)>, /* P2_3 = ET_CRS */
+ <RZA1_PINMUX(2, 4, 2)>, /* P2_4 = ET_TXD0 */
+ <RZA1_PINMUX(2, 5, 2)>, /* P2_5 = ET_TXD1 */
+ <RZA1_PINMUX(2, 6, 2)>, /* P2_6 = ET_TXD2 */
+ <RZA1_PINMUX(2, 7, 2)>, /* P2_7 = ET_TXD3 */
+ <RZA1_PINMUX(2, 8, 2)>, /* P2_8 = ET_RXD0 */
+ <RZA1_PINMUX(2, 9, 2)>, /* P2_9 = ET_RXD1 */
+ <RZA1_PINMUX(2, 10, 2)>,/* P2_10 = ET_RXD2 */
+ <RZA1_PINMUX(2, 11, 2)>;/* P2_11 = ET_RXD3 */
+ };
+
+ i2c2_pins: i2c2 {
+ /* RIIC2: P1_4 as SCL, P1_5 as SDA */
+ pinmux = <RZA1_PINMUX(1, 4, 1)>, <RZA1_PINMUX(1, 5, 1)>;
+ };
+
+ keyboard_pins: keyboard {
+ /* P3_1 as IRQ6 */
+ pinmux = <RZA1_PINMUX(3, 1, 3)>;
+ };
+
+ mmcif_pins: mmcif {
+ /* MMCIF: P3_8 is CD_GPIO, P3_10 up to P3_15, P4_0 up to P4_3 */
+ pinmux = <RZA1_PINMUX(3, 10, 8)>, /* MMC_D1 */
+ <RZA1_PINMUX(3, 11, 8)>, /* MMC_D0 */
+ <RZA1_PINMUX(3, 12, 8)>, /* MMC_CLK */
+ <RZA1_PINMUX(3, 13, 8)>, /* MMC_CMD */
+ <RZA1_PINMUX(3, 14, 8)>, /* MMC_D3 */
+ <RZA1_PINMUX(3, 15, 8)>, /* MMC_D2 */
+ <RZA1_PINMUX(4, 0, 8)>, /* MMC_D4 */
+ <RZA1_PINMUX(4, 1, 8)>, /* MMC_D5 */
+ <RZA1_PINMUX(4, 2, 8)>, /* MMC_D6 */
+ <RZA1_PINMUX(4, 3, 8)>; /* MMC_D7 */
+ };
+
+ scif2_pins: serial2 {
+ /* P3_0 as TxD2; P3_2 as RxD2 */
+ pinmux = <RZA1_PINMUX(3, 0, 6)>, <RZA1_PINMUX(3, 2, 4)>;
+ };
+
+ sdhi0_pins: sdhi0 {
+ /* SDHI0: P4_8 up to P4_15 */
+ pinmux = <RZA1_PINMUX(4, 8, 3)>, /* SD_CD_0 */
+ <RZA1_PINMUX(4, 9, 3)>, /* SD_WP_0 */
+ <RZA1_PINMUX(4, 10, 3)>, /* SD_D1_0 */
+ <RZA1_PINMUX(4, 11, 3)>, /* SD_D0_0 */
+ <RZA1_PINMUX(4, 12, 3)>, /* SD_CLK_0 */
+ <RZA1_PINMUX(4, 13, 3)>, /* SD_CMD_0 */
+ <RZA1_PINMUX(4, 14, 3)>, /* SD_D3_0 */
+ <RZA1_PINMUX(4, 15, 3)>; /* SD_D2_0 */
+ };
+};
+
+&rtc_x1_clk {
+ clock-frequency = <32768>;
+};
+
&rtc {
status = "okay";
};
@@ -219,12 +290,30 @@
status = "okay";
};
+&sdhi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhi0_pins>;
+
+ bus-width = <4>;
+ status = "okay";
+};
+
&spi4 {
status = "okay";
codec: codec@0 {
compatible = "wlf,wm8978";
reg = <0>;
- spi-max-frequency = <5000000>;
+ spi-max-frequency = <500000>;
+ #sound-dai-cells = <0>;
};
};
+
+&usb_x1_clk {
+ clock-frequency = <48000000>;
+};
+
+&wdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts b/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts
index b547216d4801..25c6d0c78828 100644
--- a/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts
+++ b/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts
@@ -78,24 +78,21 @@
pinctrl-0 = <&keyboard_pins>;
key-1 {
- interrupt-parent = <&irqc>;
- interrupts = <3 IRQ_TYPE_EDGE_BOTH>;
+ interrupts-extended = <&irqc 3 IRQ_TYPE_EDGE_BOTH>;
linux,code = <KEY_1>;
label = "SW1";
wakeup-source;
};
key-2 {
- interrupt-parent = <&irqc>;
- interrupts = <2 IRQ_TYPE_EDGE_BOTH>;
+ interrupts-extended = <&irqc 2 IRQ_TYPE_EDGE_BOTH>;
linux,code = <KEY_2>;
label = "SW2";
wakeup-source;
};
key-3 {
- interrupt-parent = <&irqc>;
- interrupts = <5 IRQ_TYPE_EDGE_BOTH>;
+ interrupts-extended = <&irqc 5 IRQ_TYPE_EDGE_BOTH>;
linux,code = <KEY_3>;
label = "SW3";
wakeup-source;
@@ -283,3 +280,8 @@
pinctrl-0 = <&scif2_pins>;
status = "okay";
};
+
+&wdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/renesas/r7s72100.dtsi b/arch/arm/boot/dts/renesas/r7s72100.dtsi
index 08ea4c551ed0..b831bbc431ef 100644
--- a/arch/arm/boot/dts/renesas/r7s72100.dtsi
+++ b/arch/arm/boot/dts/renesas/r7s72100.dtsi
@@ -36,7 +36,7 @@
clock-div = <3>;
};
- bsc: bsc {
+ bsc: bus {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
@@ -332,9 +332,9 @@
<GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp8_clks R7S72100_CLK_MMCIF>;
+ dmas = <&dmac 0x2cc9>, <&dmac 0x2cca>;
+ dma-names = "tx", "rx";
power-domains = <&cpg_clocks>;
- reg-io-width = <4>;
- bus-width = <8>;
status = "disabled";
};
@@ -370,6 +370,37 @@
status = "disabled";
};
+ dmac: dma-controller@e8200000 {
+ compatible = "renesas,r7s72100-dmac",
+ "renesas,rz-dmac";
+ reg = <0xe8200000 0x1000>,
+ <0xfcfe1000 0x20>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 9 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 10 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 11 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 12 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 13 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 14 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 15 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 16 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 17 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 18 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 19 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 20 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 22 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 23 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 24 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ };
+
gic: interrupt-controller@e8201000 {
compatible = "arm,pl390";
#interrupt-cells = <3>;
diff --git a/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts b/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts
index cd2324b8e8ff..f69a7fe56b6e 100644
--- a/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts
+++ b/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts
@@ -55,8 +55,7 @@
pinctrl-0 = <&keyboard_pins>;
key-3 {
- interrupt-parent = <&irqc>;
- interrupts = <0 IRQ_TYPE_EDGE_BOTH>;
+ interrupts-extended = <&irqc 0 IRQ_TYPE_EDGE_BOTH>;
linux,code = <KEY_3>;
label = "SW3";
wakeup-source;
diff --git a/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
index 3d02f065f71c..58becc9fbffd 100644
--- a/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
+++ b/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
@@ -193,8 +193,7 @@
ethernet@8000000 {
compatible = "smsc,lan9220", "smsc,lan9115";
reg = <0x08000000 0x1000>;
- interrupt-parent = <&irqc1>;
- interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&irqc1 8 IRQ_TYPE_LEVEL_HIGH>;
phy-mode = "mii";
reg-io-width = <4>;
smsc,irq-active-high;
diff --git a/arch/arm/boot/dts/renesas/r8a73a4.dtsi b/arch/arm/boot/dts/renesas/r8a73a4.dtsi
index 85261684b5d5..2e19ebf9e2ba 100644
--- a/arch/arm/boot/dts/renesas/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a73a4.dtsi
@@ -428,7 +428,6 @@
interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks R8A73A4_CLK_MMCIF0>;
power-domains = <&pd_a3sp>;
- reg-io-width = <4>;
status = "disabled";
};
@@ -438,7 +437,6 @@
interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks R8A73A4_CLK_MMCIF1>;
power-domains = <&pd_a3sp>;
- reg-io-width = <4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
index e1ac2c161e73..04d24b6d8056 100644
--- a/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
+++ b/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
@@ -224,8 +224,7 @@
touchscreen@55 {
compatible = "sitronix,st1232";
reg = <0x55>;
- interrupt-parent = <&irqpin1>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqpin1 2 IRQ_TYPE_LEVEL_LOW>;
pinctrl-0 = <&st1232_pins>;
pinctrl-names = "default";
gpios = <&pfc 166 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7.dts b/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7.dts
index 64102b664055..6a8a0d2113b0 100644
--- a/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7.dts
+++ b/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7.dts
@@ -202,8 +202,7 @@
touch: touchpanel@38 {
compatible = "edt,edt-ft5406";
reg = <0x38>;
- interrupt-parent = <&gpio0>;
- interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio0 24 IRQ_TYPE_EDGE_FALLING>;
/* GP1_29 is also shared with audio codec reset pin */
reset-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
vcc-supply = <&vcc_3v3_tft1>;
diff --git a/arch/arm/boot/dts/renesas/r8a7742-iwg21m.dtsi b/arch/arm/boot/dts/renesas/r8a7742-iwg21m.dtsi
index b281a4d164b0..661cc5357b57 100644
--- a/arch/arm/boot/dts/renesas/r8a7742-iwg21m.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7742-iwg21m.dtsi
@@ -55,8 +55,7 @@
rtc@68 {
compatible = "ti,bq32000";
reg = <0x68>;
- interrupt-parent = <&gpio1>;
- interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio1 1 IRQ_TYPE_EDGE_FALLING>;
};
};
diff --git a/arch/arm/boot/dts/renesas/r8a7742.dtsi b/arch/arm/boot/dts/renesas/r8a7742.dtsi
index 3a5d6b434d09..9083d288cc33 100644
--- a/arch/arm/boot/dts/renesas/r8a7742.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7742.dtsi
@@ -1651,7 +1651,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7742_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
status = "disabled";
max-frequency = <97500000>;
};
@@ -1667,7 +1666,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7742_PD_ALWAYS_ON>;
resets = <&cpg 305>;
- reg-io-width = <4>;
status = "disabled";
max-frequency = <97500000>;
};
diff --git a/arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts b/arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts
index ff274bfcb664..9b16fe7ce713 100644
--- a/arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts
+++ b/arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts
@@ -73,8 +73,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc 0 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/renesas/r8a7743.dtsi b/arch/arm/boot/dts/renesas/r8a7743.dtsi
index 8833898d5557..58a06cf37784 100644
--- a/arch/arm/boot/dts/renesas/r8a7743.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7743.dtsi
@@ -1639,7 +1639,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
max-frequency = <97500000>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/renesas/r8a7744.dtsi b/arch/arm/boot/dts/renesas/r8a7744.dtsi
index c66c1102fb72..034244648d18 100644
--- a/arch/arm/boot/dts/renesas/r8a7744.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7744.dtsi
@@ -1639,7 +1639,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7744_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
max-frequency = <97500000>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm-dbhd-ca.dts b/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm-dbhd-ca.dts
index a0b574398055..5903c1f1356f 100644
--- a/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm-dbhd-ca.dts
+++ b/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm-dbhd-ca.dts
@@ -84,8 +84,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 0 IRQ_TYPE_LEVEL_LOW>;
clocks = <&cec_clock>;
clock-names = "cec";
pd-gpios = <&gpio2 24 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm.dts b/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm.dts
index 24411044ef6c..3ac2526a24a1 100644
--- a/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm.dts
+++ b/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm.dts
@@ -185,8 +185,7 @@
port-expander@44 {
compatible = "st,stmpe811";
reg = <0x44>;
- interrupt-parent = <&gpio4>;
- interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio4 4 IRQ_TYPE_LEVEL_LOW>;
/* 3.25 MHz ADC clock speed */
st,adc-freq = <1>;
diff --git a/arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts b/arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts
index 0a75e8c79acc..571615a50620 100644
--- a/arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts
+++ b/arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts
@@ -68,8 +68,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc>;
- interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc 8 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/renesas/r8a7745.dtsi b/arch/arm/boot/dts/renesas/r8a7745.dtsi
index 6ddde364782b..704fa6f3cbd0 100644
--- a/arch/arm/boot/dts/renesas/r8a7745.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7745.dtsi
@@ -1513,7 +1513,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
max-frequency = <97500000>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/renesas/r8a77470-iwg23s-sbc.dts b/arch/arm/boot/dts/renesas/r8a77470-iwg23s-sbc.dts
index 644802285249..e511eb425bc5 100644
--- a/arch/arm/boot/dts/renesas/r8a77470-iwg23s-sbc.dts
+++ b/arch/arm/boot/dts/renesas/r8a77470-iwg23s-sbc.dts
@@ -82,8 +82,7 @@
compatible = "ethernet-phy-id0022.1622",
"ethernet-phy-ieee802.3-c22";
reg = <3>;
- interrupt-parent = <&gpio5>;
- interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio5 16 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
};
};
@@ -151,8 +150,7 @@
hdmi@39 {
compatible = "sil,sii9022";
reg = <0x39>;
- interrupt-parent = <&gpio2>;
- interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 29 IRQ_TYPE_LEVEL_LOW>;
ports {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/renesas/r8a7778-bockw.dts b/arch/arm/boot/dts/renesas/r8a7778-bockw.dts
index a3f9d74e8877..a99d226f41a6 100644
--- a/arch/arm/boot/dts/renesas/r8a7778-bockw.dts
+++ b/arch/arm/boot/dts/renesas/r8a7778-bockw.dts
@@ -61,7 +61,7 @@
};
};
-&bsc {
+&lbsc {
flash@0 {
compatible = "cfi-flash";
reg = <0x0 0x04000000>;
@@ -96,8 +96,7 @@
reg = <0x18300000 0x1000>;
phy-mode = "mii";
- interrupt-parent = <&irqpin>;
- interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqpin 0 IRQ_TYPE_EDGE_FALLING>;
reg-io-width = <4>;
vddvario-supply = <&fixedregulator3v3>;
vdd33a-supply = <&fixedregulator3v3>;
diff --git a/arch/arm/boot/dts/renesas/r8a7778.dtsi b/arch/arm/boot/dts/renesas/r8a7778.dtsi
index b80e832c9277..859dd29dfce3 100644
--- a/arch/arm/boot/dts/renesas/r8a7778.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7778.dtsi
@@ -40,7 +40,7 @@
spi2 = &hspi2;
};
- bsc: bus@1c000000 {
+ lbsc: bus {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/renesas/r8a7779-marzen.dts b/arch/arm/boot/dts/renesas/r8a7779-marzen.dts
index 9b13e8d1538b..2920d87ea6ff 100644
--- a/arch/arm/boot/dts/renesas/r8a7779-marzen.dts
+++ b/arch/arm/boot/dts/renesas/r8a7779-marzen.dts
@@ -58,17 +58,15 @@
pinctrl-0 = <&keypad0_pins>;
pinctrl-names = "default";
- interrupt-parent = <&gpio0>;
-
key-1 {
- interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio0 17 IRQ_TYPE_EDGE_FALLING>;
linux,code = <KEY_1>;
label = "SW1-1";
wakeup-source;
debounce-interval = <20>;
};
key-2 {
- interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio0 18 IRQ_TYPE_EDGE_FALLING>;
linux,code = <KEY_2>;
label = "SW1-2";
wakeup-source;
@@ -251,8 +249,7 @@
pinctrl-names = "default";
phy-mode = "mii";
- interrupt-parent = <&irqpin0>;
- interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqpin0 1 IRQ_TYPE_EDGE_FALLING>;
smsc,irq-push-pull;
reg-io-width = <4>;
vddvario-supply = <&fixedregulator3v3>;
diff --git a/arch/arm/boot/dts/renesas/r8a7779.dtsi b/arch/arm/boot/dts/renesas/r8a7779.dtsi
index 1944703cba4f..e437c22f452d 100644
--- a/arch/arm/boot/dts/renesas/r8a7779.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7779.dtsi
@@ -704,7 +704,7 @@
};
};
- lbsc: lbsc {
+ lbsc: bus {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/renesas/r8a7790-lager.dts b/arch/arm/boot/dts/renesas/r8a7790-lager.dts
index 8590981245a6..3bce5876a9d8 100644
--- a/arch/arm/boot/dts/renesas/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/renesas/r8a7790-lager.dts
@@ -79,28 +79,28 @@
pinctrl-0 = <&keyboard_pins>;
pinctrl-names = "default";
- one {
+ key-1 {
linux,code = <KEY_1>;
label = "SW2-1";
wakeup-source;
debounce-interval = <20>;
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
};
- two {
+ key-2 {
linux,code = <KEY_2>;
label = "SW2-2";
wakeup-source;
debounce-interval = <20>;
gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
};
- three {
+ key-3 {
linux,code = <KEY_3>;
label = "SW2-3";
wakeup-source;
debounce-interval = <20>;
gpios = <&gpio1 26 GPIO_ACTIVE_LOW>;
};
- four {
+ key-4 {
linux,code = <KEY_4>;
label = "SW2-4";
wakeup-source;
@@ -365,8 +365,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 15 IRQ_TYPE_LEVEL_LOW>;
clocks = <&cec_clock>;
clock-names = "cec";
@@ -403,8 +402,7 @@
hdmi-in@4c {
compatible = "adi,adv7612";
reg = <0x4c>;
- interrupt-parent = <&gpio1>;
- interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 20 IRQ_TYPE_LEVEL_LOW>;
default-input = <0>;
ports {
@@ -444,8 +442,7 @@
pmic@58 {
compatible = "dlg,da9063";
reg = <0x58>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -461,8 +458,7 @@
vdd_dvfs: regulator@68 {
compatible = "dlg,da9210";
reg = <0x68>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
@@ -692,8 +688,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc0>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 0 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio5 31 GPIO_ACTIVE_LOW>;
};
@@ -890,7 +885,7 @@
status = "okay";
pinctrl-0 = <&hsusb_pins>;
pinctrl-names = "default";
- renesas,enable-gpio = <&gpio5 18 GPIO_ACTIVE_HIGH>;
+ renesas,enable-gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
};
&usbphy {
diff --git a/arch/arm/boot/dts/renesas/r8a7790-stout.dts b/arch/arm/boot/dts/renesas/r8a7790-stout.dts
index 683f7395fab0..d7c0a9574ce8 100644
--- a/arch/arm/boot/dts/renesas/r8a7790-stout.dts
+++ b/arch/arm/boot/dts/renesas/r8a7790-stout.dts
@@ -211,8 +211,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc0>;
- interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 1 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
};
@@ -300,8 +299,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 15 IRQ_TYPE_LEVEL_LOW>;
clocks = <&osc4_clk>;
clock-names = "cec";
@@ -344,8 +342,7 @@
pmic@58 {
compatible = "dlg,da9063";
reg = <0x58>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -365,8 +362,7 @@
vdd_dvfs: regulator@68 {
compatible = "dlg,da9210";
reg = <0x68>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
@@ -377,8 +373,7 @@
vdd: regulator@70 {
compatible = "dlg,da9210";
reg = <0x70>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
diff --git a/arch/arm/boot/dts/renesas/r8a7790.dtsi b/arch/arm/boot/dts/renesas/r8a7790.dtsi
index 20e4d4c6e748..f746f0b9e686 100644
--- a/arch/arm/boot/dts/renesas/r8a7790.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7790.dtsi
@@ -1686,7 +1686,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
status = "disabled";
max-frequency = <97500000>;
};
@@ -1702,7 +1701,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
resets = <&cpg 305>;
- reg-io-width = <4>;
status = "disabled";
max-frequency = <97500000>;
};
diff --git a/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts b/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts
index 0efd9f98c75a..e4e1d9c98c61 100644
--- a/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts
@@ -397,8 +397,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio3>;
- interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 29 IRQ_TYPE_LEVEL_LOW>;
clocks = <&cec_clock>;
clock-names = "cec";
@@ -435,8 +434,7 @@
hdmi-in@4c {
compatible = "adi,adv7612";
reg = <0x4c>;
- interrupt-parent = <&gpio4>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio4 2 IRQ_TYPE_LEVEL_LOW>;
default-input = <0>;
ports {
@@ -659,8 +657,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc0>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 0 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
};
@@ -816,8 +813,7 @@
pmic@58 {
compatible = "dlg,da9063";
reg = <0x58>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -833,8 +829,7 @@
vdd_dvfs: regulator@68 {
compatible = "dlg,da9210";
reg = <0x68>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
@@ -859,7 +854,7 @@
status = "okay";
pinctrl-0 = <&usb0_pins>;
pinctrl-names = "default";
- renesas,enable-gpio = <&gpio5 31 GPIO_ACTIVE_HIGH>;
+ renesas,enable-gpios = <&gpio5 31 GPIO_ACTIVE_HIGH>;
};
&usbphy {
diff --git a/arch/arm/boot/dts/renesas/r8a7791-porter.dts b/arch/arm/boot/dts/renesas/r8a7791-porter.dts
index 93c86e921645..08381498350a 100644
--- a/arch/arm/boot/dts/renesas/r8a7791-porter.dts
+++ b/arch/arm/boot/dts/renesas/r8a7791-porter.dts
@@ -194,8 +194,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio3>;
- interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 29 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&reg_1p8v>;
dvdd-supply = <&reg_1p8v>;
@@ -329,8 +328,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc0>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 0 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
};
@@ -410,8 +408,7 @@
pmic@5a {
compatible = "dlg,da9063l";
reg = <0x5a>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -423,8 +420,7 @@
vdd_dvfs: regulator@68 {
compatible = "dlg,da9210";
reg = <0x68>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
diff --git a/arch/arm/boot/dts/renesas/r8a7791.dtsi b/arch/arm/boot/dts/renesas/r8a7791.dtsi
index f9c9e1d8f669..e57567adff55 100644
--- a/arch/arm/boot/dts/renesas/r8a7791.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7791.dtsi
@@ -1680,7 +1680,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
status = "disabled";
max-frequency = <97500000>;
};
diff --git a/arch/arm/boot/dts/renesas/r8a7792-blanche.dts b/arch/arm/boot/dts/renesas/r8a7792-blanche.dts
index 540a9ad28f28..a3986076d8e3 100644
--- a/arch/arm/boot/dts/renesas/r8a7792-blanche.dts
+++ b/arch/arm/boot/dts/renesas/r8a7792-blanche.dts
@@ -224,8 +224,7 @@
compatible = "smsc,lan89218", "smsc,lan9115";
reg = <0x18000000 0x100>;
phy-mode = "mii";
- interrupt-parent = <&irqc>;
- interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqc 0 IRQ_TYPE_EDGE_FALLING>;
smsc,irq-push-pull;
reg-io-width = <4>;
vddvario-supply = <&d3_3v>;
@@ -336,8 +335,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&irqc>;
- interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqc 3 IRQ_TYPE_EDGE_FALLING>;
avdd-supply = <&d1_8v>;
dvdd-supply = <&d1_8v>;
@@ -378,8 +376,7 @@
reg = <0x58>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_irq_pins>;
- interrupt-parent = <&irqc>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc 2 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/renesas/r8a7792-wheat.dts b/arch/arm/boot/dts/renesas/r8a7792-wheat.dts
index 000f21a2a863..bfc780f7e396 100644
--- a/arch/arm/boot/dts/renesas/r8a7792-wheat.dts
+++ b/arch/arm/boot/dts/renesas/r8a7792-wheat.dts
@@ -115,8 +115,7 @@
compatible = "smsc,lan89218", "smsc,lan9115";
reg = <0x18000000 0x100>;
phy-mode = "mii";
- interrupt-parent = <&irqc>;
- interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqc 0 IRQ_TYPE_EDGE_FALLING>;
smsc,irq-push-pull;
smsc,save-mac-address;
reg-io-width = <4>;
diff --git a/arch/arm/boot/dts/renesas/r8a7792.dtsi b/arch/arm/boot/dts/renesas/r8a7792.dtsi
index dd3bc32668b7..08cbe6c13cee 100644
--- a/arch/arm/boot/dts/renesas/r8a7792.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7792.dtsi
@@ -84,7 +84,7 @@
clock-frequency = <0>;
};
- lbsc: lbsc {
+ lbsc: bus {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/renesas/r8a7793-gose.dts b/arch/arm/boot/dts/renesas/r8a7793-gose.dts
index 1ea6c757893b..2c05d7c2b377 100644
--- a/arch/arm/boot/dts/renesas/r8a7793-gose.dts
+++ b/arch/arm/boot/dts/renesas/r8a7793-gose.dts
@@ -383,8 +383,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio3>;
- interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 29 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&reg_1p8v>;
dvdd-supply = <&reg_1p8v>;
@@ -419,8 +418,7 @@
hdmi-in@4c {
compatible = "adi,adv7612";
reg = <0x4c>;
- interrupt-parent = <&gpio4>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio4 2 IRQ_TYPE_LEVEL_LOW>;
default-input = <0>;
ports {
@@ -622,8 +620,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc0>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 0 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
};
@@ -756,8 +753,7 @@
pmic@58 {
compatible = "dlg,da9063";
reg = <0x58>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -773,8 +769,7 @@
vdd_dvfs: regulator@68 {
compatible = "dlg,da9210";
reg = <0x68>;
- interrupt-parent = <&irqc0>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 2 IRQ_TYPE_LEVEL_LOW>;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
diff --git a/arch/arm/boot/dts/renesas/r8a7793.dtsi b/arch/arm/boot/dts/renesas/r8a7793.dtsi
index 24e66ddf37e0..e48e43cc6b03 100644
--- a/arch/arm/boot/dts/renesas/r8a7793.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7793.dtsi
@@ -1343,7 +1343,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
status = "disabled";
max-frequency = <97500000>;
};
diff --git a/arch/arm/boot/dts/renesas/r8a7794-alt.dts b/arch/arm/boot/dts/renesas/r8a7794-alt.dts
index b5ecafbb2e4d..f70e26aa83a0 100644
--- a/arch/arm/boot/dts/renesas/r8a7794-alt.dts
+++ b/arch/arm/boot/dts/renesas/r8a7794-alt.dts
@@ -96,28 +96,28 @@
pinctrl-0 = <&keyboard_pins>;
pinctrl-names = "default";
- one {
+ key-1 {
linux,code = <KEY_1>;
label = "SW2-1";
wakeup-source;
debounce-interval = <20>;
gpios = <&gpio3 9 GPIO_ACTIVE_LOW>;
};
- two {
+ key-2 {
linux,code = <KEY_2>;
label = "SW2-2";
wakeup-source;
debounce-interval = <20>;
gpios = <&gpio3 10 GPIO_ACTIVE_LOW>;
};
- three {
+ key-3 {
linux,code = <KEY_3>;
label = "SW2-3";
wakeup-source;
debounce-interval = <20>;
gpios = <&gpio3 11 GPIO_ACTIVE_LOW>;
};
- four {
+ key-4 {
linux,code = <KEY_4>;
label = "SW2-4";
wakeup-source;
@@ -381,8 +381,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc0>;
- interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 8 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
};
@@ -450,8 +449,7 @@
pmic@58 {
compatible = "dlg,da9063";
reg = <0x58>;
- interrupt-parent = <&gpio3>;
- interrupts = <31 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 31 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/renesas/r8a7794-silk.dts b/arch/arm/boot/dts/renesas/r8a7794-silk.dts
index 595e074085eb..2a0819311a3c 100644
--- a/arch/arm/boot/dts/renesas/r8a7794-silk.dts
+++ b/arch/arm/boot/dts/renesas/r8a7794-silk.dts
@@ -262,8 +262,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio5>;
- interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio5 23 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&d1_8v>;
dvdd-supply = <&d1_8v>;
@@ -415,8 +414,7 @@
compatible = "ethernet-phy-id0022.1537",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- interrupt-parent = <&irqc0>;
- interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc0 8 IRQ_TYPE_LEVEL_LOW>;
micrel,led-mode = <1>;
reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
};
@@ -436,8 +434,7 @@
pmic@58 {
compatible = "dlg,da9063";
reg = <0x58>;
- interrupt-parent = <&gpio3>;
- interrupts = <31 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 31 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/renesas/r8a7794.dtsi b/arch/arm/boot/dts/renesas/r8a7794.dtsi
index 8e6386a79aea..bc16c896c0f9 100644
--- a/arch/arm/boot/dts/renesas/r8a7794.dtsi
+++ b/arch/arm/boot/dts/renesas/r8a7794.dtsi
@@ -1349,7 +1349,6 @@
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
resets = <&cpg 315>;
- reg-io-width = <4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/renesas/sh73a0-kzm9g.dts b/arch/arm/boot/dts/renesas/sh73a0-kzm9g.dts
index 98897f710063..1ce07d0878dc 100644
--- a/arch/arm/boot/dts/renesas/sh73a0-kzm9g.dts
+++ b/arch/arm/boot/dts/renesas/sh73a0-kzm9g.dts
@@ -172,8 +172,7 @@
compatible = "smsc,lan9221", "smsc,lan9115";
reg = <0x10000000 0x100>;
phy-mode = "mii";
- interrupt-parent = <&irqpin0>;
- interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqpin0 3 IRQ_TYPE_EDGE_FALLING>;
reg-io-width = <4>;
smsc,irq-push-pull;
smsc,save-mac-address;
@@ -196,8 +195,7 @@
compass@c {
compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
- interrupt-parent = <&irqpin3>;
- interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqpin3 4 IRQ_TYPE_EDGE_FALLING>;
};
ak4648: codec@12 {
@@ -209,9 +207,8 @@
accelerometer@1d {
compatible = "adi,adxl345";
reg = <0x1d>;
- interrupt-parent = <&irqpin3>;
- interrupts = <2 IRQ_TYPE_LEVEL_HIGH>,
- <3 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&irqpin3 2 IRQ_TYPE_LEVEL_HIGH>,
+ <&irqpin3 3 IRQ_TYPE_LEVEL_HIGH>;
};
rtc@32 {
@@ -297,8 +294,7 @@
touchscreen@55 {
compatible = "sitronix,st1232";
reg = <0x55>;
- interrupt-parent = <&irqpin1>;
- interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqpin1 0 IRQ_TYPE_EDGE_FALLING>;
};
};
@@ -310,8 +306,7 @@
pcf8575: gpio@20 {
compatible = "nxp,pcf8575";
reg = <0x20>;
- interrupt-parent = <&irqpin2>;
- interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&irqpin2 3 IRQ_TYPE_EDGE_FALLING>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
diff --git a/arch/arm/boot/dts/renesas/sh73a0.dtsi b/arch/arm/boot/dts/renesas/sh73a0.dtsi
index 30c67acc4e35..c7cc17e3c3c5 100644
--- a/arch/arm/boot/dts/renesas/sh73a0.dtsi
+++ b/arch/arm/boot/dts/renesas/sh73a0.dtsi
@@ -273,7 +273,6 @@
<GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_MMCIF0>;
power-domains = <&pd_a3sp>;
- reg-io-width = <4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rockchip/Makefile b/arch/arm/boot/dts/rockchip/Makefile
index ab4cd9aab722..716f5540e438 100644
--- a/arch/arm/boot/dts/rockchip/Makefile
+++ b/arch/arm/boot/dts/rockchip/Makefile
@@ -2,6 +2,7 @@
dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rv1108-elgin-r1.dtb \
rv1108-evb.dtb \
+ rv1109-relfor-saib.dtb \
rv1109-sonoff-ihost.dtb \
rv1126-edgeble-neu2-io.dtb \
rv1126-sonoff-ihost.dtb \
diff --git a/arch/arm/boot/dts/rockchip/rk3036-kylin.dts b/arch/arm/boot/dts/rockchip/rk3036-kylin.dts
index e32c73d32f0a..4f928c7898e9 100644
--- a/arch/arm/boot/dts/rockchip/rk3036-kylin.dts
+++ b/arch/arm/boot/dts/rockchip/rk3036-kylin.dts
@@ -80,7 +80,7 @@
};
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -325,8 +325,8 @@
&i2c2 {
status = "okay";
- rt5616: rt5616@1b {
- compatible = "rt5616";
+ rt5616: audio-codec@1b {
+ compatible = "realtek,rt5616";
reg = <0x1b>;
clocks = <&cru SCLK_I2S_OUT>;
clock-names = "mclk";
diff --git a/arch/arm/boot/dts/rockchip/rk3036.dtsi b/arch/arm/boot/dts/rockchip/rk3036.dtsi
index 96279d1e02fe..63b9912be06a 100644
--- a/arch/arm/boot/dts/rockchip/rk3036.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3036.dtsi
@@ -384,12 +384,13 @@
};
};
- acodec: acodec-ana@20030000 {
- compatible = "rk3036-codec";
+ acodec: audio-codec@20030000 {
+ compatible = "rockchip,rk3036-codec";
reg = <0x20030000 0x4000>;
- rockchip,grf = <&grf>;
clock-names = "acodec_pclk";
clocks = <&cru PCLK_ACODEC>;
+ rockchip,grf = <&grf>;
+ #sound-dai-cells = <0>;
status = "disabled";
};
@@ -399,7 +400,6 @@
interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_HDMI>;
clock-names = "pclk";
- rockchip,grf = <&grf>;
pinctrl-names = "default";
pinctrl-0 = <&hdmi_ctl>;
#sound-dai-cells = <0>;
@@ -553,11 +553,11 @@
};
spi: spi@20074000 {
- compatible = "rockchip,rockchip-spi";
+ compatible = "rockchip,rk3036-spi";
reg = <0x20074000 0x1000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cru PCLK_SPI>, <&cru SCLK_SPI>;
- clock-names = "apb-pclk","spi_pclk";
+ clocks = <&cru SCLK_SPI>, <&cru PCLK_SPI>;
+ clock-names = "spiclk", "apb_pclk";
dmas = <&pdma 8>, <&pdma 9>;
dma-names = "tx", "rx";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts b/arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts
index f924d4d64c3d..c227691013ea 100644
--- a/arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts
+++ b/arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts
@@ -22,7 +22,7 @@
reg = <0x60000000 0x40000000>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm3 0 1000>;
regulator-name = "vdd_log";
@@ -34,7 +34,7 @@
status = "okay";
};
- vcc_sd0: fixed-regulator {
+ vcc_sd0: regulator-fixed {
compatible = "regulator-fixed";
regulator-name = "sdmmc-supply";
regulator-min-microvolt = <3000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts b/arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts
index f6e8d49a02ef..ada7dbfc06a5 100644
--- a/arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts
+++ b/arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts
@@ -19,7 +19,7 @@
reg = <0x60000000 0x40000000>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm3 0 1000>;
regulator-name = "vdd_log";
@@ -31,7 +31,7 @@
status = "okay";
};
- vcc_sd0: sdmmc-regulator {
+ vcc_sd0: regulator-sdmmc {
compatible = "regulator-fixed";
regulator-name = "sdmmc-supply";
regulator-min-microvolt = <3000000>;
@@ -41,7 +41,7 @@
vin-supply = <&vcc_io>;
};
- vsys: vsys-regulator {
+ vsys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts b/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts
index 4de9a45c4883..25c0bcf85a56 100644
--- a/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts
+++ b/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts
@@ -61,21 +61,21 @@
};
};
- vcc_2v5: vcc-2v5 {
+ vcc_2v5: regulator-vcc-2v5 {
compatible = "regulator-fixed";
regulator-name = "vcc_2v5";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
};
- vcc_io: vcc-io {
+ vcc_io: regulator-vcc-io {
compatible = "regulator-fixed";
regulator-name = "vcc_io";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
- vcc_host: usb-host-regulator {
+ vcc_host: regulator-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -89,7 +89,7 @@
vin-supply = <&vcc_io>;
};
- vcc_otg: usb-otg-regulator {
+ vcc_otg: regulator-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -103,7 +103,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>;
pinctrl-0 = <&sdmmc_pwr>;
@@ -115,7 +115,7 @@
vin-supply = <&vcc_io>;
};
- vcc_wifi: sdio-regulator {
+ vcc_wifi: regulator-sdio {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PD0 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts b/arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts
index 29d8e5bf88f5..b0b029f14643 100644
--- a/arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts
+++ b/arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts
@@ -42,7 +42,7 @@
};
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm3 0 1000>;
regulator-name = "vdd_log";
@@ -54,7 +54,7 @@
status = "okay";
};
- vsys: vsys-regulator {
+ vsys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-min-microvolt = <5000000>;
@@ -64,7 +64,7 @@
};
/* input for 5V_STDBY is VSYS or DC5V, selectable by jumper J4 */
- vcc_stdby: stdby-regulator {
+ vcc_stdby: regulator-stdby {
compatible = "regulator-fixed";
regulator-name = "5v_stdby";
regulator-min-microvolt = <5000000>;
@@ -73,7 +73,7 @@
regulator-boot-on;
};
- vcc_emmc: emmc-regulator {
+ vcc_emmc: regulator-emmc {
compatible = "regulator-fixed";
regulator-name = "emmc_vccq";
regulator-min-microvolt = <3000000>;
@@ -81,7 +81,7 @@
vin-supply = <&vsys>;
};
- vcc_sata: sata-regulator {
+ vcc_sata: regulator-sata {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
@@ -94,7 +94,7 @@
vin-supply = <&vcc_stdby>;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -106,7 +106,7 @@
vin-supply = <&vcc_io>;
};
- vcc_host: usb-host-regulator {
+ vcc_host: regulator-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -119,7 +119,7 @@
vin-supply = <&vcc_stdby>;
};
- vcc_otg: usb-otg-regulator {
+ vcc_otg: regulator-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3128-evb.dts b/arch/arm/boot/dts/rockchip/rk3128-evb.dts
index c7ab7fcdb436..3d27d921de76 100644
--- a/arch/arm/boot/dts/rockchip/rk3128-evb.dts
+++ b/arch/arm/boot/dts/rockchip/rk3128-evb.dts
@@ -24,7 +24,7 @@
reg = <0x60000000 0x40000000>;
};
- vcc5v0_otg: vcc5v0-otg-regulator {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
gpio = <&gpio0 26 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
@@ -34,7 +34,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
gpio = <&gpio2 23 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts b/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts
index 21c1678f4e91..21f824b09191 100644
--- a/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts
+++ b/arch/arm/boot/dts/rockchip/rk3128-xpi-3128.dts
@@ -38,7 +38,7 @@
};
};
- dc_5v: dc-5v-regulator {
+ dc_5v: regulator-dc-5v {
compatible = "regulator-fixed";
regulator-name = "DC_5V";
regulator-min-microvolt = <5000000>;
@@ -62,7 +62,7 @@
* This is a vbus-supply, which also supplies the GL852G usb hub,
* thus has to be always-on
*/
- host_pwr_5v: host-pwr-5v-regulator {
+ host_pwr_5v: regulator-host-pwr-5v {
compatible = "regulator-fixed";
gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;
startup-delay-us = <1500>;
@@ -111,7 +111,7 @@
};
};
- mcu3v3: mcu3v3-regulator {
+ mcu3v3: regulator-mcu3v3 {
compatible = "regulator-fixed";
regulator-name = "MCU3V3";
regulator-min-microvolt = <3300000>;
@@ -121,7 +121,7 @@
regulator-boot-on;
};
- vcc_ddr: vcc-ddr-regulator {
+ vcc_ddr: regulator-vcc-ddr {
compatible = "regulator-fixed";
regulator-name = "VCC_DDR";
regulator-min-microvolt = <1500000>;
@@ -131,7 +131,7 @@
regulator-boot-on;
};
- vcc_io: vcc-io-regulator {
+ vcc_io: regulator-vcc-io {
compatible = "regulator-fixed";
regulator-name = "VCC_IO";
regulator-min-microvolt = <3300000>;
@@ -141,7 +141,7 @@
regulator-boot-on;
};
- vcc_lan: vcc-lan-regulator {
+ vcc_lan: regulator-vcc-lan {
compatible = "regulator-fixed";
regulator-name = "VCC_LAN";
regulator-min-microvolt = <3300000>;
@@ -151,7 +151,7 @@
regulator-boot-on;
};
- vcc_sd: vcc-sd-regulator {
+ vcc_sd: regulator-vcc-sd {
compatible = "regulator-fixed";
gpio = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>;
startup-delay-us = <500>;
@@ -163,7 +163,7 @@
pinctrl-0 = <&sdmmc_pwren>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "VCC_SYS";
regulator-min-microvolt = <5000000>;
@@ -173,7 +173,7 @@
regulator-boot-on;
};
- vcc33_hdmi: vcc33-hdmi-regulator {
+ vcc33_hdmi: regulator-vcc33-hdmi {
compatible = "regulator-fixed";
regulator-name = "VCC33_HDMI";
regulator-min-microvolt = <3300000>;
@@ -183,7 +183,7 @@
regulator-boot-on;
};
- vcca_33: vcca-33-regulator {
+ vcca_33: regulator-vcca-33 {
compatible = "regulator-fixed";
regulator-name = "VCCA_33";
regulator-min-microvolt = <3300000>;
@@ -193,7 +193,7 @@
regulator-boot-on;
};
- vdd_11: vdd-11-regulator {
+ vdd_11: regulator-vdd-11 {
compatible = "regulator-fixed";
regulator-name = "VDD_11";
regulator-min-microvolt = <1100000>;
@@ -203,7 +203,7 @@
regulator-boot-on;
};
- vdd11_hdmi: vdd11-hdmi-regulator {
+ vdd11_hdmi: regulator-vdd11-hdmi {
compatible = "regulator-fixed";
regulator-name = "VDD11_HDMI";
regulator-min-microvolt = <1100000>;
@@ -213,7 +213,7 @@
regulator-boot-on;
};
- vdd_arm: vdd-arm-regulator {
+ vdd_arm: regulator-vdd-arm {
compatible = "pwm-regulator";
regulator-name = "VDD_ARM";
pwms = <&pwm1 0 25000 1>;
@@ -231,7 +231,7 @@
* driver does not implement regulator support we have to make
* sure here that the voltage never drops below 1050 mV.
*/
- vdd_log: vdd-log-regulator {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
regulator-name = "VDD_LOG";
pwms = <&pwm2 0 25000 1>;
diff --git a/arch/arm/boot/dts/rockchip/rk3188-bqedison2qc.dts b/arch/arm/boot/dts/rockchip/rk3188-bqedison2qc.dts
index 9312be362a7a..edc2b7f9112d 100644
--- a/arch/arm/boot/dts/rockchip/rk3188-bqedison2qc.dts
+++ b/arch/arm/boot/dts/rockchip/rk3188-bqedison2qc.dts
@@ -130,7 +130,7 @@
reset-gpios = <&gpio3 RK_PD0 GPIO_ACTIVE_LOW>;
};
- avdd_cif: cif-avdd-regulator {
+ avdd_cif: regulator-cif-avdd {
compatible = "regulator-fixed";
regulator-name = "avdd-cif";
regulator-min-microvolt = <2800000>;
@@ -142,7 +142,7 @@
vin-supply = <&vcc28_cif>;
};
- vcc_5v: vcc-5v-regulator {
+ vcc_5v: regulator-vcc-5v {
compatible = "regulator-fixed";
regulator-name = "vcc-5v";
regulator-min-microvolt = <5000000>;
@@ -154,7 +154,7 @@
vin-supply = <&vsys>;
};
- vcc_lcd: lcd-regulator {
+ vcc_lcd: regulator-lcd {
compatible = "regulator-fixed";
regulator-name = "vcc-lcd";
gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>;
@@ -164,7 +164,7 @@
vin-supply = <&vcc_io>;
};
- vcc_otg: usb-otg-regulator {
+ vcc_otg: regulator-usb-otg {
compatible = "regulator-fixed";
regulator-name = "vcc-otg";
regulator-min-microvolt = <5000000>;
@@ -177,7 +177,7 @@
vin-supply = <&vcc_5v>;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
regulator-name = "vcc-sd";
regulator-min-microvolt = <3300000>;
@@ -189,7 +189,7 @@
vin-supply = <&vcc_io>;
};
- vccq_emmc: emmc-vccq-regulator {
+ vccq_emmc: regulator-emmc-vccq {
compatible = "regulator-fixed";
regulator-name = "vccq-emmc";
regulator-min-microvolt = <2800000>;
@@ -198,7 +198,7 @@
};
/* supplied from the bq24196 */
- vsys: vsys-regulator {
+ vsys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3188-px3-evb.dts b/arch/arm/boot/dts/rockchip/rk3188-px3-evb.dts
index 0a1ae689b162..32f36d7a7d28 100644
--- a/arch/arm/boot/dts/rockchip/rk3188-px3-evb.dts
+++ b/arch/arm/boot/dts/rockchip/rk3188-px3-evb.dts
@@ -39,7 +39,7 @@
};
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3188-radxarock.dts b/arch/arm/boot/dts/rockchip/rk3188-radxarock.dts
index 118deacd38c4..1f31c0a6774f 100644
--- a/arch/arm/boot/dts/rockchip/rk3188-radxarock.dts
+++ b/arch/arm/boot/dts/rockchip/rk3188-radxarock.dts
@@ -78,7 +78,7 @@
pinctrl-0 = <&ir_recv_pin>;
};
- vcc_otg: usb-otg-regulator {
+ vcc_otg: regulator-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PD7 GPIO_ACTIVE_HIGH>;
@@ -91,7 +91,7 @@
regulator-boot-on;
};
- vcc_sd0: sdmmc-regulator {
+ vcc_sd0: regulator-sdmmc {
compatible = "regulator-fixed";
regulator-name = "sdmmc-supply";
regulator-min-microvolt = <3300000>;
@@ -103,7 +103,7 @@
vin-supply = <&vcc_io>;
};
- vcc_host: usb-host-regulator {
+ vcc_host: regulator-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -116,7 +116,7 @@
regulator-boot-on;
};
- vsys: vsys-regulator {
+ vsys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3228-evb.dts b/arch/arm/boot/dts/rockchip/rk3228-evb.dts
index 69a5e239ed1a..a450cf31a0be 100644
--- a/arch/arm/boot/dts/rockchip/rk3228-evb.dts
+++ b/arch/arm/boot/dts/rockchip/rk3228-evb.dts
@@ -17,7 +17,7 @@
reg = <0x60000000 0x40000000>;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
enable-active-high;
regulator-name = "vcc_phy";
diff --git a/arch/arm/boot/dts/rockchip/rk3229-evb.dts b/arch/arm/boot/dts/rockchip/rk3229-evb.dts
index 5c3d08e3eea3..c35757d2b5dc 100644
--- a/arch/arm/boot/dts/rockchip/rk3229-evb.dts
+++ b/arch/arm/boot/dts/rockchip/rk3229-evb.dts
@@ -18,7 +18,7 @@
reg = <0x60000000 0x40000000>;
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -34,7 +34,7 @@
#clock-cells = <0>;
};
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;
@@ -46,7 +46,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
enable-active-high;
regulator-name = "vcc_phy";
@@ -57,7 +57,7 @@
vin-supply = <&vccio_1v8>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -67,7 +67,7 @@
vin-supply = <&dc_12v>;
};
- vccio_1v8: vccio-1v8-regulator {
+ vccio_1v8: regulator-vccio-1v8 {
compatible = "regulator-fixed";
regulator-name = "vccio_1v8";
regulator-min-microvolt = <1800000>;
@@ -76,7 +76,7 @@
vin-supply = <&vcc_sys>;
};
- vccio_3v3: vccio-3v3-regulator {
+ vccio_3v3: regulator-vccio-3v3 {
compatible = "regulator-fixed";
regulator-name = "vccio_3v3";
regulator-min-microvolt = <3300000>;
@@ -85,7 +85,7 @@
vin-supply = <&vcc_sys>;
};
- vdd_arm: vdd-arm-regulator {
+ vdd_arm: regulator-vdd-arm {
compatible = "pwm-regulator";
pwms = <&pwm1 0 25000 1>;
pwm-supply = <&vcc_sys>;
@@ -96,7 +96,7 @@
regulator-boot-on;
};
- vdd_log: vdd-log-regulator {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc_sys>;
diff --git a/arch/arm/boot/dts/rockchip/rk3229-xms6.dts b/arch/arm/boot/dts/rockchip/rk3229-xms6.dts
index 7bfbfd11fb55..28333449c43a 100644
--- a/arch/arm/boot/dts/rockchip/rk3229-xms6.dts
+++ b/arch/arm/boot/dts/rockchip/rk3229-xms6.dts
@@ -20,7 +20,7 @@
reg = <0x60000000 0x40000000>;
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -51,7 +51,7 @@
<&gpio2 29 GPIO_ACTIVE_LOW>;
};
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;
@@ -63,7 +63,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
enable-active-high;
regulator-name = "vcc_phy";
@@ -74,7 +74,7 @@
vin-supply = <&vccio_1v8>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -84,7 +84,7 @@
vin-supply = <&dc_12v>;
};
- vccio_1v8: vccio-1v8-regulator {
+ vccio_1v8: regulator-vccio-1v8 {
compatible = "regulator-fixed";
regulator-name = "vccio_1v8";
regulator-min-microvolt = <1800000>;
@@ -93,7 +93,7 @@
vin-supply = <&vcc_sys>;
};
- vccio_3v3: vccio-3v3-regulator {
+ vccio_3v3: regulator-vccio-3v3 {
compatible = "regulator-fixed";
regulator-name = "vccio_3v3";
regulator-min-microvolt = <3300000>;
@@ -102,7 +102,7 @@
vin-supply = <&vcc_sys>;
};
- vdd_arm: vdd-arm-regulator {
+ vdd_arm: regulator-vdd-arm {
compatible = "pwm-regulator";
pwms = <&pwm1 0 25000 1>;
pwm-supply = <&vcc_sys>;
@@ -113,7 +113,7 @@
regulator-boot-on;
};
- vdd_log: vdd-log-regulator {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc_sys>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-evb-act8846.dts b/arch/arm/boot/dts/rockchip/rk3288-evb-act8846.dts
index 8a635c243127..e1821fadbe7a 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-evb-act8846.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-evb-act8846.dts
@@ -7,7 +7,7 @@
model = "Rockchip RK3288 EVB ACT8846";
compatible = "rockchip,rk3288-evb-act8846", "rockchip,rk3288";
- vcc_lcd: vcc-lcd {
+ vcc_lcd: regulator-vcc-lcd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio7 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -17,7 +17,7 @@
vin-supply = <&vcc_io>;
};
- vcc_wl: vcc-wl {
+ vcc_wl: regulator-vcc-wl {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio7 RK_PB1 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-evb.dtsi b/arch/arm/boot/dts/rockchip/rk3288-evb.dtsi
index 382d2839cf47..11bb970c6112 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-evb.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-evb.dtsi
@@ -129,7 +129,7 @@
};
/* This turns on USB vbus for both host0 (ehci) and host1 (dwc2) */
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -140,7 +140,7 @@
regulator-boot-on;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -153,7 +153,7 @@
regulator-boot-on;
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -167,7 +167,7 @@
* vcc_io directly. Those boards won't be able to power cycle SD cards
* but it shouldn't hurt to toggle this pin there anyway.
*/
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/rockchip/rk3288-firefly-reload-core.dtsi b/arch/arm/boot/dts/rockchip/rk3288-firefly-reload-core.dtsi
index 36efa36b7190..59029483741b 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-firefly-reload-core.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-firefly-reload-core.dtsi
@@ -21,7 +21,7 @@
};
- vcc_flash: flash-regulator {
+ vcc_flash: regulator-flash {
compatible = "regulator-fixed";
regulator-name = "vcc_flash";
regulator-min-microvolt = <1800000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-firefly-reload.dts b/arch/arm/boot/dts/rockchip/rk3288-firefly-reload.dts
index a5a0826341e6..a55270672732 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-firefly-reload.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-firefly-reload.dts
@@ -85,7 +85,7 @@
#sound-dai-cells = <0>;
};
- vcc_host_5v: usb-host-regulator {
+ vcc_host_5v: regulator-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -98,7 +98,7 @@
vin-supply = <&vcc_5v>;
};
- vcc_5v: vcc_sys: vsys-regulator {
+ vcc_5v: vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_5v";
regulator-min-microvolt = <5000000>;
@@ -107,7 +107,7 @@
regulator-boot-on;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -119,7 +119,7 @@
vin-supply = <&vcc_io>;
};
- vcc_otg_5v: usb-otg-regulator {
+ vcc_otg_5v: regulator-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
@@ -132,7 +132,7 @@
vin-supply = <&vcc_5v>;
};
- dovdd_1v8: dovdd-1v8-regulator {
+ dovdd_1v8: regulator-dovdd-1v8 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
@@ -144,7 +144,7 @@
vin-supply = <&vcc_io>;
};
- vcc28_dvp: vcc28-dvp-regulator {
+ vcc28_dvp: regulator-vcc28-dvp {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
@@ -156,7 +156,7 @@
vin-supply = <&vcc_io>;
};
- af_28: af_28-regulator {
+ af_28: regulator-af-28 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
@@ -168,7 +168,7 @@
vin-supply = <&vcc_io>;
};
- dvdd_1v2: af_28-regulator {
+ dvdd_1v2: regulator-dvdd-1v2 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio7 RK_PB4 GPIO_ACTIVE_HIGH>;
@@ -180,7 +180,7 @@
vin-supply = <&vcc_io>;
};
- vbat_wl: wifi-regulator {
+ vbat_wl: regulator-wifi {
compatible = "regulator-fixed";
regulator-name = "vbat_wl";
regulator-min-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-firefly.dtsi b/arch/arm/boot/dts/rockchip/rk3288-firefly.dtsi
index 3836c61cfb76..187d4f0a52eb 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-firefly.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-firefly.dtsi
@@ -25,7 +25,7 @@
};
};
- dovdd_1v8: dovdd-1v8-regulator {
+ dovdd_1v8: regulator-dovdd-1v8 {
compatible = "regulator-fixed";
regulator-name = "dovdd_1v8";
regulator-min-microvolt = <1800000>;
@@ -79,7 +79,7 @@
};
};
- vbat_wl: vcc_sys: vsys-regulator {
+ vbat_wl: vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -88,7 +88,7 @@
regulator-boot-on;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -100,7 +100,7 @@
vin-supply = <&vcc_io>;
};
- vcc_flash: flash-regulator {
+ vcc_flash: regulator-flash {
compatible = "regulator-fixed";
regulator-name = "vcc_flash";
regulator-min-microvolt = <1800000>;
@@ -108,7 +108,7 @@
vin-supply = <&vcc_io>;
};
- vcc_5v: usb-regulator {
+ vcc_5v: regulator-usb {
compatible = "regulator-fixed";
regulator-name = "vcc_5v";
regulator-min-microvolt = <5000000>;
@@ -118,7 +118,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_host_5v: usb-host-regulator {
+ vcc_host_5v: regulator-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -131,7 +131,7 @@
vin-supply = <&vcc_5v>;
};
- vcc_otg_5v: usb-otg-regulator {
+ vcc_otg_5v: regulator-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
@@ -148,7 +148,7 @@
* A TT8142 creates both dovdd_1v8 and vcc28_dvp, controlled
* by the dvp_pwr pin.
*/
- vcc28_dvp: vcc28-dvp-regulator {
+ vcc28_dvp: regulator-vcc28-dvp {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-miqi.dts b/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
index db1eb648e0e1..dd42f8d31f70 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
@@ -37,7 +37,7 @@
};
};
- vcc_flash: flash-regulator {
+ vcc_flash: regulator-flash {
compatible = "regulator-fixed";
regulator-name = "vcc_flash";
regulator-min-microvolt = <1800000>;
@@ -45,7 +45,7 @@
vin-supply = <&vcc_io>;
};
- vcc_host: usb-host-regulator {
+ vcc_host: regulator-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -58,7 +58,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -70,7 +70,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-phycore-rdk.dts b/arch/arm/boot/dts/rockchip/rk3288-phycore-rdk.dts
index 1a5156951492..10ce0554d4fc 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-phycore-rdk.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-phycore-rdk.dts
@@ -35,7 +35,7 @@
};
};
- vcc_host0_5v: usb-host0-regulator {
+ vcc_host0_5v: regulator-usb-host0 {
compatible = "regulator-fixed";
gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
@@ -47,7 +47,7 @@
vin-supply = <&vdd_in_otg_out>;
};
- vcc_host1_5v: usb-host1-regulator {
+ vcc_host1_5v: regulator-usb-host1 {
compatible = "regulator-fixed";
gpio = <&gpio2 0 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
@@ -59,7 +59,7 @@
vin-supply = <&vdd_in_otg_out>;
};
- vcc_otg_5v: usb-otg-regulator {
+ vcc_otg_5v: regulator-usb-otg {
compatible = "regulator-fixed";
gpio = <&gpio2 12 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/rockchip/rk3288-phycore-som.dtsi b/arch/arm/boot/dts/rockchip/rk3288-phycore-som.dtsi
index e43887c9635f..12ab10c4adde 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-phycore-som.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-phycore-som.dtsi
@@ -46,7 +46,7 @@
};
};
- vdd_emmc_io: vdd-emmc-io {
+ vdd_emmc_io: regulator-vdd-emmc-io {
compatible = "regulator-fixed";
regulator-name = "vdd_emmc_io";
regulator-min-microvolt = <1800000>;
@@ -54,7 +54,7 @@
vin-supply = <&vdd_3v3_io>;
};
- vdd_in_otg_out: vdd-in-otg-out {
+ vdd_in_otg_out: regulator-vdd-in-otg-out {
compatible = "regulator-fixed";
regulator-name = "vdd_in_otg_out";
regulator-always-on;
@@ -63,7 +63,7 @@
regulator-max-microvolt = <5000000>;
};
- vdd_misc_1v8: vdd-misc-1v8 {
+ vdd_misc_1v8: regulator-vdd-misc-1v8 {
compatible = "regulator-fixed";
regulator-name = "vdd_misc_1v8";
regulator-always-on;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-popmetal.dts b/arch/arm/boot/dts/rockchip/rk3288-popmetal.dts
index fd90f3b8fc32..560bc23c33b1 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-popmetal.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-popmetal.dts
@@ -47,7 +47,7 @@
pinctrl-0 = <&ir_int>;
};
- vcc_flash: flash-regulator {
+ vcc_flash: regulator-flash {
compatible = "regulator-fixed";
regulator-name = "vcc_flash";
regulator-min-microvolt = <1800000>;
@@ -55,7 +55,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -67,7 +67,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -80,7 +80,7 @@
* A PT5128 creates both dovdd_1v8 and vcc28_dvp, controlled
* by the dvp_pwr pin.
*/
- vcc18_dvp: vcc18-dvp-regulator {
+ vcc18_dvp: regulator-vcc18-dvp {
compatible = "regulator-fixed";
regulator-name = "vcc18-dvp";
regulator-min-microvolt = <1800000>;
@@ -88,7 +88,7 @@
vin-supply = <&vcc28_dvp>;
};
- vcc28_dvp: vcc28-dvp-regulator {
+ vcc28_dvp: regulator-vcc28-dvp {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-r89.dts b/arch/arm/boot/dts/rockchip/rk3288-r89.dts
index 633e5a032463..40c65dbfb1cd 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-r89.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-r89.dts
@@ -48,7 +48,7 @@
pinctrl-0 = <&ir_int>;
};
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -59,7 +59,7 @@
regulator-boot-on;
};
- vcc_otg: vcc-otg-regulator {
+ vcc_otg: regulator-vcc-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
@@ -70,7 +70,7 @@
regulator-boot-on;
};
- vcc_sdmmc: sdmmc-regulator {
+ vcc_sdmmc: regulator-sdmmc {
compatible = "regulator-fixed";
regulator-name = "sdmmc-supply";
regulator-min-microvolt = <3300000>;
@@ -80,7 +80,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: sys-regulator {
+ vcc_sys: regulator-sys {
compatible = "regulator-fixed";
regulator-name = "sys-supply";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-rock2-som.dtsi b/arch/arm/boot/dts/rockchip/rk3288-rock2-som.dtsi
index 76363b8afcb9..30f914f22a50 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-rock2-som.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-rock2-som.dtsi
@@ -23,7 +23,7 @@
clock-output-names = "ext_gmac";
};
- vcc_flash: flash-regulator {
+ vcc_flash: regulator-flash {
compatible = "regulator-fixed";
regulator-name = "vcc_flash";
regulator-min-microvolt = <1800000>;
@@ -32,7 +32,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-rock2-square.dts b/arch/arm/boot/dts/rockchip/rk3288-rock2-square.dts
index 13cfdaa95cc7..58a7270b87da 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-rock2-square.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-rock2-square.dts
@@ -70,7 +70,7 @@
};
};
- sata_pwr: sata-prw-regulator {
+ sata_pwr: regulator-sata-prw {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 13 GPIO_ACTIVE_HIGH>;
@@ -108,7 +108,7 @@
reset-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>;
};
- vcc_usb_host: vcc-host-regulator {
+ vcc_usb_host: regulator-vcc-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -117,7 +117,7 @@
regulator-name = "vcc_host";
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi b/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi
index 09618bb7d872..8e27a20f2845 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi
@@ -85,7 +85,7 @@
};
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -94,7 +94,7 @@
regulator-boot-on;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/rockchip/rk3288-veyron-brain.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-brain.dts
index aa33d09184ad..ade9cc291813 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-veyron-brain.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-brain.dts
@@ -14,11 +14,11 @@
compatible = "google,veyron-brain-rev0", "google,veyron-brain",
"google,veyron", "rockchip,rk3288";
- vcc33_sys: vcc33-sys {
+ vcc33_sys: regulator-vcc33-sys {
vin-supply = <&vcc_5v>;
};
- vcc33_io: vcc33_io {
+ vcc33_io: regulator-vcc33-io {
compatible = "regulator-fixed";
regulator-name = "vcc33_io";
regulator-always-on;
@@ -28,7 +28,7 @@
};
/* This turns on vbus for host2 and otg (dwc2) */
- vcc5_host2: vcc5-host2-regulator {
+ vcc5_host2: regulator-vcc5-host2 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi
index 092316be67f7..3677571b4d82 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi
@@ -43,23 +43,23 @@
};
/* A non-regulated voltage from power supply or battery */
- vccsys: vccsys {
+ vccsys: regulator-vccsys {
compatible = "regulator-fixed";
regulator-name = "vccsys";
regulator-boot-on;
regulator-always-on;
};
- vcc33_sys: vcc33-sys {
+ vcc33_sys: regulator-vcc33-sys {
vin-supply = <&vccsys>;
};
- vcc_5v: vcc-5v {
+ vcc_5v: regulator-vcc-5v {
vin-supply = <&vccsys>;
};
/* This turns on vbus for host1 (dwc2) */
- vcc5_host1: vcc5-host1-regulator {
+ vcc5_host1: regulator-vcc5-host1 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
@@ -71,7 +71,7 @@
};
/* This turns on vbus for otg for host mode (dwc2) */
- vcc5v_otg: vcc5v-otg-regulator {
+ vcc5v_otg: regulator-vcc5v-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-veyron-edp.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron-edp.dtsi
index 32c0f10765dd..fb031964fa2b 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-veyron-edp.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-edp.dtsi
@@ -6,7 +6,7 @@
*/
/ {
- backlight_regulator: backlight-regulator {
+ backlight_regulator: regulator-backlight {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
@@ -17,7 +17,7 @@
startup-delay-us = <15000>;
};
- panel_regulator: panel-regulator {
+ panel_regulator: regulator-panel {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-veyron-fievel.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-fievel.dts
index 309b122b4d0d..6a0844e16279 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-veyron-fievel.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-fievel.dts
@@ -18,7 +18,7 @@
"google,veyron-fievel-rev0", "google,veyron-fievel",
"google,veyron", "rockchip,rk3288";
- vccsys: vccsys {
+ vccsys: regulator-vccsys {
compatible = "regulator-fixed";
regulator-name = "vccsys";
regulator-boot-on;
@@ -29,14 +29,14 @@
* vcc33_pmuio and vcc33_io is sourced directly from vcc33_sys,
* enabled by vcc_18
*/
- vcc33_io: vcc33-io {
+ vcc33_io: regulator-vcc33-io {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
regulator-name = "vcc33_io";
};
- vcc5_host1: vcc5-host1-regulator {
+ vcc5_host1: regulator-vcc5-host1 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio5 RK_PC2 GPIO_ACTIVE_HIGH>;
@@ -47,7 +47,7 @@
regulator-boot-on;
};
- vcc5_host2: vcc5-host2-regulator {
+ vcc5_host2: regulator-vcc5-host2 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio5 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -58,7 +58,7 @@
regulator-boot-on;
};
- vcc5v_otg: vcc5v-otg-regulator {
+ vcc5v_otg: regulator-vcc5v-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-veyron-mickey.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-mickey.dts
index ffd1121d19be..d665c3e8862c 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-veyron-mickey.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-mickey.dts
@@ -18,11 +18,11 @@
"google,veyron-mickey-rev0", "google,veyron-mickey",
"google,veyron", "rockchip,rk3288";
- vcc_5v: vcc-5v {
+ vcc_5v: regulator-vcc-5v {
vin-supply = <&vcc33_sys>;
};
- vcc33_io: vcc33_io {
+ vcc33_io: regulator-vcc33-io {
compatible = "regulator-fixed";
regulator-name = "vcc33_io";
regulator-always-on;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts
index 6337238891eb..cc27d116d025 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts
@@ -14,8 +14,8 @@
compatible = "google,veyron-pinky-rev2", "google,veyron-pinky",
"google,veyron", "rockchip,rk3288";
- /delete-node/backlight-regulator;
- /delete-node/panel-regulator;
+ /delete-node/regulator-backlight;
+ /delete-node/regulator-panel;
/delete-node/emmc-pwrseq;
/delete-node/vcc18-lcd;
};
diff --git a/arch/arm/boot/dts/rockchip/rk3288-veyron.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron.dtsi
index d838bf0d5d9a..260d6c92cfd1 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-veyron.dtsi
@@ -75,7 +75,7 @@
reset-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>;
};
- vcc_5v: vcc-5v {
+ vcc_5v: regulator-vcc-5v {
compatible = "regulator-fixed";
regulator-name = "vcc_5v";
regulator-always-on;
@@ -84,7 +84,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc33_sys: vcc33-sys {
+ vcc33_sys: regulator-vcc33-sys {
compatible = "regulator-fixed";
regulator-name = "vcc33_sys";
regulator-always-on;
@@ -93,7 +93,7 @@
regulator-max-microvolt = <3300000>;
};
- vcc50_hdmi: vcc50-hdmi {
+ vcc50_hdmi: regulator-vcc50-hdmi {
compatible = "regulator-fixed";
regulator-name = "vcc50_hdmi";
regulator-always-on;
@@ -101,7 +101,7 @@
vin-supply = <&vcc_5v>;
};
- vdd_logic: vdd-logic {
+ vdd_logic: regulator-vdd-logic {
compatible = "pwm-regulator";
regulator-name = "vdd_logic";
diff --git a/arch/arm/boot/dts/rockchip/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rockchip/rk3288-vmarc-som.dtsi
index 793951655b73..44a9efc68f42 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-vmarc-som.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-vmarc-som.dtsi
@@ -11,7 +11,7 @@
/ {
compatible = "vamrs,rk3288-vmarc-som", "rockchip,rk3288";
- vccio_flash: vccio-flash-regulator {
+ vccio_flash: regulator-vccio-flash {
compatible = "regulator-fixed";
regulator-name = "vccio_flash";
regulator-min-microvolt = <1800000>;
diff --git a/arch/arm/boot/dts/rockchip/rk3288-vyasa.dts b/arch/arm/boot/dts/rockchip/rk3288-vyasa.dts
index b156a83eb7d7..1954475c69b6 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-vyasa.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-vyasa.dts
@@ -19,7 +19,7 @@
device_type = "memory";
};
- dc12_vbat: dc12-vbat {
+ dc12_vbat: regulator-dc12-vbat {
compatible = "regulator-fixed";
regulator-name = "dc12_vbat";
regulator-min-microvolt = <12000000>;
@@ -28,7 +28,7 @@
regulator-boot-on;
};
- vboot_3v3: vboot-3v3 {
+ vboot_3v3: regulator-vboot-3v3 {
compatible = "regulator-fixed";
regulator-name = "vboot_3v3";
regulator-min-microvolt = <3300000>;
@@ -38,7 +38,7 @@
vin-supply = <&dc12_vbat>;
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <3700000>;
@@ -48,7 +48,7 @@
vin-supply = <&dc12_vbat>;
};
- vboot_5v: vboot-5v {
+ vboot_5v: regulator-vboot-5v {
compatible = "regulator-fixed";
regulator-name = "vboot_sv";
regulator-min-microvolt = <5000000>;
@@ -58,7 +58,7 @@
vin-supply = <&dc12_vbat>;
};
- v3g_3v3: v3g-3v3 {
+ v3g_3v3: regulator-v3g-3v3 {
compatible = "regulator-fixed";
regulator-name = "v3g_3v3";
regulator-min-microvolt = <3300000>;
@@ -68,7 +68,7 @@
vin-supply = <&dc12_vbat>;
};
- vsus_5v: vsus-5v {
+ vsus_5v: regulator-vsus-5v {
compatible = "regulator-fixed";
regulator-name = "vsus_5v";
regulator-min-microvolt = <5000000>;
@@ -78,7 +78,7 @@
vin-supply = <&vcc_io>;
};
- vcc50_hdmi: vcc50-hdmi {
+ vcc50_hdmi: regulator-vcc50-hdmi {
compatible = "regulator-fixed";
regulator-name = "vcc50_hdmi";
enable-active-high;
@@ -90,7 +90,7 @@
vin-supply = <&vsus_5v>;
};
- vusb1_5v: vusb1-5v {
+ vusb1_5v: regulator-vusb1-5v {
compatible = "regulator-fixed";
regulator-name = "vusb1_5v";
enable-active-high;
@@ -102,7 +102,7 @@
vin-supply = <&vsus_5v>;
};
- vusb2_5v: vusb2-5v {
+ vusb2_5v: regulator-vusb2-5v {
compatible = "regulator-fixed";
regulator-name = "vusb2_5v";
enable-active-high;
diff --git a/arch/arm/boot/dts/rockchip/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip/rockchip-radxa-dalang-carrier.dtsi
index da1d548b7330..cf5e2ed356ef 100644
--- a/arch/arm/boot/dts/rockchip/rockchip-radxa-dalang-carrier.dtsi
+++ b/arch/arm/boot/dts/rockchip/rockchip-radxa-dalang-carrier.dtsi
@@ -23,7 +23,7 @@
pinctrl-0 = <&wifi_enable_h>;
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -32,7 +32,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -42,7 +42,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vbus_host: vbus-host {
+ vbus_host: regulator-vbus-host {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb1_en_oc>;
@@ -51,7 +51,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vbus_typec: vbus-typec {
+ vbus_typec: regulator-vbus-typec {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb0_en_oc>;
diff --git a/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts b/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts
index 89ca2f8d3809..3c64f0cca9eb 100644
--- a/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts
+++ b/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts
@@ -25,7 +25,7 @@
stdout-path = "serial2:1500000n8";
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rv1108-evb.dts b/arch/arm/boot/dts/rockchip/rv1108-evb.dts
index ef150f4ee99d..0b04a8325d54 100644
--- a/arch/arm/boot/dts/rockchip/rv1108-evb.dts
+++ b/arch/arm/boot/dts/rockchip/rv1108-evb.dts
@@ -60,7 +60,7 @@
pwms = <&pwm0 0 25000 0>;
};
- vcc_sys: vsys-regulator {
+ vcc_sys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/rockchip/rv1109-relfor-saib.dts b/arch/arm/boot/dts/rockchip/rv1109-relfor-saib.dts
new file mode 100644
index 000000000000..c13829d32c32
--- /dev/null
+++ b/arch/arm/boot/dts/rockchip/rv1109-relfor-saib.dts
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Relfor Labs Pvt. Ltd.
+ */
+
+
+/dts-v1/;
+#include "rv1109.dtsi"
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Rockchip RV1109 Relfor Saib Board";
+ compatible = "relfor,saib", "rockchip,rv1109";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button {
+ gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_DATA>;
+ label = "GPIO User Switch";
+ linux,input-type = <1>;
+ };
+ };
+
+ ir_receiver: ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_rx>;
+ };
+
+ ir_transmitter: ir-transmitter {
+ compatible = "pwm-ir-tx";
+ pwms = <&pwm11 0 10000000 1>;
+ };
+
+ led-controller {
+ compatible = "pwm-leds-multicolor";
+
+ multi-led {
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_INDICATOR;
+ max-brightness = <65535>;
+
+ led-0 {
+ active-low;
+ color = <LED_COLOR_ID_BLUE>;
+ pwms = <&pwm9 0 50000 0>;
+ };
+
+ led-1 {
+ active-low;
+ color = <LED_COLOR_ID_GREEN>;
+ pwms = <&pwm6 0 50000 0>;
+ };
+
+ led-2 {
+ active-low;
+ color = <LED_COLOR_ID_RED>;
+ pwms = <&pwm10 0 50000 0>;
+ };
+ };
+ };
+
+ pwm-leds {
+ compatible = "pwm-leds";
+
+ led-0 {
+ pwms = <&pwm2 0 50000 0>;
+ max-brightness = <255>;
+ linux,default-trigger = "none";
+ };
+
+ led-1 {
+ pwms = <&pwm8 0 50000 0>;
+ max-brightness = <0>;
+ linux,default-trigger = "none";
+ };
+
+ led-2 {
+ pwms = <&pwm5 0 50000 0>;
+ max-brightness = <255>;
+ linux,default-trigger = "none";
+ };
+ };
+
+ sdio_pwrseq: pwrseq-sdio {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rtc0>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h>;
+ reset-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_LOW>;
+ };
+
+ vcc_0v8: regulator-vcc-0v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_0v8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ startup-delay-us = <150>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc_1v2_ddr: regulator-vcc-1v2-ddr {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v2_ddr";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ startup-delay-us = <75000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc_1v8: regulator-vcc-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ startup-delay-us = <51000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc1v8_ir: regulator-vcc1v8-ir {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc1v8_ir";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc_2v5_ddr: regulator-vcc-2v5-ddr {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_2v5_ddr";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vcc3v3_sys: regulator-vcc3v3-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ startup-delay-us = <75000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_sys: regulator-vcc5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd_arm: regulator-vdd-arm {
+ compatible = "pwm-regulator";
+ pwms = <&pwm0 0 5000 1>;
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <720000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-settling-time-up-us = <18000>;
+ regulator-always-on;
+ regulator-boot-on;
+ pwm-supply = <&vcc3v3_sys>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vdd_npu_vepu: regulator-vdd-npu-vepu {
+ compatible = "pwm-regulator";
+ pwms = <&pwm1 0 5000 1>;
+ regulator-name = "vdd_npu_vepu";
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <950000>;
+ regulator-settling-time-up-us = <18000>;
+ regulator-always-on;
+ regulator-boot-on;
+ pwm-supply = <&vcc3v3_sys>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ thermal_sensor1: thermal-sensor1 {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&saradc 1>;
+ io-channel-names = "sensor-channel";
+ temperature-lookup-table = <(-40000) 826
+ 85000 609>;
+ };
+
+ thermal_sensor2: thermal-sensor2 {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&saradc 2>;
+ io-channel-names = "sensor-channel";
+ temperature-lookup-table = <(-40000) 826
+ 85000 609>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&emmc {
+ bus-width = <8>;
+ non-removable;
+ pinctrl-0 = <&emmc_bus8 &emmc_cmd &emmc_clk>;
+ pinctrl-names = "default";
+ rockchip,default-sample-phase = <90>;
+ vmmc-supply = <&vcc3v3_sys>;
+ status = "okay";
+};
+
+&i2c3 {
+ pinctrl-0 = <&i2c3m2_xfer>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ rtc0: rtc@52 {
+ compatible = "microcrystal,rv3028";
+ reg = <0x52>;
+ #clock-cells = <0>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&rtc_int>;
+ pinctrl-names = "default";
+ };
+};
+
+&i2s0 {
+ /delete-property/ pinctrl-0;
+ rockchip,trcm-sync-rx-only;
+ pinctrl-0 = <&i2s0m0_sclk_rx>,
+ <&i2s0m0_lrck_rx>,
+ <&i2s0m0_sdi0>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pinctrl {
+ bluetooth-pins {
+ bt_reset: bt-reset {
+ rockchip,pins =
+ <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ bt_wake_dev: bt-wake-dev {
+ rockchip,pins =
+ <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ bt_wake_host: bt-wake-host {
+ rockchip,pins =
+ <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ buttons {
+ switch: switch {
+ rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ ir {
+ ir_rx: ir-rx {
+ rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pwm {
+ pwm0m0_pins_pull_up: pwm0m0-pins-pull-up {
+ rockchip,pins =
+ /* pwm0_pin_m0 */
+ <0 RK_PB6 3 &pcfg_pull_up>;
+ };
+ pwm1m0_pins_pull_up: pwm1m0-pins-pull-up {
+ rockchip,pins =
+ /* pwm1_pin_m0 */
+ <0 RK_PB7 3 &pcfg_pull_up>;
+ };
+ };
+
+ rtc {
+ rtc_int: rtc-int {
+ rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ sdio-pwrseq {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio0-supply = <&vcc3v3_sys>;
+ pmuio1-supply = <&vcc3v3_sys>;
+ vccio4-supply = <&vcc3v3_sys>;
+ vccio5-supply = <&vcc3v3_sys>;
+ vccio6-supply = <&vcc3v3_sys>;
+ vccio7-supply = <&vcc3v3_sys>;
+ status = "okay";
+};
+
+&pwm0 {
+ /delete-property/ pinctrl-0;
+ pinctrl-0 = <&pwm0m0_pins_pull_up>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm1 {
+ /delete-property/ pinctrl-0;
+ pinctrl-0 = <&pwm1m0_pins_pull_up>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm2 {
+ /delete-property/ pinctrl-0;
+ pinctrl-0 = <&pwm2m1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm5 {
+ pinctrl-0 = <&pwm5m0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm6 {
+ pinctrl-0 = <&pwm6m0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm8 {
+ pinctrl-0 = <&pwm8m1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm9 {
+ pinctrl-0 = <&pwm9m1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm10 {
+ pinctrl-0 = <&pwm10m1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&pwm11 {
+ /delete-property/ pinctrl-0;
+ pinctrl-0 = <&pwm11m1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdio {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ max-frequency = <100000000>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ no-mmc;
+ no-sd;
+ non-removable;
+ pinctrl-0 = <&sdmmc1_clk &sdmmc1_cmd &sdmmc1_bus4>;
+ pinctrl-names = "default";
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_sys>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_xfer &uart0_ctsn &uart0_rtsn>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ bluetooth {
+ compatible = "realtek,rtl8822cs-bt";
+ device-wake-gpios = <&gpio1 RK_PC5 GPIO_ACTIVE_HIGH>;
+ enable-gpios = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>;
+ host-wake-gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&bt_reset>, <&bt_wake_dev>, <&bt_wake_host>;
+ pinctrl-names = "default";
+ };
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m1_xfer>;
+ pinctrl-names = "default";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
index 7707d1b01440..d4e93d7c57a6 100644
--- a/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
+++ b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts
@@ -21,7 +21,7 @@
stdout-path = "serial2:1500000n8";
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -30,7 +30,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -40,7 +40,7 @@
vin-supply = <&vcc12v_dcin>;
};
- v3v3_sys: v3v3-sys-regulator {
+ v3v3_sys: regulator-v3v3-sys {
compatible = "regulator-fixed";
regulator-name = "v3v3_sys";
regulator-always-on;
diff --git a/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2.dtsi b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2.dtsi
index 7ea8d7d16f5f..5c1b60deb51b 100644
--- a/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2.dtsi
+++ b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2.dtsi
@@ -11,7 +11,7 @@
mmc0 = &emmc;
};
- vccio_flash: vccio-flash-regulator {
+ vccio_flash: regulator-vccio-flash {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/rockchip/rv1126.dtsi b/arch/arm/boot/dts/rockchip/rv1126.dtsi
index 434846b85c95..d6e8b63daa42 100644
--- a/arch/arm/boot/dts/rockchip/rv1126.dtsi
+++ b/arch/arm/boot/dts/rockchip/rv1126.dtsi
@@ -544,6 +544,14 @@
clock-names = "pclk", "timer";
};
+ wdt: watchdog@ff680000 {
+ compatible = "rockchip,rv1126-wdt", "snps,dw-wdt";
+ reg = <0xff680000 0x100>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_WDT>;
+ status = "disabled";
+ };
+
i2s0: i2s@ff800000 {
compatible = "rockchip,rv1126-i2s-tdm";
reg = <0xff800000 0x1000>;
diff --git a/arch/arm/boot/dts/st/spear1310-evb.dts b/arch/arm/boot/dts/st/spear1310-evb.dts
index 18191a87f07c..ad216571ba57 100644
--- a/arch/arm/boot/dts/st/spear1310-evb.dts
+++ b/arch/arm/boot/dts/st/spear1310-evb.dts
@@ -353,7 +353,6 @@
spi-max-frequency = <1000000>;
spi-cpha;
pl022,interface = <0>;
- pl022,slave-tx-disable;
pl022,com-mode = <0>;
pl022,rx-level-trig = <0>;
pl022,tx-level-trig = <0>;
@@ -385,7 +384,6 @@
spi-cpol;
spi-cpha;
pl022,interface = <0>;
- pl022,slave-tx-disable;
pl022,com-mode = <0x2>;
pl022,rx-level-trig = <0>;
pl022,tx-level-trig = <0>;
diff --git a/arch/arm/boot/dts/st/spear1340-evb.dts b/arch/arm/boot/dts/st/spear1340-evb.dts
index cea624fc745c..9b515b21a633 100644
--- a/arch/arm/boot/dts/st/spear1340-evb.dts
+++ b/arch/arm/boot/dts/st/spear1340-evb.dts
@@ -446,7 +446,6 @@
spi-cpol;
spi-cpha;
pl022,interface = <0>;
- pl022,slave-tx-disable;
pl022,com-mode = <0x2>;
pl022,rx-level-trig = <0>;
pl022,tx-level-trig = <0>;
@@ -461,7 +460,6 @@
spi-cpha;
reg = <1>;
pl022,interface = <0>;
- pl022,slave-tx-disable;
pl022,com-mode = <0>;
pl022,rx-level-trig = <0>;
pl022,tx-level-trig = <0>;
diff --git a/arch/arm/boot/dts/st/ste-dbx5x0-pinctrl.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0-pinctrl.dtsi
index 31a86606beda..9a6304b7ab25 100644
--- a/arch/arm/boot/dts/st/ste-dbx5x0-pinctrl.dtsi
+++ b/arch/arm/boot/dts/st/ste-dbx5x0-pinctrl.dtsi
@@ -454,6 +454,31 @@
};
};
+ /* MC2 without feedback clock on A8 */
+ mc2_a_2_default: mc2_a_2_default {
+ default_mux {
+ function = "mc2";
+ groups = "mc2_a_2";
+ };
+ default_cfg1 {
+ pins = "GPIO128_A5"; /* CLK */
+ ste,config = <&out_lo>;
+ };
+ default_cfg2 {
+ pins =
+ "GPIO129_B4", /* CMD */
+ "GPIO131_A12", /* DAT0 */
+ "GPIO132_C10", /* DAT1 */
+ "GPIO133_B10", /* DAT2 */
+ "GPIO134_B9", /* DAT3 */
+ "GPIO135_A9", /* DAT4 */
+ "GPIO136_C7", /* DAT5 */
+ "GPIO137_A7", /* DAT6 */
+ "GPIO138_C5"; /* DAT7 */
+ ste,config = <&in_pu>;
+ };
+ };
+
mc2_a_1_sleep: mc2_a_1_sleep {
sleep_cfg1 {
pins = "GPIO128_A5"; /* CLK */
@@ -478,6 +503,30 @@
ste,config = <&in_wkup_pdis>;
};
};
+
+ mc2_a_2_sleep: mc2_a_2_sleep {
+ sleep_cfg1 {
+ pins = "GPIO128_A5"; /* CLK */
+ ste,config = <&out_lo_wkup_pdis>;
+ };
+ sleep_cfg2 {
+ pins =
+ "GPIO129_B4"; /* CMD */
+ ste,config = <&in_wkup_pdis_en>;
+ };
+ sleep_cfg3 {
+ pins =
+ "GPIO131_A12", /* DAT0 */
+ "GPIO132_C10", /* DAT1 */
+ "GPIO133_B10", /* DAT2 */
+ "GPIO134_B9", /* DAT3 */
+ "GPIO135_A9", /* DAT4 */
+ "GPIO136_C7", /* DAT5 */
+ "GPIO137_A7", /* DAT6 */
+ "GPIO138_C5"; /* DAT7 */
+ ste,config = <&in_wkup_pdis>;
+ };
+ };
};
sdi4 {
diff --git a/arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts
index c623cc35c5ea..404d4ea9347b 100644
--- a/arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts
+++ b/arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts
@@ -544,6 +544,7 @@
touchscreen-size-y = <800>;
pinctrl-names = "default";
pinctrl-0 = <&tsp_default>;
+ linux,keycodes = <KEY_MENU>, <KEY_BACK>;
};
};
diff --git a/arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts
index 2355ca6e9ad6..40b0d92dfb15 100644
--- a/arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts
+++ b/arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts
@@ -451,13 +451,17 @@
no-sdio;
no-sd;
vmmc-supply = <&ldo_3v3_reg>;
+ vqmmc-supply = <&db8500_vsmps2_reg>;
pinctrl-names = "default", "sleep";
/*
- * GPIO130 will be set to input no pull-up resulting in a resistor
- * pulling the reset high and taking the memory out of reset.
+ * This muxing excludes the feedback clock on GPIO130
+ * which is instead used for reset of the eMMC.
+ * GPIO130 will be set to input no pull-up resulting in
+ * a resistor pulling the reset high and taking the
+ * memory out of reset.
*/
- pinctrl-0 = <&mc2_a_1_default>;
- pinctrl-1 = <&mc2_a_1_sleep>;
+ pinctrl-0 = <&mc2_a_2_default>;
+ pinctrl-1 = <&mc2_a_2_sleep>;
status = "okay";
};
@@ -644,6 +648,7 @@
touchscreen-size-y = <800>;
pinctrl-names = "default";
pinctrl-0 = <&tsp_default>;
+ linux,keycodes = <KEY_MENU>, <KEY_BACK>;
};
};
@@ -677,14 +682,14 @@
sdi2 {
/*
* This will make the resistor mounted in R0.0 pull up
- * the reset line and take the eMMC out of reset. On
- * R0.4 variants, GPIO130 should be set in GPIO mode and
- * pulled down. (Not connected.)
+ * the reset line and take the eMMC out of reset so set to
+ * GPIO input mode, no pull-up. On R0.4 variants, GPIO130
+ * could be set in GPIO mode and pulled down. (Not connected.)
*/
- mc2_a_1_default {
- default_cfg2 {
- pins = "GPIO130_C8"; /* FBCLK */
- ste,config = <&in_nopull>;
+ mc2_a_2_default {
+ default_cfg3 {
+ pins = "GPIO130_C8"; /* RST_N */
+ ste,config = <&gpio_in_nopull>;
};
};
};
diff --git a/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi
index 8db1ec4a3b26..a422b32d71d1 100644
--- a/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi
@@ -595,6 +595,13 @@
};
/omit-if-no-ref/
+ rtc_rsvd_pins_a: rtc-rsvd-0 {
+ pins {
+ pinmux = <STM32_PINMUX('I', 1, ANALOG)>; /* RTC_OUT2_RMP */
+ };
+ };
+
+ /omit-if-no-ref/
sai1a_pins_a: sai1a-0 {
pins {
pinmux = <STM32_PINMUX('A', 4, AF12)>, /* SAI1_SCK_A */
diff --git a/arch/arm/boot/dts/st/stm32mp135f-dk.dts b/arch/arm/boot/dts/st/stm32mp135f-dk.dts
index 1af335a39993..3a276589fef7 100644
--- a/arch/arm/boot/dts/st/stm32mp135f-dk.dts
+++ b/arch/arm/boot/dts/st/stm32mp135f-dk.dts
@@ -121,6 +121,19 @@
};
};
};
+
+ v3v3_ao: v3v3-ao {
+ compatible = "regulator-fixed";
+ regulator-name = "v3v3_ao";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&mcp23017 11 GPIO_ACTIVE_LOW>;
+ };
};
&adc_1 {
@@ -346,7 +359,14 @@
};
&rtc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_rsvd_pins_a>;
status = "okay";
+
+ rtc_lsco_pins_a: rtc-lsco-0 {
+ pins = "out2_rmp";
+ function = "lsco";
+ };
};
&scmi_regu {
@@ -385,6 +405,30 @@
status = "okay";
};
+/* Wifi */
+&sdmmc2 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_clk_pins_a>;
+ pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_clk_pins_a>;
+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>;
+ non-removable;
+ cap-sdio-irq;
+ st,neg-edge;
+ bus-width = <4>;
+ vmmc-supply = <&v3v3_ao>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_lsco_pins_a>;
+ };
+};
+
&spi5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&spi5_pins_a>;
@@ -491,6 +535,14 @@
pinctrl-2 = <&usart2_idle_pins_a>;
uart-has-rtscts;
status = "okay";
+
+ bluetooth {
+ shutdown-gpios = <&mcp23017 13 GPIO_ACTIVE_HIGH>;
+ compatible = "brcm,bcm43438-bt";
+ max-speed = <3000000>;
+ vbat-supply = <&v3v3_ao>;
+ vddio-supply = <&v3v3_ao>;
+ };
};
&usbh_ehci {
diff --git a/arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi b/arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi
index ddad6497775b..5edbc790d1d2 100644
--- a/arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp13xx-dhcor-som.dtsi
@@ -201,6 +201,12 @@
pagesize = <64>;
};
+ eeprom0wl: eeprom@58 {
+ compatible = "st,24256e-wl"; /* ST M24256E WL page of 0x50 */
+ pagesize = <64>;
+ reg = <0x58>;
+ };
+
rv3032: rtc@51 {
compatible = "microcrystal,rv3032";
reg = <0x51>;
diff --git a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi
index 70e132dc6147..95fafc51a1c8 100644
--- a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi
@@ -1697,6 +1697,13 @@
};
/omit-if-no-ref/
+ rtc_rsvd_pins_a: rtc-rsvd-0 {
+ pins {
+ pinmux = <STM32_PINMUX('I', 8, ANALOG)>; /* RTC_OUT2_RMP */
+ };
+ };
+
+ /omit-if-no-ref/
sai2a_pins_a: sai2a-0 {
pins {
pinmux = <STM32_PINMUX('I', 5, AF10)>, /* SAI2_SCK_A */
diff --git a/arch/arm/boot/dts/st/stm32mp151.dtsi b/arch/arm/boot/dts/st/stm32mp151.dtsi
index 4f878ec102c1..b28dc90926bd 100644
--- a/arch/arm/boot/dts/st/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp151.dtsi
@@ -355,6 +355,8 @@
reg = <0x5a002000 0x400>;
clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
clock-names = "pclk", "lsi";
+ interrupts-extended = <&exti 46 IRQ_TYPE_LEVEL_HIGH>;
+ wakeup-source;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
index 7a701f7ef0c7..5f9c0160a9c4 100644
--- a/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
+++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts
@@ -24,6 +24,11 @@
chosen {
stdout-path = "serial0:115200n8";
};
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpioh 4 GPIO_ACTIVE_LOW>;
+ };
};
&cryp1 {
@@ -84,10 +89,54 @@
};
};
+&rtc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_rsvd_pins_a>;
+
+ rtc_lsco_pins_a: rtc-lsco-0 {
+ pins = "out2_rmp";
+ function = "lsco";
+ };
+};
+
+/* Wifi */
+&sdmmc2 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc2_b4_pins_a>;
+ pinctrl-1 = <&sdmmc2_b4_od_pins_a>;
+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>;
+ non-removable;
+ cap-sdio-irq;
+ st,neg-edge;
+ bus-width = <4>;
+ vmmc-supply = <&v3v3>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_lsco_pins_a>;
+ };
+};
+
+/* Bluetooth */
&usart2 {
pinctrl-names = "default", "sleep", "idle";
pinctrl-0 = <&usart2_pins_c>;
pinctrl-1 = <&usart2_sleep_pins_c>;
pinctrl-2 = <&usart2_idle_pins_c>;
- status = "disabled";
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ shutdown-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>;
+ compatible = "brcm,bcm43438-bt";
+ max-speed = <3000000>;
+ vbat-supply = <&v3v3>;
+ vddio-supply = <&v3v3>;
+ };
};
diff --git a/arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi b/arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi
index a4beb718559c..ae2e8dffbe04 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi
+++ b/arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi
@@ -199,7 +199,6 @@
ti,nand-ecc-opt = "bch8";
ti,nand-xfer-type = "prefetch-dma";
- gpmc,device-nand = "true";
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
@@ -251,7 +250,7 @@
pinctrl-0 = <&tps65910_pins>;
};
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
pagesize = <8>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi
index a0fb431aec84..c400b7b70d0d 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi
@@ -216,7 +216,7 @@
reg = <0x24>;
};
- baseboard_eeprom: baseboard_eeprom@50 {
+ baseboard_eeprom: eeprom@50 {
compatible = "atmel,24c256";
reg = <0x50>;
vcc-supply = <&ldo4_reg>;
@@ -240,7 +240,7 @@
status = "okay";
clock-frequency = <100000>;
- cape_eeprom0: cape_eeprom0@54 {
+ cape_eeprom0: eeprom@54 {
compatible = "atmel,24c256";
reg = <0x54>;
@@ -255,7 +255,7 @@
};
};
- cape_eeprom1: cape_eeprom1@55 {
+ cape_eeprom1: eeprom@55 {
compatible = "atmel,24c256";
reg = <0x55>;
@@ -270,7 +270,7 @@
};
};
- cape_eeprom2: cape_eeprom2@56 {
+ cape_eeprom2: eeprom@56 {
compatible = "atmel,24c256";
reg = <0x56>;
@@ -285,7 +285,7 @@
};
};
- cape_eeprom3: cape_eeprom3@57 {
+ cape_eeprom3: eeprom@57 {
compatible = "atmel,24c256";
reg = <0x57>;
@@ -409,7 +409,7 @@
/* Support GPIO reset on revision C3 boards */
reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
reset-assert-us = <300>;
- reset-deassert-us = <13000>;
+ reset-deassert-us = <50000>;
};
};
diff --git a/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts
index 8878da773d67..f579df4c2c54 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts
@@ -313,7 +313,7 @@
};
&i2c0 {
- baseboard_eeprom: baseboard_eeprom@50 {
+ baseboard_eeprom: eeprom@50 {
compatible = "atmel,24c256";
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts b/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts
index 17574d0d0525..ded19e24e666 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts
@@ -289,7 +289,7 @@
reg = <0x2d>;
};
- m2_eeprom: m2_eeprom@50 {
+ m2_eeprom: eeprom@50 {
compatible = "atmel,24c256";
reg = <0x50>;
status = "okay";
@@ -303,12 +303,12 @@
status = "okay";
clock-frequency = <100000>;
- board_24aa025e48: board_24aa025e48@50 {
+ board_24aa025e48: eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
};
- backplane_24aa025e48: backplane_24aa025e48@53 {
+ backplane_24aa025e48: eeprom@53 {
compatible = "atmel,24c02";
reg = <0x53>;
};
diff --git a/arch/arm/boot/dts/ti/omap/am335x-shc.dts b/arch/arm/boot/dts/ti/omap/am335x-shc.dts
index 9297cb1efcd4..597482822608 100644
--- a/arch/arm/boot/dts/ti/omap/am335x-shc.dts
+++ b/arch/arm/boot/dts/ti/omap/am335x-shc.dts
@@ -169,7 +169,7 @@
reg = <0x24>;
};
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c32";
pagesize = <32>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/am3517-som.dtsi b/arch/arm/boot/dts/ti/omap/am3517-som.dtsi
index bd0a6c95afa1..e36cd98f57fa 100644
--- a/arch/arm/boot/dts/ti/omap/am3517-som.dtsi
+++ b/arch/arm/boot/dts/ti/omap/am3517-som.dtsi
@@ -44,7 +44,6 @@
nand@0,0 {
compatible = "ti,omap2-nand";
- linux,mtd-name = "micron,mt29f4g16abchch";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
nand-bus-width = <16>;
ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/ti/omap/am3874-iceboard.dts b/arch/arm/boot/dts/ti/omap/am3874-iceboard.dts
index ac082e83a9a2..bbb9200a1f26 100644
--- a/arch/arm/boot/dts/ti/omap/am3874-iceboard.dts
+++ b/arch/arm/boot/dts/ti/omap/am3874-iceboard.dts
@@ -249,8 +249,8 @@
tmp100@4c { compatible = "ti,tmp100"; reg = <0x4c>; };
/* EEPROM bank and serial number are treated as separate devices */
- at24c01@57 { compatible = "atmel,24c01"; reg = <0x57>; };
- at24cs01@5f { compatible = "atmel,24cs01"; reg = <0x5f>; };
+ eeprom@57 { compatible = "atmel,24c01"; reg = <0x57>; };
+ eeprom@5f { compatible = "atmel,24cs01"; reg = <0x5f>; };
};
};
};
@@ -270,8 +270,8 @@
multi-master;
/* All backplanes should have this -- it's how we know they're there. */
- at24c08@54 { compatible="atmel,24c08"; reg=<0x54>; };
- at24cs08@5c { compatible="atmel,24cs08"; reg=<0x5c>; };
+ eeprom@54 { compatible="atmel,24c08"; reg=<0x54>; };
+ eeprom@5c { compatible="atmel,24cs08"; reg=<0x5c>; };
/* 16 slot backplane */
tmp421@4d { compatible="ti,tmp421"; reg=<0x4d>; };
diff --git a/arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts b/arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts
index 172516a7667e..e06fc30091c8 100644
--- a/arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts
+++ b/arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts
@@ -254,7 +254,7 @@
};
};
- eeprom_module: at24@50 {
+ eeprom_module: eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <16>;
diff --git a/arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts b/arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts
index 00682ce7e14c..826f687c368a 100644
--- a/arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts
@@ -333,7 +333,7 @@
pinctrl-1 = <&i2c0_pins_sleep>;
clock-frequency = <400000>;
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c256";
pagesize = <64>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts b/arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts
index 5ec57dcb0659..73badf80b4ff 100644
--- a/arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts
+++ b/arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts
@@ -112,7 +112,7 @@
#gpio-cells = <2>;
};
- eeprom_base: at24@50 {
+ eeprom_base: eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <16>;
diff --git a/arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts b/arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts
index 9c97006ffd5b..4700f9879d2d 100644
--- a/arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts
@@ -570,7 +570,7 @@
};
};
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c256";
pagesize = <64>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts b/arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts
index 9193a4cfba78..4ac94be8d000 100644
--- a/arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts
@@ -651,7 +651,7 @@
};
};
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c256";
pagesize = <64>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts
index d6e3152b02f7..3dd898955e76 100644
--- a/arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts
+++ b/arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts
@@ -429,7 +429,7 @@
reg = <0x56>;
};
- eeprom_module: atmel@50 {
+ eeprom_module: eeprom@50 {
compatible = "atmel,24c08";
reg = <0x50>;
pagesize = <16>;
diff --git a/arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts b/arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts
index 64675f4edb60..41bef36c5554 100644
--- a/arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts
+++ b/arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts
@@ -105,7 +105,7 @@
pinctrl-0 = <&i2c5_pins_default>;
clock-frequency = <400000>;
- eeprom_base: atmel@54 {
+ eeprom_base: eeprom@54 {
compatible = "atmel,24c08";
reg = <0x54>;
pagesize = <16>;
diff --git a/arch/arm/boot/dts/ti/omap/dm8148-evm.dts b/arch/arm/boot/dts/ti/omap/dm8148-evm.dts
index ae8d9fa09d16..57a9eef09f6f 100644
--- a/arch/arm/boot/dts/ti/omap/dm8148-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/dm8148-evm.dts
@@ -51,7 +51,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,mt29f2g16aadwp";
#address-cells = <1>;
#size-cells = <1>;
ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/ti/omap/dm8168-evm.dts b/arch/arm/boot/dts/ti/omap/dm8168-evm.dts
index 1d80288f6ba5..6130b9a5f660 100644
--- a/arch/arm/boot/dts/ti/omap/dm8168-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/dm8168-evm.dts
@@ -119,7 +119,6 @@
nand@0,0 {
compatible = "ti,omap2-nand";
- linux,mtd-name = "micron,mt29f2g16aadwp";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
diff --git a/arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts b/arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts
index 2f6ac267fc15..df05a0682322 100644
--- a/arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts
@@ -51,7 +51,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,mt29f2g16aadwp";
#address-cells = <1>;
#size-cells = <1>;
ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi
index 164fa88c459e..b709703f6c0d 100644
--- a/arch/arm/boot/dts/ti/omap/dra7.dtsi
+++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi
@@ -9,7 +9,6 @@
#include <dt-bindings/clock/dra7.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/pinctrl/dra.h>
-#include <dt-bindings/clock/dra7.h>
#define MAX_SOURCES 400
diff --git a/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi
index 04f08b8c64d2..0de16ee262cf 100644
--- a/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi
+++ b/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi
@@ -1376,7 +1376,6 @@
clocks = <&apll_pcie_ck>;
#clock-cells = <0>;
reg = <0x021c>;
- ti,dividers = <2>, <1>;
ti,bit-shift = <8>;
ti,max-div = <2>;
};
diff --git a/arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi b/arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi
index c0e6b73fa472..d51a436d9774 100644
--- a/arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi
+++ b/arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi
@@ -51,7 +51,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,mt29f4g16abbda3w";
nand-bus-width = <16>;
ti,nand-ecc-opt = "bch8";
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
diff --git a/arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi
index 227699890890..0b65ac5b4230 100644
--- a/arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi
+++ b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi
@@ -49,7 +49,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,mt29f4g16abbda3w";
nand-bus-width = <16>;
ti,nand-ecc-opt = "bch8";
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
@@ -103,7 +102,7 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c3_pins>;
clock-frequency = <400000>;
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c64";
readonly;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi
index 950a29f9b4a0..cd13826d033d 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi
@@ -190,7 +190,7 @@
clock-frequency = <400000>;
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
pagesize = <16>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts b/arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts
index e0346bf842fc..9c60ac853a40 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts
@@ -60,7 +60,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "hynix,h8kds0un0mer-4em";
nand-bus-width = <16>;
gpmc,device-width = <2>;
ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/ti/omap/omap3-evm.dts b/arch/arm/boot/dts/ti/omap/omap3-evm.dts
index a2a1613c45c3..28caa5d93b87 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-evm.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3-evm.dts
@@ -60,7 +60,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,mt29f2g16abdhc";
nand-bus-width = <16>;
gpmc,device-width = <2>;
ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi b/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi
index 3661340009e7..2ee3ddd64020 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi
@@ -601,7 +601,7 @@
};
/* RFID EEPROM */
- m24lr64@50 {
+ eeprom@50 {
compatible = "atmel,24c64";
reg = <0x50>;
};
diff --git a/arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts b/arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts
index 8bd6b4b1f30b..d3a81f0b880f 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts
@@ -114,6 +114,16 @@
};
};
+&uart1 {
+ bluetooth {
+ compatible = "ti,wl1837-st";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_pins>;
+ enable-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>; /* GPIO_137 */
+ };
+};
+
+
&i2c2 {
/delete-node/ bmp085@77;
/delete-node/ bma180@41;
diff --git a/arch/arm/boot/dts/ti/omap/omap3-igep.dtsi b/arch/arm/boot/dts/ti/omap/omap3-igep.dtsi
index e068ecf86b8f..7346cad84eda 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-igep.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3-igep.dtsi
@@ -111,7 +111,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,mt29c4g96maz";
nand-bus-width = <16>;
gpmc,device-width = <2>;
ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/ti/omap/omap3-ldp.dts b/arch/arm/boot/dts/ti/omap/omap3-ldp.dts
index bb6fab9fa47d..cf325f56b464 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-ldp.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3-ldp.dts
@@ -103,7 +103,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,nand";
nand-bus-width = <16>;
gpmc,device-width = <2>;
ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi
index cc57626ea607..2793821b2c33 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi
@@ -222,7 +222,6 @@
nand@0,0 {
compatible = "ti,omap2-nand";
- linux,mtd-name = "micron,mt29c4g96maz";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
diff --git a/arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi b/arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi
index 6730c749d5ea..da80d7b7d4b1 100644
--- a/arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi
@@ -89,7 +89,7 @@
clock-frequency = <400000>;
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
pagesize = <16>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/omap3430-sdp.dts b/arch/arm/boot/dts/ti/omap/omap3430-sdp.dts
index 258ecd9e4519..cc5e9035ef73 100644
--- a/arch/arm/boot/dts/ti/omap/omap3430-sdp.dts
+++ b/arch/arm/boot/dts/ti/omap/omap3430-sdp.dts
@@ -105,7 +105,6 @@
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
- linux,mtd-name = "micron,mt29f1g08abb";
#address-cells = <1>;
#size-cells = <1>;
ti,nand-ecc-opt = "sw";
@@ -148,7 +147,6 @@
};
onenand@2,0 {
- linux,mtd-name = "samsung,kfm2g16q2m-deb8";
#address-cells = <1>;
#size-cells = <1>;
compatible = "ti,omap2-onenand";
diff --git a/arch/arm/boot/dts/ti/omap/omap36xx.dtsi b/arch/arm/boot/dts/ti/omap/omap36xx.dtsi
index c3d79ecd56e3..c217094b50ab 100644
--- a/arch/arm/boot/dts/ti/omap/omap36xx.dtsi
+++ b/arch/arm/boot/dts/ti/omap/omap36xx.dtsi
@@ -72,6 +72,7 @@
<1375000 1375000 1375000>;
/* only on am/dm37x with speed-binned bit set */
opp-supported-hw = <0xffffffff 2>;
+ turbo-mode;
};
};
diff --git a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
index 339e52ba3614..c90f43cc2fae 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
+++ b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
@@ -17,16 +17,34 @@
reg = <0x80000000 0x40000000>; /* 1024M */
};
+ battery: battery {
+ compatible = "simple-battery";
+ device-chemistry = "lithium-ion";
+ charge-full-design-microamp-hours = <2720000>;
+ voltage-max-design-microvolt = <4200000>;
+ voltage-min-design-microvolt = <3300000>;
+
+ constant-charge-voltage-max-microvolt = <4200000>;
+ /*
+ * vendor kernel says max charge 1400000, input limit 900000
+ * and charges only with dcp chargers. So it is unclear what
+ * is really allowed. Play safe for now and restrict things
+ * here. Maybe 900000 is just the limit of the vendor charger?
+ */
+ constant-charge-current-max-microamp = <900000>;
+ charge-term-current-microamp = <200000>;
+ };
+
backlight-left {
compatible = "pwm-backlight";
pwms = <&twl_pwm 1 7812500>;
- power-supply = <&unknown_supply>;
+ power-supply = <&lb_v50>;
};
backlight-right {
compatible = "pwm-backlight";
pwms = <&twl_pwm 0 7812500>;
- power-supply = <&unknown_supply>;
+ power-supply = <&lb_v50>;
};
chosen {
@@ -46,9 +64,53 @@
};
};
- unknown_supply: unknown-supply {
+ cb_v18: regulator-cb-v18 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cb_v18_pins>;
+ compatible = "regulator-fixed";
+ regulator-name = "cb_v18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ cb_v33: regulator-cb-v33 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cb_v33_pins>;
+ compatible = "regulator-fixed";
+ regulator-name = "cb_v33";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ gpio = <&gpio6 30 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ regulator-cb-v50 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cb_v50_pins>;
+ compatible = "regulator-fixed";
+ regulator-name = "cb_v50";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ gpio = <&gpio6 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ lb_v50: regulator-lb-v50 {
+ /* required for many things at the head (probably indirectly) */
+ pinctrl-names = "default";
+ pinctrl-0 = <&lb_v50_pins>;
compatible = "regulator-fixed";
- regulator-name = "unknown";
+ regulator-name = "lb_v50";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
};
wl12xx_pwrseq: wl12xx-pwrseq {
@@ -71,6 +133,73 @@
};
};
+&gpio1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio1_hog_pins &gpio1wk_hog_pins>;
+
+ lb-reset-hog {
+ gpio-hog;
+ gpios = <9 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "lb_reset";
+ };
+
+ power-en-hog {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "power_en";
+ };
+
+ /*
+ * Name taken from vendor kernel but no evidence of actual usage found
+ * nor what it really controls.
+ */
+ panel-power-en-hog {
+ gpio-hog;
+ gpios = <14 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "panel_power_en";
+ };
+
+ /*
+ * These two are exported to sysfs in vendor kernel, usage unknown,
+ * backlight state seems unrelated to these.
+ */
+ blc-r-hog {
+ gpio-hog;
+ gpios = <17 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "blc_r";
+ };
+
+ blc-l-hog {
+ gpio-hog;
+ gpios = <16 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "blc_l";
+ };
+
+ high-hog {
+ gpio-hog;
+ gpios = <15 GPIO_ACTIVE_HIGH /* maybe dsi to dpi chip reset? */
+ 21 GPIO_ACTIVE_HIGH
+ 26 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "unknown-high";
+ };
+
+ low-hog {
+ gpio-hog;
+ gpios = <18 GPIO_ACTIVE_HIGH
+ 19 GPIO_ACTIVE_HIGH
+ 20 GPIO_ACTIVE_HIGH
+ 22 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "unknown-low";
+ };
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
@@ -87,6 +216,14 @@
#interrupt-cells = <1>;
system-power-controller;
+ charger {
+ compatible = "ti,twl6032-charger", "ti,twl6030-charger";
+ interrupts = <2>, <5>;
+ io-channels = <&gpadc 10>;
+ io-channel-names = "vusb";
+ monitored-battery = <&battery>;
+ };
+
rtc {
compatible = "ti,twl4030-rtc";
interrupts = <11>;
@@ -166,7 +303,7 @@
#pwm-cells = <2>;
};
- gpadc {
+ gpadc: gpadc {
compatible = "ti,twl6032-gpadc";
interrupts = <3>;
#io-channel-cells = <1>;
@@ -188,6 +325,19 @@
clock-frequency = <200000>;
+ /* is sometimes not available, research needed */
+ gpio_head: gpio@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ /*
+ * camera chip at 0x3c, available if <&gpio_head 1> high
+ * and <&gpio_head 5> low
+ */
+
/* at head/glasses */
mpu9150h: imu@68 {
compatible = "invensense,mpu9150";
@@ -259,6 +409,8 @@
pinctrl-0 = <&mpu9150_pins>;
interrupt-parent = <&gpio2>;
interrupt = <7 IRQ_TYPE_LEVEL_HIGH>;
+ vddio-supply = <&cb_v18>;
+ vdd-supply = <&cb_v33>;
invensense,level-shifter;
};
};
@@ -336,12 +488,46 @@
>;
};
+ cb_v18_pins: pinmux-cb-v18-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x1d0, PIN_OUTPUT | MUX_MODE3) /* gpio28 */
+ >;
+ };
+
+ cb_v33_pins: pinmux-cb-v33-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x1d2, PIN_OUTPUT | MUX_MODE3) /* gpio190 */
+ >;
+ };
+
+ cb_v50_pins: pinmux-cb-v50-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x1d4, PIN_OUTPUT | MUX_MODE3) /* gpio191 */
+ >;
+ };
+
gpio_keys_pins: pinmux-gpio-key-pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x56, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio35 */
>;
};
+ gpio1_hog_pins: pinmux-gpio1-hog-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x1b4, PIN_OUTPUT | MUX_MODE3) /* gpio14 */
+ OMAP4_IOPAD(0x1b8, PIN_OUTPUT | MUX_MODE3) /* gpio16 */
+ OMAP4_IOPAD(0x1ba, PIN_OUTPUT | MUX_MODE3) /* gpio17 */
+
+ OMAP4_IOPAD(0x1b6, PIN_OUTPUT | MUX_MODE3) /* gpio15 */
+ OMAP4_IOPAD(0x1bc, PIN_OUTPUT | MUX_MODE3) /* gpio18 */
+ OMAP4_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE3) /* gpio19 */
+ OMAP4_IOPAD(0x1c0, PIN_OUTPUT | MUX_MODE3) /* gpio20 */
+ OMAP4_IOPAD(0x1c2, PIN_OUTPUT | MUX_MODE3) /* gpio21 */
+ OMAP4_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE3) /* gpio22 */
+ OMAP4_IOPAD(0x1cc, PIN_OUTPUT | MUX_MODE3) /* gpio26 */
+ >;
+ };
+
i2c1_pins: pinmux-i2c1-pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */
@@ -387,6 +573,12 @@
>;
};
+ lb_v50_pins: pinmux-lb-v50-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x1ce, PIN_OUTPUT | MUX_MODE3) /* gpio27 */
+ >;
+ };
+
mcbsp2_pins: pinmux-mcbsp2-pins {
pinctrl-single,pins = <
OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE0) /* abe_mcbsp2_clkx */
@@ -457,6 +649,15 @@
};
};
+&omap4_pmx_wkup {
+ gpio1wk_hog_pins: pinmux-gpio1wk-hog-pins {
+ pinctrl-single,pins = <
+ OMAP4_IOPAD(0x68, PIN_INPUT_PULLDOWN | MUX_MODE3) /* gpio9 */
+ OMAP4_IOPAD(0x6a, PIN_INPUT | MUX_MODE3) /* gpio10 */
+ >;
+ };
+};
+
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins &bt_pins>;
diff --git a/arch/arm/boot/dts/ti/omap/omap4-kc1.dts b/arch/arm/boot/dts/ti/omap/omap4-kc1.dts
index c6b79ba8bbc9..df874d5f5327 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-kc1.dts
+++ b/arch/arm/boot/dts/ti/omap/omap4-kc1.dts
@@ -112,11 +112,7 @@
reg = <0x48>;
/* IRQ# = 7 */
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-
- twl_power: power {
- compatible = "ti,twl6030-power";
- ti,system-power-controller;
- };
+ system-power-controller;
};
};
diff --git a/arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts b/arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts
index 6767382996ab..2fd8111de903 100644
--- a/arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts
+++ b/arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts
@@ -413,7 +413,7 @@
clock-frequency = <400000>;
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
pagesize = <16>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts b/arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts
index 02716fb796bd..7ae60dc198f3 100644
--- a/arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts
+++ b/arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts
@@ -44,7 +44,7 @@
clock-frequency = <400000>;
- at24@50 {
+ eeprom@50 {
compatible = "atmel,24c02";
pagesize = <16>;
reg = <0x50>;
diff --git a/arch/arm/boot/dts/ti/omap/twl4030.dtsi b/arch/arm/boot/dts/ti/omap/twl4030.dtsi
index a5d9c5738317..07b9ca942e78 100644
--- a/arch/arm/boot/dts/ti/omap/twl4030.dtsi
+++ b/arch/arm/boot/dts/ti/omap/twl4030.dtsi
@@ -16,7 +16,7 @@
interrupts = <11>;
};
- charger: bci {
+ charger: charger {
compatible = "ti,twl4030-bci";
interrupts = <9>, <2>;
bci3v1-supply = <&vusb3v1>;
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index 2022a7fca0f9..f2596a1b2f7d 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -201,6 +201,7 @@ CONFIG_AT_XDMAC=y
CONFIG_IIO=y
CONFIG_AT91_ADC=y
CONFIG_AT91_SAMA5D2_ADC=y
+CONFIG_PAC1934=m
CONFIG_PWM=y
CONFIG_PWM_ATMEL=y
CONFIG_PWM_ATMEL_HLCDC_PWM=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 333ef55476a3..0beecdde55f5 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -68,6 +68,7 @@ CONFIG_BT=y
CONFIG_BT_BNEP=m
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_NXPUART=m
CONFIG_CFG80211=y
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
@@ -253,6 +254,7 @@ CONFIG_MFD_ROHM_BD71828=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_ANATOP=y
CONFIG_REGULATOR_BD71815=y
+CONFIG_REGULATOR_BD71828=y
CONFIG_REGULATOR_DA9052=y
CONFIG_REGULATOR_DA9062=y
CONFIG_REGULATOR_DA9063=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 9a5f5c439b87..758276027dbc 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1323,5 +1323,8 @@ CONFIG_CRYPTO_DEV_STM32_HASH=m
CONFIG_CRYPTO_DEV_STM32_CRYP=m
CONFIG_CMA_SIZE_MBYTES=64
CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
+CONFIG_DEBUG_INFO_REDUCED=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig
index e1cb170c2bf0..38916ac4bce4 100644
--- a/arch/arm/configs/pxa_defconfig
+++ b/arch/arm/configs/pxa_defconfig
@@ -583,10 +583,6 @@ CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
CONFIG_XFS_FS=m
CONFIG_AUTOFS_FS=m
CONFIG_FUSE_FS=m
diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 9096a99b5abd..e447329398d5 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -212,6 +212,7 @@ CONFIG_VIDEO_HANTRO=m
CONFIG_IIO=y
CONFIG_AT91_ADC=y
CONFIG_AT91_SAMA5D2_ADC=y
+CONFIG_PAC1934=m
CONFIG_ENVELOPE_DETECTOR=m
CONFIG_DPOT_DAC=m
CONFIG_MCP4531=m
diff --git a/arch/arm/configs/sama7_defconfig b/arch/arm/configs/sama7_defconfig
index 7fa5d251ced2..1a2e93c8ee71 100644
--- a/arch/arm/configs/sama7_defconfig
+++ b/arch/arm/configs/sama7_defconfig
@@ -193,6 +193,7 @@ CONFIG_STAGING=y
CONFIG_IIO=y
CONFIG_IIO_SW_TRIGGER=y
CONFIG_AT91_SAMA5D2_ADC=y
+CONFIG_PAC1934=m
CONFIG_PWM=y
CONFIG_PWM_ATMEL=y
CONFIG_MCHP_EIC=y
diff --git a/arch/arm/crypto/crct10dif-ce-core.S b/arch/arm/crypto/crct10dif-ce-core.S
index 46c02c518a30..2bbf2df9c1e2 100644
--- a/arch/arm/crypto/crct10dif-ce-core.S
+++ b/arch/arm/crypto/crct10dif-ce-core.S
@@ -112,55 +112,120 @@
FOLD_CONST_L .req q10l
FOLD_CONST_H .req q10h
+ /*
+ * Pairwise long polynomial multiplication of two 16-bit values
+ *
+ * { w0, w1 }, { y0, y1 }
+ *
+ * by two 64-bit values
+ *
+ * { x0, x1, x2, x3, x4, x5, x6, x7 }, { z0, z1, z2, z3, z4, z5, z6, z7 }
+ *
+ * where each vector element is a byte, ordered from least to most
+ * significant. The resulting 80-bit vectors are XOR'ed together.
+ *
+ * This can be implemented using 8x8 long polynomial multiplication, by
+ * reorganizing the input so that each pairwise 8x8 multiplication
+ * produces one of the terms from the decomposition below, and
+ * combining the results of each rank and shifting them into place.
+ *
+ * Rank
+ * 0 w0*x0 ^ | y0*z0 ^
+ * 1 (w0*x1 ^ w1*x0) << 8 ^ | (y0*z1 ^ y1*z0) << 8 ^
+ * 2 (w0*x2 ^ w1*x1) << 16 ^ | (y0*z2 ^ y1*z1) << 16 ^
+ * 3 (w0*x3 ^ w1*x2) << 24 ^ | (y0*z3 ^ y1*z2) << 24 ^
+ * 4 (w0*x4 ^ w1*x3) << 32 ^ | (y0*z4 ^ y1*z3) << 32 ^
+ * 5 (w0*x5 ^ w1*x4) << 40 ^ | (y0*z5 ^ y1*z4) << 40 ^
+ * 6 (w0*x6 ^ w1*x5) << 48 ^ | (y0*z6 ^ y1*z5) << 48 ^
+ * 7 (w0*x7 ^ w1*x6) << 56 ^ | (y0*z7 ^ y1*z6) << 56 ^
+ * 8 w1*x7 << 64 | y1*z7 << 64
+ *
+ * The inputs can be reorganized into
+ *
+ * { w0, w0, w0, w0, y0, y0, y0, y0 }, { w1, w1, w1, w1, y1, y1, y1, y1 }
+ * { x0, x2, x4, x6, z0, z2, z4, z6 }, { x1, x3, x5, x7, z1, z3, z5, z7 }
+ *
+ * and after performing 8x8->16 bit long polynomial multiplication of
+ * each of the halves of the first vector with those of the second one,
+ * we obtain the following four vectors of 16-bit elements:
+ *
+ * a := { w0*x0, w0*x2, w0*x4, w0*x6 }, { y0*z0, y0*z2, y0*z4, y0*z6 }
+ * b := { w0*x1, w0*x3, w0*x5, w0*x7 }, { y0*z1, y0*z3, y0*z5, y0*z7 }
+ * c := { w1*x0, w1*x2, w1*x4, w1*x6 }, { y1*z0, y1*z2, y1*z4, y1*z6 }
+ * d := { w1*x1, w1*x3, w1*x5, w1*x7 }, { y1*z1, y1*z3, y1*z5, y1*z7 }
+ *
+ * Results b and c can be XORed together, as the vector elements have
+ * matching ranks. Then, the final XOR can be pulled forward, and
+ * applied between the halves of each of the remaining three vectors,
+ * which are then shifted into place, and XORed together to produce the
+ * final 80-bit result.
+ */
+ .macro pmull16x64_p8, v16, v64
+ vext.8 q11, \v64, \v64, #1
+ vld1.64 {q12}, [r4, :128]
+ vuzp.8 q11, \v64
+ vtbl.8 d24, {\v16\()_L-\v16\()_H}, d24
+ vtbl.8 d25, {\v16\()_L-\v16\()_H}, d25
+ bl __pmull16x64_p8
+ veor \v64, q12, q14
+ .endm
+
+__pmull16x64_p8:
+ vmull.p8 q13, d23, d24
+ vmull.p8 q14, d23, d25
+ vmull.p8 q15, d22, d24
+ vmull.p8 q12, d22, d25
+
+ veor q14, q14, q15
+ veor d24, d24, d25
+ veor d26, d26, d27
+ veor d28, d28, d29
+ vmov.i32 d25, #0
+ vmov.i32 d29, #0
+ vext.8 q12, q12, q12, #14
+ vext.8 q14, q14, q14, #15
+ veor d24, d24, d26
+ bx lr
+ENDPROC(__pmull16x64_p8)
+
+ .macro pmull16x64_p64, v16, v64
+ vmull.p64 q11, \v64\()l, \v16\()_L
+ vmull.p64 \v64, \v64\()h, \v16\()_H
+ veor \v64, \v64, q11
+ .endm
+
// Fold reg1, reg2 into the next 32 data bytes, storing the result back
// into reg1, reg2.
- .macro fold_32_bytes, reg1, reg2
- vld1.64 {q11-q12}, [buf]!
+ .macro fold_32_bytes, reg1, reg2, p
+ vld1.64 {q8-q9}, [buf]!
- vmull.p64 q8, \reg1\()h, FOLD_CONST_H
- vmull.p64 \reg1, \reg1\()l, FOLD_CONST_L
- vmull.p64 q9, \reg2\()h, FOLD_CONST_H
- vmull.p64 \reg2, \reg2\()l, FOLD_CONST_L
+ pmull16x64_\p FOLD_CONST, \reg1
+ pmull16x64_\p FOLD_CONST, \reg2
-CPU_LE( vrev64.8 q11, q11 )
-CPU_LE( vrev64.8 q12, q12 )
- vswp q11l, q11h
- vswp q12l, q12h
+CPU_LE( vrev64.8 q8, q8 )
+CPU_LE( vrev64.8 q9, q9 )
+ vswp q8l, q8h
+ vswp q9l, q9h
veor.8 \reg1, \reg1, q8
veor.8 \reg2, \reg2, q9
- veor.8 \reg1, \reg1, q11
- veor.8 \reg2, \reg2, q12
.endm
// Fold src_reg into dst_reg, optionally loading the next fold constants
- .macro fold_16_bytes, src_reg, dst_reg, load_next_consts
- vmull.p64 q8, \src_reg\()l, FOLD_CONST_L
- vmull.p64 \src_reg, \src_reg\()h, FOLD_CONST_H
+ .macro fold_16_bytes, src_reg, dst_reg, p, load_next_consts
+ pmull16x64_\p FOLD_CONST, \src_reg
.ifnb \load_next_consts
vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
.endif
- veor.8 \dst_reg, \dst_reg, q8
veor.8 \dst_reg, \dst_reg, \src_reg
.endm
- .macro __adrl, out, sym
- movw \out, #:lower16:\sym
- movt \out, #:upper16:\sym
- .endm
-
-//
-// u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len);
-//
-// Assumes len >= 16.
-//
-ENTRY(crc_t10dif_pmull)
-
+ .macro crct10dif, p
// For sizes less than 256 bytes, we can't fold 128 bytes at a time.
cmp len, #256
- blt .Lless_than_256_bytes
+ blt .Lless_than_256_bytes\@
- __adrl fold_consts_ptr, .Lfold_across_128_bytes_consts
+ mov_l fold_consts_ptr, .Lfold_across_128_bytes_consts
// Load the first 128 data bytes. Byte swapping is necessary to make
// the bit order match the polynomial coefficient order.
@@ -199,27 +264,27 @@ CPU_LE( vrev64.8 q7, q7 )
// While >= 128 data bytes remain (not counting q0-q7), fold the 128
// bytes q0-q7 into them, storing the result back into q0-q7.
-.Lfold_128_bytes_loop:
- fold_32_bytes q0, q1
- fold_32_bytes q2, q3
- fold_32_bytes q4, q5
- fold_32_bytes q6, q7
+.Lfold_128_bytes_loop\@:
+ fold_32_bytes q0, q1, \p
+ fold_32_bytes q2, q3, \p
+ fold_32_bytes q4, q5, \p
+ fold_32_bytes q6, q7, \p
subs len, len, #128
- bge .Lfold_128_bytes_loop
+ bge .Lfold_128_bytes_loop\@
// Now fold the 112 bytes in q0-q6 into the 16 bytes in q7.
// Fold across 64 bytes.
vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
- fold_16_bytes q0, q4
- fold_16_bytes q1, q5
- fold_16_bytes q2, q6
- fold_16_bytes q3, q7, 1
+ fold_16_bytes q0, q4, \p
+ fold_16_bytes q1, q5, \p
+ fold_16_bytes q2, q6, \p
+ fold_16_bytes q3, q7, \p, 1
// Fold across 32 bytes.
- fold_16_bytes q4, q6
- fold_16_bytes q5, q7, 1
+ fold_16_bytes q4, q6, \p
+ fold_16_bytes q5, q7, \p, 1
// Fold across 16 bytes.
- fold_16_bytes q6, q7
+ fold_16_bytes q6, q7, \p
// Add 128 to get the correct number of data bytes remaining in 0...127
// (not counting q7), following the previous extra subtraction by 128.
@@ -229,25 +294,23 @@ CPU_LE( vrev64.8 q7, q7 )
// While >= 16 data bytes remain (not counting q7), fold the 16 bytes q7
// into them, storing the result back into q7.
- blt .Lfold_16_bytes_loop_done
-.Lfold_16_bytes_loop:
- vmull.p64 q8, q7l, FOLD_CONST_L
- vmull.p64 q7, q7h, FOLD_CONST_H
- veor.8 q7, q7, q8
+ blt .Lfold_16_bytes_loop_done\@
+.Lfold_16_bytes_loop\@:
+ pmull16x64_\p FOLD_CONST, q7
vld1.64 {q0}, [buf]!
CPU_LE( vrev64.8 q0, q0 )
vswp q0l, q0h
veor.8 q7, q7, q0
subs len, len, #16
- bge .Lfold_16_bytes_loop
+ bge .Lfold_16_bytes_loop\@
-.Lfold_16_bytes_loop_done:
+.Lfold_16_bytes_loop_done\@:
// Add 16 to get the correct number of data bytes remaining in 0...15
// (not counting q7), following the previous extra subtraction by 16.
adds len, len, #16
- beq .Lreduce_final_16_bytes
+ beq .Lreduce_final_16_bytes\@
-.Lhandle_partial_segment:
+.Lhandle_partial_segment\@:
// Reduce the last '16 + len' bytes where 1 <= len <= 15 and the first
// 16 bytes are in q7 and the rest are the remaining data in 'buf'. To
// do this without needing a fold constant for each possible 'len',
@@ -262,9 +325,9 @@ CPU_LE( vrev64.8 q0, q0 )
vswp q0l, q0h
// q1 = high order part of second chunk: q7 left-shifted by 'len' bytes.
- __adrl r3, .Lbyteshift_table + 16
- sub r3, r3, len
- vld1.8 {q2}, [r3]
+ mov_l r1, .Lbyteshift_table + 16
+ sub r1, r1, len
+ vld1.8 {q2}, [r1]
vtbl.8 q1l, {q7l-q7h}, q2l
vtbl.8 q1h, {q7l-q7h}, q2h
@@ -282,12 +345,46 @@ CPU_LE( vrev64.8 q0, q0 )
vbsl.8 q2, q1, q0
// Fold the first chunk into the second chunk, storing the result in q7.
- vmull.p64 q0, q3l, FOLD_CONST_L
- vmull.p64 q7, q3h, FOLD_CONST_H
- veor.8 q7, q7, q0
- veor.8 q7, q7, q2
+ pmull16x64_\p FOLD_CONST, q3
+ veor.8 q7, q3, q2
+ b .Lreduce_final_16_bytes\@
+
+.Lless_than_256_bytes\@:
+ // Checksumming a buffer of length 16...255 bytes
+
+ mov_l fold_consts_ptr, .Lfold_across_16_bytes_consts
+
+ // Load the first 16 data bytes.
+ vld1.64 {q7}, [buf]!
+CPU_LE( vrev64.8 q7, q7 )
+ vswp q7l, q7h
+
+ // XOR the first 16 data *bits* with the initial CRC value.
+ vmov.i8 q0h, #0
+ vmov.u16 q0h[3], init_crc
+ veor.8 q7h, q7h, q0h
+
+ // Load the fold-across-16-bytes constants.
+ vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
+
+ cmp len, #16
+ beq .Lreduce_final_16_bytes\@ // len == 16
+ subs len, len, #32
+ addlt len, len, #16
+ blt .Lhandle_partial_segment\@ // 17 <= len <= 31
+ b .Lfold_16_bytes_loop\@ // 32 <= len <= 255
+
+.Lreduce_final_16_bytes\@:
+ .endm
+
+//
+// u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len);
+//
+// Assumes len >= 16.
+//
+ENTRY(crc_t10dif_pmull64)
+ crct10dif p64
-.Lreduce_final_16_bytes:
// Reduce the 128-bit value M(x), stored in q7, to the final 16-bit CRC.
// Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
@@ -320,32 +417,19 @@ CPU_LE( vrev64.8 q0, q0 )
vmov.u16 r0, q0l[0]
bx lr
+ENDPROC(crc_t10dif_pmull64)
-.Lless_than_256_bytes:
- // Checksumming a buffer of length 16...255 bytes
+ENTRY(crc_t10dif_pmull8)
+ push {r4, lr}
+ mov_l r4, .L16x64perm
- __adrl fold_consts_ptr, .Lfold_across_16_bytes_consts
+ crct10dif p8
- // Load the first 16 data bytes.
- vld1.64 {q7}, [buf]!
CPU_LE( vrev64.8 q7, q7 )
vswp q7l, q7h
-
- // XOR the first 16 data *bits* with the initial CRC value.
- vmov.i8 q0h, #0
- vmov.u16 q0h[3], init_crc
- veor.8 q7h, q7h, q0h
-
- // Load the fold-across-16-bytes constants.
- vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]!
-
- cmp len, #16
- beq .Lreduce_final_16_bytes // len == 16
- subs len, len, #32
- addlt len, len, #16
- blt .Lhandle_partial_segment // 17 <= len <= 31
- b .Lfold_16_bytes_loop // 32 <= len <= 255
-ENDPROC(crc_t10dif_pmull)
+ vst1.64 {q7}, [r3, :128]
+ pop {r4, pc}
+ENDPROC(crc_t10dif_pmull8)
.section ".rodata", "a"
.align 4
@@ -379,3 +463,6 @@ ENDPROC(crc_t10dif_pmull)
.byte 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f
.byte 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
.byte 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe , 0x0
+
+.L16x64perm:
+ .quad 0x808080800000000, 0x909090901010101
diff --git a/arch/arm/crypto/crct10dif-ce-glue.c b/arch/arm/crypto/crct10dif-ce-glue.c
index 79f3b204d8c0..a8b74523729e 100644
--- a/arch/arm/crypto/crct10dif-ce-glue.c
+++ b/arch/arm/crypto/crct10dif-ce-glue.c
@@ -19,7 +19,9 @@
#define CRC_T10DIF_PMULL_CHUNK_SIZE 16U
-asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len);
+asmlinkage u16 crc_t10dif_pmull64(u16 init_crc, const u8 *buf, size_t len);
+asmlinkage void crc_t10dif_pmull8(u16 init_crc, const u8 *buf, size_t len,
+ u8 out[16]);
static int crct10dif_init(struct shash_desc *desc)
{
@@ -29,14 +31,14 @@ static int crct10dif_init(struct shash_desc *desc)
return 0;
}
-static int crct10dif_update(struct shash_desc *desc, const u8 *data,
- unsigned int length)
+static int crct10dif_update_ce(struct shash_desc *desc, const u8 *data,
+ unsigned int length)
{
u16 *crc = shash_desc_ctx(desc);
if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
kernel_neon_begin();
- *crc = crc_t10dif_pmull(*crc, data, length);
+ *crc = crc_t10dif_pmull64(*crc, data, length);
kernel_neon_end();
} else {
*crc = crc_t10dif_generic(*crc, data, length);
@@ -45,6 +47,27 @@ static int crct10dif_update(struct shash_desc *desc, const u8 *data,
return 0;
}
+static int crct10dif_update_neon(struct shash_desc *desc, const u8 *data,
+ unsigned int length)
+{
+ u16 *crcp = shash_desc_ctx(desc);
+ u8 buf[16] __aligned(16);
+ u16 crc = *crcp;
+
+ if (length > CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
+ kernel_neon_begin();
+ crc_t10dif_pmull8(crc, data, length, buf);
+ kernel_neon_end();
+
+ crc = 0;
+ data = buf;
+ length = sizeof(buf);
+ }
+
+ *crcp = crc_t10dif_generic(crc, data, length);
+ return 0;
+}
+
static int crct10dif_final(struct shash_desc *desc, u8 *out)
{
u16 *crc = shash_desc_ctx(desc);
@@ -53,10 +76,22 @@ static int crct10dif_final(struct shash_desc *desc, u8 *out)
return 0;
}
-static struct shash_alg crc_t10dif_alg = {
+static struct shash_alg algs[] = {{
+ .digestsize = CRC_T10DIF_DIGEST_SIZE,
+ .init = crct10dif_init,
+ .update = crct10dif_update_neon,
+ .final = crct10dif_final,
+ .descsize = CRC_T10DIF_DIGEST_SIZE,
+
+ .base.cra_name = "crct10dif",
+ .base.cra_driver_name = "crct10dif-arm-neon",
+ .base.cra_priority = 150,
+ .base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+}, {
.digestsize = CRC_T10DIF_DIGEST_SIZE,
.init = crct10dif_init,
- .update = crct10dif_update,
+ .update = crct10dif_update_ce,
.final = crct10dif_final,
.descsize = CRC_T10DIF_DIGEST_SIZE,
@@ -65,19 +100,19 @@ static struct shash_alg crc_t10dif_alg = {
.base.cra_priority = 200,
.base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
-};
+}};
static int __init crc_t10dif_mod_init(void)
{
- if (!(elf_hwcap2 & HWCAP2_PMULL))
+ if (!(elf_hwcap & HWCAP_NEON))
return -ENODEV;
- return crypto_register_shash(&crc_t10dif_alg);
+ return crypto_register_shashes(algs, 1 + !!(elf_hwcap2 & HWCAP2_PMULL));
}
static void __exit crc_t10dif_mod_exit(void)
{
- crypto_unregister_shash(&crc_t10dif_alg);
+ crypto_unregister_shashes(algs, 1 + !!(elf_hwcap2 & HWCAP2_PMULL));
}
module_init(crc_t10dif_mod_init);
diff --git a/arch/arm/include/asm/arm_pmuv3.h b/arch/arm/include/asm/arm_pmuv3.h
index f63ba8986b24..2ec0e5e83fc9 100644
--- a/arch/arm/include/asm/arm_pmuv3.h
+++ b/arch/arm/include/asm/arm_pmuv3.h
@@ -212,6 +212,8 @@ static inline void write_pmuserenr(u32 val)
write_sysreg(val, PMUSERENR);
}
+static inline void write_pmuacr(u64 val) {}
+
static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
static inline void kvm_clr_pmu_events(u32 clr) {}
static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr)
@@ -231,6 +233,7 @@ static inline void kvm_vcpu_pmu_resync_el0(void) {}
#define ARMV8_PMU_DFR_VER_V3P1 0x4
#define ARMV8_PMU_DFR_VER_V3P4 0x5
#define ARMV8_PMU_DFR_VER_V3P5 0x6
+#define ARMV8_PMU_DFR_VER_V3P9 0x9
#define ARMV8_PMU_DFR_VER_IMP_DEF 0xF
static inline bool pmuv3_implemented(int pmuver)
@@ -249,6 +252,11 @@ static inline bool is_pmuv3p5(int pmuver)
return pmuver >= ARMV8_PMU_DFR_VER_V3P5;
}
+static inline bool is_pmuv3p9(int pmuver)
+{
+ return pmuver >= ARMV8_PMU_DFR_VER_V3P9;
+}
+
static inline u64 read_pmceid0(void)
{
u64 val = read_sysreg(PMCEID0);
diff --git a/arch/arm/include/asm/div64.h b/arch/arm/include/asm/div64.h
index 4b69cf850451..d3ef8e416b27 100644
--- a/arch/arm/include/asm/div64.h
+++ b/arch/arm/include/asm/div64.h
@@ -52,10 +52,17 @@ static inline uint32_t __div64_32(uint64_t *n, uint32_t base)
#else
-static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
+#ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
+static __always_inline
+#else
+static inline
+#endif
+uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
{
unsigned long long res;
register unsigned int tmp asm("ip") = 0;
+ bool no_ovf = __builtin_constant_p(m) &&
+ ((m >> 32) + (m & 0xffffffff) < 0x100000000);
if (!bias) {
asm ( "umull %Q0, %R0, %Q1, %Q2\n\t"
@@ -63,7 +70,7 @@ static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
: "=&r" (res)
: "r" (m), "r" (n)
: "cc");
- } else if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
+ } else if (no_ovf) {
res = m;
asm ( "umlal %Q0, %R0, %Q1, %Q2\n\t"
"mov %Q0, #0"
@@ -80,7 +87,7 @@ static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
: "cc");
}
- if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
+ if (no_ovf) {
asm ( "umlal %R0, %Q0, %R1, %Q2\n\t"
"umlal %R0, %Q0, %Q1, %R2\n\t"
"mov %R0, #0\n\t"
diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index e4eb54f6cd9f..a35aba7f548c 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -9,13 +9,17 @@
#define JUMP_LABEL_NOP_SIZE 4
+/* This macro is also expanded on the Rust side. */
+#define ARCH_STATIC_BRANCH_ASM(key, label) \
+ "1:\n\t" \
+ WASM(nop) "\n\t" \
+ ".pushsection __jump_table, \"aw\"\n\t" \
+ ".word 1b, " label ", " key "\n\t" \
+ ".popsection\n\t" \
+
static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
- asm goto("1:\n\t"
- WASM(nop) "\n\t"
- ".pushsection __jump_table, \"aw\"\n\t"
- ".word 1b, %l[l_yes], %c0\n\t"
- ".popsection\n\t"
+ asm goto(ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
: : "i" (&((char *)key)[branch]) : : l_yes);
return false;
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index ef2aa79ece5a..7c2fa7dcec6d 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -148,12 +148,6 @@ extern unsigned long vectors_base;
#endif
/*
- * Convert a page to/from a physical address
- */
-#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
-#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
-
-/*
* PLAT_PHYS_OFFSET is the offset (from zero) of the start of physical
* memory. This is used for XIP and NoMMU kernels, and on platforms that don't
* have CONFIG_ARM_PATCH_PHYS_VIRT. Assembly code must always use
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index 62af9f7f9e96..ef11b721230e 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -7,10 +7,7 @@
#ifndef _ASMARM_PAGE_H
#define _ASMARM_PAGE_H
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+#include <vdso/page.h>
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index bdbc1e590891..c08f16f2e243 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -8,13 +8,6 @@
#ifndef __ARM_PERF_EVENT_H__
#define __ARM_PERF_EVENT_H__
-#ifdef CONFIG_PERF_EVENTS
-struct pt_regs;
-extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
-extern unsigned long perf_misc_flags(struct pt_regs *regs);
-#define perf_misc_flags(regs) perf_misc_flags(regs)
-#endif
-
#define perf_arch_fetch_caller_regs(regs, __ip) { \
(regs)->ARM_pc = (__ip); \
frame_pointer((regs)) = (unsigned long) __builtin_frame_address(0); \
diff --git a/arch/arm/include/asm/spinlock_types.h b/arch/arm/include/asm/spinlock_types.h
index 0c14b36ef101..5404a2a96bf3 100644
--- a/arch/arm/include/asm/spinlock_types.h
+++ b/arch/arm/include/asm/spinlock_types.h
@@ -3,7 +3,7 @@
#define __ASM_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
#define TICKET_SHIFT 16
diff --git a/arch/arm/include/asm/patch.h b/arch/arm/include/asm/text-patching.h
index 0b48247c4600..0b48247c4600 100644
--- a/arch/arm/include/asm/patch.h
+++ b/arch/arm/include/asm/text-patching.h
diff --git a/arch/arm/include/asm/vdso/gettimeofday.h b/arch/arm/include/asm/vdso/gettimeofday.h
index 2134cbd5469f..592d3d015ca7 100644
--- a/arch/arm/include/asm/vdso/gettimeofday.h
+++ b/arch/arm/include/asm/vdso/gettimeofday.h
@@ -15,8 +15,6 @@
#define VDSO_HAS_CLOCK_GETRES 1
-extern struct vdso_data *__get_datapage(void);
-
static __always_inline int gettimeofday_fallback(
struct __kernel_old_timeval *_tv,
struct timezone *_tz)
@@ -139,7 +137,7 @@ static __always_inline u64 __arch_get_hw_counter(int clock_mode,
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{
- return __get_datapage();
+ return _vdso_data;
}
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arm/include/asm/vdso/vsyscall.h b/arch/arm/include/asm/vdso/vsyscall.h
index 47e41ae8ccd0..705414710dcd 100644
--- a/arch/arm/include/asm/vdso/vsyscall.h
+++ b/arch/arm/include/asm/vdso/vsyscall.h
@@ -4,16 +4,12 @@
#ifndef __ASSEMBLY__
-#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
#include <asm/cacheflush.h>
extern struct vdso_data *vdso_data;
extern bool cntvct_ok;
-/*
- * Update the vDSO data page to keep in sync with kernel timekeeping.
- */
static __always_inline
struct vdso_data *__arm_get_k_vdso_data(void)
{
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index fdb74e64206a..3b78966e750a 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -200,7 +200,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt_virt)
mdesc_best = &__mach_desc_GENERIC_DT;
- if (!dt_virt || !early_init_dt_verify(dt_virt))
+ if (!dt_virt || !early_init_dt_verify(dt_virt, __pa(dt_virt)))
return NULL;
mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 1dfae1af8e31..ef6a657c8d13 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -25,6 +25,7 @@
#include <asm/tls.h>
#include <asm/system_info.h>
#include <asm/uaccess-asm.h>
+#include <asm/kasan_def.h>
#include "entry-header.S"
#include <asm/probes.h>
@@ -561,6 +562,13 @@ ENTRY(__switch_to)
@ entries covering the vmalloc region.
@
ldr r2, [ip]
+#ifdef CONFIG_KASAN_VMALLOC
+ @ Also dummy read from the KASAN shadow memory for the new stack if we
+ @ are using KASAN
+ mov_l r2, KASAN_SHADOW_OFFSET
+ add r2, r2, ip, lsr #KASAN_SHADOW_SCALE_SHIFT
+ ldr r2, [r2]
+#endif
#endif
@ When CONFIG_THREAD_INFO_IN_TASK=n, the update of SP itself is what
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index e61591f33a6c..845acf9ce21e 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -23,7 +23,7 @@
#include <asm/insn.h>
#include <asm/set_memory.h>
#include <asm/stacktrace.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
/*
* The compiler emitted profiling hook consists of
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 1ec35f065617..f22c50d4bd41 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -252,18 +252,23 @@ __create_page_tables:
*/
add r0, r4, #KERNEL_OFFSET >> (SECTION_SHIFT - PMD_ENTRY_ORDER)
ldr r6, =(_end - 1)
+
+ /* For XIP, kernel_sec_start/kernel_sec_end are currently in RO memory */
+#ifndef CONFIG_XIP_KERNEL
adr_l r5, kernel_sec_start @ _pa(kernel_sec_start)
#if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32
str r8, [r5, #4] @ Save physical start of kernel (BE)
#else
str r8, [r5] @ Save physical start of kernel (LE)
#endif
+#endif
orr r3, r8, r7 @ Add the MMU flags
add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ENTRY_ORDER)
1: str r3, [r0], #1 << PMD_ENTRY_ORDER
add r3, r3, #1 << SECTION_SHIFT
cmp r0, r6
bls 1b
+#ifndef CONFIG_XIP_KERNEL
eor r3, r3, r7 @ Remove the MMU flags
adr_l r5, kernel_sec_end @ _pa(kernel_sec_end)
#if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32
@@ -271,8 +276,7 @@ __create_page_tables:
#else
str r3, [r5] @ Save physical end of kernel (LE)
#endif
-
-#ifdef CONFIG_XIP_KERNEL
+#else
/*
* Map the kernel image separately as it is not located in RAM.
*/
@@ -407,7 +411,11 @@ ENTRY(secondary_startup)
/*
* Use the page tables supplied from __cpu_up.
*/
+#ifdef CONFIG_XIP_KERNEL
+ ldr r3, =(secondary_data + PLAT_PHYS_OFFSET - PAGE_OFFSET)
+#else
adr_l r3, secondary_data
+#endif
mov_l r12, __secondary_switched
ldrd r4, r5, [r3, #0] @ get secondary_data.pgdir
ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE:
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index dab42d066d06..e1993e28a9ec 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -111,7 +111,7 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
- if (unlikely(!irq || irq >= nr_irqs))
+ if (unlikely(!irq || irq >= irq_get_nr_irqs()))
desc = NULL;
else
desc = irq_to_desc(irq);
@@ -151,7 +151,6 @@ void __init init_IRQ(void)
#ifdef CONFIG_SPARSE_IRQ
int __init arch_probe_nr_irqs(void)
{
- nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
- return nr_irqs;
+ return irq_set_nr_irqs(machine_desc->nr_irqs ? : NR_IRQS);
}
#endif
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c
index eb9c24b6e8e2..a06a92d0f550 100644
--- a/arch/arm/kernel/jump_label.c
+++ b/arch/arm/kernel/jump_label.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
#include <linux/jump_label.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/insn.h>
static void __arch_jump_label_transform(struct jump_entry *entry,
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
index 22f937e6f3ff..ab76c55fd610 100644
--- a/arch/arm/kernel/kgdb.c
+++ b/arch/arm/kernel/kgdb.c
@@ -15,7 +15,7 @@
#include <linux/kgdb.h>
#include <linux/uaccess.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/traps.h>
struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c
index e9e828b6bb30..4d45e60cd46d 100644
--- a/arch/arm/kernel/patch.c
+++ b/arch/arm/kernel/patch.c
@@ -9,7 +9,7 @@
#include <asm/fixmap.h>
#include <asm/smp_plat.h>
#include <asm/opcodes.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
struct patch {
void *addr;
diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c
index 1d230ac9d0eb..a2601b1ef318 100644
--- a/arch/arm/kernel/perf_callchain.c
+++ b/arch/arm/kernel/perf_callchain.c
@@ -96,20 +96,3 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
arm_get_current_stackframe(regs, &fr);
walk_stackframe(&fr, callchain_trace, entry);
}
-
-unsigned long perf_instruction_pointer(struct pt_regs *regs)
-{
- return instruction_pointer(regs);
-}
-
-unsigned long perf_misc_flags(struct pt_regs *regs)
-{
- int misc = 0;
-
- if (user_mode(regs))
- misc |= PERF_RECORD_MISC_USER;
- else
- misc |= PERF_RECORD_MISC_KERNEL;
-
- return misc;
-}
diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c
index d4392e177484..3bb0c4dcfc5c 100644
--- a/arch/arm/kernel/psci_smp.c
+++ b/arch/arm/kernel/psci_smp.c
@@ -45,8 +45,15 @@ extern void secondary_startup(void);
static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
if (psci_ops.cpu_on)
+#ifdef CONFIG_XIP_KERNEL
+ return psci_ops.cpu_on(cpu_logical_map(cpu),
+ ((phys_addr_t)(&secondary_startup)
+ - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+ + CONFIG_XIP_PHYS_ADDR));
+#else
return psci_ops.cpu_on(cpu_logical_map(cpu),
virt_to_idmap(&secondary_startup));
+#endif
return -ENODEV;
}
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 9a14f721a2b0..42a3706e16a6 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -93,7 +93,6 @@ static void twd_timer_stop(void)
{
struct clock_event_device *clk = raw_cpu_ptr(twd_evt);
- twd_shutdown(clk);
disable_percpu_irq(clk->irq);
}
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index f5781ff54a5c..2944721e82a2 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -235,12 +235,12 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
- struct fd f = fdget_raw(fd);
+ CLASS(fd_raw, f)(fd);
struct flock64 flock;
- long err = -EBADF;
+ long err;
- if (!fd_file(f))
- goto out;
+ if (fd_empty(f))
+ return -EBADF;
switch (cmd) {
case F_GETLK64:
@@ -271,8 +271,6 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
err = sys_fcntl64(fd, cmd, arg);
break;
}
- fdput(f);
-out:
return err;
}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 480e307501bb..6ea645939573 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -570,6 +570,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
static inline int
__do_cache_op(unsigned long start, unsigned long end)
{
+ unsigned int ua_flags;
int ret;
do {
@@ -578,7 +579,9 @@ __do_cache_op(unsigned long start, unsigned long end)
if (fatal_signal_pending(current))
return 0;
+ ua_flags = uaccess_save_and_enable();
ret = flush_icache_user_range(start, start + chunk);
+ uaccess_restore(ua_flags);
if (ret)
return ret;
diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
index d499ad461b00..29dd2f3c62fe 100644
--- a/arch/arm/kernel/vdso.c
+++ b/arch/arm/kernel/vdso.c
@@ -14,7 +14,6 @@
#include <linux/of.h>
#include <linux/printk.h>
#include <linux/slab.h>
-#include <linux/timekeeper_internal.h>
#include <linux/vmalloc.h>
#include <asm/arch_timer.h>
#include <asm/barrier.h>
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index 2e523f29ec3b..6baedf4c6304 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -58,5 +58,6 @@ endif
# BCMBCA
ifeq ($(CONFIG_ARCH_BCMBCA),y)
+obj-$(CONFIG_DEBUG_BCMBCA) += board_bcmbca.o
obj-$(CONFIG_SMP) += bcm63xx_smp.o bcm63xx_pmb.o
endif
diff --git a/arch/arm/mach-bcm/board_bcmbca.c b/arch/arm/mach-bcm/board_bcmbca.c
new file mode 100644
index 000000000000..b510d959870a
--- /dev/null
+++ b/arch/arm/mach-bcm/board_bcmbca.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2024 Linus Walleij <linus.walleij@linaro.org>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+/* This is needed for LL-debug/earlyprintk/debug-macro.S */
+static struct map_desc bcmbca_io_desc[] __initdata = {
+ {
+ .virtual = CONFIG_DEBUG_UART_VIRT,
+ .pfn = __phys_to_pfn(CONFIG_DEBUG_UART_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init bcmbca_map_io(void)
+{
+ iotable_init(bcmbca_io_desc, ARRAY_SIZE(bcmbca_io_desc));
+}
+
+static const char * const bcmbca_dt_compat[] = {
+ /* TODO: Add other BCMBCA SoCs here to get debug UART support */
+ "brcm,bcm6846",
+ NULL,
+};
+
+DT_MACHINE_START(BCMBCA_DT, "BCMBCA Broadband Access Processors")
+ .map_io = bcmbca_map_io,
+ .dt_compat = bcmbca_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-bcm/brcmstb.c b/arch/arm/mach-bcm/brcmstb.c
index 43bc98e388bf..27948b515993 100644
--- a/arch/arm/mach-bcm/brcmstb.c
+++ b/arch/arm/mach-bcm/brcmstb.c
@@ -23,11 +23,6 @@ u32 brcmstb_uart_config[3] = {
0,
};
-static void __init brcmstb_init_irq(void)
-{
- irqchip_init();
-}
-
static const char *const brcmstb_match[] __initconst = {
"brcm,bcm7445",
"brcm,brcmstb",
@@ -36,5 +31,4 @@ static const char *const brcmstb_match[] __initconst = {
DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)")
.dt_compat = brcmstb_match,
- .init_irq = brcmstb_init_irq,
MACHINE_END
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index ab767f059929..e4fe059cd861 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -6,7 +6,6 @@ menuconfig ARCH_MXC
select CLKSRC_IMX_GPT
select GENERIC_IRQ_CHIP
select GPIOLIB
- select PINCTRL
select PM_OPP if PM
select SOC_BUS
select SRAM
@@ -49,7 +48,6 @@ config SOC_IMX31
config SOC_IMX35
bool "i.MX35 support"
select MXC_AVIC
- select PINCTRL_IMX35
help
This enables support for Freescale i.MX35 processor
@@ -61,7 +59,6 @@ config SOC_IMX1
bool "i.MX1 support"
select CPU_ARM920T
select MXC_AVIC
- select PINCTRL_IMX1
help
This enables support for Freescale i.MX1 processor
@@ -73,7 +70,6 @@ config SOC_IMX25
bool "i.MX25 support"
select CPU_ARM926T
select MXC_AVIC
- select PINCTRL_IMX25
help
This enables support for Freescale i.MX25 processor
@@ -81,7 +77,6 @@ config SOC_IMX27
bool "i.MX27 support"
select CPU_ARM926T
select MXC_AVIC
- select PINCTRL_IMX27
help
This enables support for Freescale i.MX27 processor
@@ -98,7 +93,6 @@ config SOC_IMX5
config SOC_IMX50
bool "i.MX50 support"
- select PINCTRL_IMX50
select SOC_IMX5
help
@@ -106,14 +100,12 @@ config SOC_IMX50
config SOC_IMX51
bool "i.MX51 support"
- select PINCTRL_IMX51
select SOC_IMX5
help
This enables support for Freescale i.MX51 processor
config SOC_IMX53
bool "i.MX53 support"
- select PINCTRL_IMX53
select SOC_IMX5
help
@@ -137,7 +129,6 @@ config SOC_IMX6Q
select ARM_ERRATA_775420
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD
- select PINCTRL_IMX6Q
select SOC_IMX6
help
@@ -147,7 +138,6 @@ config SOC_IMX6SL
bool "i.MX6 SoloLite support"
select ARM_ERRATA_754322
select ARM_ERRATA_775420
- select PINCTRL_IMX6SL
select SOC_IMX6
help
@@ -157,7 +147,6 @@ config SOC_IMX6SLL
bool "i.MX6 SoloLiteLite support"
select ARM_ERRATA_754322
select ARM_ERRATA_775420
- select PINCTRL_IMX6SLL
select SOC_IMX6
help
@@ -167,7 +156,6 @@ config SOC_IMX6SX
bool "i.MX6 SoloX support"
select ARM_ERRATA_754322
select ARM_ERRATA_775420
- select PINCTRL_IMX6SX
select SOC_IMX6
help
@@ -175,7 +163,6 @@ config SOC_IMX6SX
config SOC_IMX6UL
bool "i.MX6 UltraLite support"
- select PINCTRL_IMX6UL
select SOC_IMX6
select ARM_ERRATA_814220
@@ -211,7 +198,6 @@ config SOC_IMX7D_CM4
config SOC_IMX7D
bool "i.MX7 Dual support"
- select PINCTRL_IMX7D
select SOC_IMX7D_CA7 if ARCH_MULTI_V7
select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
select ARM_ERRATA_814220 if ARCH_MULTI_V7
@@ -221,7 +207,6 @@ config SOC_IMX7D
config SOC_IMX7ULP
bool "i.MX7ULP support"
select CLKSRC_IMX_TPM
- select PINCTRL_IMX7ULP
select SOC_IMX7D_CA7 if ARCH_MULTI_V7
select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
help
@@ -237,7 +222,6 @@ config SOC_IMXRT
config SOC_VF610
bool "Vybrid Family VF610 support"
select ARM_GIC if ARCH_MULTI_V7
- select PINCTRL_VF610
help
This enables support for Freescale Vybrid VF610 processor.
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index b36f05b54cc7..a671ca498f88 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -634,13 +634,11 @@ static void imx6_pm_stby_poweroff(void)
static int imx6_pm_stby_poweroff_probe(void)
{
- if (pm_power_off) {
- pr_warn("%s: pm_power_off already claimed %p %ps!\n",
- __func__, pm_power_off, pm_power_off);
+ if (register_platform_power_off(imx6_pm_stby_poweroff)) {
+ pr_warn("%s: platform power off already claimed!\n", __func__);
return -EBUSY;
}
- pm_power_off = imx6_pm_stby_poweroff;
return 0;
}
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index 60e662324699..83a79d0c0bec 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -9,7 +9,6 @@
#ifndef __MACH_ZYNQ_COMMON_H__
#define __MACH_ZYNQ_COMMON_H__
-extern int zynq_slcr_init(void);
extern int zynq_early_slcr_init(void);
extern void zynq_slcr_cpu_stop(int cpu);
extern void zynq_slcr_cpu_start(int cpu);
diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c
index 97db5397c320..fecac107fd0d 100644
--- a/arch/arm/mm/dma-mapping-nommu.c
+++ b/arch/arm/mm/dma-mapping-nommu.c
@@ -39,7 +39,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent)
/*
* Cache support for v7m is optional, so can be treated as
* coherent if no cache has been detected. Note that it is not
- * enough to check if MPU is in use or not since in absense of
+ * enough to check if MPU is in use or not since in absence of
* MPU system memory map is used.
*/
dev->dma_coherent = cacheid ? coherent : true;
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 831793cd6ff9..2bec87c3327d 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -61,32 +61,8 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address,
return ret;
}
-#if defined(CONFIG_SPLIT_PTE_PTLOCKS)
-/*
- * If we are using split PTE locks, then we need to take the page
- * lock here. Otherwise we are using shared mm->page_table_lock
- * which is already locked, thus cannot take it.
- */
-static inline void do_pte_lock(spinlock_t *ptl)
-{
- /*
- * Use nested version here to indicate that we are already
- * holding one similar spinlock.
- */
- spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
-}
-
-static inline void do_pte_unlock(spinlock_t *ptl)
-{
- spin_unlock(ptl);
-}
-#else /* !defined(CONFIG_SPLIT_PTE_PTLOCKS) */
-static inline void do_pte_lock(spinlock_t *ptl) {}
-static inline void do_pte_unlock(spinlock_t *ptl) {}
-#endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */
-
static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
- unsigned long pfn)
+ unsigned long pfn, struct vm_fault *vmf)
{
spinlock_t *ptl;
pgd_t *pgd;
@@ -94,6 +70,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
+ pmd_t pmdval;
int ret;
pgd = pgd_offset(vma->vm_mm, address);
@@ -112,20 +89,33 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
if (pmd_none_or_clear_bad(pmd))
return 0;
+again:
/*
* This is called while another page table is mapped, so we
* must use the nested version. This also means we need to
* open-code the spin-locking.
*/
- pte = pte_offset_map_nolock(vma->vm_mm, pmd, address, &ptl);
+ pte = pte_offset_map_rw_nolock(vma->vm_mm, pmd, address, &pmdval, &ptl);
if (!pte)
return 0;
- do_pte_lock(ptl);
+ /*
+ * If we are using split PTE locks, then we need to take the page
+ * lock here. Otherwise we are using shared mm->page_table_lock
+ * which is already locked, thus cannot take it.
+ */
+ if (ptl != vmf->ptl) {
+ spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
+ if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmd)))) {
+ pte_unmap_unlock(pte, ptl);
+ goto again;
+ }
+ }
ret = do_adjust_pte(vma, address, pfn, pte);
- do_pte_unlock(ptl);
+ if (ptl != vmf->ptl)
+ spin_unlock(ptl);
pte_unmap(pte);
return ret;
@@ -133,7 +123,8 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
static void
make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
- unsigned long addr, pte_t *ptep, unsigned long pfn)
+ unsigned long addr, pte_t *ptep, unsigned long pfn,
+ struct vm_fault *vmf)
{
struct mm_struct *mm = vma->vm_mm;
struct vm_area_struct *mpnt;
@@ -160,7 +151,7 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
if (!(mpnt->vm_flags & VM_MAYSHARE))
continue;
offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
- aliases += adjust_pte(mpnt, mpnt->vm_start + offset, pfn);
+ aliases += adjust_pte(mpnt, mpnt->vm_start + offset, pfn, vmf);
}
flush_dcache_mmap_unlock(mapping);
if (aliases)
@@ -203,7 +194,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
__flush_dcache_folio(mapping, folio);
if (mapping) {
if (cache_is_vivt())
- make_coherent(mapping, vma, addr, ptep, pfn);
+ make_coherent(mapping, vma, addr, ptep, pfn, vmf);
else if (vma->vm_flags & VM_EXEC)
__flush_icache_all();
}
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index 448e57c6f653..4a833e89782a 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -84,8 +84,15 @@ static void identity_mapping_add(pgd_t *pgd, const char *text_start,
unsigned long addr, end;
unsigned long next;
+#ifdef CONFIG_XIP_KERNEL
+ addr = (phys_addr_t)(text_start) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+ + CONFIG_XIP_PHYS_ADDR;
+ end = (phys_addr_t)(text_end) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+ + CONFIG_XIP_PHYS_ADDR;
+#else
addr = virt_to_idmap(text_start);
end = virt_to_idmap(text_end);
+#endif
pr_info("Setting up static identity map for 0x%lx - 0x%lx\n", addr, end);
prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 794cfea9f9d4..89f1c97f3079 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -23,6 +23,7 @@
*/
#include <linux/module.h>
#include <linux/errno.h>
+#include <linux/kasan.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/io.h>
@@ -115,16 +116,40 @@ int ioremap_page(unsigned long virt, unsigned long phys,
}
EXPORT_SYMBOL(ioremap_page);
+#ifdef CONFIG_KASAN
+static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
+{
+ return (unsigned long)kasan_mem_to_shadow((void *)addr);
+}
+#else
+static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
+{
+ return 0;
+}
+#endif
+
+static void memcpy_pgd(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ end = ALIGN(end, PGDIR_SIZE);
+ memcpy(pgd_offset(mm, start), pgd_offset_k(start),
+ sizeof(pgd_t) * (pgd_index(end) - pgd_index(start)));
+}
+
void __check_vmalloc_seq(struct mm_struct *mm)
{
int seq;
do {
- seq = atomic_read(&init_mm.context.vmalloc_seq);
- memcpy(pgd_offset(mm, VMALLOC_START),
- pgd_offset_k(VMALLOC_START),
- sizeof(pgd_t) * (pgd_index(VMALLOC_END) -
- pgd_index(VMALLOC_START)));
+ seq = atomic_read_acquire(&init_mm.context.vmalloc_seq);
+ memcpy_pgd(mm, VMALLOC_START, VMALLOC_END);
+ if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
+ unsigned long start =
+ arm_kasan_mem_to_shadow(VMALLOC_START);
+ unsigned long end =
+ arm_kasan_mem_to_shadow(VMALLOC_END);
+ memcpy_pgd(mm, start, end);
+ }
/*
* Use a store-release so that other CPUs that observe the
* counter's new value are guaranteed to see the results of the
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index f85c177cdf8d..f5b7a16c5803 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1403,18 +1403,6 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
}
/*
- * Map the kernel if it is XIP.
- * It is always first in the modulearea.
- */
-#ifdef CONFIG_XIP_KERNEL
- map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
- map.virtual = MODULES_VADDR;
- map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
- map.type = MT_ROM;
- create_mapping(&map);
-#endif
-
- /*
* Map the cache flushing regions.
*/
#ifdef FLUSH_BASE
@@ -1603,12 +1591,27 @@ static void __init map_kernel(void)
* This will only persist until we turn on proper memory management later on
* and we remap the whole kernel with page granularity.
*/
+#ifdef CONFIG_XIP_KERNEL
+ phys_addr_t kernel_nx_start = kernel_sec_start;
+#else
phys_addr_t kernel_x_start = kernel_sec_start;
phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
phys_addr_t kernel_nx_start = kernel_x_end;
+#endif
phys_addr_t kernel_nx_end = kernel_sec_end;
struct map_desc map;
+ /*
+ * Map the kernel if it is XIP.
+ * It is always first in the modulearea.
+ */
+#ifdef CONFIG_XIP_KERNEL
+ map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
+ map.virtual = MODULES_VADDR;
+ map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
+ map.type = MT_ROM;
+ create_mapping(&map);
+#else
map.pfn = __phys_to_pfn(kernel_x_start);
map.virtual = __phys_to_virt(kernel_x_start);
map.length = kernel_x_end - kernel_x_start;
@@ -1618,7 +1621,7 @@ static void __init map_kernel(void)
/* If the nx part is small it may end up covered by the tail of the RWX section */
if (kernel_x_end == kernel_nx_end)
return;
-
+#endif
map.pfn = __phys_to_pfn(kernel_nx_start);
map.virtual = __phys_to_virt(kernel_nx_start);
map.length = kernel_nx_end - kernel_nx_start;
@@ -1764,6 +1767,11 @@ void __init paging_init(const struct machine_desc *mdesc)
{
void *zero_page;
+#ifdef CONFIG_XIP_KERNEL
+ /* Store the kernel RW RAM region start/end in these variables */
+ kernel_sec_start = CONFIG_PHYS_OFFSET & SECTION_MASK;
+ kernel_sec_end = round_up(__pa(_end), SECTION_SIZE);
+#endif
pr_debug("physical kernel sections: 0x%08llx-0x%08llx\n",
kernel_sec_start, kernel_sec_end);
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 5fb9a6aecb00..2cd933342679 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -94,7 +94,7 @@ SYM_TYPED_FUNC_START(cpu_v7_dcache_clean_area)
ret lr
SYM_FUNC_END(cpu_v7_dcache_clean_area)
-#ifdef CONFIG_ARM_PSCI
+#if defined(CONFIG_ARM_PSCI) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
.arch_extension sec
SYM_TYPED_FUNC_START(cpu_v7_smc_switch_mm)
stmfd sp!, {r0 - r3}
diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c
index d8238da095df..9fd877c87a38 100644
--- a/arch/arm/probes/kprobes/core.c
+++ b/arch/arm/probes/kprobes/core.c
@@ -25,7 +25,7 @@
#include <asm/cacheflush.h>
#include <linux/percpu.h>
#include <linux/bug.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/sections.h>
#include "../decode-arm.h"
diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c
index 7f65048380ca..966c6042c5ad 100644
--- a/arch/arm/probes/kprobes/opt-arm.c
+++ b/arch/arm/probes/kprobes/opt-arm.c
@@ -14,7 +14,7 @@
/* for arm_gen_branch */
#include <asm/insn.h>
/* for patch_text */
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include "core.h"
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index 23c98203c40f..49eeb2ad8dbd 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -477,3 +477,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile
index 01067a2bc43b..8a306bbec4a0 100644
--- a/arch/arm/vdso/Makefile
+++ b/arch/arm/vdso/Makefile
@@ -5,7 +5,7 @@ include $(srctree)/lib/vdso/Makefile
hostprogs := vdsomunge
-obj-vdso := vgettimeofday.o datapage.o note.o
+obj-vdso := vgettimeofday.o note.o
# Build rules
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds
diff --git a/arch/arm/vdso/datapage.S b/arch/arm/vdso/datapage.S
deleted file mode 100644
index 9cd73b725d9f..000000000000
--- a/arch/arm/vdso/datapage.S
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <linux/linkage.h>
-#include <asm/asm-offsets.h>
-
- .align 2
-.L_vdso_data_ptr:
- .long _start - . - VDSO_DATA_SIZE
-
-ENTRY(__get_datapage)
- .fnstart
- adr r0, .L_vdso_data_ptr
- ldr r1, [r0]
- add r0, r0, r1
- bx lr
- .fnend
-ENDPROC(__get_datapage)
diff --git a/arch/arm/vdso/vdso.lds.S b/arch/arm/vdso/vdso.lds.S
index 165d1d2eb76b..9bfa0f52923c 100644
--- a/arch/arm/vdso/vdso.lds.S
+++ b/arch/arm/vdso/vdso.lds.S
@@ -11,6 +11,7 @@
*/
#include <linux/const.h>
+#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/vdso.h>
@@ -19,7 +20,7 @@ OUTPUT_ARCH(arm)
SECTIONS
{
- PROVIDE(_start = .);
+ PROVIDE(_vdso_data = . - VDSO_DATA_SIZE);
. = SIZEOF_HEADERS;
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index b68efe643a12..d44867fc0c5e 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -56,6 +56,34 @@ extern unsigned int VFP_arch_feroceon __alias(VFP_arch);
union vfp_state *vfp_current_hw_state[NR_CPUS];
/*
+ * Claim ownership of the VFP unit.
+ *
+ * The caller may change VFP registers until vfp_state_release() is called.
+ *
+ * local_bh_disable() is used to disable preemption and to disable VFP
+ * processing in softirq context. On PREEMPT_RT kernels local_bh_disable() is
+ * not sufficient because it only serializes soft interrupt related sections
+ * via a local lock, but stays preemptible. Disabling preemption is the right
+ * choice here as bottom half processing is always in thread context on RT
+ * kernels so it implicitly prevents bottom half processing as well.
+ */
+static void vfp_state_hold(void)
+{
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+ local_bh_disable();
+ else
+ preempt_disable();
+}
+
+static void vfp_state_release(void)
+{
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+ local_bh_enable();
+ else
+ preempt_enable();
+}
+
+/*
* Is 'thread's most up to date state stored in this CPUs hardware?
* Must be called from non-preemptible context.
*/
@@ -240,7 +268,7 @@ static void vfp_panic(char *reason, u32 inst)
/*
* Process bitmask of exception conditions.
*/
-static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs)
+static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr)
{
int si_code = 0;
@@ -248,8 +276,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
if (exceptions == VFP_EXCEPTION_ERROR) {
vfp_panic("unhandled bounce", inst);
- vfp_raise_sigfpe(FPE_FLTINV, regs);
- return;
+ return FPE_FLTINV;
}
/*
@@ -277,8 +304,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
- if (si_code)
- vfp_raise_sigfpe(si_code, regs);
+ return si_code;
}
/*
@@ -324,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
{
u32 fpscr, orig_fpscr, fpsid, exceptions;
+ int si_code2 = 0;
+ int si_code = 0;
pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
@@ -369,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
* unallocated VFP instruction but with FPSCR.IXE set and not
* on VFP subarch 1.
*/
- vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
- return;
+ si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr);
+ goto exit;
}
/*
@@ -394,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
*/
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
if (exceptions)
- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
+ si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
/*
* If there isn't a second FP instruction, exit now. Note that
* the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
*/
if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
- return;
+ goto exit;
/*
* The barrier() here prevents fpinst2 being read
@@ -413,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
emulate:
exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
if (exceptions)
- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
+ si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
+exit:
+ vfp_state_release();
+ if (si_code2)
+ vfp_raise_sigfpe(si_code2, regs);
+ if (si_code)
+ vfp_raise_sigfpe(si_code, regs);
}
static void vfp_enable(void *unused)
@@ -512,11 +546,9 @@ static inline void vfp_pm_init(void) { }
*/
void vfp_sync_hwstate(struct thread_info *thread)
{
- unsigned int cpu = get_cpu();
+ vfp_state_hold();
- local_bh_disable();
-
- if (vfp_state_in_hw(cpu, thread)) {
+ if (vfp_state_in_hw(raw_smp_processor_id(), thread)) {
u32 fpexc = fmrx(FPEXC);
/*
@@ -527,8 +559,7 @@ void vfp_sync_hwstate(struct thread_info *thread)
fmxr(FPEXC, fpexc);
}
- local_bh_enable();
- put_cpu();
+ vfp_state_release();
}
/* Ensure that the thread reloads the hardware VFP state on the next use. */
@@ -683,7 +714,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
if (!user_mode(regs))
return vfp_kmode_exception(regs, trigger);
- local_bh_disable();
+ vfp_state_hold();
fpexc = fmrx(FPEXC);
/*
@@ -748,6 +779,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
* replay the instruction that trapped.
*/
fmxr(FPEXC, fpexc);
+ vfp_state_release();
} else {
/* Check for synchronous or asynchronous exceptions */
if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) {
@@ -762,17 +794,17 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
if (!(fpscr & FPSCR_IXE)) {
if (!(fpscr & FPSCR_LENGTH_MASK)) {
pr_debug("not VFP\n");
- local_bh_enable();
+ vfp_state_release();
return -ENOEXEC;
}
fpexc |= FPEXC_DEX;
}
}
bounce: regs->ARM_pc += 4;
+ /* VFP_bounce() will invoke vfp_state_release() */
VFP_bounce(trigger, fpexc, regs);
}
- local_bh_enable();
return 0;
}
@@ -837,7 +869,7 @@ void kernel_neon_begin(void)
unsigned int cpu;
u32 fpexc;
- local_bh_disable();
+ vfp_state_hold();
/*
* Kernel mode NEON is only allowed outside of hardirq context with
@@ -868,7 +900,7 @@ void kernel_neon_end(void)
{
/* Disable the NEON/VFP unit. */
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
- local_bh_enable();
+ vfp_state_release();
}
EXPORT_SYMBOL(kernel_neon_end);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index fd9df6dcc593..100570a048c5 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -14,13 +14,13 @@ config ARM64
select ARCH_HAS_DEBUG_WX
select ARCH_BINFMT_ELF_EXTRA_PHDRS
select ARCH_BINFMT_ELF_STATE
- select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
select ARCH_HAS_CACHE_LINE_SIZE
+ select ARCH_HAS_CC_PLATFORM
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE
@@ -38,12 +38,15 @@ config ARM64
select ARCH_HAS_MEM_ENCRYPT
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+ select ARCH_HAS_NONLEAF_PMD_YOUNG if ARM64_HAFT
select ARCH_HAS_PTE_DEVMAP
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_HW_PTE_YOUNG
select ARCH_HAS_SETUP_DMA_OPS
select ARCH_HAS_SET_DIRECT_MAP
select ARCH_HAS_SET_MEMORY
+ select ARCH_HAS_MEM_ENCRYPT
+ select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select ARCH_STACKWALK
select ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_HAS_STRICT_MODULE_RWX
@@ -1232,6 +1235,17 @@ config HISILICON_ERRATUM_161600802
If unsure, say Y.
+config HISILICON_ERRATUM_162100801
+ bool "Hip09 162100801 erratum support"
+ default y
+ help
+ When enabling GICv4.1 in hip09, VMAPP will fail to clear some caches
+ during unmapping operation, which will cause some vSGIs lost.
+ To fix the issue, invalidate related vPE cache through GICR_INVALLR
+ after VMOVP.
+
+ If unsure, say Y.
+
config QCOM_FALKOR_ERRATUM_1003
bool "Falkor E1003: Incorrect translation due to ASID change"
default y
@@ -1576,6 +1590,9 @@ config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG
config ARCH_SUPPORTS_CRASH_DUMP
def_bool y
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
def_bool CRASH_RESERVE
@@ -2156,6 +2173,9 @@ config ARM64_EPAN
if the cpu does not implement the feature.
endmenu # "ARMv8.7 architectural features"
+config AS_HAS_MOPS
+ def_bool $(as-instr,.arch_extension mops)
+
menu "ARMv8.9 architectural features"
config ARM64_POE
@@ -2177,8 +2197,44 @@ config ARCH_PKEY_BITS
int
default 3
+config ARM64_HAFT
+ bool "Support for Hardware managed Access Flag for Table Descriptors"
+ depends on ARM64_HW_AFDBM
+ default y
+ help
+ The ARMv8.9/ARMv9.5 introduces the feature Hardware managed Access
+ Flag for Table descriptors. When enabled an architectural executed
+ memory access will update the Access Flag in each Table descriptor
+ which is accessed during the translation table walk and for which
+ the Access Flag is 0. The Access Flag of the Table descriptor use
+ the same bit of PTE_AF.
+
+ The feature will only be enabled if all the CPUs in the system
+ support this feature. If unsure, say Y.
+
endmenu # "ARMv8.9 architectural features"
+menu "v9.4 architectural features"
+
+config ARM64_GCS
+ bool "Enable support for Guarded Control Stack (GCS)"
+ default y
+ select ARCH_HAS_USER_SHADOW_STACK
+ select ARCH_USES_HIGH_VMA_FLAGS
+ depends on !UPROBES
+ help
+ Guarded Control Stack (GCS) provides support for a separate
+ stack with restricted access which contains only return
+ addresses. This can be used to harden against some attacks
+ by comparing return address used by the program with what is
+ stored in the GCS, and may also be used to efficiently obtain
+ the call stack for applications such as profiling.
+
+ The feature is detected at runtime, and will remain disabled
+ if the system does not implement the feature.
+
+endmenu # "v9.4 architectural features"
+
config ARM64_SVE
bool "ARM Scalable Vector Extension support"
default y
@@ -2214,6 +2270,7 @@ config ARM64_SME
bool "ARM Scalable Matrix Extension support"
default y
depends on ARM64_SVE
+ depends on BROKEN
help
The Scalable Matrix Extension (SME) is an extension to the AArch64
execution state which utilises a substantial subset of the SVE
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 6c6d11536b42..370a9d2b6919 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -37,8 +37,8 @@ config ARCH_APPLE
bool "Apple Silicon SoC family"
select APPLE_AIC
help
- This enables support for Apple's in-house ARM SoC family, starting
- with the Apple M1.
+ This enables support for Apple's in-house ARM SoC family, such
+ as the Apple M1.
menuconfig ARCH_BCM
bool "Broadcom SoC Support"
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 9efd3f37c2fd..358c68565bfd 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -71,7 +71,7 @@ stack_protector_prepare: prepare0
-mstack-protector-guard-reg=sp_el0 \
-mstack-protector-guard-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
endif
ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
index f5c5c1464482..a387bccdcefd 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
@@ -7,6 +7,8 @@
#include "sun50i-a100.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
/{
model = "Allwinner A100 Perf1";
compatible = "allwinner,a100-perf1", "allwinner,sun50i-a100";
@@ -20,6 +22,22 @@
};
};
+&mmc0 {
+ vmmc-supply = <&reg_dcdc1>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc2 {
+ vmmc-supply = <&reg_dcdc1>;
+ vqmmc-supply = <&reg_aldo1>;
+ cap-mmc-hw-reset;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
+};
+
&pio {
vcc-pb-supply = <&reg_dcdc1>;
vcc-pc-supply = <&reg_eldo1>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index a3dccf193765..29ac7716c7a5 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -25,21 +25,21 @@
enable-method = "psci";
};
- cpu@1 {
+ cpu1: cpu@1 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x1>;
enable-method = "psci";
};
- cpu@2 {
+ cpu2: cpu@2 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x2>;
enable-method = "psci";
};
- cpu@3 {
+ cpu3: cpu@3 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x3>;
@@ -47,6 +47,15 @@
};
};
+ pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <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>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
psci {
compatible = "arm,psci-1.0";
method = "smc";
@@ -135,6 +144,14 @@
};
};
+ watchdog@30090a0 {
+ compatible = "allwinner,sun50i-a100-wdt",
+ "allwinner,sun6i-a31-wdt";
+ reg = <0x030090a0 0x20>;
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo24M>;
+ };
+
pio: pinctrl@300b000 {
compatible = "allwinner,sun50i-a100-pinctrl";
reg = <0x0300b000 0x400>;
@@ -152,12 +169,83 @@
interrupt-controller;
#interrupt-cells = <3>;
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3",
+ "PF4", "PF5";
+ function = "mmc0";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ /omit-if-no-ref/
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3",
+ "PG4", "PG5";
+ function = "mmc1";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ mmc2_pins: mmc2-pins {
+ pins = "PC0", "PC1", "PC5", "PC6",
+ "PC8", "PC9", "PC10", "PC11",
+ "PC13", "PC14", "PC15", "PC16";
+ function = "mmc2";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
uart0_pb_pins: uart0-pb-pins {
pins = "PB9", "PB10";
function = "uart0";
};
};
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun50i-a100-mmc";
+ reg = <0x04020000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun50i-a100-mmc";
+ reg = <0x04021000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun50i-a100-emmc";
+ reg = <0x04022000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
uart0: serial@5000000 {
compatible = "snps,dw-apb-uart";
reg = <0x05000000 0x400>;
@@ -285,6 +373,97 @@
#thermal-sensor-cells = <1>;
};
+ usb_otg: usb@5100000 {
+ compatible = "allwinner,sun50i-a100-musb",
+ "allwinner,sun8i-a33-musb";
+ reg = <0x05100000 0x0400>;
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ extcon = <&usbphy 0>;
+ status = "disabled";
+ };
+
+ usbphy: phy@5100400 {
+ compatible = "allwinner,sun50i-a100-usb-phy",
+ "allwinner,sun20i-d1-usb-phy";
+ reg = <0x05100400 0x100>,
+ <0x05101800 0x100>,
+ <0x05200800 0x100>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1";
+ clocks = <&ccu CLK_USB_PHY0>,
+ <&ccu CLK_USB_PHY1>;
+ clock-names = "usb0_phy",
+ "usb1_phy";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>;
+ reset-names = "usb0_reset",
+ "usb1_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@5101000 {
+ compatible = "allwinner,sun50i-a100-ehci",
+ "generic-ehci";
+ reg = <0x05101000 0x100>;
+ interrupts = <GIC_SPI 30 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-a100-ohci",
+ "generic-ohci";
+ reg = <0x05101400 0x100>;
+ interrupts = <GIC_SPI 31 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-a100-ehci",
+ "generic-ehci";
+ reg = <0x05200000 0x100>;
+ interrupts = <GIC_SPI 33 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-a100-ohci",
+ "generic-ohci";
+ reg = <0x05200400 0x100>;
+ interrupts = <GIC_SPI 34 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";
+ };
+
r_ccu: clock@7010000 {
compatible = "allwinner,sun50i-a100-r-ccu";
reg = <0x07010000 0x300>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
index 6eab61a12cd8..4bc6c1ef2cde 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
@@ -188,12 +188,30 @@
&i2c1 {
status = "okay";
+ /* Alternative magnetometer */
+ af8133j: magnetometer@1c {
+ compatible = "voltafield,af8133j";
+ reg = <0x1c>;
+ reset-gpios = <&pio 1 1 GPIO_ACTIVE_LOW>;
+ avdd-supply = <&reg_dldo1>;
+ dvdd-supply = <&reg_dldo1>;
+ mount-matrix = "0", "-1", "0",
+ "-1", "0", "0",
+ "0", "0", "-1";
+
+ /* status will be fixed up in firmware */
+ status = "disabled";
+ };
+
/* Magnetometer */
lis3mdl: magnetometer@1e {
compatible = "st,lis3mdl-magn";
reg = <0x1e>;
vdd-supply = <&reg_dldo1>;
vddio-supply = <&reg_dldo1>;
+ mount-matrix = "0", "1", "0",
+ "-1", "0", "0",
+ "0", "0", "1";
};
/* Light/proximity sensor */
@@ -212,6 +230,9 @@
interrupts = <7 5 IRQ_TYPE_EDGE_RISING>; /* PH5 */
vdd-supply = <&reg_dldo1>;
vddio-supply = <&reg_dldo1>;
+ mount-matrix = "0", "1", "0",
+ "-1", "0", "0",
+ "0", "0", "1";
};
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h313-tanix-tx1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h313-tanix-tx1.dts
index bb2cde59bd03..bafd3e803106 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h313-tanix-tx1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h313-tanix-tx1.dts
@@ -65,6 +65,11 @@
};
};
+&codec {
+ allwinner,audio-routing = "Line Out", "LINEOUT";
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&reg_dcdc2>;
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts
index 526443bb736c..18fa541795a6 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts
@@ -136,6 +136,7 @@
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ disable-wp;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
index 05486cccee1c..128295f5a5d6 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
@@ -88,6 +88,7 @@
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
+ disable-wp;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-r1s-h5.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-r1s-h5.dts
index 3a7ee44708a2..44fdc8b3f79d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-r1s-h5.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-r1s-h5.dts
@@ -157,6 +157,7 @@
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
+ disable-wp;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
index ce3ae19e72db..0f29da7d51e6 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
@@ -153,6 +153,7 @@
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
+ disable-wp;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
index b699bb900e13..d4fc4e60e4e7 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
@@ -153,6 +153,7 @@
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
+ disable-wp;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts
index ae85131aac9c..3322cc4d9aa4 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts
@@ -82,6 +82,7 @@
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
+ disable-wp;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
index 734481e998b8..3eb986c354a9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
@@ -79,6 +79,7 @@
&mmc0 {
vmmc-supply = <&reg_vcc3v3>;
+ disable-wp;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
index 3be1e8c2fdb9..13a0e63afeaf 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
@@ -129,6 +129,7 @@
&mmc0 {
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ disable-wp;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
index 6c3bfe3d09d9..ab87c3447cd7 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
@@ -131,6 +131,7 @@
&mmc0 {
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ disable-wp;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
index 13b07141c334..d05dc5d6e6b9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
@@ -94,6 +94,7 @@
&mmc0 {
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ disable-wp;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index c8b275552872..fa7a765ee828 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -133,6 +133,7 @@
&mmc0 {
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ disable-wp;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi
index 855b7d43bc50..bb7de37c0d58 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi
@@ -124,6 +124,7 @@
pinctrl-0 = <&mmc0_pins>;
vmmc-supply = <&reg_vcc3v3>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ disable-wp;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi
index fc7315b94406..908fa3b847a6 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi
@@ -59,6 +59,11 @@
};
};
+&codec {
+ allwinner,audio-routing = "Line Out", "LINEOUT";
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -81,6 +86,7 @@
&mmc0 {
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ disable-wp;
bus-width = <4>;
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 26d25b5b59e0..968960ebf1d1 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
@@ -33,6 +33,11 @@
};
};
+&codec {
+ allwinner,audio-routing = "Line Out", "LINEOUT";
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&reg_dcdca>;
};
@@ -52,6 +57,7 @@
&mmc0 {
vmmc-supply = <&reg_dcdce>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ disable-wp;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
index e88c1fbac6ac..cdce3dcb8ec0 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -630,21 +630,6 @@
};
};
- spdif: spdif@5093000 {
- compatible = "allwinner,sun50i-h616-spdif";
- reg = <0x05093000 0x400>;
- interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
- clock-names = "apb", "spdif";
- resets = <&ccu RST_BUS_SPDIF>;
- dmas = <&dma 2>;
- dma-names = "tx";
- pinctrl-names = "default";
- pinctrl-0 = <&spdif_tx_pin>;
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
gpadc: adc@5070000 {
compatible = "allwinner,sun50i-h616-gpadc",
"allwinner,sun20i-d1-gpadc";
@@ -679,6 +664,35 @@
status = "disabled";
};
+ spdif: spdif@5093000 {
+ compatible = "allwinner,sun50i-h616-spdif";
+ reg = <0x05093000 0x400>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
+ clock-names = "apb", "spdif";
+ resets = <&ccu RST_BUS_SPDIF>;
+ dmas = <&dma 2>;
+ dma-names = "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spdif_tx_pin>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ codec: codec@5096000 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun50i-h616-codec";
+ reg = <0x05096000 0x31c>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_AUDIO_CODEC>,
+ <&ccu CLK_AUDIO_CODEC_1X>;
+ clock-names = "apb", "codec";
+ resets = <&ccu RST_BUS_AUDIO_CODEC>;
+ dmas = <&dma 6>;
+ dma-names = "tx";
+ status = "disabled";
+ };
+
usbotg: usb@5100000 {
compatible = "allwinner,sun50i-h616-musb",
"allwinner,sun8i-h3-musb";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h618-longanpi-3h.dts b/arch/arm64/boot/dts/allwinner/sun50i-h618-longanpi-3h.dts
index 18b29c6b867f..16c68177ff69 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h618-longanpi-3h.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-longanpi-3h.dts
@@ -111,6 +111,7 @@
};
&mmc0 {
+ disable-wp;
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
vmmc-supply = <&reg_vcc3v3>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts b/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts
index 6a4f0da97233..a0fe7a9afb77 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts
@@ -54,6 +54,11 @@
};
};
+&codec {
+ allwinner,audio-routing = "Line Out", "LINEOUT";
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&reg_dcdc2>;
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h618-transpeed-8k618-t.dts b/arch/arm64/boot/dts/allwinner/sun50i-h618-transpeed-8k618-t.dts
index d6631bfe629f..f828ca1ce51e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h618-transpeed-8k618-t.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-transpeed-8k618-t.dts
@@ -52,6 +52,11 @@
};
};
+&codec {
+ allwinner,audio-routing = "Line Out", "LINEOUT";
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&reg_dcdc2>;
};
@@ -71,6 +76,7 @@
&mmc0 {
vmmc-supply = <&reg_dldo1>;
cd-gpios = <&pio 8 16 GPIO_ACTIVE_LOW>; /* PI16 */
+ disable-wp;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts
index 80ccab7b5ba7..a231abf1684a 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts
@@ -177,6 +177,12 @@
};
};
+&codec {
+ allwinner,audio-routing = "Line Out", "LINEOUT";
+ allwinner,pa-gpios = <&pio 8 5 GPIO_ACTIVE_HIGH>; // PI5
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&reg_dcdc1>;
};
@@ -270,7 +276,7 @@
reg_aldo4: aldo4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- regulator-name = "vcc-pg";
+ regulator-name = "avcc";
};
reg_bldo1: bldo1 {
@@ -293,7 +299,10 @@
};
reg_cldo1: cldo1 {
- /* 3.3v - audio codec - not yet implemented */
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-spkr-amp";
};
reg_cldo2: cldo2 {
diff --git a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts
index 1a65f1ec183d..7c82d90e940d 100644
--- a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts
+++ b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b0.dts
@@ -27,7 +27,6 @@
&ccp0 {
status = "okay";
- amd,zlib-support = <1>;
};
/**
diff --git a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts
index 52f8d36295a8..58e2b0a6f841 100644
--- a/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts
+++ b/arch/arm64/boot/dts/amd/amd-overdrive-rev-b1.dts
@@ -27,7 +27,6 @@
&ccp0 {
status = "okay";
- amd,zlib-support = <1>;
};
/**
diff --git a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
index 690020589d41..d3d931eb7677 100644
--- a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
+++ b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
@@ -123,8 +123,8 @@
reg = <0 0xe1020000 0 0x1000>;
spi-controller;
interrupts = <0 330 4>;
- clocks = <&uartspiclk_100mhz>;
- clock-names = "apb_pclk";
+ clocks = <&uartspiclk_100mhz>, <&uartspiclk_100mhz>;
+ clock-names = "sspclk", "apb_pclk";
};
spi1: spi@e1030000 {
@@ -133,8 +133,8 @@
reg = <0 0xe1030000 0 0x1000>;
spi-controller;
interrupts = <0 329 4>;
- clocks = <&uartspiclk_100mhz>;
- clock-names = "apb_pclk";
+ clocks = <&uartspiclk_100mhz>, <&uartspiclk_100mhz>;
+ clock-names = "sspclk", "apb_pclk";
num-cs = <1>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi
index d0cda759c25d..fd0e557eba06 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi
@@ -410,6 +410,300 @@
drive-strength-microamp = <4000>;
};
};
+
+ pwm_a_pins1: pwm-a-pins1 {
+ mux {
+ groups = "pwm_a";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_b_pins1: pwm-b-pins1 {
+ mux {
+ groups = "pwm_b";
+ function = "pwm_b";
+ };
+ };
+
+ pwm_c_pins1: pwm-c-pins1 {
+ mux {
+ groups = "pwm_c";
+ function = "pwm_c";
+ };
+ };
+
+ pwm_d_pins1: pwm-d-pins1 {
+ mux {
+ groups = "pwm_d";
+ function = "pwm_d";
+ };
+ };
+
+ pwm_e_pins1: pwm-e-pins1 {
+ mux {
+ groups = "pwm_e";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_f_pins1: pwm-f-pins1 {
+ mux {
+ groups = "pwm_f";
+ function = "pwm_f";
+ };
+ };
+
+ pwm_g_pins1: pwm-g-pins1 {
+ mux {
+ groups = "pwm_g_b";
+ function = "pwm_g";
+ };
+ };
+
+ pwm_g_pins2: pwm-g-pins2 {
+ mux {
+ groups = "pwm_g_c";
+ function = "pwm_g";
+ };
+ };
+
+ pwm_g_pins3: pwm-g-pins3 {
+ mux {
+ groups = "pwm_g_d";
+ function = "pwm_g";
+ };
+ };
+
+ pwm_g_pins4: pwm-g-pins4 {
+ mux {
+ groups = "pwm_g_x0";
+ function = "pwm_g";
+ };
+ };
+
+ pwm_g_pins5: pwm-g-pins5 {
+ mux {
+ groups = "pwm_g_x8";
+ function = "pwm_g";
+ };
+ };
+
+ pwm_h_pins1: pwm-h-pins1 {
+ mux {
+ groups = "pwm_h_b";
+ function = "pwm_h";
+ };
+ };
+
+ pwm_h_pins2: pwm-h-pins2 {
+ mux {
+ groups = "pwm_h_c";
+ function = "pwm_h";
+ };
+ };
+
+ pwm_h_pins3: pwm-h-pins3 {
+ mux {
+ groups = "pwm_h_d";
+ function = "pwm_h";
+ };
+ };
+
+ pwm_h_pins4: pwm-h-pins4 {
+ mux {
+ groups = "pwm_h_x1";
+ function = "pwm_h";
+ };
+ };
+
+ pwm_h_pins5: pwm-h-pins5 {
+ mux {
+ groups = "pwm_h_x9";
+ function = "pwm_h";
+ };
+ };
+
+ pwm_i_pins1: pwm-i-pins1 {
+ mux {
+ groups = "pwm_i_b";
+ function = "pwm_i";
+ };
+ };
+
+ pwm_i_pins2: pwm-i-pins2 {
+ mux {
+ groups = "pwm_i_c";
+ function = "pwm_i";
+ };
+ };
+
+ pwm_i_pins3: pwm-i-pins3 {
+ mux {
+ groups = "pwm_i_d";
+ function = "pwm_i";
+ };
+ };
+
+ pwm_i_pins4: pwm-i-pins4 {
+ mux {
+ groups = "pwm_i_x2";
+ function = "pwm_i";
+ };
+ };
+
+ pwm_i_pins5: pwm-i-pins5 {
+ mux {
+ groups = "pwm_i_x10";
+ function = "pwm_i";
+ };
+ };
+
+ pwm_j_pins1: pwm-j-pins1 {
+ mux {
+ groups = "pwm_j_c";
+ function = "pwm_j";
+ };
+ };
+
+ pwm_j_pins2: pwm-j-pins2 {
+ mux {
+ groups = "pwm_j_d";
+ function = "pwm_j";
+ };
+ };
+
+ pwm_j_pins3: pwm-j-pins3 {
+ mux {
+ groups = "pwm_j_b";
+ function = "pwm_j";
+ };
+ };
+
+ pwm_j_pins4: pwm-j-pins4 {
+ mux {
+ groups = "pwm_j_x3";
+ function = "pwm_j";
+ };
+ };
+
+ pwm_j_pins5: pwm-j-pins5 {
+ mux {
+ groups = "pwm_j_x12";
+ function = "pwm_j";
+ };
+ };
+
+ pwm_k_pins1: pwm-k-pins1 {
+ mux {
+ groups = "pwm_k_c";
+ function = "pwm_k";
+ };
+ };
+
+ pwm_k_pins2: pwm-k-pins2 {
+ mux {
+ groups = "pwm_k_d";
+ function = "pwm_k";
+ };
+ };
+
+ pwm_k_pins3: pwm-k-pins3 {
+ mux {
+ groups = "pwm_k_b";
+ function = "pwm_k";
+ };
+ };
+
+ pwm_k_pins4: pwm-k-pins4 {
+ mux {
+ groups = "pwm_k_x4";
+ function = "pwm_k";
+ };
+ };
+
+ pwm_k_pins5: pwm-k-pins5 {
+ mux {
+ groups = "pwm_k_x13";
+ function = "pwm_k";
+ };
+ };
+
+ pwm_l_pins1: pwm-l-pins1 {
+ mux {
+ groups = "pwm_l_c";
+ function = "pwm_l";
+ };
+ };
+
+ pwm_l_pins2: pwm-l-pins2 {
+ mux {
+ groups = "pwm_l_x";
+ function = "pwm_l";
+ };
+ };
+
+ pwm_l_pins3: pwm-l-pins3 {
+ mux {
+ groups = "pwm_l_b";
+ function = "pwm_l";
+ };
+ };
+
+ pwm_l_pins4: pwm-l-pins4 {
+ mux {
+ groups = "pwm_l_a";
+ function = "pwm_l";
+ };
+ };
+
+ pwm_m_pins1: pwm-m-pins1 {
+ mux {
+ groups = "pwm_m_c";
+ function = "pwm_m";
+ };
+ };
+
+ pwm_m_pins2: pwm-m-pins2 {
+ mux {
+ groups = "pwm_m_x";
+ function = "pwm_m";
+ };
+ };
+
+ pwm_m_pins3: pwm-m-pins3 {
+ mux {
+ groups = "pwm_m_a";
+ function = "pwm_m";
+ };
+ };
+
+ pwm_m_pins4: pwm-m-pins4 {
+ mux {
+ groups = "pwm_m_b";
+ function = "pwm_m";
+ };
+ };
+
+ pwm_n_pins1: pwm-n-pins1 {
+ mux {
+ groups = "pwm_n_x";
+ function = "pwm_n";
+ };
+ };
+
+ pwm_n_pins2: pwm-n-pins2 {
+ mux {
+ groups = "pwm_n_a";
+ function = "pwm_n";
+ };
+ };
+
+ pwm_n_pins3: pwm-n-pins3 {
+ mux {
+ groups = "pwm_n_b";
+ function = "pwm_n";
+ };
+ };
};
gpio_intc: interrupt-controller@4080 {
@@ -490,6 +784,16 @@
status = "disabled";
};
+ pwm_mn: pwm@54000 {
+ compatible = "amlogic,c3-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 54000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_M>,
+ <&clkc_periphs CLKID_PWM_N>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
spifc: spi@56000 {
compatible = "amlogic,a1-spifc";
reg = <0x0 0x56000 0x0 0x290>;
@@ -499,6 +803,66 @@
status = "disabled";
};
+ pwm_ab: pwm@58000 {
+ compatible = "amlogic,c3-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x58000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_A>,
+ <&clkc_periphs CLKID_PWM_B>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm_cd: pwm@5a000 {
+ compatible = "amlogic,c3-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x5a000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_C>,
+ <&clkc_periphs CLKID_PWM_D>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm_ef: pwm@5c000 {
+ compatible = "amlogic,c3-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x5c000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_E>,
+ <&clkc_periphs CLKID_PWM_F>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm_gh: pwm@5e000 {
+ compatible = "amlogic,c3-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x5e000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_G>,
+ <&clkc_periphs CLKID_PWM_H>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm_ij: pwm@60000 {
+ compatible = "amlogic,c3-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x60000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_I>,
+ <&clkc_periphs CLKID_PWM_J>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm_kl: pwm@62000 {
+ compatible = "amlogic,c3-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x62000 0x0 0x24>;
+ clocks = <&clkc_periphs CLKID_PWM_K>,
+ <&clkc_periphs CLKID_PWM_L>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
i2c0: i2c@66000 {
compatible = "amlogic,meson-axg-i2c";
reg = <0x0 0x66000 0x0 0x24>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index e5366d4239b1..1eba0afb3fd9 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -245,6 +245,188 @@
};
};
+ pwm_a_pins1: pwm-a-pins1 {
+ mux {
+ groups = "pwm_a_x6";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_a_pins2: pwm-a-pins2 {
+ mux {
+ groups = "pwm_a_x7";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_a_pins3: pwm-a-pins3 {
+ mux {
+ groups = "pwm_a_f10";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_a_pins4: pwm-a-pins4 {
+ mux {
+ groups = "pwm_a_f6";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_a_pins5: pwm-a-pins5 {
+ mux {
+ groups = "pwm_a_a";
+ function = "pwm_a";
+ };
+ };
+
+ pwm_b_pins1: pwm-b-pins1 {
+ mux {
+ groups = "pwm_b_x";
+ function = "pwm_b";
+ };
+ };
+
+ pwm_b_pins2: pwm-b-pins2 {
+ mux {
+ groups = "pwm_b_f";
+ function = "pwm_b";
+ };
+ };
+
+ pwm_b_pins3: pwm-b-pins3 {
+ mux {
+ groups = "pwm_b_a";
+ function = "pwm_b";
+ };
+ };
+
+ pwm_c_pins1: pwm-c-pins1 {
+ mux {
+ groups = "pwm_c_x";
+ function = "pwm_c";
+ };
+ };
+
+ pwm_c_pins2: pwm-c-pins2 {
+ mux {
+ groups = "pwm_c_f3";
+ function = "pwm_c";
+ };
+ };
+
+ pwm_c_pins3: pwm-c-pins3 {
+ mux {
+ groups = "pwm_c_f8";
+ function = "pwm_c";
+ };
+ };
+
+ pwm_c_pins4: pwm-c-pins4 {
+ mux {
+ groups = "pwm_c_a";
+ function = "pwm_c";
+ };
+ };
+
+ pwm_d_pins1: pwm-d-pins1 {
+ mux {
+ groups = "pwm_d_x15";
+ function = "pwm_d";
+ };
+ };
+
+ pwm_d_pins2: pwm-d-pins2 {
+ mux {
+ groups = "pwm_d_x13";
+ function = "pwm_d";
+ };
+ };
+
+ pwm_d_pins3: pwm-d-pins3 {
+ mux {
+ groups = "pwm_d_x10";
+ function = "pwm_d";
+ };
+ };
+
+ pwm_d_pins4: pwm-d-pins4 {
+ mux {
+ groups = "pwm_d_f";
+ function = "pwm_d";
+ };
+ };
+
+ pwm_e_pins1: pwm-e-pins1 {
+ mux {
+ groups = "pwm_e_p";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_e_pins2: pwm-e-pins2 {
+ mux {
+ groups = "pwm_e_x16";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_e_pins3: pwm-e-pins3 {
+ mux {
+ groups = "pwm_e_x14";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_e_pins4: pwm-e-pins4 {
+ mux {
+ groups = "pwm_e_x2";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_e_pins5: pwm-e-pins5 {
+ mux {
+ groups = "pwm_e_f";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_e_pins6: pwm-e-pins6 {
+ mux {
+ groups = "pwm_e_a";
+ function = "pwm_e";
+ };
+ };
+
+ pwm_f_pins1: pwm-f-pins1 {
+ mux {
+ groups = "pwm_f_b";
+ function = "pwm_f";
+ };
+ };
+
+ pwm_f_pins2: pwm-f-pins2 {
+ mux {
+ groups = "pwm_f_x";
+ function = "pwm_f";
+ };
+ };
+
+ pwm_f_pins3: pwm-f-pins3 {
+ mux {
+ groups = "pwm_f_f4";
+ function = "pwm_f";
+ };
+ };
+
+ pwm_f_pins4: pwm-f-pins4 {
+ mux {
+ groups = "pwm_f_f12";
+ function = "pwm_f";
+ };
+ };
+
sdio_pins: sdio {
mux0 {
groups = "sdcard_d0_x",
@@ -340,6 +522,28 @@
status = "disabled";
};
+ pwm_ab: pwm@2400 {
+ compatible = "amlogic,meson-a1-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x2400 0x0 0x24>;
+ #pwm-cells = <3>;
+ clocks = <&clkc_periphs CLKID_PWM_A>,
+ <&clkc_periphs CLKID_PWM_B>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ status = "disabled";
+ };
+
+ pwm_cd: pwm@2800 {
+ compatible = "amlogic,meson-a1-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x2800 0x0 0x24>;
+ #pwm-cells = <3>;
+ clocks = <&clkc_periphs CLKID_PWM_C>,
+ <&clkc_periphs CLKID_PWM_D>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ status = "disabled";
+ };
+
saradc: adc@2c00 {
compatible = "amlogic,meson-g12a-saradc",
"amlogic,meson-saradc";
@@ -409,6 +613,7 @@
assigned-clock-rates = <500000>;
#thermal-sensor-cells = <0>;
amlogic,ao-secure = <&sec_AO>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
};
hwrng: rng@5118 {
@@ -423,6 +628,17 @@
amlogic,has-chip-id;
};
+ pwm_ef: pwm@5400 {
+ compatible = "amlogic,meson-a1-pwm",
+ "amlogic,meson-s4-pwm";
+ reg = <0x0 0x5400 0x0 0x24>;
+ #pwm-cells = <3>;
+ clocks = <&clkc_periphs CLKID_PWM_E>,
+ <&clkc_periphs CLKID_PWM_F>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ status = "disabled";
+ };
+
clkc_pll: pll-clock-controller@7c80 {
compatible = "amlogic,a1-pll-clkc";
reg = <0 0x7c80 0 0x18c>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index d08c97797010..49b51c54013f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -1913,7 +1913,7 @@
};
};
- uart_ao_a_pins: uart-a-ao {
+ uart_ao_a_pins: uart-ao-a {
mux {
groups = "uart_ao_a_tx",
"uart_ao_a_rx";
diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
index ea5721ea02f0..5a64239b4708 100644
--- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
@@ -809,7 +809,6 @@
interrupts = <0 0x45 0x4>;
#clock-cells = <1>;
clocks = <&sbapbclk 0>;
- bus_num = <1>;
};
i2c4: i2c@10640000 {
@@ -819,7 +818,6 @@
reg = <0x0 0x10640000 0x0 0x1000>;
interrupts = <0 0x3a 0x4>;
clocks = <&i2c4clk 0>;
- bus_num = <4>;
};
};
};
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index 6ad4703925dc..872093b05ce1 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -851,7 +851,6 @@
interrupts = <0 0x44 0x4>;
#clock-cells = <1>;
clocks = <&ahbclk 0>;
- bus_num = <0>;
};
phy1: phy@1f21a000 {
diff --git a/arch/arm64/boot/dts/apple/Makefile b/arch/arm64/boot/dts/apple/Makefile
index aec5e29cdfb7..ab6ebb53218a 100644
--- a/arch/arm64/boot/dts/apple/Makefile
+++ b/arch/arm64/boot/dts/apple/Makefile
@@ -1,4 +1,57 @@
# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j71.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j73.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j85m.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j86m.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j87m.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-n53.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j72.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j85.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j86.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-j87.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s5l8960x-n51.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7000-j42d.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7000-j96.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7000-j97.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7000-n102.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7000-n56.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7000-n61.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7001-j81.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t7001-j82.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8000-j71s.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8000-j72s.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8000-n66.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8000-n69u.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8000-n71.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8003-j71t.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8003-j72t.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8003-n66m.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8003-n69.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8003-n71m.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8001-j127.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8001-j128.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8001-j98a.dtb
+dtb-$(CONFIG_ARCH_APPLE) += s8001-j99a.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-d101.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-d10.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-d111.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-d11.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-j171.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-j172.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-j71b.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-j72b.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8010-n112.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8011-j105a.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8011-j120.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8011-j121.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8011-j207.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8011-j208.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8015-d201.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8015-d20.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8015-d211.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8015-d21.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8015-d221.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t8015-d22.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j274.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j293.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j313.dtb
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-5s.dtsi b/arch/arm64/boot/dts/apple/s5l8960x-5s.dtsi
new file mode 100644
index 000000000000..0b16adf07f79
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-5s.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 5s common device tree
+ * Based on A7 (APL0698), up to 1.3GHz
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s5l8960x.dtsi"
+#include "s5l8960x-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "handset";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl 2 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl 3 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl 5 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl 4 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl 16 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-air1.dtsi b/arch/arm64/boot/dts/apple/s5l8960x-air1.dtsi
new file mode 100644
index 000000000000..741c5a9f21dd
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-air1.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Air common device tree
+ * Based on A7 (APL5698), up to 1.4GHz
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s5l8960x.dtsi"
+#include "s5l8960x-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl 2 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl 3 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl 4 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl 5 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl 110 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-common.dtsi b/arch/arm64/boot/dts/apple/s5l8960x-common.dtsi
new file mode 100644
index 000000000000..243480ca2356
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-common.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 5s, iPad mini 2/3, iPad Air
+ *
+ * This file contains parts common to all Apple A7 devices.
+ *
+ * target-type: J71, J72, J73, J85, J85m, J86, J86m, J87, J87m, N51, N53
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ };
+
+ 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@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j71.dts b/arch/arm64/boot/dts/apple/s5l8960x-j71.dts
new file mode 100644
index 000000000000..e13036dacb45
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j71.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Air (Wi-Fi), J71, iPad4,1 (A1474)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-air1.dtsi"
+
+/ {
+ compatible = "apple,j71", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad Air (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j72.dts b/arch/arm64/boot/dts/apple/s5l8960x-j72.dts
new file mode 100644
index 000000000000..afb71b8885c6
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j72.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Air (Cellular), J72, iPad4,2 (A1475)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-air1.dtsi"
+
+/ {
+ compatible = "apple,j72", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad Air (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j73.dts b/arch/arm64/boot/dts/apple/s5l8960x-j73.dts
new file mode 100644
index 000000000000..c871962df529
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j73.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Air (Cellular, China), J73, iPad4,2 (A1476)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-air1.dtsi"
+
+/ {
+ compatible = "apple,j73", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad Air (Cellular, China)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j85.dts b/arch/arm64/boot/dts/apple/s5l8960x-j85.dts
new file mode 100644
index 000000000000..aefb7b36d7aa
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j85.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 2 (Wi-Fi), J85, iPad4,4 (A1489)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-mini2.dtsi"
+
+/ {
+ compatible = "apple,j85", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad mini 2 (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j85m.dts b/arch/arm64/boot/dts/apple/s5l8960x-j85m.dts
new file mode 100644
index 000000000000..ec2bcaa6d1d5
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j85m.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 3 (Wi-Fi), J85m, iPad4,7 (A1599)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-mini3.dtsi"
+
+/ {
+ compatible = "apple,j85m", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad mini 3 (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j86.dts b/arch/arm64/boot/dts/apple/s5l8960x-j86.dts
new file mode 100644
index 000000000000..470f2f825e70
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j86.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 2 (Cellular), J86, iPad4,5 (A1490)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-mini2.dtsi"
+
+/ {
+ compatible = "apple,j86", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad mini 2 (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j86m.dts b/arch/arm64/boot/dts/apple/s5l8960x-j86m.dts
new file mode 100644
index 000000000000..90311d98aaad
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j86m.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 3 (Cellular), J86m, iPad4,8 (A1600)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-mini3.dtsi"
+
+/ {
+ compatible = "apple,j86m", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad mini 3 (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j87.dts b/arch/arm64/boot/dts/apple/s5l8960x-j87.dts
new file mode 100644
index 000000000000..3580fd8e3831
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j87.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 2 (Cellular, China), J87, iPad4,6 (A1491)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-mini2.dtsi"
+
+/ {
+ compatible = "apple,j87", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad mini 2 (Cellular, China)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-j87m.dts b/arch/arm64/boot/dts/apple/s5l8960x-j87m.dts
new file mode 100644
index 000000000000..fa0da4fa6727
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-j87m.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 3 (Cellular, China), J87m, iPad4,9 (A1601)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-mini3.dtsi"
+
+/ {
+ compatible = "apple,j87m", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPad mini 3 (Cellular, China)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-mini2.dtsi b/arch/arm64/boot/dts/apple/s5l8960x-mini2.dtsi
new file mode 100644
index 000000000000..b27ef5680626
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-mini2.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 2 common device tree
+ * Based on A7 (APL0698), up to 1.3GHz
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s5l8960x.dtsi"
+#include "s5l8960x-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl 2 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl 3 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl 5 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl 4 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-mini3.dtsi b/arch/arm64/boot/dts/apple/s5l8960x-mini3.dtsi
new file mode 100644
index 000000000000..4e397b3d7d7a
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-mini3.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 3 common device tree
+ * Based on A7 (APL0698), up to 1.3GHz
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/*
+ * The Mini 3 seems to be only an iteration over the Mini 2 with some
+ * small changes, like the introduction of Touch ID, hence there is little
+ * to no differentiation between these 2 for now.
+ */
+#include "s5l8960x-mini2.dtsi"
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-n51.dts b/arch/arm64/boot/dts/apple/s5l8960x-n51.dts
new file mode 100644
index 000000000000..cd52f814fbf2
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-n51.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 5s (GSM), N51, iPhone6,1 (A1453/A1533)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-5s.dtsi"
+
+/ {
+ compatible = "apple,n51", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPhone 5s (GSM)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x-n53.dts b/arch/arm64/boot/dts/apple/s5l8960x-n53.dts
new file mode 100644
index 000000000000..4795798a4444
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x-n53.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 5s (LTE), N53, iPhone6,2 (A1457/A1518/A1528/A1530)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s5l8960x-5s.dtsi"
+
+/ {
+ compatible = "apple,n53", "apple,s5l8960x", "apple,arm-platform";
+ model = "Apple iPhone 5s (LTE)";
+};
diff --git a/arch/arm64/boot/dts/apple/s5l8960x.dtsi b/arch/arm64/boot/dts/apple/s5l8960x.dtsi
new file mode 100644
index 000000000000..0218ecac1d83
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s5l8960x.dtsi
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple S5L8960X "A7" SoC
+ *
+ * Other Names: H6, "Alcatraz"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ * Based on Asahi Linux's M1 (t8103.dtsi) and Corellium's A10 efforts.
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "apple,cyclone";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "apple,cyclone";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@20a0a0000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0a0000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 140 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ wdt: watchdog@20e027000 {
+ compatible = "apple,s5l8960x-wdt", "apple,wdt";
+ reg = <0x2 0x0e027000 0x0 0x1000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ aic: interrupt-controller@20e100000 {
+ compatible = "apple,s5l8960x-aic", "apple,aic";
+ reg = <0x2 0x0e100000 0x0 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl: pinctrl@20e300000 {
+ compatible = "apple,s5l8960x-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x0e300000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 200>;
+ apple,npins = <200>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 108 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 109 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 110 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 111 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 112 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 113 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 114 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A7 doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s800-0-3-common.dtsi b/arch/arm64/boot/dts/apple/s800-0-3-common.dtsi
new file mode 100644
index 000000000000..4276bd890e81
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s800-0-3-common.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6s, iPhone 6s Plus, iPad 5, iPhone SE
+ *
+ * This file contains parts common to all Apple A9 devices.
+ *
+ * target-type: J71s, J72s, N66, N69u, N71, J71t, J72t, N66m, N69, N71m
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ };
+
+ 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@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/s8000-j71s.dts b/arch/arm64/boot/dts/apple/s8000-j71s.dts
new file mode 100644
index 000000000000..b5a2dfa1121e
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8000-j71s.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 5 (Wi-Fi) (Samsung), J71s, iPad6,11 (A1822)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8000.dtsi"
+#include "s800x-ipad5.dtsi"
+
+/ {
+ compatible = "apple,j71s", "apple,s8000", "apple,arm-platform";
+ model = "Apple iPad 5 (Wi-Fi) (Samsung)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8000-j72s.dts b/arch/arm64/boot/dts/apple/s8000-j72s.dts
new file mode 100644
index 000000000000..8f3dea5adb09
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8000-j72s.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 5 (Cellular) (Samsung), J72s, iPad6,12 (A1823)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8000.dtsi"
+#include "s800x-ipad5.dtsi"
+
+/ {
+ compatible = "apple,j72s", "apple,s8000", "apple,arm-platform";
+ model = "Apple iPad 5 (Cellular) (Samsung)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8000-n66.dts b/arch/arm64/boot/dts/apple/s8000-n66.dts
new file mode 100644
index 000000000000..30b4b6630b60
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8000-n66.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6s Plus (Samsung), N66, iPhone8,2 (A1634/A1687/A1690/A1699)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8000.dtsi"
+#include "s800x-6s.dtsi"
+
+/ {
+ compatible = "apple,n66", "apple,s8000", "apple,arm-platform";
+ model = "Apple iPhone 6s Plus (Samsung)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8000-n69u.dts b/arch/arm64/boot/dts/apple/s8000-n69u.dts
new file mode 100644
index 000000000000..e63bc2e7f7c1
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8000-n69u.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone SE (Samsung), N69u, iPhone8,4 (A1662/A1723/A1724)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8000.dtsi"
+#include "s800x-se.dtsi"
+
+/ {
+ compatible = "apple,n69u", "apple,s8000", "apple,arm-platform";
+ model = "Apple iPhone SE (Samsung)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8000-n71.dts b/arch/arm64/boot/dts/apple/s8000-n71.dts
new file mode 100644
index 000000000000..f2964a1fc434
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8000-n71.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6s (Samsung), N71, iPhone8,1 (A1633/A1688/A1691/A1700)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8000.dtsi"
+#include "s800x-6s.dtsi"
+
+/ {
+ compatible = "apple,n71", "apple,s8000", "apple,arm-platform";
+ model = "Apple iPhone 6s (Samsung)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8000.dtsi b/arch/arm64/boot/dts/apple/s8000.dtsi
new file mode 100644
index 000000000000..6e9046ea106c
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8000.dtsi
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple S8000 "A9" (Samsung) SoC
+ *
+ * Other names: H8P, "Maui"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "apple,twister";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "apple,twister";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@20a0c0000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0c0000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 192 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ aic: interrupt-controller@20e100000 {
+ compatible = "apple,s8000-aic", "apple,aic";
+ reg = <0x2 0x0e100000 0x0 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl_ap: pinctrl@20f100000 {
+ compatible = "apple,s8000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x0f100000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_ap 0 0 208>;
+ apple,npins = <208>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 42 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 43 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 44 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 45 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 46 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 47 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 48 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_aop: pinctrl@2100f0000 {
+ compatible = "apple,s8000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x100f0000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_aop 0 0 42>;
+ apple,npins = <42>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 113 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 114 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 115 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 116 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 117 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 118 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 119 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wdt: watchdog@2102b0000 {
+ compatible = "apple,s8000-wdt", "apple,wdt";
+ reg = <0x2 0x102b0000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A9 doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
+
+/*
+ * The A9 was made by two separate fabs on two different process
+ * nodes: Samsung made the S8000 (APL0898) on 14nm and TSMC made
+ * the S8003 (APL1022) on 16nm. While they are seemingly the same,
+ * they do have distinct part numbers and devices using them have
+ * distinct model names. There are currently no known differences
+ * between these as far as Linux is concerned, but let's keep things
+ * structured properly to make it easier to alter the behaviour of
+ * one of the chips if need be.
+ */
diff --git a/arch/arm64/boot/dts/apple/s8001-common.dtsi b/arch/arm64/boot/dts/apple/s8001-common.dtsi
new file mode 100644
index 000000000000..e94d0e77653a
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8001-common.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro (9.7-inch), iPad Pro (12.9-inch)
+ *
+ * This file contains parts common to all Apple A9X devices.
+ *
+ * target-type: J127, J128, J98a, J99a
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ };
+
+ 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@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/s8001-j127.dts b/arch/arm64/boot/dts/apple/s8001-j127.dts
new file mode 100644
index 000000000000..8b522085cb3e
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8001-j127.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro (9.7-inch) (Wi-Fi), J127, iPad6,3 (A1673)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8001-pro.dtsi"
+
+/ {
+ compatible = "apple,j127", "apple,s8001", "apple,arm-platform";
+ model = "Apple iPad Pro (9.7-inch) (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8001-j128.dts b/arch/arm64/boot/dts/apple/s8001-j128.dts
new file mode 100644
index 000000000000..cdd3d06dcbf1
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8001-j128.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro (9.7-inch) (Cellular), J128, iPad6,4 (A1674/A1675)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8001-pro.dtsi"
+
+/ {
+ compatible = "apple,j128", "apple,s8001", "apple,arm-platform";
+ model = "Apple iPad Pro (9.7-inch) (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8001-j98a.dts b/arch/arm64/boot/dts/apple/s8001-j98a.dts
new file mode 100644
index 000000000000..6d6b841e7ab0
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8001-j98a.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro (12.9-inch) (Wi-Fi), J98a, iPad6,7 (A1584)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8001-pro.dtsi"
+
+/ {
+ compatible = "apple,j98a", "apple,s8001", "apple,arm-platform";
+ model = "Apple iPad Pro (12.9-inch) (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8001-j99a.dts b/arch/arm64/boot/dts/apple/s8001-j99a.dts
new file mode 100644
index 000000000000..d20194b1cae7
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8001-j99a.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro (12.9-inch) (Cellular), J99a, iPad6,8 (A1652)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8001-pro.dtsi"
+
+/ {
+ compatible = "apple,j99a", "apple,s8001", "apple,arm-platform";
+ model = "Apple iPad Pro (12.9-inch) (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8001-pro.dtsi b/arch/arm64/boot/dts/apple/s8001-pro.dtsi
new file mode 100644
index 000000000000..1fce5a7c4200
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8001-pro.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro (1st generation) common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s8001.dtsi"
+#include "s8001-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl_ap 122 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 123 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 15 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 12 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s8001.dtsi b/arch/arm64/boot/dts/apple/s8001.dtsi
new file mode 100644
index 000000000000..23ee3238844d
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8001.dtsi
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple S8001 "A9X" SoC
+ *
+ * Other names: H8G, "Elba"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "apple,twister";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "apple,twister";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@20a0c0000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0c0000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 218 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ aic: interrupt-controller@20e100000 {
+ compatible = "apple,s8000-aic", "apple,aic";
+ reg = <0x2 0x0e100000 0x0 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl_ap: pinctrl@20f100000 {
+ compatible = "apple,s8000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x0f100000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_ap 0 0 219>;
+ apple,npins = <219>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 42 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 43 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 44 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 45 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 46 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 47 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 48 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_aop: pinctrl@2100f0000 {
+ compatible = "apple,s8000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x100f0000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_aop 0 0 28>;
+ apple,npins = <28>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 128 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 129 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 130 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 131 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 132 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 133 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 134 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wdt: watchdog@2102b0000 {
+ compatible = "apple,s8000-wdt", "apple,wdt";
+ reg = <0x2 0x102b0000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A9X doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s8003-j71t.dts b/arch/arm64/boot/dts/apple/s8003-j71t.dts
new file mode 100644
index 000000000000..0d906ae80b07
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8003-j71t.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 5 (Wi-Fi) (TSMC), J71t, iPad6,11 (A1822)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8003.dtsi"
+#include "s800x-ipad5.dtsi"
+
+/ {
+ compatible = "apple,j71t", "apple,s8003", "apple,arm-platform";
+ model = "Apple iPad 5 (Wi-Fi) (TSMC)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8003-j72t.dts b/arch/arm64/boot/dts/apple/s8003-j72t.dts
new file mode 100644
index 000000000000..0cd7d88e9dfb
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8003-j72t.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 5 (Cellular) (TSMC), J72t, iPad6,12 (A1823)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8003.dtsi"
+#include "s800x-ipad5.dtsi"
+
+/ {
+ compatible = "apple,j72t", "apple,s8003", "apple,arm-platform";
+ model = "Apple iPad 5 (Cellular) (TSMC)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8003-n66m.dts b/arch/arm64/boot/dts/apple/s8003-n66m.dts
new file mode 100644
index 000000000000..4146cd28160d
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8003-n66m.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6s Plus (TSMC), N66m, iPhone8,2 (A1634/A1687/A1690/A1699)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8003.dtsi"
+#include "s800x-6s.dtsi"
+
+/ {
+ compatible = "apple,n66m", "apple,s8003", "apple,arm-platform";
+ model = "Apple iPhone 6s Plus (TSMC)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8003-n69.dts b/arch/arm64/boot/dts/apple/s8003-n69.dts
new file mode 100644
index 000000000000..8eed879b155e
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8003-n69.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone SE (TSMC), N69, iPhone8,4 (A1662/A1723/A1724)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8003.dtsi"
+#include "s800x-se.dtsi"
+
+/ {
+ compatible = "apple,n69", "apple,s8003", "apple,arm-platform";
+ model = "Apple iPhone SE (TSMC)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8003-n71m.dts b/arch/arm64/boot/dts/apple/s8003-n71m.dts
new file mode 100644
index 000000000000..7ec6d2cda0bf
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8003-n71m.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6s (TSMC), N71m, iPhone8,1 (A1633/A1688/A1691/A1700)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "s8003.dtsi"
+#include "s800x-6s.dtsi"
+
+/ {
+ compatible = "apple,n71m", "apple,s8003", "apple,arm-platform";
+ model = "Apple iPhone 6s (TSMC)";
+};
diff --git a/arch/arm64/boot/dts/apple/s8003.dtsi b/arch/arm64/boot/dts/apple/s8003.dtsi
new file mode 100644
index 000000000000..7e4ad4f7e499
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s8003.dtsi
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple S8003 "A9" (TSMC) SoC
+ *
+ * Other names: H8P, "Malta"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s8000.dtsi"
+
+/*
+ * The A9 was made by two separate fabs on two different process
+ * nodes: Samsung made the S8000 (APL0898) on 14nm and TSMC made
+ * the S8003 (APL1022) on 16nm. While they are seemingly the same,
+ * they do have distinct part numbers and devices using them have
+ * distinct model names. There are currently no known differences
+ * between these as far as Linux is concerned, but let's keep things
+ * structured properly to make it easier to alter the behaviour of
+ * one of the chips if need be.
+ */
diff --git a/arch/arm64/boot/dts/apple/s800x-6s.dtsi b/arch/arm64/boot/dts/apple/s800x-6s.dtsi
new file mode 100644
index 000000000000..49b04db310c6
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s800x-6s.dtsi
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6s / 6S Plus common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s800-0-3-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "handset";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl_ap 96 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 97 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 67 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 66 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl_ap 149 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s800x-ipad5.dtsi b/arch/arm64/boot/dts/apple/s800x-ipad5.dtsi
new file mode 100644
index 000000000000..32570ed3cdf0
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s800x-ipad5.dtsi
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 5 common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s800-0-3-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl_ap 96 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 97 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 143 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 144 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/s800x-se.dtsi b/arch/arm64/boot/dts/apple/s800x-se.dtsi
new file mode 100644
index 000000000000..a1a5690e8371
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/s800x-se.dtsi
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone SE common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "s800-0-3-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "handset";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl_ap 96 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 97 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 67 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 66 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl_ap 149 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-6.dtsi b/arch/arm64/boot/dts/apple/t7000-6.dtsi
new file mode 100644
index 000000000000..f60ea4a4a387
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-6.dtsi
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6 / 6 Plus common device tree
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include <dt-bindings/input/input.h>
+#include "t7000.dtsi"
+#include "t7000-common.dtsi"
+#include "t7000-handheld.dtsi"
+
+/ {
+ chassis-type = "handset";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl 32 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl 33 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl 45 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl 46 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl 131 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-common.dtsi b/arch/arm64/boot/dts/apple/t7000-common.dtsi
new file mode 100644
index 000000000000..87146e6daae7
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-common.dtsi
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple TV HD, iPhone 6, iPhone 6 Plus, iPad mini 4, iPod touch 6
+ *
+ * This file contains parts common to all Apple A8 devices.
+ *
+ * target-type: J42d, J96, J97, N56, N61, N102
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ serial6 = &serial6;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ };
+
+ memory@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-handheld.dtsi b/arch/arm64/boot/dts/apple/t7000-handheld.dtsi
new file mode 100644
index 000000000000..8984c9ec6cc8
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-handheld.dtsi
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6, iPhone 6 Plus, iPad mini 4, iPod touch 6
+ *
+ * This file contains the parts common to handheld devices with t7000
+ *
+ * target-type: J96, J97, N56, N61, N102
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ chosen {
+ 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";
+ };
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-j42d.dts b/arch/arm64/boot/dts/apple/t7000-j42d.dts
new file mode 100644
index 000000000000..2231db6a739d
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-j42d.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple TV HD, J42d, AppleTV5,3 (A1625)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7000.dtsi"
+#include "t7000-common.dtsi"
+
+/ {
+ compatible = "apple,j42d", "apple,t7000", "apple,arm-platform";
+ model = "Apple TV HD";
+ chassis-type = "television";
+
+ chosen {
+ stdout-path = "serial6";
+
+ 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";
+ };
+ };
+};
+
+&serial6 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-j96.dts b/arch/arm64/boot/dts/apple/t7000-j96.dts
new file mode 100644
index 000000000000..8a32a50cc2df
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-j96.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 4 (Wi-Fi), J96, iPad5,1 (A1538)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7000-mini4.dtsi"
+
+/ {
+ compatible = "apple,j96", "apple,t7000", "apple,arm-platform";
+ model = "Apple iPad mini 4 (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-j97.dts b/arch/arm64/boot/dts/apple/t7000-j97.dts
new file mode 100644
index 000000000000..ac7d501f88d2
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-j97.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 4 (Cellular), J97, iPad5,2 (A1550)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7000-mini4.dtsi"
+
+/ {
+ compatible = "apple,j97", "apple,t7000", "apple,arm-platform";
+ model = "Apple iPad mini 4 (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-mini4.dtsi b/arch/arm64/boot/dts/apple/t7000-mini4.dtsi
new file mode 100644
index 000000000000..c64ddc402fda
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-mini4.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad mini 4 common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "t7000.dtsi"
+#include "t7000-common.dtsi"
+#include "t7000-handheld.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl 32 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl 33 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl 45 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl 46 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl 36 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-n102.dts b/arch/arm64/boot/dts/apple/t7000-n102.dts
new file mode 100644
index 000000000000..9c55d339ba4e
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-n102.dts
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPod touch 6, N102, iPod7,1 (A1574)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7000.dtsi"
+#include "t7000-common.dtsi"
+#include "t7000-handheld.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ compatible = "apple,n102", "apple,t7000", "apple,arm-platform";
+ model = "Apple iPod touch 6";
+ chassis-type = "handset";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl 32 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl 33 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl 46 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl 45 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-n56.dts b/arch/arm64/boot/dts/apple/t7000-n56.dts
new file mode 100644
index 000000000000..2c358df14458
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-n56.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6 Plus, N56, iPhone7,2 (A1549/A1586/A1589)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7000-6.dtsi"
+
+/ {
+ compatible = "apple,n56", "apple,t7000", "apple,arm-platform";
+ model = "Apple iPhone 6 Plus";
+};
diff --git a/arch/arm64/boot/dts/apple/t7000-n61.dts b/arch/arm64/boot/dts/apple/t7000-n61.dts
new file mode 100644
index 000000000000..10b4ca8babf7
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000-n61.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 6, N61, iPhone7,2 (A1549/A1586/A1589)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7000-6.dtsi"
+
+/ {
+ compatible = "apple,n61", "apple,t7000", "apple,arm-platform";
+ model = "Apple iPhone 6";
+};
diff --git a/arch/arm64/boot/dts/apple/t7000.dtsi b/arch/arm64/boot/dts/apple/t7000.dtsi
new file mode 100644
index 000000000000..a7cc29e84c84
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7000.dtsi
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T7000 "A8" SoC
+ *
+ * Other names: H7P, "Fiji"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ * Based on Asahi Linux's M1 (t8103.dtsi) and Corellium's A10 efforts.
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "apple,typhoon";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "apple,typhoon";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@20a0c0000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0c0000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 158 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ serial6: serial@20a0d8000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0d8000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 164 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ wdt: watchdog@20e027000 {
+ compatible = "apple,t7000-wdt", "apple,wdt";
+ reg = <0x2 0x0e027000 0x0 0x1000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ aic: interrupt-controller@20e100000 {
+ compatible = "apple,t7000-aic", "apple,aic";
+ reg = <0x2 0x0e100000 0x0 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl: pinctrl@20e300000 {
+ compatible = "apple,t7000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x0e300000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 208>;
+ apple,npins = <208>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 62 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 63 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 64 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 65 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 66 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 67 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 68 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A8 doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t7001-air2.dtsi b/arch/arm64/boot/dts/apple/t7001-air2.dtsi
new file mode 100644
index 000000000000..19fabd425c52
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7001-air2.dtsi
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Air 2 common device tree
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "t7001.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ 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";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl 0 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl 1 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl 92 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl 93 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+ memory@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/t7001-j81.dts b/arch/arm64/boot/dts/apple/t7001-j81.dts
new file mode 100644
index 000000000000..ca90dc0c872c
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7001-j81.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Air 2 (Wi-Fi), J81, iPad5,3 (A1566)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7001-air2.dtsi"
+
+/ {
+ compatible = "apple,j81", "apple,t7001", "apple,arm-platform";
+ model = "Apple iPad Air 2 (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/t7001-j82.dts b/arch/arm64/boot/dts/apple/t7001-j82.dts
new file mode 100644
index 000000000000..d9fd16f48db7
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7001-j82.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Air 2 (Cellular), J82, iPad5,4 (A1567)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t7001-air2.dtsi"
+
+/ {
+ compatible = "apple,j82", "apple,t7001", "apple,arm-platform";
+ model = "Apple iPad Air 2 (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/t7001.dtsi b/arch/arm64/boot/dts/apple/t7001.dtsi
new file mode 100644
index 000000000000..a76e034c85e3
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t7001.dtsi
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T7001 "A8X" SoC
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ * Based on Asahi Linux's M1 (t8103.dtsi) and Corellium's A10 efforts.
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &serial0;
+ };
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "apple,typhoon";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "apple,typhoon";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled in by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu2: cpu@2 {
+ compatible = "apple,typhoon";
+ reg = <0x0 0x2>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@20a0c0000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0c0000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 158 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ wdt: watchdog@20e027000 {
+ compatible = "apple,t7000-wdt", "apple,wdt";
+ reg = <0x2 0x0e027000 0x0 0x1000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ aic: interrupt-controller@20e100000 {
+ compatible = "apple,t7000-aic", "apple,aic";
+ reg = <0x2 0x0e100000 0x0 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl: pinctrl@20e300000 {
+ compatible = "apple,t7000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x0e300000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 184>;
+ apple,npins = <184>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 62 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 63 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 64 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 65 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 66 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 67 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 68 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A8X doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-7.dtsi b/arch/arm64/boot/dts/apple/t8010-7.dtsi
new file mode 100644
index 000000000000..1332fd73f50f
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-7.dtsi
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 7 / 7 Plus common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "t8010.dtsi"
+#include "t8010-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "handset";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 179 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 180 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 23 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ switch-mute {
+ label = "Mute Switch";
+ gpios = <&pinctrl_ap 86 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_MUTE>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-common.dtsi b/arch/arm64/boot/dts/apple/t8010-common.dtsi
new file mode 100644
index 000000000000..6613fb57c92f
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-common.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Apple iPhone 7, iPhone 7 Plus, iPad 6, iPad 7, iPod touch 7
+ *
+ * This file contains parts common to all Apple A10 devices.
+ *
+ * target-type: D10, D11, D101, D111, J71b, J72b, J171, J172, N112
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ };
+
+ 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@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-d10.dts b/arch/arm64/boot/dts/apple/t8010-d10.dts
new file mode 100644
index 000000000000..39cdd12db6bf
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-d10.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 7 (Qualcomm), D10, iPhone9,1 (A1660/A1778/A1779/A1780)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-7.dtsi"
+
+/ {
+ compatible = "apple,d10", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPhone 7 (Qualcomm)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-d101.dts b/arch/arm64/boot/dts/apple/t8010-d101.dts
new file mode 100644
index 000000000000..6a9f0856f930
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-d101.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 7 (Intel), D101, iPhone9,3 (A1660/A1778/A1779/A1780)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-7.dtsi"
+
+/ {
+ compatible = "apple,d101", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPhone 7 (Intel)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-d11.dts b/arch/arm64/boot/dts/apple/t8010-d11.dts
new file mode 100644
index 000000000000..57e41c2cfbe2
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-d11.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 7 Plus (Qualcomm), D11, iPhone9,2 (A1661/A1784/A1785/A1786)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-7.dtsi"
+
+/ {
+ compatible = "apple,d11", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPhone 7 Plus (Qualcomm)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-d111.dts b/arch/arm64/boot/dts/apple/t8010-d111.dts
new file mode 100644
index 000000000000..37e395a48c1d
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-d111.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 7 Plus (Intel), D111, iPhone9,4 (A1661/A1784/A1785/A1786)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-7.dtsi"
+
+/ {
+ compatible = "apple,d111", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPhone 7 Plus (Intel)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-ipad6.dtsi b/arch/arm64/boot/dts/apple/t8010-ipad6.dtsi
new file mode 100644
index 000000000000..81696c6e302c
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-ipad6.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 6 common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "t8010.dtsi"
+#include "t8010-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl_ap 180 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 179 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 89 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 90 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-ipad7.dtsi b/arch/arm64/boot/dts/apple/t8010-ipad7.dtsi
new file mode 100644
index 000000000000..bd0e9c0b5696
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-ipad7.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 7 common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/*
+ * The iPad 7 seems to be only an iteration over the iPad 6 with some
+ * small changes, like the a bigger screen and 1 GiB of RAM more, hence
+ * there is little to no differentiation between these 2 generations for
+ * now.
+ */
+#include "t8010-ipad6.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8010-j171.dts b/arch/arm64/boot/dts/apple/t8010-j171.dts
new file mode 100644
index 000000000000..6751bf3a4afd
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-j171.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 7 (Wi-Fi), J171, iPad7,11 (A2197)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-ipad7.dtsi"
+
+/ {
+ compatible = "apple,j171", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPad 7 (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-j172.dts b/arch/arm64/boot/dts/apple/t8010-j172.dts
new file mode 100644
index 000000000000..51aaa950acd9
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-j172.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 7 (Cellular), J172, iPad7,12 (A2198/A2200)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-ipad7.dtsi"
+
+/ {
+ compatible = "apple,j172", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPad 7 (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-j71b.dts b/arch/arm64/boot/dts/apple/t8010-j71b.dts
new file mode 100644
index 000000000000..534eb8413e08
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-j71b.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 6 (Wi-Fi), J71b, iPad7,5 (A1893)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-ipad6.dtsi"
+
+/ {
+ compatible = "apple,j71b", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPad 6 (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-j72b.dts b/arch/arm64/boot/dts/apple/t8010-j72b.dts
new file mode 100644
index 000000000000..264924e41f42
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-j72b.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad 6 (Cellular), J72b, iPad7,6 (A1954)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010-ipad6.dtsi"
+
+/ {
+ compatible = "apple,j72b", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPad 6 (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8010-n112.dts b/arch/arm64/boot/dts/apple/t8010-n112.dts
new file mode 100644
index 000000000000..6e71c3cb5d92
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010-n112.dts
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPod touch 7, N112, iPod9,1 (A2178)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8010.dtsi"
+#include "t8010-common.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ compatible = "apple,n112", "apple,t8010", "apple,arm-platform";
+ model = "Apple iPod touch 7";
+ chassis-type = "handset";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl_ap 86 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 179 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 180 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 23 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8010.dtsi b/arch/arm64/boot/dts/apple/t8010.dtsi
new file mode 100644
index 000000000000..e3d6a8354103
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8010.dtsi
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Apple T8010 "A10" SoC
+ *
+ * Other names: H9P, "Cayman"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "apple,hurricane-zephyr";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "apple,hurricane-zephyr";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@20a0c0000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0c0000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 218 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ aic: interrupt-controller@20e100000 {
+ compatible = "apple,t8010-aic", "apple,aic";
+ reg = <0x2 0x0e100000 0x0 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl_ap: pinctrl@20f100000 {
+ compatible = "apple,t8010-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x0f100000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_ap 0 0 208>;
+ apple,npins = <208>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 42 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 43 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 44 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 45 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 46 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 47 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 48 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_aop: pinctrl@2100f0000 {
+ compatible = "apple,t8010-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x100f0000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_aop 0 0 42>;
+ apple,npins = <42>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 128 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 129 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 130 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 131 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 132 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 133 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 134 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wdt: watchdog@2102b0000 {
+ compatible = "apple,t8010-wdt", "apple,wdt";
+ reg = <0x2 0x102b0000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A10 doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8011-common.dtsi b/arch/arm64/boot/dts/apple/t8011-common.dtsi
new file mode 100644
index 000000000000..44a0d0ea2ee3
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011-common.dtsi
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple TV 4K, Apple iPad Pro 2
+ *
+ * This file contains parts common to all Apple A10X devices.
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ };
+
+ 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@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/t8011-j105a.dts b/arch/arm64/boot/dts/apple/t8011-j105a.dts
new file mode 100644
index 000000000000..d3e5b69c67aa
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011-j105a.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple TV 4K (1st Generation), J105a, AppleTV6,2 (A1482)
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "t8011.dtsi"
+#include "t8011-common.dtsi"
+
+/ {
+ compatible = "apple,j105a", "apple,t8011", "apple,arm-platform";
+ model = "Apple TV 4K (1st Generation)";
+ chassis-type = "television";
+};
diff --git a/arch/arm64/boot/dts/apple/t8011-j120.dts b/arch/arm64/boot/dts/apple/t8011-j120.dts
new file mode 100644
index 000000000000..1b49bb5c97c3
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011-j120.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro 2 (12.9-inch) (Wi-Fi), J120, iPad7,1 (A1670)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8011.dtsi"
+#include "t8011-common.dtsi"
+#include "t8011-pro2.dtsi"
+
+/ {
+ compatible = "apple,j120", "apple,t8011", "apple,arm-platform";
+ model = "Apple iPad Pro 2 (12.9-inch) (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8011-j121.dts b/arch/arm64/boot/dts/apple/t8011-j121.dts
new file mode 100644
index 000000000000..22f4aa1ecbda
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011-j121.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro 2 (12.9-inch) (Cellular), J121, iPad7,2 (A1671)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8011.dtsi"
+#include "t8011-common.dtsi"
+#include "t8011-pro2.dtsi"
+
+/ {
+ compatible = "apple,j121", "apple,t8011", "apple,arm-platform";
+ model = "Apple iPad Pro 2 (12.9-inch) (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8011-j207.dts b/arch/arm64/boot/dts/apple/t8011-j207.dts
new file mode 100644
index 000000000000..c3384e2cad44
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011-j207.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro 2 (10.5-inch) (Wi-Fi), J207, iPad7,3 (A1701)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8011.dtsi"
+#include "t8011-common.dtsi"
+#include "t8011-pro2.dtsi"
+
+/ {
+ compatible = "apple,j207", "apple,t8011", "apple,arm-platform";
+ model = "Apple iPad Pro 2 (10.5-inch) (Wi-Fi)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8011-j208.dts b/arch/arm64/boot/dts/apple/t8011-j208.dts
new file mode 100644
index 000000000000..251fa76efb6b
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011-j208.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro 2 (10.5-inch) (Cellular), J208, iPad7,4 (A1709)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8011.dtsi"
+#include "t8011-common.dtsi"
+#include "t8011-pro2.dtsi"
+
+/ {
+ compatible = "apple,j208", "apple,t8011", "apple,arm-platform";
+ model = "Apple iPad Pro 2 (10.5-inch) (Cellular)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8011-pro2.dtsi b/arch/arm64/boot/dts/apple/t8011-pro2.dtsi
new file mode 100644
index 000000000000..f4e707415003
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011-pro2.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPad Pro 2 common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include <dt-bindings/input/input.h>
+
+/ {
+ chassis-type = "tablet";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-home {
+ label = "Home Button";
+ gpios = <&pinctrl_ap 139 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ wakeup-source;
+ };
+
+ button-power {
+ label = "Power Button";
+ gpios = <&pinctrl_ap 138 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+
+ button-voldown {
+ label = "Volume Down";
+ gpios = <&pinctrl_ap 43 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volup {
+ label = "Volume Up";
+ gpios = <&pinctrl_ap 40 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8011.dtsi b/arch/arm64/boot/dts/apple/t8011.dtsi
new file mode 100644
index 000000000000..6c4ed9dc4a50
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8011.dtsi
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T8011 "A10X" SoC
+ *
+ * Other names: H9G, "Myst"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "apple,hurricane-zephyr";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "apple,hurricane-zephyr";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu2: cpu@2 {
+ compatible = "apple,hurricane-zephyr";
+ reg = <0x0 0x2>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@20a0c0000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x0a0c0000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 216 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ aic: interrupt-controller@20e100000 {
+ compatible = "apple,t8010-aic", "apple,aic";
+ reg = <0x2 0x0e100000 0x0 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl_ap: pinctrl@20f100000 {
+ compatible = "apple,t8010-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x0f100000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_ap 0 0 219>;
+ apple,npins = <219>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 42 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 43 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 44 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 45 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 46 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 47 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 48 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_aop: pinctrl@2100f0000 {
+ compatible = "apple,t8010-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x100f0000 0x0 0x100000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_aop 0 0 42>;
+ apple,npins = <42>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 125 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 126 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 127 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 128 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 129 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 130 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 131 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wdt: watchdog@2102b0000 {
+ compatible = "apple,t8010-wdt", "apple,wdt";
+ reg = <0x2 0x102b0000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 4 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A10X doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-8.dtsi b/arch/arm64/boot/dts/apple/t8015-8.dtsi
new file mode 100644
index 000000000000..b6505b5185bd
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-8.dtsi
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 8 common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "t8015.dtsi"
+#include "t8015-common.dtsi"
+
+/ {
+ chassis-type = "handset";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-8plus.dtsi b/arch/arm64/boot/dts/apple/t8015-8plus.dtsi
new file mode 100644
index 000000000000..ea291a95f028
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-8plus.dtsi
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 8 Plus common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/* The 8 Plus has minor differences like 1 more camera, 1 GiB of RAM more and a bigger display. */
+#include "t8015-8.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8015-common.dtsi b/arch/arm64/boot/dts/apple/t8015-common.dtsi
new file mode 100644
index 000000000000..69258a33ea50
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-common.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 8, iPhone 8 Plus, iPhone X
+ *
+ * This file contains parts common to all Apple A11 devices.
+ *
+ * target-type: D20, D21, D22, D201, D211, D221
+ *
+ * Copyright (c) 2024, Nick Chan <towinchenmi@gmail.com>
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ };
+
+ 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@800000000 {
+ device_type = "memory";
+ reg = <0x8 0 0 0>; /* To be filled by loader */
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-d20.dts b/arch/arm64/boot/dts/apple/t8015-d20.dts
new file mode 100644
index 000000000000..35d79e2ceebc
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-d20.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 8 (Global), D20 iPhone10,1 (A1863/A1906/A1907)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8015-8.dtsi"
+
+/ {
+ compatible = "apple,d20", "apple,t8015", "apple,arm-platform";
+ model = "Apple iPhone 8 (Global)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-d201.dts b/arch/arm64/boot/dts/apple/t8015-d201.dts
new file mode 100644
index 000000000000..31e0947fee70
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-d201.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 8 (GSM), D20 iPhone10,4 (A1905)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8015-8.dtsi"
+
+/ {
+ compatible = "apple,d201", "apple,t8015", "apple,arm-platform";
+ model = "Apple iPhone 8 (GSM)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-d21.dts b/arch/arm64/boot/dts/apple/t8015-d21.dts
new file mode 100644
index 000000000000..a902ba7f1133
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-d21.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 8 Plus (Global), D21 iPhone10,2 (A1864/A1897/A1898)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8015-8plus.dtsi"
+
+/ {
+ compatible = "apple,d21", "apple,t8015", "apple,arm-platform";
+ model = "Apple iPhone 8 Plus (Global)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-d211.dts b/arch/arm64/boot/dts/apple/t8015-d211.dts
new file mode 100644
index 000000000000..3b3f886c0c09
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-d211.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone 8 Plus (GSM), D211 iPhone10,5 (A1899)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8015-8plus.dtsi"
+
+/ {
+ compatible = "apple,d211", "apple,t8015", "apple,arm-platform";
+ model = "Apple iPhone 8 Plus (GSM)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-d22.dts b/arch/arm64/boot/dts/apple/t8015-d22.dts
new file mode 100644
index 000000000000..5a7a6092c2d0
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-d22.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone X (Global), D22, iPhone10,3 (A1865)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8015-x.dtsi"
+
+/ {
+ compatible = "apple,d22", "apple,t8015", "apple,arm-platform";
+ model = "Apple iPhone X (Global)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-d221.dts b/arch/arm64/boot/dts/apple/t8015-d221.dts
new file mode 100644
index 000000000000..dd920c945bd6
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-d221.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone X (GSM), D221, iPhone10,6 (A1901)
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+/dts-v1/;
+
+#include "t8015-x.dtsi"
+
+/ {
+ compatible = "apple,d221", "apple,t8015", "apple,arm-platform";
+ model = "Apple iPhone X (GSM)";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015-x.dtsi b/arch/arm64/boot/dts/apple/t8015-x.dtsi
new file mode 100644
index 000000000000..41134ed40b89
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015-x.dtsi
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple iPhone X common device tree
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#include "t8015.dtsi"
+#include "t8015-common.dtsi"
+
+/ {
+ chassis-type = "handset";
+};
diff --git a/arch/arm64/boot/dts/apple/t8015.dtsi b/arch/arm64/boot/dts/apple/t8015.dtsi
new file mode 100644
index 000000000000..8828d830e5be
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t8015.dtsi
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T8015 "A11" SoC
+ *
+ * Other names: H10, "Skye"
+ *
+ * Copyright (c) 2022, Konrad Dybcio <konradybcio@kernel.org>
+ */
+
+#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>
+
+/ {
+ interrupt-parent = <&aic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <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>;
+ };
+ };
+ };
+
+ cpu_e0: cpu@0 {
+ compatible = "apple,mistral";
+ reg = <0x0 0x0>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu_e1: cpu@1 {
+ compatible = "apple,mistral";
+ reg = <0x0 0x1>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu_e2: cpu@2 {
+ compatible = "apple,mistral";
+ reg = <0x0 0x2>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu_e3: cpu@3 {
+ compatible = "apple,mistral";
+ reg = <0x0 0x3>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu_p0: cpu@10004 {
+ compatible = "apple,monsoon";
+ reg = <0x0 0x10004>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+
+ cpu_p1: cpu@10005 {
+ compatible = "apple,monsoon";
+ reg = <0x0 0x10005>;
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ enable-method = "spin-table";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nonposted-mmio;
+ ranges;
+
+ serial0: serial@22e600000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x2 0x2e600000 0x0 0x4000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 282 IRQ_TYPE_LEVEL_HIGH>;
+ /* Use the bootloader-enabled clocks for now. */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ status = "disabled";
+ };
+
+ aic: interrupt-controller@232100000 {
+ compatible = "apple,t8015-aic", "apple,aic";
+ reg = <0x2 0x32100000 0x0 0x8000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ pinctrl_ap: pinctrl@233100000 {
+ compatible = "apple,t8015-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x33100000 0x0 0x1000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_ap 0 0 223>;
+ apple,npins = <223>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 50 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 51 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 52 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 53 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 54 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 55 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 56 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_aop: pinctrl@2340f0000 {
+ compatible = "apple,t8015-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x340f0000 0x0 0x4000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_aop 0 0 49>;
+ apple,npins = <49>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 135 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 136 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 137 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 138 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 139 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 140 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 141 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_nub: pinctrl@2351f0000 {
+ compatible = "apple,t8015-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x351f0000 0x0 0x4000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_nub 0 0 8>;
+ apple,npins = <8>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 168 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 169 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 170 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wdt: watchdog@2352b0000 {
+ compatible = "apple,t8015-wdt", "apple,wdt";
+ reg = <0x2 0x352b0000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 172 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_smc: pinctrl@236024000 {
+ compatible = "apple,t8015-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x36024000 0x0 0x4000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_smc 0 0 6>;
+ apple,npins = <6>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 199 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 200 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 201 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 202 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 203 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 204 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 205 IRQ_TYPE_LEVEL_HIGH>;
+ /*
+ * SMC is not yet supported and accessing this pinctrl while SMC is
+ * suspended results in a hang.
+ */
+ status = "disabled";
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt";
+ /* Note that A11 doesn't actually have a hypervisor (EL2 is not implemented). */
+ interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm64/boot/dts/exynos/Makefile b/arch/arm64/boot/dts/exynos/Makefile
index d7f2191c2cdb..7a934499b235 100644
--- a/arch/arm64/boot/dts/exynos/Makefile
+++ b/arch/arm64/boot/dts/exynos/Makefile
@@ -7,5 +7,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += \
exynos7-espresso.dtb \
exynos7885-jackpotlte.dtb \
exynos850-e850-96.dtb \
+ exynos8895-dreamlte.dtb \
+ exynos990-c1s.dtb \
exynosautov9-sadk.dtb \
exynosautov920-sadk.dtb
diff --git a/arch/arm64/boot/dts/exynos/exynos8895-dreamlte.dts b/arch/arm64/boot/dts/exynos/exynos8895-dreamlte.dts
new file mode 100644
index 000000000000..3a376ab2bb9e
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos8895-dreamlte.dts
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung Galaxy S8 (dreamlte/SM-G950F) device tree source
+ *
+ * Copyright (c) 2024, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+ */
+
+/dts-v1/;
+#include "exynos8895.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ model = "Samsung Galaxy S8 (SM-G950F)";
+ compatible = "samsung,dreamlte", "samsung,exynos8895";
+ chassis-type = "handset";
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges;
+
+ framebuffer: framebuffer@cc000000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0xcc000000 (1440 * 2960 * 4)>;
+ width = <1440>;
+ height = <2960>;
+ stride = <(1440 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x3c800000>,
+ <0x0 0xc0000000 0x40000000>,
+ <0x8 0x80000000 0x80000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges;
+
+ ramoops@92000000 {
+ compatible = "ramoops";
+ reg = <0 0x92000000 0x8000>;
+ record-size = <0x4000>;
+ console-size = <0x4000>;
+ };
+
+ cont_splash_mem: framebuffer@cc000000 {
+ reg = <0 0xcc000000 (1440 * 2960 * 4)>;
+ no-map;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&key_power &key_voldown &key_volup &key_wink>;
+ pinctrl-names = "default";
+
+ power-key {
+ label = "Power";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpa2 4 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+
+ voldown-key {
+ label = "Volume Down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ gpios = <&gpa0 4 GPIO_ACTIVE_LOW>;
+ };
+
+ volup-key {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&gpa0 3 GPIO_ACTIVE_LOW>;
+ };
+
+ /* Typically used for Bixby. Map it as a camera button for now */
+ wink-key {
+ label = "Camera";
+ linux,code = <KEY_CAMERA>;
+ gpios = <&gpa0 6 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+ };
+};
+
+&oscclk {
+ clock-frequency = <26000000>;
+};
+
+&pinctrl_alive {
+ key_power: key-power-pins {
+ samsung,pins = "gpa2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ key_voldown: key-voldown-pins {
+ samsung,pins = "gpa0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ key_volup: key-volup-pins {
+ samsung,pins = "gpa0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ key_wink: key-wink-pins {
+ samsung,pins = "gpa0-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/exynos/exynos8895-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos8895-pinctrl.dtsi
new file mode 100644
index 000000000000..51e9c9c4b166
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos8895-pinctrl.dtsi
@@ -0,0 +1,1094 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung's Exynos 8895 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2024, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "exynos-pinctrl.h"
+
+&pinctrl_abox {
+ gph0: gph0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gph1: gph1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gph3: gph3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+};
+
+&pinctrl_alive {
+ gpa0: gpa0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gic>;
+ 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>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpa1: gpa1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpa2: gpa2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpa3: gpa3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpa4: gpa4-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ bt_hostwake: bt-hostwake-pins {
+ samsung,pins = "gpa2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ pcie_wake: pcie-wake-pins {
+ samsung,pins = "gpa3-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart1_bus: uart1-bus-pins {
+ samsung,pins = "gpa4-4", "gpa4-3", "gpa4-2", "gpa4-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ wlan_host_wake: wlan-host-wake-pins {
+ samsung,pins = "gpa0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_DOWN>;
+ };
+};
+
+&pinctrl_busc {
+ gpb2: gpb2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ hsi2c0_bus: hsi2c0-bus-pins {
+ samsung,pins = "gpb2-1", "gpb2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ speedy_bus: speedy-bus-pins {
+ samsung,pins = "gpb2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+};
+
+&pinctrl_fsys0 {
+ gpi0: gpi0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpi1: gpi1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ ufs_rst_n: ufs-rst-n-pins {
+ samsung,pins = "gpi0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ };
+
+ ufs_refclk_out: ufs-refclk-out-pins {
+ samsung,pins = "gpi0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ };
+};
+
+&pinctrl_fsys1 {
+ gpj0: gpj0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj1: gpj1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ bt_btwake: bt-btwake-pins {
+ samsung,pins = "gpj1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ bt_en: bt-en-pins {
+ samsung,pins ="gpj1-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ cfg_wlanen: cfg-wlanen-pins {
+ samsung,pins = "gpj1-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ };
+
+ sd2_clk: sd2-clk-pins {
+ samsung,pins = "gpj0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV2>;
+ };
+
+ sd2_cmd: sd2-cmd-pins {
+ samsung,pins = "gpj0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV3>;
+ };
+
+ sd2_bus1: sd2-bus-width1-pins {
+ samsung,pins = "gpj0-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV3>;
+ };
+
+ sd2_bus4: sd2-bus-width4-pins {
+ samsung,pins = "gpj0-3", "gpj0-4", "gpj0-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV3>;
+ };
+
+ /* For Drive strength swapping */
+ sd2_clk_fast_slew_rate_1x: sd2-clk-fast-slew-rate-1x-pins {
+ samsung,pins = "gpj0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ sd2_clk_fast_slew_rate_2x: sd2-clk-fast-slew-rate-2x-pins {
+ samsung,pins = "gpj0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV3>;
+ };
+
+ sd2_clk_fast_slew_rate_3x: sd2-clk-fast-slew-rate-3x-pins {
+ samsung,pins = "gpj0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV2>;
+ };
+
+ sd2_clk_fast_slew_rate_4x: sd2-clk-fast-slew-rate-4x-pins {
+ samsung,pins = "gpj0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+ };
+};
+
+&pinctrl_peric0 {
+ gpb1: gpb1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd0: gpd0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd1: gpd1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd2: gpd2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd3: gpd3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe7: gpe7-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf1: gpf1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ hsi2c5_bus: hsi2c5-bus-pins {
+ samsung,pins = "gpd1-1", "gpd1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c6_bus: hsi2c6-bus-pins {
+ samsung,pins = "gpd1-3", "gpd1-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c7_bus: hsi2c7-bus-pins {
+ samsung,pins = "gpd1-5", "gpd1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c8_bus: hsi2c8-bus-pins {
+ samsung,pins = "gpd1-7", "gpd1-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c9_bus: hsi2c9-bus-pins {
+ samsung,pins = "gpd2-1", "gpd2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c10_bus: hsi2c10-bus-pins {
+ samsung,pins = "gpd2-3", "gpd2-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c11_bus: hsi2c11-bus-pins {
+ samsung,pins = "gpd3-1", "gpd3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c12_bus: hsi2c12-bus-pins {
+ samsung,pins = "gpd3-3", "gpd3-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hs_i2c14_bus: hs-i2c14-bus-pins {
+ samsung,pins = "gpe6-3", "gpe6-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV2>;
+ };
+
+ spi2_bus: spi2-bus-pins {
+ samsung,pins = "gpd1-3", "gpd1-2", "gpd1-1", "gpd1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV2>;
+ };
+
+ spi2_cs: spi2-cs-pins {
+ samsung,pins = "gpd1-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi3_bus: spi3-bus-pins {
+ samsung,pins = "gpd1-7", "gpd1-5", "gpd1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi3_cs: spi3-cs-pins {
+ samsung,pins = "gpd1-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi4_bus: spi4-bus-pins {
+ samsung,pins = "gpd2-3", "gpd2-1", "gpd2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi4_cs: spi4-cs-pins {
+ samsung,pins = "gpd2-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi5_bus: spi5-bus-pins {
+ samsung,pins = "gpd3-3", "gpd3-1", "gpd3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi5_cs: spi5-cs-pins {
+ samsung,pins = "gpd3-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ uart0_bus: uart0-bus-pins {
+ samsung,pins = "gpd0-7", "gpd0-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart2_bus: uart2-bus-pins {
+ samsung,pins = "gpd1-3", "gpd1-2", "gpd1-1", "gpd1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart2_bus_dual: uart2-bus-dual-pins {
+ samsung,pins = "gpd1-1", "gpd1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart3_bus: uart3-bus-pins {
+ samsung,pins = "gpd1-7", "gpd1-6", "gpd1-5", "gpd1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart3_bus_dual: uart3-bus-dual-pins {
+ samsung,pins = "gpd1-5", "gpd1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart4_bus: uart4-bus-pins {
+ samsung,pins = "gpd2-3", "gpd2-2", "gpd2-1", "gpd2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart4_bus_dual: uart4-bus-dual-pins {
+ samsung,pins = "gpd2-1", "gpd2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart5_bus: uart5-bus-pins {
+ samsung,pins = "gpd3-3", "gpd3-2", "gpd3-1", "gpd3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart5_bus_dual: uart5-bus-dual-pins {
+ samsung,pins = "gpd3-1", "gpd3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+};
+
+&pinctrl_peric1 {
+ gpb0: gpb0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc0: gpc0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc1: gpc1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc2: gpc2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc3: gpc3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe1: gpe1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe2: gpe2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe3: gpe3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe4: gpe4-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe5: gpe5-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe6: gpe6-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf0: gpf0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpg0: gpg0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpk0: gpk0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ hrm_irq: hrm-irq-pins {
+ samsung,pins = "gpe6-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+ };
+
+ hsi2c1_bus: hsi2c1-bus-pins {
+ samsung,pins = "gpc2-1", "gpc2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c2_bus: hsi2c2-bus-pins {
+ samsung,pins = "gpc2-3", "gpc2-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV4>;
+ };
+
+ hsi2c3_bus: hsi2c3-bus-pins {
+ samsung,pins = "gpc2-5", "gpc2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c4_bus: hsi2c4-bus-pins {
+ samsung,pins = "gpc2-7", "gpc2-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c13_bus: hsi2c13-bus-pins {
+ samsung,pins = "gpe5-1", "gpe5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c14_bus: hsi2c14-bus-pins {
+ samsung,pins = "gpe5-3", "gpe5-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c15_bus: hsi2c15-bus-pins {
+ samsung,pins = "gpe1-1", "gpe1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c16_bus: hsi2c16-bus-pins {
+ samsung,pins = "gpe1-3", "gpe1-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c17_bus: hsi2c17-bus-pins {
+ samsung,pins = "gpe1-5", "gpe1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c18_bus: hsi2c18-bus-pins {
+ samsung,pins = "gpe1-7", "gpe1-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c19_bus: hsi2c19-bus-pins {
+ samsung,pins = "gpe2-1", "gpe2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c20_bus: hsi2c20-bus-pins {
+ samsung,pins = "gpe2-3", "gpe2-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c21_bus: hsi2c21-bus-pins {
+ samsung,pins = "gpe2-5", "gpe2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c22_bus: hsi2c22-bus-pins {
+ samsung,pins = "gpe2-7", "gpe2-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c23_bus: hsi2c23-bus-pins {
+ samsung,pins = "gpe3-1", "gpe3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c24_bus: hsi2c24-bus-pins {
+ samsung,pins = "gpe3-3", "gpe3-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c25_bus: hsi2c25-bus-pins {
+ samsung,pins = "gpe3-5", "gpe3-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c26_bus: hsi2c26-bus-pins {
+ samsung,pins = "gpe3-7", "gpe3-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c27_bus: hsi2c27-bus-pins {
+ samsung,pins = "gpe4-1", "gpe4-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c28_bus: hsi2c28-bus-pins {
+ samsung,pins = "gpe4-3", "gpe4-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c29_bus: hsi2c29-bus-pins {
+ samsung,pins = "gpe4-5", "gpe4-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c30_bus: hsi2c30-bus-pins {
+ samsung,pins = "gpe4-7", "gpe4-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV2>;
+ };
+
+ hsi2c31_bus: hsi2c31-bus-pins {
+ samsung,pins = "gpe5-5", "gpe5-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ hsi2c32_bus: hsi2c32-bus-pins {
+ samsung,pins = "gpe5-7", "gpe5-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi0_bus: spi0-bus-pins {
+ samsung,pins = "gpc3-3", "gpc3-2", "gpc3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi0_cs: spi0-cs-pins {
+ samsung,pins = "gpc3-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi1_bus: spi1-bus-pins {
+ samsung,pins = "gpc3-7", "gpc3-6", "gpc3-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi1_cs: spi1-cs-pins {
+ samsung,pins = "gpc3-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi6_bus: spi6-bus-pins {
+ samsung,pins = "gpe5-3", "gpe5-1", "gpe5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi6_cs: spi6-cs-pins {
+ samsung,pins = "gpe5-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi7_bus: spi7-bus-pins {
+ samsung,pins = "gpe1-3", "gpe1-1", "gpe1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi7_cs: spi7-cs-pins {
+ samsung,pins = "gpe1-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi8_bus: spi8-bus-pins {
+ samsung,pins = "gpe1-7", "gpe1-5", "gpe1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi8_cs: spi8-cs-pins {
+ samsung,pins = "gpe1-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi9_bus: spi9-bus-pins {
+ samsung,pins = "gpe2-3", "gpe2-1", "gpe2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi9_cs: spi9-cs-pins {
+ samsung,pins = "gpe2-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi10_bus: spi10-bus-pins {
+ samsung,pins = "gpe2-7", "gpe2-5", "gpe2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi10_cs: spi10-cs-pins {
+ samsung,pins = "gpe2-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi11_bus: spi11-bus-pins {
+ samsung,pins = "gpe3-3", "gpe3-1", "gpe3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi11_cs: spi11-cs-pins {
+ samsung,pins = "gpe3-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi12_bus: spi12-bus-pins {
+ samsung,pins = "gpe3-7", "gpe3-5", "gpe3-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi12_cs: spi12-cs-pins {
+ samsung,pins = "gpe3-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi13_bus: spi13-bus-pins {
+ samsung,pins = "gpe4-3", "gpe4-1", "gpe4-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi13_cs: spi13-cs-pins {
+ samsung,pins = "gpe4-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi14_bus: spi14-bus-pins {
+ samsung,pins = "gpe4-7", "gpe4-5", "gpe4-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi14_cs: spi14-cs-pins {
+ samsung,pins = "gpe4-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi15_bus: spi15-bus-pins {
+ samsung,pins = "gpe5-7", "gpe5-5", "gpe5-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ spi15_cs: spi15-cs-pins {
+ samsung,pins = "gpe5-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS7_PIN_DRV_LV1>;
+ };
+
+ uart6_bus: uart6-bus-pins {
+ samsung,pins = "gpe5-3", "gpe5-2", "gpe5-1", "gpe5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart6_bus_dual: uart6-bus-dual-pins {
+ samsung,pins = "gpe5-1", "gpe5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart7_bus: uart7-bus-pins {
+ samsung,pins = "gpe1-3", "gpe1-2", "gpe1-1", "gpe1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart7_bus_dual: uart7-bus-dual-pins {
+ samsung,pins = "gpe1-1", "gpe1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart8_bus: uart8-bus-pins {
+ samsung,pins = "gpe1-7", "gpe1-6", "gpe1-5", "gpe1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart8_bus_dual: uart8-bus-dual-pins {
+ samsung,pins = "gpe1-5", "gpe1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart9_bus: uart9-bus-pins {
+ samsung,pins = "gpe2-3", "gpe2-2", "gpe2-1", "gpe2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart9_bus_dual: uart9-bus-dual-pins {
+ samsung,pins = "gpe2-1", "gpe2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart10_bus: uart10-bus-pins {
+ samsung,pins = "gpe2-7", "gpe2-6", "gpe2-5", "gpe2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart10_bus_dual: uart10-bus-dual-pins {
+ samsung,pins = "gpe2-5", "gpe2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart11_bus: uart11-bus-pins {
+ samsung,pins = "gpe3-3", "gpe3-2", "gpe3-1", "gpe3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart11_bus_dual: uart11-bus-dual-pins {
+ samsung,pins = "gpe3-1", "gpe3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart12_bus: uart12-bus-pins {
+ samsung,pins = "gpe3-7", "gpe3-6", "gpe3-5", "gpe3-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart12_bus_dual: uart12-bus-dual-pins {
+ samsung,pins = "gpe3-5", "gpe3-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart13_bus: uart13-bus-pins {
+ samsung,pins = "gpe4-3", "gpe4-2", "gpe4-1", "gpe4-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart13_bus_dual: uart13-bus-dual-pins {
+ samsung,pins = "gpe4-1", "gpe4-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart14_bus: uart14-bus-pins {
+ samsung,pins = "gpe4-7", "gpe4-6", "gpe4-5", "gpe4-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart14_bus_dual: uart14-bus-dual-pins {
+ samsung,pins = "gpe4-5", "gpe4-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart15_bus: uart15-bus-pins {
+ samsung,pins = "gpe5-7", "gpe5-6", "gpe5-5", "gpe5-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart15_bus_dual: uart15-bus-dual-pins {
+ samsung,pins = "gpe5-5", "gpe5-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+};
+
+&pinctrl_vts {
+ gph2: gph2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+};
diff --git a/arch/arm64/boot/dts/exynos/exynos8895.dtsi b/arch/arm64/boot/dts/exynos/exynos8895.dtsi
new file mode 100644
index 000000000000..9f9ac5359879
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos8895.dtsi
@@ -0,0 +1,386 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung's Exynos 8895 SoC device tree source
+ *
+ * Copyright (c) 2024, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+ */
+
+#include <dt-bindings/clock/samsung,exynos8895.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "samsung,exynos8895";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&gic>;
+
+ aliases {
+ pinctrl0 = &pinctrl_alive;
+ pinctrl1 = &pinctrl_abox;
+ pinctrl2 = &pinctrl_vts;
+ pinctrl3 = &pinctrl_fsys0;
+ pinctrl4 = &pinctrl_fsys1;
+ pinctrl5 = &pinctrl_busc;
+ pinctrl6 = &pinctrl_peric0;
+ pinctrl7 = &pinctrl_peric1;
+ };
+
+ arm-a53-pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>,
+ <&cpu1>,
+ <&cpu2>,
+ <&cpu3>;
+ };
+
+ /* There's no PMU model for the Mongoose cores */
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ 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>;
+ };
+ };
+ };
+
+ cpu4: cpu@0 {
+ device_type = "cpu";
+ compatible = "samsung,mongoose-m2";
+ reg = <0x0>;
+ enable-method = "psci";
+ };
+
+ cpu5: cpu@1 {
+ device_type = "cpu";
+ compatible = "samsung,mongoose-m2";
+ reg = <0x1>;
+ enable-method = "psci";
+ };
+
+ cpu6: cpu@2 {
+ device_type = "cpu";
+ compatible = "samsung,mongoose-m2";
+ reg = <0x2>;
+ enable-method = "psci";
+ };
+
+ cpu7: cpu@3 {
+ device_type = "cpu";
+ compatible = "samsung,mongoose-m2";
+ reg = <0x3>;
+ enable-method = "psci";
+ };
+
+ cpu0: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x100>;
+ enable-method = "psci";
+ };
+
+ cpu1: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x101>;
+ enable-method = "psci";
+ };
+
+ cpu2: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x102>;
+ enable-method = "psci";
+ };
+
+ cpu3: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x103>;
+ enable-method = "psci";
+ };
+ };
+
+ oscclk: osc-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "oscclk";
+ };
+
+ psci {
+ compatible = "arm,psci";
+ method = "smc";
+ cpu_off = <0x84000002>;
+ cpu_on = <0xc4000003>;
+ cpu_suspend = <0xc4000001>;
+ };
+
+ soc: soc@0 {
+ compatible = "simple-bus";
+ ranges = <0x0 0x0 0x0 0x20000000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ chipid@10000000 {
+ compatible = "samsung,exynos8895-chipid",
+ "samsung,exynos850-chipid";
+ reg = <0x10000000 0x24>;
+ };
+
+ cmu_peris: clock-controller@10010000 {
+ compatible = "samsung,exynos8895-cmu-peris";
+ reg = <0x10010000 0x8000>;
+ #clock-cells = <1>;
+ clocks = <&oscclk>,
+ <&cmu_top CLK_DOUT_CMU_PERIS_BUS>;
+ clock-names = "oscclk", "bus";
+ };
+
+ timer@10040000 {
+ compatible = "samsung,exynos8895-mct",
+ "samsung,exynos4210-mct";
+ reg = <0x10040000 0x800>;
+ clocks = <&oscclk>, <&cmu_peris CLK_GOUT_PERIS_MCT_PCLK>;
+ clock-names = "fin_pll", "mct";
+ interrupts = <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gic: interrupt-controller@10201000 {
+ compatible = "arm,gic-400";
+ reg = <0x10201000 0x1000>,
+ <0x10202000 0x1000>,
+ <0x10204000 0x2000>,
+ <0x10206000 0x2000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) |
+ IRQ_TYPE_LEVEL_HIGH)>;
+ #address-cells = <0>;
+ #size-cells = <1>;
+ };
+
+ cmu_peric0: clock-controller@10400000 {
+ compatible = "samsung,exynos8895-cmu-peric0";
+ reg = <0x10400000 0x8000>;
+ #clock-cells = <1>;
+ clocks = <&oscclk>,
+ <&cmu_top CLK_DOUT_CMU_PERIC0_BUS>,
+ <&cmu_top CLK_DOUT_CMU_PERIC0_UART_DBG>,
+ <&cmu_top CLK_DOUT_CMU_PERIC0_USI00>,
+ <&cmu_top CLK_DOUT_CMU_PERIC0_USI01>,
+ <&cmu_top CLK_DOUT_CMU_PERIC0_USI02>,
+ <&cmu_top CLK_DOUT_CMU_PERIC0_USI03>;
+ clock-names = "oscclk", "bus", "uart", "usi0",
+ "usi1", "usi2", "usi3";
+ };
+
+ pinctrl_peric0: pinctrl@104d0000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x104d0000 0x1000>;
+ interrupts = <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ cmu_peric1: clock-controller@10800000 {
+ compatible = "samsung,exynos8895-cmu-peric1";
+ reg = <0x10800000 0x8000>;
+ #clock-cells = <1>;
+ clocks = <&oscclk>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_BUS>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_SPEEDY2>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_SPI_CAM0>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_SPI_CAM1>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_UART_BT>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI04>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI05>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI06>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI07>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI08>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI09>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI10>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI11>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI12>,
+ <&cmu_top CLK_DOUT_CMU_PERIC1_USI13>;
+ clock-names = "oscclk", "bus", "speedy", "cam0",
+ "cam1", "uart", "usi4", "usi5",
+ "usi6", "usi7", "usi8", "usi9",
+ "usi10", "usi11", "usi12", "usi13";
+ };
+
+ pinctrl_peric1: pinctrl@10980000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x10980000 0x1000>;
+ interrupts = <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ spi_0: spi@109d0000 {
+ compatible = "samsung,exynos8895-spi",
+ "samsung,exynos850-spi";
+ reg = <0x109d0000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&cmu_peric1 CLK_GOUT_PERIC1_SPI_CAM0_PCLK>,
+ <&cmu_peric1 CLK_GOUT_PERIC1_SPI_CAM0_SPI_EXT_CLK>;
+ clock-names = "spi", "spi_busclk0";
+ interrupts = <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&spi0_bus>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ spi_1: spi@109e0000 {
+ compatible = "samsung,exynos8895-spi",
+ "samsung,exynos850-spi";
+ reg = <0x109e0000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&cmu_peric1 CLK_GOUT_PERIC1_SPI_CAM1_PCLK>,
+ <&cmu_peric1 CLK_GOUT_PERIC1_SPI_CAM1_SPI_EXT_CLK>;
+ clock-names = "spi", "spi_busclk0";
+ interrupts = <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&spi1_bus>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ cmu_fsys0: clock-controller@11000000 {
+ compatible = "samsung,exynos8895-cmu-fsys0";
+ reg = <0x11000000 0x8000>;
+ #clock-cells = <1>;
+ clocks = <&oscclk>,
+ <&cmu_top CLK_DOUT_CMU_FSYS0_BUS>,
+ <&cmu_top CLK_DOUT_CMU_FSYS0_DPGTC>,
+ <&cmu_top CLK_DOUT_CMU_FSYS0_MMC_EMBD>,
+ <&cmu_top CLK_DOUT_CMU_FSYS0_UFS_EMBD>,
+ <&cmu_top CLK_DOUT_CMU_FSYS0_USBDRD30>;
+ clock-names = "oscclk", "bus", "dpgtc", "mmc",
+ "ufs", "usbdrd30";
+ };
+
+ pinctrl_fsys0: pinctrl@11050000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x11050000 0x1000>;
+ interrupts = <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ cmu_fsys1: clock-controller@11400000 {
+ compatible = "samsung,exynos8895-cmu-fsys1";
+ reg = <0x11400000 0x8000>;
+ #clock-cells = <1>;
+ clocks = <&oscclk>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_BUS>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_PCIE>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_UFS_CARD>,
+ <&cmu_top CLK_DOUT_CMU_FSYS1_MMC_CARD>;
+ clock-names = "oscclk", "bus", "pcie", "ufs", "mmc";
+ };
+
+ pinctrl_fsys1: pinctrl@11430000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x11430000 0x1000>;
+ interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_abox: pinctrl@13e60000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x13e60000 0x1000>;
+ };
+
+ pinctrl_vts: pinctrl@14080000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x14080000 0x1000>;
+ };
+
+ pinctrl_busc: pinctrl@15a30000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x15a30000 0x1000>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ cmu_top: clock-controller@15a80000 {
+ compatible = "samsung,exynos8895-cmu-top";
+ reg = <0x15a80000 0x8000>;
+ #clock-cells = <1>;
+ clocks = <&oscclk>;
+ clock-names = "oscclk";
+ };
+
+ pmu_system_controller: system-controller@16480000 {
+ compatible = "samsung,exynos8895-pmu",
+ "samsung,exynos7-pmu", "syscon";
+ reg = <0x16480000 0x10000>;
+ };
+
+ pinctrl_alive: pinctrl@164b0000 {
+ compatible = "samsung,exynos8895-pinctrl";
+ reg = <0x164b0000 0x1000>;
+
+ wakeup-interrupt-controller {
+ compatible = "samsung,exynos8895-wakeup-eint",
+ "samsung,exynos7-wakeup-eint";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ /* Hypervisor Virtual Timer interrupt is not wired to GIC */
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ /*
+ * Non-updatable, broken stock Samsung bootloader does not
+ * configure CNTFRQ_EL0
+ */
+ clock-frequency = <26000000>;
+ };
+};
+
+#include "exynos8895-pinctrl.dtsi"
+#include "arm/samsung/exynos-syscon-restart.dtsi"
diff --git a/arch/arm64/boot/dts/exynos/exynos990-c1s.dts b/arch/arm64/boot/dts/exynos/exynos990-c1s.dts
new file mode 100644
index 000000000000..36a6f1377e92
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos990-c1s.dts
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung Galaxy Note20 5G (c1s/SM-N981B) device tree source
+ *
+ * Copyright (c) 2024, Igor Belwon <igor.belwon@mentallysanemainliners.org>
+ */
+
+/dts-v1/;
+#include "exynos990.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ model = "Samsung Galaxy Note20";
+ compatible = "samsung,c1s", "samsung,exynos990";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer0: framebuffer@f1000000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0xf1000000 0 (1080 * 2400 * 4)>;
+ width = <1080>;
+ height = <2400>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x3ab00000>,
+ /* Memory hole */
+ <0x0 0xc1200000 0x0 0x1ee00000>,
+ /* Memory hole */
+ <0x0 0xe1900000 0x0 0x1e700000>,
+ /* Memory hole - last block */
+ <0x8 0x80000000 0x1 0x7ec00000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ cont_splash_mem: framebuffer@f1000000 {
+ reg = <0 0xf1000000 0 0x13c6800>;
+ no-map;
+ };
+
+ abox_reserved: audio@f7fb0000 {
+ reg = <0 0xf7fb0000 0 0x2a50000>;
+ no-map;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&key_power &key_voldown &key_volup>;
+ pinctrl-names = "default";
+
+ power-key {
+ label = "Power";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpa2 4 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+
+ voldown-key {
+ label = "Volume Down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ gpios = <&gpa0 4 GPIO_ACTIVE_LOW>;
+ };
+
+ volup-key {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&gpa0 3 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&oscclk {
+ clock-frequency = <26000000>;
+};
+
+&pinctrl_alive {
+ key_power: key-power-pins {
+ samsung,pins = "gpa2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ key_voldown: key-voldown-pins {
+ samsung,pins = "gpa0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ key_volup: key-volup-pins {
+ samsung,pins = "gpa0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/exynos/exynos990-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos990-pinctrl.dtsi
new file mode 100644
index 000000000000..a03d36458d76
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos990-pinctrl.dtsi
@@ -0,0 +1,2195 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung Exynos 990 pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2024, Igor Belwon <igor.belwon@mentallysanemainliners.org>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "exynos-pinctrl.h"
+
+&pinctrl_alive {
+ gpa0: gpa0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gic>;
+ 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>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpa1: gpa1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpa2: gpa2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpa3: gpa3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpa4: gpa4-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpq0: gpq0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ speedy_bus: speedy-bus-pins {
+ samsung,pins = "gpq0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ speedy1_bus: speedy1-bus-pins {
+ samsung,pins = "gpq0-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ /* UART1 is also referred to as UART_BT in downstream. */
+ uart1_bus_single: uart1-bus-pins {
+ samsung,pins = "gpq0-3", "gpq0-2", "gpq0-1", "gpq0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ };
+
+ uart1_rxd_pull: uart1-bus-rxd-pins {
+ samsung,pins = "gpq0-0";
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ };
+
+ uart1_bus_rts: uart1-bus-rts-pins {
+ samsung,pins = "gpq0-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart1_bus_tx_input: uart1-bus-tx-input-pins {
+ samsung,pins = "gpq0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ };
+
+ uart1_bus_tx_dat: uart1-bus-tx-dat-pins {
+ samsung,pins = "gpq0-1";
+ };
+
+ uart1_bus_tx_con: uart1-bus-tx-con-pins {
+ samsung,pins = "gpq0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ };
+
+ wlan_host_wake: wlan-host-wake-pins {
+ samsung,pins = "gpa0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+};
+
+&pinctrl_cmgp {
+ gpm0: gpm0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm1: gpm1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm2: gpm2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm3: gpm3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm4: gpm4-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm5: gpm5-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm6: gpm6-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm7: gpm7-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm8: gpm8-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm9: gpm9-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm10: gpm10-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm11: gpm11-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm12: gpm12-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm13: gpm13-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm14: gpm14-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm15: gpm15-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm16: gpm16-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm17: gpm17-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm18: gpm18-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm19: gpm19-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm20: gpm20-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm21: gpm21-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm22: gpm22-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm23: gpm23-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm24: gpm24-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm25: gpm25-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm26: gpm26-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm27: gpm27-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm28: gpm28-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm29: gpm29-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm30: gpm30-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm31: gpm31-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm32: gpm32-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ gpm33: gpm33-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ hsi2c38_bus: hsi2c38-bus-pins {
+ samsung,pins = "gpm0-0", "gpm1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c39_bus: hsi2c39-bus-pins {
+ samsung,pins = "gpm2-0", "gpm3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c40_bus: hsi2c40-bus-pins {
+ samsung,pins = "gpm4-0", "gpm5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c41_bus: hsi2c41-bus-pins {
+ samsung,pins = "gpm6-0", "gpm7-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c42_bus: hsi2c42-bus-pins {
+ samsung,pins = "gpm8-0", "gpm9-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c43_bus: hsi2c43-bus-pins {
+ samsung,pins = "gpm10-0", "gpm11-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c44_bus: hsi2c44-bus-pins {
+ samsung,pins = "gpm12-0", "gpm13-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c45_bus: hsi2c45-bus-pins {
+ samsung,pins = "gpm14-0", "gpm15-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi19_bus: spi19-bus-pins {
+ samsung,pins = "gpm0-0", "gpm1-0", "gpm2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi19_cs: spi19-cs-pins {
+ samsung,pins = "gpm3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi19_cs_func: spi19-cs-func-pins {
+ samsung,pins = "gpm3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi20_bus: spi20-bus-pins {
+ samsung,pins = "gpm4-0", "gpm5-0", "gpm6-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi20_cs: spi20-cs-pins {
+ samsung,pins = "gpm7-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi20_cs_func: spi20-cs-func-pins {
+ samsung,pins = "gpm7-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi21_bus: spi21-bus-pins {
+ samsung,pins = "gpm8-0", "gpm9-0", "gpm10-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi21_cs: spi21-cs-pins {
+ samsung,pins = "gpm11-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi21_cs_func: spi21-cs-func-pins {
+ samsung,pins = "gpm11-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi22_bus: spi22-bus-pins {
+ samsung,pins = "gpm12-0", "gpm13-0", "gpm14-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi22_cs: spi22-cs-pins {
+ samsung,pins = "gpm15-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi22_cs_func: spi22-cs-func-pins {
+ samsung,pins = "gpm15-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ uart21_bus_single: uart21-bus-pins {
+ samsung,pins = "gpm0-0", "gpm1-0", "gpm2-0", "gpm3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart21_bus_dual: uart21-bus-dual-pins {
+ samsung,pins = "gpm0-0", "gpm1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart22_bus_single: uart22-bus-pins {
+ samsung,pins = "gpm4-0", "gpm5-0", "gpm6-0", "gpm7-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart22_bus_dual: uart22-bus-dual-pins {
+ samsung,pins = "gpm4-0", "gpm5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart23_bus_single: uart23-bus-pins {
+ samsung,pins = "gpm8-0", "gpm9-0", "gpm10-0", "gpm11-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart23_bus_dual: uart23-bus-dual-pins {
+ samsung,pins = "gpm8-0", "gpm9-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart24_bus_single: uart24-bus-pins {
+ samsung,pins = "gpm12-0", "gpm13-0", "gpm14-0", "gpm15-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart24_bus_dual: uart24-bus-dual-pins {
+ samsung,pins = "gpm12-0", "gpm13-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+};
+
+&pinctrl_hsi1 {
+ gpf0: gpf0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf1: gpf1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf2: gpf2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pcie0_clkreq: pcie0-clkreq-pins {
+ samsung,pins = "gpf0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_UP>;
+ };
+
+ pcie0_perst: pcie0-perst-pins {
+ samsung,pins = "gpf0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ };
+
+ pcie1_clkreq: pcie1-clkreq-pins {
+ samsung,pins = "gpf0-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_UP>;
+ };
+
+ pcie1_perst: pcie1-perst-pins {
+ samsung,pins = "gpf0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ };
+
+ ufs_rst_n: ufs-rst-n-pins {
+ samsung,pins = "gpf2-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ ufs_refclk_out: ufs-refclk-out-pins {
+ samsung,pins = "gpf2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ sd2_clk: sd2-clk-pins {
+ samsung,pins = "gpf1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV3>;
+ };
+
+ sd2_cmd: sd2-cmd-pins {
+ samsung,pins = "gpf1-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ };
+
+ sd2_bus1: sd2-bus-width1-pins {
+ samsung,pins = "gpf1-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ };
+
+ sd2_bus4: sd2-bus-width4-pins {
+ samsung,pins = "gpf1-3", "gpf1-4", "gpf1-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ };
+
+ sd2_clk_fast_slew_rate_1x: sd2-clk-fast-slew-rate-1x-pins {
+ samsung,pins = "gpf1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV1>;
+ };
+
+ sd2_clk_fast_slew_rate_1_5x: sd2-clk-fast-slew-rate-1-5x-pins {
+ samsung,pins = "gpf1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV1_5>;
+ };
+
+ sd2_clk_fast_slew_rate_2x: sd2-clk-fast-slew-rate-2x-pins {
+ samsung,pins = "gpf1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2>;
+ };
+
+ sd2_clk_fast_slew_rate_2_5x: sd2-clk-fast-slew-rate-2-5x-pins {
+ samsung,pins = "gpf1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV2_5>;
+ };
+
+ sd2_clk_fast_slew_rate_3x: sd2-clk-fas-slew-rate-3x-pins {
+ samsung,pins = "gpf1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV3>;
+ };
+
+ sd2_clk_fast_slew_rate_4x: sd2-clk-fast-slew-rate-4x-pins {
+ samsung,pins = "gpf1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS850_HSI_PIN_DRV_LV4>;
+ };
+
+ sd2_pins_as_pdn: sd2-pins-as-pdn-pins {
+ samsung,pins = "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3", "gpf1-4", "gpf1-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ };
+};
+
+&pinctrl_hsi2 {
+ gpf3: gpf3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pcie2_clkreq: pcie2-clkreq-pins {
+ samsung,pins = "gpf3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV4>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_UP>;
+ };
+
+ pcie2_perst: pcie2-perst-pins {
+ samsung,pins = "gpf3-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV4>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ };
+};
+
+&pinctrl_peric0 {
+ gpg0: gpg0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp0: gpp0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp1: gpp1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp2: gpp2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp3: gpp3-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp4: gpp4-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ hsi2c0_bus: hsi2c0-bus-pins {
+ samsung,pins = "gpp0-0", "gpp0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c1_bus: hsi2c1-bus-pins {
+ samsung,pins = "gpp0-2", "gpp0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c2_bus: hsi2c2-bus-pins {
+ samsung,pins = "gpp0-4", "gpp0-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c3_bus: hsi2c3-bus-pins {
+ samsung,pins = "gpp0-6", "gpp0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c4_bus: hsi2c4-bus-pins {
+ samsung,pins = "gpp1-0", "gpp1-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ hsi2c5_bus: hsi2c5-bus-pins {
+ samsung,pins = "gpp1-2", "gpp1-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c6_bus: hsi2c6-bus-pins {
+ samsung,pins = "gpp1-4", "gpp1-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c7_bus: hsi2c7-bus-pins {
+ samsung,pins = "gpp1-6", "gpp1-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c8_bus: hsi2c8-bus-pins {
+ samsung,pins = "gpp2-0", "gpp2-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c9_bus: hsi2c9-bus-pins {
+ samsung,pins = "gpp2-2", "gpp2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c10_bus: hsi2c10-bus-pins {
+ samsung,pins = "gpp2-4", "gpp2-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c11_bus: hsi2c11-bus-pins {
+ samsung,pins = "gpp2-6", "gpp2-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c26_bus: hsi2c26-bus-pins {
+ samsung,pins = "gpp3-0", "gpp3-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c27_bus: hsi2c27-bus-pins {
+ samsung,pins = "gpp3-2", "gpp3-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ hsi2c28_bus: hsi2c28-bus-pins {
+ samsung,pins = "gpp3-4", "gpp3-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c29_bus: hsi2c29-bus-pins {
+ samsung,pins = "gpp3-6", "gpp3-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c30_bus: hsi2c30-bus-pins {
+ samsung,pins = "gpp4-0", "gpp4-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c31_bus: hsi2c31-bus-pins {
+ samsung,pins = "gpp4-2", "gpp4-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi0_bus: spi0-bus-pins {
+ samsung,pins = "gpp0-2", "gpp0-1", "gpp0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi0_cs: spi0-cs-pins {
+ samsung,pins = "gpp0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi0_cs_func: spi0-cs-func-pins {
+ samsung,pins = "gpp0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi1_bus: spi1-bus-pins {
+ samsung,pins = "gpp0-6", "gpp0-5", "gpp0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi1_cs: spi1-cs-pins {
+ samsung,pins = "gpp0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi1_cs_func: spi1-cs-func-pins {
+ samsung,pins = "gpp0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi2_bus: spi2-bus-pins {
+ samsung,pins = "gpp1-2", "gpp1-1", "gpp1-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi2_cs: spi2-cs-pins {
+ samsung,pins = "gpp1-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi2_cs_func: spi2-cs-func-pins {
+ samsung,pins = "gpp1-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi3_bus: spi3-bus-pins {
+ samsung,pins = "gpp1-6", "gpp1-5", "gpp1-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi3_cs: spi3-cs-pins {
+ samsung,pins = "gpp1-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi3_cs_func: spi3-cs-func-pins {
+ samsung,pins = "gpp1-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi4_bus: spi4-bus-pins {
+ samsung,pins = "gpp2-2", "gpp2-1", "gpp2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi4_cs: spi4-cs-pins {
+ samsung,pins = "gpp2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi4_cs_func: spi4-cs-func-pins {
+ samsung,pins = "gpp2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi4_fp_inactive: spi4-fp-inactive-pins {
+ samsung,pins = "gpp2-3", "gpp2-2", "gpp2-1", "gpp2-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi4_fp_cs_func_high: spi4-fp-cs-func-high-pins {
+ samsung,pins = "gpp2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi5_bus: spi5-bus-pins {
+ samsung,pins = "gpp2-6", "gpp2-5", "gpp2-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi5_cs: spi5-cs-pins {
+ samsung,pins = "gpp2-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi5_cs_func: spi5-cs-func-pins {
+ samsung,pins = "gpp2-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi13_bus: spi13-bus-pins {
+ samsung,pins = "gpp3-2", "gpp3-1", "gpp3-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi13_cs: spi13-cs-pins {
+ samsung,pins = "gpp3-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi13_cs_func: spi13-cs-func-pins {
+ samsung,pins = "gpp3-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi14_bus: spi14-bus-pins {
+ samsung,pins = "gpp3-6", "gpp3-5", "gpp3-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi14_cs: spi14-cs-pins {
+ samsung,pins = "gpp3-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi14_cs_func: spi14-cs-func-pins {
+ samsung,pins = "gpp3-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi15_bus: spi15-bus-pins {
+ samsung,pins = "gpp4-2", "gpp4-1", "gpp4-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi15_cs: spi15-cs-pins {
+ samsung,pins = "gpp4-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi15_cs_func: spi15-cs-func-pins {
+ samsung,pins = "gpp4-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ uart0_bus: uart0-bus-pins {
+ samsung,pins = "gpp4-6", "gpp4-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ };
+
+ uart2_bus_single: uart2-bus-pins {
+ samsung,pins = "gpp0-0", "gpp0-1", "gpp0-2", "gpp0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart2_bus_dual: uart2-bus-dual-pins {
+ samsung,pins = "gpp0-0", "gpp0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart3_bus_single: uart3-bus-pins {
+ samsung,pins = "gpp0-4", "gpp0-5", "gpp0-6", "gpp0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart3_bus_dual: uart3-bus-dual-pins {
+ samsung,pins = "gpp0-4", "gpp0-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart4_bus_single: uart4-bus-pins {
+ samsung,pins = "gpp1-0", "gpp1-1", "gpp1-2", "gpp1-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart4_bus_dual: uart4-bus-dual-pins {
+ samsung,pins = "gpp1-0", "gpp1-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart5_bus_single: uart5-bus-pins {
+ samsung,pins = "gpp1-4", "gpp1-5", "gpp1-6", "gpp1-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart5_bus_dual: uart5-bus-dual-pins {
+ samsung,pins = "gpp1-4", "gpp1-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart6_bus_single: uart6-bus-pins {
+ samsung,pins = "gpp2-0", "gpp2-1", "gpp2-2", "gpp2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart6_bus_dual: uart6-bus-dual-pins {
+ samsung,pins = "gpp2-0", "gpp2-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart7_bus_single: uart7-bus-pins {
+ samsung,pins = "gpp2-4", "gpp2-5", "gpp2-6", "gpp2-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart7_bus_dual: uart7-bus-dual-pins {
+ samsung,pins = "gpp2-4", "gpp2-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart15_bus_single: uart15-bus-pins {
+ samsung,pins = "gpp3-0", "gpp3-1", "gpp3-2", "gpp3-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart15_bus_dual: uart15-bus-dual-pins {
+ samsung,pins = "gpp3-0", "gpp3-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart16_bus_single: uart16-bus-pins {
+ samsung,pins = "gpp3-4", "gpp3-5", "gpp3-6", "gpp3-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart16_bus_dual: uart16-bus-dual-pins {
+ samsung,pins = "gpp3-4", "gpp3-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart17_bus_single: uart17-bus-pins {
+ samsung,pins = "gpp4-0", "gpp4-1", "gpp4-2", "gpp4-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart17_bus_dual: uart17-bus-dual-pins {
+ samsung,pins = "gpp4-0", "gpp4-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+};
+
+&pinctrl_peric1 {
+ gpb0: gpb0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpb1: gpb1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpb2: gpb2-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc0: gpc0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpg1: gpg1-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp5: gpp5-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp6: gpp6-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp7: gpp7-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp8: gpp8-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp9: gpp9-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ aud_i2s0_bus: aud-i2s0-bus-pins {
+ samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_i2s0_idle: aud-i2s0-idle-pins {
+ samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+
+ aud_i2s1_bus: aud-i2s1-bus-pins {
+ samsung,pins = "gpb0-4", "gpb0-5", "gpb0-6", "gpb0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_i2s1_idle: aud-i2s1-idle-pins {
+ samsung,pins = "gpb0-4", "gpb0-5", "gpb0-6", "gpb0-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+
+ aud_i2s2_bus: aud-i2s2-bus-pins {
+ samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2", "gpb1-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_i2s2_idle: aud-i2s2-idle-pins {
+ samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2", "gpb1-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+
+ aud_i2s3_bus: aud-i2s3-bus-pins {
+ samsung,pins = "gpb1-4", "gpb1-5", "gpb1-6", "gpb1-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_i2s3_idle: aud-i2s3-idle-pins {
+ samsung,pins = "gpb1-4", "gpb1-5", "gpb1-6", "gpb1-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+
+ aud_i2s4_bus: aud-i2s4-bus-pins {
+ samsung,pins = "gpb2-0", "gpb2-1", "gpb2-2", "gpb2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_i2s4_pci: aud-i2s4-pci-pins {
+ samsung,pins = "gpb2-0", "gpb2-1", "gpb2-2", "gpb2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_i2s4_idle: aud-i2s4-idle-pins {
+ samsung,pins = "gpb2-0", "gpb2-1", "gpb2-2", "gpb2-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+
+ aud_i2s5_bus: aud-i2s5-bus-pins {
+ samsung,pins = "gpb2-4", "gpb2-5", "gpb2-6", "gpb2-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_i2s5_idle: aud-i2s5-idle-pins {
+ samsung,pins = "gpb2-4", "gpb2-5", "gpb2-6", "gpb2-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+
+ aud_dsd_bus: aud-dsd-bus-pins {
+ samsung,pins = "gpb2-4", "gpb2-5", "gpb2-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ aud_dsd_idle: aud-dsd-idle-pins {
+ samsung,pins = "gpb2-4", "gpb2-5", "gpb2-6";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ };
+
+ cfg_wlanen: cfg-wlanen-pins {
+ samsung,pins = "gpb0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV4>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ cnss_wlan_en_active: cnss-wlan-en-active-pins {
+ samsung,pins = "gpb0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV4>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ cnss_wlan_en_sleep: cnss-wlan-en-sleep-pins {
+ samsung,pins = "gpb0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV2>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ decon_f_te_on: decon-f-te-on-pins {
+ samsung,pins = "gpc0-4";
+ samsung,pin-function = <0xf>;
+ };
+
+ decon_f_te_off: decon-f-te-off-pins {
+ samsung,pins = "gpc0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ };
+
+ decon_s_te_on: decon-s-te-on-pins {
+ samsung,pins = "gpc0-5";
+ samsung,pin-function = <0xf>;
+ };
+
+ decon_s_te_off: decon-s-te-off-pins {
+ samsung,pins = "gpc0-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ };
+
+ hsi2c12_bus: hsi2c12-bus-pins {
+ samsung,pins = "gpp5-0", "gpp5-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c13_bus: hsi2c13-bus-pins {
+ samsung,pins = "gpp5-2", "gpp5-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c14_bus: hsi2c14-bus-pins {
+ samsung,pins = "gpp5-4", "gpp5-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c15_bus: hsi2c15-bus-pins {
+ samsung,pins = "gpp5-6", "gpp5-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c16_bus: hsi2c16-bus-pins {
+ samsung,pins = "gpp6-0", "gpp6-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c17_bus: hsi2c17-bus-pins {
+ samsung,pins = "gpp6-2", "gpp6-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c18_bus: hsi2c18-bus-pins {
+ samsung,pins = "gpp6-4", "gpp6-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c19_bus: hsi2c19-bus-pins {
+ samsung,pins = "gpp6-6", "gpp6-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c20_bus: hsi2c20-bus-pins {
+ samsung,pins = "gpp7-0", "gpp7-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c21_bus: hsi2c21-bus-pins {
+ samsung,pins = "gpp7-2", "gpp7-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c22_bus: hsi2c22-bus-pins {
+ samsung,pins = "gpp7-4", "gpp7-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c23_bus: hsi2c23-bus-pins {
+ samsung,pins = "gpp7-6", "gpp7-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c24_bus: hsi2c24-bus-pins {
+ samsung,pins = "gpp8-0", "gpp8-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c25_bus: hsi2c25-bus-pins {
+ samsung,pins = "gpp8-2", "gpp8-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c32_bus: hsi2c32-bus-pins {
+ samsung,pins = "gpp8-4", "gpp8-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c33_bus: hsi2c33-bus-pins {
+ samsung,pins = "gpp8-6", "gpp8-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c34_bus: hsi2c34-bus-pins {
+ samsung,pins = "gpp9-0", "gpp9-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c35_bus: hsi2c35-bus-pins {
+ samsung,pins = "gpp9-2", "gpp9-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c36_bus: hsi2c36-bus-pins {
+ samsung,pins = "gpp9-4", "gpp9-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ hsi2c37_bus: hsi2c37-bus-pins {
+ samsung,pins = "gpp9-6", "gpp9-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk0_out: sensor-mclk0-out-pins {
+ samsung,pins = "gpc0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk1_out: sensor-mclk1-out-pins {
+ samsung,pins = "gpg1-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk2_out: sensor-mclk2-out-pins {
+ samsung,pins = "gpc0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk3_out: sensor-mclk3-out-pins {
+ samsung,pins = "gpc0-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk4_out: sensor-mclk4-out-pins {
+ samsung,pins = "gpc0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk5_out: sensor-mclk5-out-pins {
+ samsung,pins = "gpg1-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk0_fn: sensor-mclk0-fn-pins {
+ samsung,pins = "gpc0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk1_fn: sensor-mclk1-fn-pins {
+ samsung,pins = "gpg1-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk2_fn: sensor-mclk2-fn-pins {
+ samsung,pins = "gpc0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk3_fn: sensor-mclk3-fn-pins {
+ samsung,pins = "gpc0-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk4_fn: sensor-mclk4-fn-pins {
+ samsung,pins = "gpc0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ sensor_mclk5_fn: sensor-mclk5-fn-pins {
+ samsung,pins = "gpg1-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi6_bus: spi6-bus-pins {
+ samsung,pins = "gpp5-2", "gpp5-1", "gpp5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi6_cs: spi6-cs-pins {
+ samsung,pins = "gpp5-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi6_cs_func: spi6-cs-func-pins {
+ samsung,pins = "gpp5-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi7_bus: spi7-bus-pins {
+ samsung,pins = "gpp5-6", "gpp5-5", "gpp5-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi7_cs: spi7-cs-pins {
+ samsung,pins = "gpp5-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi7_cs_func: spi7-cs-func-pins {
+ samsung,pins = "gpp5-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi8_bus: spi8-bus-pins {
+ samsung,pins = "gpp6-2", "gpp6-1", "gpp6-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi8_cs: spi8-cs-pins {
+ samsung,pins = "gpp6-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi8_cs_func: spi8-cs-func-pins {
+ samsung,pins = "gpp6-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi9_bus: spi9-bus-pins {
+ samsung,pins = "gpp6-6", "gpp6-5", "gpp6-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi9_cs: spi9-cs-pins {
+ samsung,pins = "gpp6-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi9_cs_func: spi9-cs-func-pins {
+ samsung,pins = "gpp6-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi10_bus: spi10-bus-pins {
+ samsung,pins = "gpp7-2", "gpp7-1", "gpp7-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi10_cs: spi10-cs-pins {
+ samsung,pins = "gpp7-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi10_cs_func: spi10-cs-func-pins {
+ samsung,pins = "gpp7-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi11_bus: spi11-bus-pins {
+ samsung,pins = "gpp7-6", "gpp7-5", "gpp7-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi11_cs: spi11-cs-pins {
+ samsung,pins = "gpp7-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi11_cs_func: spi11-cs-func-pins {
+ samsung,pins = "gpp7-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi12_bus: spi12-bus-pins {
+ samsung,pins = "gpp8-2", "gpp8-1", "gpp8-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi12_cs: spi12-cs-pins {
+ samsung,pins = "gpp8-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi12_cs_func: spi12-cs-func-pins {
+ samsung,pins = "gpp8-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi16_bus: spi16-bus-pins {
+ samsung,pins = "gpp8-6", "gpp8-5", "gpp8-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ spi16_cs: spi16-cs-pins {
+ samsung,pins = "gpp8-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi16_cs_func: spi16-cs-func-pins {
+ samsung,pins = "gpp8-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_PREV>;
+ samsung,pin-pud-pdn = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ spi17_bus: spi17-bus-pins {
+ samsung,pins = "gpp9-2", "gpp9-1", "gpp9-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi17_cs: spi17-cs-pins {
+ samsung,pins = "gpp9-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi17_cs_func: spi17-cs-func-pins {
+ samsung,pins = "gpp9-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi18_bus: spi18-bus-pins {
+ samsung,pins = "gpp9-6", "gpp9-5", "gpp9-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi18_cs: spi18-cs-pins {
+ samsung,pins = "gpp9-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ spi18_cs_func: spi18-cs-func-pins {
+ samsung,pins = "gpp9-7";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+ };
+
+ uart8_bus_single: uart8-bus-pins {
+ samsung,pins = "gpp5-3", "gpp5-2", "gpp5-1", "gpp5-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart8_bus_dual: uart8-bus-dual-pins {
+ samsung,pins = "gpp5-0", "gpp5-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart9_bus_single: uart9-bus-pins {
+ samsung,pins = "gpp5-7", "gpp5-6", "gpp5-5", "gpp5-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart9_bus_dual: uart9-bus-dual-pins {
+ samsung,pins = "gpp5-4", "gpp5-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart10_bus_single: uart10-bus-pins {
+ samsung,pins = "gpp6-3", "gpp6-2", "gpp6-1", "gpp6-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart10_bus_dual: uart10-bus-dual-pins {
+ samsung,pins = "gpp6-0", "gpp6-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart11_bus_single: uart11-bus-pins {
+ samsung,pins = "gpp6-7", "gpp6-6", "gpp6-5", "gpp6-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart11_bus_dual: uart11-bus-dual-pins {
+ samsung,pins = "gpp6-4", "gpp6-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart12_bus_single: uart12-bus-pins {
+ samsung,pins = "gpp7-3", "gpp7-2", "gpp7-1", "gpp7-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart12_bus_dual: uart12-bus-dual-pins {
+ samsung,pins = "gpp7-0", "gpp7-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart13_bus_single: uart13-bus-pins {
+ samsung,pins = "gpp7-7", "gpp7-6", "gpp7-5", "gpp7-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart13_bus_dual: uart13-bus-dual-pins {
+ samsung,pins = "gpp7-4", "gpp7-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart14_bus_single: uart14-bus-pins {
+ samsung,pins = "gpp8-3", "gpp8-2", "gpp8-1", "gpp8-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart14_bus_dual: uart14-bus-dual-pins {
+ samsung,pins = "gpp8-0", "gpp8-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart18_bus_single: uart18-bus-pins {
+ samsung,pins = "gpp8-7", "gpp8-6", "gpp8-5", "gpp8-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart18_bus_dual: uart18-bus-dual-pins {
+ samsung,pins = "gpp8-4", "gpp8-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart19_bus_single: uart19-bus-pins {
+ samsung,pins = "gpp9-3", "gpp9-2", "gpp9-1", "gpp9-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart19_bus_dual: uart19-bus-dual-pins {
+ samsung,pins = "gpp9-0", "gpp9-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart20_bus_single: uart20-bus-pins {
+ samsung,pins = "gpp9-7", "gpp9-6", "gpp9-5", "gpp9-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+
+ uart20_bus_dual: uart20-bus-dual-pins {
+ samsung,pins = "gpp9-4", "gpp9-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ };
+};
+
+&pinctrl_vts {
+ gpv0: gpv0-gpio-bank {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ amic_pdm: amic-pdm-pins {
+ samsung,pins = "gpv0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_bus_clk: dmic-bus-clk-pins {
+ samsung,pins = "gpv0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_bus_clk_idle: dmic-bus-clk-idle-pins {
+ samsung,pins = "gpv0-0";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_bus_clk1: dmic-bus-clk1-pins {
+ samsung,pins = "gpv0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_bus_clk1_idle: dmic-bus-clk1-idle-pins {
+ samsung,pins = "gpv0-1";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_bus_clk2: dmic-bus-clk2-pins {
+ samsung,pins = "gpv0-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_bus_clk2_idle: dmic-bus-clk2-idle-pins {
+ samsung,pins = "gpv0-2";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_pdm: dmic-pdm-pins {
+ samsung,pins = "gpv0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_pdm_idle: dmic-pdm-idle-pins {
+ samsung,pins = "gpv0-3";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_pdm1_bus: dmic-pdm1-bus-pins {
+ samsung,pins = "gpv0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_pdm1_idle: dmic-pdm1-idle-pins {
+ samsung,pins = "gpv0-4";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_pdm2_bus: dmic-pdm2-bus-pins {
+ samsung,pins = "gpv0-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+
+ dmic_pdm2_idle: dmic-pdm2-idle-pins {
+ samsung,pins = "gpv0-5";
+ samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-con-pdn = <EXYNOS_PIN_PDN_INPUT>;
+ };
+};
diff --git a/arch/arm64/boot/dts/exynos/exynos990.dtsi b/arch/arm64/boot/dts/exynos/exynos990.dtsi
new file mode 100644
index 000000000000..c1986f00e443
--- /dev/null
+++ b/arch/arm64/boot/dts/exynos/exynos990.dtsi
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Samsung Exynos 990 SoC device tree source
+ *
+ * Copyright (c) 2024, Igor Belwon <igor.belwon@mentallysanemainliners.org>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "samsung,exynos990";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&gic>;
+
+ aliases {
+ pinctrl0 = &pinctrl_alive;
+ pinctrl1 = &pinctrl_cmgp;
+ pinctrl2 = &pinctrl_hsi1;
+ pinctrl3 = &pinctrl_hsi2;
+ pinctrl4 = &pinctrl_peric0;
+ pinctrl5 = &pinctrl_peric1;
+ pinctrl6 = &pinctrl_vts;
+ };
+
+ arm-a55-pmu {
+ compatible = "arm,cortex-a55-pmu";
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-affinity = <&cpu0>,
+ <&cpu1>,
+ <&cpu2>,
+ <&cpu3>;
+ };
+
+ arm-a76-pmu {
+ compatible = "arm,cortex-a76-pmu";
+ interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-affinity = <&cpu4>,
+ <&cpu5>;
+ };
+
+ /* There's no PMU model for cluster2, which are the Mongoose cores. */
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+
+ core2 {
+ cpu = <&cpu2>;
+ };
+
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu4>;
+ };
+
+ core1 {
+ cpu = <&cpu5>;
+ };
+ };
+
+ cluster2 {
+ core0 {
+ cpu = <&cpu6>;
+ };
+
+ core1 {
+ cpu = <&cpu7>;
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0>;
+ enable-method = "psci";
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x1>;
+ enable-method = "psci";
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x2>;
+ enable-method = "psci";
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x3>;
+ enable-method = "psci";
+ };
+
+ cpu4: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x4>;
+ enable-method = "psci";
+ };
+
+ cpu5: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x5>;
+ enable-method = "psci";
+ };
+
+ cpu6: cpu@200 {
+ device_type = "cpu";
+ compatible = "samsung,mongoose-m5";
+ reg = <0x6>;
+ enable-method = "psci";
+ };
+
+ cpu7: cpu@201 {
+ device_type = "cpu";
+ compatible = "samsung,mongoose-m5";
+ reg = <0x7>;
+ enable-method = "psci";
+ };
+ };
+
+ oscclk: clock-osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "oscclk";
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "hvc";
+ };
+
+ soc: soc@0 {
+ compatible = "simple-bus";
+ ranges = <0x0 0x0 0x0 0x20000000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ chipid@10000000 {
+ compatible = "samsung,exynos990-chipid",
+ "samsung,exynos850-chipid";
+ reg = <0x10000000 0x100>;
+ };
+
+ gic: interrupt-controller@10101000 {
+ compatible = "arm,gic-400";
+ reg = <0x10101000 0x1000>,
+ <0x10102000 0x1000>,
+ <0x10104000 0x2000>,
+ <0x10106000 0x2000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) |
+ IRQ_TYPE_LEVEL_HIGH)>;
+ #address-cells = <0>;
+ #size-cells = <1>;
+ };
+
+ pinctrl_peric0: pinctrl@10430000 {
+ compatible = "samsung,exynos990-pinctrl";
+ reg = <0x10430000 0x1000>;
+ interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_peric1: pinctrl@10730000 {
+ compatible = "samsung,exynos990-pinctrl";
+ reg = <0x10730000 0x1000>;
+ interrupts = <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_hsi1: pinctrl@13040000 {
+ compatible = "samsung,exynos990-pinctrl";
+ reg = <0x13040000 0x1000>;
+ interrupts = <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_hsi2: pinctrl@13c30000 {
+ compatible = "samsung,exynos990-pinctrl";
+ reg = <0x13c30000 0x1000>;
+ interrupts = <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pinctrl_vts: pinctrl@15580000 {
+ compatible = "samsung,exynos990-pinctrl";
+ reg = <0x15580000 0x1000>;
+ };
+
+ pinctrl_alive: pinctrl@15850000 {
+ compatible = "samsung,exynos990-pinctrl";
+ reg = <0x15850000 0x1000>;
+
+ wakeup-interrupt-controller {
+ compatible = "samsung,exynos990-wakeup-eint",
+ "samsung,exynos850-wakeup-eint",
+ "samsung,exynos7-wakeup-eint";
+ };
+ };
+
+ pinctrl_cmgp: pinctrl@15c30000 {
+ compatible = "samsung,exynos990-pinctrl";
+ reg = <0x15c30000 0x1000>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+
+ /*
+ * Non-updatable, broken stock Samsung bootloader does not
+ * configure CNTFRQ_EL0
+ */
+ clock-frequency = <26000000>;
+ };
+};
+
+#include "exynos990-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
index 91882b37fdb3..c759134c909e 100644
--- a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi
@@ -172,6 +172,17 @@
reg = <0x10000000 0x24>;
};
+ cmu_misc: clock-controller@10020000 {
+ compatible = "samsung,exynosautov920-cmu-misc";
+ reg = <0x10020000 0x8000>;
+ #clock-cells = <1>;
+
+ clocks = <&xtcxo>,
+ <&cmu_top DOUT_CLKCMU_MISC_NOC>;
+ clock-names = "oscclk",
+ "noc";
+ };
+
gic: interrupt-controller@10400000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
@@ -247,6 +258,19 @@
status = "disabled";
};
+ cmu_peric1: clock-controller@10c00000 {
+ compatible = "samsung,exynosautov920-cmu-peric1";
+ reg = <0x10c00000 0x8000>;
+ #clock-cells = <1>;
+
+ clocks = <&xtcxo>,
+ <&cmu_top DOUT_CLKCMU_PERIC1_NOC>,
+ <&cmu_top DOUT_CLKCMU_PERIC1_IP>;
+ clock-names = "oscclk",
+ "noc",
+ "ip";
+ };
+
syscon_peric1: syscon@10c20000 {
compatible = "samsung,exynosautov920-peric1-sysreg",
"syscon";
@@ -283,12 +307,38 @@
reg = <0x11860000 0x10000>;
};
+ cmu_hsi0: clock-controller@16000000 {
+ compatible = "samsung,exynosautov920-cmu-hsi0";
+ reg = <0x16000000 0x8000>;
+ #clock-cells = <1>;
+
+ clocks = <&xtcxo>,
+ <&cmu_top DOUT_CLKCMU_HSI0_NOC>;
+ clock-names = "oscclk",
+ "noc";
+ };
+
pinctrl_hsi0: pinctrl@16040000 {
compatible = "samsung,exynosautov920-pinctrl";
reg = <0x16040000 0x10000>;
interrupts = <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>;
};
+ cmu_hsi1: clock-controller@16400000 {
+ compatible = "samsung,exynosautov920-cmu-hsi1";
+ reg = <0x16400000 0x8000>;
+ #clock-cells = <1>;
+
+ clocks = <&xtcxo>,
+ <&cmu_top DOUT_CLKCMU_HSI1_NOC>,
+ <&cmu_top DOUT_CLKCMU_HSI1_USBDRD>,
+ <&cmu_top DOUT_CLKCMU_HSI1_MMC_CARD>;
+ clock-names = "oscclk",
+ "noc",
+ "usbdrd",
+ "mmc_card";
+ };
+
pinctrl_hsi1: pinctrl@16450000 {
compatible = "samsung,exynosautov920-pinctrl";
reg = <0x16450000 0x10000>;
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 9d3df8b218a2..42e6482a31cb 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -136,10 +136,12 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7903.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7904.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-dahlia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-dev.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-ivy.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-mallow.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-yavia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-dahlia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-dev.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-ivy.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-mallow.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-wifi-yavia.dtb
@@ -167,12 +169,22 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-beacon-kit.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-debix-model-a.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-debix-som-a-bmb-08.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-dhcom-drc02.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-dhcom-pdk2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-dhcom-pdk3.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-dhcom-picoitx.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-icore-mx8mp-edimm2.2.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-iota2-lumpy.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-kontron-bl-osm-s.dtb
+
+imx8mp-kontron-dl-dtbs += imx8mp-kontron-bl-osm-s.dtb imx8mp-kontron-dl.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-kontron-dl.dtb
+
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-kontron-smarc-eval-carrier.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-msc-sm2s-ep1.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-navqp.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-nitrogen-smarc-universal-board.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk.dtb
imx8mp-phyboard-pollux-rdk-no-eth-dtbs += imx8mp-phyboard-pollux-rdk.dtb imx8mp-phycore-no-eth.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk-no-eth.dtb
@@ -187,17 +199,22 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw72xx-2x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw73xx-2x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw74xx.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw75xx-2x.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw82xx-2x.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-dahlia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-dev.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-ivy.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-mallow.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-yavia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-wifi-dahlia.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-wifi-dev.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-wifi-ivy.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-wifi-mallow.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-wifi-yavia.dtb
imx8mp-evk-mx8-dlvds-lcd1-dtbs += imx8mp-evk.dtb imx8mp-evk-mx8-dlvds-lcd1.dtbo
+imx8mp-evk-pcie-ep-dtbs += imx8mp-evk.dtb imx8mp-evk-pcie-ep.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-mx8-dlvds-lcd1.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-pcie-ep.dtb
imx8mp-tqma8mpql-mba8mpxl-lvds-dtbs += imx8mp-tqma8mpql-mba8mpxl.dtb imx8mp-tqma8mpql-mba8mpxl-lvds.dtbo
imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01-dtbs += imx8mp-tqma8mpql-mba8mpxl.dtb imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01.dtbo
@@ -240,6 +257,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qxp-tqma8xqp-mba8xx.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8ulp-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-9x9-qsb.dtb
+
+imx93-9x9-qsb-i3c-dtbs += imx93-9x9-qsb.dtb imx93-9x9-qsb-i3c.dtbo
+dtb-$(CONFIG_ARCH_MXC) += imx93-9x9-qsb-i3c.dtb
+
dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-kontron-bl-osm-s.dtb
@@ -249,6 +270,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb
dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
+imx8mm-kontron-dl-dtbs := imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo
+
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-dl.dtb
+
imx8mm-venice-gw72xx-0x-imx219-dtbs := imx8mm-venice-gw72xx-0x.dtb imx8mm-venice-gw72xx-0x-imx219.dtbo
imx8mm-venice-gw72xx-0x-rpidsi-dtbs := imx8mm-venice-gw72xx-0x.dtb imx8mm-venice-gw72xx-0x-rpidsi.dtbo
imx8mm-venice-gw72xx-0x-rs232-rts-dtbs := imx8mm-venice-gw72xx-0x.dtb imx8mm-venice-gw72xx-0x-rs232-rts.dtbo
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
index bbdf989058ff..ce59b94d8c22 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
@@ -87,7 +87,7 @@
flash@2 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "en25s64", "jedec,spi-nor";
+ compatible = "jedec,spi-nor";
spi-cpol;
spi-cpha;
reg = <2>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts
index d9fac647f432..1d53b529af88 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts
@@ -19,8 +19,6 @@
pwm-fan {
compatible = "pwm-fan";
- cooling-min-state = <0>;
- cooling-max-state = <3>;
#cooling-cells = <2>;
pwms = <&sl28cpld_pwm0 0 4000000>;
cooling-levels = <1 128 192 255>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
index a1d9102ff32b..736722b58e77 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
@@ -69,7 +69,7 @@
flash@2 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "en25s64", "jedec,spi-nor";
+ compatible = "jedec,spi-nor";
spi-cpol;
spi-cpha;
reg = <2>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
index d32a52ab00a4..e4b727070814 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
@@ -94,9 +94,6 @@
fan-temperature-ctrlr@18 {
compatible = "ti,amc6821";
reg = <0x18>;
- cooling-min-state = <0>;
- cooling-max-state = <9>;
- #cooling-cells = <2>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
new file mode 100644
index 000000000000..f54005e37924
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Device Tree file for LX2160 REV2
+//
+// Copyright 2025 NXP
+
+/dts-v1/;
+
+#include "fsl-lx2160a.dtsi"
+
+&pcie1 {
+ compatible = "fsl,lx2160ar2-pcie", "fsl,ls2088a-pcie";
+ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
+ 0x80 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+
+ ranges = <0x81000000 0x0 0x00000000 0x80 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>;
+
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+
+ /delete-property/ apio-wins;
+ /delete-property/ ppio-wins;
+};
+
+&pcie2 {
+ compatible = "fsl,lx2160ar2-pcie", "fsl,ls2088a-pcie";
+ reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */
+ 0x88 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+
+ ranges = <0x81000000 0x0 0x00000000 0x88 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>;
+
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+
+ /delete-property/ apio-wins;
+ /delete-property/ ppio-wins;
+};
+
+&pcie3 {
+ compatible = "fsl,lx2160ar2-pcie", "fsl,ls2088a-pcie";
+ reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */
+ 0x90 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+
+ ranges = <0x81000000 0x0 0x00000000 0x90 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>;
+
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+
+ /delete-property/ apio-wins;
+ /delete-property/ ppio-wins;
+};
+
+
+&pcie4 {
+ compatible = "fsl,lx2160ar2-pcie", "fsl,ls2088a-pcie";
+ reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */
+ 0x98 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+
+ ranges = <0x81000000 0x0 0x00000000 0x98 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>;
+
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+
+ /delete-property/ apio-wins;
+ /delete-property/ ppio-wins;
+};
+
+&pcie5 {
+ compatible = "fsl,lx2160ar2-pcie", "fsl,ls2088a-pcie";
+ reg = <0x00 0x03800000 0x0 0x00100000 /* controller registers */
+ 0xa0 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+
+ ranges = <0x81000000 0x0 0x00000000 0xa0 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>;
+
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+
+ /delete-property/ apio-wins;
+ /delete-property/ ppio-wins;
+};
+
+&pcie6 {
+ compatible = "fsl,lx2160ar2-pcie", "fsl,ls2088a-pcie";
+ reg = <0x00 0x03900000 0x0 0x00100000 /* controller registers */
+ 0xa8 0x00000000 0x0 0x00002000>; /* configuration space */
+ reg-names = "regs", "config";
+
+ ranges = <0x81000000 0x0 0x00000000 0xa8 0x00010000 0x0 0x00010000
+ 0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>;
+
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+
+ /delete-property/ apio-wins;
+ /delete-property/ ppio-wins;
+};
+
+&soc {
+ pcie_ep1: pcie-ep@3400000 {
+ compatible = "fsl,lx2160ar2-pcie-ep";
+ reg = <0x00 0x03400000 0x0 0x00100000
+ 0x80 0x00000000 0x8 0x00000000>;
+ reg-names = "regs", "addr_space";
+ num-ob-windows = <8>;
+ num-ib-windows = <8>;
+ status = "disabled";
+ };
+
+ pcie_ep2: pcie-ep@3500000 {
+ compatible = "fsl,lx2160ar2-pcie-ep";
+ reg = <0x00 0x03500000 0x0 0x00100000
+ 0x88 0x00000000 0x8 0x00000000>;
+ reg-names = "regs", "addr_space";
+ num-ob-windows = <8>;
+ num-ib-windows = <8>;
+ status = "disabled";
+ };
+
+ pcie_ep3: pcie-ep@3600000 {
+ compatible = "fsl,lx2160ar2-pcie-ep";
+ reg = <0x00 0x03600000 0x0 0x00100000
+ 0x90 0x00000000 0x8 0x00000000>;
+ reg-names = "regs", "addr_space";
+ num-ob-windows = <256>;
+ num-ib-windows = <24>;
+ status = "disabled";
+ };
+
+ pcie_ep4: pcie-ep@3700000 {
+ compatible = "fsl,lx2160ar2-pcie-ep";
+ reg = <0x00 0x03700000 0x0 0x00100000
+ 0x98 0x00000000 0x8 0x00000000>;
+ reg-names = "regs", "addr_space";
+ num-ob-windows = <8>;
+ num-ib-windows = <8>;
+ status = "disabled";
+ };
+
+
+ pcie_ep5: pcie-ep@3800000 {
+ compatible = "fsl,lx2160ar2-pcie-ep";
+ reg = <0x00 0x03800000 0x0 0x00100000
+ 0xa0 0x00000000 0x8 0x00000000>;
+ reg-names = "regs", "addr_space";
+ num-ob-windows = <256>;
+ num-ib-windows = <24>;
+ status = "disabled";
+ };
+
+ pcie_ep6: pcie-ep@3900000 {
+ compatible = "fsl,lx2160ar2-pcie-ep";
+ reg = <0x00 0x03900000 0x0 0x00100000
+ 0xa8 0x00000000 0x8 0x00000000>;
+ reg-names = "regs", "addr_space";
+ num-ob-windows = <8>;
+ num-ib-windows = <8>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index 927ecf66a740..c9541403bcd8 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -614,7 +614,7 @@
};
};
- soc {
+ soc: soc {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-eval-v1.2.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-eval-v1.2.dtsi
index f5c6a0164f36..5862b24fb764 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-eval-v1.2.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-eval-v1.2.dtsi
@@ -51,6 +51,40 @@
regulator-name = "5V_SW_CAN2";
startup-delay-us = <10000>;
};
+
+ sound-carrier {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&codec_dai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&codec_dai>;
+ simple-audio-card,name = "apalis-nau8822";
+ simple-audio-card,routing =
+ "Headphones", "LHP",
+ "Headphones", "RHP",
+ "Speaker", "LSPK",
+ "Speaker", "RSPK",
+ "Line Out", "AUXOUT1",
+ "Line Out", "AUXOUT2",
+ "LAUX", "Line In",
+ "RAUX", "Line In",
+ "LMICP", "Mic In",
+ "RMICP", "Mic In";
+ simple-audio-card,widgets =
+ "Headphones", "Headphones",
+ "Line Out", "Line Out",
+ "Speaker", "Speaker",
+ "Microphone", "Mic In",
+ "Line", "Line In";
+
+ codec_dai: simple-audio-card,codec {
+ sound-dai = <&nau8822_1a>;
+ system-clock-frequency = <12288000>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai0>;
+ };
+ };
};
/* Apalis CAN1 */
@@ -69,6 +103,13 @@
&i2c2 {
status = "okay";
+ /* Audio Codec */
+ nau8822_1a: audio-codec@1a {
+ compatible = "nuvoton,nau8822";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ };
+
/* Power/Current Measurement Sensor */
hwmon@40 {
compatible = "ti,ina219";
@@ -87,6 +128,18 @@
};
};
+&sai0 {
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&sai0_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai0>;
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
+
/* Apalis MMC1 */
&usdhc2 {
pinctrl-0 = <&pinctrl_usdhc2_4bit>, <&pinctrl_mmc1_cd>;
@@ -105,6 +158,15 @@
};
&iomuxc {
+ pinctrl-0 = <&pinctrl_cam1_gpios>,
+ <&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
+ <&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio_keys>,
+ <&pinctrl_gpio_usbh_oc_n>, <&pinctrl_lpuart1ctrl>,
+ <&pinctrl_lvds0_i2c0_gpio>, <&pinctrl_lvds1_i2c0_gpios>,
+ <&pinctrl_mipi_dsi_0_1_en>, <&pinctrl_mipi_dsi1_gpios>,
+ <&pinctrl_mlb_gpios>, <&pinctrl_qspi1a_gpios>,
+ <&pinctrl_sata1_act>, <&pinctrl_sim0_gpios>,
+ <&pinctrl_usdhc1_gpios>;
pinctrl_enable_3v3_mmc: enable3v3mmcgrp {
fsl,pins = <IMX8QM_USDHC1_DATA4_LSIO_GPIO5_IO19 0x00000021>; /* MXM3_148 */
@@ -121,4 +183,11 @@
pinctrl_enable_can2_power: enablecan2powergrp {
fsl,pins = <IMX8QM_USDHC1_DATA6_LSIO_GPIO5_IO21 0x00000021>; /* MXM3_156 */
};
+
+ pinctrl_sai0: sai0grp {
+ fsl,pins = <IMX8QM_SAI1_RXC_AUD_SAI0_TXD 0xc600006c>, /* MXM3_196 */
+ <IMX8QM_SPI0_CS1_AUD_SAI0_TXC 0xc600004c>, /* MXM3_200 */
+ <IMX8QM_SAI1_RXFS_AUD_SAI0_RXD 0xc600004c>, /* MXM3_202 */
+ <IMX8QM_SPI2_CS1_AUD_SAI0_TXFS 0xc600004c>; /* MXM3_204 */
+ };
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi
index deecb96a1596..dc127298715b 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi
@@ -22,9 +22,13 @@
status = "okay";
};
-/* TODO: Audio Mixer */
+&amix {
+ status = "okay";
+};
-/* TODO: Asynchronous Sample Rate Converter (ASRC) */
+&asrc0 {
+ status = "okay";
+};
/* TODO: Display Controller */
@@ -104,13 +108,25 @@
/* TODO: Apalis BKL1_PWM */
-/* TODO: Apalis DAP1 */
+/* Apalis DAP1 */
+&sai1 {
+ status = "okay";
+};
-/* TODO: Apalis Analogue Audio */
+&sai5 {
+ status = "okay";
+};
+
+&sai5_lpcg {
+ status = "okay";
+};
/* TODO: Apalis SATA1 */
-/* TODO: Apalis SPDIF1 */
+/* Apalis SPDIF1 */
+&spdif0 {
+ status = "okay";
+};
/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */
@@ -119,4 +135,7 @@
status = "okay";
};
-/* TODO: Apalis USBH4 SuperSpeed */
+/* Apalis USBH4 SuperSpeed */
+&usbotg3_cdns3 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
index 5438923a905c..d4a1ad528f65 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi
@@ -62,9 +62,13 @@
status = "okay";
};
-/* TODO: Audio Mixer */
+&amix {
+ status = "okay";
+};
-/* TODO: Asynchronous Sample Rate Converter (ASRC) */
+&asrc0 {
+ status = "okay";
+};
/* TODO: Display Controller */
@@ -191,13 +195,25 @@
/* TODO: Apalis BKL1_PWM */
-/* TODO: Apalis DAP1 */
+/* Apalis DAP1 */
+&sai1 {
+ status = "okay";
+};
-/* TODO: Apalis Analogue Audio */
+&sai5 {
+ status = "okay";
+};
+
+&sai5_lpcg {
+ status = "okay";
+};
/* TODO: Apalis SATA1 */
-/* TODO: Apalis SPDIF1 */
+/* Apalis SPDIF1 */
+&spdif0 {
+ status = "okay";
+};
/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */
@@ -206,7 +222,10 @@
status = "okay";
};
-/* TODO: Apalis USBH4 SuperSpeed */
+/* Apalis USBH4 SuperSpeed */
+&usbotg3_cdns3 {
+ status = "okay";
+};
/* Apalis MMC1 */
&usdhc2 {
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi
index f6654fdcb147..5e132c83e1b2 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi
@@ -94,9 +94,13 @@
status = "okay";
};
-/* TODO: Audio Mixer */
+&amix {
+ status = "okay";
+};
-/* TODO: Asynchronous Sample Rate Converter (ASRC) */
+&asrc0 {
+ status = "okay";
+};
/* TODO: Display Controller */
@@ -240,13 +244,25 @@
/* TODO: Apalis BKL1_PWM */
-/* TODO: Apalis DAP1 */
+/* Apalis DAP1 */
+&sai1 {
+ status = "okay";
+};
-/* TODO: Apalis Analogue Audio */
+&sai5 {
+ status = "okay";
+};
+
+&sai5_lpcg {
+ status = "okay";
+};
/* TODO: Apalis SATA1 */
-/* TODO: Apalis SPDIF1 */
+/* Apalis SPDIF1 */
+&spdif0 {
+ status = "okay";
+};
/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */
@@ -255,7 +271,10 @@
status = "okay";
};
-/* TODO: Apalis USBH4 SuperSpeed */
+/* Apalis USBH4 SuperSpeed */
+&usbotg3_cdns3 {
+ status = "okay";
+};
/* Apalis MMC1 */
&usdhc2 {
diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
index 160153853b68..a3fc945aea16 100644
--- a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi
@@ -126,6 +126,13 @@
regulator-name = "usb-phy-dummy";
};
+ reg_vref_1v8: regulator-vref-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "+V1.8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
@@ -198,11 +205,32 @@
};
};
- /* TODO: Apalis Analogue Audio */
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,name = "apalis-imx8qm";
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai1>;
+ };
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&sgtl5000>;
+ };
+ };
/* TODO: HDMI Audio */
- /* TODO: Apalis SPDIF1 */
+ /* Apalis SPDIF1 */
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif0>;
+ spdif-in;
+ spdif-out;
+ };
touchscreen: touchscreen {
compatible = "toradex,vf50-touchscreen";
@@ -227,6 +255,10 @@
};
+&asrc0 {
+ fsl,asrc-rate = <48000>;
+};
+
&adc0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_adc0>;
@@ -239,6 +271,30 @@
/* TODO: Asynchronous Sample Rate Converter (ASRC) */
+&cpu_alert0 {
+ temperature = <95000>;
+};
+
+&cpu_alert1 {
+ temperature = <95000>;
+};
+
+&cpu_crit0 {
+ temperature = <105000>;
+};
+
+&cpu_crit1 {
+ temperature = <105000>;
+};
+
+&drc_alert0 {
+ temperature = <95000>;
+};
+
+&drc_crit0 {
+ temperature = <105000>;
+};
+
/* Apalis ETH1 */
&fec1 {
pinctrl-names = "default", "sleep";
@@ -285,6 +341,22 @@
/* TODO: Apalis HDMI1 */
+&gpu_alert0 {
+ temperature = <95000>;
+};
+
+&gpu_alert1 {
+ temperature = <95000>;
+};
+
+&gpu_crit0 {
+ temperature = <105000>;
+};
+
+&gpu_crit1 {
+ temperature = <105000>;
+};
+
/* On-module I2C */
&i2c1 {
pinctrl-names = "default";
@@ -294,8 +366,6 @@
clock-frequency = <100000>;
status = "okay";
- /* TODO: Audio Codec */
-
/* USB3503A */
usb-hub@8 {
compatible = "smsc,usb3503a";
@@ -308,6 +378,24 @@
refclk-frequency = <25000000>;
reset-gpios = <&lsio_gpio1 2 GPIO_ACTIVE_LOW>;
};
+
+ /* On Module Audio Codec */
+ sgtl5000: audio-codec@a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&mclkout0_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <12288000>;
+ clocks = <&mclkout0_lpcg IMX_LPCG_CLK_0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sgtl5000>;
+ #sound-dai-cells = <0>;
+ VDDA-supply = <&reg_module_3v3_avdd>;
+ VDDD-supply = <&reg_vref_1v8>;
+ VDDIO-supply = <&reg_module_3v3>;
+ };
};
/* Apalis I2C1 */
@@ -689,19 +777,48 @@
/* TODO: Apalis BKL1_PWM */
-/* TODO: Apalis DAP1 */
-
-/* TODO: Analogue Audio */
+/* Apalis DAP1 */
+&sai1 {
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&sai1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
/* TODO: Apalis SATA1 */
-/* TODO: Apalis SPDIF1 */
+/* Apalis SPDIF1 */
+&spdif0 {
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif0>;
+ status = "okay";
+};
/* TODO: Thermal Zones */
/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */
-/* TODO: Apalis USBH4 */
+/* Apalis USBH4 */
+&usb3_phy {
+ status = "okay";
+};
+
+&usbotg3 {
+ status = "okay";
+};
+
+&usbotg3_cdns3 {
+ dr_mode = "host";
+};
/* Apalis USBO1 */
&usbphy1 {
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
index ff5df0fed9e9..a60ebb718789 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi
@@ -431,22 +431,19 @@ audio_subsys: bus@59000000 {
};
dsp: dsp@596e8000 {
- compatible = "fsl,imx8qxp-dsp";
+ compatible = "fsl,imx8qxp-hifi4";
reg = <0x596e8000 0x88000>;
clocks = <&dsp_lpcg IMX_LPCG_CLK_5>,
<&dsp_ram_lpcg IMX_LPCG_CLK_4>,
<&dsp_lpcg IMX_LPCG_CLK_7>;
clock-names = "ipg", "ocram", "core";
- power-domains = <&pd IMX_SC_R_MU_13A>,
- <&pd IMX_SC_R_MU_13B>,
- <&pd IMX_SC_R_DSP>,
- <&pd IMX_SC_R_DSP_RAM>;
- mbox-names = "txdb0", "txdb1",
- "rxdb0", "rxdb1";
- mboxes = <&lsio_mu13 2 0>,
- <&lsio_mu13 2 1>,
- <&lsio_mu13 3 0>,
- <&lsio_mu13 3 1>;
+ power-domains = <&pd IMX_SC_R_MU_13B>,
+ <&pd IMX_SC_R_MU_2A>;
+ mbox-names = "tx", "rx", "rxdb";
+ mboxes = <&lsio_mu13 0 0>,
+ <&lsio_mu13 1 0>,
+ <&lsio_mu13 3 0>;
+ firmware-name = "imx/dsp/hifi4.bin";
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
index a4a10ce03bfe..ce6ef160fd55 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
@@ -350,7 +350,7 @@ conn_subsys: bus@5b000000 {
power-domains = <&pd IMX_SC_R_NAND>;
};
- gpmi: nand-controller@5b812000{
+ gpmi: nand-controller@5b812000 {
compatible = "fsl,imx8qxp-gpmi-nand";
reg = <0x5b812000 0x2000>, <0x5b814000 0x2000>;
reg-names = "gpmi-nand", "bch";
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-hsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-hsio.dtsi
new file mode 100644
index 000000000000..70a8aa1a6791
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-hsio.dtsi
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ *
+ * Richard Zhu <hongxing.zhu@nxp.com>
+ */
+#include <dt-bindings/phy/phy.h>
+
+hsio_axi_clk: clock-hsio-axi {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <400000000>;
+ clock-output-names = "hsio_axi_clk";
+};
+
+hsio_per_clk: clock-hsio-per {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <133333333>;
+ clock-output-names = "hsio_per_clk";
+};
+
+hsio_refa_clk: clock-hsio-refa {
+ compatible = "gpio-gate-clock";
+ clocks = <&xtal100m>;
+ #clock-cells = <0>;
+ enable-gpios = <&lsio_gpio4 27 GPIO_ACTIVE_LOW>;
+};
+
+hsio_refb_clk: clock-hsio-refb {
+ compatible = "gpio-gate-clock";
+ clocks = <&xtal100m>;
+ #clock-cells = <0>;
+ enable-gpios = <&lsio_gpio4 1 GPIO_ACTIVE_LOW>;
+};
+
+xtal100m: clock-xtal100m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ clock-output-names = "xtal_100MHz";
+};
+
+hsio_subsys: bus@5f000000 {
+ compatible = "simple-bus";
+ ranges = <0x5f000000 0x0 0x5f000000 0x01000000>,
+ <0x80000000 0x0 0x70000000 0x10000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ dma-ranges = <0x80000000 0 0x80000000 0x80000000>;
+
+ pcieb: pcie@5f010000 {
+ compatible = "fsl,imx8q-pcie";
+ reg = <0x5f010000 0x10000>,
+ <0x8ff00000 0x80000>;
+ reg-names = "dbi", "config";
+ ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
+ <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ clocks = <&pcieb_lpcg IMX_LPCG_CLK_6>,
+ <&pcieb_lpcg IMX_LPCG_CLK_4>,
+ <&pcieb_lpcg IMX_LPCG_CLK_5>;
+ clock-names = "dbi", "mstr", "slv";
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ interrupt-map = <0 0 0 1 &gic 0 105 4>,
+ <0 0 0 2 &gic 0 106 4>,
+ <0 0 0 3 &gic 0 107 4>,
+ <0 0 0 4 &gic 0 108 4>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ num-lanes = <1>;
+ num-viewport = <4>;
+ power-domains = <&pd IMX_SC_R_PCIE_B>;
+ fsl,max-link-speed = <3>;
+ status = "disabled";
+ };
+
+ pcieb_lpcg: clock-controller@5f060000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f060000 0x10000>;
+ clocks = <&hsio_axi_clk>, <&hsio_axi_clk>, <&hsio_axi_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_5>, <IMX_LPCG_CLK_6>;
+ clock-output-names = "hsio_pcieb_mstr_axi_clk",
+ "hsio_pcieb_slv_axi_clk",
+ "hsio_pcieb_dbi_axi_clk";
+ power-domains = <&pd IMX_SC_R_PCIE_B>;
+ };
+
+ phyx1_crr1_lpcg: clock-controller@5f0b0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f0b0000 0x10000>;
+ clocks = <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_phyx1_per_clk";
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ };
+
+ pcieb_crr3_lpcg: clock-controller@5f0d0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f0d0000 0x10000>;
+ clocks = <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_pcieb_per_clk";
+ power-domains = <&pd IMX_SC_R_PCIE_B>;
+ };
+
+ misc_crr5_lpcg: clock-controller@5f0f0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f0f0000 0x10000>;
+ clocks = <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_misc_per_clk";
+ power-domains = <&pd IMX_SC_R_HSIO_GPIO>;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi
index d00036204a8c..dad0dc8fb431 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi
@@ -14,7 +14,7 @@ lvds0_subsys: bus@56240000 {
compatible = "fsl,imx8qxp-lpcg";
reg = <0x56243000 0x4>;
#clock-cells = <1>;
- clock-output-names = "mipi1_lis_lpcg_ipg_clk";
+ clock-output-names = "lvds0_lis_lpcg_ipg_clk";
power-domains = <&pd IMX_SC_R_MIPI_1>;
};
@@ -22,9 +22,9 @@ lvds0_subsys: bus@56240000 {
compatible = "fsl,imx8qxp-lpcg";
reg = <0x5624300c 0x4>;
#clock-cells = <1>;
- clock-output-names = "mipi1_pwm_lpcg_clk",
- "mipi1_pwm_lpcg_ipg_clk",
- "mipi1_pwm_lpcg_32k_clk";
+ clock-output-names = "lvds0_pwm_lpcg_clk",
+ "lvds0_pwm_lpcg_ipg_clk",
+ "lvds0_pwm_lpcg_32k_clk";
power-domains = <&pd IMX_SC_R_MIPI_1_PWM_0>;
};
@@ -32,8 +32,8 @@ lvds0_subsys: bus@56240000 {
compatible = "fsl,imx8qxp-lpcg";
reg = <0x56243010 0x4>;
#clock-cells = <1>;
- clock-output-names = "mipi1_i2c0_lpcg_clk",
- "mipi1_i2c0_lpcg_ipg_clk";
+ clock-output-names = "lvds0_i2c0_lpcg_clk",
+ "lvds0_i2c0_lpcg_ipg_clk";
power-domains = <&pd IMX_SC_R_MIPI_1_I2C_0>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi
index c6540768bdb9..87211c18d65a 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi
@@ -15,7 +15,7 @@ vpu: vpu@2c000000 {
mu_m0: mailbox@2d000000 {
compatible = "fsl,imx6sx-mu";
reg = <0x2d000000 0x20000>;
- interrupts = <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>;
#mbox-cells = <2>;
power-domains = <&pd IMX_SC_R_VPU_MU_0>;
status = "disabled";
@@ -24,7 +24,7 @@ vpu: vpu@2c000000 {
mu1_m0: mailbox@2d020000 {
compatible = "fsl,imx6sx-mu";
reg = <0x2d020000 0x20000>;
- interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>;
#mbox-cells = <2>;
power-domains = <&pd IMX_SC_R_VPU_MU_1>;
status = "disabled";
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
index 4caaecc19227..6259186cd4d9 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
@@ -182,6 +182,15 @@
regulator-always-on;
};
+ reg_pcieb: regulator-pcieb {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "reg_pcieb";
+ gpio = <&pca6416_1 13 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
bt_sco_codec: audio-codec-bt {
compatible = "linux,bt-sco";
#sound-dai-cells = <1>;
@@ -567,6 +576,12 @@
status = "okay";
};
+&hsio_phy {
+ fsl,hsio-cfg = "pciea-x2-pcieb";
+ fsl,refclk-pad-mode = "output";
+ status = "okay";
+};
+
&cm40_intmux {
status = "disabled";
};
@@ -585,6 +600,16 @@
status = "okay";
};
+&pcieb {
+ phys = <&hsio_phy 0 PHY_TYPE_PCIE 0>;
+ phy-names = "pcie-phy";
+ pinctrl-0 = <&pinctrl_pcieb>;
+ pinctrl-names = "default";
+ reset-gpio = <&lsio_gpio4 0 GPIO_ACTIVE_LOW>;
+ vpcie-supply = <&reg_pcieb>;
+ status = "okay";
+};
+
&sai0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai0>;
@@ -868,6 +893,14 @@
>;
};
+ pinctrl_pcieb: pcieagrp {
+ fsl,pins = <
+ IMX8DXL_PCIE_CTRL0_PERST_B_LSIO_GPIO4_IO00 0x06000021
+ IMX8DXL_PCIE_CTRL0_CLKREQ_B_LSIO_GPIO4_IO01 0x06000021
+ IMX8DXL_PCIE_CTRL0_WAKE_B_LSIO_GPIO4_IO02 0x04000021
+ >;
+ };
+
pinctrl_sai0: sai0grp {
fsl,pins = <
IMX8DXL_SPI0_CS0_ADMA_SAI0_RXD 0x06000060
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
index 1e02b04494e9..9b114bed084b 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
@@ -138,6 +138,10 @@
interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
};
+&usbphy1 {
+ compatible = "fsl,imx8dxl-usbphy", "fsl,imx7ulp-usbphy";
+};
+
&usdhc1 {
compatible = "fsl,imx8dxl-usdhc", "fsl,imx8qxp-usdhc";
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-hsio.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-hsio.dtsi
new file mode 100644
index 000000000000..afbe962d78ce
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-hsio.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ */
+
+&hsio_subsys {
+ phyx1_lpcg: clock-controller@5f090000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f090000 0x10000>;
+ clocks = <&hsio_refb_clk>, <&hsio_per_clk>,
+ <&hsio_per_clk>, <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_1>,
+ <IMX_LPCG_CLK_2>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_phyx1_pclk",
+ "hsio_phyx1_epcs_tx_clk",
+ "hsio_phyx1_epcs_rx_clk",
+ "hsio_phyx1_apb_clk";
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ };
+
+ hsio_phy: phy@5f1a0000 {
+ compatible = "fsl,imx8qxp-hsio";
+ reg = <0x5f1a0000 0x10000>,
+ <0x5f120000 0x10000>,
+ <0x5f140000 0x10000>,
+ <0x5f160000 0x10000>;
+ reg-names = "reg", "phy", "ctrl", "misc";
+ clocks = <&phyx1_lpcg IMX_LPCG_CLK_0>,
+ <&phyx1_lpcg IMX_LPCG_CLK_4>,
+ <&phyx1_crr1_lpcg IMX_LPCG_CLK_4>,
+ <&pcieb_crr3_lpcg IMX_LPCG_CLK_4>,
+ <&misc_crr5_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "pclk0", "apb_pclk0", "phy0_crr", "ctl0_crr",
+ "misc_crr";
+ #phy-cells = <3>;
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ status = "disabled";
+ };
+};
+
+&pcieb {
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ interrupt-map = <0 0 0 1 &gic 0 47 4>,
+ <0 0 0 2 &gic 0 48 4>,
+ <0 0 0 3 &gic 0 49 4>,
+ <0 0 0 4 &gic 0 50 4>;
+ interrupt-map-mask = <0 0 0 0x7>;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
index 7e54cf202858..a71d8b32c192 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
@@ -30,6 +30,10 @@
gpio6 = &lsio_gpio6;
gpio7 = &lsio_gpio7;
mu1 = &lsio_mu1;
+ spi0 = &lpspi0;
+ spi1 = &lpspi1;
+ spi2 = &lpspi2;
+ spi3 = &lpspi3;
};
cpus: cpus {
@@ -237,12 +241,14 @@
#include "imx8-ss-conn.dtsi"
#include "imx8-ss-ddr.dtsi"
#include "imx8-ss-lsio.dtsi"
+ #include "imx8-ss-hsio.dtsi"
};
#include "imx8dxl-ss-adma.dtsi"
#include "imx8dxl-ss-conn.dtsi"
#include "imx8dxl-ss-lsio.dtsi"
#include "imx8dxl-ss-ddr.dtsi"
+#include "imx8dxl-ss-hsio.dtsi"
&cm40_intmux {
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts b/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts
index 7d2cb74c64ee..90e638b8e92a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright 2023 Emtop Embedded Solutions
+ *
+ * Author: Himanshu Bhavani <himanshu.bhavani@siliconsignals.io>
+ * Author: Tarang Raval <tarang.raval@siliconsignals.io>
*/
/dts-v1/;
@@ -11,6 +14,113 @@
model = "Emtop Embedded Solutions i.MX8M Mini Baseboard V1";
compatible = "ees,imx8mm-emtop-baseboard", "ees,imx8mm-emtop-som",
"fsl,imx8mm";
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg>;
+ id-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+
+ port {
+ high_speed_ep: endpoint {
+ remote-endpoint = <&usb_hs_ep>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_led>;
+
+ led-1 {
+ label = "buzzer";
+ gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ osc_can: clock-osc-can {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <16000000>;
+ clock-output-names = "osc-can";
+ };
+
+ reg_audio: regulator-audio {
+ compatible = "regulator-fixed";
+ regulator-name = "wm8904_supply";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ reg_wifi_vmmc: regulator-wifi-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100>;
+ off-on-delay-us = <20000>;
+ };
+
+ sound-wm8904 {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,name = "wm8904-audio";
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN2L", "Line In Jack",
+ "IN2R", "Line In Jack",
+ "Headphone Jack", "MICBIAS",
+ "IN1L", "Headphone Jack";
+
+ simple-audio-card,widgets =
+ "Microphone","Headphone Jack",
+ "Headphone", "Headphone Jack",
+ "Line", "Line In Jack";
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&wm8904>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai3>;
+ };
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif1>;
+ spdif-out;
+ spdif-in;
+ };
+};
+
+/* CAN BUS */
+&ecspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ status = "okay";
+
+ can: can@0 {
+ compatible = "microchip,mcp2515";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_canbus>;
+ clocks = <&osc_can>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <10000000>;
+ };
};
&fec1 {
@@ -40,7 +150,135 @@
};
};
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ wm8904: audio-codec@1a {
+ compatible = "wlf,wm8904";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ clocks = <&clk IMX8MM_CLK_SAI3_ROOT>;
+ clock-names = "mclk";
+ DCVDD-supply = <&reg_audio>;
+ DBVDD-supply = <&reg_audio>;
+ AVDD-supply = <&reg_audio>;
+ CPVDD-supply = <&reg_audio>;
+ MICVDD-supply = <&reg_audio>;
+ };
+
+ rtc@32 {
+ compatible = "epson,rx8025";
+ reg = <0x32>;
+ };
+};
+
+/* AUDIO */
+&sai3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3>;
+ assigned-clocks = <&clk IMX8MM_CLK_SAI3>;
+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <24576000>;
+ status = "okay";
+};
+
+&spdif1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif1>;
+ assigned-clocks = <&clk IMX8MM_CLK_SPDIF1>;
+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <24576000>;
+ clocks = <&clk IMX8MM_CLK_AUDIO_AHB>, <&clk IMX8MM_CLK_24M>,
+ <&clk IMX8MM_CLK_SPDIF1>, <&clk IMX8MM_CLK_DUMMY>,
+ <&clk IMX8MM_CLK_DUMMY>, <&clk IMX8MM_CLK_DUMMY>,
+ <&clk IMX8MM_CLK_AUDIO_AHB>, <&clk IMX8MM_CLK_DUMMY>,
+ <&clk IMX8MM_CLK_DUMMY>, <&clk IMX8MM_CLK_DUMMY>,
+ <&clk IMX8MM_AUDIO_PLL1_OUT>, <&clk IMX8MM_AUDIO_PLL2_OUT>;
+ clock-names = "core", "rxtx0", "rxtx1", "rxtx2", "rxtx3",
+ "rxtx4", "rxtx5", "rxtx6", "rxtx7", "spba", "pll8k", "pll11k";
+ status = "okay";
+};
+
+/* USBOTG */
+&usbotg1 {
+ dr_mode = "otg";
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ usb_hs_ep: endpoint {
+ remote-endpoint = <&high_speed_ep>;
+ };
+ };
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* Wifi */
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>, <&pinctrl_usdhc1_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>, <&pinctrl_usdhc1_gpio>;
+ bus-width = <4>;
+ vmmc-supply = <&reg_wifi_vmmc>;
+ cap-power-off-card;
+ keep-power-in-suspend;
+ non-removable;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ wifi: wifi@1 {
+ compatible = "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "host-wake";
+ };
+};
+
+/* SD-card */
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ bus-width = <4>;
+ status = "okay";
+};
+
&iomuxc {
+
+ pinctrl_canbus: canbusgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14 0x14
+ >;
+ };
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SS0_ECSPI2_SS0 0x82
+ MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0x82
+ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0x82
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0x82
+ >;
+ };
+
+ pinctrl_usb_otg: usbotggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x140 /* otg_id */
+ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x19 /* otg_vbus */
+ >;
+ };
+
pinctrl_fec1: fec1grp {
fsl,pins = <
MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3
@@ -60,4 +298,101 @@
MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x19
>;
};
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6
+ MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6
+ MX8MM_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6
+ MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6
+ MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6
+ >;
+ };
+
+ pinctrl_spdif1: spdif1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SPDIF_TX_SPDIF1_OUT 0xd6
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x190
+ 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
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp{
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x194
+ 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
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x196
+ 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
+ >;
+ };
+
+ pinctrl_usdhc1_gpio: usdhc1-gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_RESET_B_GPIO2_IO10 0x41 /* wl_reg_on */
+ MX8MM_IOMUXC_SD1_DATA7_GPIO2_IO9 0x41 /* wl_host_wake */
+ MX8MM_IOMUXC_GPIO1_IO00_ANAMIX_REF_CLK_32K 0x141 /* LP0: 32KHz */
+ >;
+ };
+
+ 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-kontron-bl.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts
index aab8e2421650..a8ef4fba16a9 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts
@@ -25,6 +25,17 @@
clock-output-names = "osc-can";
};
+ hdmi-out {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_in_conn: endpoint {
+ remote-endpoint = <&bridge_out_conn>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -132,6 +143,86 @@
};
};
+&gpio4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio4>;
+
+ dsi_mux_sel_hdmi: dsi-mux-sel-hdmi-hog {
+ gpio-hog;
+ gpios = <14 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "dsi-mux-sel";
+ };
+
+ dsi_mux_sel_lvds: dsi-mux-sel-lvds-hog {
+ gpio-hog;
+ gpios = <14 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "dsi-mux-sel";
+ status = "disabled";
+ };
+
+ dsi-mux-oe-hog {
+ gpio-hog;
+ gpios = <15 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "dsi-mux-oe";
+ };
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ lvds: bridge@2c {
+ compatible = "ti,sn65dsi84";
+ reg = <0x2c>;
+ enable-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sn65dsi84>;
+ status = "disabled";
+ };
+
+ hdmi: hdmi@39 {
+ compatible = "adi,adv7535";
+ reg = <0x39>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adv7535>;
+ adi,dsi-lanes = <4>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+ a2vdd-supply = <&reg_vdd_1v8>;
+ avdd-supply = <&reg_vdd_1v8>;
+ dvdd-supply = <&reg_vdd_1v8>;
+ pvdd-supply = <&reg_vdd_1v8>;
+ v1p2-supply = <&reg_vdd_1v8>;
+ v3p3-supply = <&reg_vdd_3v3>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ bridge_in_dsi_hdmi: endpoint {
+ remote-endpoint = <&mipi_dsi_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ bridge_out_conn: endpoint {
+ remote-endpoint = <&hdmi_in_conn>;
+ };
+ };
+ };
+ };
+};
+
&i2c4 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -144,6 +235,19 @@
};
};
+&lcdif {
+ status = "okay";
+};
+
+&mipi_dsi {
+ samsung,esc-clock-frequency = <54000000>;
+ status = "okay";
+};
+
+&mipi_dsi_out {
+ remote-endpoint = <&bridge_in_dsi_hdmi>;
+};
+
&pwm2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm2>;
@@ -207,6 +311,12 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio>;
+ pinctrl_adv7535: adv7535grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x19
+ >;
+ };
+
pinctrl_can: cangrp {
fsl,pins = <
MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x19
@@ -277,6 +387,20 @@
>;
};
+ pinctrl_gpio4: gpio4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x19
+ MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x19
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x40000083
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x40000083
+ >;
+ };
+
pinctrl_i2c4: i2c4grp {
fsl,pins = <
MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x40000083
@@ -290,6 +414,13 @@
>;
};
+ pinctrl_sn65dsi84: sn65dsi84grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI2_TXD0_GPIO4_IO26 0x19
+ MX8MM_IOMUXC_SD2_WP_GPIO2_IO20 0x19
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX8MM_IOMUXC_SAI2_RXC_UART1_DCE_RX 0x0
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-dl.dtso b/arch/arm64/boot/dts/freescale/imx8mm-kontron-dl.dtso
new file mode 100644
index 000000000000..1db27731b581
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-dl.dtso
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Kontron Electronics GmbH
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "imx8mm-pinfunc.h"
+
+&{/} {
+ compatible = "kontron,imx8mm-bl", "kontron,imx8mm-sl", "fsl,imx8mm";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 50000 0>;
+ brightness-levels = <0 100>;
+ num-interpolated-steps = <100>;
+ default-brightness-level = <100>;
+ };
+
+ panel {
+ compatible = "jenson,bl-jt60050-01a", "panel-lvds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_panel>;
+ backlight = <&backlight>;
+ data-mapping = "vesa-24";
+ enable-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+ height-mm = <86>;
+ width-mm = <154>;
+
+ panel-timing {
+ clock-frequency = <51200000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hsync-len = <1>;
+ hfront-porch = <160>;
+ hback-porch = <160>;
+ vsync-len = <1>;
+ vfront-porch = <12>;
+ vback-porch = <23>;
+ };
+
+ port {
+ panel_out_bridge: endpoint {
+ remote-endpoint = <&bridge_out_panel>;
+ };
+ };
+ };
+};
+
+&dsi_mux_sel_hdmi {
+ status = "disabled";
+};
+
+&dsi_mux_sel_lvds {
+ status = "okay";
+};
+
+&mipi_dsi_out {
+ remote-endpoint = <&bridge_in_dsi_lvds>;
+};
+
+&gpio3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio3>;
+
+ panel-rst-hog {
+ gpio-hog;
+ gpios = <20 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "panel-reset";
+ };
+
+ panel-stby-hog {
+ gpio-hog;
+ gpios = <21 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "panel-standby";
+ };
+
+ panel-hinv-hog {
+ gpio-hog;
+ gpios = <24 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "panel-horizontal-invert";
+ };
+
+ panel-vinv-hog {
+ gpio-hog;
+ gpios = <25 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "panel-vertical-invert";
+ };
+};
+
+&hdmi {
+ status = "disabled";
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ touchscreen@5d {
+ compatible = "goodix,gt928";
+ reg = <0x5d>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_touch>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <22 8>;
+ reset-gpios = <&gpio3 23 0>;
+ irq-gpios = <&gpio3 22 0>;
+ };
+};
+
+&lvds {
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ bridge_in_dsi_lvds: endpoint {
+ remote-endpoint = <&mipi_dsi_out>;
+ data-lanes = <1 2>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ bridge_out_panel: endpoint {
+ remote-endpoint = <&panel_out_bridge>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_gpio3: gpio3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXD3_GPIO3_IO24 0x19
+ MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20 0x19
+ MX8MM_IOMUXC_SAI5_RXD0_GPIO3_IO21 0x19
+ MX8MM_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x19
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x40000083
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x40000083
+ >;
+ };
+
+ pinctrl_panel: panelgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXFS_GPIO3_IO19 0x19
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SPDIF_EXT_CLK_PWM1_OUT 0x6
+ >;
+ };
+
+ pinctrl_touch: touchgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI5_RXD1_GPIO3_IO22 0x19
+ MX8MM_IOMUXC_SAI5_RXD2_GPIO3_IO23 0x19
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dts b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dts
index 01b632b220dc..b941c8c4f7bb 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dts
@@ -75,6 +75,11 @@
};
};
+&mipi_dsi {
+ samsung,burst-clock-frequency = <891000000>;
+ samsung,esc-clock-frequency = <20000000>;
+};
+
&pcie_phy {
fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
fsl,clkreq-unsupported;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
index 36803b038cd5..5a3b1142ddf4 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
@@ -9,6 +9,11 @@
#include <dt-bindings/net/ti-dp83867.h>
/ {
+ aliases {
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
+ };
+
memory@40000000 {
device_type = "memory";
reg = <0x0 0x40000000 0 0x80000000>;
@@ -292,7 +297,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso
index 9bee7159a67b..b1a9f35e1dfa 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso
@@ -15,10 +15,6 @@
/dts-v1/;
/plugin/;
-&{/} {
- compatible = "gw,imx8mm-gw73xx-0x";
-};
-
&gpio4 {
rs485-en-hog {
gpio-hog;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso
index e98f50bcec57..44ebc0a58c51 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso
@@ -18,10 +18,6 @@
/dts-v1/;
/plugin/;
-&{/} {
- compatible = "gw,imx8mm-gw73xx-0x";
-};
-
&gpio4 {
rs485-en-hog {
gpio-hog;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso
index e875ff4637bd..2f8a7ac40873 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso
@@ -18,10 +18,6 @@
/dts-v1/;
/plugin/;
-&{/} {
- compatible = "gw,imx8mm-gw73xx-0x";
-};
-
&gpio4 {
rs485-en-hog {
gpio-hog;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx.dtsi
index 5eb92005195c..53004c4a13aa 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx.dtsi
@@ -116,6 +116,16 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+ accelerometer@19 {
+ compatible = "st,lis2de12";
+ reg = <0x19>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_accel>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ st,drdy-int-pin = <1>;
+ };
+
eeprom@52 {
compatible = "atmel,24c32";
reg = <0x52>;
@@ -198,6 +208,12 @@
>;
};
+ pinctrl_accel: accelgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_MISO_GPIO5_IO8 0x159
+ >;
+ };
+
pinctrl_gpio_leds: gpioledgrp {
fsl,pins = <
MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x6 /* LEDG */
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
index 35ae0faa815b..d8b67e12f7d7 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
@@ -22,6 +22,8 @@
ethernet2 = &lan2;
ethernet3 = &lan3;
ethernet4 = &lan4;
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
usb0 = &usbotg1;
usb1 = &usbotg2;
};
@@ -497,7 +499,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
index c11260c26d0b..46d1ee0a4ee8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
@@ -19,6 +19,8 @@
aliases {
ethernet1 = &eth1;
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
usb0 = &usbotg1;
usb1 = &usbotg2;
};
@@ -564,7 +566,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
index db1737bf637d..c0aadff4e25b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
@@ -18,6 +18,8 @@
aliases {
ethernet0 = &fec1;
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
usb0 = &usbotg1;
};
@@ -394,7 +396,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
index 05489a31e7fd..86a610de84fe 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
@@ -16,6 +16,11 @@
model = "Gateworks Venice GW7904 i.MX8MM board";
compatible = "gateworks,imx8mm-gw7904", "fsl,imx8mm";
+ aliases {
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
+ };
+
chosen {
stdout-path = &uart2;
};
@@ -438,7 +443,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi
new file mode 100644
index 000000000000..29075ff5eda6
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi
@@ -0,0 +1,471 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ *
+ * Common dtsi for Verdin IMX8MM SoM on Ivy carrier board
+ *
+ * https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx-8m-mini-nano
+ * https://www.toradex.com/products/carrier-board/ivy-carrier-board
+ */
+
+#include <dt-bindings/mux/mux.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ /* AIN1 Voltage w/o AIN1_MODE gpio control */
+ ain1_voltage_unmanaged: voltage-divider-ain1 {
+ compatible = "voltage-divider";
+ #io-channel-cells = <1>;
+ io-channels = <&ivy_adc1 0>;
+ full-ohms = <19>;
+ output-ohms = <1>;
+ };
+
+ /* AIN1 Current w/o AIN1_MODE gpio control */
+ ain1_current_unmanaged: current-sense-shunt-ain1 {
+ compatible = "current-sense-shunt";
+ #io-channel-cells = <0>;
+ io-channels = <&ivy_adc1 1>;
+ shunt-resistor-micro-ohms = <100000000>;
+ };
+
+ /* AIN1_MODE - SODIMM 216 */
+ ain1_mode_mux_ctrl: mux-controller-0 {
+ compatible = "gpio-mux";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio5>;
+ #mux-control-cells = <0>;
+ mux-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ ain1-voltage {
+ compatible = "io-channel-mux";
+ channels = "ain1_voltage", "";
+ io-channels = <&ain1_voltage_unmanaged 0>;
+ io-channel-names = "parent";
+ mux-controls = <&ain1_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ ain1-current {
+ compatible = "io-channel-mux";
+ channels = "", "ain1_current";
+ io-channels = <&ain1_current_unmanaged>;
+ io-channel-names = "parent";
+ mux-controls = <&ain1_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ /* AIN2 Voltage w/o AIN2_MODE gpio control */
+ ain2_voltage_unmanaged: voltage-divider-ain2 {
+ compatible = "voltage-divider";
+ #io-channel-cells = <1>;
+ io-channels = <&ivy_adc2 0>;
+ full-ohms = <19>;
+ output-ohms = <1>;
+ };
+
+ /* AIN2 Current w/o AIN2_MODE gpio control */
+ ain2_current_unmanaged: current-sense-shunt-ain2 {
+ compatible = "current-sense-shunt";
+ #io-channel-cells = <0>;
+ io-channels = <&ivy_adc2 1>;
+ shunt-resistor-micro-ohms = <100000000>;
+ };
+
+ /* AIN2_MODE - SODIMM 218 */
+ ain2_mode_mux_ctrl: mux-controller-1 {
+ compatible = "gpio-mux";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio6>;
+ #mux-control-cells = <0>;
+ mux-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ ain2-voltage {
+ compatible = "io-channel-mux";
+ channels = "ain2_voltage", "";
+ io-channels = <&ain2_voltage_unmanaged 0>;
+ io-channel-names = "parent";
+ mux-controls = <&ain2_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ ain2-current {
+ compatible = "io-channel-mux";
+ channels = "", "ain2_current";
+ io-channels = <&ain2_current_unmanaged>;
+ io-channel-names = "parent";
+ mux-controls = <&ain2_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ivy_leds>;
+
+ /* D7 Blue - SODIMM 30 - LEDs.GPIO1 */
+ led-0 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&gpio4 25 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D7 Green - SODIMM 32 - LEDs.GPIO2 */
+ led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D7 Red - SODIMM 34 - LEDs.GPIO3 */
+ led-2 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Blue - SODIMM 36 - LEDs.GPIO4 */
+ led-3 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Green - SODIMM 54 - LEDs.GPIO5 */
+ led-4 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&gpio3 1 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Red - SODIMM 44 - LEDs.GPIO6 */
+ led-5 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D9 Blue - SODIMM 46 - LEDs.GPIO7 */
+ led-6 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <3>;
+ gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D9 Red - SODIMM 48 - LEDs.GPIO8 */
+ led-7 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <3>;
+ gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ reg_3v2_ain1: regulator-3v2-ain1 {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3200000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-name = "+3V2_AIN1";
+ };
+
+ reg_3v2_ain2: regulator-3v2-ain2 {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3200000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-name = "+3V2_AIN2";
+ };
+
+ /* Ivy Power Supply Input Voltage */
+ ivy-input-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_1 */
+ io-channels = <&verdin_som_adc 7>;
+ full-ohms = <204700>; /* 200k + 4.7k */
+ output-ohms = <4700>;
+ };
+
+ ivy-5v-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_2 */
+ io-channels = <&verdin_som_adc 6>;
+ full-ohms = <39000>; /* 27k + 12k */
+ output-ohms = <12000>;
+ };
+
+ ivy-3v3-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_3 */
+ io-channels = <&verdin_som_adc 5>;
+ full-ohms = <54000>; /* 27k + 27k */
+ output-ohms = <27000>;
+ };
+
+ ivy-1v8-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_4 */
+ io-channels = <&verdin_som_adc 4>;
+ full-ohms = <39000>; /* 12k + 27k */
+ output-ohms = <27000>;
+ };
+};
+
+/* Verdin SPI_1 */
+&ecspi2 {
+ pinctrl-0 = <&pinctrl_ecspi2>,
+ <&pinctrl_gpio1>,
+ <&pinctrl_gpio4>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>,
+ <&gpio3 4 GPIO_ACTIVE_LOW>,
+ <&gpio5 27 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ tpm@1 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <1>;
+ spi-max-frequency = <18500000>;
+ };
+
+ fram@2 {
+ compatible = "fujitsu,mb85rs256", "atmel,at25";
+ reg = <2>;
+ address-width = <16>;
+ size = <32768>;
+ spi-max-frequency = <33000000>;
+ pagesize = <1>;
+ };
+};
+
+/* EEPROM on Ivy */
+&eeprom_carrier_board {
+ status = "okay";
+};
+
+/* Verdin ETH_1 */
+&fec1 {
+ status = "okay";
+};
+
+&gpio3 {
+ gpio-line-names =
+ "", /* 0 */
+ "",
+ "REL3", /* SODIMM 64 */
+ "",
+ "",
+ "",
+ "DIG_1", /* SODIMM 56 */
+ "DIG_2", /* SODIMM 58 */
+ "REL1", /* SODIMM 60 */
+ "REL2", /* SODIMM 62 */
+ "", /* 10 */
+ "",
+ "",
+ "",
+ "REL4", /* SODIMM 66 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 20 */
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+&gpio5 {
+ gpio-line-names =
+ "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "GPIO2", /* Verdin GPIO_2 - SODIMM 208 */
+ "",
+ "",
+ "",
+ "",
+ "", /* 10 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 20 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "GPIO3", /* Verdin GPIO_3 - SODIMM 210 */
+ "",
+ "",
+ "";
+};
+
+/* Temperature sensor on Ivy */
+&hwmon_temp {
+ compatible = "ti,tmp1075";
+ status = "okay";
+};
+
+/* Verdin I2C_4 CSI */
+&i2c3 {
+ status = "okay";
+
+ ivy_adc1: adc@40 {
+ compatible = "ti,ads1119";
+ reg = <0x40>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio7>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+ avdd-supply = <&reg_3v2_ain1>;
+ dvdd-supply = <&reg_3v2_ain1>;
+ vref-supply = <&reg_3v2_ain1>;
+ #address-cells = <1>;
+ #io-channel-cells = <1>;
+ #size-cells = <0>;
+
+ /* AIN1 0-33V Voltage Input */
+ channel@0 {
+ reg = <0>;
+ diff-channels = <0 1>;
+ };
+
+ /* AIN1 0-20mA Current Input */
+ channel@1 {
+ reg = <1>;
+ diff-channels = <2 3>;
+ };
+ };
+
+ ivy_adc2: adc@41 {
+ compatible = "ti,ads1119";
+ reg = <0x41>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio8>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+ avdd-supply = <&reg_3v2_ain2>;
+ dvdd-supply = <&reg_3v2_ain2>;
+ vref-supply = <&reg_3v2_ain2>;
+ #address-cells = <1>;
+ #io-channel-cells = <1>;
+ #size-cells = <0>;
+
+ /* AIN2 0-33V Voltage Input */
+ channel@0 {
+ reg = <0>;
+ diff-channels = <0 1>;
+ };
+
+ /* AIN2 0-20mA Current Input */
+ channel@1 {
+ reg = <1>;
+ diff-channels = <2 3>;
+ };
+ };
+};
+
+/* Verdin I2C_1 */
+&i2c4 {
+ status = "okay";
+};
+
+/* Verdin PCIE_1 */
+&pcie0 {
+ status = "okay";
+};
+
+&pcie_phy {
+ status = "okay";
+};
+
+/* Verdin UART_3 */
+&uart1 {
+ status = "okay";
+};
+
+/* Verdin UART_1 */
+&uart2 {
+ status = "okay";
+};
+
+/* Verdin UART_2 */
+&uart3 {
+ linux,rs485-enabled-at-boot-time;
+ rs485-rx-during-tx;
+ status = "okay";
+};
+
+/* Verdin USB_1*/
+&usbotg1 {
+ status = "okay";
+};
+
+/* Verdin USB_2 */
+&usbotg2 {
+ status = "okay";
+};
+
+/* Verdin SD_1 */
+&usdhc2 {
+ status = "okay";
+};
+
+&iomuxc {
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio2>, <&pinctrl_gpio3>,
+ <&pinctrl_ivy_dig_inputs>, <&pinctrl_ivy_relays>;
+
+ pinctrl_ivy_dig_inputs: ivydiginputsgrp {
+ fsl,pins =
+ <MX8MM_IOMUXC_NAND_DATA00_GPIO3_IO6 0x96>, /* SODIMM 56 */
+ <MX8MM_IOMUXC_NAND_DATA01_GPIO3_IO7 0x96>; /* SODIMM 58 */
+ };
+
+ pinctrl_ivy_leds: ivyledsgrp {
+ fsl,pins =
+ <MX8MM_IOMUXC_SAI2_TXC_GPIO4_IO25 0x16>, /* SODIMM 30 */
+ <MX8MM_IOMUXC_SAI2_TXFS_GPIO4_IO24 0x16>, /* SODIMM 32 */
+ <MX8MM_IOMUXC_SAI2_TXD0_GPIO4_IO26 0x16>, /* SODIMM 34 */
+ <MX8MM_IOMUXC_SAI2_RXD0_GPIO4_IO23 0x16>, /* SODIMM 36 */
+ <MX8MM_IOMUXC_SAI5_RXD1_GPIO3_IO22 0x16>, /* SODIMM 44 */
+ <MX8MM_IOMUXC_SAI5_RXD3_GPIO3_IO24 0x16>, /* SODIMM 46 */
+ <MX8MM_IOMUXC_SAI5_RXD0_GPIO3_IO21 0x16>, /* SODIMM 48 */
+ <MX8MM_IOMUXC_NAND_CE0_B_GPIO3_IO1 0x16>; /* SODIMM 54 */
+ };
+
+ pinctrl_ivy_relays: ivyrelaysgrp {
+ fsl,pins =
+ <MX8MM_IOMUXC_NAND_DATA02_GPIO3_IO8 0x16>, /* SODIMM 60 */
+ <MX8MM_IOMUXC_NAND_DATA03_GPIO3_IO9 0x16>, /* SODIMM 62 */
+ <MX8MM_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x16>, /* SODIMM 64 */
+ <MX8MM_IOMUXC_NAND_DQS_GPIO3_IO14 0x16>; /* SODIMM 66 */
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-ivy.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-ivy.dts
new file mode 100644
index 000000000000..82b34a12ee2b
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-ivy.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin.dtsi"
+#include "imx8mm-verdin-nonwifi.dtsi"
+#include "imx8mm-verdin-ivy.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini on Ivy";
+ compatible = "toradex,verdin-imx8mm-nonwifi-ivy",
+ "toradex,verdin-imx8mm-nonwifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-ivy.dts b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-ivy.dts
new file mode 100644
index 000000000000..3369ba852b5c
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-wifi-ivy.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mm-verdin.dtsi"
+#include "imx8mm-verdin-wifi.dtsi"
+#include "imx8mm-verdin-ivy.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Mini WB on Ivy";
+ compatible = "toradex,verdin-imx8mm-wifi-ivy",
+ "toradex,verdin-imx8mm-wifi",
+ "toradex,verdin-imx8mm",
+ "fsl,imx8mm";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
index 5fa395914191..c528594ac442 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
@@ -162,7 +162,7 @@
regulator-max-microvolt = <3300000>;
regulator-min-microvolt = <3300000>;
regulator-name = "+V3.3_SD";
- startup-delay-us = <2000>;
+ startup-delay-us = <20000>;
};
reserved-memory {
@@ -367,6 +367,7 @@
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)>;
+ single-master;
status = "okay";
pca9450: pmic@25 {
@@ -483,11 +484,12 @@
reg = <0x32>;
};
- adc@49 {
+ verdin_som_adc: adc@49 {
compatible = "ti,ads1015";
reg = <0x49>;
#address-cells = <1>;
#size-cells = <0>;
+ #io-channel-cells = <1>;
/* Verdin I2C_1 (ADC_4 - ADC_3) */
channel@0 {
@@ -561,6 +563,7 @@
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)>;
+ single-master;
status = "disabled";
};
@@ -574,6 +577,7 @@
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)>;
+ single-master;
};
/* Verdin I2C_1 */
@@ -584,6 +588,7 @@
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)>;
+ single-master;
gpio_expander_21: gpio-expander@21 {
compatible = "nxp,pcal6416";
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 9535dedcef59..4de3bf22902b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -1375,9 +1375,11 @@
pcie0_ep: pcie-ep@33800000 {
compatible = "fsl,imx8mm-pcie-ep";
- reg = <0x33800000 0x400000>,
- <0x18000000 0x8000000>;
- reg-names = "dbi", "addr_space";
+ reg = <0x33800000 0x100000>,
+ <0x18000000 0x8000000>,
+ <0x33900000 0x100000>,
+ <0x33b00000 0x100000>;
+ reg-names = "dbi", "addr_space", "dbi2", "atu";
num-lanes = <1>;
interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "dma";
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso
index 96db07fc9bec..1f2a0fe70a0a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso
+++ b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx-usbotg.dtso
@@ -29,12 +29,37 @@
};
};
+/*
+ * rst_usb_hub_hog and sel_usb_hub_hog have property 'output-high',
+ * dt overlay don't support /delete-property/. Both 'output-low' and
+ * 'output-high' will be exist under hog nodes if overlay file set
+ * 'output-low'. Workaround is disable these hog and create new hog with
+ * 'output-low'.
+ */
+
&rst_usb_hub_hog {
- output-low;
+ status = "disabled";
+};
+
+&expander0 {
+ rst-usb-low-hub-hog {
+ gpio-hog;
+ gpios = <13 0>;
+ output-low;
+ line-name = "RST_USB_HUB#";
+ };
};
&sel_usb_hub_hog {
- output-low;
+ status = "disabled";
+};
+
+&gpio2 {
+ sel-usb-low-hub-hog {
+ gpio-hog;
+ gpios = <1 GPIO_ACTIVE_HIGH>;
+ output-low;
+ };
};
&usbotg1 {
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx.dts b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx.dts
index 433d8bba4425..dc94d73f7106 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-tqma8mqnl-mba8mx.dts
@@ -64,6 +64,11 @@
};
};
+&mipi_dsi {
+ samsung,burst-clock-frequency = <891000000>;
+ samsung,esc-clock-frequency = <20000000>;
+};
+
&sai3 {
assigned-clocks = <&clk IMX8MN_CLK_SAI3>;
assigned-clock-parents = <&clk IMX8MN_AUDIO_PLL1_OUT>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
index 0b1fa04f1d67..30c286b34aa5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
@@ -17,6 +17,8 @@
compatible = "gw,imx8mn-gw7902", "fsl,imx8mn";
aliases {
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
usb0 = &usbotg1;
};
@@ -562,7 +564,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-drc02.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-drc02.dts
new file mode 100644
index 000000000000..c6bf7fd91981
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-drc02.dts
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2024 Marek Vasut <marex@denx.de>
+ *
+ * DHCOM iMX8MP variant:
+ * DHCM-iMX8ML8-C160-R204-F1638-SPI16-E2-CAN2-RTC-I-01D2
+ * DHCOM PCB number: 660-100 or newer
+ * DRC02 PCB number: 568-100 or newer
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+#include "imx8mp-dhcom-som.dtsi"
+
+/ {
+ model = "DH electronics i.MX8M Plus DHCOM on DRC02";
+ compatible = "dh,imx8mp-dhcom-drc02", "dh,imx8mp-dhcom-som",
+ "fsl,imx8mp";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+};
+
+&eqos { /* First ethernet */
+ pinctrl-0 = <&pinctrl_eqos_rmii>;
+ phy-handle = <&ethphy0f>;
+ phy-mode = "rmii";
+
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_266M>,
+ <&clk IMX8MP_SYS_PLL2_100M>,
+ <&clk IMX8MP_SYS_PLL2_50M>;
+ assigned-clock-rates = <0>, <100000000>, <50000000>;
+};
+
+&ethphy0g { /* Micrel KSZ9131RNXI */
+ status = "disabled";
+};
+
+&ethphy0f { /* SMSC LAN8740Ai */
+ status = "okay";
+};
+
+&fec { /* Second ethernet */
+ pinctrl-0 = <&pinctrl_fec_rmii>;
+ phy-handle = <&ethphy1f>;
+ phy-mode = "rmii";
+ status = "okay";
+
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_266M>,
+ <&clk IMX8MP_SYS_PLL2_100M>,
+ <&clk IMX8MP_SYS_PLL2_50M>,
+ <&clk IMX8MP_SYS_PLL2_50M>;
+ assigned-clock-rates = <0>, <100000000>, <50000000>, <0>;
+};
+
+&ethphy1f { /* SMSC LAN8740Ai */
+ status = "okay";
+};
+
+&flexcan1 {
+ status = "okay";
+};
+
+&flexcan2 {
+ status = "okay";
+};
+
+&gpio1 {
+ gpio-line-names =
+ "DRC02-In1", "", "", "", "", "DHCOM-I", "DRC02-HW2", "DRC02-HW0",
+ "DHCOM-B", "DHCOM-A", "", "DHCOM-H", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "";
+
+ /*
+ * NOTE: On DRC02, the RS485_RX_En is controlled by a separate
+ * GPIO line, however the i.MX8 UART driver assumes RX happens
+ * during TX anyway and that it only controls drive enable DE
+ * line. Hence, the RX is always enabled here.
+ */
+ rs485-rx-en-hog {
+ gpio-hog;
+ gpios = <13 0>; /* GPIO Q */
+ line-name = "rs485-rx-en";
+ output-low;
+ };
+};
+
+&gpio2 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "DHCOM-O", "DHCOM-N", "", "SOM-HW1", "", "", "", "",
+ "", "", "", "", "DRC02-In2", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio3 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "SOM-HW0", "",
+ "", "", "", "", "", "", "SOM-MEM0", "SOM-MEM1",
+ "SOM-MEM2", "SOM-HW2", "", "", "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "SOM-HW1", "", "", "", "",
+ "", "", "", "DRC02-Out2", "", "", "", "";
+};
+
+&gpio5 {
+ gpio-line-names =
+ "", "", "DHCOM-C", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "DHCOM-E", "DRC02-Out1",
+ "", "", "", "", "", "", "", "";
+};
+
+/* No HS connector on this SoM variant, so no HDMI, PCIe and only USB HS. */
+&hdmi_blk_ctrl {
+ status = "disabled";
+};
+
+&hdmi_pvi {
+ status = "disabled";
+};
+
+&hdmi_tx {
+ status = "disabled";
+};
+
+&hdmi_tx_phy {
+ status = "disabled";
+};
+
+&i2c3 {
+ /* Resistive touch controller not populated on this one SoM variant. */
+ touchscreen@49 {
+ status = "disabled";
+ };
+};
+
+&irqsteer_hdmi {
+ status = "disabled";
+};
+
+&lcdif3 {
+ status = "disabled";
+};
+
+&pcie_phy {
+ status = "disabled";
+};
+
+&pcie {
+ status = "disabled";
+};
+
+/* Console UART */
+&pinctrl_uart1 {
+ fsl,pins = <
+ /* No pull-ups on DRC02, enable in-SoC pull-ups */
+ MX8MP_IOMUXC_SAI2_RXC__UART1_DCE_RX 0x149
+ MX8MP_IOMUXC_SAI2_RXFS__UART1_DCE_TX 0x149
+ >;
+};
+
+&pinctrl_uart3 {
+ fsl,pins = <
+ /* No pull-ups on DRC02, enable in-SoC pull-ups */
+ MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX 0x149
+ MX8MP_IOMUXC_ECSPI1_MOSI__UART3_DCE_TX 0x149
+ >;
+};
+
+&uart1 {
+ /*
+ * Due to the use of CAN2 the signals for CAN2 Tx and Rx are routed to
+ * DHCOM UART1 RTS/CTS pins. Therefore this UART have to use DHCOM GPIOs
+ * for RTS/CTS. So configure DHCOM GPIO I as RTS and GPIO M as CTS.
+ */
+ /delete-property/ uart-has-rtscts;
+ cts-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>; /* GPIO M */
+ pinctrl-0 = <&pinctrl_uart1 &pinctrl_dhcom_i &pinctrl_dhcom_m>;
+ pinctrl-names = "default";
+ rts-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; /* GPIO I */
+};
+
+&uart3 {
+ /*
+ * On DRC02 this UART is used as RS485 interface and RS485_TX_En is
+ * controlled by DHCOM GPIO P. So remove RTS/CTS pins and the property
+ * uart-has-rtscts from this UART and add the DHCOM GPIO P pin via
+ * rts-gpios. The RS485_RX_En is controlled by DHCOM GPIO Q, see gpio1
+ * node above.
+ */
+ /delete-property/ uart-has-rtscts;
+ linux,rs485-enabled-at-boot-time;
+ pinctrl-0 = <&pinctrl_uart3 &pinctrl_dhcom_p &pinctrl_dhcom_q>;
+ pinctrl-names = "default";
+ rts-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; /* GPIO P */
+};
+
+/* No WiFi/BT chipset on this SoM variant. */
+&uart2 {
+ bluetooth {
+ status = "disabled";
+ };
+};
+
+/* USB_OTG port is not routed out on DRC02. */
+&usb3_0 {
+ status = "disabled";
+};
+
+&usb_dwc3_0 {
+ status = "disabled";
+};
+
+/* USB_HOST port has USB Hub connected to it, PWR/OC pins are unused */
+&usb3_1 {
+ fsl,disable-port-power-control;
+ fsl,permanently-attached;
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ maximum-speed = "high-speed";
+};
+
+/* No WiFi/BT chipset on this SoM variant. */
+&usdhc1 {
+ status = "disabled";
+};
+
+&iomuxc {
+ /*
+ * GPIO I is connected to UART1_RTS
+ * GPIO M is connected to UART1_CTS
+ * GPIO P is connected to RS485_TX_En
+ * GPIO Q is connected to RS485_RX_En
+ */
+ pinctrl-0 = <&pinctrl_hog_base
+ &pinctrl_dhcom_a &pinctrl_dhcom_b &pinctrl_dhcom_c
+ &pinctrl_dhcom_d &pinctrl_dhcom_e &pinctrl_dhcom_f
+ &pinctrl_dhcom_g &pinctrl_dhcom_h &pinctrl_dhcom_j
+ &pinctrl_dhcom_k &pinctrl_dhcom_l &pinctrl_dhcom_n
+ &pinctrl_dhcom_o &pinctrl_dhcom_r &pinctrl_dhcom_s
+ &pinctrl_dhcom_int>;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-picoitx.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-picoitx.dts
new file mode 100644
index 000000000000..703cf0fb3d2b
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-picoitx.dts
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023-2024 Marek Vasut <marex@denx.de>
+ *
+ * DHCOM iMX8MP variant:
+ * DHCM-iMX8ML8-C160-R204-F1638-SPI16-E-SD-RTC-T-RGB-I-01D2
+ * DHCOM PCB number: 660-200 or newer
+ * PicoITX PCB number: 487-600 or newer
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "imx8mp-dhcom-som.dtsi"
+
+/ {
+ model = "DH electronics i.MX8M Plus DHCOM PicoITX";
+ compatible = "dh,imx8mp-dhcom-picoitx", "dh,imx8mp-dhcom-som",
+ "fsl,imx8mp";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ led {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_YELLOW>;
+ default-state = "off";
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; /* GPIO I */
+ pinctrl-0 = <&pinctrl_dhcom_i>;
+ pinctrl-names = "default";
+ };
+ };
+};
+
+&eqos { /* First ethernet */
+ pinctrl-0 = <&pinctrl_eqos_rmii>;
+ phy-handle = <&ethphy0f>;
+ phy-mode = "rmii";
+
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_266M>,
+ <&clk IMX8MP_SYS_PLL2_100M>,
+ <&clk IMX8MP_SYS_PLL2_50M>;
+ assigned-clock-rates = <0>, <100000000>, <50000000>;
+};
+
+&ethphy0g { /* Micrel KSZ9131RNXI */
+ status = "disabled";
+};
+
+&ethphy0f { /* SMSC LAN8740Ai */
+ status = "okay";
+};
+
+&fec {
+ status = "disabled";
+};
+
+&flexcan1 {
+ status = "okay";
+};
+
+&gpio1 {
+ gpio-line-names =
+ "DHCOM-G", "", "", "",
+ "", "DHCOM-I", "PicoITX-HW0", "PicoITX-HW2",
+ "DHCOM-B", "DHCOM-A", "", "DHCOM-H", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio2 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "PicoITX-HW1", "", "", "", "",
+ "", "", "", "", "DHCOM-INT", "", "", "",
+ "", "", "", "", "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "SOM-HW1", "", "", "", "",
+ "", "", "", "PicoITX-Out2", "", "", "", "";
+};
+
+&gpio5 {
+ gpio-line-names =
+ "", "", "PicoITX-In2", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "",
+ "", "", "PicoITX-In1", "PicoITX-Out1",
+ "", "", "", "", "", "", "", "";
+};
+
+/* No HS connector on this SoM variant, so no HDMI, PCIe and only USB HS. */
+&hdmi_blk_ctrl {
+ status = "disabled";
+};
+
+&hdmi_pvi {
+ status = "disabled";
+};
+
+&hdmi_tx {
+ status = "disabled";
+};
+
+&hdmi_tx_phy {
+ status = "disabled";
+};
+
+&irqsteer_hdmi {
+ status = "disabled";
+};
+
+&lcdif3 {
+ status = "disabled";
+};
+
+&pcie_phy {
+ status = "disabled";
+};
+
+&pcie {
+ status = "disabled";
+};
+
+/* No WiFi/BT chipset on this SoM variant. */
+&uart2 {
+ bluetooth {
+ status = "disabled";
+ };
+};
+
+/* USB_OTG port is not routed out on PicoITX. */
+&usb3_0 {
+ status = "disabled";
+};
+
+&usb_dwc3_0 {
+ status = "disabled";
+};
+
+&usb3_1 {
+ fsl,over-current-active-low;
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ maximum-speed = "high-speed";
+};
+
+/* No WiFi/BT chipset on this SoM variant. */
+&usdhc1 {
+ status = "disabled";
+};
+
+&iomuxc {
+ /*
+ * The following DHCOM GPIOs are used on this board.
+ * Therefore, they have been removed from the list below.
+ * I: yellow led
+ */
+ pinctrl-0 = <&pinctrl_dhcom_a &pinctrl_dhcom_b &pinctrl_dhcom_c
+ &pinctrl_dhcom_d &pinctrl_dhcom_e &pinctrl_dhcom_f
+ &pinctrl_dhcom_g &pinctrl_dhcom_h &pinctrl_dhcom_j
+ &pinctrl_dhcom_k &pinctrl_dhcom_l &pinctrl_dhcom_m
+ &pinctrl_dhcom_n &pinctrl_dhcom_o &pinctrl_dhcom_p
+ &pinctrl_dhcom_q &pinctrl_dhcom_r &pinctrl_dhcom_s
+ &pinctrl_dhcom_int>;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-pcie-ep.dtso b/arch/arm64/boot/dts/freescale/imx8mp-evk-pcie-ep.dtso
new file mode 100644
index 000000000000..244e820699b5
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-pcie-ep.dtso
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024 NXP
+ */
+
+/dts-v1/;
+/plugin/;
+
+&pcie {
+ status = "disabled";
+};
+
+&pcie_ep {
+ pinctrl-0 = <&pinctrl_pcie0>;
+ pinctrl-names = "default";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-iota2-lumpy.dts b/arch/arm64/boot/dts/freescale/imx8mp-iota2-lumpy.dts
new file mode 100644
index 000000000000..f48cf22b423d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-iota2-lumpy.dts
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2023 Y Soft
+ */
+
+/dts-v1/;
+
+#include "imx8mp.dtsi"
+
+/ {
+ compatible = "ysoft,imx8mp-iota2-lumpy", "fsl,imx8mp";
+ model = "Y Soft i.MX8MPlus IOTA2 Lumpy board";
+
+ beeper {
+ compatible = "pwm-beeper";
+ pwms = <&pwm4 0 500000 0>;
+ };
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ gpio_keys: gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+ pinctrl-names = "default";
+
+ button-reset {
+ gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+ label = "Factory RESET";
+ linux,code = <BTN_0>;
+ };
+ };
+
+ reg_usb_host: regulator-usb-host {
+ compatible = "regulator-fixed";
+ pinctrl-0 = <&pinctrl_usb_host_vbus>;
+ pinctrl-names = "default";
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "usb-host";
+ gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ memory@40000000 {
+ reg = <0x0 0x40000000 0 0x80000000>,
+ <0x1 0x00000000 0 0x80000000>;
+ device_type = "memory";
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&reg_arm>;
+};
+
+&A53_1 {
+ cpu-supply = <&reg_arm>;
+};
+
+&A53_2 {
+ cpu-supply = <&reg_arm>;
+};
+
+&A53_3 {
+ cpu-supply = <&reg_arm>;
+};
+
+&eqos {
+ phy-handle = <&ethphy0>;
+ phy-mode = "rgmii-id";
+ pinctrl-0 = <&pinctrl_eqos>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ reg = <0>;
+ interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio3>;
+ pinctrl-0 = <&pinctrl_ethphy0>;
+ pinctrl-names = "default";
+ reset-assert-us = <1000>;
+ reset-deassert-us = <1000>;
+ reset-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+ micrel,led-mode = <0>;
+ };
+ };
+};
+
+&fec {
+ fsl,magic-packet;
+ phy-handle = <&ethphy1>;
+ phy-mode = "rgmii-id";
+ pinctrl-0 = <&pinctrl_fec>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@0 {
+ reg = <0>;
+ interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio3>;
+ pinctrl-0 = <&pinctrl_ethphy1>;
+ pinctrl-names = "default";
+ reset-assert-us = <1000>;
+ reset-deassert-us = <1000>;
+ reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ micrel,led-mode = <0>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ pmic@25 {
+ compatible = "nxp,pca9450c";
+ reg = <0x25>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio1>;
+ pinctrl-0 = <&pinctrl_pmic>;
+ pinctrl-names = "default";
+
+ regulators {
+ BUCK1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1000000>;
+ regulator-min-microvolt = <720000>;
+ regulator-name = "BUCK1";
+ regulator-ramp-delay = <3125>;
+ };
+
+ reg_arm: BUCK2 {
+ nxp,dvs-run-voltage = <950000>;
+ nxp,dvs-standby-voltage = <850000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1025000>;
+ regulator-min-microvolt = <720000>;
+ regulator-name = "BUCK2";
+ regulator-ramp-delay = <3125>;
+ };
+
+ BUCK4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <3600000>;
+ regulator-min-microvolt = <3000000>;
+ regulator-name = "BUCK4";
+ };
+
+ BUCK5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1950000>;
+ regulator-min-microvolt = <1650000>;
+ regulator-name = "BUCK5";
+ };
+
+ BUCK6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1155000>;
+ regulator-min-microvolt = <1045000>;
+ regulator-name = "BUCK6";
+ };
+
+ LDO1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1950000>;
+ regulator-min-microvolt = <1650000>;
+ regulator-name = "LDO1";
+ };
+
+ LDO3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1890000>;
+ regulator-min-microvolt = <1710000>;
+ regulator-name = "LDO3";
+ };
+
+ LDO4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <950000>;
+ regulator-min-microvolt = <850000>;
+ regulator-name = "LDO4";
+ };
+
+ LDO5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-name = "LDO5";
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ rtc: rtc@68 {
+ compatible = "dallas,ds1341";
+ reg = <0x68>;
+ };
+};
+
+&pwm4 {
+ pinctrl-0 = <&pinctrl_pwm4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&pinctrl_uart2>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb3_1 {
+ status = "okay";
+};
+
+&usb3_phy1 {
+ vbus-supply = <&reg_usb_host>;
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usdhc3 {
+ assigned-clocks = <&clk IMX8MP_CLK_USDHC3>;
+ assigned-clock-rates = <400000000>;
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-0 = <&pinctrl_wdog>;
+ pinctrl-names = "default";
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_eqos: eqosgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x2
+ MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO 0x2
+ MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0 0x90
+ MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1 0x90
+ MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2 0x90
+ MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3 0x90
+ MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x90
+ MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x90
+ MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0 0x16
+ MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1 0x16
+ MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2 0x16
+ MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3 0x16
+ MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x16
+ MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x16
+ >;
+ };
+
+ pinctrl_ethphy0: ethphy0grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXD0__GPIO3_IO21 0x10
+ MX8MP_IOMUXC_SAI5_RXD1__GPIO3_IO22 0x10
+ >;
+ };
+
+ pinctrl_ethphy1: ethphy1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXFS__GPIO3_IO19 0x10
+ MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20 0x10
+ >;
+ };
+
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC 0x2
+ MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO 0x2
+ MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0 0x90
+ MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1 0x90
+ MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2 0x90
+ MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3 0x90
+ MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC 0x90
+ MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL 0x90
+ MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0 0x16
+ MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1 0x16
+ MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2 0x16
+ MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3 0x16
+ MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL 0x16
+ MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC 0x16
+ >;
+ };
+
+ pinctrl_gpio_keys: gpiokeysgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07 0x80
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c2
+ MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA 0x400001c2
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2
+ MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2
+ >;
+ };
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO03__GPIO1_IO03 0x1c0
+ >;
+ };
+
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI3_MCLK__PWM4_OUT 0x102
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x0
+ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x0
+ >;
+ };
+
+ pinctrl_usb_host_vbus: usb1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR 0x0
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x194
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d4
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d4
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d4
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d4
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d4
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d4
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d4
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d4
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d4
+ MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x196
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d6
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d6
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d6
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d6
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d6
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d6
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d6
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d6
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d6
+ MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x196
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x190
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d0
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d0
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d0
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d0
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d0
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d0
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d0
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d0
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d0
+ MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x190
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0x166
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-kontron-bl-osm-s.dts b/arch/arm64/boot/dts/freescale/imx8mp-kontron-bl-osm-s.dts
new file mode 100644
index 000000000000..0eb9e726a9b8
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-kontron-bl-osm-s.dts
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2022 Kontron Electronics GmbH
+ */
+
+/dts-v1/;
+
+#include "imx8mp-kontron-osm-s.dtsi"
+
+/ {
+ model = "Kontron BL i.MX8MP OSM-S";
+ compatible = "kontron,imx8mp-bl-osm-s", "kontron,imx8mp-osm-s", "fsl,imx8mp";
+
+ aliases {
+ ethernet0 = &fec;
+ ethernet1 = &eqos;
+ };
+
+ extcon_usbc: usbc {
+ compatible = "linux,extcon-usb-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb1_id>;
+ id-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led1 {
+ label = "led1";
+ gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ pwm-beeper {
+ compatible = "pwm-beeper";
+ pwms = <&pwm2 0 5000 0>;
+ };
+
+ reg_vcc_panel: regulator-vcc-panel {
+ compatible = "regulator-fixed";
+ gpio = <&gpio4 3 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "VCC_PANEL";
+ };
+};
+
+&ecspi2 {
+ status = "okay";
+
+ eeram@0 {
+ compatible = "microchip,48l640";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ };
+};
+
+&eqos { /* Second ethernet (OSM-S ETH_B) */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eqos_rgmii>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-id4f51.e91b";
+ reg = <1>;
+ pinctrl-0 = <&pinctrl_ethphy1>;
+ pinctrl-names = "default";
+ reset-assert-us = <10000>;
+ reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&fec { /* First ethernet (OSM-S ETH_A) */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_rgmii>;
+ phy-connection-type = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-id4f51.e91b";
+ reg = <1>;
+ pinctrl-0 = <&pinctrl_ethphy0>;
+ pinctrl-names = "default";
+ reset-assert-us = <10000>;
+ reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&flexcan1 {
+ status = "okay";
+};
+
+/*
+ * Rename SoM signals according to board usage:
+ * SDIO_A_PWR_EN -> CAN_ADDR2
+ * SDIO_A_WP -> CAN_ADDR3
+ */
+&gpio2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio2>;
+ gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "",
+ "SDIO_A_CD", "SDIO_A_CLK", "SDIO_A_CMD", "SDIO_A_D0",
+ "SDIO_A_D1", "SDIO_A_D2", "SDIO_A_D3", "CAN_ADDR2",
+ "CAN_ADDR3";
+};
+
+/*
+ * Rename SoM signals according to board usage:
+ * SPI_A_WP -> CAN_ADDR0
+ * SPI_A_HOLD -> CAN_ADDR1
+ * GPIO_B_0 -> DIO1_OUT
+ * GPIO_B_1 -> DIO2_OUT
+ */
+&gpio3 {
+ gpio-line-names = "PCIE_WAKE", "PCIE_CLKREQ", "PCIE_A_PERST", "SDIO_B_D5",
+ "SDIO_B_D6", "SDIO_B_D7", "CAN_ADDR0", "CAN_ADDR1",
+ "UART_B_RTS", "UART_B_CTS", "SDIO_B_D0", "SDIO_B_D1",
+ "SDIO_B_D2", "SDIO_B_D3", "SDIO_B_WP", "SDIO_B_D4",
+ "PCIE_SM_ALERT", "SDIO_B_CLK", "SDIO_B_CMD", "DIO1_OUT",
+ "DIO2_OUT", "", "BOOT_SEL0", "BOOT_SEL1",
+ "", "", "SDIO_B_CD", "SDIO_B_PWR_EN",
+ "HDMI_CEC", "HDMI_HPD";
+};
+
+/*
+ * Rename SoM signals according to board usage:
+ * GPIO_B_5 -> DIO2_IN
+ * GPIO_B_6 -> DIO3_IN
+ * GPIO_B_7 -> DIO4_IN
+ * GPIO_B_3 -> DIO4_OUT
+ * GPIO_B_4 -> DIO1_IN
+ * GPIO_B_2 -> DIO3_OUT
+ */
+&gpio4 {
+ gpio-line-names = "DIO2_IN", "DIO3_IN", "DIO4_IN", "GPIO_C_0",
+ "ETH_A_MDC", "ETH_A_MDIO", "ETH_A_RXD0", "ETH_A_RXD1",
+ "ETH_A_RXD2", "ETH_A_RXD3", "ETH_A_RX_DV", "ETH_A_RX_CLK",
+ "ETH_A_TXD0", "ETH_A_TXD1", "ETH_A_TXD2", "ETH_A_TXD3",
+ "ETH_A_TX_EN", "ETH_A_TX_CLK", "DIO4_OUT", "DIO1_IN",
+ "DIO3_OUT", "GPIO_A_6", "CAN_A_TX", "UART_A_CTS",
+ "UART_A_RTS", "CAN_A_RX", "CAN_B_TX", "CAN_B_RX",
+ "GPIO_A_7", "CARRIER_PWR_EN", "I2S_A_DATA_IN", "I2S_LRCLK";
+};
+
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi>;
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ gpio_expander_dio: io-expander@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "DIO1_OUT","DIO1_IN", "DIO2_OUT","DIO2_IN",
+ "DIO3_OUT","DIO3_IN", "DIO4_OUT","DIO4_IN";
+ interrupt-parent = <&gpio3>;
+ interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&lcdif3 {
+ status = "okay";
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&reg_usdhc2_vcc {
+ status = "disabled";
+};
+
+&snvs_pwrkey {
+ status = "okay";
+};
+
+&uart1 {
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart4 {
+ linux,rs485-enabled-at-boot-time;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ adp-disable;
+ hnp-disable;
+ srp-disable;
+ dr_mode = "otg";
+ extcon = <&extcon_usbc>;
+ usb-role-switch;
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_hub>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dr_mode = "host";
+ status = "okay";
+
+ usb-hub@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ reset-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&usb3_0 {
+ status = "okay";
+};
+
+&usb3_1 {
+ fsl,disable-port-power-control;
+ fsl,permanently-attached;
+ status = "okay";
+};
+
+&usb3_phy0 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
+
+&usb3_phy1 {
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ vmmc-supply = <&reg_vdd_3v3>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_ethphy0: ethphy0grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO01__GPIO1_IO01 0x46
+ >;
+ };
+
+ pinctrl_ethphy1: ethphy1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00 0x46
+ >;
+ };
+
+ pinctrl_gpio2: gpio2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x46
+ MX8MP_IOMUXC_SD2_WP__GPIO2_IO20 0x46
+ >;
+ };
+
+ pinctrl_usb_hub: usbhubgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x46
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso b/arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso
new file mode 100644
index 000000000000..a3cba41d2b53
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2023 Kontron Electronics GmbH
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "imx8mp-pinfunc.h"
+
+&{/} {
+ model = "Kontron DL i.MX8MP OSM-S";
+ compatible = "kontron,imx8mp-bl-osm-s", "kontron,imx8mp-osm-s", "fsl,imx8mp";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 50000 0>;
+ brightness-levels = <0 100>;
+ num-interpolated-steps = <100>;
+ default-brightness-level = <100>;
+ };
+
+ panel {
+ compatible = "jenson,bl-jt60050-01a", "panel-lvds";
+ backlight = <&backlight>;
+ data-mapping = "vesa-24";
+ enable-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+ power-supply = <&reg_vcc_panel>;
+ height-mm = <86>;
+ width-mm = <154>;
+
+ panel-timing {
+ clock-frequency = <50000000>;
+ hactive = <1024>;
+ hback-porch = <160>;
+ hfront-porch = <160>;
+ hsync-len = <1>;
+ vactive = <600>;
+ vback-porch = <23>;
+ vfront-porch = <12>;
+ vsync-len = <1>;
+ };
+
+ port {
+ panel_in_lvds0: endpoint {
+ remote-endpoint = <&ldb_lvds_ch0>;
+ };
+ };
+ };
+};
+
+&gpio4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio4>, <&pinctrl_panel_stby>;
+
+ panel-rst-hog {
+ gpio-hog;
+ gpios = <21 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "panel-reset";
+ };
+
+ panel-stby-hog {
+ gpio-hog;
+ gpios = <28 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "panel-standby";
+ };
+};
+
+&i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ touchscreen@5d {
+ compatible = "goodix,gt928";
+ reg = <0x5d>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <6 8>;
+ irq-gpios = <&gpio1 6 0>;
+ AVDD28-supply = <&reg_vcc_panel>;
+ VDDIO-supply = <&reg_vcc_panel>;
+ reset-gpios = <&gpio1 7 0>;
+ };
+};
+
+&lcdif2 {
+ status = "okay";
+};
+
+&ldb_lvds_ch0 {
+ remote-endpoint = <&panel_in_lvds0>;
+};
+
+&lvds_bridge {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_panel_stby: panelstbygrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28 0x19
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-kontron-osm-s.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-kontron-osm-s.dtsi
new file mode 100644
index 000000000000..e0e9f6f7616d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-kontron-osm-s.dtsi
@@ -0,0 +1,908 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2022 Kontron Electronics GmbH
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "imx8mp.dtsi"
+
+/ {
+ model = "Kontron OSM-S i.MX8MP";
+ compatible = "kontron,imx8mp-osm-s", "fsl,imx8mp";
+
+ aliases {
+ rtc0 = &rv3028;
+ rtc1 = &snvs_rtc;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ /*
+ * There are multiple SoM flavors with different DDR sizes.
+ * The smallest is 1GB. For larger sizes the bootloader will
+ * update the reg property.
+ */
+ reg = <0x0 0x40000000 0 0x80000000>;
+ };
+
+ chosen {
+ stdout-path = &uart3;
+ };
+
+ reg_usb1_vbus: regulator-usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usb1_vbus>;
+ gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "VBUS_USB_A";
+ };
+
+ reg_usb2_vbus: regulator-usb2-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usb2_vbus>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "VBUS_USB_B";
+ };
+
+ reg_usdhc2_vcc: regulator-usdhc2-vcc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vcc>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "VCC_SDIO_A";
+ };
+
+ reg_usdhc3_vcc: regulator-usdhc3-vcc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc3_vcc>;
+ gpio = <&gpio3 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "VCC_SDIO_B";
+ };
+
+ reg_vdd_carrier: regulator-vdd-carrier {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_vdd_carrier>;
+ gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "VDD_CARRIER";
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+ };
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+
+ regulator-state-disk {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&reg_vdd_arm>;
+};
+
+&A53_1 {
+ cpu-supply = <&reg_vdd_arm>;
+};
+
+&A53_2 {
+ cpu-supply = <&reg_vdd_arm>;
+};
+
+&A53_3 {
+ cpu-supply = <&reg_vdd_arm>;
+};
+
+&ecspi1 { /* OSM-S SPI_A */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+};
+
+&ecspi2 { /* OSM-S SPI_B */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+};
+
+&flexcan1 { /* OSM-S CAN_A */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+};
+
+&flexcan2 { /* OSM-S CAN_B */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+};
+
+&gpio1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio1>;
+ gpio-line-names = "GPIO_A_0", "GPIO_A_1", "", "",
+ "", "GPIO_A_2", "GPIO_A_3", "GPIO_A_4",
+ "GPIO_A_5", "USB_B_EN", "USB_A_ID", "USB_B_ID",
+ "USB_A_EN", "USB_A_OC","CAM_MCK", "USB_B_OC",
+ "ETH_B_MDC", "ETH_B_MDIO", "ETH_B_TXD3", "ETH_B_TXD2",
+ "ETH_B_TXD1", "ETH_B_TXD0", "ETH_B_TX_EN", "ETH_B_TX_CLK",
+ "ETH_B_RX_DV", "ETH_B_RX_CLK", "ETH_B_RXD0", "ETH_B_RXD1",
+ "ETH_B_RXD2", "ETH_B_RXD3";
+};
+
+&gpio2 {
+ gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "",
+ "SDIO_A_CD", "SDIO_A_CLK", "SDIO_A_CMD", "SDIO_A_D0",
+ "SDIO_A_D1", "SDIO_A_D2", "SDIO_A_D3", "SDIO_A_PWR_EN",
+ "SDIO_A_WP";
+};
+
+&gpio3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio3>;
+ gpio-line-names = "PCIE_WAKE", "PCIE_CLKREQ", "PCIE_A_PERST", "SDIO_B_D5",
+ "SDIO_B_D6", "SDIO_B_D7", "SPI_A_WP", "SPI_A_HOLD",
+ "UART_B_RTS", "UART_B_CTS", "SDIO_B_D0", "SDIO_B_D1",
+ "SDIO_B_D2", "SDIO_B_D3", "SDIO_B_WP", "SDIO_B_D4",
+ "PCIE_SM_ALERT", "SDIO_B_CLK", "SDIO_B_CMD", "GPIO_B_0",
+ "GPIO_B_1", "", "BOOT_SEL0", "BOOT_SEL1",
+ "", "", "SDIO_B_CD", "SDIO_B_PWR_EN",
+ "HDMI_CEC", "HDMI_HPD";
+};
+
+&gpio4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio4>;
+ gpio-line-names = "GPIO_B_5", "GPIO_B_6", "GPIO_B_7", "GPIO_C_0",
+ "ETH_A_MDC", "ETH_A_MDIO", "ETH_A_RXD0", "ETH_A_RXD1",
+ "ETH_A_RXD2", "ETH_A_RXD3", "ETH_A_RX_DV", "ETH_A_RX_CLK",
+ "ETH_A_TXD0", "ETH_A_TXD1", "ETH_A_TXD2", "ETH_A_TXD3",
+ "ETH_A_TX_EN", "ETH_A_TX_CLK", "GPIO_B_3", "GPIO_B_4",
+ "GPIO_B_2", "GPIO_A_6", "CAN_A_TX", "UART_A_CTS",
+ "UART_A_RTS", "CAN_A_RX", "CAN_B_TX", "CAN_B_RX",
+ "GPIO_A_7", "CARRIER_PWR_EN", "I2S_A_DATA_IN", "I2S_LRCLK";
+};
+
+&gpio5 {
+ gpio-line-names = "I2S_BITCLK", "I2S_A_DATA_OUT", "I2S_MCLK", "PWM_2",
+ "PWM_1", "PWM_0", "SPI_A_SCK", "SPI_A_SDO",
+ "SPI_A_SDI", "SPI_A_CS0", "SPI_B_SCK", "SPI_B_SDO",
+ "SPI_B_SDI", "SPI_B_CS0", "I2C_A_SCL", "I2C_A_SDA",
+ "I2C_B_SCL", "I2C_B_SDA", "PCIE_SMCLK", "PCIE_SMDAT",
+ "I2C_CAM_SCL", "I2C_CAM_SDA", "UART_A_RX", "UART_A_TX",
+ "UART_C_RX", "UART_C_TX", "UART_CON_RX", "UART_CON_TX",
+ "UART_B_RX", "UART_B_TX";
+};
+
+&i2c1 { /* OSM-S I2C_A */
+ clock-frequency = <400000>;
+ 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)>;
+};
+
+&i2c2 { /* OSM-S I2C_B */
+ clock-frequency = <400000>;
+ 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)>;
+};
+
+&i2c3 { /* OSM-S PCIe SMDAT/SMCLK */
+ clock-frequency = <400000>;
+ 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)>;
+};
+
+&i2c4 { /* OSM-S I2C_CAM */
+ clock-frequency = <400000>;
+ 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)>;
+};
+
+&i2c5 { /* PMIC, EEPROM, RTC */
+ clock-frequency = <400000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c5>;
+ pinctrl-1 = <&pinctrl_i2c5_gpio>;
+ scl-gpios = <&gpio3 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio3 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ pca9450: pmic@25 {
+ compatible = "nxp,pca9450c";
+ reg = <0x25>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ nxp,i2c-lt-enable;
+
+ regulators {
+ reg_vdd_soc: BUCK1 { /* dual phase with BUCK3 */
+ regulator-name = "+0V8_VDD_SOC (BUCK1)";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <950000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ };
+
+ reg_vdd_arm: BUCK2 {
+ regulator-name = "+0V9_VDD_ARM (BUCK2)";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <950000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ nxp,dvs-run-voltage = <950000>;
+ nxp,dvs-standby-voltage = <850000>;
+ };
+
+ reg_vdd_3v3: BUCK4 {
+ regulator-name = "+3V3 (BUCK4)";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_vdd_1v8: BUCK5 {
+ regulator-name = "+1V8 (BUCK5)";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_nvcc_dram: BUCK6 {
+ regulator-name = "+1V1_NVCC_DRAM (BUCK6)";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_nvcc_snvs: LDO1 {
+ regulator-name = "+1V8_NVCC_SNVS (LDO1)";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_vdda: LDO3 {
+ regulator-name = "+1V8_VDDA (LDO3)";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_nvcc_sd: LDO5 {
+ regulator-name = "NVCC_SD (LDO5)";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+
+ eeprom@50 {
+ compatible = "onnn,n24s64b", "atmel,24c64";
+ reg = <0x50>;
+ pagesize = <32>;
+ size = <8192>;
+ num-addresses = <1>;
+ };
+
+ rv3028: rtc@52 {
+ compatible = "microcrystal,rv3028";
+ reg = <0x52>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rtc>;
+ interrupts-extended = <&gpio3 24 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&pwm1 { /* OSM-S PWM_0 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+};
+
+&pwm2 { /* OSM-S PWM_1 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+};
+
+&pwm3 { /* OSM-S PWM_2 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+};
+
+&sai3 { /* OSM-S I2S_A */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3>;
+};
+
+&uart1 { /* OSM-S UART_A */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+};
+
+&uart2 { /* OSM-S UART_C */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+};
+
+&uart3 { /* OSM-S UART_CON */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+&uart4 { /* OSM-S UART_B */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+};
+
+&usb3_0 { /* OSM-S USB_A */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb1_oc>;
+ fsl,over-current-active-low;
+};
+
+&usb3_1 { /* OSM-S USB_B */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2_oc>;
+ fsl,over-current-active-low;
+};
+
+&usdhc1 { /* eMMC */
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ vmmc-supply = <&reg_vdd_3v3>;
+ vqmmc-supply = <&reg_vdd_1v8>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&usdhc2 { /* OSM-S SDIO_A */
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>, <&pinctrl_usdhc2_wp>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>, <&pinctrl_usdhc2_wp>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>, <&pinctrl_usdhc2_wp>;
+ vmmc-supply = <&reg_usdhc2_vcc>;
+ vqmmc-supply = <&reg_nvcc_sd>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+};
+
+&usdhc3 { /* OSM-S SDIO_B */
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>, <&pinctrl_usdhc3_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>, <&pinctrl_usdhc3_gpio>;
+ vmmc-supply = <&reg_usdhc3_vcc>;
+ vqmmc-supply = <&reg_nvcc_sd>;
+ cd-gpios = <&gpio3 26 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_csi_mck: csimckgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO14__CCM_CLKO1 0x59 /* CAM_MCK */
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_ECSPI1_MISO__ECSPI1_MISO 0x44 /* SPI_A_SDI_(IO0) */
+ MX8MP_IOMUXC_ECSPI1_MOSI__ECSPI1_MOSI 0x44 /* SPI_A_SDO_(IO1) */
+ MX8MP_IOMUXC_ECSPI1_SCLK__ECSPI1_SCLK 0x44 /* SPI_A_SCK */
+ MX8MP_IOMUXC_ECSPI1_SS0__GPIO5_IO09 0x40 /* SPI_A_CS0# */
+ >;
+ };
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 0x44 /* SPI_B_SDI */
+ MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI 0x44 /* SPI_B_SDO */
+ MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK 0x44 /* SPI_B_SCK */
+ MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13 0x40 /* SPI_B_CS0# */
+ >;
+ };
+
+ pinctrl_enet_rgmii: enetrgmiigrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC 0x3 /* ETH_MDC */
+ MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO 0x3 /* ETH_MDIO */
+ MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0 0x91 /* ETH_A_(S)(R)(G)MII_RXD0 */
+ MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1 0x91 /* ETH_A_(S)(R)(G)MII_RXD1 */
+ MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2 0x91 /* ETH_A_(R)(G)MII_RXD2 */
+ MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3 0x91 /* ETH_A_(R)(G)MII_RXD3 */
+ MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC 0x91 /* ETH_A_(R)(G)MII_RX_CLK */
+ MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL 0x91 /* ETH_A_(R)(G)MII_RX_DV(_ER) */
+ MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0 0x1f /* ETH_A_(S)(R)(G)MII_TXD0 */
+ MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1 0x1f /* ETH_A_(S)(R)(G)MII_TXD1 */
+ MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2 0x1f /* ETH_A_(S)(R)(G)MII_TXD2 */
+ MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3 0x1f /* ETH_A_(S)(R)(G)MII_TXD3 */
+ MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC 0x1f /* ETH_A_(R)(G)MII_TX_CLK */
+ MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL 0x1f /* ETH_A_(R)(G)MII_TX_EN(_ER) */
+ >;
+ };
+
+ pinctrl_eqos_rgmii: eqosrgmiigrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x3 /* ETH_B_MDC */
+ MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO 0x3 /* ETH_B_MDIO */
+ MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0 0x91 /* ETH_B_(S)(R)(G)MII_RXD0 */
+ MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1 0x91 /* ETH_B_(S)(R)(G)MII_RXD1 */
+ MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2 0x91 /* ETH_B_(R)(G)MII_RXD2 */
+ MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3 0x91 /* ETH_B_(R)(G)MII_RXD3 */
+ MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x91 /* ETH_B_(R)(G)MII_RX_CLK */
+ MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x91 /* ETH_B_(R)(G)MII_RX_DV(_ER) */
+ MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0 0x1f /* ETH_B_(S)(R)(G)MII_TXD0 */
+ MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1 0x1f /* ETH_B_(S)(R)(G)MII_TXD1 */
+ MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2 0x1f /* ETH_B_(S)(R)(G)MII_TXD2 */
+ MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3 0x1f /* ETH_B_(S)(R)(G)MII_TXD3 */
+ MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x1f /* ETH_B_(R)(G)MII_TX_CLK */
+ MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x1f /* ETH_B_(R)(G)MII_TX_EN(_ER) */
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI2_RXC__CAN1_TX 0x154 /* CAN_A_TX */
+ MX8MP_IOMUXC_SAI2_TXC__CAN1_RX 0x154 /* CAN_A_RX */
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI2_TXD0__CAN2_TX 0x154 /* CAN_B_TX */
+ MX8MP_IOMUXC_SAI2_MCLK__CAN2_RX 0x154 /* CAN_B_RX */
+ >;
+ };
+
+ pinctrl_gpio1: gpio1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00 0x19 /* GPIO_A_0 */
+ MX8MP_IOMUXC_GPIO1_IO01__GPIO1_IO01 0x19 /* GPIO_A_1 */
+ MX8MP_IOMUXC_GPIO1_IO05__GPIO1_IO05 0x19 /* GPIO_A_2 */
+ MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x19 /* GPIO_A_3 */
+ MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07 0x19 /* GPIO_A_4 */
+ MX8MP_IOMUXC_GPIO1_IO08__GPIO1_IO08 0x19 /* GPIO_A_5 */
+ >;
+ };
+
+ pinctrl_gpio3: gpio3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_CE0_B__GPIO3_IO01 0x19 /* GPIO_A_7 */
+ MX8MP_IOMUXC_SAI5_RXFS__GPIO3_IO19 0x19 /* GPIO_B_0 */
+ MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20 0x19 /* GPIO_B_1 */
+ MX8MP_IOMUXC_SAI5_RXD1__GPIO3_IO22 0x19 /* BOOT_SEL0# */
+ MX8MP_IOMUXC_SAI5_RXD2__GPIO3_IO23 0x19 /* BOOT_SEL1# */
+ >;
+ };
+
+ pinctrl_gpio4: gpio4grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_RXFS__GPIO4_IO00 0x19 /* GPIO_B_5 */
+ MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x19 /* GPIO_B_6 */
+ MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02 0x19 /* GPIO_B_7 */
+ MX8MP_IOMUXC_SAI1_RXD1__GPIO4_IO03 0x19 /* GPIO_C_0 */
+ MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18 0x19 /* GPIO_B_3 */
+ MX8MP_IOMUXC_SAI1_TXD7__GPIO4_IO19 0x19 /* GPIO_B_4 */
+ MX8MP_IOMUXC_SAI1_MCLK__GPIO4_IO20 0x19 /* GPIO_B_2 */
+ MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x19 /* GPIO_A_6 */
+ >;
+ };
+
+ pinctrl_hdmi: hdmigrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x19 /* HDMI_HPD */
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x40000084 /* I2C_A_SCL */
+ MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA 0x40000084 /* I2C_A_SDA */
+ >;
+ };
+
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C1_SCL__GPIO5_IO14 0x84 /* I2C_A_SCL */
+ MX8MP_IOMUXC_I2C1_SDA__GPIO5_IO15 0x84 /* I2C_A_SDA */
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x40000084 /* I2C_B_SCL */
+ MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x40000084 /* I2C_B_SDA */
+ >;
+ };
+
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16 0x84 /* I2C_B_SCL */
+ MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x84 /* I2C_B_SDA */
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x40000084 /* PCIe_SMCLK */
+ MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x40000084 /* PCIe_SMDAT */
+ >;
+ };
+
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18 0x84 /* PCIe_SMCLK */
+ MX8MP_IOMUXC_I2C3_SDA__GPIO5_IO19 0x84 /* PCIe_SMDAT */
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C4_SCL__I2C4_SCL 0x40000084 /* I2C_CAM_SCL/CSI_TX_P */
+ MX8MP_IOMUXC_I2C4_SDA__I2C4_SDA 0x40000084 /* I2C_CAM_SDA/CSI_TX_N */
+ >;
+ };
+
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C4_SCL__GPIO5_IO20 0x84 /* I2C_CAM_SCL/CSI_TX_P */
+ MX8MP_IOMUXC_I2C4_SDA__GPIO5_IO21 0x84 /* I2C_CAM_SDA/CSI_TX_N */
+ >;
+ };
+
+ pinctrl_i2c5: i2c5grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXD0__I2C5_SCL 0x40000084
+ MX8MP_IOMUXC_SAI5_MCLK__I2C5_SDA 0x40000084
+ >;
+ };
+
+ pinctrl_i2c5_gpio: i2c5gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXD0__GPIO3_IO21 0x84
+ MX8MP_IOMUXC_SAI5_MCLK__GPIO3_IO25 0x84
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART4_RXD__PCIE_CLKREQ_B 0x19 /* PCIe_CLKREQ# */
+ MX8MP_IOMUXC_NAND_CE1_B__GPIO3_IO02 0x19 /* PCIe_A_PERST# */
+ MX8MP_IOMUXC_NAND_ALE__GPIO3_IO00 0x19 /* PCIe_WAKE# */
+ MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x19 /* PCIe_SM_ALERT */
+ >;
+ };
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO03__GPIO1_IO03 0x1c0
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SPDIF_EXT_CLK__PWM1_OUT 0x6 /* PWM_0 */
+ >;
+ };
+
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SPDIF_RX__PWM2_OUT 0x6 /* PWM_1 */
+ >;
+ };
+
+ pinctrl_pwm3: pwm3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SPDIF_TX__PWM3_OUT 0x6 /* PWM_2 */
+ >;
+ };
+
+ pinctrl_reg_usb1_vbus: regusb1vbusgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x19 /* USB_A_EN */
+ >;
+ };
+
+ pinctrl_reg_usb2_vbus: regusb2vbusgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO09__GPIO1_IO09 0x19 /* USB_B_EN */
+ >;
+ };
+
+ pinctrl_reg_usdhc2_vcc: regusdhc2vccgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x19 /* SDIO_A_PWR_EN */
+ >;
+ };
+
+ pinctrl_reg_usdhc3_vcc: regusdhc3vccgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_HDMI_DDC_SDA__GPIO3_IO27 0x19 /* SDIO_B_PWR_EN */
+ >;
+ };
+
+ pinctrl_reg_vdd_carrier: regvddcarriergrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x19 /* CARRIER_PWR_EN */
+ >;
+ };
+
+ pinctrl_rtc: rtcgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXD3__GPIO3_IO24 0x1c0
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0xd6 /* I2S_A_DATA_IN */
+ MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0xd6 /* I2S_A_DATA_OUT */
+ MX8MP_IOMUXC_SAI3_RXFS__AUDIOMIX_SAI3_RX_DATA01 0xd6 /* I2S_B_DATA_IN */
+ MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_DATA01 0xd6 /* I2S_B_DATA_OUT */
+ MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI3_MCLK 0xd6 /* I2S_MCLK */
+ MX8MP_IOMUXC_NAND_DATA01__AUDIOMIX_SAI3_TX_SYNC 0xd6 /* I2S_LRCLK */
+ MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0xd6 /* I2S_BITCLK */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140 /* UART_A_RX */
+ MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140 /* UART_A_TX */
+ MX8MP_IOMUXC_SAI2_RXD0__UART1_DCE_RTS 0x140 /* UART_A_CTS */
+ MX8MP_IOMUXC_SAI2_TXFS__UART1_DCE_CTS 0x140 /* UART_A_RTS */
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x140 /* UART_C_RX */
+ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x140 /* UART_C_TX */
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART3_RXD__UART3_DCE_RX 0x140 /* UART_CON_RX */
+ MX8MP_IOMUXC_UART3_TXD__UART3_DCE_TX 0x140 /* UART_CON_TX */
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_DATA00__UART4_DCE_RX 0x140 /* UART_B_RX */
+ MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX 0x140 /* UART_B_TX */
+ MX8MP_IOMUXC_NAND_DATA03__UART4_DCE_RTS 0x140 /* UART_B_CTS */
+ MX8MP_IOMUXC_NAND_DATA02__UART4_DCE_CTS 0x140 /* UART_B_RTS */
+ >;
+ };
+
+ pinctrl_usb1_id: usb1idgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x1c4 /* USB_A_ID */
+ >;
+ };
+
+ pinctrl_usb1_oc: usb1ocgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO13__USB1_OTG_OC 0x1c0 /* USB_A_OC# */
+ >;
+ };
+
+ pinctrl_usb2_id: usb2idgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO11__USB2_OTG_ID 0x1c4 /* USB_B_ID */
+ >;
+ };
+
+ pinctrl_usb2_oc: usb2ocgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO15__USB2_OTG_OC 0x1c0 /* USB_B_OC# */
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x190
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d0
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d0
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d0
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d0
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d0
+ MX8MP_IOMUXC_SD1_DATA4__USDHC1_DATA4 0x1d0
+ MX8MP_IOMUXC_SD1_DATA5__USDHC1_DATA5 0x1d0
+ MX8MP_IOMUXC_SD1_DATA6__USDHC1_DATA6 0x1d0
+ MX8MP_IOMUXC_SD1_DATA7__USDHC1_DATA7 0x1d0
+ MX8MP_IOMUXC_SD1_RESET_B__USDHC1_RESET_B 0x141
+ MX8MP_IOMUXC_SD1_STROBE__USDHC1_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x194
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d4
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d4
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d4
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d4
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d4
+ MX8MP_IOMUXC_SD1_DATA4__USDHC1_DATA4 0x1d4
+ MX8MP_IOMUXC_SD1_DATA5__USDHC1_DATA5 0x1d4
+ MX8MP_IOMUXC_SD1_DATA6__USDHC1_DATA6 0x1d4
+ MX8MP_IOMUXC_SD1_DATA7__USDHC1_DATA7 0x1d4
+ MX8MP_IOMUXC_SD1_RESET_B__USDHC1_RESET_B 0x141
+ MX8MP_IOMUXC_SD1_STROBE__USDHC1_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x196
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d6
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d6
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d6
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d6
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d6
+ MX8MP_IOMUXC_SD1_DATA4__USDHC1_DATA4 0x1d6
+ MX8MP_IOMUXC_SD1_DATA5__USDHC1_DATA5 0x1d6
+ MX8MP_IOMUXC_SD1_DATA6__USDHC1_DATA6 0x1d6
+ MX8MP_IOMUXC_SD1_DATA7__USDHC1_DATA7 0x1d6
+ MX8MP_IOMUXC_SD1_RESET_B__USDHC1_RESET_B 0x141
+ MX8MP_IOMUXC_SD1_STROBE__USDHC1_STROBE 0x196
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190 /* SDIO_A_CLK */
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d0 /* SDIO_A_CMD */
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d0 /* SDIO_A_D0 */
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d0 /* SDIO_A_D1 */
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d0 /* SDIO_A_D2 */
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d0 /* SDIO_A_D3 */
+ MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x194 /* SDIO_A_CLK */
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d4 /* SDIO_A_CMD */
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d4 /* SDIO_A_D0 */
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d4 /* SDIO_A_D1 */
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d4 /* SDIO_A_D2 */
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d4 /* SDIO_A_D3 */
+ MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x196 /* SDIO_A_CLK */
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d6 /* SDIO_A_CMD */
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d6 /* SDIO_A_D0 */
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d6 /* SDIO_A_D1 */
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d6 /* SDIO_A_D2 */
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d6 /* SDIO_A_D3 */
+ MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x19 /* SDIO_A_CD# */
+ >;
+ };
+
+ pinctrl_usdhc2_wp: usdhc2wpgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_WP__USDHC2_WP 0x400000d6 /* SDIO_A_WP */
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x190 /* SDIO_B_CLK */
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d0 /* SDIO_B_CMD */
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d0 /* SDIO_B_D0 */
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d0 /* SDIO_B_D1 */
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d0 /* SDIO_B_D2 */
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d0 /* SDIO_B_D3 */
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d0 /* SDIO_B_D4 */
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d0 /* SDIO_B_D5 */
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d0 /* SDIO_B_D6 */
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d0 /* SDIO_B_D7 */
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x194 /* SDIO_B_CLK */
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d4 /* SDIO_B_CMD */
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d4 /* SDIO_B_D0 */
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d4 /* SDIO_B_D1 */
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d4 /* SDIO_B_D2 */
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d4 /* SDIO_B_D3 */
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d4 /* SDIO_B_D4 */
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d4 /* SDIO_B_D5 */
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d4 /* SDIO_B_D6 */
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d4 /* SDIO_B_D7 */
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x196 /* SDIO_B_CLK */
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d6 /* SDIO_B_CMD */
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d6 /* SDIO_B_D0 */
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d6 /* SDIO_B_D1 */
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d6 /* SDIO_B_D2 */
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d6 /* SDIO_B_D3 */
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d6 /* SDIO_B_D4 */
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d6 /* SDIO_B_D5 */
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d6 /* SDIO_B_D6 */
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d6 /* SDIO_B_D7 */
+ >;
+ };
+
+ pinctrl_usdhc3_gpio: usdhc3gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_HDMI_DDC_SCL__GPIO3_IO26 0x19 /* SDIO_B_CD# */
+ MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x19 /* SDIO_B_WP */
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc-eval-carrier.dts b/arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc-eval-carrier.dts
new file mode 100644
index 000000000000..2173a36ff691
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc-eval-carrier.dts
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2024 Kontron Electronics GmbH
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+#include "imx8mp-kontron-smarc.dtsi"
+
+/ {
+ model = "Kontron SMARC Eval Carrier with i.MX8MP";
+ compatible = "kontron,imx8mp-smarc-eval-carrier", "kontron,imx8mp-smarc",
+ "kontron,imx8mp-osm-s", "fsl,imx8mp";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 50000 0>;
+ brightness-levels = <0 100>;
+ num-interpolated-steps = <100>;
+ default-brightness-level = <100>;
+ enable-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+ };
+
+ extcon_usbc: usbc {
+ compatible = "linux,extcon-usb-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb1_id>;
+ id-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&codec_dai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&codec_dai>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,name = "imx8mp-wm8904";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN2L", "Line In Jack",
+ "IN2R", "Line In Jack",
+ "Headphone Jack", "MICBIAS",
+ "IN1L", "Headphone Jack";
+ simple-audio-card,widgets =
+ "Microphone", "Headphone Jack",
+ "Headphone", "Headphone Jack",
+ "Line", "Line In Jack";
+
+ codec_dai: simple-audio-card,codec {
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>;
+ sound-dai = <&wm8904>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai3>;
+ };
+ };
+
+ regulator_can0: can0-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "can0_en";
+ gpio = <&expander_pm_out 6 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ regulator_can1: can1-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "can1_en";
+ gpio = <&expander_pm_out 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&ecspi1 {
+ status = "okay";
+};
+
+&ecspi2 {
+ status = "okay";
+};
+
+&eqos {
+ status = "okay";
+};
+
+&fec {
+ status = "okay";
+};
+
+&flexcan1 {
+ xceiver-supply = <&regulator_can0>;
+ status = "okay";
+};
+
+&flexcan2 {
+ xceiver-supply = <&regulator_can1>;
+ status = "okay";
+};
+
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi>;
+ ddc-i2c-bus = <&i2c3>;
+ status = "okay";
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ expander_pm_out: io-expander@22 {
+ compatible = "nxp,pca9554";
+ reg = <0x22>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "EN_5V0_S0", "EN_3V3_S0", "EN_1V8_S0",
+ "EN_1V5_S0", "EN_12V0_PCIE", "EN_3V3_S5",
+ "CAN0_EN", "CAN1_EN";
+ };
+
+ expander_pm_in: io-expander@24 {
+ compatible = "nxp,pca9554";
+ reg = <0x24>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "PG_5V0_3V3_S0", "PG_5V0_3V3_S5", "PG_1V8_S0",
+ "PG_1V5_S0", "PG_BKLT_5V", "PG_BKLT_12V";
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ wm8904: audio-codec@1a {
+ compatible = "wlf,wm8904";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>;
+ clock-names = "mclk";
+ AVDD-supply = <&reg_vdd_1v8>;
+ CPVDD-supply = <&reg_vdd_1v8>;
+ DBVDD-supply = <&reg_vdd_1v8>;
+ DCVDD-supply = <&reg_vdd_1v8>;
+ MICVDD-supply = <&reg_vdd_3v3>;
+ };
+
+ expander_audio: io-expander@20 {
+ compatible = "nxp,pca9554";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "I2C_SEL_CODEC_LOOPBACK", "FPAH_PRESENCE",
+ "CODEC_OPTION_SW_I2S_HDA", "LINE_IN_JD",
+ "LINE_OUT_JD", "HEADPHONES_JD", "MIC_JD";
+ };
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&lcdif3 {
+ status = "okay";
+};
+
+&pcie_phy {
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>;
+ fsl,clkreq-unsupported;
+ clocks = <&hsio_blk_ctrl>;
+ clock-names = "ref";
+ status = "okay";
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio3 2 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&sai3 {
+ assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
+ assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <24576000>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
+&uart1 {
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart4 {
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ adp-disable;
+ hnp-disable;
+ srp-disable;
+ dr_mode = "otg";
+ extcon = <&extcon_usbc>;
+ usb-role-switch;
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ status = "okay";
+};
+
+&usb3_0 {
+ status = "okay";
+};
+
+&usb3_1 {
+ status = "okay";
+};
+
+&usb3_phy0 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
+
+&usb3_phy1 {
+ status = "okay";
+};
+
+&usdhc2 {
+ vmmc-supply = <&reg_vdd_3v3>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc.dtsi
new file mode 100644
index 000000000000..1e831d9b8a93
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-kontron-smarc.dtsi
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2024 Kontron Electronics GmbH
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include "imx8mp-kontron-osm-s.dtsi"
+
+/ {
+ model = "Kontron SMARC i.MX8MP";
+ compatible = "kontron,imx8mp-smarc", "kontron,imx8mp-osm-s", "fsl,imx8mp";
+
+ leds {
+ compatible = "gpio-leds";
+
+ led1 {
+ label = "led1";
+ gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
+
+&ecspi1 {
+ status = "okay";
+
+ tpm@0 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <0>;
+ spi-max-frequency = <18500000>;
+ };
+};
+
+&eqos { /* Second ethernet (OSM-S ETH_B) */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eqos_rgmii>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy1>;
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-id4f51.e91b";
+ reg = <1>;
+ pinctrl-0 = <&pinctrl_ethphy1>;
+ pinctrl-names = "default";
+ reset-assert-us = <10000>;
+ reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&fec { /* First ethernet (OSM-S ETH_A) */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_rgmii>;
+ phy-connection-type = "rgmii-id";
+ phy-handle = <&ethphy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-id4f51.e91b";
+ reg = <1>;
+ pinctrl-0 = <&pinctrl_ethphy0>;
+ pinctrl-names = "default";
+ reset-assert-us = <10000>;
+ reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+/*
+ * Rename SoM signals according to SMARC module usage:
+ * GPIO_A_2 -> GPIO0
+ * GPIO_A_3 -> GPIO1
+ * GPIO_A_4 -> GPIO2
+ * GPIO_A_5 -> GPIO3
+ * USB_B_EN -> n.a.
+ * USB_B_ID -> n.a.
+ * USB_B_OC -> n.a.
+ */
+&gpio1 {
+ gpio-line-names = "GPIO_A_0", "GPIO_A_1", "", "",
+ "", "GPIO0", "GPIO1", "GPIO2",
+ "GPIO3", "", "USB_A_ID", "",
+ "USB_A_EN", "USB_A_OC","CAM_MCK", "",
+ "ETH_B_MDC", "ETH_B_MDIO", "ETH_B_TXD3", "ETH_B_TXD2",
+ "ETH_B_TXD1", "ETH_B_TXD0", "ETH_B_TX_EN", "ETH_B_TX_CLK",
+ "ETH_B_RX_DV", "ETH_B_RX_CLK", "ETH_B_RXD0", "ETH_B_RXD1",
+ "ETH_B_RXD2", "ETH_B_RXD3";
+};
+
+/*
+ * Rename SoM signals according to SMARC module usage:
+ * SDIO_A_CD -> SDIO_CD
+ * SDIO_A_CLK -> SDIO_CK
+ * SDIO_A_CMD -> SDIO_CMD
+ * SDIO_A_D0 -> SDIO_D0
+ * SDIO_A_D1 -> SDIO_D1
+ * SDIO_A_D2 -> SDIO_D2
+ * SDIO_A_D3 -> SDIO_D3
+ * SDIO_A_PWR_EN -> SDIO_PWR_EN
+ * SDIO_A_WP -> SDIO_WP
+ */
+&gpio2 {
+ gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "",
+ "SDIO_CD", "SDIO_CK", "SDIO_CMD", "SDIO_D0",
+ "SDIO_D1", "SDIO_D2", "SDIO_D3", "SDIO_PWR_EN",
+ "SDIO_WP";
+};
+
+/*
+ * Rename SoM signals according to SMARC module usage:
+ * PCIE_CLKREQ -> PCIE_A_CKREQ
+ * PCIE_A_PERST -> PCIE_A_RST
+ * SDIO_B_D5 -> n.a.
+ * SDIO_B_D6 -> n.a.
+ * SDIO_B_D7 -> n.a.
+ * SPI_A_WP -> n.a.
+ * SPI_A_HOLD -> n.a.
+ * UART_B_RTS -> SER2_RTS
+ * UART_B_CTS -> SER2_CTS
+ * SDIO_B_D0 -> GPIO8
+ * SDIO_B_D1 -> GPIO9
+ * SDIO_B_D2 -> GPIO10
+ * SDIO_B_D3 -> GPIO11
+ * SDIO_B_WP -> n.a.
+ * SDIO_B_D4 -> n.a.
+ * PCIE_SM_ALERT -> SMB_ALERT
+ * SDIO_B_CLK -> GPIO6
+ * SDIO_B_CMD -> GPIO7
+ * GPIO_B_0 -> LCD0_BKLT_EN
+ * GPIO_B_1 -> LCD1_BKLT_EN
+ * BOOT_SEL0 -> BOOT_SEL2
+ * SDIO_B_CD -> n.a.
+ * SDIO_B_PWR_EN -> n.a.
+ * HDMI_CEC -> n.a.
+ * SDIO_B_PWR_EN -> n.a.
+ */
+&gpio3 {
+ pinctrl-0 = <&pinctrl_gpio3>, <&pinctrl_gpio3_smarc>;
+ gpio-line-names = "PCIE_WAKE", "PCIE_A_CKREQ", "PCIE_A_RST", "",
+ "", "", "", "",
+ "SER2_RTS", "SER2_CTS", "GPIO8", "GPIO9",
+ "GPIO10", "GPIO11", "", "",
+ "SMB_ALERT", "GPIO6", "GPIO7", "LCD0_BKLT_EN",
+ "LCD1_BKLT_EN", "", "BOOT_SEL2", "BOOT_SEL1",
+ "", "", "", "",
+ "", "HDMI_HPD";
+};
+
+/*
+ * Rename SoM signals according to SMARC module usage:
+ * GPIO_B_5 -> n.a.
+ * GPIO_B_6 -> n.a.
+ * GPIO_B_7 -> n.a.
+ * GPIO_C_0 -> LED
+ * GPIO_B_3 -> ETH2_INT
+ * GPIO_B_4 -> USB_HUB_RST
+ * GPIO_B_2 -> ETH1_INT
+ * GPIO_A_6 -> GPIO4
+ * CAN_A_TX -> CAN0_TX
+ * UART_A_CTS -> SER0_CTS
+ * UART_A_RTS -> SER0_RTS
+ * CAN_A_RX -> CAN0_RX
+ * CAN_B_TX -> CAN1_TX
+ * CAN_B_RX -> CAN1_RX
+ * GPIO_A_7 -> TEST
+ * I2S_A_DATA_IN -> I2S0_SDIN
+ * I2S_LRCLK -> I2S0_LRCK
+ */
+&gpio4 {
+ gpio-line-names = "", "", "", "LED",
+ "ETH_A_MDC", "ETH_A_MDIO", "ETH_A_RXD0", "ETH_A_RXD1",
+ "ETH_A_RXD2", "ETH_A_RXD3", "ETH_A_RX_DV", "ETH_A_RX_CLK",
+ "ETH_A_TXD0", "ETH_A_TXD1", "ETH_A_TXD2", "ETH_A_TXD3",
+ "ETH_A_TX_EN", "ETH_A_TX_CLK", "ETH2_INT", "USB_HUB_RST",
+ "ETH1_INT", "GPIO4", "CAN0_TX", "SER0_CTS",
+ "SER0_RTS", "CAN0_RX", "CAN1_TX", "CAN1_RX",
+ "TEST", "CARRIER_PWR_EN", "I2S0_SDIN", "I2S0_LRCK";
+};
+
+/*
+ * Rename SoM signals according to SMARC module usage:
+ * I2S_BITCLK -> I2S0_CK
+ * I2S_A_DATA_OUT -> I2S0_SDOUT
+ * I2S_MCLK -> AUDIO_MCK
+ * PWM_2 -> GPIO5
+ * PWM_1 -> LCD1_BKLT_PWM
+ * PWM_0 -> LCD0_BKLT_PWM
+ * SPI_A_SCK -> SPI0_CK
+ * SPI_A_SDO -> SPI0_DO
+ * SPI_A_SDI -> SPI0_DIN
+ * SPI_A_CS0 -> SPI0_CS0
+ * SPI_B_SCK -> ESPI_CK
+ * SPI_B_SDO -> ESPI_IO_0
+ * SPI_B_SDI -> ESPI_IO_1
+ * SPI_B_CS0 -> ESPI_CS0
+ * I2C_A_SCL -> I2C_PM_CK
+ * I2C_A_SDA -> I2C_PM_DAT
+ * I2C_B_SCL -> I2C_GP_CK
+ * I2C_B_SDA -> I2C_GP_DAT
+ * PCIE_SMCLK -> HDMI_CTRL_CK
+ * PCIE_SMDAT -> HDMI_CTRL_DAT
+ * I2C_CAM_SCL -> I2C_CAM1_CK
+ * I2C_CAM_SDA -> I2C_CAM1_DAT
+ * UART_A_RX -> SER0_RX
+ * UART_A_TX -> SER0_TX
+ * UART_C_RX -> SER3_RX
+ * UART_C_TX -> SER3_TX
+ * UART_CON_RX -> SER1_RX
+ * UART_CON_TX -> SER1_TX
+ * UART_B_RX -> SER2_RX
+ * UART_B_TX -> SER2_TX
+ */
+&gpio5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio5_smarc>;
+ gpio-line-names = "I2S0_CK", "I2S0_SDOUT", "AUDIO_MCK", "GPIO5",
+ "LCD1_BKLT_PWM", "LCD0_BKLT_PWM", "SPI0_CK", "SPI0_DO",
+ "SPI0_DIN", "SPI0_CS0", "ESPI_CK", "ESPI_IO_0",
+ "ESPI_IO_1", "ESPI_CS0", "I2C_PM_CK", "I2C_PM_DAT",
+ "I2C_GP_CK", "I2C_GP_DAT", "HDMI_CTRL_CK", "HDMI_CTRL_DAT",
+ "I2C_CAM1_CK", "I2C_CAM1_DAT", "SER0_RX", "SER0_TX",
+ "SER3_RX", "SER3_TX", "SER1_RX", "SER1_TX",
+ "SER2_RX", "SER2_TX";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb-hub@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ reset-gpios = <&gpio4 19 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&usb3_1 {
+ fsl,disable-port-power-control;
+ fsl,permanently-attached;
+};
+
+&iomuxc {
+ pinctrl_ethphy0: ethphy0grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO01__GPIO1_IO01 0x46
+ >;
+ };
+
+ pinctrl_ethphy1: ethphy1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00 0x46
+ >;
+ };
+
+ pinctrl_gpio3_smarc: gpio3smarcgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_DATA04__GPIO3_IO10 0x1d0 /* SMARC GPIO8 */
+ MX8MP_IOMUXC_NAND_DATA05__GPIO3_IO11 0x1d0 /* SMARC GPIO9 */
+ MX8MP_IOMUXC_NAND_DATA06__GPIO3_IO12 0x1d0 /* SMARC GPIO10 */
+ MX8MP_IOMUXC_NAND_DATA07__GPIO3_IO13 0x1d0 /* SMARC GPIO11 */
+ MX8MP_IOMUXC_NAND_WE_B__GPIO3_IO17 0x190 /* SMARC GPIO6 */
+ MX8MP_IOMUXC_NAND_WP_B__GPIO3_IO18 0x1d0 /* SMARC GPIO7 */
+ >;
+ };
+
+ pinctrl_gpio5_smarc: gpio5smarcgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SPDIF_RX__GPIO5_IO04 0x1d0 /* SMARC GPIO5 */
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-navqp.dts b/arch/arm64/boot/dts/freescale/imx8mp-navqp.dts
index 5fd1614982cd..4a4f7c1adc23 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-navqp.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-navqp.dts
@@ -18,6 +18,18 @@
stdout-path = &uart2;
};
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ label = "J15";
+ type = "d";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_out>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -85,6 +97,28 @@
};
};
+&hdmi_pvi {
+ status = "okay";
+};
+
+&hdmi_tx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi>;
+ status = "okay";
+
+ ports {
+ port@1 {
+ hdmi_tx_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+ };
+ };
+};
+
+&hdmi_tx_phy {
+ status = "okay";
+};
+
&i2c1 {
clock-frequency = <400000>;
pinctrl-names = "default";
@@ -213,6 +247,10 @@
};
};
+&lcdif3 {
+ status = "okay";
+};
+
&uart2 {
/* console */
pinctrl-names = "default";
@@ -279,6 +317,15 @@
>;
};
+ pinctrl_hdmi: hdmigrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_HDMI_DDC_SCL__HDMIMIX_HDMI_SCL 0x1c2
+ MX8MP_IOMUXC_HDMI_DDC_SDA__HDMIMIX_HDMI_SDA 0x1c2
+ MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x10
+ MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x10
+ >;
+ };
+
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c3
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-som.dtsi
new file mode 100644
index 000000000000..5da0f1b3ed8a
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-som.dtsi
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2023 Boundary Devices
+ * Copyright 2024 Silicon Signals Pvt. Ltd.
+ *
+ * Author : Bhavin Sharma <bhavin.sharma@siliconsignals.io>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "imx8mp.dtsi"
+
+/ {
+ model = "Boundary Device Nitrogen8MP SMARC SoM";
+ compatible = "boundary,imx8mp-nitrogen-smarc-som", "fsl,imx8mp";
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_led>;
+
+ led-0 {
+ function = LED_FUNCTION_POWER;
+ gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_1 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_2 {
+ cpu-supply = <&buck2>;
+};
+
+&A53_3 {
+ cpu-supply = <&buck2>;
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic@25 {
+ compatible = "nxp,pca9450c";
+ reg = <0x25>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
+
+ regulators {
+ buck1: BUCK1 {
+ regulator-name = "BUCK1";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <2187500>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ };
+
+ buck2: BUCK2 {
+ regulator-name = "BUCK2";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <2187500>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <3125>;
+ nxp,dvs-run-voltage = <950000>;
+ nxp,dvs-standby-voltage = <850000>;
+ };
+
+ buck4: BUCK4 {
+ regulator-name = "BUCK4";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5: BUCK5 {
+ regulator-name = "BUCK5";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6: BUCK6 {
+ regulator-name = "BUCK6";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1: LDO1 {
+ regulator-name = "LDO1";
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2: LDO2 {
+ regulator-name = "LDO2";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3: LDO3 {
+ regulator-name = "LDO3";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4: LDO4 {
+ regulator-name = "LDO4";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo5: LDO5 {
+ regulator-name = "LDO5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c6 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c6>;
+ status = "okay";
+
+ mcp23018: gpio@20 {
+ compatible = "microchip,mcp23018";
+ gpio-controller;
+ #gpio-cells = <0x2>;
+ reg = <0x20>;
+ interrupts-extended = <&gpio4 22 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <0x2>;
+ microchip,irq-mirror;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mcp23018>;
+ reset-gpios = <&gpio4 27 GPIO_ACTIVE_LOW>;
+ };
+};
+
+/* Console */
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+/* SD-card */
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+/* eMMC */
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_gpio_led: gpioledgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c3
+ MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c6: i2c6grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXFS__I2C6_SCL 0x400001c3
+ MX8MP_IOMUXC_SAI5_RXC__I2C6_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_mcp23018: mcp23018grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x1c0
+ MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x100
+ >;
+ };
+
+ pinctrl_pmic: pmicgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 0x1c0
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x40
+ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x40
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x10
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x150
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x150
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x150
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x150
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x150
+ MX8MP_IOMUXC_SD1_DATA4__USDHC1_DATA4 0x150
+ MX8MP_IOMUXC_SD1_DATA5__USDHC1_DATA5 0x150
+ MX8MP_IOMUXC_SD1_DATA6__USDHC1_DATA6 0x150
+ MX8MP_IOMUXC_SD1_DATA7__USDHC1_DATA7 0x150
+ MX8MP_IOMUXC_SD1_STROBE__USDHC1_STROBE 0x10
+ MX8MP_IOMUXC_SD1_RESET_B__USDHC1_RESET_B 0x140
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x14
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x154
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x154
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x154
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x154
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x154
+ MX8MP_IOMUXC_SD1_DATA4__USDHC1_DATA4 0x154
+ MX8MP_IOMUXC_SD1_DATA5__USDHC1_DATA5 0x154
+ MX8MP_IOMUXC_SD1_DATA6__USDHC1_DATA6 0x154
+ MX8MP_IOMUXC_SD1_DATA7__USDHC1_DATA7 0x154
+ MX8MP_IOMUXC_SD1_STROBE__USDHC1_STROBE 0x14
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x12
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x152
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x152
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x152
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x152
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x152
+ MX8MP_IOMUXC_SD1_DATA4__USDHC1_DATA4 0x152
+ MX8MP_IOMUXC_SD1_DATA5__USDHC1_DATA5 0x152
+ MX8MP_IOMUXC_SD1_DATA6__USDHC1_DATA6 0x152
+ MX8MP_IOMUXC_SD1_DATA7__USDHC1_DATA7 0x152
+ MX8MP_IOMUXC_SD1_STROBE__USDHC1_STROBE 0x12
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d0
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d0
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d0
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d0
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x194
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d4
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d4
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d4
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d4
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d4
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x196
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d6
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d6
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d6
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d6
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d6
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0x140
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-universal-board.dts b/arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-universal-board.dts
new file mode 100644
index 000000000000..46b243218dc8
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-nitrogen-smarc-universal-board.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2023 Boundary Devices
+ * Copyright 2024 Silicon Signals Pvt. Ltd.
+ *
+ * Author : Bhavin Sharma <bhavin.sharma@siliconsignals.io>
+ */
+
+/dts-v1/;
+
+#include "imx8mp-nitrogen-smarc-som.dtsi"
+
+/ {
+ model = "Boundary Device Nitrogen8MP Universal SMARC Carrier Board";
+ compatible = "boundary,imx8mp-nitrogen-smarc-universal-board",
+ "boundary,imx8mp-nitrogen-smarc-som", "fsl,imx8mp";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts
index 50debe821c42..436152308642 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/phy/phy-imx8-pcie.h>
#include <dt-bindings/leds/leds-pca9532.h>
#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/thermal/thermal.h>
#include "imx8mp-phycore-som.dtsi"
/ {
@@ -32,6 +33,16 @@
pwms = <&pwm3 0 50000 0>;
};
+ fan0: fan {
+ compatible = "gpio-fan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fan>;
+ gpio-fan,speed-map = <0 0
+ 13000 1>;
+ gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
+ #cooling-cells = <2>;
+ };
+
panel1_lvds: panel-lvds {
compatible = "edt,etml1010g3dra";
backlight = <&backlight_lvds>;
@@ -111,6 +122,25 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
+
+ thermal-zones {
+ soc-thermal {
+ trips {
+ active1: trip2 {
+ temperature = <60000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map1 {
+ trip = <&active1>;
+ cooling-device = <&fan0 1 THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
};
/* TPM */
@@ -218,6 +248,18 @@
};
};
+&media_blk_ctrl {
+ /*
+ * The LVDS panel on this device uses 72.4 MHz pixel clock,
+ * set IMX8MP_VIDEO_PLL1 to 72.4 * 7 = 506.8 MHz so the LDB
+ * serializer and LCDIFv3 scanout engine can reach accurate
+ * pixel clock of exactly 72.4 MHz.
+ */
+ assigned-clock-rates = <500000000>, <200000000>,
+ <0>, <0>, <500000000>,
+ <506800000>;
+};
+
&snvs_pwrkey {
status = "okay";
};
@@ -322,15 +364,16 @@
&gpio1 {
gpio-line-names = "", "", "X_PMIC_WDOG_B", "",
- "PMIC_SD_VSEL", "", "", "", "", "",
- "", "", "USB1_OTG_PWR", "", "", "X_nETHPHY_INT";
+ "PMIC_SD_VSEL", "", "", "", "PCIe_nPERST", "LVDS1REG_EN",
+ "PCIe_nWAKE", "PCIe_nCLKREQ", "USB1_OTG_PWR", "",
+ "PCIe_nW_DISABLE";
};
&gpio2 {
gpio-line-names = "", "", "", "",
"", "", "", "", "", "",
"", "", "X_SD2_CD_B", "", "", "",
- "", "", "", "SD2_RESET_B";
+ "", "", "", "SD2_RESET_B", "LVDS1_BL_EN";
};
&gpio3 {
@@ -344,7 +387,12 @@
gpio-line-names = "", "", "", "",
"", "", "", "", "", "",
"", "", "", "", "", "",
- "", "", "X_PMIC_IRQ_B", "", "nENET0_INT_PWDN";
+ "", "", "X_PMIC_IRQ_B", "nRTC_INT", "nENET0_INT_PWDN";
+};
+
+&gpio5 {
+ gpio-line-names = "", "", "", "",
+ "", "", "", "", "", "X_ECSPI1_SSO";
};
&iomuxc {
@@ -377,6 +425,12 @@
>;
};
+ pinctrl_fan: fan0grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SPDIF_RX__GPIO5_IO04 0x16
+ >;
+ };
+
pinctrl_flexcan1: flexcan1grp {
fsl,pins = <
MX8MP_IOMUXC_SAI5_RXD2__CAN1_RX 0x154
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
index a5ecdca8bc0e..04f724c6ec21 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
@@ -209,9 +209,7 @@
};
&gpio1 {
- gpio-line-names = "", "", "X_PMIC_WDOG_B", "",
- "", "", "", "", "", "",
- "", "", "", "", "", "X_nETHPHY_INT";
+ gpio-line-names = "", "", "X_PMIC_WDOG_B";
};
&gpio4 {
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts b/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts
index 3c2efdc59bfa..30962922b361 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts
@@ -71,6 +71,7 @@
assigned-clock-rates = <500000000>, <200000000>, <0>,
/* IMX8MP_CLK_MEDIA_DISP2_PIX = pixelclk of lvds panel */
<68900000>,
+ <500000000>,
/* IMX8MP_VIDEO_PLL1 = IMX8MP_CLK_MEDIA_LDB * 2 */
<964600000>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi
index 6c75a5ecf56b..10713c34ff39 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi
@@ -11,6 +11,8 @@
/ {
aliases {
ethernet0 = &eqos;
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
};
memory@40000000 {
@@ -280,7 +282,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
index d765b7972841..6daa2313f879 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
@@ -25,6 +25,8 @@
ethernet4 = &lan3;
ethernet5 = &lan4;
ethernet6 = &lan5;
+ rtc0 = &gsc_rtc;
+ rtc1 = &snvs_rtc;
};
chosen {
@@ -299,7 +301,7 @@
&gpio3 {
gpio-line-names =
"", "", "", "", "", "", "m2_rst", "",
- "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "m2_gpio10", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "";
};
@@ -481,7 +483,7 @@
pagesize = <16>;
};
- rtc@68 {
+ gsc_rtc: rtc@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
@@ -816,6 +818,7 @@
MX8MP_IOMUXC_SD2_CMD__GPIO2_IO14 0x40000150 /* PCIE3_WDIS# */
MX8MP_IOMUXC_SD2_DATA3__GPIO2_IO18 0x40000150 /* PCIE2_WDIS# */
MX8MP_IOMUXC_NAND_DATA00__GPIO3_IO06 0x40000040 /* M2SKT_RST# */
+ MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x40000040 /* M2SKT_GPIO10 */
MX8MP_IOMUXC_SAI3_TXD__GPIO5_IO01 0x40000104 /* UART_TERM */
MX8MP_IOMUXC_SAI3_TXFS__GPIO4_IO31 0x40000104 /* UART_RS485 */
MX8MP_IOMUXC_SAI3_TXC__GPIO5_IO00 0x40000104 /* UART_HALF */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx.dtsi
index 0d40cb0f05f6..f90b293c85fc 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx.dtsi
@@ -104,6 +104,16 @@
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
+ accelerometer@19 {
+ compatible = "st,lis2de12";
+ reg = <0x19>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_accel>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ st,drdy-int-pin = <1>;
+ };
+
eeprom@52 {
compatible = "atmel,24c32";
reg = <0x52>;
@@ -204,6 +214,12 @@
>;
};
+ pinctrl_accel: accelgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_ECSPI1_MISO__GPIO5_IO08 0x159
+ >;
+ };
+
pinctrl_gpio_leds: gpioledgrp {
fsl,pins = <
MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x6 /* LEDG */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx-2x.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx-2x.dts
new file mode 100644
index 000000000000..597813308630
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx-2x.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include "imx8mp.dtsi"
+#include "imx8mp-venice-gw702x.dtsi"
+#include "imx8mp-venice-gw82xx.dtsi"
+
+/ {
+ model = "Gateworks Venice GW82xx-2x i.MX8MP Development Kit";
+ compatible = "gateworks,imx8mp-gw82xx-2x", "fsl,imx8mp";
+
+ chosen {
+ stdout-path = &uart2;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx.dtsi
new file mode 100644
index 000000000000..2b86cc62a41a
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw82xx.dtsi
@@ -0,0 +1,533 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+
+/ {
+ aliases {
+ ethernet1 = &eth1;
+ fsa1 = &fsa0;
+ fsa2 = &fsa1;
+ };
+
+ led-controller {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+
+ led-0 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ pcie0_refclk: clock-pcie0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ };
+
+ pps {
+ compatible = "pps-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pps>;
+ gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>;
+ };
+
+ reg_usb2_vbus: regulator-usb2 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usb2_en>;
+ regulator-name = "usb2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 12 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2_vmmc>;
+ regulator-name = "VDD_3V3_SD";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ off-on-delay-us = <12000>;
+ startup-delay-us = <100>;
+ };
+};
+
+&ecspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi2>;
+ cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>, /* CS0 onboard TPM */
+ <&gpio5 13 GPIO_ACTIVE_LOW>, /* CS1 off-board J32 SPI */
+ <&gpio1 12 GPIO_ACTIVE_LOW>, /* CS3 off-board J52 FSA1 */
+ <&gpio4 26 GPIO_ACTIVE_LOW>; /* CS2 off-board J51 FSA2 */
+ status = "okay";
+
+ tpm@0 {
+ compatible = "atmel,attpm20p", "tcg,tpm_tis-spi";
+ reg = <0x0>;
+ spi-max-frequency = <10000000>;
+ };
+};
+
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can2>;
+ status = "okay";
+};
+
+&gpio1 {
+ gpio-line-names =
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "fsa2_gpio1", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ "", "", "", "",
+ "", "", "", "",
+ "dio1", "fsa1_gpio2", "", "dio0",
+ "", "", "", "",
+ "", "", "", "",
+ "", "", "rs485_en", "rs485_term",
+ "fsa2_gpio2", "fsa1_gpio1", "", "rs485_half",
+ "", "", "", "";
+};
+
+&i2c2 {
+ accelerometer@19 {
+ compatible = "st,lis2de12";
+ reg = <0x19>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_accel>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ st,drdy-int-pin = <1>;
+ };
+
+ magnetometer@1e {
+ compatible = "st,lis2mdl";
+ reg = <0x1e>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mag>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&i2c3 {
+ i2c-mux@70 {
+ compatible = "nxp,pca9548";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* J30 */
+ fsa1: i2c@0 {
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fsa2i2c>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio@20 {
+ compatible = "nxp,pca9555";
+ reg = <0x20>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ eeprom@54 {
+ compatible = "atmel,24c02";
+ reg = <0x54>;
+ pagesize = <16>;
+ };
+
+ eeprom@55 {
+ compatible = "atmel,24c02";
+ reg = <0x55>;
+ pagesize = <16>;
+ };
+ };
+
+ /* J29 */
+ fsa0: i2c@1 {
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fsa1i2c>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio@20 {
+ compatible = "nxp,pca9555";
+ reg = <0x20>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <14 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ eeprom@54 {
+ compatible = "atmel,24c02";
+ reg = <0x54>;
+ pagesize = <16>;
+ };
+
+ eeprom@55 {
+ compatible = "atmel,24c02";
+ reg = <0x55>;
+ pagesize = <16>;
+ };
+ };
+
+ /* J33 */
+ i2c@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&pcie_phy {
+ clocks = <&pcie0_refclk>;
+ clock-names = "ref";
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
+ fsl,clkreq-unsupported;
+ status = "okay";
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie0>;
+ reset-gpio = <&gpio4 29 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ pcie@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ pcie@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ pcie@7,0 {
+ reg = <0x3800 0 0 0 0>;
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ eth1: ethernet@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ local-mac-address = [00 00 00 00 00 00];
+ };
+ };
+ };
+ };
+};
+
+/* GPS */
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+/* RS232 */
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+/* USB1 - FSA1 */
+&usb3_0 {
+ fsl,permanently-attached;
+ fsl,disable-port-power-control;
+ status = "okay";
+};
+
+&usb3_phy0 {
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* USB2 - USB3.0 Hub */
+&usb3_1 {
+ fsl,permanently-attached;
+ fsl,disable-port-power-control;
+ status = "okay";
+};
+
+&usb3_phy1 {
+ vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/* SDIO 1.8V */
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+};
+
+/* microSD */
+&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>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>; /* CD is active high */
+ bus-width = <4>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_RXD6__GPIO4_IO08 0x40000146 /* DIO1 */
+ MX8MP_IOMUXC_SAI1_TXC__GPIO4_IO11 0x40000146 /* DIO0 */
+ MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x40000106 /* RS485_HALF */
+ MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x40000106 /* RS485_EN */
+ MX8MP_IOMUXC_SAI2_RXD0__GPIO4_IO23 0x40000106 /* RS485_TERM */
+ >;
+ };
+
+ pinctrl_accel: accelgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x150 /* IRQ# */
+ >;
+ };
+
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SPDIF_TX__CAN1_TX 0x154
+ MX8MP_IOMUXC_SPDIF_RX__CAN1_RX 0x154
+ >;
+ };
+
+ pinctrl_can2: can2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXD3__CAN2_TX 0x154
+ MX8MP_IOMUXC_SAI5_MCLK__CAN2_RX 0x154
+ >;
+ };
+
+ pinctrl_gpio_leds: gpioledgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x6 /* LEDG */
+ MX8MP_IOMUXC_SAI1_RXD3__GPIO4_IO05 0x6 /* LEDR */
+ >;
+ };
+
+ pinctrl_fsa1i2c: fsa1i2cgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_TXD2__GPIO4_IO14 0x1d0 /* FSA1_ALERT# */
+ MX8MP_IOMUXC_SAI2_TXC__GPIO4_IO25 0x400001d0 /* FSA1_GPIO1 */
+ MX8MP_IOMUXC_SAI1_RXD7__GPIO4_IO09 0x400001d0 /* FSA1_GPIO2 */
+ >;
+ };
+
+ pinctrl_fsa2i2c: fsa2i2cgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_RXD2__GPIO4_IO04 0x1d0 /* FSA2_ALERT# */
+ MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x400001d0 /* FSA2_GPIO1 */
+ MX8MP_IOMUXC_SAI2_TXFS__GPIO4_IO24 0x400001d0 /* FSA2_GPIO2 */
+ >;
+ };
+
+ pinctrl_mag: maggrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28 0x140 /* IRQ# */
+ >;
+ };
+
+ pinctrl_pcie0: pcie0grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x106 /* PERST# */
+ >;
+ };
+
+ pinctrl_pps: ppsgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_RXD1__GPIO4_IO03 0x146
+ >;
+ };
+
+ pinctrl_reg_usb2_en: regusb2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI1_TXD0__GPIO4_IO12 0x146 /* USBHUB_RST# */
+ >;
+ };
+
+ pinctrl_spi2: spi2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK 0xd0
+ MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI 0xd0
+ MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 0xd0
+ MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13 0x140 /* J32_CS */
+ MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x140 /* TPM_CS */
+ MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x140 /* FSA1_CS */
+ MX8MP_IOMUXC_SAI2_TXD0__GPIO4_IO26 0x140 /* FSA2_CS */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140
+ MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART4_RXD__UART4_DCE_RX 0x140
+ MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x190
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d0
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d0
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d0
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d0
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x194
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d4
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d4
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d4
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d4
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d4
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x196
+ MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d6
+ MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d6
+ MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d6
+ MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d6
+ MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d6
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d0
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d0
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d0
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d0
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d0
+ MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x194
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d4
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d4
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d4
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d4
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d4
+ MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x196
+ MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d6
+ MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d6
+ MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d6
+ MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d6
+ MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d6
+ MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_vmmc: usdhc2-vmmc-grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x1c4
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi
new file mode 100644
index 000000000000..db1b4ee7728c
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi
@@ -0,0 +1,512 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ *
+ * Common dtsi for Verdin IMX8MP SoM on Ivy carrier board
+ *
+ * https://www.toradex.com/computer-on-modules/verdin-arm-family/nxp-imx-8m-plus
+ * https://www.toradex.com/products/carrier-board/ivy-carrier-board
+ */
+
+#include <dt-bindings/mux/mux.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+ /* AIN1 Voltage w/o AIN1_MODE gpio control */
+ ain1_voltage_unmanaged: voltage-divider-ain1 {
+ compatible = "voltage-divider";
+ #io-channel-cells = <1>;
+ io-channels = <&ivy_adc1 0>;
+ full-ohms = <19>;
+ output-ohms = <1>;
+ };
+
+ /* AIN1 Current w/o AIN1_MODE gpio control */
+ ain1_current_unmanaged: current-sense-shunt-ain1 {
+ compatible = "current-sense-shunt";
+ #io-channel-cells = <0>;
+ io-channels = <&ivy_adc1 1>;
+ shunt-resistor-micro-ohms = <100000000>;
+ };
+
+ /* AIN1_MODE - SODIMM 216 */
+ ain1_mode_mux_ctrl: mux-controller-0 {
+ compatible = "gpio-mux";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio5>;
+ #mux-control-cells = <0>;
+ mux-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ ain1-voltage {
+ compatible = "io-channel-mux";
+ channels = "ain1_voltage", "";
+ io-channels = <&ain1_voltage_unmanaged 0>;
+ io-channel-names = "parent";
+ mux-controls = <&ain1_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ ain1-current {
+ compatible = "io-channel-mux";
+ channels = "", "ain1_current";
+ io-channels = <&ain1_current_unmanaged>;
+ io-channel-names = "parent";
+ mux-controls = <&ain1_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ /* AIN2 Voltage w/o AIN2_MODE gpio control */
+ ain2_voltage_unmanaged: voltage-divider-ain2 {
+ compatible = "voltage-divider";
+ #io-channel-cells = <1>;
+ io-channels = <&ivy_adc2 0>;
+ full-ohms = <19>;
+ output-ohms = <1>;
+ };
+
+ /* AIN2 Current w/o AIN2_MODE gpio control */
+ ain2_current_unmanaged: current-sense-shunt-ain2 {
+ compatible = "current-sense-shunt";
+ #io-channel-cells = <0>;
+ io-channels = <&ivy_adc2 1>;
+ shunt-resistor-micro-ohms = <100000000>;
+ };
+
+ /* AIN2_MODE - SODIMM 218 */
+ ain2_mode_mux_ctrl: mux-controller-1 {
+ compatible = "gpio-mux";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio6>;
+ #mux-control-cells = <0>;
+ mux-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+ };
+
+ ain2-voltage {
+ compatible = "io-channel-mux";
+ channels = "ain2_voltage", "";
+ io-channels = <&ain2_voltage_unmanaged 0>;
+ io-channel-names = "parent";
+ mux-controls = <&ain2_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ ain2-current {
+ compatible = "io-channel-mux";
+ channels = "", "ain2_current";
+ io-channels = <&ain2_current_unmanaged>;
+ io-channel-names = "parent";
+ mux-controls = <&ain2_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ivy_leds>;
+
+ /* D7 Blue - SODIMM 30 - LEDs.GPIO1 */
+ led-0 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D7 Green - SODIMM 32 - LEDs.GPIO2 */
+ led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D7 Red - SODIMM 34 - LEDs.GPIO3 */
+ led-2 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Blue - SODIMM 36 - LEDs.GPIO4 */
+ led-3 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Green - SODIMM 54 - LEDs.GPIO5 */
+ led-4 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&gpio3 1 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Red - SODIMM 44 - LEDs.GPIO6 */
+ led-5 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D9 Blue - SODIMM 46 - LEDs.GPIO7 */
+ led-6 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <3>;
+ gpios = <&gpio5 01 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D9 Red - SODIMM 48 - LEDs.GPIO8 */
+ led-7 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <3>;
+ gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ reg_3v2_ain1: regulator-3v2-ain1 {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3200000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-name = "+3V2_AIN1";
+ };
+
+ reg_3v2_ain2: regulator-3v2-ain2 {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3200000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-name = "+3V2_AIN2";
+ };
+
+ /* Ivy Power Supply Input Voltage */
+ ivy-input-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_1 */
+ io-channels = <&verdin_som_adc 7>;
+ full-ohms = <204700>; /* 200k + 4.7k */
+ output-ohms = <4700>;
+ };
+
+ ivy-5v-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_2 */
+ io-channels = <&verdin_som_adc 6>;
+ full-ohms = <39000>; /* 27k + 12k */
+ output-ohms = <12000>;
+ };
+
+ ivy-3v3-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_3 */
+ io-channels = <&verdin_som_adc 5>;
+ full-ohms = <54000>; /* 27k + 27k */
+ output-ohms = <27000>;
+ };
+
+ ivy-1v8-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_4 */
+ io-channels = <&verdin_som_adc 4>;
+ full-ohms = <39000>; /* 12k + 27k */
+ output-ohms = <27000>;
+ };
+};
+
+/* Verdin SPI_1 */
+&ecspi1 {
+ pinctrl-0 = <&pinctrl_ecspi1>,
+ <&pinctrl_gpio1>,
+ <&pinctrl_gpio4>;
+ cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>,
+ <&gpio1 0 GPIO_ACTIVE_LOW>,
+ <&gpio1 6 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ tpm@1 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <1>;
+ spi-max-frequency = <18500000>;
+ };
+
+ fram@2 {
+ compatible = "fujitsu,mb85rs256", "atmel,at25";
+ reg = <2>;
+ address-width = <16>;
+ size = <32768>;
+ spi-max-frequency = <33000000>;
+ pagesize = <1>;
+ };
+};
+
+/* EEPROM on Ivy */
+&eeprom_carrier_board {
+ status = "okay";
+};
+
+/* Verdin ETH_1 */
+&eqos {
+ status = "okay";
+};
+
+/* Verdin ETH_2 */
+&fec {
+ phy-handle = <&ethphy2>;
+ phy-mode = "rgmii-id";
+ status = "okay";
+};
+
+&verdin_eth2_mdio {
+ ethphy2: ethernet-phy@2 {
+ reg = <2>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ };
+};
+
+/* Verdin CAN_1 */
+&flexcan1 {
+ status = "okay";
+};
+
+/* Verdin CAN_2 */
+&flexcan2 {
+ status = "okay";
+};
+
+&gpio1 {
+ gpio-line-names =
+ "", /* 0 */
+ "GPIO2", /* Verdin GPIO_2 - SODIMM 208 */
+ "",
+ "",
+ "",
+ "GPIO3", /* Verdin GPIO_3 - SODIMM 210 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 10 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 20 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+&gpio3 {
+ gpio-line-names =
+ "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "DIG_1", /* SODIMM 56 */
+ "DIG_2", /* SODIMM 58 */
+ "REL1", /* SODIMM 60 */
+ "REL2", /* SODIMM 62 */
+ "", /* 10 */
+ "",
+ "",
+ "",
+ "REL4", /* SODIMM 66 */
+ "",
+ "REL3", /* SODIMM 64 */
+ "",
+ "",
+ "",
+ "", /* 20 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+/* Temperature sensor on Ivy */
+&hwmon_temp {
+ compatible = "ti,tmp1075";
+ status = "okay";
+};
+
+/* Verdin I2C_4 CSI */
+&i2c3 {
+ status = "okay";
+
+ ivy_adc1: adc@40 {
+ compatible = "ti,ads1119";
+ reg = <0x40>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio7>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ avdd-supply = <&reg_3v2_ain1>;
+ dvdd-supply = <&reg_3v2_ain1>;
+ vref-supply = <&reg_3v2_ain1>;
+ #address-cells = <1>;
+ #io-channel-cells = <1>;
+ #size-cells = <0>;
+
+ /* AIN1 0-33V Voltage Input */
+ channel@0 {
+ reg = <0>;
+ diff-channels = <0 1>;
+ };
+
+ /* AIN1 0-20mA Current Input */
+ channel@1 {
+ reg = <1>;
+ diff-channels = <2 3>;
+ };
+ };
+
+ ivy_adc2: adc@41 {
+ compatible = "ti,ads1119";
+ reg = <0x41>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio8>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ avdd-supply = <&reg_3v2_ain2>;
+ dvdd-supply = <&reg_3v2_ain2>;
+ vref-supply = <&reg_3v2_ain2>;
+ #address-cells = <1>;
+ #io-channel-cells = <1>;
+ #size-cells = <0>;
+
+ /* AIN2 0-33V Voltage Input */
+ channel@0 {
+ reg = <0>;
+ diff-channels = <0 1>;
+ };
+
+ /* AIN2 0-20mA Current Input */
+ channel@1 {
+ reg = <1>;
+ diff-channels = <2 3>;
+ };
+ };
+};
+
+/* Verdin I2C_1 */
+&i2c4 {
+ status = "okay";
+};
+
+/* Verdin PCIE_1 */
+&pcie {
+ status = "okay";
+};
+
+&pcie_phy {
+ status = "okay";
+};
+
+/* Verdin UART_1 */
+&uart1 {
+ status = "okay";
+};
+
+/* Verdin UART_2 */
+&uart2 {
+ linux,rs485-enabled-at-boot-time;
+ rs485-rx-during-tx;
+ status = "okay";
+};
+
+/* Verdin UART_3 */
+&uart3 {
+ status = "okay";
+};
+
+/* Verdin USB_1 */
+&usb3_0 {
+ status = "okay";
+};
+
+&usb3_phy0 {
+ status = "okay";
+};
+
+/* Verdin USB_2 */
+&usb3_1 {
+ status = "okay";
+};
+
+&usb3_phy1 {
+ status = "okay";
+};
+
+/* Verdin SD_1 */
+&usdhc2 {
+ status = "okay";
+};
+
+&iomuxc {
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio2>, <&pinctrl_gpio3>,
+ <&pinctrl_ivy_dig_inputs>, <&pinctrl_ivy_relays>;
+
+ pinctrl_ivy_dig_inputs: ivydiginputsgrp {
+ fsl,pins =
+ <MX8MP_IOMUXC_NAND_DATA00__GPIO3_IO06 0x96>, /* SODIMM 56 */
+ <MX8MP_IOMUXC_NAND_DATA01__GPIO3_IO07 0x96>; /* SODIMM 58 */
+ };
+
+ pinctrl_ivy_leds: ivyledsgrp {
+ fsl,pins =
+ <MX8MP_IOMUXC_SAI5_MCLK__GPIO3_IO25 0x16>, /* SODIMM 30 */
+ <MX8MP_IOMUXC_SAI5_RXD1__GPIO3_IO22 0x16>, /* SODIMM 32 */
+ <MX8MP_IOMUXC_SAI5_RXFS__GPIO3_IO19 0x16>, /* SODIMM 34 */
+ <MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02 0x16>, /* SODIMM 36 */
+ <MX8MP_IOMUXC_SAI3_TXFS__GPIO4_IO31 0x16>, /* SODIMM 44 */
+ <MX8MP_IOMUXC_SAI3_TXD__GPIO5_IO01 0x16>, /* SODIMM 46 */
+ <MX8MP_IOMUXC_SAI3_RXD__GPIO4_IO30 0x16>, /* SODIMM 48 */
+ <MX8MP_IOMUXC_NAND_CE0_B__GPIO3_IO01 0x16>; /* SODIMM 54 */
+ };
+
+ pinctrl_ivy_relays: ivyrelaysgrp {
+ fsl,pins =
+ <MX8MP_IOMUXC_NAND_DATA02__GPIO3_IO08 0x16>, /* SODIMM 60 */
+ <MX8MP_IOMUXC_NAND_DATA03__GPIO3_IO09 0x16>, /* SODIMM 62 */
+ <MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x16>, /* SODIMM 64 */
+ <MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x16>; /* SODIMM 66 */
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-ivy.dts b/arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-ivy.dts
new file mode 100644
index 000000000000..cb49690050ff
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-nonwifi-ivy.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mp-verdin.dtsi"
+#include "imx8mp-verdin-nonwifi.dtsi"
+#include "imx8mp-verdin-ivy.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Plus on Ivy";
+ compatible = "toradex,verdin-imx8mp-nonwifi-ivy",
+ "toradex,verdin-imx8mp-nonwifi",
+ "toradex,verdin-imx8mp",
+ "fsl,imx8mp";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-ivy.dts b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-ivy.dts
new file mode 100644
index 000000000000..22b8fe70b36d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi-ivy.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ */
+
+/dts-v1/;
+
+#include "imx8mp-verdin.dtsi"
+#include "imx8mp-verdin-wifi.dtsi"
+#include "imx8mp-verdin-ivy.dtsi"
+
+/ {
+ model = "Toradex Verdin iMX8M Plus WB on Ivy";
+ compatible = "toradex,verdin-imx8mp-wifi-ivy",
+ "toradex,verdin-imx8mp-wifi",
+ "toradex,verdin-imx8mp",
+ "fsl,imx8mp";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
index a19ad5ee7f79..e3869efe4fd0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
@@ -175,7 +175,7 @@
regulator-max-microvolt = <3300000>;
regulator-min-microvolt = <3300000>;
regulator-name = "+V3.3_SD";
- startup-delay-us = <2000>;
+ startup-delay-us = <20000>;
};
reserved-memory {
@@ -320,7 +320,7 @@
pinctrl-0 = <&pinctrl_fec>;
pinctrl-1 = <&pinctrl_fec_sleep>;
- mdio {
+ verdin_eth2_mdio: mdio {
#address-cells = <1>;
#size-cells = <0>;
@@ -478,6 +478,7 @@
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)>;
+ single-master;
status = "okay";
pca9450: pmic@25 {
@@ -591,11 +592,12 @@
vs-supply = <&reg_vdd_1v8>;
};
- adc@49 {
+ verdin_som_adc: adc@49 {
compatible = "ti,ads1015";
reg = <0x49>;
#address-cells = <1>;
#size-cells = <0>;
+ #io-channel-cells = <1>;
/* Verdin I2C_1 (ADC_4 - ADC_3) */
channel@0 {
@@ -669,6 +671,7 @@
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)>;
+ single-master;
atmel_mxt_ts_mezzanine: touch-mezzanine@4a {
compatible = "atmel,maxtouch";
@@ -690,6 +693,7 @@
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)>;
+ single-master;
};
/* Verdin I2C_1 */
@@ -700,6 +704,7 @@
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)>;
+ single-master;
gpio_expander_21: gpio-expander@21 {
compatible = "nxp,pcal6416";
@@ -788,6 +793,7 @@
pinctrl-1 = <&pinctrl_i2c5_gpio>;
scl-gpios = <&gpio3 26 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio3 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ single-master;
};
/* Verdin PCIE_1 */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index f3531cfb0d79..e0d3b8cba221 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -47,6 +47,20 @@
#address-cells = <1>;
#size-cells = <0>;
+ idle-states {
+ entry-method = "psci";
+
+ cpu_pd_wait: cpu-pd-wait {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x0010033>;
+ local-timer-stop;
+ entry-latency-us = <1000>;
+ exit-latency-us = <700>;
+ min-residency-us = <2700>;
+ wakeup-latency-us = <1500>;
+ };
+ };
+
A53_0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
@@ -65,6 +79,7 @@
nvmem-cell-names = "speed_grade";
operating-points-v2 = <&a53_opp_table>;
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_1: cpu@1 {
@@ -83,6 +98,7 @@
next-level-cache = <&A53_L2>;
operating-points-v2 = <&a53_opp_table>;
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_2: cpu@2 {
@@ -101,6 +117,7 @@
next-level-cache = <&A53_L2>;
operating-points-v2 = <&a53_opp_table>;
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_3: cpu@3 {
@@ -119,6 +136,7 @@
next-level-cache = <&A53_L2>;
operating-points-v2 = <&a53_opp_table>;
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
};
A53_L2: l2-cache0 {
@@ -1261,7 +1279,7 @@
compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b40000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MP_CLK_DUMMY>,
+ clocks = <&clk IMX8MP_CLK_IPG_ROOT>,
<&clk IMX8MP_CLK_NAND_USDHC_BUS>,
<&clk IMX8MP_CLK_USDHC1_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -1275,7 +1293,7 @@
compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b50000 0x10000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MP_CLK_DUMMY>,
+ clocks = <&clk IMX8MP_CLK_IPG_ROOT>,
<&clk IMX8MP_CLK_NAND_USDHC_BUS>,
<&clk IMX8MP_CLK_USDHC2_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -1289,7 +1307,7 @@
compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b60000 0x10000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MP_CLK_DUMMY>,
+ clocks = <&clk IMX8MP_CLK_IPG_ROOT>,
<&clk IMX8MP_CLK_NAND_USDHC_BUS>,
<&clk IMX8MP_CLK_USDHC3_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -2176,8 +2194,11 @@
pcie_ep: pcie-ep@33800000 {
compatible = "fsl,imx8mp-pcie-ep";
- reg = <0x33800000 0x000400000>, <0x18000000 0x08000000>;
- reg-names = "dbi", "addr_space";
+ reg = <0x33800000 0x100000>,
+ <0x18000000 0x8000000>,
+ <0x33900000 0x100000>,
+ <0x33b00000 0x100000>;
+ reg-names = "dbi", "addr_space", "dbi2", "atu";
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
<&clk IMX8MP_CLK_HSIO_AXI>,
<&clk IMX8MP_CLK_PCIE_ROOT>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index e03186bbc415..d51de8d899b2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1819,9 +1819,11 @@
pcie1_ep: pcie-ep@33c00000 {
compatible = "fsl,imx8mq-pcie-ep";
- reg = <0x33c00000 0x000400000>,
- <0x20000000 0x08000000>;
- reg-names = "dbi", "addr_space";
+ reg = <0x33c00000 0x100000>,
+ <0x20000000 0x8000000>,
+ <0x33d00000 0x100000>,
+ <0x33f00000 0x100000>;
+ reg-names = "dbi", "addr_space", "dbi2", "atu";
num-lanes = <1>;
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "dma";
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
index 62203eed6a6c..50fd3370f7dc 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
@@ -92,6 +92,27 @@
reg = <0 0x90400000 0 0x100000>;
no-map;
};
+
+ dsp_reserved: memory@92400000 {
+ reg = <0 0x92400000 0 0x1000000>;
+ no-map;
+ };
+
+ dsp_vdev0vring0: memory@942f0000 {
+ reg = <0 0x942f0000 0 0x8000>;
+ no-map;
+ };
+
+ dsp_vdev0vring1: memory@942f8000 {
+ reg = <0 0x942f8000 0 0x8000>;
+ no-map;
+ };
+
+ dsp_vdev0buffer: memory@94300000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x94300000 0 0x100000>;
+ no-map;
+ };
};
lvds_backlight0: backlight-lvds0 {
@@ -181,6 +202,17 @@
vin-supply = <&reg_can2_en>;
};
+ reg_pciea: regulator-pcie {
+ compatible = "regulator-fixed";
+ pinctrl-0 = <&pinctrl_pciea_reg>;
+ pinctrl-names = "default";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "mpcie_3v3";
+ gpio = <&lsio_gpio1 13 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
reg_vref_1v8: regulator-adc-vref {
compatible = "regulator-fixed";
regulator-name = "vref_1v8";
@@ -296,6 +328,12 @@
status = "okay";
};
+&hsio_phy {
+ fsl,hsio-cfg = "pciea-pcieb-sata";
+ fsl,refclk-pad-mode = "input";
+ status = "okay";
+};
+
&i2c0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -541,6 +579,25 @@
status = "okay";
};
+&pciea {
+ phys = <&hsio_phy 0 PHY_TYPE_PCIE 0>;
+ phy-names = "pcie-phy";
+ pinctrl-0 = <&pinctrl_pciea>;
+ pinctrl-names = "default";
+ reset-gpio = <&lsio_gpio4 29 GPIO_ACTIVE_LOW>;
+ vpcie-supply = <&reg_pciea>;
+ status = "okay";
+};
+
+&pcieb {
+ phys = <&hsio_phy 1 PHY_TYPE_PCIE 1>;
+ phy-names = "pcie-phy";
+ pinctrl-0 = <&pinctrl_pcieb>;
+ pinctrl-names = "default";
+ reset-gpio = <&lsio_gpio5 0 GPIO_ACTIVE_LOW>;
+ status = "disabled";
+};
+
&qm_pwm_lvds0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm_lvds0>;
@@ -640,6 +697,16 @@
status = "okay";
};
+&sata {
+ status = "okay";
+};
+
+&vpu_dsp {
+ memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>,
+ <&dsp_vdev0vring1>, <&dsp_reserved>;
+ status = "okay";
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
@@ -829,6 +896,28 @@
>;
};
+ pinctrl_pciea: pcieagrp {
+ fsl,pins = <
+ IMX8QM_PCIE_CTRL0_WAKE_B_LSIO_GPIO4_IO28 0x04000021
+ IMX8QM_PCIE_CTRL0_PERST_B_LSIO_GPIO4_IO29 0x06000021
+ IMX8QM_SCU_GPIO0_07_SCU_DSC_RTC_CLOCK_OUTPUT_32K 0x20
+ >;
+ };
+
+ pinctrl_pciea_reg: pcieareggrp {
+ fsl,pins = <
+ IMX8QM_LVDS1_I2C0_SDA_LSIO_GPIO1_IO13 0x06000021
+ >;
+ };
+
+ pinctrl_pcieb: pciebgrp {
+ fsl,pins = <
+ IMX8QM_PCIE_CTRL1_CLKREQ_B_HSIO_PCIE1_CLKREQ_B 0x06000021
+ IMX8QM_PCIE_CTRL1_WAKE_B_LSIO_GPIO4_IO31 0x04000021
+ IMX8QM_PCIE_CTRL1_PERST_B_LSIO_GPIO5_IO00 0x06000021
+ >;
+ };
+
pinctrl_pwm_lvds0: pwmlvds0grp {
fsl,pins = <
IMX8QM_LVDS0_GPIO00_LVDS0_PWM0_OUT 0x00000020
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi
index 3036af49fc85..e24e639b98ee 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-audio.dtsi
@@ -304,7 +304,7 @@
};
/* edma2 called in imx8qm RM with the same address in edma0 of imx8qxp */
-&edma0{
+&edma0 {
reg = <0x591f0000 0x150000>;
dma-channels = <20>;
dma-channel-mask = <0>;
@@ -351,7 +351,7 @@
};
/* edma3 called in imx8qm RM with the same address in edma1 of imx8qxp */
-&edma1{
+&edma1 {
reg = <0x599f0000 0xc0000>;
dma-channels = <11>;
dma-channel-mask = <0xc0>;
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi
index 545e175c88b3..ccf9f510e0f8 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi
@@ -4,6 +4,10 @@
* Dong Aisheng <aisheng.dong@nxp.com>
*/
+&usbphy1 {
+ compatible = "fsl,imx8qm-usbphy", "fsl,imx7ulp-usbphy";
+};
+
&fec1 {
compatible = "fsl,imx8qm-fec", "fsl,imx6sx-fec";
iommus = <&smmu 0x12 0x7f80>;
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
index aa9f28c4431d..d4856b8590e0 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
@@ -4,6 +4,9 @@
* Dong Aisheng <aisheng.dong@nxp.com>
*/
+/delete-node/ &adma_pwm;
+/delete-node/ &adma_pwm_lpcg;
+
&dma_subsys {
uart4_lpcg: clock-controller@5a4a0000 {
compatible = "fsl,imx8qxp-lpcg";
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-hsio.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-hsio.dtsi
new file mode 100644
index 000000000000..b1d0189a1725
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-hsio.dtsi
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ * Richard Zhu <hongxing.zhu@nxp.com>
+ */
+
+&hsio_subsys {
+ compatible = "simple-bus";
+ ranges = <0x5f000000 0x0 0x5f000000 0x01000000>,
+ <0x40000000 0x0 0x60000000 0x10000000>,
+ <0x80000000 0x0 0x70000000 0x10000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pciea: pcie@5f000000 {
+ compatible = "fsl,imx8q-pcie";
+ reg = <0x5f000000 0x10000>,
+ <0x4ff00000 0x80000>;
+ reg-names = "dbi", "config";
+ ranges = <0x81000000 0 0x00000000 0x4ff80000 0 0x00010000>,
+ <0x82000000 0 0x40000000 0x40000000 0 0x0ff00000>;
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ clocks = <&pciea_lpcg IMX_LPCG_CLK_6>,
+ <&pciea_lpcg IMX_LPCG_CLK_4>,
+ <&pciea_lpcg IMX_LPCG_CLK_5>;
+ clock-names = "dbi", "mstr", "slv";
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ interrupt-map = <0 0 0 1 &gic 0 73 4>,
+ <0 0 0 2 &gic 0 74 4>,
+ <0 0 0 3 &gic 0 75 4>,
+ <0 0 0 4 &gic 0 76 4>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ num-lanes = <1>;
+ num-viewport = <4>;
+ power-domains = <&pd IMX_SC_R_PCIE_A>;
+ fsl,max-link-speed = <3>;
+ status = "disabled";
+ };
+
+ pcieb: pcie@5f010000 {
+ compatible = "fsl,imx8q-pcie";
+ reg = <0x5f010000 0x10000>,
+ <0x8ff00000 0x80000>;
+ reg-names = "dbi", "config";
+ ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
+ <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ clocks = <&pcieb_lpcg IMX_LPCG_CLK_6>,
+ <&pcieb_lpcg IMX_LPCG_CLK_4>,
+ <&pcieb_lpcg IMX_LPCG_CLK_5>;
+ clock-names = "dbi", "mstr", "slv";
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ interrupt-map = <0 0 0 1 &gic 0 105 4>,
+ <0 0 0 2 &gic 0 106 4>,
+ <0 0 0 3 &gic 0 107 4>,
+ <0 0 0 4 &gic 0 108 4>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ num-lanes = <1>;
+ num-viewport = <4>;
+ power-domains = <&pd IMX_SC_R_PCIE_B>;
+ fsl,max-link-speed = <3>;
+ status = "disabled";
+ };
+
+ sata: sata@5f020000 {
+ compatible = "fsl,imx8qm-ahci";
+ reg = <0x5f020000 0x10000>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sata_lpcg IMX_LPCG_CLK_4>,
+ <&sata_crr4_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "sata", "sata_ref";
+ phy-names = "sata-phy", "cali-phy0", "cali-phy1";
+ power-domains = <&pd IMX_SC_R_SATA_0>;
+ /*
+ * Since "REXT" pin is only present for first lane PHY
+ * and its calibration result will be stored, and shared
+ * by the PHY used by SATA.
+ *
+ * Add the calibration PHYs for SATA here, although only
+ * the third lane PHY is used by SATA.
+ */
+ phys = <&hsio_phy 2 PHY_TYPE_SATA 0>,
+ <&hsio_phy 0 PHY_TYPE_PCIE 0>,
+ <&hsio_phy 1 PHY_TYPE_PCIE 1>;
+ status = "disabled";
+ };
+
+ pciea_lpcg: clock-controller@5f050000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f050000 0x10000>;
+ clocks = <&hsio_axi_clk>, <&hsio_axi_clk>, <&hsio_axi_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_5>, <IMX_LPCG_CLK_6>;
+ clock-output-names = "hsio_pciea_mstr_axi_clk",
+ "hsio_pciea_slv_axi_clk",
+ "hsio_pciea_dbi_axi_clk";
+ power-domains = <&pd IMX_SC_R_PCIE_A>;
+ };
+
+ sata_lpcg: clock-controller@5f070000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f070000 0x10000>;
+ clocks = <&hsio_axi_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_sata_clk";
+ power-domains = <&pd IMX_SC_R_SATA_0>;
+ };
+
+ phyx2_lpcg: clock-controller@5f080000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f080000 0x10000>;
+ clocks = <&hsio_refa_clk>, <&hsio_per_clk>,
+ <&hsio_refa_clk>, <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_1>,
+ <IMX_LPCG_CLK_4>, <IMX_LPCG_CLK_5>;
+ clock-output-names = "hsio_phyx2_pclk_0",
+ "hsio_phyx2_pclk_1",
+ "hsio_phyx2_apbclk_0",
+ "hsio_phyx2_apbclk_1";
+ power-domains = <&pd IMX_SC_R_SERDES_0>;
+ };
+
+ phyx1_lpcg: clock-controller@5f090000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f090000 0x10000>;
+ clocks = <&hsio_refa_clk>, <&hsio_per_clk>,
+ <&hsio_per_clk>, <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_1>,
+ <IMX_LPCG_CLK_2>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_phyx1_pclk",
+ "hsio_phyx1_epcs_tx_clk",
+ "hsio_phyx1_epcs_rx_clk",
+ "hsio_phyx1_apb_clk";
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ };
+
+ phyx2_crr0_lpcg: clock-controller@5f0a0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f0a0000 0x10000>;
+ clocks = <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_phyx2_per_clk";
+ power-domains = <&pd IMX_SC_R_SERDES_0>;
+ };
+
+ pciea_crr2_lpcg: clock-controller@5f0c0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f0c0000 0x10000>;
+ clocks = <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_pciea_per_clk";
+ power-domains = <&pd IMX_SC_R_PCIE_A>;
+ };
+
+ sata_crr4_lpcg: clock-controller@5f0e0000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f0e0000 0x10000>;
+ clocks = <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_sata_per_clk";
+ power-domains = <&pd IMX_SC_R_SATA_0>;
+ };
+
+ hsio_phy: phy@5f180000 {
+ compatible = "fsl,imx8qm-hsio";
+ reg = <0x5f180000 0x30000>,
+ <0x5f110000 0x20000>,
+ <0x5f130000 0x30000>,
+ <0x5f160000 0x10000>;
+ reg-names = "reg", "phy", "ctrl", "misc";
+ clocks = <&phyx2_lpcg IMX_LPCG_CLK_0>,
+ <&phyx2_lpcg IMX_LPCG_CLK_1>,
+ <&phyx2_lpcg IMX_LPCG_CLK_4>,
+ <&phyx2_lpcg IMX_LPCG_CLK_5>,
+ <&phyx1_lpcg IMX_LPCG_CLK_0>,
+ <&phyx1_lpcg IMX_LPCG_CLK_1>,
+ <&phyx1_lpcg IMX_LPCG_CLK_2>,
+ <&phyx1_lpcg IMX_LPCG_CLK_4>,
+ <&phyx2_crr0_lpcg IMX_LPCG_CLK_4>,
+ <&phyx1_crr1_lpcg IMX_LPCG_CLK_4>,
+ <&pciea_crr2_lpcg IMX_LPCG_CLK_4>,
+ <&pcieb_crr3_lpcg IMX_LPCG_CLK_4>,
+ <&sata_crr4_lpcg IMX_LPCG_CLK_4>,
+ <&misc_crr5_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "pclk0", "pclk1", "apb_pclk0", "apb_pclk1",
+ "pclk2", "epcs_tx", "epcs_rx", "apb_pclk2",
+ "phy0_crr", "phy1_crr", "ctl0_crr",
+ "ctl1_crr", "ctl2_crr", "misc_crr";
+ #phy-cells = <3>;
+ power-domains = <&pd IMX_SC_R_SERDES_0>, <&pd IMX_SC_R_SERDES_1>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm.dtsi b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
index 3ee6e2869e3c..6fa31bc9ece8 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
@@ -24,6 +24,10 @@
serial1 = &lpuart1;
serial2 = &lpuart2;
serial3 = &lpuart3;
+ spi0 = &lpspi0;
+ spi1 = &lpspi1;
+ spi2 = &lpspi2;
+ spi3 = &lpspi3;
vpu-core0 = &vpu_core0;
vpu-core1 = &vpu_core1;
vpu-core2 = &vpu_core2;
@@ -581,6 +585,32 @@
clock-output-names = "mipi_pll_div2_clk";
};
+ vpu_subsys_dsp: bus@55000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x55000000 0x0 0x55000000 0x1000000>;
+
+ vpu_dsp: dsp@556e8000 {
+ compatible = "fsl,imx8qm-hifi4";
+ reg = <0x556e8000 0x88000>;
+ clocks = <&clk_dummy>,
+ <&clk_dummy>,
+ <&clk_dummy>;
+ clock-names = "ipg", "ocram", "core";
+ power-domains = <&pd IMX_SC_R_MU_13B>,
+ <&pd IMX_SC_R_DSP>,
+ <&pd IMX_SC_R_DSP_RAM>,
+ <&pd IMX_SC_R_MU_2A>;
+ mboxes = <&lsio_mu13 0 0>,
+ <&lsio_mu13 1 0>,
+ <&lsio_mu13 3 0>;
+ mbox-names = "tx", "rx", "rxdb";
+ firmware-name = "imx/dsp/hifi4.bin";
+ status = "disabled";
+ };
+ };
+
/* sorted in register address */
#include "imx8-ss-cm41.dtsi"
#include "imx8-ss-audio.dtsi"
@@ -594,6 +624,7 @@
#include "imx8-ss-dma.dtsi"
#include "imx8-ss-conn.dtsi"
#include "imx8-ss-lsio.dtsi"
+ #include "imx8-ss-hsio.dtsi"
};
#include "imx8qm-ss-img.dtsi"
@@ -603,3 +634,6 @@
#include "imx8qm-ss-audio.dtsi"
#include "imx8qm-ss-lvds.dtsi"
#include "imx8qm-ss-mipi.dtsi"
+#include "imx8qm-ss-hsio.dtsi"
+
+/delete-node/ &dsp;
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
index 936ba5ecdcac..be79c793213a 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
@@ -12,15 +12,52 @@
model = "Freescale i.MX8QXP MEK";
compatible = "fsl,imx8qxp-mek", "fsl,imx8qxp";
+ bt_sco_codec: audio-codec-bt {
+ compatible = "linux,bt-sco";
+ #sound-dai-cells = <1>;
+ };
+
chosen {
stdout-path = &lpuart0;
};
+ imx8x_cm4: imx8x-cm4 {
+ compatible = "fsl,imx8qxp-cm4";
+ mbox-names = "tx", "rx", "rxdb";
+ mboxes = <&lsio_mu5 0 1
+ &lsio_mu5 1 1
+ &lsio_mu5 3 1>;
+ memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>,
+ <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>;
+ power-domains = <&pd IMX_SC_R_M4_0_PID0>,
+ <&pd IMX_SC_R_M4_0_MU_1A>;
+ fsl,entry-address = <0x34fe0000>;
+ fsl,resource-id = <IMX_SC_R_M4_0_PID0>;
+ };
+
memory@80000000 {
device_type = "memory";
reg = <0x00000000 0x80000000 0 0x40000000>;
};
+ reserved-memory {
+ dsp_vdev0vring0: memory@942f0000 {
+ reg = <0 0x942f0000 0 0x8000>;
+ no-map;
+ };
+
+ dsp_vdev0vring1: memory@942f8000 {
+ reg = <0 0x942f8000 0 0x8000>;
+ no-map;
+ };
+
+ dsp_vdev0buffer: memory@94300000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x94300000 0 0x100000>;
+ no-map;
+ };
+ };
+
reg_usdhc2_vmmc: usdhc2-vmmc {
compatible = "regulator-fixed";
regulator-name = "SD1_SPWR";
@@ -45,6 +82,132 @@
};
};
+ reg_pcieb: regulator-pcie {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "mpcie_3v3";
+ gpio = <&pca9557_a 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_audio: regulator-audio {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "cs42888_supply";
+ };
+
+ reg_can_en: regulator-can-en {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "can-en";
+ gpio = <&pca6416 3 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can_stby: regulator-can-stby {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "can-stby";
+ gpio = <&pca6416 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_can_en>;
+ };
+
+ reg_usb_otg1_vbus: regulator-usbotg1-vbus {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "usb_otg1_vbus";
+ gpio = <&pca9557_b 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ vdev0vring0: memory@90000000 {
+ reg = <0 0x90000000 0 0x8000>;
+ no-map;
+ };
+
+ vdev0vring1: memory@90008000 {
+ reg = <0 0x90008000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring0: memory@90010000 {
+ reg = <0 0x90010000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring1: memory@90018000 {
+ reg = <0 0x90018000 0 0x8000>;
+ no-map;
+ };
+
+ rsc_table: memory@900ff000 {
+ reg = <0 0x900ff000 0 0x1000>;
+ no-map;
+ };
+
+ vdevbuffer: memory@90400000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90400000 0 0x100000>;
+ no-map;
+ };
+
+ gpu_reserved: memory@880000000 {
+ no-map;
+ reg = <0x8 0x80000000 0 0x10000000>;
+ };
+ };
+
+ sound-bt-sco {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-inversion;
+ simple-audio-card,bitclock-master = <&btcpu>;
+ simple-audio-card,format = "dsp_a";
+ simple-audio-card,frame-master = <&btcpu>;
+ simple-audio-card,name = "bt-sco-audio";
+
+ simple-audio-card,codec {
+ sound-dai = <&bt_sco_codec 1>;
+ };
+
+ btcpu: simple-audio-card,cpu {
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <16>;
+ sound-dai = <&sai0>;
+ };
+ };
+
+ sound-cs42888 {
+ compatible = "fsl,imx-audio-cs42888";
+ audio-asrc = <&asrc0>;
+ audio-codec = <&cs42888>;
+ audio-cpu = <&esai0>;
+ audio-routing =
+ "Line Out Jack", "AOUT1L",
+ "Line Out Jack", "AOUT1R",
+ "Line Out Jack", "AOUT2L",
+ "Line Out Jack", "AOUT2R",
+ "Line Out Jack", "AOUT3L",
+ "Line Out Jack", "AOUT3R",
+ "Line Out Jack", "AOUT4L",
+ "Line Out Jack", "AOUT4R",
+ "AIN1L", "Line In Jack",
+ "AIN1R", "Line In Jack",
+ "AIN2L", "Line In Jack",
+ "AIN2R", "Line In Jack";
+ model = "imx-cs42888";
+ };
+
sound-wm8960 {
compatible = "fsl,imx-audio-wm8960";
model = "wm8960-audio";
@@ -62,8 +225,18 @@
};
};
+&amix {
+ status = "okay";
+};
+
+&asrc0 {
+ fsl,asrc-rate = <48000>;
+ status = "okay";
+};
+
&dsp {
- memory-region = <&dsp_reserved>;
+ memory-region = <&dsp_vdev0buffer>, <&dsp_vdev0vring0>,
+ <&dsp_vdev0vring1>, <&dsp_reserved>;
status = "okay";
};
@@ -71,6 +244,19 @@
status = "okay";
};
+&esai0 {
+ assigned-clocks = <&acm IMX_ADMA_ACM_ESAI0_MCLK_SEL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&esai0_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-parents = <&aud_pll_div0_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <0>, <786432000>, <49152000>, <12288000>, <49152000>;
+ pinctrl-0 = <&pinctrl_esai0>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec1>;
@@ -240,12 +426,57 @@
gpio-controller;
#gpio-cells = <2>;
};
+
+ cs42888: audio-codec@48 {
+ compatible = "cirrus,cs42888";
+ reg = <0x48>;
+ clocks = <&mclkout0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "mclk";
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&mclkout0_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <12288000>;
+ reset-gpios = <&pca9557_b 1 GPIO_ACTIVE_LOW>;
+ VA-supply = <&reg_audio>;
+ VD-supply = <&reg_audio>;
+ VLC-supply = <&reg_audio>;
+ VLS-supply = <&reg_audio>;
+ };
};
&cm40_intmux {
status = "okay";
};
+&hsio_phy {
+ fsl,hsio-cfg = "pciea-x2-pcieb";
+ fsl,refclk-pad-mode = "input";
+ status = "okay";
+};
+
+&flexcan1 {
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ pinctrl-names = "default";
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&flexcan2 {
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ pinctrl-names = "default";
+ xceiver-supply = <&reg_can_stby>;
+ status = "okay";
+};
+
+&jpegdec {
+ status = "okay";
+};
+
+&jpegenc {
+ status = "okay";
+};
+
&lpuart0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpuart0>;
@@ -264,6 +495,10 @@
status = "okay";
};
+&lsio_mu5 {
+ status = "okay";
+};
+
&mu_m0 {
status = "okay";
};
@@ -272,6 +507,16 @@
status = "okay";
};
+&pcieb {
+ phys = <&hsio_phy 0 PHY_TYPE_PCIE 0>;
+ phy-names = "pcie-phy";
+ pinctrl-0 = <&pinctrl_pcieb>;
+ pinctrl-names = "default";
+ reset-gpios = <&lsio_gpio4 0 GPIO_ACTIVE_LOW>;
+ vpcie-supply = <&reg_pcieb>;
+ status = "okay";
+};
+
&scu_key {
status = "okay";
};
@@ -384,6 +629,20 @@
status = "okay";
};
+&usbphy1 {
+ status = "okay";
+};
+
+&usbotg1 {
+ adp-disable;
+ hnp-disable;
+ srp-disable;
+ disable-over-current;
+ power-active-high;
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ status = "okay";
+};
+
&usbotg3 {
status = "okay";
};
@@ -434,6 +693,21 @@
>;
};
+ pinctrl_esai0: esai0grp {
+ fsl,pins = <
+ IMX8QXP_ESAI0_FSR_ADMA_ESAI0_FSR 0xc6000040
+ IMX8QXP_ESAI0_FST_ADMA_ESAI0_FST 0xc6000040
+ IMX8QXP_ESAI0_SCKR_ADMA_ESAI0_SCKR 0xc6000040
+ IMX8QXP_ESAI0_SCKT_ADMA_ESAI0_SCKT 0xc6000040
+ IMX8QXP_ESAI0_TX0_ADMA_ESAI0_TX0 0xc6000040
+ IMX8QXP_ESAI0_TX1_ADMA_ESAI0_TX1 0xc6000040
+ IMX8QXP_ESAI0_TX2_RX3_ADMA_ESAI0_TX2_RX3 0xc6000040
+ IMX8QXP_ESAI0_TX3_RX2_ADMA_ESAI0_TX3_RX2 0xc6000040
+ IMX8QXP_ESAI0_TX4_RX1_ADMA_ESAI0_TX4_RX1 0xc6000040
+ IMX8QXP_ESAI0_TX5_RX0_ADMA_ESAI0_TX5_RX0 0xc6000040
+ >;
+ };
+
pinctrl_fec1: fec1grp {
fsl,pins = <
IMX8QXP_ENET0_MDC_CONN_ENET0_MDC 0x06000020
@@ -453,6 +727,20 @@
>;
};
+ pinctrl_flexcan1: flexcan0grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN0_TX_ADMA_FLEXCAN0_TX 0x21
+ IMX8QXP_FLEXCAN0_RX_ADMA_FLEXCAN0_RX 0x21
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan1grp {
+ fsl,pins = <
+ IMX8QXP_FLEXCAN1_TX_ADMA_FLEXCAN1_TX 0x21
+ IMX8QXP_FLEXCAN1_RX_ADMA_FLEXCAN1_RX 0x21
+ >;
+ };
+
pinctrl_ioexp_rst: ioexprstgrp {
fsl,pins = <
IMX8QXP_SPI2_SDO_LSIO_GPIO1_IO01 0x06000021
@@ -493,6 +781,14 @@
>;
};
+ pinctrl_pcieb: pcieagrp {
+ fsl,pins = <
+ IMX8QXP_PCIE_CTRL0_PERST_B_LSIO_GPIO4_IO00 0x06000021
+ IMX8QXP_PCIE_CTRL0_CLKREQ_B_HSIO_PCIE0_CLKREQ_B 0x06000021
+ IMX8QXP_PCIE_CTRL0_WAKE_B_LSIO_GPIO4_IO02 0x04000021
+ >;
+ };
+
pinctrl_typec: typecgrp {
fsl,pins = <
IMX8QXP_SPI2_SCK_LSIO_GPIO1_IO03 0x06000021
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-ss-conn.dtsi
index 46da21af3702..4eb48ad48745 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ss-conn.dtsi
@@ -4,6 +4,10 @@
* Dong Aisheng <aisheng.dong@nxp.com>
*/
+&usbphy1 {
+ compatible = "fsl,imx8qxp-usbphy", "fsl,imx7ulp-usbphy";
+};
+
&usdhc1 {
compatible = "fsl,imx8qxp-usdhc", "fsl,imx7d-usdhc";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ss-hsio.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-ss-hsio.dtsi
new file mode 100644
index 000000000000..47fc6e0cff4a
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ss-hsio.dtsi
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ * Richard Zhu <hongxing.zhu@nxp.com>
+ */
+
+&hsio_subsys {
+ phyx1_lpcg: clock-controller@5f090000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5f090000 0x10000>;
+ clocks = <&hsio_refb_clk>, <&hsio_per_clk>,
+ <&hsio_per_clk>, <&hsio_per_clk>;
+ #clock-cells = <1>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_1>,
+ <IMX_LPCG_CLK_2>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "hsio_phyx1_pclk",
+ "hsio_phyx1_epcs_tx_clk",
+ "hsio_phyx1_epcs_rx_clk",
+ "hsio_phyx1_apb_clk";
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ };
+
+ hsio_phy: phy@5f1a0000 {
+ compatible = "fsl,imx8qxp-hsio";
+ reg = <0x5f1a0000 0x10000>,
+ <0x5f120000 0x10000>,
+ <0x5f140000 0x10000>,
+ <0x5f160000 0x10000>;
+ reg-names = "reg", "phy", "ctrl", "misc";
+ clocks = <&phyx1_lpcg IMX_LPCG_CLK_0>,
+ <&phyx1_lpcg IMX_LPCG_CLK_1>,
+ <&phyx1_crr1_lpcg IMX_LPCG_CLK_4>,
+ <&pcieb_crr3_lpcg IMX_LPCG_CLK_4>,
+ <&misc_crr5_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "pclk0", "apb_pclk0", "phy0_crr", "ctl0_crr",
+ "misc_crr";
+ #phy-cells = <3>;
+ power-domains = <&pd IMX_SC_R_SERDES_1>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi
index 7894a3ab26d6..f81937b5fb72 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi
@@ -5,6 +5,14 @@
* Author: Alexander Stein
*/
+&mu_m0 {
+ interrupts = <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mu1_m0 {
+ interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>;
+};
+
&vpu_core0 {
reg = <0x2d040000 0x10000>;
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
index 0313f295de2e..05138326f0a5 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
@@ -46,6 +46,10 @@
serial1 = &lpuart1;
serial2 = &lpuart2;
serial3 = &lpuart3;
+ spi0 = &lpspi0;
+ spi1 = &lpspi1;
+ spi2 = &lpspi2;
+ spi3 = &lpspi3;
vpu-core0 = &vpu_core0;
vpu-core1 = &vpu_core1;
};
@@ -323,6 +327,7 @@
#include "imx8-ss-conn.dtsi"
#include "imx8-ss-ddr.dtsi"
#include "imx8-ss-lsio.dtsi"
+ #include "imx8-ss-hsio.dtsi"
};
#include "imx8qxp-ss-img.dtsi"
@@ -330,3 +335,4 @@
#include "imx8qxp-ss-adma.dtsi"
#include "imx8qxp-ss-conn.dtsi"
#include "imx8qxp-ss-lsio.dtsi"
+#include "imx8qxp-ss-hsio.dtsi"
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
index e937e5f8fa8b..290a49bea2f7 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts
@@ -11,6 +11,11 @@
model = "NXP i.MX8ULP EVK";
compatible = "fsl,imx8ulp-evk", "fsl,imx8ulp";
+ bt_sco_codec: bt-sco-codec {
+ #sound-dai-cells = <1>;
+ compatible = "linux,bt-sco";
+ };
+
chosen {
stdout-path = &lpuart5;
};
@@ -83,6 +88,37 @@
clock-output-names = "ext_ts_clk";
#clock-cells = <0>;
};
+
+ sound-bt-sco {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "bt-sco-audio";
+ simple-audio-card,format = "dsp_a";
+ simple-audio-card,bitclock-inversion;
+ simple-audio-card,frame-master = <&btcpu>;
+ simple-audio-card,bitclock-master = <&btcpu>;
+
+ btcpu: simple-audio-card,cpu {
+ sound-dai = <&sai5>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <16>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&bt_sco_codec 1>;
+ };
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ audio-cpu = <&spdif>;
+ audio-codec = <&spdif_out>;
+ };
+
+ spdif_out: spdif-out {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ };
};
&cm33 {
@@ -153,6 +189,25 @@
};
};
+&sai5 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_sai5>;
+ pinctrl-1 = <&pinctrl_sai5>;
+ assigned-clocks = <&cgc1 IMX8ULP_CLK_SAI5_SEL>;
+ assigned-clock-parents = <&cgc1 IMX8ULP_CLK_SPLL3_PFD1_DIV1>;
+ fsl,dataline = <1 0x08 0x01>;
+ status = "okay";
+};
+
+&spdif {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_spdif>;
+ pinctrl-1 = <&pinctrl_spdif>;
+ assigned-clocks = <&cgc2 IMX8ULP_CLK_SPDIF_SEL>;
+ assigned-clock-parents = <&cgc1 IMX8ULP_CLK_SPLL3_PFD1_DIV1>;
+ status = "okay";
+};
+
&usbotg1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb1>;
@@ -282,6 +337,21 @@
>;
};
+ pinctrl_sai5: sai5grp {
+ fsl,pins = <
+ MX8ULP_PAD_PTF26__I2S5_TX_BCLK 0x43
+ MX8ULP_PAD_PTF27__I2S5_TX_FS 0x43
+ MX8ULP_PAD_PTF28__I2S5_TXD0 0x43
+ MX8ULP_PAD_PTF24__I2S5_RXD3 0x43
+ >;
+ };
+
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <
+ MX8ULP_PAD_PTF25__SPDIF_OUT1 0x43
+ >;
+ };
+
pinctrl_typec1: typec1grp {
fsl,pins = <
MX8ULP_PAD_PTF3__PTF3 0x3
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
index e32d5afcf4a9..2562a35286c2 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
@@ -28,6 +28,8 @@
serial1 = &lpuart5;
serial2 = &lpuart6;
serial3 = &lpuart7;
+ spi0 = &lpspi4;
+ spi1 = &lpspi5;
};
cpus {
@@ -212,6 +214,70 @@
#size-cells = <1>;
ranges;
+ edma1: dma-controller@29010000 {
+ compatible = "fsl,imx8ulp-edma";
+ reg = <0x29010000 0x210000>;
+ #dma-cells = <3>;
+ dma-channels = <32>;
+ 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>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc3 IMX8ULP_CLK_DMA1_MP>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH0>, <&pcc3 IMX8ULP_CLK_DMA1_CH1>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH2>, <&pcc3 IMX8ULP_CLK_DMA1_CH3>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH4>, <&pcc3 IMX8ULP_CLK_DMA1_CH5>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH6>, <&pcc3 IMX8ULP_CLK_DMA1_CH7>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH8>, <&pcc3 IMX8ULP_CLK_DMA1_CH9>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH10>, <&pcc3 IMX8ULP_CLK_DMA1_CH11>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH12>, <&pcc3 IMX8ULP_CLK_DMA1_CH13>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH14>, <&pcc3 IMX8ULP_CLK_DMA1_CH15>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH16>, <&pcc3 IMX8ULP_CLK_DMA1_CH17>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH18>, <&pcc3 IMX8ULP_CLK_DMA1_CH19>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH20>, <&pcc3 IMX8ULP_CLK_DMA1_CH21>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH22>, <&pcc3 IMX8ULP_CLK_DMA1_CH23>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH24>, <&pcc3 IMX8ULP_CLK_DMA1_CH25>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH26>, <&pcc3 IMX8ULP_CLK_DMA1_CH27>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH28>, <&pcc3 IMX8ULP_CLK_DMA1_CH29>,
+ <&pcc3 IMX8ULP_CLK_DMA1_CH30>, <&pcc3 IMX8ULP_CLK_DMA1_CH31>;
+ clock-names = "dma", "ch00","ch01", "ch02", "ch03",
+ "ch04", "ch05", "ch06", "ch07",
+ "ch08", "ch09", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15",
+ "ch16", "ch17", "ch18", "ch19",
+ "ch20", "ch21", "ch22", "ch23",
+ "ch24", "ch25", "ch26", "ch27",
+ "ch28", "ch29", "ch30", "ch31";
+ };
+
mu: mailbox@29220000 {
compatible = "fsl,imx8ulp-mu";
reg = <0x29220000 0x10000>;
@@ -384,7 +450,7 @@
};
flexspi2: spi@29810000 {
- compatible = "nxp,imx8mm-fspi";
+ compatible = "nxp,imx8ulp-fspi";
reg = <0x29810000 0x10000>, <0x60000000 0x10000000>;
reg-names = "fspi_base", "fspi_mmap";
#address-cells = <1>;
@@ -442,6 +508,36 @@
status = "disabled";
};
+ sai4: sai@29880000 {
+ compatible = "fsl,imx8ulp-sai";
+ reg = <0x29880000 0x10000>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc4 IMX8ULP_CLK_SAI4>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc1 IMX8ULP_CLK_SAI4_SEL>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc1 IMX8ULP_CLK_DUMMY>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dmas = <&edma1 67 0 1>, <&edma1 68 0 0>;
+ dma-names = "rx", "tx";
+ #sound-dai-cells = <0>;
+ fsl,dataline = <0 0x03 0x03>;
+ status = "disabled";
+ };
+
+ sai5: sai@29890000 {
+ compatible = "fsl,imx8ulp-sai";
+ reg = <0x29890000 0x10000>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc4 IMX8ULP_CLK_SAI5>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc1 IMX8ULP_CLK_SAI5_SEL>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc1 IMX8ULP_CLK_DUMMY>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dmas = <&edma1 69 0 1>, <&edma1 70 0 0>;
+ dma-names = "rx", "tx";
+ #sound-dai-cells = <0>;
+ fsl,dataline = <0 0x0f 0x0f>;
+ status = "disabled";
+ };
+
iomuxc1: pinctrl@298c0000 {
compatible = "fsl,imx8ulp-iomuxc1";
reg = <0x298c0000 0x10000>;
@@ -614,6 +710,70 @@
#size-cells = <1>;
ranges;
+ edma2: dma-controller@2d800000 {
+ compatible = "fsl,imx8ulp-edma";
+ reg = <0x2d800000 0x210000>;
+ #dma-cells = <3>;
+ dma-channels = <32>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+ <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>,
+ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc5 IMX8ULP_CLK_DMA2_MP>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH0>, <&pcc5 IMX8ULP_CLK_DMA2_CH1>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH2>, <&pcc5 IMX8ULP_CLK_DMA2_CH3>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH4>, <&pcc5 IMX8ULP_CLK_DMA2_CH5>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH6>, <&pcc5 IMX8ULP_CLK_DMA2_CH7>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH8>, <&pcc5 IMX8ULP_CLK_DMA2_CH9>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH10>, <&pcc5 IMX8ULP_CLK_DMA2_CH11>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH12>, <&pcc5 IMX8ULP_CLK_DMA2_CH13>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH14>, <&pcc5 IMX8ULP_CLK_DMA2_CH15>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH16>, <&pcc5 IMX8ULP_CLK_DMA2_CH17>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH18>, <&pcc5 IMX8ULP_CLK_DMA2_CH19>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH20>, <&pcc5 IMX8ULP_CLK_DMA2_CH21>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH22>, <&pcc5 IMX8ULP_CLK_DMA2_CH23>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH24>, <&pcc5 IMX8ULP_CLK_DMA2_CH25>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH26>, <&pcc5 IMX8ULP_CLK_DMA2_CH27>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH28>, <&pcc5 IMX8ULP_CLK_DMA2_CH29>,
+ <&pcc5 IMX8ULP_CLK_DMA2_CH30>, <&pcc5 IMX8ULP_CLK_DMA2_CH31>;
+ clock-names = "dma", "ch00","ch01", "ch02", "ch03",
+ "ch04", "ch05", "ch06", "ch07",
+ "ch08", "ch09", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15",
+ "ch16", "ch17", "ch18", "ch19",
+ "ch20", "ch21", "ch22", "ch23",
+ "ch24", "ch25", "ch26", "ch27",
+ "ch28", "ch29", "ch30", "ch31";
+ };
+
cgc2: clock-controller@2da60000 {
compatible = "fsl,imx8ulp-cgc2";
reg = <0x2da60000 0x10000>;
@@ -626,6 +786,60 @@
#clock-cells = <1>;
#reset-cells = <1>;
};
+
+ sai6: sai@2da90000 {
+ compatible = "fsl,imx8ulp-sai";
+ reg = <0x2da90000 0x10000>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc5 IMX8ULP_CLK_SAI6>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc2 IMX8ULP_CLK_SAI6_SEL>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc1 IMX8ULP_CLK_DUMMY>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dmas = <&edma2 71 0 1>, <&edma2 72 0 0>;
+ dma-names = "rx", "tx";
+ #sound-dai-cells = <0>;
+ fsl,dataline = <0 0x0f 0x0f>;
+ status = "disabled";
+ };
+
+ sai7: sai@2daa0000 {
+ compatible = "fsl,imx8ulp-sai";
+ reg = <0x2daa0000 0x10000>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc5 IMX8ULP_CLK_SAI7>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc2 IMX8ULP_CLK_SAI7_SEL>, <&cgc1 IMX8ULP_CLK_DUMMY>,
+ <&cgc1 IMX8ULP_CLK_DUMMY>;
+ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
+ dmas = <&edma2 73 0 1>, <&edma2 74 0 0>;
+ dma-names = "rx", "tx";
+ #sound-dai-cells = <0>;
+ fsl,dataline = <0 0x0f 0x0f>;
+ status = "disabled";
+ };
+
+ spdif: spdif@2dab0000 {
+ compatible = "fsl,imx8ulp-spdif";
+ reg = <0x2dab0000 0x10000>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pcc5 IMX8ULP_CLK_SPDIF>, /* core */
+ <&sosc>, /* 0, extal */
+ <&cgc2 IMX8ULP_CLK_SPDIF_SEL>, /* 1, tx */
+ <&cgc1 IMX8ULP_CLK_DUMMY>, /* 2, tx1 */
+ <&cgc1 IMX8ULP_CLK_DUMMY>, /* 3, tx2 */
+ <&cgc1 IMX8ULP_CLK_DUMMY>, /* 4, tx3 */
+ <&pcc5 IMX8ULP_CLK_SPDIF>, /* 5, sys */
+ <&cgc1 IMX8ULP_CLK_DUMMY>, /* 6, tx4 */
+ <&cgc1 IMX8ULP_CLK_DUMMY>, /* 7, tx5 */
+ <&cgc1 IMX8ULP_CLK_DUMMY>; /* spba */
+ clock-names = "core", "rxtx0",
+ "rxtx1", "rxtx2",
+ "rxtx3", "rxtx4",
+ "rxtx5", "rxtx6",
+ "rxtx7", "spba";
+ dmas = <&edma2 75 0 5>, <&edma2 76 0 4>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
};
gpiod: gpio@2e200000 {
diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
index edba5b582414..d5abfdb8ede2 100644
--- a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
@@ -166,7 +166,7 @@
};
/* Touch controller */
- touchscreen@2c {
+ ad7879_ts: touchscreen@2c {
compatible = "adi,ad7879-1";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ad7879_int>;
@@ -698,7 +698,7 @@
/*
* This pin is used in the SCFW as a UART. Using it from
- * Linux would require rewritting the SCFW board file.
+ * Linux would require rewriting the SCFW board file.
*/
pinctrl_hog_scfw: hogscfwgrp {
fsl,pins = <IMX8QXP_SCU_GPIO0_00_LSIO_GPIO2_IO03 0x20>; /* SODIMM 144 */
diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
index 8d036b3962e9..0e12dcd0d4d1 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
@@ -78,6 +78,23 @@
regulator-max-microvolt = <1800000>;
};
+ reg_audio_pwr: regulator-audio-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "audio-pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&adp5585 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_can2_standby: regulator-can2-standby {
+ compatible = "regulator-fixed";
+ regulator-name = "can2-stby";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&adp5585 6 GPIO_ACTIVE_LOW>;
+ };
+
reg_usdhc2_vmmc: regulator-usdhc2 {
compatible = "regulator-fixed";
pinctrl-names = "default";
@@ -139,6 +156,22 @@
};
};
+ sound-wm8962 {
+ compatible = "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ audio-cpu = <&sai3>;
+ audio-codec = <&wm8962>;
+ hp-det-gpio = <&pcal6524 4 GPIO_ACTIVE_HIGH>;
+ audio-routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Ext Spk", "SPKOUTL",
+ "Ext Spk", "SPKOUTR",
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC",
+ "IN1R", "AMIC";
+ };
+
sound-xcvr {
compatible = "fsl,imx-audio-card";
model = "imx-audio-xcvr";
@@ -216,12 +249,41 @@
};
};
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can2_standby>;
+ status = "okay";
+};
+
&lpi2c1 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpi2c1>;
status = "okay";
+ wm8962: codec@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clk IMX93_CLK_SAI3_GATE>;
+ DCVDD-supply = <&reg_audio_pwr>;
+ DBVDD-supply = <&reg_audio_pwr>;
+ AVDD-supply = <&reg_audio_pwr>;
+ CPVDD-supply = <&reg_audio_pwr>;
+ MICVDD-supply = <&reg_audio_pwr>;
+ PLLVDD-supply = <&reg_audio_pwr>;
+ SPKVDD1-supply = <&reg_audio_pwr>;
+ SPKVDD2-supply = <&reg_audio_pwr>;
+ gpio-cfg = <
+ 0x0000 /* 0:Default */
+ 0x0000 /* 1:Default */
+ 0x0000 /* 2:FN_DMICCLK */
+ 0x0000 /* 3:Default */
+ 0x0000 /* 4:FN_DMICCDAT */
+ 0x0000 /* 5:Default */
+ >;
+ };
+
inertial-meter@6a {
compatible = "st,lsm6dso";
reg = <0x6a>;
@@ -230,9 +292,8 @@
&lpi2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default", "sleep";
+ pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lpi2c2>;
- pinctrl-1 = <&pinctrl_lpi2c2>;
status = "okay";
pcal6524: gpio@22 {
@@ -273,7 +334,7 @@
regulator-ramp-delay = <3125>;
};
- buck4: BUCK4{
+ buck4: BUCK4 {
regulator-name = "BUCK4";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <3400000>;
@@ -281,7 +342,7 @@
regulator-always-on;
};
- buck5: BUCK5{
+ buck5: BUCK5 {
regulator-name = "BUCK5";
regulator-min-microvolt = <1620000>;
regulator-max-microvolt = <3400000>;
@@ -340,6 +401,14 @@
pinctrl-0 = <&pinctrl_lpi2c3>;
status = "okay";
+ adp5585_isp: io-expander@34 {
+ compatible = "adi,adp5585-01", "adi,adp5585";
+ reg = <0x34>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #pwm-cells = <3>;
+ };
+
ptn5110: tcpc@50 {
compatible = "nxp,ptn5110", "tcpci";
reg = <0x50>;
@@ -455,6 +524,17 @@
status = "okay";
};
+&sai3 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_sai3>;
+ pinctrl-1 = <&pinctrl_sai3_sleep>;
+ assigned-clocks = <&clk IMX93_CLK_SAI3>;
+ assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>;
+ assigned-clock-rates = <12288000>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
&usbotg1 {
dr_mode = "otg";
hnp-disable;
@@ -614,6 +694,13 @@
>;
};
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO25__CAN2_TX 0x139e
+ MX93_PAD_GPIO_IO27__CAN2_RX 0x139e
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX93_PAD_UART1_RXD__LPUART1_RX 0x31e
@@ -748,6 +835,26 @@
>;
};
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO26__SAI3_TX_SYNC 0x31e
+ MX93_PAD_GPIO_IO16__SAI3_TX_BCLK 0x31e
+ MX93_PAD_GPIO_IO17__SAI3_MCLK 0x31e
+ MX93_PAD_GPIO_IO19__SAI3_TX_DATA00 0x31e
+ MX93_PAD_GPIO_IO20__SAI3_RX_DATA00 0x31e
+ >;
+ };
+
+ pinctrl_sai3_sleep: sai3sleepgrp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO26__GPIO2_IO26 0x51e
+ MX93_PAD_GPIO_IO16__GPIO2_IO16 0x51e
+ MX93_PAD_GPIO_IO17__GPIO2_IO17 0x51e
+ MX93_PAD_GPIO_IO19__GPIO2_IO19 0x51e
+ MX93_PAD_GPIO_IO20__GPIO2_IO20 0x51e
+ >;
+ };
+
pinctrl_spdif: spdifgrp {
fsl,pins = <
MX93_PAD_GPIO_IO22__SPDIF_IN 0x31e
diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-i3c.dtso b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-i3c.dtso
new file mode 100644
index 000000000000..3fe6209a3423
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-i3c.dtso
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/i3c/i3c.h>
+#include <dt-bindings/usb/pd.h>
+
+#include "imx93-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&lpi2c1 {
+ status = "disabled";
+};
+
+&i3c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i3c1>;
+ #address-cells = <3>;
+ #size-cells = <0>;
+ i2c-scl-hz = <400000>;
+ status = "okay";
+
+ tcpc@50 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x50 0x00 (I2C_FM | I2C_NO_FILTER_LOW_FREQUENCY)>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ power-role = "dual";
+ data-role = "dual";
+ try-power-role = "sink";
+ source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+ sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
+ PDO_VAR(5000, 20000, 3000)>;
+ op-sink-microwatt = <15000000>;
+ self-powered;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ typec1_dr_sw: endpoint {
+ remote-endpoint = <&usb1_drd_sw>;
+ };
+ };
+ };
+ };
+ };
+};
+
+&usb1_drd_sw {
+ remote-endpoint = <&typec1_dr_sw>;
+};
+
+&iomuxc {
+ pinctrl_i3c1: i3c1grp {
+ fsl,pins = <
+ MX93_PAD_I2C1_SCL__I3C1_SCL 0x40000186
+ MX93_PAD_I2C1_SDA__I3C1_SDA 0x40000186
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
index f8a73612fa05..20ec5b3c21f4 100644
--- a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
@@ -12,6 +12,11 @@
model = "NXP i.MX93 9x9 Quick Start Board";
compatible = "fsl,imx93-9x9-qsb", "fsl,imx93";
+ bt_sco_codec: bt-sco-codec {
+ #sound-dai-cells = <1>;
+ compatible = "linux,bt-sco";
+ };
+
chosen {
stdout-path = &lpuart1;
};
@@ -68,6 +73,15 @@
regulator-max-microvolt = <1800000>;
};
+ reg_audio_pwr: regulator-audio-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "audio-pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pcal6524 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
reg_rpi_3v3: regulator-rpi {
compatible = "regulator-fixed";
regulator-name = "VDD_RPI_3V3";
@@ -88,6 +102,55 @@
enable-active-high;
off-on-delay-us = <12000>;
};
+
+ sound-bt-sco {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "bt-sco-audio";
+ simple-audio-card,format = "dsp_a";
+ simple-audio-card,bitclock-inversion;
+ simple-audio-card,frame-master = <&btcpu>;
+ simple-audio-card,bitclock-master = <&btcpu>;
+
+ btcpu: simple-audio-card,cpu {
+ sound-dai = <&sai1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <16>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&bt_sco_codec 1>;
+ };
+ };
+
+ sound-micfil {
+ compatible = "fsl,imx-audio-card";
+ model = "micfil-audio";
+
+ pri-dai-link {
+ link-name = "micfil hifi";
+ format = "i2s";
+
+ cpu {
+ sound-dai = <&micfil>;
+ };
+ };
+ };
+
+ sound-wm8962 {
+ compatible = "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ audio-cpu = <&sai3>;
+ audio-codec = <&wm8962>;
+ hp-det-gpio = <&pcal6524 4 GPIO_ACTIVE_HIGH>;
+ audio-routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Ext Spk", "SPKOUTL",
+ "Ext Spk", "SPKOUTR",
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC",
+ "IN1R", "AMIC";
+ };
};
&adc1 {
@@ -136,6 +199,28 @@
pinctrl-0 = <&pinctrl_lpi2c1>;
status = "okay";
+ wm8962: audio-codec@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clk IMX93_CLK_SAI3_GATE>;
+ DCVDD-supply = <&reg_audio_pwr>;
+ DBVDD-supply = <&reg_audio_pwr>;
+ AVDD-supply = <&reg_audio_pwr>;
+ CPVDD-supply = <&reg_audio_pwr>;
+ MICVDD-supply = <&reg_audio_pwr>;
+ PLLVDD-supply = <&reg_audio_pwr>;
+ SPKVDD1-supply = <&reg_audio_pwr>;
+ SPKVDD2-supply = <&reg_audio_pwr>;
+ gpio-cfg = <
+ 0x0000 /* 0:Default */
+ 0x0000 /* 1:Default */
+ 0x0000 /* 2:FN_DMICCLK */
+ 0x0000 /* 3:Default */
+ 0x0000 /* 4:FN_DMICCDAT */
+ 0x0000 /* 5:Default */
+ >;
+ };
+
ptn5110: tcpc@50 {
compatible = "nxp,ptn5110", "tcpci";
reg = <0x50>;
@@ -194,6 +279,18 @@
interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcal6524>;
+
+ exp-sel-hog {
+ gpio-hog;
+ gpios = <22 GPIO_ACTIVE_HIGH>;
+ output-low;
+ };
+
+ mic-can-sel-hog {
+ gpio-hog;
+ gpios = <17 GPIO_ACTIVE_HIGH>;
+ output-low;
+ };
};
pmic@25 {
@@ -221,7 +318,7 @@
regulator-ramp-delay = <3125>;
};
- buck4: BUCK4{
+ buck4: BUCK4 {
regulator-name = "BUCK4";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <3400000>;
@@ -229,7 +326,7 @@
regulator-always-on;
};
- buck5: BUCK5{
+ buck5: BUCK5 {
regulator-name = "BUCK5";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <3400000>;
@@ -278,6 +375,15 @@
status = "okay";
};
+&micfil {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pdm>;
+ assigned-clocks = <&clk IMX93_CLK_PDM>;
+ assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>;
+ assigned-clock-rates = <49152000>;
+ status = "okay";
+};
+
&mu1 {
status = "okay";
};
@@ -286,6 +392,27 @@
status = "okay";
};
+&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ assigned-clocks = <&clk IMX93_CLK_SAI1>;
+ assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>;
+ assigned-clock-rates = <12288000>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
+&sai3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3>;
+ assigned-clocks = <&clk IMX93_CLK_SAI3>;
+ assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>;
+ assigned-clock-rates = <12288000>;
+ fsl,sai-mclk-direction-output;
+ fsl,sai-synchronous-rx;
+ status = "okay";
+};
+
&usbotg1 {
dr_mode = "otg";
hnp-disable;
@@ -370,6 +497,14 @@
>;
};
+ pinctrl_pdm: pdmgrp {
+ fsl,pins = <
+ MX93_PAD_PDM_CLK__PDM_CLK 0x31e
+ MX93_PAD_PDM_BIT_STREAM0__PDM_BIT_STREAM00 0x31e
+ MX93_PAD_PDM_BIT_STREAM1__PDM_BIT_STREAM01 0x31e
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX93_PAD_UART1_RXD__LPUART1_RX 0x31e
@@ -443,6 +578,25 @@
>;
};
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX93_PAD_SAI1_TXC__SAI1_TX_BCLK 0x31e
+ MX93_PAD_SAI1_TXFS__SAI1_TX_SYNC 0x31e
+ MX93_PAD_SAI1_TXD0__SAI1_TX_DATA00 0x31e
+ MX93_PAD_SAI1_RXD0__SAI1_RX_DATA00 0x31e
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX93_PAD_GPIO_IO12__SAI3_RX_SYNC 0x31e
+ MX93_PAD_GPIO_IO18__SAI3_RX_BCLK 0x31e
+ MX93_PAD_GPIO_IO17__SAI3_MCLK 0x31e
+ MX93_PAD_GPIO_IO19__SAI3_TX_DATA00 0x31e
+ MX93_PAD_GPIO_IO20__SAI3_RX_DATA00 0x31e
+ >;
+ };
+
pinctrl_usdhc2_gpio: usdhc2gpiogrp {
fsl,pins = <
MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e
diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
index 04b9b3d31f4f..688488de8cd2 100644
--- a/arch/arm64/boot/dts/freescale/imx93.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
@@ -42,6 +42,14 @@
serial5 = &lpuart6;
serial6 = &lpuart7;
serial7 = &lpuart8;
+ spi0 = &lpspi1;
+ spi1 = &lpspi2;
+ spi2 = &lpspi3;
+ spi3 = &lpspi4;
+ spi4 = &lpspi5;
+ spi5 = &lpspi6;
+ spi6 = &lpspi7;
+ spi7 = &lpspi8;
};
cpus {
diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
index 37a1d4ca1b20..6086cb7fa5a0 100644
--- a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
@@ -8,11 +8,33 @@
#include <dt-bindings/pwm/pwm.h>
#include "imx95.dtsi"
+#define FALLING_EDGE 1
+#define RISING_EDGE 2
+
+#define BRD_SM_CTRL_SD3_WAKE 0x8000 /* PCAL6408A-0 */
+#define BRD_SM_CTRL_PCIE1_WAKE 0x8001 /* PCAL6408A-4 */
+#define BRD_SM_CTRL_BT_WAKE 0x8002 /* PCAL6408A-5 */
+#define BRD_SM_CTRL_PCIE2_WAKE 0x8003 /* PCAL6408A-6 */
+#define BRD_SM_CTRL_BUTTON 0x8004 /* PCAL6408A-7 */
+
/ {
model = "NXP i.MX95 19X19 board";
compatible = "fsl,imx95-19x19-evk", "fsl,imx95";
aliases {
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
+ gpio4 = &gpio5;
+ i2c0 = &lpi2c1;
+ i2c1 = &lpi2c2;
+ i2c2 = &lpi2c3;
+ i2c3 = &lpi2c4;
+ i2c4 = &lpi2c5;
+ i2c5 = &lpi2c6;
+ i2c6 = &lpi2c7;
+ i2c7 = &lpi2c8;
mmc0 = &usdhc1;
mmc1 = &usdhc2;
serial0 = &lpuart1;
@@ -232,6 +254,42 @@
};
};
+&lpi2c5 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c5>;
+ status = "okay";
+
+ i2c5_pcal6408: gpio@21 {
+ compatible = "nxp,pcal6408";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ vcc-supply = <&reg_3p3v>;
+ };
+};
+
+&lpi2c6 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpi2c6>;
+ status = "okay";
+
+ i2c6_pcal6416: gpio@21 {
+ compatible = "nxp,pcal6416";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcal6416>;
+ vcc-supply = <&reg_3p3v>;
+ };
+};
+
&lpi2c7 {
clock-frequency = <1000000>;
pinctrl-names = "default";
@@ -357,6 +415,14 @@
status = "okay";
};
+&scmi_misc {
+ nxp,ctrl-ids = <BRD_SM_CTRL_SD3_WAKE FALLING_EDGE
+ BRD_SM_CTRL_PCIE1_WAKE FALLING_EDGE
+ BRD_SM_CTRL_BT_WAKE FALLING_EDGE
+ BRD_SM_CTRL_PCIE2_WAKE FALLING_EDGE
+ BRD_SM_CTRL_BUTTON FALLING_EDGE>;
+};
+
&wdog3 {
fsl,ext-reset-output;
status = "okay";
@@ -410,6 +476,20 @@
>;
};
+ pinctrl_lpi2c5: lpi2c5grp {
+ fsl,pins = <
+ IMX95_PAD_GPIO_IO22__LPI2C5_SDA 0x40000b9e
+ IMX95_PAD_GPIO_IO23__LPI2C5_SCL 0x40000b9e
+ >;
+ };
+
+ pinctrl_lpi2c6: lpi2c6grp {
+ fsl,pins = <
+ IMX95_PAD_GPIO_IO02__LPI2C6_SDA 0x40000b9e
+ IMX95_PAD_GPIO_IO03__LPI2C6_SCL 0x40000b9e
+ >;
+ };
+
pinctrl_lpi2c7: lpi2c7grp {
fsl,pins = <
IMX95_PAD_GPIO_IO08__LPI2C7_SDA 0x40000b9e
@@ -429,6 +509,12 @@
>;
};
+ pinctrl_pcal6416: pcal6416grp {
+ fsl,pins = <
+ IMX95_PAD_CCM_CLKO3__GPIO4_IO_BIT28 0x31e
+ >;
+ };
+
pinctrl_pdm: pdmgrp {
fsl,pins = <
IMX95_PAD_PDM_CLK__AONMIX_TOP_PDM_CLK 0x31e
diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
index 03661e76550f..d10f62eacfe0 100644
--- a/arch/arm64/boot/dts/freescale/imx95.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
@@ -22,12 +22,27 @@
#address-cells = <1>;
#size-cells = <0>;
+ idle-states {
+ entry-method = "psci";
+
+ cpu_pd_wait: cpu-pd-wait {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x0010033>;
+ local-timer-stop;
+ entry-latency-us = <10000>;
+ exit-latency-us = <7000>;
+ min-residency-us = <27000>;
+ wakeup-latency-us = <15000>;
+ };
+ };
+
A55_0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0>;
enable-method = "psci";
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
power-domains = <&scmi_perf IMX95_PERF_A55>;
power-domain-names = "perf";
i-cache-size = <32768>;
@@ -45,6 +60,7 @@
reg = <0x100>;
enable-method = "psci";
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
power-domains = <&scmi_perf IMX95_PERF_A55>;
power-domain-names = "perf";
i-cache-size = <32768>;
@@ -62,6 +78,7 @@
reg = <0x200>;
enable-method = "psci";
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
power-domains = <&scmi_perf IMX95_PERF_A55>;
power-domain-names = "perf";
i-cache-size = <32768>;
@@ -79,6 +96,7 @@
reg = <0x300>;
enable-method = "psci";
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
power-domains = <&scmi_perf IMX95_PERF_A55>;
power-domain-names = "perf";
i-cache-size = <32768>;
@@ -98,6 +116,7 @@
power-domain-names = "perf";
enable-method = "psci";
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
i-cache-size = <32768>;
i-cache-line-size = <64>;
i-cache-sets = <128>;
@@ -115,6 +134,7 @@
power-domain-names = "perf";
enable-method = "psci";
#cooling-cells = <2>;
+ cpu-idle-states = <&cpu_pd_wait>;
i-cache-size = <32768>;
i-cache-line-size = <64>;
i-cache-sets = <128>;
@@ -293,12 +313,17 @@
shmem = <&scmi_buf0>, <&scmi_buf1>;
#address-cells = <1>;
#size-cells = <0>;
+ arm,max-rx-timeout-ms = <5000>;
scmi_devpd: protocol@11 {
reg = <0x11>;
#power-domain-cells = <1>;
};
+ scmi_sys_power: protocol@12 {
+ reg = <0x12>;
+ };
+
scmi_perf: protocol@13 {
reg = <0x13>;
#power-domain-cells = <1>;
@@ -318,6 +343,13 @@
reg = <0x19>;
};
+ scmi_bbm: protocol@81 {
+ reg = <0x81>;
+ };
+
+ scmi_misc: protocol@84 {
+ reg = <0x84>;
+ };
};
};
@@ -334,13 +366,13 @@
trips {
cpu_alert0: trip0 {
- temperature = <85000>;
+ temperature = <105000>;
hysteresis = <2000>;
type = "passive";
};
cpu_crit0: trip1 {
- temperature = <95000>;
+ temperature = <125000>;
hysteresis = <2000>;
type = "critical";
};
@@ -359,6 +391,38 @@
};
};
};
+
+ ana-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&scmi_sensor 0>;
+ trips {
+ ana_alert: trip0 {
+ temperature = <105000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ ana_crit0: trip1 {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&ana_alert>;
+ cooling-device =
+ <&A55_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A55_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A55_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A55_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A55_4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A55_5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
};
psci {
diff --git a/arch/arm64/boot/dts/freescale/mba8mx.dtsi b/arch/arm64/boot/dts/freescale/mba8mx.dtsi
index c60c7a9e54af..58e3865c2889 100644
--- a/arch/arm64/boot/dts/freescale/mba8mx.dtsi
+++ b/arch/arm64/boot/dts/freescale/mba8mx.dtsi
@@ -100,7 +100,6 @@
port {
panel_in_lvds: endpoint {
- data-lanes = <1 2 3 4>;
remote-endpoint = <&lvds_bridge_out>;
};
};
@@ -318,11 +317,6 @@
};
};
-&mipi_dsi {
- samsung,burst-clock-frequency = <891000000>;
- samsung,esc-clock-frequency = <20000000>;
-};
-
&mipi_dsi_out {
data-lanes = <1 2 3 4>;
remote-endpoint = <&lvds_bridge_in>;
diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi
index fa054bfe7d5c..7be430b78c83 100644
--- a/arch/arm64/boot/dts/freescale/s32g2.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi
@@ -162,6 +162,159 @@
slew-rate = <166>;
};
};
+
+ pinctrl_usdhc0: usdhc0grp-pins {
+ usdhc0-grp0 {
+ pinmux = <0x2e1>,
+ <0x381>;
+ output-enable;
+ bias-pull-down;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp1 {
+ pinmux = <0x2f1>,
+ <0x301>,
+ <0x311>,
+ <0x321>,
+ <0x331>,
+ <0x341>,
+ <0x351>,
+ <0x361>,
+ <0x371>;
+ output-enable;
+ input-enable;
+ bias-pull-up;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp2 {
+ pinmux = <0x391>;
+ output-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp3 {
+ pinmux = <0x3a0>;
+ input-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp4 {
+ pinmux = <0x2032>,
+ <0x2042>,
+ <0x2052>,
+ <0x2062>,
+ <0x2072>,
+ <0x2082>,
+ <0x2092>,
+ <0x20a2>,
+ <0x20b2>,
+ <0x20c2>;
+ };
+ };
+
+ pinctrl_usdhc0_100mhz: usdhc0-100mhzgrp-pins {
+ usdhc0-100mhz-grp0 {
+ pinmux = <0x2e1>,
+ <0x381>;
+ output-enable;
+ bias-pull-down;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp1 {
+ pinmux = <0x2f1>,
+ <0x301>,
+ <0x311>,
+ <0x321>,
+ <0x331>,
+ <0x341>,
+ <0x351>,
+ <0x361>,
+ <0x371>;
+ output-enable;
+ input-enable;
+ bias-pull-up;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp2 {
+ pinmux = <0x391>;
+ output-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp3 {
+ pinmux = <0x3a0>;
+ input-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp4 {
+ pinmux = <0x2032>,
+ <0x2042>,
+ <0x2052>,
+ <0x2062>,
+ <0x2072>,
+ <0x2082>,
+ <0x2092>,
+ <0x20a2>,
+ <0x20b2>,
+ <0x20c2>;
+ };
+ };
+
+ pinctrl_usdhc0_200mhz: usdhc0-200mhzgrp-pins {
+ usdhc0-200mhz-grp0 {
+ pinmux = <0x2e1>,
+ <0x381>;
+ output-enable;
+ bias-pull-down;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp1 {
+ pinmux = <0x2f1>,
+ <0x301>,
+ <0x311>,
+ <0x321>,
+ <0x331>,
+ <0x341>,
+ <0x351>,
+ <0x361>,
+ <0x371>;
+ output-enable;
+ input-enable;
+ bias-pull-up;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp2 {
+ pinmux = <0x391>;
+ output-enable;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp3 {
+ pinmux = <0x3a0>;
+ input-enable;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp4 {
+ pinmux = <0x2032>,
+ <0x2042>,
+ <0x2052>,
+ <0x2062>,
+ <0x2072>,
+ <0x2082>,
+ <0x2092>,
+ <0x20a2>,
+ <0x20b2>,
+ <0x20c2>;
+ };
+ };
};
uart0: serial@401c8000 {
diff --git a/arch/arm64/boot/dts/freescale/s32g274a-evb.dts b/arch/arm64/boot/dts/freescale/s32g274a-evb.dts
index dbe498798bd9..b9a119eea2b7 100644
--- a/arch/arm64/boot/dts/freescale/s32g274a-evb.dts
+++ b/arch/arm64/boot/dts/freescale/s32g274a-evb.dts
@@ -34,6 +34,11 @@
};
&usdhc0 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc0>;
+ pinctrl-1 = <&pinctrl_usdhc0_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc0_200mhz>;
disable-wp;
+ no-1-8-v;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts b/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts
index ab1e5caaeae7..aaa61a8ad0da 100644
--- a/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts
+++ b/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts
@@ -40,6 +40,19 @@
};
&usdhc0 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc0>;
+ pinctrl-1 = <&pinctrl_usdhc0_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc0_200mhz>;
disable-wp;
+ /* Remove no-1-8-v to enable higher speed modes for SD card.
+ * However, this is not enough to enable HS400 or HS200 modes for eMMC.
+ * In this case, the position of the resistor R797 must be changed
+ * from A to B before removing the property.
+ * If the property is removed without changing the resistor position,
+ * HS*00 may be enabled, but the interface might be unstable because of
+ * the wrong VCCQ voltage applied to the eMMC.
+ */
+ no-1-8-v;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/s32g3.dtsi b/arch/arm64/boot/dts/freescale/s32g3.dtsi
index b4226a9143c8..6c572ffe37ca 100644
--- a/arch/arm64/boot/dts/freescale/s32g3.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g3.dtsi
@@ -219,6 +219,159 @@
slew-rate = <166>;
};
};
+
+ pinctrl_usdhc0: usdhc0grp-pins {
+ usdhc0-grp0 {
+ pinmux = <0x2e1>,
+ <0x381>;
+ output-enable;
+ bias-pull-down;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp1 {
+ pinmux = <0x2f1>,
+ <0x301>,
+ <0x311>,
+ <0x321>,
+ <0x331>,
+ <0x341>,
+ <0x351>,
+ <0x361>,
+ <0x371>;
+ output-enable;
+ input-enable;
+ bias-pull-up;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp2 {
+ pinmux = <0x391>;
+ output-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp3 {
+ pinmux = <0x3a0>;
+ input-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-grp4 {
+ pinmux = <0x2032>,
+ <0x2042>,
+ <0x2052>,
+ <0x2062>,
+ <0x2072>,
+ <0x2082>,
+ <0x2092>,
+ <0x20a2>,
+ <0x20b2>,
+ <0x20c2>;
+ };
+ };
+
+ pinctrl_usdhc0_100mhz: usdhc0-100mhzgrp-pins {
+ usdhc0-100mhz-grp0 {
+ pinmux = <0x2e1>,
+ <0x381>;
+ output-enable;
+ bias-pull-down;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp1 {
+ pinmux = <0x2f1>,
+ <0x301>,
+ <0x311>,
+ <0x321>,
+ <0x331>,
+ <0x341>,
+ <0x351>,
+ <0x361>,
+ <0x371>;
+ output-enable;
+ input-enable;
+ bias-pull-up;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp2 {
+ pinmux = <0x391>;
+ output-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp3 {
+ pinmux = <0x3a0>;
+ input-enable;
+ slew-rate = <150>;
+ };
+
+ usdhc0-100mhz-grp4 {
+ pinmux = <0x2032>,
+ <0x2042>,
+ <0x2052>,
+ <0x2062>,
+ <0x2072>,
+ <0x2082>,
+ <0x2092>,
+ <0x20a2>,
+ <0x20b2>,
+ <0x20c2>;
+ };
+ };
+
+ pinctrl_usdhc0_200mhz: usdhc0-200mhzgrp-pins {
+ usdhc0-200mhz-grp0 {
+ pinmux = <0x2e1>,
+ <0x381>;
+ output-enable;
+ bias-pull-down;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp1 {
+ pinmux = <0x2f1>,
+ <0x301>,
+ <0x311>,
+ <0x321>,
+ <0x331>,
+ <0x341>,
+ <0x351>,
+ <0x361>,
+ <0x371>;
+ output-enable;
+ input-enable;
+ bias-pull-up;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp2 {
+ pinmux = <0x391>;
+ output-enable;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp3 {
+ pinmux = <0x3a0>;
+ input-enable;
+ slew-rate = <208>;
+ };
+
+ usdhc0-200mhz-grp4 {
+ pinmux = <0x2032>,
+ <0x2042>,
+ <0x2052>,
+ <0x2062>,
+ <0x2072>,
+ <0x2082>,
+ <0x2092>,
+ <0x20a2>,
+ <0x20b2>,
+ <0x20c2>;
+ };
+ };
};
uart0: serial@401c8000 {
diff --git a/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts b/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts
index 176e5af191c8..828e353455b5 100644
--- a/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts
+++ b/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts
@@ -40,6 +40,10 @@
};
&usdhc0 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc0>;
+ pinctrl-1 = <&pinctrl_usdhc0_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc0_200mhz>;
bus-width = <8>;
disable-wp;
status = "okay";
diff --git a/arch/arm64/boot/dts/lg/lg1312.dtsi b/arch/arm64/boot/dts/lg/lg1312.dtsi
index b864ffa74ea8..bb0bcc6875dc 100644
--- a/arch/arm64/boot/dts/lg/lg1312.dtsi
+++ b/arch/arm64/boot/dts/lg/lg1312.dtsi
@@ -173,15 +173,15 @@
compatible = "arm,pl022", "arm,primecell";
reg = <0x0 0xfe800000 0x1000>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_bus>;
- clock-names = "apb_pclk";
+ clocks = <&clk_bus>, <&clk_bus>;
+ clock-names = "sspclk", "apb_pclk";
};
spi1: spi@fe900000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x0 0xfe900000 0x1000>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_bus>;
- clock-names = "apb_pclk";
+ clocks = <&clk_bus>, <&clk_bus>;
+ clock-names = "sspclk", "apb_pclk";
};
dmac0: dma-controller@c1128000 {
compatible = "arm,pl330", "arm,primecell";
diff --git a/arch/arm64/boot/dts/lg/lg1313.dtsi b/arch/arm64/boot/dts/lg/lg1313.dtsi
index 996fb39bb50c..c07d670bc465 100644
--- a/arch/arm64/boot/dts/lg/lg1313.dtsi
+++ b/arch/arm64/boot/dts/lg/lg1313.dtsi
@@ -173,15 +173,15 @@
compatible = "arm,pl022", "arm,primecell";
reg = <0x0 0xfe800000 0x1000>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_bus>;
- clock-names = "apb_pclk";
+ clocks = <&clk_bus>, <&clk_bus>;
+ clock-names = "sspclk", "apb_pclk";
};
spi1: spi@fe900000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x0 0xfe900000 0x1000>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_bus>;
- clock-names = "apb_pclk";
+ clocks = <&clk_bus>, <&clk_bus>;
+ clock-names = "sspclk", "apb_pclk";
};
dmac0: dma-controller@c1128000 {
compatible = "arm,pl330", "arm,primecell";
diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
index 5e5baf6beea4..1e0ab35cc686 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
@@ -214,7 +214,6 @@
sata-port@1 {
phys = <&cp0_comphy3 1>;
- phy-names = "cp0-sata0-1-phy";
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts b/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts
index 40b7ee7ead72..7af949092b91 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts
@@ -433,13 +433,11 @@
/* 7 + 12 SATA connector (J24) */
sata-port@0 {
phys = <&cp0_comphy2 0>;
- phy-names = "cp0-sata0-0-phy";
};
/* M.2-2250 B-key (J39) */
sata-port@1 {
phys = <&cp0_comphy3 1>;
- phy-names = "cp0-sata0-1-phy";
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
index 67892f0d2863..7005a32a6e1e 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
@@ -475,7 +475,6 @@
sata-port@1 {
phys = <&cp1_comphy0 1>;
- phy-names = "cp1-sata0-1-phy";
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
index 92897bd7e6cf..2ec19d364e62 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
@@ -145,11 +145,9 @@
sata-port@0 {
phys = <&cp0_comphy1 0>;
- phy-names = "cp0-sata0-0-phy";
};
sata-port@1 {
phys = <&cp0_comphy3 1>;
- phy-names = "cp0-sata0-1-phy";
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
index c864df9ec84d..e88ff5b179c8 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
@@ -245,7 +245,6 @@
/* CPM Lane 5 - U29 */
sata-port@1 {
phys = <&cp0_comphy5 1>;
- phy-names = "cp0-sata0-1-phy";
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts b/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts
index 42a60f3dd5d1..3e5e0651ce68 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts
@@ -408,12 +408,10 @@
sata-port@0 {
phys = <&cp0_comphy2 0>;
- phy-names = "cp0-sata0-0-phy";
};
sata-port@1 {
phys = <&cp0_comphy5 1>;
- phy-names = "cp0-sata0-1-phy";
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt6358.dtsi b/arch/arm64/boot/dts/mediatek/mt6358.dtsi
index 641d452fbc08..e23672a2eea4 100644
--- a/arch/arm64/boot/dts/mediatek/mt6358.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6358.dtsi
@@ -15,12 +15,12 @@
#io-channel-cells = <1>;
};
- mt6358codec: mt6358codec {
+ mt6358codec: audio-codec {
compatible = "mediatek,mt6358-sound";
mediatek,dmic-mode = <0>; /* two-wires */
};
- mt6358regulator: mt6358regulator {
+ mt6358regulator: regulators {
compatible = "mediatek,mt6358-regulator";
mt6358_vdram1_reg: buck_vdram1 {
diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
index aa728331e876..c9649b815276 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
@@ -86,7 +86,7 @@
#clock-cells = <1>;
};
- clock-controller@1001b000 {
+ topckgen: clock-controller@1001b000 {
compatible = "mediatek,mt7988-topckgen", "syscon";
reg = <0 0x1001b000 0 0x1000>;
#clock-cells = <1>;
@@ -124,6 +124,39 @@
status = "disabled";
};
+ serial@11000000 {
+ compatible = "mediatek,mt7988-uart", "mediatek,mt6577-uart";
+ reg = <0 0x11000000 0 0x100>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uart", "wakeup";
+ clocks = <&topckgen CLK_TOP_UART_SEL>,
+ <&infracfg CLK_INFRA_52M_UART0_CK>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ serial@11000100 {
+ compatible = "mediatek,mt7988-uart", "mediatek,mt6577-uart";
+ reg = <0 0x11000100 0 0x100>;
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uart", "wakeup";
+ clocks = <&topckgen CLK_TOP_UART_SEL>,
+ <&infracfg CLK_INFRA_52M_UART1_CK>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ serial@11000200 {
+ compatible = "mediatek,mt7988-uart", "mediatek,mt6577-uart";
+ reg = <0 0x11000200 0 0x100>;
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uart", "wakeup";
+ clocks = <&topckgen CLK_TOP_UART_SEL>,
+ <&infracfg CLK_INFRA_52M_UART2_CK>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
i2c@11003000 {
compatible = "mediatek,mt7981-i2c";
reg = <0 0x11003000 0 0x1000>,
@@ -198,6 +231,13 @@
#clock-cells = <1>;
};
+ efuse@11f50000 {
+ compatible = "mediatek,mt7988-efuse", "mediatek,efuse";
+ reg = <0 0x11f50000 0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
clock-controller@15000000 {
compatible = "mediatek,mt7988-ethsys", "syscon";
reg = <0 0x15000000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
index 8d1cbc92bce3..dfc5c2f0ddef 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
@@ -14,6 +14,7 @@
compatible = "melfas,mip4_ts";
reg = <0x34>;
interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;
+ status = "fail-needs-probe";
};
/*
@@ -26,6 +27,7 @@
reg = <0x20>;
hid-descr-addr = <0x0020>;
interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;
+ status = "fail-needs-probe";
};
/* Lenovo Ideapad C330 uses G2Touch touchscreen as a 2nd source touchscreen */
@@ -35,6 +37,7 @@
hid-descr-addr = <0x0001>;
interrupt-parent = <&pio>;
interrupts = <88 IRQ_TYPE_LEVEL_LOW>;
+ status = "fail-needs-probe";
};
};
@@ -47,9 +50,20 @@
trackpad2: trackpad@2c {
compatible = "hid-over-i2c";
interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&trackpad_irq>;
reg = <0x2c>;
hid-descr-addr = <0x0020>;
+ /*
+ * The trackpad needs a post-power-on delay of 100ms,
+ * but at time of writing, the power supply for it on
+ * this board is always on. The delay is therefore not
+ * added to avoid impacting the readiness of the
+ * trackpad.
+ */
+ vdd-supply = <&mt6397_vgp6_reg>;
wakeup-source;
+ status = "fail-needs-probe";
};
};
@@ -74,3 +88,11 @@
};
};
};
+
+&touchscreen {
+ status = "fail-needs-probe";
+};
+
+&trackpad {
+ status = "fail-needs-probe";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
index b4d85147b77b..eee64461421f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
@@ -358,12 +358,12 @@
&i2c4 {
clock-frequency = <400000>;
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&trackpad_irq>;
trackpad: trackpad@15 {
compatible = "elan,ekth3000";
interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&trackpad_irq>;
reg = <0x15>;
vcc-supply = <&mt6397_vgp6_reg>;
wakeup-source;
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts
index 19c1e2bee494..20b71f2e7159 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts
@@ -30,3 +30,6 @@
};
};
+&i2c2 {
+ i2c-scl-internal-delay-ns = <4100>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
index f34964afe39b..83bbcfe62083 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
@@ -18,6 +18,8 @@
};
&i2c2 {
+ i2c-scl-internal-delay-ns = <25000>;
+
trackpad@2c {
compatible = "hid-over-i2c";
reg = <0x2c>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts
index 0b45aee2e299..65860b33c01f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts
@@ -30,3 +30,6 @@
qcom,ath10k-calibration-variant = "GO_DAMU";
};
+&i2c2 {
+ i2c-scl-internal-delay-ns = <20000>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi
index bbe6c338f465..f9c1ec366b26 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi
@@ -25,3 +25,6 @@
};
};
+&i2c2 {
+ i2c-scl-internal-delay-ns = <21500>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
index 783c333107bc..49e053b932e7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
@@ -8,28 +8,32 @@
#include <arm/cros-ec-keyboard.dtsi>
/ {
- pp1200_mipibrdg: pp1200-mipibrdg {
+ pp1000_mipibrdg: pp1000-mipibrdg {
compatible = "regulator-fixed";
- regulator-name = "pp1200_mipibrdg";
+ regulator-name = "pp1000_mipibrdg";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
pinctrl-names = "default";
- pinctrl-0 = <&pp1200_mipibrdg_en>;
+ pinctrl-0 = <&pp1000_mipibrdg_en>;
enable-active-high;
regulator-boot-on;
gpio = <&pio 54 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&pp1800_alw>;
};
pp1800_mipibrdg: pp1800-mipibrdg {
compatible = "regulator-fixed";
regulator-name = "pp1800_mipibrdg";
pinctrl-names = "default";
- pinctrl-0 = <&pp1800_lcd_en>;
+ pinctrl-0 = <&pp1800_mipibrdg_en>;
enable-active-high;
regulator-boot-on;
gpio = <&pio 36 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&pp1800_alw>;
};
pp3300_panel: pp3300-panel {
@@ -44,18 +48,20 @@
regulator-boot-on;
gpio = <&pio 35 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&pp3300_alw>;
};
- vddio_mipibrdg: vddio-mipibrdg {
+ pp3300_mipibrdg: pp3300-mipibrdg {
compatible = "regulator-fixed";
- regulator-name = "vddio_mipibrdg";
+ regulator-name = "pp3300_mipibrdg";
pinctrl-names = "default";
- pinctrl-0 = <&vddio_mipibrdg_en>;
+ pinctrl-0 = <&pp3300_mipibrdg_en>;
enable-active-high;
regulator-boot-on;
gpio = <&pio 37 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&pp3300_alw>;
};
volume_buttons: volume-buttons {
@@ -146,9 +152,9 @@
pinctrl-0 = <&anx7625_pins>;
enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
- vdd10-supply = <&pp1200_mipibrdg>;
+ vdd10-supply = <&pp1000_mipibrdg>;
vdd18-supply = <&pp1800_mipibrdg>;
- vdd33-supply = <&vddio_mipibrdg>;
+ vdd33-supply = <&pp3300_mipibrdg>;
ports {
#address-cells = <1>;
@@ -391,14 +397,14 @@
"",
"";
- pp1200_mipibrdg_en: pp1200-mipibrdg-en {
+ pp1000_mipibrdg_en: pp1000-mipibrdg-en {
pins1 {
pinmux = <PINMUX_GPIO54__FUNC_GPIO54>;
output-low;
};
};
- pp1800_lcd_en: pp1800-lcd-en {
+ pp1800_mipibrdg_en: pp1800-mipibrdg-en {
pins1 {
pinmux = <PINMUX_GPIO36__FUNC_GPIO36>;
output-low;
@@ -460,7 +466,7 @@
};
};
- vddio_mipibrdg_en: vddio-mipibrdg-en {
+ pp3300_mipibrdg_en: pp3300-mipibrdg-en {
pins1 {
pinmux = <PINMUX_GPIO37__FUNC_GPIO37>;
output-low;
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
index bfb9e42c8aca..ff02f63bac29 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
@@ -92,9 +92,9 @@
clock-frequency = <400000>;
vbus-supply = <&mt6358_vcn18_reg>;
- eeprom@54 {
+ eeprom@50 {
compatible = "atmel,24c32";
- reg = <0x54>;
+ reg = <0x50>;
pagesize = <32>;
vcc-supply = <&mt6358_vcn18_reg>;
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku32.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku32.dts
index 05361008e8ac..2b5a8d1f900e 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku32.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku32.dts
@@ -23,7 +23,7 @@
interrupts-extended = <&pio 155 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&pio 156 GPIO_ACTIVE_LOW>;
- vdd-supply = <&lcd_pp3300>;
+ vdd-supply = <&pp3300_alw>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku38.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku38.dts
index cf008ed82878..75fadf2c7059 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku38.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-katsu-sku38.dts
@@ -23,7 +23,7 @@
interrupts-extended = <&pio 155 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&pio 156 GPIO_ACTIVE_LOW>;
- vdd-supply = <&lcd_pp3300>;
+ vdd-supply = <&pp3300_alw>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
index 5c1bf6a1e475..da6e767b4cee 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
@@ -79,9 +79,9 @@
clock-frequency = <400000>;
vbus-supply = <&mt6358_vcn18_reg>;
- eeprom@54 {
+ eeprom@50 {
compatible = "atmel,24c64";
- reg = <0x54>;
+ reg = <0x50>;
pagesize = <32>;
vcc-supply = <&mt6358_vcn18_reg>;
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
index 0f5fa893a774..8b56b8564ed7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
@@ -88,9 +88,9 @@
clock-frequency = <400000>;
vbus-supply = <&mt6358_vcn18_reg>;
- eeprom@54 {
+ eeprom@50 {
compatible = "atmel,24c32";
- reg = <0x54>;
+ reg = <0x50>;
pagesize = <32>;
vcc-supply = <&mt6358_vcn18_reg>;
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
index 22924f61ec9e..4b974bb781b1 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
@@ -52,27 +52,6 @@
vin-supply = <&pp1800_alw>;
};
- lcd_pp3300: regulator1 {
- compatible = "regulator-fixed";
- regulator-name = "lcd_pp3300";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- mmc1_fixed_power: regulator3 {
- compatible = "regulator-fixed";
- regulator-name = "mmc1_power";
- vin-supply = <&pp3300_alw>;
- };
-
- mmc1_fixed_io: regulator4 {
- compatible = "regulator-fixed";
- regulator-name = "mmc1_io";
- vin-supply = <&pp1800_alw>;
- };
-
pp1800_alw: regulator5 {
compatible = "regulator-fixed";
regulator-name = "pp1800_alw";
@@ -290,6 +269,11 @@
};
};
+&dpi0 {
+ /* TODO Re-enable after DP to Type-C port muxing can be described */
+ status = "disabled";
+};
+
&gic {
mediatek,broken-save-restore-fw;
};
@@ -369,8 +353,8 @@
pinctrl-names = "default", "state_uhs";
pinctrl-0 = <&mmc1_pins_default>;
pinctrl-1 = <&mmc1_pins_uhs>;
- vmmc-supply = <&mmc1_fixed_power>;
- vqmmc-supply = <&mmc1_fixed_io>;
+ vmmc-supply = <&pp3300_alw>;
+ vqmmc-supply = <&pp1800_alw>;
mmc-pwrseq = <&wifi_pwrseq>;
bus-width = <4>;
max-frequency = <200000000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
index 1aa668c3ccf9..61a6f66914b8 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts
@@ -63,6 +63,18 @@
pulldown-ohm = <0>;
io-channels = <&auxadc 0>;
};
+
+ connector {
+ compatible = "hdmi-connector";
+ label = "hdmi";
+ type = "d";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_connector_out>;
+ };
+ };
+ };
};
&auxadc {
@@ -120,6 +132,43 @@
pinctrl-0 = <&i2c6_pins>;
status = "okay";
clock-frequency = <100000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ it66121hdmitx: hdmitx@4c {
+ compatible = "ite,it66121";
+ reg = <0x4c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ite_pins>;
+ reset-gpios = <&pio 160 GPIO_ACTIVE_LOW>;
+ interrupt-parent = <&pio>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ vcn33-supply = <&mt6358_vcn33_reg>;
+ vcn18-supply = <&mt6358_vcn18_reg>;
+ vrf12-supply = <&mt6358_vrf12_reg>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ it66121_in: endpoint {
+ bus-width = <12>;
+ remote-endpoint = <&dpi_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ hdmi_connector_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+ };
+ };
+ };
};
&keyboard {
@@ -362,6 +411,67 @@
input-enable;
};
};
+
+ ite_pins: ite-pins {
+ pins-irq {
+ pinmux = <PINMUX_GPIO4__FUNC_GPIO4>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-rst {
+ pinmux = <PINMUX_GPIO160__FUNC_GPIO160>;
+ output-high;
+ };
+ };
+
+ dpi_func_pins: dpi-func-pins {
+ pins-dpi {
+ pinmux = <PINMUX_GPIO12__FUNC_I2S5_BCK>,
+ <PINMUX_GPIO46__FUNC_I2S5_LRCK>,
+ <PINMUX_GPIO47__FUNC_I2S5_DO>,
+ <PINMUX_GPIO13__FUNC_DBPI_D0>,
+ <PINMUX_GPIO14__FUNC_DBPI_D1>,
+ <PINMUX_GPIO15__FUNC_DBPI_D2>,
+ <PINMUX_GPIO16__FUNC_DBPI_D3>,
+ <PINMUX_GPIO17__FUNC_DBPI_D4>,
+ <PINMUX_GPIO18__FUNC_DBPI_D5>,
+ <PINMUX_GPIO19__FUNC_DBPI_D6>,
+ <PINMUX_GPIO20__FUNC_DBPI_D7>,
+ <PINMUX_GPIO21__FUNC_DBPI_D8>,
+ <PINMUX_GPIO22__FUNC_DBPI_D9>,
+ <PINMUX_GPIO23__FUNC_DBPI_D10>,
+ <PINMUX_GPIO24__FUNC_DBPI_D11>,
+ <PINMUX_GPIO25__FUNC_DBPI_HSYNC>,
+ <PINMUX_GPIO26__FUNC_DBPI_VSYNC>,
+ <PINMUX_GPIO27__FUNC_DBPI_DE>,
+ <PINMUX_GPIO28__FUNC_DBPI_CK>;
+ };
+ };
+
+ dpi_idle_pins: dpi-idle-pins {
+ pins-idle {
+ pinmux = <PINMUX_GPIO12__FUNC_GPIO12>,
+ <PINMUX_GPIO46__FUNC_GPIO46>,
+ <PINMUX_GPIO47__FUNC_GPIO47>,
+ <PINMUX_GPIO13__FUNC_GPIO13>,
+ <PINMUX_GPIO14__FUNC_GPIO14>,
+ <PINMUX_GPIO15__FUNC_GPIO15>,
+ <PINMUX_GPIO16__FUNC_GPIO16>,
+ <PINMUX_GPIO17__FUNC_GPIO17>,
+ <PINMUX_GPIO18__FUNC_GPIO18>,
+ <PINMUX_GPIO19__FUNC_GPIO19>,
+ <PINMUX_GPIO20__FUNC_GPIO20>,
+ <PINMUX_GPIO21__FUNC_GPIO21>,
+ <PINMUX_GPIO22__FUNC_GPIO22>,
+ <PINMUX_GPIO23__FUNC_GPIO23>,
+ <PINMUX_GPIO24__FUNC_GPIO24>,
+ <PINMUX_GPIO25__FUNC_GPIO25>,
+ <PINMUX_GPIO26__FUNC_GPIO26>,
+ <PINMUX_GPIO27__FUNC_GPIO27>,
+ <PINMUX_GPIO28__FUNC_GPIO28>;
+ };
+ };
};
&pmic {
@@ -415,3 +525,16 @@
&dsi0 {
status = "disabled";
};
+
+&dpi0 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&dpi_func_pins>;
+ pinctrl-1 = <&dpi_idle_pins>;
+ status = "okay";
+
+ port {
+ dpi_out: endpoint {
+ remote-endpoint = <&it66121_in>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 266441e999f2..1afeeb1155f5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -1845,6 +1845,10 @@
<&mmsys CLK_MM_DPI_MM>,
<&apmixedsys CLK_APMIXED_TVDPLL>;
clock-names = "pixel", "engine", "pll";
+
+ port {
+ dpi_out: endpoint { };
+ };
};
mutex: mutex@14016000 {
@@ -1974,6 +1978,23 @@
power-domains = <&spm MT8183_POWER_DOMAIN_VENC>;
};
+ vcodec_enc: vcodec@17020000 {
+ compatible = "mediatek,mt8183-vcodec-enc";
+ reg = <0 0x17020000 0 0x1000>;
+ interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_LOW>;
+ iommus = <&iommu M4U_PORT_VENC_REC>,
+ <&iommu M4U_PORT_VENC_BSDMA>,
+ <&iommu M4U_PORT_VENC_RD_COMV>,
+ <&iommu M4U_PORT_VENC_CUR_LUMA>,
+ <&iommu M4U_PORT_VENC_CUR_CHROMA>,
+ <&iommu M4U_PORT_VENC_REF_LUMA>,
+ <&iommu M4U_PORT_VENC_REF_CHROMA>;
+ mediatek,scp = <&scp>;
+ power-domains = <&spm MT8183_POWER_DOMAIN_VENC>;
+ clocks = <&vencsys CLK_VENC_VENC>;
+ clock-names = "venc_sel";
+ };
+
venc_jpg: jpeg-encoder@17030000 {
compatible = "mediatek,mt8183-jpgenc", "mediatek,mtk-jpgenc";
reg = <0 0x17030000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi
index 52ec58128d56..b495a241b443 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola-voltorb.dtsi
@@ -10,12 +10,6 @@
/ {
chassis-type = "laptop";
-
- max98360a: max98360a {
- compatible = "maxim,max98360a";
- sdmode-gpios = <&pio 150 GPIO_ACTIVE_HIGH>;
- #sound-dai-cells = <0>;
- };
};
&cpu6 {
@@ -59,19 +53,14 @@
opp-hz = /bits/ 64 <2200000000>;
};
-&rt1019p{
- status = "disabled";
-};
-
&sound {
compatible = "mediatek,mt8186-mt6366-rt5682s-max98360-sound";
- status = "okay";
+};
- spk-hdmi-playback-dai-link {
- codec {
- sound-dai = <&it6505dptx>, <&max98360a>;
- };
- };
+&speaker_codec {
+ compatible = "maxim,max98360a";
+ sdmode-gpios = <&pio 150 GPIO_ACTIVE_HIGH>;
+ /delete-property/ sdb-gpios;
};
&spmi {
diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
index 682c6ad2574d..cfcc7909dfe6 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
@@ -259,15 +259,15 @@
mediatek,clk-provider = "cpu";
/* RT1019P and IT6505 connected to the same I2S line */
codec {
- sound-dai = <&it6505dptx>, <&rt1019p>;
+ sound-dai = <&it6505dptx>, <&speaker_codec>;
};
};
};
- rt1019p: speaker-codec {
+ speaker_codec: speaker-codec {
compatible = "realtek,rt1019p";
pinctrl-names = "default";
- pinctrl-0 = <&rt1019p_pins_default>;
+ pinctrl-0 = <&speaker_codec_pins_default>;
#sound-dai-cells = <0>;
sdb-gpios = <&pio 150 GPIO_ACTIVE_HIGH>;
};
@@ -423,7 +423,7 @@
#sound-dai-cells = <0>;
ovdd-supply = <&mt6366_vsim2_reg>;
pwr18-supply = <&pp1800_dpbrdg_dx>;
- reset-gpios = <&pio 177 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&pio 177 GPIO_ACTIVE_LOW>;
ports {
#address-cells = <1>;
@@ -1179,7 +1179,7 @@
};
};
- rt1019p_pins_default: rt1019p-default-pins {
+ speaker_codec_pins_default: speaker-codec-default-pins {
pins-sdb {
pinmux = <PINMUX_GPIO150__FUNC_GPIO150>;
output-low;
@@ -1336,7 +1336,7 @@
regulator-allowed-modes = <MT6397_BUCK_MODE_AUTO
MT6397_BUCK_MODE_FORCE_PWM>;
regulator-coupled-with = <&mt6366_vsram_gpu_reg>;
- regulator-coupled-max-spread = <10000>;
+ regulator-coupled-max-spread = <100000>;
};
mt6366_vproc11_reg: vproc11 {
@@ -1545,7 +1545,7 @@
regulator-ramp-delay = <6250>;
regulator-enable-ramp-delay = <240>;
regulator-coupled-with = <&mt6366_vgpu_reg>;
- regulator-coupled-max-spread = <10000>;
+ regulator-coupled-max-spread = <100000>;
};
mt6366_vsram_others_reg: vsram-others {
diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
index 148c332018b0..d3c3c2a40adc 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
@@ -29,6 +29,13 @@
rdma1 = &rdma1;
};
+ fhctl: fhctl@1000ce00 {
+ compatible = "mediatek,mt8186-fhctl";
+ clocks = <&apmixedsys CLK_APMIXED_TVDPLL>;
+ reg = <0 0x1000ce00 0 0x200>;
+ status = "disabled";
+ };
+
cci: cci {
compatible = "mediatek,mt8186-cci";
clocks = <&mcusys CLK_MCU_ARMPLL_BUS_SEL>,
diff --git a/arch/arm64/boot/dts/mediatek/mt8188-evb.dts b/arch/arm64/boot/dts/mediatek/mt8188-evb.dts
index 68a82b49f7a3..f89835ac36f3 100644
--- a/arch/arm64/boot/dts/mediatek/mt8188-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8188-evb.dts
@@ -140,8 +140,6 @@
&nor_flash {
pinctrl-names = "default";
pinctrl-0 = <&nor_pins_default>;
- #address-cells = <1>;
- #size-cells = <0>;
status = "okay";
flash@0 {
diff --git a/arch/arm64/boot/dts/mediatek/mt8188.dtsi b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
index cd27966d2e3c..faccc7f16259 100644
--- a/arch/arm64/boot/dts/mediatek/mt8188.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8188.dtsi
@@ -9,6 +9,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/mailbox/mediatek,mt8188-gce.h>
+#include <dt-bindings/memory/mediatek,mt8188-memory-port.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/mediatek,mt8188-pinfunc.h>
#include <dt-bindings/power/mediatek,mt8188-power.h>
@@ -22,6 +23,37 @@
#address-cells = <2>;
#size-cells = <2>;
+ aliases {
+ dp-intf0 = &dp_intf0;
+ dp-intf1 = &dp_intf1;
+ ethdr0 = &ethdr0;
+ gce0 = &gce0;
+ gce1 = &gce1;
+ merge1 = &merge1;
+ merge2 = &merge2;
+ merge3 = &merge3;
+ merge4 = &merge4;
+ merge5 = &merge5;
+ mutex0 = &mutex0;
+ mutex1 = &mutex1;
+ padding0 = &padding0;
+ padding1 = &padding1;
+ padding2 = &padding2;
+ padding3 = &padding3;
+ padding4 = &padding4;
+ padding5 = &padding5;
+ padding6 = &padding6;
+ padding7 = &padding7;
+ vdo1-rdma0 = &vdo1_rdma0;
+ vdo1-rdma1 = &vdo1_rdma1;
+ vdo1-rdma2 = &vdo1_rdma2;
+ vdo1-rdma3 = &vdo1_rdma3;
+ vdo1-rdma4 = &vdo1_rdma4;
+ vdo1-rdma5 = &vdo1_rdma5;
+ vdo1-rdma6 = &vdo1_rdma6;
+ vdo1-rdma7 = &vdo1_rdma7;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -41,6 +73,7 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&l2_0>;
+ performance-domains = <&performance 0>;
#cooling-cells = <2>;
};
@@ -59,6 +92,7 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&l2_0>;
+ performance-domains = <&performance 0>;
#cooling-cells = <2>;
};
@@ -77,6 +111,7 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&l2_0>;
+ performance-domains = <&performance 0>;
#cooling-cells = <2>;
};
@@ -95,6 +130,7 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&l2_0>;
+ performance-domains = <&performance 0>;
#cooling-cells = <2>;
};
@@ -113,6 +149,7 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&l2_0>;
+ performance-domains = <&performance 0>;
#cooling-cells = <2>;
};
@@ -131,6 +168,7 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&l2_0>;
+ performance-domains = <&performance 0>;
#cooling-cells = <2>;
};
@@ -149,6 +187,7 @@
d-cache-line-size = <64>;
d-cache-sets = <256>;
next-level-cache = <&l2_1>;
+ performance-domains = <&performance 1>;
#cooling-cells = <2>;
};
@@ -167,6 +206,7 @@
d-cache-line-size = <64>;
d-cache-sets = <256>;
next-level-cache = <&l2_1>;
+ performance-domains = <&performance 1>;
#cooling-cells = <2>;
};
@@ -420,6 +460,11 @@
method = "smc";
};
+ sound: sound {
+ mediatek,platform = <&afe>;
+ status = "disabled";
+ };
+
thermal_zones: thermal-zones {
cpu-little0-thermal {
polling-delay = <1000>;
@@ -878,8 +923,15 @@
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
+ dma-ranges = <0x0 0x0 0x0 0x0 0x4 0x0>;
ranges;
+ performance: performance-controller@11bc10 {
+ compatible = "mediatek,cpufreq-hw";
+ reg = <0 0x0011bc10 0 0x120>, <0 0x0011bd30 0 0x120>;
+ #performance-domain-cells = <1>;
+ };
+
gic: interrupt-controller@c000000 {
compatible = "arm,gic-v3";
#interrupt-cells = <4>;
@@ -956,9 +1008,9 @@
#size-cells = <0>;
#power-domain-cells = <1>;
- power-domain@MT8188_POWER_DOMAIN_MFG1 {
+ mfg1: power-domain@MT8188_POWER_DOMAIN_MFG1 {
reg = <MT8188_POWER_DOMAIN_MFG1>;
- clocks = <&topckgen CLK_APMIXED_MFGPLL>,
+ clocks = <&apmixedsys CLK_APMIXED_MFGPLL>,
<&topckgen CLK_TOP_MFG_CORE_TMP>;
clock-names = "mfg", "alt";
mediatek,infracfg = <&infracfg_ao>;
@@ -1061,20 +1113,22 @@
#power-domain-cells = <0>;
};
- power-domain@MT8188_POWER_DOMAIN_VDEC1 {
- reg = <MT8188_POWER_DOMAIN_VDEC1>;
- clocks = <&vdecsys CLK_VDEC2_LARB1>;
- clock-names = "ss-vdec";
- mediatek,infracfg = <&infracfg_ao>;
- #power-domain-cells = <0>;
- };
-
power-domain@MT8188_POWER_DOMAIN_VDEC0 {
reg = <MT8188_POWER_DOMAIN_VDEC0>;
clocks = <&vdecsys_soc CLK_VDEC1_SOC_LARB1>;
- clock-names = "ss-vdec";
+ clock-names = "ss-vdec1-soc-l1";
mediatek,infracfg = <&infracfg_ao>;
- #power-domain-cells = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+
+ power-domain@MT8188_POWER_DOMAIN_VDEC1 {
+ reg = <MT8188_POWER_DOMAIN_VDEC1>;
+ clocks = <&vdecsys CLK_VDEC2_LARB1>;
+ clock-names = "ss-vdec2-l1";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
};
cam_vcore: power-domain@MT8188_POWER_DOMAIN_CAM_VCORE {
@@ -1291,6 +1345,25 @@
clock-names = "spi", "wrap";
};
+ spmi: spmi@10027000 {
+ compatible = "mediatek,mt8188-spmi", "mediatek,mt8195-spmi";
+ reg = <0 0x10027000 0 0xe00>, <0 0x10029000 0 0x100>;
+ reg-names = "pmif", "spmimst";
+ assigned-clocks = <&topckgen CLK_TOP_SPMI_M_MST>;
+ assigned-clock-parents = <&topckgen CLK_TOP_ULPOSC1_D10>;
+ clocks = <&infracfg_ao CLK_INFRA_AO_PMIC_AP>,
+ <&infracfg_ao CLK_INFRA_AO_PMIC_TMR>,
+ <&topckgen CLK_TOP_SPMI_M_MST>;
+ clock-names = "pmif_sys_ck", "pmif_tmr_ck", "spmimst_clk_mux";
+ };
+
+ infra_iommu: iommu@10315000 {
+ compatible = "mediatek,mt8188-iommu-infra";
+ reg = <0 0x10315000 0 0x1000>;
+ interrupts = <GIC_SPI 795 IRQ_TYPE_LEVEL_HIGH 0>;
+ #iommu-cells = <1>;
+ };
+
gce0: mailbox@10320000 {
compatible = "mediatek,mt8188-gce";
reg = <0 0x10320000 0 0x4000>;
@@ -1315,6 +1388,97 @@
interrupts = <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH 0>;
};
+ afe: audio-controller@10b10000 {
+ compatible = "mediatek,mt8188-afe";
+ reg = <0 0x10b10000 0 0x10000>;
+ assigned-clocks = <&topckgen CLK_TOP_A1SYS_HP>;
+ assigned-clock-parents = <&clk26m>;
+ clocks = <&clk26m>,
+ <&apmixedsys CLK_APMIXED_APLL1>,
+ <&apmixedsys CLK_APMIXED_APLL2>,
+ <&topckgen CLK_TOP_APLL12_CK_DIV0>,
+ <&topckgen CLK_TOP_APLL12_CK_DIV1>,
+ <&topckgen CLK_TOP_APLL12_CK_DIV2>,
+ <&topckgen CLK_TOP_APLL12_CK_DIV3>,
+ <&topckgen CLK_TOP_APLL12_CK_DIV9>,
+ <&topckgen CLK_TOP_A1SYS_HP>,
+ <&topckgen CLK_TOP_AUD_INTBUS>,
+ <&topckgen CLK_TOP_AUDIO_H>,
+ <&topckgen CLK_TOP_AUDIO_LOCAL_BUS>,
+ <&topckgen CLK_TOP_DPTX>,
+ <&topckgen CLK_TOP_I2SO1>,
+ <&topckgen CLK_TOP_I2SO2>,
+ <&topckgen CLK_TOP_I2SI1>,
+ <&topckgen CLK_TOP_I2SI2>,
+ <&adsp_audio26m CLK_AUDIODSP_AUDIO26M>,
+ <&topckgen CLK_TOP_APLL1_D4>,
+ <&topckgen CLK_TOP_APLL2_D4>,
+ <&topckgen CLK_TOP_APLL12_CK_DIV4>,
+ <&topckgen CLK_TOP_A2SYS>,
+ <&topckgen CLK_TOP_AUD_IEC>;
+ clock-names = "clk26m",
+ "apll1",
+ "apll2",
+ "apll12_div0",
+ "apll12_div1",
+ "apll12_div2",
+ "apll12_div3",
+ "apll12_div9",
+ "top_a1sys_hp",
+ "top_aud_intbus",
+ "top_audio_h",
+ "top_audio_local_bus",
+ "top_dptx",
+ "top_i2so1",
+ "top_i2so2",
+ "top_i2si1",
+ "top_i2si2",
+ "adsp_audio_26m",
+ "apll1_d4",
+ "apll2_d4",
+ "apll12_div4",
+ "top_a2sys",
+ "top_aud_iec";
+ interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_AUDIO>;
+ resets = <&watchdog MT8188_TOPRGU_AUDIO_SW_RST>;
+ reset-names = "audiosys";
+ mediatek,infracfg = <&infracfg_ao>;
+ mediatek,topckgen = <&topckgen>;
+ status = "disabled";
+ };
+
+ adsp: adsp@10b80000 {
+ compatible = "mediatek,mt8188-dsp";
+ reg = <0 0x10b80000 0 0x2000>,
+ <0 0x10d00000 0 0x80000>,
+ <0 0x10b8b000 0 0x100>,
+ <0 0x10b8f000 0 0x1000>;
+ reg-names = "cfg", "sram", "sec", "bus";
+ assigned-clocks = <&topckgen CLK_TOP_ADSP>;
+ clocks = <&topckgen CLK_TOP_ADSP>,
+ <&topckgen CLK_TOP_AUDIO_LOCAL_BUS>;
+ clock-names = "audiodsp", "adsp_bus";
+ mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>;
+ mbox-names = "rx", "tx";
+ power-domains = <&spm MT8188_POWER_DOMAIN_ADSP>;
+ status = "disabled";
+ };
+
+ adsp_mailbox0: mailbox@10b86100 {
+ compatible = "mediatek,mt8188-adsp-mbox", "mediatek,mt8186-adsp-mbox";
+ reg = <0 0x10b86100 0 0x1000>;
+ interrupts = <GIC_SPI 478 IRQ_TYPE_LEVEL_HIGH 0>;
+ #mbox-cells = <0>;
+ };
+
+ adsp_mailbox1: mailbox@10b87100 {
+ compatible = "mediatek,mt8188-adsp-mbox", "mediatek,mt8186-adsp-mbox";
+ reg = <0 0x10b87100 0 0x1000>;
+ interrupts = <GIC_SPI 479 IRQ_TYPE_LEVEL_HIGH 0>;
+ #mbox-cells = <0>;
+ };
+
adsp_audio26m: clock-controller@10b91100 {
compatible = "mediatek,mt8188-adsp-audio26m";
reg = <0 0x10b91100 0 0x100>;
@@ -1396,6 +1560,28 @@
#thermal-sensor-cells = <1>;
};
+ disp_pwm0: pwm@1100e000 {
+ compatible = "mediatek,mt8188-disp-pwm", "mediatek,mt8183-disp-pwm";
+ reg = <0 0x1100e000 0 0x1000>;
+ clocks = <&topckgen CLK_TOP_DISP_PWM0>,
+ <&infracfg_ao CLK_INFRA_AO_DISP_PWM>;
+ clock-names = "main", "mm";
+ interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
+ disp_pwm1: pwm@1100f000 {
+ compatible = "mediatek,mt8188-disp-pwm", "mediatek,mt8183-disp-pwm";
+ reg = <0 0x1100f000 0 0x1000>;
+ clocks = <&topckgen CLK_TOP_DISP_PWM1>,
+ <&infracfg_ao CLK_INFRA_AO_DISP_PWM1>;
+ clock-names = "main", "mm";
+ interrupts = <GIC_SPI 793 IRQ_TYPE_LEVEL_HIGH 0>;
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
spi1: spi@11010000 {
compatible = "mediatek,mt8188-spi-ipm", "mediatek,spi-ipm";
#address-cells = <1>;
@@ -1461,6 +1647,103 @@
status = "disabled";
};
+ eth: ethernet@11021000 {
+ compatible = "mediatek,mt8188-gmac", "mediatek,mt8195-gmac",
+ "snps,dwmac-5.10a";
+ reg = <0 0x11021000 0 0x4000>;
+ interrupts = <GIC_SPI 716 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "macirq";
+ clocks = <&pericfg_ao CLK_PERI_AO_ETHERNET>,
+ <&pericfg_ao CLK_PERI_AO_ETHERNET_BUS>,
+ <&topckgen CLK_TOP_SNPS_ETH_250M>,
+ <&topckgen CLK_TOP_SNPS_ETH_62P4M_PTP>,
+ <&topckgen CLK_TOP_SNPS_ETH_50M_RMII>,
+ <&pericfg_ao CLK_PERI_AO_ETHERNET_MAC>;
+ clock-names = "axi", "apb", "mac_main", "ptp_ref",
+ "rmii_internal", "mac_cg";
+ assigned-clocks = <&topckgen CLK_TOP_SNPS_ETH_250M>,
+ <&topckgen CLK_TOP_SNPS_ETH_62P4M_PTP>,
+ <&topckgen CLK_TOP_SNPS_ETH_50M_RMII>;
+ assigned-clock-parents = <&topckgen CLK_TOP_ETHPLL_D2>,
+ <&topckgen CLK_TOP_ETHPLL_D8>,
+ <&topckgen CLK_TOP_ETHPLL_D10>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_ETHER>;
+ mediatek,pericfg = <&infracfg_ao>;
+ snps,axi-config = <&stmmac_axi_setup>;
+ snps,mtl-rx-config = <&mtl_rx_setup>;
+ snps,mtl-tx-config = <&mtl_tx_setup>;
+ snps,txpbl = <16>;
+ snps,rxpbl = <16>;
+ snps,clk-csr = <0>;
+ status = "disabled";
+
+ eth_mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ stmmac_axi_setup: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <0x7>;
+ snps,wr_osr_lmt = <0x7>;
+ };
+
+ mtl_rx_setup: rx-queues-config {
+ snps,rx-queues-to-use = <4>;
+ snps,rx-sched-sp;
+
+ queue0 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x0>;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x0>;
+ };
+
+ queue2 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x0>;
+ };
+
+ queue3 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x0>;
+ };
+ };
+
+ mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <4>;
+ snps,tx-sched-wrr;
+
+ queue0 {
+ snps,dcb-algorithm;
+ snps,priority = <0x0>;
+ snps,weight = <0x10>;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ snps,priority = <0x1>;
+ snps,weight = <0x11>;
+ };
+
+ queue2 {
+ snps,dcb-algorithm;
+ snps,priority = <0x2>;
+ snps,weight = <0x12>;
+ };
+
+ queue3 {
+ snps,dcb-algorithm;
+ snps,priority = <0x3>;
+ snps,weight = <0x13>;
+ };
+ };
+ };
+
xhci1: usb@11200000 {
compatible = "mediatek,mt8188-xhci", "mediatek,mtk-xhci";
reg = <0 0x11200000 0 0x1000>,
@@ -1606,6 +1889,54 @@
status = "disabled";
};
+ pcie: pcie@112f0000 {
+ compatible = "mediatek,mt8188-pcie", "mediatek,mt8192-pcie";
+ reg = <0 0x112f0000 0 0x2000>;
+ reg-names = "pcie-mac";
+ ranges = <0x82000000 0 0x20000000 0 0x20000000 0 0x4000000>;
+ bus-range = <0 0xff>;
+ device_type = "pci";
+ linux,pci-domain = <0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ 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_FMEM>;
+ clock-names = "pl_250m", "tl_26m", "tl_96m", "tl_32k",
+ "peri_26m", "peri_mem";
+
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 791 IRQ_TYPE_LEVEL_HIGH 0>;
+ 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>;
+
+ iommu-map = <0 &infra_iommu IFR_IOMMU_PORT_PCIE_0 0xffff>;
+ iommu-map-mask = <0>;
+
+ phys = <&pcieport PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy";
+
+ power-domains = <&spm MT8188_POWER_DOMAIN_PEXTP_MAC_P0>;
+
+ resets = <&watchdog MT8188_TOPRGU_PCIE_SW_RST>;
+ reset-names = "mac";
+
+ status = "disabled";
+
+ pcie_intc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
nor_flash: spi@1132c000 {
compatible = "mediatek,mt8188-nor", "mediatek,mt8186-nor";
reg = <0 0x1132c000 0 0x1000>;
@@ -1615,6 +1946,44 @@
clock-names = "spi", "sf", "axi";
assigned-clocks = <&topckgen CLK_TOP_SPINOR>;
interrupts = <GIC_SPI 825 IRQ_TYPE_LEVEL_HIGH 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ pciephy: t-phy@11c20700 {
+ compatible = "mediatek,mt8188-tphy", "mediatek,generic-tphy-v3";
+ ranges = <0 0 0x11c20700 0x700>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_PEXTP_PHY_TOP>;
+ status = "disabled";
+
+ pcieport: pcie-phy@0 {
+ reg = <0 0x700>;
+ clocks = <&topckgen CLK_TOP_CFGREG_F_PCIE_PHY_REF>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ };
+ };
+
+ mipi_tx_config0: dsi-phy@11c80000 {
+ compatible = "mediatek,mt8188-mipi-tx", "mediatek,mt8183-mipi-tx";
+ reg = <0 0x11c80000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-output-names = "mipi_tx0_pll";
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
+ mipi_tx_config1: dsi-phy@11c90000 {
+ compatible = "mediatek,mt8188-mipi-tx", "mediatek,mt8183-mipi-tx";
+ reg = <0 0x11c90000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-output-names = "mipi_tx0_pll";
+ #clock-cells = <0>;
+ #phy-cells = <0>;
status = "disabled";
};
@@ -1689,7 +2058,6 @@
<&clk26m>;
clock-names = "ref", "da_ref";
#phy-cells = <1>;
- status = "disabled";
};
};
@@ -1749,9 +2117,21 @@
#address-cells = <1>;
#size-cells = <1>;
+ dp_calib_data: dp-calib@1a0 {
+ reg = <0x1a0 0xc>;
+ };
+
lvts_efuse_data1: lvts1-calib@1ac {
reg = <0x1ac 0x40>;
};
+
+ socinfo-data1@7a0 {
+ reg = <0x7a0 0x4>;
+ };
+
+ socinfo-data2@7e0 {
+ reg = <0x7e0 0x4>;
+ };
};
gpu: gpu@13000000 {
@@ -1778,12 +2158,43 @@
#clock-cells = <1>;
};
- vppsys0: clock-controller@14000000 {
- compatible = "mediatek,mt8188-vppsys0";
+ vppsys0: syscon@14000000 {
+ compatible = "mediatek,mt8188-vppsys0", "syscon";
reg = <0 0x14000000 0 0x1000>;
#clock-cells = <1>;
};
+ vpp_smi_common: smi@14012000 {
+ compatible = "mediatek,mt8188-smi-common-vpp";
+ reg = <0 0x14012000 0 0x1000>;
+ clocks = <&vppsys0 CLK_VPP0_SMI_COMMON_LARB4>,
+ <&vppsys0 CLK_VPP0_SMI_SUB_COMMON_REORDER>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VPPSYS0>;
+ };
+
+ larb4: smi@14013000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x14013000 0 0x1000>;
+ clocks = <&vppsys0 CLK_VPP0_SMI_COMMON_LARB4>,
+ <&vppsys0 CLK_VPP0_SMI_COMMON_LARB4>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VPPSYS0>;
+ mediatek,larb-id = <SMI_L4_ID>;
+ mediatek,smi = <&vpp_smi_common>;
+ };
+
+ vpp_iommu: iommu@14018000 {
+ compatible = "mediatek,mt8188-iommu-vpp";
+ reg = <0 0x14018000 0 0x5000>;
+ clocks = <&vppsys0 CLK_VPP0_SMI_IOMMU>;
+ clock-names = "bclk";
+ interrupts = <GIC_SPI 594 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VPPSYS0>;
+ #iommu-cells = <1>;
+ mediatek,larbs = <&larb1 &larb3 &larb4 &larb6 &larb7 &larb23>;
+ };
+
wpesys: clock-controller@14e00000 {
compatible = "mediatek,mt8188-wpesys";
reg = <0 0x14e00000 0 0x1000>;
@@ -1796,12 +2207,45 @@
#clock-cells = <1>;
};
- vppsys1: clock-controller@14f00000 {
- compatible = "mediatek,mt8188-vppsys1";
+ larb7: smi@14e04000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x14e04000 0 0x1000>;
+ clocks = <&wpesys CLK_WPE_TOP_SMI_LARB7>,
+ <&wpesys CLK_WPE_TOP_SMI_LARB7>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_WPE>;
+ mediatek,larb-id = <SMI_L7_ID>;
+ mediatek,smi = <&vpp_smi_common>;
+ };
+
+ vppsys1: syscon@14f00000 {
+ compatible = "mediatek,mt8188-vppsys1", "syscon";
reg = <0 0x14f00000 0 0x1000>;
#clock-cells = <1>;
};
+ larb5: smi@14f02000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x14f02000 0 0x1000>;
+ clocks = <&vppsys1 CLK_VPP1_GALS5>,
+ <&vppsys1 CLK_VPP1_LARB5>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VPPSYS1>;
+ mediatek,larb-id = <SMI_L5_ID>;
+ mediatek,smi = <&vdo_smi_common>;
+ };
+
+ larb6: smi@14f03000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x14f03000 0 0x1000>;
+ clocks = <&vppsys1 CLK_VPP1_GALS6>,
+ <&vppsys1 CLK_VPP1_LARB6>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VPPSYS1>;
+ mediatek,larb-id = <SMI_L6_ID>;
+ mediatek,smi = <&vpp_smi_common>;
+ };
+
imgsys: clock-controller@15000000 {
compatible = "mediatek,mt8188-imgsys";
reg = <0 0x15000000 0 0x1000>;
@@ -1880,12 +2324,92 @@
#clock-cells = <1>;
};
+ video_decoder: video-decoder@18000000 {
+ compatible = "mediatek,mt8188-vcodec-dec";
+ reg = <0 0x18000000 0 0x1000>, <0 0x18004000 0 0x1000>;
+ ranges = <0 0 0 0x18000000 0 0x26000>;
+ iommus = <&vpp_iommu M4U_PORT_L23_HW_VDEC_UFO_ENC_EXT>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ mediatek,scp = <&scp>;
+
+ video-codec@10000 {
+ compatible = "mediatek,mtk-vcodec-lat";
+ reg = <0 0x10000 0 0x800>;
+ assigned-clocks = <&topckgen CLK_TOP_VDEC>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D6>;
+ clocks = <&topckgen CLK_TOP_VDEC>,
+ <&vdecsys_soc CLK_VDEC1_SOC_VDEC>,
+ <&vdecsys_soc CLK_VDEC1_SOC_LAT>,
+ <&topckgen CLK_TOP_UNIVPLL_D6>;
+ clock-names = "sel", "vdec", "lat", "top";
+ interrupts = <GIC_SPI 708 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vpp_iommu M4U_PORT_L23_HW_VDEC_LAT0_VLD_EXT>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_LAT0_VLD2_EXT>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_LAT0_AVC_MV_EXT>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_LAT0_PRED_RD_EXT>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_LAT0_TILE_EXT>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_LAT0_WDMA_EXT>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_UFO_ENC_EXT>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_UFO_ENC_EXT_C>,
+ <&vpp_iommu M4U_PORT_L23_HW_VDEC_MC_EXT_C>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDEC0>;
+ };
+
+ video-codec@25000 {
+ compatible = "mediatek,mtk-vcodec-core";
+ reg = <0 0x25000 0 0x1000>;
+ assigned-clocks = <&topckgen CLK_TOP_VDEC>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D6>;
+ clocks = <&topckgen CLK_TOP_VDEC>,
+ <&vdecsys CLK_VDEC2_VDEC>,
+ <&vdecsys CLK_VDEC2_LAT>,
+ <&topckgen CLK_TOP_UNIVPLL_D6>;
+ clock-names = "sel", "vdec", "lat", "top";
+ interrupts = <GIC_SPI 707 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L21_HW_VDEC_MC_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_UFO_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_PP_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_PRED_RD_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_PRED_WR_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_PPWRAP_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_TILE_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_VLD_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_VLD2_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_AVC_MV_EXT>,
+ <&vdo_iommu M4U_PORT_L21_HW_VDEC_UFO_EXT_C>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDEC1>;
+ };
+ };
+
+ larb23: smi@1800d000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x1800d000 0 0x1000>;
+ clocks = <&vdecsys_soc CLK_VDEC1_SOC_LARB1>,
+ <&vdecsys_soc CLK_VDEC1_SOC_LARB1>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDEC0>;
+ mediatek,larb-id = <SMI_L23_ID>;
+ mediatek,smi = <&vpp_smi_common>;
+ };
+
vdecsys_soc: clock-controller@1800f000 {
compatible = "mediatek,mt8188-vdecsys-soc";
reg = <0 0x1800f000 0 0x1000>;
#clock-cells = <1>;
};
+ larb21: smi@1802e000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x1802e000 0 0x1000>;
+ clocks = <&vdecsys CLK_VDEC2_LARB1>,
+ <&vdecsys CLK_VDEC2_LARB1>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDEC1>;
+ mediatek,larb-id = <SMI_L21_ID>;
+ mediatek,smi = <&vdo_smi_common>;
+ };
+
vdecsys: clock-controller@1802f000 {
compatible = "mediatek,mt8188-vdecsys";
reg = <0 0x1802f000 0 0x1000>;
@@ -1898,14 +2422,249 @@
#clock-cells = <1>;
};
+ larb19: smi@1a010000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x1a010000 0 0x1000>;
+ clocks = <&vencsys CLK_VENC1_VENC>,
+ <&vencsys CLK_VENC1_VENC>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VENC>;
+ mediatek,larb-id = <SMI_L19_ID>;
+ mediatek,smi = <&vdo_smi_common>;
+ };
+
+ video_encoder: video-encoder@1a020000 {
+ compatible = "mediatek,mt8188-vcodec-enc";
+ reg = <0 0x1a020000 0 0x10000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ assigned-clocks = <&topckgen CLK_TOP_VENC>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
+ clocks = <&vencsys CLK_VENC1_VENC>;
+ clock-names = "venc_sel";
+ interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L19_VENC_RCPU>,
+ <&vdo_iommu M4U_PORT_L19_VENC_REC>,
+ <&vdo_iommu M4U_PORT_L19_VENC_BSDMA>,
+ <&vdo_iommu M4U_PORT_L19_VENC_SV_COMV>,
+ <&vdo_iommu M4U_PORT_L19_VENC_RD_COMV>,
+ <&vdo_iommu M4U_PORT_L19_VENC_CUR_LUMA>,
+ <&vdo_iommu M4U_PORT_L19_VENC_CUR_CHROMA>,
+ <&vdo_iommu M4U_PORT_L19_VENC_REF_LUMA>,
+ <&vdo_iommu M4U_PORT_L19_VENC_REF_CHROMA>,
+ <&vdo_iommu M4U_PORT_L19_VENC_SUB_W_LUMA>,
+ <&vdo_iommu M4U_PORT_L19_VENC_SUB_R_LUMA>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VENC>;
+ mediatek,scp = <&scp>;
+ };
+
+ jpeg_encoder: jpeg-encoder@1a030000 {
+ compatible = "mediatek,mt8188-jpgenc", "mediatek,mtk-jpgenc";
+ reg = <0 0x1a030000 0 0x10000>;
+ clocks = <&vencsys CLK_VENC1_JPGENC>;
+ clock-names = "jpgenc";
+ interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L19_JPGENC_Y_RDMA>,
+ <&vdo_iommu M4U_PORT_L19_JPGENC_C_RDMA>,
+ <&vdo_iommu M4U_PORT_L19_JPGENC_Q_TABLE>,
+ <&vdo_iommu M4U_PORT_L19_JPGENC_BSDMA>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VENC>;
+ };
+
+ jpeg_decoder: jpeg-decoder@1a040000 {
+ compatible = "mediatek,mt8188-jpgdec", "mediatek,mt2701-jpgdec";
+ reg = <0 0x1a040000 0 0x10000>;
+ clocks = <&vencsys CLK_VENC1_LARB>,
+ <&vencsys CLK_VENC1_JPGDEC>;
+ clock-names = "jpgdec-smi", "jpgdec";
+ interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L19_JPGDEC_WDMA_0>,
+ <&vdo_iommu M4U_PORT_L19_JPGDEC_BSDMA_0>,
+ <&vdo_iommu M4U_PORT_L19_JPGDEC_WDMA_1>,
+ <&vdo_iommu M4U_PORT_L19_JPGDEC_BSDMA_1>,
+ <&vdo_iommu M4U_PORT_L19_JPGDEC_HUFF_OFFSET_1>,
+ <&vdo_iommu M4U_PORT_L19_JPGDEC_HUFF_OFFSET_0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDEC0>;
+ };
+
+ ovl0: ovl@1c000000 {
+ compatible = "mediatek,mt8188-disp-ovl", "mediatek,mt8183-disp-ovl";
+ reg = <0 0x1c000000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_OVL0>;
+ interrupts = <GIC_SPI 636 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L0_DISP_OVL0_RDMA0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c00XXXX 0x0000 0x1000>;
+ };
+
+ rdma0: rdma@1c002000 {
+ compatible = "mediatek,mt8188-disp-rdma", "mediatek,mt8195-disp-rdma";
+ reg = <0 0x1c002000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_RDMA0>;
+ interrupts = <GIC_SPI 638 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L1_DISP_RDMA0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c00XXXX 0x2000 0x1000>;
+ };
+
+ color0: color@1c003000 {
+ compatible = "mediatek,mt8188-disp-color", "mediatek,mt8173-disp-color";
+ reg = <0 0x1c003000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_COLOR0>;
+ interrupts = <GIC_SPI 639 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c00XXXX 0x3000 0x1000>;
+ };
+
+ ccorr0: ccorr@1c004000 {
+ compatible = "mediatek,mt8188-disp-ccorr", "mediatek,mt8192-disp-ccorr";
+ reg = <0 0x1c004000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_CCORR0>;
+ interrupts = <GIC_SPI 640 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c00XXXX 0x4000 0x1000>;
+ };
+
+ aal0: aal@1c005000 {
+ compatible = "mediatek,mt8188-disp-aal", "mediatek,mt8183-disp-aal";
+ reg = <0 0x1c005000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_AAL0>;
+ interrupts = <GIC_SPI 641 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c00XXXX 0x5000 0x1000>;
+ };
+
+ gamma0: gamma@1c006000 {
+ compatible = "mediatek,mt8188-disp-gamma", "mediatek,mt8195-disp-gamma";
+ reg = <0 0x1c006000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_GAMMA0>;
+ interrupts = <GIC_SPI 642 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c00XXXX 0x6000 0x1000>;
+ };
+
+ dither0: dither@1c007000 {
+ compatible = "mediatek,mt8188-disp-dither", "mediatek,mt8183-disp-dither";
+ reg = <0 0x1c007000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_DITHER0>;
+ interrupts = <GIC_SPI 643 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c00XXXX 0x7000 0x1000>;
+ };
+
+ disp_dsi0: dsi@1c008000 {
+ compatible = "mediatek,mt8188-dsi";
+ reg = <0 0x1c008000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DSI0>,
+ <&vdosys0 CLK_VDO0_DSI0_DSI>,
+ <&mipi_tx_config0>;
+ clock-names = "engine", "digital", "hs";
+ interrupts = <GIC_SPI 644 IRQ_TYPE_LEVEL_HIGH 0>;
+ phys = <&mipi_tx_config0>;
+ phy-names = "dphy";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ resets = <&vdosys0 MT8188_VDO0_RST_DSI0>;
+ status = "disabled";
+ };
+
+ disp_dsi1: dsi@1c012000 {
+ compatible = "mediatek,mt8188-dsi";
+ reg = <0 0x1c012000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DSI1>,
+ <&vdosys0 CLK_VDO0_DSI1_DSI>,
+ <&mipi_tx_config1>;
+ clock-names = "engine", "digital", "hs";
+ interrupts = <GIC_SPI 654 IRQ_TYPE_LEVEL_HIGH 0>;
+ phys = <&mipi_tx_config1>;
+ phy-names = "dphy";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ resets = <&vdosys0 MT8188_VDO0_RST_DSI1>;
+ status = "disabled";
+ };
+
+ dp_intf0: dp-intf@1c015000 {
+ compatible = "mediatek,mt8188-dp-intf";
+ reg = <0 0x1c015000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DP_INTF0_DP_INTF>,
+ <&vdosys0 CLK_VDO0_DP_INTF0>,
+ <&apmixedsys CLK_APMIXED_TVDPLL1>;
+ clock-names = "pixel", "engine", "pll";
+ interrupts = <GIC_SPI 657 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ status = "disabled";
+ };
+
+ mutex0: mutex@1c016000 {
+ compatible = "mediatek,mt8188-disp-mutex";
+ reg = <0 0x1c016000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_MUTEX0>;
+ interrupts = <GIC_SPI 658 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0x6000 0x1000>;
+ mediatek,gce-events = <CMDQ_EVENT_VDO0_DISP_STREAM_DONE_0>;
+ };
+
+ postmask0: postmask@1c01a000 {
+ compatible = "mediatek,mt8188-disp-postmask",
+ "mediatek,mt8192-disp-postmask";
+ reg = <0 0x1c01a000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_POSTMASK0>;
+ interrupts = <GIC_SPI 661 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0xa000 0x1000>;
+ };
+
vdosys0: syscon@1c01d000 {
compatible = "mediatek,mt8188-vdosys0", "syscon";
reg = <0 0x1c01d000 0 0x1000>;
#clock-cells = <1>;
+ #reset-cells = <1>;
mboxes = <&gce0 0 CMDQ_THR_PRIO_4>;
mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0xd000 0x1000>;
};
+ larb0: smi@1c022000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x1c022000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_SMI_LARB>,
+ <&vdosys0 CLK_VDO0_SMI_LARB>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,larb-id = <SMI_L0_ID>;
+ mediatek,smi = <&vdo_smi_common>;
+ };
+
+ larb1: smi@1c023000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x1c023000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_SMI_LARB>,
+ <&vdosys0 CLK_VDO0_SMI_LARB>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ mediatek,larb-id = <SMI_L1_ID>;
+ mediatek,smi = <&vpp_smi_common>;
+ };
+
+ vdo_smi_common: smi@1c024000 {
+ compatible = "mediatek,mt8188-smi-common-vdo";
+ reg = <0 0x1c024000 0 0x1000>;
+ clocks = <&vdosys0 CLK_VDO0_SMI_COMMON>,
+ <&vdosys0 CLK_VDO0_SMI_GALS>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ };
+
+ vdo_iommu: iommu@1c028000 {
+ compatible = "mediatek,mt8188-iommu-vdo";
+ reg = <0 0x1c028000 0 0x5000>;
+ clocks = <&vdosys0 CLK_VDO0_SMI_IOMMU>;
+ clock-names = "bclk";
+ interrupts = <GIC_SPI 673 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS0>;
+ #iommu-cells = <1>;
+ mediatek,larbs = <&larb0 &larb2 &larb5 &larb19 &larb21>;
+ };
+
vdosys1: syscon@1c100000 {
compatible = "mediatek,mt8188-vdosys1", "syscon";
reg = <0 0x1c100000 0 0x1000>;
@@ -1914,5 +2673,336 @@
mboxes = <&gce0 1 CMDQ_THR_PRIO_4>;
mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0 0x1000>;
};
+
+ mutex1: mutex@1c101000 {
+ compatible = "mediatek,mt8188-disp-mutex";
+ reg = <0 0x1c101000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>;
+ interrupts = <GIC_SPI 494 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>;
+ mediatek,gce-events = <CMDQ_EVENT_VDO1_STREAM_DONE_ENG_0>;
+ };
+
+ larb2: smi@1c102000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x1c102000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_SMI_LARB2>,
+ <&vdosys1 CLK_VDO1_SMI_LARB2>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,larb-id = <SMI_L2_ID>;
+ mediatek,smi = <&vdo_smi_common>;
+ };
+
+ larb3: smi@1c103000 {
+ compatible = "mediatek,mt8188-smi-larb";
+ reg = <0 0x1c103000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_SMI_LARB3>,
+ <&vdosys1 CLK_VDO1_SMI_LARB3>;
+ clock-names = "apb", "smi";
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,larb-id = <SMI_L3_ID>;
+ mediatek,smi = <&vpp_smi_common>;
+ };
+
+ vdo1_rdma0: rdma@1c104000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c104000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA0>;
+ interrupts = <GIC_SPI 495 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L2_MDP_RDMA0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x4000 0x1000>;
+ };
+
+ vdo1_rdma1: rdma@1c105000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c105000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA1>;
+ interrupts = <GIC_SPI 496 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vpp_iommu M4U_PORT_L3_MDP_RDMA1>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x5000 0x1000>;
+ };
+
+ vdo1_rdma2: rdma@1c106000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c106000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA2>;
+ interrupts = <GIC_SPI 497 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L2_MDP_RDMA2>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x6000 0x1000>;
+ };
+
+ vdo1_rdma3: rdma@1c107000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c107000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA3>;
+ interrupts = <GIC_SPI 498 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vpp_iommu M4U_PORT_L3_MDP_RDMA3>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x7000 0x1000>;
+ };
+
+ vdo1_rdma4: rdma@1c108000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c108000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA4>;
+ interrupts = <GIC_SPI 499 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L2_MDP_RDMA4>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x8000 0x1000>;
+ };
+
+ vdo1_rdma5: rdma@1c109000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c109000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA5>;
+ interrupts = <GIC_SPI 500 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vpp_iommu M4U_PORT_L3_MDP_RDMA5>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x9000 0x1000>;
+ };
+
+ vdo1_rdma6: rdma@1c10a000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c10a000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA6>;
+ interrupts = <GIC_SPI 501 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vdo_iommu M4U_PORT_L2_MDP_RDMA6>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xa000 0x1000>;
+ };
+
+ vdo1_rdma7: rdma@1c10b000 {
+ compatible = "mediatek,mt8188-vdo1-rdma", "mediatek,mt8195-vdo1-rdma";
+ reg = <0 0x1c10b000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_MDP_RDMA7>;
+ interrupts = <GIC_SPI 502 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vpp_iommu M4U_PORT_L3_MDP_RDMA7>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ #dma-cells = <1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xb000 0x1000>;
+ };
+
+ merge1: merge@1c10c000 {
+ compatible = "mediatek,mt8188-disp-merge", "mediatek,mt8195-disp-merge";
+ reg = <0 0x1c10c000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_VPP_MERGE0>,
+ <&vdosys1 CLK_VDO1_MERGE0_DL_ASYNC>;
+ clock-names = "merge", "merge_async";
+ interrupts = <GIC_SPI 503 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ resets = <&vdosys1 MT8188_VDO1_RST_MERGE0_DL_ASYNC>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xc000 0x1000>;
+ mediatek,merge-mute;
+ };
+
+ merge2: merge@1c10d000 {
+ compatible = "mediatek,mt8188-disp-merge", "mediatek,mt8195-disp-merge";
+ reg = <0 0x1c10d000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_VPP_MERGE1>,
+ <&vdosys1 CLK_VDO1_MERGE1_DL_ASYNC>;
+ clock-names = "merge", "merge_async";
+ interrupts = <GIC_SPI 504 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ resets = <&vdosys1 MT8188_VDO1_RST_MERGE1_DL_ASYNC>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xd000 0x1000>;
+ mediatek,merge-mute;
+ };
+
+ merge3: merge@1c10e000 {
+ compatible = "mediatek,mt8188-disp-merge", "mediatek,mt8195-disp-merge";
+ reg = <0 0x1c10e000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_VPP_MERGE2>,
+ <&vdosys1 CLK_VDO1_MERGE2_DL_ASYNC>;
+ clock-names = "merge", "merge_async";
+ interrupts = <GIC_SPI 505 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ resets = <&vdosys1 MT8188_VDO1_RST_MERGE2_DL_ASYNC>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xe000 0x1000>;
+ mediatek,merge-mute;
+ };
+
+ merge4: merge@1c10f000 {
+ compatible = "mediatek,mt8188-disp-merge", "mediatek,mt8195-disp-merge";
+ reg = <0 0x1c10f000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_VPP_MERGE3>,
+ <&vdosys1 CLK_VDO1_MERGE3_DL_ASYNC>;
+ clock-names = "merge", "merge_async";
+ interrupts = <GIC_SPI 506 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ resets = <&vdosys1 MT8188_VDO1_RST_MERGE3_DL_ASYNC>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xf000 0x1000>;
+ mediatek,merge-mute;
+ };
+
+ merge5: merge@1c110000 {
+ compatible = "mediatek,mt8188-disp-merge", "mediatek,mt8195-disp-merge";
+ reg = <0 0x1c110000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_VPP_MERGE4>,
+ <&vdosys1 CLK_VDO1_MERGE4_DL_ASYNC>;
+ clock-names = "merge", "merge_async";
+ interrupts = <GIC_SPI 507 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ resets = <&vdosys1 MT8188_VDO1_RST_MERGE4_DL_ASYNC>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0x0000 0x1000>;
+ mediatek,merge-fifo-en;
+ };
+
+ dp_intf1: dp-intf@1c113000 {
+ compatible = "mediatek,mt8188-dp-intf";
+ reg = <0 0x1c113000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_DPINTF>,
+ <&vdosys1 CLK_VDO1_DP_INTF0_MMCK>,
+ <&apmixedsys CLK_APMIXED_TVDPLL2>;
+ clock-names = "pixel", "engine", "pll";
+ interrupts = <GIC_SPI 513 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ status = "disabled";
+ };
+
+ ethdr0: ethdr@1c114000 {
+ compatible = "mediatek,mt8188-disp-ethdr", "mediatek,mt8195-disp-ethdr";
+ reg = <0 0x1c114000 0 0x1000>,
+ <0 0x1c115000 0 0x1000>,
+ <0 0x1c117000 0 0x1000>,
+ <0 0x1c119000 0 0x1000>,
+ <0 0x1c11a000 0 0x1000>,
+ <0 0x1c11b000 0 0x1000>,
+ <0 0x1c11c000 0 0x1000>;
+ reg-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1",
+ "vdo_be", "adl_ds";
+
+ clocks = <&vdosys1 CLK_VDO1_DISP_MIXER>,
+ <&vdosys1 CLK_VDO1_HDR_VDO_FE0>,
+ <&vdosys1 CLK_VDO1_HDR_VDO_FE1>,
+ <&vdosys1 CLK_VDO1_HDR_GFX_FE0>,
+ <&vdosys1 CLK_VDO1_HDR_GFX_FE1>,
+ <&vdosys1 CLK_VDO1_HDR_VDO_BE>,
+ <&vdosys1 CLK_VDO1_26M_SLOW>,
+ <&vdosys1 CLK_VDO1_HDR_VDO_FE0_DL_ASYNC>,
+ <&vdosys1 CLK_VDO1_HDR_VDO_FE1_DL_ASYNC>,
+ <&vdosys1 CLK_VDO1_HDR_GFX_FE0_DL_ASYNC>,
+ <&vdosys1 CLK_VDO1_HDR_GFX_FE1_DL_ASYNC>,
+ <&vdosys1 CLK_VDO1_HDR_VDO_BE_DL_ASYNC>,
+ <&topckgen CLK_TOP_ETHDR>;
+ clock-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1",
+ "vdo_be", "adl_ds", "vdo_fe0_async", "vdo_fe1_async",
+ "gfx_fe0_async", "gfx_fe1_async", "vdo_be_async", "ethdr_top";
+
+ interrupts = <GIC_SPI 566 IRQ_TYPE_LEVEL_HIGH 0>;
+ iommus = <&vpp_iommu M4U_PORT_L3_HDR_DS_SMI>,
+ <&vpp_iommu M4U_PORT_L3_HDR_ADL_SMI>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ resets = <&vdosys1 MT8188_VDO1_RST_HDR_VDO_FE0_DL_ASYNC>,
+ <&vdosys1 MT8188_VDO1_RST_HDR_VDO_FE1_DL_ASYNC>,
+ <&vdosys1 MT8188_VDO1_RST_HDR_GFX_FE0_DL_ASYNC>,
+ <&vdosys1 MT8188_VDO1_RST_HDR_GFX_FE1_DL_ASYNC>,
+ <&vdosys1 MT8188_VDO1_RST_HDR_VDO_BE_DL_ASYNC>;
+
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0x4000 0x1000>,
+ <&gce0 SUBSYS_1c11XXXX 0x5000 0x1000>,
+ <&gce0 SUBSYS_1c11XXXX 0x7000 0x1000>,
+ <&gce0 SUBSYS_1c11XXXX 0x9000 0x1000>,
+ <&gce0 SUBSYS_1c11XXXX 0xa000 0x1000>,
+ <&gce0 SUBSYS_1c11XXXX 0xb000 0x1000>,
+ <&gce0 SUBSYS_1c11XXXX 0xc000 0x1000>;
+ };
+
+ padding0: padding@1c11d000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c11d000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING0>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0xd000 0x1000>;
+ };
+
+ padding1: padding@1c11e000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c11e000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING1>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0xe000 0x1000>;
+ };
+
+ padding2: padding@1c11f000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c11f000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING2>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0xf000 0x1000>;
+ };
+
+ padding3: padding@1c120000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c120000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING3>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c12XXXX 0x0000 0x1000>;
+ };
+
+ padding4: padding@1c121000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c121000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING4>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c12XXXX 0x1000 0x1000>;
+ };
+
+ padding5: padding@1c122000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c122000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING5>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c12XXXX 0x2000 0x1000>;
+ };
+
+ padding6: padding@1c123000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c123000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING6>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c12XXXX 0x3000 0x1000>;
+ };
+
+ padding7: padding@1c124000 {
+ compatible = "mediatek,mt8188-disp-padding";
+ reg = <0 0x1c124000 0 0x1000>;
+ clocks = <&vdosys1 CLK_VDO1_PADDING7>;
+ power-domains = <&spm MT8188_POWER_DOMAIN_VDOSYS1>;
+ mediatek,gce-client-reg = <&gce0 SUBSYS_1c12XXXX 0x4000 0x1000>;
+ };
+
+ edp_tx: edp-tx@1c500000 {
+ compatible = "mediatek,mt8188-edp-tx";
+ reg = <0 0x1c500000 0 0x8000>;
+ interrupts = <GIC_SPI 676 IRQ_TYPE_LEVEL_HIGH 0>;
+ nvmem-cells = <&dp_calib_data>;
+ nvmem-cell-names = "dp_calibration_data";
+ power-domains = <&spm MT8188_POWER_DOMAIN_EDP_TX>;
+ max-linkrate-mhz = <8100>;
+ status = "disabled";
+ };
+
+ dp_tx: dp-tx@1c600000 {
+ compatible = "mediatek,mt8188-dp-tx";
+ reg = <0 0x1c600000 0 0x8000>;
+ interrupts = <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH 0>;
+ nvmem-cells = <&dp_calib_data>;
+ nvmem-cell-names = "dp_calibration_data";
+ power-domains = <&spm MT8188_POWER_DOMAIN_DP_TX>;
+ max-linkrate-mhz = <5400>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
index 29aa87e93888..8c485c3ced2c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-spherion-r0.dts
@@ -79,3 +79,14 @@
&touchscreen {
compatible = "elan,ekth3500";
};
+
+&i2c2 {
+ /* synaptics touchpad */
+ trackpad@2c {
+ compatible = "hid-over-i2c";
+ reg = <0x2c>;
+ hid-descr-addr = <0x20>;
+ interrupts-extended = <&pio 15 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
index 08d71ddf3668..8dda8b63765b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
@@ -335,14 +335,12 @@
clock-frequency = <400000>;
clock-stretch-ns = <12600>;
pinctrl-names = "default";
- pinctrl-0 = <&i2c2_pins>;
+ pinctrl-0 = <&i2c2_pins>, <&trackpad_pins>;
trackpad@15 {
compatible = "elan,ekth3000";
reg = <0x15>;
interrupts-extended = <&pio 15 IRQ_TYPE_LEVEL_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&trackpad_pins>;
vcc-supply = <&pp3300_u>;
wakeup-source;
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
index 75d56b2d5a3d..2c7b2223ee76 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
@@ -438,7 +438,7 @@
/* Realtek RT5682i or RT5682s, sharing the same configuration */
reg = <0x1a>;
interrupts-extended = <&pio 89 IRQ_TYPE_EDGE_BOTH>;
- #sound-dai-cells = <0>;
+ #sound-dai-cells = <1>;
realtek,jd-src = <1>;
AVDD-supply = <&mt6359_vio18_ldo_reg>;
@@ -1181,7 +1181,7 @@
link-name = "ETDM1_OUT_BE";
mediatek,clk-provider = "cpu";
codec {
- sound-dai = <&audio_codec>;
+ sound-dai = <&audio_codec 0>;
};
};
@@ -1189,7 +1189,7 @@
link-name = "ETDM2_IN_BE";
mediatek,clk-provider = "cpu";
codec {
- sound-dai = <&audio_codec>;
+ sound-dai = <&audio_codec 0>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index e89ba384c4aa..ade685ed2190 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -487,7 +487,7 @@
};
infracfg_ao: syscon@10001000 {
- compatible = "mediatek,mt8195-infracfg_ao", "syscon", "simple-mfd";
+ compatible = "mediatek,mt8195-infracfg_ao", "syscon";
reg = <0 0x10001000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -3331,11 +3331,9 @@
mutex1: mutex@1c101000 {
compatible = "mediatek,mt8195-disp-mutex";
reg = <0 0x1c101000 0 0x1000>;
- reg-names = "vdo1_mutex";
interrupts = <GIC_SPI 494 IRQ_TYPE_LEVEL_HIGH 0>;
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>;
- clock-names = "vdo1_mutex";
mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>;
mediatek,gce-events = <CMDQ_EVENT_VDO1_STREAM_DONE_ENG_0>;
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts b/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts
index 1474bef7e754..13f2e0e3fa8a 100644
--- a/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8390-genio-700-evk.dts
@@ -23,6 +23,16 @@
"mediatek,mt8188";
aliases {
+ ethernet0 = &eth;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
+ i2c6 = &i2c6;
+ mmc0 = &mmc0;
+ mmc1 = &mmc1;
serial0 = &uart0;
};
@@ -87,109 +97,124 @@
common_fixed_5v: regulator-0 {
compatible = "regulator-fixed";
- regulator-name = "5v_en";
+ regulator-name = "vdd_5v";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&pio 10 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-always-on;
+ vin-supply = <&reg_vsys>;
};
edp_panel_fixed_3v3: regulator-1 {
compatible = "regulator-fixed";
- regulator-name = "edp_panel_3v3";
+ regulator-name = "vedp_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
enable-active-high;
gpio = <&pio 15 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&edp_panel_3v3_en_pins>;
+ vin-supply = <&reg_vsys>;
};
gpio_fixed_3v3: regulator-2 {
compatible = "regulator-fixed";
- regulator-name = "gpio_3v3_en";
+ regulator-name = "ext_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pio 9 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-always-on;
+ vin-supply = <&reg_vsys>;
};
+ /* system wide 4.2V power rail from charger */
+ reg_vsys: regulator-vsys {
+ compatible = "regulator-fixed";
+ regulator-name = "vsys";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ /* used by mmc2 */
sdio_fixed_1v8: regulator-3 {
compatible = "regulator-fixed";
- regulator-name = "sdio_io";
+ regulator-name = "vio18_conn";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
enable-active-high;
regulator-always-on;
};
+ /* used by mmc2 */
sdio_fixed_3v3: regulator-4 {
compatible = "regulator-fixed";
- regulator-name = "sdio_card";
+ regulator-name = "wifi_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pio 74 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-always-on;
+ vin-supply = <&reg_vsys>;
};
touch0_fixed_3v3: regulator-5 {
compatible = "regulator-fixed";
- regulator-name = "touch_3v3";
+ regulator-name = "vio33_tp1";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pio 119 GPIO_ACTIVE_HIGH>;
enable-active-high;
+ vin-supply = <&reg_vsys>;
};
usb_hub_fixed_3v3: regulator-6 {
compatible = "regulator-fixed";
- regulator-name = "usb_hub_3v3";
+ regulator-name = "vhub_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pio 112 GPIO_ACTIVE_HIGH>; /* HUB_3V3_EN */
startup-delay-us = <10000>;
enable-active-high;
+ vin-supply = <&reg_vsys>;
};
- usb_hub_reset_1v8: regulator-7 {
- compatible = "regulator-fixed";
- regulator-name = "usb_hub_reset";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- gpio = <&pio 7 GPIO_ACTIVE_HIGH>; /* HUB_RESET */
- vin-supply = <&usb_hub_fixed_3v3>;
- };
-
- usb_p0_vbus: regulator-8 {
+ usb_p0_vbus: regulator-7 {
compatible = "regulator-fixed";
- regulator-name = "usb_p0_vbus";
+ regulator-name = "vbus_p0";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&pio 84 GPIO_ACTIVE_HIGH>;
enable-active-high;
+ vin-supply = <&reg_vsys>;
};
- usb_p1_vbus: regulator-9 {
+ usb_p1_vbus: regulator-8 {
compatible = "regulator-fixed";
- regulator-name = "usb_p1_vbus";
+ regulator-name = "vbus_p1";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&pio 87 GPIO_ACTIVE_HIGH>;
enable-active-high;
+ vin-supply = <&reg_vsys>;
};
- usb_p2_vbus: regulator-10 {
+ /* used by ssusb2 */
+ usb_p2_vbus: regulator-9 {
compatible = "regulator-fixed";
- regulator-name = "usb_p2_vbus";
+ regulator-name = "wifi_3v3";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
};
};
+&gpu {
+ mali-supply = <&mt6359_vproc2_buck_reg>;
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
@@ -234,7 +259,6 @@
&i2c4 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins>;
- pinctrl-1 = <&rt1715_int_pins>;
clock-frequency = <1000000>;
status = "okay";
};
@@ -253,6 +277,14 @@
status = "okay";
};
+&mfg0 {
+ domain-supply = <&mt6359_vproc2_buck_reg>;
+};
+
+&mfg1 {
+ domain-supply = <&mt6359_vsram_others_ldo_reg>;
+};
+
&mmc0 {
status = "okay";
pinctrl-names = "default", "state_uhs";
@@ -295,38 +327,65 @@
};
&mt6359_vcn18_ldo_reg {
+ regulator-name = "vcn18_pmu";
regulator-always-on;
};
&mt6359_vcn33_2_bt_ldo_reg {
+ regulator-name = "vcn33_2_pmu";
regulator-always-on;
};
&mt6359_vcore_buck_reg {
+ regulator-name = "dvdd_proc_l";
regulator-always-on;
};
&mt6359_vgpu11_buck_reg {
+ regulator-name = "dvdd_core";
regulator-always-on;
};
&mt6359_vpa_buck_reg {
+ regulator-name = "vpa_pmu";
regulator-max-microvolt = <3100000>;
};
+&mt6359_vproc2_buck_reg {
+ /* The name "vgpu" is required by mtk-regulator-coupler */
+ regulator-name = "vgpu";
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <800000>;
+ regulator-coupled-with = <&mt6359_vsram_others_ldo_reg>;
+ regulator-coupled-max-spread = <6250>;
+};
+
&mt6359_vpu_buck_reg {
+ regulator-name = "dvdd_adsp";
regulator-always-on;
};
&mt6359_vrf12_ldo_reg {
+ regulator-name = "va12_abb2_pmu";
regulator-always-on;
};
&mt6359_vsim1_ldo_reg {
+ regulator-name = "vsim1_pmu";
regulator-enable-ramp-delay = <480>;
};
+&mt6359_vsram_others_ldo_reg {
+ /* The name "vsram_gpu" is required by mtk-regulator-coupler */
+ regulator-name = "vsram_gpu";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <800000>;
+ regulator-coupled-with = <&mt6359_vproc2_buck_reg>;
+ regulator-coupled-max-spread = <6250>;
+};
+
&mt6359_vufs_ldo_reg {
+ regulator-name = "vufs18_pmu";
regulator-always-on;
};
@@ -335,6 +394,16 @@
mediatek,mic-type-1 = <3>; /* DCC */
};
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pins_default>;
+ status = "okay";
+};
+
+&pciephy {
+ status = "okay";
+};
+
&pio {
audio_default_pins: audio-default-pins {
pins-cmd-dat {
@@ -700,6 +769,15 @@
};
};
+ pcie_pins_default: pcie-default {
+ mux {
+ pinmux = <PINMUX_GPIO47__FUNC_I1_WAKEN>,
+ <PINMUX_GPIO48__FUNC_O_PERSTN>,
+ <PINMUX_GPIO49__FUNC_B1_CLKREQN>;
+ bias-pull-up;
+ };
+ };
+
rt1715_int_pins: rt1715-int-pins {
pins_cmd0_dat {
pinmux = <PINMUX_GPIO12__FUNC_B_GPIO12>;
@@ -814,9 +892,39 @@
};
};
+&eth {
+ phy-mode ="rgmii-id";
+ phy-handle = <&ethernet_phy0>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&eth_default_pins>;
+ pinctrl-1 = <&eth_sleep_pins>;
+ mediatek,mac-wol;
+ snps,reset-gpio = <&pio 147 GPIO_ACTIVE_HIGH>;
+ snps,reset-delays-us = <0 10000 10000>;
+ status = "okay";
+};
+
+&eth_mdio {
+ ethernet_phy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0x1>;
+ };
+};
+
&pmic {
interrupt-parent = <&pio>;
interrupts = <222 IRQ_TYPE_LEVEL_HIGH>;
+
+ mt6359keys: keys {
+ compatible = "mediatek,mt6359-keys";
+ mediatek,long-press-mode = <1>;
+ power-off-time-sec = <0>;
+
+ power-key {
+ linux,keycodes = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
};
&scp {
@@ -824,6 +932,15 @@
status = "okay";
};
+&spi2 {
+ pinctrl-0 = <&spi2_pins>;
+ pinctrl-names = "default";
+ mediatek,pad-select = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-0 = <&uart0_pins>;
pinctrl-names = "default";
@@ -842,15 +959,6 @@
status = "okay";
};
-&spi2 {
- pinctrl-0 = <&spi2_pins>;
- pinctrl-names = "default";
- mediatek,pad-select = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "okay";
-};
-
&u3phy0 {
status = "okay";
};
@@ -871,10 +979,28 @@
&xhci1 {
status = "okay";
vusb33-supply = <&mt6359_vusb_ldo_reg>;
- vbus-supply = <&usb_hub_reset_1v8>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hub_2_0: hub@1 {
+ compatible = "usb451,8025";
+ reg = <1>;
+ peer-hub = <&hub_3_0>;
+ reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+ vdd-supply = <&usb_hub_fixed_3v3>;
+ };
+
+ hub_3_0: hub@2 {
+ compatible = "usb451,8027";
+ reg = <2>;
+ peer-hub = <&hub_2_0>;
+ reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+ vdd-supply = <&usb_hub_fixed_3v3>;
+ };
};
&xhci2 {
status = "okay";
vusb33-supply = <&mt6359_vusb_ldo_reg>;
+ vbus-supply = <&sdio_fixed_3v3>; /* wifi_3v3 */
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts
index 1ef6262b65c9..5f16fb820580 100644
--- a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts
@@ -187,13 +187,18 @@
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
- eth_phy0: eth-phy0@1 {
+ eth_phy0: ethernet-phy@1 {
compatible = "ethernet-phy-id001c.c916";
reg = <0x1>;
};
};
};
+&gpu {
+ mali-supply = <&mt6315_7_vbuck1>;
+ status = "okay";
+};
+
&i2c0 {
clock-frequency = <400000>;
pinctrl-0 = <&i2c0_pins>;
@@ -337,6 +342,10 @@
domain-supply = <&mt6315_7_vbuck1>;
};
+&mfg1 {
+ domain-supply = <&mt6359_vsram_others_ldo_reg>;
+};
+
&mmc0 {
status = "okay";
pinctrl-names = "default", "state_uhs";
@@ -407,6 +416,12 @@
regulator-always-on;
};
+/* for GPU SRAM */
+&mt6359_vsram_others_ldo_reg {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+};
+
&mt6359codec {
mediatek,mic-type-0 = <1>; /* ACC */
mediatek,mic-type-1 = <3>; /* DCC */
@@ -839,8 +854,8 @@
mt6315_7_vbuck1: vbuck1 {
regulator-compatible = "vbuck1";
regulator-name = "Vgpu";
- regulator-min-microvolt = <300000>;
- regulator-max-microvolt = <1193750>;
+ regulator-min-microvolt = <546000>;
+ regulator-max-microvolt = <787000>;
regulator-enable-ramp-delay = <256>;
regulator-allowed-modes = <0 1 2>;
};
diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile
index c38c809fe577..0fbb8a494dba 100644
--- a/arch/arm64/boot/dts/nvidia/Makefile
+++ b/arch/arm64/boot/dts/nvidia/Makefile
@@ -27,6 +27,7 @@ dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p3509-0000+p3668-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p3509-0000+p3668-0001.dtb
dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-sim-vdk.dtb
dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3737-0000+p3701-0000.dtb
+dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3737-0000+p3701-0008.dtb
dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3740-0002+p3701-0008.dtb
dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3768-0000+p3767-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3768-0000+p3767-0005.dtb
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index c00db75e3910..1c53ccc5e3cb 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -351,7 +351,7 @@
#size-cells = <0>;
wifi@1 {
- compatible = "brcm,bcm4354-fmac";
+ compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac";
reg = <1>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 2) IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
index 2e5b6b2c1f56..5aa6afd56cbc 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
@@ -1362,6 +1362,19 @@
};
};
+ i2c@7000c000 {
+ status = "okay";
+ clock-frequency = <1000000>;
+
+ touchscreen: i2c-hid-dev@20 {
+ compatible = "hid-over-i2c";
+ reg = <0x20>;
+ hid-descr-addr = <0x0020>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(X, 1) IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
+
i2c@7000c400 {
status = "okay";
clock-frequency = <1000000>;
@@ -1385,6 +1398,11 @@
reg = <0x55>;
};
};
+
+ usbc_extcon0: extcon0 {
+ compatible = "google,extcon-usbc-cros-ec";
+ google,usb-port-id = <0>;
+ };
};
};
@@ -1719,6 +1737,15 @@
#gpio-cells = <2>;
status = "okay";
};
+
+ tmp451: temperature-sensor@4c {
+ compatible = "ti,tmp451";
+ reg = <0x4c>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(X, 4) IRQ_TYPE_LEVEL_LOW>;
+ vcc-supply = <&pp1800>;
+ #thermal-sensor-cells = <1>;
+ };
};
pmc@7000e400 {
diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 882b1d1f4ada..942e3a0f81ed 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1218,6 +1218,8 @@
nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
+ nvidia,pad-autocal-pull-up-offset-sdr104 = <0x0>;
+ nvidia,pad-autocal-pull-down-offset-sdr104 = <0x0>;
nvidia,default-tap = <0x2>;
nvidia,default-trim = <0x4>;
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
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 90f12277aede..4c0e96f9d493 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
@@ -1,551 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
-#include <dt-bindings/input/linux-event-codes.h>
-#include <dt-bindings/input/gpio-keys.h>
-#include <dt-bindings/sound/rt5640.h>
-
+// Module files must be included first
#include "tegra234-p3701-0000.dtsi"
+#include "tegra234-p3737-0000+p3701.dtsi"
/ {
model = "NVIDIA Jetson AGX Orin Developer Kit";
compatible = "nvidia,p3737-0000+p3701-0000", "nvidia,p3701-0000", "nvidia,tegra234";
-
- aliases {
- serial0 = &tcu;
- serial1 = &uarta;
- };
-
- chosen {
- bootargs = "console=ttyTCU0,115200n8";
- stdout-path = "serial0:115200n8";
- };
-
- bus@0 {
- aconnect@2900000 {
- ahub@2900800 {
- i2s@2901000 {
- ports {
- port@1 {
- endpoint {
- dai-format = "i2s";
- remote-endpoint = <&rt5640_ep>;
- };
- };
- };
- };
- };
- };
-
- serial@3100000 {
- compatible = "nvidia,tegra194-hsuart";
- reset-names = "serial";
- status = "okay";
- };
-
- i2c@3160000 {
- status = "okay";
-
- eeprom@56 {
- compatible = "atmel,24c02";
- reg = <0x56>;
-
- label = "system";
- vcc-supply = <&vdd_1v8_sys>;
- address-width = <8>;
- pagesize = <8>;
- size = <256>;
- read-only;
- };
- };
-
- serial@31d0000 {
- current-speed = <115200>;
- status = "okay";
- };
-
- i2c@31e0000 {
- status = "okay";
-
- audio-codec@1c {
- compatible = "realtek,rt5640";
- reg = <0x1c>;
- interrupt-parent = <&gpio>;
- interrupts = <TEGRA234_MAIN_GPIO(AC, 5) GPIO_ACTIVE_HIGH>;
- clocks = <&bpmp TEGRA234_CLK_AUD_MCLK>;
- clock-names = "mclk";
- realtek,dmic1-data-pin = <RT5640_DMIC1_DATA_PIN_NONE>;
- realtek,dmic2-data-pin = <RT5640_DMIC2_DATA_PIN_NONE>;
- realtek,jack-detect-source = <RT5640_JD_SRC_HDA_HEADER>;
- sound-name-prefix = "CVB-RT";
-
- port {
- rt5640_ep: endpoint {
- remote-endpoint = <&i2s1_dap>;
- mclk-fs = <256>;
- };
- };
- };
- };
-
- pwm@3280000 {
- status = "okay";
- };
-
- pwm@32a0000 {
- assigned-clocks = <&bpmp TEGRA234_CLK_PWM3>;
- assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
- status = "okay";
- };
-
- pwm@32c0000 {
- status = "okay";
- };
-
- pwm@32f0000 {
- status = "okay";
- };
-
- mmc@3400000 {
- status = "okay";
- bus-width = <4>;
- cd-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 7) GPIO_ACTIVE_LOW>;
- disable-wp;
- };
-
- hda@3510000 {
- nvidia,model = "NVIDIA Jetson AGX Orin HDA";
- status = "okay";
- };
-
- padctl@3520000 {
- status = "okay";
-
- pads {
- usb2 {
- lanes {
- usb2-0 {
- status = "okay";
- };
-
- usb2-1 {
- status = "okay";
- };
-
- usb2-2 {
- status = "okay";
- };
-
- usb2-3 {
- status = "okay";
- };
- };
- };
-
- usb3 {
- lanes {
- usb3-0 {
- status = "okay";
- };
-
- usb3-1 {
- status = "okay";
- };
-
- usb3-2 {
- status = "okay";
- };
- };
- };
- };
-
- ports {
- usb2-0 {
- mode = "otg";
- usb-role-switch;
- status = "okay";
-
- port {
- hs_typec_p1: endpoint {
- remote-endpoint = <&hs_ucsi_ccg_p1>;
- };
- };
- };
-
- usb2-1 {
- mode = "host";
- status = "okay";
-
- port {
- hs_typec_p0: endpoint {
- remote-endpoint = <&hs_ucsi_ccg_p0>;
- };
- };
- };
-
- usb2-2 {
- mode = "host";
- status = "okay";
- };
-
- usb2-3 {
- mode = "host";
- status = "okay";
- };
-
- usb3-0 {
- nvidia,usb2-companion = <1>;
- status = "okay";
-
- port {
- ss_typec_p0: endpoint {
- remote-endpoint = <&ss_ucsi_ccg_p0>;
- };
- };
- };
-
- usb3-1 {
- nvidia,usb2-companion = <0>;
- status = "okay";
-
- port {
- ss_typec_p1: endpoint {
- remote-endpoint = <&ss_ucsi_ccg_p1>;
- };
- };
- };
-
- usb3-2 {
- nvidia,usb2-companion = <3>;
- status = "okay";
- };
- };
- };
-
- usb@3550000 {
- status = "okay";
-
- phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>,
- <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>;
- phy-names = "usb2-0", "usb3-0";
- };
-
- usb@3610000 {
- status = "okay";
-
- 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-2}>,
- <&{/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-1}>,
- <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-2}>;
- phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3",
- "usb3-0", "usb3-1", "usb3-2";
- };
-
- ethernet@6800000 {
- status = "okay";
-
- phy-handle = <&mgbe0_phy>;
- phy-mode = "10gbase-r";
-
- mdio {
- #address-cells = <1>;
- #size-cells = <0>;
-
- mgbe0_phy: phy@0 {
- compatible = "ethernet-phy-ieee802.3-c45";
- reg = <0x0>;
-
- #phy-cells = <0>;
- };
- };
- };
-
- i2c@c240000 {
- status = "okay";
-
- typec@8 {
- compatible = "cypress,cypd4226";
- reg = <0x08>;
- interrupt-parent = <&gpio>;
- interrupts = <TEGRA234_MAIN_GPIO(Y, 4) IRQ_TYPE_LEVEL_LOW>;
- firmware-name = "nvidia,jetson-agx-xavier";
- status = "okay";
-
- #address-cells = <1>;
- #size-cells = <0>;
-
- ccg_typec_con0: connector@0 {
- compatible = "usb-c-connector";
- reg = <0>;
- label = "USB-C";
- data-role = "host";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
-
- hs_ucsi_ccg_p0: endpoint {
- remote-endpoint = <&hs_typec_p0>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- ss_ucsi_ccg_p0: endpoint {
- remote-endpoint = <&ss_typec_p0>;
- };
- };
- };
- };
-
- ccg_typec_con1: connector@1 {
- compatible = "usb-c-connector";
- reg = <1>;
- label = "USB-C";
- data-role = "dual";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
-
- hs_ucsi_ccg_p1: endpoint {
- remote-endpoint = <&hs_typec_p1>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- ss_ucsi_ccg_p1: endpoint {
- remote-endpoint = <&ss_typec_p1>;
- };
- };
- };
- };
- };
- };
-
- pcie@14100000 {
- status = "okay";
-
- vddio-pex-ctl-supply = <&vdd_1v8_ao>;
-
- phys = <&p2u_hsio_3>;
- phy-names = "p2u-0";
- };
-
- pcie@14160000 {
- status = "okay";
-
- vddio-pex-ctl-supply = <&vdd_1v8_ao>;
-
- phys = <&p2u_hsio_4>, <&p2u_hsio_5>, <&p2u_hsio_6>,
- <&p2u_hsio_7>;
- phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3";
- };
-
- pcie@141a0000 {
- status = "okay";
-
- vddio-pex-ctl-supply = <&vdd_1v8_ls>;
- vpcie3v3-supply = <&vdd_3v3_pcie>;
- vpcie12v-supply = <&vdd_12v_pcie>;
-
- phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>,
- <&p2u_nvhs_3>, <&p2u_nvhs_4>, <&p2u_nvhs_5>,
- <&p2u_nvhs_6>, <&p2u_nvhs_7>;
- phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4",
- "p2u-5", "p2u-6", "p2u-7";
- };
-
- pcie-ep@141a0000 {
- status = "disabled";
-
- vddio-pex-ctl-supply = <&vdd_1v8_ls>;
-
- reset-gpios = <&gpio TEGRA234_MAIN_GPIO(AF, 1) GPIO_ACTIVE_LOW>;
-
- nvidia,refclk-select-gpios = <&gpio_aon
- TEGRA234_AON_GPIO(AA, 4)
- GPIO_ACTIVE_HIGH>;
-
- phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>,
- <&p2u_nvhs_3>, <&p2u_nvhs_4>, <&p2u_nvhs_5>,
- <&p2u_nvhs_6>, <&p2u_nvhs_7>;
- phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4",
- "p2u-5", "p2u-6", "p2u-7";
- };
- };
-
- gpio-keys {
- compatible = "gpio-keys";
- status = "okay";
-
- key-force-recovery {
- label = "Force Recovery";
- gpios = <&gpio TEGRA234_MAIN_GPIO(G, 0) GPIO_ACTIVE_LOW>;
- linux,input-type = <EV_KEY>;
- linux,code = <BTN_1>;
- };
-
- key-power {
- label = "Power";
- gpios = <&gpio_aon TEGRA234_AON_GPIO(EE, 4) GPIO_ACTIVE_LOW>;
- linux,input-type = <EV_KEY>;
- linux,code = <KEY_POWER>;
- wakeup-event-action = <EV_ACT_ASSERTED>;
- wakeup-source;
- };
-
- key-suspend {
- label = "Suspend";
- gpios = <&gpio TEGRA234_MAIN_GPIO(G, 2) GPIO_ACTIVE_LOW>;
- linux,input-type = <EV_KEY>;
- linux,code = <KEY_SLEEP>;
- };
- };
-
- fan: pwm-fan {
- compatible = "pwm-fan";
- cooling-levels = <66 215 255>;
- pwms = <&pwm3 0 45334>;
- #cooling-cells = <2>;
- };
-
- serial {
- status = "okay";
- };
-
- sound {
- compatible = "nvidia,tegra186-audio-graph-card";
- status = "okay";
-
- dais = /* ADMAIF (FE) Ports */
- <&admaif0_port>, <&admaif1_port>, <&admaif2_port>, <&admaif3_port>,
- <&admaif4_port>, <&admaif5_port>, <&admaif6_port>, <&admaif7_port>,
- <&admaif8_port>, <&admaif9_port>, <&admaif10_port>, <&admaif11_port>,
- <&admaif12_port>, <&admaif13_port>, <&admaif14_port>, <&admaif15_port>,
- <&admaif16_port>, <&admaif17_port>, <&admaif18_port>, <&admaif19_port>,
- /* XBAR Ports */
- <&xbar_i2s1_port>, <&xbar_i2s2_port>, <&xbar_i2s4_port>,
- <&xbar_i2s6_port>, <&xbar_dmic3_port>,
- <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
- <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,
- <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,
- <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
- <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
- <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
- <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
- <&xbar_amx3_in1_port>, <&xbar_amx3_in2_port>,
- <&xbar_amx3_in3_port>, <&xbar_amx3_in4_port>,
- <&xbar_amx4_in1_port>, <&xbar_amx4_in2_port>,
- <&xbar_amx4_in3_port>, <&xbar_amx4_in4_port>,
- <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
- <&xbar_adx3_in_port>, <&xbar_adx4_in_port>,
- <&xbar_mix_in1_port>, <&xbar_mix_in2_port>,
- <&xbar_mix_in3_port>, <&xbar_mix_in4_port>,
- <&xbar_mix_in5_port>, <&xbar_mix_in6_port>,
- <&xbar_mix_in7_port>, <&xbar_mix_in8_port>,
- <&xbar_mix_in9_port>, <&xbar_mix_in10_port>,
- <&xbar_asrc_in1_port>, <&xbar_asrc_in2_port>,
- <&xbar_asrc_in3_port>, <&xbar_asrc_in4_port>,
- <&xbar_asrc_in5_port>, <&xbar_asrc_in6_port>,
- <&xbar_asrc_in7_port>,
- <&xbar_ope1_in_port>,
- /* HW accelerators */
- <&sfc1_out_port>, <&sfc2_out_port>,
- <&sfc3_out_port>, <&sfc4_out_port>,
- <&mvc1_out_port>, <&mvc2_out_port>,
- <&amx1_out_port>, <&amx2_out_port>,
- <&amx3_out_port>, <&amx4_out_port>,
- <&adx1_out1_port>, <&adx1_out2_port>,
- <&adx1_out3_port>, <&adx1_out4_port>,
- <&adx2_out1_port>, <&adx2_out2_port>,
- <&adx2_out3_port>, <&adx2_out4_port>,
- <&adx3_out1_port>, <&adx3_out2_port>,
- <&adx3_out3_port>, <&adx3_out4_port>,
- <&adx4_out1_port>, <&adx4_out2_port>,
- <&adx4_out3_port>, <&adx4_out4_port>,
- <&mix_out1_port>, <&mix_out2_port>, <&mix_out3_port>,
- <&mix_out4_port>, <&mix_out5_port>,
- <&asrc_out1_port>, <&asrc_out2_port>, <&asrc_out3_port>,
- <&asrc_out4_port>, <&asrc_out5_port>, <&asrc_out6_port>,
- <&ope1_out_port>,
- /* BE I/O Ports */
- <&i2s1_port>, <&i2s2_port>, <&i2s4_port>, <&i2s6_port>,
- <&dmic3_port>;
-
- label = "NVIDIA Jetson AGX Orin APE";
-
- widgets = "Microphone", "CVB-RT MIC Jack",
- "Microphone", "CVB-RT MIC",
- "Headphone", "CVB-RT HP Jack",
- "Speaker", "CVB-RT SPK";
-
- routing = /* I2S1 <-> RT5640 */
- "CVB-RT AIF1 Playback", "I2S1 DAP-Playback",
- "I2S1 DAP-Capture", "CVB-RT AIF1 Capture",
- /* RT5640 codec controls */
- "CVB-RT HP Jack", "CVB-RT HPOL",
- "CVB-RT HP Jack", "CVB-RT HPOR",
- "CVB-RT IN1P", "CVB-RT MIC Jack",
- "CVB-RT IN2P", "CVB-RT MIC Jack",
- "CVB-RT SPK", "CVB-RT SPOLP",
- "CVB-RT SPK", "CVB-RT SPORP",
- "CVB-RT DMIC1", "CVB-RT MIC",
- "CVB-RT DMIC2", "CVB-RT MIC";
- };
-
- thermal-zones {
- tj-thermal {
- cooling-maps {
- map-active-0 {
- cooling-device = <&fan 0 1>;
- trip = <&tj_trip_active0>;
- };
-
- map-active-1 {
- cooling-device = <&fan 1 2>;
- trip = <&tj_trip_active1>;
- };
- };
- };
- };
-
- vdd_1v8_sys: regulator-vdd-1v8-sys {
- compatible = "regulator-fixed";
- regulator-name = "VDD_1V8_SYS";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- vdd_3v3_pcie: regulator-vdd-3v3-pcie {
- compatible = "regulator-fixed";
- regulator-name = "VDD_3V3_PCIE";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpio TEGRA234_MAIN_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
- regulator-boot-on;
- enable-active-high;
- };
-
- vdd_12v_pcie: regulator-vdd-12v-pcie {
- compatible = "regulator-fixed";
- regulator-name = "VDD_12V_PCIE";
- regulator-min-microvolt = <12000000>;
- regulator-max-microvolt = <12000000>;
- gpio = <&gpio TEGRA234_MAIN_GPIO(A, 1) GPIO_ACTIVE_LOW>;
- regulator-boot-on;
- };
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0008.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0008.dts
new file mode 100644
index 000000000000..979f085691a1
--- /dev/null
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0008.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+// Module files must be included first
+#include "tegra234-p3701-0008.dtsi"
+#include "tegra234-p3737-0000+p3701.dtsi"
+
+/ {
+ model = "NVIDIA Jetson AGX Orin Developer Kit";
+ compatible = "nvidia,p3737-0000+p3701-0008", "nvidia,p3701-0008", "nvidia,tegra234";
+};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701.dtsi
new file mode 100644
index 000000000000..f6cad29355e6
--- /dev/null
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701.dtsi
@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/clock/tegra234-clock.h>
+#include <dt-bindings/gpio/tegra234-gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/input/gpio-keys.h>
+#include <dt-bindings/sound/rt5640.h>
+
+/ {
+ aliases {
+ serial0 = &tcu;
+ serial1 = &uarta;
+ };
+
+ chosen {
+ bootargs = "console=ttyTCU0,115200n8";
+ stdout-path = "serial0:115200n8";
+ };
+
+ bus@0 {
+ aconnect@2900000 {
+ ahub@2900800 {
+ i2s@2901000 {
+ ports {
+ port@1 {
+ endpoint {
+ dai-format = "i2s";
+ remote-endpoint = <&rt5640_ep>;
+ };
+ };
+ };
+ };
+ };
+ };
+
+ serial@3100000 {
+ compatible = "nvidia,tegra194-hsuart";
+ reset-names = "serial";
+ status = "okay";
+ };
+
+ i2c@3160000 {
+ status = "okay";
+
+ eeprom@56 {
+ compatible = "atmel,24c02";
+ reg = <0x56>;
+
+ label = "system";
+ vcc-supply = <&vdd_1v8_sys>;
+ address-width = <8>;
+ pagesize = <8>;
+ size = <256>;
+ read-only;
+ };
+ };
+
+ serial@31d0000 {
+ current-speed = <115200>;
+ status = "okay";
+ };
+
+ i2c@31e0000 {
+ status = "okay";
+
+ audio-codec@1c {
+ compatible = "realtek,rt5640";
+ reg = <0x1c>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA234_MAIN_GPIO(AC, 5) GPIO_ACTIVE_HIGH>;
+ clocks = <&bpmp TEGRA234_CLK_AUD_MCLK>;
+ clock-names = "mclk";
+ realtek,dmic1-data-pin = <RT5640_DMIC1_DATA_PIN_NONE>;
+ realtek,dmic2-data-pin = <RT5640_DMIC2_DATA_PIN_NONE>;
+ realtek,jack-detect-source = <RT5640_JD_SRC_HDA_HEADER>;
+ sound-name-prefix = "CVB-RT";
+
+ port {
+ rt5640_ep: endpoint {
+ remote-endpoint = <&i2s1_dap>;
+ mclk-fs = <256>;
+ };
+ };
+ };
+ };
+
+ pwm@3280000 {
+ status = "okay";
+ };
+
+ pwm@32a0000 {
+ assigned-clocks = <&bpmp TEGRA234_CLK_PWM3>;
+ assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
+ status = "okay";
+ };
+
+ pwm@32c0000 {
+ status = "okay";
+ };
+
+ pwm@32f0000 {
+ status = "okay";
+ };
+
+ mmc@3400000 {
+ status = "okay";
+ bus-width = <4>;
+ cd-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 7) GPIO_ACTIVE_LOW>;
+ disable-wp;
+ };
+
+ hda@3510000 {
+ nvidia,model = "NVIDIA Jetson AGX Orin HDA";
+ status = "okay";
+ };
+
+ padctl@3520000 {
+ status = "okay";
+
+ pads {
+ usb2 {
+ lanes {
+ usb2-0 {
+ status = "okay";
+ };
+
+ usb2-1 {
+ status = "okay";
+ };
+
+ usb2-2 {
+ status = "okay";
+ };
+
+ usb2-3 {
+ status = "okay";
+ };
+ };
+ };
+
+ usb3 {
+ lanes {
+ usb3-0 {
+ status = "okay";
+ };
+
+ usb3-1 {
+ status = "okay";
+ };
+
+ usb3-2 {
+ status = "okay";
+ };
+ };
+ };
+ };
+
+ ports {
+ usb2-0 {
+ mode = "otg";
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ hs_typec_p1: endpoint {
+ remote-endpoint = <&hs_ucsi_ccg_p1>;
+ };
+ };
+ };
+
+ usb2-1 {
+ mode = "host";
+ status = "okay";
+
+ port {
+ hs_typec_p0: endpoint {
+ remote-endpoint = <&hs_ucsi_ccg_p0>;
+ };
+ };
+ };
+
+ usb2-2 {
+ mode = "host";
+ status = "okay";
+ };
+
+ usb2-3 {
+ mode = "host";
+ status = "okay";
+ };
+
+ usb3-0 {
+ nvidia,usb2-companion = <1>;
+ status = "okay";
+
+ port {
+ ss_typec_p0: endpoint {
+ remote-endpoint = <&ss_ucsi_ccg_p0>;
+ };
+ };
+ };
+
+ usb3-1 {
+ nvidia,usb2-companion = <0>;
+ status = "okay";
+
+ port {
+ ss_typec_p1: endpoint {
+ remote-endpoint = <&ss_ucsi_ccg_p1>;
+ };
+ };
+ };
+
+ usb3-2 {
+ nvidia,usb2-companion = <3>;
+ status = "okay";
+ };
+ };
+ };
+
+ usb@3550000 {
+ status = "okay";
+
+ phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>,
+ <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>;
+ phy-names = "usb2-0", "usb3-0";
+ };
+
+ usb@3610000 {
+ status = "okay";
+
+ 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-2}>,
+ <&{/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-1}>,
+ <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-2}>;
+ phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3",
+ "usb3-0", "usb3-1", "usb3-2";
+ };
+
+ ethernet@6800000 {
+ status = "okay";
+
+ phy-handle = <&mgbe0_phy>;
+ phy-mode = "10gbase-r";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mgbe0_phy: phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <0x0>;
+
+ #phy-cells = <0>;
+ };
+ };
+ };
+
+ i2c@c240000 {
+ status = "okay";
+
+ typec@8 {
+ compatible = "cypress,cypd4226";
+ reg = <0x08>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA234_MAIN_GPIO(Y, 4) IRQ_TYPE_LEVEL_LOW>;
+ firmware-name = "nvidia,jetson-agx-xavier";
+ status = "okay";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ccg_typec_con0: connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ label = "USB-C";
+ data-role = "host";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ hs_ucsi_ccg_p0: endpoint {
+ remote-endpoint = <&hs_typec_p0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ ss_ucsi_ccg_p0: endpoint {
+ remote-endpoint = <&ss_typec_p0>;
+ };
+ };
+ };
+ };
+
+ ccg_typec_con1: connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ label = "USB-C";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ hs_ucsi_ccg_p1: endpoint {
+ remote-endpoint = <&hs_typec_p1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ ss_ucsi_ccg_p1: endpoint {
+ remote-endpoint = <&ss_typec_p1>;
+ };
+ };
+ };
+ };
+ };
+ };
+
+ pcie@14100000 {
+ status = "okay";
+
+ vddio-pex-ctl-supply = <&vdd_1v8_ao>;
+
+ phys = <&p2u_hsio_3>;
+ phy-names = "p2u-0";
+ };
+
+ pcie@14160000 {
+ status = "okay";
+
+ vddio-pex-ctl-supply = <&vdd_1v8_ao>;
+
+ phys = <&p2u_hsio_4>, <&p2u_hsio_5>, <&p2u_hsio_6>,
+ <&p2u_hsio_7>;
+ phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3";
+ };
+
+ pcie@141a0000 {
+ status = "okay";
+
+ vddio-pex-ctl-supply = <&vdd_1v8_ls>;
+ vpcie3v3-supply = <&vdd_3v3_pcie>;
+ vpcie12v-supply = <&vdd_12v_pcie>;
+
+ phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>,
+ <&p2u_nvhs_3>, <&p2u_nvhs_4>, <&p2u_nvhs_5>,
+ <&p2u_nvhs_6>, <&p2u_nvhs_7>;
+ phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4",
+ "p2u-5", "p2u-6", "p2u-7";
+ };
+
+ pcie-ep@141a0000 {
+ status = "disabled";
+
+ vddio-pex-ctl-supply = <&vdd_1v8_ls>;
+
+ reset-gpios = <&gpio TEGRA234_MAIN_GPIO(AF, 1) GPIO_ACTIVE_LOW>;
+
+ nvidia,refclk-select-gpios = <&gpio_aon
+ TEGRA234_AON_GPIO(AA, 4)
+ GPIO_ACTIVE_HIGH>;
+
+ phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>,
+ <&p2u_nvhs_3>, <&p2u_nvhs_4>, <&p2u_nvhs_5>,
+ <&p2u_nvhs_6>, <&p2u_nvhs_7>;
+ phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4",
+ "p2u-5", "p2u-6", "p2u-7";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ status = "okay";
+
+ key-force-recovery {
+ label = "Force Recovery";
+ gpios = <&gpio TEGRA234_MAIN_GPIO(G, 0) GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_KEY>;
+ linux,code = <BTN_1>;
+ };
+
+ key-power {
+ label = "Power";
+ gpios = <&gpio_aon TEGRA234_AON_GPIO(EE, 4) GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_KEY>;
+ linux,code = <KEY_POWER>;
+ wakeup-event-action = <EV_ACT_ASSERTED>;
+ wakeup-source;
+ };
+
+ key-suspend {
+ label = "Suspend";
+ gpios = <&gpio TEGRA234_MAIN_GPIO(G, 2) GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_KEY>;
+ linux,code = <KEY_SLEEP>;
+ };
+ };
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ cooling-levels = <66 215 255>;
+ pwms = <&pwm3 0 45334>;
+ #cooling-cells = <2>;
+ };
+
+ serial {
+ status = "okay";
+ };
+
+ sound {
+ compatible = "nvidia,tegra186-audio-graph-card";
+ status = "okay";
+
+ dais = /* ADMAIF (FE) Ports */
+ <&admaif0_port>, <&admaif1_port>, <&admaif2_port>, <&admaif3_port>,
+ <&admaif4_port>, <&admaif5_port>, <&admaif6_port>, <&admaif7_port>,
+ <&admaif8_port>, <&admaif9_port>, <&admaif10_port>, <&admaif11_port>,
+ <&admaif12_port>, <&admaif13_port>, <&admaif14_port>, <&admaif15_port>,
+ <&admaif16_port>, <&admaif17_port>, <&admaif18_port>, <&admaif19_port>,
+ /* XBAR Ports */
+ <&xbar_i2s1_port>, <&xbar_i2s2_port>, <&xbar_i2s4_port>,
+ <&xbar_i2s6_port>, <&xbar_dmic3_port>,
+ <&xbar_sfc1_in_port>, <&xbar_sfc2_in_port>,
+ <&xbar_sfc3_in_port>, <&xbar_sfc4_in_port>,
+ <&xbar_mvc1_in_port>, <&xbar_mvc2_in_port>,
+ <&xbar_amx1_in1_port>, <&xbar_amx1_in2_port>,
+ <&xbar_amx1_in3_port>, <&xbar_amx1_in4_port>,
+ <&xbar_amx2_in1_port>, <&xbar_amx2_in2_port>,
+ <&xbar_amx2_in3_port>, <&xbar_amx2_in4_port>,
+ <&xbar_amx3_in1_port>, <&xbar_amx3_in2_port>,
+ <&xbar_amx3_in3_port>, <&xbar_amx3_in4_port>,
+ <&xbar_amx4_in1_port>, <&xbar_amx4_in2_port>,
+ <&xbar_amx4_in3_port>, <&xbar_amx4_in4_port>,
+ <&xbar_adx1_in_port>, <&xbar_adx2_in_port>,
+ <&xbar_adx3_in_port>, <&xbar_adx4_in_port>,
+ <&xbar_mix_in1_port>, <&xbar_mix_in2_port>,
+ <&xbar_mix_in3_port>, <&xbar_mix_in4_port>,
+ <&xbar_mix_in5_port>, <&xbar_mix_in6_port>,
+ <&xbar_mix_in7_port>, <&xbar_mix_in8_port>,
+ <&xbar_mix_in9_port>, <&xbar_mix_in10_port>,
+ <&xbar_asrc_in1_port>, <&xbar_asrc_in2_port>,
+ <&xbar_asrc_in3_port>, <&xbar_asrc_in4_port>,
+ <&xbar_asrc_in5_port>, <&xbar_asrc_in6_port>,
+ <&xbar_asrc_in7_port>,
+ <&xbar_ope1_in_port>,
+ /* HW accelerators */
+ <&sfc1_out_port>, <&sfc2_out_port>,
+ <&sfc3_out_port>, <&sfc4_out_port>,
+ <&mvc1_out_port>, <&mvc2_out_port>,
+ <&amx1_out_port>, <&amx2_out_port>,
+ <&amx3_out_port>, <&amx4_out_port>,
+ <&adx1_out1_port>, <&adx1_out2_port>,
+ <&adx1_out3_port>, <&adx1_out4_port>,
+ <&adx2_out1_port>, <&adx2_out2_port>,
+ <&adx2_out3_port>, <&adx2_out4_port>,
+ <&adx3_out1_port>, <&adx3_out2_port>,
+ <&adx3_out3_port>, <&adx3_out4_port>,
+ <&adx4_out1_port>, <&adx4_out2_port>,
+ <&adx4_out3_port>, <&adx4_out4_port>,
+ <&mix_out1_port>, <&mix_out2_port>, <&mix_out3_port>,
+ <&mix_out4_port>, <&mix_out5_port>,
+ <&asrc_out1_port>, <&asrc_out2_port>, <&asrc_out3_port>,
+ <&asrc_out4_port>, <&asrc_out5_port>, <&asrc_out6_port>,
+ <&ope1_out_port>,
+ /* BE I/O Ports */
+ <&i2s1_port>, <&i2s2_port>, <&i2s4_port>, <&i2s6_port>,
+ <&dmic3_port>;
+
+ label = "NVIDIA Jetson AGX Orin APE";
+
+ widgets = "Microphone", "CVB-RT MIC Jack",
+ "Microphone", "CVB-RT MIC",
+ "Headphone", "CVB-RT HP Jack",
+ "Speaker", "CVB-RT SPK";
+
+ routing = /* I2S1 <-> RT5640 */
+ "CVB-RT AIF1 Playback", "I2S1 DAP-Playback",
+ "I2S1 DAP-Capture", "CVB-RT AIF1 Capture",
+ /* RT5640 codec controls */
+ "CVB-RT HP Jack", "CVB-RT HPOL",
+ "CVB-RT HP Jack", "CVB-RT HPOR",
+ "CVB-RT IN1P", "CVB-RT MIC Jack",
+ "CVB-RT IN2P", "CVB-RT MIC Jack",
+ "CVB-RT SPK", "CVB-RT SPOLP",
+ "CVB-RT SPK", "CVB-RT SPORP",
+ "CVB-RT DMIC1", "CVB-RT MIC",
+ "CVB-RT DMIC2", "CVB-RT MIC";
+ };
+
+ thermal-zones {
+ tj-thermal {
+ cooling-maps {
+ map-active-0 {
+ cooling-device = <&fan 0 1>;
+ trip = <&tj_trip_active0>;
+ };
+
+ map-active-1 {
+ cooling-device = <&fan 1 2>;
+ trip = <&tj_trip_active1>;
+ };
+ };
+ };
+ };
+
+ vdd_1v8_sys: regulator-vdd-1v8-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_1V8_SYS";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ vdd_3v3_pcie: regulator-vdd-3v3-pcie {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_3V3_PCIE";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio TEGRA234_MAIN_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
+ regulator-boot-on;
+ enable-active-high;
+ };
+
+ vdd_12v_pcie: regulator-vdd-12v-pcie {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_12V_PCIE";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ gpio = <&gpio TEGRA234_MAIN_GPIO(A, 1) GPIO_ACTIVE_LOW>;
+ regulator-boot-on;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index ae002c7cf126..6ca8db4b8afe 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -112,10 +112,15 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs8550-aim300-aiot.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3.dtb
dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb4210-rb2.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb
+
+qrb5165-rb5-vision-mezzanine-dtbs := qrb5165-rb5.dtb qrb5165-rb5-vision-mezzanine.dtbo
+
dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtb
dtb-$(CONFIG_ARCH_QCOM) += qru1000-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb
@@ -191,6 +196,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sc8180x-lenovo-flex-5g.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc8180x-primus.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-crd.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-lenovo-thinkpad-x13s.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-microsoft-arcata.dtb
dtb-$(CONFIG_ARCH_QCOM) += sda660-inforce-ifc6560.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm450-lenovo-tbx605f.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm450-motorola-ali.dtb
@@ -207,6 +213,9 @@ 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
+
+sdm845-db845c-navigation-mezzanine-dtbs := sdm845-db845c.dtb sdm845-db845c-navigation-mezzanine.dtbo
+
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
@@ -235,6 +244,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sm6375-sony-xperia-murray-pdx225.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm7125-xiaomi-curtana.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm7125-xiaomi-joyeuse.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm7225-fairphone-fp4.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm7325-nothing-spacewar.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-microsoft-surface-duo.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-mtp.dtb
@@ -271,6 +281,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8650-qrd.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e78100-lenovo-thinkpad-t14s.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e80100-asus-vivobook-s15.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e80100-crd.dtb
+dtb-$(CONFIG_ARCH_QCOM) += x1e80100-dell-xps13-9345.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e80100-lenovo-yoga-slim7x.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e80100-microsoft-romulus13.dtb
dtb-$(CONFIG_ARCH_QCOM) += x1e80100-microsoft-romulus15.dtb
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 7e6e2c121979..8914f2ef0bc4 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -31,27 +31,27 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x1>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x80000>;
diff --git a/arch/arm64/boot/dts/qcom/ipq5332.dtsi b/arch/arm64/boot/dts/qcom/ipq5332.dtsi
index 71328b223531..d3c3e215a15c 100644
--- a/arch/arm64/boot/dts/qcom/ipq5332.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5332.dtsi
@@ -31,47 +31,47 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x1>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x2>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x3>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
index 8edd535a188f..dbf6716bcb59 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -34,12 +34,12 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -47,12 +47,12 @@
#cooling-cells = <2>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x1>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -60,12 +60,12 @@
#cooling-cells = <2>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -73,12 +73,12 @@
#cooling-cells = <2>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x3>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -86,7 +86,7 @@
#cooling-cells = <2>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -1015,10 +1015,10 @@
cooling-maps {
map0 {
trip = <&cpu_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
index 284a4553070f..78e1992b7495 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -32,39 +32,39 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
enable-method = "psci";
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x1>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x3>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
diff --git a/arch/arm64/boot/dts/qcom/ipq9574.dtsi b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
index 08a82a5cf667..d1fd35ebc4a2 100644
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
@@ -34,12 +34,12 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -47,12 +47,12 @@
#cooling-cells = <2>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x1>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -60,12 +60,12 @@
#cooling-cells = <2>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x2>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -73,12 +73,12 @@
#cooling-cells = <2>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x3>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -86,7 +86,7 @@
#cooling-cells = <2>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -234,7 +234,7 @@
};
mdio: mdio@90000 {
- compatible = "qcom,ipq9574-mdio", "qcom,ipq4019-mdio";
+ compatible = "qcom,ipq9574-mdio", "qcom,ipq4019-mdio";
reg = <0x00090000 0x64>;
#address-cells = <1>;
#size-cells = <0>;
@@ -863,10 +863,10 @@
cooling-maps {
map0 {
trip = <&cpu0_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -891,10 +891,10 @@
cooling-maps {
map0 {
trip = <&cpu1_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -919,10 +919,10 @@
cooling-maps {
map0 {
trip = <&cpu2_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -947,10 +947,10 @@
cooling-maps {
map0 {
trip = <&cpu3_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts
index 3cfa80e38a9e..d6b03e08c34a 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts
@@ -57,7 +57,7 @@
widgets = "Speaker", "Speaker",
"Headphone", "Headphones";
pin-switches = "Speaker", "Headphones";
- audio-routing = "Speaker", "Speaker Amp OUT",
+ audio-routing = "Speaker", "Speaker Amp OUT",
"Speaker Amp IN", "HPH_R",
"Headphones", "Headphones Switch OUTL",
"Headphones", "Headphones Switch OUTR",
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 0ee44706b70b..5e558bcc9d87 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -133,67 +133,67 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
enable-method = "psci";
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,acc = <&cpu0_acc>;
qcom,saw = <&cpu0_saw>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x1>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
enable-method = "psci";
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
qcom,acc = <&cpu1_acc>;
qcom,saw = <&cpu1_saw>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
enable-method = "psci";
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
qcom,acc = <&cpu2_acc>;
qcom,saw = <&cpu2_saw>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x3>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
enable-method = "psci";
clocks = <&apcs>;
operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
qcom,acc = <&cpu3_acc>;
qcom,saw = <&cpu3_saw>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -202,7 +202,7 @@
idle-states {
entry-method = "psci";
- CPU_SLEEP_0: cpu-sleep-0 {
+ cpu_sleep_0: cpu-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "standalone-power-collapse";
arm,psci-suspend-param = <0x40000002>;
@@ -215,7 +215,7 @@
domain-idle-states {
- CLUSTER_RET: cluster-retention {
+ cluster_ret: cluster-retention {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000012>;
entry-latency-us = <500>;
@@ -223,7 +223,7 @@
min-residency-us = <2000>;
};
- CLUSTER_PWRDN: cluster-gdhs {
+ cluster_pwrdn: cluster-gdhs {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000032>;
entry-latency-us = <2000>;
@@ -273,33 +273,33 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cluster {
+ cluster_pd: power-domain-cluster {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>;
+ domain-idle-states = <&cluster_ret>, <&cluster_pwrdn>;
};
};
@@ -823,7 +823,7 @@
reg = <0x00850000 0x1000>;
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
status = "disabled";
};
@@ -832,7 +832,7 @@
reg = <0x00852000 0x1000>;
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
status = "disabled";
};
@@ -841,7 +841,7 @@
reg = <0x00854000 0x1000>;
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
status = "disabled";
};
@@ -850,7 +850,7 @@
reg = <0x00856000 0x1000>;
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
status = "disabled";
};
@@ -864,7 +864,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
arm,cs-dev-assoc = <&etm0>;
status = "disabled";
@@ -879,7 +879,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
arm,cs-dev-assoc = <&etm1>;
status = "disabled";
@@ -894,7 +894,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
arm,cs-dev-assoc = <&etm2>;
status = "disabled";
@@ -909,7 +909,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
arm,cs-dev-assoc = <&etm3>;
status = "disabled";
@@ -923,7 +923,7 @@
clock-names = "apb_pclk", "atclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
status = "disabled";
@@ -944,7 +944,7 @@
clock-names = "apb_pclk", "atclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
status = "disabled";
@@ -965,7 +965,7 @@
clock-names = "apb_pclk", "atclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
status = "disabled";
@@ -986,7 +986,7 @@
clock-names = "apb_pclk", "atclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
status = "disabled";
@@ -2644,10 +2644,10 @@
cooling-maps {
map0 {
trip = <&cpu0_1_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2673,10 +2673,10 @@
cooling-maps {
map0 {
trip = <&cpu2_3_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8939.dtsi b/arch/arm64/boot/dts/qcom/msm8939.dtsi
index 28634789a8a9..7a6f1eeaa3fc 100644
--- a/arch/arm64/boot/dts/qcom/msm8939.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8939.dtsi
@@ -42,122 +42,122 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@100 {
+ cpu0: cpu@100 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x100>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs1_mbox>;
#cooling-cells = <2>;
- L2_1: l2-cache {
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@101 {
+ cpu1: cpu@101 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x101>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs1_mbox>;
#cooling-cells = <2>;
};
- CPU2: cpu@102 {
+ cpu2: cpu@102 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x102>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,acc = <&acc2>;
qcom,saw = <&saw2>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs1_mbox>;
#cooling-cells = <2>;
};
- CPU3: cpu@103 {
+ cpu3: cpu@103 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x103>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,acc = <&acc3>;
qcom,saw = <&saw3>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs1_mbox>;
#cooling-cells = <2>;
};
- CPU4: cpu@0 {
+ cpu4: cpu@0 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x0>;
qcom,acc = <&acc4>;
qcom,saw = <&saw4>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs0_mbox>;
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU5: cpu@1 {
+ cpu5: cpu@1 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x1>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,acc = <&acc5>;
qcom,saw = <&saw5>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs0_mbox>;
#cooling-cells = <2>;
};
- CPU6: cpu@2 {
+ cpu6: cpu@2 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,acc = <&acc6>;
qcom,saw = <&saw6>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs0_mbox>;
#cooling-cells = <2>;
};
- CPU7: cpu@3 {
+ cpu7: cpu@3 {
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "spin-table";
reg = <0x3>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,acc = <&acc7>;
qcom,saw = <&saw7>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
clocks = <&apcs0_mbox>;
#cooling-cells = <2>;
};
idle-states {
- CPU_SLEEP_0: cpu-sleep-0 {
+ cpu_sleep_0: cpu-sleep-0 {
compatible = "arm,idle-state";
entry-latency-us = <130>;
exit-latency-us = <150>;
@@ -182,19 +182,19 @@
/* LITTLE (efficiency) cluster */
cluster0 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
@@ -202,19 +202,19 @@
/* Boot CPU is cluster 1 core 0 */
cluster1 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
};
@@ -248,7 +248,7 @@
smd-edge {
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
- mboxes = <&apcs1_mbox 0>;
+ qcom,ipc = <&apcs1_mbox 8 0>;
qcom,smd-edge = <15>;
rpm_requests: rpm-requests {
@@ -2318,10 +2318,10 @@
cooling-maps {
map0 {
trip = <&cpu0_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2348,10 +2348,10 @@
cooling-maps {
map0 {
trip = <&cpu1_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2378,10 +2378,10 @@
cooling-maps {
map0 {
trip = <&cpu2_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2408,10 +2408,10 @@
cooling-maps {
map0 {
trip = <&cpu3_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2438,10 +2438,10 @@
cooling-maps {
map0 {
trip = <&cpu4567_alert>;
- 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>;
+ 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>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index d20fd3d7c46e..af4c341e2533 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -38,125 +38,125 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x1>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x2>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x3>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
};
- CPU4: cpu@100 {
+ cpu4: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x100>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
#cooling-cells = <2>;
};
- CPU5: cpu@101 {
+ cpu5: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x101>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
#cooling-cells = <2>;
};
- CPU6: cpu@102 {
+ cpu6: cpu@102 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x102>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
#cooling-cells = <2>;
};
- CPU7: cpu@103 {
+ cpu7: cpu@103 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x103>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
#cooling-cells = <2>;
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
- L2_0: l2-cache-0 {
+ l2_0: l2-cache-0 {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
- L2_1: l2-cache-1 {
+ l2_1: l2-cache-1 {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -1985,7 +1985,7 @@
cooling-maps {
map0 {
trip = <&cpu0_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2009,7 +2009,7 @@
cooling-maps {
map0 {
trip = <&cpu1_alert>;
- cooling-device = <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2033,7 +2033,7 @@
cooling-maps {
map0 {
trip = <&cpu2_alert>;
- cooling-device = <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2057,7 +2057,7 @@
cooling-maps {
map0 {
trip = <&cpu3_alert>;
- cooling-device = <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2079,7 +2079,7 @@
cooling-maps {
map0 {
trip = <&cpu4_alert>;
- cooling-device = <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2101,7 +2101,7 @@
cooling-maps {
map0 {
trip = <&cpu5_alert>;
- cooling-device = <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2123,7 +2123,7 @@
cooling-maps {
map0 {
trip = <&cpu6_alert>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2145,7 +2145,7 @@
cooling-maps {
map0 {
trip = <&cpu7_alert>;
- cooling-device = <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8976.dtsi b/arch/arm64/boot/dts/qcom/msm8976.dtsi
index 06af6e5ec578..d036f31dfdca 100644
--- a/arch/arm64/boot/dts/qcom/msm8976.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8976.dtsi
@@ -31,7 +31,7 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
@@ -42,7 +42,7 @@
#cooling-cells = <2>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x1>;
@@ -53,7 +53,7 @@
#cooling-cells = <2>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x2>;
@@ -64,7 +64,7 @@
#cooling-cells = <2>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x3>;
@@ -75,7 +75,7 @@
#cooling-cells = <2>;
};
- CPU4: cpu@100 {
+ cpu4: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a72";
reg = <0x100>;
@@ -86,7 +86,7 @@
#cooling-cells = <2>;
};
- CPU5: cpu@101 {
+ cpu5: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a72";
reg = <0x101>;
@@ -97,7 +97,7 @@
#cooling-cells = <2>;
};
- CPU6: cpu@102 {
+ cpu6: cpu@102 {
device_type = "cpu";
compatible = "arm,cortex-a72";
reg = <0x102>;
@@ -108,7 +108,7 @@
#cooling-cells = <2>;
};
- CPU7: cpu@103 {
+ cpu7: cpu@103 {
device_type = "cpu";
compatible = "arm,cortex-a72";
reg = <0x103>;
@@ -122,37 +122,37 @@
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -1193,7 +1193,7 @@
apps_iommu: iommu@1ee0000 {
compatible = "qcom,msm8976-iommu", "qcom,msm-iommu-v2";
reg = <0x01ee0000 0x3000>;
- ranges = <0 0x01e20000 0x20000>;
+ ranges = <0 0x01e20000 0x20000>;
clocks = <&gcc GCC_SMMU_CFG_CLK>,
<&gcc GCC_APSS_TCU_CLK>;
diff --git a/arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts b/arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts
index 38b305816d2f..4520d5d51a29 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts
@@ -91,27 +91,27 @@
};
};
-&CPU0 {
+&cpu0 {
enable-method = "spin-table";
};
-&CPU1 {
+&cpu1 {
enable-method = "spin-table";
};
-&CPU2 {
+&cpu2 {
enable-method = "spin-table";
};
-&CPU3 {
+&cpu3 {
enable-method = "spin-table";
};
-&CPU4 {
+&cpu4 {
enable-method = "spin-table";
};
-&CPU5 {
+&cpu5 {
enable-method = "spin-table";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
index 133f9c2540bc..d0290a20b888 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
@@ -175,7 +175,7 @@
};
&pm8994_spmi_regulators {
- VDD_APC0: s8 {
+ s8 {
regulator-min-microvolt = <680000>;
regulator-max-microvolt = <1180000>;
regulator-always-on;
@@ -183,7 +183,7 @@
};
/* APC1 is 3-phase, but quoting downstream, s11 is "the gang leader" */
- VDD_APC1: s11 {
+ s11 {
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1225000>;
regulator-always-on;
diff --git a/arch/arm64/boot/dts/qcom/msm8992.dtsi b/arch/arm64/boot/dts/qcom/msm8992.dtsi
index 02fc3795dbfd..b2dc46c25fa2 100644
--- a/arch/arm64/boot/dts/qcom/msm8992.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8992.dtsi
@@ -6,8 +6,8 @@
#include "msm8994.dtsi"
/* 8992 only features 2 A57 cores. */
-/delete-node/ &CPU6;
-/delete-node/ &CPU7;
+/delete-node/ &cpu6;
+/delete-node/ &cpu7;
/delete-node/ &cpu6_map;
/delete-node/ &cpu7_map;
diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi
index fc2a7f13f690..1acb0f159511 100644
--- a/arch/arm64/boot/dts/qcom/msm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi
@@ -43,114 +43,114 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x1>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x2>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x3>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU4: cpu@100 {
+ cpu4: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a57";
reg = <0x0 0x100>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
+ next-level-cache = <&l2_1>;
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU5: cpu@101 {
+ cpu5: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a57";
reg = <0x0 0x101>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
- CPU6: cpu@102 {
+ cpu6: cpu@102 {
device_type = "cpu";
compatible = "arm,cortex-a57";
reg = <0x0 0x102>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
- CPU7: cpu@103 {
+ cpu7: cpu@103 {
device_type = "cpu";
compatible = "arm,cortex-a57";
reg = <0x0 0x103>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
cpu6_map: core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
cpu7_map: core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index e5966724f37c..b379623c1b8a 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -43,90 +43,90 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x0>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
capacity-dmips-mhz = <1024>;
clocks = <&kryocc 0>;
interconnects = <&cbf MASTER_CBF_M4M &cbf SLAVE_CBF_M4M>;
operating-points-v2 = <&cluster0_opp>;
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x1>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
capacity-dmips-mhz = <1024>;
clocks = <&kryocc 0>;
interconnects = <&cbf MASTER_CBF_M4M &cbf SLAVE_CBF_M4M>;
operating-points-v2 = <&cluster0_opp>;
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU2: cpu@100 {
+ cpu2: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x100>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
capacity-dmips-mhz = <1024>;
clocks = <&kryocc 1>;
interconnects = <&cbf MASTER_CBF_M4M &cbf SLAVE_CBF_M4M>;
operating-points-v2 = <&cluster1_opp>;
#cooling-cells = <2>;
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
+ next-level-cache = <&l2_1>;
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU3: cpu@101 {
+ cpu3: cpu@101 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x101>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
capacity-dmips-mhz = <1024>;
clocks = <&kryocc 1>;
interconnects = <&cbf MASTER_CBF_M4M &cbf SLAVE_CBF_M4M>;
operating-points-v2 = <&cluster1_opp>;
#cooling-cells = <2>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
};
cluster1 {
core0 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core1 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
};
@@ -134,7 +134,7 @@
idle-states {
entry-method = "psci";
- CPU_SLEEP_0: cpu-sleep-0 {
+ cpu_sleep_0: cpu-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "standalone-power-collapse";
arm,psci-suspend-param = <0x00000004>;
@@ -2829,7 +2829,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
etm@3840000 {
@@ -2839,7 +2839,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
out-ports {
port {
@@ -2858,7 +2858,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
etm@3940000 {
@@ -2868,7 +2868,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
out-ports {
port {
@@ -2923,7 +2923,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
etm@3a40000 {
@@ -2933,7 +2933,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
out-ports {
port {
@@ -2952,7 +2952,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>;
clock-names = "apb_pclk";
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
etm@3b40000 {
@@ -2962,7 +2962,7 @@
clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
out-ports {
port {
diff --git a/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
index 3b7172aa4037..157c4f04564b 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
@@ -61,36 +61,36 @@
* not advertised as enabled in ACPI, and enabling it in DT can cause boot
* hangs.
*/
-&CPU0 {
- cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+&cpu0 {
+ cpu-idle-states = <&little_cpu_sleep_1>;
};
-&CPU1 {
- cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+&cpu1 {
+ cpu-idle-states = <&little_cpu_sleep_1>;
};
-&CPU2 {
- cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+&cpu2 {
+ cpu-idle-states = <&little_cpu_sleep_1>;
};
-&CPU3 {
- cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+&cpu3 {
+ cpu-idle-states = <&little_cpu_sleep_1>;
};
-&CPU4 {
- cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+&cpu4 {
+ cpu-idle-states = <&big_cpu_sleep_1>;
};
-&CPU5 {
- cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+&cpu5 {
+ cpu-idle-states = <&big_cpu_sleep_1>;
};
-&CPU6 {
- cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+&cpu6 {
+ cpu-idle-states = <&big_cpu_sleep_1>;
};
-&CPU7 {
- cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+&cpu7 {
+ cpu-idle-states = <&big_cpu_sleep_1>;
};
/*
@@ -128,6 +128,12 @@
};
};
+&pm8998_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+
+ status = "okay";
+};
+
&qusb2phy {
status = "okay";
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 a105143bee4a..901f6ac0084d 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts
@@ -3,12 +3,45 @@
/dts-v1/;
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include "msm8998-clamshell.dtsi"
/ {
model = "Lenovo Miix 630";
compatible = "lenovo,miix-630", "qcom,msm8998";
chassis-type = "convertible";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ autorepeat;
+
+ pinctrl-0 = <&vol_up_pin_a>;
+ pinctrl-names = "default";
+
+ key-vol-up {
+ label = "Volume Up";
+ gpios = <&pm8998_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+ };
+};
+
+&blsp1_i2c5 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchscreen@10 {
+ compatible = "hid-over-i2c";
+ reg = <0x10>;
+ hid-descr-addr = <0x1>;
+
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&i2c5_hid_active>;
+ pinctrl-names = "default";
+ };
};
&blsp1_i2c6 {
@@ -27,11 +60,46 @@
};
};
+&pm8998_gpios {
+ vol_up_pin_a: vol-up-active-state {
+ pins = "gpio6";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ };
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/msm8998/LENOVO/81F1/qcadsp8998.mbn";
+
+ status = "okay";
+};
+
&remoteproc_mss {
firmware-name = "qcom/msm8998/LENOVO/81F1/qcdsp1v28998.mbn",
"qcom/msm8998/LENOVO/81F1/qcdsp28998.mbn";
};
+&remoteproc_slpi {
+ firmware-name = "qcom/msm8998/LENOVO/81F1/qcslpi8998.mbn";
+
+ status = "okay";
+};
+
&sdhc2 {
cd-gpios = <&tlmm 95 GPIO_ACTIVE_HIGH>;
};
+
+&tlmm {
+ i2c5_hid_active: i2c5-hid-active-state {
+ pins = "gpio125";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+};
+
+&wifi {
+ qcom,ath10k-calibration-variant = "Lenovo_Miix630";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
index 9aa9c5cee355..c2caad85c668 100644
--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -136,130 +136,130 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x0>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ cpu-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x1>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
- next-level-cache = <&L2_0>;
+ cpu-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
+ next-level-cache = <&l2_0>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x2>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
- next-level-cache = <&L2_0>;
+ cpu-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
+ next-level-cache = <&l2_0>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x3>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
- next-level-cache = <&L2_0>;
+ cpu-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
+ next-level-cache = <&l2_0>;
};
- CPU4: cpu@100 {
+ cpu4: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x100>;
enable-method = "psci";
capacity-dmips-mhz = <1536>;
- cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ next-level-cache = <&l2_1>;
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU5: cpu@101 {
+ cpu5: cpu@101 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x101>;
enable-method = "psci";
capacity-dmips-mhz = <1536>;
- cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
- next-level-cache = <&L2_1>;
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ next-level-cache = <&l2_1>;
};
- CPU6: cpu@102 {
+ cpu6: cpu@102 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x102>;
enable-method = "psci";
capacity-dmips-mhz = <1536>;
- cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
- next-level-cache = <&L2_1>;
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ next-level-cache = <&l2_1>;
};
- CPU7: cpu@103 {
+ cpu7: cpu@103 {
device_type = "cpu";
compatible = "qcom,kryo280";
reg = <0x0 0x103>;
enable-method = "psci";
capacity-dmips-mhz = <1536>;
- cpu-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
- next-level-cache = <&L2_1>;
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ next-level-cache = <&l2_1>;
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -267,7 +267,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-retention";
/* CPU Retention (C2D), L2 Active */
@@ -277,7 +277,7 @@
min-residency-us = <504>;
};
- LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
+ little_cpu_sleep_1: cpu-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "little-power-collapse";
/* CPU + L2 Power Collapse (C3, D4) */
@@ -288,7 +288,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-retention";
/* CPU Retention (C2D), L2 Active */
@@ -298,7 +298,7 @@
min-residency-us = <1302>;
};
- BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
+ big_cpu_sleep_1: cpu-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "big-power-collapse";
/* CPU + L2 Power Collapse (C3, D4) */
@@ -1415,6 +1415,34 @@
drive-strength = <6>;
bias-disable;
};
+
+ hdmi_cec_default: hdmi-cec-default-state {
+ pins = "gpio31";
+ function = "hdmi_cec";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ hdmi_ddc_default: hdmi-ddc-default-state {
+ pins = "gpio32", "gpio33";
+ function = "hdmi_ddc";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ hdmi_hpd_default: hdmi-hpd-default-state {
+ pins = "gpio34";
+ function = "hdmi_hot";
+ drive-strength = <16>;
+ bias-pull-down;
+ };
+
+ hdmi_hpd_sleep: hdmi-hpd-sleep-state {
+ pins = "gpio34";
+ function = "hdmi_hot";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
};
remoteproc_mss: remoteproc@4080000 {
@@ -1846,7 +1874,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
out-ports {
port {
@@ -1866,7 +1894,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
out-ports {
port {
@@ -1886,7 +1914,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
out-ports {
port {
@@ -1906,7 +1934,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
out-ports {
port {
@@ -2040,7 +2068,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
out-ports {
port {
@@ -2059,7 +2087,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
out-ports {
port {
@@ -2078,7 +2106,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
out-ports {
port {
@@ -2097,7 +2125,7 @@
clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
clock-names = "apb_pclk", "atclk";
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
out-ports {
port {
@@ -2766,7 +2794,7 @@
<&mdss_dsi0_phy 0>,
<&mdss_dsi1_phy 1>,
<&mdss_dsi1_phy 0>,
- <0>,
+ <&mdss_hdmi_phy 0>,
<0>,
<0>,
<&gcc GCC_MMSS_GPLL0_DIV_CLK>;
@@ -2871,6 +2899,14 @@
remote-endpoint = <&mdss_dsi1_in>;
};
};
+
+ port@2 {
+ reg = <2>;
+
+ dpu_intf3_out: endpoint {
+ remote-endpoint = <&hdmi_in>;
+ };
+ };
};
};
@@ -3026,6 +3062,96 @@
status = "disabled";
};
+
+ mdss_hdmi: hdmi-tx@c9a0000 {
+ compatible = "qcom,hdmi-tx-8998";
+ reg = <0x0c9a0000 0x50c>,
+ <0x00780000 0x6220>,
+ <0x0c9e0000 0x2c>;
+ reg-names = "core_physical",
+ "qfprom_physical",
+ "hdcp_physical";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <8>;
+
+ clocks = <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_HDMI_CLK>,
+ <&mmcc MDSS_HDMI_DP_AHB_CLK>,
+ <&mmcc MDSS_EXTPCLK_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MNOC_AHB_CLK>,
+ <&mmcc MISC_AHB_CLK>;
+ clock-names =
+ "mdp_core",
+ "iface",
+ "core",
+ "alt_iface",
+ "extp",
+ "bus",
+ "mnoc",
+ "iface_mmss";
+
+ phys = <&mdss_hdmi_phy>;
+ #sound-dai-cells = <1>;
+
+ pinctrl-0 = <&hdmi_hpd_default>,
+ <&hdmi_ddc_default>,
+ <&hdmi_cec_default>;
+ pinctrl-1 = <&hdmi_hpd_sleep>,
+ <&hdmi_ddc_default>,
+ <&hdmi_cec_default>;
+ pinctrl-names = "default", "sleep";
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ hdmi_in: endpoint {
+ remote-endpoint = <&dpu_intf3_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ hdmi_out: endpoint {
+ };
+ };
+ };
+ };
+
+ mdss_hdmi_phy: hdmi-phy@c9a0600 {
+ compatible = "qcom,hdmi-phy-8998";
+ reg = <0x0c9a0600 0x18b>,
+ <0x0c9a0a00 0x38>,
+ <0x0c9a0c00 0x38>,
+ <0x0c9a0e00 0x38>,
+ <0x0c9a1000 0x38>,
+ <0x0c9a1200 0x0e8>;
+ reg-names = "hdmi_pll",
+ "hdmi_tx_l0",
+ "hdmi_tx_l1",
+ "hdmi_tx_l2",
+ "hdmi_tx_l3",
+ "hdmi_phy";
+
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&gcc GCC_HDMI_CLKREF_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface",
+ "ref",
+ "xo";
+
+ status = "disabled";
+ };
};
venus: video-codec@cc00000 {
diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
index 79bc42ffb6a1..f0746123e594 100644
--- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
@@ -42,7 +42,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x0>;
@@ -50,18 +50,18 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x1>;
@@ -69,13 +69,13 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x2>;
@@ -83,13 +83,13 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x3>;
@@ -97,34 +97,34 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
};
domain-idle-states {
- CLUSTER_SLEEP: cluster-sleep-0 {
+ cluster_sleep: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000043>;
entry-latency-us = <800>;
@@ -136,7 +136,7 @@
idle-states {
entry-method = "psci";
- CPU_SLEEP: cpu-sleep-0 {
+ cpu_sleep: cpu-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -174,34 +174,34 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_SLEEP>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_sleep>;
};
- CLUSTER_PD: power-domain-cpu-cluster {
+ cluster_pd: power-domain-cpu-cluster {
#power-domain-cells = <0>;
power-domains = <&mpm>;
- domain-idle-states = <&CLUSTER_SLEEP>;
+ domain-idle-states = <&cluster_sleep>;
};
};
@@ -2067,7 +2067,7 @@
compatible = "qcom,qcm2290-lmh", "qcom,sm8150-lmh";
reg = <0x0 0x0f550800 0x0 0x400>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
- cpus = <&CPU0>;
+ cpus = <&cpu0>;
qcom,lmh-temp-arm-millicelsius = <65000>;
qcom,lmh-temp-low-millicelsius = <94500>;
qcom,lmh-temp-high-millicelsius = <95000>;
diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
index 8ab30c01712e..fdc62f1b1c5a 100644
--- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
+++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
@@ -207,6 +207,20 @@
};
};
+ mem-thermal {
+ polling-delay-passive = <0>;
+
+ thermal-sensors = <&pm7250b_adc_tm 2>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
pm8008-thermal {
polling-delay-passive = <100>;
thermal-sensors = <&pm8008>;
@@ -679,6 +693,9 @@
};
&pm7250b_adc {
+ pinctrl-0 = <&pm7250b_adc_default>;
+ pinctrl-names = "default";
+
channel@4d {
reg = <ADC5_AMUX_THM1_100K_PU>;
qcom,ratiometric;
@@ -694,6 +711,14 @@
qcom,pre-scaling = <1 1>;
label = "conn_therm";
};
+
+ channel@53 {
+ reg = <ADC5_GPIO2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "mem_therm";
+ };
};
&pm7250b_adc_tm {
@@ -712,6 +737,21 @@
qcom,ratiometric;
qcom,hw-settle-time-us = <200>;
};
+
+ mem-therm@2 {
+ reg = <2>;
+ io-channels = <&pm7250b_adc ADC5_GPIO2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pm7250b_gpios {
+ pm7250b_adc_default: adc-default-state {
+ pins = "gpio12";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ bias-high-impedance;
+ };
};
&pm7325_gpios {
diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
index 84c45419cb8d..c5fb153614e1 100644
--- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
+++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
@@ -499,6 +499,14 @@
};
};
+&gpu {
+ status = "okay";
+};
+
+&gpu_zap_shader {
+ firmware-name = "qcom/qcm6490/a660_zap.mbn";
+};
+
&mdss {
status = "okay";
};
@@ -694,6 +702,25 @@
status = "okay";
};
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 175 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vreg_l7b_2p952>;
+ vcc-max-microamp = <800000>;
+ vccq-supply = <&vreg_l9b_1p2>;
+ vccq-max-microamp = <900000>;
+ vccq2-supply = <&vreg_l9b_1p2>;
+ vccq2-max-microamp = <900000>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l10c_0p88>;
+ vdda-pll-supply = <&vreg_l6b_1p2>;
+
+ status = "okay";
+};
+
&usb_1 {
status = "okay";
};
@@ -720,4 +747,7 @@
&wifi {
memory-region = <&wlan_fw_mem>;
+ qcom,ath11k-calibration-variant = "Qualcomm_qcm6490idp";
+
+ status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
index cddc16bac0ce..215ba146207a 100644
--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
@@ -36,13 +36,13 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@100 {
+ cpu0: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x100>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
- next-level-cache = <&L2_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
clocks = <&apcs_glb>;
operating-points-v2 = <&cpu_opp_table>;
@@ -50,13 +50,13 @@
power-domain-names = "cpr";
};
- CPU1: cpu@101 {
+ cpu1: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x101>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
- next-level-cache = <&L2_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
clocks = <&apcs_glb>;
operating-points-v2 = <&cpu_opp_table>;
@@ -64,13 +64,13 @@
power-domain-names = "cpr";
};
- CPU2: cpu@102 {
+ cpu2: cpu@102 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x102>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
- next-level-cache = <&L2_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
clocks = <&apcs_glb>;
operating-points-v2 = <&cpu_opp_table>;
@@ -78,13 +78,13 @@
power-domain-names = "cpr";
};
- CPU3: cpu@103 {
+ cpu3: cpu@103 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x103>;
enable-method = "psci";
- cpu-idle-states = <&CPU_SLEEP_0>;
- next-level-cache = <&L2_0>;
+ cpu-idle-states = <&cpu_sleep_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
clocks = <&apcs_glb>;
operating-points-v2 = <&cpu_opp_table>;
@@ -92,7 +92,7 @@
power-domain-names = "cpr";
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -101,7 +101,7 @@
idle-states {
entry-method = "psci";
- CPU_SLEEP_0: cpu-sleep-0 {
+ cpu_sleep_0: cpu-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "standalone-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -1679,10 +1679,10 @@
cooling-maps {
map0 {
trip = <&cluster_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -1712,10 +1712,10 @@
cooling-maps {
map0 {
trip = <&cpu0_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -1745,10 +1745,10 @@
cooling-maps {
map0 {
trip = <&cpu1_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -1778,10 +1778,10 @@
cooling-maps {
map0 {
trip = <&cpu2_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -1811,10 +1811,10 @@
cooling-maps {
map0 {
trip = <&cpu3_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
index 0d45662b8028..27695bd54220 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
@@ -9,6 +9,7 @@
#define PM7250B_SID 8
#define PM7250B_SID1 9
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sc7280.dtsi"
#include "pm7250b.dtsi"
@@ -153,6 +154,20 @@
};
};
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&kypd_vol_up_n>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume Up";
+ gpios = <&pm7325_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ linux,can-disable;
+ };
+ };
+
pmic-glink {
compatible = "qcom,qcm6490-pmic-glink", "qcom,pmic-glink";
@@ -557,6 +572,14 @@
status = "okay";
};
+&gpu {
+ status = "okay";
+};
+
+&gpu_zap_shader {
+ firmware-name = "qcom/qcs6490/a660_zap.mbn";
+};
+
&i2c0 {
clock-frequency = <400000>;
status = "okay";
@@ -598,6 +621,7 @@
};
&i2c1 {
+ clock-frequency = <100000>;
status = "okay";
typec-mux@1c {
@@ -684,10 +708,56 @@
status = "okay";
};
+&pcie1 {
+ perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&pcie1_reset_n>, <&pcie1_wake_n>;
+ pinctrl-names = "default";
+
+ iommu-map = <0x0 &apps_smmu 0x1c80 0x1>,
+ <0x100 &apps_smmu 0x1c81 0x1>,
+ <0x208 &apps_smmu 0x1c84 0x1>,
+ <0x210 &apps_smmu 0x1c85 0x1>,
+ <0x218 &apps_smmu 0x1c86 0x1>,
+ <0x300 &apps_smmu 0x1c87 0x1>,
+ <0x400 &apps_smmu 0x1c88 0x1>,
+ <0x500 &apps_smmu 0x1c89 0x1>,
+ <0x501 &apps_smmu 0x1c90 0x1>;
+
+ status = "okay";
+};
+
+&pcie1_phy {
+ vdda-phy-supply = <&vreg_l10c_0p88>;
+ vdda-pll-supply = <&vreg_l6b_1p2>;
+
+ status = "okay";
+};
+
+&pm7325_gpios {
+ kypd_vol_up_n: kypd-vol-up-n-state {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ power-source = <1>;
+ bias-pull-up;
+ input-enable;
+ };
+};
+
&pmk8350_rtc {
status = "okay";
};
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+
+ status = "okay";
+};
+
&qupv3_id_0 {
status = "okay";
};
@@ -707,7 +777,7 @@
};
&remoteproc_mpss {
- firmware-name = "qcom/qcs6490/modem.mdt";
+ firmware-name = "qcom/qcs6490/modem.mbn";
status = "okay";
};
@@ -716,6 +786,18 @@
status = "okay";
};
+&sdhc_2 {
+ pinctrl-0 = <&sdc2_clk>, <&sdc2_cmd>, <&sdc2_data>, <&sd_cd>;
+ pinctrl-1 = <&sdc2_clk_sleep>, <&sdc2_cmd_sleep>, <&sdc2_data_sleep>, <&sd_cd>;
+
+ vmmc-supply = <&vreg_l9c_2p96>;
+ vqmmc-supply = <&vreg_l6c_2p96>;
+
+ cd-gpios = <&tlmm 91 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+};
+
&tlmm {
gpio-reserved-ranges = <32 2>, /* ADSP */
<48 4>; /* NFC */
@@ -790,8 +872,15 @@
status = "okay";
};
+&venus {
+ status = "okay";
+};
+
&wifi {
memory-region = <&wlan_fw_mem>;
+ qcom,ath11k-calibration-variant = "Qualcomm_rb3gen2";
+
+ status = "okay";
};
/* PINCTRL - ADDITIONS TO NODES IN PARENT DEVICE TREE FILES */
@@ -812,6 +901,21 @@
};
};
+&sdc2_clk {
+ bias-disable;
+ drive-strength = <16>;
+};
+
+&sdc2_cmd {
+ bias-pull-up;
+ drive-strength = <10>;
+};
+
+&sdc2_data {
+ bias-pull-up;
+ drive-strength = <10>;
+};
+
&tlmm {
lt9611_irq_pin: lt9611-irq-state {
pins = "gpio24";
@@ -819,4 +923,25 @@
drive-strength = <2>;
bias-disable;
};
+
+ pcie1_reset_n: pcie1-reset-n-state {
+ pins = "gpio2";
+ function = "gpio";
+ drive-strength = <16>;
+ output-low;
+ bias-disable;
+ };
+
+ pcie1_wake_n: pcie1-wake-n-state {
+ pins = "gpio3";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ sd_cd: sd-cd-state {
+ pins = "gpio91";
+ function = "gpio";
+ bias-pull-up;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/qcs8550.dtsi b/arch/arm64/boot/dts/qcom/qcs8550.dtsi
index 07b314834d88..f0acdd0b1e93 100644
--- a/arch/arm64/boot/dts/qcom/qcs8550.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs8550.dtsi
@@ -154,7 +154,7 @@
no-map;
};
- mpss_dsm_mem: mpss_dsm_region@d4d00000 {
+ mpss_dsm_mem: mpss-dsm-region@d4d00000 {
reg = <0x0 0xd4d00000 0x0 0x3300000>;
no-map;
};
diff --git a/arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts b/arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts
new file mode 100644
index 000000000000..759d1ec694b2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+#include "sa8775p-ride-r3.dts"
+/ {
+ model = "Qualcomm QCS9100 Ride Rev3";
+ compatible = "qcom,qcs9100-ride-r3", "qcom,qcs9100", "qcom,sa8775p";
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs9100-ride.dts b/arch/arm64/boot/dts/qcom/qcs9100-ride.dts
new file mode 100644
index 000000000000..979462dfec30
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs9100-ride.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+#include "sa8775p-ride.dts"
+/ {
+ model = "Qualcomm QCS9100 Ride";
+ compatible = "qcom,qcs9100-ride", "qcom,qcs9100", "qcom,sa8775p";
+};
diff --git a/arch/arm64/boot/dts/qcom/qdu1000.dtsi b/arch/arm64/boot/dts/qcom/qdu1000.dtsi
index 642ca8f0236b..47c0dd31aaf2 100644
--- a/arch/arm64/boot/dts/qcom/qdu1000.dtsi
+++ b/arch/arm64/boot/dts/qcom/qdu1000.dtsi
@@ -25,22 +25,22 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domains = <&cpufreq_hw 0>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -48,76 +48,76 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
qcom,freq-domains = <&cpufreq_hw 0>;
- next-level-cache = <&L2_100>;
- L2_100: l2-cache {
+ next-level-cache = <&l2_100>;
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
qcom,freq-domains = <&cpufreq_hw 0>;
- next-level-cache = <&L2_200>;
- L2_200: l2-cache {
+ next-level-cache = <&l2_200>;
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
qcom,freq-domains = <&cpufreq_hw 0>;
- next-level-cache = <&L2_300>;
- L2_300: l2-cache {
+ next-level-cache = <&l2_300>;
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
};
@@ -126,7 +126,7 @@
idle-states {
entry-method = "psci";
- CPU_OFF: cpu-sleep-0 {
+ cpu_off: cpu-sleep-0 {
compatible = "arm,idle-state";
entry-latency-us = <274>;
exit-latency-us = <480>;
@@ -137,7 +137,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
entry-latency-us = <584>;
exit-latency-us = <2332>;
@@ -145,7 +145,7 @@
arm,psci-suspend-param = <0x41000044>;
};
- CLUSTER_SLEEP_1: cluster-sleep-1 {
+ cluster_sleep_1: cluster-sleep-1 {
compatible = "domain-idle-state";
entry-latency-us = <2893>;
exit-latency-us = <4023>;
@@ -187,33 +187,33 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off>;
};
- CLUSTER_PD: power-domain-cluster {
+ cluster_pd: power-domain-cluster {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_1>;
+ domain-idle-states = <&cluster_sleep_0 &cluster_sleep_1>;
};
};
@@ -921,7 +921,7 @@
reg = <0x0 0x088e3000 0x0 0x120>;
#phy-cells = <0>;
- clocks =<&gcc GCC_USB2_CLKREF_EN>;
+ clocks = <&gcc GCC_USB2_CLKREF_EN>;
clock-names = "ref";
resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
@@ -1412,6 +1412,7 @@
<GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
intc: interrupt-controller@17200000 {
@@ -1498,7 +1499,7 @@
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 0>;
label = "apps_rsc";
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
index e19790464a11..7a789b41c2f1 100644
--- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
@@ -24,7 +24,7 @@
};
clocks {
- clk40M: can-clk {
+ clk40m: can-clk {
compatible = "fixed-clock";
clock-frequency = <40000000>;
#clock-cells = <0>;
@@ -188,23 +188,23 @@
};
};
-&CPU_PD0 {
+&cpu_pd0 {
/delete-property/ power-domains;
};
-&CPU_PD1 {
+&cpu_pd1 {
/delete-property/ power-domains;
};
-&CPU_PD2 {
+&cpu_pd2 {
/delete-property/ power-domains;
};
-&CPU_PD3 {
+&cpu_pd3 {
/delete-property/ power-domains;
};
-/delete-node/ &CLUSTER_PD;
+/delete-node/ &cluster_pd;
&gpi_dma0 {
status = "okay";
@@ -541,7 +541,7 @@
compatible = "microchip,mcp2518fd";
reg = <0>;
interrupts-extended = <&tlmm 39 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&clk40M>;
+ clocks = <&clk40m>;
spi-max-frequency = <10000000>;
vdd-supply = <&vdc_5v>;
xceiver-supply = <&vdc_5v>;
diff --git a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
index 1888d99d398b..a9540e92d3e6 100644
--- a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
+++ b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
@@ -25,7 +25,7 @@
};
clocks {
- clk40M: can-clk {
+ clk40m: can-clk {
compatible = "fixed-clock";
clock-frequency = <40000000>;
#clock-cells = <0>;
@@ -537,7 +537,7 @@
compatible = "microchip,mcp2518fd";
reg = <0>;
interrupts-extended = <&tlmm 39 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&clk40M>;
+ clocks = <&clk40m>;
spi-max-frequency = <10000000>;
vdd-supply = <&vdc_5v>;
xceiver-supply = <&vdc_5v>;
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dtso
index edc0e42ee017..ae256c713a36 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dtso
@@ -4,8 +4,21 @@
*/
/dts-v1/;
+/plugin/;
-#include "qrb5165-rb5.dts"
+#include <dt-bindings/clock/qcom,camcc-sm8250.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ reserved-memory {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x8000000>;
+ reusable;
+ linux,cma-default;
+ };
+ };
+};
&camcc {
status = "okay";
@@ -33,6 +46,9 @@
};
&cci1_i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
camera@1a {
compatible = "sony,imx577";
reg = <0x1a>;
@@ -52,7 +68,6 @@
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 ccff6cd73fdf..52eef88e882c 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -32,7 +32,7 @@
};
/* Fixed crystal oscillator dedicated to MCP2518FD */
- clk40M: can-clock {
+ clk40m: can-clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <40000000>;
@@ -1118,7 +1118,7 @@
can@0 {
compatible = "microchip,mcp2518fd";
reg = <0>;
- clocks = <&clk40M>;
+ clocks = <&clk40m>;
interrupts-extended = <&tlmm 15 IRQ_TYPE_LEVEL_LOW>;
spi-max-frequency = <10000000>;
vdd-supply = <&vdc_5v>;
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
index 0c1b21def4b6..3fc62e123689 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
@@ -27,6 +27,83 @@
chosen {
stdout-path = "serial0:115200n8";
};
+
+ vreg_conn_1p8: vreg_conn_1p8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_conn_1p8";
+ startup-delay-us = <4000>;
+ enable-active-high;
+ gpio = <&pmm8654au_1_gpios 4 GPIO_ACTIVE_HIGH>;
+ };
+
+ vreg_conn_pa: vreg_conn_pa {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_conn_pa";
+ startup-delay-us = <4000>;
+ enable-active-high;
+ gpio = <&pmm8654au_1_gpios 6 GPIO_ACTIVE_HIGH>;
+ };
+
+ wcn6855-pmu {
+ compatible = "qcom,wcn6855-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_en_state>, <&wlan_en_state>;
+
+ vddio-supply = <&vreg_conn_pa>;
+ vddaon-supply = <&vreg_l2c>;
+ vddpmu-supply = <&vreg_conn_1p8>;
+ vddrfa0p95-supply = <&vreg_l2c>;
+ vddrfa1p3-supply = <&vreg_l6e>;
+ vddrfa1p9-supply = <&vreg_s5a>;
+ vddpcie1p3-supply = <&vreg_l6e>;
+ vddpcie1p9-supply = <&vreg_s5a>;
+
+ bt-enable-gpios = <&pmm8654au_1_gpios 8 GPIO_ACTIVE_HIGH>;
+ wlan-enable-gpios = <&pmm8654au_1_gpios 7 GPIO_ACTIVE_HIGH>;
+
+ regulators {
+ vreg_pmu_rfa_cmn: ldo0 {
+ regulator-name = "vreg_pmu_rfa_cmn";
+ };
+
+ vreg_pmu_aon_0p59: ldo1 {
+ regulator-name = "vreg_pmu_aon_0p59";
+ };
+
+ vreg_pmu_wlcx_0p8: ldo2 {
+ regulator-name = "vreg_pmu_wlcx_0p8";
+ };
+
+ vreg_pmu_wlmx_0p85: ldo3 {
+ regulator-name = "vreg_pmu_wlmx_0p85";
+ };
+
+ vreg_pmu_btcmx_0p85: ldo4 {
+ regulator-name = "vreg_pmu_btcmx_0p85";
+ };
+
+ vreg_pmu_rfa_0p8: ldo5 {
+ regulator-name = "vreg_pmu_rfa_0p8";
+ };
+
+ vreg_pmu_rfa_1p2: ldo6 {
+ regulator-name = "vreg_pmu_rfa_1p2";
+ };
+
+ vreg_pmu_rfa_1p7: ldo7 {
+ regulator-name = "vreg_pmu_rfa_1p7";
+ };
+
+ vreg_pmu_pcie_0p9: ldo8 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_pcie_1p8: ldo9 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+ };
+ };
};
&apps_rsc {
@@ -453,6 +530,20 @@
"USB2_PWR_EN",
"USB2_FAULT";
+ wlan_en_state: wlan-en-state {
+ pins = "gpio7";
+ function = "normal";
+ output-low;
+ bias-pull-down;
+ };
+
+ bt_en_state: bt-en-state {
+ pins = "gpio8";
+ function = "normal";
+ output-low;
+ bias-pull-down;
+ };
+
usb2_en_state: usb2-en-state {
pins = "gpio9";
function = "normal";
@@ -702,6 +793,25 @@
status = "okay";
};
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1101";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ qcom,ath11k-calibration-variant = "QC_SA8775P_Ride";
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+ vddaon-supply = <&vreg_pmu_aon_0p59>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ };
+};
+
&remoteproc_adsp {
firmware-name = "qcom/sa8775p/adsp.mbn";
status = "okay";
@@ -744,6 +854,17 @@
pinctrl-0 = <&qup_uart17_default>;
pinctrl-names = "default";
status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn6855-bt";
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+ vddaon-supply = <&vreg_pmu_aon_0p59>;
+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
+ };
};
&ufs_mem_hc {
diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index e8dbc8d820a6..9f315a51a7c1 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2023, Linaro Limited
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <dt-bindings/interconnect/qcom,icc.h>
@@ -8,6 +9,7 @@
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/clock/qcom,sa8775p-gcc.h>
#include <dt-bindings/clock/qcom,sa8775p-gpucc.h>
+#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
#include <dt-bindings/firmware/qcom,scm.h>
@@ -37,21 +39,21 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x0>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -59,72 +61,72 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x100>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_1: l2-cache {
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x200>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
- next-level-cache = <&L2_2>;
+ next-level-cache = <&l2_2>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_2: l2-cache {
+ l2_2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x300>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
- next-level-cache = <&L2_3>;
+ next-level-cache = <&l2_3>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_3: l2-cache {
+ l2_3: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@10000 {
+ cpu4: cpu@10000 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x10000>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
- next-level-cache = <&L2_4>;
+ next-level-cache = <&l2_4>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_4: l2-cache {
+ l2_4: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_1>;
- L3_1: l3-cache {
+ next-level-cache = <&l3_1>;
+ l3_1: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -133,91 +135,91 @@
};
};
- CPU5: cpu@10100 {
+ cpu5: cpu@10100 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x10100>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
- next-level-cache = <&L2_5>;
+ next-level-cache = <&l2_5>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_5: l2-cache {
+ l2_5: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_1>;
+ next-level-cache = <&l3_1>;
};
};
- CPU6: cpu@10200 {
+ cpu6: cpu@10200 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x10200>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
- next-level-cache = <&L2_6>;
+ next-level-cache = <&l2_6>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_6: l2-cache {
+ l2_6: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_1>;
+ next-level-cache = <&l3_1>;
};
};
- CPU7: cpu@10300 {
+ cpu7: cpu@10300 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x10300>;
enable-method = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
- next-level-cache = <&L2_7>;
+ next-level-cache = <&l2_7>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- L2_7: l2-cache {
+ l2_7: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_1>;
+ next-level-cache = <&l3_1>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -225,7 +227,7 @@
idle-states {
entry-method = "psci";
- GOLD_CPU_SLEEP_0: cpu-sleep-0 {
+ gold_cpu_sleep_0: cpu-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -235,7 +237,7 @@
local-timer-stop;
};
- GOLD_RAIL_CPU_SLEEP_0: cpu-sleep-1 {
+ gold_rail_cpu_sleep_0: cpu-sleep-1 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -247,7 +249,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_GOLD: cluster-sleep-0 {
+ cluster_sleep_gold: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <2752>;
@@ -255,7 +257,7 @@
min-residency-us = <6118>;
};
- CLUSTER_SLEEP_APSS_RSC_PC: cluster-sleep-1 {
+ cluster_sleep_apss_rsc_pc: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x42000144>;
entry-latency-us = <3263>;
@@ -281,6 +283,7 @@
firmware {
scm {
compatible = "qcom,scm-sa8775p", "qcom,scm";
+ qcom,dload-mode = <&tcsr 0x13000>;
memory-region = <&tz_ffi_mem>;
};
};
@@ -393,77 +396,77 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>,
- <&GOLD_RAIL_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>,
+ <&gold_rail_cpu_sleep_0>;
};
- CLUSTER_0_PD: power-domain-cluster0 {
+ cluster_0_pd: power-domain-cluster0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_2_PD>;
- domain-idle-states = <&CLUSTER_SLEEP_GOLD>;
+ power-domains = <&cluster_2_pd>;
+ domain-idle-states = <&cluster_sleep_gold>;
};
- CLUSTER_1_PD: power-domain-cluster1 {
+ cluster_1_pd: power-domain-cluster1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_2_PD>;
- domain-idle-states = <&CLUSTER_SLEEP_GOLD>;
+ power-domains = <&cluster_2_pd>;
+ domain-idle-states = <&cluster_sleep_gold>;
};
- CLUSTER_2_PD: power-domain-cluster2 {
+ cluster_2_pd: power-domain-cluster2 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_APSS_RSC_PC>;
+ domain-idle-states = <&cluster_sleep_apss_rsc_pc>;
};
};
@@ -851,6 +854,28 @@
#mbox-cells = <2>;
};
+ gpi_dma2: qcom,gpi-dma@800000 {
+ compatible = "qcom,sm6350-gpi-dma";
+ reg = <0x0 0x00800000 0x0 0x60000>;
+ #dma-cells = <3>;
+ interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 590 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 591 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 593 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 594 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 595 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 596 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 597 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 598 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 599 IRQ_TYPE_LEVEL_HIGH>;
+ dma-channels = <12>;
+ dma-channel-mask = <0xfff>;
+ iommus = <&apps_smmu 0x5b6 0x0>;
+ status = "disabled";
+ };
+
qupv3_id_2: geniqup@8c0000 {
compatible = "qcom,geni-se-qup";
reg = <0x0 0x008c0000 0x0 0x6000>;
@@ -881,6 +906,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -902,6 +931,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart14: serial@880000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00880000 0x0 0x4000>;
+ interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -923,6 +971,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -944,6 +996,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart15: serial@884000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00884000 0x0 0x4000>;
+ interrupts = <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -965,6 +1036,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -984,11 +1059,30 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
+ uart16: serial@888000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00888000 0x0 0x4000>;
+ interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
+ status = "disabled";
+ };
+
i2c17: i2c@88c000 {
compatible = "qcom,geni-i2c";
reg = <0x0 0x88c000 0x0 0x4000>;
@@ -1007,6 +1101,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1028,6 +1126,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1062,6 +1164,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1085,6 +1191,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart18: serial@890000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00890000 0x0 0x4000>;
+ interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -1106,6 +1231,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1127,6 +1256,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 5 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 5 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart19: serial@894000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00894000 0x0 0x4000>;
+ interrupts = <GIC_SPI 587 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -1148,6 +1296,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 6 QCOM_GPI_I2C>,
+ <&gpi_dma2 1 6 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1169,8 +1321,50 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma2 0 6 QCOM_GPI_SPI>,
+ <&gpi_dma2 1 6 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
+
+ uart20: serial@898000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00898000 0x0 0x4000>;
+ interrupts = <GIC_SPI 834 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP2_S6_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
+ status = "disabled";
+ };
+
+ };
+
+ gpi_dma0: qcom,gpi-dma@900000 {
+ compatible = "qcom,sm6350-gpi-dma";
+ reg = <0x0 0x00900000 0x0 0x60000>;
+ #dma-cells = <3>;
+ 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>;
+ dma-channels = <12>;
+ dma-channel-mask = <0xfff>;
+ iommus = <&apps_smmu 0x416 0x0>;
+ status = "disabled";
};
qupv3_id_0: geniqup@9c0000 {
@@ -1203,6 +1397,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1224,6 +1422,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart0: serial@980000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x980000 0x0 0x4000>;
+ interrupts = <GIC_SPI 550 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -1245,6 +1462,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1266,6 +1487,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart1: serial@984000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x984000 0x0 0x4000>;
+ interrupts = <GIC_SPI 551 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -1287,6 +1527,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1308,6 +1552,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart2: serial@988000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x988000 0x0 0x4000>;
+ interrupts = <GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -1329,6 +1592,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1350,6 +1617,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart3: serial@98c000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x98c000 0x0 0x4000>;
+ interrupts = <GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -1371,6 +1657,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1392,6 +1682,25 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart4: serial@990000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x990000 0x0 0x4000>;
+ interrupts = <GIC_SPI 531 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+ clock-names = "se";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "qup-core", "qup-config";
+ power-domains = <&rpmhpd SA8775P_CX>;
status = "disabled";
};
@@ -1413,6 +1722,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1434,6 +1747,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 5 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1453,6 +1770,28 @@
};
};
+ gpi_dma1: qcom,gpi-dma@a00000 {
+ compatible = "qcom,sm6350-gpi-dma";
+ reg = <0x0 0x00a00000 0x0 0x60000>;
+ #dma-cells = <3>;
+ 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>;
+ iommus = <&apps_smmu 0x456 0x0>;
+ dma-channels = <12>;
+ dma-channel-mask = <0xfff>;
+ status = "disabled";
+ };
+
qupv3_id_1: geniqup@ac0000 {
compatible = "qcom,geni-se-qup";
reg = <0x0 0x00ac0000 0x0 0x6000>;
@@ -1483,6 +1822,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1504,6 +1847,26 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart7: serial@a80000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00a80000 0x0 0x4000>;
+ interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
+ interconnect-names = "qup-core", "qup-config";
+ interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>;
+ power-domains = <&rpmhpd SA8775P_CX>;
+ operating-points-v2 = <&qup_opp_table_100mhz>;
status = "disabled";
};
@@ -1525,6 +1888,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1546,6 +1913,26 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart8: serial@a84000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00a84000 0x0 0x4000>;
+ interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+ interconnect-names = "qup-core", "qup-config";
+ interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>;
+ power-domains = <&rpmhpd SA8775P_CX>;
+ operating-points-v2 = <&qup_opp_table_100mhz>;
status = "disabled";
};
@@ -1567,6 +1954,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1588,6 +1979,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1624,6 +2019,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1645,6 +2044,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1682,6 +2085,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1703,6 +2110,26 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart11: serial@a90000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00a90000 0x0 0x4000>;
+ interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
+ interconnect-names = "qup-core", "qup-config";
+ interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>;
+ power-domains = <&rpmhpd SA8775P_CX>;
+ operating-points-v2 = <&qup_opp_table_100mhz>;
status = "disabled";
};
@@ -1724,6 +2151,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1745,6 +2176,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 5 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 5 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1781,10 +2216,29 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma1 0 6 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 6 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
+
};
};
+ gpi_dma3: qcom,gpi-dma@b00000 {
+ compatible = "qcom,sm6350-gpi-dma";
+ reg = <0x0 0x00b00000 0x0 0x58000>;
+ #dma-cells = <3>;
+ interrupts = <GIC_SPI 368 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 527 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 528 IRQ_TYPE_LEVEL_HIGH>;
+ iommus = <&apps_smmu 0x056 0x0>;
+ dma-channels = <4>;
+ dma-channel-mask = <0xf>;
+ status = "disabled";
+ };
+
qupv3_id_3: geniqup@bc0000 {
compatible = "qcom,geni-se-qup";
reg = <0x0 0xbc0000 0x0 0x6000>;
@@ -1815,6 +2269,10 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma3 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma3 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx",
+ "rx";
status = "disabled";
};
@@ -1836,6 +2294,26 @@
"qup-config",
"qup-memory";
power-domains = <&rpmhpd SA8775P_CX>;
+ dmas = <&gpi_dma3 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma3 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx",
+ "rx";
+ status = "disabled";
+ };
+
+ uart21: serial@b80000 {
+ compatible = "qcom,geni-uart";
+ reg = <0x0 0x00b80000 0x0 0x4000>;
+ interrupts = <GIC_SPI 831 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP3_S0_CLK>;
+ interconnect-names = "qup-core", "qup-config";
+ interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS
+ &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>,
+ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ALWAYS>;
+ power-domains = <&rpmhpd SA8775P_CX>;
+ operating-points-v2 = <&qup_opp_table_100mhz>;
status = "disabled";
};
};
@@ -1845,7 +2323,7 @@
reg = <0 0x010d2000 0 0x1000>;
};
- ufs_mem_hc: ufs@1d84000 {
+ ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sa8775p-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
reg = <0x0 0x01d84000 0x0 0x3000>;
interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
@@ -1908,10 +2386,32 @@
ice: crypto@1d88000 {
compatible = "qcom,sa8775p-inline-crypto-engine",
"qcom,inline-crypto-engine";
- reg = <0x0 0x01d88000 0x0 0x8000>;
+ reg = <0x0 0x01d88000 0x0 0x18000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
};
+ cryptobam: dma-controller@1dc4000 {
+ compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0";
+ reg = <0x0 0x01dc4000 0x0 0x28000>;
+ interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ qcom,controlled-remotely;
+ iommus = <&apps_smmu 0x480 0x00>,
+ <&apps_smmu 0x481 0x00>;
+ };
+
+ crypto: crypto@1dfa000 {
+ compatible = "qcom,sa8775p-qce", "qcom,qce";
+ reg = <0x0 0x01dfa000 0x0 0x6000>;
+ dmas = <&cryptobam 4>, <&cryptobam 5>;
+ dma-names = "rx", "tx";
+ iommus = <&apps_smmu 0x480 0x00>,
+ <&apps_smmu 0x481 0x00>;
+ interconnects = <&aggre2_noc MASTER_CRYPTO_CORE0 0 &mc_virt SLAVE_EBI1 0>;
+ interconnect-names = "memory";
+ };
+
stm: stm@4002000 {
compatible = "arm,coresight-stm", "arm,primecell";
reg = <0x0 0x4002000 0x0 0x1000>,
@@ -2382,7 +2882,7 @@
etm@6040000 {
compatible = "arm,primecell";
reg = <0x0 0x6040000 0x0 0x1000>;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2402,7 +2902,7 @@
etm@6140000 {
compatible = "arm,primecell";
reg = <0x0 0x6140000 0x0 0x1000>;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2422,7 +2922,7 @@
etm@6240000 {
compatible = "arm,primecell";
reg = <0x0 0x6240000 0x0 0x1000>;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2442,7 +2942,7 @@
etm@6340000 {
compatible = "arm,primecell";
reg = <0x0 0x6340000 0x0 0x1000>;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2462,7 +2962,7 @@
etm@6440000 {
compatible = "arm,primecell";
reg = <0x0 0x6440000 0x0 0x1000>;
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2482,7 +2982,7 @@
etm@6540000 {
compatible = "arm,primecell";
reg = <0x0 0x6540000 0x0 0x1000>;
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2502,7 +3002,7 @@
etm@6640000 {
compatible = "arm,primecell";
reg = <0x0 0x6640000 0x0 0x1000>;
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2522,7 +3022,7 @@
etm@6740000 {
compatible = "arm,primecell";
reg = <0x0 0x6740000 0x0 0x1000>;
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3072,6 +3572,11 @@
#hwlock-cells = <1>;
};
+ tcsr: syscon@1fc0000 {
+ compatible = "qcom,sa8775p-tcsr", "syscon";
+ reg = <0x0 0x1fc0000 0x0 0x30000>;
+ };
+
gpucc: clock-controller@3d90000 {
compatible = "qcom,sa8775p-gpucc";
reg = <0x0 0x03d90000 0x0 0xa000>;
@@ -5570,7 +6075,7 @@
status = "disabled";
- pcie@0 {
+ pcieport0: pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
bus-range = <0x01 0xff>;
@@ -5624,6 +6129,7 @@
phy-names = "pciephy";
max-link-speed = <3>; /* FIXME: Limiting the Gen speed due to stability issues */
num-lanes = <2>;
+ linux,pci-domain = <0>;
status = "disabled";
};
@@ -5781,6 +6287,7 @@
phy-names = "pciephy";
max-link-speed = <3>; /* FIXME: Limiting the Gen speed due to stability issues */
num-lanes = <4>;
+ linux,pci-domain = <1>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-firmware-tfa.dtsi b/arch/arm64/boot/dts/qcom/sc7180-firmware-tfa.dtsi
index ee35a454dbf6..59162b3afcb8 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-firmware-tfa.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-firmware-tfa.dtsi
@@ -6,82 +6,82 @@
* by Qualcomm firmware.
*/
-&CPU0 {
+&cpu0 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU1 {
+&cpu1 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU2 {
+&cpu2 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU3 {
+&cpu3 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU4 {
+&cpu4 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU5 {
+&cpu5 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU6 {
+&cpu6 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&big_cpu_sleep_0
+ &big_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU7 {
+&cpu7 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&big_cpu_sleep_0
+ &big_cpu_sleep_1
+ &cluster_sleep_0>;
};
/delete-node/ &domain_idle_states;
&idle_states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "cluster-power-down";
arm,psci-suspend-param = <0x40003444>;
@@ -92,15 +92,15 @@
};
};
-/delete-node/ &CPU_PD0;
-/delete-node/ &CPU_PD1;
-/delete-node/ &CPU_PD2;
-/delete-node/ &CPU_PD3;
-/delete-node/ &CPU_PD4;
-/delete-node/ &CPU_PD5;
-/delete-node/ &CPU_PD6;
-/delete-node/ &CPU_PD7;
-/delete-node/ &CLUSTER_PD;
+/delete-node/ &cpu_pd0;
+/delete-node/ &cpu_pd1;
+/delete-node/ &cpu_pd2;
+/delete-node/ &cpu_pd3;
+/delete-node/ &cpu_pd4;
+/delete-node/ &cpu_pd5;
+/delete-node/ &cpu_pd6;
+/delete-node/ &cpu_pd7;
+/delete-node/ &cluster_pd;
&apps_rsc {
/delete-property/ power-domains;
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
index 3c124bbe2f4c..25b17b0425f2 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
@@ -53,14 +53,14 @@
cooling-maps {
map0 {
trip = <&skin_temp_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&skin_temp_alert1>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
index b2df22faafe8..f57976906d63 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
@@ -71,14 +71,14 @@
cooling-maps {
map0 {
trip = <&skin_temp_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&skin_temp_alert1>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
index af89d80426ab..d4925be3b1fc 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
@@ -78,14 +78,14 @@
cooling-maps {
map0 {
trip = <&skin_temp_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&skin_temp_alert1>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index b5ebf8980325..76fe314d2ad5 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -77,28 +77,28 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
capacity-dmips-mhz = <415>;
dynamic-power-coefficient = <137>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 0>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -106,206 +106,206 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
capacity-dmips-mhz = <415>;
dynamic-power-coefficient = <137>;
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 0>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
capacity-dmips-mhz = <415>;
dynamic-power-coefficient = <137>;
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 0>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
capacity-dmips-mhz = <415>;
dynamic-power-coefficient = <137>;
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 0>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x400>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
capacity-dmips-mhz = <415>;
dynamic-power-coefficient = <137>;
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 0>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x500>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
capacity-dmips-mhz = <415>;
dynamic-power-coefficient = <137>;
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 0>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x600>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <480>;
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 1>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo468";
reg = <0x0 0x700>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <480>;
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
qcom,freq-domain = <&cpufreq_hw 1>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -313,7 +313,7 @@
idle_states: idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-power-down";
arm,psci-suspend-param = <0x40000003>;
@@ -323,7 +323,7 @@
local-timer-stop;
};
- LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
+ little_cpu_sleep_1: cpu-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-down";
arm,psci-suspend-param = <0x40000004>;
@@ -333,7 +333,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-power-down";
arm,psci-suspend-param = <0x40000003>;
@@ -343,7 +343,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
+ big_cpu_sleep_1: cpu-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-down";
arm,psci-suspend-param = <0x40000004>;
@@ -355,27 +355,24 @@
};
domain_idle_states: domain-idle-states {
- CLUSTER_SLEEP_PC: cluster-sleep-0 {
+ cluster_sleep_pc: cluster-sleep-0 {
compatible = "domain-idle-state";
- idle-state-name = "cluster-l3-power-collapse";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <2752>;
exit-latency-us = <3048>;
min-residency-us = <6118>;
};
- CLUSTER_SLEEP_CX_RET: cluster-sleep-1 {
+ cluster_sleep_cx_ret: cluster-sleep-1 {
compatible = "domain-idle-state";
- idle-state-name = "cluster-cx-retention";
arm,psci-suspend-param = <0x41001244>;
entry-latency-us = <3638>;
exit-latency-us = <4562>;
min-residency-us = <8467>;
};
- CLUSTER_AOSS_SLEEP: cluster-sleep-2 {
+ cluster_aoss_sleep: cluster-sleep-2 {
compatible = "domain-idle-state";
- idle-state-name = "cluster-power-down";
arm,psci-suspend-param = <0x4100b244>;
entry-latency-us = <3263>;
exit-latency-us = <6562>;
@@ -583,59 +580,59 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: cpu0 {
+ cpu_pd0: cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD1: cpu1 {
+ cpu_pd1: cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD2: cpu2 {
+ cpu_pd2: cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD3: cpu3 {
+ cpu_pd3: cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD4: cpu4 {
+ cpu_pd4: cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD5: cpu5 {
+ cpu_pd5: cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD6: cpu6 {
+ cpu_pd6: cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CPU_PD7: cpu7 {
+ cpu_pd7: cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CLUSTER_PD: cpu-cluster0 {
+ cluster_pd: cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_PC
- &CLUSTER_SLEEP_CX_RET
- &CLUSTER_AOSS_SLEEP>;
+ domain-idle-states = <&cluster_sleep_pc
+ &cluster_sleep_cx_ret
+ &cluster_aoss_sleep>;
};
};
@@ -2546,7 +2543,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07040000 0 0x1000>;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2566,7 +2563,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07140000 0 0x1000>;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2586,7 +2583,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07240000 0 0x1000>;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2606,7 +2603,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07340000 0 0x1000>;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2626,7 +2623,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07440000 0 0x1000>;
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2646,7 +2643,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07540000 0 0x1000>;
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2666,7 +2663,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07640000 0 0x1000>;
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -2686,7 +2683,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07740000 0 0x1000>;
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3625,6 +3622,7 @@
<GIC_SPI 410 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 411 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 412 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
intc: interrupt-controller@17a00000 {
@@ -3734,7 +3732,7 @@
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
rpmhcc: clock-controller {
compatible = "qcom,sc7180-rpmh-clk";
@@ -4063,21 +4061,21 @@
cooling-maps {
map0 {
trip = <&cpu0_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu0_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4111,21 +4109,21 @@
cooling-maps {
map0 {
trip = <&cpu1_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu1_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4159,21 +4157,21 @@
cooling-maps {
map0 {
trip = <&cpu2_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu2_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4207,21 +4205,21 @@
cooling-maps {
map0 {
trip = <&cpu3_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu3_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4255,21 +4253,21 @@
cooling-maps {
map0 {
trip = <&cpu4_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu4_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4303,21 +4301,21 @@
cooling-maps {
map0 {
trip = <&cpu5_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu5_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4351,13 +4349,13 @@
cooling-maps {
map0 {
trip = <&cpu6_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu6_alert1>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4391,13 +4389,13 @@
cooling-maps {
map0 {
trip = <&cpu7_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu7_alert1>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4431,13 +4429,13 @@
cooling-maps {
map0 {
trip = <&cpu8_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu8_alert1>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4471,13 +4469,13 @@
cooling-maps {
map0 {
trip = <&cpu9_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu9_alert1>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
index cecb3e89f7f7..8b4239f13748 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
@@ -29,7 +29,7 @@
/ {
cpus {
domain_idle_states: domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x40003444>;
entry-latency-us = <2752>;
@@ -52,8 +52,12 @@
};
};
-&CLUSTER_PD {
- domain-idle-states = <&CLUSTER_SLEEP_0>;
+&cluster_pd {
+ domain-idle-states = <&cluster_sleep_0>;
+};
+
+&gpu {
+ status = "okay";
};
&lpass_aon {
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index 3d8410683402..55db1c83ef55 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -193,15 +193,15 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
operating-points-v2 = <&cpu0_opp_table>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
@@ -209,12 +209,12 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -222,15 +222,15 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
operating-points-v2 = <&cpu0_opp_table>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
@@ -238,23 +238,23 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
operating-points-v2 = <&cpu0_opp_table>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
@@ -262,23 +262,23 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
operating-points-v2 = <&cpu0_opp_table>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
@@ -286,23 +286,23 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x400>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
operating-points-v2 = <&cpu4_opp_table>;
capacity-dmips-mhz = <1946>;
dynamic-power-coefficient = <520>;
@@ -310,23 +310,23 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x500>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
operating-points-v2 = <&cpu4_opp_table>;
capacity-dmips-mhz = <1946>;
dynamic-power-coefficient = <520>;
@@ -334,23 +334,23 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x600>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
operating-points-v2 = <&cpu4_opp_table>;
capacity-dmips-mhz = <1946>;
dynamic-power-coefficient = <520>;
@@ -358,23 +358,23 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo";
reg = <0x0 0x700>;
clocks = <&cpufreq_hw 2>;
enable-method = "psci";
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
operating-points-v2 = <&cpu7_opp_table>;
capacity-dmips-mhz = <1985>;
dynamic-power-coefficient = <552>;
@@ -382,46 +382,46 @@
<&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
qcom,freq-domain = <&cpufreq_hw 2>;
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -429,7 +429,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-power-down";
arm,psci-suspend-param = <0x40000003>;
@@ -439,7 +439,7 @@
local-timer-stop;
};
- LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
+ little_cpu_sleep_1: cpu-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-down";
arm,psci-suspend-param = <0x40000004>;
@@ -449,7 +449,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-power-down";
arm,psci-suspend-param = <0x40000003>;
@@ -459,7 +459,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
+ big_cpu_sleep_1: cpu-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-down";
arm,psci-suspend-param = <0x40000004>;
@@ -471,7 +471,7 @@
};
domain_idle_states: domain-idle-states {
- CLUSTER_SLEEP_APSS_OFF: cluster-sleep-0 {
+ cluster_sleep_apss_off: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <2752>;
@@ -479,7 +479,7 @@
min-residency-us = <6118>;
};
- CLUSTER_SLEEP_CX_RET: cluster-sleep-1 {
+ cluster_sleep_cx_ret: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41001344>;
entry-latency-us = <3263>;
@@ -487,7 +487,7 @@
min-residency-us = <8467>;
};
- CLUSTER_SLEEP_LLCC_OFF: cluster-sleep-2 {
+ cluster_sleep_llcc_off: cluster-sleep-2 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100b344>;
entry-latency-us = <3638>;
@@ -845,8 +845,13 @@
};
};
- pmu {
- compatible = "arm,armv8-pmuv3";
+ pmu-a55 {
+ compatible = "arm,cortex-a55-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu-a78 {
+ compatible = "arm,cortex-a78-pmu";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
};
@@ -854,57 +859,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CLUSTER_PD: power-domain-cluster {
+ cluster_pd: power-domain-cluster {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_APSS_OFF &CLUSTER_SLEEP_CX_RET &CLUSTER_SLEEP_LLCC_OFF>;
+ domain-idle-states = <&cluster_sleep_apss_off &cluster_sleep_cx_ret &cluster_sleep_llcc_off>;
};
};
@@ -2318,7 +2323,7 @@
status = "disabled";
};
- ufs_mem_hc: ufs@1d84000 {
+ ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sc7280-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
reg = <0x0 0x01d84000 0x0 0x3000>;
@@ -2718,7 +2723,7 @@
interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
#dma-cells = <1>;
qcom,controlled-remotely;
- num-channels = <31>;
+ num-channels = <31>;
qcom,ee = <1>;
qcom,num-ees = <2>;
iommus = <&apps_smmu 0x1826 0x0>;
@@ -2823,6 +2828,8 @@
nvmem-cells = <&gpu_speed_bin>;
nvmem-cell-names = "speed_bin";
+ status = "disabled";
+
gpu_zap_shader: zap-shader {
memory-region = <&gpu_zap_mem>;
};
@@ -2834,14 +2841,14 @@
opp-hz = /bits/ 64 <315000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
opp-peak-kBps = <1804000>;
- opp-supported-hw = <0x07>;
+ opp-supported-hw = <0x17>;
};
opp-450000000 {
opp-hz = /bits/ 64 <450000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
opp-peak-kBps = <4068000>;
- opp-supported-hw = <0x07>;
+ opp-supported-hw = <0x17>;
};
/* Only applicable for SKUs which has 550Mhz as Fmax */
@@ -2856,14 +2863,14 @@
opp-hz = /bits/ 64 <550000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
opp-peak-kBps = <6832000>;
- opp-supported-hw = <0x06>;
+ opp-supported-hw = <0x16>;
};
opp-608000000 {
opp-hz = /bits/ 64 <608000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L2>;
opp-peak-kBps = <8368000>;
- opp-supported-hw = <0x06>;
+ opp-supported-hw = <0x16>;
};
opp-700000000 {
@@ -3278,7 +3285,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07040000 0 0x1000>;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3298,7 +3305,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07140000 0 0x1000>;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3318,7 +3325,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07240000 0 0x1000>;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3338,7 +3345,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07340000 0 0x1000>;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3358,7 +3365,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07440000 0 0x1000>;
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3378,7 +3385,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07540000 0 0x1000>;
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3398,7 +3405,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07640000 0 0x1000>;
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3418,7 +3425,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07740000 0 0x1000>;
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -6057,7 +6064,7 @@
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
@@ -6177,17 +6184,17 @@
cooling-maps {
map0 {
trip = <&cpu0_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu0_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6220,17 +6227,17 @@
cooling-maps {
map0 {
trip = <&cpu1_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu1_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6263,17 +6270,17 @@
cooling-maps {
map0 {
trip = <&cpu2_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu2_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6306,17 +6313,17 @@
cooling-maps {
map0 {
trip = <&cpu3_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu3_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6349,17 +6356,17 @@
cooling-maps {
map0 {
trip = <&cpu4_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>;
+ 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 = <&cpu4_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>;
+ 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>;
};
};
};
@@ -6392,17 +6399,17 @@
cooling-maps {
map0 {
trip = <&cpu5_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>;
+ 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 = <&cpu5_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>;
+ 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>;
};
};
};
@@ -6435,17 +6442,17 @@
cooling-maps {
map0 {
trip = <&cpu6_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>;
+ 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 = <&cpu6_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>;
+ 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>;
};
};
};
@@ -6478,17 +6485,17 @@
cooling-maps {
map0 {
trip = <&cpu7_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>;
+ 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 = <&cpu7_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>;
+ 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>;
};
};
};
@@ -6521,17 +6528,17 @@
cooling-maps {
map0 {
trip = <&cpu8_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>;
+ 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 = <&cpu8_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>;
+ 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>;
};
};
};
@@ -6564,17 +6571,17 @@
cooling-maps {
map0 {
trip = <&cpu9_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>;
+ 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 = <&cpu9_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>;
+ 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>;
};
};
};
@@ -6607,17 +6614,17 @@
cooling-maps {
map0 {
trip = <&cpu10_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>;
+ 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 = <&cpu10_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>;
+ 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>;
};
};
};
@@ -6650,17 +6657,17 @@
cooling-maps {
map0 {
trip = <&cpu11_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>;
+ 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 = <&cpu11_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>;
+ 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>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
index 0e9429684dd9..745a7d0b8381 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
@@ -42,28 +42,28 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x0>;
enable-method = "psci";
capacity-dmips-mhz = <602>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -71,207 +71,207 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x100>;
enable-method = "psci";
capacity-dmips-mhz = <602>;
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x200>;
enable-method = "psci";
capacity-dmips-mhz = <602>;
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x300>;
enable-method = "psci";
capacity-dmips-mhz = <602>;
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-unified;
cache-level = <2>;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x400>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 1>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-unified;
cache-level = <2>;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x500>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 1>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-unified;
cache-level = <2>;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x600>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 1>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-unified;
cache-level = <2>;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x700>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
#cooling-cells = <2>;
clocks = <&cpufreq_hw 1>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-unified;
cache-level = <2>;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -279,7 +279,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
arm,psci-suspend-param = <0x40000004>;
entry-latency-us = <355>;
@@ -288,7 +288,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
arm,psci-suspend-param = <0x40000004>;
entry-latency-us = <2411>;
@@ -299,7 +299,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_APSS_OFF: cluster-sleep-0 {
+ cluster_sleep_apss_off: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <3300>;
@@ -307,7 +307,7 @@
min-residency-us = <6000>;
};
- CLUSTER_SLEEP_AOSS_SLEEP: cluster-sleep-1 {
+ cluster_sleep_aoss_sleep: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100a344>;
entry-latency-us = <3263>;
@@ -541,57 +541,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_APSS_OFF &CLUSTER_SLEEP_AOSS_SLEEP>;
+ domain-idle-states = <&cluster_sleep_apss_off &cluster_sleep_aoss_sleep>;
};
};
@@ -3662,7 +3662,7 @@
<GIC_SPI 773 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 774 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 775 IRQ_TYPE_LEVEL_HIGH>;
-
+ dma-coherent;
};
remoteproc_adsp: remoteproc@17300000 {
@@ -3790,7 +3790,7 @@
<WAKE_TCS 1>,
<CONTROL_TCS 0>;
label = "apps_rsc";
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
@@ -3868,7 +3868,7 @@
compatible = "qcom,sc8180x-lmh";
reg = <0 0x18350800 0 0x400>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
- cpus = <&CPU4>;
+ cpus = <&cpu4>;
qcom,lmh-temp-arm-millicelsius = <65000>;
qcom,lmh-temp-low-millicelsius = <94500>;
qcom,lmh-temp-high-millicelsius = <95000>;
@@ -3880,7 +3880,7 @@
compatible = "qcom,sc8180x-lmh";
reg = <0 0x18358800 0 0x400>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
- cpus = <&CPU0>;
+ cpus = <&cpu0>;
qcom,lmh-temp-arm-millicelsius = <65000>;
qcom,lmh-temp-low-millicelsius = <94500>;
qcom,lmh-temp-high-millicelsius = <95000>;
@@ -3889,7 +3889,7 @@
};
cpufreq_hw: cpufreq@18323000 {
- compatible = "qcom,cpufreq-hw";
+ compatible = "qcom,sc8180x-cpufreq-hw", "qcom,cpufreq-hw";
reg = <0 0x18323000 0 0x1400>, <0 0x18325800 0 0x1400>;
reg-names = "freq-domain0", "freq-domain1";
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
index 6020582b0a59..75adaa19d1c3 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
@@ -20,6 +20,7 @@
i2c4 = &i2c4;
i2c21 = &i2c21;
serial0 = &uart17;
+ serial1 = &uart2;
};
backlight: backlight {
@@ -260,6 +261,70 @@
};
};
};
+
+ wcn6855-pmu {
+ compatible = "qcom,wcn6855-pmu";
+
+ pinctrl-0 = <&bt_en>, <&wlan_en>;
+ pinctrl-names = "default";
+
+ wlan-enable-gpios = <&tlmm 134 GPIO_ACTIVE_HIGH>;
+ bt-enable-gpios = <&tlmm 133 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 132 GPIO_ACTIVE_HIGH>;
+
+ vddio-supply = <&vreg_s10b>;
+ vddaon-supply = <&vreg_s12b>;
+ vddpmu-supply = <&vreg_s12b>;
+ vddpmumx-supply = <&vreg_s12b>;
+ vddpmucx-supply = <&vreg_s12b>;
+ vddrfa0p95-supply = <&vreg_s12b>;
+ vddrfa1p3-supply = <&vreg_s11b>;
+ vddrfa1p9-supply = <&vreg_s1c>;
+ vddpcie1p3-supply = <&vreg_s11b>;
+ vddpcie1p9-supply = <&vreg_s1c>;
+
+ regulators {
+ vreg_pmu_rfa_cmn_0p8: ldo0 {
+ regulator-name = "vreg_pmu_rfa_cmn_0p8";
+ };
+
+ vreg_pmu_aon_0p8: ldo1 {
+ regulator-name = "vreg_pmu_aon_0p8";
+ };
+
+ vreg_pmu_wlcx_0p8: ldo2 {
+ regulator-name = "vreg_pmu_wlcx_0p8";
+ };
+
+ vreg_pmu_wlmx_0p8: ldo3 {
+ regulator-name = "vreg_pmu_wlmx_0p8";
+ };
+
+ vreg_pmu_btcmx_0p8: ldo4 {
+ regulator-name = "vreg_pmu_btcmx_0p8";
+ };
+
+ vreg_pmu_pcie_1p8: ldo5 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+
+ vreg_pmu_pcie_0p9: ldo6 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_rfa_0p8: ldo7 {
+ regulator-name = "vreg_pmu_rfa_0p8";
+ };
+
+ vreg_pmu_rfa_1p2: ldo8 {
+ regulator-name = "vreg_pmu_rfa_1p2";
+ };
+
+ vreg_pmu_rfa_1p7: ldo9 {
+ regulator-name = "vreg_pmu_rfa_1p7";
+ };
+ };
+ };
};
&apps_rsc {
@@ -269,6 +334,15 @@
vdd-l3-l5-supply = <&vreg_s11b>;
+ vreg_s10b: smps10 {
+ regulator-name = "vreg_s10b";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
vreg_s11b: smps11 {
regulator-name = "vreg_s11b";
regulator-min-microvolt = <1272000>;
@@ -276,6 +350,13 @@
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+ vreg_s12b: smps12 {
+ regulator-name = "vreg_s12b";
+ regulator-min-microvolt = <984000>;
+ regulator-max-microvolt = <984000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
vreg_l3b: ldo3 {
regulator-name = "vreg_l3b";
regulator-min-microvolt = <1200000>;
@@ -304,6 +385,13 @@
compatible = "qcom,pm8350c-rpmh-regulators";
qcom,pmic-id = "c";
+ vreg_s1c: smps1 {
+ regulator-name = "vreg_s1c";
+ regulator-min-microvolt = <1888000>;
+ regulator-max-microvolt = <1888000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
vreg_l1c: ldo1 {
regulator-name = "vreg_l1c";
regulator-min-microvolt = <1800000>;
@@ -583,6 +671,25 @@
status = "okay";
};
+&pcie4_port0 {
+ wifi@0 {
+ compatible = "pci17cb,1103";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+ vddaon-supply = <&vreg_pmu_aon_0p8>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+
+ qcom,ath11k-calibration-variant = "QC_8280XP_CRD";
+ };
+};
+
&pmc8280c_lpg {
status = "okay";
};
@@ -643,6 +750,26 @@
status = "okay";
};
+&uart2 {
+ pinctrl-0 = <&uart2_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn6855-bt";
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+ vddaon-supply = <&vreg_pmu_aon_0p8>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p8>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+ };
+};
+
&uart17 {
compatible = "qcom,geni-debug-uart";
@@ -788,6 +915,13 @@
&tlmm {
gpio-reserved-ranges = <74 6>, <83 4>, <125 2>, <128 2>, <154 7>;
+ bt_en: bt-en-state {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
edp_reg_en: edp-reg-en-state {
pins = "gpio25";
function = "gpio";
@@ -981,6 +1115,34 @@
};
};
+ uart2_default: uart2-default-state {
+ cts-pins {
+ pins = "gpio121";
+ function = "qup2";
+ bias-bus-hold;
+ };
+
+ rts-pins {
+ pins = "gpio122";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx-pins {
+ pins = "gpio124";
+ function = "qup2";
+ bias-pull-up;
+ };
+
+ tx-pins {
+ pins = "gpio123";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
usb0_sbu_default: usb0-sbu-state {
oe-n-pins {
pins = "gpio101";
@@ -1030,4 +1192,11 @@
output-high;
};
};
+
+ wlan_en: wlan-en-state {
+ pins = "gpio134";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
};
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 6a28cab97189..f3190f408f4b 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
@@ -346,18 +346,18 @@
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>;
+ 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>;
+ 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>;
};
};
};
@@ -400,6 +400,70 @@
};
};
};
+
+ wcn6855-pmu {
+ compatible = "qcom,wcn6855-pmu";
+
+ pinctrl-0 = <&bt_default>, <&wlan_en>;
+ pinctrl-names = "default";
+
+ wlan-enable-gpios = <&tlmm 134 GPIO_ACTIVE_HIGH>;
+ bt-enable-gpios = <&tlmm 133 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 132 GPIO_ACTIVE_HIGH>;
+
+ vddio-supply = <&vreg_s10b>;
+ vddaon-supply = <&vreg_s12b>;
+ vddpmu-supply = <&vreg_s12b>;
+ vddpmumx-supply = <&vreg_s12b>;
+ vddpmucx-supply = <&vreg_s12b>;
+ vddrfa0p95-supply = <&vreg_s12b>;
+ vddrfa1p3-supply = <&vreg_s11b>;
+ vddrfa1p9-supply = <&vreg_s1c>;
+ vddpcie1p3-supply = <&vreg_s11b>;
+ vddpcie1p9-supply = <&vreg_s1c>;
+
+ regulators {
+ vreg_pmu_rfa_cmn_0p8: ldo0 {
+ regulator-name = "vreg_pmu_rfa_cmn_0p8";
+ };
+
+ vreg_pmu_aon_0p8: ldo1 {
+ regulator-name = "vreg_pmu_aon_0p8";
+ };
+
+ vreg_pmu_wlcx_0p8: ldo2 {
+ regulator-name = "vreg_pmu_wlcx_0p8";
+ };
+
+ vreg_pmu_wlmx_0p8: ldo3 {
+ regulator-name = "vreg_pmu_wlmx_0p8";
+ };
+
+ vreg_pmu_btcmx_0p8: ldo4 {
+ regulator-name = "vreg_pmu_btcmx_0p8";
+ };
+
+ vreg_pmu_pcie_1p8: ldo5 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+
+ vreg_pmu_pcie_0p9: ldo6 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_rfa_0p8: ldo7 {
+ regulator-name = "vreg_pmu_rfa_0p8";
+ };
+
+ vreg_pmu_rfa_1p2: ldo8 {
+ regulator-name = "vreg_pmu_rfa_1p2";
+ };
+
+ vreg_pmu_rfa_1p7: ldo9 {
+ regulator-name = "vreg_pmu_rfa_1p7";
+ };
+ };
+ };
};
&apps_rsc {
@@ -426,7 +490,6 @@
regulator-min-microvolt = <1272000>;
regulator-max-microvolt = <1272000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-always-on;
};
vreg_s12b: smps12 {
@@ -434,7 +497,6 @@
regulator-min-microvolt = <984000>;
regulator-max-microvolt = <984000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-always-on;
};
vreg_l1b: ldo1 {
@@ -633,7 +695,6 @@
port {
ov5675_ep: endpoint {
- clock-lanes = <0>;
data-lanes = <1 2>;
link-frequencies = /bits/ 64 <450000000>;
remote-endpoint = <&csiphy0_lanes01_ep>;
@@ -927,6 +988,16 @@
compatible = "pci17cb,1103";
reg = <0x10000 0x0 0x0 0x0 0x0>;
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+ vddaon-supply = <&vreg_pmu_aon_0p8>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+
qcom,ath11k-calibration-variant = "LE_X13S";
};
};
@@ -1258,20 +1329,16 @@
bluetooth {
compatible = "qcom,wcn6855-bt";
- vddio-supply = <&vreg_s10b>;
- vddbtcxmx-supply = <&vreg_s12b>;
- vddrfacmn-supply = <&vreg_s12b>;
- vddrfa0p8-supply = <&vreg_s12b>;
- vddrfa1p2-supply = <&vreg_s11b>;
- vddrfa1p7-supply = <&vreg_s1c>;
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+ vddaon-supply = <&vreg_pmu_aon_0p8>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p8>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
max-speed = <3200000>;
-
- enable-gpios = <&tlmm 133 GPIO_ACTIVE_HIGH>;
- swctrl-gpios = <&tlmm 132 GPIO_ACTIVE_HIGH>;
-
- pinctrl-0 = <&bt_default>;
- pinctrl-names = "default";
};
};
@@ -1761,4 +1828,11 @@
bias-disable;
};
};
+
+ wlan_en: wlan-en-state {
+ pins = "gpio134";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-down;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-microsoft-arcata.dts b/arch/arm64/boot/dts/qcom/sc8280xp-microsoft-arcata.dts
new file mode 100644
index 000000000000..ae5daeac8fe2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-microsoft-arcata.dts
@@ -0,0 +1,1032 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Jérôme de Bretagne <jerome.debretagne@gmail.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "sc8280xp.dtsi"
+#include "sc8280xp-pmics.dtsi"
+
+/ {
+ model = "Microsoft Surface Pro 9 5G";
+ compatible = "microsoft,arcata", "qcom,sc8280xp";
+
+ aliases {
+ serial0 = &uart18;
+ serial1 = &uart2;
+ };
+
+ wcd938x: audio-codec {
+ compatible = "qcom,wcd9380-codec";
+
+ pinctrl-0 = <&wcd_default>;
+ pinctrl-names = "default";
+
+ reset-gpios = <&tlmm 106 GPIO_ACTIVE_LOW>;
+
+ vdd-buck-supply = <&vreg_s10b>;
+ vdd-rxtx-supply = <&vreg_s10b>;
+ vdd-io-supply = <&vreg_s10b>;
+ vdd-mic-bias-supply = <&vreg_bob>;
+
+ 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>;
+
+ #sound-dai-cells = <1>;
+ };
+
+ pmic-glink {
+ compatible = "qcom,sc8280xp-pmic-glink", "qcom,pmic-glink";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Left-side top port */
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_con0_hs: endpoint {
+ remote-endpoint = <&usb_0_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_con0_ss: endpoint {
+ remote-endpoint = <&usb_0_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_con0_sbu: endpoint {
+ remote-endpoint = <&usb0_sbu_mux>;
+ };
+ };
+ };
+ };
+
+ /* Left-side bottom port */
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_con1_hs: endpoint {
+ remote-endpoint = <&usb_1_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_con1_ss: endpoint {
+ remote-endpoint = <&usb_1_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_con1_sbu: endpoint {
+ remote-endpoint = <&usb1_sbu_mux>;
+ };
+ };
+ };
+ };
+ };
+
+ 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-0 = <&nvme_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VPH_VCC3R9";
+ regulator-min-microvolt = <3900000>;
+ regulator-max-microvolt = <3900000>;
+
+ 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-0 = <&hastings_reg_en>;
+ pinctrl-names = "default";
+
+ 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-0 = <&wwan_sw_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ reserved-memory {
+ gpu_mem: gpu-mem@8bf00000 {
+ reg = <0 0x8bf00000 0 0x2000>;
+ no-map;
+ };
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x8000000>;
+ reusable;
+ linux,cma-default;
+ };
+ };
+
+ thermal-zones {
+ skin-temp-thermal {
+ polling-delay-passive = <250>;
+
+ 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>;
+ };
+ };
+ };
+ };
+
+ usb0-sbu-mux {
+ compatible = "pericom,pi3usb102", "gpio-sbu-mux";
+
+ enable-gpios = <&tlmm 101 GPIO_ACTIVE_LOW>;
+ select-gpios = <&tlmm 164 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&usb0_sbu_default>;
+ pinctrl-names = "default";
+
+ mode-switch;
+ orientation-switch;
+
+ port {
+ usb0_sbu_mux: endpoint {
+ remote-endpoint = <&pmic_glink_con0_sbu>;
+ };
+ };
+ };
+
+ usb1-sbu-mux {
+ compatible = "pericom,pi3usb102", "gpio-sbu-mux";
+
+ enable-gpios = <&tlmm 48 GPIO_ACTIVE_LOW>;
+ select-gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&usb1_sbu_default>;
+ pinctrl-names = "default";
+
+ mode-switch;
+ orientation-switch;
+
+ port {
+ usb1_sbu_mux: endpoint {
+ remote-endpoint = <&pmic_glink_con1_sbu>;
+ };
+ };
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8350-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-l1-l4-supply = <&vreg_s12b>;
+ vdd-l2-l7-supply = <&vreg_bob>;
+ vdd-l3-l5-supply = <&vreg_s11b>;
+ vdd-l6-l9-l10-supply = <&vreg_s12b>;
+ vdd-l8-supply = <&vreg_s12b>;
+
+ vreg_s10b: smps10 {
+ regulator-name = "vreg_s10b";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_s11b: smps11 {
+ regulator-name = "vreg_s11b";
+ regulator-min-microvolt = <1272000>;
+ regulator-max-microvolt = <1272000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_s12b: smps12 {
+ regulator-name = "vreg_s12b";
+ regulator-min-microvolt = <984000>;
+ regulator-max-microvolt = <984000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_l3b: ldo3 {
+ regulator-name = "vreg_l3b";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-boot-on;
+ };
+
+ vreg_l4b: ldo4 {
+ regulator-name = "vreg_l4b";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b: ldo6 {
+ regulator-name = "vreg_l6b";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-boot-on;
+ regulator-always-on; // FIXME: VDD_A_EDP_0_0P9
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8350c-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-bob-supply = <&vreg_vph_pwr>;
+ vdd-l1-l12-supply = <&vreg_s1c>;
+ vdd-l2-l8-supply = <&vreg_s1c>;
+ vdd-l3-l4-l5-l7-l13-supply = <&vreg_bob>;
+ vdd-l6-l9-l11-supply = <&vreg_bob>;
+ vdd-l10-supply = <&vreg_s11b>;
+
+ vreg_s1c: smps1 {
+ regulator-name = "vreg_s1c";
+ regulator-min-microvolt = <1880000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_l1c: ldo1 {
+ regulator-name = "vreg_l1c";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12c: ldo12 {
+ regulator-name = "vreg_l12c";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13c: ldo13 {
+ regulator-name = "vreg_l13c";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob: bob {
+ regulator-name = "vreg_bob";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ regulator-always-on;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pm8350-rpmh-regulators";
+ qcom,pmic-id = "d";
+
+ vdd-l1-l4-supply = <&vreg_s11b>;
+ vdd-l2-l7-supply = <&vreg_bob>;
+ vdd-l3-l5-supply = <&vreg_s11b>;
+ vdd-l6-l9-l10-supply = <&vreg_s12b>;
+ vdd-l8-supply = <&vreg_s12b>;
+
+ vreg_l3d: ldo3 {
+ regulator-name = "vreg_l3d";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4d: ldo4 {
+ regulator-name = "vreg_l4d";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ 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>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9d: ldo9 {
+ regulator-name = "vreg_l9d";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&dispcc0 {
+ status = "okay";
+};
+
+&dispcc1 {
+ status = "okay";
+};
+
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ memory-region = <&gpu_mem>;
+ firmware-name = "qcom/sc8280xp/MICROSOFT/SurfacePro9/qcdxkmsuc8280.mbn";
+ };
+};
+
+&mdss0 {
+ status = "okay";
+};
+
+&mdss0_dp0 {
+ status = "okay";
+};
+
+&mdss0_dp0_out {
+ data-lanes = <0 1>;
+ remote-endpoint = <&usb_0_qmpphy_dp_in>;
+};
+
+&mdss0_dp1 {
+ status = "okay";
+};
+
+&mdss0_dp1_out {
+ data-lanes = <0 1>;
+ remote-endpoint = <&usb_1_qmpphy_dp_in>;
+};
+
+&pcie2a {
+ perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_nvme>;
+
+ pinctrl-0 = <&pcie2a_default>;
+ pinctrl-names = "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-0 = <&pcie3a_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie3a_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
+&pcie4 {
+ max-link-speed = <2>;
+
+ perst-gpios = <&tlmm 141 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 139 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_wlan>;
+
+ pinctrl-0 = <&pcie4_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie4_port0 {
+ wifi@0 {
+ compatible = "pci17cb,1103";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ qcom,ath11k-calibration-variant = "MS_SP9_5G";
+ };
+};
+
+&pcie4_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
+&pmk8280_pon_pwrkey {
+ status = "okay";
+};
+
+&pmk8280_pon_resin {
+ status = "okay";
+};
+
+&pmk8280_rtc {
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "offset";
+
+ status = "okay";
+};
+
+&pmk8280_sdam_6 {
+ status = "okay";
+
+ rtc_offset: rtc-offset@bc {
+ reg = <0xbc 0x4>;
+ };
+};
+
+&qup0 {
+ status = "okay";
+};
+
+&qup1 {
+ status = "okay";
+};
+
+&qup2 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/sc8280xp/MICROSOFT/SurfacePro9/qcadsp8280.mbn";
+
+ status = "okay";
+};
+
+&remoteproc_nsp0 {
+ firmware-name = "qcom/sc8280xp/MICROSOFT/SurfacePro9/qccdsp8280.mbn";
+
+ status = "okay";
+};
+
+&rxmacro {
+ status = "okay";
+};
+
+&sound {
+ compatible = "qcom,sc8280xp-sndcard";
+ model = "SC8280XP-MICROSOFT-SURFACE-PRO-9-5G";
+ 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",
+ "VA DMIC0", "VA MIC BIAS1",
+ "VA DMIC1", "VA MIC BIAS1",
+ "VA DMIC2", "VA 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 = <&swr0 0>, <&wsamacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ va-dai-link {
+ link-name = "VA Capture";
+
+ cpu {
+ sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+
+ codec {
+ sound-dai = <&vamacro 0>;
+ };
+ };
+};
+
+&swr0 {
+ status = "okay";
+};
+
+&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>;
+ };
+};
+
+&txmacro {
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn6855-bt";
+
+ vddio-supply = <&vreg_s10b>;
+ vddbtcxmx-supply = <&vreg_s12b>;
+ vddrfacmn-supply = <&vreg_s12b>;
+ vddrfa0p8-supply = <&vreg_s12b>;
+ vddrfa1p2-supply = <&vreg_s11b>;
+ vddrfa1p7-supply = <&vreg_s1c>;
+
+ max-speed = <3200000>;
+
+ enable-gpios = <&tlmm 133 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 132 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&bt_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&uart18 {
+ status = "okay";
+
+ embedded-controller {
+ compatible = "microsoft,surface-sam";
+
+ interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_RISING>;
+
+ current-speed = <4000000>;
+
+ pinctrl-0 = <&ssam_state>;
+ pinctrl-names = "default";
+ };
+};
+
+&usb_0 {
+ status = "okay";
+};
+
+&usb_0_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_0_dwc3_hs {
+ remote-endpoint = <&pmic_glink_con0_hs>;
+};
+
+&usb_0_hsphy {
+ vdda-pll-supply = <&vreg_l9d>;
+ vdda18-supply = <&vreg_l1c>;
+ vdda33-supply = <&vreg_l7d>;
+
+ status = "okay";
+};
+
+&usb_0_qmpphy {
+ vdda-phy-supply = <&vreg_l9d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ orientation-switch;
+
+ status = "okay";
+};
+
+&usb_0_qmpphy_dp_in {
+ remote-endpoint = <&mdss0_dp0_out>;
+};
+
+&usb_0_qmpphy_out {
+ remote-endpoint = <&pmic_glink_con0_ss>;
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_con1_hs>;
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&vreg_l4b>;
+ vdda18-supply = <&vreg_l1c>;
+ vdda33-supply = <&vreg_l13c>;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l4b>;
+ vdda-pll-supply = <&vreg_l3b>;
+
+ orientation-switch;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy_dp_in {
+ remote-endpoint = <&mdss0_dp1_out>;
+};
+
+&usb_1_qmpphy_out {
+ remote-endpoint = <&pmic_glink_con1_ss>;
+};
+
+&vamacro {
+ pinctrl-0 = <&dmic01_default>, <&dmic23_default>;
+ pinctrl-names = "default";
+
+ vdd-micb-supply = <&vreg_s10b>;
+
+ qcom,dmic-sample-rate = <4800000>;
+
+ status = "okay";
+};
+
+&wsamacro {
+ status = "okay";
+};
+
+&xo_board_clk {
+ clock-frequency = <38400000>;
+};
+
+/* PINCTRL */
+
+&lpass_tlmm {
+ status = "okay";
+};
+
+&pmc8280_2_gpios {
+ wwan_sw_en: wwan-sw-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
+
+&pmr735a_gpios {
+ hastings_reg_en: hastings-reg-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
+
+&tlmm {
+ bt_default: bt-default-state {
+ hstp-bt-en-pins {
+ pins = "gpio133";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ hstp-sw-ctrl-pins {
+ pins = "gpio132";
+ function = "gpio";
+ bias-pull-down;
+ };
+ };
+
+ 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-disable;
+ };
+
+ 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-disable;
+ };
+
+ 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-disable;
+ };
+
+ wake-n-pins {
+ pins = "gpio139";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+
+ ssam_state: ssam-state-state {
+ pins = "gpio85";
+ function = "gpio";
+ bias-disable;
+ };
+
+ uart2_default: uart2-default-state {
+ cts-pins {
+ pins = "gpio121";
+ function = "qup2";
+ bias-bus-hold;
+ };
+
+ rts-pins {
+ pins = "gpio122";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx-pins {
+ pins = "gpio124";
+ function = "qup2";
+ bias-pull-up;
+ };
+
+ tx-pins {
+ pins = "gpio123";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ usb0_sbu_default: usb0-sbu-state {
+ oe-n-pins {
+ pins = "gpio101";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <16>;
+ output-high;
+ };
+
+ sel-pins {
+ pins = "gpio164";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <16>;
+ };
+ };
+
+ usb1_sbu_default: usb1-sbu-state {
+ oe-n-pins {
+ pins = "gpio48";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <16>;
+ output-high;
+ };
+
+ sel-pins {
+ pins = "gpio47";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <16>;
+ };
+ };
+
+ wcd_default: wcd-default-state {
+ reset-pins {
+ pins = "gpio106";
+ function = "gpio";
+ bias-disable;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
index 80a57aa22839..ef06d1ac084d 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
@@ -44,7 +44,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a78c";
reg = <0x0 0x0>;
@@ -52,19 +52,19 @@
enable-method = "psci";
capacity-dmips-mhz = <981>;
dynamic-power-coefficient = <549>;
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd0>;
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 {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -72,7 +72,7 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a78c";
reg = <0x0 0x100>;
@@ -80,22 +80,22 @@
enable-method = "psci";
capacity-dmips-mhz = <981>;
dynamic-power-coefficient = <549>;
- next-level-cache = <&L2_100>;
- power-domains = <&CPU_PD1>;
+ next-level-cache = <&l2_100>;
+ power-domains = <&cpu_pd1>;
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 {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a78c";
reg = <0x0 0x200>;
@@ -103,22 +103,22 @@
enable-method = "psci";
capacity-dmips-mhz = <981>;
dynamic-power-coefficient = <549>;
- next-level-cache = <&L2_200>;
- power-domains = <&CPU_PD2>;
+ next-level-cache = <&l2_200>;
+ power-domains = <&cpu_pd2>;
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 {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a78c";
reg = <0x0 0x300>;
@@ -126,22 +126,22 @@
enable-method = "psci";
capacity-dmips-mhz = <981>;
dynamic-power-coefficient = <549>;
- next-level-cache = <&L2_300>;
- power-domains = <&CPU_PD3>;
+ next-level-cache = <&l2_300>;
+ power-domains = <&cpu_pd3>;
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 {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "arm,cortex-x1c";
reg = <0x0 0x400>;
@@ -149,22 +149,22 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <590>;
- next-level-cache = <&L2_400>;
- power-domains = <&CPU_PD4>;
+ next-level-cache = <&l2_400>;
+ power-domains = <&cpu_pd4>;
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 {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "arm,cortex-x1c";
reg = <0x0 0x500>;
@@ -172,22 +172,22 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <590>;
- next-level-cache = <&L2_500>;
- power-domains = <&CPU_PD5>;
+ next-level-cache = <&l2_500>;
+ power-domains = <&cpu_pd5>;
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 {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "arm,cortex-x1c";
reg = <0x0 0x600>;
@@ -195,22 +195,22 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <590>;
- next-level-cache = <&L2_600>;
- power-domains = <&CPU_PD6>;
+ next-level-cache = <&l2_600>;
+ power-domains = <&cpu_pd6>;
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 {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "arm,cortex-x1c";
reg = <0x0 0x700>;
@@ -218,53 +218,53 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <590>;
- next-level-cache = <&L2_700>;
- power-domains = <&CPU_PD7>;
+ next-level-cache = <&l2_700>;
+ power-domains = <&cpu_pd7>;
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 {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -272,7 +272,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -282,7 +282,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -294,7 +294,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c344>;
entry-latency-us = <3263>;
@@ -593,57 +593,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>;
+ domain-idle-states = <&cluster_sleep_0>;
};
};
@@ -1007,6 +1007,24 @@
status = "disabled";
};
+ uart18: serial@888000 {
+ compatible = "qcom,geni-uart";
+ reg = <0 0x00888000 0 0x4000>;
+ clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>;
+ clock-names = "se";
+ interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>;
+ operating-points-v2 = <&qup_opp_table_100mhz>;
+ power-domains = <&rpmhpd SC8280XP_CX>;
+ interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_2 0>;
+ interconnect-names = "qup-core", "qup-config";
+
+ pinctrl-0 = <&qup_uart18_default>;
+ pinctrl-names = "default";
+
+ status = "disabled";
+ };
+
i2c19: i2c@88c000 {
compatible = "qcom,geni-i2c";
reg = <0 0x0088c000 0 0x4000>;
@@ -2294,7 +2312,7 @@
status = "disabled";
};
- ufs_mem_hc: ufs@1d84000 {
+ ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sc8280xp-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
reg = <0 0x01d84000 0 0x3000>;
@@ -2360,7 +2378,7 @@
status = "disabled";
};
- ufs_card_hc: ufs@1da4000 {
+ ufs_card_hc: ufshc@1da4000 {
compatible = "qcom,sc8280xp-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
reg = <0 0x01da4000 0 0x3000>;
@@ -4871,6 +4889,36 @@
bias-pull-down;
};
};
+
+ qup_uart18_default: qup-uart18-default-state {
+ cts-pins {
+ pins = "gpio66";
+ function = "qup18";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rts-pins {
+ pins = "gpio67";
+ function = "qup18";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tx-pins {
+ pins = "gpio68";
+ function = "qup18";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx-pins {
+ pins = "gpio69";
+ function = "qup18";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
};
apps_smmu: iommu@15000000 {
@@ -5008,6 +5056,7 @@
<GIC_SPI 892 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 891 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 890 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
intc: interrupt-controller@17a00000 {
@@ -5111,7 +5160,7 @@
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 1>;
label = "apps_rsc";
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
diff --git a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
index 60412281ab27..d402f4c85b11 100644
--- a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
+++ b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
@@ -104,12 +104,20 @@
compatible = "regulator-fixed";
regulator-name = "vreg_l10a_1p8";
regulator-min-microvolt = <1804000>;
- regulator-max-microvolt = <1896000>;
+ regulator-max-microvolt = <1804000>;
regulator-always-on;
regulator-boot-on;
};
};
+&adreno_gpu {
+ status = "okay";
+};
+
+&adreno_gpu_zap {
+ firmware-name = "qcom/sda660/a512_zap.mbn";
+};
+
&adsp_pil {
firmware-name = "qcom/sda660/adsp.mbn";
};
@@ -244,6 +252,11 @@
vdda-phy-dpdm-supply = <&vreg_l7b_3p125>;
};
+&remoteproc_mss {
+ firmware-name = "qcom/sda660/mba.mbn", "qcom/sda660/modem.mbn";
+ status = "okay";
+};
+
&rpm_requests {
regulators-0 {
compatible = "qcom,rpm-pm660-regulators";
@@ -283,6 +296,11 @@
regulator-allow-set-load;
};
+ vreg_l5a_0p8: l5 {
+ regulator-min-microvolt = <848000>;
+ regulator-max-microvolt = <848000>;
+ };
+
vreg_l6a_1p3: l6 {
regulator-min-microvolt = <1304000>;
regulator-max-microvolt = <1368000>;
@@ -481,3 +499,15 @@
vdda-pll-supply = <&vreg_l10a_1p8>;
status = "okay";
};
+
+&wifi {
+ vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
+ vdd-1.8-xo-supply = <&vreg_l9a_1p8>;
+ vdd-1.3-rfa-supply = <&vreg_l6a_1p3>;
+ vdd-3.3-ch0-supply = <&vreg_l19a_3p3>;
+ vdd-3.3-ch1-supply = <&vreg_l8b_3p3>;
+
+ qcom,ath10k-calibration-variant = "Inforce_IFC6560";
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts b/arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts
index 175befc02b22..c509bbfe5d3e 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-lenovo-tbx605f.dts
@@ -40,7 +40,7 @@
};
reserved-memory {
- other_ext_region@0 {
+ other-ext-region@0 {
no-map;
reg = <0x00 0x84500000 0x00 0x2300000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
index c8da5cb8d04e..19420cfdadf1 100644
--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
@@ -49,170 +49,170 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@100 {
+ cpu0: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x100>;
enable-method = "psci";
- cpu-idle-states = <&PERF_CPU_SLEEP_0
- &PERF_CPU_SLEEP_1
- &PERF_CLUSTER_SLEEP_0
- &PERF_CLUSTER_SLEEP_1
- &PERF_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&perf_cpu_sleep_0
+ &perf_cpu_sleep_1
+ &perf_cluster_sleep_0
+ &perf_cluster_sleep_1
+ &perf_cluster_sleep_2>;
capacity-dmips-mhz = <1126>;
#cooling-cells = <2>;
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
+ next-level-cache = <&l2_1>;
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@101 {
+ cpu1: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x101>;
enable-method = "psci";
- cpu-idle-states = <&PERF_CPU_SLEEP_0
- &PERF_CPU_SLEEP_1
- &PERF_CLUSTER_SLEEP_0
- &PERF_CLUSTER_SLEEP_1
- &PERF_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&perf_cpu_sleep_0
+ &perf_cpu_sleep_1
+ &perf_cluster_sleep_0
+ &perf_cluster_sleep_1
+ &perf_cluster_sleep_2>;
capacity-dmips-mhz = <1126>;
#cooling-cells = <2>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
- CPU2: cpu@102 {
+ cpu2: cpu@102 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x102>;
enable-method = "psci";
- cpu-idle-states = <&PERF_CPU_SLEEP_0
- &PERF_CPU_SLEEP_1
- &PERF_CLUSTER_SLEEP_0
- &PERF_CLUSTER_SLEEP_1
- &PERF_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&perf_cpu_sleep_0
+ &perf_cpu_sleep_1
+ &perf_cluster_sleep_0
+ &perf_cluster_sleep_1
+ &perf_cluster_sleep_2>;
capacity-dmips-mhz = <1126>;
#cooling-cells = <2>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
- CPU3: cpu@103 {
+ cpu3: cpu@103 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x103>;
enable-method = "psci";
- cpu-idle-states = <&PERF_CPU_SLEEP_0
- &PERF_CPU_SLEEP_1
- &PERF_CLUSTER_SLEEP_0
- &PERF_CLUSTER_SLEEP_1
- &PERF_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&perf_cpu_sleep_0
+ &perf_cpu_sleep_1
+ &perf_cluster_sleep_0
+ &perf_cluster_sleep_1
+ &perf_cluster_sleep_2>;
capacity-dmips-mhz = <1126>;
#cooling-cells = <2>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
- CPU4: cpu@0 {
+ cpu4: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x0>;
enable-method = "psci";
- cpu-idle-states = <&PWR_CPU_SLEEP_0
- &PWR_CPU_SLEEP_1
- &PWR_CLUSTER_SLEEP_0
- &PWR_CLUSTER_SLEEP_1
- &PWR_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&pwr_cpu_sleep_0
+ &pwr_cpu_sleep_1
+ &pwr_cluster_sleep_0
+ &pwr_cluster_sleep_1
+ &pwr_cluster_sleep_2>;
capacity-dmips-mhz = <1024>;
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU5: cpu@1 {
+ cpu5: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x1>;
enable-method = "psci";
- cpu-idle-states = <&PWR_CPU_SLEEP_0
- &PWR_CPU_SLEEP_1
- &PWR_CLUSTER_SLEEP_0
- &PWR_CLUSTER_SLEEP_1
- &PWR_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&pwr_cpu_sleep_0
+ &pwr_cpu_sleep_1
+ &pwr_cluster_sleep_0
+ &pwr_cluster_sleep_1
+ &pwr_cluster_sleep_2>;
capacity-dmips-mhz = <1024>;
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU6: cpu@2 {
+ cpu6: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x2>;
enable-method = "psci";
- cpu-idle-states = <&PWR_CPU_SLEEP_0
- &PWR_CPU_SLEEP_1
- &PWR_CLUSTER_SLEEP_0
- &PWR_CLUSTER_SLEEP_1
- &PWR_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&pwr_cpu_sleep_0
+ &pwr_cpu_sleep_1
+ &pwr_cluster_sleep_0
+ &pwr_cluster_sleep_1
+ &pwr_cluster_sleep_2>;
capacity-dmips-mhz = <1024>;
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU7: cpu@3 {
+ cpu7: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0 0x3>;
enable-method = "psci";
- cpu-idle-states = <&PWR_CPU_SLEEP_0
- &PWR_CPU_SLEEP_1
- &PWR_CLUSTER_SLEEP_0
- &PWR_CLUSTER_SLEEP_1
- &PWR_CLUSTER_SLEEP_2>;
+ cpu-idle-states = <&pwr_cpu_sleep_0
+ &pwr_cpu_sleep_1
+ &pwr_cluster_sleep_0
+ &pwr_cluster_sleep_1
+ &pwr_cluster_sleep_2>;
capacity-dmips-mhz = <1024>;
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
cluster1 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
};
@@ -220,7 +220,7 @@
idle-states {
entry-method = "psci";
- PWR_CPU_SLEEP_0: cpu-sleep-0-0 {
+ pwr_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "pwr-retention";
arm,psci-suspend-param = <0x40000002>;
@@ -229,7 +229,7 @@
min-residency-us = <200>;
};
- PWR_CPU_SLEEP_1: cpu-sleep-0-1 {
+ pwr_cpu_sleep_1: cpu-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "pwr-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -239,7 +239,7 @@
local-timer-stop;
};
- PERF_CPU_SLEEP_0: cpu-sleep-1-0 {
+ perf_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "perf-retention";
arm,psci-suspend-param = <0x40000002>;
@@ -248,7 +248,7 @@
min-residency-us = <200>;
};
- PERF_CPU_SLEEP_1: cpu-sleep-1-1 {
+ perf_cpu_sleep_1: cpu-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "perf-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -258,7 +258,7 @@
local-timer-stop;
};
- PWR_CLUSTER_SLEEP_0: cluster-sleep-0-0 {
+ pwr_cluster_sleep_0: cluster-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "pwr-cluster-dynamic-retention";
arm,psci-suspend-param = <0x400000F2>;
@@ -268,7 +268,7 @@
local-timer-stop;
};
- PWR_CLUSTER_SLEEP_1: cluster-sleep-0-1 {
+ pwr_cluster_sleep_1: cluster-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "pwr-cluster-retention";
arm,psci-suspend-param = <0x400000F3>;
@@ -278,7 +278,7 @@
local-timer-stop;
};
- PWR_CLUSTER_SLEEP_2: cluster-sleep-0-2 {
+ pwr_cluster_sleep_2: cluster-sleep-0-2 {
compatible = "arm,idle-state";
idle-state-name = "pwr-cluster-retention";
arm,psci-suspend-param = <0x400000F4>;
@@ -288,7 +288,7 @@
local-timer-stop;
};
- PERF_CLUSTER_SLEEP_0: cluster-sleep-1-0 {
+ perf_cluster_sleep_0: cluster-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "perf-cluster-dynamic-retention";
arm,psci-suspend-param = <0x400000F2>;
@@ -298,7 +298,7 @@
local-timer-stop;
};
- PERF_CLUSTER_SLEEP_1: cluster-sleep-1-1 {
+ perf_cluster_sleep_1: cluster-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "perf-cluster-retention";
arm,psci-suspend-param = <0x400000F3>;
@@ -308,7 +308,7 @@
local-timer-stop;
};
- PERF_CLUSTER_SLEEP_2: cluster-sleep-1-2 {
+ perf_cluster_sleep_2: cluster-sleep-1-2 {
compatible = "arm,idle-state";
idle-state-name = "perf-cluster-retention";
arm,psci-suspend-param = <0x400000F4>;
@@ -665,8 +665,6 @@
<GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
-
- status = "disabled";
};
a2noc: interconnect@1704000 {
@@ -1150,6 +1148,10 @@
opp-supported-hw = <0xff>;
};
};
+
+ adreno_gpu_zap: zap-shader {
+ memory-region = <&zap_shader_region>;
+ };
};
kgsl_smmu: iommu@5040000 {
@@ -1186,8 +1188,6 @@
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>;
-
- status = "disabled";
};
gpucc: clock-controller@5065000 {
@@ -1203,7 +1203,6 @@
clock-names = "xo",
"gcc_gpu_gpll0_clk",
"gcc_gpu_gpll0_div_clk";
- status = "disabled";
};
lpass_smmu: iommu@5100000 {
@@ -1233,8 +1232,6 @@
<GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
-
- status = "disabled";
};
sram@290000 {
@@ -2415,6 +2412,33 @@
redistributor-stride = <0x0 0x20000>;
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ wifi: wifi@18800000 {
+ compatible = "qcom,wcn3990-wifi";
+ reg = <0x18800000 0x800000>;
+ reg-names = "membase";
+ memory-region = <&wlan_msa_mem>;
+ clocks = <&rpmcc RPM_SMD_RF_CLK1_PIN>;
+ clock-names = "cxo_ref_clk_pin";
+ interrupts =
+ <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>;
+ iommus = <&anoc2_smmu 0x1a00>,
+ <&anoc2_smmu 0x1a01>;
+ qcom,snoc-host-cap-8bit-quirk;
+ qcom,no-msa-ready-indicator;
+ status = "disabled";
+ };
};
sound: sound {
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index 95b025ea260b..40d86d91b67f 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -14,10 +14,10 @@
cooling-maps {
map0 {
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -42,40 +42,40 @@
/*
* SDM632 uses Kryo 250 instead of Cortex A53
- * CPU0-3 are efficiency cores, CPU4-7 are performance cores
+ * cpu0-3 are efficiency cores, cpu4-7 are performance cores
*/
-&CPU0 {
+&cpu0 {
compatible = "qcom,kryo250";
};
-&CPU1 {
+&cpu1 {
compatible = "qcom,kryo250";
};
-&CPU2 {
+&cpu2 {
compatible = "qcom,kryo250";
};
-&CPU3 {
+&cpu3 {
compatible = "qcom,kryo250";
};
-&CPU4 {
+&cpu4 {
compatible = "qcom,kryo250";
capacity-dmips-mhz = <1980>;
};
-&CPU5 {
+&cpu5 {
compatible = "qcom,kryo250";
capacity-dmips-mhz = <1980>;
};
-&CPU6 {
+&cpu6 {
compatible = "qcom,kryo250";
capacity-dmips-mhz = <1980>;
};
-&CPU7 {
+&cpu7 {
compatible = "qcom,kryo250";
capacity-dmips-mhz = <1980>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm660.dtsi b/arch/arm64/boot/dts/qcom/sdm660.dtsi
index f89b27c99f40..3164a4817e32 100644
--- a/arch/arm64/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm660.dtsi
@@ -85,49 +85,49 @@
};
};
-&CPU0 {
+&cpu0 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <1024>;
/delete-property/ operating-points-v2;
};
-&CPU1 {
+&cpu1 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <1024>;
/delete-property/ operating-points-v2;
};
-&CPU2 {
+&cpu2 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <1024>;
/delete-property/ operating-points-v2;
};
-&CPU3 {
+&cpu3 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <1024>;
/delete-property/ operating-points-v2;
};
-&CPU4 {
+&cpu4 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <640>;
/delete-property/ operating-points-v2;
};
-&CPU5 {
+&cpu5 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <640>;
/delete-property/ operating-points-v2;
};
-&CPU6 {
+&cpu6 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <640>;
/delete-property/ operating-points-v2;
};
-&CPU7 {
+&cpu7 {
compatible = "qcom,kryo260";
capacity-dmips-mhz = <640>;
/delete-property/ operating-points-v2;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 187c6698835d..c93dd06c0b7d 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -32,7 +32,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x0>;
@@ -43,15 +43,15 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
cache-level = <2>;
cache-unified;
- L3_0: l3-cache {
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -59,7 +59,7 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x100>;
@@ -70,18 +70,18 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
- next-level-cache = <&L2_100>;
- L2_100: l2-cache {
+ next-level-cache = <&l2_100>;
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x200>;
@@ -92,18 +92,18 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
- next-level-cache = <&L2_200>;
- L2_200: l2-cache {
+ next-level-cache = <&l2_200>;
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x300>;
@@ -114,18 +114,18 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
- next-level-cache = <&L2_300>;
- L2_300: l2-cache {
+ next-level-cache = <&l2_300>;
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x400>;
@@ -136,18 +136,18 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
- next-level-cache = <&L2_400>;
- L2_400: l2-cache {
+ next-level-cache = <&l2_400>;
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x500>;
@@ -158,18 +158,18 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
- next-level-cache = <&L2_500>;
- L2_500: l2-cache {
+ next-level-cache = <&l2_500>;
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x600>;
@@ -180,18 +180,18 @@
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
- next-level-cache = <&L2_600>;
- L2_600: l2-cache {
+ next-level-cache = <&l2_600>;
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo360";
reg = <0x0 0x700>;
@@ -202,49 +202,49 @@
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&gladiator_noc MASTER_AMPSS_M0 3 &mem_noc SLAVE_EBI_CH0 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
- next-level-cache = <&L2_700>;
- L2_700: l2-cache {
+ next-level-cache = <&l2_700>;
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -252,7 +252,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -262,7 +262,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -274,7 +274,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c244>;
entry-latency-us = <3263>;
@@ -429,57 +429,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cluster {
+ cluster_pd: power-domain-cluster {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>;
+ domain-idle-states = <&cluster_sleep_0>;
};
};
@@ -1737,6 +1737,7 @@
<GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
gladiator_noc: interconnect@17900000 {
@@ -1762,7 +1763,7 @@
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
index e8276db9eabb..743c339ba108 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
@@ -164,7 +164,7 @@
};
&cpu_idle_states {
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-power-down";
arm,psci-suspend-param = <0x40000003>;
@@ -174,7 +174,7 @@
local-timer-stop;
};
- LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
+ little_cpu_sleep_1: cpu-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-down";
arm,psci-suspend-param = <0x40000004>;
@@ -184,7 +184,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-power-down";
arm,psci-suspend-param = <0x40000003>;
@@ -194,7 +194,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
+ big_cpu_sleep_1: cpu-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-down";
arm,psci-suspend-param = <0x40000004>;
@@ -204,7 +204,7 @@
local-timer-stop;
};
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "cluster-power-down";
arm,psci-suspend-param = <0x400000F4>;
@@ -215,68 +215,68 @@
};
};
-&CPU0 {
+&cpu0 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU1 {
+&cpu1 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU2 {
+&cpu2 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU3 {
+&cpu3 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&LITTLE_CPU_SLEEP_0
- &LITTLE_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&little_cpu_sleep_0
+ &little_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU4 {
+&cpu4 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&big_cpu_sleep_0
+ &big_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU5 {
+&cpu5 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&big_cpu_sleep_0
+ &big_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU6 {
+&cpu6 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&big_cpu_sleep_0
+ &big_cpu_sleep_1
+ &cluster_sleep_0>;
};
-&CPU7 {
+&cpu7 {
/delete-property/ power-domains;
/delete-property/ power-domain-names;
- cpu-idle-states = <&BIG_CPU_SLEEP_0
- &BIG_CPU_SLEEP_1
- &CLUSTER_SLEEP_0>;
+ cpu-idle-states = <&big_cpu_sleep_0
+ &big_cpu_sleep_1
+ &cluster_sleep_0>;
};
&lmh_cluster0 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
index a21caa6f3fa2..0a87df806caf 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dtso
@@ -4,8 +4,21 @@
*/
/dts-v1/;
-
-#include "sdm845-db845c.dts"
+/plugin/;
+
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ reserved-memory {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x8000000>;
+ reusable;
+ linux,cma-default;
+ };
+ };
+};
&camss {
vdda-phy-supply = <&vreg_l1a_0p875>;
@@ -28,6 +41,9 @@
};
&cci_i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
camera@10 {
compatible = "ovti,ov8856";
reg = <0x10>;
@@ -65,6 +81,9 @@
};
&cci_i2c1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
camera@60 {
compatible = "ovti,ov7251";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
index 9a6d3d0c0ee4..1cc0f571e1f7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
@@ -31,7 +31,7 @@
};
/* Fixed crystal oscillator dedicated to MCP2517FD */
- clk40M: can-clock {
+ clk40m: can-clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <40000000>;
@@ -863,7 +863,7 @@
can@0 {
compatible = "microchip,mcp2517fd";
reg = <0>;
- clocks = <&clk40M>;
+ clocks = <&clk40m>;
interrupts-extended = <&tlmm 104 IRQ_TYPE_LEVEL_LOW>;
spi-max-frequency = <10000000>;
vdd-supply = <&vdc_5v>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 54077549b9da..1ed794638a7c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -91,7 +91,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x0>;
@@ -103,16 +103,16 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
#cooling-cells = <2>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -120,7 +120,7 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x100>;
@@ -132,19 +132,19 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
#cooling-cells = <2>;
- next-level-cache = <&L2_100>;
- L2_100: l2-cache {
+ next-level-cache = <&l2_100>;
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x200>;
@@ -156,19 +156,19 @@
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
#cooling-cells = <2>;
- next-level-cache = <&L2_200>;
- L2_200: l2-cache {
+ next-level-cache = <&l2_200>;
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x300>;
@@ -181,18 +181,18 @@
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
- next-level-cache = <&L2_300>;
- L2_300: l2-cache {
+ next-level-cache = <&l2_300>;
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x400>;
@@ -204,19 +204,19 @@
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
#cooling-cells = <2>;
- next-level-cache = <&L2_400>;
- L2_400: l2-cache {
+ next-level-cache = <&l2_400>;
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x500>;
@@ -228,19 +228,19 @@
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
#cooling-cells = <2>;
- next-level-cache = <&L2_500>;
- L2_500: l2-cache {
+ next-level-cache = <&l2_500>;
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x600>;
@@ -252,19 +252,19 @@
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
#cooling-cells = <2>;
- next-level-cache = <&L2_600>;
- L2_600: l2-cache {
+ next-level-cache = <&l2_600>;
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo385";
reg = <0x0 0x700>;
@@ -276,50 +276,50 @@
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gladiator_noc MASTER_APPSS_PROC 3 &mem_noc SLAVE_EBI1 3>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
#cooling-cells = <2>;
- next-level-cache = <&L2_700>;
- L2_700: l2-cache {
+ next-level-cache = <&l2_700>;
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -327,7 +327,7 @@
cpu_idle_states: idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -337,7 +337,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -349,7 +349,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c244>;
entry-latency-us = <3263>;
@@ -717,57 +717,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cluster {
+ cluster_pd: power-domain-cluster {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>;
+ domain-idle-states = <&cluster_sleep_0>;
};
};
@@ -3615,7 +3615,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07040000 0 0x1000>;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3635,7 +3635,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07140000 0 0x1000>;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3655,7 +3655,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07240000 0 0x1000>;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3675,7 +3675,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07340000 0 0x1000>;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3695,7 +3695,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07440000 0 0x1000>;
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3715,7 +3715,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07540000 0 0x1000>;
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3735,7 +3735,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07640000 0 0x1000>;
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3755,7 +3755,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07740000 0 0x1000>;
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3959,7 +3959,7 @@
compatible = "qcom,sdm845-lmh";
reg = <0 0x17d70800 0 0x400>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
- cpus = <&CPU4>;
+ cpus = <&cpu4>;
qcom,lmh-temp-arm-millicelsius = <65000>;
qcom,lmh-temp-low-millicelsius = <94500>;
qcom,lmh-temp-high-millicelsius = <95000>;
@@ -3971,7 +3971,7 @@
compatible = "qcom,sdm845-lmh";
reg = <0 0x17d78800 0 0x400>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
- cpus = <&CPU0>;
+ cpus = <&cpu0>;
qcom,lmh-temp-arm-millicelsius = <65000>;
qcom,lmh-temp-low-millicelsius = <94500>;
qcom,lmh-temp-high-millicelsius = <95000>;
@@ -5159,6 +5159,7 @@
<GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
anoc_1_tbu: tbu@150c5000 {
@@ -5277,7 +5278,7 @@
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
diff --git a/arch/arm64/boot/dts/qcom/sdx75.dtsi b/arch/arm64/boot/dts/qcom/sdx75.dtsi
index 7cf3fcb469a8..5f7e59ecf1ca 100644
--- a/arch/arm64/boot/dts/qcom/sdx75.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdx75.dtsi
@@ -43,25 +43,25 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -69,85 +69,85 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
};
@@ -155,7 +155,7 @@
idle-states {
entry-method = "psci";
- CPU_OFF: cpu-sleep-0 {
+ cpu_off: cpu-sleep-0 {
compatible = "arm,idle-state";
entry-latency-us = <235>;
exit-latency-us = <428>;
@@ -164,7 +164,7 @@
local-timer-stop;
};
- CPU_RAIL_OFF: cpu-rail-sleep-1 {
+ cpu_rail_off: cpu-rail-sleep-1 {
compatible = "arm,idle-state";
entry-latency-us = <800>;
exit-latency-us = <750>;
@@ -176,7 +176,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <1050>;
@@ -184,7 +184,7 @@
min-residency-us = <5309>;
};
- CLUSTER_SLEEP_1: cluster-sleep-1 {
+ cluster_sleep_1: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41001344>;
entry-latency-us = <2761>;
@@ -192,7 +192,7 @@
min-residency-us = <8467>;
};
- CLUSTER_SLEEP_2: cluster-sleep-2 {
+ cluster_sleep_2: cluster-sleep-2 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100b344>;
entry-latency-us = <2793>;
@@ -235,33 +235,33 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off &cpu_rail_off>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off &cpu_rail_off>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off &cpu_rail_off>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&cpu_off &cpu_rail_off>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_1 &CLUSTER_SLEEP_2>;
+ domain-idle-states = <&cluster_sleep_0 &cluster_sleep_1 &cluster_sleep_2>;
};
};
@@ -1444,7 +1444,7 @@
<GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
qcom,tcs-offset = <0xd00>;
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 3>,
diff --git a/arch/arm64/boot/dts/qcom/sm4250.dtsi b/arch/arm64/boot/dts/qcom/sm4250.dtsi
index c5add8f44fc0..a0ed61925e12 100644
--- a/arch/arm64/boot/dts/qcom/sm4250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm4250.dtsi
@@ -5,34 +5,34 @@
#include "sm6115.dtsi"
-&CPU0 {
+&cpu0 {
compatible = "qcom,kryo240";
};
-&CPU1 {
+&cpu1 {
compatible = "qcom,kryo240";
};
-&CPU2 {
+&cpu2 {
compatible = "qcom,kryo240";
};
-&CPU3 {
+&cpu3 {
compatible = "qcom,kryo240";
};
-&CPU4 {
+&cpu4 {
compatible = "qcom,kryo240";
};
-&CPU5 {
+&cpu5 {
compatible = "qcom,kryo240";
};
-&CPU6 {
+&cpu6 {
compatible = "qcom,kryo240";
};
-&CPU7 {
+&cpu7 {
compatible = "qcom,kryo240";
};
diff --git a/arch/arm64/boot/dts/qcom/sm4450.dtsi b/arch/arm64/boot/dts/qcom/sm4450.dtsi
index 1e05cd00b635..a0de5fe16faa 100644
--- a/arch/arm64/boot/dts/qcom/sm4450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm4450.dtsi
@@ -46,25 +46,25 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
- L3_0: l3-cache {
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -72,178 +72,178 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_100>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_100>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_200>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_200>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_300>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_300>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x400>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_400>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_400>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x500>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_500>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_500>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "arm,cortex-a78";
reg = <0x0 0x600>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_600>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_600>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "arm,cortex-a78";
reg = <0x0 0x700>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_700>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_700>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -251,7 +251,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
arm,psci-suspend-param = <0x40000004>;
entry-latency-us = <800>;
@@ -260,7 +260,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
arm,psci-suspend-param = <0x40000004>;
entry-latency-us = <600>;
@@ -271,7 +271,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <1050>;
@@ -279,7 +279,7 @@
min-residency-us = <5309>;
};
- CLUSTER_SLEEP_1: cluster-sleep-1 {
+ cluster_sleep_1: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41003344>;
entry-latency-us = <1561>;
@@ -309,57 +309,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>, <&CLUSTER_SLEEP_1>;
+ domain-idle-states = <&cluster_sleep_0>, <&cluster_sleep_1>;
};
};
@@ -579,7 +579,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 0>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi
index 41216cc319d6..9b23534c456b 100644
--- a/arch/arm64/boot/dts/qcom/sm6115.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi
@@ -40,7 +40,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x0>;
@@ -48,18 +48,18 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x1>;
@@ -67,13 +67,13 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x2>;
@@ -81,13 +81,13 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x3>;
@@ -95,13 +95,13 @@
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
};
- CPU4: cpu@100 {
+ cpu4: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x100>;
@@ -109,18 +109,18 @@
enable-method = "psci";
capacity-dmips-mhz = <1638>;
dynamic-power-coefficient = <282>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,freq-domain = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
- L2_1: l2-cache {
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU5: cpu@101 {
+ cpu5: cpu@101 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x101>;
@@ -128,13 +128,13 @@
capacity-dmips-mhz = <1638>;
dynamic-power-coefficient = <282>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,freq-domain = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
};
- CPU6: cpu@102 {
+ cpu6: cpu@102 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x102>;
@@ -142,13 +142,13 @@
capacity-dmips-mhz = <1638>;
dynamic-power-coefficient = <282>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,freq-domain = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
};
- CPU7: cpu@103 {
+ cpu7: cpu@103 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x103>;
@@ -156,46 +156,46 @@
capacity-dmips-mhz = <1638>;
dynamic-power-coefficient = <282>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
qcom,freq-domain = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -203,7 +203,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "silver-rail-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -213,7 +213,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -225,7 +225,7 @@
};
domain-idle-states {
- CLUSTER_0_SLEEP_0: cluster-sleep-0-0 {
+ cluster_0_sleep_0: cluster-sleep-0-0 {
/* GDHS */
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x40000022>;
@@ -234,7 +234,7 @@
min-residency-us = <782>;
};
- CLUSTER_0_SLEEP_1: cluster-sleep-0-1 {
+ cluster_0_sleep_1: cluster-sleep-0-1 {
/* Power Collapse */
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
@@ -243,7 +243,7 @@
min-residency-us = <7376>;
};
- CLUSTER_1_SLEEP_0: cluster-sleep-1-0 {
+ cluster_1_sleep_0: cluster-sleep-1-0 {
/* GDHS */
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x40000042>;
@@ -252,7 +252,7 @@
min-residency-us = <660>;
};
- CLUSTER_1_SLEEP_1: cluster-sleep-1-1 {
+ cluster_1_sleep_1: cluster-sleep-1-1 {
/* Power Collapse */
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
@@ -306,62 +306,62 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_0_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_0_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_1_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_1_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_0_PD: power-domain-cpu-cluster0 {
+ cluster_0_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_0_SLEEP_0>, <&CLUSTER_0_SLEEP_1>;
+ domain-idle-states = <&cluster_0_sleep_0>, <&cluster_0_sleep_1>;
};
- CLUSTER_1_PD: power-domain-cpu-cluster1 {
+ cluster_1_pd: power-domain-cpu-cluster1 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_1_SLEEP_0>, <&CLUSTER_1_SLEEP_1>;
+ domain-idle-states = <&cluster_1_sleep_0>, <&cluster_1_sleep_1>;
};
};
@@ -1178,7 +1178,7 @@
};
};
- ufs_mem_hc: ufs@4804000 {
+ ufs_mem_hc: ufshc@4804000 {
compatible = "qcom,sm6115-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
reg = <0x0 0x04804000 0x0 0x3000>, <0x0 0x04810000 0x0 0x8000>;
reg-names = "std", "ice";
@@ -2405,7 +2405,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
status = "disabled";
@@ -2426,7 +2426,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
status = "disabled";
@@ -2447,7 +2447,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
status = "disabled";
@@ -2468,7 +2468,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
status = "disabled";
@@ -2489,7 +2489,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
status = "disabled";
@@ -2510,7 +2510,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
status = "disabled";
@@ -2531,7 +2531,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
status = "disabled";
@@ -2552,7 +2552,7 @@
clock-names = "apb_pclk";
arm,coresight-loses-context-with-cpu;
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
index 133610d14fc4..17d528d63934 100644
--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -37,122 +37,122 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x0>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
+ next-level-cache = <&l2_0>;
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x1>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x2>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x3>;
enable-method = "psci";
capacity-dmips-mhz = <1024>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU4: cpu@100 {
+ cpu4: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x100>;
enable-method = "psci";
capacity-dmips-mhz = <1638>;
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
+ next-level-cache = <&l2_1>;
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU5: cpu@101 {
+ cpu5: cpu@101 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x101>;
enable-method = "psci";
capacity-dmips-mhz = <1638>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
- CPU6: cpu@102 {
+ cpu6: cpu@102 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x102>;
enable-method = "psci";
capacity-dmips-mhz = <1638>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
- CPU7: cpu@103 {
+ cpu7: cpu@103 {
device_type = "cpu";
compatible = "qcom,kryo260";
reg = <0x0 0x103>;
enable-method = "psci";
capacity-dmips-mhz = <1638>;
- next-level-cache = <&L2_1>;
+ next-level-cache = <&l2_1>;
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -763,7 +763,7 @@
status = "disabled";
};
- ufs_mem_hc: ufs@4804000 {
+ ufs_mem_hc: ufshc@4804000 {
compatible = "qcom,sm6125-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
reg = <0x04804000 0x3000>, <0x04810000 0x8000>;
reg-names = "std", "ice";
diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi
index 7986ddb30f6e..8d697280249f 100644
--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi
@@ -45,7 +45,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x0>;
@@ -53,21 +53,21 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -75,7 +75,7 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x100>;
@@ -83,24 +83,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x200>;
@@ -108,24 +108,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x300>;
@@ -133,24 +133,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x400>;
@@ -158,24 +158,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x500>;
@@ -183,24 +183,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x600>;
@@ -208,24 +208,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1894>;
dynamic-power-coefficient = <703>;
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo560";
reg = <0x0 0x700>;
@@ -233,61 +233,61 @@
enable-method = "psci";
capacity-dmips-mhz = <1894>;
dynamic-power-coefficient = <703>;
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY
&clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
domain-idle-states {
- CLUSTER_SLEEP_PC: cluster-sleep-0 {
+ cluster_sleep_pc: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <2752>;
@@ -295,7 +295,7 @@
min-residency-us = <6118>;
};
- CLUSTER_SLEEP_CX_RET: cluster-sleep-1 {
+ cluster_sleep_cx_ret: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41001244>;
entry-latency-us = <3638>;
@@ -303,7 +303,7 @@
min-residency-us = <8467>;
};
- CLUSTER_AOSS_SLEEP: cluster-sleep-2 {
+ cluster_aoss_sleep: cluster-sleep-2 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100b244>;
entry-latency-us = <3263>;
@@ -315,7 +315,7 @@
cpu_idle_states: idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -325,7 +325,7 @@
local-timer-stop;
};
- LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
+ little_cpu_sleep_1: cpu-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -335,7 +335,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -345,7 +345,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
+ big_cpu_sleep_1: cpu-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -504,59 +504,59 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_PC
- &CLUSTER_SLEEP_CX_RET
- &CLUSTER_AOSS_SLEEP>;
+ domain-idle-states = <&cluster_sleep_pc
+ &cluster_sleep_cx_ret
+ &cluster_aoss_sleep>;
};
};
@@ -1136,7 +1136,7 @@
qcom,bcm-voters = <&apps_bcm_voter>;
};
- ufs_mem_hc: ufs@1d84000 {
+ ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sm6350-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
reg = <0 0x01d84000 0 0x3000>,
@@ -1376,43 +1376,43 @@
opp-850000000 {
opp-hz = /bits/ 64 <850000000>;
opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
- opp-supported-hw = <0x02>;
+ opp-supported-hw = <0x03>;
};
opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
- opp-supported-hw = <0x04>;
+ opp-supported-hw = <0x07>;
};
opp-650000000 {
opp-hz = /bits/ 64 <650000000>;
opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
- opp-supported-hw = <0x08>;
+ opp-supported-hw = <0x0f>;
};
opp-565000000 {
opp-hz = /bits/ 64 <565000000>;
opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
- opp-supported-hw = <0x10>;
+ opp-supported-hw = <0x1f>;
};
opp-430000000 {
opp-hz = /bits/ 64 <430000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
- opp-supported-hw = <0xff>;
+ opp-supported-hw = <0x1f>;
};
opp-355000000 {
opp-hz = /bits/ 64 <355000000>;
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
- opp-supported-hw = <0xff>;
+ opp-supported-hw = <0x1f>;
};
opp-253000000 {
opp-hz = /bits/ 64 <253000000>;
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
- opp-supported-hw = <0xff>;
+ opp-supported-hw = <0x1f>;
};
};
};
@@ -2685,6 +2685,7 @@
<GIC_SPI 411 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 412 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
intc: interrupt-controller@17a00000 {
@@ -2776,7 +2777,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 1>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
rpmhcc: clock-controller {
compatible = "qcom,sm6350-rpmh-clk";
@@ -2953,7 +2954,7 @@
cooling-maps {
map0 {
trip = <&cpu0_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -2978,7 +2979,7 @@
cooling-maps {
map0 {
trip = <&cpu1_alert0>;
- cooling-device = <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3003,7 +3004,7 @@
cooling-maps {
map0 {
trip = <&cpu2_alert0>;
- cooling-device = <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3028,7 +3029,7 @@
cooling-maps {
map0 {
trip = <&cpu3_alert0>;
- cooling-device = <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3053,7 +3054,7 @@
cooling-maps {
map0 {
trip = <&cpu4_alert0>;
- cooling-device = <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3078,7 +3079,7 @@
cooling-maps {
map0 {
trip = <&cpu5_alert0>;
- cooling-device = <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3103,7 +3104,7 @@
cooling-maps {
map0 {
trip = <&cpu6_left_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3128,7 +3129,7 @@
cooling-maps {
map0 {
trip = <&cpu6_right_alert0>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3153,7 +3154,7 @@
cooling-maps {
map0 {
trip = <&cpu7_left_alert0>;
- cooling-device = <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3178,7 +3179,7 @@
cooling-maps {
map0 {
trip = <&cpu7_right_alert0>;
- cooling-device = <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm6375.dtsi b/arch/arm64/boot/dts/qcom/sm6375.dtsi
index 4d519dd6e7ef..e0b1c54e98c0 100644
--- a/arch/arm64/boot/dts/qcom/sm6375.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6375.dtsi
@@ -38,25 +38,25 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -64,185 +64,185 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x400>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x500>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x600>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo660";
reg = <0x0 0x700>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu6_opp_table>;
interconnects = <&cpucp_l3 MASTER_EPSS_L3_APPS &cpucp_l3 SLAVE_EPSS_L3_SHARED>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -250,7 +250,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "silver-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -260,7 +260,7 @@
local-timer-stop;
};
- LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
+ little_cpu_sleep_1: cpu-sleep-0-1 {
compatible = "arm,idle-state";
idle-state-name = "silver-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -270,7 +270,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-power-collapse";
arm,psci-suspend-param = <0x40000003>;
@@ -280,7 +280,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
+ big_cpu_sleep_1: cpu-sleep-1-1 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -292,7 +292,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <2752>;
@@ -455,58 +455,58 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0 &little_cpu_sleep_1>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
power-domains = <&mpm>;
- domain-idle-states = <&CLUSTER_SLEEP_0>;
+ domain-idle-states = <&cluster_sleep_0>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm7125.dtsi b/arch/arm64/boot/dts/qcom/sm7125.dtsi
index 12dd72859a43..a53145a610a3 100644
--- a/arch/arm64/boot/dts/qcom/sm7125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm7125.dtsi
@@ -6,11 +6,11 @@
#include "sc7180.dtsi"
/* SM7125 uses Kryo 465 instead of Kryo 468 */
-&CPU0 { compatible = "qcom,kryo465"; };
-&CPU1 { compatible = "qcom,kryo465"; };
-&CPU2 { compatible = "qcom,kryo465"; };
-&CPU3 { compatible = "qcom,kryo465"; };
-&CPU4 { compatible = "qcom,kryo465"; };
-&CPU5 { compatible = "qcom,kryo465"; };
-&CPU6 { compatible = "qcom,kryo465"; };
-&CPU7 { compatible = "qcom,kryo465"; };
+&cpu0 { compatible = "qcom,kryo465"; };
+&cpu1 { compatible = "qcom,kryo465"; };
+&cpu2 { compatible = "qcom,kryo465"; };
+&cpu3 { compatible = "qcom,kryo465"; };
+&cpu4 { compatible = "qcom,kryo465"; };
+&cpu5 { compatible = "qcom,kryo465"; };
+&cpu6 { compatible = "qcom,kryo465"; };
+&cpu7 { compatible = "qcom,kryo465"; };
diff --git a/arch/arm64/boot/dts/qcom/sm7225.dtsi b/arch/arm64/boot/dts/qcom/sm7225.dtsi
index b7b4044e9bb0..a8ffdfb254fe 100644
--- a/arch/arm64/boot/dts/qcom/sm7225.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm7225.dtsi
@@ -6,14 +6,14 @@
#include "sm6350.dtsi"
/* SM7225 uses Kryo 570 instead of Kryo 560 */
-&CPU0 { compatible = "qcom,kryo570"; };
-&CPU1 { compatible = "qcom,kryo570"; };
-&CPU2 { compatible = "qcom,kryo570"; };
-&CPU3 { compatible = "qcom,kryo570"; };
-&CPU4 { compatible = "qcom,kryo570"; };
-&CPU5 { compatible = "qcom,kryo570"; };
-&CPU6 { compatible = "qcom,kryo570"; };
-&CPU7 { compatible = "qcom,kryo570"; };
+&cpu0 { compatible = "qcom,kryo570"; };
+&cpu1 { compatible = "qcom,kryo570"; };
+&cpu2 { compatible = "qcom,kryo570"; };
+&cpu3 { compatible = "qcom,kryo570"; };
+&cpu4 { compatible = "qcom,kryo570"; };
+&cpu5 { compatible = "qcom,kryo570"; };
+&cpu6 { compatible = "qcom,kryo570"; };
+&cpu7 { compatible = "qcom,kryo570"; };
&cpu0_opp_table {
opp-1804800000 {
diff --git a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts
new file mode 100644
index 000000000000..a5cda478bd78
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts
@@ -0,0 +1,1260 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Eugene Lepshy <fekz115@gmail.com>
+ * Copyright (c) 2024, Danila Tikhonov <danila@jiaxyga.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/arm/qcom,ids.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/iio/qcom,spmi-adc7-pm7325.h>
+#include <dt-bindings/iio/qcom,spmi-adc7-pm8350b.h>
+#include <dt-bindings/iio/qcom,spmi-adc7-pmk8350.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+
+#include "sm7325.dtsi"
+#include "pm7325.dtsi"
+#include "pm8350b.dtsi" /* PM7325B */
+#include "pm8350c.dtsi" /* PM7350C */
+#include "pmk8350.dtsi" /* PMK7325 */
+
+/delete-node/ &rmtfs_mem;
+
+/ {
+ model = "Nothing Phone (1)";
+ compatible = "nothing,spacewar", "qcom,sm7325";
+ chassis-type = "handset";
+
+ aliases {
+ bluetooth0 = &bluetooth;
+ serial0 = &uart5;
+ serial1 = &uart7;
+ wifi0 = &wifi;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0:115200n8";
+
+ framebuffer0: framebuffer@e1000000 {
+ compatible = "simple-framebuffer";
+ reg = <0x0 0xe1000000 0x0 (1080 * 2400 * 4)>;
+ width = <1080>;
+ height = <2400>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&kypd_volp_n>;
+ pinctrl-names = "default";
+
+ key-volume-up {
+ label = "Volume up";
+ gpios = <&pm7325_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+
+ pmic-glink {
+ compatible = "qcom,sm7325-pmic-glink",
+ "qcom,qcm6490-pmic-glink",
+ "qcom,pmic-glink";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ orientation-gpios = <&tlmm 140 GPIO_ACTIVE_HIGH>;
+
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_hs_in: endpoint {
+ remote-endpoint = <&usb_1_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_sbu: endpoint {
+ remote-endpoint = <&fsa4480_sbu_mux>;
+ };
+ };
+ };
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ramoops_mem: ramoops@83a00000 {
+ compatible = "ramoops";
+ reg = <0x0 0x83a00000 0x0 0x400000>;
+ pmsg-size = <0x200000>;
+ mem-type = <2>;
+ console-size = <0x200000>;
+ };
+
+ cdsp_mem: cdsp@88f00000 {
+ reg = <0x0 0x88f00000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ removed_mem: removed@c0000000 {
+ reg = <0x0 0xc0000000 0x0 0x5100000>;
+ no-map;
+ };
+
+ cont_splash_mem: cont-splash@e1000000 {
+ reg = <0x0 0xe1000000 0x0 (1080 * 2400 * 4)>;
+ no-map;
+ };
+
+ rmtfs_mem: rmtfs@f8500000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0xf8500000 0x0 0x600000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <QCOM_SCM_VMID_MSS_MSA>,
+ <QCOM_SCM_VMID_NAV>;
+ };
+ };
+
+ thermal-zones {
+ camera-thermal {
+ polling-delay-passive = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 2>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ chg-skin-thermal {
+ polling-delay-passive = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 6>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ conn-thermal {
+ polling-delay-passive = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 5>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ quiet-thermal {
+ polling-delay-passive = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 1>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ rear-cam-thermal {
+ polling-delay-passive = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 4>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ sdm-skin-thermal {
+ polling-delay-passive = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 3>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ xo-thermal {
+ polling-delay-passive = <0>;
+ thermal-sensors = <&pmk8350_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ };
+
+ // S2B is really ebi.lvl but it's there for supply map completeness sake.
+ vreg_s2b_0p7: smpa3-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_s2b_0p7";
+
+ regulator-min-microvolt = <65535>;
+ regulator-max-microvolt = <65535>;
+ regulator-always-on;
+ vin-supply = <&vph_pwr>;
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm7325-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+
+ vdd-l1-l4-l12-l15-supply = <&vreg_s7b_0p952>;
+ vdd-l2-l7-supply = <&vreg_bob>;
+ vdd-l3-supply = <&vreg_s2b_0p7>;
+ vdd-l5-supply = <&vreg_s2b_0p7>;
+ vdd-l6-l9-l10-supply = <&vreg_s8b_1p256>;
+ vdd-l8-supply = <&vreg_s7b_0p952>;
+ vdd-l11-l17-l18-l19-supply = <&vreg_s1b_1p856>;
+ vdd-l13-supply = <&vreg_s7b_0p952>;
+ vdd-l14-l16-supply = <&vreg_s8b_1p256>;
+
+ /*
+ * S2, L4-L5 are ARCs:
+ * S2 - ebi.lvl,
+ * L4 - lmx.lvl,
+ * l5 - lcx.lvl.
+ *
+ * L10 are unused.
+ */
+
+ vdd19_pmu_rfa_i:
+ vreg_s1b_1p856: smps1 {
+ regulator-name = "vreg_s1b_1p856";
+ regulator-min-microvolt = <1840000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vdd_pmu_aon_i:
+ vdd09_pmu_rfa_i:
+ vdd095_mx_pmu:
+ vdd095_pmu_1:
+ vdd095_pmu_2:
+ vreg_s7b_0p952: smps7 {
+ regulator-name = "vreg_s7b_0p952";
+ regulator-min-microvolt = <535000>;
+ regulator-max-microvolt = <1120000>;
+ };
+
+ vdd13_pmu_rfa_i:
+ vreg_s8b_1p256: smps8 {
+ regulator-name = "vreg_s8b_1p256";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_RET>;
+ };
+
+ vreg_l1b_0p912: ldo1 {
+ regulator-name = "vreg_l1b_0p912";
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <925000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_a_usbhs_3p1:
+ vreg_l2b_3p072: ldo2 {
+ regulator-name = "vreg_l2b_3p072";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_io_ebi0_1:
+ vdd_io_ebi0_2:
+ vdd_io_ebi0_3:
+ vdd_io_ebi0_4:
+ vdd_io_ebi1_1:
+ vdd_io_ebi1_2:
+ vdd_io_ebi1_3:
+ vdd_io_ebi1_4:
+ vreg_l3b_0p6: ldo3 {
+ regulator-name = "vreg_l3b_0p6";
+ regulator-min-microvolt = <312000>;
+ regulator-max-microvolt = <910000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_a_csi_01_1p2:
+ vdd_a_csi_23_1p2:
+ vdd_a_csi_4_1p2:
+ vdd_a_dsi_0_1p2:
+ vdd_a_qlink_0_1p2_ck:
+ vdd_a_qlink_1_1p2:
+ vdd_a_ufs_0_1p2:
+ vdd_vref_1p2_1:
+ vdd_vref_1p2_2:
+ vreg_l6b_1p2: ldo6 {
+ regulator-name = "vreg_l6b_1p2";
+ regulator-min-microvolt = <1140000>;
+ regulator-max-microvolt = <1260000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7b_2p96: ldo7 {
+ regulator-name = "vreg_l7b_2p96";
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b_0p904: ldo8 {
+ regulator-name = "vreg_l8b_0p904";
+ regulator-min-microvolt = <870000>;
+ regulator-max-microvolt = <970000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_px10:
+ vreg_l9b_1p2: ldo9 {
+ regulator-name = "vreg_l9b_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddah_0:
+ vddah_1:
+ vddah_fbrx:
+ vddah_tx0:
+ vddah_tx0_1:
+ vddah_tx1:
+ vddah_tx1_1:
+ vreg_l11b_1p776: ldo11 {
+ regulator-name = "vreg_l11b_1p776";
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddal_dig0:
+ vddal_dig_1:
+ vddal_dig_2:
+ vddal_dig_xo:
+ vddal_gps_l1:
+ vddal_gps_l5:
+ vddal_icon:
+ vddal_rx:
+ vddal_rx0:
+ vddal_rx1:
+ vddal_rx2:
+ vddal_tx0:
+ vddal_tx0_1:
+ vddal_tx1:
+ vddal_tx1_2:
+ vreg_l12b_0p8: ldo12 {
+ regulator-name = "vreg_l12b_0p8";
+ regulator-min-microvolt = <751000>;
+ regulator-max-microvolt = <824000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_cx1:
+ vdd_cx2:
+ vreg_l13b_0p8: ldo13 {
+ regulator-name = "vreg_l13b_0p8";
+ regulator-min-microvolt = <530000>;
+ regulator-max-microvolt = <824000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_1p2:
+ vdd_lna:
+ vddam_fbrx:
+ vddam_rx_0:
+ vddam_rx_1:
+ vddam_rx0:
+ vddam_rx1:
+ vddam_rx2:
+ vddam_rxe_a:
+ vddam_rxe_b:
+ vddam_rxe_c:
+ vddam_rxe_d:
+ vddam_rxe_e:
+ vddam_tx0:
+ vddam_tx0_1:
+ vddam_tx1:
+ vddam_tx1_1:
+ vddam_xo:
+ vreg_l14b_1p2: ldo14 {
+ regulator-name = "vreg_l14b_1p2";
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_mx:
+ vddmx_tx:
+ vdd_phy:
+ vreg_l15b_0p88: ldo15 {
+ regulator-name = "vreg_l15b_0p88";
+ regulator-min-microvolt = <765000>;
+ regulator-max-microvolt = <1020000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16b_1p2: ldo16 {
+ regulator-name = "vreg_l16b_1p2";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_buck:
+ vreg_l17b_1p8: ldo17 {
+ regulator-name = "vreg_l17b_1p8";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_px_wcd9385:
+ vdd_txrx:
+ vdd_px0:
+ vdd_px3:
+ vdd_px7:
+ vreg_l18b_1p8: ldo18 {
+ regulator-name = "vreg_l18b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_1p8:
+ vdd_px_sdr735:
+ vdd_pxm:
+ vddio_px_1:
+ vddio_px_2:
+ vddio_px_3:
+ vdd18_io:
+ vddpx_ts:
+ vddpx_wl4otp:
+ vreg_l19b_1p8: ldo19 {
+ regulator-name = "vreg_l19b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8350c-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+
+ vdd-l1-l12-supply = <&vreg_s1b_1p856>;
+ vdd-l2-l8-supply = <&vreg_s1b_1p856>;
+ vdd-l3-l4-l5-l7-l13-supply = <&vreg_bob>;
+ vdd-l6-l9-l11-supply = <&vreg_bob>;
+ vdd-l10-supply = <&vreg_s7b_0p952>;
+
+ vdd-bob-supply = <&vph_pwr>;
+
+ /*
+ * S2, S5, S7, S10 are ARCs:
+ * S2 - cx.lvl,
+ * S5 - mss.lvl,
+ * S7 - gfx.lvl,
+ * S10 - mx.lvl.
+ */
+
+ vdd22_wlbtpa_ch0:
+ vdd22_wlbtpa_ch1:
+ vdd22_wlbtppa_ch0:
+ vdd22_wlbtppa_ch1:
+ vdd22_wlpa5g_ch0:
+ vdd22_wlpa5g_ch1:
+ vdd22_wlppa5g_ch0:
+ vdd22_wlppa5g_ch1:
+ vreg_s1c_2p2: smps1 {
+ regulator-name = "vreg_s1c_2p2";
+ regulator-min-microvolt = <2190000>;
+ regulator-max-microvolt = <2210000>;
+ };
+
+ vdd_px1:
+ vreg_s9c_0p676: smps9 {
+ regulator-name = "vreg_s9c_0p676";
+ regulator-min-microvolt = <1010000>;
+ regulator-max-microvolt = <1170000>;
+ };
+
+ vdd_a_apc_cs_1p8:
+ vdd_a_cxo_1p8:
+ vdd_a_gfx_cs_1p8:
+ vdd_a_qrefs_1p8:
+ vdd_a_turing_q6_cs_1p8:
+ vdd_a_usbhs_1p8:
+ vdd_qfprom:
+ vreg_l1c_1p8: ldo1 {
+ regulator-name = "vreg_l1c_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c_1p8: ldo2 {
+ regulator-name = "vreg_l2c_1p8";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_ts:
+ vreg_l3c_3p0: ldo3 {
+ regulator-name = "vreg_l3c_3p0";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3540000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_px5:
+ vreg_l4c_1p8_3p0: ldo4 {
+ regulator-name = "vreg_l4c_1p8_3p0";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_px6:
+ vreg_l5c_1p8_3p0: ldo5 {
+ regulator-name = "vreg_l5c_1p8_3p0";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_px2:
+ vreg_l6c_2p96: ldo6 {
+ regulator-name = "vreg_l6c_2p96";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_sensor_3p3:
+ vreg_l7c_3p0: ldo7 {
+ regulator-name = "vreg_l7c_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_sensor_1p8:
+ vreg_l8c_1p8: ldo8 {
+ regulator-name = "vreg_l8c_1p8";
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9c_2p96: ldo9 {
+ regulator-name = "vreg_l9c_2p96";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_a_csi_01_0p9:
+ vdd_a_csi_23_0p9:
+ vdd_a_csi_4_0p9:
+ vdd_a_dsi_0_0p9:
+ vdd_a_dsi_0_pll_0p9:
+ vdd_a_gnss_0p9:
+ vdd_a_qlink_0_0p9:
+ vdd_a_qlink_0_0p9_ck:
+ vdd_a_qlink_1_0p9:
+ vdd_a_qlink_1_0p9_ck:
+ vdd_a_qrefs_0p875_1:
+ vdd_a_qrefs_0p875_2:
+ vdd_a_qrefs_0p875_3:
+ vdd_a_qrefs_0p875_4:
+ vdd_a_qrefs_0p875_5:
+ vdd_a_qrefs_0p875_6:
+ vdd_a_qrefs_0p875_7:
+ vdd_a_qrefs_0p875_8:
+ vdd_a_qrefs_0p875_9:
+ vdd_a_ufs_0_core:
+ vdd_a_usbhs_core:
+ vdd_vref_0p9:
+ vreg_l10c_0p88: ldo10 {
+ regulator-name = "vreg_l10c_0p88";
+ regulator-min-microvolt = <720000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_fm:
+ vdd_wlan_fem:
+ vreg_l11c_2p8: ldo11 {
+ regulator-name = "vreg_l11c_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_io_oled:
+ vreg_l12c_1p8: ldo12 {
+ regulator-name = "vreg_l12c_1p8";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_oled:
+ vreg_l13c_3p0: ldo13 {
+ regulator-name = "vreg_l13c_3p0";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_flash:
+ vdd_mic_bias:
+ vreg_bob: bob {
+ regulator-name = "vreg_bob";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+ };
+};
+
+&cci0 {
+ status = "okay";
+};
+
+&cci0_i2c0 {
+ /* sony,imx471 (Front) */
+};
+
+&cci1 {
+ status = "okay";
+};
+
+&cci1_i2c0 {
+ /* samsung,s5kjn1 (Rear-aux UW) */
+};
+
+&cci1_i2c1 {
+ /* sony,imx766 (Rear Wide) */
+};
+
+&gcc {
+ protected-clocks = <GCC_CFG_NOC_LPASS_CLK>,
+ <GCC_MSS_CFG_AHB_CLK>,
+ <GCC_MSS_OFFLINE_AXI_CLK>,
+ <GCC_MSS_Q6SS_BOOT_CLK_SRC>,
+ <GCC_MSS_Q6_MEMNOC_AXI_CLK>,
+ <GCC_MSS_SNOC_AXI_CLK>,
+ <GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
+ <GCC_QSPI_CORE_CLK>,
+ <GCC_QSPI_CORE_CLK_SRC>,
+ <GCC_SEC_CTRL_CLK_SRC>,
+ <GCC_WPSS_AHB_BDG_MST_CLK>,
+ <GCC_WPSS_AHB_CLK>,
+ <GCC_WPSS_RSCP_CLK>;
+};
+
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&gpu_zap_shader {
+ firmware-name = "qcom/sm7325/nothing/spacewar/a660_zap.mbn";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ status = "okay";
+
+ /* awinic,aw21018 (Glyph LED) @ 20 */
+
+ typec-mux@42 {
+ compatible = "fcs,fsa4480";
+ reg = <0x42>;
+
+ vcc-supply = <&vreg_bob>;
+
+ mode-switch;
+ orientation-switch;
+
+ port {
+ fsa4480_sbu_mux: endpoint {
+ remote-endpoint = <&pmic_glink_sbu>;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ status = "okay";
+
+ /* nxp,tfa9873 (EAR speaker codec) @ 34 */
+ /* nxp,tfa9873 (Main speaker codec) @ 35 */
+};
+
+&i2c9 {
+ clock-frequency = <1000000>;
+ status = "okay";
+
+ nfc@28 {
+ compatible = "nxp,pn553",
+ "nxp,nxp-nci-i2c";
+ reg = <0x28>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <41 IRQ_TYPE_EDGE_RISING>;
+
+ enable-gpios = <&tlmm 38 GPIO_ACTIVE_HIGH>;
+ firmware-gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-0 = <&nfc_en>,
+ <&nfc_clk_req>,
+ <&nfc_dwl_req>,
+ <&nfc_int_req>;
+ pinctrl-names = "default";
+ };
+};
+
+&ipa {
+ qcom,gsi-loader = "self";
+ memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/sm7325/nothing/spacewar/ipa_fws.mbn";
+
+ status = "okay";
+};
+
+/* MDSS remains disabled until the panel driver is present. */
+&mdss_dsi {
+ vdda-supply = <&vdd_a_dsi_0_1p2>;
+
+ /* Visionox RM692E5 panel */
+};
+
+&mdss_dsi_phy {
+ vdds-supply = <&vdd_a_dsi_0_0p9>;
+};
+
+&pm7325_gpios {
+ gpio-line-names = "NC", /* GPIO_1 */
+ "PA_THERM3",
+ "PA_THERM4",
+ "NC",
+ "NC",
+ "KYPD_VOLP_N",
+ "NC",
+ "NC",
+ "NC",
+ "NC"; /* GPIO_10 */
+
+ kypd_volp_n: kypd-volp-n-state {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ bias-pull-up;
+ input-enable;
+ power-source = <1>;
+ };
+};
+
+&pm8350c_flash {
+ status = "okay";
+
+ led-0 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ led-sources = <1>, <4>;
+ led-max-microamp = <500000>;
+ flash-max-microamp = <1500000>;
+ flash-max-timeout-us = <1280000>;
+ };
+};
+
+&pmk8350_adc_tm {
+ status = "okay";
+
+ /* PMK8350 */
+ xo-therm@0 {
+ reg = <0>;
+ io-channels = <&pmk8350_vadc PMK8350_ADC7_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ /* PM7325 */
+ quiet-therm@1 {
+ reg = <1>;
+ io-channels = <&pmk8350_vadc PM7325_ADC7_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ cam-flash-therm@2 {
+ reg = <2>;
+ io-channels = <&pmk8350_vadc PM7325_ADC7_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ sdm-skin-therm@3 {
+ reg = <3>;
+ io-channels = <&pmk8350_vadc PM7325_ADC7_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ wide-rfc-therm@4 {
+ reg = <4>;
+ io-channels = <&pmk8350_vadc PM7325_ADC7_AMUX_THM4_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ /* PM8350B */
+ usb-conn-therm@5 {
+ reg = <5>;
+ io-channels = <&pmk8350_vadc PM8350B_ADC7_AMUX_THM4_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ chg-skin-therm@6 {
+ reg = <6>;
+ io-channels = <&pmk8350_vadc PM8350B_ADC7_GPIO2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pmk8350_rtc {
+ status = "okay";
+};
+
+&pmk8350_vadc {
+ /* PMK8350 */
+ channel@44 {
+ reg = <PMK8350_ADC7_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pmk8350_xo_therm";
+ };
+
+ /* PM7325 */
+ channel@144 {
+ reg = <PM7325_ADC7_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm7325_quiet_therm";
+ };
+
+ channel@145 {
+ reg = <PM7325_ADC7_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm7325_cam_flash_therm";
+ };
+
+ channel@146 {
+ reg = <PM7325_ADC7_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm7325_sdm_skin_therm";
+ };
+
+ channel@147 {
+ reg = <PM7325_ADC7_AMUX_THM4_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm7325_wide_rfc_therm";
+ };
+
+ channel@14a {
+ reg = <PM7325_ADC7_GPIO1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm7325_pa3_therm";
+ };
+
+ channel@14b {
+ reg = <PM7325_ADC7_GPIO2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm7325_pa4_therm";
+ };
+
+ /* PM8350B */
+ channel@344 {
+ reg = <PM8350B_ADC7_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm8350b_batt_therm";
+ };
+
+ channel@347 {
+ reg = <PM8350B_ADC7_AMUX_THM4_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm8350b_usb_conn_therm";
+ };
+
+ channel@34b {
+ reg = <PM8350B_ADC7_GPIO2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm8350b_chg_skin_therm";
+ };
+
+ channel@34c {
+ reg = <PM8350B_ADC7_GPIO3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ label = "pm8350b_usb_therm2";
+ };
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&q6afedai {
+ dai@16 {
+ reg = <PRIMARY_MI2S_RX>;
+ qcom,sd-lines = <1>;
+ };
+};
+
+&q6asmdai {
+ dai@0 {
+ reg = <0>;
+ };
+};
+
+&qfprom {
+ vcc-supply = <&vdd_qfprom>;
+};
+
+&qup_uart5_rx {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_uart5_tx {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/sm7325/nothing/spacewar/adsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/sm7325/nothing/spacewar/cdsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_mpss {
+ firmware-name = "qcom/sm7325/nothing/spacewar/modem.mbn";
+ status = "okay";
+};
+
+&remoteproc_wpss {
+ firmware-name = "qcom/sm7325/nothing/spacewar/wpss.mbn";
+ status = "okay";
+};
+
+&spi13 {
+ status = "okay";
+
+ /* focaltech,ft3680 (Touchscreen) @ 0 */
+};
+
+&tlmm {
+ /* 56-59: Fingerprint reader (SPI) */
+ gpio-reserved-ranges = <56 4>;
+
+ bt_uart_sleep_cts: bt-uart-sleep-cts-state {
+ pins = "gpio28";
+ function = "gpio";
+ bias-bus-hold;
+ };
+
+ bt_uart_sleep_rts: bt-uart-sleep-rts-state {
+ pins = "gpio29";
+ function = "gpio";
+ bias-pull-down;
+ };
+
+ bt_uart_sleep_txd: bt-uart-sleep-txd-state {
+ pins = "gpio30";
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ bt_uart_sleep_rxd: bt-uart-sleep-rxd-state {
+ pins = "gpio31";
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ nfc_en: nfc-en-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ nfc_clk_req: nfc-clk-req-state {
+ pins = "gpio39";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ nfc_dwl_req: nfc-dwl-req-state {
+ pins = "gpio40";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ nfc_int_req: nfc-int-req-state {
+ pins = "gpio41";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ hst_bt_en: hst-bt-en-state {
+ pins = "gpio85";
+ function = "gpio";
+ output-low;
+ bias-disable;
+ };
+
+ hst_sw_ctrl: hst-sw-ctrl-state {
+ pins = "gpio86";
+ function = "gpio";
+ bias-pull-down;
+ };
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&uart7 {
+ /delete-property/interrupts;
+ interrupts-extended = <&intc GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>,
+ <&tlmm 31 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-1 = <&bt_uart_sleep_cts>,
+ <&bt_uart_sleep_rts>,
+ <&bt_uart_sleep_txd>,
+ <&bt_uart_sleep_rxd>;
+ pinctrl-names = "default", "sleep";
+
+ status = "okay";
+
+ bluetooth: bluetooth {
+ compatible = "qcom,wcn6750-bt";
+
+ pinctrl-0 = <&hst_bt_en>,
+ <&hst_sw_ctrl>;
+ pinctrl-names = "default";
+
+ enable-gpios = <&tlmm 85 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 86 GPIO_ACTIVE_HIGH>;
+
+ vddio-supply = <&vreg_l19b_1p8>;
+ vddaon-supply = <&vreg_s7b_0p952>;
+ vddbtcxmx-supply = <&vreg_s7b_0p952>;
+ vddrfacmn-supply = <&vreg_s7b_0p952>;
+ vddrfa0p8-supply = <&vreg_s7b_0p952>;
+ vddrfa1p7-supply = <&vdd19_pmu_rfa_i>;
+ vddrfa1p2-supply = <&vdd13_pmu_rfa_i>;
+ vddrfa2p2-supply = <&vreg_s1c_2p2>;
+ vddasd-supply = <&vreg_l11c_2p8>;
+ max-speed = <3200000>;
+
+ qcom,local-bd-address-broken;
+ };
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 175 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l7b_2p96>;
+ vcc-max-microamp = <800000>;
+ /*
+ * Technically l9b enables an eLDO (supplied by s1b) which then powers
+ * VCCQ2 of the UFS.
+ */
+ vccq-supply = <&vreg_l9b_1p2>;
+ vccq-max-microamp = <900000>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vdd_a_ufs_0_core>;
+ vdda-pll-supply = <&vdd_a_ufs_0_1p2>;
+ status = "okay";
+};
+
+&usb_1 {
+ /* USB 2.0 only */
+ qcom,select-utmi-as-pipe-clk;
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "otg";
+ usb-role-switch;
+ maximum-speed = "high-speed";
+ /* Remove USB3 phy */
+ phys = <&usb_1_hsphy>;
+ phy-names = "usb2-phy";
+};
+
+&usb_1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_hs_in>;
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&vdd_a_usbhs_core>;
+ vdda18-supply = <&vdd_a_usbhs_1p8>;
+ vdda33-supply = <&vdd_a_usbhs_3p1>;
+ status = "okay";
+};
+
+&venus {
+ firmware-name = "qcom/sm7325/nothing/spacewar/vpu20_1v.mbn";
+ status = "okay";
+};
+
+&wifi {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm7325.dtsi b/arch/arm64/boot/dts/qcom/sm7325.dtsi
new file mode 100644
index 000000000000..85d34b53e5e9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm7325.dtsi
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024, Eugene Lepshy <fekz115@gmail.com>
+ * Copyright (c) 2024, Danila Tikhonov <danila@jiaxyga.com>
+ */
+
+#include "sc7280.dtsi"
+
+/* SM7325 uses Kryo 670 */
+&cpu0 { compatible = "qcom,kryo670"; };
+&cpu1 { compatible = "qcom,kryo670"; };
+&cpu2 { compatible = "qcom,kryo670"; };
+&cpu3 { compatible = "qcom,kryo670"; };
+&cpu4 { compatible = "qcom,kryo670"; };
+&cpu5 { compatible = "qcom,kryo670"; };
+&cpu6 { compatible = "qcom,kryo670"; };
+&cpu7 { compatible = "qcom,kryo670"; };
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 27f87835bc55..cedae8d03a51 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -48,7 +48,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x0>;
@@ -56,20 +56,20 @@
enable-method = "psci";
capacity-dmips-mhz = <488>;
dynamic-power-coefficient = <232>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -77,7 +77,7 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x100>;
@@ -85,23 +85,23 @@
enable-method = "psci";
capacity-dmips-mhz = <488>;
dynamic-power-coefficient = <232>;
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x200>;
@@ -109,23 +109,23 @@
enable-method = "psci";
capacity-dmips-mhz = <488>;
dynamic-power-coefficient = <232>;
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x300>;
@@ -133,23 +133,23 @@
enable-method = "psci";
capacity-dmips-mhz = <488>;
dynamic-power-coefficient = <232>;
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x400>;
@@ -157,23 +157,23 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <369>;
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x500>;
@@ -181,23 +181,23 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <369>;
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x600>;
@@ -205,23 +205,23 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <369>;
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x700>;
@@ -229,54 +229,54 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <421>;
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
qcom,freq-domain = <&cpufreq_hw 2>;
operating-points-v2 = <&cpu7_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -284,7 +284,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "little-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -294,7 +294,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "big-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -306,7 +306,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c244>;
entry-latency-us = <3263>;
@@ -628,57 +628,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>;
+ domain-idle-states = <&cluster_sleep_0>;
};
};
@@ -3096,7 +3096,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07040000 0 0x1000>;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3116,7 +3116,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07140000 0 0x1000>;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3136,7 +3136,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07240000 0 0x1000>;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3156,7 +3156,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07340000 0 0x1000>;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3176,7 +3176,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07440000 0 0x1000>;
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3196,7 +3196,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07540000 0 0x1000>;
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3216,7 +3216,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07640000 0 0x1000>;
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3236,7 +3236,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07740000 0 0x1000>;
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -4296,6 +4296,7 @@
<GIC_SPI 407 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 409 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
remoteproc_adsp: remoteproc@17300000 {
@@ -4457,7 +4458,7 @@
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
rpmhcc: clock-controller {
compatible = "qcom,sm8150-rpmh-clk";
@@ -4553,7 +4554,7 @@
compatible = "qcom,sm8150-lmh";
reg = <0 0x18350800 0 0x400>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
- cpus = <&CPU4>;
+ cpus = <&cpu4>;
qcom,lmh-temp-arm-millicelsius = <60000>;
qcom,lmh-temp-low-millicelsius = <84500>;
qcom,lmh-temp-high-millicelsius = <85000>;
@@ -4565,7 +4566,7 @@
compatible = "qcom,sm8150-lmh";
reg = <0 0x18358800 0 0x400>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
- cpus = <&CPU0>;
+ cpus = <&cpu0>;
qcom,lmh-temp-arm-millicelsius = <60000>;
qcom,lmh-temp-low-millicelsius = <84500>;
qcom,lmh-temp-high-millicelsius = <85000>;
@@ -4634,17 +4635,17 @@
cooling-maps {
map0 {
trip = <&cpu0_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu0_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4677,17 +4678,17 @@
cooling-maps {
map0 {
trip = <&cpu1_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu1_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4720,17 +4721,17 @@
cooling-maps {
map0 {
trip = <&cpu2_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu2_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4763,17 +4764,17 @@
cooling-maps {
map0 {
trip = <&cpu3_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu3_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -4806,17 +4807,17 @@
cooling-maps {
map0 {
trip = <&cpu4_top_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>;
+ 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 = <&cpu4_top_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>;
+ 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>;
};
};
};
@@ -4849,17 +4850,17 @@
cooling-maps {
map0 {
trip = <&cpu5_top_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>;
+ 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 = <&cpu5_top_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>;
+ 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>;
};
};
};
@@ -4892,17 +4893,17 @@
cooling-maps {
map0 {
trip = <&cpu6_top_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>;
+ 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 = <&cpu6_top_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>;
+ 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>;
};
};
};
@@ -4935,17 +4936,17 @@
cooling-maps {
map0 {
trip = <&cpu7_top_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>;
+ 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 = <&cpu7_top_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>;
+ 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>;
};
};
};
@@ -4978,17 +4979,17 @@
cooling-maps {
map0 {
trip = <&cpu4_bottom_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>;
+ 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 = <&cpu4_bottom_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>;
+ 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>;
};
};
};
@@ -5021,17 +5022,17 @@
cooling-maps {
map0 {
trip = <&cpu5_bottom_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>;
+ 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 = <&cpu5_bottom_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>;
+ 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>;
};
};
};
@@ -5064,17 +5065,17 @@
cooling-maps {
map0 {
trip = <&cpu6_bottom_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>;
+ 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 = <&cpu6_bottom_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>;
+ 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>;
};
};
};
@@ -5107,17 +5108,17 @@
cooling-maps {
map0 {
trip = <&cpu7_bottom_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>;
+ 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 = <&cpu7_bottom_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>;
+ 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>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index 630f4eff20bf..48318ed1ce98 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -93,7 +93,7 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x0>;
@@ -101,21 +101,21 @@
enable-method = "psci";
capacity-dmips-mhz = <448>;
dynamic-power-coefficient = <105>;
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x20000>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-size = <0x400000>;
@@ -124,7 +124,7 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x100>;
@@ -132,24 +132,24 @@
enable-method = "psci";
capacity-dmips-mhz = <448>;
dynamic-power-coefficient = <105>;
- next-level-cache = <&L2_100>;
- power-domains = <&CPU_PD1>;
+ next-level-cache = <&l2_100>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x20000>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x200>;
@@ -157,24 +157,24 @@
enable-method = "psci";
capacity-dmips-mhz = <448>;
dynamic-power-coefficient = <105>;
- next-level-cache = <&L2_200>;
- power-domains = <&CPU_PD2>;
+ next-level-cache = <&l2_200>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x20000>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x300>;
@@ -182,24 +182,24 @@
enable-method = "psci";
capacity-dmips-mhz = <448>;
dynamic-power-coefficient = <105>;
- next-level-cache = <&L2_300>;
- power-domains = <&CPU_PD3>;
+ next-level-cache = <&l2_300>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x20000>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x400>;
@@ -207,24 +207,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <379>;
- next-level-cache = <&L2_400>;
- power-domains = <&CPU_PD4>;
+ next-level-cache = <&l2_400>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x40000>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x500>;
@@ -232,24 +232,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <379>;
- next-level-cache = <&L2_500>;
- power-domains = <&CPU_PD5>;
+ next-level-cache = <&l2_500>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x40000>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x600>;
@@ -257,24 +257,24 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <379>;
- next-level-cache = <&L2_600>;
- power-domains = <&CPU_PD6>;
+ next-level-cache = <&l2_600>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x40000>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo485";
reg = <0x0 0x700>;
@@ -282,55 +282,55 @@
enable-method = "psci";
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <444>;
- next-level-cache = <&L2_700>;
- power-domains = <&CPU_PD7>;
+ next-level-cache = <&l2_700>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 2>;
operating-points-v2 = <&cpu7_opp_table>;
interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>,
<&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>;
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x80000>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -338,7 +338,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "silver-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -348,7 +348,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -360,7 +360,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c244>;
entry-latency-us = <3264>;
@@ -689,57 +689,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>;
+ domain-idle-states = <&cluster_sleep_0>;
};
};
@@ -3522,7 +3522,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07040000 0 0x1000>;
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3541,7 +3541,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07140000 0 0x1000>;
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3560,7 +3560,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07240000 0 0x1000>;
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3579,7 +3579,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07340000 0 0x1000>;
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3598,7 +3598,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07440000 0 0x1000>;
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3617,7 +3617,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07540000 0 0x1000>;
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3636,7 +3636,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07640000 0 0x1000>;
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -3655,7 +3655,7 @@
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x07740000 0 0x1000>;
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
clocks = <&aoss_qmp>;
clock-names = "apb_pclk";
@@ -6165,7 +6165,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 1>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
rpmhcc: clock-controller {
compatible = "qcom,sm8250-rpmh-clk";
@@ -6302,17 +6302,17 @@
cooling-maps {
map0 {
trip = <&cpu0_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu0_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6345,17 +6345,17 @@
cooling-maps {
map0 {
trip = <&cpu1_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu1_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6388,17 +6388,17 @@
cooling-maps {
map0 {
trip = <&cpu2_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu2_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6431,17 +6431,17 @@
cooling-maps {
map0 {
trip = <&cpu3_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu3_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -6474,17 +6474,17 @@
cooling-maps {
map0 {
trip = <&cpu4_top_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>;
+ 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 = <&cpu4_top_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>;
+ 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>;
};
};
};
@@ -6517,17 +6517,17 @@
cooling-maps {
map0 {
trip = <&cpu5_top_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>;
+ 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 = <&cpu5_top_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>;
+ 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>;
};
};
};
@@ -6560,17 +6560,17 @@
cooling-maps {
map0 {
trip = <&cpu6_top_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>;
+ 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 = <&cpu6_top_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>;
+ 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>;
};
};
};
@@ -6603,17 +6603,17 @@
cooling-maps {
map0 {
trip = <&cpu7_top_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>;
+ 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 = <&cpu7_top_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>;
+ 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>;
};
};
};
@@ -6646,17 +6646,17 @@
cooling-maps {
map0 {
trip = <&cpu4_bottom_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>;
+ 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 = <&cpu4_bottom_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>;
+ 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>;
};
};
};
@@ -6689,17 +6689,17 @@
cooling-maps {
map0 {
trip = <&cpu5_bottom_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>;
+ 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 = <&cpu5_bottom_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>;
+ 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>;
};
};
};
@@ -6732,17 +6732,17 @@
cooling-maps {
map0 {
trip = <&cpu6_bottom_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>;
+ 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 = <&cpu6_bottom_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>;
+ 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>;
};
};
};
@@ -6775,17 +6775,17 @@
cooling-maps {
map0 {
trip = <&cpu7_bottom_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>;
+ 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 = <&cpu7_bottom_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>;
+ 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>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
index 895adce59e75..796cbb58ef6e 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
@@ -382,10 +382,6 @@
firmware-name = "qcom/sm8350/cdsp.mbn";
};
-&dispcc {
- status = "okay";
-};
-
&mdss_dsi0 {
vdda-supply = <&vreg_l6b_1p2>;
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
index 37a2aba0d4ca..877905dfd861 100644
--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
@@ -51,23 +51,23 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -75,171 +75,171 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_100>;
+ next-level-cache = <&l2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a55";
reg = <0x0 0x300>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_300>;
+ next-level-cache = <&l2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "arm,cortex-a78";
reg = <0x0 0x400>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "arm,cortex-a78";
reg = <0x0 0x500>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "arm,cortex-a78";
reg = <0x0 0x600>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "arm,cortex-x1";
reg = <0x0 0x700>;
clocks = <&cpufreq_hw 2>;
enable-method = "psci";
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
qcom,freq-domain = <&cpufreq_hw 2>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -247,7 +247,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "silver-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -257,7 +257,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -269,7 +269,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_APSS_OFF: cluster-sleep-0 {
+ cluster_sleep_apss_off: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <2752>;
@@ -277,7 +277,7 @@
min-residency-us = <6118>;
};
- CLUSTER_SLEEP_AOSS_SLEEP: cluster-sleep-1 {
+ cluster_sleep_aoss_sleep: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c344>;
entry-latency-us = <3263>;
@@ -320,57 +320,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_APSS_OFF &CLUSTER_SLEEP_AOSS_SLEEP>;
+ domain-idle-states = <&cluster_sleep_apss_off &cluster_sleep_aoss_sleep>;
};
};
@@ -3282,6 +3282,7 @@
<GIC_SPI 696 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 697 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 707 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
adsp: remoteproc@17300000 {
@@ -3504,7 +3505,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 0>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
rpmhcc: clock-controller {
compatible = "qcom,sm8350-rpmh-clk";
@@ -3728,17 +3729,17 @@
cooling-maps {
map0 {
trip = <&cpu0_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu0_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3771,17 +3772,17 @@
cooling-maps {
map0 {
trip = <&cpu1_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu1_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3814,17 +3815,17 @@
cooling-maps {
map0 {
trip = <&cpu2_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu2_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3857,17 +3858,17 @@
cooling-maps {
map0 {
trip = <&cpu3_alert0>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map1 {
trip = <&cpu3_alert1>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -3900,17 +3901,17 @@
cooling-maps {
map0 {
trip = <&cpu4_top_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>;
+ 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 = <&cpu4_top_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>;
+ 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>;
};
};
};
@@ -3943,17 +3944,17 @@
cooling-maps {
map0 {
trip = <&cpu5_top_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>;
+ 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 = <&cpu5_top_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>;
+ 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>;
};
};
};
@@ -3986,17 +3987,17 @@
cooling-maps {
map0 {
trip = <&cpu6_top_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>;
+ 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 = <&cpu6_top_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>;
+ 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>;
};
};
};
@@ -4029,17 +4030,17 @@
cooling-maps {
map0 {
trip = <&cpu7_top_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>;
+ 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 = <&cpu7_top_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>;
+ 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>;
};
};
};
@@ -4072,17 +4073,17 @@
cooling-maps {
map0 {
trip = <&cpu4_bottom_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>;
+ 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 = <&cpu4_bottom_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>;
+ 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>;
};
};
};
@@ -4115,17 +4116,17 @@
cooling-maps {
map0 {
trip = <&cpu5_bottom_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>;
+ 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 = <&cpu5_bottom_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>;
+ 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>;
};
};
};
@@ -4158,17 +4159,17 @@
cooling-maps {
map0 {
trip = <&cpu6_bottom_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>;
+ 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 = <&cpu6_bottom_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>;
+ 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>;
};
};
};
@@ -4201,17 +4202,17 @@
cooling-maps {
map0 {
trip = <&cpu7_bottom_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>;
+ 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 = <&cpu7_bottom_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>;
+ 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>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
index a754b8fe9167..2ff40a120aad 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
@@ -26,6 +26,7 @@
aliases {
serial0 = &uart7;
+ serial1 = &uart20;
};
wcd938x: audio-codec {
@@ -247,6 +248,71 @@
};
};
+ wcn6855-pmu {
+ compatible = "qcom,wcn6855-pmu";
+
+ pinctrl-0 = <&bt_en>, <&wlan_en>, <&xo_clk_default>;
+ pinctrl-names = "default";
+
+ wlan-enable-gpios = <&tlmm 80 GPIO_ACTIVE_HIGH>;
+ bt-enable-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>;
+ swctrl-gpios = <&tlmm 82 GPIO_ACTIVE_HIGH>;
+ xo-clk-gpios = <&tlmm 204 GPIO_ACTIVE_HIGH>;
+
+ vddio-supply = <&vreg_s10b_1p8>;
+ vddaon-supply = <&vreg_s11b_0p95>;
+ vddpmu-supply = <&vreg_s12b_1p25>;
+ vddpmumx-supply = <&vreg_s2e_0p85>;
+ vddpmucx-supply = <&vreg_s11b_0p95>;
+ vddrfa0p95-supply = <&vreg_s11b_0p95>;
+ vddrfa1p3-supply = <&vreg_s12b_1p25>;
+ vddrfa1p9-supply = <&vreg_s1c_1p86>;
+ vddpcie1p3-supply = <&vreg_s12b_1p25>;
+ vddpcie1p9-supply = <&vreg_s1c_1p86>;
+
+ regulators {
+ vreg_pmu_rfa_cmn_0p8: ldo0 {
+ regulator-name = "vreg_pmu_rfa_cmn_0p8";
+ };
+
+ vreg_pmu_aon_0p8: ldo1 {
+ regulator-name = "vreg_pmu_aon_0p8";
+ };
+
+ vreg_pmu_wlcx_0p8: ldo2 {
+ regulator-name = "vreg_pmu_wlcx_0p8";
+ };
+
+ vreg_pmu_wlmx_0p8: ldo3 {
+ regulator-name = "vreg_pmu_wlmx_0p8";
+ };
+
+ vreg_pmu_btcmx_0p8: ldo4 {
+ regulator-name = "vreg_pmu_btcmx_0p8";
+ };
+
+ vreg_pmu_pcie_1p8: ldo5 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+
+ vreg_pmu_pcie_0p9: ldo6 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_rfa_0p8: ldo7 {
+ regulator-name = "vreg_pmu_rfa_0p8";
+ };
+
+ vreg_pmu_rfa_1p2: ldo8 {
+ regulator-name = "vreg_pmu_rfa_1p2";
+ };
+
+ vreg_pmu_rfa_1p7: ldo9 {
+ regulator-name = "vreg_pmu_rfa_1p7";
+ };
+ };
+ };
+
vph_pwr: vph-pwr-regulator {
compatible = "regulator-fixed";
regulator-name = "vph_pwr";
@@ -575,10 +641,6 @@
};
};
-&dispcc {
- status = "okay";
-};
-
&gpu {
status = "okay";
@@ -689,6 +751,23 @@
vdda-pll-supply = <&vreg_l6b_1p2>;
};
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1103";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+ vddaon-supply = <&vreg_pmu_aon_0p8>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+ };
+};
+
&pcie1 {
status = "okay";
};
@@ -896,6 +975,10 @@
status = "okay";
};
+&qupv3_id_2 {
+ status = "okay";
+};
+
&sdhc_2 {
cd-gpios = <&tlmm 92 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default", "sleep";
@@ -1073,6 +1156,26 @@
status = "okay";
};
+&uart20 {
+ pinctrl-0 = <&uart20_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn6855-bt";
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn_0p8>;
+ vddaon-supply = <&vreg_pmu_aon_0p8>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p8>;
+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p8>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p7>;
+ };
+};
+
&ufs_mem_hc {
status = "okay";
@@ -1134,6 +1237,14 @@
};
&tlmm {
+ bt_en: bt-en-state {
+ pins = "gpio81";
+ function = "gpio";
+ drive-strength = <16>;
+ output-low;
+ bias-pull-down;
+ };
+
spkr_1_sd_n_active: spkr-1-sd-n-active-state {
pins = "gpio1";
function = "gpio";
@@ -1157,4 +1268,46 @@
bias-disable;
output-low;
};
+
+ wlan_en: wlan-en-state {
+ pins = "gpio80";
+ function = "gpio";
+ drive-strength = <16>;
+ output-low;
+ bias-pull-down;
+ };
+
+ uart20_default: uart20-default-state {
+ cts-pins {
+ pins = "gpio76";
+ function = "qup20";
+ bias-disable;
+ };
+
+ rts-pins {
+ pins = "gpio77";
+ function = "qup20";
+ bias-disable;
+ };
+
+ rx-pins {
+ pins = "gpio78";
+ function = "qup20";
+ bias-disable;
+ };
+
+ tx-pins {
+ pins = "gpio79";
+ function = "qup20";
+ bias-disable;
+ };
+ };
+
+ xo_clk_default: xo-clk-state {
+ pins = "gpio204";
+ function = "gpio";
+ drive-strength = <16>;
+ output-low;
+ bias-pull-down;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
index 7b62ead68e77..8c39fbcaad80 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
@@ -349,6 +349,10 @@
};
};
+&dispcc {
+ status = "disabled";
+};
+
&pcie0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
index 17dbb67868ae..cc1335a07a35 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
@@ -468,6 +468,10 @@
};
};
+&dispcc {
+ status = "disabled";
+};
+
&gpi_dma0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
index 9bafb3b350ff..53147aa6f7e4 100644
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -51,23 +51,23 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -75,171 +75,171 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x100>;
enable-method = "psci";
- next-level-cache = <&L2_100>;
- power-domains = <&CPU_PD1>;
+ next-level-cache = <&l2_100>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x200>;
enable-method = "psci";
- next-level-cache = <&L2_200>;
- power-domains = <&CPU_PD2>;
+ next-level-cache = <&l2_200>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x300>;
enable-method = "psci";
- next-level-cache = <&L2_300>;
- power-domains = <&CPU_PD3>;
+ next-level-cache = <&l2_300>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 0>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x400>;
enable-method = "psci";
- next-level-cache = <&L2_400>;
- power-domains = <&CPU_PD4>;
+ next-level-cache = <&l2_400>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 1>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x500>;
enable-method = "psci";
- next-level-cache = <&L2_500>;
- power-domains = <&CPU_PD5>;
+ next-level-cache = <&l2_500>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 1>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x600>;
enable-method = "psci";
- next-level-cache = <&L2_600>;
- power-domains = <&CPU_PD6>;
+ next-level-cache = <&l2_600>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 1>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "qcom,kryo780";
reg = <0x0 0x700>;
enable-method = "psci";
- next-level-cache = <&L2_700>;
- power-domains = <&CPU_PD7>;
+ next-level-cache = <&l2_700>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 2>;
#cooling-cells = <2>;
clocks = <&cpufreq_hw 2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -247,7 +247,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "silver-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -257,7 +257,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -269,7 +269,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <1050>;
@@ -277,7 +277,7 @@
min-residency-us = <5309>;
};
- CLUSTER_SLEEP_1: cluster-sleep-1 {
+ cluster_sleep_1: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c344>;
entry-latency-us = <2700>;
@@ -323,57 +323,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cpu-cluster0 {
+ cluster_pd: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>, <&CLUSTER_SLEEP_1>;
+ domain-idle-states = <&cluster_sleep_0>, <&cluster_sleep_1>;
};
};
@@ -1787,7 +1787,8 @@
<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 148 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0",
"msi1",
"msi2",
@@ -1795,7 +1796,8 @@
"msi4",
"msi5",
"msi6",
- "msi7";
+ "msi7",
+ "global";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc 0 0 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
@@ -1880,7 +1882,7 @@
};
};
- pcie@0 {
+ pcieport0: pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;
bus-range = <0x01 0xff>;
@@ -1949,7 +1951,8 @@
<GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0",
"msi1",
"msi2",
@@ -1957,7 +1960,8 @@
"msi4",
"msi5",
"msi6",
- "msi7";
+ "msi7",
+ "global";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc 0 0 0 434 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
@@ -1973,7 +1977,7 @@
clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
<&gcc GCC_PCIE_1_PIPE_CLK_SRC>,
- <&pcie1_phy>,
+ <&pcie1_phy QMP_PCIE_PIPE_CLK>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_PCIE_1_AUX_CLK>,
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
@@ -3435,7 +3439,6 @@
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
- status = "disabled";
};
pdc: interrupt-controller@b220000 {
@@ -4257,6 +4260,7 @@
<GIC_SPI 695 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 696 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 697 IRQ_TYPE_LEVEL_HIGH>;
+ dma-coherent;
};
intc: interrupt-controller@17100000 {
@@ -4354,7 +4358,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 3>, <SLEEP_TCS 2>,
<WAKE_TCS 2>, <CONTROL_TCS 0>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
diff --git a/arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts b/arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts
index 3d351e90bb39..3c5d8d26704f 100644
--- a/arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts
+++ b/arch/arm64/boot/dts/qcom/sm8550-samsung-q5q.dts
@@ -98,7 +98,7 @@
* The bootloader will only keep display hardware enabled
* if this memory region is named exactly 'splash_region'
*/
- splash_region@b8000000 {
+ splash-region@b8000000 {
reg = <0x0 0xb8000000 0x0 0x2b00000>;
no-map;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
index 9dc0ee3eb98f..e7774d32fb6d 100644
--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
@@ -64,25 +64,25 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a510";
reg = <0 0>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
- L3_0: l3-cache {
+ next-level-cache = <&l3_0>;
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -90,185 +90,185 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a510";
reg = <0 0x100>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_100>;
- power-domains = <&CPU_PD1>;
+ next-level-cache = <&l2_100>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
#cooling-cells = <2>;
- L2_100: l2-cache {
+ l2_100: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a510";
reg = <0 0x200>;
clocks = <&cpufreq_hw 0>;
enable-method = "psci";
- next-level-cache = <&L2_200>;
- power-domains = <&CPU_PD2>;
+ next-level-cache = <&l2_200>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a715";
reg = <0 0x300>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_300>;
- power-domains = <&CPU_PD3>;
+ next-level-cache = <&l2_300>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <270>;
#cooling-cells = <2>;
- L2_300: l2-cache {
+ l2_300: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "arm,cortex-a715";
reg = <0 0x400>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_400>;
- power-domains = <&CPU_PD4>;
+ next-level-cache = <&l2_400>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <270>;
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "arm,cortex-a710";
reg = <0 0x500>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_500>;
- power-domains = <&CPU_PD5>;
+ next-level-cache = <&l2_500>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <270>;
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "arm,cortex-a710";
reg = <0 0x600>;
clocks = <&cpufreq_hw 1>;
enable-method = "psci";
- next-level-cache = <&L2_600>;
- power-domains = <&CPU_PD6>;
+ next-level-cache = <&l2_600>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <270>;
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "arm,cortex-x3";
reg = <0 0x700>;
clocks = <&cpufreq_hw 2>;
enable-method = "psci";
- next-level-cache = <&L2_700>;
- power-domains = <&CPU_PD7>;
+ next-level-cache = <&l2_700>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 2>;
capacity-dmips-mhz = <1894>;
dynamic-power-coefficient = <588>;
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -276,7 +276,7 @@
idle-states {
entry-method = "psci";
- LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ little_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "silver-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -286,7 +286,7 @@
local-timer-stop;
};
- BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ big_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -296,7 +296,7 @@
local-timer-stop;
};
- PRIME_CPU_SLEEP_0: cpu-sleep-2-0 {
+ prime_cpu_sleep_0: cpu-sleep-2-0 {
compatible = "arm,idle-state";
idle-state-name = "goldplus-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -308,7 +308,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <750>;
@@ -316,7 +316,7 @@
min-residency-us = <9144>;
};
- CLUSTER_SLEEP_1: cluster-sleep-1 {
+ cluster_sleep_1: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c344>;
entry-latency-us = <2800>;
@@ -376,57 +376,57 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&little_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&big_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&PRIME_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&prime_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cluster {
+ cluster_pd: power-domain-cluster {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>, <&CLUSTER_SLEEP_1>;
+ domain-idle-states = <&cluster_sleep_0>, <&cluster_sleep_1>;
};
};
@@ -1989,7 +1989,7 @@
status = "disabled";
};
- ufs_mem_hc: ufs@1d84000 {
+ ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sm8550-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
reg = <0x0 0x01d84000 0x0 0x3000>;
@@ -2076,7 +2076,8 @@
ice: crypto@1d88000 {
compatible = "qcom,sm8550-inline-crypto-engine",
"qcom,inline-crypto-engine";
- reg = <0 0x01d88000 0 0x8000>;
+ reg = <0 0x01d88000 0 0x18000>;
+
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
};
@@ -4365,7 +4366,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 3>, <SLEEP_TCS 2>,
<WAKE_TCS 2>, <CONTROL_TCS 0>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
diff --git a/arch/arm64/boot/dts/qcom/sm8650-hdk.dts b/arch/arm64/boot/dts/qcom/sm8650-hdk.dts
index 127c7aacd4fc..f00bdff4280a 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-hdk.dts
@@ -814,10 +814,6 @@
};
};
-&dispcc {
- status = "okay";
-};
-
&gpi_dma1 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8650-mtp.dts b/arch/arm64/boot/dts/qcom/sm8650-mtp.dts
index c63822f5b127..0db2cb03f252 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-mtp.dts
@@ -585,10 +585,6 @@
};
};
-&dispcc {
- status = "okay";
-};
-
&lpass_tlmm {
spkr_1_sd_n_active: spkr-1-sd-n-active-state {
pins = "gpio21";
diff --git a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
index 8ca0d28eba9b..c5e8c3c2df91 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
@@ -741,10 +741,6 @@
};
};
-&dispcc {
- status = "okay";
-};
-
&gpi_dma1 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
index 01ac3769ffa6..25e47505adcb 100644
--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
@@ -68,18 +68,18 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a520";
reg = <0 0>;
clocks = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
@@ -87,13 +87,13 @@
#cooling-cells = <2>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
- L3_0: l3-cache {
+ l3_0: l3-cache {
compatible = "cache";
cache-level = <3>;
cache-unified;
@@ -101,18 +101,18 @@
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a520";
reg = <0 0x100>;
clocks = <&cpufreq_hw 0>;
- power-domains = <&CPU_PD1>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
capacity-dmips-mhz = <1024>;
dynamic-power-coefficient = <100>;
@@ -121,18 +121,18 @@
#cooling-cells = <2>;
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a720";
reg = <0 0x200>;
clocks = <&cpufreq_hw 3>;
- power-domains = <&CPU_PD2>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <238>;
@@ -140,26 +140,26 @@
#cooling-cells = <2>;
- L2_200: l2-cache {
+ l2_200: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,cortex-a720";
reg = <0 0x300>;
clocks = <&cpufreq_hw 3>;
- power-domains = <&CPU_PD3>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_200>;
+ next-level-cache = <&l2_200>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <238>;
@@ -168,18 +168,18 @@
#cooling-cells = <2>;
};
- CPU4: cpu@400 {
+ cpu4: cpu@400 {
device_type = "cpu";
compatible = "arm,cortex-a720";
reg = <0 0x400>;
clocks = <&cpufreq_hw 3>;
- power-domains = <&CPU_PD4>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_400>;
+ next-level-cache = <&l2_400>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <238>;
@@ -187,26 +187,26 @@
#cooling-cells = <2>;
- L2_400: l2-cache {
+ l2_400: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU5: cpu@500 {
+ cpu5: cpu@500 {
device_type = "cpu";
compatible = "arm,cortex-a720";
reg = <0 0x500>;
clocks = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD5>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_500>;
+ next-level-cache = <&l2_500>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <238>;
@@ -214,26 +214,26 @@
#cooling-cells = <2>;
- L2_500: l2-cache {
+ l2_500: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU6: cpu@600 {
+ cpu6: cpu@600 {
device_type = "cpu";
compatible = "arm,cortex-a720";
reg = <0 0x600>;
clocks = <&cpufreq_hw 1>;
- power-domains = <&CPU_PD6>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_600>;
+ next-level-cache = <&l2_600>;
capacity-dmips-mhz = <1792>;
dynamic-power-coefficient = <238>;
@@ -241,26 +241,26 @@
#cooling-cells = <2>;
- L2_600: l2-cache {
+ l2_600: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
- CPU7: cpu@700 {
+ cpu7: cpu@700 {
device_type = "cpu";
compatible = "arm,cortex-x4";
reg = <0 0x700>;
clocks = <&cpufreq_hw 2>;
- power-domains = <&CPU_PD7>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
enable-method = "psci";
- next-level-cache = <&L2_700>;
+ next-level-cache = <&l2_700>;
capacity-dmips-mhz = <1894>;
dynamic-power-coefficient = <588>;
@@ -268,46 +268,46 @@
#cooling-cells = <2>;
- L2_700: l2-cache {
+ l2_700: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
- next-level-cache = <&L3_0>;
+ next-level-cache = <&l3_0>;
};
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
core4 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core5 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core6 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core7 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
};
@@ -315,7 +315,7 @@
idle-states {
entry-method = "psci";
- SILVER_CPU_SLEEP_0: cpu-sleep-0-0 {
+ silver_cpu_sleep_0: cpu-sleep-0-0 {
compatible = "arm,idle-state";
idle-state-name = "silver-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -325,7 +325,7 @@
local-timer-stop;
};
- GOLD_CPU_SLEEP_0: cpu-sleep-1-0 {
+ gold_cpu_sleep_0: cpu-sleep-1-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -335,7 +335,7 @@
local-timer-stop;
};
- GOLD_PLUS_CPU_SLEEP_0: cpu-sleep-2-0 {
+ gold_plus_cpu_sleep_0: cpu-sleep-2-0 {
compatible = "arm,idle-state";
idle-state-name = "gold-plus-rail-power-collapse";
arm,psci-suspend-param = <0x40000004>;
@@ -347,7 +347,7 @@
};
domain-idle-states {
- CLUSTER_SLEEP_0: cluster-sleep-0 {
+ cluster_sleep_0: cluster-sleep-0 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x41000044>;
entry-latency-us = <750>;
@@ -355,7 +355,7 @@
min-residency-us = <9144>;
};
- CLUSTER_SLEEP_1: cluster-sleep-1 {
+ cluster_sleep_1: cluster-sleep-1 {
compatible = "domain-idle-state";
arm,psci-suspend-param = <0x4100c344>;
entry-latency-us = <2800>;
@@ -411,58 +411,58 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&SILVER_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&silver_cpu_sleep_0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&SILVER_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&silver_cpu_sleep_0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&SILVER_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&silver_cpu_sleep_0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&GOLD_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&gold_cpu_sleep_0>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
- domain-idle-states = <&GOLD_PLUS_CPU_SLEEP_0>;
+ power-domains = <&cluster_pd>;
+ domain-idle-states = <&gold_plus_cpu_sleep_0>;
};
- CLUSTER_PD: power-domain-cluster {
+ cluster_pd: power-domain-cluster {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_SLEEP_0>,
- <&CLUSTER_SLEEP_1>;
+ domain-idle-states = <&cluster_sleep_0>,
+ <&cluster_sleep_1>;
};
};
@@ -2535,7 +2535,7 @@
status = "disabled";
};
- ufs_mem_hc: ufs@1d84000 {
+ ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sm8650-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
reg = <0 0x01d84000 0 0x3000>;
@@ -2595,7 +2595,7 @@
ice: crypto@1d88000 {
compatible = "qcom,sm8650-inline-crypto-engine",
"qcom,inline-crypto-engine";
- reg = <0 0x01d88000 0 0x8000>;
+ reg = <0 0x01d88000 0 0x18000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
};
@@ -3841,8 +3841,6 @@
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
-
- status = "disabled";
};
usb_1_hsphy: phy@88e3000 {
@@ -5083,7 +5081,7 @@
<GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&CLUSTER_PD>;
+ power-domains = <&cluster_pd>;
qcom,tcs-offset = <0xd00>;
qcom,drv-id = <2>;
diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts
index 941dfddd6713..975550139e10 100644
--- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts
+++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts
@@ -139,6 +139,8 @@
pinctrl-0 = <&nvme_reg_en>;
pinctrl-names = "default";
+
+ regulator-boot-on;
};
vph_pwr: regulator-vph-pwr {
@@ -451,6 +453,9 @@
&i2c0 {
clock-frequency = <400000>;
+ pinctrl-0 = <&qup_i2c0_data_clk>, <&tpad_default>;
+ pinctrl-names = "default";
+
status = "okay";
/* ELAN06E2 or ELAN06E3 */
@@ -461,13 +466,19 @@
hid-descr-addr = <0x1>;
interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>;
- pinctrl-0 = <&tpad_default>;
- pinctrl-names = "default";
-
wakeup-source;
};
- /* TODO: second-sourced SYNA8022 or SYNA8024 touchpad @ 0x2c */
+ /* SYNA8022 or SYNA8024 */
+ touchpad@2c {
+ compatible = "hid-over-i2c";
+ reg = <0x2c>;
+
+ hid-descr-addr = <0x20>;
+ interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>;
+
+ wakeup-source;
+ };
/* ELAN06F1 or SYNA06F2 */
keyboard@3a {
@@ -762,10 +773,6 @@
status = "okay";
};
-&usb_1_ss0_dwc3 {
- dr_mode = "host";
-};
-
&usb_1_ss0_dwc3_hs {
remote-endpoint = <&pmic_glink_ss0_hs_in>;
};
@@ -794,10 +801,6 @@
status = "okay";
};
-&usb_1_ss1_dwc3 {
- dr_mode = "host";
-};
-
&usb_1_ss1_dwc3_hs {
remote-endpoint = <&pmic_glink_ss1_hs_in>;
};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
index 20616bd4aa6c..8515c254e158 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts
@@ -94,17 +94,6 @@
};
};
- 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;
- };
-
vreg_edp_3p3: regulator-edp-3p3 {
compatible = "regulator-fixed";
@@ -134,6 +123,19 @@
pinctrl-0 = <&nvme_reg_en>;
pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
};
};
@@ -592,8 +594,6 @@
vdda-phy-supply = <&vreg_l3e_1p2>;
vdda-pll-supply = <&vreg_l1j_0p8>;
- orientation-switch;
-
status = "okay";
};
@@ -626,8 +626,6 @@
vdda-phy-supply = <&vreg_l3e_1p2>;
vdda-pll-supply = <&vreg_l2d_0p9>;
- orientation-switch;
-
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
index 10b28d870f08..39f9d9cdc10d 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
@@ -8,6 +8,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "x1e80100.dtsi"
@@ -177,9 +178,9 @@
compatible = "qcom,x1e80100-sndcard";
model = "X1E80100-CRD";
audio-routing = "WooferLeft IN", "WSA WSA_SPK1 OUT",
- "TwitterLeft IN", "WSA WSA_SPK2 OUT",
+ "TweeterLeft IN", "WSA WSA_SPK2 OUT",
"WooferRight IN", "WSA2 WSA_SPK2 OUT",
- "TwitterRight IN", "WSA2 WSA_SPK2 OUT",
+ "TweeterRight IN", "WSA2 WSA_SPK2 OUT",
"IN1_HPHL", "HPHL_OUT",
"IN2_HPHR", "HPHR_OUT",
"AMIC2", "MIC BIAS2",
@@ -261,31 +262,37 @@
};
};
- vph_pwr: vph-pwr-regulator {
+ vreg_edp_3p3: regulator-edp-3p3 {
compatible = "regulator-fixed";
- regulator-name = "vph_pwr";
- regulator-min-microvolt = <3700000>;
- regulator-max-microvolt = <3700000>;
+ regulator-name = "VREG_EDP_3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 70 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&edp_reg_en>;
+ pinctrl-names = "default";
- regulator-always-on;
regulator-boot-on;
};
- vreg_edp_3p3: regulator-edp-3p3 {
+ vreg_misc_3p3: regulator-misc-3p3 {
compatible = "regulator-fixed";
- regulator-name = "VREG_EDP_3P3";
+ regulator-name = "VREG_MISC_3P3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- gpio = <&tlmm 70 GPIO_ACTIVE_HIGH>;
+ gpio = <&pm8550ve_8_gpios 6 GPIO_ACTIVE_HIGH>;
enable-active-high;
- pinctrl-0 = <&edp_reg_en>;
pinctrl-names = "default";
+ pinctrl-0 = <&misc_3p3_reg_en>;
regulator-boot-on;
+ regulator-always-on;
};
vreg_nvme: regulator-nvme {
@@ -300,6 +307,19 @@
pinctrl-names = "default";
pinctrl-0 = <&nvme_reg_en>;
+
+ regulator-boot-on;
+ };
+
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
};
vreg_wwan: regulator-wwan {
@@ -689,6 +709,9 @@
hid-descr-addr = <0x1>;
interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <&vreg_misc_3p3>;
+ vddl-supply = <&vreg_l12b_1p2>;
+
pinctrl-0 = <&tpad_default>;
pinctrl-names = "default";
@@ -702,6 +725,9 @@
hid-descr-addr = <0x1>;
interrupts-extended = <&tlmm 67 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <&vreg_misc_3p3>;
+ vddl-supply = <&vreg_l12b_1p2>;
+
pinctrl-0 = <&kybd_default>;
pinctrl-names = "default";
@@ -721,6 +747,9 @@
hid-descr-addr = <0x1>;
interrupts-extended = <&tlmm 51 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <&vreg_misc_3p3>;
+ vddl-supply = <&vreg_l15b_1p8>;
+
pinctrl-0 = <&ts0_default>;
pinctrl-names = "default";
};
@@ -854,6 +883,19 @@
status = "okay";
};
+&pm8550ve_8_gpios {
+ misc_3p3_reg_en: misc-3p3-reg-en-state {
+ pins = "gpio6";
+ function = "normal";
+ bias-disable;
+ input-disable;
+ output-enable;
+ drive-push-pull;
+ power-source = <1>; /* 1.8 V */
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ };
+};
+
&pmc8380_3_gpios {
edp_bl_en: edp-bl-en-state {
pins = "gpio4";
@@ -933,7 +975,7 @@
reg = <0 1>;
reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0>;
- sound-name-prefix = "TwitterLeft";
+ sound-name-prefix = "TweeterLeft";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l12b_1p2>;
qcom,port-mapping = <4 5 6 7 11 13>;
@@ -986,7 +1028,7 @@
reg = <0 1>;
reset-gpios = <&lpass_tlmm 13 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0>;
- sound-name-prefix = "TwitterRight";
+ sound-name-prefix = "TweeterRight";
vdd-1p8-supply = <&vreg_l15b_1p8>;
vdd-io-supply = <&vreg_l12b_1p2>;
qcom,port-mapping = <4 5 6 7 11 13>;
@@ -1155,10 +1197,6 @@
status = "okay";
};
-&usb_1_ss0_dwc3 {
- dr_mode = "host";
-};
-
&usb_1_ss0_dwc3_hs {
remote-endpoint = <&pmic_glink_ss0_hs_in>;
};
@@ -1187,10 +1225,6 @@
status = "okay";
};
-&usb_1_ss1_dwc3 {
- dr_mode = "host";
-};
-
&usb_1_ss1_dwc3_hs {
remote-endpoint = <&pmic_glink_ss1_hs_in>;
};
@@ -1219,10 +1253,6 @@
status = "okay";
};
-&usb_1_ss2_dwc3 {
- dr_mode = "host";
-};
-
&usb_1_ss2_dwc3_hs {
remote-endpoint = <&pmic_glink_ss2_hs_in>;
};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts b/arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts
new file mode 100644
index 000000000000..05624226faf9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/x1e80100-dell-xps13-9345.dts
@@ -0,0 +1,875 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024 Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/gpio-keys.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "x1e80100.dtsi"
+#include "x1e80100-pmics.dtsi"
+
+/ {
+ model = "Dell XPS 13 9345";
+ compatible = "dell,xps13-9345", "qcom,x1e80100";
+ chassis-type = "laptop";
+
+ aliases {
+ serial0 = &uart21;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&hall_int_n_default>;
+ pinctrl-names = "default";
+
+ switch-lid {
+ gpios = <&tlmm 92 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ wakeup-source;
+ wakeup-event-action = <EV_ACT_DEASSERTED>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam_indicator_en>;
+
+ led-camera-indicator {
+ label = "white:camera-indicator";
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_WHITE>;
+ gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ default-state = "off";
+ /* Reuse as a panic indicator until we get a "camera on" trigger */
+ panic-indicator;
+ };
+ };
+
+ pmic-glink {
+ compatible = "qcom,x1e80100-pmic-glink",
+ "qcom,sm8550-pmic-glink",
+ "qcom,pmic-glink";
+ orientation-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>,
+ <&tlmm 123 GPIO_ACTIVE_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Right-side USB Type-C port */
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_ss0_hs_in: endpoint {
+ remote-endpoint = <&usb_1_ss0_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_ss0_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss0_qmpphy_out>;
+ };
+ };
+ };
+ };
+
+ /* Left-side USB Type-C port */
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ pmic_glink_ss1_hs_in: endpoint {
+ remote-endpoint = <&usb_1_ss1_dwc3_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ pmic_glink_ss1_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss1_qmpphy_out>;
+ };
+ };
+ };
+ };
+ };
+
+ reserved-memory {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x8000000>;
+ reusable;
+ linux,cma-default;
+ };
+ };
+
+ vreg_edp_3p3: regulator-edp-3p3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_EDP_3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 70 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&edp_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_nvme: regulator-nvme {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_NVME_3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 18 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&nvme_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8550-rpmh-regulators";
+ qcom,pmic-id = "b";
+ vdd-bob1-supply = <&vreg_vph_pwr>;
+ vdd-bob2-supply = <&vreg_vph_pwr>;
+ vdd-l1-l4-l10-supply = <&vreg_s4c_1p8>;
+ vdd-l2-l13-l14-supply = <&vreg_bob1>;
+ vdd-l5-l16-supply = <&vreg_bob1>;
+ vdd-l6-l7-supply = <&vreg_bob2>;
+ vdd-l8-l9-supply = <&vreg_bob1>;
+ vdd-l12-supply = <&vreg_s5j_1p2>;
+ vdd-l15-supply = <&vreg_s4c_1p8>;
+ vdd-l17-supply = <&vreg_bob2>;
+
+ vreg_bob1: bob1 {
+ regulator-name = "vreg_bob1";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob2: bob2 {
+ regulator-name = "vreg_bob2";
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2b_3p0: ldo2 {
+ regulator-name = "vreg_l2b_3p0";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4b_1p8: ldo4 {
+ regulator-name = "vreg_l4b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6b_1p8: ldo6 {
+ regulator-name = "vreg_l6b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8b_3p0: ldo8 {
+ regulator-name = "vreg_l8b_3p0";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9b_2p9: ldo9 {
+ regulator-name = "vreg_l9b_2p9";
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12b_1p2: ldo12 {
+ regulator-name = "vreg_l12b_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13b_3p0: ldo13 {
+ regulator-name = "vreg_l13b_3p0";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14b_3p0: ldo14 {
+ regulator-name = "vreg_l14b_3p0";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15b_1p8: ldo15 {
+ regulator-name = "vreg_l15b_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17b_2p5: ldo17 {
+ regulator-name = "vreg_l17b_2p5";
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <2504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8550ve-rpmh-regulators";
+ qcom,pmic-id = "c";
+ vdd-l1-supply = <&vreg_s5j_1p2>;
+ vdd-l2-supply = <&vreg_s1f_0p7>;
+ vdd-l3-supply = <&vreg_s1f_0p7>;
+
+ vreg_s4c_1p8: smps4 {
+ regulator-name = "vreg_s4c_1p8";
+ regulator-min-microvolt = <1856000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1c_1p2: ldo1 {
+ regulator-name = "vreg_l1c_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c_0p8: ldo2 {
+ regulator-name = "vreg_l2c_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c_0p9: ldo3 {
+ regulator-name = "vreg_l3c_0p9";
+ regulator-min-microvolt = <920000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pmc8380-rpmh-regulators";
+ qcom,pmic-id = "d";
+ vdd-l1-supply = <&vreg_s1f_0p7>;
+ vdd-l2-supply = <&vreg_s1f_0p7>;
+ vdd-l3-supply = <&vreg_s4c_1p8>;
+ vdd-s1-supply = <&vreg_vph_pwr>;
+
+ vreg_l1d_0p8: ldo1 {
+ regulator-name = "vreg_l1d_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2d_0p9: ldo2 {
+ regulator-name = "vreg_l2d_0p9";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3d_1p8: ldo3 {
+ regulator-name = "vreg_l3d_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-3 {
+ compatible = "qcom,pmc8380-rpmh-regulators";
+ qcom,pmic-id = "e";
+ vdd-l2-supply = <&vreg_s1f_0p7>;
+ vdd-l3-supply = <&vreg_s5j_1p2>;
+
+ vreg_l2e_0p8: ldo2 {
+ regulator-name = "vreg_l2e_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3e_1p2: ldo3 {
+ regulator-name = "vreg_l3e_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-4 {
+ compatible = "qcom,pmc8380-rpmh-regulators";
+ qcom,pmic-id = "f";
+ vdd-l1-supply = <&vreg_s5j_1p2>;
+ vdd-l2-supply = <&vreg_s5j_1p2>;
+ vdd-l3-supply = <&vreg_s5j_1p2>;
+ vdd-s1-supply = <&vreg_vph_pwr>;
+
+ vreg_s1f_0p7: smps1 {
+ regulator-name = "vreg_s1f_0p7";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-6 {
+ compatible = "qcom,pm8550ve-rpmh-regulators";
+ qcom,pmic-id = "i";
+ vdd-l1-supply = <&vreg_s4c_1p8>;
+ vdd-l2-supply = <&vreg_s5j_1p2>;
+ vdd-l3-supply = <&vreg_s1f_0p7>;
+ vdd-s1-supply = <&vreg_vph_pwr>;
+ vdd-s2-supply = <&vreg_vph_pwr>;
+
+ vreg_s1i_0p9: smps1 {
+ regulator-name = "vreg_s1i_0p9";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s2i_1p0: smps2 {
+ regulator-name = "vreg_s2i_1p0";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1i_1p8: ldo1 {
+ regulator-name = "vreg_l1i_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2i_1p2: ldo2 {
+ regulator-name = "vreg_l2i_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3i_0p8: ldo3 {
+ regulator-name = "vreg_l3i_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-7 {
+ compatible = "qcom,pm8550ve-rpmh-regulators";
+ qcom,pmic-id = "j";
+ vdd-l1-supply = <&vreg_s1f_0p7>;
+ vdd-l2-supply = <&vreg_s5j_1p2>;
+ vdd-l3-supply = <&vreg_s1f_0p7>;
+ vdd-s5-supply = <&vreg_vph_pwr>;
+
+ vreg_s5j_1p2: smps5 {
+ regulator-name = "vreg_s5j_1p2";
+ regulator-min-microvolt = <1256000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l1j_0p9: ldo1 {
+ regulator-name = "vreg_l1j_0p9";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2j_1p2: ldo2 {
+ regulator-name = "vreg_l2j_1p2";
+ regulator-min-microvolt = <1256000>;
+ regulator-max-microvolt = <1256000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3j_0p8: ldo3 {
+ regulator-name = "vreg_l3j_0p8";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ firmware-name = "qcom/x1e80100/dell/xps13-9345/qcdxkmsuc8380.mbn";
+ };
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ keyboard@5 {
+ compatible = "hid-over-i2c";
+ reg = <0x5>;
+
+ hid-descr-addr = <0x20>;
+ interrupts-extended = <&tlmm 67 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&kybd_default>;
+ pinctrl-names = "default";
+
+ wakeup-source;
+ };
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+ status = "disabled";
+ /* PS8830 Retimer @0x8 */
+ /* Unknown device @0x9 */
+};
+
+&i2c5 {
+ clock-frequency = <100000>;
+ status = "disabled";
+ /* EC @0x3b */
+};
+
+&i2c7 {
+ clock-frequency = <400000>;
+ status = "disabled";
+ /* PS8830 Retimer @0x8 */
+ /* Unknown device @0x9 */
+};
+
+&i2c8 {
+ clock-frequency = <400000>;
+
+ status = "okay";
+
+ touchscreen@10 {
+ compatible = "hid-over-i2c";
+ reg = <0x10>;
+
+ hid-descr-addr = <0x1>;
+ interrupts-extended = <&tlmm 51 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&ts0_default>;
+ pinctrl-names = "default";
+ };
+};
+
+&i2c9 {
+ clock-frequency = <400000>;
+ status = "disabled";
+ /* USB3 retimer device @0x4f */
+};
+
+&i2c17 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchpad@2c {
+ compatible = "hid-over-i2c";
+ reg = <0x2c>;
+
+ hid-descr-addr = <0x20>;
+ interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-0 = <&tpad_default>;
+ pinctrl-names = "default";
+
+ wakeup-source;
+ };
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dp3 {
+ /delete-property/ #sound-dai-cells;
+
+ status = "okay";
+
+ aux-bus {
+ panel {
+ compatible = "edp-panel";
+ enable-gpios = <&tlmm 74 GPIO_ACTIVE_HIGH>;
+ power-supply = <&vreg_edp_3p3>;
+
+ pinctrl-0 = <&edp_bl_en>;
+ pinctrl-names = "default";
+
+ port {
+ edp_panel_in: endpoint {
+ remote-endpoint = <&mdss_dp3_out>;
+ };
+ };
+ };
+ };
+
+ ports {
+ port@1 {
+ reg = <1>;
+
+ mdss_dp3_out: endpoint {
+ data-lanes = <0 1 2 3>;
+ link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>;
+
+ remote-endpoint = <&edp_panel_in>;
+ };
+ };
+ };
+};
+
+&mdss_dp3_phy {
+ vdda-phy-supply = <&vreg_l3j_0p8>;
+ vdda-pll-supply = <&vreg_l2j_1p2>;
+
+ status = "okay";
+};
+
+&pcie4 {
+ perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&pcie4_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie4_phy {
+ vdda-phy-supply = <&vreg_l3i_0p8>;
+ vdda-pll-supply = <&vreg_l3e_1p2>;
+
+ status = "okay";
+};
+
+&pcie6a {
+ perst-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_nvme>;
+
+ pinctrl-0 = <&pcie6a_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&pcie6a_phy {
+ vdda-phy-supply = <&vreg_l1d_0p8>;
+ vdda-pll-supply = <&vreg_l2j_1p2>;
+
+ status = "okay";
+};
+
+&qupv3_0 {
+ status = "okay";
+};
+
+&qupv3_1 {
+ status = "okay";
+};
+
+&qupv3_2 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/x1e80100/dell/xps13-9345/qcadsp8380.mbn",
+ "qcom/x1e80100/dell/xps13-9345/adsp_dtbs.elf";
+
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/x1e80100/dell/xps13-9345/qccdsp8380.mbn",
+ "qcom/x1e80100/dell/xps13-9345/cdsp_dtbs.elf";
+
+ status = "okay";
+};
+
+&smb2360_0_eusb2_repeater {
+ vdd18-supply = <&vreg_l3d_1p8>;
+ vdd3-supply = <&vreg_l2b_3p0>;
+};
+
+&smb2360_1_eusb2_repeater {
+ vdd18-supply = <&vreg_l3d_1p8>;
+ vdd3-supply = <&vreg_l14b_3p0>;
+};
+
+&tlmm {
+ gpio-reserved-ranges = <44 4>, /* SPI11 (TPM) */
+ <76 4>, /* SPI19 (TZ Protected) */
+ <238 1>; /* UFS Reset */
+
+ cam_indicator_en: cam-indicator-en-state {
+ pins = "gpio110";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ edp_bl_en: edp-bl-en-state {
+ pins = "gpio74";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ edp_reg_en: edp-reg-en-state {
+ pins = "gpio70";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ hall_int_n_default: hall-int-n-state {
+ pins = "gpio92";
+ function = "gpio";
+
+ bias-disable;
+ };
+
+ kybd_default: kybd-default-state {
+ pins = "gpio67";
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ nvme_reg_en: nvme-reg-en-state {
+ pins = "gpio18";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pcie4_default: pcie4-default-state {
+ clkreq-n-pins {
+ pins = "gpio147";
+ function = "pcie4_clk";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio146";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ wake-n-pins {
+ pins = "gpio148";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie6a_default: pcie6a-default-state {
+ clkreq-n-pins {
+ pins = "gpio153";
+ function = "pcie6a_clk";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio152";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ wake-n-pins {
+ pins = "gpio154";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ tpad_default: tpad-default-state {
+ disable-pins {
+ pins = "gpio38";
+ function = "gpio";
+ output-high;
+ };
+
+ int-n-pins {
+ pins = "gpio3";
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ reset-n-pins {
+ pins = "gpio52";
+ function = "gpio";
+ bias-disable;
+ };
+ };
+
+ ts0_default: ts0-default-state {
+ disable-pins {
+ pins = "gpio75";
+ function = "gpio";
+ output-high;
+ };
+
+ int-n-pins {
+ pins = "gpio51";
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ reset-n-pins {
+ /* Technically should be High-Z input */
+ pins = "gpio48";
+ function = "gpio";
+ output-low;
+ drive-strength = <2>;
+ };
+ };
+};
+
+&uart21 {
+ compatible = "qcom,geni-debug-uart";
+ status = "okay";
+};
+
+&usb_1_ss0_hsphy {
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
+
+ phys = <&smb2360_0_eusb2_repeater>;
+
+ status = "okay";
+};
+
+&usb_1_ss0_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l1j_0p9>;
+
+ status = "okay";
+};
+
+&usb_1_ss0 {
+ status = "okay";
+};
+
+&usb_1_ss0_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_ss0_dwc3_hs {
+ remote-endpoint = <&pmic_glink_ss0_hs_in>;
+};
+
+&usb_1_ss0_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss0_ss_in>;
+};
+
+&usb_1_ss1_hsphy {
+ vdd-supply = <&vreg_l3j_0p8>;
+ vdda12-supply = <&vreg_l2j_1p2>;
+
+ phys = <&smb2360_1_eusb2_repeater>;
+
+ status = "okay";
+};
+
+&usb_1_ss1_qmpphy {
+ vdda-phy-supply = <&vreg_l3e_1p2>;
+ vdda-pll-supply = <&vreg_l2d_0p9>;
+
+ status = "okay";
+};
+
+&usb_1_ss1 {
+ status = "okay";
+};
+
+&usb_1_ss1_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_ss1_dwc3_hs {
+ remote-endpoint = <&pmic_glink_ss1_hs_in>;
+};
+
+&usb_1_ss1_qmpphy_out {
+ remote-endpoint = <&pmic_glink_ss1_ss_in>;
+};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts
index 3c13331a9ef4..ca5a808f2c7d 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts
@@ -15,6 +15,14 @@
model = "Lenovo Yoga Slim 7x";
compatible = "lenovo,yoga-slim7x", "qcom,x1e80100";
+ aliases {
+ serial0 = &uart21;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
pmic-glink {
compatible = "qcom,x1e80100-pmic-glink",
"qcom,sm8550-pmic-glink",
@@ -166,17 +174,6 @@
};
};
- 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;
- };
-
vreg_edp_3p3: regulator-edp-3p3 {
compatible = "regulator-fixed";
@@ -205,6 +202,19 @@
pinctrl-0 = <&nvme_reg_en>;
pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
};
};
@@ -883,6 +893,11 @@
};
+&uart21 {
+ compatible = "qcom,geni-debug-uart";
+ status = "okay";
+};
+
&usb_1_ss0_hsphy {
vdd-supply = <&vreg_l3j_0p8>;
vdda12-supply = <&vreg_l2j_1p2>;
@@ -896,8 +911,6 @@
vdda-phy-supply = <&vreg_l3e_1p2>;
vdda-pll-supply = <&vreg_l1j_0p8>;
- orientation-switch;
-
status = "okay";
};
@@ -930,8 +943,6 @@
vdda-phy-supply = <&vreg_l3e_1p2>;
vdda-pll-supply = <&vreg_l2d_0p9>;
- orientation-switch;
-
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi
index 42e02ad6a9c3..6835fdeef3ae 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi
@@ -4,6 +4,8 @@
*/
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/gpio-keys.h>
+#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
@@ -30,6 +32,21 @@
pinctrl-names = "default";
};
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-0 = <&hall_int_n_default>;
+ pinctrl-names = "default";
+
+ switch-lid {
+ gpios = <&tlmm 2 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ wakeup-source;
+ wakeup-event-action = <EV_ACT_DEASSERTED>;
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -125,17 +142,6 @@
};
};
- 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;
- };
-
vreg_edp_3p3: regulator-edp-3p3 {
compatible = "regulator-fixed";
@@ -164,6 +170,19 @@
pinctrl-0 = <&nvme_reg_en>;
pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
};
};
@@ -555,7 +574,17 @@
status = "okay";
- /* Something @4f */
+ ptn3222: redriver@4f {
+ compatible = "nxp,ptn3222";
+ reg = <0x4f>;
+
+ reset-gpios = <&tlmm 7 GPIO_ACTIVE_LOW>;
+
+ vdd3v3-supply = <&vreg_l13b>;
+ vdd1v8-supply = <&vreg_l4b>;
+
+ #phy-cells = <0>;
+ };
};
&i2c7 {
@@ -566,7 +595,6 @@
/* PS8830 USB retimer @8 */
};
-
&mdss {
status = "okay";
};
@@ -700,10 +728,25 @@
vdd3-supply = <&vreg_l14b>;
};
+&smb2360_2 {
+ status = "okay";
+};
+
+&smb2360_2_eusb2_repeater {
+ vdd18-supply = <&vreg_l3d>;
+ vdd3-supply = <&vreg_l8b>;
+};
+
&tlmm {
gpio-reserved-ranges = <44 4>, /* SPI (TPM) */
<238 1>; /* UFS Reset */
+ hall_int_n_default: hall-int-n-state {
+ pins = "gpio2";
+ function = "gpio";
+ bias-disable;
+ };
+
nvme_reg_en: nvme-reg-en-state {
pins = "gpio18";
function = "gpio";
@@ -833,3 +876,40 @@
&usb_1_ss1_qmpphy_out {
remote-endpoint = <&pmic_glink_ss1_ss_in>;
};
+
+/* MP0 goes to the Surface Connector, MP1 goes to the USB-A port */
+&usb_mp {
+ status = "okay";
+};
+
+&usb_mp_hsphy0 {
+ vdd-supply = <&vreg_l2e>;
+ vdda12-supply = <&vreg_l2j>;
+
+ phys = <&smb2360_2_eusb2_repeater>;
+
+ status = "okay";
+};
+
+&usb_mp_hsphy1 {
+ vdd-supply = <&vreg_l2e>;
+ vdda12-supply = <&vreg_l2j>;
+
+ phys = <&ptn3222>;
+
+ status = "okay";
+};
+
+&usb_mp_qmpphy0 {
+ vdda-phy-supply = <&vreg_l3e>;
+ vdda-pll-supply = <&vreg_l3c>;
+
+ status = "okay";
+};
+
+&usb_mp_qmpphy1 {
+ vdda-phy-supply = <&vreg_l3e>;
+ vdda-pll-supply = <&vreg_l3c>;
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
index 1c3a6a7b3ed6..5ef030c60abe 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
@@ -253,6 +253,8 @@
pinctrl-names = "default";
pinctrl-0 = <&nvme_reg_en>;
+
+ regulator-boot-on;
};
};
diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
index a36076e3c56b..88805629ed2b 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
@@ -65,208 +65,208 @@
#address-cells = <2>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD0>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd0>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU1: cpu@100 {
+ cpu1: cpu@100 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x100>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD1>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd1>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU2: cpu@200 {
+ cpu2: cpu@200 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x200>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD2>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd2>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU3: cpu@300 {
+ cpu3: cpu@300 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x300>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
- power-domains = <&CPU_PD3>;
+ next-level-cache = <&l2_0>;
+ power-domains = <&cpu_pd3>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU4: cpu@10000 {
+ cpu4: cpu@10000 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x10000>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
- power-domains = <&CPU_PD4>;
+ next-level-cache = <&l2_1>;
+ power-domains = <&cpu_pd4>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
- L2_1: l2-cache {
+ l2_1: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU5: cpu@10100 {
+ cpu5: cpu@10100 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x10100>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
- power-domains = <&CPU_PD5>;
+ next-level-cache = <&l2_1>;
+ power-domains = <&cpu_pd5>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU6: cpu@10200 {
+ cpu6: cpu@10200 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x10200>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
- power-domains = <&CPU_PD6>;
+ next-level-cache = <&l2_1>;
+ power-domains = <&cpu_pd6>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU7: cpu@10300 {
+ cpu7: cpu@10300 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x10300>;
enable-method = "psci";
- next-level-cache = <&L2_1>;
- power-domains = <&CPU_PD7>;
+ next-level-cache = <&l2_1>;
+ power-domains = <&cpu_pd7>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU8: cpu@20000 {
+ cpu8: cpu@20000 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x20000>;
enable-method = "psci";
- next-level-cache = <&L2_2>;
- power-domains = <&CPU_PD8>;
+ next-level-cache = <&l2_2>;
+ power-domains = <&cpu_pd8>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
- L2_2: l2-cache {
+ l2_2: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
};
};
- CPU9: cpu@20100 {
+ cpu9: cpu@20100 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x20100>;
enable-method = "psci";
- next-level-cache = <&L2_2>;
- power-domains = <&CPU_PD9>;
+ next-level-cache = <&l2_2>;
+ power-domains = <&cpu_pd9>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU10: cpu@20200 {
+ cpu10: cpu@20200 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x20200>;
enable-method = "psci";
- next-level-cache = <&L2_2>;
- power-domains = <&CPU_PD10>;
+ next-level-cache = <&l2_2>;
+ power-domains = <&cpu_pd10>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
- CPU11: cpu@20300 {
+ cpu11: cpu@20300 {
device_type = "cpu";
compatible = "qcom,oryon";
reg = <0x0 0x20300>;
enable-method = "psci";
- next-level-cache = <&L2_2>;
- power-domains = <&CPU_PD11>;
+ next-level-cache = <&l2_2>;
+ power-domains = <&cpu_pd11>;
power-domain-names = "psci";
- cpu-idle-states = <&CLUSTER_C4>;
+ cpu-idle-states = <&cluster_c4>;
};
cpu-map {
cluster0 {
core0 {
- cpu = <&CPU0>;
+ cpu = <&cpu0>;
};
core1 {
- cpu = <&CPU1>;
+ cpu = <&cpu1>;
};
core2 {
- cpu = <&CPU2>;
+ cpu = <&cpu2>;
};
core3 {
- cpu = <&CPU3>;
+ cpu = <&cpu3>;
};
};
cluster1 {
core0 {
- cpu = <&CPU4>;
+ cpu = <&cpu4>;
};
core1 {
- cpu = <&CPU5>;
+ cpu = <&cpu5>;
};
core2 {
- cpu = <&CPU6>;
+ cpu = <&cpu6>;
};
core3 {
- cpu = <&CPU7>;
+ cpu = <&cpu7>;
};
};
cluster2 {
core0 {
- cpu = <&CPU8>;
+ cpu = <&cpu8>;
};
core1 {
- cpu = <&CPU9>;
+ cpu = <&cpu9>;
};
core2 {
- cpu = <&CPU10>;
+ cpu = <&cpu10>;
};
core3 {
- cpu = <&CPU11>;
+ cpu = <&cpu11>;
};
};
};
@@ -274,32 +274,30 @@
idle-states {
entry-method = "psci";
- CLUSTER_C4: cpu-sleep-0 {
+ cluster_c4: cpu-sleep-0 {
compatible = "arm,idle-state";
idle-state-name = "ret";
arm,psci-suspend-param = <0x00000004>;
entry-latency-us = <180>;
- exit-latency-us = <320>;
- min-residency-us = <1000>;
+ exit-latency-us = <500>;
+ min-residency-us = <600>;
};
};
domain-idle-states {
- CLUSTER_CL4: cluster-sleep-0 {
+ cluster_cl4: cluster-sleep-0 {
compatible = "domain-idle-state";
- idle-state-name = "l2-ret";
arm,psci-suspend-param = <0x01000044>;
entry-latency-us = <350>;
exit-latency-us = <500>;
min-residency-us = <2500>;
};
- CLUSTER_CL5: cluster-sleep-1 {
+ cluster_cl5: cluster-sleep-1 {
compatible = "domain-idle-state";
- idle-state-name = "ret-pll-off";
arm,psci-suspend-param = <0x01000054>;
entry-latency-us = <2200>;
- exit-latency-us = <2500>;
+ exit-latency-us = <4000>;
min-residency-us = <7000>;
};
};
@@ -310,6 +308,7 @@
compatible = "qcom,scm-x1e80100", "qcom,scm";
interconnects = <&aggre2_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
+ qcom,dload-mode = <&tcsr 0x19000>;
};
};
@@ -340,85 +339,85 @@
compatible = "arm,psci-1.0";
method = "smc";
- CPU_PD0: power-domain-cpu0 {
+ cpu_pd0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD0>;
+ power-domains = <&cluster_pd0>;
};
- CPU_PD1: power-domain-cpu1 {
+ cpu_pd1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD0>;
+ power-domains = <&cluster_pd0>;
};
- CPU_PD2: power-domain-cpu2 {
+ cpu_pd2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD0>;
+ power-domains = <&cluster_pd0>;
};
- CPU_PD3: power-domain-cpu3 {
+ cpu_pd3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD0>;
+ power-domains = <&cluster_pd0>;
};
- CPU_PD4: power-domain-cpu4 {
+ cpu_pd4: power-domain-cpu4 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD1>;
+ power-domains = <&cluster_pd1>;
};
- CPU_PD5: power-domain-cpu5 {
+ cpu_pd5: power-domain-cpu5 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD1>;
+ power-domains = <&cluster_pd1>;
};
- CPU_PD6: power-domain-cpu6 {
+ cpu_pd6: power-domain-cpu6 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD1>;
+ power-domains = <&cluster_pd1>;
};
- CPU_PD7: power-domain-cpu7 {
+ cpu_pd7: power-domain-cpu7 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD1>;
+ power-domains = <&cluster_pd1>;
};
- CPU_PD8: power-domain-cpu8 {
+ cpu_pd8: power-domain-cpu8 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD2>;
+ power-domains = <&cluster_pd2>;
};
- CPU_PD9: power-domain-cpu9 {
+ cpu_pd9: power-domain-cpu9 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD2>;
+ power-domains = <&cluster_pd2>;
};
- CPU_PD10: power-domain-cpu10 {
+ cpu_pd10: power-domain-cpu10 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD2>;
+ power-domains = <&cluster_pd2>;
};
- CPU_PD11: power-domain-cpu11 {
+ cpu_pd11: power-domain-cpu11 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD2>;
+ power-domains = <&cluster_pd2>;
};
- CLUSTER_PD0: power-domain-cpu-cluster0 {
+ cluster_pd0: power-domain-cpu-cluster0 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_CL4>, <&CLUSTER_CL5>;
- power-domains = <&SYSTEM_PD>;
+ domain-idle-states = <&cluster_cl4>, <&cluster_cl5>;
+ power-domains = <&system_pd>;
};
- CLUSTER_PD1: power-domain-cpu-cluster1 {
+ cluster_pd1: power-domain-cpu-cluster1 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_CL4>, <&CLUSTER_CL5>;
- power-domains = <&SYSTEM_PD>;
+ domain-idle-states = <&cluster_cl4>, <&cluster_cl5>;
+ power-domains = <&system_pd>;
};
- CLUSTER_PD2: power-domain-cpu-cluster2 {
+ cluster_pd2: power-domain-cpu-cluster2 {
#power-domain-cells = <0>;
- domain-idle-states = <&CLUSTER_CL4>, <&CLUSTER_CL5>;
- power-domains = <&SYSTEM_PD>;
+ domain-idle-states = <&cluster_cl4>, <&cluster_cl5>;
+ power-domains = <&system_pd>;
};
- SYSTEM_PD: power-domain-system {
+ system_pd: power-domain-system {
#power-domain-cells = <0>;
/* TODO: system-wide idle states */
};
@@ -2924,14 +2923,16 @@
"mhi";
#address-cells = <3>;
#size-cells = <2>;
- ranges = <0x01000000 0 0x00000000 0 0x70200000 0 0x100000>,
- <0x02000000 0 0x70300000 0 0x70300000 0 0x3d00000>;
- bus-range = <0 0xff>;
+ ranges = <0x01000000 0x0 0x00000000 0x0 0x70200000 0x0 0x100000>,
+ <0x02000000 0x0 0x70300000 0x0 0x70300000 0x0 0x1d00000>;
+ bus-range = <0x00 0xff>;
dma-coherent;
linux,pci-domain = <6>;
- num-lanes = <2>;
+ num-lanes = <4>;
+
+ msi-map = <0x0 &gic_its 0xe0000 0x10000>;
interrupts = <GIC_SPI 773 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 774 IRQ_TYPE_LEVEL_HIGH>,
@@ -2997,19 +2998,22 @@
};
pcie6a_phy: phy@1bfc000 {
- compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy";
- reg = <0 0x01bfc000 0 0x2000>;
+ compatible = "qcom,x1e80100-qmp-gen4x4-pcie-phy";
+ reg = <0 0x01bfc000 0 0x2000>,
+ <0 0x01bfe000 0 0x2000>;
clocks = <&gcc GCC_PCIE_6A_PHY_AUX_CLK>,
<&gcc GCC_PCIE_6A_CFG_AHB_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
+ <&tcsr TCSR_PCIE_4L_CLKREF_EN>,
<&gcc GCC_PCIE_6A_PHY_RCHNG_CLK>,
- <&gcc GCC_PCIE_6A_PIPE_CLK>;
+ <&gcc GCC_PCIE_6A_PIPE_CLK>,
+ <&gcc GCC_PCIE_6A_PIPEDIV2_CLK>;
clock-names = "aux",
"cfg_ahb",
"ref",
"rchng",
- "pipe";
+ "pipe",
+ "pipediv2";
resets = <&gcc GCC_PCIE_6A_PHY_BCR>,
<&gcc GCC_PCIE_6A_NOCSR_COM_PHY_BCR>;
@@ -3021,6 +3025,8 @@
power-domains = <&gcc GCC_PCIE_6_PHY_GDSC>;
+ qcom,4ln-config-sel = <&tcsr 0x1a000 0>;
+
#clock-cells = <0>;
clock-output-names = "pcie6a_pipe_clk";
@@ -3097,7 +3103,7 @@
assigned-clocks = <&gcc GCC_PCIE_5_AUX_CLK>;
assigned-clock-rates = <19200000>;
- interconnects = <&pcie_south_anoc MASTER_PCIE_5 QCOM_ICC_TAG_ALWAYS
+ interconnects = <&pcie_north_anoc MASTER_PCIE_5 QCOM_ICC_TAG_ALWAYS
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
<&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
&cnoc_main SLAVE_PCIE_5 QCOM_ICC_TAG_ALWAYS>;
@@ -3124,14 +3130,16 @@
clocks = <&gcc GCC_PCIE_5_AUX_CLK>,
<&gcc GCC_PCIE_5_CFG_AHB_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
+ <&tcsr TCSR_PCIE_2L_5_CLKREF_EN>,
<&gcc GCC_PCIE_5_PHY_RCHNG_CLK>,
- <&gcc GCC_PCIE_5_PIPE_CLK>;
+ <&gcc GCC_PCIE_5_PIPE_CLK>,
+ <&gcc GCC_PCIE_5_PIPEDIV2_CLK>;
clock-names = "aux",
"cfg_ahb",
"ref",
"rchng",
- "pipe";
+ "pipe",
+ "pipediv2";
resets = <&gcc GCC_PCIE_5_PHY_BCR>;
reset-names = "phy";
@@ -3166,8 +3174,8 @@
"mhi";
#address-cells = <3>;
#size-cells = <2>;
- ranges = <0x01000000 0 0x00000000 0 0x7c200000 0 0x100000>,
- <0x02000000 0 0x7c300000 0 0x7c300000 0 0x3d00000>;
+ ranges = <0x01000000 0x0 0x00000000 0x0 0x7c200000 0x0 0x100000>,
+ <0x02000000 0x0 0x7c300000 0x0 0x7c300000 0x0 0x1d00000>;
bus-range = <0x00 0xff>;
dma-coherent;
@@ -3175,6 +3183,8 @@
linux,pci-domain = <4>;
num-lanes = <2>;
+ msi-map = <0x0 &gic_its 0xc0000 0x10000>;
+
interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
@@ -3217,7 +3227,7 @@
assigned-clocks = <&gcc GCC_PCIE_4_AUX_CLK>;
assigned-clock-rates = <19200000>;
- interconnects = <&pcie_south_anoc MASTER_PCIE_4 QCOM_ICC_TAG_ALWAYS
+ interconnects = <&pcie_north_anoc MASTER_PCIE_4 QCOM_ICC_TAG_ALWAYS
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
<&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
&cnoc_main SLAVE_PCIE_4 QCOM_ICC_TAG_ALWAYS>;
@@ -3254,14 +3264,16 @@
clocks = <&gcc GCC_PCIE_4_AUX_CLK>,
<&gcc GCC_PCIE_4_CFG_AHB_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
+ <&tcsr TCSR_PCIE_2L_4_CLKREF_EN>,
<&gcc GCC_PCIE_4_PHY_RCHNG_CLK>,
- <&gcc GCC_PCIE_4_PIPE_CLK>;
+ <&gcc GCC_PCIE_4_PIPE_CLK>,
+ <&gcc GCC_PCIE_4_PIPEDIV2_CLK>;
clock-names = "aux",
"cfg_ahb",
"ref",
"rchng",
- "pipe";
+ "pipe",
+ "pipediv2";
resets = <&gcc GCC_PCIE_4_PHY_BCR>;
reset-names = "phy";
@@ -3386,7 +3398,7 @@
reg = <0x0 0x03d6a000 0x0 0x35000>,
<0x0 0x03d50000 0x0 0x10000>,
<0x0 0x0b280000 0x0 0x10000>;
- reg-names = "gmu", "rscc", "gmu_pdc";
+ reg-names = "gmu", "rscc", "gmu_pdc";
interrupts = <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>;
@@ -4054,6 +4066,8 @@
dma-coherent;
+ usb-role-switch;
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -4307,6 +4321,8 @@
dma-coherent;
+ usb-role-switch;
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -4405,6 +4421,8 @@
dma-coherent;
+ usb-role-switch;
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -5738,12 +5756,14 @@
#iommu-cells = <2>;
#global-interrupts = <1>;
+
+ dma-coherent;
};
intc: interrupt-controller@17000000 {
compatible = "arm,gic-v3";
reg = <0 0x17000000 0 0x10000>, /* GICD */
- <0 0x17080000 0 0x480000>; /* GICR * 12 */
+ <0 0x17080000 0 0x300000>; /* GICR * 12 */
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
@@ -5763,8 +5783,6 @@
msi-controller;
#msi-cells = <1>;
-
- status = "disabled";
};
};
@@ -5784,7 +5802,7 @@
<WAKE_TCS 2>, <CONTROL_TCS 0>;
label = "apps_rsc";
- power-domains = <&SYSTEM_PD>;
+ power-domains = <&system_pd>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
@@ -6084,7 +6102,8 @@
<0 0x25a00000 0 0x200000>,
<0 0x25c00000 0 0x200000>,
<0 0x25e00000 0 0x200000>,
- <0 0x26000000 0 0x200000>;
+ <0 0x26000000 0 0x200000>,
+ <0 0x26200000 0 0x200000>;
reg-names = "llcc0_base",
"llcc1_base",
"llcc2_base",
@@ -6093,7 +6112,8 @@
"llcc5_base",
"llcc6_base",
"llcc7_base",
- "llcc_broadcast_base";
+ "llcc_broadcast_base",
+ "llcc_broadcast_and_base";
interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
};
diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
index 5a14f116f7a1..d55f2d7066ad 100644
--- a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
+++ b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi
@@ -200,7 +200,7 @@
widgets = "Microphone", "Mic Jack",
"Line", "Line In Jack",
"Headphone", "Headphone Jack";
- mic-det-gpio = <&gpio0 2 GPIO_ACTIVE_LOW>;
+ mic-det-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
routing = "Headphone Jack", "HPOUTL",
"Headphone Jack", "HPOUTR",
"IN3R", "MICBIAS",
@@ -364,6 +364,8 @@
#clock-cells = <1>;
clocks = <&x304_clk>;
clock-names = "xin";
+ idt,shutdown = <0>;
+ idt,output-enable-active = <0>;
assigned-clocks = <&versaclock6_bb 1>, <&versaclock6_bb 2>,
<&versaclock6_bb 3>, <&versaclock6_bb 4>;
@@ -440,16 +442,14 @@
touchscreen@26 {
compatible = "ilitek,ili2117";
reg = <0x26>;
- interrupt-parent = <&gpio5>;
- interrupts = <9 IRQ_TYPE_EDGE_RISING>;
+ interrupts-extended = <&gpio5 9 IRQ_TYPE_EDGE_RISING>;
wakeup-source;
};
hd3ss3220@47 {
compatible = "ti,hd3ss3220";
reg = <0x47>;
- interrupt-parent = <&gpio6>;
- interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio6 4 IRQ_TYPE_LEVEL_LOW>;
ports {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi
index 68b04e56ae56..43f88c199b78 100644
--- a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi
@@ -62,8 +62,7 @@
compatible = "ethernet-phy-id0022.1640",
"ethernet-phy-ieee802.3-c22";
reg = <0>;
- interrupt-parent = <&gpio2>;
- interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 11 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
};
};
@@ -131,8 +130,7 @@
pca9654_lte: gpio@21 {
compatible = "onnn,pca9654";
reg = <0x21>;
- interrupt-parent = <&gpio5>;
- interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio5 25 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
@@ -166,6 +164,8 @@
#clock-cells = <1>;
clocks = <&x304_clk>;
clock-names = "xin";
+ idt,shutdown = <0>;
+ idt,output-enable-active = <0>;
/* du_dotclkin0, du_dotclkin2, usb_extal, avb_txcrefclk */
assigned-clocks = <&versaclock5 1>,
<&versaclock5 2>,
@@ -302,8 +302,7 @@
brcmf: bcrmf@1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
- interrupt-parent = <&gpio1>;
- interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 27 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "host-wake";
};
};
diff --git a/arch/arm64/boot/dts/renesas/cat875.dtsi b/arch/arm64/boot/dts/renesas/cat875.dtsi
index 8c9da8b4bd60..191b051ecfd4 100644
--- a/arch/arm64/boot/dts/renesas/cat875.dtsi
+++ b/arch/arm64/boot/dts/renesas/cat875.dtsi
@@ -25,8 +25,7 @@
compatible = "ethernet-phy-id001c.c915",
"ethernet-phy-ieee802.3-c22";
reg = <0>;
- interrupt-parent = <&gpio2>;
- interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 21 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/condor-common.dtsi b/arch/arm64/boot/dts/renesas/condor-common.dtsi
index 8b7c0c34eadc..375a56b20f26 100644
--- a/arch/arm64/boot/dts/renesas/condor-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/condor-common.dtsi
@@ -166,8 +166,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio4>;
- interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio4 23 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>;
};
};
@@ -196,8 +195,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 20 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&d1_8v>;
dvdd-supply = <&d1_8v>;
pvdd-supply = <&d1_8v>;
diff --git a/arch/arm64/boot/dts/renesas/draak.dtsi b/arch/arm64/boot/dts/renesas/draak.dtsi
index 6f133f54ded5..05712cd96d28 100644
--- a/arch/arm64/boot/dts/renesas/draak.dtsi
+++ b/arch/arm64/boot/dts/renesas/draak.dtsi
@@ -247,8 +247,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio5>;
- interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio5 19 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio5 18 GPIO_ACTIVE_LOW>;
/*
* TX clock internal delay mode is required for reliable
@@ -368,8 +367,7 @@
compatible = "adi,adv7511w";
reg = <0x39>, <0x3f>, <0x3c>, <0x38>;
reg-names = "main", "edid", "cec", "packet";
- interrupt-parent = <&gpio1>;
- interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&reg_1p8v>;
dvdd-supply = <&reg_1p8v>;
diff --git a/arch/arm64/boot/dts/renesas/ebisu.dtsi b/arch/arm64/boot/dts/renesas/ebisu.dtsi
index cba2fde9dd36..ab8283656660 100644
--- a/arch/arm64/boot/dts/renesas/ebisu.dtsi
+++ b/arch/arm64/boot/dts/renesas/ebisu.dtsi
@@ -314,8 +314,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio2>;
- interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 21 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
/*
* TX clock internal delay mode is required for reliable
@@ -393,15 +392,13 @@
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
- interrupt-parent = <&gpio2>;
- interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 22 IRQ_TYPE_LEVEL_LOW>;
};
hdmi-encoder@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 1 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&reg_1p8v>;
dvdd-supply = <&reg_1p8v>;
@@ -437,10 +434,9 @@
compatible = "adi,adv7482";
reg = <0x70>;
- interrupt-parent = <&gpio0>;
+ interrupts-extended = <&gpio0 7 IRQ_TYPE_LEVEL_LOW>,
+ <&gpio0 17 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "intrq1", "intrq2";
- interrupts = <7 IRQ_TYPE_LEVEL_LOW>,
- <17 IRQ_TYPE_LEVEL_LOW>;
ports {
#address-cells = <1>;
@@ -517,8 +513,7 @@
compatible = "rohm,bd9571mwv";
reg = <0x30>;
- interrupt-parent = <&intc_ex>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&intc_ex 0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/renesas/hihope-common.dtsi b/arch/arm64/boot/dts/renesas/hihope-common.dtsi
index 83104af2813e..659ae1fed2fa 100644
--- a/arch/arm64/boot/dts/renesas/hihope-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-common.dtsi
@@ -198,6 +198,8 @@
#clock-cells = <1>;
clocks = <&x304_clk>;
clock-names = "xin";
+ idt,shutdown = <0>;
+ idt,output-enable-active = <1>;
};
};
@@ -325,8 +327,7 @@
wlcore: wlcore@2 {
compatible = "ti,wl1837";
reg = <2>;
- interrupt-parent = <&gpio2>;
- interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&gpio2 5 IRQ_TYPE_LEVEL_HIGH>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi b/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi
index 8e2db1d6ca81..25c55b32aafe 100644
--- a/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi
@@ -69,9 +69,6 @@
status = "okay";
- /* Single DAI */
- #sound-dai-cells = <0>;
-
rsnd_port: port {
rsnd_endpoint: endpoint {
remote-endpoint = <&dw_hdmi0_snd_in>;
diff --git a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
index 66f3affe0469..deb69c272775 100644
--- a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
@@ -84,9 +84,6 @@
pinctrl-names = "default";
status = "okay";
- /* Single DAI */
- #sound-dai-cells = <0>;
-
/* audio_clkout0/1/2/3 */
#clock-cells = <1>;
clock-frequency = <12288000 11289600>;
diff --git a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
index ad898c6db4e6..4113710d5522 100644
--- a/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
+++ b/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
@@ -27,8 +27,7 @@
compatible = "ethernet-phy-id001c.c915",
"ethernet-phy-ieee802.3-c22";
reg = <0>;
- interrupt-parent = <&gpio2>;
- interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 11 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
index 5a6ea08ffd2b..b78dbd807d15 100644
--- a/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
+++ b/arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
@@ -208,8 +208,7 @@
hd3ss3220@47 {
compatible = "ti,hd3ss3220";
reg = <0x47>;
- interrupt-parent = <&gpio6>;
- interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio6 3 IRQ_TYPE_LEVEL_LOW>;
ports {
#address-cells = <1>;
@@ -232,8 +231,7 @@
tda19988: tda19988@70 {
compatible = "nxp,tda998x";
reg = <0x70>;
- interrupt-parent = <&gpio1>;
- interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 1 IRQ_TYPE_LEVEL_LOW>;
video-ports = <0x234501>;
@@ -414,8 +412,7 @@
wlcore: wlcore@2 {
compatible = "ti,wl1837";
reg = <2>;
- interrupt-parent = <&gpio1>;
- interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&gpio1 0 IRQ_TYPE_LEVEL_HIGH>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle-function-expansion.dtso b/arch/arm64/boot/dts/renesas/r8a77970-eagle-function-expansion.dtso
index 3aa243c5f04c..9450d8ac94cb 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle-function-expansion.dtso
+++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle-function-expansion.dtso
@@ -82,8 +82,7 @@
compatible = "adi,adv7612";
reg = <0x4c>, <0x50>, <0x52>, <0x54>, <0x56>, <0x58>;
reg-names = "main", "afe", "rep", "edid", "hdmi", "cp";
- interrupt-parent = <&gpio3>;
- interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 2 IRQ_TYPE_LEVEL_LOW>;
default-input = <0>;
ports {
@@ -114,8 +113,8 @@
0x60 0x61 0x62 0x63 0x64 0x65>;
reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater",
"infoframe", "cbus", "cec", "sdp", "txa", "txb" ;
- interrupt-parent = <&gpio3>;
- interrupts = <03 IRQ_TYPE_LEVEL_LOW>, <04 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 3 IRQ_TYPE_LEVEL_LOW>,
+ <&gpio3 4 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "intrq1", "intrq2";
ports {
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
index 0608dce92e40..32f07aa27316 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
@@ -111,8 +111,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio1>;
- interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 17 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
};
};
@@ -172,8 +171,7 @@
hdmi@39 {
compatible = "adi,adv7511w";
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 20 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&d1p8>;
dvdd-supply = <&d1p8>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
index e36999e91af5..118e77f4477e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
@@ -117,8 +117,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio1>;
- interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 17 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
};
};
@@ -149,8 +148,7 @@
compatible = "adi,adv7511w";
#sound-dai-cells = <0>;
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 20 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&vcc_d1_8v>;
dvdd-supply = <&vcc_d1_8v>;
pvdd-supply = <&vcc_d1_8v>;
diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
index 77d22df25fff..b409a8d1737e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
@@ -124,8 +124,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio4>;
- interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio4 23 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>;
};
};
@@ -141,8 +140,7 @@
compatible = "adi,adv7511w";
#sound-dai-cells = <0>;
reg = <0x39>;
- interrupt-parent = <&gpio1>;
- interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio1 20 IRQ_TYPE_LEVEL_LOW>;
avdd-supply = <&vcc1v8_d4>;
dvdd-supply = <&vcc1v8_d4>;
pvdd-supply = <&vcc1v8_d4>;
diff --git a/arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi
index 99b73e21c82c..e8c8fca48b69 100644
--- a/arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi
@@ -208,8 +208,7 @@
clocks = <&sn65dsi86_refclk>;
clock-names = "refclk";
- interrupt-parent = <&intc_ex>;
- interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&intc_ex 0 IRQ_TYPE_LEVEL_HIGH>;
vccio-supply = <&reg_1p8v>;
vpll-supply = <&reg_1p8v>;
diff --git a/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts b/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts
index 63db822e5f46..6bd580737f25 100644
--- a/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts
@@ -31,8 +31,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio4>;
- interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio4 16 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
index 1f4ab27acc33..7156b1a542e8 100644
--- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
@@ -245,6 +245,14 @@
#interrupt-cells = <2>;
};
+ fuse: fuse@e6078800 {
+ compatible = "renesas,r8a779a0-efuse";
+ reg = <0 0xe6078800 0 0x100>;
+ clocks = <&cpg CPG_MOD 916>;
+ power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
+ resets = <&cpg 916>;
+ };
+
cmt0: timer@e60f0000 {
compatible = "renesas,r8a779a0-cmt0",
"renesas,rcar-gen4-cmt0";
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
index 4ed8d4c37906..e03baefb6a98 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
@@ -171,7 +171,7 @@
};
&pciec0 {
- reset-gpio = <&gpio_exp_20 0 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio_exp_20 0 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi
index 33c1015e9ab3..5d38669ed1ec 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi
@@ -60,8 +60,7 @@
u101: ethernet-phy@1 {
reg = <1>;
compatible = "ethernet-phy-ieee802.3-c45";
- interrupt-parent = <&gpio3>;
- interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 10 IRQ_TYPE_LEVEL_LOW>;
};
};
};
@@ -78,8 +77,7 @@
u201: ethernet-phy@2 {
reg = <2>;
compatible = "ethernet-phy-ieee802.3-c45";
- interrupt-parent = <&gpio3>;
- interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 11 IRQ_TYPE_LEVEL_LOW>;
};
};
};
@@ -96,8 +94,7 @@
u301: ethernet-phy@3 {
reg = <3>;
compatible = "ethernet-phy-ieee802.3-c45";
- interrupt-parent = <&gpio3>;
- interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 9 IRQ_TYPE_LEVEL_LOW>;
};
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
index 9629adb47d99..054498e54730 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
@@ -377,6 +377,14 @@
#interrupt-cells = <2>;
};
+ fuse: fuse@e6078800 {
+ compatible = "renesas,r8a779f0-efuse";
+ reg = <0 0xe6078800 0 0x200>;
+ clocks = <&cpg CPG_MOD 915>;
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 915>;
+ };
+
cmt0: timer@e60f0000 {
compatible = "renesas,r8a779f0-cmt0",
"renesas,rcar-gen4-cmt0";
diff --git a/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
index fa910b85859e..5d71d52f9c65 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts
@@ -197,8 +197,7 @@
ic99: ethernet-phy@1 {
reg = <1>;
compatible = "ethernet-phy-ieee802.3-c45";
- interrupt-parent = <&gpio3>;
- interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 10 IRQ_TYPE_LEVEL_LOW>;
};
};
};
@@ -216,8 +215,7 @@
ic102: ethernet-phy@2 {
reg = <2>;
compatible = "ethernet-phy-ieee802.3-c45";
- interrupt-parent = <&gpio3>;
- interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio3 11 IRQ_TYPE_LEVEL_LOW>;
};
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
index 12900ebd098b..61c6b8022ffd 100644
--- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
@@ -477,6 +477,11 @@
#thermal-sensor-cells = <1>;
};
+ otp: otp@e61be000 {
+ compatible = "renesas,r8a779g0-otp";
+ reg = <0 0xe61be000 0 0x1000>, <0 0xe61bf000 0 0x1000>;
+ };
+
intc_ex: interrupt-controller@e61c0000 {
compatible = "renesas,intc-ex-r8a779g0", "renesas,irqc";
#interrupt-cells = <2>;
diff --git a/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts b/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts
index 50a428572d9b..0062362b0ba0 100644
--- a/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts
@@ -70,8 +70,7 @@
compatible = "ethernet-phy-id002b.0980",
"ethernet-phy-ieee802.3-c22";
reg = <0>;
- interrupt-parent = <&gpio4>;
- interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio4 3 IRQ_TYPE_LEVEL_LOW>;
};
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts b/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts
index 9a1917b87f61..58eabcc7e0e0 100644
--- a/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts
@@ -126,6 +126,12 @@
reg = <0x4 0x80000000 0x1 0x80000000>;
};
+ pcie_clk: clk-9fgv0841-pci {
+ compatible = "fixed-clock";
+ clock-frequency = <100000000>;
+ #clock-cells = <0>;
+ };
+
reg_1p8v: regulator-1p8v {
compatible = "regulator-fixed";
regulator-name = "fixed-1.8V";
@@ -175,8 +181,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio7>;
- interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio7 5 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio7 10 GPIO_ACTIVE_LOW>;
};
};
@@ -240,6 +245,16 @@
status = "okay";
clock-frequency = <400000>;
+ io_expander_a: gpio@20 {
+ compatible = "onnn,pca9654";
+ reg = <0x20>;
+ interrupts-extended = <&gpio0 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";
@@ -309,6 +324,18 @@
status = "okay";
};
+&pcie0_clkref {
+ compatible = "gpio-gate-clock";
+ clocks = <&pcie_clk>;
+ enable-gpios = <&gpio4 21 GPIO_ACTIVE_LOW>;
+ /delete-property/ clock-frequency;
+};
+
+&pciec0 {
+ reset-gpios = <&io_expander_a 0 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
&pfc {
pinctrl-0 = <&scif_clk_pins>, <&scif_clk2_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a779h0.dtsi b/arch/arm64/boot/dts/renesas/r8a779h0.dtsi
index 12d8be3fd579..facfff4b9cdc 100644
--- a/arch/arm64/boot/dts/renesas/r8a779h0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779h0.dtsi
@@ -147,6 +147,13 @@
clock-frequency = <0>;
};
+ pcie0_clkref: pcie0-clkref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
pmu-a76 {
compatible = "arm,cortex-a76-pmu";
interrupts-extended = <&gic GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
@@ -417,6 +424,11 @@
#thermal-sensor-cells = <1>;
};
+ otp: otp@e61be000 {
+ compatible = "renesas,r8a779h0-otp";
+ reg = <0 0xe61be000 0 0x1000>, <0 0xe61bf000 0 0x1000>;
+ };
+
intc_ex: interrupt-controller@e61c0000 {
compatible = "renesas,intc-ex-r8a779h0", "renesas,irqc";
#interrupt-cells = <2>;
@@ -643,6 +655,66 @@
status = "disabled";
};
+ pciec0: pcie@e65d0000 {
+ compatible = "renesas,r8a779h0-pcie",
+ "renesas,rcar-gen4-pcie";
+ reg = <0 0xe65d0000 0 0x1000>, <0 0xe65d2000 0 0x0800>,
+ <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>,
+ <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>,
+ <0 0xfe000000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "config";
+ interrupts = <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779H0_PD_A2PCIPHY>;
+ resets = <&cpg 624>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ ranges = <0x01000000 0 0x00000000 0 0xfe000000 0 0x00400000>,
+ <0x02000000 0 0x30000000 0 0x30000000 0 0x10000000>;
+ dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>;
+ snps,enable-cdm-check;
+ status = "disabled";
+ };
+
+ pciec0_ep: pcie-ep@e65d0000 {
+ compatible = "renesas,r8a779h0-pcie-ep",
+ "renesas,rcar-gen4-pcie-ep";
+ reg = <0 0xe65d0000 0 0x2000>, <0 0xe65d2000 0 0x1000>,
+ <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>,
+ <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>,
+ <0 0xfe000000 0 0x400000>;
+ reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "addr_space";
+ interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dma", "sft_ce", "app";
+ clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>;
+ clock-names = "core", "ref";
+ power-domains = <&sysc R8A779H0_PD_A2PCIPHY>;
+ resets = <&cpg 624>;
+ reset-names = "pwr";
+ max-link-speed = <4>;
+ num-lanes = <2>;
+ max-functions = /bits/ 8 <2>;
+ status = "disabled";
+ };
+
canfd: can@e6660000 {
compatible = "renesas,r8a779h0-canfd",
"renesas,rcar-gen4-canfd";
diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
index 067a26a66c24..be8a0a768c65 100644
--- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/r9a08g045-cpg.h>
+#include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
/ {
compatible = "renesas,r9a08g045";
@@ -72,6 +73,32 @@
status = "disabled";
};
+ rtc: rtc@1004ec00 {
+ compatible = "renesas,r9a08g045-rtca3", "renesas,rz-rtca3";
+ reg = <0 0x1004ec00 0 0x400>;
+ interrupts = <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "alarm", "period", "carry";
+ clocks = <&cpg CPG_MOD R9A08G045_VBAT_BCLK>, <&vbattb VBATTB_VBATTCLK>;
+ clock-names = "bus", "counter";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_VBAT_BRESETN>;
+ status = "disabled";
+ };
+
+ vbattb: clock-controller@1005c000 {
+ compatible = "renesas,r9a08g045-vbattb";
+ reg = <0 0x1005c000 0 0x1000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD R9A08G045_VBAT_BCLK>, <&vbattb_xtal>;
+ clock-names = "bclk", "rtx";
+ #clock-cells = <1>;
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_VBAT_BRESETN>;
+ status = "disabled";
+ };
+
i2c0: i2c@10090000 {
compatible = "renesas,riic-r9a08g045", "renesas,riic-r9a09g057";
reg = <0 0x10090000 0 0x400>;
@@ -425,4 +452,11 @@
interrupt-names = "sec-phys", "phys", "virt", "hyp-phys",
"hyp-virt";
};
+
+ vbattb_xtal: vbattb-xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board. */
+ clock-frequency = <0>;
+ };
};
diff --git a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
index 1ad5a1b6917f..1c550b22b164 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
@@ -20,6 +20,39 @@
clock-frequency = <0>;
};
+ /*
+ * The default cluster table is based on the assumption that the PLLCA55 clock
+ * frequency is set to 1.7GHz. The PLLCA55 clock frequency can be set to
+ * 1.7/1.6/1.5/1.1 GHz based on the BOOTPLLCA_0/1 pins (and additionally can be
+ * clocked to 1.8GHz as well). The table below should be overridden in the board
+ * DTS based on the PLLCA55 clock frequency.
+ */
+ cluster0_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+
+ opp-1700000000 {
+ opp-hz = /bits/ 64 <1700000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-850000000 {
+ opp-hz = /bits/ 64 <850000000>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-425000000 {
+ opp-hz = /bits/ 64 <425000000>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-212500000 {
+ opp-hz = /bits/ 64 <212500000>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <300000>;
+ opp-suspend;
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -30,6 +63,8 @@
device_type = "cpu";
next-level-cache = <&L3_CA55>;
enable-method = "psci";
+ clocks = <&cpg CPG_CORE R9A09G057_CA55_0_CORE_CLK0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu1: cpu@100 {
@@ -38,6 +73,8 @@
device_type = "cpu";
next-level-cache = <&L3_CA55>;
enable-method = "psci";
+ clocks = <&cpg CPG_CORE R9A09G057_CA55_0_CORE_CLK1>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu2: cpu@200 {
@@ -46,6 +83,8 @@
device_type = "cpu";
next-level-cache = <&L3_CA55>;
enable-method = "psci";
+ clocks = <&cpg CPG_CORE R9A09G057_CA55_0_CORE_CLK2>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu3: cpu@300 {
@@ -54,6 +93,8 @@
device_type = "cpu";
next-level-cache = <&L3_CA55>;
enable-method = "psci";
+ clocks = <&cpg CPG_CORE R9A09G057_CA55_0_CORE_CLK3>;
+ operating-points-v2 = <&cluster0_opp>;
};
L3_CA55: cache-controller-0 {
@@ -90,6 +131,95 @@
#size-cells = <2>;
ranges;
+ icu: interrupt-controller@10400000 {
+ compatible = "renesas,r9a09g057-icu";
+ reg = <0 0x10400000 0 0x10000>;
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ interrupt-controller;
+ 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>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 262 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 263 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 264 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 265 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "nmi",
+ "port_irq0", "port_irq1", "port_irq2",
+ "port_irq3", "port_irq4", "port_irq5",
+ "port_irq6", "port_irq7", "port_irq8",
+ "port_irq9", "port_irq10", "port_irq11",
+ "port_irq12", "port_irq13", "port_irq14",
+ "port_irq15",
+ "tint0", "tint1", "tint2", "tint3",
+ "tint4", "tint5", "tint6", "tint7",
+ "tint8", "tint9", "tint10", "tint11",
+ "tint12", "tint13", "tint14", "tint15",
+ "tint16", "tint17", "tint18", "tint19",
+ "tint20", "tint21", "tint22", "tint23",
+ "tint24", "tint25", "tint26", "tint27",
+ "tint28", "tint29", "tint30", "tint31",
+ "int-ca55-0", "int-ca55-1",
+ "int-ca55-2", "int-ca55-3",
+ "icu-error-ca55",
+ "gpt-u0-gtciada", "gpt-u0-gtciadb",
+ "gpt-u1-gtciada", "gpt-u1-gtciadb";
+ clocks = <&cpg CPG_MOD 0x5>;
+ power-domains = <&cpg>;
+ resets = <&cpg 0x36>;
+ };
+
pinctrl: pinctrl@10410000 {
compatible = "renesas,r9a09g057-pinctrl";
reg = <0 0x10410000 0 0x10000>;
@@ -99,6 +229,7 @@
gpio-ranges = <&pinctrl 0 0 96>;
#interrupt-cells = <2>;
interrupt-controller;
+ interrupt-parent = <&icu>;
power-domains = <&cpg>;
resets = <&cpg 0xa5>, <&cpg 0xa6>;
};
diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi
index 83f5642d0d35..21cf198b3c17 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi
@@ -102,8 +102,7 @@
compatible = "ethernet-phy-id0022.1640",
"ethernet-phy-ieee802.3-c22";
reg = <7>;
- interrupt-parent = <&irqc>;
- interrupts = <RZG2L_IRQ2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc RZG2L_IRQ2 IRQ_TYPE_LEVEL_LOW>;
rxc-skew-psec = <2400>;
txc-skew-psec = <2400>;
rxdv-skew-psec = <0>;
@@ -130,8 +129,7 @@
compatible = "ethernet-phy-id0022.1640",
"ethernet-phy-ieee802.3-c22";
reg = <7>;
- interrupt-parent = <&irqc>;
- interrupts = <RZG2L_IRQ3 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc RZG2L_IRQ3 IRQ_TYPE_LEVEL_LOW>;
rxc-skew-psec = <2400>;
txc-skew-psec = <2400>;
rxdv-skew-psec = <0>;
@@ -341,11 +339,18 @@
#address-cells = <1>;
#size-cells = <1>;
- boot@0 {
- reg = <0x00000000 0x2000000>;
- read-only;
+ partition@0 {
+ label = "bl2";
+ reg = <0x00000000 0x0001d000>;
};
- user@2000000 {
+
+ partition@1d000 { /* fip is at offset 0x200 */
+ label = "fip";
+ reg = <0x0001d000 0x1fe3000>;
+ };
+
+ partition@2000000 {
+ label = "user";
reg = <0x2000000 0x2000000>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
index ee3d96fdb616..789f7b0b5ebc 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
@@ -64,8 +64,7 @@
compatible = "adi,adv7535";
reg = <0x3d>;
- interrupt-parent = <&pinctrl>;
- interrupts = <RZG2L_GPIO(2, 1) IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&pinctrl RZG2L_GPIO(2, 1) IRQ_TYPE_EDGE_FALLING>;
clocks = <&osc1>;
clock-names = "cec";
avdd-supply = <&reg_1p8v>;
diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi
index b4ef5ea8a9e3..9aa729fbdce0 100644
--- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi
@@ -82,8 +82,7 @@
compatible = "ethernet-phy-id0022.1640",
"ethernet-phy-ieee802.3-c22";
reg = <7>;
- interrupt-parent = <&irqc>;
- interrupts = <RZG2L_IRQ0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc RZG2L_IRQ0 IRQ_TYPE_LEVEL_LOW>;
rxc-skew-psec = <2400>;
txc-skew-psec = <2400>;
rxdv-skew-psec = <0>;
@@ -259,11 +258,18 @@
#address-cells = <1>;
#size-cells = <1>;
- boot@0 {
- reg = <0x00000000 0x2000000>;
- read-only;
+ partition@0 {
+ label = "bl2";
+ reg = <0x00000000 0x0001d000>;
};
- user@2000000 {
+
+ partition@1d000 { /* fip is at offset 0x200 */
+ label = "fip";
+ reg = <0x0001d000 0x1fe3000>;
+ };
+
+ partition@2000000 {
+ label = "user";
reg = <0x2000000 0x2000000>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
index 377849cbb462..345b779e4f60 100644
--- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
@@ -86,8 +86,7 @@
compatible = "adi,adv7535";
reg = <0x3d>;
- interrupt-parent = <&pinctrl>;
- interrupts = <RZG2L_GPIO(43, 1) IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&pinctrl RZG2L_GPIO(43, 1) IRQ_TYPE_EDGE_FALLING>;
clocks = <&osc1>;
clock-names = "cec";
avdd-supply = <&reg_1p8v>;
diff --git a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi
index 79443fb3f581..cd4275d86935 100644
--- a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi
@@ -78,8 +78,7 @@
compatible = "ethernet-phy-id0022.1640",
"ethernet-phy-ieee802.3-c22";
reg = <7>;
- interrupt-parent = <&irqc>;
- interrupts = <RZG2L_IRQ2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc RZG2L_IRQ2 IRQ_TYPE_LEVEL_LOW>;
rxc-skew-psec = <2400>;
txc-skew-psec = <2400>;
rxdv-skew-psec = <0>;
@@ -107,8 +106,7 @@
compatible = "ethernet-phy-id0022.1640",
"ethernet-phy-ieee802.3-c22";
reg = <7>;
- interrupt-parent = <&irqc>;
- interrupts = <RZG2L_IRQ7 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&irqc RZG2L_IRQ7 IRQ_TYPE_LEVEL_LOW>;
rxc-skew-psec = <2400>;
txc-skew-psec = <2400>;
rxdv-skew-psec = <0>;
@@ -201,6 +199,12 @@
};
};
+ qspi0_pins: qspi0 {
+ pins = "QSPI0_IO0", "QSPI0_IO1", "QSPI0_IO2", "QSPI0_IO3",
+ "QSPI0_SPCLK", "QSPI0_SSL";
+ power-source = <1800>;
+ };
+
sdhi0_emmc_pins: sd0emmc {
sd0_emmc_data {
pins = "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3",
@@ -252,6 +256,45 @@
};
};
+&sbc {
+ pinctrl-0 = <&qspi0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+
+ spi-cpol;
+ spi-cpha;
+ m25p,fast-read;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl2";
+ reg = <0x00000000 0x0001d000>;
+ };
+
+ partition@1d000 { /* fip is at offset 0x200 */
+ label = "fip";
+ reg = <0x0001d000 0x7e3000>;
+ };
+
+ partition@800000 {
+ label = "user";
+ reg = <0x800000 0x800000>;
+ };
+ };
+ };
+};
+
#if (SW_SW0_DEV_SEL)
&sdhi0 {
pinctrl-0 = <&sdhi0_emmc_pins>;
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
index 21bfa4e03972..2ed01d391554 100644
--- a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
@@ -5,6 +5,7 @@
* Copyright (C) 2023 Renesas Electronics Corp.
*/
+#include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
@@ -103,8 +104,7 @@
phy0: ethernet-phy@7 {
reg = <7>;
- interrupt-parent = <&pinctrl>;
- interrupts = <RZG2L_GPIO(12, 0) IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&pinctrl RZG2L_GPIO(12, 0) IRQ_TYPE_EDGE_FALLING>;
rxc-skew-psec = <0>;
txc-skew-psec = <0>;
rxdv-skew-psec = <0>;
@@ -129,8 +129,7 @@
phy1: ethernet-phy@7 {
reg = <7>;
- interrupt-parent = <&pinctrl>;
- interrupts = <RZG2L_GPIO(12, 1) IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&pinctrl RZG2L_GPIO(12, 1) IRQ_TYPE_EDGE_FALLING>;
rxc-skew-psec = <0>;
txc-skew-psec = <0>;
rxdv-skew-psec = <0>;
@@ -346,6 +345,21 @@
};
};
+&rtc {
+ status = "okay";
+};
+
+&vbattb {
+ assigned-clocks = <&vbattb VBATTB_MUX>;
+ assigned-clock-parents = <&vbattb VBATTB_XC>;
+ quartz-load-femtofarads = <12500>;
+ status = "okay";
+};
+
+&vbattb_xtal {
+ clock-frequency = <32768>;
+};
+
&wdt0 {
timeout-sec = <60>;
status = "okay";
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi
index 7945d44e6ee1..4509151344c4 100644
--- a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi
@@ -20,8 +20,7 @@
compatible = "gpio-keys";
key-1 {
- interrupts = <RZG2L_GPIO(18, 0) IRQ_TYPE_EDGE_FALLING>;
- interrupt-parent = <&pinctrl>;
+ interrupts-extended = <&pinctrl RZG2L_GPIO(18, 0) IRQ_TYPE_EDGE_FALLING>;
linux,code = <KEY_1>;
label = "USER_SW1";
wakeup-source;
@@ -29,8 +28,7 @@
};
key-2 {
- interrupts = <RZG2L_GPIO(0, 1) IRQ_TYPE_EDGE_FALLING>;
- interrupt-parent = <&pinctrl>;
+ interrupts-extended = <&pinctrl RZG2L_GPIO(0, 1) IRQ_TYPE_EDGE_FALLING>;
linux,code = <KEY_2>;
label = "USER_SW2";
wakeup-source;
@@ -38,8 +36,7 @@
};
key-3 {
- interrupts = <RZG2L_GPIO(0, 3) IRQ_TYPE_EDGE_FALLING>;
- interrupt-parent = <&pinctrl>;
+ interrupts-extended = <&pinctrl RZG2L_GPIO(0, 3) IRQ_TYPE_EDGE_FALLING>;
linux,code = <KEY_3>;
label = "USER_SW3";
wakeup-source;
diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
index 1eb4883b3219..06c7e9746304 100644
--- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
@@ -353,8 +353,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio2>;
- interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 11 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
};
};
@@ -531,10 +530,9 @@
reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater",
"infoframe", "cbus", "cec", "sdp", "txa", "txb" ;
- interrupt-parent = <&gpio6>;
+ interrupts-extended = <&gpio6 30 IRQ_TYPE_LEVEL_LOW>,
+ <&gpio6 31 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "intrq1", "intrq2";
- interrupts = <30 IRQ_TYPE_LEVEL_LOW>,
- <31 IRQ_TYPE_LEVEL_LOW>;
ports {
#address-cells = <1>;
@@ -604,8 +602,7 @@
compatible = "rohm,bd9571mwv";
reg = <0x30>;
- interrupt-parent = <&intc_ex>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&intc_ex 0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/renesas/salvator-x.dtsi b/arch/arm64/boot/dts/renesas/salvator-x.dtsi
index ddee50e64632..5920932cbc2f 100644
--- a/arch/arm64/boot/dts/renesas/salvator-x.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-x.dtsi
@@ -25,5 +25,7 @@
#clock-cells = <1>;
clocks = <&x23_clk>;
clock-names = "xin";
+ idt,shutdown = <0>;
+ idt,output-enable-active = <1>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/salvator-xs.dtsi b/arch/arm64/boot/dts/renesas/salvator-xs.dtsi
index 08b925624e12..1d18dedb1ff0 100644
--- a/arch/arm64/boot/dts/renesas/salvator-xs.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-xs.dtsi
@@ -25,6 +25,8 @@
#clock-cells = <1>;
clocks = <&x23_clk>;
clock-names = "xin";
+ idt,shutdown = <0>;
+ idt,output-enable-active = <1>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
index 431b37bf5661..5c211ed83049 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
@@ -150,8 +150,7 @@
pinctrl-0 = <&hdmi1_pins>;
pinctrl-names = "default";
- interrupt-parent = <&gpio2>;
- interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 14 IRQ_TYPE_LEVEL_LOW>;
clocks = <&cs2000>;
clock-names = "cec";
@@ -236,8 +235,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
- interrupt-parent = <&gpio6>;
- interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio6 8 IRQ_TYPE_EDGE_FALLING>;
audio-out-off-hog {
gpio-hog;
@@ -297,8 +295,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
- interrupt-parent = <&gpio6>;
- interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio6 4 IRQ_TYPE_EDGE_FALLING>;
};
};
@@ -318,8 +315,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
- interrupt-parent = <&gpio7>;
- interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio7 3 IRQ_TYPE_EDGE_FALLING>;
};
gpio_exp_77: gpio@77 {
@@ -329,8 +325,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
- interrupt-parent = <&gpio5>;
- interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio5 9 IRQ_TYPE_EDGE_FALLING>;
};
};
@@ -449,8 +444,7 @@
wlcore: wlcore@2 {
compatible = "ti,wl1837";
reg = <2>;
- interrupt-parent = <&gpio1>;
- interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+ interrupts-extended = <&gpio1 25 IRQ_TYPE_EDGE_FALLING>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi
index a2f66f916048..cb11abba7bef 100644
--- a/arch/arm64/boot/dts/renesas/ulcb.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi
@@ -150,8 +150,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio2>;
- interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio2 11 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
};
};
@@ -234,6 +233,8 @@
#clock-cells = <1>;
clocks = <&x23_clk>;
clock-names = "xin";
+ idt,shutdown = <0>;
+ idt,output-enable-active = <1>;
};
};
@@ -248,8 +249,7 @@
compatible = "rohm,bd9571mwv";
reg = <0x30>;
- interrupt-parent = <&intc_ex>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&intc_ex 0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi b/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi
index 3845b413bd24..f24814d7c924 100644
--- a/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi
@@ -167,8 +167,7 @@
"ethernet-phy-ieee802.3-c22";
rxc-skew-ps = <1500>;
reg = <0>;
- interrupt-parent = <&gpio7>;
- interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio7 5 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio7 10 GPIO_ACTIVE_LOW>;
};
};
@@ -216,8 +215,7 @@
io_expander_a: gpio@20 {
compatible = "onnn,pca9654";
reg = <0x20>;
- interrupt-parent = <&gpio0>;
- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio0 0 IRQ_TYPE_LEVEL_LOW>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -240,14 +238,16 @@
clock-frequency = <400000>;
bridge@2c {
+ pinctrl-0 = <&irq0_pins>;
+ pinctrl-names = "default";
+
compatible = "ti,sn65dsi86";
reg = <0x2c>;
clocks = <&sn65dsi86_refclk>;
clock-names = "refclk";
- interrupt-parent = <&intc_ex>;
- interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&intc_ex 0 IRQ_TYPE_LEVEL_HIGH>;
enable-gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
@@ -302,7 +302,7 @@
};
&pciec0 {
- reset-gpio = <&io_expander_a 0 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&io_expander_a 0 GPIO_ACTIVE_LOW>;
status = "okay";
};
@@ -344,6 +344,11 @@
function = "i2c1";
};
+ irq0_pins: irq0 {
+ groups = "intc_ex_irq0_a";
+ function = "intc_ex";
+ };
+
keys_pins: keys {
pins = "GP_5_0", "GP_5_1", "GP_5_2";
bias-pull-up;
diff --git a/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi b/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi
index 595ec4ff4cdd..ad94bf3f5e6c 100644
--- a/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi
+++ b/arch/arm64/boot/dts/renesas/white-hawk-ethernet.dtsi
@@ -29,8 +29,7 @@
avb1_phy: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <0>;
- interrupt-parent = <&gpio6>;
- interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio6 3 IRQ_TYPE_LEVEL_LOW>;
};
};
};
@@ -51,8 +50,7 @@
avb2_phy: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <0>;
- interrupt-parent = <&gpio5>;
- interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&gpio5 4 IRQ_TYPE_LEVEL_LOW>;
};
};
};
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index 09423070c992..86cc418a2255 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -5,6 +5,7 @@ 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-firefly-jd4-core-mb.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-ringneck-haikou.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-bpi-p2-pro.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
@@ -76,6 +77,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64.dtb
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) += rk3528-radxa-e20c.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg-arc-d.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg-arc-s.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353p.dtb
@@ -91,6 +93,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinetab2-v0.1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinetab2-v2.0.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-powkiddy-rgb10max3.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-powkiddy-rgb20sx.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-powkiddy-rgb30.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-powkiddy-rk2023.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-powkiddy-x55.dtb
@@ -107,6 +110,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-model-a.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-box-demo.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-lckfb-tspi.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-lubancat-1.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-nanopi-r3s.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-fastrhino-r66s.dtb
@@ -124,7 +128,9 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3b.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5-display-vz.dtbo
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5-io-expander.dtbo
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-armsom-sige5.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-armsom-sige7.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-armsom-w3.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-coolpi-cm5-evb.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-coolpi-cm5-genbook.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-io.dtb
@@ -146,11 +152,14 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-tiger-haikou.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-toybrick-x0.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-turing-rk1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-coolpi-4b.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-evb1-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-gameforce-ace.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-indiedroid-nova.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-khadas-edge2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6s.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6c.dtb
-dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-rock-5a.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-odroid-m2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5b.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-rock-5a.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-rock-5c.dtb
diff --git a/arch/arm64/boot/dts/rockchip/px30-engicam-common.dtsi b/arch/arm64/boot/dts/rockchip/px30-engicam-common.dtsi
index 5b4e22385165..1edfd643b25a 100644
--- a/arch/arm64/boot/dts/rockchip/px30-engicam-common.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-engicam-common.dtsi
@@ -12,7 +12,7 @@
mmc2 = &sdio;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys"; /* +5V */
regulator-always-on;
@@ -42,7 +42,7 @@
states = <3300000 0x0>;
};
- vcc3v3_rf_aux_mod: vcc3v3-rf-aux-mod {
+ vcc3v3_rf_aux_mod: regulator-vcc3v3-rf-aux-mod {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_rf_aux_mod";
regulator-min-microvolt = <3300000>;
diff --git a/arch/arm64/boot/dts/rockchip/px30-engicam-px30-core.dtsi b/arch/arm64/boot/dts/rockchip/px30-engicam-px30-core.dtsi
index 5eecbefa8a33..dd715d22d4d2 100644
--- a/arch/arm64/boot/dts/rockchip/px30-engicam-px30-core.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-engicam-px30-core.dtsi
@@ -50,7 +50,7 @@
interrupts = <RK_PA7 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <1>;
clock-output-names = "rk808-clkout1", "rk808-clkout2";
diff --git a/arch/arm64/boot/dts/rockchip/px30-evb.dts b/arch/arm64/boot/dts/rockchip/px30-evb.dts
index 0a90a88fc664..d93aaac7a42f 100644
--- a/arch/arm64/boot/dts/rockchip/px30-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/px30-evb.dts
@@ -89,7 +89,7 @@
reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */
};
- vcc5v0_sys: vccsys {
+ vcc5v0_sys: regulator-vccsys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -189,7 +189,7 @@
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <0>;
clock-output-names = "xin32k";
diff --git a/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts
index d03e6aef54dc..5e3c10d825a0 100644
--- a/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts
+++ b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts
@@ -24,7 +24,7 @@
stdout-path = "serial2:115200n8";
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -85,7 +85,7 @@
reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */
};
- vcc5v0_baseboard: vcc5v0-baseboard-regulator {
+ vcc5v0_baseboard: regulator-vcc5v0-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_baseboard";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi
index f18d7eb9a9c7..1ad0e52a64ab 100644
--- a/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi
@@ -17,7 +17,7 @@
reset-gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_HIGH>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -70,7 +70,7 @@
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <0>;
clock-output-names = "xin32k";
diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts b/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
index ae398acdcf45..e4517f47d519 100644
--- a/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
+++ b/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
@@ -90,7 +90,7 @@
clock-frequency = <24576000>;
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -99,7 +99,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_baseboard: vcc3v3-baseboard-regulator {
+ vcc3v3_baseboard: regulator-vcc3v3-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_baseboard";
regulator-always-on;
@@ -109,7 +109,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_baseboard: vcc5v0-baseboard-regulator {
+ vcc5v0_baseboard: regulator-vcc5v0-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_baseboard";
regulator-always-on;
@@ -119,7 +119,7 @@
vin-supply = <&dc_12v>;
};
- vdda_codec: vdda-codec-regulator {
+ vdda_codec: regulator-vdda-codec {
compatible = "regulator-fixed";
regulator-name = "vdda_codec";
regulator-boot-on;
@@ -128,7 +128,7 @@
vin-supply = <&vcc5v0_baseboard>;
};
- vddd_codec: vddd-codec-regulator {
+ vddd_codec: regulator-vddd-codec {
compatible = "regulator-fixed";
regulator-name = "vddd_codec";
regulator-boot-on;
diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
index bb1aea82e666..ae050cc6cd05 100644
--- a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
@@ -9,12 +9,19 @@
/ {
aliases {
+ i2c10 = &i2c10;
mmc0 = &emmc;
mmc1 = &sdio;
rtc0 = &rtc_twi;
rtc1 = &rk809;
};
+ /* allows userspace to control the gate of the ATtiny UPDI pass FET via sysfs */
+ attiny-updi-gate-regulator {
+ compatible = "regulator-output";
+ vout-supply = <&vg_attiny_updi>;
+ };
+
emmc_pwrseq: emmc-pwrseq {
compatible = "mmc-pwrseq-emmc";
pinctrl-0 = <&emmc_reset>;
@@ -36,7 +43,7 @@
};
};
- vcc5v0_sys: vccsys-regulator {
+ vcc5v0_sys: regulator-vccsys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -66,7 +73,6 @@
bus-width = <8>;
cap-mmc-highspeed;
mmc-hs200-1_8v;
- supports-emmc;
mmc-pwrseq = <&emmc_pwrseq>;
non-removable;
vmmc-supply = <&vcc_3v3>;
@@ -127,7 +133,7 @@
pinctrl-names = "default";
#clock-cells = <0>;
clock-output-names = "xin32k";
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc5v0_sys>;
@@ -281,6 +287,11 @@
regulator-suspend-microvolt = <1800000>;
};
};
+
+ /* supplies the gate of the ATtiny UPDI pass FET */
+ vg_attiny_updi: SWITCH_REG1 {
+ regulator-name = "vg_attiny_updi";
+ };
};
};
};
@@ -292,14 +303,25 @@
clock-frequency = <400000>;
fan: fan@18 {
- compatible = "ti,amc6821";
+ compatible = "tsd,mule", "ti,amc6821";
reg = <0x18>;
- #cooling-cells = <2>;
- };
- rtc_twi: rtc@6f {
- compatible = "isil,isl1208";
- reg = <0x6f>;
+ i2c-mux {
+ compatible = "tsd,mule-i2c-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c10: i2c@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc_twi: rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3308-bpi-p2-pro.dts b/arch/arm64/boot/dts/rockchip/rk3308-bpi-p2-pro.dts
new file mode 100644
index 000000000000..2f7b09b7f43f
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3308-bpi-p2-pro.dts
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include "rk3308.dtsi"
+
+/ {
+ model = "Banana Pi P2 Pro (RK3308) Board";
+ compatible = "sinovoip,rk3308-bpi-p2pro", "rockchip,rk3308";
+
+ aliases {
+ ethernet0 = &gmac;
+ mmc0 = &emmc;
+ mmc1 = &sdmmc;
+ mmc2 = &sdio;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-recovery {
+ label = "Recovery";
+ linux,code = <KEY_VENDOR>;
+ press-threshold-microvolt = <10000>;
+ };
+ };
+
+ analog-sound {
+ compatible = "audio-graph-card";
+ label = "rockchip,rk3308";
+
+ dais = <&i2s_8ch_2_p0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&phone_ctl>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_en0>, <&led_en1>;
+
+ blue-led {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "on";
+ function = LED_FUNCTION_POWER;
+ gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
+ label = "blue:power";
+ linux,default-trigger = "default-on";
+ };
+
+ green-led {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
+ label = "green:heartbeat";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ vdd_log: regulator-1v04-vdd-log {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_log";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1040000>;
+ regulator-max-microvolt = <1040000>;
+ vin-supply = <&vcc_in>;
+ };
+
+ vcc_ddr: regulator-1v5-vcc-ddr {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ vin-supply = <&vcc_in>;
+ };
+
+ vcc_1v8: regulator-1v8-vcc {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_io>;
+ };
+
+ vcc_io: regulator-3v3-vcc-io {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_io";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_in>;
+ };
+
+ vcc_in: regulator-5v0-vcc-in {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_in";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vdd_core: regulator-vdd-core {
+ compatible = "pwm-regulator";
+ pwms = <&pwm0 0 5000 1>;
+ pwm-supply = <&vcc_in>;
+ regulator-name = "vdd_core";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <827000>;
+ regulator-max-microvolt = <1340000>;
+ regulator-settling-time-up-us = <250>;
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-0 = <&wifi_reg_on>;
+ pinctrl-names = "default";
+ reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&codec {
+ status = "okay";
+
+ port {
+ codec_p0_0: endpoint {
+ remote-endpoint = <&i2s_8ch_2_p0_0>;
+ };
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_core>;
+};
+
+&emmc {
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ no-sd;
+ no-sdio;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_pwren>;
+ status = "okay";
+};
+
+&gmac {
+ assigned-clocks = <&cru SCLK_MAC>;
+ assigned-clock-parents = <&mac_clkin>;
+ clock_in_out = "input";
+ phy-handle = <&rtl8201f>;
+ phy-supply = <&vcc_io>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ rtl8201f: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac_rst>;
+ reset-assert-us = <50000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&i2s_8ch_2 {
+ #sound-dai-cells = <0>;
+ status = "okay";
+
+ i2s_8ch_2_p0: port {
+ i2s_8ch_2_p0_0: endpoint {
+ dai-format = "i2s";
+ mclk-fs = <256>;
+ remote-endpoint = <&codec_p0_0>;
+ };
+ };
+};
+
+&io_domains {
+ vccio0-supply = <&vcc_io>;
+ vccio1-supply = <&vcc_io>;
+ vccio2-supply = <&vcc_io>;
+ vccio3-supply = <&vcc_io>;
+ vccio4-supply = <&vcc_1v8>;
+ vccio5-supply = <&vcc_io>;
+ status = "okay";
+};
+
+&pinctrl {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_32k>;
+
+ bt {
+ bt_reg_on: bt-reg-on {
+ rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_host: bt-wake-host {
+ rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ host_wake_bt: host-wake-bt {
+ rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ gmac {
+ mac_rst: mac-rst {
+ rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ led_en0: led-en0 {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ led_en1: led-en1 {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sound {
+ phone_ctl: phone-ctl {
+ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_reg_on: wifi-reg-on {
+ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wifi_wake_host: wifi-wake-host {
+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+};
+
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_pin_pull_down>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+/* WIFI part of the AP6256 connected with SDIO */
+&sdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ disable-wp;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ no-mmc;
+ no-sd;
+ non-removable;
+ sd-uhs-sdr104;
+ status = "okay";
+
+ ap6256: wifi@1 {
+ compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wake";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_wake_host>;
+ };
+};
+
+&sdmmc {
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ disable-wp;
+ vmmc-supply = <&vcc_io>;
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+};
+
+&u2phy_host {
+ status = "okay";
+};
+
+&u2phy_otg {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+/* BT part of the AP6256 connected with UART */
+&uart4 {
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4345c5";
+ clocks = <&cru SCLK_RTC32K>;
+ clock-names = "lpo";
+ interrupt-parent = <&gpio4>;
+ interrupts = <RK_PB4 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wakeup";
+ device-wakeup-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>;
+ max-speed = <1500000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_reg_on &bt_wake_host &host_wake_bt>;
+ vbat-supply = <&vcc_io>;
+ vddio-supply = <&vcc_1v8>;
+ };
+};
+
+&usb20_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usb_host_ehci {
+ status = "okay";
+};
+
+&usb_host_ohci {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3308-evb.dts b/arch/arm64/boot/dts/rockchip/rk3308-evb.dts
index 184b84fdde07..3f1aafe2dc13 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3308-evb.dts
@@ -84,7 +84,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-min-microvolt = <12000000>;
@@ -93,7 +93,7 @@
regulator-boot-on;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-min-microvolt = <5000000>;
@@ -103,7 +103,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vccio_sdio: vcc_1v8: vcc-1v8 {
+ vccio_sdio: vcc_1v8: regulator-vcc-1v8 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v8";
regulator-min-microvolt = <1800000>;
@@ -113,7 +113,7 @@
vin-supply = <&vcc_io>;
};
- vcc_ddr: vcc-ddr {
+ vcc_ddr: regulator-vcc-ddr {
compatible = "regulator-fixed";
regulator-name = "vcc_ddr";
regulator-min-microvolt = <1500000>;
@@ -123,7 +123,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_io: vcc-io {
+ vcc_io: regulator-vcc-io {
compatible = "regulator-fixed";
regulator-name = "vcc_io";
regulator-min-microvolt = <3300000>;
@@ -133,7 +133,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vccio_flash: vccio-flash {
+ vccio_flash: regulator-vccio-flash {
compatible = "regulator-fixed";
regulator-name = "vccio_flash";
regulator-min-microvolt = <3300000>;
@@ -143,7 +143,7 @@
vin-supply = <&vcc_io>;
};
- vcc5v0_host: vcc5v0-host {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
enable-active-high;
@@ -153,7 +153,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vdd_core: vdd-core {
+ vdd_core: regulator-vdd-core {
compatible = "pwm-regulator";
pwms = <&pwm0 0 5000 1>;
regulator-name = "vdd_core";
@@ -165,7 +165,7 @@
pwm-supply = <&vcc5v0_sys>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "regulator-fixed";
regulator-name = "vdd_log";
regulator-min-microvolt = <1050000>;
@@ -175,7 +175,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vdd_1v0: vdd-1v0 {
+ vdd_1v0: regulator-vdd-1v0 {
compatible = "regulator-fixed";
regulator-name = "vdd_1v0";
regulator-min-microvolt = <1000000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
index 9232357f4fec..629121de5a13 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts
@@ -36,20 +36,20 @@
power_led: led-0 {
label = "firefly:red:power";
- linux,default-trigger = "ir-power-click";
+ linux,default-trigger = "default-on";
default-state = "on";
gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
};
user_led: led-1 {
label = "firefly:blue:user";
- linux,default-trigger = "ir-user-click";
+ linux,default-trigger = "rc-feedback";
default-state = "off";
gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>;
};
};
- typec_vcc5v: typec-vcc5v {
+ typec_vcc5v: regulator-typec-vcc5v {
compatible = "regulator-fixed";
regulator-name = "typec_vcc5v";
regulator-min-microvolt = <5000000>;
@@ -58,7 +58,7 @@
regulator-boot-on;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-min-microvolt = <5000000>;
@@ -68,7 +68,7 @@
vin-supply = <&typec_vcc5v>;
};
- vcc_io: vcc-io {
+ vcc_io: regulator-vcc-io {
compatible = "regulator-fixed";
regulator-name = "vcc_io";
regulator-min-microvolt = <3300000>;
@@ -89,7 +89,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_sd: vcc-sd {
+ vcc_sd: regulator-vcc-sd {
compatible = "regulator-fixed";
gpio = <&gpio4 RK_PD6 GPIO_ACTIVE_LOW>;
regulator-name = "vcc_sd";
@@ -100,7 +100,7 @@
vin-supply = <&vcc_io>;
};
- vdd_core: vdd-core {
+ vdd_core: regulator-vdd-core {
compatible = "pwm-regulator";
pwms = <&pwm0 0 5000 1>;
regulator-name = "vdd_core";
@@ -112,7 +112,7 @@
pwm-supply = <&vcc5v0_sys>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "regulator-fixed";
regulator-name = "vdd_log";
regulator-min-microvolt = <1050000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts
index 62d18ca769a1..7a32972bc249 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts
@@ -55,7 +55,7 @@
reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
};
- vcc_1v8: vcc-1v8 {
+ vcc_1v8: regulator-vcc-1v8 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v8";
regulator-always-on;
@@ -65,7 +65,7 @@
vin-supply = <&vcc_io>;
};
- vcc_io: vcc-io {
+ vcc_io: regulator-vcc-io {
compatible = "regulator-fixed";
regulator-name = "vcc_io";
regulator-always-on;
@@ -75,7 +75,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_ddr: vcc-ddr {
+ vcc_ddr: regulator-vcc-ddr {
compatible = "regulator-fixed";
regulator-name = "vcc_ddr";
regulator-always-on;
@@ -85,7 +85,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_otg: vcc5v0-otg {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -96,7 +96,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -105,7 +105,7 @@
regulator-max-microvolt = <5000000>;
};
- vdd_core: vdd-core {
+ vdd_core: regulator-vdd-core {
compatible = "pwm-regulator";
pwms = <&pwm0 0 5000 1>;
pwm-supply = <&vcc5v0_sys>;
@@ -117,7 +117,7 @@
regulator-boot-on;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "regulator-fixed";
regulator-name = "vdd_log";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts b/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts
index c7b1862fca6a..a94114fb7cc1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3318-a95x-z2.dts
@@ -78,7 +78,7 @@
};
/* Power tree */
- vccio_1v8: vccio-1v8-regulator {
+ vccio_1v8: regulator-vccio-1v8 {
compatible = "regulator-fixed";
regulator-name = "vccio_1v8";
regulator-min-microvolt = <1800000>;
@@ -86,7 +86,7 @@
regulator-always-on;
};
- vccio_3v3: vccio-3v3-regulator {
+ vccio_3v3: regulator-vccio-3v3 {
compatible = "regulator-fixed";
regulator-name = "vccio_3v3";
regulator-min-microvolt = <3300000>;
@@ -94,7 +94,7 @@
regulator-always-on;
};
- vcc_otg_vbus: otg-vbus-regulator {
+ vcc_otg_vbus: regulator-otg-vbus {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&otg_vbus_drv>;
@@ -105,7 +105,7 @@
enable-active-high;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
pinctrl-0 = <&sdmmc0m1_pin>;
@@ -116,7 +116,7 @@
vin-supply = <&vccio_3v3>;
};
- vdd_arm: vdd-arm {
+ vdd_arm: regulator-vdd-arm {
compatible = "pwm-regulator";
pwms = <&pwm0 0 5000 1>;
regulator-name = "vdd_arm";
@@ -127,7 +127,7 @@
regulator-boot-on;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm1 0 5000 1>;
regulator-name = "vdd_log";
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dtsi
index b6d041dbed94..150fadcb0b3c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dtsi
@@ -49,7 +49,7 @@
compatible = "simple-audio-card";
simple-audio-card,name = "rk817_int";
simple-audio-card,format = "i2s";
- simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,hp-det-gpios = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
@@ -70,7 +70,7 @@
};
};
- vccsys: vccsys {
+ vccsys: regulator-vccsys {
compatible = "regulator-fixed";
regulator-name = "vcc3v8_sys";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-gameforce-chi.dts b/arch/arm64/boot/dts/rockchip/rk3326-gameforce-chi.dts
index 579261b3a474..10e6ab724ac4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3326-gameforce-chi.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3326-gameforce-chi.dts
@@ -245,7 +245,7 @@
simple-audio-card,name = "rk817_ext";
simple-audio-card,aux-devs = <&spk_amp>;
simple-audio-card,format = "i2s";
- simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,hp-det-gpios = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
@@ -292,7 +292,7 @@
reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
};
- vccsys: vccsys-regulator {
+ vccsys: regulator-vccsys {
compatible = "regulator-fixed";
regulator-name = "vcc3v8_sys";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi
index 80fc53c807a4..446a1a6c12e7 100644
--- a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi
@@ -144,7 +144,7 @@
compatible = "simple-audio-card";
simple-audio-card,name = "rk817_int";
simple-audio-card,format = "i2s";
- simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,hp-det-gpios = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
@@ -165,7 +165,7 @@
};
};
- vccsys: vccsys {
+ vccsys: regulator-vccsys {
compatible = "regulator-fixed";
regulator-name = "vcc3v8_sys";
regulator-always-on;
@@ -173,7 +173,7 @@
regulator-max-microvolt = <3800000>;
};
- vcc_host: vcc_host {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
regulator-name = "vcc_host";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
index 824183e515da..8dfeaf1f8eb0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
@@ -36,7 +36,7 @@
#clock-cells = <0>;
};
- vcc_host_5v: usb3-current-switch {
+ vcc_host_5v: regulator-usb3-current-switch {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
@@ -46,7 +46,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -159,7 +159,7 @@
interrupts = <RK_PA6 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <0>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts
index 1eef5504445f..3707df6acf1f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts
@@ -21,7 +21,7 @@
stdout-path = "serial2:1500000n8";
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -44,7 +44,7 @@
reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio0 30 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -55,7 +55,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -65,7 +65,7 @@
vin-supply = <&dc_12v>;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
regulator-name = "vcc_phy";
regulator-always-on;
@@ -121,7 +121,7 @@
#gpio-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2.dtsi
new file mode 100644
index 000000000000..1715d311e1f2
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2.dtsi
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 David Bauer <mail@david-bauer.net>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "rk3328.dtsi"
+
+/ {
+ aliases {
+ ethernet0 = &gmac2io;
+ ethernet1 = &rtl8153;
+ mmc0 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ gmac_clk: gmac-clock {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac_clkin";
+ #clock-cells = <0>;
+ };
+
+ keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&reset_button_pin>;
+ pinctrl-names = "default";
+
+ key-reset {
+ label = "reset";
+ gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ debounce-interval = <50>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>;
+ pinctrl-names = "default";
+
+ lan_led: led-0 {
+ gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
+ label = "nanopi-r2s:green:lan";
+ };
+
+ sys_led: led-1 {
+ gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
+ label = "nanopi-r2s:red:sys";
+ default-state = "on";
+ };
+
+ wan_led: led-2 {
+ gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>;
+ label = "nanopi-r2s:green:wan";
+ };
+ };
+
+ vcc_io_sdio: regulator-sdmmcio {
+ compatible = "regulator-gpio";
+ enable-active-high;
+ gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&sdio_vcc_pin>;
+ pinctrl-names = "default";
+ regulator-name = "vcc_io_sdio";
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-settling-time-us = <5000>;
+ regulator-type = "voltage";
+ startup-delay-us = <2000>;
+ states = <1800000 0x1>,
+ <3300000 0x0>;
+ vin-supply = <&vcc_io_33>;
+ };
+
+ vcc_sd: regulator-sdmmc {
+ compatible = "regulator-fixed";
+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&sdmmc0m1_pin>;
+ pinctrl-names = "default";
+ regulator-name = "vcc_sd";
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_io_33>;
+ };
+
+ vdd_5v: regulator-vdd-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_5v";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vdd_5v_lan: regulator-vdd-5v-lan {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&lan_vdd_pin>;
+ pinctrl-names = "default";
+ regulator-name = "vdd_5v_lan";
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vdd_5v>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&display_subsystem {
+ status = "disabled";
+};
+
+&gmac2io {
+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
+ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>;
+ clock_in_out = "input";
+ phy-mode = "rgmii";
+ phy-supply = <&vcc_io_33>;
+ pinctrl-0 = <&rgmiim1_pins>;
+ pinctrl-names = "default";
+ snps,aal;
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ rk805: pmic@18 {
+ compatible = "rockchip,rk805";
+ reg = <0x18>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "xin32k", "rk805-clkout2";
+ gpio-controller;
+ #gpio-cells = <2>;
+ pinctrl-0 = <&pmic_int_l>;
+ pinctrl-names = "default";
+ system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vdd_5v>;
+ vcc2-supply = <&vdd_5v>;
+ vcc3-supply = <&vdd_5v>;
+ vcc4-supply = <&vdd_5v>;
+ vcc5-supply = <&vcc_io_33>;
+ vcc6-supply = <&vdd_5v>;
+
+ regulators {
+ vdd_log: DCDC_REG1 {
+ regulator-name = "vdd_log";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1450000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1450000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-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_io_33: DCDC_REG4 {
+ regulator-name = "vcc_io_33";
+ 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>;
+ };
+ };
+
+ vcc_18: LDO_REG1 {
+ regulator-name = "vcc_18";
+ 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>;
+ };
+ };
+
+ vcc18_emmc: LDO_REG2 {
+ regulator-name = "vcc18_emmc";
+ 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>;
+ };
+ };
+
+ vdd_10: LDO_REG3 {
+ regulator-name = "vdd_10";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+ };
+ };
+};
+
+&io_domains {
+ pmuio-supply = <&vcc_io_33>;
+ vccio1-supply = <&vcc_io_33>;
+ vccio2-supply = <&vcc18_emmc>;
+ vccio3-supply = <&vcc_io_sdio>;
+ vccio4-supply = <&vcc_18>;
+ vccio5-supply = <&vcc_io_33>;
+ vccio6-supply = <&vcc_io_33>;
+ status = "okay";
+};
+
+&pinctrl {
+ button {
+ reset_button_pin: reset-button-pin {
+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ gmac2io {
+ eth_phy_reset_pin: eth-phy-reset-pin {
+ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ leds {
+ lan_led_pin: lan-led-pin {
+ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ sys_led_pin: sys-led-pin {
+ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wan_led_pin: wan-led-pin {
+ rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ lan {
+ lan_vdd_pin: lan-vdd-pin {
+ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ sd {
+ sdio_vcc_pin: sdio-vcc-pin {
+ rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>;
+ pinctrl-names = "default";
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_sd>;
+ vqmmc-supply = <&vcc_io_sdio>;
+ status = "okay";
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <0>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+};
+
+&u2phy_host {
+ status = "okay";
+};
+
+&u2phy_otg {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb20_otg {
+ status = "okay";
+ dr_mode = "host";
+};
+
+&usbdrd3 {
+ dr_mode = "host";
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Second port is for USB 3.0 */
+ rtl8153: device@2 {
+ compatible = "usbbda,8153";
+ reg = <2>;
+ };
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts
index 16a1958e4572..3709ba30bbd4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts
@@ -7,7 +7,8 @@
*/
/dts-v1/;
-#include "rk3328-nanopi-r2c.dts"
+
+#include "rk3328-nanopi-r2c.dtsi"
/ {
model = "FriendlyElec NanoPi R2C Plus";
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts
index a07a26b944a0..e8ab773dc245 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts
@@ -7,34 +7,10 @@
*/
/dts-v1/;
-#include "rk3328-nanopi-r2s.dts"
+
+#include "rk3328-nanopi-r2c.dtsi"
/ {
model = "FriendlyElec NanoPi R2C";
compatible = "friendlyarm,nanopi-r2c", "rockchip,rk3328";
};
-
-&gmac2io {
- phy-handle = <&yt8521s>;
- tx_delay = <0x22>;
- rx_delay = <0x12>;
-
- mdio {
- /delete-node/ ethernet-phy@1;
-
- yt8521s: ethernet-phy@3 {
- compatible = "ethernet-phy-ieee802.3-c22";
- reg = <3>;
-
- motorcomm,clk-out-frequency-hz = <125000000>;
- motorcomm,keep-pll-enabled;
- motorcomm,auto-sleep-disabled;
-
- pinctrl-0 = <&eth_phy_reset_pin>;
- pinctrl-names = "default";
- reset-assert-us = <10000>;
- reset-deassert-us = <50000>;
- reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
- };
- };
-};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dtsi
new file mode 100644
index 000000000000..3b0457de2a98
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dtsi
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) 2021 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * Copyright (c) 2021-2023 Tianling Shen <cnsztl@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "rk3328-nanopi-r2.dtsi"
+
+&gmac2io {
+ phy-handle = <&yt8521s>;
+ tx_delay = <0x22>;
+ rx_delay = <0x12>;
+ status = "okay";
+
+ mdio {
+ yt8521s: ethernet-phy@3 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <3>;
+
+ motorcomm,clk-out-frequency-hz = <125000000>;
+ motorcomm,keep-pll-enabled;
+ motorcomm,auto-sleep-disabled;
+
+ pinctrl-0 = <&eth_phy_reset_pin>;
+ pinctrl-names = "default";
+ reset-assert-us = <10000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts
index cb81ba3f23ff..f72b1518c14f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts
@@ -7,7 +7,8 @@
*/
/dts-v1/;
-#include "rk3328-nanopi-r2s.dts"
+
+#include "rk3328-nanopi-r2s.dtsi"
/ {
compatible = "friendlyarm,nanopi-r2s-plus", "rockchip,rk3328";
@@ -24,9 +25,24 @@
disable-wp;
mmc-hs200-1_8v;
non-removable;
- num-slots = <1>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
- supports-emmc;
status = "okay";
};
+
+&gmac2io {
+ phy-handle = <&rtl8211e>;
+ tx_delay = <0x24>;
+ rx_delay = <0x18>;
+
+ mdio {
+ rtl8211e: ethernet-phy@1 {
+ reg = <1>;
+ pinctrl-0 = <&eth_phy_reset_pin>;
+ pinctrl-names = "default";
+ reset-assert-us = <10000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts
index a4399da7d8b1..8579f22a1942 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts
@@ -5,406 +5,9 @@
/dts-v1/;
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/gpio/gpio.h>
-#include "rk3328.dtsi"
+#include "rk3328-nanopi-r2s.dtsi"
/ {
model = "FriendlyElec NanoPi R2S";
compatible = "friendlyarm,nanopi-r2s", "rockchip,rk3328";
-
- aliases {
- ethernet0 = &gmac2io;
- ethernet1 = &rtl8153;
- mmc0 = &sdmmc;
- };
-
- chosen {
- stdout-path = "serial2:1500000n8";
- };
-
- gmac_clk: gmac-clock {
- compatible = "fixed-clock";
- clock-frequency = <125000000>;
- clock-output-names = "gmac_clkin";
- #clock-cells = <0>;
- };
-
- keys {
- compatible = "gpio-keys";
- pinctrl-0 = <&reset_button_pin>;
- pinctrl-names = "default";
-
- key-reset {
- label = "reset";
- gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
- linux,code = <KEY_RESTART>;
- debounce-interval = <50>;
- };
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>;
- pinctrl-names = "default";
-
- lan_led: led-0 {
- gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
- label = "nanopi-r2s:green:lan";
- };
-
- sys_led: led-1 {
- gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
- label = "nanopi-r2s:red:sys";
- default-state = "on";
- };
-
- wan_led: led-2 {
- gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>;
- label = "nanopi-r2s:green:wan";
- };
- };
-
- vcc_io_sdio: sdmmcio-regulator {
- compatible = "regulator-gpio";
- enable-active-high;
- gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
- pinctrl-0 = <&sdio_vcc_pin>;
- pinctrl-names = "default";
- regulator-name = "vcc_io_sdio";
- regulator-always-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-settling-time-us = <5000>;
- regulator-type = "voltage";
- startup-delay-us = <2000>;
- states = <1800000 0x1>,
- <3300000 0x0>;
- vin-supply = <&vcc_io_33>;
- };
-
- vcc_sd: sdmmc-regulator {
- compatible = "regulator-fixed";
- gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
- pinctrl-0 = <&sdmmc0m1_pin>;
- pinctrl-names = "default";
- regulator-name = "vcc_sd";
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- vin-supply = <&vcc_io_33>;
- };
-
- vdd_5v: vdd-5v {
- compatible = "regulator-fixed";
- regulator-name = "vdd_5v";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- };
-
- vdd_5v_lan: vdd-5v-lan {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
- pinctrl-0 = <&lan_vdd_pin>;
- pinctrl-names = "default";
- regulator-name = "vdd_5v_lan";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vdd_5v>;
- };
-};
-
-&cpu0 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu1 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu2 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu3 {
- cpu-supply = <&vdd_arm>;
-};
-
-&display_subsystem {
- status = "disabled";
-};
-
-&gmac2io {
- assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
- assigned-clock-parents = <&gmac_clk>, <&gmac_clk>;
- clock_in_out = "input";
- phy-handle = <&rtl8211e>;
- phy-mode = "rgmii";
- phy-supply = <&vcc_io_33>;
- pinctrl-0 = <&rgmiim1_pins>;
- pinctrl-names = "default";
- rx_delay = <0x18>;
- snps,aal;
- tx_delay = <0x24>;
- status = "okay";
-
- mdio {
- compatible = "snps,dwmac-mdio";
- #address-cells = <1>;
- #size-cells = <0>;
-
- rtl8211e: ethernet-phy@1 {
- reg = <1>;
- pinctrl-0 = <&eth_phy_reset_pin>;
- pinctrl-names = "default";
- reset-assert-us = <10000>;
- reset-deassert-us = <50000>;
- reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
- };
- };
-};
-
-&i2c1 {
- status = "okay";
-
- rk805: pmic@18 {
- compatible = "rockchip,rk805";
- reg = <0x18>;
- interrupt-parent = <&gpio1>;
- interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
- #clock-cells = <1>;
- clock-output-names = "xin32k", "rk805-clkout2";
- gpio-controller;
- #gpio-cells = <2>;
- pinctrl-0 = <&pmic_int_l>;
- pinctrl-names = "default";
- rockchip,system-power-controller;
- wakeup-source;
-
- vcc1-supply = <&vdd_5v>;
- vcc2-supply = <&vdd_5v>;
- vcc3-supply = <&vdd_5v>;
- vcc4-supply = <&vdd_5v>;
- vcc5-supply = <&vcc_io_33>;
- vcc6-supply = <&vdd_5v>;
-
- regulators {
- vdd_log: DCDC_REG1 {
- regulator-name = "vdd_log";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <712500>;
- regulator-max-microvolt = <1450000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
-
- vdd_arm: DCDC_REG2 {
- regulator-name = "vdd_arm";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <712500>;
- regulator-max-microvolt = <1450000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-on-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_io_33: DCDC_REG4 {
- regulator-name = "vcc_io_33";
- 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>;
- };
- };
-
- vcc_18: LDO_REG1 {
- regulator-name = "vcc_18";
- 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>;
- };
- };
-
- vcc18_emmc: LDO_REG2 {
- regulator-name = "vcc18_emmc";
- 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>;
- };
- };
-
- vdd_10: LDO_REG3 {
- regulator-name = "vdd_10";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
- };
- };
-};
-
-&io_domains {
- pmuio-supply = <&vcc_io_33>;
- vccio1-supply = <&vcc_io_33>;
- vccio2-supply = <&vcc18_emmc>;
- vccio3-supply = <&vcc_io_sdio>;
- vccio4-supply = <&vcc_18>;
- vccio5-supply = <&vcc_io_33>;
- vccio6-supply = <&vcc_io_33>;
- status = "okay";
-};
-
-&pinctrl {
- button {
- reset_button_pin: reset-button-pin {
- rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- gmac2io {
- eth_phy_reset_pin: eth-phy-reset-pin {
- rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
- };
- };
-
- leds {
- lan_led_pin: lan-led-pin {
- rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- sys_led_pin: sys-led-pin {
- rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- wan_led_pin: wan-led-pin {
- rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- lan {
- lan_vdd_pin: lan-vdd-pin {
- rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- pmic {
- pmic_int_l: pmic-int-l {
- rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-
- sd {
- sdio_vcc_pin: sdio-vcc-pin {
- rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-};
-
-&pwm2 {
- status = "okay";
-};
-
-&sdmmc {
- bus-width = <4>;
- cap-sd-highspeed;
- disable-wp;
- pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>;
- pinctrl-names = "default";
- sd-uhs-sdr12;
- sd-uhs-sdr25;
- sd-uhs-sdr50;
- sd-uhs-sdr104;
- vmmc-supply = <&vcc_sd>;
- vqmmc-supply = <&vcc_io_sdio>;
- status = "okay";
-};
-
-&tsadc {
- rockchip,hw-tshut-mode = <0>;
- rockchip,hw-tshut-polarity = <0>;
- status = "okay";
-};
-
-&u2phy {
- status = "okay";
-};
-
-&u2phy_host {
- status = "okay";
-};
-
-&u2phy_otg {
- status = "okay";
-};
-
-&uart2 {
- status = "okay";
-};
-
-&usb20_otg {
- status = "okay";
- dr_mode = "host";
-};
-
-&usbdrd3 {
- dr_mode = "host";
- status = "okay";
- #address-cells = <1>;
- #size-cells = <0>;
-
- /* Second port is for USB 3.0 */
- rtl8153: device@2 {
- compatible = "usbbda,8153";
- reg = <2>;
- };
-};
-
-&usb_host0_ehci {
- status = "okay";
-};
-
-&usb_host0_ohci {
- status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dtsi
new file mode 100644
index 000000000000..308e526c2861
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dtsi
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * (C) Copyright 2018 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ */
+
+/dts-v1/;
+
+#include "rk3328-nanopi-r2.dtsi"
+
+&gmac2io {
+ phy-handle = <&rtl8211e>;
+ tx_delay = <0x24>;
+ rx_delay = <0x18>;
+ status = "okay";
+
+ mdio {
+ rtl8211e: ethernet-phy@1 {
+ reg = <1>;
+ pinctrl-0 = <&eth_phy_reset_pin>;
+ pinctrl-names = "default";
+ reset-assert-us = <10000>;
+ reset-deassert-us = <50000>;
+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts
index 4237f2ee8fee..67c246ad8b8c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts
@@ -7,7 +7,8 @@
*/
/dts-v1/;
-#include "rk3328-orangepi-r1-plus.dts"
+
+#include "rk3328-orangepi-r1-plus.dtsi"
/ {
model = "Xunlong Orange Pi R1 Plus LTS";
@@ -18,10 +19,9 @@
phy-handle = <&yt8531c>;
tx_delay = <0x19>;
rx_delay = <0x05>;
+ status = "okay";
mdio {
- /delete-node/ ethernet-phy@1;
-
yt8531c: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts
index f20662929c77..324a8e951f7e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts
@@ -6,127 +6,20 @@
/dts-v1/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/leds/common.h>
-#include "rk3328.dtsi"
+#include "rk3328-orangepi-r1-plus.dtsi"
/ {
model = "Xunlong Orange Pi R1 Plus";
compatible = "xunlong,orangepi-r1-plus", "rockchip,rk3328";
-
- aliases {
- ethernet0 = &gmac2io;
- ethernet1 = &rtl8153;
- mmc0 = &sdmmc;
- };
-
- chosen {
- stdout-path = "serial2:1500000n8";
- };
-
- gmac_clk: gmac-clock {
- compatible = "fixed-clock";
- clock-frequency = <125000000>;
- clock-output-names = "gmac_clkin";
- #clock-cells = <0>;
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>;
- pinctrl-names = "default";
-
- led-0 {
- function = LED_FUNCTION_LAN;
- color = <LED_COLOR_ID_GREEN>;
- gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
- };
-
- led-1 {
- function = LED_FUNCTION_STATUS;
- color = <LED_COLOR_ID_RED>;
- gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "heartbeat";
- };
-
- led-2 {
- function = LED_FUNCTION_WAN;
- color = <LED_COLOR_ID_GREEN>;
- gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>;
- };
- };
-
- vcc_sd: sdmmc-regulator {
- compatible = "regulator-fixed";
- gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
- pinctrl-0 = <&sdmmc0m1_pin>;
- pinctrl-names = "default";
- regulator-name = "vcc_sd";
- regulator-boot-on;
- vin-supply = <&vcc_io>;
- };
-
- vcc_sys: vcc-sys-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vcc_sys";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- };
-
- vdd_5v_lan: vdd-5v-lan-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
- pinctrl-0 = <&lan_vdd_pin>;
- pinctrl-names = "default";
- regulator-name = "vdd_5v_lan";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vcc_sys>;
- };
-};
-
-&cpu0 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu1 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu2 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu3 {
- cpu-supply = <&vdd_arm>;
-};
-
-&display_subsystem {
- status = "disabled";
};
&gmac2io {
- assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
- assigned-clock-parents = <&gmac_clk>, <&gmac_clk>;
- clock_in_out = "input";
phy-handle = <&rtl8211e>;
- phy-mode = "rgmii";
- phy-supply = <&vcc_io>;
- pinctrl-0 = <&rgmiim1_pins>;
- pinctrl-names = "default";
- snps,aal;
- rx_delay = <0x18>;
tx_delay = <0x24>;
+ rx_delay = <0x18>;
status = "okay";
mdio {
- compatible = "snps,dwmac-mdio";
- #address-cells = <1>;
- #size-cells = <0>;
-
rtl8211e: ethernet-phy@1 {
reg = <1>;
pinctrl-0 = <&eth_phy_reset_pin>;
@@ -137,238 +30,3 @@
};
};
};
-
-&i2c1 {
- status = "okay";
-
- rk805: pmic@18 {
- compatible = "rockchip,rk805";
- reg = <0x18>;
- interrupt-parent = <&gpio1>;
- interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
- #clock-cells = <1>;
- clock-output-names = "xin32k", "rk805-clkout2";
- gpio-controller;
- #gpio-cells = <2>;
- pinctrl-0 = <&pmic_int_l>;
- pinctrl-names = "default";
- rockchip,system-power-controller;
- wakeup-source;
-
- vcc1-supply = <&vcc_sys>;
- vcc2-supply = <&vcc_sys>;
- vcc3-supply = <&vcc_sys>;
- vcc4-supply = <&vcc_sys>;
- vcc5-supply = <&vcc_io>;
- vcc6-supply = <&vcc_sys>;
-
- regulators {
- vdd_log: DCDC_REG1 {
- regulator-name = "vdd_log";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <712500>;
- regulator-max-microvolt = <1450000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
-
- vdd_arm: DCDC_REG2 {
- regulator-name = "vdd_arm";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <712500>;
- regulator-max-microvolt = <1450000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-on-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_io: DCDC_REG4 {
- regulator-name = "vcc_io";
- 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>;
- };
- };
-
- vcc_18: LDO_REG1 {
- regulator-name = "vcc_18";
- 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>;
- };
- };
-
- vcc18_emmc: LDO_REG2 {
- regulator-name = "vcc18_emmc";
- 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>;
- };
- };
-
- vdd_10: LDO_REG3 {
- regulator-name = "vdd_10";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
- };
- };
-};
-
-&io_domains {
- pmuio-supply = <&vcc_io>;
- vccio1-supply = <&vcc_io>;
- vccio2-supply = <&vcc18_emmc>;
- vccio3-supply = <&vcc_io>;
- vccio4-supply = <&vcc_io>;
- vccio5-supply = <&vcc_io>;
- vccio6-supply = <&vcc_io>;
- status = "okay";
-};
-
-&pinctrl {
- gmac2io {
- eth_phy_reset_pin: eth-phy-reset-pin {
- rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
- };
- };
-
- leds {
- lan_led_pin: lan-led-pin {
- rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- sys_led_pin: sys-led-pin {
- rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- wan_led_pin: wan-led-pin {
- rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- lan {
- lan_vdd_pin: lan-vdd-pin {
- rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- pmic {
- pmic_int_l: pmic-int-l {
- rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-};
-
-&pwm2 {
- status = "okay";
-};
-
-&sdmmc {
- bus-width = <4>;
- cap-sd-highspeed;
- disable-wp;
- pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>;
- pinctrl-names = "default";
- vmmc-supply = <&vcc_sd>;
- status = "okay";
-};
-
-&spi0 {
- status = "okay";
-
- flash@0 {
- compatible = "jedec,spi-nor";
- reg = <0>;
- spi-max-frequency = <50000000>;
- };
-};
-
-&tsadc {
- rockchip,hw-tshut-mode = <0>;
- rockchip,hw-tshut-polarity = <0>;
- status = "okay";
-};
-
-&u2phy {
- status = "okay";
-};
-
-&u2phy_host {
- status = "okay";
-};
-
-&u2phy_otg {
- status = "okay";
-};
-
-&uart2 {
- status = "okay";
-};
-
-&usb20_otg {
- dr_mode = "host";
- status = "okay";
-};
-
-&usbdrd3 {
- dr_mode = "host";
- status = "okay";
- #address-cells = <1>;
- #size-cells = <0>;
-
- /* Second port is for USB 3.0 */
- rtl8153: device@2 {
- compatible = "usbbda,8153";
- reg = <2>;
- };
-};
-
-&usb_host0_ehci {
- status = "okay";
-};
-
-&usb_host0_ohci {
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dtsi
new file mode 100644
index 000000000000..82021ffb0a49
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dtsi
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Based on rk3328-nanopi-r2s.dts, which is:
+ * Copyright (c) 2020 David Bauer <mail@david-bauer.net>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "rk3328.dtsi"
+
+/ {
+ aliases {
+ ethernet0 = &gmac2io;
+ ethernet1 = &rtl8153;
+ mmc0 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ gmac_clk: gmac-clock {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac_clkin";
+ #clock-cells = <0>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>;
+ pinctrl-names = "default";
+
+ led-0 {
+ function = LED_FUNCTION_LAN;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-2 {
+ function = LED_FUNCTION_WAN;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ vcc_sd: regulator-sdmmc {
+ compatible = "regulator-fixed";
+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&sdmmc0m1_pin>;
+ pinctrl-names = "default";
+ regulator-name = "vcc_sd";
+ regulator-boot-on;
+ vin-supply = <&vcc_io>;
+ };
+
+ vcc_sys: regulator-vcc-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vdd_5v_lan: regulator-vdd-5v-lan {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&lan_vdd_pin>;
+ pinctrl-names = "default";
+ regulator-name = "vdd_5v_lan";
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc_sys>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&display_subsystem {
+ status = "disabled";
+};
+
+&gmac2io {
+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
+ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>;
+ clock_in_out = "input";
+ phy-mode = "rgmii";
+ phy-supply = <&vcc_io>;
+ pinctrl-0 = <&rgmiim1_pins>;
+ pinctrl-names = "default";
+ snps,aal;
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ rk805: pmic@18 {
+ compatible = "rockchip,rk805";
+ reg = <0x18>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "xin32k", "rk805-clkout2";
+ gpio-controller;
+ #gpio-cells = <2>;
+ pinctrl-0 = <&pmic_int_l>;
+ pinctrl-names = "default";
+ system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc_sys>;
+ vcc2-supply = <&vcc_sys>;
+ vcc3-supply = <&vcc_sys>;
+ vcc4-supply = <&vcc_sys>;
+ vcc5-supply = <&vcc_io>;
+ vcc6-supply = <&vcc_sys>;
+
+ regulators {
+ vdd_log: DCDC_REG1 {
+ regulator-name = "vdd_log";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1450000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1450000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-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_io: DCDC_REG4 {
+ regulator-name = "vcc_io";
+ 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>;
+ };
+ };
+
+ vcc_18: LDO_REG1 {
+ regulator-name = "vcc_18";
+ 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>;
+ };
+ };
+
+ vcc18_emmc: LDO_REG2 {
+ regulator-name = "vcc18_emmc";
+ 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>;
+ };
+ };
+
+ vdd_10: LDO_REG3 {
+ regulator-name = "vdd_10";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+ };
+ };
+};
+
+&io_domains {
+ pmuio-supply = <&vcc_io>;
+ vccio1-supply = <&vcc_io>;
+ vccio2-supply = <&vcc18_emmc>;
+ vccio3-supply = <&vcc_io>;
+ vccio4-supply = <&vcc_io>;
+ vccio5-supply = <&vcc_io>;
+ vccio6-supply = <&vcc_io>;
+ status = "okay";
+};
+
+&pinctrl {
+ gmac2io {
+ eth_phy_reset_pin: eth-phy-reset-pin {
+ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ leds {
+ lan_led_pin: lan-led-pin {
+ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ sys_led_pin: sys-led-pin {
+ rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wan_led_pin: wan-led-pin {
+ rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ lan {
+ lan_vdd_pin: lan-vdd-pin {
+ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&pwm2 {
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>;
+ pinctrl-names = "default";
+ vmmc-supply = <&vcc_sd>;
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <0>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+};
+
+&u2phy_host {
+ status = "okay";
+};
+
+&u2phy_otg {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb20_otg {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbdrd3 {
+ dr_mode = "host";
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Second port is for USB 3.0 */
+ rtl8153: device@2 {
+ compatible = "usbbda,8153";
+ reg = <2>;
+ };
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
index 414897a57e75..1ea4b2a95a09 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
@@ -4,381 +4,24 @@
*/
/dts-v1/;
-#include "rk3328.dtsi"
+
+#include <dt-bindings/input/input.h>
+#include "rk3328-roc.dtsi"
/ {
- model = "Firefly roc-rk3328-cc";
+ model = "Firefly ROC-RK3328-CC";
compatible = "firefly,roc-rk3328-cc", "rockchip,rk3328";
-
- aliases {
- ethernet0 = &gmac2io;
- mmc0 = &sdmmc;
- mmc1 = &emmc;
- };
-
- chosen {
- stdout-path = "serial2:1500000n8";
- };
-
- gmac_clkin: external-gmac-clock {
- compatible = "fixed-clock";
- clock-frequency = <125000000>;
- clock-output-names = "gmac_clkin";
- #clock-cells = <0>;
- };
-
- dc_12v: dc-12v {
- compatible = "regulator-fixed";
- regulator-name = "dc_12v";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <12000000>;
- regulator-max-microvolt = <12000000>;
- };
-
- vcc_sd: sdmmc-regulator {
- compatible = "regulator-fixed";
- gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc0m1_pin>;
- regulator-boot-on;
- regulator-name = "vcc_sd";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- vin-supply = <&vcc_io>;
- };
-
- vcc_sdio: sdmmcio-regulator {
- compatible = "regulator-gpio";
- gpios = <&grf_gpio 0 GPIO_ACTIVE_HIGH>;
- states = <1800000 0x1>,
- <3300000 0x0>;
- regulator-name = "vcc_sdio";
- regulator-type = "voltage";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- vin-supply = <&vcc_sys>;
- };
-
- vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&usb20_host_drv>;
- regulator-name = "vcc_host1_5v";
- regulator-always-on;
- vin-supply = <&vcc_sys>;
- };
-
- vcc_sys: vcc-sys {
- compatible = "regulator-fixed";
- regulator-name = "vcc_sys";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- vin-supply = <&dc_12v>;
- };
-
- vcc_phy: vcc-phy-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vcc_phy";
- regulator-always-on;
- regulator-boot-on;
- };
-
- leds {
- compatible = "gpio-leds";
-
- power_led: led-0 {
- label = "firefly:blue:power";
- linux,default-trigger = "heartbeat";
- gpios = <&rk805 1 GPIO_ACTIVE_LOW>;
- default-state = "on";
- };
-
- user_led: led-1 {
- label = "firefly:yellow:user";
- linux,default-trigger = "mmc1";
- gpios = <&rk805 0 GPIO_ACTIVE_LOW>;
- default-state = "off";
- };
- };
-};
-
-&analog_sound {
- status = "okay";
-};
-
-&codec {
- status = "okay";
-};
-
-&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;
- max-frequency = <150000000>;
- mmc-ddr-1_8v;
- mmc-hs200-1_8v;
- non-removable;
- pinctrl-names = "default";
- pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
- vmmc-supply = <&vcc_io>;
- vqmmc-supply = <&vcc18_emmc>;
- status = "okay";
-};
-
-&gmac2io {
- assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
- assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>;
- clock_in_out = "input";
- phy-supply = <&vcc_phy>;
- phy-mode = "rgmii";
- pinctrl-names = "default";
- pinctrl-0 = <&rgmiim1_pins>;
- snps,aal;
- snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
- snps,reset-active-low;
- snps,reset-delays-us = <0 10000 50000>;
- snps,rxpbl = <0x4>;
- snps,txpbl = <0x4>;
- tx_delay = <0x24>;
- rx_delay = <0x18>;
- status = "okay";
-};
-
-&hdmi {
- status = "okay";
-};
-
-&hdmiphy {
- status = "okay";
-};
-
-&hdmi_sound {
- status = "okay";
-};
-
-&i2c1 {
- status = "okay";
-
- rk805: pmic@18 {
- compatible = "rockchip,rk805";
- reg = <0x18>;
- interrupt-parent = <&gpio1>;
- interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
- #clock-cells = <1>;
- clock-output-names = "xin32k", "rk805-clkout2";
- gpio-controller;
- #gpio-cells = <2>;
- pinctrl-names = "default";
- pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
- wakeup-source;
-
- vcc1-supply = <&vcc_sys>;
- vcc2-supply = <&vcc_sys>;
- vcc3-supply = <&vcc_sys>;
- vcc4-supply = <&vcc_sys>;
- vcc5-supply = <&vcc_io>;
- vcc6-supply = <&vcc_io>;
-
- regulators {
- vdd_logic: DCDC_REG1 {
- regulator-name = "vdd_logic";
- regulator-min-microvolt = <712500>;
- regulator-max-microvolt = <1450000>;
- regulator-always-on;
- regulator-boot-on;
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
-
- vdd_arm: DCDC_REG2 {
- regulator-name = "vdd_arm";
- regulator-min-microvolt = <712500>;
- regulator-max-microvolt = <1450000>;
- regulator-always-on;
- regulator-boot-on;
- regulator-state-mem {
- regulator-on-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_io: DCDC_REG4 {
- regulator-name = "vcc_io";
- 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_18: LDO_REG1 {
- regulator-name = "vcc_18";
- 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>;
- };
- };
-
- vcc18_emmc: LDO_REG2 {
- regulator-name = "vcc18_emmc";
- 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_10: LDO_REG3 {
- regulator-name = "vdd_10";
- 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>;
- };
- };
- };
- };
-};
-
-&i2s0 {
- status = "okay";
-};
-
-&i2s1 {
- status = "okay";
-};
-
-&io_domains {
- status = "okay";
-
- vccio1-supply = <&vcc_io>;
- vccio2-supply = <&vcc18_emmc>;
- vccio3-supply = <&vcc_sdio>;
- vccio4-supply = <&vcc_18>;
- vccio5-supply = <&vcc_io>;
- vccio6-supply = <&vcc_io>;
- pmuio-supply = <&vcc_io>;
-};
-
-&pinctrl {
- pmic {
- pmic_int_l: pmic-int-l {
- rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-
- usb2 {
- usb20_host_drv: usb20-host-drv {
- rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-};
-
-&sdmmc {
- bus-width = <4>;
- cap-mmc-highspeed;
- cap-sd-highspeed;
- disable-wp;
- max-frequency = <150000000>;
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>;
- sd-uhs-sdr12;
- sd-uhs-sdr25;
- sd-uhs-sdr50;
- sd-uhs-sdr104;
- vmmc-supply = <&vcc_sd>;
- vqmmc-supply = <&vcc_sdio>;
- status = "okay";
-};
-
-&tsadc {
- status = "okay";
-};
-
-&u2phy {
- status = "okay";
-};
-
-&u2phy_host {
- status = "okay";
-};
-
-&u2phy_otg {
- status = "okay";
-};
-
-&uart2 {
- status = "okay";
-};
-
-&usb20_otg {
- dr_mode = "host";
- status = "okay";
-};
-
-&usbdrd3 {
- dr_mode = "host";
- status = "okay";
-};
-
-&usb_host0_ehci {
- status = "okay";
};
-&usb_host0_ohci {
- status = "okay";
+&rk805 {
+ interrupt-parent = <&gpio1>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
};
-&vop {
- status = "okay";
+&vcc_host1_5v {
+ gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
};
-&vop_mmu {
- status = "okay";
+&vcc_sdio {
+ gpios = <&grf_gpio 0 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-pc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-pc.dts
index e3e3984d01d4..329d03172433 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-pc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-pc.dts
@@ -4,8 +4,7 @@
/dts-v1/;
#include <dt-bindings/input/input.h>
-
-#include "rk3328-roc-cc.dts"
+#include "rk3328-roc.dtsi"
/ {
model = "Firefly ROC-RK3328-PC";
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-roc.dtsi
new file mode 100644
index 000000000000..b5bd5e7d5748
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc.dtsi
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2017 T-Chip Intelligent Technology Co., Ltd
+ */
+
+/dts-v1/;
+
+#include "rk3328.dtsi"
+
+/ {
+ aliases {
+ ethernet0 = &gmac2io;
+ mmc0 = &sdmmc;
+ mmc1 = &emmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ gmac_clkin: external-gmac-clock {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac_clkin";
+ #clock-cells = <0>;
+ };
+
+ dc_12v: regulator-dc-12v {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_12v";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc_sd: regulator-sdmmc {
+ compatible = "regulator-fixed";
+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0m1_pin>;
+ regulator-boot-on;
+ regulator-name = "vcc_sd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_io>;
+ };
+
+ vcc_sdio: regulator-sdmmcio {
+ compatible = "regulator-gpio";
+ states = <1800000 0x1>, <3300000 0x0>;
+ regulator-name = "vcc_sdio";
+ regulator-type = "voltage";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc_host1_5v: vcc_otg_5v: regulator-vcc-host1-5v {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb20_host_drv>;
+ regulator-name = "vcc_host1_5v";
+ regulator-always-on;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc_sys: regulator-vcc-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vcc_phy: regulator-vcc-phy {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_phy";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ power_led: led-0 {
+ label = "firefly:blue:power";
+ linux,default-trigger = "heartbeat";
+ gpios = <&rk805 1 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+
+ user_led: led-1 {
+ label = "firefly:yellow:user";
+ linux,default-trigger = "mmc1";
+ gpios = <&rk805 0 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ };
+ };
+};
+
+&analog_sound {
+ status = "okay";
+};
+
+&codec {
+ status = "okay";
+};
+
+&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;
+ max-frequency = <150000000>;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+ vmmc-supply = <&vcc_io>;
+ vqmmc-supply = <&vcc18_emmc>;
+ status = "okay";
+};
+
+&gmac2io {
+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
+ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>;
+ clock_in_out = "input";
+ phy-supply = <&vcc_phy>;
+ phy-mode = "rgmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmiim1_pins>;
+ snps,aal;
+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 50000>;
+ snps,rxpbl = <0x4>;
+ snps,txpbl = <0x4>;
+ tx_delay = <0x24>;
+ rx_delay = <0x18>;
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmiphy {
+ status = "okay";
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ rk805: pmic@18 {
+ compatible = "rockchip,rk805";
+ reg = <0x18>;
+ #clock-cells = <1>;
+ clock-output-names = "xin32k", "rk805-clkout2";
+ gpio-controller;
+ #gpio-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>;
+ system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc_sys>;
+ vcc2-supply = <&vcc_sys>;
+ vcc3-supply = <&vcc_sys>;
+ vcc4-supply = <&vcc_sys>;
+ vcc5-supply = <&vcc_io>;
+ vcc6-supply = <&vcc_io>;
+
+ regulators {
+ vdd_logic: DCDC_REG1 {
+ regulator-name = "vdd_logic";
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1450000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1450000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-state-mem {
+ regulator-on-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_io: DCDC_REG4 {
+ regulator-name = "vcc_io";
+ 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_18: LDO_REG1 {
+ regulator-name = "vcc_18";
+ 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>;
+ };
+ };
+
+ vcc18_emmc: LDO_REG2 {
+ regulator-name = "vcc18_emmc";
+ 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_10: LDO_REG3 {
+ regulator-name = "vdd_10";
+ 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>;
+ };
+ };
+ };
+ };
+};
+
+&i2s0 {
+ status = "okay";
+};
+
+&i2s1 {
+ status = "okay";
+};
+
+&io_domains {
+ status = "okay";
+
+ vccio1-supply = <&vcc_io>;
+ vccio2-supply = <&vcc18_emmc>;
+ vccio3-supply = <&vcc_sdio>;
+ vccio4-supply = <&vcc_18>;
+ vccio5-supply = <&vcc_io>;
+ vccio6-supply = <&vcc_io>;
+ pmuio-supply = <&vcc_io>;
+};
+
+&pinctrl {
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ usb2 {
+ usb20_host_drv: usb20-host-drv {
+ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ disable-wp;
+ max-frequency = <150000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_sd>;
+ vqmmc-supply = <&vcc_sdio>;
+ status = "okay";
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+};
+
+&u2phy_host {
+ status = "okay";
+};
+
+&u2phy_otg {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb20_otg {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbdrd3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts
index 3e08e2fd0a78..425de197ddb8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts
@@ -64,7 +64,7 @@
};
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -74,7 +74,7 @@
vin-supply = <&vcc_io>;
};
- vcc_host_5v: vcc-host-5v-regulator {
+ vcc_host_5v: regulator-vcc-host-5v {
compatible = "regulator-fixed";
gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
@@ -86,7 +86,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -95,7 +95,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc_wifi: vcc-wifi-regulator {
+ vcc_wifi: regulator-vcc-wifi {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -249,7 +249,7 @@
#gpio-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
index 90fef766f3ae..745d3e996418 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
@@ -27,7 +27,7 @@
#clock-cells = <0>;
};
- vcc_sd: sdmmc-regulator {
+ vcc_sd: regulator-sdmmc {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -39,7 +39,7 @@
};
/* Common enable line for all of the rails mentioned in the labels */
- vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator {
+ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: regulator-vcc-host-5v {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -50,7 +50,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -181,7 +181,7 @@
#gpio-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 16b4faa22e4f..0597de415fe0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -754,8 +754,7 @@
compatible = "rockchip,rk3328-dw-hdmi";
reg = <0x0 0xff3c0000 0x0 0x20000>;
reg-io-width = <4>;
- interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_HDMI>,
<&cru SCLK_HDMI_SFC>,
<&cru SCLK_RTC32K>;
@@ -813,8 +812,10 @@
};
cru: clock-controller@ff440000 {
- compatible = "rockchip,rk3328-cru", "rockchip,cru", "syscon";
+ compatible = "rockchip,rk3328-cru";
reg = <0x0 0xff440000 0x0 0x1000>;
+ clocks = <&xin24m>;
+ clock-names = "xin24m";
rockchip,grf = <&grf>;
#clock-cells = <1>;
#reset-cells = <1>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi
index e5c0dbf794ae..8662494a44d5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi
@@ -85,7 +85,7 @@
};
/* supplies both host and otg */
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
@@ -97,7 +97,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_lan: vcc-lan-regulator {
+ vcc_lan: regulator-vcc-lan {
compatible = "regulator-fixed";
regulator-name = "vcc_lan";
regulator-min-microvolt = <3300000>;
@@ -107,7 +107,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts b/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
index 029b8e22e709..445ec20d6df8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
@@ -68,7 +68,7 @@
};
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -113,7 +113,7 @@
pinctrl-0 = <&pmic_int>, <&pmic_sleep>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc_sys>;
vcc2-supply = <&vcc_sys>;
vcc3-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts b/arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts
index e0cc4da7f392..b99bb0a5f900 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3368-lba3368.dts
@@ -47,7 +47,7 @@
analog-sound {
compatible = "audio-graph-card";
dais = <&i2s_8ch_p0>;
- hp-det-gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
+ hp-det-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
label = "alc5640";
routing = "Mic Jack", "MICBIAS1",
"IN1P", "Mic Jack",
@@ -64,7 +64,7 @@
pinctrl-0 = <&hp_det>;
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-min-microvolt = <12000000>;
@@ -80,7 +80,7 @@
#clock-cells = <0>;
};
- hub_avdd: hub-avdd-regulator {
+ hub_avdd: regulator-hub-avdd {
compatible = "regulator-fixed";
regulator-name = "hub_avdd";
regulator-min-microvolt = <3300000>;
@@ -111,7 +111,7 @@
pinctrl-0 = <&wifi_reg_on>;
};
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
gpio = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
regulator-name = "vcc_host";
@@ -124,7 +124,7 @@
regulator-always-on;
};
- vcc_lan: vcc-lan-regulator {
+ vcc_lan: regulator-vcc-lan {
compatible = "regulator-fixed";
regulator-name = "vcc_lan";
regulator-min-microvolt = <3300000>;
@@ -133,7 +133,7 @@
regulator-always-on;
};
- vcc_otg: vcc-otg-regulator {
+ vcc_otg: regulator-vcc-otg {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
regulator-name = "vcc_otg";
@@ -146,7 +146,7 @@
regulator-always-on;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -156,7 +156,7 @@
regulator-boot-on;
};
- vdd10_usb: vdd10-usb-regulator {
+ vdd10_usb: regulator-vdd10-usb {
compatible = "regulator-fixed";
regulator-name = "vdd10_usb";
regulator-min-microvolt = <1000000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts
index cae01d35b93d..ab70ee5f561a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts
@@ -38,7 +38,7 @@
};
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -47,7 +47,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_baseboard: vcc3v3-baseboard {
+ vcc3v3_baseboard: regulator-vcc3v3-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_baseboard";
regulator-always-on;
@@ -57,7 +57,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_otg: vcc5v0-otg-regulator {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi
index 8ac8acf4082d..8ccc3184a836 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi
@@ -61,7 +61,6 @@
fan: fan@18 {
compatible = "ti,amc6821";
reg = <0x18>;
- #cooling-cells = <2>;
};
rtc_twi: rtc@6f {
@@ -97,7 +96,7 @@
};
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -179,7 +178,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>, <&pmic_sleep>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc_sys>;
vcc2-supply = <&vcc_sys>;
vcc3-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts b/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts
index 23ae2d9de382..abef858e7cea 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts
@@ -73,7 +73,7 @@
};
};
- vcc_18: vcc18-regulator {
+ vcc_18: regulator-vcc18 {
compatible = "regulator-fixed";
regulator-name = "vcc_18";
regulator-min-microvolt = <1800000>;
@@ -84,7 +84,7 @@
};
/* supplies both host and otg */
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -95,7 +95,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_io: vcc-io-regulator {
+ vcc_io: regulator-vcc-io {
compatible = "regulator-fixed";
regulator-name = "vcc_io";
regulator-min-microvolt = <3300000>;
@@ -105,7 +105,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_lan: vcc-lan-regulator {
+ vcc_lan: regulator-vcc-lan {
compatible = "regulator-fixed";
regulator-name = "vcc_lan";
regulator-min-microvolt = <3300000>;
@@ -115,7 +115,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sd: vcc-sd-regulator {
+ vcc_sd: regulator-vcc-sd {
compatible = "regulator-fixed";
regulator-name = "vcc_sd";
gpio = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>;
@@ -124,7 +124,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -133,7 +133,7 @@
regulator-boot-on;
};
- vccio_sd: vcc-io-sd-regulator {
+ vccio_sd: regulator-vcc-io-sd {
compatible = "regulator-fixed";
regulator-name = "vccio_sd";
regulator-min-microvolt = <1800000>;
@@ -143,7 +143,7 @@
vin-supply = <&vcc_io>;
};
- vccio_wl: vccio-wl-regulator {
+ vccio_wl: regulator-vccio-wl {
compatible = "regulator-fixed";
regulator-name = "vccio_wl";
regulator-min-microvolt = <3300000>;
@@ -153,7 +153,7 @@
vin-supply = <&vcc_io>;
};
- vdd_10: vdd-10-regulator {
+ vdd_10: regulator-vdd-10 {
compatible = "regulator-fixed";
regulator-name = "vdd_10";
regulator-min-microvolt = <1000000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
index 29df84b81552..5132ffe014ff 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
@@ -38,7 +38,7 @@
};
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -73,7 +73,7 @@
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&pmic_sleep>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc_sys>;
vcc2-supply = <&vcc_sys>;
vcc3-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
index 7f14206d53c3..b73100c6d182 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
@@ -79,7 +79,7 @@
<&gpio3 RK_PA4 GPIO_ACTIVE_LOW>;
};
- vcc_18: vcc18-regulator {
+ vcc_18: regulator-vcc18 {
compatible = "regulator-fixed";
regulator-name = "vcc_18";
regulator-min-microvolt = <1800000>;
@@ -90,7 +90,7 @@
};
/* supplies both host and otg */
- vcc_host: vcc-host-regulator {
+ vcc_host: regulator-vcc-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
@@ -102,7 +102,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_io: vcc-io-regulator {
+ vcc_io: regulator-vcc-io {
compatible = "regulator-fixed";
regulator-name = "vcc_io";
regulator-min-microvolt = <3300000>;
@@ -112,7 +112,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_lan: vcc-lan-regulator {
+ vcc_lan: regulator-vcc-lan {
compatible = "regulator-fixed";
regulator-name = "vcc_lan";
regulator-min-microvolt = <3300000>;
@@ -122,7 +122,7 @@
vin-supply = <&vcc_io>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -131,7 +131,7 @@
regulator-boot-on;
};
- vccio_wl: vccio-wl-regulator {
+ vccio_wl: regulator-vccio-wl {
compatible = "regulator-fixed";
regulator-name = "vccio_wl";
regulator-min-microvolt = <3300000>;
@@ -141,7 +141,7 @@
vin-supply = <&vcc_io>;
};
- vdd_10: vdd-10-regulator {
+ vdd_10: regulator-vdd-10 {
compatible = "regulator-fixed";
regulator-name = "vdd_10";
regulator-min-microvolt = <1000000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts b/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts
index 1489eb32e266..b90bf26b58be 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts
@@ -66,7 +66,7 @@
#clock-cells = <0>;
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -168,7 +168,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s3";
regulator-always-on;
@@ -178,7 +178,7 @@
vin-supply = <&vcc_1v8>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -188,7 +188,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -199,7 +199,7 @@
};
/* For USB3.0 Port1/2 */
- vcc5v0_host1: vcc5v0-host1-regulator {
+ vcc5v0_host1: regulator-vcc5v0-host1 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -211,7 +211,7 @@
};
/* For USB2.0 Port1/2 */
- vcc5v0_host3: vcc5v0-host3-regulator {
+ vcc5v0_host3: regulator-vcc5v0-host3 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
@@ -222,7 +222,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_typec: vcc5v0-typec-regulator {
+ vcc5v0_typec: regulator-vcc5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -233,7 +233,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "regulator-fixed";
regulator-name = "vdd_log";
regulator-always-on;
@@ -309,7 +309,7 @@
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <1>;
clock-output-names = "xin32k", "rk808-clkout2";
@@ -541,11 +541,11 @@
status = "okay";
rt5651: audio-codec@1a {
- compatible = "rockchip,rt5651";
+ compatible = "realtek,rt5651";
reg = <0x1a>;
clocks = <&cru SCLK_I2S_8CH_OUT>;
clock-names = "mclk";
- hp-det-gpio = <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>;
+ hp-det-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>;
spk-con-gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
#sound-dai-cells = <0>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
index 54e67d2dac09..9ea91f90c67a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
@@ -75,7 +75,7 @@
#clock-cells = <0>;
};
- vdd_center: vdd-center {
+ vdd_center: regulator-vdd-center {
compatible = "pwm-regulator";
pwms = <&pwm3 0 25000 0>;
regulator-name = "vdd_center";
@@ -86,7 +86,7 @@
status = "okay";
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -95,7 +95,7 @@
regulator-max-microvolt = <3300000>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -104,7 +104,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
@@ -114,14 +114,14 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
regulator-name = "vcc_phy";
regulator-always-on;
regulator-boot-on;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
regulator-name = "vcc_phy";
regulator-always-on;
@@ -178,7 +178,7 @@
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <1>;
clock-output-names = "rk808-clkout1", "rk808-clkout2";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
index f4491317a1b0..0568dfa140b3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
@@ -72,7 +72,7 @@
#clock-cells = <0>;
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -178,7 +178,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s3";
regulator-always-on;
@@ -188,7 +188,7 @@
vin-supply = <&vcc_1v8>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
@@ -200,7 +200,7 @@
vin-supply = <&dc_12v>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -211,7 +211,7 @@
};
/* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
@@ -222,7 +222,7 @@
vin-supply = <&vcc_sys>;
};
- vcc5v0_typec: vcc5v0-typec-regulator {
+ vcc5v0_typec: regulator-vcc5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -233,7 +233,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -243,7 +243,7 @@
vin-supply = <&dc_12v>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc_sys>;
@@ -326,7 +326,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
index cacbad35cfc8..988e6ca32fac 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
@@ -8,7 +8,7 @@
#include "rk3399-gru.dtsi"
/ {
- pp900_ap: pp900-ap {
+ pp900_ap: regulator-pp900-ap {
compatible = "regulator-fixed";
regulator-name = "pp900_ap";
@@ -29,7 +29,7 @@
pp900_pcie: pp900-ap {
};
- pp3000: pp3000 {
+ pp3000: regulator-pp3000 {
compatible = "regulator-fixed";
regulator-name = "pp3000";
pinctrl-names = "default";
@@ -46,7 +46,7 @@
vin-supply = <&ppvar_sys>;
};
- ppvar_centerlogic_pwm: ppvar-centerlogic-pwm {
+ ppvar_centerlogic_pwm: regulator-ppvar-centerlogic-pwm {
compatible = "pwm-regulator";
regulator-name = "ppvar_centerlogic_pwm";
@@ -78,7 +78,7 @@
};
/* Schematics call this PPVAR even though it's fixed */
- ppvar_logic: ppvar-logic {
+ ppvar_logic: regulator-ppvar-logic {
compatible = "regulator-fixed";
regulator-name = "ppvar_logic";
@@ -91,7 +91,7 @@
vin-supply = <&ppvar_sys>;
};
- pp1800_audio: pp1800-audio {
+ pp1800_audio: regulator-pp1800-audio {
compatible = "regulator-fixed";
regulator-name = "pp1800_audio";
pinctrl-names = "default";
@@ -107,7 +107,7 @@
};
/* gpio is shared with pp3300_wifi_bt */
- pp1800_pcie: pp1800-pcie {
+ pp1800_pcie: regulator-pp1800-pcie {
compatible = "regulator-fixed";
regulator-name = "pp1800_pcie";
pinctrl-names = "default";
@@ -129,7 +129,7 @@
pp3000_ap: pp3000_emmc: pp3000 {
};
- pp1500_ap_io: pp1500-ap-io {
+ pp1500_ap_io: regulator-pp1500-ap-io {
compatible = "regulator-fixed";
regulator-name = "pp1500_ap_io";
pinctrl-names = "default";
@@ -146,7 +146,7 @@
vin-supply = <&pp1800>;
};
- pp3300_disp: pp3300-disp {
+ pp3300_disp: regulator-pp3300-disp {
compatible = "regulator-fixed";
regulator-name = "pp3300_disp";
pinctrl-names = "default";
@@ -164,7 +164,7 @@
};
/* gpio is shared with pp1800_pcie and pinctrl is set there */
- pp3300_wifi_bt: pp3300-wifi-bt {
+ pp3300_wifi_bt: regulator-pp3300-wifi-bt {
compatible = "regulator-fixed";
regulator-name = "pp3300_wifi_bt";
@@ -180,7 +180,7 @@
* With some stretching of the imagination, we can call the 1.8V
* regulator a supply.
*/
- wlan_pd_n: wlan-pd-n {
+ wlan_pd_n: regulator-wlan-pd-n {
compatible = "regulator-fixed";
regulator-name = "wlan_pd_n";
pinctrl-names = "default";
@@ -550,7 +550,7 @@ ap_i2c_tp: &i2c5 {
};
&pinctrl {
- discrete-regulators {
+ discretes {
pp1500_en: pp1500-en {
rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO
&pcfg_pull_none>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
index 2cc9b3386c16..7b907c80dd32 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
@@ -28,7 +28,7 @@
/* Power tree */
- p3_3v_dig: p3-3v-dig {
+ p3_3v_dig: regulator-p3-3v-dig {
compatible = "regulator-fixed";
regulator-name = "p3.3v_dig";
pinctrl-names = "default";
@@ -314,7 +314,7 @@ ap_i2c_dig: &i2c2 {
};
};
- discrete-regulators {
+ discretes {
cpu3_pen_pwr_en: cpu3-pen-pwr-en {
rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi
index d5e035823eb5..19b23b438965 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi
@@ -13,7 +13,7 @@
/* Power tree */
/* ppvar_sys children, sorted by name */
- pp1250_s3: pp1250-s3 {
+ pp1250_s3: regulator-pp1250-s3 {
compatible = "regulator-fixed";
regulator-name = "pp1250_s3";
@@ -26,7 +26,7 @@
vin-supply = <&ppvar_sys>;
};
- pp1250_cam: pp1250-dvdd {
+ pp1250_cam: regulator-pp1250-dvdd {
compatible = "regulator-fixed";
regulator-name = "pp1250_dvdd";
pinctrl-names = "default";
@@ -42,7 +42,7 @@
vin-supply = <&pp1250_s3>;
};
- pp900_s0: pp900-s0 {
+ pp900_s0: regulator-pp900-s0 {
compatible = "regulator-fixed";
regulator-name = "pp900_s0";
@@ -55,7 +55,7 @@
vin-supply = <&ppvar_sys>;
};
- ppvarn_lcd: ppvarn-lcd {
+ ppvarn_lcd: regulator-ppvarn-lcd {
compatible = "regulator-fixed";
regulator-name = "ppvarn_lcd";
pinctrl-names = "default";
@@ -66,7 +66,7 @@
vin-supply = <&ppvar_sys>;
};
- ppvarp_lcd: ppvarp-lcd {
+ ppvarp_lcd: regulator-ppvarp-lcd {
compatible = "regulator-fixed";
regulator-name = "ppvarp_lcd";
pinctrl-names = "default";
@@ -78,7 +78,7 @@
};
/* pp1800 children, sorted by name */
- pp900_s3: pp900-s3 {
+ pp900_s3: regulator-pp900-s3 {
compatible = "regulator-fixed";
regulator-name = "pp900_s3";
@@ -96,7 +96,7 @@
};
/* pp3300 children, sorted by name */
- pp2800_cam: pp2800-avdd {
+ pp2800_cam: regulator-pp2800-avdd {
compatible = "regulator-fixed";
regulator-name = "pp2800_avdd";
pinctrl-names = "default";
@@ -127,7 +127,7 @@
* the boot process it also enables its supply regulator bt_3v3,
* which changes BT_EN to high.
*/
- bt_3v3: bt-3v3 {
+ bt_3v3: regulator-bt-3v3 {
compatible = "regulator-fixed";
regulator-name = "bt_3v3";
pinctrl-names = "default";
@@ -138,7 +138,7 @@
vin-supply = <&pp3300_s3>;
};
- wlan_3v3: wlan-3v3 {
+ wlan_3v3: regulator-wlan-3v3 {
compatible = "regulator-fixed";
regulator-name = "wlan_3v3";
pinctrl-names = "default";
@@ -833,7 +833,7 @@ camera: &i2c7 {
};
};
- discrete-regulators {
+ discretes {
display_rst_l: display-rst-l {
rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_down>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
index 776c0eec04d7..6d9e60b01225 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -42,14 +42,14 @@
* schematic.
*/
- ppvar_sys: ppvar-sys {
+ ppvar_sys: regulator-ppvar-sys {
compatible = "regulator-fixed";
regulator-name = "ppvar_sys";
regulator-always-on;
regulator-boot-on;
};
- pp1200_lpddr: pp1200-lpddr {
+ pp1200_lpddr: regulator-pp1200-lpddr {
compatible = "regulator-fixed";
regulator-name = "pp1200_lpddr";
@@ -62,7 +62,7 @@
vin-supply = <&ppvar_sys>;
};
- pp1800: pp1800 {
+ pp1800: regulator-pp1800 {
compatible = "regulator-fixed";
regulator-name = "pp1800";
@@ -75,7 +75,7 @@
vin-supply = <&ppvar_sys>;
};
- pp3300: pp3300 {
+ pp3300: regulator-pp3300 {
compatible = "regulator-fixed";
regulator-name = "pp3300";
@@ -88,7 +88,7 @@
vin-supply = <&ppvar_sys>;
};
- pp5000: pp5000 {
+ pp5000: regulator-pp5000 {
compatible = "regulator-fixed";
regulator-name = "pp5000";
@@ -101,7 +101,7 @@
vin-supply = <&ppvar_sys>;
};
- ppvar_bigcpu_pwm: ppvar-bigcpu-pwm {
+ ppvar_bigcpu_pwm: regulator-ppvar-bigcpu-pwm {
compatible = "pwm-regulator";
regulator-name = "ppvar_bigcpu_pwm";
@@ -130,7 +130,7 @@
regulator-settling-time-up-us = <322>;
};
- ppvar_litcpu_pwm: ppvar-litcpu-pwm {
+ ppvar_litcpu_pwm: regulator-ppvar-litcpu-pwm {
compatible = "pwm-regulator";
regulator-name = "ppvar_litcpu_pwm";
@@ -159,7 +159,7 @@
regulator-settling-time-up-us = <384>;
};
- ppvar_gpu_pwm: ppvar-gpu-pwm {
+ ppvar_gpu_pwm: regulator-ppvar-gpu-pwm {
compatible = "pwm-regulator";
regulator-name = "ppvar_gpu_pwm";
@@ -224,7 +224,7 @@
pp1800_usb: pp1800 {
};
- pp3000_sd_slot: pp3000-sd-slot {
+ pp3000_sd_slot: regulator-pp3000-sd-slot {
compatible = "regulator-fixed";
regulator-name = "pp3000_sd_slot";
pinctrl-names = "default";
@@ -724,7 +724,7 @@ ap_i2c_audio: &i2c8 {
};
};
- discrete-regulators {
+ discretes {
sd_io_pwr_en: sd-io-pwr-en {
rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO
&pcfg_pull_none>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts
index 5a02502d21cd..81c4fcb30f39 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts
@@ -27,7 +27,7 @@
#clock-cells = <0>;
};
- dc_5v: dc-5v {
+ dc_5v: regulator-dc-5v {
compatible = "regulator-fixed";
regulator-name = "dc_5v";
regulator-always-on;
@@ -56,7 +56,7 @@
};
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-min-microvolt = <5000000>;
@@ -65,14 +65,14 @@
vin-supply = <&dc_5v>;
};
- vcc_phy: vcc-phy-regulator {
+ vcc_phy: regulator-vcc-phy {
compatible = "regulator-fixed";
regulator-name = "vcc_phy";
regulator-always-on;
regulator-boot-on;
};
- vcc1v8_s0: vcc1v8-s0 {
+ vcc1v8_s0: regulator-vcc1v8-s0 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s0";
regulator-min-microvolt = <1800000>;
@@ -80,7 +80,7 @@
regulator-always-on;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-min-microvolt = <3300000>;
@@ -89,7 +89,7 @@
vin-supply = <&vcc_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>;
@@ -99,7 +99,7 @@
regulator-always-on;
};
- vcc5v0_typec: vcc5v0-typec-regulator {
+ vcc5v0_typec: regulator-vcc5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -110,7 +110,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb: vcc5v0-usb {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -120,7 +120,7 @@
vin-supply = <&dc_5v>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc_sys>;
@@ -252,7 +252,7 @@
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <1>;
clock-output-names = "xin32k", "rtc_clko_wifi";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi
index c772985ae4e5..880c24084952 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi
@@ -45,7 +45,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s3";
regulator-always-on;
@@ -55,7 +55,7 @@
vin-supply = <&vcc_1v8>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-always-on;
@@ -66,7 +66,7 @@
};
/* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
@@ -77,7 +77,7 @@
vin-supply = <&vsys_5v0>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vsys_3v3>;
@@ -88,14 +88,14 @@
regulator-max-microvolt = <1400000>;
};
- vsys: vsys {
+ vsys: regulator-vsys {
compatible = "regulator-fixed";
regulator-name = "vsys";
regulator-always-on;
regulator-boot-on;
};
- vsys_3v3: vsys-3v3 {
+ vsys_3v3: regulator-vsys-3v3 {
compatible = "regulator-fixed";
regulator-name = "vsys_3v3";
regulator-always-on;
@@ -105,7 +105,7 @@
vin-supply = <&vsys>;
};
- vsys_5v0: vsys-5v0 {
+ vsys_5v0: regulator-vsys-5v0 {
compatible = "regulator-fixed";
regulator-name = "vsys_5v0";
regulator-always-on;
@@ -315,7 +315,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vsys_3v3>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
index b0c1fb0b704e..e7d4a2f9a95e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
@@ -23,7 +23,7 @@
mmc1 = &sdhci;
};
- avdd_0v9_s0: avdd-0v9-s0 {
+ avdd_0v9_s0: regulator-avdd-0v9-s0 {
compatible = "regulator-fixed";
regulator-name = "avdd_0v9_s0";
regulator-always-on;
@@ -33,7 +33,7 @@
vin-supply = <&vcc1v8_sys_s3>;
};
- avdd_1v8_s0: avdd-1v8-s0 {
+ avdd_1v8_s0: regulator-avdd-1v8-s0 {
compatible = "regulator-fixed";
regulator-name = "avdd_1v8_s0";
regulator-always-on;
@@ -86,7 +86,7 @@
};
};
- hdd_a_power: hdd-a-power {
+ hdd_a_power: regulator-hdd-a-power {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
@@ -98,7 +98,7 @@
startup-delay-us = <2000000>;
};
- hdd_b_power: hdd-b-power {
+ hdd_b_power: regulator-hdd-b-power {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
@@ -110,7 +110,7 @@
startup-delay-us = <2000000>;
};
- pcie_power: pcie-power {
+ pcie_power: regulator-pcie-power {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
@@ -122,7 +122,7 @@
vin-supply = <&vcc5v0_perdev>;
};
- usblan_power: usblan-power {
+ usblan_power: regulator-usblan-power {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>;
@@ -134,7 +134,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc1v8_sys_s0: vcc1v8-sys-s0 {
+ vcc1v8_sys_s0: regulator-vcc1v8-sys-s0 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_sys_s0";
regulator-always-on;
@@ -144,7 +144,7 @@
vin-supply = <&vcc1v8_sys_s3>;
};
- vcc3v0_sd: vcc3v0-sd {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
@@ -157,7 +157,7 @@
vin-supply = <&vcc3v3_sys_s3>;
};
- vcc3v3_sys_s3: vcc_lan: vcc3v3-sys-s3 {
+ vcc3v3_sys_s3: vcc_lan: regulator-vcc3v3-sys-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys_s3";
regulator-always-on;
@@ -171,7 +171,7 @@
};
};
- vcc5v0_perdev: vcc5v0-perdev {
+ vcc5v0_perdev: regulator-vcc5v0-perdev {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_perdev";
regulator-always-on;
@@ -181,7 +181,7 @@
vin-supply = <&vcc12v_dcin_bkup>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -195,7 +195,7 @@
};
};
- vcc5v0_usb: vcc5v0-usb {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>;
@@ -209,7 +209,7 @@
vin-supply = <&vcc5v0_perdev>;
};
- vcc12v_dcin: vcc12v-dcin {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -218,7 +218,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc12v_dcin_bkup: vcc12v-dcin-bkup {
+ vcc12v_dcin_bkup: regulator-vcc12v-dcin-bkup {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin_bkup";
regulator-always-on;
@@ -309,7 +309,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc5v0_sys>;
vcc2-supply = <&vcc5v0_sys>;
vcc3-supply = <&vcc5v0_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts
index f12b1eb00575..2cdc2013c320 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts
@@ -40,7 +40,7 @@
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
};
- dc5v_adp: dc5v-adp {
+ dc5v_adp: regulator-dc5v-adp {
compatible = "regulator-fixed";
regulator-name = "dc5v_adapter";
regulator-always-on;
@@ -49,7 +49,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc3v3_lan: vcc3v3-lan {
+ vcc3v3_lan: regulator-vcc3v3-lan {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_lan";
regulator-always-on;
@@ -59,7 +59,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -69,7 +69,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host0: vcc5v0_host1: vcc5v0-host {
+ vcc5v0_host0: vcc5v0_host1: regulator-vcc5v0-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -79,7 +79,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host3: vcc5v0-host3 {
+ vcc5v0_host3: regulator-vcc5v0-host3 {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host3";
enable-active-high;
@@ -90,7 +90,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -100,7 +100,7 @@
vin-supply = <&dc5v_adp>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc5v0_sys>;
@@ -187,7 +187,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc5v0_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
index 3bf8f959e42c..e5fc05cc64bd 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
@@ -15,7 +15,7 @@
model = "FriendlyElec NanoPC-T4";
compatible = "friendlyarm,nanopc-t4", "rockchip,rk3399";
- vcc12v0_sys: vcc12v0-sys {
+ vcc12v0_sys: regulator-vcc12v0-sys {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -24,7 +24,7 @@
regulator-name = "vcc12v0_sys";
};
- vcc5v0_host0: vcc5v0-host0 {
+ vcc5v0_host0: regulator-vcc5v0-host0 {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dts
index 60358ab8c7df..e091b20c2d1f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dts
@@ -10,57 +10,14 @@
*/
/dts-v1/;
-#include "rk3399-nanopi4.dtsi"
+
+#include "rk3399-nanopi-m4.dtsi"
/ {
model = "FriendlyElec NanoPi M4";
compatible = "friendlyarm,nanopi-m4", "rockchip,rk3399";
-
- vdd_5v: vdd-5v {
- compatible = "regulator-fixed";
- regulator-name = "vdd_5v";
- regulator-always-on;
- regulator-boot-on;
- };
-
- vcc5v0_core: vcc5v0-core {
- compatible = "regulator-fixed";
- regulator-name = "vcc5v0_core";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vdd_5v>;
- };
-
- vcc5v0_usb1: vcc5v0-usb1 {
- compatible = "regulator-fixed";
- regulator-name = "vcc5v0_usb1";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vcc5v0_sys>;
- };
-
- vcc5v0_usb2: vcc5v0-usb2 {
- compatible = "regulator-fixed";
- regulator-name = "vcc5v0_usb2";
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&vcc5v0_sys>;
- };
-};
-
-&vcc3v3_sys {
- vin-supply = <&vcc5v0_core>;
};
&u2phy0_host {
phy-supply = <&vcc5v0_usb1>;
};
-
-&u2phy1_host {
- phy-supply = <&vcc5v0_usb2>;
-};
-
-&vbus_typec {
- regulator-always-on;
- vin-supply = <&vdd_5v>;
-};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dtsi
new file mode 100644
index 000000000000..1ac6bc140823
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4.dtsi
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * FriendlyElec NanoPi M4 board device tree source
+ *
+ * Copyright (c) 2018 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * Copyright (c) 2018 Collabora Ltd.
+ * Copyright (c) 2019 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "rk3399-nanopi4.dtsi"
+
+/ {
+ vdd_5v: regulator-vdd-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_5v";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc5v0_core: regulator-vcc5v0-core {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_core";
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vdd_5v>;
+ };
+
+ vcc5v0_usb1: regulator-vcc5v0-usb1 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb1";
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_usb2: regulator-vcc5v0-usb2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb2";
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&vcc3v3_sys {
+ vin-supply = <&vcc5v0_core>;
+};
+
+&u2phy1_host {
+ phy-supply = <&vcc5v0_usb2>;
+};
+
+&vbus_typec {
+ regulator-always-on;
+ vin-supply = <&vdd_5v>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4b.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4b.dts
index 65cb21837b0c..d03ce6fa5bf6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-m4b.dts
@@ -6,7 +6,8 @@
*/
/dts-v1/;
-#include "rk3399-nanopi-m4.dts"
+
+#include "rk3399-nanopi-m4.dtsi"
/ {
model = "FriendlyElec NanoPi M4B";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts
index 195410b089b9..3ae645edeb62 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts
@@ -12,14 +12,14 @@
model = "FriendlyARM NanoPi NEO4";
compatible = "friendlyarm,nanopi-neo4", "rockchip,rk3399";
- vdd_5v: vdd-5v {
+ vdd_5v: regulator-vdd-5v {
compatible = "regulator-fixed";
regulator-name = "vdd_5v";
regulator-always-on;
regulator-boot-on;
};
- vcc5v0_core: vcc5v0-core {
+ vcc5v0_core: regulator-vcc5v0-core {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_core";
regulator-always-on;
@@ -27,7 +27,7 @@
vin-supply = <&vdd_5v>;
};
- vcc5v0_usb1: vcc5v0-usb1 {
+ vcc5v0_usb1: regulator-vcc5v0-usb1 {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb1";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s-enterprise.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s-enterprise.dts
index a23d11ca0eb6..b76f98962076 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s-enterprise.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s-enterprise.dts
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/dts-v1/;
-#include "rk3399-nanopi-r4s.dts"
+
+#include "rk3399-nanopi-r4s.dtsi"
/ {
model = "FriendlyElec NanoPi R4S Enterprise Edition";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts
index fe5b52610010..ec3883f6221e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts
@@ -1,133 +1,13 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
- * FriendlyElec NanoPC-T4 board device tree source
- *
* Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd.
- * (http://www.friendlyarm.com)
- *
- * Copyright (c) 2018 Collabora Ltd.
- *
- * Copyright (c) 2020 Jensen Huang <jensenhuang@friendlyarm.com>
- * Copyright (c) 2020 Marty Jones <mj8263788@gmail.com>
- * Copyright (c) 2021 Tianling Shen <cnsztl@gmail.com>
*/
/dts-v1/;
-#include "rk3399-nanopi4.dtsi"
+
+#include "rk3399-nanopi-r4s.dtsi"
/ {
model = "FriendlyElec NanoPi R4S";
compatible = "friendlyarm,nanopi-r4s", "rockchip,rk3399";
-
- /delete-node/ display-subsystem;
-
- gpio-leds {
- pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>;
-
- /delete-node/ led-0;
-
- lan_led: led-lan {
- gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
- label = "green:lan";
- };
-
- sys_led: led-sys {
- gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
- label = "red:power";
- default-state = "on";
- };
-
- wan_led: led-wan {
- gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
- label = "green:wan";
- };
- };
-
- gpio-keys {
- pinctrl-0 = <&reset_button_pin>;
-
- /delete-node/ key-power;
-
- key-reset {
- debounce-interval = <50>;
- gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>;
- label = "reset";
- linux,code = <KEY_RESTART>;
- };
- };
-
- vdd_5v: vdd-5v {
- compatible = "regulator-fixed";
- regulator-name = "vdd_5v";
- regulator-always-on;
- regulator-boot-on;
- };
-};
-
-&emmc_phy {
- status = "disabled";
-};
-
-&i2c4 {
- status = "disabled";
-};
-
-&pcie0 {
- max-link-speed = <1>;
- num-lanes = <1>;
- vpcie3v3-supply = <&vcc3v3_sys>;
-};
-
-&pinctrl {
- gpio-leds {
- /delete-node/ status-led-pin;
-
- lan_led_pin: lan-led-pin {
- rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- sys_led_pin: sys-led-pin {
- rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- wan_led_pin: wan-led-pin {
- rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- rockchip-key {
- /delete-node/ power-key;
-
- reset_button_pin: reset-button-pin {
- rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-};
-
-&sdhci {
- status = "disabled";
-};
-
-&sdio0 {
- status = "disabled";
-};
-
-&u2phy0_host {
- phy-supply = <&vdd_5v>;
-};
-
-&u2phy1_host {
- status = "disabled";
-};
-
-&uart0 {
- status = "disabled";
-};
-
-&usbdrd_dwc3_0 {
- dr_mode = "host";
-};
-
-&vcc3v3_sys {
- vin-supply = <&vcc5v0_sys>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi
new file mode 100644
index 000000000000..b1c9bd0e63ef
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dtsi
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * FriendlyElec NanoPC-R4 board device tree source
+ *
+ * Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * Copyright (c) 2018 Collabora Ltd.
+ *
+ * Copyright (c) 2020 Jensen Huang <jensenhuang@friendlyarm.com>
+ * Copyright (c) 2020 Marty Jones <mj8263788@gmail.com>
+ * Copyright (c) 2021 Tianling Shen <cnsztl@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "rk3399-nanopi4.dtsi"
+
+/ {
+ /delete-node/ display-subsystem;
+
+ gpio-leds {
+ pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>;
+
+ /delete-node/ led-0;
+
+ lan_led: led-lan {
+ gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
+ label = "green:lan";
+ };
+
+ sys_led: led-sys {
+ gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
+ label = "red:power";
+ default-state = "on";
+ };
+
+ wan_led: led-wan {
+ gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
+ label = "green:wan";
+ };
+ };
+
+ gpio-keys {
+ pinctrl-0 = <&reset_button_pin>;
+
+ /delete-node/ key-power;
+
+ key-reset {
+ debounce-interval = <50>;
+ gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>;
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ };
+ };
+
+ vdd_5v: regulator-vdd-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_5v";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&emmc_phy {
+ status = "disabled";
+};
+
+&i2c4 {
+ status = "disabled";
+};
+
+&pcie0 {
+ max-link-speed = <1>;
+ num-lanes = <1>;
+ vpcie3v3-supply = <&vcc3v3_sys>;
+};
+
+&pinctrl {
+ gpio-leds {
+ /delete-node/ status-led-pin;
+
+ lan_led_pin: lan-led-pin {
+ rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ sys_led_pin: sys-led-pin {
+ rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wan_led_pin: wan-led-pin {
+ rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ rockchip-key {
+ /delete-node/ power-key;
+
+ reset_button_pin: reset-button-pin {
+ rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&sdhci {
+ status = "disabled";
+};
+
+&sdio0 {
+ status = "disabled";
+};
+
+&u2phy0_host {
+ phy-supply = <&vdd_5v>;
+};
+
+&u2phy1_host {
+ status = "disabled";
+};
+
+&uart0 {
+ status = "disabled";
+};
+
+&usbdrd_dwc3_0 {
+ dr_mode = "host";
+};
+
+&vcc3v3_sys {
+ vin-supply = <&vcc5v0_sys>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
index 7debc4a1b5fa..b169be06d4d1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
@@ -34,7 +34,7 @@
#clock-cells = <0>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -43,7 +43,7 @@
regulator-name = "vcc3v3_sys";
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -54,7 +54,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -64,7 +64,7 @@
vin-supply = <&vcc_1v8>;
};
- vcc3v0_sd: vcc3v0-sd {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
@@ -81,7 +81,7 @@
* Really, this is supplied by vcc_1v8, and vcc1v8_s3 only
* drives the enable pin, but we can't quite model that.
*/
- vcca0v9_s3: vcca0v9-s3 {
+ vcca0v9_s3: regulator-vcca0v9-s3 {
compatible = "regulator-fixed";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <900000>;
@@ -90,7 +90,7 @@
};
/* As above, actually supplied by vcc3v3_sys */
- vcca1v8_s3: vcca1v8-s3 {
+ vcca1v8_s3: regulator-vcca1v8-s3 {
compatible = "regulator-fixed";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -98,7 +98,7 @@
vin-supply = <&vcc1v8_s3>;
};
- vbus_typec: vbus-typec {
+ vbus_typec: regulator-vbus-typec {
compatible = "regulator-fixed";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
@@ -269,7 +269,7 @@
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>, <&ap_pwroff>, <&clk_32k>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-op1.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-op1.dtsi
index b24bff511513..c4f4f1ff6117 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-op1.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-op1.dtsi
@@ -12,32 +12,32 @@
opp00 {
opp-hz = /bits/ 64 <408000000>;
- opp-microvolt = <800000>;
+ opp-microvolt = <800000 800000 1150000>;
clock-latency-ns = <40000>;
};
opp01 {
opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <825000>;
+ opp-microvolt = <825000 825000 1150000>;
};
opp02 {
opp-hz = /bits/ 64 <816000000>;
- opp-microvolt = <850000>;
+ opp-microvolt = <850000 850000 1150000>;
};
opp03 {
opp-hz = /bits/ 64 <1008000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1150000>;
};
opp04 {
opp-hz = /bits/ 64 <1200000000>;
- opp-microvolt = <975000>;
+ opp-microvolt = <975000 975000 1150000>;
};
opp05 {
opp-hz = /bits/ 64 <1416000000>;
- opp-microvolt = <1100000>;
+ opp-microvolt = <1100000 1100000 1150000>;
};
opp06 {
opp-hz = /bits/ 64 <1512000000>;
- opp-microvolt = <1150000>;
+ opp-microvolt = <1150000 1150000 1150000>;
};
};
@@ -47,40 +47,40 @@
opp00 {
opp-hz = /bits/ 64 <408000000>;
- opp-microvolt = <800000>;
+ opp-microvolt = <800000 800000 1250000>;
clock-latency-ns = <40000>;
};
opp01 {
opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <800000>;
+ opp-microvolt = <800000 800000 1250000>;
};
opp02 {
opp-hz = /bits/ 64 <816000000>;
- opp-microvolt = <825000>;
+ opp-microvolt = <825000 825000 1250000>;
};
opp03 {
opp-hz = /bits/ 64 <1008000000>;
- opp-microvolt = <850000>;
+ opp-microvolt = <850000 850000 1250000>;
};
opp04 {
opp-hz = /bits/ 64 <1200000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1250000>;
};
opp05 {
opp-hz = /bits/ 64 <1416000000>;
- opp-microvolt = <975000>;
+ opp-microvolt = <975000 975000 1250000>;
};
opp06 {
opp-hz = /bits/ 64 <1608000000>;
- opp-microvolt = <1050000>;
+ opp-microvolt = <1050000 1050000 1250000>;
};
opp07 {
opp-hz = /bits/ 64 <1800000000>;
- opp-microvolt = <1150000>;
+ opp-microvolt = <1150000 1150000 1250000>;
};
opp08 {
opp-hz = /bits/ 64 <2016000000>;
- opp-microvolt = <1250000>;
+ opp-microvolt = <1250000 1250000 1250000>;
};
};
@@ -89,27 +89,27 @@
opp00 {
opp-hz = /bits/ 64 <200000000>;
- opp-microvolt = <800000>;
+ opp-microvolt = <800000 800000 1075000>;
};
opp01 {
opp-hz = /bits/ 64 <297000000>;
- opp-microvolt = <800000>;
+ opp-microvolt = <800000 800000 1075000>;
};
opp02 {
opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <825000>;
+ opp-microvolt = <825000 825000 1075000>;
};
opp03 {
opp-hz = /bits/ 64 <500000000>;
- opp-microvolt = <850000>;
+ opp-microvolt = <850000 850000 1075000>;
};
opp04 {
opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <925000>;
+ opp-microvolt = <925000 925000 1075000>;
};
opp05 {
opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = <1075000>;
+ opp-microvolt = <1075000 1075000 1075000>;
};
};
@@ -118,19 +118,19 @@
opp00 {
opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 925000>;
};
opp01 {
opp-hz = /bits/ 64 <666000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 925000>;
};
opp02 {
opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 925000>;
};
opp03 {
opp-hz = /bits/ 64 <928000000>;
- opp-microvolt = <925000>;
+ opp-microvolt = <925000 925000 925000>;
};
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts
index 07ec33f3f55f..2ddd4da15597 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts
@@ -65,7 +65,7 @@
};
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -100,7 +100,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s3";
regulator-always-on;
@@ -110,7 +110,7 @@
vin-supply = <&vcc_1v8>;
};
- vcc3v0_sd: vcc3v0-sd {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
@@ -123,7 +123,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -133,7 +133,7 @@
vin-supply = <&vcc_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
@@ -144,7 +144,7 @@
vin-supply = <&vcc_sys>;
};
- vbus_typec: vbus-typec-regulator {
+ vbus_typec: regulator-vbus-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -154,7 +154,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -164,7 +164,7 @@
vin-supply = <&dc_12v>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc_sys>;
@@ -262,7 +262,7 @@
clock-output-names = "rtc_clko_soc", "rtc_clko_wifi";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
index a5a7e374bc59..5473070823cb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
@@ -150,7 +150,7 @@
"Speaker", "Speaker Amplifier OUTL",
"Speaker", "Speaker Amplifier OUTR";
- simple-audio-card,hp-det-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,hp-det-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
simple-audio-card,aux-devs = <&speaker_amp>;
simple-audio-card,pin-switches = "Speaker";
@@ -172,7 +172,7 @@
/* Power tree */
/* Root power source */
- vcc_sysin: vcc-sysin {
+ vcc_sysin: regulator-vcc-sysin {
compatible = "regulator-fixed";
regulator-name = "vcc_sysin";
regulator-always-on;
@@ -181,7 +181,7 @@
/* Regulators supplied by vcc_sysin */
/* LCD backlight supply */
- vcc_12v: vcc-12v {
+ vcc_12v: regulator-vcc-12v {
compatible = "regulator-fixed";
regulator-name = "vcc_12v";
regulator-always-on;
@@ -196,7 +196,7 @@
};
/* Main 3.3 V supply */
- vcc3v3_sys: wifi_bat: vcc3v3-sys {
+ vcc3v3_sys: wifi_bat: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -211,7 +211,7 @@
};
/* 5 V USB power supply */
- vcc5v0_usb: pa_5v: vcc5v0-usb-regulator {
+ vcc5v0_usb: pa_5v: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
@@ -229,7 +229,7 @@
};
/* RK3399 logic supply */
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc_sysin>;
@@ -246,7 +246,7 @@
/* Regulators supplied by vcc3v3_sys */
/* 0.9 V supply, always on */
- vcc_0v9: vcc-0v9 {
+ vcc_0v9: regulator-vcc-0v9 {
compatible = "regulator-fixed";
regulator-name = "vcc_0v9";
regulator-always-on;
@@ -257,7 +257,7 @@
};
/* S3 1.8 V supply, switched by vcc1v8_s3 */
- vcca1v8_s3: vcc1v8-s3 {
+ vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcca1v8_s3";
regulator-always-on;
@@ -268,7 +268,7 @@
};
/* micro SD card power */
- vcc3v0_sd: vcc3v0-sd {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
@@ -286,7 +286,7 @@
};
/* LCD panel power, called VCC3V3_S0 in schematic */
- vcc3v3_panel: vcc3v3-panel {
+ vcc3v3_panel: regulator-vcc3v3-panel {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>;
@@ -305,7 +305,7 @@
};
/* M.2 adapter power, switched by vcc1v8_s3 */
- vcc3v3_ssd: vcc3v3-ssd {
+ vcc3v3_ssd: regulator-vcc3v3-ssd {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_ssd";
regulator-min-microvolt = <3300000>;
@@ -315,7 +315,7 @@
/* Regulators supplied by vcc5v0_usb */
/* USB 3 port power supply regulator */
- vcc5v0_otg: vcc5v0-otg {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>;
@@ -334,7 +334,7 @@
/* Regulators supplied by vcc5v0_usb */
/* Type C port power supply regulator */
- vbus_5vout: vbus_typec: vbus-5vout {
+ vbus_5vout: vbus_typec: regulator-vbus-5vout {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -352,7 +352,7 @@
/* Regulators supplied by vcc_1v8 */
/* Primary 0.9 V LDO */
- vcca0v9_s3: vcca0v9-s3 {
+ vcca0v9_s3: regulator-vcca0v9-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc0v9_s3";
regulator-min-microvolt = <5000000>;
@@ -447,7 +447,7 @@
interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l_pin>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sysin>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 1a44582a49fb..04ba4c4565d0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -13,7 +13,7 @@
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/leds/common.h>
-#include "rk3399.dtsi"
+#include "rk3399-s.dtsi"
/ {
model = "Pine64 PinePhone Pro";
@@ -97,14 +97,14 @@
leds = <&led_red>, <&led_green>, <&led_blue>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
regulator-boot-on;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -114,7 +114,7 @@
vin-supply = <&vcc_sys>;
};
- vcca1v8_s3: vcc1v8-s3-regulator {
+ vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcca1v8_s3";
regulator-min-microvolt = <1800000>;
@@ -124,7 +124,7 @@
regulator-boot-on;
};
- vcc1v8_codec: vcc1v8-codec-regulator {
+ vcc1v8_codec: regulator-vcc1v8-codec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>;
@@ -158,7 +158,7 @@
};
/* MIPI DSI panel 1.8v supply */
- vcc1v8_lcd: vcc1v8-lcd {
+ vcc1v8_lcd: regulator-vcc1v8-lcd {
compatible = "regulator-fixed";
enable-active-high;
regulator-name = "vcc1v8_lcd";
@@ -166,11 +166,10 @@
regulator-max-microvolt = <1800000>;
vin-supply = <&vcc3v3_sys>;
gpio = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
};
/* MIPI DSI panel 2.8v supply */
- vcc2v8_lcd: vcc2v8-lcd {
+ vcc2v8_lcd: regulator-vcc2v8-lcd {
compatible = "regulator-fixed";
enable-active-high;
regulator-name = "vcc2v8_lcd";
@@ -178,7 +177,6 @@
regulator-max-microvolt = <2800000>;
vin-supply = <&vcc3v3_sys>;
gpio = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
};
vibrator {
@@ -243,7 +241,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sys>;
@@ -456,27 +454,6 @@
};
};
-&cluster0_opp {
- opp04 {
- status = "disabled";
- };
-
- opp05 {
- status = "disabled";
- };
-};
-
-&cluster1_opp {
- opp06 {
- opp-hz = /bits/ 64 <1500000000>;
- opp-microvolt = <1100000 1100000 1150000>;
- };
-
- opp07 {
- status = "disabled";
- };
-};
-
&io_domains {
bt656-supply = <&vcc1v8_dvp>;
audio-supply = <&vcca1v8_codec>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
index f6f15946579e..947bbd62a6b0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
@@ -30,6 +30,12 @@
linux,code = <KEY_BATTERY>;
};
+ button-pwrbtn-n {
+ gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_LOW>;
+ label = "PWRBTN#";
+ linux,code = <KEY_POWER>;
+ };
+
button-slp-btn-n {
gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_LOW>;
label = "SLP_BTN#";
@@ -85,7 +91,7 @@
clock-frequency = <24576000>;
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -94,7 +100,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_baseboard: vcc3v3-baseboard {
+ vcc3v3_baseboard: regulator-vcc3v3-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_baseboard";
regulator-always-on;
@@ -104,7 +110,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_baseboard: vcc5v0-baseboard {
+ vcc5v0_baseboard: regulator-vcc5v0-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_baseboard";
regulator-always-on;
@@ -114,7 +120,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_otg: vcc5v0-otg-regulator {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
@@ -124,7 +130,7 @@
regulator-always-on;
};
- vdda_codec: vdda-codec {
+ vdda_codec: regulator-vdda-codec {
compatible = "regulator-fixed";
regulator-name = "vdda_codec";
regulator-boot-on;
@@ -133,7 +139,7 @@
vin-supply = <&vcc5v0_baseboard>;
};
- vddd_codec: vddd-codec {
+ vddd_codec: regulator-vddd-codec {
compatible = "regulator-fixed";
regulator-name = "vddd_codec";
regulator-boot-on;
@@ -203,6 +209,8 @@
buttons {
haikou_keys_pin: haikou-keys-pin {
rockchip,pins =
+ /* PWRBTN# */
+ <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>,
/* LID_BTN */
<0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
/* BATLOW# */
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
index 650b1ba9c192..d12e661dfd99 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
@@ -9,6 +9,7 @@
/ {
aliases {
ethernet0 = &gmac;
+ i2c10 = &i2c10;
mmc0 = &sdhci;
};
@@ -39,7 +40,7 @@
#clock-cells = <0>;
};
- vcc1v2_phy: vcc1v2-phy {
+ vcc1v2_phy: regulator-vcc1v2-phy {
compatible = "regulator-fixed";
regulator-name = "vcc1v2_phy";
regulator-always-on;
@@ -49,7 +50,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -59,7 +60,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -69,7 +70,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -78,7 +79,7 @@
regulator-max-microvolt = <5000000>;
};
- vcca_0v9: vcca-0v9-regulator {
+ vcca_0v9: regulator-vcca-0v9 {
compatible = "regulator-fixed";
regulator-name = "vcca_0v9";
regulator-always-on;
@@ -88,7 +89,7 @@
vin-supply = <&vcc_1v8>;
};
- vcca_1v8: vcca-1v8-regulator {
+ vcca_1v8: regulator-vcca-1v8 {
compatible = "regulator-fixed";
regulator-name = "vcca_1v8";
regulator-always-on;
@@ -98,7 +99,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc5v0_sys>;
@@ -205,7 +206,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc5v0_sys>;
@@ -393,14 +394,25 @@
clock-frequency = <400000>;
fan: fan@18 {
- compatible = "ti,amc6821";
+ compatible = "tsd,mule", "ti,amc6821";
reg = <0x18>;
- #cooling-cells = <2>;
- };
- rtc_twi: rtc@6f {
- compatible = "isil,isl1208";
- reg = <0x6f>;
+ i2c-mux {
+ compatible = "tsd,mule-i2c-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c10: i2c@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc_twi: rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-mezzanine.dts b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-mezzanine.dts
index 9447c8724b65..ce057e2db242 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-mezzanine.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-mezzanine.dts
@@ -16,7 +16,7 @@
};
/* MP8009 PoE PD */
- poe_12v: poe-12v {
+ poe_12v: regulator-poe-12v {
compatible = "regulator-fixed";
regulator-name = "poe_12v";
regulator-always-on;
@@ -25,7 +25,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_ngff: vcc3v3-ngff {
+ vcc3v3_ngff: regulator-vcc3v3-ngff {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_ngff";
enable-active-high;
@@ -39,7 +39,7 @@
vin-supply = <&sys_12v>;
};
- vcc3v3_pcie: vcc3v3-pcie {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
enable-active-high;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts
index 7ba1c28f70a9..e2e9279fa267 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts
@@ -26,7 +26,7 @@
model = "Firefly ROC-RK3399-PC-PLUS Board";
compatible = "firefly,roc-rk3399-pc-plus", "rockchip,rk3399";
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -51,7 +51,7 @@
"Headphone Amp INR", "ROUT2",
"Headphones", "Headphone Amp OUTL",
"Headphones", "Headphone Amp OUTR";
- simple-audio-card,hp-det-gpio = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,hp-det-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
simple-audio-card,aux-devs = <&headphones_amp>;
simple-audio-card,pin-switches = "Headphones";
@@ -114,7 +114,6 @@
es8388: es8388@11 {
compatible = "everest,es8388";
reg = <0x11>;
- clock-names = "mclk";
clocks = <&cru SCLK_I2S_8CH_OUT>;
#sound-dai-cells = <0>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi
index d95b1cde1fc3..0393da25cdfb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi
@@ -113,7 +113,7 @@
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
};
- vcc_vbus_typec0: vcc-vbus-typec0 {
+ vcc_vbus_typec0: regulator-vcc-vbus-typec0 {
compatible = "regulator-fixed";
regulator-name = "vcc_vbus_typec0";
regulator-always-on;
@@ -122,7 +122,7 @@
regulator-max-microvolt = <5000000>;
};
- sys_12v: sys-12v {
+ sys_12v: regulator-sys-12v {
compatible = "regulator-fixed";
regulator-name = "sys_12v";
regulator-always-on;
@@ -131,7 +131,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s3";
regulator-always-on;
@@ -141,7 +141,7 @@
vin-supply = <&vcc_1v8>;
};
- vcc3v0_sd: vcc3v0-sd {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD6 GPIO_ACTIVE_HIGH>;
@@ -154,7 +154,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -164,7 +164,7 @@
vin-supply = <&sys_12v>;
};
- vcca_0v9: vcca-0v9 {
+ vcca_0v9: regulator-vcca-0v9 {
compatible = "regulator-fixed";
regulator-name = "vcca_0v9";
regulator-always-on;
@@ -175,7 +175,7 @@
};
/* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
@@ -185,7 +185,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_vbus_typec1: vcc-vbus-typec1 {
+ vcc_vbus_typec1: regulator-vcc-vbus-typec1 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
@@ -196,7 +196,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -209,7 +209,7 @@
vin-supply = <&sys_12v>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
regulator-name = "vdd_log";
@@ -298,7 +298,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc3v3_sys>;
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 475d57f64d58..15da5c80d25d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts
@@ -76,7 +76,7 @@
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
};
- vcc_3v3: vcc-3v3-regulator {
+ vcc_3v3: regulator-vcc-3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc_3v3";
regulator-always-on;
@@ -86,7 +86,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_phy1: vcc3v3-phy1-regulator {
+ vcc3v3_phy1: regulator-vcc3v3-phy1 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_phy1";
regulator-always-on;
@@ -96,7 +96,7 @@
vin-supply = <&vcc_3v3>;
};
- vcc5v0_host1: vcc5v0-host-regulator {
+ vcc5v0_host1: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>;
@@ -108,7 +108,7 @@
vin-supply = <&vcc5v0_host0_s0>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -117,7 +117,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc5v0_typec: vcc5v0-typec-regulator {
+ vcc5v0_typec: regulator-vcc5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -129,7 +129,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vdd_log: vdd-log-regulator {
+ vdd_log: regulator-vdd-log {
compatible = "regulator-fixed";
regulator-name = "vdd_log";
regulator-always-on;
@@ -220,7 +220,7 @@
clock-output-names = "rk808-clkout1", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>, <&i2s_8ch_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
wakeup-source;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
index 9666504cd1c1..541dca12bf1a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi
@@ -72,7 +72,7 @@
};
};
- vbus_typec: vbus-typec-regulator {
+ vbus_typec: regulator-vbus-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -83,7 +83,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc12v_dcin: dc-12v {
+ vcc12v_dcin: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -92,7 +92,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_lan: vcc3v3-lan-regulator {
+ vcc3v3_lan: regulator-vcc3v3-lan {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_lan";
regulator-always-on;
@@ -102,7 +102,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
@@ -114,7 +114,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -124,7 +124,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
@@ -135,7 +135,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc-sys {
+ vcc5v0_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -145,7 +145,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc_0v9: vcc-0v9 {
+ vcc_0v9: regulator-vcc-0v9 {
compatible = "regulator-fixed";
regulator-name = "vcc_0v9";
regulator-always-on;
@@ -155,7 +155,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc5v0_sys>;
@@ -245,7 +245,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc5v0_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts
index 725ac3c1f6f6..4fc9c13dbec1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts
@@ -21,5 +21,5 @@
};
&sound {
- hp-det-gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
+ hp-det-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts
index 682e8b7297c1..9c741d1a3047 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts
@@ -39,7 +39,7 @@
};
&sound {
- hp-det-gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
+ hp-det-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
};
&uart0 {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts
index 82ad2ca6b5c2..5dc5505b58e2 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts
@@ -40,7 +40,7 @@
};
&sound {
- hp-det-gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
+ hp-det-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
};
&spi1 {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
index 8146f870d2bd..7b1086682d11 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
@@ -24,7 +24,7 @@
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
};
- vcc12v_dcin: vcc12v-dcin {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-min-microvolt = <12000000>;
@@ -33,7 +33,7 @@
regulator-boot-on;
};
- vcc1v8_s0: vcc1v8-s0 {
+ vcc1v8_s0: regulator-vcc1v8-s0 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s0";
regulator-min-microvolt = <1800000>;
@@ -41,7 +41,7 @@
regulator-always-on;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-min-microvolt = <5000000>;
@@ -50,7 +50,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-min-microvolt = <3300000>;
@@ -59,7 +59,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
enable-active-high;
pinctrl-names = "default";
@@ -71,7 +71,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
pinctrl-names = "default";
@@ -83,7 +83,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_0v9: vcc-0v9 {
+ vcc_0v9: regulator-vcc-0v9 {
compatible = "regulator-fixed";
regulator-name = "vcc_0v9";
regulator-always-on;
@@ -186,7 +186,7 @@
interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <1>;
clock-output-names = "xin32k", "rk808-clkout2";
@@ -576,7 +576,7 @@
bluetooth {
compatible = "brcm,bcm43438-bt";
clocks = <&rk808 1>;
- clock-names = "ext_clock";
+ clock-names = "txco";
device-wakeup-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>;
host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
index 11d99d8b34a2..69a9d6170649 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
@@ -116,7 +116,7 @@
};
};
- avdd: avdd-regulator {
+ avdd: regulator-avdd {
compatible = "regulator-fixed";
regulator-name = "avdd";
regulator-min-microvolt = <11000000>;
@@ -124,7 +124,7 @@
vin-supply = <&vcc3v3_s0>;
};
- vcc12v_dcin: vcc12v-dcin {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -134,7 +134,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s3";
regulator-always-on;
@@ -145,7 +145,7 @@
};
/* micro SD card power */
- vcc3v0_sd: vcc3v0-sd {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
@@ -162,7 +162,7 @@
};
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
@@ -174,7 +174,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -185,7 +185,7 @@
};
/* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>;
@@ -196,7 +196,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_typec: vcc5v0-typec-regulator {
+ vcc5v0_typec: regulator-vcc5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -207,7 +207,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -217,7 +217,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb: vcc5v0-usb {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -227,7 +227,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc5v0_sys>;
@@ -342,7 +342,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc5v0_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-s.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-s.dtsi
new file mode 100644
index 000000000000..e54f451af9f3
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3399-s.dtsi
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd
+ */
+
+#include "rk3399-base.dtsi"
+
+/ {
+ cluster0_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <825000 825000 1250000>;
+ clock-latency-ns = <40000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <825000 825000 1250000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <850000 850000 1250000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <925000 925000 1250000>;
+ };
+ };
+
+ cluster1_opp: opp-table-1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <825000 825000 1250000>;
+ clock-latency-ns = <40000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <825000 825000 1250000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <825000 825000 1250000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <875000 875000 1250000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <950000 950000 1250000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <1025000 1025000 1250000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ };
+ };
+
+ gpu_opp_table: opp-table-2 {
+ compatible = "operating-points-v2";
+
+ opp00 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <825000 825000 1150000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <297000000>;
+ opp-microvolt = <825000 825000 1150000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <825000 825000 1150000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <875000 875000 1150000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <925000 925000 1150000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ };
+ };
+};
+
+&cpu_l0 {
+ operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_l1 {
+ operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_l2 {
+ operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_l3 {
+ operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_b0 {
+ operating-points-v2 = <&cluster1_opp>;
+};
+
+&cpu_b1 {
+ operating-points-v2 = <&cluster1_opp>;
+};
+
+&gpu {
+ operating-points-v2 = <&gpu_opp_table>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
index dbec2b7173a0..fdaa8472b7a7 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
@@ -163,11 +163,11 @@
status = "okay";
rt5651: rt5651@1a {
- compatible = "rockchip,rt5651";
+ compatible = "realtek,rt5651";
reg = <0x1a>;
clocks = <&cru SCLK_I2S_8CH_OUT>;
clock-names = "mclk";
- hp-det-gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>;
+ hp-det-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>;
spk-con-gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
#sound-dai-cells = <0>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
index 31832aae9ab6..e5c4addb4837 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
@@ -27,7 +27,7 @@
#clock-cells = <0>;
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -66,7 +66,7 @@
};
/* switched by pmic_sleep */
- vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+ vcc1v8_s3: vcca1v8_s3: regulator-vcc1v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_s3";
regulator-always-on;
@@ -76,7 +76,7 @@
vin-supply = <&vcc_1v8>;
};
- vcc3v0_sd: vcc3v0-sd {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
@@ -89,7 +89,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -99,7 +99,7 @@
vin-supply = <&vcc_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
@@ -110,7 +110,7 @@
vin-supply = <&vcc_sys>;
};
- vcc5v0_typec0: vcc5v0-typec0-regulator {
+ vcc5v0_typec0: regulator-vcc5v0-typec0 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>;
@@ -120,7 +120,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -130,7 +130,7 @@
vin-supply = <&dc_12v>;
};
- vdd_log: vdd-log {
+ vdd_log: regulator-vdd-log {
compatible = "pwm-regulator";
pwms = <&pwm2 0 25000 1>;
pwm-supply = <&vcc_sys>;
@@ -233,7 +233,7 @@
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi
index 8823c924dc1d..64e6ba345739 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi
@@ -18,7 +18,7 @@
mmc1 = &sdmmc;
};
- vcc3v3_pcie: vcc-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc-pcie {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>;
@@ -78,7 +78,7 @@
clock-output-names = "rk808-clkout1", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc5v0_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
new file mode 100644
index 000000000000..d2cdb63d4a9d
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd
+ * Copyright (c) 2024 Radxa Limited
+ * Copyright (c) 2024 Yao Zi <ziyao@disroot.org>
+ */
+
+/dts-v1/;
+#include "rk3528.dtsi"
+
+/ {
+ model = "Radxa E20C";
+ compatible = "radxa,e20c", "rockchip,rk3528";
+
+ chosen {
+ stdout-path = "serial0:1500000n8";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
new file mode 100644
index 000000000000..e58faa985aa4
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2024 Yao Zi <ziyao@disroot.org>
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ compatible = "rockchip,rk3528";
+
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &uart5;
+ serial6 = &uart6;
+ serial7 = &uart7;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ core2 {
+ cpu = <&cpu2>;
+ };
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a53";
+ reg = <0x0>;
+ device_type = "cpu";
+ enable-method = "psci";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a53";
+ reg = <0x1>;
+ device_type = "cpu";
+ enable-method = "psci";
+ };
+
+ cpu2: cpu@2 {
+ compatible = "arm,cortex-a53";
+ reg = <0x2>;
+ device_type = "cpu";
+ enable-method = "psci";
+ };
+
+ cpu3: cpu@3 {
+ compatible = "arm,cortex-a53";
+ reg = <0x3>;
+ device_type = "cpu";
+ enable-method = "psci";
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ xin24m: clock-xin24m {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ #clock-cells = <0>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ ranges = <0x0 0xfe000000 0x0 0xfe000000 0x0 0x2000000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ gic: interrupt-controller@fed01000 {
+ compatible = "arm,gic-400";
+ reg = <0x0 0xfed01000 0 0x1000>,
+ <0x0 0xfed02000 0 0x2000>,
+ <0x0 0xfed04000 0 0x2000>,
+ <0x0 0xfed06000 0 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) |
+ IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <3>;
+ };
+
+ uart0: serial@ff9f0000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xff9f0000 0x0 0x100>;
+ clock-frequency = <24000000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart1: serial@ff9f8000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xff9f8000 0x0 0x100>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart2: serial@ffa00000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xffa00000 0x0 0x100>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart3: serial@ffa08000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xffa08000 0x0 0x100>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart4: serial@ffa10000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xffa10000 0x0 0x100>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart5: serial@ffa18000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xffa18000 0x0 0x100>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart6: serial@ffa20000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xffa20000 0x0 0x100>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+
+ uart7: serial@ffa28000 {
+ compatible = "rockchip,rk3528-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xffa28000 0x0 0x100>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg-arc.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg-arc.dtsi
index a4a60e4a53d4..0aa2694552ae 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg-arc.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg-arc.dtsi
@@ -41,7 +41,7 @@
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,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts
index a73cf30801ec..b80b6b593ce4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts
@@ -43,7 +43,7 @@
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,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
@@ -92,7 +92,7 @@
};
&i2c2 {
- pintctrl-names = "default";
+ pinctrl-names = "default";
pinctrl-0 = <&i2c2m1_xfer>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts
index ca5284e4807d..4fb712fe918c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts
@@ -42,7 +42,7 @@
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,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts
index e9954a33e8cd..01588bebf9cc 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts
@@ -42,7 +42,7 @@
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,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
@@ -79,7 +79,7 @@
};
&i2c2 {
- pintctrl-names = "default";
+ pinctrl-names = "default";
pinctrl-0 = <&i2c2m1_xfer>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts
index 90da43855d1c..5a30e3918c04 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts
@@ -41,7 +41,7 @@
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,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts
index 74cf313e0635..4dcc0ea4cf0f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts
@@ -132,7 +132,7 @@
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,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-base.dtsi
new file mode 100644
index 000000000000..e56e0b6ba941
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-base.dtsi
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+#include "rk356x-base.dtsi"
+
+/ {
+ compatible = "rockchip,rk3566";
+};
+
+&pipegrf {
+ compatible = "rockchip,rk3566-pipe-grf", "syscon";
+};
+
+&power {
+ power-domain@RK3568_PD_PIPE {
+ reg = <RK3568_PD_PIPE>;
+ clocks = <&cru PCLK_PIPE>;
+ pm_qos = <&qos_pcie2x1>,
+ <&qos_sata1>,
+ <&qos_sata2>,
+ <&qos_usb3_0>,
+ <&qos_usb3_1>;
+ #power-domain-cells = <0>;
+ };
+};
+
+&usb_host0_xhci {
+ phys = <&usb2phy0_otg>;
+ phy-names = "usb2-phy";
+ extcon = <&usb2phy0>;
+ maximum-speed = "high-speed";
+};
+
+&vop {
+ compatible = "rockchip,rk3566-vop";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
index 0c18406e4c59..7d4680933823 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
@@ -449,9 +449,9 @@
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>;
+ clock-names = "txco";
+ device-wakeup-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>;
+ host-wakeup-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>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts b/arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts
index 7cd91f8000cb..ed65d3120444 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts
@@ -245,7 +245,7 @@
interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
wakeup-source;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts b/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts
index c1194d1e438d..61dd71c259aa 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts
@@ -52,7 +52,7 @@
};
};
- usb_5v: usb-5v-regulator {
+ usb_5v: regulator-usb-5v {
compatible = "regulator-fixed";
regulator-name = "usb_5v";
regulator-always-on;
@@ -61,7 +61,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -71,7 +71,7 @@
vin-supply = <&usb_5v>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -81,7 +81,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;
@@ -92,7 +92,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb20_host: vcc5v0-usb20-host-regulator {
+ vcc5v0_usb20_host: regulator-vcc5v0-usb20-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -102,7 +102,7 @@
regulator-always-on;
};
- vcc5v0_usb30_host: vcc5v0-usb30-host-regulator {
+ vcc5v0_usb30_host: regulator-vcc5v0-usb30-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
@@ -197,7 +197,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <1>;
@@ -507,7 +507,6 @@
non-removable;
pinctrl-names = "default";
pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>;
- supports-emmc;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts b/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts
new file mode 100644
index 000000000000..fb1f65c86883
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-nanopi-r3s.dts
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
+ *
+ * Copyright (c) 2024 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyelec.com)
+ *
+ * Copyright (c) 2024 Tianling Shen <cnsztl@gmail.com>
+ */
+
+/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 <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3566.dtsi"
+
+/ {
+ model = "FriendlyElec NanoPi R3S";
+ compatible = "friendlyarm,nanopi-r3s", "rockchip,rk3566";
+
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc0;
+ };
+
+ chosen: chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&reset_button_pin>;
+
+ button-reset {
+ label = "reset";
+ gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ debounce-interval = <50>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&power_led_pin>, <&lan_led_pin>, <&wan_led_pin>;
+
+ power_led: led-0 {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_POWER;
+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+
+ lan_led: led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_LAN;
+ gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
+ };
+
+ wan_led: led-2 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WAN;
+ gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ 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 = <&vcc5v0_sys>;
+ };
+
+ 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 = <&vdd_usbc>;
+ };
+
+ vcc5v0_usb: regulator-vcc5v0_usb {
+ 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";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vdd_usbc: regulator-vdd-usbc {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_usbc";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+&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>, <&cru CLK_MAC1_2TOP>;
+ assigned-clock-rates = <0>, <125000000>;
+ clock_in_out = "output";
+ phy-mode = "rgmii-id";
+ phy-handle = <&rgmii_phy1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m0_miim
+ &gmac1m0_tx_bus2_level3
+ &gmac1m0_rx_bus2
+ &gmac1m0_rgmii_clk_level2
+ &gmac1m0_rgmii_bus_level3>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ 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 = <&vcc5v0_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>;
+ #clock-cells = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int>;
+ system-power-controller;
+ 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-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-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-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-min-microvolt = <950000>;
+ regulator-max-microvolt = <950000>;
+
+ 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-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-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-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <RK_PC3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&eth_phy_reset_pin>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie2x1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_reset_h>;
+ reset-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&pinctrl {
+ gpio-leds {
+ lan_led_pin: lan-led-pin {
+ rockchip,pins = <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ power_led_pin: power-led-pin {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wan_led_pin: wan-led-pin {
+ rockchip,pins = <3 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ gmac {
+ eth_phy_reset_pin: eth-phy-reset-pin {
+ rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ pcie {
+ pcie_reset_h: pcie-reset-h {
+ rockchip,pins = <4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ pmic {
+ pmic_int: pmic-int {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ rockchip-key {
+ reset_button_pin: reset-button-pin {
+ rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ rtc {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ usb {
+ vcc5v0_usb_host_en: vcc5v0-usb-host-en {
+ rockchip,pins = <0 RK_PA6 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_3v3>;
+ vccio5-supply = <&vcc_1v8>;
+ vccio6-supply = <&vcc_3v3>;
+ vccio7-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ mmc-hs200-1_8v;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
+ status = "okay";
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ disable-wp;
+ no-sdio;
+ no-mmc;
+ 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";
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_host {
+ phy-supply = <&vcc5v0_usb>;
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ extcon = <&usb2phy0>;
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ 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";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
index ae2536c65a83..2d3ae1544822 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
@@ -129,7 +129,7 @@
};
};
- vbat_4g: vbat-4g {
+ vbat_4g: regulator-vbat-4g {
compatible = "regulator-fixed";
regulator-name = "vbat_4g";
regulator-min-microvolt = <3800000>;
@@ -138,7 +138,7 @@
vin-supply = <&vbat_4g_en>;
};
- vcc_1v8: vcc-1v8 {
+ vcc_1v8: regulator-vcc-1v8 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v8";
regulator-always-on;
@@ -148,7 +148,7 @@
vin-supply = <&vcc_1v8_en>;
};
- vcc_bat: vcc-bat {
+ vcc_bat: regulator-vcc-bat {
compatible = "regulator-fixed";
regulator-name = "vcc_bat";
regulator-always-on;
@@ -156,7 +156,7 @@
regulator-max-microvolt = <3800000>;
};
- vcc_hall_3v3: vcc-hall-3v3 {
+ vcc_hall_3v3: regulator-vcc-hall-3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc_hall_3v3";
regulator-always-on;
@@ -165,7 +165,7 @@
vin-supply = <&vcc_sys>;
};
- vcc_sys: vcc-sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -174,7 +174,7 @@
vin-supply = <&vcc_bat>;
};
- vcc_wl: vcc-wl {
+ vcc_wl: regulator-vcc-wl {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
@@ -186,7 +186,7 @@
vin-supply = <&vcc_bat>;
};
- vdda_0v9: vdda-0v9 {
+ vdda_0v9: regulator-vdda-0v9 {
compatible = "regulator-fixed";
regulator-name = "vdda_0v9";
regulator-always-on;
@@ -244,7 +244,7 @@
#clock-cells = <1>;
pinctrl-0 = <&i2s1m0_mclk>, <&pmic_int_l>, <&pmic_sleep>;
pinctrl-names = "default";
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
wakeup-source;
@@ -684,11 +684,11 @@
compatible = "brcm,bcm43438-bt";
clocks = <&rk817 1>;
clock-names = "lpo";
- device-wake-gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>;
- host-wake-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;
- reset-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>;
+ device-wakeup-gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&bt_enable_h>, <&bt_host_wake_l>, <&bt_wake_h>;
pinctrl-names = "default";
+ shutdown-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
vbat-supply = <&vcc_wl>;
vddio-supply = <&vcca_1v8_pmu>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-pinetab2.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-pinetab2.dtsi
index db40281eafbe..26cf765a7297 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-pinetab2.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-pinetab2.dtsi
@@ -121,7 +121,7 @@
"Internal Speakers", "Speaker Amplifier OUTR",
"Speaker Amplifier INL", "HPOL",
"Speaker Amplifier INR", "HPOR";
- simple-audio-card,hp-det-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_LOW>;
+ simple-audio-card,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_LOW>;
simple-audio-card,aux-devs = <&speaker_amp>;
simple-audio-card,pin-switches = "Internal Speakers";
@@ -143,7 +143,7 @@
VCC-supply = <&vcc_bat>;
};
- vcc_3v3: vcc-3v3-regulator {
+ vcc_3v3: regulator-vcc-3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc_3v3";
regulator-always-on;
@@ -153,7 +153,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_minipcie: vcc3v3-minipcie-regulator {
+ vcc3v3_minipcie: regulator-vcc3v3-minipcie {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>;
@@ -165,7 +165,7 @@
vin-supply = <&vcc_sys>;
};
- vcc3v3_sd: vcc3v3-sd-regulator {
+ vcc3v3_sd: regulator-vcc3v3-sd {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
@@ -176,7 +176,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc5v0_flashled: vcc5v0-flashled-regulator {
+ vcc5v0_flashled: regulator-vcc5v0-flashled {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -188,7 +188,7 @@
vin-supply = <&vcc5v_midu>;
};
- vcc5v0_usb_host0: vcc5v0-usb-host0-regulator {
+ vcc5v0_usb_host0: regulator-vcc5v0-usb-host0 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>;
@@ -200,7 +200,7 @@
vin-supply = <&vcc5v_midu>;
};
- vcc5v0_usb_host2: vcc5v0-usb-host2-regulator {
+ vcc5v0_usb_host2: regulator-vcc5v0-usb-host2 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -212,14 +212,14 @@
vin-supply = <&vcc5v_midu>;
};
- vcc_bat: vcc-bat-regulator {
+ vcc_bat: regulator-vcc-bat {
compatible = "regulator-fixed";
regulator-name = "vcc_bat";
regulator-always-on;
regulator-boot-on;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -227,7 +227,7 @@
vin-supply = <&vcc_bat>;
};
- vdd1v2_dvp: vdd1v2-dvp-regulator {
+ vdd1v2_dvp: regulator-vdd1v2-dvp {
compatible = "regulator-fixed";
regulator-name = "vdd1v2_dvp";
regulator-min-microvolt = <1200000>;
@@ -370,7 +370,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
wakeup-source;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb20sx.dts b/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb20sx.dts
new file mode 100644
index 000000000000..9b70026ce4a5
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-rgb20sx.dts
@@ -0,0 +1,89 @@
+// 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-powkiddy-rk2023.dtsi"
+
+/ {
+ model = "Powkiddy RGB20SX";
+ compatible = "powkiddy,rgb20sx", "rockchip,rk3566";
+
+ chosen: chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc_keys: adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 0>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <60>;
+
+ /*
+ * Button is labelled as FN, but according to input
+ * guidelines it should be mode.
+ */
+ button-mode {
+ label = "MODE";
+ linux,code = <BTN_MODE>;
+ press-threshold-microvolt = <1750>;
+ };
+ };
+};
+
+&battery {
+ charge-full-design-microamp-hours = <5000000>;
+};
+
+&bluetooth {
+ compatible = "realtek,rtl8723ds-bt";
+};
+
+&cru {
+ assigned-clocks = <&pmucru CLK_RTC_32K>, <&cru PLL_GPLL>,
+ <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
+ assigned-clock-rates = <32768>, <1200000000>,
+ <200000000>, <292500000>;
+};
+
+&dsi0 {
+ panel: panel@0 {
+ compatible = "powkiddy,rgb30-panel";
+ reg = <0>;
+ backlight = <&backlight>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_rst>;
+ reset-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vcc3v3_lcd0_n>;
+ iovcc-supply = <&vcc3v3_lcd0_n>;
+
+ port {
+ mipi_in_panel: endpoint {
+ remote-endpoint = <&mipi_out_panel>;
+ };
+ };
+ };
+};
+
+&i2c0 {
+ vdd_cpu: regulator@1c {
+ compatible = "tcs,tcs4525";
+ reg = <0x1c>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-min-microvolt = <712500>;
+ regulator-max-microvolt = <1390000>;
+ regulator-name = "vdd_cpu";
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc_sys>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-x55.dts b/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-x55.dts
index 5a648db41f35..e274f7bf9dfb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-x55.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-powkiddy-x55.dts
@@ -269,7 +269,7 @@
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,hp-det-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
index 37a1303d9a34..98e75df8b158 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
@@ -117,7 +117,7 @@
};
};
- vcc12v_dcin: vcc12v_dcin {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -130,7 +130,7 @@
* With no battery attached, also feeds vcc_bat+
* via ON/OFF_BAT jumper
*/
- vbus: vbus {
+ vbus: regulator-vbus {
compatible = "regulator-fixed";
regulator-name = "vbus";
regulator-always-on;
@@ -140,7 +140,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc3v3_pcie_p: vcc3v3-pcie-p-regulator {
+ vcc3v3_pcie_p: regulator-vcc3v3-pcie-p {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
@@ -152,7 +152,7 @@
vin-supply = <&vcc_3v3>;
};
- vcc5v0_usb: vcc5v0_usb {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -166,7 +166,7 @@
* the host ports are sourced from vcc5v0_usb
* the otg port is sourced from vcc5v0_midu
*/
- vcc5v0_usb20_host: vcc5v0_usb20_host {
+ vcc5v0_usb20_host: regulator-vcc5v0-usb20-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>;
@@ -178,7 +178,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb20_otg: vcc5v0_usb20_otg {
+ vcc5v0_usb20_otg: regulator-vcc5v0-usb20-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>;
@@ -188,7 +188,7 @@
vin-supply = <&dcdc_boost>;
};
- vcc3v3_sd: vcc3v3_sd {
+ vcc3v3_sd: regulator-vcc3v3-sd {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -201,7 +201,7 @@
};
/* sourced from vbus and vcc_bat+ via rk817 sw5 */
- vcc_sys: vcc_sys {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -212,7 +212,7 @@
};
/* sourced from vcc_sys, sdio module operates internally at 3.3v */
- vcc_wl: vcc_wl {
+ vcc_wl: regulator-vcc-wl {
compatible = "regulator-fixed";
regulator-name = "vcc_wl";
regulator-always-on;
@@ -347,7 +347,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
wakeup-source;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
index c164074ddf54..24928a129446 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
@@ -81,7 +81,7 @@
power-off-delay-us = <5000000>;
};
- vcc3v3_pcie_p: vcc3v3-pcie-p-regulator {
+ vcc3v3_pcie_p: regulator-vcc3v3-pcie-p {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -93,7 +93,7 @@
vin-supply = <&vcc_3v3>;
};
- vcc5v0_in: vcc5v0-in-regulator {
+ vcc5v0_in: regulator-vcc5v0-in {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_in";
regulator-always-on;
@@ -102,7 +102,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -112,7 +112,7 @@
vin-supply = <&vcc5v0_in>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-min-microvolt = <3300000>;
@@ -121,7 +121,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb30_host: vcc5v0-usb30-host-regulator {
+ vcc5v0_usb30_host: regulator-vcc5v0-usb30-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb30_host";
enable-active-high;
@@ -134,7 +134,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb_otg";
enable-active-high;
@@ -255,7 +255,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
wakeup-source;
#clock-cells = <1>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3-io.dts b/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3-io.dts
index 3ae24e39450a..b5b253f04cdf 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3-io.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3-io.dts
@@ -53,7 +53,7 @@
};
};
- vcc5v0_usb30: vcc5v0-usb30-regulator {
+ vcc5v0_usb30: regulator-vcc5v0-usb30 {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb30";
enable-active-high;
@@ -66,7 +66,7 @@
vin-supply = <&vcc_sys>;
};
- vcca1v8_image: vcca1v8-image-regulator {
+ vcca1v8_image: regulator-vcca1v8-image {
compatible = "regulator-fixed";
regulator-name = "vcca1v8_image";
regulator-always-on;
@@ -76,7 +76,7 @@
vin-supply = <&vcc_1v8_p>;
};
- vdda0v9_image: vdda0v9-image-regulator {
+ vdda0v9_image: regulator-vdda0v9-image {
compatible = "regulator-fixed";
regulator-name = "vcca0v9_image";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi
index 45de2630bb50..8453f06c261c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi
@@ -28,7 +28,7 @@
};
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -37,7 +37,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc_1v8: vcc-1v8-regulator {
+ vcc_1v8: regulator-vcc-1v8 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v8";
regulator-always-on;
@@ -47,7 +47,7 @@
vin-supply = <&vcc_1v8_p>;
};
- vcc_3v3: vcc-3v3-regulator {
+ vcc_3v3: regulator-vcc-3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc_3v3";
regulator-always-on;
@@ -57,7 +57,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcca_1v8: vcca-1v8-regulator {
+ vcca_1v8: regulator-vcca-1v8 {
compatible = "regulator-fixed";
regulator-name = "vcca_1v8";
regulator-always-on;
@@ -127,7 +127,7 @@
interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc_sys>;
@@ -402,9 +402,9 @@
clock-names = "lpo";
device-wakeup-gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_HIGH>;
host-wakeup-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_HIGH>;
- reset-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&bt_host_wake_h &bt_reg_on_h &bt_wake_host_h>;
+ shutdown-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>;
vbat-supply = <&vcc_3v3>;
vddio-supply = <&vcc_1v8>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi
index de390d92c35e..1ee5d96a46a1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi
@@ -3,7 +3,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/soc/rockchip,vop2.h>
-#include "rk3566.dtsi"
+#include "rk3566t.dtsi"
/ {
chosen {
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts b/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
index 67e7801bd489..7e499064e035 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
@@ -80,7 +80,7 @@
reset-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>;
};
- usb_5v: usb-5v-regulator {
+ usb_5v: regulator-usb-5v {
compatible = "regulator-fixed";
regulator-name = "usb_5v";
regulator-always-on;
@@ -89,7 +89,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -99,7 +99,7 @@
vin-supply = <&usb_5v>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
@@ -111,7 +111,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-min-microvolt = <3300000>;
@@ -120,7 +120,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb30_host: vcc5v0-usb30-host-regulator {
+ vcc5v0_usb30_host: regulator-vcc5v0-usb30-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb30_host";
enable-active-high;
@@ -133,7 +133,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb_otg";
enable-active-high;
@@ -253,7 +253,7 @@
clocks = <&cru I2S1_MCLKOUT_TX>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
#clock-cells = <1>;
#sound-dai-cells = <0>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts b/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
index f2cc086e5001..53e71528e4c4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-rock-3c.dts
@@ -5,7 +5,7 @@
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/soc/rockchip,vop2.h>
-#include "rk3566.dtsi"
+#include "rk3566t.dtsi"
/ {
model = "Radxa ROCK 3C";
@@ -64,7 +64,7 @@
reset-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_LOW>;
};
- vcc5v_dcin: vcc5v-dcin-regulator {
+ vcc5v_dcin: regulator-vcc5v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc5v_dcin";
regulator-always-on;
@@ -73,7 +73,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -85,7 +85,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -95,7 +95,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -105,7 +105,7 @@
vin-supply = <&vcc5v_dcin>;
};
- vcc5v0_usb30_host: vcc5v0-usb30-host-regulator {
+ vcc5v0_usb30_host: regulator-vcc5v0-usb30-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -117,7 +117,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
@@ -129,7 +129,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_cam: vcc-cam-regulator {
+ vcc_cam: regulator-vcc-cam {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
@@ -145,7 +145,7 @@
};
};
- vcc_mipi: vcc-mipi-regulator {
+ vcc_mipi: regulator-vcc-mipi {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
index fdbb4a6a19d8..b64d0c957ef6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
@@ -18,7 +18,7 @@
};
/* labeled VCC3V0_SD in schematic to not conflict with PMIC regulator */
- vcc3v0_sd: vcc3v0-sd-regulator {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
regulator-name = "vcc3v0_sd";
regulator-always-on;
@@ -29,7 +29,7 @@
};
/* labeled VCC_SSD in schematic */
- vcc3v3_pcie_p: vcc3v3-pcie-regulator {
+ vcc3v3_pcie_p: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie_p";
regulator-always-on;
@@ -39,7 +39,7 @@
vin-supply = <&vbus>;
};
- vcc5v_dcin: vcc5v-dcin-regulator {
+ vcc5v_dcin: regulator-vcc5v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc5v_dcin";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
index 2b6f0df477b6..38155316846d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
@@ -13,7 +13,7 @@
};
/* labeled +12v in schematic */
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -23,7 +23,7 @@
};
/* labeled +5v in schematic */
- vcc_5v: vcc-5v-regulator {
+ vcc_5v: regulator-vcc-5v {
compatible = "regulator-fixed";
regulator-name = "vcc_5v";
regulator-always-on;
@@ -33,7 +33,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc_sd_pwr: vcc-sd-pwr-regulator {
+ vcc_sd_pwr: regulator-vcc-sd-pwr {
compatible = "regulator-fixed";
regulator-name = "vcc_sd_pwr";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
index 9a6a63277c3d..2e130eef54df 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
@@ -13,7 +13,7 @@
};
/* labeled DCIN_12V in schematic */
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -22,7 +22,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -36,7 +36,7 @@
* Labelled VCC3V0_SD in schematic to not conflict with PMIC
* regulator, it's 3.3v in actuality
*/
- vcc3v0_sd: vcc3v0-sd-regulator {
+ vcc3v0_sd: regulator-vcc3v0-sd {
compatible = "regulator-fixed";
regulator-name = "vcc3v0_sd";
regulator-always-on;
@@ -46,7 +46,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-always-on;
@@ -56,7 +56,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc12v_pcie: vcc12v-pcie-regulator {
+ vcc12v_pcie: regulator-vcc12v-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc12v_pcie";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
index e42c474ef4ad..6b9aa0e1ad21 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
@@ -74,7 +74,7 @@
reset-gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_LOW>;
};
- vbus: vbus-regulator {
+ vbus: regulator-vbus {
compatible = "regulator-fixed";
regulator-name = "vbus";
regulator-always-on;
@@ -84,7 +84,7 @@
};
/* sourced from vbus, vbus is provided by the carrier board */
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -94,7 +94,7 @@
vin-supply = <&vbus>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -213,7 +213,7 @@
clock-output-names = "rk808-clkout1", "rk808-clkout2";
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566.dtsi b/arch/arm64/boot/dts/rockchip/rk3566.dtsi
index 6c4b17d27bdc..3fcca79279f7 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566.dtsi
@@ -1,35 +1,107 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-#include "rk356x.dtsi"
+#include "rk3566-base.dtsi"
/ {
- compatible = "rockchip,rk3566";
+ cpu0_opp_table: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-816000000 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+
+ opp-1104000000 {
+ opp-hz = /bits/ 64 <1104000000>;
+ opp-microvolt = <900000 900000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <1025000 1025000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <1150000 1150000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ gpu_opp_table: opp-table-1 {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <900000 900000 1000000>;
+ };
+
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <950000 950000 1000000>;
+ };
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1000000 1000000 1000000>;
+ };
+ };
};
-&pipegrf {
- compatible = "rockchip,rk3566-pipe-grf", "syscon";
+&cpu0 {
+ operating-points-v2 = <&cpu0_opp_table>;
};
-&power {
- power-domain@RK3568_PD_PIPE {
- reg = <RK3568_PD_PIPE>;
- clocks = <&cru PCLK_PIPE>;
- pm_qos = <&qos_pcie2x1>,
- <&qos_sata1>,
- <&qos_sata2>,
- <&qos_usb3_0>,
- <&qos_usb3_1>;
- #power-domain-cells = <0>;
- };
+&cpu1 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&cpu2 {
+ operating-points-v2 = <&cpu0_opp_table>;
};
-&usb_host0_xhci {
- phys = <&usb2phy0_otg>;
- phy-names = "usb2-phy";
- extcon = <&usb2phy0>;
- maximum-speed = "high-speed";
+&cpu3 {
+ operating-points-v2 = <&cpu0_opp_table>;
};
-&vop {
- compatible = "rockchip,rk3566-vop";
+&gpu {
+ operating-points-v2 = <&gpu_opp_table>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566t.dtsi b/arch/arm64/boot/dts/rockchip/rk3566t.dtsi
new file mode 100644
index 000000000000..cd89bd3b125b
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566t.dtsi
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+#include "rk3566-base.dtsi"
+
+/ {
+ cpu0_opp_table: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-816000000 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+
+ opp-1104000000 {
+ opp-hz = /bits/ 64 <1104000000>;
+ opp-microvolt = <900000 900000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <1025000 1025000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ gpu_opp_table: opp-table-1 {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <900000 900000 1000000>;
+ };
+
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <950000 950000 1000000>;
+ };
+ };
+};
+
+&cpu0 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&cpu1 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&cpu2 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&cpu3 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&gpu {
+ operating-points-v2 = <&gpu_opp_table>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
index c87fad2c34cb..4d3ebe50b90b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
@@ -46,7 +46,7 @@
};
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -73,7 +73,7 @@
pinctrl-0 = <&ir_receiver_pin>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -83,7 +83,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -93,7 +93,7 @@
vin-supply = <&dc_12v>;
};
- pcie30_avdd0v9: pcie30-avdd0v9-regulator {
+ pcie30_avdd0v9: regulator-pcie30-avdd0v9 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v9";
regulator-always-on;
@@ -103,7 +103,7 @@
vin-supply = <&vcc3v3_sys>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -114,7 +114,7 @@
};
/* pi6c pcie clock generator feeds both ports */
- vcc3v3_pi6c_05: vcc3v3-pi6c-05-regulator {
+ vcc3v3_pi6c_05: regulator-vcc3v3-pi6c-05 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;
@@ -126,7 +126,7 @@
};
/* actually fed by vcc3v3_sys, dependent on pi6c clock generator */
- vcc3v3_minipcie: vcc3v3-minipcie-regulator {
+ vcc3v3_minipcie: regulator-vcc3v3-minipcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_minipcie";
regulator-min-microvolt = <3300000>;
@@ -140,7 +140,7 @@
};
/* actually fed by vcc3v3_sys, dependent on pi6c clock generator */
- vcc3v3_ngff: vcc3v3-ngff-regulator {
+ vcc3v3_ngff: regulator-vcc3v3-ngff {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_ngff";
regulator-min-microvolt = <3300000>;
@@ -153,7 +153,7 @@
vin-supply = <&vcc3v3_pi6c_05>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -163,7 +163,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_usb_host: vcc5v0-usb-host-regulator {
+ vcc5v0_usb_host: regulator-vcc5v0-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -175,7 +175,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -291,7 +291,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
vcc3-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
index 8c3ab07d3807..b073a4d03e4f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
@@ -26,7 +26,7 @@
stdout-path = "serial2:1500000n8";
};
- dc_12v: dc-12v {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -73,7 +73,7 @@
};
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -83,7 +83,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -93,7 +93,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_usb: vcc5v0-usb {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -103,7 +103,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_usb_host: vcc5v0-usb-host {
+ vcc5v0_usb_host: regulator-vcc5v0-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -115,7 +115,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -127,7 +127,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc3v3_lcd0_n: vcc3v3-lcd0-n {
+ vcc3v3_lcd0_n: regulator-vcc3v3-lcd0-n {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_lcd0_n";
regulator-min-microvolt = <3300000>;
@@ -143,7 +143,7 @@
};
};
- vcc3v3_lcd1_n: vcc3v3-lcd1-n {
+ vcc3v3_lcd1_n: regulator-vcc3v3-lcd1-n {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_lcd1_n";
regulator-min-microvolt = <3300000>;
@@ -275,7 +275,7 @@
clocks = <&cru I2S1_MCLKOUT_TX>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi
index 25c49bdbadbc..b0ac1e58a352 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi
@@ -39,7 +39,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -48,7 +48,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-always-on;
@@ -58,7 +58,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -68,7 +68,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -78,7 +78,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -152,7 +152,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
vcc3-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts b/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts
index a3112d5df200..a7fe5655a85d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts
@@ -51,7 +51,7 @@
};
};
- dc_5v: dc-5v-regulator {
+ dc_5v: regulator-dc-5v {
compatible = "regulator-fixed";
regulator-name = "dc_5v";
regulator-always-on;
@@ -60,7 +60,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -70,7 +70,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -80,7 +80,7 @@
vin-supply = <&dc_5v>;
};
- vcc3v3_m2_pcie: vcc3v3-m2-pcie-regulator {
+ vcc3v3_m2_pcie: regulator-vcc3v3-m2-pcie {
compatible = "regulator-fixed";
regulator-name = "m2_pcie_3v3";
enable-active-high;
@@ -93,7 +93,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_mini_pcie: vcc3v3-mini-pcie-regulator {
+ vcc3v3_mini_pcie: regulator-vcc3v3-mini-pcie {
compatible = "regulator-fixed";
regulator-name = "minipcie_3v3";
enable-active-high;
@@ -106,7 +106,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb20_host: vcc5v0-usb20-host-regulator {
+ vcc5v0_usb20_host: regulator-vcc5v0-usb20-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb20_host";
enable-active-high;
@@ -115,7 +115,7 @@
pinctrl-names = "default";
};
- vcc5v0_usb30_host: vcc5v0-usb30-host-regulator {
+ vcc5v0_usb30_host: regulator-vcc5v0-usb30-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb30_host";
enable-active-high;
@@ -124,7 +124,7 @@
pinctrl-names = "default";
};
- vcc5v0_otg_vbus: vcc5v0-otg-vbus-regulator {
+ vcc5v0_otg_vbus: regulator-vcc5v0-otg-vbus {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_otg_vbus";
enable-active-high;
@@ -223,7 +223,7 @@
clocks = <&cru I2S1_MCLKOUT_TX>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
@@ -589,7 +589,6 @@
non-removable;
pinctrl-names = "default";
pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>;
- supports-emmc;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dtsi
index 93189f830640..00c479aa1871 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dtsi
@@ -35,7 +35,7 @@
};
};
- vdd_usbc: vdd-usbc-regulator {
+ vdd_usbc: regulator-vdd-usbc {
compatible = "regulator-fixed";
regulator-name = "vdd_usbc";
regulator-always-on;
@@ -44,7 +44,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -54,7 +54,7 @@
vin-supply = <&vdd_usbc>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -64,7 +64,7 @@
vin-supply = <&vdd_usbc>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
regulator-min-microvolt = <3300000>;
@@ -75,7 +75,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -85,7 +85,7 @@
vin-supply = <&vdd_usbc>;
};
- vcc5v0_usb_host: vcc5v0-usb-host-regulator {
+ vcc5v0_usb_host: regulator-vcc5v0-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -99,7 +99,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -111,7 +111,7 @@
vin-supply = <&vcc5v0_usb>;
};
- pcie30_avdd0v9: pcie30-avdd0v9-regulator {
+ pcie30_avdd0v9: regulator-pcie30-avdd0v9 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v9";
regulator-always-on;
@@ -121,7 +121,7 @@
vin-supply = <&vcc3v3_sys>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -215,7 +215,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
vcc3-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
index 6a02db4f073f..0f844806ec54 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
@@ -29,7 +29,7 @@
stdout-path = "serial2:1500000n8";
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -84,7 +84,7 @@
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,hp-det-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Headphone", "Headphones",
@@ -103,7 +103,7 @@
};
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
enable-active-high;
@@ -116,7 +116,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -126,7 +126,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -136,7 +136,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_usb_host: vcc5v0-usb-host-regulator {
+ vcc5v0_usb_host: regulator-vcc5v0-usb-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb_host";
enable-active-high;
@@ -148,7 +148,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb_otg";
enable-active-high;
@@ -273,7 +273,7 @@
clocks = <&cru I2S1_MCLKOUT_TX>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi
index 19d309654bdb..729e38b9f620 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi
@@ -29,7 +29,7 @@
};
};
- pcie30_avdd0v9: pcie30-avdd0v9-regulator {
+ pcie30_avdd0v9: regulator-pcie30-avdd0v9 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v9";
regulator-always-on;
@@ -39,7 +39,7 @@
vin-supply = <&vcc3v3_sys>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -49,7 +49,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -59,7 +59,7 @@
vin-supply = <&vcc5v_input>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -70,7 +70,7 @@
};
/* labeled +5v_input in schematic */
- vcc5v_input: vcc5v-input-regulator {
+ vcc5v_input: regulator-vcc5v-input {
compatible = "regulator-fixed";
regulator-name = "vcc5v_input";
regulator-always-on;
@@ -141,7 +141,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
wakeup-source;
vcc1-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts b/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts
index 84a0789fad96..98cfa3abb809 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts
@@ -16,6 +16,7 @@
multi-led {
color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_STATUS;
max-brightness = <255>;
led-red {
@@ -35,7 +36,7 @@
};
};
- vbus_typec: vbus-typec-regulator {
+ vbus_typec: regulator-vbus-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
@@ -50,7 +51,7 @@
/* actually fed by vcc5v0_sys, dependent
* on pi6c clock generator
*/
- vcc3v3_minipcie: vcc3v3-minipcie-regulator {
+ vcc3v3_minipcie: regulator-vcc3v3-minipcie {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;
@@ -62,7 +63,7 @@
vin-supply = <&vcc3v3_pi6c_05>;
};
- vcc3v3_ngff: vcc3v3-ngff-regulator {
+ vcc3v3_ngff: regulator-vcc3v3-ngff {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>;
@@ -74,7 +75,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie30x1: vcc3v3-pcie30x1-regulator {
+ vcc3v3_pcie30x1: regulator-vcc3v3-pcie30x1 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -86,7 +87,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pi6c_05: vcc3v3-pi6c-05-regulator {
+ vcc3v3_pi6c_05: regulator-vcc3v3-pi6c-05 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
@@ -123,7 +124,7 @@
&pcie3x1 {
num-lanes = <1>;
pinctrl-names = "default";
- pinctrl-0 = <&pcie30x1m0_pins>;
+ pinctrl-0 = <&pcie30x1_reset_h>;
reset-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_minipcie>;
status = "okay";
@@ -148,6 +149,10 @@
rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
};
+ pcie30x1_reset_h: pcie30x1-reset-h {
+ rockchip,pins = <0 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
pcie30x2_reset_h: pcie30x2-reset-h {
rockchip,pins = <2 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts b/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts
index e333449ead04..60faa0c80cd7 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts
@@ -25,7 +25,7 @@
stdout-path = "serial2:1500000n8";
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -73,7 +73,7 @@
};
};
- pcie30_avdd0v9: pcie30-avdd0v9-regulator {
+ pcie30_avdd0v9: regulator-pcie30-avdd0v9 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v9";
regulator-always-on;
@@ -83,7 +83,7 @@
vin-supply = <&vcc3v3_sys>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -93,7 +93,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -103,7 +103,7 @@
vin-supply = <&dc_12v>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie";
enable-active-high;
@@ -116,7 +116,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -126,7 +126,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -136,7 +136,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
enable-active-high;
@@ -147,7 +147,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_otg: vcc5v0-otg-regulator {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_otg";
enable-active-high;
@@ -255,7 +255,7 @@
#clock-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
vcc3-supply = <&vcc3v3_sys>;
@@ -272,7 +272,6 @@
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>;
@@ -285,7 +284,6 @@
vdd_gpu: DCDC_REG2 {
regulator-name = "vdd_gpu";
- regulator-init-microvolt = <900000>;
regulator-initial-mode = <0x2>;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
@@ -309,7 +307,6 @@
vdd_npu: DCDC_REG4 {
regulator-name = "vdd_npu";
- regulator-init-microvolt = <900000>;
regulator-initial-mode = <0x2>;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
index 59f1403b4fa5..ac79140a9ecd 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
@@ -79,14 +79,14 @@
reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_LOW>;
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
regulator-boot-on;
};
- pcie30_avdd0v9: pcie30-avdd0v9-regulator {
+ pcie30_avdd0v9: regulator-pcie30-avdd0v9 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v9";
regulator-always-on;
@@ -96,7 +96,7 @@
vin-supply = <&vcc3v3_sys>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -107,7 +107,7 @@
};
/* pi6c pcie clock generator */
- vcc3v3_pi6c_03: vcc3v3-pi6c-03-regulator {
+ vcc3v3_pi6c_03: regulator-vcc3v3-pi6c-03 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pi6c_03";
regulator-always-on;
@@ -117,7 +117,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie: vcc3v3-pcie-regulator {
+ vcc3v3_pcie: regulator-vcc3v3-pcie {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;
@@ -129,7 +129,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -139,7 +139,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -149,7 +149,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -159,7 +159,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb_host: vcc5v0-usb-host-regulator {
+ vcc5v0_usb_host: regulator-vcc5v0-usb-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -171,7 +171,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb_hub: vcc5v0-usb-hub-regulator {
+ vcc5v0_usb_hub: regulator-vcc5v0-usb-hub {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
@@ -182,7 +182,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ vcc5v0_usb_otg: regulator-vcc5v0-usb-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -194,7 +194,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc_cam: vcc-cam-regulator {
+ vcc_cam: regulator-vcc-cam {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
@@ -210,7 +210,7 @@
};
};
- vcc_mipi: vcc-mipi-regulator {
+ vcc_mipi: regulator-vcc-mipi {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
@@ -333,7 +333,7 @@
clocks = <&cru I2S1_MCLKOUT_TX>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>;
- rockchip,system-power-controller;
+ system-power-controller;
#sound-dai-cells = <0>;
vcc1-supply = <&vcc3v3_sys>;
vcc2-supply = <&vcc3v3_sys>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso
index ebcaeafc3800..048933de2943 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso
+++ b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-io-expander.dtso
@@ -21,7 +21,7 @@
#clock-cells = <0>;
};
- usb_host_vbus: usb-host-vbus-regulator {
+ usb_host_vbus: regulator-usb-host-vbus {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -33,7 +33,7 @@
vin-supply = <&vcc5v_in>;
};
- vcc1v8_eth: vcc1v8-eth-regulator {
+ vcc1v8_eth: regulator-vcc1v8-eth {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
@@ -47,9 +47,8 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_eth: vcc3v3-eth-regulator {
+ vcc3v3_eth: regulator-vcc3v3-eth {
compatible = "regulator-fixed";
- enable-active-low;
gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&vcc3v3_eth_enn>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5.dts b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5.dts
index 170b14f92f51..e8243c908542 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5.dts
@@ -39,7 +39,7 @@
};
};
- hdmi_tx_5v: hdmi-tx-5v-regulator {
+ hdmi_tx_5v: regulator-hdmi-tx-5v {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -70,7 +70,7 @@
};
};
- vcc12v_cam: vcc12v-cam-regulator {
+ vcc12v_cam: regulator-vcc12v-cam {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>;
@@ -82,7 +82,7 @@
vin-supply = <&vcc12v_in>;
};
- vcc12v_in: vcc12v-in-regulator {
+ vcc12v_in: regulator-vcc12v-in {
compatible = "regulator-fixed";
regulator-name = "12v_in";
regulator-always-on;
@@ -91,7 +91,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v8_cam: vcc3v8-cam-regulator {
+ vcc3v8_cam: regulator-vcc3v8-cam {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;
@@ -103,7 +103,7 @@
vin-supply = <&vcc5v_in>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "3v3_sys";
regulator-always-on;
@@ -113,7 +113,7 @@
vin-supply = <&vcc5v_in>;
};
- vcc5v_in: vcc5v-in-regulator {
+ vcc5v_in: regulator-vcc5v-in {
compatible = "regulator-fixed";
regulator-name = "5v_in";
regulator-always-on;
@@ -178,7 +178,7 @@
#clock-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int_l>;
- rockchip,system-power-controller;
+ system-power-controller;
vcc1-supply = <&vcc5v_in>;
vcc2-supply = <&vcc5v_in>;
vcc3-supply = <&vcc5v_in>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
index 0946310e8c12..ecaefe208e3e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
@@ -3,11 +3,99 @@
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
*/
-#include "rk356x.dtsi"
+#include "rk356x-base.dtsi"
/ {
compatible = "rockchip,rk3568";
+ cpu0_opp_table: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-816000000 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <850000 850000 1150000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+
+ opp-1104000000 {
+ opp-hz = /bits/ 64 <1104000000>;
+ opp-microvolt = <900000 900000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <1025000 1025000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <1150000 1150000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1992000000 {
+ opp-hz = /bits/ 64 <1992000000>;
+ opp-microvolt = <1150000 1150000 1150000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ gpu_opp_table: opp-table-1 {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <900000 900000 1000000>;
+ };
+
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <950000 950000 1000000>;
+ };
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1000000 1000000 1000000>;
+ };
+ };
+
sata0: sata@fc000000 {
compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
reg = <0 0xfc000000 0 0x1000>;
@@ -269,11 +357,24 @@
};
};
-&cpu0_opp_table {
- opp-1992000000 {
- opp-hz = /bits/ 64 <1992000000>;
- opp-microvolt = <1150000 1150000 1150000>;
- };
+&cpu0 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&cpu1 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&cpu2 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&cpu3 {
+ operating-points-v2 = <&cpu0_opp_table>;
+};
+
+&gpu {
+ operating-points-v2 = <&gpu_opp_table>;
};
&pipegrf {
diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
index 0ee0ada6f0ab..62be06f3b863 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi
@@ -56,7 +56,6 @@
clocks = <&scmi_clk 0>;
#cooling-cells = <2>;
enable-method = "psci";
- operating-points-v2 = <&cpu0_opp_table>;
i-cache-size = <0x8000>;
i-cache-line-size = <64>;
i-cache-sets = <128>;
@@ -72,7 +71,6 @@
reg = <0x0 0x100>;
#cooling-cells = <2>;
enable-method = "psci";
- operating-points-v2 = <&cpu0_opp_table>;
i-cache-size = <0x8000>;
i-cache-line-size = <64>;
i-cache-sets = <128>;
@@ -88,7 +86,6 @@
reg = <0x0 0x200>;
#cooling-cells = <2>;
enable-method = "psci";
- operating-points-v2 = <&cpu0_opp_table>;
i-cache-size = <0x8000>;
i-cache-line-size = <64>;
i-cache-sets = <128>;
@@ -104,7 +101,6 @@
reg = <0x0 0x300>;
#cooling-cells = <2>;
enable-method = "psci";
- operating-points-v2 = <&cpu0_opp_table>;
i-cache-size = <0x8000>;
i-cache-line-size = <64>;
i-cache-sets = <128>;
@@ -128,48 +124,6 @@
cache-sets = <512>;
};
- cpu0_opp_table: opp-table-0 {
- compatible = "operating-points-v2";
- opp-shared;
-
- opp-408000000 {
- opp-hz = /bits/ 64 <408000000>;
- opp-microvolt = <900000 900000 1150000>;
- clock-latency-ns = <40000>;
- };
-
- opp-600000000 {
- opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <900000 900000 1150000>;
- };
-
- opp-816000000 {
- opp-hz = /bits/ 64 <816000000>;
- opp-microvolt = <900000 900000 1150000>;
- opp-suspend;
- };
-
- opp-1104000000 {
- opp-hz = /bits/ 64 <1104000000>;
- opp-microvolt = <900000 900000 1150000>;
- };
-
- opp-1416000000 {
- opp-hz = /bits/ 64 <1416000000>;
- opp-microvolt = <900000 900000 1150000>;
- };
-
- opp-1608000000 {
- opp-hz = /bits/ 64 <1608000000>;
- opp-microvolt = <975000 975000 1150000>;
- };
-
- opp-1800000000 {
- opp-hz = /bits/ 64 <1800000000>;
- opp-microvolt = <1050000 1050000 1150000>;
- };
- };
-
display_subsystem: display-subsystem {
compatible = "rockchip,display-subsystem";
ports = <&vop_out>;
@@ -190,40 +144,6 @@
};
};
- gpu_opp_table: opp-table-1 {
- compatible = "operating-points-v2";
-
- opp-200000000 {
- opp-hz = /bits/ 64 <200000000>;
- opp-microvolt = <850000 850000 1000000>;
- };
-
- opp-300000000 {
- opp-hz = /bits/ 64 <300000000>;
- opp-microvolt = <850000 850000 1000000>;
- };
-
- opp-400000000 {
- opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <850000 850000 1000000>;
- };
-
- opp-600000000 {
- opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <900000 900000 1000000>;
- };
-
- opp-700000000 {
- opp-hz = /bits/ 64 <700000000>;
- opp-microvolt = <950000 950000 1000000>;
- };
-
- opp-800000000 {
- opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = <1000000 1000000 1000000>;
- };
- };
-
hdmi_sound: hdmi-sound {
compatible = "simple-audio-card";
simple-audio-card,name = "HDMI";
@@ -629,7 +549,6 @@
clocks = <&scmi_clk 1>, <&cru CLK_GPU>;
clock-names = "gpu", "bus";
#cooling-cells = <2>;
- operating-points-v2 = <&gpu_opp_table>;
power-domains = <&power RK3568_PD_GPU>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
new file mode 100644
index 000000000000..7c7331936a7f
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts
@@ -0,0 +1,658 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Rockchip Electronics 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/pwm/pwm.h>
+#include <dt-bindings/usb/pd.h>
+#include "rk3576.dtsi"
+
+/ {
+ model = "ArmSoM Sige5";
+ compatible = "armsom,sige5", "rockchip,rk3576";
+
+ aliases {
+ ethernet0 = &gmac0;
+ ethernet1 = &gmac1;
+ };
+
+ chosen {
+ stdout-path = "serial0:1500000n8";
+ };
+
+ leds: leds {
+ compatible = "gpio-leds";
+
+ green_led: green-led {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ red_led: red-led {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+ };
+
+ vcc_12v0_dcin: regulator-vcc-12v0-dcin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_12v0_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ vcc_1v2_ufs_vccq_s0: regulator-vcc-1v2-ufs-vccq-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v2_ufs_vccq_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ vcc_1v8_s0: regulator-vcc-1v8-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v8_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_1v8_s3>;
+ };
+
+ vcc_1v8_ufs_vccq2_s0: regulator-vcc-1v8-ufs-vccq2-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v8_ufs_vccq2_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_1v8_s3>;
+ };
+
+ vcc_2v0_pldo_s3: regulator-vcc-2v0-pldo-s3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_2v0_pldo_s3";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ vcc_3v3_pcie: regulator-vcc-3v3-pcie {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_pcie";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ vcc_3v3_rtc_s5: regulator-vcc-3v3-rtc-s5 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_rtc_s5";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+
+ vcc_3v3_s0: regulator-vcc-3v3-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc_5v0_sys: regulator-vcc-5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_12v0_dcin>;
+ };
+
+ vcc_5v0_device: regulator-vcc-5v0-device {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_5v0_device";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_12v0_dcin>;
+ };
+
+ vcc_3v3_ufs_s0: regulator-vcc-ufs-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_ufs_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_5v0_sys>;
+ };
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gmac0 {
+ phy-mode = "rgmii-id";
+ clock_in_out = "output";
+
+ snps,reset-gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 20000 100000>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&eth0m0_miim
+ &eth0m0_tx_bus2
+ &eth0m0_rx_bus2
+ &eth0m0_rgmii_clk
+ &eth0m0_rgmii_bus
+ &ethm0_clk0_25m_out>;
+
+ phy-handle = <&rgmii_phy0>;
+ status = "okay";
+};
+
+&gmac1 {
+ phy-mode = "rgmii-id";
+ clock_in_out = "output";
+
+ snps,reset-gpio = <&gpio3 RK_PA3 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 20000 100000>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&eth1m0_miim
+ &eth1m0_tx_bus2
+ &eth1m0_rx_bus2
+ &eth1m0_rgmii_clk
+ &eth1m0_rgmii_bus
+ &ethm0_clk1_25m_out>;
+
+ phy-handle = <&rgmii_phy1>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ pmic@23 {
+ compatible = "rockchip,rk806";
+ reg = <0x23>;
+
+ interrupt-parent = <&gpio0>;
+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+
+ system-power-controller;
+
+ vcc1-supply = <&vcc_5v0_sys>;
+ vcc2-supply = <&vcc_5v0_sys>;
+ vcc3-supply = <&vcc_5v0_sys>;
+ vcc4-supply = <&vcc_5v0_sys>;
+ vcc5-supply = <&vcc_5v0_sys>;
+ vcc6-supply = <&vcc_5v0_sys>;
+ vcc7-supply = <&vcc_5v0_sys>;
+ vcc8-supply = <&vcc_5v0_sys>;
+ vcc9-supply = <&vcc_5v0_sys>;
+ vcc10-supply = <&vcc_5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc_5v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc_5v0_sys>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs1_slp: dvs1-slp-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun1";
+ };
+
+ rk806_dvs1_pwrdn: dvs1-pwrdn-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun2";
+ };
+
+ rk806_dvs1_rst: dvs1-rst-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun3";
+ };
+
+ rk806_dvs2_slp: dvs2-slp-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun1";
+ };
+
+ rk806_dvs2_pwrdn: dvs2-pwrdn-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun2";
+ };
+
+ rk806_dvs2_rst: dvs2-rst-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun3";
+ };
+
+ rk806_dvs2_dvs: dvs2-dvs-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun4";
+ };
+
+ rk806_dvs2_gpio: dvs2-gpio-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun5";
+ };
+
+ rk806_dvs3_slp: dvs3-slp-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun1";
+ };
+
+ rk806_dvs3_pwrdn: dvs3-pwrdn-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun2";
+ };
+
+ rk806_dvs3_rst: dvs3-rst-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun3";
+ };
+
+ rk806_dvs3_dvs: dvs3-dvs-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun4";
+ };
+
+ rk806_dvs3_gpio: dvs3-gpio-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun5";
+ };
+
+ regulators {
+ vdd_cpu_big_s0: dcdc-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_cpu_big_s0";
+ regulator-enable-ramp-delay = <400>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_npu_s0: dcdc-reg2 {
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_npu_s0";
+ regulator-enable-ramp-delay = <400>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc_3v3_s3";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vdd_gpu_s0: dcdc-reg5 {
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_gpu_s0";
+ regulator-enable-ramp-delay = <400>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vddq_ddr_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_logic_s0: dcdc-reg7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <800000>;
+ regulator-name = "vdd_logic_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc_1v8_s3";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg9 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vdd2_ddr_s3";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg10 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "vdd_ddr_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca_1v8_s0: pldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcca_1v8_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca1v8_pldo2_s0: pldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcca1v8_pldo2_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_1v2_s0: pldo-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "vdda_1v2_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca_3v3_s0: pldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcca_3v3_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vccio_sd_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca1v8_pldo6_s3: pldo-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcca1v8_pldo6_s3";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdd_0v75_s3";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdda_ddr_pll_s0: nldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdda_ddr_pll_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda0v75_hdmi_s0: nldo-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <837500>;
+ regulator-max-microvolt = <837500>;
+ regulator-name = "vdda0v75_hdmi_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v85_s0: nldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdda_0v85_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v75_s0: nldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdda_0v75_s0";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ clock-output-names = "hym8563";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ wakeup-source;
+ #clock-cells = <0>;
+ };
+};
+
+&mdio0 {
+ rgmii_phy0: phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ clocks = <&cru REFCLKO25M_GMAC0_OUT>;
+ };
+};
+
+&mdio1 {
+ rgmii_phy1: phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ clocks = <&cru REFCLKO25M_GMAC1_OUT>;
+ };
+};
+
+&pinctrl {
+ headphone {
+ hp_det: hp-det {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ leds {
+ led_rgb_r: led-red-en {
+ rockchip,pins = <4 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ led_rgb_g: led-green-en {
+ rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&sdhci {
+ bus-width = <8>;
+ full-pwr-cycle-in-suspend;
+ max-frequency = <200000000>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ no-sdio;
+ no-sd;
+ non-removable;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ disable-wp;
+ max-frequency = <200000000>;
+ no-sdio;
+ no-mmc;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_s3>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0m0_xfer>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi
new file mode 100644
index 000000000000..0b0851a7e4ea
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi
@@ -0,0 +1,5775 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rockchip-pinconf.dtsi"
+
+/*
+ * This file is auto generated by pin2dts tool, please keep these code
+ * by adding changes at end of this file.
+ */
+&pinctrl {
+ aupll_clk {
+ /omit-if-no-ref/
+ aupll_clkm0_pins: aupll_clkm0-pins {
+ rockchip,pins =
+ /* aupll_clk_in_m0 */
+ <0 RK_PA0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ aupll_clkm1_pins: aupll_clkm1-pins {
+ rockchip,pins =
+ /* aupll_clk_in_m1 */
+ <0 RK_PB0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ aupll_clkm2_pins: aupll_clkm2-pins {
+ rockchip,pins =
+ /* aupll_clk_in_m2 */
+ <4 RK_PA2 3 &pcfg_pull_none>;
+ };
+ };
+
+ cam_clk0 {
+ /omit-if-no-ref/
+ cam_clk0m0_clk0: cam_clk0m0-clk0 {
+ rockchip,pins =
+ /* cam_clk0_out_m0 */
+ <3 RK_PD7 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ cam_clk0m1_clk0: cam_clk0m1-clk0 {
+ rockchip,pins =
+ /* cam_clk0_out_m1 */
+ <2 RK_PD2 1 &pcfg_pull_none>;
+ };
+ };
+
+ cam_clk1 {
+ /omit-if-no-ref/
+ cam_clk1m0_clk1: cam_clk1m0-clk1 {
+ rockchip,pins =
+ /* cam_clk1_out_m0 */
+ <4 RK_PA0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ cam_clk1m1_clk1: cam_clk1m1-clk1 {
+ rockchip,pins =
+ /* cam_clk1_out_m1 */
+ <2 RK_PD6 1 &pcfg_pull_none>;
+ };
+ };
+
+ cam_clk2 {
+ /omit-if-no-ref/
+ cam_clk2m0_clk2: cam_clk2m0-clk2 {
+ rockchip,pins =
+ /* cam_clk2_out_m0 */
+ <4 RK_PA1 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ cam_clk2m1_clk2: cam_clk2m1-clk2 {
+ rockchip,pins =
+ /* cam_clk2_out_m1 */
+ <2 RK_PD7 1 &pcfg_pull_none>;
+ };
+ };
+
+ can0 {
+ /omit-if-no-ref/
+ can0m0_pins: can0m0-pins {
+ rockchip,pins =
+ /* can0_rx_m0 */
+ <2 RK_PA0 13 &pcfg_pull_none>,
+ /* can0_tx_m0 */
+ <2 RK_PA1 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ can0m1_pins: can0m1-pins {
+ rockchip,pins =
+ /* can0_rx_m1 */
+ <4 RK_PC3 12 &pcfg_pull_none>,
+ /* can0_tx_m1 */
+ <4 RK_PC2 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ can0m2_pins: can0m2-pins {
+ rockchip,pins =
+ /* can0_rx_m2 */
+ <4 RK_PA6 13 &pcfg_pull_none>,
+ /* can0_tx_m2 */
+ <4 RK_PA4 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ can0m3_pins: can0m3-pins {
+ rockchip,pins =
+ /* can0_rx_m3 */
+ <3 RK_PC1 12 &pcfg_pull_none>,
+ /* can0_tx_m3 */
+ <3 RK_PC4 12 &pcfg_pull_none>;
+ };
+ };
+
+ can1 {
+ /omit-if-no-ref/
+ can1m0_pins: can1m0-pins {
+ rockchip,pins =
+ /* can1_rx_m0 */
+ <2 RK_PA2 13 &pcfg_pull_none>,
+ /* can1_tx_m0 */
+ <2 RK_PA3 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ can1m1_pins: can1m1-pins {
+ rockchip,pins =
+ /* can1_rx_m1 */
+ <4 RK_PC7 13 &pcfg_pull_none>,
+ /* can1_tx_m1 */
+ <4 RK_PC6 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ can1m2_pins: can1m2-pins {
+ rockchip,pins =
+ /* can1_rx_m2 */
+ <4 RK_PB4 13 &pcfg_pull_none>,
+ /* can1_tx_m2 */
+ <4 RK_PB5 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ can1m3_pins: can1m3-pins {
+ rockchip,pins =
+ /* can1_rx_m3 */
+ <3 RK_PA3 11 &pcfg_pull_none>,
+ /* can1_tx_m3 */
+ <3 RK_PA2 11 &pcfg_pull_none>;
+ };
+ };
+
+ clk0_32k {
+ /omit-if-no-ref/
+ clk0_32k_pins: clk0_32k-pins {
+ rockchip,pins =
+ /* clk0_32k_out */
+ <0 RK_PA2 10 &pcfg_pull_none>;
+ };
+ };
+
+ clk1_32k {
+ /omit-if-no-ref/
+ clk1_32k_pins: clk1_32k-pins {
+ rockchip,pins =
+ /* clk1_32k_out */
+ <1 RK_PD5 13 &pcfg_pull_none>;
+ };
+ };
+
+ clk_32k {
+ /omit-if-no-ref/
+ clk_32k_pins: clk_32k-pins {
+ rockchip,pins =
+ /* clk_32k_in */
+ <0 RK_PA2 9 &pcfg_pull_none>;
+ };
+ };
+
+ cpubig {
+ /omit-if-no-ref/
+ cpubig_pins: cpubig-pins {
+ rockchip,pins =
+ /* cpubig_avs */
+ <0 RK_PD2 11 &pcfg_pull_none>;
+ };
+ };
+
+ cpulit {
+ /omit-if-no-ref/
+ cpulit_pins: cpulit-pins {
+ rockchip,pins =
+ /* cpulit_avs */
+ <0 RK_PC0 11 &pcfg_pull_none>;
+ };
+ };
+
+ debug0_test {
+ /omit-if-no-ref/
+ debug0_test_pins: debug0_test-pins {
+ rockchip,pins =
+ /* debug0_test_out */
+ <1 RK_PC4 7 &pcfg_pull_none>;
+ };
+ };
+
+ debug1_test {
+ /omit-if-no-ref/
+ debug1_test_pins: debug1_test-pins {
+ rockchip,pins =
+ /* debug1_test_out */
+ <1 RK_PC5 7 &pcfg_pull_none>;
+ };
+ };
+
+ debug2_test {
+ /omit-if-no-ref/
+ debug2_test_pins: debug2_test-pins {
+ rockchip,pins =
+ /* debug2_test_out */
+ <1 RK_PC6 7 &pcfg_pull_none>;
+ };
+ };
+
+ debug3_test {
+ /omit-if-no-ref/
+ debug3_test_pins: debug3_test-pins {
+ rockchip,pins =
+ /* debug3_test_out */
+ <1 RK_PC7 7 &pcfg_pull_none>;
+ };
+ };
+
+ debug4_test {
+ /omit-if-no-ref/
+ debug4_test_pins: debug4_test-pins {
+ rockchip,pins =
+ /* debug4_test_out */
+ <1 RK_PD0 7 &pcfg_pull_none>;
+ };
+ };
+
+ debug5_test {
+ /omit-if-no-ref/
+ debug5_test_pins: debug5_test-pins {
+ rockchip,pins =
+ /* debug5_test_out */
+ <1 RK_PD1 7 &pcfg_pull_none>;
+ };
+ };
+
+ debug6_test {
+ /omit-if-no-ref/
+ debug6_test_pins: debug6_test-pins {
+ rockchip,pins =
+ /* debug6_test_out */
+ <1 RK_PD2 7 &pcfg_pull_none>;
+ };
+ };
+
+ debug7_test {
+ /omit-if-no-ref/
+ debug7_test_pins: debug7_test-pins {
+ rockchip,pins =
+ /* debug7_test_out */
+ <1 RK_PD3 7 &pcfg_pull_none>;
+ };
+ };
+
+ dp {
+ /omit-if-no-ref/
+ dpm0_pins: dpm0-pins {
+ rockchip,pins =
+ /* dp_hpdin_m0 */
+ <4 RK_PC4 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dpm1_pins: dpm1-pins {
+ rockchip,pins =
+ /* dp_hpdin_m1 */
+ <0 RK_PC5 9 &pcfg_pull_none>;
+ };
+ };
+
+ dsm_aud {
+ /omit-if-no-ref/
+ dsm_audm0_ln: dsm_audm0-ln {
+ rockchip,pins =
+ /* dsm_aud_ln_m0 */
+ <2 RK_PA1 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dsm_audm0_lp: dsm_audm0-lp {
+ rockchip,pins =
+ /* dsm_aud_lp_m0 */
+ <2 RK_PA0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dsm_audm0_rn: dsm_audm0-rn {
+ rockchip,pins =
+ /* dsm_aud_rn_m0 */
+ <2 RK_PA3 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dsm_audm0_rp: dsm_audm0-rp {
+ rockchip,pins =
+ /* dsm_aud_rp_m0 */
+ <2 RK_PA2 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dsm_audm1_ln: dsm_audm1-ln {
+ rockchip,pins =
+ /* dsm_aud_ln_m1 */
+ <4 RK_PC1 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dsm_audm1_lp: dsm_audm1-lp {
+ rockchip,pins =
+ /* dsm_aud_lp_m1 */
+ <4 RK_PC0 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dsm_audm1_rn: dsm_audm1-rn {
+ rockchip,pins =
+ /* dsm_aud_rn_m1 */
+ <4 RK_PC3 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ dsm_audm1_rp: dsm_audm1-rp {
+ rockchip,pins =
+ /* dsm_aud_rp_m1 */
+ <4 RK_PC2 1 &pcfg_pull_none>;
+ };
+ };
+
+ dsmc {
+ /omit-if-no-ref/
+ dsmc_clkn: dsmc-clkn {
+ rockchip,pins =
+ /* dsmc_clkn */
+ <3 RK_PD6 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_clkp: dsmc-clkp {
+ rockchip,pins =
+ /* dsmc_clkp */
+ <3 RK_PD5 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_csn0: dsmc-csn0 {
+ rockchip,pins =
+ /* dsmc_csn0 */
+ <3 RK_PD3 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_csn1: dsmc-csn1 {
+ rockchip,pins =
+ /* dsmc_csn1 */
+ <3 RK_PB0 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_csn2: dsmc-csn2 {
+ rockchip,pins =
+ /* dsmc_csn2 */
+ <3 RK_PD1 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_csn3: dsmc-csn3 {
+ rockchip,pins =
+ /* dsmc_csn3 */
+ <3 RK_PD2 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data0: dsmc-data0 {
+ rockchip,pins =
+ /* dsmc_data0 */
+ <3 RK_PD4 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data1: dsmc-data1 {
+ rockchip,pins =
+ /* dsmc_data1 */
+ <3 RK_PD0 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data2: dsmc-data2 {
+ rockchip,pins =
+ /* dsmc_data2 */
+ <3 RK_PC7 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data3: dsmc-data3 {
+ rockchip,pins =
+ /* dsmc_data3 */
+ <3 RK_PC6 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data4: dsmc-data4 {
+ rockchip,pins =
+ /* dsmc_data4 */
+ <3 RK_PC5 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data5: dsmc-data5 {
+ rockchip,pins =
+ /* dsmc_data5 */
+ <3 RK_PC4 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data6: dsmc-data6 {
+ rockchip,pins =
+ /* dsmc_data6 */
+ <3 RK_PC1 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data7: dsmc-data7 {
+ rockchip,pins =
+ /* dsmc_data7 */
+ <3 RK_PC0 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data8: dsmc-data8 {
+ rockchip,pins =
+ /* dsmc_data8 */
+ <3 RK_PB5 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data9: dsmc-data9 {
+ rockchip,pins =
+ /* dsmc_data9 */
+ <3 RK_PB4 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data10: dsmc-data10 {
+ rockchip,pins =
+ /* dsmc_data10 */
+ <3 RK_PB3 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data11: dsmc-data11 {
+ rockchip,pins =
+ /* dsmc_data11 */
+ <3 RK_PB2 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data12: dsmc-data12 {
+ rockchip,pins =
+ /* dsmc_data12 */
+ <3 RK_PB1 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data13: dsmc-data13 {
+ rockchip,pins =
+ /* dsmc_data13 */
+ <3 RK_PA7 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data14: dsmc-data14 {
+ rockchip,pins =
+ /* dsmc_data14 */
+ <3 RK_PA6 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_data15: dsmc-data15 {
+ rockchip,pins =
+ /* dsmc_data15 */
+ <3 RK_PA5 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_dqs0: dsmc-dqs0 {
+ rockchip,pins =
+ /* dsmc_dqs0 */
+ <3 RK_PB7 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_dqs1: dsmc-dqs1 {
+ rockchip,pins =
+ /* dsmc_dqs1 */
+ <3 RK_PB6 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_int0: dsmc-int0 {
+ rockchip,pins =
+ /* dsmc_int0 */
+ <4 RK_PA0 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_int1: dsmc-int1 {
+ rockchip,pins =
+ /* dsmc_int1 */
+ <3 RK_PC2 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_int2: dsmc-int2 {
+ rockchip,pins =
+ /* dsmc_int2 */
+ <4 RK_PA1 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_int3: dsmc-int3 {
+ rockchip,pins =
+ /* dsmc_int3 */
+ <3 RK_PC3 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_rdyn: dsmc-rdyn {
+ rockchip,pins =
+ /* dsmc_rdyn */
+ <3 RK_PA4 5 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ dsmc_resetn: dsmc-resetn {
+ rockchip,pins =
+ /* dsmc_resetn */
+ <3 RK_PD7 5 &pcfg_pull_none>;
+ };
+ };
+
+ dsmc_testclk {
+ /omit-if-no-ref/
+ dsmc_testclk_out: dsmc-testclk-out {
+ rockchip,pins =
+ /* dsmc_testclk_out */
+ <3 RK_PC2 7 &pcfg_pull_none>;
+ };
+ };
+
+ dsmc_testdata {
+ /omit-if-no-ref/
+ dsmc_testdata_out: dsmc-testdata-out {
+ rockchip,pins =
+ /* dsmc_testdata_out */
+ <3 RK_PC3 7 &pcfg_pull_none>;
+ };
+ };
+
+ edp_tx {
+ /omit-if-no-ref/
+ edp_txm0_pins: edp_txm0-pins {
+ rockchip,pins =
+ /* edp_tx_hpdin_m0 */
+ <4 RK_PC1 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ edp_txm1_pins: edp_txm1-pins {
+ rockchip,pins =
+ /* edp_tx_hpdin_m1 */
+ <0 RK_PB6 10 &pcfg_pull_none>;
+ };
+ };
+
+ emmc {
+ /omit-if-no-ref/
+ emmc_rstnout: emmc-rstnout {
+ rockchip,pins =
+ /* emmc_rstn */
+ <1 RK_PB3 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ emmc_bus8: emmc-bus8 {
+ rockchip,pins =
+ /* emmc_d0 */
+ <1 RK_PA0 1 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d1 */
+ <1 RK_PA1 1 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d2 */
+ <1 RK_PA2 1 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d3 */
+ <1 RK_PA3 1 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d4 */
+ <1 RK_PA4 1 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d5 */
+ <1 RK_PA5 1 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d6 */
+ <1 RK_PA6 1 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d7 */
+ <1 RK_PA7 1 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ emmc_clk: emmc-clk {
+ rockchip,pins =
+ /* emmc_clk */
+ <1 RK_PB1 1 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ emmc_cmd: emmc-cmd {
+ rockchip,pins =
+ /* emmc_cmd */
+ <1 RK_PB0 1 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ emmc_strb: emmc-strb {
+ rockchip,pins =
+ /* emmc_strb */
+ <1 RK_PB2 1 &pcfg_pull_none>;
+ };
+ };
+
+ emmc_testclk {
+ /omit-if-no-ref/
+ emmc_testclk_test: emmc_testclk-test {
+ rockchip,pins =
+ /* emmc_testclk_out */
+ <1 RK_PB3 6 &pcfg_pull_none>;
+ };
+ };
+
+ emmc_testdata {
+ /omit-if-no-ref/
+ emmc_testdata_test: emmc_testdata-test {
+ rockchip,pins =
+ /* emmc_testdata_out */
+ <1 RK_PB7 5 &pcfg_pull_none>;
+ };
+ };
+
+ eth0 {
+ /omit-if-no-ref/
+ eth0m0_miim: eth0m0-miim {
+ rockchip,pins =
+ /* eth0_mdc_m0 */
+ <3 RK_PA6 3 &pcfg_pull_none>,
+ /* eth0_mdio_m0 */
+ <3 RK_PA5 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m0_rx_bus2: eth0m0-rx_bus2 {
+ rockchip,pins =
+ /* eth0_rxctl_m0 */
+ <3 RK_PA7 3 &pcfg_pull_none>,
+ /* eth0_rxd0_m0 */
+ <3 RK_PB2 3 &pcfg_pull_none>,
+ /* eth0_rxd1_m0 */
+ <3 RK_PB1 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m0_tx_bus2: eth0m0-tx_bus2 {
+ rockchip,pins =
+ /* eth0_txctl_m0 */
+ <3 RK_PB3 3 &pcfg_pull_none>,
+ /* eth0_txd0_m0 */
+ <3 RK_PB5 3 &pcfg_pull_none>,
+ /* eth0_txd1_m0 */
+ <3 RK_PB4 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m0_rgmii_clk: eth0m0-rgmii_clk {
+ rockchip,pins =
+ /* eth0_rxclk_m0 */
+ <3 RK_PD1 3 &pcfg_pull_none>,
+ /* eth0_txclk_m0 */
+ <3 RK_PB6 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m0_rgmii_bus: eth0m0-rgmii_bus {
+ rockchip,pins =
+ /* eth0_rxd2_m0 */
+ <3 RK_PD3 3 &pcfg_pull_none>,
+ /* eth0_rxd3_m0 */
+ <3 RK_PD2 3 &pcfg_pull_none>,
+ /* eth0_txd2_m0 */
+ <3 RK_PC3 3 &pcfg_pull_none>,
+ /* eth0_txd3_m0 */
+ <3 RK_PC2 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m0_mclk: eth0m0-mclk {
+ rockchip,pins =
+ /* eth0m0_mclk */
+ <3 RK_PB0 3 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth0m0_ppsclk: eth0m0-ppsclk {
+ rockchip,pins =
+ /* eth0m0_ppsclk */
+ <3 RK_PC0 3 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth0m0_ppstrig: eth0m0-ppstrig {
+ rockchip,pins =
+ /* eth0m0_ppstrig */
+ <3 RK_PB7 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m1_miim: eth0m1-miim {
+ rockchip,pins =
+ /* eth0_mdc_m1 */
+ <3 RK_PA1 3 &pcfg_pull_none>,
+ /* eth0_mdio_m1 */
+ <3 RK_PA0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m1_rx_bus2: eth0m1-rx_bus2 {
+ rockchip,pins =
+ /* eth0_rxctl_m1 */
+ <3 RK_PA2 3 &pcfg_pull_none>,
+ /* eth0_rxd0_m1 */
+ <2 RK_PA6 3 &pcfg_pull_none>,
+ /* eth0_rxd1_m1 */
+ <3 RK_PA3 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m1_tx_bus2: eth0m1-tx_bus2 {
+ rockchip,pins =
+ /* eth0_txctl_m1 */
+ <2 RK_PA7 3 &pcfg_pull_none>,
+ /* eth0_txd0_m1 */
+ <2 RK_PB1 3 &pcfg_pull_none>,
+ /* eth0_txd1_m1 */
+ <2 RK_PB0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m1_rgmii_clk: eth0m1-rgmii_clk {
+ rockchip,pins =
+ /* eth0_rxclk_m1 */
+ <2 RK_PB5 3 &pcfg_pull_none>,
+ /* eth0_txclk_m1 */
+ <2 RK_PB3 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m1_rgmii_bus: eth0m1-rgmii_bus {
+ rockchip,pins =
+ /* eth0_rxd2_m1 */
+ <2 RK_PB7 3 &pcfg_pull_none>,
+ /* eth0_rxd3_m1 */
+ <2 RK_PB6 3 &pcfg_pull_none>,
+ /* eth0_txd2_m1 */
+ <2 RK_PB4 3 &pcfg_pull_none>,
+ /* eth0_txd3_m1 */
+ <2 RK_PB2 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m1_mclk: eth0m1-mclk {
+ rockchip,pins =
+ /* eth0m1_mclk */
+ <2 RK_PD6 3 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth0m1_ppsclk: eth0m1-ppsclk {
+ rockchip,pins =
+ /* eth0m1_ppsclk */
+ <2 RK_PC1 3 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth0m1_ppstrig: eth0m1-ppstrig {
+ rockchip,pins =
+ /* eth0m1_ppstrig */
+ <2 RK_PC2 3 &pcfg_pull_none>;
+ };
+ };
+
+ eth1 {
+ /omit-if-no-ref/
+ eth1m0_miim: eth1m0-miim {
+ rockchip,pins =
+ /* eth1_mdc_m0 */
+ <2 RK_PD4 2 &pcfg_pull_none>,
+ /* eth1_mdio_m0 */
+ <2 RK_PD5 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m0_rx_bus2: eth1m0-rx_bus2 {
+ rockchip,pins =
+ /* eth1_rxctl_m0 */
+ <2 RK_PD3 2 &pcfg_pull_none>,
+ /* eth1_rxd0_m0 */
+ <2 RK_PD1 2 &pcfg_pull_none>,
+ /* eth1_rxd1_m0 */
+ <2 RK_PD2 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m0_tx_bus2: eth1m0-tx_bus2 {
+ rockchip,pins =
+ /* eth1_txctl_m0 */
+ <2 RK_PD0 2 &pcfg_pull_none>,
+ /* eth1_txd0_m0 */
+ <2 RK_PC6 2 &pcfg_pull_none>,
+ /* eth1_txd1_m0 */
+ <2 RK_PC7 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m0_rgmii_clk: eth1m0-rgmii_clk {
+ rockchip,pins =
+ /* eth1_rxclk_m0 */
+ <2 RK_PC2 2 &pcfg_pull_none>,
+ /* eth1_txclk_m0 */
+ <2 RK_PC5 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m0_rgmii_bus: eth1m0-rgmii_bus {
+ rockchip,pins =
+ /* eth1_rxd2_m0 */
+ <2 RK_PC0 2 &pcfg_pull_none>,
+ /* eth1_rxd3_m0 */
+ <2 RK_PC1 2 &pcfg_pull_none>,
+ /* eth1_txd2_m0 */
+ <2 RK_PC3 2 &pcfg_pull_none>,
+ /* eth1_txd3_m0 */
+ <2 RK_PC4 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m0_mclk: eth1m0-mclk {
+ rockchip,pins =
+ /* eth1m0_mclk */
+ <2 RK_PD7 2 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth1m0_ppsclk: eth1m0-ppsclk {
+ rockchip,pins =
+ /* eth1m0_ppsclk */
+ <3 RK_PA2 2 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth1m0_ppstrig: eth1m0-ppstrig {
+ rockchip,pins =
+ /* eth1m0_ppstrig */
+ <3 RK_PA1 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m1_miim: eth1m1-miim {
+ rockchip,pins =
+ /* eth1_mdc_m1 */
+ <1 RK_PD2 1 &pcfg_pull_none>,
+ /* eth1_mdio_m1 */
+ <1 RK_PD3 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m1_rx_bus2: eth1m1-rx_bus2 {
+ rockchip,pins =
+ /* eth1_rxctl_m1 */
+ <1 RK_PD1 1 &pcfg_pull_none>,
+ /* eth1_rxd0_m1 */
+ <1 RK_PC7 1 &pcfg_pull_none>,
+ /* eth1_rxd1_m1 */
+ <1 RK_PD0 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m1_tx_bus2: eth1m1-tx_bus2 {
+ rockchip,pins =
+ /* eth1_txctl_m1 */
+ <1 RK_PC6 1 &pcfg_pull_none>,
+ /* eth1_txd0_m1 */
+ <1 RK_PC4 1 &pcfg_pull_none>,
+ /* eth1_txd1_m1 */
+ <1 RK_PC5 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m1_rgmii_clk: eth1m1-rgmii_clk {
+ rockchip,pins =
+ /* eth1_rxclk_m1 */
+ <1 RK_PB6 1 &pcfg_pull_none>,
+ /* eth1_txclk_m1 */
+ <1 RK_PC1 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m1_rgmii_bus: eth1m1-rgmii_bus {
+ rockchip,pins =
+ /* eth1_rxd2_m1 */
+ <1 RK_PB4 1 &pcfg_pull_none>,
+ /* eth1_rxd3_m1 */
+ <1 RK_PB5 1 &pcfg_pull_none>,
+ /* eth1_txd2_m1 */
+ <1 RK_PB7 1 &pcfg_pull_none>,
+ /* eth1_txd3_m1 */
+ <1 RK_PC0 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m1_mclk: eth1m1-mclk {
+ rockchip,pins =
+ /* eth1m1_mclk */
+ <1 RK_PD4 1 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth1m1_ppsclk: eth1m1-ppsclk {
+ rockchip,pins =
+ /* eth1m1_ppsclk */
+ <1 RK_PC2 1 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ eth1m1_ppstrig: eth1m1-ppstrig {
+ rockchip,pins =
+ /* eth1m1_ppstrig */
+ <1 RK_PC3 1 &pcfg_pull_none>;
+ };
+ };
+
+ eth0_ptp {
+ /omit-if-no-ref/
+ eth0m0_ptp_refclk: eth0m0-ptp-refclk {
+ rockchip,pins =
+ /* eth0m0_ptp_refclk */
+ <3 RK_PC1 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0m1_ptp_refclk: eth0m1-ptp-refclk {
+ rockchip,pins =
+ /* eth0m1_ptp_refclk */
+ <2 RK_PC0 3 &pcfg_pull_none>;
+ };
+ };
+
+ eth0_testrxclk {
+ /omit-if-no-ref/
+ eth0_testrxclkm0_test: eth0_testrxclkm0-test {
+ rockchip,pins =
+ /* eth0_testrxclk_out_m0 */
+ <3 RK_PC7 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0_testrxclkm1_test: eth0_testrxclkm1-test {
+ rockchip,pins =
+ /* eth0_testrxclk_out_m1 */
+ <2 RK_PC5 6 &pcfg_pull_none>;
+ };
+ };
+
+ eth0_testrxd {
+ /omit-if-no-ref/
+ eth0_testrxdm0_test: eth0_testrxdm0-test {
+ rockchip,pins =
+ /* eth0_testrxd_out_m0 */
+ <3 RK_PD0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth0_testrxdm1_test: eth0_testrxdm1-test {
+ rockchip,pins =
+ /* eth0_testrxd_out_m1 */
+ <2 RK_PC4 6 &pcfg_pull_none>;
+ };
+ };
+
+ eth1_ptp {
+ /omit-if-no-ref/
+ eth1m0_ptp_refclk: eth1m0-ptp-refclk {
+ rockchip,pins =
+ /* eth1m0_ptp_refclk */
+ <3 RK_PA3 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1m1_ptp_refclk: eth1m1-ptp-refclk {
+ rockchip,pins =
+ /* eth1m1_ptp_refclk */
+ <2 RK_PB6 2 &pcfg_pull_none>;
+ };
+ };
+
+ eth1_testrxclk {
+ /omit-if-no-ref/
+ eth1_testrxclkm0_test: eth1_testrxclkm0-test {
+ rockchip,pins =
+ /* eth1_testrxclk_out_m0 */
+ <3 RK_PA1 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1_testrxclkm1_test: eth1_testrxclkm1-test {
+ rockchip,pins =
+ /* eth1_testrxclk_out_m1 */
+ <1 RK_PC3 6 &pcfg_pull_none>;
+ };
+ };
+
+ eth1_testrxd {
+ /omit-if-no-ref/
+ eth1_testrxdm0_test: eth1_testrxdm0-test {
+ rockchip,pins =
+ /* eth1_testrxd_out_m0 */
+ <3 RK_PA0 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ eth1_testrxdm1_test: eth1_testrxdm1-test {
+ rockchip,pins =
+ /* eth1_testrxd_out_m1 */
+ <1 RK_PC2 6 &pcfg_pull_none>;
+ };
+ };
+
+ eth_clk0_25m {
+ /omit-if-no-ref/
+ ethm0_clk0_25m_out: ethm0-clk0-25m-out {
+ rockchip,pins =
+ /* ethm0_clk0_25m_out */
+ <3 RK_PA4 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ ethm1_clk0_25m_out: ethm1-clk0-25m-out {
+ rockchip,pins =
+ /* ethm1_clk0_25m_out */
+ <2 RK_PD7 3 &pcfg_pull_none>;
+ };
+ };
+
+ eth_clk1_25m {
+ /omit-if-no-ref/
+ ethm0_clk1_25m_out: ethm0-clk1-25m-out {
+ rockchip,pins =
+ /* ethm0_clk1_25m_out */
+ <2 RK_PD6 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ ethm1_clk1_25m_out: ethm1-clk1-25m-out {
+ rockchip,pins =
+ /* ethm1_clk1_25m_out */
+ <1 RK_PD5 1 &pcfg_pull_none>;
+ };
+ };
+
+ flexbus0 {
+ /omit-if-no-ref/
+ flexbus0m0_csn: flexbus0m0-csn {
+ rockchip,pins =
+ /* flexbus0_csn_m0 */
+ <3 RK_PA4 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m0_d13: flexbus0m0-d13 {
+ rockchip,pins =
+ /* flexbus0_d13_m0 */
+ <4 RK_PA0 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m0_d14: flexbus0m0-d14 {
+ rockchip,pins =
+ /* flexbus0_d14_m0 */
+ <4 RK_PA1 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m0_d15: flexbus0m0-d15 {
+ rockchip,pins =
+ /* flexbus0_d15_m0 */
+ <3 RK_PD7 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m1_csn: flexbus0m1-csn {
+ rockchip,pins =
+ /* flexbus0_csn_m1 */
+ <4 RK_PA1 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m1_d13: flexbus0m1-d13 {
+ rockchip,pins =
+ /* flexbus0_d13_m1 */
+ <4 RK_PA4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m1_d14: flexbus0m1-d14 {
+ rockchip,pins =
+ /* flexbus0_d14_m1 */
+ <4 RK_PA6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m1_d15: flexbus0m1-d15 {
+ rockchip,pins =
+ /* flexbus0_d15_m1 */
+ <4 RK_PB5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m2_csn: flexbus0m2-csn {
+ rockchip,pins =
+ /* flexbus0_csn_m2 */
+ <3 RK_PC3 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m3_csn: flexbus0m3-csn {
+ rockchip,pins =
+ /* flexbus0_csn_m3 */
+ <3 RK_PD2 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0m4_csn: flexbus0m4-csn {
+ rockchip,pins =
+ /* flexbus0_csn_m4 */
+ <4 RK_PB4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_clk: flexbus0-clk {
+ rockchip,pins =
+ /* flexbus0_clk */
+ <3 RK_PB6 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d10: flexbus0-d10 {
+ rockchip,pins =
+ /* flexbus0_d10 */
+ <3 RK_PC3 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d11: flexbus0-d11 {
+ rockchip,pins =
+ /* flexbus0_d11 */
+ <3 RK_PD1 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d12: flexbus0-d12 {
+ rockchip,pins =
+ /* flexbus0_d12 */
+ <3 RK_PD2 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d0: flexbus0-d0 {
+ rockchip,pins =
+ /* flexbus0_d0 */
+ <3 RK_PB5 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d1: flexbus0-d1 {
+ rockchip,pins =
+ /* flexbus0_d1 */
+ <3 RK_PB4 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d2: flexbus0-d2 {
+ rockchip,pins =
+ /* flexbus0_d2 */
+ <3 RK_PB3 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d3: flexbus0-d3 {
+ rockchip,pins =
+ /* flexbus0_d3 */
+ <3 RK_PB2 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d4: flexbus0-d4 {
+ rockchip,pins =
+ /* flexbus0_d4 */
+ <3 RK_PB1 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d5: flexbus0-d5 {
+ rockchip,pins =
+ /* flexbus0_d5 */
+ <3 RK_PA7 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d6: flexbus0-d6 {
+ rockchip,pins =
+ /* flexbus0_d6 */
+ <3 RK_PA6 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d7: flexbus0-d7 {
+ rockchip,pins =
+ /* flexbus0_d7 */
+ <3 RK_PA5 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d8: flexbus0-d8 {
+ rockchip,pins =
+ /* flexbus0_d8 */
+ <3 RK_PB0 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus0_d9: flexbus0-d9 {
+ rockchip,pins =
+ /* flexbus0_d9 */
+ <3 RK_PC2 6 &pcfg_pull_none>;
+ };
+ };
+
+ flexbus1 {
+ /omit-if-no-ref/
+ flexbus1m0_csn: flexbus1m0-csn {
+ rockchip,pins =
+ /* flexbus1_csn_m0 */
+ <3 RK_PB7 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m0_d12: flexbus1m0-d12 {
+ rockchip,pins =
+ /* flexbus1_d12_m0 */
+ <3 RK_PD7 7 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m0_d13: flexbus1m0-d13 {
+ rockchip,pins =
+ /* flexbus1_d13_m0 */
+ <4 RK_PA1 7 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m0_d14: flexbus1m0-d14 {
+ rockchip,pins =
+ /* flexbus1_d14_m0 */
+ <4 RK_PA0 7 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m0_d15: flexbus1m0-d15 {
+ rockchip,pins =
+ /* flexbus1_d15_m0 */
+ <3 RK_PD2 7 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m1_csn: flexbus1m1-csn {
+ rockchip,pins =
+ /* flexbus1_csn_m1 */
+ <3 RK_PD7 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m1_d12: flexbus1m1-d12 {
+ rockchip,pins =
+ /* flexbus1_d12_m1 */
+ <4 RK_PA5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m1_d13: flexbus1m1-d13 {
+ rockchip,pins =
+ /* flexbus1_d13_m1 */
+ <4 RK_PB0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m1_d14: flexbus1m1-d14 {
+ rockchip,pins =
+ /* flexbus1_d14_m1 */
+ <4 RK_PB1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m1_d15: flexbus1m1-d15 {
+ rockchip,pins =
+ /* flexbus1_d15_m1 */
+ <4 RK_PB2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m2_csn: flexbus1m2-csn {
+ rockchip,pins =
+ /* flexbus1_csn_m2 */
+ <3 RK_PD1 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m3_csn: flexbus1m3-csn {
+ rockchip,pins =
+ /* flexbus1_csn_m3 */
+ <4 RK_PA0 8 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1m4_csn: flexbus1m4-csn {
+ rockchip,pins =
+ /* flexbus1_csn_m4 */
+ <4 RK_PA3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_clk: flexbus1-clk {
+ rockchip,pins =
+ /* flexbus1_clk */
+ <3 RK_PD6 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d10: flexbus1-d10 {
+ rockchip,pins =
+ /* flexbus1_d10 */
+ <3 RK_PB7 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d11: flexbus1-d11 {
+ rockchip,pins =
+ /* flexbus1_d11 */
+ <3 RK_PA4 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d0: flexbus1-d0 {
+ rockchip,pins =
+ /* flexbus1_d0 */
+ <3 RK_PD5 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d1: flexbus1-d1 {
+ rockchip,pins =
+ /* flexbus1_d1 */
+ <3 RK_PD4 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d2: flexbus1-d2 {
+ rockchip,pins =
+ /* flexbus1_d2 */
+ <3 RK_PD3 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d3: flexbus1-d3 {
+ rockchip,pins =
+ /* flexbus1_d3 */
+ <3 RK_PD0 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d4: flexbus1-d4 {
+ rockchip,pins =
+ /* flexbus1_d4 */
+ <3 RK_PC7 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d5: flexbus1-d5 {
+ rockchip,pins =
+ /* flexbus1_d5 */
+ <3 RK_PC6 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d6: flexbus1-d6 {
+ rockchip,pins =
+ /* flexbus1_d6 */
+ <3 RK_PC5 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d7: flexbus1-d7 {
+ rockchip,pins =
+ /* flexbus1_d7 */
+ <3 RK_PC4 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d8: flexbus1-d8 {
+ rockchip,pins =
+ /* flexbus1_d8 */
+ <3 RK_PC1 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ flexbus1_d9: flexbus1-d9 {
+ rockchip,pins =
+ /* flexbus1_d9 */
+ <3 RK_PC0 6 &pcfg_pull_none>;
+ };
+ };
+
+ flexbus0_testclk {
+ /omit-if-no-ref/
+ flexbus0_testclk_testclk: flexbus0_testclk-testclk {
+ rockchip,pins =
+ /* flexbus0_testclk_out */
+ <2 RK_PA3 6 &pcfg_pull_none>;
+ };
+ };
+
+ flexbus0_testdata {
+ /omit-if-no-ref/
+ flexbus0_testdata_testdata: flexbus0_testdata-testdata {
+ rockchip,pins =
+ /* flexbus0_testdata_out */
+ <2 RK_PA2 6 &pcfg_pull_none>;
+ };
+ };
+
+ flexbus1_testclk {
+ /omit-if-no-ref/
+ flexbus1_testclk_testclk: flexbus1_testclk-testclk {
+ rockchip,pins =
+ /* flexbus1_testclk_out */
+ <2 RK_PA5 6 &pcfg_pull_none>;
+ };
+ };
+
+ flexbus1_testdata {
+ /omit-if-no-ref/
+ flexbus1_testdata_testdata: flexbus1_testdata-testdata {
+ rockchip,pins =
+ /* flexbus1_testdata_out */
+ <2 RK_PA4 6 &pcfg_pull_none>;
+ };
+ };
+
+ fspi0 {
+ /omit-if-no-ref/
+ fspi0_pins: fspi0-pins {
+ rockchip,pins =
+ /* fspi0_clk */
+ <1 RK_PB1 2 &pcfg_pull_none>,
+ /* fspi0_d0 */
+ <1 RK_PA0 2 &pcfg_pull_none>,
+ /* fspi0_d1 */
+ <1 RK_PA1 2 &pcfg_pull_none>,
+ /* fspi0_d2 */
+ <1 RK_PA2 2 &pcfg_pull_none>,
+ /* fspi0_d3 */
+ <1 RK_PA3 2 &pcfg_pull_none>,
+ /* fspi0_d4 */
+ <1 RK_PA4 2 &pcfg_pull_none>,
+ /* fspi0_d5 */
+ <1 RK_PA5 2 &pcfg_pull_none>,
+ /* fspi0_d6 */
+ <1 RK_PA6 2 &pcfg_pull_none>,
+ /* fspi0_d7 */
+ <1 RK_PA7 2 &pcfg_pull_none>,
+ /* fspi0_dqs */
+ <1 RK_PB2 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ fspi0_csn0: fspi0-csn0 {
+ rockchip,pins =
+ /* fspi0_csn0 */
+ <1 RK_PB3 2 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ fspi0_csn1: fspi0-csn1 {
+ rockchip,pins =
+ /* fspi0_csn1 */
+ <1 RK_PB0 2 &pcfg_pull_none>;
+ };
+ };
+
+ fspi1 {
+ /omit-if-no-ref/
+ fspi1m0_pins: fspi1m0-pins {
+ rockchip,pins =
+ /* fspi1_clk_m0 */
+ <2 RK_PA5 2 &pcfg_pull_none>,
+ /* fspi1_d0_m0 */
+ <2 RK_PA0 2 &pcfg_pull_none>,
+ /* fspi1_d1_m0 */
+ <2 RK_PA1 2 &pcfg_pull_none>,
+ /* fspi1_d2_m0 */
+ <2 RK_PA2 2 &pcfg_pull_none>,
+ /* fspi1_d3_m0 */
+ <2 RK_PA3 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ fspi1m0_csn0: fspi1m0-csn0 {
+ rockchip,pins =
+ /* fspi1m0_csn0 */
+ <2 RK_PA4 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ fspi1m1_pins: fspi1m1-pins {
+ rockchip,pins =
+ /* fspi1_clk_m1 */
+ <1 RK_PD5 3 &pcfg_pull_none>,
+ /* fspi1_d0_m1 */
+ <1 RK_PC4 3 &pcfg_pull_none>,
+ /* fspi1_d1_m1 */
+ <1 RK_PC5 3 &pcfg_pull_none>,
+ /* fspi1_d2_m1 */
+ <1 RK_PC6 3 &pcfg_pull_none>,
+ /* fspi1_d3_m1 */
+ <1 RK_PC7 3 &pcfg_pull_none>,
+ /* fspi1_d4_m1 */
+ <1 RK_PD0 3 &pcfg_pull_none>,
+ /* fspi1_d5_m1 */
+ <1 RK_PD1 3 &pcfg_pull_none>,
+ /* fspi1_d6_m1 */
+ <1 RK_PD2 3 &pcfg_pull_none>,
+ /* fspi1_d7_m1 */
+ <1 RK_PD3 3 &pcfg_pull_none>,
+ /* fspi1_dqs_m1 */
+ <1 RK_PD4 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ fspi1m1_csn0: fspi1m1-csn0 {
+ rockchip,pins =
+ /* fspi1m1_csn0 */
+ <1 RK_PC3 3 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ fspi1m1_csn1: fspi1m1-csn1 {
+ rockchip,pins =
+ /* fspi1m1_csn1 */
+ <1 RK_PC2 3 &pcfg_pull_none>;
+ };
+ };
+
+ fspi0_testclk {
+ /omit-if-no-ref/
+ fspi0_testclk_test: fspi0_testclk-test {
+ rockchip,pins =
+ /* fspi0_testclk_out */
+ <1 RK_PB0 6 &pcfg_pull_none>;
+ };
+ };
+
+ fspi0_testdata {
+ /omit-if-no-ref/
+ fspi0_testdata_test: fspi0_testdata-test {
+ rockchip,pins =
+ /* fspi0_testdata_out */
+ <1 RK_PB7 6 &pcfg_pull_none>;
+ };
+ };
+
+ fspi1_testclk {
+ /omit-if-no-ref/
+ fspi1_testclkm1_test: fspi1_testclkm1-test {
+ rockchip,pins =
+ /* fspi1_testclk_out_m1 */
+ <1 RK_PC1 7 &pcfg_pull_none>;
+ };
+ };
+
+ fspi1_testdata {
+ /omit-if-no-ref/
+ fspi1_testdatam1_test: fspi1_testdatam1-test {
+ rockchip,pins =
+ /* fspi1_testdata_out_m1 */
+ <1 RK_PB7 7 &pcfg_pull_none>;
+ };
+ };
+
+ gpu {
+ /omit-if-no-ref/
+ gpu_pins: gpu-pins {
+ rockchip,pins =
+ /* gpu_avs */
+ <0 RK_PD3 11 &pcfg_pull_none>;
+ };
+ };
+
+ hdmi_tx {
+ /omit-if-no-ref/
+ hdmi_txm0_pins: hdmi_txm0-pins {
+ rockchip,pins =
+ /* hdmi_tx_cec_m0 */
+ <4 RK_PC0 9 &pcfg_pull_none>,
+ /* hdmi_tx_hpdin_m0 */
+ <4 RK_PC1 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ hdmi_txm1_pins: hdmi_txm1-pins {
+ rockchip,pins =
+ /* hdmi_tx_cec_m1 */
+ <0 RK_PC3 9 &pcfg_pull_none>,
+ /* hdmi_tx_hpdin_m1 */
+ <0 RK_PB6 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ hdmi_tx_scl: hdmi-tx-scl {
+ rockchip,pins =
+ /* hdmi_tx_scl */
+ <4 RK_PC2 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ hdmi_tx_sda: hdmi-tx-sda {
+ rockchip,pins =
+ /* hdmi_tx_sda */
+ <4 RK_PC3 9 &pcfg_pull_none>;
+ };
+ };
+
+ i2c0 {
+ /omit-if-no-ref/
+ i2c0m0_xfer: i2c0m0-xfer {
+ rockchip,pins =
+ /* i2c0_scl_m0 */
+ <0 RK_PB0 11 &pcfg_pull_none_smt>,
+ /* i2c0_sda_m0 */
+ <0 RK_PB1 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c0m1_xfer: i2c0m1-xfer {
+ rockchip,pins =
+ /* i2c0_scl_m1 */
+ <0 RK_PC1 9 &pcfg_pull_none_smt>,
+ /* i2c0_sda_m1 */
+ <0 RK_PC2 9 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c1 {
+ /omit-if-no-ref/
+ i2c1m0_xfer: i2c1m0-xfer {
+ rockchip,pins =
+ /* i2c1_scl_m0 */
+ <0 RK_PB2 11 &pcfg_pull_none_smt>,
+ /* i2c1_sda_m0 */
+ <0 RK_PB3 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c1m1_xfer: i2c1m1-xfer {
+ rockchip,pins =
+ /* i2c1_scl_m1 */
+ <0 RK_PB4 9 &pcfg_pull_none_smt>,
+ /* i2c1_sda_m1 */
+ <0 RK_PB5 9 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c2 {
+ /omit-if-no-ref/
+ i2c2m0_xfer: i2c2m0-xfer {
+ rockchip,pins =
+ /* i2c2_scl_m0 */
+ <0 RK_PB7 9 &pcfg_pull_none_smt>,
+ /* i2c2_sda_m0 */
+ <0 RK_PC0 9 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c2m1_xfer: i2c2m1-xfer {
+ rockchip,pins =
+ /* i2c2_scl_m1 */
+ <1 RK_PA0 10 &pcfg_pull_none_smt>,
+ /* i2c2_sda_m1 */
+ <1 RK_PA1 10 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c2m2_xfer: i2c2m2-xfer {
+ rockchip,pins =
+ /* i2c2_scl_m2 */
+ <4 RK_PA3 11 &pcfg_pull_none_smt>,
+ /* i2c2_sda_m2 */
+ <4 RK_PA5 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c2m3_xfer: i2c2m3-xfer {
+ rockchip,pins =
+ /* i2c2_scl_m3 */
+ <4 RK_PC2 11 &pcfg_pull_none_smt>,
+ /* i2c2_sda_m3 */
+ <4 RK_PC3 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c3 {
+ /omit-if-no-ref/
+ i2c3m0_xfer: i2c3m0-xfer {
+ rockchip,pins =
+ /* i2c3_scl_m0 */
+ <4 RK_PB5 11 &pcfg_pull_none_smt>,
+ /* i2c3_sda_m0 */
+ <4 RK_PB4 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c3m1_xfer: i2c3m1-xfer {
+ rockchip,pins =
+ /* i2c3_scl_m1 */
+ <0 RK_PC6 9 &pcfg_pull_none_smt>,
+ /* i2c3_sda_m1 */
+ <0 RK_PC7 9 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c3m2_xfer: i2c3m2-xfer {
+ rockchip,pins =
+ /* i2c3_scl_m2 */
+ <3 RK_PD4 11 &pcfg_pull_none_smt>,
+ /* i2c3_sda_m2 */
+ <3 RK_PD5 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c3m3_xfer: i2c3m3-xfer {
+ rockchip,pins =
+ /* i2c3_scl_m3 */
+ <4 RK_PC4 11 &pcfg_pull_none_smt>,
+ /* i2c3_sda_m3 */
+ <4 RK_PC5 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c4 {
+ /omit-if-no-ref/
+ i2c4m0_xfer: i2c4m0-xfer {
+ rockchip,pins =
+ /* i2c4_scl_m0 */
+ <0 RK_PD2 9 &pcfg_pull_none_smt>,
+ /* i2c4_sda_m0 */
+ <0 RK_PD3 9 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c4m1_xfer: i2c4m1-xfer {
+ rockchip,pins =
+ /* i2c4_scl_m1 */
+ <4 RK_PA4 11 &pcfg_pull_none_smt>,
+ /* i2c4_sda_m1 */
+ <4 RK_PA6 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c4m2_xfer: i2c4m2-xfer {
+ rockchip,pins =
+ /* i2c4_scl_m2 */
+ <2 RK_PA6 11 &pcfg_pull_none_smt>,
+ /* i2c4_sda_m2 */
+ <2 RK_PA7 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c4m3_xfer: i2c4m3-xfer {
+ rockchip,pins =
+ /* i2c4_scl_m3 */
+ <3 RK_PC0 11 &pcfg_pull_none_smt>,
+ /* i2c4_sda_m3 */
+ <3 RK_PB7 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c5 {
+ /omit-if-no-ref/
+ i2c5m0_xfer: i2c5m0-xfer {
+ rockchip,pins =
+ /* i2c5_scl_m0 */
+ <2 RK_PA5 11 &pcfg_pull_none_smt>,
+ /* i2c5_sda_m0 */
+ <2 RK_PA4 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c5m1_xfer: i2c5m1-xfer {
+ rockchip,pins =
+ /* i2c5_scl_m1 */
+ <1 RK_PD4 10 &pcfg_pull_none_smt>,
+ /* i2c5_sda_m1 */
+ <1 RK_PD5 10 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c5m2_xfer: i2c5m2-xfer {
+ rockchip,pins =
+ /* i2c5_scl_m2 */
+ <2 RK_PC6 11 &pcfg_pull_none_smt>,
+ /* i2c5_sda_m2 */
+ <2 RK_PC7 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c5m3_xfer: i2c5m3-xfer {
+ rockchip,pins =
+ /* i2c5_scl_m3 */
+ <3 RK_PC4 11 &pcfg_pull_none_smt>,
+ /* i2c5_sda_m3 */
+ <3 RK_PC1 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c6 {
+ /omit-if-no-ref/
+ i2c6m0_xfer: i2c6m0-xfer {
+ rockchip,pins =
+ /* i2c6_scl_m0 */
+ <0 RK_PA2 11 &pcfg_pull_none_smt>,
+ /* i2c6_sda_m0 */
+ <0 RK_PA5 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c6m1_xfer: i2c6m1-xfer {
+ rockchip,pins =
+ /* i2c6_scl_m1 */
+ <1 RK_PC2 10 &pcfg_pull_none_smt>,
+ /* i2c6_sda_m1 */
+ <1 RK_PC3 10 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c6m2_xfer: i2c6m2-xfer {
+ rockchip,pins =
+ /* i2c6_scl_m2 */
+ <2 RK_PD0 11 &pcfg_pull_none_smt>,
+ /* i2c6_sda_m2 */
+ <2 RK_PD1 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c6m3_xfer: i2c6m3-xfer {
+ rockchip,pins =
+ /* i2c6_scl_m3 */
+ <4 RK_PC6 11 &pcfg_pull_none_smt>,
+ /* i2c6_sda_m3 */
+ <4 RK_PC7 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c7 {
+ /omit-if-no-ref/
+ i2c7m0_xfer: i2c7m0-xfer {
+ rockchip,pins =
+ /* i2c7_scl_m0 */
+ <1 RK_PB0 10 &pcfg_pull_none_smt>,
+ /* i2c7_sda_m0 */
+ <1 RK_PB3 10 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c7m1_xfer: i2c7m1-xfer {
+ rockchip,pins =
+ /* i2c7_scl_m1 */
+ <3 RK_PA0 11 &pcfg_pull_none_smt>,
+ /* i2c7_sda_m1 */
+ <3 RK_PA1 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c7m2_xfer: i2c7m2-xfer {
+ rockchip,pins =
+ /* i2c7_scl_m2 */
+ <4 RK_PA0 11 &pcfg_pull_none_smt>,
+ /* i2c7_sda_m2 */
+ <4 RK_PA1 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c7m3_xfer: i2c7m3-xfer {
+ rockchip,pins =
+ /* i2c7_scl_m3 */
+ <4 RK_PC0 11 &pcfg_pull_none_smt>,
+ /* i2c7_sda_m3 */
+ <4 RK_PC1 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c8 {
+ /omit-if-no-ref/
+ i2c8m0_xfer: i2c8m0-xfer {
+ rockchip,pins =
+ /* i2c8_scl_m0 */
+ <2 RK_PA0 11 &pcfg_pull_none_smt>,
+ /* i2c8_sda_m0 */
+ <2 RK_PA1 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c8m1_xfer: i2c8m1-xfer {
+ rockchip,pins =
+ /* i2c8_scl_m1 */
+ <1 RK_PC6 10 &pcfg_pull_none_smt>,
+ /* i2c8_sda_m1 */
+ <1 RK_PC7 10 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c8m2_xfer: i2c8m2-xfer {
+ rockchip,pins =
+ /* i2c8_scl_m2 */
+ <2 RK_PB6 11 &pcfg_pull_none_smt>,
+ /* i2c8_sda_m2 */
+ <2 RK_PB7 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c8m3_xfer: i2c8m3-xfer {
+ rockchip,pins =
+ /* i2c8_scl_m3 */
+ <3 RK_PB3 11 &pcfg_pull_none_smt>,
+ /* i2c8_sda_m3 */
+ <3 RK_PB2 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i2c9 {
+ /omit-if-no-ref/
+ i2c9m0_xfer: i2c9m0-xfer {
+ rockchip,pins =
+ /* i2c9_scl_m0 */
+ <1 RK_PA5 10 &pcfg_pull_none_smt>,
+ /* i2c9_sda_m0 */
+ <1 RK_PA6 10 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c9m1_xfer: i2c9m1-xfer {
+ rockchip,pins =
+ /* i2c9_scl_m1 */
+ <1 RK_PB5 10 &pcfg_pull_none_smt>,
+ /* i2c9_sda_m1 */
+ <1 RK_PB4 10 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c9m2_xfer: i2c9m2-xfer {
+ rockchip,pins =
+ /* i2c9_scl_m2 */
+ <2 RK_PD5 11 &pcfg_pull_none_smt>,
+ /* i2c9_sda_m2 */
+ <2 RK_PD4 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i2c9m3_xfer: i2c9m3-xfer {
+ rockchip,pins =
+ /* i2c9_scl_m3 */
+ <3 RK_PC2 11 &pcfg_pull_none_smt>,
+ /* i2c9_sda_m3 */
+ <3 RK_PC3 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i3c0 {
+ /omit-if-no-ref/
+ i3c0m0_xfer: i3c0m0-xfer {
+ rockchip,pins =
+ /* i3c0_scl_m0 */
+ <0 RK_PC1 11 &pcfg_pull_none_smt>,
+ /* i3c0_sda_m0 */
+ <0 RK_PC2 11 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i3c0m1_xfer: i3c0m1-xfer {
+ rockchip,pins =
+ /* i3c0_scl_m1 */
+ <1 RK_PD2 10 &pcfg_pull_none_smt>,
+ /* i3c0_sda_m1 */
+ <1 RK_PD3 10 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i3c1 {
+ /omit-if-no-ref/
+ i3c1m0_xfer: i3c1m0-xfer {
+ rockchip,pins =
+ /* i3c1_scl_m0 */
+ <2 RK_PD2 12 &pcfg_pull_none_smt>,
+ /* i3c1_sda_m0 */
+ <2 RK_PD3 12 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i3c1m1_xfer: i3c1m1-xfer {
+ rockchip,pins =
+ /* i3c1_scl_m1 */
+ <2 RK_PA2 14 &pcfg_pull_none_smt>,
+ /* i3c1_sda_m1 */
+ <2 RK_PA3 14 &pcfg_pull_none_smt>;
+ };
+
+ /omit-if-no-ref/
+ i3c1m2_xfer: i3c1m2-xfer {
+ rockchip,pins =
+ /* i3c1_scl_m2 */
+ <3 RK_PD3 11 &pcfg_pull_none_smt>,
+ /* i3c1_sda_m2 */
+ <3 RK_PD2 11 &pcfg_pull_none_smt>;
+ };
+ };
+
+ i3c0_sda {
+ /omit-if-no-ref/
+ i3c0_sdam0_pu: i3c0_sdam0-pu {
+ rockchip,pins =
+ /* i3c0_sda_pu_m0 */
+ <0 RK_PC5 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ i3c0_sdam1_pu: i3c0_sdam1-pu {
+ rockchip,pins =
+ /* i3c0_sda_pu_m1 */
+ <1 RK_PD1 10 &pcfg_pull_none>;
+ };
+ };
+
+ i3c1_sda {
+ /omit-if-no-ref/
+ i3c1_sdam0_pu: i3c1_sdam0-pu {
+ rockchip,pins =
+ /* i3c1_sda_pu_m0 */
+ <2 RK_PD6 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ i3c1_sdam1_pu: i3c1_sdam1-pu {
+ rockchip,pins =
+ /* i3c1_sda_pu_m1 */
+ <2 RK_PA5 14 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ i3c1_sdam2_pu: i3c1_sdam2-pu {
+ rockchip,pins =
+ /* i3c1_sda_pu_m2 */
+ <3 RK_PD1 11 &pcfg_pull_none>;
+ };
+ };
+
+ isp_flash {
+ /omit-if-no-ref/
+ isp_flashm0_pins: isp_flashm0-pins {
+ rockchip,pins =
+ /* isp_flash_trigout_m0 */
+ <2 RK_PD5 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ isp_flashm1_pins: isp_flashm1-pins {
+ rockchip,pins =
+ /* isp_flash_trigout_m1 */
+ <4 RK_PC5 1 &pcfg_pull_none>;
+ };
+ };
+
+ isp_prelight {
+ /omit-if-no-ref/
+ isp_prelightm0_pins: isp_prelightm0-pins {
+ rockchip,pins =
+ /* isp_prelight_trig_m0 */
+ <2 RK_PD4 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ isp_prelightm1_pins: isp_prelightm1-pins {
+ rockchip,pins =
+ /* isp_prelight_trig_m1 */
+ <4 RK_PC4 1 &pcfg_pull_none>;
+ };
+ };
+
+ jtag {
+ /omit-if-no-ref/
+ jtagm0_pins: jtagm0-pins {
+ rockchip,pins =
+ /* jtag_tck_m0 */
+ <2 RK_PA2 9 &pcfg_pull_none>,
+ /* jtag_tms_m0 */
+ <2 RK_PA3 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ jtagm1_pins: jtagm1-pins {
+ rockchip,pins =
+ /* jtag_tck_m1 */
+ <0 RK_PD4 10 &pcfg_pull_none>,
+ /* jtag_tms_m1 */
+ <0 RK_PD5 10 &pcfg_pull_none>;
+ };
+ };
+
+ mipi {
+ /omit-if-no-ref/
+ mipim0_pins: mipim0-pins {
+ rockchip,pins =
+ /* mipi_te_m0 */
+ <4 RK_PB2 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ mipim1_pins: mipim1-pins {
+ rockchip,pins =
+ /* mipi_te_m1 */
+ <3 RK_PA2 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ mipim2_pins: mipim2-pins {
+ rockchip,pins =
+ /* mipi_te_m2 */
+ <4 RK_PA0 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ mipim3_pins: mipim3-pins {
+ rockchip,pins =
+ /* mipi_te_m3 */
+ <1 RK_PB3 11 &pcfg_pull_none>;
+ };
+ };
+
+ npu {
+ /omit-if-no-ref/
+ npu_pins: npu-pins {
+ rockchip,pins =
+ /* npu_avs */
+ <0 RK_PB7 11 &pcfg_pull_none>;
+ };
+ };
+
+ pcie0 {
+ /omit-if-no-ref/
+ pcie0m0_pins: pcie0m0-pins {
+ rockchip,pins =
+ /* pcie21_port0_clkreq_m0 */
+ <2 RK_PB2 11 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie0m1_pins: pcie0m1-pins {
+ rockchip,pins =
+ /* pcie0_clkreq_m1 */
+ <1 RK_PB6 12 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie0m2_pins: pcie0m2-pins {
+ rockchip,pins =
+ /* pcie0_clkreq_m2 */
+ <4 RK_PB5 12 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie0m3_pins: pcie0m3-pins {
+ rockchip,pins =
+ /* pcie0_clkreq_m3 */
+ <4 RK_PC6 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie0_buttonrst: pcie21-port0-buttonrst {
+ rockchip,pins =
+ /* pcie0_buttonrst */
+ <1 RK_PC4 12 &pcfg_pull_none>;
+ };
+ };
+
+ pcie1 {
+ /omit-if-no-ref/
+ pcie1m0_pins: pcie1m0-pins {
+ rockchip,pins =
+ /* pcie1_clkreq_m0 */
+ <2 RK_PB3 11 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie1m1_pins: pcie1m1-pins {
+ rockchip,pins =
+ /* pcie1_clkreq_m1 */
+ <1 RK_PB4 12 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie1m2_pins: pcie1m2-pins {
+ rockchip,pins =
+ /* pcie1_clkreq_m2 */
+ <4 RK_PA5 12 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie1m3_pins: pcie1m3-pins {
+ rockchip,pins =
+ /* pcie1_clkreq_m3 */
+ <4 RK_PC1 10 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ pcie1_buttonrst: pcie21-port1-buttonrst {
+ rockchip,pins =
+ /* pcie1_buttonrst */
+ <1 RK_PC5 12 &pcfg_pull_none>;
+ };
+ };
+
+ pdm0 {
+ /omit-if-no-ref/
+ pdm0m0_clk0: pdm0m0-clk0 {
+ rockchip,pins =
+ /* pdm0_clk0_m0 */
+ <0 RK_PC4 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m0_clk1: pdm0m0-clk1 {
+ rockchip,pins =
+ /* pdm0_clk1_m0 */
+ <0 RK_PC3 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m0_sdi0: pdm0m0-sdi0 {
+ rockchip,pins =
+ /* pdm0_sdi0_m0 */
+ <0 RK_PD0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m0_sdi1: pdm0m0-sdi1 {
+ rockchip,pins =
+ /* pdm0_sdi1_m0 */
+ <0 RK_PD1 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m0_sdi2: pdm0m0-sdi2 {
+ rockchip,pins =
+ /* pdm0_sdi2_m0 */
+ <0 RK_PD2 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m0_sdi3: pdm0m0-sdi3 {
+ rockchip,pins =
+ /* pdm0_sdi3_m0 */
+ <0 RK_PD3 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m1_clk0: pdm0m1-clk0 {
+ rockchip,pins =
+ /* pdm0_clk0_m1 */
+ <1 RK_PB1 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m1_clk1: pdm0m1-clk1 {
+ rockchip,pins =
+ /* pdm0_clk1_m1 */
+ <1 RK_PA6 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m1_sdi0: pdm0m1-sdi0 {
+ rockchip,pins =
+ /* pdm0_sdi0_m1 */
+ <1 RK_PB2 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m1_sdi1: pdm0m1-sdi1 {
+ rockchip,pins =
+ /* pdm0_sdi1_m1 */
+ <1 RK_PA3 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m1_sdi2: pdm0m1-sdi2 {
+ rockchip,pins =
+ /* pdm0_sdi2_m1 */
+ <1 RK_PA5 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m1_sdi3: pdm0m1-sdi3 {
+ rockchip,pins =
+ /* pdm0_sdi3_m1 */
+ <1 RK_PA2 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m2_clk0: pdm0m2-clk0 {
+ rockchip,pins =
+ /* pdm0_clk0_m2 */
+ <1 RK_PC1 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m2_clk1: pdm0m2-clk1 {
+ rockchip,pins =
+ /* pdm0_clk1_m2 */
+ <1 RK_PD5 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m2_sdi0: pdm0m2-sdi0 {
+ rockchip,pins =
+ /* pdm0_sdi0_m2 */
+ <1 RK_PC6 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m2_sdi1: pdm0m2-sdi1 {
+ rockchip,pins =
+ /* pdm0_sdi1_m2 */
+ <1 RK_PC7 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m2_sdi2: pdm0m2-sdi2 {
+ rockchip,pins =
+ /* pdm0_sdi2_m2 */
+ <1 RK_PC0 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m2_sdi3: pdm0m2-sdi3 {
+ rockchip,pins =
+ /* pdm0_sdi3_m2 */
+ <1 RK_PD4 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m3_clk0: pdm0m3-clk0 {
+ rockchip,pins =
+ /* pdm0_clk0_m3 */
+ <2 RK_PB5 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m3_clk1: pdm0m3-clk1 {
+ rockchip,pins =
+ /* pdm0_clk1_m3 */
+ <2 RK_PB3 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m3_sdi0: pdm0m3-sdi0 {
+ rockchip,pins =
+ /* pdm0_sdi0_m3 */
+ <2 RK_PB4 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m3_sdi1: pdm0m3-sdi1 {
+ rockchip,pins =
+ /* pdm0_sdi1_m3 */
+ <2 RK_PB2 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m3_sdi2: pdm0m3-sdi2 {
+ rockchip,pins =
+ /* pdm0_sdi2_m3 */
+ <2 RK_PB1 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm0m3_sdi3: pdm0m3-sdi3 {
+ rockchip,pins =
+ /* pdm0_sdi3_m3 */
+ <2 RK_PB0 5 &pcfg_pull_none>;
+ };
+ };
+
+ pdm1 {
+ /omit-if-no-ref/
+ pdm1m0_clk0: pdm1m0-clk0 {
+ rockchip,pins =
+ /* pdm1_clk0_m0 */
+ <2 RK_PC5 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m0_clk1: pdm1m0-clk1 {
+ rockchip,pins =
+ /* pdm1_clk1_m0 */
+ <2 RK_PC1 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m0_sdi0: pdm1m0-sdi0 {
+ rockchip,pins =
+ /* pdm1_sdi0_m0 */
+ <2 RK_PC4 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m0_sdi1: pdm1m0-sdi1 {
+ rockchip,pins =
+ /* pdm1_sdi1_m0 */
+ <2 RK_PC0 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m0_sdi2: pdm1m0-sdi2 {
+ rockchip,pins =
+ /* pdm1_sdi2_m0 */
+ <2 RK_PC2 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m0_sdi3: pdm1m0-sdi3 {
+ rockchip,pins =
+ /* pdm1_sdi3_m0 */
+ <2 RK_PC3 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m1_clk0: pdm1m1-clk0 {
+ rockchip,pins =
+ /* pdm1_clk0_m1 */
+ <4 RK_PA6 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m1_clk1: pdm1m1-clk1 {
+ rockchip,pins =
+ /* pdm1_clk1_m1 */
+ <4 RK_PB0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m1_sdi0: pdm1m1-sdi0 {
+ rockchip,pins =
+ /* pdm1_sdi0_m1 */
+ <4 RK_PB3 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m1_sdi1: pdm1m1-sdi1 {
+ rockchip,pins =
+ /* pdm1_sdi1_m1 */
+ <4 RK_PB2 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m1_sdi2: pdm1m1-sdi2 {
+ rockchip,pins =
+ /* pdm1_sdi2_m1 */
+ <4 RK_PB1 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m1_sdi3: pdm1m1-sdi3 {
+ rockchip,pins =
+ /* pdm1_sdi3_m1 */
+ <4 RK_PA4 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m2_clk0: pdm1m2-clk0 {
+ rockchip,pins =
+ /* pdm1_clk0_m2 */
+ <3 RK_PB1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m2_clk1: pdm1m2-clk1 {
+ rockchip,pins =
+ /* pdm1_clk1_m2 */
+ <3 RK_PA7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m2_sdi0: pdm1m2-sdi0 {
+ rockchip,pins =
+ /* pdm1_sdi0_m2 */
+ <3 RK_PB3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m2_sdi1: pdm1m2-sdi1 {
+ rockchip,pins =
+ /* pdm1_sdi1_m2 */
+ <3 RK_PB2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m2_sdi2: pdm1m2-sdi2 {
+ rockchip,pins =
+ /* pdm1_sdi2_m2 */
+ <3 RK_PA6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pdm1m2_sdi3: pdm1m2-sdi3 {
+ rockchip,pins =
+ /* pdm1_sdi3_m2 */
+ <3 RK_PA5 4 &pcfg_pull_none>;
+ };
+ };
+
+ pmu_debug_test {
+ /omit-if-no-ref/
+ pmu_debug_test_pins: pmu_debug_test-pins {
+ rockchip,pins =
+ /* pmu_debug_test_out */
+ <0 RK_PB0 2 &pcfg_pull_none>;
+ };
+ };
+
+ pwm0 {
+ /omit-if-no-ref/
+ pwm0m0_ch0: pwm0m0-ch0 {
+ rockchip,pins =
+ /* pwm0_ch0_m0 */
+ <0 RK_PC4 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm0m0_ch1: pwm0m0-ch1 {
+ rockchip,pins =
+ /* pwm0_ch1_m0 */
+ <0 RK_PC3 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm0m1_ch0: pwm0m1-ch0 {
+ rockchip,pins =
+ /* pwm0_ch0_m1 */
+ <1 RK_PC0 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm0m1_ch1: pwm0m1-ch1 {
+ rockchip,pins =
+ /* pwm0_ch1_m1 */
+ <4 RK_PC1 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm0m2_ch0: pwm0m2-ch0 {
+ rockchip,pins =
+ /* pwm0_ch0_m2 */
+ <2 RK_PC3 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm0m2_ch1: pwm0m2-ch1 {
+ rockchip,pins =
+ /* pwm0_ch1_m2 */
+ <2 RK_PC7 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm0m3_ch0: pwm0m3-ch0 {
+ rockchip,pins =
+ /* pwm0_ch0_m3 */
+ <3 RK_PB0 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm0m3_ch1: pwm0m3-ch1 {
+ rockchip,pins =
+ /* pwm0_ch1_m3 */
+ <3 RK_PB6 12 &pcfg_pull_none_drv_level_2>;
+ };
+ };
+
+ pwm1 {
+ /omit-if-no-ref/
+ pwm1m0_ch0: pwm1m0-ch0 {
+ rockchip,pins =
+ /* pwm1_ch0_m0 */
+ <0 RK_PB4 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m0_ch1: pwm1m0-ch1 {
+ rockchip,pins =
+ /* pwm1_ch1_m0 */
+ <0 RK_PB5 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m0_ch2: pwm1m0-ch2 {
+ rockchip,pins =
+ /* pwm1_ch2_m0 */
+ <0 RK_PB6 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m0_ch3: pwm1m0-ch3 {
+ rockchip,pins =
+ /* pwm1_ch3_m0 */
+ <0 RK_PC0 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m0_ch4: pwm1m0-ch4 {
+ rockchip,pins =
+ /* pwm1_ch4_m0 */
+ <0 RK_PB7 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m0_ch5: pwm1m0-ch5 {
+ rockchip,pins =
+ /* pwm1_ch5_m0 */
+ <0 RK_PD2 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m1_ch0: pwm1m1-ch0 {
+ rockchip,pins =
+ /* pwm1_ch0_m1 */
+ <1 RK_PB4 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m1_ch1: pwm1m1-ch1 {
+ rockchip,pins =
+ /* pwm1_ch1_m1 */
+ <1 RK_PB5 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m1_ch2: pwm1m1-ch2 {
+ rockchip,pins =
+ /* pwm1_ch2_m1 */
+ <1 RK_PC2 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m1_ch3: pwm1m1-ch3 {
+ rockchip,pins =
+ /* pwm1_ch3_m1 */
+ <1 RK_PD2 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m1_ch4: pwm1m1-ch4 {
+ rockchip,pins =
+ /* pwm1_ch4_m1 */
+ <1 RK_PD3 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m1_ch5: pwm1m1-ch5 {
+ rockchip,pins =
+ /* pwm1_ch5_m1 */
+ <4 RK_PC0 14 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m2_ch0: pwm1m2-ch0 {
+ rockchip,pins =
+ /* pwm1_ch0_m2 */
+ <2 RK_PC0 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m2_ch1: pwm1m2-ch1 {
+ rockchip,pins =
+ /* pwm1_ch1_m2 */
+ <2 RK_PC1 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m2_ch2: pwm1m2-ch2 {
+ rockchip,pins =
+ /* pwm1_ch2_m2 */
+ <2 RK_PC2 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m2_ch3: pwm1m2-ch3 {
+ rockchip,pins =
+ /* pwm1_ch3_m2 */
+ <2 RK_PC4 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m2_ch4: pwm1m2-ch4 {
+ rockchip,pins =
+ /* pwm1_ch4_m2 */
+ <2 RK_PC5 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m2_ch5: pwm1m2-ch5 {
+ rockchip,pins =
+ /* pwm1_ch5_m2 */
+ <2 RK_PC6 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m3_ch0: pwm1m3-ch0 {
+ rockchip,pins =
+ /* pwm1_ch0_m3 */
+ <3 RK_PA4 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m3_ch1: pwm1m3-ch1 {
+ rockchip,pins =
+ /* pwm1_ch1_m3 */
+ <3 RK_PA5 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m3_ch2: pwm1m3-ch2 {
+ rockchip,pins =
+ /* pwm1_ch2_m3 */
+ <3 RK_PA6 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m3_ch3: pwm1m3-ch3 {
+ rockchip,pins =
+ /* pwm1_ch3_m3 */
+ <3 RK_PB1 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m3_ch4: pwm1m3-ch4 {
+ rockchip,pins =
+ /* pwm1_ch4_m3 */
+ <3 RK_PB4 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pwm1m3_ch5: pwm1m3-ch5 {
+ rockchip,pins =
+ /* pwm1_ch5_m3 */
+ <3 RK_PB5 12 &pcfg_pull_none>;
+ };
+ };
+
+ pwm2 {
+ /omit-if-no-ref/
+ pwm2m0_ch0: pwm2m0-ch0 {
+ rockchip,pins =
+ /* pwm2_ch0_m0 */
+ <0 RK_PD3 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m0_ch1: pwm2m0-ch1 {
+ rockchip,pins =
+ /* pwm2_ch1_m0 */
+ <1 RK_PB3 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m0_ch2: pwm2m0-ch2 {
+ rockchip,pins =
+ /* pwm2_ch2_m0 */
+ <2 RK_PA0 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m0_ch3: pwm2m0-ch3 {
+ rockchip,pins =
+ /* pwm2_ch3_m0 */
+ <2 RK_PA1 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m0_ch4: pwm2m0-ch4 {
+ rockchip,pins =
+ /* pwm2_ch4_m0 */
+ <2 RK_PA4 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m0_ch5: pwm2m0-ch5 {
+ rockchip,pins =
+ /* pwm2_ch5_m0 */
+ <4 RK_PA2 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m0_ch6: pwm2m0-ch6 {
+ rockchip,pins =
+ /* pwm2_ch6_m0 */
+ <4 RK_PA7 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m0_ch7: pwm2m0-ch7 {
+ rockchip,pins =
+ /* pwm2_ch7_m0 */
+ <4 RK_PB3 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch0: pwm2m1-ch0 {
+ rockchip,pins =
+ /* pwm2_ch0_m1 */
+ <4 RK_PC2 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch1: pwm2m1-ch1 {
+ rockchip,pins =
+ /* pwm2_ch1_m1 */
+ <4 RK_PC3 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch2: pwm2m1-ch2 {
+ rockchip,pins =
+ /* pwm2_ch2_m1 */
+ <4 RK_PC6 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch3: pwm2m1-ch3 {
+ rockchip,pins =
+ /* pwm2_ch3_m1 */
+ <4 RK_PC7 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch4: pwm2m1-ch4 {
+ rockchip,pins =
+ /* pwm2_ch4_m1 */
+ <4 RK_PA3 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch5: pwm2m1-ch5 {
+ rockchip,pins =
+ /* pwm2_ch5_m1 */
+ <4 RK_PC5 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch6: pwm2m1-ch6 {
+ rockchip,pins =
+ /* pwm2_ch6_m1 */
+ <4 RK_PC4 14 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m1_ch7: pwm2m1-ch7 {
+ rockchip,pins =
+ /* pwm2_ch7_m1 */
+ <1 RK_PB1 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch0: pwm2m2-ch0 {
+ rockchip,pins =
+ /* pwm2_ch0_m2 */
+ <2 RK_PD0 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch1: pwm2m2-ch1 {
+ rockchip,pins =
+ /* pwm2_ch1_m2 */
+ <2 RK_PD1 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch2: pwm2m2-ch2 {
+ rockchip,pins =
+ /* pwm2_ch2_m2 */
+ <2 RK_PD2 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch3: pwm2m2-ch3 {
+ rockchip,pins =
+ /* pwm2_ch3_m2 */
+ <2 RK_PD3 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch4: pwm2m2-ch4 {
+ rockchip,pins =
+ /* pwm2_ch4_m2 */
+ <2 RK_PD4 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch5: pwm2m2-ch5 {
+ rockchip,pins =
+ /* pwm2_ch5_m2 */
+ <2 RK_PD5 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch6: pwm2m2-ch6 {
+ rockchip,pins =
+ /* pwm2_ch6_m2 */
+ <2 RK_PD6 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m2_ch7: pwm2m2-ch7 {
+ rockchip,pins =
+ /* pwm2_ch7_m2 */
+ <2 RK_PD7 13 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch0: pwm2m3-ch0 {
+ rockchip,pins =
+ /* pwm2_ch0_m3 */
+ <3 RK_PC2 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch1: pwm2m3-ch1 {
+ rockchip,pins =
+ /* pwm2_ch1_m3 */
+ <3 RK_PC3 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch2: pwm2m3-ch2 {
+ rockchip,pins =
+ /* pwm2_ch2_m3 */
+ <3 RK_PC5 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch3: pwm2m3-ch3 {
+ rockchip,pins =
+ /* pwm2_ch3_m3 */
+ <3 RK_PD0 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch4: pwm2m3-ch4 {
+ rockchip,pins =
+ /* pwm2_ch4_m3 */
+ <3 RK_PD2 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch5: pwm2m3-ch5 {
+ rockchip,pins =
+ /* pwm2_ch5_m3 */
+ <3 RK_PD3 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch6: pwm2m3-ch6 {
+ rockchip,pins =
+ /* pwm2_ch6_m3 */
+ <3 RK_PD6 12 &pcfg_pull_none_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ pwm2m3_ch7: pwm2m3-ch7 {
+ rockchip,pins =
+ /* pwm2_ch7_m3 */
+ <3 RK_PD7 12 &pcfg_pull_none_drv_level_2>;
+ };
+ };
+
+ ref_clk0 {
+ /omit-if-no-ref/
+ ref_clk0_clk0: ref_clk0-clk0 {
+ rockchip,pins =
+ /* ref_clk0_out */
+ <0 RK_PA0 1 &pcfg_pull_none>;
+ };
+ };
+
+ ref_clk1 {
+ /omit-if-no-ref/
+ ref_clk1_clk1: ref_clk1-clk1 {
+ rockchip,pins =
+ /* ref_clk1_out */
+ <0 RK_PB4 1 &pcfg_pull_none>;
+ };
+ };
+
+ ref_clk2 {
+ /omit-if-no-ref/
+ ref_clk2_clk2: ref_clk2-clk2 {
+ rockchip,pins =
+ /* ref_clk2_out */
+ <0 RK_PB5 1 &pcfg_pull_none>;
+ };
+ };
+
+ sai0 {
+ /omit-if-no-ref/
+ sai0m0_lrck: sai0m0-lrck {
+ rockchip,pins =
+ /* sai0_lrck_m0 */
+ <2 RK_PB7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_mclk: sai0m0-mclk {
+ rockchip,pins =
+ /* sai0_mclk_m0 */
+ <2 RK_PB5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sclk: sai0m0-sclk {
+ rockchip,pins =
+ /* sai0_sclk_m0 */
+ <2 RK_PB6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdi0: sai0m0-sdi0 {
+ rockchip,pins =
+ /* sai0_sdi0_m0 */
+ <2 RK_PB0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdi1: sai0m0-sdi1 {
+ rockchip,pins =
+ /* sai0_sdi1_m0 */
+ <2 RK_PB1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdi2: sai0m0-sdi2 {
+ rockchip,pins =
+ /* sai0_sdi2_m0 */
+ <2 RK_PB2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdi3: sai0m0-sdi3 {
+ rockchip,pins =
+ /* sai0_sdi3_m0 */
+ <2 RK_PB4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdo0: sai0m0-sdo0 {
+ rockchip,pins =
+ /* sai0_sdo0_m0 */
+ <2 RK_PA6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdo1: sai0m0-sdo1 {
+ rockchip,pins =
+ /* sai0_sdo1_m0 */
+ <2 RK_PA7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdo2: sai0m0-sdo2 {
+ rockchip,pins =
+ /* sai0_sdo2_m0 */
+ <2 RK_PB3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m0_sdo3: sai0m0-sdo3 {
+ rockchip,pins =
+ /* sai0_sdo3_m0 */
+ <2 RK_PD7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_lrck: sai0m1-lrck {
+ rockchip,pins =
+ /* sai0_lrck_m1 */
+ <0 RK_PC7 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_mclk: sai0m1-mclk {
+ rockchip,pins =
+ /* sai0_mclk_m1 */
+ <0 RK_PC4 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sclk: sai0m1-sclk {
+ rockchip,pins =
+ /* sai0_sclk_m1 */
+ <0 RK_PC6 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdi0: sai0m1-sdi0 {
+ rockchip,pins =
+ /* sai0_sdi0_m1 */
+ <0 RK_PD0 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdi1: sai0m1-sdi1 {
+ rockchip,pins =
+ /* sai0_sdi1_m1 */
+ <0 RK_PD1 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdi2: sai0m1-sdi2 {
+ rockchip,pins =
+ /* sai0_sdi2_m1 */
+ <0 RK_PD2 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdi3: sai0m1-sdi3 {
+ rockchip,pins =
+ /* sai0_sdi3_m1 */
+ <0 RK_PD3 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdo0: sai0m1-sdo0 {
+ rockchip,pins =
+ /* sai0_sdo0_m1 */
+ <0 RK_PC5 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdo1: sai0m1-sdo1 {
+ rockchip,pins =
+ /* sai0_sdo1_m1 */
+ <0 RK_PD3 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdo2: sai0m1-sdo2 {
+ rockchip,pins =
+ /* sai0_sdo2_m1 */
+ <0 RK_PD2 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m1_sdo3: sai0m1-sdo3 {
+ rockchip,pins =
+ /* sai0_sdo3_m1 */
+ <0 RK_PD1 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_lrck: sai0m2-lrck {
+ rockchip,pins =
+ /* sai0_lrck_m2 */
+ <1 RK_PA1 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_mclk: sai0m2-mclk {
+ rockchip,pins =
+ /* sai0_mclk_m2 */
+ <1 RK_PA4 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sclk: sai0m2-sclk {
+ rockchip,pins =
+ /* sai0_sclk_m2 */
+ <1 RK_PA0 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdi0: sai0m2-sdi0 {
+ rockchip,pins =
+ /* sai0_sdi0_m2 */
+ <1 RK_PB2 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdi1: sai0m2-sdi1 {
+ rockchip,pins =
+ /* sai0_sdi1_m2 */
+ <1 RK_PB1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdi2: sai0m2-sdi2 {
+ rockchip,pins =
+ /* sai0_sdi2_m2 */
+ <1 RK_PA3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdi3: sai0m2-sdi3 {
+ rockchip,pins =
+ /* sai0_sdi3_m2 */
+ <1 RK_PA2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdo0: sai0m2-sdo0 {
+ rockchip,pins =
+ /* sai0_sdo0_m2 */
+ <1 RK_PA7 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdo1: sai0m2-sdo1 {
+ rockchip,pins =
+ /* sai0_sdo1_m2 */
+ <1 RK_PA2 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdo2: sai0m2-sdo2 {
+ rockchip,pins =
+ /* sai0_sdo2_m2 */
+ <1 RK_PA3 3 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai0m2_sdo3: sai0m2-sdo3 {
+ rockchip,pins =
+ /* sai0_sdo3_m2 */
+ <1 RK_PB1 3 &pcfg_pull_none>;
+ };
+ };
+
+ sai1 {
+ /omit-if-no-ref/
+ sai1m0_lrck: sai1m0-lrck {
+ rockchip,pins =
+ /* sai1_lrck_m0 */
+ <4 RK_PA5 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_mclk: sai1m0-mclk {
+ rockchip,pins =
+ /* sai1_mclk_m0 */
+ <4 RK_PA2 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sclk: sai1m0-sclk {
+ rockchip,pins =
+ /* sai1_sclk_m0 */
+ <4 RK_PA3 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdi0: sai1m0-sdi0 {
+ rockchip,pins =
+ /* sai1_sdi0_m0 */
+ <4 RK_PB3 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdi1: sai1m0-sdi1 {
+ rockchip,pins =
+ /* sai1_sdi1_m0 */
+ <4 RK_PB2 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdi2: sai1m0-sdi2 {
+ rockchip,pins =
+ /* sai1_sdi2_m0 */
+ <4 RK_PB1 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdi3: sai1m0-sdi3 {
+ rockchip,pins =
+ /* sai1_sdi3_m0 */
+ <4 RK_PB0 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdo0: sai1m0-sdo0 {
+ rockchip,pins =
+ /* sai1_sdo0_m0 */
+ <4 RK_PA7 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdo1: sai1m0-sdo1 {
+ rockchip,pins =
+ /* sai1_sdo1_m0 */
+ <4 RK_PB0 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdo2: sai1m0-sdo2 {
+ rockchip,pins =
+ /* sai1_sdo2_m0 */
+ <4 RK_PB1 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m0_sdo3: sai1m0-sdo3 {
+ rockchip,pins =
+ /* sai1_sdo3_m0 */
+ <4 RK_PB2 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_lrck: sai1m1-lrck {
+ rockchip,pins =
+ /* sai1_lrck_m1 */
+ <3 RK_PC6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_mclk: sai1m1-mclk {
+ rockchip,pins =
+ /* sai1_mclk_m1 */
+ <3 RK_PD0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sclk: sai1m1-sclk {
+ rockchip,pins =
+ /* sai1_sclk_m1 */
+ <3 RK_PC7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdi0: sai1m1-sdi0 {
+ rockchip,pins =
+ /* sai1_sdi0_m1 */
+ <3 RK_PB7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdi1: sai1m1-sdi1 {
+ rockchip,pins =
+ /* sai1_sdi1_m1 */
+ <3 RK_PD4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdi2: sai1m1-sdi2 {
+ rockchip,pins =
+ /* sai1_sdi2_m1 */
+ <3 RK_PD5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdi3: sai1m1-sdi3 {
+ rockchip,pins =
+ /* sai1_sdi3_m1 */
+ <3 RK_PD6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdo0: sai1m1-sdo0 {
+ rockchip,pins =
+ /* sai1_sdo0_m1 */
+ <3 RK_PC5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdo1: sai1m1-sdo1 {
+ rockchip,pins =
+ /* sai1_sdo1_m1 */
+ <3 RK_PC4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdo2: sai1m1-sdo2 {
+ rockchip,pins =
+ /* sai1_sdo2_m1 */
+ <3 RK_PC1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai1m1_sdo3: sai1m1-sdo3 {
+ rockchip,pins =
+ /* sai1_sdo3_m1 */
+ <3 RK_PC0 4 &pcfg_pull_none>;
+ };
+ };
+
+ sai2 {
+ /omit-if-no-ref/
+ sai2m0_lrck: sai2m0-lrck {
+ rockchip,pins =
+ /* sai2_lrck_m0 */
+ <1 RK_PD2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m0_mclk: sai2m0-mclk {
+ rockchip,pins =
+ /* sai2_mclk_m0 */
+ <1 RK_PD4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m0_sclk: sai2m0-sclk {
+ rockchip,pins =
+ /* sai2_sclk_m0 */
+ <1 RK_PD1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m0_sdi: sai2m0-sdi {
+ rockchip,pins =
+ /* sai2m0_sdi */
+ <1 RK_PD3 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai2m0_sdo: sai2m0-sdo {
+ rockchip,pins =
+ /* sai2m0_sdo */
+ <1 RK_PD0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m1_lrck: sai2m1-lrck {
+ rockchip,pins =
+ /* sai2_lrck_m1 */
+ <2 RK_PC3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m1_mclk: sai2m1-mclk {
+ rockchip,pins =
+ /* sai2_mclk_m1 */
+ <2 RK_PC1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m1_sclk: sai2m1-sclk {
+ rockchip,pins =
+ /* sai2_sclk_m1 */
+ <2 RK_PC2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m1_sdi: sai2m1-sdi {
+ rockchip,pins =
+ /* sai2m1_sdi */
+ <2 RK_PC5 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai2m1_sdo: sai2m1-sdo {
+ rockchip,pins =
+ /* sai2m1_sdo */
+ <2 RK_PC4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m2_lrck: sai2m2-lrck {
+ rockchip,pins =
+ /* sai2_lrck_m2 */
+ <3 RK_PC3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m2_mclk: sai2m2-mclk {
+ rockchip,pins =
+ /* sai2_mclk_m2 */
+ <3 RK_PD1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m2_sclk: sai2m2-sclk {
+ rockchip,pins =
+ /* sai2_sclk_m2 */
+ <3 RK_PC2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai2m2_sdi: sai2m2-sdi {
+ rockchip,pins =
+ /* sai2m2_sdi */
+ <3 RK_PD2 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai2m2_sdo: sai2m2-sdo {
+ rockchip,pins =
+ /* sai2m2_sdo */
+ <3 RK_PD3 4 &pcfg_pull_none>;
+ };
+ };
+
+ sai3 {
+ /omit-if-no-ref/
+ sai3m0_lrck: sai3m0-lrck {
+ rockchip,pins =
+ /* sai3_lrck_m0 */
+ <1 RK_PA6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m0_mclk: sai3m0-mclk {
+ rockchip,pins =
+ /* sai3_mclk_m0 */
+ <1 RK_PA4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m0_sclk: sai3m0-sclk {
+ rockchip,pins =
+ /* sai3_sclk_m0 */
+ <1 RK_PA5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m0_sdi: sai3m0-sdi {
+ rockchip,pins =
+ /* sai3m0_sdi */
+ <1 RK_PA7 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai3m0_sdo: sai3m0-sdo {
+ rockchip,pins =
+ /* sai3m0_sdo */
+ <1 RK_PB2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m1_lrck: sai3m1-lrck {
+ rockchip,pins =
+ /* sai3_lrck_m1 */
+ <1 RK_PB5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m1_mclk: sai3m1-mclk {
+ rockchip,pins =
+ /* sai3_mclk_m1 */
+ <1 RK_PC1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m1_sclk: sai3m1-sclk {
+ rockchip,pins =
+ /* sai3_sclk_m1 */
+ <1 RK_PB4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m1_sdi: sai3m1-sdi {
+ rockchip,pins =
+ /* sai3m1_sdi */
+ <1 RK_PB7 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai3m1_sdo: sai3m1-sdo {
+ rockchip,pins =
+ /* sai3m1_sdo */
+ <1 RK_PB6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m2_lrck: sai3m2-lrck {
+ rockchip,pins =
+ /* sai3_lrck_m2 */
+ <3 RK_PA1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m2_mclk: sai3m2-mclk {
+ rockchip,pins =
+ /* sai3_mclk_m2 */
+ <2 RK_PD6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m2_sclk: sai3m2-sclk {
+ rockchip,pins =
+ /* sai3_sclk_m2 */
+ <3 RK_PA0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m2_sdi: sai3m2-sdi {
+ rockchip,pins =
+ /* sai3m2_sdi */
+ <3 RK_PA3 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai3m2_sdo: sai3m2-sdo {
+ rockchip,pins =
+ /* sai3m2_sdo */
+ <3 RK_PA2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m3_lrck: sai3m3-lrck {
+ rockchip,pins =
+ /* sai3_lrck_m3 */
+ <2 RK_PA2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m3_mclk: sai3m3-mclk {
+ rockchip,pins =
+ /* sai3_mclk_m3 */
+ <2 RK_PA1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m3_sclk: sai3m3-sclk {
+ rockchip,pins =
+ /* sai3_sclk_m3 */
+ <2 RK_PA5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai3m3_sdi: sai3m3-sdi {
+ rockchip,pins =
+ /* sai3m3_sdi */
+ <2 RK_PA3 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai3m3_sdo: sai3m3-sdo {
+ rockchip,pins =
+ /* sai3m3_sdo */
+ <2 RK_PA4 4 &pcfg_pull_none>;
+ };
+ };
+
+ sai4 {
+ /omit-if-no-ref/
+ sai4m0_lrck: sai4m0-lrck {
+ rockchip,pins =
+ /* sai4_lrck_m0 */
+ <4 RK_PA6 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m0_mclk: sai4m0-mclk {
+ rockchip,pins =
+ /* sai4_mclk_m0 */
+ <4 RK_PA2 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m0_sclk: sai4m0-sclk {
+ rockchip,pins =
+ /* sai4_sclk_m0 */
+ <4 RK_PA4 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m0_sdi: sai4m0-sdi {
+ rockchip,pins =
+ /* sai4m0_sdi */
+ <4 RK_PA7 2 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai4m0_sdo: sai4m0-sdo {
+ rockchip,pins =
+ /* sai4m0_sdo */
+ <4 RK_PB3 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m1_lrck: sai4m1-lrck {
+ rockchip,pins =
+ /* sai4_lrck_m1 */
+ <4 RK_PA0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m1_mclk: sai4m1-mclk {
+ rockchip,pins =
+ /* sai4_mclk_m1 */
+ <3 RK_PB0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m1_sclk: sai4m1-sclk {
+ rockchip,pins =
+ /* sai4_sclk_m1 */
+ <3 RK_PD7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m1_sdi: sai4m1-sdi {
+ rockchip,pins =
+ /* sai4m1_sdi */
+ <3 RK_PA4 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai4m1_sdo: sai4m1-sdo {
+ rockchip,pins =
+ /* sai4m1_sdo */
+ <4 RK_PA1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m2_lrck: sai4m2-lrck {
+ rockchip,pins =
+ /* sai4_lrck_m2 */
+ <4 RK_PC4 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m2_mclk: sai4m2-mclk {
+ rockchip,pins =
+ /* sai4_mclk_m2 */
+ <4 RK_PC0 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m2_sclk: sai4m2-sclk {
+ rockchip,pins =
+ /* sai4_sclk_m2 */
+ <4 RK_PC7 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m2_sdi: sai4m2-sdi {
+ rockchip,pins =
+ /* sai4m2_sdi */
+ <4 RK_PC6 2 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai4m2_sdo: sai4m2-sdo {
+ rockchip,pins =
+ /* sai4m2_sdo */
+ <4 RK_PC5 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m3_lrck: sai4m3-lrck {
+ rockchip,pins =
+ /* sai4_lrck_m3 */
+ <2 RK_PC7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m3_mclk: sai4m3-mclk {
+ rockchip,pins =
+ /* sai4_mclk_m3 */
+ <2 RK_PD2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m3_sclk: sai4m3-sclk {
+ rockchip,pins =
+ /* sai4_sclk_m3 */
+ <2 RK_PC6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sai4m3_sdi: sai4m3-sdi {
+ rockchip,pins =
+ /* sai4m3_sdi */
+ <2 RK_PD0 4 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sai4m3_sdo: sai4m3-sdo {
+ rockchip,pins =
+ /* sai4m3_sdo */
+ <2 RK_PD1 4 &pcfg_pull_none>;
+ };
+ };
+
+ sata30 {
+ /omit-if-no-ref/
+ sata30_sata: sata30-sata {
+ rockchip,pins =
+ /* sata30_cpdet */
+ <1 RK_PC7 12 &pcfg_pull_none>,
+ /* sata30_cppod */
+ <1 RK_PC6 12 &pcfg_pull_none>,
+ /* sata30_mpswit */
+ <1 RK_PD5 12 &pcfg_pull_none>;
+ };
+ };
+
+ sata30_port0 {
+ /omit-if-no-ref/
+ sata30_port0m0_port0: sata30_port0m0-port0 {
+ rockchip,pins =
+ /* sata30_port0_actled_m0 */
+ <2 RK_PB4 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sata30_port0m1_port0: sata30_port0m1-port0 {
+ rockchip,pins =
+ /* sata30_port0_actled_m1 */
+ <4 RK_PC6 10 &pcfg_pull_none>;
+ };
+ };
+
+ sata30_port1 {
+ /omit-if-no-ref/
+ sata30_port1m0_port1: sata30_port1m0-port1 {
+ rockchip,pins =
+ /* sata30_port1_actled_m0 */
+ <2 RK_PB5 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sata30_port1m1_port1: sata30_port1m1-port1 {
+ rockchip,pins =
+ /* sata30_port1_actled_m1 */
+ <4 RK_PC5 10 &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc0 {
+ /omit-if-no-ref/
+ sdmmc0_bus4: sdmmc0-bus4 {
+ rockchip,pins =
+ /* sdmmc0_d0 */
+ <2 RK_PA0 1 &pcfg_pull_up_drv_level_3>,
+ /* sdmmc0_d1 */
+ <2 RK_PA1 1 &pcfg_pull_up_drv_level_3>,
+ /* sdmmc0_d2 */
+ <2 RK_PA2 1 &pcfg_pull_up_drv_level_3>,
+ /* sdmmc0_d3 */
+ <2 RK_PA3 1 &pcfg_pull_up_drv_level_3>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc0_clk: sdmmc0-clk {
+ rockchip,pins =
+ /* sdmmc0_clk */
+ <2 RK_PA5 1 &pcfg_pull_up_drv_level_3>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc0_cmd: sdmmc0-cmd {
+ rockchip,pins =
+ /* sdmmc0_cmd */
+ <2 RK_PA4 1 &pcfg_pull_up_drv_level_3>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc0_det: sdmmc0-det {
+ rockchip,pins =
+ /* sdmmc0_detn */
+ <0 RK_PA7 1 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc0_pwren: sdmmc0-pwren {
+ rockchip,pins =
+ /* sdmmc0_pwren */
+ <0 RK_PB6 1 &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc1 {
+ /omit-if-no-ref/
+ sdmmc1m0_bus4: sdmmc1m0-bus4 {
+ rockchip,pins =
+ /* sdmmc1_d0_m0 */
+ <1 RK_PB4 2 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d1_m0 */
+ <1 RK_PB5 2 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d2_m0 */
+ <1 RK_PB6 2 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d3_m0 */
+ <1 RK_PB7 2 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m0_clk: sdmmc1m0-clk {
+ rockchip,pins =
+ /* sdmmc1_clk_m0 */
+ <1 RK_PC1 2 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m0_cmd: sdmmc1m0-cmd {
+ rockchip,pins =
+ /* sdmmc1_cmd_m0 */
+ <1 RK_PC0 2 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m0_det: sdmmc1m0-det {
+ rockchip,pins =
+ /* sdmmc1_detn_m0 */
+ <1 RK_PC3 2 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m0_pwren: sdmmc1m0-pwren {
+ rockchip,pins =
+ /* sdmmc1m0_pwren */
+ <1 RK_PC2 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m1_bus4: sdmmc1m1-bus4 {
+ rockchip,pins =
+ /* sdmmc1_d0_m1 */
+ <2 RK_PA6 2 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d1_m1 */
+ <2 RK_PA7 2 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d2_m1 */
+ <2 RK_PB0 2 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d3_m1 */
+ <2 RK_PB1 2 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m1_clk: sdmmc1m1-clk {
+ rockchip,pins =
+ /* sdmmc1_clk_m1 */
+ <2 RK_PB3 2 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m1_cmd: sdmmc1m1-cmd {
+ rockchip,pins =
+ /* sdmmc1_cmd_m1 */
+ <2 RK_PB2 2 &pcfg_pull_up_drv_level_2>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m1_det: sdmmc1m1-det {
+ rockchip,pins =
+ /* sdmmc1_detn_m1 */
+ <2 RK_PB5 2 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m1_pwren: sdmmc1m1-pwren {
+ rockchip,pins =
+ /* sdmmc1m1_pwren */
+ <2 RK_PB4 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ sdmmc1m2_det: sdmmc1m2-det {
+ rockchip,pins =
+ /* sdmmc1_detn_m2 */
+ <0 RK_PB6 2 &pcfg_pull_up>;
+ };
+ };
+
+ sdmmc0_testclk {
+ /omit-if-no-ref/
+ sdmmc0_testclk_test: sdmmc0_testclk-test {
+ rockchip,pins =
+ /* sdmmc0_testclk_out */
+ <1 RK_PC4 6 &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc0_testdata {
+ /omit-if-no-ref/
+ sdmmc0_testdata_test: sdmmc0_testdata-test {
+ rockchip,pins =
+ /* sdmmc0_testdata_out */
+ <1 RK_PC5 6 &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc1_testclk {
+ /omit-if-no-ref/
+ sdmmc1_testclkm0_test: sdmmc1_testclkm0-test {
+ rockchip,pins =
+ /* sdmmc1_testclk_out_m0 */
+ <1 RK_PC4 5 &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc1_testdata {
+ /omit-if-no-ref/
+ sdmmc1_testdatam0_test: sdmmc1_testdatam0-test {
+ rockchip,pins =
+ /* sdmmc1_testdata_out_m0 */
+ <1 RK_PC5 5 &pcfg_pull_none>;
+ };
+ };
+
+ spdif {
+ /omit-if-no-ref/
+ spdifm0_rx0: spdifm0-rx0 {
+ rockchip,pins =
+ /* spdif_rx0_m0 */
+ <4 RK_PB4 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm0_rx1: spdifm0-rx1 {
+ rockchip,pins =
+ /* spdif_rx1_m0 */
+ <3 RK_PB4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm0_tx0: spdifm0-tx0 {
+ rockchip,pins =
+ /* spdif_tx0_m0 */
+ <4 RK_PB5 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm0_tx1: spdifm0-tx1 {
+ rockchip,pins =
+ /* spdif_tx1_m0 */
+ <3 RK_PB5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm1_rx0: spdifm1-rx0 {
+ rockchip,pins =
+ /* spdif_rx0_m1 */
+ <4 RK_PA0 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm1_rx1: spdifm1-rx1 {
+ rockchip,pins =
+ /* spdif_rx1_m1 */
+ <3 RK_PA2 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm1_tx0: spdifm1-tx0 {
+ rockchip,pins =
+ /* spdif_tx0_m1 */
+ <4 RK_PA1 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm1_tx1: spdifm1-tx1 {
+ rockchip,pins =
+ /* spdif_tx1_m1 */
+ <3 RK_PA3 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm2_rx0: spdifm2-rx0 {
+ rockchip,pins =
+ /* spdif_rx0_m2 */
+ <2 RK_PD6 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm2_rx1: spdifm2-rx1 {
+ rockchip,pins =
+ /* spdif_rx1_m2 */
+ <1 RK_PD4 6 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm2_tx0: spdifm2-tx0 {
+ rockchip,pins =
+ /* spdif_tx0_m2 */
+ <2 RK_PD7 5 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spdifm2_tx1: spdifm2-tx1 {
+ rockchip,pins =
+ /* spdif_tx1_m2 */
+ <1 RK_PD5 6 &pcfg_pull_none>;
+ };
+ };
+
+ spi0 {
+ /omit-if-no-ref/
+ spi0m0_pins: spi0m0-pins {
+ rockchip,pins =
+ /* spi0_clk_m0 */
+ <0 RK_PC7 11 &pcfg_pull_none>,
+ /* spi0_miso_m0 */
+ <0 RK_PD1 11 &pcfg_pull_none>,
+ /* spi0_mosi_m0 */
+ <0 RK_PD0 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi0m0_csn0: spi0m0-csn0 {
+ rockchip,pins =
+ /* spi0m0_csn0 */
+ <0 RK_PC6 11 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi0m0_csn1: spi0m0-csn1 {
+ rockchip,pins =
+ /* spi0m0_csn1 */
+ <0 RK_PC3 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi0m1_pins: spi0m1-pins {
+ rockchip,pins =
+ /* spi0_clk_m1 */
+ <2 RK_PA5 12 &pcfg_pull_none>,
+ /* spi0_miso_m1 */
+ <2 RK_PA1 12 &pcfg_pull_none>,
+ /* spi0_mosi_m1 */
+ <2 RK_PA0 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi0m1_csn0: spi0m1-csn0 {
+ rockchip,pins =
+ /* spi0m1_csn0 */
+ <2 RK_PA4 12 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi0m1_csn1: spi0m1-csn1 {
+ rockchip,pins =
+ /* spi0m1_csn1 */
+ <2 RK_PA2 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi0m2_pins: spi0m2-pins {
+ rockchip,pins =
+ /* spi0_clk_m2 */
+ <1 RK_PA7 9 &pcfg_pull_none>,
+ /* spi0_miso_m2 */
+ <1 RK_PA6 9 &pcfg_pull_none>,
+ /* spi0_mosi_m2 */
+ <1 RK_PA5 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi0m2_csn0: spi0m2-csn0 {
+ rockchip,pins =
+ /* spi0m2_csn0 */
+ <1 RK_PA4 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi0m2_csn1: spi0m2-csn1 {
+ rockchip,pins =
+ /* spi0m2_csn1 */
+ <1 RK_PB2 9 &pcfg_pull_none>;
+ };
+ };
+
+ spi1 {
+ /omit-if-no-ref/
+ spi1m0_pins: spi1m0-pins {
+ rockchip,pins =
+ /* spi1_clk_m0 */
+ <1 RK_PB4 11 &pcfg_pull_none>,
+ /* spi1_miso_m0 */
+ <1 RK_PB6 11 &pcfg_pull_none>,
+ /* spi1_mosi_m0 */
+ <1 RK_PB5 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi1m0_csn0: spi1m0-csn0 {
+ rockchip,pins =
+ /* spi1m0_csn0 */
+ <1 RK_PB7 11 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi1m0_csn1: spi1m0-csn1 {
+ rockchip,pins =
+ /* spi1m0_csn1 */
+ <1 RK_PC0 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi1m1_pins: spi1m1-pins {
+ rockchip,pins =
+ /* spi1_clk_m1 */
+ <2 RK_PC5 10 &pcfg_pull_none>,
+ /* spi1_miso_m1 */
+ <2 RK_PC3 10 &pcfg_pull_none>,
+ /* spi1_mosi_m1 */
+ <2 RK_PC2 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi1m1_csn0: spi1m1-csn0 {
+ rockchip,pins =
+ /* spi1m1_csn0 */
+ <2 RK_PC4 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi1m1_csn1: spi1m1-csn1 {
+ rockchip,pins =
+ /* spi1m1_csn1 */
+ <2 RK_PC1 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi1m2_pins: spi1m2-pins {
+ rockchip,pins =
+ /* spi1_clk_m2 */
+ <3 RK_PC7 10 &pcfg_pull_none>,
+ /* spi1_miso_m2 */
+ <3 RK_PC5 10 &pcfg_pull_none>,
+ /* spi1_mosi_m2 */
+ <3 RK_PC6 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi1m2_csn0: spi1m2-csn0 {
+ rockchip,pins =
+ /* spi1m2_csn0 */
+ <3 RK_PD0 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi1m2_csn1: spi1m2-csn1 {
+ rockchip,pins =
+ /* spi1m2_csn1 */
+ <4 RK_PA0 10 &pcfg_pull_none>;
+ };
+ };
+
+ spi2 {
+ /omit-if-no-ref/
+ spi2m0_pins: spi2m0-pins {
+ rockchip,pins =
+ /* spi2_clk_m0 */
+ <0 RK_PB2 9 &pcfg_pull_none>,
+ /* spi2_miso_m0 */
+ <0 RK_PB1 9 &pcfg_pull_none>,
+ /* spi2_mosi_m0 */
+ <0 RK_PB3 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi2m0_csn0: spi2m0-csn0 {
+ rockchip,pins =
+ /* spi2m0_csn0 */
+ <0 RK_PB0 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi2m0_csn1: spi2m0-csn1 {
+ rockchip,pins =
+ /* spi2m0_csn1 */
+ <0 RK_PA7 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi2m1_pins: spi2m1-pins {
+ rockchip,pins =
+ /* spi2_clk_m1 */
+ <1 RK_PD5 11 &pcfg_pull_none>,
+ /* spi2_miso_m1 */
+ <1 RK_PC5 11 &pcfg_pull_none>,
+ /* spi2_mosi_m1 */
+ <1 RK_PC4 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi2m1_csn0: spi2m1-csn0 {
+ rockchip,pins =
+ /* spi2m1_csn0 */
+ <1 RK_PC3 11 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi2m1_csn1: spi2m1-csn1 {
+ rockchip,pins =
+ /* spi2m1_csn1 */
+ <1 RK_PC2 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi2m2_pins: spi2m2-pins {
+ rockchip,pins =
+ /* spi2_clk_m2 */
+ <3 RK_PA4 10 &pcfg_pull_none>,
+ /* spi2_miso_m2 */
+ <3 RK_PC1 10 &pcfg_pull_none>,
+ /* spi2_mosi_m2 */
+ <3 RK_PB0 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi2m2_csn0: spi2m2-csn0 {
+ rockchip,pins =
+ /* spi2m2_csn0 */
+ <3 RK_PC4 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi2m2_csn1: spi2m2-csn1 {
+ rockchip,pins =
+ /* spi2m2_csn1 */
+ <3 RK_PA5 10 &pcfg_pull_none>;
+ };
+ };
+
+ spi3 {
+ /omit-if-no-ref/
+ spi3m0_pins: spi3m0-pins {
+ rockchip,pins =
+ /* spi3_clk_m0 */
+ <3 RK_PA0 10 &pcfg_pull_none>,
+ /* spi3_miso_m0 */
+ <3 RK_PA2 10 &pcfg_pull_none>,
+ /* spi3_mosi_m0 */
+ <3 RK_PA1 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi3m0_csn0: spi3m0-csn0 {
+ rockchip,pins =
+ /* spi3m0_csn0 */
+ <3 RK_PA3 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi3m0_csn1: spi3m0-csn1 {
+ rockchip,pins =
+ /* spi3m0_csn1 */
+ <2 RK_PD7 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi3m1_pins: spi3m1-pins {
+ rockchip,pins =
+ /* spi3_clk_m1 */
+ <3 RK_PD4 10 &pcfg_pull_none>,
+ /* spi3_miso_m1 */
+ <3 RK_PD5 10 &pcfg_pull_none>,
+ /* spi3_mosi_m1 */
+ <3 RK_PD6 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi3m1_csn0: spi3m1-csn0 {
+ rockchip,pins =
+ /* spi3m1_csn0 */
+ <3 RK_PB6 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi3m1_csn1: spi3m1-csn1 {
+ rockchip,pins =
+ /* spi3m1_csn1 */
+ <3 RK_PD7 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi3m2_pins: spi3m2-pins {
+ rockchip,pins =
+ /* spi3_clk_m2 */
+ <4 RK_PA7 9 &pcfg_pull_none>,
+ /* spi3_miso_m2 */
+ <4 RK_PA6 9 &pcfg_pull_none>,
+ /* spi3_mosi_m2 */
+ <4 RK_PA4 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi3m2_csn0: spi3m2-csn0 {
+ rockchip,pins =
+ /* spi3m2_csn0 */
+ <4 RK_PA3 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi3m2_csn1: spi3m2-csn1 {
+ rockchip,pins =
+ /* spi3m2_csn1 */
+ <4 RK_PB3 10 &pcfg_pull_none>;
+ };
+ };
+
+ spi4 {
+ /omit-if-no-ref/
+ spi4m0_pins: spi4m0-pins {
+ rockchip,pins =
+ /* spi4_clk_m0 */
+ <4 RK_PC7 12 &pcfg_pull_none>,
+ /* spi4_miso_m0 */
+ <4 RK_PC6 12 &pcfg_pull_none>,
+ /* spi4_mosi_m0 */
+ <4 RK_PC5 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi4m0_csn0: spi4m0-csn0 {
+ rockchip,pins =
+ /* spi4m0_csn0 */
+ <4 RK_PC4 12 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi4m0_csn1: spi4m0-csn1 {
+ rockchip,pins =
+ /* spi4m0_csn1 */
+ <4 RK_PC0 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi4m1_pins: spi4m1-pins {
+ rockchip,pins =
+ /* spi4_clk_m1 */
+ <3 RK_PD1 10 &pcfg_pull_none>,
+ /* spi4_miso_m1 */
+ <3 RK_PC2 10 &pcfg_pull_none>,
+ /* spi4_mosi_m1 */
+ <3 RK_PC3 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi4m1_csn0: spi4m1-csn0 {
+ rockchip,pins =
+ /* spi4m1_csn0 */
+ <3 RK_PB1 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi4m1_csn1: spi4m1-csn1 {
+ rockchip,pins =
+ /* spi4m1_csn1 */
+ <3 RK_PD2 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi4m2_pins: spi4m2-pins {
+ rockchip,pins =
+ /* spi4_clk_m2 */
+ <4 RK_PB0 9 &pcfg_pull_none>,
+ /* spi4_miso_m2 */
+ <4 RK_PB2 9 &pcfg_pull_none>,
+ /* spi4_mosi_m2 */
+ <4 RK_PB1 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi4m2_csn0: spi4m2-csn0 {
+ rockchip,pins =
+ /* spi4m2_csn0 */
+ <4 RK_PB3 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi4m2_csn1: spi4m2-csn1 {
+ rockchip,pins =
+ /* spi4m2_csn1 */
+ <4 RK_PA5 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi4m3_pins: spi4m3-pins {
+ rockchip,pins =
+ /* spi4_clk_m3 */
+ <2 RK_PB3 10 &pcfg_pull_none>,
+ /* spi4_miso_m3 */
+ <2 RK_PB5 10 &pcfg_pull_none>,
+ /* spi4_mosi_m3 */
+ <2 RK_PB4 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ spi4m3_csn0: spi4m3-csn0 {
+ rockchip,pins =
+ /* spi4m3_csn0 */
+ <2 RK_PB2 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ spi4m3_csn1: spi4m3-csn1 {
+ rockchip,pins =
+ /* spi4m3_csn1 */
+ <2 RK_PA6 10 &pcfg_pull_none>;
+ };
+ };
+
+ test_clk {
+ /omit-if-no-ref/
+ test_clk_pins: test_clk-pins {
+ rockchip,pins =
+ /* test_clk_out */
+ <2 RK_PA5 5 &pcfg_pull_none>;
+ };
+ };
+
+ tsadc {
+ /omit-if-no-ref/
+ tsadcm0_pins: tsadcm0-pins {
+ rockchip,pins =
+ /* tsadc_ctrl_m0 */
+ <0 RK_PA1 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ tsadcm1_pins: tsadcm1-pins {
+ rockchip,pins =
+ /* tsadc_ctrl_m1 */
+ <0 RK_PA3 10 &pcfg_pull_none>;
+ };
+ };
+
+ tsadc_ctrl {
+ /omit-if-no-ref/
+ tsadc_ctrl_pins: tsadc_ctrl-pins {
+ rockchip,pins =
+ /* tsadc_ctrl_org */
+ <0 RK_PA1 10 &pcfg_pull_none>;
+ };
+ };
+
+ uart0 {
+ /omit-if-no-ref/
+ uart0m0_xfer: uart0m0-xfer {
+ rockchip,pins =
+ /* uart0_rx_m0 */
+ <0 RK_PD5 9 &pcfg_pull_up>,
+ /* uart0_tx_m0 */
+ <0 RK_PD4 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart0m1_xfer: uart0m1-xfer {
+ rockchip,pins =
+ /* uart0_rx_m1 */
+ <2 RK_PA0 9 &pcfg_pull_up>,
+ /* uart0_tx_m1 */
+ <2 RK_PA1 9 &pcfg_pull_up>;
+ };
+ };
+
+ uart1 {
+ /omit-if-no-ref/
+ uart1m0_xfer: uart1m0-xfer {
+ rockchip,pins =
+ /* uart1_rx_m0 */
+ <0 RK_PC0 10 &pcfg_pull_up>,
+ /* uart1_tx_m0 */
+ <0 RK_PB7 10 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart1m0_ctsn: uart1m0-ctsn {
+ rockchip,pins =
+ /* uart1m0_ctsn */
+ <0 RK_PD2 13 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart1m0_rtsn: uart1m0-rtsn {
+ rockchip,pins =
+ /* uart1m0_rtsn */
+ <0 RK_PD3 13 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart1m1_xfer: uart1m1-xfer {
+ rockchip,pins =
+ /* uart1_rx_m1 */
+ <2 RK_PB1 9 &pcfg_pull_up>,
+ /* uart1_tx_m1 */
+ <2 RK_PB0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart1m1_ctsn: uart1m1-ctsn {
+ rockchip,pins =
+ /* uart1m1_ctsn */
+ <2 RK_PB2 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart1m1_rtsn: uart1m1-rtsn {
+ rockchip,pins =
+ /* uart1m1_rtsn */
+ <2 RK_PB3 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart1m2_xfer: uart1m2-xfer {
+ rockchip,pins =
+ /* uart1_rx_m2 */
+ <3 RK_PA6 9 &pcfg_pull_up>,
+ /* uart1_tx_m2 */
+ <3 RK_PA7 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart1m2_ctsn: uart1m2-ctsn {
+ rockchip,pins =
+ /* uart1m2_ctsn */
+ <3 RK_PA4 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart1m2_rtsn: uart1m2-rtsn {
+ rockchip,pins =
+ /* uart1m2_rtsn */
+ <3 RK_PA5 9 &pcfg_pull_none>;
+ };
+ };
+
+ uart2 {
+ /omit-if-no-ref/
+ uart2m0_xfer: uart2m0-xfer {
+ rockchip,pins =
+ /* uart2_rx_m0 */
+ <1 RK_PC7 9 &pcfg_pull_up>,
+ /* uart2_tx_m0 */
+ <1 RK_PC6 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart2m0_ctsn: uart2m0-ctsn {
+ rockchip,pins =
+ /* uart2m0_ctsn */
+ <1 RK_PC5 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart2m0_rtsn: uart2m0-rtsn {
+ rockchip,pins =
+ /* uart2m0_rtsn */
+ <1 RK_PC4 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart2m1_xfer: uart2m1-xfer {
+ rockchip,pins =
+ /* uart2_rx_m1 */
+ <4 RK_PB4 10 &pcfg_pull_up>,
+ /* uart2_tx_m1 */
+ <4 RK_PB5 10 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart2m1_ctsn: uart2m1-ctsn {
+ rockchip,pins =
+ /* uart2m1_ctsn */
+ <4 RK_PB1 12 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart2m1_rtsn: uart2m1-rtsn {
+ rockchip,pins =
+ /* uart2m1_rtsn */
+ <4 RK_PB0 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart2m2_xfer: uart2m2-xfer {
+ rockchip,pins =
+ /* uart2_rx_m2 */
+ <3 RK_PB7 9 &pcfg_pull_up>,
+ /* uart2_tx_m2 */
+ <3 RK_PC0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart2m2_ctsn: uart2m2-ctsn {
+ rockchip,pins =
+ /* uart2m2_ctsn */
+ <3 RK_PD3 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart2m2_rtsn: uart2m2-rtsn {
+ rockchip,pins =
+ /* uart2m2_rtsn */
+ <3 RK_PD2 9 &pcfg_pull_none>;
+ };
+ };
+
+ uart3 {
+ /omit-if-no-ref/
+ uart3m0_xfer: uart3m0-xfer {
+ rockchip,pins =
+ /* uart3_rx_m0 */
+ <3 RK_PA1 9 &pcfg_pull_up>,
+ /* uart3_tx_m0 */
+ <3 RK_PA0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart3m0_ctsn: uart3m0-ctsn {
+ rockchip,pins =
+ /* uart3m0_ctsn */
+ <3 RK_PA2 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart3m0_rtsn: uart3m0-rtsn {
+ rockchip,pins =
+ /* uart3m0_rtsn */
+ <3 RK_PA3 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart3m1_xfer: uart3m1-xfer {
+ rockchip,pins =
+ /* uart3_rx_m1 */
+ <4 RK_PA1 9 &pcfg_pull_up>,
+ /* uart3_tx_m1 */
+ <4 RK_PA0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart3m1_ctsn: uart3m1-ctsn {
+ rockchip,pins =
+ /* uart3m1_ctsn */
+ <3 RK_PB7 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart3m1_rtsn: uart3m1-rtsn {
+ rockchip,pins =
+ /* uart3m1_rtsn */
+ <3 RK_PC0 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart3m2_xfer: uart3m2-xfer {
+ rockchip,pins =
+ /* uart3_rx_m2 */
+ <1 RK_PC1 9 &pcfg_pull_up>,
+ /* uart3_tx_m2 */
+ <1 RK_PC0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart3m2_ctsn: uart3m2-ctsn {
+ rockchip,pins =
+ /* uart3m2_ctsn */
+ <1 RK_PB6 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart3m2_rtsn: uart3m2-rtsn {
+ rockchip,pins =
+ /* uart3m2_rtsn */
+ <1 RK_PB7 9 &pcfg_pull_none>;
+ };
+ };
+
+ uart4 {
+ /omit-if-no-ref/
+ uart4m0_xfer: uart4m0-xfer {
+ rockchip,pins =
+ /* uart4_rx_m0 */
+ <2 RK_PD1 9 &pcfg_pull_up>,
+ /* uart4_tx_m0 */
+ <2 RK_PD0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart4m0_ctsn: uart4m0-ctsn {
+ rockchip,pins =
+ /* uart4m0_ctsn */
+ <2 RK_PC6 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart4m0_rtsn: uart4m0-rtsn {
+ rockchip,pins =
+ /* uart4m0_rtsn */
+ <2 RK_PC7 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart4m1_xfer: uart4m1-xfer {
+ rockchip,pins =
+ /* uart4_rx_m1 */
+ <1 RK_PC5 9 &pcfg_pull_up>,
+ /* uart4_tx_m1 */
+ <1 RK_PC4 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart4m1_ctsn: uart4m1-ctsn {
+ rockchip,pins =
+ /* uart4m1_ctsn */
+ <1 RK_PC3 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart4m1_rtsn: uart4m1-rtsn {
+ rockchip,pins =
+ /* uart4m1_rtsn */
+ <1 RK_PC2 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart4m2_xfer: uart4m2-xfer {
+ rockchip,pins =
+ /* uart4_rx_m2 */
+ <0 RK_PB5 10 &pcfg_pull_up>,
+ /* uart4_tx_m2 */
+ <0 RK_PB4 10 &pcfg_pull_up>;
+ };
+ };
+
+ uart5 {
+ /omit-if-no-ref/
+ uart5m0_xfer: uart5m0-xfer {
+ rockchip,pins =
+ /* uart5_rx_m0 */
+ <3 RK_PD4 9 &pcfg_pull_up>,
+ /* uart5_tx_m0 */
+ <3 RK_PD5 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart5m0_ctsn: uart5m0-ctsn {
+ rockchip,pins =
+ /* uart5m0_ctsn */
+ <3 RK_PD6 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart5m0_rtsn: uart5m0-rtsn {
+ rockchip,pins =
+ /* uart5m0_rtsn */
+ <3 RK_PD7 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart5m1_xfer: uart5m1-xfer {
+ rockchip,pins =
+ /* uart5_rx_m1 */
+ <4 RK_PB1 10 &pcfg_pull_up>,
+ /* uart5_tx_m1 */
+ <4 RK_PB0 10 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart5m1_ctsn: uart5m1-ctsn {
+ rockchip,pins =
+ /* uart5m1_ctsn */
+ <4 RK_PA5 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart5m1_rtsn: uart5m1-rtsn {
+ rockchip,pins =
+ /* uart5m1_rtsn */
+ <4 RK_PA3 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart5m2_xfer: uart5m2-xfer {
+ rockchip,pins =
+ /* uart5_rx_m2 */
+ <2 RK_PA4 9 &pcfg_pull_up>,
+ /* uart5_tx_m2 */
+ <2 RK_PA5 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart5m2_ctsn: uart5m2-ctsn {
+ rockchip,pins =
+ /* uart5m2_ctsn */
+ <2 RK_PA3 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart5m2_rtsn: uart5m2-rtsn {
+ rockchip,pins =
+ /* uart5m2_rtsn */
+ <2 RK_PA2 10 &pcfg_pull_none>;
+ };
+ };
+
+ uart6 {
+ /omit-if-no-ref/
+ uart6m0_xfer: uart6m0-xfer {
+ rockchip,pins =
+ /* uart6_rx_m0 */
+ <4 RK_PA6 10 &pcfg_pull_up>,
+ /* uart6_tx_m0 */
+ <4 RK_PA4 10 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart6m0_ctsn: uart6m0-ctsn {
+ rockchip,pins =
+ /* uart6m0_ctsn */
+ <4 RK_PB1 11 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart6m0_rtsn: uart6m0-rtsn {
+ rockchip,pins =
+ /* uart6m0_rtsn */
+ <4 RK_PB0 11 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart6m1_xfer: uart6m1-xfer {
+ rockchip,pins =
+ /* uart6_rx_m1 */
+ <2 RK_PD3 9 &pcfg_pull_up>,
+ /* uart6_tx_m1 */
+ <2 RK_PD2 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart6m1_ctsn: uart6m1-ctsn {
+ rockchip,pins =
+ /* uart6m1_ctsn */
+ <2 RK_PD5 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart6m1_rtsn: uart6m1-rtsn {
+ rockchip,pins =
+ /* uart6m1_rtsn */
+ <2 RK_PD4 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart6m2_xfer: uart6m2-xfer {
+ rockchip,pins =
+ /* uart6_rx_m2 */
+ <1 RK_PB3 9 &pcfg_pull_up>,
+ /* uart6_tx_m2 */
+ <1 RK_PB0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart6m2_ctsn: uart6m2-ctsn {
+ rockchip,pins =
+ /* uart6m2_ctsn */
+ <1 RK_PA3 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart6m2_rtsn: uart6m2-rtsn {
+ rockchip,pins =
+ /* uart6m2_rtsn */
+ <1 RK_PA2 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart6m3_xfer: uart6m3-xfer {
+ rockchip,pins =
+ /* uart6_rx_m3 */
+ <4 RK_PC5 13 &pcfg_pull_up>,
+ /* uart6_tx_m3 */
+ <4 RK_PC4 13 &pcfg_pull_up>;
+ };
+ };
+
+ uart7 {
+ /omit-if-no-ref/
+ uart7m0_xfer: uart7m0-xfer {
+ rockchip,pins =
+ /* uart7_rx_m0 */
+ <2 RK_PB7 9 &pcfg_pull_up>,
+ /* uart7_tx_m0 */
+ <2 RK_PB6 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart7m0_ctsn: uart7m0-ctsn {
+ rockchip,pins =
+ /* uart7m0_ctsn */
+ <2 RK_PB4 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart7m0_rtsn: uart7m0-rtsn {
+ rockchip,pins =
+ /* uart7m0_rtsn */
+ <2 RK_PB5 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart7m1_xfer: uart7m1-xfer {
+ rockchip,pins =
+ /* uart7_rx_m1 */
+ <1 RK_PA3 9 &pcfg_pull_up>,
+ /* uart7_tx_m1 */
+ <1 RK_PA2 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart7m1_ctsn: uart7m1-ctsn {
+ rockchip,pins =
+ /* uart7m1_ctsn */
+ <1 RK_PA1 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart7m1_rtsn: uart7m1-rtsn {
+ rockchip,pins =
+ /* uart7m1_rtsn */
+ <1 RK_PA0 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart7m2_xfer: uart7m2-xfer {
+ rockchip,pins =
+ /* uart7_rx_m2 */
+ <2 RK_PA0 10 &pcfg_pull_up>,
+ /* uart7_tx_m2 */
+ <2 RK_PA1 10 &pcfg_pull_up>;
+ };
+ };
+
+ uart8 {
+ /omit-if-no-ref/
+ uart8m0_xfer: uart8m0-xfer {
+ rockchip,pins =
+ /* uart8_rx_m0 */
+ <3 RK_PC5 9 &pcfg_pull_up>,
+ /* uart8_tx_m0 */
+ <3 RK_PC6 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart8m0_ctsn: uart8m0-ctsn {
+ rockchip,pins =
+ /* uart8m0_ctsn */
+ <3 RK_PD0 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart8m0_rtsn: uart8m0-rtsn {
+ rockchip,pins =
+ /* uart8m0_rtsn */
+ <3 RK_PC7 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart8m1_xfer: uart8m1-xfer {
+ rockchip,pins =
+ /* uart8_rx_m1 */
+ <2 RK_PA7 9 &pcfg_pull_up>,
+ /* uart8_tx_m1 */
+ <2 RK_PA6 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart8m1_ctsn: uart8m1-ctsn {
+ rockchip,pins =
+ /* uart8m1_ctsn */
+ <2 RK_PB7 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart8m1_rtsn: uart8m1-rtsn {
+ rockchip,pins =
+ /* uart8m1_rtsn */
+ <2 RK_PB6 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart8m2_xfer: uart8m2-xfer {
+ rockchip,pins =
+ /* uart8_rx_m2 */
+ <0 RK_PC2 10 &pcfg_pull_up>,
+ /* uart8_tx_m2 */
+ <0 RK_PC1 10 &pcfg_pull_up>;
+ };
+ };
+
+ uart9 {
+ /omit-if-no-ref/
+ uart9m0_xfer: uart9m0-xfer {
+ rockchip,pins =
+ /* uart9_rx_m0 */
+ <2 RK_PC0 9 &pcfg_pull_up>,
+ /* uart9_tx_m0 */
+ <2 RK_PC1 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart9m0_ctsn: uart9m0-ctsn {
+ rockchip,pins =
+ /* uart9m0_ctsn */
+ <2 RK_PD7 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart9m0_rtsn: uart9m0-rtsn {
+ rockchip,pins =
+ /* uart9m0_rtsn */
+ <2 RK_PD6 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart9m1_xfer: uart9m1-xfer {
+ rockchip,pins =
+ /* uart9_rx_m1 */
+ <3 RK_PB2 9 &pcfg_pull_up>,
+ /* uart9_tx_m1 */
+ <3 RK_PB3 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart9m1_ctsn: uart9m1-ctsn {
+ rockchip,pins =
+ /* uart9m1_ctsn */
+ <3 RK_PB5 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart9m1_rtsn: uart9m1-rtsn {
+ rockchip,pins =
+ /* uart9m1_rtsn */
+ <3 RK_PB4 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart9m2_xfer: uart9m2-xfer {
+ rockchip,pins =
+ /* uart9_rx_m2 */
+ <4 RK_PC3 13 &pcfg_pull_up>,
+ /* uart9_tx_m2 */
+ <4 RK_PC2 13 &pcfg_pull_up>;
+ };
+ };
+
+ uart10 {
+ /omit-if-no-ref/
+ uart10m0_xfer: uart10m0-xfer {
+ rockchip,pins =
+ /* uart10_rx_m0 */
+ <3 RK_PB0 9 &pcfg_pull_up>,
+ /* uart10_tx_m0 */
+ <3 RK_PB1 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart10m0_ctsn: uart10m0-ctsn {
+ rockchip,pins =
+ /* uart10m0_ctsn */
+ <3 RK_PA6 10 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart10m0_rtsn: uart10m0-rtsn {
+ rockchip,pins =
+ /* uart10m0_rtsn */
+ <3 RK_PA7 10 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart10m1_xfer: uart10m1-xfer {
+ rockchip,pins =
+ /* uart10_rx_m1 */
+ <1 RK_PD1 9 &pcfg_pull_up>,
+ /* uart10_tx_m1 */
+ <1 RK_PD0 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart10m1_ctsn: uart10m1-ctsn {
+ rockchip,pins =
+ /* uart10m1_ctsn */
+ <1 RK_PD5 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart10m1_rtsn: uart10m1-rtsn {
+ rockchip,pins =
+ /* uart10m1_rtsn */
+ <1 RK_PD4 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart10m2_xfer: uart10m2-xfer {
+ rockchip,pins =
+ /* uart10_rx_m2 */
+ <0 RK_PC5 10 &pcfg_pull_up>,
+ /* uart10_tx_m2 */
+ <0 RK_PC4 10 &pcfg_pull_up>;
+ };
+ };
+
+ uart11 {
+ /omit-if-no-ref/
+ uart11m0_xfer: uart11m0-xfer {
+ rockchip,pins =
+ /* uart11_rx_m0 */
+ <3 RK_PC1 9 &pcfg_pull_up>,
+ /* uart11_tx_m0 */
+ <3 RK_PC4 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart11m0_ctsn: uart11m0-ctsn {
+ rockchip,pins =
+ /* uart11m0_ctsn */
+ <3 RK_PC3 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart11m0_rtsn: uart11m0-rtsn {
+ rockchip,pins =
+ /* uart11m0_rtsn */
+ <3 RK_PC2 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart11m1_xfer: uart11m1-xfer {
+ rockchip,pins =
+ /* uart11_rx_m1 */
+ <2 RK_PC5 9 &pcfg_pull_up>,
+ /* uart11_tx_m1 */
+ <2 RK_PC4 9 &pcfg_pull_up>;
+ };
+
+ /omit-if-no-ref/
+ uart11m1_ctsn: uart11m1-ctsn {
+ rockchip,pins =
+ /* uart11m1_ctsn */
+ <2 RK_PC2 9 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart11m1_rtsn: uart11m1-rtsn {
+ rockchip,pins =
+ /* uart11m1_rtsn */
+ <2 RK_PC3 9 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ uart11m2_xfer: uart11m2-xfer {
+ rockchip,pins =
+ /* uart11_rx_m2 */
+ <4 RK_PC1 13 &pcfg_pull_up>,
+ /* uart11_tx_m2 */
+ <4 RK_PC0 13 &pcfg_pull_up>;
+ };
+ };
+
+ ufs {
+ /omit-if-no-ref/
+ ufs_refclk: ufs-refclk {
+ rockchip,pins =
+ /* ufs_refclk */
+ <4 RK_PD1 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ ufs_rst: ufs-rst {
+ rockchip,pins =
+ /* ufs_rstn */
+ <4 RK_PD0 1 &pcfg_pull_none>;
+ };
+ };
+
+ ufs_testdata0 {
+ /omit-if-no-ref/
+ ufs_testdata0_test: ufs_testdata0-test {
+ rockchip,pins =
+ /* ufs_testdata0_out */
+ <4 RK_PC4 4 &pcfg_pull_none>;
+ };
+ };
+
+ ufs_testdata1 {
+ /omit-if-no-ref/
+ ufs_testdata1_test: ufs_testdata1-test {
+ rockchip,pins =
+ /* ufs_testdata1_out */
+ <4 RK_PC5 4 &pcfg_pull_none>;
+ };
+ };
+
+ ufs_testdata2 {
+ /omit-if-no-ref/
+ ufs_testdata2_test: ufs_testdata2-test {
+ rockchip,pins =
+ /* ufs_testdata2_out */
+ <4 RK_PC6 4 &pcfg_pull_none>;
+ };
+ };
+
+ ufs_testdata3 {
+ /omit-if-no-ref/
+ ufs_testdata3_test: ufs_testdata3-test {
+ rockchip,pins =
+ /* ufs_testdata3_out */
+ <4 RK_PC7 4 &pcfg_pull_none>;
+ };
+ };
+
+ vi_cif {
+ /omit-if-no-ref/
+ vi_cif_pins: vi_cif-pins {
+ rockchip,pins =
+ /* vi_cif_clki */
+ <3 RK_PA3 1 &pcfg_pull_none>,
+ /* vi_cif_clko */
+ <3 RK_PA2 1 &pcfg_pull_none>,
+ /* vi_cif_d0 */
+ <2 RK_PC5 1 &pcfg_pull_none>,
+ /* vi_cif_d1 */
+ <2 RK_PC4 1 &pcfg_pull_none>,
+ /* vi_cif_d2 */
+ <2 RK_PC3 1 &pcfg_pull_none>,
+ /* vi_cif_d3 */
+ <2 RK_PC2 1 &pcfg_pull_none>,
+ /* vi_cif_d4 */
+ <2 RK_PC1 1 &pcfg_pull_none>,
+ /* vi_cif_d5 */
+ <2 RK_PC0 1 &pcfg_pull_none>,
+ /* vi_cif_d6 */
+ <2 RK_PB7 1 &pcfg_pull_none>,
+ /* vi_cif_d7 */
+ <2 RK_PB6 1 &pcfg_pull_none>,
+ /* vi_cif_d8 */
+ <2 RK_PB5 1 &pcfg_pull_none>,
+ /* vi_cif_d9 */
+ <2 RK_PB4 1 &pcfg_pull_none>,
+ /* vi_cif_d10 */
+ <2 RK_PB3 1 &pcfg_pull_none>,
+ /* vi_cif_d11 */
+ <2 RK_PB2 1 &pcfg_pull_none>,
+ /* vi_cif_d12 */
+ <2 RK_PB1 1 &pcfg_pull_none>,
+ /* vi_cif_d13 */
+ <2 RK_PB0 1 &pcfg_pull_none>,
+ /* vi_cif_d14 */
+ <2 RK_PA7 1 &pcfg_pull_none>,
+ /* vi_cif_d15 */
+ <2 RK_PA6 1 &pcfg_pull_none>,
+ /* vi_cif_href */
+ <3 RK_PA0 1 &pcfg_pull_none>,
+ /* vi_cif_vsync */
+ <3 RK_PA1 1 &pcfg_pull_none>;
+ };
+ };
+
+ vo_lcdc {
+ /omit-if-no-ref/
+ vo_lcdc_pins: vo_lcdc-pins {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d0 */
+ <3 RK_PD3 1 &pcfg_pull_none>,
+ /* vo_lcdc_d1 */
+ <3 RK_PD2 1 &pcfg_pull_none>,
+ /* vo_lcdc_d2 */
+ <3 RK_PD1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d3 */
+ <3 RK_PD0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d4 */
+ <3 RK_PC7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d5 */
+ <3 RK_PC6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d6 */
+ <3 RK_PC5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d7 */
+ <3 RK_PC4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d8 */
+ <3 RK_PC3 1 &pcfg_pull_none>,
+ /* vo_lcdc_d9 */
+ <3 RK_PC2 1 &pcfg_pull_none>,
+ /* vo_lcdc_d10 */
+ <3 RK_PC1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d11 */
+ <3 RK_PC0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d12 */
+ <3 RK_PB7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d13 */
+ <3 RK_PB6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d14 */
+ <3 RK_PB5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d15 */
+ <3 RK_PB4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d16 */
+ <3 RK_PB3 1 &pcfg_pull_none>,
+ /* vo_lcdc_d17 */
+ <3 RK_PB2 1 &pcfg_pull_none>,
+ /* vo_lcdc_d18 */
+ <3 RK_PB1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d19 */
+ <3 RK_PB0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d20 */
+ <3 RK_PA7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d21 */
+ <3 RK_PA6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d22 */
+ <3 RK_PA5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d23 */
+ <3 RK_PA4 1 &pcfg_pull_none>,
+ /* vo_lcdc_den */
+ <3 RK_PD4 1 &pcfg_pull_none>,
+ /* vo_lcdc_hsync */
+ <3 RK_PD5 1 &pcfg_pull_none>,
+ /* vo_lcdc_vsync */
+ <3 RK_PD6 1 &pcfg_pull_none>;
+ };
+ };
+
+ vo_post {
+ /omit-if-no-ref/
+ vo_post_pins: vo_post-pins {
+ rockchip,pins =
+ /* vo_post_empty */
+ <4 RK_PA1 1 &pcfg_pull_none>;
+ };
+ };
+
+ vp0_sync {
+ /omit-if-no-ref/
+ vp0_sync_pins: vp0_sync-pins {
+ rockchip,pins =
+ /* vp0_sync_out */
+ <4 RK_PC5 3 &pcfg_pull_none>;
+ };
+ };
+
+ vp1_sync {
+ /omit-if-no-ref/
+ vp1_sync_pins: vp1_sync-pins {
+ rockchip,pins =
+ /* vp1_sync_out */
+ <4 RK_PC6 3 &pcfg_pull_none>;
+ };
+ };
+
+ vp2_sync {
+ /omit-if-no-ref/
+ vp2_sync_pins: vp2_sync-pins {
+ rockchip,pins =
+ /* vp2_sync_out */
+ <4 RK_PC7 3 &pcfg_pull_none>;
+ };
+ };
+};
+
+/*
+ * This part is edited handly.
+ */
+&pinctrl {
+ pmic {
+ /omit-if-no-ref/
+ pmic_pins: pmic-pins {
+ rockchip,pins =
+ /* pmic_int */
+ <0 RK_PA6 9 &pcfg_pull_up>,
+ /* pmic_sleep */
+ <0 RK_PA4 9 &pcfg_pull_none>;
+ };
+ };
+
+ vo {
+ /omit-if-no-ref/
+ bt1120_pins: bt1120-pins {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d3 */
+ <3 RK_PD0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d4 */
+ <3 RK_PC7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d5 */
+ <3 RK_PC6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d6 */
+ <3 RK_PC5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d7 */
+ <3 RK_PC4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d10 */
+ <3 RK_PC1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d11 */
+ <3 RK_PC0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d12 */
+ <3 RK_PB7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d13 */
+ <3 RK_PB6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d14 */
+ <3 RK_PB5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d15 */
+ <3 RK_PB4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d19 */
+ <3 RK_PB0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d20 */
+ <3 RK_PA7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d21 */
+ <3 RK_PA6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d22 */
+ <3 RK_PA5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d23 */
+ <3 RK_PA4 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ bt656_pins: bt656-pins {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d3 */
+ <3 RK_PD0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d4 */
+ <3 RK_PC7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d5 */
+ <3 RK_PC6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d6 */
+ <3 RK_PC5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d7 */
+ <3 RK_PC4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d10 */
+ <3 RK_PC1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d11 */
+ <3 RK_PC0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d12 */
+ <3 RK_PB7 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ rgb3x8_pins_m0: rgb3x8-pins-m0 {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d3 */
+ <3 RK_PD0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d4 */
+ <3 RK_PC7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d5 */
+ <3 RK_PC6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d6 */
+ <3 RK_PC5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d7 */
+ <3 RK_PC4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d10 */
+ <3 RK_PC1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d11 */
+ <3 RK_PC0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d12 */
+ <3 RK_PB7 1 &pcfg_pull_none>,
+ /* vo_lcdc_den */
+ <3 RK_PD4 1 &pcfg_pull_none>,
+ /* vo_lcdc_hsync */
+ <3 RK_PD5 1 &pcfg_pull_none>,
+ /* vo_lcdc_vsync */
+ <3 RK_PD6 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ rgb3x8_pins_m1: rgb3x8-pins-m1 {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d13 */
+ <3 RK_PB6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d14 */
+ <3 RK_PB5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d15 */
+ <3 RK_PB4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d19 */
+ <3 RK_PB0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d20 */
+ <3 RK_PA7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d21 */
+ <3 RK_PA6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d22 */
+ <3 RK_PA5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d23 */
+ <3 RK_PA4 1 &pcfg_pull_none>,
+ /* vo_lcdc_den */
+ <3 RK_PD4 1 &pcfg_pull_none>,
+ /* vo_lcdc_hsync */
+ <3 RK_PD5 1 &pcfg_pull_none>,
+ /* vo_lcdc_vsync */
+ <3 RK_PD6 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ rgb565_pins: rgb565-pins {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d3 */
+ <3 RK_PD0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d4 */
+ <3 RK_PC7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d5 */
+ <3 RK_PC6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d6 */
+ <3 RK_PC5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d7 */
+ <3 RK_PC4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d10 */
+ <3 RK_PC1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d11 */
+ <3 RK_PC0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d12 */
+ <3 RK_PB7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d13 */
+ <3 RK_PB6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d14 */
+ <3 RK_PB5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d15 */
+ <3 RK_PB4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d19 */
+ <3 RK_PB0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d20 */
+ <3 RK_PA7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d21 */
+ <3 RK_PA6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d22 */
+ <3 RK_PA5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d23 */
+ <3 RK_PA4 1 &pcfg_pull_none>,
+ /* vo_lcdc_den */
+ <3 RK_PD4 1 &pcfg_pull_none>,
+ /* vo_lcdc_hsync */
+ <3 RK_PD5 1 &pcfg_pull_none>,
+ /* vo_lcdc_vsync */
+ <3 RK_PD6 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ rgb666_pins: rgb666-pins {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d2 */
+ <3 RK_PD1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d3 */
+ <3 RK_PD0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d4 */
+ <3 RK_PC7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d5 */
+ <3 RK_PC6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d6 */
+ <3 RK_PC5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d7 */
+ <3 RK_PC4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d10 */
+ <3 RK_PC1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d11 */
+ <3 RK_PC0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d12 */
+ <3 RK_PB7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d13 */
+ <3 RK_PB6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d14 */
+ <3 RK_PB5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d15 */
+ <3 RK_PB4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d18 */
+ <3 RK_PB1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d19 */
+ <3 RK_PB0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d20 */
+ <3 RK_PA7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d21 */
+ <3 RK_PA6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d22 */
+ <3 RK_PA5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d23 */
+ <3 RK_PA4 1 &pcfg_pull_none>,
+ /* vo_lcdc_den */
+ <3 RK_PD4 1 &pcfg_pull_none>,
+ /* vo_lcdc_hsync */
+ <3 RK_PD5 1 &pcfg_pull_none>,
+ /* vo_lcdc_vsync */
+ <3 RK_PD6 1 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ rgb888_pins: rgb888-pins {
+ rockchip,pins =
+ /* vo_lcdc_clk */
+ <3 RK_PD7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d0 */
+ <3 RK_PD3 1 &pcfg_pull_none>,
+ /* vo_lcdc_d1 */
+ <3 RK_PD2 1 &pcfg_pull_none>,
+ /* vo_lcdc_d2 */
+ <3 RK_PD1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d3 */
+ <3 RK_PD0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d4 */
+ <3 RK_PC7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d5 */
+ <3 RK_PC6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d6 */
+ <3 RK_PC5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d7 */
+ <3 RK_PC4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d8 */
+ <3 RK_PC3 1 &pcfg_pull_none>,
+ /* vo_lcdc_d9 */
+ <3 RK_PC2 1 &pcfg_pull_none>,
+ /* vo_lcdc_d10 */
+ <3 RK_PC1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d11 */
+ <3 RK_PC0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d12 */
+ <3 RK_PB7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d13 */
+ <3 RK_PB6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d14 */
+ <3 RK_PB5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d15 */
+ <3 RK_PB4 1 &pcfg_pull_none>,
+ /* vo_lcdc_d16 */
+ <3 RK_PB3 1 &pcfg_pull_none>,
+ /* vo_lcdc_d17 */
+ <3 RK_PB2 1 &pcfg_pull_none>,
+ /* vo_lcdc_d18 */
+ <3 RK_PB1 1 &pcfg_pull_none>,
+ /* vo_lcdc_d19 */
+ <3 RK_PB0 1 &pcfg_pull_none>,
+ /* vo_lcdc_d20 */
+ <3 RK_PA7 1 &pcfg_pull_none>,
+ /* vo_lcdc_d21 */
+ <3 RK_PA6 1 &pcfg_pull_none>,
+ /* vo_lcdc_d22 */
+ <3 RK_PA5 1 &pcfg_pull_none>,
+ /* vo_lcdc_d23 */
+ <3 RK_PA4 1 &pcfg_pull_none>,
+ /* vo_lcdc_den */
+ <3 RK_PD4 1 &pcfg_pull_none>,
+ /* vo_lcdc_hsync */
+ <3 RK_PD5 1 &pcfg_pull_none>,
+ /* vo_lcdc_vsync */
+ <3 RK_PD6 1 &pcfg_pull_none>;
+ };
+ };
+
+ vo_ebc {
+ /omit-if-no-ref/
+ vo_ebc_pins: vo_ebc-pins {
+ rockchip,pins =
+ /* vo_ebc_gdclk */
+ <3 RK_PD5 2 &pcfg_pull_none>,
+ /* vo_ebc_gdoe */
+ <3 RK_PA6 2 &pcfg_pull_none>,
+ /* vo_ebc_gdsp */
+ <3 RK_PA5 2 &pcfg_pull_none>,
+ /* vo_ebc_sdce0 */
+ <3 RK_PB3 2 &pcfg_pull_none>,
+ /* vo_ebc_sdclk */
+ <3 RK_PD6 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo0 */
+ <3 RK_PD3 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo1 */
+ <3 RK_PD2 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo2 */
+ <3 RK_PD1 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo3 */
+ <3 RK_PD0 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo4 */
+ <3 RK_PC7 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo5 */
+ <3 RK_PC6 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo6 */
+ <3 RK_PC5 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo7 */
+ <3 RK_PC4 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo8 */
+ <3 RK_PC3 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo9 */
+ <3 RK_PC2 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo10 */
+ <3 RK_PC1 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo11 */
+ <3 RK_PC0 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo12 */
+ <3 RK_PB7 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo13 */
+ <3 RK_PB6 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo14 */
+ <3 RK_PB5 2 &pcfg_pull_none>,
+ /* vo_ebc_sddo15 */
+ <3 RK_PB4 2 &pcfg_pull_none>,
+ /* vo_ebc_sdle */
+ <3 RK_PD4 2 &pcfg_pull_none>,
+ /* vo_ebc_sdoe */
+ <3 RK_PD7 2 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ vo_ebc_extern: vo_ebc-extern {
+ rockchip,pins =
+ /* vo_ebc_sdce1 */
+ <3 RK_PB2 2 &pcfg_pull_none>,
+ /* vo_ebc_sdce2 */
+ <3 RK_PB1 2 &pcfg_pull_none>,
+ /* vo_ebc_sdce3 */
+ <3 RK_PB0 2 &pcfg_pull_none>,
+ /* vo_ebc_sdshr */
+ <3 RK_PA4 2 &pcfg_pull_none>,
+ /* vo_ebc_vcom */
+ <3 RK_PA7 2 &pcfg_pull_none>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
new file mode 100644
index 000000000000..436232ffe4d1
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
@@ -0,0 +1,1678 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/clock/rockchip,rk3576-cru.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/power/rockchip,rk3576-power.h>
+#include <dt-bindings/reset/rockchip,rk3576-cru.h>
+#include <dt-bindings/soc/rockchip,boot-mode.h>
+
+/ {
+ compatible = "rockchip,rk3576";
+
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
+ i2c6 = &i2c6;
+ i2c7 = &i2c7;
+ i2c8 = &i2c8;
+ i2c9 = &i2c9;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &uart5;
+ serial6 = &uart6;
+ serial7 = &uart7;
+ serial8 = &uart8;
+ serial9 = &uart9;
+ serial10 = &uart10;
+ serial11 = &uart11;
+ spi0 = &spi0;
+ spi1 = &spi1;
+ spi2 = &spi2;
+ spi3 = &spi3;
+ spi4 = &spi4;
+ };
+
+ xin32k: clock-xin32k {
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ clock-output-names = "xin32k";
+ #clock-cells = <0>;
+ };
+
+ xin24m: clock-xin24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ };
+
+ spll: clock-spll {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <702000000>;
+ clock-output-names = "spll";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu_l0>;
+ };
+ core1 {
+ cpu = <&cpu_l1>;
+ };
+ core2 {
+ cpu = <&cpu_l2>;
+ };
+ core3 {
+ cpu = <&cpu_l3>;
+ };
+ };
+ cluster1 {
+ core0 {
+ cpu = <&cpu_b0>;
+ };
+ core1 {
+ cpu = <&cpu_b1>;
+ };
+ core2 {
+ cpu = <&cpu_b2>;
+ };
+ core3 {
+ cpu = <&cpu_b3>;
+ };
+ };
+ };
+
+ cpu_l0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <485>;
+ clocks = <&scmi_clk ARMCLK_L>;
+ operating-points-v2 = <&cluster0_opp_table>;
+ #cooling-cells = <2>;
+ dynamic-power-coefficient = <120>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ cpu_l1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x1>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <485>;
+ clocks = <&scmi_clk ARMCLK_L>;
+ operating-points-v2 = <&cluster0_opp_table>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ cpu_l2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x2>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <485>;
+ clocks = <&scmi_clk ARMCLK_L>;
+ operating-points-v2 = <&cluster0_opp_table>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ cpu_l3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x3>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <485>;
+ clocks = <&scmi_clk ARMCLK_L>;
+ operating-points-v2 = <&cluster0_opp_table>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ cpu_b0: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x100>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk ARMCLK_B>;
+ operating-points-v2 = <&cluster1_opp_table>;
+ #cooling-cells = <2>;
+ dynamic-power-coefficient = <320>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ cpu_b1: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x101>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk ARMCLK_B>;
+ operating-points-v2 = <&cluster1_opp_table>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ cpu_b2: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x102>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk ARMCLK_B>;
+ operating-points-v2 = <&cluster1_opp_table>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ cpu_b3: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x103>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ clocks = <&scmi_clk ARMCLK_B>;
+ operating-points-v2 = <&cluster1_opp_table>;
+ cpu-idle-states = <&CPU_SLEEP>;
+ };
+
+ idle-states {
+ entry-method = "psci";
+
+ CPU_SLEEP: cpu-sleep {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x0010000>;
+ entry-latency-us = <120>;
+ exit-latency-us = <250>;
+ min-residency-us = <900>;
+ local-timer-stop;
+ };
+ };
+ };
+
+ cluster0_opp_table: opp-table-cluster0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-816000000 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <725000 725000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <750000 750000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <825000 825000 950000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <900000 900000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <950000 950000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ cluster1_opp_table: opp-table-cluster1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-816000000 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <700000 700000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <712500 712500 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <737500 737500 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <800000 800000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <862500 862500 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <925000 925000 950000>;
+ clock-latency-ns = <40000>;
+ };
+
+ opp-2304000000 {
+ opp-hz = /bits/ 64 <2304000000>;
+ opp-microvolt = <950000 950000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ gpu_opp_table: opp-table-gpu {
+ compatible = "operating-points-v2";
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <700000 700000 850000>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <700000 700000 850000>;
+ };
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <700000 700000 850000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <700000 700000 850000>;
+ };
+
+ opp-700000000 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <725000 725000 850000>;
+ };
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <775000 775000 850000>;
+ };
+
+ opp-900000000 {
+ opp-hz = /bits/ 64 <900000000>;
+ opp-microvolt = <825000 825000 850000>;
+ };
+
+ opp-950000000 {
+ opp-hz = /bits/ 64 <950000000>;
+ opp-microvolt = <850000 850000 850000>;
+ };
+ };
+
+ firmware {
+ scmi: scmi {
+ compatible = "arm,scmi-smc";
+ arm,smc-id = <0x82000010>;
+ shmem = <&scmi_shmem>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ scmi_clk: protocol@14 {
+ reg = <0x14>;
+ #clock-cells = <1>;
+ };
+ };
+ };
+
+ pmu_a53: pmu-a53 {
+ compatible = "arm,cortex-a53-pmu";
+ 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>;
+ interrupt-affinity = <&cpu_l0>, <&cpu_l1>, <&cpu_l2>, <&cpu_l3>;
+ };
+
+ pmu_a72: pmu-a72 {
+ compatible = "arm,cortex-a72-pmu";
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu_b0>, <&cpu_b1>, <&cpu_b2>, <&cpu_b3>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ sys_grf: syscon@2600a000 {
+ compatible = "rockchip,rk3576-sys-grf", "syscon";
+ reg = <0x0 0x2600a000 0x0 0x2000>;
+ };
+
+ bigcore_grf: syscon@2600c000 {
+ compatible = "rockchip,rk3576-bigcore-grf", "syscon";
+ reg = <0x0 0x2600c000 0x0 0x2000>;
+ };
+
+ litcore_grf: syscon@2600e000 {
+ compatible = "rockchip,rk3576-litcore-grf", "syscon";
+ reg = <0x0 0x2600e000 0x0 0x2000>;
+ };
+
+ cci_grf: syscon@26010000 {
+ compatible = "rockchip,rk3576-cci-grf", "syscon";
+ reg = <0x0 0x26010000 0x0 0x2000>;
+ };
+
+ gpu_grf: syscon@26016000 {
+ compatible = "rockchip,rk3576-gpu-grf", "syscon";
+ reg = <0x0 0x26016000 0x0 0x2000>;
+ };
+
+ npu_grf: syscon@26018000 {
+ compatible = "rockchip,rk3576-npu-grf", "syscon";
+ reg = <0x0 0x26018000 0x0 0x2000>;
+ };
+
+ vo0_grf: syscon@2601a000 {
+ compatible = "rockchip,rk3576-vo0-grf", "syscon";
+ reg = <0x0 0x2601a000 0x0 0x2000>;
+ };
+
+ usb_grf: syscon@2601e000 {
+ compatible = "rockchip,rk3576-usb-grf", "syscon";
+ reg = <0x0 0x2601e000 0x0 0x1000>;
+ };
+
+ php_grf: syscon@26020000 {
+ compatible = "rockchip,rk3576-php-grf", "syscon";
+ reg = <0x0 0x26020000 0x0 0x2000>;
+ };
+
+ pmu0_grf: syscon@26024000 {
+ compatible = "rockchip,rk3576-pmu0-grf", "syscon", "simple-mfd";
+ reg = <0x0 0x26024000 0x0 0x1000>;
+ };
+
+ pmu1_grf: syscon@26026000 {
+ compatible = "rockchip,rk3576-pmu1-grf", "syscon";
+ reg = <0x0 0x26026000 0x0 0x1000>;
+ };
+
+ pipe_phy0_grf: syscon@26028000 {
+ compatible = "rockchip,rk3576-pipe-phy-grf", "syscon";
+ reg = <0x0 0x26028000 0x0 0x2000>;
+ };
+
+ pipe_phy1_grf: syscon@2602a000 {
+ compatible = "rockchip,rk3576-pipe-phy-grf", "syscon";
+ reg = <0x0 0x2602a000 0x0 0x2000>;
+ };
+
+ usbdpphy_grf: syscon@2602c000 {
+ compatible = "rockchip,rk3576-usbdpphy-grf", "syscon";
+ reg = <0x0 0x2602c000 0x0 0x2000>;
+ };
+
+ sdgmac_grf: syscon@26038000 {
+ compatible = "rockchip,rk3576-sdgmac-grf", "syscon";
+ reg = <0x0 0x26038000 0x0 0x1000>;
+ };
+
+ ioc_grf: syscon@26040000 {
+ compatible = "rockchip,rk3576-ioc-grf", "syscon", "simple-mfd";
+ reg = <0x0 0x26040000 0x0 0xc000>;
+ };
+
+ cru: clock-controller@27200000 {
+ compatible = "rockchip,rk3576-cru";
+ reg = <0x0 0x27200000 0x0 0x50000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+
+ assigned-clocks =
+ <&cru CLK_AUDIO_FRAC_1_SRC>,
+ <&cru PLL_GPLL>, <&cru PLL_CPLL>,
+ <&cru PLL_AUPLL>, <&cru CLK_UART_FRAC_0>,
+ <&cru CLK_UART_FRAC_1>, <&cru CLK_UART_FRAC_2>,
+ <&cru CLK_AUDIO_FRAC_0>, <&cru CLK_AUDIO_FRAC_1>,
+ <&cru CLK_CPLL_DIV2>, <&cru CLK_CPLL_DIV4>,
+ <&cru CLK_CPLL_DIV10>, <&cru FCLK_DDR_CM0_CORE>,
+ <&cru ACLK_PHP_ROOT>;
+ assigned-clock-parents = <&cru PLL_AUPLL>;
+ assigned-clock-rates =
+ <0>,
+ <1188000000>, <1000000000>,
+ <786432000>, <18432000>,
+ <96000000>, <128000000>,
+ <45158400>, <49152000>,
+ <500000000>, <250000000>,
+ <100000000>, <500000000>,
+ <250000000>;
+ };
+
+ i2c0: i2c@27300000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x27300000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C0>, <&cru PCLK_I2C0>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ uart1: serial@27310000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x27310000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 8>, <&dmac0 9>;
+ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1m0_xfer>;
+ status = "disabled";
+ };
+
+ pmu: power-management@27380000 {
+ compatible = "rockchip,rk3576-pmu", "syscon", "simple-mfd";
+ reg = <0x0 0x27380000 0x0 0x800>;
+
+ power: power-controller {
+ compatible = "rockchip,rk3576-power-controller";
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3576_PD_NPU {
+ reg = <RK3576_PD_NPU>;
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3576_PD_NPUTOP {
+ reg = <RK3576_PD_NPUTOP>;
+ clocks = <&cru ACLK_RKNN0>,
+ <&cru ACLK_RKNN1>,
+ <&cru ACLK_RKNN_CBUF>,
+ <&cru CLK_RKNN_DSU0>,
+ <&cru HCLK_RKNN_CBUF>,
+ <&cru HCLK_RKNN_ROOT>,
+ <&cru HCLK_NPU_CM0_ROOT>,
+ <&cru PCLK_NPUTOP_ROOT>;
+ pm_qos = <&qos_npu_mcu>,
+ <&qos_npu_nsp0>,
+ <&qos_npu_nsp1>,
+ <&qos_npu_m0ro>,
+ <&qos_npu_m1ro>;
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3576_PD_NPU0 {
+ reg = <RK3576_PD_NPU0>;
+ clocks = <&cru HCLK_RKNN_ROOT>,
+ <&cru ACLK_RKNN0>;
+ pm_qos = <&qos_npu_m0>;
+ #power-domain-cells = <0>;
+ };
+ power-domain@RK3576_PD_NPU1 {
+ reg = <RK3576_PD_NPU1>;
+ clocks = <&cru HCLK_RKNN_ROOT>,
+ <&cru ACLK_RKNN1>;
+ pm_qos = <&qos_npu_m1>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
+ power-domain@RK3576_PD_GPU {
+ reg = <RK3576_PD_GPU>;
+ clocks = <&cru CLK_GPU>, <&cru PCLK_GPU_ROOT>;
+ pm_qos = <&qos_gpu>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RK3576_PD_NVM {
+ reg = <RK3576_PD_NVM>;
+ clocks = <&cru ACLK_EMMC>, <&cru HCLK_EMMC>;
+ pm_qos = <&qos_emmc>,
+ <&qos_fspi0>;
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3576_PD_SDGMAC {
+ reg = <RK3576_PD_SDGMAC>;
+ clocks = <&cru ACLK_HSGPIO>,
+ <&cru ACLK_GMAC0>,
+ <&cru ACLK_GMAC1>,
+ <&cru CCLK_SRC_SDIO>,
+ <&cru CCLK_SRC_SDMMC0>,
+ <&cru HCLK_HSGPIO>,
+ <&cru HCLK_SDIO>,
+ <&cru HCLK_SDMMC0>,
+ <&cru PCLK_SDGMAC_ROOT>;
+ pm_qos = <&qos_fspi1>,
+ <&qos_gmac0>,
+ <&qos_gmac1>,
+ <&qos_sdio>,
+ <&qos_sdmmc>,
+ <&qos_flexbus>;
+ #power-domain-cells = <0>;
+ };
+ };
+
+ power-domain@RK3576_PD_PHP {
+ reg = <RK3576_PD_PHP>;
+ clocks = <&cru ACLK_PHP_ROOT>,
+ <&cru PCLK_PHP_ROOT>,
+ <&cru ACLK_MMU0>,
+ <&cru ACLK_MMU1>;
+ pm_qos = <&qos_mmu0>,
+ <&qos_mmu1>;
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3576_PD_SUBPHP {
+ reg = <RK3576_PD_SUBPHP>;
+ #power-domain-cells = <0>;
+ };
+ };
+
+ power-domain@RK3576_PD_AUDIO {
+ reg = <RK3576_PD_AUDIO>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RK3576_PD_VEPU1 {
+ reg = <RK3576_PD_VEPU1>;
+ clocks = <&cru ACLK_VEPU1>,
+ <&cru HCLK_VEPU1>;
+ pm_qos = <&qos_vepu1>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RK3576_PD_VPU {
+ reg = <RK3576_PD_VPU>;
+ clocks = <&cru ACLK_EBC>,
+ <&cru HCLK_EBC>,
+ <&cru ACLK_JPEG>,
+ <&cru HCLK_JPEG>,
+ <&cru ACLK_RGA2E_0>,
+ <&cru HCLK_RGA2E_0>,
+ <&cru ACLK_RGA2E_1>,
+ <&cru HCLK_RGA2E_1>,
+ <&cru ACLK_VDPP>,
+ <&cru HCLK_VDPP>;
+ pm_qos = <&qos_ebc>,
+ <&qos_jpeg>,
+ <&qos_rga0>,
+ <&qos_rga1>,
+ <&qos_vdpp>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RK3576_PD_VDEC {
+ reg = <RK3576_PD_VDEC>;
+ clocks = <&cru ACLK_RKVDEC_ROOT>,
+ <&cru HCLK_RKVDEC>;
+ pm_qos = <&qos_rkvdec>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RK3576_PD_VI {
+ reg = <RK3576_PD_VI>;
+ clocks = <&cru ACLK_VICAP>,
+ <&cru HCLK_VICAP>,
+ <&cru DCLK_VICAP>,
+ <&cru ACLK_VI_ROOT>,
+ <&cru HCLK_VI_ROOT>,
+ <&cru PCLK_VI_ROOT>,
+ <&cru CLK_ISP_CORE>,
+ <&cru ACLK_ISP>,
+ <&cru HCLK_ISP>,
+ <&cru CLK_CORE_VPSS>,
+ <&cru ACLK_VPSS>,
+ <&cru HCLK_VPSS>;
+ pm_qos = <&qos_isp_mro>,
+ <&qos_isp_mwo>,
+ <&qos_vicap_m0>,
+ <&qos_vpss_mro>,
+ <&qos_vpss_mwo>;
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3576_PD_VEPU0 {
+ reg = <RK3576_PD_VEPU0>;
+ clocks = <&cru ACLK_VEPU0>,
+ <&cru HCLK_VEPU0>;
+ pm_qos = <&qos_vepu0>;
+ #power-domain-cells = <0>;
+ };
+ };
+
+ power-domain@RK3576_PD_VOP {
+ reg = <RK3576_PD_VOP>;
+ clocks = <&cru ACLK_VOP>,
+ <&cru HCLK_VOP>,
+ <&cru HCLK_VOP_ROOT>,
+ <&cru PCLK_VOP_ROOT>;
+ pm_qos = <&qos_vop_m0>,
+ <&qos_vop_m1ro>;
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RK3576_PD_USB {
+ reg = <RK3576_PD_USB>;
+ clocks = <&cru PCLK_PHP_ROOT>,
+ <&cru ACLK_USB_ROOT>,
+ <&cru ACLK_MMU2>,
+ <&cru ACLK_SLV_MMU2>,
+ <&cru ACLK_UFS_SYS>;
+ pm_qos = <&qos_mmu2>,
+ <&qos_ufshc>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RK3576_PD_VO0 {
+ reg = <RK3576_PD_VO0>;
+ clocks = <&cru ACLK_HDCP0>,
+ <&cru HCLK_HDCP0>,
+ <&cru ACLK_VO0_ROOT>,
+ <&cru PCLK_VO0_ROOT>,
+ <&cru HCLK_VOP_ROOT>;
+ pm_qos = <&qos_hdcp0>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RK3576_PD_VO1 {
+ reg = <RK3576_PD_VO1>;
+ clocks = <&cru ACLK_HDCP1>,
+ <&cru HCLK_HDCP1>,
+ <&cru ACLK_VO1_ROOT>,
+ <&cru PCLK_VO1_ROOT>,
+ <&cru HCLK_VOP_ROOT>;
+ pm_qos = <&qos_hdcp1>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+ };
+
+ gpu: gpu@27800000 {
+ compatible = "rockchip,rk3576-mali", "arm,mali-bifrost";
+ reg = <0x0 0x27800000 0x0 0x200000>;
+ assigned-clocks = <&scmi_clk CLK_GPU>;
+ assigned-clock-rates = <198000000>;
+ clocks = <&cru CLK_GPU>;
+ clock-names = "core";
+ dynamic-power-coefficient = <1625>;
+ interrupts = <GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "job", "mmu", "gpu";
+ operating-points-v2 = <&gpu_opp_table>;
+ power-domains = <&power RK3576_PD_GPU>;
+ #cooling-cells = <2>;
+ status = "disabled";
+ };
+
+ qos_hdcp1: qos@27f02000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f02000 0x0 0x20>;
+ };
+
+ qos_fspi1: qos@27f04000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f04000 0x0 0x20>;
+ };
+
+ qos_gmac0: qos@27f04080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f04080 0x0 0x20>;
+ };
+
+ qos_gmac1: qos@27f04100 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f04100 0x0 0x20>;
+ };
+
+ qos_sdio: qos@27f04180 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f04180 0x0 0x20>;
+ };
+
+ qos_sdmmc: qos@27f04200 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f04200 0x0 0x20>;
+ };
+
+ qos_flexbus: qos@27f04280 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f04280 0x0 0x20>;
+ };
+
+ qos_gpu: qos@27f05000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f05000 0x0 0x20>;
+ };
+
+ qos_vepu1: qos@27f06000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f06000 0x0 0x20>;
+ };
+
+ qos_npu_mcu: qos@27f08000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f08000 0x0 0x20>;
+ };
+
+ qos_npu_nsp0: qos@27f08080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f08080 0x0 0x20>;
+ };
+
+ qos_npu_nsp1: qos@27f08100 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f08100 0x0 0x20>;
+ };
+
+ qos_emmc: qos@27f09000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f09000 0x0 0x20>;
+ };
+
+ qos_fspi0: qos@27f09080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f09080 0x0 0x20>;
+ };
+
+ qos_mmu0: qos@27f0a000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f0a000 0x0 0x20>;
+ };
+
+ qos_mmu1: qos@27f0a080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f0a080 0x0 0x20>;
+ };
+
+ qos_rkvdec: qos@27f0c000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f0c000 0x0 0x20>;
+ };
+
+ qos_crypto: qos@27f0d000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f0d000 0x0 0x20>;
+ };
+
+ qos_mmu2: qos@27f0e000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f0e000 0x0 0x20>;
+ };
+
+ qos_ufshc: qos@27f0e080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f0e080 0x0 0x20>;
+ };
+
+ qos_vepu0: qos@27f0f000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f0f000 0x0 0x20>;
+ };
+
+ qos_isp_mro: qos@27f10000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f10000 0x0 0x20>;
+ };
+
+ qos_isp_mwo: qos@27f10080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f10080 0x0 0x20>;
+ };
+
+ qos_vicap_m0: qos@27f10100 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f10100 0x0 0x20>;
+ };
+
+ qos_vpss_mro: qos@27f10180 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f10180 0x0 0x20>;
+ };
+
+ qos_vpss_mwo: qos@27f10200 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f10200 0x0 0x20>;
+ };
+
+ qos_hdcp0: qos@27f11000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f11000 0x0 0x20>;
+ };
+
+ qos_vop_m0: qos@27f12800 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f12800 0x0 0x20>;
+ };
+
+ qos_vop_m1ro: qos@27f12880 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f12880 0x0 0x20>;
+ };
+
+ qos_ebc: qos@27f13000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f13000 0x0 0x20>;
+ };
+
+ qos_rga0: qos@27f13080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f13080 0x0 0x20>;
+ };
+
+ qos_rga1: qos@27f13100 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f13100 0x0 0x20>;
+ };
+
+ qos_jpeg: qos@27f13180 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f13180 0x0 0x20>;
+ };
+
+ qos_vdpp: qos@27f13200 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f13200 0x0 0x20>;
+ };
+
+ qos_npu_m0: qos@27f20000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f20000 0x0 0x20>;
+ };
+
+ qos_npu_m1: qos@27f21000 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f21000 0x0 0x20>;
+ };
+
+ qos_npu_m0ro: qos@27f22080 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f22080 0x0 0x20>;
+ };
+
+ qos_npu_m1ro: qos@27f22100 {
+ compatible = "rockchip,rk3576-qos", "syscon";
+ reg = <0x0 0x27f22100 0x0 0x20>;
+ };
+
+ gmac0: ethernet@2a220000 {
+ compatible = "rockchip,rk3576-gmac", "snps,dwmac-4.20a";
+ reg = <0x0 0x2a220000 0x0 0x10000>;
+ clocks = <&cru CLK_GMAC0_125M_SRC>, <&cru CLK_GMAC0_RMII_CRU>,
+ <&cru PCLK_GMAC0>, <&cru ACLK_GMAC0>,
+ <&cru CLK_GMAC0_PTP_REF>;
+ clock-names = "stmmaceth", "clk_mac_ref",
+ "pclk_mac", "aclk_mac",
+ "ptp_ref";
+ interrupts = <GIC_SPI 293 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ power-domains = <&power RK3576_PD_SDGMAC>;
+ resets = <&cru SRST_A_GMAC0>;
+ reset-names = "stmmaceth";
+ rockchip,grf = <&sdgmac_grf>;
+ rockchip,php-grf = <&ioc_grf>;
+ snps,axi-config = <&gmac0_stmmac_axi_setup>;
+ snps,mixed-burst;
+ snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;
+ snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;
+ snps,tso;
+ status = "disabled";
+
+ mdio0: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ };
+
+ gmac0_stmmac_axi_setup: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <8>;
+ snps,wr_osr_lmt = <4>;
+ };
+
+ gmac0_mtl_rx_setup: rx-queues-config {
+ snps,rx-queues-to-use = <1>;
+ queue0 {};
+ };
+
+ gmac0_mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <1>;
+ queue0 {};
+ };
+ };
+
+ gmac1: ethernet@2a230000 {
+ compatible = "rockchip,rk3576-gmac", "snps,dwmac-4.20a";
+ reg = <0x0 0x2a230000 0x0 0x10000>;
+ clocks = <&cru CLK_GMAC1_125M_SRC>, <&cru CLK_GMAC1_RMII_CRU>,
+ <&cru PCLK_GMAC1>, <&cru ACLK_GMAC1>,
+ <&cru CLK_GMAC1_PTP_REF>;
+ clock-names = "stmmaceth", "clk_mac_ref",
+ "pclk_mac", "aclk_mac",
+ "ptp_ref";
+ interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ power-domains = <&power RK3576_PD_SDGMAC>;
+ resets = <&cru SRST_A_GMAC1>;
+ reset-names = "stmmaceth";
+ rockchip,grf = <&sdgmac_grf>;
+ rockchip,php-grf = <&ioc_grf>;
+ snps,axi-config = <&gmac1_stmmac_axi_setup>;
+ snps,mixed-burst;
+ snps,mtl-rx-config = <&gmac1_mtl_rx_setup>;
+ snps,mtl-tx-config = <&gmac1_mtl_tx_setup>;
+ snps,tso;
+ status = "disabled";
+
+ mdio1: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ };
+
+ gmac1_stmmac_axi_setup: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <8>;
+ snps,wr_osr_lmt = <4>;
+ };
+
+ gmac1_mtl_rx_setup: rx-queues-config {
+ snps,rx-queues-to-use = <1>;
+ queue0 {};
+ };
+
+ gmac1_mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <1>;
+ queue0 {};
+ };
+ };
+
+ sdmmc: mmc@2a310000 {
+ compatible = "rockchip,rk3576-dw-mshc";
+ reg = <0x0 0x2a310000 0x0 0x4000>;
+ clocks = <&cru HCLK_SDMMC0>, <&cru CCLK_SRC_SDMMC0>;
+ clock-names = "biu", "ciu";
+ fifo-depth = <0x100>;
+ interrupts = <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>;
+ max-frequency = <200000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4 &sdmmc0_pwren>;
+ power-domains = <&power RK3576_PD_SDGMAC>;
+ resets = <&cru SRST_H_SDMMC0>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
+ sdhci: mmc@2a330000 {
+ compatible = "rockchip,rk3576-dwcmshc", "rockchip,rk3588-dwcmshc";
+ reg = <0x0 0x2a330000 0x0 0x10000>;
+ assigned-clocks = <&cru BCLK_EMMC>, <&cru TCLK_EMMC>, <&cru CCLK_SRC_EMMC>;
+ assigned-clock-rates = <200000000>, <24000000>, <200000000>;
+ clocks = <&cru CCLK_SRC_EMMC>, <&cru HCLK_EMMC>,
+ <&cru ACLK_EMMC>, <&cru BCLK_EMMC>,
+ <&cru TCLK_EMMC>;
+ clock-names = "core", "bus", "axi", "block", "timer";
+ interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>;
+ max-frequency = <200000000>;
+ pinctrl-0 = <&emmc_rstnout>, <&emmc_bus8>, <&emmc_clk>,
+ <&emmc_cmd>, <&emmc_strb>;
+ pinctrl-names = "default";
+ power-domains = <&power RK3576_PD_NVM>;
+ resets = <&cru SRST_C_EMMC>, <&cru SRST_H_EMMC>,
+ <&cru SRST_A_EMMC>, <&cru SRST_B_EMMC>,
+ <&cru SRST_T_EMMC>;
+ reset-names = "core", "bus", "axi", "block", "timer";
+ supports-cqe;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@2a701000 {
+ compatible = "arm,gic-400";
+ reg = <0x0 0x2a701000 0 0x10000>,
+ <0x0 0x2a702000 0 0x10000>,
+ <0x0 0x2a704000 0 0x10000>,
+ <0x0 0x2a706000 0 0x10000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ };
+
+ dmac0: dma-controller@2ab90000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0x2ab90000 0x0 0x4000>;
+ arm,pl330-periph-burst;
+ clocks = <&cru ACLK_DMAC0>;
+ clock-names = "apb_pclk";
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ };
+
+ dmac1: dma-controller@2abb0000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0x2abb0000 0x0 0x4000>;
+ arm,pl330-periph-burst;
+ clocks = <&cru ACLK_DMAC1>;
+ clock-names = "apb_pclk";
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ };
+
+ dmac2: dma-controller@2abd0000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0x2abd0000 0x0 0x4000>;
+ arm,pl330-periph-burst;
+ clocks = <&cru ACLK_DMAC2>;
+ clock-names = "apb_pclk";
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ };
+
+ i2c1: i2c@2ac40000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2ac40000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@2ac50000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2ac50000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C2>, <&cru PCLK_I2C2>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@2ac60000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2ac60000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@2ac70000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2ac70000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@2ac80000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2ac80000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C5>, <&cru PCLK_I2C5>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c5m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+
+ i2c6: i2c@2ac90000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2ac90000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C6>, <&cru PCLK_I2C6>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c7: i2c@2aca0000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2aca0000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C7>, <&cru PCLK_I2C7>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c7m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c8: i2c@2acb0000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2acb0000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C8>, <&cru PCLK_I2C8>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8m0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ timer0: timer@2acc0000 {
+ compatible = "rockchip,rk3576-timer", "rockchip,rk3288-timer";
+ reg = <0x0 0x2acc0000 0x0 0x20>;
+ clocks = <&cru PCLK_BUSTIMER0>, <&cru CLK_TIMER0>;
+ clock-names = "pclk", "timer";
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wdt: watchdog@2ace0000 {
+ compatible = "rockchip,rk3576-wdt", "snps,dw-wdt";
+ reg = <0x0 0x2ace0000 0x0 0x100>;
+ clocks = <&cru TCLK_WDT0>, <&cru PCLK_WDT0>;
+ clock-names = "tclk", "pclk";
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ spi0: spi@2acf0000 {
+ compatible = "rockchip,rk3576-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0x2acf0000 0x0 0x1000>;
+ clocks = <&cru CLK_SPI0>, <&cru PCLK_SPI0>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac0 14>, <&dmac0 15>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0m0_csn0 &spi0m0_csn1 &spi0m0_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi1: spi@2ad00000 {
+ compatible = "rockchip,rk3576-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0x2ad00000 0x0 0x1000>;
+ clocks = <&cru CLK_SPI1>, <&cru PCLK_SPI1>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac0 16>, <&dmac0 17>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1m0_csn0 &spi1m0_csn1 &spi1m0_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi2: spi@2ad10000 {
+ compatible = "rockchip,rk3576-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0x2ad10000 0x0 0x1000>;
+ clocks = <&cru CLK_SPI2>, <&cru PCLK_SPI2>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac1 15>, <&dmac1 16>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m0_csn0 &spi2m0_csn1 &spi2m0_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi3: spi@2ad20000 {
+ compatible = "rockchip,rk3576-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0x2ad20000 0x0 0x1000>;
+ clocks = <&cru CLK_SPI3>, <&cru PCLK_SPI3>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac1 17>, <&dmac1 18>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi3m0_csn0 &spi3m0_csn1 &spi3m0_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi4: spi@2ad30000 {
+ compatible = "rockchip,rk3576-spi", "rockchip,rk3066-spi";
+ reg = <0x0 0x2ad30000 0x0 0x1000>;
+ clocks = <&cru CLK_SPI4>, <&cru PCLK_SPI4>;
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac2 12>, <&dmac2 13>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi4m0_csn0 &spi4m0_csn1 &spi4m0_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ uart0: serial@2ad40000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2ad40000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 6>, <&dmac0 7>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart0m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart2: serial@2ad50000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2ad50000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 10>, <&dmac0 11>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "disabled";
+ };
+
+ uart3: serial@2ad60000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2ad60000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac0 12>, <&dmac0 13>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart3m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart4: serial@2ad70000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2ad70000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac1 9>, <&dmac1 10>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart4m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart5: serial@2ad80000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2ad80000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac1 11>, <&dmac1 12>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart5m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart6: serial@2ad90000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2ad90000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac1 13>, <&dmac1 14>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart6m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart7: serial@2ada0000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2ada0000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 6>, <&dmac2 7>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart7m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart8: serial@2adb0000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2adb0000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART8>, <&cru PCLK_UART8>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 8>, <&dmac2 9>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart8m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart9: serial@2adc0000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2adc0000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART9>, <&cru PCLK_UART9>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 10>, <&dmac2 11>;
+ dma-names = "tx", "rx";
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&uart9m0_xfer>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ saradc: adc@2ae00000 {
+ compatible = "rockchip,rk3576-saradc", "rockchip,rk3588-saradc";
+ reg = <0x0 0x2ae00000 0x0 0x10000>;
+ clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
+ clock-names = "saradc", "apb_pclk";
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&cru SRST_P_SARADC>;
+ reset-names = "saradc-apb";
+ #io-channel-cells = <1>;
+ status = "disabled";
+ };
+
+ i2c9: i2c@2ae80000 {
+ compatible = "rockchip,rk3576-i2c", "rockchip,rk3399-i2c";
+ reg = <0x0 0x2ae80000 0x0 0x1000>;
+ clocks = <&cru CLK_I2C9>, <&cru PCLK_I2C9>;
+ clock-names = "i2c", "pclk";
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c9m0_xfer>;
+ resets = <&cru SRST_I2C9>, <&cru SRST_P_I2C9>;
+ reset-names = "i2c", "apb";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ uart10: serial@2afc0000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2afc0000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART10>, <&cru PCLK_UART10>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 21>, <&dmac2 22>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart10m0_xfer>;
+ status = "disabled";
+ };
+
+ uart11: serial@2afd0000 {
+ compatible = "rockchip,rk3576-uart", "snps,dw-apb-uart";
+ reg = <0x0 0x2afd0000 0x0 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART11>, <&cru PCLK_UART11>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac2 23>, <&dmac2 24>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart11m0_xfer>;
+ status = "disabled";
+ };
+
+ sram: sram@3ff88000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0x3ff88000 0x0 0x78000>;
+ ranges = <0x0 0x0 0x3ff88000 0x78000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* start address and size should be 4k align */
+ rkvdec_sram: rkvdec-sram@0 {
+ reg = <0x0 0x78000>;
+ };
+ };
+
+ scmi_shmem: scmi-shmem@4010f000 {
+ compatible = "arm,scmi-shmem";
+ reg = <0x0 0x4010f000 0x0 0x100>;
+ };
+
+ pinctrl: pinctrl {
+ compatible = "rockchip,rk3576-pinctrl";
+ rockchip,grf = <&ioc_grf>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gpio0: gpio@27320000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0x27320000 0x0 0x200>;
+ clocks = <&cru PCLK_GPIO0>, <&cru DBCLK_GPIO0>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 0 32>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio1: gpio@2ae10000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0x2ae10000 0x0 0x200>;
+ clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 32 32>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@2ae20000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0x2ae20000 0x0 0x200>;
+ clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 64 32>;
+ interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@2ae30000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0x2ae30000 0x0 0x200>;
+ clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 96 32>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio@2ae40000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x0 0x2ae40000 0x0 0x200>;
+ clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl 0 128 32>;
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+ };
+ };
+};
+
+#include "rk3576-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-lm7.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-armsom-lm7.dtsi
new file mode 100644
index 000000000000..a3138d2d384c
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-lm7.dtsi
@@ -0,0 +1,455 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "rk3588.dtsi"
+
+/ {
+ compatible = "armsom,lm7", "rockchip,rk3588";
+
+ aliases {
+ mmc0 = &sdhci;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ 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>;
+ };
+
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m2_xfer>;
+ status = "okay";
+
+ vdd_cpu_big0_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_s0: regulator@43 {
+ compatible = "rockchip,rk8603", "rockchip,rk8602";
+ reg = <0x43>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&saradc {
+ vref-supply = <&avcc_1v8_s0>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ no-sdio;
+ no-sd;
+ non-removable;
+ status = "okay";
+};
+
+&spi2 {
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+ status = "okay";
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ reg = <0x0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ spi-max-frequency = <1000000>;
+ system-power-controller;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 {
+ regulator-name = "vdd_gpu_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 {
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-name = "vdd_log_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 {
+ regulator-name = "vdd_vdenc_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg5 {
+ regulator-name = "vdd_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg6 {
+ regulator-name = "vdd2_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-name = "vdd_2v0_pldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg8 {
+ regulator-name = "vcc_3v3_s3";
+ 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>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-name = "vddq_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg10 {
+ regulator-name = "vcc_1v8_s3";
+ 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>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-name = "avcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s0: pldo-reg2 {
+ regulator-name = "vcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avdd_1v2_s0: pldo-reg3 {
+ regulator-name = "avdd_1v2_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-name = "vcc_3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-name = "vccio_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-name = "pldo6_s3";
+ 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>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-name = "vdd_0v75_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-name = "vdd_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg3 {
+ regulator-name = "avdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg4 {
+ regulator-name = "vdd_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v75_s0: nldo-reg5 {
+ regulator-name = "vdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
index c667704ba985..08f09053a066 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
@@ -23,7 +23,7 @@
compatible = "audio-graph-card";
dais = <&i2s0_8ch_p0>;
label = "rk3588-es8316";
- hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
+ hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&hp_detect>;
routing = "MIC2", "Mic Jack",
@@ -61,7 +61,7 @@
#cooling-cells = <2>;
};
- vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2-regulator {
+ vcc3v3_pcie2x1l2: regulator-vcc3v3-pcie2x1l2 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie2x1l2";
regulator-min-microvolt = <3300000>;
@@ -70,7 +70,7 @@
vin-supply = <&vcc_3v3_s3>;
};
- vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
@@ -81,7 +81,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -95,7 +95,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -104,7 +104,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts
new file mode 100644
index 000000000000..779cd1b1798c
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-w3.dts
@@ -0,0 +1,408 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "rk3588-armsom-lm7.dtsi"
+
+/ {
+ model = "ArmSoM W3";
+ compatible = "armsom,w3", "armsom,lm7", "rockchip,rk3588";
+
+ aliases {
+ mmc1 = &sdmmc;
+ mmc2 = &sdio;
+ };
+
+ analog-sound {
+ compatible = "audio-graph-card";
+ label = "rk3588-es8316";
+
+ widgets = "Microphone", "Mic Jack",
+ "Headphone", "Headphones";
+
+ routing = "MIC2", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR";
+
+ dais = <&i2s0_8ch_p0>;
+ hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_detect>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_rgb_b>;
+
+ led-rgb-b {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-rgb-r {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ };
+ };
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ cooling-levels = <0 120 150 180 210 240 255>;
+ fan-supply = <&vcc5v0_sys>;
+ pwms = <&pwm1 0 50000 0>;
+ #cooling-cells = <2>;
+ };
+
+ rfkill {
+ compatible = "rfkill-gpio";
+ label = "rfkill-pcie-wlan";
+ radio-type = "wlan";
+ shutdown-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ };
+
+ rfkill-bt {
+ compatible = "rfkill-gpio";
+ label = "rfkill-m2-bt";
+ radio-type = "bluetooth";
+ shutdown-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
+ };
+
+ vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_0_vcc3v3_en>;
+ regulator-name = "vcc3v3_pcie2x1l0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <50000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc3v3_pcie2x1l2: regulator-vcc3v3-pcie2x1l2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie2x1l2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3_vcc3v3_en>;
+ regulator-name = "vcc3v3_pcie30";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_host: regulator-vcc5v0-host {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_host";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_host_en>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy1_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
+
+&i2c7 {
+ status = "okay";
+
+ es8316: audio-codec@11 {
+ compatible = "everest,es8316";
+ reg = <0x11>;
+ clocks = <&cru I2S0_8CH_MCLKOUT>;
+ clock-names = "mclk";
+ assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
+ assigned-clock-rates = <12288000>;
+ #sound-dai-cells = <0>;
+
+ port {
+ es8316_p0_0: endpoint {
+ remote-endpoint = <&i2s0_8ch_p0_0>;
+ };
+ };
+ };
+};
+
+&i2s0_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_lrck
+ &i2s0_mclk
+ &i2s0_sclk
+ &i2s0_sdi0
+ &i2s0_sdo0>;
+ status = "okay";
+
+ i2s0_8ch_p0: port {
+ i2s0_8ch_p0_0: endpoint {
+ dai-format = "i2s";
+ mclk-fs = <256>;
+ remote-endpoint = <&es8316_p0_0>;
+ };
+ };
+};
+
+&package_thermal {
+ polling-delay = <1000>;
+
+ trips {
+ package_fan0: package-fan0 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+
+ package_fan1: package-fan1 {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&package_fan0>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+ };
+
+ map1 {
+ trip = <&package_fan1>;
+ cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+ };
+ };
+};
+
+&pcie2x1l0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_0_rst>;
+ reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie2x1l0>;
+ status = "okay";
+};
+
+&pcie2x1l2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_2_rst>;
+ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie2x1l2>;
+ status = "okay";
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3_rst>;
+ reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie30>;
+ status = "okay";
+};
+
+&pinctrl {
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ led_rgb_b: led-rgb-b {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sound {
+ hp_detect: hp-detect {
+ rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie2 {
+ pcie2_0_rst: pcie2-0-rst {
+ rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie2_0_vcc3v3_en: pcie2-0-vcc-en {
+ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie2_2_rst: pcie2-2-rst {
+ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie3 {
+ pcie3_rst: pcie3-rst {
+ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie3_vcc3v3_en: pcie3-vcc3v3-en {
+ rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ vcc5v0_host_en: vcc5v0-host-en {
+ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ max-frequency = <200000000>;
+ no-sdio;
+ no-mmc;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_s3>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&sdio {
+ bus-width = <4>;
+ cap-sdio-irq;
+ disable-wp;
+ keep-power-in-suspend;
+ max-frequency = <200000000>;
+ no-sd;
+ no-mmc;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdiom0_pins>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_pcie2x1l0>;
+ vqmmc-supply = <&vcc_1v8_s3>;
+ wakeup-source;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&uart6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>;
+ status = "okay";
+};
+
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ /* connected to USB hub, which is powered by vcc5v0_sys */
+ phy-supply = <&vcc5v0_sys>;
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc5v0_host>;
+ status = "okay";
+};
+
+&usbdp_phy1 {
+ 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 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb_host2_xhci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi
index d1368418502a..7f874c77410c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi
@@ -1612,23 +1612,43 @@
pcie20x1 {
/omit-if-no-ref/
- pcie20x1m0_pins: pcie20x1m0-pins {
+ pcie20x1m0_clkreqn: pcie20x1m0-clkreqn {
rockchip,pins =
/* pcie20x1_2_clkreqn_m0 */
- <3 RK_PC7 4 &pcfg_pull_none>,
+ <3 RK_PC7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie20x1m0_perstn: pcie20x1m0-perstn {
+ rockchip,pins =
/* pcie20x1_2_perstn_m0 */
- <3 RK_PD1 4 &pcfg_pull_none>,
+ <3 RK_PD1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie20x1m0_waken: pcie20x1m0-waken {
+ rockchip,pins =
/* pcie20x1_2_waken_m0 */
<3 RK_PD0 4 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie20x1m1_pins: pcie20x1m1-pins {
+ pcie20x1m1_clkreqn: pcie20x1m1-clkreqn {
rockchip,pins =
/* pcie20x1_2_clkreqn_m1 */
- <4 RK_PB7 4 &pcfg_pull_none>,
+ <4 RK_PB7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie20x1m1_perstn: pcie20x1m1-perstn {
+ rockchip,pins =
/* pcie20x1_2_perstn_m1 */
- <4 RK_PC1 4 &pcfg_pull_none>,
+ <4 RK_PC1 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie20x1m1_waken: pcie20x1m1-waken {
+ rockchip,pins =
/* pcie20x1_2_waken_m1 */
<4 RK_PC0 4 &pcfg_pull_none>;
};
@@ -1654,52 +1674,127 @@
pcie30x1 {
/omit-if-no-ref/
- pcie30x1m0_pins: pcie30x1m0-pins {
+ pcie30x1m0_0_clkreqn: pcie30x1m0-0-clkreqn {
rockchip,pins =
/* pcie30x1_0_clkreqn_m0 */
- <0 RK_PC0 12 &pcfg_pull_none>,
+ <0 RK_PC0 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m0_0_perstn: pcie30x1m0-0-perstn {
+ rockchip,pins =
/* pcie30x1_0_perstn_m0 */
- <0 RK_PC5 12 &pcfg_pull_none>,
+ <0 RK_PC5 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m0_0_waken: pcie30x1m0-0-waken {
+ rockchip,pins =
/* pcie30x1_0_waken_m0 */
- <0 RK_PC4 12 &pcfg_pull_none>,
+ <0 RK_PC4 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m0_1_clkreqn: pcie30x1m0-1-clkreqn {
+ rockchip,pins =
/* pcie30x1_1_clkreqn_m0 */
- <0 RK_PB5 12 &pcfg_pull_none>,
+ <0 RK_PB5 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m0_1_perstn: pcie30x1m0-1-perstn {
+ rockchip,pins =
/* pcie30x1_1_perstn_m0 */
- <0 RK_PB7 12 &pcfg_pull_none>,
+ <0 RK_PB7 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m0_1_waken: pcie30x1m0-1-waken {
+ rockchip,pins =
/* pcie30x1_1_waken_m0 */
<0 RK_PB6 12 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x1m1_pins: pcie30x1m1-pins {
+ pcie30x1m1_0_clkreqn: pcie30x1m1-0-clkreqn {
rockchip,pins =
/* pcie30x1_0_clkreqn_m1 */
- <4 RK_PA3 4 &pcfg_pull_none>,
+ <4 RK_PA3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m1_0_perstn: pcie30x1m1-0-perstn {
+ rockchip,pins =
/* pcie30x1_0_perstn_m1 */
- <4 RK_PA5 4 &pcfg_pull_none>,
+ <4 RK_PA5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m1_0_waken: pcie30x1m1-0-waken {
+ rockchip,pins =
/* pcie30x1_0_waken_m1 */
- <4 RK_PA4 4 &pcfg_pull_none>,
+ <4 RK_PA4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m1_1_clkreqn: pcie30x1m1-1-clkreqn {
+ rockchip,pins =
/* pcie30x1_1_clkreqn_m1 */
- <4 RK_PA0 4 &pcfg_pull_none>,
+ <4 RK_PA0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m1_1_perstn: pcie30x1m1-1-perstn {
+ rockchip,pins =
/* pcie30x1_1_perstn_m1 */
- <4 RK_PA2 4 &pcfg_pull_none>,
+ <4 RK_PA2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m1_1_waken: pcie30x1m1-1-waken {
+ rockchip,pins =
/* pcie30x1_1_waken_m1 */
<4 RK_PA1 4 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x1m2_pins: pcie30x1m2-pins {
+ pcie30x1m2_0_clkreqn: pcie30x1m2-0-clkreqn {
rockchip,pins =
/* pcie30x1_0_clkreqn_m2 */
- <1 RK_PB5 4 &pcfg_pull_none>,
+ <1 RK_PB5 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m2_0_perstn: pcie30x1m2-0-perstn {
+ rockchip,pins =
/* pcie30x1_0_perstn_m2 */
- <1 RK_PB4 4 &pcfg_pull_none>,
+ <1 RK_PB4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m2_0_waken: pcie30x1m2-0-waken {
+ rockchip,pins =
/* pcie30x1_0_waken_m2 */
- <1 RK_PB3 4 &pcfg_pull_none>,
+ <1 RK_PB3 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m2_1_clkreqn: pcie30x1m2-1-clkreqn {
+ rockchip,pins =
/* pcie30x1_1_clkreqn_m2 */
- <1 RK_PA0 4 &pcfg_pull_none>,
+ <1 RK_PA0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m2_1_perstn: pcie30x1m2-1-perstn {
+ rockchip,pins =
/* pcie30x1_1_perstn_m2 */
- <1 RK_PA7 4 &pcfg_pull_none>,
+ <1 RK_PA7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x1m2_1_waken: pcie30x1m2-1-waken {
+ rockchip,pins =
/* pcie30x1_1_waken_m2 */
<1 RK_PA1 4 &pcfg_pull_none>;
};
@@ -1721,45 +1816,85 @@
pcie30x2 {
/omit-if-no-ref/
- pcie30x2m0_pins: pcie30x2m0-pins {
+ pcie30x2m0_clkreqn: pcie30x2m0-clkreqn {
rockchip,pins =
/* pcie30x2_clkreqn_m0 */
- <0 RK_PD1 12 &pcfg_pull_none>,
+ <0 RK_PD1 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m0_perstn: pcie30x2m0-perstn {
+ rockchip,pins =
/* pcie30x2_perstn_m0 */
- <0 RK_PD4 12 &pcfg_pull_none>,
+ <0 RK_PD4 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m0_waken: pcie30x2m0-waken {
+ rockchip,pins =
/* pcie30x2_waken_m0 */
<0 RK_PD2 12 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x2m1_pins: pcie30x2m1-pins {
+ pcie30x2m1_clkreqn: pcie30x2m1-clkreqn {
rockchip,pins =
/* pcie30x2_clkreqn_m1 */
- <4 RK_PA6 4 &pcfg_pull_none>,
+ <4 RK_PA6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m1_perstn: pcie30x2m1-perstn {
+ rockchip,pins =
/* pcie30x2_perstn_m1 */
- <4 RK_PB0 4 &pcfg_pull_none>,
+ <4 RK_PB0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m1_waken: pcie30x2m1-waken {
+ rockchip,pins =
/* pcie30x2_waken_m1 */
<4 RK_PA7 4 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x2m2_pins: pcie30x2m2-pins {
+ pcie30x2m2_clkreqn: pcie30x2m2-clkreqn {
rockchip,pins =
/* pcie30x2_clkreqn_m2 */
- <3 RK_PD2 4 &pcfg_pull_none>,
+ <3 RK_PD2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m2_perstn: pcie30x2m2-perstn {
+ rockchip,pins =
/* pcie30x2_perstn_m2 */
- <3 RK_PD4 4 &pcfg_pull_none>,
+ <3 RK_PD4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m2_waken: pcie30x2m2-waken {
+ rockchip,pins =
/* pcie30x2_waken_m2 */
<3 RK_PD3 4 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x2m3_pins: pcie30x2m3-pins {
+ pcie30x2m3_clkreqn: pcie30x2m3-clkreqn {
rockchip,pins =
/* pcie30x2_clkreqn_m3 */
- <1 RK_PD7 4 &pcfg_pull_none>,
+ <1 RK_PD7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m3_perstn: pcie30x2m3-perstn {
+ rockchip,pins =
/* pcie30x2_perstn_m3 */
- <1 RK_PB7 4 &pcfg_pull_none>,
+ <1 RK_PB7 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x2m3_waken: pcie30x2m3-waken {
+ rockchip,pins =
/* pcie30x2_waken_m3 */
<1 RK_PB6 4 &pcfg_pull_none>;
};
@@ -1774,45 +1909,85 @@
pcie30x4 {
/omit-if-no-ref/
- pcie30x4m0_pins: pcie30x4m0-pins {
+ pcie30x4m0_clkreqn: pcie30x4m0-clkreqn {
rockchip,pins =
/* pcie30x4_clkreqn_m0 */
- <0 RK_PC6 12 &pcfg_pull_none>,
+ <0 RK_PC6 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m0_perstn: pcie30x4m0-perstn {
+ rockchip,pins =
/* pcie30x4_perstn_m0 */
- <0 RK_PD0 12 &pcfg_pull_none>,
+ <0 RK_PD0 12 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m0_waken: pcie30x4m0-waken {
+ rockchip,pins =
/* pcie30x4_waken_m0 */
<0 RK_PC7 12 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x4m1_pins: pcie30x4m1-pins {
+ pcie30x4m1_clkreqn: pcie30x4m1-clkreqn {
rockchip,pins =
/* pcie30x4_clkreqn_m1 */
- <4 RK_PB4 4 &pcfg_pull_none>,
+ <4 RK_PB4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m1_perstn: pcie30x4m1-perstn {
+ rockchip,pins =
/* pcie30x4_perstn_m1 */
- <4 RK_PB6 4 &pcfg_pull_none>,
+ <4 RK_PB6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m1_waken: pcie30x4m1-waken {
+ rockchip,pins =
/* pcie30x4_waken_m1 */
<4 RK_PB5 4 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x4m2_pins: pcie30x4m2-pins {
+ pcie30x4m2_clkreqn: pcie30x4m2-clkreqn {
rockchip,pins =
/* pcie30x4_clkreqn_m2 */
- <3 RK_PC4 4 &pcfg_pull_none>,
+ <3 RK_PC4 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m2_perstn: pcie30x4m2-perstn {
+ rockchip,pins =
/* pcie30x4_perstn_m2 */
- <3 RK_PC6 4 &pcfg_pull_none>,
+ <3 RK_PC6 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m2_waken: pcie30x4m2-waken {
+ rockchip,pins =
/* pcie30x4_waken_m2 */
<3 RK_PC5 4 &pcfg_pull_none>;
};
/omit-if-no-ref/
- pcie30x4m3_pins: pcie30x4m3-pins {
+ pcie30x4m3_clkreqn: pcie30x4m3-clkreqn {
rockchip,pins =
/* pcie30x4_clkreqn_m3 */
- <1 RK_PB0 4 &pcfg_pull_none>,
+ <1 RK_PB0 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m3_perstn: pcie30x4m3-perstn {
+ rockchip,pins =
/* pcie30x4_perstn_m3 */
- <1 RK_PB2 4 &pcfg_pull_none>,
+ <1 RK_PB2 4 &pcfg_pull_none>;
+ };
+
+ /omit-if-no-ref/
+ pcie30x4m3_waken: pcie30x4m3-waken {
+ rockchip,pins =
/* pcie30x4_waken_m3 */
<1 RK_PB1 4 &pcfg_pull_none>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index d97d84b88837..a337f3fb8377 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -337,15 +337,19 @@
cache-unified;
next-level-cache = <&l3_cache>;
};
+ };
- l3_cache: l3-cache {
- compatible = "cache";
- cache-size = <3145728>;
- cache-line-size = <64>;
- cache-sets = <4096>;
- cache-level = <3>;
- cache-unified;
- };
+ /*
+ * The L3 cache belongs to the DynamIQ Shared Unit (DSU),
+ * so it's represented here, outside the "cpus" node
+ */
+ l3_cache: l3-cache {
+ compatible = "cache";
+ cache-size = <3145728>;
+ cache-line-size = <64>;
+ cache-sets = <4096>;
+ cache-level = <3>;
+ cache-unified;
};
display_subsystem: display-subsystem {
@@ -1366,6 +1370,47 @@
status = "disabled";
};
+ hdmi0: hdmi@fde80000 {
+ compatible = "rockchip,rk3588-dw-hdmi-qp";
+ reg = <0x0 0xfde80000 0x0 0x20000>;
+ clocks = <&cru PCLK_HDMITX0>,
+ <&cru CLK_HDMITX0_EARC>,
+ <&cru CLK_HDMITX0_REF>,
+ <&cru MCLK_I2S5_8CH_TX>,
+ <&cru CLK_HDMIHDP0>,
+ <&cru HCLK_VO1>;
+ clock-names = "pclk", "earc", "ref", "aud", "hdp", "hclk_vo1";
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "avp", "cec", "earc", "main", "hpd";
+ phys = <&hdptxphy_hdmi0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmim0_tx0_cec &hdmim0_tx0_hpd
+ &hdmim0_tx0_scl &hdmim0_tx0_sda>;
+ power-domains = <&power RK3588_PD_VO1>;
+ resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>;
+ reset-names = "ref", "hdp";
+ rockchip,grf = <&sys_grf>;
+ rockchip,vo-grf = <&vo1_grf>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi0_in: port@0 {
+ reg = <0>;
+ };
+
+ hdmi0_out: port@1 {
+ reg = <1>;
+ };
+ };
+ };
+
qos_gpu_m0: qos@fdf35000 {
compatible = "rockchip,rk3588-qos", "syscon";
reg = <0x0 0xfdf35000 0x0 0x20>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-evb.dts b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-evb.dts
index a4946cdc3bb3..9d525c8ff725 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-evb.dts
@@ -7,6 +7,7 @@
/dts-v1/;
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588-coolpi-cm5.dtsi"
/ {
@@ -22,6 +23,17 @@
pwms = <&pwm2 0 25000 0>;
};
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
leds: leds {
compatible = "gpio-leds";
@@ -33,7 +45,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -42,7 +54,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -52,7 +64,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -62,7 +74,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc3v3_lcd: vcc3v3-lcd-regulator {
+ vcc3v3_lcd: regulator-vcc3v3-lcd {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_lcd";
enable-active-high;
@@ -72,7 +84,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc5v0_usb_host1: vcc5v0_usb_host2: vcc5v0-usb-host-regulator {
+ vcc5v0_usb_host1: vcc5v0_usb_host2: regulator-vcc5v0-usb-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -86,7 +98,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_usb30_otg: vcc5v0-usb30-otg-regulator {
+ vcc5v0_usb30_otg: regulator-vcc5v0-usb30-otg {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_otg";
regulator-boot-on;
@@ -101,6 +113,26 @@
};
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
/* M.2 E-Key */
&pcie2x1l1 {
reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
@@ -214,3 +246,18 @@
&usb_host1_ohci {
status = "okay";
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts
index 6418286efe40..92f0ed83c990 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts
@@ -7,6 +7,7 @@
/dts-v1/;
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588-coolpi-cm5.dtsi"
/ {
@@ -35,6 +36,17 @@
gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>;
};
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
leds: leds {
compatible = "gpio-leds";
@@ -58,7 +70,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -67,7 +79,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc_sys: vcc-sys-regulator {
+ vcc_sys: regulator-vcc-sys {
compatible = "regulator-fixed";
regulator-name = "vcc_sys";
regulator-always-on;
@@ -77,7 +89,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -87,7 +99,7 @@
vin-supply = <&vcc_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -97,7 +109,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_lcd: vcc3v3-lcd-regulator {
+ vcc3v3_lcd: regulator-vcc3v3-lcd {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_lcd";
enable-active-high;
@@ -107,7 +119,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-boot-on;
@@ -121,7 +133,7 @@
vin-supply = <&vcc_sys>;
};
- vcc5v0_usb_host0: vcc5v0_usb30_host: vcc5v0-usb-host-regulator {
+ vcc5v0_usb_host0: vcc5v0_usb30_host: regulator-vcc5v0-usb-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -136,6 +148,28 @@
};
};
+/* HDMI CEC is not used */
+&hdmi0 {
+ pinctrl-0 = <&hdmim0_tx0_hpd &hdmim0_tx0_scl &hdmim0_tx0_sda>;
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c4 {
status = "okay";
pinctrl-names = "default";
@@ -347,3 +381,18 @@
dr_mode = "host";
status = "okay";
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
index fde8b228f2c7..71ed680621b8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
@@ -36,7 +36,7 @@
stdout-path = "serial2:1500000n8";
};
- avdd0v85_pcie20: avdd0v85-pcie20-regulator {
+ avdd0v85_pcie20: regulator-avdd0v85-pcie20 {
compatible = "regulator-fixed";
regulator-name = "avdd0v85_pcie20";
regulator-boot-on;
@@ -46,7 +46,7 @@
vin-supply = <&vdd_0v85_s0>;
};
- avdd1v8_pcie20: avdd1v8-pcie20-regulator {
+ avdd1v8_pcie20: regulator-avdd1v8-pcie20 {
compatible = "regulator-fixed";
regulator-name = "avdd1v8_pcie20";
regulator-boot-on;
@@ -56,7 +56,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- avdd0v75_pcie30: avdd0v75-pcie30-regulator {
+ avdd0v75_pcie30: regulator-avdd0v75-pcie30 {
compatible = "regulator-fixed";
regulator-name = "avdd0v75_pcie30";
regulator-boot-on;
@@ -66,7 +66,7 @@
vin-supply = <&avdd_0v75_s0>;
};
- pcie30_avdd1v8: avdd1v8-pcie30-regulator {
+ pcie30_avdd1v8: regulator-avdd1v8-pcie30 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-boot-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
index 03fd193be253..5e72d0eff0e0 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
@@ -24,7 +24,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -33,7 +33,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -43,7 +43,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtsi
index 7b1317898358..05ae9bdcfbbd 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-io.dtsi
@@ -10,7 +10,7 @@
stdout-path = "serial2:1500000n8";
};
- vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator {
+ vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie2x1l0";
regulator-min-microvolt = <3300000>;
@@ -19,7 +19,7 @@
vin-supply = <&vcc_3v3_s3>;
};
- vcc3v3_pcie3x2: vcc3v3-pcie3x2-regulator {
+ vcc3v3_pcie3x2: regulator-vcc3v3-pcie3x2 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio2 RK_PC4 GPIO_ACTIVE_HIGH>; /* PCIE_4G_PWEN */
@@ -32,7 +32,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie3x4: vcc3v3-pcie3x4-regulator {
+ vcc3v3_pcie3x4: regulator-vcc3v3-pcie3x4 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; /* PCIE30x4_PWREN_H */
@@ -45,7 +45,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC7 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-wifi.dtso b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-wifi.dtso
index e9a3855e8752..2128ffcc3616 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-wifi.dtso
+++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-wifi.dtso
@@ -14,7 +14,7 @@
#include <dt-bindings/pinctrl/rockchip.h>
&{/} {
- vcc3v3_pcie2x1l1: vcc3v3-pcie2x1l1-regulator {
+ vcc3v3_pcie2x1l1: regulator-vcc3v3-pcie2x1l1 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; /* WIFI_3V3_EN */
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index 00f660d50127..d6e464cdc536 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include <dt-bindings/usb/pd.h>
#include "rk3588.dtsi"
@@ -66,7 +67,7 @@
simple-audio-card,bitclock-master = <&masterdai>;
simple-audio-card,format = "i2s";
simple-audio-card,frame-master = <&masterdai>;
- simple-audio-card,hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>;
+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,pin-switches = "Headphones", "Speaker";
simple-audio-card,routing =
@@ -120,7 +121,18 @@
pwms = <&pwm2 0 25000 0>;
};
- pcie20_avdd0v85: pcie20-avdd0v85-regulator {
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
+ pcie20_avdd0v85: regulator-pcie20-avdd0v85 {
compatible = "regulator-fixed";
regulator-name = "pcie20_avdd0v85";
regulator-always-on;
@@ -130,7 +142,7 @@
vin-supply = <&avdd_0v85_s0>;
};
- pcie20_avdd1v8: pcie20-avdd1v8-regulator {
+ pcie20_avdd1v8: regulator-pcie20-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie20_avdd1v8";
regulator-always-on;
@@ -140,7 +152,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- pcie30_avdd0v75: pcie30-avdd0v75-regulator {
+ pcie30_avdd0v75: regulator-pcie30-avdd0v75 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v75";
regulator-always-on;
@@ -150,7 +162,7 @@
vin-supply = <&avdd_0v75_s0>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -160,7 +172,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- vbus5v0_typec: vbus5v0-typec-regulator {
+ vbus5v0_typec: regulator-vbus5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>;
@@ -172,7 +184,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -181,7 +193,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie30";
regulator-min-microvolt = <3300000>;
@@ -194,7 +206,7 @@
pinctrl-0 = <&vcc3v3_pcie30_en>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -208,7 +220,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -218,7 +230,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usbdcin: vcc5v0-usbdcin-regulator {
+ vcc5v0_usbdcin: regulator-vcc5v0-usbdcin {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usbdcin";
regulator-always-on;
@@ -228,7 +240,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -300,6 +312,26 @@
status = "okay";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c2 {
status = "okay";
@@ -1256,3 +1288,18 @@
dr_mode = "host";
status = "okay";
};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-fet3588-c.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-fet3588-c.dtsi
index 47e64d547ea9..390051317389 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-fet3588-c.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-fet3588-c.dtsi
@@ -29,7 +29,7 @@
};
};
- pcie20_avdd0v85: pcie20-avdd0v85-regulator {
+ pcie20_avdd0v85: regulator-pcie20-avdd0v85 {
compatible = "regulator-fixed";
regulator-name = "pcie20_avdd0v85";
regulator-always-on;
@@ -39,7 +39,7 @@
vin-supply = <&vdd_0v85_s0>;
};
- pcie20_avdd1v8: pcie20-avdd1v8-regulator {
+ pcie20_avdd1v8: regulator-pcie20-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie20_avdd1v8";
regulator-always-on;
@@ -49,7 +49,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- pcie30_avdd0v75: pcie30-avdd0v75-regulator {
+ pcie30_avdd0v75: regulator-pcie30-avdd0v75 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v75";
regulator-always-on;
@@ -59,7 +59,7 @@
vin-supply = <&avdd_0v75_s0>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -69,7 +69,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -79,7 +79,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc4v0_sys: vcc4v0-sys-regulator {
+ vcc4v0_sys: regulator-vcc4v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc4v0_sys";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts b/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts
index 83103e4c7216..b3a04ca370bb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dts
@@ -11,6 +11,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include <dt-bindings/usb/pd.h>
#include "rk3588-friendlyelec-cm3588.dtsi"
@@ -38,7 +39,7 @@
pinctrl-0 = <&headphone_detect>;
simple-audio-card,format = "i2s";
- simple-audio-card,hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>;
+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,name = "realtek,rt5616-codec";
@@ -89,6 +90,17 @@
};
};
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
ir-receiver {
compatible = "gpio-ir-receiver";
gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>;
@@ -307,6 +319,26 @@
"", "", "", "";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
/* Connected to MIPI-DSI0 */
&i2c5 {
pinctrl-names = "default";
@@ -776,3 +808,18 @@
&usbdp_phy1 {
status = "okay";
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts b/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts
index 31d2f8994f85..90f823b2c219 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-jaguar.dts
@@ -8,6 +8,7 @@
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include <dt-bindings/usb/pd.h>
#include "rk3588.dtsi"
@@ -32,6 +33,7 @@
aliases {
ethernet0 = &gmac0;
+ i2c10 = &i2c10;
mmc0 = &sdhci;
mmc1 = &sdmmc;
rtc0 = &rtc_twi;
@@ -42,7 +44,7 @@
};
/* DCIN is 12-24V but standard is 12V */
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -58,6 +60,17 @@
reset-gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_HIGH>;
};
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -98,7 +111,7 @@
gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -108,7 +121,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_1v2_s3: vcc-1v2-s3-regulator {
+ vcc_1v2_s3: regulator-vcc-1v2-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v2_s3";
regulator-always-on;
@@ -119,7 +132,7 @@
};
/* Exposed on P14 and P15 */
- vcc_2v8_s3: vcc-2v8-s3-regulator {
+ vcc_2v8_s3: regulator-vcc-2v8-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_2v8_s3";
regulator-always-on;
@@ -129,7 +142,7 @@
vin-supply = <&vcc_3v3_s3>;
};
- vcc_5v0_usb_a: vcc-5v0-usb-a-regulator {
+ vcc_5v0_usb_a: regulator-vcc-5v0-usb-a {
compatible = "regulator-fixed";
regulator-name = "usb_a_vcc";
regulator-min-microvolt = <5000000>;
@@ -139,7 +152,7 @@
enable-active-high;
};
- vcc_5v0_usb_c1: vcc-5v0-usb-c1-regulator {
+ vcc_5v0_usb_c1: regulator-vcc-5v0-usb-c1 {
compatible = "regulator-fixed";
regulator-name = "5v_usbc1";
regulator-min-microvolt = <5000000>;
@@ -149,7 +162,7 @@
enable-active-high;
};
- vcc_5v0_usb_c2: vcc-5v0-usb-c2-regulator {
+ vcc_5v0_usb_c2: regulator-vcc-5v0-usb-c2 {
compatible = "regulator-fixed";
regulator-name = "5v_usbc2";
regulator-min-microvolt = <5000000>;
@@ -159,7 +172,7 @@
enable-active-high;
};
- vcc3v3_mdot2: vcc3v3-mdot2-regulator {
+ vcc3v3_mdot2: regulator-vcc3v3-mdot2 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_mdot2";
regulator-always-on;
@@ -169,7 +182,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -179,7 +192,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -271,13 +284,53 @@
status = "okay";
};
+&hdmi0 {
+ /* No CEC on Jaguar */
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmim0_tx0_hpd &hdmim0_tx0_scl &hdmim0_tx0_sda>;
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-0 = <&i2c0m2_xfer>;
status = "okay";
fan@18 {
- compatible = "ti,amc6821";
+ compatible = "tsd,mule", "ti,amc6821";
reg = <0x18>;
+
+ i2c-mux {
+ compatible = "tsd,mule-i2c-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c10: i2c@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc_twi: rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+ };
+ };
};
vdd_npu_s0: regulator@42 {
@@ -313,11 +366,6 @@
regulator-off-in-suspend;
};
};
-
- rtc_twi: rtc@6f {
- compatible = "isil,isl1208";
- reg = <0x6f>;
- };
};
&i2c1 {
@@ -864,3 +912,18 @@
&usb_host1_ohci {
status = "okay";
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts
index 2d92bbb4027d..ff855064be08 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts
@@ -15,7 +15,7 @@
compatible = "friendlyarm,nanopc-t6-lts", "rockchip,rk3588";
/* provide power for on-board USB 2.0 hub */
- vcc5v0_usb20_host: vcc5v0-usb20-host-regulator {
+ vcc5v0_usb20_host: regulator-vcc5v0-usb20-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
index 92321c1d3ff1..40290a81bb9d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
@@ -14,7 +14,7 @@
model = "FriendlyElec NanoPC-T6";
compatible = "friendlyarm,nanopc-t6", "rockchip,rk3588";
- vdd_4g_3v3: vdd-4g-3v3-regulator {
+ vdd_4g_3v3: regulator-vdd-4g-3v3 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi
index fc131789b4c3..cb350727d116 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include <dt-bindings/usb/pd.h>
#include "rk3588.dtsi"
@@ -40,6 +41,17 @@
stdout-path = "serial2:1500000n8";
};
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
ir-receiver {
compatible = "gpio-ir-receiver";
gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>;
@@ -75,7 +87,7 @@
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
- simple-audio-card,hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>;
+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>;
simple-audio-card,widgets =
"Headphone", "Headphones",
@@ -94,7 +106,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -104,7 +116,7 @@
};
/* vcc5v0_sys powers peripherals */
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -115,7 +127,7 @@
};
/* vcc4v0_sys powers the RK806, RK860's */
- vcc4v0_sys: vcc4v0-sys-regulator {
+ vcc4v0_sys: regulator-vcc4v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc4v0_sys";
regulator-always-on;
@@ -125,7 +137,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc-1v1-nldo-s3";
regulator-always-on;
@@ -135,7 +147,7 @@
vin-supply = <&vcc4v0_sys>;
};
- vcc_3v3_pcie20: vcc3v3-pcie20-regulator {
+ vcc_3v3_pcie20: regulator-vcc3v3-pcie20 {
compatible = "regulator-fixed";
regulator-name = "vcc_3v3_pcie20";
regulator-always-on;
@@ -145,7 +157,7 @@
vin-supply = <&vcc_3v3_s3>;
};
- vbus5v0_typec: vbus5v0-typec-regulator {
+ vbus5v0_typec: regulator-vbus5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
@@ -159,7 +171,21 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator {
+ vbus5v0_usb: regulator-vbus5v0-usb {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb5v_pwren>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vbus5v0_usb";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>;
@@ -171,7 +197,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -183,7 +209,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sd_s0: vcc3v3-sd-s0-regulator {
+ vcc3v3_sd_s0: regulator-vcc3v3-sd-s0 {
compatible = "regulator-fixed";
gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_LOW>;
regulator-boot-on;
@@ -318,6 +344,26 @@
status = "okay";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -575,6 +621,10 @@
rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
};
+ usb5v_pwren: usb5v_pwren {
+ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
usbc0_int: usbc0-int {
rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
};
@@ -973,6 +1023,14 @@
status = "okay";
};
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ status = "okay";
+};
+
&u2phy2_host {
status = "okay";
};
@@ -1012,6 +1070,11 @@
};
};
+&usbdp_phy1 {
+ phy-supply = <&vbus5v0_usb>;
+ status = "okay";
+};
+
&usb_host0_ehci {
status = "okay";
};
@@ -1032,6 +1095,11 @@
};
};
+&usb_host1_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
&usb_host1_ehci {
status = "okay";
};
@@ -1039,3 +1107,18 @@
&usb_host1_ohci {
status = "okay";
};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
index c2a08bdf09e8..1c0851b45eb8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
@@ -75,7 +75,7 @@
simple-audio-card,bitclock-master = <&masterdai>;
simple-audio-card,format = "i2s";
simple-audio-card,frame-master = <&masterdai>;
- simple-audio-card,hp-det-gpio = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,pin-switches = "Headphones", "Speaker";
simple-audio-card,widgets =
@@ -100,7 +100,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -109,7 +109,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc1v8_sys: vcc1v8-sys-regulator {
+ vcc1v8_sys: regulator-vcc1v8-sys {
compatible = "regulator-fixed";
regulator-name = "vcc1v8_sys";
regulator-always-on;
@@ -119,7 +119,7 @@
vin-supply = <&vcc3v3_sys>;
};
- vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator {
+ vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie2x1l0";
regulator-min-microvolt = <3300000>;
@@ -128,7 +128,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2-regulator {
+ vcc3v3_pcie2x1l2: regulator-vcc3v3-pcie2x1l2 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie2x1l2";
regulator-min-microvolt = <3300000>;
@@ -137,7 +137,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie30: vcc3v3_pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3_pcie30 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie30";
regulator-always-on;
@@ -147,7 +147,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sys: vcc3v3-sys-regulator {
+ vcc3v3_sys: regulator-vcc3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -157,7 +157,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
index c3a6812cc93a..9f5a38b290bf 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/leds/common.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include <dt-bindings/usb/pd.h>
#include "rk3588.dtsi"
@@ -85,6 +86,17 @@
};
};
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
fan: pwm-fan {
compatible = "pwm-fan";
cooling-levels = <0 70 75 80 100>;
@@ -120,7 +132,7 @@
simple-audio-card,aux-devs = <&speaker_amp>, <&headphone_amp>;
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
- simple-audio-card,hp-det-gpio = <&gpio1 RK_PD3 GPIO_ACTIVE_LOW>;
+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_LOW>;
simple-audio-card,bitclock-master = <&daicpu>;
simple-audio-card,frame-master = <&daicpu>;
/*TODO: SARADC_IN3 is used as MIC detection / key input */
@@ -165,7 +177,7 @@
};
};
- vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -176,7 +188,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie_eth: vcc3v3-pcie-eth-regulator {
+ vcc3v3_pcie_eth: regulator-vcc3v3-pcie-eth {
compatible = "regulator-fixed";
gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
regulator-name = "vcc3v3_pcie_eth";
@@ -186,7 +198,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_wf: vcc3v3-wf-regulator {
+ vcc3v3_wf: regulator-vcc3v3-wf {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -197,7 +209,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -206,7 +218,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc5v0_usb20: vcc5v0-usb20-regulator {
+ vcc5v0_usb20: regulator-vcc5v0-usb20 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
@@ -263,6 +275,31 @@
cpu-supply = <&vdd_cpu_lit_s0>;
};
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -328,7 +365,6 @@
compatible = "everest,es8388";
reg = <0x11>;
clocks = <&cru I2S0_8CH_MCLKOUT>;
- clock-names = "mclk";
AVDD-supply = <&vcc_1v8_s0>;
DVDD-supply = <&vcc_1v8_s0>;
HPVDD-supply = <&vcc_3v3_s0>;
@@ -358,6 +394,36 @@
status = "okay";
};
+&package_thermal {
+ polling-delay = <1000>;
+
+ cooling-maps {
+ map0 {
+ trip = <&package_fan0>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+ };
+
+ map1 {
+ trip = <&package_fan1>;
+ cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+ };
+ };
+
+ trips {
+ package_fan0: package-fan0 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+
+ package_fan1: package-fan1 {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+ };
+};
+
/* phy1 - M.KEY socket */
&pcie2x1l0 {
reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -853,3 +919,18 @@
&usb_host1_ohci {
status = "okay";
};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
index e4a20cda65ed..088cfade6f6f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
@@ -104,7 +104,7 @@
simple-audio-card,aux-devs = <&speaker_amp>, <&headphone_amp>;
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
- simple-audio-card,hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>;
+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>;
simple-audio-card,bitclock-master = <&daicpu>;
simple-audio-card,frame-master = <&daicpu>;
/* SARADC_IN3 is used as MIC detection / key input */
@@ -149,7 +149,7 @@
};
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -158,7 +158,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_bt: vcc3v3-bt-regulator {
+ vcc3v3_bt: regulator-vcc3v3-bt {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -169,7 +169,7 @@
vin-supply = <&vcc_3v3_s0>;
};
- vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>;
@@ -180,7 +180,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc3v3_wf: vcc3v3-wf-regulator {
+ vcc3v3_wf: regulator-vcc3v3-wf {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>;
@@ -191,7 +191,7 @@
vin-supply = <&vcc_3v3_s0>;
};
- vcc4v0_sys: vcc4v0-sys-regulator {
+ vcc4v0_sys: regulator-vcc4v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc4v0_sys";
regulator-always-on;
@@ -201,7 +201,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
@@ -215,7 +215,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -316,7 +316,6 @@
assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
assigned-clock-rates = <12288000>;
clocks = <&cru I2S0_8CH_MCLKOUT>;
- clock-names = "mclk";
AVDD-supply = <&avcc_1v8_codec_s0>;
DVDD-supply = <&avcc_1v8_codec_s0>;
HPVDD-supply = <&vcc_3v3_s0>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
index d0b922b8d67e..6d68f70284e4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5-itx.dts
@@ -46,7 +46,7 @@
compatible = "audio-graph-card";
label = "rk3588-es8316";
dais = <&i2s0_8ch_p0>;
- hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
+ hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&hp_detect>;
routing = "MIC2", "Mic Jack",
@@ -72,6 +72,15 @@
};
};
+ /* Unnamed gated oscillator: 100MHz,3.3V,3225 */
+ pcie30_port0_refclk: pcie30_port1_refclk: pcie-oscillator {
+ compatible = "gated-fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ clock-output-names = "pcie30_refclk";
+ vdd-supply = <&vcc3v3_pi6c_05>;
+ };
+
fan0: pwm-fan {
compatible = "pwm-fan";
#cooling-cells = <2>;
@@ -146,13 +155,14 @@
vin-supply = <&vcc_3v3_s3>;
};
- vcc3v3_mkey: regulator-vcc3v3-mkey {
+ /* The PCIE30x4_PWREN_H controls two regulators */
+ vcc3v3_mkey: vcc3v3_pi6c_05: regulator-vcc3v3-pi6c-05 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pcie30x4_pwren_h>;
- regulator-name = "vcc3v3_mkey";
+ regulator-name = "vcc3v3_pi6c_05";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
startup-delay-us = <5000>;
@@ -513,6 +523,18 @@
/* ASMedia ASM1164 Sata controller */
&pcie3x2 {
+ /*
+ * The board has a "pcie_refclk" oscillator that needs enabling,
+ * so add it to the list of clocks.
+ */
+ clocks = <&cru ACLK_PCIE_2L_MSTR>, <&cru ACLK_PCIE_2L_SLV>,
+ <&cru ACLK_PCIE_2L_DBI>, <&cru PCLK_PCIE_2L>,
+ <&cru CLK_PCIE_AUX1>, <&cru CLK_PCIE2L_PIPE>,
+ <&pcie30_port1_refclk>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe",
+ "ref";
pinctrl-names = "default";
pinctrl-0 = <&pcie30x2_perstn_m1_l>;
reset-gpios = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
@@ -522,6 +544,18 @@
/* M.2 M.key */
&pcie3x4 {
+ /*
+ * The board has a "pcie_refclk" oscillator that needs enabling,
+ * so add it to the list of clocks.
+ */
+ clocks = <&cru ACLK_PCIE_4L_MSTR>, <&cru ACLK_PCIE_4L_SLV>,
+ <&cru ACLK_PCIE_4L_DBI>, <&cru PCLK_PCIE_4L>,
+ <&cru CLK_PCIE_AUX0>, <&cru CLK_PCIE4L_PIPE>,
+ <&pcie30_port0_refclk>;
+ clock-names = "aclk_mst", "aclk_slv",
+ "aclk_dbi", "pclk",
+ "aux", "pipe",
+ "ref";
num-lanes = <2>;
pinctrl-names = "default";
pinctrl-0 = <&pcie30x4_perstn_m1_l>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 966bbc582d89..c44d001da169 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -4,6 +4,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588.dtsi"
/ {
@@ -32,11 +33,22 @@
"Headphones", "HPOR";
dais = <&i2s0_8ch_p0>;
- hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
+ hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&hp_detect>;
};
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -72,7 +84,7 @@
shutdown-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
};
- vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator {
+ vcc3v3_pcie2x1l0: regulator-vcc3v3-pcie2x1l0 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
@@ -87,7 +99,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2-regulator {
+ vcc3v3_pcie2x1l2: regulator-vcc3v3-pcie2x1l2 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie2x1l2";
regulator-min-microvolt = <3300000>;
@@ -96,7 +108,7 @@
vin-supply = <&vcc_3v3_s3>;
};
- vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>;
@@ -109,7 +121,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -123,7 +135,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -132,7 +144,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -192,6 +204,26 @@
status = "okay";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -304,12 +336,12 @@
};
cooling-maps {
- map1 {
+ map0 {
trip = <&package_fan0>;
cooling-device = <&fan THERMAL_NO_LIMIT 1>;
};
- map2 {
+ map1 {
trip = <&package_fan1>;
cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
};
@@ -858,3 +890,18 @@
&usb_host2_xhci {
status = "okay";
};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts
index e4b7a0a4444b..3187b4918a30 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-tiger-haikou.dts
@@ -5,6 +5,7 @@
/dts-v1/;
#include <dt-bindings/input/input.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588-tiger.dtsi"
/ {
@@ -20,7 +21,7 @@
stdout-path = "serial2:115200n8";
};
- dc_12v: dc-12v-regulator {
+ dc_12v: regulator-dc-12v {
compatible = "regulator-fixed";
regulator-name = "dc_12v";
regulator-always-on;
@@ -61,6 +62,17 @@
};
};
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
i2s3-sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
@@ -84,7 +96,7 @@
clock-frequency = <24576000>;
};
- vcc3v3_baseboard: vcc3v3-baseboard-regulator {
+ vcc3v3_baseboard: regulator-vcc3v3-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_baseboard";
regulator-always-on;
@@ -94,7 +106,7 @@
vin-supply = <&dc_12v>;
};
- vcc3v3_low_noise: vcc3v3-low-noise-regulator {
+ vcc3v3_low_noise: regulator-vcc3v3-low-noise {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_low_noise";
regulator-boot-on;
@@ -103,7 +115,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_baseboard: vcc5v0-baseboard-regulator {
+ vcc5v0_baseboard: regulator-vcc5v0-baseboard {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_baseboard";
regulator-always-on;
@@ -113,7 +125,7 @@
vin-supply = <&dc_12v>;
};
- vcc5v0_otg: vcc5v0-otg-regulator {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
@@ -123,7 +135,7 @@
regulator-always-on;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -133,7 +145,7 @@
vin-supply = <&dc_12v>;
};
- vddd_audio_1v6: vddd-audio-1v6-regulator {
+ vddd_audio_1v6: regulator-vddd-audio-1v6 {
compatible = "regulator-fixed";
regulator-name = "vddd_audio_1v6";
regulator-boot-on;
@@ -155,6 +167,32 @@
status = "okay";
};
+&hdmi0 {
+ /*
+ * While HDMI-CEC is present on the Q7 connector, it is not
+ * connected on Haikou itself.
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmim0_tx0_hpd &hdmim1_tx0_scl &hdmim1_tx0_sda>;
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c1 {
status = "okay";
@@ -321,3 +359,18 @@
&usb_host2_xhci {
status = "okay";
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi
index 615094bb8ba3..81a6a05ce13b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-tiger.dtsi
@@ -12,6 +12,7 @@
compatible = "tsd,rk3588-tiger", "rockchip,rk3588";
aliases {
+ i2c10 = &i2c10;
mmc0 = &sdhci;
rtc0 = &rtc_twi;
};
@@ -64,7 +65,7 @@
enable-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; /* PCIE30X4_CLKREQN_M1_L */
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -74,7 +75,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_1v2_s3: vcc-1v2-s3-regulator {
+ vcc_1v2_s3: regulator-vcc-1v2-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v2_s3";
regulator-always-on;
@@ -84,7 +85,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -152,6 +153,12 @@
status = "okay";
};
+&hdmi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmim1_tx0_cec &hdmim0_tx0_hpd &hdmim1_tx0_scl
+ &hdmim1_tx0_sda>;
+};
+
&i2c1 {
pinctrl-0 = <&i2c1m0_xfer>;
};
@@ -224,13 +231,25 @@
status = "okay";
fan@18 {
- compatible = "ti,amc6821";
+ compatible = "tsd,mule", "ti,amc6821";
reg = <0x18>;
- };
- rtc_twi: rtc@6f {
- compatible = "isil,isl1208";
- reg = <0x6f>;
+ i2c-mux {
+ compatible = "tsd,mule-i2c-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c10: i2c@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc_twi: rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
index d0021524e7f9..3cbee5b97470 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
@@ -61,7 +61,7 @@
pwms = <&pwm2 0 25000 0>;
};
- pcie20_avdd0v85: pcie20-avdd0v85-regulator {
+ pcie20_avdd0v85: regulator-pcie20-avdd0v85 {
compatible = "regulator-fixed";
regulator-name = "pcie20_avdd0v85";
regulator-always-on;
@@ -71,7 +71,7 @@
vin-supply = <&vdd_0v85_s0>;
};
- pcie20_avdd1v8: pcie20-avdd1v8-regulator {
+ pcie20_avdd1v8: regulator-pcie20-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie20_avdd1v8";
regulator-always-on;
@@ -81,7 +81,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- pcie30_avdd0v75: pcie30-avdd0v75-regulator {
+ pcie30_avdd0v75: regulator-pcie30-avdd0v75 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd0v75";
regulator-always-on;
@@ -91,7 +91,7 @@
vin-supply = <&avdd_0v75_s0>;
};
- pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ pcie30_avdd1v8: regulator-pcie30-avdd1v8 {
compatible = "regulator-fixed";
regulator-name = "pcie30_avdd1v8";
regulator-always-on;
@@ -101,7 +101,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -110,7 +110,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
@@ -124,7 +124,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -134,7 +134,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usbdcin: vcc5v0-usbdcin-regulator {
+ vcc5v0_usbdcin: regulator-vcc5v0-usbdcin {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usbdcin";
regulator-always-on;
@@ -144,7 +144,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -154,7 +154,7 @@
vin-supply = <&vcc5v0_usbdcin>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -428,7 +428,6 @@
regulator-boot-on;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <950000>;
- regulator-init-microvolt = <750000>;
regulator-ramp-delay = <12500>;
regulator-state-mem {
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
index dbaa94ca69f4..6bc46734cc14 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
@@ -33,7 +33,7 @@
#cooling-cells = <2>;
};
- vcc3v3_pcie30: vcc3v3-pcie30-regulator {
+ vcc3v3_pcie30: regulator-vcc3v3-pcie30 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie30";
regulator-min-microvolt = <3300000>;
@@ -45,7 +45,7 @@
startup-delay-us = <5000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -54,7 +54,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -116,6 +116,11 @@
status = "okay";
};
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -208,10 +213,63 @@
};
};
+&package_thermal {
+ trips {
+ package_active1: trip-active1 {
+ temperature = <45000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+ package_active2: trip-active2 {
+ temperature = <50000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+ package_active3: trip-active3 {
+ temperature = <60000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+ package_active4: trip-active4 {
+ temperature = <70000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+ package_active5: trip-active5 {
+ temperature = <80000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map1 {
+ trip = <&package_active1>;
+ cooling-device = <&fan 1 1>;
+ };
+ map2 {
+ trip = <&package_active2>;
+ cooling-device = <&fan 2 2>;
+ };
+ map3 {
+ trip = <&package_active3>;
+ cooling-device = <&fan 3 3>;
+ };
+ map4 {
+ trip = <&package_active4>;
+ cooling-device = <&fan 4 4>;
+ };
+ map5 {
+ trip = <&package_active5>;
+ cooling-device = <&fan 5 5>;
+ };
+ };
+};
+
&pcie2x1l1 {
linux,pci-domain = <1>;
pinctrl-names = "default";
- pinctrl-0 = <&pcie2_reset>;
+ pinctrl-0 = <&pcie2_reset>, <&pcie30x1m1_0_clkreqn>, <&pcie30x1m1_0_waken>;
reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
status = "okay";
};
@@ -223,7 +281,7 @@
&pcie3x4 {
linux,pci-domain = <0>;
pinctrl-names = "default";
- pinctrl-0 = <&pcie3_reset>;
+ pinctrl-0 = <&pcie3_reset>, <&pcie30x4m1_clkreqn>, <&pcie30x4m1_waken>;
reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_pcie30>;
status = "okay";
@@ -296,6 +354,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
<&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ system-power-controller;
vcc1-supply = <&vcc5v0_sys>;
vcc2-supply = <&vcc5v0_sys>;
@@ -333,6 +392,17 @@
regulators {
vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 {
+ /*
+ * RK3588's GPU power domain cannot be enabled
+ * without this regulator active, but it
+ * doesn't have to be on when the GPU PD is
+ * disabled. Because the PD binding does not
+ * currently allow us to express this
+ * relationship, we have no choice but to do
+ * this instead:
+ */
+ regulator-always-on;
+
regulator-boot-on;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <950000>;
@@ -613,3 +683,68 @@
pinctrl-0 = <&uart9m0_xfer>;
status = "okay";
};
+
+/* USB 0: USB 2.0 only, OTG-capable */
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+&usbdp_phy0 {
+ /*
+ * TODO: On the RK1, USBDP0 drives the DisplayPort pins and is not
+ * involved in this USB2-only bus. The bus controller (below) needs to
+ * know that it doesn't have a USB3 port so it can ignore any
+ * USB3-related signals. This is handled in hardware by updating the
+ * GRFs corresponding to that bus controller. Alas, Linux currently
+ * puts the code to do that in the USBDP driver, so USBDP0 must be
+ * enabled for now.
+ */
+ rockchip,dp-lane-mux = <0 1 2 3>; /* "No USB lanes" */
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ extcon = <&u2phy0>;
+ maximum-speed = "high-speed";
+ status = "okay";
+};
+
+/* USB 1: USB 3.0, host only */
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ status = "okay";
+};
+
+&usbdp_phy1 {
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ dr_mode = "host";
+ extcon = <&u2phy1>;
+ status = "okay";
+};
+
+/* USB 2: USB 2.0, host only */
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
index 074c316a9a69..9c394f733bbf 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts
@@ -11,6 +11,7 @@
#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 "rk3588s.dtsi"
/ {
@@ -38,6 +39,17 @@
stdout-path = "serial2:1500000n8";
};
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "d";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
leds: leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -75,7 +87,7 @@
reset-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_LOW>;
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -84,7 +96,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -94,7 +106,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usbdcin: vcc5v0-usbdcin-regulator {
+ vcc5v0_usbdcin: regulator-vcc5v0-usbdcin {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usbdcin";
regulator-always-on;
@@ -104,7 +116,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -114,7 +126,7 @@
vin-supply = <&vcc5v0_usbdcin>;
};
- avdd0v85_pcie20: avdd0v85-pcie20-regulator {
+ avdd0v85_pcie20: regulator-avdd0v85-pcie20 {
compatible = "regulator-fixed";
regulator-name = "avdd0v85_pcie20";
regulator-boot-on;
@@ -124,7 +136,7 @@
vin-supply = <&vdd_0v85_s0>;
};
- avdd1v8_pcie20: avdd1v8-pcie20-regulator {
+ avdd1v8_pcie20: regulator-avdd1v8-pcie20 {
compatible = "regulator-fixed";
regulator-name = "avdd1v8_pcie20";
regulator-boot-on;
@@ -134,7 +146,7 @@
vin-supply = <&avcc_1v8_s0>;
};
- vcc3v3_mipi: vcc3v3-mipi-regulator {
+ vcc3v3_mipi: regulator-vcc3v3-mipi {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
@@ -144,7 +156,7 @@
vin-supply = <&vcc_3v3_s3>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
@@ -158,7 +170,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_otg: vcc5v0-otg-regulator {
+ vcc5v0_otg: regulator-vcc5v0-otg {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
@@ -172,7 +184,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -208,6 +220,26 @@
status = "okay";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-0 = <&i2c0m2_xfer>;
status = "okay";
@@ -815,3 +847,18 @@
&usb_host1_ohci {
status = "okay";
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
new file mode 100644
index 000000000000..bc4077575beb
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-v10.dts
@@ -0,0 +1,1170 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/usb/pd.h>
+#include "rk3588s.dtsi"
+
+/ {
+ model = "Rockchip RK3588S EVB1 V10 Board";
+ compatible = "rockchip,rk3588s-evb1-v10", "rockchip,rk3588s";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-escape {
+ label = "Escape";
+ linux,code = <KEY_ESC>;
+ press-threshold-microvolt = <1235000>;
+ };
+
+ button-menu {
+ label = "Menu";
+ linux,code = <KEY_MENU>;
+ press-threshold-microvolt = <890000>;
+ };
+
+ button-vol-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ press-threshold-microvolt = <17000>;
+ };
+
+ button-vol-down {
+ label = "Volume Down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ press-threshold-microvolt = <417000>;
+ };
+ };
+
+ amp_headphone: amplifier-headphone {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&headphone_amplifier_en>;
+ sound-name-prefix = "Headphones Amplifier";
+ };
+
+ amp_speaker: amplifier-speaker {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&speaker_amplifier_en>;
+ sound-name-prefix = "Speaker Amplifier";
+ };
+
+ analog-sound {
+ compatible = "simple-audio-card";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_detect>;
+ simple-audio-card,name = "RK3588 EVB1 Audio";
+ simple-audio-card,aux-devs = <&amp_headphone>, <&amp_speaker>;
+ simple-audio-card,bitclock-master = <&masterdai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&masterdai>;
+ simple-audio-card,hp-det-gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_LOW>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,pin-switches = "Headphones", "Speaker";
+ simple-audio-card,routing =
+ "Speaker Amplifier INL", "LOUT2",
+ "Speaker Amplifier INR", "ROUT2",
+ "Speaker", "Speaker Amplifier OUTL",
+ "Speaker", "Speaker Amplifier OUTR",
+ "Headphones Amplifier INL", "LOUT1",
+ "Headphones Amplifier INR", "ROUT1",
+ "Headphones", "Headphones Amplifier OUTL",
+ "Headphones", "Headphones Amplifier OUTR",
+ "LINPUT1", "Onboard Microphone",
+ "RINPUT1", "Onboard Microphone",
+ "LINPUT2", "Microphone Jack",
+ "RINPUT2", "Microphone Jack";
+ simple-audio-card,widgets =
+ "Microphone", "Microphone Jack",
+ "Microphone", "Onboard Microphone",
+ "Headphone", "Headphones",
+ "Speaker", "Speaker";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0_8ch>;
+ };
+
+ masterdai: simple-audio-card,codec {
+ sound-dai = <&es8388>;
+ system-clock-frequency = <12288000>;
+ };
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ power-supply = <&vcc3v3_lcd_edp>;
+ pwms = <&pwm12 0 25000 0>;
+ };
+
+ combophy_avdd0v85: regulator-combophy-avdd0v85 {
+ compatible = "regulator-fixed";
+ regulator-name = "combophy_avdd0v85";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ vin-supply = <&vdd_0v85_s0>;
+ };
+
+ combophy_avdd1v8: regulator-combophy-avdd1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "combophy_avdd1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&avcc_1v8_s0>;
+ };
+
+ vbus5v0_typec: regulator-vbus5v0-typec {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec5v_pwren>;
+ regulator-name = "vbus5v0_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_usb>;
+ };
+
+ vcc12v_dcin: regulator-vcc12v-dcin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc12v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc3v3_lcd_edp: regulator-vcc3v3-lcd-edp {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc3v3_lcd_edp_en>;
+ regulator-name = "vcc3v3_lcd_edp";
+ regulator-boot-on;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc3v3_pcie20: regulator-vcc3v3-pcie20 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc3v3_pcie20_en>;
+ regulator-name = "vcc3v3_pcie20";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc5v0_host: regulator-vcc5v0-host {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_host_en>;
+ regulator-name = "vcc5v0_host";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_usb>;
+ };
+
+ 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 = <&vcc12v_dcin>;
+ };
+
+ vcc5v0_usb: regulator-vcc5v0-usb {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_usbdcin>;
+ };
+
+ vcc5v0_usbdcin: regulator-vcc5v0-usbdcin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usbdcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+
+ es8388: audio-codec@11 {
+ compatible = "everest,es8388";
+ reg = <0x11>;
+ clocks = <&cru I2S0_8CH_MCLKOUT>;
+ assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
+ assigned-clock-rates = <12288000>;
+ AVDD-supply = <&avcc_1v8_s0>;
+ DVDD-supply = <&avcc_1v8_s0>;
+ HPVDD-supply = <&vcc_3v3_s0>;
+ PVDD-supply = <&vcc_3v3_s0>;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&i2c8 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c8m2_xfer>;
+ status = "okay";
+
+ usbc0: usb-typec@22 {
+ compatible = "fcs,fusb302";
+ reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbc0_int>;
+ vbus-supply = <&vbus5v0_typec>;
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ op-sink-microwatt = <1000000>;
+ power-role = "dual";
+ sink-pdos =
+ <PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
+ source-pdos =
+ <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+ try-power-role = "source";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usbc0_orien_sw: endpoint {
+ remote-endpoint = <&usbdp_phy0_orientation_switch>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usbc0_role_sw: endpoint {
+ remote-endpoint = <&dwc3_0_role_switch>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ dp_altmode_mux: endpoint {
+ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
+ };
+ };
+ };
+ };
+ };
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PC4 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
+
+&pcie2x1l1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_1_rst>;
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie20>;
+ status = "okay";
+};
+
+&pcie2x1l2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_2_rst>;
+ reset-gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&pinctrl {
+ audio {
+ hp_detect: headphone-detect {
+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ headphone_amplifier_en: headphone-amplifier-en {
+ rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ speaker_amplifier_en: speaker-amplifier-en {
+ rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ lcd-edp {
+ vcc3v3_lcd_edp_en: vcc3v3-lcd-edp-en {
+ rockchip,pins = <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie2 {
+ pcie2_1_rst: pcie2-1-rst {
+ rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie2_2_rst: pcie2-2-rst {
+ rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc3v3_pcie20_en: vcc3v3-pcie20-en {
+ rockchip,pins = <4 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ vcc5v0_host_en: vcc5v0-host-en {
+ rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb-typec {
+ typec5v_pwren: typec5v-pwren {
+ rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usbc0_int: usbc0-int {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&pwm12 {
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8_s0>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ no-sdio;
+ no-sd;
+ non-removable;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ max-frequency = <150000000>;
+ no-mmc;
+ no-sdio;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_sd_s0>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&spi2 {
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <2>;
+ status = "okay";
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ reg = <0x0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ spi-max-frequency = <1000000>;
+ system-power-controller;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vcc5v0_sys>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: dcdc-reg1 {
+ regulator-name = "vdd_gpu_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_npu_s0: dcdc-reg2 {
+ regulator-name = "vdd_npu_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-name = "vdd_log_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: dcdc-reg4 {
+ regulator-name = "vdd_vdenc_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_gpu_mem_s0: dcdc-reg5 {
+ regulator-name = "vdd_gpu_mem_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_npu_mem_s0: dcdc-reg6 {
+ regulator-name = "vdd_npu_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-name = "vdd_2v0_pldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vdd_vdenc_mem_s0: dcdc-reg8 {
+ regulator-name = "vdd_vdenc_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg9 {
+ regulator-name = "vdd2_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_1v1_nldo_s3: dcdc-reg10 {
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1100000>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-name = "avcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd1_1v8_ddr_s3: pldo-reg2 {
+ regulator-name = "vdd1_1v8_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_1v8_s3: pldo-reg3 {
+ regulator-name = "vcc_1v8_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-name = "vcc_3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-name = "vccio_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ master_pldo6_s3: pldo-reg6 {
+ regulator-name = "master_pldo6_s3";
+ 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>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-name = "vdd_0v75_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd2l_0v9_ddr_s3: nldo-reg2 {
+ regulator-name = "vdd2l_0v9_ddr_s3";
+ 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>;
+ };
+ };
+
+ master_nldo3: nldo-reg3 {
+ regulator-name = "master_nldo3";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg4 {
+ regulator-name = "avdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg5 {
+ regulator-name = "vdd_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+
+ pmic@1 {
+ compatible = "rockchip,rk806";
+ reg = <0x01>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rk806_slave_dvs1_null>, <&rk806_slave_dvs2_null>,
+ <&rk806_slave_dvs3_null>;
+ spi-max-frequency = <1000000>;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_2v0_pldo_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ rk806_slave_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_slave_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_slave_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_cpu_big1_s0: dcdc-reg1 {
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big1_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big0_s0: dcdc-reg2 {
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big0_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg3 {
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_lit_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg4 {
+ regulator-name = "vcc_3v3_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vdd_cpu_big1_mem_s0: dcdc-reg5 {
+ regulator-name = "vdd_cpu_big1_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big1_s0>;
+ regulator-coupled-max-spread = <10000>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+
+ vdd_cpu_big0_mem_s0: dcdc-reg6 {
+ regulator-name = "vdd_cpu_big0_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big0_s0>;
+ regulator-coupled-max-spread = <10000>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s0: dcdc-reg7 {
+ regulator-name = "vcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_mem_s0: dcdc-reg8 {
+ regulator-name = "vdd_cpu_lit_mem_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_lit_s0>;
+ regulator-coupled-max-spread = <10000>;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-name = "vddq_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg10 {
+ regulator-name = "vdd_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_cam_s0: pldo-reg1 {
+ regulator-name = "vcc_1v8_cam_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd1v8_ddr_pll_s0: pldo-reg2 {
+ regulator-name = "avdd1v8_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_1v8_pll_s0: pldo-reg3 {
+ regulator-name = "vdd_1v8_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_sd_s0: pldo-reg4 {
+ regulator-name = "vcc_3v3_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_2v8_cam_s0: pldo-reg5 {
+ regulator-name = "vcc_2v8_cam_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-name = "pldo6_s3";
+ 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>;
+ };
+ };
+
+ vdd_0v75_pll_s0: nldo-reg1 {
+ regulator-name = "vdd_0v75_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-name = "vdd_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ slave_nldo3: nldo-reg3 {
+ regulator-name = "slave_nldo3";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd_1v2_cam_s0: nldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "avdd_1v2_cam_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd_1v2_s0: nldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "avdd_1v2_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+&u2phy2_host {
+ phy-supply = <&vcc5v0_host>;
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc5v0_host>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dwc3_0_role_switch: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_role_sw>;
+ };
+ };
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usbdp_phy0 {
+ mode-switch;
+ orientation-switch;
+ sbu1-dc-gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
+ sbu2-dc-gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbdp_phy0_orientation_switch: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_orien_sw>;
+ };
+
+ usbdp_phy0_dp_altmode_mux: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dp_altmode_mux>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts b/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts
index 467f69594089..812bba0aef1a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts
@@ -122,7 +122,7 @@
simple-audio-card,bitclock-master = <&masterdai>;
simple-audio-card,format = "i2s";
simple-audio-card,frame-master = <&masterdai>;
- simple-audio-card,hp-det-gpio = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
+ simple-audio-card,hp-det-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,name = "rockchip,es8388-codec";
simple-audio-card,pin-switches = "Headphones", "Speaker";
@@ -346,7 +346,7 @@
VCC-supply = <&vcc5v0_spk>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -356,7 +356,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_lcd0_n: vcc3v3-lcd0-n-regulator {
+ vcc3v3_lcd0_n: regulator-vcc3v3-lcd0-n {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
@@ -371,7 +371,7 @@
};
};
- vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator {
+ vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;
@@ -383,7 +383,7 @@
vin-supply = <&vcc_3v3_s3>;
};
- vcc5v0_spk: vcc5v0-spk-regulator {
+ vcc5v0_spk: regulator-vcc5v0-spk {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
@@ -398,7 +398,7 @@
};
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
index d8c50fdcca3b..4a3aa80f2226 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
@@ -5,6 +5,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include <dt-bindings/usb/pd.h>
#include "rk3588s.dtsi"
@@ -50,6 +51,17 @@
stdout-path = "serial2:1500000n8";
};
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "d";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
sdio_pwrseq: sdio-pwrseq {
compatible = "mmc-pwrseq-simple";
clock-names = "ext_clock";
@@ -62,7 +74,7 @@
sound {
compatible = "audio-graph-card";
- label = "rockchip,es8388-codec";
+ label = "rockchip,es8388";
widgets = "Microphone", "Mic Jack",
"Headphone", "Headphones";
routing = "LINPUT2", "Mic Jack",
@@ -71,7 +83,7 @@
dais = <&i2s0_8ch_p0>;
};
- vbus5v0_typec: vbus5v0-typec-regulator {
+ vbus5v0_typec: regulator-vbus5v0-typec {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
@@ -83,7 +95,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -94,7 +106,7 @@
};
/* Regulator is enabled whenever vcc_1v8_s0 is above 1.6v */
- vcc_3v3_s0: vcc-3v3-s0-regulator {
+ vcc_3v3_s0: regulator-vcc-3v3-s0 {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -108,7 +120,7 @@
};
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -117,7 +129,7 @@
regulator-name = "vcc5v0_sys";
};
- vcc5v0_usb: vcc5v0-usb-regulator {
+ vcc5v0_usb: regulator-vcc5v0-usb {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -127,7 +139,7 @@
vin-supply = <&vcc5v0_usbdcin>;
};
- vcc5v0_usbdcin: vcc5v0-usbdcin-regulator {
+ vcc5v0_usbdcin: regulator-vcc5v0-usbdcin {
compatible = "regulator-fixed";
regulator-always-on;
regulator-boot-on;
@@ -242,6 +254,34 @@
"", "", "", "";
};
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&hdmi0 {
+ pinctrl-0 = <&hdmim0_tx0_scl>, <&hdmim0_tx0_sda>,
+ <&hdmim0_tx0_hpd>, <&hdmim0_tx0_cec>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-0 = <&i2c0m2_xfer>;
pinctrl-names = "default";
@@ -377,7 +417,6 @@
assigned-clock-rates = <12288000>;
assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
AVDD-supply = <&vcc_3v3_s3>;
- clock-names = "mclk";
clocks = <&cru I2S0_8CH_MCLKOUT>;
DVDD-supply = <&vcc_1v8_s3>;
HPVDD-supply = <&vcc_3v3_s3>;
@@ -919,3 +958,18 @@
};
};
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
index dbddfc3bb464..ac48e7fd3923 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
@@ -76,7 +76,7 @@
};
};
- vcc3v3_pcie_wl: vcc3v3-pcie-wl-regulator {
+ vcc3v3_pcie_wl: regulator-vcc3v3-pcie-wl {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
@@ -89,7 +89,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -103,7 +103,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -112,7 +112,7 @@
regulator-max-microvolt = <5000000>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -122,7 +122,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vdd_3v3_sd: vdd-3v3-sd-regulator {
+ vdd_3v3_sd: regulator-vdd-3v3-sd {
compatible = "regulator-fixed";
regulator-name = "vdd_3v3_sd";
gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
@@ -283,6 +283,22 @@
reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_pcie_wl>;
status = "okay";
+
+ pcie@0,0 {
+ reg = <0x400000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ device_type = "pci";
+ bus-range = <0x40 0x4f>;
+
+ wifi: wifi@0,0 {
+ compatible = "pci14e4,449d";
+ reg = <0x410000 0 0 0 0>;
+ clocks = <&hym8563>;
+ clock-names = "lpo";
+ };
+ };
};
&pwm11 {
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi
new file mode 100644
index 000000000000..76a6e8e517e9
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6.dtsi
@@ -0,0 +1,812 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3588s.dtsi"
+
+/ {
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdmmc;
+ mmc1 = &sdhci;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 0>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-maskrom {
+ label = "Maskrom";
+ linux,code = <KEY_VENDOR>;
+ press-threshold-microvolt = <1800>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&key1_pin>;
+
+ button-user {
+ label = "User";
+ linux,code = <BTN_1>;
+ gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>;
+ debounce-interval = <50>;
+ };
+ };
+
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ sys_led: led-0 {
+ label = "sys_led";
+ gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ pinctrl-names = "default";
+ pinctrl-0 = <&sys_led_pin>;
+ };
+
+ wan_led: led-1 {
+ label = "wan_led";
+ gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wan_led_pin>;
+ };
+
+ lan1_led: led-2 {
+ label = "lan1_led";
+ gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lan1_led_pin>;
+ };
+
+ lan2_led: led-3 {
+ gpios = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&lan2_led_pin>;
+ };
+ };
+
+ 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>;
+ };
+
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc_3v3_s0: regulator-vcc-3v3-s0 {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc_3v3_s0";
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_s0_pwr>;
+ regulator-name = "vcc_3v3_sd_s0";
+ regulator-boot-on;
+ regulator-max-microvolt = <3000000>;
+ regulator-min-microvolt = <3000000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc_3v3_pcie20: regulator-vcc3v3-pcie20 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_pcie20";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc5v0_usb: regulator-vcc5v0-usb {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_usb_otg0: regulator-vcc5v0-usb-otg0 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec5v_pwren>;
+ regulator-name = "vcc5v0_usb_otg0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_usb>;
+ };
+
+ vcc5v0_host_20: regulator-vcc5v0-host-20 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_host20_en>;
+ regulator-name = "vcc5v0_host_20";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_usb>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gmac1 {
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-rxid";
+ pinctrl-0 = <&gmac1_miim
+ &gmac1_tx_bus2
+ &gmac1_rx_bus2
+ &gmac1_rgmii_clk
+ &gmac1_rgmii_bus>;
+ pinctrl-names = "default";
+ tx_delay = <0x42>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m2_xfer>;
+ status = "okay";
+
+ vdd_cpu_big0_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_s0: regulator@43 {
+ compatible = "rockchip,rk8603", "rockchip,rk8602";
+ reg = <0x43>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ vdd_npu_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_npu_s0";
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <2300>;
+ regulator-boot-on;
+ regulator-always-on;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c6 {
+ clock-frequency = <200000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6m0_xfer>;
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0x1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtl8211f_rst>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie2x1l1 {
+ reset-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_pcie20>;
+ status = "okay";
+};
+
+&pcie2x1l2 {
+ reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_pcie20>;
+ status = "okay";
+};
+
+&pinctrl {
+ gpio-key {
+ key1_pin: key1-pin {
+ rockchip,pins = <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ gpio-leds {
+ sys_led_pin: sys-led-pin {
+ rockchip,pins =
+ <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wan_led_pin: wan-led-pin {
+ rockchip,pins =
+ <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ lan1_led_pin: lan1-led-pin {
+ rockchip,pins =
+ <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ lan2_led_pin: lan2-led-pin {
+ rockchip,pins =
+ <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ hym8563 {
+ rtc_int: rtc-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ sdmmc {
+ sd_s0_pwr: sd-s0-pwr {
+ rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ usb {
+ typec5v_pwren: typec5v-pwren {
+ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc5v0_host20_en: vcc5v0-host20-en {
+ rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ rtl8211f {
+ rtl8211f_rst: rtl8211f-rst {
+ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&saradc {
+ vref-supply = <&avcc_1v8_s0>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ no-sdio;
+ no-sd;
+ non-removable;
+ mmc-hs200-1_8v;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ max-frequency = <150000000>;
+ no-mmc;
+ no-sdio;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_sd_s0>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&spi2 {
+ status = "okay";
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+ num-cs = <1>;
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ spi-max-frequency = <1000000>;
+ reg = <0x0>;
+
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+
+ system-power-controller;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 {
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_gpu_s0";
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_cpu_lit_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_log_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_vdenc_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_ddr_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vdd2_ddr_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_2v0_pldo_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc_3v3_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vddq_ddr_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg10 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc_1v8_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "avcc_1v8_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_1v8_s0: pldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc_1v8_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avdd_1v2_s0: pldo-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "avdd_1v2_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avcc_3v3_s0: pldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "avcc_3v3_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vccio_sd_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "pldo6_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdd_0v75_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ avdd_ddr_pll_s0: nldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "avdd_ddr_pll_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "avdd_0v75_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ avdd_0v85_s0: nldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "avdd_0v85_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v75_s0: nldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdd_0v75_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ phy-supply = <&vcc5v0_host_20>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts
index 497bbb57071f..ccc5e4627517 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6c.dts
@@ -2,7 +2,7 @@
/dts-v1/;
-#include "rk3588s-nanopi-r6s.dts"
+#include "rk3588s-nanopi-r6.dtsi"
/ {
model = "FriendlyElec NanoPi R6C";
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts
index 4fa644ae510c..9c3e0b0daaac 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-nanopi-r6s.dts
@@ -2,763 +2,13 @@
/dts-v1/;
-#include <dt-bindings/pinctrl/rockchip.h>
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-#include "rk3588s.dtsi"
+#include "rk3588s-nanopi-r6.dtsi"
/ {
model = "FriendlyElec NanoPi R6S";
compatible = "friendlyarm,nanopi-r6s", "rockchip,rk3588s";
-
- aliases {
- ethernet0 = &gmac1;
- mmc0 = &sdmmc;
- mmc1 = &sdhci;
- };
-
- chosen {
- stdout-path = "serial2:1500000n8";
- };
-
- adc-keys {
- compatible = "adc-keys";
- io-channels = <&saradc 0>;
- io-channel-names = "buttons";
- keyup-threshold-microvolt = <1800000>;
- poll-interval = <100>;
-
- button-maskrom {
- label = "Maskrom";
- linux,code = <KEY_VENDOR>;
- press-threshold-microvolt = <1800>;
- };
- };
-
- gpio-keys {
- compatible = "gpio-keys";
- pinctrl-names = "default";
- pinctrl-0 = <&key1_pin>;
-
- button-user {
- label = "User";
- linux,code = <BTN_1>;
- gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>;
- debounce-interval = <50>;
- };
- };
-
- leds {
- compatible = "gpio-leds";
-
- sys_led: led-0 {
- label = "sys_led";
- gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "heartbeat";
- pinctrl-names = "default";
- pinctrl-0 = <&sys_led_pin>;
- };
-
- wan_led: led-1 {
- label = "wan_led";
- gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&wan_led_pin>;
- };
-
- lan1_led: led-2 {
- label = "lan1_led";
- gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&lan1_led_pin>;
- };
-
- lan2_led: led-3 {
- label = "lan2_led";
- gpios = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&lan2_led_pin>;
- };
- };
-
- 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>;
- };
-
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vcc_1v1_nldo_s3";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- vin-supply = <&vcc5v0_sys>;
- };
-
- vcc_3v3_s0: vcc-3v3-s0-regulator {
- compatible = "regulator-fixed";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc_3v3_s0";
- vin-supply = <&vcc_3v3_s3>;
- };
-
- vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&sd_s0_pwr>;
- regulator-name = "vcc_3v3_sd_s0";
- regulator-boot-on;
- regulator-max-microvolt = <3000000>;
- regulator-min-microvolt = <3000000>;
- vin-supply = <&vcc_3v3_s3>;
- };
-
- vcc_3v3_pcie20: vcc3v3-pcie20-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vcc_3v3_pcie20";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- vin-supply = <&vcc_3v3_s3>;
- };
-
- 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 = <&vcc5v0_sys>;
- };
-
- vcc5v0_usb_otg0: vcc5v0-usb-otg0-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&typec5v_pwren>;
- regulator-name = "vcc5v0_usb_otg0";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- vin-supply = <&vcc5v0_usb>;
- };
-
- vcc5v0_host_20: vcc5v0-host-20-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&vcc5v0_host20_en>;
- regulator-name = "vcc5v0_host_20";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- vin-supply = <&vcc5v0_usb>;
- };
-};
-
-&combphy0_ps {
- status = "okay";
-};
-
-&combphy2_psu {
- status = "okay";
-};
-
-&cpu_b0 {
- cpu-supply = <&vdd_cpu_big0_s0>;
-};
-
-&cpu_b1 {
- cpu-supply = <&vdd_cpu_big0_s0>;
-};
-
-&cpu_b2 {
- cpu-supply = <&vdd_cpu_big1_s0>;
-};
-
-&cpu_b3 {
- cpu-supply = <&vdd_cpu_big1_s0>;
-};
-
-&cpu_l0 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&cpu_l1 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&cpu_l2 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&cpu_l3 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&gmac1 {
- clock_in_out = "output";
- phy-handle = <&rgmii_phy1>;
- phy-mode = "rgmii-rxid";
- pinctrl-0 = <&gmac1_miim
- &gmac1_tx_bus2
- &gmac1_rx_bus2
- &gmac1_rgmii_clk
- &gmac1_rgmii_bus>;
- pinctrl-names = "default";
- tx_delay = <0x42>;
- status = "okay";
-};
-
-&i2c0 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0m2_xfer>;
- status = "okay";
-
- vdd_cpu_big0_s0: regulator@42 {
- compatible = "rockchip,rk8602";
- reg = <0x42>;
- fcs,suspend-voltage-selector = <1>;
- regulator-name = "vdd_cpu_big0_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <1050000>;
- regulator-ramp-delay = <2300>;
- vin-supply = <&vcc5v0_sys>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_cpu_big1_s0: regulator@43 {
- compatible = "rockchip,rk8603", "rockchip,rk8602";
- reg = <0x43>;
- fcs,suspend-voltage-selector = <1>;
- regulator-name = "vdd_cpu_big1_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <1050000>;
- regulator-ramp-delay = <2300>;
- vin-supply = <&vcc5v0_sys>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-};
-
-&i2c2 {
- status = "okay";
-
- vdd_npu_s0: regulator@42 {
- compatible = "rockchip,rk8602";
- reg = <0x42>;
- fcs,suspend-voltage-selector = <1>;
- regulator-name = "vdd_npu_s0";
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <2300>;
- regulator-boot-on;
- regulator-always-on;
- vin-supply = <&vcc5v0_sys>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-};
-
-&i2c6 {
- clock-frequency = <200000>;
- pinctrl-names = "default";
- pinctrl-0 = <&i2c6m0_xfer>;
- status = "okay";
-
- hym8563: rtc@51 {
- compatible = "haoyu,hym8563";
- reg = <0x51>;
- #clock-cells = <0>;
- clock-output-names = "hym8563";
- pinctrl-names = "default";
- pinctrl-0 = <&rtc_int>;
- interrupt-parent = <&gpio0>;
- interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
- wakeup-source;
- };
-};
-
-&mdio1 {
- rgmii_phy1: ethernet-phy@1 {
- compatible = "ethernet-phy-id001c.c916";
- reg = <0x1>;
- pinctrl-names = "default";
- pinctrl-0 = <&rtl8211f_rst>;
- reset-assert-us = <20000>;
- reset-deassert-us = <100000>;
- reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
- };
-};
-
-&pcie2x1l1 {
- reset-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>;
- vpcie3v3-supply = <&vcc_3v3_pcie20>;
- status = "okay";
-};
-
-&pcie2x1l2 {
- reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
- vpcie3v3-supply = <&vcc_3v3_pcie20>;
- status = "okay";
-};
-
-&pinctrl {
- gpio-key {
- key1_pin: key1-pin {
- rockchip,pins = <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-
- gpio-leds {
- sys_led_pin: sys-led-pin {
- rockchip,pins =
- <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- wan_led_pin: wan-led-pin {
- rockchip,pins =
- <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- lan1_led_pin: lan1-led-pin {
- rockchip,pins =
- <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- lan2_led_pin: lan2-led-pin {
- rockchip,pins =
- <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- hym8563 {
- rtc_int: rtc-int {
- rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-
- sdmmc {
- sd_s0_pwr: sd-s0-pwr {
- rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-
- usb {
- typec5v_pwren: typec5v-pwren {
- rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- vcc5v0_host20_en: vcc5v0-host20-en {
- rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- rtl8211f {
- rtl8211f_rst: rtl8211f-rst {
- rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-};
-
-&saradc {
- vref-supply = <&avcc_1v8_s0>;
- status = "okay";
-};
-
-&sdhci {
- bus-width = <8>;
- no-sdio;
- no-sd;
- non-removable;
- mmc-hs200-1_8v;
- status = "okay";
-};
-
-&sdmmc {
- bus-width = <4>;
- cap-sd-highspeed;
- disable-wp;
- max-frequency = <150000000>;
- no-mmc;
- no-sdio;
- sd-uhs-sdr104;
- vmmc-supply = <&vcc_3v3_sd_s0>;
- vqmmc-supply = <&vccio_sd_s0>;
- status = "okay";
-};
-
-&spi2 {
- status = "okay";
- assigned-clocks = <&cru CLK_SPI2>;
- assigned-clock-rates = <200000000>;
- pinctrl-names = "default";
- pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
- num-cs = <1>;
-
- pmic@0 {
- compatible = "rockchip,rk806";
- spi-max-frequency = <1000000>;
- reg = <0x0>;
-
- interrupt-parent = <&gpio0>;
- interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
- <&rk806_dvs2_null>, <&rk806_dvs3_null>;
-
- system-power-controller;
-
- vcc1-supply = <&vcc5v0_sys>;
- vcc2-supply = <&vcc5v0_sys>;
- vcc3-supply = <&vcc5v0_sys>;
- vcc4-supply = <&vcc5v0_sys>;
- vcc5-supply = <&vcc5v0_sys>;
- vcc6-supply = <&vcc5v0_sys>;
- vcc7-supply = <&vcc5v0_sys>;
- vcc8-supply = <&vcc5v0_sys>;
- vcc9-supply = <&vcc5v0_sys>;
- vcc10-supply = <&vcc5v0_sys>;
- vcc11-supply = <&vcc_2v0_pldo_s3>;
- vcc12-supply = <&vcc5v0_sys>;
- vcc13-supply = <&vcc_1v1_nldo_s3>;
- vcc14-supply = <&vcc_1v1_nldo_s3>;
- vcca-supply = <&vcc5v0_sys>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- rk806_dvs1_null: dvs1-null-pins {
- pins = "gpio_pwrctrl1";
- function = "pin_fun0";
- };
-
- rk806_dvs2_null: dvs2-null-pins {
- pins = "gpio_pwrctrl2";
- function = "pin_fun0";
- };
-
- rk806_dvs3_null: dvs3-null-pins {
- pins = "gpio_pwrctrl3";
- function = "pin_fun0";
- };
-
- regulators {
- vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 {
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "vdd_gpu_s0";
- regulator-enable-ramp-delay = <400>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "vdd_cpu_lit_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_log_s0: dcdc-reg3 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <675000>;
- regulator-max-microvolt = <750000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "vdd_log_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <750000>;
- };
- };
-
- vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "vdd_vdenc_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_ddr_s0: dcdc-reg5 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <675000>;
- regulator-max-microvolt = <900000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "vdd_ddr_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <850000>;
- };
- };
-
- vdd2_ddr_s3: dcdc-reg6 {
- regulator-always-on;
- regulator-boot-on;
- regulator-name = "vdd2_ddr_s3";
-
- regulator-state-mem {
- regulator-on-in-suspend;
- };
- };
-
- vcc_2v0_pldo_s3: dcdc-reg7 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <2000000>;
- regulator-max-microvolt = <2000000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "vdd_2v0_pldo_s3";
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <2000000>;
- };
- };
-
- vcc_3v3_s3: dcdc-reg8 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "vcc_3v3_s3";
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vddq_ddr_s0: dcdc-reg9 {
- regulator-always-on;
- regulator-boot-on;
- regulator-name = "vddq_ddr_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vcc_1v8_s3: dcdc-reg10 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "vcc_1v8_s3";
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- avcc_1v8_s0: pldo-reg1 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "avcc_1v8_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- vcc_1v8_s0: pldo-reg2 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "vcc_1v8_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- avdd_1v2_s0: pldo-reg3 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-name = "avdd_1v2_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- avcc_3v3_s0: pldo-reg4 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "avcc_3v3_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vccio_sd_s0: pldo-reg5 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-ramp-delay = <12500>;
- regulator-name = "vccio_sd_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- pldo6_s3: pldo-reg6 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-name = "pldo6_s3";
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- vdd_0v75_s3: nldo-reg1 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <750000>;
- regulator-name = "vdd_0v75_s3";
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <750000>;
- };
- };
-
- avdd_ddr_pll_s0: nldo-reg2 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <850000>;
- regulator-name = "avdd_ddr_pll_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <850000>;
- };
- };
-
- avdd_0v75_s0: nldo-reg3 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <750000>;
- regulator-name = "avdd_0v75_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- avdd_0v85_s0: nldo-reg4 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <850000>;
- regulator-name = "avdd_0v85_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_0v75_s0: nldo-reg5 {
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <750000>;
- regulator-name = "vdd_0v75_s0";
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
- };
- };
-};
-
-&tsadc {
- status = "okay";
-};
-
-&u2phy2 {
- status = "okay";
-};
-
-&u2phy2_host {
- phy-supply = <&vcc5v0_host_20>;
- status = "okay";
-};
-
-&uart2 {
- pinctrl-0 = <&uart2m0_xfer>;
- status = "okay";
-};
-
-&usb_host0_ehci {
- status = "okay";
};
-&usb_host0_ohci {
- status = "okay";
+&lan2_led {
+ label = "lan2_led";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts
index 63d91236ba9f..8f034c6d494c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts
@@ -5,6 +5,7 @@
#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 <dt-bindings/usb/pd.h>
#include "rk3588s.dtsi"
@@ -22,6 +23,17 @@
stdout-path = "serial2:1500000n8";
};
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -236,6 +248,26 @@
status = "okay";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -901,3 +933,18 @@
};
};
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
index feea6b20a6bf..ad6d04793b0a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
@@ -2,85 +2,13 @@
/dts-v1/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/leds/common.h>
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/rockchip.h>
-#include <dt-bindings/usb/pd.h>
-#include "rk3588s.dtsi"
+#include "rk3588s-orangepi-5.dtsi"
/ {
model = "Xunlong Orange Pi 5";
compatible = "xunlong,orangepi-5", "rockchip,rk3588s";
- aliases {
- ethernet0 = &gmac1;
- mmc0 = &sdmmc;
- };
-
- chosen {
- stdout-path = "serial2:1500000n8";
- };
-
- adc-keys {
- compatible = "adc-keys";
- io-channels = <&saradc 1>;
- io-channel-names = "buttons";
- keyup-threshold-microvolt = <1800000>;
- poll-interval = <100>;
-
- button-recovery {
- label = "Recovery";
- linux,code = <KEY_VENDOR>;
- press-threshold-microvolt = <1800>;
- };
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&leds_gpio>;
-
- led-1 {
- gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>;
- label = "status_led";
- linux,default-trigger = "heartbeat";
- };
- };
-
- vbus_typec: vbus-typec-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&typec5v_pwren>;
- regulator-name = "vbus_typec";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- vin-supply = <&vcc5v0_sys>;
- };
-
- 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>;
- };
-
- vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator {
- compatible = "regulator-fixed";
- enable-active-low;
- gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>;
- regulator-name = "vcc_3v3_sd_s0";
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- vin-supply = <&vcc_3v3_s3>;
- };
-
- vcc3v3_pcie20: vcc3v3-pcie20-regulator {
+ vcc3v3_pcie20: regulator-vcc3v3-pcie20 {
compatible = "regulator-fixed";
enable-active-high;
gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
@@ -93,674 +21,12 @@
};
};
-&combphy0_ps {
- status = "okay";
-};
-
-&combphy2_psu {
- status = "okay";
-};
-
-&cpu_b0 {
- cpu-supply = <&vdd_cpu_big0_s0>;
-};
-
-&cpu_b1 {
- cpu-supply = <&vdd_cpu_big0_s0>;
-};
-
-&cpu_b2 {
- cpu-supply = <&vdd_cpu_big1_s0>;
-};
-
-&cpu_b3 {
- cpu-supply = <&vdd_cpu_big1_s0>;
-};
-
-&cpu_l0 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&cpu_l1 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&cpu_l2 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&cpu_l3 {
- cpu-supply = <&vdd_cpu_lit_s0>;
-};
-
-&gmac1 {
- clock_in_out = "output";
- phy-handle = <&rgmii_phy1>;
- phy-mode = "rgmii-rxid";
- pinctrl-0 = <&gmac1_miim
- &gmac1_tx_bus2
- &gmac1_rx_bus2
- &gmac1_rgmii_clk
- &gmac1_rgmii_bus>;
- pinctrl-names = "default";
- tx_delay = <0x42>;
- status = "okay";
-};
-
-&gpu {
- mali-supply = <&vdd_gpu_s0>;
- status = "okay";
-};
-
-&i2c0 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0m2_xfer>;
- status = "okay";
-
- vdd_cpu_big0_s0: regulator@42 {
- compatible = "rockchip,rk8602";
- reg = <0x42>;
- fcs,suspend-voltage-selector = <1>;
- regulator-name = "vdd_cpu_big0_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <1050000>;
- regulator-ramp-delay = <2300>;
- vin-supply = <&vcc5v0_sys>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_cpu_big1_s0: regulator@43 {
- compatible = "rockchip,rk8603", "rockchip,rk8602";
- reg = <0x43>;
- fcs,suspend-voltage-selector = <1>;
- regulator-name = "vdd_cpu_big1_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <1050000>;
- regulator-ramp-delay = <2300>;
- vin-supply = <&vcc5v0_sys>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-};
-
-&i2c2 {
- status = "okay";
-
- vdd_npu_s0: regulator@42 {
- compatible = "rockchip,rk8602";
- reg = <0x42>;
- fcs,suspend-voltage-selector = <1>;
- regulator-name = "vdd_npu_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <2300>;
- vin-supply = <&vcc5v0_sys>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-};
-
-&i2c6 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c6m3_xfer>;
- status = "okay";
-
- usbc0: usb-typec@22 {
- compatible = "fcs,fusb302";
- reg = <0x22>;
- interrupt-parent = <&gpio0>;
- interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&usbc0_int>;
- vbus-supply = <&vbus_typec>;
- status = "okay";
-
- usb_con: connector {
- compatible = "usb-c-connector";
- label = "USB-C";
- data-role = "dual";
- op-sink-microwatt = <1000000>;
- power-role = "dual";
- sink-pdos =
- <PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
- source-pdos =
- <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- try-power-role = "source";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- usbc0_hs: endpoint {
- remote-endpoint = <&usb_host0_xhci_drd_sw>;
- };
- };
-
- port@1 {
- reg = <1>;
- usbc0_ss: endpoint {
- remote-endpoint = <&usbdp_phy0_typec_ss>;
- };
- };
-
- port@2 {
- reg = <2>;
- usbc0_sbu: endpoint {
- remote-endpoint = <&usbdp_phy0_typec_sbu>;
- };
- };
- };
- };
- };
-
- hym8563: rtc@51 {
- compatible = "haoyu,hym8563";
- reg = <0x51>;
- #clock-cells = <0>;
- clock-output-names = "hym8563";
- pinctrl-names = "default";
- pinctrl-0 = <&hym8563_int>;
- interrupt-parent = <&gpio0>;
- interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
- wakeup-source;
- };
-};
-
-&mdio1 {
- rgmii_phy1: ethernet-phy@1 {
- compatible = "ethernet-phy-ieee802.3-c22";
- reg = <0x1>;
- reset-assert-us = <20000>;
- reset-deassert-us = <100000>;
- reset-gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>;
- };
-};
-
&pcie2x1l2 {
reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_pcie20>;
status = "okay";
};
-&pinctrl {
- gpio-func {
- leds_gpio: leds-gpio {
- rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- hym8563 {
- hym8563_int: hym8563-int {
- rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- usb-typec {
- usbc0_int: usbc0-int {
- rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
- };
-
- typec5v_pwren: typec5v-pwren {
- rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-};
-
-&saradc {
- vref-supply = <&avcc_1v8_s0>;
- status = "okay";
-};
-
-&sdmmc {
- bus-width = <4>;
- cap-sd-highspeed;
- disable-wp;
- max-frequency = <150000000>;
- no-mmc;
- no-sdio;
- sd-uhs-sdr104;
- vmmc-supply = <&vcc_3v3_sd_s0>;
- vqmmc-supply = <&vccio_sd_s0>;
- status = "okay";
-};
-
&sfc {
- pinctrl-names = "default";
- pinctrl-0 = <&fspim0_pins>;
- status = "okay";
-
- flash@0 {
- compatible = "jedec,spi-nor";
- reg = <0x0>;
- spi-max-frequency = <100000000>;
- spi-rx-bus-width = <4>;
- spi-tx-bus-width = <1>;
- };
-};
-
-&spi2 {
- status = "okay";
- assigned-clocks = <&cru CLK_SPI2>;
- assigned-clock-rates = <200000000>;
- num-cs = <1>;
- pinctrl-names = "default";
- pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
-
- pmic@0 {
- compatible = "rockchip,rk806";
- reg = <0x0>;
- interrupt-parent = <&gpio0>;
- interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
- <&rk806_dvs2_null>, <&rk806_dvs3_null>;
- spi-max-frequency = <1000000>;
- system-power-controller;
-
- vcc1-supply = <&vcc5v0_sys>;
- vcc2-supply = <&vcc5v0_sys>;
- vcc3-supply = <&vcc5v0_sys>;
- vcc4-supply = <&vcc5v0_sys>;
- vcc5-supply = <&vcc5v0_sys>;
- vcc6-supply = <&vcc5v0_sys>;
- vcc7-supply = <&vcc5v0_sys>;
- vcc8-supply = <&vcc5v0_sys>;
- vcc9-supply = <&vcc5v0_sys>;
- vcc10-supply = <&vcc5v0_sys>;
- vcc11-supply = <&vcc_2v0_pldo_s3>;
- vcc12-supply = <&vcc5v0_sys>;
- vcc13-supply = <&vcc_1v1_nldo_s3>;
- vcc14-supply = <&vcc_1v1_nldo_s3>;
- vcca-supply = <&vcc5v0_sys>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- rk806_dvs1_null: dvs1-null-pins {
- pins = "gpio_pwrctrl1";
- function = "pin_fun0";
- };
-
- rk806_dvs2_null: dvs2-null-pins {
- pins = "gpio_pwrctrl2";
- function = "pin_fun0";
- };
-
- rk806_dvs3_null: dvs3-null-pins {
- pins = "gpio_pwrctrl3";
- function = "pin_fun0";
- };
-
- regulators {
- vdd_gpu_s0: dcdc-reg1 {
- regulator-name = "vdd_gpu_s0";
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <12500>;
- regulator-enable-ramp-delay = <400>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_cpu_lit_s0: dcdc-reg2 {
- regulator-name = "vdd_cpu_lit_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_log_s0: dcdc-reg3 {
- regulator-name = "vdd_log_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <675000>;
- regulator-max-microvolt = <750000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <750000>;
- };
- };
-
- vdd_vdenc_s0: dcdc-reg4 {
- regulator-name = "vdd_vdenc_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <550000>;
- regulator-max-microvolt = <950000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_ddr_s0: dcdc-reg5 {
- regulator-name = "vdd_ddr_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <675000>;
- regulator-max-microvolt = <900000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <850000>;
- };
- };
-
- vcc_1v1_nldo_s3: vdd2_ddr_s3: dcdc-reg6 {
- regulator-name = "vdd2_ddr_s3";
- regulator-always-on;
- regulator-boot-on;
- regulator-max-microvolt = <1100000>;
- regulator-min-microvolt = <1100000>;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- };
- };
-
- vcc_2v0_pldo_s3: dcdc-reg7 {
- regulator-name = "vdd_2v0_pldo_s3";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <2000000>;
- regulator-max-microvolt = <2000000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <2000000>;
- };
- };
-
- vcc_3v3_s3: dcdc-reg8 {
- regulator-name = "vcc_3v3_s3";
- 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>;
- };
- };
-
- vddq_ddr_s0: dcdc-reg9 {
- regulator-name = "vddq_ddr_s0";
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vcc_1v8_s3: dcdc-reg10 {
- regulator-name = "vcc_1v8_s3";
- 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>;
- };
- };
-
- avcc_1v8_s0: pldo-reg1 {
- regulator-name = "avcc_1v8_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vcc_1v8_s0: pldo-reg2 {
- regulator-name = "vcc_1v8_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- avdd_1v2_s0: pldo-reg3 {
- regulator-name = "avdd_1v2_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vcc_3v3_s0: pldo-reg4 {
- regulator-name = "vcc_3v3_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vccio_sd_s0: pldo-reg5 {
- regulator-name = "vccio_sd_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-ramp-delay = <12500>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- pldo6_s3: pldo-reg6 {
- regulator-name = "pldo6_s3";
- 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>;
- };
- };
-
- vdd_0v75_s3: nldo-reg1 {
- regulator-name = "vdd_0v75_s3";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <750000>;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <750000>;
- };
- };
-
- vdd_ddr_pll_s0: nldo-reg2 {
- regulator-name = "vdd_ddr_pll_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <850000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <850000>;
- };
- };
-
- avdd_0v75_s0: nldo-reg3 {
- regulator-name = "avdd_0v75_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <750000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_0v85_s0: nldo-reg4 {
- regulator-name = "vdd_0v85_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <850000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
- vdd_0v75_s0: nldo-reg5 {
- regulator-name = "vdd_0v75_s0";
- regulator-always-on;
- regulator-boot-on;
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <750000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
- };
- };
-};
-
-&tsadc {
- status = "okay";
-};
-
-&u2phy0 {
- status = "okay";
-};
-
-&u2phy0_otg {
- status = "okay";
-};
-
-&u2phy2 {
- status = "okay";
-};
-
-&u2phy2_host {
- status = "okay";
-};
-
-&u2phy3 {
- status = "okay";
-};
-
-&u2phy3_host {
- status = "okay";
-};
-
-&uart2 {
- pinctrl-0 = <&uart2m0_xfer>;
- status = "okay";
-};
-
-&usbdp_phy0 {
- mode-switch;
- orientation-switch;
- sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
- sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
- status = "okay";
-
- port {
- #address-cells = <1>;
- #size-cells = <0>;
-
- usbdp_phy0_typec_ss: endpoint@0 {
- reg = <0>;
- remote-endpoint = <&usbc0_ss>;
- };
-
- usbdp_phy0_typec_sbu: endpoint@1 {
- reg = <1>;
- remote-endpoint = <&usbc0_sbu>;
- };
- };
-};
-
-&usb_host0_ehci {
- status = "okay";
-};
-
-&usb_host0_ohci {
- status = "okay";
-};
-
-&usb_host0_xhci {
- dr_mode = "otg";
- usb-role-switch;
- status = "okay";
-
- port {
- usb_host0_xhci_drd_sw: endpoint {
- remote-endpoint = <&usbc0_hs>;
- };
- };
-};
-
-&usb_host1_ehci {
- status = "okay";
-};
-
-&usb_host1_ohci {
- status = "okay";
-};
-
-&usb_host2_xhci {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
new file mode 100644
index 000000000000..d86aeacca238
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
@@ -0,0 +1,866 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include <dt-bindings/usb/pd.h>
+#include "rk3588s.dtsi"
+
+/ {
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-recovery {
+ label = "Recovery";
+ linux,code = <KEY_VENDOR>;
+ press-threshold-microvolt = <1800>;
+ };
+ };
+
+ analog-sound {
+ compatible = "simple-audio-card";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_detect>;
+ simple-audio-card,name = "rockchip,es8388";
+ simple-audio-card,bitclock-master = <&masterdai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&masterdai>;
+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,pin-switches = "Headphones";
+ simple-audio-card,routing =
+ "Headphones", "LOUT1",
+ "Headphones", "ROUT1",
+ "LINPUT1", "Microphone Jack",
+ "RINPUT1", "Microphone Jack",
+ "LINPUT2", "Onboard Microphone",
+ "RINPUT2", "Onboard Microphone";
+ simple-audio-card,widgets =
+ "Microphone", "Microphone Jack",
+ "Microphone", "Onboard Microphone",
+ "Headphone", "Headphones";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+
+ masterdai: simple-audio-card,codec {
+ sound-dai = <&es8388>;
+ system-clock-frequency = <12288000>;
+ };
+ };
+
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
+ pwm-leds {
+ compatible = "pwm-leds";
+
+ led {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ linux,default-trigger = "heartbeat";
+ max-brightness = <255>;
+ pwms = <&pwm0 0 25000 0>;
+ };
+ };
+
+ vbus_typec: regulator-vbus-typec {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec5v_pwren>;
+ regulator-name = "vbus_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ 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>;
+ };
+
+ vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
+ compatible = "regulator-fixed";
+ gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>;
+ regulator-name = "vcc_3v3_sd_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gmac1 {
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-rxid";
+ pinctrl-0 = <&gmac1_miim
+ &gmac1_tx_bus2
+ &gmac1_rx_bus2
+ &gmac1_rgmii_clk
+ &gmac1_rgmii_bus>;
+ pinctrl-names = "default";
+ tx_delay = <0x42>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m2_xfer>;
+ status = "okay";
+
+ vdd_cpu_big0_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_s0: regulator@43 {
+ compatible = "rockchip,rk8603", "rockchip,rk8602";
+ reg = <0x43>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ vdd_npu_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_npu_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc5v0_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6m3_xfer>;
+ status = "okay";
+
+ es8388: audio-codec@10 {
+ compatible = "everest,es8388";
+ reg = <0x10>;
+ clocks = <&cru I2S1_8CH_MCLKOUT>;
+ AVDD-supply = <&vcc_3v3_s0>;
+ DVDD-supply = <&vcc_1v8_s0>;
+ HPVDD-supply = <&vcc_3v3_s0>;
+ PVDD-supply = <&vcc_3v3_s0>;
+ assigned-clocks = <&cru I2S1_8CH_MCLKOUT>;
+ assigned-clock-rates = <12288000>;
+ #sound-dai-cells = <0>;
+ };
+
+ usbc0: usb-typec@22 {
+ compatible = "fcs,fusb302";
+ reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbc0_int>;
+ vbus-supply = <&vbus_typec>;
+ status = "okay";
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ op-sink-microwatt = <1000000>;
+ power-role = "dual";
+ sink-pdos =
+ <PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
+ source-pdos =
+ <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+ try-power-role = "source";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usbc0_hs: endpoint {
+ remote-endpoint = <&usb_host0_xhci_drd_sw>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ usbc0_ss: endpoint {
+ remote-endpoint = <&usbdp_phy0_typec_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ usbc0_sbu: endpoint {
+ remote-endpoint = <&usbdp_phy0_typec_sbu>;
+ };
+ };
+ };
+ };
+ };
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "hym8563";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+ };
+};
+
+&i2s1_8ch {
+ rockchip,i2s-tx-route = <3 2 1 0>;
+ rockchip,i2s-rx-route = <1 3 2 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s1m0_sclk
+ &i2s1m0_mclk
+ &i2s1m0_lrck
+ &i2s1m0_sdi1
+ &i2s1m0_sdo3>;
+ status = "okay";
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pinctrl {
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sound {
+ hp_detect: hp-detect {
+ rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb-typec {
+ usbc0_int: usbc0-int {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ typec5v_pwren: typec5v-pwren {
+ rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm0 {
+ pinctrl-0 = <&pwm0m2_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&avcc_1v8_s0>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ no-sdio;
+ no-sd;
+ non-removable;
+ max-frequency = <200000000>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ status = "disabled";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ max-frequency = <150000000>;
+ no-mmc;
+ no-sdio;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_sd_s0>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&sfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fspim0_pins>;
+ status = "disabled";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <100000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&spi2 {
+ status = "okay";
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ reg = <0x0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ spi-max-frequency = <1000000>;
+ system-power-controller;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc5v0_sys>;
+ vcc6-supply = <&vcc5v0_sys>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc5v0_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+ vcc10-supply = <&vcc5v0_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc5v0_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc5v0_sys>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: dcdc-reg1 {
+ regulator-name = "vdd_gpu_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg2 {
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_log_s0: dcdc-reg3 {
+ regulator-name = "vdd_log_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: dcdc-reg4 {
+ regulator-name = "vdd_vdenc_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg5 {
+ regulator-name = "vdd_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vcc_1v1_nldo_s3: vdd2_ddr_s3: dcdc-reg6 {
+ regulator-name = "vdd2_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-max-microvolt = <1100000>;
+ regulator-min-microvolt = <1100000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-name = "vdd_2v0_pldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg8 {
+ regulator-name = "vcc_3v3_s3";
+ 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>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-name = "vddq_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg10 {
+ regulator-name = "vcc_1v8_s3";
+ 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>;
+ };
+ };
+
+ avcc_1v8_s0: pldo-reg1 {
+ regulator-name = "avcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s0: pldo-reg2 {
+ regulator-name = "vcc_1v8_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ avdd_1v2_s0: pldo-reg3 {
+ regulator-name = "avdd_1v2_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3_s0: pldo-reg4 {
+ regulator-name = "vcc_3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-name = "vccio_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-name = "pldo6_s3";
+ 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>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-name = "vdd_0v75_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_ddr_pll_s0: nldo-reg2 {
+ regulator-name = "vdd_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ avdd_0v75_s0: nldo-reg3 {
+ regulator-name = "avdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v85_s0: nldo-reg4 {
+ regulator-name = "vdd_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v75_s0: nldo-reg5 {
+ regulator-name = "vdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&usbdp_phy0 {
+ mode-switch;
+ orientation-switch;
+ sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbdp_phy0_typec_ss: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_ss>;
+ };
+
+ usbdp_phy0_typec_sbu: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&usbc0_sbu>;
+ };
+ };
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ dr_mode = "otg";
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ usb_host0_xhci_drd_sw: endpoint {
+ remote-endpoint = <&usbc0_hs>;
+ };
+ };
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usb_host2_xhci {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
new file mode 100644
index 000000000000..d21ec320d295
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3588s-orangepi-5.dtsi"
+
+/ {
+ model = "Xunlong Orange Pi 5B";
+ compatible = "xunlong,orangepi-5b", "rockchip,rk3588s";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc;
+ };
+};
+
+&sdhci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
index 294b99dd50da..70a43432bdc5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
@@ -5,6 +5,7 @@
#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 "rk3588s.dtsi"
/ {
@@ -35,6 +36,17 @@
stdout-path = "serial2:1500000n8";
};
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "d";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -56,7 +68,7 @@
#cooling-cells = <2>;
};
- vcc12v_dcin: vcc12v-dcin-regulator {
+ vcc12v_dcin: regulator-vcc12v-dcin {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
@@ -65,7 +77,7 @@
regulator-max-microvolt = <12000000>;
};
- vcc3v3_wf: vcc3v3-wf-regulator {
+ vcc3v3_wf: regulator-vcc3v3-wf {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_wf";
regulator-min-microvolt = <3300000>;
@@ -77,7 +89,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_host: vcc5v0-host-regulator {
+ vcc5v0_host: regulator-vcc5v0-host {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_host";
regulator-boot-on;
@@ -91,7 +103,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc5v0_sys: vcc5v0-sys-regulator {
+ vcc5v0_sys: regulator-vcc5v0-sys {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -101,7 +113,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc_5v0: vcc-5v0-regulator {
+ vcc_5v0: regulator-vcc-5v0 {
compatible = "regulator-fixed";
regulator-name = "vcc_5v0";
regulator-min-microvolt = <5000000>;
@@ -115,7 +127,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v1_nldo_s3";
regulator-always-on;
@@ -166,6 +178,11 @@
cpu-supply = <&vdd_cpu_lit_s0>;
};
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -296,6 +313,31 @@
status = "okay";
};
+&hdmi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmim0_tx0_cec
+ &hdmim1_tx0_hpd
+ &hdmim0_tx0_scl
+ &hdmim0_tx0_sda>;
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&mdio1 {
rgmii_phy1: ethernet-phy@1 {
/* RTL8211F */
@@ -310,7 +352,7 @@
};
&pcie2x1l2 {
- pinctrl-0 = <&pcie20x1m0_pins>;
+ pinctrl-0 = <&pcie2_reset>, <&pcie20x1m0_clkreqn>, <&pcie20x1m0_waken>;
pinctrl-names = "default";
reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_wf>;
@@ -328,6 +370,10 @@
pow_en: pow-en {
rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
};
+
+ pcie2_reset: pcie2-reset {
+ rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
};
power {
@@ -784,3 +830,18 @@
&usb_host2_xhci {
status = "okay";
};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dts
new file mode 100644
index 000000000000..9b14d5383cdc
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5c.dts
@@ -0,0 +1,920 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Radxa Computer (Shenzhen) 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 "rk3588s.dtsi"
+
+/ {
+ model = "Radxa ROCK 5C";
+ compatible = "radxa,rock-5c", "rockchip,rk3588s";
+
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ analog-sound {
+ compatible = "audio-graph-card";
+ label = "rk3588-es8316";
+ dais = <&i2s0_8ch_p0>;
+ routing = "MIC2", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR";
+ widgets = "Microphone", "Mic Jack",
+ "Headphone", "Headphones";
+ };
+
+ hdmi0-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi0_con_in: endpoint {
+ remote-endpoint = <&hdmi0_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins>;
+
+ led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ function = LED_FUNCTION_POWER;
+ gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-1 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "on";
+ function = LED_FUNCTION_HEARTBEAT;
+ gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ cooling-levels = <0 64 128 192 255>;
+ fan-supply = <&vcc_5v0>;
+ pwms = <&pwm3 0 10000 0>;
+ };
+
+ pcie2x1l2_3v3: regulator-pcie2x1l2-3v3 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pow_en>;
+ regulator-name = "pcie2x1l2_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_sysin>;
+ };
+
+ vcc5v_dcin: regulator-vcc5v-dcin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc5v0_usb_host: regulator-vcc5v0-usb-host {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_host_pwren_h>;
+ regulator-name = "vcc5v0_usb_host";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_sysin>;
+ };
+
+ vcc5v0_usb_otg0: regulator-vcc5v0-usb-otg0 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_otg_pwren_h>;
+ regulator-name = "vcc5v0_usb_otg0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_sysin>;
+ };
+
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&vcc_sysin>;
+ };
+
+ vcc_3v3_pmu: regulator-vcc-3v3-pmu {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc_3v3_s0: regulator-vcc-3v3-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_1v8_s0>;
+ };
+
+ vcc_5v0: regulator-vcc-5v0 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc_5v0_pwren_h>;
+ regulator-name = "vcc_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_sysin>;
+ };
+
+ vcc_sysin: regulator-vcc-sysin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sysin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v_dcin>;
+ };
+
+ vcca: regulator-vcca {
+ compatible = "regulator-fixed";
+ regulator-name = "vcca";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ vin-supply = <&vcc_sysin>;
+ };
+
+ vdd_3v3: regulator-vdd-3v3 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_wifi_pwr>;
+ regulator-name = "vdd_3v3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy2_psu {
+ status = "okay";
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_big0_s0>;
+};
+
+&cpu_b2 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_b3 {
+ cpu-supply = <&vdd_cpu_big1_s0>;
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&gmac1 {
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-id";
+ phy-supply = <&vcc_3v3_s0>;
+ pinctrl-0 = <&gmac1_miim
+ &gmac1_tx_bus2
+ &gmac1_rx_bus2
+ &gmac1_rgmii_clk
+ &gmac1_rgmii_bus
+ &gmac1_clkinout>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&hdmi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmim0_tx0_cec
+ &hdmim1_tx0_hpd
+ &hdmim0_tx0_scl
+ &hdmim0_tx0_sda>;
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdmi0_out {
+ hdmi0_out_con: endpoint {
+ remote-endpoint = <&hdmi0_con_in>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0m2_xfer>;
+ status = "okay";
+
+ vdd_cpu_big0_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big0_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc_sysin>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_big1_s0: regulator@43 {
+ compatible = "rockchip,rk8603", "rockchip,rk8602";
+ reg = <0x43>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu_big1_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc_sysin>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ eeprom@50 {
+ compatible = "belling,bl24c16a", "atmel,24c16";
+ reg = <0x50>;
+ pagesize = <16>;
+ vcc-supply = <&vcc_3v3_pmu>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ vdd_npu_s0: regulator@42 {
+ compatible = "rockchip,rk8602";
+ reg = <0x42>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_npu_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc_sysin>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&i2c5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c5m2_xfer>;
+ status = "okay";
+
+ rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ clock-output-names = "rtcic_32kout";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_int_l>;
+ };
+};
+
+&i2c7 {
+ status = "okay";
+
+ audio-codec@11 {
+ compatible = "everest,es8316";
+ reg = <0x11>;
+ assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
+ assigned-clock-rates = <12288000>;
+ clocks = <&cru I2S0_8CH_MCLKOUT>;
+ clock-names = "mclk";
+ #sound-dai-cells = <0>;
+
+ port {
+ es8316_p0_0: endpoint {
+ remote-endpoint = <&i2s0_8ch_p0_0>;
+ };
+ };
+ };
+};
+
+&i2s0_8ch {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_lrck
+ &i2s0_mclk
+ &i2s0_sclk
+ &i2s0_sdi0
+ &i2s0_sdo0>;
+ status = "okay";
+
+ i2s0_8ch_p0: port {
+ i2s0_8ch_p0_0: endpoint {
+ dai-format = "i2s";
+ mclk-fs = <256>;
+ remote-endpoint = <&es8316_p0_0>;
+ };
+ };
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1_rstn>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie2x1l2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie20x1_2_perstn_m0>;
+ reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&pcie2x1l2_3v3>;
+ status = "okay";
+};
+
+&pinctrl {
+ leds {
+ led_pins: led-pins {
+ rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>,
+ <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ mdio {
+ gmac1_rstn: gmac1-rstn {
+ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie {
+ pcie20x1_2_perstn_m0: pcie20x1-2-perstn-m0 {
+ rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pow_en: pow-en {
+ rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ rtc {
+ rtc_int_l: rtc-int-l {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ usb_host_pwren_h: usb-host-pwren-h {
+ rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usb_otg_pwren_h: usb-otg-pwren-h {
+ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usb_wifi_pwr: usb-wifi-pwr {
+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc_5v0_pwren_h: vcc-5v0-pwren-h {
+ rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3m1_pins>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcca_1v8_s0>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ no-sdio;
+ no-sd;
+ non-removable;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ disable-wp;
+ no-sdio;
+ no-mmc;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_3v3_s3>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&sfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fspim0_pins>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <104000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&spi2 {
+ status = "okay";
+ assigned-clocks = <&cru CLK_SPI2>;
+ assigned-clock-rates = <200000000>;
+ num-cs = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
+
+ pmic@0 {
+ compatible = "rockchip,rk806";
+ reg = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ spi-max-frequency = <1000000>;
+ system-power-controller;
+
+ vcc1-supply = <&vcc_sysin>;
+ vcc2-supply = <&vcc_sysin>;
+ vcc3-supply = <&vcc_sysin>;
+ vcc4-supply = <&vcc_sysin>;
+ vcc5-supply = <&vcc_sysin>;
+ vcc6-supply = <&vcc_sysin>;
+ vcc7-supply = <&vcc_sysin>;
+ vcc8-supply = <&vcc_sysin>;
+ vcc9-supply = <&vcc_sysin>;
+ vcc10-supply = <&vcc_sysin>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc_sysin>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcca>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ regulators {
+ vdd_gpu_s0: dcdc-reg1 {
+ regulator-name = "vdd_gpu_s0";
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg2 {
+ regulator-name = "vdd_cpu_lit_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_logic_s0: dcdc-reg3 {
+ regulator-name = "vdd_logic_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <750000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdd_vdenc_s0: dcdc-reg4 {
+ regulator-name = "vdd_vdenc_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg5 {
+ regulator-name = "vdd_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg6 {
+ regulator-name = "vdd2_ddr_s3";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_2v0_pldo_s3: dcdc-reg7 {
+ regulator-name = "vdd_2v0_pldo_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-ramp-delay = <12500>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2000000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg8 {
+ regulator-name = "vcc_3v3_s3";
+ 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>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg9 {
+ regulator-name = "vddq_ddr_s0";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc1v8_pmu_ddr_s3: dcdc-reg10 {
+ regulator-name = "vcc1v8_pmu_ddr_s3";
+ 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>;
+ };
+ };
+
+ vcc_1v8_s0: pldo-reg1 {
+ regulator-name = "vcc_1v8_s0";
+ 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>;
+ };
+ };
+
+ vcca_1v8_s0: pldo-reg2 {
+ regulator-name = "vcca_1v8_s0";
+ 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>;
+ };
+ };
+
+ vdda_1v2_s0: pldo-reg3 {
+ regulator-name = "vdda_1v2_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca_3v3_s0: pldo-reg4 {
+ regulator-name = "vcca_3v3_s0";
+ 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>;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-name = "vccio_sd_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ pldo6_s3: pldo-reg6 {
+ regulator-name = "pldo6_s3";
+ 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>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-name = "vdd_0v75_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdda_ddr_pll_s0: nldo-reg2 {
+ regulator-name = "vdda_ddr_pll_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vdda_0v75_s0: nldo-reg3 {
+ regulator-name = "vdda_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v85_s0: nldo-reg4 {
+ regulator-name = "vdda_0v85_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_0v75_s0: nldo-reg5 {
+ regulator-name = "vdd_0v75_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ phy-supply = <&vcc5v0_usb_otg0>;
+ status = "okay";
+};
+
+&u2phy2 {
+ status = "okay";
+};
+
+&u2phy2_host {
+ /* connected to USB hub, which is powered by vcc_5v0 */
+ phy-supply = <&vcc_5v0>;
+ status = "okay";
+};
+
+&u2phy3 {
+ status = "okay";
+};
+
+&u2phy3_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-0 = <&uart2m0_xfer>;
+ status = "okay";
+};
+
+&usbdp_phy0 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usb_host2_xhci {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index 1167cf63d7e8..6fe12e3bd7dd 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -245,6 +245,9 @@
interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI2>;
resets = <&rcc SPI2_R>;
+ dmas = <&hpdma 51 0x20 0x3012>,
+ <&hpdma 52 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 23>;
status = "disabled";
};
@@ -257,6 +260,9 @@
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI3>;
resets = <&rcc SPI3_R>;
+ dmas = <&hpdma 53 0x20 0x3012>,
+ <&hpdma 54 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 24>;
status = "disabled";
};
@@ -266,6 +272,9 @@
reg = <0x400e0000 0x400>;
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_USART2>;
+ dmas = <&hpdma 11 0x20 0x10012>,
+ <&hpdma 12 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 32>;
status = "disabled";
};
@@ -275,6 +284,9 @@
reg = <0x400f0000 0x400>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_USART3>;
+ dmas = <&hpdma 13 0x20 0x10012>,
+ <&hpdma 14 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 33>;
status = "disabled";
};
@@ -284,6 +296,9 @@
reg = <0x40100000 0x400>;
interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_UART4>;
+ dmas = <&hpdma 15 0x20 0x10012>,
+ <&hpdma 16 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 34>;
status = "disabled";
};
@@ -293,6 +308,9 @@
reg = <0x40110000 0x400>;
interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_UART5>;
+ dmas = <&hpdma 17 0x20 0x10012>,
+ <&hpdma 18 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 35>;
status = "disabled";
};
@@ -306,6 +324,9 @@
resets = <&rcc I2C1_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 27 0x20 0x3012>,
+ <&hpdma 28 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 41>;
status = "disabled";
};
@@ -319,6 +340,9 @@
resets = <&rcc I2C2_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 30 0x20 0x3012>,
+ <&hpdma 31 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 42>;
status = "disabled";
};
@@ -332,6 +356,9 @@
resets = <&rcc I2C3_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 33 0x20 0x3012>,
+ <&hpdma 34 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 43>;
status = "disabled";
};
@@ -345,6 +372,9 @@
resets = <&rcc I2C4_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 36 0x20 0x3012>,
+ <&hpdma 37 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 44>;
status = "disabled";
};
@@ -358,6 +388,9 @@
resets = <&rcc I2C5_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 39 0x20 0x3012>,
+ <&hpdma 40 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 45>;
status = "disabled";
};
@@ -371,6 +404,9 @@
resets = <&rcc I2C6_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 42 0x20 0x3012>,
+ <&hpdma 43 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 46>;
status = "disabled";
};
@@ -384,6 +420,9 @@
resets = <&rcc I2C7_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 45 0x20 0x3012>,
+ <&hpdma 46 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 47>;
status = "disabled";
};
@@ -393,6 +432,9 @@
reg = <0x40220000 0x400>;
interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_USART6>;
+ dmas = <&hpdma 19 0x20 0x10012>,
+ <&hpdma 20 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 36>;
status = "disabled";
};
@@ -405,6 +447,9 @@
interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI1>;
resets = <&rcc SPI1_R>;
+ dmas = <&hpdma 49 0x20 0x3012>,
+ <&hpdma 50 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 22>;
status = "disabled";
};
@@ -417,6 +462,9 @@
interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI4>;
resets = <&rcc SPI4_R>;
+ dmas = <&hpdma 55 0x20 0x3012>,
+ <&hpdma 56 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 25>;
status = "disabled";
};
@@ -429,6 +477,9 @@
interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI5>;
resets = <&rcc SPI5_R>;
+ dmas = <&hpdma 57 0x20 0x3012>,
+ <&hpdma 58 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 26>;
status = "disabled";
};
@@ -438,6 +489,9 @@
reg = <0x402c0000 0x400>;
interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_UART9>;
+ dmas = <&hpdma 25 0x20 0x10012>,
+ <&hpdma 26 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 39>;
status = "disabled";
};
@@ -447,6 +501,9 @@
reg = <0x40330000 0x400>;
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_USART1>;
+ dmas = <&hpdma 9 0x20 0x10012>,
+ <&hpdma 10 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 31>;
status = "disabled";
};
@@ -459,6 +516,9 @@
interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI6>;
resets = <&rcc SPI6_R>;
+ dmas = <&hpdma 59 0x20 0x3012>,
+ <&hpdma 60 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 27>;
status = "disabled";
};
@@ -471,6 +531,9 @@
interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI7>;
resets = <&rcc SPI7_R>;
+ dmas = <&hpdma 61 0x20 0x3012>,
+ <&hpdma 62 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 28>;
status = "disabled";
};
@@ -480,6 +543,9 @@
reg = <0x40370000 0x400>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_UART7>;
+ dmas = <&hpdma 21 0x20 0x10012>,
+ <&hpdma 22 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 37>;
status = "disabled";
};
@@ -489,10 +555,23 @@
reg = <0x40380000 0x400>;
interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_UART8>;
+ dmas = <&hpdma 23 0x20 0x10012>,
+ <&hpdma 24 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 38>;
status = "disabled";
};
+ rng: rng@42020000 {
+ compatible = "st,stm32mp25-rng";
+ reg = <0x42020000 0x400>;
+ clocks = <&clk_rcbsec>, <&rcc CK_BUS_RNG>;
+ clock-names = "core", "bus";
+ resets = <&rcc RNG_R>;
+ access-controllers = <&rifsc 92>;
+ status = "disabled";
+ };
+
spi8: spi@46020000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -501,6 +580,9 @@
interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_SPI8>;
resets = <&rcc SPI8_R>;
+ dmas = <&hpdma 171 0x20 0x3012>,
+ <&hpdma 172 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 29>;
status = "disabled";
};
@@ -514,6 +596,9 @@
resets = <&rcc I2C8_R>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&hpdma 168 0x20 0x3012>,
+ <&hpdma 169 0x20 0x3021>;
+ dma-names = "rx", "tx";
access-controllers = <&rifsc 48>;
status = "disabled";
};
@@ -916,6 +1001,16 @@
};
};
+ rtc: rtc@46000000 {
+ compatible = "st,stm32mp25-rtc";
+ reg = <0x46000000 0x400>;
+ clocks = <&scmi_clk CK_SCMI_RTC>,
+ <&scmi_clk CK_SCMI_RTCCK>;
+ clock-names = "pclk", "rtc_ck";
+ interrupts-extended = <&exti2 17 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
pinctrl_z: pinctrl@46200000 {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 214191a8322b..6f393b082789 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -93,6 +93,10 @@
status = "disabled";
};
+&rtc {
+ status = "okay";
+};
+
&scmi_regu {
scmi_vddio1: regulator@0 {
regulator-min-microvolt = <1800000>;
@@ -157,6 +161,8 @@
pinctrl-0 = <&usart2_pins_a>;
pinctrl-1 = <&usart2_idle_pins_a>;
pinctrl-2 = <&usart2_sleep_pins_a>;
+ /delete-property/dmas;
+ /delete-property/dma-names;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
index bcd392c3206e..f71360f14f23 100644
--- a/arch/arm64/boot/dts/ti/Makefile
+++ b/arch/arm64/boot/dts/ti/Makefile
@@ -16,13 +16,14 @@ dtb-$(CONFIG_ARCH_K3) += k3-am625-phyboard-lyra-rdk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-sk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-dahlia.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-dev.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-ivy.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-mallow.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-yavia.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dahlia.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dev.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-ivy.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-mallow.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-yavia.dtb
-dtb-$(CONFIG_ARCH_K3) += k3-am625-phyboard-lyra-1-4-ghz-opp.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am62x-phyboard-lyra-gpio-fan.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk-nand.dtbo
@@ -48,6 +49,7 @@ k3-am642-hummingboard-t-usb3-dtbs := \
dtb-$(CONFIG_ARCH_K3) += k3-am642-evm.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-evm-icssg1-dualemac.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am642-evm-icssg1-dualemac-mii.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am642-evm-pcie0-ep.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-am642-hummingboard-t.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-hummingboard-t-pcie.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am642-hummingboard-t-usb3.dtb
@@ -96,6 +98,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-am654-pcie-usb3.dtbo
# Boards with J7200 SoC
k3-j7200-evm-dtbs := k3-j7200-common-proc-board.dtb k3-j7200-evm-quad-port-eth-exp.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j7200-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j7200-evm-pcie1-ep.dtbo
# Boards with J721e SoC
k3-j721e-evm-dtbs := k3-j721e-common-proc-board.dtb k3-j721e-evm-quad-port-eth-exp.dtbo
@@ -126,13 +129,14 @@ dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm-pcie0-pcie1-ep.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm-quad-port-eth-exp1.dtbo
dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm-usxgmii-exp1-exp2.dtbo
+# Boards with J742S2 SoC
+dtb-$(CONFIG_ARCH_K3) += k3-j742s2-evm.dtb
+
# Build time test only, enabled by CONFIG_OF_ALL_DTBS
k3-am625-beagleplay-csi2-ov5640-dtbs := k3-am625-beagleplay.dtb \
k3-am625-beagleplay-csi2-ov5640.dtbo
k3-am625-beagleplay-csi2-tevi-ov5640-dtbs := k3-am625-beagleplay.dtb \
k3-am625-beagleplay-csi2-tevi-ov5640.dtbo
-k3-am625-phyboard-lyra-1-4-ghz-opp.dtbs := k3-am625-phyboard-lyra-rdk.dtb \
- k3-am625-phyboard-lyra-1-4-ghz-opp.dtbo
k3-am625-phyboard-lyra-disable-eth-phy-dtbs := k3-am625-phyboard-lyra-rdk.dtb \
k3-am6xx-phycore-disable-eth-phy.dtbo
k3-am625-phyboard-lyra-disable-rtc-dtbs := k3-am625-phyboard-lyra-rdk.dtb \
@@ -168,6 +172,8 @@ k3-am642-evm-icssg1-dualemac-dtbs := \
k3-am642-evm.dtb k3-am642-evm-icssg1-dualemac.dtbo
k3-am642-evm-icssg1-dualemac-mii-dtbs := \
k3-am642-evm.dtb k3-am642-evm-icssg1-dualemac-mii.dtbo
+k3-am642-evm-pcie0-ep-dtbs := \
+ k3-am642-evm.dtb k3-am642-evm-pcie0-ep.dtbo
k3-am642-phyboard-electra-disable-eth-phy-dtbs := \
k3-am642-phyboard-electra-rdk.dtb k3-am6xx-phycore-disable-eth-phy.dtbo
k3-am642-phyboard-electra-disable-rtc-dtbs := \
@@ -188,6 +194,8 @@ k3-am68-sk-base-board-csi2-dual-imx219-dtbs := k3-am68-sk-base-board.dtb \
k3-j721e-sk-csi2-dual-imx219.dtbo
k3-am69-sk-csi2-dual-imx219-dtbs := k3-am69-sk.dtb \
k3-j721e-sk-csi2-dual-imx219.dtbo
+k3-j7200-evm-pcie1-ep-dtbs := k3-j7200-common-proc-board.dtb \
+ k3-j7200-evm-pcie1-ep.dtbo
k3-j721e-common-proc-board-infotainment-dtbs := k3-j721e-common-proc-board.dtb \
k3-j721e-common-proc-board-infotainment.dtbo
k3-j721e-evm-pcie0-ep-dtbs := k3-j721e-common-proc-board.dtb \
@@ -217,10 +225,12 @@ dtb- += k3-am625-beagleplay-csi2-ov5640.dtb \
k3-am62p5-sk-csi2-tevi-ov5640.dtb \
k3-am642-evm-icssg1-dualemac.dtb \
k3-am642-evm-icssg1-dualemac-mii.dtb \
+ k3-am642-evm-pcie0-ep.dtb \
k3-am642-tqma64xxl-mbax4xxl-sdcard.dtb \
k3-am642-tqma64xxl-mbax4xxl-wlan.dtb \
k3-am68-sk-base-board-csi2-dual-imx219.dtb \
k3-am69-sk-csi2-dual-imx219.dtb \
+ k3-j7200-evm-pcie1-ep.dtbo \
k3-j721e-common-proc-board-infotainment.dtb \
k3-j721e-evm-pcie0-ep.dtb \
k3-j721e-sk-csi2-dual-imx219.dtb \
@@ -243,7 +253,9 @@ DTC_FLAGS_k3-am642-tqma64xxl-mbax4xxl += -@
DTC_FLAGS_k3-am6548-iot2050-advanced-m2 += -@
DTC_FLAGS_k3-am68-sk-base-board += -@
DTC_FLAGS_k3-am69-sk += -@
+DTC_FLAGS_k3-j7200-common-proc-board += -@
DTC_FLAGS_k3-j721e-common-proc-board += -@
DTC_FLAGS_k3-j721e-sk += -@
DTC_FLAGS_k3-j721s2-common-proc-board += -@
DTC_FLAGS_k3-j784s4-evm += -@
+DTC_FLAGS_k3-j742s2-evm += -@
diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
index 5b92aef5b284..7cd727d10a5f 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
@@ -561,10 +561,9 @@
ti,clkbuf-sel = <0x7>;
ti,otap-del-sel-legacy = <0x0>;
ti,otap-del-sel-mmc-hs = <0x0>;
- ti,otap-del-sel-ddr52 = <0x5>;
- ti,otap-del-sel-hs200 = <0x5>;
- ti,itap-del-sel-legacy = <0xa>;
- ti,itap-del-sel-mmc-hs = <0x1>;
+ ti,otap-del-sel-hs200 = <0x6>;
+ ti,itap-del-sel-legacy = <0x0>;
+ ti,itap-del-sel-mmc-hs = <0x0>;
status = "disabled";
};
@@ -577,17 +576,17 @@
clock-names = "clk_ahb", "clk_xin";
bus-width = <4>;
ti,clkbuf-sel = <0x7>;
- ti,otap-del-sel-legacy = <0x8>;
+ ti,otap-del-sel-legacy = <0x0>;
ti,otap-del-sel-sd-hs = <0x0>;
- ti,otap-del-sel-sdr12 = <0x0>;
- ti,otap-del-sel-sdr25 = <0x0>;
- ti,otap-del-sel-sdr50 = <0x8>;
- ti,otap-del-sel-sdr104 = <0x7>;
- ti,otap-del-sel-ddr50 = <0x4>;
- ti,itap-del-sel-legacy = <0xa>;
- ti,itap-del-sel-sd-hs = <0x1>;
- ti,itap-del-sel-sdr12 = <0xa>;
- ti,itap-del-sel-sdr25 = <0x1>;
+ ti,otap-del-sel-sdr12 = <0xf>;
+ ti,otap-del-sel-sdr25 = <0xf>;
+ ti,otap-del-sel-sdr50 = <0xc>;
+ ti,otap-del-sel-sdr104 = <0x6>;
+ ti,otap-del-sel-ddr50 = <0x9>;
+ ti,itap-del-sel-legacy = <0x0>;
+ ti,itap-del-sel-sd-hs = <0x0>;
+ ti,itap-del-sel-sdr12 = <0x0>;
+ ti,itap-del-sel-sdr25 = <0x0>;
status = "disabled";
};
@@ -600,17 +599,17 @@
clock-names = "clk_ahb", "clk_xin";
bus-width = <4>;
ti,clkbuf-sel = <0x7>;
- ti,otap-del-sel-legacy = <0x8>;
+ ti,otap-del-sel-legacy = <0x0>;
ti,otap-del-sel-sd-hs = <0x0>;
- ti,otap-del-sel-sdr12 = <0x0>;
- ti,otap-del-sel-sdr25 = <0x0>;
- ti,otap-del-sel-sdr50 = <0x8>;
- ti,otap-del-sel-sdr104 = <0x7>;
- ti,otap-del-sel-ddr50 = <0x8>;
- ti,itap-del-sel-legacy = <0xa>;
- ti,itap-del-sel-sd-hs = <0xa>;
- ti,itap-del-sel-sdr12 = <0xa>;
- ti,itap-del-sel-sdr25 = <0x1>;
+ ti,otap-del-sel-sdr12 = <0xf>;
+ ti,otap-del-sel-sdr25 = <0xf>;
+ ti,otap-del-sel-sdr50 = <0xc>;
+ ti,otap-del-sel-sdr104 = <0x6>;
+ ti,otap-del-sel-ddr50 = <0x9>;
+ ti,itap-del-sel-legacy = <0x0>;
+ ti,itap-del-sel-sd-hs = <0x0>;
+ ti,itap-del-sel-sdr12 = <0x0>;
+ ti,itap-del-sel-sdr25 = <0x0>;
status = "disabled";
};
@@ -843,6 +842,33 @@
status = "disabled";
};
+ eqep0: counter@23200000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23200000 0x00 0x100>;
+ power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 59 0>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep1: counter@23210000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23210000 0x00 0x100>;
+ power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 60 0>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep2: counter@23220000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23220000 0x00 0x100>;
+ power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 62 0>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
main_mcan0: can@20701000 {
compatible = "bosch,m_can";
reg = <0x00 0x20701000 0x00 0x200>,
diff --git a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
index bb43a411f59b..68e906796aef 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
@@ -174,4 +174,17 @@
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
status = "disabled";
};
+
+ mcu_m4fss: m4fss@5000000 {
+ compatible = "ti,am64-m4fss";
+ reg = <0x00 0x5000000 0x00 0x30000>,
+ <0x00 0x5040000 0x00 0x10000>;
+ reg-names = "iram", "dram";
+ resets = <&k3_reset 9 1>;
+ firmware-name = "am62-mcu-m4f0_0-fw";
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <9>;
+ ti,sci-proc-ids = <0x18 0xff>;
+ status = "disabled";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
index 43488cc8bcb1..5952874fe429 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
@@ -45,6 +45,18 @@
pmsg-size = <0x8000>;
};
+ mcu_m4fss_dma_memory_region: m4f-dma-memory@9cb00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0x9cb00000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_m4fss_memory_region: m4f-memory@9cc00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0x9cc00000 0x00 0xe00000>;
+ no-map;
+ };
+
secure_tfa_ddr: tfa@9e780000 {
reg = <0x00 0x9e780000 0x00 0x80000>;
alignment = <0x1000>;
@@ -173,6 +185,13 @@
};
};
+&a53_opp_table {
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-supported-hw = <0x01 0x0004>;
+ };
+};
+
&cpsw3g {
pinctrl-names = "default";
pinctrl-0 = <&main_rgmii1_pins_default>;
@@ -196,6 +215,13 @@
};
};
+&mailbox0_cluster0 {
+ mbox_m4_0: mbox-m4-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+};
+
&main_i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
@@ -226,8 +252,8 @@
regulators {
vdd_core: buck1 {
regulator-name = "VDD_CORE";
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <750000>;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
regulator-boot-on;
regulator-always-on;
};
@@ -295,6 +321,13 @@
};
};
+&mcu_m4fss {
+ mboxes = <&mailbox0_cluster0 &mbox_m4_0>;
+ memory-region = <&mcu_m4fss_dma_memory_region>,
+ <&mcu_m4fss_memory_region>;
+ status = "okay";
+};
+
&ospi0 {
pinctrl-names = "default";
pinctrl-0 = <&ospi0_pins_default>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-ivy.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-ivy.dtsi
new file mode 100644
index 000000000000..71c29eab0eee
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-ivy.dtsi
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ *
+ * Common dtsi for Verdin AM62 SoM on Ivy carrier board
+ *
+ * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62
+ * https://www.toradex.com/products/carrier-board/ivy-carrier-board
+ */
+
+#include <dt-bindings/mux/mux.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+ /* AIN1 Voltage w/o AIN1_MODE gpio control */
+ ain1_voltage_unmanaged: voltage-divider-ain1 {
+ compatible = "voltage-divider";
+ #io-channel-cells = <1>;
+ io-channels = <&ivy_adc1 0>;
+ full-ohms = <19>;
+ output-ohms = <1>;
+ };
+
+ /* AIN1 Current w/o AIN1_MODE gpio control */
+ ain1_current_unmanaged: current-sense-shunt-ain1 {
+ compatible = "current-sense-shunt";
+ #io-channel-cells = <0>;
+ io-channels = <&ivy_adc1 1>;
+ shunt-resistor-micro-ohms = <100000000>;
+ };
+
+ /* AIN1_MODE - SODIMM 216 */
+ ain1_mode_mux_ctrl: mux-controller-0 {
+ compatible = "gpio-mux";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_5>;
+ #mux-control-cells = <0>;
+ mux-gpios = <&main_gpio0 40 GPIO_ACTIVE_HIGH>;
+ };
+
+ ain1-voltage {
+ compatible = "io-channel-mux";
+ channels = "ain1_voltage", "";
+ io-channels = <&ain1_voltage_unmanaged 0>;
+ io-channel-names = "parent";
+ mux-controls = <&ain1_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ ain1-current {
+ compatible = "io-channel-mux";
+ channels = "", "ain1_current";
+ io-channels = <&ain1_current_unmanaged>;
+ io-channel-names = "parent";
+ mux-controls = <&ain1_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ /* AIN2 Voltage w/o AIN2_MODE gpio control */
+ ain2_voltage_unmanaged: voltage-divider-ain2 {
+ compatible = "voltage-divider";
+ #io-channel-cells = <1>;
+ io-channels = <&ivy_adc2 0>;
+ full-ohms = <19>;
+ output-ohms = <1>;
+ };
+
+ /* AIN2 Current w/o AIN2_MODE gpio control */
+ ain2_current_unmanaged: current-sense-shunt-ain2 {
+ compatible = "current-sense-shunt";
+ #io-channel-cells = <0>;
+ io-channels = <&ivy_adc2 1>;
+ shunt-resistor-micro-ohms = <100000000>;
+ };
+
+ /* AIN2_MODE - SODIMM 218 */
+ ain2_mode_mux_ctrl: mux-controller-1 {
+ compatible = "gpio-mux";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_6>;
+ #mux-control-cells = <0>;
+ mux-gpios = <&main_gpio0 36 GPIO_ACTIVE_HIGH>;
+ };
+
+ ain2-voltage {
+ compatible = "io-channel-mux";
+ channels = "ain2_voltage", "";
+ io-channels = <&ain2_voltage_unmanaged 0>;
+ io-channel-names = "parent";
+ mux-controls = <&ain2_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ ain2-current {
+ compatible = "io-channel-mux";
+ channels = "", "ain2_current";
+ io-channels = <&ain2_current_unmanaged>;
+ io-channel-names = "parent";
+ mux-controls = <&ain2_mode_mux_ctrl>;
+ settle-time-us = <1000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ivy_leds>;
+
+ /* D7 Blue - SODIMM 30 - LEDs.GPIO1 */
+ led-0 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&main_gpio1 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D7 Green - SODIMM 32 - LEDs.GPIO2 */
+ led-1 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&main_gpio1 12 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D7 Red - SODIMM 34 - LEDs.GPIO3 */
+ led-2 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <1>;
+ gpios = <&main_gpio1 10 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Blue - SODIMM 36 - LEDs.GPIO4 */
+ led-3 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&main_gpio1 9 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Green - SODIMM 54 - LEDs.GPIO5 */
+ led-4 {
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&main_gpio0 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D8 Red - SODIMM 44 - LEDs.GPIO6 */
+ led-5 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <2>;
+ gpios = <&main_gpio0 37 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D9 Blue - SODIMM 46 - LEDs.GPIO7 */
+ led-6 {
+ color = <LED_COLOR_ID_BLUE>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <3>;
+ gpios = <&main_gpio0 34 GPIO_ACTIVE_HIGH>;
+ };
+
+ /* D9 Red - SODIMM 48 - LEDs.GPIO8 */
+ led-7 {
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ function-enumerator = <3>;
+ gpios = <&main_gpio0 33 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ reg_3v2_ain1: regulator-3v2-ain1 {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3200000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-name = "+3V2_AIN1";
+ };
+
+ reg_3v2_ain2: regulator-3v2-ain2 {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <3200000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-name = "+3V2_AIN2";
+ };
+
+ /* Ivy Power Supply Input Voltage */
+ ivy-input-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_1 */
+ io-channels = <&verdin_som_adc 7>;
+ full-ohms = <204700>; /* 200K + 4.7K */
+ output-ohms = <4700>;
+ };
+
+ ivy-5v-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_2 */
+ io-channels = <&verdin_som_adc 6>;
+ full-ohms = <39000>; /* 27K + 12K */
+ output-ohms = <12000>;
+ };
+
+ ivy-3v3-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_3 */
+ io-channels = <&verdin_som_adc 5>;
+ full-ohms = <54000>; /* 27K + 27K */
+ output-ohms = <27000>;
+ };
+
+ ivy-1v8-voltage {
+ compatible = "voltage-divider";
+ /* Verdin ADC_4 */
+ io-channels = <&verdin_som_adc 4>;
+ full-ohms = <39000>; /* 12K + 27K */
+ output-ohms = <27000>;
+ };
+};
+
+&main_pmx0 {
+ pinctrl_ivy_leds: ivy-leds-default-pins {
+ pinctrl-single,pins =
+ <AM62X_IOPAD(0x019c, PIN_INPUT, 7)>, /* (B18) MCASP0_AXR1.GPIO1_9 */ /* SODIMM 36 */
+ <AM62X_IOPAD(0x01a0, PIN_INPUT, 7)>, /* (B20) MCASP0_AXR0.GPIO1_10 */ /* SODIMM 34 */
+ <AM62X_IOPAD(0x01a4, PIN_INPUT, 7)>, /* (A19) MCASP0_ACLKX.GPIO1_11 */ /* SODIMM 30 */
+ <AM62X_IOPAD(0x01a8, PIN_INPUT, 7)>, /* (A20) MCASP0_AFSX.GPIO1_12 */ /* SODIMM 32 */
+ <AM62X_IOPAD(0x0088, PIN_INPUT, 7)>, /* (L17) GPMC0_OEn_REn.GPIO0_33 */ /* SODIMM 48 */
+ <AM62X_IOPAD(0x0098, PIN_INPUT, 7)>, /* (R18) GPMC0_WAIT0.GPIO0_37 */ /* SODIMM 44 */
+ <AM62X_IOPAD(0x008c, PIN_INPUT, 7)>, /* (L25) GPMC0_WEn.GPIO0_34 */ /* SODIMM 46 */
+ <AM62X_IOPAD(0x002c, PIN_INPUT, 7)>; /* (F23) OSPI0_CSn0.GPIO0_11 */ /* SODIMM 54 */
+ };
+};
+
+/* Verdin ETH */
+&cpsw3g {
+ status = "okay";
+};
+
+/* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */
+&cpsw3g_mdio {
+ status = "okay";
+
+ cpsw3g_phy1: ethernet-phy@2 {
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eth2_rgmii_int>;
+ interrupt-parent = <&main_gpio0>;
+ interrupts = <38 IRQ_TYPE_EDGE_FALLING>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ };
+};
+
+/* Verdin ETH_1*/
+&cpsw_port1 {
+ status = "okay";
+};
+
+/* Verdin ETH_2_RGMII */
+&cpsw_port2 {
+ phy-handle = <&cpsw3g_phy1>;
+ phy-mode = "rgmii-rxid";
+ status = "okay";
+};
+
+&main_gpio0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ctrl_sleep_moci>,
+ <&pinctrl_qspi1_cs2_gpio>,
+ <&pinctrl_qspi1_io0_gpio>,
+ <&pinctrl_qspi1_io1_gpio>,
+ <&pinctrl_qspi1_io2_gpio>,
+ <&pinctrl_qspi1_io3_gpio>;
+ gpio-line-names =
+ "", /* 0 */
+ "",
+ "",
+ "DIGI_1", /* SODIMM 56 */
+ "DIGI_2", /* SODIMM 58 */
+ "REL1", /* SODIMM 60 */
+ "REL2", /* SODIMM 62 */
+ "",
+ "",
+ "",
+ "", /* 10 */
+ "",
+ "REL3", /* SODIMM 64 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 20 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 30 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 40 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 50 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 60 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 70 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 80 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+&main_gpio1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi1_dqs_gpio>;
+ gpio-line-names =
+ "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 10 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "REL4", /* SODIMM 66 */
+ "",
+ "", /* 20 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 30 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 40 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 50 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 60 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 70 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 80 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+/* Verdin I2C_1 */
+&main_i2c1 {
+ status = "okay";
+
+ temperature-sensor@4f {
+ compatible = "ti,tmp1075";
+ reg = <0x4f>;
+ };
+
+ eeprom@57 {
+ compatible = "st,24c02", "atmel,24c02";
+ reg = <0x57>;
+ pagesize = <16>;
+ };
+};
+
+/* Verdin I2C_4 CSI */
+&main_i2c3 {
+ status = "okay";
+
+ ivy_adc1: adc@40 {
+ compatible = "ti,ads1119";
+ reg = <0x40>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_7>;
+ interrupt-parent = <&main_gpio0>;
+ interrupts = <41 IRQ_TYPE_EDGE_FALLING>;
+ avdd-supply = <&reg_3v2_ain1>;
+ dvdd-supply = <&reg_3v2_ain1>;
+ vref-supply = <&reg_3v2_ain1>;
+ #address-cells = <1>;
+ #io-channel-cells = <1>;
+ #size-cells = <0>;
+
+ /* AIN1 0-33V Voltage Input */
+ channel@0 {
+ reg = <0>;
+ diff-channels = <0 1>;
+ };
+
+ /* AIN1 0-20mA Current Input */
+ channel@1 {
+ reg = <1>;
+ diff-channels = <2 3>;
+ };
+ };
+
+ ivy_adc2: adc@41 {
+ compatible = "ti,ads1119";
+ reg = <0x41>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_8>;
+ interrupt-parent = <&main_gpio0>;
+ interrupts = <42 IRQ_TYPE_EDGE_FALLING>;
+ avdd-supply = <&reg_3v2_ain2>;
+ dvdd-supply = <&reg_3v2_ain2>;
+ vref-supply = <&reg_3v2_ain2>;
+ #address-cells = <1>;
+ #io-channel-cells = <1>;
+ #size-cells = <0>;
+
+ /* AIN2 0-33V Voltage Input */
+ channel@0 {
+ reg = <0>;
+ diff-channels = <0 1>;
+ };
+
+ /* AIN2 0-20mA Current Input */
+ channel@1 {
+ reg = <1>;
+ diff-channels = <2 3>;
+ };
+ };
+};
+
+/* Verdin CAN_1 */
+&main_mcan0 {
+ status = "okay";
+};
+
+/* Verdin SPI_1 */
+&main_spi1 {
+ pinctrl-0 = <&pinctrl_spi1>,
+ <&pinctrl_spi1_cs0>,
+ <&pinctrl_gpio_1>,
+ <&pinctrl_gpio_4>;
+ cs-gpios = <0>,
+ <&mcu_gpio0 1 GPIO_ACTIVE_LOW>,
+ <&mcu_gpio0 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ tpm@1 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <1>;
+ spi-max-frequency = <18500000>;
+ };
+
+ fram@2 {
+ compatible = "fujitsu,mb85rs256", "atmel,at25";
+ reg = <2>;
+ address-width = <16>;
+ size = <32768>;
+ spi-max-frequency = <33000000>;
+ pagesize = <1>;
+ };
+};
+
+/* Verdin UART_3 */
+&main_uart0 {
+ status = "okay";
+};
+
+/* Verdin UART_1 */
+&main_uart1 {
+ status = "okay";
+};
+
+&mcu_gpio0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_2>,
+ <&pinctrl_gpio_3>,
+ <&pinctrl_pcie_1_reset>;
+ gpio-line-names =
+ "",
+ "",
+ "GPIO2", /* Verdin GPIO_2 - SODIMM 208 */
+ "GPIO3", /* Verdin GPIO_3 - SODIMM 210 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "";
+};
+
+/* Verdin CAN_2 */
+&mcu_mcan0 {
+ status = "okay";
+};
+
+/* Verdin SD_1 */
+&sdhci1 {
+ status = "okay";
+};
+
+/* Verdin USB_1*/
+&usbss0 {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+/* Verdin USB_2 */
+&usbss1 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+/* Verdin PCIE_1_RESET# */
+&verdin_pcie_1_reset_hog {
+ status = "okay";
+};
+
+/* Verdin UART_2 */
+&wkup_uart0 {
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-active-low;
+ rs485-rx-during-tx;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
index 5bef31b8577b..1ea8f64b1b3b 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
@@ -160,7 +160,7 @@
regulator-max-microvolt = <3300000>;
regulator-min-microvolt = <3300000>;
regulator-name = "+V3.3_SD";
- startup-delay-us = <2000>;
+ startup-delay-us = <20000>;
};
reg_sdhc1_vqmmc: regulator-sdhci1-vqmmc {
@@ -1131,6 +1131,11 @@
};
};
+ tpm@2e {
+ compatible = "st,st33ktpm2xi2c", "tcg,tpm-tis-i2c";
+ reg = <0x2e>;
+ };
+
pmic@30 {
compatible = "ti,tps65219";
reg = <0x30>;
@@ -1219,11 +1224,12 @@
reg = <0x48>;
};
- adc@49 {
- compatible = "ti,ads1015";
+ verdin_som_adc: adc@49 {
+ compatible = "ti,tla2024";
reg = <0x49>;
#address-cells = <1>;
#size-cells = <0>;
+ #io-channel-cells = <1>;
/* Verdin PMIC_I2C (ADC_4 - ADC_3) */
channel@0 {
diff --git a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
index e0afafd532a5..9b8a1f85aa15 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
@@ -8,9 +8,9 @@
#include <dt-bindings/bus/ti-sysc.h>
&cbass_wakeup {
- wkup_conf: syscon@43000000 {
+ wkup_conf: bus@43000000 {
bootph-all;
- compatible = "syscon", "simple-mfd";
+ compatible = "simple-bus";
reg = <0x00 0x43000000 0x00 0x20000>;
#address-cells = <1>;
#size-cells = <1>;
@@ -22,6 +22,11 @@
reg = <0x14 0x4>;
};
+ opp_efuse_table: syscon@18 {
+ compatible = "ti,am62-opp-efuse-table", "syscon";
+ reg = <0x18 0x4>;
+ };
+
cpsw_mac_syscon: ethernet-mac-syscon@200 {
compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
reg = <0x200 0x8>;
diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
index a1cd47d7f5e3..ee96f4f6deb0 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
@@ -419,6 +419,12 @@
>;
};
+ mikrobus_pwm_pins_default: mikrobus-pwm-default-pins {
+ pinctrl-single,pins = <
+ AM62X_IOPAD(0x01a4, PIN_INPUT, 2) /* (B20) MCASP0_ACLKX.ECAP2_IN_APWM_OUT */
+ >;
+ };
+
main_uart0_pins_default: main-uart0-default-pins {
bootph-all;
pinctrl-single,pins = <
@@ -926,3 +932,9 @@
0 0 0 0
>;
};
+
+&ecap2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mikrobus_pwm_pins_default>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-1-4-ghz-opp.dtso b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-1-4-ghz-opp.dtso
deleted file mode 100644
index 6ec6d57ec49c..000000000000
--- a/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-1-4-ghz-opp.dtso
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only OR MIT
-/*
- * Copyright (C) 2024 PHYTEC America LLC
- * Author: Nathan Morrisson <nmorrisson@phytec.com>
- */
-
-/dts-v1/;
-/plugin/;
-
-&vdd_core {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <850000>;
-};
-
-&a53_opp_table {
- opp-1400000000 {
- opp-hz = /bits/ 64 <1400000000>;
- opp-supported-hw = <0x01 0x0004>;
- };
-};
diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-ivy.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-ivy.dts
new file mode 100644
index 000000000000..48798bf3da4f
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-ivy.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ *
+ * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62
+ * https://www.toradex.com/products/carrier-board/ivy-carrier-board
+ */
+
+/dts-v1/;
+
+#include "k3-am625.dtsi"
+#include "k3-am62-verdin.dtsi"
+#include "k3-am62-verdin-nonwifi.dtsi"
+#include "k3-am62-verdin-ivy.dtsi"
+
+/ {
+ model = "Toradex Verdin AM62 on Ivy Board";
+ compatible = "toradex,verdin-am62-nonwifi-ivy",
+ "toradex,verdin-am62-nonwifi",
+ "toradex,verdin-am62",
+ "ti,am625";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-ivy.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-ivy.dts
new file mode 100644
index 000000000000..d96d8a0ebd86
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-ivy.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2024 Toradex
+ *
+ * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62
+ * https://www.toradex.com/products/carrier-board/ivy-carrier-board
+ */
+
+/dts-v1/;
+
+#include "k3-am625.dtsi"
+#include "k3-am62-verdin.dtsi"
+#include "k3-am62-verdin-wifi.dtsi"
+#include "k3-am62-verdin-ivy.dtsi"
+
+/ {
+ model = "Toradex Verdin AM62 WB on Ivy Board";
+ compatible = "toradex,verdin-am62-wifi-ivy",
+ "toradex,verdin-am62-wifi",
+ "toradex,verdin-am62",
+ "ti,am625";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am625.dtsi b/arch/arm64/boot/dts/ti/k3-am625.dtsi
index c3d1db47dc9f..c249883a8a8d 100644
--- a/arch/arm64/boot/dts/ti/k3-am625.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am625.dtsi
@@ -108,7 +108,7 @@
a53_opp_table: opp-table {
compatible = "operating-points-v2-ti-cpu";
opp-shared;
- syscon = <&wkup_conf>;
+ syscon = <&opp_efuse_table>;
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
index 16a578ae2b41..a93e2cd7b8c7 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
@@ -943,6 +943,33 @@
status = "disabled";
};
+ eqep0: counter@23200000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23200000 0x00 0x100>;
+ power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 59 0>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep1: counter@23210000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23210000 0x00 0x100>;
+ power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 60 0>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep2: counter@23220000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23220000 0x00 0x100>;
+ power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 62 0>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
mcasp0: audio-controller@2b00000 {
compatible = "ti,am33xx-mcasp-audio";
reg = <0x00 0x02b00000 0x00 0x2000>,
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
index f5ac101a04df..0b1dd5390cd3 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
@@ -17,6 +17,11 @@
reg = <0x14 0x4>;
};
+ opp_efuse_table: syscon@18 {
+ compatible = "ti,am62-opp-efuse-table", "syscon";
+ reg = <0x18 0x4>;
+ };
+
cpsw_mac_syscon: ethernet-mac-syscon@200 {
compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
reg = <0x200 0x8>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-phyboard-lyra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-phyboard-lyra-rdk.dts
index 3b93409b23e7..77e5fef618ba 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-phyboard-lyra-rdk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-phyboard-lyra-rdk.dts
@@ -16,3 +16,7 @@
"phytec,am62a-phycore-som", "ti,am62a7";
model = "PHYTEC phyBOARD-Lyra AM62A7";
};
+
+&cpsw3g_phy3 {
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
index 67faf46d7a35..a6f0d87a50d8 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
@@ -68,6 +68,15 @@
};
};
+ opp-table {
+ /* Requires VDD_CORE at 0v85 */
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-supported-hw = <0x01 0x0004>;
+ clock-latency-ns = <6000000>;
+ };
+ };
+
vmain_pd: regulator-0 {
/* TPS25750 PD CONTROLLER OUTPUT */
compatible = "regulator-fixed";
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7.dtsi b/arch/arm64/boot/dts/ti/k3-am62a7.dtsi
index f86a23404e6d..6c99221beb6b 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a7.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 = <&opp_efuse_table>;
+
+ 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-am62p-j722s-common-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
index 9b6f51379108..41e1c24b1144 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi
@@ -827,6 +827,33 @@
status = "disabled";
};
+ eqep0: counter@23200000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23200000 0x00 0x100>;
+ power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 59 0>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep1: counter@23210000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23210000 0x00 0x100>;
+ power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 60 0>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep2: counter@23220000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23220000 0x00 0x100>;
+ power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 62 0>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
main_mcan0: can@20701000 {
compatible = "bosch,m_can";
reg = <0x00 0x20701000 0x00 0x200>,
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi
index 315d0092e736..6f32135f00a5 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-wakeup.dtsi
@@ -20,6 +20,11 @@
bootph-all;
};
+ opp_efuse_table: syscon@18 {
+ compatible = "ti,am62-opp-efuse-table", "syscon";
+ reg = <0x18 0x4>;
+ };
+
cpsw_mac_syscon: ethernet-mac-syscon@200 {
compatible = "ti,am62p-cpsw-mac-efuse", "syscon";
reg = <0x200 0x8>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
index 3efa12bb7254..7f3dc39e12bc 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
@@ -128,6 +128,15 @@
};
};
+ opp-table {
+ /* Requires VDD_CORE at 0v85 */
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-supported-hw = <0x01 0x0004>;
+ clock-latency-ns = <6000000>;
+ };
+ };
+
tlv320_mclk: clk-0 {
#clock-cells = <0>;
compatible = "fixed-clock";
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5.dtsi b/arch/arm64/boot/dts/ti/k3-am62p5.dtsi
index 41f479dca455..140587d02e88 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p5.dtsi
@@ -47,6 +47,7 @@
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>;
};
@@ -62,6 +63,7 @@
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>;
};
@@ -77,6 +79,7 @@
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>;
};
@@ -92,10 +95,54 @@
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 = <&opp_efuse_table>;
+
+ 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;
+ };
+ };
+
l2_0: l2-cache0 {
compatible = "cache";
cache-unified;
diff --git a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
index e4633af87eb9..d364c247833f 100644
--- a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra.dtsi
@@ -82,8 +82,8 @@
};
sound_master: simple-audio-card,codec {
- sound-dai = <&audio_codec>;
- clocks = <&audio_refclk1>;
+ sound-dai = <&audio_codec>;
+ clocks = <&audio_refclk1>;
};
};
@@ -433,8 +433,6 @@
0 0 0 0
0 0 0 0
>;
- tx-num-evt = <32>;
- rx-num-evt = <32>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
index 44ff67b6bf1e..6957b3e44c82 100644
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
@@ -56,6 +56,18 @@
linux,cma-default;
};
+ mcu_m4fss_dma_memory_region: m4f-dma-memory@9cb00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0x9cb00000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_m4fss_memory_region: m4f-memory@9cc00000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0x9cc00000 0x00 0xe00000>;
+ no-map;
+ };
+
secure_tfa_ddr: tfa@9e780000 {
reg = <0x00 0x9e780000 0x00 0x80000>;
alignment = <0x1000>;
@@ -464,6 +476,13 @@
};
};
+&mcu_m4fss {
+ mboxes = <&mailbox0_cluster0 &mbox_m4_0>;
+ memory-region = <&mcu_m4fss_dma_memory_region>,
+ <&mcu_m4fss_memory_region>;
+ status = "okay";
+};
+
&usbss0 {
bootph-all;
status = "okay";
diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
index 7eae18399caa..c66289a4362b 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
@@ -1175,6 +1175,33 @@
status = "disabled";
};
+ eqep0: counter@23200000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23200000 0x00 0x100>;
+ power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 59 0>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep1: counter@23210000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23210000 0x00 0x100>;
+ power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 60 0>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ eqep2: counter@23220000 {
+ compatible = "ti,am62-eqep";
+ reg = <0x00 0x23220000 0x00 0x100>;
+ power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 62 0>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
main_rti0: watchdog@e000000 {
compatible = "ti,j7-rti-wdt";
reg = <0x00 0xe000000 0x00 0x100>;
@@ -1261,6 +1288,11 @@
reg = <0x33000 0x1000>;
};
+ icssg0_pa_stats: pa-stats@2c000 {
+ compatible = "ti,pruss-pa-st", "syscon";
+ reg = <0x2c000 0x1000>;
+ };
+
icssg0_intc: interrupt-controller@20000 {
compatible = "ti,icssg-intc";
reg = <0x20000 0x2000>;
@@ -1426,6 +1458,11 @@
reg = <0x33000 0x1000>;
};
+ icssg1_pa_stats: pa-stats@2c000 {
+ compatible = "ti,pruss-pa-st", "syscon";
+ reg = <0x2c000 0x1000>;
+ };
+
icssg1_intc: interrupt-controller@20000 {
compatible = "ti,icssg-intc";
reg = <0x20000 0x2000>;
diff --git a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
index ad4bed5d3f9e..a243c981e853 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
@@ -161,4 +161,17 @@
/* Interrupt sources: esm0_cfg, esm0_hi, esm0_low, mrti0 */
ti,esm-pins = <0>, <1>, <2>, <85>;
};
+
+ mcu_m4fss: m4fss@5000000 {
+ compatible = "ti,am64-m4fss";
+ reg = <0x00 0x5000000 0x00 0x30000>,
+ <0x00 0x5040000 0x00 0x10000>;
+ reg-names = "iram", "dram";
+ resets = <&k3_reset 9 1>;
+ firmware-name = "am64-mcu-m4f0_0-fw";
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <9>;
+ ti,sci-proc-ids = <0x18 0xff>;
+ status = "disabled";
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
index 6bece2fb4e95..99a6fdfaa7fb 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi
@@ -87,6 +87,18 @@
reg = <0x00 0xa3100000 0x00 0xf00000>;
no-map;
};
+
+ mcu_m4fss_dma_memory_region: m4f-dma-memory@a4000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_m4fss_memory_region: m4f-memory@a4100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4100000 0x00 0xf00000>;
+ no-map;
+ };
};
leds {
@@ -240,6 +252,15 @@
};
};
+&mailbox0_cluster6 {
+ status = "okay";
+
+ mbox_m4_0: mbox-m4-0 {
+ ti,mbox-rx = <0 0 2>;
+ ti,mbox-tx = <1 0 2>;
+ };
+};
+
&main_i2c0 {
status = "okay";
pinctrl-names = "default";
@@ -333,6 +354,13 @@
<&main_r5fss1_core1_memory_region>;
};
+&mcu_m4fss {
+ mboxes = <&mailbox0_cluster6 &mbox_m4_0>;
+ memory-region = <&mcu_m4fss_dma_memory_region>,
+ <&mcu_m4fss_memory_region>;
+ status = "okay";
+};
+
&ospi0 {
status = "okay";
pinctrl-names = "default";
@@ -354,7 +382,6 @@
&sdhci0 {
status = "okay";
- bus-width = <8>;
non-removable;
ti,driver-strength-ohm = <50>;
disable-wp;
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm-pcie0-ep.dtso b/arch/arm64/boot/dts/ti/k3-am642-evm-pcie0-ep.dtso
new file mode 100644
index 000000000000..6b029539e0db
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm-pcie0-ep.dtso
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/**
+ * DT Overlay for enabling PCIE0 instance in Endpoint Configuration with the
+ * AM642 EVM.
+ *
+ * AM642 EVM Product Link: https://www.ti.com/tool/TMDS64EVM
+ *
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+#include "k3-pinctrl.h"
+
+/*
+ * Since Root Complex and Endpoint modes are mutually exclusive
+ * disable Root Complex mode.
+ */
+&pcie0_rc {
+ status = "disabled";
+};
+
+&cbass_main {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&gic500>;
+
+ pcie0_ep: pcie-ep@f102000 {
+ compatible = "ti,am64-pcie-ep", "ti,j721e-pcie-ep";
+ reg = <0x00 0x0f102000 0x00 0x1000>,
+ <0x00 0x0f100000 0x00 0x400>,
+ <0x00 0x0d000000 0x00 0x00800000>,
+ <0x00 0x68000000 0x00 0x08000000>;
+ reg-names = "intd_cfg", "user_cfg", "reg", "mem";
+ interrupt-names = "link_state";
+ interrupts = <GIC_SPI 203 IRQ_TYPE_EDGE_RISING>;
+ max-link-speed = <2>;
+ num-lanes = <1>;
+ power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 114 0>;
+ clock-names = "fck";
+ max-functions = /bits/ 8 <1>;
+ phys = <&serdes0_pcie_link>;
+ phy-names = "pcie-phy";
+ ti,syscon-pcie-ctrl = <&main_conf 0x4070>;
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
index 97ca16f00cd2..f8ec40523254 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
@@ -101,6 +101,18 @@
no-map;
};
+ mcu_m4fss_dma_memory_region: m4f-dma-memory@a4000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_m4fss_memory_region: m4f-memory@a4100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4100000 0x00 0xf00000>;
+ no-map;
+ };
+
rtos_ipc_memory_region: ipc-memories@a5000000 {
reg = <0x00 0xa5000000 0x00 0x00800000>;
alignment = <0x1000>;
@@ -253,6 +265,7 @@
ti,mii-g-rt = <&icssg1_mii_g_rt>;
ti,mii-rt = <&icssg1_mii_rt>;
ti,iep = <&icssg1_iep0>, <&icssg1_iep1>;
+ ti,pa-stats = <&icssg1_pa_stats>;
interrupt-parent = <&icssg1_intc>;
interrupts = <24 0 2>, <25 1 3>;
interrupt-names = "tx_ts0", "tx_ts1";
@@ -450,7 +463,7 @@
>;
};
- icssg1_rgmii1_pins_default: icssg1-rgmii1-default-pins{
+ icssg1_rgmii1_pins_default: icssg1-rgmii1-default-pins {
pinctrl-single,pins = <
AM64X_IOPAD(0x00b8, PIN_INPUT, 2) /* (Y7) PRG1_PRU0_GPO0.PRG1_RGMII1_RD0 */
AM64X_IOPAD(0x00bc, PIN_INPUT, 2) /* (U8) PRG1_PRU0_GPO1.PRG1_RGMII1_RD1 */
@@ -776,6 +789,13 @@
<&main_r5fss1_core1_memory_region>;
};
+&mcu_m4fss {
+ mboxes = <&mailbox0_cluster6 &mbox_m4_0>;
+ memory-region = <&mcu_m4fss_dma_memory_region>,
+ <&mcu_m4fss_memory_region>;
+ status = "okay";
+};
+
&serdes_ln_ctrl {
idle-states = <AM64_SERDES0_LANE0_PCIE0>;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
index 60285d736e07..bc8e1ce11047 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts
@@ -344,6 +344,10 @@
};
};
+&i2c_som_rtc {
+ trickle-resistor-ohms = <3000>;
+};
+
&main_i2c1 {
status = "okay";
pinctrl-names = "default";
@@ -423,7 +427,6 @@
vmmc-supply = <&vcc_3v3_mmc>;
pinctrl-names = "default";
pinctrl-0 = <&main_mmc1_pins_default>;
- bus-width = <4>;
disable-wp;
no-1-8-v;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
index 86369525259c..33e421ec18ab 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
@@ -99,6 +99,18 @@
no-map;
};
+ mcu_m4fss_dma_memory_region: m4f-dma-memory@a4000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_m4fss_memory_region: m4f-memory@a4100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4100000 0x00 0xf00000>;
+ no-map;
+ };
+
rtos_ipc_memory_region: ipc-memories@a5000000 {
reg = <0x00 0xa5000000 0x00 0x00800000>;
alignment = <0x1000>;
@@ -357,6 +369,16 @@
AM64X_IOPAD(0x0270, PIN_INPUT, 0) /* (D18) ECAP0_IN_APWM_OUT */
>;
};
+
+ main_eqep0_pins_default: main-eqep0-default-pins {
+ pinctrl-single,pins = <
+ AM64X_IOPAD(0x00a0, PIN_INPUT, 3) /* (N16) GPMC0_WPn.EQEP0_A */
+ AM64X_IOPAD(0x00a4, PIN_INPUT, 3) /* (N17) GPMC0_DIR.EQEP0_B */
+ AM64X_IOPAD(0x00ac, PIN_INPUT, 3) /* (R20) GPMC0_CSn1.EQEP0_I */
+ AM64X_IOPAD(0x00a8, PIN_INPUT, 3) /* (R19) GPMC0_CSn0.EQEP0_S */
+ >;
+ };
+
main_wlan_en_pins_default: main-wlan-en-default-pins {
pinctrl-single,pins = <
AM64X_IOPAD(0x00c4, PIN_OUTPUT_PULLUP, 7) /* (V8) GPIO0_48 */
@@ -681,9 +703,23 @@
<&main_r5fss1_core1_memory_region>;
};
+&mcu_m4fss {
+ mboxes = <&mailbox0_cluster6 &mbox_m4_0>;
+ memory-region = <&mcu_m4fss_dma_memory_region>,
+ <&mcu_m4fss_memory_region>;
+ status = "okay";
+};
+
&ecap0 {
status = "okay";
/* PWM is available on Pin 1 of header J3 */
pinctrl-names = "default";
pinctrl-0 = <&main_ecap0_pins_default>;
};
+
+&eqep0 {
+ status = "okay";
+ /* EQEP0 A & B available on pins 18 & 22 of J4 header */
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_eqep0_pins_default>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index 1f1af7ea2330..94a812a1355b 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -1167,6 +1167,11 @@
reg = <0x33000 0x1000>;
};
+ icssg0_pa_stats: pa-stats@2c000 {
+ compatible = "ti,pruss-pa-st", "syscon";
+ reg = <0x2c000 0x1000>;
+ };
+
icssg0_intc: interrupt-controller@20000 {
compatible = "ti,icssg-intc";
reg = <0x20000 0x2000>;
@@ -1333,6 +1338,11 @@
reg = <0x33000 0x1000>;
};
+ icssg1_pa_stats: pa-stats@2c000 {
+ compatible = "ti,pruss-pa-st", "syscon";
+ reg = <0x2c000 0x1000>;
+ };
+
icssg1_intc: interrupt-controller@20000 {
compatible = "ti,icssg-intc";
reg = <0x20000 0x2000>;
@@ -1499,6 +1509,11 @@
reg = <0x33000 0x1000>;
};
+ icssg2_pa_stats: pa-stats@2c000 {
+ compatible = "ti,pruss-pa-st", "syscon";
+ reg = <0x2c000 0x1000>;
+ };
+
icssg2_intc: interrupt-controller@20000 {
compatible = "ti,icssg-intc";
reg = <0x20000 0x2000>;
diff --git a/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso b/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso
index 0a6e75265ba9..66bb0b913d49 100644
--- a/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso
+++ b/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso
@@ -41,6 +41,7 @@
ti,mii-g-rt = <&icssg2_mii_g_rt>;
ti,mii-rt = <&icssg2_mii_rt>;
+ ti,pa-stats = <&icssg2_pa_stats>;
ti,iep = <&icssg2_iep0>, <&icssg2_iep1>;
interrupt-parent = <&icssg2_intc>;
diff --git a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso
index b0ce2cb2fdc8..6cb44dae9f90 100644
--- a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso
+++ b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso
@@ -43,6 +43,7 @@
ti,mii-g-rt = <&icssg0_mii_g_rt>;
ti,mii-rt = <&icssg0_mii_rt>;
+ ti,pa-stats = <&icssg0_pa_stats>;
ti,iep = <&icssg0_iep0>, <&icssg0_iep1>;
interrupt-parent = <&icssg0_intc>;
@@ -109,6 +110,7 @@
ti,mii-g-rt = <&icssg1_mii_g_rt>;
ti,mii-rt = <&icssg1_mii_rt>;
+ ti,pa-stats = <&icssg1_pa_stats>;
ti,iep = <&icssg1_iep0>, <&icssg1_iep1>;
interrupt-parent = <&icssg1_intc>;
diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
index d5ceab79536c..11522b36e0ce 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
@@ -184,6 +184,7 @@
J721S2_IOPAD(0x0d0, PIN_INPUT, 11) /* (AF26) SPI0_CS1.UART8_RXD */
J721S2_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AH27) SPI0_CLK.UART8_TXD */
>;
+ bootph-all;
};
main_i2c0_pins_default: main-i2c0-default-pins {
@@ -211,6 +212,7 @@
J721S2_IOPAD(0x0f0, PIN_INPUT, 0) /* (R22) MMC1_DAT3 */
J721S2_IOPAD(0x0e8, PIN_INPUT, 8) /* (AE25) TIMER_IO0.MMC1_SDCD */
>;
+ bootph-all;
};
vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
@@ -313,6 +315,7 @@
J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (D28) WKUP_UART0_RXD */
J721S2_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (D27) WKUP_UART0_TXD */
>;
+ bootph-all;
};
mcu_cpsw_pins_default: mcu-cpsw-default-pins {
@@ -372,6 +375,7 @@
J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C24) WKUP_GPIO0_13.MCU_UART0_RXD */
J721S2_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (C25) WKUP_GPIO0_12.MCU_UART0_TXD */
>;
+ bootph-all;
};
mcu_rpi_header_gpio0_pins0_default: mcu-rpi-header-gpio0-default-pins-0 {
@@ -413,6 +417,7 @@
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&wkup_uart0_pins_default>;
+ bootph-all;
};
&wkup_i2c0 {
@@ -495,6 +500,7 @@
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_uart0_pins_default>;
+ bootph-all;
};
&main_uart8 {
@@ -503,6 +509,7 @@
pinctrl-0 = <&main_uart8_pins_default>;
/* Shared with TFA on this platform */
power-domains = <&k3_pds 357 TI_SCI_PD_SHARED>;
+ bootph-all;
};
&main_i2c0 {
@@ -597,6 +604,7 @@
disable-wp;
vmmc-supply = <&vdd_mmc1>;
vqmmc-supply = <&vdd_sd_dv>;
+ bootph-all;
};
&mcu_cpsw {
diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
index 5bc0d2fb4b8f..4ca2d4e2fb9b 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
@@ -156,6 +156,7 @@
J721S2_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (H24) WKUP_I2C0_SCL */
J721S2_WKUP_IOPAD(0x09c, PIN_INPUT, 0) /* (H27) WKUP_I2C0_SDA */
>;
+ bootph-all;
};
};
@@ -169,6 +170,7 @@
/* AT24C512C-MAHM-T */
compatible = "atmel,24c512";
reg = <0x51>;
+ bootph-all;
};
};
@@ -190,7 +192,6 @@
cdns,read-delay = <4>;
partitions {
- bootph-all;
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
@@ -226,9 +227,9 @@
};
partition@3fc0000 {
- bootph-pre-ram;
label = "ospi.phypattern";
reg = <0x3fc0000 0x40000>;
+ bootph-all;
};
};
};
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 6593c5da82c0..db43e7e10b76 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
@@ -129,6 +129,7 @@
J721E_WKUP_IOPAD(0x8c, PIN_INPUT, 0) /* (D20) MCU_UART0_RXD */
J721E_WKUP_IOPAD(0x88, PIN_OUTPUT, 0) /* (D19) MCU_UART0_TXD */
>;
+ bootph-all;
};
wkup_uart0_pins_default: wkup-uart0-default-pins {
@@ -136,6 +137,7 @@
J721E_WKUP_IOPAD(0x48, PIN_INPUT, 0) /* (B14) WKUP_UART0_RXD */
J721E_WKUP_IOPAD(0x4c, PIN_OUTPUT, 0) /* (A14) WKUP_UART0_TXD */
>;
+ bootph-all;
};
mcu_cpsw_pins_default: mcu-cpsw-default-pins {
@@ -204,6 +206,7 @@
J721E_IOPAD(0xc0, PIN_INPUT, 2) /* (W3) SPI0_CS0.UART0_CTSn */
J721E_IOPAD(0xc4, PIN_OUTPUT, 2) /* (U5) SPI0_CS1.UART0_RTSn */
>;
+ bootph-all;
};
main_uart1_pins_default: main-uart1-default-pins {
@@ -238,6 +241,7 @@
J721E_IOPAD(0xec, PIN_INPUT, 0) /* (N19) MMC1_DAT3 */
J721E_IOPAD(0xe4, PIN_INPUT, 8) /* (V1) TIMER_IO0.MMC1_SDCD */
>;
+ bootph-all;
};
vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
@@ -254,11 +258,12 @@
};
};
-&main_pmx1 {
+&main_pmx2 {
main_usbss0_pins_default: main-usbss0-default-pins {
pinctrl-single,pins = <
J721E_IOPAD(0x04, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS */
>;
+ bootph-all;
};
};
@@ -267,12 +272,14 @@
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&wkup_uart0_pins_default>;
+ bootph-all;
};
&mcu_uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_uart0_pins_default>;
+ bootph-all;
};
&main_uart0 {
@@ -281,6 +288,7 @@
power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
+ bootph-all;
};
&main_uart1 {
@@ -379,6 +387,7 @@
/* eMMC */
status = "okay";
non-removable;
+ bootph-all;
ti,driver-strength-ohm = <50>;
disable-wp;
};
@@ -390,6 +399,7 @@
pinctrl-names = "default";
vmmc-supply = <&vdd_mmc1>;
vqmmc-supply = <&vdd_sd_dv>;
+ bootph-all;
ti,driver-strength-ohm = <50>;
disable-wp;
};
@@ -401,11 +411,13 @@
&usb_serdes_mux {
idle-states = <1>; /* USB0 to SERDES lane 3 */
+ bootph-all;
};
&usbss0 {
pinctrl-names = "default";
pinctrl-0 = <&main_usbss0_pins_default>;
+ bootph-all;
ti,vbus-divider;
ti,usb2-only;
};
@@ -413,6 +425,7 @@
&usb0 {
dr_mode = "otg";
maximum-speed = "high-speed";
+ bootph-all;
};
&tscadc0 {
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-evm-pcie1-ep.dtso b/arch/arm64/boot/dts/ti/k3-j7200-evm-pcie1-ep.dtso
new file mode 100644
index 000000000000..3cc315a0e084
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j7200-evm-pcie1-ep.dtso
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/**
+ * DT Overlay for enabling PCIE1 instance in Endpoint Configuration with the
+ * J7 common processor board.
+ *
+ * J7 Common Processor Board Product Link: https://www.ti.com/tool/J721EXCPXEVM
+ *
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+#include "k3-pinctrl.h"
+
+/*
+ * Since Root Complex and Endpoint modes are mutually exclusive
+ * disable Root Complex mode.
+ */
+&pcie1_rc {
+ status = "disabled";
+};
+
+&cbass_main {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&gic500>;
+
+ pcie1_ep: pcie-ep@2910000 {
+ compatible = "ti,j7200-pcie-ep", "ti,j721e-pcie-ep";
+ reg = <0x00 0x02910000 0x00 0x1000>,
+ <0x00 0x02917000 0x00 0x400>,
+ <0x00 0x0d800000 0x00 0x00800000>,
+ <0x00 0x18000000 0x00 0x08000000>;
+ reg-names = "intd_cfg", "user_cfg", "reg", "mem";
+ interrupt-names = "link_state";
+ interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+ max-link-speed = <3>;
+ num-lanes = <2>;
+ power-domains = <&k3_pds 240 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 240 6>;
+ clock-names = "fck";
+ max-functions = /bits/ 8 <6>;
+ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
+ dma-coherent;
+ phys = <&serdes0_pcie_link>;
+ phy-names = "pcie-phy";
+ ti,syscon-pcie-ctrl = <&scm_conf 0x4074>;
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
index 9386bf3ef9f6..5ab510a0605f 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
@@ -136,6 +136,7 @@
<0x00 0x32800000 0x00 0x100000>;
interrupt-names = "rx_011";
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ bootph-all;
};
hwspinlock: spinlock@30e00000 {
@@ -426,10 +427,28 @@
pinctrl-single,function-mask = <0xffffffff>;
};
- main_pmx1: pinctrl@11c11c {
+ main_pmx1: pinctrl@11c110 {
compatible = "ti,j7200-padconf", "pinctrl-single";
/* Proxy 0 addressing */
- reg = <0x00 0x11c11c 0x00 0xc>;
+ reg = <0x00 0x11c110 0x00 0x004>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0xffffffff>;
+ };
+
+ main_pmx2: pinctrl@11c11c {
+ compatible = "ti,j7200-padconf", "pinctrl-single";
+ /* Proxy 0 addressing */
+ reg = <0x00 0x11c11c 0x00 0x00c>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0xffffffff>;
+ };
+
+ main_pmx3: pinctrl@11c164 {
+ compatible = "ti,j7200-padconf", "pinctrl-single";
+ /* Proxy 0 addressing */
+ reg = <0x00 0x11c164 0x00 0x008>;
#pinctrl-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0xffffffff>;
@@ -1145,7 +1164,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 266 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 266 1>;
+ clocks = <&k3_clks 266 4>;
status = "disabled";
};
@@ -1156,7 +1175,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 267 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 267 1>;
+ clocks = <&k3_clks 267 4>;
status = "disabled";
};
@@ -1167,7 +1186,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 268 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 268 1>;
+ clocks = <&k3_clks 268 4>;
status = "disabled";
};
@@ -1178,7 +1197,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 269 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 269 1>;
+ clocks = <&k3_clks 269 4>;
status = "disabled";
};
@@ -1189,7 +1208,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 270 1>;
+ clocks = <&k3_clks 270 2>;
status = "disabled";
};
@@ -1200,7 +1219,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 271 1>;
+ clocks = <&k3_clks 271 4>;
status = "disabled";
};
@@ -1211,7 +1230,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 272 1>;
+ clocks = <&k3_clks 272 4>;
status = "disabled";
};
@@ -1222,7 +1241,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 273 1>;
+ clocks = <&k3_clks 273 4>;
status = "disabled";
};
@@ -1527,6 +1546,7 @@
main_esm: esm@700000 {
compatible = "ti,j721e-esm";
reg = <0x0 0x700000 0x0 0x1000>;
+ bootph-pre-ram;
ti,esm-pins = <656>, <657>;
};
};
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 5097d192c2b2..6a8453865874 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
@@ -21,16 +21,19 @@
k3_pds: power-controller {
compatible = "ti,sci-pm-domain";
#power-domain-cells = <2>;
+ bootph-all;
};
k3_clks: clock-controller {
compatible = "ti,k2g-sci-clk";
#clock-cells = <2>;
+ bootph-all;
};
k3_reset: reset-controller {
compatible = "ti,sci-reset";
#reset-cells = <2>;
+ bootph-all;
};
};
@@ -44,6 +47,7 @@
assigned-clocks = <&k3_clks 35 1>;
assigned-clock-parents = <&k3_clks 35 2>;
power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+ bootph-pre-ram;
ti,timer-pwm;
};
@@ -191,6 +195,7 @@
chipid: chipid@14 {
compatible = "ti,am654-chipid";
reg = <0x14 0x4>;
+ bootph-all;
};
};
@@ -344,6 +349,7 @@
<0x00 0x28440000 0x00 0x40000>;
reg-names = "rt", "fifos", "proxy_gcfg",
"proxy_target", "cfg";
+ bootph-all;
ti,num-rings = <286>;
ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */
ti,sci = <&dmsc>;
@@ -363,6 +369,7 @@
"tchan", "rchan", "rflow";
msi-parent = <&main_udmass_inta>;
#dma-cells = <1>;
+ bootph-all;
ti,sci = <&dmsc>;
ti,sci-dev-id = <236>;
@@ -383,6 +390,8 @@
reg = <0x0 0x2a480000 0x0 0x80000>,
<0x0 0x2a380000 0x0 0x80000>,
<0x0 0x2a400000 0x0 0x80000>;
+ bootph-pre-ram;
+
/*
* Marked Disabled:
* Node is incomplete as it is meant for bootloaders and
@@ -494,7 +503,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 274 0>;
+ clocks = <&k3_clks 274 4>;
status = "disabled";
};
@@ -505,7 +514,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 275 0>;
+ clocks = <&k3_clks 275 4>;
status = "disabled";
};
@@ -516,7 +525,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 276 0>;
+ clocks = <&k3_clks 276 2>;
status = "disabled";
};
@@ -534,6 +543,7 @@
reg = <0x00 0x47000004 0x00 0x4>;
#mux-control-cells = <1>;
mux-reg-masks = <0x0 0x2>; /* HBMC select */
+ bootph-all;
};
hbmc: hyperbus@47034000 {
@@ -652,6 +662,7 @@
<0x00 0x42050000 0x00 0x350>;
power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
#thermal-sensor-cells = <1>;
+ bootph-pre-ram;
};
mcu_esm: esm@40800000 {
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 e78b4622a7d1..291ab9bb414d 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
@@ -121,6 +121,7 @@
J721E_WKUP_IOPAD(0x24, PIN_INPUT, 1) /* (A8) MCU_OSPI0_D6.MCU_HYPERBUS0_DQ6 */
J721E_WKUP_IOPAD(0x28, PIN_INPUT, 1) /* (A7) MCU_OSPI0_D7.MCU_HYPERBUS0_DQ7 */
>;
+ bootph-all;
};
mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins {
@@ -137,6 +138,7 @@
J721E_WKUP_IOPAD(0x0028, PIN_INPUT, 0) /* MCU_OSPI0_D7 */
J721E_WKUP_IOPAD(0x0008, PIN_INPUT, 0) /* MCU_OSPI0_DQS */
>;
+ bootph-all;
};
};
@@ -146,6 +148,7 @@
J721E_WKUP_IOPAD(0x98, PIN_INPUT_PULLUP, 0) /* (F20) WKUP_I2C0_SCL */
J721E_WKUP_IOPAD(0x9c, PIN_INPUT_PULLUP, 0) /* (H21) WKUP_I2C0_SDA */
>;
+ bootph-all;
};
};
@@ -186,6 +189,7 @@
flash@0,0 {
compatible = "cypress,hyperflash", "cfi-flash";
reg = <0x00 0x00 0x4000000>;
+ bootph-all;
partitions {
compatible = "fixed-partitions";
@@ -347,6 +351,7 @@
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
+ bootph-all;
};
bucka2: buck2 {
@@ -520,6 +525,7 @@
partition@3fc0000 {
label = "ospi.phypattern";
reg = <0x3fc0000 0x40000>;
+ bootph-all;
};
};
};
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 8230d53cd696..4c1e02a4e7a2 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
@@ -193,6 +193,7 @@
J721E_IOPAD(0x1e8, PIN_INPUT, 0) /* (AB2) UART0_RXD */
J721E_IOPAD(0x1ec, PIN_OUTPUT, 0) /* (AB3) UART0_TXD */
>;
+ bootph-all;
};
main_uart1_pins_default: main-uart1-default-pins {
@@ -234,6 +235,7 @@
J721E_IOPAD(0x258, PIN_INPUT, 0) /* (P23) MMC1_SDCD */
J721E_IOPAD(0x25c, PIN_INPUT, 0) /* (R28) MMC1_SDWP */
>;
+ bootph-all;
};
vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-default-pins {
@@ -247,6 +249,7 @@
J721E_IOPAD(0x290, PIN_OUTPUT, 0) /* (U6) USB0_DRVVBUS */
J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 */
>;
+ bootph-all;
};
main_usbss1_pins_default: main-usbss1-default-pins {
@@ -342,6 +345,7 @@
J721E_WKUP_IOPAD(0xa0, PIN_INPUT, 0) /* (J29) WKUP_UART0_RXD */
J721E_WKUP_IOPAD(0xa4, PIN_OUTPUT, 0) /* (J28) WKUP_UART0_TXD */
>;
+ bootph-all;
};
mcu_uart0_pins_default: mcu-uart0-default-pins {
@@ -351,6 +355,7 @@
J721E_WKUP_IOPAD(0xe4, PIN_INPUT, 0) /* (H28) WKUP_GPIO0_13.MCU_UART0_RXD */
J721E_WKUP_IOPAD(0xe0, PIN_OUTPUT, 0) /* (G29) WKUP_GPIO0_12.MCU_UART0_TXD */
>;
+ bootph-all;
};
sw11_button_pins_default: sw11-button-default-pins {
@@ -370,6 +375,7 @@
J721E_WKUP_IOPAD(0x3c, PIN_INPUT, 0) /* (B23) MCU_OSPI1_DQS */
J721E_WKUP_IOPAD(0x38, PIN_INPUT, 0) /* (A23) MCU_OSPI1_LBCLKO */
>;
+ bootph-all;
};
mcu_cpsw_pins_default: mcu-cpsw-default-pins {
@@ -435,12 +441,14 @@
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&wkup_uart0_pins_default>;
+ bootph-all;
};
&mcu_uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_uart0_pins_default>;
+ bootph-all;
};
&main_uart0 {
@@ -449,6 +457,7 @@
pinctrl-0 = <&main_uart0_pins_default>;
/* Shared with ATF on this platform */
power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
+ bootph-all;
};
&main_uart1 {
@@ -487,6 +496,7 @@
/* eMMC */
status = "okay";
non-removable;
+ bootph-all;
ti,driver-strength-ohm = <50>;
disable-wp;
};
@@ -498,12 +508,14 @@
vqmmc-supply = <&vdd_sd_dv_alt>;
pinctrl-names = "default";
pinctrl-0 = <&main_mmc1_pins_default>;
+ bootph-all;
ti,driver-strength-ohm = <50>;
disable-wp;
};
&usb_serdes_mux {
idle-states = <1>, <0>; /* USB0 to SERDES3, USB1 to SERDES1 */
+ bootph-all;
};
&serdes_ln_ctrl {
@@ -513,6 +525,7 @@
<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>;
+ bootph-all;
};
&serdes_wiz3 {
@@ -533,6 +546,7 @@
&usbss0 {
pinctrl-names = "default";
pinctrl-0 = <&main_usbss0_pins_default>;
+ bootph-all;
ti,vbus-divider;
};
@@ -541,6 +555,7 @@
maximum-speed = "super-speed";
phys = <&serdes3_usb_link>;
phy-names = "cdns3,usb3-phy";
+ bootph-all;
};
&usbss1 {
@@ -613,6 +628,7 @@
partition@3fe0000 {
label = "qspi.phypattern";
reg = <0x3fe0000 0x20000>;
+ bootph-all;
};
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
index 0da785be80ff..af3d730154ac 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
@@ -226,6 +226,7 @@
<0x00 0x32800000 0x00 0x100000>;
interrupt-names = "rx_011";
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ bootph-all;
};
smmu0: iommu@36600000 {
@@ -2853,6 +2854,7 @@
main_esm: esm@700000 {
compatible = "ti,j721e-esm";
reg = <0x0 0x700000 0x0 0x1000>;
+ bootph-pre-ram;
ti,esm-pins = <344>, <345>;
};
};
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 3731ffb4a5c9..b02142b2b460 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
@@ -21,16 +21,19 @@
k3_pds: power-controller {
compatible = "ti,sci-pm-domain";
#power-domain-cells = <2>;
+ bootph-all;
};
k3_clks: clock-controller {
compatible = "ti,k2g-sci-clk";
#clock-cells = <2>;
+ bootph-all;
};
k3_reset: reset-controller {
compatible = "ti,sci-reset";
#reset-cells = <2>;
+ bootph-all;
};
};
@@ -61,6 +64,7 @@
chipid: chipid@14 {
compatible = "ti,am654-chipid";
reg = <0x14 0x4>;
+ bootph-all;
};
};
@@ -112,6 +116,7 @@
assigned-clocks = <&k3_clks 35 1>;
assigned-clock-parents = <&k3_clks 35 2>;
power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+ bootph-pre-ram;
ti,timer-pwm;
/* Non-MPU Firmware usage */
status = "reserved";
@@ -362,6 +367,7 @@
reg = <0x00 0x47000004 0x00 0x4>;
#mux-control-cells = <1>;
mux-reg-masks = <0x0 0x2>; /* HBMC select */
+ bootph-all;
};
hbmc: hyperbus@47034000 {
@@ -470,6 +476,7 @@
<0x0 0x2a500000 0x0 0x40000>,
<0x0 0x28440000 0x0 0x40000>;
reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target", "cfg";
+ bootph-all;
ti,num-rings = <286>;
ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */
ti,sci = <&dmsc>;
@@ -489,6 +496,7 @@
"tchan", "rchan", "rflow";
msi-parent = <&main_udmass_inta>;
#dma-cells = <1>;
+ bootph-all;
ti,sci = <&dmsc>;
ti,sci-dev-id = <236>;
@@ -509,6 +517,7 @@
reg = <0x0 0x2a480000 0x0 0x80000>,
<0x0 0x2a380000 0x0 0x80000>,
<0x0 0x2a400000 0x0 0x80000>;
+ bootph-pre-ram;
/*
* Marked Disabled:
* Node is incomplete as it is meant for bootloaders and
@@ -654,7 +663,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 274 0>;
+ clocks = <&k3_clks 274 1>;
status = "disabled";
};
@@ -665,7 +674,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 275 0>;
+ clocks = <&k3_clks 275 1>;
status = "disabled";
};
@@ -676,7 +685,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 276 0>;
+ clocks = <&k3_clks 276 1>;
status = "disabled";
};
@@ -687,6 +696,7 @@
<0x00 0x43000300 0x00 0x10>;
power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
#thermal-sensor-cells = <1>;
+ bootph-pre-ram;
};
mcu_esm: esm@40800000 {
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
index 6285e8d94dde..69b3d1ed8a21 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
@@ -346,6 +346,7 @@
J721E_IOPAD(0x240, PIN_INPUT, 0) /* (R26) MMC1_DAT3 */
J721E_IOPAD(0x258, PIN_INPUT, 0) /* (P23) MMC1_SDCD */
>;
+ bootph-all;
};
main_uart0_pins_default: main-uart0-default-pins {
@@ -355,6 +356,7 @@
J721E_IOPAD(0x1e8, PIN_INPUT, 0) /* (AB2) UART0_RXD */
J721E_IOPAD(0x1ec, PIN_OUTPUT, 0) /* (AB3) UART0_TXD */
>;
+ bootph-all;
};
main_uart1_pins_default: main-uart1-default-pins {
@@ -390,12 +392,14 @@
J721E_IOPAD(0x290, PIN_OUTPUT, 0) /* (U6) USB0_DRVVBUS */
J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 */
>;
+ bootph-all;
};
main_usbss1_pins_default: main-usbss1-default-pins {
pinctrl-single,pins = <
J721E_IOPAD(0x214, PIN_OUTPUT, 4) /* (V4) MCAN1_TX.USB1_DRVVBUS */
>;
+ bootph-all;
};
main_csi_mux_sel_pins_default: main-csi-mux-sel-default-pins {
@@ -594,6 +598,7 @@
J721E_WKUP_IOPAD(0x28, PIN_INPUT, 0) /* (G21) MCU_OSPI0_D7 */
J721E_WKUP_IOPAD(0x8, PIN_INPUT, 0) /* (D21) MCU_OSPI0_DQS */
>;
+ bootph-all;
};
vdd_mmc1_en_pins_default: vdd-mmc1-en-default-pins {
@@ -622,6 +627,7 @@
J721E_WKUP_IOPAD(0xe4, PIN_INPUT, 0) /* (H28) WKUP_GPIO0_13.MCU_UART0_RXD */
J721E_WKUP_IOPAD(0xe0, PIN_OUTPUT, 0)/* (G29) WKUP_GPIO0_12.MCU_UART0_TXD */
>;
+ bootph-all;
};
wkup_i2c0_pins_default: wkup-i2c0-default-pins {
@@ -629,6 +635,7 @@
J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */
J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */
>;
+ bootph-all;
};
mcu_mcan0_pins_default: mcu-mcan0-default-pins {
@@ -657,6 +664,7 @@
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&wkup_uart0_pins_default>;
+ bootph-all;
};
&wkup_i2c0 {
@@ -821,6 +829,7 @@
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_uart0_pins_default>;
+ bootph-all;
};
&main_uart0 {
@@ -829,6 +838,7 @@
pinctrl-0 = <&main_uart0_pins_default>;
/* Shared with ATF on this platform */
power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
+ bootph-all;
};
&main_uart1 {
@@ -844,6 +854,7 @@
vqmmc-supply = <&vdd_sd_dv_alt>;
pinctrl-names = "default";
pinctrl-0 = <&main_mmc1_pins_default>;
+ bootph-all;
ti,driver-strength-ohm = <50>;
disable-wp;
};
@@ -908,6 +919,7 @@
partition@3fc0000 {
label = "ospi.phypattern";
reg = <0x3fc0000 0x40000>;
+ bootph-all;
};
};
};
@@ -1003,6 +1015,7 @@
&usb_serdes_mux {
idle-states = <1>, <1>; /* USB0 to SERDES3, USB1 to SERDES2 */
+ bootph-all;
};
&serdes_ln_ctrl {
@@ -1012,6 +1025,7 @@
<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>;
+ bootph-all;
};
&serdes_wiz3 {
@@ -1050,6 +1064,7 @@
&usbss0 {
pinctrl-names = "default";
pinctrl-0 = <&main_usbss0_pins_default>;
+ bootph-all;
ti,vbus-divider;
};
@@ -1058,6 +1073,7 @@
maximum-speed = "super-speed";
phys = <&serdes3_usb_link>;
phy-names = "cdns3,usb3-phy";
+ bootph-all;
};
&serdes2 {
@@ -1073,6 +1089,7 @@
&usbss1 {
pinctrl-names = "default";
pinctrl-0 = <&main_usbss1_pins_default>;
+ bootph-all;
ti,vbus-divider;
};
@@ -1081,6 +1098,7 @@
maximum-speed = "super-speed";
phys = <&serdes2_usb_link>;
phy-names = "cdns3,usb3-phy";
+ bootph-all;
};
&mcu_cpsw {
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 cef47c67493f..0722f6361cc8 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
@@ -151,6 +151,7 @@
J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */
J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */
>;
+ bootph-all;
};
pmic_irq_pins_default: pmic-irq-default-pins {
@@ -173,6 +174,7 @@
J721E_WKUP_IOPAD(0x0028, PIN_INPUT, 0) /* MCU_OSPI0_D7 */
J721E_WKUP_IOPAD(0x002c, PIN_OUTPUT, 0) /* MCU_OSPI0_CSn0 */
>;
+ bootph-all;
};
mcu_fss0_hpb0_pins_default: mcu-fss0-hpb0-default-pins {
@@ -192,6 +194,7 @@
J721E_WKUP_IOPAD(0x24, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ6 */
J721E_WKUP_IOPAD(0x28, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ7 */
>;
+ bootph-all;
};
};
@@ -422,6 +425,7 @@
partition@3fe0000 {
label = "ospi.phypattern";
reg = <0x3fe0000 0x20000>;
+ bootph-all;
};
};
};
@@ -440,6 +444,7 @@
flash@0,0 {
compatible = "cypress,hyperflash", "cfi-flash";
reg = <0x00 0x00 0x4000000>;
+ bootph-all;
partitions {
compatible = "fixed-partitions";
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 c5a0b7cbb14f..e2fc1288ed07 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
@@ -138,6 +138,7 @@
J721S2_IOPAD(0x0d0, PIN_INPUT, 11) /* (AF26) SPI0_CS1.UART8_RXD */
J721S2_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AH27) SPI0_CLK.UART8_TXD */
>;
+ bootph-all;
};
main_i2c3_pins_default: main-i2c3-default-pins {
@@ -165,6 +166,7 @@
J721S2_IOPAD(0x0f0, PIN_INPUT, 0) /* (R22) MMC1_DAT3 */
J721S2_IOPAD(0x0e8, PIN_INPUT, 8) /* (AE25) TIMER_IO0.MMC1_SDCD */
>;
+ bootph-all;
};
vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
@@ -177,6 +179,7 @@
pinctrl-single,pins = <
J721S2_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AG25) TIMER_IO1.USB0_DRVVBUS */
>;
+ bootph-all;
};
main_mcan3_pins_default: main-mcan3-default-pins {
@@ -200,6 +203,7 @@
J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (D28) WKUP_UART0_RXD */
J721S2_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (D27) WKUP_UART0_TXD */
>;
+ bootph-all;
};
mcu_uart0_pins_default: mcu-uart0-default-pins {
@@ -209,6 +213,7 @@
J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C24) WKUP_GPIO0_13.MCU_UART0_RXD */
J721S2_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (C25) WKUP_GPIO0_12.MCU_UART0_TXD */
>;
+ bootph-all;
};
mcu_cpsw_pins_default: mcu-cpsw-default-pins {
@@ -301,6 +306,7 @@
J721S2_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B19) MCU_OSPI1_DQS */
J721S2_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B20) MCU_OSPI1_LBCLKO */
>;
+ bootph-all;
};
};
@@ -316,12 +322,14 @@
status = "reserved";
pinctrl-names = "default";
pinctrl-0 = <&wkup_uart0_pins_default>;
+ bootph-all;
};
&mcu_uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_uart0_pins_default>;
+ bootph-all;
};
&main_uart8 {
@@ -330,6 +338,7 @@
pinctrl-0 = <&main_uart8_pins_default>;
/* Shared with TFA on this platform */
power-domains = <&k3_pds 357 TI_SCI_PD_SHARED>;
+ bootph-all;
};
&main_i2c0 {
@@ -383,6 +392,7 @@
/* eMMC */
status = "okay";
non-removable;
+ bootph-all;
ti,driver-strength-ohm = <50>;
disable-wp;
};
@@ -395,6 +405,7 @@
disable-wp;
vmmc-supply = <&vdd_mmc1>;
vqmmc-supply = <&vdd_sd_dv>;
+ bootph-all;
};
&mcu_cpsw {
@@ -444,6 +455,7 @@
status = "okay";
pinctrl-0 = <&main_usbss0_pins_default>;
pinctrl-names = "default";
+ bootph-all;
ti,vbus-divider;
ti,usb2-only;
};
@@ -451,6 +463,7 @@
&usb0 {
dr_mode = "otg";
maximum-speed = "high-speed";
+ bootph-all;
};
&ospi1 {
@@ -464,6 +477,7 @@
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
spi-max-frequency = <40000000>;
+ bootph-all;
cdns,tshsl-ns = <60>;
cdns,tsd2d-ns = <60>;
cdns,tchsh-ns = <60>;
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
index 9ed6949b40e9..92bf48fdbeba 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
@@ -816,6 +816,7 @@
<0x00 0x32800000 0x00 0x100000>;
interrupt-names = "rx_011";
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ bootph-all;
};
hwspinlock: spinlock@30e00000 {
@@ -1708,7 +1709,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 339 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 339 1>;
+ clocks = <&k3_clks 339 2>;
status = "disabled";
};
@@ -1719,7 +1720,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 340 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 340 1>;
+ clocks = <&k3_clks 340 2>;
status = "disabled";
};
@@ -1730,7 +1731,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 341 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 341 1>;
+ clocks = <&k3_clks 341 2>;
status = "disabled";
};
@@ -1741,7 +1742,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 342 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 342 1>;
+ clocks = <&k3_clks 342 2>;
status = "disabled";
};
@@ -1752,7 +1753,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 343 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 343 1>;
+ clocks = <&k3_clks 343 2>;
status = "disabled";
};
@@ -1763,7 +1764,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 344 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 344 1>;
+ clocks = <&k3_clks 344 2>;
status = "disabled";
};
@@ -1774,7 +1775,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 345 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 345 1>;
+ clocks = <&k3_clks 345 2>;
status = "disabled";
};
@@ -1785,7 +1786,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 346 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 346 1>;
+ clocks = <&k3_clks 346 2>;
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 9d96b19d0e7c..bc31266126d0 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
@@ -21,16 +21,19 @@
k3_pds: power-controller {
compatible = "ti,sci-pm-domain";
#power-domain-cells = <2>;
+ bootph-all;
};
k3_clks: clock-controller {
compatible = "ti,k2g-sci-clk";
#clock-cells = <2>;
+ bootph-all;
};
k3_reset: reset-controller {
compatible = "ti,sci-reset";
#reset-cells = <2>;
+ bootph-all;
};
};
@@ -43,6 +46,7 @@
chipid: chipid@14 {
compatible = "ti,am654-chipid";
reg = <0x14 0x4>;
+ bootph-all;
};
};
@@ -53,6 +57,8 @@
reg = <0x00 0x43600000 0x00 0x10000>,
<0x00 0x44880000 0x00 0x20000>,
<0x00 0x44860000 0x00 0x20000>;
+ bootph-pre-ram;
+
/*
* Marked Disabled:
* Node is incomplete as it is meant for bootloaders and
@@ -167,6 +173,7 @@
assigned-clocks = <&k3_clks 35 1>;
assigned-clock-parents = <&k3_clks 35 2>;
power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+ bootph-pre-ram;
ti,timer-pwm;
/* Non-MPU Firmware usage */
status = "reserved";
@@ -361,6 +368,7 @@
clocks = <&k3_clks 223 1>;
clock-names = "fck";
power-domains = <&k3_pds 223 TI_SCI_PD_EXCLUSIVE>;
+ bootph-all;
status = "disabled";
};
@@ -425,7 +433,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 347 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 347 0>;
+ clocks = <&k3_clks 347 2>;
status = "disabled";
};
@@ -436,7 +444,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 348 0>;
+ clocks = <&k3_clks 348 2>;
status = "disabled";
};
@@ -447,7 +455,7 @@
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 349 0>;
+ clocks = <&k3_clks 349 2>;
status = "disabled";
};
@@ -469,6 +477,7 @@
<0x0 0x2a500000 0x0 0x40000>,
<0x0 0x28440000 0x0 0x40000>;
reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target", "cfg";
+ bootph-all;
ti,num-rings = <286>;
ti,sci-rm-range-gp-rings = <0x1>;
ti,sci = <&sms>;
@@ -488,6 +497,7 @@
"tchan", "rchan", "rflow";
msi-parent = <&main_udmass_inta>;
#dma-cells = <1>;
+ bootph-all;
ti,sci = <&sms>;
ti,sci-dev-id = <273>;
@@ -507,6 +517,8 @@
reg = <0x00 0x2a480000 0x00 0x80000>,
<0x00 0x2a380000 0x00 0x80000>,
<0x00 0x2a400000 0x00 0x80000>;
+ bootph-pre-ram;
+
/*
* Marked Disabled:
* Node is incomplete as it is meant for bootloaders and
@@ -667,6 +679,7 @@
<0x00 0x42050000 0x0 0x350>;
power-domains = <&k3_pds 180 TI_SCI_PD_SHARED>;
#thermal-sensor-cells = <1>;
+ bootph-pre-ram;
};
mcu_r5fss0: r5fss@41000000 {
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 89252e4a5f1b..b3a0385ed3d8 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
@@ -170,6 +170,7 @@
J721S2_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (E18) MCU_OSPI0_DQS */
J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E20) MCU_OSPI0_LBCLKO */
>;
+ bootph-all;
};
};
@@ -188,6 +189,7 @@
J721S2_WKUP_IOPAD(0x98, PIN_INPUT, 0) /* (H24) WKUP_I2C0_SCL */
J721S2_WKUP_IOPAD(0x9c, PIN_INPUT, 0) /* (H27) WKUP_I2C0_SDA */
>;
+ bootph-pre-ram;
};
};
@@ -440,6 +442,7 @@
spi-tx-bus-width = <8>;
spi-rx-bus-width = <8>;
spi-max-frequency = <25000000>;
+ bootph-all;
cdns,tshsl-ns = <60>;
cdns,tsd2d-ns = <60>;
cdns,tchsh-ns = <60>;
diff --git a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi
index ed6f4ba08afc..3ac2d45a0558 100644
--- a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi
@@ -135,7 +135,7 @@
ranges;
status = "disabled";
- usb1: usb@31200000{
+ usb1: usb@31200000 {
compatible = "cdns,usb3";
reg = <0x00 0x31200000 0x00 0x10000>,
<0x00 0x31210000 0x00 0x10000>,
diff --git a/arch/arm64/boot/dts/ti/k3-j742s2-evm.dts b/arch/arm64/boot/dts/ti/k3-j742s2-evm.dts
new file mode 100644
index 000000000000..fcb7f05d7faf
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j742s2-evm.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * EVM Board Schematics: https://www.ti.com/lit/zip/SPAC001
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-j742s2.dtsi"
+#include "k3-j784s4-j742s2-evm-common.dtsi"
+
+/ {
+ model = "Texas Instruments J742S2 EVM";
+ compatible = "ti,j742s2-evm", "ti,j742s2";
+
+ memory@80000000 {
+ /* 16G RAM */
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+ <0x00000008 0x80000000 0x00000003 0x80000000>;
+ device_type = "memory";
+ bootph-all;
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j742s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j742s2-main.dtsi
new file mode 100644
index 000000000000..b320c27f7afe
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j742s2-main.dtsi
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source for J742S2 SoC Family
+ *
+ * TRM: https://www.ti.com/lit/pdf/spruje3
+ *
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+&c71_0 {
+ firmware-name = "j742s2-c71_0-fw";
+};
+
+&c71_1 {
+ firmware-name = "j742s2-c71_1-fw";
+};
+
+&c71_2 {
+ firmware-name = "j742s2-c71_2-fw";
+};
+
+&main_r5fss0_core0 {
+ firmware-name = "j742s2-main-r5f0_0-fw";
+};
+
+&main_r5fss0_core1 {
+ firmware-name = "j742s2-main-r5f0_1-fw";
+};
+
+&main_r5fss1_core0 {
+ firmware-name = "j742s2-main-r5f1_0-fw";
+};
+
+&main_r5fss1_core1 {
+ firmware-name = "j742s2-main-r5f1_1-fw";
+};
+
+&main_r5fss2_core0 {
+ firmware-name = "j742s2-main-r5f2_0-fw";
+};
+
+&main_r5fss2_core1 {
+ firmware-name = "j742s2-main-r5f2_1-fw";
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j742s2.dtsi b/arch/arm64/boot/dts/ti/k3-j742s2.dtsi
new file mode 100644
index 000000000000..7a72f82f56d6
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j742s2.dtsi
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source for J742S2 SoC Family
+ *
+ * TRM: https://www.ti.com/lit/pdf/spruje3
+ *
+ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+#include "k3-j784s4-j742s2-common.dtsi"
+
+/ {
+ model = "Texas Instruments K3 J742S2 SoC";
+ compatible = "ti,j742s2";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0: cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+
+ core1 {
+ cpu = <&cpu1>;
+ };
+
+ core2 {
+ cpu = <&cpu2>;
+ };
+
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a72";
+ reg = <0x000>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0xc000>;
+ 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 = <&L2_0>;
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a72";
+ reg = <0x001>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0xc000>;
+ 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 = <&L2_0>;
+ };
+
+ cpu2: cpu@2 {
+ compatible = "arm,cortex-a72";
+ reg = <0x002>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0xc000>;
+ 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 = <&L2_0>;
+ };
+
+ cpu3: cpu@3 {
+ compatible = "arm,cortex-a72";
+ reg = <0x003>;
+ device_type = "cpu";
+ enable-method = "psci";
+ i-cache-size = <0xc000>;
+ 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 = <&L2_0>;
+ };
+ };
+};
+
+#include "k3-j742s2-main.dtsi"
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
index 6695ebbcb4d0..a84bde08f85e 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
@@ -10,176 +10,23 @@
#include <dt-bindings/net/ti-dp83867.h>
#include <dt-bindings/gpio/gpio.h>
#include "k3-j784s4.dtsi"
+#include "k3-j784s4-j742s2-evm-common.dtsi"
/ {
compatible = "ti,j784s4-evm", "ti,j784s4";
model = "Texas Instruments J784S4 EVM";
- chosen {
- stdout-path = "serial2:115200n8";
- };
-
- aliases {
- serial0 = &wkup_uart0;
- serial1 = &mcu_uart0;
- serial2 = &main_uart8;
- mmc0 = &main_sdhci0;
- mmc1 = &main_sdhci1;
- i2c0 = &wkup_i2c0;
- i2c3 = &main_i2c0;
- ethernet0 = &mcu_cpsw_port1;
- ethernet1 = &main_cpsw1_port1;
- };
-
memory@80000000 {
- device_type = "memory";
- bootph-all;
/* 32G RAM */
reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
<0x00000008 0x80000000 0x00000007 0x80000000>;
+ device_type = "memory";
+ bootph-all;
};
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;
- };
-
- main_r5fss2_core0_dma_memory_region: r5f-dma-memory@a6000000 {
- compatible = "shared-dma-pool";
- reg = <0x00 0xa6000000 0x00 0x100000>;
- no-map;
- };
-
- main_r5fss2_core0_memory_region: r5f-memory@a6100000 {
- compatible = "shared-dma-pool";
- reg = <0x00 0xa6100000 0x00 0xf00000>;
- no-map;
- };
-
- main_r5fss2_core1_dma_memory_region: r5f-dma-memory@a7000000 {
- compatible = "shared-dma-pool";
- reg = <0x00 0xa7000000 0x00 0x100000>;
- no-map;
- };
-
- main_r5fss2_core1_memory_region: r5f-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;
- };
-
- c71_1_dma_memory_region: c71-dma-memory@a9000000 {
- compatible = "shared-dma-pool";
- reg = <0x00 0xa9000000 0x00 0x100000>;
- no-map;
- };
-
- c71_1_memory_region: c71-memory@a9100000 {
- compatible = "shared-dma-pool";
- reg = <0x00 0xa9100000 0x00 0xf00000>;
- no-map;
- };
-
- c71_2_dma_memory_region: c71-dma-memory@aa000000 {
- compatible = "shared-dma-pool";
- reg = <0x00 0xaa000000 0x00 0x100000>;
- no-map;
- };
-
- c71_2_memory_region: c71-memory@aa100000 {
- compatible = "shared-dma-pool";
- reg = <0x00 0xaa100000 0x00 0xf00000>;
- no-map;
- };
c71_3_dma_memory_region: c71-dma-memory@ab000000 {
compatible = "shared-dma-pool";
@@ -193,1339 +40,18 @@
no-map;
};
};
-
- evm_12v0: regulator-evm12v0 {
- /* 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-vsys3v3 {
- /* Output of LM5140 */
- 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-vsys5v0 {
- /* 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-sd {
- /* Output of TPS22918 */
- compatible = "regulator-fixed";
- regulator-name = "vdd_mmc1";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- enable-active-high;
- vin-supply = <&vsys_3v3>;
- gpio = <&exp2 2 GPIO_ACTIVE_HIGH>;
- };
-
- vdd_sd_dv: regulator-TLV71033 {
- /* Output of TLV71033 */
- compatible = "regulator-gpio";
- regulator-name = "tlv71033";
- pinctrl-names = "default";
- pinctrl-0 = <&vdd_sd_dv_pins_default>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- vin-supply = <&vsys_5v0>;
- gpios = <&main_gpio0 8 GPIO_ACTIVE_HIGH>;
- states = <1800000 0x0>,
- <3300000 0x1>;
- };
-
- dp0_pwr_3v3: regulator-dp0-prw {
- compatible = "regulator-fixed";
- regulator-name = "dp0-pwr";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&exp4 0 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
-
- dp0: connector-dp0 {
- compatible = "dp-connector";
- label = "DP0";
- type = "full-size";
- dp-pwr-supply = <&dp0_pwr_3v3>;
-
- port {
- dp0_connector_in: endpoint {
- remote-endpoint = <&dp0_out>;
- };
- };
- };
-
- transceiver0: can-phy0 {
- compatible = "ti,tcan1042";
- #phy-cells = <0>;
- max-bitrate = <5000000>;
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_mcan0_gpio_pins_default>;
- standby-gpios = <&wkup_gpio0 69 GPIO_ACTIVE_HIGH>;
- };
-
- transceiver1: can-phy1 {
- compatible = "ti,tcan1042";
- #phy-cells = <0>;
- max-bitrate = <5000000>;
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_mcan1_gpio_pins_default>;
- standby-gpios = <&wkup_gpio0 2 GPIO_ACTIVE_HIGH>;
- };
-
- transceiver2: can-phy2 {
- /* standby pin has been grounded by default */
- compatible = "ti,tcan1042";
- #phy-cells = <0>;
- max-bitrate = <5000000>;
- };
-
- transceiver3: can-phy3 {
- compatible = "ti,tcan1042";
- #phy-cells = <0>;
- max-bitrate = <5000000>;
- standby-gpios = <&exp2 7 GPIO_ACTIVE_HIGH>;
- mux-states = <&mux1 1>;
- };
-
- mux1: mux-controller {
- compatible = "gpio-mux";
- #mux-state-cells = <1>;
- mux-gpios = <&exp2 14 GPIO_ACTIVE_HIGH>;
- idle-state = <1>;
- };
-
- codec_audio: sound {
- compatible = "ti,j7200-cpb-audio";
- model = "j784s4-cpb";
-
- ti,cpb-mcasp = <&mcasp0>;
- ti,cpb-codec = <&pcm3168a_1>;
-
- clocks = <&k3_clks 265 0>, <&k3_clks 265 1>,
- <&k3_clks 157 34>, <&k3_clks 157 63>;
- clock-names = "cpb-mcasp-auxclk", "cpb-mcasp-auxclk-48000",
- "cpb-codec-scki", "cpb-codec-scki-48000";
- };
-};
-
-&wkup_gpio0 {
- status = "okay";
-};
-
-&main_pmx0 {
- bootph-all;
- main_cpsw2g_default_pins: main-cpsw2g-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x0b8, PIN_INPUT, 6) /* (AC34) MCASP1_ACLKX.RGMII1_RD0 */
- J784S4_IOPAD(0x0a0, PIN_INPUT, 6) /* (AD34) MCASP0_AXR12.RGMII1_RD1 */
- J784S4_IOPAD(0x0a4, PIN_INPUT, 6) /* (AJ36) MCASP0_AXR13.RGMII1_RD2 */
- J784S4_IOPAD(0x0a8, PIN_INPUT, 6) /* (AF34) MCASP0_AXR14.RGMII1_RD3 */
- J784S4_IOPAD(0x0b0, PIN_INPUT, 6) /* (AL33) MCASP1_AXR3.RGMII1_RXC */
- J784S4_IOPAD(0x0ac, PIN_INPUT, 6) /* (AE34) MCASP0_AXR15.RGMII1_RX_CTL */
- J784S4_IOPAD(0x08c, PIN_INPUT, 6) /* (AE35) MCASP0_AXR7.RGMII1_TD0 */
- J784S4_IOPAD(0x090, PIN_INPUT, 6) /* (AC35) MCASP0_AXR8.RGMII1_TD1 */
- J784S4_IOPAD(0x094, PIN_INPUT, 6) /* (AG35) MCASP0_AXR9.RGMII1_TD2 */
- J784S4_IOPAD(0x098, PIN_INPUT, 6) /* (AH36) MCASP0_AXR10.RGMII1_TD3 */
- J784S4_IOPAD(0x0b4, PIN_INPUT, 6) /* (AL34) MCASP1_AXR4.RGMII1_TXC */
- J784S4_IOPAD(0x09c, PIN_INPUT, 6) /* (AF35) MCASP0_AXR11.RGMII1_TX_CTL */
- >;
- };
-
- main_cpsw2g_mdio_default_pins: main-cpsw2g-mdio-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x0c0, PIN_INPUT, 6) /* (AD38) MCASP1_AXR0.MDIO0_MDC */
- J784S4_IOPAD(0x0bc, PIN_INPUT, 6) /* (AD33) MCASP1_AFSX.MDIO0_MDIO */
- >;
- };
-
- main_uart8_pins_default: main-uart8-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_IOPAD(0x040, PIN_INPUT, 14) /* (AF37) MCASP0_AXR0.UART8_CTSn */
- J784S4_IOPAD(0x044, PIN_OUTPUT, 14) /* (AG37) MCASP0_AXR1.UART8_RTSn */
- J784S4_IOPAD(0x0d0, PIN_INPUT, 11) /* (AP38) SPI0_CS1.UART8_RXD */
- J784S4_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AN38) SPI0_CLK.UART8_TXD */
- >;
- };
-
- main_i2c0_pins_default: main-i2c0-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x0e0, PIN_INPUT_PULLUP, 0) /* (AN36) I2C0_SCL */
- J784S4_IOPAD(0x0e4, PIN_INPUT_PULLUP, 0) /* (AP37) I2C0_SDA */
- >;
- };
-
- main_i2c5_pins_default: main-i2c5-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x01c, PIN_INPUT, 8) /* (AG34) MCAN15_TX.I2C5_SCL */
- J784S4_IOPAD(0x018, PIN_INPUT, 8) /* (AK36) MCAN14_RX.I2C5_SDA */
- >;
- };
-
- main_mmc1_pins_default: main-mmc1-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_IOPAD(0x104, PIN_INPUT, 0) /* (AB38) MMC1_CLK */
- J784S4_IOPAD(0x108, PIN_INPUT, 0) /* (AB36) MMC1_CMD */
- J784S4_IOPAD(0x100, PIN_INPUT, 0) /* (No Pin) MMC1_CLKLB */
- J784S4_IOPAD(0x0fc, PIN_INPUT, 0) /* (AA33) MMC1_DAT0 */
- J784S4_IOPAD(0x0f8, PIN_INPUT, 0) /* (AB34) MMC1_DAT1 */
- J784S4_IOPAD(0x0f4, PIN_INPUT, 0) /* (AA32) MMC1_DAT2 */
- J784S4_IOPAD(0x0f0, PIN_INPUT, 0) /* (AC38) MMC1_DAT3 */
- J784S4_IOPAD(0x0e8, PIN_INPUT, 8) /* (AR38) TIMER_IO0.MMC1_SDCD */
- >;
- };
-
- vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x020, PIN_INPUT, 7) /* (AJ35) MCAN15_RX.GPIO0_8 */
- >;
- };
-
- dp0_pins_default: dp0-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x0cc, PIN_INPUT, 12) /* (AM37) SPI0_CS0.DP0_HPD */
- >;
- };
-
- main_i2c4_pins_default: main-i2c4-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AG33) MCAN14_TX.I2C4_SCL */
- J784S4_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AH33) MCAN13_RX.I2C4_SDA */
- >;
- };
-
- main_mcan4_pins_default: main-mcan4-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x088, PIN_INPUT, 0) /* (AF36) MCAN4_RX */
- J784S4_IOPAD(0x084, PIN_OUTPUT, 0) /* (AG38) MCAN4_TX */
- >;
- };
-
- main_mcan16_pins_default: main-mcan16-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x028, PIN_INPUT, 0) /* (AE33) MCAN16_RX */
- J784S4_IOPAD(0x024, PIN_OUTPUT, 0) /* (AH34) MCAN16_TX */
- >;
- };
-
- main_usbss0_pins_default: main-usbss0-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AN37) TIMER_IO1.USB0_DRVVBUS */
- >;
- };
-
- main_i2c3_pins_default: main-i2c3-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x064, PIN_INPUT, 13) /* (AF38) MCAN0_TX.I2C3_SCL */
- J784S4_IOPAD(0x060, PIN_INPUT, 13) /* (AE36) MCASP2_AXR1.I2C3_SDA */
- >;
- };
-
- main_mcasp0_pins_default: main-mcasp0-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x038, PIN_OUTPUT_PULLDOWN, 1) /* (AK35) MCASP0_ACLKX */
- J784S4_IOPAD(0x03c, PIN_OUTPUT_PULLDOWN, 1) /* (AK38) MCASP0_AFSX */
- J784S4_IOPAD(0x07c, PIN_OUTPUT_PULLDOWN, 1) /* (AJ38) MCASP0_AXR3 */
- J784S4_IOPAD(0x080, PIN_INPUT_PULLDOWN, 1) /* (AK34) MCASP0_AXR4 */
- >;
- };
-
- audio_ext_refclk1_pins_default: audio-ext-refclk1-default-pins {
- pinctrl-single,pins = <
- J784S4_IOPAD(0x078, PIN_OUTPUT, 1) /* (AH37) MCAN2_RX.AUDIO_EXT_REFCLK1 */
- >;
- };
-};
-
-&wkup_pmx2 {
- bootph-all;
- wkup_uart0_pins_default: wkup-uart0-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (K35) WKUP_UART0_RXD */
- J784S4_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (K34) WKUP_UART0_TXD */
- >;
- };
-
- wkup_i2c0_pins_default: wkup-i2c0-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x98, PIN_INPUT, 0) /* (N33) WKUP_I2C0_SCL */
- J784S4_WKUP_IOPAD(0x9c, PIN_INPUT, 0) /* (N35) WKUP_I2C0_SDA */
- >;
- };
-
- mcu_uart0_pins_default: mcu-uart0-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (H37) WKUP_GPIO0_14.MCU_UART0_CTSn */
- J784S4_WKUP_IOPAD(0x094, PIN_OUTPUT, 0) /* (K37) WKUP_GPIO0_15.MCU_UART0_RTSn */
- J784S4_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (K38) WKUP_GPIO0_13.MCU_UART0_RXD */
- J784S4_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (J37) WKUP_GPIO0_12.MCU_UART0_TXD */
- >;
- };
-
- mcu_cpsw_pins_default: mcu-cpsw-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (A35) MCU_RGMII1_RD0 */
- J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B36) MCU_RGMII1_RD1 */
- J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C36) MCU_RGMII1_RD2 */
- J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D36) MCU_RGMII1_RD3 */
- J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (B37) MCU_RGMII1_RXC */
- J784S4_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (C37) MCU_RGMII1_RX_CTL */
- J784S4_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (D37) MCU_RGMII1_TD0 */
- J784S4_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (D38) MCU_RGMII1_TD1 */
- J784S4_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E37) MCU_RGMII1_TD2 */
- J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E38) MCU_RGMII1_TD3 */
- J784S4_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (E36) MCU_RGMII1_TXC */
- J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (C38) MCU_RGMII1_TX_CTL */
- >;
- };
-
- mcu_mdio_pins_default: mcu-mdio-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A36) MCU_MDIO0_MDC */
- J784S4_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (B35) MCU_MDIO0_MDIO */
- >;
- };
-
- mcu_adc0_pins_default: mcu-adc0-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x0cc, PIN_INPUT, 0) /* (P36) MCU_ADC0_AIN0 */
- J784S4_WKUP_IOPAD(0x0d0, PIN_INPUT, 0) /* (V36) MCU_ADC0_AIN1 */
- J784S4_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (T34) MCU_ADC0_AIN2 */
- J784S4_WKUP_IOPAD(0x0d8, PIN_INPUT, 0) /* (T36) MCU_ADC0_AIN3 */
- J784S4_WKUP_IOPAD(0x0dc, PIN_INPUT, 0) /* (P34) MCU_ADC0_AIN4 */
- J784S4_WKUP_IOPAD(0x0e0, PIN_INPUT, 0) /* (R37) MCU_ADC0_AIN5 */
- J784S4_WKUP_IOPAD(0x0e4, PIN_INPUT, 0) /* (R33) MCU_ADC0_AIN6 */
- J784S4_WKUP_IOPAD(0x0e8, PIN_INPUT, 0) /* (V38) MCU_ADC0_AIN7 */
- >;
- };
-
- mcu_adc1_pins_default: mcu-adc1-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x0ec, PIN_INPUT, 0) /* (Y38) MCU_ADC1_AIN0 */
- J784S4_WKUP_IOPAD(0x0f0, PIN_INPUT, 0) /* (Y34) MCU_ADC1_AIN1 */
- J784S4_WKUP_IOPAD(0x0f4, PIN_INPUT, 0) /* (V34) MCU_ADC1_AIN2 */
- J784S4_WKUP_IOPAD(0x0f8, PIN_INPUT, 0) /* (W37) MCU_ADC1_AIN3 */
- J784S4_WKUP_IOPAD(0x0fc, PIN_INPUT, 0) /* (AA37) MCU_ADC1_AIN4 */
- J784S4_WKUP_IOPAD(0x100, PIN_INPUT, 0) /* (W33) MCU_ADC1_AIN5 */
- J784S4_WKUP_IOPAD(0x104, PIN_INPUT, 0) /* (U33) MCU_ADC1_AIN6 */
- J784S4_WKUP_IOPAD(0x108, PIN_INPUT, 0) /* (Y36) MCU_ADC1_AIN7 */
- >;
- };
-
- mcu_mcan0_pins_default: mcu-mcan0-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (K33) MCU_MCAN0_TX */
- J784S4_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (F38) MCU_MCAN0_RX */
- >;
- };
-
- mcu_mcan1_pins_default: mcu-mcan1-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (H35) WKUP_GPIO0_4.MCU_MCAN1_TX */
- J784S4_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (K36) WKUP_GPIO0_5.MCU_MCAN1_RX */
- >;
- };
-
- mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x040, PIN_INPUT, 7) /* (J38) MCU_SPI0_D1.WKUP_GPIO0_69 */
- >;
- };
-
- mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-default-pins {
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (J35) WKUP_GPIO0_2 */
- >;
- };
-};
-
-&wkup_pmx1 {
- status = "okay";
-
- pmic_irq_pins_default: pmic-irq-default-pins {
- pinctrl-single,pins = <
- /* (G33) MCU_OSPI1_CSn1.WKUP_GPIO0_39 */
- J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 7)
- >;
- };
-};
-
-&wkup_pmx0 {
- bootph-all;
- mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (E32) MCU_OSPI0_CLK */
- J784S4_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (A32) MCU_OSPI0_CSn0 */
- J784S4_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B33) MCU_OSPI0_D0 */
- J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B32) MCU_OSPI0_D1 */
- J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (C33) MCU_OSPI0_D2 */
- J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (C35) MCU_OSPI0_D3 */
- J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D33) MCU_OSPI0_D4 */
- J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D34) MCU_OSPI0_D5 */
- J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (E34) MCU_OSPI0_D6 */
- J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (E33) MCU_OSPI0_D7 */
- J784S4_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (C34) MCU_OSPI0_DQS */
- >;
- };
-};
-
-&wkup_pmx1 {
- bootph-all;
- mcu_fss0_ospi0_1_pins_default: mcu-fss0-ospi0-1-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x004, PIN_OUTPUT, 6) /* (C32) MCU_OSPI0_ECC_FAIL */
- J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 6) /* (B34) MCU_OSPI0_RESET_OUT0 */
- >;
- };
-
- mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-default-pins {
- bootph-all;
- pinctrl-single,pins = <
- J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (F32) MCU_OSPI1_CLK */
- J784S4_WKUP_IOPAD(0x024, PIN_OUTPUT, 0) /* (G32) MCU_OSPI1_CSn0 */
- J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (E35) MCU_OSPI1_D0 */
- J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (D31) MCU_OSPI1_D1 */
- J784S4_WKUP_IOPAD(0x01C, PIN_INPUT, 0) /* (G31) MCU_OSPI1_D2 */
- J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (F33) MCU_OSPI1_D3 */
- J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (F31) MCU_OSPI1_DQS */
- J784S4_WKUP_IOPAD(0x00C, PIN_INPUT, 0) /* (C31) MCU_OSPI1_LBCLKO */
- >;
- };
-};
-
-&wkup_uart0 {
- /* Firmware usage */
- status = "reserved";
- pinctrl-names = "default";
- pinctrl-0 = <&wkup_uart0_pins_default>;
-};
-
-&wkup_i2c0 {
- bootph-all;
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&wkup_i2c0_pins_default>;
- clock-frequency = <400000>;
-
- eeprom@50 {
- /* CAV24C256WE-GT3 */
- compatible = "atmel,24c256";
- reg = <0x50>;
- };
-
- tps659413: pmic@48 {
- compatible = "ti,tps6594-q1";
- reg = <0x48>;
- system-power-controller;
- pinctrl-names = "default";
- pinctrl-0 = <&pmic_irq_pins_default>;
- interrupt-parent = <&wkup_gpio0>;
- interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
- gpio-controller;
- #gpio-cells = <2>;
- ti,primary-pmic;
- buck12-supply = <&vsys_3v3>;
- buck3-supply = <&vsys_3v3>;
- buck4-supply = <&vsys_3v3>;
- buck5-supply = <&vsys_3v3>;
- ldo1-supply = <&vsys_3v3>;
- ldo2-supply = <&vsys_3v3>;
- ldo3-supply = <&vsys_3v3>;
- ldo4-supply = <&vsys_3v3>;
-
- regulators {
- bucka12: buck12 {
- regulator-name = "vdd_ddr_1v1";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- bucka3: buck3 {
- regulator-name = "vdd_ram_0v85";
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <850000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- bucka4: buck4 {
- regulator-name = "vdd_io_1v8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- bucka5: buck5 {
- regulator-name = "vdd_mcu_0v85";
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <850000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ldoa1: ldo1 {
- regulator-name = "vdd_mcuio_1v8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ldoa2: ldo2 {
- regulator-name = "vdd_mcuio_3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ldoa3: ldo3 {
- regulator-name = "vds_dll_0v8";
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <800000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- ldoa4: ldo4 {
- regulator-name = "vda_mcu_1v8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-boot-on;
- regulator-always-on;
- };
- };
- };
-
- tps62873a: regulator@40 {
- compatible = "ti,tps62873";
- reg = <0x40>;
- bootph-pre-ram;
- regulator-name = "VDD_CPU_AVS";
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1330000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- tps62873b: regulator@43 {
- compatible = "ti,tps62873";
- reg = <0x43>;
- regulator-name = "VDD_CORE_0V8";
- regulator-min-microvolt = <760000>;
- regulator-max-microvolt = <840000>;
- regulator-boot-on;
- regulator-always-on;
- };
-};
-
-&mcu_uart0 {
- bootph-all;
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_uart0_pins_default>;
-};
-
-&main_uart8 {
- bootph-all;
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&main_uart8_pins_default>;
-};
-
-&ufs_wrapper {
- status = "okay";
-};
-
-&fss {
- bootph-all;
- status = "okay";
-};
-
-&ospi0 {
- bootph-all;
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_fss0_ospi0_pins_default>, <&mcu_fss0_ospi0_1_pins_default>;
-
- flash@0 {
- bootph-all;
- compatible = "jedec,spi-nor";
- reg = <0x0>;
- spi-tx-bus-width = <8>;
- spi-rx-bus-width = <8>;
- spi-max-frequency = <25000000>;
- cdns,tshsl-ns = <60>;
- cdns,tsd2d-ns = <60>;
- cdns,tchsh-ns = <60>;
- cdns,tslch-ns = <60>;
- cdns,read-delay = <4>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "ospi.tiboot3";
- reg = <0x0 0x80000>;
- };
-
- partition@80000 {
- label = "ospi.tispl";
- reg = <0x80000 0x200000>;
- };
-
- partition@280000 {
- label = "ospi.u-boot";
- reg = <0x280000 0x400000>;
- };
-
- partition@680000 {
- label = "ospi.env";
- reg = <0x680000 0x40000>;
- };
-
- partition@6c0000 {
- label = "ospi.env.backup";
- reg = <0x6c0000 0x40000>;
- };
-
- partition@800000 {
- label = "ospi.rootfs";
- reg = <0x800000 0x37c0000>;
- };
-
- partition@3fc0000 {
- bootph-all;
- label = "ospi.phypattern";
- reg = <0x3fc0000 0x40000>;
- };
- };
- };
-};
-
-&ospi1 {
- bootph-all;
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_fss0_ospi1_pins_default>;
-
- flash@0 {
- bootph-all;
- compatible = "jedec,spi-nor";
- reg = <0x0>;
- spi-tx-bus-width = <1>;
- spi-rx-bus-width = <4>;
- spi-max-frequency = <40000000>;
- cdns,tshsl-ns = <60>;
- cdns,tsd2d-ns = <60>;
- cdns,tchsh-ns = <60>;
- cdns,tslch-ns = <60>;
- cdns,read-delay = <2>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "qspi.tiboot3";
- reg = <0x0 0x80000>;
- };
-
- partition@80000 {
- label = "qspi.tispl";
- reg = <0x80000 0x200000>;
- };
-
- partition@280000 {
- label = "qspi.u-boot";
- reg = <0x280000 0x400000>;
- };
-
- partition@680000 {
- label = "qspi.env";
- reg = <0x680000 0x40000>;
- };
-
- partition@6c0000 {
- label = "qspi.env.backup";
- reg = <0x6c0000 0x40000>;
- };
-
- partition@800000 {
- label = "qspi.rootfs";
- reg = <0x800000 0x37c0000>;
- };
-
- partition@3fc0000 {
- bootph-all;
- label = "qspi.phypattern";
- reg = <0x3fc0000 0x40000>;
- };
- };
-
- };
-};
-
-&main_i2c0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&main_i2c0_pins_default>;
-
- clock-frequency = <400000>;
-
- exp1: gpio@20 {
- compatible = "ti,tca6416";
- reg = <0x20>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-line-names = "PCIE1_2L_MODE_SEL", "PCIE1_4L_PERSTZ", "PCIE1_2L_RC_RSTZ",
- "PCIE1_2L_EP_RST_EN", "PCIE0_4L_MODE_SEL", "PCIE0_4L_PERSTZ",
- "PCIE0_4L_RC_RSTZ", "PCIE0_4L_EP_RST_EN", "PCIE1_4L_PRSNT#",
- "PCIE0_4L_PRSNT#", "CDCI1_OE1/OE4", "CDCI1_OE2/OE3",
- "AUDIO_MUX_SEL", "EXP_MUX2", "EXP_MUX3", "GESI_EXP_PHY_RSTZ";
-
- p12-hog {
- /* P12 - AUDIO_MUX_SEL */
- gpio-hog;
- gpios = <12 GPIO_ACTIVE_HIGH>;
- output-low;
- line-name = "AUDIO_MUX_SEL";
- };
- };
-
- exp2: gpio@22 {
- compatible = "ti,tca6424";
- reg = <0x22>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-line-names = "R_GPIO_RGMII1_RST", "ENET2_I2CMUX_SEL", "GPIO_USD_PWR_EN",
- "USBC_PWR_EN", "USBC_MODE_SEL1", "USBC_MODE_SEL0",
- "GPIO_LIN_EN", "R_CAN_STB", "CTRL_PM_I2C_OE#",
- "ENET2_EXP_PWRDN", "ENET2_EXP_SPARE2", "CDCI2_RSTZ",
- "USB2.0_MUX_SEL", "CANUART_MUX_SEL0", "CANUART_MUX2_SEL1",
- "CANUART_MUX1_SEL1", "ENET1_EXP_PWRDN", "ENET1_EXP_RESETZ",
- "ENET1_I2CMUX_SEL", "ENET1_EXP_SPARE2", "ENET2_EXP_RESETZ",
- "USER_INPUT1", "USER_LED1", "USER_LED2";
-
- p13-hog {
- /* P13 - CANUART_MUX_SEL0 */
- gpio-hog;
- gpios = <13 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "CANUART_MUX_SEL0";
- };
-
- p15-hog {
- /* P15 - CANUART_MUX1_SEL1 */
- gpio-hog;
- gpios = <15 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "CANUART_MUX1_SEL1";
- };
- };
-};
-
-&main_i2c5 {
- pinctrl-names = "default";
- pinctrl-0 = <&main_i2c5_pins_default>;
- clock-frequency = <400000>;
- status = "okay";
-
- exp5: gpio@20 {
- compatible = "ti,tca6408";
- reg = <0x20>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-line-names = "CSI2_EXP_RSTZ", "CSI2_EXP_A_GPIO0",
- "CSI2_EXP_A_GPIO1", "CSI2_EXP_A_GPIO3",
- "CSI2_EXP_B_GPIO1", "CSI2_EXP_B_GPIO2",
- "CSI2_EXP_B_GPIO3", "CSI2_EXP_B_GPIO4";
- };
-};
-
-&main_sdhci0 {
- bootph-all;
- /* eMMC */
- status = "okay";
- non-removable;
- ti,driver-strength-ohm = <50>;
- disable-wp;
-};
-
-&main_sdhci1 {
- bootph-all;
- /* SD card */
- status = "okay";
- pinctrl-0 = <&main_mmc1_pins_default>;
- pinctrl-names = "default";
- disable-wp;
- vmmc-supply = <&vdd_mmc1>;
- vqmmc-supply = <&vdd_sd_dv>;
-};
-
-&main_gpio0 {
- status = "okay";
-};
-
-&mcu_cpsw {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_cpsw_pins_default>;
-};
-
-&davinci_mdio {
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_mdio_pins_default>;
-
- mcu_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>;
- ti,min-output-impedance;
- };
-};
-
-&mcu_cpsw_port1 {
- status = "okay";
- phy-mode = "rgmii-rxid";
- phy-handle = <&mcu_phy0>;
-};
-
-&main_cpsw1 {
- pinctrl-names = "default";
- pinctrl-0 = <&main_cpsw2g_default_pins>;
- status = "okay";
-};
-
-&main_cpsw1_mdio {
- pinctrl-names = "default";
- pinctrl-0 = <&main_cpsw2g_mdio_default_pins>;
- status = "okay";
-
- main_cpsw1_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>;
- ti,min-output-impedance;
- };
-};
-
-&main_cpsw1_port1 {
- phy-mode = "rgmii-rxid";
- phy-handle = <&main_cpsw1_phy0>;
- status = "okay";
-};
-
-&mailbox0_cluster0 {
- status = "okay";
- 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 {
- status = "okay";
- 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 {
- status = "okay";
- 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 {
- status = "okay";
- interrupts = <424>;
-
- mbox_main_r5fss2_core0: mbox-main-r5fss2-core0 {
- ti,mbox-rx = <0 0 0>;
- ti,mbox-tx = <1 0 0>;
- };
-
- mbox_main_r5fss2_core1: mbox-main-r5fss2-core1 {
- ti,mbox-rx = <2 0 0>;
- ti,mbox-tx = <3 0 0>;
- };
-};
-
-&mailbox0_cluster4 {
- status = "okay";
- interrupts = <420>;
-
- mbox_c71_0: mbox-c71-0 {
- ti,mbox-rx = <0 0 0>;
- ti,mbox-tx = <1 0 0>;
- };
-
- mbox_c71_1: mbox-c71-1 {
- ti,mbox-rx = <2 0 0>;
- ti,mbox-tx = <3 0 0>;
- };
};
&mailbox0_cluster5 {
- status = "okay";
- interrupts = <416>;
-
- mbox_c71_2: mbox-c71-2 {
- ti,mbox-rx = <0 0 0>;
- ti,mbox-tx = <1 0 0>;
- };
-
mbox_c71_3: mbox-c71-3 {
ti,mbox-rx = <2 0 0>;
ti,mbox-tx = <3 0 0>;
};
};
-&mcu_r5fss0_core0 {
- status = "okay";
- mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
- memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
- <&mcu_r5fss0_core0_memory_region>;
-};
-
-&mcu_r5fss0_core1 {
- status = "okay";
- mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
- memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
- <&mcu_r5fss0_core1_memory_region>;
-};
-
-&main_r5fss0 {
- ti,cluster-mode = <0>;
-};
-
-&main_r5fss1 {
- ti,cluster-mode = <0>;
-};
-
-&main_r5fss2 {
- ti,cluster-mode = <0>;
-};
-
-/* Timers are used by Remoteproc firmware */
-&main_timer0 {
- status = "reserved";
-};
-
-&main_timer1 {
- status = "reserved";
-};
-
-&main_timer2 {
- status = "reserved";
-};
-
-&main_timer3 {
- status = "reserved";
-};
-
-&main_timer4 {
- status = "reserved";
-};
-
-&main_timer5 {
- status = "reserved";
-};
-
-&main_timer6 {
- status = "reserved";
-};
-
-&main_timer7 {
- status = "reserved";
-};
-
-&main_timer8 {
- status = "reserved";
-};
-
-&main_timer9 {
- status = "reserved";
-};
-
-&main_r5fss0_core0 {
- status = "okay";
- mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
- memory-region = <&main_r5fss0_core0_dma_memory_region>,
- <&main_r5fss0_core0_memory_region>;
-};
-
-&main_r5fss0_core1 {
- status = "okay";
- mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
- memory-region = <&main_r5fss0_core1_dma_memory_region>,
- <&main_r5fss0_core1_memory_region>;
-};
-
-&main_r5fss1_core0 {
- status = "okay";
- mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
- memory-region = <&main_r5fss1_core0_dma_memory_region>,
- <&main_r5fss1_core0_memory_region>;
-};
-
-&main_r5fss1_core1 {
- status = "okay";
- mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
- memory-region = <&main_r5fss1_core1_dma_memory_region>,
- <&main_r5fss1_core1_memory_region>;
-};
-
-&main_r5fss2_core0 {
- status = "okay";
- mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core0>;
- memory-region = <&main_r5fss2_core0_dma_memory_region>,
- <&main_r5fss2_core0_memory_region>;
-};
-
-&main_r5fss2_core1 {
- status = "okay";
- mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core1>;
- memory-region = <&main_r5fss2_core1_dma_memory_region>,
- <&main_r5fss2_core1_memory_region>;
-};
-
-&c71_0 {
- status = "okay";
- mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
- memory-region = <&c71_0_dma_memory_region>,
- <&c71_0_memory_region>;
-};
-
-&c71_1 {
- status = "okay";
- mboxes = <&mailbox0_cluster4 &mbox_c71_1>;
- memory-region = <&c71_1_dma_memory_region>,
- <&c71_1_memory_region>;
-};
-
-&c71_2 {
- status = "okay";
- mboxes = <&mailbox0_cluster5 &mbox_c71_2>;
- memory-region = <&c71_2_dma_memory_region>,
- <&c71_2_memory_region>;
-};
-
&c71_3 {
- status = "okay";
mboxes = <&mailbox0_cluster5 &mbox_c71_3>;
memory-region = <&c71_3_dma_memory_region>,
<&c71_3_memory_region>;
-};
-
-&tscadc0 {
- pinctrl-0 = <&mcu_adc0_pins_default>;
- pinctrl-names = "default";
- status = "okay";
- adc {
- ti,adc-channels = <0 1 2 3 4 5 6 7>;
- };
-};
-
-&tscadc1 {
- pinctrl-0 = <&mcu_adc1_pins_default>;
- pinctrl-names = "default";
- status = "okay";
- adc {
- ti,adc-channels = <0 1 2 3 4 5 6 7>;
- };
-};
-
-&serdes_refclk {
- status = "okay";
- clock-frequency = <100000000>;
-};
-
-&dss {
- status = "okay";
- assigned-clocks = <&k3_clks 218 2>,
- <&k3_clks 218 5>,
- <&k3_clks 218 14>,
- <&k3_clks 218 18>;
- assigned-clock-parents = <&k3_clks 218 3>,
- <&k3_clks 218 7>,
- <&k3_clks 218 16>,
- <&k3_clks 218 22>;
-};
-
-&serdes0 {
- status = "okay";
-
- serdes0_pcie1_link: phy@0 {
- reg = <0>;
- cdns,num-lanes = <2>;
- #phy-cells = <0>;
- cdns,phy-type = <PHY_TYPE_PCIE>;
- resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>;
- };
-
- serdes0_usb_link: phy@3 {
- reg = <3>;
- cdns,num-lanes = <1>;
- #phy-cells = <0>;
- cdns,phy-type = <PHY_TYPE_USB3>;
- resets = <&serdes_wiz0 4>;
- };
-};
-
-&serdes_wiz0 {
- status = "okay";
-};
-
-&usb_serdes_mux {
- idle-states = <0>; /* USB0 to SERDES lane 3 */
-};
-
-&usbss0 {
- status = "okay";
- pinctrl-0 = <&main_usbss0_pins_default>;
- pinctrl-names = "default";
- ti,vbus-divider;
-};
-
-&usb0 {
- dr_mode = "otg";
- maximum-speed = "super-speed";
- phys = <&serdes0_usb_link>;
- phy-names = "cdns3,usb3-phy";
-};
-
-&serdes_wiz4 {
- status = "okay";
-};
-
-&serdes4 {
- status = "okay";
- serdes4_dp_link: phy@0 {
- reg = <0>;
- cdns,num-lanes = <4>;
- #phy-cells = <0>;
- cdns,phy-type = <PHY_TYPE_DP>;
- resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>,
- <&serdes_wiz4 3>, <&serdes_wiz4 4>;
- };
-};
-
-&mhdp {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&dp0_pins_default>;
- phys = <&serdes4_dp_link>;
- phy-names = "dpphy";
-};
-
-&dss_ports {
- /* DP */
- port {
- dpi0_out: endpoint {
- remote-endpoint = <&dp0_in>;
- };
- };
-};
-
-&main_i2c4 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&main_i2c4_pins_default>;
- clock-frequency = <400000>;
-
- exp4: gpio@20 {
- compatible = "ti,tca6408";
- reg = <0x20>;
- gpio-controller;
- #gpio-cells = <2>;
- };
-};
-
-&dp0_ports {
- port@0 {
- reg = <0>;
-
- dp0_in: endpoint {
- remote-endpoint = <&dpi0_out>;
- };
- };
-
- port@4 {
- reg = <4>;
-
- dp0_out: endpoint {
- remote-endpoint = <&dp0_connector_in>;
- };
- };
-};
-
-&mcu_mcan0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_mcan0_pins_default>;
- phys = <&transceiver0>;
-};
-
-&mcu_mcan1 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mcu_mcan1_pins_default>;
- phys = <&transceiver1>;
-};
-
-&main_mcan16 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&main_mcan16_pins_default>;
- phys = <&transceiver2>;
-};
-
-&main_mcan4 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&main_mcan4_pins_default>;
- phys = <&transceiver3>;
-};
-
-&pcie1_rc {
- status = "okay";
- num-lanes = <2>;
- reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>;
- phys = <&serdes0_pcie1_link>;
- phy-names = "pcie-phy";
-};
-
-&serdes1 {
- status = "okay";
-
- serdes1_pcie0_link: phy@0 {
- reg = <0>;
- cdns,num-lanes = <4>;
- #phy-cells = <0>;
- cdns,phy-type = <PHY_TYPE_PCIE>;
- resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>,
- <&serdes_wiz1 3>, <&serdes_wiz1 4>;
- };
-};
-
-&serdes_wiz1 {
- status = "okay";
-};
-
-&pcie0_rc {
- status = "okay";
- reset-gpios = <&exp1 6 GPIO_ACTIVE_HIGH>;
- phys = <&serdes1_pcie0_link>;
- phy-names = "pcie-phy";
-};
-
-&k3_clks {
- /* Confiure AUDIO_EXT_REFCLK1 pin as output */
- pinctrl-names = "default";
- pinctrl-0 = <&audio_ext_refclk1_pins_default>;
-};
-
-&main_i2c3 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&main_i2c3_pins_default>;
- clock-frequency = <400000>;
-
- exp3: gpio@20 {
- compatible = "ti,tca6408";
- reg = <0x20>;
- gpio-controller;
- #gpio-cells = <2>;
- };
-
- pcm3168a_1: audio-codec@44 {
- compatible = "ti,pcm3168a";
- reg = <0x44>;
- #sound-dai-cells = <1>;
- reset-gpios = <&exp3 0 GPIO_ACTIVE_LOW>;
- clocks = <&audio_refclk1>;
- clock-names = "scki";
- VDD1-supply = <&vsys_3v3>;
- VDD2-supply = <&vsys_3v3>;
- VCCAD1-supply = <&vsys_5v0>;
- VCCAD2-supply = <&vsys_5v0>;
- VCCDA1-supply = <&vsys_5v0>;
- VCCDA2-supply = <&vsys_5v0>;
- };
-};
-
-&mcasp0 {
status = "okay";
- #sound-dai-cells = <0>;
- pinctrl-names = "default";
- pinctrl-0 = <&main_mcasp0_pins_default>;
- op-mode = <0>; /* MCASP_IIS_MODE */
- tdm-slots = <2>;
- auxclk-fs-ratio = <256>;
- serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
- 0 0 0 1
- 2 0 0 0
- 0 0 0 0
- 0 0 0 0
- >;
};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-common.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-common.dtsi
new file mode 100644
index 000000000000..1dceff119a47
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-common.dtsi
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source for J784S4 and J742S2 SoC Family
+ *
+ * TRM (j784s4) (SPRUJ43 JULY 2022): https://www.ti.com/lit/zip/spruj52
+ * TRM (j742s2): https://www.ti.com/lit/pdf/spruje3
+ *
+ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+#include "k3-pinctrl.h"
+
+/ {
+ interrupt-parent = <&gic500>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ L2_0: l2-cache0 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x200000>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ next-level-cache = <&msmc_l3>;
+ };
+
+ L2_1: l2-cache1 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x200000>;
+ cache-line-size = <64>;
+ cache-sets = <1024>;
+ next-level-cache = <&msmc_l3>;
+ };
+
+ msmc_l3: l3-cache0 {
+ compatible = "cache";
+ cache-level = <3>;
+ cache-unified;
+ };
+
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+
+ psci: psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+ };
+
+ a72_timer0: timer-cl0-cpu0 {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, /* cntpsirq */
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, /* cntpnsirq */
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, /* cntvirq */
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; /* cnthpirq */
+ };
+
+ pmu: pmu {
+ compatible = "arm,cortex-a72-pmu";
+ /* Recommendation from GIC500 TRM Table A.3 */
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ cbass_main: bus@100000 {
+ bootph-all;
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */
+ <0x00 0x00600000 0x00 0x00600000 0x00 0x00031100>, /* GPIO */
+ <0x00 0x00700000 0x00 0x00700000 0x00 0x00001000>, /* ESM */
+ <0x00 0x01000000 0x00 0x01000000 0x00 0x0d000000>, /* Most peripherals */
+ <0x00 0x04210000 0x00 0x04210000 0x00 0x00010000>, /* VPU0 */
+ <0x00 0x04220000 0x00 0x04220000 0x00 0x00010000>, /* VPU1 */
+ <0x00 0x0d000000 0x00 0x0d000000 0x00 0x00800000>, /* PCIe0 Core*/
+ <0x00 0x0d800000 0x00 0x0d800000 0x00 0x00800000>, /* PCIe1 Core*/
+ <0x00 0x0e000000 0x00 0x0e000000 0x00 0x00800000>, /* PCIe2 Core*/
+ <0x00 0x0e800000 0x00 0x0e800000 0x00 0x00800000>, /* PCIe3 Core*/
+ <0x00 0x10000000 0x00 0x10000000 0x00 0x08000000>, /* PCIe0 DAT0 */
+ <0x00 0x18000000 0x00 0x18000000 0x00 0x08000000>, /* PCIe1 DAT0 */
+ <0x00 0x64800000 0x00 0x64800000 0x00 0x0070c000>, /* C71_1 */
+ <0x00 0x65800000 0x00 0x65800000 0x00 0x0070c000>, /* C71_2 */
+ <0x00 0x66800000 0x00 0x66800000 0x00 0x0070c000>, /* C71_3 */
+ <0x00 0x67800000 0x00 0x67800000 0x00 0x0070c000>, /* C71_4 */
+ <0x00 0x6f000000 0x00 0x6f000000 0x00 0x00310000>, /* A72 PERIPHBASE */
+ <0x00 0x70000000 0x00 0x70000000 0x00 0x00400000>, /* MSMC RAM */
+ <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>, /* MAIN NAVSS */
+ <0x40 0x00000000 0x40 0x00000000 0x01 0x00000000>, /* PCIe0 DAT1 */
+ <0x41 0x00000000 0x41 0x00000000 0x01 0x00000000>, /* PCIe1 DAT1 */
+ <0x42 0x00000000 0x42 0x00000000 0x01 0x00000000>, /* PCIe2 DAT1 */
+ <0x43 0x00000000 0x43 0x00000000 0x01 0x00000000>, /* PCIe3 DAT1 */
+ <0x44 0x00000000 0x44 0x00000000 0x00 0x08000000>, /* PCIe2 DAT0 */
+ <0x44 0x10000000 0x44 0x10000000 0x00 0x08000000>, /* PCIe3 DAT0 */
+ <0x4e 0x20000000 0x4e 0x20000000 0x00 0x00080000>, /* GPU */
+
+ /* MCUSS_WKUP Range */
+ <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>,
+ <0x00 0x40200000 0x00 0x40200000 0x00 0x00998400>,
+ <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>,
+ <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>,
+ <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>,
+ <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00100000>,
+ <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>,
+ <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>,
+ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>,
+ <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>,
+ <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>,
+ <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>;
+
+ cbass_mcu_wakeup: bus@28380000 {
+ bootph-all;
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, /* MCU NAVSS*/
+ <0x00 0x40200000 0x00 0x40200000 0x00 0x00998400>, /* First peripheral window */
+ <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>, /* CTRL_MMR0 */
+ <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>, /* MCU R5F Core0 */
+ <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>, /* MCU R5F Core1 */
+ <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00100000>, /* MCU SRAM */
+ <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, /* WKUP peripheral window */
+ <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */
+ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */
+ <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, /* OSPI register space */
+ <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS data region 1 */
+ <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; /* FSS data region 0/3 */
+ };
+ };
+
+ thermal_zones: thermal-zones {
+ #include "k3-j784s4-j742s2-thermal-common.dtsi"
+ };
+};
+
+/* Now include peripherals from each bus segment */
+#include "k3-j784s4-j742s2-main-common.dtsi"
+#include "k3-j784s4-j742s2-mcu-wakeup-common.dtsi"
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi
new file mode 100644
index 000000000000..b2e2b9f507a9
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi
@@ -0,0 +1,1481 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * EVM Board Schematics(j784s4): https://www.ti.com/lit/zip/sprr458
+ * EVM Board Schematics(j742s2): https://www.ti.com/lit/zip/SPAC001
+ */
+/ {
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ aliases {
+ serial0 = &wkup_uart0;
+ serial1 = &mcu_uart0;
+ serial2 = &main_uart8;
+ mmc0 = &main_sdhci0;
+ mmc1 = &main_sdhci1;
+ i2c0 = &wkup_i2c0;
+ i2c3 = &main_i2c0;
+ ethernet0 = &mcu_cpsw_port1;
+ ethernet1 = &main_cpsw1_port1;
+ };
+
+ 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;
+ };
+
+ main_r5fss2_core0_dma_memory_region: r5f-dma-memory@a6000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss2_core0_memory_region: r5f-memory@a6100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss2_core1_dma_memory_region: r5f-dma-memory@a7000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss2_core1_memory_region: r5f-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;
+ };
+
+ c71_1_dma_memory_region: c71-dma-memory@a9000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa9000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_1_memory_region: c71-memory@a9100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa9100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_2_dma_memory_region: c71-dma-memory@aa000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xaa000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_2_memory_region: c71-memory@aa100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xaa100000 0x00 0xf00000>;
+ no-map;
+ };
+ };
+
+ evm_12v0: regulator-evm12v0 {
+ /* 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-vsys3v3 {
+ /* Output of LM5140 */
+ 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-vsys5v0 {
+ /* 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-sd {
+ /* Output of TPS22918 */
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_mmc1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ enable-active-high;
+ vin-supply = <&vsys_3v3>;
+ gpio = <&exp2 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ vdd_sd_dv: regulator-TLV71033 {
+ /* Output of TLV71033 */
+ compatible = "regulator-gpio";
+ regulator-name = "tlv71033";
+ pinctrl-names = "default";
+ pinctrl-0 = <&vdd_sd_dv_pins_default>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ vin-supply = <&vsys_5v0>;
+ gpios = <&main_gpio0 8 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x0>,
+ <3300000 0x1>;
+ };
+
+ dp0_pwr_3v3: regulator-dp0-prw {
+ compatible = "regulator-fixed";
+ regulator-name = "dp0-pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&exp4 0 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ dp0: connector-dp0 {
+ compatible = "dp-connector";
+ label = "DP0";
+ type = "full-size";
+ dp-pwr-supply = <&dp0_pwr_3v3>;
+
+ port {
+ dp0_connector_in: endpoint {
+ remote-endpoint = <&dp0_out>;
+ };
+ };
+ };
+
+ transceiver0: can-phy0 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mcan0_gpio_pins_default>;
+ standby-gpios = <&wkup_gpio0 69 GPIO_ACTIVE_HIGH>;
+ };
+
+ transceiver1: can-phy1 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mcan1_gpio_pins_default>;
+ standby-gpios = <&wkup_gpio0 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ transceiver2: can-phy2 {
+ /* standby pin has been grounded by default */
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ };
+
+ transceiver3: can-phy3 {
+ compatible = "ti,tcan1042";
+ #phy-cells = <0>;
+ max-bitrate = <5000000>;
+ standby-gpios = <&exp2 7 GPIO_ACTIVE_HIGH>;
+ mux-states = <&mux1 1>;
+ };
+
+ mux1: mux-controller {
+ compatible = "gpio-mux";
+ #mux-state-cells = <1>;
+ mux-gpios = <&exp2 14 GPIO_ACTIVE_HIGH>;
+ idle-state = <1>;
+ };
+
+ codec_audio: sound {
+ compatible = "ti,j7200-cpb-audio";
+ model = "j784s4-cpb";
+
+ ti,cpb-mcasp = <&mcasp0>;
+ ti,cpb-codec = <&pcm3168a_1>;
+
+ clocks = <&k3_clks 265 0>, <&k3_clks 265 1>,
+ <&k3_clks 157 34>, <&k3_clks 157 63>;
+ clock-names = "cpb-mcasp-auxclk", "cpb-mcasp-auxclk-48000",
+ "cpb-codec-scki", "cpb-codec-scki-48000";
+ };
+};
+
+&wkup_gpio0 {
+ status = "okay";
+};
+
+&main_pmx0 {
+ main_cpsw2g_default_pins: main-cpsw2g-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x0b8, PIN_INPUT, 6) /* (AC34) MCASP1_ACLKX.RGMII1_RD0 */
+ J784S4_IOPAD(0x0a0, PIN_INPUT, 6) /* (AD34) MCASP0_AXR12.RGMII1_RD1 */
+ J784S4_IOPAD(0x0a4, PIN_INPUT, 6) /* (AJ36) MCASP0_AXR13.RGMII1_RD2 */
+ J784S4_IOPAD(0x0a8, PIN_INPUT, 6) /* (AF34) MCASP0_AXR14.RGMII1_RD3 */
+ J784S4_IOPAD(0x0b0, PIN_INPUT, 6) /* (AL33) MCASP1_AXR3.RGMII1_RXC */
+ J784S4_IOPAD(0x0ac, PIN_INPUT, 6) /* (AE34) MCASP0_AXR15.RGMII1_RX_CTL */
+ J784S4_IOPAD(0x08c, PIN_INPUT, 6) /* (AE35) MCASP0_AXR7.RGMII1_TD0 */
+ J784S4_IOPAD(0x090, PIN_INPUT, 6) /* (AC35) MCASP0_AXR8.RGMII1_TD1 */
+ J784S4_IOPAD(0x094, PIN_INPUT, 6) /* (AG35) MCASP0_AXR9.RGMII1_TD2 */
+ J784S4_IOPAD(0x098, PIN_INPUT, 6) /* (AH36) MCASP0_AXR10.RGMII1_TD3 */
+ J784S4_IOPAD(0x0b4, PIN_INPUT, 6) /* (AL34) MCASP1_AXR4.RGMII1_TXC */
+ J784S4_IOPAD(0x09c, PIN_INPUT, 6) /* (AF35) MCASP0_AXR11.RGMII1_TX_CTL */
+ >;
+ };
+
+ main_cpsw2g_mdio_default_pins: main-cpsw2g-mdio-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x0c0, PIN_INPUT, 6) /* (AD38) MCASP1_AXR0.MDIO0_MDC */
+ J784S4_IOPAD(0x0bc, PIN_INPUT, 6) /* (AD33) MCASP1_AFSX.MDIO0_MDIO */
+ >;
+ };
+
+ main_uart8_pins_default: main-uart8-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x040, PIN_INPUT, 14) /* (AF37) MCASP0_AXR0.UART8_CTSn */
+ J784S4_IOPAD(0x044, PIN_OUTPUT, 14) /* (AG37) MCASP0_AXR1.UART8_RTSn */
+ J784S4_IOPAD(0x0d0, PIN_INPUT, 11) /* (AP38) SPI0_CS1.UART8_RXD */
+ J784S4_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AN38) SPI0_CLK.UART8_TXD */
+ >;
+ };
+
+ main_i2c0_pins_default: main-i2c0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x0e0, PIN_INPUT_PULLUP, 0) /* (AN36) I2C0_SCL */
+ J784S4_IOPAD(0x0e4, PIN_INPUT_PULLUP, 0) /* (AP37) I2C0_SDA */
+ >;
+ };
+
+ main_i2c5_pins_default: main-i2c5-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x01c, PIN_INPUT, 8) /* (AG34) MCAN15_TX.I2C5_SCL */
+ J784S4_IOPAD(0x018, PIN_INPUT, 8) /* (AK36) MCAN14_RX.I2C5_SDA */
+ >;
+ };
+
+ main_mmc1_pins_default: main-mmc1-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x104, PIN_INPUT, 0) /* (AB38) MMC1_CLK */
+ J784S4_IOPAD(0x108, PIN_INPUT, 0) /* (AB36) MMC1_CMD */
+ J784S4_IOPAD(0x100, PIN_INPUT, 0) /* (No Pin) MMC1_CLKLB */
+ J784S4_IOPAD(0x0fc, PIN_INPUT, 0) /* (AA33) MMC1_DAT0 */
+ J784S4_IOPAD(0x0f8, PIN_INPUT, 0) /* (AB34) MMC1_DAT1 */
+ J784S4_IOPAD(0x0f4, PIN_INPUT, 0) /* (AA32) MMC1_DAT2 */
+ J784S4_IOPAD(0x0f0, PIN_INPUT, 0) /* (AC38) MMC1_DAT3 */
+ J784S4_IOPAD(0x0e8, PIN_INPUT, 8) /* (AR38) TIMER_IO0.MMC1_SDCD */
+ >;
+ };
+
+ vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x020, PIN_INPUT, 7) /* (AJ35) MCAN15_RX.GPIO0_8 */
+ >;
+ };
+
+ dp0_pins_default: dp0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x0cc, PIN_INPUT, 12) /* (AM37) SPI0_CS0.DP0_HPD */
+ >;
+ };
+
+ main_i2c4_pins_default: main-i2c4-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AG33) MCAN14_TX.I2C4_SCL */
+ J784S4_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AH33) MCAN13_RX.I2C4_SDA */
+ >;
+ };
+
+ main_mcan4_pins_default: main-mcan4-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x088, PIN_INPUT, 0) /* (AF36) MCAN4_RX */
+ J784S4_IOPAD(0x084, PIN_OUTPUT, 0) /* (AG38) MCAN4_TX */
+ >;
+ };
+
+ main_mcan16_pins_default: main-mcan16-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x028, PIN_INPUT, 0) /* (AE33) MCAN16_RX */
+ J784S4_IOPAD(0x024, PIN_OUTPUT, 0) /* (AH34) MCAN16_TX */
+ >;
+ };
+
+ main_usbss0_pins_default: main-usbss0-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AN37) TIMER_IO1.USB0_DRVVBUS */
+ >;
+ };
+
+ main_i2c3_pins_default: main-i2c3-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x064, PIN_INPUT, 13) /* (AF38) MCAN0_TX.I2C3_SCL */
+ J784S4_IOPAD(0x060, PIN_INPUT, 13) /* (AE36) MCASP2_AXR1.I2C3_SDA */
+ >;
+ };
+
+ main_mcasp0_pins_default: main-mcasp0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x038, PIN_OUTPUT_PULLDOWN, 1) /* (AK35) MCASP0_ACLKX */
+ J784S4_IOPAD(0x03c, PIN_OUTPUT_PULLDOWN, 1) /* (AK38) MCASP0_AFSX */
+ J784S4_IOPAD(0x07c, PIN_OUTPUT_PULLDOWN, 1) /* (AJ38) MCASP0_AXR3 */
+ J784S4_IOPAD(0x080, PIN_INPUT_PULLDOWN, 1) /* (AK34) MCASP0_AXR4 */
+ >;
+ };
+
+ audio_ext_refclk1_pins_default: audio-ext-refclk1-default-pins {
+ pinctrl-single,pins = <
+ J784S4_IOPAD(0x078, PIN_OUTPUT, 1) /* (AH37) MCAN2_RX.AUDIO_EXT_REFCLK1 */
+ >;
+ };
+};
+
+&wkup_pmx2 {
+ wkup_uart0_pins_default: wkup-uart0-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (K35) WKUP_UART0_RXD */
+ J784S4_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (K34) WKUP_UART0_TXD */
+ >;
+ };
+
+ wkup_i2c0_pins_default: wkup-i2c0-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x98, PIN_INPUT, 0) /* (N33) WKUP_I2C0_SCL */
+ J784S4_WKUP_IOPAD(0x9c, PIN_INPUT, 0) /* (N35) WKUP_I2C0_SDA */
+ >;
+ };
+
+ mcu_uart0_pins_default: mcu-uart0-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (H37) WKUP_GPIO0_14.MCU_UART0_CTSn */
+ J784S4_WKUP_IOPAD(0x094, PIN_OUTPUT, 0) /* (K37) WKUP_GPIO0_15.MCU_UART0_RTSn */
+ J784S4_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (K38) WKUP_GPIO0_13.MCU_UART0_RXD */
+ J784S4_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (J37) WKUP_GPIO0_12.MCU_UART0_TXD */
+ >;
+ };
+
+ mcu_cpsw_pins_default: mcu-cpsw-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (A35) MCU_RGMII1_RD0 */
+ J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B36) MCU_RGMII1_RD1 */
+ J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C36) MCU_RGMII1_RD2 */
+ J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D36) MCU_RGMII1_RD3 */
+ J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (B37) MCU_RGMII1_RXC */
+ J784S4_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (C37) MCU_RGMII1_RX_CTL */
+ J784S4_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (D37) MCU_RGMII1_TD0 */
+ J784S4_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (D38) MCU_RGMII1_TD1 */
+ J784S4_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E37) MCU_RGMII1_TD2 */
+ J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E38) MCU_RGMII1_TD3 */
+ J784S4_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (E36) MCU_RGMII1_TXC */
+ J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (C38) MCU_RGMII1_TX_CTL */
+ >;
+ };
+
+ mcu_mdio_pins_default: mcu-mdio-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A36) MCU_MDIO0_MDC */
+ J784S4_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (B35) MCU_MDIO0_MDIO */
+ >;
+ };
+
+ mcu_adc0_pins_default: mcu-adc0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x0cc, PIN_INPUT, 0) /* (P36) MCU_ADC0_AIN0 */
+ J784S4_WKUP_IOPAD(0x0d0, PIN_INPUT, 0) /* (V36) MCU_ADC0_AIN1 */
+ J784S4_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (T34) MCU_ADC0_AIN2 */
+ J784S4_WKUP_IOPAD(0x0d8, PIN_INPUT, 0) /* (T36) MCU_ADC0_AIN3 */
+ J784S4_WKUP_IOPAD(0x0dc, PIN_INPUT, 0) /* (P34) MCU_ADC0_AIN4 */
+ J784S4_WKUP_IOPAD(0x0e0, PIN_INPUT, 0) /* (R37) MCU_ADC0_AIN5 */
+ J784S4_WKUP_IOPAD(0x0e4, PIN_INPUT, 0) /* (R33) MCU_ADC0_AIN6 */
+ J784S4_WKUP_IOPAD(0x0e8, PIN_INPUT, 0) /* (V38) MCU_ADC0_AIN7 */
+ >;
+ };
+
+ mcu_adc1_pins_default: mcu-adc1-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x0ec, PIN_INPUT, 0) /* (Y38) MCU_ADC1_AIN0 */
+ J784S4_WKUP_IOPAD(0x0f0, PIN_INPUT, 0) /* (Y34) MCU_ADC1_AIN1 */
+ J784S4_WKUP_IOPAD(0x0f4, PIN_INPUT, 0) /* (V34) MCU_ADC1_AIN2 */
+ J784S4_WKUP_IOPAD(0x0f8, PIN_INPUT, 0) /* (W37) MCU_ADC1_AIN3 */
+ J784S4_WKUP_IOPAD(0x0fc, PIN_INPUT, 0) /* (AA37) MCU_ADC1_AIN4 */
+ J784S4_WKUP_IOPAD(0x100, PIN_INPUT, 0) /* (W33) MCU_ADC1_AIN5 */
+ J784S4_WKUP_IOPAD(0x104, PIN_INPUT, 0) /* (U33) MCU_ADC1_AIN6 */
+ J784S4_WKUP_IOPAD(0x108, PIN_INPUT, 0) /* (Y36) MCU_ADC1_AIN7 */
+ >;
+ };
+
+ mcu_mcan0_pins_default: mcu-mcan0-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (K33) MCU_MCAN0_TX */
+ J784S4_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (F38) MCU_MCAN0_RX */
+ >;
+ };
+
+ mcu_mcan1_pins_default: mcu-mcan1-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (H35) WKUP_GPIO0_4.MCU_MCAN1_TX */
+ J784S4_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (K36) WKUP_GPIO0_5.MCU_MCAN1_RX */
+ >;
+ };
+
+ mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x040, PIN_INPUT, 7) /* (J38) MCU_SPI0_D1.WKUP_GPIO0_69 */
+ >;
+ };
+
+ mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-default-pins {
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (J35) WKUP_GPIO0_2 */
+ >;
+ };
+};
+
+&wkup_pmx1 {
+ status = "okay";
+
+ pmic_irq_pins_default: pmic-irq-default-pins {
+ pinctrl-single,pins = <
+ /* (G33) MCU_OSPI1_CSn1.WKUP_GPIO0_39 */
+ J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 7)
+ >;
+ };
+};
+
+&wkup_pmx0 {
+ mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (E32) MCU_OSPI0_CLK */
+ J784S4_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (A32) MCU_OSPI0_CSn0 */
+ J784S4_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B33) MCU_OSPI0_D0 */
+ J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B32) MCU_OSPI0_D1 */
+ J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (C33) MCU_OSPI0_D2 */
+ J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (C35) MCU_OSPI0_D3 */
+ J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D33) MCU_OSPI0_D4 */
+ J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D34) MCU_OSPI0_D5 */
+ J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (E34) MCU_OSPI0_D6 */
+ J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (E33) MCU_OSPI0_D7 */
+ J784S4_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (C34) MCU_OSPI0_DQS */
+ >;
+ };
+};
+
+&wkup_pmx1 {
+ mcu_fss0_ospi0_1_pins_default: mcu-fss0-ospi0-1-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x004, PIN_OUTPUT, 6) /* (C32) MCU_OSPI0_ECC_FAIL */
+ J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 6) /* (B34) MCU_OSPI0_RESET_OUT0 */
+ >;
+ };
+
+ mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+ J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (F32) MCU_OSPI1_CLK */
+ J784S4_WKUP_IOPAD(0x024, PIN_OUTPUT, 0) /* (G32) MCU_OSPI1_CSn0 */
+ J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (E35) MCU_OSPI1_D0 */
+ J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (D31) MCU_OSPI1_D1 */
+ J784S4_WKUP_IOPAD(0x01C, PIN_INPUT, 0) /* (G31) MCU_OSPI1_D2 */
+ J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (F33) MCU_OSPI1_D3 */
+ J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (F31) MCU_OSPI1_DQS */
+ J784S4_WKUP_IOPAD(0x00C, PIN_INPUT, 0) /* (C31) MCU_OSPI1_LBCLKO */
+ >;
+ };
+};
+
+&wkup_uart0 {
+ /* Firmware usage */
+ status = "reserved";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wkup_uart0_pins_default>;
+};
+
+&wkup_i2c0 {
+ bootph-all;
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wkup_i2c0_pins_default>;
+ clock-frequency = <400000>;
+
+ eeprom@50 {
+ /* CAV24C256WE-GT3 */
+ compatible = "atmel,24c256";
+ reg = <0x50>;
+ };
+
+ tps659413: pmic@48 {
+ compatible = "ti,tps6594-q1";
+ reg = <0x48>;
+ system-power-controller;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_irq_pins_default>;
+ interrupt-parent = <&wkup_gpio0>;
+ interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ti,primary-pmic;
+ buck12-supply = <&vsys_3v3>;
+ buck3-supply = <&vsys_3v3>;
+ buck4-supply = <&vsys_3v3>;
+ buck5-supply = <&vsys_3v3>;
+ ldo1-supply = <&vsys_3v3>;
+ ldo2-supply = <&vsys_3v3>;
+ ldo3-supply = <&vsys_3v3>;
+ ldo4-supply = <&vsys_3v3>;
+
+ regulators {
+ bucka12: buck12 {
+ regulator-name = "vdd_ddr_1v1";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ bucka3: buck3 {
+ regulator-name = "vdd_ram_0v85";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ bucka4: buck4 {
+ regulator-name = "vdd_io_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ bucka5: buck5 {
+ regulator-name = "vdd_mcu_0v85";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldoa1: ldo1 {
+ regulator-name = "vdd_mcuio_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldoa2: ldo2 {
+ regulator-name = "vdd_mcuio_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldoa3: ldo3 {
+ regulator-name = "vds_dll_0v8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldoa4: ldo4 {
+ regulator-name = "vda_mcu_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+
+ tps62873a: regulator@40 {
+ compatible = "ti,tps62873";
+ reg = <0x40>;
+ bootph-pre-ram;
+ regulator-name = "VDD_CPU_AVS";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1330000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ tps62873b: regulator@43 {
+ compatible = "ti,tps62873";
+ reg = <0x43>;
+ regulator-name = "VDD_CORE_0V8";
+ regulator-min-microvolt = <760000>;
+ regulator-max-microvolt = <840000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
+&mcu_uart0 {
+ bootph-all;
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_uart0_pins_default>;
+};
+
+&main_uart8 {
+ bootph-all;
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_uart8_pins_default>;
+};
+
+&ufs_wrapper {
+ status = "okay";
+};
+
+&fss {
+ status = "okay";
+};
+
+&ospi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_fss0_ospi0_pins_default>, <&mcu_fss0_ospi0_1_pins_default>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-tx-bus-width = <8>;
+ spi-rx-bus-width = <8>;
+ spi-max-frequency = <25000000>;
+ cdns,tshsl-ns = <60>;
+ cdns,tsd2d-ns = <60>;
+ cdns,tchsh-ns = <60>;
+ cdns,tslch-ns = <60>;
+ cdns,read-delay = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "ospi.tiboot3";
+ reg = <0x0 0x80000>;
+ };
+
+ partition@80000 {
+ label = "ospi.tispl";
+ reg = <0x80000 0x200000>;
+ };
+
+ partition@280000 {
+ label = "ospi.u-boot";
+ reg = <0x280000 0x400000>;
+ };
+
+ partition@680000 {
+ label = "ospi.env";
+ reg = <0x680000 0x40000>;
+ };
+
+ partition@6c0000 {
+ label = "ospi.env.backup";
+ reg = <0x6c0000 0x40000>;
+ };
+
+ partition@800000 {
+ label = "ospi.rootfs";
+ reg = <0x800000 0x37c0000>;
+ };
+
+ partition@3fc0000 {
+ bootph-all;
+ label = "ospi.phypattern";
+ reg = <0x3fc0000 0x40000>;
+ };
+ };
+ };
+};
+
+&ospi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_fss0_ospi1_pins_default>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <40000000>;
+ cdns,tshsl-ns = <60>;
+ cdns,tsd2d-ns = <60>;
+ cdns,tchsh-ns = <60>;
+ cdns,tslch-ns = <60>;
+ cdns,read-delay = <2>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "qspi.tiboot3";
+ reg = <0x0 0x80000>;
+ };
+
+ partition@80000 {
+ label = "qspi.tispl";
+ reg = <0x80000 0x200000>;
+ };
+
+ partition@280000 {
+ label = "qspi.u-boot";
+ reg = <0x280000 0x400000>;
+ };
+
+ partition@680000 {
+ label = "qspi.env";
+ reg = <0x680000 0x40000>;
+ };
+
+ partition@6c0000 {
+ label = "qspi.env.backup";
+ reg = <0x6c0000 0x40000>;
+ };
+
+ partition@800000 {
+ label = "qspi.rootfs";
+ reg = <0x800000 0x37c0000>;
+ };
+
+ partition@3fc0000 {
+ bootph-all;
+ label = "qspi.phypattern";
+ reg = <0x3fc0000 0x40000>;
+ };
+ };
+
+ };
+};
+
+&main_i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c0_pins_default>;
+
+ clock-frequency = <400000>;
+
+ exp1: gpio@20 {
+ compatible = "ti,tca6416";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "PCIE1_2L_MODE_SEL", "PCIE1_4L_PERSTZ", "PCIE1_2L_RC_RSTZ",
+ "PCIE1_2L_EP_RST_EN", "PCIE0_4L_MODE_SEL", "PCIE0_4L_PERSTZ",
+ "PCIE0_4L_RC_RSTZ", "PCIE0_4L_EP_RST_EN", "PCIE1_4L_PRSNT#",
+ "PCIE0_4L_PRSNT#", "CDCI1_OE1/OE4", "CDCI1_OE2/OE3",
+ "AUDIO_MUX_SEL", "EXP_MUX2", "EXP_MUX3", "GESI_EXP_PHY_RSTZ";
+
+ p12-hog {
+ /* P12 - AUDIO_MUX_SEL */
+ gpio-hog;
+ gpios = <12 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "AUDIO_MUX_SEL";
+ };
+ };
+
+ exp2: gpio@22 {
+ compatible = "ti,tca6424";
+ reg = <0x22>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "R_GPIO_RGMII1_RST", "ENET2_I2CMUX_SEL", "GPIO_USD_PWR_EN",
+ "USBC_PWR_EN", "USBC_MODE_SEL1", "USBC_MODE_SEL0",
+ "GPIO_LIN_EN", "R_CAN_STB", "CTRL_PM_I2C_OE#",
+ "ENET2_EXP_PWRDN", "ENET2_EXP_SPARE2", "CDCI2_RSTZ",
+ "USB2.0_MUX_SEL", "CANUART_MUX_SEL0", "CANUART_MUX2_SEL1",
+ "CANUART_MUX1_SEL1", "ENET1_EXP_PWRDN", "ENET1_EXP_RESETZ",
+ "ENET1_I2CMUX_SEL", "ENET1_EXP_SPARE2", "ENET2_EXP_RESETZ",
+ "USER_INPUT1", "USER_LED1", "USER_LED2";
+
+ p13-hog {
+ /* P13 - CANUART_MUX_SEL0 */
+ gpio-hog;
+ gpios = <13 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "CANUART_MUX_SEL0";
+ };
+
+ p15-hog {
+ /* P15 - CANUART_MUX1_SEL1 */
+ gpio-hog;
+ gpios = <15 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "CANUART_MUX1_SEL1";
+ };
+ };
+};
+
+&main_i2c5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c5_pins_default>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ exp5: gpio@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "CSI2_EXP_RSTZ", "CSI2_EXP_A_GPIO0",
+ "CSI2_EXP_A_GPIO1", "CSI2_EXP_A_GPIO3",
+ "CSI2_EXP_B_GPIO1", "CSI2_EXP_B_GPIO2",
+ "CSI2_EXP_B_GPIO3", "CSI2_EXP_B_GPIO4";
+ };
+};
+
+&main_sdhci0 {
+ bootph-all;
+ /* eMMC */
+ status = "okay";
+ non-removable;
+ ti,driver-strength-ohm = <50>;
+ disable-wp;
+};
+
+&main_sdhci1 {
+ bootph-all;
+ /* SD card */
+ status = "okay";
+ pinctrl-0 = <&main_mmc1_pins_default>;
+ pinctrl-names = "default";
+ disable-wp;
+ vmmc-supply = <&vdd_mmc1>;
+ vqmmc-supply = <&vdd_sd_dv>;
+};
+
+&main_gpio0 {
+ status = "okay";
+};
+
+&mcu_cpsw {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_cpsw_pins_default>;
+};
+
+&davinci_mdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mdio_pins_default>;
+
+ mcu_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>;
+ ti,min-output-impedance;
+ };
+};
+
+&mcu_cpsw_port1 {
+ status = "okay";
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&mcu_phy0>;
+};
+
+&main_cpsw1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_cpsw2g_default_pins>;
+ status = "okay";
+};
+
+&main_cpsw1_mdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_cpsw2g_mdio_default_pins>;
+ status = "okay";
+
+ main_cpsw1_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>;
+ ti,min-output-impedance;
+ };
+};
+
+&main_cpsw1_port1 {
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&main_cpsw1_phy0>;
+ status = "okay";
+};
+
+&mailbox0_cluster0 {
+ status = "okay";
+ 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 {
+ status = "okay";
+ 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 {
+ status = "okay";
+ 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 {
+ status = "okay";
+ interrupts = <424>;
+
+ mbox_main_r5fss2_core0: mbox-main-r5fss2-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss2_core1: mbox-main-r5fss2-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster4 {
+ status = "okay";
+ interrupts = <420>;
+
+ mbox_c71_0: mbox-c71-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_c71_1: mbox-c71-1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster5 {
+ status = "okay";
+ interrupts = <416>;
+
+ mbox_c71_2: mbox-c71-2 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+};
+
+&mcu_r5fss0_core0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+ memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+ <&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+ memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+ <&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0 {
+ ti,cluster-mode = <0>;
+};
+
+&main_r5fss1 {
+ ti,cluster-mode = <0>;
+};
+
+&main_r5fss2 {
+ ti,cluster-mode = <0>;
+};
+
+/* Timers are used by Remoteproc firmware */
+&main_timer0 {
+ status = "reserved";
+};
+
+&main_timer1 {
+ status = "reserved";
+};
+
+&main_timer2 {
+ status = "reserved";
+};
+
+&main_timer3 {
+ status = "reserved";
+};
+
+&main_timer4 {
+ status = "reserved";
+};
+
+&main_timer5 {
+ status = "reserved";
+};
+
+&main_timer6 {
+ status = "reserved";
+};
+
+&main_timer7 {
+ status = "reserved";
+};
+
+&main_timer8 {
+ status = "reserved";
+};
+
+&main_timer9 {
+ status = "reserved";
+};
+
+&main_r5fss0_core0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+ memory-region = <&main_r5fss0_core0_dma_memory_region>,
+ <&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+ memory-region = <&main_r5fss0_core1_dma_memory_region>,
+ <&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+ memory-region = <&main_r5fss1_core0_dma_memory_region>,
+ <&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+ memory-region = <&main_r5fss1_core1_dma_memory_region>,
+ <&main_r5fss1_core1_memory_region>;
+};
+
+&main_r5fss2_core0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core0>;
+ memory-region = <&main_r5fss2_core0_dma_memory_region>,
+ <&main_r5fss2_core0_memory_region>;
+};
+
+&main_r5fss2_core1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core1>;
+ memory-region = <&main_r5fss2_core1_dma_memory_region>,
+ <&main_r5fss2_core1_memory_region>;
+};
+
+&c71_0 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+ memory-region = <&c71_0_dma_memory_region>,
+ <&c71_0_memory_region>;
+};
+
+&c71_1 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster4 &mbox_c71_1>;
+ memory-region = <&c71_1_dma_memory_region>,
+ <&c71_1_memory_region>;
+};
+
+&c71_2 {
+ status = "okay";
+ mboxes = <&mailbox0_cluster5 &mbox_c71_2>;
+ memory-region = <&c71_2_dma_memory_region>,
+ <&c71_2_memory_region>;
+};
+
+&tscadc0 {
+ pinctrl-0 = <&mcu_adc0_pins_default>;
+ pinctrl-names = "default";
+ status = "okay";
+ adc {
+ ti,adc-channels = <0 1 2 3 4 5 6 7>;
+ };
+};
+
+&tscadc1 {
+ pinctrl-0 = <&mcu_adc1_pins_default>;
+ pinctrl-names = "default";
+ status = "okay";
+ adc {
+ ti,adc-channels = <0 1 2 3 4 5 6 7>;
+ };
+};
+
+&serdes_refclk {
+ status = "okay";
+ clock-frequency = <100000000>;
+};
+
+&dss {
+ status = "okay";
+ assigned-clocks = <&k3_clks 218 2>,
+ <&k3_clks 218 5>,
+ <&k3_clks 218 14>,
+ <&k3_clks 218 18>;
+ assigned-clock-parents = <&k3_clks 218 3>,
+ <&k3_clks 218 7>,
+ <&k3_clks 218 16>,
+ <&k3_clks 218 22>;
+};
+
+&serdes0 {
+ status = "okay";
+
+ serdes0_pcie1_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <2>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>;
+ };
+
+ serdes0_usb_link: phy@3 {
+ reg = <3>;
+ cdns,num-lanes = <1>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_USB3>;
+ resets = <&serdes_wiz0 4>;
+ };
+};
+
+&serdes_wiz0 {
+ status = "okay";
+};
+
+&usb_serdes_mux {
+ idle-states = <0>; /* USB0 to SERDES lane 3 */
+};
+
+&usbss0 {
+ status = "okay";
+ pinctrl-0 = <&main_usbss0_pins_default>;
+ pinctrl-names = "default";
+ ti,vbus-divider;
+};
+
+&usb0 {
+ dr_mode = "otg";
+ maximum-speed = "super-speed";
+ phys = <&serdes0_usb_link>;
+ phy-names = "cdns3,usb3-phy";
+};
+
+&serdes_wiz4 {
+ status = "okay";
+};
+
+&serdes4 {
+ status = "okay";
+ serdes4_dp_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <4>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_DP>;
+ resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>,
+ <&serdes_wiz4 3>, <&serdes_wiz4 4>;
+ };
+};
+
+&mhdp {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp0_pins_default>;
+ phys = <&serdes4_dp_link>;
+ phy-names = "dpphy";
+};
+
+&dss_ports {
+ /* DP */
+ port {
+ dpi0_out: endpoint {
+ remote-endpoint = <&dp0_in>;
+ };
+ };
+};
+
+&main_i2c4 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c4_pins_default>;
+ clock-frequency = <400000>;
+
+ exp4: gpio@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
+&dp0_ports {
+ port@0 {
+ reg = <0>;
+
+ dp0_in: endpoint {
+ remote-endpoint = <&dpi0_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+
+ dp0_out: endpoint {
+ remote-endpoint = <&dp0_connector_in>;
+ };
+ };
+};
+
+&mcu_mcan0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mcan0_pins_default>;
+ phys = <&transceiver0>;
+};
+
+&mcu_mcan1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mcan1_pins_default>;
+ phys = <&transceiver1>;
+};
+
+&main_mcan16 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan16_pins_default>;
+ phys = <&transceiver2>;
+};
+
+&main_mcan4 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcan4_pins_default>;
+ phys = <&transceiver3>;
+};
+
+&pcie1_rc {
+ status = "okay";
+ num-lanes = <2>;
+ reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes0_pcie1_link>;
+ phy-names = "pcie-phy";
+};
+
+&serdes1 {
+ status = "okay";
+
+ serdes1_pcie0_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <4>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>,
+ <&serdes_wiz1 3>, <&serdes_wiz1 4>;
+ };
+};
+
+&serdes_wiz1 {
+ status = "okay";
+};
+
+&pcie0_rc {
+ status = "okay";
+ reset-gpios = <&exp1 6 GPIO_ACTIVE_HIGH>;
+ phys = <&serdes1_pcie0_link>;
+ phy-names = "pcie-phy";
+};
+
+&k3_clks {
+ /* Confiure AUDIO_EXT_REFCLK1 pin as output */
+ pinctrl-names = "default";
+ pinctrl-0 = <&audio_ext_refclk1_pins_default>;
+};
+
+&main_i2c3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c3_pins_default>;
+ clock-frequency = <400000>;
+
+ exp3: gpio@20 {
+ compatible = "ti,tca6408";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ pcm3168a_1: audio-codec@44 {
+ compatible = "ti,pcm3168a";
+ reg = <0x44>;
+ #sound-dai-cells = <1>;
+ reset-gpios = <&exp3 0 GPIO_ACTIVE_LOW>;
+ clocks = <&audio_refclk1>;
+ clock-names = "scki";
+ VDD1-supply = <&vsys_3v3>;
+ VDD2-supply = <&vsys_3v3>;
+ VCCAD1-supply = <&vsys_5v0>;
+ VCCAD2-supply = <&vsys_5v0>;
+ VCCDA1-supply = <&vsys_5v0>;
+ VCCDA2-supply = <&vsys_5v0>;
+ };
+};
+
+&mcasp0 {
+ status = "okay";
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mcasp0_pins_default>;
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ auxclk-fs-ratio = <256>;
+ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+ 0 0 0 1
+ 2 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
new file mode 100644
index 000000000000..7721852c1f68
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-main-common.dtsi
@@ -0,0 +1,2671 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Device Tree Source for J784S4 and J742S2 SoC Family Main Domain peripherals
+ *
+ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/mux/mux.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-ti.h>
+
+#include "k3-serdes.h"
+
+/ {
+ serdes_refclk: clock-serdes {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ /* To be enabled when serdes_wiz* is functional */
+ status = "disabled";
+ };
+};
+
+&cbass_main {
+ /*
+ * MSMC is configured by bootloaders and a runtime fixup is done in the
+ * DT for this node
+ */
+ msmc_ram: sram@70000000 {
+ compatible = "mmio-sram";
+ reg = <0x00 0x70000000 0x00 0x800000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x00 0x00 0x70000000 0x800000>;
+
+ atf-sram@0 {
+ reg = <0x00 0x20000>;
+ };
+
+ tifs-sram@1f0000 {
+ reg = <0x1f0000 0x10000>;
+ };
+
+ l3cache-sram@200000 {
+ reg = <0x200000 0x200000>;
+ };
+ };
+
+ scm_conf: bus@100000 {
+ compatible = "simple-bus";
+ reg = <0x00 0x00100000 0x00 0x1c000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x00 0x00 0x00100000 0x1c000>;
+
+ cpsw1_phy_gmii_sel: phy@4034 {
+ compatible = "ti,am654-phy-gmii-sel";
+ reg = <0x4034 0x4>;
+ #phy-cells = <1>;
+ };
+
+ cpsw0_phy_gmii_sel: phy@4044 {
+ compatible = "ti,j784s4-cpsw9g-phy-gmii-sel";
+ reg = <0x4044 0x20>;
+ #phy-cells = <1>;
+ ti,qsgmii-main-ports = <7>, <7>;
+ };
+
+ pcie0_ctrl: pcie0-ctrl@4070 {
+ compatible = "ti,j784s4-pcie-ctrl", "syscon";
+ reg = <0x4070 0x4>;
+ };
+
+ pcie1_ctrl: pcie1-ctrl@4074 {
+ compatible = "ti,j784s4-pcie-ctrl", "syscon";
+ reg = <0x4074 0x4>;
+ };
+
+ serdes_ln_ctrl: mux-controller@4080 {
+ compatible = "reg-mux";
+ reg = <0x00004080 0x30>;
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x0 0x3>, <0x4 0x3>, /* SERDES0 lane0/1 select */
+ <0x8 0x3>, <0xc 0x3>, /* SERDES0 lane2/3 select */
+ <0x10 0x3>, <0x14 0x3>, /* SERDES1 lane0/1 select */
+ <0x18 0x3>, <0x1c 0x3>, /* SERDES1 lane2/3 select */
+ <0x20 0x3>, <0x24 0x3>, /* SERDES2 lane0/1 select */
+ <0x28 0x3>, <0x2c 0x3>; /* SERDES2 lane2/3 select */
+ idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>,
+ <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+ <J784S4_SERDES0_LANE2_IP3_UNUSED>,
+ <J784S4_SERDES0_LANE3_USB>,
+ <J784S4_SERDES1_LANE0_PCIE0_LANE0>,
+ <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+ <J784S4_SERDES1_LANE2_PCIE0_LANE2>,
+ <J784S4_SERDES1_LANE3_PCIE0_LANE3>,
+ <J784S4_SERDES2_LANE0_IP2_UNUSED>,
+ <J784S4_SERDES2_LANE1_IP2_UNUSED>,
+ <J784S4_SERDES2_LANE2_QSGMII_LANE1>,
+ <J784S4_SERDES2_LANE3_QSGMII_LANE2>,
+ <J784S4_SERDES4_LANE0_EDP_LANE0>,
+ <J784S4_SERDES4_LANE1_EDP_LANE1>,
+ <J784S4_SERDES4_LANE2_EDP_LANE2>,
+ <J784S4_SERDES4_LANE3_EDP_LANE3>;
+ };
+
+ usb_serdes_mux: mux-controller@4000 {
+ compatible = "reg-mux";
+ reg = <0x4000 0x4>;
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x0 0x8000000>; /* USB0 to SERDES0 lane 3 mux */
+ };
+
+ ehrpwm_tbclk: clock-controller@4140 {
+ compatible = "ti,am654-ehrpwm-tbclk";
+ reg = <0x4140 0x18>;
+ #clock-cells = <1>;
+ };
+
+ audio_refclk1: clock@82e4 {
+ compatible = "ti,am62-audio-refclk";
+ reg = <0x82e4 0x4>;
+ clocks = <&k3_clks 157 34>;
+ assigned-clocks = <&k3_clks 157 34>;
+ assigned-clock-parents = <&k3_clks 157 63>;
+ #clock-cells = <0>;
+ };
+ };
+
+ main_ehrpwm0: pwm@3000000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ reg = <0x00 0x3000000 0x00 0x100>;
+ clocks = <&ehrpwm_tbclk 0>, <&k3_clks 219 0>;
+ clock-names = "tbclk", "fck";
+ power-domains = <&k3_pds 219 TI_SCI_PD_EXCLUSIVE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ main_ehrpwm1: pwm@3010000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ reg = <0x00 0x3010000 0x00 0x100>;
+ clocks = <&ehrpwm_tbclk 1>, <&k3_clks 220 0>;
+ clock-names = "tbclk", "fck";
+ power-domains = <&k3_pds 220 TI_SCI_PD_EXCLUSIVE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ main_ehrpwm2: pwm@3020000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ reg = <0x00 0x3020000 0x00 0x100>;
+ clocks = <&ehrpwm_tbclk 2>, <&k3_clks 221 0>;
+ clock-names = "tbclk", "fck";
+ power-domains = <&k3_pds 221 TI_SCI_PD_EXCLUSIVE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ main_ehrpwm3: pwm@3030000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ reg = <0x00 0x3030000 0x00 0x100>;
+ clocks = <&ehrpwm_tbclk 3>, <&k3_clks 222 0>;
+ clock-names = "tbclk", "fck";
+ power-domains = <&k3_pds 222 TI_SCI_PD_EXCLUSIVE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ main_ehrpwm4: pwm@3040000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ reg = <0x00 0x3040000 0x00 0x100>;
+ clocks = <&ehrpwm_tbclk 4>, <&k3_clks 223 0>;
+ clock-names = "tbclk", "fck";
+ power-domains = <&k3_pds 223 TI_SCI_PD_EXCLUSIVE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ main_ehrpwm5: pwm@3050000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ reg = <0x00 0x3050000 0x00 0x100>;
+ clocks = <&ehrpwm_tbclk 5>, <&k3_clks 224 0>;
+ clock-names = "tbclk", "fck";
+ power-domains = <&k3_pds 224 TI_SCI_PD_EXCLUSIVE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ gic500: interrupt-controller@1800000 {
+ compatible = "arm,gic-v3";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00 0x01800000 0x00 0x200000>, /* GICD */
+ <0x00 0x01900000 0x00 0x100000>, /* GICR */
+ <0x00 0x6f000000 0x00 0x2000>, /* GICC */
+ <0x00 0x6f010000 0x00 0x1000>, /* GICH */
+ <0x00 0x6f020000 0x00 0x2000>; /* GICV */
+
+ /* vcpumntirq: virtual CPU interface maintenance interrupt */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+ gic_its: msi-controller@1820000 {
+ compatible = "arm,gic-v3-its";
+ reg = <0x00 0x01820000 0x00 0x10000>;
+ socionext,synquacer-pre-its = <0x1000000 0x400000>;
+ msi-controller;
+ #msi-cells = <1>;
+ };
+ };
+
+ main_gpio_intr: interrupt-controller@a00000 {
+ compatible = "ti,sci-intr";
+ reg = <0x00 0x00a00000 0x00 0x800>;
+ ti,intr-trigger-type = <1>;
+ interrupt-controller;
+ interrupt-parent = <&gic500>;
+ #interrupt-cells = <1>;
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <10>;
+ ti,interrupt-ranges = <8 392 56>;
+ };
+
+ main_pmx0: pinctrl@11c000 {
+ compatible = "pinctrl-single";
+ /* Proxy 0 addressing */
+ reg = <0x00 0x11c000 0x00 0x120>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0xffffffff>;
+ };
+
+ /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */
+ main_timerio_input: pinctrl@104200 {
+ compatible = "pinctrl-single";
+ reg = <0x00 0x104200 0x00 0x50>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x00000007>;
+ };
+
+ /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */
+ main_timerio_output: pinctrl@104280 {
+ compatible = "pinctrl-single";
+ reg = <0x00 0x104280 0x00 0x20>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x0000001f>;
+ };
+
+ main_crypto: crypto@4e00000 {
+ compatible = "ti,j721e-sa2ul";
+ reg = <0x00 0x4e00000 0x00 0x1200>;
+ power-domains = <&k3_pds 369 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 0x4e10000 0x00 0x7d>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ main_timer0: timer@2400000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2400000 0x00 0x400>;
+ interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 97 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 97 2>;
+ assigned-clock-parents = <&k3_clks 97 3>;
+ power-domains = <&k3_pds 97 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 98 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 98 2>;
+ assigned-clock-parents = <&k3_clks 98 3>;
+ power-domains = <&k3_pds 98 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 99 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 99 2>;
+ assigned-clock-parents = <&k3_clks 99 3>;
+ power-domains = <&k3_pds 99 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 100 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 100 2>;
+ assigned-clock-parents = <&k3_clks 100 3>;
+ power-domains = <&k3_pds 100 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 101 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 101 2>;
+ assigned-clock-parents = <&k3_clks 101 3>;
+ power-domains = <&k3_pds 101 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 102 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 102 2>;
+ assigned-clock-parents = <&k3_clks 102 3>;
+ power-domains = <&k3_pds 102 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 103 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 103 2>;
+ assigned-clock-parents = <&k3_clks 103 3>;
+ power-domains = <&k3_pds 103 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 104 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 104 2>;
+ assigned-clock-parents = <&k3_clks 104 3>;
+ power-domains = <&k3_pds 104 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 105 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 105 2>;
+ assigned-clock-parents = <&k3_clks 105 3>;
+ power-domains = <&k3_pds 105 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 106 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 106 2>;
+ assigned-clock-parents = <&k3_clks 106 3>;
+ power-domains = <&k3_pds 106 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 107 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 107 2>;
+ assigned-clock-parents = <&k3_clks 107 3>;
+ power-domains = <&k3_pds 107 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 108 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 108 2>;
+ assigned-clock-parents = <&k3_clks 108 3>;
+ power-domains = <&k3_pds 108 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer12: timer@24c0000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x24c0000 0x00 0x400>;
+ interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 109 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 109 2>;
+ assigned-clock-parents = <&k3_clks 109 3>;
+ power-domains = <&k3_pds 109 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer13: timer@24d0000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x24d0000 0x00 0x400>;
+ interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 110 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 110 2>;
+ assigned-clock-parents = <&k3_clks 110 3>;
+ power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer14: timer@24e0000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x24e0000 0x00 0x400>;
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 111 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 111 2>;
+ assigned-clock-parents = <&k3_clks 111 3>;
+ power-domains = <&k3_pds 111 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer15: timer@24f0000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x24f0000 0x00 0x400>;
+ interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 112 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 112 2>;
+ assigned-clock-parents = <&k3_clks 112 3>;
+ power-domains = <&k3_pds 112 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer16: timer@2500000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2500000 0x00 0x400>;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 113 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 113 2>;
+ assigned-clock-parents = <&k3_clks 113 3>;
+ power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer17: timer@2510000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2510000 0x00 0x400>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 114 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 114 2>;
+ assigned-clock-parents = <&k3_clks 114 3>;
+ power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer18: timer@2520000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2520000 0x00 0x400>;
+ interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 115 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 115 2>;
+ assigned-clock-parents = <&k3_clks 115 3>;
+ power-domains = <&k3_pds 115 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer19: timer@2530000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2530000 0x00 0x400>;
+ interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 116 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 116 2>;
+ assigned-clock-parents = <&k3_clks 116 3>;
+ power-domains = <&k3_pds 116 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_uart0: serial@2800000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02800000 0x00 0x200>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 146 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart1: serial@2810000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02810000 0x00 0x200>;
+ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 388 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 388 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart2: serial@2820000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02820000 0x00 0x200>;
+ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 389 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 389 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart3: serial@2830000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02830000 0x00 0x200>;
+ interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 390 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 390 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart4: serial@2840000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02840000 0x00 0x200>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 391 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 391 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart5: serial@2850000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02850000 0x00 0x200>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 392 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 392 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart6: serial@2860000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02860000 0x00 0x200>;
+ interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 393 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 393 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart7: serial@2870000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02870000 0x00 0x200>;
+ interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 394 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 394 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart8: serial@2880000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02880000 0x00 0x200>;
+ interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 395 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 395 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_uart9: serial@2890000 {
+ compatible = "ti,j721e-uart", "ti,am654-uart";
+ reg = <0x00 0x02890000 0x00 0x200>;
+ interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 396 0>;
+ clock-names = "fclk";
+ power-domains = <&k3_pds 396 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_gpio0: gpio@600000 {
+ compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00600000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <145>, <146>, <147>, <148>, <149>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,ngpio = <66>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 163 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 163 0>;
+ clock-names = "gpio";
+ status = "disabled";
+ };
+
+ main_gpio2: gpio@610000 {
+ compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00610000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <154>, <155>, <156>, <157>, <158>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,ngpio = <66>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 164 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 164 0>;
+ clock-names = "gpio";
+ status = "disabled";
+ };
+
+ main_gpio4: gpio@620000 {
+ compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00620000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <163>, <164>, <165>, <166>, <167>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,ngpio = <66>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 165 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 165 0>;
+ clock-names = "gpio";
+ status = "disabled";
+ };
+
+ main_gpio6: gpio@630000 {
+ compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+ reg = <0x00 0x00630000 0x00 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&main_gpio_intr>;
+ interrupts = <172>, <173>, <174>, <175>, <176>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,ngpio = <66>;
+ ti,davinci-gpio-unbanked = <0>;
+ power-domains = <&k3_pds 166 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 166 0>;
+ clock-names = "gpio";
+ status = "disabled";
+ };
+
+ usbss0: usb@4104000 {
+ bootph-all;
+ compatible = "ti,j721e-usb";
+ reg = <0x00 0x4104000 0x00 0x100>;
+ dma-coherent;
+ power-domains = <&k3_pds 398 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 398 21>, <&k3_clks 398 2>;
+ clock-names = "ref", "lpm";
+ assigned-clocks = <&k3_clks 398 21>; /* USB2_REFCLK */
+ assigned-clock-parents = <&k3_clks 398 22>; /* HFOSC0 */
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ status = "disabled"; /* Needs lane config */
+
+ usb0: usb@6000000 {
+ bootph-all;
+ compatible = "cdns,usb3";
+ reg = <0x00 0x6000000 0x00 0x10000>,
+ <0x00 0x6010000 0x00 0x10000>,
+ <0x00 0x6020000 0x00 0x10000>;
+ reg-names = "otg", "xhci", "dev";
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, /* irq.6 */
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; /* otgirq.0 */
+ interrupt-names = "host",
+ "peripheral",
+ "otg";
+ };
+ };
+
+ main_i2c0: i2c@2000000 {
+ compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x02000000 0x00 0x100>;
+ interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 270 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_i2c1: i2c@2010000 {
+ compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x02010000 0x00 0x100>;
+ interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 271 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_i2c2: i2c@2020000 {
+ compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x02020000 0x00 0x100>;
+ interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 272 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_i2c3: i2c@2030000 {
+ compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x02030000 0x00 0x100>;
+ interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 273 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_i2c4: i2c@2040000 {
+ compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x02040000 0x00 0x100>;
+ interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 274 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_i2c5: i2c@2050000 {
+ compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x02050000 0x00 0x100>;
+ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 275 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ main_i2c6: i2c@2060000 {
+ compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+ reg = <0x00 0x02060000 0x00 0x100>;
+ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 276 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ ti_csi2rx0: ticsi2rx@4500000 {
+ compatible = "ti,j721e-csi2rx-shim";
+ reg = <0x00 0x04500000 0x00 0x00001000>;
+ ranges;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dmas = <&main_bcdma_csi 0 0x4940 0>;
+ dma-names = "rx0";
+ power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+
+ cdns_csi2rx0: csi-bridge@4504000 {
+ compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
+ reg = <0x00 0x04504000 0x00 0x00001000>;
+ clocks = <&k3_clks 72 2>, <&k3_clks 72 0>, <&k3_clks 72 2>,
+ <&k3_clks 72 2>, <&k3_clks 72 3>, <&k3_clks 72 3>;
+ clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+ phys = <&dphy0>;
+ phy-names = "dphy";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ csi0_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ };
+
+ csi0_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ };
+
+ csi0_port2: port@2 {
+ reg = <2>;
+ status = "disabled";
+ };
+
+ csi0_port3: port@3 {
+ reg = <3>;
+ status = "disabled";
+ };
+
+ csi0_port4: port@4 {
+ reg = <4>;
+ status = "disabled";
+ };
+ };
+ };
+ };
+
+ ti_csi2rx1: ticsi2rx@4510000 {
+ compatible = "ti,j721e-csi2rx-shim";
+ reg = <0x00 0x04510000 0x00 0x1000>;
+ ranges;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dmas = <&main_bcdma_csi 0 0x4960 0>;
+ dma-names = "rx0";
+ power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+
+ cdns_csi2rx1: csi-bridge@4514000 {
+ compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
+ reg = <0x00 0x04514000 0x00 0x00001000>;
+ clocks = <&k3_clks 73 2>, <&k3_clks 73 0>, <&k3_clks 73 2>,
+ <&k3_clks 73 2>, <&k3_clks 73 3>, <&k3_clks 73 3>;
+ clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+ phys = <&dphy1>;
+ phy-names = "dphy";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ csi1_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ };
+
+ csi1_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ };
+
+ csi1_port2: port@2 {
+ reg = <2>;
+ status = "disabled";
+ };
+
+ csi1_port3: port@3 {
+ reg = <3>;
+ status = "disabled";
+ };
+
+ csi1_port4: port@4 {
+ reg = <4>;
+ status = "disabled";
+ };
+ };
+ };
+ };
+
+ ti_csi2rx2: ticsi2rx@4520000 {
+ compatible = "ti,j721e-csi2rx-shim";
+ reg = <0x00 0x04520000 0x00 0x00001000>;
+ ranges;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dmas = <&main_bcdma_csi 0 0x4980 0>;
+ dma-names = "rx0";
+ power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+
+ cdns_csi2rx2: csi-bridge@4524000 {
+ compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
+ reg = <0x00 0x04524000 0x00 0x00001000>;
+ clocks = <&k3_clks 74 2>, <&k3_clks 74 0>, <&k3_clks 74 2>,
+ <&k3_clks 74 2>, <&k3_clks 74 3>, <&k3_clks 74 3>;
+ clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+ phys = <&dphy2>;
+ phy-names = "dphy";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ csi2_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ };
+
+ csi2_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ };
+
+ csi2_port2: port@2 {
+ reg = <2>;
+ status = "disabled";
+ };
+
+ csi2_port3: port@3 {
+ reg = <3>;
+ status = "disabled";
+ };
+
+ csi2_port4: port@4 {
+ reg = <4>;
+ status = "disabled";
+ };
+ };
+ };
+ };
+
+ dphy0: phy@4580000 {
+ compatible = "cdns,dphy-rx";
+ reg = <0x00 0x04580000 0x00 0x00001100>;
+ #phy-cells = <0>;
+ power-domains = <&k3_pds 212 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ dphy1: phy@4590000 {
+ compatible = "cdns,dphy-rx";
+ reg = <0x00 0x04590000 0x00 0x00001100>;
+ #phy-cells = <0>;
+ power-domains = <&k3_pds 213 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ dphy2: phy@45a0000 {
+ compatible = "cdns,dphy-rx";
+ reg = <0x00 0x045a0000 0x00 0x00001100>;
+ #phy-cells = <0>;
+ power-domains = <&k3_pds 214 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ vpu0: video-codec@4210000 {
+ compatible = "ti,j721s2-wave521c", "cnm,wave521c";
+ reg = <0x00 0x4210000 0x00 0x10000>;
+ interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 241 2>;
+ power-domains = <&k3_pds 241 TI_SCI_PD_EXCLUSIVE>;
+ };
+
+ vpu1: video-codec@4220000 {
+ compatible = "ti,j721s2-wave521c", "cnm,wave521c";
+ reg = <0x00 0x4220000 0x00 0x10000>;
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 242 2>;
+ power-domains = <&k3_pds 242 TI_SCI_PD_EXCLUSIVE>;
+ };
+
+ main_sdhci0: mmc@4f80000 {
+ compatible = "ti,j721e-sdhci-8bit";
+ reg = <0x00 0x04f80000 0x00 0x1000>,
+ <0x00 0x04f88000 0x00 0x400>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 140 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 140 1>, <&k3_clks 140 2>;
+ clock-names = "clk_ahb", "clk_xin";
+ assigned-clocks = <&k3_clks 140 2>;
+ assigned-clock-parents = <&k3_clks 140 3>;
+ bus-width = <8>;
+ ti,otap-del-sel-legacy = <0x0>;
+ ti,otap-del-sel-mmc-hs = <0x0>;
+ ti,otap-del-sel-ddr52 = <0x6>;
+ ti,otap-del-sel-hs200 = <0x8>;
+ ti,otap-del-sel-hs400 = <0x5>;
+ ti,itap-del-sel-legacy = <0x10>;
+ ti,itap-del-sel-mmc-hs = <0xa>;
+ ti,strobe-sel = <0x77>;
+ ti,clkbuf-sel = <0x7>;
+ ti,trm-icp = <0x8>;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ dma-coherent;
+ status = "disabled";
+ };
+
+ main_sdhci1: mmc@4fb0000 {
+ compatible = "ti,j721e-sdhci-4bit";
+ reg = <0x00 0x04fb0000 0x00 0x1000>,
+ <0x00 0x04fb8000 0x00 0x400>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 141 3>, <&k3_clks 141 4>;
+ clock-names = "clk_ahb", "clk_xin";
+ assigned-clocks = <&k3_clks 141 4>;
+ assigned-clock-parents = <&k3_clks 141 5>;
+ bus-width = <4>;
+ ti,otap-del-sel-legacy = <0x0>;
+ ti,otap-del-sel-sd-hs = <0x0>;
+ ti,otap-del-sel-sdr12 = <0xf>;
+ ti,otap-del-sel-sdr25 = <0xf>;
+ ti,otap-del-sel-sdr50 = <0xc>;
+ ti,otap-del-sel-sdr104 = <0x5>;
+ ti,otap-del-sel-ddr50 = <0xc>;
+ ti,itap-del-sel-legacy = <0x0>;
+ ti,itap-del-sel-sd-hs = <0x0>;
+ ti,itap-del-sel-sdr12 = <0x0>;
+ ti,itap-del-sel-sdr25 = <0x0>;
+ ti,itap-del-sel-ddr50 = <0x2>;
+ ti,clkbuf-sel = <0x7>;
+ ti,trm-icp = <0x8>;
+ dma-coherent;
+ status = "disabled";
+ };
+
+ pcie0_rc: pcie@2900000 {
+ compatible = "ti,j784s4-pcie-host";
+ reg = <0x00 0x02900000 0x00 0x1000>,
+ <0x00 0x02907000 0x00 0x400>,
+ <0x00 0x0d000000 0x00 0x00800000>,
+ <0x00 0x10000000 0x00 0x00001000>;
+ reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+ interrupt-names = "link_state";
+ interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
+ device_type = "pci";
+ ti,syscon-pcie-ctrl = <&pcie0_ctrl 0x0>;
+ max-link-speed = <3>;
+ num-lanes = <4>;
+ power-domains = <&k3_pds 332 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 332 0>;
+ clock-names = "fck";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x0 0xff>;
+ vendor-id = <0x104c>;
+ device-id = <0xb012>;
+ msi-map = <0x0 &gic_its 0x0 0x10000>;
+ dma-coherent;
+ ranges = <0x01000000 0x0 0x10001000 0x0 0x10001000 0x0 0x0010000>,
+ <0x02000000 0x0 0x10011000 0x0 0x10011000 0x0 0x7fef000>;
+ dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+ status = "disabled";
+ };
+
+ pcie1_rc: pcie@2910000 {
+ compatible = "ti,j784s4-pcie-host";
+ reg = <0x00 0x02910000 0x00 0x1000>,
+ <0x00 0x02917000 0x00 0x400>,
+ <0x00 0x0d800000 0x00 0x00800000>,
+ <0x00 0x18000000 0x00 0x00001000>;
+ reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+ interrupt-names = "link_state";
+ interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+ device_type = "pci";
+ ti,syscon-pcie-ctrl = <&pcie1_ctrl 0x0>;
+ max-link-speed = <3>;
+ num-lanes = <4>;
+ power-domains = <&k3_pds 333 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 333 0>;
+ clock-names = "fck";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x0 0xff>;
+ vendor-id = <0x104c>;
+ device-id = <0xb012>;
+ msi-map = <0x0 &gic_its 0x10000 0x10000>;
+ dma-coherent;
+ ranges = <0x01000000 0x0 0x18001000 0x00 0x18001000 0x0 0x0010000>,
+ <0x02000000 0x0 0x18011000 0x00 0x18011000 0x0 0x7fef000>;
+ dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+ status = "disabled";
+ };
+
+ serdes_wiz0: wiz@5060000 {
+ compatible = "ti,j784s4-wiz-10g";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 404 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 404 2>, <&k3_clks 404 6>, <&serdes_refclk>, <&k3_clks 404 5>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+ assigned-clocks = <&k3_clks 404 6>;
+ assigned-clock-parents = <&k3_clks 404 10>;
+ num-lanes = <4>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ ranges = <0x5060000 0x00 0x5060000 0x10000>;
+ status = "disabled";
+
+ serdes0: serdes@5060000 {
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x05060000 0x010000>;
+ reg-names = "torrent_phy";
+ resets = <&serdes_wiz0 0>;
+ reset-names = "torrent_reset";
+ clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz0 TI_WIZ_PHY_EN_REFCLK>;
+ clock-names = "refclk", "phy_en_refclk";
+ assigned-clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz0 TI_WIZ_PLL1_REFCLK>,
+ <&serdes_wiz0 TI_WIZ_REFCLK_DIG>;
+ assigned-clock-parents = <&k3_clks 404 6>,
+ <&k3_clks 404 6>,
+ <&k3_clks 404 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ serdes_wiz1: wiz@5070000 {
+ compatible = "ti,j784s4-wiz-10g";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 405 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 405 2>, <&k3_clks 405 6>, <&serdes_refclk>, <&k3_clks 405 5>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+ assigned-clocks = <&k3_clks 405 6>;
+ assigned-clock-parents = <&k3_clks 405 10>;
+ num-lanes = <4>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ ranges = <0x05070000 0x00 0x05070000 0x10000>;
+ status = "disabled";
+
+ serdes1: serdes@5070000 {
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x05070000 0x010000>;
+ reg-names = "torrent_phy";
+ resets = <&serdes_wiz1 0>;
+ reset-names = "torrent_reset";
+ clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz1 TI_WIZ_PHY_EN_REFCLK>;
+ clock-names = "refclk", "phy_en_refclk";
+ assigned-clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz1 TI_WIZ_PLL1_REFCLK>,
+ <&serdes_wiz1 TI_WIZ_REFCLK_DIG>;
+ assigned-clock-parents = <&k3_clks 405 6>,
+ <&k3_clks 405 6>,
+ <&k3_clks 405 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ serdes_wiz4: wiz@5050000 {
+ compatible = "ti,j784s4-wiz-10g";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ power-domains = <&k3_pds 407 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 407 2>, <&k3_clks 407 6>, <&serdes_refclk>, <&k3_clks 407 5>;
+ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+ assigned-clocks = <&k3_clks 407 6>;
+ assigned-clock-parents = <&k3_clks 407 10>;
+ num-lanes = <4>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ ranges = <0x05050000 0x00 0x05050000 0x10000>,
+ <0xa030a00 0x00 0xa030a00 0x40>; /* DPTX PHY */
+ status = "disabled";
+
+ serdes4: serdes@5050000 {
+ /*
+ * Note: we also map DPTX PHY registers as the Torrent
+ * needs to manage those.
+ */
+ compatible = "ti,j721e-serdes-10g";
+ reg = <0x05050000 0x010000>,
+ <0x0a030a00 0x40>; /* DPTX PHY */
+ reg-names = "torrent_phy";
+ resets = <&serdes_wiz4 0>;
+ reset-names = "torrent_reset";
+ clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz4 TI_WIZ_PHY_EN_REFCLK>;
+ clock-names = "refclk", "phy_en_refclk";
+ assigned-clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
+ <&serdes_wiz4 TI_WIZ_PLL1_REFCLK>,
+ <&serdes_wiz4 TI_WIZ_REFCLK_DIG>;
+ assigned-clock-parents = <&k3_clks 407 6>,
+ <&k3_clks 407 6>,
+ <&k3_clks 407 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+ };
+
+ main_navss: bus@30000000 {
+ bootph-all;
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
+ ti,sci-dev-id = <280>;
+ dma-coherent;
+ dma-ranges;
+
+ main_navss_intr: interrupt-controller@310e0000 {
+ compatible = "ti,sci-intr";
+ reg = <0x00 0x310e0000 0x00 0x4000>;
+ ti,intr-trigger-type = <4>;
+ interrupt-controller;
+ interrupt-parent = <&gic500>;
+ #interrupt-cells = <1>;
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <283>;
+ ti,interrupt-ranges = <0 64 64>,
+ <64 448 64>,
+ <128 672 64>;
+ };
+
+ main_udmass_inta: msi-controller@33d00000 {
+ compatible = "ti,sci-inta";
+ reg = <0x00 0x33d00000 0x00 0x100000>;
+ interrupt-controller;
+ #interrupt-cells = <0>;
+ interrupt-parent = <&main_navss_intr>;
+ msi-controller;
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <321>;
+ ti,interrupt-ranges = <0 0 256>;
+ ti,unmapped-event-sources = <&main_bcdma_csi>;
+ };
+
+ secure_proxy_main: mailbox@32c00000 {
+ bootph-all;
+ compatible = "ti,am654-secure-proxy";
+ #mbox-cells = <1>;
+ reg-names = "target_data", "rt", "scfg";
+ reg = <0x00 0x32c00000 0x00 0x100000>,
+ <0x00 0x32400000 0x00 0x100000>,
+ <0x00 0x32800000 0x00 0x100000>;
+ interrupt-names = "rx_011";
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ hwspinlock: hwlock@30e00000 {
+ compatible = "ti,am654-hwspinlock";
+ reg = <0x00 0x30e00000 0x00 0x1000>;
+ #hwlock-cells = <1>;
+ };
+
+ mailbox0_cluster0: mailbox@31f80000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f80000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster1: mailbox@31f81000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f81000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster2: mailbox@31f82000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f82000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster3: mailbox@31f83000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f83000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster4: mailbox@31f84000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f84000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster5: mailbox@31f85000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f85000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster6: mailbox@31f86000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f86000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster7: mailbox@31f87000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f87000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster8: mailbox@31f88000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f88000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster9: mailbox@31f89000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f89000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster10: mailbox@31f8a000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f8a000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox0_cluster11: mailbox@31f8b000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f8b000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster0: mailbox@31f90000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f90000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster1: mailbox@31f91000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f91000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster2: mailbox@31f92000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f92000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster3: mailbox@31f93000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f93000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster4: mailbox@31f94000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f94000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster5: mailbox@31f95000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f95000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster6: mailbox@31f96000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f96000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster7: mailbox@31f97000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f97000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster8: mailbox@31f98000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f98000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster9: mailbox@31f99000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f99000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster10: mailbox@31f9a000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f9a000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ mailbox1_cluster11: mailbox@31f9b000 {
+ compatible = "ti,am654-mailbox";
+ reg = <0x00 0x31f9b000 0x00 0x200>;
+ #mbox-cells = <1>;
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <16>;
+ interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
+ };
+
+ main_ringacc: ringacc@3c000000 {
+ compatible = "ti,am654-navss-ringacc";
+ reg = <0x00 0x3c000000 0x00 0x400000>,
+ <0x00 0x38000000 0x00 0x400000>,
+ <0x00 0x31120000 0x00 0x100>,
+ <0x00 0x33000000 0x00 0x40000>,
+ <0x00 0x31080000 0x00 0x40000>;
+ reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target", "cfg";
+ ti,num-rings = <1024>;
+ ti,sci-rm-range-gp-rings = <0x1>;
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <315>;
+ msi-parent = <&main_udmass_inta>;
+ };
+
+ main_udmap: dma-controller@31150000 {
+ compatible = "ti,j721e-navss-main-udmap";
+ reg = <0x00 0x31150000 0x00 0x100>,
+ <0x00 0x34000000 0x00 0x80000>,
+ <0x00 0x35000000 0x00 0x200000>,
+ <0x00 0x30b00000 0x00 0x20000>,
+ <0x00 0x30c00000 0x00 0x8000>,
+ <0x00 0x30d00000 0x00 0x4000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt",
+ "tchan", "rchan", "rflow";
+ msi-parent = <&main_udmass_inta>;
+ #dma-cells = <1>;
+
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <319>;
+ ti,ringacc = <&main_ringacc>;
+
+ ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */
+ <0x0f>, /* TX_HCHAN */
+ <0x10>; /* TX_UHCHAN */
+ ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */
+ <0x0b>, /* RX_HCHAN */
+ <0x0c>; /* RX_UHCHAN */
+ ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
+ };
+
+ main_bcdma_csi: dma-controller@311a0000 {
+ compatible = "ti,j721s2-dmss-bcdma-csi";
+ reg = <0x00 0x311a0000 0x00 0x100>,
+ <0x00 0x35d00000 0x00 0x20000>,
+ <0x00 0x35c00000 0x00 0x10000>,
+ <0x00 0x35e00000 0x00 0x80000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+ msi-parent = <&main_udmass_inta>;
+ #dma-cells = <3>;
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <281>;
+ ti,sci-rm-range-rchan = <0x21>;
+ ti,sci-rm-range-tchan = <0x22>;
+ };
+
+ cpts@310d0000 {
+ compatible = "ti,j721e-cpts";
+ reg = <0x00 0x310d0000 0x00 0x400>;
+ reg-names = "cpts";
+ clocks = <&k3_clks 282 0>;
+ clock-names = "cpts";
+ assigned-clocks = <&k3_clks 62 3>; /* CPTS_RFT_CLK */
+ assigned-clock-parents = <&k3_clks 62 5>; /* MAIN_0_HSDIV6_CLK */
+ interrupts-extended = <&main_navss_intr 391>;
+ interrupt-names = "cpts";
+ ti,cpts-periodic-outputs = <6>;
+ ti,cpts-ext-ts-inputs = <8>;
+ };
+ };
+
+ main_cpsw0: ethernet@c000000 {
+ compatible = "ti,j784s4-cpswxg-nuss";
+ reg = <0x00 0xc000000 0x00 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x00 0x00 0x00 0xc000000 0x00 0x200000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-coherent;
+ clocks = <&k3_clks 64 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 64 TI_SCI_PD_EXCLUSIVE>;
+
+ dmas = <&main_udmap 0xca00>,
+ <&main_udmap 0xca01>,
+ <&main_udmap 0xca02>,
+ <&main_udmap 0xca03>,
+ <&main_udmap 0xca04>,
+ <&main_udmap 0xca05>,
+ <&main_udmap 0xca06>,
+ <&main_udmap 0xca07>,
+ <&main_udmap 0x4a00>;
+ dma-names = "tx0", "tx1", "tx2", "tx3",
+ "tx4", "tx5", "tx6", "tx7",
+ "rx";
+
+ status = "disabled";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ main_cpsw0_port1: port@1 {
+ reg = <1>;
+ label = "port1";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port2: port@2 {
+ reg = <2>;
+ label = "port2";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port3: port@3 {
+ reg = <3>;
+ label = "port3";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port4: port@4 {
+ reg = <4>;
+ label = "port4";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port5: port@5 {
+ reg = <5>;
+ label = "port5";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port6: port@6 {
+ reg = <6>;
+ label = "port6";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port7: port@7 {
+ reg = <7>;
+ label = "port7";
+ ti,mac-only;
+ status = "disabled";
+ };
+
+ main_cpsw0_port8: port@8 {
+ reg = <8>;
+ label = "port8";
+ ti,mac-only;
+ status = "disabled";
+ };
+ };
+
+ main_cpsw0_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+ reg = <0x00 0xf00 0x00 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 64 0>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ status = "disabled";
+ };
+
+ cpts@3d000 {
+ compatible = "ti,am65-cpts";
+ reg = <0x00 0x3d000 0x00 0x400>;
+ clocks = <&k3_clks 64 3>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
+ };
+
+ main_cpsw1: ethernet@c200000 {
+ compatible = "ti,j721e-cpsw-nuss";
+ reg = <0x00 0xc200000 0x00 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x00 0x00 0x00 0xc200000 0x00 0x200000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-coherent;
+ clocks = <&k3_clks 62 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+
+ dmas = <&main_udmap 0xc640>,
+ <&main_udmap 0xc641>,
+ <&main_udmap 0xc642>,
+ <&main_udmap 0xc643>,
+ <&main_udmap 0xc644>,
+ <&main_udmap 0xc645>,
+ <&main_udmap 0xc646>,
+ <&main_udmap 0xc647>,
+ <&main_udmap 0x4640>;
+ dma-names = "tx0", "tx1", "tx2", "tx3",
+ "tx4", "tx5", "tx6", "tx7",
+ "rx";
+
+ status = "disabled";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ main_cpsw1_port1: port@1 {
+ reg = <1>;
+ label = "port1";
+ phys = <&cpsw1_phy_gmii_sel 1>;
+ ti,mac-only;
+ status = "disabled";
+ };
+ };
+
+ main_cpsw1_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio", "ti,davinci_mdio";
+ reg = <0x00 0xf00 0x00 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 62 0>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ status = "disabled";
+ };
+
+ cpts@3d000 {
+ compatible = "ti,am65-cpts";
+ reg = <0x00 0x3d000 0x00 0x400>;
+ clocks = <&k3_clks 62 3>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
+ };
+
+ main_mcan0: can@2701000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02701000 0x00 0x200>,
+ <0x00 0x02708000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 245 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 245 6>, <&k3_clks 245 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan1: can@2711000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02711000 0x00 0x200>,
+ <0x00 0x02718000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 246 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 246 6>, <&k3_clks 246 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan2: can@2721000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02721000 0x00 0x200>,
+ <0x00 0x02728000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 247 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 247 6>, <&k3_clks 247 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan3: can@2731000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02731000 0x00 0x200>,
+ <0x00 0x02738000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 248 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 248 6>, <&k3_clks 248 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan4: can@2741000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02741000 0x00 0x200>,
+ <0x00 0x02748000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 249 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 249 6>, <&k3_clks 249 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan5: can@2751000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02751000 0x00 0x200>,
+ <0x00 0x02758000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 250 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 250 6>, <&k3_clks 250 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan6: can@2761000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02761000 0x00 0x200>,
+ <0x00 0x02768000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 251 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 251 6>, <&k3_clks 251 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan7: can@2771000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02771000 0x00 0x200>,
+ <0x00 0x02778000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 252 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 252 6>, <&k3_clks 252 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan8: can@2781000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02781000 0x00 0x200>,
+ <0x00 0x02788000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 253 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 253 6>, <&k3_clks 253 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 576 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan9: can@2791000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02791000 0x00 0x200>,
+ <0x00 0x02798000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 254 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 254 6>, <&k3_clks 254 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 579 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan10: can@27a1000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x027a1000 0x00 0x200>,
+ <0x00 0x027a8000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 255 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 255 6>, <&k3_clks 255 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan11: can@27b1000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x027b1000 0x00 0x200>,
+ <0x00 0x027b8000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 256 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 256 6>, <&k3_clks 256 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan12: can@27c1000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x027c1000 0x00 0x200>,
+ <0x00 0x027c8000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 257 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 257 6>, <&k3_clks 257 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan13: can@27d1000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x027d1000 0x00 0x200>,
+ <0x00 0x027d8000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 258 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 258 6>, <&k3_clks 258 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 591 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan14: can@2681000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02681000 0x00 0x200>,
+ <0x00 0x02688000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 259 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 259 6>, <&k3_clks 259 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 594 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 595 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan15: can@2691000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x02691000 0x00 0x200>,
+ <0x00 0x02698000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 260 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 260 6>, <&k3_clks 260 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 597 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 598 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan16: can@26a1000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x026a1000 0x00 0x200>,
+ <0x00 0x026a8000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 261 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 261 6>, <&k3_clks 261 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 784 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 785 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_mcan17: can@26b1000 {
+ compatible = "bosch,m_can";
+ reg = <0x00 0x026b1000 0x00 0x200>,
+ <0x00 0x026b8000 0x00 0x8000>;
+ reg-names = "m_can", "message_ram";
+ power-domains = <&k3_pds 262 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 262 6>, <&k3_clks 262 1>;
+ clock-names = "hclk", "cclk";
+ interrupts = <GIC_SPI 787 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 788 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+ status = "disabled";
+ };
+
+ main_spi0: spi@2100000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02100000 0x00 0x400>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 376 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 376 1>;
+ status = "disabled";
+ };
+
+ main_spi1: spi@2110000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02110000 0x00 0x400>;
+ interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 377 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 377 1>;
+ status = "disabled";
+ };
+
+ main_spi2: spi@2120000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02120000 0x00 0x400>;
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 378 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 378 1>;
+ status = "disabled";
+ };
+
+ main_spi3: spi@2130000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02130000 0x00 0x400>;
+ interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 379 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 379 1>;
+ status = "disabled";
+ };
+
+ main_spi4: spi@2140000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02140000 0x00 0x400>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 380 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 380 1>;
+ status = "disabled";
+ };
+
+ main_spi5: spi@2150000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02150000 0x00 0x400>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 381 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 381 1>;
+ status = "disabled";
+ };
+
+ main_spi6: spi@2160000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02160000 0x00 0x400>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 382 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 382 1>;
+ status = "disabled";
+ };
+
+ main_spi7: spi@2170000 {
+ compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+ reg = <0x00 0x02170000 0x00 0x400>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&k3_pds 383 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 383 1>;
+ status = "disabled";
+ };
+
+ ufs_wrapper: ufs-wrapper@4e80000 {
+ compatible = "ti,j721e-ufs";
+ reg = <0x00 0x4e80000 0x00 0x100>;
+ power-domains = <&k3_pds 387 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 387 3>;
+ assigned-clocks = <&k3_clks 387 3>;
+ assigned-clock-parents = <&k3_clks 387 6>;
+ ranges;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ status = "disabled";
+
+ ufs@4e84000 {
+ compatible = "cdns,ufshc-m31-16nm", "jedec,ufs-2.0";
+ reg = <0x00 0x4e84000 0x00 0x10000>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ freq-table-hz = <250000000 250000000>, <19200000 19200000>,
+ <19200000 19200000>;
+ clocks = <&k3_clks 387 1>, <&k3_clks 387 3>, <&k3_clks 387 3>;
+ clock-names = "core_clk", "phy_clk", "ref_clk";
+ dma-coherent;
+ };
+ };
+
+ main_r5fss0: r5fss@5c00000 {
+ compatible = "ti,j721s2-r5fss";
+ ti,cluster-mode = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
+ <0x5d00000 0x00 0x5d00000 0x20000>;
+ power-domains = <&k3_pds 336 TI_SCI_PD_EXCLUSIVE>;
+
+ main_r5fss0_core0: r5f@5c00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5c00000 0x00010000>,
+ <0x5c10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <339>;
+ ti,sci-proc-ids = <0x06 0xff>;
+ resets = <&k3_reset 339 1>;
+ firmware-name = "j784s4-main-r5f0_0-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+
+ main_r5fss0_core1: r5f@5d00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5d00000 0x00010000>,
+ <0x5d10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <340>;
+ ti,sci-proc-ids = <0x07 0xff>;
+ resets = <&k3_reset 340 1>;
+ firmware-name = "j784s4-main-r5f0_1-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+ };
+
+ main_r5fss1: r5fss@5e00000 {
+ compatible = "ti,j721s2-r5fss";
+ ti,cluster-mode = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x5e00000 0x00 0x5e00000 0x20000>,
+ <0x5f00000 0x00 0x5f00000 0x20000>;
+ power-domains = <&k3_pds 337 TI_SCI_PD_EXCLUSIVE>;
+
+ main_r5fss1_core0: r5f@5e00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5e00000 0x00010000>,
+ <0x5e10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <341>;
+ ti,sci-proc-ids = <0x08 0xff>;
+ resets = <&k3_reset 341 1>;
+ firmware-name = "j784s4-main-r5f1_0-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+
+ main_r5fss1_core1: r5f@5f00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5f00000 0x00010000>,
+ <0x5f10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <342>;
+ ti,sci-proc-ids = <0x09 0xff>;
+ resets = <&k3_reset 342 1>;
+ firmware-name = "j784s4-main-r5f1_1-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+ };
+
+ main_r5fss2: r5fss@5900000 {
+ compatible = "ti,j721s2-r5fss";
+ ti,cluster-mode = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x5900000 0x00 0x5900000 0x20000>,
+ <0x5a00000 0x00 0x5a00000 0x20000>;
+ power-domains = <&k3_pds 338 TI_SCI_PD_EXCLUSIVE>;
+
+ main_r5fss2_core0: r5f@5900000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5900000 0x00010000>,
+ <0x5910000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <343>;
+ ti,sci-proc-ids = <0x0a 0xff>;
+ resets = <&k3_reset 343 1>;
+ firmware-name = "j784s4-main-r5f2_0-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+
+ main_r5fss2_core1: r5f@5a00000 {
+ compatible = "ti,j721s2-r5f";
+ reg = <0x5a00000 0x00010000>,
+ <0x5a10000 0x00010000>;
+ reg-names = "atcm", "btcm";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <344>;
+ ti,sci-proc-ids = <0x0b 0xff>;
+ resets = <&k3_reset 344 1>;
+ firmware-name = "j784s4-main-r5f2_1-fw";
+ ti,atcm-enable = <1>;
+ ti,btcm-enable = <1>;
+ ti,loczrama = <1>;
+ };
+ };
+
+ c71_0: dsp@64800000 {
+ compatible = "ti,j721s2-c71-dsp";
+ reg = <0x00 0x64800000 0x00 0x00080000>,
+ <0x00 0x64e00000 0x00 0x0000c000>;
+ reg-names = "l2sram", "l1dram";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <30>;
+ ti,sci-proc-ids = <0x30 0xff>;
+ resets = <&k3_reset 30 1>;
+ firmware-name = "j784s4-c71_0-fw";
+ status = "disabled";
+ };
+
+ c71_1: dsp@65800000 {
+ compatible = "ti,j721s2-c71-dsp";
+ reg = <0x00 0x65800000 0x00 0x00080000>,
+ <0x00 0x65e00000 0x00 0x0000c000>;
+ reg-names = "l2sram", "l1dram";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <33>;
+ ti,sci-proc-ids = <0x31 0xff>;
+ resets = <&k3_reset 33 1>;
+ firmware-name = "j784s4-c71_1-fw";
+ status = "disabled";
+ };
+
+ c71_2: dsp@66800000 {
+ compatible = "ti,j721s2-c71-dsp";
+ reg = <0x00 0x66800000 0x00 0x00080000>,
+ <0x00 0x66e00000 0x00 0x0000c000>;
+ reg-names = "l2sram", "l1dram";
+ ti,sci = <&sms>;
+ ti,sci-dev-id = <37>;
+ ti,sci-proc-ids = <0x32 0xff>;
+ resets = <&k3_reset 37 1>;
+ firmware-name = "j784s4-c71_2-fw";
+ status = "disabled";
+ };
+
+ main_esm: esm@700000 {
+ compatible = "ti,j721e-esm";
+ reg = <0x00 0x700000 0x00 0x1000>;
+ ti,esm-pins = <688>, <689>, <690>, <691>, <692>, <693>, <694>,
+ <695>;
+ bootph-pre-ram;
+ };
+
+ watchdog0: watchdog@2200000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2200000 0x00 0x100>;
+ clocks = <&k3_clks 348 0>;
+ power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 348 0>;
+ assigned-clock-parents = <&k3_clks 348 4>;
+ };
+
+ watchdog1: watchdog@2210000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2210000 0x00 0x100>;
+ clocks = <&k3_clks 349 0>;
+ power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 349 0>;
+ assigned-clock-parents = <&k3_clks 349 4>;
+ };
+
+ watchdog2: watchdog@2220000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2220000 0x00 0x100>;
+ clocks = <&k3_clks 350 0>;
+ power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 350 0>;
+ assigned-clock-parents = <&k3_clks 350 4>;
+ };
+
+ watchdog3: watchdog@2230000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2230000 0x00 0x100>;
+ clocks = <&k3_clks 351 0>;
+ power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 351 0>;
+ assigned-clock-parents = <&k3_clks 351 4>;
+ };
+
+ watchdog4: watchdog@2240000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2240000 0x00 0x100>;
+ clocks = <&k3_clks 352 0>;
+ power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 352 0>;
+ assigned-clock-parents = <&k3_clks 352 4>;
+ };
+
+ watchdog5: watchdog@2250000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2250000 0x00 0x100>;
+ clocks = <&k3_clks 353 0>;
+ power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 353 0>;
+ assigned-clock-parents = <&k3_clks 353 4>;
+ };
+
+ watchdog6: watchdog@2260000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2260000 0x00 0x100>;
+ clocks = <&k3_clks 354 0>;
+ power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 354 0>;
+ assigned-clock-parents = <&k3_clks 354 4>;
+ };
+
+ watchdog7: watchdog@2270000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2270000 0x00 0x100>;
+ clocks = <&k3_clks 355 0>;
+ power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 355 0>;
+ assigned-clock-parents = <&k3_clks 355 4>;
+ };
+
+ /*
+ * The following RTI instances are coupled with MCU R5Fs, c7x and
+ * GPU so keeping them reserved as these will be used by their
+ * respective firmware
+ */
+ watchdog8: watchdog@22f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x22f0000 0x00 0x100>;
+ clocks = <&k3_clks 360 0>;
+ power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 360 0>;
+ assigned-clock-parents = <&k3_clks 360 4>;
+ /* reserved for GPU */
+ status = "reserved";
+ };
+
+ watchdog9: watchdog@2300000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2300000 0x00 0x100>;
+ clocks = <&k3_clks 356 0>;
+ power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 356 0>;
+ assigned-clock-parents = <&k3_clks 356 4>;
+ /* reserved for C7X_0 DSP */
+ status = "reserved";
+ };
+
+ watchdog10: watchdog@2310000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2310000 0x00 0x100>;
+ clocks = <&k3_clks 357 0>;
+ power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 357 0>;
+ assigned-clock-parents = <&k3_clks 357 4>;
+ /* reserved for C7X_1 DSP */
+ status = "reserved";
+ };
+
+ watchdog11: watchdog@2320000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2320000 0x00 0x100>;
+ clocks = <&k3_clks 358 0>;
+ power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 358 0>;
+ assigned-clock-parents = <&k3_clks 358 4>;
+ /* reserved for C7X_2 DSP */
+ status = "reserved";
+ };
+
+ watchdog12: watchdog@2330000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2330000 0x00 0x100>;
+ clocks = <&k3_clks 359 0>;
+ power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 359 0>;
+ assigned-clock-parents = <&k3_clks 359 4>;
+ /* reserved for C7X_3 DSP */
+ status = "reserved";
+ };
+
+ watchdog13: watchdog@23c0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23c0000 0x00 0x100>;
+ clocks = <&k3_clks 361 0>;
+ power-domains = <&k3_pds 361 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 361 0>;
+ assigned-clock-parents = <&k3_clks 361 4>;
+ /* reserved for MAIN_R5F0_0 */
+ status = "reserved";
+ };
+
+ watchdog14: watchdog@23d0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23d0000 0x00 0x100>;
+ clocks = <&k3_clks 362 0>;
+ power-domains = <&k3_pds 362 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 362 0>;
+ assigned-clock-parents = <&k3_clks 362 4>;
+ /* reserved for MAIN_R5F0_1 */
+ status = "reserved";
+ };
+
+ watchdog15: watchdog@23e0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23e0000 0x00 0x100>;
+ clocks = <&k3_clks 363 0>;
+ power-domains = <&k3_pds 363 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 363 0>;
+ assigned-clock-parents = <&k3_clks 363 4>;
+ /* reserved for MAIN_R5F1_0 */
+ status = "reserved";
+ };
+
+ watchdog16: watchdog@23f0000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x23f0000 0x00 0x100>;
+ clocks = <&k3_clks 364 0>;
+ power-domains = <&k3_pds 364 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 364 0>;
+ assigned-clock-parents = <&k3_clks 364 4>;
+ /* reserved for MAIN_R5F1_1 */
+ status = "reserved";
+ };
+
+ watchdog17: watchdog@2540000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2540000 0x00 0x100>;
+ clocks = <&k3_clks 365 0>;
+ power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 365 0>;
+ assigned-clock-parents = <&k3_clks 366 4>;
+ /* reserved for MAIN_R5F2_0 */
+ status = "reserved";
+ };
+
+ watchdog18: watchdog@2550000 {
+ compatible = "ti,j7-rti-wdt";
+ reg = <0x00 0x2550000 0x00 0x100>;
+ clocks = <&k3_clks 366 0>;
+ power-domains = <&k3_pds 366 TI_SCI_PD_EXCLUSIVE>;
+ assigned-clocks = <&k3_clks 366 0>;
+ assigned-clock-parents = <&k3_clks 366 4>;
+ /* reserved for MAIN_R5F2_1 */
+ status = "reserved";
+ };
+
+ mhdp: bridge@a000000 {
+ compatible = "ti,j721e-mhdp8546";
+ reg = <0x0 0xa000000 0x0 0x30a00>,
+ <0x0 0x4f40000 0x0 0x20>;
+ reg-names = "mhdptx", "j721e-intg";
+ clocks = <&k3_clks 217 11>;
+ interrupt-parent = <&gic500>;
+ interrupts = <GIC_SPI 614 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&k3_pds 217 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+
+ dp0_ports: ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* Remote-endpoints are on the boards so
+ * ports are defined in the platform dt file.
+ */
+ };
+ };
+
+ dss: dss@4a00000 {
+ compatible = "ti,j721e-dss";
+ reg = <0x00 0x04a00000 0x00 0x10000>, /* common_m */
+ <0x00 0x04a10000 0x00 0x10000>, /* common_s0*/
+ <0x00 0x04b00000 0x00 0x10000>, /* common_s1*/
+ <0x00 0x04b10000 0x00 0x10000>, /* common_s2*/
+ <0x00 0x04a20000 0x00 0x10000>, /* vidl1 */
+ <0x00 0x04a30000 0x00 0x10000>, /* vidl2 */
+ <0x00 0x04a50000 0x00 0x10000>, /* vid1 */
+ <0x00 0x04a60000 0x00 0x10000>, /* vid2 */
+ <0x00 0x04a70000 0x00 0x10000>, /* ovr1 */
+ <0x00 0x04a90000 0x00 0x10000>, /* ovr2 */
+ <0x00 0x04ab0000 0x00 0x10000>, /* ovr3 */
+ <0x00 0x04ad0000 0x00 0x10000>, /* ovr4 */
+ <0x00 0x04a80000 0x00 0x10000>, /* vp1 */
+ <0x00 0x04aa0000 0x00 0x10000>, /* vp1 */
+ <0x00 0x04ac0000 0x00 0x10000>, /* vp1 */
+ <0x00 0x04ae0000 0x00 0x10000>, /* vp4 */
+ <0x00 0x04af0000 0x00 0x10000>; /* wb */
+ reg-names = "common_m", "common_s0",
+ "common_s1", "common_s2",
+ "vidl1", "vidl2","vid1","vid2",
+ "ovr1", "ovr2", "ovr3", "ovr4",
+ "vp1", "vp2", "vp3", "vp4",
+ "wb";
+ clocks = <&k3_clks 218 0>,
+ <&k3_clks 218 2>,
+ <&k3_clks 218 5>,
+ <&k3_clks 218 14>,
+ <&k3_clks 218 18>;
+ clock-names = "fck", "vp1", "vp2", "vp3", "vp4";
+ power-domains = <&k3_pds 218 TI_SCI_PD_EXCLUSIVE>;
+ interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "common_m",
+ "common_s0",
+ "common_s1",
+ "common_s2";
+ status = "disabled";
+
+ dss_ports: ports {
+ /* Ports that DSS drives are platform specific
+ * so they are defined in platform dt file.
+ */
+ };
+ };
+
+ mcasp0: mcasp@2b00000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b00000 0x00 0x2000>,
+ <0x00 0x02b08000 0x00 0x1000>;
+ reg-names = "mpu","dat";
+ interrupts = <GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 545 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+ dmas = <&main_udmap 0xc400>, <&main_udmap 0x4400>;
+ dma-names = "tx", "rx";
+ clocks = <&k3_clks 265 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 265 0>;
+ assigned-clock-parents = <&k3_clks 265 1>;
+ power-domains = <&k3_pds 265 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp1: mcasp@2b10000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b10000 0x00 0x2000>,
+ <0x00 0x02b18000 0x00 0x1000>;
+ reg-names = "mpu","dat";
+ interrupts = <GIC_SPI 546 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 547 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+ dmas = <&main_udmap 0xc401>, <&main_udmap 0x4401>;
+ dma-names = "tx", "rx";
+ clocks = <&k3_clks 266 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 266 0>;
+ assigned-clock-parents = <&k3_clks 266 1>;
+ power-domains = <&k3_pds 266 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp2: mcasp@2b20000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b20000 0x00 0x2000>,
+ <0x00 0x02b28000 0x00 0x1000>;
+ reg-names = "mpu","dat";
+ interrupts = <GIC_SPI 548 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 549 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+ dmas = <&main_udmap 0xc402>, <&main_udmap 0x4402>;
+ dma-names = "tx", "rx";
+ clocks = <&k3_clks 267 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 267 0>;
+ assigned-clock-parents = <&k3_clks 267 1>;
+ power-domains = <&k3_pds 267 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp3: mcasp@2b30000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b30000 0x00 0x2000>,
+ <0x00 0x02b38000 0x00 0x1000>;
+ reg-names = "mpu","dat";
+ interrupts = <GIC_SPI 550 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 551 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+ dmas = <&main_udmap 0xc403>, <&main_udmap 0x4403>;
+ dma-names = "tx", "rx";
+ clocks = <&k3_clks 268 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 268 0>;
+ assigned-clock-parents = <&k3_clks 268 1>;
+ power-domains = <&k3_pds 268 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+
+ mcasp4: mcasp@2b40000 {
+ compatible = "ti,am33xx-mcasp-audio";
+ reg = <0x00 0x02b40000 0x00 0x2000>,
+ <0x00 0x02b48000 0x00 0x1000>;
+ reg-names = "mpu","dat";
+ interrupts = <GIC_SPI 552 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 553 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
+ dmas = <&main_udmap 0xc404>, <&main_udmap 0x4404>;
+ dma-names = "tx", "rx";
+ clocks = <&k3_clks 269 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 269 0>;
+ assigned-clock-parents = <&k3_clks 269 1>;
+ power-domains = <&k3_pds 269 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-mcu-wakeup-common.dtsi
index f603380fc91c..9638130caece 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-mcu-wakeup-common.dtsi
@@ -1,13 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
- * Device Tree Source for J784S4 SoC Family MCU/WAKEUP Domain peripherals
+ * Device Tree Source for J784S4 and J742S2 SoC Family MCU/WAKEUP Domain peripherals
*
* Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/
*/
&cbass_mcu_wakeup {
sms: system-controller@44083000 {
- bootph-all;
compatible = "ti,k2g-sci";
ti,host-id = <12>;
@@ -39,7 +38,6 @@
};
wkup_conf: bus@43000000 {
- bootph-all;
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
@@ -59,6 +57,8 @@
reg = <0x00 0x43600000 0x00 0x10000>,
<0x00 0x44880000 0x00 0x20000>,
<0x00 0x44860000 0x00 0x20000>;
+ bootph-pre-ram;
+
/*
* Marked Disabled:
* Node is incomplete as it is meant for bootloaders and
@@ -172,13 +172,13 @@
assigned-clocks = <&k3_clks 35 2>;
assigned-clock-parents = <&k3_clks 35 3>;
power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+ bootph-all;
ti,timer-pwm;
/* Non-MPU Firmware usage */
status = "reserved";
};
mcu_timer1: timer@40410000 {
- bootph-all;
compatible = "ti,am654-timer";
reg = <0x00 0x40410000 0x00 0x400>;
interrupts = <GIC_SPI 817 IRQ_TYPE_LEVEL_HIGH>;
@@ -458,7 +458,6 @@
};
mcu_navss: bus@28380000 {
- bootph-all;
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
@@ -515,6 +514,8 @@
reg = <0x00 0x2a480000 0x00 0x80000>,
<0x00 0x2a380000 0x00 0x80000>,
<0x00 0x2a400000 0x00 0x80000>;
+ bootph-pre-ram;
+
/*
* Marked Disabled:
* Node is incomplete as it is meant for bootloaders and
@@ -632,6 +633,7 @@
<0x00 0x42050000 0x00 0x350>;
power-domains = <&k3_pds 243 TI_SCI_PD_SHARED>;
#thermal-sensor-cells = <1>;
+ bootph-pre-ram;
};
tscadc0: tscadc@40200000 {
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-thermal-common.dtsi
index e3ef61c1658f..e3ef61c1658f 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-thermal-common.dtsi
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
index e73bb750b09a..0160fe0da983 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
@@ -5,1110 +5,17 @@
* Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/
*/
-#include <dt-bindings/mux/mux.h>
-#include <dt-bindings/phy/phy.h>
-#include <dt-bindings/phy/phy-ti.h>
-
-#include "k3-serdes.h"
-
-/ {
- serdes_refclk: clock-serdes {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- /* To be enabled when serdes_wiz* is functional */
- status = "disabled";
- };
-};
-
&cbass_main {
- msmc_ram: sram@70000000 {
- compatible = "mmio-sram";
- reg = <0x00 0x70000000 0x00 0x800000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x00 0x00 0x70000000 0x800000>;
-
- atf-sram@0 {
- reg = <0x00 0x20000>;
- };
-
- tifs-sram@1f0000 {
- reg = <0x1f0000 0x10000>;
- };
-
- l3cache-sram@200000 {
- reg = <0x200000 0x200000>;
- };
- };
-
- scm_conf: bus@100000 {
- compatible = "simple-bus";
- reg = <0x00 0x00100000 0x00 0x1c000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x00 0x00 0x00100000 0x1c000>;
-
- cpsw1_phy_gmii_sel: phy@4034 {
- compatible = "ti,am654-phy-gmii-sel";
- reg = <0x4034 0x4>;
- #phy-cells = <1>;
- };
-
- cpsw0_phy_gmii_sel: phy@4044 {
- compatible = "ti,j784s4-cpsw9g-phy-gmii-sel";
- reg = <0x4044 0x20>;
- #phy-cells = <1>;
- ti,qsgmii-main-ports = <7>, <7>;
- };
-
- pcie0_ctrl: pcie0-ctrl@4070 {
- compatible = "ti,j784s4-pcie-ctrl", "syscon";
- reg = <0x4070 0x4>;
- };
-
- pcie1_ctrl: pcie1-ctrl@4074 {
- compatible = "ti,j784s4-pcie-ctrl", "syscon";
- reg = <0x4074 0x4>;
- };
-
- pcie2_ctrl: pcie2-ctrl@4078 {
- compatible = "ti,j784s4-pcie-ctrl", "syscon";
- reg = <0x4078 0x4>;
- };
-
- pcie3_ctrl: pcie3-ctrl@407c {
- compatible = "ti,j784s4-pcie-ctrl", "syscon";
- reg = <0x407c 0x4>;
- };
-
- serdes_ln_ctrl: mux-controller@4080 {
- compatible = "reg-mux";
- reg = <0x00004080 0x30>;
- #mux-control-cells = <1>;
- mux-reg-masks = <0x0 0x3>, <0x4 0x3>, /* SERDES0 lane0/1 select */
- <0x8 0x3>, <0xc 0x3>, /* SERDES0 lane2/3 select */
- <0x10 0x3>, <0x14 0x3>, /* SERDES1 lane0/1 select */
- <0x18 0x3>, <0x1c 0x3>, /* SERDES1 lane2/3 select */
- <0x20 0x3>, <0x24 0x3>, /* SERDES2 lane0/1 select */
- <0x28 0x3>, <0x2c 0x3>; /* SERDES2 lane2/3 select */
- idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>,
- <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
- <J784S4_SERDES0_LANE2_IP3_UNUSED>,
- <J784S4_SERDES0_LANE3_USB>,
- <J784S4_SERDES1_LANE0_PCIE0_LANE0>,
- <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
- <J784S4_SERDES1_LANE2_PCIE0_LANE2>,
- <J784S4_SERDES1_LANE3_PCIE0_LANE3>,
- <J784S4_SERDES2_LANE0_IP2_UNUSED>,
- <J784S4_SERDES2_LANE1_IP2_UNUSED>,
- <J784S4_SERDES2_LANE2_QSGMII_LANE1>,
- <J784S4_SERDES2_LANE3_QSGMII_LANE2>,
- <J784S4_SERDES4_LANE0_EDP_LANE0>,
- <J784S4_SERDES4_LANE1_EDP_LANE1>,
- <J784S4_SERDES4_LANE2_EDP_LANE2>,
- <J784S4_SERDES4_LANE3_EDP_LANE3>;
- };
-
- usb_serdes_mux: mux-controller@4000 {
- compatible = "reg-mux";
- reg = <0x4000 0x4>;
- #mux-control-cells = <1>;
- mux-reg-masks = <0x0 0x8000000>; /* USB0 to SERDES0 lane 3 mux */
- };
-
- ehrpwm_tbclk: clock-controller@4140 {
- compatible = "ti,am654-ehrpwm-tbclk";
- reg = <0x4140 0x18>;
- #clock-cells = <1>;
- };
-
- audio_refclk1: clock@82e4 {
- compatible = "ti,am62-audio-refclk";
- reg = <0x82e4 0x4>;
- clocks = <&k3_clks 157 34>;
- assigned-clocks = <&k3_clks 157 34>;
- assigned-clock-parents = <&k3_clks 157 63>;
- #clock-cells = <0>;
- };
- };
-
- main_ehrpwm0: pwm@3000000 {
- compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
- reg = <0x00 0x3000000 0x00 0x100>;
- clocks = <&ehrpwm_tbclk 0>, <&k3_clks 219 0>;
- clock-names = "tbclk", "fck";
- power-domains = <&k3_pds 219 TI_SCI_PD_EXCLUSIVE>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- main_ehrpwm1: pwm@3010000 {
- compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
- reg = <0x00 0x3010000 0x00 0x100>;
- clocks = <&ehrpwm_tbclk 1>, <&k3_clks 220 0>;
- clock-names = "tbclk", "fck";
- power-domains = <&k3_pds 220 TI_SCI_PD_EXCLUSIVE>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- main_ehrpwm2: pwm@3020000 {
- compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
- reg = <0x00 0x3020000 0x00 0x100>;
- clocks = <&ehrpwm_tbclk 2>, <&k3_clks 221 0>;
- clock-names = "tbclk", "fck";
- power-domains = <&k3_pds 221 TI_SCI_PD_EXCLUSIVE>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- main_ehrpwm3: pwm@3030000 {
- compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
- reg = <0x00 0x3030000 0x00 0x100>;
- clocks = <&ehrpwm_tbclk 3>, <&k3_clks 222 0>;
- clock-names = "tbclk", "fck";
- power-domains = <&k3_pds 222 TI_SCI_PD_EXCLUSIVE>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- main_ehrpwm4: pwm@3040000 {
- compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
- reg = <0x00 0x3040000 0x00 0x100>;
- clocks = <&ehrpwm_tbclk 4>, <&k3_clks 223 0>;
- clock-names = "tbclk", "fck";
- power-domains = <&k3_pds 223 TI_SCI_PD_EXCLUSIVE>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- main_ehrpwm5: pwm@3050000 {
- compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
- reg = <0x00 0x3050000 0x00 0x100>;
- clocks = <&ehrpwm_tbclk 5>, <&k3_clks 224 0>;
- clock-names = "tbclk", "fck";
- power-domains = <&k3_pds 224 TI_SCI_PD_EXCLUSIVE>;
- #pwm-cells = <3>;
- status = "disabled";
- };
-
- gic500: interrupt-controller@1800000 {
- compatible = "arm,gic-v3";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0x00 0x01800000 0x00 0x200000>, /* GICD */
- <0x00 0x01900000 0x00 0x100000>, /* GICR */
- <0x00 0x6f000000 0x00 0x2000>, /* GICC */
- <0x00 0x6f010000 0x00 0x1000>, /* GICH */
- <0x00 0x6f020000 0x00 0x2000>; /* GICV */
-
- /* vcpumntirq: virtual CPU interface maintenance interrupt */
- interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
-
- gic_its: msi-controller@1820000 {
- compatible = "arm,gic-v3-its";
- reg = <0x00 0x01820000 0x00 0x10000>;
- socionext,synquacer-pre-its = <0x1000000 0x400000>;
- msi-controller;
- #msi-cells = <1>;
- };
- };
-
- main_gpio_intr: interrupt-controller@a00000 {
- compatible = "ti,sci-intr";
- reg = <0x00 0x00a00000 0x00 0x800>;
- ti,intr-trigger-type = <1>;
- interrupt-controller;
- interrupt-parent = <&gic500>;
- #interrupt-cells = <1>;
+ c71_3: dsp@67800000 {
+ compatible = "ti,j721s2-c71-dsp";
+ reg = <0x00 0x67800000 0x00 0x00080000>,
+ <0x00 0x67e00000 0x00 0x0000c000>;
+ reg-names = "l2sram", "l1dram";
+ resets = <&k3_reset 40 1>;
+ firmware-name = "j784s4-c71_3-fw";
ti,sci = <&sms>;
- ti,sci-dev-id = <10>;
- ti,interrupt-ranges = <8 392 56>;
- };
-
- main_pmx0: pinctrl@11c000 {
- compatible = "pinctrl-single";
- /* Proxy 0 addressing */
- reg = <0x00 0x11c000 0x00 0x120>;
- #pinctrl-cells = <1>;
- pinctrl-single,register-width = <32>;
- pinctrl-single,function-mask = <0xffffffff>;
- };
-
- /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */
- main_timerio_input: pinctrl@104200 {
- compatible = "pinctrl-single";
- reg = <0x00 0x104200 0x00 0x50>;
- #pinctrl-cells = <1>;
- pinctrl-single,register-width = <32>;
- pinctrl-single,function-mask = <0x00000007>;
- };
-
- /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */
- main_timerio_output: pinctrl@104280 {
- compatible = "pinctrl-single";
- reg = <0x00 0x104280 0x00 0x20>;
- #pinctrl-cells = <1>;
- pinctrl-single,register-width = <32>;
- pinctrl-single,function-mask = <0x0000001f>;
- };
-
- main_crypto: crypto@4e00000 {
- compatible = "ti,j721e-sa2ul";
- reg = <0x00 0x4e00000 0x00 0x1200>;
- power-domains = <&k3_pds 369 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 0x4e10000 0x00 0x7d>;
- interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
- };
- };
-
- main_timer0: timer@2400000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2400000 0x00 0x400>;
- interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 97 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 97 2>;
- assigned-clock-parents = <&k3_clks 97 3>;
- power-domains = <&k3_pds 97 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 98 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 98 2>;
- assigned-clock-parents = <&k3_clks 98 3>;
- power-domains = <&k3_pds 98 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 99 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 99 2>;
- assigned-clock-parents = <&k3_clks 99 3>;
- power-domains = <&k3_pds 99 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 100 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 100 2>;
- assigned-clock-parents = <&k3_clks 100 3>;
- power-domains = <&k3_pds 100 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 101 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 101 2>;
- assigned-clock-parents = <&k3_clks 101 3>;
- power-domains = <&k3_pds 101 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 102 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 102 2>;
- assigned-clock-parents = <&k3_clks 102 3>;
- power-domains = <&k3_pds 102 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 103 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 103 2>;
- assigned-clock-parents = <&k3_clks 103 3>;
- power-domains = <&k3_pds 103 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 104 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 104 2>;
- assigned-clock-parents = <&k3_clks 104 3>;
- power-domains = <&k3_pds 104 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 105 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 105 2>;
- assigned-clock-parents = <&k3_clks 105 3>;
- power-domains = <&k3_pds 105 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 106 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 106 2>;
- assigned-clock-parents = <&k3_clks 106 3>;
- power-domains = <&k3_pds 106 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 107 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 107 2>;
- assigned-clock-parents = <&k3_clks 107 3>;
- power-domains = <&k3_pds 107 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 108 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 108 2>;
- assigned-clock-parents = <&k3_clks 108 3>;
- power-domains = <&k3_pds 108 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer12: timer@24c0000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x24c0000 0x00 0x400>;
- interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 109 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 109 2>;
- assigned-clock-parents = <&k3_clks 109 3>;
- power-domains = <&k3_pds 109 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer13: timer@24d0000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x24d0000 0x00 0x400>;
- interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 110 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 110 2>;
- assigned-clock-parents = <&k3_clks 110 3>;
- power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer14: timer@24e0000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x24e0000 0x00 0x400>;
- interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 111 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 111 2>;
- assigned-clock-parents = <&k3_clks 111 3>;
- power-domains = <&k3_pds 111 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer15: timer@24f0000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x24f0000 0x00 0x400>;
- interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 112 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 112 2>;
- assigned-clock-parents = <&k3_clks 112 3>;
- power-domains = <&k3_pds 112 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer16: timer@2500000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2500000 0x00 0x400>;
- interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 113 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 113 2>;
- assigned-clock-parents = <&k3_clks 113 3>;
- power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer17: timer@2510000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2510000 0x00 0x400>;
- interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 114 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 114 2>;
- assigned-clock-parents = <&k3_clks 114 3>;
- power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer18: timer@2520000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2520000 0x00 0x400>;
- interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 115 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 115 2>;
- assigned-clock-parents = <&k3_clks 115 3>;
- power-domains = <&k3_pds 115 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_timer19: timer@2530000 {
- compatible = "ti,am654-timer";
- reg = <0x00 0x2530000 0x00 0x400>;
- interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 116 2>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 116 2>;
- assigned-clock-parents = <&k3_clks 116 3>;
- power-domains = <&k3_pds 116 TI_SCI_PD_EXCLUSIVE>;
- ti,timer-pwm;
- };
-
- main_uart0: serial@2800000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02800000 0x00 0x200>;
- interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 146 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart1: serial@2810000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02810000 0x00 0x200>;
- interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 388 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 388 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart2: serial@2820000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02820000 0x00 0x200>;
- interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 389 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 389 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart3: serial@2830000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02830000 0x00 0x200>;
- interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 390 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 390 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart4: serial@2840000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02840000 0x00 0x200>;
- interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 391 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 391 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart5: serial@2850000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02850000 0x00 0x200>;
- interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 392 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 392 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart6: serial@2860000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02860000 0x00 0x200>;
- interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 393 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 393 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart7: serial@2870000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02870000 0x00 0x200>;
- interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 394 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 394 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart8: serial@2880000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02880000 0x00 0x200>;
- interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 395 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 395 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_uart9: serial@2890000 {
- compatible = "ti,j721e-uart", "ti,am654-uart";
- reg = <0x00 0x02890000 0x00 0x200>;
- interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 396 0>;
- clock-names = "fclk";
- power-domains = <&k3_pds 396 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_gpio0: gpio@600000 {
- compatible = "ti,j721e-gpio", "ti,keystone-gpio";
- reg = <0x00 0x00600000 0x00 0x100>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-parent = <&main_gpio_intr>;
- interrupts = <145>, <146>, <147>, <148>, <149>;
- interrupt-controller;
- #interrupt-cells = <2>;
- ti,ngpio = <66>;
- ti,davinci-gpio-unbanked = <0>;
- power-domains = <&k3_pds 163 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 163 0>;
- clock-names = "gpio";
- status = "disabled";
- };
-
- main_gpio2: gpio@610000 {
- compatible = "ti,j721e-gpio", "ti,keystone-gpio";
- reg = <0x00 0x00610000 0x00 0x100>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-parent = <&main_gpio_intr>;
- interrupts = <154>, <155>, <156>, <157>, <158>;
- interrupt-controller;
- #interrupt-cells = <2>;
- ti,ngpio = <66>;
- ti,davinci-gpio-unbanked = <0>;
- power-domains = <&k3_pds 164 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 164 0>;
- clock-names = "gpio";
- status = "disabled";
- };
-
- main_gpio4: gpio@620000 {
- compatible = "ti,j721e-gpio", "ti,keystone-gpio";
- reg = <0x00 0x00620000 0x00 0x100>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-parent = <&main_gpio_intr>;
- interrupts = <163>, <164>, <165>, <166>, <167>;
- interrupt-controller;
- #interrupt-cells = <2>;
- ti,ngpio = <66>;
- ti,davinci-gpio-unbanked = <0>;
- power-domains = <&k3_pds 165 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 165 0>;
- clock-names = "gpio";
- status = "disabled";
- };
-
- main_gpio6: gpio@630000 {
- compatible = "ti,j721e-gpio", "ti,keystone-gpio";
- reg = <0x00 0x00630000 0x00 0x100>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-parent = <&main_gpio_intr>;
- interrupts = <172>, <173>, <174>, <175>, <176>;
- interrupt-controller;
- #interrupt-cells = <2>;
- ti,ngpio = <66>;
- ti,davinci-gpio-unbanked = <0>;
- power-domains = <&k3_pds 166 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 166 0>;
- clock-names = "gpio";
- status = "disabled";
- };
-
- usbss0: usb@4104000 {
- bootph-all;
- compatible = "ti,j721e-usb";
- reg = <0x00 0x4104000 0x00 0x100>;
- dma-coherent;
- power-domains = <&k3_pds 398 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 398 21>, <&k3_clks 398 2>;
- clock-names = "ref", "lpm";
- assigned-clocks = <&k3_clks 398 21>; /* USB2_REFCLK */
- assigned-clock-parents = <&k3_clks 398 22>; /* HFOSC0 */
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
-
- status = "disabled"; /* Needs lane config */
-
- usb0: usb@6000000 {
- bootph-all;
- compatible = "cdns,usb3";
- reg = <0x00 0x6000000 0x00 0x10000>,
- <0x00 0x6010000 0x00 0x10000>,
- <0x00 0x6020000 0x00 0x10000>;
- reg-names = "otg", "xhci", "dev";
- interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
- <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, /* irq.6 */
- <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; /* otgirq.0 */
- interrupt-names = "host",
- "peripheral",
- "otg";
- };
- };
-
- main_i2c0: i2c@2000000 {
- compatible = "ti,j721e-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02000000 0x00 0x100>;
- interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 270 2>;
- clock-names = "fck";
- power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_i2c1: i2c@2010000 {
- compatible = "ti,j721e-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02010000 0x00 0x100>;
- interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 271 2>;
- clock-names = "fck";
- power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_i2c2: i2c@2020000 {
- compatible = "ti,j721e-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02020000 0x00 0x100>;
- interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 272 2>;
- clock-names = "fck";
- power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_i2c3: i2c@2030000 {
- compatible = "ti,j721e-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02030000 0x00 0x100>;
- interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 273 2>;
- clock-names = "fck";
- power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_i2c4: i2c@2040000 {
- compatible = "ti,j721e-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02040000 0x00 0x100>;
- interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 274 2>;
- clock-names = "fck";
- power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_i2c5: i2c@2050000 {
- compatible = "ti,j721e-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02050000 0x00 0x100>;
- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 275 2>;
- clock-names = "fck";
- power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- main_i2c6: i2c@2060000 {
- compatible = "ti,j721e-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02060000 0x00 0x100>;
- interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 276 2>;
- clock-names = "fck";
- power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- ti_csi2rx0: ticsi2rx@4500000 {
- compatible = "ti,j721e-csi2rx-shim";
- reg = <0x00 0x04500000 0x00 0x00001000>;
- ranges;
- #address-cells = <2>;
- #size-cells = <2>;
- dmas = <&main_bcdma_csi 0 0x4940 0>;
- dma-names = "rx0";
- power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
-
- cdns_csi2rx0: csi-bridge@4504000 {
- compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
- reg = <0x00 0x04504000 0x00 0x00001000>;
- clocks = <&k3_clks 72 2>, <&k3_clks 72 0>, <&k3_clks 72 2>,
- <&k3_clks 72 2>, <&k3_clks 72 3>, <&k3_clks 72 3>;
- clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
- "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
- phys = <&dphy0>;
- phy-names = "dphy";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- csi0_port0: port@0 {
- reg = <0>;
- status = "disabled";
- };
-
- csi0_port1: port@1 {
- reg = <1>;
- status = "disabled";
- };
-
- csi0_port2: port@2 {
- reg = <2>;
- status = "disabled";
- };
-
- csi0_port3: port@3 {
- reg = <3>;
- status = "disabled";
- };
-
- csi0_port4: port@4 {
- reg = <4>;
- status = "disabled";
- };
- };
- };
- };
-
- ti_csi2rx1: ticsi2rx@4510000 {
- compatible = "ti,j721e-csi2rx-shim";
- reg = <0x00 0x04510000 0x00 0x1000>;
- ranges;
- #address-cells = <2>;
- #size-cells = <2>;
- dmas = <&main_bcdma_csi 0 0x4960 0>;
- dma-names = "rx0";
- power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
-
- cdns_csi2rx1: csi-bridge@4514000 {
- compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
- reg = <0x00 0x04514000 0x00 0x00001000>;
- clocks = <&k3_clks 73 2>, <&k3_clks 73 0>, <&k3_clks 73 2>,
- <&k3_clks 73 2>, <&k3_clks 73 3>, <&k3_clks 73 3>;
- clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
- "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
- phys = <&dphy1>;
- phy-names = "dphy";
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- csi1_port0: port@0 {
- reg = <0>;
- status = "disabled";
- };
-
- csi1_port1: port@1 {
- reg = <1>;
- status = "disabled";
- };
-
- csi1_port2: port@2 {
- reg = <2>;
- status = "disabled";
- };
-
- csi1_port3: port@3 {
- reg = <3>;
- status = "disabled";
- };
-
- csi1_port4: port@4 {
- reg = <4>;
- status = "disabled";
- };
- };
- };
- };
-
- ti_csi2rx2: ticsi2rx@4520000 {
- compatible = "ti,j721e-csi2rx-shim";
- reg = <0x00 0x04520000 0x00 0x00001000>;
- ranges;
- #address-cells = <2>;
- #size-cells = <2>;
- dmas = <&main_bcdma_csi 0 0x4980 0>;
- dma-names = "rx0";
- power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
-
- cdns_csi2rx2: csi-bridge@4524000 {
- compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
- reg = <0x00 0x04524000 0x00 0x00001000>;
- clocks = <&k3_clks 74 2>, <&k3_clks 74 0>, <&k3_clks 74 2>,
- <&k3_clks 74 2>, <&k3_clks 74 3>, <&k3_clks 74 3>;
- clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
- "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
- phys = <&dphy2>;
- phy-names = "dphy";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- csi2_port0: port@0 {
- reg = <0>;
- status = "disabled";
- };
-
- csi2_port1: port@1 {
- reg = <1>;
- status = "disabled";
- };
-
- csi2_port2: port@2 {
- reg = <2>;
- status = "disabled";
- };
-
- csi2_port3: port@3 {
- reg = <3>;
- status = "disabled";
- };
-
- csi2_port4: port@4 {
- reg = <4>;
- status = "disabled";
- };
- };
- };
- };
-
- dphy0: phy@4580000 {
- compatible = "cdns,dphy-rx";
- reg = <0x00 0x04580000 0x00 0x00001100>;
- #phy-cells = <0>;
- power-domains = <&k3_pds 212 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- dphy1: phy@4590000 {
- compatible = "cdns,dphy-rx";
- reg = <0x00 0x04590000 0x00 0x00001100>;
- #phy-cells = <0>;
- power-domains = <&k3_pds 213 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- dphy2: phy@45a0000 {
- compatible = "cdns,dphy-rx";
- reg = <0x00 0x045a0000 0x00 0x00001100>;
- #phy-cells = <0>;
- power-domains = <&k3_pds 214 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- vpu0: video-codec@4210000 {
- compatible = "ti,j721s2-wave521c", "cnm,wave521c";
- reg = <0x00 0x4210000 0x00 0x10000>;
- interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 241 2>;
- power-domains = <&k3_pds 241 TI_SCI_PD_EXCLUSIVE>;
- };
-
- vpu1: video-codec@4220000 {
- compatible = "ti,j721s2-wave521c", "cnm,wave521c";
- reg = <0x00 0x4220000 0x00 0x10000>;
- interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 242 2>;
- power-domains = <&k3_pds 242 TI_SCI_PD_EXCLUSIVE>;
- };
-
- main_sdhci0: mmc@4f80000 {
- compatible = "ti,j721e-sdhci-8bit";
- reg = <0x00 0x04f80000 0x00 0x1000>,
- <0x00 0x04f88000 0x00 0x400>;
- interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 140 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 140 1>, <&k3_clks 140 2>;
- clock-names = "clk_ahb", "clk_xin";
- assigned-clocks = <&k3_clks 140 2>;
- assigned-clock-parents = <&k3_clks 140 3>;
- bus-width = <8>;
- ti,otap-del-sel-legacy = <0x0>;
- ti,otap-del-sel-mmc-hs = <0x0>;
- ti,otap-del-sel-ddr52 = <0x6>;
- ti,otap-del-sel-hs200 = <0x8>;
- ti,otap-del-sel-hs400 = <0x5>;
- ti,itap-del-sel-legacy = <0x10>;
- ti,itap-del-sel-mmc-hs = <0xa>;
- ti,strobe-sel = <0x77>;
- ti,clkbuf-sel = <0x7>;
- ti,trm-icp = <0x8>;
- mmc-ddr-1_8v;
- mmc-hs200-1_8v;
- mmc-hs400-1_8v;
- dma-coherent;
- status = "disabled";
- };
-
- main_sdhci1: mmc@4fb0000 {
- compatible = "ti,j721e-sdhci-4bit";
- reg = <0x00 0x04fb0000 0x00 0x1000>,
- <0x00 0x04fb8000 0x00 0x400>;
- interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 141 3>, <&k3_clks 141 4>;
- clock-names = "clk_ahb", "clk_xin";
- assigned-clocks = <&k3_clks 141 4>;
- assigned-clock-parents = <&k3_clks 141 5>;
- bus-width = <4>;
- ti,otap-del-sel-legacy = <0x0>;
- ti,otap-del-sel-sd-hs = <0x0>;
- ti,otap-del-sel-sdr12 = <0xf>;
- ti,otap-del-sel-sdr25 = <0xf>;
- ti,otap-del-sel-sdr50 = <0xc>;
- ti,otap-del-sel-sdr104 = <0x5>;
- ti,otap-del-sel-ddr50 = <0xc>;
- ti,itap-del-sel-legacy = <0x0>;
- ti,itap-del-sel-sd-hs = <0x0>;
- ti,itap-del-sel-sdr12 = <0x0>;
- ti,itap-del-sel-sdr25 = <0x0>;
- ti,itap-del-sel-ddr50 = <0x2>;
- ti,clkbuf-sel = <0x7>;
- ti,trm-icp = <0x8>;
- dma-coherent;
- status = "disabled";
- };
-
- pcie0_rc: pcie@2900000 {
- compatible = "ti,j784s4-pcie-host";
- reg = <0x00 0x02900000 0x00 0x1000>,
- <0x00 0x02907000 0x00 0x400>,
- <0x00 0x0d000000 0x00 0x00800000>,
- <0x00 0x10000000 0x00 0x00001000>;
- reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
- interrupt-names = "link_state";
- interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
- device_type = "pci";
- ti,syscon-pcie-ctrl = <&pcie0_ctrl 0x0>;
- max-link-speed = <3>;
- num-lanes = <4>;
- power-domains = <&k3_pds 332 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 332 0>;
- clock-names = "fck";
- #address-cells = <3>;
- #size-cells = <2>;
- bus-range = <0x0 0xff>;
- vendor-id = <0x104c>;
- device-id = <0xb012>;
- msi-map = <0x0 &gic_its 0x0 0x10000>;
- dma-coherent;
- ranges = <0x01000000 0x0 0x10001000 0x0 0x10001000 0x0 0x0010000>,
- <0x02000000 0x0 0x10011000 0x0 0x10011000 0x0 0x7fef000>;
- dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
- status = "disabled";
- };
-
- pcie1_rc: pcie@2910000 {
- compatible = "ti,j784s4-pcie-host";
- reg = <0x00 0x02910000 0x00 0x1000>,
- <0x00 0x02917000 0x00 0x400>,
- <0x00 0x0d800000 0x00 0x00800000>,
- <0x00 0x18000000 0x00 0x00001000>;
- reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
- interrupt-names = "link_state";
- interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
- device_type = "pci";
- ti,syscon-pcie-ctrl = <&pcie1_ctrl 0x0>;
- max-link-speed = <3>;
- num-lanes = <4>;
- power-domains = <&k3_pds 333 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 333 0>;
- clock-names = "fck";
- #address-cells = <3>;
- #size-cells = <2>;
- bus-range = <0x0 0xff>;
- vendor-id = <0x104c>;
- device-id = <0xb012>;
- msi-map = <0x0 &gic_its 0x10000 0x10000>;
- dma-coherent;
- ranges = <0x01000000 0x0 0x18001000 0x00 0x18001000 0x0 0x0010000>,
- <0x02000000 0x0 0x18011000 0x00 0x18011000 0x0 0x7fef000>;
- dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+ ti,sci-dev-id = <40>;
+ ti,sci-proc-ids = <0x33 0xff>;
status = "disabled";
};
@@ -1118,11 +25,12 @@
<0x00 0x02927000 0x00 0x400>,
<0x00 0x0e000000 0x00 0x00800000>,
<0x44 0x00000000 0x00 0x00001000>;
+ ranges = <0x01000000 0x0 0x00001000 0x44 0x00001000 0x0 0x0010000>,
+ <0x02000000 0x0 0x00011000 0x44 0x00011000 0x0 0x7fef000>;
reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
interrupt-names = "link_state";
interrupts = <GIC_SPI 342 IRQ_TYPE_EDGE_RISING>;
device_type = "pci";
- ti,syscon-pcie-ctrl = <&pcie2_ctrl 0x0>;
max-link-speed = <3>;
num-lanes = <2>;
power-domains = <&k3_pds 334 TI_SCI_PD_EXCLUSIVE>;
@@ -1135,9 +43,8 @@
device-id = <0xb012>;
msi-map = <0x0 &gic_its 0x20000 0x10000>;
dma-coherent;
- ranges = <0x01000000 0x0 0x00001000 0x44 0x00001000 0x0 0x0010000>,
- <0x02000000 0x0 0x00011000 0x44 0x00011000 0x0 0x7fef000>;
dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+ ti,syscon-pcie-ctrl = <&pcie2_ctrl 0x0>;
status = "disabled";
};
@@ -1147,11 +54,12 @@
<0x00 0x02937000 0x00 0x400>,
<0x00 0x0e800000 0x00 0x00800000>,
<0x44 0x10000000 0x00 0x00001000>;
+ ranges = <0x01000000 0x0 0x00001000 0x44 0x10001000 0x0 0x0010000>,
+ <0x02000000 0x0 0x00011000 0x44 0x10011000 0x0 0x7fef000>;
reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
interrupt-names = "link_state";
interrupts = <GIC_SPI 354 IRQ_TYPE_EDGE_RISING>;
device_type = "pci";
- ti,syscon-pcie-ctrl = <&pcie3_ctrl 0x0>;
max-link-speed = <3>;
num-lanes = <2>;
power-domains = <&k3_pds 335 TI_SCI_PD_EXCLUSIVE>;
@@ -1164,88 +72,14 @@
device-id = <0xb012>;
msi-map = <0x0 &gic_its 0x30000 0x10000>;
dma-coherent;
- ranges = <0x01000000 0x0 0x00001000 0x44 0x10001000 0x0 0x0010000>,
- <0x02000000 0x0 0x00011000 0x44 0x10011000 0x0 0x7fef000>;
dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+ ti,syscon-pcie-ctrl = <&pcie3_ctrl 0x0>;
status = "disabled";
};
- serdes_wiz0: wiz@5060000 {
- compatible = "ti,j784s4-wiz-10g";
- #address-cells = <1>;
- #size-cells = <1>;
- power-domains = <&k3_pds 404 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 404 2>, <&k3_clks 404 6>, <&serdes_refclk>, <&k3_clks 404 5>;
- clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
- assigned-clocks = <&k3_clks 404 6>;
- assigned-clock-parents = <&k3_clks 404 10>;
- num-lanes = <4>;
- #reset-cells = <1>;
- #clock-cells = <1>;
- ranges = <0x5060000 0x00 0x5060000 0x10000>;
- status = "disabled";
-
- serdes0: serdes@5060000 {
- compatible = "ti,j721e-serdes-10g";
- reg = <0x05060000 0x010000>;
- reg-names = "torrent_phy";
- resets = <&serdes_wiz0 0>;
- reset-names = "torrent_reset";
- clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
- <&serdes_wiz0 TI_WIZ_PHY_EN_REFCLK>;
- clock-names = "refclk", "phy_en_refclk";
- assigned-clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
- <&serdes_wiz0 TI_WIZ_PLL1_REFCLK>,
- <&serdes_wiz0 TI_WIZ_REFCLK_DIG>;
- assigned-clock-parents = <&k3_clks 404 6>,
- <&k3_clks 404 6>,
- <&k3_clks 404 6>;
- #address-cells = <1>;
- #size-cells = <0>;
- #clock-cells = <1>;
- status = "disabled";
- };
- };
-
- serdes_wiz1: wiz@5070000 {
- compatible = "ti,j784s4-wiz-10g";
- #address-cells = <1>;
- #size-cells = <1>;
- power-domains = <&k3_pds 405 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 405 2>, <&k3_clks 405 6>, <&serdes_refclk>, <&k3_clks 405 5>;
- clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
- assigned-clocks = <&k3_clks 405 6>;
- assigned-clock-parents = <&k3_clks 405 10>;
- num-lanes = <4>;
- #reset-cells = <1>;
- #clock-cells = <1>;
- ranges = <0x05070000 0x00 0x05070000 0x10000>;
- status = "disabled";
-
- serdes1: serdes@5070000 {
- compatible = "ti,j721e-serdes-10g";
- reg = <0x05070000 0x010000>;
- reg-names = "torrent_phy";
- resets = <&serdes_wiz1 0>;
- reset-names = "torrent_reset";
- clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
- <&serdes_wiz1 TI_WIZ_PHY_EN_REFCLK>;
- clock-names = "refclk", "phy_en_refclk";
- assigned-clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
- <&serdes_wiz1 TI_WIZ_PLL1_REFCLK>,
- <&serdes_wiz1 TI_WIZ_REFCLK_DIG>;
- assigned-clock-parents = <&k3_clks 405 6>,
- <&k3_clks 405 6>,
- <&k3_clks 405 6>;
- #address-cells = <1>;
- #size-cells = <0>;
- #clock-cells = <1>;
- status = "disabled";
- };
- };
-
serdes_wiz2: wiz@5020000 {
compatible = "ti,j784s4-wiz-10g";
+ ranges = <0x05020000 0x00 0x05020000 0x10000>;
#address-cells = <1>;
#size-cells = <1>;
power-domains = <&k3_pds 406 TI_SCI_PD_EXCLUSIVE>;
@@ -1256,7 +90,6 @@
num-lanes = <4>;
#reset-cells = <1>;
#clock-cells = <1>;
- ranges = <0x05020000 0x00 0x05020000 0x10000>;
status = "disabled";
serdes2: serdes@5020000 {
@@ -1280,1506 +113,16 @@
status = "disabled";
};
};
+};
- serdes_wiz4: wiz@5050000 {
- compatible = "ti,j784s4-wiz-10g";
- #address-cells = <1>;
- #size-cells = <1>;
- power-domains = <&k3_pds 407 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 407 2>, <&k3_clks 407 6>, <&serdes_refclk>, <&k3_clks 407 5>;
- clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
- assigned-clocks = <&k3_clks 407 6>;
- assigned-clock-parents = <&k3_clks 407 10>;
- num-lanes = <4>;
- #reset-cells = <1>;
- #clock-cells = <1>;
- ranges = <0x05050000 0x00 0x05050000 0x10000>,
- <0xa030a00 0x00 0xa030a00 0x40>; /* DPTX PHY */
- status = "disabled";
-
- serdes4: serdes@5050000 {
- /*
- * Note: we also map DPTX PHY registers as the Torrent
- * needs to manage those.
- */
- compatible = "ti,j721e-serdes-10g";
- reg = <0x05050000 0x010000>,
- <0x0a030a00 0x40>; /* DPTX PHY */
- reg-names = "torrent_phy";
- resets = <&serdes_wiz4 0>;
- reset-names = "torrent_reset";
- clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
- <&serdes_wiz4 TI_WIZ_PHY_EN_REFCLK>;
- clock-names = "refclk", "phy_en_refclk";
- assigned-clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
- <&serdes_wiz4 TI_WIZ_PLL1_REFCLK>,
- <&serdes_wiz4 TI_WIZ_REFCLK_DIG>;
- assigned-clock-parents = <&k3_clks 407 6>,
- <&k3_clks 407 6>,
- <&k3_clks 407 6>;
- #address-cells = <1>;
- #size-cells = <0>;
- #clock-cells = <1>;
- status = "disabled";
- };
- };
-
- main_navss: bus@30000000 {
- bootph-all;
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
- ti,sci-dev-id = <280>;
- dma-coherent;
- dma-ranges;
-
- main_navss_intr: interrupt-controller@310e0000 {
- compatible = "ti,sci-intr";
- reg = <0x00 0x310e0000 0x00 0x4000>;
- ti,intr-trigger-type = <4>;
- interrupt-controller;
- interrupt-parent = <&gic500>;
- #interrupt-cells = <1>;
- ti,sci = <&sms>;
- ti,sci-dev-id = <283>;
- ti,interrupt-ranges = <0 64 64>,
- <64 448 64>,
- <128 672 64>;
- };
-
- main_udmass_inta: msi-controller@33d00000 {
- compatible = "ti,sci-inta";
- reg = <0x00 0x33d00000 0x00 0x100000>;
- interrupt-controller;
- #interrupt-cells = <0>;
- interrupt-parent = <&main_navss_intr>;
- msi-controller;
- ti,sci = <&sms>;
- ti,sci-dev-id = <321>;
- ti,interrupt-ranges = <0 0 256>;
- ti,unmapped-event-sources = <&main_bcdma_csi>;
- };
-
- secure_proxy_main: mailbox@32c00000 {
- bootph-all;
- compatible = "ti,am654-secure-proxy";
- #mbox-cells = <1>;
- reg-names = "target_data", "rt", "scfg";
- reg = <0x00 0x32c00000 0x00 0x100000>,
- <0x00 0x32400000 0x00 0x100000>,
- <0x00 0x32800000 0x00 0x100000>;
- interrupt-names = "rx_011";
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- hwspinlock: hwlock@30e00000 {
- compatible = "ti,am654-hwspinlock";
- reg = <0x00 0x30e00000 0x00 0x1000>;
- #hwlock-cells = <1>;
- };
-
- mailbox0_cluster0: mailbox@31f80000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f80000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster1: mailbox@31f81000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f81000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster2: mailbox@31f82000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f82000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster3: mailbox@31f83000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f83000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster4: mailbox@31f84000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f84000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster5: mailbox@31f85000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f85000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster6: mailbox@31f86000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f86000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster7: mailbox@31f87000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f87000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster8: mailbox@31f88000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f88000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster9: mailbox@31f89000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f89000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster10: mailbox@31f8a000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f8a000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox0_cluster11: mailbox@31f8b000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f8b000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster0: mailbox@31f90000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f90000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster1: mailbox@31f91000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f91000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster2: mailbox@31f92000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f92000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster3: mailbox@31f93000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f93000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster4: mailbox@31f94000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f94000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster5: mailbox@31f95000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f95000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster6: mailbox@31f96000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f96000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster7: mailbox@31f97000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f97000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster8: mailbox@31f98000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f98000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster9: mailbox@31f99000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f99000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster10: mailbox@31f9a000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f9a000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- mailbox1_cluster11: mailbox@31f9b000 {
- compatible = "ti,am654-mailbox";
- reg = <0x00 0x31f9b000 0x00 0x200>;
- #mbox-cells = <1>;
- ti,mbox-num-users = <4>;
- ti,mbox-num-fifos = <16>;
- interrupt-parent = <&main_navss_intr>;
- status = "disabled";
- };
-
- main_ringacc: ringacc@3c000000 {
- compatible = "ti,am654-navss-ringacc";
- reg = <0x00 0x3c000000 0x00 0x400000>,
- <0x00 0x38000000 0x00 0x400000>,
- <0x00 0x31120000 0x00 0x100>,
- <0x00 0x33000000 0x00 0x40000>,
- <0x00 0x31080000 0x00 0x40000>;
- reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target", "cfg";
- ti,num-rings = <1024>;
- ti,sci-rm-range-gp-rings = <0x1>;
- ti,sci = <&sms>;
- ti,sci-dev-id = <315>;
- msi-parent = <&main_udmass_inta>;
- };
-
- main_udmap: dma-controller@31150000 {
- compatible = "ti,j721e-navss-main-udmap";
- reg = <0x00 0x31150000 0x00 0x100>,
- <0x00 0x34000000 0x00 0x80000>,
- <0x00 0x35000000 0x00 0x200000>,
- <0x00 0x30b00000 0x00 0x20000>,
- <0x00 0x30c00000 0x00 0x8000>,
- <0x00 0x30d00000 0x00 0x4000>;
- reg-names = "gcfg", "rchanrt", "tchanrt",
- "tchan", "rchan", "rflow";
- msi-parent = <&main_udmass_inta>;
- #dma-cells = <1>;
-
- ti,sci = <&sms>;
- ti,sci-dev-id = <319>;
- ti,ringacc = <&main_ringacc>;
-
- ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */
- <0x0f>, /* TX_HCHAN */
- <0x10>; /* TX_UHCHAN */
- ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */
- <0x0b>, /* RX_HCHAN */
- <0x0c>; /* RX_UHCHAN */
- ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
- };
-
- main_bcdma_csi: dma-controller@311a0000 {
- compatible = "ti,j721s2-dmss-bcdma-csi";
- reg = <0x00 0x311a0000 0x00 0x100>,
- <0x00 0x35d00000 0x00 0x20000>,
- <0x00 0x35c00000 0x00 0x10000>,
- <0x00 0x35e00000 0x00 0x80000>;
- reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
- msi-parent = <&main_udmass_inta>;
- #dma-cells = <3>;
- ti,sci = <&sms>;
- ti,sci-dev-id = <281>;
- ti,sci-rm-range-rchan = <0x21>;
- ti,sci-rm-range-tchan = <0x22>;
- };
-
- cpts@310d0000 {
- compatible = "ti,j721e-cpts";
- reg = <0x00 0x310d0000 0x00 0x400>;
- reg-names = "cpts";
- clocks = <&k3_clks 282 0>;
- clock-names = "cpts";
- assigned-clocks = <&k3_clks 62 3>; /* CPTS_RFT_CLK */
- assigned-clock-parents = <&k3_clks 62 5>; /* MAIN_0_HSDIV6_CLK */
- interrupts-extended = <&main_navss_intr 391>;
- interrupt-names = "cpts";
- ti,cpts-periodic-outputs = <6>;
- ti,cpts-ext-ts-inputs = <8>;
- };
- };
-
- main_cpsw0: ethernet@c000000 {
- compatible = "ti,j784s4-cpswxg-nuss";
- reg = <0x00 0xc000000 0x00 0x200000>;
- reg-names = "cpsw_nuss";
- ranges = <0x00 0x00 0x00 0xc000000 0x00 0x200000>;
- #address-cells = <2>;
- #size-cells = <2>;
- dma-coherent;
- clocks = <&k3_clks 64 0>;
- clock-names = "fck";
- power-domains = <&k3_pds 64 TI_SCI_PD_EXCLUSIVE>;
-
- dmas = <&main_udmap 0xca00>,
- <&main_udmap 0xca01>,
- <&main_udmap 0xca02>,
- <&main_udmap 0xca03>,
- <&main_udmap 0xca04>,
- <&main_udmap 0xca05>,
- <&main_udmap 0xca06>,
- <&main_udmap 0xca07>,
- <&main_udmap 0x4a00>;
- dma-names = "tx0", "tx1", "tx2", "tx3",
- "tx4", "tx5", "tx6", "tx7",
- "rx";
-
- status = "disabled";
-
- ethernet-ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- main_cpsw0_port1: port@1 {
- reg = <1>;
- label = "port1";
- ti,mac-only;
- status = "disabled";
- };
-
- main_cpsw0_port2: port@2 {
- reg = <2>;
- label = "port2";
- ti,mac-only;
- status = "disabled";
- };
-
- main_cpsw0_port3: port@3 {
- reg = <3>;
- label = "port3";
- ti,mac-only;
- status = "disabled";
- };
-
- main_cpsw0_port4: port@4 {
- reg = <4>;
- label = "port4";
- ti,mac-only;
- status = "disabled";
- };
-
- main_cpsw0_port5: port@5 {
- reg = <5>;
- label = "port5";
- ti,mac-only;
- status = "disabled";
- };
-
- main_cpsw0_port6: port@6 {
- reg = <6>;
- label = "port6";
- ti,mac-only;
- status = "disabled";
- };
-
- main_cpsw0_port7: port@7 {
- reg = <7>;
- label = "port7";
- ti,mac-only;
- status = "disabled";
- };
-
- main_cpsw0_port8: port@8 {
- reg = <8>;
- label = "port8";
- ti,mac-only;
- status = "disabled";
- };
- };
-
- main_cpsw0_mdio: mdio@f00 {
- compatible = "ti,cpsw-mdio","ti,davinci_mdio";
- reg = <0x00 0xf00 0x00 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 64 0>;
- clock-names = "fck";
- bus_freq = <1000000>;
- status = "disabled";
- };
-
- cpts@3d000 {
- compatible = "ti,am65-cpts";
- reg = <0x00 0x3d000 0x00 0x400>;
- clocks = <&k3_clks 64 3>;
- clock-names = "cpts";
- interrupts-extended = <&gic500 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cpts";
- ti,cpts-ext-ts-inputs = <4>;
- ti,cpts-periodic-outputs = <2>;
- };
- };
-
- main_cpsw1: ethernet@c200000 {
- compatible = "ti,j721e-cpsw-nuss";
- reg = <0x00 0xc200000 0x00 0x200000>;
- reg-names = "cpsw_nuss";
- ranges = <0x00 0x00 0x00 0xc200000 0x00 0x200000>;
- #address-cells = <2>;
- #size-cells = <2>;
- dma-coherent;
- clocks = <&k3_clks 62 0>;
- clock-names = "fck";
- power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
-
- dmas = <&main_udmap 0xc640>,
- <&main_udmap 0xc641>,
- <&main_udmap 0xc642>,
- <&main_udmap 0xc643>,
- <&main_udmap 0xc644>,
- <&main_udmap 0xc645>,
- <&main_udmap 0xc646>,
- <&main_udmap 0xc647>,
- <&main_udmap 0x4640>;
- dma-names = "tx0", "tx1", "tx2", "tx3",
- "tx4", "tx5", "tx6", "tx7",
- "rx";
-
- status = "disabled";
-
- ethernet-ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- main_cpsw1_port1: port@1 {
- reg = <1>;
- label = "port1";
- phys = <&cpsw1_phy_gmii_sel 1>;
- ti,mac-only;
- status = "disabled";
- };
- };
-
- main_cpsw1_mdio: mdio@f00 {
- compatible = "ti,cpsw-mdio", "ti,davinci_mdio";
- reg = <0x00 0xf00 0x00 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&k3_clks 62 0>;
- clock-names = "fck";
- bus_freq = <1000000>;
- status = "disabled";
- };
-
- cpts@3d000 {
- compatible = "ti,am65-cpts";
- reg = <0x00 0x3d000 0x00 0x400>;
- clocks = <&k3_clks 62 3>;
- clock-names = "cpts";
- interrupts-extended = <&gic500 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cpts";
- ti,cpts-ext-ts-inputs = <4>;
- ti,cpts-periodic-outputs = <2>;
- };
- };
-
- main_mcan0: can@2701000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02701000 0x00 0x200>,
- <0x00 0x02708000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 245 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 245 6>, <&k3_clks 245 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan1: can@2711000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02711000 0x00 0x200>,
- <0x00 0x02718000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 246 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 246 6>, <&k3_clks 246 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan2: can@2721000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02721000 0x00 0x200>,
- <0x00 0x02728000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 247 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 247 6>, <&k3_clks 247 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan3: can@2731000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02731000 0x00 0x200>,
- <0x00 0x02738000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 248 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 248 6>, <&k3_clks 248 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan4: can@2741000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02741000 0x00 0x200>,
- <0x00 0x02748000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 249 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 249 6>, <&k3_clks 249 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan5: can@2751000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02751000 0x00 0x200>,
- <0x00 0x02758000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 250 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 250 6>, <&k3_clks 250 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan6: can@2761000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02761000 0x00 0x200>,
- <0x00 0x02768000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 251 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 251 6>, <&k3_clks 251 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan7: can@2771000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02771000 0x00 0x200>,
- <0x00 0x02778000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 252 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 252 6>, <&k3_clks 252 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan8: can@2781000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02781000 0x00 0x200>,
- <0x00 0x02788000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 253 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 253 6>, <&k3_clks 253 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 576 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan9: can@2791000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02791000 0x00 0x200>,
- <0x00 0x02798000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 254 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 254 6>, <&k3_clks 254 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 579 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan10: can@27a1000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x027a1000 0x00 0x200>,
- <0x00 0x027a8000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 255 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 255 6>, <&k3_clks 255 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan11: can@27b1000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x027b1000 0x00 0x200>,
- <0x00 0x027b8000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 256 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 256 6>, <&k3_clks 256 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan12: can@27c1000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x027c1000 0x00 0x200>,
- <0x00 0x027c8000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 257 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 257 6>, <&k3_clks 257 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan13: can@27d1000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x027d1000 0x00 0x200>,
- <0x00 0x027d8000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 258 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 258 6>, <&k3_clks 258 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 591 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan14: can@2681000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02681000 0x00 0x200>,
- <0x00 0x02688000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 259 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 259 6>, <&k3_clks 259 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 594 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 595 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan15: can@2691000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x02691000 0x00 0x200>,
- <0x00 0x02698000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 260 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 260 6>, <&k3_clks 260 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 597 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 598 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan16: can@26a1000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x026a1000 0x00 0x200>,
- <0x00 0x026a8000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 261 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 261 6>, <&k3_clks 261 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 784 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 785 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_mcan17: can@26b1000 {
- compatible = "bosch,m_can";
- reg = <0x00 0x026b1000 0x00 0x200>,
- <0x00 0x026b8000 0x00 0x8000>;
- reg-names = "m_can", "message_ram";
- power-domains = <&k3_pds 262 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 262 6>, <&k3_clks 262 1>;
- clock-names = "hclk", "cclk";
- interrupts = <GIC_SPI 787 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 788 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "int0", "int1";
- bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
- status = "disabled";
- };
-
- main_spi0: spi@2100000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02100000 0x00 0x400>;
- interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 376 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 376 1>;
- status = "disabled";
- };
-
- main_spi1: spi@2110000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02110000 0x00 0x400>;
- interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 377 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 377 1>;
- status = "disabled";
- };
-
- main_spi2: spi@2120000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02120000 0x00 0x400>;
- interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 378 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 378 1>;
- status = "disabled";
- };
-
- main_spi3: spi@2130000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02130000 0x00 0x400>;
- interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 379 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 379 1>;
- status = "disabled";
- };
-
- main_spi4: spi@2140000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02140000 0x00 0x400>;
- interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 380 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 380 1>;
- status = "disabled";
- };
-
- main_spi5: spi@2150000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02150000 0x00 0x400>;
- interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 381 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 381 1>;
- status = "disabled";
- };
-
- main_spi6: spi@2160000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02160000 0x00 0x400>;
- interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 382 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 382 1>;
- status = "disabled";
- };
-
- main_spi7: spi@2170000 {
- compatible = "ti,am654-mcspi","ti,omap4-mcspi";
- reg = <0x00 0x02170000 0x00 0x400>;
- interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- power-domains = <&k3_pds 383 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 383 1>;
- status = "disabled";
- };
-
- ufs_wrapper: ufs-wrapper@4e80000 {
- compatible = "ti,j721e-ufs";
- reg = <0x00 0x4e80000 0x00 0x100>;
- power-domains = <&k3_pds 387 TI_SCI_PD_EXCLUSIVE>;
- clocks = <&k3_clks 387 3>;
- assigned-clocks = <&k3_clks 387 3>;
- assigned-clock-parents = <&k3_clks 387 6>;
- ranges;
- #address-cells = <2>;
- #size-cells = <2>;
- status = "disabled";
-
- ufs@4e84000 {
- compatible = "cdns,ufshc-m31-16nm", "jedec,ufs-2.0";
- reg = <0x00 0x4e84000 0x00 0x10000>;
- interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
- freq-table-hz = <250000000 250000000>, <19200000 19200000>,
- <19200000 19200000>;
- clocks = <&k3_clks 387 1>, <&k3_clks 387 3>, <&k3_clks 387 3>;
- clock-names = "core_clk", "phy_clk", "ref_clk";
- dma-coherent;
- };
- };
-
- main_r5fss0: r5fss@5c00000 {
- compatible = "ti,j721s2-r5fss";
- ti,cluster-mode = <1>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
- <0x5d00000 0x00 0x5d00000 0x20000>;
- power-domains = <&k3_pds 336 TI_SCI_PD_EXCLUSIVE>;
-
- main_r5fss0_core0: r5f@5c00000 {
- compatible = "ti,j721s2-r5f";
- reg = <0x5c00000 0x00010000>,
- <0x5c10000 0x00010000>;
- reg-names = "atcm", "btcm";
- ti,sci = <&sms>;
- ti,sci-dev-id = <339>;
- ti,sci-proc-ids = <0x06 0xff>;
- resets = <&k3_reset 339 1>;
- firmware-name = "j784s4-main-r5f0_0-fw";
- ti,atcm-enable = <1>;
- ti,btcm-enable = <1>;
- ti,loczrama = <1>;
- };
-
- main_r5fss0_core1: r5f@5d00000 {
- compatible = "ti,j721s2-r5f";
- reg = <0x5d00000 0x00010000>,
- <0x5d10000 0x00010000>;
- reg-names = "atcm", "btcm";
- ti,sci = <&sms>;
- ti,sci-dev-id = <340>;
- ti,sci-proc-ids = <0x07 0xff>;
- resets = <&k3_reset 340 1>;
- firmware-name = "j784s4-main-r5f0_1-fw";
- ti,atcm-enable = <1>;
- ti,btcm-enable = <1>;
- ti,loczrama = <1>;
- };
- };
-
- main_r5fss1: r5fss@5e00000 {
- compatible = "ti,j721s2-r5fss";
- ti,cluster-mode = <1>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x5e00000 0x00 0x5e00000 0x20000>,
- <0x5f00000 0x00 0x5f00000 0x20000>;
- power-domains = <&k3_pds 337 TI_SCI_PD_EXCLUSIVE>;
-
- main_r5fss1_core0: r5f@5e00000 {
- compatible = "ti,j721s2-r5f";
- reg = <0x5e00000 0x00010000>,
- <0x5e10000 0x00010000>;
- reg-names = "atcm", "btcm";
- ti,sci = <&sms>;
- ti,sci-dev-id = <341>;
- ti,sci-proc-ids = <0x08 0xff>;
- resets = <&k3_reset 341 1>;
- firmware-name = "j784s4-main-r5f1_0-fw";
- ti,atcm-enable = <1>;
- ti,btcm-enable = <1>;
- ti,loczrama = <1>;
- };
-
- main_r5fss1_core1: r5f@5f00000 {
- compatible = "ti,j721s2-r5f";
- reg = <0x5f00000 0x00010000>,
- <0x5f10000 0x00010000>;
- reg-names = "atcm", "btcm";
- ti,sci = <&sms>;
- ti,sci-dev-id = <342>;
- ti,sci-proc-ids = <0x09 0xff>;
- resets = <&k3_reset 342 1>;
- firmware-name = "j784s4-main-r5f1_1-fw";
- ti,atcm-enable = <1>;
- ti,btcm-enable = <1>;
- ti,loczrama = <1>;
- };
- };
-
- main_r5fss2: r5fss@5900000 {
- compatible = "ti,j721s2-r5fss";
- ti,cluster-mode = <1>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x5900000 0x00 0x5900000 0x20000>,
- <0x5a00000 0x00 0x5a00000 0x20000>;
- power-domains = <&k3_pds 338 TI_SCI_PD_EXCLUSIVE>;
-
- main_r5fss2_core0: r5f@5900000 {
- compatible = "ti,j721s2-r5f";
- reg = <0x5900000 0x00010000>,
- <0x5910000 0x00010000>;
- reg-names = "atcm", "btcm";
- ti,sci = <&sms>;
- ti,sci-dev-id = <343>;
- ti,sci-proc-ids = <0x0a 0xff>;
- resets = <&k3_reset 343 1>;
- firmware-name = "j784s4-main-r5f2_0-fw";
- ti,atcm-enable = <1>;
- ti,btcm-enable = <1>;
- ti,loczrama = <1>;
- };
-
- main_r5fss2_core1: r5f@5a00000 {
- compatible = "ti,j721s2-r5f";
- reg = <0x5a00000 0x00010000>,
- <0x5a10000 0x00010000>;
- reg-names = "atcm", "btcm";
- ti,sci = <&sms>;
- ti,sci-dev-id = <344>;
- ti,sci-proc-ids = <0x0b 0xff>;
- resets = <&k3_reset 344 1>;
- firmware-name = "j784s4-main-r5f2_1-fw";
- ti,atcm-enable = <1>;
- ti,btcm-enable = <1>;
- ti,loczrama = <1>;
- };
- };
-
- c71_0: dsp@64800000 {
- compatible = "ti,j721s2-c71-dsp";
- reg = <0x00 0x64800000 0x00 0x00080000>,
- <0x00 0x64e00000 0x00 0x0000c000>;
- reg-names = "l2sram", "l1dram";
- ti,sci = <&sms>;
- ti,sci-dev-id = <30>;
- ti,sci-proc-ids = <0x30 0xff>;
- resets = <&k3_reset 30 1>;
- firmware-name = "j784s4-c71_0-fw";
- status = "disabled";
- };
-
- c71_1: dsp@65800000 {
- compatible = "ti,j721s2-c71-dsp";
- reg = <0x00 0x65800000 0x00 0x00080000>,
- <0x00 0x65e00000 0x00 0x0000c000>;
- reg-names = "l2sram", "l1dram";
- ti,sci = <&sms>;
- ti,sci-dev-id = <33>;
- ti,sci-proc-ids = <0x31 0xff>;
- resets = <&k3_reset 33 1>;
- firmware-name = "j784s4-c71_1-fw";
- status = "disabled";
- };
-
- c71_2: dsp@66800000 {
- compatible = "ti,j721s2-c71-dsp";
- reg = <0x00 0x66800000 0x00 0x00080000>,
- <0x00 0x66e00000 0x00 0x0000c000>;
- reg-names = "l2sram", "l1dram";
- ti,sci = <&sms>;
- ti,sci-dev-id = <37>;
- ti,sci-proc-ids = <0x32 0xff>;
- resets = <&k3_reset 37 1>;
- firmware-name = "j784s4-c71_2-fw";
- status = "disabled";
- };
-
- c71_3: dsp@67800000 {
- compatible = "ti,j721s2-c71-dsp";
- reg = <0x00 0x67800000 0x00 0x00080000>,
- <0x00 0x67e00000 0x00 0x0000c000>;
- reg-names = "l2sram", "l1dram";
- ti,sci = <&sms>;
- ti,sci-dev-id = <40>;
- ti,sci-proc-ids = <0x33 0xff>;
- resets = <&k3_reset 40 1>;
- firmware-name = "j784s4-c71_3-fw";
- status = "disabled";
- };
-
- main_esm: esm@700000 {
- compatible = "ti,j721e-esm";
- reg = <0x00 0x700000 0x00 0x1000>;
- ti,esm-pins = <688>, <689>, <690>, <691>, <692>, <693>, <694>,
- <695>;
- bootph-pre-ram;
- };
-
- watchdog0: watchdog@2200000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2200000 0x00 0x100>;
- clocks = <&k3_clks 348 0>;
- power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 348 0>;
- assigned-clock-parents = <&k3_clks 348 4>;
- };
-
- watchdog1: watchdog@2210000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2210000 0x00 0x100>;
- clocks = <&k3_clks 349 0>;
- power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 349 0>;
- assigned-clock-parents = <&k3_clks 349 4>;
- };
-
- watchdog2: watchdog@2220000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2220000 0x00 0x100>;
- clocks = <&k3_clks 350 0>;
- power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 350 0>;
- assigned-clock-parents = <&k3_clks 350 4>;
- };
-
- watchdog3: watchdog@2230000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2230000 0x00 0x100>;
- clocks = <&k3_clks 351 0>;
- power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 351 0>;
- assigned-clock-parents = <&k3_clks 351 4>;
- };
-
- watchdog4: watchdog@2240000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2240000 0x00 0x100>;
- clocks = <&k3_clks 352 0>;
- power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 352 0>;
- assigned-clock-parents = <&k3_clks 352 4>;
- };
-
- watchdog5: watchdog@2250000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2250000 0x00 0x100>;
- clocks = <&k3_clks 353 0>;
- power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 353 0>;
- assigned-clock-parents = <&k3_clks 353 4>;
- };
-
- watchdog6: watchdog@2260000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2260000 0x00 0x100>;
- clocks = <&k3_clks 354 0>;
- power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 354 0>;
- assigned-clock-parents = <&k3_clks 354 4>;
- };
-
- watchdog7: watchdog@2270000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2270000 0x00 0x100>;
- clocks = <&k3_clks 355 0>;
- power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 355 0>;
- assigned-clock-parents = <&k3_clks 355 4>;
- };
-
- /*
- * The following RTI instances are coupled with MCU R5Fs, c7x and
- * GPU so keeping them reserved as these will be used by their
- * respective firmware
- */
- watchdog8: watchdog@22f0000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x22f0000 0x00 0x100>;
- clocks = <&k3_clks 360 0>;
- power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 360 0>;
- assigned-clock-parents = <&k3_clks 360 4>;
- /* reserved for GPU */
- status = "reserved";
- };
-
- watchdog9: watchdog@2300000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2300000 0x00 0x100>;
- clocks = <&k3_clks 356 0>;
- power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 356 0>;
- assigned-clock-parents = <&k3_clks 356 4>;
- /* reserved for C7X_0 DSP */
- status = "reserved";
- };
-
- watchdog10: watchdog@2310000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2310000 0x00 0x100>;
- clocks = <&k3_clks 357 0>;
- power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 357 0>;
- assigned-clock-parents = <&k3_clks 357 4>;
- /* reserved for C7X_1 DSP */
- status = "reserved";
- };
-
- watchdog11: watchdog@2320000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2320000 0x00 0x100>;
- clocks = <&k3_clks 358 0>;
- power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 358 0>;
- assigned-clock-parents = <&k3_clks 358 4>;
- /* reserved for C7X_2 DSP */
- status = "reserved";
- };
-
- watchdog12: watchdog@2330000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2330000 0x00 0x100>;
- clocks = <&k3_clks 359 0>;
- power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 359 0>;
- assigned-clock-parents = <&k3_clks 359 4>;
- /* reserved for C7X_3 DSP */
- status = "reserved";
- };
-
- watchdog13: watchdog@23c0000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x23c0000 0x00 0x100>;
- clocks = <&k3_clks 361 0>;
- power-domains = <&k3_pds 361 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 361 0>;
- assigned-clock-parents = <&k3_clks 361 4>;
- /* reserved for MAIN_R5F0_0 */
- status = "reserved";
- };
-
- watchdog14: watchdog@23d0000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x23d0000 0x00 0x100>;
- clocks = <&k3_clks 362 0>;
- power-domains = <&k3_pds 362 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 362 0>;
- assigned-clock-parents = <&k3_clks 362 4>;
- /* reserved for MAIN_R5F0_1 */
- status = "reserved";
- };
-
- watchdog15: watchdog@23e0000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x23e0000 0x00 0x100>;
- clocks = <&k3_clks 363 0>;
- power-domains = <&k3_pds 363 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 363 0>;
- assigned-clock-parents = <&k3_clks 363 4>;
- /* reserved for MAIN_R5F1_0 */
- status = "reserved";
- };
-
- watchdog16: watchdog@23f0000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x23f0000 0x00 0x100>;
- clocks = <&k3_clks 364 0>;
- power-domains = <&k3_pds 364 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 364 0>;
- assigned-clock-parents = <&k3_clks 364 4>;
- /* reserved for MAIN_R5F1_1 */
- status = "reserved";
- };
-
- watchdog17: watchdog@2540000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2540000 0x00 0x100>;
- clocks = <&k3_clks 365 0>;
- power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 365 0>;
- assigned-clock-parents = <&k3_clks 366 4>;
- /* reserved for MAIN_R5F2_0 */
- status = "reserved";
- };
-
- watchdog18: watchdog@2550000 {
- compatible = "ti,j7-rti-wdt";
- reg = <0x00 0x2550000 0x00 0x100>;
- clocks = <&k3_clks 366 0>;
- power-domains = <&k3_pds 366 TI_SCI_PD_EXCLUSIVE>;
- assigned-clocks = <&k3_clks 366 0>;
- assigned-clock-parents = <&k3_clks 366 4>;
- /* reserved for MAIN_R5F2_1 */
- status = "reserved";
- };
-
- mhdp: bridge@a000000 {
- compatible = "ti,j721e-mhdp8546";
- reg = <0x0 0xa000000 0x0 0x30a00>,
- <0x0 0x4f40000 0x0 0x20>;
- reg-names = "mhdptx", "j721e-intg";
- clocks = <&k3_clks 217 11>;
- interrupt-parent = <&gic500>;
- interrupts = <GIC_SPI 614 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&k3_pds 217 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
-
- dp0_ports: ports {
- #address-cells = <1>;
- #size-cells = <0>;
- /* Remote-endpoints are on the boards so
- * ports are defined in the platform dt file.
- */
- };
- };
-
- dss: dss@4a00000 {
- compatible = "ti,j721e-dss";
- reg = <0x00 0x04a00000 0x00 0x10000>, /* common_m */
- <0x00 0x04a10000 0x00 0x10000>, /* common_s0*/
- <0x00 0x04b00000 0x00 0x10000>, /* common_s1*/
- <0x00 0x04b10000 0x00 0x10000>, /* common_s2*/
- <0x00 0x04a20000 0x00 0x10000>, /* vidl1 */
- <0x00 0x04a30000 0x00 0x10000>, /* vidl2 */
- <0x00 0x04a50000 0x00 0x10000>, /* vid1 */
- <0x00 0x04a60000 0x00 0x10000>, /* vid2 */
- <0x00 0x04a70000 0x00 0x10000>, /* ovr1 */
- <0x00 0x04a90000 0x00 0x10000>, /* ovr2 */
- <0x00 0x04ab0000 0x00 0x10000>, /* ovr3 */
- <0x00 0x04ad0000 0x00 0x10000>, /* ovr4 */
- <0x00 0x04a80000 0x00 0x10000>, /* vp1 */
- <0x00 0x04aa0000 0x00 0x10000>, /* vp1 */
- <0x00 0x04ac0000 0x00 0x10000>, /* vp1 */
- <0x00 0x04ae0000 0x00 0x10000>, /* vp4 */
- <0x00 0x04af0000 0x00 0x10000>; /* wb */
- reg-names = "common_m", "common_s0",
- "common_s1", "common_s2",
- "vidl1", "vidl2","vid1","vid2",
- "ovr1", "ovr2", "ovr3", "ovr4",
- "vp1", "vp2", "vp3", "vp4",
- "wb";
- clocks = <&k3_clks 218 0>,
- <&k3_clks 218 2>,
- <&k3_clks 218 5>,
- <&k3_clks 218 14>,
- <&k3_clks 218 18>;
- clock-names = "fck", "vp1", "vp2", "vp3", "vp4";
- power-domains = <&k3_pds 218 TI_SCI_PD_EXCLUSIVE>;
- interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "common_m",
- "common_s0",
- "common_s1",
- "common_s2";
- status = "disabled";
-
- dss_ports: ports {
- /* Ports that DSS drives are platform specific
- * so they are defined in platform dt file.
- */
- };
- };
-
- mcasp0: mcasp@2b00000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b00000 0x00 0x2000>,
- <0x00 0x02b08000 0x00 0x1000>;
- reg-names = "mpu","dat";
- interrupts = <GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 545 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
- dmas = <&main_udmap 0xc400>, <&main_udmap 0x4400>;
- dma-names = "tx", "rx";
- clocks = <&k3_clks 265 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 265 0>;
- assigned-clock-parents = <&k3_clks 265 1>;
- power-domains = <&k3_pds 265 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- mcasp1: mcasp@2b10000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b10000 0x00 0x2000>,
- <0x00 0x02b18000 0x00 0x1000>;
- reg-names = "mpu","dat";
- interrupts = <GIC_SPI 546 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 547 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
- dmas = <&main_udmap 0xc401>, <&main_udmap 0x4401>;
- dma-names = "tx", "rx";
- clocks = <&k3_clks 266 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 266 0>;
- assigned-clock-parents = <&k3_clks 266 1>;
- power-domains = <&k3_pds 266 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- mcasp2: mcasp@2b20000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b20000 0x00 0x2000>,
- <0x00 0x02b28000 0x00 0x1000>;
- reg-names = "mpu","dat";
- interrupts = <GIC_SPI 548 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 549 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
- dmas = <&main_udmap 0xc402>, <&main_udmap 0x4402>;
- dma-names = "tx", "rx";
- clocks = <&k3_clks 267 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 267 0>;
- assigned-clock-parents = <&k3_clks 267 1>;
- power-domains = <&k3_pds 267 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
- };
-
- mcasp3: mcasp@2b30000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b30000 0x00 0x2000>,
- <0x00 0x02b38000 0x00 0x1000>;
- reg-names = "mpu","dat";
- interrupts = <GIC_SPI 550 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 551 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
- dmas = <&main_udmap 0xc403>, <&main_udmap 0x4403>;
- dma-names = "tx", "rx";
- clocks = <&k3_clks 268 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 268 0>;
- assigned-clock-parents = <&k3_clks 268 1>;
- power-domains = <&k3_pds 268 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
+&scm_conf {
+ pcie2_ctrl: pcie2-ctrl@4078 {
+ compatible = "ti,j784s4-pcie-ctrl", "syscon";
+ reg = <0x4078 0x4>;
};
- mcasp4: mcasp@2b40000 {
- compatible = "ti,am33xx-mcasp-audio";
- reg = <0x00 0x02b40000 0x00 0x2000>,
- <0x00 0x02b48000 0x00 0x1000>;
- reg-names = "mpu","dat";
- interrupts = <GIC_SPI 552 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 553 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tx", "rx";
- dmas = <&main_udmap 0xc404>, <&main_udmap 0x4404>;
- dma-names = "tx", "rx";
- clocks = <&k3_clks 269 0>;
- clock-names = "fck";
- assigned-clocks = <&k3_clks 269 0>;
- assigned-clock-parents = <&k3_clks 269 1>;
- power-domains = <&k3_pds 269 TI_SCI_PD_EXCLUSIVE>;
- status = "disabled";
+ pcie3_ctrl: pcie3-ctrl@407c {
+ compatible = "ti,j784s4-pcie-ctrl", "syscon";
+ reg = <0x407c 0x4>;
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi
index 5e84c6b4f5ad..f5afa32157cb 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi
@@ -8,18 +8,11 @@
*
*/
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/soc/ti,sci_pm_domain.h>
-
-#include "k3-pinctrl.h"
+#include "k3-j784s4-j742s2-common.dtsi"
/ {
model = "Texas Instruments K3 J784S4 SoC";
compatible = "ti,j784s4";
- interrupt-parent = <&gic500>;
- #address-cells = <2>;
- #size-cells = <2>;
cpus {
#address-cells = <1>;
@@ -174,130 +167,6 @@
next-level-cache = <&L2_1>;
};
};
-
- L2_0: l2-cache0 {
- compatible = "cache";
- cache-level = <2>;
- cache-unified;
- cache-size = <0x200000>;
- cache-line-size = <64>;
- cache-sets = <1024>;
- next-level-cache = <&msmc_l3>;
- };
-
- L2_1: l2-cache1 {
- compatible = "cache";
- cache-level = <2>;
- cache-unified;
- cache-size = <0x200000>;
- cache-line-size = <64>;
- cache-sets = <1024>;
- next-level-cache = <&msmc_l3>;
- };
-
- msmc_l3: l3-cache0 {
- compatible = "cache";
- cache-level = <3>;
- cache-unified;
- };
-
- firmware {
- optee {
- compatible = "linaro,optee-tz";
- method = "smc";
- };
-
- psci: psci {
- compatible = "arm,psci-1.0";
- method = "smc";
- };
- };
-
- a72_timer0: timer-cl0-cpu0 {
- compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, /* cntpsirq */
- <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, /* cntpnsirq */
- <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, /* cntvirq */
- <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; /* cnthpirq */
- };
-
- pmu: pmu {
- compatible = "arm,cortex-a72-pmu";
- /* Recommendation from GIC500 TRM Table A.3 */
- interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- cbass_main: bus@100000 {
- bootph-all;
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */
- <0x00 0x00600000 0x00 0x00600000 0x00 0x00031100>, /* GPIO */
- <0x00 0x00700000 0x00 0x00700000 0x00 0x00001000>, /* ESM */
- <0x00 0x01000000 0x00 0x01000000 0x00 0x0d000000>, /* Most peripherals */
- <0x00 0x04210000 0x00 0x04210000 0x00 0x00010000>, /* VPU0 */
- <0x00 0x04220000 0x00 0x04220000 0x00 0x00010000>, /* VPU1 */
- <0x00 0x0d000000 0x00 0x0d000000 0x00 0x00800000>, /* PCIe0 Core*/
- <0x00 0x0d800000 0x00 0x0d800000 0x00 0x00800000>, /* PCIe1 Core*/
- <0x00 0x0e000000 0x00 0x0e000000 0x00 0x00800000>, /* PCIe2 Core*/
- <0x00 0x0e800000 0x00 0x0e800000 0x00 0x00800000>, /* PCIe3 Core*/
- <0x00 0x10000000 0x00 0x10000000 0x00 0x08000000>, /* PCIe0 DAT0 */
- <0x00 0x18000000 0x00 0x18000000 0x00 0x08000000>, /* PCIe1 DAT0 */
- <0x00 0x64800000 0x00 0x64800000 0x00 0x0070c000>, /* C71_1 */
- <0x00 0x65800000 0x00 0x65800000 0x00 0x0070c000>, /* C71_2 */
- <0x00 0x66800000 0x00 0x66800000 0x00 0x0070c000>, /* C71_3 */
- <0x00 0x67800000 0x00 0x67800000 0x00 0x0070c000>, /* C71_4 */
- <0x00 0x6f000000 0x00 0x6f000000 0x00 0x00310000>, /* A72 PERIPHBASE */
- <0x00 0x70000000 0x00 0x70000000 0x00 0x00400000>, /* MSMC RAM */
- <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>, /* MAIN NAVSS */
- <0x40 0x00000000 0x40 0x00000000 0x01 0x00000000>, /* PCIe0 DAT1 */
- <0x41 0x00000000 0x41 0x00000000 0x01 0x00000000>, /* PCIe1 DAT1 */
- <0x42 0x00000000 0x42 0x00000000 0x01 0x00000000>, /* PCIe2 DAT1 */
- <0x43 0x00000000 0x43 0x00000000 0x01 0x00000000>, /* PCIe3 DAT1 */
- <0x44 0x00000000 0x44 0x00000000 0x00 0x08000000>, /* PCIe2 DAT0 */
- <0x44 0x10000000 0x44 0x10000000 0x00 0x08000000>, /* PCIe3 DAT0 */
- <0x4e 0x20000000 0x4e 0x20000000 0x00 0x00080000>, /* GPU */
-
- /* MCUSS_WKUP Range */
- <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>,
- <0x00 0x40200000 0x00 0x40200000 0x00 0x00998400>,
- <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>,
- <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>,
- <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>,
- <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00100000>,
- <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>,
- <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>,
- <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>,
- <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>,
- <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>,
- <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>;
-
- cbass_mcu_wakeup: bus@28380000 {
- bootph-all;
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, /* MCU NAVSS*/
- <0x00 0x40200000 0x00 0x40200000 0x00 0x00998400>, /* First peripheral window */
- <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>, /* CTRL_MMR0 */
- <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>, /* MCU R5F Core0 */
- <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>, /* MCU R5F Core1 */
- <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00100000>, /* MCU SRAM */
- <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, /* WKUP peripheral window */
- <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */
- <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */
- <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, /* OSPI register space */
- <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS data region 1 */
- <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; /* FSS data region 0/3 */
- };
- };
-
- thermal_zones: thermal-zones {
- #include "k3-j784s4-thermal.dtsi"
- };
};
-/* Now include peripherals from each bus segment */
#include "k3-j784s4-main.dtsi"
-#include "k3-j784s4-mcu-wakeup.dtsi"
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts
index 86e6c4990560..bfa7ea6b9224 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts
@@ -90,20 +90,6 @@
};
};
- ams {
- compatible = "iio-hwmon";
- io-channels = <&xilinx_ams 0>, <&xilinx_ams 1>, <&xilinx_ams 2>,
- <&xilinx_ams 3>, <&xilinx_ams 4>, <&xilinx_ams 5>,
- <&xilinx_ams 6>, <&xilinx_ams 7>, <&xilinx_ams 8>,
- <&xilinx_ams 9>, <&xilinx_ams 10>, <&xilinx_ams 11>,
- <&xilinx_ams 12>, <&xilinx_ams 13>, <&xilinx_ams 14>,
- <&xilinx_ams 15>, <&xilinx_ams 16>, <&xilinx_ams 17>,
- <&xilinx_ams 18>, <&xilinx_ams 19>, <&xilinx_ams 20>,
- <&xilinx_ams 21>, <&xilinx_ams 22>, <&xilinx_ams 23>,
- <&xilinx_ams 24>, <&xilinx_ams 25>, <&xilinx_ams 26>,
- <&xilinx_ams 27>, <&xilinx_ams 28>, <&xilinx_ams 29>;
- };
-
pwm-fan {
compatible = "pwm-fan";
status = "okay";
@@ -366,10 +352,6 @@
"", "", "", ""; /* 170 - 173 */
};
-&xilinx_ams {
- status = "okay";
-};
-
&ams_ps {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
index c5945067cd57..62c2503a502a 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
@@ -590,10 +590,6 @@
status = "okay";
};
-&xilinx_ams {
- status = "okay";
-};
-
&ams_ps {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts
index d2175f3dd099..7e26489a1539 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts
@@ -1028,10 +1028,6 @@
status = "okay";
};
-&xilinx_ams {
- status = "okay";
-};
-
&ams_ps {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts
index b1eca1bb6a63..eb2090673ec1 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts
@@ -511,10 +511,6 @@
status = "okay";
};
-&xilinx_ams {
- status = "okay";
-};
-
&ams_ps {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts
index ddc74d963a05..4694d0a841f1 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts
@@ -523,10 +523,6 @@
status = "okay";
};
-&xilinx_ams {
- status = "okay";
-};
-
&ams_ps {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index b1b31dcf6291..467f084c6469 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -18,6 +18,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/xlnx-zynqmp-power.h>
#include <dt-bindings/reset/xlnx-zynqmp-resets.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
compatible = "xlnx,zynqmp";
@@ -36,6 +37,7 @@
#size-cells = <0>;
cpu0: cpu@0 {
+ #cooling-cells = <2>;
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
@@ -46,6 +48,7 @@
};
cpu1: cpu@1 {
+ #cooling-cells = <2>;
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
@@ -56,6 +59,7 @@
};
cpu2: cpu@2 {
+ #cooling-cells = <2>;
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
@@ -66,6 +70,7 @@
};
cpu3: cpu@3 {
+ #cooling-cells = <2>;
compatible = "arm,cortex-a53";
device_type = "cpu";
enable-method = "psci";
@@ -392,6 +397,101 @@
};
};
+ ams {
+ compatible = "iio-hwmon";
+ io-channels = <&xilinx_ams 0>, <&xilinx_ams 1>, <&xilinx_ams 2>,
+ <&xilinx_ams 3>, <&xilinx_ams 4>, <&xilinx_ams 5>,
+ <&xilinx_ams 6>, <&xilinx_ams 7>, <&xilinx_ams 8>,
+ <&xilinx_ams 9>, <&xilinx_ams 10>, <&xilinx_ams 11>,
+ <&xilinx_ams 12>, <&xilinx_ams 13>, <&xilinx_ams 14>,
+ <&xilinx_ams 15>, <&xilinx_ams 16>, <&xilinx_ams 17>,
+ <&xilinx_ams 18>, <&xilinx_ams 19>, <&xilinx_ams 20>,
+ <&xilinx_ams 21>, <&xilinx_ams 22>, <&xilinx_ams 23>,
+ <&xilinx_ams 24>, <&xilinx_ams 25>, <&xilinx_ams 26>,
+ <&xilinx_ams 27>, <&xilinx_ams 28>, <&xilinx_ams 29>;
+ };
+
+
+ tsens_apu: thermal-sensor-apu {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&xilinx_ams 7>;
+ io-channel-names = "sensor-channel";
+ };
+
+ tsens_rpu: thermal-sensor-rpu {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&xilinx_ams 8>;
+ io-channel-names = "sensor-channel";
+ };
+
+ tsens_pl: thermal-sensor-pl {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&xilinx_ams 20>;
+ io-channel-names = "sensor-channel";
+ };
+
+ thermal-zones {
+ apu-thermal {
+ polling-delay-passive = <1000>;
+ polling-delay = <5000>;
+ thermal-sensors = <&tsens_apu>;
+
+ trips {
+ apu_passive: passive {
+ temperature = <93000>;
+ hysteresis = <3500>;
+ type = "passive";
+ };
+
+ apu_critical: critical {
+ temperature = <96500>;
+ hysteresis = <3500>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&apu_passive>;
+ cooling-device =
+ <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ rpu-thermal {
+ polling-delay = <10000>;
+ thermal-sensors = <&tsens_rpu>;
+
+ trips {
+ critical {
+ temperature = <96500>;
+ hysteresis = <3500>;
+ type = "critical";
+ };
+ };
+ };
+
+ pl-thermal {
+ polling-delay = <10000>;
+ thermal-sensors = <&tsens_pl>;
+
+ trips {
+ critical {
+ temperature = <96500>;
+ hysteresis = <3500>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
amba: axi {
compatible = "simple-bus";
bootph-all;
@@ -1157,7 +1257,6 @@
xilinx_ams: ams@ffa50000 {
compatible = "xlnx,zynqmp-ams";
- status = "disabled";
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x0 0xffa50000 0x0 0x800>;
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5fdbfea7a5b2..c62831e61586 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -659,6 +659,7 @@ CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_ADP5585=m
+CONFIG_GPIO_PCF857X=m
CONFIG_GPIO_BD9571MWV=m
CONFIG_GPIO_MAX77620=y
CONFIG_GPIO_SL28CPLD=m
@@ -1221,6 +1222,7 @@ CONFIG_RTC_DRV_IMX_SC=m
CONFIG_RTC_DRV_MT6397=m
CONFIG_RTC_DRV_XGENE=y
CONFIG_RTC_DRV_TI_K3=m
+CONFIG_RTC_DRV_RENESAS_RTCA3=m
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=y
CONFIG_DMA_SUN6I=m
@@ -1323,6 +1325,7 @@ CONFIG_MSM_MMCC_8998=m
CONFIG_QCM_GCC_2290=y
CONFIG_QCM_DISPCC_2290=m
CONFIG_QCS_GCC_404=y
+CONFIG_SC_CAMCC_7280=m
CONFIG_QDU_GCC_1000=y
CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7280=m
@@ -1336,6 +1339,8 @@ CONFIG_SC_GCC_8280XP=y
CONFIG_SC_GPUCC_7280=m
CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_8280XP=m
+CONFIG_SC_LPASS_CORECC_7280=m
+CONFIG_SC_VIDEOCC_7280=m
CONFIG_SDM_CAMCC_845=m
CONFIG_SDM_GPUCC_845=y
CONFIG_SDM_VIDEOCC_845=y
@@ -1367,6 +1372,7 @@ CONFIG_SM_VIDEOCC_8250=y
CONFIG_QCOM_HFPLL=y
CONFIG_CLK_GFM_LPASS_SM8250=m
CONFIG_CLK_RCAR_USB2_CLOCK_SEL=y
+CONFIG_CLK_RENESAS_VBATTB=m
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_TEGRA186_TIMER=y
@@ -1472,6 +1478,7 @@ CONFIG_ARM_MEDIATEK_CCI_DEVFREQ=m
CONFIG_EXTCON_PTN5150=m
CONFIG_EXTCON_USB_GPIO=y
CONFIG_EXTCON_USBC_CROS_EC=y
+CONFIG_FSL_IFC=y
CONFIG_RENESAS_RPCIF=m
CONFIG_IIO=y
CONFIG_EXYNOS_ADC=y
diff --git a/arch/arm64/crypto/crct10dif-ce-core.S b/arch/arm64/crypto/crct10dif-ce-core.S
index 5604de61d06d..87dd6d46224d 100644
--- a/arch/arm64/crypto/crct10dif-ce-core.S
+++ b/arch/arm64/crypto/crct10dif-ce-core.S
@@ -1,8 +1,11 @@
//
// Accelerated CRC-T10DIF using arm64 NEON and Crypto Extensions instructions
//
-// Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
-// Copyright (C) 2019 Google LLC <ebiggers@google.com>
+// Copyright (C) 2016 Linaro Ltd
+// Copyright (C) 2019-2024 Google LLC
+//
+// Authors: Ard Biesheuvel <ardb@google.com>
+// Eric Biggers <ebiggers@google.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@@ -71,161 +74,117 @@
init_crc .req w0
buf .req x1
len .req x2
- fold_consts_ptr .req x3
+ fold_consts_ptr .req x5
fold_consts .req v10
- ad .req v14
-
- k00_16 .req v15
- k32_48 .req v16
-
t3 .req v17
t4 .req v18
t5 .req v19
t6 .req v20
t7 .req v21
t8 .req v22
- t9 .req v23
- perm1 .req v24
- perm2 .req v25
- perm3 .req v26
- perm4 .req v27
-
- bd1 .req v28
- bd2 .req v29
- bd3 .req v30
- bd4 .req v31
-
- .macro __pmull_init_p64
- .endm
+ perm .req v27
- .macro __pmull_pre_p64, bd
+ .macro pmull16x64_p64, a16, b64, c64
+ pmull2 \c64\().1q, \a16\().2d, \b64\().2d
+ pmull \b64\().1q, \a16\().1d, \b64\().1d
.endm
- .macro __pmull_init_p8
- // k00_16 := 0x0000000000000000_000000000000ffff
- // k32_48 := 0x00000000ffffffff_0000ffffffffffff
- movi k32_48.2d, #0xffffffff
- mov k32_48.h[2], k32_48.h[0]
- ushr k00_16.2d, k32_48.2d, #32
-
- // prepare the permutation vectors
- mov_q x5, 0x080f0e0d0c0b0a09
- movi perm4.8b, #8
- dup perm1.2d, x5
- eor perm1.16b, perm1.16b, perm4.16b
- ushr perm2.2d, perm1.2d, #8
- ushr perm3.2d, perm1.2d, #16
- ushr perm4.2d, perm1.2d, #24
- sli perm2.2d, perm1.2d, #56
- sli perm3.2d, perm1.2d, #48
- sli perm4.2d, perm1.2d, #40
+ /*
+ * Pairwise long polynomial multiplication of two 16-bit values
+ *
+ * { w0, w1 }, { y0, y1 }
+ *
+ * by two 64-bit values
+ *
+ * { x0, x1, x2, x3, x4, x5, x6, x7 }, { z0, z1, z2, z3, z4, z5, z6, z7 }
+ *
+ * where each vector element is a byte, ordered from least to most
+ * significant.
+ *
+ * This can be implemented using 8x8 long polynomial multiplication, by
+ * reorganizing the input so that each pairwise 8x8 multiplication
+ * produces one of the terms from the decomposition below, and
+ * combining the results of each rank and shifting them into place.
+ *
+ * Rank
+ * 0 w0*x0 ^ | y0*z0 ^
+ * 1 (w0*x1 ^ w1*x0) << 8 ^ | (y0*z1 ^ y1*z0) << 8 ^
+ * 2 (w0*x2 ^ w1*x1) << 16 ^ | (y0*z2 ^ y1*z1) << 16 ^
+ * 3 (w0*x3 ^ w1*x2) << 24 ^ | (y0*z3 ^ y1*z2) << 24 ^
+ * 4 (w0*x4 ^ w1*x3) << 32 ^ | (y0*z4 ^ y1*z3) << 32 ^
+ * 5 (w0*x5 ^ w1*x4) << 40 ^ | (y0*z5 ^ y1*z4) << 40 ^
+ * 6 (w0*x6 ^ w1*x5) << 48 ^ | (y0*z6 ^ y1*z5) << 48 ^
+ * 7 (w0*x7 ^ w1*x6) << 56 ^ | (y0*z7 ^ y1*z6) << 56 ^
+ * 8 w1*x7 << 64 | y1*z7 << 64
+ *
+ * The inputs can be reorganized into
+ *
+ * { w0, w0, w0, w0, y0, y0, y0, y0 }, { w1, w1, w1, w1, y1, y1, y1, y1 }
+ * { x0, x2, x4, x6, z0, z2, z4, z6 }, { x1, x3, x5, x7, z1, z3, z5, z7 }
+ *
+ * and after performing 8x8->16 bit long polynomial multiplication of
+ * each of the halves of the first vector with those of the second one,
+ * we obtain the following four vectors of 16-bit elements:
+ *
+ * a := { w0*x0, w0*x2, w0*x4, w0*x6 }, { y0*z0, y0*z2, y0*z4, y0*z6 }
+ * b := { w0*x1, w0*x3, w0*x5, w0*x7 }, { y0*z1, y0*z3, y0*z5, y0*z7 }
+ * c := { w1*x0, w1*x2, w1*x4, w1*x6 }, { y1*z0, y1*z2, y1*z4, y1*z6 }
+ * d := { w1*x1, w1*x3, w1*x5, w1*x7 }, { y1*z1, y1*z3, y1*z5, y1*z7 }
+ *
+ * Results b and c can be XORed together, as the vector elements have
+ * matching ranks. Then, the final XOR (*) can be pulled forward, and
+ * applied between the halves of each of the remaining three vectors,
+ * which are then shifted into place, and combined to produce two
+ * 80-bit results.
+ *
+ * (*) NOTE: the 16x64 bit polynomial multiply below is not equivalent
+ * to the 64x64 bit one above, but XOR'ing the outputs together will
+ * produce the expected result, and this is sufficient in the context of
+ * this algorithm.
+ */
+ .macro pmull16x64_p8, a16, b64, c64
+ ext t7.16b, \b64\().16b, \b64\().16b, #1
+ tbl t5.16b, {\a16\().16b}, perm.16b
+ uzp1 t7.16b, \b64\().16b, t7.16b
+ bl __pmull_p8_16x64
+ ext \b64\().16b, t4.16b, t4.16b, #15
+ eor \c64\().16b, t8.16b, t5.16b
.endm
- .macro __pmull_pre_p8, bd
- tbl bd1.16b, {\bd\().16b}, perm1.16b
- tbl bd2.16b, {\bd\().16b}, perm2.16b
- tbl bd3.16b, {\bd\().16b}, perm3.16b
- tbl bd4.16b, {\bd\().16b}, perm4.16b
- .endm
-
-SYM_FUNC_START_LOCAL(__pmull_p8_core)
-.L__pmull_p8_core:
- ext t4.8b, ad.8b, ad.8b, #1 // A1
- ext t5.8b, ad.8b, ad.8b, #2 // A2
- ext t6.8b, ad.8b, ad.8b, #3 // A3
-
- pmull t4.8h, t4.8b, fold_consts.8b // F = A1*B
- pmull t8.8h, ad.8b, bd1.8b // E = A*B1
- pmull t5.8h, t5.8b, fold_consts.8b // H = A2*B
- pmull t7.8h, ad.8b, bd2.8b // G = A*B2
- pmull t6.8h, t6.8b, fold_consts.8b // J = A3*B
- pmull t9.8h, ad.8b, bd3.8b // I = A*B3
- pmull t3.8h, ad.8b, bd4.8b // K = A*B4
- b 0f
-
-.L__pmull_p8_core2:
- tbl t4.16b, {ad.16b}, perm1.16b // A1
- tbl t5.16b, {ad.16b}, perm2.16b // A2
- tbl t6.16b, {ad.16b}, perm3.16b // A3
-
- pmull2 t4.8h, t4.16b, fold_consts.16b // F = A1*B
- pmull2 t8.8h, ad.16b, bd1.16b // E = A*B1
- pmull2 t5.8h, t5.16b, fold_consts.16b // H = A2*B
- pmull2 t7.8h, ad.16b, bd2.16b // G = A*B2
- pmull2 t6.8h, t6.16b, fold_consts.16b // J = A3*B
- pmull2 t9.8h, ad.16b, bd3.16b // I = A*B3
- pmull2 t3.8h, ad.16b, bd4.16b // K = A*B4
-
-0: eor t4.16b, t4.16b, t8.16b // L = E + F
- eor t5.16b, t5.16b, t7.16b // M = G + H
- eor t6.16b, t6.16b, t9.16b // N = I + J
-
- uzp1 t8.2d, t4.2d, t5.2d
- uzp2 t4.2d, t4.2d, t5.2d
- uzp1 t7.2d, t6.2d, t3.2d
- uzp2 t6.2d, t6.2d, t3.2d
-
- // t4 = (L) (P0 + P1) << 8
- // t5 = (M) (P2 + P3) << 16
- eor t8.16b, t8.16b, t4.16b
- and t4.16b, t4.16b, k32_48.16b
-
- // t6 = (N) (P4 + P5) << 24
- // t7 = (K) (P6 + P7) << 32
- eor t7.16b, t7.16b, t6.16b
- and t6.16b, t6.16b, k00_16.16b
-
- eor t8.16b, t8.16b, t4.16b
- eor t7.16b, t7.16b, t6.16b
-
- zip2 t5.2d, t8.2d, t4.2d
- zip1 t4.2d, t8.2d, t4.2d
- zip2 t3.2d, t7.2d, t6.2d
- zip1 t6.2d, t7.2d, t6.2d
-
- ext t4.16b, t4.16b, t4.16b, #15
+SYM_FUNC_START_LOCAL(__pmull_p8_16x64)
+ ext t6.16b, t5.16b, t5.16b, #8
+
+ pmull t3.8h, t7.8b, t5.8b
+ pmull t4.8h, t7.8b, t6.8b
+ pmull2 t5.8h, t7.16b, t5.16b
+ pmull2 t6.8h, t7.16b, t6.16b
+
+ ext t8.16b, t3.16b, t3.16b, #8
+ eor t4.16b, t4.16b, t6.16b
+ ext t7.16b, t5.16b, t5.16b, #8
+ ext t6.16b, t4.16b, t4.16b, #8
+ eor t8.8b, t8.8b, t3.8b
+ eor t5.8b, t5.8b, t7.8b
+ eor t4.8b, t4.8b, t6.8b
ext t5.16b, t5.16b, t5.16b, #14
- ext t6.16b, t6.16b, t6.16b, #13
- ext t3.16b, t3.16b, t3.16b, #12
-
- eor t4.16b, t4.16b, t5.16b
- eor t6.16b, t6.16b, t3.16b
ret
-SYM_FUNC_END(__pmull_p8_core)
+SYM_FUNC_END(__pmull_p8_16x64)
- .macro __pmull_p8, rq, ad, bd, i
- .ifnc \bd, fold_consts
- .err
- .endif
- mov ad.16b, \ad\().16b
- .ifb \i
- pmull \rq\().8h, \ad\().8b, \bd\().8b // D = A*B
- .else
- pmull2 \rq\().8h, \ad\().16b, \bd\().16b // D = A*B
- .endif
-
- bl .L__pmull_p8_core\i
-
- eor \rq\().16b, \rq\().16b, t4.16b
- eor \rq\().16b, \rq\().16b, t6.16b
- .endm
// Fold reg1, reg2 into the next 32 data bytes, storing the result back
// into reg1, reg2.
.macro fold_32_bytes, p, reg1, reg2
ldp q11, q12, [buf], #0x20
- __pmull_\p v8, \reg1, fold_consts, 2
- __pmull_\p \reg1, \reg1, fold_consts
+ pmull16x64_\p fold_consts, \reg1, v8
CPU_LE( rev64 v11.16b, v11.16b )
CPU_LE( rev64 v12.16b, v12.16b )
- __pmull_\p v9, \reg2, fold_consts, 2
- __pmull_\p \reg2, \reg2, fold_consts
+ pmull16x64_\p fold_consts, \reg2, v9
CPU_LE( ext v11.16b, v11.16b, v11.16b, #8 )
CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 )
@@ -238,26 +197,15 @@ CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 )
// Fold src_reg into dst_reg, optionally loading the next fold constants
.macro fold_16_bytes, p, src_reg, dst_reg, load_next_consts
- __pmull_\p v8, \src_reg, fold_consts
- __pmull_\p \src_reg, \src_reg, fold_consts, 2
+ pmull16x64_\p fold_consts, \src_reg, v8
.ifnb \load_next_consts
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
- __pmull_pre_\p fold_consts
.endif
eor \dst_reg\().16b, \dst_reg\().16b, v8.16b
eor \dst_reg\().16b, \dst_reg\().16b, \src_reg\().16b
.endm
- .macro __pmull_p64, rd, rn, rm, n
- .ifb \n
- pmull \rd\().1q, \rn\().1d, \rm\().1d
- .else
- pmull2 \rd\().1q, \rn\().2d, \rm\().2d
- .endif
- .endm
-
.macro crc_t10dif_pmull, p
- __pmull_init_\p
// For sizes less than 256 bytes, we can't fold 128 bytes at a time.
cmp len, #256
@@ -296,7 +244,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
// Load the constants for folding across 128 bytes.
ld1 {fold_consts.2d}, [fold_consts_ptr]
- __pmull_pre_\p fold_consts
// Subtract 128 for the 128 data bytes just consumed. Subtract another
// 128 to simplify the termination condition of the following loop.
@@ -318,7 +265,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
// Fold across 64 bytes.
add fold_consts_ptr, fold_consts_ptr, #16
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
- __pmull_pre_\p fold_consts
fold_16_bytes \p, v0, v4
fold_16_bytes \p, v1, v5
fold_16_bytes \p, v2, v6
@@ -339,8 +285,7 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
// into them, storing the result back into v7.
b.lt .Lfold_16_bytes_loop_done_\@
.Lfold_16_bytes_loop_\@:
- __pmull_\p v8, v7, fold_consts
- __pmull_\p v7, v7, fold_consts, 2
+ pmull16x64_\p fold_consts, v7, v8
eor v7.16b, v7.16b, v8.16b
ldr q0, [buf], #16
CPU_LE( rev64 v0.16b, v0.16b )
@@ -387,51 +332,10 @@ CPU_LE( ext v0.16b, v0.16b, v0.16b, #8 )
bsl v2.16b, v1.16b, v0.16b
// Fold the first chunk into the second chunk, storing the result in v7.
- __pmull_\p v0, v3, fold_consts
- __pmull_\p v7, v3, fold_consts, 2
- eor v7.16b, v7.16b, v0.16b
+ pmull16x64_\p fold_consts, v3, v0
+ eor v7.16b, v3.16b, v0.16b
eor v7.16b, v7.16b, v2.16b
-
-.Lreduce_final_16_bytes_\@:
- // Reduce the 128-bit value M(x), stored in v7, to the final 16-bit CRC.
-
- movi v2.16b, #0 // init zero register
-
- // Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
- ld1 {fold_consts.2d}, [fold_consts_ptr], #16
- __pmull_pre_\p fold_consts
-
- // Fold the high 64 bits into the low 64 bits, while also multiplying by
- // x^64. This produces a 128-bit value congruent to x^64 * M(x) and
- // whose low 48 bits are 0.
- ext v0.16b, v2.16b, v7.16b, #8
- __pmull_\p v7, v7, fold_consts, 2 // high bits * x^48 * (x^80 mod G(x))
- eor v0.16b, v0.16b, v7.16b // + low bits * x^64
-
- // Fold the high 32 bits into the low 96 bits. This produces a 96-bit
- // value congruent to x^64 * M(x) and whose low 48 bits are 0.
- ext v1.16b, v0.16b, v2.16b, #12 // extract high 32 bits
- mov v0.s[3], v2.s[0] // zero high 32 bits
- __pmull_\p v1, v1, fold_consts // high 32 bits * x^48 * (x^48 mod G(x))
- eor v0.16b, v0.16b, v1.16b // + low bits
-
- // Load G(x) and floor(x^48 / G(x)).
- ld1 {fold_consts.2d}, [fold_consts_ptr]
- __pmull_pre_\p fold_consts
-
- // Use Barrett reduction to compute the final CRC value.
- __pmull_\p v1, v0, fold_consts, 2 // high 32 bits * floor(x^48 / G(x))
- ushr v1.2d, v1.2d, #32 // /= x^32
- __pmull_\p v1, v1, fold_consts // *= G(x)
- ushr v0.2d, v0.2d, #48
- eor v0.16b, v0.16b, v1.16b // + low 16 nonzero bits
- // Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of v0.
-
- umov w0, v0.h[0]
- .ifc \p, p8
- frame_pop
- .endif
- ret
+ b .Lreduce_final_16_bytes_\@
.Lless_than_256_bytes_\@:
// Checksumming a buffer of length 16...255 bytes
@@ -450,7 +354,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
// Load the fold-across-16-bytes constants.
ld1 {fold_consts.2d}, [fold_consts_ptr], #16
- __pmull_pre_\p fold_consts
cmp len, #16
b.eq .Lreduce_final_16_bytes_\@ // len == 16
@@ -458,6 +361,8 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
b.ge .Lfold_16_bytes_loop_\@ // 32 <= len <= 255
add len, len, #16
b .Lhandle_partial_segment_\@ // 17 <= len <= 31
+
+.Lreduce_final_16_bytes_\@:
.endm
//
@@ -467,7 +372,22 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
//
SYM_FUNC_START(crc_t10dif_pmull_p8)
frame_push 1
+
+ // Compose { 0,0,0,0, 8,8,8,8, 1,1,1,1, 9,9,9,9 }
+ movi perm.4h, #8, lsl #8
+ orr perm.2s, #1, lsl #16
+ orr perm.2s, #1, lsl #24
+ zip1 perm.16b, perm.16b, perm.16b
+ zip1 perm.16b, perm.16b, perm.16b
+
crc_t10dif_pmull p8
+
+CPU_LE( rev64 v7.16b, v7.16b )
+CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
+ str q7, [x3]
+
+ frame_pop
+ ret
SYM_FUNC_END(crc_t10dif_pmull_p8)
.align 5
@@ -478,6 +398,41 @@ SYM_FUNC_END(crc_t10dif_pmull_p8)
//
SYM_FUNC_START(crc_t10dif_pmull_p64)
crc_t10dif_pmull p64
+
+ // Reduce the 128-bit value M(x), stored in v7, to the final 16-bit CRC.
+
+ movi v2.16b, #0 // init zero register
+
+ // Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'.
+ ld1 {fold_consts.2d}, [fold_consts_ptr], #16
+
+ // Fold the high 64 bits into the low 64 bits, while also multiplying by
+ // x^64. This produces a 128-bit value congruent to x^64 * M(x) and
+ // whose low 48 bits are 0.
+ ext v0.16b, v2.16b, v7.16b, #8
+ pmull2 v7.1q, v7.2d, fold_consts.2d // high bits * x^48 * (x^80 mod G(x))
+ eor v0.16b, v0.16b, v7.16b // + low bits * x^64
+
+ // Fold the high 32 bits into the low 96 bits. This produces a 96-bit
+ // value congruent to x^64 * M(x) and whose low 48 bits are 0.
+ ext v1.16b, v0.16b, v2.16b, #12 // extract high 32 bits
+ mov v0.s[3], v2.s[0] // zero high 32 bits
+ pmull v1.1q, v1.1d, fold_consts.1d // high 32 bits * x^48 * (x^48 mod G(x))
+ eor v0.16b, v0.16b, v1.16b // + low bits
+
+ // Load G(x) and floor(x^48 / G(x)).
+ ld1 {fold_consts.2d}, [fold_consts_ptr]
+
+ // Use Barrett reduction to compute the final CRC value.
+ pmull2 v1.1q, v0.2d, fold_consts.2d // high 32 bits * floor(x^48 / G(x))
+ ushr v1.2d, v1.2d, #32 // /= x^32
+ pmull v1.1q, v1.1d, fold_consts.1d // *= G(x)
+ ushr v0.2d, v0.2d, #48
+ eor v0.16b, v0.16b, v1.16b // + low 16 nonzero bits
+ // Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of v0.
+
+ umov w0, v0.h[0]
+ ret
SYM_FUNC_END(crc_t10dif_pmull_p64)
.section ".rodata", "a"
diff --git a/arch/arm64/crypto/crct10dif-ce-glue.c b/arch/arm64/crypto/crct10dif-ce-glue.c
index 606d25c559ed..08bcbd884395 100644
--- a/arch/arm64/crypto/crct10dif-ce-glue.c
+++ b/arch/arm64/crypto/crct10dif-ce-glue.c
@@ -20,7 +20,8 @@
#define CRC_T10DIF_PMULL_CHUNK_SIZE 16U
-asmlinkage u16 crc_t10dif_pmull_p8(u16 init_crc, const u8 *buf, size_t len);
+asmlinkage void crc_t10dif_pmull_p8(u16 init_crc, const u8 *buf, size_t len,
+ u8 out[16]);
asmlinkage u16 crc_t10dif_pmull_p64(u16 init_crc, const u8 *buf, size_t len);
static int crct10dif_init(struct shash_desc *desc)
@@ -34,25 +35,21 @@ static int crct10dif_init(struct shash_desc *desc)
static int crct10dif_update_pmull_p8(struct shash_desc *desc, const u8 *data,
unsigned int length)
{
- u16 *crc = shash_desc_ctx(desc);
-
- if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
- do {
- unsigned int chunk = length;
-
- if (chunk > SZ_4K + CRC_T10DIF_PMULL_CHUNK_SIZE)
- chunk = SZ_4K;
-
- kernel_neon_begin();
- *crc = crc_t10dif_pmull_p8(*crc, data, chunk);
- kernel_neon_end();
- data += chunk;
- length -= chunk;
- } while (length);
- } else {
- *crc = crc_t10dif_generic(*crc, data, length);
+ u16 *crcp = shash_desc_ctx(desc);
+ u16 crc = *crcp;
+ u8 buf[16];
+
+ if (length > CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
+ kernel_neon_begin();
+ crc_t10dif_pmull_p8(crc, data, length, buf);
+ kernel_neon_end();
+
+ crc = 0;
+ data = buf;
+ length = sizeof(buf);
}
+ *crcp = crc_t10dif_generic(crc, data, length);
return 0;
}
@@ -62,18 +59,9 @@ static int crct10dif_update_pmull_p64(struct shash_desc *desc, const u8 *data,
u16 *crc = shash_desc_ctx(desc);
if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
- do {
- unsigned int chunk = length;
-
- if (chunk > SZ_4K + CRC_T10DIF_PMULL_CHUNK_SIZE)
- chunk = SZ_4K;
-
- kernel_neon_begin();
- *crc = crc_t10dif_pmull_p64(*crc, data, chunk);
- kernel_neon_end();
- data += chunk;
- length -= chunk;
- } while (length);
+ kernel_neon_begin();
+ *crc = crc_t10dif_pmull_p64(*crc, data, length);
+ kernel_neon_end();
} else {
*crc = crc_t10dif_generic(*crc, data, length);
}
diff --git a/arch/arm64/include/asm/arm_pmuv3.h b/arch/arm64/include/asm/arm_pmuv3.h
index 468a049bc63b..8a777dec8d88 100644
--- a/arch/arm64/include/asm/arm_pmuv3.h
+++ b/arch/arm64/include/asm/arm_pmuv3.h
@@ -152,6 +152,11 @@ static inline void write_pmuserenr(u32 val)
write_sysreg(val, pmuserenr_el0);
}
+static inline void write_pmuacr(u64 val)
+{
+ write_sysreg_s(val, SYS_PMUACR_EL1);
+}
+
static inline u64 read_pmceid0(void)
{
return read_sysreg(pmceid0_el0);
@@ -178,4 +183,9 @@ static inline bool is_pmuv3p5(int pmuver)
return pmuver >= ID_AA64DFR0_EL1_PMUVer_V3P5;
}
+static inline bool is_pmuv3p9(int pmuver)
+{
+ return pmuver >= ID_AA64DFR0_EL1_PMUVer_V3P9;
+}
+
#endif
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index bc0b0d75acef..3d8d534a7a77 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -249,13 +249,6 @@ alternative_endif
.endm
/*
- * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
- */
- .macro vma_vm_mm, rd, rn
- ldr \rd, [\rn, #VMA_VM_MM]
- .endm
-
-/*
* read_ctr - read CTR_EL0. If the system has mismatched register fields,
* provide the system wide safe value from arm64_ftr_reg_ctrel0.sys_val
*/
diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
index 9b73fd0cd721..81e4157f92b7 100644
--- a/arch/arm64/include/asm/cpu.h
+++ b/arch/arm64/include/asm/cpu.h
@@ -46,6 +46,7 @@ struct cpuinfo_arm64 {
u64 reg_revidr;
u64 reg_gmid;
u64 reg_smidr;
+ u64 reg_mpamidr;
u64 reg_id_aa64dfr0;
u64 reg_id_aa64dfr1;
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index a6e5b07b64fd..201a46efd918 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -42,6 +42,8 @@ cpucap_is_possible(const unsigned int cap)
return IS_ENABLED(CONFIG_ARM64_BTI);
case ARM64_HAS_TLB_RANGE:
return IS_ENABLED(CONFIG_ARM64_TLB_RANGE);
+ case ARM64_HAS_S1POE:
+ return IS_ENABLED(CONFIG_ARM64_POE);
case ARM64_UNMAP_KERNEL_AT_EL0:
return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0);
case ARM64_WORKAROUND_843419:
@@ -60,6 +62,11 @@ cpucap_is_possible(const unsigned int cap)
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
case ARM64_WORKAROUND_SPECULATIVE_SSBS:
return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
+ case ARM64_MPAM:
+ /*
+ * KVM MPAM support doesn't rely on the host kernel supporting MPAM.
+ */
+ return true;
}
return true;
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 3d261cc123c1..b64e49bd9d10 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -12,7 +12,7 @@
#include <asm/hwcap.h>
#include <asm/sysreg.h>
-#define MAX_CPU_FEATURES 128
+#define MAX_CPU_FEATURES 192
#define cpu_feature(x) KERNEL_HWCAP_ ## x
#define ARM64_SW_FEATURE_OVERRIDE_NOKASLR 0
@@ -438,6 +438,7 @@ void cpu_set_feature(unsigned int num);
bool cpu_have_feature(unsigned int num);
unsigned long cpu_get_elf_hwcap(void);
unsigned long cpu_get_elf_hwcap2(void);
+unsigned long cpu_get_elf_hwcap3(void);
#define cpu_set_named_feature(name) cpu_set_feature(cpu_feature(name))
#define cpu_have_named_feature(name) cpu_have_feature(cpu_feature(name))
@@ -612,6 +613,13 @@ static inline bool id_aa64pfr1_sme(u64 pfr1)
return val > 0;
}
+static inline bool id_aa64pfr0_mpam(u64 pfr0)
+{
+ u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT);
+
+ return val > 0;
+}
+
static inline bool id_aa64pfr1_mte(u64 pfr1)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr1, ID_AA64PFR1_EL1_MTE_SHIFT);
@@ -834,8 +842,29 @@ static inline bool system_supports_lpa2(void)
static inline bool system_supports_poe(void)
{
- return IS_ENABLED(CONFIG_ARM64_POE) &&
- alternative_has_cap_unlikely(ARM64_HAS_S1POE);
+ return alternative_has_cap_unlikely(ARM64_HAS_S1POE);
+}
+
+static inline bool system_supports_gcs(void)
+{
+ return IS_ENABLED(CONFIG_ARM64_GCS) &&
+ alternative_has_cap_unlikely(ARM64_HAS_GCS);
+}
+
+static inline bool system_supports_haft(void)
+{
+ return IS_ENABLED(CONFIG_ARM64_HAFT) &&
+ cpus_have_final_cap(ARM64_HAFT);
+}
+
+static __always_inline bool system_supports_mpam(void)
+{
+ return alternative_has_cap_unlikely(ARM64_MPAM);
+}
+
+static __always_inline bool system_supports_mpam_hcr(void)
+{
+ return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
}
int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h
index 55f57dfa8e2f..fbb5c99eb2f9 100644
--- a/arch/arm64/include/asm/daifflags.h
+++ b/arch/arm64/include/asm/daifflags.h
@@ -132,7 +132,7 @@ static inline void local_daif_inherit(struct pt_regs *regs)
trace_hardirqs_on();
if (system_uses_irq_prio_masking())
- gic_write_pmr(regs->pmr_save);
+ gic_write_pmr(regs->pmr);
/*
* We can't use local_daif_restore(regs->pstate) here as
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
index 13d437bcbf58..8f6ba31b8658 100644
--- a/arch/arm64/include/asm/debug-monitors.h
+++ b/arch/arm64/include/asm/debug-monitors.h
@@ -105,6 +105,7 @@ void kernel_enable_single_step(struct pt_regs *regs);
void kernel_disable_single_step(void);
int kernel_active_single_step(void);
void kernel_rewind_single_step(struct pt_regs *regs);
+void kernel_fastforward_single_step(struct pt_regs *regs);
#ifdef CONFIG_HAVE_HW_BREAKPOINT
int reinstall_suspended_bps(struct pt_regs *regs);
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
index e0ffdf13a18b..85ef966c08cd 100644
--- a/arch/arm64/include/asm/el2_setup.h
+++ b/arch/arm64/include/asm/el2_setup.h
@@ -27,6 +27,14 @@
ubfx x0, x0, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4
cbz x0, .Lskip_hcrx_\@
mov_q x0, HCRX_HOST_FLAGS
+
+ /* Enable GCS if supported */
+ mrs_s x1, SYS_ID_AA64PFR1_EL1
+ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4
+ cbz x1, .Lset_hcrx_\@
+ orr x0, x0, #HCRX_EL2_GCSEn
+
+.Lset_hcrx_\@:
msr_s SYS_HCRX_EL2, x0
.Lskip_hcrx_\@:
.endm
@@ -200,6 +208,16 @@
orr x0, x0, #HFGxTR_EL2_nPOR_EL0
.Lskip_poe_fgt_\@:
+ /* GCS depends on PIE so we don't check it if PIE is absent */
+ mrs_s x1, SYS_ID_AA64PFR1_EL1
+ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4
+ cbz x1, .Lset_fgt_\@
+
+ /* Disable traps of access to GCS registers at EL0 and EL1 */
+ orr x0, x0, #HFGxTR_EL2_nGCS_EL1_MASK
+ orr x0, x0, #HFGxTR_EL2_nGCS_EL0_MASK
+
+.Lset_fgt_\@:
msr_s SYS_HFGRTR_EL2, x0
msr_s SYS_HFGWTR_EL2, x0
msr_s SYS_HFGITR_EL2, xzr
@@ -215,11 +233,35 @@
.Lskip_fgt_\@:
.endm
+.macro __init_el2_gcs
+ mrs_s x1, SYS_ID_AA64PFR1_EL1
+ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4
+ cbz x1, .Lskip_gcs_\@
+
+ /* Ensure GCS is not enabled when we start trying to do BLs */
+ msr_s SYS_GCSCR_EL1, xzr
+ msr_s SYS_GCSCRE0_EL1, xzr
+.Lskip_gcs_\@:
+.endm
+
.macro __init_el2_nvhe_prepare_eret
mov x0, #INIT_PSTATE_EL1
msr spsr_el2, x0
.endm
+.macro __init_el2_mpam
+ /* Memory Partitioning And Monitoring: disable EL2 traps */
+ mrs x1, id_aa64pfr0_el1
+ ubfx x0, x1, #ID_AA64PFR0_EL1_MPAM_SHIFT, #4
+ cbz x0, .Lskip_mpam_\@ // skip if no MPAM
+ msr_s SYS_MPAM2_EL2, xzr // use the default partition
+ // and disable lower traps
+ mrs_s x0, SYS_MPAMIDR_EL1
+ tbz x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@ // skip if no MPAMHCR reg
+ msr_s SYS_MPAMHCR_EL2, xzr // clear TRAP_MPAMIDR_EL1 -> EL2
+.Lskip_mpam_\@:
+.endm
+
/**
* Initialize EL2 registers to sane values. This should be called early on all
* cores that were booted in EL2. Note that everything gets initialised as
@@ -237,9 +279,11 @@
__init_el2_stage2
__init_el2_gicv3
__init_el2_hstr
+ __init_el2_mpam
__init_el2_nvhe_idregs
__init_el2_cptr
__init_el2_fgt
+ __init_el2_gcs
.endm
#ifndef __KVM_NVHE_HYPERVISOR__
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index da6d2c1c0b03..d1b1a33f9a8b 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -51,7 +51,8 @@
#define ESR_ELx_EC_FP_EXC32 UL(0x28)
/* Unallocated EC: 0x29 - 0x2B */
#define ESR_ELx_EC_FP_EXC64 UL(0x2C)
-/* Unallocated EC: 0x2D - 0x2E */
+#define ESR_ELx_EC_GCS UL(0x2D)
+/* Unallocated EC: 0x2E */
#define ESR_ELx_EC_SERROR UL(0x2F)
#define ESR_ELx_EC_BREAKPT_LOW UL(0x30)
#define ESR_ELx_EC_BREAKPT_CUR UL(0x31)
@@ -386,6 +387,31 @@
#define ESR_ELx_MOPS_ISS_SRCREG(esr) (((esr) & (UL(0x1f) << 5)) >> 5)
#define ESR_ELx_MOPS_ISS_SIZEREG(esr) (((esr) & (UL(0x1f) << 0)) >> 0)
+/* ISS field definitions for GCS */
+#define ESR_ELx_ExType_SHIFT (20)
+#define ESR_ELx_ExType_MASK GENMASK(23, 20)
+#define ESR_ELx_Raddr_SHIFT (10)
+#define ESR_ELx_Raddr_MASK GENMASK(14, 10)
+#define ESR_ELx_Rn_SHIFT (5)
+#define ESR_ELx_Rn_MASK GENMASK(9, 5)
+#define ESR_ELx_Rvalue_SHIFT 5
+#define ESR_ELx_Rvalue_MASK GENMASK(9, 5)
+#define ESR_ELx_IT_SHIFT (0)
+#define ESR_ELx_IT_MASK GENMASK(4, 0)
+
+#define ESR_ELx_ExType_DATA_CHECK 0
+#define ESR_ELx_ExType_EXLOCK 1
+#define ESR_ELx_ExType_STR 2
+
+#define ESR_ELx_IT_RET 0
+#define ESR_ELx_IT_GCSPOPM 1
+#define ESR_ELx_IT_RET_KEYA 2
+#define ESR_ELx_IT_RET_KEYB 3
+#define ESR_ELx_IT_GCSSS1 4
+#define ESR_ELx_IT_GCSSS2 5
+#define ESR_ELx_IT_GCSPOPCX 6
+#define ESR_ELx_IT_GCSPOPX 7
+
#ifndef __ASSEMBLY__
#include <asm/types.h>
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index f296662590c7..d48fc16584cd 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -57,6 +57,8 @@ 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_el0_gcs(struct pt_regs *regs, unsigned long esr);
+void do_el1_gcs(struct pt_regs *regs, unsigned long esr);
void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
struct pt_regs *regs);
void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);
@@ -73,6 +75,7 @@ void do_el0_svc_compat(struct pt_regs *regs);
void do_el0_fpac(struct pt_regs *regs, unsigned long esr);
void do_el1_fpac(struct pt_regs *regs, unsigned long esr);
void do_el0_mops(struct pt_regs *regs, unsigned long esr);
+void do_el1_mops(struct pt_regs *regs, unsigned long esr);
void do_serror(struct pt_regs *regs, unsigned long esr);
void do_signal(struct pt_regs *regs);
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index dc9cf0bd2a4c..5ccff4de7f09 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -54,8 +54,11 @@ extern void return_to_handler(void);
unsigned long ftrace_call_adjust(unsigned long addr);
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
+#define HAVE_ARCH_FTRACE_REGS
struct dyn_ftrace;
struct ftrace_ops;
+struct ftrace_regs;
+#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
#define arch_ftrace_get_regs(regs) NULL
@@ -63,7 +66,7 @@ struct ftrace_ops;
* Note: sizeof(struct ftrace_regs) must be a multiple of 16 to ensure correct
* stack alignment
*/
-struct ftrace_regs {
+struct __arch_ftrace_regs {
/* x0 - x8 */
unsigned long regs[9];
@@ -83,47 +86,47 @@ struct ftrace_regs {
static __always_inline unsigned long
ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
{
- return fregs->pc;
+ return arch_ftrace_regs(fregs)->pc;
}
static __always_inline void
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
unsigned long pc)
{
- fregs->pc = pc;
+ arch_ftrace_regs(fregs)->pc = pc;
}
static __always_inline unsigned long
ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs)
{
- return fregs->sp;
+ return arch_ftrace_regs(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 arch_ftrace_regs(fregs)->regs[n];
return 0;
}
static __always_inline unsigned long
ftrace_regs_get_return_value(const struct ftrace_regs *fregs)
{
- return fregs->regs[0];
+ return arch_ftrace_regs(fregs)->regs[0];
}
static __always_inline void
ftrace_regs_set_return_value(struct ftrace_regs *fregs,
unsigned long ret)
{
- fregs->regs[0] = ret;
+ arch_ftrace_regs(fregs)->regs[0] = ret;
}
static __always_inline void
ftrace_override_function_with_return(struct ftrace_regs *fregs)
{
- fregs->pc = fregs->lr;
+ arch_ftrace_regs(fregs)->pc = arch_ftrace_regs(fregs)->lr;
}
int ftrace_regs_query_register_offset(const char *name);
@@ -143,7 +146,7 @@ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs,
* The ftrace trampoline will return to this address instead of the
* instrumented function.
*/
- fregs->direct_tramp = addr;
+ arch_ftrace_regs(fregs)->direct_tramp = addr;
}
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h
new file mode 100644
index 000000000000..f50660603ecf
--- /dev/null
+++ b/arch/arm64/include/asm/gcs.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 ARM Ltd.
+ */
+#ifndef __ASM_GCS_H
+#define __ASM_GCS_H
+
+#include <asm/types.h>
+#include <asm/uaccess.h>
+
+struct kernel_clone_args;
+struct ksignal;
+
+static inline void gcsb_dsync(void)
+{
+ asm volatile(".inst 0xd503227f" : : : "memory");
+}
+
+static inline void gcsstr(u64 *addr, u64 val)
+{
+ register u64 *_addr __asm__ ("x0") = addr;
+ register long _val __asm__ ("x1") = val;
+
+ /* GCSSTTR x1, x0 */
+ asm volatile(
+ ".inst 0xd91f1c01\n"
+ :
+ : "rZ" (_val), "r" (_addr)
+ : "memory");
+}
+
+static inline void gcsss1(u64 Xt)
+{
+ asm volatile (
+ "sys #3, C7, C7, #2, %0\n"
+ :
+ : "rZ" (Xt)
+ : "memory");
+}
+
+static inline u64 gcsss2(void)
+{
+ u64 Xt;
+
+ asm volatile(
+ "SYSL %0, #3, C7, C7, #3\n"
+ : "=r" (Xt)
+ :
+ : "memory");
+
+ return Xt;
+}
+
+#define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK \
+ (PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE | PR_SHADOW_STACK_PUSH)
+
+#ifdef CONFIG_ARM64_GCS
+
+static inline bool task_gcs_el0_enabled(struct task_struct *task)
+{
+ return current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE;
+}
+
+void gcs_set_el0_mode(struct task_struct *task);
+void gcs_free(struct task_struct *task);
+void gcs_preserve_current_state(void);
+unsigned long gcs_alloc_thread_stack(struct task_struct *tsk,
+ const struct kernel_clone_args *args);
+
+static inline int gcs_check_locked(struct task_struct *task,
+ unsigned long new_val)
+{
+ unsigned long cur_val = task->thread.gcs_el0_mode;
+
+ cur_val &= task->thread.gcs_el0_locked;
+ new_val &= task->thread.gcs_el0_locked;
+
+ if (cur_val != new_val)
+ return -EBUSY;
+
+ return 0;
+}
+
+#else
+
+static inline bool task_gcs_el0_enabled(struct task_struct *task)
+{
+ return false;
+}
+
+static inline void gcs_set_el0_mode(struct task_struct *task) { }
+static inline void gcs_free(struct task_struct *task) { }
+static inline void gcs_preserve_current_state(void) { }
+static inline unsigned long gcs_alloc_thread_stack(struct task_struct *tsk,
+ const struct kernel_clone_args *args)
+{
+ return -ENOTSUPP;
+}
+static inline int gcs_check_locked(struct task_struct *task,
+ unsigned long new_val)
+{
+ return 0;
+}
+
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 293f880865e8..c6dff3e69539 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -11,6 +11,7 @@
#define __ASM_HUGETLB_H
#include <asm/cacheflush.h>
+#include <asm/mte.h>
#include <asm/page.h>
#ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
@@ -21,6 +22,13 @@ extern bool arch_hugetlb_migration_supported(struct hstate *h);
static inline void arch_clear_hugetlb_flags(struct folio *folio)
{
clear_bit(PG_dcache_clean, &folio->flags);
+
+#ifdef CONFIG_ARM64_MTE
+ if (system_supports_mte()) {
+ clear_bit(PG_mte_tagged, &folio->flags);
+ clear_bit(PG_mte_lock, &folio->flags);
+ }
+#endif
}
#define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index a775adddecf2..2b6c61c608e2 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -92,6 +92,7 @@
#define KERNEL_HWCAP_SB __khwcap_feature(SB)
#define KERNEL_HWCAP_PACA __khwcap_feature(PACA)
#define KERNEL_HWCAP_PACG __khwcap_feature(PACG)
+#define KERNEL_HWCAP_GCS __khwcap_feature(GCS)
#define __khwcap2_feature(x) (const_ilog2(HWCAP2_ ## x) + 64)
#define KERNEL_HWCAP_DCPODP __khwcap2_feature(DCPODP)
@@ -159,17 +160,21 @@
#define KERNEL_HWCAP_SME_SF8DP2 __khwcap2_feature(SME_SF8DP2)
#define KERNEL_HWCAP_POE __khwcap2_feature(POE)
+#define __khwcap3_feature(x) (const_ilog2(HWCAP3_ ## x) + 128)
+
/*
* This yields a mask that user programs can use to figure out what
* instruction set this cpu supports.
*/
#define ELF_HWCAP cpu_get_elf_hwcap()
#define ELF_HWCAP2 cpu_get_elf_hwcap2()
+#define ELF_HWCAP3 cpu_get_elf_hwcap3()
#ifdef CONFIG_COMPAT
#define COMPAT_ELF_HWCAP (compat_elf_hwcap)
#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2)
-extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
+#define COMPAT_ELF_HWCAP3 (compat_elf_hwcap3)
+extern unsigned int compat_elf_hwcap, compat_elf_hwcap2, compat_elf_hwcap3;
#endif
enum {
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 8c0a36f72d6f..e390c432f546 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -353,6 +353,7 @@ __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000)
__AARCH64_INSN_FUNCS(exclusive, 0x3F800000, 0x08000000)
__AARCH64_INSN_FUNCS(load_ex, 0x3F400000, 0x08400000)
__AARCH64_INSN_FUNCS(store_ex, 0x3F400000, 0x08000000)
+__AARCH64_INSN_FUNCS(mops, 0x3B200C00, 0x19000400)
__AARCH64_INSN_FUNCS(stp, 0x7FC00000, 0x29000000)
__AARCH64_INSN_FUNCS(ldp, 0x7FC00000, 0x29400000)
__AARCH64_INSN_FUNCS(stp_post, 0x7FC00000, 0x28800000)
@@ -575,6 +576,11 @@ static __always_inline u32 aarch64_insn_gen_nop(void)
return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
}
+static __always_inline bool aarch64_insn_is_nop(u32 insn)
+{
+ return insn == aarch64_insn_gen_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,
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 1ada23a6ec19..76ebbdc6ffdd 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -17,6 +17,7 @@
#include <asm/early_ioremap.h>
#include <asm/alternative.h>
#include <asm/cpufeature.h>
+#include <asm/rsi.h>
/*
* Generic IO read/write. These perform native-endian accesses.
@@ -129,17 +130,6 @@ static __always_inline u64 __raw_readq(const volatile void __iomem *addr)
#define PCI_IOBASE ((void __iomem *)PCI_IO_START)
/*
- * String version of I/O memory access operations.
- */
-extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t);
-extern void __memcpy_toio(volatile void __iomem *, const void *, size_t);
-extern void __memset_io(volatile void __iomem *, int, size_t);
-
-#define memset_io(c,v,l) __memset_io((c),(v),(l))
-#define memcpy_fromio(a,c,l) __memcpy_fromio((a),(c),(l))
-#define memcpy_toio(c,a,l) __memcpy_toio((c),(a),(l))
-
-/*
* The ARM64 iowrite implementation is intended to support drivers that want to
* use write combining. For instance PCI drivers using write combining with a 64
* byte __iowrite64_copy() expect to get a 64 byte MemWr TLP on the PCIe bus.
@@ -318,4 +308,11 @@ extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
unsigned long flags);
#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
+static inline bool arm64_is_protected_mmio(phys_addr_t phys_addr, size_t size)
+{
+ if (unlikely(is_realm_world()))
+ return __arm64_is_protected_mmio(phys_addr, size);
+ return false;
+}
+
#endif /* __ASM_IO_H */
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index a0a5bbae7229..424ed421cd97 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,10 +19,14 @@
#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\"\n\t" \
".align 3\n\t" \
- ".long 1b - ., %l["#label"] - .\n\t" \
- ".quad %c0 - .\n\t" \
- ".popsection\n\t" \
- : : "i"(key) : : label
+ ".long 1b - ., " label " - .\n\t" \
+ ".quad " key " - .\n\t" \
+ ".popsection\n\t"
+
+/* This macro is also expanded on the Rust side. */
+#define ARCH_STATIC_BRANCH_ASM(key, label) \
+ "1: nop\n\t" \
+ JUMP_TABLE_ENTRY(key, label)
static __always_inline bool arch_static_branch(struct static_key * const key,
const bool branch)
@@ -30,8 +34,8 @@ static __always_inline bool arch_static_branch(struct static_key * const key,
char *k = &((char *)key)[branch];
asm goto(
- "1: nop \n\t"
- JUMP_TABLE_ENTRY(k, l_yes)
+ ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
+ : : "i"(k) : : l_yes
);
return false;
@@ -43,9 +47,11 @@ static __always_inline bool arch_static_branch_jump(struct static_key * const ke
const bool branch)
{
char *k = &((char *)key)[branch];
+
asm goto(
"1: b %l[l_yes] \n\t"
- JUMP_TABLE_ENTRY(k, l_yes)
+ JUMP_TABLE_ENTRY("%c0", "%l[l_yes]")
+ : : "i"(k) : : l_yes
);
return false;
l_yes:
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index bf05a77873a4..fd5a08450b12 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -26,7 +26,6 @@
#define SWAPPER_SKIP_LEVEL 0
#endif
#define SWAPPER_BLOCK_SIZE (UL(1) << SWAPPER_BLOCK_SHIFT)
-#define SWAPPER_TABLE_SHIFT (SWAPPER_BLOCK_SHIFT + PAGE_SHIFT - 3)
#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS - SWAPPER_SKIP_LEVEL)
#define INIT_IDMAP_PGTABLE_LEVELS (IDMAP_LEVELS - SWAPPER_SKIP_LEVEL)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 109a85ee6910..3e0f0de1d2da 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -103,6 +103,7 @@
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
#define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En | HCRX_EL2_EnFPM)
+#define MPAMHCR_HOST_FLAGS 0
/* TCR_EL2 Registers bits */
#define TCR_EL2_DS (1UL << 32)
@@ -311,35 +312,6 @@
GENMASK(19, 18) | \
GENMASK(15, 0))
-/* Hyp Debug Configuration Register bits */
-#define MDCR_EL2_E2TB_MASK (UL(0x3))
-#define MDCR_EL2_E2TB_SHIFT (UL(24))
-#define MDCR_EL2_HPMFZS (UL(1) << 36)
-#define MDCR_EL2_HPMFZO (UL(1) << 29)
-#define MDCR_EL2_MTPME (UL(1) << 28)
-#define MDCR_EL2_TDCC (UL(1) << 27)
-#define MDCR_EL2_HLP (UL(1) << 26)
-#define MDCR_EL2_HCCD (UL(1) << 23)
-#define MDCR_EL2_TTRF (UL(1) << 19)
-#define MDCR_EL2_HPMD (UL(1) << 17)
-#define MDCR_EL2_TPMS (UL(1) << 14)
-#define MDCR_EL2_E2PB_MASK (UL(0x3))
-#define MDCR_EL2_E2PB_SHIFT (UL(12))
-#define MDCR_EL2_TDRA (UL(1) << 11)
-#define MDCR_EL2_TDOSA (UL(1) << 10)
-#define MDCR_EL2_TDA (UL(1) << 9)
-#define MDCR_EL2_TDE (UL(1) << 8)
-#define MDCR_EL2_HPME (UL(1) << 7)
-#define MDCR_EL2_TPM (UL(1) << 6)
-#define MDCR_EL2_TPMCR (UL(1) << 5)
-#define MDCR_EL2_HPMN_MASK (UL(0x1F))
-#define MDCR_EL2_RES0 (GENMASK(63, 37) | \
- GENMASK(35, 30) | \
- GENMASK(25, 24) | \
- GENMASK(22, 20) | \
- BIT(18) | \
- GENMASK(16, 15))
-
/*
* FGT register definitions
*
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 67afac659231..ca2590344313 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -76,7 +76,6 @@ enum __kvm_host_smccc_func {
__KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff,
__KVM_HOST_SMCCC_FUNC___vgic_v3_save_vmcr_aprs,
__KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs,
- __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_init_traps,
__KVM_HOST_SMCCC_FUNC___pkvm_init_vm,
__KVM_HOST_SMCCC_FUNC___pkvm_init_vcpu,
__KVM_HOST_SMCCC_FUNC___pkvm_teardown_vm,
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index a601a9305b10..cf811009a33c 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -225,6 +225,11 @@ static inline bool is_hyp_ctxt(const struct kvm_vcpu *vcpu)
return vcpu_has_nv(vcpu) && __is_hyp_ctxt(&vcpu->arch.ctxt);
}
+static inline bool vcpu_is_host_el0(const struct kvm_vcpu *vcpu)
+{
+ return is_hyp_ctxt(vcpu) && !vcpu_is_el2(vcpu);
+}
+
/*
* The layout of SPSR for an AArch32 state is different when observed from an
* AArch64 SPSR_ELx or an AArch32 SPSR_*. This function generates the AArch32
@@ -693,4 +698,8 @@ static inline bool guest_hyp_sve_traps_enabled(const struct kvm_vcpu *vcpu)
return __guest_hyp_cptr_xen_trap_enabled(vcpu, ZEN);
}
+static inline void kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
+{
+ vcpu_set_flag(vcpu, GUEST_HAS_PTRAUTH);
+}
#endif /* __ARM64_KVM_EMULATE_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index bf64fed9820e..e18e9244d17a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -74,8 +74,6 @@ enum kvm_mode kvm_get_mode(void);
static inline enum kvm_mode kvm_get_mode(void) { return KVM_MODE_NONE; };
#endif
-DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
-
extern unsigned int __ro_after_init kvm_sve_max_vl;
extern unsigned int __ro_after_init kvm_host_sve_max_vl;
int __init kvm_arm_init_sve(void);
@@ -374,7 +372,7 @@ struct kvm_arch {
u64 ctr_el0;
- /* Masks for VNCR-baked sysregs */
+ /* Masks for VNCR-backed and general EL2 sysregs */
struct kvm_sysreg_masks *sysreg_masks;
/*
@@ -408,6 +406,9 @@ struct kvm_vcpu_fault_info {
r = __VNCR_START__ + ((VNCR_ ## r) / 8), \
__after_##r = __MAX__(__before_##r - 1, r)
+#define MARKER(m) \
+ m, __after_##m = m - 1
+
enum vcpu_sysreg {
__INVALID_SYSREG__, /* 0 is reserved as an invalid value */
MPIDR_EL1, /* MultiProcessor Affinity Register */
@@ -468,13 +469,15 @@ enum vcpu_sysreg {
/* EL2 registers */
SCTLR_EL2, /* System Control Register (EL2) */
ACTLR_EL2, /* Auxiliary Control Register (EL2) */
- MDCR_EL2, /* Monitor Debug Configuration Register (EL2) */
CPTR_EL2, /* Architectural Feature Trap Register (EL2) */
HACR_EL2, /* Hypervisor Auxiliary Control Register */
ZCR_EL2, /* SVE Control Register (EL2) */
TTBR0_EL2, /* Translation Table Base Register 0 (EL2) */
TTBR1_EL2, /* Translation Table Base Register 1 (EL2) */
TCR_EL2, /* Translation Control Register (EL2) */
+ PIRE0_EL2, /* Permission Indirection Register 0 (EL2) */
+ PIR_EL2, /* Permission Indirection Register 1 (EL2) */
+ POR_EL2, /* Permission Overlay Register 2 (EL2) */
SPSR_EL2, /* EL2 saved program status register */
ELR_EL2, /* EL2 exception link register */
AFSR0_EL2, /* Auxiliary Fault Status Register 0 (EL2) */
@@ -494,7 +497,13 @@ enum vcpu_sysreg {
CNTHV_CTL_EL2,
CNTHV_CVAL_EL2,
- __VNCR_START__, /* Any VNCR-capable reg goes after this point */
+ /* Anything from this can be RES0/RES1 sanitised */
+ MARKER(__SANITISED_REG_START__),
+ TCR2_EL2, /* Extended Translation Control Register (EL2) */
+ MDCR_EL2, /* Monitor Debug Configuration Register (EL2) */
+
+ /* Any VNCR-capable reg goes after this point */
+ MARKER(__VNCR_START__),
VNCR(SCTLR_EL1),/* System Control Register */
VNCR(ACTLR_EL1),/* Auxiliary Control Register */
@@ -554,7 +563,7 @@ struct kvm_sysreg_masks {
struct {
u64 res0;
u64 res1;
- } mask[NR_SYS_REGS - __VNCR_START__];
+ } mask[NR_SYS_REGS - __SANITISED_REG_START__];
};
struct kvm_cpu_context {
@@ -1002,13 +1011,13 @@ static inline u64 *___ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
#define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r))
-u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg);
+u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u64);
#define __vcpu_sys_reg(v,r) \
(*({ \
const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \
u64 *__r = __ctxt_sys_reg(ctxt, (r)); \
- if (vcpu_has_nv((v)) && (r) >= __VNCR_START__) \
- *__r = kvm_vcpu_sanitise_vncr_reg((v), (r)); \
+ if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \
+ *__r = kvm_vcpu_apply_reg_masks((v), (r), *__r);\
__r; \
}))
@@ -1037,6 +1046,10 @@ static inline bool __vcpu_read_sys_reg_from_cpu(int reg, u64 *val)
case TTBR0_EL1: *val = read_sysreg_s(SYS_TTBR0_EL12); break;
case TTBR1_EL1: *val = read_sysreg_s(SYS_TTBR1_EL12); break;
case TCR_EL1: *val = read_sysreg_s(SYS_TCR_EL12); break;
+ case TCR2_EL1: *val = read_sysreg_s(SYS_TCR2_EL12); break;
+ case PIR_EL1: *val = read_sysreg_s(SYS_PIR_EL12); break;
+ case PIRE0_EL1: *val = read_sysreg_s(SYS_PIRE0_EL12); break;
+ case POR_EL1: *val = read_sysreg_s(SYS_POR_EL12); break;
case ESR_EL1: *val = read_sysreg_s(SYS_ESR_EL12); break;
case AFSR0_EL1: *val = read_sysreg_s(SYS_AFSR0_EL12); break;
case AFSR1_EL1: *val = read_sysreg_s(SYS_AFSR1_EL12); break;
@@ -1083,6 +1096,10 @@ static inline bool __vcpu_write_sys_reg_to_cpu(u64 val, int reg)
case TTBR0_EL1: write_sysreg_s(val, SYS_TTBR0_EL12); break;
case TTBR1_EL1: write_sysreg_s(val, SYS_TTBR1_EL12); break;
case TCR_EL1: write_sysreg_s(val, SYS_TCR_EL12); break;
+ case TCR2_EL1: write_sysreg_s(val, SYS_TCR2_EL12); break;
+ case PIR_EL1: write_sysreg_s(val, SYS_PIR_EL12); break;
+ case PIRE0_EL1: write_sysreg_s(val, SYS_PIRE0_EL12); break;
+ case POR_EL1: write_sysreg_s(val, SYS_POR_EL12); break;
case ESR_EL1: write_sysreg_s(val, SYS_ESR_EL12); break;
case AFSR0_EL1: write_sysreg_s(val, SYS_AFSR0_EL12); break;
case AFSR1_EL1: write_sysreg_s(val, SYS_AFSR1_EL12); break;
@@ -1140,7 +1157,7 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
void kvm_arm_halt_guest(struct kvm *kvm);
void kvm_arm_resume_guest(struct kvm *kvm);
-#define vcpu_has_run_once(vcpu) !!rcu_access_pointer((vcpu)->pid)
+#define vcpu_has_run_once(vcpu) (!!READ_ONCE((vcpu)->pid))
#ifndef __KVM_NVHE_HYPERVISOR__
#define kvm_call_hyp_nvhe(f, ...) \
@@ -1503,4 +1520,13 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
(system_supports_fpmr() && \
kvm_has_feat((k), ID_AA64PFR2_EL1, FPMR, IMP))
+#define kvm_has_tcr2(k) \
+ (kvm_has_feat((k), ID_AA64MMFR3_EL1, TCRX, IMP))
+
+#define kvm_has_s1pie(k) \
+ (kvm_has_feat((k), ID_AA64MMFR3_EL1, S1PIE, IMP))
+
+#define kvm_has_s1poe(k) \
+ (kvm_has_feat((k), ID_AA64MMFR3_EL1, S1POE, IMP))
+
#endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 03f4c3d7839c..aab04097b505 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -674,10 +674,8 @@ int kvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size);
*
* If there is a valid, leaf page-table entry used to translate @addr, then
* set the access flag in that entry.
- *
- * Return: The old page-table entry prior to setting the flag, 0 on failure.
*/
-kvm_pte_t kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr);
+void kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr);
/**
* kvm_pgtable_stage2_test_clear_young() - Test and optionally clear the access
diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/mem_encrypt.h
index b0c9a86b13a4..f8f78f622dd2 100644
--- a/arch/arm64/include/asm/mem_encrypt.h
+++ b/arch/arm64/include/asm/mem_encrypt.h
@@ -2,6 +2,8 @@
#ifndef __ASM_MEM_ENCRYPT_H
#define __ASM_MEM_ENCRYPT_H
+#include <asm/rsi.h>
+
struct arm64_mem_crypt_ops {
int (*encrypt)(unsigned long addr, int numpages);
int (*decrypt)(unsigned long addr, int numpages);
@@ -12,4 +14,11 @@ int arm64_mem_crypt_ops_register(const struct arm64_mem_crypt_ops *ops);
int set_memory_encrypted(unsigned long addr, int numpages);
int set_memory_decrypted(unsigned long addr, int numpages);
+int realm_register_memory_enc_ops(void);
+
+static inline bool force_dma_unencrypted(struct device *dev)
+{
+ return is_realm_world();
+}
+
#endif /* __ASM_MEM_ENCRYPT_H */
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 0480c61dbb4f..8b9f33cf561b 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -110,7 +110,7 @@
#define PAGE_END (_PAGE_END(VA_BITS_MIN))
#endif /* CONFIG_KASAN */
-#define PHYSMEM_END __pa(PAGE_END - 1)
+#define DIRECT_MAP_PHYSMEM_END __pa(PAGE_END - 1)
#define MIN_THREAD_SHIFT (14 + KASAN_THREAD_SHIFT)
@@ -354,12 +354,6 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x);
#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
/*
- * Convert a page to/from a physical address
- */
-#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
-#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
-
-/*
* Note: Drivers should NOT use these. They are the wrong
* translation for translating DMA addresses. Use the driver
* DMA support - see dma-mapping.h.
diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h
index 9e39217b4afb..1d53022fc7e1 100644
--- a/arch/arm64/include/asm/mman.h
+++ b/arch/arm64/include/asm/mman.h
@@ -6,6 +6,8 @@
#ifndef BUILD_VDSO
#include <linux/compiler.h>
+#include <linux/fs.h>
+#include <linux/shmem_fs.h>
#include <linux/types.h>
static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
@@ -31,19 +33,24 @@ static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
}
#define arch_calc_vm_prot_bits(prot, pkey) arch_calc_vm_prot_bits(prot, pkey)
-static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
+static inline unsigned long arch_calc_vm_flag_bits(struct file *file,
+ unsigned long flags)
{
/*
* Only allow MTE on anonymous mappings as these are guaranteed to be
* backed by tags-capable memory. The vm_flags may be overridden by a
* filesystem supporting MTE (RAM-based).
*/
- if (system_supports_mte() && (flags & MAP_ANONYMOUS))
- return VM_MTE_ALLOWED;
+ if (system_supports_mte()) {
+ if (flags & (MAP_ANONYMOUS | MAP_HUGETLB))
+ return VM_MTE_ALLOWED;
+ if (shmem_file(file))
+ return VM_MTE_ALLOWED;
+ }
return 0;
}
-#define arch_calc_vm_flag_bits(flags) arch_calc_vm_flag_bits(flags)
+#define arch_calc_vm_flag_bits(file, flags) arch_calc_vm_flag_bits(file, flags)
static inline bool arch_validate_prot(unsigned long prot,
unsigned long addr __always_unused)
@@ -62,11 +69,26 @@ static inline bool arch_validate_prot(unsigned long prot,
static inline bool arch_validate_flags(unsigned long vm_flags)
{
- if (!system_supports_mte())
- return true;
+ if (system_supports_mte()) {
+ /*
+ * only allow VM_MTE if VM_MTE_ALLOWED has been set
+ * previously
+ */
+ if ((vm_flags & VM_MTE) && !(vm_flags & VM_MTE_ALLOWED))
+ return false;
+ }
+
+ if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) {
+ /* An executable GCS isn't a good idea. */
+ if (vm_flags & VM_EXEC)
+ return false;
+
+ /* The memory management core should prevent this */
+ VM_WARN_ON(vm_flags & VM_SHARED);
+ }
+
+ return true;
- /* only allow VM_MTE if VM_MTE_ALLOWED has been set previously */
- return !(vm_flags & VM_MTE) || (vm_flags & VM_MTE_ALLOWED);
}
#define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags)
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index 7c09d47e09cb..48b3d9553b67 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -20,6 +20,7 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
#include <asm/daifflags.h>
+#include <asm/gcs.h>
#include <asm/proc-fns.h>
#include <asm/cputype.h>
#include <asm/sysreg.h>
@@ -311,6 +312,14 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
return por_el0_allows_pkey(vma_pkey(vma), write, execute);
}
+#define deactivate_mm deactivate_mm
+static inline void deactivate_mm(struct task_struct *tsk,
+ struct mm_struct *mm)
+{
+ gcs_free(tsk);
+}
+
+
#include <asm-generic/mmu_context.h>
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
index 0f84518632b4..6567df8ec8ca 100644
--- a/arch/arm64/include/asm/mte.h
+++ b/arch/arm64/include/asm/mte.h
@@ -41,6 +41,8 @@ void mte_free_tag_storage(char *storage);
static inline void set_page_mte_tagged(struct page *page)
{
+ VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));
+
/*
* Ensure that the tags written prior to this function are visible
* before the page flags update.
@@ -53,6 +55,8 @@ static inline bool page_mte_tagged(struct page *page)
{
bool ret = test_bit(PG_mte_tagged, &page->flags);
+ VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));
+
/*
* If the page is tagged, ensure ordering with a likely subsequent
* read of the tags.
@@ -76,6 +80,8 @@ static inline bool page_mte_tagged(struct page *page)
*/
static inline bool try_page_mte_tagging(struct page *page)
{
+ VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));
+
if (!test_and_set_bit(PG_mte_lock, &page->flags))
return true;
@@ -157,6 +163,67 @@ static inline int mte_ptrace_copy_tags(struct task_struct *child,
#endif /* CONFIG_ARM64_MTE */
+#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_ARM64_MTE)
+static inline void folio_set_hugetlb_mte_tagged(struct folio *folio)
+{
+ VM_WARN_ON_ONCE(!folio_test_hugetlb(folio));
+
+ /*
+ * Ensure that the tags written prior to this function are visible
+ * before the folio flags update.
+ */
+ smp_wmb();
+ set_bit(PG_mte_tagged, &folio->flags);
+
+}
+
+static inline bool folio_test_hugetlb_mte_tagged(struct folio *folio)
+{
+ bool ret = test_bit(PG_mte_tagged, &folio->flags);
+
+ VM_WARN_ON_ONCE(!folio_test_hugetlb(folio));
+
+ /*
+ * If the folio is tagged, ensure ordering with a likely subsequent
+ * read of the tags.
+ */
+ if (ret)
+ smp_rmb();
+ return ret;
+}
+
+static inline bool folio_try_hugetlb_mte_tagging(struct folio *folio)
+{
+ VM_WARN_ON_ONCE(!folio_test_hugetlb(folio));
+
+ if (!test_and_set_bit(PG_mte_lock, &folio->flags))
+ return true;
+
+ /*
+ * The tags are either being initialised or may have been initialised
+ * already. Check if the PG_mte_tagged flag has been set or wait
+ * otherwise.
+ */
+ smp_cond_load_acquire(&folio->flags, VAL & (1UL << PG_mte_tagged));
+
+ return false;
+}
+#else
+static inline void folio_set_hugetlb_mte_tagged(struct folio *folio)
+{
+}
+
+static inline bool folio_test_hugetlb_mte_tagged(struct folio *folio)
+{
+ return false;
+}
+
+static inline bool folio_try_hugetlb_mte_tagging(struct folio *folio)
+{
+ return false;
+}
+#endif
+
static inline void mte_disable_tco_entry(struct task_struct *task)
{
if (!system_supports_mte())
diff --git a/arch/arm64/include/asm/page-def.h b/arch/arm64/include/asm/page-def.h
index 792e9fe881dc..d402e08442ee 100644
--- a/arch/arm64/include/asm/page-def.h
+++ b/arch/arm64/include/asm/page-def.h
@@ -10,9 +10,6 @@
#include <linux/const.h>
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#endif /* __ASM_PAGE_DEF_H */
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h
index eb7071c9eb34..ee45b4e77347 100644
--- a/arch/arm64/include/asm/perf_event.h
+++ b/arch/arm64/include/asm/perf_event.h
@@ -10,10 +10,6 @@
#include <asm/ptrace.h>
#ifdef CONFIG_PERF_EVENTS
-struct pt_regs;
-extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
-extern unsigned long perf_misc_flags(struct pt_regs *regs);
-#define perf_misc_flags(regs) perf_misc_flags(regs)
#define perf_arch_bpf_user_pt_regs(regs) &regs->user_regs
#endif
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
index 8ff5f2a2579e..e75422864d1b 100644
--- a/arch/arm64/include/asm/pgalloc.h
+++ b/arch/arm64/include/asm/pgalloc.h
@@ -28,7 +28,7 @@ static inline void __pud_populate(pud_t *pudp, phys_addr_t pmdp, pudval_t prot)
static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmdp)
{
- pudval_t pudval = PUD_TYPE_TABLE;
+ pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_AF;
pudval |= (mm == &init_mm) ? PUD_TABLE_UXN : PUD_TABLE_PXN;
__pud_populate(pudp, __pa(pmdp), pudval);
@@ -50,7 +50,7 @@ static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot)
static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp)
{
- p4dval_t p4dval = P4D_TYPE_TABLE;
+ p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_AF;
p4dval |= (mm == &init_mm) ? P4D_TABLE_UXN : P4D_TABLE_PXN;
__p4d_populate(p4dp, __pa(pudp), p4dval);
@@ -79,7 +79,7 @@ static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t p4dp, pgdval_t prot)
static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, p4d_t *p4dp)
{
- pgdval_t pgdval = PGD_TYPE_TABLE;
+ pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_AF;
pgdval |= (mm == &init_mm) ? PGD_TABLE_UXN : PGD_TABLE_PXN;
__pgd_populate(pgdp, __pa(p4dp), pgdval);
@@ -127,14 +127,16 @@ static inline void
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
{
VM_BUG_ON(mm && mm != &init_mm);
- __pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE | PMD_TABLE_UXN);
+ __pmd_populate(pmdp, __pa(ptep),
+ PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_UXN);
}
static inline void
pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
{
VM_BUG_ON(mm == &init_mm);
- __pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE | PMD_TABLE_PXN);
+ __pmd_populate(pmdp, page_to_phys(ptep),
+ PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_PXN);
}
#endif
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index fd330c1db289..c78a988cca93 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -99,6 +99,7 @@
#define PGD_TYPE_TABLE (_AT(pgdval_t, 3) << 0)
#define PGD_TABLE_BIT (_AT(pgdval_t, 1) << 1)
#define PGD_TYPE_MASK (_AT(pgdval_t, 3) << 0)
+#define PGD_TABLE_AF (_AT(pgdval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
#define PGD_TABLE_PXN (_AT(pgdval_t, 1) << 59)
#define PGD_TABLE_UXN (_AT(pgdval_t, 1) << 60)
@@ -110,6 +111,7 @@
#define P4D_TYPE_MASK (_AT(p4dval_t, 3) << 0)
#define P4D_TYPE_SECT (_AT(p4dval_t, 1) << 0)
#define P4D_SECT_RDONLY (_AT(p4dval_t, 1) << 7) /* AP[2] */
+#define P4D_TABLE_AF (_AT(p4dval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
#define P4D_TABLE_PXN (_AT(p4dval_t, 1) << 59)
#define P4D_TABLE_UXN (_AT(p4dval_t, 1) << 60)
@@ -121,6 +123,7 @@
#define PUD_TYPE_MASK (_AT(pudval_t, 3) << 0)
#define PUD_TYPE_SECT (_AT(pudval_t, 1) << 0)
#define PUD_SECT_RDONLY (_AT(pudval_t, 1) << 7) /* AP[2] */
+#define PUD_TABLE_AF (_AT(pudval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
#define PUD_TABLE_PXN (_AT(pudval_t, 1) << 59)
#define PUD_TABLE_UXN (_AT(pudval_t, 1) << 60)
@@ -131,6 +134,7 @@
#define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0)
#define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0)
#define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1)
+#define PMD_TABLE_AF (_AT(pmdval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
/*
* Section
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 2a11d0c10760..9f9cf13bbd95 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -35,7 +35,6 @@
#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_WP */
#define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
-#define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_MAYBE_NG | PTE_MAYBE_SHARED | PTE_AF)
#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_MAYBE_NG | PMD_MAYBE_SHARED | PMD_SECT_AF)
@@ -68,8 +67,12 @@
#include <asm/cpufeature.h>
#include <asm/pgtable-types.h>
+#include <asm/rsi.h>
extern bool arm64_use_ng_mappings;
+extern unsigned long prot_ns_shared;
+
+#define PROT_NS_SHARED (is_realm_world() ? prot_ns_shared : 0)
#define PTE_MAYBE_NG (arm64_use_ng_mappings ? PTE_NG : 0)
#define PMD_MAYBE_NG (arm64_use_ng_mappings ? PMD_SECT_NG : 0)
@@ -144,15 +147,23 @@ static inline bool __pure lpa2_is_enabled(void)
/* 6: PTE_PXN | PTE_WRITE */
/* 7: PAGE_SHARED_EXEC PTE_PXN | PTE_WRITE | PTE_USER */
/* 8: PAGE_KERNEL_ROX PTE_UXN */
-/* 9: PTE_UXN | PTE_USER */
+/* 9: PAGE_GCS_RO PTE_UXN | PTE_USER */
/* a: PAGE_KERNEL_EXEC PTE_UXN | PTE_WRITE */
-/* b: PTE_UXN | PTE_WRITE | PTE_USER */
+/* b: PAGE_GCS PTE_UXN | PTE_WRITE | PTE_USER */
/* c: PAGE_KERNEL_RO PTE_UXN | PTE_PXN */
/* d: PAGE_READONLY PTE_UXN | PTE_PXN | PTE_USER */
/* e: PAGE_KERNEL PTE_UXN | PTE_PXN | PTE_WRITE */
/* f: PAGE_SHARED PTE_UXN | PTE_PXN | PTE_WRITE | PTE_USER */
+#define _PAGE_GCS (_PAGE_DEFAULT | PTE_NG | PTE_UXN | PTE_WRITE | PTE_USER)
+#define _PAGE_GCS_RO (_PAGE_DEFAULT | PTE_NG | PTE_UXN | PTE_USER)
+
+#define PAGE_GCS __pgprot(_PAGE_GCS)
+#define PAGE_GCS_RO __pgprot(_PAGE_GCS_RO)
+
#define PIE_E0 ( \
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS), PIE_GCS) | \
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS_RO), PIE_R) | \
PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_X_O) | \
PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX_O) | \
PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RWX_O) | \
@@ -160,6 +171,8 @@ static inline bool __pure lpa2_is_enabled(void)
PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED), PIE_RW_O))
#define PIE_E1 ( \
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS), PIE_NONE_O) | \
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS_RO), PIE_NONE_O) | \
PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_NONE_O) | \
PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_R) | \
PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RW) | \
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index c329ea061dc9..6986345b537a 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -265,8 +265,7 @@ static inline pte_t pte_mkspecial(pte_t pte)
static inline pte_t pte_mkcont(pte_t pte)
{
- pte = set_pte_bit(pte, __pgprot(PTE_CONT));
- return set_pte_bit(pte, __pgprot(PTE_TYPE_PAGE));
+ return set_pte_bit(pte, __pgprot(PTE_CONT));
}
static inline pte_t pte_mknoncont(pte_t pte)
@@ -338,7 +337,7 @@ static inline pte_t __ptep_get(pte_t *ptep)
}
extern void __sync_icache_dcache(pte_t pteval);
-bool pgattr_change_is_safe(u64 old, u64 new);
+bool pgattr_change_is_safe(pteval_t old, pteval_t new);
/*
* PTE bits configuration in the presence of hardware Dirty Bit Management
@@ -439,11 +438,6 @@ static inline void __set_ptes(struct mm_struct *mm,
}
/*
- * Huge pte definitions.
- */
-#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
-
-/*
* Hugetlb definitions.
*/
#define HUGE_MAX_HSTATE 4
@@ -684,6 +678,11 @@ static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
#define pgprot_nx(prot) \
__pgprot_modify(prot, PTE_MAYBE_GP, PTE_PXN)
+#define pgprot_decrypted(prot) \
+ __pgprot_modify(prot, PROT_NS_SHARED, PROT_NS_SHARED)
+#define pgprot_encrypted(prot) \
+ __pgprot_modify(prot, PROT_NS_SHARED, 0)
+
/*
* Mark the prot value as uncacheable and unbufferable.
*/
@@ -927,6 +926,9 @@ static inline phys_addr_t p4d_page_paddr(p4d_t p4d)
static inline pud_t *p4d_to_folded_pud(p4d_t *p4dp, unsigned long addr)
{
+ /* Ensure that 'p4dp' indexes a page table according to 'addr' */
+ VM_BUG_ON(((addr >> P4D_SHIFT) ^ ((u64)p4dp >> 3)) % PTRS_PER_P4D);
+
return (pud_t *)PTR_ALIGN_DOWN(p4dp, PAGE_SIZE) + pud_index(addr);
}
@@ -1051,6 +1053,9 @@ static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
static inline p4d_t *pgd_to_folded_p4d(pgd_t *pgdp, unsigned long addr)
{
+ /* Ensure that 'pgdp' indexes a page table according to 'addr' */
+ VM_BUG_ON(((addr >> PGDIR_SHIFT) ^ ((u64)pgdp >> 3)) % PTRS_PER_PGD);
+
return (p4d_t *)PTR_ALIGN_DOWN(pgdp, PAGE_SIZE) + p4d_index(addr);
}
@@ -1259,15 +1264,17 @@ static inline int __ptep_clear_flush_young(struct vm_area_struct *vma,
return young;
}
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG)
#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
unsigned long address,
pmd_t *pmdp)
{
+ /* Operation applies to PMD table entry only if FEAT_HAFT is enabled */
+ VM_WARN_ON(pmd_table(READ_ONCE(*pmdp)) && !system_supports_haft());
return __ptep_test_and_clear_young(vma, address, (pte_t *)pmdp);
}
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */
static inline pte_t __ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, pte_t *ptep)
@@ -1502,6 +1509,10 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
*/
#define arch_has_hw_pte_young cpu_has_hw_af
+#ifdef CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG
+#define arch_has_hw_nonleaf_pmd_young system_supports_haft
+#endif
+
/*
* Experimentally, it's cheap to set the access flag in hardware and we
* benefit from prefaulting mappings as 'old' to start with.
diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
index 006946745352..d49368886309 100644
--- a/arch/arm64/include/asm/probes.h
+++ b/arch/arm64/include/asm/probes.h
@@ -9,21 +9,18 @@
#include <asm/insn.h>
-typedef u32 probe_opcode_t;
typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *);
-/* architecture specific copy of original instruction */
struct arch_probe_insn {
- probe_opcode_t *insn;
- pstate_check_t *pstate_cc;
probes_handler_t *handler;
- /* restore address after step xol */
- unsigned long restore;
};
#ifdef CONFIG_KPROBES
-typedef u32 kprobe_opcode_t;
+typedef __le32 kprobe_opcode_t;
struct arch_specific_insn {
struct arch_probe_insn api;
+ kprobe_opcode_t *xol_insn;
+ /* restore address after step xol */
+ unsigned long xol_restore;
};
#endif
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 1438424f0064..1bf1a3b16e88 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -185,6 +185,13 @@ struct thread_struct {
u64 svcr;
u64 tpidr2_el0;
u64 por_el0;
+#ifdef CONFIG_ARM64_GCS
+ unsigned int gcs_el0_mode;
+ unsigned int gcs_el0_locked;
+ u64 gcspr_el0;
+ u64 gcs_base;
+ u64 gcs_size;
+#endif
};
static inline unsigned int thread_get_vl(struct thread_struct *thread,
@@ -285,22 +292,44 @@ void tls_preserve_current_state(void);
.fpsimd_cpu = NR_CPUS, \
}
-static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
+static inline void start_thread_common(struct pt_regs *regs, unsigned long pc,
+ unsigned long pstate)
{
- s32 previous_syscall = regs->syscallno;
- memset(regs, 0, sizeof(*regs));
- regs->syscallno = previous_syscall;
- regs->pc = pc;
+ /*
+ * Ensure all GPRs are zeroed, and initialize PC + PSTATE.
+ * The SP (or compat SP) will be initialized later.
+ */
+ regs->user_regs = (struct user_pt_regs) {
+ .pc = pc,
+ .pstate = pstate,
+ };
+ /*
+ * To allow the syscalls:sys_exit_execve tracepoint we need to preserve
+ * syscallno, but do not need orig_x0 or the original GPRs.
+ */
+ regs->orig_x0 = 0;
+
+ /*
+ * An exec from a kernel thread won't have an existing PMR value.
+ */
if (system_uses_irq_prio_masking())
- regs->pmr_save = GIC_PRIO_IRQON;
+ regs->pmr = GIC_PRIO_IRQON;
+
+ /*
+ * The pt_regs::stackframe field must remain valid throughout this
+ * function as a stacktrace can be taken at any time. Any user or
+ * kernel task should have a valid final frame.
+ */
+ WARN_ON_ONCE(regs->stackframe.record.fp != 0);
+ WARN_ON_ONCE(regs->stackframe.record.lr != 0);
+ WARN_ON_ONCE(regs->stackframe.type != FRAME_META_TYPE_FINAL);
}
static inline void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
- start_thread_common(regs, pc);
- regs->pstate = PSR_MODE_EL0t;
+ start_thread_common(regs, pc, PSR_MODE_EL0t);
spectre_v4_enable_task_mitigation(current);
regs->sp = sp;
}
@@ -309,15 +338,13 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc,
static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
- start_thread_common(regs, pc);
- regs->pstate = PSR_AA32_MODE_USR;
+ unsigned long pstate = PSR_AA32_MODE_USR;
if (pc & 1)
- regs->pstate |= PSR_AA32_T_BIT;
-
-#ifdef __AARCH64EB__
- regs->pstate |= PSR_AA32_E_BIT;
-#endif
+ pstate |= PSR_AA32_T_BIT;
+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+ pstate |= PSR_AA32_E_BIT;
+ start_thread_common(regs, pc, pstate);
spectre_v4_enable_task_mitigation(current);
regs->compat_sp = sp;
}
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 0abe975d68a8..47ff8654c5ec 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -98,6 +98,8 @@
#include <linux/bug.h>
#include <linux/types.h>
+#include <asm/stacktrace/frame.h>
+
/* sizeof(struct user) for AArch32 */
#define COMPAT_USER_SZ 296
@@ -149,8 +151,7 @@ static inline unsigned long pstate_to_compat_psr(const unsigned long pstate)
/*
* This struct defines the way the registers are stored on the stack during an
- * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for
- * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs.
+ * exception. struct user_pt_regs must form a prefix of struct pt_regs.
*/
struct pt_regs {
union {
@@ -163,23 +164,20 @@ struct pt_regs {
};
};
u64 orig_x0;
-#ifdef __AARCH64EB__
- u32 unused2;
- s32 syscallno;
-#else
s32 syscallno;
- u32 unused2;
-#endif
+ u32 pmr;
+
u64 sdei_ttbr1;
- /* Only valid when ARM64_HAS_GIC_PRIO_MASKING is enabled. */
- u64 pmr_save;
- u64 stackframe[2];
+ struct frame_record_meta stackframe;
/* Only valid for some EL1 exceptions. */
u64 lockdep_hardirqs;
u64 exit_rcu;
};
+/* For correct stack alignment, pt_regs has to be a multiple of 16 bytes. */
+static_assert(IS_ALIGNED(sizeof(struct pt_regs), 16));
+
static inline bool in_syscall(struct pt_regs const *regs)
{
return regs->syscallno != NO_SYSCALL;
@@ -213,7 +211,7 @@ static inline void forget_syscall(struct pt_regs *regs)
#define irqs_priority_unmasked(regs) \
(system_uses_irq_prio_masking() ? \
- (regs)->pmr_save == GIC_PRIO_IRQON : \
+ (regs)->pmr == GIC_PRIO_IRQON : \
true)
#define interrupts_enabled(regs) \
diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
new file mode 100644
index 000000000000..188cbb9b23f5
--- /dev/null
+++ b/arch/arm64/include/asm/rsi.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 ARM Ltd.
+ */
+
+#ifndef __ASM_RSI_H_
+#define __ASM_RSI_H_
+
+#include <linux/errno.h>
+#include <linux/jump_label.h>
+#include <asm/rsi_cmds.h>
+
+DECLARE_STATIC_KEY_FALSE(rsi_present);
+
+void __init arm64_rsi_init(void);
+
+bool __arm64_is_protected_mmio(phys_addr_t base, size_t size);
+
+static inline bool is_realm_world(void)
+{
+ return static_branch_unlikely(&rsi_present);
+}
+
+static inline int rsi_set_memory_range(phys_addr_t start, phys_addr_t end,
+ enum ripas state, unsigned long flags)
+{
+ unsigned long ret;
+ phys_addr_t top;
+
+ while (start != end) {
+ ret = rsi_set_addr_range_state(start, end, state, flags, &top);
+ if (ret || top < start || top > end)
+ return -EINVAL;
+ start = top;
+ }
+
+ return 0;
+}
+
+/*
+ * Convert the specified range to RAM. Do not use this if you rely on the
+ * contents of a page that may already be in RAM state.
+ */
+static inline int rsi_set_memory_range_protected(phys_addr_t start,
+ phys_addr_t end)
+{
+ return rsi_set_memory_range(start, end, RSI_RIPAS_RAM,
+ RSI_CHANGE_DESTROYED);
+}
+
+/*
+ * Convert the specified range to RAM. Do not convert any pages that may have
+ * been DESTROYED, without our permission.
+ */
+static inline int rsi_set_memory_range_protected_safe(phys_addr_t start,
+ phys_addr_t end)
+{
+ return rsi_set_memory_range(start, end, RSI_RIPAS_RAM,
+ RSI_NO_CHANGE_DESTROYED);
+}
+
+static inline int rsi_set_memory_range_shared(phys_addr_t start,
+ phys_addr_t end)
+{
+ return rsi_set_memory_range(start, end, RSI_RIPAS_EMPTY,
+ RSI_CHANGE_DESTROYED);
+}
+#endif /* __ASM_RSI_H_ */
diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi_cmds.h
new file mode 100644
index 000000000000..e6a211001bd3
--- /dev/null
+++ b/arch/arm64/include/asm/rsi_cmds.h
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 ARM Ltd.
+ */
+
+#ifndef __ASM_RSI_CMDS_H
+#define __ASM_RSI_CMDS_H
+
+#include <linux/arm-smccc.h>
+
+#include <asm/rsi_smc.h>
+
+#define RSI_GRANULE_SHIFT 12
+#define RSI_GRANULE_SIZE (_AC(1, UL) << RSI_GRANULE_SHIFT)
+
+enum ripas {
+ RSI_RIPAS_EMPTY = 0,
+ RSI_RIPAS_RAM = 1,
+ RSI_RIPAS_DESTROYED = 2,
+ RSI_RIPAS_DEV = 3,
+};
+
+static inline unsigned long rsi_request_version(unsigned long req,
+ unsigned long *out_lower,
+ unsigned long *out_higher)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_RSI_ABI_VERSION, req, 0, 0, 0, 0, 0, 0, &res);
+
+ if (out_lower)
+ *out_lower = res.a1;
+ if (out_higher)
+ *out_higher = res.a2;
+
+ return res.a0;
+}
+
+static inline unsigned long rsi_get_realm_config(struct realm_config *cfg)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_RSI_REALM_CONFIG, virt_to_phys(cfg),
+ 0, 0, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static inline unsigned long rsi_ipa_state_get(phys_addr_t start,
+ phys_addr_t end,
+ enum ripas *state,
+ phys_addr_t *top)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_RSI_IPA_STATE_GET,
+ start, end, 0, 0, 0, 0, 0,
+ &res);
+
+ if (res.a0 == RSI_SUCCESS) {
+ if (top)
+ *top = res.a1;
+ if (state)
+ *state = res.a2;
+ }
+
+ return res.a0;
+}
+
+static inline long rsi_set_addr_range_state(phys_addr_t start,
+ phys_addr_t end,
+ enum ripas state,
+ unsigned long flags,
+ phys_addr_t *top)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_RSI_IPA_STATE_SET, start, end, state,
+ flags, 0, 0, 0, &res);
+
+ if (top)
+ *top = res.a1;
+
+ if (res.a2 != RSI_ACCEPT)
+ return -EPERM;
+
+ return res.a0;
+}
+
+/**
+ * rsi_attestation_token_init - Initialise the operation to retrieve an
+ * attestation token.
+ *
+ * @challenge: The challenge data to be used in the attestation token
+ * generation.
+ * @size: Size of the challenge data in bytes.
+ *
+ * Initialises the attestation token generation and returns an upper bound
+ * on the attestation token size that can be used to allocate an adequate
+ * buffer. The caller is expected to subsequently call
+ * rsi_attestation_token_continue() to retrieve the attestation token data on
+ * the same CPU.
+ *
+ * Returns:
+ * On success, returns the upper limit of the attestation report size.
+ * Otherwise, -EINVAL
+ */
+static inline long
+rsi_attestation_token_init(const u8 *challenge, unsigned long size)
+{
+ struct arm_smccc_1_2_regs regs = { 0 };
+
+ /* The challenge must be at least 32bytes and at most 64bytes */
+ if (!challenge || size < 32 || size > 64)
+ return -EINVAL;
+
+ regs.a0 = SMC_RSI_ATTESTATION_TOKEN_INIT;
+ memcpy(&regs.a1, challenge, size);
+ arm_smccc_1_2_smc(&regs, &regs);
+
+ if (regs.a0 == RSI_SUCCESS)
+ return regs.a1;
+
+ return -EINVAL;
+}
+
+/**
+ * rsi_attestation_token_continue - Continue the operation to retrieve an
+ * attestation token.
+ *
+ * @granule: {I}PA of the Granule to which the token will be written.
+ * @offset: Offset within Granule to start of buffer in bytes.
+ * @size: The size of the buffer.
+ * @len: The number of bytes written to the buffer.
+ *
+ * Retrieves up to a RSI_GRANULE_SIZE worth of token data per call. The caller
+ * is expected to call rsi_attestation_token_init() before calling this
+ * function to retrieve the attestation token.
+ *
+ * Return:
+ * * %RSI_SUCCESS - Attestation token retrieved successfully.
+ * * %RSI_INCOMPLETE - Token generation is not complete.
+ * * %RSI_ERROR_INPUT - A parameter was not valid.
+ * * %RSI_ERROR_STATE - Attestation not in progress.
+ */
+static inline unsigned long rsi_attestation_token_continue(phys_addr_t granule,
+ unsigned long offset,
+ unsigned long size,
+ unsigned long *len)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_invoke(SMC_RSI_ATTESTATION_TOKEN_CONTINUE,
+ granule, offset, size, 0, &res);
+
+ if (len)
+ *len = res.a1;
+ return res.a0;
+}
+
+#endif /* __ASM_RSI_CMDS_H */
diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_smc.h
new file mode 100644
index 000000000000..6cb070eca9e9
--- /dev/null
+++ b/arch/arm64/include/asm/rsi_smc.h
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 ARM Ltd.
+ */
+
+#ifndef __ASM_RSI_SMC_H_
+#define __ASM_RSI_SMC_H_
+
+#include <linux/arm-smccc.h>
+
+/*
+ * This file describes the Realm Services Interface (RSI) Application Binary
+ * Interface (ABI) for SMC calls made from within the Realm to the RMM and
+ * serviced by the RMM.
+ */
+
+/*
+ * The major version number of the RSI implementation. This is increased when
+ * the binary format or semantics of the SMC calls change.
+ */
+#define RSI_ABI_VERSION_MAJOR UL(1)
+
+/*
+ * The minor version number of the RSI implementation. This is increased when
+ * a bug is fixed, or a feature is added without breaking binary compatibility.
+ */
+#define RSI_ABI_VERSION_MINOR UL(0)
+
+#define RSI_ABI_VERSION ((RSI_ABI_VERSION_MAJOR << 16) | \
+ RSI_ABI_VERSION_MINOR)
+
+#define RSI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
+#define RSI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
+
+#define RSI_SUCCESS UL(0)
+#define RSI_ERROR_INPUT UL(1)
+#define RSI_ERROR_STATE UL(2)
+#define RSI_INCOMPLETE UL(3)
+#define RSI_ERROR_UNKNOWN UL(4)
+
+#define SMC_RSI_FID(n) ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_STANDARD, \
+ n)
+
+/*
+ * Returns RSI version.
+ *
+ * arg1 == Requested interface revision
+ * ret0 == Status / error
+ * ret1 == Lower implemented interface revision
+ * ret2 == Higher implemented interface revision
+ */
+#define SMC_RSI_ABI_VERSION SMC_RSI_FID(0x190)
+
+/*
+ * Read feature register.
+ *
+ * arg1 == Feature register index
+ * ret0 == Status / error
+ * ret1 == Feature register value
+ */
+#define SMC_RSI_FEATURES SMC_RSI_FID(0x191)
+
+/*
+ * Read measurement for the current Realm.
+ *
+ * arg1 == Index, which measurements slot to read
+ * ret0 == Status / error
+ * ret1 == Measurement value, bytes: 0 - 7
+ * ret2 == Measurement value, bytes: 8 - 15
+ * ret3 == Measurement value, bytes: 16 - 23
+ * ret4 == Measurement value, bytes: 24 - 31
+ * ret5 == Measurement value, bytes: 32 - 39
+ * ret6 == Measurement value, bytes: 40 - 47
+ * ret7 == Measurement value, bytes: 48 - 55
+ * ret8 == Measurement value, bytes: 56 - 63
+ */
+#define SMC_RSI_MEASUREMENT_READ SMC_RSI_FID(0x192)
+
+/*
+ * Extend Realm Extensible Measurement (REM) value.
+ *
+ * arg1 == Index, which measurements slot to extend
+ * arg2 == Size of realm measurement in bytes, max 64 bytes
+ * arg3 == Measurement value, bytes: 0 - 7
+ * arg4 == Measurement value, bytes: 8 - 15
+ * arg5 == Measurement value, bytes: 16 - 23
+ * arg6 == Measurement value, bytes: 24 - 31
+ * arg7 == Measurement value, bytes: 32 - 39
+ * arg8 == Measurement value, bytes: 40 - 47
+ * arg9 == Measurement value, bytes: 48 - 55
+ * arg10 == Measurement value, bytes: 56 - 63
+ * ret0 == Status / error
+ */
+#define SMC_RSI_MEASUREMENT_EXTEND SMC_RSI_FID(0x193)
+
+/*
+ * Initialize the operation to retrieve an attestation token.
+ *
+ * arg1 == Challenge value, bytes: 0 - 7
+ * arg2 == Challenge value, bytes: 8 - 15
+ * arg3 == Challenge value, bytes: 16 - 23
+ * arg4 == Challenge value, bytes: 24 - 31
+ * arg5 == Challenge value, bytes: 32 - 39
+ * arg6 == Challenge value, bytes: 40 - 47
+ * arg7 == Challenge value, bytes: 48 - 55
+ * arg8 == Challenge value, bytes: 56 - 63
+ * ret0 == Status / error
+ * ret1 == Upper bound of token size in bytes
+ */
+#define SMC_RSI_ATTESTATION_TOKEN_INIT SMC_RSI_FID(0x194)
+
+/*
+ * Continue the operation to retrieve an attestation token.
+ *
+ * arg1 == The IPA of token buffer
+ * arg2 == Offset within the granule of the token buffer
+ * arg3 == Size of the granule buffer
+ * ret0 == Status / error
+ * ret1 == Length of token bytes copied to the granule buffer
+ */
+#define SMC_RSI_ATTESTATION_TOKEN_CONTINUE SMC_RSI_FID(0x195)
+
+#ifndef __ASSEMBLY__
+
+struct realm_config {
+ union {
+ struct {
+ unsigned long ipa_bits; /* Width of IPA in bits */
+ unsigned long hash_algo; /* Hash algorithm */
+ };
+ u8 pad[0x200];
+ };
+ union {
+ u8 rpv[64]; /* Realm Personalization Value */
+ u8 pad2[0xe00];
+ };
+ /*
+ * The RMM requires the configuration structure to be aligned to a 4k
+ * boundary, ensure this happens by aligning this structure.
+ */
+} __aligned(0x1000);
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Read configuration for the current Realm.
+ *
+ * arg1 == struct realm_config addr
+ * ret0 == Status / error
+ */
+#define SMC_RSI_REALM_CONFIG SMC_RSI_FID(0x196)
+
+/*
+ * Request RIPAS of a target IPA range to be changed to a specified value.
+ *
+ * arg1 == Base IPA address of target region
+ * arg2 == Top of the region
+ * arg3 == RIPAS value
+ * arg4 == flags
+ * ret0 == Status / error
+ * ret1 == Top of modified IPA range
+ * ret2 == Whether the Host accepted or rejected the request
+ */
+#define SMC_RSI_IPA_STATE_SET SMC_RSI_FID(0x197)
+
+#define RSI_NO_CHANGE_DESTROYED UL(0)
+#define RSI_CHANGE_DESTROYED UL(1)
+
+#define RSI_ACCEPT UL(0)
+#define RSI_REJECT UL(1)
+
+/*
+ * Get RIPAS of a target IPA range.
+ *
+ * arg1 == Base IPA of target region
+ * arg2 == End of target IPA region
+ * ret0 == Status / error
+ * ret1 == Top of IPA region which has the reported RIPAS value
+ * ret2 == RIPAS value
+ */
+#define SMC_RSI_IPA_STATE_GET SMC_RSI_FID(0x198)
+
+/*
+ * Make a Host call.
+ *
+ * arg1 == IPA of host call structure
+ * ret0 == Status / error
+ */
+#define SMC_RSI_HOST_CALL SMC_RSI_FID(0x199)
+
+#endif /* __ASM_RSI_SMC_H_ */
diff --git a/arch/arm64/include/asm/scs.h b/arch/arm64/include/asm/scs.h
index 2e010ea76be2..a76f9b387a26 100644
--- a/arch/arm64/include/asm/scs.h
+++ b/arch/arm64/include/asm/scs.h
@@ -46,8 +46,14 @@ static inline void dynamic_scs_init(void)
static inline void dynamic_scs_init(void) {}
#endif
+enum {
+ EDYNSCS_INVALID_CIE_HEADER = 1,
+ EDYNSCS_INVALID_CIE_SDATA_SIZE = 2,
+ EDYNSCS_INVALID_FDE_AUGM_DATA_SIZE = 3,
+ EDYNSCS_INVALID_CFA_OPCODE = 4,
+};
+
int __pi_scs_patch(const u8 eh_frame[], int size);
-asmlinkage void __pi_scs_patch_vmlinux(void);
#endif /* __ASSEMBLY __ */
diff --git a/arch/arm64/include/asm/set_memory.h b/arch/arm64/include/asm/set_memory.h
index 917761feeffd..90f61b17275e 100644
--- a/arch/arm64/include/asm/set_memory.h
+++ b/arch/arm64/include/asm/set_memory.h
@@ -13,6 +13,10 @@ int set_memory_valid(unsigned long addr, int numpages, int enable);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
bool kernel_page_present(struct page *page);
+int set_memory_encrypted(unsigned long addr, int numpages);
+int set_memory_decrypted(unsigned long addr, int numpages);
+
#endif /* _ASM_ARM64_SET_MEMORY_H */
diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h
index 11ab1c077697..7cde3d8bd0ad 100644
--- a/arch/arm64/include/asm/spinlock_types.h
+++ b/arch/arm64/include/asm/spinlock_types.h
@@ -6,7 +6,7 @@
#define __ASM_SPINLOCK_TYPES_H
#if !defined(__LINUX_SPINLOCK_TYPES_RAW_H) && !defined(__ASM_SPINLOCK_H)
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
#include <asm-generic/qspinlock_types.h>
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index f63dc654e545..821a8fdd31af 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -60,13 +60,27 @@ static inline void unwind_init_common(struct unwind_state *state)
state->stack = stackinfo_get_unknown();
}
-static struct stack_info *unwind_find_next_stack(const struct unwind_state *state,
- unsigned long sp,
- unsigned long size)
+/**
+ * unwind_find_stack() - Find the accessible stack which entirely contains an
+ * object.
+ *
+ * @state: the current unwind state.
+ * @sp: the base address of the object.
+ * @size: the size of the object.
+ *
+ * Return: a pointer to the relevant stack_info if found; NULL otherwise.
+ */
+static struct stack_info *unwind_find_stack(struct unwind_state *state,
+ unsigned long sp,
+ unsigned long size)
{
- for (int i = 0; i < state->nr_stacks; i++) {
- struct stack_info *info = &state->stacks[i];
+ struct stack_info *info = &state->stack;
+ if (stackinfo_on_stack(info, sp, size))
+ return info;
+
+ for (int i = 0; i < state->nr_stacks; i++) {
+ info = &state->stacks[i];
if (stackinfo_on_stack(info, sp, size))
return info;
}
@@ -75,36 +89,31 @@ static struct stack_info *unwind_find_next_stack(const struct unwind_state *stat
}
/**
- * unwind_consume_stack() - Check if an object is on an accessible stack,
- * updating stack boundaries so that future unwind steps cannot consume this
- * object again.
+ * unwind_consume_stack() - Update stack boundaries so that future unwind steps
+ * cannot consume this object again.
*
* @state: the current unwind state.
+ * @info: the stack_info of the stack containing the object.
* @sp: the base address of the object.
* @size: the size of the object.
*
* Return: 0 upon success, an error code otherwise.
*/
-static inline int unwind_consume_stack(struct unwind_state *state,
- unsigned long sp,
- unsigned long size)
+static inline void unwind_consume_stack(struct unwind_state *state,
+ struct stack_info *info,
+ unsigned long sp,
+ unsigned long size)
{
- struct stack_info *next;
-
- if (stackinfo_on_stack(&state->stack, sp, size))
- goto found;
-
- next = unwind_find_next_stack(state, sp, size);
- if (!next)
- return -EINVAL;
+ struct stack_info tmp;
/*
* Stack transitions are strictly one-way, and once we've
* transitioned from one stack to another, it's never valid to
* unwind back to the old stack.
*
- * Remove the current stack from the list of stacks so that it cannot
- * be found on a subsequent transition.
+ * Destroy the old stack info so that it cannot be found upon a
+ * subsequent transition. If the stack has not changed, we'll
+ * immediately restore the current stack info.
*
* Note that stacks can nest in several valid orders, e.g.
*
@@ -115,16 +124,15 @@ static inline int unwind_consume_stack(struct unwind_state *state,
* ... so we do not check the specific order of stack
* transitions.
*/
- state->stack = *next;
- *next = stackinfo_get_unknown();
+ tmp = *info;
+ *info = stackinfo_get_unknown();
+ state->stack = tmp;
-found:
/*
* Future unwind steps can only consume stack above this frame record.
* Update the current stack to start immediately above it.
*/
state->stack.low = sp + size;
- return 0;
}
/**
@@ -137,21 +145,25 @@ found:
static inline int
unwind_next_frame_record(struct unwind_state *state)
{
+ struct stack_info *info;
+ struct frame_record *record;
unsigned long fp = state->fp;
- int err;
if (fp & 0x7)
return -EINVAL;
- err = unwind_consume_stack(state, fp, 16);
- if (err)
- return err;
+ info = unwind_find_stack(state, fp, sizeof(*record));
+ if (!info)
+ return -EINVAL;
+
+ unwind_consume_stack(state, info, fp, sizeof(*record));
/*
* Record this frame record's values.
*/
- state->fp = READ_ONCE(*(unsigned long *)(fp));
- state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+ record = (struct frame_record *)fp;
+ state->fp = READ_ONCE(record->fp);
+ state->pc = READ_ONCE(record->lr);
return 0;
}
diff --git a/arch/arm64/include/asm/stacktrace/frame.h b/arch/arm64/include/asm/stacktrace/frame.h
new file mode 100644
index 000000000000..0ee0f6ba0fd8
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace/frame.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_STACKTRACE_FRAME_H
+#define __ASM_STACKTRACE_FRAME_H
+
+/*
+ * - FRAME_META_TYPE_NONE
+ *
+ * This value is reserved.
+ *
+ * - FRAME_META_TYPE_FINAL
+ *
+ * The record is the last entry on the stack.
+ * Unwinding should terminate successfully.
+ *
+ * - FRAME_META_TYPE_PT_REGS
+ *
+ * The record is embedded within a struct pt_regs, recording the registers at
+ * an arbitrary point in time.
+ * Unwinding should consume pt_regs::pc, followed by pt_regs::lr.
+ *
+ * Note: all other values are reserved and should result in unwinding
+ * terminating with an error.
+ */
+#define FRAME_META_TYPE_NONE 0
+#define FRAME_META_TYPE_FINAL 1
+#define FRAME_META_TYPE_PT_REGS 2
+
+#ifndef __ASSEMBLY__
+/*
+ * A standard AAPCS64 frame record.
+ */
+struct frame_record {
+ u64 fp;
+ u64 lr;
+};
+
+/*
+ * A metadata frame record indicating a special unwind.
+ * The record::{fp,lr} fields must be zero to indicate the presence of
+ * metadata.
+ */
+struct frame_record_meta {
+ struct frame_record record;
+ u64 type;
+};
+#endif /* __ASSEMBLY */
+
+#endif /* __ASM_STACKTRACE_FRAME_H */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 9ea97dddefc4..b8303a83c0bf 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -542,18 +542,6 @@
#define SYS_MAIR_EL2 sys_reg(3, 4, 10, 2, 0)
#define SYS_AMAIR_EL2 sys_reg(3, 4, 10, 3, 0)
-#define SYS_MPAMHCR_EL2 sys_reg(3, 4, 10, 4, 0)
-#define SYS_MPAMVPMV_EL2 sys_reg(3, 4, 10, 4, 1)
-#define SYS_MPAM2_EL2 sys_reg(3, 4, 10, 5, 0)
-#define __SYS__MPAMVPMx_EL2(x) sys_reg(3, 4, 10, 6, x)
-#define SYS_MPAMVPM0_EL2 __SYS__MPAMVPMx_EL2(0)
-#define SYS_MPAMVPM1_EL2 __SYS__MPAMVPMx_EL2(1)
-#define SYS_MPAMVPM2_EL2 __SYS__MPAMVPMx_EL2(2)
-#define SYS_MPAMVPM3_EL2 __SYS__MPAMVPMx_EL2(3)
-#define SYS_MPAMVPM4_EL2 __SYS__MPAMVPMx_EL2(4)
-#define SYS_MPAMVPM5_EL2 __SYS__MPAMVPMx_EL2(5)
-#define SYS_MPAMVPM6_EL2 __SYS__MPAMVPMx_EL2(6)
-#define SYS_MPAMVPM7_EL2 __SYS__MPAMVPMx_EL2(7)
#define SYS_VBAR_EL2 sys_reg(3, 4, 12, 0, 0)
#define SYS_RVBAR_EL2 sys_reg(3, 4, 12, 0, 1)
@@ -1101,6 +1089,26 @@
/* Initial value for Permission Overlay Extension for EL0 */
#define POR_EL0_INIT POE_RXW
+/*
+ * Definitions for Guarded Control Stack
+ */
+
+#define GCS_CAP_ADDR_MASK GENMASK(63, 12)
+#define GCS_CAP_ADDR_SHIFT 12
+#define GCS_CAP_ADDR_WIDTH 52
+#define GCS_CAP_ADDR(x) FIELD_GET(GCS_CAP_ADDR_MASK, x)
+
+#define GCS_CAP_TOKEN_MASK GENMASK(11, 0)
+#define GCS_CAP_TOKEN_SHIFT 0
+#define GCS_CAP_TOKEN_WIDTH 12
+#define GCS_CAP_TOKEN(x) FIELD_GET(GCS_CAP_TOKEN_MASK, x)
+
+#define GCS_CAP_VALID_TOKEN 0x1
+#define GCS_CAP_IN_PROGRESS_TOKEN 0x5
+
+#define GCS_CAP(x) ((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \
+ GCS_CAP_VALID_TOKEN)
+
#define ARM64_FEATURE_FIELD_BITS 4
/* Defined for compatibility only, do not add new users. */
diff --git a/arch/arm64/include/asm/patching.h b/arch/arm64/include/asm/text-patching.h
index 587bdb91ab7a..587bdb91ab7a 100644
--- a/arch/arm64/include/asm/patching.h
+++ b/arch/arm64/include/asm/text-patching.h
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 95fbc8c05607..bc94e036a26b 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -431,6 +431,23 @@ do { \
#define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \
__flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false, kvm_lpa2_is_enabled());
+static inline bool __flush_tlb_range_limit_excess(unsigned long start,
+ unsigned long end, unsigned long pages, unsigned long stride)
+{
+ /*
+ * When the system does not support TLB range based flush
+ * operation, (MAX_DVM_OPS - 1) pages can be handled. But
+ * with TLB range based operation, MAX_TLBI_RANGE_PAGES
+ * pages can be handled.
+ */
+ if ((!system_supports_tlb_range() &&
+ (end - start) >= (MAX_DVM_OPS * stride)) ||
+ pages > MAX_TLBI_RANGE_PAGES)
+ return true;
+
+ return false;
+}
+
static inline void __flush_tlb_range_nosync(struct vm_area_struct *vma,
unsigned long start, unsigned long end,
unsigned long stride, bool last_level,
@@ -442,15 +459,7 @@ static inline void __flush_tlb_range_nosync(struct vm_area_struct *vma,
end = round_up(end, stride);
pages = (end - start) >> PAGE_SHIFT;
- /*
- * When not uses TLB range ops, we can handle up to
- * (MAX_DVM_OPS - 1) pages;
- * When uses TLB range ops, we can handle up to
- * MAX_TLBI_RANGE_PAGES pages.
- */
- if ((!system_supports_tlb_range() &&
- (end - start) >= (MAX_DVM_OPS * stride)) ||
- pages > MAX_TLBI_RANGE_PAGES) {
+ if (__flush_tlb_range_limit_excess(start, end, pages, stride)) {
flush_tlb_mm(vma->vm_mm);
return;
}
@@ -492,19 +501,21 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
- unsigned long addr;
+ const unsigned long stride = PAGE_SIZE;
+ unsigned long pages;
- if ((end - start) > (MAX_DVM_OPS * PAGE_SIZE)) {
+ start = round_down(start, stride);
+ end = round_up(end, stride);
+ pages = (end - start) >> PAGE_SHIFT;
+
+ if (__flush_tlb_range_limit_excess(start, end, pages, stride)) {
flush_tlb_all();
return;
}
- start = __TLBI_VADDR(start, 0);
- end = __TLBI_VADDR(end, 0);
-
dsb(ishst);
- for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12))
- __tlbi(vaale1is, addr);
+ __flush_tlb_range_op(vaale1is, start, pages, stride, 0,
+ TLBI_TTL_UNKNOWN, false, lpa2_is_enabled());
dsb(ish);
isb();
}
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h
index 5fc3af9f8f29..341174bf9106 100644
--- a/arch/arm64/include/asm/topology.h
+++ b/arch/arm64/include/asm/topology.h
@@ -26,10 +26,6 @@ void update_freq_counters_refs(void);
#define arch_scale_freq_invariant topology_scale_freq_invariant
#define arch_scale_freq_ref topology_get_freq_ref
-#ifdef CONFIG_ACPI_CPPC_LIB
-#define arch_init_invariance_cppc topology_init_cpu_capacity_cppc
-#endif
-
/* Replace task scheduler's default cpu-invariant accounting */
#define arch_scale_cpu_capacity topology_get_cpu_scale
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 1aa4ecb73429..5b91803201ef 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -502,4 +502,44 @@ static inline size_t probe_subpage_writeable(const char __user *uaddr,
#endif /* CONFIG_ARCH_HAS_SUBPAGE_FAULTS */
+#ifdef CONFIG_ARM64_GCS
+
+static inline int gcssttr(unsigned long __user *addr, unsigned long val)
+{
+ register unsigned long __user *_addr __asm__ ("x0") = addr;
+ register unsigned long _val __asm__ ("x1") = val;
+ int err = 0;
+
+ /* GCSSTTR x1, x0 */
+ asm volatile(
+ "1: .inst 0xd91f1c01\n"
+ "2: \n"
+ _ASM_EXTABLE_UACCESS_ERR(1b, 2b, %w0)
+ : "+r" (err)
+ : "rZ" (_val), "r" (_addr)
+ : "memory");
+
+ return err;
+}
+
+static inline void put_user_gcs(unsigned long val, unsigned long __user *addr,
+ int *err)
+{
+ int ret;
+
+ if (!access_ok((char __user *)addr, sizeof(u64))) {
+ *err = -EFAULT;
+ return;
+ }
+
+ uaccess_ttbr0_enable();
+ ret = gcssttr(addr, val);
+ if (ret != 0)
+ *err = ret;
+ uaccess_ttbr0_disable();
+}
+
+
+#endif /* CONFIG_ARM64_GCS */
+
#endif /* __ASM_UACCESS_H */
diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 4305995c8f82..3e3c3fdb1842 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -5,13 +5,6 @@
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H
-/*
- * Default link address for the vDSO.
- * Since we randomise the VDSO mapping, there's little point in trying
- * to prelink this.
- */
-#define VDSO_LBASE 0x0
-
#define __VVAR_PAGES 2
#ifndef __ASSEMBLY__
@@ -20,7 +13,7 @@
#define VDSO_SYMBOL(base, name) \
({ \
- (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
+ (void *)(vdso_offset_##name + (unsigned long)(base)); \
})
extern char vdso_start[], vdso_end[];
diff --git a/arch/arm64/include/asm/vdso/vsyscall.h b/arch/arm64/include/asm/vdso/vsyscall.h
index 5b6d0dd3cef5..eea51946d45a 100644
--- a/arch/arm64/include/asm/vdso/vsyscall.h
+++ b/arch/arm64/include/asm/vdso/vsyscall.h
@@ -6,7 +6,6 @@
#ifndef __ASSEMBLY__
-#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
enum vvar_pages {
@@ -37,7 +36,7 @@ struct vdso_rng_data *__arm64_get_k_vdso_rnd_data(void)
#define __arch_get_k_vdso_rng_data __arm64_get_k_vdso_rnd_data
static __always_inline
-void __arm64_update_vsyscall(struct vdso_data *vdata, struct timekeeper *tk)
+void __arm64_update_vsyscall(struct vdso_data *vdata)
{
vdata[CS_HRES_COARSE].mask = VDSO_PRECISION_MASK;
vdata[CS_RAW].mask = VDSO_PRECISION_MASK;
diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm/vncr_mapping.h
index 06f8ec0906a6..4f9bbd4d6c26 100644
--- a/arch/arm64/include/asm/vncr_mapping.h
+++ b/arch/arm64/include/asm/vncr_mapping.h
@@ -50,7 +50,6 @@
#define VNCR_VBAR_EL1 0x250
#define VNCR_TCR2_EL1 0x270
#define VNCR_PIRE0_EL1 0x290
-#define VNCR_PIRE0_EL2 0x298
#define VNCR_PIR_EL1 0x2A0
#define VNCR_POR_EL1 0x2A8
#define VNCR_ICH_LR0_EL2 0x400
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index 055381b2c615..48d46b768eae 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -21,7 +21,7 @@
* HWCAP flags - for AT_HWCAP
*
* Bits 62 and 63 are reserved for use by libc.
- * Bits 32-61 are unallocated for potential use by libc.
+ * Bits 33-61 are unallocated for potential use by libc.
*/
#define HWCAP_FP (1 << 0)
#define HWCAP_ASIMD (1 << 1)
@@ -55,6 +55,7 @@
#define HWCAP_SB (1 << 29)
#define HWCAP_PACA (1 << 30)
#define HWCAP_PACG (1UL << 31)
+#define HWCAP_GCS (1UL << 32)
/*
* HWCAP2 flags - for AT_HWCAP2
@@ -124,4 +125,8 @@
#define HWCAP2_SME_SF8DP2 (1UL << 62)
#define HWCAP2_POE (1UL << 63)
+/*
+ * HWCAP3 flags - for AT_HWCAP3
+ */
+
#endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 964df31da975..66736ff04011 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -484,6 +484,12 @@ enum {
*/
#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (1ULL << 0)
+/*
+ * Shutdown caused by a PSCI v1.3 SYSTEM_OFF2 call.
+ * Valid only when the system event has a type of KVM_SYSTEM_EVENT_SHUTDOWN.
+ */
+#define KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2 (1ULL << 0)
+
/* run->fail_entry.hardware_entry_failure_reason codes. */
#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED (1ULL << 0)
diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
index 7fa2f7036aa7..0f39ba4f3efd 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -324,6 +324,14 @@ struct user_za_header {
#define ZA_PT_SIZE(vq) \
(ZA_PT_ZA_OFFSET + ZA_PT_ZA_SIZE(vq))
+/* GCS state (NT_ARM_GCS) */
+
+struct user_gcs {
+ __u64 features_enabled;
+ __u64 features_locked;
+ __u64 gcspr_el0;
+};
+
#endif /* __ASSEMBLY__ */
#endif /* _UAPI__ASM_PTRACE_H */
diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
index bb7af77a30a7..d42f7a92238b 100644
--- a/arch/arm64/include/uapi/asm/sigcontext.h
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
@@ -183,6 +183,15 @@ struct zt_context {
__u16 __reserved[3];
};
+#define GCS_MAGIC 0x47435300
+
+struct gcs_context {
+ struct _aarch64_ctx head;
+ __u64 gcspr;
+ __u64 features_enabled;
+ __u64 reserved;
+};
+
#endif /* !__ASSEMBLY__ */
#include <asm/sve_context.h>
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2b112f3b7510..71c29a2a2f19 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -33,7 +33,8 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
return_address.o cpuinfo.o cpu_errata.o \
cpufeature.o alternative.o cacheinfo.o \
smp.o smp_spin_table.o topology.o smccc-call.o \
- syscall.o proton-pack.o idle.o patching.o pi/
+ syscall.o proton-pack.o idle.o patching.o pi/ \
+ rsi.o
obj-$(CONFIG_COMPAT) += sys32.o signal32.o \
sys_compat.o
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index b21dd24b8efc..29bf85dacffe 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -12,15 +12,12 @@
#include <linux/ftrace.h>
#include <linux/kexec.h>
#include <linux/mm.h>
-#include <linux/dma-mapping.h>
#include <linux/kvm_host.h>
-#include <linux/preempt.h>
#include <linux/suspend.h>
#include <asm/cpufeature.h>
#include <asm/fixmap.h>
#include <asm/thread_info.h>
#include <asm/memory.h>
-#include <asm/signal32.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>
#include <linux/kbuild.h>
@@ -28,8 +25,6 @@
int main(void)
{
- DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
- BLANK();
DEFINE(TSK_TI_CPU, offsetof(struct task_struct, thread_info.cpu));
DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags));
DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count));
@@ -79,45 +74,27 @@ int main(void)
DEFINE(S_PSTATE, offsetof(struct pt_regs, pstate));
DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno));
DEFINE(S_SDEI_TTBR1, offsetof(struct pt_regs, sdei_ttbr1));
- DEFINE(S_PMR_SAVE, offsetof(struct pt_regs, pmr_save));
+ DEFINE(S_PMR, offsetof(struct pt_regs, pmr));
DEFINE(S_STACKFRAME, offsetof(struct pt_regs, stackframe));
+ DEFINE(S_STACKFRAME_TYPE, offsetof(struct pt_regs, stackframe.type));
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_X0, offsetof(struct __arch_ftrace_regs, regs[0]));
+ DEFINE(FREGS_X2, offsetof(struct __arch_ftrace_regs, regs[2]));
+ DEFINE(FREGS_X4, offsetof(struct __arch_ftrace_regs, regs[4]));
+ DEFINE(FREGS_X6, offsetof(struct __arch_ftrace_regs, regs[6]));
+ DEFINE(FREGS_X8, offsetof(struct __arch_ftrace_regs, regs[8]));
+ DEFINE(FREGS_FP, offsetof(struct __arch_ftrace_regs, fp));
+ DEFINE(FREGS_LR, offsetof(struct __arch_ftrace_regs, lr));
+ DEFINE(FREGS_SP, offsetof(struct __arch_ftrace_regs, sp));
+ DEFINE(FREGS_PC, offsetof(struct __arch_ftrace_regs, pc));
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
- DEFINE(FREGS_DIRECT_TRAMP, offsetof(struct ftrace_regs, direct_tramp));
-#endif
- DEFINE(FREGS_SIZE, sizeof(struct ftrace_regs));
- BLANK();
+ DEFINE(FREGS_DIRECT_TRAMP, offsetof(struct __arch_ftrace_regs, direct_tramp));
#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));
+ DEFINE(FREGS_SIZE, sizeof(struct __arch_ftrace_regs));
BLANK();
#endif
- DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id.counter));
- BLANK();
- DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm));
- DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags));
- BLANK();
- DEFINE(VM_EXEC, VM_EXEC);
- BLANK();
- DEFINE(PAGE_SZ, PAGE_SIZE);
- BLANK();
- DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE);
- DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE);
- BLANK();
- DEFINE(PREEMPT_DISABLE_OFFSET, PREEMPT_DISABLE_OFFSET);
- BLANK();
DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task));
BLANK();
DEFINE(FTR_OVR_VAL_OFFSET, offsetof(struct arm64_ftr_override, val));
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 718728a85430..6ce71f444ed8 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -103,6 +103,7 @@ static DECLARE_BITMAP(elf_hwcap, MAX_CPU_FEATURES) __read_mostly;
COMPAT_HWCAP_LPAE)
unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
unsigned int compat_elf_hwcap2 __read_mostly;
+unsigned int compat_elf_hwcap3 __read_mostly;
#endif
DECLARE_BITMAP(system_cpucaps, ARM64_NCAPS);
@@ -228,6 +229,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
};
static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_XS_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_I8MM_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_DGH_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_BF16_SHIFT, 4, 0),
@@ -291,6 +293,8 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
};
static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
+ ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_GCS),
+ FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_GCS_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SME),
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_SME_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_MPAM_frac_SHIFT, 4, 0),
@@ -684,6 +688,14 @@ static const struct arm64_ftr_bits ftr_id_dfr1[] = {
ARM64_FTR_END,
};
+static const struct arm64_ftr_bits ftr_mpamidr[] = {
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, MPAMIDR_EL1_PMG_MAX_SHIFT, MPAMIDR_EL1_PMG_MAX_WIDTH, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, MPAMIDR_EL1_VPMR_MAX_SHIFT, MPAMIDR_EL1_VPMR_MAX_WIDTH, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MPAMIDR_EL1_HAS_HCR_SHIFT, 1, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, MPAMIDR_EL1_PARTID_MAX_SHIFT, MPAMIDR_EL1_PARTID_MAX_WIDTH, 0),
+ ARM64_FTR_END,
+};
+
/*
* Common ftr bits for a 32bit register with all hidden, strict
* attributes, with 4bit feature fields and a default safe value of
@@ -804,6 +816,9 @@ static const struct __ftr_reg_entry {
ARM64_FTR_REG(SYS_ID_AA64MMFR3_EL1, ftr_id_aa64mmfr3),
ARM64_FTR_REG(SYS_ID_AA64MMFR4_EL1, ftr_id_aa64mmfr4),
+ /* Op1 = 0, CRn = 10, CRm = 4 */
+ ARM64_FTR_REG(SYS_MPAMIDR_EL1, ftr_mpamidr),
+
/* Op1 = 1, CRn = 0, CRm = 0 */
ARM64_FTR_REG(SYS_GMID_EL1, ftr_gmid),
@@ -1163,6 +1178,9 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
cpacr_restore(cpacr);
}
+ if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0))
+ init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
+
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
}
@@ -1419,6 +1437,11 @@ void update_cpu_features(int cpu,
cpacr_restore(cpacr);
}
+ if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0)) {
+ taint |= check_update_ftr_reg(SYS_MPAMIDR_EL1, cpu,
+ info->reg_mpamidr, boot->reg_mpamidr);
+ }
+
/*
* The kernel uses the LDGM/STGM instructions and the number of tags
* they read/write depends on the GMID_EL1.BS field. Check that the
@@ -2358,6 +2381,14 @@ static void cpu_enable_poe(const struct arm64_cpu_capabilities *__unused)
}
#endif
+#ifdef CONFIG_ARM64_GCS
+static void cpu_enable_gcs(const struct arm64_cpu_capabilities *__unused)
+{
+ /* GCSPR_EL0 is always readable */
+ write_sysreg_s(GCSCRE0_EL1_nTR, SYS_GCSCRE0_EL1);
+}
+#endif
+
/* Internal helper functions to match cpu capability type */
static bool
cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap)
@@ -2377,6 +2408,36 @@ cpucap_panic_on_conflict(const struct arm64_cpu_capabilities *cap)
return !!(cap->type & ARM64_CPUCAP_PANIC_ON_CONFLICT);
}
+static bool
+test_has_mpam(const struct arm64_cpu_capabilities *entry, int scope)
+{
+ if (!has_cpuid_feature(entry, scope))
+ return false;
+
+ /* Check firmware actually enabled MPAM on this cpu. */
+ return (read_sysreg_s(SYS_MPAM1_EL1) & MPAM1_EL1_MPAMEN);
+}
+
+static void
+cpu_enable_mpam(const struct arm64_cpu_capabilities *entry)
+{
+ /*
+ * Access by the kernel (at EL1) should use the reserved PARTID
+ * which is configured unrestricted. This avoids priority-inversion
+ * where latency sensitive tasks have to wait for a task that has
+ * been throttled to release the lock.
+ */
+ write_sysreg_s(0, SYS_MPAM1_EL1);
+}
+
+static bool
+test_has_mpam_hcr(const struct arm64_cpu_capabilities *entry, int scope)
+{
+ u64 idr = read_sanitised_ftr_reg(SYS_MPAMIDR_EL1);
+
+ return idr & MPAMIDR_EL1_HAS_HCR;
+}
+
static const struct arm64_cpu_capabilities arm64_features[] = {
{
.capability = ARM64_ALWAYS_BOOT,
@@ -2591,6 +2652,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, DBM)
},
#endif
+#ifdef CONFIG_ARM64_HAFT
+ {
+ .desc = "Hardware managed Access Flag for Table Descriptors",
+ /*
+ * Contrary to the page/block access flag, the table access flag
+ * cannot be emulated in software (no access fault will occur).
+ * Therefore this should be used only if it's supported system
+ * wide.
+ */
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .capability = ARM64_HAFT,
+ .matches = has_cpuid_feature,
+ ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, HAFT)
+ },
+#endif
{
.desc = "CRC32 instructions",
.capability = ARM64_HAS_CRC32,
@@ -2874,6 +2950,20 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
},
#endif
{
+ .desc = "Memory Partitioning And Monitoring",
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .capability = ARM64_MPAM,
+ .matches = test_has_mpam,
+ .cpu_enable = cpu_enable_mpam,
+ ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, MPAM, 1)
+ },
+ {
+ .desc = "Memory Partitioning And Monitoring Virtualisation",
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .capability = ARM64_MPAM_HCR,
+ .matches = test_has_mpam_hcr,
+ },
+ {
.desc = "NV1",
.capability = ARM64_HAS_HCR_NV1,
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
@@ -2890,6 +2980,16 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
ARM64_CPUID_FIELDS(ID_AA64MMFR3_EL1, S1POE, IMP)
},
#endif
+#ifdef CONFIG_ARM64_GCS
+ {
+ .desc = "Guarded Control Stack (GCS)",
+ .capability = ARM64_HAS_GCS,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .cpu_enable = cpu_enable_gcs,
+ .matches = has_cpuid_feature,
+ ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, GCS, IMP)
+ },
+#endif
{},
};
@@ -3006,6 +3106,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_CAP(ID_AA64ZFR0_EL1, F32MM, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEF32MM),
HWCAP_CAP(ID_AA64ZFR0_EL1, F64MM, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEF64MM),
#endif
+#ifdef CONFIG_ARM64_GCS
+ HWCAP_CAP(ID_AA64PFR1_EL1, GCS, IMP, CAP_HWCAP, KERNEL_HWCAP_GCS),
+#endif
HWCAP_CAP(ID_AA64PFR1_EL1, SSBS, SSBS2, CAP_HWCAP, KERNEL_HWCAP_SSBS),
#ifdef CONFIG_ARM64_BTI
HWCAP_CAP(ID_AA64PFR1_EL1, BT, IMP, CAP_HWCAP, KERNEL_HWCAP_BTI),
@@ -3396,6 +3499,36 @@ static void verify_hyp_capabilities(void)
}
}
+static void verify_mpam_capabilities(void)
+{
+ u64 cpu_idr = read_cpuid(ID_AA64PFR0_EL1);
+ u64 sys_idr = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
+ u16 cpu_partid_max, cpu_pmg_max, sys_partid_max, sys_pmg_max;
+
+ if (FIELD_GET(ID_AA64PFR0_EL1_MPAM_MASK, cpu_idr) !=
+ FIELD_GET(ID_AA64PFR0_EL1_MPAM_MASK, sys_idr)) {
+ pr_crit("CPU%d: MPAM version mismatch\n", smp_processor_id());
+ cpu_die_early();
+ }
+
+ cpu_idr = read_cpuid(MPAMIDR_EL1);
+ sys_idr = read_sanitised_ftr_reg(SYS_MPAMIDR_EL1);
+ if (FIELD_GET(MPAMIDR_EL1_HAS_HCR, cpu_idr) !=
+ FIELD_GET(MPAMIDR_EL1_HAS_HCR, sys_idr)) {
+ pr_crit("CPU%d: Missing MPAM HCR\n", smp_processor_id());
+ cpu_die_early();
+ }
+
+ cpu_partid_max = FIELD_GET(MPAMIDR_EL1_PARTID_MAX, cpu_idr);
+ cpu_pmg_max = FIELD_GET(MPAMIDR_EL1_PMG_MAX, cpu_idr);
+ sys_partid_max = FIELD_GET(MPAMIDR_EL1_PARTID_MAX, sys_idr);
+ sys_pmg_max = FIELD_GET(MPAMIDR_EL1_PMG_MAX, sys_idr);
+ if (cpu_partid_max < sys_partid_max || cpu_pmg_max < sys_pmg_max) {
+ pr_crit("CPU%d: MPAM PARTID/PMG max values are mismatched\n", smp_processor_id());
+ cpu_die_early();
+ }
+}
+
/*
* Run through the enabled system capabilities and enable() it on this CPU.
* The capabilities were decided based on the available CPUs at the boot time.
@@ -3422,6 +3555,9 @@ static void verify_local_cpu_capabilities(void)
if (is_hyp_mode_available())
verify_hyp_capabilities();
+
+ if (system_supports_mpam())
+ verify_mpam_capabilities();
}
void check_local_cpu_capabilities(void)
@@ -3499,6 +3635,11 @@ unsigned long cpu_get_elf_hwcap2(void)
return elf_hwcap[1];
}
+unsigned long cpu_get_elf_hwcap3(void)
+{
+ return elf_hwcap[2];
+}
+
static void __init setup_boot_cpu_capabilities(void)
{
/*
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 44718d0482b3..d79e88fccdfc 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -80,6 +80,7 @@ static const char *const hwcap_str[] = {
[KERNEL_HWCAP_SB] = "sb",
[KERNEL_HWCAP_PACA] = "paca",
[KERNEL_HWCAP_PACG] = "pacg",
+ [KERNEL_HWCAP_GCS] = "gcs",
[KERNEL_HWCAP_DCPODP] = "dcpodp",
[KERNEL_HWCAP_SVE2] = "sve2",
[KERNEL_HWCAP_SVEAES] = "sveaes",
@@ -478,6 +479,9 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
__cpuinfo_store_cpu_32bit(&info->aarch32);
+ if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0))
+ info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
+
cpuinfo_detect_icache_policy(info);
}
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 024a7b245056..58f047de3e1c 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -303,7 +303,6 @@ static int call_break_hook(struct pt_regs *regs, unsigned long esr)
{
struct break_hook *hook;
struct list_head *list;
- int (*fn)(struct pt_regs *regs, unsigned long esr) = NULL;
list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
@@ -313,10 +312,10 @@ static int call_break_hook(struct pt_regs *regs, unsigned long esr)
*/
list_for_each_entry_rcu(hook, list, node) {
if ((esr_brk_comment(esr) & ~hook->mask) == hook->imm)
- fn = hook->fn;
+ return hook->fn(regs, esr);
}
- return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
+ return DBG_HOOK_ERROR;
}
NOKPROBE_SYMBOL(call_break_hook);
@@ -441,6 +440,11 @@ void kernel_rewind_single_step(struct pt_regs *regs)
set_regs_spsr_ss(regs);
}
+void kernel_fastforward_single_step(struct pt_regs *regs)
+{
+ clear_regs_spsr_ss(regs);
+}
+
/* ptrace API */
void user_enable_single_step(struct task_struct *task)
{
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 712718aed5dd..1d25d8899dbf 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -34,8 +34,16 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
u64 attr = md->attribute;
u32 type = md->type;
- if (type == EFI_MEMORY_MAPPED_IO)
- return PROT_DEVICE_nGnRE;
+ if (type == EFI_MEMORY_MAPPED_IO) {
+ pgprot_t prot = __pgprot(PROT_DEVICE_nGnRE);
+
+ if (arm64_is_protected_mmio(md->phys_addr,
+ md->num_pages << EFI_PAGE_SHIFT))
+ prot = pgprot_encrypted(prot);
+ else
+ prot = pgprot_decrypted(prot);
+ return pgprot_val(prot);
+ }
if (region_is_misaligned(md)) {
static bool __initdata code_is_misaligned;
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 3fcd9d080bf2..b260ddc4d3e9 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -463,6 +463,24 @@ static void noinstr el1_bti(struct pt_regs *regs, unsigned long esr)
exit_to_kernel_mode(regs);
}
+static void noinstr el1_gcs(struct pt_regs *regs, unsigned long esr)
+{
+ enter_from_kernel_mode(regs);
+ local_daif_inherit(regs);
+ do_el1_gcs(regs, esr);
+ local_daif_mask();
+ exit_to_kernel_mode(regs);
+}
+
+static void noinstr el1_mops(struct pt_regs *regs, unsigned long esr)
+{
+ enter_from_kernel_mode(regs);
+ local_daif_inherit(regs);
+ do_el1_mops(regs, esr);
+ local_daif_mask();
+ exit_to_kernel_mode(regs);
+}
+
static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
{
unsigned long far = read_sysreg(far_el1);
@@ -505,6 +523,12 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
case ESR_ELx_EC_BTI:
el1_bti(regs, esr);
break;
+ case ESR_ELx_EC_GCS:
+ el1_gcs(regs, esr);
+ break;
+ case ESR_ELx_EC_MOPS:
+ el1_mops(regs, esr);
+ break;
case ESR_ELx_EC_BREAKPT_CUR:
case ESR_ELx_EC_SOFTSTP_CUR:
case ESR_ELx_EC_WATCHPT_CUR:
@@ -684,6 +708,14 @@ static void noinstr el0_mops(struct pt_regs *regs, unsigned long esr)
exit_to_user_mode(regs);
}
+static void noinstr el0_gcs(struct pt_regs *regs, unsigned long esr)
+{
+ enter_from_user_mode(regs);
+ local_daif_restore(DAIF_PROCCTX);
+ do_el0_gcs(regs, esr);
+ exit_to_user_mode(regs);
+}
+
static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr)
{
enter_from_user_mode(regs);
@@ -766,6 +798,9 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
case ESR_ELx_EC_MOPS:
el0_mops(regs, esr);
break;
+ case ESR_ELx_EC_GCS:
+ el0_gcs(regs, esr);
+ break;
case ESR_ELx_EC_BREAKPT_LOW:
case ESR_ELx_EC_SOFTSTP_LOW:
case ESR_ELx_EC_WATCHPT_LOW:
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 7ef0e127b149..5ae2a34b50bd 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -25,6 +25,7 @@
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/scs.h>
+#include <asm/stacktrace/frame.h>
#include <asm/thread_info.h>
#include <asm/asm-uaccess.h>
#include <asm/unistd.h>
@@ -284,15 +285,16 @@ alternative_else_nop_endif
stp lr, x21, [sp, #S_LR]
/*
- * For exceptions from EL0, create a final frame record.
- * For exceptions from EL1, create a synthetic frame record so the
- * interrupted code shows up in the backtrace.
+ * Create a metadata frame record. The unwinder will use this to
+ * identify and unwind exception boundaries.
*/
- .if \el == 0
stp xzr, xzr, [sp, #S_STACKFRAME]
+ .if \el == 0
+ mov x0, #FRAME_META_TYPE_FINAL
.else
- stp x29, x22, [sp, #S_STACKFRAME]
+ mov x0, #FRAME_META_TYPE_PT_REGS
.endif
+ str x0, [sp, #S_STACKFRAME_TYPE]
add x29, sp, #S_STACKFRAME
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
@@ -315,7 +317,7 @@ alternative_if_not ARM64_HAS_GIC_PRIO_MASKING
alternative_else_nop_endif
mrs_s x20, SYS_ICC_PMR_EL1
- str x20, [sp, #S_PMR_SAVE]
+ str w20, [sp, #S_PMR]
mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET
msr_s SYS_ICC_PMR_EL1, x20
@@ -342,7 +344,7 @@ alternative_if_not ARM64_HAS_GIC_PRIO_MASKING
b .Lskip_pmr_restore\@
alternative_else_nop_endif
- ldr x20, [sp, #S_PMR_SAVE]
+ ldr w20, [sp, #S_PMR]
msr_s SYS_ICC_PMR_EL1, x20
/* Ensure priority change is seen by redistributor */
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 77006df20a75..8c4c1a2186cc 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -386,7 +386,7 @@ static void task_fpsimd_load(void)
* fpsimd_save_user_state() 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
+ * memory allocated for FPSIMD registers so
* try that and hope for the best.
*/
WARN_ON_ONCE(1);
@@ -1367,6 +1367,7 @@ static void sve_init_regs(void)
} else {
fpsimd_to_sve(current);
current->thread.fp_type = FP_STATE_SVE;
+ fpsimd_flush_task_state(current);
}
}
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a650f5e11fc5..245cb419ca24 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -15,7 +15,7 @@
#include <asm/debug-monitors.h>
#include <asm/ftrace.h>
#include <asm/insn.h>
-#include <asm/patching.h>
+#include <asm/text-patching.h>
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
struct fregs_offset {
@@ -23,10 +23,10 @@ struct fregs_offset {
int offset;
};
-#define FREGS_OFFSET(n, field) \
-{ \
- .name = n, \
- .offset = offsetof(struct ftrace_regs, field), \
+#define FREGS_OFFSET(n, field) \
+{ \
+ .name = n, \
+ .offset = offsetof(struct __arch_ftrace_regs, field), \
}
static const struct fregs_offset fregs_offsets[] = {
@@ -481,7 +481,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- prepare_ftrace_return(ip, &fregs->lr, fregs->fp);
+ prepare_ftrace_return(ip, &arch_ftrace_regs(fregs)->lr, arch_ftrace_regs(fregs)->fp);
}
#else
/*
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index cb68adcabe07..5ab1970ee543 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -32,6 +32,7 @@
#include <asm/scs.h>
#include <asm/smp.h>
#include <asm/sysreg.h>
+#include <asm/stacktrace/frame.h>
#include <asm/thread_info.h>
#include <asm/virt.h>
@@ -199,6 +200,8 @@ SYM_CODE_END(preserve_boot_args)
sub sp, sp, #PT_REGS_SIZE
stp xzr, xzr, [sp, #S_STACKFRAME]
+ mov \tmp1, #FRAME_META_TYPE_FINAL
+ str \tmp1, [sp, #S_STACKFRAME_TYPE]
add x29, sp, #S_STACKFRAME
scs_load_current
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 7b11d84f533c..18749e9a6c2d 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -266,9 +266,15 @@ static int swsusp_mte_save_tags(void)
max_zone_pfn = zone_end_pfn(zone);
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
struct page *page = pfn_to_online_page(pfn);
+ struct folio *folio;
if (!page)
continue;
+ folio = page_folio(page);
+
+ if (folio_test_hugetlb(folio) &&
+ !folio_test_hugetlb_mte_tagged(folio))
+ continue;
if (!page_mte_tagged(page))
continue;
diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c
index ef48089fbfe1..fe86ada23c7d 100644
--- a/arch/arm64/kernel/io.c
+++ b/arch/arm64/kernel/io.c
@@ -10,34 +10,6 @@
#include <linux/io.h>
/*
- * Copy data from IO memory space to "real" memory space.
- */
-void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
-{
- while (count && !IS_ALIGNED((unsigned long)from, 8)) {
- *(u8 *)to = __raw_readb(from);
- from++;
- to++;
- count--;
- }
-
- while (count >= 8) {
- *(u64 *)to = __raw_readq(from);
- from += 8;
- to += 8;
- count -= 8;
- }
-
- while (count) {
- *(u8 *)to = __raw_readb(from);
- from++;
- to++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memcpy_fromio);
-
-/*
* This generates a memcpy that works on a from/to address which is aligned to
* bits. Count is in terms of the number of bits sized quantities to copy. It
* optimizes to use the STR groupings when possible so that it is WC friendly.
@@ -78,62 +50,3 @@ void __iowrite32_copy_full(void __iomem *to, const void *from, size_t count)
dgh();
}
EXPORT_SYMBOL(__iowrite32_copy_full);
-
-/*
- * Copy data from "real" memory space to IO memory space.
- */
-void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
-{
- while (count && !IS_ALIGNED((unsigned long)to, 8)) {
- __raw_writeb(*(u8 *)from, to);
- from++;
- to++;
- count--;
- }
-
- while (count >= 8) {
- __raw_writeq(*(u64 *)from, to);
- from += 8;
- to += 8;
- count -= 8;
- }
-
- while (count) {
- __raw_writeb(*(u8 *)from, to);
- from++;
- to++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memcpy_toio);
-
-/*
- * "memset" on IO memory space.
- */
-void __memset_io(volatile void __iomem *dst, int c, size_t count)
-{
- u64 qc = (u8)c;
-
- qc |= qc << 8;
- qc |= qc << 16;
- qc |= qc << 32;
-
- while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
- __raw_writeb(c, dst);
- dst++;
- count--;
- }
-
- while (count >= 8) {
- __raw_writeq(qc, dst);
- dst += 8;
- count -= 8;
- }
-
- while (count) {
- __raw_writeb(c, dst);
- dst++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memset_io);
diff --git a/arch/arm64/kernel/jump_label.c b/arch/arm64/kernel/jump_label.c
index f63ea915d6ad..b345425193d2 100644
--- a/arch/arm64/kernel/jump_label.c
+++ b/arch/arm64/kernel/jump_label.c
@@ -9,7 +9,7 @@
#include <linux/jump_label.h>
#include <linux/smp.h>
#include <asm/insn.h>
-#include <asm/patching.h>
+#include <asm/text-patching.h>
bool arch_jump_label_transform_queue(struct jump_entry *entry,
enum jump_label_type type)
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index 4e1f983df3d1..f3c4d3a8a20f 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -17,7 +17,7 @@
#include <asm/debug-monitors.h>
#include <asm/insn.h>
-#include <asm/patching.h>
+#include <asm/text-patching.h>
#include <asm/traps.h>
struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 36b25af56324..06bb680bfe97 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -462,14 +462,20 @@ int module_finalize(const Elf_Ehdr *hdr,
struct module *me)
{
const Elf_Shdr *s;
+ int ret;
+
s = find_section(hdr, sechdrs, ".altinstructions");
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)
- __pi_scs_patch((void *)s->sh_addr, s->sh_size);
+ if (s) {
+ ret = __pi_scs_patch((void *)s->sh_addr, s->sh_size);
+ if (ret)
+ pr_err("module %s: error occurred during dynamic SCS patching (%d)\n",
+ me->name, ret);
+ }
}
return module_init_ftrace_plt(hdr, sechdrs, me);
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 6174671be7c1..2fbfd27ff5f2 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -38,7 +38,24 @@ EXPORT_SYMBOL_GPL(mte_async_or_asymm_mode);
void mte_sync_tags(pte_t pte, unsigned int nr_pages)
{
struct page *page = pte_page(pte);
- unsigned int i;
+ struct folio *folio = page_folio(page);
+ unsigned long i;
+
+ if (folio_test_hugetlb(folio)) {
+ unsigned long nr = folio_nr_pages(folio);
+
+ /* Hugetlb MTE flags are set for head page only */
+ if (folio_try_hugetlb_mte_tagging(folio)) {
+ for (i = 0; i < nr; i++, page++)
+ mte_clear_page_tags(page_address(page));
+ folio_set_hugetlb_mte_tagged(folio);
+ }
+
+ /* ensure the tags are visible before the PTE is set */
+ smp_wmb();
+
+ return;
+ }
/* if PG_mte_tagged is set, tags have already been initialised */
for (i = 0; i < nr_pages; i++, page++) {
@@ -410,6 +427,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
void *maddr;
struct page *page = get_user_page_vma_remote(mm, addr,
gup_flags, &vma);
+ struct folio *folio;
if (IS_ERR(page)) {
err = PTR_ERR(page);
@@ -428,7 +446,12 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
put_page(page);
break;
}
- WARN_ON_ONCE(!page_mte_tagged(page));
+
+ folio = page_folio(page);
+ if (folio_test_hugetlb(folio))
+ WARN_ON_ONCE(!folio_test_hugetlb_mte_tagged(folio));
+ else
+ WARN_ON_ONCE(!page_mte_tagged(page));
/* limit access to the end of the page */
offset = offset_in_page(addr);
diff --git a/arch/arm64/kernel/patching.c b/arch/arm64/kernel/patching.c
index 945df74005c7..7f99723fbb8c 100644
--- a/arch/arm64/kernel/patching.c
+++ b/arch/arm64/kernel/patching.c
@@ -10,7 +10,7 @@
#include <asm/fixmap.h>
#include <asm/insn.h>
#include <asm/kprobes.h>
-#include <asm/patching.h>
+#include <asm/text-patching.h>
#include <asm/sections.h>
static DEFINE_RAW_SPINLOCK(patch_lock);
diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c
index e8ed5673f481..9b7f26b128b5 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -38,31 +38,3 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
arch_stack_walk(callchain_trace, entry, current, regs);
}
-
-unsigned long perf_instruction_pointer(struct pt_regs *regs)
-{
- if (perf_guest_state())
- return perf_guest_get_ip();
-
- return instruction_pointer(regs);
-}
-
-unsigned long perf_misc_flags(struct pt_regs *regs)
-{
- unsigned int guest_state = perf_guest_state();
- int misc = 0;
-
- if (guest_state) {
- if (guest_state & PERF_GUEST_USER)
- misc |= PERF_RECORD_MISC_GUEST_USER;
- else
- misc |= PERF_RECORD_MISC_GUEST_KERNEL;
- } else {
- if (user_mode(regs))
- misc |= PERF_RECORD_MISC_USER;
- else
- misc |= PERF_RECORD_MISC_KERNEL;
- }
-
- return misc;
-}
diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
index 29d4b6244a6f..22159251eb3a 100644
--- a/arch/arm64/kernel/pi/idreg-override.c
+++ b/arch/arm64/kernel/pi/idreg-override.c
@@ -38,6 +38,15 @@ struct ftr_set_desc {
#define FIELD(n, s, f) { .name = n, .shift = s, .width = 4, .filter = f }
+static const struct ftr_set_desc mmfr0 __prel64_initconst = {
+ .name = "id_aa64mmfr0",
+ .override = &id_aa64mmfr0_override,
+ .fields = {
+ FIELD("ecv", ID_AA64MMFR0_EL1_ECV_SHIFT, NULL),
+ {}
+ },
+};
+
static bool __init mmfr1_vh_filter(u64 val)
{
/*
@@ -133,6 +142,7 @@ static const struct ftr_set_desc pfr1 __prel64_initconst = {
.override = &id_aa64pfr1_override,
.fields = {
FIELD("bt", ID_AA64PFR1_EL1_BT_SHIFT, NULL ),
+ FIELD("gcs", ID_AA64PFR1_EL1_GCS_SHIFT, NULL),
FIELD("mte", ID_AA64PFR1_EL1_MTE_SHIFT, NULL),
FIELD("sme", ID_AA64PFR1_EL1_SME_SHIFT, pfr1_sme_filter),
{}
@@ -196,6 +206,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
static const
PREL64(const struct ftr_set_desc, reg) regs[] __prel64_initconst = {
+ { &mmfr0 },
{ &mmfr1 },
{ &mmfr2 },
{ &pfr0 },
@@ -215,6 +226,7 @@ static const struct {
{ "arm64.nosve", "id_aa64pfr0.sve=0" },
{ "arm64.nosme", "id_aa64pfr1.sme=0" },
{ "arm64.nobti", "id_aa64pfr1.bt=0" },
+ { "arm64.nogcs", "id_aa64pfr1.gcs=0" },
{ "arm64.nopauth",
"id_aa64isar1.gpi=0 id_aa64isar1.gpa=0 "
"id_aa64isar1.api=0 id_aa64isar1.apa=0 "
diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
index 5410b2cac590..2b69e3beeef8 100644
--- a/arch/arm64/kernel/pi/map_range.c
+++ b/arch/arm64/kernel/pi/map_range.c
@@ -30,7 +30,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot,
int level, pte_t *tbl, bool may_use_cont, u64 va_offset)
{
u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX;
- u64 protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
+ pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK;
int lshift = (3 - level) * (PAGE_SHIFT - 3);
u64 lmask = (PAGE_SIZE << lshift) - 1;
diff --git a/arch/arm64/kernel/pi/patch-scs.c b/arch/arm64/kernel/pi/patch-scs.c
index 49d8b40e61bc..55d0cd64ef71 100644
--- a/arch/arm64/kernel/pi/patch-scs.c
+++ b/arch/arm64/kernel/pi/patch-scs.c
@@ -50,6 +50,10 @@ bool dynamic_scs_is_enabled;
#define DW_CFA_GNU_negative_offset_extended 0x2f
#define DW_CFA_hi_user 0x3f
+#define DW_EH_PE_sdata4 0x0b
+#define DW_EH_PE_sdata8 0x0c
+#define DW_EH_PE_pcrel 0x10
+
enum {
PACIASP = 0xd503233f,
AUTIASP = 0xd50323bf,
@@ -120,7 +124,12 @@ struct eh_frame {
union {
struct { // CIE
u8 version;
- u8 augmentation_string[];
+ u8 augmentation_string[3];
+ u8 code_alignment_factor;
+ u8 data_alignment_factor;
+ u8 return_address_register;
+ u8 augmentation_data_size;
+ u8 fde_pointer_format;
};
struct { // FDE
@@ -128,29 +137,38 @@ struct eh_frame {
s32 range;
u8 opcodes[];
};
+
+ struct { // FDE
+ s64 initial_loc64;
+ s64 range64;
+ u8 opcodes64[];
+ };
};
};
static int scs_handle_fde_frame(const struct eh_frame *frame,
- bool fde_has_augmentation_data,
int code_alignment_factor,
+ bool use_sdata8,
bool dry_run)
{
int size = frame->size - offsetof(struct eh_frame, opcodes) + 4;
u64 loc = (u64)offset_to_ptr(&frame->initial_loc);
const u8 *opcode = frame->opcodes;
+ int l;
- if (fde_has_augmentation_data) {
- int l;
+ if (use_sdata8) {
+ loc = (u64)&frame->initial_loc64 + frame->initial_loc64;
+ opcode = frame->opcodes64;
+ size -= 8;
+ }
- // assume single byte uleb128_t
- if (WARN_ON(*opcode & BIT(7)))
- return -ENOEXEC;
+ // assume single byte uleb128_t for augmentation data size
+ if (*opcode & BIT(7))
+ return EDYNSCS_INVALID_FDE_AUGM_DATA_SIZE;
- l = *opcode++;
- opcode += l;
- size -= l + 1;
- }
+ l = *opcode++;
+ opcode += l;
+ size -= l + 1;
/*
* Starting from 'loc', apply the CFA opcodes that advance the location
@@ -201,7 +219,7 @@ static int scs_handle_fde_frame(const struct eh_frame *frame,
break;
default:
- return -ENOEXEC;
+ return EDYNSCS_INVALID_CFA_OPCODE;
}
}
return 0;
@@ -209,12 +227,12 @@ static int scs_handle_fde_frame(const struct eh_frame *frame,
int scs_patch(const u8 eh_frame[], int size)
{
+ int code_alignment_factor = 1;
+ bool fde_use_sdata8 = false;
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 ||
@@ -223,28 +241,47 @@ int scs_patch(const u8 eh_frame[], int 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';
+ /*
+ * Require presence of augmentation data (z) with a
+ * specifier for the size of the FDE initial_loc and
+ * range fields (R), and nothing else.
+ */
+ if (strcmp(frame->augmentation_string, "zR"))
+ return EDYNSCS_INVALID_CIE_HEADER;
/*
* 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.
+ * there is no point in decoding the whole thing. Also
+ * sanity check the size of the data alignment factor
+ * field, and the values of the return address register
+ * and augmentation data size fields.
*/
- p += strlen(p) + 1;
- if (!WARN_ON(*p & BIT(7)))
- code_alignment_factor = *p;
+ if ((frame->code_alignment_factor & BIT(7)) ||
+ (frame->data_alignment_factor & BIT(7)) ||
+ frame->return_address_register != 30 ||
+ frame->augmentation_data_size != 1)
+ return EDYNSCS_INVALID_CIE_HEADER;
+
+ code_alignment_factor = frame->code_alignment_factor;
+
+ switch (frame->fde_pointer_format) {
+ case DW_EH_PE_pcrel | DW_EH_PE_sdata4:
+ fde_use_sdata8 = false;
+ break;
+ case DW_EH_PE_pcrel | DW_EH_PE_sdata8:
+ fde_use_sdata8 = true;
+ break;
+ default:
+ return EDYNSCS_INVALID_CIE_SDATA_SIZE;
+ }
} else {
- ret = scs_handle_fde_frame(frame,
- fde_has_augmentation_data,
- code_alignment_factor,
- true);
+ ret = scs_handle_fde_frame(frame, code_alignment_factor,
+ fde_use_sdata8, true);
if (ret)
return ret;
- scs_handle_fde_frame(frame, fde_has_augmentation_data,
- code_alignment_factor, false);
+ scs_handle_fde_frame(frame, code_alignment_factor,
+ fde_use_sdata8, false);
}
p += sizeof(frame->size) + frame->size;
diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c
index 3496d6169e59..6438bf62e753 100644
--- a/arch/arm64/kernel/probes/decode-insn.c
+++ b/arch/arm64/kernel/probes/decode-insn.c
@@ -58,10 +58,13 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn)
* Instructions which load PC relative literals are not going to work
* when executed from an XOL slot. Instructions doing an exclusive
* load/store are not going to complete successfully when single-step
- * exception handling happens in the middle of the sequence.
+ * exception handling happens in the middle of the sequence. Memory
+ * copy/set instructions require that all three instructions be placed
+ * consecutively in memory.
*/
if (aarch64_insn_uses_literal(insn) ||
- aarch64_insn_is_exclusive(insn))
+ aarch64_insn_is_exclusive(insn) ||
+ aarch64_insn_is_mops(insn))
return false;
return true;
@@ -73,9 +76,18 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn)
* INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
*/
enum probe_insn __kprobes
-arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api)
+arm_probe_decode_insn(u32 insn, struct arch_probe_insn *api)
{
/*
+ * While 'nop' instruction can execute in the out-of-line slot,
+ * simulating them in breakpoint handling offers better performance.
+ */
+ if (aarch64_insn_is_nop(insn)) {
+ api->handler = simulate_nop;
+ return INSN_GOOD_NO_SLOT;
+ }
+
+ /*
* Instructions reading or modifying the PC won't work from the XOL
* slot.
*/
@@ -133,8 +145,8 @@ enum probe_insn __kprobes
arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi)
{
enum probe_insn decoded;
- probe_opcode_t insn = le32_to_cpu(*addr);
- probe_opcode_t *scan_end = NULL;
+ u32 insn = le32_to_cpu(*addr);
+ kprobe_opcode_t *scan_end = NULL;
unsigned long size = 0, offset = 0;
struct arch_probe_insn *api = &asi->api;
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 8b758c5a2062..0e4195de8206 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -28,6 +28,6 @@ enum probe_insn __kprobes
arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi);
#endif
enum probe_insn __kprobes
-arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *asi);
+arm_probe_decode_insn(u32 insn, struct arch_probe_insn *asi);
#endif /* _ARM_KERNEL_KPROBES_ARM64_H */
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 4268678d0e86..d9e462eafb95 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -27,7 +27,7 @@
#include <asm/debug-monitors.h>
#include <asm/insn.h>
#include <asm/irq.h>
-#include <asm/patching.h>
+#include <asm/text-patching.h>
#include <asm/ptrace.h>
#include <asm/sections.h>
#include <asm/system_misc.h>
@@ -43,7 +43,7 @@ post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *);
static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
{
- kprobe_opcode_t *addr = p->ainsn.api.insn;
+ kprobe_opcode_t *addr = p->ainsn.xol_insn;
/*
* Prepare insn slot, Mark Rutland points out it depends on a coupe of
@@ -64,20 +64,20 @@ static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
* the BRK exception handler, so it is unnecessary to generate
* Contex-Synchronization-Event via ISB again.
*/
- aarch64_insn_patch_text_nosync(addr, p->opcode);
+ aarch64_insn_patch_text_nosync(addr, le32_to_cpu(p->opcode));
aarch64_insn_patch_text_nosync(addr + 1, BRK64_OPCODE_KPROBES_SS);
/*
* Needs restoring of return address after stepping xol.
*/
- p->ainsn.api.restore = (unsigned long) p->addr +
+ p->ainsn.xol_restore = (unsigned long) p->addr +
sizeof(kprobe_opcode_t);
}
static void __kprobes arch_prepare_simulate(struct kprobe *p)
{
/* This instructions is not executed xol. No need to adjust the PC */
- p->ainsn.api.restore = 0;
+ p->ainsn.xol_restore = 0;
}
static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
@@ -85,7 +85,7 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
if (p->ainsn.api.handler)
- p->ainsn.api.handler((u32)p->opcode, (long)p->addr, regs);
+ p->ainsn.api.handler(le32_to_cpu(p->opcode), (long)p->addr, regs);
/* single step simulated, now go for post processing */
post_kprobe_handler(p, kcb, regs);
@@ -99,7 +99,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return -EINVAL;
/* copy instruction */
- p->opcode = le32_to_cpu(*p->addr);
+ p->opcode = *p->addr;
if (search_exception_tables(probe_addr))
return -EINVAL;
@@ -110,18 +110,18 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return -EINVAL;
case INSN_GOOD_NO_SLOT: /* insn need simulation */
- p->ainsn.api.insn = NULL;
+ p->ainsn.xol_insn = NULL;
break;
case INSN_GOOD: /* instruction uses slot */
- p->ainsn.api.insn = get_insn_slot();
- if (!p->ainsn.api.insn)
+ p->ainsn.xol_insn = get_insn_slot();
+ if (!p->ainsn.xol_insn)
return -ENOMEM;
break;
}
/* prepare the instruction */
- if (p->ainsn.api.insn)
+ if (p->ainsn.xol_insn)
arch_prepare_ss_slot(p);
else
arch_prepare_simulate(p);
@@ -142,15 +142,16 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
void *addr = p->addr;
+ u32 insn = le32_to_cpu(p->opcode);
- aarch64_insn_patch_text(&addr, &p->opcode, 1);
+ aarch64_insn_patch_text(&addr, &insn, 1);
}
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
- if (p->ainsn.api.insn) {
- free_insn_slot(p->ainsn.api.insn, 0);
- p->ainsn.api.insn = NULL;
+ if (p->ainsn.xol_insn) {
+ free_insn_slot(p->ainsn.xol_insn, 0);
+ p->ainsn.xol_insn = NULL;
}
}
@@ -205,9 +206,9 @@ static void __kprobes setup_singlestep(struct kprobe *p,
}
- if (p->ainsn.api.insn) {
+ if (p->ainsn.xol_insn) {
/* prepare for single stepping */
- slot = (unsigned long)p->ainsn.api.insn;
+ slot = (unsigned long)p->ainsn.xol_insn;
kprobes_save_local_irqflag(kcb, regs);
instruction_pointer_set(regs, slot);
@@ -245,8 +246,8 @@ static void __kprobes
post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_regs *regs)
{
/* return addr restore if non-branching insn */
- if (cur->ainsn.api.restore != 0)
- instruction_pointer_set(regs, cur->ainsn.api.restore);
+ if (cur->ainsn.xol_restore != 0)
+ instruction_pointer_set(regs, cur->ainsn.xol_restore);
/* restore back original saved kprobe variables and continue */
if (kcb->kprobe_status == KPROBE_REENTER) {
@@ -348,7 +349,7 @@ kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned long esr)
struct kprobe *cur = kprobe_running();
if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) &&
- ((unsigned long)&cur->ainsn.api.insn[1] == addr)) {
+ ((unsigned long)&cur->ainsn.xol_insn[1] == addr)) {
kprobes_restore_local_irqflag(kcb, regs);
post_kprobe_handler(cur, kcb, regs);
diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c
index b65334ab79d2..4c6d2d712fbd 100644
--- a/arch/arm64/kernel/probes/simulate-insn.c
+++ b/arch/arm64/kernel/probes/simulate-insn.c
@@ -196,3 +196,9 @@ simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs)
instruction_pointer_set(regs, instruction_pointer(regs) + 4);
}
+
+void __kprobes
+simulate_nop(u32 opcode, long addr, struct pt_regs *regs)
+{
+ arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
+}
diff --git a/arch/arm64/kernel/probes/simulate-insn.h b/arch/arm64/kernel/probes/simulate-insn.h
index e065dc92218e..efb2803ec943 100644
--- a/arch/arm64/kernel/probes/simulate-insn.h
+++ b/arch/arm64/kernel/probes/simulate-insn.h
@@ -16,5 +16,6 @@ void simulate_cbz_cbnz(u32 opcode, long addr, struct pt_regs *regs);
void simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs);
void simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs);
void simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs);
+void simulate_nop(u32 opcode, long addr, struct pt_regs *regs);
#endif /* _ARM_KERNEL_KPROBES_SIMULATE_INSN_H */
diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
index a2f137a595fc..cb3d05af36e3 100644
--- a/arch/arm64/kernel/probes/uprobes.c
+++ b/arch/arm64/kernel/probes/uprobes.c
@@ -17,12 +17,20 @@ void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
void *xol_page_kaddr = kmap_atomic(page);
void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK);
+ /*
+ * Initial cache maintenance of the xol page done via set_pte_at().
+ * Subsequent CMOs only needed if the xol slot changes.
+ */
+ if (!memcmp(dst, src, len))
+ goto done;
+
/* Initialize the slot */
memcpy(dst, src, len);
/* flush caches (dcache/icache) */
sync_icache_aliases((unsigned long)dst, (unsigned long)dst + len);
+done:
kunmap_atomic(xol_page_kaddr);
}
@@ -34,7 +42,7 @@ unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
unsigned long addr)
{
- probe_opcode_t insn;
+ u32 insn;
/* TODO: Currently we do not support AARCH32 instruction probing */
if (mm->context.flags & MMCF_AARCH32)
@@ -102,7 +110,7 @@ bool arch_uprobe_xol_was_trapped(struct task_struct *t)
bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
{
- probe_opcode_t insn;
+ u32 insn;
unsigned long addr;
if (!auprobe->simulate)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 3e7c8c8195c3..2968a33bb3bc 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -49,6 +49,7 @@
#include <asm/cacheflush.h>
#include <asm/exec.h>
#include <asm/fpsimd.h>
+#include <asm/gcs.h>
#include <asm/mmu_context.h>
#include <asm/mte.h>
#include <asm/processor.h>
@@ -227,7 +228,7 @@ void __show_regs(struct pt_regs *regs)
printk("sp : %016llx\n", sp);
if (system_uses_irq_prio_masking())
- printk("pmr_save: %08llx\n", regs->pmr_save);
+ printk("pmr: %08x\n", regs->pmr);
i = top_reg;
@@ -280,6 +281,51 @@ static void flush_poe(void)
write_sysreg_s(POR_EL0_INIT, SYS_POR_EL0);
}
+#ifdef CONFIG_ARM64_GCS
+
+static void flush_gcs(void)
+{
+ if (!system_supports_gcs())
+ return;
+
+ gcs_free(current);
+ current->thread.gcs_el0_mode = 0;
+ write_sysreg_s(GCSCRE0_EL1_nTR, SYS_GCSCRE0_EL1);
+ write_sysreg_s(0, SYS_GCSPR_EL0);
+}
+
+static int copy_thread_gcs(struct task_struct *p,
+ const struct kernel_clone_args *args)
+{
+ unsigned long gcs;
+
+ if (!system_supports_gcs())
+ return 0;
+
+ p->thread.gcs_base = 0;
+ p->thread.gcs_size = 0;
+
+ gcs = gcs_alloc_thread_stack(p, args);
+ if (IS_ERR_VALUE(gcs))
+ return PTR_ERR((void *)gcs);
+
+ p->thread.gcs_el0_mode = current->thread.gcs_el0_mode;
+ p->thread.gcs_el0_locked = current->thread.gcs_el0_locked;
+
+ return 0;
+}
+
+#else
+
+static void flush_gcs(void) { }
+static int copy_thread_gcs(struct task_struct *p,
+ const struct kernel_clone_args *args)
+{
+ return 0;
+}
+
+#endif
+
void flush_thread(void)
{
fpsimd_flush_thread();
@@ -287,11 +333,13 @@ void flush_thread(void)
flush_ptrace_hw_breakpoint(current);
flush_tagged_addr_state();
flush_poe();
+ flush_gcs();
}
void arch_release_task_struct(struct task_struct *tsk)
{
fpsimd_release_task(tsk);
+ gcs_free(tsk);
}
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
@@ -355,6 +403,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
unsigned long stack_start = args->stack;
unsigned long tls = args->tls;
struct pt_regs *childregs = task_pt_regs(p);
+ int ret;
memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
@@ -399,6 +448,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
p->thread.uw.tp_value = tls;
p->thread.tpidr2_el0 = 0;
}
+
+ ret = copy_thread_gcs(p, args);
+ if (ret != 0)
+ return ret;
} else {
/*
* A kthread has no context to ERET to, so ensure any buggy
@@ -409,6 +462,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
*/
memset(childregs, 0, sizeof(struct pt_regs));
childregs->pstate = PSR_MODE_EL1h | PSR_IL_BIT;
+ childregs->stackframe.type = FRAME_META_TYPE_FINAL;
p->thread.cpu_context.x19 = (unsigned long)args->fn;
p->thread.cpu_context.x20 = (unsigned long)args->fn_arg;
@@ -422,7 +476,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
* For the benefit of the unwinder, set up childregs->stackframe
* as the final frame for the new task.
*/
- p->thread.cpu_context.fp = (unsigned long)childregs->stackframe;
+ p->thread.cpu_context.fp = (unsigned long)&childregs->stackframe;
ptrace_hw_copy_thread(p);
@@ -442,7 +496,7 @@ static void tls_thread_switch(struct task_struct *next)
if (is_compat_thread(task_thread_info(next)))
write_sysreg(next->thread.uw.tp_value, tpidrro_el0);
- else if (!arm64_kernel_unmapped_at_el0())
+ else
write_sysreg(0, tpidrro_el0);
write_sysreg(*task_user_tls(next), tpidr_el0);
@@ -487,6 +541,46 @@ static void entry_task_switch(struct task_struct *next)
__this_cpu_write(__entry_task, next);
}
+#ifdef CONFIG_ARM64_GCS
+
+void gcs_preserve_current_state(void)
+{
+ current->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0);
+}
+
+static void gcs_thread_switch(struct task_struct *next)
+{
+ if (!system_supports_gcs())
+ return;
+
+ /* GCSPR_EL0 is always readable */
+ gcs_preserve_current_state();
+ write_sysreg_s(next->thread.gcspr_el0, SYS_GCSPR_EL0);
+
+ if (current->thread.gcs_el0_mode != next->thread.gcs_el0_mode)
+ gcs_set_el0_mode(next);
+
+ /*
+ * Ensure that GCS memory effects of the 'prev' thread are
+ * ordered before other memory accesses with release semantics
+ * (or preceded by a DMB) on the current PE. In addition, any
+ * memory accesses with acquire semantics (or succeeded by a
+ * DMB) are ordered before GCS memory effects of the 'next'
+ * thread. This will ensure that the GCS memory effects are
+ * visible to other PEs in case of migration.
+ */
+ if (task_gcs_el0_enabled(current) || task_gcs_el0_enabled(next))
+ gcsb_dsync();
+}
+
+#else
+
+static void gcs_thread_switch(struct task_struct *next)
+{
+}
+
+#endif
+
/*
* Handle sysreg updates for ARM erratum 1418040 which affects the 32bit view of
* CNTVCT, various other errata which require trapping all CNTVCT{,_EL0}
@@ -583,6 +677,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
cntkctl_thread_switch(prev, next);
ptrauth_thread_switch_user(next);
permission_overlay_switch(next);
+ gcs_thread_switch(next);
/*
* Complete any pending TLB or cache maintenance on this CPU in case
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index b756578aeaee..e4437f62a2cd 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -34,6 +34,7 @@
#include <asm/cpufeature.h>
#include <asm/debug-monitors.h>
#include <asm/fpsimd.h>
+#include <asm/gcs.h>
#include <asm/mte.h>
#include <asm/pointer_auth.h>
#include <asm/stacktrace.h>
@@ -898,7 +899,11 @@ static int sve_set_common(struct task_struct *target,
if (ret)
goto out;
- /* Actual VL set may be less than the user asked for: */
+ /*
+ * Actual VL set may be different from what the user asked
+ * for, or we may have configured the _ONEXEC VL not the
+ * current VL:
+ */
vq = sve_vq_from_vl(task_get_vl(target, type));
/* Enter/exit streaming mode */
@@ -1125,7 +1130,11 @@ static int za_set(struct task_struct *target,
if (ret)
goto out;
- /* Actual VL set may be less than the user asked for: */
+ /*
+ * Actual VL set may be different from what the user asked
+ * for, or we may have configured the _ONEXEC rather than
+ * current VL:
+ */
vq = sve_vq_from_vl(task_get_sme_vl(target));
/* Ensure there is some SVE storage for streaming mode */
@@ -1473,6 +1482,52 @@ static int poe_set(struct task_struct *target, const struct
}
#endif
+#ifdef CONFIG_ARM64_GCS
+static int gcs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ struct user_gcs user_gcs;
+
+ if (!system_supports_gcs())
+ return -EINVAL;
+
+ if (target == current)
+ gcs_preserve_current_state();
+
+ user_gcs.features_enabled = target->thread.gcs_el0_mode;
+ user_gcs.features_locked = target->thread.gcs_el0_locked;
+ user_gcs.gcspr_el0 = target->thread.gcspr_el0;
+
+ return membuf_write(&to, &user_gcs, sizeof(user_gcs));
+}
+
+static int gcs_set(struct task_struct *target, const struct
+ user_regset *regset, unsigned int pos,
+ unsigned int count, const void *kbuf, const
+ void __user *ubuf)
+{
+ int ret;
+ struct user_gcs user_gcs;
+
+ if (!system_supports_gcs())
+ return -EINVAL;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_gcs, 0, -1);
+ if (ret)
+ return ret;
+
+ if (user_gcs.features_enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK)
+ return -EINVAL;
+
+ target->thread.gcs_el0_mode = user_gcs.features_enabled;
+ target->thread.gcs_el0_locked = user_gcs.features_locked;
+ target->thread.gcspr_el0 = user_gcs.gcspr_el0;
+
+ return 0;
+}
+#endif
+
enum aarch64_regset {
REGSET_GPR,
REGSET_FPR,
@@ -1503,7 +1558,10 @@ enum aarch64_regset {
REGSET_TAGGED_ADDR_CTRL,
#endif
#ifdef CONFIG_ARM64_POE
- REGSET_POE
+ REGSET_POE,
+#endif
+#ifdef CONFIG_ARM64_GCS
+ REGSET_GCS,
#endif
};
@@ -1674,6 +1732,16 @@ static const struct user_regset aarch64_regsets[] = {
.set = poe_set,
},
#endif
+#ifdef CONFIG_ARM64_GCS
+ [REGSET_GCS] = {
+ .core_note_type = NT_ARM_GCS,
+ .n = sizeof(struct user_gcs) / sizeof(u64),
+ .size = sizeof(u64),
+ .align = sizeof(u64),
+ .regset_get = gcs_get,
+ .set = gcs_set,
+ },
+#endif
};
static const struct user_regset_view user_aarch64_view = {
diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
new file mode 100644
index 000000000000..3031f25c32ef
--- /dev/null
+++ b/arch/arm64/kernel/rsi.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 ARM Ltd.
+ */
+
+#include <linux/jump_label.h>
+#include <linux/memblock.h>
+#include <linux/psci.h>
+#include <linux/swiotlb.h>
+#include <linux/cc_platform.h>
+
+#include <asm/io.h>
+#include <asm/mem_encrypt.h>
+#include <asm/rsi.h>
+
+static struct realm_config config;
+
+unsigned long prot_ns_shared;
+EXPORT_SYMBOL(prot_ns_shared);
+
+DEFINE_STATIC_KEY_FALSE_RO(rsi_present);
+EXPORT_SYMBOL(rsi_present);
+
+bool cc_platform_has(enum cc_attr attr)
+{
+ switch (attr) {
+ case CC_ATTR_MEM_ENCRYPT:
+ return is_realm_world();
+ default:
+ return false;
+ }
+}
+EXPORT_SYMBOL_GPL(cc_platform_has);
+
+static bool rsi_version_matches(void)
+{
+ unsigned long ver_lower, ver_higher;
+ unsigned long ret = rsi_request_version(RSI_ABI_VERSION,
+ &ver_lower,
+ &ver_higher);
+
+ if (ret == SMCCC_RET_NOT_SUPPORTED)
+ return false;
+
+ if (ret != RSI_SUCCESS) {
+ pr_err("RME: RMM doesn't support RSI version %lu.%lu. Supported range: %lu.%lu-%lu.%lu\n",
+ RSI_ABI_VERSION_MAJOR, RSI_ABI_VERSION_MINOR,
+ RSI_ABI_VERSION_GET_MAJOR(ver_lower),
+ RSI_ABI_VERSION_GET_MINOR(ver_lower),
+ RSI_ABI_VERSION_GET_MAJOR(ver_higher),
+ RSI_ABI_VERSION_GET_MINOR(ver_higher));
+ return false;
+ }
+
+ pr_info("RME: Using RSI version %lu.%lu\n",
+ RSI_ABI_VERSION_GET_MAJOR(ver_lower),
+ RSI_ABI_VERSION_GET_MINOR(ver_lower));
+
+ return true;
+}
+
+static void __init arm64_rsi_setup_memory(void)
+{
+ u64 i;
+ phys_addr_t start, end;
+
+ /*
+ * Iterate over the available memory ranges and convert the state to
+ * protected memory. We should take extra care to ensure that we DO NOT
+ * permit any "DESTROYED" pages to be converted to "RAM".
+ *
+ * panic() is used because if the attempt to switch the memory to
+ * protected has failed here, then future accesses to the memory are
+ * simply going to be reflected as a SEA (Synchronous External Abort)
+ * which we can't handle. Bailing out early prevents the guest limping
+ * on and dying later.
+ */
+ for_each_mem_range(i, &start, &end) {
+ if (rsi_set_memory_range_protected_safe(start, end)) {
+ panic("Failed to set memory range to protected: %pa-%pa",
+ &start, &end);
+ }
+ }
+}
+
+bool __arm64_is_protected_mmio(phys_addr_t base, size_t size)
+{
+ enum ripas ripas;
+ phys_addr_t end, top;
+
+ /* Overflow ? */
+ if (WARN_ON(base + size <= base))
+ return false;
+
+ end = ALIGN(base + size, RSI_GRANULE_SIZE);
+ base = ALIGN_DOWN(base, RSI_GRANULE_SIZE);
+
+ while (base < end) {
+ if (WARN_ON(rsi_ipa_state_get(base, end, &ripas, &top)))
+ break;
+ if (WARN_ON(top <= base))
+ break;
+ if (ripas != RSI_RIPAS_DEV)
+ break;
+ base = top;
+ }
+
+ return base >= end;
+}
+EXPORT_SYMBOL(__arm64_is_protected_mmio);
+
+static int realm_ioremap_hook(phys_addr_t phys, size_t size, pgprot_t *prot)
+{
+ if (__arm64_is_protected_mmio(phys, size))
+ *prot = pgprot_encrypted(*prot);
+ else
+ *prot = pgprot_decrypted(*prot);
+
+ return 0;
+}
+
+void __init arm64_rsi_init(void)
+{
+ if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
+ return;
+ if (!rsi_version_matches())
+ return;
+ if (WARN_ON(rsi_get_realm_config(&config)))
+ return;
+ prot_ns_shared = BIT(config.ipa_bits - 1);
+
+ if (arm64_ioremap_prot_hook_register(realm_ioremap_hook))
+ return;
+
+ if (realm_register_memory_enc_ops())
+ return;
+
+ arm64_rsi_setup_memory();
+
+ static_branch_enable(&rsi_present);
+}
+
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index b22d28ec8028..4f613e8e0745 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -43,6 +43,7 @@
#include <asm/cpu_ops.h>
#include <asm/kasan.h>
#include <asm/numa.h>
+#include <asm/rsi.h>
#include <asm/scs.h>
#include <asm/sections.h>
#include <asm/setup.h>
@@ -175,7 +176,11 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
if (dt_virt)
memblock_reserve(dt_phys, size);
- if (!dt_virt || !early_init_dt_scan(dt_virt)) {
+ /*
+ * dt_virt is a fixmap address, hence __pa(dt_virt) can't be used.
+ * Pass dt_phys directly.
+ */
+ if (!early_init_dt_scan(dt_virt, dt_phys)) {
pr_crit("\n"
"Error: invalid device tree blob at physical address %pa (virtual address 0x%px)\n"
"The dtb must be 8-byte aligned and must not exceed 2 MB in size\n"
@@ -351,6 +356,8 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
else
psci_acpi_init();
+ arm64_rsi_init();
+
init_bootcpu_ops();
smp_init_cpus();
smp_build_mpidr_hash();
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index c7d311d8b92a..14ac6fdb872b 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -26,6 +26,7 @@
#include <asm/elf.h>
#include <asm/exception.h>
#include <asm/cacheflush.h>
+#include <asm/gcs.h>
#include <asm/ucontext.h>
#include <asm/unistd.h>
#include <asm/fpsimd.h>
@@ -35,6 +36,15 @@
#include <asm/traps.h>
#include <asm/vdso.h>
+#ifdef CONFIG_ARM64_GCS
+#define GCS_SIGNAL_CAP(addr) (((unsigned long)addr) & GCS_CAP_ADDR_MASK)
+
+static bool gcs_signal_cap_valid(u64 addr, u64 val)
+{
+ return val == GCS_SIGNAL_CAP(addr);
+}
+#endif
+
/*
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
*/
@@ -43,11 +53,6 @@ struct rt_sigframe {
struct ucontext uc;
};
-struct frame_record {
- u64 fp;
- u64 lr;
-};
-
struct rt_sigframe_user_layout {
struct rt_sigframe __user *sigframe;
struct frame_record __user *next_frame;
@@ -57,6 +62,7 @@ struct rt_sigframe_user_layout {
unsigned long fpsimd_offset;
unsigned long esr_offset;
+ unsigned long gcs_offset;
unsigned long sve_offset;
unsigned long tpidr2_offset;
unsigned long za_offset;
@@ -79,7 +85,6 @@ struct user_access_state {
u64 por_el0;
};
-#define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16)
#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
@@ -242,6 +247,8 @@ struct user_ctxs {
u32 fpmr_size;
struct poe_context __user *poe;
u32 poe_size;
+ struct gcs_context __user *gcs;
+ u32 gcs_size;
};
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
@@ -689,6 +696,82 @@ extern int restore_zt_context(struct user_ctxs *user);
#endif /* ! CONFIG_ARM64_SME */
+#ifdef CONFIG_ARM64_GCS
+
+static int preserve_gcs_context(struct gcs_context __user *ctx)
+{
+ int err = 0;
+ u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0);
+
+ /*
+ * If GCS is enabled we will add a cap token to the frame,
+ * include it in the GCSPR_EL0 we report to support stack
+ * switching via sigreturn if GCS is enabled. We do not allow
+ * enabling via sigreturn so the token is only relevant for
+ * threads with GCS enabled.
+ */
+ if (task_gcs_el0_enabled(current))
+ gcspr -= 8;
+
+ __put_user_error(GCS_MAGIC, &ctx->head.magic, err);
+ __put_user_error(sizeof(*ctx), &ctx->head.size, err);
+ __put_user_error(gcspr, &ctx->gcspr, err);
+ __put_user_error(0, &ctx->reserved, err);
+ __put_user_error(current->thread.gcs_el0_mode,
+ &ctx->features_enabled, err);
+
+ return err;
+}
+
+static int restore_gcs_context(struct user_ctxs *user)
+{
+ u64 gcspr, enabled;
+ int err = 0;
+
+ if (user->gcs_size != sizeof(*user->gcs))
+ return -EINVAL;
+
+ __get_user_error(gcspr, &user->gcs->gcspr, err);
+ __get_user_error(enabled, &user->gcs->features_enabled, err);
+ if (err)
+ return err;
+
+ /* Don't allow unknown modes */
+ if (enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK)
+ return -EINVAL;
+
+ err = gcs_check_locked(current, enabled);
+ if (err != 0)
+ return err;
+
+ /* Don't allow enabling */
+ if (!task_gcs_el0_enabled(current) &&
+ (enabled & PR_SHADOW_STACK_ENABLE))
+ return -EINVAL;
+
+ /* If we are disabling disable everything */
+ if (!(enabled & PR_SHADOW_STACK_ENABLE))
+ enabled = 0;
+
+ current->thread.gcs_el0_mode = enabled;
+
+ /*
+ * We let userspace set GCSPR_EL0 to anything here, we will
+ * validate later in gcs_restore_signal().
+ */
+ write_sysreg_s(gcspr, SYS_GCSPR_EL0);
+
+ return 0;
+}
+
+#else /* ! CONFIG_ARM64_GCS */
+
+/* Turn any non-optimised out attempts to use these into a link error: */
+extern int preserve_gcs_context(void __user *ctx);
+extern int restore_gcs_context(struct user_ctxs *user);
+
+#endif /* ! CONFIG_ARM64_GCS */
+
static int parse_user_sigframe(struct user_ctxs *user,
struct rt_sigframe __user *sf)
{
@@ -707,6 +790,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
user->zt = NULL;
user->fpmr = NULL;
user->poe = NULL;
+ user->gcs = NULL;
if (!IS_ALIGNED((unsigned long)base, 16))
goto invalid;
@@ -823,6 +907,17 @@ static int parse_user_sigframe(struct user_ctxs *user,
user->fpmr_size = size;
break;
+ case GCS_MAGIC:
+ if (!system_supports_gcs())
+ goto invalid;
+
+ if (user->gcs)
+ goto invalid;
+
+ user->gcs = (struct gcs_context __user *)head;
+ user->gcs_size = size;
+ break;
+
case EXTRA_MAGIC:
if (have_extra_context)
goto invalid;
@@ -943,6 +1038,9 @@ static int restore_sigframe(struct pt_regs *regs,
err = restore_fpsimd_context(&user);
}
+ if (err == 0 && system_supports_gcs() && user.gcs)
+ err = restore_gcs_context(&user);
+
if (err == 0 && system_supports_tpidr2() && user.tpidr2)
err = restore_tpidr2_context(&user);
@@ -961,6 +1059,58 @@ static int restore_sigframe(struct pt_regs *regs,
return err;
}
+#ifdef CONFIG_ARM64_GCS
+static int gcs_restore_signal(void)
+{
+ unsigned long __user *gcspr_el0;
+ u64 cap;
+ int ret;
+
+ if (!system_supports_gcs())
+ return 0;
+
+ if (!(current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE))
+ return 0;
+
+ gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0);
+
+ /*
+ * Ensure that any changes to the GCS done via GCS operations
+ * are visible to the normal reads we do to validate the
+ * token.
+ */
+ gcsb_dsync();
+
+ /*
+ * GCSPR_EL0 should be pointing at a capped GCS, read the cap.
+ * We don't enforce that this is in a GCS page, if it is not
+ * then faults will be generated on GCS operations - the main
+ * concern is to protect GCS pages.
+ */
+ ret = copy_from_user(&cap, gcspr_el0, sizeof(cap));
+ if (ret)
+ return -EFAULT;
+
+ /*
+ * Check that the cap is the actual GCS before replacing it.
+ */
+ if (!gcs_signal_cap_valid((u64)gcspr_el0, cap))
+ return -EINVAL;
+
+ /* Invalidate the token to prevent reuse */
+ put_user_gcs(0, (__user void*)gcspr_el0, &ret);
+ if (ret != 0)
+ return -EFAULT;
+
+ write_sysreg_s(gcspr_el0 + 1, SYS_GCSPR_EL0);
+
+ return 0;
+}
+
+#else
+static int gcs_restore_signal(void) { return 0; }
+#endif
+
SYSCALL_DEFINE0(rt_sigreturn)
{
struct pt_regs *regs = current_pt_regs();
@@ -985,6 +1135,9 @@ SYSCALL_DEFINE0(rt_sigreturn)
if (restore_sigframe(regs, frame, &ua_state))
goto badframe;
+ if (gcs_restore_signal())
+ goto badframe;
+
if (restore_altstack(&frame->uc.uc_stack))
goto badframe;
@@ -1024,6 +1177,15 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
return err;
}
+#ifdef CONFIG_ARM64_GCS
+ if (system_supports_gcs() && (add_all || current->thread.gcspr_el0)) {
+ err = sigframe_alloc(user, &user->gcs_offset,
+ sizeof(struct gcs_context));
+ if (err)
+ return err;
+ }
+#endif
+
if (system_supports_sve() || system_supports_sme()) {
unsigned int vq = 0;
@@ -1132,6 +1294,12 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
__put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
}
+ if (system_supports_gcs() && err == 0 && user->gcs_offset) {
+ struct gcs_context __user *gcs_ctx =
+ apply_user_offset(user, user->gcs_offset);
+ err |= preserve_gcs_context(gcs_ctx);
+ }
+
/* Scalable Vector Extension state (including streaming), if present */
if ((system_supports_sve() || system_supports_sme()) &&
err == 0 && user->sve_offset) {
@@ -1154,7 +1322,7 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
err |= preserve_fpmr_context(fpmr_ctx);
}
- if (system_supports_poe() && err == 0 && user->poe_offset) {
+ if (system_supports_poe() && err == 0) {
struct poe_context __user *poe_ctx =
apply_user_offset(user, user->poe_offset);
@@ -1249,7 +1417,48 @@ static int get_sigframe(struct rt_sigframe_user_layout *user,
return 0;
}
-static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+#ifdef CONFIG_ARM64_GCS
+
+static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig)
+{
+ unsigned long __user *gcspr_el0;
+ int ret = 0;
+
+ if (!system_supports_gcs())
+ return 0;
+
+ if (!task_gcs_el0_enabled(current))
+ return 0;
+
+ /*
+ * We are entering a signal handler, current register state is
+ * active.
+ */
+ gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0);
+
+ /*
+ * Push a cap and the GCS entry for the trampoline onto the GCS.
+ */
+ put_user_gcs((unsigned long)sigtramp, gcspr_el0 - 2, &ret);
+ put_user_gcs(GCS_SIGNAL_CAP(gcspr_el0 - 1), gcspr_el0 - 1, &ret);
+ if (ret != 0)
+ return ret;
+
+ gcspr_el0 -= 2;
+ write_sysreg_s((unsigned long)gcspr_el0, SYS_GCSPR_EL0);
+
+ return 0;
+}
+#else
+
+static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig)
+{
+ return 0;
+}
+
+#endif
+
+static int setup_return(struct pt_regs *regs, struct ksignal *ksig,
struct rt_sigframe_user_layout *user, int usig)
{
__sigrestore_t sigtramp;
@@ -1257,7 +1466,7 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
regs->regs[0] = usig;
regs->sp = (unsigned long)user->sigframe;
regs->regs[29] = (unsigned long)&user->next_frame->fp;
- regs->pc = (unsigned long)ka->sa.sa_handler;
+ regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
/*
* Signal delivery is a (wacky) indirect function call in
@@ -1297,12 +1506,14 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
sme_smstop();
}
- if (ka->sa.sa_flags & SA_RESTORER)
- sigtramp = ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ sigtramp = ksig->ka.sa.sa_restorer;
else
sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
regs->regs[30] = (unsigned long)sigtramp;
+
+ return gcs_signal_entry(sigtramp, ksig);
}
static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
@@ -1327,7 +1538,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
err |= setup_sigframe(&user, regs, set, &ua_state);
if (err == 0) {
- setup_return(regs, &ksig->ka, &user, usig);
+ err = setup_return(regs, ksig, &user, usig);
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->regs[1] = (unsigned long)&frame->info;
diff --git a/arch/arm64/kernel/smccc-call.S b/arch/arm64/kernel/smccc-call.S
index 487381164ff6..2def9d0dd3dd 100644
--- a/arch/arm64/kernel/smccc-call.S
+++ b/arch/arm64/kernel/smccc-call.S
@@ -7,48 +7,19 @@
#include <asm/asm-offsets.h>
#include <asm/assembler.h>
-#include <asm/thread_info.h>
-
-/*
- * If we have SMCCC v1.3 and (as is likely) no SVE state in
- * the registers then set the SMCCC hint bit to say there's no
- * need to preserve it. Do this by directly adjusting the SMCCC
- * function value which is already stored in x0 ready to be called.
- */
-SYM_FUNC_START(__arm_smccc_sve_check)
-
- ldr_l x16, smccc_has_sve_hint
- cbz x16, 2f
-
- get_current_task x16
- ldr x16, [x16, #TSK_TI_FLAGS]
- tbnz x16, #TIF_FOREIGN_FPSTATE, 1f // Any live FP state?
- tbnz x16, #TIF_SVE, 2f // Does that state include SVE?
-
-1: orr x0, x0, ARM_SMCCC_1_3_SVE_HINT
-
-2: ret
-SYM_FUNC_END(__arm_smccc_sve_check)
-EXPORT_SYMBOL(__arm_smccc_sve_check)
.macro SMCCC instr
- stp x29, x30, [sp, #-16]!
- mov x29, sp
-alternative_if ARM64_SVE
- bl __arm_smccc_sve_check
-alternative_else_nop_endif
\instr #0
- ldr x4, [sp, #16]
+ ldr x4, [sp]
stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
- ldr x4, [sp, #24]
+ ldr x4, [sp, #8]
cbz x4, 1f /* no quirk structure */
ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6
b.ne 1f
str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
-1: ldp x29, x30, [sp], #16
- ret
+1: ret
.endm
/*
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 2729faaee4b4..caef85462acb 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -20,6 +20,23 @@
#include <asm/stack_pointer.h>
#include <asm/stacktrace.h>
+enum kunwind_source {
+ KUNWIND_SOURCE_UNKNOWN,
+ KUNWIND_SOURCE_FRAME,
+ KUNWIND_SOURCE_CALLER,
+ KUNWIND_SOURCE_TASK,
+ KUNWIND_SOURCE_REGS_PC,
+ KUNWIND_SOURCE_REGS_LR,
+};
+
+union unwind_flags {
+ unsigned long all;
+ struct {
+ unsigned long fgraph : 1,
+ kretprobe : 1;
+ };
+};
+
/*
* Kernel unwind state
*
@@ -37,6 +54,9 @@ struct kunwind_state {
#ifdef CONFIG_KRETPROBES
struct llist_node *kr_cur;
#endif
+ enum kunwind_source source;
+ union unwind_flags flags;
+ struct pt_regs *regs;
};
static __always_inline void
@@ -45,6 +65,9 @@ kunwind_init(struct kunwind_state *state,
{
unwind_init_common(&state->common);
state->task = task;
+ state->source = KUNWIND_SOURCE_UNKNOWN;
+ state->flags.all = 0;
+ state->regs = NULL;
}
/*
@@ -60,8 +83,10 @@ kunwind_init_from_regs(struct kunwind_state *state,
{
kunwind_init(state, current);
+ state->regs = regs;
state->common.fp = regs->regs[29];
state->common.pc = regs->pc;
+ state->source = KUNWIND_SOURCE_REGS_PC;
}
/*
@@ -79,6 +104,7 @@ kunwind_init_from_caller(struct kunwind_state *state)
state->common.fp = (unsigned long)__builtin_frame_address(1);
state->common.pc = (unsigned long)__builtin_return_address(0);
+ state->source = KUNWIND_SOURCE_CALLER;
}
/*
@@ -99,6 +125,7 @@ kunwind_init_from_task(struct kunwind_state *state,
state->common.fp = thread_saved_fp(task);
state->common.pc = thread_saved_pc(task);
+ state->source = KUNWIND_SOURCE_TASK;
}
static __always_inline int
@@ -114,6 +141,7 @@ kunwind_recover_return_address(struct kunwind_state *state)
if (WARN_ON_ONCE(state->common.pc == orig_pc))
return -EINVAL;
state->common.pc = orig_pc;
+ state->flags.fgraph = 1;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
@@ -124,12 +152,110 @@ kunwind_recover_return_address(struct kunwind_state *state)
(void *)state->common.fp,
&state->kr_cur);
state->common.pc = orig_pc;
+ state->flags.kretprobe = 1;
}
#endif /* CONFIG_KRETPROBES */
return 0;
}
+static __always_inline
+int kunwind_next_regs_pc(struct kunwind_state *state)
+{
+ struct stack_info *info;
+ unsigned long fp = state->common.fp;
+ struct pt_regs *regs;
+
+ regs = container_of((u64 *)fp, struct pt_regs, stackframe.record.fp);
+
+ info = unwind_find_stack(&state->common, (unsigned long)regs, sizeof(*regs));
+ if (!info)
+ return -EINVAL;
+
+ unwind_consume_stack(&state->common, info, (unsigned long)regs,
+ sizeof(*regs));
+
+ state->regs = regs;
+ state->common.pc = regs->pc;
+ state->common.fp = regs->regs[29];
+ state->source = KUNWIND_SOURCE_REGS_PC;
+ return 0;
+}
+
+static __always_inline int
+kunwind_next_regs_lr(struct kunwind_state *state)
+{
+ /*
+ * The stack for the regs was consumed by kunwind_next_regs_pc(), so we
+ * cannot consume that again here, but we know the regs are safe to
+ * access.
+ */
+ state->common.pc = state->regs->regs[30];
+ state->common.fp = state->regs->regs[29];
+ state->regs = NULL;
+ state->source = KUNWIND_SOURCE_REGS_LR;
+
+ return 0;
+}
+
+static __always_inline int
+kunwind_next_frame_record_meta(struct kunwind_state *state)
+{
+ struct task_struct *tsk = state->task;
+ unsigned long fp = state->common.fp;
+ struct frame_record_meta *meta;
+ struct stack_info *info;
+
+ info = unwind_find_stack(&state->common, fp, sizeof(*meta));
+ if (!info)
+ return -EINVAL;
+
+ meta = (struct frame_record_meta *)fp;
+ switch (READ_ONCE(meta->type)) {
+ case FRAME_META_TYPE_FINAL:
+ if (meta == &task_pt_regs(tsk)->stackframe)
+ return -ENOENT;
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ case FRAME_META_TYPE_PT_REGS:
+ return kunwind_next_regs_pc(state);
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+}
+
+static __always_inline int
+kunwind_next_frame_record(struct kunwind_state *state)
+{
+ unsigned long fp = state->common.fp;
+ struct frame_record *record;
+ struct stack_info *info;
+ unsigned long new_fp, new_pc;
+
+ if (fp & 0x7)
+ return -EINVAL;
+
+ info = unwind_find_stack(&state->common, fp, sizeof(*record));
+ if (!info)
+ return -EINVAL;
+
+ record = (struct frame_record *)fp;
+ new_fp = READ_ONCE(record->fp);
+ new_pc = READ_ONCE(record->lr);
+
+ if (!new_fp && !new_pc)
+ return kunwind_next_frame_record_meta(state);
+
+ unwind_consume_stack(&state->common, info, fp, sizeof(*record));
+
+ state->common.fp = new_fp;
+ state->common.pc = new_pc;
+ state->source = KUNWIND_SOURCE_FRAME;
+
+ return 0;
+}
+
/*
* Unwind from one frame record (A) to the next frame record (B).
*
@@ -140,15 +266,24 @@ kunwind_recover_return_address(struct kunwind_state *state)
static __always_inline int
kunwind_next(struct kunwind_state *state)
{
- struct task_struct *tsk = state->task;
- unsigned long fp = state->common.fp;
int err;
- /* Final frame; nothing to unwind */
- if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
- return -ENOENT;
+ state->flags.all = 0;
+
+ switch (state->source) {
+ case KUNWIND_SOURCE_FRAME:
+ case KUNWIND_SOURCE_CALLER:
+ case KUNWIND_SOURCE_TASK:
+ case KUNWIND_SOURCE_REGS_LR:
+ err = kunwind_next_frame_record(state);
+ break;
+ case KUNWIND_SOURCE_REGS_PC:
+ err = kunwind_next_regs_lr(state);
+ break;
+ default:
+ err = -EINVAL;
+ }
- err = unwind_next_frame_record(&state->common);
if (err)
return err;
@@ -294,10 +429,33 @@ noinline noinstr void arch_bpf_stack_walk(bool (*consume_entry)(void *cookie, u6
kunwind_stack_walk(arch_bpf_unwind_consume_entry, &data, current, NULL);
}
-static bool dump_backtrace_entry(void *arg, unsigned long where)
+static const char *state_source_string(const struct kunwind_state *state)
{
+ switch (state->source) {
+ case KUNWIND_SOURCE_FRAME: return NULL;
+ case KUNWIND_SOURCE_CALLER: return "C";
+ case KUNWIND_SOURCE_TASK: return "T";
+ case KUNWIND_SOURCE_REGS_PC: return "P";
+ case KUNWIND_SOURCE_REGS_LR: return "L";
+ default: return "U";
+ }
+}
+
+static bool dump_backtrace_entry(const struct kunwind_state *state, void *arg)
+{
+ const char *source = state_source_string(state);
+ union unwind_flags flags = state->flags;
+ bool has_info = source || flags.all;
char *loglvl = arg;
- printk("%s %pSb\n", loglvl, (void *)where);
+
+ printk("%s %pSb%s%s%s%s%s\n", loglvl,
+ (void *)state->common.pc,
+ has_info ? " (" : "",
+ source ? source : "",
+ flags.fgraph ? "F" : "",
+ flags.kretprobe ? "K" : "",
+ has_info ? ")" : "");
+
return true;
}
@@ -316,7 +474,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
return;
printk("%sCall trace:\n", loglvl);
- arch_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs);
+ kunwind_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs);
put_task_stack(tsk);
}
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 563cbce11126..4e26bd356a48 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -41,7 +41,7 @@
#include <asm/extable.h>
#include <asm/insn.h>
#include <asm/kprobes.h>
-#include <asm/patching.h>
+#include <asm/text-patching.h>
#include <asm/traps.h>
#include <asm/smp.h>
#include <asm/stack_pointer.h>
@@ -506,6 +506,16 @@ void do_el1_bti(struct pt_regs *regs, unsigned long esr)
die("Oops - BTI", regs, esr);
}
+void do_el0_gcs(struct pt_regs *regs, unsigned long esr)
+{
+ force_signal_inject(SIGSEGV, SEGV_CPERR, regs->pc, 0);
+}
+
+void do_el1_gcs(struct pt_regs *regs, unsigned long esr)
+{
+ die("Oops - GCS", regs, esr);
+}
+
void do_el0_fpac(struct pt_regs *regs, unsigned long esr)
{
force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr);
@@ -531,6 +541,13 @@ void do_el0_mops(struct pt_regs *regs, unsigned long esr)
user_fastforward_single_step(current);
}
+void do_el1_mops(struct pt_regs *regs, unsigned long esr)
+{
+ arm64_mops_reset_regs(&regs->user_regs, esr);
+
+ kernel_fastforward_single_step(regs);
+}
+
#define __user_cache_maint(insn, address, res) \
if (address >= TASK_SIZE_MAX) { \
res = -EFAULT; \
@@ -852,6 +869,7 @@ static const char *esr_class_str[] = {
[ESR_ELx_EC_MOPS] = "MOPS",
[ESR_ELx_EC_FP_EXC32] = "FP (AArch32)",
[ESR_ELx_EC_FP_EXC64] = "FP (AArch64)",
+ [ESR_ELx_EC_GCS] = "Guarded Control Stack",
[ESR_ELx_EC_SERROR] = "SError",
[ESR_ELx_EC_BREAKPT_LOW] = "Breakpoint (lower EL)",
[ESR_ELx_EC_BREAKPT_CUR] = "Breakpoint (current EL)",
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 706c9c3a7a50..e8ed8e5b713b 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -19,7 +19,6 @@
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/time_namespace.h>
-#include <linux/timekeeper_internal.h>
#include <linux/vmalloc.h>
#include <vdso/datapage.h>
#include <vdso/helpers.h>
@@ -39,8 +38,6 @@ struct vdso_abi_info {
const char *vdso_code_start;
const char *vdso_code_end;
unsigned long vdso_pages;
- /* Data Mapping */
- struct vm_special_mapping *dm;
/* Code Mapping */
struct vm_special_mapping *cm;
};
@@ -113,6 +110,8 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page)
return (struct vdso_data *)(vvar_page);
}
+static const struct vm_special_mapping vvar_map;
+
/*
* The vvar mapping contains data for a specific time namespace, so when a task
* changes namespace we must unmap its vvar data for the old namespace.
@@ -129,12 +128,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_lock(mm);
for_each_vma(vmi, vma) {
- if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_AA64].dm))
- zap_vma_pages(vma);
-#ifdef CONFIG_COMPAT_VDSO
- if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_AA32].dm))
+ if (vma_is_special_mapping(vma, &vvar_map))
zap_vma_pages(vma);
-#endif
}
mmap_read_unlock(mm);
@@ -176,6 +171,11 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
return vmf_insert_pfn(vma, vmf->address, pfn);
}
+static const struct vm_special_mapping vvar_map = {
+ .name = "[vvar]",
+ .fault = vvar_fault,
+};
+
static int __setup_additional_pages(enum vdso_abi abi,
struct mm_struct *mm,
struct linux_binprm *bprm,
@@ -199,7 +199,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
ret = _install_special_mapping(mm, vdso_base, VVAR_NR_PAGES * PAGE_SIZE,
VM_READ|VM_MAYREAD|VM_PFNMAP,
- vdso_info[abi].dm);
+ &vvar_map);
if (IS_ERR(ret))
goto up_fail;
@@ -229,7 +229,6 @@ up_fail:
enum aarch32_map {
AA32_MAP_VECTORS, /* kuser helpers */
AA32_MAP_SIGPAGE,
- AA32_MAP_VVAR,
AA32_MAP_VDSO,
};
@@ -254,10 +253,6 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
.pages = &aarch32_sig_page,
.mremap = aarch32_sigpage_mremap,
},
- [AA32_MAP_VVAR] = {
- .name = "[vvar]",
- .fault = vvar_fault,
- },
[AA32_MAP_VDSO] = {
.name = "[vdso]",
.mremap = vdso_mremap,
@@ -307,7 +302,6 @@ static int __init __aarch32_alloc_vdso_pages(void)
if (!IS_ENABLED(CONFIG_COMPAT_VDSO))
return 0;
- vdso_info[VDSO_ABI_AA32].dm = &aarch32_vdso_maps[AA32_MAP_VVAR];
vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO];
return __vdso_init(VDSO_ABI_AA32);
@@ -402,26 +396,14 @@ out:
}
#endif /* CONFIG_COMPAT */
-enum aarch64_map {
- AA64_MAP_VVAR,
- AA64_MAP_VDSO,
-};
-
-static struct vm_special_mapping aarch64_vdso_maps[] __ro_after_init = {
- [AA64_MAP_VVAR] = {
- .name = "[vvar]",
- .fault = vvar_fault,
- },
- [AA64_MAP_VDSO] = {
- .name = "[vdso]",
- .mremap = vdso_mremap,
- },
+static struct vm_special_mapping aarch64_vdso_map __ro_after_init = {
+ .name = "[vdso]",
+ .mremap = vdso_mremap,
};
static int __init vdso_init(void)
{
- vdso_info[VDSO_ABI_AA64].dm = &aarch64_vdso_maps[AA64_MAP_VVAR];
- vdso_info[VDSO_ABI_AA64].cm = &aarch64_vdso_maps[AA64_MAP_VDSO];
+ vdso_info[VDSO_ABI_AA64].cm = &aarch64_vdso_map;
return __vdso_init(VDSO_ABI_AA64);
}
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
index f204a9ddc833..4ec32e86a8da 100644
--- a/arch/arm64/kernel/vdso/vdso.lds.S
+++ b/arch/arm64/kernel/vdso/vdso.lds.S
@@ -25,7 +25,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
#endif
- . = VDSO_LBASE + SIZEOF_HEADERS;
+ . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) }
diff --git a/arch/arm64/kernel/vdso32/vdso.lds.S b/arch/arm64/kernel/vdso32/vdso.lds.S
index 8d95d7d35057..732702a187e9 100644
--- a/arch/arm64/kernel/vdso32/vdso.lds.S
+++ b/arch/arm64/kernel/vdso32/vdso.lds.S
@@ -22,7 +22,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS
PROVIDE_HIDDEN(_timens_data = _vdso_data + PAGE_SIZE);
#endif
- . = VDSO_LBASE + SIZEOF_HEADERS;
+ . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) }
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 58d89d997d05..f84c71f04d9e 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -287,6 +287,9 @@ SECTIONS
__initdata_end = .;
__init_end = .;
+ .data.rel.ro : { *(.data.rel.ro) }
+ ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")
+
_data = .;
_sdata = .;
RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)
@@ -343,9 +346,6 @@ SECTIONS
*(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)
}
ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
-
- .data.rel.ro : { *(.data.rel.ro) }
- ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")
}
#include "image-vars.h"
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 879982b1cc73..1215df590418 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -206,8 +206,7 @@ void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
static inline bool userspace_irqchip(struct kvm *kvm)
{
- return static_branch_unlikely(&userspace_irqchip_in_use) &&
- unlikely(!irqchip_in_kernel(kvm));
+ return unlikely(!irqchip_in_kernel(kvm));
}
static void soft_timer_start(struct hrtimer *hrt, u64 ns)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 48cafb65d6ac..a102c3aebdbc 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -69,7 +69,6 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
static bool vgic_present, kvm_arm_initialised;
static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized);
-DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
bool is_kvm_arm_initialised(void)
{
@@ -503,9 +502,6 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
{
- if (vcpu_has_run_once(vcpu) && unlikely(!irqchip_in_kernel(vcpu->kvm)))
- static_branch_dec(&userspace_irqchip_in_use);
-
kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
kvm_timer_vcpu_terminate(vcpu);
kvm_pmu_vcpu_destroy(vcpu);
@@ -848,22 +844,6 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
return ret;
}
- if (!irqchip_in_kernel(kvm)) {
- /*
- * Tell the rest of the code that there are userspace irqchip
- * VMs in the wild.
- */
- static_branch_inc(&userspace_irqchip_in_use);
- }
-
- /*
- * Initialize traps for protected VMs.
- * NOTE: Move to run in EL2 directly, rather than via a hypercall, once
- * the code is in place for first run initialization at EL2.
- */
- if (kvm_vm_is_protected(kvm))
- kvm_call_hyp_nvhe(__pkvm_vcpu_init_traps, vcpu);
-
mutex_lock(&kvm->arch.config_lock);
set_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags);
mutex_unlock(&kvm->arch.config_lock);
@@ -1077,7 +1057,7 @@ static bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu, int *ret)
* state gets updated in kvm_timer_update_run and
* kvm_pmu_update_run below).
*/
- if (static_branch_unlikely(&userspace_irqchip_in_use)) {
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm))) {
if (kvm_timer_should_notify_user(vcpu) ||
kvm_pmu_should_notify_user(vcpu)) {
*ret = -EINTR;
@@ -1199,7 +1179,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
vcpu->mode = OUTSIDE_GUEST_MODE;
isb(); /* Ensure work in x_flush_hwstate is committed */
kvm_pmu_sync_hwstate(vcpu);
- if (static_branch_unlikely(&userspace_irqchip_in_use))
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
kvm_timer_sync_user(vcpu);
kvm_vgic_sync_hwstate(vcpu);
local_irq_enable();
@@ -1245,7 +1225,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
* we don't want vtimer interrupts to race with syncing the
* timer virtual interrupt state.
*/
- if (static_branch_unlikely(&userspace_irqchip_in_use))
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
kvm_timer_sync_user(vcpu);
kvm_arch_vcpu_ctxsync_fp(vcpu);
diff --git a/arch/arm64/kvm/at.c b/arch/arm64/kvm/at.c
index 39f0e87a340e..8c5d7990e5b3 100644
--- a/arch/arm64/kvm/at.c
+++ b/arch/arm64/kvm/at.c
@@ -24,6 +24,9 @@ struct s1_walk_info {
unsigned int txsz;
int sl;
bool hpd;
+ bool e0poe;
+ bool poe;
+ bool pan;
bool be;
bool s2;
};
@@ -37,6 +40,16 @@ struct s1_walk_result {
u8 APTable;
bool UXNTable;
bool PXNTable;
+ bool uwxn;
+ bool uov;
+ bool ur;
+ bool uw;
+ bool ux;
+ bool pwxn;
+ bool pov;
+ bool pr;
+ bool pw;
+ bool px;
};
struct {
u8 fst;
@@ -87,6 +100,51 @@ static enum trans_regime compute_translation_regime(struct kvm_vcpu *vcpu, u32 o
}
}
+static bool s1pie_enabled(struct kvm_vcpu *vcpu, enum trans_regime regime)
+{
+ if (!kvm_has_s1pie(vcpu->kvm))
+ return false;
+
+ switch (regime) {
+ case TR_EL2:
+ case TR_EL20:
+ return vcpu_read_sys_reg(vcpu, TCR2_EL2) & TCR2_EL2_PIE;
+ case TR_EL10:
+ return (__vcpu_sys_reg(vcpu, HCRX_EL2) & HCRX_EL2_TCR2En) &&
+ (__vcpu_sys_reg(vcpu, TCR2_EL1) & TCR2_EL1x_PIE);
+ default:
+ BUG();
+ }
+}
+
+static void compute_s1poe(struct kvm_vcpu *vcpu, struct s1_walk_info *wi)
+{
+ u64 val;
+
+ if (!kvm_has_s1poe(vcpu->kvm)) {
+ wi->poe = wi->e0poe = false;
+ return;
+ }
+
+ switch (wi->regime) {
+ case TR_EL2:
+ case TR_EL20:
+ val = vcpu_read_sys_reg(vcpu, TCR2_EL2);
+ wi->poe = val & TCR2_EL2_POE;
+ wi->e0poe = (wi->regime == TR_EL20) && (val & TCR2_EL2_E0POE);
+ break;
+ case TR_EL10:
+ if (__vcpu_sys_reg(vcpu, HCRX_EL2) & HCRX_EL2_TCR2En) {
+ wi->poe = wi->e0poe = false;
+ return;
+ }
+
+ val = __vcpu_sys_reg(vcpu, TCR2_EL1);
+ wi->poe = val & TCR2_EL1x_POE;
+ wi->e0poe = val & TCR2_EL1x_E0POE;
+ }
+}
+
static int setup_s1_walk(struct kvm_vcpu *vcpu, u32 op, struct s1_walk_info *wi,
struct s1_walk_result *wr, u64 va)
{
@@ -98,6 +156,8 @@ static int setup_s1_walk(struct kvm_vcpu *vcpu, u32 op, struct s1_walk_info *wi,
wi->regime = compute_translation_regime(vcpu, op);
as_el0 = (op == OP_AT_S1E0R || op == OP_AT_S1E0W);
+ wi->pan = (op == OP_AT_S1E1RP || op == OP_AT_S1E1WP) &&
+ (*vcpu_cpsr(vcpu) & PSR_PAN_BIT);
va55 = va & BIT(55);
@@ -180,6 +240,14 @@ static int setup_s1_walk(struct kvm_vcpu *vcpu, u32 op, struct s1_walk_info *wi,
(va55 ?
FIELD_GET(TCR_HPD1, tcr) :
FIELD_GET(TCR_HPD0, tcr)));
+ /* R_JHSVW */
+ wi->hpd |= s1pie_enabled(vcpu, wi->regime);
+
+ /* Do we have POE? */
+ compute_s1poe(vcpu, wi);
+
+ /* R_BVXDG */
+ wi->hpd |= (wi->poe || wi->e0poe);
/* Someone was silly enough to encode TG0/TG1 differently */
if (va55) {
@@ -412,6 +480,11 @@ struct mmu_config {
u64 ttbr1;
u64 tcr;
u64 mair;
+ u64 tcr2;
+ u64 pir;
+ u64 pire0;
+ u64 por_el0;
+ u64 por_el1;
u64 sctlr;
u64 vttbr;
u64 vtcr;
@@ -424,6 +497,17 @@ static void __mmu_config_save(struct mmu_config *config)
config->ttbr1 = read_sysreg_el1(SYS_TTBR1);
config->tcr = read_sysreg_el1(SYS_TCR);
config->mair = read_sysreg_el1(SYS_MAIR);
+ if (cpus_have_final_cap(ARM64_HAS_TCR2)) {
+ config->tcr2 = read_sysreg_el1(SYS_TCR2);
+ if (cpus_have_final_cap(ARM64_HAS_S1PIE)) {
+ config->pir = read_sysreg_el1(SYS_PIR);
+ config->pire0 = read_sysreg_el1(SYS_PIRE0);
+ }
+ if (system_supports_poe()) {
+ config->por_el1 = read_sysreg_el1(SYS_POR);
+ config->por_el0 = read_sysreg_s(SYS_POR_EL0);
+ }
+ }
config->sctlr = read_sysreg_el1(SYS_SCTLR);
config->vttbr = read_sysreg(vttbr_el2);
config->vtcr = read_sysreg(vtcr_el2);
@@ -444,6 +528,17 @@ static void __mmu_config_restore(struct mmu_config *config)
write_sysreg_el1(config->ttbr1, SYS_TTBR1);
write_sysreg_el1(config->tcr, SYS_TCR);
write_sysreg_el1(config->mair, SYS_MAIR);
+ if (cpus_have_final_cap(ARM64_HAS_TCR2)) {
+ write_sysreg_el1(config->tcr2, SYS_TCR2);
+ if (cpus_have_final_cap(ARM64_HAS_S1PIE)) {
+ write_sysreg_el1(config->pir, SYS_PIR);
+ write_sysreg_el1(config->pire0, SYS_PIRE0);
+ }
+ if (system_supports_poe()) {
+ write_sysreg_el1(config->por_el1, SYS_POR);
+ write_sysreg_s(config->por_el0, SYS_POR_EL0);
+ }
+ }
write_sysreg_el1(config->sctlr, SYS_SCTLR);
write_sysreg(config->vttbr, vttbr_el2);
write_sysreg(config->vtcr, vtcr_el2);
@@ -739,6 +834,9 @@ static bool pan3_enabled(struct kvm_vcpu *vcpu, enum trans_regime regime)
if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR1_EL1, PAN, PAN3))
return false;
+ if (s1pie_enabled(vcpu, regime))
+ return true;
+
if (regime == TR_EL10)
sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
else
@@ -747,111 +845,343 @@ static bool pan3_enabled(struct kvm_vcpu *vcpu, enum trans_regime regime)
return sctlr & SCTLR_EL1_EPAN;
}
-static u64 handle_at_slow(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
+static void compute_s1_direct_permissions(struct kvm_vcpu *vcpu,
+ struct s1_walk_info *wi,
+ struct s1_walk_result *wr)
{
- bool perm_fail, ur, uw, ux, pr, pw, px;
- struct s1_walk_result wr = {};
- struct s1_walk_info wi = {};
- int ret, idx;
+ bool wxn;
- ret = setup_s1_walk(vcpu, op, &wi, &wr, vaddr);
- if (ret)
- goto compute_par;
-
- if (wr.level == S1_MMU_DISABLED)
- goto compute_par;
-
- idx = srcu_read_lock(&vcpu->kvm->srcu);
-
- ret = walk_s1(vcpu, &wi, &wr, vaddr);
-
- srcu_read_unlock(&vcpu->kvm->srcu, idx);
-
- if (ret)
- goto compute_par;
-
- /* FIXME: revisit when adding indirect permission support */
- /* AArch64.S1DirectBasePermissions() */
- if (wi.regime != TR_EL2) {
- switch (FIELD_GET(PTE_USER | PTE_RDONLY, wr.desc)) {
+ /* Non-hierarchical part of AArch64.S1DirectBasePermissions() */
+ if (wi->regime != TR_EL2) {
+ switch (FIELD_GET(PTE_USER | PTE_RDONLY, wr->desc)) {
case 0b00:
- pr = pw = true;
- ur = uw = false;
+ wr->pr = wr->pw = true;
+ wr->ur = wr->uw = false;
break;
case 0b01:
- pr = pw = ur = uw = true;
+ wr->pr = wr->pw = wr->ur = wr->uw = true;
break;
case 0b10:
- pr = true;
- pw = ur = uw = false;
+ wr->pr = true;
+ wr->pw = wr->ur = wr->uw = false;
break;
case 0b11:
- pr = ur = true;
- pw = uw = false;
+ wr->pr = wr->ur = true;
+ wr->pw = wr->uw = false;
break;
}
- switch (wr.APTable) {
+ /* We don't use px for anything yet, but hey... */
+ wr->px = !((wr->desc & PTE_PXN) || wr->uw);
+ wr->ux = !(wr->desc & PTE_UXN);
+ } else {
+ wr->ur = wr->uw = wr->ux = false;
+
+ if (!(wr->desc & PTE_RDONLY)) {
+ wr->pr = wr->pw = true;
+ } else {
+ wr->pr = true;
+ wr->pw = false;
+ }
+
+ /* XN maps to UXN */
+ wr->px = !(wr->desc & PTE_UXN);
+ }
+
+ switch (wi->regime) {
+ case TR_EL2:
+ case TR_EL20:
+ wxn = (vcpu_read_sys_reg(vcpu, SCTLR_EL2) & SCTLR_ELx_WXN);
+ break;
+ case TR_EL10:
+ wxn = (__vcpu_sys_reg(vcpu, SCTLR_EL1) & SCTLR_ELx_WXN);
+ break;
+ }
+
+ wr->pwxn = wr->uwxn = wxn;
+ wr->pov = wi->poe;
+ wr->uov = wi->e0poe;
+}
+
+static void compute_s1_hierarchical_permissions(struct kvm_vcpu *vcpu,
+ struct s1_walk_info *wi,
+ struct s1_walk_result *wr)
+{
+ /* Hierarchical part of AArch64.S1DirectBasePermissions() */
+ if (wi->regime != TR_EL2) {
+ switch (wr->APTable) {
case 0b00:
break;
case 0b01:
- ur = uw = false;
+ wr->ur = wr->uw = false;
break;
case 0b10:
- pw = uw = false;
+ wr->pw = wr->uw = false;
break;
case 0b11:
- pw = ur = uw = false;
+ wr->pw = wr->ur = wr->uw = false;
break;
}
- /* We don't use px for anything yet, but hey... */
- px = !((wr.desc & PTE_PXN) || wr.PXNTable || uw);
- ux = !((wr.desc & PTE_UXN) || wr.UXNTable);
+ wr->px &= !wr->PXNTable;
+ wr->ux &= !wr->UXNTable;
+ } else {
+ if (wr->APTable & BIT(1))
+ wr->pw = false;
+
+ /* XN maps to UXN */
+ wr->px &= !wr->UXNTable;
+ }
+}
- if (op == OP_AT_S1E1RP || op == OP_AT_S1E1WP) {
- bool pan;
+#define perm_idx(v, r, i) ((vcpu_read_sys_reg((v), (r)) >> ((i) * 4)) & 0xf)
+
+#define set_priv_perms(wr, r, w, x) \
+ do { \
+ (wr)->pr = (r); \
+ (wr)->pw = (w); \
+ (wr)->px = (x); \
+ } while (0)
+
+#define set_unpriv_perms(wr, r, w, x) \
+ do { \
+ (wr)->ur = (r); \
+ (wr)->uw = (w); \
+ (wr)->ux = (x); \
+ } while (0)
+
+#define set_priv_wxn(wr, v) \
+ do { \
+ (wr)->pwxn = (v); \
+ } while (0)
+
+#define set_unpriv_wxn(wr, v) \
+ do { \
+ (wr)->uwxn = (v); \
+ } while (0)
+
+/* Similar to AArch64.S1IndirectBasePermissions(), without GCS */
+#define set_perms(w, wr, ip) \
+ do { \
+ /* R_LLZDZ */ \
+ switch ((ip)) { \
+ case 0b0000: \
+ set_ ## w ## _perms((wr), false, false, false); \
+ break; \
+ case 0b0001: \
+ set_ ## w ## _perms((wr), true , false, false); \
+ break; \
+ case 0b0010: \
+ set_ ## w ## _perms((wr), false, false, true ); \
+ break; \
+ case 0b0011: \
+ set_ ## w ## _perms((wr), true , false, true ); \
+ break; \
+ case 0b0100: \
+ set_ ## w ## _perms((wr), false, false, false); \
+ break; \
+ case 0b0101: \
+ set_ ## w ## _perms((wr), true , true , false); \
+ break; \
+ case 0b0110: \
+ set_ ## w ## _perms((wr), true , true , true ); \
+ break; \
+ case 0b0111: \
+ set_ ## w ## _perms((wr), true , true , true ); \
+ break; \
+ case 0b1000: \
+ set_ ## w ## _perms((wr), true , false, false); \
+ break; \
+ case 0b1001: \
+ set_ ## w ## _perms((wr), true , false, false); \
+ break; \
+ case 0b1010: \
+ set_ ## w ## _perms((wr), true , false, true ); \
+ break; \
+ case 0b1011: \
+ set_ ## w ## _perms((wr), false, false, false); \
+ break; \
+ case 0b1100: \
+ set_ ## w ## _perms((wr), true , true , false); \
+ break; \
+ case 0b1101: \
+ set_ ## w ## _perms((wr), false, false, false); \
+ break; \
+ case 0b1110: \
+ set_ ## w ## _perms((wr), true , true , true ); \
+ break; \
+ case 0b1111: \
+ set_ ## w ## _perms((wr), false, false, false); \
+ break; \
+ } \
+ \
+ /* R_HJYGR */ \
+ set_ ## w ## _wxn((wr), ((ip) == 0b0110)); \
+ \
+ } while (0)
+
+static void compute_s1_indirect_permissions(struct kvm_vcpu *vcpu,
+ struct s1_walk_info *wi,
+ struct s1_walk_result *wr)
+{
+ u8 up, pp, idx;
- pan = *vcpu_cpsr(vcpu) & PSR_PAN_BIT;
- pan &= ur || uw || (pan3_enabled(vcpu, wi.regime) && ux);
- pw &= !pan;
- pr &= !pan;
- }
- } else {
- ur = uw = ux = false;
+ idx = pte_pi_index(wr->desc);
- if (!(wr.desc & PTE_RDONLY)) {
- pr = pw = true;
- } else {
- pr = true;
- pw = false;
- }
+ switch (wi->regime) {
+ case TR_EL10:
+ pp = perm_idx(vcpu, PIR_EL1, idx);
+ up = perm_idx(vcpu, PIRE0_EL1, idx);
+ break;
+ case TR_EL20:
+ pp = perm_idx(vcpu, PIR_EL2, idx);
+ up = perm_idx(vcpu, PIRE0_EL2, idx);
+ break;
+ case TR_EL2:
+ pp = perm_idx(vcpu, PIR_EL2, idx);
+ up = 0;
+ break;
+ }
- if (wr.APTable & BIT(1))
- pw = false;
+ set_perms(priv, wr, pp);
- /* XN maps to UXN */
- px = !((wr.desc & PTE_UXN) || wr.UXNTable);
+ if (wi->regime != TR_EL2)
+ set_perms(unpriv, wr, up);
+ else
+ set_unpriv_perms(wr, false, false, false);
+
+ wr->pov = wi->poe && !(pp & BIT(3));
+ wr->uov = wi->e0poe && !(up & BIT(3));
+
+ /* R_VFPJF */
+ if (wr->px && wr->uw) {
+ set_priv_perms(wr, false, false, false);
+ set_unpriv_perms(wr, false, false, false);
+ }
+}
+
+static void compute_s1_overlay_permissions(struct kvm_vcpu *vcpu,
+ struct s1_walk_info *wi,
+ struct s1_walk_result *wr)
+{
+ u8 idx, pov_perms, uov_perms;
+
+ idx = FIELD_GET(PTE_PO_IDX_MASK, wr->desc);
+
+ switch (wi->regime) {
+ case TR_EL10:
+ pov_perms = perm_idx(vcpu, POR_EL1, idx);
+ uov_perms = perm_idx(vcpu, POR_EL0, idx);
+ break;
+ case TR_EL20:
+ pov_perms = perm_idx(vcpu, POR_EL2, idx);
+ uov_perms = perm_idx(vcpu, POR_EL0, idx);
+ break;
+ case TR_EL2:
+ pov_perms = perm_idx(vcpu, POR_EL2, idx);
+ uov_perms = 0;
+ break;
+ }
+
+ if (pov_perms & ~POE_RXW)
+ pov_perms = POE_NONE;
+
+ if (wi->poe && wr->pov) {
+ wr->pr &= pov_perms & POE_R;
+ wr->px &= pov_perms & POE_X;
+ wr->pw &= pov_perms & POE_W;
+ }
+
+ if (uov_perms & ~POE_RXW)
+ uov_perms = POE_NONE;
+
+ if (wi->e0poe && wr->uov) {
+ wr->ur &= uov_perms & POE_R;
+ wr->ux &= uov_perms & POE_X;
+ wr->uw &= uov_perms & POE_W;
}
+}
+
+static void compute_s1_permissions(struct kvm_vcpu *vcpu,
+ struct s1_walk_info *wi,
+ struct s1_walk_result *wr)
+{
+ bool pan;
+
+ if (!s1pie_enabled(vcpu, wi->regime))
+ compute_s1_direct_permissions(vcpu, wi, wr);
+ else
+ compute_s1_indirect_permissions(vcpu, wi, wr);
+
+ if (!wi->hpd)
+ compute_s1_hierarchical_permissions(vcpu, wi, wr);
+
+ if (wi->poe || wi->e0poe)
+ compute_s1_overlay_permissions(vcpu, wi, wr);
+
+ /* R_QXXPC */
+ if (wr->pwxn) {
+ if (!wr->pov && wr->pw)
+ wr->px = false;
+ if (wr->pov && wr->px)
+ wr->pw = false;
+ }
+
+ /* R_NPBXC */
+ if (wr->uwxn) {
+ if (!wr->uov && wr->uw)
+ wr->ux = false;
+ if (wr->uov && wr->ux)
+ wr->uw = false;
+ }
+
+ pan = wi->pan && (wr->ur || wr->uw ||
+ (pan3_enabled(vcpu, wi->regime) && wr->ux));
+ wr->pw &= !pan;
+ wr->pr &= !pan;
+}
- perm_fail = false;
+static u64 handle_at_slow(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
+{
+ struct s1_walk_result wr = {};
+ struct s1_walk_info wi = {};
+ bool perm_fail = false;
+ int ret, idx;
+
+ ret = setup_s1_walk(vcpu, op, &wi, &wr, vaddr);
+ if (ret)
+ goto compute_par;
+
+ if (wr.level == S1_MMU_DISABLED)
+ goto compute_par;
+
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+ ret = walk_s1(vcpu, &wi, &wr, vaddr);
+
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
+ if (ret)
+ goto compute_par;
+
+ compute_s1_permissions(vcpu, &wi, &wr);
switch (op) {
case OP_AT_S1E1RP:
case OP_AT_S1E1R:
case OP_AT_S1E2R:
- perm_fail = !pr;
+ perm_fail = !wr.pr;
break;
case OP_AT_S1E1WP:
case OP_AT_S1E1W:
case OP_AT_S1E2W:
- perm_fail = !pw;
+ perm_fail = !wr.pw;
break;
case OP_AT_S1E0R:
- perm_fail = !ur;
+ perm_fail = !wr.ur;
break;
case OP_AT_S1E0W:
- perm_fail = !uw;
+ perm_fail = !wr.uw;
break;
case OP_AT_S1E1A:
case OP_AT_S1E2A:
@@ -914,6 +1244,17 @@ static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
write_sysreg_el1(vcpu_read_sys_reg(vcpu, TTBR1_EL1), SYS_TTBR1);
write_sysreg_el1(vcpu_read_sys_reg(vcpu, TCR_EL1), SYS_TCR);
write_sysreg_el1(vcpu_read_sys_reg(vcpu, MAIR_EL1), SYS_MAIR);
+ if (kvm_has_tcr2(vcpu->kvm)) {
+ write_sysreg_el1(vcpu_read_sys_reg(vcpu, TCR2_EL1), SYS_TCR2);
+ if (kvm_has_s1pie(vcpu->kvm)) {
+ write_sysreg_el1(vcpu_read_sys_reg(vcpu, PIR_EL1), SYS_PIR);
+ write_sysreg_el1(vcpu_read_sys_reg(vcpu, PIRE0_EL1), SYS_PIRE0);
+ }
+ if (kvm_has_s1poe(vcpu->kvm)) {
+ write_sysreg_el1(vcpu_read_sys_reg(vcpu, POR_EL1), SYS_POR);
+ write_sysreg_s(vcpu_read_sys_reg(vcpu, POR_EL0), SYS_POR_EL0);
+ }
+ }
write_sysreg_el1(vcpu_read_sys_reg(vcpu, SCTLR_EL1), SYS_SCTLR);
__load_stage2(mmu, mmu->arch);
@@ -992,12 +1333,9 @@ void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
* switching context behind everybody's back, disable interrupts...
*/
scoped_guard(write_lock_irqsave, &vcpu->kvm->mmu_lock) {
- struct kvm_s2_mmu *mmu;
u64 val, hcr;
bool fail;
- mmu = &vcpu->kvm->arch.mmu;
-
val = hcr = read_sysreg(hcr_el2);
val &= ~HCR_TGE;
val |= HCR_VM;
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 05b6435d02a9..1ffbfd1c3cf2 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -16,9 +16,13 @@
enum trap_behaviour {
BEHAVE_HANDLE_LOCALLY = 0,
+
BEHAVE_FORWARD_READ = BIT(0),
BEHAVE_FORWARD_WRITE = BIT(1),
- BEHAVE_FORWARD_ANY = BEHAVE_FORWARD_READ | BEHAVE_FORWARD_WRITE,
+ BEHAVE_FORWARD_RW = BEHAVE_FORWARD_READ | BEHAVE_FORWARD_WRITE,
+
+ /* Traps that take effect in Host EL0, this is rare! */
+ BEHAVE_FORWARD_IN_HOST_EL0 = BIT(2),
};
struct trap_bits {
@@ -79,7 +83,6 @@ enum cgt_group_id {
CGT_MDCR_E2TB,
CGT_MDCR_TDCC,
- CGT_CPACR_E0POE,
CGT_CPTR_TAM,
CGT_CPTR_TCPAC,
@@ -106,6 +109,7 @@ enum cgt_group_id {
CGT_HCR_TPU_TOCU,
CGT_HCR_NV1_nNV2_ENSCXT,
CGT_MDCR_TPM_TPMCR,
+ CGT_MDCR_TPM_HPMN,
CGT_MDCR_TDE_TDA,
CGT_MDCR_TDE_TDOSA,
CGT_MDCR_TDE_TDRA,
@@ -122,6 +126,7 @@ enum cgt_group_id {
CGT_CNTHCTL_EL1PTEN,
CGT_CPTR_TTA,
+ CGT_MDCR_HPMN,
/* Must be last */
__NR_CGT_GROUP_IDS__
@@ -138,7 +143,7 @@ static const struct trap_bits coarse_trap_bits[] = {
.index = HCR_EL2,
.value = HCR_TID2,
.mask = HCR_TID2,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TID3] = {
.index = HCR_EL2,
@@ -162,37 +167,37 @@ static const struct trap_bits coarse_trap_bits[] = {
.index = HCR_EL2,
.value = HCR_TIDCP,
.mask = HCR_TIDCP,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TACR] = {
.index = HCR_EL2,
.value = HCR_TACR,
.mask = HCR_TACR,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TSW] = {
.index = HCR_EL2,
.value = HCR_TSW,
.mask = HCR_TSW,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TPC] = { /* Also called TCPC when FEAT_DPB is implemented */
.index = HCR_EL2,
.value = HCR_TPC,
.mask = HCR_TPC,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TPU] = {
.index = HCR_EL2,
.value = HCR_TPU,
.mask = HCR_TPU,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TTLB] = {
.index = HCR_EL2,
.value = HCR_TTLB,
.mask = HCR_TTLB,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TVM] = {
.index = HCR_EL2,
@@ -204,7 +209,7 @@ static const struct trap_bits coarse_trap_bits[] = {
.index = HCR_EL2,
.value = HCR_TDZ,
.mask = HCR_TDZ,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TRVM] = {
.index = HCR_EL2,
@@ -216,205 +221,201 @@ static const struct trap_bits coarse_trap_bits[] = {
.index = HCR_EL2,
.value = HCR_TLOR,
.mask = HCR_TLOR,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TERR] = {
.index = HCR_EL2,
.value = HCR_TERR,
.mask = HCR_TERR,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_APK] = {
.index = HCR_EL2,
.value = 0,
.mask = HCR_APK,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_NV] = {
.index = HCR_EL2,
.value = HCR_NV,
.mask = HCR_NV,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_NV_nNV2] = {
.index = HCR_EL2,
.value = HCR_NV,
.mask = HCR_NV | HCR_NV2,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_NV1_nNV2] = {
.index = HCR_EL2,
.value = HCR_NV | HCR_NV1,
.mask = HCR_NV | HCR_NV1 | HCR_NV2,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_AT] = {
.index = HCR_EL2,
.value = HCR_AT,
.mask = HCR_AT,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_nFIEN] = {
.index = HCR_EL2,
.value = 0,
.mask = HCR_FIEN,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TID4] = {
.index = HCR_EL2,
.value = HCR_TID4,
.mask = HCR_TID4,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TICAB] = {
.index = HCR_EL2,
.value = HCR_TICAB,
.mask = HCR_TICAB,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TOCU] = {
.index = HCR_EL2,
.value = HCR_TOCU,
.mask = HCR_TOCU,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_ENSCXT] = {
.index = HCR_EL2,
.value = 0,
.mask = HCR_ENSCXT,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TTLBIS] = {
.index = HCR_EL2,
.value = HCR_TTLBIS,
.mask = HCR_TTLBIS,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCR_TTLBOS] = {
.index = HCR_EL2,
.value = HCR_TTLBOS,
.mask = HCR_TTLBOS,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_TPMCR] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TPMCR,
.mask = MDCR_EL2_TPMCR,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW |
+ BEHAVE_FORWARD_IN_HOST_EL0,
},
[CGT_MDCR_TPM] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TPM,
.mask = MDCR_EL2_TPM,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW |
+ BEHAVE_FORWARD_IN_HOST_EL0,
},
[CGT_MDCR_TDE] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TDE,
.mask = MDCR_EL2_TDE,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_TDA] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TDA,
.mask = MDCR_EL2_TDA,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_TDOSA] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TDOSA,
.mask = MDCR_EL2_TDOSA,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_TDRA] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TDRA,
.mask = MDCR_EL2_TDRA,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_E2PB] = {
.index = MDCR_EL2,
.value = 0,
.mask = BIT(MDCR_EL2_E2PB_SHIFT),
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_TPMS] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TPMS,
.mask = MDCR_EL2_TPMS,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_TTRF] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TTRF,
.mask = MDCR_EL2_TTRF,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_E2TB] = {
.index = MDCR_EL2,
.value = 0,
.mask = BIT(MDCR_EL2_E2TB_SHIFT),
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_MDCR_TDCC] = {
.index = MDCR_EL2,
.value = MDCR_EL2_TDCC,
.mask = MDCR_EL2_TDCC,
- .behaviour = BEHAVE_FORWARD_ANY,
- },
- [CGT_CPACR_E0POE] = {
- .index = CPTR_EL2,
- .value = CPACR_ELx_E0POE,
- .mask = CPACR_ELx_E0POE,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_CPTR_TAM] = {
.index = CPTR_EL2,
.value = CPTR_EL2_TAM,
.mask = CPTR_EL2_TAM,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_CPTR_TCPAC] = {
.index = CPTR_EL2,
.value = CPTR_EL2_TCPAC,
.mask = CPTR_EL2_TCPAC,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCRX_EnFPM] = {
.index = HCRX_EL2,
.value = 0,
.mask = HCRX_EL2_EnFPM,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_HCRX_TCR2En] = {
.index = HCRX_EL2,
.value = 0,
.mask = HCRX_EL2_TCR2En,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_ICH_HCR_TC] = {
.index = ICH_HCR_EL2,
.value = ICH_HCR_TC,
.mask = ICH_HCR_TC,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_ICH_HCR_TALL0] = {
.index = ICH_HCR_EL2,
.value = ICH_HCR_TALL0,
.mask = ICH_HCR_TALL0,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_ICH_HCR_TALL1] = {
.index = ICH_HCR_EL2,
.value = ICH_HCR_TALL1,
.mask = ICH_HCR_TALL1,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
[CGT_ICH_HCR_TDIR] = {
.index = ICH_HCR_EL2,
.value = ICH_HCR_TDIR,
.mask = ICH_HCR_TDIR,
- .behaviour = BEHAVE_FORWARD_ANY,
+ .behaviour = BEHAVE_FORWARD_RW,
},
};
@@ -435,6 +436,7 @@ static const enum cgt_group_id *coarse_control_combo[] = {
MCB(CGT_HCR_TPU_TOCU, CGT_HCR_TPU, CGT_HCR_TOCU),
MCB(CGT_HCR_NV1_nNV2_ENSCXT, CGT_HCR_NV1_nNV2, CGT_HCR_ENSCXT),
MCB(CGT_MDCR_TPM_TPMCR, CGT_MDCR_TPM, CGT_MDCR_TPMCR),
+ MCB(CGT_MDCR_TPM_HPMN, CGT_MDCR_TPM, CGT_MDCR_HPMN),
MCB(CGT_MDCR_TDE_TDA, CGT_MDCR_TDE, CGT_MDCR_TDA),
MCB(CGT_MDCR_TDE_TDOSA, CGT_MDCR_TDE, CGT_MDCR_TDOSA),
MCB(CGT_MDCR_TDE_TDRA, CGT_MDCR_TDE, CGT_MDCR_TDRA),
@@ -474,7 +476,7 @@ static enum trap_behaviour check_cnthctl_el1pcten(struct kvm_vcpu *vcpu)
if (get_sanitized_cnthctl(vcpu) & (CNTHCTL_EL1PCTEN << 10))
return BEHAVE_HANDLE_LOCALLY;
- return BEHAVE_FORWARD_ANY;
+ return BEHAVE_FORWARD_RW;
}
static enum trap_behaviour check_cnthctl_el1pten(struct kvm_vcpu *vcpu)
@@ -482,7 +484,7 @@ static enum trap_behaviour check_cnthctl_el1pten(struct kvm_vcpu *vcpu)
if (get_sanitized_cnthctl(vcpu) & (CNTHCTL_EL1PCEN << 10))
return BEHAVE_HANDLE_LOCALLY;
- return BEHAVE_FORWARD_ANY;
+ return BEHAVE_FORWARD_RW;
}
static enum trap_behaviour check_cptr_tta(struct kvm_vcpu *vcpu)
@@ -493,7 +495,35 @@ static enum trap_behaviour check_cptr_tta(struct kvm_vcpu *vcpu)
val = translate_cptr_el2_to_cpacr_el1(val);
if (val & CPACR_ELx_TTA)
- return BEHAVE_FORWARD_ANY;
+ return BEHAVE_FORWARD_RW;
+
+ return BEHAVE_HANDLE_LOCALLY;
+}
+
+static enum trap_behaviour check_mdcr_hpmn(struct kvm_vcpu *vcpu)
+{
+ u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_esr(vcpu));
+ unsigned int idx;
+
+
+ switch (sysreg) {
+ case SYS_PMEVTYPERn_EL0(0) ... SYS_PMEVTYPERn_EL0(30):
+ case SYS_PMEVCNTRn_EL0(0) ... SYS_PMEVCNTRn_EL0(30):
+ idx = (sys_reg_CRm(sysreg) & 0x3) << 3 | sys_reg_Op2(sysreg);
+ break;
+ case SYS_PMXEVTYPER_EL0:
+ case SYS_PMXEVCNTR_EL0:
+ idx = SYS_FIELD_GET(PMSELR_EL0, SEL,
+ __vcpu_sys_reg(vcpu, PMSELR_EL0));
+ break;
+ default:
+ /* Someone used this trap helper for something else... */
+ KVM_BUG_ON(1, vcpu->kvm);
+ return BEHAVE_HANDLE_LOCALLY;
+ }
+
+ if (kvm_pmu_counter_is_hyp(vcpu, idx))
+ return BEHAVE_FORWARD_RW | BEHAVE_FORWARD_IN_HOST_EL0;
return BEHAVE_HANDLE_LOCALLY;
}
@@ -505,6 +535,7 @@ static const complex_condition_check ccc[] = {
CCC(CGT_CNTHCTL_EL1PCTEN, check_cnthctl_el1pcten),
CCC(CGT_CNTHCTL_EL1PTEN, check_cnthctl_el1pten),
CCC(CGT_CPTR_TTA, check_cptr_tta),
+ CCC(CGT_MDCR_HPMN, check_mdcr_hpmn),
};
/*
@@ -711,6 +742,10 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
SR_TRAP(SYS_MAIR_EL1, CGT_HCR_TVM_TRVM),
SR_TRAP(SYS_AMAIR_EL1, CGT_HCR_TVM_TRVM),
SR_TRAP(SYS_CONTEXTIDR_EL1, CGT_HCR_TVM_TRVM),
+ SR_TRAP(SYS_PIR_EL1, CGT_HCR_TVM_TRVM),
+ SR_TRAP(SYS_PIRE0_EL1, CGT_HCR_TVM_TRVM),
+ SR_TRAP(SYS_POR_EL0, CGT_HCR_TVM_TRVM),
+ SR_TRAP(SYS_POR_EL1, CGT_HCR_TVM_TRVM),
SR_TRAP(SYS_TCR2_EL1, CGT_HCR_TVM_TRVM_HCRX_TCR2En),
SR_TRAP(SYS_DC_ZVA, CGT_HCR_TDZ),
SR_TRAP(SYS_DC_GVA, CGT_HCR_TDZ),
@@ -919,77 +954,77 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
SR_TRAP(SYS_PMOVSCLR_EL0, CGT_MDCR_TPM),
SR_TRAP(SYS_PMCEID0_EL0, CGT_MDCR_TPM),
SR_TRAP(SYS_PMCEID1_EL0, CGT_MDCR_TPM),
- SR_TRAP(SYS_PMXEVTYPER_EL0, CGT_MDCR_TPM),
+ SR_TRAP(SYS_PMXEVTYPER_EL0, CGT_MDCR_TPM_HPMN),
SR_TRAP(SYS_PMSWINC_EL0, CGT_MDCR_TPM),
SR_TRAP(SYS_PMSELR_EL0, CGT_MDCR_TPM),
- SR_TRAP(SYS_PMXEVCNTR_EL0, CGT_MDCR_TPM),
+ SR_TRAP(SYS_PMXEVCNTR_EL0, CGT_MDCR_TPM_HPMN),
SR_TRAP(SYS_PMCCNTR_EL0, CGT_MDCR_TPM),
SR_TRAP(SYS_PMUSERENR_EL0, CGT_MDCR_TPM),
SR_TRAP(SYS_PMINTENSET_EL1, CGT_MDCR_TPM),
SR_TRAP(SYS_PMINTENCLR_EL1, CGT_MDCR_TPM),
SR_TRAP(SYS_PMMIR_EL1, CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(0), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(1), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(2), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(3), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(4), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(5), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(6), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(7), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(8), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(9), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(10), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(11), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(12), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(13), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(14), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(15), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(16), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(17), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(18), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(19), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(20), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(21), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(22), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(23), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(24), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(25), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(26), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(27), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(28), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(29), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVCNTRn_EL0(30), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(0), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(1), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(2), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(3), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(4), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(5), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(6), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(7), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(8), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(9), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(10), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(11), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(12), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(13), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(14), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(15), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(16), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(17), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(18), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(19), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(20), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(21), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(22), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(23), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(24), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(25), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(26), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(27), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(28), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(29), CGT_MDCR_TPM),
- SR_TRAP(SYS_PMEVTYPERn_EL0(30), CGT_MDCR_TPM),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(0), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(1), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(2), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(3), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(4), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(5), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(6), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(7), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(8), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(9), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(10), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(11), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(12), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(13), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(14), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(15), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(16), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(17), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(18), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(19), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(20), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(21), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(22), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(23), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(24), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(25), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(26), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(27), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(28), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(29), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVCNTRn_EL0(30), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(0), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(1), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(2), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(3), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(4), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(5), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(6), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(7), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(8), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(9), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(10), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(11), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(12), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(13), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(14), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(15), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(16), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(17), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(18), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(19), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(20), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(21), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(22), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(23), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(24), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(25), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(26), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(27), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(28), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(29), CGT_MDCR_TPM_HPMN),
+ SR_TRAP(SYS_PMEVTYPERn_EL0(30), CGT_MDCR_TPM_HPMN),
SR_TRAP(SYS_PMCCFILTR_EL0, CGT_MDCR_TPM),
SR_TRAP(SYS_MDCCSR_EL0, CGT_MDCR_TDCC_TDE_TDA),
SR_TRAP(SYS_MDCCINT_EL1, CGT_MDCR_TDCC_TDE_TDA),
@@ -1141,7 +1176,6 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
SR_TRAP(SYS_AMEVTYPER1_EL0(13), CGT_CPTR_TAM),
SR_TRAP(SYS_AMEVTYPER1_EL0(14), CGT_CPTR_TAM),
SR_TRAP(SYS_AMEVTYPER1_EL0(15), CGT_CPTR_TAM),
- SR_TRAP(SYS_POR_EL0, CGT_CPACR_E0POE),
/* op0=2, op1=1, and CRn<0b1000 */
SR_RANGE_TRAP(sys_reg(2, 1, 0, 0, 0),
sys_reg(2, 1, 7, 15, 7), CGT_CPTR_TTA),
@@ -2021,7 +2055,8 @@ check_mcb:
cgids = coarse_control_combo[id - __MULTIPLE_CONTROL_BITS__];
for (int i = 0; cgids[i] != __RESERVED__; i++) {
- if (cgids[i] >= __MULTIPLE_CONTROL_BITS__) {
+ if (cgids[i] >= __MULTIPLE_CONTROL_BITS__ &&
+ cgids[i] < __COMPLEX_CONDITIONS__) {
kvm_err("Recursive MCB %d/%d\n", id, cgids[i]);
ret = -EINVAL;
}
@@ -2126,11 +2161,19 @@ static u64 kvm_get_sysreg_res0(struct kvm *kvm, enum vcpu_sysreg sr)
return masks->mask[sr - __VNCR_START__].res0;
}
-static bool check_fgt_bit(struct kvm *kvm, bool is_read,
+static bool check_fgt_bit(struct kvm_vcpu *vcpu, bool is_read,
u64 val, const union trap_config tc)
{
+ struct kvm *kvm = vcpu->kvm;
enum vcpu_sysreg sr;
+ /*
+ * KVM doesn't know about any FGTs that apply to the host, and hopefully
+ * that'll remain the case.
+ */
+ if (is_hyp_ctxt(vcpu))
+ return false;
+
if (tc.pol)
return (val & BIT(tc.bit));
@@ -2207,7 +2250,15 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)
* If we're not nesting, immediately return to the caller, with the
* sysreg index, should we have it.
*/
- if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
+ if (!vcpu_has_nv(vcpu))
+ goto local;
+
+ /*
+ * There are a few traps that take effect InHost, but are constrained
+ * to EL0. Don't bother with computing the trap behaviour if the vCPU
+ * isn't in EL0.
+ */
+ if (is_hyp_ctxt(vcpu) && !vcpu_is_host_el0(vcpu))
goto local;
switch ((enum fgt_group_id)tc.fgt) {
@@ -2253,12 +2304,14 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)
goto local;
}
- if (tc.fgt != __NO_FGT_GROUP__ && check_fgt_bit(vcpu->kvm, is_read,
- val, tc))
+ if (tc.fgt != __NO_FGT_GROUP__ && check_fgt_bit(vcpu, is_read, val, tc))
goto inject;
b = compute_trap_behaviour(vcpu, tc);
+ if (!(b & BEHAVE_FORWARD_IN_HOST_EL0) && vcpu_is_host_el0(vcpu))
+ goto local;
+
if (((b & BEHAVE_FORWARD_READ) && is_read) ||
((b & BEHAVE_FORWARD_WRITE) && !is_read))
goto inject;
@@ -2393,6 +2446,8 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
kvm_arch_vcpu_load(vcpu, smp_processor_id());
preempt_enable();
+
+ kvm_pmu_nested_transition(vcpu);
}
static void kvm_inject_el2_exception(struct kvm_vcpu *vcpu, u64 esr_el2,
@@ -2475,6 +2530,8 @@ static int kvm_inject_nested(struct kvm_vcpu *vcpu, u64 esr_el2,
kvm_arch_vcpu_load(vcpu, smp_processor_id());
preempt_enable();
+ kvm_pmu_nested_transition(vcpu);
+
return 1;
}
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 962f985977c2..12dad841f2a5 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -1051,50 +1051,58 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
}
while (length > 0) {
- kvm_pfn_t pfn = gfn_to_pfn_prot(kvm, gfn, write, NULL);
+ struct page *page = __gfn_to_page(kvm, gfn, write);
void *maddr;
unsigned long num_tags;
- struct page *page;
+ struct folio *folio;
- if (is_error_noslot_pfn(pfn)) {
+ if (!page) {
ret = -EFAULT;
goto out;
}
- page = pfn_to_online_page(pfn);
- if (!page) {
+ if (!pfn_to_online_page(page_to_pfn(page))) {
/* Reject ZONE_DEVICE memory */
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_unused(page);
ret = -EFAULT;
goto out;
}
+ folio = page_folio(page);
maddr = page_address(page);
if (!write) {
- if (page_mte_tagged(page))
+ if ((folio_test_hugetlb(folio) &&
+ folio_test_hugetlb_mte_tagged(folio)) ||
+ page_mte_tagged(page))
num_tags = mte_copy_tags_to_user(tags, maddr,
MTE_GRANULES_PER_PAGE);
else
/* No tags in memory, so write zeros */
num_tags = MTE_GRANULES_PER_PAGE -
clear_user(tags, MTE_GRANULES_PER_PAGE);
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_clean(page);
} else {
/*
* Only locking to serialise with a concurrent
* __set_ptes() in the VMM but still overriding the
* tags, hence ignoring the return value.
*/
- try_page_mte_tagging(page);
+ if (folio_test_hugetlb(folio))
+ folio_try_hugetlb_mte_tagging(folio);
+ else
+ try_page_mte_tagging(page);
num_tags = mte_copy_tags_from_user(maddr, tags,
MTE_GRANULES_PER_PAGE);
/* uaccess failed, don't leave stale tags */
if (num_tags != MTE_GRANULES_PER_PAGE)
mte_clear_page_tags(maddr);
- set_page_mte_tagged(page);
+ if (folio_test_hugetlb(folio))
+ folio_set_hugetlb_mte_tagged(folio);
+ else
+ set_page_mte_tagged(page);
- kvm_release_pfn_dirty(pfn);
+ kvm_release_page_dirty(page);
}
if (num_tags != MTE_GRANULES_PER_PAGE) {
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 5310fe1da616..34f53707892d 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -204,6 +204,35 @@ static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu)
__deactivate_fgt(hctxt, vcpu, kvm, HAFGRTR_EL2);
}
+static inline void __activate_traps_mpam(struct kvm_vcpu *vcpu)
+{
+ u64 r = MPAM2_EL2_TRAPMPAM0EL1 | MPAM2_EL2_TRAPMPAM1EL1;
+
+ if (!system_supports_mpam())
+ return;
+
+ /* trap guest access to MPAMIDR_EL1 */
+ if (system_supports_mpam_hcr()) {
+ write_sysreg_s(MPAMHCR_EL2_TRAP_MPAMIDR_EL1, SYS_MPAMHCR_EL2);
+ } else {
+ /* From v1.1 TIDR can trap MPAMIDR, set it unconditionally */
+ r |= MPAM2_EL2_TIDR;
+ }
+
+ write_sysreg_s(r, SYS_MPAM2_EL2);
+}
+
+static inline void __deactivate_traps_mpam(void)
+{
+ if (!system_supports_mpam())
+ return;
+
+ write_sysreg_s(0, SYS_MPAM2_EL2);
+
+ if (system_supports_mpam_hcr())
+ write_sysreg_s(MPAMHCR_HOST_FLAGS, SYS_MPAMHCR_EL2);
+}
+
static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
{
/* Trap on AArch32 cp15 c15 (impdef sysregs) accesses (EL1 or EL0) */
@@ -244,6 +273,7 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
}
__activate_traps_hfgxtr(vcpu);
+ __activate_traps_mpam(vcpu);
}
static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
@@ -263,6 +293,7 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
write_sysreg_s(HCRX_HOST_FLAGS, SYS_HCRX_EL2);
__deactivate_traps_hfgxtr(vcpu);
+ __deactivate_traps_mpam();
}
static inline void ___activate_traps(struct kvm_vcpu *vcpu, u64 hcr)
diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
index 1579a3c08a36..a651c43ad679 100644
--- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
+++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
@@ -58,7 +58,7 @@ static inline bool ctxt_has_s1pie(struct kvm_cpu_context *ctxt)
return false;
vcpu = ctxt_to_vcpu(ctxt);
- return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1PIE, IMP);
+ return kvm_has_s1pie(kern_hyp_va(vcpu->kvm));
}
static inline bool ctxt_has_tcrx(struct kvm_cpu_context *ctxt)
@@ -69,7 +69,7 @@ static inline bool ctxt_has_tcrx(struct kvm_cpu_context *ctxt)
return false;
vcpu = ctxt_to_vcpu(ctxt);
- return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, TCRX, IMP);
+ return kvm_has_tcr2(kern_hyp_va(vcpu->kvm));
}
static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt)
@@ -80,7 +80,7 @@ static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt)
return false;
vcpu = ctxt_to_vcpu(ctxt);
- return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1POE, IMP);
+ return kvm_has_s1poe(kern_hyp_va(vcpu->kvm));
}
static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
@@ -152,9 +152,10 @@ static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
write_sysreg(ctxt_sys_reg(ctxt, TPIDRRO_EL0), tpidrro_el0);
}
-static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
+static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt,
+ u64 mpidr)
{
- write_sysreg(ctxt_sys_reg(ctxt, MPIDR_EL1), vmpidr_el2);
+ write_sysreg(mpidr, vmpidr_el2);
if (has_vhe() ||
!cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
diff --git a/arch/arm64/kvm/hyp/include/nvhe/trap_handler.h b/arch/arm64/kvm/hyp/include/nvhe/trap_handler.h
index 45a84f0ade04..1e6d995968a1 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/trap_handler.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/trap_handler.h
@@ -15,6 +15,4 @@
#define DECLARE_REG(type, name, ctxt, reg) \
type name = (type)cpu_reg(ctxt, (reg))
-void __pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu);
-
#endif /* __ARM64_KVM_NVHE_TRAP_HANDLER_H__ */
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index fefc89209f9e..6aa0b13d86e5 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -105,8 +105,10 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_vcpu->vcpu.arch.hw_mmu = host_vcpu->arch.hw_mmu;
- hyp_vcpu->vcpu.arch.hcr_el2 = host_vcpu->arch.hcr_el2;
hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
+ hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
+ hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
+ (HCR_TWI | HCR_TWE);
hyp_vcpu->vcpu.arch.iflags = host_vcpu->arch.iflags;
@@ -349,13 +351,6 @@ static void handle___pkvm_prot_finalize(struct kvm_cpu_context *host_ctxt)
cpu_reg(host_ctxt, 1) = __pkvm_prot_finalize();
}
-static void handle___pkvm_vcpu_init_traps(struct kvm_cpu_context *host_ctxt)
-{
- DECLARE_REG(struct kvm_vcpu *, vcpu, host_ctxt, 1);
-
- __pkvm_vcpu_init_traps(kern_hyp_va(vcpu));
-}
-
static void handle___pkvm_init_vm(struct kvm_cpu_context *host_ctxt)
{
DECLARE_REG(struct kvm *, host_kvm, host_ctxt, 1);
@@ -411,7 +406,6 @@ static const hcall_t host_hcall[] = {
HANDLE_FUNC(__kvm_timer_set_cntvoff),
HANDLE_FUNC(__vgic_v3_save_vmcr_aprs),
HANDLE_FUNC(__vgic_v3_restore_vmcr_aprs),
- HANDLE_FUNC(__pkvm_vcpu_init_traps),
HANDLE_FUNC(__pkvm_init_vm),
HANDLE_FUNC(__pkvm_init_vcpu),
HANDLE_FUNC(__pkvm_teardown_vm),
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 077d4098548d..01616c39a810 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -6,6 +6,9 @@
#include <linux/kvm_host.h>
#include <linux/mm.h>
+
+#include <asm/kvm_emulate.h>
+
#include <nvhe/fixed_config.h>
#include <nvhe/mem_protect.h>
#include <nvhe/memory.h>
@@ -201,11 +204,46 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu)
}
}
+static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
+
+ if (has_hvhe())
+ vcpu->arch.hcr_el2 |= HCR_E2H;
+
+ if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) {
+ /* route synchronous external abort exceptions to EL2 */
+ vcpu->arch.hcr_el2 |= HCR_TEA;
+ /* trap error record accesses */
+ vcpu->arch.hcr_el2 |= HCR_TERR;
+ }
+
+ if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
+ vcpu->arch.hcr_el2 |= HCR_FWB;
+
+ if (cpus_have_final_cap(ARM64_HAS_EVT) &&
+ !cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE))
+ vcpu->arch.hcr_el2 |= HCR_TID4;
+ else
+ vcpu->arch.hcr_el2 |= HCR_TID2;
+
+ if (vcpu_has_ptrauth(vcpu))
+ vcpu->arch.hcr_el2 |= (HCR_API | HCR_APK);
+}
+
/*
* Initialize trap register values in protected mode.
*/
-void __pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu)
+static void pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu)
{
+ vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu);
+ vcpu->arch.mdcr_el2 = 0;
+
+ pkvm_vcpu_reset_hcr(vcpu);
+
+ if ((!vcpu_is_protected(vcpu)))
+ return;
+
pvm_init_trap_regs(vcpu);
pvm_init_traps_aa64pfr0(vcpu);
pvm_init_traps_aa64pfr1(vcpu);
@@ -289,6 +327,65 @@ void pkvm_put_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_spin_unlock(&vm_table_lock);
}
+static void pkvm_init_features_from_host(struct pkvm_hyp_vm *hyp_vm, const struct kvm *host_kvm)
+{
+ struct kvm *kvm = &hyp_vm->kvm;
+ DECLARE_BITMAP(allowed_features, KVM_VCPU_MAX_FEATURES);
+
+ /* No restrictions for non-protected VMs. */
+ if (!kvm_vm_is_protected(kvm)) {
+ bitmap_copy(kvm->arch.vcpu_features,
+ host_kvm->arch.vcpu_features,
+ KVM_VCPU_MAX_FEATURES);
+ return;
+ }
+
+ bitmap_zero(allowed_features, KVM_VCPU_MAX_FEATURES);
+
+ /*
+ * For protected VMs, always allow:
+ * - CPU starting in poweroff state
+ * - PSCI v0.2
+ */
+ set_bit(KVM_ARM_VCPU_POWER_OFF, allowed_features);
+ set_bit(KVM_ARM_VCPU_PSCI_0_2, allowed_features);
+
+ /*
+ * Check if remaining features are allowed:
+ * - Performance Monitoring
+ * - Scalable Vectors
+ * - Pointer Authentication
+ */
+ if (FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), PVM_ID_AA64DFR0_ALLOW))
+ set_bit(KVM_ARM_VCPU_PMU_V3, allowed_features);
+
+ if (FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), PVM_ID_AA64PFR0_ALLOW))
+ set_bit(KVM_ARM_VCPU_SVE, allowed_features);
+
+ if (FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_EL1_API), PVM_ID_AA64ISAR1_RESTRICT_UNSIGNED) &&
+ FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_EL1_APA), PVM_ID_AA64ISAR1_RESTRICT_UNSIGNED))
+ set_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, allowed_features);
+
+ if (FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_EL1_GPI), PVM_ID_AA64ISAR1_ALLOW) &&
+ FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_EL1_GPA), PVM_ID_AA64ISAR1_ALLOW))
+ set_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, allowed_features);
+
+ bitmap_and(kvm->arch.vcpu_features, host_kvm->arch.vcpu_features,
+ allowed_features, KVM_VCPU_MAX_FEATURES);
+}
+
+static void pkvm_vcpu_init_ptrauth(struct pkvm_hyp_vcpu *hyp_vcpu)
+{
+ struct kvm_vcpu *vcpu = &hyp_vcpu->vcpu;
+
+ if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_PTRAUTH_ADDRESS) ||
+ vcpu_has_feature(vcpu, KVM_ARM_VCPU_PTRAUTH_GENERIC)) {
+ kvm_vcpu_enable_ptrauth(vcpu);
+ } else {
+ vcpu_clear_flag(&hyp_vcpu->vcpu, GUEST_HAS_PTRAUTH);
+ }
+}
+
static void unpin_host_vcpu(struct kvm_vcpu *host_vcpu)
{
if (host_vcpu)
@@ -310,6 +407,18 @@ static void init_pkvm_hyp_vm(struct kvm *host_kvm, struct pkvm_hyp_vm *hyp_vm,
hyp_vm->host_kvm = host_kvm;
hyp_vm->kvm.created_vcpus = nr_vcpus;
hyp_vm->kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
+ hyp_vm->kvm.arch.pkvm.enabled = READ_ONCE(host_kvm->arch.pkvm.enabled);
+ pkvm_init_features_from_host(hyp_vm, host_kvm);
+}
+
+static void pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp_vcpu, struct kvm_vcpu *host_vcpu)
+{
+ struct kvm_vcpu *vcpu = &hyp_vcpu->vcpu;
+
+ if (!vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) {
+ vcpu_clear_flag(vcpu, GUEST_HAS_SVE);
+ vcpu_clear_flag(vcpu, VCPU_SVE_FINALIZED);
+ }
}
static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu,
@@ -335,6 +444,11 @@ static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu,
hyp_vcpu->vcpu.arch.hw_mmu = &hyp_vm->kvm.arch.mmu;
hyp_vcpu->vcpu.arch.cflags = READ_ONCE(host_vcpu->arch.cflags);
+ hyp_vcpu->vcpu.arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
+
+ pkvm_vcpu_init_sve(hyp_vcpu, host_vcpu);
+ pkvm_vcpu_init_ptrauth(hyp_vcpu);
+ pkvm_vcpu_init_traps(&hyp_vcpu->vcpu);
done:
if (ret)
unpin_host_vcpu(host_vcpu);
diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
index dfe8fe0f7eaf..9c2ce1e0e99a 100644
--- a/arch/arm64/kvm/hyp/nvhe/psci-relay.c
+++ b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
@@ -265,6 +265,8 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_
case PSCI_1_0_FN_PSCI_FEATURES:
case PSCI_1_0_FN_SET_SUSPEND_MODE:
case PSCI_1_1_FN64_SYSTEM_RESET2:
+ case PSCI_1_3_FN_SYSTEM_OFF2:
+ case PSCI_1_3_FN64_SYSTEM_OFF2:
return psci_forward(host_ctxt);
case PSCI_1_0_FN64_SYSTEM_SUSPEND:
return psci_system_suspend(func_id, host_ctxt);
diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index 174007f3fadd..cbdd18cd3f98 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -95,7 +95,6 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
{
void *start, *end, *virt = hyp_phys_to_virt(phys);
unsigned long pgt_size = hyp_s1_pgtable_pages() << PAGE_SHIFT;
- enum kvm_pgtable_prot prot;
int ret, i;
/* Recreate the hyp page-table using the early page allocator */
@@ -147,24 +146,7 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
return ret;
}
- pkvm_create_host_sve_mappings();
-
- /*
- * Map the host sections RO in the hypervisor, but transfer the
- * ownership from the host to the hypervisor itself to make sure they
- * can't be donated or shared with another entity.
- *
- * The ownership transition requires matching changes in the host
- * stage-2. This will be done later (see finalize_host_mappings()) once
- * the hyp_vmemmap is addressable.
- */
- prot = pkvm_mkstate(PAGE_HYP_RO, PKVM_PAGE_SHARED_OWNED);
- ret = pkvm_create_mappings(&kvm_vgic_global_state,
- &kvm_vgic_global_state + 1, prot);
- if (ret)
- return ret;
-
- return 0;
+ return pkvm_create_host_sve_mappings();
}
static void update_nvhe_init_params(void)
diff --git a/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c b/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c
index 29305022bc04..dba101565de3 100644
--- a/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c
@@ -28,7 +28,7 @@ void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt)
void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt)
{
- __sysreg_restore_el1_state(ctxt);
+ __sysreg_restore_el1_state(ctxt, ctxt_sys_reg(ctxt, MPIDR_EL1));
__sysreg_restore_common_state(ctxt);
__sysreg_restore_user_state(ctxt);
__sysreg_restore_el2_return_state(ctxt);
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index b11bcebac908..40bd55966540 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -1245,19 +1245,16 @@ int kvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
NULL, NULL, 0);
}
-kvm_pte_t kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr)
+void kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr)
{
- kvm_pte_t pte = 0;
int ret;
ret = stage2_update_leaf_attrs(pgt, addr, 1, KVM_PTE_LEAF_ATTR_LO_S2_AF, 0,
- &pte, NULL,
+ NULL, NULL,
KVM_PGTABLE_WALK_HANDLE_FAULT |
KVM_PGTABLE_WALK_SHARED);
if (!ret)
dsb(ishst);
-
- return pte;
}
struct stage2_age_data {
diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index 18d4677002b1..3f9741e51d41 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -1012,9 +1012,6 @@ static void __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
/* IDbits */
val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
- /* SEIS */
- if (kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK)
- val |= BIT(ICC_CTLR_EL1_SEIS_SHIFT);
/* A3V */
val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
/* EOImode */
diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
index e12bd7d6d2dc..5f78a39053a7 100644
--- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c
@@ -15,6 +15,131 @@
#include <asm/kvm_hyp.h>
#include <asm/kvm_nested.h>
+static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu)
+{
+ /* These registers are common with EL1 */
+ __vcpu_sys_reg(vcpu, PAR_EL1) = read_sysreg(par_el1);
+ __vcpu_sys_reg(vcpu, TPIDR_EL1) = read_sysreg(tpidr_el1);
+
+ __vcpu_sys_reg(vcpu, ESR_EL2) = read_sysreg_el1(SYS_ESR);
+ __vcpu_sys_reg(vcpu, AFSR0_EL2) = read_sysreg_el1(SYS_AFSR0);
+ __vcpu_sys_reg(vcpu, AFSR1_EL2) = read_sysreg_el1(SYS_AFSR1);
+ __vcpu_sys_reg(vcpu, FAR_EL2) = read_sysreg_el1(SYS_FAR);
+ __vcpu_sys_reg(vcpu, MAIR_EL2) = read_sysreg_el1(SYS_MAIR);
+ __vcpu_sys_reg(vcpu, VBAR_EL2) = read_sysreg_el1(SYS_VBAR);
+ __vcpu_sys_reg(vcpu, CONTEXTIDR_EL2) = read_sysreg_el1(SYS_CONTEXTIDR);
+ __vcpu_sys_reg(vcpu, AMAIR_EL2) = read_sysreg_el1(SYS_AMAIR);
+
+ /*
+ * In VHE mode those registers are compatible between EL1 and EL2,
+ * and the guest uses the _EL1 versions on the CPU naturally.
+ * So we save them into their _EL2 versions here.
+ * For nVHE mode we trap accesses to those registers, so our
+ * _EL2 copy in sys_regs[] is always up-to-date and we don't need
+ * to save anything here.
+ */
+ if (vcpu_el2_e2h_is_set(vcpu)) {
+ u64 val;
+
+ /*
+ * We don't save CPTR_EL2, as accesses to CPACR_EL1
+ * are always trapped, ensuring that the in-memory
+ * copy is always up-to-date. A small blessing...
+ */
+ __vcpu_sys_reg(vcpu, SCTLR_EL2) = read_sysreg_el1(SYS_SCTLR);
+ __vcpu_sys_reg(vcpu, TTBR0_EL2) = read_sysreg_el1(SYS_TTBR0);
+ __vcpu_sys_reg(vcpu, TTBR1_EL2) = read_sysreg_el1(SYS_TTBR1);
+ __vcpu_sys_reg(vcpu, TCR_EL2) = read_sysreg_el1(SYS_TCR);
+
+ if (ctxt_has_tcrx(&vcpu->arch.ctxt)) {
+ __vcpu_sys_reg(vcpu, TCR2_EL2) = read_sysreg_el1(SYS_TCR2);
+
+ if (ctxt_has_s1pie(&vcpu->arch.ctxt)) {
+ __vcpu_sys_reg(vcpu, PIRE0_EL2) = read_sysreg_el1(SYS_PIRE0);
+ __vcpu_sys_reg(vcpu, PIR_EL2) = read_sysreg_el1(SYS_PIR);
+ }
+
+ if (ctxt_has_s1poe(&vcpu->arch.ctxt))
+ __vcpu_sys_reg(vcpu, POR_EL2) = read_sysreg_el1(SYS_POR);
+ }
+
+ /*
+ * The EL1 view of CNTKCTL_EL1 has a bunch of RES0 bits where
+ * the interesting CNTHCTL_EL2 bits live. So preserve these
+ * bits when reading back the guest-visible value.
+ */
+ val = read_sysreg_el1(SYS_CNTKCTL);
+ val &= CNTKCTL_VALID_BITS;
+ __vcpu_sys_reg(vcpu, CNTHCTL_EL2) &= ~CNTKCTL_VALID_BITS;
+ __vcpu_sys_reg(vcpu, CNTHCTL_EL2) |= val;
+ }
+
+ __vcpu_sys_reg(vcpu, SP_EL2) = read_sysreg(sp_el1);
+ __vcpu_sys_reg(vcpu, ELR_EL2) = read_sysreg_el1(SYS_ELR);
+ __vcpu_sys_reg(vcpu, SPSR_EL2) = read_sysreg_el1(SYS_SPSR);
+}
+
+static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu)
+{
+ u64 val;
+
+ /* These registers are common with EL1 */
+ write_sysreg(__vcpu_sys_reg(vcpu, PAR_EL1), par_el1);
+ write_sysreg(__vcpu_sys_reg(vcpu, TPIDR_EL1), tpidr_el1);
+
+ write_sysreg(__vcpu_sys_reg(vcpu, MPIDR_EL1), vmpidr_el2);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, MAIR_EL2), SYS_MAIR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, VBAR_EL2), SYS_VBAR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, CONTEXTIDR_EL2), SYS_CONTEXTIDR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, AMAIR_EL2), SYS_AMAIR);
+
+ if (vcpu_el2_e2h_is_set(vcpu)) {
+ /*
+ * In VHE mode those registers are compatible between
+ * EL1 and EL2.
+ */
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, SCTLR_EL2), SYS_SCTLR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, CPTR_EL2), SYS_CPACR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, TTBR0_EL2), SYS_TTBR0);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, TTBR1_EL2), SYS_TTBR1);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, TCR_EL2), SYS_TCR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, CNTHCTL_EL2), SYS_CNTKCTL);
+ } else {
+ /*
+ * CNTHCTL_EL2 only affects EL1 when running nVHE, so
+ * no need to restore it.
+ */
+ val = translate_sctlr_el2_to_sctlr_el1(__vcpu_sys_reg(vcpu, SCTLR_EL2));
+ write_sysreg_el1(val, SYS_SCTLR);
+ val = translate_cptr_el2_to_cpacr_el1(__vcpu_sys_reg(vcpu, CPTR_EL2));
+ write_sysreg_el1(val, SYS_CPACR);
+ val = translate_ttbr0_el2_to_ttbr0_el1(__vcpu_sys_reg(vcpu, TTBR0_EL2));
+ write_sysreg_el1(val, SYS_TTBR0);
+ val = translate_tcr_el2_to_tcr_el1(__vcpu_sys_reg(vcpu, TCR_EL2));
+ write_sysreg_el1(val, SYS_TCR);
+ }
+
+ if (ctxt_has_tcrx(&vcpu->arch.ctxt)) {
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, TCR2_EL2), SYS_TCR2);
+
+ if (ctxt_has_s1pie(&vcpu->arch.ctxt)) {
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, PIR_EL2), SYS_PIR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, PIRE0_EL2), SYS_PIRE0);
+ }
+
+ if (ctxt_has_s1poe(&vcpu->arch.ctxt))
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, POR_EL2), SYS_POR);
+ }
+
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, ESR_EL2), SYS_ESR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, AFSR0_EL2), SYS_AFSR0);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, AFSR1_EL2), SYS_AFSR1);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, FAR_EL2), SYS_FAR);
+ write_sysreg(__vcpu_sys_reg(vcpu, SP_EL2), sp_el1);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, ELR_EL2), SYS_ELR);
+ write_sysreg_el1(__vcpu_sys_reg(vcpu, SPSR_EL2), SYS_SPSR);
+}
+
/*
* VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and
* pstate, which are handled as part of the el2 return state) on every
@@ -66,6 +191,7 @@ void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
struct kvm_cpu_context *host_ctxt;
+ u64 mpidr;
host_ctxt = host_data_ptr(host_ctxt);
__sysreg_save_user_state(host_ctxt);
@@ -89,7 +215,29 @@ void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu)
*/
__sysreg32_restore_state(vcpu);
__sysreg_restore_user_state(guest_ctxt);
- __sysreg_restore_el1_state(guest_ctxt);
+
+ if (unlikely(__is_hyp_ctxt(guest_ctxt))) {
+ __sysreg_restore_vel2_state(vcpu);
+ } else {
+ if (vcpu_has_nv(vcpu)) {
+ /*
+ * Use the guest hypervisor's VPIDR_EL2 when in a
+ * nested state. The hardware value of MIDR_EL1 gets
+ * restored on put.
+ */
+ write_sysreg(ctxt_sys_reg(guest_ctxt, VPIDR_EL2), vpidr_el2);
+
+ /*
+ * As we're restoring a nested guest, set the value
+ * provided by the guest hypervisor.
+ */
+ mpidr = ctxt_sys_reg(guest_ctxt, VMPIDR_EL2);
+ } else {
+ mpidr = ctxt_sys_reg(guest_ctxt, MPIDR_EL1);
+ }
+
+ __sysreg_restore_el1_state(guest_ctxt, mpidr);
+ }
vcpu_set_flag(vcpu, SYSREGS_ON_CPU);
}
@@ -112,12 +260,20 @@ void __vcpu_put_switch_sysregs(struct kvm_vcpu *vcpu)
host_ctxt = host_data_ptr(host_ctxt);
- __sysreg_save_el1_state(guest_ctxt);
+ if (unlikely(__is_hyp_ctxt(guest_ctxt)))
+ __sysreg_save_vel2_state(vcpu);
+ else
+ __sysreg_save_el1_state(guest_ctxt);
+
__sysreg_save_user_state(guest_ctxt);
__sysreg32_save_state(vcpu);
/* Restore host user state */
__sysreg_restore_user_state(host_ctxt);
+ /* If leaving a nesting guest, restore MIDR_EL1 default view */
+ if (vcpu_has_nv(vcpu))
+ write_sysreg(read_cpuid_id(), vpidr_el2);
+
vcpu_clear_flag(vcpu, SYSREGS_ON_CPU);
}
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index ee6573befb81..27ce4cb44904 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -575,6 +575,8 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
case KVM_ARM_PSCI_0_2:
case KVM_ARM_PSCI_1_0:
case KVM_ARM_PSCI_1_1:
+ case KVM_ARM_PSCI_1_2:
+ case KVM_ARM_PSCI_1_3:
if (!wants_02)
return -EINVAL;
vcpu->kvm->arch.psci_version = val;
diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
index cd6b7b83e2c3..ab365e839874 100644
--- a/arch/arm64/kvm/mmio.c
+++ b/arch/arm64/kvm/mmio.c
@@ -72,6 +72,31 @@ unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
return data;
}
+static bool kvm_pending_sync_exception(struct kvm_vcpu *vcpu)
+{
+ if (!vcpu_get_flag(vcpu, PENDING_EXCEPTION))
+ return false;
+
+ if (vcpu_el1_is_32bit(vcpu)) {
+ switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
+ case unpack_vcpu_flag(EXCEPT_AA32_UND):
+ case unpack_vcpu_flag(EXCEPT_AA32_IABT):
+ case unpack_vcpu_flag(EXCEPT_AA32_DABT):
+ return true;
+ default:
+ return false;
+ }
+ } else {
+ switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
+ case unpack_vcpu_flag(EXCEPT_AA64_EL1_SYNC):
+ case unpack_vcpu_flag(EXCEPT_AA64_EL2_SYNC):
+ return true;
+ default:
+ return false;
+ }
+ }
+}
+
/**
* kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
* or in-kernel IO emulation
@@ -84,8 +109,11 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
unsigned int len;
int mask;
- /* Detect an already handled MMIO return */
- if (unlikely(!vcpu->mmio_needed))
+ /*
+ * Detect if the MMIO return was already handled or if userspace aborted
+ * the MMIO access.
+ */
+ if (unlikely(!vcpu->mmio_needed || kvm_pending_sync_exception(vcpu)))
return 1;
vcpu->mmio_needed = 0;
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 0f7658aefa1a..c9d46ad57e52 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1402,10 +1402,21 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,
{
unsigned long i, nr_pages = size >> PAGE_SHIFT;
struct page *page = pfn_to_page(pfn);
+ struct folio *folio = page_folio(page);
if (!kvm_has_mte(kvm))
return;
+ if (folio_test_hugetlb(folio)) {
+ /* Hugetlb has MTE flags set on head page only */
+ if (folio_try_hugetlb_mte_tagging(folio)) {
+ for (i = 0; i < nr_pages; i++, page++)
+ mte_clear_page_tags(page_address(page));
+ folio_set_hugetlb_mte_tagged(folio);
+ }
+ return;
+ }
+
for (i = 0; i < nr_pages; i++, page++) {
if (try_page_mte_tagging(page)) {
mte_clear_page_tags(page_address(page));
@@ -1440,6 +1451,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
long vma_pagesize, fault_granule;
enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
struct kvm_pgtable *pgt;
+ struct page *page;
if (fault_is_perm)
fault_granule = kvm_vcpu_trap_get_perm_fault_granule(vcpu);
@@ -1561,7 +1573,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
/*
* Read mmu_invalidate_seq so that KVM can detect if the results of
- * vma_lookup() or __gfn_to_pfn_memslot() become stale prior to
+ * vma_lookup() or __kvm_faultin_pfn() become stale prior to
* acquiring kvm->mmu_lock.
*
* Rely on mmap_read_unlock() for an implicit smp_rmb(), which pairs
@@ -1570,8 +1582,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
mmu_seq = vcpu->kvm->mmu_invalidate_seq;
mmap_read_unlock(current->mm);
- pfn = __gfn_to_pfn_memslot(memslot, gfn, false, false, NULL,
- write_fault, &writable, NULL);
+ pfn = __kvm_faultin_pfn(memslot, gfn, write_fault ? FOLL_WRITE : 0,
+ &writable, &page);
if (pfn == KVM_PFN_ERR_HWPOISON) {
kvm_send_hwpoison_signal(hva, vma_shift);
return 0;
@@ -1584,7 +1596,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
* If the page was identified as device early by looking at
* the VMA flags, vma_pagesize is already representing the
* largest quantity we can map. If instead it was mapped
- * via gfn_to_pfn_prot(), vma_pagesize is set to PAGE_SIZE
+ * via __kvm_faultin_pfn(), vma_pagesize is set to PAGE_SIZE
* and must not be upgraded.
*
* In both cases, we don't let transparent_hugepage_adjust()
@@ -1693,33 +1705,27 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
}
out_unlock:
+ kvm_release_faultin_page(kvm, page, !!ret, writable);
read_unlock(&kvm->mmu_lock);
/* Mark the page dirty only if the fault is handled successfully */
- if (writable && !ret) {
- kvm_set_pfn_dirty(pfn);
+ if (writable && !ret)
mark_page_dirty_in_slot(kvm, memslot, gfn);
- }
- kvm_release_pfn_clean(pfn);
return ret != -EAGAIN ? ret : 0;
}
/* Resolve the access fault by making the page young again. */
static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
{
- kvm_pte_t pte;
struct kvm_s2_mmu *mmu;
trace_kvm_access_fault(fault_ipa);
read_lock(&vcpu->kvm->mmu_lock);
mmu = vcpu->arch.hw_mmu;
- pte = kvm_pgtable_stage2_mkyoung(mmu->pgt, fault_ipa);
+ kvm_pgtable_stage2_mkyoung(mmu->pgt, fault_ipa);
read_unlock(&vcpu->kvm->mmu_lock);
-
- if (kvm_pte_valid(pte))
- kvm_set_pfn_accessed(kvm_pte_to_pfn(pte));
}
/**
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index c4b17d90fc49..9b36218b48de 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -917,12 +917,13 @@ static void limit_nv_id_regs(struct kvm *kvm)
ID_AA64MMFR4_EL1_E2H0_NI_NV1);
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val);
- /* Only limited support for PMU, Debug, BPs and WPs */
+ /* Only limited support for PMU, Debug, BPs, WPs, and HPMN0 */
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1);
val &= (NV_FTR(DFR0, PMUVer) |
NV_FTR(DFR0, WRPs) |
NV_FTR(DFR0, BRPs) |
- NV_FTR(DFR0, DebugVer));
+ NV_FTR(DFR0, DebugVer) |
+ NV_FTR(DFR0, HPMN0));
/* Cap Debug to ARMv8.1 */
tmp = FIELD_GET(NV_FTR(DFR0, DebugVer), val);
@@ -933,15 +934,15 @@ static void limit_nv_id_regs(struct kvm *kvm)
kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val);
}
-u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysreg sr)
+u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *vcpu,
+ enum vcpu_sysreg sr, u64 v)
{
- u64 v = ctxt_sys_reg(&vcpu->arch.ctxt, sr);
struct kvm_sysreg_masks *masks;
masks = vcpu->kvm->arch.sysreg_masks;
if (masks) {
- sr -= __VNCR_START__;
+ sr -= __SANITISED_REG_START__;
v &= ~masks->mask[sr].res0;
v |= masks->mask[sr].res1;
@@ -950,9 +951,13 @@ u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysreg sr)
return v;
}
-static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
+static __always_inline void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
{
- int i = sr - __VNCR_START__;
+ int i = sr - __SANITISED_REG_START__;
+
+ BUILD_BUG_ON(!__builtin_constant_p(sr));
+ BUILD_BUG_ON(sr < __SANITISED_REG_START__);
+ BUILD_BUG_ON(sr >= NR_SYS_REGS);
kvm->arch.sysreg_masks->mask[i].res0 = res0;
kvm->arch.sysreg_masks->mask[i].res1 = res1;
@@ -1050,7 +1055,7 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
res0 |= HCRX_EL2_PTTWI;
if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, SCTLRX, IMP))
res0 |= HCRX_EL2_SCTLR2En;
- if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
+ if (!kvm_has_tcr2(kvm))
res0 |= HCRX_EL2_TCR2En;
if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
res0 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
@@ -1101,9 +1106,9 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
res0 |= (HFGxTR_EL2_nSMPRI_EL1 | HFGxTR_EL2_nTPIDR2_EL0);
if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, THE, IMP))
res0 |= HFGxTR_EL2_nRCWMASK_EL1;
- if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP))
+ if (!kvm_has_s1pie(kvm))
res0 |= (HFGxTR_EL2_nPIRE0_EL1 | HFGxTR_EL2_nPIR_EL1);
- if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1POE, IMP))
+ if (!kvm_has_s1poe(kvm))
res0 |= (HFGxTR_EL2_nPOR_EL0 | HFGxTR_EL2_nPOR_EL1);
if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S2POE, IMP))
res0 |= HFGxTR_EL2_nS2POR_EL1;
@@ -1200,6 +1205,28 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
res0 |= ~(res0 | res1);
set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
+ /* TCR2_EL2 */
+ res0 = TCR2_EL2_RES0;
+ res1 = TCR2_EL2_RES1;
+ if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, D128, IMP))
+ res0 |= (TCR2_EL2_DisCH0 | TCR2_EL2_DisCH1 | TCR2_EL2_D128);
+ if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, MEC, IMP))
+ res0 |= TCR2_EL2_AMEC1 | TCR2_EL2_AMEC0;
+ if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, HAFDBS, HAFT))
+ res0 |= TCR2_EL2_HAFT;
+ if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, THE, IMP))
+ res0 |= TCR2_EL2_PTTWI | TCR2_EL2_PnCH;
+ if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, AIE, IMP))
+ res0 |= TCR2_EL2_AIE;
+ if (!kvm_has_s1poe(kvm))
+ res0 |= TCR2_EL2_POE | TCR2_EL2_E0POE;
+ if (!kvm_has_s1pie(kvm))
+ res0 |= TCR2_EL2_PIE;
+ if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
+ res0 |= (TCR2_EL2_E0POE | TCR2_EL2_D128 |
+ TCR2_EL2_AMEC1 | TCR2_EL2_DisCH0 | TCR2_EL2_DisCH1);
+ set_sysreg_masks(kvm, TCR2_EL2, res0, res1);
+
/* SCTLR_EL1 */
res0 = SCTLR_EL1_RES0;
res1 = SCTLR_EL1_RES1;
@@ -1207,6 +1234,43 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
res0 |= SCTLR_EL1_EPAN;
set_sysreg_masks(kvm, SCTLR_EL1, res0, res1);
+ /* MDCR_EL2 */
+ res0 = MDCR_EL2_RES0;
+ res1 = MDCR_EL2_RES1;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, IMP))
+ res0 |= (MDCR_EL2_HPMN | MDCR_EL2_TPMCR |
+ MDCR_EL2_TPM | MDCR_EL2_HPME);
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, IMP))
+ res0 |= MDCR_EL2_E2PB | MDCR_EL2_TPMS;
+ if (!kvm_has_feat(kvm, ID_AA64DFR1_EL1, SPMU, IMP))
+ res0 |= MDCR_EL2_EnSPM;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, V3P1))
+ res0 |= MDCR_EL2_HPMD;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceFilt, IMP))
+ res0 |= MDCR_EL2_TTRF;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, V3P5))
+ res0 |= MDCR_EL2_HCCD | MDCR_EL2_HLP;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceBuffer, IMP))
+ res0 |= MDCR_EL2_E2TB;
+ if (!kvm_has_feat(kvm, ID_AA64MMFR0_EL1, FGT, IMP))
+ res0 |= MDCR_EL2_TDCC;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, MTPMU, IMP) ||
+ kvm_has_feat(kvm, ID_AA64PFR0_EL1, EL3, IMP))
+ res0 |= MDCR_EL2_MTPME;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, V3P7))
+ res0 |= MDCR_EL2_HPMFZO;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSS, IMP))
+ res0 |= MDCR_EL2_PMSSE;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, V1P2))
+ res0 |= MDCR_EL2_HPMFZS;
+ if (!kvm_has_feat(kvm, ID_AA64DFR1_EL1, EBEP, IMP))
+ res0 |= MDCR_EL2_PMEE;
+ if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, DebugVer, V8P9))
+ res0 |= MDCR_EL2_EBWE;
+ if (!kvm_has_feat(kvm, ID_AA64DFR2_EL1, STEP, IMP))
+ res0 |= MDCR_EL2_EnSTEPOP;
+ set_sysreg_masks(kvm, MDCR_EL2, res0, res1);
+
return 0;
}
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index ac36c438b8c1..456102bc0b55 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -89,7 +89,11 @@ static bool kvm_pmc_is_64bit(struct kvm_pmc *pmc)
static bool kvm_pmc_has_64bit_overflow(struct kvm_pmc *pmc)
{
- u64 val = kvm_vcpu_read_pmcr(kvm_pmc_to_vcpu(pmc));
+ struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
+ u64 val = kvm_vcpu_read_pmcr(vcpu);
+
+ if (kvm_pmu_counter_is_hyp(vcpu, pmc->idx))
+ return __vcpu_sys_reg(vcpu, MDCR_EL2) & MDCR_EL2_HLP;
return (pmc->idx < ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LP)) ||
(pmc->idx == ARMV8_PMU_CYCLE_IDX && (val & ARMV8_PMU_PMCR_LC));
@@ -111,6 +115,11 @@ static u32 counter_index_to_evtreg(u64 idx)
return (idx == ARMV8_PMU_CYCLE_IDX) ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + idx;
}
+static u64 kvm_pmc_read_evtreg(const struct kvm_pmc *pmc)
+{
+ return __vcpu_sys_reg(kvm_pmc_to_vcpu(pmc), counter_index_to_evtreg(pmc->idx));
+}
+
static u64 kvm_pmu_get_pmc_value(struct kvm_pmc *pmc)
{
struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
@@ -244,7 +253,7 @@ void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
*/
void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
{
- unsigned long mask = kvm_pmu_valid_counter_mask(vcpu);
+ unsigned long mask = kvm_pmu_implemented_counter_mask(vcpu);
int i;
for_each_set_bit(i, &mask, 32)
@@ -265,7 +274,50 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
irq_work_sync(&vcpu->arch.pmu.overflow_work);
}
-u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
+static u64 kvm_pmu_hyp_counter_mask(struct kvm_vcpu *vcpu)
+{
+ unsigned int hpmn, n;
+
+ if (!vcpu_has_nv(vcpu))
+ return 0;
+
+ hpmn = SYS_FIELD_GET(MDCR_EL2, HPMN, __vcpu_sys_reg(vcpu, MDCR_EL2));
+ n = vcpu->kvm->arch.pmcr_n;
+
+ /*
+ * Programming HPMN to a value greater than PMCR_EL0.N is
+ * CONSTRAINED UNPREDICTABLE. Make the implementation choice that an
+ * UNKNOWN number of counters (in our case, zero) are reserved for EL2.
+ */
+ if (hpmn >= n)
+ return 0;
+
+ /*
+ * Programming HPMN=0 is CONSTRAINED UNPREDICTABLE if FEAT_HPMN0 isn't
+ * implemented. Since KVM's ability to emulate HPMN=0 does not directly
+ * depend on hardware (all PMU registers are trapped), make the
+ * implementation choice that all counters are included in the second
+ * range reserved for EL2/EL3.
+ */
+ return GENMASK(n - 1, hpmn);
+}
+
+bool kvm_pmu_counter_is_hyp(struct kvm_vcpu *vcpu, unsigned int idx)
+{
+ return kvm_pmu_hyp_counter_mask(vcpu) & BIT(idx);
+}
+
+u64 kvm_pmu_accessible_counter_mask(struct kvm_vcpu *vcpu)
+{
+ u64 mask = kvm_pmu_implemented_counter_mask(vcpu);
+
+ if (!vcpu_has_nv(vcpu) || vcpu_is_el2(vcpu))
+ return mask;
+
+ return mask & ~kvm_pmu_hyp_counter_mask(vcpu);
+}
+
+u64 kvm_pmu_implemented_counter_mask(struct kvm_vcpu *vcpu)
{
u64 val = FIELD_GET(ARMV8_PMU_PMCR_N, kvm_vcpu_read_pmcr(vcpu));
@@ -336,15 +388,30 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
}
}
-static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
+/*
+ * Returns the PMU overflow state, which is true if there exists an event
+ * counter where the values of the global enable control, PMOVSSET_EL0[n], and
+ * PMINTENSET_EL1[n] are all 1.
+ */
+static bool kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
{
- u64 reg = 0;
+ u64 reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
- if ((kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E)) {
- reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
- reg &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
- reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
- }
+ reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
+
+ /*
+ * PMCR_EL0.E is the global enable control for event counters available
+ * to EL0 and EL1.
+ */
+ if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E))
+ reg &= kvm_pmu_hyp_counter_mask(vcpu);
+
+ /*
+ * Otherwise, MDCR_EL2.HPME is the global enable control for event
+ * counters reserved for EL2.
+ */
+ if (!(vcpu_read_sys_reg(vcpu, MDCR_EL2) & MDCR_EL2_HPME))
+ reg &= ~kvm_pmu_hyp_counter_mask(vcpu);
return reg;
}
@@ -357,7 +424,7 @@ static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
if (!kvm_vcpu_has_pmu(vcpu))
return;
- overflow = !!kvm_pmu_overflow_status(vcpu);
+ overflow = kvm_pmu_overflow_status(vcpu);
if (pmu->irq_level == overflow)
return;
@@ -574,7 +641,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0);
if (val & ARMV8_PMU_PMCR_P) {
- unsigned long mask = kvm_pmu_valid_counter_mask(vcpu);
+ unsigned long mask = kvm_pmu_accessible_counter_mask(vcpu);
mask &= ~BIT(ARMV8_PMU_CYCLE_IDX);
for_each_set_bit(i, &mask, 32)
kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, i), 0, true);
@@ -585,8 +652,44 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc)
{
struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
- return (kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E) &&
- (__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(pmc->idx));
+ unsigned int mdcr = __vcpu_sys_reg(vcpu, MDCR_EL2);
+
+ if (!(__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(pmc->idx)))
+ return false;
+
+ if (kvm_pmu_counter_is_hyp(vcpu, pmc->idx))
+ return mdcr & MDCR_EL2_HPME;
+
+ return kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E;
+}
+
+static bool kvm_pmc_counts_at_el0(struct kvm_pmc *pmc)
+{
+ u64 evtreg = kvm_pmc_read_evtreg(pmc);
+ bool nsu = evtreg & ARMV8_PMU_EXCLUDE_NS_EL0;
+ bool u = evtreg & ARMV8_PMU_EXCLUDE_EL0;
+
+ return u == nsu;
+}
+
+static bool kvm_pmc_counts_at_el1(struct kvm_pmc *pmc)
+{
+ u64 evtreg = kvm_pmc_read_evtreg(pmc);
+ bool nsk = evtreg & ARMV8_PMU_EXCLUDE_NS_EL1;
+ bool p = evtreg & ARMV8_PMU_EXCLUDE_EL1;
+
+ return p == nsk;
+}
+
+static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
+{
+ struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
+ u64 mdcr = __vcpu_sys_reg(vcpu, MDCR_EL2);
+
+ if (!kvm_pmu_counter_is_hyp(vcpu, pmc->idx) && (mdcr & MDCR_EL2_HPMD))
+ return false;
+
+ return kvm_pmc_read_evtreg(pmc) & ARMV8_PMU_INCLUDE_EL2;
}
/**
@@ -599,17 +702,15 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
struct arm_pmu *arm_pmu = vcpu->kvm->arch.arm_pmu;
struct perf_event *event;
struct perf_event_attr attr;
- u64 eventsel, reg, data;
- bool p, u, nsk, nsu;
+ u64 eventsel, evtreg;
- reg = counter_index_to_evtreg(pmc->idx);
- data = __vcpu_sys_reg(vcpu, reg);
+ evtreg = kvm_pmc_read_evtreg(pmc);
kvm_pmu_stop_counter(pmc);
if (pmc->idx == ARMV8_PMU_CYCLE_IDX)
eventsel = ARMV8_PMUV3_PERFCTR_CPU_CYCLES;
else
- eventsel = data & kvm_pmu_event_mask(vcpu->kvm);
+ eventsel = evtreg & kvm_pmu_event_mask(vcpu->kvm);
/*
* Neither SW increment nor chained events need to be backed
@@ -627,23 +728,26 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
!test_bit(eventsel, vcpu->kvm->arch.pmu_filter))
return;
- p = data & ARMV8_PMU_EXCLUDE_EL1;
- u = data & ARMV8_PMU_EXCLUDE_EL0;
- nsk = data & ARMV8_PMU_EXCLUDE_NS_EL1;
- nsu = data & ARMV8_PMU_EXCLUDE_NS_EL0;
-
memset(&attr, 0, sizeof(struct perf_event_attr));
attr.type = arm_pmu->pmu.type;
attr.size = sizeof(attr);
attr.pinned = 1;
attr.disabled = !kvm_pmu_counter_is_enabled(pmc);
- attr.exclude_user = (u != nsu);
- attr.exclude_kernel = (p != nsk);
+ attr.exclude_user = !kvm_pmc_counts_at_el0(pmc);
attr.exclude_hv = 1; /* Don't count EL2 events */
attr.exclude_host = 1; /* Don't count host events */
attr.config = eventsel;
/*
+ * Filter events at EL1 (i.e. vEL2) when in a hyp context based on the
+ * guest's EL2 filter.
+ */
+ if (unlikely(is_hyp_ctxt(vcpu)))
+ attr.exclude_kernel = !kvm_pmc_counts_at_el2(pmc);
+ else
+ attr.exclude_kernel = !kvm_pmc_counts_at_el1(pmc);
+
+ /*
* If counting with a 64bit counter, advertise it to the perf
* code, carefully dealing with the initial sample period
* which also depends on the overflow.
@@ -804,7 +908,7 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu)
{
- u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+ u64 mask = kvm_pmu_implemented_counter_mask(vcpu);
kvm_pmu_handle_pmcr(vcpu, kvm_vcpu_read_pmcr(vcpu));
@@ -1139,3 +1243,32 @@ u64 kvm_vcpu_read_pmcr(struct kvm_vcpu *vcpu)
return u64_replace_bits(pmcr, vcpu->kvm->arch.pmcr_n, ARMV8_PMU_PMCR_N);
}
+
+void kvm_pmu_nested_transition(struct kvm_vcpu *vcpu)
+{
+ bool reprogrammed = false;
+ unsigned long mask;
+ int i;
+
+ if (!kvm_vcpu_has_pmu(vcpu))
+ return;
+
+ mask = __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
+ for_each_set_bit(i, &mask, 32) {
+ struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, i);
+
+ /*
+ * We only need to reconfigure events where the filter is
+ * different at EL1 vs. EL2, as we're multiplexing the true EL1
+ * event filter bit for nested.
+ */
+ if (kvm_pmc_counts_at_el1(pmc) == kvm_pmc_counts_at_el2(pmc))
+ continue;
+
+ kvm_pmu_create_perf_event(pmc);
+ reprogrammed = true;
+ }
+
+ if (reprogrammed)
+ kvm_vcpu_pmu_restore_guest(vcpu);
+}
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index 1f69b667332b..3b5dbe9a0a0e 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -194,6 +194,12 @@ static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN, 0);
}
+static void kvm_psci_system_off2(struct kvm_vcpu *vcpu)
+{
+ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN,
+ KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2);
+}
+
static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
{
kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET, 0);
@@ -322,7 +328,7 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
switch(psci_fn) {
case PSCI_0_2_FN_PSCI_VERSION:
- val = minor == 0 ? KVM_ARM_PSCI_1_0 : KVM_ARM_PSCI_1_1;
+ val = PSCI_VERSION(1, minor);
break;
case PSCI_1_0_FN_PSCI_FEATURES:
arg = smccc_get_arg1(vcpu);
@@ -358,6 +364,11 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
if (minor >= 1)
val = 0;
break;
+ case PSCI_1_3_FN_SYSTEM_OFF2:
+ case PSCI_1_3_FN64_SYSTEM_OFF2:
+ if (minor >= 3)
+ val = PSCI_1_3_OFF_TYPE_HIBERNATE_OFF;
+ break;
}
break;
case PSCI_1_0_FN_SYSTEM_SUSPEND:
@@ -392,6 +403,33 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
break;
}
break;
+ case PSCI_1_3_FN_SYSTEM_OFF2:
+ kvm_psci_narrow_to_32bit(vcpu);
+ fallthrough;
+ case PSCI_1_3_FN64_SYSTEM_OFF2:
+ if (minor < 3)
+ break;
+
+ arg = smccc_get_arg1(vcpu);
+ /*
+ * SYSTEM_OFF2 defaults to HIBERNATE_OFF if arg1 is zero. arg2
+ * must be zero.
+ */
+ if ((arg && arg != PSCI_1_3_OFF_TYPE_HIBERNATE_OFF) ||
+ smccc_get_arg2(vcpu) != 0) {
+ val = PSCI_RET_INVALID_PARAMS;
+ break;
+ }
+ kvm_psci_system_off2(vcpu);
+ /*
+ * We shouldn't be going back to the guest after receiving a
+ * SYSTEM_OFF2 request. Preload a return value of
+ * INTERNAL_FAILURE should userspace ignore the exit and resume
+ * the vCPU.
+ */
+ val = PSCI_RET_INTERNAL_FAILURE;
+ ret = 0;
+ break;
default:
return kvm_psci_0_2_call(vcpu);
}
@@ -449,6 +487,10 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
}
switch (version) {
+ case KVM_ARM_PSCI_1_3:
+ return kvm_psci_1_x_call(vcpu, 3);
+ case KVM_ARM_PSCI_1_2:
+ return kvm_psci_1_x_call(vcpu, 2);
case KVM_ARM_PSCI_1_1:
return kvm_psci_1_x_call(vcpu, 1);
case KVM_ARM_PSCI_1_0:
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 0b0ae5ae7bc2..470524b31951 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -167,11 +167,6 @@ static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
memset(vcpu->arch.sve_state, 0, vcpu_sve_state_size(vcpu));
}
-static void kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
-{
- vcpu_set_flag(vcpu, GUEST_HAS_PTRAUTH);
-}
-
/**
* kvm_reset_vcpu - sets core registers and sys_regs to reset value
* @vcpu: The VCPU pointer
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index ff8c4e1b847e..83c6b4a07ef5 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -110,6 +110,14 @@ static bool get_el2_to_el1_mapping(unsigned int reg,
PURE_EL2_SYSREG( RVBAR_EL2 );
PURE_EL2_SYSREG( TPIDR_EL2 );
PURE_EL2_SYSREG( HPFAR_EL2 );
+ PURE_EL2_SYSREG( HCRX_EL2 );
+ PURE_EL2_SYSREG( HFGRTR_EL2 );
+ PURE_EL2_SYSREG( HFGWTR_EL2 );
+ PURE_EL2_SYSREG( HFGITR_EL2 );
+ PURE_EL2_SYSREG( HDFGRTR_EL2 );
+ PURE_EL2_SYSREG( HDFGWTR_EL2 );
+ PURE_EL2_SYSREG( HAFGRTR_EL2 );
+ PURE_EL2_SYSREG( CNTVOFF_EL2 );
PURE_EL2_SYSREG( CNTHCTL_EL2 );
MAPPED_EL2_SYSREG(SCTLR_EL2, SCTLR_EL1,
translate_sctlr_el2_to_sctlr_el1 );
@@ -126,10 +134,15 @@ static bool get_el2_to_el1_mapping(unsigned int reg,
MAPPED_EL2_SYSREG(ESR_EL2, ESR_EL1, NULL );
MAPPED_EL2_SYSREG(FAR_EL2, FAR_EL1, NULL );
MAPPED_EL2_SYSREG(MAIR_EL2, MAIR_EL1, NULL );
+ MAPPED_EL2_SYSREG(TCR2_EL2, TCR2_EL1, NULL );
+ MAPPED_EL2_SYSREG(PIR_EL2, PIR_EL1, NULL );
+ MAPPED_EL2_SYSREG(PIRE0_EL2, PIRE0_EL1, NULL );
+ MAPPED_EL2_SYSREG(POR_EL2, POR_EL1, NULL );
MAPPED_EL2_SYSREG(AMAIR_EL2, AMAIR_EL1, NULL );
MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1, NULL );
MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1, NULL );
MAPPED_EL2_SYSREG(ZCR_EL2, ZCR_EL1, NULL );
+ MAPPED_EL2_SYSREG(CONTEXTIDR_EL2, CONTEXTIDR_EL1, NULL );
default:
return false;
}
@@ -149,6 +162,21 @@ u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
goto memory_read;
/*
+ * CNTHCTL_EL2 requires some special treatment to
+ * account for the bits that can be set via CNTKCTL_EL1.
+ */
+ switch (reg) {
+ case CNTHCTL_EL2:
+ if (vcpu_el2_e2h_is_set(vcpu)) {
+ val = read_sysreg_el1(SYS_CNTKCTL);
+ val &= CNTKCTL_VALID_BITS;
+ val |= __vcpu_sys_reg(vcpu, reg) & ~CNTKCTL_VALID_BITS;
+ return val;
+ }
+ break;
+ }
+
+ /*
* If this register does not have an EL1 counterpart,
* then read the stored EL2 version.
*/
@@ -165,6 +193,9 @@ u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
/* Get the current version of the EL1 counterpart. */
WARN_ON(!__vcpu_read_sys_reg_from_cpu(el1r, &val));
+ if (reg >= __SANITISED_REG_START__)
+ val = kvm_vcpu_apply_reg_masks(vcpu, reg, val);
+
return val;
}
@@ -198,6 +229,19 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
*/
__vcpu_sys_reg(vcpu, reg) = val;
+ switch (reg) {
+ case CNTHCTL_EL2:
+ /*
+ * If E2H=0, CNHTCTL_EL2 is a pure shadow register.
+ * Otherwise, some of the bits are backed by
+ * CNTKCTL_EL1, while the rest is kept in memory.
+ * Yes, this is fun stuff.
+ */
+ if (vcpu_el2_e2h_is_set(vcpu))
+ write_sysreg_el1(val, SYS_CNTKCTL);
+ return;
+ }
+
/* No EL1 counterpart? We're done here.? */
if (reg == el1r)
return;
@@ -390,10 +434,6 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
bool was_enabled = vcpu_has_cache_enabled(vcpu);
u64 val, mask, shift;
- if (reg_to_encoding(r) == SYS_TCR2_EL1 &&
- !kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
- return undef_access(vcpu, p, r);
-
BUG_ON(!p->is_write);
get_access_mask(r, &mask, &shift);
@@ -1128,7 +1168,7 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va
{
bool set;
- val &= kvm_pmu_valid_counter_mask(vcpu);
+ val &= kvm_pmu_accessible_counter_mask(vcpu);
switch (r->reg) {
case PMOVSSET_EL0:
@@ -1151,7 +1191,7 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va
static int get_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 *val)
{
- u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+ u64 mask = kvm_pmu_accessible_counter_mask(vcpu);
*val = __vcpu_sys_reg(vcpu, r->reg) & mask;
return 0;
@@ -1165,7 +1205,7 @@ static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
if (pmu_access_el0_disabled(vcpu))
return false;
- mask = kvm_pmu_valid_counter_mask(vcpu);
+ mask = kvm_pmu_accessible_counter_mask(vcpu);
if (p->is_write) {
val = p->regval & mask;
if (r->Op2 & 0x1) {
@@ -1188,7 +1228,7 @@ static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
static bool access_pminten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
- u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+ u64 mask = kvm_pmu_accessible_counter_mask(vcpu);
if (check_pmu_access_disabled(vcpu, 0))
return false;
@@ -1212,7 +1252,7 @@ static bool access_pminten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
- u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+ u64 mask = kvm_pmu_accessible_counter_mask(vcpu);
if (pmu_access_el0_disabled(vcpu))
return false;
@@ -1242,7 +1282,7 @@ static bool access_pmswinc(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
if (pmu_write_swinc_el0_disabled(vcpu))
return false;
- mask = kvm_pmu_valid_counter_mask(vcpu);
+ mask = kvm_pmu_accessible_counter_mask(vcpu);
kvm_pmu_software_increment(vcpu, p->regval & mask);
return true;
}
@@ -1509,6 +1549,9 @@ static u8 pmuver_to_perfmon(u8 pmuver)
}
}
+static u64 sanitise_id_aa64pfr0_el1(const struct kvm_vcpu *vcpu, u64 val);
+static u64 sanitise_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val);
+
/* Read a sanitised cpufeature ID register by sys_reg_desc */
static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
const struct sys_reg_desc *r)
@@ -1522,6 +1565,12 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
val = read_sanitised_ftr_reg(id);
switch (id) {
+ case SYS_ID_AA64DFR0_EL1:
+ val = sanitise_id_aa64dfr0_el1(vcpu, val);
+ break;
+ case SYS_ID_AA64PFR0_EL1:
+ val = sanitise_id_aa64pfr0_el1(vcpu, val);
+ break;
case SYS_ID_AA64PFR1_EL1:
if (!kvm_has_mte(vcpu->kvm))
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE);
@@ -1535,6 +1584,7 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_DF2);
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_PFAR);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MPAM_frac);
break;
case SYS_ID_AA64PFR2_EL1:
/* We only expose FPMR */
@@ -1692,11 +1742,8 @@ static unsigned int fp8_visibility(const struct kvm_vcpu *vcpu,
return REG_HIDDEN;
}
-static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
- const struct sys_reg_desc *rd)
+static u64 sanitise_id_aa64pfr0_el1(const struct kvm_vcpu *vcpu, u64 val)
{
- u64 val = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
-
if (!vcpu_has_sve(vcpu))
val &= ~ID_AA64PFR0_EL1_SVE_MASK;
@@ -1724,6 +1771,13 @@ static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
val &= ~ID_AA64PFR0_EL1_AMU_MASK;
+ /*
+ * MPAM is disabled by default as KVM also needs a set of PARTID to
+ * program the MPAMVPMx_EL2 PARTID remapping registers with. But some
+ * older kernels let the guest see the ID bit.
+ */
+ val &= ~ID_AA64PFR0_EL1_MPAM_MASK;
+
return val;
}
@@ -1737,11 +1791,8 @@ static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
(val); \
})
-static u64 read_sanitised_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
- const struct sys_reg_desc *rd)
+static u64 sanitise_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val)
{
- u64 val = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
-
val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64DFR0_EL1, DebugVer, V8P8);
/*
@@ -1834,6 +1885,70 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
return set_id_reg(vcpu, rd, val);
}
+static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd, u64 user_val)
+{
+ u64 hw_val = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
+ u64 mpam_mask = ID_AA64PFR0_EL1_MPAM_MASK;
+
+ /*
+ * Commit 011e5f5bf529f ("arm64/cpufeature: Add remaining feature bits
+ * in ID_AA64PFR0 register") exposed the MPAM field of AA64PFR0_EL1 to
+ * guests, but didn't add trap handling. KVM doesn't support MPAM and
+ * always returns an UNDEF for these registers. The guest must see 0
+ * for this field.
+ *
+ * But KVM must also accept values from user-space that were provided
+ * by KVM. On CPUs that support MPAM, permit user-space to write
+ * the sanitizied value to ID_AA64PFR0_EL1.MPAM, but ignore this field.
+ */
+ if ((hw_val & mpam_mask) == (user_val & mpam_mask))
+ user_val &= ~ID_AA64PFR0_EL1_MPAM_MASK;
+
+ return set_id_reg(vcpu, rd, user_val);
+}
+
+static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd, u64 user_val)
+{
+ u64 hw_val = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
+ u64 mpam_mask = ID_AA64PFR1_EL1_MPAM_frac_MASK;
+
+ /* See set_id_aa64pfr0_el1 for comment about MPAM */
+ if ((hw_val & mpam_mask) == (user_val & mpam_mask))
+ user_val &= ~ID_AA64PFR1_EL1_MPAM_frac_MASK;
+
+ return set_id_reg(vcpu, rd, user_val);
+}
+
+static int set_ctr_el0(struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd, u64 user_val)
+{
+ u8 user_L1Ip = SYS_FIELD_GET(CTR_EL0, L1Ip, user_val);
+
+ /*
+ * Both AIVIVT (0b01) and VPIPT (0b00) are documented as reserved.
+ * Hence only allow to set VIPT(0b10) or PIPT(0b11) for L1Ip based
+ * on what hardware reports.
+ *
+ * Using a VIPT software model on PIPT will lead to over invalidation,
+ * but still correct. Hence, we can allow downgrading PIPT to VIPT,
+ * but not the other way around. This is handled via arm64_ftr_safe_value()
+ * as CTR_EL0 ftr_bits has L1Ip field with type FTR_EXACT and safe value
+ * set as VIPT.
+ */
+ switch (user_L1Ip) {
+ case CTR_EL0_L1Ip_RESERVED_VPIPT:
+ case CTR_EL0_L1Ip_RESERVED_AIVIVT:
+ return -EINVAL;
+ case CTR_EL0_L1Ip_VIPT:
+ case CTR_EL0_L1Ip_PIPT:
+ return set_id_reg(vcpu, rd, user_val);
+ default:
+ return -ENOENT;
+ }
+}
+
/*
* cpufeature ID register user accessors
*
@@ -2104,6 +2219,15 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
.val = v, \
}
+#define EL2_REG_FILTERED(name, acc, rst, v, filter) { \
+ SYS_DESC(SYS_##name), \
+ .access = acc, \
+ .reset = rst, \
+ .reg = name, \
+ .visibility = filter, \
+ .val = v, \
+}
+
#define EL2_REG_VNCR(name, rst, v) EL2_REG(name, bad_vncr_trap, rst, v)
#define EL2_REG_REDIR(name, rst, v) EL2_REG(name, bad_redir_trap, rst, v)
@@ -2150,6 +2274,15 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
.val = mask, \
}
+/* sys_reg_desc initialiser for cpufeature ID registers that need filtering */
+#define ID_FILTERED(sysreg, name, mask) { \
+ ID_DESC(sysreg), \
+ .set_user = set_##name, \
+ .visibility = id_visibility, \
+ .reset = kvm_read_sanitised_id_reg, \
+ .val = (mask), \
+}
+
/*
* sys_reg_desc initialiser for architecturally unallocated cpufeature ID
* register with encoding Op0=3, Op1=0, CRn=0, CRm=crm, Op2=op2
@@ -2236,16 +2369,18 @@ static u64 reset_hcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
return __vcpu_sys_reg(vcpu, r->reg) = val;
}
+static unsigned int __el2_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd,
+ unsigned int (*fn)(const struct kvm_vcpu *,
+ const struct sys_reg_desc *))
+{
+ return el2_visibility(vcpu, rd) ?: fn(vcpu, rd);
+}
+
static unsigned int sve_el2_visibility(const struct kvm_vcpu *vcpu,
const struct sys_reg_desc *rd)
{
- unsigned int r;
-
- r = el2_visibility(vcpu, rd);
- if (r)
- return r;
-
- return sve_visibility(vcpu, rd);
+ return __el2_visibility(vcpu, rd, sve_visibility);
}
static bool access_zcr_el2(struct kvm_vcpu *vcpu,
@@ -2273,12 +2408,48 @@ static bool access_zcr_el2(struct kvm_vcpu *vcpu,
static unsigned int s1poe_visibility(const struct kvm_vcpu *vcpu,
const struct sys_reg_desc *rd)
{
- if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S1POE, IMP))
+ if (kvm_has_s1poe(vcpu->kvm))
+ return 0;
+
+ return REG_HIDDEN;
+}
+
+static unsigned int s1poe_el2_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd)
+{
+ return __el2_visibility(vcpu, rd, s1poe_visibility);
+}
+
+static unsigned int tcr2_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd)
+{
+ if (kvm_has_tcr2(vcpu->kvm))
+ return 0;
+
+ return REG_HIDDEN;
+}
+
+static unsigned int tcr2_el2_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd)
+{
+ return __el2_visibility(vcpu, rd, tcr2_visibility);
+}
+
+static unsigned int s1pie_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd)
+{
+ if (kvm_has_s1pie(vcpu->kvm))
return 0;
return REG_HIDDEN;
}
+static unsigned int s1pie_el2_visibility(const struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *rd)
+{
+ return __el2_visibility(vcpu, rd, s1pie_visibility);
+}
+
/*
* Architected system registers.
* Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
@@ -2374,18 +2545,15 @@ static const struct sys_reg_desc sys_reg_descs[] = {
/* AArch64 ID registers */
/* CRm=4 */
- { SYS_DESC(SYS_ID_AA64PFR0_EL1),
- .access = access_id_reg,
- .get_user = get_id_reg,
- .set_user = set_id_reg,
- .reset = read_sanitised_id_aa64pfr0_el1,
- .val = ~(ID_AA64PFR0_EL1_AMU |
- ID_AA64PFR0_EL1_MPAM |
- ID_AA64PFR0_EL1_SVE |
- ID_AA64PFR0_EL1_RAS |
- ID_AA64PFR0_EL1_AdvSIMD |
- ID_AA64PFR0_EL1_FP), },
- ID_WRITABLE(ID_AA64PFR1_EL1, ~(ID_AA64PFR1_EL1_PFAR |
+ ID_FILTERED(ID_AA64PFR0_EL1, id_aa64pfr0_el1,
+ ~(ID_AA64PFR0_EL1_AMU |
+ ID_AA64PFR0_EL1_MPAM |
+ ID_AA64PFR0_EL1_SVE |
+ ID_AA64PFR0_EL1_RAS |
+ ID_AA64PFR0_EL1_AdvSIMD |
+ ID_AA64PFR0_EL1_FP)),
+ ID_FILTERED(ID_AA64PFR1_EL1, id_aa64pfr1_el1,
+ ~(ID_AA64PFR1_EL1_PFAR |
ID_AA64PFR1_EL1_DF2 |
ID_AA64PFR1_EL1_MTEX |
ID_AA64PFR1_EL1_THE |
@@ -2406,11 +2574,6 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_WRITABLE(ID_AA64FPFR0_EL1, ~ID_AA64FPFR0_EL1_RES0),
/* CRm=5 */
- { SYS_DESC(SYS_ID_AA64DFR0_EL1),
- .access = access_id_reg,
- .get_user = get_id_reg,
- .set_user = set_id_aa64dfr0_el1,
- .reset = read_sanitised_id_aa64dfr0_el1,
/*
* Prior to FEAT_Debugv8.9, the architecture defines context-aware
* breakpoints (CTX_CMPs) as the highest numbered breakpoints (BRPs).
@@ -2423,10 +2586,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
* See DDI0487K.a, section D2.8.3 Breakpoint types and linking
* of breakpoints for more details.
*/
- .val = ID_AA64DFR0_EL1_DoubleLock_MASK |
- ID_AA64DFR0_EL1_WRPs_MASK |
- ID_AA64DFR0_EL1_PMUVer_MASK |
- ID_AA64DFR0_EL1_DebugVer_MASK, },
+ ID_FILTERED(ID_AA64DFR0_EL1, id_aa64dfr0_el1,
+ ID_AA64DFR0_EL1_DoubleLock_MASK |
+ ID_AA64DFR0_EL1_WRPs_MASK |
+ ID_AA64DFR0_EL1_PMUVer_MASK |
+ ID_AA64DFR0_EL1_DebugVer_MASK),
ID_SANITISED(ID_AA64DFR1_EL1),
ID_UNALLOCATED(5,2),
ID_UNALLOCATED(5,3),
@@ -2489,7 +2653,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
{ SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },
{ SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
- { SYS_DESC(SYS_TCR2_EL1), access_vm_reg, reset_val, TCR2_EL1, 0 },
+ { SYS_DESC(SYS_TCR2_EL1), access_vm_reg, reset_val, TCR2_EL1, 0,
+ .visibility = tcr2_visibility },
PTRAUTH_KEY(APIA),
PTRAUTH_KEY(APIB),
@@ -2543,8 +2708,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_PMMIR_EL1), trap_raz_wi },
{ SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
- { SYS_DESC(SYS_PIRE0_EL1), NULL, reset_unknown, PIRE0_EL1 },
- { SYS_DESC(SYS_PIR_EL1), NULL, reset_unknown, PIR_EL1 },
+ { SYS_DESC(SYS_PIRE0_EL1), NULL, reset_unknown, PIRE0_EL1,
+ .visibility = s1pie_visibility },
+ { SYS_DESC(SYS_PIR_EL1), NULL, reset_unknown, PIR_EL1,
+ .visibility = s1pie_visibility },
{ SYS_DESC(SYS_POR_EL1), NULL, reset_unknown, POR_EL1,
.visibility = s1poe_visibility },
{ SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
@@ -2553,8 +2720,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_LOREA_EL1), trap_loregion },
{ SYS_DESC(SYS_LORN_EL1), trap_loregion },
{ SYS_DESC(SYS_LORC_EL1), trap_loregion },
+ { SYS_DESC(SYS_MPAMIDR_EL1), undef_access },
{ SYS_DESC(SYS_LORID_EL1), trap_loregion },
+ { SYS_DESC(SYS_MPAM1_EL1), undef_access },
+ { SYS_DESC(SYS_MPAM0_EL1), undef_access },
{ SYS_DESC(SYS_VBAR_EL1), access_rw, reset_val, VBAR_EL1, 0 },
{ SYS_DESC(SYS_DISR_EL1), NULL, reset_val, DISR_EL1, 0 },
@@ -2599,10 +2769,12 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
- ID_WRITABLE(CTR_EL0, CTR_EL0_DIC_MASK |
- CTR_EL0_IDC_MASK |
- CTR_EL0_DminLine_MASK |
- CTR_EL0_IminLine_MASK),
+ ID_FILTERED(CTR_EL0, ctr_el0,
+ CTR_EL0_DIC_MASK |
+ CTR_EL0_IDC_MASK |
+ CTR_EL0_DminLine_MASK |
+ CTR_EL0_L1Ip_MASK |
+ CTR_EL0_IminLine_MASK),
{ SYS_DESC(SYS_SVCR), undef_access, reset_val, SVCR, 0, .visibility = sme_visibility },
{ SYS_DESC(SYS_FPMR), undef_access, reset_val, FPMR, 0, .visibility = fp8_visibility },
@@ -2818,14 +2990,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
EL2_REG_VNCR(HFGITR_EL2, reset_val, 0),
EL2_REG_VNCR(HACR_EL2, reset_val, 0),
- { SYS_DESC(SYS_ZCR_EL2), .access = access_zcr_el2, .reset = reset_val,
- .visibility = sve_el2_visibility, .reg = ZCR_EL2 },
+ EL2_REG_FILTERED(ZCR_EL2, access_zcr_el2, reset_val, 0,
+ sve_el2_visibility),
EL2_REG_VNCR(HCRX_EL2, reset_val, 0),
EL2_REG(TTBR0_EL2, access_rw, reset_val, 0),
EL2_REG(TTBR1_EL2, access_rw, reset_val, 0),
EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1),
+ EL2_REG_FILTERED(TCR2_EL2, access_rw, reset_val, TCR2_EL2_RES1,
+ tcr2_el2_visibility),
EL2_REG_VNCR(VTTBR_EL2, reset_val, 0),
EL2_REG_VNCR(VTCR_EL2, reset_val, 0),
@@ -2853,7 +3027,24 @@ static const struct sys_reg_desc sys_reg_descs[] = {
EL2_REG(HPFAR_EL2, access_rw, reset_val, 0),
EL2_REG(MAIR_EL2, access_rw, reset_val, 0),
+ EL2_REG_FILTERED(PIRE0_EL2, access_rw, reset_val, 0,
+ s1pie_el2_visibility),
+ EL2_REG_FILTERED(PIR_EL2, access_rw, reset_val, 0,
+ s1pie_el2_visibility),
+ EL2_REG_FILTERED(POR_EL2, access_rw, reset_val, 0,
+ s1poe_el2_visibility),
EL2_REG(AMAIR_EL2, access_rw, reset_val, 0),
+ { SYS_DESC(SYS_MPAMHCR_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPMV_EL2), undef_access },
+ { SYS_DESC(SYS_MPAM2_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM0_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM1_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM2_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM3_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM4_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM5_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM6_EL2), undef_access },
+ { SYS_DESC(SYS_MPAMVPM7_EL2), undef_access },
EL2_REG(VBAR_EL2, access_rw, reset_val, 0),
EL2_REG(RVBAR_EL2, access_rw, reset_val, 0),
@@ -4719,7 +4910,7 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
- if (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
+ if (kvm_has_tcr2(kvm))
vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
if (kvm_has_fpmr(kvm))
@@ -4769,11 +4960,11 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_ATS1E1RP |
HFGITR_EL2_ATS1E1WP);
- if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP))
+ if (!kvm_has_s1pie(kvm))
kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 |
HFGxTR_EL2_nPIR_EL1);
- if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1POE, IMP))
+ if (!kvm_has_s1poe(kvm))
kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPOR_EL1 |
HFGxTR_EL2_nPOR_EL0);
diff --git a/arch/arm64/kvm/vgic/vgic-debug.c b/arch/arm64/kvm/vgic/vgic-debug.c
index e1397ab2072a..afb018528bc3 100644
--- a/arch/arm64/kvm/vgic/vgic-debug.c
+++ b/arch/arm64/kvm/vgic/vgic-debug.c
@@ -287,7 +287,10 @@ static int vgic_debug_show(struct seq_file *s, void *v)
* Expect this to succeed, as iter_mark_lpis() takes a reference on
* every LPI to be visited.
*/
- irq = vgic_get_irq(kvm, vcpu, iter->intid);
+ if (iter->intid < VGIC_NR_PRIVATE_IRQS)
+ irq = vgic_get_vcpu_irq(vcpu, iter->intid);
+ else
+ irq = vgic_get_irq(kvm, iter->intid);
if (WARN_ON_ONCE(!irq))
return -EINVAL;
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index 48c952563e85..bc7e22ab5d81 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -322,7 +322,7 @@ int vgic_init(struct kvm *kvm)
goto out;
for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
- struct vgic_irq *irq = vgic_get_irq(kvm, vcpu, i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i);
switch (dist->vgic_model) {
case KVM_DEV_TYPE_ARM_VGIC_V3:
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index ba945ba78cc7..f4c4494645c3 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -31,6 +31,41 @@ static int vgic_its_commit_v0(struct vgic_its *its);
static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
struct kvm_vcpu *filter_vcpu, bool needs_inv);
+#define vgic_its_read_entry_lock(i, g, valp, t) \
+ ({ \
+ int __sz = vgic_its_get_abi(i)->t##_esz; \
+ struct kvm *__k = (i)->dev->kvm; \
+ int __ret; \
+ \
+ BUILD_BUG_ON(NR_ITS_ABIS == 1 && \
+ sizeof(*(valp)) != ABI_0_ESZ); \
+ if (NR_ITS_ABIS > 1 && \
+ KVM_BUG_ON(__sz != sizeof(*(valp)), __k)) \
+ __ret = -EINVAL; \
+ else \
+ __ret = kvm_read_guest_lock(__k, (g), \
+ valp, __sz); \
+ __ret; \
+ })
+
+#define vgic_its_write_entry_lock(i, g, val, t) \
+ ({ \
+ int __sz = vgic_its_get_abi(i)->t##_esz; \
+ struct kvm *__k = (i)->dev->kvm; \
+ typeof(val) __v = (val); \
+ int __ret; \
+ \
+ BUILD_BUG_ON(NR_ITS_ABIS == 1 && \
+ sizeof(__v) != ABI_0_ESZ); \
+ if (NR_ITS_ABIS > 1 && \
+ KVM_BUG_ON(__sz != sizeof(__v), __k)) \
+ __ret = -EINVAL; \
+ else \
+ __ret = vgic_write_guest_lock(__k, (g), \
+ &__v, __sz); \
+ __ret; \
+ })
+
/*
* Creates a new (reference to a) struct vgic_irq for a given LPI.
* If this LPI is already mapped on another ITS, we increase its refcount
@@ -42,7 +77,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
struct kvm_vcpu *vcpu)
{
struct vgic_dist *dist = &kvm->arch.vgic;
- struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq;
+ struct vgic_irq *irq = vgic_get_irq(kvm, intid), *oldirq;
unsigned long flags;
int ret;
@@ -419,7 +454,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
last_byte_offset = byte_offset;
}
- irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+ irq = vgic_get_irq(vcpu->kvm, intid);
if (!irq)
continue;
@@ -782,6 +817,9 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
ite = find_ite(its, device_id, event_id);
if (ite && its_is_collection_mapped(ite->collection)) {
+ struct its_device *device = find_its_device(its, device_id);
+ int ite_esz = vgic_its_get_abi(its)->ite_esz;
+ gpa_t gpa = device->itt_addr + ite->event_id * ite_esz;
/*
* Though the spec talks about removing the pending state, we
* don't bother here since we clear the ITTE anyway and the
@@ -790,7 +828,8 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
vgic_its_invalidate_cache(its);
its_free_ite(kvm, ite);
- return 0;
+
+ return vgic_its_write_entry_lock(its, gpa, 0ULL, ite);
}
return E_ITS_DISCARD_UNMAPPED_INTERRUPT;
@@ -1140,8 +1179,9 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
u8 num_eventid_bits = its_cmd_get_size(its_cmd);
gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd);
struct its_device *device;
+ gpa_t gpa;
- if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL))
+ if (!vgic_its_check_id(its, its->baser_device_table, device_id, &gpa))
return E_ITS_MAPD_DEVICE_OOR;
if (valid && num_eventid_bits > VITS_TYPER_IDBITS)
@@ -1162,7 +1202,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
* is an error, so we are done in any case.
*/
if (!valid)
- return 0;
+ return vgic_its_write_entry_lock(its, gpa, 0ULL, dte);
device = vgic_its_alloc_device(its, device_id, itt_addr,
num_eventid_bits);
@@ -1282,7 +1322,7 @@ int vgic_its_invall(struct kvm_vcpu *vcpu)
unsigned long intid;
xa_for_each(&dist->lpi_xa, intid, irq) {
- irq = vgic_get_irq(kvm, NULL, intid);
+ irq = vgic_get_irq(kvm, intid);
if (!irq)
continue;
@@ -1348,7 +1388,7 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
return 0;
xa_for_each(&dist->lpi_xa, intid, irq) {
- irq = vgic_get_irq(kvm, NULL, intid);
+ irq = vgic_get_irq(kvm, intid);
if (!irq)
continue;
@@ -2084,9 +2124,8 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
* vgic_its_save_ite - Save an interrupt translation entry at @gpa
*/
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
- struct its_ite *ite, gpa_t gpa, int ite_esz)
+ struct its_ite *ite, gpa_t gpa)
{
- struct kvm *kvm = its->dev->kvm;
u32 next_offset;
u64 val;
@@ -2095,7 +2134,8 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
ite->collection->collection_id;
val = cpu_to_le64(val);
- return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
+
+ return vgic_its_write_entry_lock(its, gpa, val, ite);
}
/**
@@ -2195,7 +2235,7 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
if (ite->irq->hw && !kvm_vgic_global_state.has_gicv4_1)
return -EACCES;
- ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
+ ret = vgic_its_save_ite(its, device, ite, gpa);
if (ret)
return ret;
}
@@ -2234,12 +2274,10 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
* @its: ITS handle
* @dev: ITS device
* @ptr: GPA
- * @dte_esz: device table entry size
*/
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
- gpa_t ptr, int dte_esz)
+ gpa_t ptr)
{
- struct kvm *kvm = its->dev->kvm;
u64 val, itt_addr_field;
u32 next_offset;
@@ -2250,7 +2288,8 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
(dev->num_eventid_bits - 1));
val = cpu_to_le64(val);
- return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
+
+ return vgic_its_write_entry_lock(its, ptr, val, dte);
}
/**
@@ -2326,10 +2365,8 @@ static int vgic_its_device_cmp(void *priv, const struct list_head *a,
*/
static int vgic_its_save_device_tables(struct vgic_its *its)
{
- const struct vgic_its_abi *abi = vgic_its_get_abi(its);
u64 baser = its->baser_device_table;
struct its_device *dev;
- int dte_esz = abi->dte_esz;
if (!(baser & GITS_BASER_VALID))
return 0;
@@ -2348,7 +2385,7 @@ static int vgic_its_save_device_tables(struct vgic_its *its)
if (ret)
return ret;
- ret = vgic_its_save_dte(its, dev, eaddr, dte_esz);
+ ret = vgic_its_save_dte(its, dev, eaddr);
if (ret)
return ret;
}
@@ -2429,7 +2466,7 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
static int vgic_its_save_cte(struct vgic_its *its,
struct its_collection *collection,
- gpa_t gpa, int esz)
+ gpa_t gpa)
{
u64 val;
@@ -2437,7 +2474,8 @@ static int vgic_its_save_cte(struct vgic_its *its,
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
collection->collection_id);
val = cpu_to_le64(val);
- return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
+
+ return vgic_its_write_entry_lock(its, gpa, val, cte);
}
/*
@@ -2445,7 +2483,7 @@ static int vgic_its_save_cte(struct vgic_its *its,
* Return +1 on success, 0 if the entry was invalid (which should be
* interpreted as end-of-table), and a negative error value for generic errors.
*/
-static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
+static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa)
{
struct its_collection *collection;
struct kvm *kvm = its->dev->kvm;
@@ -2453,8 +2491,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
u64 val;
int ret;
- BUG_ON(esz > sizeof(val));
- ret = kvm_read_guest_lock(kvm, gpa, &val, esz);
+ ret = vgic_its_read_entry_lock(its, gpa, &val, cte);
if (ret)
return ret;
val = le64_to_cpu(val);
@@ -2492,7 +2529,6 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
u64 baser = its->baser_coll_table;
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
struct its_collection *collection;
- u64 val;
size_t max_size, filled = 0;
int ret, cte_esz = abi->cte_esz;
@@ -2502,7 +2538,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
list_for_each_entry(collection, &its->collection_list, coll_list) {
- ret = vgic_its_save_cte(its, collection, gpa, cte_esz);
+ ret = vgic_its_save_cte(its, collection, gpa);
if (ret)
return ret;
gpa += cte_esz;
@@ -2516,10 +2552,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
* table is not fully filled, add a last dummy element
* with valid bit unset
*/
- val = 0;
- BUG_ON(cte_esz > sizeof(val));
- ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
- return ret;
+ return vgic_its_write_entry_lock(its, gpa, 0ULL, cte);
}
/*
@@ -2544,7 +2577,7 @@ static int vgic_its_restore_collection_table(struct vgic_its *its)
max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
while (read < max_size) {
- ret = vgic_its_restore_cte(its, gpa, cte_esz);
+ ret = vgic_its_restore_cte(its, gpa);
if (ret <= 0)
break;
gpa += cte_esz;
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
index e070cda86e12..f25fccb1f8e6 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
@@ -148,7 +148,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
if (!(targets & (1U << c)))
continue;
- irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->pending_latch = true;
@@ -167,7 +167,7 @@ static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
u64 val = 0;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
val |= (u64)irq->targets << (i * 8);
@@ -191,7 +191,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
return;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, intid + i);
int target;
raw_spin_lock_irqsave(&irq->irq_lock, flags);
@@ -213,7 +213,7 @@ static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
u64 val = 0;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
val |= (u64)irq->source << (i * 8);
@@ -231,7 +231,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
unsigned long flags;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
@@ -253,7 +253,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
unsigned long flags;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 9e50928f5d7d..ae4c0593d114 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -194,7 +194,7 @@ static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len)
{
int intid = VGIC_ADDR_TO_INTID(addr, 64);
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, intid);
unsigned long ret = 0;
if (!irq)
@@ -220,7 +220,7 @@ static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
if (addr & 4)
return;
- irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+ irq = vgic_get_irq(vcpu->kvm, intid);
if (!irq)
return;
@@ -530,6 +530,7 @@ static void vgic_mmio_write_invlpi(struct kvm_vcpu *vcpu,
unsigned long val)
{
struct vgic_irq *irq;
+ u32 intid;
/*
* If the guest wrote only to the upper 32bit part of the
@@ -541,9 +542,13 @@ static void vgic_mmio_write_invlpi(struct kvm_vcpu *vcpu,
if ((addr & 4) || !vgic_lpis_enabled(vcpu))
return;
+ intid = lower_32_bits(val);
+ if (intid < VGIC_MIN_LPI)
+ return;
+
vgic_set_rdist_busy(vcpu, true);
- irq = vgic_get_irq(vcpu->kvm, NULL, lower_32_bits(val));
+ irq = vgic_get_irq(vcpu->kvm, intid);
if (irq) {
vgic_its_inv_lpi(vcpu->kvm, irq);
vgic_put_irq(vcpu->kvm, irq);
@@ -1020,7 +1025,7 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
static void vgic_v3_queue_sgi(struct kvm_vcpu *vcpu, u32 sgi, bool allow_group1)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, sgi);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, sgi);
unsigned long flags;
raw_spin_lock_irqsave(&irq->irq_lock, flags);
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c
index cf76523a2194..e416e433baff 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio.c
@@ -50,7 +50,7 @@ unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->group)
value |= BIT(i);
@@ -74,7 +74,7 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
unsigned long flags;
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->group = !!(val & BIT(i));
@@ -102,7 +102,7 @@ unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->enabled)
value |= (1U << i);
@@ -122,7 +122,7 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
@@ -171,7 +171,7 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->hw && vgic_irq_is_sgi(irq->intid) && irq->enabled)
@@ -193,7 +193,7 @@ int vgic_uaccess_write_senable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->enabled = true;
@@ -214,7 +214,7 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->enabled = false;
@@ -236,7 +236,7 @@ static unsigned long __read_pending(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
unsigned long flags;
bool val;
@@ -309,7 +309,7 @@ static void __set_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
/* GICD_ISPENDR0 SGI bits are WI when written from the guest. */
if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
@@ -395,7 +395,7 @@ static void __clear_pending(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
/* GICD_ICPENDR0 SGI bits are WI when written from the guest. */
if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
@@ -494,7 +494,7 @@ static unsigned long __vgic_mmio_read_active(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
/*
* Even for HW interrupts, don't evaluate the HW state as
@@ -598,7 +598,7 @@ static void __vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
int i;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
vgic_mmio_change_active(vcpu, irq, false);
vgic_put_irq(vcpu->kvm, irq);
}
@@ -635,7 +635,7 @@ static void __vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
int i;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
vgic_mmio_change_active(vcpu, irq, true);
vgic_put_irq(vcpu->kvm, irq);
}
@@ -672,7 +672,7 @@ unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
u64 val = 0;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
val |= (u64)irq->priority << (i * 8);
@@ -698,7 +698,7 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
unsigned long flags;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
/* Narrow the priority range to what we actually support */
@@ -719,7 +719,7 @@ unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
int i;
for (i = 0; i < len * 4; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->config == VGIC_CONFIG_EDGE)
value |= (2U << (i * 2));
@@ -750,7 +750,7 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
if (intid + i < VGIC_NR_PRIVATE_IRQS)
continue;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ irq = vgic_get_irq(vcpu->kvm, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (test_bit(i * 2 + 1, &val))
@@ -775,7 +775,7 @@ u32 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid)
if ((intid + i) < VGIC_NR_SGIS || (intid + i) >= nr_irqs)
continue;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->config == VGIC_CONFIG_LEVEL && irq->line_level)
val |= (1U << i);
@@ -799,7 +799,7 @@ void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
if ((intid + i) < VGIC_NR_SGIS || (intid + i) >= nr_irqs)
continue;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ irq = vgic_get_vcpu_irq(vcpu, intid + i);
/*
* Line level is set irrespective of irq type
diff --git a/arch/arm64/kvm/vgic/vgic-v2.c b/arch/arm64/kvm/vgic/vgic-v2.c
index ae5a44d5702d..381673f03c39 100644
--- a/arch/arm64/kvm/vgic/vgic-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-v2.c
@@ -72,7 +72,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
kvm_notify_acked_irq(vcpu->kvm, 0,
intid - VGIC_NR_PRIVATE_IRQS);
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
raw_spin_lock(&irq->irq_lock);
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index b217b256853c..f267bc2486a1 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -65,7 +65,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
kvm_notify_acked_irq(vcpu->kvm, 0,
intid - VGIC_NR_PRIVATE_IRQS);
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
if (!irq) /* An LPI could have been unmapped. */
continue;
diff --git a/arch/arm64/kvm/vgic/vgic-v4.c b/arch/arm64/kvm/vgic/vgic-v4.c
index 74a67ad87f29..eedecbbbcf31 100644
--- a/arch/arm64/kvm/vgic/vgic-v4.c
+++ b/arch/arm64/kvm/vgic/vgic-v4.c
@@ -123,7 +123,7 @@ static void vgic_v4_enable_vsgis(struct kvm_vcpu *vcpu)
* IRQ. The SGI code will do its magic.
*/
for (i = 0; i < VGIC_NR_SGIS; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i);
struct irq_desc *desc;
unsigned long flags;
int ret;
@@ -160,7 +160,7 @@ static void vgic_v4_disable_vsgis(struct kvm_vcpu *vcpu)
int i;
for (i = 0; i < VGIC_NR_SGIS; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i);
struct irq_desc *desc;
unsigned long flags;
int ret;
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index f50274fd5581..cc8c6b9b5dd8 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -84,17 +84,11 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
* struct vgic_irq. It also increases the refcount, so any caller is expected
* to call vgic_put_irq() once it's finished with this IRQ.
*/
-struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
- u32 intid)
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, u32 intid)
{
- /* SGIs and PPIs */
- if (intid <= VGIC_MAX_PRIVATE) {
- intid = array_index_nospec(intid, VGIC_MAX_PRIVATE + 1);
- return &vcpu->arch.vgic_cpu.private_irqs[intid];
- }
-
/* SPIs */
- if (intid < (kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) {
+ if (intid >= VGIC_NR_PRIVATE_IRQS &&
+ intid < (kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) {
intid = array_index_nospec(intid, kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS);
return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
}
@@ -106,6 +100,20 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
return NULL;
}
+struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
+{
+ if (WARN_ON(!vcpu))
+ return NULL;
+
+ /* SGIs and PPIs */
+ if (intid < VGIC_NR_PRIVATE_IRQS) {
+ intid = array_index_nospec(intid, VGIC_NR_PRIVATE_IRQS);
+ return &vcpu->arch.vgic_cpu.private_irqs[intid];
+ }
+
+ return vgic_get_irq(vcpu->kvm, intid);
+}
+
/*
* We can't do anything in here, because we lack the kvm pointer to
* lock and remove the item from the lpi_list. So we keep this function
@@ -437,7 +445,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
trace_vgic_update_irq_pending(vcpu ? vcpu->vcpu_idx : 0, intid, level);
- irq = vgic_get_irq(kvm, vcpu, intid);
+ if (intid < VGIC_NR_PRIVATE_IRQS)
+ irq = vgic_get_vcpu_irq(vcpu, intid);
+ else
+ irq = vgic_get_irq(kvm, intid);
if (!irq)
return -EINVAL;
@@ -499,7 +510,7 @@ static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
u32 vintid, struct irq_ops *ops)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, vintid);
unsigned long flags;
int ret;
@@ -524,7 +535,7 @@ int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
*/
void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, vintid);
unsigned long flags;
if (!irq->hw)
@@ -547,7 +558,7 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
if (!vgic_initialized(vcpu->kvm))
return -EAGAIN;
- irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ irq = vgic_get_vcpu_irq(vcpu, vintid);
BUG_ON(!irq);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
@@ -560,7 +571,7 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
int kvm_vgic_get_map(struct kvm_vcpu *vcpu, unsigned int vintid)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, vintid);
unsigned long flags;
int ret = -1;
@@ -596,7 +607,7 @@ int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner)
if (!irq_is_ppi(intid) && !vgic_valid_spi(vcpu->kvm, intid))
return -EINVAL;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->owner && irq->owner != owner)
ret = -EEXIST;
@@ -1008,7 +1019,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
if (!vgic_initialized(vcpu->kvm))
return false;
- irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ irq = vgic_get_vcpu_irq(vcpu, vintid);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
map_is_active = irq->hw && irq->active;
raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index f2486b4d9f95..122d95b4e284 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -179,8 +179,8 @@ int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
const struct vgic_register_region *
vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev,
gpa_t addr, int len);
-struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
- u32 intid);
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, u32 intid);
+struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid);
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq);
bool vgic_get_phys_line_level(struct vgic_irq *irq);
void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending);
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
index 13e6a2829116..8e882f479d98 100644
--- a/arch/arm64/lib/Makefile
+++ b/arch/arm64/lib/Makefile
@@ -13,7 +13,7 @@ endif
lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o
-obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_CRC32) += crc32.o crc32-glue.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
diff --git a/arch/arm64/lib/clear_page.S b/arch/arm64/lib/clear_page.S
index ebde40e7fa2b..bd6f7d5eb6eb 100644
--- a/arch/arm64/lib/clear_page.S
+++ b/arch/arm64/lib/clear_page.S
@@ -15,6 +15,19 @@
* x0 - dest
*/
SYM_FUNC_START(__pi_clear_page)
+#ifdef CONFIG_AS_HAS_MOPS
+ .arch_extension mops
+alternative_if_not ARM64_HAS_MOPS
+ b .Lno_mops
+alternative_else_nop_endif
+
+ mov x1, #PAGE_SIZE
+ setpn [x0]!, x1!, xzr
+ setmn [x0]!, x1!, xzr
+ seten [x0]!, x1!, xzr
+ ret
+.Lno_mops:
+#endif
mrs x1, dczid_el0
tbnz x1, #4, 2f /* Branch if DC ZVA is prohibited */
and w1, w1, #0xf
diff --git a/arch/arm64/lib/copy_page.S b/arch/arm64/lib/copy_page.S
index 6a56d7cf309d..e6374e7e5511 100644
--- a/arch/arm64/lib/copy_page.S
+++ b/arch/arm64/lib/copy_page.S
@@ -18,6 +18,19 @@
* x1 - src
*/
SYM_FUNC_START(__pi_copy_page)
+#ifdef CONFIG_AS_HAS_MOPS
+ .arch_extension mops
+alternative_if_not ARM64_HAS_MOPS
+ b .Lno_mops
+alternative_else_nop_endif
+
+ mov x2, #PAGE_SIZE
+ cpypwn [x0]!, [x1]!, x2!
+ cpymwn [x0]!, [x1]!, x2!
+ cpyewn [x0]!, [x1]!, x2!
+ ret
+.Lno_mops:
+#endif
ldp x2, x3, [x1]
ldp x4, x5, [x1, #16]
ldp x6, x7, [x1, #32]
diff --git a/arch/arm64/lib/crc32-glue.c b/arch/arm64/lib/crc32-glue.c
new file mode 100644
index 000000000000..295ae3e6b997
--- /dev/null
+++ b/arch/arm64/lib/crc32-glue.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/crc32.h>
+#include <linux/linkage.h>
+
+#include <asm/alternative.h>
+#include <asm/cpufeature.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+
+#include <crypto/internal/simd.h>
+
+// The minimum input length to consider the 4-way interleaved code path
+static const size_t min_len = 1024;
+
+asmlinkage u32 crc32_le_arm64(u32 crc, unsigned char const *p, size_t len);
+asmlinkage u32 crc32c_le_arm64(u32 crc, unsigned char const *p, size_t len);
+asmlinkage u32 crc32_be_arm64(u32 crc, unsigned char const *p, size_t len);
+
+asmlinkage u32 crc32_le_arm64_4way(u32 crc, unsigned char const *p, size_t len);
+asmlinkage u32 crc32c_le_arm64_4way(u32 crc, unsigned char const *p, size_t len);
+asmlinkage u32 crc32_be_arm64_4way(u32 crc, unsigned char const *p, size_t len);
+
+u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
+{
+ if (!alternative_has_cap_likely(ARM64_HAS_CRC32))
+ return crc32_le_base(crc, p, len);
+
+ if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) {
+ kernel_neon_begin();
+ crc = crc32_le_arm64_4way(crc, p, len);
+ kernel_neon_end();
+
+ p += round_down(len, 64);
+ len %= 64;
+
+ if (!len)
+ return crc;
+ }
+
+ return crc32_le_arm64(crc, p, len);
+}
+
+u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+ if (!alternative_has_cap_likely(ARM64_HAS_CRC32))
+ return __crc32c_le_base(crc, p, len);
+
+ if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) {
+ kernel_neon_begin();
+ crc = crc32c_le_arm64_4way(crc, p, len);
+ kernel_neon_end();
+
+ p += round_down(len, 64);
+ len %= 64;
+
+ if (!len)
+ return crc;
+ }
+
+ return crc32c_le_arm64(crc, p, len);
+}
+
+u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
+{
+ if (!alternative_has_cap_likely(ARM64_HAS_CRC32))
+ return crc32_be_base(crc, p, len);
+
+ if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) {
+ kernel_neon_begin();
+ crc = crc32_be_arm64_4way(crc, p, len);
+ kernel_neon_end();
+
+ p += round_down(len, 64);
+ len %= 64;
+
+ if (!len)
+ return crc;
+ }
+
+ return crc32_be_arm64(crc, p, len);
+}
diff --git a/arch/arm64/lib/crc32.S b/arch/arm64/lib/crc32.S
index 8340dccff46f..68825317460f 100644
--- a/arch/arm64/lib/crc32.S
+++ b/arch/arm64/lib/crc32.S
@@ -1,54 +1,60 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Accelerated CRC32(C) using AArch64 CRC instructions
+ * Accelerated CRC32(C) using AArch64 CRC and PMULL instructions
*
- * Copyright (C) 2016 - 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2016 - 2018 Linaro Ltd.
+ * Copyright (C) 2024 Google LLC
+ *
+ * Author: Ard Biesheuvel <ardb@kernel.org>
*/
#include <linux/linkage.h>
-#include <asm/alternative.h>
#include <asm/assembler.h>
- .arch armv8-a+crc
+ .cpu generic+crc+crypto
- .macro byteorder, reg, be
- .if \be
-CPU_LE( rev \reg, \reg )
- .else
-CPU_BE( rev \reg, \reg )
- .endif
+ .macro bitle, reg
.endm
- .macro byteorder16, reg, be
- .if \be
-CPU_LE( rev16 \reg, \reg )
- .else
-CPU_BE( rev16 \reg, \reg )
- .endif
+ .macro bitbe, reg
+ rbit \reg, \reg
.endm
- .macro bitorder, reg, be
- .if \be
- rbit \reg, \reg
- .endif
+ .macro bytele, reg
.endm
- .macro bitorder16, reg, be
- .if \be
+ .macro bytebe, reg
rbit \reg, \reg
- lsr \reg, \reg, #16
- .endif
+ lsr \reg, \reg, #24
.endm
- .macro bitorder8, reg, be
- .if \be
+ .macro hwordle, reg
+CPU_BE( rev16 \reg, \reg )
+ .endm
+
+ .macro hwordbe, reg
+CPU_LE( rev \reg, \reg )
rbit \reg, \reg
- lsr \reg, \reg, #24
- .endif
+CPU_BE( lsr \reg, \reg, #16 )
+ .endm
+
+ .macro le, regs:vararg
+ .irp r, \regs
+CPU_BE( rev \r, \r )
+ .endr
.endm
- .macro __crc32, c, be=0
- bitorder w0, \be
+ .macro be, regs:vararg
+ .irp r, \regs
+CPU_LE( rev \r, \r )
+ .endr
+ .irp r, \regs
+ rbit \r, \r
+ .endr
+ .endm
+
+ .macro __crc32, c, order=le
+ bit\order w0
cmp x2, #16
b.lt 8f // less than 16 bytes
@@ -61,14 +67,7 @@ CPU_BE( rev16 \reg, \reg )
add x8, x8, x1
add x1, x1, x7
ldp x5, x6, [x8]
- byteorder x3, \be
- byteorder x4, \be
- byteorder x5, \be
- byteorder x6, \be
- bitorder x3, \be
- bitorder x4, \be
- bitorder x5, \be
- bitorder x6, \be
+ \order x3, x4, x5, x6
tst x7, #8
crc32\c\()x w8, w0, x3
@@ -96,65 +95,268 @@ CPU_BE( rev16 \reg, \reg )
32: ldp x3, x4, [x1], #32
sub x2, x2, #32
ldp x5, x6, [x1, #-16]
- byteorder x3, \be
- byteorder x4, \be
- byteorder x5, \be
- byteorder x6, \be
- bitorder x3, \be
- bitorder x4, \be
- bitorder x5, \be
- bitorder x6, \be
+ \order x3, x4, x5, x6
crc32\c\()x w0, w0, x3
crc32\c\()x w0, w0, x4
crc32\c\()x w0, w0, x5
crc32\c\()x w0, w0, x6
cbnz x2, 32b
-0: bitorder w0, \be
+0: bit\order w0
ret
8: tbz x2, #3, 4f
ldr x3, [x1], #8
- byteorder x3, \be
- bitorder x3, \be
+ \order x3
crc32\c\()x w0, w0, x3
4: tbz x2, #2, 2f
ldr w3, [x1], #4
- byteorder w3, \be
- bitorder w3, \be
+ \order w3
crc32\c\()w w0, w0, w3
2: tbz x2, #1, 1f
ldrh w3, [x1], #2
- byteorder16 w3, \be
- bitorder16 w3, \be
+ hword\order w3
crc32\c\()h w0, w0, w3
1: tbz x2, #0, 0f
ldrb w3, [x1]
- bitorder8 w3, \be
+ byte\order w3
crc32\c\()b w0, w0, w3
-0: bitorder w0, \be
+0: bit\order w0
ret
.endm
.align 5
-SYM_FUNC_START(crc32_le)
-alternative_if_not ARM64_HAS_CRC32
- b crc32_le_base
-alternative_else_nop_endif
+SYM_FUNC_START(crc32_le_arm64)
__crc32
-SYM_FUNC_END(crc32_le)
+SYM_FUNC_END(crc32_le_arm64)
.align 5
-SYM_FUNC_START(__crc32c_le)
-alternative_if_not ARM64_HAS_CRC32
- b __crc32c_le_base
-alternative_else_nop_endif
+SYM_FUNC_START(crc32c_le_arm64)
__crc32 c
-SYM_FUNC_END(__crc32c_le)
+SYM_FUNC_END(crc32c_le_arm64)
.align 5
-SYM_FUNC_START(crc32_be)
-alternative_if_not ARM64_HAS_CRC32
- b crc32_be_base
-alternative_else_nop_endif
- __crc32 be=1
-SYM_FUNC_END(crc32_be)
+SYM_FUNC_START(crc32_be_arm64)
+ __crc32 order=be
+SYM_FUNC_END(crc32_be_arm64)
+
+ in .req x1
+ len .req x2
+
+ /*
+ * w0: input CRC at entry, output CRC at exit
+ * x1: pointer to input buffer
+ * x2: length of input in bytes
+ */
+ .macro crc4way, insn, table, order=le
+ bit\order w0
+ lsr len, len, #6 // len := # of 64-byte blocks
+
+ /* Process up to 64 blocks of 64 bytes at a time */
+.La\@: mov x3, #64
+ cmp len, #64
+ csel x3, x3, len, hi // x3 := min(len, 64)
+ sub len, len, x3
+
+ /* Divide the input into 4 contiguous blocks */
+ add x4, x3, x3, lsl #1 // x4 := 3 * x3
+ add x7, in, x3, lsl #4 // x7 := in + 16 * x3
+ add x8, in, x3, lsl #5 // x8 := in + 32 * x3
+ add x9, in, x4, lsl #4 // x9 := in + 16 * x4
+
+ /* Load the folding coefficients from the lookup table */
+ adr_l x5, \table - 12 // entry 0 omitted
+ add x5, x5, x4, lsl #2 // x5 += 12 * x3
+ ldp s0, s1, [x5]
+ ldr s2, [x5, #8]
+
+ /* Zero init partial CRCs for this iteration */
+ mov w4, wzr
+ mov w5, wzr
+ mov w6, wzr
+ mov x17, xzr
+
+.Lb\@: sub x3, x3, #1
+ \insn w6, w6, x17
+ ldp x10, x11, [in], #16
+ ldp x12, x13, [x7], #16
+ ldp x14, x15, [x8], #16
+ ldp x16, x17, [x9], #16
+
+ \order x10, x11, x12, x13, x14, x15, x16, x17
+
+ /* Apply the CRC transform to 4 16-byte blocks in parallel */
+ \insn w0, w0, x10
+ \insn w4, w4, x12
+ \insn w5, w5, x14
+ \insn w6, w6, x16
+ \insn w0, w0, x11
+ \insn w4, w4, x13
+ \insn w5, w5, x15
+ cbnz x3, .Lb\@
+
+ /* Combine the 4 partial results into w0 */
+ mov v3.d[0], x0
+ mov v4.d[0], x4
+ mov v5.d[0], x5
+ pmull v0.1q, v0.1d, v3.1d
+ pmull v1.1q, v1.1d, v4.1d
+ pmull v2.1q, v2.1d, v5.1d
+ eor v0.8b, v0.8b, v1.8b
+ eor v0.8b, v0.8b, v2.8b
+ mov x5, v0.d[0]
+ eor x5, x5, x17
+ \insn w0, w6, x5
+
+ mov in, x9
+ cbnz len, .La\@
+
+ bit\order w0
+ ret
+ .endm
+
+ .align 5
+SYM_FUNC_START(crc32c_le_arm64_4way)
+ crc4way crc32cx, .L0
+SYM_FUNC_END(crc32c_le_arm64_4way)
+
+ .align 5
+SYM_FUNC_START(crc32_le_arm64_4way)
+ crc4way crc32x, .L1
+SYM_FUNC_END(crc32_le_arm64_4way)
+
+ .align 5
+SYM_FUNC_START(crc32_be_arm64_4way)
+ crc4way crc32x, .L1, be
+SYM_FUNC_END(crc32_be_arm64_4way)
+
+ .section .rodata, "a", %progbits
+ .align 6
+.L0: .long 0xddc0152b, 0xba4fc28e, 0x493c7d27
+ .long 0x0715ce53, 0x9e4addf8, 0xba4fc28e
+ .long 0xc96cfdc0, 0x0715ce53, 0xddc0152b
+ .long 0xab7aff2a, 0x0d3b6092, 0x9e4addf8
+ .long 0x299847d5, 0x878a92a7, 0x39d3b296
+ .long 0xb6dd949b, 0xab7aff2a, 0x0715ce53
+ .long 0xa60ce07b, 0x83348832, 0x47db8317
+ .long 0xd270f1a2, 0xb9e02b86, 0x0d3b6092
+ .long 0x65863b64, 0xb6dd949b, 0xc96cfdc0
+ .long 0xb3e32c28, 0xbac2fd7b, 0x878a92a7
+ .long 0xf285651c, 0xce7f39f4, 0xdaece73e
+ .long 0x271d9844, 0xd270f1a2, 0xab7aff2a
+ .long 0x6cb08e5c, 0x2b3cac5d, 0x2162d385
+ .long 0xcec3662e, 0x1b03397f, 0x83348832
+ .long 0x8227bb8a, 0xb3e32c28, 0x299847d5
+ .long 0xd7a4825c, 0xdd7e3b0c, 0xb9e02b86
+ .long 0xf6076544, 0x10746f3c, 0x18b33a4e
+ .long 0x98d8d9cb, 0x271d9844, 0xb6dd949b
+ .long 0x57a3d037, 0x93a5f730, 0x78d9ccb7
+ .long 0x3771e98f, 0x6b749fb2, 0xbac2fd7b
+ .long 0xe0ac139e, 0xcec3662e, 0xa60ce07b
+ .long 0x6f345e45, 0xe6fc4e6a, 0xce7f39f4
+ .long 0xa2b73df1, 0xb0cd4768, 0x61d82e56
+ .long 0x86d8e4d2, 0xd7a4825c, 0xd270f1a2
+ .long 0xa90fd27a, 0x0167d312, 0xc619809d
+ .long 0xca6ef3ac, 0x26f6a60a, 0x2b3cac5d
+ .long 0x4597456a, 0x98d8d9cb, 0x65863b64
+ .long 0xc9c8b782, 0x68bce87a, 0x1b03397f
+ .long 0x62ec6c6d, 0x6956fc3b, 0xebb883bd
+ .long 0x2342001e, 0x3771e98f, 0xb3e32c28
+ .long 0xe8b6368b, 0x2178513a, 0x064f7f26
+ .long 0x9ef68d35, 0x170076fa, 0xdd7e3b0c
+ .long 0x0b0bf8ca, 0x6f345e45, 0xf285651c
+ .long 0x02ee03b2, 0xff0dba97, 0x10746f3c
+ .long 0x135c83fd, 0xf872e54c, 0xc7a68855
+ .long 0x00bcf5f6, 0x86d8e4d2, 0x271d9844
+ .long 0x58ca5f00, 0x5bb8f1bc, 0x8e766a0c
+ .long 0xded288f8, 0xb3af077a, 0x93a5f730
+ .long 0x37170390, 0xca6ef3ac, 0x6cb08e5c
+ .long 0xf48642e9, 0xdd66cbbb, 0x6b749fb2
+ .long 0xb25b29f2, 0xe9e28eb4, 0x1393e203
+ .long 0x45cddf4e, 0xc9c8b782, 0xcec3662e
+ .long 0xdfd94fb2, 0x93e106a4, 0x96c515bb
+ .long 0x021ac5ef, 0xd813b325, 0xe6fc4e6a
+ .long 0x8e1450f7, 0x2342001e, 0x8227bb8a
+ .long 0xe0cdcf86, 0x6d9a4957, 0xb0cd4768
+ .long 0x613eee91, 0xd2c3ed1a, 0x39c7ff35
+ .long 0xbedc6ba1, 0x9ef68d35, 0xd7a4825c
+ .long 0x0cd1526a, 0xf2271e60, 0x0ab3844b
+ .long 0xd6c3a807, 0x2664fd8b, 0x0167d312
+ .long 0x1d31175f, 0x02ee03b2, 0xf6076544
+ .long 0x4be7fd90, 0x363bd6b3, 0x26f6a60a
+ .long 0x6eeed1c9, 0x5fabe670, 0xa741c1bf
+ .long 0xb3a6da94, 0x00bcf5f6, 0x98d8d9cb
+ .long 0x2e7d11a7, 0x17f27698, 0x49c3cc9c
+ .long 0x889774e1, 0xaa7c7ad5, 0x68bce87a
+ .long 0x8a074012, 0xded288f8, 0x57a3d037
+ .long 0xbd0bb25f, 0x6d390dec, 0x6956fc3b
+ .long 0x3be3c09b, 0x6353c1cc, 0x42d98888
+ .long 0x465a4eee, 0xf48642e9, 0x3771e98f
+ .long 0x2e5f3c8c, 0xdd35bc8d, 0xb42ae3d9
+ .long 0xa52f58ec, 0x9a5ede41, 0x2178513a
+ .long 0x47972100, 0x45cddf4e, 0xe0ac139e
+ .long 0x359674f7, 0xa51b6135, 0x170076fa
+
+.L1: .long 0xaf449247, 0x81256527, 0xccaa009e
+ .long 0x57c54819, 0x1d9513d7, 0x81256527
+ .long 0x3f41287a, 0x57c54819, 0xaf449247
+ .long 0xf5e48c85, 0x910eeec1, 0x1d9513d7
+ .long 0x1f0c2cdd, 0x9026d5b1, 0xae0b5394
+ .long 0x71d54a59, 0xf5e48c85, 0x57c54819
+ .long 0x1c63267b, 0xfe807bbd, 0x0cbec0ed
+ .long 0xd31343ea, 0xe95c1271, 0x910eeec1
+ .long 0xf9d9c7ee, 0x71d54a59, 0x3f41287a
+ .long 0x9ee62949, 0xcec97417, 0x9026d5b1
+ .long 0xa55d1514, 0xf183c71b, 0xd1df2327
+ .long 0x21aa2b26, 0xd31343ea, 0xf5e48c85
+ .long 0x9d842b80, 0xeea395c4, 0x3c656ced
+ .long 0xd8110ff1, 0xcd669a40, 0xfe807bbd
+ .long 0x3f9e9356, 0x9ee62949, 0x1f0c2cdd
+ .long 0x1d6708a0, 0x0c30f51d, 0xe95c1271
+ .long 0xef82aa68, 0xdb3935ea, 0xb918a347
+ .long 0xd14bcc9b, 0x21aa2b26, 0x71d54a59
+ .long 0x99cce860, 0x356d209f, 0xff6f2fc2
+ .long 0xd8af8e46, 0xc352f6de, 0xcec97417
+ .long 0xf1996890, 0xd8110ff1, 0x1c63267b
+ .long 0x631bc508, 0xe95c7216, 0xf183c71b
+ .long 0x8511c306, 0x8e031a19, 0x9b9bdbd0
+ .long 0xdb3839f3, 0x1d6708a0, 0xd31343ea
+ .long 0x7a92fffb, 0xf7003835, 0x4470ac44
+ .long 0x6ce68f2a, 0x00eba0c8, 0xeea395c4
+ .long 0x4caaa263, 0xd14bcc9b, 0xf9d9c7ee
+ .long 0xb46f7cff, 0x9a1b53c8, 0xcd669a40
+ .long 0x60290934, 0x81b6f443, 0x6d40f445
+ .long 0x8e976a7d, 0xd8af8e46, 0x9ee62949
+ .long 0xdcf5088a, 0x9dbdc100, 0x145575d5
+ .long 0x1753ab84, 0xbbf2f6d6, 0x0c30f51d
+ .long 0x255b139e, 0x631bc508, 0xa55d1514
+ .long 0xd784eaa8, 0xce26786c, 0xdb3935ea
+ .long 0x6d2c864a, 0x8068c345, 0x2586d334
+ .long 0x02072e24, 0xdb3839f3, 0x21aa2b26
+ .long 0x06689b0a, 0x5efd72f5, 0xe0575528
+ .long 0x1e52f5ea, 0x4117915b, 0x356d209f
+ .long 0x1d3d1db6, 0x6ce68f2a, 0x9d842b80
+ .long 0x3796455c, 0xb8e0e4a8, 0xc352f6de
+ .long 0xdf3a4eb3, 0xc55a2330, 0xb84ffa9c
+ .long 0x28ae0976, 0xb46f7cff, 0xd8110ff1
+ .long 0x9764bc8d, 0xd7e7a22c, 0x712510f0
+ .long 0x13a13e18, 0x3e9a43cd, 0xe95c7216
+ .long 0xb8ee242e, 0x8e976a7d, 0x3f9e9356
+ .long 0x0c540e7b, 0x753c81ff, 0x8e031a19
+ .long 0x9924c781, 0xb9220208, 0x3edcde65
+ .long 0x3954de39, 0x1753ab84, 0x1d6708a0
+ .long 0xf32238b5, 0xbec81497, 0x9e70b943
+ .long 0xbbd2cd2c, 0x0925d861, 0xf7003835
+ .long 0xcc401304, 0xd784eaa8, 0xef82aa68
+ .long 0x4987e684, 0x6044fbb0, 0x00eba0c8
+ .long 0x3aa11427, 0x18fe3b4a, 0x87441142
+ .long 0x297aad60, 0x02072e24, 0xd14bcc9b
+ .long 0xf60c5e51, 0x6ef6f487, 0x5b7fdd0a
+ .long 0x632d78c5, 0x3fc33de4, 0x9a1b53c8
+ .long 0x25b8822a, 0x1e52f5ea, 0x99cce860
+ .long 0xd4fc84bc, 0x1af62fb8, 0x81b6f443
+ .long 0x5690aa32, 0xa91fdefb, 0x688a110e
+ .long 0x1357a093, 0x3796455c, 0xd8af8e46
+ .long 0x798fdd33, 0xaaa18a37, 0x357b9517
+ .long 0xc2815395, 0x54d42691, 0x9dbdc100
+ .long 0x21cfc0f7, 0x28ae0976, 0xf1996890
+ .long 0xa0decef3, 0x7b4aa8b7, 0xbbf2f6d6
diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S
index 4ab48d49c451..9b99106fb95f 100644
--- a/arch/arm64/lib/memcpy.S
+++ b/arch/arm64/lib/memcpy.S
@@ -57,7 +57,7 @@
The loop tail is handled by always copying 64 bytes from the end.
*/
-SYM_FUNC_START(__pi_memcpy)
+SYM_FUNC_START_LOCAL(__pi_memcpy_generic)
add srcend, src, count
add dstend, dstin, count
cmp count, 128
@@ -238,7 +238,24 @@ L(copy64_from_start):
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstin]
ret
+SYM_FUNC_END(__pi_memcpy_generic)
+
+#ifdef CONFIG_AS_HAS_MOPS
+ .arch_extension mops
+SYM_FUNC_START(__pi_memcpy)
+alternative_if_not ARM64_HAS_MOPS
+ b __pi_memcpy_generic
+alternative_else_nop_endif
+
+ mov dst, dstin
+ cpyp [dst]!, [src]!, count!
+ cpym [dst]!, [src]!, count!
+ cpye [dst]!, [src]!, count!
+ ret
SYM_FUNC_END(__pi_memcpy)
+#else
+SYM_FUNC_ALIAS(__pi_memcpy, __pi_memcpy_generic)
+#endif
SYM_FUNC_ALIAS(__memcpy, __pi_memcpy)
EXPORT_SYMBOL(__memcpy)
diff --git a/arch/arm64/lib/memset.S b/arch/arm64/lib/memset.S
index a5aebe82ad73..97157da65ec6 100644
--- a/arch/arm64/lib/memset.S
+++ b/arch/arm64/lib/memset.S
@@ -26,6 +26,7 @@
*/
dstin .req x0
+val_x .req x1
val .req w1
count .req x2
tmp1 .req x3
@@ -42,7 +43,7 @@ dst .req x8
tmp3w .req w9
tmp3 .req x9
-SYM_FUNC_START(__pi_memset)
+SYM_FUNC_START_LOCAL(__pi_memset_generic)
mov dst, dstin /* Preserve return value. */
and A_lw, val, #255
orr A_lw, A_lw, A_lw, lsl #8
@@ -201,7 +202,24 @@ SYM_FUNC_START(__pi_memset)
ands count, count, zva_bits_x
b.ne .Ltail_maybe_long
ret
+SYM_FUNC_END(__pi_memset_generic)
+
+#ifdef CONFIG_AS_HAS_MOPS
+ .arch_extension mops
+SYM_FUNC_START(__pi_memset)
+alternative_if_not ARM64_HAS_MOPS
+ b __pi_memset_generic
+alternative_else_nop_endif
+
+ mov dst, dstin
+ setp [dst]!, count!, val_x
+ setm [dst]!, count!, val_x
+ sete [dst]!, count!, val_x
+ ret
SYM_FUNC_END(__pi_memset)
+#else
+SYM_FUNC_ALIAS(__pi_memset, __pi_memset_generic)
+#endif
SYM_FUNC_ALIAS(__memset, __pi_memset)
EXPORT_SYMBOL(__memset)
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
index 2fc8c6dd0407..fc92170a8f37 100644
--- a/arch/arm64/mm/Makefile
+++ b/arch/arm64/mm/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_TRANS_TABLE) += trans_pgd.o
obj-$(CONFIG_TRANS_TABLE) += trans_pgd-asm.o
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
obj-$(CONFIG_ARM64_MTE) += mteswap.o
+obj-$(CONFIG_ARM64_GCS) += gcs.o
KASAN_SANITIZE_physaddr.o += n
obj-$(CONFIG_KASAN) += kasan_init.o
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
index a7bb20055ce0..87b3f1a25535 100644
--- a/arch/arm64/mm/copypage.c
+++ b/arch/arm64/mm/copypage.c
@@ -18,15 +18,40 @@ void copy_highpage(struct page *to, struct page *from)
{
void *kto = page_address(to);
void *kfrom = page_address(from);
+ struct folio *src = page_folio(from);
+ struct folio *dst = page_folio(to);
+ unsigned int i, nr_pages;
copy_page(kto, kfrom);
if (kasan_hw_tags_enabled())
page_kasan_tag_reset(to);
- if (system_supports_mte() && page_mte_tagged(from)) {
+ if (!system_supports_mte())
+ return;
+
+ if (folio_test_hugetlb(src) &&
+ folio_test_hugetlb_mte_tagged(src)) {
+ if (!folio_try_hugetlb_mte_tagging(dst))
+ return;
+
+ /*
+ * Populate tags for all subpages.
+ *
+ * Don't assume the first page is head page since
+ * huge page copy may start from any subpage.
+ */
+ nr_pages = folio_nr_pages(src);
+ for (i = 0; i < nr_pages; i++) {
+ kfrom = page_address(folio_page(src, i));
+ kto = page_address(folio_page(dst, i));
+ mte_copy_page_tags(kto, kfrom);
+ }
+ folio_set_hugetlb_mte_tagged(dst);
+ } else if (page_mte_tagged(from)) {
/* It's a new page, shouldn't have been tagged yet */
WARN_ON_ONCE(!try_page_mte_tagging(to));
+
mte_copy_page_tags(kto, kfrom);
set_page_mte_tagged(to);
}
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 8b281cf308b3..ef63651099a9 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -504,6 +504,14 @@ static bool fault_from_pkey(unsigned long esr, struct vm_area_struct *vma,
false);
}
+static bool is_gcs_fault(unsigned long esr)
+{
+ if (!esr_is_data_abort(esr))
+ return false;
+
+ return ESR_ELx_ISS2(esr) & ESR_ELx_GCS;
+}
+
static bool is_el0_instruction_abort(unsigned long esr)
{
return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW;
@@ -518,6 +526,23 @@ static bool is_write_abort(unsigned long esr)
return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM);
}
+static bool is_invalid_gcs_access(struct vm_area_struct *vma, u64 esr)
+{
+ if (!system_supports_gcs())
+ return false;
+
+ if (unlikely(is_gcs_fault(esr))) {
+ /* GCS accesses must be performed on a GCS page */
+ if (!(vma->vm_flags & VM_SHADOW_STACK))
+ return true;
+ } else if (unlikely(vma->vm_flags & VM_SHADOW_STACK)) {
+ /* Only GCS operations can write to a GCS page */
+ return esr_is_data_abort(esr) && is_write_abort(esr);
+ }
+
+ return false;
+}
+
static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
struct pt_regs *regs)
{
@@ -554,6 +579,14 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
/* It was exec fault */
vm_flags = VM_EXEC;
mm_flags |= FAULT_FLAG_INSTRUCTION;
+ } else if (is_gcs_fault(esr)) {
+ /*
+ * The GCS permission on a page implies both read and
+ * write so always handle any GCS fault as a write fault,
+ * we need to trigger CoW even for GCS reads.
+ */
+ vm_flags = VM_WRITE;
+ mm_flags |= FAULT_FLAG_WRITE;
} else if (is_write_abort(esr)) {
/* It was write fault */
vm_flags = VM_WRITE;
@@ -587,6 +620,13 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
if (!vma)
goto lock_mmap;
+ if (is_invalid_gcs_access(vma, esr)) {
+ vma_end_read(vma);
+ fault = 0;
+ si_code = SEGV_ACCERR;
+ goto bad_area;
+ }
+
if (!(vma->vm_flags & vm_flags)) {
vma_end_read(vma);
fault = 0;
@@ -983,7 +1023,7 @@ struct folio *vma_alloc_zeroed_movable_folio(struct vm_area_struct *vma,
if (vma->vm_flags & VM_MTE)
flags |= __GFP_ZEROTAGS;
- return vma_alloc_folio(flags, 0, vma, vaddr, false);
+ return vma_alloc_folio(flags, 0, vma, vaddr);
}
void tag_clear_highpage(struct page *page)
diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c
index de1e09d986ad..c5c5425791da 100644
--- a/arch/arm64/mm/fixmap.c
+++ b/arch/arm64/mm/fixmap.c
@@ -47,7 +47,8 @@ static void __init early_fixmap_init_pte(pmd_t *pmdp, unsigned long addr)
if (pmd_none(pmd)) {
ptep = bm_pte[BM_PTE_TABLE_IDX(addr)];
- __pmd_populate(pmdp, __pa_symbol(ptep), PMD_TYPE_TABLE);
+ __pmd_populate(pmdp, __pa_symbol(ptep),
+ PMD_TYPE_TABLE | PMD_TABLE_AF);
}
}
@@ -59,7 +60,8 @@ static void __init early_fixmap_init_pmd(pud_t *pudp, unsigned long addr,
pmd_t *pmdp;
if (pud_none(pud))
- __pud_populate(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE);
+ __pud_populate(pudp, __pa_symbol(bm_pmd),
+ PUD_TYPE_TABLE | PUD_TABLE_AF);
pmdp = pmd_offset_kimg(pudp, addr);
do {
@@ -86,7 +88,8 @@ static void __init early_fixmap_init_pud(p4d_t *p4dp, unsigned long addr,
}
if (p4d_none(p4d))
- __p4d_populate(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE);
+ __p4d_populate(p4dp, __pa_symbol(bm_pud),
+ P4D_TYPE_TABLE | P4D_TABLE_AF);
pudp = pud_offset_kimg(p4dp, addr);
early_fixmap_init_pmd(pudp, addr, end);
diff --git a/arch/arm64/mm/gcs.c b/arch/arm64/mm/gcs.c
new file mode 100644
index 000000000000..5c46ec527b1c
--- /dev/null
+++ b/arch/arm64/mm/gcs.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/syscalls.h>
+#include <linux/types.h>
+
+#include <asm/cmpxchg.h>
+#include <asm/cpufeature.h>
+#include <asm/gcs.h>
+#include <asm/page.h>
+
+static unsigned long alloc_gcs(unsigned long addr, unsigned long size)
+{
+ int flags = MAP_ANONYMOUS | MAP_PRIVATE;
+ struct mm_struct *mm = current->mm;
+ unsigned long mapped_addr, unused;
+
+ if (addr)
+ flags |= MAP_FIXED_NOREPLACE;
+
+ mmap_write_lock(mm);
+ mapped_addr = do_mmap(NULL, addr, size, PROT_READ, flags,
+ VM_SHADOW_STACK | VM_WRITE, 0, &unused, NULL);
+ mmap_write_unlock(mm);
+
+ return mapped_addr;
+}
+
+static unsigned long gcs_size(unsigned long size)
+{
+ if (size)
+ return PAGE_ALIGN(size);
+
+ /* Allocate RLIMIT_STACK/2 with limits of PAGE_SIZE..2G */
+ size = PAGE_ALIGN(min_t(unsigned long long,
+ rlimit(RLIMIT_STACK) / 2, SZ_2G));
+ return max(PAGE_SIZE, size);
+}
+
+unsigned long gcs_alloc_thread_stack(struct task_struct *tsk,
+ const struct kernel_clone_args *args)
+{
+ unsigned long addr, size;
+
+ if (!system_supports_gcs())
+ return 0;
+
+ if (!task_gcs_el0_enabled(tsk))
+ return 0;
+
+ if ((args->flags & (CLONE_VFORK | CLONE_VM)) != CLONE_VM) {
+ tsk->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0);
+ return 0;
+ }
+
+ size = args->stack_size / 2;
+
+ size = gcs_size(size);
+ addr = alloc_gcs(0, size);
+ if (IS_ERR_VALUE(addr))
+ return addr;
+
+ tsk->thread.gcs_base = addr;
+ tsk->thread.gcs_size = size;
+ tsk->thread.gcspr_el0 = addr + size - sizeof(u64);
+
+ return addr;
+}
+
+SYSCALL_DEFINE3(map_shadow_stack, unsigned long, addr, unsigned long, size, unsigned int, flags)
+{
+ unsigned long alloc_size;
+ unsigned long __user *cap_ptr;
+ unsigned long cap_val;
+ int ret = 0;
+ int cap_offset;
+
+ if (!system_supports_gcs())
+ return -EOPNOTSUPP;
+
+ if (flags & ~(SHADOW_STACK_SET_TOKEN | SHADOW_STACK_SET_MARKER))
+ return -EINVAL;
+
+ if (!PAGE_ALIGNED(addr))
+ return -EINVAL;
+
+ if (size == 8 || !IS_ALIGNED(size, 8))
+ return -EINVAL;
+
+ /*
+ * An overflow would result in attempting to write the restore token
+ * to the wrong location. Not catastrophic, but just return the right
+ * error code and block it.
+ */
+ alloc_size = PAGE_ALIGN(size);
+ if (alloc_size < size)
+ return -EOVERFLOW;
+
+ addr = alloc_gcs(addr, alloc_size);
+ if (IS_ERR_VALUE(addr))
+ return addr;
+
+ /*
+ * Put a cap token at the end of the allocated region so it
+ * can be switched to.
+ */
+ if (flags & SHADOW_STACK_SET_TOKEN) {
+ /* Leave an extra empty frame as a top of stack marker? */
+ if (flags & SHADOW_STACK_SET_MARKER)
+ cap_offset = 2;
+ else
+ cap_offset = 1;
+
+ cap_ptr = (unsigned long __user *)(addr + size -
+ (cap_offset * sizeof(unsigned long)));
+ cap_val = GCS_CAP(cap_ptr);
+
+ put_user_gcs(cap_val, cap_ptr, &ret);
+ if (ret != 0) {
+ vm_munmap(addr, size);
+ return -EFAULT;
+ }
+
+ /*
+ * Ensure the new cap is ordered before standard
+ * memory accesses to the same location.
+ */
+ gcsb_dsync();
+ }
+
+ return addr;
+}
+
+/*
+ * Apply the GCS mode configured for the specified task to the
+ * hardware.
+ */
+void gcs_set_el0_mode(struct task_struct *task)
+{
+ u64 gcscre0_el1 = GCSCRE0_EL1_nTR;
+
+ if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE)
+ gcscre0_el1 |= GCSCRE0_EL1_RVCHKEN | GCSCRE0_EL1_PCRSEL;
+
+ if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_WRITE)
+ gcscre0_el1 |= GCSCRE0_EL1_STREn;
+
+ if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_PUSH)
+ gcscre0_el1 |= GCSCRE0_EL1_PUSHMEn;
+
+ write_sysreg_s(gcscre0_el1, SYS_GCSCRE0_EL1);
+}
+
+void gcs_free(struct task_struct *task)
+{
+ if (!system_supports_gcs())
+ return;
+
+ /*
+ * When fork() with CLONE_VM fails, the child (tsk) already
+ * has a GCS allocated, and exit_thread() calls this function
+ * to free it. In this case the parent (current) and the
+ * child share the same mm struct.
+ */
+ if (!task->mm || task->mm != current->mm)
+ return;
+
+ if (task->thread.gcs_base)
+ vm_munmap(task->thread.gcs_base, task->thread.gcs_size);
+
+ task->thread.gcspr_el0 = 0;
+ task->thread.gcs_base = 0;
+ task->thread.gcs_size = 0;
+}
+
+int arch_set_shadow_stack_status(struct task_struct *task, unsigned long arg)
+{
+ unsigned long gcs, size;
+ int ret;
+
+ if (!system_supports_gcs())
+ return -EINVAL;
+
+ if (is_compat_thread(task_thread_info(task)))
+ return -EINVAL;
+
+ /* Reject unknown flags */
+ if (arg & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK)
+ return -EINVAL;
+
+ ret = gcs_check_locked(task, arg);
+ if (ret != 0)
+ return ret;
+
+ /* If we are enabling GCS then make sure we have a stack */
+ if (arg & PR_SHADOW_STACK_ENABLE &&
+ !task_gcs_el0_enabled(task)) {
+ /* Do not allow GCS to be reenabled */
+ if (task->thread.gcs_base || task->thread.gcspr_el0)
+ return -EINVAL;
+
+ if (task != current)
+ return -EBUSY;
+
+ size = gcs_size(0);
+ gcs = alloc_gcs(0, size);
+ if (!gcs)
+ return -ENOMEM;
+
+ task->thread.gcspr_el0 = gcs + size - sizeof(u64);
+ task->thread.gcs_base = gcs;
+ task->thread.gcs_size = size;
+ if (task == current)
+ write_sysreg_s(task->thread.gcspr_el0,
+ SYS_GCSPR_EL0);
+ }
+
+ task->thread.gcs_el0_mode = arg;
+ if (task == current)
+ gcs_set_el0_mode(task);
+
+ return 0;
+}
+
+int arch_get_shadow_stack_status(struct task_struct *task,
+ unsigned long __user *arg)
+{
+ if (!system_supports_gcs())
+ return -EINVAL;
+
+ if (is_compat_thread(task_thread_info(task)))
+ return -EINVAL;
+
+ return put_user(task->thread.gcs_el0_mode, arg);
+}
+
+int arch_lock_shadow_stack_status(struct task_struct *task,
+ unsigned long arg)
+{
+ if (!system_supports_gcs())
+ return -EINVAL;
+
+ if (is_compat_thread(task_thread_info(task)))
+ return -EINVAL;
+
+ /*
+ * We support locking unknown bits so applications can prevent
+ * any changes in a future proof manner.
+ */
+ task->thread.gcs_el0_locked |= arg;
+
+ return 0;
+}
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 5f1e2103888b..3215adf48a1b 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -361,14 +361,25 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
{
size_t pagesize = 1UL << shift;
- entry = pte_mkhuge(entry);
- if (pagesize == CONT_PTE_SIZE) {
- entry = pte_mkcont(entry);
- } else if (pagesize == CONT_PMD_SIZE) {
+ switch (pagesize) {
+#ifndef __PAGETABLE_PMD_FOLDED
+ case PUD_SIZE:
+ entry = pud_pte(pud_mkhuge(pte_pud(entry)));
+ break;
+#endif
+ case CONT_PMD_SIZE:
entry = pmd_pte(pmd_mkcont(pte_pmd(entry)));
- } else if (pagesize != PUD_SIZE && pagesize != PMD_SIZE) {
+ fallthrough;
+ case PMD_SIZE:
+ entry = pmd_pte(pmd_mkhuge(pte_pmd(entry)));
+ break;
+ case CONT_PTE_SIZE:
+ entry = pte_mkcont(entry);
+ break;
+ default:
pr_warn("%s: unrecognized huge page size 0x%lx\n",
__func__, pagesize);
+ break;
}
return entry;
}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 27a32ff15412..d21f67d67cf5 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -41,6 +41,7 @@
#include <asm/kvm_host.h>
#include <asm/memory.h>
#include <asm/numa.h>
+#include <asm/rsi.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <linux/sizes.h>
@@ -366,8 +367,14 @@ void __init bootmem_init(void)
*/
void __init mem_init(void)
{
+ unsigned int flags = SWIOTLB_VERBOSE;
bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit);
+ if (is_realm_world()) {
+ swiotlb = true;
+ flags |= SWIOTLB_FORCE;
+ }
+
if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb) {
/*
* If no bouncing needed for ZONE_DMA, reduce the swiotlb
@@ -379,7 +386,8 @@ void __init mem_init(void)
swiotlb = true;
}
- swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
+ swiotlb_init(swiotlb, flags);
+ swiotlb_update_mem_attributes();
/* this will put all unused low memory onto the freelists */
memblock_free_all();
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 7e3ad97e27d8..07aeab8a7606 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -83,8 +83,15 @@ arch_initcall(adjust_protection_map);
pgprot_t vm_get_page_prot(unsigned long vm_flags)
{
- pteval_t prot = pgprot_val(protection_map[vm_flags &
+ pteval_t prot;
+
+ /* Short circuit GCS to avoid bloating the table. */
+ if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) {
+ prot = _PAGE_GCS_RO;
+ } else {
+ prot = pgprot_val(protection_map[vm_flags &
(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]);
+ }
if (vm_flags & VM_ARM64_BTI)
prot |= PTE_GP;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index e55b02fbddc8..e2739b69e11b 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -119,7 +119,7 @@ static phys_addr_t __init early_pgtable_alloc(int shift)
return phys;
}
-bool pgattr_change_is_safe(u64 old, u64 new)
+bool pgattr_change_is_safe(pteval_t old, pteval_t new)
{
/*
* The following mapping attributes may be updated in live
@@ -201,7 +201,7 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
BUG_ON(pmd_sect(pmd));
if (pmd_none(pmd)) {
- pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN;
+ pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF;
phys_addr_t pte_phys;
if (flags & NO_EXEC_MAPPINGS)
@@ -288,7 +288,7 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
*/
BUG_ON(pud_sect(pud));
if (pud_none(pud)) {
- pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN;
+ pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN | PUD_TABLE_AF;
phys_addr_t pmd_phys;
if (flags & NO_EXEC_MAPPINGS)
@@ -333,7 +333,7 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
pud_t *pudp;
if (p4d_none(p4d)) {
- p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN;
+ p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN | P4D_TABLE_AF;
phys_addr_t pud_phys;
if (flags & NO_EXEC_MAPPINGS)
@@ -391,7 +391,7 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
p4d_t *p4dp;
if (pgd_none(pgd)) {
- pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN;
+ pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN | PGD_TABLE_AF;
phys_addr_t p4d_phys;
if (flags & NO_EXEC_MAPPINGS)
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 0e270a1c51e6..39fd1f7ff02a 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -5,10 +5,12 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/mem_encrypt.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <asm/cacheflush.h>
+#include <asm/pgtable-prot.h>
#include <asm/set_memory.h>
#include <asm/tlbflush.h>
#include <asm/kfence.h>
@@ -23,14 +25,16 @@ bool rodata_full __ro_after_init = IS_ENABLED(CONFIG_RODATA_FULL_DEFAULT_ENABLED
bool can_set_direct_map(void)
{
/*
- * rodata_full and DEBUG_PAGEALLOC require linear map to be
- * mapped at page granularity, so that it is possible to
+ * rodata_full, DEBUG_PAGEALLOC and a Realm guest all require linear
+ * map to be mapped at page granularity, so that it is possible to
* protect/unprotect single pages.
*
* KFENCE pool requires page-granular mapping if initialized late.
+ *
+ * Realms need to make pages shared/protected at page granularity.
*/
return rodata_full || debug_pagealloc_enabled() ||
- arm64_kfence_can_set_direct_map();
+ arm64_kfence_can_set_direct_map() || is_realm_world();
}
static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
@@ -60,7 +64,13 @@ static int __change_memory_common(unsigned long start, unsigned long size,
ret = apply_to_page_range(&init_mm, start, size, change_page_range,
&data);
- flush_tlb_kernel_range(start, start + size);
+ /*
+ * If the memory is being made valid without changing any other bits
+ * then a TLBI isn't required as a non-valid entry cannot be cached in
+ * the TLB.
+ */
+ if (pgprot_val(set_mask) != PTE_VALID || pgprot_val(clear_mask))
+ flush_tlb_kernel_range(start, start + size);
return ret;
}
@@ -192,7 +202,103 @@ int set_direct_map_default_noflush(struct page *page)
PAGE_SIZE, change_page_range, &data);
}
+static int __set_memory_enc_dec(unsigned long addr,
+ int numpages,
+ bool encrypt)
+{
+ unsigned long set_prot = 0, clear_prot = 0;
+ phys_addr_t start, end;
+ int ret;
+
+ if (!is_realm_world())
+ return 0;
+
+ if (!__is_lm_address(addr))
+ return -EINVAL;
+
+ start = __virt_to_phys(addr);
+ end = start + numpages * PAGE_SIZE;
+
+ if (encrypt)
+ clear_prot = PROT_NS_SHARED;
+ else
+ set_prot = PROT_NS_SHARED;
+
+ /*
+ * Break the mapping before we make any changes to avoid stale TLB
+ * entries or Synchronous External Aborts caused by RIPAS_EMPTY
+ */
+ ret = __change_memory_common(addr, PAGE_SIZE * numpages,
+ __pgprot(set_prot),
+ __pgprot(clear_prot | PTE_VALID));
+
+ if (ret)
+ return ret;
+
+ if (encrypt)
+ ret = rsi_set_memory_range_protected(start, end);
+ else
+ ret = rsi_set_memory_range_shared(start, end);
+
+ if (ret)
+ return ret;
+
+ return __change_memory_common(addr, PAGE_SIZE * numpages,
+ __pgprot(PTE_VALID),
+ __pgprot(0));
+}
+
+static int realm_set_memory_encrypted(unsigned long addr, int numpages)
+{
+ int ret = __set_memory_enc_dec(addr, numpages, true);
+
+ /*
+ * If the request to change state fails, then the only sensible cause
+ * of action for the caller is to leak the memory
+ */
+ WARN(ret, "Failed to encrypt memory, %d pages will be leaked",
+ numpages);
+
+ return ret;
+}
+
+static int realm_set_memory_decrypted(unsigned long addr, int numpages)
+{
+ int ret = __set_memory_enc_dec(addr, numpages, false);
+
+ WARN(ret, "Failed to decrypt memory, %d pages will be leaked",
+ numpages);
+
+ return ret;
+}
+
+static const struct arm64_mem_crypt_ops realm_crypt_ops = {
+ .encrypt = realm_set_memory_encrypted,
+ .decrypt = realm_set_memory_decrypted,
+};
+
+int realm_register_memory_enc_ops(void)
+{
+ return arm64_mem_crypt_ops_register(&realm_crypt_ops);
+}
+
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
+{
+ unsigned long addr = (unsigned long)page_address(page);
+
+ if (!can_set_direct_map())
+ return 0;
+
+ return set_memory_valid(addr, nr, valid);
+}
+
#ifdef CONFIG_DEBUG_PAGEALLOC
+/*
+ * This is - apart from the return value - doing the same
+ * thing as the new set_direct_map_valid_noflush() function.
+ *
+ * Unify? Explain the conceptual differences?
+ */
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
if (!can_set_direct_map())
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 8abdc7fed321..b8edc5765441 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -465,10 +465,12 @@ SYM_FUNC_START(__cpu_setup)
*/
mair .req x17
tcr .req x16
+ tcr2 .req x15
mov_q mair, MAIR_EL1_SET
mov_q tcr, TCR_T0SZ(IDMAP_VA_BITS) | TCR_T1SZ(VA_BITS_MIN) | TCR_CACHE_FLAGS | \
TCR_SHARED | TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \
TCR_TBI0 | TCR_A1 | TCR_KASAN_SW_FLAGS | TCR_MTE_FLAGS
+ mov tcr2, xzr
tcr_clear_errata_bits tcr, x9, x5
@@ -493,9 +495,14 @@ alternative_else_nop_endif
* via capabilities.
*/
mrs x9, ID_AA64MMFR1_EL1
- and x9, x9, ID_AA64MMFR1_EL1_HAFDBS_MASK
+ ubfx x9, x9, ID_AA64MMFR1_EL1_HAFDBS_SHIFT, #4
cbz x9, 1f
orr tcr, tcr, #TCR_HA // hardware Access flag update
+#ifdef CONFIG_ARM64_HAFT
+ cmp x9, ID_AA64MMFR1_EL1_HAFDBS_HAFT
+ b.lt 1f
+ orr tcr2, tcr2, TCR2_EL1x_HAFT
+#endif /* CONFIG_ARM64_HAFT */
1:
#endif /* CONFIG_ARM64_HW_AFDBM */
msr mair_el1, mair
@@ -525,11 +532,16 @@ alternative_else_nop_endif
#undef PTE_MAYBE_NG
#undef PTE_MAYBE_SHARED
- mov x0, TCR2_EL1x_PIE
- msr REG_TCR2_EL1, x0
+ orr tcr2, tcr2, TCR2_EL1x_PIE
.Lskip_indirection:
+ mrs_s x1, SYS_ID_AA64MMFR3_EL1
+ ubfx x1, x1, #ID_AA64MMFR3_EL1_TCRX_SHIFT, #4
+ cbz x1, 1f
+ msr REG_TCR2_EL1, tcr2
+1:
+
/*
* Prepare SCTLR
*/
@@ -538,4 +550,5 @@ alternative_else_nop_endif
.unreq mair
.unreq tcr
+ .unreq tcr2
SYM_FUNC_END(__cpu_setup)
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 264c5f9b97d8..688fbe0271ca 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -80,10 +80,10 @@ static const struct ptdump_prot_bits pte_bits[] = {
.set = "CON",
.clear = " ",
}, {
- .mask = PTE_TABLE_BIT,
- .val = PTE_TABLE_BIT,
- .set = " ",
- .clear = "BLK",
+ .mask = PTE_TABLE_BIT | PTE_VALID,
+ .val = PTE_VALID,
+ .set = "BLK",
+ .clear = " ",
}, {
.mask = PTE_UXN,
.val = PTE_UXN,
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 5db82bfc9dc1..66708b95493a 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -19,7 +19,7 @@
#include <asm/cacheflush.h>
#include <asm/debug-monitors.h>
#include <asm/insn.h>
-#include <asm/patching.h>
+#include <asm/text-patching.h>
#include <asm/set_memory.h>
#include "bpf_jit.h"
@@ -2094,6 +2094,12 @@ static void restore_args(struct jit_ctx *ctx, int args_off, int nregs)
}
}
+static bool is_struct_ops_tramp(const struct bpf_tramp_links *fentry_links)
+{
+ return fentry_links->nr_links == 1 &&
+ fentry_links->links[0]->link.type == BPF_LINK_TYPE_STRUCT_OPS;
+}
+
/* Based on the x86's implementation of arch_prepare_bpf_trampoline().
*
* bpf prog and function entry before bpf trampoline hooked:
@@ -2123,6 +2129,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
bool save_ret;
__le32 **branches = NULL;
+ bool is_struct_ops = is_struct_ops_tramp(fentry);
/* trampoline stack layout:
* [ parent ip ]
@@ -2191,11 +2198,14 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
*/
emit_bti(A64_BTI_JC, ctx);
- /* frame for parent function */
- emit(A64_PUSH(A64_FP, A64_R(9), A64_SP), ctx);
- emit(A64_MOV(1, A64_FP, A64_SP), ctx);
+ /* x9 is not set for struct_ops */
+ if (!is_struct_ops) {
+ /* frame for parent function */
+ emit(A64_PUSH(A64_FP, A64_R(9), A64_SP), ctx);
+ emit(A64_MOV(1, A64_FP, A64_SP), ctx);
+ }
- /* frame for patched function */
+ /* frame for patched function for tracing, or caller for struct_ops */
emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
emit(A64_MOV(1, A64_FP, A64_SP), ctx);
@@ -2289,19 +2299,24 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
/* reset SP */
emit(A64_MOV(1, A64_SP, A64_FP), ctx);
- /* pop frames */
- emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
- emit(A64_POP(A64_FP, A64_R(9), A64_SP), ctx);
-
- if (flags & BPF_TRAMP_F_SKIP_FRAME) {
- /* skip patched function, return to parent */
- emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
- emit(A64_RET(A64_R(9)), ctx);
+ if (is_struct_ops) {
+ emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
+ emit(A64_RET(A64_LR), ctx);
} else {
- /* return to patched function */
- emit(A64_MOV(1, A64_R(10), A64_LR), ctx);
- emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
- emit(A64_RET(A64_R(10)), ctx);
+ /* pop frames */
+ emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
+ emit(A64_POP(A64_FP, A64_R(9), A64_SP), ctx);
+
+ if (flags & BPF_TRAMP_F_SKIP_FRAME) {
+ /* skip patched function, return to parent */
+ emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
+ emit(A64_RET(A64_R(9)), ctx);
+ } else {
+ /* return to patched function */
+ emit(A64_MOV(1, A64_R(10), A64_LR), ctx);
+ emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
+ emit(A64_RET(A64_R(10)), ctx);
+ }
}
kfree(branches);
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index eedb5acc21ed..eb17f59e543c 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -29,6 +29,7 @@ HAS_EVT
HAS_FPMR
HAS_FGT
HAS_FPSIMD
+HAS_GCS
HAS_GENERIC_AUTH
HAS_GENERIC_AUTH_ARCH_QARMA3
HAS_GENERIC_AUTH_ARCH_QARMA5
@@ -56,10 +57,13 @@ HAS_TLB_RANGE
HAS_VA52
HAS_VIRT_HOST_EXTN
HAS_WFXT
+HAFT
HW_DBM
KVM_HVHE
KVM_PROTECTED_MODE
MISMATCHED_CACHE_TYPE
+MPAM
+MPAM_HCR
MTE
MTE_ASYMM
SME
diff --git a/arch/arm64/tools/syscall_32.tbl b/arch/arm64/tools/syscall_32.tbl
index 9a37930d4e26..69a829912a05 100644
--- a/arch/arm64/tools/syscall_32.tbl
+++ b/arch/arm64/tools/syscall_32.tbl
@@ -474,3 +474,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 8d637ac4b7c6..b081b54d6d22 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -1200,7 +1200,7 @@ UnsignedEnum 55:52 BRBE
0b0001 IMP
0b0010 BRBE_V1P1
EndEnum
-Enum 51:48 MTPMU
+SignedEnum 51:48 MTPMU
0b0000 NI_IMPDEF
0b0001 IMP
0b1111 NI
@@ -1208,6 +1208,7 @@ EndEnum
UnsignedEnum 47:44 TraceBuffer
0b0000 NI
0b0001 IMP
+ 0b0010 TRBE_V1P1
EndEnum
UnsignedEnum 43:40 TraceFilt
0b0000 NI
@@ -1224,11 +1225,18 @@ UnsignedEnum 35:32 PMSVer
0b0011 V1P2
0b0100 V1P3
0b0101 V1P4
+ 0b0110 V1P5
EndEnum
Field 31:28 CTX_CMPs
-Res0 27:24
+UnsignedEnum 27:24 SEBEP
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
Field 23:20 WRPs
-Res0 19:16
+UnsignedEnum 19:16 PMSS
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
Field 15:12 BRPs
UnsignedEnum 11:8 PMUVer
0b0000 NI
@@ -1238,6 +1246,7 @@ UnsignedEnum 11:8 PMUVer
0b0110 V3P5
0b0111 V3P7
0b1000 V3P8
+ 0b1001 V3P9
0b1111 IMP_DEF
EndEnum
UnsignedEnum 7:4 TraceVer
@@ -1287,6 +1296,32 @@ Field 15:8 BRPs
Field 7:0 SYSPMUID
EndSysreg
+Sysreg ID_AA64DFR2_EL1 3 0 0 5 2
+Res0 63:28
+UnsignedEnum 27:24 TRBE_EXC
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+UnsignedEnum 23:20 SPE_nVM
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+UnsignedEnum 19:16 SPE_EXC
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Res0 15:8
+UnsignedEnum 7:4 BWE
+ 0b0000 NI
+ 0b0001 FEAT_BWE
+ 0b0002 FEAT_BWE2
+EndEnum
+UnsignedEnum 3:0 STEP
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
Sysreg ID_AA64AFR0_EL1 3 0 0 5 4
Res0 63:32
Field 31:28 IMPDEF7
@@ -1648,6 +1683,8 @@ EndEnum
UnsignedEnum 39:36 ETS
0b0000 NI
0b0001 IMP
+ 0b0010 ETS2
+ 0b0011 ETS3
EndEnum
UnsignedEnum 35:32 TWED
0b0000 NI
@@ -1688,6 +1725,8 @@ UnsignedEnum 3:0 HAFDBS
0b0000 NI
0b0001 AF
0b0010 DBM
+ 0b0011 HAFT
+ 0b0100 HDBSS
EndEnum
EndSysreg
@@ -2178,6 +2217,13 @@ Field 4 P
Field 3:0 ALIGN
EndSysreg
+Sysreg PMUACR_EL1 3 0 9 14 4
+Res0 63:33
+Field 32 F0
+Field 31 C
+Field 30:0 P
+EndSysreg
+
Sysreg PMSELR_EL0 3 3 9 12 5
Res0 63:5
Field 4:0 SEL
@@ -2388,6 +2434,41 @@ Field 1 AFSR1_EL1
Field 0 AFSR0_EL1
EndSysregFields
+Sysreg MDCR_EL2 3 4 1 1 1
+Res0 63:51
+Field 50 EnSTEPOP
+Res0 49:44
+Field 43 EBWE
+Res0 42
+Field 41:40 PMEE
+Res0 39:37
+Field 36 HPMFZS
+Res0 35:32
+Field 31:30 PMSSE
+Field 29 HPMFZO
+Field 28 MTPME
+Field 27 TDCC
+Field 26 HLP
+Field 25:24 E2TB
+Field 23 HCCD
+Res0 22:20
+Field 19 TTRF
+Res0 18
+Field 17 HPMD
+Res0 16
+Field 15 EnSPM
+Field 14 TPMS
+Field 13:12 E2PB
+Field 11 TDRA
+Field 10 TDOSA
+Field 9 TDA
+Field 8 TDE
+Field 7 HPME
+Field 6 TPM
+Field 5 TPMCR
+Field 4:0 HPMN
+EndSysreg
+
Sysreg HFGRTR_EL2 3 4 1 1 4
Fields HFGxTR_EL2
EndSysreg
@@ -2737,6 +2818,126 @@ Field 1 E2SPE
Field 0 E0HSPE
EndSysreg
+Sysreg MPAMHCR_EL2 3 4 10 4 0
+Res0 63:32
+Field 31 TRAP_MPAMIDR_EL1
+Res0 30:9
+Field 8 GSTAPP_PLK
+Res0 7:2
+Field 1 EL1_VPMEN
+Field 0 EL0_VPMEN
+EndSysreg
+
+Sysreg MPAMVPMV_EL2 3 4 10 4 1
+Res0 63:32
+Field 31 VPM_V31
+Field 30 VPM_V30
+Field 29 VPM_V29
+Field 28 VPM_V28
+Field 27 VPM_V27
+Field 26 VPM_V26
+Field 25 VPM_V25
+Field 24 VPM_V24
+Field 23 VPM_V23
+Field 22 VPM_V22
+Field 21 VPM_V21
+Field 20 VPM_V20
+Field 19 VPM_V19
+Field 18 VPM_V18
+Field 17 VPM_V17
+Field 16 VPM_V16
+Field 15 VPM_V15
+Field 14 VPM_V14
+Field 13 VPM_V13
+Field 12 VPM_V12
+Field 11 VPM_V11
+Field 10 VPM_V10
+Field 9 VPM_V9
+Field 8 VPM_V8
+Field 7 VPM_V7
+Field 6 VPM_V6
+Field 5 VPM_V5
+Field 4 VPM_V4
+Field 3 VPM_V3
+Field 2 VPM_V2
+Field 1 VPM_V1
+Field 0 VPM_V0
+EndSysreg
+
+Sysreg MPAM2_EL2 3 4 10 5 0
+Field 63 MPAMEN
+Res0 62:59
+Field 58 TIDR
+Res0 57
+Field 56 ALTSP_HFC
+Field 55 ALTSP_EL2
+Field 54 ALTSP_FRCD
+Res0 53:51
+Field 50 EnMPAMSM
+Field 49 TRAPMPAM0EL1
+Field 48 TRAPMPAM1EL1
+Field 47:40 PMG_D
+Field 39:32 PMG_I
+Field 31:16 PARTID_D
+Field 15:0 PARTID_I
+EndSysreg
+
+Sysreg MPAMVPM0_EL2 3 4 10 6 0
+Field 63:48 PhyPARTID3
+Field 47:32 PhyPARTID2
+Field 31:16 PhyPARTID1
+Field 15:0 PhyPARTID0
+EndSysreg
+
+Sysreg MPAMVPM1_EL2 3 4 10 6 1
+Field 63:48 PhyPARTID7
+Field 47:32 PhyPARTID6
+Field 31:16 PhyPARTID5
+Field 15:0 PhyPARTID4
+EndSysreg
+
+Sysreg MPAMVPM2_EL2 3 4 10 6 2
+Field 63:48 PhyPARTID11
+Field 47:32 PhyPARTID10
+Field 31:16 PhyPARTID9
+Field 15:0 PhyPARTID8
+EndSysreg
+
+Sysreg MPAMVPM3_EL2 3 4 10 6 3
+Field 63:48 PhyPARTID15
+Field 47:32 PhyPARTID14
+Field 31:16 PhyPARTID13
+Field 15:0 PhyPARTID12
+EndSysreg
+
+Sysreg MPAMVPM4_EL2 3 4 10 6 4
+Field 63:48 PhyPARTID19
+Field 47:32 PhyPARTID18
+Field 31:16 PhyPARTID17
+Field 15:0 PhyPARTID16
+EndSysreg
+
+Sysreg MPAMVPM5_EL2 3 4 10 6 5
+Field 63:48 PhyPARTID23
+Field 47:32 PhyPARTID22
+Field 31:16 PhyPARTID21
+Field 15:0 PhyPARTID20
+EndSysreg
+
+Sysreg MPAMVPM6_EL2 3 4 10 6 6
+Field 63:48 PhyPARTID27
+Field 47:32 PhyPARTID26
+Field 31:16 PhyPARTID25
+Field 15:0 PhyPARTID24
+EndSysreg
+
+Sysreg MPAMVPM7_EL2 3 4 10 6 7
+Field 63:48 PhyPARTID31
+Field 47:32 PhyPARTID30
+Field 31:16 PhyPARTID29
+Field 15:0 PhyPARTID28
+EndSysreg
+
Sysreg CONTEXTIDR_EL2 3 4 13 0 1
Fields CONTEXTIDR_ELx
EndSysreg
@@ -2769,6 +2970,10 @@ Sysreg FAR_EL12 3 5 6 0 0
Field 63:0 ADDR
EndSysreg
+Sysreg MPAM1_EL12 3 5 10 5 0
+Fields MPAM1_ELx
+EndSysreg
+
Sysreg CONTEXTIDR_EL12 3 5 13 0 1
Fields CONTEXTIDR_ELx
EndSysreg
@@ -2819,8 +3024,7 @@ Field 13 AMEC1
Field 12 AMEC0
Field 11 HAFT
Field 10 PTTWI
-Field 9:8 SKL1
-Field 7:6 SKL0
+Res0 9:6
Field 5 D128
Field 4 AIE
Field 3 POE
@@ -2883,6 +3087,10 @@ Sysreg PIRE0_EL12 3 5 10 2 2
Fields PIRx_ELx
EndSysreg
+Sysreg PIRE0_EL2 3 4 10 2 2
+Fields PIRx_ELx
+EndSysreg
+
Sysreg PIR_EL1 3 0 10 2 3
Fields PIRx_ELx
EndSysreg
@@ -2903,6 +3111,10 @@ Sysreg POR_EL1 3 0 10 2 4
Fields PIRx_ELx
EndSysreg
+Sysreg POR_EL2 3 4 10 2 4
+Fields PIRx_ELx
+EndSysreg
+
Sysreg POR_EL12 3 5 10 2 4
Fields PIRx_ELx
EndSysreg
@@ -2941,6 +3153,22 @@ Res0 1
Field 0 EN
EndSysreg
+Sysreg MPAMIDR_EL1 3 0 10 4 4
+Res0 63:62
+Field 61 HAS_SDEFLT
+Field 60 HAS_FORCE_NS
+Field 59 SP4
+Field 58 HAS_TIDR
+Field 57 HAS_ALTSP
+Res0 56:40
+Field 39:32 PMG_MAX
+Res0 31:21
+Field 20:18 VPMR_MAX
+Field 17 HAS_HCR
+Res0 16
+Field 15:0 PARTID_MAX
+EndSysreg
+
Sysreg LORID_EL1 3 0 10 4 7
Res0 63:24
Field 23:16 LD
@@ -2948,6 +3176,27 @@ Res0 15:8
Field 7:0 LR
EndSysreg
+Sysreg MPAM1_EL1 3 0 10 5 0
+Field 63 MPAMEN
+Res0 62:61
+Field 60 FORCED_NS
+Res0 59:55
+Field 54 ALTSP_FRCD
+Res0 53:48
+Field 47:40 PMG_D
+Field 39:32 PMG_I
+Field 31:16 PARTID_D
+Field 15:0 PARTID_I
+EndSysreg
+
+Sysreg MPAM0_EL1 3 0 10 5 1
+Res0 63:48
+Field 47:40 PMG_D
+Field 39:32 PMG_I
+Field 31:16 PARTID_D
+Field 15:0 PARTID_I
+EndSysreg
+
Sysreg ISR_EL1 3 0 12 1 0
Res0 63:11
Field 10 IS
diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
index 5479707eb5d1..acc431c331b0 100644
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -64,9 +64,6 @@ config CSKY
select GENERIC_IRQ_MULTI_HANDLER
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_TIME_VSYSCALL
- select GENERIC_VDSO_32
- select GENERIC_GETTIMEOFDAY
select GX6605S_TIMER if CPU_CK610
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_AUDITSYSCALL
@@ -80,7 +77,6 @@ config CSKY
select HAVE_DEBUG_KMEMLEAK
select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_REGS
- select HAVE_GENERIC_VDSO
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_ERROR_INJECTION
diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild
index 9a9bc65b57a9..3a5c7f6e5aac 100644
--- a/arch/csky/include/asm/Kbuild
+++ b/arch/csky/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += qspinlock.h
generic-y += parport.h
generic-y += user.h
generic-y += vmlinux.lds.h
+generic-y += text-patching.h
diff --git a/arch/csky/include/asm/io.h b/arch/csky/include/asm/io.h
index 4725bb977b0f..ed53f0b47388 100644
--- a/arch/csky/include/asm/io.h
+++ b/arch/csky/include/asm/io.h
@@ -32,17 +32,6 @@
#endif
/*
- * String version of I/O memory access operations.
- */
-extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t);
-extern void __memcpy_toio(volatile void __iomem *, const void *, size_t);
-extern void __memset_io(volatile void __iomem *, int, size_t);
-
-#define memset_io(c,v,l) __memset_io((c),(v),(l))
-#define memcpy_fromio(a,c,l) __memcpy_fromio((a),(c),(l))
-#define memcpy_toio(c,a,l) __memcpy_toio((c),(a),(l))
-
-/*
* I/O memory mapping functions.
*/
#define ioremap_wc(addr, size) \
diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h
index 0ca6c408c07f..4911d0892b71 100644
--- a/arch/csky/include/asm/page.h
+++ b/arch/csky/include/asm/page.h
@@ -7,12 +7,8 @@
#include <asm/cache.h>
#include <linux/const.h>
-/*
- * PAGE_SHIFT determines the page size: 4KB
- */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE - 1))
+#include <vdso/page.h>
+
#define THREAD_SIZE (PAGE_SIZE * 2)
#define THREAD_MASK (~(THREAD_SIZE - 1))
#define THREAD_SHIFT (PAGE_SHIFT + 1)
@@ -43,9 +39,6 @@ extern void *memcpy(void *to, const void *from, size_t l);
#define clear_page(page) memset((page), 0, PAGE_SIZE)
#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-#define phys_to_page(paddr) (pfn_to_page(PFN_DOWN(paddr)))
-
struct page;
#include <abi/page.h>
diff --git a/arch/csky/include/asm/vdso/clocksource.h b/arch/csky/include/asm/vdso/clocksource.h
deleted file mode 100644
index dfca7b4724b7..000000000000
--- a/arch/csky/include/asm/vdso/clocksource.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#ifndef __ASM_VDSO_CSKY_CLOCKSOURCE_H
-#define __ASM_VDSO_CSKY_CLOCKSOURCE_H
-
-#define VDSO_ARCH_CLOCKMODES \
- VDSO_CLOCKMODE_ARCHTIMER
-
-#endif /* __ASM_VDSO_CSKY_CLOCKSOURCE_H */
diff --git a/arch/csky/include/asm/vdso/gettimeofday.h b/arch/csky/include/asm/vdso/gettimeofday.h
deleted file mode 100644
index 6c4f1446944f..000000000000
--- a/arch/csky/include/asm/vdso/gettimeofday.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#ifndef __ASM_VDSO_CSKY_GETTIMEOFDAY_H
-#define __ASM_VDSO_CSKY_GETTIMEOFDAY_H
-
-#ifndef __ASSEMBLY__
-
-#include <asm/barrier.h>
-#include <asm/unistd.h>
-#include <abi/regdef.h>
-#include <uapi/linux/time.h>
-
-#define VDSO_HAS_CLOCK_GETRES 1
-
-static __always_inline
-int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
- struct timezone *_tz)
-{
- register struct __kernel_old_timeval *tv asm("a0") = _tv;
- register struct timezone *tz asm("a1") = _tz;
- register long ret asm("a0");
- register long nr asm(syscallid) = __NR_gettimeofday;
-
- asm volatile ("trap 0\n"
- : "=r" (ret)
- : "r"(tv), "r"(tz), "r"(nr)
- : "memory");
-
- return ret;
-}
-
-static __always_inline
-long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
-{
- register clockid_t clkid asm("a0") = _clkid;
- register struct __kernel_timespec *ts asm("a1") = _ts;
- register long ret asm("a0");
- register long nr asm(syscallid) = __NR_clock_gettime64;
-
- asm volatile ("trap 0\n"
- : "=r" (ret)
- : "r"(clkid), "r"(ts), "r"(nr)
- : "memory");
-
- return ret;
-}
-
-static __always_inline
-long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
-{
- register clockid_t clkid asm("a0") = _clkid;
- register struct old_timespec32 *ts asm("a1") = _ts;
- register long ret asm("a0");
- register long nr asm(syscallid) = __NR_clock_gettime;
-
- asm volatile ("trap 0\n"
- : "=r" (ret)
- : "r"(clkid), "r"(ts), "r"(nr)
- : "memory");
-
- return ret;
-}
-
-static __always_inline
-int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
-{
- register clockid_t clkid asm("a0") = _clkid;
- register struct __kernel_timespec *ts asm("a1") = _ts;
- register long ret asm("a0");
- register long nr asm(syscallid) = __NR_clock_getres_time64;
-
- asm volatile ("trap 0\n"
- : "=r" (ret)
- : "r"(clkid), "r"(ts), "r"(nr)
- : "memory");
-
- return ret;
-}
-
-static __always_inline
-int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
-{
- register clockid_t clkid asm("a0") = _clkid;
- register struct old_timespec32 *ts asm("a1") = _ts;
- register long ret asm("a0");
- register long nr asm(syscallid) = __NR_clock_getres;
-
- asm volatile ("trap 0\n"
- : "=r" (ret)
- : "r"(clkid), "r"(ts), "r"(nr)
- : "memory");
-
- return ret;
-}
-
-uint64_t csky_pmu_read_cc(void);
-static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
- const struct vdso_data *vd)
-{
-#ifdef CONFIG_CSKY_PMU_V1
- return csky_pmu_read_cc();
-#else
- return 0;
-#endif
-}
-
-static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
-{
- return _vdso_data;
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __ASM_VDSO_CSKY_GETTIMEOFDAY_H */
diff --git a/arch/csky/include/asm/vdso/processor.h b/arch/csky/include/asm/vdso/processor.h
deleted file mode 100644
index 39a6b561d0cc..000000000000
--- a/arch/csky/include/asm/vdso/processor.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __ASM_VDSO_CSKY_PROCESSOR_H
-#define __ASM_VDSO_CSKY_PROCESSOR_H
-
-#ifndef __ASSEMBLY__
-
-#define cpu_relax() barrier()
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_VDSO_CSKY_PROCESSOR_H */
diff --git a/arch/csky/include/asm/vdso/vsyscall.h b/arch/csky/include/asm/vdso/vsyscall.h
deleted file mode 100644
index c276211a7c4d..000000000000
--- a/arch/csky/include/asm/vdso/vsyscall.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#ifndef __ASM_VDSO_CSKY_VSYSCALL_H
-#define __ASM_VDSO_CSKY_VSYSCALL_H
-
-#ifndef __ASSEMBLY__
-
-#include <vdso/datapage.h>
-
-extern struct vdso_data *vdso_data;
-
-static __always_inline struct vdso_data *__csky_get_k_vdso_data(void)
-{
- return vdso_data;
-}
-#define __arch_get_k_vdso_data __csky_get_k_vdso_data
-
-#include <asm-generic/vdso/vsyscall.h>
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __ASM_VDSO_CSKY_VSYSCALL_H */
diff --git a/arch/csky/kernel/Makefile b/arch/csky/kernel/Makefile
index 8a868316b912..de1c3472e8f0 100644
--- a/arch/csky/kernel/Makefile
+++ b/arch/csky/kernel/Makefile
@@ -2,7 +2,7 @@
extra-y := vmlinux.lds
obj-y += head.o entry.o atomic.o signal.o traps.o irq.o time.o vdso.o vdso/
-obj-y += power.o syscall.o syscall_table.o setup.o io.o
+obj-y += power.o syscall.o syscall_table.o setup.o
obj-y += process.o cpu-probe.o ptrace.o stacktrace.o
obj-y += probes/
diff --git a/arch/csky/kernel/io.c b/arch/csky/kernel/io.c
deleted file mode 100644
index 5883f13fa2b1..000000000000
--- a/arch/csky/kernel/io.c
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/io.h>
-
-/*
- * Copy data from IO memory space to "real" memory space.
- */
-void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
-{
- while (count && !IS_ALIGNED((unsigned long)from, 4)) {
- *(u8 *)to = __raw_readb(from);
- from++;
- to++;
- count--;
- }
-
- while (count >= 4) {
- *(u32 *)to = __raw_readl(from);
- from += 4;
- to += 4;
- count -= 4;
- }
-
- while (count) {
- *(u8 *)to = __raw_readb(from);
- from++;
- to++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memcpy_fromio);
-
-/*
- * Copy data from "real" memory space to IO memory space.
- */
-void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
-{
- while (count && !IS_ALIGNED((unsigned long)to, 4)) {
- __raw_writeb(*(u8 *)from, to);
- from++;
- to++;
- count--;
- }
-
- while (count >= 4) {
- __raw_writel(*(u32 *)from, to);
- from += 4;
- to += 4;
- count -= 4;
- }
-
- while (count) {
- __raw_writeb(*(u8 *)from, to);
- from++;
- to++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memcpy_toio);
-
-/*
- * "memset" on IO memory space.
- */
-void __memset_io(volatile void __iomem *dst, int c, size_t count)
-{
- u32 qc = (u8)c;
-
- qc |= qc << 8;
- qc |= qc << 16;
-
- while (count && !IS_ALIGNED((unsigned long)dst, 4)) {
- __raw_writeb(c, dst);
- dst++;
- count--;
- }
-
- while (count >= 4) {
- __raw_writel(qc, dst);
- dst += 4;
- count -= 4;
- }
-
- while (count) {
- __raw_writeb(c, dst);
- dst++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memset_io);
diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c
index 51012e90780d..fe715b707fd0 100644
--- a/arch/csky/kernel/setup.c
+++ b/arch/csky/kernel/setup.c
@@ -112,9 +112,9 @@ asmlinkage __visible void __init csky_start(unsigned int unused,
pre_trap_init();
if (dtb_start == NULL)
- early_init_dt_scan(__dtb_start);
+ early_init_dt_scan(__dtb_start, __pa(dtb_start));
else
- early_init_dt_scan(dtb_start);
+ early_init_dt_scan(dtb_start, __pa(dtb_start));
start_kernel();
diff --git a/arch/csky/kernel/vdso.c b/arch/csky/kernel/vdso.c
index 5c9ef63c29f1..c54d019d66bc 100644
--- a/arch/csky/kernel/vdso.c
+++ b/arch/csky/kernel/vdso.c
@@ -8,23 +8,19 @@
#include <linux/slab.h>
#include <asm/page.h>
-#include <vdso/datapage.h>
extern char vdso_start[], vdso_end[];
static unsigned int vdso_pages;
static struct page **vdso_pagelist;
-static union vdso_data_store vdso_data_store __page_aligned_data;
-struct vdso_data *vdso_data = vdso_data_store.data;
-
static int __init vdso_init(void)
{
unsigned int i;
vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
vdso_pagelist =
- kcalloc(vdso_pages + 1, sizeof(struct page *), GFP_KERNEL);
+ kcalloc(vdso_pages, sizeof(struct page *), GFP_KERNEL);
if (unlikely(vdso_pagelist == NULL)) {
pr_err("vdso: pagelist allocation failed\n");
return -ENOMEM;
@@ -36,7 +32,6 @@ static int __init vdso_init(void)
pg = virt_to_page(vdso_start + (i << PAGE_SHIFT));
vdso_pagelist[i] = pg;
}
- vdso_pagelist[i] = virt_to_page(vdso_data);
return 0;
}
@@ -52,11 +47,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
static struct vm_special_mapping vdso_mapping = {
.name = "[vdso]",
};
- static struct vm_special_mapping vvar_mapping = {
- .name = "[vvar]",
- };
- vdso_len = (vdso_pages + 1) << PAGE_SHIFT;
+ vdso_len = vdso_pages << PAGE_SHIFT;
mmap_write_lock(mm);
vdso_base = get_unmapped_area(NULL, 0, vdso_len, 0, 0);
@@ -85,27 +77,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
}
vdso_base += (vdso_pages << PAGE_SHIFT);
- vvar_mapping.pages = &vdso_pagelist[vdso_pages];
- vma = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
- (VM_READ | VM_MAYREAD), &vvar_mapping);
-
- if (IS_ERR(vma)) {
- ret = PTR_ERR(vma);
- mm->context.vdso = NULL;
- goto end;
- }
ret = 0;
end:
mmap_write_unlock(mm);
return ret;
}
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
- if (vma->vm_mm && (vma->vm_start == (long)vma->vm_mm->context.vdso))
- return "[vdso]";
- if (vma->vm_mm && (vma->vm_start ==
- (long)vma->vm_mm->context.vdso + PAGE_SIZE))
- return "[vdso_data]";
- return NULL;
-}
diff --git a/arch/csky/kernel/vdso/Makefile b/arch/csky/kernel/vdso/Makefile
index bc2261f5a8d4..069ef0b17fe5 100644
--- a/arch/csky/kernel/vdso/Makefile
+++ b/arch/csky/kernel/vdso/Makefile
@@ -5,7 +5,6 @@ include $(srctree)/lib/vdso/Makefile
# Symbols present in the vdso
vdso-syms += rt_sigreturn
-vdso-syms += vgettimeofday
# Files to link into the vdso
obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o
diff --git a/arch/csky/kernel/vdso/vdso.lds.S b/arch/csky/kernel/vdso/vdso.lds.S
index 590a6c79fff7..8d226252d439 100644
--- a/arch/csky/kernel/vdso/vdso.lds.S
+++ b/arch/csky/kernel/vdso/vdso.lds.S
@@ -49,10 +49,6 @@ VERSION
LINUX_5.10 {
global:
__vdso_rt_sigreturn;
- __vdso_clock_gettime;
- __vdso_clock_gettime64;
- __vdso_gettimeofday;
- __vdso_clock_getres;
local: *;
};
}
diff --git a/arch/csky/kernel/vdso/vgettimeofday.c b/arch/csky/kernel/vdso/vgettimeofday.c
deleted file mode 100644
index 55af30e83752..000000000000
--- a/arch/csky/kernel/vdso/vgettimeofday.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-#include <linux/time.h>
-#include <linux/types.h>
-#include <vdso/gettime.h>
-
-extern
-int __vdso_clock_gettime(clockid_t clock,
- struct old_timespec32 *ts)
-{
- return __cvdso_clock_gettime32(clock, ts);
-}
-
-int __vdso_clock_gettime64(clockid_t clock,
- struct __kernel_timespec *ts)
-{
- return __cvdso_clock_gettime(clock, ts);
-}
-
-int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
- struct timezone *tz)
-{
- return __cvdso_gettimeofday(tv, tz);
-}
-
-int __vdso_clock_getres(clockid_t clock_id,
- struct old_timespec32 *res)
-{
- return __cvdso_clock_getres_time32(clock_id, res);
-}
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index e233b5efa276..3eb51fbe804e 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -30,8 +30,6 @@ config HEXAGON
select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK
select NEED_SG_DMA_LENGTH
- select NO_IOPORT_MAP
- select GENERIC_IOMAP
select GENERIC_IOREMAP
select GENERIC_SMP_IDLE_THREAD
select STACKTRACE_SUPPORT
@@ -59,6 +57,9 @@ config EARLY_PRINTK
config MMU
def_bool y
+config NO_IOPORT_MAP
+ def_bool y
+
config GENERIC_CSUM
def_bool y
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 8c1a78c8f527..1efa1e993d4b 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -5,3 +5,4 @@ generic-y += extable.h
generic-y += iomap.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
+generic-y += text-patching.h
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
index 522d321ea85a..83b2eb5de60c 100644
--- a/arch/hexagon/include/asm/io.h
+++ b/arch/hexagon/include/asm/io.h
@@ -8,38 +8,13 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H
-#ifdef __KERNEL__
-
#include <linux/types.h>
-#include <asm/iomap.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
-/*
- * We don't have PCI yet.
- * _IO_BASE is pointing at what should be unused virtual space.
- */
-#define IO_SPACE_LIMIT 0xffff
-#define _IO_BASE ((void __iomem *)0xfe000000)
-
-#define IOMEM(x) ((void __force __iomem *)(x))
-
extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
unsigned long end, unsigned long flags);
-/* Defined in lib/io.c, needed for smc91x driver. */
-extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
-extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
-
-extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
-extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
-
-#define readsw(p, d, l) __raw_readsw(p, d, l)
-#define writesw(p, d, l) __raw_writesw(p, d, l)
-
-#define readsl(p, d, l) __raw_readsl(p, d, l)
-#define writesl(p, d, l) __raw_writesl(p, d, l)
-
/*
* virt_to_phys - map virtual address to physical
* @address: address to map
@@ -59,20 +34,11 @@ static inline void *phys_to_virt(unsigned long address)
}
/*
- * IO port access primitives. Hexagon doesn't have special IO access
- * instructions; all I/O is memory mapped.
- *
- * in/out are used for "ports", but we don't have "port instructions",
- * so these are really just memory mapped too.
- */
-
-/*
* readb - read byte from memory mapped device
* @addr: pointer to memory
*
- * Operates on "I/O bus memory space"
*/
-static inline u8 readb(const volatile void __iomem *addr)
+static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
asm volatile(
@@ -82,8 +48,9 @@ static inline u8 readb(const volatile void __iomem *addr)
);
return val;
}
+#define __raw_readb __raw_readb
-static inline u16 readw(const volatile void __iomem *addr)
+static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
asm volatile(
@@ -93,8 +60,9 @@ static inline u16 readw(const volatile void __iomem *addr)
);
return val;
}
+#define __raw_readw __raw_readw
-static inline u32 readl(const volatile void __iomem *addr)
+static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
asm volatile(
@@ -104,6 +72,7 @@ static inline u32 readl(const volatile void __iomem *addr)
);
return val;
}
+#define __raw_readl __raw_readl
/*
* writeb - write a byte to a memory location
@@ -111,7 +80,7 @@ static inline u32 readl(const volatile void __iomem *addr)
* @addr: pointer to memory
*
*/
-static inline void writeb(u8 data, volatile void __iomem *addr)
+static inline void __raw_writeb(u8 data, volatile void __iomem *addr)
{
asm volatile(
"memb(%0) = %1;"
@@ -120,8 +89,9 @@ static inline void writeb(u8 data, volatile void __iomem *addr)
: "memory"
);
}
+#define __raw_writeb __raw_writeb
-static inline void writew(u16 data, volatile void __iomem *addr)
+static inline void __raw_writew(u16 data, volatile void __iomem *addr)
{
asm volatile(
"memh(%0) = %1;"
@@ -131,8 +101,9 @@ static inline void writew(u16 data, volatile void __iomem *addr)
);
}
+#define __raw_writew __raw_writew
-static inline void writel(u32 data, volatile void __iomem *addr)
+static inline void __raw_writel(u32 data, volatile void __iomem *addr)
{
asm volatile(
"memw(%0) = %1;"
@@ -141,26 +112,7 @@ static inline void writel(u32 data, volatile void __iomem *addr)
: "memory"
);
}
-
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-
-/*
- * http://comments.gmane.org/gmane.linux.ports.arm.kernel/117626
- */
-
-#define readb_relaxed __raw_readb
-#define readw_relaxed __raw_readw
-#define readl_relaxed __raw_readl
-
-#define writeb_relaxed __raw_writeb
-#define writew_relaxed __raw_writew
-#define writel_relaxed __raw_writel
+#define __raw_writel __raw_writel
/*
* I/O memory mapping functions.
@@ -168,140 +120,6 @@ static inline void writel(u32 data, volatile void __iomem *addr)
#define _PAGE_IOREMAP (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
(__HEXAGON_C_DEV << 6))
-#define __raw_writel writel
-
-static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
- int count)
-{
- memcpy(dst, (void *) src, count);
-}
-
-static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
- int count)
-{
- memcpy((void *) dst, src, count);
-}
-
-static inline void memset_io(volatile void __iomem *addr, int value,
- size_t size)
-{
- memset((void __force *)addr, value, size);
-}
-
-#define PCI_IO_ADDR (volatile void __iomem *)
-
-/*
- * inb - read byte from I/O port or something
- * @port: address in I/O space
- *
- * Operates on "I/O bus I/O space"
- */
-static inline u8 inb(unsigned long port)
-{
- return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
-}
-
-static inline u16 inw(unsigned long port)
-{
- return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
-}
-
-static inline u32 inl(unsigned long port)
-{
- return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
-}
-
-/*
- * outb - write a byte to a memory location
- * @data: data to write to
- * @addr: address in I/O space
- */
-static inline void outb(u8 data, unsigned long port)
-{
- writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
-}
-
-static inline void outw(u16 data, unsigned long port)
-{
- writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
-}
-
-static inline void outl(u32 data, unsigned long port)
-{
- writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
-}
-
-#define outb_p outb
-#define outw_p outw
-#define outl_p outl
-
-#define inb_p inb
-#define inw_p inw
-#define inl_p inl
-
-static inline void insb(unsigned long port, void *buffer, int count)
-{
- if (count) {
- u8 *buf = buffer;
- do {
- u8 x = inb(port);
- *buf++ = x;
- } while (--count);
- }
-}
-
-static inline void insw(unsigned long port, void *buffer, int count)
-{
- if (count) {
- u16 *buf = buffer;
- do {
- u16 x = inw(port);
- *buf++ = x;
- } while (--count);
- }
-}
-
-static inline void insl(unsigned long port, void *buffer, int count)
-{
- if (count) {
- u32 *buf = buffer;
- do {
- u32 x = inw(port);
- *buf++ = x;
- } while (--count);
- }
-}
-
-static inline void outsb(unsigned long port, const void *buffer, int count)
-{
- if (count) {
- const u8 *buf = buffer;
- do {
- outb(*buf++, port);
- } while (--count);
- }
-}
-
-static inline void outsw(unsigned long port, const void *buffer, int count)
-{
- if (count) {
- const u16 *buf = buffer;
- do {
- outw(*buf++, port);
- } while (--count);
- }
-}
-
-static inline void outsl(unsigned long port, const void *buffer, int count)
-{
- if (count) {
- const u32 *buf = buffer;
- do {
- outl(*buf++, port);
- } while (--count);
- }
-}
-
/*
* These defines are necessary to use the generic io.h for filling in
* the missing parts of the API contract. This is because the platform
@@ -310,23 +128,6 @@ static inline void outsl(unsigned long port, const void *buffer, int count)
*/
#define virt_to_phys virt_to_phys
#define phys_to_virt phys_to_virt
-#define memset_io memset_io
-#define memcpy_fromio memcpy_fromio
-#define memcpy_toio memcpy_toio
-#define readb readb
-#define readw readw
-#define readl readl
-#define writeb writeb
-#define writew writew
-#define writel writel
-#define insb insb
-#define insw insw
-#define insl insl
-#define outsb outsb
-#define outsw outsw
-#define outsl outsl
#include <asm-generic/io.h>
-#endif /* __KERNEL__ */
-
#endif
diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h
index 8a6af57274c2..137ba7c5de48 100644
--- a/arch/hexagon/include/asm/page.h
+++ b/arch/hexagon/include/asm/page.h
@@ -45,9 +45,7 @@
#define HVM_HUGEPAGE_SIZE 0x5
#endif
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+#include <vdso/page.h>
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@@ -118,12 +116,6 @@ static inline void clear_page(void *page)
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-/*
- * page_to_phys - convert page to physical address
- * @page - pointer to page entry in mem_map
- */
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-
static inline unsigned long virt_to_pfn(const void *kaddr)
{
return __pa(kaddr) >> PAGE_SHIFT;
diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h
index d5f66495b670..63add2d863e8 100644
--- a/arch/hexagon/include/asm/spinlock_types.h
+++ b/arch/hexagon/include/asm/spinlock_types.h
@@ -9,7 +9,7 @@
#define _ASM_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
typedef struct {
diff --git a/arch/hexagon/lib/Makefile b/arch/hexagon/lib/Makefile
index a64641e89d5f..107894c0910e 100644
--- a/arch/hexagon/lib/Makefile
+++ b/arch/hexagon/lib/Makefile
@@ -2,5 +2,5 @@
#
# Makefile for hexagon-specific library files.
#
-obj-y = checksum.o io.o memcpy.o memset.o memcpy_likely_aligned.o \
+obj-y = checksum.o memcpy.o memset.o memcpy_likely_aligned.o \
divsi3.o modsi3.o udivsi3.o umodsi3.o
diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c
deleted file mode 100644
index 55f75392857b..000000000000
--- a/arch/hexagon/lib/io.c
+++ /dev/null
@@ -1,82 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * I/O access functions for Hexagon
- *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
- */
-
-#include <asm/io.h>
-
-/* These are all FIFO routines! */
-
-/*
- * __raw_readsw - read words a short at a time
- * @addr: source address
- * @data: data address
- * @len: number of shorts to read
- */
-void __raw_readsw(const void __iomem *addr, void *data, int len)
-{
- const volatile short int *src = (short int *) addr;
- short int *dst = (short int *) data;
-
- if ((u32)data & 0x1)
- panic("unaligned pointer to readsw");
-
- while (len-- > 0)
- *dst++ = *src;
-
-}
-EXPORT_SYMBOL(__raw_readsw);
-
-/*
- * __raw_writesw - read words a short at a time
- * @addr: source address
- * @data: data address
- * @len: number of shorts to read
- */
-void __raw_writesw(void __iomem *addr, const void *data, int len)
-{
- const short int *src = (short int *)data;
- volatile short int *dst = (short int *)addr;
-
- if ((u32)data & 0x1)
- panic("unaligned pointer to writesw");
-
- while (len-- > 0)
- *dst = *src++;
-
-
-}
-EXPORT_SYMBOL(__raw_writesw);
-
-/* Pretty sure len is pre-adjusted for the length of the access already */
-void __raw_readsl(const void __iomem *addr, void *data, int len)
-{
- const volatile long *src = (long *) addr;
- long *dst = (long *) data;
-
- if ((u32)data & 0x3)
- panic("unaligned pointer to readsl");
-
- while (len-- > 0)
- *dst++ = *src;
-
-
-}
-EXPORT_SYMBOL(__raw_readsl);
-
-void __raw_writesl(void __iomem *addr, const void *data, int len)
-{
- const long *src = (long *)data;
- volatile long *dst = (long *)addr;
-
- if ((u32)data & 0x3)
- panic("unaligned pointer to writesl");
-
- while (len-- > 0)
- *dst = *src++;
-
-
-}
-EXPORT_SYMBOL(__raw_writesl);
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index bb35c34f86d2..dae3a9104ca6 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -23,6 +23,7 @@ config LOONGARCH
select ARCH_HAS_KERNEL_FPU_SUPPORT if CPU_HAS_FPU
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+ select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTE_DEVMAP
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SET_MEMORY
@@ -66,6 +67,7 @@ config LOONGARCH
select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_LTO_CLANG_THIN
select ARCH_SUPPORTS_NUMA_BALANCING
+ select ARCH_SUPPORTS_RT
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_USE_QUEUED_RWLOCKS
@@ -155,6 +157,7 @@ config LOONGARCH
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK
select HAVE_PREEMPT_DYNAMIC_KEY
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE if UNWINDER_ORC
@@ -604,6 +607,9 @@ config ARCH_SUPPORTS_KEXEC
config ARCH_SUPPORTS_CRASH_DUMP
def_bool y
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
config ARCH_SELECTS_CRASH_DUMP
def_bool y
depends on CRASH_DUMP
diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile
index ae3f80622f4c..567bd122a9ee 100644
--- a/arch/loongarch/Makefile
+++ b/arch/loongarch/Makefile
@@ -59,7 +59,7 @@ endif
ifdef CONFIG_64BIT
ld-emul = $(64bit-emul)
-cflags-y += -mabi=lp64s
+cflags-y += -mabi=lp64s -mcmodel=normal
endif
cflags-y += -pipe $(CC_FLAGS_NO_FPU)
@@ -104,7 +104,7 @@ ifdef CONFIG_OBJTOOL
KBUILD_CFLAGS += -fno-jump-tables
endif
-KBUILD_RUSTFLAGS += --target=loongarch64-unknown-none-softfloat
+KBUILD_RUSTFLAGS += --target=loongarch64-unknown-none-softfloat -Ccode-model=small
KBUILD_RUSTFLAGS_KERNEL += -Zdirect-access-external-data=yes
KBUILD_RUSTFLAGS_MODULE += -Zdirect-access-external-data=no
diff --git a/arch/loongarch/boot/dts/loongson-2k1000.dtsi b/arch/loongarch/boot/dts/loongson-2k1000.dtsi
index 92180140eb56..8dff2aa52417 100644
--- a/arch/loongarch/boot/dts/loongson-2k1000.dtsi
+++ b/arch/loongarch/boot/dts/loongson-2k1000.dtsi
@@ -266,7 +266,7 @@
status = "disabled";
};
- dma-controller@1fe00c20 {
+ apbdma2: dma-controller@1fe00c20 {
compatible = "loongson,ls2k1000-apbdma";
reg = <0x0 0x1fe00c20 0x0 0x8>;
interrupt-parent = <&liointc1>;
@@ -276,7 +276,7 @@
status = "disabled";
};
- dma-controller@1fe00c30 {
+ apbdma3: dma-controller@1fe00c30 {
compatible = "loongson,ls2k1000-apbdma";
reg = <0x0 0x1fe00c30 0x0 0x8>;
interrupt-parent = <&liointc1>;
@@ -352,6 +352,19 @@
status = "disabled";
};
+ i2s: i2s@1fe2d000 {
+ compatible = "loongson,ls2k1000-i2s";
+ reg = <0 0x1fe2d000 0 0x14>,
+ <0 0x1fe00438 0 0x8>;
+ interrupt-parent = <&liointc0>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk LOONGSON2_APB_CLK>;
+ dmas = <&apbdma2 0>, <&apbdma3 0>;
+ dma-names = "tx", "rx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
spi0: spi@1fff0220 {
compatible = "loongson,ls2k1000-spi";
reg = <0x0 0x1fff0220 0x0 0x10>;
diff --git a/arch/loongarch/boot/dts/loongson-2k2000.dtsi b/arch/loongarch/boot/dts/loongson-2k2000.dtsi
index 0953c5707825..b4ff55a33e90 100644
--- a/arch/loongarch/boot/dts/loongson-2k2000.dtsi
+++ b/arch/loongarch/boot/dts/loongson-2k2000.dtsi
@@ -173,6 +173,22 @@
status = "disabled";
};
+ i2c@1fe00120 {
+ compatible = "loongson,ls2k-i2c";
+ reg = <0x0 0x1fe00120 0x0 0x8>;
+ interrupt-parent = <&liointc>;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ i2c@1fe00130 {
+ compatible = "loongson,ls2k-i2c";
+ reg = <0x0 0x1fe00130 0x0 0x8>;
+ interrupt-parent = <&liointc>;
+ interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
uart0: serial@1fe001e0 {
compatible = "ns16550a";
reg = <0x0 0x1fe001e0 0x0 0x10>;
@@ -243,9 +259,11 @@
status = "disabled";
};
- hda@7,0 {
+ i2s@7,0 {
reg = <0x3800 0x0 0x0 0x0 0x0>;
- interrupts = <58 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <78 IRQ_TYPE_LEVEL_HIGH>,
+ <79 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tx", "rx";
interrupt-parent = <&pic>;
status = "disabled";
};
diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig
index 75b366407a60..4dffc90192f7 100644
--- a/arch/loongarch/configs/loongson3_defconfig
+++ b/arch/loongarch/configs/loongson3_defconfig
@@ -1,4 +1,5 @@
# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_ZSTD=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ=y
@@ -70,6 +71,14 @@ CONFIG_ACPI_IPMI=m
CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_PCI_SLOT=y
CONFIG_ACPI_HOTPLUG_MEMORY=y
+CONFIG_ACPI_BGRT=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_LOONGSON3_CPUFREQ=m
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_JUMP_LABEL=y
@@ -78,6 +87,9 @@ CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
+CONFIG_MODULE_COMPRESS=y
+CONFIG_MODULE_COMPRESS_ZSTD=y
+CONFIG_MODULE_DECOMPRESS=y
CONFIG_BLK_DEV_ZONED=y
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_BLK_WBT=y
@@ -85,6 +97,8 @@ CONFIG_BLK_CGROUP_IOLATENCY=y
CONFIG_BLK_CGROUP_FC_APPID=y
CONFIG_BLK_CGROUP_IOCOST=y
CONFIG_BLK_CGROUP_IOPRIO=y
+CONFIG_BLK_INLINE_ENCRYPTION=y
+CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_BSD_DISKLABEL=y
CONFIG_UNIXWARE_DISKLABEL=y
@@ -413,7 +427,16 @@ CONFIG_PARPORT_PC=y
CONFIG_PARPORT_SERIAL=y
CONFIG_PARPORT_PC_FIFO=y
CONFIG_ZRAM=m
+CONFIG_ZRAM_BACKEND_LZ4=y
+CONFIG_ZRAM_BACKEND_LZ4HC=y
+CONFIG_ZRAM_BACKEND_ZSTD=y
+CONFIG_ZRAM_BACKEND_DEFLATE=y
+CONFIG_ZRAM_BACKEND_842=y
+CONFIG_ZRAM_BACKEND_LZO=y
CONFIG_ZRAM_DEF_COMP_ZSTD=y
+CONFIG_ZRAM_WRITEBACK=y
+CONFIG_ZRAM_MEMORY_TRACKING=y
+CONFIG_ZRAM_MULTI_COMP=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
@@ -433,6 +456,9 @@ CONFIG_NVME_TARGET_RDMA=m
CONFIG_NVME_TARGET_FC=m
CONFIG_NVME_TARGET_TCP=m
CONFIG_EEPROM_AT24=m
+CONFIG_PVPANIC=y
+CONFIG_PVPANIC_MMIO=m
+CONFIG_PVPANIC_PCI=m
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_CHR_DEV_SG=y
@@ -470,12 +496,10 @@ CONFIG_PATA_ATIIXP=y
CONFIG_PATA_PCMCIA=m
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID456=m
-CONFIG_MD_MULTIPATH=m
CONFIG_BCACHE=m
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=m
@@ -489,6 +513,16 @@ CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_QL=m
CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_MULTIPATH_HST=m
+CONFIG_DM_MULTIPATH_IOA=m
+CONFIG_DM_INIT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=m
+CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_INTEGRITY=m
+CONFIG_DM_ZONED=m
+CONFIG_DM_VDO=m
CONFIG_TARGET_CORE=m
CONFIG_TCM_IBLOCK=m
CONFIG_TCM_FILEIO=m
@@ -500,6 +534,13 @@ CONFIG_NETDEVICES=y
CONFIG_BONDING=m
CONFIG_DUMMY=y
CONFIG_WIREGUARD=m
+CONFIG_IFB=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
@@ -580,12 +621,14 @@ CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=m
# CONFIG_USB_NET_AX8817X is not set
# CONFIG_USB_NET_AX88179_178A is not set
CONFIG_USB_NET_CDC_EEM=m
CONFIG_USB_NET_HUAWEI_CDC_NCM=m
CONFIG_USB_NET_CDC_MBIM=m
# CONFIG_USB_NET_NET1080 is not set
+CONFIG_USB_NET_RNDIS_HOST=m
# CONFIG_USB_BELKIN is not set
# CONFIG_USB_ARMLINUX is not set
# CONFIG_USB_NET_ZAURUS is not set
@@ -594,10 +637,11 @@ CONFIG_ATH9K_HTC=m
CONFIG_IWLWIFI=m
CONFIG_IWLDVM=m
CONFIG_IWLMVM=m
-CONFIG_HOSTAP=m
CONFIG_MT7601U=m
CONFIG_RT2X00=m
CONFIG_RT2800USB=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
CONFIG_RTL8192CE=m
CONFIG_RTL8192SE=m
CONFIG_RTL8192DE=m
@@ -607,18 +651,26 @@ CONFIG_RTL8188EE=m
CONFIG_RTL8192EE=m
CONFIG_RTL8821AE=m
CONFIG_RTL8192CU=m
+CONFIG_RTL8192DU=m
# CONFIG_RTLWIFI_DEBUG is not set
CONFIG_RTL8XXXU=m
CONFIG_RTW88=m
CONFIG_RTW88_8822BE=m
+CONFIG_RTW88_8822BU=m
CONFIG_RTW88_8822CE=m
+CONFIG_RTW88_8822CU=m
CONFIG_RTW88_8723DE=m
+CONFIG_RTW88_8723DU=m
CONFIG_RTW88_8821CE=m
+CONFIG_RTW88_8821CU=m
CONFIG_RTW89=m
+CONFIG_RTW89_8851BE=m
CONFIG_RTW89_8852AE=m
+CONFIG_RTW89_8852BE=m
+CONFIG_RTW89_8852BTE=m
CONFIG_RTW89_8852CE=m
+CONFIG_RTW89_8922AE=m
CONFIG_ZD1211RW=m
-CONFIG_USB_NET_RNDIS_WLAN=m
CONFIG_USB4_NET=m
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
@@ -651,6 +703,9 @@ CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PIIX4=y
+CONFIG_I2C_DESIGNWARE_CORE=y
+CONFIG_I2C_DESIGNWARE_SLAVE=y
+CONFIG_I2C_DESIGNWARE_PCI=y
CONFIG_I2C_GPIO=y
CONFIG_I2C_LS2X=y
CONFIG_SPI=y
@@ -727,11 +782,22 @@ CONFIG_SND_HDA_CODEC_CONEXANT=y
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_SOC=m
CONFIG_SND_SOC_LOONGSON_CARD=m
+CONFIG_SND_SOC_ES7134=m
+CONFIG_SND_SOC_ES7241=m
+CONFIG_SND_SOC_ES8311=m
+CONFIG_SND_SOC_ES8316=m
+CONFIG_SND_SOC_ES8323=m
+CONFIG_SND_SOC_ES8326=m
+CONFIG_SND_SOC_ES8328_I2C=m
+CONFIG_SND_SOC_ES8328_SPI=m
+CONFIG_SND_SOC_UDA1334=m
+CONFIG_SND_SOC_UDA1342=m
CONFIG_SND_VIRTIO=m
CONFIG_HIDRAW=y
CONFIG_UHID=m
CONFIG_HID_A4TECH=m
CONFIG_HID_CHERRY=m
+CONFIG_HID_ELAN=m
CONFIG_HID_LOGITECH=m
CONFIG_HID_LOGITECH_DJ=m
CONFIG_LOGITECH_FF=y
@@ -740,7 +806,11 @@ CONFIG_LOGIG940_FF=y
CONFIG_HID_MICROSOFT=m
CONFIG_HID_MULTITOUCH=m
CONFIG_HID_SUNPLUS=m
+CONFIG_HID_WACOM=m
CONFIG_USB_HIDDEV=y
+CONFIG_I2C_HID_ACPI=m
+CONFIG_I2C_HID_OF=m
+CONFIG_I2C_HID_OF_ELAN=m
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_MON=y
@@ -775,7 +845,7 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_EFI=y
CONFIG_RTC_DRV_LOONGSON=y
CONFIG_DMADEVICES=y
-CONFIG_LS2X_APB_DMA=y
+CONFIG_LOONGSON2_APB_DMA=y
CONFIG_UDMABUF=y
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_HEAPS_SYSTEM=y
@@ -852,6 +922,9 @@ CONFIG_F2FS_FS=m
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_CHECK_FS=y
CONFIG_F2FS_FS_COMPRESSION=y
+CONFIG_FS_ENCRYPTION=y
+CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
+CONFIG_FS_VERITY=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
@@ -904,16 +977,14 @@ CONFIG_SQUASHFS_ZSTD=y
CONFIG_MINIX_FS=m
CONFIG_ROMFS_FS=m
CONFIG_PSTORE=m
-CONFIG_PSTORE_LZO_COMPRESS=m
-CONFIG_PSTORE_LZ4_COMPRESS=m
-CONFIG_PSTORE_LZ4HC_COMPRESS=m
-CONFIG_PSTORE_842_COMPRESS=y
-CONFIG_PSTORE_ZSTD_COMPRESS=y
-CONFIG_PSTORE_ZSTD_COMPRESS_DEFAULT=y
+CONFIG_PSTORE_COMPRESS=y
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
CONFIG_EROFS_FS=m
CONFIG_EROFS_FS_ZIP_LZMA=y
+CONFIG_EROFS_FS_ZIP_DEFLATE=y
+CONFIG_EROFS_FS_ZIP_ZSTD=y
+CONFIG_EROFS_FS_ONDEMAND=y
CONFIG_EROFS_FS_PCPU_KTHREAD=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
diff --git a/arch/loongarch/include/asm/Kbuild b/arch/loongarch/include/asm/Kbuild
index 5b5a6c90e6e2..80ddb5edb845 100644
--- a/arch/loongarch/include/asm/Kbuild
+++ b/arch/loongarch/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += ioctl.h
generic-y += mmzone.h
generic-y += statfs.h
generic-y += param.h
+generic-y += text-patching.h
diff --git a/arch/loongarch/include/asm/ftrace.h b/arch/loongarch/include/asm/ftrace.h
index c0a682808e07..8f13eaeaa325 100644
--- a/arch/loongarch/include/asm/ftrace.h
+++ b/arch/loongarch/include/asm/ftrace.h
@@ -44,40 +44,19 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent);
#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
struct ftrace_ops;
-struct ftrace_regs {
- struct pt_regs regs;
-};
+#include <linux/ftrace_regs.h>
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
{
- return &fregs->regs;
-}
-
-static __always_inline unsigned long
-ftrace_regs_get_instruction_pointer(struct ftrace_regs *fregs)
-{
- return instruction_pointer(&fregs->regs);
+ return &arch_ftrace_regs(fregs)->regs;
}
static __always_inline void
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip)
{
- instruction_pointer_set(&fregs->regs, ip);
+ instruction_pointer_set(&arch_ftrace_regs(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)
-
#define ftrace_graph_func ftrace_graph_func
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs);
@@ -90,7 +69,7 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
}
#define arch_ftrace_set_direct_caller(fregs, addr) \
- __arch_ftrace_set_direct_caller(&(fregs)->regs, addr)
+ __arch_ftrace_set_direct_caller(&arch_ftrace_regs(fregs)->regs, addr)
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
#endif
diff --git a/arch/loongarch/include/asm/hugetlb.h b/arch/loongarch/include/asm/hugetlb.h
index 5da32c00d483..b837c65a4894 100644
--- a/arch/loongarch/include/asm/hugetlb.h
+++ b/arch/loongarch/include/asm/hugetlb.h
@@ -16,12 +16,7 @@ static inline int prepare_hugepage_range(struct file *file,
unsigned long len)
{
unsigned long task_size = STACK_TOP;
- struct hstate *h = hstate_file(file);
- if (len & ~huge_page_mask(h))
- return -EINVAL;
- if (addr & ~huge_page_mask(h))
- return -EINVAL;
if (len > task_size)
return -ENOMEM;
if (task_size - len < addr)
diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h
index 5e95a60df180..e77a56eaf906 100644
--- a/arch/loongarch/include/asm/io.h
+++ b/arch/loongarch/include/asm/io.h
@@ -62,16 +62,6 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
#define mmiowb() wmb()
-/*
- * String version of I/O memory access operations.
- */
-extern void __memset_io(volatile void __iomem *dst, int c, size_t count);
-extern void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count);
-extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count);
-#define memset_io(c, v, l) __memset_io((c), (v), (l))
-#define memcpy_fromio(a, c, l) __memcpy_fromio((a), (c), (l))
-#define memcpy_toio(c, a, l) __memcpy_toio((c), (a), (l))
-
#define __io_aw() mmiowb()
#ifdef CONFIG_KFENCE
diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h
index 9c2ca785faa9..a0ca84da8541 100644
--- a/arch/loongarch/include/asm/irq.h
+++ b/arch/loongarch/include/asm/irq.h
@@ -65,6 +65,7 @@ extern struct acpi_vector_group pch_group[MAX_IO_PICS];
extern struct acpi_vector_group msi_group[MAX_IO_PICS];
#define CORES_PER_EIO_NODE 4
+#define CORES_PER_VEIO_NODE 256
#define LOONGSON_CPU_UART0_VEC 10 /* CPU UART0 */
#define LOONGSON_CPU_THSENS_VEC 14 /* CPU Thsens */
diff --git a/arch/loongarch/include/asm/jump_label.h b/arch/loongarch/include/asm/jump_label.h
index 29acfe3de3fa..8a924bd69d19 100644
--- a/arch/loongarch/include/asm/jump_label.h
+++ b/arch/loongarch/include/asm/jump_label.h
@@ -13,18 +13,22 @@
#define JUMP_LABEL_NOP_SIZE 4
-#define JUMP_TABLE_ENTRY \
+/* This macro is also expanded on the Rust side. */
+#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\" \n\t" \
".align 3 \n\t" \
- ".long 1b - ., %l[l_yes] - . \n\t" \
- ".quad %0 - . \n\t" \
+ ".long 1b - ., " label " - . \n\t" \
+ ".quad " key " - . \n\t" \
".popsection \n\t"
+#define ARCH_STATIC_BRANCH_ASM(key, label) \
+ "1: nop \n\t" \
+ JUMP_TABLE_ENTRY(key, label)
+
static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
{
asm goto(
- "1: nop \n\t"
- JUMP_TABLE_ENTRY
+ ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]")
: : "i"(&((char *)key)[branch]) : : l_yes);
return false;
@@ -37,7 +41,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key * const ke
{
asm goto(
"1: b %l[l_yes] \n\t"
- JUMP_TABLE_ENTRY
+ JUMP_TABLE_ENTRY("%0", "%l[l_yes]")
: : "i"(&((char *)key)[branch]) : : l_yes);
return false;
diff --git a/arch/loongarch/include/asm/kasan.h b/arch/loongarch/include/asm/kasan.h
index c6bce5fbff57..7f52bd31b9d4 100644
--- a/arch/loongarch/include/asm/kasan.h
+++ b/arch/loongarch/include/asm/kasan.h
@@ -25,6 +25,7 @@
/* 64-bit segment value. */
#define XKPRANGE_UC_SEG (0x8000)
#define XKPRANGE_CC_SEG (0x9000)
+#define XKPRANGE_WC_SEG (0xa000)
#define XKVRANGE_VC_SEG (0xffff)
/* Cached */
@@ -41,20 +42,28 @@
#define XKPRANGE_UC_SHADOW_SIZE (XKPRANGE_UC_SIZE >> KASAN_SHADOW_SCALE_SHIFT)
#define XKPRANGE_UC_SHADOW_END (XKPRANGE_UC_KASAN_OFFSET + XKPRANGE_UC_SHADOW_SIZE)
+/* WriteCombine */
+#define XKPRANGE_WC_START WRITECOMBINE_BASE
+#define XKPRANGE_WC_SIZE XRANGE_SIZE
+#define XKPRANGE_WC_KASAN_OFFSET XKPRANGE_UC_SHADOW_END
+#define XKPRANGE_WC_SHADOW_SIZE (XKPRANGE_WC_SIZE >> KASAN_SHADOW_SCALE_SHIFT)
+#define XKPRANGE_WC_SHADOW_END (XKPRANGE_WC_KASAN_OFFSET + XKPRANGE_WC_SHADOW_SIZE)
+
/* VMALLOC (Cached or UnCached) */
#define XKVRANGE_VC_START MODULES_VADDR
#define XKVRANGE_VC_SIZE round_up(KFENCE_AREA_END - MODULES_VADDR + 1, PGDIR_SIZE)
-#define XKVRANGE_VC_KASAN_OFFSET XKPRANGE_UC_SHADOW_END
+#define XKVRANGE_VC_KASAN_OFFSET XKPRANGE_WC_SHADOW_END
#define XKVRANGE_VC_SHADOW_SIZE (XKVRANGE_VC_SIZE >> KASAN_SHADOW_SCALE_SHIFT)
#define XKVRANGE_VC_SHADOW_END (XKVRANGE_VC_KASAN_OFFSET + XKVRANGE_VC_SHADOW_SIZE)
/* KAsan shadow memory start right after vmalloc. */
#define KASAN_SHADOW_START round_up(KFENCE_AREA_END, PGDIR_SIZE)
#define KASAN_SHADOW_SIZE (XKVRANGE_VC_SHADOW_END - XKPRANGE_CC_KASAN_OFFSET)
-#define KASAN_SHADOW_END round_up(KASAN_SHADOW_START + KASAN_SHADOW_SIZE, PGDIR_SIZE)
+#define KASAN_SHADOW_END (round_up(KASAN_SHADOW_START + KASAN_SHADOW_SIZE, PGDIR_SIZE) - 1)
#define XKPRANGE_CC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_CC_KASAN_OFFSET)
#define XKPRANGE_UC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_UC_KASAN_OFFSET)
+#define XKPRANGE_WC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_WC_KASAN_OFFSET)
#define XKVRANGE_VC_SHADOW_OFFSET (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET)
extern bool kasan_early_stage;
diff --git a/arch/loongarch/include/asm/kvm_eiointc.h b/arch/loongarch/include/asm/kvm_eiointc.h
new file mode 100644
index 000000000000..a3a40aba8acf
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_eiointc.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_KVM_EIOINTC_H
+#define __ASM_KVM_EIOINTC_H
+
+#include <kvm/iodev.h>
+
+#define EIOINTC_IRQS 256
+#define EIOINTC_ROUTE_MAX_VCPUS 256
+#define EIOINTC_IRQS_U8_NUMS (EIOINTC_IRQS / 8)
+#define EIOINTC_IRQS_U16_NUMS (EIOINTC_IRQS_U8_NUMS / 2)
+#define EIOINTC_IRQS_U32_NUMS (EIOINTC_IRQS_U8_NUMS / 4)
+#define EIOINTC_IRQS_U64_NUMS (EIOINTC_IRQS_U8_NUMS / 8)
+/* map to ipnum per 32 irqs */
+#define EIOINTC_IRQS_NODETYPE_COUNT 16
+
+#define EIOINTC_BASE 0x1400
+#define EIOINTC_SIZE 0x900
+
+#define EIOINTC_NODETYPE_START 0xa0
+#define EIOINTC_NODETYPE_END 0xbf
+#define EIOINTC_IPMAP_START 0xc0
+#define EIOINTC_IPMAP_END 0xc7
+#define EIOINTC_ENABLE_START 0x200
+#define EIOINTC_ENABLE_END 0x21f
+#define EIOINTC_BOUNCE_START 0x280
+#define EIOINTC_BOUNCE_END 0x29f
+#define EIOINTC_ISR_START 0x300
+#define EIOINTC_ISR_END 0x31f
+#define EIOINTC_COREISR_START 0x400
+#define EIOINTC_COREISR_END 0x41f
+#define EIOINTC_COREMAP_START 0x800
+#define EIOINTC_COREMAP_END 0x8ff
+
+#define EIOINTC_VIRT_BASE (0x40000000)
+#define EIOINTC_VIRT_SIZE (0x1000)
+
+#define EIOINTC_VIRT_FEATURES (0x0)
+#define EIOINTC_HAS_VIRT_EXTENSION (0)
+#define EIOINTC_HAS_ENABLE_OPTION (1)
+#define EIOINTC_HAS_INT_ENCODE (2)
+#define EIOINTC_HAS_CPU_ENCODE (3)
+#define EIOINTC_VIRT_HAS_FEATURES ((1U << EIOINTC_HAS_VIRT_EXTENSION) \
+ | (1U << EIOINTC_HAS_ENABLE_OPTION) \
+ | (1U << EIOINTC_HAS_INT_ENCODE) \
+ | (1U << EIOINTC_HAS_CPU_ENCODE))
+#define EIOINTC_VIRT_CONFIG (0x4)
+#define EIOINTC_ENABLE (1)
+#define EIOINTC_ENABLE_INT_ENCODE (2)
+#define EIOINTC_ENABLE_CPU_ENCODE (3)
+
+#define LOONGSON_IP_NUM 8
+
+struct loongarch_eiointc {
+ spinlock_t lock;
+ struct kvm *kvm;
+ struct kvm_io_device device;
+ struct kvm_io_device device_vext;
+ uint32_t num_cpu;
+ uint32_t features;
+ uint32_t status;
+
+ /* hardware state */
+ union nodetype {
+ u64 reg_u64[EIOINTC_IRQS_NODETYPE_COUNT / 4];
+ u32 reg_u32[EIOINTC_IRQS_NODETYPE_COUNT / 2];
+ u16 reg_u16[EIOINTC_IRQS_NODETYPE_COUNT];
+ u8 reg_u8[EIOINTC_IRQS_NODETYPE_COUNT * 2];
+ } nodetype;
+
+ /* one bit shows the state of one irq */
+ union bounce {
+ u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
+ u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
+ u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
+ u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
+ } bounce;
+
+ union isr {
+ u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
+ u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
+ u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
+ u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
+ } isr;
+ union coreisr {
+ u64 reg_u64[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U64_NUMS];
+ u32 reg_u32[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U32_NUMS];
+ u16 reg_u16[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U16_NUMS];
+ u8 reg_u8[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U8_NUMS];
+ } coreisr;
+ union enable {
+ u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
+ u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
+ u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
+ u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
+ } enable;
+
+ /* use one byte to config ipmap for 32 irqs at once */
+ union ipmap {
+ u64 reg_u64;
+ u32 reg_u32[EIOINTC_IRQS_U32_NUMS / 4];
+ u16 reg_u16[EIOINTC_IRQS_U16_NUMS / 4];
+ u8 reg_u8[EIOINTC_IRQS_U8_NUMS / 4];
+ } ipmap;
+ /* use one byte to config coremap for one irq */
+ union coremap {
+ u64 reg_u64[EIOINTC_IRQS / 8];
+ u32 reg_u32[EIOINTC_IRQS / 4];
+ u16 reg_u16[EIOINTC_IRQS / 2];
+ u8 reg_u8[EIOINTC_IRQS];
+ } coremap;
+
+ DECLARE_BITMAP(sw_coreisr[EIOINTC_ROUTE_MAX_VCPUS][LOONGSON_IP_NUM], EIOINTC_IRQS);
+ uint8_t sw_coremap[EIOINTC_IRQS];
+};
+
+int kvm_loongarch_register_eiointc_device(void);
+void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level);
+
+#endif /* __ASM_KVM_EIOINTC_H */
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index d6bb72424027..7b8367c39da8 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -18,8 +18,13 @@
#include <asm/inst.h>
#include <asm/kvm_mmu.h>
+#include <asm/kvm_ipi.h>
+#include <asm/kvm_eiointc.h>
+#include <asm/kvm_pch_pic.h>
#include <asm/loongarch.h>
+#define __KVM_HAVE_ARCH_INTC_INITIALIZED
+
/* Loongarch KVM register ids */
#define KVM_GET_IOC_CSR_IDX(id) ((id & KVM_CSR_IDX_MASK) >> LOONGARCH_REG_SHIFT)
#define KVM_GET_IOC_CPUCFG_IDX(id) ((id & KVM_CPUCFG_IDX_MASK) >> LOONGARCH_REG_SHIFT)
@@ -44,6 +49,12 @@ struct kvm_vm_stat {
struct kvm_vm_stat_generic generic;
u64 pages;
u64 hugepages;
+ u64 ipi_read_exits;
+ u64 ipi_write_exits;
+ u64 eiointc_read_exits;
+ u64 eiointc_write_exits;
+ u64 pch_pic_read_exits;
+ u64 pch_pic_write_exits;
};
struct kvm_vcpu_stat {
@@ -84,7 +95,7 @@ struct kvm_world_switch {
*
* For LOONGARCH_CSR_CPUID register, max CPUID size if 512
* For IPI hardware, max destination CPUID size 1024
- * For extioi interrupt controller, max destination CPUID size is 256
+ * For eiointc interrupt controller, max destination CPUID size is 256
* For msgint interrupt controller, max supported CPUID size is 65536
*
* Currently max CPUID is defined as 256 for KVM hypervisor, in future
@@ -117,6 +128,9 @@ struct kvm_arch {
s64 time_offset;
struct kvm_context __percpu *vmcs;
+ struct loongarch_ipi *ipi;
+ struct loongarch_eiointc *eiointc;
+ struct loongarch_pch_pic *pch_pic;
};
#define CSR_MAX_NUMS 0x800
@@ -221,6 +235,8 @@ struct kvm_vcpu_arch {
int last_sched_cpu;
/* mp state */
struct kvm_mp_state mp_state;
+ /* ipi state */
+ struct ipi_state ipi_state;
/* cpucfg */
u32 cpucfg[KVM_MAX_CPUCFG_REGS];
diff --git a/arch/loongarch/include/asm/kvm_ipi.h b/arch/loongarch/include/asm/kvm_ipi.h
new file mode 100644
index 000000000000..060163dfb4a3
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_ipi.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_KVM_IPI_H
+#define __ASM_KVM_IPI_H
+
+#include <kvm/iodev.h>
+
+#define LARCH_INT_IPI 12
+
+struct loongarch_ipi {
+ spinlock_t lock;
+ struct kvm *kvm;
+ struct kvm_io_device device;
+};
+
+struct ipi_state {
+ spinlock_t lock;
+ uint32_t status;
+ uint32_t en;
+ uint32_t set;
+ uint32_t clear;
+ uint64_t buf[4];
+};
+
+#define IOCSR_IPI_BASE 0x1000
+#define IOCSR_IPI_SIZE 0x160
+
+#define IOCSR_IPI_STATUS 0x000
+#define IOCSR_IPI_EN 0x004
+#define IOCSR_IPI_SET 0x008
+#define IOCSR_IPI_CLEAR 0x00c
+#define IOCSR_IPI_BUF_20 0x020
+#define IOCSR_IPI_BUF_28 0x028
+#define IOCSR_IPI_BUF_30 0x030
+#define IOCSR_IPI_BUF_38 0x038
+#define IOCSR_IPI_SEND 0x040
+#define IOCSR_MAIL_SEND 0x048
+#define IOCSR_ANY_SEND 0x158
+
+int kvm_loongarch_register_ipi_device(void);
+
+#endif
diff --git a/arch/loongarch/include/asm/kvm_pch_pic.h b/arch/loongarch/include/asm/kvm_pch_pic.h
new file mode 100644
index 000000000000..e6df6a4c1c70
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_pch_pic.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_KVM_PCH_PIC_H
+#define __ASM_KVM_PCH_PIC_H
+
+#include <kvm/iodev.h>
+
+#define PCH_PIC_SIZE 0x3e8
+
+#define PCH_PIC_INT_ID_START 0x0
+#define PCH_PIC_INT_ID_END 0x7
+#define PCH_PIC_MASK_START 0x20
+#define PCH_PIC_MASK_END 0x27
+#define PCH_PIC_HTMSI_EN_START 0x40
+#define PCH_PIC_HTMSI_EN_END 0x47
+#define PCH_PIC_EDGE_START 0x60
+#define PCH_PIC_EDGE_END 0x67
+#define PCH_PIC_CLEAR_START 0x80
+#define PCH_PIC_CLEAR_END 0x87
+#define PCH_PIC_AUTO_CTRL0_START 0xc0
+#define PCH_PIC_AUTO_CTRL0_END 0xc7
+#define PCH_PIC_AUTO_CTRL1_START 0xe0
+#define PCH_PIC_AUTO_CTRL1_END 0xe7
+#define PCH_PIC_ROUTE_ENTRY_START 0x100
+#define PCH_PIC_ROUTE_ENTRY_END 0x13f
+#define PCH_PIC_HTMSI_VEC_START 0x200
+#define PCH_PIC_HTMSI_VEC_END 0x23f
+#define PCH_PIC_INT_IRR_START 0x380
+#define PCH_PIC_INT_IRR_END 0x38f
+#define PCH_PIC_INT_ISR_START 0x3a0
+#define PCH_PIC_INT_ISR_END 0x3af
+#define PCH_PIC_POLARITY_START 0x3e0
+#define PCH_PIC_POLARITY_END 0x3e7
+#define PCH_PIC_INT_ID_VAL 0x7000000UL
+#define PCH_PIC_INT_ID_VER 0x1UL
+
+struct loongarch_pch_pic {
+ spinlock_t lock;
+ struct kvm *kvm;
+ struct kvm_io_device device;
+ uint64_t mask; /* 1:disable irq, 0:enable irq */
+ uint64_t htmsi_en; /* 1:msi */
+ uint64_t edge; /* 1:edge triggered, 0:level triggered */
+ uint64_t auto_ctrl0; /* only use default value 00b */
+ uint64_t auto_ctrl1; /* only use default value 00b */
+ uint64_t last_intirr; /* edge detection */
+ uint64_t irr; /* interrupt request register */
+ uint64_t isr; /* interrupt service register */
+ uint64_t polarity; /* 0: high level trigger, 1: low level trigger */
+ uint8_t route_entry[64]; /* default value 0, route to int0: eiointc */
+ uint8_t htmsi_vector[64]; /* irq route table for routing to eiointc */
+ uint64_t pch_pic_base;
+};
+
+int kvm_loongarch_register_pch_pic_device(void);
+void pch_pic_set_irq(struct loongarch_pch_pic *s, int irq, int level);
+void pch_msi_set_irq(struct kvm *kvm, int irq, int level);
+
+#endif /* __ASM_KVM_PCH_PIC_H */
diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h
index e85df33f11c7..7368f12b7cb1 100644
--- a/arch/loongarch/include/asm/page.h
+++ b/arch/loongarch/include/asm/page.h
@@ -8,12 +8,7 @@
#include <linux/const.h>
#include <asm/addrspace.h>
-/*
- * PAGE_SHIFT determines the page size
- */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE - 1))
+#include <vdso/page.h>
#define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
@@ -81,9 +76,6 @@ struct page *tlb_virt_to_page(unsigned long kaddr);
#define pfn_to_phys(pfn) __pfn_to_phys(pfn)
#define phys_to_pfn(paddr) __phys_to_pfn(paddr)
-#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
-#define phys_to_page(paddr) pfn_to_page(phys_to_pfn(paddr))
-
#ifndef CONFIG_KFENCE
#define page_to_virt(page) __va(page_to_phys(page))
@@ -113,10 +105,7 @@ struct page *tlb_virt_to_page(unsigned long kaddr);
extern int __virt_addr_valid(volatile void *kaddr);
#define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr))
-#define VM_DATA_DEFAULT_FLAGS \
- (VM_READ | VM_WRITE | \
- ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_TSK_EXEC
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h
index 20714b73f14c..da346733a1da 100644
--- a/arch/loongarch/include/asm/pgtable.h
+++ b/arch/loongarch/include/asm/pgtable.h
@@ -268,8 +268,11 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pm
*/
extern void pgd_init(void *addr);
extern void pud_init(void *addr);
+#define pud_init pud_init
extern void pmd_init(void *addr);
+#define pmd_init pmd_init
extern void kernel_pte_init(void *addr);
+#define kernel_pte_init kernel_pte_init
/*
* Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
diff --git a/arch/loongarch/include/asm/set_memory.h b/arch/loongarch/include/asm/set_memory.h
index d70505b6676c..55dfaefd02c8 100644
--- a/arch/loongarch/include/asm/set_memory.h
+++ b/arch/loongarch/include/asm/set_memory.h
@@ -17,5 +17,6 @@ int set_memory_rw(unsigned long addr, int numpages);
bool kernel_page_present(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_invalid_noflush(struct page *page);
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
#endif /* _ASM_LOONGARCH_SET_MEMORY_H */
diff --git a/arch/loongarch/include/asm/thread_info.h b/arch/loongarch/include/asm/thread_info.h
index 8bf0e6f51546..4f5a9441754e 100644
--- a/arch/loongarch/include/asm/thread_info.h
+++ b/arch/loongarch/include/asm/thread_info.h
@@ -66,8 +66,9 @@ register unsigned long current_stack_pointer __asm__("$sp");
* - pending work-to-be-done flags are in LSW
* - other flags in MSW
*/
-#define TIF_SIGPENDING 1 /* signal pending */
-#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
+#define TIF_NEED_RESCHED 0 /* rescheduling necessary */
+#define TIF_NEED_RESCHED_LAZY 1 /* lazy rescheduling necessary */
+#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NOTIFY_RESUME 3 /* callback before returning to user */
#define TIF_NOTIFY_SIGNAL 4 /* signal notifications exist */
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
@@ -88,8 +89,9 @@ register unsigned long current_stack_pointer __asm__("$sp");
#define TIF_LBT_CTX_LIVE 20 /* LBT context must be preserved */
#define TIF_PATCH_PENDING 21 /* pending live patching update */
-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_NEED_RESCHED_LAZY (1<<TIF_NEED_RESCHED_LAZY)
+#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_NOTIFY_SIGNAL (1<<TIF_NOTIFY_SIGNAL)
#define _TIF_NOHZ (1<<TIF_NOHZ)
diff --git a/arch/loongarch/include/asm/vdso/getrandom.h b/arch/loongarch/include/asm/vdso/getrandom.h
index 02f36772541b..e80f3c4ac748 100644
--- a/arch/loongarch/include/asm/vdso/getrandom.h
+++ b/arch/loongarch/include/asm/vdso/getrandom.h
@@ -30,8 +30,7 @@ static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, uns
static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{
- return (const struct vdso_rng_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START *
- PAGE_SIZE + offsetof(struct loongarch_vdso_data, rng_data));
+ return &_loongarch_data.rng_data;
}
#endif /* !__ASSEMBLY__ */
diff --git a/arch/loongarch/include/asm/vdso/gettimeofday.h b/arch/loongarch/include/asm/vdso/gettimeofday.h
index 89e6b222c2f2..7eb3f041af76 100644
--- a/arch/loongarch/include/asm/vdso/gettimeofday.h
+++ b/arch/loongarch/include/asm/vdso/gettimeofday.h
@@ -91,14 +91,14 @@ static inline bool loongarch_vdso_hres_capable(void)
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{
- return (const struct vdso_data *)get_vdso_data();
+ return _vdso_data;
}
#ifdef CONFIG_TIME_NS
static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{
- return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE);
+ return _timens_data;
}
#endif
#endif /* !__ASSEMBLY__ */
diff --git a/arch/loongarch/include/asm/vdso/vdso.h b/arch/loongarch/include/asm/vdso/vdso.h
index e31ac7474513..1c183a9b2115 100644
--- a/arch/loongarch/include/asm/vdso/vdso.h
+++ b/arch/loongarch/include/asm/vdso/vdso.h
@@ -48,23 +48,7 @@ enum vvar_pages {
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
-static inline unsigned long get_vdso_base(void)
-{
- unsigned long addr;
-
- __asm__(
- " la.pcrel %0, _start\n"
- : "=r" (addr)
- :
- :);
-
- return addr;
-}
-
-static inline unsigned long get_vdso_data(void)
-{
- return get_vdso_base() - VVAR_SIZE;
-}
+extern struct loongarch_vdso_data _loongarch_data __attribute__((visibility("hidden")));
#endif /* __ASSEMBLY__ */
diff --git a/arch/loongarch/include/asm/vdso/vsyscall.h b/arch/loongarch/include/asm/vdso/vsyscall.h
index b1273ce6f140..8987e951d0a9 100644
--- a/arch/loongarch/include/asm/vdso/vsyscall.h
+++ b/arch/loongarch/include/asm/vdso/vsyscall.h
@@ -4,15 +4,11 @@
#ifndef __ASSEMBLY__
-#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
extern struct vdso_data *vdso_data;
extern struct vdso_rng_data *vdso_rng_data;
-/*
- * Update the vDSO data page to keep in sync with kernel timekeeping.
- */
static __always_inline
struct vdso_data *__loongarch_get_k_vdso_data(void)
{
diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index 70d89070bfeb..5f354f5c6847 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -8,6 +8,8 @@
#include <linux/types.h>
+#define __KVM_HAVE_IRQ_LINE
+
/*
* KVM LoongArch specific structures and definitions.
*
@@ -132,4 +134,22 @@ struct kvm_iocsr_entry {
#define KVM_IRQCHIP_NUM_PINS 64
#define KVM_MAX_CORES 256
+#define KVM_DEV_LOONGARCH_IPI_GRP_REGS 0x40000001
+
+#define KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS 0x40000002
+
+#define KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS 0x40000003
+#define KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU 0x0
+#define KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_FEATURE 0x1
+#define KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_STATE 0x2
+
+#define KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL 0x40000004
+#define KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU 0x0
+#define KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE 0x1
+#define KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED 0x3
+
+#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS 0x40000005
+#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL 0x40000006
+#define KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT 0
+
#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index c9bfeda89e40..9497968ee158 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -8,7 +8,7 @@ OBJECT_FILES_NON_STANDARD_head.o := y
extra-y := vmlinux.lds
obj-y += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
- traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \
+ traps.o irq.o idle.o process.o dma.o mem.o reset.o switch.o \
elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o \
alternative.o unwind.o
diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c
index f1a74b80f22c..382a09a7152c 100644
--- a/arch/loongarch/kernel/acpi.c
+++ b/arch/loongarch/kernel/acpi.c
@@ -58,48 +58,48 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
return ioremap_cache(phys, size);
}
-static int cpu_enumerated = 0;
-
#ifdef CONFIG_SMP
-static int set_processor_mask(u32 id, u32 flags)
+static int set_processor_mask(u32 id, u32 pass)
{
- int nr_cpus;
- int cpu, cpuid = id;
-
- if (!cpu_enumerated)
- nr_cpus = NR_CPUS;
- else
- nr_cpus = nr_cpu_ids;
+ int cpu = -1, cpuid = id;
- if (num_processors >= nr_cpus) {
+ if (num_processors >= NR_CPUS) {
pr_warn(PREFIX "nr_cpus limit of %i reached."
- " processor 0x%x ignored.\n", nr_cpus, cpuid);
+ " processor 0x%x ignored.\n", NR_CPUS, cpuid);
return -ENODEV;
}
+
if (cpuid == loongson_sysconf.boot_cpu_id)
cpu = 0;
- else
- cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS);
-
- if (!cpu_enumerated)
- set_cpu_possible(cpu, true);
- if (flags & ACPI_MADT_ENABLED) {
+ switch (pass) {
+ case 1: /* Pass 1 handle enabled processors */
+ if (cpu < 0)
+ cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS);
num_processors++;
set_cpu_present(cpu, true);
- __cpu_number_map[cpuid] = cpu;
- __cpu_logical_map[cpu] = cpuid;
- } else
+ break;
+ case 2: /* Pass 2 handle disabled processors */
+ if (cpu < 0)
+ cpu = find_first_zero_bit(cpumask_bits(cpu_possible_mask), NR_CPUS);
disabled_cpus++;
+ break;
+ default:
+ return cpu;
+ }
+
+ set_cpu_possible(cpu, true);
+ __cpu_number_map[cpuid] = cpu;
+ __cpu_logical_map[cpu] = cpuid;
return cpu;
}
#endif
static int __init
-acpi_parse_processor(union acpi_subtable_headers *header, const unsigned long end)
+acpi_parse_p1_processor(union acpi_subtable_headers *header, const unsigned long end)
{
struct acpi_madt_core_pic *processor = NULL;
@@ -110,13 +110,30 @@ acpi_parse_processor(union acpi_subtable_headers *header, const unsigned long en
acpi_table_print_madt_entry(&header->common);
#ifdef CONFIG_SMP
acpi_core_pic[processor->core_id] = *processor;
- set_processor_mask(processor->core_id, processor->flags);
+ if (processor->flags & ACPI_MADT_ENABLED)
+ set_processor_mask(processor->core_id, 1);
#endif
return 0;
}
static int __init
+acpi_parse_p2_processor(union acpi_subtable_headers *header, const unsigned long end)
+{
+ struct acpi_madt_core_pic *processor = NULL;
+
+ processor = (struct acpi_madt_core_pic *)header;
+ if (BAD_MADT_ENTRY(processor, end))
+ return -EINVAL;
+
+#ifdef CONFIG_SMP
+ if (!(processor->flags & ACPI_MADT_ENABLED))
+ set_processor_mask(processor->core_id, 2);
+#endif
+
+ return 0;
+}
+static int __init
acpi_parse_eio_master(union acpi_subtable_headers *header, const unsigned long end)
{
static int core = 0;
@@ -143,12 +160,14 @@ static void __init acpi_process_madt(void)
}
#endif
acpi_table_parse_madt(ACPI_MADT_TYPE_CORE_PIC,
- acpi_parse_processor, MAX_CORE_PIC);
+ acpi_parse_p1_processor, MAX_CORE_PIC);
+
+ acpi_table_parse_madt(ACPI_MADT_TYPE_CORE_PIC,
+ acpi_parse_p2_processor, MAX_CORE_PIC);
acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC,
acpi_parse_eio_master, MAX_IO_PICS);
- cpu_enumerated = 1;
loongson_sysconf.nr_cpus = num_processors;
}
@@ -310,6 +329,10 @@ static int __ref acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
int nid;
nid = acpi_get_node(handle);
+
+ if (nid != NUMA_NO_NODE)
+ nid = early_cpu_to_node(cpu);
+
if (nid != NUMA_NO_NODE) {
set_cpuid_to_node(physid, nid);
node_set(nid, numa_nodes_parsed);
@@ -324,12 +347,14 @@ int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id, int *pcpu
{
int cpu;
- cpu = set_processor_mask(physid, ACPI_MADT_ENABLED);
- if (cpu < 0) {
+ cpu = cpu_number_map(physid);
+ if (cpu < 0 || cpu >= nr_cpu_ids) {
pr_info(PREFIX "Unable to map lapic to logical cpu number\n");
- return cpu;
+ return -ERANGE;
}
+ num_processors++;
+ set_cpu_present(cpu, true);
acpi_map_cpu2node(handle, cpu, physid);
*pcpu = cpu;
diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c
index bee9f7a3108f..049c5c3e370c 100644
--- a/arch/loongarch/kernel/asm-offsets.c
+++ b/arch/loongarch/kernel/asm-offsets.c
@@ -14,6 +14,7 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/ftrace.h>
+#include <vdso/datapage.h>
static void __used output_ptreg_defines(void)
{
@@ -321,3 +322,11 @@ static void __used output_kvm_defines(void)
OFFSET(KVM_GPGD, kvm, arch.pgd);
BLANK();
}
+
+static void __used output_vdso_defines(void)
+{
+ COMMENT("LoongArch vDSO offsets.");
+
+ DEFINE(__VVAR_PAGES, VVAR_NR_PAGES);
+ BLANK();
+}
diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c
index bff058317062..18056229e22e 100644
--- a/arch/loongarch/kernel/ftrace_dyn.c
+++ b/arch/loongarch/kernel/ftrace_dyn.c
@@ -241,7 +241,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent)
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- struct pt_regs *regs = &fregs->regs;
+ struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
unsigned long *parent = (unsigned long *)&regs->regs[1];
prepare_ftrace_return(ip, (unsigned long *)parent);
diff --git a/arch/loongarch/kernel/io.c b/arch/loongarch/kernel/io.c
deleted file mode 100644
index cb85bda5a6ad..000000000000
--- a/arch/loongarch/kernel/io.c
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
- */
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/io.h>
-
-/*
- * Copy data from IO memory space to "real" memory space.
- */
-void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
-{
- while (count && !IS_ALIGNED((unsigned long)from, 8)) {
- *(u8 *)to = __raw_readb(from);
- from++;
- to++;
- count--;
- }
-
- while (count >= 8) {
- *(u64 *)to = __raw_readq(from);
- from += 8;
- to += 8;
- count -= 8;
- }
-
- while (count) {
- *(u8 *)to = __raw_readb(from);
- from++;
- to++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memcpy_fromio);
-
-/*
- * Copy data from "real" memory space to IO memory space.
- */
-void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
-{
- while (count && !IS_ALIGNED((unsigned long)to, 8)) {
- __raw_writeb(*(u8 *)from, to);
- from++;
- to++;
- count--;
- }
-
- while (count >= 8) {
- __raw_writeq(*(u64 *)from, to);
- from += 8;
- to += 8;
- count -= 8;
- }
-
- while (count) {
- __raw_writeb(*(u8 *)from, to);
- from++;
- to++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memcpy_toio);
-
-/*
- * "memset" on IO memory space.
- */
-void __memset_io(volatile void __iomem *dst, int c, size_t count)
-{
- u64 qc = (u8)c;
-
- qc |= qc << 8;
- qc |= qc << 16;
- qc |= qc << 32;
-
- while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
- __raw_writeb(c, dst);
- dst++;
- count--;
- }
-
- while (count >= 8) {
- __raw_writeq(qc, dst);
- dst += 8;
- count -= 8;
- }
-
- while (count) {
- __raw_writeb(c, dst);
- dst++;
- count--;
- }
-}
-EXPORT_SYMBOL(__memset_io);
diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c
index d129039b368b..80946cafaec1 100644
--- a/arch/loongarch/kernel/irq.c
+++ b/arch/loongarch/kernel/irq.c
@@ -92,9 +92,9 @@ int __init arch_probe_nr_irqs(void)
int nr_io_pics = bitmap_weight(loongson_sysconf.cores_io_master, NR_CPUS);
if (!cpu_has_avecint)
- nr_irqs = (64 + NR_VECTORS * nr_io_pics);
+ irq_set_nr_irqs(64 + NR_VECTORS * nr_io_pics);
else
- nr_irqs = (64 + NR_VECTORS * (nr_cpu_ids + nr_io_pics));
+ irq_set_nr_irqs(64 + NR_VECTORS * (nr_cpu_ids + nr_io_pics));
return NR_IRQS_LEGACY;
}
diff --git a/arch/loongarch/kernel/paravirt.c b/arch/loongarch/kernel/paravirt.c
index a5fc61f8b348..e5a39bbad078 100644
--- a/arch/loongarch/kernel/paravirt.c
+++ b/arch/loongarch/kernel/paravirt.c
@@ -51,11 +51,18 @@ static u64 paravt_steal_clock(int cpu)
}
#ifdef CONFIG_SMP
+static struct smp_ops native_ops;
+
static void pv_send_ipi_single(int cpu, unsigned int action)
{
int min, old;
irq_cpustat_t *info = &per_cpu(irq_stat, cpu);
+ if (unlikely(action == ACTION_BOOT_CPU)) {
+ native_ops.send_ipi_single(cpu, action);
+ return;
+ }
+
old = atomic_fetch_or(BIT(action), &info->message);
if (old)
return;
@@ -75,6 +82,11 @@ static void pv_send_ipi_mask(const struct cpumask *mask, unsigned int action)
if (cpumask_empty(mask))
return;
+ if (unlikely(action == ACTION_BOOT_CPU)) {
+ native_ops.send_ipi_mask(mask, action);
+ return;
+ }
+
action = BIT(action);
for_each_cpu(i, mask) {
info = &per_cpu(irq_stat, i);
@@ -147,6 +159,8 @@ static void pv_init_ipi(void)
{
int r, swi;
+ /* Init native ipi irq for ACTION_BOOT_CPU */
+ native_ops.init_ipi();
swi = get_percpu_irq(INT_SWI0);
if (swi < 0)
panic("SWI0 IRQ mapping failed\n");
@@ -193,6 +207,7 @@ int __init pv_ipi_init(void)
return 0;
#ifdef CONFIG_SMP
+ native_ops = mp_ops;
mp_ops.init_ipi = pv_init_ipi;
mp_ops.send_ipi_single = pv_send_ipi_single;
mp_ops.send_ipi_mask = pv_send_ipi_mask;
diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
index cbd3c09a93c1..56934fe58170 100644
--- a/arch/loongarch/kernel/setup.c
+++ b/arch/loongarch/kernel/setup.c
@@ -291,7 +291,7 @@ static void __init fdt_setup(void)
if (!fdt_pointer || fdt_check_header(fdt_pointer))
return;
- early_init_dt_scan(fdt_pointer);
+ early_init_dt_scan(fdt_pointer, __pa(fdt_pointer));
early_init_fdt_reserve_self();
max_low_pfn = PFN_PHYS(memblock_end_of_DRAM());
diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c
index 9afc2d8b3414..5d59e9ce2772 100644
--- a/arch/loongarch/kernel/smp.c
+++ b/arch/loongarch/kernel/smp.c
@@ -302,7 +302,7 @@ static void __init fdt_smp_setup(void)
__cpu_number_map[cpuid] = cpu;
__cpu_logical_map[cpu] = cpuid;
- early_numa_add_cpu(cpu, 0);
+ early_numa_add_cpu(cpuid, 0);
set_cpuid_to_node(cpuid, 0);
}
@@ -331,11 +331,11 @@ void __init loongson_prepare_cpus(unsigned int max_cpus)
int i = 0;
parse_acpi_topology();
+ cpu_data[0].global_id = cpu_logical_map(0);
for (i = 0; i < loongson_sysconf.nr_cpus; i++) {
set_cpu_present(i, true);
csr_mail_send(0, __cpu_logical_map[i], 0);
- cpu_data[i].global_id = __cpu_logical_map[i];
}
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
@@ -380,6 +380,7 @@ void loongson_init_secondary(void)
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core :
cpu_logical_map(cpu) % loongson_sysconf.cores_per_package;
+ cpu_data[cpu].global_id = cpu_logical_map(cpu);
}
void loongson_smp_finish(void)
diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c
index 46d7d40c87e3..a07d7eff4dc5 100644
--- a/arch/loongarch/kernel/time.c
+++ b/arch/loongarch/kernel/time.c
@@ -127,7 +127,11 @@ void sync_counter(void)
int constant_clockevent_init(void)
{
unsigned int cpu = smp_processor_id();
- unsigned long min_delta = 0x600;
+#ifdef CONFIG_PREEMPT_RT
+ unsigned long min_delta = 100;
+#else
+ unsigned long min_delta = 1000;
+#endif
unsigned long max_delta = (1UL << 48) - 1;
struct clock_event_device *cd;
static int irq = 0, timer_irq_installed = 0;
diff --git a/arch/loongarch/kernel/vdso.c b/arch/loongarch/kernel/vdso.c
index 2c0d852ca536..05e5fbac102a 100644
--- a/arch/loongarch/kernel/vdso.c
+++ b/arch/loongarch/kernel/vdso.c
@@ -15,7 +15,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/time_namespace.h>
-#include <linux/timekeeper_internal.h>
#include <asm/page.h>
#include <asm/vdso.h>
diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig
index 248744b4d086..97a811077ac3 100644
--- a/arch/loongarch/kvm/Kconfig
+++ b/arch/loongarch/kvm/Kconfig
@@ -21,13 +21,16 @@ config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
depends on AS_HAS_LVZ_EXTENSION
select HAVE_KVM_DIRTY_RING_ACQ_REL
+ select HAVE_KVM_IRQ_ROUTING
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_MSI
+ select HAVE_KVM_READONLY_MEM
select HAVE_KVM_VCPU_ASYNC_IOCTL
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
select KVM_GENERIC_MMU_NOTIFIER
select KVM_MMIO
- select HAVE_KVM_READONLY_MEM
select KVM_XFER_TO_GUEST_WORK
select SCHED_INFO
help
diff --git a/arch/loongarch/kvm/Makefile b/arch/loongarch/kvm/Makefile
index b2f4cbe01ae8..3a01292f71cc 100644
--- a/arch/loongarch/kvm/Makefile
+++ b/arch/loongarch/kvm/Makefile
@@ -18,5 +18,9 @@ kvm-y += timer.o
kvm-y += tlb.o
kvm-y += vcpu.o
kvm-y += vm.o
+kvm-y += intc/ipi.o
+kvm-y += intc/eiointc.o
+kvm-y += intc/pch_pic.o
+kvm-y += irqfd.o
CFLAGS_exit.o += $(call cc-option,-Wno-override-init,)
diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
index 90894f70ff4a..69f3e3782cc9 100644
--- a/arch/loongarch/kvm/exit.c
+++ b/arch/loongarch/kvm/exit.c
@@ -157,7 +157,7 @@ static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst)
int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
{
int ret;
- unsigned long val;
+ unsigned long *val;
u32 addr, rd, rj, opcode;
/*
@@ -170,6 +170,7 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
ret = EMULATE_DO_IOCSR;
run->iocsr_io.phys_addr = addr;
run->iocsr_io.is_write = 0;
+ val = &vcpu->arch.gprs[rd];
/* LoongArch is Little endian */
switch (opcode) {
@@ -202,16 +203,25 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
run->iocsr_io.is_write = 1;
break;
default:
- ret = EMULATE_FAIL;
- break;
+ return EMULATE_FAIL;
}
- if (ret == EMULATE_DO_IOCSR) {
- if (run->iocsr_io.is_write) {
- val = vcpu->arch.gprs[rd];
- memcpy(run->iocsr_io.data, &val, run->iocsr_io.len);
- }
- vcpu->arch.io_gpr = rd;
+ if (run->iocsr_io.is_write) {
+ if (!kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
+ ret = EMULATE_DONE;
+ else
+ /* Save data and let user space to write it */
+ memcpy(run->iocsr_io.data, val, run->iocsr_io.len);
+
+ trace_kvm_iocsr(KVM_TRACE_IOCSR_WRITE, run->iocsr_io.len, addr, val);
+ } else {
+ if (!kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
+ ret = EMULATE_DONE;
+ else
+ /* Save register id for iocsr read completion */
+ vcpu->arch.io_gpr = rd;
+
+ trace_kvm_iocsr(KVM_TRACE_IOCSR_READ, run->iocsr_io.len, addr, NULL);
}
return ret;
@@ -447,19 +457,33 @@ int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
}
if (ret == EMULATE_DO_MMIO) {
+ trace_kvm_mmio(KVM_TRACE_MMIO_READ, run->mmio.len, run->mmio.phys_addr, NULL);
+
+ /*
+ * If mmio device such as PCH-PIC is emulated in KVM,
+ * it need not return to user space to handle the mmio
+ * exception.
+ */
+ ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, vcpu->arch.badv,
+ run->mmio.len, &vcpu->arch.gprs[rd]);
+ if (!ret) {
+ update_pc(&vcpu->arch);
+ vcpu->mmio_needed = 0;
+ return EMULATE_DONE;
+ }
+
/* Set for kvm_complete_mmio_read() use */
vcpu->arch.io_gpr = rd;
run->mmio.is_write = 0;
vcpu->mmio_is_write = 0;
- trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, run->mmio.len,
- run->mmio.phys_addr, NULL);
- } else {
- kvm_err("Read not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
- inst.word, vcpu->arch.pc, vcpu->arch.badv);
- kvm_arch_vcpu_dump_regs(vcpu);
- vcpu->mmio_needed = 0;
+ return EMULATE_DO_MMIO;
}
+ kvm_err("Read not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
+ inst.word, vcpu->arch.pc, vcpu->arch.badv);
+ kvm_arch_vcpu_dump_regs(vcpu);
+ vcpu->mmio_needed = 0;
+
return ret;
}
@@ -600,19 +624,29 @@ int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
}
if (ret == EMULATE_DO_MMIO) {
+ trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, run->mmio.len, run->mmio.phys_addr, data);
+
+ /*
+ * If mmio device such as PCH-PIC is emulated in KVM,
+ * it need not return to user space to handle the mmio
+ * exception.
+ */
+ ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, vcpu->arch.badv, run->mmio.len, data);
+ if (!ret)
+ return EMULATE_DONE;
+
run->mmio.is_write = 1;
vcpu->mmio_needed = 1;
vcpu->mmio_is_write = 1;
- trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, run->mmio.len,
- run->mmio.phys_addr, data);
- } else {
- vcpu->arch.pc = curr_pc;
- kvm_err("Write not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
- inst.word, vcpu->arch.pc, vcpu->arch.badv);
- kvm_arch_vcpu_dump_regs(vcpu);
- /* Rollback PC if emulation was unsuccessful */
+ return EMULATE_DO_MMIO;
}
+ vcpu->arch.pc = curr_pc;
+ kvm_err("Write not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
+ inst.word, vcpu->arch.pc, vcpu->arch.badv);
+ kvm_arch_vcpu_dump_regs(vcpu);
+ /* Rollback PC if emulation was unsuccessful */
+
return ret;
}
diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c
new file mode 100644
index 000000000000..f39929d7bf8a
--- /dev/null
+++ b/arch/loongarch/kvm/intc/eiointc.c
@@ -0,0 +1,1027 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#include <asm/kvm_eiointc.h>
+#include <asm/kvm_vcpu.h>
+#include <linux/count_zeros.h>
+
+static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s)
+{
+ int ipnum, cpu, irq_index, irq_mask, irq;
+
+ for (irq = 0; irq < EIOINTC_IRQS; irq++) {
+ ipnum = s->ipmap.reg_u8[irq / 32];
+ if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
+ ipnum = count_trailing_zeros(ipnum);
+ ipnum = (ipnum >= 0 && ipnum < 4) ? ipnum : 0;
+ }
+ irq_index = irq / 32;
+ irq_mask = BIT(irq & 0x1f);
+
+ cpu = s->coremap.reg_u8[irq];
+ if (!!(s->coreisr.reg_u32[cpu][irq_index] & irq_mask))
+ set_bit(irq, s->sw_coreisr[cpu][ipnum]);
+ else
+ clear_bit(irq, s->sw_coreisr[cpu][ipnum]);
+ }
+}
+
+static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
+{
+ int ipnum, cpu, found, irq_index, irq_mask;
+ struct kvm_vcpu *vcpu;
+ struct kvm_interrupt vcpu_irq;
+
+ ipnum = s->ipmap.reg_u8[irq / 32];
+ if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
+ ipnum = count_trailing_zeros(ipnum);
+ ipnum = (ipnum >= 0 && ipnum < 4) ? ipnum : 0;
+ }
+
+ cpu = s->sw_coremap[irq];
+ vcpu = kvm_get_vcpu(s->kvm, cpu);
+ irq_index = irq / 32;
+ irq_mask = BIT(irq & 0x1f);
+
+ if (level) {
+ /* if not enable return false */
+ if (((s->enable.reg_u32[irq_index]) & irq_mask) == 0)
+ return;
+ s->coreisr.reg_u32[cpu][irq_index] |= irq_mask;
+ found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS);
+ set_bit(irq, s->sw_coreisr[cpu][ipnum]);
+ } else {
+ s->coreisr.reg_u32[cpu][irq_index] &= ~irq_mask;
+ clear_bit(irq, s->sw_coreisr[cpu][ipnum]);
+ found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS);
+ }
+
+ if (found < EIOINTC_IRQS)
+ return; /* other irq is handling, needn't update parent irq */
+
+ vcpu_irq.irq = level ? (INT_HWI0 + ipnum) : -(INT_HWI0 + ipnum);
+ kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq);
+}
+
+static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s,
+ int irq, void *pvalue, u32 len, bool notify)
+{
+ int i, cpu;
+ u64 val = *(u64 *)pvalue;
+
+ for (i = 0; i < len; i++) {
+ cpu = val & 0xff;
+ val = val >> 8;
+
+ if (!(s->status & BIT(EIOINTC_ENABLE_CPU_ENCODE))) {
+ cpu = ffs(cpu) - 1;
+ cpu = (cpu >= 4) ? 0 : cpu;
+ }
+
+ if (s->sw_coremap[irq + i] == cpu)
+ continue;
+
+ if (notify && test_bit(irq + i, (unsigned long *)s->isr.reg_u8)) {
+ /* lower irq at old cpu and raise irq at new cpu */
+ eiointc_update_irq(s, irq + i, 0);
+ s->sw_coremap[irq + i] = cpu;
+ eiointc_update_irq(s, irq + i, 1);
+ } else {
+ s->sw_coremap[irq + i] = cpu;
+ }
+ }
+}
+
+void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level)
+{
+ unsigned long flags;
+ unsigned long *isr = (unsigned long *)s->isr.reg_u8;
+
+ level ? set_bit(irq, isr) : clear_bit(irq, isr);
+ spin_lock_irqsave(&s->lock, flags);
+ eiointc_update_irq(s, irq, level);
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static inline void eiointc_enable_irq(struct kvm_vcpu *vcpu,
+ struct loongarch_eiointc *s, int index, u8 mask, int level)
+{
+ u8 val;
+ int irq;
+
+ val = mask & s->isr.reg_u8[index];
+ irq = ffs(val);
+ while (irq != 0) {
+ /*
+ * enable bit change from 0 to 1,
+ * need to update irq by pending bits
+ */
+ eiointc_update_irq(s, irq - 1 + index * 8, level);
+ val &= ~BIT(irq - 1);
+ irq = ffs(val);
+ }
+}
+
+static int loongarch_eiointc_readb(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s,
+ gpa_t addr, int len, void *val)
+{
+ int index, ret = 0;
+ u8 data = 0;
+ gpa_t offset;
+
+ offset = addr - EIOINTC_BASE;
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = offset - EIOINTC_NODETYPE_START;
+ data = s->nodetype.reg_u8[index];
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ index = offset - EIOINTC_IPMAP_START;
+ data = s->ipmap.reg_u8[index];
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = offset - EIOINTC_ENABLE_START;
+ data = s->enable.reg_u8[index];
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ index = offset - EIOINTC_BOUNCE_START;
+ data = s->bounce.reg_u8[index];
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = offset - EIOINTC_COREISR_START;
+ data = s->coreisr.reg_u8[vcpu->vcpu_id][index];
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ index = offset - EIOINTC_COREMAP_START;
+ data = s->coremap.reg_u8[index];
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *(u8 *)val = data;
+
+ return ret;
+}
+
+static int loongarch_eiointc_readw(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s,
+ gpa_t addr, int len, void *val)
+{
+ int index, ret = 0;
+ u16 data = 0;
+ gpa_t offset;
+
+ offset = addr - EIOINTC_BASE;
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = (offset - EIOINTC_NODETYPE_START) >> 1;
+ data = s->nodetype.reg_u16[index];
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ index = (offset - EIOINTC_IPMAP_START) >> 1;
+ data = s->ipmap.reg_u16[index];
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = (offset - EIOINTC_ENABLE_START) >> 1;
+ data = s->enable.reg_u16[index];
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ index = (offset - EIOINTC_BOUNCE_START) >> 1;
+ data = s->bounce.reg_u16[index];
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = (offset - EIOINTC_COREISR_START) >> 1;
+ data = s->coreisr.reg_u16[vcpu->vcpu_id][index];
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ index = (offset - EIOINTC_COREMAP_START) >> 1;
+ data = s->coremap.reg_u16[index];
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *(u16 *)val = data;
+
+ return ret;
+}
+
+static int loongarch_eiointc_readl(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s,
+ gpa_t addr, int len, void *val)
+{
+ int index, ret = 0;
+ u32 data = 0;
+ gpa_t offset;
+
+ offset = addr - EIOINTC_BASE;
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = (offset - EIOINTC_NODETYPE_START) >> 2;
+ data = s->nodetype.reg_u32[index];
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ index = (offset - EIOINTC_IPMAP_START) >> 2;
+ data = s->ipmap.reg_u32[index];
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = (offset - EIOINTC_ENABLE_START) >> 2;
+ data = s->enable.reg_u32[index];
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ index = (offset - EIOINTC_BOUNCE_START) >> 2;
+ data = s->bounce.reg_u32[index];
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = (offset - EIOINTC_COREISR_START) >> 2;
+ data = s->coreisr.reg_u32[vcpu->vcpu_id][index];
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ index = (offset - EIOINTC_COREMAP_START) >> 2;
+ data = s->coremap.reg_u32[index];
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *(u32 *)val = data;
+
+ return ret;
+}
+
+static int loongarch_eiointc_readq(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s,
+ gpa_t addr, int len, void *val)
+{
+ int index, ret = 0;
+ u64 data = 0;
+ gpa_t offset;
+
+ offset = addr - EIOINTC_BASE;
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = (offset - EIOINTC_NODETYPE_START) >> 3;
+ data = s->nodetype.reg_u64[index];
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ index = (offset - EIOINTC_IPMAP_START) >> 3;
+ data = s->ipmap.reg_u64;
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = (offset - EIOINTC_ENABLE_START) >> 3;
+ data = s->enable.reg_u64[index];
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ index = (offset - EIOINTC_BOUNCE_START) >> 3;
+ data = s->bounce.reg_u64[index];
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = (offset - EIOINTC_COREISR_START) >> 3;
+ data = s->coreisr.reg_u64[vcpu->vcpu_id][index];
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ index = (offset - EIOINTC_COREMAP_START) >> 3;
+ data = s->coremap.reg_u64[index];
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ *(u64 *)val = data;
+
+ return ret;
+}
+
+static int kvm_eiointc_read(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, void *val)
+{
+ int ret = -EINVAL;
+ unsigned long flags;
+ struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
+
+ if (!eiointc) {
+ kvm_err("%s: eiointc irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+
+ vcpu->kvm->stat.eiointc_read_exits++;
+ spin_lock_irqsave(&eiointc->lock, flags);
+ switch (len) {
+ case 1:
+ ret = loongarch_eiointc_readb(vcpu, eiointc, addr, len, val);
+ break;
+ case 2:
+ ret = loongarch_eiointc_readw(vcpu, eiointc, addr, len, val);
+ break;
+ case 4:
+ ret = loongarch_eiointc_readl(vcpu, eiointc, addr, len, val);
+ break;
+ case 8:
+ ret = loongarch_eiointc_readq(vcpu, eiointc, addr, len, val);
+ break;
+ default:
+ WARN_ONCE(1, "%s: Abnormal address access: addr 0x%llx, size %d\n",
+ __func__, addr, len);
+ }
+ spin_unlock_irqrestore(&eiointc->lock, flags);
+
+ return ret;
+}
+
+static int loongarch_eiointc_writeb(struct kvm_vcpu *vcpu,
+ struct loongarch_eiointc *s,
+ gpa_t addr, int len, const void *val)
+{
+ int index, irq, bits, ret = 0;
+ u8 cpu;
+ u8 data, old_data;
+ u8 coreisr, old_coreisr;
+ gpa_t offset;
+
+ data = *(u8 *)val;
+ offset = addr - EIOINTC_BASE;
+
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = (offset - EIOINTC_NODETYPE_START);
+ s->nodetype.reg_u8[index] = data;
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ /*
+ * ipmap cannot be set at runtime, can be set only at the beginning
+ * of irqchip driver, need not update upper irq level
+ */
+ index = (offset - EIOINTC_IPMAP_START);
+ s->ipmap.reg_u8[index] = data;
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = (offset - EIOINTC_ENABLE_START);
+ old_data = s->enable.reg_u8[index];
+ s->enable.reg_u8[index] = data;
+ /*
+ * 1: enable irq.
+ * update irq when isr is set.
+ */
+ data = s->enable.reg_u8[index] & ~old_data & s->isr.reg_u8[index];
+ eiointc_enable_irq(vcpu, s, index, data, 1);
+ /*
+ * 0: disable irq.
+ * update irq when isr is set.
+ */
+ data = ~s->enable.reg_u8[index] & old_data & s->isr.reg_u8[index];
+ eiointc_enable_irq(vcpu, s, index, data, 0);
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ /* do not emulate hw bounced irq routing */
+ index = offset - EIOINTC_BOUNCE_START;
+ s->bounce.reg_u8[index] = data;
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = (offset - EIOINTC_COREISR_START);
+ /* use attrs to get current cpu index */
+ cpu = vcpu->vcpu_id;
+ coreisr = data;
+ old_coreisr = s->coreisr.reg_u8[cpu][index];
+ /* write 1 to clear interrupt */
+ s->coreisr.reg_u8[cpu][index] = old_coreisr & ~coreisr;
+ coreisr &= old_coreisr;
+ bits = sizeof(data) * 8;
+ irq = find_first_bit((void *)&coreisr, bits);
+ while (irq < bits) {
+ eiointc_update_irq(s, irq + index * bits, 0);
+ bitmap_clear((void *)&coreisr, irq, 1);
+ irq = find_first_bit((void *)&coreisr, bits);
+ }
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ irq = offset - EIOINTC_COREMAP_START;
+ index = irq;
+ s->coremap.reg_u8[index] = data;
+ eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int loongarch_eiointc_writew(struct kvm_vcpu *vcpu,
+ struct loongarch_eiointc *s,
+ gpa_t addr, int len, const void *val)
+{
+ int i, index, irq, bits, ret = 0;
+ u8 cpu;
+ u16 data, old_data;
+ u16 coreisr, old_coreisr;
+ gpa_t offset;
+
+ data = *(u16 *)val;
+ offset = addr - EIOINTC_BASE;
+
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = (offset - EIOINTC_NODETYPE_START) >> 1;
+ s->nodetype.reg_u16[index] = data;
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ /*
+ * ipmap cannot be set at runtime, can be set only at the beginning
+ * of irqchip driver, need not update upper irq level
+ */
+ index = (offset - EIOINTC_IPMAP_START) >> 1;
+ s->ipmap.reg_u16[index] = data;
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = (offset - EIOINTC_ENABLE_START) >> 1;
+ old_data = s->enable.reg_u32[index];
+ s->enable.reg_u16[index] = data;
+ /*
+ * 1: enable irq.
+ * update irq when isr is set.
+ */
+ data = s->enable.reg_u16[index] & ~old_data & s->isr.reg_u16[index];
+ index = index << 1;
+ for (i = 0; i < sizeof(data); i++) {
+ u8 mask = (data >> (i * 8)) & 0xff;
+ eiointc_enable_irq(vcpu, s, index + i, mask, 1);
+ }
+ /*
+ * 0: disable irq.
+ * update irq when isr is set.
+ */
+ data = ~s->enable.reg_u16[index] & old_data & s->isr.reg_u16[index];
+ for (i = 0; i < sizeof(data); i++) {
+ u8 mask = (data >> (i * 8)) & 0xff;
+ eiointc_enable_irq(vcpu, s, index, mask, 0);
+ }
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ /* do not emulate hw bounced irq routing */
+ index = (offset - EIOINTC_BOUNCE_START) >> 1;
+ s->bounce.reg_u16[index] = data;
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = (offset - EIOINTC_COREISR_START) >> 1;
+ /* use attrs to get current cpu index */
+ cpu = vcpu->vcpu_id;
+ coreisr = data;
+ old_coreisr = s->coreisr.reg_u16[cpu][index];
+ /* write 1 to clear interrupt */
+ s->coreisr.reg_u16[cpu][index] = old_coreisr & ~coreisr;
+ coreisr &= old_coreisr;
+ bits = sizeof(data) * 8;
+ irq = find_first_bit((void *)&coreisr, bits);
+ while (irq < bits) {
+ eiointc_update_irq(s, irq + index * bits, 0);
+ bitmap_clear((void *)&coreisr, irq, 1);
+ irq = find_first_bit((void *)&coreisr, bits);
+ }
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ irq = offset - EIOINTC_COREMAP_START;
+ index = irq >> 1;
+ s->coremap.reg_u16[index] = data;
+ eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int loongarch_eiointc_writel(struct kvm_vcpu *vcpu,
+ struct loongarch_eiointc *s,
+ gpa_t addr, int len, const void *val)
+{
+ int i, index, irq, bits, ret = 0;
+ u8 cpu;
+ u32 data, old_data;
+ u32 coreisr, old_coreisr;
+ gpa_t offset;
+
+ data = *(u32 *)val;
+ offset = addr - EIOINTC_BASE;
+
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = (offset - EIOINTC_NODETYPE_START) >> 2;
+ s->nodetype.reg_u32[index] = data;
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ /*
+ * ipmap cannot be set at runtime, can be set only at the beginning
+ * of irqchip driver, need not update upper irq level
+ */
+ index = (offset - EIOINTC_IPMAP_START) >> 2;
+ s->ipmap.reg_u32[index] = data;
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = (offset - EIOINTC_ENABLE_START) >> 2;
+ old_data = s->enable.reg_u32[index];
+ s->enable.reg_u32[index] = data;
+ /*
+ * 1: enable irq.
+ * update irq when isr is set.
+ */
+ data = s->enable.reg_u32[index] & ~old_data & s->isr.reg_u32[index];
+ index = index << 2;
+ for (i = 0; i < sizeof(data); i++) {
+ u8 mask = (data >> (i * 8)) & 0xff;
+ eiointc_enable_irq(vcpu, s, index + i, mask, 1);
+ }
+ /*
+ * 0: disable irq.
+ * update irq when isr is set.
+ */
+ data = ~s->enable.reg_u32[index] & old_data & s->isr.reg_u32[index];
+ for (i = 0; i < sizeof(data); i++) {
+ u8 mask = (data >> (i * 8)) & 0xff;
+ eiointc_enable_irq(vcpu, s, index, mask, 0);
+ }
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ /* do not emulate hw bounced irq routing */
+ index = (offset - EIOINTC_BOUNCE_START) >> 2;
+ s->bounce.reg_u32[index] = data;
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = (offset - EIOINTC_COREISR_START) >> 2;
+ /* use attrs to get current cpu index */
+ cpu = vcpu->vcpu_id;
+ coreisr = data;
+ old_coreisr = s->coreisr.reg_u32[cpu][index];
+ /* write 1 to clear interrupt */
+ s->coreisr.reg_u32[cpu][index] = old_coreisr & ~coreisr;
+ coreisr &= old_coreisr;
+ bits = sizeof(data) * 8;
+ irq = find_first_bit((void *)&coreisr, bits);
+ while (irq < bits) {
+ eiointc_update_irq(s, irq + index * bits, 0);
+ bitmap_clear((void *)&coreisr, irq, 1);
+ irq = find_first_bit((void *)&coreisr, bits);
+ }
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ irq = offset - EIOINTC_COREMAP_START;
+ index = irq >> 2;
+ s->coremap.reg_u32[index] = data;
+ eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
+ struct loongarch_eiointc *s,
+ gpa_t addr, int len, const void *val)
+{
+ int i, index, irq, bits, ret = 0;
+ u8 cpu;
+ u64 data, old_data;
+ u64 coreisr, old_coreisr;
+ gpa_t offset;
+
+ data = *(u64 *)val;
+ offset = addr - EIOINTC_BASE;
+
+ switch (offset) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ index = (offset - EIOINTC_NODETYPE_START) >> 3;
+ s->nodetype.reg_u64[index] = data;
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ /*
+ * ipmap cannot be set at runtime, can be set only at the beginning
+ * of irqchip driver, need not update upper irq level
+ */
+ index = (offset - EIOINTC_IPMAP_START) >> 3;
+ s->ipmap.reg_u64 = data;
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ index = (offset - EIOINTC_ENABLE_START) >> 3;
+ old_data = s->enable.reg_u64[index];
+ s->enable.reg_u64[index] = data;
+ /*
+ * 1: enable irq.
+ * update irq when isr is set.
+ */
+ data = s->enable.reg_u64[index] & ~old_data & s->isr.reg_u64[index];
+ index = index << 3;
+ for (i = 0; i < sizeof(data); i++) {
+ u8 mask = (data >> (i * 8)) & 0xff;
+ eiointc_enable_irq(vcpu, s, index + i, mask, 1);
+ }
+ /*
+ * 0: disable irq.
+ * update irq when isr is set.
+ */
+ data = ~s->enable.reg_u64[index] & old_data & s->isr.reg_u64[index];
+ for (i = 0; i < sizeof(data); i++) {
+ u8 mask = (data >> (i * 8)) & 0xff;
+ eiointc_enable_irq(vcpu, s, index, mask, 0);
+ }
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ /* do not emulate hw bounced irq routing */
+ index = (offset - EIOINTC_BOUNCE_START) >> 3;
+ s->bounce.reg_u64[index] = data;
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ index = (offset - EIOINTC_COREISR_START) >> 3;
+ /* use attrs to get current cpu index */
+ cpu = vcpu->vcpu_id;
+ coreisr = data;
+ old_coreisr = s->coreisr.reg_u64[cpu][index];
+ /* write 1 to clear interrupt */
+ s->coreisr.reg_u64[cpu][index] = old_coreisr & ~coreisr;
+ coreisr &= old_coreisr;
+ bits = sizeof(data) * 8;
+ irq = find_first_bit((void *)&coreisr, bits);
+ while (irq < bits) {
+ eiointc_update_irq(s, irq + index * bits, 0);
+ bitmap_clear((void *)&coreisr, irq, 1);
+ irq = find_first_bit((void *)&coreisr, bits);
+ }
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ irq = offset - EIOINTC_COREMAP_START;
+ index = irq >> 3;
+ s->coremap.reg_u64[index] = data;
+ eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int kvm_eiointc_write(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, const void *val)
+{
+ int ret = -EINVAL;
+ unsigned long flags;
+ struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
+
+ if (!eiointc) {
+ kvm_err("%s: eiointc irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+
+ vcpu->kvm->stat.eiointc_write_exits++;
+ spin_lock_irqsave(&eiointc->lock, flags);
+ switch (len) {
+ case 1:
+ ret = loongarch_eiointc_writeb(vcpu, eiointc, addr, len, val);
+ break;
+ case 2:
+ ret = loongarch_eiointc_writew(vcpu, eiointc, addr, len, val);
+ break;
+ case 4:
+ ret = loongarch_eiointc_writel(vcpu, eiointc, addr, len, val);
+ break;
+ case 8:
+ ret = loongarch_eiointc_writeq(vcpu, eiointc, addr, len, val);
+ break;
+ default:
+ WARN_ONCE(1, "%s: Abnormal address access: addr 0x%llx, size %d\n",
+ __func__, addr, len);
+ }
+ spin_unlock_irqrestore(&eiointc->lock, flags);
+
+ return ret;
+}
+
+static const struct kvm_io_device_ops kvm_eiointc_ops = {
+ .read = kvm_eiointc_read,
+ .write = kvm_eiointc_write,
+};
+
+static int kvm_eiointc_virt_read(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, void *val)
+{
+ unsigned long flags;
+ u32 *data = val;
+ struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
+
+ if (!eiointc) {
+ kvm_err("%s: eiointc irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+
+ addr -= EIOINTC_VIRT_BASE;
+ spin_lock_irqsave(&eiointc->lock, flags);
+ switch (addr) {
+ case EIOINTC_VIRT_FEATURES:
+ *data = eiointc->features;
+ break;
+ case EIOINTC_VIRT_CONFIG:
+ *data = eiointc->status;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&eiointc->lock, flags);
+
+ return 0;
+}
+
+static int kvm_eiointc_virt_write(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, const void *val)
+{
+ int ret = 0;
+ unsigned long flags;
+ u32 value = *(u32 *)val;
+ struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
+
+ if (!eiointc) {
+ kvm_err("%s: eiointc irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+
+ addr -= EIOINTC_VIRT_BASE;
+ spin_lock_irqsave(&eiointc->lock, flags);
+ switch (addr) {
+ case EIOINTC_VIRT_FEATURES:
+ ret = -EPERM;
+ break;
+ case EIOINTC_VIRT_CONFIG:
+ /*
+ * eiointc features can only be set at disabled status
+ */
+ if ((eiointc->status & BIT(EIOINTC_ENABLE)) && value) {
+ ret = -EPERM;
+ break;
+ }
+ eiointc->status = value & eiointc->features;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&eiointc->lock, flags);
+
+ return ret;
+}
+
+static const struct kvm_io_device_ops kvm_eiointc_virt_ops = {
+ .read = kvm_eiointc_virt_read,
+ .write = kvm_eiointc_virt_write,
+};
+
+static int kvm_eiointc_ctrl_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ int ret = 0;
+ unsigned long flags;
+ unsigned long type = (unsigned long)attr->attr;
+ u32 i, start_irq;
+ void __user *data;
+ struct loongarch_eiointc *s = dev->kvm->arch.eiointc;
+
+ data = (void __user *)attr->addr;
+ spin_lock_irqsave(&s->lock, flags);
+ switch (type) {
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU:
+ if (copy_from_user(&s->num_cpu, data, 4))
+ ret = -EFAULT;
+ break;
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE:
+ if (copy_from_user(&s->features, data, 4))
+ ret = -EFAULT;
+ if (!(s->features & BIT(EIOINTC_HAS_VIRT_EXTENSION)))
+ s->status |= BIT(EIOINTC_ENABLE);
+ break;
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED:
+ eiointc_set_sw_coreisr(s);
+ for (i = 0; i < (EIOINTC_IRQS / 4); i++) {
+ start_irq = i * 4;
+ eiointc_update_sw_coremap(s, start_irq,
+ (void *)&s->coremap.reg_u32[i], sizeof(u32), false);
+ }
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return ret;
+}
+
+static int kvm_eiointc_regs_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ bool is_write)
+{
+ int addr, cpuid, offset, ret = 0;
+ unsigned long flags;
+ void *p = NULL;
+ void __user *data;
+ struct loongarch_eiointc *s;
+
+ s = dev->kvm->arch.eiointc;
+ addr = attr->attr;
+ cpuid = addr >> 16;
+ addr &= 0xffff;
+ data = (void __user *)attr->addr;
+ switch (addr) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ offset = (addr - EIOINTC_NODETYPE_START) / 4;
+ p = &s->nodetype.reg_u32[offset];
+ break;
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
+ offset = (addr - EIOINTC_IPMAP_START) / 4;
+ p = &s->ipmap.reg_u32[offset];
+ break;
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
+ offset = (addr - EIOINTC_ENABLE_START) / 4;
+ p = &s->enable.reg_u32[offset];
+ break;
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
+ offset = (addr - EIOINTC_BOUNCE_START) / 4;
+ p = &s->bounce.reg_u32[offset];
+ break;
+ case EIOINTC_ISR_START ... EIOINTC_ISR_END:
+ offset = (addr - EIOINTC_ISR_START) / 4;
+ p = &s->isr.reg_u32[offset];
+ break;
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
+ offset = (addr - EIOINTC_COREISR_START) / 4;
+ p = &s->coreisr.reg_u32[cpuid][offset];
+ break;
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
+ offset = (addr - EIOINTC_COREMAP_START) / 4;
+ p = &s->coremap.reg_u32[offset];
+ break;
+ default:
+ kvm_err("%s: unknown eiointc register, addr = %d\n", __func__, addr);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&s->lock, flags);
+ if (is_write) {
+ if (copy_from_user(p, data, 4))
+ ret = -EFAULT;
+ } else {
+ if (copy_to_user(data, p, 4))
+ ret = -EFAULT;
+ }
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return ret;
+}
+
+static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ bool is_write)
+{
+ int addr, ret = 0;
+ unsigned long flags;
+ void *p = NULL;
+ void __user *data;
+ struct loongarch_eiointc *s;
+
+ s = dev->kvm->arch.eiointc;
+ addr = attr->attr;
+ addr &= 0xffff;
+
+ data = (void __user *)attr->addr;
+ switch (addr) {
+ case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU:
+ p = &s->num_cpu;
+ break;
+ case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_FEATURE:
+ p = &s->features;
+ break;
+ case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_STATE:
+ p = &s->status;
+ break;
+ default:
+ kvm_err("%s: unknown eiointc register, addr = %d\n", __func__, addr);
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&s->lock, flags);
+ if (is_write) {
+ if (copy_from_user(p, data, 4))
+ ret = -EFAULT;
+ } else {
+ if (copy_to_user(data, p, 4))
+ ret = -EFAULT;
+ }
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return ret;
+}
+
+static int kvm_eiointc_get_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
+ return kvm_eiointc_regs_access(dev, attr, false);
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
+ return kvm_eiointc_sw_status_access(dev, attr, false);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int kvm_eiointc_set_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL:
+ return kvm_eiointc_ctrl_access(dev, attr);
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
+ return kvm_eiointc_regs_access(dev, attr, true);
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
+ return kvm_eiointc_sw_status_access(dev, attr, true);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int kvm_eiointc_create(struct kvm_device *dev, u32 type)
+{
+ int ret;
+ struct loongarch_eiointc *s;
+ struct kvm_io_device *device, *device1;
+ struct kvm *kvm = dev->kvm;
+
+ /* eiointc has been created */
+ if (kvm->arch.eiointc)
+ return -EINVAL;
+
+ s = kzalloc(sizeof(struct loongarch_eiointc), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ spin_lock_init(&s->lock);
+ s->kvm = kvm;
+
+ /*
+ * Initialize IOCSR device
+ */
+ device = &s->device;
+ kvm_iodevice_init(device, &kvm_eiointc_ops);
+ mutex_lock(&kvm->slots_lock);
+ ret = kvm_io_bus_register_dev(kvm, KVM_IOCSR_BUS,
+ EIOINTC_BASE, EIOINTC_SIZE, device);
+ mutex_unlock(&kvm->slots_lock);
+ if (ret < 0) {
+ kfree(s);
+ return ret;
+ }
+
+ device1 = &s->device_vext;
+ kvm_iodevice_init(device1, &kvm_eiointc_virt_ops);
+ ret = kvm_io_bus_register_dev(kvm, KVM_IOCSR_BUS,
+ EIOINTC_VIRT_BASE, EIOINTC_VIRT_SIZE, device1);
+ if (ret < 0) {
+ kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &s->device);
+ kfree(s);
+ return ret;
+ }
+ kvm->arch.eiointc = s;
+
+ return 0;
+}
+
+static void kvm_eiointc_destroy(struct kvm_device *dev)
+{
+ struct kvm *kvm;
+ struct loongarch_eiointc *eiointc;
+
+ if (!dev || !dev->kvm || !dev->kvm->arch.eiointc)
+ return;
+
+ kvm = dev->kvm;
+ eiointc = kvm->arch.eiointc;
+ kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &eiointc->device);
+ kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &eiointc->device_vext);
+ kfree(eiointc);
+}
+
+static struct kvm_device_ops kvm_eiointc_dev_ops = {
+ .name = "kvm-loongarch-eiointc",
+ .create = kvm_eiointc_create,
+ .destroy = kvm_eiointc_destroy,
+ .set_attr = kvm_eiointc_set_attr,
+ .get_attr = kvm_eiointc_get_attr,
+};
+
+int kvm_loongarch_register_eiointc_device(void)
+{
+ return kvm_register_device_ops(&kvm_eiointc_dev_ops, KVM_DEV_TYPE_LOONGARCH_EIOINTC);
+}
diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c
new file mode 100644
index 000000000000..a233a323e295
--- /dev/null
+++ b/arch/loongarch/kvm/intc/ipi.c
@@ -0,0 +1,475 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_ipi.h>
+#include <asm/kvm_vcpu.h>
+
+static void ipi_send(struct kvm *kvm, uint64_t data)
+{
+ int cpu, action;
+ uint32_t status;
+ struct kvm_vcpu *vcpu;
+ struct kvm_interrupt irq;
+
+ cpu = ((data & 0xffffffff) >> 16) & 0x3ff;
+ vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu);
+ if (unlikely(vcpu == NULL)) {
+ kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
+ return;
+ }
+
+ action = BIT(data & 0x1f);
+ spin_lock(&vcpu->arch.ipi_state.lock);
+ status = vcpu->arch.ipi_state.status;
+ vcpu->arch.ipi_state.status |= action;
+ spin_unlock(&vcpu->arch.ipi_state.lock);
+ if (status == 0) {
+ irq.irq = LARCH_INT_IPI;
+ kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+ }
+}
+
+static void ipi_clear(struct kvm_vcpu *vcpu, uint64_t data)
+{
+ uint32_t status;
+ struct kvm_interrupt irq;
+
+ spin_lock(&vcpu->arch.ipi_state.lock);
+ vcpu->arch.ipi_state.status &= ~data;
+ status = vcpu->arch.ipi_state.status;
+ spin_unlock(&vcpu->arch.ipi_state.lock);
+ if (status == 0) {
+ irq.irq = -LARCH_INT_IPI;
+ kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+ }
+}
+
+static uint64_t read_mailbox(struct kvm_vcpu *vcpu, int offset, int len)
+{
+ uint64_t data = 0;
+
+ spin_lock(&vcpu->arch.ipi_state.lock);
+ data = *(ulong *)((void *)vcpu->arch.ipi_state.buf + (offset - 0x20));
+ spin_unlock(&vcpu->arch.ipi_state.lock);
+
+ switch (len) {
+ case 1:
+ return data & 0xff;
+ case 2:
+ return data & 0xffff;
+ case 4:
+ return data & 0xffffffff;
+ case 8:
+ return data;
+ default:
+ kvm_err("%s: unknown data len: %d\n", __func__, len);
+ return 0;
+ }
+}
+
+static void write_mailbox(struct kvm_vcpu *vcpu, int offset, uint64_t data, int len)
+{
+ void *pbuf;
+
+ spin_lock(&vcpu->arch.ipi_state.lock);
+ pbuf = (void *)vcpu->arch.ipi_state.buf + (offset - 0x20);
+
+ switch (len) {
+ case 1:
+ *(unsigned char *)pbuf = (unsigned char)data;
+ break;
+ case 2:
+ *(unsigned short *)pbuf = (unsigned short)data;
+ break;
+ case 4:
+ *(unsigned int *)pbuf = (unsigned int)data;
+ break;
+ case 8:
+ *(unsigned long *)pbuf = (unsigned long)data;
+ break;
+ default:
+ kvm_err("%s: unknown data len: %d\n", __func__, len);
+ }
+ spin_unlock(&vcpu->arch.ipi_state.lock);
+}
+
+static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
+{
+ int i, ret;
+ uint32_t val = 0, mask = 0;
+
+ /*
+ * Bit 27-30 is mask for byte writing.
+ * If the mask is 0, we need not to do anything.
+ */
+ if ((data >> 27) & 0xf) {
+ /* Read the old val */
+ ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
+ if (unlikely(ret)) {
+ kvm_err("%s: : read date from addr %llx failed\n", __func__, addr);
+ return ret;
+ }
+ /* Construct the mask by scanning the bit 27-30 */
+ for (i = 0; i < 4; i++) {
+ if (data & (BIT(27 + i)))
+ mask |= (0xff << (i * 8));
+ }
+ /* Save the old part of val */
+ val &= mask;
+ }
+ val |= ((uint32_t)(data >> 32) & ~mask);
+ ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
+ if (unlikely(ret))
+ kvm_err("%s: : write date to addr %llx failed\n", __func__, addr);
+
+ return ret;
+}
+
+static int mail_send(struct kvm *kvm, uint64_t data)
+{
+ int cpu, mailbox, offset;
+ struct kvm_vcpu *vcpu;
+
+ cpu = ((data & 0xffffffff) >> 16) & 0x3ff;
+ vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu);
+ if (unlikely(vcpu == NULL)) {
+ kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
+ return -EINVAL;
+ }
+ mailbox = ((data & 0xffffffff) >> 2) & 0x7;
+ offset = IOCSR_IPI_BASE + IOCSR_IPI_BUF_20 + mailbox * 4;
+
+ return send_ipi_data(vcpu, offset, data);
+}
+
+static int any_send(struct kvm *kvm, uint64_t data)
+{
+ int cpu, offset;
+ struct kvm_vcpu *vcpu;
+
+ cpu = ((data & 0xffffffff) >> 16) & 0x3ff;
+ vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu);
+ if (unlikely(vcpu == NULL)) {
+ kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
+ return -EINVAL;
+ }
+ offset = data & 0xffff;
+
+ return send_ipi_data(vcpu, offset, data);
+}
+
+static int loongarch_ipi_readl(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *val)
+{
+ int ret = 0;
+ uint32_t offset;
+ uint64_t res = 0;
+
+ offset = (uint32_t)(addr & 0x1ff);
+ WARN_ON_ONCE(offset & (len - 1));
+
+ switch (offset) {
+ case IOCSR_IPI_STATUS:
+ spin_lock(&vcpu->arch.ipi_state.lock);
+ res = vcpu->arch.ipi_state.status;
+ spin_unlock(&vcpu->arch.ipi_state.lock);
+ break;
+ case IOCSR_IPI_EN:
+ spin_lock(&vcpu->arch.ipi_state.lock);
+ res = vcpu->arch.ipi_state.en;
+ spin_unlock(&vcpu->arch.ipi_state.lock);
+ break;
+ case IOCSR_IPI_SET:
+ res = 0;
+ break;
+ case IOCSR_IPI_CLEAR:
+ res = 0;
+ break;
+ case IOCSR_IPI_BUF_20 ... IOCSR_IPI_BUF_38 + 7:
+ if (offset + len > IOCSR_IPI_BUF_38 + 8) {
+ kvm_err("%s: invalid offset or len: offset = %d, len = %d\n",
+ __func__, offset, len);
+ ret = -EINVAL;
+ break;
+ }
+ res = read_mailbox(vcpu, offset, len);
+ break;
+ default:
+ kvm_err("%s: unknown addr: %llx\n", __func__, addr);
+ ret = -EINVAL;
+ break;
+ }
+ *(uint64_t *)val = res;
+
+ return ret;
+}
+
+static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, const void *val)
+{
+ int ret = 0;
+ uint64_t data;
+ uint32_t offset;
+
+ data = *(uint64_t *)val;
+
+ offset = (uint32_t)(addr & 0x1ff);
+ WARN_ON_ONCE(offset & (len - 1));
+
+ switch (offset) {
+ case IOCSR_IPI_STATUS:
+ ret = -EINVAL;
+ break;
+ case IOCSR_IPI_EN:
+ spin_lock(&vcpu->arch.ipi_state.lock);
+ vcpu->arch.ipi_state.en = data;
+ spin_unlock(&vcpu->arch.ipi_state.lock);
+ break;
+ case IOCSR_IPI_SET:
+ ret = -EINVAL;
+ break;
+ case IOCSR_IPI_CLEAR:
+ /* Just clear the status of the current vcpu */
+ ipi_clear(vcpu, data);
+ break;
+ case IOCSR_IPI_BUF_20 ... IOCSR_IPI_BUF_38 + 7:
+ if (offset + len > IOCSR_IPI_BUF_38 + 8) {
+ kvm_err("%s: invalid offset or len: offset = %d, len = %d\n",
+ __func__, offset, len);
+ ret = -EINVAL;
+ break;
+ }
+ write_mailbox(vcpu, offset, data, len);
+ break;
+ case IOCSR_IPI_SEND:
+ ipi_send(vcpu->kvm, data);
+ break;
+ case IOCSR_MAIL_SEND:
+ ret = mail_send(vcpu->kvm, *(uint64_t *)val);
+ break;
+ case IOCSR_ANY_SEND:
+ ret = any_send(vcpu->kvm, *(uint64_t *)val);
+ break;
+ default:
+ kvm_err("%s: unknown addr: %llx\n", __func__, addr);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int kvm_ipi_read(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, void *val)
+{
+ int ret;
+ struct loongarch_ipi *ipi;
+
+ ipi = vcpu->kvm->arch.ipi;
+ if (!ipi) {
+ kvm_err("%s: ipi irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+ ipi->kvm->stat.ipi_read_exits++;
+ ret = loongarch_ipi_readl(vcpu, addr, len, val);
+
+ return ret;
+}
+
+static int kvm_ipi_write(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, const void *val)
+{
+ int ret;
+ struct loongarch_ipi *ipi;
+
+ ipi = vcpu->kvm->arch.ipi;
+ if (!ipi) {
+ kvm_err("%s: ipi irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+ ipi->kvm->stat.ipi_write_exits++;
+ ret = loongarch_ipi_writel(vcpu, addr, len, val);
+
+ return ret;
+}
+
+static const struct kvm_io_device_ops kvm_ipi_ops = {
+ .read = kvm_ipi_read,
+ .write = kvm_ipi_write,
+};
+
+static int kvm_ipi_regs_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ bool is_write)
+{
+ int len = 4;
+ int cpu, addr;
+ uint64_t val;
+ void *p = NULL;
+ struct kvm_vcpu *vcpu;
+
+ cpu = (attr->attr >> 16) & 0x3ff;
+ addr = attr->attr & 0xff;
+
+ vcpu = kvm_get_vcpu(dev->kvm, cpu);
+ if (unlikely(vcpu == NULL)) {
+ kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
+ return -EINVAL;
+ }
+
+ switch (addr) {
+ case IOCSR_IPI_STATUS:
+ p = &vcpu->arch.ipi_state.status;
+ break;
+ case IOCSR_IPI_EN:
+ p = &vcpu->arch.ipi_state.en;
+ break;
+ case IOCSR_IPI_SET:
+ p = &vcpu->arch.ipi_state.set;
+ break;
+ case IOCSR_IPI_CLEAR:
+ p = &vcpu->arch.ipi_state.clear;
+ break;
+ case IOCSR_IPI_BUF_20:
+ p = &vcpu->arch.ipi_state.buf[0];
+ len = 8;
+ break;
+ case IOCSR_IPI_BUF_28:
+ p = &vcpu->arch.ipi_state.buf[1];
+ len = 8;
+ break;
+ case IOCSR_IPI_BUF_30:
+ p = &vcpu->arch.ipi_state.buf[2];
+ len = 8;
+ break;
+ case IOCSR_IPI_BUF_38:
+ p = &vcpu->arch.ipi_state.buf[3];
+ len = 8;
+ break;
+ default:
+ kvm_err("%s: unknown ipi register, addr = %d\n", __func__, addr);
+ return -EINVAL;
+ }
+
+ if (is_write) {
+ if (len == 4) {
+ if (get_user(val, (uint32_t __user *)attr->addr))
+ return -EFAULT;
+ *(uint32_t *)p = (uint32_t)val;
+ } else if (len == 8) {
+ if (get_user(val, (uint64_t __user *)attr->addr))
+ return -EFAULT;
+ *(uint64_t *)p = val;
+ }
+ } else {
+ if (len == 4) {
+ val = *(uint32_t *)p;
+ return put_user(val, (uint32_t __user *)attr->addr);
+ } else if (len == 8) {
+ val = *(uint64_t *)p;
+ return put_user(val, (uint64_t __user *)attr->addr);
+ }
+ }
+
+ return 0;
+}
+
+static int kvm_ipi_get_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_IPI_GRP_REGS:
+ return kvm_ipi_regs_access(dev, attr, false);
+ default:
+ kvm_err("%s: unknown group (%d)\n", __func__, attr->group);
+ return -EINVAL;
+ }
+}
+
+static int kvm_ipi_set_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_IPI_GRP_REGS:
+ return kvm_ipi_regs_access(dev, attr, true);
+ default:
+ kvm_err("%s: unknown group (%d)\n", __func__, attr->group);
+ return -EINVAL;
+ }
+}
+
+static int kvm_ipi_create(struct kvm_device *dev, u32 type)
+{
+ int ret;
+ struct kvm *kvm;
+ struct kvm_io_device *device;
+ struct loongarch_ipi *s;
+
+ if (!dev) {
+ kvm_err("%s: kvm_device ptr is invalid!\n", __func__);
+ return -EINVAL;
+ }
+
+ kvm = dev->kvm;
+ if (kvm->arch.ipi) {
+ kvm_err("%s: LoongArch IPI has already been created!\n", __func__);
+ return -EINVAL;
+ }
+
+ s = kzalloc(sizeof(struct loongarch_ipi), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ spin_lock_init(&s->lock);
+ s->kvm = kvm;
+
+ /*
+ * Initialize IOCSR device
+ */
+ device = &s->device;
+ kvm_iodevice_init(device, &kvm_ipi_ops);
+ mutex_lock(&kvm->slots_lock);
+ ret = kvm_io_bus_register_dev(kvm, KVM_IOCSR_BUS, IOCSR_IPI_BASE, IOCSR_IPI_SIZE, device);
+ mutex_unlock(&kvm->slots_lock);
+ if (ret < 0) {
+ kvm_err("%s: Initialize IOCSR dev failed, ret = %d\n", __func__, ret);
+ goto err;
+ }
+
+ kvm->arch.ipi = s;
+ return 0;
+
+err:
+ kfree(s);
+ return -EFAULT;
+}
+
+static void kvm_ipi_destroy(struct kvm_device *dev)
+{
+ struct kvm *kvm;
+ struct loongarch_ipi *ipi;
+
+ if (!dev || !dev->kvm || !dev->kvm->arch.ipi)
+ return;
+
+ kvm = dev->kvm;
+ ipi = kvm->arch.ipi;
+ kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &ipi->device);
+ kfree(ipi);
+}
+
+static struct kvm_device_ops kvm_ipi_dev_ops = {
+ .name = "kvm-loongarch-ipi",
+ .create = kvm_ipi_create,
+ .destroy = kvm_ipi_destroy,
+ .set_attr = kvm_ipi_set_attr,
+ .get_attr = kvm_ipi_get_attr,
+};
+
+int kvm_loongarch_register_ipi_device(void)
+{
+ return kvm_register_device_ops(&kvm_ipi_dev_ops, KVM_DEV_TYPE_LOONGARCH_IPI);
+}
diff --git a/arch/loongarch/kvm/intc/pch_pic.c b/arch/loongarch/kvm/intc/pch_pic.c
new file mode 100644
index 000000000000..08fce845f668
--- /dev/null
+++ b/arch/loongarch/kvm/intc/pch_pic.c
@@ -0,0 +1,519 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#include <asm/kvm_eiointc.h>
+#include <asm/kvm_pch_pic.h>
+#include <asm/kvm_vcpu.h>
+#include <linux/count_zeros.h>
+
+/* update the isr according to irq level and route irq to eiointc */
+static void pch_pic_update_irq(struct loongarch_pch_pic *s, int irq, int level)
+{
+ u64 mask = BIT(irq);
+
+ /*
+ * set isr and route irq to eiointc and
+ * the route table is in htmsi_vector[]
+ */
+ if (level) {
+ if (mask & s->irr & ~s->mask) {
+ s->isr |= mask;
+ irq = s->htmsi_vector[irq];
+ eiointc_set_irq(s->kvm->arch.eiointc, irq, level);
+ }
+ } else {
+ if (mask & s->isr & ~s->irr) {
+ s->isr &= ~mask;
+ irq = s->htmsi_vector[irq];
+ eiointc_set_irq(s->kvm->arch.eiointc, irq, level);
+ }
+ }
+}
+
+/* update batch irqs, the irq_mask is a bitmap of irqs */
+static void pch_pic_update_batch_irqs(struct loongarch_pch_pic *s, u64 irq_mask, int level)
+{
+ int irq, bits;
+
+ /* find each irq by irqs bitmap and update each irq */
+ bits = sizeof(irq_mask) * 8;
+ irq = find_first_bit((void *)&irq_mask, bits);
+ while (irq < bits) {
+ pch_pic_update_irq(s, irq, level);
+ bitmap_clear((void *)&irq_mask, irq, 1);
+ irq = find_first_bit((void *)&irq_mask, bits);
+ }
+}
+
+/* called when a irq is triggered in pch pic */
+void pch_pic_set_irq(struct loongarch_pch_pic *s, int irq, int level)
+{
+ u64 mask = BIT(irq);
+
+ spin_lock(&s->lock);
+ if (level)
+ s->irr |= mask; /* set irr */
+ else {
+ /*
+ * In edge triggered mode, 0 does not mean to clear irq
+ * The irr register variable is cleared when cpu writes to the
+ * PCH_PIC_CLEAR_START address area
+ */
+ if (s->edge & mask) {
+ spin_unlock(&s->lock);
+ return;
+ }
+ s->irr &= ~mask;
+ }
+ pch_pic_update_irq(s, irq, level);
+ spin_unlock(&s->lock);
+}
+
+/* msi irq handler */
+void pch_msi_set_irq(struct kvm *kvm, int irq, int level)
+{
+ eiointc_set_irq(kvm->arch.eiointc, irq, level);
+}
+
+/*
+ * pch pic register is 64-bit, but it is accessed by 32-bit,
+ * so we use high to get whether low or high 32 bits we want
+ * to read.
+ */
+static u32 pch_pic_read_reg(u64 *s, int high)
+{
+ u64 val = *s;
+
+ /* read the high 32 bits when high is 1 */
+ return high ? (u32)(val >> 32) : (u32)val;
+}
+
+/*
+ * pch pic register is 64-bit, but it is accessed by 32-bit,
+ * so we use high to get whether low or high 32 bits we want
+ * to write.
+ */
+static u32 pch_pic_write_reg(u64 *s, int high, u32 v)
+{
+ u64 val = *s, data = v;
+
+ if (high) {
+ /*
+ * Clear val high 32 bits
+ * Write the high 32 bits when the high is 1
+ */
+ *s = (val << 32 >> 32) | (data << 32);
+ val >>= 32;
+ } else
+ /*
+ * Clear val low 32 bits
+ * Write the low 32 bits when the high is 0
+ */
+ *s = (val >> 32 << 32) | v;
+
+ return (u32)val;
+}
+
+static int loongarch_pch_pic_read(struct loongarch_pch_pic *s, gpa_t addr, int len, void *val)
+{
+ int offset, index, ret = 0;
+ u32 data = 0;
+ u64 int_id = 0;
+
+ offset = addr - s->pch_pic_base;
+
+ spin_lock(&s->lock);
+ switch (offset) {
+ case PCH_PIC_INT_ID_START ... PCH_PIC_INT_ID_END:
+ /* int id version */
+ int_id |= (u64)PCH_PIC_INT_ID_VER << 32;
+ /* irq number */
+ int_id |= (u64)31 << (32 + 16);
+ /* int id value */
+ int_id |= PCH_PIC_INT_ID_VAL;
+ *(u64 *)val = int_id;
+ break;
+ case PCH_PIC_MASK_START ... PCH_PIC_MASK_END:
+ offset -= PCH_PIC_MASK_START;
+ index = offset >> 2;
+ /* read mask reg */
+ data = pch_pic_read_reg(&s->mask, index);
+ *(u32 *)val = data;
+ break;
+ case PCH_PIC_HTMSI_EN_START ... PCH_PIC_HTMSI_EN_END:
+ offset -= PCH_PIC_HTMSI_EN_START;
+ index = offset >> 2;
+ /* read htmsi enable reg */
+ data = pch_pic_read_reg(&s->htmsi_en, index);
+ *(u32 *)val = data;
+ break;
+ case PCH_PIC_EDGE_START ... PCH_PIC_EDGE_END:
+ offset -= PCH_PIC_EDGE_START;
+ index = offset >> 2;
+ /* read edge enable reg */
+ data = pch_pic_read_reg(&s->edge, index);
+ *(u32 *)val = data;
+ break;
+ case PCH_PIC_AUTO_CTRL0_START ... PCH_PIC_AUTO_CTRL0_END:
+ case PCH_PIC_AUTO_CTRL1_START ... PCH_PIC_AUTO_CTRL1_END:
+ /* we only use default mode: fixed interrupt distribution mode */
+ *(u32 *)val = 0;
+ break;
+ case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END:
+ /* only route to int0: eiointc */
+ *(u8 *)val = 1;
+ break;
+ case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END:
+ offset -= PCH_PIC_HTMSI_VEC_START;
+ /* read htmsi vector */
+ data = s->htmsi_vector[offset];
+ *(u8 *)val = data;
+ break;
+ case PCH_PIC_POLARITY_START ... PCH_PIC_POLARITY_END:
+ /* we only use defalut value 0: high level triggered */
+ *(u32 *)val = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ spin_unlock(&s->lock);
+
+ return ret;
+}
+
+static int kvm_pch_pic_read(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, void *val)
+{
+ int ret;
+ struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic;
+
+ if (!s) {
+ kvm_err("%s: pch pic irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+
+ /* statistics of pch pic reading */
+ vcpu->kvm->stat.pch_pic_read_exits++;
+ ret = loongarch_pch_pic_read(s, addr, len, val);
+
+ return ret;
+}
+
+static int loongarch_pch_pic_write(struct loongarch_pch_pic *s, gpa_t addr,
+ int len, const void *val)
+{
+ int ret;
+ u32 old, data, offset, index;
+ u64 irq;
+
+ ret = 0;
+ data = *(u32 *)val;
+ offset = addr - s->pch_pic_base;
+
+ spin_lock(&s->lock);
+ switch (offset) {
+ case PCH_PIC_MASK_START ... PCH_PIC_MASK_END:
+ offset -= PCH_PIC_MASK_START;
+ /* get whether high or low 32 bits we want to write */
+ index = offset >> 2;
+ old = pch_pic_write_reg(&s->mask, index, data);
+ /* enable irq when mask value change to 0 */
+ irq = (old & ~data) << (32 * index);
+ pch_pic_update_batch_irqs(s, irq, 1);
+ /* disable irq when mask value change to 1 */
+ irq = (~old & data) << (32 * index);
+ pch_pic_update_batch_irqs(s, irq, 0);
+ break;
+ case PCH_PIC_HTMSI_EN_START ... PCH_PIC_HTMSI_EN_END:
+ offset -= PCH_PIC_HTMSI_EN_START;
+ index = offset >> 2;
+ pch_pic_write_reg(&s->htmsi_en, index, data);
+ break;
+ case PCH_PIC_EDGE_START ... PCH_PIC_EDGE_END:
+ offset -= PCH_PIC_EDGE_START;
+ index = offset >> 2;
+ /* 1: edge triggered, 0: level triggered */
+ pch_pic_write_reg(&s->edge, index, data);
+ break;
+ case PCH_PIC_CLEAR_START ... PCH_PIC_CLEAR_END:
+ offset -= PCH_PIC_CLEAR_START;
+ index = offset >> 2;
+ /* write 1 to clear edge irq */
+ old = pch_pic_read_reg(&s->irr, index);
+ /*
+ * get the irq bitmap which is edge triggered and
+ * already set and to be cleared
+ */
+ irq = old & pch_pic_read_reg(&s->edge, index) & data;
+ /* write irr to the new state where irqs have been cleared */
+ pch_pic_write_reg(&s->irr, index, old & ~irq);
+ /* update cleared irqs */
+ pch_pic_update_batch_irqs(s, irq, 0);
+ break;
+ case PCH_PIC_AUTO_CTRL0_START ... PCH_PIC_AUTO_CTRL0_END:
+ offset -= PCH_PIC_AUTO_CTRL0_START;
+ index = offset >> 2;
+ /* we only use default mode: fixed interrupt distribution mode */
+ pch_pic_write_reg(&s->auto_ctrl0, index, 0);
+ break;
+ case PCH_PIC_AUTO_CTRL1_START ... PCH_PIC_AUTO_CTRL1_END:
+ offset -= PCH_PIC_AUTO_CTRL1_START;
+ index = offset >> 2;
+ /* we only use default mode: fixed interrupt distribution mode */
+ pch_pic_write_reg(&s->auto_ctrl1, index, 0);
+ break;
+ case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END:
+ offset -= PCH_PIC_ROUTE_ENTRY_START;
+ /* only route to int0: eiointc */
+ s->route_entry[offset] = 1;
+ break;
+ case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END:
+ /* route table to eiointc */
+ offset -= PCH_PIC_HTMSI_VEC_START;
+ s->htmsi_vector[offset] = (u8)data;
+ break;
+ case PCH_PIC_POLARITY_START ... PCH_PIC_POLARITY_END:
+ offset -= PCH_PIC_POLARITY_START;
+ index = offset >> 2;
+ /* we only use defalut value 0: high level triggered */
+ pch_pic_write_reg(&s->polarity, index, 0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ spin_unlock(&s->lock);
+
+ return ret;
+}
+
+static int kvm_pch_pic_write(struct kvm_vcpu *vcpu,
+ struct kvm_io_device *dev,
+ gpa_t addr, int len, const void *val)
+{
+ int ret;
+ struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic;
+
+ if (!s) {
+ kvm_err("%s: pch pic irqchip not valid!\n", __func__);
+ return -EINVAL;
+ }
+
+ /* statistics of pch pic writing */
+ vcpu->kvm->stat.pch_pic_write_exits++;
+ ret = loongarch_pch_pic_write(s, addr, len, val);
+
+ return ret;
+}
+
+static const struct kvm_io_device_ops kvm_pch_pic_ops = {
+ .read = kvm_pch_pic_read,
+ .write = kvm_pch_pic_write,
+};
+
+static int kvm_pch_pic_init(struct kvm_device *dev, u64 addr)
+{
+ int ret;
+ struct kvm *kvm = dev->kvm;
+ struct kvm_io_device *device;
+ struct loongarch_pch_pic *s = dev->kvm->arch.pch_pic;
+
+ s->pch_pic_base = addr;
+ device = &s->device;
+ /* init device by pch pic writing and reading ops */
+ kvm_iodevice_init(device, &kvm_pch_pic_ops);
+ mutex_lock(&kvm->slots_lock);
+ /* register pch pic device */
+ ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, addr, PCH_PIC_SIZE, device);
+ mutex_unlock(&kvm->slots_lock);
+
+ return (ret < 0) ? -EFAULT : 0;
+}
+
+/* used by user space to get or set pch pic registers */
+static int kvm_pch_pic_regs_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ bool is_write)
+{
+ int addr, offset, len = 8, ret = 0;
+ void __user *data;
+ void *p = NULL;
+ struct loongarch_pch_pic *s;
+
+ s = dev->kvm->arch.pch_pic;
+ addr = attr->attr;
+ data = (void __user *)attr->addr;
+
+ /* get pointer to pch pic register by addr */
+ switch (addr) {
+ case PCH_PIC_MASK_START:
+ p = &s->mask;
+ break;
+ case PCH_PIC_HTMSI_EN_START:
+ p = &s->htmsi_en;
+ break;
+ case PCH_PIC_EDGE_START:
+ p = &s->edge;
+ break;
+ case PCH_PIC_AUTO_CTRL0_START:
+ p = &s->auto_ctrl0;
+ break;
+ case PCH_PIC_AUTO_CTRL1_START:
+ p = &s->auto_ctrl1;
+ break;
+ case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END:
+ offset = addr - PCH_PIC_ROUTE_ENTRY_START;
+ p = &s->route_entry[offset];
+ len = 1;
+ break;
+ case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END:
+ offset = addr - PCH_PIC_HTMSI_VEC_START;
+ p = &s->htmsi_vector[offset];
+ len = 1;
+ break;
+ case PCH_PIC_INT_IRR_START:
+ p = &s->irr;
+ break;
+ case PCH_PIC_INT_ISR_START:
+ p = &s->isr;
+ break;
+ case PCH_PIC_POLARITY_START:
+ p = &s->polarity;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock(&s->lock);
+ /* write or read value according to is_write */
+ if (is_write) {
+ if (copy_from_user(p, data, len))
+ ret = -EFAULT;
+ } else {
+ if (copy_to_user(data, p, len))
+ ret = -EFAULT;
+ }
+ spin_unlock(&s->lock);
+
+ return ret;
+}
+
+static int kvm_pch_pic_get_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS:
+ return kvm_pch_pic_regs_access(dev, attr, false);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int kvm_pch_pic_set_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ u64 addr;
+ void __user *uaddr = (void __user *)(long)attr->addr;
+
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL:
+ switch (attr->attr) {
+ case KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT:
+ if (copy_from_user(&addr, uaddr, sizeof(addr)))
+ return -EFAULT;
+
+ if (!dev->kvm->arch.pch_pic) {
+ kvm_err("%s: please create pch_pic irqchip first!\n", __func__);
+ return -ENODEV;
+ }
+
+ return kvm_pch_pic_init(dev, addr);
+ default:
+ kvm_err("%s: unknown group (%d) attr (%lld)\n", __func__, attr->group,
+ attr->attr);
+ return -EINVAL;
+ }
+ case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS:
+ return kvm_pch_pic_regs_access(dev, attr, true);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int kvm_setup_default_irq_routing(struct kvm *kvm)
+{
+ int i, ret;
+ u32 nr = KVM_IRQCHIP_NUM_PINS;
+ struct kvm_irq_routing_entry *entries;
+
+ entries = kcalloc(nr, sizeof(*entries), GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ for (i = 0; i < nr; i++) {
+ entries[i].gsi = i;
+ entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
+ entries[i].u.irqchip.irqchip = 0;
+ entries[i].u.irqchip.pin = i;
+ }
+ ret = kvm_set_irq_routing(kvm, entries, nr, 0);
+ kfree(entries);
+
+ return ret;
+}
+
+static int kvm_pch_pic_create(struct kvm_device *dev, u32 type)
+{
+ int ret;
+ struct kvm *kvm = dev->kvm;
+ struct loongarch_pch_pic *s;
+
+ /* pch pic should not has been created */
+ if (kvm->arch.pch_pic)
+ return -EINVAL;
+
+ ret = kvm_setup_default_irq_routing(kvm);
+ if (ret)
+ return -ENOMEM;
+
+ s = kzalloc(sizeof(struct loongarch_pch_pic), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ spin_lock_init(&s->lock);
+ s->kvm = kvm;
+ kvm->arch.pch_pic = s;
+
+ return 0;
+}
+
+static void kvm_pch_pic_destroy(struct kvm_device *dev)
+{
+ struct kvm *kvm;
+ struct loongarch_pch_pic *s;
+
+ if (!dev || !dev->kvm || !dev->kvm->arch.pch_pic)
+ return;
+
+ kvm = dev->kvm;
+ s = kvm->arch.pch_pic;
+ /* unregister pch pic device and free it's memory */
+ kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &s->device);
+ kfree(s);
+}
+
+static struct kvm_device_ops kvm_pch_pic_dev_ops = {
+ .name = "kvm-loongarch-pch-pic",
+ .create = kvm_pch_pic_create,
+ .destroy = kvm_pch_pic_destroy,
+ .set_attr = kvm_pch_pic_set_attr,
+ .get_attr = kvm_pch_pic_get_attr,
+};
+
+int kvm_loongarch_register_pch_pic_device(void)
+{
+ return kvm_register_device_ops(&kvm_pch_pic_dev_ops, KVM_DEV_TYPE_LOONGARCH_PCHPIC);
+}
diff --git a/arch/loongarch/kvm/irqfd.c b/arch/loongarch/kvm/irqfd.c
new file mode 100644
index 000000000000..9a39627aecf0
--- /dev/null
+++ b/arch/loongarch/kvm/irqfd.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+#include <asm/kvm_pch_pic.h>
+
+static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id, int level, bool line_status)
+{
+ /* PCH-PIC pin (0 ~ 64) <---> GSI (0 ~ 64) */
+ pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level);
+
+ return 0;
+}
+
+/*
+ * kvm_set_msi: inject the MSI corresponding to the
+ * MSI routing entry
+ *
+ * This is the entry point for irqfd MSI injection
+ * and userspace MSI injection.
+ */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id, int level, bool line_status)
+{
+ if (!level)
+ return -1;
+
+ pch_msi_set_irq(kvm, e->msi.data, level);
+
+ return 0;
+}
+
+/*
+ * kvm_set_routing_entry: populate a kvm routing entry
+ * from a user routing entry
+ *
+ * @kvm: the VM this entry is applied to
+ * @e: kvm kernel routing entry handle
+ * @ue: user api routing entry handle
+ * return 0 on success, -EINVAL on errors.
+ */
+int kvm_set_routing_entry(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
+{
+ switch (ue->type) {
+ case KVM_IRQ_ROUTING_IRQCHIP:
+ e->set = kvm_set_pic_irq;
+ e->irqchip.irqchip = ue->u.irqchip.irqchip;
+ e->irqchip.pin = ue->u.irqchip.pin;
+
+ if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS)
+ return -EINVAL;
+
+ return 0;
+ case KVM_IRQ_ROUTING_MSI:
+ e->set = kvm_set_msi;
+ e->msi.address_lo = ue->u.msi.address_lo;
+ e->msi.address_hi = ue->u.msi.address_hi;
+ e->msi.data = ue->u.msi.data;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id, int level, bool line_status)
+{
+ switch (e->type) {
+ case KVM_IRQ_ROUTING_IRQCHIP:
+ pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level);
+ return 0;
+ case KVM_IRQ_ROUTING_MSI:
+ pch_msi_set_irq(kvm, e->msi.data, level);
+ return 0;
+ default:
+ return -EWOULDBLOCK;
+ }
+}
+
+bool kvm_arch_intc_initialized(struct kvm *kvm)
+{
+ return kvm_arch_irqchip_in_kernel(kvm);
+}
diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c
index 27e9b94c0a0b..396fed2665a5 100644
--- a/arch/loongarch/kvm/main.c
+++ b/arch/loongarch/kvm/main.c
@@ -9,6 +9,8 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
#include <asm/kvm_csr.h>
+#include <asm/kvm_eiointc.h>
+#include <asm/kvm_pch_pic.h>
#include "trace.h"
unsigned long vpid_mask;
@@ -313,7 +315,7 @@ void kvm_arch_disable_virtualization_cpu(void)
static int kvm_loongarch_env_init(void)
{
- int cpu, order;
+ int cpu, order, ret;
void *addr;
struct kvm_context *context;
@@ -368,7 +370,20 @@ static int kvm_loongarch_env_init(void)
kvm_init_gcsr_flag();
- return 0;
+ /* Register LoongArch IPI interrupt controller interface. */
+ ret = kvm_loongarch_register_ipi_device();
+ if (ret)
+ return ret;
+
+ /* Register LoongArch EIOINTC interrupt controller interface. */
+ ret = kvm_loongarch_register_eiointc_device();
+ if (ret)
+ return ret;
+
+ /* Register LoongArch PCH-PIC interrupt controller interface. */
+ ret = kvm_loongarch_register_pch_pic_device();
+
+ return ret;
}
static void kvm_loongarch_env_exit(void)
diff --git a/arch/loongarch/kvm/mmu.c b/arch/loongarch/kvm/mmu.c
index 28681dfb4b85..4d203294767c 100644
--- a/arch/loongarch/kvm/mmu.c
+++ b/arch/loongarch/kvm/mmu.c
@@ -552,12 +552,10 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
{
int ret = 0;
- kvm_pfn_t pfn = 0;
kvm_pte_t *ptep, changed, new;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct kvm *kvm = vcpu->kvm;
struct kvm_memory_slot *slot;
- struct page *page;
spin_lock(&kvm->mmu_lock);
@@ -570,8 +568,6 @@ static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool writ
/* Track access to pages marked old */
new = kvm_pte_mkyoung(*ptep);
- /* call kvm_set_pfn_accessed() after unlock */
-
if (write && !kvm_pte_dirty(new)) {
if (!kvm_pte_write(new)) {
ret = -EFAULT;
@@ -595,26 +591,14 @@ static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool writ
}
changed = new ^ (*ptep);
- if (changed) {
+ if (changed)
kvm_set_pte(ptep, new);
- pfn = kvm_pte_pfn(new);
- page = kvm_pfn_to_refcounted_page(pfn);
- if (page)
- get_page(page);
- }
+
spin_unlock(&kvm->mmu_lock);
- if (changed) {
- if (kvm_pte_young(changed))
- kvm_set_pfn_accessed(pfn);
+ if (kvm_pte_dirty(changed))
+ mark_page_dirty(kvm, gfn);
- if (kvm_pte_dirty(changed)) {
- mark_page_dirty(kvm, gfn);
- kvm_set_pfn_dirty(pfn);
- }
- if (page)
- put_page(page);
- }
return ret;
out:
spin_unlock(&kvm->mmu_lock);
@@ -796,6 +780,7 @@ static int kvm_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
struct kvm *kvm = vcpu->kvm;
struct kvm_memory_slot *memslot;
struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
+ struct page *page;
/* Try the fast path to handle old / clean pages */
srcu_idx = srcu_read_lock(&kvm->srcu);
@@ -823,7 +808,7 @@ retry:
mmu_seq = kvm->mmu_invalidate_seq;
/*
* Ensure the read of mmu_invalidate_seq isn't reordered with PTE reads in
- * gfn_to_pfn_prot() (which calls get_user_pages()), so that we don't
+ * kvm_faultin_pfn() (which calls get_user_pages()), so that we don't
* risk the page we get a reference to getting unmapped before we have a
* chance to grab the mmu_lock without mmu_invalidate_retry() noticing.
*
@@ -835,7 +820,7 @@ retry:
smp_rmb();
/* Slow path - ask KVM core whether we can access this GPA */
- pfn = gfn_to_pfn_prot(kvm, gfn, write, &writeable);
+ pfn = kvm_faultin_pfn(vcpu, gfn, write, &writeable, &page);
if (is_error_noslot_pfn(pfn)) {
err = -EFAULT;
goto out;
@@ -847,10 +832,10 @@ retry:
/*
* This can happen when mappings are changed asynchronously, but
* also synchronously if a COW is triggered by
- * gfn_to_pfn_prot().
+ * kvm_faultin_pfn().
*/
spin_unlock(&kvm->mmu_lock);
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_unused(page);
if (retry_no > 100) {
retry_no = 0;
schedule();
@@ -915,14 +900,13 @@ retry:
else
++kvm->stat.pages;
kvm_set_pte(ptep, new_pte);
+
+ kvm_release_faultin_page(kvm, page, false, writeable);
spin_unlock(&kvm->mmu_lock);
- if (prot_bits & _PAGE_DIRTY) {
+ if (prot_bits & _PAGE_DIRTY)
mark_page_dirty_in_slot(kvm, memslot, gfn);
- kvm_set_pfn_dirty(pfn);
- }
- kvm_release_pfn_clean(pfn);
out:
srcu_read_unlock(&kvm->srcu, srcu_idx);
return err;
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 174734a23d0a..cab1818be68d 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -1475,6 +1475,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
/* Init */
vcpu->arch.last_sched_cpu = -1;
+ /* Init ipi_state lock */
+ spin_lock_init(&vcpu->arch.ipi_state.lock);
+
/*
* Initialize guest register state to valid architectural reset state.
*/
diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
index 4ba734aaef87..b8b3e1972d6e 100644
--- a/arch/loongarch/kvm/vm.c
+++ b/arch/loongarch/kvm/vm.c
@@ -6,6 +6,8 @@
#include <linux/kvm_host.h>
#include <asm/kvm_mmu.h>
#include <asm/kvm_vcpu.h>
+#include <asm/kvm_eiointc.h>
+#include <asm/kvm_pch_pic.h>
const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
KVM_GENERIC_VM_STATS(),
@@ -76,6 +78,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
int r;
switch (ext) {
+ case KVM_CAP_IRQCHIP:
case KVM_CAP_ONE_REG:
case KVM_CAP_ENABLE_CAP:
case KVM_CAP_READONLY_MEM:
@@ -161,6 +164,8 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
struct kvm_device_attr attr;
switch (ioctl) {
+ case KVM_CREATE_IRQCHIP:
+ return 0;
case KVM_HAS_DEVICE_ATTR:
if (copy_from_user(&attr, argp, sizeof(attr)))
return -EFAULT;
@@ -170,3 +175,19 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
return -ENOIOCTLCMD;
}
}
+
+int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, bool line_status)
+{
+ if (!kvm_arch_irqchip_in_kernel(kvm))
+ return -ENXIO;
+
+ irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
+ irq_event->irq, irq_event->level, line_status);
+
+ return 0;
+}
+
+bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
+{
+ return (kvm->arch.ipi && kvm->arch.eiointc && kvm->arch.pch_pic);
+}
diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c
index 427d6b1aec09..d2681272d8f0 100644
--- a/arch/loongarch/mm/kasan_init.c
+++ b/arch/loongarch/mm/kasan_init.c
@@ -13,6 +13,13 @@
static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
+#ifdef __PAGETABLE_P4D_FOLDED
+#define __pgd_none(early, pgd) (0)
+#else
+#define __pgd_none(early, pgd) (early ? (pgd_val(pgd) == 0) : \
+(__pa(pgd_val(pgd)) == (unsigned long)__pa(kasan_early_shadow_p4d)))
+#endif
+
#ifdef __PAGETABLE_PUD_FOLDED
#define __p4d_none(early, p4d) (0)
#else
@@ -55,6 +62,9 @@ void *kasan_mem_to_shadow(const void *addr)
case XKPRANGE_UC_SEG:
offset = XKPRANGE_UC_SHADOW_OFFSET;
break;
+ case XKPRANGE_WC_SEG:
+ offset = XKPRANGE_WC_SHADOW_OFFSET;
+ break;
case XKVRANGE_VC_SEG:
offset = XKVRANGE_VC_SHADOW_OFFSET;
break;
@@ -79,6 +89,8 @@ const void *kasan_shadow_to_mem(const void *shadow_addr)
if (addr >= XKVRANGE_VC_SHADOW_OFFSET)
return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START);
+ else if (addr >= XKPRANGE_WC_SHADOW_OFFSET)
+ return (void *)(((addr - XKPRANGE_WC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_WC_START);
else if (addr >= XKPRANGE_UC_SHADOW_OFFSET)
return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START);
else if (addr >= XKPRANGE_CC_SHADOW_OFFSET)
@@ -142,6 +154,19 @@ static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node,
return pud_offset(p4dp, addr);
}
+static p4d_t *__init kasan_p4d_offset(pgd_t *pgdp, unsigned long addr, int node, bool early)
+{
+ if (__pgd_none(early, pgdp_get(pgdp))) {
+ phys_addr_t p4d_phys = early ?
+ __pa_symbol(kasan_early_shadow_p4d) : kasan_alloc_zeroed_page(node);
+ if (!early)
+ memcpy(__va(p4d_phys), kasan_early_shadow_p4d, sizeof(kasan_early_shadow_p4d));
+ pgd_populate(&init_mm, pgdp, (p4d_t *)__va(p4d_phys));
+ }
+
+ return p4d_offset(pgdp, addr);
+}
+
static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr,
unsigned long end, int node, bool early)
{
@@ -178,19 +203,19 @@ static void __init kasan_pud_populate(p4d_t *p4dp, unsigned long addr,
do {
next = pud_addr_end(addr, end);
kasan_pmd_populate(pudp, addr, next, node, early);
- } while (pudp++, addr = next, addr != end);
+ } while (pudp++, addr = next, addr != end && __pud_none(early, READ_ONCE(*pudp)));
}
static void __init kasan_p4d_populate(pgd_t *pgdp, unsigned long addr,
unsigned long end, int node, bool early)
{
unsigned long next;
- p4d_t *p4dp = p4d_offset(pgdp, addr);
+ p4d_t *p4dp = kasan_p4d_offset(pgdp, addr, node, early);
do {
next = p4d_addr_end(addr, end);
kasan_pud_populate(p4dp, addr, next, node, early);
- } while (p4dp++, addr = next, addr != end);
+ } while (p4dp++, addr = next, addr != end && __p4d_none(early, READ_ONCE(*p4dp)));
}
static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
@@ -218,7 +243,7 @@ static void __init kasan_map_populate(unsigned long start, unsigned long end,
asmlinkage void __init kasan_early_init(void)
{
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE));
- BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE));
+ BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END + 1, PGDIR_SIZE));
}
static inline void kasan_set_pgd(pgd_t *pgdp, pgd_t pgdval)
@@ -233,7 +258,7 @@ static void __init clear_pgds(unsigned long start, unsigned long end)
* swapper_pg_dir. pgd_clear() can't be used
* here because it's nop on 2,3-level pagetable setups
*/
- for (; start < end; start += PGDIR_SIZE)
+ for (; start < end; start = pgd_addr_end(start, end))
kasan_set_pgd((pgd_t *)pgd_offset_k(start), __pgd(0));
}
@@ -243,6 +268,17 @@ void __init kasan_init(void)
phys_addr_t pa_start, pa_end;
/*
+ * If PGDIR_SIZE is too large for cpu_vabits, KASAN_SHADOW_END will
+ * overflow UINTPTR_MAX and then looks like a user space address.
+ * For example, PGDIR_SIZE of CONFIG_4KB_4LEVEL is 2^39, which is too
+ * large for Loongson-2K series whose cpu_vabits = 39.
+ */
+ if (KASAN_SHADOW_END < vm_map_base) {
+ pr_warn("PGDIR_SIZE too large for cpu_vabits, KernelAddressSanitizer disabled.\n");
+ return;
+ }
+
+ /*
* PGD was populated as invalid_pmd_table or invalid_pud_table
* in pagetable_init() which depends on how many levels of page
* table you are using, but we had to clean the gpd of kasan
diff --git a/arch/loongarch/mm/pageattr.c b/arch/loongarch/mm/pageattr.c
index ffd8d76021d4..bf8678248444 100644
--- a/arch/loongarch/mm/pageattr.c
+++ b/arch/loongarch/mm/pageattr.c
@@ -216,3 +216,22 @@ int set_direct_map_invalid_noflush(struct page *page)
return __set_memory(addr, 1, __pgprot(0), __pgprot(_PAGE_PRESENT | _PAGE_VALID));
}
+
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
+{
+ unsigned long addr = (unsigned long)page_address(page);
+ pgprot_t set, clear;
+
+ if (addr < vm_map_base)
+ return 0;
+
+ if (valid) {
+ set = PAGE_KERNEL;
+ clear = __pgprot(0);
+ } else {
+ set = __pgprot(0);
+ clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID);
+ }
+
+ return __set_memory(addr, 1, set, clear);
+}
diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c
index 5ac9beb5f093..3b427b319db2 100644
--- a/arch/loongarch/mm/tlb.c
+++ b/arch/loongarch/mm/tlb.c
@@ -289,7 +289,7 @@ static void setup_tlb_handler(int cpu)
/* Avoid lockdep warning */
rcutree_report_cpu_starting(cpu);
-#ifdef CONFIG_NUMA
+#if defined(CONFIG_NUMA) && !defined(CONFIG_PREEMPT_RT)
vec_sz = sizeof(exception_handlers);
if (pcpu_handlers[cpu])
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index 7dbefd4ba210..dd350cba1252 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -179,7 +179,7 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
if (!is_tail_call) {
/* Set return value */
- move_reg(ctx, LOONGARCH_GPR_A0, regmap[BPF_REG_0]);
+ emit_insn(ctx, addiw, LOONGARCH_GPR_A0, regmap[BPF_REG_0], 0);
/* Return to the caller */
emit_insn(ctx, jirl, LOONGARCH_GPR_RA, LOONGARCH_GPR_ZERO, 0);
} else {
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
index 40c1175823d6..fdde1bcd4e26 100644
--- a/arch/loongarch/vdso/Makefile
+++ b/arch/loongarch/vdso/Makefile
@@ -19,7 +19,7 @@ ccflags-vdso := \
cflags-vdso := $(ccflags-vdso) \
-isystem $(shell $(CC) -print-file-name=include) \
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
- -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \
+ -std=gnu11 -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \
-fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
$(call cc-option, -fno-asynchronous-unwind-tables) \
$(call cc-option, -fno-stack-protector)
diff --git a/arch/loongarch/vdso/vdso.lds.S b/arch/loongarch/vdso/vdso.lds.S
index 6b441bde4026..160cfaef2de4 100644
--- a/arch/loongarch/vdso/vdso.lds.S
+++ b/arch/loongarch/vdso/vdso.lds.S
@@ -3,6 +3,8 @@
* Author: Huacai Chen <chenhuacai@loongson.cn>
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
*/
+#include <asm/page.h>
+#include <generated/asm-offsets.h>
OUTPUT_FORMAT("elf64-loongarch", "elf64-loongarch", "elf64-loongarch")
@@ -10,7 +12,11 @@ OUTPUT_ARCH(loongarch)
SECTIONS
{
- PROVIDE(_start = .);
+ PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE);
+#ifdef CONFIG_TIME_NS
+ PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
+#endif
+ PROVIDE(_loongarch_data = _vdso_data + 2 * PAGE_SIZE);
. = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
diff --git a/arch/loongarch/vdso/vgetcpu.c b/arch/loongarch/vdso/vgetcpu.c
index 9e445be39763..0db51258b2a7 100644
--- a/arch/loongarch/vdso/vgetcpu.c
+++ b/arch/loongarch/vdso/vgetcpu.c
@@ -21,7 +21,7 @@ static __always_inline int read_cpu_id(void)
static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
{
- return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE);
+ return _loongarch_data.pdata;
}
extern
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index cc26df907bfe..7c4f7bcc89d7 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -84,24 +84,23 @@ config MMU
support by paged memory management. If unsure, say 'Y'.
config MMU_MOTOROLA
- bool
+ def_bool MMU && M68KCLASSIC
select HAVE_PAGE_SIZE_4KB
config MMU_COLDFIRE
+ def_bool MMU && COLDFIRE
select HAVE_PAGE_SIZE_8KB
- bool
config MMU_SUN3
- bool
+ def_bool MMU && SUN3
select HAVE_PAGE_SIZE_8KB
- depends on MMU && !MMU_MOTOROLA && !MMU_COLDFIRE
config ARCH_SUPPORTS_KEXEC
- def_bool M68KCLASSIC && MMU
+ def_bool (M68KCLASSIC || SUN3) && MMU
config BOOTINFO_PROC
bool "Export bootinfo in procfs"
- depends on KEXEC && M68KCLASSIC
+ depends on KEXEC && (M68KCLASSIC || SUN3)
help
Say Y to export the bootinfo used to boot the kernel in a
"bootinfo" file in procfs. This is useful with kexec.
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index c777a129768a..c9a7e602d8a4 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -2,7 +2,7 @@
comment "Processor Type"
choice
- prompt "CPU family support"
+ prompt "CPU/machine family support"
default M68KCLASSIC if MMU
default COLDFIRE if !MMU
help
@@ -19,8 +19,9 @@ choice
processor, select COLDFIRE.
config M68KCLASSIC
- bool "Classic M68K CPU family support"
+ bool "Classic M68K CPU/machine family support"
select HAVE_ARCH_PFN_VALID
+ select M68020 if MMU && !(M68030 || M68040 || M68060)
config COLDFIRE
bool "Coldfire CPU family support"
@@ -32,13 +33,23 @@ config COLDFIRE
select HAVE_LEGACY_CLK
select HAVE_PAGE_SIZE_8KB if !MMU
-endchoice
+config SUN3
+ bool "Sun3 machine support"
+ depends on MMU
+ select HAVE_ARCH_PFN_VALID
+ select LEGACY_TIMER_TICK
+ select NO_DMA
+ select M68020
+ help
+ This option enables support for the Sun 3 series of workstations
+ (3/50, 3/60, 3/1xx, 3/2xx systems). These use a classic 68020 CPU
+ but the custom memory management unit makes them incompatible with
+ all other classic m68k machines, including Sun 3x.
-if M68KCLASSIC
+endchoice
config M68000
- def_bool y
- depends on !MMU
+ def_bool M68KCLASSIC && !MMU
select CPU_HAS_NO_BITFIELDS
select CPU_HAS_NO_CAS
select CPU_HAS_NO_MULDIV64
@@ -56,7 +67,7 @@ config M68000
a paging MMU.
config M68020
- bool "68020 support"
+ bool "68020 support" if M68KCLASSIC
depends on MMU
select FPU
select CPU_HAS_ADDRESS_SPACES
@@ -66,9 +77,10 @@ config M68020
68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
Sun 3, which provides its own version.
+if M68KCLASSIC && MMU
+
config M68030
bool "68030 support"
- depends on MMU && !MMU_SUN3
select FPU
select CPU_HAS_ADDRESS_SPACES
help
@@ -78,7 +90,6 @@ config M68030
config M68040
bool "68040 support"
- depends on MMU && !MMU_SUN3
select FPU
select CPU_HAS_ADDRESS_SPACES
help
@@ -89,13 +100,14 @@ config M68040
config M68060
bool "68060 support"
- depends on MMU && !MMU_SUN3
select FPU
select CPU_HAS_ADDRESS_SPACES
help
If you anticipate running this kernel on a computer with a MC68060
processor, say Y. Otherwise, say N.
+endif # M68KCLASSIC
+
config M68328
bool
depends on !MMU
@@ -117,8 +129,6 @@ config M68VZ328
help
Motorola 68VZ328 processor support.
-endif # M68KCLASSIC
-
if COLDFIRE
choice
@@ -325,7 +335,7 @@ comment "Processor Specific Options"
config M68KFPU_EMU
bool "Math emulation support"
- depends on M68KCLASSIC && FPU
+ depends on (M68KCLASSIC || SUN3) && FPU
help
At some point in the future, this will cause floating-point math
instructions to be emulated by the kernel on machines that lack a
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index d06b1c5d9b0c..de39f23b180e 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -6,7 +6,6 @@ if M68KCLASSIC
config AMIGA
bool "Amiga support"
depends on MMU
- select MMU_MOTOROLA if MMU
select LEGACY_TIMER_TICK
help
This option enables support for the Amiga series of computers. If
@@ -16,7 +15,6 @@ config AMIGA
config ATARI
bool "Atari support"
depends on MMU
- select MMU_MOTOROLA if MMU
select HAVE_ARCH_NVRAM_OPS
select LEGACY_TIMER_TICK
help
@@ -31,7 +29,6 @@ config ATARI_KBD_CORE
config MAC
bool "Macintosh support"
depends on MMU
- select MMU_MOTOROLA if MMU
select HAVE_ARCH_NVRAM_OPS
select HAVE_PATA_PLATFORM
select LEGACY_TIMER_TICK
@@ -44,7 +41,6 @@ config MAC
config APOLLO
bool "Apollo support"
depends on MMU
- select MMU_MOTOROLA if MMU
select LEGACY_TIMER_TICK
help
Say Y here if you want to run Linux on an MC680x0-based Apollo
@@ -53,7 +49,6 @@ config APOLLO
config VME
bool "VME (Motorola and BVM) support"
depends on MMU
- select MMU_MOTOROLA if MMU
help
Say Y here if you want to build a kernel for a 680x0 based VME
board. Boards currently supported include Motorola boards MVME147,
@@ -97,7 +92,6 @@ config BVME6000
config HP300
bool "HP9000/300 and HP9000/400 support"
depends on MMU
- select MMU_MOTOROLA if MMU
select LEGACY_TIMER_TICK
help
This option enables support for the HP9000/300 and HP9000/400 series
@@ -110,7 +104,6 @@ config SUN3X
bool "Sun3x support"
depends on MMU
select LEGACY_TIMER_TICK
- select MMU_MOTOROLA if MMU
select M68030
help
This option enables support for the Sun 3x series of workstations.
@@ -124,7 +117,6 @@ config SUN3X
config Q40
bool "Q40/Q60 support"
depends on MMU
- select MMU_MOTOROLA if MMU
select LEGACY_TIMER_TICK
help
The Q40 is a Motorola 68040-based successor to the Sinclair QL
@@ -133,22 +125,6 @@ config Q40
Q60. Select your CPU below. For 68LC060 don't forget to enable FPU
emulation.
-config SUN3
- bool "Sun3 support"
- depends on MMU
- depends on !MMU_MOTOROLA
- select MMU_SUN3 if MMU
- select LEGACY_TIMER_TICK
- select NO_DMA
- select M68020
- help
- This option enables support for the Sun 3 series of workstations
- (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
- that all other hardware types must be disabled, as Sun 3 kernels
- are incompatible with all other m68k targets (including Sun 3x!).
-
- If you don't want to compile a kernel exclusively for a Sun 3, say N.
-
config VIRT
bool "Virtual M68k Machine support"
depends on MMU
@@ -157,7 +133,6 @@ config VIRT
select GOLDFISH_TIMER
select GOLDFISH_TTY
select M68040
- select MMU_MOTOROLA if MMU
select RTC_CLASS
select RTC_DRV_GOLDFISH
select TTY
diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c
index 7dab46728aed..b6958ec2a220 100644
--- a/arch/m68k/coldfire/device.c
+++ b/arch/m68k/coldfire/device.c
@@ -93,7 +93,7 @@ static struct platform_device mcf_uart = {
.dev.platform_data = mcf_uart_platform_data,
};
-#if IS_ENABLED(CONFIG_FEC)
+#ifdef MCFFEC_BASE0
#ifdef CONFIG_M5441x
#define FEC_NAME "enet-fec"
@@ -145,6 +145,7 @@ static struct platform_device mcf_fec0 = {
.platform_data = FEC_PDATA,
}
};
+#endif /* MCFFEC_BASE0 */
#ifdef MCFFEC_BASE1
static struct resource mcf_fec1_resources[] = {
@@ -182,7 +183,6 @@ static struct platform_device mcf_fec1 = {
}
};
#endif /* MCFFEC_BASE1 */
-#endif /* CONFIG_FEC */
#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
/*
@@ -624,12 +624,12 @@ static struct platform_device mcf_flexcan0 = {
static struct platform_device *mcf_devices[] __initdata = {
&mcf_uart,
-#if IS_ENABLED(CONFIG_FEC)
+#ifdef MCFFEC_BASE0
&mcf_fec0,
+#endif
#ifdef MCFFEC_BASE1
&mcf_fec1,
#endif
-#endif
#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
&mcf_qspi,
#endif
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index d01dc47d52ea..c705247e7b5b 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -449,7 +449,6 @@ CONFIG_RTC_DRV_RP5C01=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -620,6 +619,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 46808e581d7b..6d62b9187a58 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -406,7 +406,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -577,6 +576,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 4469a7839c9d..c3c644df852d 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -426,7 +426,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -597,6 +596,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index c0719322c028..20261f819691 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -398,7 +398,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -569,6 +568,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 8d429e63f8f2..ce4fe93a0f70 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -408,7 +408,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -579,6 +578,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index bafd33da27c1..040ae75f47c3 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -425,7 +425,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -596,6 +595,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 6f5ca3f85ea1..20d877cb4e30 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -503,6 +503,7 @@ CONFIG_UHID=m
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
# CONFIG_RTC_NVMEM is not set
+CONFIG_RTC_DRV_M48T59=m
CONFIG_RTC_DRV_MSM6242=m
CONFIG_RTC_DRV_RP5C01=m
CONFIG_RTC_DRV_GENERIC=m
@@ -511,7 +512,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -682,6 +682,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index d16b328c7136..5e1c8d0d3da5 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -391,13 +391,13 @@ CONFIG_UHID=m
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
# CONFIG_RTC_NVMEM is not set
+CONFIG_RTC_DRV_M48T59=y
CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -568,6 +568,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 80f6c15a5ed5..5d1409e6a137 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -392,13 +392,13 @@ CONFIG_UHID=m
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
# CONFIG_RTC_NVMEM is not set
+CONFIG_RTC_DRV_M48T59=y
CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -569,6 +569,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 0e81589f0ee2..e4c30e2b9bbb 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -415,7 +415,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -586,6 +585,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 8cd785290339..980843a9ea1e 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -396,7 +396,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -566,6 +565,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 78035369f60f..38681cc6b598 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -396,7 +396,6 @@ CONFIG_RTC_DRV_GENERIC=m
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_DAX=m
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=m
CONFIG_JFS_FS=m
CONFIG_OCFS2_FS=m
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
@@ -567,6 +566,7 @@ CONFIG_KUNIT_ALL_TESTS=m
CONFIG_TEST_DHRY=m
CONFIG_TEST_MIN_HEAP=m
CONFIG_TEST_DIV64=m
+CONFIG_TEST_MULDIV64=m
CONFIG_REED_SOLOMON_TEST=m
CONFIG_ATOMIC64_SELFTEST=m
CONFIG_ASYNC_RAID6_TEST=m
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 0dbf9c5c6fae..b282e0dd8dc1 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -4,3 +4,4 @@ generic-y += extable.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += spinlock.h
+generic-y += text-patching.h
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index 14992fde7340..2263e92d418a 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -28,10 +28,8 @@
#define NR_IRQS 32
#elif defined(CONFIG_APOLLO)
#define NR_IRQS 24
-#elif defined(CONFIG_HP300)
+#else /* CONFIG_HP300 etc. */
#define NR_IRQS 8
-#else
-#define NR_IRQS 0
#endif
#if defined(CONFIG_M68020) || defined(CONFIG_M68030) || \
diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h
index 019f24439546..9c91ecdafc45 100644
--- a/arch/m68k/include/asm/mcfgpio.h
+++ b/arch/m68k/include/asm/mcfgpio.h
@@ -136,7 +136,7 @@ static inline void gpio_free(unsigned gpio)
* read-modify-write as well as those controlled by the EPORT and GPIO modules.
*/
#define MCFGPIO_SCR_START 40
-#elif defined(CONFIGM5441x)
+#elif defined(CONFIG_M5441x)
/* The m5441x EPORT doesn't have its own GPIO port, uses PORT C */
#define MCFGPIO_SCR_START 0
#else
diff --git a/arch/m68k/include/asm/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h
index e28eb1c0e0bf..6ad93bac06f9 100644
--- a/arch/m68k/include/asm/mvme147hw.h
+++ b/arch/m68k/include/asm/mvme147hw.h
@@ -4,24 +4,7 @@
#include <asm/irq.h>
-typedef struct {
- unsigned char
- ctrl,
- bcd_sec,
- bcd_min,
- bcd_hr,
- bcd_dow,
- bcd_dom,
- bcd_mth,
- bcd_year;
-} MK48T02;
-
-#define RTC_WRITE 0x80
-#define RTC_READ 0x40
-#define RTC_STOP 0x20
-
-#define m147_rtc ((MK48T02 * volatile)0xfffe07f8)
-
+#define MVME147_RTC_BASE 0xfffe0000
struct pcc_regs {
volatile u_long dma_tadr;
@@ -93,8 +76,8 @@ struct pcc_regs {
#define M147_SCC_B_ADDR 0xfffe3000
#define M147_SCC_PCLK 5000000
-#define MVME147_IRQ_SCSI_PORT (IRQ_USER+0x45)
-#define MVME147_IRQ_SCSI_DMA (IRQ_USER+0x46)
+#define MVME147_IRQ_SCSI_PORT (IRQ_USER + 5)
+#define MVME147_IRQ_SCSI_DMA (IRQ_USER + 6)
/* SCC interrupts, for MVME147 */
diff --git a/arch/m68k/include/asm/mvme16xhw.h b/arch/m68k/include/asm/mvme16xhw.h
index cc7f5ae1220f..ff1126a51fbe 100644
--- a/arch/m68k/include/asm/mvme16xhw.h
+++ b/arch/m68k/include/asm/mvme16xhw.h
@@ -24,23 +24,7 @@ typedef struct {
#define mvmelp ((*(volatile MVMElpPtr)(MVME_LPR_BASE)))
-typedef struct {
- unsigned char
- ctrl,
- bcd_sec,
- bcd_min,
- bcd_hr,
- bcd_dow,
- bcd_dom,
- bcd_mth,
- bcd_year;
-} MK48T08_t, *MK48T08ptr_t;
-
-#define RTC_WRITE 0x80
-#define RTC_READ 0x40
-#define RTC_STOP 0x20
-
-#define MVME_RTC_BASE 0xfffc1ff8
+#define MVME_RTC_BASE 0xfffc0000
#define MVME_I596_BASE 0xfff46000
diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
index 8cfb84b49975..b173ba27d36f 100644
--- a/arch/m68k/include/asm/page.h
+++ b/arch/m68k/include/asm/page.h
@@ -6,10 +6,8 @@
#include <asm/setup.h>
#include <asm/page_offset.h>
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
+
#define PAGE_OFFSET (PAGE_OFFSET_RAW)
#ifndef __ASSEMBLY__
diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h
index af3a10973233..63c0e706084b 100644
--- a/arch/m68k/include/asm/page_no.h
+++ b/arch/m68k/include/asm/page_no.h
@@ -14,7 +14,7 @@ extern unsigned long memory_end;
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
#define vma_alloc_zeroed_movable_folio(vma, vaddr) \
- vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr, false)
+ vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr)
#define __pa(vaddr) ((unsigned long)(vaddr))
#define __va(paddr) ((void *)((unsigned long)(paddr)))
diff --git a/arch/m68k/include/asm/virtconvert.h b/arch/m68k/include/asm/virtconvert.h
index 0a27905b0036..32e27bddb7d4 100644
--- a/arch/m68k/include/asm/virtconvert.h
+++ b/arch/m68k/include/asm/virtconvert.h
@@ -28,9 +28,6 @@ static inline void *phys_to_virt(unsigned long address)
return __va(address);
}
-/* Permanent address of a page. */
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-
/*
* IO bus memory addresses are 1:1 with the physical address,
* deprecated globally but still used on two machines.
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index f335bf3268a1..6c732ed3998b 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -5,16 +5,8 @@
extra-y += vmlinux.lds
-obj-$(CONFIG_AMIGA) := head.o
-obj-$(CONFIG_ATARI) := head.o
-obj-$(CONFIG_MAC) := head.o
-obj-$(CONFIG_APOLLO) := head.o
-obj-$(CONFIG_VME) := head.o
-obj-$(CONFIG_HP300) := head.o
-obj-$(CONFIG_Q40) := head.o
-obj-$(CONFIG_SUN3X) := head.o
-obj-$(CONFIG_VIRT) := head.o
-obj-$(CONFIG_SUN3) := sun3-head.o
+obj-$(CONFIG_MMU_MOTOROLA) := head.o
+obj-$(CONFIG_SUN3) := sun3-head.o
obj-y += entry.o irq.o module.o process.o ptrace.o
obj-y += setup.o signal.o sys_m68k.o syscalltable.o time.o traps.o
diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c
index 3cc944df04f6..f11ef9f1f56f 100644
--- a/arch/m68k/kernel/early_printk.c
+++ b/arch/m68k/kernel/early_printk.c
@@ -13,6 +13,7 @@
#include <asm/setup.h>
+#include "../mvme147/mvme147.h"
#include "../mvme16x/mvme16x.h"
asmlinkage void __init debug_cons_nputs(const char *s, unsigned n);
@@ -22,7 +23,9 @@ static void __ref debug_cons_write(struct console *c,
{
#if !(defined(CONFIG_SUN3) || defined(CONFIG_M68000) || \
defined(CONFIG_COLDFIRE))
- if (MACH_IS_MVME16x)
+ if (MACH_IS_MVME147)
+ mvme147_scc_write(c, s, n);
+ else if (MACH_IS_MVME16x)
mvme16x_cons_write(c, s, n);
else
debug_cons_nputs(s, n);
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index 10310b04f77d..15c1a595a1de 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -249,7 +249,11 @@ void __init setup_arch(char **cmdline_p)
process_uboot_commandline(&m68k_command_line[0], CL_SIZE);
*cmdline_p = m68k_command_line;
memcpy(boot_command_line, *cmdline_p, CL_SIZE);
-
+ /*
+ * Initialise the static keys early as they may be enabled by the
+ * cpufeature code and early parameters.
+ */
+ jump_label_init();
parse_early_param();
switch (m68k_machtype) {
diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
index 22a3cbd4c602..f5ed71f1910d 100644
--- a/arch/m68k/kernel/syscalls/syscall.tbl
+++ b/arch/m68k/kernel/syscalls/syscall.tbl
@@ -462,3 +462,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index a97600b2af50..acd4c2da562b 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -62,7 +62,7 @@ void timer_heartbeat(void)
}
#endif /* CONFIG_HEARTBEAT */
-#ifdef CONFIG_M68KCLASSIC
+#if defined(CONFIG_M68KCLASSIC) || defined(CONFIG_SUN3)
/* machine dependent timer functions */
int (*mach_hwclk) (int, struct rtc_time*);
EXPORT_SYMBOL(mach_hwclk);
@@ -149,7 +149,7 @@ static int __init rtc_init(void)
module_init(rtc_init);
#endif /* CONFIG_RTC_DRV_GENERIC */
-#endif /* CONFIG M68KCLASSIC */
+#endif /* CONFIG_M68KCLASSIC || SUN3 */
void __init time_init(void)
{
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 53d0cf343d90..d2f25e8895e5 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -383,7 +383,7 @@ static inline void bus_error030 (struct frame *fp)
fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
if (ssw & DF)
pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
+ str_read_write(ssw & RW),
fp->un.fmtb.daddr,
space_names[ssw & DFC], fp->ptregs.pc);
@@ -419,7 +419,7 @@ static inline void bus_error030 (struct frame *fp)
}
pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
+ str_read_write(ssw & RW),
fp->un.fmtb.daddr,
space_names[ssw & DFC], fp->ptregs.pc);
}
@@ -455,7 +455,7 @@ static inline void bus_error030 (struct frame *fp)
pr_debug("*** unexpected busfault type=%#04x\n",
buserr_type);
pr_debug("invalid %s access at %#lx from pc %#lx\n",
- !(ssw & RW) ? "write" : "read", addr,
+ str_read_write(ssw & RW), addr,
fp->ptregs.pc);
die_if_kernel ("Oops", &fp->ptregs, buserr_type);
force_sig (SIGBUS);
@@ -514,7 +514,7 @@ static inline void bus_error030 (struct frame *fp)
fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
if (ssw & DF)
pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
+ str_read_write(ssw & RW),
fp->un.fmtb.daddr,
space_names[ssw & DFC], fp->ptregs.pc);
@@ -548,7 +548,7 @@ static inline void bus_error030 (struct frame *fp)
/* We might have an exception table for this PC */
if (ssw & 4 && !search_exception_tables(fp->ptregs.pc)) {
pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
+ str_read_write(ssw & RW),
fp->un.fmtb.daddr,
space_names[ssw & DFC], fp->ptregs.pc);
goto buserr;
@@ -564,7 +564,7 @@ static inline void bus_error030 (struct frame *fp)
mmusr);
} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
pr_err("invalid %s access at %#lx from pc %#lx\n",
- !(ssw & RW) ? "write" : "read", addr,
+ str_read_write(ssw & RW), addr,
fp->ptregs.pc);
die_if_kernel("Oops",&fp->ptregs,mmusr);
force_sig(SIGSEGV);
@@ -575,7 +575,7 @@ static inline void bus_error030 (struct frame *fp)
#endif
pr_err("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
- !(ssw & RW) ? "write" : "read", addr,
+ str_read_write(ssw & RW), addr,
fp->ptregs.pc, ssw);
asm volatile ("ptestr #1,%1@,#0\n\t"
"pmove %%psr,%0"
@@ -991,7 +991,7 @@ static void bad_super_trap(struct frame *fp)
fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
if (ssw & DF)
pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
- ssw & RW ? "read" : "write",
+ str_read_write(ssw & RW),
fp->un.fmtb.daddr, space_names[ssw & DFC],
fp->ptregs.pc);
}
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 8b5dc07f0811..3054d3857efa 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -19,8 +19,9 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/major.h>
-#include <linux/rtc.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/rtc/m48t59.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo-vme.h>
@@ -32,16 +33,13 @@
#include <asm/mvme147hw.h>
#include <asm/config.h>
+#include "mvme147.h"
static void mvme147_get_model(char *model);
-extern void mvme147_sched_init(void);
-extern int mvme147_hwclk (int, struct rtc_time *);
+static void __init mvme147_sched_init(void);
extern void mvme147_reset (void);
-static int bcd2int (unsigned char b);
-
-
int __init mvme147_parse_bootinfo(const struct bi_record *bi)
{
uint16_t tag = be16_to_cpu(bi->tag);
@@ -79,7 +77,6 @@ void __init config_mvme147(void)
{
mach_sched_init = mvme147_sched_init;
mach_init_IRQ = mvme147_init_IRQ;
- mach_hwclk = mvme147_hwclk;
mach_reset = mvme147_reset;
mach_get_model = mvme147_get_model;
@@ -88,6 +85,28 @@ void __init config_mvme147(void)
vme_brdtype = VME_TYPE_MVME147;
}
+static struct resource m48t59_rsrc[] = {
+ DEFINE_RES_MEM(MVME147_RTC_BASE, 0x800),
+};
+
+static struct m48t59_plat_data m48t59_data = {
+ .type = M48T59RTC_TYPE_M48T02,
+ .yy_offset = 70,
+};
+
+static int __init mvme147_platform_init(void)
+{
+ if (!MACH_IS_MVME147)
+ return 0;
+
+ platform_device_register_resndata(NULL, "rtc-m48t59", -1,
+ m48t59_rsrc, ARRAY_SIZE(m48t59_rsrc),
+ &m48t59_data, sizeof(m48t59_data));
+ return 0;
+}
+
+arch_initcall(mvme147_platform_init);
+
static u64 mvme147_read_clk(struct clocksource *cs);
static struct clocksource mvme147_clk = {
@@ -123,7 +142,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
}
-void mvme147_sched_init (void)
+static void __init mvme147_sched_init(void)
{
if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQF_TIMER,
"timer 1", NULL))
@@ -161,27 +180,31 @@ static u64 mvme147_read_clk(struct clocksource *cs)
return ticks;
}
-static int bcd2int (unsigned char b)
+static void scc_delay(void)
+{
+ __asm__ __volatile__ ("nop; nop;");
+}
+
+static void scc_write(char ch)
{
- return ((b>>4)*10 + (b&15));
+ do {
+ scc_delay();
+ } while (!(in_8(M147_SCC_A_ADDR) & BIT(2)));
+ scc_delay();
+ out_8(M147_SCC_A_ADDR, 8);
+ scc_delay();
+ out_8(M147_SCC_A_ADDR, ch);
}
-int mvme147_hwclk(int op, struct rtc_time *t)
+void mvme147_scc_write(struct console *co, const char *str, unsigned int count)
{
- if (!op) {
- m147_rtc->ctrl = RTC_READ;
- t->tm_year = bcd2int (m147_rtc->bcd_year);
- t->tm_mon = bcd2int(m147_rtc->bcd_mth) - 1;
- t->tm_mday = bcd2int (m147_rtc->bcd_dom);
- t->tm_hour = bcd2int (m147_rtc->bcd_hr);
- t->tm_min = bcd2int (m147_rtc->bcd_min);
- t->tm_sec = bcd2int (m147_rtc->bcd_sec);
- m147_rtc->ctrl = 0;
- if (t->tm_year < 70)
- t->tm_year += 100;
- } else {
- /* FIXME Setting the time is not yet supported */
- return -EOPNOTSUPP;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ while (count--) {
+ if (*str == '\n')
+ scc_write('\r');
+ scc_write(*str++);
}
- return 0;
+ local_irq_restore(flags);
}
diff --git a/arch/m68k/mvme147/mvme147.h b/arch/m68k/mvme147/mvme147.h
new file mode 100644
index 000000000000..140bc98b0102
--- /dev/null
+++ b/arch/m68k/mvme147/mvme147.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+struct console;
+
+/* config.c */
+void mvme147_scc_write(struct console *co, const char *str, unsigned int count);
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index a8a368c2cbea..02f9e4ad8209 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -3,4 +3,4 @@
# Makefile for Linux arch/m68k/mvme16x source directory
#
-obj-y := config.o rtc.o
+obj-y := config.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index d1fbd1704d65..99768fe8da73 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -21,9 +21,10 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/major.h>
-#include <linux/rtc.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc/m48t59.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo-vme.h>
@@ -39,16 +40,10 @@
extern t_bdid mvme_bdid;
-static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
-
static void mvme16x_get_model(char *model);
extern void mvme16x_sched_init(void);
-extern int mvme16x_hwclk (int, struct rtc_time *);
extern void mvme16x_reset (void);
-int bcd2int (unsigned char b);
-
-
unsigned short mvme16x_config;
EXPORT_SYMBOL(mvme16x_config);
@@ -268,7 +263,6 @@ void __init config_mvme16x(void)
mach_sched_init = mvme16x_sched_init;
mach_init_IRQ = mvme16x_init_IRQ;
- mach_hwclk = mvme16x_hwclk;
mach_reset = mvme16x_reset;
mach_get_model = mvme16x_get_model;
mach_get_hardware_list = mvme16x_get_hardware_list;
@@ -312,6 +306,28 @@ void __init config_mvme16x(void)
}
}
+static struct resource m48t59_rsrc[] = {
+ DEFINE_RES_MEM(MVME_RTC_BASE, 0x2000),
+};
+
+static struct m48t59_plat_data m48t59_data = {
+ .type = M48T59RTC_TYPE_M48T08,
+ .yy_offset = 70,
+};
+
+static int __init mvme16x_platform_init(void)
+{
+ if (!MACH_IS_MVME16x)
+ return 0;
+
+ platform_device_register_resndata(NULL, "rtc-m48t59", -1,
+ m48t59_rsrc, ARRAY_SIZE(m48t59_rsrc),
+ &m48t59_data, sizeof(m48t59_data));
+ return 0;
+}
+
+arch_initcall(mvme16x_platform_init);
+
static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
{
unsigned long *new = (unsigned long *)vectors;
@@ -426,28 +442,3 @@ static u64 mvme16x_read_clk(struct clocksource *cs)
return ticks;
}
-
-int bcd2int (unsigned char b)
-{
- return ((b>>4)*10 + (b&15));
-}
-
-int mvme16x_hwclk(int op, struct rtc_time *t)
-{
- if (!op) {
- rtc->ctrl = RTC_READ;
- t->tm_year = bcd2int (rtc->bcd_year);
- t->tm_mon = bcd2int(rtc->bcd_mth) - 1;
- t->tm_mday = bcd2int (rtc->bcd_dom);
- t->tm_hour = bcd2int (rtc->bcd_hr);
- t->tm_min = bcd2int (rtc->bcd_min);
- t->tm_sec = bcd2int (rtc->bcd_sec);
- rtc->ctrl = 0;
- if (t->tm_year < 70)
- t->tm_year += 100;
- } else {
- /* FIXME Setting the time is not yet supported */
- return -EOPNOTSUPP;
- }
- return 0;
-}
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
deleted file mode 100644
index ccbaae1125e6..000000000000
--- a/arch/m68k/mvme16x/rtc.c
+++ /dev/null
@@ -1,165 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Real Time Clock interface for Linux on the MVME16x
- *
- * Based on the PC driver by Paul Gortmaker.
- */
-
-#define RTC_VERSION "1.00"
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/ioport.h>
-#include <linux/capability.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/rtc.h> /* For struct rtc_time and ioctls, etc */
-#include <linux/bcd.h>
-#include <asm/mvme16xhw.h>
-
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <asm/setup.h>
-
-/*
- * We sponge a minor off of the misc major. No need slurping
- * up another valuable major dev number for this. If you add
- * an ioctl, make sure you don't conflict with SPARC's RTC
- * ioctls.
- */
-
-static const unsigned char days_in_mo[] =
-{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-static atomic_t rtc_ready = ATOMIC_INIT(1);
-
-static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE;
- unsigned long flags;
- struct rtc_time wtime;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
- case RTC_RD_TIME: /* Read the time/date from RTC */
- {
- local_irq_save(flags);
- /* Ensure clock and real-time-mode-register are accessible */
- rtc->ctrl = RTC_READ;
- memset(&wtime, 0, sizeof(struct rtc_time));
- wtime.tm_sec = bcd2bin(rtc->bcd_sec);
- wtime.tm_min = bcd2bin(rtc->bcd_min);
- wtime.tm_hour = bcd2bin(rtc->bcd_hr);
- wtime.tm_mday = bcd2bin(rtc->bcd_dom);
- wtime.tm_mon = bcd2bin(rtc->bcd_mth)-1;
- wtime.tm_year = bcd2bin(rtc->bcd_year);
- if (wtime.tm_year < 70)
- wtime.tm_year += 100;
- wtime.tm_wday = bcd2bin(rtc->bcd_dow)-1;
- rtc->ctrl = 0;
- local_irq_restore(flags);
- return copy_to_user(argp, &wtime, sizeof wtime) ?
- -EFAULT : 0;
- }
- case RTC_SET_TIME: /* Set the RTC */
- {
- struct rtc_time rtc_tm;
- unsigned char mon, day, hrs, min, sec, leap_yr;
- unsigned int yrs;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time)))
- return -EFAULT;
-
- yrs = rtc_tm.tm_year;
- if (yrs < 1900)
- yrs += 1900;
- mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
- day = rtc_tm.tm_mday;
- hrs = rtc_tm.tm_hour;
- min = rtc_tm.tm_min;
- sec = rtc_tm.tm_sec;
-
- leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
-
- if ((mon > 12) || (day == 0))
- return -EINVAL;
-
- if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
- return -EINVAL;
-
- if ((hrs >= 24) || (min >= 60) || (sec >= 60))
- return -EINVAL;
-
- if (yrs >= 2070)
- return -EINVAL;
-
- local_irq_save(flags);
- rtc->ctrl = RTC_WRITE;
-
- rtc->bcd_sec = bin2bcd(sec);
- rtc->bcd_min = bin2bcd(min);
- rtc->bcd_hr = bin2bcd(hrs);
- rtc->bcd_dom = bin2bcd(day);
- rtc->bcd_mth = bin2bcd(mon);
- rtc->bcd_year = bin2bcd(yrs%100);
-
- rtc->ctrl = 0;
- local_irq_restore(flags);
- return 0;
- }
- default:
- return -EINVAL;
- }
-}
-
-/*
- * We enforce only one user at a time here with the open/close.
- */
-static int rtc_open(struct inode *inode, struct file *file)
-{
- if( !atomic_dec_and_test(&rtc_ready) )
- {
- atomic_inc( &rtc_ready );
- return -EBUSY;
- }
- return 0;
-}
-
-static int rtc_release(struct inode *inode, struct file *file)
-{
- atomic_inc( &rtc_ready );
- return 0;
-}
-
-/*
- * The various file operations we support.
- */
-
-static const struct file_operations rtc_fops = {
- .unlocked_ioctl = rtc_ioctl,
- .open = rtc_open,
- .release = rtc_release,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice rtc_dev=
-{
- .minor = RTC_MINOR,
- .name = "rtc",
- .fops = &rtc_fops
-};
-
-static int __init rtc_MK48T08_init(void)
-{
- if (!MACH_IS_MVME16x)
- return -ENODEV;
-
- pr_info("MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION);
- return misc_register(&rtc_dev);
-}
-device_initcall(rtc_MK48T08_init);
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index a055f5dbe00a..7178f990e8b3 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += parport.h
generic-y += syscalls.h
generic-y += tlb.h
generic-y += user.h
+generic-y += text-patching.h
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h
index 8810f4f1c3b0..90fc9c81debd 100644
--- a/arch/microblaze/include/asm/page.h
+++ b/arch/microblaze/include/asm/page.h
@@ -19,10 +19,7 @@
#ifdef __KERNEL__
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#define LOAD_OFFSET ASM_CONST((CONFIG_KERNEL_START-CONFIG_KERNEL_BASE_ADDR))
@@ -101,7 +98,6 @@ extern int page_is_ram(unsigned long pfn);
# define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
# define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
-# define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)
# endif /* __ASSEMBLY__ */
diff --git a/arch/microblaze/include/uapi/asm/setup.h b/arch/microblaze/include/uapi/asm/setup.h
index 6831794e6f2c..16c56807f86a 100644
--- a/arch/microblaze/include/uapi/asm/setup.h
+++ b/arch/microblaze/include/uapi/asm/setup.h
@@ -14,7 +14,4 @@
#define COMMAND_LINE_SIZE 256
-# ifndef __ASSEMBLY__
-
-# endif /* __ASSEMBLY__ */
#endif /* _UAPI_ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index 9581d194d9e4..37cb2898216b 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -66,10 +66,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
" MSR:\t\t%s\n"
" PCMP:\t\t%s\n"
" DIV:\t\t%s\n",
- (cpuinfo.use_instr & PVR0_USE_BARREL_MASK) ? "yes" : "no",
- (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) ? "yes" : "no",
- (cpuinfo.use_instr & PVR2_USE_PCMP_INSTR) ? "yes" : "no",
- (cpuinfo.use_instr & PVR0_USE_DIV_MASK) ? "yes" : "no");
+ str_yes_no(cpuinfo.use_instr & PVR0_USE_BARREL_MASK),
+ str_yes_no(cpuinfo.use_instr & PVR2_USE_MSR_INSTR),
+ str_yes_no(cpuinfo.use_instr & PVR2_USE_PCMP_INSTR),
+ str_yes_no(cpuinfo.use_instr & PVR0_USE_DIV_MASK));
seq_printf(m, " MMU:\t\t%x\n", cpuinfo.mmu);
@@ -120,7 +120,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m,
"HW-Debug:\t%s\n",
- cpuinfo.hw_debug ? "yes" : "no");
+ str_yes_no(cpuinfo.hw_debug));
seq_printf(m,
"PVR-USR1:\t%02x\n"
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
index c892e173ec99..a8553f54152b 100644
--- a/arch/microblaze/kernel/microblaze_ksyms.c
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -16,6 +16,7 @@
#include <asm/page.h>
#include <linux/ftrace.h>
#include <linux/uaccess.h>
+#include <asm/xilinx_mb_manager.h>
#ifdef CONFIG_FUNCTION_TRACER
extern void _mcount(void);
@@ -46,3 +47,12 @@ extern void __udivsi3(void);
EXPORT_SYMBOL(__udivsi3);
extern void __umodsi3(void);
EXPORT_SYMBOL(__umodsi3);
+
+#ifdef CONFIG_MB_MANAGER
+extern void xmb_manager_register(uintptr_t phys_baseaddr, u32 cr_val,
+ void (*callback)(void *data),
+ void *priv, void (*reset_callback)(void *data));
+EXPORT_SYMBOL(xmb_manager_register);
+extern asmlinkage void xmb_inject_err(void);
+EXPORT_SYMBOL(xmb_inject_err);
+#endif
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index e424c796e297..76ac4cfdfb42 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -18,7 +18,7 @@ void __init early_init_devtree(void *params)
{
pr_debug(" -> early_init_devtree(%p)\n", params);
- early_init_dt_scan(params);
+ early_init_dt_scan(params, __pa(params));
if (!strlen(boot_command_line))
strscpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
index 2b81a6bd78b2..680f568b77f2 100644
--- a/arch/microblaze/kernel/syscalls/syscall.tbl
+++ b/arch/microblaze/kernel/syscalls/syscall.tbl
@@ -468,3 +468,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 397edf05dd72..467b10f4361a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2876,6 +2876,9 @@ config ARCH_SUPPORTS_KEXEC
config ARCH_SUPPORTS_CRASH_DUMP
def_bool y
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
config PHYSICAL_START
hex "Physical address where the kernel is loaded"
default "0xffffffff84000000"
diff --git a/arch/mips/boot/dts/brcm/bcm6358.dtsi b/arch/mips/boot/dts/brcm/bcm6358.dtsi
index 777c4379ed03..5e487f66c343 100644
--- a/arch/mips/boot/dts/brcm/bcm6358.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm6358.dtsi
@@ -13,6 +13,7 @@
#size-cells = <0>;
mips-hpt-frequency = <150000000>;
+ brcm,bmips-cbr-reg = <0xff400000>;
cpu@0 {
compatible = "brcm,bmips4350";
diff --git a/arch/mips/boot/dts/brcm/bcm6368.dtsi b/arch/mips/boot/dts/brcm/bcm6368.dtsi
index fc15e200877d..087f3295a14b 100644
--- a/arch/mips/boot/dts/brcm/bcm6368.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm6368.dtsi
@@ -13,6 +13,7 @@
#size-cells = <0>;
mips-hpt-frequency = <200000000>;
+ brcm,bmips-cbr-reg = <0xff400000>;
cpu@0 {
compatible = "brcm,bmips4350";
diff --git a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
index cce9428afc41..ee71045883e7 100644
--- a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
+++ b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
@@ -70,7 +70,6 @@
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
- #interrupt-cells = <2>;
msi-parent = <&msi>;
reg = <0 0x1a000000 0 0x02000000>,
@@ -234,7 +233,7 @@
};
};
- pci_bridge@9,0 {
+ pcie@9,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -244,12 +243,16 @@
interrupts = <32 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 32 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@a,0 {
+ pcie@a,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -259,12 +262,16 @@
interrupts = <33 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 33 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@b,0 {
+ pcie@b,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -274,12 +281,16 @@
interrupts = <34 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 34 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@c,0 {
+ pcie@c,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -289,12 +300,16 @@
interrupts = <35 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 35 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@d,0 {
+ pcie@d,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -304,12 +319,16 @@
interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 36 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@e,0 {
+ pcie@e,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -319,12 +338,16 @@
interrupts = <37 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 37 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@f,0 {
+ pcie@f,0 {
compatible = "pci0014,7a29.1",
"pci0014,7a29",
"pciclass060400",
@@ -334,12 +357,16 @@
interrupts = <40 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 40 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@10,0 {
+ pcie@10,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -349,12 +376,16 @@
interrupts = <41 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 41 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@11,0 {
+ pcie@11,0 {
compatible = "pci0014,7a29.1",
"pci0014,7a29",
"pciclass060400",
@@ -364,12 +395,16 @@
interrupts = <42 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 42 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@12,0 {
+ pcie@12,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -379,12 +414,16 @@
interrupts = <43 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 43 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@13,0 {
+ pcie@13,0 {
compatible = "pci0014,7a29.1",
"pci0014,7a29",
"pciclass060400",
@@ -394,12 +433,16 @@
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 38 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@14,0 {
+ pcie@14,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -409,9 +452,13 @@
interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 39 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
};
diff --git a/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi b/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi
deleted file mode 100644
index 17a342cc744e..000000000000
--- a/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi
+++ /dev/null
@@ -1,270 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-/*
- * Copyright 2023 Mobileye Vision Technologies Ltd.
- */
-
-#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
-
-/ {
- /* Fixed clock */
- xtal: xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <30000000>;
- };
-
-/* PLL_CPU derivatives */
- occ_cpu: occ-cpu {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_CPU>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- si_css0_ref_clk: si-css0-ref-clk { /* gate ClkRstGen_si_css0_ref */
- compatible = "fixed-factor-clock";
- clocks = <&occ_cpu>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- cpc_clk: cpc-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core0_clk: core0-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core1_clk: core1-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core2_clk: core2-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core3_clk: core3-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- cm_clk: cm-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- mem_clk: mem-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- occ_isram: occ-isram {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_CPU>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
- isram_clk: isram-clk { /* gate ClkRstGen_isram */
- compatible = "fixed-factor-clock";
- clocks = <&occ_isram>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- occ_dbu: occ-dbu {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_CPU>;
- #clock-cells = <0>;
- clock-div = <10>;
- clock-mult = <1>;
- };
- si_dbu_tp_pclk: si-dbu-tp-pclk { /* gate ClkRstGen_dbu */
- compatible = "fixed-factor-clock";
- clocks = <&occ_dbu>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
-/* PLL_VDI derivatives */
- occ_vdi: occ-vdi {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_VDI>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
- vdi_clk: vdi-clk { /* gate ClkRstGen_vdi */
- compatible = "fixed-factor-clock";
- clocks = <&occ_vdi>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- occ_can_ser: occ-can-ser {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_VDI>;
- #clock-cells = <0>;
- clock-div = <16>;
- clock-mult = <1>;
- };
- can_ser_clk: can-ser-clk { /* gate ClkRstGen_can_ser */
- compatible = "fixed-factor-clock";
- clocks = <&occ_can_ser>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- i2c_ser_clk: i2c-ser-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_VDI>;
- #clock-cells = <0>;
- clock-div = <20>;
- clock-mult = <1>;
- };
-/* PLL_PER derivatives */
- occ_periph: occ-periph {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <16>;
- clock-mult = <1>;
- };
- periph_clk: periph-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- can_clk: can-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- spi_clk: spi-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- uart_clk: uart-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- i2c_clk: i2c-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "i2c_clk";
- };
- timer_clk: timer-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "timer_clk";
- };
- gpio_clk: gpio-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "gpio_clk";
- };
- emmc_sys_clk: emmc-sys-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <10>;
- clock-mult = <1>;
- clock-output-names = "emmc_sys_clk";
- };
- ccf_ctrl_clk: ccf-ctrl-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <4>;
- clock-mult = <1>;
- clock-output-names = "ccf_ctrl_clk";
- };
- occ_mjpeg_core: occ-mjpeg-core {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- clock-output-names = "occ_mjpeg_core";
- };
- hsm_clk: hsm-clk { /* gate ClkRstGen_hsm */
- compatible = "fixed-factor-clock";
- clocks = <&occ_mjpeg_core>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "hsm_clk";
- };
- mjpeg_core_clk: mjpeg-core-clk { /* gate ClkRstGen_mjpeg_gen */
- compatible = "fixed-factor-clock";
- clocks = <&occ_mjpeg_core>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "mjpeg_core_clk";
- };
- fcmu_a_clk: fcmu-a-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <20>;
- clock-mult = <1>;
- clock-output-names = "fcmu_a_clk";
- };
- occ_pci_sys: occ-pci-sys {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <8>;
- clock-mult = <1>;
- clock-output-names = "occ_pci_sys";
- };
- pclk: pclk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <250000000>; /* 250MHz */
- };
- tsu_clk: tsu-clk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <125000000>; /* 125MHz */
- };
-};
diff --git a/arch/mips/boot/dts/mobileye/eyeq5.dtsi b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
index 0708771c193d..5d73e8320b8e 100644
--- a/arch/mips/boot/dts/mobileye/eyeq5.dtsi
+++ b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
@@ -5,7 +5,7 @@
#include <dt-bindings/interrupt-controller/mips-gic.h>
-#include "eyeq5-clocks.dtsi"
+#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
/ {
#address-cells = <2>;
@@ -17,7 +17,7 @@
device_type = "cpu";
compatible = "img,i6500";
reg = <0>;
- clocks = <&core0_clk>;
+ clocks = <&olb EQ5C_CPU_CORE0>;
};
};
@@ -64,6 +64,24 @@
#interrupt-cells = <1>;
};
+ xtal: xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ };
+
+ pclk: pclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <250000000>; /* 250MHz */
+ };
+
+ tsu_clk: tsu-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <125000000>; /* 125MHz */
+ };
+
soc: soc {
#address-cells = <2>;
#size-cells = <2>;
@@ -76,7 +94,7 @@
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&uart_clk>, <&occ_periph>;
+ clocks = <&olb EQ5C_PER_UART>, <&olb EQ5C_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
resets = <&olb 0 10>;
pinctrl-names = "default";
@@ -89,7 +107,7 @@
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&uart_clk>, <&occ_periph>;
+ clocks = <&olb EQ5C_PER_UART>, <&olb EQ5C_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
resets = <&olb 0 11>;
pinctrl-names = "default";
@@ -102,7 +120,7 @@
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&uart_clk>, <&occ_periph>;
+ clocks = <&olb EQ5C_PER_UART>, <&olb EQ5C_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
resets = <&olb 0 12>;
pinctrl-names = "default";
@@ -135,7 +153,7 @@
timer {
compatible = "mti,gic-timer";
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
- clocks = <&core0_clk>;
+ clocks = <&olb EQ5C_CPU_CORE0>;
};
};
};
diff --git a/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts b/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts
index ebc0d363fbf8..59a3e95050eb 100644
--- a/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts
+++ b/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts
@@ -8,7 +8,7 @@
#include "eyeq6h.dtsi"
/ {
- compatible = "mobileye,eyeq6-epm6", "mobileye,eyeq6";
+ compatible = "mobileye,eyeq6h-epm6", "mobileye,eyeq6h";
model = "Mobile EyeQ6H MP6 Evaluation board";
chosen {
diff --git a/arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi b/arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi
deleted file mode 100644
index 5fa99e06fde7..000000000000
--- a/arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi
+++ /dev/null
@@ -1,52 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-/*
- * Copyright 2023 Mobileye Vision Technologies Ltd.
- */
-
-#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
-
-/ {
- xtal: clock-30000000 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <30000000>;
- };
-
- pll_west: clock-2000000000-west {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <2000000000>;
- };
-
- pll_cpu: clock-2000000000-cpu {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <2000000000>;
- };
-
- /* pll-cpu derivatives */
- occ_cpu: clock-2000000000-occ-cpu {
- compatible = "fixed-factor-clock";
- clocks = <&pll_cpu>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
-
- /* pll-west derivatives */
- occ_periph_w: clock-200000000 {
- compatible = "fixed-factor-clock";
- clocks = <&pll_west>;
- #clock-cells = <0>;
- clock-div = <10>;
- clock-mult = <1>;
- };
- uart_clk: clock-200000000-uart {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph_w>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
-
-};
diff --git a/arch/mips/boot/dts/mobileye/eyeq6h.dtsi b/arch/mips/boot/dts/mobileye/eyeq6h.dtsi
index 1db3c3cda2e3..4a1a43f351d3 100644
--- a/arch/mips/boot/dts/mobileye/eyeq6h.dtsi
+++ b/arch/mips/boot/dts/mobileye/eyeq6h.dtsi
@@ -5,7 +5,7 @@
#include <dt-bindings/interrupt-controller/mips-gic.h>
-#include "eyeq6h-fixed-clocks.dtsi"
+#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
/ {
#address-cells = <2>;
@@ -17,7 +17,7 @@
device_type = "cpu";
compatible = "img,i6500";
reg = <0>;
- clocks = <&occ_cpu>;
+ clocks = <&olb_central EQ6HC_CENTRAL_CPU_OCC>;
};
};
@@ -32,19 +32,42 @@
#interrupt-cells = <1>;
};
+ xtal: clock-30000000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ };
+
soc: soc {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ olb_acc: system-controller@d2003000 {
+ compatible = "mobileye,eyeq6h-acc-olb", "syscon";
+ reg = <0x0 0xd2003000 0x0 0x1000>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
+ olb_central: system-controller@d3100000 {
+ compatible = "mobileye,eyeq6h-central-olb", "syscon";
+ reg = <0x0 0xd3100000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
uart0: serial@d3331000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0 0xd3331000 0x0 0x1000>;
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 43 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&occ_periph_w>, <&occ_periph_w>;
+ clocks = <&olb_west EQ6HC_WEST_PER_UART>, <&olb_west EQ6HC_WEST_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
};
@@ -56,6 +79,15 @@
pinctrl-single,function-mask = <0xffff>;
};
+ olb_west: system-controller@d3338000 {
+ compatible = "mobileye,eyeq6h-west-olb", "syscon";
+ reg = <0x0 0xd3338000 0x0 0x1000>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
pinctrl_east: pinctrl@d3357000 {
compatible = "pinctrl-single";
reg = <0x0 0xd3357000 0x0 0xb0>;
@@ -64,6 +96,23 @@
pinctrl-single,function-mask = <0xffff>;
};
+ olb_east: system-controller@d3358000 {
+ compatible = "mobileye,eyeq6h-east-olb", "syscon";
+ reg = <0x0 0xd3358000 0x0 0x1000>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
+ olb_south: system-controller@d8013000 {
+ compatible = "mobileye,eyeq6h-south-olb", "syscon";
+ reg = <0x0 0xd8013000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
pinctrl_south: pinctrl@d8014000 {
compatible = "pinctrl-single";
reg = <0x0 0xd8014000 0x0 0xf8>;
@@ -72,6 +121,22 @@
pinctrl-single,function-mask = <0xffff>;
};
+ olb_ddr0: system-controller@e4080000 {
+ compatible = "mobileye,eyeq6h-ddr0-olb", "syscon";
+ reg = <0x0 0xe4080000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
+ olb_ddr1: system-controller@e4081000 {
+ compatible = "mobileye,eyeq6h-ddr1-olb", "syscon";
+ reg = <0x0 0xe4081000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
gic: interrupt-controller@f0920000 {
compatible = "mti,gic";
reg = <0x0 0xf0920000 0x0 0x20000>;
@@ -89,7 +154,7 @@
timer {
compatible = "mti,gic-timer";
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
- clocks = <&occ_cpu>;
+ clocks = <&olb_central EQ6HC_CENTRAL_CPU_OCC>;
};
};
};
diff --git a/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts b/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts
index 77d2566545f2..6789bf374044 100644
--- a/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts
+++ b/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/dts-v1/;
-#include "rtl930x.dtsi"
+#include "rtl9302c.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
diff --git a/arch/mips/boot/dts/realtek/rtl9302c.dtsi b/arch/mips/boot/dts/realtek/rtl9302c.dtsi
new file mode 100644
index 000000000000..8690433af498
--- /dev/null
+++ b/arch/mips/boot/dts/realtek/rtl9302c.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause
+
+#include "rtl930x.dtsi"
+
+&switch0 {
+ compatible = "realtek,rtl9302c-switch", "syscon", "simple-mfd";
+};
+
+&i2c0 {
+ compatible = "realtek,rtl9302c-i2c", "realtek,rtl9301-i2c";
+};
+
+&i2c1 {
+ compatible = "realtek,rtl9302c-i2c", "realtek,rtl9301-i2c";
+};
diff --git a/arch/mips/boot/dts/realtek/rtl930x.dtsi b/arch/mips/boot/dts/realtek/rtl930x.dtsi
index f271940f82be..17577457d159 100644
--- a/arch/mips/boot/dts/realtek/rtl930x.dtsi
+++ b/arch/mips/boot/dts/realtek/rtl930x.dtsi
@@ -29,9 +29,40 @@
#clock-cells = <0>;
clock-frequency = <175000000>;
};
+
+ switch0: switch@1b000000 {
+ compatible = "realtek,rtl9301-switch", "syscon", "simple-mfd";
+ reg = <0x1b000000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ reboot@c {
+ compatible = "syscon-reboot";
+ reg = <0x0c 0x4>;
+ value = <0x01>;
+ };
+
+ i2c0: i2c@36c {
+ compatible = "realtek,rtl9301-i2c";
+ reg = <0x36c 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@388 {
+ compatible = "realtek,rtl9301-i2c";
+ reg = <0x388 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ };
};
&soc {
+ ranges = <0x0 0x18000000 0x20000>;
+
intc: interrupt-controller@3000 {
compatible = "realtek,rtl9300-intc", "realtek,rtl-intc";
reg = <0x3000 0x18>, <0x3018 0x18>;
@@ -59,6 +90,17 @@
interrupts = <7>, <8>, <9>, <10>, <11>;
clocks = <&lx_clk>;
};
+
+ snand: spi@1a400 {
+ compatible = "realtek,rtl9301-snand";
+ reg = <0x1a400 0x44>;
+ interrupt-parent = <&intc>;
+ interrupts = <19>;
+ clocks = <&lx_clk>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
&uart0 {
diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
index 78f498752066..98844b457b7f 100644
--- a/arch/mips/configs/loongson3_defconfig
+++ b/arch/mips/configs/loongson3_defconfig
@@ -5,6 +5,8 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_BPF_JIT=y
CONFIG_PREEMPT=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -22,18 +24,16 @@ CONFIG_CGROUP_CPUACCT=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
-CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
-CONFIG_BPF_SYSCALL=y
CONFIG_EXPERT=y
CONFIG_PERF_EVENTS=y
+CONFIG_KEXEC=y
CONFIG_MACH_LOONGSON64=y
CONFIG_CPU_HAS_MSA=y
CONFIG_NUMA=y
CONFIG_NR_CPUS=16
CONFIG_HZ_256=y
-CONFIG_KEXEC=y
CONFIG_MIPS32_O32=y
CONFIG_MIPS32_N32=y
CONFIG_VIRTUALIZATION=y
@@ -47,15 +47,12 @@ CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_MQ_IOSCHED_DEADLINE=m
CONFIG_IOSCHED_BFQ=y
-CONFIG_BFQ_GROUP_IOSCHED=y
CONFIG_BINFMT_MISC=m
CONFIG_KSM=y
CONFIG_NET=y
CONFIG_PACKET=y
-CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
-CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
@@ -106,7 +103,6 @@ CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_SECURITY=m
-CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_TABLES_IPV6=y
@@ -128,7 +124,6 @@ CONFIG_L2TP=m
CONFIG_BRIDGE=m
CONFIG_VSOCKETS=m
CONFIG_VIRTIO_VSOCKETS=m
-CONFIG_BPF_JIT=y
CONFIG_CFG80211=m
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=m
@@ -146,6 +141,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_VIRTIO_BLK=y
+CONFIG_BLK_DEV_NVME=m
CONFIG_RAID_ATTRS=m
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
@@ -167,12 +163,10 @@ CONFIG_SATA_AHCI=y
CONFIG_PATA_ATIIXP=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID456=m
-CONFIG_MD_MULTIPATH=m
CONFIG_BLK_DEV_DM=m
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
@@ -196,7 +190,6 @@ CONFIG_VIRTIO_NET=m
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_VENDOR_ATHEROS is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_BROCADE is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_CISCO is not set
@@ -216,6 +209,7 @@ CONFIG_IXGBE=y
# CONFIG_NET_VENDOR_NVIDIA is not set
# CONFIG_NET_VENDOR_OKI is not set
# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
# CONFIG_NET_VENDOR_RDC is not set
CONFIG_8139CP=m
CONFIG_8139TOO=m
@@ -242,7 +236,6 @@ CONFIG_PPPOL2TP=m
CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
CONFIG_ATH9K=m
-CONFIG_HOSTAP=m
CONFIG_INPUT_SPARSEKMAP=y
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
@@ -276,23 +269,20 @@ CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_DRM=y
+CONFIG_DRM_RADEON=m
CONFIG_DRM_AMDGPU=m
CONFIG_DRM_AMDGPU_SI=y
CONFIG_DRM_AMDGPU_CIK=y
CONFIG_DRM_AMDGPU_USERPTR=y
CONFIG_DRM_AMD_ACP=y
-CONFIG_DRM_AMD_DC=y
CONFIG_DRM_AMD_DC_SI=y
CONFIG_DRM_AST=m
-CONFIG_DRM_RADEON=m
CONFIG_DRM_QXL=y
CONFIG_DRM_VIRTIO_GPU=y
CONFIG_FB=y
CONFIG_FB_RADEON=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_PLATFORM=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_LOGO=y
CONFIG_SOUND=y
@@ -350,13 +340,11 @@ CONFIG_EXT3_FS_SECURITY=y
CONFIG_XFS_FS=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_QUOTA=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_QFMT_V1=m
CONFIG_QFMT_V2=m
CONFIG_AUTOFS_FS=y
CONFIG_FUSE_FS=m
CONFIG_VIRTIO_FS=m
-CONFIG_NETFS_SUPPORT=m
CONFIG_FSCACHE=y
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
@@ -391,23 +379,21 @@ CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_PATH=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_DEFAULT_SECURITY_DAC=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_PRINTK_TIME=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
CONFIG_FUNCTION_TRACER=y
CONFIG_FTRACE_SYSCALLS=y
CONFIG_CMDLINE_BOOL=y
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 935585d8bb26..8e98c0796437 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -275,7 +275,6 @@ CONFIG_DM9102=m
CONFIG_ULI526X=m
CONFIG_PCMCIA_XIRCOM=m
CONFIG_DL2K=m
-CONFIG_SUNDANCE=m
CONFIG_PCMCIA_FMVJ18X=m
CONFIG_E100=m
CONFIG_E1000=m
diff --git a/arch/mips/crypto/crc32-mips.c b/arch/mips/crypto/crc32-mips.c
index a7a1d43a1b2c..90eacf00cfc3 100644
--- a/arch/mips/crypto/crc32-mips.c
+++ b/arch/mips/crypto/crc32-mips.c
@@ -123,20 +123,20 @@ static u32 crc32c_mips_le_hw(u32 crc_, const u8 *p, unsigned int len)
for (; len >= sizeof(u64); p += sizeof(u64), len -= sizeof(u64)) {
u64 value = get_unaligned_le64(p);
- CRC32(crc, value, d);
+ CRC32C(crc, value, d);
}
if (len & sizeof(u32)) {
u32 value = get_unaligned_le32(p);
- CRC32(crc, value, w);
+ CRC32C(crc, value, w);
p += sizeof(u32);
}
} else {
for (; len >= sizeof(u32); len -= sizeof(u32)) {
u32 value = get_unaligned_le32(p);
- CRC32(crc, value, w);
+ CRC32C(crc, value, w);
p += sizeof(u32);
}
}
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7ba67a0d6c97..684569b2ecd6 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += parport.h
generic-y += qrwlock.h
generic-y += qspinlock.h
generic-y += user.h
+generic-y += text-patching.h
diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h
index fd69c8808554..d0a86ce83de9 100644
--- a/arch/mips/include/asm/hugetlb.h
+++ b/arch/mips/include/asm/hugetlb.h
@@ -17,12 +17,7 @@ static inline int prepare_hugepage_range(struct file *file,
unsigned long len)
{
unsigned long task_size = STACK_TOP;
- struct hstate *h = hstate_file(file);
- if (len & ~huge_page_mask(h))
- return -EINVAL;
- if (addr & ~huge_page_mask(h))
- return -EINVAL;
if (len > task_size)
return -ENOMEM;
if (task_size - len < addr)
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index af58d6ae06b8..0bddb568af7c 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -125,11 +125,6 @@ static inline unsigned long isa_virt_to_bus(volatile void *address)
return virt_to_phys(address);
}
-/*
- * Change "struct page" to physical address.
- */
-#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
-
void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long prot_val);
void iounmap(const volatile void __iomem *addr);
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index 1e782275850a..23ce951f445b 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -326,7 +326,9 @@ GCR_CX_ACCESSOR_RW(32, 0x018, other)
/* GCR_Cx_RESET_BASE - Configure where powered up cores will fetch from */
GCR_CX_ACCESSOR_RW(32, 0x020, reset_base)
+GCR_CX_ACCESSOR_RW(64, 0x020, reset64_base)
#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE GENMASK(31, 12)
+#define CM_GCR_Cx_RESET64_BASE_BEVEXCBASE GENMASK_ULL(47, 12)
#define CM_GCR_Cx_RESET_BASE_MODE BIT(1)
/* GCR_Cx_ID - Identify the current core */
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index 4609cb0326cf..bc3e3484c1bf 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -14,12 +14,7 @@
#include <linux/kernel.h>
#include <asm/mipsregs.h>
-/*
- * PAGE_SHIFT determines the page size
- */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+#include <vdso/page.h>
/*
* This is used for calculating the real page sizes
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index 401c1d9e4409..6e854bb11f37 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -317,7 +317,9 @@ static inline pmd_t *pud_pgtable(pud_t pud)
*/
extern void pgd_init(void *addr);
extern void pud_init(void *addr);
+#define pud_init pud_init
extern void pmd_init(void *addr);
+#define pmd_init pmd_init
/*
* Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index a4374b4cb88f..d6ccd5344021 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -97,7 +97,7 @@ do { \
} \
} while (0)
#else
-# define __sanitize_fcr31(next)
+# define __sanitize_fcr31(next) do { (void) (next); } while (0)
#endif
/*
diff --git a/arch/mips/include/asm/vdso/vsyscall.h b/arch/mips/include/asm/vdso/vsyscall.h
index 47168aaf1eff..a4582870aaea 100644
--- a/arch/mips/include/asm/vdso/vsyscall.h
+++ b/arch/mips/include/asm/vdso/vsyscall.h
@@ -4,7 +4,6 @@
#ifndef __ASSEMBLY__
-#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
extern struct vdso_data *vdso_data;
diff --git a/arch/mips/include/asm/vga.h b/arch/mips/include/asm/vga.h
index 0136e0366698..491c2b5aeb81 100644
--- a/arch/mips/include/asm/vga.h
+++ b/arch/mips/include/asm/vga.h
@@ -47,10 +47,6 @@ static inline void scr_memsetw(u16 *s, u16 v, unsigned int count)
memset16(s, cpu_to_le16(v), count / 2);
}
-#define scr_memcpyw(d, s, c) memcpy(d, s, c)
-#define scr_memmovew(d, s, c) memmove(d, s, c)
-#define VT_BUF_HAVE_MEMCPYW
-#define VT_BUF_HAVE_MEMMOVEW
#define VT_BUF_HAVE_MEMSETW
#endif /* _ASM_VGA_H */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 9c48d9a21aa0..b700dae28c48 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -105,6 +105,9 @@
#define MADV_COLLAPSE 25 /* Synchronous hugepage collapse */
+#define MADV_GUARD_INSTALL 102 /* fatal signal on access to range */
+#define MADV_GUARD_REMOVE 103 /* unguard range */
+
/* compatibility flags */
#define MAP_FILE 0
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 8ab7582291ab..d118d4731580 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -157,6 +157,8 @@
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
#define SO_DEVMEM_DONTNEED 80
+#define SCM_TS_OPT_ID 81
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index b825ed4476c7..e3ff6179c99f 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -59,6 +59,7 @@
#endif
.endm
+ __HEAD
#ifndef CONFIG_NO_EXCEPT_FILL
/*
* Reserved space for exception handlers.
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 8eba5a1ed664..8f0a0001540c 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -66,24 +66,23 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "BogoMIPS\t\t: %u.%02u\n",
cpu_data[n].udelay_val / (500000/HZ),
(cpu_data[n].udelay_val / (5000/HZ)) % 100);
- seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no");
+ seq_printf(m, "wait instruction\t: %s\n", str_yes_no(cpu_wait));
seq_printf(m, "microsecond timers\t: %s\n",
- cpu_has_counter ? "yes" : "no");
+ str_yes_no(cpu_has_counter));
seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize);
seq_printf(m, "extra interrupt vector\t: %s\n",
- cpu_has_divec ? "yes" : "no");
- seq_printf(m, "hardware watchpoint\t: %s",
- cpu_has_watch ? "yes, " : "no\n");
+ str_yes_no(cpu_has_divec));
+ seq_printf(m, "hardware watchpoint\t: %s", str_yes_no(cpu_has_watch));
if (cpu_has_watch) {
- seq_printf(m, "count: %d, address/irw mask: [",
+ seq_printf(m, ", count: %d, address/irw mask: [",
cpu_data[n].watch_reg_count);
for (i = 0; i < cpu_data[n].watch_reg_count; i++)
seq_printf(m, "%s0x%04x", i ? ", " : "",
cpu_data[n].watch_reg_masks[i]);
- seq_puts(m, "]\n");
+ seq_puts(m, "]");
}
- seq_puts(m, "isa\t\t\t:");
+ seq_puts(m, "\nisa\t\t\t:");
if (cpu_has_mips_1)
seq_puts(m, " mips1");
if (cpu_has_mips_2)
@@ -155,7 +154,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (cpu_has_mmips) {
seq_printf(m, "micromips kernel\t: %s\n",
- (read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no");
+ str_yes_no(read_c0_config3() & MIPS_CONF3_ISA_OE));
}
seq_puts(m, "Options implemented\t:");
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index 6062e6fa589a..4fd6da0a06c3 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -41,7 +41,7 @@ char *mips_get_machine_name(void)
void __init __dt_setup_arch(void *bph)
{
- if (!early_init_dt_scan(bph))
+ if (!early_init_dt_scan(bph, __pa(bph)))
return;
mips_set_machine_name(of_flat_dt_get_machine_name());
diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c
index 7eeeaf1ff95d..cda7983e7c18 100644
--- a/arch/mips/kernel/relocate.c
+++ b/arch/mips/kernel/relocate.c
@@ -337,7 +337,7 @@ void *__init relocate_kernel(void)
#if defined(CONFIG_USE_OF)
/* Deal with the device tree */
fdt = plat_get_fdt();
- early_init_dt_scan(fdt);
+ early_init_dt_scan(fdt, __pa(fdt));
if (boot_command_line[0]) {
/* Boot command line was passed in device tree */
strscpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 395622c37325..82c8f9b9573c 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -37,7 +37,7 @@ enum label_id {
UASM_L_LA(_not_nmi)
static DECLARE_BITMAP(core_power, NR_CPUS);
-static uint32_t core_entry_reg;
+static u64 core_entry_reg;
static phys_addr_t cps_vec_pa;
struct core_boot_config *mips_cps_core_bootcfg;
@@ -94,6 +94,20 @@ static void __init *mips_cps_build_core_entry(void *addr)
return p;
}
+static bool __init check_64bit_reset(void)
+{
+ bool cx_64bit_reset = false;
+
+ mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
+ write_gcr_co_reset64_base(CM_GCR_Cx_RESET64_BASE_BEVEXCBASE);
+ if ((read_gcr_co_reset64_base() & CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) ==
+ CM_GCR_Cx_RESET64_BASE_BEVEXCBASE)
+ cx_64bit_reset = true;
+ mips_cm_unlock_other();
+
+ return cx_64bit_reset;
+}
+
static int __init allocate_cps_vecs(void)
{
/* Try to allocate in KSEG1 first */
@@ -105,11 +119,23 @@ static int __init allocate_cps_vecs(void)
CM_GCR_Cx_RESET_BASE_BEVEXCBASE;
if (!cps_vec_pa && mips_cm_is64) {
- cps_vec_pa = memblock_phys_alloc_range(BEV_VEC_SIZE, BEV_VEC_ALIGN,
- 0x0, SZ_4G - 1);
- if (cps_vec_pa)
- core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET_BASE_BEVEXCBASE) |
+ phys_addr_t end;
+
+ if (check_64bit_reset()) {
+ pr_info("VP Local Reset Exception Base support 47 bits address\n");
+ end = MEMBLOCK_ALLOC_ANYWHERE;
+ } else {
+ end = SZ_4G - 1;
+ }
+ cps_vec_pa = memblock_phys_alloc_range(BEV_VEC_SIZE, BEV_VEC_ALIGN, 0, end);
+ if (cps_vec_pa) {
+ if (check_64bit_reset())
+ core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) |
+ CM_GCR_Cx_RESET_BASE_MODE;
+ else
+ core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET_BASE_BEVEXCBASE) |
CM_GCR_Cx_RESET_BASE_MODE;
+ }
}
if (!cps_vec_pa)
@@ -308,7 +334,10 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
/* Set its reset vector */
- write_gcr_co_reset_base(core_entry_reg);
+ if (mips_cm_is64)
+ write_gcr_co_reset64_base(core_entry_reg);
+ else
+ write_gcr_co_reset_base(core_entry_reg);
/* Ensure its coherency is disabled */
write_gcr_co_coherence(0);
@@ -411,7 +440,10 @@ static int cps_boot_secondary(int cpu, struct task_struct *idle)
if (cpu_has_vp) {
mips_cm_lock_other(0, core, vpe_id, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
- write_gcr_co_reset_base(core_entry_reg);
+ if (mips_cm_is64)
+ write_gcr_co_reset64_base(core_entry_reg);
+ else
+ write_gcr_co_reset_base(core_entry_reg);
mips_cm_unlock_other();
}
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index 953f5b7dc723..0b9b7e25b69a 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -401,3 +401,7 @@
460 n32 lsm_set_self_attr sys_lsm_set_self_attr
461 n32 lsm_list_modules sys_lsm_list_modules
462 n32 mseal sys_mseal
+463 n32 setxattrat sys_setxattrat
+464 n32 getxattrat sys_getxattrat
+465 n32 listxattrat sys_listxattrat
+466 n32 removexattrat sys_removexattrat
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index 1464c6be6eb3..c844cd5cda62 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -377,3 +377,7 @@
460 n64 lsm_set_self_attr sys_lsm_set_self_attr
461 n64 lsm_list_modules sys_lsm_list_modules
462 n64 mseal sys_mseal
+463 n64 setxattrat sys_setxattrat
+464 n64 getxattrat sys_getxattrat
+465 n64 listxattrat sys_listxattrat
+466 n64 removexattrat sys_removexattrat
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 2439a2491cff..349b8aad1159 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -450,3 +450,7 @@
460 o32 lsm_set_self_attr sys_lsm_set_self_attr
461 o32 lsm_list_modules sys_lsm_list_modules
462 o32 mseal sys_mseal
+463 o32 setxattrat sys_setxattrat
+464 o32 getxattrat sys_getxattrat
+465 o32 listxattrat sys_listxattrat
+466 o32 removexattrat sys_removexattrat
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index dda36fa26307..4c8e3c0aa210 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -14,7 +14,6 @@
#include <linux/random.h>
#include <linux/sched.h>
#include <linux/slab.h>
-#include <linux/timekeeper_internal.h>
#include <asm/abi.h>
#include <asm/mips-cps.h>
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 9ff55cb80a64..2b708fac8d2c 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -61,6 +61,7 @@ SECTIONS
/* read-only */
_text = .; /* Text and read-only data */
.text : {
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
index c17157e700c0..d2c3b6b41f18 100644
--- a/arch/mips/kvm/mmu.c
+++ b/arch/mips/kvm/mmu.c
@@ -484,8 +484,6 @@ static int _kvm_mips_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa,
struct kvm *kvm = vcpu->kvm;
gfn_t gfn = gpa >> PAGE_SHIFT;
pte_t *ptep;
- kvm_pfn_t pfn = 0; /* silence bogus GCC warning */
- bool pfn_valid = false;
int ret = 0;
spin_lock(&kvm->mmu_lock);
@@ -498,12 +496,9 @@ static int _kvm_mips_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa,
}
/* Track access to pages marked old */
- if (!pte_young(*ptep)) {
+ if (!pte_young(*ptep))
set_pte(ptep, pte_mkyoung(*ptep));
- pfn = pte_pfn(*ptep);
- pfn_valid = true;
- /* call kvm_set_pfn_accessed() after unlock */
- }
+
if (write_fault && !pte_dirty(*ptep)) {
if (!pte_write(*ptep)) {
ret = -EFAULT;
@@ -512,9 +507,7 @@ static int _kvm_mips_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa,
/* Track dirtying of writeable pages */
set_pte(ptep, pte_mkdirty(*ptep));
- pfn = pte_pfn(*ptep);
mark_page_dirty(kvm, gfn);
- kvm_set_pfn_dirty(pfn);
}
if (out_entry)
@@ -524,8 +517,6 @@ static int _kvm_mips_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa,
out:
spin_unlock(&kvm->mmu_lock);
- if (pfn_valid)
- kvm_set_pfn_accessed(pfn);
return ret;
}
@@ -566,6 +557,7 @@ static int kvm_mips_map_page(struct kvm_vcpu *vcpu, unsigned long gpa,
bool writeable;
unsigned long prot_bits;
unsigned long mmu_seq;
+ struct page *page;
/* Try the fast path to handle old / clean pages */
srcu_idx = srcu_read_lock(&kvm->srcu);
@@ -587,7 +579,7 @@ retry:
mmu_seq = kvm->mmu_invalidate_seq;
/*
* Ensure the read of mmu_invalidate_seq isn't reordered with PTE reads
- * in gfn_to_pfn_prot() (which calls get_user_pages()), so that we don't
+ * in kvm_faultin_pfn() (which calls get_user_pages()), so that we don't
* risk the page we get a reference to getting unmapped before we have a
* chance to grab the mmu_lock without mmu_invalidate_retry() noticing.
*
@@ -599,7 +591,7 @@ retry:
smp_rmb();
/* Slow path - ask KVM core whether we can access this GPA */
- pfn = gfn_to_pfn_prot(kvm, gfn, write_fault, &writeable);
+ pfn = kvm_faultin_pfn(vcpu, gfn, write_fault, &writeable, &page);
if (is_error_noslot_pfn(pfn)) {
err = -EFAULT;
goto out;
@@ -611,10 +603,10 @@ retry:
/*
* This can happen when mappings are changed asynchronously, but
* also synchronously if a COW is triggered by
- * gfn_to_pfn_prot().
+ * kvm_faultin_pfn().
*/
spin_unlock(&kvm->mmu_lock);
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_unused(page);
goto retry;
}
@@ -628,7 +620,6 @@ retry:
if (write_fault) {
prot_bits |= __WRITEABLE;
mark_page_dirty(kvm, gfn);
- kvm_set_pfn_dirty(pfn);
}
}
entry = pfn_pte(pfn, __pgprot(prot_bits));
@@ -642,9 +633,8 @@ retry:
if (out_buddy)
*out_buddy = *ptep_buddy(ptep);
+ kvm_release_faultin_page(kvm, page, false, writeable);
spin_unlock(&kvm->mmu_lock);
- kvm_release_pfn_clean(pfn);
- kvm_set_pfn_accessed(pfn);
out:
srcu_read_unlock(&kvm->srcu, srcu_idx);
return err;
diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
index 08c012a2591f..910d059ec70b 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -1,13 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
if RALINK
-config CLKEVT_RT3352
- bool
- depends on SOC_RT305X || SOC_MT7620
- default y
- select TIMER_OF
- select CLKSRC_MMIO
-
config RALINK_ILL_ACC
bool
depends on SOC_RT305X
diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
index 26fabbdea1f1..0c109eae1953 100644
--- a/arch/mips/ralink/Makefile
+++ b/arch/mips/ralink/Makefile
@@ -10,8 +10,6 @@ ifndef CONFIG_MIPS_GIC
obj-y += clk.o timer.o
endif
-obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o
-
obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o
obj-$(CONFIG_IRQ_INTC) += irq.o
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
index d20eec742bfa..5893ea4e382c 100644
--- a/arch/mips/sgi-ip22/ip22-gio.c
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -165,9 +165,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
char *buf)
{
struct gio_device *gio_dev = to_gio_device(dev);
- int len = snprintf(buf, PAGE_SIZE, "gio:%x\n", gio_dev->id.id);
- return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+ return sysfs_emit(buf, "gio:%x\n", gio_dev->id.id);
}
static DEVICE_ATTR_RO(modalias);
@@ -177,7 +176,7 @@ static ssize_t name_show(struct device *dev,
struct gio_device *giodev;
giodev = to_gio_device(dev);
- return sprintf(buf, "%s", giodev->name);
+ return sysfs_emit(buf, "%s\n", giodev->name);
}
static DEVICE_ATTR_RO(name);
@@ -187,7 +186,7 @@ static ssize_t id_show(struct device *dev,
struct gio_device *giodev;
giodev = to_gio_device(dev);
- return sprintf(buf, "%x", giodev->id.id);
+ return sysfs_emit(buf, "%x\n", giodev->id.id);
}
static DEVICE_ATTR_RO(id);
diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c
index 09e30eb4be86..d47412ea6e67 100644
--- a/arch/mips/vdso/genvdso.c
+++ b/arch/mips/vdso/genvdso.c
@@ -270,7 +270,7 @@ int main(int argc, char **argv)
/* Write out the stripped VDSO data. */
fprintf(out_file,
- "static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t",
+ "static unsigned char vdso_image_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t",
vdso_size);
for (i = 0; i < vdso_size; i++) {
if (!(i % 10))
@@ -286,7 +286,7 @@ int main(int argc, char **argv)
fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n",
(vdso_name[0]) ? "_" : "", vdso_name);
- fprintf(out_file, "\t.data = vdso_data,\n");
+ fprintf(out_file, "\t.data = vdso_image_data,\n");
fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size);
fprintf(out_file, "\t.mapping = {\n");
fprintf(out_file, "\t\t.name = \"[vdso]\",\n");
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index 0d09829ed144..28004301c236 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -7,3 +7,4 @@ generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += spinlock.h
generic-y += user.h
+generic-y += text-patching.h
diff --git a/arch/nios2/include/asm/io.h b/arch/nios2/include/asm/io.h
index 746853ac7d8d..36e3550673b3 100644
--- a/arch/nios2/include/asm/io.h
+++ b/arch/nios2/include/asm/io.h
@@ -28,9 +28,6 @@
void __iomem *ioremap(unsigned long physaddr, unsigned long size);
void iounmap(void __iomem *addr);
-/* Pages to physical address... */
-#define page_to_phys(page) virt_to_phys(page_to_virt(page))
-
/* Macros used for converting between virtual and physical mappings. */
#define phys_to_virt(vaddr) \
((void *)((unsigned long)(vaddr) | CONFIG_NIOS2_KERNEL_REGION_BASE))
diff --git a/arch/nios2/include/asm/page.h b/arch/nios2/include/asm/page.h
index 0722f88e63cc..2897ec1b74f6 100644
--- a/arch/nios2/include/asm/page.h
+++ b/arch/nios2/include/asm/page.h
@@ -18,12 +18,7 @@
#include <linux/pfn.h>
#include <linux/const.h>
-/*
- * PAGE_SHIFT determines the page size
- */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE - 1))
+#include <vdso/page.h>
/*
* PAGE_OFFSET -- the first address of the first page of memory.
diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c
index 9a8393e6b4a8..db049249766f 100644
--- a/arch/nios2/kernel/prom.c
+++ b/arch/nios2/kernel/prom.c
@@ -27,7 +27,7 @@ void __init early_init_devtree(void *params)
if (be32_to_cpup((__be32 *)CONFIG_NIOS2_DTB_PHYS_ADDR) ==
OF_DT_HEADER) {
params = (void *)CONFIG_NIOS2_DTB_PHYS_ADDR;
- early_init_dt_scan(params);
+ early_init_dt_scan(params, __pa(params));
return;
}
#endif
@@ -37,5 +37,5 @@ void __init early_init_devtree(void *params)
params = (void *)__dtb_start;
#endif
- early_init_dt_scan(params);
+ early_init_dt_scan(params, __pa(params));
}
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 69c0258700b2..3279ef457c57 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -65,6 +65,9 @@ config STACKTRACE_SUPPORT
config LOCKDEP_SUPPORT
def_bool y
+config FIX_EARLYCON_MEM
+ def_bool y
+
menu "Processor type and features"
choice
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index cef49d60d74c..2b1a6b00cdac 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += spinlock.h
generic-y += qrwlock_types.h
generic-y += qrwlock.h
generic-y += user.h
+generic-y += text-patching.h
diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h
index ecdb98a5839f..aaa6a26a3e92 100644
--- a/arch/openrisc/include/asm/fixmap.h
+++ b/arch/openrisc/include/asm/fixmap.h
@@ -26,29 +26,18 @@
#include <linux/bug.h>
#include <asm/page.h>
-/*
- * On OpenRISC we use these special fixed_addresses for doing ioremap
- * early in the boot process before memory initialization is complete.
- * This is used, in particular, by the early serial console code.
- *
- * It's not really 'fixmap', per se, but fits loosely into the same
- * paradigm.
- */
enum fixed_addresses {
- /*
- * FIX_IOREMAP entries are useful for mapping physical address
- * space before ioremap() is useable, e.g. really early in boot
- * before kmalloc() is working.
- */
-#define FIX_N_IOREMAPS 32
- FIX_IOREMAP_BEGIN,
- FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
+ FIX_EARLYCON_MEM_BASE,
__end_of_fixed_addresses
};
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
/* FIXADDR_BOTTOM might be a better name here... */
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+#define FIXMAP_PAGE_IO PAGE_KERNEL_NOCACHE
+
+extern void __set_fixmap(enum fixed_addresses idx,
+ phys_addr_t phys, pgprot_t flags);
#include <asm-generic/fixmap.h>
diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h
index 1d5913f67c31..c589e96035e1 100644
--- a/arch/openrisc/include/asm/page.h
+++ b/arch/openrisc/include/asm/page.h
@@ -15,16 +15,7 @@
#ifndef __ASM_OPENRISC_PAGE_H
#define __ASM_OPENRISC_PAGE_H
-
-/* PAGE_SHIFT determines the page size */
-
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#ifdef __ASSEMBLY__
-#define PAGE_SIZE (1 << PAGE_SHIFT)
-#else
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#endif
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#define PAGE_OFFSET 0xc0000000
#define KERNELBASE PAGE_OFFSET
@@ -80,8 +71,6 @@ static inline unsigned long virt_to_pfn(const void *kaddr)
#define virt_to_page(addr) \
(mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
-#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
-
#define virt_addr_valid(kaddr) (pfn_valid(virt_to_pfn(kaddr)))
#endif /* __ASSEMBLY__ */
diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c
index 19e6008bf114..e424e9bd12a7 100644
--- a/arch/openrisc/kernel/prom.c
+++ b/arch/openrisc/kernel/prom.c
@@ -22,6 +22,6 @@
void __init early_init_devtree(void *params)
{
- early_init_dt_scan(params);
+ early_init_dt_scan(params, __pa(params));
memblock_allow_resize();
}
diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c
index 1dcd78c8f0e9..d0cb1a0126f9 100644
--- a/arch/openrisc/mm/init.c
+++ b/arch/openrisc/mm/init.c
@@ -207,6 +207,43 @@ void __init mem_init(void)
return;
}
+static int __init map_page(unsigned long va, phys_addr_t pa, pgprot_t prot)
+{
+ p4d_t *p4d;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ p4d = p4d_offset(pgd_offset_k(va), va);
+ pud = pud_offset(p4d, va);
+ pmd = pmd_offset(pud, va);
+ pte = pte_alloc_kernel(pmd, va);
+
+ if (pte == NULL)
+ return -ENOMEM;
+
+ if (pgprot_val(prot))
+ set_pte_at(&init_mm, va, pte, pfn_pte(pa >> PAGE_SHIFT, prot));
+ else
+ pte_clear(&init_mm, va, pte);
+
+ local_flush_tlb_page(NULL, va);
+ return 0;
+}
+
+void __init __set_fixmap(enum fixed_addresses idx,
+ phys_addr_t phys, pgprot_t prot)
+{
+ unsigned long address = __fix_to_virt(idx);
+
+ if (idx >= __end_of_fixed_addresses) {
+ BUG();
+ return;
+ }
+
+ map_page(address, phys, prot);
+}
+
static const pgprot_t protection_map[16] = {
[VM_NONE] = PAGE_NONE,
[VM_READ] = PAGE_READONLY_X,
diff --git a/arch/parisc/include/asm/hugetlb.h b/arch/parisc/include/asm/hugetlb.h
index 72daacc472a0..5b3a5429f71b 100644
--- a/arch/parisc/include/asm/hugetlb.h
+++ b/arch/parisc/include/asm/hugetlb.h
@@ -12,21 +12,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep);
-/*
- * If the arch doesn't supply something else, assume that hugepage
- * size aligned regions are ok without further preparation.
- */
-#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE
-static inline int prepare_hugepage_range(struct file *file,
- unsigned long addr, unsigned long len)
-{
- if (len & ~HPAGE_MASK)
- return -EINVAL;
- if (addr & ~HPAGE_MASK)
- return -EINVAL;
- return 0;
-}
-
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep)
diff --git a/arch/parisc/include/asm/mman.h b/arch/parisc/include/asm/mman.h
index 89b6beeda0b8..663f587dc789 100644
--- a/arch/parisc/include/asm/mman.h
+++ b/arch/parisc/include/asm/mman.h
@@ -2,6 +2,7 @@
#ifndef __ASM_MMAN_H__
#define __ASM_MMAN_H__
+#include <linux/fs.h>
#include <uapi/asm/mman.h>
/* PARISC cannot allow mdwe as it needs writable stacks */
@@ -11,7 +12,7 @@ static inline bool arch_memory_deny_write_exec_supported(void)
}
#define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported
-static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
+static inline unsigned long arch_calc_vm_flag_bits(struct file *file, unsigned long flags)
{
/*
* The stack on parisc grows upwards, so if userspace requests memory
@@ -23,6 +24,6 @@ static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
return 0;
}
-#define arch_calc_vm_flag_bits(flags) arch_calc_vm_flag_bits(flags)
+#define arch_calc_vm_flag_bits(file, flags) arch_calc_vm_flag_bits(file, flags)
#endif /* __ASM_MMAN_H__ */
diff --git a/arch/parisc/include/asm/page.h b/arch/parisc/include/asm/page.h
index 4bea2e95798f..7fd447092630 100644
--- a/arch/parisc/include/asm/page.h
+++ b/arch/parisc/include/asm/page.h
@@ -4,9 +4,7 @@
#include <linux/const.h>
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
@@ -168,7 +166,6 @@ extern int npmem_ranges;
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#include <asm-generic/memory_model.h>
diff --git a/arch/parisc/include/asm/patch.h b/arch/parisc/include/asm/text-patching.h
index 400d84c6e504..400d84c6e504 100644
--- a/arch/parisc/include/asm/patch.h
+++ b/arch/parisc/include/asm/text-patching.h
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 68c44f99bc93..b6a709506987 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -75,6 +75,9 @@
#define MADV_HWPOISON 100 /* poison a page for testing */
#define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */
+#define MADV_GUARD_INSTALL 102 /* fatal signal on access to range */
+#define MADV_GUARD_REMOVE 103 /* unguard range */
+
/* compatibility flags */
#define MAP_FILE 0
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 38fc0b188e08..d268d69bfcd2 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -138,6 +138,8 @@
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
#define SO_DEVMEM_DONTNEED 80
+#define SCM_TS_OPT_ID 0x404C
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
index c91f9c2e61ed..10fd5b3e63e7 100644
--- a/arch/parisc/kernel/ftrace.c
+++ b/arch/parisc/kernel/ftrace.c
@@ -20,7 +20,7 @@
#include <asm/assembly.h>
#include <asm/sections.h>
#include <asm/ftrace.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#define __hot __section(".text.hot")
@@ -87,7 +87,7 @@ int ftrace_enable_ftrace_graph_caller(void)
int ftrace_disable_ftrace_graph_caller(void)
{
- static_key_enable(&ftrace_graph_enable.key);
+ static_key_disable(&ftrace_graph_enable.key);
return 0;
}
#endif
diff --git a/arch/parisc/kernel/jump_label.c b/arch/parisc/kernel/jump_label.c
index e253b134500d..ea51f15bf0e6 100644
--- a/arch/parisc/kernel/jump_label.c
+++ b/arch/parisc/kernel/jump_label.c
@@ -8,7 +8,7 @@
#include <linux/jump_label.h>
#include <linux/bug.h>
#include <asm/alternative.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
static inline int reassemble_17(int as17)
{
diff --git a/arch/parisc/kernel/kgdb.c b/arch/parisc/kernel/kgdb.c
index b16fa9bac5f4..fee81f877525 100644
--- a/arch/parisc/kernel/kgdb.c
+++ b/arch/parisc/kernel/kgdb.c
@@ -16,7 +16,7 @@
#include <asm/ptrace.h>
#include <asm/traps.h>
#include <asm/processor.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/cacheflush.h>
const struct kgdb_arch arch_kgdb_ops = {
diff --git a/arch/parisc/kernel/kprobes.c b/arch/parisc/kernel/kprobes.c
index 6e0b86652f30..9255adba67a3 100644
--- a/arch/parisc/kernel/kprobes.c
+++ b/arch/parisc/kernel/kprobes.c
@@ -12,7 +12,7 @@
#include <linux/kprobes.h>
#include <linux/slab.h>
#include <asm/cacheflush.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c
index e59574f65e64..35dd764b871e 100644
--- a/arch/parisc/kernel/patch.c
+++ b/arch/parisc/kernel/patch.c
@@ -13,7 +13,7 @@
#include <asm/cacheflush.h>
#include <asm/fixmap.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
struct patch {
void *addr;
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index 66dc406b12e4..d9fc94c86965 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -461,3 +461,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
index 4818f3db84a5..59d8c15d81bd 100644
--- a/arch/parisc/lib/checksum.c
+++ b/arch/parisc/lib/checksum.c
@@ -25,15 +25,6 @@
: "=r"(_t) \
: "r"(_r), "0"(_t));
-static inline unsigned short from32to16(unsigned int x)
-{
- /* 32 bits --> 16 bits + carry */
- x = (x & 0xffff) + (x >> 16);
- /* 16 bits + carry --> 16 bits including carry */
- x = (x & 0xffff) + (x >> 16);
- return (unsigned short)x;
-}
-
static inline unsigned int do_csum(const unsigned char * buff, int len)
{
int odd, count;
@@ -85,7 +76,7 @@ static inline unsigned int do_csum(const unsigned char * buff, int len)
}
if (len & 1)
result += le16_to_cpu(*buff);
- result = from32to16(result);
+ result = csum_from32to16(result);
if (odd)
result = swab16(result);
out:
@@ -102,7 +93,7 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned int result = do_csum(buff, len);
addc(result, sum);
- return (__force __wsum)from32to16(result);
+ return (__force __wsum)csum_from32to16(result);
}
EXPORT_SYMBOL(csum_partial);
diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c
index aa664f7ddb63..e9d18cf25b79 100644
--- a/arch/parisc/mm/hugetlbpage.c
+++ b/arch/parisc/mm/hugetlbpage.c
@@ -21,27 +21,6 @@
#include <asm/mmu_context.h>
-unsigned long
-hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
-
- if (len & ~huge_page_mask(h))
- return -EINVAL;
- if (len > TASK_SIZE)
- return -ENOMEM;
-
- if (flags & MAP_FIXED)
- if (prepare_hugepage_range(file, addr, len))
- return -EINVAL;
-
- if (addr)
- addr = ALIGN(addr, huge_page_size(h));
-
- /* we need to make sure the colouring is OK */
- return arch_get_unmapped_area(file, addr, len, pgoff, flags, 0);
-}
pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
diff --git a/arch/powerpc/Kbuild b/arch/powerpc/Kbuild
index 571f260b0842..b010ccb071b6 100644
--- a/arch/powerpc/Kbuild
+++ b/arch/powerpc/Kbuild
@@ -19,4 +19,4 @@ obj-$(CONFIG_KEXEC_CORE) += kexec/
obj-$(CONFIG_KEXEC_FILE) += purgatory/
# for cleaning
-subdir- += boot
+subdir- += boot tools
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8094a01974cc..a0ce777f9706 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -234,6 +234,8 @@ config PPC
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_ARGS if ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32
+ select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if PPC_FTRACE_OUT_OF_LINE || (PPC32 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY)
+ select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS
select HAVE_DYNAMIC_FTRACE_WITH_REGS if ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32
select HAVE_EBPF_JIT
select HAVE_EFFICIENT_UNALIGNED_ACCESS
@@ -243,7 +245,7 @@ config PPC
select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1
select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_FUNCTION_GRAPH_TRACER
- select HAVE_FUNCTION_TRACER if PPC64 || (PPC32 && CC_IS_GCC)
+ select HAVE_FUNCTION_TRACER if !COMPILE_TEST && (PPC64 || (PPC32 && CC_IS_GCC))
select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC
select HAVE_GENERIC_VDSO
select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC_BOOK3S_64 && SMP
@@ -273,10 +275,12 @@ config PPC
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE
select HAVE_RSEQ
+ select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
select HAVE_SETUP_PER_CPU_AREA if PPC64
select HAVE_SOFTIRQ_ON_OWN_STACK
- select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2)
- select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13)
+ select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,$(m32-flag) -mstack-protector-guard=tls -mstack-protector-guard-reg=r2 -mstack-protector-guard-offset=0)
+ select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,$(m64-flag) -mstack-protector-guard=tls -mstack-protector-guard-reg=r13 -mstack-protector-guard-offset=0)
select HAVE_STATIC_CALL if PPC32
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING
@@ -569,6 +573,22 @@ config ARCH_USING_PATCHABLE_FUNCTION_ENTRY
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mlittle-endian) if PPC64 && CPU_LITTLE_ENDIAN
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mbig-endian) if PPC64 && CPU_BIG_ENDIAN
+config PPC_FTRACE_OUT_OF_LINE
+ def_bool PPC64 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY
+ select ARCH_WANTS_PRE_LINK_VMLINUX
+
+config PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE
+ int "Number of ftrace out-of-line stubs to reserve within .text"
+ depends on PPC_FTRACE_OUT_OF_LINE
+ default 32768
+ help
+ Number of stubs to reserve for use by ftrace. This space is
+ reserved within .text, and is distinct from any additional space
+ added at the end of .text before the final vmlinux link. Set to
+ zero to have stubs only be generated at the end of vmlinux (only
+ if the size of vmlinux is less than 32MB). Set to a higher value
+ if building vmlinux larger than 48MB.
+
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
depends on SMP && (PPC_PSERIES || \
@@ -684,6 +704,10 @@ config RELOCATABLE_TEST
config ARCH_SUPPORTS_CRASH_DUMP
def_bool PPC64 || PPC_BOOK3S_32 || PPC_85xx || (44x && !SMP)
+config ARCH_DEFAULT_CRASH_DUMP
+ bool
+ default y if !PPC_BOOK3S_32
+
config ARCH_SELECTS_CRASH_DUMP
def_bool y
depends on CRASH_DUMP
@@ -1298,6 +1322,14 @@ config MODULES_SIZE
endmenu
+config PPC64_PROC_SYSTEMCFG
+ def_bool y
+ depends on PPC64 && PROC_FS
+ help
+ This option enables the presence of /proc/ppc64/systemcfg through
+ which the systemcfg page can be accessed.
+ This interface only exists for backwards-compatibility.
+
if PPC64
# This value must have zeroes in the bottom 60 bits otherwise lots will break
config PAGE_OFFSET
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 0bbec4afc0d5..20d05605fa83 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -223,12 +223,6 @@ config PPC_EARLY_DEBUG_RTAS_CONSOLE
help
Select this to enable early debugging via the RTAS console.
-config PPC_EARLY_DEBUG_MAPLE
- bool "Maple real mode"
- depends on PPC_MAPLE
- help
- Select this to enable early debugging for Maple.
-
config PPC_EARLY_DEBUG_PAS_REALMODE
bool "PA Semi real mode"
depends on PPC_PASEMI
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index bbfe4a1f06ef..f3804103c56c 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -62,14 +62,14 @@ KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
endif
ifdef CONFIG_CPU_LITTLE_ENDIAN
-KBUILD_CFLAGS += -mlittle-endian
+KBUILD_CPPFLAGS += -mlittle-endian
KBUILD_LDFLAGS += -EL
LDEMULATION := lppc
GNUTARGET := powerpcle
MULTIPLEWORD := -mno-multiple
KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-save-toc-indirect)
else
-KBUILD_CFLAGS += $(call cc-option,-mbig-endian)
+KBUILD_CPPFLAGS += $(call cc-option,-mbig-endian)
KBUILD_LDFLAGS += -EB
LDEMULATION := ppc
GNUTARGET := powerpc
@@ -95,18 +95,11 @@ aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian)
aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian
ifeq ($(HAS_BIARCH),y)
-KBUILD_CFLAGS += -m$(BITS)
+KBUILD_CPPFLAGS += -m$(BITS)
KBUILD_AFLAGS += -m$(BITS)
KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION)
endif
-cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard=tls
-ifdef CONFIG_PPC64
-cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r13
-else
-cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r2
-endif
-
LDFLAGS_vmlinux-y := -Bstatic
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) += -z notext
@@ -155,7 +148,15 @@ CC_FLAGS_NO_FPU := $(call cc-option,-msoft-float)
ifdef CONFIG_FUNCTION_TRACER
ifdef CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
+ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+CC_FLAGS_FTRACE := -fpatchable-function-entry=1
+else
+ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS # PPC32 only
+CC_FLAGS_FTRACE := -fpatchable-function-entry=3,1
+else
CC_FLAGS_FTRACE := -fpatchable-function-entry=2
+endif
+endif
else
CC_FLAGS_FTRACE := -pg
ifdef CONFIG_MPROFILE_KERNEL
@@ -175,7 +176,6 @@ KBUILD_CPPFLAGS += -I $(srctree)/arch/powerpc $(asinstr)
KBUILD_AFLAGS += $(AFLAGS-y)
KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU)
KBUILD_CFLAGS += $(CFLAGS-y)
-CPP = $(CC) -E $(KBUILD_CFLAGS)
CHECKFLAGS += -m$(BITS) -D__powerpc__ -D__powerpc$(BITS)__
ifdef CONFIG_CPU_BIG_ENDIAN
@@ -359,7 +359,7 @@ define archhelp
echo ' install - Install kernel using'
echo ' (your) ~/bin/$(INSTALLKERNEL) or'
echo ' (distribution) /sbin/$(INSTALLKERNEL) or'
- echo ' install to $$(INSTALL_PATH) and run lilo'
+ echo ' install to $$(INSTALL_PATH)'
echo ' *_defconfig - Select default config from arch/powerpc/configs'
echo ''
echo ' Targets with <dt> embed a device tree blob inside the image'
@@ -402,9 +402,13 @@ prepare: stack_protector_prepare
PHONY += stack_protector_prepare
stack_protector_prepare: prepare0
ifdef CONFIG_PPC64
- $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h))
+ $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls -mstack-protector-guard-reg=r13 \
+ -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' \
+ $(objtree)/include/generated/asm-offsets.h))
else
- $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
+ $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls -mstack-protector-guard-reg=r2 \
+ -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' \
+ $(objtree)/include/generated/asm-offsets.h))
endif
endif
diff --git a/arch/powerpc/Makefile.postlink b/arch/powerpc/Makefile.postlink
index ae5a4256b03d..bb601be36173 100644
--- a/arch/powerpc/Makefile.postlink
+++ b/arch/powerpc/Makefile.postlink
@@ -24,6 +24,9 @@ else
$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$(NM)" "$@"
endif
+quiet_cmd_ftrace_check = CHKFTRC $@
+ cmd_ftrace_check = $(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/ftrace_check.sh "$(NM)" "$@"
+
# `@true` prevents complaint when there is nothing to be done
vmlinux: FORCE
@@ -34,6 +37,11 @@ endif
ifdef CONFIG_RELOCATABLE
$(call if_changed,relocs_check)
endif
+ifdef CONFIG_FUNCTION_TRACER
+ifndef CONFIG_PPC64_ELF_ABI_V1
+ $(call cmd,ftrace_check)
+endif
+endif
clean:
rm -f .tmp_symbols.txt
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
index a4716d138cfc..5a867f23fe7f 100644
--- a/arch/powerpc/boot/.gitignore
+++ b/arch/powerpc/boot/.gitignore
@@ -30,7 +30,6 @@ zImage.coff
zImage.epapr
zImage.holly
zImage.*lds
-zImage.maple
zImage.miboot
zImage.pmac
zImage.pseries
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index fa8518067d38..1ff6ad4f6cd2 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -276,7 +276,6 @@ quiet_cmd_wrap = WRAP $@
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
image-$(CONFIG_PPC_POWERNV) += zImage.pseries
-image-$(CONFIG_PPC_MAPLE) += zImage.maple
image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries
image-$(CONFIG_PPC_PS3) += dtbImage.ps3
image-$(CONFIG_PPC_CHRP) += zImage.chrp
@@ -444,7 +443,7 @@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \
zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \
zImage.miboot zImage.pmac zImage.pseries \
- zImage.maple simpleImage.* otheros.bld
+ simpleImage.* otheros.bld
# clean up files cached by wrapper
clean-kernel-base := vmlinux.strip vmlinux.bin
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index b1f5549a3c9c..1db60fe13802 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -271,11 +271,6 @@ pseries)
fi
make_space=n
;;
-maple)
- platformo="$object/of.o $object/epapr.o"
- link_address='0x400000'
- make_space=n
- ;;
pmac|chrp)
platformo="$object/of.o $object/epapr.o"
make_space=n
@@ -517,7 +512,7 @@ fi
# post-processing needed for some platforms
case "$platform" in
-pseries|chrp|maple)
+pseries|chrp)
$objbin/addnote "$ofile"
;;
coff)
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
deleted file mode 100644
index c821a97f4a89..000000000000
--- a/arch/powerpc/configs/maple_defconfig
+++ /dev/null
@@ -1,111 +0,0 @@
-CONFIG_PPC64=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=4
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_PROFILING=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-# CONFIG_PPC_POWERNV is not set
-# CONFIG_PPC_PSERIES is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_MAPLE=y
-CONFIG_UDBG_RTAS_CONSOLE=y
-CONFIG_GEN_RTC=y
-CONFIG_KEXEC=y
-CONFIG_IRQ_ALL_CPUS=y
-CONFIG_PPC_4K_PAGES=y
-CONFIG_PCI_MSI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IPV6 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_IPR=y
-CONFIG_ATA=y
-CONFIG_PATA_AMD=y
-CONFIG_ATA_GENERIC=y
-CONFIG_NETDEVICES=y
-CONFIG_AMD8111_ETH=y
-CONFIG_TIGON3=y
-CONFIG_E1000=y
-CONFIG_USB_PEGASUS=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_HVC_RTAS=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_AMD8111=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_HID_GYRATION=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-# CONFIG_USB_EHCI_HCD_PPC_OF is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_CYPRESS_M8=m
-CONFIG_USB_SERIAL_GARMIN=m
-CONFIG_USB_SERIAL_IPW=m
-CONFIG_USB_SERIAL_KEYSPAN=y
-CONFIG_USB_SERIAL_TI=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT4_FS=y
-CONFIG_FS_DAX=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="utf-8"
-CONFIG_NLS_UTF8=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_STACK_USAGE=y
-CONFIG_DEBUG_STACKOVERFLOW=y
-CONFIG_XMON=y
-CONFIG_XMON_DEFAULT=y
-CONFIG_BOOTX_TEXT=y
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_HW is not set
-CONFIG_PRINTK_TIME=y
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index a5e3e7f97f4d..f39c0d000c43 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -44,7 +44,6 @@ CONFIG_PPC_SMLPAR=y
CONFIG_IBMEBUS=y
CONFIG_PAPR_SCM=m
CONFIG_PPC_SVM=y
-CONFIG_PPC_MAPLE=y
CONFIG_PPC_PASEMI=y
CONFIG_PPC_PASEMI_IOMMU=y
CONFIG_PPC_PS3=y
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index c06344db0eb3..4d77e17541e9 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -435,7 +435,6 @@ CONFIG_DM9102=m
CONFIG_ULI526X=m
CONFIG_PCMCIA_XIRCOM=m
CONFIG_DL2K=m
-CONFIG_SUNDANCE=m
CONFIG_S2IO=m
CONFIG_FEC_MPC52xx=m
CONFIG_GIANFAR=m
diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig
index 46a4c85e85e2..951a43726461 100644
--- a/arch/powerpc/crypto/Kconfig
+++ b/arch/powerpc/crypto/Kconfig
@@ -107,12 +107,12 @@ config CRYPTO_AES_PPC_SPE
config CRYPTO_AES_GCM_P10
tristate "Stitched AES/GCM acceleration support on P10 or later CPU (PPC)"
- depends on BROKEN
depends on PPC64 && CPU_LITTLE_ENDIAN && VSX
select CRYPTO_LIB_AES
select CRYPTO_ALGAPI
select CRYPTO_AEAD
select CRYPTO_SKCIPHER
+ select CRYPTO_SIMD
help
AEAD cipher: AES cipher algorithms (FIPS-197)
GCM (Galois/Counter Mode) authenticated encryption mode (NIST SP800-38D)
diff --git a/arch/powerpc/crypto/aes-gcm-p10-glue.c b/arch/powerpc/crypto/aes-gcm-p10-glue.c
index f66ad56e765f..f37b3d13fc53 100644
--- a/arch/powerpc/crypto/aes-gcm-p10-glue.c
+++ b/arch/powerpc/crypto/aes-gcm-p10-glue.c
@@ -8,6 +8,7 @@
#include <linux/unaligned.h>
#include <asm/simd.h>
#include <asm/switch_to.h>
+#include <crypto/gcm.h>
#include <crypto/aes.h>
#include <crypto/algapi.h>
#include <crypto/b128ops.h>
@@ -24,6 +25,7 @@
#define PPC_ALIGN 16
#define GCM_IV_SIZE 12
+#define RFC4106_NONCE_SIZE 4
MODULE_DESCRIPTION("PPC64le AES-GCM with Stitched implementation");
MODULE_AUTHOR("Danny Tsen <dtsen@linux.ibm.com");
@@ -31,7 +33,7 @@ MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("aes");
asmlinkage int aes_p10_set_encrypt_key(const u8 *userKey, const int bits,
- void *key);
+ void *key);
asmlinkage void aes_p10_encrypt(const u8 *in, u8 *out, const void *key);
asmlinkage void aes_p10_gcm_encrypt(u8 *in, u8 *out, size_t len,
void *rkey, u8 *iv, void *Xi);
@@ -39,7 +41,8 @@ asmlinkage void aes_p10_gcm_decrypt(u8 *in, u8 *out, size_t len,
void *rkey, u8 *iv, void *Xi);
asmlinkage void gcm_init_htable(unsigned char htable[], unsigned char Xi[]);
asmlinkage void gcm_ghash_p10(unsigned char *Xi, unsigned char *Htable,
- unsigned char *aad, unsigned int alen);
+ unsigned char *aad, unsigned int alen);
+asmlinkage void gcm_update(u8 *iv, void *Xi);
struct aes_key {
u8 key[AES_MAX_KEYLENGTH];
@@ -52,6 +55,7 @@ struct gcm_ctx {
u8 aad_hash[16];
u64 aadLen;
u64 Plen; /* offset 56 - used in aes_p10_gcm_{en/de}crypt */
+ u8 pblock[16];
};
struct Hash_ctx {
u8 H[16]; /* subkey */
@@ -60,17 +64,20 @@ struct Hash_ctx {
struct p10_aes_gcm_ctx {
struct aes_key enc_key;
+ u8 nonce[RFC4106_NONCE_SIZE];
};
static void vsx_begin(void)
{
preempt_disable();
+ pagefault_disable();
enable_kernel_vsx();
}
static void vsx_end(void)
{
disable_kernel_vsx();
+ pagefault_enable();
preempt_enable();
}
@@ -185,7 +192,7 @@ static int set_authsize(struct crypto_aead *tfm, unsigned int authsize)
}
static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key,
- unsigned int keylen)
+ unsigned int keylen)
{
struct crypto_tfm *tfm = crypto_aead_tfm(aead);
struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
@@ -198,7 +205,8 @@ static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key,
return ret ? -EINVAL : 0;
}
-static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
+static int p10_aes_gcm_crypt(struct aead_request *req, u8 *riv,
+ int assoclen, int enc)
{
struct crypto_tfm *tfm = req->base.tfm;
struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
@@ -210,7 +218,6 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
struct skcipher_walk walk;
u8 *assocmem = NULL;
u8 *assoc;
- unsigned int assoclen = req->assoclen;
unsigned int cryptlen = req->cryptlen;
unsigned char ivbuf[AES_BLOCK_SIZE+PPC_ALIGN];
unsigned char *iv = PTR_ALIGN((void *)ivbuf, PPC_ALIGN);
@@ -218,11 +225,12 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
unsigned long auth_tag_len = crypto_aead_authsize(__crypto_aead_cast(tfm));
u8 otag[16];
int total_processed = 0;
+ int nbytes;
memset(databuf, 0, sizeof(databuf));
memset(hashbuf, 0, sizeof(hashbuf));
memset(ivbuf, 0, sizeof(ivbuf));
- memcpy(iv, req->iv, GCM_IV_SIZE);
+ memcpy(iv, riv, GCM_IV_SIZE);
/* Linearize assoc, if not already linear */
if (req->src->length >= assoclen && req->src->length) {
@@ -257,19 +265,25 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
if (ret)
return ret;
- while (walk.nbytes > 0 && ret == 0) {
+ while ((nbytes = walk.nbytes) > 0 && ret == 0) {
+ u8 *src = walk.src.virt.addr;
+ u8 *dst = walk.dst.virt.addr;
+ u8 buf[AES_BLOCK_SIZE];
+
+ if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE))
+ src = dst = memcpy(buf, src, nbytes);
vsx_begin();
if (enc)
- aes_p10_gcm_encrypt(walk.src.virt.addr,
- walk.dst.virt.addr,
- walk.nbytes,
+ aes_p10_gcm_encrypt(src, dst, nbytes,
&ctx->enc_key, gctx->iv, hash->Htable);
else
- aes_p10_gcm_decrypt(walk.src.virt.addr,
- walk.dst.virt.addr,
- walk.nbytes,
+ aes_p10_gcm_decrypt(src, dst, nbytes,
&ctx->enc_key, gctx->iv, hash->Htable);
+
+ if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE))
+ memcpy(walk.dst.virt.addr, buf, nbytes);
+
vsx_end();
total_processed += walk.nbytes;
@@ -281,6 +295,7 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
/* Finalize hash */
vsx_begin();
+ gcm_update(gctx->iv, hash->Htable);
finish_tag(gctx, hash, total_processed);
vsx_end();
@@ -302,17 +317,63 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc)
return 0;
}
+static int rfc4106_setkey(struct crypto_aead *tfm, const u8 *inkey,
+ unsigned int keylen)
+{
+ struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(tfm);
+ int err;
+
+ keylen -= RFC4106_NONCE_SIZE;
+ err = p10_aes_gcm_setkey(tfm, inkey, keylen);
+ if (err)
+ return err;
+
+ memcpy(ctx->nonce, inkey + keylen, RFC4106_NONCE_SIZE);
+ return 0;
+}
+
+static int rfc4106_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
+{
+ return crypto_rfc4106_check_authsize(authsize);
+}
+
+static int rfc4106_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead);
+ u8 iv[AES_BLOCK_SIZE];
+
+ memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE);
+ memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE);
+
+ return crypto_ipsec_check_assoclen(req->assoclen) ?:
+ p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 1);
+}
+
+static int rfc4106_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead);
+ u8 iv[AES_BLOCK_SIZE];
+
+ memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE);
+ memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE);
+
+ return crypto_ipsec_check_assoclen(req->assoclen) ?:
+ p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 0);
+}
+
static int p10_aes_gcm_encrypt(struct aead_request *req)
{
- return p10_aes_gcm_crypt(req, 1);
+ return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 1);
}
static int p10_aes_gcm_decrypt(struct aead_request *req)
{
- return p10_aes_gcm_crypt(req, 0);
+ return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 0);
}
-static struct aead_alg gcm_aes_alg = {
+static struct aead_alg gcm_aes_algs[] = {{
.ivsize = GCM_IV_SIZE,
.maxauthsize = 16,
@@ -321,23 +382,57 @@ static struct aead_alg gcm_aes_alg = {
.encrypt = p10_aes_gcm_encrypt,
.decrypt = p10_aes_gcm_decrypt,
- .base.cra_name = "gcm(aes)",
- .base.cra_driver_name = "aes_gcm_p10",
+ .base.cra_name = "__gcm(aes)",
+ .base.cra_driver_name = "__aes_gcm_p10",
.base.cra_priority = 2100,
.base.cra_blocksize = 1,
- .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx),
+ .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx)+
+ 4 * sizeof(u64[2]),
.base.cra_module = THIS_MODULE,
-};
+ .base.cra_flags = CRYPTO_ALG_INTERNAL,
+}, {
+ .ivsize = GCM_RFC4106_IV_SIZE,
+ .maxauthsize = 16,
+ .setkey = rfc4106_setkey,
+ .setauthsize = rfc4106_setauthsize,
+ .encrypt = rfc4106_encrypt,
+ .decrypt = rfc4106_decrypt,
+
+ .base.cra_name = "__rfc4106(gcm(aes))",
+ .base.cra_driver_name = "__rfc4106_aes_gcm_p10",
+ .base.cra_priority = 2100,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx) +
+ 4 * sizeof(u64[2]),
+ .base.cra_module = THIS_MODULE,
+ .base.cra_flags = CRYPTO_ALG_INTERNAL,
+}};
+
+static struct simd_aead_alg *p10_simd_aeads[ARRAY_SIZE(gcm_aes_algs)];
static int __init p10_init(void)
{
- return crypto_register_aead(&gcm_aes_alg);
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_ARCH_31))
+ return 0;
+
+ ret = simd_register_aeads_compat(gcm_aes_algs,
+ ARRAY_SIZE(gcm_aes_algs),
+ p10_simd_aeads);
+ if (ret) {
+ simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs),
+ p10_simd_aeads);
+ return ret;
+ }
+ return 0;
}
static void __exit p10_exit(void)
{
- crypto_unregister_aead(&gcm_aes_alg);
+ simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs),
+ p10_simd_aeads);
}
-module_cpu_feature_match(PPC_MODULE_FEATURE_P10, p10_init);
+module_init(p10_init);
module_exit(p10_exit);
diff --git a/arch/powerpc/crypto/aes-gcm-p10.S b/arch/powerpc/crypto/aes-gcm-p10.S
index a51f4b265308..89f50eef3512 100644
--- a/arch/powerpc/crypto/aes-gcm-p10.S
+++ b/arch/powerpc/crypto/aes-gcm-p10.S
@@ -1,42 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
- #
- # Accelerated AES-GCM stitched implementation for ppc64le.
- #
- # Copyright 2022- IBM Inc. All rights reserved
- #
- #===================================================================================
- # Written by Danny Tsen <dtsen@linux.ibm.com>
- #
- # GHASH is based on the Karatsuba multiplication method.
- #
- # Xi xor X1
- #
- # X1 * H^4 + X2 * H^3 + x3 * H^2 + X4 * H =
- # (X1.h * H4.h + xX.l * H4.l + X1 * H4) +
- # (X2.h * H3.h + X2.l * H3.l + X2 * H3) +
- # (X3.h * H2.h + X3.l * H2.l + X3 * H2) +
- # (X4.h * H.h + X4.l * H.l + X4 * H)
- #
- # Xi = v0
- # H Poly = v2
- # Hash keys = v3 - v14
- # ( H.l, H, H.h)
- # ( H^2.l, H^2, H^2.h)
- # ( H^3.l, H^3, H^3.h)
- # ( H^4.l, H^4, H^4.h)
- #
- # v30 is IV
- # v31 - counter 1
- #
- # AES used,
- # vs0 - vs14 for round keys
- # v15, v16, v17, v18, v19, v20, v21, v22 for 8 blocks (encrypted)
- #
- # This implementation uses stitched AES-GCM approach to improve overall performance.
- # AES is implemented with 8x blocks and GHASH is using 2 4x blocks.
- #
- # ===================================================================================
- #
+#
+# Accelerated AES-GCM stitched implementation for ppc64le.
+#
+# Copyright 2024- IBM Inc.
+#
+#===================================================================================
+# Written by Danny Tsen <dtsen@us.ibm.com>
+#
+# GHASH is based on the Karatsuba multiplication method.
+#
+# Xi xor X1
+#
+# X1 * H^4 + X2 * H^3 + x3 * H^2 + X4 * H =
+# (X1.h * H4.h + xX.l * H4.l + X1 * H4) +
+# (X2.h * H3.h + X2.l * H3.l + X2 * H3) +
+# (X3.h * H2.h + X3.l * H2.l + X3 * H2) +
+# (X4.h * H.h + X4.l * H.l + X4 * H)
+#
+# Xi = v0
+# H Poly = v2
+# Hash keys = v3 - v14
+# ( H.l, H, H.h)
+# ( H^2.l, H^2, H^2.h)
+# ( H^3.l, H^3, H^3.h)
+# ( H^4.l, H^4, H^4.h)
+#
+# v30 is IV
+# v31 - counter 1
+#
+# AES used,
+# vs0 - round key 0
+# v15, v16, v17, v18, v19, v20, v21, v22 for 8 blocks (encrypted)
+#
+# This implementation uses stitched AES-GCM approach to improve overall performance.
+# AES is implemented with 8x blocks and GHASH is using 2 4x blocks.
+#
+# ===================================================================================
+#
#include <asm/ppc_asm.h>
#include <linux/linkage.h>
@@ -44,483 +44,224 @@
.machine "any"
.text
- # 4x loops
- # v15 - v18 - input states
- # vs1 - vs9 - round keys
- #
-.macro Loop_aes_middle4x
- xxlor 19+32, 1, 1
- xxlor 20+32, 2, 2
- xxlor 21+32, 3, 3
- xxlor 22+32, 4, 4
-
- vcipher 15, 15, 19
- vcipher 16, 16, 19
- vcipher 17, 17, 19
- vcipher 18, 18, 19
-
- vcipher 15, 15, 20
- vcipher 16, 16, 20
- vcipher 17, 17, 20
- vcipher 18, 18, 20
-
- vcipher 15, 15, 21
- vcipher 16, 16, 21
- vcipher 17, 17, 21
- vcipher 18, 18, 21
-
- vcipher 15, 15, 22
- vcipher 16, 16, 22
- vcipher 17, 17, 22
- vcipher 18, 18, 22
-
- xxlor 19+32, 5, 5
- xxlor 20+32, 6, 6
- xxlor 21+32, 7, 7
- xxlor 22+32, 8, 8
-
- vcipher 15, 15, 19
- vcipher 16, 16, 19
- vcipher 17, 17, 19
- vcipher 18, 18, 19
-
- vcipher 15, 15, 20
- vcipher 16, 16, 20
- vcipher 17, 17, 20
- vcipher 18, 18, 20
-
- vcipher 15, 15, 21
- vcipher 16, 16, 21
- vcipher 17, 17, 21
- vcipher 18, 18, 21
-
- vcipher 15, 15, 22
- vcipher 16, 16, 22
- vcipher 17, 17, 22
- vcipher 18, 18, 22
-
- xxlor 23+32, 9, 9
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
+.macro SAVE_GPR GPR OFFSET FRAME
+ std \GPR,\OFFSET(\FRAME)
.endm
- # 8x loops
- # v15 - v22 - input states
- # vs1 - vs9 - round keys
- #
-.macro Loop_aes_middle8x
- xxlor 23+32, 1, 1
- xxlor 24+32, 2, 2
- xxlor 25+32, 3, 3
- xxlor 26+32, 4, 4
-
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
- vcipher 19, 19, 23
- vcipher 20, 20, 23
- vcipher 21, 21, 23
- vcipher 22, 22, 23
-
- vcipher 15, 15, 24
- vcipher 16, 16, 24
- vcipher 17, 17, 24
- vcipher 18, 18, 24
- vcipher 19, 19, 24
- vcipher 20, 20, 24
- vcipher 21, 21, 24
- vcipher 22, 22, 24
-
- vcipher 15, 15, 25
- vcipher 16, 16, 25
- vcipher 17, 17, 25
- vcipher 18, 18, 25
- vcipher 19, 19, 25
- vcipher 20, 20, 25
- vcipher 21, 21, 25
- vcipher 22, 22, 25
-
- vcipher 15, 15, 26
- vcipher 16, 16, 26
- vcipher 17, 17, 26
- vcipher 18, 18, 26
- vcipher 19, 19, 26
- vcipher 20, 20, 26
- vcipher 21, 21, 26
- vcipher 22, 22, 26
-
- xxlor 23+32, 5, 5
- xxlor 24+32, 6, 6
- xxlor 25+32, 7, 7
- xxlor 26+32, 8, 8
-
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
- vcipher 19, 19, 23
- vcipher 20, 20, 23
- vcipher 21, 21, 23
- vcipher 22, 22, 23
-
- vcipher 15, 15, 24
- vcipher 16, 16, 24
- vcipher 17, 17, 24
- vcipher 18, 18, 24
- vcipher 19, 19, 24
- vcipher 20, 20, 24
- vcipher 21, 21, 24
- vcipher 22, 22, 24
-
- vcipher 15, 15, 25
- vcipher 16, 16, 25
- vcipher 17, 17, 25
- vcipher 18, 18, 25
- vcipher 19, 19, 25
- vcipher 20, 20, 25
- vcipher 21, 21, 25
- vcipher 22, 22, 25
-
- vcipher 15, 15, 26
- vcipher 16, 16, 26
- vcipher 17, 17, 26
- vcipher 18, 18, 26
- vcipher 19, 19, 26
- vcipher 20, 20, 26
- vcipher 21, 21, 26
- vcipher 22, 22, 26
-
- xxlor 23+32, 9, 9
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
- vcipher 19, 19, 23
- vcipher 20, 20, 23
- vcipher 21, 21, 23
- vcipher 22, 22, 23
+.macro SAVE_VRS VRS OFFSET FRAME
+ stxv \VRS+32, \OFFSET(\FRAME)
.endm
-.macro Loop_aes_middle_1x
- xxlor 19+32, 1, 1
- xxlor 20+32, 2, 2
- xxlor 21+32, 3, 3
- xxlor 22+32, 4, 4
-
- vcipher 15, 15, 19
- vcipher 15, 15, 20
- vcipher 15, 15, 21
- vcipher 15, 15, 22
-
- xxlor 19+32, 5, 5
- xxlor 20+32, 6, 6
- xxlor 21+32, 7, 7
- xxlor 22+32, 8, 8
-
- vcipher 15, 15, 19
- vcipher 15, 15, 20
- vcipher 15, 15, 21
- vcipher 15, 15, 22
-
- xxlor 19+32, 9, 9
- vcipher 15, 15, 19
+.macro RESTORE_GPR GPR OFFSET FRAME
+ ld \GPR,\OFFSET(\FRAME)
.endm
- #
- # Compute 4x hash values based on Karatsuba method.
- #
-.macro ppc_aes_gcm_ghash
- vxor 15, 15, 0
-
- vpmsumd 23, 12, 15 # H4.L * X.L
- vpmsumd 24, 9, 16
- vpmsumd 25, 6, 17
- vpmsumd 26, 3, 18
-
- vxor 23, 23, 24
- vxor 23, 23, 25
- vxor 23, 23, 26 # L
-
- vpmsumd 24, 13, 15 # H4.L * X.H + H4.H * X.L
- vpmsumd 25, 10, 16 # H3.L * X1.H + H3.H * X1.L
- vpmsumd 26, 7, 17
- vpmsumd 27, 4, 18
-
- vxor 24, 24, 25
- vxor 24, 24, 26
- vxor 24, 24, 27 # M
-
- # sum hash and reduction with H Poly
- vpmsumd 28, 23, 2 # reduction
-
- vxor 29, 29, 29
- vsldoi 26, 24, 29, 8 # mL
- vsldoi 29, 29, 24, 8 # mH
- vxor 23, 23, 26 # mL + L
-
- vsldoi 23, 23, 23, 8 # swap
- vxor 23, 23, 28
-
- vpmsumd 24, 14, 15 # H4.H * X.H
- vpmsumd 25, 11, 16
- vpmsumd 26, 8, 17
- vpmsumd 27, 5, 18
-
- vxor 24, 24, 25
- vxor 24, 24, 26
- vxor 24, 24, 27
-
- vxor 24, 24, 29
-
- # sum hash and reduction with H Poly
- vsldoi 27, 23, 23, 8 # swap
- vpmsumd 23, 23, 2
- vxor 27, 27, 24
- vxor 23, 23, 27
-
- xxlor 32, 23+32, 23+32 # update hash
-
+.macro RESTORE_VRS VRS OFFSET FRAME
+ lxv \VRS+32, \OFFSET(\FRAME)
.endm
- #
- # Combine two 4x ghash
- # v15 - v22 - input blocks
- #
-.macro ppc_aes_gcm_ghash2_4x
- # first 4x hash
- vxor 15, 15, 0 # Xi + X
-
- vpmsumd 23, 12, 15 # H4.L * X.L
- vpmsumd 24, 9, 16
- vpmsumd 25, 6, 17
- vpmsumd 26, 3, 18
-
- vxor 23, 23, 24
- vxor 23, 23, 25
- vxor 23, 23, 26 # L
-
- vpmsumd 24, 13, 15 # H4.L * X.H + H4.H * X.L
- vpmsumd 25, 10, 16 # H3.L * X1.H + H3.H * X1.L
- vpmsumd 26, 7, 17
- vpmsumd 27, 4, 18
-
- vxor 24, 24, 25
- vxor 24, 24, 26
-
- # sum hash and reduction with H Poly
- vpmsumd 28, 23, 2 # reduction
-
- vxor 29, 29, 29
-
- vxor 24, 24, 27 # M
- vsldoi 26, 24, 29, 8 # mL
- vsldoi 29, 29, 24, 8 # mH
- vxor 23, 23, 26 # mL + L
-
- vsldoi 23, 23, 23, 8 # swap
- vxor 23, 23, 28
+.macro SAVE_REGS
+ mflr 0
+ std 0, 16(1)
+ stdu 1,-512(1)
+
+ SAVE_GPR 14, 112, 1
+ SAVE_GPR 15, 120, 1
+ SAVE_GPR 16, 128, 1
+ SAVE_GPR 17, 136, 1
+ SAVE_GPR 18, 144, 1
+ SAVE_GPR 19, 152, 1
+ SAVE_GPR 20, 160, 1
+ SAVE_GPR 21, 168, 1
+ SAVE_GPR 22, 176, 1
+ SAVE_GPR 23, 184, 1
+ SAVE_GPR 24, 192, 1
+
+ addi 9, 1, 256
+ SAVE_VRS 20, 0, 9
+ SAVE_VRS 21, 16, 9
+ SAVE_VRS 22, 32, 9
+ SAVE_VRS 23, 48, 9
+ SAVE_VRS 24, 64, 9
+ SAVE_VRS 25, 80, 9
+ SAVE_VRS 26, 96, 9
+ SAVE_VRS 27, 112, 9
+ SAVE_VRS 28, 128, 9
+ SAVE_VRS 29, 144, 9
+ SAVE_VRS 30, 160, 9
+ SAVE_VRS 31, 176, 9
+.endm # SAVE_REGS
- vpmsumd 24, 14, 15 # H4.H * X.H
- vpmsumd 25, 11, 16
- vpmsumd 26, 8, 17
- vpmsumd 27, 5, 18
+.macro RESTORE_REGS
+ addi 9, 1, 256
+ RESTORE_VRS 20, 0, 9
+ RESTORE_VRS 21, 16, 9
+ RESTORE_VRS 22, 32, 9
+ RESTORE_VRS 23, 48, 9
+ RESTORE_VRS 24, 64, 9
+ RESTORE_VRS 25, 80, 9
+ RESTORE_VRS 26, 96, 9
+ RESTORE_VRS 27, 112, 9
+ RESTORE_VRS 28, 128, 9
+ RESTORE_VRS 29, 144, 9
+ RESTORE_VRS 30, 160, 9
+ RESTORE_VRS 31, 176, 9
+
+ RESTORE_GPR 14, 112, 1
+ RESTORE_GPR 15, 120, 1
+ RESTORE_GPR 16, 128, 1
+ RESTORE_GPR 17, 136, 1
+ RESTORE_GPR 18, 144, 1
+ RESTORE_GPR 19, 152, 1
+ RESTORE_GPR 20, 160, 1
+ RESTORE_GPR 21, 168, 1
+ RESTORE_GPR 22, 176, 1
+ RESTORE_GPR 23, 184, 1
+ RESTORE_GPR 24, 192, 1
+
+ addi 1, 1, 512
+ ld 0, 16(1)
+ mtlr 0
+.endm # RESTORE_REGS
+
+# 4x loops
+.macro AES_CIPHER_4x _VCIPHER ST r
+ \_VCIPHER \ST, \ST, \r
+ \_VCIPHER \ST+1, \ST+1, \r
+ \_VCIPHER \ST+2, \ST+2, \r
+ \_VCIPHER \ST+3, \ST+3, \r
+.endm
- vxor 24, 24, 25
- vxor 24, 24, 26
- vxor 24, 24, 27 # H
+# 8x loops
+.macro AES_CIPHER_8x _VCIPHER ST r
+ \_VCIPHER \ST, \ST, \r
+ \_VCIPHER \ST+1, \ST+1, \r
+ \_VCIPHER \ST+2, \ST+2, \r
+ \_VCIPHER \ST+3, \ST+3, \r
+ \_VCIPHER \ST+4, \ST+4, \r
+ \_VCIPHER \ST+5, \ST+5, \r
+ \_VCIPHER \ST+6, \ST+6, \r
+ \_VCIPHER \ST+7, \ST+7, \r
+.endm
- vxor 24, 24, 29 # H + mH
+.macro LOOP_8AES_STATE
+ xxlor 32+23, 1, 1
+ xxlor 32+24, 2, 2
+ xxlor 32+25, 3, 3
+ xxlor 32+26, 4, 4
+ AES_CIPHER_8x vcipher, 15, 23
+ AES_CIPHER_8x vcipher, 15, 24
+ AES_CIPHER_8x vcipher, 15, 25
+ AES_CIPHER_8x vcipher, 15, 26
+ xxlor 32+23, 5, 5
+ xxlor 32+24, 6, 6
+ xxlor 32+25, 7, 7
+ xxlor 32+26, 8, 8
+ AES_CIPHER_8x vcipher, 15, 23
+ AES_CIPHER_8x vcipher, 15, 24
+ AES_CIPHER_8x vcipher, 15, 25
+ AES_CIPHER_8x vcipher, 15, 26
+.endm
- # sum hash and reduction with H Poly
- vsldoi 27, 23, 23, 8 # swap
- vpmsumd 23, 23, 2
- vxor 27, 27, 24
- vxor 27, 23, 27 # 1st Xi
-
- # 2nd 4x hash
- vpmsumd 24, 9, 20
- vpmsumd 25, 6, 21
- vpmsumd 26, 3, 22
- vxor 19, 19, 27 # Xi + X
- vpmsumd 23, 12, 19 # H4.L * X.L
-
- vxor 23, 23, 24
- vxor 23, 23, 25
- vxor 23, 23, 26 # L
-
- vpmsumd 24, 13, 19 # H4.L * X.H + H4.H * X.L
- vpmsumd 25, 10, 20 # H3.L * X1.H + H3.H * X1.L
- vpmsumd 26, 7, 21
- vpmsumd 27, 4, 22
-
- vxor 24, 24, 25
- vxor 24, 24, 26
+#
+# PPC_GHASH4x(H, S1, S2, S3, S4): Compute 4x hash values based on Karatsuba method.
+# H: returning digest
+# S#: states
+#
+# S1 should xor with the previous digest
+#
+# Xi = v0
+# H Poly = v2
+# Hash keys = v3 - v14
+# Scratch: v23 - v29
+#
+.macro PPC_GHASH4x H S1 S2 S3 S4
+
+ vpmsumd 23, 12, \S1 # H4.L * X.L
+ vpmsumd 24, 9, \S2
+ vpmsumd 25, 6, \S3
+ vpmsumd 26, 3, \S4
+
+ vpmsumd 27, 13, \S1 # H4.L * X.H + H4.H * X.L
+ vpmsumd 28, 10, \S2 # H3.L * X1.H + H3.H * X1.L
+
+ vxor 23, 23, 24
+ vxor 23, 23, 25
+ vxor 23, 23, 26 # L
+
+ vxor 24, 27, 28
+ vpmsumd 25, 7, \S3
+ vpmsumd 26, 4, \S4
+
+ vxor 24, 24, 25
+ vxor 24, 24, 26 # M
# sum hash and reduction with H Poly
- vpmsumd 28, 23, 2 # reduction
-
- vxor 29, 29, 29
+ vpmsumd 28, 23, 2 # reduction
- vxor 24, 24, 27 # M
- vsldoi 26, 24, 29, 8 # mL
- vsldoi 29, 29, 24, 8 # mH
- vxor 23, 23, 26 # mL + L
+ vxor 1, 1, 1
+ vsldoi 25, 24, 1, 8 # mL
+ vsldoi 1, 1, 24, 8 # mH
+ vxor 23, 23, 25 # mL + L
- vsldoi 23, 23, 23, 8 # swap
- vxor 23, 23, 28
+ # This performs swap and xor like,
+ # vsldoi 23, 23, 23, 8 # swap
+ # vxor 23, 23, 28
+ xxlor 32+25, 10, 10
+ vpermxor 23, 23, 28, 25
- vpmsumd 24, 14, 19 # H4.H * X.H
- vpmsumd 25, 11, 20
- vpmsumd 26, 8, 21
- vpmsumd 27, 5, 22
+ vpmsumd 26, 14, \S1 # H4.H * X.H
+ vpmsumd 27, 11, \S2
+ vpmsumd 28, 8, \S3
+ vpmsumd 29, 5, \S4
- vxor 24, 24, 25
- vxor 24, 24, 26
- vxor 24, 24, 27 # H
+ vxor 24, 26, 27
+ vxor 24, 24, 28
+ vxor 24, 24, 29
- vxor 24, 24, 29 # H + mH
+ vxor 24, 24, 1
# sum hash and reduction with H Poly
- vsldoi 27, 23, 23, 8 # swap
- vpmsumd 23, 23, 2
- vxor 27, 27, 24
- vxor 23, 23, 27
-
- xxlor 32, 23+32, 23+32 # update hash
-
+ vsldoi 25, 23, 23, 8 # swap
+ vpmsumd 23, 23, 2
+ vxor 27, 25, 24
+ vxor \H, 23, 27
.endm
- #
- # Compute update single hash
- #
-.macro ppc_update_hash_1x
- vxor 28, 28, 0
-
- vxor 19, 19, 19
+#
+# Compute update single ghash
+# scratch: v1, v22..v27
+#
+.macro PPC_GHASH1x H S1
- vpmsumd 22, 3, 28 # L
- vpmsumd 23, 4, 28 # M
- vpmsumd 24, 5, 28 # H
+ vxor 1, 1, 1
- vpmsumd 27, 22, 2 # reduction
+ vpmsumd 22, 3, \S1 # L
+ vpmsumd 23, 4, \S1 # M
+ vpmsumd 24, 5, \S1 # H
- vsldoi 25, 23, 19, 8 # mL
- vsldoi 26, 19, 23, 8 # mH
- vxor 22, 22, 25 # LL + LL
- vxor 24, 24, 26 # HH + HH
+ vpmsumd 27, 22, 2 # reduction
- vsldoi 22, 22, 22, 8 # swap
- vxor 22, 22, 27
+ vsldoi 25, 23, 1, 8 # mL
+ vsldoi 26, 1, 23, 8 # mH
+ vxor 22, 22, 25 # LL + LL
+ vxor 24, 24, 26 # HH + HH
- vsldoi 20, 22, 22, 8 # swap
- vpmsumd 22, 22, 2 # reduction
- vxor 20, 20, 24
- vxor 22, 22, 20
+ xxlor 32+25, 10, 10
+ vpermxor 22, 22, 27, 25
- vmr 0, 22 # update hash
-
-.endm
-
-.macro SAVE_REGS
- stdu 1,-640(1)
- mflr 0
-
- std 14,112(1)
- std 15,120(1)
- std 16,128(1)
- std 17,136(1)
- std 18,144(1)
- std 19,152(1)
- std 20,160(1)
- std 21,168(1)
- li 9, 256
- stvx 20, 9, 1
- addi 9, 9, 16
- stvx 21, 9, 1
- addi 9, 9, 16
- stvx 22, 9, 1
- addi 9, 9, 16
- stvx 23, 9, 1
- addi 9, 9, 16
- stvx 24, 9, 1
- addi 9, 9, 16
- stvx 25, 9, 1
- addi 9, 9, 16
- stvx 26, 9, 1
- addi 9, 9, 16
- stvx 27, 9, 1
- addi 9, 9, 16
- stvx 28, 9, 1
- addi 9, 9, 16
- stvx 29, 9, 1
- addi 9, 9, 16
- stvx 30, 9, 1
- addi 9, 9, 16
- stvx 31, 9, 1
- stxv 14, 464(1)
- stxv 15, 480(1)
- stxv 16, 496(1)
- stxv 17, 512(1)
- stxv 18, 528(1)
- stxv 19, 544(1)
- stxv 20, 560(1)
- stxv 21, 576(1)
- stxv 22, 592(1)
- std 0, 656(1)
-.endm
-
-.macro RESTORE_REGS
- lxv 14, 464(1)
- lxv 15, 480(1)
- lxv 16, 496(1)
- lxv 17, 512(1)
- lxv 18, 528(1)
- lxv 19, 544(1)
- lxv 20, 560(1)
- lxv 21, 576(1)
- lxv 22, 592(1)
- li 9, 256
- lvx 20, 9, 1
- addi 9, 9, 16
- lvx 21, 9, 1
- addi 9, 9, 16
- lvx 22, 9, 1
- addi 9, 9, 16
- lvx 23, 9, 1
- addi 9, 9, 16
- lvx 24, 9, 1
- addi 9, 9, 16
- lvx 25, 9, 1
- addi 9, 9, 16
- lvx 26, 9, 1
- addi 9, 9, 16
- lvx 27, 9, 1
- addi 9, 9, 16
- lvx 28, 9, 1
- addi 9, 9, 16
- lvx 29, 9, 1
- addi 9, 9, 16
- lvx 30, 9, 1
- addi 9, 9, 16
- lvx 31, 9, 1
-
- ld 0, 656(1)
- ld 14,112(1)
- ld 15,120(1)
- ld 16,128(1)
- ld 17,136(1)
- ld 18,144(1)
- ld 19,152(1)
- ld 20,160(1)
- ld 21,168(1)
-
- mtlr 0
- addi 1, 1, 640
+ vsldoi 23, 22, 22, 8 # swap
+ vpmsumd 22, 22, 2 # reduction
+ vxor 23, 23, 24
+ vxor \H, 22, 23
.endm
+#
+# LOAD_HASH_TABLE
+# Xi = v0
+# H Poly = v2
+# Hash keys = v3 - v14
+#
.macro LOAD_HASH_TABLE
# Load Xi
lxvb16x 32, 0, 8 # load Xi
@@ -557,657 +298,434 @@
lxvd2x 14+32, 10, 8 # H^4h
.endm
- #
- # aes_p10_gcm_encrypt (const void *inp, void *out, size_t len,
- # const char *rk, unsigned char iv[16], void *Xip);
- #
- # r3 - inp
- # r4 - out
- # r5 - len
- # r6 - AES round keys
- # r7 - iv and other data
- # r8 - Xi, HPoli, hash keys
- #
- # rounds is at offset 240 in rk
- # Xi is at 0 in gcm_table (Xip).
- #
-_GLOBAL(aes_p10_gcm_encrypt)
-.align 5
-
- SAVE_REGS
-
- LOAD_HASH_TABLE
-
- # initialize ICB: GHASH( IV ), IV - r7
- lxvb16x 30+32, 0, 7 # load IV - v30
-
- mr 12, 5 # length
- li 11, 0 # block index
-
- # counter 1
- vxor 31, 31, 31
- vspltisb 22, 1
- vsldoi 31, 31, 22,1 # counter 1
-
- # load round key to VSR
- lxv 0, 0(6)
- lxv 1, 0x10(6)
- lxv 2, 0x20(6)
- lxv 3, 0x30(6)
- lxv 4, 0x40(6)
- lxv 5, 0x50(6)
- lxv 6, 0x60(6)
- lxv 7, 0x70(6)
- lxv 8, 0x80(6)
- lxv 9, 0x90(6)
- lxv 10, 0xa0(6)
-
- # load rounds - 10 (128), 12 (192), 14 (256)
- lwz 9,240(6)
-
- #
- # vxor state, state, w # addroundkey
- xxlor 32+29, 0, 0
- vxor 15, 30, 29 # IV + round key - add round key 0
-
- cmpdi 9, 10
- beq Loop_aes_gcm_8x
-
- # load 2 more round keys (v11, v12)
- lxv 11, 0xb0(6)
- lxv 12, 0xc0(6)
-
- cmpdi 9, 12
- beq Loop_aes_gcm_8x
-
- # load 2 more round keys (v11, v12, v13, v14)
- lxv 13, 0xd0(6)
- lxv 14, 0xe0(6)
- cmpdi 9, 14
- beq Loop_aes_gcm_8x
-
- b aes_gcm_out
-
-.align 5
-Loop_aes_gcm_8x:
- mr 14, 3
- mr 9, 4
-
- #
- # check partial block
- #
-Continue_partial_check:
- ld 15, 56(7)
- cmpdi 15, 0
- beq Continue
- bgt Final_block
- cmpdi 15, 16
- blt Final_block
-
-Continue:
- # n blcoks
- li 10, 128
- divdu 10, 12, 10 # n 128 bytes-blocks
- cmpdi 10, 0
- beq Loop_last_block
-
- vaddudm 30, 30, 31 # IV + counter
- vxor 16, 30, 29
- vaddudm 30, 30, 31
- vxor 17, 30, 29
- vaddudm 30, 30, 31
- vxor 18, 30, 29
- vaddudm 30, 30, 31
- vxor 19, 30, 29
- vaddudm 30, 30, 31
- vxor 20, 30, 29
- vaddudm 30, 30, 31
- vxor 21, 30, 29
- vaddudm 30, 30, 31
- vxor 22, 30, 29
-
- mtctr 10
-
- li 15, 16
- li 16, 32
- li 17, 48
- li 18, 64
- li 19, 80
- li 20, 96
- li 21, 112
-
- lwz 10, 240(6)
-
-Loop_8x_block:
-
- lxvb16x 15, 0, 14 # load block
- lxvb16x 16, 15, 14 # load block
- lxvb16x 17, 16, 14 # load block
- lxvb16x 18, 17, 14 # load block
- lxvb16x 19, 18, 14 # load block
- lxvb16x 20, 19, 14 # load block
- lxvb16x 21, 20, 14 # load block
- lxvb16x 22, 21, 14 # load block
- addi 14, 14, 128
-
- Loop_aes_middle8x
-
- xxlor 23+32, 10, 10
-
- cmpdi 10, 10
- beq Do_next_ghash
-
- # 192 bits
- xxlor 24+32, 11, 11
-
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
- vcipher 19, 19, 23
- vcipher 20, 20, 23
- vcipher 21, 21, 23
- vcipher 22, 22, 23
-
- vcipher 15, 15, 24
- vcipher 16, 16, 24
- vcipher 17, 17, 24
- vcipher 18, 18, 24
- vcipher 19, 19, 24
- vcipher 20, 20, 24
- vcipher 21, 21, 24
- vcipher 22, 22, 24
-
- xxlor 23+32, 12, 12
-
- cmpdi 10, 12
- beq Do_next_ghash
-
- # 256 bits
- xxlor 24+32, 13, 13
-
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
- vcipher 19, 19, 23
- vcipher 20, 20, 23
- vcipher 21, 21, 23
- vcipher 22, 22, 23
-
- vcipher 15, 15, 24
- vcipher 16, 16, 24
- vcipher 17, 17, 24
- vcipher 18, 18, 24
- vcipher 19, 19, 24
- vcipher 20, 20, 24
- vcipher 21, 21, 24
- vcipher 22, 22, 24
-
- xxlor 23+32, 14, 14
-
- cmpdi 10, 14
- beq Do_next_ghash
- b aes_gcm_out
-
-Do_next_ghash:
-
- #
- # last round
- vcipherlast 15, 15, 23
- vcipherlast 16, 16, 23
-
- xxlxor 47, 47, 15
- stxvb16x 47, 0, 9 # store output
- xxlxor 48, 48, 16
- stxvb16x 48, 15, 9 # store output
-
- vcipherlast 17, 17, 23
- vcipherlast 18, 18, 23
-
- xxlxor 49, 49, 17
- stxvb16x 49, 16, 9 # store output
- xxlxor 50, 50, 18
- stxvb16x 50, 17, 9 # store output
-
- vcipherlast 19, 19, 23
- vcipherlast 20, 20, 23
-
- xxlxor 51, 51, 19
- stxvb16x 51, 18, 9 # store output
- xxlxor 52, 52, 20
- stxvb16x 52, 19, 9 # store output
-
- vcipherlast 21, 21, 23
- vcipherlast 22, 22, 23
-
- xxlxor 53, 53, 21
- stxvb16x 53, 20, 9 # store output
- xxlxor 54, 54, 22
- stxvb16x 54, 21, 9 # store output
-
- addi 9, 9, 128
-
- # ghash here
- ppc_aes_gcm_ghash2_4x
-
- xxlor 27+32, 0, 0
- vaddudm 30, 30, 31 # IV + counter
- vmr 29, 30
- vxor 15, 30, 27 # add round key
- vaddudm 30, 30, 31
- vxor 16, 30, 27
- vaddudm 30, 30, 31
- vxor 17, 30, 27
- vaddudm 30, 30, 31
- vxor 18, 30, 27
- vaddudm 30, 30, 31
- vxor 19, 30, 27
- vaddudm 30, 30, 31
- vxor 20, 30, 27
- vaddudm 30, 30, 31
- vxor 21, 30, 27
- vaddudm 30, 30, 31
- vxor 22, 30, 27
-
- addi 12, 12, -128
- addi 11, 11, 128
-
- bdnz Loop_8x_block
-
- vmr 30, 29
- stxvb16x 30+32, 0, 7 # update IV
-
-Loop_last_block:
- cmpdi 12, 0
- beq aes_gcm_out
-
- # loop last few blocks
+################################################################################
+# Compute AES and ghash one block at a time.
+# r23: AES rounds
+# v30: current IV
+# vs0: roundkey 0
+#
+################################################################################
+SYM_FUNC_START_LOCAL(aes_gcm_crypt_1x)
+
+ cmpdi 5, 16
+ bge __More_1x
+ blr
+__More_1x:
li 10, 16
- divdu 10, 12, 10
-
- mtctr 10
-
- lwz 10, 240(6)
-
- cmpdi 12, 16
- blt Final_block
-
-Next_rem_block:
- lxvb16x 15, 0, 14 # load block
-
- Loop_aes_middle_1x
-
- xxlor 23+32, 10, 10
-
- cmpdi 10, 10
- beq Do_next_1x
-
- # 192 bits
- xxlor 24+32, 11, 11
-
- vcipher 15, 15, 23
- vcipher 15, 15, 24
-
- xxlor 23+32, 12, 12
+ divdu 12, 5, 10
+
+ xxlxor 32+15, 32+30, 0
+
+ # Pre-load 8 AES rounds to scratch vectors.
+ xxlor 32+16, 1, 1
+ xxlor 32+17, 2, 2
+ xxlor 32+18, 3, 3
+ xxlor 32+19, 4, 4
+ xxlor 32+20, 5, 5
+ xxlor 32+21, 6, 6
+ xxlor 32+28, 7, 7
+ xxlor 32+29, 8, 8
+ lwz 23, 240(6) # n rounds
+ addi 22, 23, -9 # remaing AES rounds
- cmpdi 10, 12
- beq Do_next_1x
-
- # 256 bits
- xxlor 24+32, 13, 13
-
- vcipher 15, 15, 23
- vcipher 15, 15, 24
-
- xxlor 23+32, 14, 14
-
- cmpdi 10, 14
- beq Do_next_1x
-
-Do_next_1x:
- vcipherlast 15, 15, 23
-
- xxlxor 47, 47, 15
- stxvb16x 47, 0, 9 # store output
- addi 14, 14, 16
- addi 9, 9, 16
-
- vmr 28, 15
- ppc_update_hash_1x
-
- addi 12, 12, -16
- addi 11, 11, 16
- xxlor 19+32, 0, 0
- vaddudm 30, 30, 31 # IV + counter
- vxor 15, 30, 19 # add round key
-
- bdnz Next_rem_block
-
- li 15, 0
- std 15, 56(7) # clear partial?
- stxvb16x 30+32, 0, 7 # update IV
cmpdi 12, 0
- beq aes_gcm_out
-
-Final_block:
- lwz 10, 240(6)
- Loop_aes_middle_1x
-
- xxlor 23+32, 10, 10
-
- cmpdi 10, 10
- beq Do_final_1x
-
- # 192 bits
- xxlor 24+32, 11, 11
-
- vcipher 15, 15, 23
- vcipher 15, 15, 24
-
- xxlor 23+32, 12, 12
-
- cmpdi 10, 12
- beq Do_final_1x
-
- # 256 bits
- xxlor 24+32, 13, 13
-
- vcipher 15, 15, 23
- vcipher 15, 15, 24
+ bgt __Loop_1x
+ blr
- xxlor 23+32, 14, 14
+__Loop_1x:
+ mtctr 22
+ addi 10, 6, 144
+ vcipher 15, 15, 16
+ vcipher 15, 15, 17
+ vcipher 15, 15, 18
+ vcipher 15, 15, 19
+ vcipher 15, 15, 20
+ vcipher 15, 15, 21
+ vcipher 15, 15, 28
+ vcipher 15, 15, 29
- cmpdi 10, 14
- beq Do_final_1x
+__Loop_aes_1state:
+ lxv 32+1, 0(10)
+ vcipher 15, 15, 1
+ addi 10, 10, 16
+ bdnz __Loop_aes_1state
+ lxv 32+1, 0(10) # last round key
+ lxvb16x 11, 0, 14 # load input block
+ vcipherlast 15, 15, 1
+
+ xxlxor 32+15, 32+15, 11
+ stxvb16x 32+15, 0, 9 # store output
+ addi 14, 14, 16
+ addi 9, 9, 16
-Do_final_1x:
- vcipherlast 15, 15, 23
+ cmpdi 24, 0 # decrypt?
+ bne __Encrypt_1x
+ xxlor 15+32, 11, 11
+__Encrypt_1x:
+ vxor 15, 15, 0
+ PPC_GHASH1x 0, 15
- # check partial block
- li 21, 0 # encrypt
- ld 15, 56(7) # partial?
- cmpdi 15, 0
- beq Normal_block
- bl Do_partial_block
+ addi 5, 5, -16
+ addi 11, 11, 16
+ vadduwm 30, 30, 31 # IV + counter
+ xxlxor 32+15, 32+30, 0
+ addi 12, 12, -1
cmpdi 12, 0
- ble aes_gcm_out
+ bgt __Loop_1x
- b Continue_partial_check
-
-Normal_block:
- lxvb16x 15, 0, 14 # load last block
- xxlxor 47, 47, 15
-
- # create partial block mask
- li 15, 16
- sub 15, 15, 12 # index to the mask
-
- vspltisb 16, -1 # first 16 bytes - 0xffff...ff
- vspltisb 17, 0 # second 16 bytes - 0x0000...00
- li 10, 192
- stvx 16, 10, 1
+ stxvb16x 32+30, 0, 7 # update IV
+ stxvb16x 32+0, 0, 8 # update Xi
+ blr
+SYM_FUNC_END(aes_gcm_crypt_1x)
+
+################################################################################
+# Process a normal partial block when we come here.
+# Compute partial mask, Load and store partial block to stack.
+# Update partial_len and pblock.
+# pblock is (encrypted ^ AES state) for encrypt
+# and (input ^ AES state) for decrypt.
+#
+################################################################################
+SYM_FUNC_START_LOCAL(__Process_partial)
+
+ # create partial mask
+ vspltisb 16, -1
+ li 12, 16
+ sub 12, 12, 5
+ sldi 12, 12, 3
+ mtvsrdd 32+17, 0, 12
+ vslo 16, 16, 17 # partial block mask
+
+ lxvb16x 11, 0, 14 # load partial block
+ xxland 11, 11, 32+16
+
+ # AES crypt partial
+ xxlxor 32+15, 32+30, 0
+ lwz 23, 240(6) # n rounds
+ addi 22, 23, -1 # loop - 1
+ mtctr 22
+ addi 10, 6, 16
+
+__Loop_aes_pstate:
+ lxv 32+1, 0(10)
+ vcipher 15, 15, 1
addi 10, 10, 16
- stvx 17, 10, 1
-
- addi 10, 1, 192
- lxvb16x 16, 15, 10 # load partial block mask
- xxland 47, 47, 16
-
- vmr 28, 15
- ppc_update_hash_1x
+ bdnz __Loop_aes_pstate
+ lxv 32+1, 0(10) # last round key
+ vcipherlast 15, 15, 1
- # * should store only the remaining bytes.
- bl Write_partial_block
-
- stxvb16x 30+32, 0, 7 # update IV
- std 12, 56(7) # update partial?
- li 16, 16
+ xxlxor 32+15, 32+15, 11
+ vand 15, 15, 16
- stxvb16x 32, 0, 8 # write out Xi
- stxvb16x 32, 16, 8 # write out Xi
- b aes_gcm_out
-
- #
- # Compute data mask
- #
-.macro GEN_MASK _mask _start _end
- vspltisb 16, -1 # first 16 bytes - 0xffff...ff
- vspltisb 17, 0 # second 16 bytes - 0x0000...00
- li 10, 192
- stxvb16x 17+32, 10, 1
- add 10, 10, \_start
- stxvb16x 16+32, 10, 1
- add 10, 10, \_end
- stxvb16x 17+32, 10, 1
-
- addi 10, 1, 192
- lxvb16x \_mask, 0, 10 # load partial block mask
-.endm
+ # AES crypt output v15
+ # Write partial
+ li 10, 224
+ stxvb16x 15+32, 10, 1 # write v15 to stack
+ addi 10, 1, 223
+ addi 12, 9, -1
+ mtctr 5 # partial block len
+__Write_partial:
+ lbzu 22, 1(10)
+ stbu 22, 1(12)
+ bdnz __Write_partial
+
+ cmpdi 24, 0 # decrypt?
+ bne __Encrypt_partial
+ xxlor 32+15, 11, 11 # decrypt using the input block
+__Encrypt_partial:
+ #vxor 15, 15, 0 # ^ previous hash
+ #PPC_GHASH1x 0, 15
+
+ add 14, 14, 5
+ add 9, 9, 5
+ std 5, 56(7) # update partial
+ sub 11, 11, 5
+ li 5, 0 # done last byte
- #
- # Handle multiple partial blocks for encrypt and decrypt
- # operations.
- #
-SYM_FUNC_START_LOCAL(Do_partial_block)
- add 17, 15, 5
- cmpdi 17, 16
- bgt Big_block
- GEN_MASK 18, 15, 5
- b _Partial
-SYM_FUNC_END(Do_partial_block)
-Big_block:
+ #
+ # Don't increase IV since this is the last partial.
+ # It should get updated in gcm_update if no more data blocks.
+ #vadduwm 30, 30, 31 # increase IV
+ stxvb16x 32+30, 0, 7 # update IV
+ li 10, 64
+ stxvb16x 32+0, 0, 8 # Update X1
+ stxvb16x 32+15, 10, 7 # Update pblock
+ blr
+SYM_FUNC_END(__Process_partial)
+
+################################################################################
+# Combine partial blocks and ghash when we come here.
+#
+# The partial block has to be shifted to the right location to encrypt/decrypt
+# and compute ghash if combing the previous partial block is needed.
+# - Compute ghash for a full block. Clear Partial_len and pblock. Update IV.
+# Write Xi.
+# - Don't compute ghash if not full block. gcm_update will take care of it
+# is the last block. Update Partial_len and pblock.
+#
+################################################################################
+SYM_FUNC_START_LOCAL(__Combine_partial)
+
+ ld 12, 56(7)
+ mr 21, 5 # these bytes to be processed
+
+ li 17, 0
li 16, 16
- GEN_MASK 18, 15, 16
-
-_Partial:
- lxvb16x 17+32, 0, 14 # load last block
- sldi 16, 15, 3
- mtvsrdd 32+16, 0, 16
- vsro 17, 17, 16
- xxlxor 47, 47, 17+32
- xxland 47, 47, 18
-
- vxor 0, 0, 0 # clear Xi
- vmr 28, 15
-
- cmpdi 21, 0 # encrypt/decrypt ops?
- beq Skip_decrypt
- xxland 32+28, 32+17, 18
-
-Skip_decrypt:
-
- ppc_update_hash_1x
+ sub 22, 16, 12 # bytes to complete a block
+ sub 17, 22, 5 # remaining bytes in a block
+ cmpdi 5, 16
+ ble __Inp_msg_less16
+ li 17, 0
+ mr 21, 22
+ b __Combine_continue
+__Inp_msg_less16:
+ cmpd 22, 5
+ bgt __Combine_continue
+ li 17, 0
+ mr 21, 22 # these bytes to be processed
+
+__Combine_continue:
+ # load msg and shift to the proper location and mask
+ vspltisb 16, -1
+ sldi 15, 12, 3
+ mtvsrdd 32+17, 0, 15
+ vslo 16, 16, 17
+ vsro 16, 16, 17
+ sldi 15, 17, 3
+ mtvsrdd 32+17, 0, 15
+ vsro 16, 16, 17
+ vslo 16, 16, 17 # mask
+
+ lxvb16x 32+19, 0, 14 # load partial block
+ sldi 15, 12, 3
+ mtvsrdd 32+17, 0, 15
+ vsro 19, 19, 17 # 0x00..xxxx??..??
+ sldi 15, 17, 3
+ mtvsrdd 32+17, 0, 15
+ vsro 19, 19, 17 # 0x00..xxxx
+ vslo 19, 19, 17 # shift back to form 0x00..xxxx00..00
+
+ # AES crypt partial
+ xxlxor 32+15, 32+30, 0
+ lwz 23, 240(6) # n rounds
+ addi 22, 23, -1 # loop - 1
+ mtctr 22
+ addi 10, 6, 16
+
+__Loop_aes_cpstate:
+ lxv 32+1, 0(10)
+ vcipher 15, 15, 1
+ addi 10, 10, 16
+ bdnz __Loop_aes_cpstate
+ lxv 32+1, 0(10) # last round key
+ vcipherlast 15, 15, 1
- li 16, 16
- lxvb16x 32+29, 16, 8
- vxor 0, 0, 29
- stxvb16x 32, 0, 8 # save Xi
- stxvb16x 32, 16, 8 # save Xi
-
- # store partial block
- # loop the rest of the stream if any
- sldi 16, 15, 3
- mtvsrdd 32+16, 0, 16
- vslo 15, 15, 16
- #stxvb16x 15+32, 0, 9 # last block
+ vxor 15, 15, 19
+ vand 15, 15, 16
- li 16, 16
- sub 17, 16, 15 # 16 - partial
-
- add 16, 15, 5
- cmpdi 16, 16
- bgt Larger_16
- mr 17, 5
-Larger_16:
-
- # write partial
- li 10, 192
- stxvb16x 15+32, 10, 1 # save current block
-
- addi 10, 9, -1
- addi 16, 1, 191
- mtctr 17 # move partial byte count
-
-Write_last_partial:
- lbzu 18, 1(16)
- stbu 18, 1(10)
- bdnz Write_last_partial
- # Complete loop partial
-
- add 14, 14, 17
- add 9, 9, 17
- sub 12, 12, 17
- add 11, 11, 17
-
- add 15, 15, 5
- cmpdi 15, 16
- blt Save_partial
-
- vaddudm 30, 30, 31
- stxvb16x 30+32, 0, 7 # update IV
- xxlor 32+29, 0, 0
- vxor 15, 30, 29 # IV + round key - add round key 0
- li 15, 0
- std 15, 56(7) # partial done - clear
- b Partial_done
-Save_partial:
- std 15, 56(7) # partial
-
-Partial_done:
+ # AES crypt output v15
+ # Write partial
+ li 10, 224
+ stxvb16x 15+32, 10, 1 # write v15 to stack
+ addi 10, 1, 223
+ add 10, 10, 12 # add offset
+ addi 15, 9, -1
+ mtctr 21 # partial block len
+__Write_combine_partial:
+ lbzu 22, 1(10)
+ stbu 22, 1(15)
+ bdnz __Write_combine_partial
+
+ add 14, 14, 21
+ add 11, 11, 21
+ add 9, 9, 21
+ sub 5, 5, 21
+
+ # Encrypt/Decrypt?
+ cmpdi 24, 0 # decrypt?
+ bne __Encrypt_combine_partial
+ vmr 15, 19 # decrypt using the input block
+
+__Encrypt_combine_partial:
+ #
+ # Update partial flag and combine ghash.
+__Update_partial_ghash:
+ li 10, 64
+ lxvb16x 32+17, 10, 7 # load previous pblock
+ add 12, 12, 21 # combined pprocessed
+ vxor 15, 15, 17 # combined pblock
+
+ cmpdi 12, 16
+ beq __Clear_partial_flag
+ std 12, 56(7) # update partial len
+ stxvb16x 32+15, 10, 7 # Update current pblock
blr
- #
- # Write partial block
- # r9 - output
- # r12 - remaining bytes
- # v15 - partial input data
- #
-SYM_FUNC_START_LOCAL(Write_partial_block)
- li 10, 192
- stxvb16x 15+32, 10, 1 # last block
-
- addi 10, 9, -1
- addi 16, 1, 191
-
- mtctr 12 # remaining bytes
- li 15, 0
-
-Write_last_byte:
- lbzu 14, 1(16)
- stbu 14, 1(10)
- bdnz Write_last_byte
+__Clear_partial_flag:
+ li 12, 0
+ std 12, 56(7)
+ # Update IV and ghash here
+ vadduwm 30, 30, 31 # increase IV
+ stxvb16x 32+30, 0, 7 # update IV
+
+ # v15 either is either (input blockor encrypted)^(AES state)
+ vxor 15, 15, 0
+ PPC_GHASH1x 0, 15
+ stxvb16x 32+0, 10, 7 # update pblock for debug?
+ stxvb16x 32+0, 0, 8 # update Xi
blr
-SYM_FUNC_END(Write_partial_block)
+SYM_FUNC_END(__Combine_partial)
-aes_gcm_out:
- # out = state
- stxvb16x 32, 0, 8 # write out Xi
- add 3, 11, 12 # return count
+################################################################################
+# gcm_update(iv, Xi) - compute last hash
+#
+################################################################################
+SYM_FUNC_START(gcm_update)
- RESTORE_REGS
- blr
+ ld 10, 56(3)
+ cmpdi 10, 0
+ beq __no_update
- #
- # 8x Decrypt
- #
-_GLOBAL(aes_p10_gcm_decrypt)
-.align 5
+ lxvb16x 32, 0, 4 # load Xi
+ # load Hash - h^4, h^3, h^2, h
+ li 10, 32
+ lxvd2x 2+32, 10, 4 # H Poli
+ li 10, 48
+ lxvd2x 3+32, 10, 4 # Hl
+ li 10, 64
+ lxvd2x 4+32, 10, 4 # H
+ li 10, 80
+ lxvd2x 5+32, 10, 4 # Hh
+
+ addis 11, 2, permx@toc@ha
+ addi 11, 11, permx@toc@l
+ lxv 10, 0(11) # vs10: vpermxor vector
+
+ li 9, 64
+ lxvb16x 32+6, 9, 3 # load pblock
+ vxor 6, 6, 0
+
+ vxor 1, 1, 1
+ vpmsumd 12, 3, 6 # L
+ vpmsumd 13, 4, 6 # M
+ vpmsumd 14, 5, 6 # H
+ vpmsumd 17, 12, 2 # reduction
+ vsldoi 15, 13, 1, 8 # mL
+ vsldoi 16, 1, 13, 8 # mH
+ vxor 12, 12, 15 # LL + LL
+ vxor 14, 14, 16 # HH + HH
+ xxlor 32+15, 10, 10
+ vpermxor 12, 12, 17, 15
+ vsldoi 13, 12, 12, 8 # swap
+ vpmsumd 12, 12, 2 # reduction
+ vxor 13, 13, 14
+ vxor 7, 12, 13
+
+ #vxor 0, 0, 0
+ #stxvb16x 32+0, 9, 3
+ li 10, 0
+ std 10, 56(3)
+ stxvb16x 32+7, 0, 4
+
+__no_update:
+ blr
+SYM_FUNC_END(gcm_update)
+
+################################################################################
+# aes_p10_gcm_encrypt (const void *inp, void *out, size_t len,
+# const char *rk, unsigned char iv[16], void *Xip);
+#
+# r3 - inp
+# r4 - out
+# r5 - len
+# r6 - AES round keys
+# r7 - iv and other data
+# r8 - Xi, HPoli, hash keys
+#
+# rounds is at offset 240 in rk
+# Xi is at 0 in gcm_table (Xip).
+#
+################################################################################
+SYM_FUNC_START(aes_p10_gcm_encrypt)
+
+ cmpdi 5, 0
+ ble __Invalid_msg_len
SAVE_REGS
-
LOAD_HASH_TABLE
# initialize ICB: GHASH( IV ), IV - r7
lxvb16x 30+32, 0, 7 # load IV - v30
- mr 12, 5 # length
- li 11, 0 # block index
+ mr 14, 3
+ mr 9, 4
# counter 1
vxor 31, 31, 31
vspltisb 22, 1
vsldoi 31, 31, 22,1 # counter 1
- # load round key to VSR
- lxv 0, 0(6)
- lxv 1, 0x10(6)
- lxv 2, 0x20(6)
- lxv 3, 0x30(6)
- lxv 4, 0x40(6)
- lxv 5, 0x50(6)
- lxv 6, 0x60(6)
- lxv 7, 0x70(6)
- lxv 8, 0x80(6)
- lxv 9, 0x90(6)
- lxv 10, 0xa0(6)
+ addis 11, 2, permx@toc@ha
+ addi 11, 11, permx@toc@l
+ lxv 10, 0(11) # vs10: vpermxor vector
+ li 11, 0
+
+ # load 9 round keys to VSR
+ lxv 0, 0(6) # round key 0
+ lxv 1, 16(6) # round key 1
+ lxv 2, 32(6) # round key 2
+ lxv 3, 48(6) # round key 3
+ lxv 4, 64(6) # round key 4
+ lxv 5, 80(6) # round key 5
+ lxv 6, 96(6) # round key 6
+ lxv 7, 112(6) # round key 7
+ lxv 8, 128(6) # round key 8
# load rounds - 10 (128), 12 (192), 14 (256)
- lwz 9,240(6)
+ lwz 23, 240(6) # n rounds
+ li 24, 1 # encrypt
+__Process_encrypt:
#
- # vxor state, state, w # addroundkey
- xxlor 32+29, 0, 0
- vxor 15, 30, 29 # IV + round key - add round key 0
-
- cmpdi 9, 10
- beq Loop_aes_gcm_8x_dec
-
- # load 2 more round keys (v11, v12)
- lxv 11, 0xb0(6)
- lxv 12, 0xc0(6)
-
- cmpdi 9, 12
- beq Loop_aes_gcm_8x_dec
-
- # load 2 more round keys (v11, v12, v13, v14)
- lxv 13, 0xd0(6)
- lxv 14, 0xe0(6)
- cmpdi 9, 14
- beq Loop_aes_gcm_8x_dec
+ # Process different blocks
+ #
+ ld 12, 56(7)
+ cmpdi 12, 0
+ bgt __Do_combine_enc
+ cmpdi 5, 128
+ blt __Process_more_enc
+
+#
+# Process 8x AES/GCM blocks
+#
+__Process_8x_enc:
+ # 8x blcoks
+ li 10, 128
+ divdu 12, 5, 10 # n 128 bytes-blocks
- b aes_gcm_out
+ addi 12, 12, -1 # loop - 1
-.align 5
-Loop_aes_gcm_8x_dec:
- mr 14, 3
- mr 9, 4
+ vmr 15, 30 # first state: IV
+ vadduwm 16, 15, 31 # state + counter
+ vadduwm 17, 16, 31
+ vadduwm 18, 17, 31
+ vadduwm 19, 18, 31
+ vadduwm 20, 19, 31
+ vadduwm 21, 20, 31
+ vadduwm 22, 21, 31
+ xxlor 9, 32+22, 32+22 # save last state
- #
- # check partial block
- #
-Continue_partial_check_dec:
- ld 15, 56(7)
- cmpdi 15, 0
- beq Continue_dec
- bgt Final_block_dec
- cmpdi 15, 16
- blt Final_block_dec
-
-Continue_dec:
- # n blcoks
- li 10, 128
- divdu 10, 12, 10 # n 128 bytes-blocks
- cmpdi 10, 0
- beq Loop_last_block_dec
-
- vaddudm 30, 30, 31 # IV + counter
- vxor 16, 30, 29
- vaddudm 30, 30, 31
- vxor 17, 30, 29
- vaddudm 30, 30, 31
- vxor 18, 30, 29
- vaddudm 30, 30, 31
- vxor 19, 30, 29
- vaddudm 30, 30, 31
- vxor 20, 30, 29
- vaddudm 30, 30, 31
- vxor 21, 30, 29
- vaddudm 30, 30, 31
- vxor 22, 30, 29
-
- mtctr 10
+ # vxor state, state, w # addroundkey
+ xxlor 32+29, 0, 0
+ vxor 15, 15, 29 # IV + round key - add round key 0
+ vxor 16, 16, 29
+ vxor 17, 17, 29
+ vxor 18, 18, 29
+ vxor 19, 19, 29
+ vxor 20, 20, 29
+ vxor 21, 21, 29
+ vxor 22, 22, 29
li 15, 16
li 16, 32
@@ -1217,305 +735,502 @@ Continue_dec:
li 20, 96
li 21, 112
- lwz 10, 240(6)
-
-Loop_8x_block_dec:
-
- lxvb16x 15, 0, 14 # load block
- lxvb16x 16, 15, 14 # load block
- lxvb16x 17, 16, 14 # load block
- lxvb16x 18, 17, 14 # load block
- lxvb16x 19, 18, 14 # load block
- lxvb16x 20, 19, 14 # load block
- lxvb16x 21, 20, 14 # load block
- lxvb16x 22, 21, 14 # load block
- addi 14, 14, 128
-
- Loop_aes_middle8x
-
- xxlor 23+32, 10, 10
-
- cmpdi 10, 10
- beq Do_next_ghash_dec
-
- # 192 bits
- xxlor 24+32, 11, 11
-
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
- vcipher 19, 19, 23
- vcipher 20, 20, 23
- vcipher 21, 21, 23
- vcipher 22, 22, 23
-
- vcipher 15, 15, 24
- vcipher 16, 16, 24
- vcipher 17, 17, 24
- vcipher 18, 18, 24
- vcipher 19, 19, 24
- vcipher 20, 20, 24
- vcipher 21, 21, 24
- vcipher 22, 22, 24
-
- xxlor 23+32, 12, 12
-
- cmpdi 10, 12
- beq Do_next_ghash_dec
-
- # 256 bits
- xxlor 24+32, 13, 13
-
- vcipher 15, 15, 23
- vcipher 16, 16, 23
- vcipher 17, 17, 23
- vcipher 18, 18, 23
- vcipher 19, 19, 23
- vcipher 20, 20, 23
- vcipher 21, 21, 23
- vcipher 22, 22, 23
-
- vcipher 15, 15, 24
- vcipher 16, 16, 24
- vcipher 17, 17, 24
- vcipher 18, 18, 24
- vcipher 19, 19, 24
- vcipher 20, 20, 24
- vcipher 21, 21, 24
- vcipher 22, 22, 24
-
- xxlor 23+32, 14, 14
-
- cmpdi 10, 14
- beq Do_next_ghash_dec
- b aes_gcm_out
+ #
+ # Pre-compute first 8 AES state and leave 1/3/5 more rounds
+ # for the loop.
+ #
+ addi 22, 23, -9 # process 8 keys
+ mtctr 22 # AES key loop
+ addi 10, 6, 144
-Do_next_ghash_dec:
+ LOOP_8AES_STATE # process 8 AES keys
- #
- # last round
- vcipherlast 15, 15, 23
- vcipherlast 16, 16, 23
-
- xxlxor 47, 47, 15
- stxvb16x 47, 0, 9 # store output
- xxlxor 48, 48, 16
- stxvb16x 48, 15, 9 # store output
-
- vcipherlast 17, 17, 23
- vcipherlast 18, 18, 23
-
- xxlxor 49, 49, 17
- stxvb16x 49, 16, 9 # store output
- xxlxor 50, 50, 18
- stxvb16x 50, 17, 9 # store output
-
- vcipherlast 19, 19, 23
- vcipherlast 20, 20, 23
-
- xxlxor 51, 51, 19
- stxvb16x 51, 18, 9 # store output
- xxlxor 52, 52, 20
- stxvb16x 52, 19, 9 # store output
-
- vcipherlast 21, 21, 23
- vcipherlast 22, 22, 23
-
- xxlxor 53, 53, 21
- stxvb16x 53, 20, 9 # store output
- xxlxor 54, 54, 22
- stxvb16x 54, 21, 9 # store output
-
- addi 9, 9, 128
-
- xxlor 15+32, 15, 15
- xxlor 16+32, 16, 16
- xxlor 17+32, 17, 17
- xxlor 18+32, 18, 18
- xxlor 19+32, 19, 19
- xxlor 20+32, 20, 20
- xxlor 21+32, 21, 21
- xxlor 22+32, 22, 22
+__PreLoop_aes_state:
+ lxv 32+1, 0(10) # round key
+ AES_CIPHER_8x vcipher 15 1
+ addi 10, 10, 16
+ bdnz __PreLoop_aes_state
+ lxv 32+1, 0(10) # last round key (v1)
+
+ cmpdi 12, 0 # Only one loop (8 block)
+ beq __Finish_ghash
+
+#
+# Loop 8x blocks and compute ghash
+#
+__Loop_8x_block_enc:
+ vcipherlast 15, 15, 1
+ vcipherlast 16, 16, 1
+ vcipherlast 17, 17, 1
+ vcipherlast 18, 18, 1
+ vcipherlast 19, 19, 1
+ vcipherlast 20, 20, 1
+ vcipherlast 21, 21, 1
+ vcipherlast 22, 22, 1
+
+ lxvb16x 32+23, 0, 14 # load block
+ lxvb16x 32+24, 15, 14 # load block
+ lxvb16x 32+25, 16, 14 # load block
+ lxvb16x 32+26, 17, 14 # load block
+ lxvb16x 32+27, 18, 14 # load block
+ lxvb16x 32+28, 19, 14 # load block
+ lxvb16x 32+29, 20, 14 # load block
+ lxvb16x 32+30, 21, 14 # load block
+ addi 14, 14, 128
+
+ vxor 15, 15, 23
+ vxor 16, 16, 24
+ vxor 17, 17, 25
+ vxor 18, 18, 26
+ vxor 19, 19, 27
+ vxor 20, 20, 28
+ vxor 21, 21, 29
+ vxor 22, 22, 30
+
+ stxvb16x 47, 0, 9 # store output
+ stxvb16x 48, 15, 9 # store output
+ stxvb16x 49, 16, 9 # store output
+ stxvb16x 50, 17, 9 # store output
+ stxvb16x 51, 18, 9 # store output
+ stxvb16x 52, 19, 9 # store output
+ stxvb16x 53, 20, 9 # store output
+ stxvb16x 54, 21, 9 # store output
+ addi 9, 9, 128
# ghash here
- ppc_aes_gcm_ghash2_4x
-
- xxlor 27+32, 0, 0
- vaddudm 30, 30, 31 # IV + counter
- vmr 29, 30
- vxor 15, 30, 27 # add round key
- vaddudm 30, 30, 31
- vxor 16, 30, 27
- vaddudm 30, 30, 31
- vxor 17, 30, 27
- vaddudm 30, 30, 31
- vxor 18, 30, 27
- vaddudm 30, 30, 31
- vxor 19, 30, 27
- vaddudm 30, 30, 31
- vxor 20, 30, 27
- vaddudm 30, 30, 31
- vxor 21, 30, 27
- vaddudm 30, 30, 31
- vxor 22, 30, 27
-
- addi 12, 12, -128
+ vxor 15, 15, 0
+ PPC_GHASH4x 0, 15, 16, 17, 18
+
+ vxor 19, 19, 0
+ PPC_GHASH4x 0, 19, 20, 21, 22
+
+ xxlor 32+15, 9, 9 # last state
+ vadduwm 15, 15, 31 # state + counter
+ vadduwm 16, 15, 31
+ vadduwm 17, 16, 31
+ vadduwm 18, 17, 31
+ vadduwm 19, 18, 31
+ vadduwm 20, 19, 31
+ vadduwm 21, 20, 31
+ vadduwm 22, 21, 31
+ xxlor 9, 32+22, 32+22 # save last state
+
+ xxlor 32+27, 0, 0 # restore roundkey 0
+ vxor 15, 15, 27 # IV + round key - add round key 0
+ vxor 16, 16, 27
+ vxor 17, 17, 27
+ vxor 18, 18, 27
+ vxor 19, 19, 27
+ vxor 20, 20, 27
+ vxor 21, 21, 27
+ vxor 22, 22, 27
+
+ addi 5, 5, -128
addi 11, 11, 128
- bdnz Loop_8x_block_dec
-
- vmr 30, 29
- stxvb16x 30+32, 0, 7 # update IV
-
-Loop_last_block_dec:
- cmpdi 12, 0
- beq aes_gcm_out
-
- # loop last few blocks
- li 10, 16
- divdu 10, 12, 10
-
- mtctr 10
-
- lwz 10, 240(6)
-
- cmpdi 12, 16
- blt Final_block_dec
-
-Next_rem_block_dec:
- lxvb16x 15, 0, 14 # load block
-
- Loop_aes_middle_1x
-
- xxlor 23+32, 10, 10
+ LOOP_8AES_STATE # process 8 AES keys
+ mtctr 22 # AES key loop
+ addi 10, 6, 144
+__LastLoop_aes_state:
+ lxv 32+1, 0(10) # round key
+ AES_CIPHER_8x vcipher 15 1
+ addi 10, 10, 16
+ bdnz __LastLoop_aes_state
+ lxv 32+1, 0(10) # last round key (v1)
- cmpdi 10, 10
- beq Do_next_1x_dec
+ addi 12, 12, -1
+ cmpdi 12, 0
+ bne __Loop_8x_block_enc
+
+__Finish_ghash:
+ vcipherlast 15, 15, 1
+ vcipherlast 16, 16, 1
+ vcipherlast 17, 17, 1
+ vcipherlast 18, 18, 1
+ vcipherlast 19, 19, 1
+ vcipherlast 20, 20, 1
+ vcipherlast 21, 21, 1
+ vcipherlast 22, 22, 1
+
+ lxvb16x 32+23, 0, 14 # load block
+ lxvb16x 32+24, 15, 14 # load block
+ lxvb16x 32+25, 16, 14 # load block
+ lxvb16x 32+26, 17, 14 # load block
+ lxvb16x 32+27, 18, 14 # load block
+ lxvb16x 32+28, 19, 14 # load block
+ lxvb16x 32+29, 20, 14 # load block
+ lxvb16x 32+30, 21, 14 # load block
+ addi 14, 14, 128
+
+ vxor 15, 15, 23
+ vxor 16, 16, 24
+ vxor 17, 17, 25
+ vxor 18, 18, 26
+ vxor 19, 19, 27
+ vxor 20, 20, 28
+ vxor 21, 21, 29
+ vxor 22, 22, 30
+
+ stxvb16x 47, 0, 9 # store output
+ stxvb16x 48, 15, 9 # store output
+ stxvb16x 49, 16, 9 # store output
+ stxvb16x 50, 17, 9 # store output
+ stxvb16x 51, 18, 9 # store output
+ stxvb16x 52, 19, 9 # store output
+ stxvb16x 53, 20, 9 # store output
+ stxvb16x 54, 21, 9 # store output
+ addi 9, 9, 128
+
+ vxor 15, 15, 0
+ PPC_GHASH4x 0, 15, 16, 17, 18
+
+ vxor 19, 19, 0
+ PPC_GHASH4x 0, 19, 20, 21, 22
+
+ xxlor 30+32, 9, 9 # last ctr
+ vadduwm 30, 30, 31 # increase ctr
+ stxvb16x 32+30, 0, 7 # update IV
+ stxvb16x 32+0, 0, 8 # update Xi
+
+ addi 5, 5, -128
+ addi 11, 11, 128
- # 192 bits
- xxlor 24+32, 11, 11
+ #
+ # Done 8x blocks
+ #
- vcipher 15, 15, 23
- vcipher 15, 15, 24
+ cmpdi 5, 0
+ beq aes_gcm_out
- xxlor 23+32, 12, 12
+__Process_more_enc:
+ li 24, 1 # encrypt
+ bl aes_gcm_crypt_1x
+ cmpdi 5, 0
+ beq aes_gcm_out
- cmpdi 10, 12
- beq Do_next_1x_dec
+ bl __Process_partial
+ cmpdi 5, 0
+ beq aes_gcm_out
+__Do_combine_enc:
+ bl __Combine_partial
+ cmpdi 5, 0
+ bgt __Process_encrypt
+ b aes_gcm_out
- # 256 bits
- xxlor 24+32, 13, 13
+SYM_FUNC_END(aes_p10_gcm_encrypt)
- vcipher 15, 15, 23
- vcipher 15, 15, 24
+################################################################################
+# aes_p10_gcm_decrypt (const void *inp, void *out, size_t len,
+# const char *rk, unsigned char iv[16], void *Xip);
+# 8x Decrypt
+#
+################################################################################
+SYM_FUNC_START(aes_p10_gcm_decrypt)
- xxlor 23+32, 14, 14
+ cmpdi 5, 0
+ ble __Invalid_msg_len
- cmpdi 10, 14
- beq Do_next_1x_dec
+ SAVE_REGS
+ LOAD_HASH_TABLE
-Do_next_1x_dec:
- vcipherlast 15, 15, 23
+ # initialize ICB: GHASH( IV ), IV - r7
+ lxvb16x 30+32, 0, 7 # load IV - v30
- xxlxor 47, 47, 15
- stxvb16x 47, 0, 9 # store output
- addi 14, 14, 16
- addi 9, 9, 16
+ mr 14, 3
+ mr 9, 4
- xxlor 28+32, 15, 15
- #vmr 28, 15
- ppc_update_hash_1x
+ # counter 1
+ vxor 31, 31, 31
+ vspltisb 22, 1
+ vsldoi 31, 31, 22,1 # counter 1
- addi 12, 12, -16
- addi 11, 11, 16
- xxlor 19+32, 0, 0
- vaddudm 30, 30, 31 # IV + counter
- vxor 15, 30, 19 # add round key
+ addis 11, 2, permx@toc@ha
+ addi 11, 11, permx@toc@l
+ lxv 10, 0(11) # vs10: vpermxor vector
+ li 11, 0
+
+ # load 9 round keys to VSR
+ lxv 0, 0(6) # round key 0
+ lxv 1, 16(6) # round key 1
+ lxv 2, 32(6) # round key 2
+ lxv 3, 48(6) # round key 3
+ lxv 4, 64(6) # round key 4
+ lxv 5, 80(6) # round key 5
+ lxv 6, 96(6) # round key 6
+ lxv 7, 112(6) # round key 7
+ lxv 8, 128(6) # round key 8
- bdnz Next_rem_block_dec
+ # load rounds - 10 (128), 12 (192), 14 (256)
+ lwz 23, 240(6) # n rounds
+ li 24, 0 # decrypt
- li 15, 0
- std 15, 56(7) # clear partial?
- stxvb16x 30+32, 0, 7 # update IV
+__Process_decrypt:
+ #
+ # Process different blocks
+ #
+ ld 12, 56(7)
cmpdi 12, 0
- beq aes_gcm_out
-
-Final_block_dec:
- lwz 10, 240(6)
- Loop_aes_middle_1x
-
- xxlor 23+32, 10, 10
-
- cmpdi 10, 10
- beq Do_final_1x_dec
+ bgt __Do_combine_dec
+ cmpdi 5, 128
+ blt __Process_more_dec
+
+#
+# Process 8x AES/GCM blocks
+#
+__Process_8x_dec:
+ # 8x blcoks
+ li 10, 128
+ divdu 12, 5, 10 # n 128 bytes-blocks
- # 192 bits
- xxlor 24+32, 11, 11
+ addi 12, 12, -1 # loop - 1
- vcipher 15, 15, 23
- vcipher 15, 15, 24
+ vmr 15, 30 # first state: IV
+ vadduwm 16, 15, 31 # state + counter
+ vadduwm 17, 16, 31
+ vadduwm 18, 17, 31
+ vadduwm 19, 18, 31
+ vadduwm 20, 19, 31
+ vadduwm 21, 20, 31
+ vadduwm 22, 21, 31
+ xxlor 9, 32+22, 32+22 # save last state
- xxlor 23+32, 12, 12
+ # vxor state, state, w # addroundkey
+ xxlor 32+29, 0, 0
+ vxor 15, 15, 29 # IV + round key - add round key 0
+ vxor 16, 16, 29
+ vxor 17, 17, 29
+ vxor 18, 18, 29
+ vxor 19, 19, 29
+ vxor 20, 20, 29
+ vxor 21, 21, 29
+ vxor 22, 22, 29
- cmpdi 10, 12
- beq Do_final_1x_dec
+ li 15, 16
+ li 16, 32
+ li 17, 48
+ li 18, 64
+ li 19, 80
+ li 20, 96
+ li 21, 112
- # 256 bits
- xxlor 24+32, 13, 13
+ #
+ # Pre-compute first 8 AES state and leave 1/3/5 more rounds
+ # for the loop.
+ #
+ addi 22, 23, -9 # process 8 keys
+ mtctr 22 # AES key loop
+ addi 10, 6, 144
- vcipher 15, 15, 23
- vcipher 15, 15, 24
+ LOOP_8AES_STATE # process 8 AES keys
- xxlor 23+32, 14, 14
+__PreLoop_aes_state_dec:
+ lxv 32+1, 0(10) # round key
+ AES_CIPHER_8x vcipher 15 1
+ addi 10, 10, 16
+ bdnz __PreLoop_aes_state_dec
+ lxv 32+1, 0(10) # last round key (v1)
+
+ cmpdi 12, 0 # Only one loop (8 block)
+ beq __Finish_ghash_dec
+
+#
+# Loop 8x blocks and compute ghash
+#
+__Loop_8x_block_dec:
+ vcipherlast 15, 15, 1
+ vcipherlast 16, 16, 1
+ vcipherlast 17, 17, 1
+ vcipherlast 18, 18, 1
+ vcipherlast 19, 19, 1
+ vcipherlast 20, 20, 1
+ vcipherlast 21, 21, 1
+ vcipherlast 22, 22, 1
+
+ lxvb16x 32+23, 0, 14 # load block
+ lxvb16x 32+24, 15, 14 # load block
+ lxvb16x 32+25, 16, 14 # load block
+ lxvb16x 32+26, 17, 14 # load block
+ lxvb16x 32+27, 18, 14 # load block
+ lxvb16x 32+28, 19, 14 # load block
+ lxvb16x 32+29, 20, 14 # load block
+ lxvb16x 32+30, 21, 14 # load block
+ addi 14, 14, 128
+
+ vxor 15, 15, 23
+ vxor 16, 16, 24
+ vxor 17, 17, 25
+ vxor 18, 18, 26
+ vxor 19, 19, 27
+ vxor 20, 20, 28
+ vxor 21, 21, 29
+ vxor 22, 22, 30
+
+ stxvb16x 47, 0, 9 # store output
+ stxvb16x 48, 15, 9 # store output
+ stxvb16x 49, 16, 9 # store output
+ stxvb16x 50, 17, 9 # store output
+ stxvb16x 51, 18, 9 # store output
+ stxvb16x 52, 19, 9 # store output
+ stxvb16x 53, 20, 9 # store output
+ stxvb16x 54, 21, 9 # store output
+
+ addi 9, 9, 128
+
+ vmr 15, 23
+ vmr 16, 24
+ vmr 17, 25
+ vmr 18, 26
+ vmr 19, 27
+ vmr 20, 28
+ vmr 21, 29
+ vmr 22, 30
- cmpdi 10, 14
- beq Do_final_1x_dec
+ # ghash here
+ vxor 15, 15, 0
+ PPC_GHASH4x 0, 15, 16, 17, 18
+
+ vxor 19, 19, 0
+ PPC_GHASH4x 0, 19, 20, 21, 22
+
+ xxlor 32+15, 9, 9 # last state
+ vadduwm 15, 15, 31 # state + counter
+ vadduwm 16, 15, 31
+ vadduwm 17, 16, 31
+ vadduwm 18, 17, 31
+ vadduwm 19, 18, 31
+ vadduwm 20, 19, 31
+ vadduwm 21, 20, 31
+ vadduwm 22, 21, 31
+ xxlor 9, 32+22, 32+22 # save last state
+
+ xxlor 32+27, 0, 0 # restore roundkey 0
+ vxor 15, 15, 27 # IV + round key - add round key 0
+ vxor 16, 16, 27
+ vxor 17, 17, 27
+ vxor 18, 18, 27
+ vxor 19, 19, 27
+ vxor 20, 20, 27
+ vxor 21, 21, 27
+ vxor 22, 22, 27
+
+ addi 5, 5, -128
+ addi 11, 11, 128
-Do_final_1x_dec:
- vcipherlast 15, 15, 23
+ LOOP_8AES_STATE # process 8 AES keys
+ mtctr 22 # AES key loop
+ addi 10, 6, 144
+__LastLoop_aes_state_dec:
+ lxv 32+1, 0(10) # round key
+ AES_CIPHER_8x vcipher 15 1
+ addi 10, 10, 16
+ bdnz __LastLoop_aes_state_dec
+ lxv 32+1, 0(10) # last round key (v1)
- # check partial block
- li 21, 1 # decrypt
- ld 15, 56(7) # partial?
- cmpdi 15, 0
- beq Normal_block_dec
- bl Do_partial_block
+ addi 12, 12, -1
cmpdi 12, 0
- ble aes_gcm_out
-
- b Continue_partial_check_dec
+ bne __Loop_8x_block_dec
+
+__Finish_ghash_dec:
+ vcipherlast 15, 15, 1
+ vcipherlast 16, 16, 1
+ vcipherlast 17, 17, 1
+ vcipherlast 18, 18, 1
+ vcipherlast 19, 19, 1
+ vcipherlast 20, 20, 1
+ vcipherlast 21, 21, 1
+ vcipherlast 22, 22, 1
+
+ lxvb16x 32+23, 0, 14 # load block
+ lxvb16x 32+24, 15, 14 # load block
+ lxvb16x 32+25, 16, 14 # load block
+ lxvb16x 32+26, 17, 14 # load block
+ lxvb16x 32+27, 18, 14 # load block
+ lxvb16x 32+28, 19, 14 # load block
+ lxvb16x 32+29, 20, 14 # load block
+ lxvb16x 32+30, 21, 14 # load block
+ addi 14, 14, 128
+
+ vxor 15, 15, 23
+ vxor 16, 16, 24
+ vxor 17, 17, 25
+ vxor 18, 18, 26
+ vxor 19, 19, 27
+ vxor 20, 20, 28
+ vxor 21, 21, 29
+ vxor 22, 22, 30
+
+ stxvb16x 47, 0, 9 # store output
+ stxvb16x 48, 15, 9 # store output
+ stxvb16x 49, 16, 9 # store output
+ stxvb16x 50, 17, 9 # store output
+ stxvb16x 51, 18, 9 # store output
+ stxvb16x 52, 19, 9 # store output
+ stxvb16x 53, 20, 9 # store output
+ stxvb16x 54, 21, 9 # store output
+ addi 9, 9, 128
+
+ #vmr 15, 23
+ vxor 15, 23, 0
+ vmr 16, 24
+ vmr 17, 25
+ vmr 18, 26
+ vmr 19, 27
+ vmr 20, 28
+ vmr 21, 29
+ vmr 22, 30
+
+ #vxor 15, 15, 0
+ PPC_GHASH4x 0, 15, 16, 17, 18
+
+ vxor 19, 19, 0
+ PPC_GHASH4x 0, 19, 20, 21, 22
+
+ xxlor 30+32, 9, 9 # last ctr
+ vadduwm 30, 30, 31 # increase ctr
+ stxvb16x 32+30, 0, 7 # update IV
+ stxvb16x 32+0, 0, 8 # update Xi
+
+ addi 5, 5, -128
+ addi 11, 11, 128
-Normal_block_dec:
- lxvb16x 15, 0, 14 # load last block
- xxlxor 47, 47, 15
+ #
+ # Done 8x blocks
+ #
- # create partial block mask
- li 15, 16
- sub 15, 15, 12 # index to the mask
+ cmpdi 5, 0
+ beq aes_gcm_out
- vspltisb 16, -1 # first 16 bytes - 0xffff...ff
- vspltisb 17, 0 # second 16 bytes - 0x0000...00
- li 10, 192
- stvx 16, 10, 1
- addi 10, 10, 16
- stvx 17, 10, 1
+__Process_more_dec:
+ li 24, 0 # decrypt
+ bl aes_gcm_crypt_1x
+ cmpdi 5, 0
+ beq aes_gcm_out
- addi 10, 1, 192
- lxvb16x 16, 15, 10 # load partial block mask
- xxland 47, 47, 16
+ bl __Process_partial
+ cmpdi 5, 0
+ beq aes_gcm_out
+__Do_combine_dec:
+ bl __Combine_partial
+ cmpdi 5, 0
+ bgt __Process_decrypt
+ b aes_gcm_out
+SYM_FUNC_END(aes_p10_gcm_decrypt)
- xxland 32+28, 15, 16
- #vmr 28, 15
- ppc_update_hash_1x
+SYM_FUNC_START_LOCAL(aes_gcm_out)
- # * should store only the remaining bytes.
- bl Write_partial_block
+ mr 3, 11 # return count
- stxvb16x 30+32, 0, 7 # update IV
- std 12, 56(7) # update partial?
- li 16, 16
+ RESTORE_REGS
+ blr
- stxvb16x 32, 0, 8 # write out Xi
- stxvb16x 32, 16, 8 # write out Xi
- b aes_gcm_out
+__Invalid_msg_len:
+ li 3, 0
+ blr
+SYM_FUNC_END(aes_gcm_out)
+
+SYM_DATA_START_LOCAL(PERMX)
+.align 4
+# for vector permute and xor
+permx:
+.long 0x4c5d6e7f, 0x08192a3b, 0xc4d5e6f7, 0x8091a2b3
+SYM_DATA_END(permx)
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 201218faed61..29a529d2ab8b 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -193,6 +193,7 @@ static inline void cpu_feature_keys_init(void) { }
#define CPU_FTR_ARCH_31 LONG_ASM_CONST(0x0004000000000000)
#define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008000000000000)
#define CPU_FTR_DEXCR_NPHIE LONG_ASM_CONST(0x0010000000000000)
+#define CPU_FTR_P11_PVR LONG_ASM_CONST(0x0020000000000000)
#ifndef __ASSEMBLY__
@@ -454,7 +455,7 @@ static inline void cpu_feature_keys_init(void) { }
CPU_FTR_DAWR | CPU_FTR_DAWR1 | \
CPU_FTR_DEXCR_NPHIE)
-#define CPU_FTRS_POWER11 CPU_FTRS_POWER10
+#define CPU_FTRS_POWER11 (CPU_FTRS_POWER10 | CPU_FTR_P11_PVR)
#define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
@@ -475,7 +476,7 @@ static inline void cpu_feature_keys_init(void) { }
(CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \
CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \
- CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10)
+ CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11)
#else
#define CPU_FTRS_POSSIBLE \
(CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \
@@ -483,7 +484,7 @@ static inline void cpu_feature_keys_init(void) { }
CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \
CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \
CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \
- CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10)
+ CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11)
#endif /* CONFIG_CPU_LITTLE_ENDIAN */
#endif
#else
@@ -547,7 +548,7 @@ enum {
(CPU_FTRS_POSSIBLE & ~CPU_FTR_HVMODE & ~CPU_FTR_DBELL & \
CPU_FTRS_POWER7 & CPU_FTRS_POWER8E & CPU_FTRS_POWER8 & \
CPU_FTRS_POWER9 & CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_POWER9_DD2_2 & \
- CPU_FTRS_POWER10 & CPU_FTRS_DT_CPU_BASE)
+ CPU_FTRS_POWER10 & CPU_FTRS_POWER11 & CPU_FTRS_DT_CPU_BASE)
#else
#define CPU_FTRS_ALWAYS \
(CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \
@@ -555,7 +556,7 @@ enum {
CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \
~CPU_FTR_HVMODE & ~CPU_FTR_DBELL & CPU_FTRS_POSSIBLE & \
CPU_FTRS_POWER9 & CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_POWER9_DD2_2 & \
- CPU_FTRS_POWER10 & CPU_FTRS_DT_CPU_BASE)
+ CPU_FTRS_POWER10 & CPU_FTRS_POWER11 & CPU_FTRS_DT_CPU_BASE)
#endif /* CONFIG_CPU_LITTLE_ENDIAN */
#endif
#else
diff --git a/arch/powerpc/include/asm/dtl.h b/arch/powerpc/include/asm/dtl.h
index d6f43d149f8d..a5c21bc623cb 100644
--- a/arch/powerpc/include/asm/dtl.h
+++ b/arch/powerpc/include/asm/dtl.h
@@ -1,8 +1,8 @@
#ifndef _ASM_POWERPC_DTL_H
#define _ASM_POWERPC_DTL_H
+#include <linux/rwsem.h>
#include <asm/lppaca.h>
-#include <linux/spinlock_types.h>
/*
* Layout of entries in the hypervisor's dispatch trace log buffer.
@@ -35,7 +35,7 @@ struct dtl_entry {
#define DTL_LOG_ALL (DTL_LOG_CEDE | DTL_LOG_PREEMPT | DTL_LOG_FAULT)
extern struct kmem_cache *dtl_cache;
-extern rwlock_t dtl_access_lock;
+extern struct rw_semaphore dtl_access_lock;
extern void register_dtl_buffer(int cpu);
extern void alloc_dtl_buffers(unsigned long *time_limit);
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index ef40c9b6972a..a48f54dde4f6 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -19,6 +19,7 @@ extern int is_fadump_active(void);
extern int should_fadump_crash(void);
extern void crash_fadump(struct pt_regs *, const char *);
extern void fadump_cleanup(void);
+void fadump_setup_param_area(void);
extern void fadump_append_bootargs(void);
#else /* CONFIG_FA_DUMP */
@@ -26,6 +27,7 @@ static inline int is_fadump_active(void) { return 0; }
static inline int should_fadump_crash(void) { return 0; }
static inline void crash_fadump(struct pt_regs *regs, const char *str) { }
static inline void fadump_cleanup(void) { }
+static inline void fadump_setup_param_area(void) { }
static inline void fadump_append_bootargs(void) { }
#endif /* !CONFIG_FA_DUMP */
@@ -34,4 +36,11 @@ extern int early_init_dt_scan_fw_dump(unsigned long node, const char *uname,
int depth, void *data);
extern int fadump_reserve_mem(void);
#endif
+
+#if defined(CONFIG_FA_DUMP) && defined(CONFIG_CMA)
+void fadump_cma_init(void);
+#else
+static inline void fadump_cma_init(void) { }
+#endif
+
#endif /* _ASM_POWERPC_FADUMP_H */
diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h
index 559560286e6d..db481b336bca 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -24,7 +24,10 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
struct module;
struct dyn_ftrace;
struct dyn_arch_ftrace {
- struct module *mod;
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ /* pointer to the associated out-of-line stub */
+ unsigned long ool_stub;
+#endif
};
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
@@ -32,42 +35,21 @@ struct dyn_arch_ftrace {
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
#define ftrace_init_nop ftrace_init_nop
-struct ftrace_regs {
- struct pt_regs regs;
-};
+#include <linux/ftrace_regs.h>
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
{
/* We clear regs.msr in ftrace_call */
- return fregs->regs.msr ? &fregs->regs : NULL;
+ return arch_ftrace_regs(fregs)->regs.msr ? &arch_ftrace_regs(fregs)->regs : NULL;
}
static __always_inline void
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
unsigned long ip)
{
- regs_set_return_ip(&fregs->regs, ip);
+ regs_set_return_ip(&arch_ftrace_regs(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
@@ -131,8 +113,36 @@ static inline u8 this_cpu_get_ftrace_enabled(void) { return 1; }
#ifdef CONFIG_FUNCTION_TRACER
extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[];
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+struct ftrace_ool_stub {
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
+ struct ftrace_ops *ftrace_op;
+#endif
+ u32 insn[4];
+} __aligned(sizeof(unsigned long));
+extern struct ftrace_ool_stub ftrace_ool_stub_text_end[], ftrace_ool_stub_text[],
+ ftrace_ool_stub_inittext[];
+extern unsigned int ftrace_ool_stub_text_end_count, ftrace_ool_stub_text_count,
+ ftrace_ool_stub_inittext_count;
+#endif
void ftrace_free_init_tramp(void);
unsigned long ftrace_call_adjust(unsigned long addr);
+
+#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 differentiated in the
+ * ftrace_caller trampoline so that the direct call can be invoked after the
+ * other ftrace ops. To do this, place the direct caller in the orig_gpr3 field
+ * of pt_regs. This tells ftrace_caller that there's a direct caller.
+ */
+static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
+{
+ struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
+
+ regs->orig_gpr3 = addr;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
#else
static inline void ftrace_free_init_tramp(void) { }
static inline unsigned long ftrace_call_adjust(unsigned long addr) { return addr; }
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 7a8495660c2f..65d1f291393d 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -495,6 +495,7 @@
#define H_GUEST_CAP_COPY_MEM (1UL<<(63-0))
#define H_GUEST_CAP_POWER9 (1UL<<(63-1))
#define H_GUEST_CAP_POWER10 (1UL<<(63-2))
+#define H_GUEST_CAP_POWER11 (1UL<<(63-3))
#define H_GUEST_CAP_BITMAP2 (1UL<<(63-63))
#ifndef __ASSEMBLY__
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 52e1b1d15ff6..fd92ac450169 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -970,18 +970,6 @@ static inline void * phys_to_virt(unsigned long address)
#define phys_to_virt phys_to_virt
/*
- * Change "struct page" to physical address.
- */
-static inline phys_addr_t page_to_phys(struct page *page)
-{
- unsigned long pfn = page_to_pfn(page);
-
- WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && !pfn_valid(pfn));
-
- return PFN_PHYS(pfn);
-}
-
-/*
* 32 bits still uses virt_to_bus() for its implementation of DMA
* mappings se we have to keep it defined here. We also have some old
* drivers (shame shame shame) that use bus_to_virt() and haven't been
diff --git a/arch/powerpc/include/asm/kfence.h b/arch/powerpc/include/asm/kfence.h
index fab124ada1c7..1f7cab58ab2c 100644
--- a/arch/powerpc/include/asm/kfence.h
+++ b/arch/powerpc/include/asm/kfence.h
@@ -15,7 +15,7 @@
#define ARCH_FUNC_PREFIX "."
#endif
-#ifdef CONFIG_KFENCE
+extern bool kfence_early_init;
extern bool kfence_disabled;
static inline void disable_kfence(void)
@@ -27,7 +27,11 @@ static inline bool arch_kfence_init_pool(void)
{
return !kfence_disabled;
}
-#endif
+
+static inline bool kfence_early_init_enabled(void)
+{
+ return IS_ENABLED(CONFIG_KFENCE) && kfence_early_init;
+}
#ifdef CONFIG_PPC64
static inline bool kfence_protect_page(unsigned long addr, bool protect)
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 4525a9c68260..dfe2e5ad3b21 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -21,7 +21,7 @@
#include <linux/percpu.h>
#include <linux/module.h>
#include <asm/probes.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#ifdef CONFIG_KPROBES
#define __ARCH_WANT_KPROBES_INSN_SLOT
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 10618622d7ef..e1ff291ba891 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -203,7 +203,7 @@ extern bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested,
extern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
unsigned long gpa,
struct kvm_memory_slot *memslot,
- bool writing, bool kvm_ro,
+ bool writing,
pte_t *inserted_pte, unsigned int *levelp);
extern int kvmppc_init_vm_radix(struct kvm *kvm);
extern void kvmppc_free_radix(struct kvm *kvm);
@@ -235,7 +235,7 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
extern int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu);
extern kvm_pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa,
- bool writing, bool *writable);
+ bool writing, bool *writable, struct page **page);
extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
unsigned long *rmap, long pte_index, int realmode);
extern void kvmppc_update_dirty_map(const struct kvm_memory_slot *memslot,
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 2ef9a5f4e5d1..b936e174eefd 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -684,10 +684,16 @@ int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1);
int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu);
int kvmhv_nestedv2_set_vpa(struct kvm_vcpu *vcpu, unsigned long vpa);
-int kmvhv_counters_tracepoint_regfunc(void);
-void kmvhv_counters_tracepoint_unregfunc(void);
+int kvmhv_counters_tracepoint_regfunc(void);
+void kvmhv_counters_tracepoint_unregfunc(void);
int kvmhv_get_l2_counters_status(void);
void kvmhv_set_l2_counters_status(int cpu, bool status);
+u64 kvmhv_get_l1_to_l2_cs_time(void);
+u64 kvmhv_get_l2_to_l1_cs_time(void);
+u64 kvmhv_get_l2_runtime_agg(void);
+u64 kvmhv_get_l1_to_l2_cs_time_vcpu(void);
+u64 kvmhv_get_l2_to_l1_cs_time_vcpu(void);
+u64 kvmhv_get_l2_runtime_agg_vcpu(void);
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 37e581c5b201..6e1108f8fce6 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -871,6 +871,11 @@ struct kvm_vcpu_arch {
struct kvmhv_tb_accumulator cede_time; /* time napping inside guest */
#endif
#endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ u64 l1_to_l2_cs;
+ u64 l2_to_l1_cs;
+ u64 l2_runtime_agg;
+#endif
};
#define VCPU_FPR(vcpu, i) (vcpu)->arch.fp.fpr[i][TS_FPROFFSET]
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 1862f94335ee..3298eec123a3 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -4,20 +4,24 @@
#ifdef __KERNEL__
#include <linux/compiler.h>
-#include <linux/seq_file.h>
#include <linux/init.h>
-#include <linux/dma-mapping.h>
#include <linux/export.h>
+#include <linux/time64.h>
+
+#include <asm/page.h>
struct pt_regs;
struct pci_bus;
+struct device;
struct device_node;
struct iommu_table;
struct rtc_time;
struct file;
+struct pci_dev;
struct pci_controller;
struct kimage;
struct pci_host_bridge;
+struct seq_file;
struct machdep_calls {
const char *name;
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index 300c777cc307..e1ee5026ac4a 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -35,9 +35,11 @@ struct mod_arch_specific {
bool toc_fixed; /* Have we fixed up .TOC.? */
#endif
+#ifdef CONFIG_PPC64_ELF_ABI_V1
/* For module function descriptor dereference */
unsigned long start_opd;
unsigned long end_opd;
+#endif
#else /* powerpc64 */
/* Indices of PLT sections within module. */
unsigned int core_plt_section;
@@ -47,6 +49,11 @@ struct mod_arch_specific {
#ifdef CONFIG_DYNAMIC_FTRACE
unsigned long tramp;
unsigned long tramp_regs;
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ struct ftrace_ool_stub *ool_stubs;
+ unsigned int ool_stub_count;
+ unsigned int ool_stub_index;
+#endif
#endif
};
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index 83d0a4fc5f75..af9a2628d1df 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -21,8 +21,7 @@
* page size. When using 64K pages however, whether we are really supporting
* 64K pages in HW or not is irrelevant to those definitions.
*/
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
+#include <vdso/page.h>
#ifndef __ASSEMBLY__
#ifndef CONFIG_HUGETLB_PAGE
@@ -42,13 +41,6 @@ extern unsigned int hpage_shift;
#endif
/*
- * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we
- * assign PAGE_MASK to a larger type it gets extended the way we want
- * (i.e. with 1s in the high bits)
- */
-#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
-
-/*
* KERNELBASE is the virtual address of the start of the kernel, it's often
* the same as PAGE_OFFSET, but _might not be_.
*
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 5995614e9062..af0f46e2373b 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -102,8 +102,8 @@ struct power_pmu {
int __init register_power_pmu(struct power_pmu *pmu);
struct pt_regs;
-extern unsigned long perf_misc_flags(struct pt_regs *regs);
-extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
+extern unsigned long perf_arch_misc_flags(struct pt_regs *regs);
+extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs);
extern unsigned long int read_bhrb(int n);
/*
@@ -111,7 +111,7 @@ extern unsigned long int read_bhrb(int n);
* if we have hardware PMU support.
*/
#ifdef CONFIG_PPC_PERF_CTRS
-#define perf_misc_flags(regs) perf_misc_flags(regs)
+#define perf_arch_misc_flags(regs) perf_arch_misc_flags(regs)
#endif
/*
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index b98a9e982c03..4312bcb913a4 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -587,12 +587,26 @@
#define PPC_RAW_MTSPR(spr, d) (0x7c0003a6 | ___PPC_RS(d) | __PPC_SPR(spr))
#define PPC_RAW_EIEIO() (0x7c0006ac)
+/* bcl 20,31,$+4 */
+#define PPC_RAW_BCL4() (0x429f0005)
#define PPC_RAW_BRANCH(offset) (0x48000000 | PPC_LI(offset))
#define PPC_RAW_BL(offset) (0x48000001 | PPC_LI(offset))
#define PPC_RAW_TW(t0, a, b) (0x7c000008 | ___PPC_RS(t0) | ___PPC_RA(a) | ___PPC_RB(b))
#define PPC_RAW_TRAP() PPC_RAW_TW(31, 0, 0)
#define PPC_RAW_SETB(t, bfa) (0x7c000100 | ___PPC_RT(t) | ___PPC_RA((bfa) << 2))
+#ifdef CONFIG_PPC32
+#define PPC_RAW_STL PPC_RAW_STW
+#define PPC_RAW_STLU PPC_RAW_STWU
+#define PPC_RAW_LL PPC_RAW_LWZ
+#define PPC_RAW_CMPLI PPC_RAW_CMPWI
+#else
+#define PPC_RAW_STL PPC_RAW_STD
+#define PPC_RAW_STLU PPC_RAW_STDU
+#define PPC_RAW_LL PPC_RAW_LD
+#define PPC_RAW_CMPLI PPC_RAW_CMPDI
+#endif
+
/* Deal with instructions that older assemblers aren't aware of */
#define PPC_BCCTR_FLUSH stringify_in_c(.long PPC_INST_BCCTR_FLUSH)
#define PPC_CP_ABORT stringify_in_c(.long PPC_RAW_CP_ABORT)
diff --git a/arch/powerpc/include/asm/set_memory.h b/arch/powerpc/include/asm/set_memory.h
index 9a025b776a4b..9c8d5747755d 100644
--- a/arch/powerpc/include/asm/set_memory.h
+++ b/arch/powerpc/include/asm/set_memory.h
@@ -12,37 +12,37 @@
int change_memory_attr(unsigned long addr, int numpages, long action);
-static inline int set_memory_ro(unsigned long addr, int numpages)
+static inline int __must_check set_memory_ro(unsigned long addr, int numpages)
{
return change_memory_attr(addr, numpages, SET_MEMORY_RO);
}
-static inline int set_memory_rw(unsigned long addr, int numpages)
+static inline int __must_check set_memory_rw(unsigned long addr, int numpages)
{
return change_memory_attr(addr, numpages, SET_MEMORY_RW);
}
-static inline int set_memory_nx(unsigned long addr, int numpages)
+static inline int __must_check set_memory_nx(unsigned long addr, int numpages)
{
return change_memory_attr(addr, numpages, SET_MEMORY_NX);
}
-static inline int set_memory_x(unsigned long addr, int numpages)
+static inline int __must_check set_memory_x(unsigned long addr, int numpages)
{
return change_memory_attr(addr, numpages, SET_MEMORY_X);
}
-static inline int set_memory_np(unsigned long addr, int numpages)
+static inline int __must_check set_memory_np(unsigned long addr, int numpages)
{
return change_memory_attr(addr, numpages, SET_MEMORY_NP);
}
-static inline int set_memory_p(unsigned long addr, int numpages)
+static inline int __must_check set_memory_p(unsigned long addr, int numpages)
{
return change_memory_attr(addr, numpages, SET_MEMORY_P);
}
-static inline int set_memory_rox(unsigned long addr, int numpages)
+static inline int __must_check set_memory_rox(unsigned long addr, int numpages)
{
return change_memory_attr(addr, numpages, SET_MEMORY_ROX);
}
diff --git a/arch/powerpc/include/asm/simple_spinlock_types.h b/arch/powerpc/include/asm/simple_spinlock_types.h
index 08243338069d..391fc19f7272 100644
--- a/arch/powerpc/include/asm/simple_spinlock_types.h
+++ b/arch/powerpc/include/asm/simple_spinlock_types.h
@@ -3,7 +3,7 @@
#define _ASM_POWERPC_SIMPLE_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
typedef struct {
diff --git a/arch/powerpc/include/asm/spinlock_types.h b/arch/powerpc/include/asm/spinlock_types.h
index 40b01446cf75..569765fa16bc 100644
--- a/arch/powerpc/include/asm/spinlock_types.h
+++ b/arch/powerpc/include/asm/spinlock_types.h
@@ -3,7 +3,7 @@
#define _ASM_POWERPC_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
#ifdef CONFIG_PPC_QUEUED_SPINLOCKS
diff --git a/arch/powerpc/include/asm/spu_priv1.h b/arch/powerpc/include/asm/spu_priv1.h
index 2167d756e6d5..6fee411d973d 100644
--- a/arch/powerpc/include/asm/spu_priv1.h
+++ b/arch/powerpc/include/asm/spu_priv1.h
@@ -216,7 +216,6 @@ spu_disable_spu (struct spu_context *ctx)
*/
extern const struct spu_priv1_ops spu_priv1_mmio_ops;
-extern const struct spu_priv1_ops spu_priv1_beat_ops;
extern const struct spu_management_ops spu_management_of_ops;
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h
index 50950deedb87..e3d0e714ff28 100644
--- a/arch/powerpc/include/asm/sstep.h
+++ b/arch/powerpc/include/asm/sstep.h
@@ -173,9 +173,4 @@ int emulate_step(struct pt_regs *regs, ppc_inst_t instr);
*/
extern int emulate_loadstore(struct pt_regs *regs, struct instruction_op *op);
-extern void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
- const void *mem, bool cross_endian);
-extern void emulate_vsx_store(struct instruction_op *op,
- const union vsx_reg *reg, void *mem,
- bool cross_endian);
extern int emulate_dcbz(unsigned long ea, struct pt_regs *regs);
diff --git a/arch/powerpc/include/asm/systemcfg.h b/arch/powerpc/include/asm/systemcfg.h
new file mode 100644
index 000000000000..2f9b1d6a5c98
--- /dev/null
+++ b/arch/powerpc/include/asm/systemcfg.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _SYSTEMCFG_H
+#define _SYSTEMCFG_H
+
+/*
+ * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
+ * Copyright (C) 2005 Benjamin Herrenschmidy <benh@kernel.crashing.org>,
+ * IBM Corp.
+ */
+
+#ifdef CONFIG_PPC64
+
+/*
+ * If the major version changes we are incompatible.
+ * Minor version changes are a hint.
+ */
+#define SYSTEMCFG_MAJOR 1
+#define SYSTEMCFG_MINOR 1
+
+#include <linux/types.h>
+
+struct systemcfg {
+ __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
+ struct { /* Systemcfg version numbers */
+ __u32 major; /* Major number 0x10 */
+ __u32 minor; /* Minor number 0x14 */
+ } version;
+
+ /* Note about the platform flags: it now only contains the lpar
+ * bit. The actual platform number is dead and buried
+ */
+ __u32 platform; /* Platform flags 0x18 */
+ __u32 processor; /* Processor type 0x1C */
+ __u64 processorCount; /* # of physical processors 0x20 */
+ __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
+ __u64 tb_orig_stamp; /* (NU) Timebase at boot 0x30 */
+ __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
+ __u64 tb_to_xs; /* (NU) Inverse of TB to 2^20 0x40 */
+ __u64 stamp_xsec; /* (NU) 0x48 */
+ __u64 tb_update_count; /* (NU) Timebase atomicity ctr 0x50 */
+ __u32 tz_minuteswest; /* (NU) Min. west of Greenwich 0x58 */
+ __u32 tz_dsttime; /* (NU) Type of dst correction 0x5C */
+ __u32 dcache_size; /* L1 d-cache size 0x60 */
+ __u32 dcache_line_size; /* L1 d-cache line size 0x64 */
+ __u32 icache_size; /* L1 i-cache size 0x68 */
+ __u32 icache_line_size; /* L1 i-cache line size 0x6C */
+};
+
+extern struct systemcfg *systemcfg;
+
+#endif /* CONFIG_PPC64 */
+#endif /* _SYSTEMCFG_H */
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/text-patching.h
index e7f14720f630..e7f14720f630 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/text-patching.h
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 289023f7a656..a8681b12864f 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -38,7 +38,6 @@ void __init udbg_early_init(void);
void __init udbg_init_debug_lpar(void);
void __init udbg_init_debug_lpar_hvsi(void);
void __init udbg_init_pmac_realmode(void);
-void __init udbg_init_maple_realmode(void);
void __init udbg_init_pas_realmode(void);
void __init udbg_init_rtas_panel(void);
void __init udbg_init_rtas_console(void);
diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h
index 7650b6ce14c8..8d972bc98b55 100644
--- a/arch/powerpc/include/asm/vdso.h
+++ b/arch/powerpc/include/asm/vdso.h
@@ -25,6 +25,7 @@ int vdso_getcpu_init(void);
#ifdef __VDSO64__
#define V_FUNCTION_BEGIN(name) \
.globl name; \
+ .type name,@function; \
name: \
#define V_FUNCTION_END(name) \
diff --git a/arch/powerpc/include/asm/vdso/getrandom.h b/arch/powerpc/include/asm/vdso/getrandom.h
index 501d6bb14e8a..80ce0709725e 100644
--- a/arch/powerpc/include/asm/vdso/getrandom.h
+++ b/arch/powerpc/include/asm/vdso/getrandom.h
@@ -7,6 +7,8 @@
#ifndef __ASSEMBLY__
+#include <asm/vdso_datapage.h>
+
static __always_inline int do_syscall_3(const unsigned long _r0, const unsigned long _r3,
const unsigned long _r4, const unsigned long _r5)
{
@@ -43,11 +45,21 @@ static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsig
static __always_inline struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{
- return NULL;
+ struct vdso_arch_data *data;
+
+ asm (
+ " bcl 20, 31, .+4 ;"
+ "0: mflr %0 ;"
+ " addis %0, %0, (_vdso_datapage - 0b)@ha ;"
+ " addi %0, %0, (_vdso_datapage - 0b)@l ;"
+ : "=r" (data) : : "lr"
+ );
+
+ return &data->rng_data;
}
ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state,
- size_t opaque_len, const struct vdso_rng_data *vd);
+ size_t opaque_len);
#endif /* !__ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/vdso/vsyscall.h b/arch/powerpc/include/asm/vdso/vsyscall.h
index 92f480d8cc6d..48560a119559 100644
--- a/arch/powerpc/include/asm/vdso/vsyscall.h
+++ b/arch/powerpc/include/asm/vdso/vsyscall.h
@@ -4,12 +4,8 @@
#ifndef __ASSEMBLY__
-#include <linux/timekeeper_internal.h>
#include <asm/vdso_datapage.h>
-/*
- * Update the vDSO data page to keep in sync with kernel timekeeping.
- */
static __always_inline
struct vdso_data *__arch_get_k_vdso_data(void)
{
diff --git a/arch/powerpc/include/asm/vdso_datapage.h b/arch/powerpc/include/asm/vdso_datapage.h
index 248dee138f7b..a202f5b63479 100644
--- a/arch/powerpc/include/asm/vdso_datapage.h
+++ b/arch/powerpc/include/asm/vdso_datapage.h
@@ -9,29 +9,6 @@
* IBM Corp.
*/
-
-/*
- * Note about this structure:
- *
- * This structure was historically called systemcfg and exposed to
- * userland via /proc/ppc64/systemcfg. Unfortunately, this became an
- * ABI issue as some proprietary software started relying on being able
- * to mmap() it, thus we have to keep the base layout at least for a
- * few kernel versions.
- *
- * However, since ppc32 doesn't suffer from this backward handicap,
- * a simpler version of the data structure is used there with only the
- * fields actually used by the vDSO.
- *
- */
-
-/*
- * If the major version changes we are incompatible.
- * Minor version changes are a hint.
- */
-#define SYSTEMCFG_MAJOR 1
-#define SYSTEMCFG_MINOR 1
-
#ifndef __ASSEMBLY__
#include <linux/unistd.h>
@@ -40,41 +17,10 @@
#define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32)
-/*
- * So here is the ppc64 backward compatible version
- */
-
#ifdef CONFIG_PPC64
struct vdso_arch_data {
- __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
- struct { /* Systemcfg version numbers */
- __u32 major; /* Major number 0x10 */
- __u32 minor; /* Minor number 0x14 */
- } version;
-
- /* Note about the platform flags: it now only contains the lpar
- * bit. The actual platform number is dead and buried
- */
- __u32 platform; /* Platform flags 0x18 */
- __u32 processor; /* Processor type 0x1C */
- __u64 processorCount; /* # of physical processors 0x20 */
- __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
- __u64 tb_orig_stamp; /* (NU) Timebase at boot 0x30 */
- __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
- __u64 tb_to_xs; /* (NU) Inverse of TB to 2^20 0x40 */
- __u64 stamp_xsec; /* (NU) 0x48 */
- __u64 tb_update_count; /* (NU) Timebase atomicity ctr 0x50 */
- __u32 tz_minuteswest; /* (NU) Min. west of Greenwich 0x58 */
- __u32 tz_dsttime; /* (NU) Type of dst correction 0x5C */
- __u32 dcache_size; /* L1 d-cache size 0x60 */
- __u32 dcache_line_size; /* L1 d-cache line size 0x64 */
- __u32 icache_size; /* L1 i-cache size 0x68 */
- __u32 icache_line_size; /* L1 i-cache line size 0x6C */
-
- /* those additional ones don't have to be located anywhere
- * special as they were not part of the original systemcfg
- */
+ __u64 tb_ticks_per_sec; /* Timebase tics / sec */
__u32 dcache_block_size; /* L1 d-cache block size */
__u32 icache_block_size; /* L1 i-cache block size */
__u32 dcache_log_block_size; /* L1 d-cache log block size */
@@ -82,21 +28,20 @@ struct vdso_arch_data {
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
__u32 compat_syscall_map[SYSCALL_MAP_SIZE]; /* Map of compat syscalls */
- struct vdso_data data[CS_BASES];
struct vdso_rng_data rng_data;
+
+ struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
};
#else /* CONFIG_PPC64 */
-/*
- * And here is the simpler 32 bits version
- */
struct vdso_arch_data {
- __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
+ __u64 tb_ticks_per_sec; /* Timebase tics / sec */
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
__u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
- struct vdso_data data[CS_BASES];
struct vdso_rng_data rng_data;
+
+ struct vdso_data data[CS_BASES] __aligned(1 << CONFIG_PAGE_SHIFT);
};
#endif /* CONFIG_PPC64 */
@@ -105,29 +50,17 @@ extern struct vdso_arch_data *vdso_data;
#else /* __ASSEMBLY__ */
-.macro get_datapage ptr
+.macro get_datapage ptr offset=0
bcl 20, 31, .+4
999:
mflr \ptr
- addis \ptr, \ptr, (_vdso_datapage - 999b)@ha
- addi \ptr, \ptr, (_vdso_datapage - 999b)@l
+ addis \ptr, \ptr, (_vdso_datapage - 999b + \offset)@ha
+ addi \ptr, \ptr, (_vdso_datapage - 999b + \offset)@l
.endm
#include <asm/asm-offsets.h>
#include <asm/page.h>
-.macro get_realdatapage ptr scratch
- get_datapage \ptr
-#ifdef CONFIG_TIME_NS
- lwz \scratch, VDSO_CLOCKMODE_OFFSET(\ptr)
- xoris \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@h
- xori \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@l
- cntlzw \scratch, \scratch
- rlwinm \scratch, \scratch, PAGE_SHIFT - 5, 1 << PAGE_SHIFT
- add \ptr, \ptr, \scratch
-#endif
-.endm
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/vga.h b/arch/powerpc/include/asm/vga.h
index fcf721682a71..f2dc40e1c52a 100644
--- a/arch/powerpc/include/asm/vga.h
+++ b/arch/powerpc/include/asm/vga.h
@@ -40,11 +40,6 @@ static inline void scr_memsetw(u16 *s, u16 v, unsigned int n)
memset16(s, cpu_to_le16(v), n / 2);
}
-#define VT_BUF_HAVE_MEMCPYW
-#define VT_BUF_HAVE_MEMMOVEW
-#define scr_memcpyw memcpy
-#define scr_memmovew memmove
-
#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */
#ifdef __powerpc64__
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 131a8cc10dbe..7a390bd4f4af 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -335,7 +335,6 @@ int main(void)
/* datapage offsets for use by vdso */
OFFSET(VDSO_DATA_OFFSET, vdso_arch_data, data);
- OFFSET(VDSO_RNG_DATA_OFFSET, vdso_arch_data, rng_data);
OFFSET(CFG_TB_TICKS_PER_SEC, vdso_arch_data, tb_ticks_per_sec);
#ifdef CONFIG_PPC64
OFFSET(CFG_ICACHE_BLOCKSZ, vdso_arch_data, icache_block_size);
@@ -347,8 +346,6 @@ int main(void)
#else
OFFSET(CFG_SYSCALL_MAP32, vdso_arch_data, syscall_map);
#endif
- OFFSET(VDSO_CLOCKMODE_OFFSET, vdso_arch_data, data[0].clock_mode);
- DEFINE(VDSO_CLOCKMODE_TIMENS, VDSO_CLOCKMODE_TIMENS);
#ifdef CONFIG_BUG
DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
@@ -597,7 +594,6 @@ int main(void)
HSTATE_FIELD(HSTATE_DABR, dabr);
HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
HSTATE_FIELD(HSTATE_SPLIT_MODE, kvm_split_mode);
- DEFINE(IPI_PRIORITY, IPI_PRIORITY);
OFFSET(KVM_SPLIT_RPR, kvm_split_mode, rpr);
OFFSET(KVM_SPLIT_PMMAR, kvm_split_mode, pmmar);
OFFSET(KVM_SPLIT_LDBAR, kvm_split_mode, ldbar);
@@ -677,5 +673,16 @@ int main(void)
DEFINE(BPT_SIZE, BPT_SIZE);
#endif
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ DEFINE(FTRACE_OOL_STUB_SIZE, sizeof(struct ftrace_ool_stub));
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
+ OFFSET(FTRACE_OPS_FUNC, ftrace_ops, func);
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ OFFSET(FTRACE_OPS_DIRECT_CALL, ftrace_ops, direct_call);
+#endif
+#endif
+
return 0;
}
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 2086fa6cdc25..103b6605dd68 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -13,7 +13,7 @@
#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/of.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/kdump.h>
#include <asm/firmware.h>
#include <linux/uio.h>
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index af4263594eb2..1bee15c013e7 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -867,7 +867,7 @@ bool __init dt_cpu_ftrs_init(void *fdt)
using_dt_cpu_ftrs = false;
/* Setup and verify the FDT, if it fails we just bail */
- if (!early_init_dt_verify(fdt))
+ if (!early_init_dt_verify(fdt, __pa(fdt)))
return false;
if (!of_scan_flat_dt(fdt_find_cpu_features, NULL))
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index d4b8aff20815..247ab2acaccc 100644
--- a/arch/powerpc/kernel/epapr_paravirt.c
+++ b/arch/powerpc/kernel/epapr_paravirt.c
@@ -9,7 +9,7 @@
#include <linux/of_fdt.h>
#include <asm/epapr_hcalls.h>
#include <asm/cacheflush.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/machdep.h>
#include <asm/inst.h>
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index a612e7513a4f..4b371c738213 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -78,26 +78,38 @@ static struct cma *fadump_cma;
* But for some reason even if it fails we still have the memory reservation
* with us and we can still continue doing fadump.
*/
-static int __init fadump_cma_init(void)
+void __init fadump_cma_init(void)
{
- unsigned long long base, size;
+ unsigned long long base, size, end;
int rc;
- if (!fw_dump.fadump_enabled)
- return 0;
-
+ if (!fw_dump.fadump_supported || !fw_dump.fadump_enabled ||
+ fw_dump.dump_active)
+ return;
/*
* Do not use CMA if user has provided fadump=nocma kernel parameter.
- * Return 1 to continue with fadump old behaviour.
*/
- if (fw_dump.nocma)
- return 1;
+ if (fw_dump.nocma || !fw_dump.boot_memory_size)
+ return;
+ /*
+ * [base, end) should be reserved during early init in
+ * fadump_reserve_mem(). No need to check this here as
+ * cma_init_reserved_mem() already checks for overlap.
+ * Here we give the aligned chunk of this reserved memory to CMA.
+ */
base = fw_dump.reserve_dump_area_start;
size = fw_dump.boot_memory_size;
+ end = base + size;
- if (!size)
- return 0;
+ base = ALIGN(base, CMA_MIN_ALIGNMENT_BYTES);
+ end = ALIGN_DOWN(end, CMA_MIN_ALIGNMENT_BYTES);
+ size = end - base;
+
+ if (end <= base) {
+ pr_warn("%s: Too less memory to give to CMA\n", __func__);
+ return;
+ }
rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma);
if (rc) {
@@ -108,7 +120,7 @@ static int __init fadump_cma_init(void)
* blocked from production system usage. Hence return 1,
* so that we can continue with fadump.
*/
- return 1;
+ return;
}
/*
@@ -120,15 +132,13 @@ static int __init fadump_cma_init(void)
/*
* So we now have successfully initialized cma area for fadump.
*/
- pr_info("Initialized 0x%lx bytes cma area at %ldMB from 0x%lx "
+ pr_info("Initialized [0x%llx, %luMB] cma area from [0x%lx, %luMB] "
"bytes of memory reserved for firmware-assisted dump\n",
- cma_get_size(fadump_cma),
- (unsigned long)cma_get_base(fadump_cma) >> 20,
- fw_dump.reserve_dump_area_size);
- return 1;
+ cma_get_base(fadump_cma), cma_get_size(fadump_cma) >> 20,
+ fw_dump.reserve_dump_area_start,
+ fw_dump.boot_memory_size >> 20);
+ return;
}
-#else
-static int __init fadump_cma_init(void) { return 1; }
#endif /* CONFIG_CMA */
/*
@@ -143,7 +153,7 @@ void __init fadump_append_bootargs(void)
if (!fw_dump.dump_active || !fw_dump.param_area_supported || !fw_dump.param_area)
return;
- if (fw_dump.param_area >= fw_dump.boot_mem_top) {
+ if (fw_dump.param_area < fw_dump.boot_mem_top) {
if (memblock_reserve(fw_dump.param_area, COMMAND_LINE_SIZE)) {
pr_warn("WARNING: Can't use additional parameters area!\n");
fw_dump.param_area = 0;
@@ -558,13 +568,6 @@ int __init fadump_reserve_mem(void)
if (!fw_dump.dump_active) {
fw_dump.boot_memory_size =
PAGE_ALIGN(fadump_calculate_reserve_size());
-#ifdef CONFIG_CMA
- if (!fw_dump.nocma) {
- fw_dump.boot_memory_size =
- ALIGN(fw_dump.boot_memory_size,
- CMA_MIN_ALIGNMENT_BYTES);
- }
-#endif
bootmem_min = fw_dump.ops->fadump_get_bootmem_min();
if (fw_dump.boot_memory_size < bootmem_min) {
@@ -637,8 +640,6 @@ int __init fadump_reserve_mem(void)
pr_info("Reserved %lldMB of memory at %#016llx (System RAM: %lldMB)\n",
(size >> 20), base, (memblock_phys_mem_size() >> 20));
-
- ret = fadump_cma_init();
}
return ret;
@@ -1586,6 +1587,12 @@ static void __init fadump_init_files(void)
return;
}
+ if (fw_dump.param_area) {
+ rc = sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr);
+ if (rc)
+ pr_err("unable to create bootargs_append sysfs file (%d)\n", rc);
+ }
+
debugfs_create_file("fadump_region", 0444, arch_debugfs_dir, NULL,
&fadump_region_fops);
@@ -1740,7 +1747,7 @@ err_out:
* Reserve memory to store additional parameters to be passed
* for fadump/capture kernel.
*/
-static void __init fadump_setup_param_area(void)
+void __init fadump_setup_param_area(void)
{
phys_addr_t range_start, range_end;
@@ -1748,7 +1755,7 @@ static void __init fadump_setup_param_area(void)
return;
/* This memory can't be used by PFW or bootloader as it is shared across kernels */
- if (radix_enabled()) {
+ if (early_radix_enabled()) {
/*
* Anywhere in the upper half should be good enough as all memory
* is accessible in real mode.
@@ -1776,12 +1783,12 @@ static void __init fadump_setup_param_area(void)
COMMAND_LINE_SIZE,
range_start,
range_end);
- if (!fw_dump.param_area || sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr)) {
+ if (!fw_dump.param_area) {
pr_warn("WARNING: Could not setup area to pass additional parameters!\n");
return;
}
- memset(phys_to_virt(fw_dump.param_area), 0, COMMAND_LINE_SIZE);
+ memset((void *)fw_dump.param_area, 0, COMMAND_LINE_SIZE);
}
/*
@@ -1807,7 +1814,6 @@ int __init setup_fadump(void)
}
/* Initialize the kernel dump memory structure and register with f/w */
else if (fw_dump.reserve_dump_area_size) {
- fadump_setup_param_area();
fw_dump.ops->fadump_init_mem_struct(&fw_dump);
register_fadump();
}
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 2e1600a8bbbb..a0e8b998c9b5 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -89,69 +89,69 @@ int arch_show_interrupts(struct seq_file *p, int prec)
#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
if (tau_initialized) {
- seq_printf(p, "%*s: ", prec, "TAU");
+ seq_printf(p, "%*s:", prec, "TAU");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", tau_interrupts(j));
+ seq_put_decimal_ull_width(p, " ", tau_interrupts(j), 10);
seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
}
#endif /* CONFIG_PPC32 && CONFIG_TAU_INT */
- seq_printf(p, "%*s: ", prec, "LOC");
+ seq_printf(p, "%*s:", prec, "LOC");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_event);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).timer_irqs_event, 10);
seq_printf(p, " Local timer interrupts for timer event device\n");
- seq_printf(p, "%*s: ", prec, "BCT");
+ seq_printf(p, "%*s:", prec, "BCT");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).broadcast_irqs_event);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).broadcast_irqs_event, 10);
seq_printf(p, " Broadcast timer interrupts for timer event device\n");
- seq_printf(p, "%*s: ", prec, "LOC");
+ seq_printf(p, "%*s:", prec, "LOC");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_others);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).timer_irqs_others, 10);
seq_printf(p, " Local timer interrupts for others\n");
- seq_printf(p, "%*s: ", prec, "SPU");
+ seq_printf(p, "%*s:", prec, "SPU");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).spurious_irqs);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).spurious_irqs, 10);
seq_printf(p, " Spurious interrupts\n");
- seq_printf(p, "%*s: ", prec, "PMI");
+ seq_printf(p, "%*s:", prec, "PMI");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).pmu_irqs);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).pmu_irqs, 10);
seq_printf(p, " Performance monitoring interrupts\n");
- seq_printf(p, "%*s: ", prec, "MCE");
+ seq_printf(p, "%*s:", prec, "MCE");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).mce_exceptions, 10);
seq_printf(p, " Machine check exceptions\n");
#ifdef CONFIG_PPC_BOOK3S_64
if (cpu_has_feature(CPU_FTR_HVMODE)) {
- seq_printf(p, "%*s: ", prec, "HMI");
+ seq_printf(p, "%*s:", prec, "HMI");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", paca_ptrs[j]->hmi_irqs);
+ seq_put_decimal_ull_width(p, " ", paca_ptrs[j]->hmi_irqs, 10);
seq_printf(p, " Hypervisor Maintenance Interrupts\n");
}
#endif
- seq_printf(p, "%*s: ", prec, "NMI");
+ seq_printf(p, "%*s:", prec, "NMI");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).sreset_irqs);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).sreset_irqs, 10);
seq_printf(p, " System Reset interrupts\n");
#ifdef CONFIG_PPC_WATCHDOG
- seq_printf(p, "%*s: ", prec, "WDG");
+ seq_printf(p, "%*s:", prec, "WDG");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).soft_nmi_irqs);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).soft_nmi_irqs, 10);
seq_printf(p, " Watchdog soft-NMI interrupts\n");
#endif
#ifdef CONFIG_PPC_DOORBELL
if (cpu_has_feature(CPU_FTR_DBELL)) {
- seq_printf(p, "%*s: ", prec, "DBL");
+ seq_printf(p, "%*s:", prec, "DBL");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat, j).doorbell_irqs);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, j).doorbell_irqs, 10);
seq_printf(p, " Doorbell interrupts\n");
}
#endif
diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c
index 5277cf582c16..2659e1ac8604 100644
--- a/arch/powerpc/kernel/jump_label.c
+++ b/arch/powerpc/kernel/jump_label.c
@@ -5,7 +5,7 @@
#include <linux/kernel.h>
#include <linux/jump_label.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/inst.h>
void arch_jump_label_transform(struct jump_entry *entry,
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index 7a8bc03a00af..5081334b7bd2 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -21,7 +21,7 @@
#include <asm/processor.h>
#include <asm/machdep.h>
#include <asm/debug.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <linux/slab.h>
#include <asm/inst.h>
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index f8aa91bc3b17..c0d9f12cb441 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -21,7 +21,7 @@
#include <linux/slab.h>
#include <linux/set_memory.h>
#include <linux/execmem.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/cacheflush.h>
#include <asm/sstep.h>
#include <asm/sections.h>
@@ -105,24 +105,22 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
return addr;
}
-static bool arch_kprobe_on_func_entry(unsigned long offset)
+static bool arch_kprobe_on_func_entry(unsigned long addr, unsigned long offset)
{
-#ifdef CONFIG_PPC64_ELF_ABI_V2
-#ifdef CONFIG_KPROBES_ON_FTRACE
- return offset <= 16;
-#else
- return offset <= 8;
-#endif
-#else
+ unsigned long ip = ftrace_location(addr);
+
+ if (ip)
+ return offset <= (ip - addr);
+ if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && !IS_ENABLED(CONFIG_PPC_KERNEL_PCREL))
+ return offset <= 8;
return !offset;
-#endif
}
/* XXX try and fold the magic of kprobe_lookup_name() in this */
kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset,
bool *on_func_entry)
{
- *on_func_entry = arch_kprobe_on_func_entry(offset);
+ *on_func_entry = arch_kprobe_on_func_entry(addr, offset);
return (kprobe_opcode_t *)(addr + offset);
}
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 91123e102db4..a997c7f43dc0 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -74,7 +74,7 @@ _GLOBAL(rmci_off)
blr
#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
-#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
+#ifdef CONFIG_PPC_PMAC
/*
* Do an IO access in real mode
@@ -137,7 +137,7 @@ _GLOBAL(real_writeb)
sync
isync
blr
-#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
+#endif // CONFIG_PPC_PMAC
#ifdef CONFIG_PPC_PASEMI
@@ -174,7 +174,7 @@ _GLOBAL(real_205_writeb)
#endif /* CONFIG_PPC_PASEMI */
-#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE)
+#ifdef CONFIG_CPU_FREQ_PMAC64
/*
* SCOM access functions for 970 (FX only for now)
*
@@ -243,7 +243,7 @@ _GLOBAL(scom970_write)
/* restore interrupts */
mtmsrd r5,1
blr
-#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
+#endif // CONFIG_CPU_FREQ_PMAC64
/* kexec_wait(phys_cpu)
*
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index 816a63fd71fb..f930e3395a7f 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -18,7 +18,7 @@
#include <linux/bug.h>
#include <linux/sort.h>
#include <asm/setup.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
/* Count how many different relocations (different symbol, different
addend) */
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index e9bab599d0c2..45dac7b46aa3 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -17,7 +17,7 @@
#include <linux/kernel.h>
#include <asm/module.h>
#include <asm/firmware.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <linux/sort.h>
#include <asm/setup.h>
#include <asm/sections.h>
@@ -205,7 +205,9 @@ static int relacmp(const void *_x, const void *_y)
/* Get size of potential trampolines required. */
static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
- const Elf64_Shdr *sechdrs)
+ const Elf64_Shdr *sechdrs,
+ char *secstrings,
+ struct module *me)
{
/* One extra reloc so it's always 0-addr terminated */
unsigned long relocs = 1;
@@ -241,13 +243,25 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
}
}
-#ifdef CONFIG_DYNAMIC_FTRACE
- /* make the trampoline to the ftrace_caller */
- relocs++;
-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
- /* an additional one for ftrace_regs_caller */
- relocs++;
-#endif
+ /* stubs for ftrace_caller and ftrace_regs_caller */
+ relocs += IS_ENABLED(CONFIG_DYNAMIC_FTRACE) + IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS);
+
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ /* stubs for the function tracer */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (!strcmp(secstrings + sechdrs[i].sh_name, "__patchable_function_entries")) {
+ me->arch.ool_stub_count = sechdrs[i].sh_size / sizeof(unsigned long);
+ me->arch.ool_stub_index = 0;
+ relocs += roundup(me->arch.ool_stub_count * sizeof(struct ftrace_ool_stub),
+ sizeof(struct ppc64_stub_entry)) /
+ sizeof(struct ppc64_stub_entry);
+ break;
+ }
+ }
+ if (i == hdr->e_shnum) {
+ pr_err("%s: doesn't contain __patchable_function_entries.\n", me->name);
+ return -ENOEXEC;
+ }
#endif
pr_debug("Looks like a total of %lu stubs, max\n", relocs);
@@ -460,7 +474,7 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
#endif
/* Override the stubs size */
- sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
+ sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs, secstrings, me);
return 0;
}
@@ -1085,6 +1099,37 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
return 0;
}
+static int setup_ftrace_ool_stubs(const Elf64_Shdr *sechdrs, unsigned long addr, struct module *me)
+{
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ unsigned int i, total_stubs, num_stubs;
+ struct ppc64_stub_entry *stub;
+
+ total_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*stub);
+ num_stubs = roundup(me->arch.ool_stub_count * sizeof(struct ftrace_ool_stub),
+ sizeof(struct ppc64_stub_entry)) / sizeof(struct ppc64_stub_entry);
+
+ /* Find the next available entry */
+ stub = (void *)sechdrs[me->arch.stubs_section].sh_addr;
+ for (i = 0; stub_func_addr(stub[i].funcdata); i++)
+ if (WARN_ON(i >= total_stubs))
+ return -1;
+
+ if (WARN_ON(i + num_stubs > total_stubs))
+ return -1;
+
+ stub += i;
+ me->arch.ool_stubs = (struct ftrace_ool_stub *)stub;
+
+ /* reserve stubs */
+ for (i = 0; i < num_stubs; i++)
+ if (patch_u32((void *)&stub->funcdata, PPC_RAW_NOP()))
+ return -1;
+#endif
+
+ return 0;
+}
+
int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
{
mod->arch.tramp = stub_for_addr(sechdrs,
@@ -1103,6 +1148,9 @@ int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
if (!mod->arch.tramp)
return -ENOENT;
+ if (setup_ftrace_ool_stubs(sechdrs, mod->arch.tramp, mod))
+ return -ENOENT;
+
return 0;
}
#endif
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index c0b351d61058..2e83702bf9ba 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -13,7 +13,7 @@
#include <asm/kprobes.h>
#include <asm/ptrace.h>
#include <asm/cacheflush.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/sstep.h>
#include <asm/ppc-opcode.h>
#include <asm/inst.h>
diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c
index b109cd7b5d01..3816a2bf2b84 100644
--- a/arch/powerpc/kernel/proc_powerpc.c
+++ b/arch/powerpc/kernel/proc_powerpc.c
@@ -4,6 +4,7 @@
*/
#include <linux/init.h>
+#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
@@ -12,9 +13,10 @@
#include <asm/machdep.h>
#include <asm/vdso_datapage.h>
#include <asm/rtas.h>
+#include <asm/systemcfg.h>
#include <linux/uaccess.h>
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
static loff_t page_map_seek(struct file *file, loff_t off, int whence)
{
@@ -33,10 +35,9 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
if ((vma->vm_end - vma->vm_start) > PAGE_SIZE)
return -EINVAL;
- remap_pfn_range(vma, vma->vm_start,
- __pa(pde_data(file_inode(file))) >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot);
- return 0;
+ return remap_pfn_range(vma, vma->vm_start,
+ __pa(pde_data(file_inode(file))) >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot);
}
static const struct proc_ops page_map_proc_ops = {
@@ -45,13 +46,35 @@ static const struct proc_ops page_map_proc_ops = {
.proc_mmap = page_map_mmap,
};
+static union {
+ struct systemcfg data;
+ u8 page[PAGE_SIZE];
+} systemcfg_data_store __page_aligned_data;
+struct systemcfg *systemcfg = &systemcfg_data_store.data;
static int __init proc_ppc64_init(void)
{
struct proc_dir_entry *pde;
+ strcpy((char *)systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
+ systemcfg->version.major = SYSTEMCFG_MAJOR;
+ systemcfg->version.minor = SYSTEMCFG_MINOR;
+ systemcfg->processor = mfspr(SPRN_PVR);
+ /*
+ * Fake the old platform number for pSeries and add
+ * in LPAR bit if necessary
+ */
+ systemcfg->platform = 0x100;
+ if (firmware_has_feature(FW_FEATURE_LPAR))
+ systemcfg->platform |= 1;
+ systemcfg->physicalMemorySize = memblock_phys_mem_size();
+ systemcfg->dcache_size = ppc64_caches.l1d.size;
+ systemcfg->dcache_line_size = ppc64_caches.l1d.line_size;
+ systemcfg->icache_size = ppc64_caches.l1i.size;
+ systemcfg->icache_line_size = ppc64_caches.l1i.line_size;
+
pde = proc_create_data("powerpc/systemcfg", S_IFREG | 0444, NULL,
- &page_map_proc_ops, vdso_data);
+ &page_map_proc_ops, systemcfg);
if (!pde)
return 1;
proc_set_size(pde, PAGE_SIZE);
@@ -60,7 +83,7 @@ static int __init proc_ppc64_init(void)
}
__initcall(proc_ppc64_init);
-#endif /* CONFIG_PPC64 */
+#endif /* CONFIG_PPC64_PROC_SYSTEMCFG */
/*
* Create the ppc64 and ppc64/rtas directories early. This allows us to
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index ff61a3e7984c..7b739b9a91ab 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -54,7 +54,7 @@
#include <asm/firmware.h>
#include <asm/hw_irq.h>
#endif
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/exec.h>
#include <asm/livepatch.h>
#include <asm/cpu_has_feature.h>
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 0be07ed407c7..e0059842a1c6 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -791,7 +791,7 @@ void __init early_init_devtree(void *params)
DBG(" -> early_init_devtree(%px)\n", params);
/* Too early to BUG_ON(), do it by hand */
- if (!early_init_dt_verify(params))
+ if (!early_init_dt_verify(params, __pa(params)))
panic("BUG: Failed verifying flat device tree, bad version?");
of_scan_flat_dt(early_init_dt_scan_model, NULL);
@@ -908,6 +908,9 @@ void __init early_init_devtree(void *params)
mmu_early_init_devtree();
+ /* Setup param area for passing additional parameters to fadump capture kernel. */
+ fadump_setup_param_area();
+
#ifdef CONFIG_PPC_POWERNV
/* Scan and build the list of machine check recoverable ranges */
of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index fbb68fc28ed3..8e776ba39497 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2792,90 +2792,6 @@ static void __init flatten_device_tree(void)
dt_struct_start, dt_struct_end);
}
-#ifdef CONFIG_PPC_MAPLE
-/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
- * The values are bad, and it doesn't even have the right number of cells. */
-static void __init fixup_device_tree_maple(void)
-{
- phandle isa;
- u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
- u32 isa_ranges[6];
- char *name;
-
- name = "/ht@0/isa@4";
- isa = call_prom("finddevice", 1, 1, ADDR(name));
- if (!PHANDLE_VALID(isa)) {
- name = "/ht@0/isa@6";
- isa = call_prom("finddevice", 1, 1, ADDR(name));
- rloc = 0x01003000; /* IO space; PCI device = 6 */
- }
- if (!PHANDLE_VALID(isa))
- return;
-
- if (prom_getproplen(isa, "ranges") != 12)
- return;
- if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
- == PROM_ERROR)
- return;
-
- if (isa_ranges[0] != 0x1 ||
- isa_ranges[1] != 0xf4000000 ||
- isa_ranges[2] != 0x00010000)
- return;
-
- prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
-
- isa_ranges[0] = 0x1;
- isa_ranges[1] = 0x0;
- isa_ranges[2] = rloc;
- isa_ranges[3] = 0x0;
- isa_ranges[4] = 0x0;
- isa_ranges[5] = 0x00010000;
- prom_setprop(isa, name, "ranges",
- isa_ranges, sizeof(isa_ranges));
-}
-
-#define CPC925_MC_START 0xf8000000
-#define CPC925_MC_LENGTH 0x1000000
-/* The values for memory-controller don't have right number of cells */
-static void __init fixup_device_tree_maple_memory_controller(void)
-{
- phandle mc;
- u32 mc_reg[4];
- char *name = "/hostbridge@f8000000";
- u32 ac, sc;
-
- mc = call_prom("finddevice", 1, 1, ADDR(name));
- if (!PHANDLE_VALID(mc))
- return;
-
- if (prom_getproplen(mc, "reg") != 8)
- return;
-
- prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
- prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
- if ((ac != 2) || (sc != 2))
- return;
-
- if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
- return;
-
- if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
- return;
-
- prom_printf("Fixing up bogus hostbridge on Maple...\n");
-
- mc_reg[0] = 0x0;
- mc_reg[1] = CPC925_MC_START;
- mc_reg[2] = 0x0;
- mc_reg[3] = CPC925_MC_LENGTH;
- prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
-}
-#else
-#define fixup_device_tree_maple()
-#define fixup_device_tree_maple_memory_controller()
-#endif
-
#ifdef CONFIG_PPC_CHRP
/*
* Pegasos and BriQ lacks the "ranges" property in the isa node
@@ -2932,7 +2848,7 @@ static void __init fixup_device_tree_chrp(void)
#endif
#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
-static void __init fixup_device_tree_pmac(void)
+static void __init fixup_device_tree_pmac64(void)
{
phandle u3, i2c, mpic;
u32 u3_rev;
@@ -2972,7 +2888,31 @@ static void __init fixup_device_tree_pmac(void)
&parent, sizeof(parent));
}
#else
-#define fixup_device_tree_pmac()
+#define fixup_device_tree_pmac64()
+#endif
+
+#ifdef CONFIG_PPC_PMAC
+static void __init fixup_device_tree_pmac(void)
+{
+ __be32 val = 1;
+ char type[8];
+ phandle node;
+
+ // Some pmacs are missing #size-cells on escc nodes
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = '\0';
+ prom_getprop(node, "device_type", type, sizeof(type));
+ if (prom_strcmp(type, "escc"))
+ continue;
+
+ if (prom_getproplen(node, "#size-cells") != PROM_ERROR)
+ continue;
+
+ prom_setprop(node, NULL, "#size-cells", &val, sizeof(val));
+ }
+}
+#else
+static inline void fixup_device_tree_pmac(void) { }
#endif
#ifdef CONFIG_PPC_EFIKA
@@ -3193,10 +3133,9 @@ static inline void fixup_device_tree_pasemi(void) { }
static void __init fixup_device_tree(void)
{
- fixup_device_tree_maple();
- fixup_device_tree_maple_memory_controller();
fixup_device_tree_chrp();
fixup_device_tree_pmac();
+ fixup_device_tree_pmac64();
fixup_device_tree_efika();
fixup_device_tree_pasemi();
}
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index f7e86e09c49f..d31c9799cab2 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -1390,21 +1390,14 @@ bool __ref rtas_busy_delay(int status)
*/
ms = clamp(ms, 1U, 1000U);
/*
- * The delay hint is an order-of-magnitude suggestion, not
- * a minimum. It is fine, possibly even advantageous, for
- * us to pause for less time than hinted. For small values,
- * use usleep_range() to ensure we don't sleep much longer
- * than actually needed.
- *
- * See Documentation/timers/timers-howto.rst for
- * explanation of the threshold used here. In effect we use
- * usleep_range() for 9900 and 9901, msleep() for
- * 9902-9905.
+ * The delay hint is an order-of-magnitude suggestion, not a
+ * minimum. It is fine, possibly even advantageous, for us to
+ * pause for less time than hinted. To make sure pause time will
+ * not be way longer than requested independent of HZ
+ * configuration, use fsleep(). See fsleep() for details of
+ * used sleeping functions.
*/
- if (ms <= 20)
- usleep_range(ms * 100, ms * 1000);
- else
- msleep(ms);
+ fsleep(ms * 1000);
break;
case RTAS_BUSY:
ret = true;
diff --git a/arch/powerpc/kernel/secure_boot.c b/arch/powerpc/kernel/secure_boot.c
index 9e0efb657f39..3a28795b4ed8 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -5,6 +5,7 @@
*/
#include <linux/types.h>
#include <linux/of.h>
+#include <linux/string_choices.h>
#include <asm/secure_boot.h>
static struct device_node *get_ppc_fw_sb_node(void)
@@ -38,7 +39,7 @@ bool is_ppc_secureboot_enabled(void)
of_node_put(node);
out:
- pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
+ pr_info("Secure boot mode %s\n", str_enabled_disabled(enabled));
return enabled;
}
@@ -62,7 +63,7 @@ bool is_ppc_trustedboot_enabled(void)
of_node_put(node);
out:
- pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
+ pr_info("Trusted boot mode %s\n", str_enabled_disabled(enabled));
return enabled;
}
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
index 4856e1a5161c..fbb7ebd8aa08 100644
--- a/arch/powerpc/kernel/security.c
+++ b/arch/powerpc/kernel/security.c
@@ -14,7 +14,7 @@
#include <linux/debugfs.h>
#include <asm/asm-prototypes.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/security_features.h>
#include <asm/sections.h>
#include <asm/setup.h>
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 943430077375..6fa179448c33 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -67,6 +67,7 @@
#include <asm/cpu_has_feature.h>
#include <asm/kasan.h>
#include <asm/mce.h>
+#include <asm/systemcfg.h>
#include "setup.h"
@@ -560,7 +561,9 @@ void __init smp_setup_cpu_maps(void)
out:
of_node_put(dn);
}
- vdso_data->processorCount = num_present_cpus();
+#endif
+#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
+ systemcfg->processorCount = num_present_cpus();
#endif /* CONFIG_PPC64 */
/* Initialize CPU <=> thread mapping/
@@ -997,9 +1000,11 @@ void __init setup_arch(char **cmdline_p)
initmem_init();
/*
- * Reserve large chunks of memory for use by CMA for KVM and hugetlb. These must
- * be called after initmem_init(), so that pageblock_order is initialised.
+ * Reserve large chunks of memory for use by CMA for fadump, KVM and
+ * hugetlb. These must be called after initmem_init(), so that
+ * pageblock_order is initialised.
*/
+ fadump_cma_init();
kvm_cma_reserve();
gigantic_hugetlb_cma_reserve();
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index e515c1f7d8d3..75dbf3e0d9c4 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -40,7 +40,7 @@
#include <asm/time.h>
#include <asm/serial.h>
#include <asm/udbg.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/cpu_has_feature.h>
#include <asm/asm-prototypes.h>
#include <asm/kdump.h>
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 22f83fbbc762..e67f3048611f 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -60,7 +60,7 @@
#include <asm/xmon.h>
#include <asm/udbg.h>
#include <asm/kexec.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/ftrace.h>
#include <asm/opal.h>
#include <asm/cputhreads.h>
@@ -920,6 +920,7 @@ static int __init disable_hardlockup_detector(void)
hardlockup_detector_disable();
#else
if (firmware_has_feature(FW_FEATURE_LPAR)) {
+ check_kvm_guest();
if (is_kvm_guest())
hardlockup_detector_disable();
}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 4ab9b8cee77a..5ac7084eebc0 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -61,6 +61,7 @@
#include <asm/ftrace.h>
#include <asm/kup.h>
#include <asm/fadump.h>
+#include <asm/systemcfg.h>
#include <trace/events/ipi.h>
@@ -1186,8 +1187,8 @@ int generic_cpu_disable(void)
return -EBUSY;
set_cpu_online(cpu, false);
-#ifdef CONFIG_PPC64
- vdso_data->processorCount--;
+#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
+ systemcfg->processorCount--;
#endif
/* Update affinity of all IRQs previously aimed at this CPU */
irq_migrate_all_off_this_cpu();
@@ -1642,10 +1643,12 @@ void start_secondary(void *unused)
secondary_cpu_time_init();
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
if (system_state == SYSTEM_RUNNING)
- vdso_data->processorCount++;
+ systemcfg->processorCount++;
+#endif
+#ifdef CONFIG_PPC64
vdso_getcpu_init();
#endif
set_numa_node(numa_cpu_lookup_table[cpu]);
diff --git a/arch/powerpc/kernel/static_call.c b/arch/powerpc/kernel/static_call.c
index 1502b7e439ca..7cfd0710e757 100644
--- a/arch/powerpc/kernel/static_call.c
+++ b/arch/powerpc/kernel/static_call.c
@@ -2,7 +2,7 @@
#include <linux/memory.h>
#include <linux/static_call.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
{
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index ebae8415dfbb..d8b4ab78bef0 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -553,3 +553,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index b842c83ab497..6b3dd6decdf9 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -17,6 +17,7 @@
#include <asm/hvcall.h>
#include <asm/machdep.h>
#include <asm/smp.h>
+#include <asm/time.h>
#include <asm/pmc.h>
#include <asm/firmware.h>
#include <asm/idle.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 0ff9f038e800..0727332ad86f 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -71,11 +71,11 @@
#include <asm/vdso_datapage.h>
#include <asm/firmware.h>
#include <asm/mce.h>
+#include <asm/systemcfg.h>
/* powerpc clocksource/clockevent code */
#include <linux/clockchips.h>
-#include <linux/timekeeper_internal.h>
static u64 timebase_read(struct clocksource *);
static struct clocksource clocksource_timebase = {
@@ -951,6 +951,9 @@ void __init time_init(void)
}
vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
+#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
+ systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
+#endif
/* initialise and enable the large decrementer (if we have one) */
set_decrementer_max();
diff --git a/arch/powerpc/kernel/trace/Makefile b/arch/powerpc/kernel/trace/Makefile
index 125f4ca588b9..d6c3885453bd 100644
--- a/arch/powerpc/kernel/trace/Makefile
+++ b/arch/powerpc/kernel/trace/Makefile
@@ -9,12 +9,15 @@ CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_ftrace_64_pg.o = $(CC_FLAGS_FTRACE)
endif
-obj32-$(CONFIG_FUNCTION_TRACER) += ftrace.o ftrace_entry.o
-ifdef CONFIG_MPROFILE_KERNEL
-obj64-$(CONFIG_FUNCTION_TRACER) += ftrace.o ftrace_entry.o
+ifdef CONFIG_FUNCTION_TRACER
+obj32-y += ftrace.o ftrace_entry.o
+ifeq ($(CONFIG_MPROFILE_KERNEL)$(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY),)
+obj64-y += ftrace_64_pg.o ftrace_64_pg_entry.o
else
-obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64_pg.o ftrace_64_pg_entry.o
+obj64-y += ftrace.o ftrace_entry.o
+endif
endif
+
obj-$(CONFIG_TRACING) += trace_clock.o
obj-$(CONFIG_PPC64) += $(obj64-y)
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index d8d6b4fd9a14..5ccd791761e8 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -23,7 +23,7 @@
#include <linux/list.h>
#include <asm/cacheflush.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/ftrace.h>
#include <asm/syscall.h>
#include <asm/inst.h>
@@ -37,8 +37,12 @@ unsigned long ftrace_call_adjust(unsigned long addr)
if (addr >= (unsigned long)__exittext_begin && addr < (unsigned long)__exittext_end)
return 0;
- if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY))
+ if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY) &&
+ !IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
addr += MCOUNT_INSN_SIZE;
+ if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
+ addr += MCOUNT_INSN_SIZE;
+ }
return addr;
}
@@ -82,7 +86,7 @@ static inline int ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_
{
int ret = ftrace_validate_inst(ip, old);
- if (!ret)
+ if (!ret && !ppc_inst_equal(old, new))
ret = patch_instruction((u32 *)ip, new);
return ret;
@@ -106,28 +110,68 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
return 0;
}
+#ifdef CONFIG_MODULES
+static unsigned long ftrace_lookup_module_stub(unsigned long ip, unsigned long addr)
+{
+ struct module *mod = NULL;
+
+ preempt_disable();
+ mod = __module_text_address(ip);
+ preempt_enable();
+
+ if (!mod)
+ pr_err("No module loaded at addr=%lx\n", ip);
+
+ return (addr == (unsigned long)ftrace_caller ? mod->arch.tramp : mod->arch.tramp_regs);
+}
+#else
+static unsigned long ftrace_lookup_module_stub(unsigned long ip, unsigned long addr)
+{
+ return 0;
+}
+#endif
+
+static unsigned long ftrace_get_ool_stub(struct dyn_ftrace *rec)
+{
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ return rec->arch.ool_stub;
+#else
+ BUILD_BUG();
+#endif
+}
+
static int ftrace_get_call_inst(struct dyn_ftrace *rec, unsigned long addr, ppc_inst_t *call_inst)
{
- unsigned long ip = rec->ip;
+ unsigned long ip;
unsigned long stub;
- if (is_offset_in_branch_range(addr - ip)) {
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ ip = ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE; /* second instruction in stub */
+ else
+ ip = rec->ip;
+
+ if (!is_offset_in_branch_range(addr - ip) && addr != FTRACE_ADDR &&
+ addr != FTRACE_REGS_ADDR) {
+ /* This can only happen with ftrace direct */
+ if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS)) {
+ pr_err("0x%lx (0x%lx): Unexpected target address 0x%lx\n",
+ ip, rec->ip, addr);
+ return -EINVAL;
+ }
+ addr = FTRACE_ADDR;
+ }
+
+ if (is_offset_in_branch_range(addr - ip))
/* Within range */
stub = addr;
-#ifdef CONFIG_MODULES
- } else if (rec->arch.mod) {
- /* Module code would be going to one of the module stubs */
- stub = (addr == (unsigned long)ftrace_caller ? rec->arch.mod->arch.tramp :
- rec->arch.mod->arch.tramp_regs);
-#endif
- } else if (core_kernel_text(ip)) {
+ else if (core_kernel_text(ip))
/* We would be branching to one of our ftrace stubs */
stub = find_ftrace_tramp(ip);
- if (!stub) {
- pr_err("0x%lx: No ftrace stubs reachable\n", ip);
- return -EINVAL;
- }
- } else {
+ else
+ stub = ftrace_lookup_module_stub(ip, addr);
+
+ if (!stub) {
+ pr_err("0x%lx (0x%lx): No ftrace stubs reachable\n", ip, rec->ip);
return -EINVAL;
}
@@ -135,6 +179,145 @@ static int ftrace_get_call_inst(struct dyn_ftrace *rec, unsigned long addr, ppc_
return 0;
}
+static int ftrace_init_ool_stub(struct module *mod, struct dyn_ftrace *rec)
+{
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ static int ool_stub_text_index, ool_stub_text_end_index, ool_stub_inittext_index;
+ int ret = 0, ool_stub_count, *ool_stub_index;
+ ppc_inst_t inst;
+ /*
+ * See ftrace_entry.S if changing the below instruction sequence, as we rely on
+ * decoding the last branch instruction here to recover the correct function ip.
+ */
+ struct ftrace_ool_stub *ool_stub, ool_stub_template = {
+ .insn = {
+ PPC_RAW_MFLR(_R0),
+ PPC_RAW_NOP(), /* bl ftrace_caller */
+ PPC_RAW_MTLR(_R0),
+ PPC_RAW_NOP() /* b rec->ip + 4 */
+ }
+ };
+
+ WARN_ON(rec->arch.ool_stub);
+
+ if (is_kernel_inittext(rec->ip)) {
+ ool_stub = ftrace_ool_stub_inittext;
+ ool_stub_index = &ool_stub_inittext_index;
+ ool_stub_count = ftrace_ool_stub_inittext_count;
+ } else if (is_kernel_text(rec->ip)) {
+ /*
+ * ftrace records are sorted, so we first use up the stub area within .text
+ * (ftrace_ool_stub_text) before using the area at the end of .text
+ * (ftrace_ool_stub_text_end), unless the stub is out of range of the record.
+ */
+ if (ool_stub_text_index >= ftrace_ool_stub_text_count ||
+ !is_offset_in_branch_range((long)rec->ip -
+ (long)&ftrace_ool_stub_text[ool_stub_text_index])) {
+ ool_stub = ftrace_ool_stub_text_end;
+ ool_stub_index = &ool_stub_text_end_index;
+ ool_stub_count = ftrace_ool_stub_text_end_count;
+ } else {
+ ool_stub = ftrace_ool_stub_text;
+ ool_stub_index = &ool_stub_text_index;
+ ool_stub_count = ftrace_ool_stub_text_count;
+ }
+#ifdef CONFIG_MODULES
+ } else if (mod) {
+ ool_stub = mod->arch.ool_stubs;
+ ool_stub_index = &mod->arch.ool_stub_index;
+ ool_stub_count = mod->arch.ool_stub_count;
+#endif
+ } else {
+ return -EINVAL;
+ }
+
+ ool_stub += (*ool_stub_index)++;
+
+ if (WARN_ON(*ool_stub_index > ool_stub_count))
+ return -EINVAL;
+
+ if (!is_offset_in_branch_range((long)rec->ip - (long)&ool_stub->insn[0]) ||
+ !is_offset_in_branch_range((long)(rec->ip + MCOUNT_INSN_SIZE) -
+ (long)&ool_stub->insn[3])) {
+ pr_err("%s: ftrace ool stub out of range (%p -> %p).\n",
+ __func__, (void *)rec->ip, (void *)&ool_stub->insn[0]);
+ return -EINVAL;
+ }
+
+ rec->arch.ool_stub = (unsigned long)&ool_stub->insn[0];
+
+ /* bl ftrace_caller */
+ if (!mod)
+ ret = ftrace_get_call_inst(rec, (unsigned long)ftrace_caller, &inst);
+#ifdef CONFIG_MODULES
+ else
+ /*
+ * We can't use ftrace_get_call_inst() since that uses
+ * __module_text_address(rec->ip) to look up the module.
+ * But, since the module is not fully formed at this stage,
+ * the lookup fails. We know the target though, so generate
+ * the branch inst directly.
+ */
+ inst = ftrace_create_branch_inst(ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE,
+ mod->arch.tramp, 1);
+#endif
+ ool_stub_template.insn[1] = ppc_inst_val(inst);
+
+ /* b rec->ip + 4 */
+ if (!ret && create_branch(&inst, &ool_stub->insn[3], rec->ip + MCOUNT_INSN_SIZE, 0))
+ return -EINVAL;
+ ool_stub_template.insn[3] = ppc_inst_val(inst);
+
+ if (!ret)
+ ret = patch_instructions((u32 *)ool_stub, (u32 *)&ool_stub_template,
+ sizeof(ool_stub_template), false);
+
+ return ret;
+#else /* !CONFIG_PPC_FTRACE_OUT_OF_LINE */
+ BUILD_BUG();
+#endif
+}
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
+static const struct ftrace_ops *powerpc_rec_get_ops(struct dyn_ftrace *rec)
+{
+ const struct ftrace_ops *ops = NULL;
+
+ if (rec->flags & FTRACE_FL_CALL_OPS_EN) {
+ ops = ftrace_find_unique_ops(rec);
+ WARN_ON_ONCE(!ops);
+ }
+
+ if (!ops)
+ ops = &ftrace_list_ops;
+
+ return ops;
+}
+
+static int ftrace_rec_set_ops(struct dyn_ftrace *rec, const struct ftrace_ops *ops)
+{
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ return patch_ulong((void *)(ftrace_get_ool_stub(rec) - sizeof(unsigned long)),
+ (unsigned long)ops);
+ else
+ return patch_ulong((void *)(rec->ip - MCOUNT_INSN_SIZE - sizeof(unsigned long)),
+ (unsigned long)ops);
+}
+
+static int ftrace_rec_set_nop_ops(struct dyn_ftrace *rec)
+{
+ return ftrace_rec_set_ops(rec, &ftrace_nop_ops);
+}
+
+static int ftrace_rec_update_ops(struct dyn_ftrace *rec)
+{
+ return ftrace_rec_set_ops(rec, powerpc_rec_get_ops(rec));
+}
+#else
+static int ftrace_rec_set_nop_ops(struct dyn_ftrace *rec) { return 0; }
+static int ftrace_rec_update_ops(struct dyn_ftrace *rec) { return 0; }
+#endif
+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, unsigned long addr)
{
@@ -147,18 +330,33 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, unsigned
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
ppc_inst_t old, new;
- int ret;
+ unsigned long ip = rec->ip;
+ int ret = 0;
/* This can only ever be called during module load */
- if (WARN_ON(!IS_ENABLED(CONFIG_MODULES) || core_kernel_text(rec->ip)))
+ if (WARN_ON(!IS_ENABLED(CONFIG_MODULES) || core_kernel_text(ip)))
return -EINVAL;
old = ppc_inst(PPC_RAW_NOP());
- ret = ftrace_get_call_inst(rec, addr, &new);
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
+ ip = ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE; /* second instruction in stub */
+ ret = ftrace_get_call_inst(rec, (unsigned long)ftrace_caller, &old);
+ }
+
+ ret |= ftrace_get_call_inst(rec, addr, &new);
+
+ if (!ret)
+ ret = ftrace_modify_code(ip, old, new);
+
+ ret = ftrace_rec_update_ops(rec);
if (ret)
return ret;
- return ftrace_modify_code(rec->ip, old, new);
+ if (!ret && IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ ret = ftrace_modify_code(rec->ip, ppc_inst(PPC_RAW_NOP()),
+ ppc_inst(PPC_RAW_BRANCH((long)ftrace_get_ool_stub(rec) - (long)rec->ip)));
+
+ return ret;
}
int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
@@ -191,6 +389,13 @@ void ftrace_replace_code(int enable)
new_addr = ftrace_get_addr_new(rec);
update = ftrace_update_record(rec, enable);
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE) && update != FTRACE_UPDATE_IGNORE) {
+ ip = ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE;
+ ret = ftrace_get_call_inst(rec, (unsigned long)ftrace_caller, &nop_inst);
+ if (ret)
+ goto out;
+ }
+
switch (update) {
case FTRACE_UPDATE_IGNORE:
default:
@@ -198,16 +403,19 @@ void ftrace_replace_code(int enable)
case FTRACE_UPDATE_MODIFY_CALL:
ret = ftrace_get_call_inst(rec, new_addr, &new_call_inst);
ret |= ftrace_get_call_inst(rec, addr, &call_inst);
+ ret |= ftrace_rec_update_ops(rec);
old = call_inst;
new = new_call_inst;
break;
case FTRACE_UPDATE_MAKE_NOP:
ret = ftrace_get_call_inst(rec, addr, &call_inst);
+ ret |= ftrace_rec_set_nop_ops(rec);
old = call_inst;
new = nop_inst;
break;
case FTRACE_UPDATE_MAKE_CALL:
ret = ftrace_get_call_inst(rec, new_addr, &call_inst);
+ ret |= ftrace_rec_update_ops(rec);
old = nop_inst;
new = call_inst;
break;
@@ -215,6 +423,24 @@ void ftrace_replace_code(int enable)
if (!ret)
ret = ftrace_modify_code(ip, old, new);
+
+ if (!ret && IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE) &&
+ (update == FTRACE_UPDATE_MAKE_NOP || update == FTRACE_UPDATE_MAKE_CALL)) {
+ /* Update the actual ftrace location */
+ call_inst = ppc_inst(PPC_RAW_BRANCH((long)ftrace_get_ool_stub(rec) -
+ (long)rec->ip));
+ nop_inst = ppc_inst(PPC_RAW_NOP());
+ ip = rec->ip;
+
+ if (update == FTRACE_UPDATE_MAKE_NOP)
+ ret = ftrace_modify_code(ip, call_inst, nop_inst);
+ else
+ ret = ftrace_modify_code(ip, nop_inst, call_inst);
+
+ if (ret)
+ goto out;
+ }
+
if (ret)
goto out;
}
@@ -234,20 +460,27 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
/* Verify instructions surrounding the ftrace location */
if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY)) {
/* Expect nops */
- ret = ftrace_validate_inst(ip - 4, ppc_inst(PPC_RAW_NOP()));
+ if (!IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ ret = ftrace_validate_inst(ip - 4, ppc_inst(PPC_RAW_NOP()));
if (!ret)
ret = ftrace_validate_inst(ip, ppc_inst(PPC_RAW_NOP()));
} else if (IS_ENABLED(CONFIG_PPC32)) {
/* Expected sequence: 'mflr r0', 'stw r0,4(r1)', 'bl _mcount' */
ret = ftrace_validate_inst(ip - 8, ppc_inst(PPC_RAW_MFLR(_R0)));
- if (!ret)
- ret = ftrace_validate_inst(ip - 4, ppc_inst(PPC_RAW_STW(_R0, _R1, 4)));
+ if (ret)
+ return ret;
+ ret = ftrace_modify_code(ip - 4, ppc_inst(PPC_RAW_STW(_R0, _R1, 4)),
+ ppc_inst(PPC_RAW_NOP()));
} else if (IS_ENABLED(CONFIG_MPROFILE_KERNEL)) {
/* Expected sequence: 'mflr r0', ['std r0,16(r1)'], 'bl _mcount' */
ret = ftrace_read_inst(ip - 4, &old);
if (!ret && !ppc_inst_equal(old, ppc_inst(PPC_RAW_MFLR(_R0)))) {
+ /* Gcc v5.x emit the additional 'std' instruction, gcc v6.x don't */
ret = ftrace_validate_inst(ip - 8, ppc_inst(PPC_RAW_MFLR(_R0)));
- ret |= ftrace_validate_inst(ip - 4, ppc_inst(PPC_RAW_STD(_R0, _R1, 16)));
+ if (ret)
+ return ret;
+ ret = ftrace_modify_code(ip - 4, ppc_inst(PPC_RAW_STD(_R0, _R1, 16)),
+ ppc_inst(PPC_RAW_NOP()));
}
} else {
return -EINVAL;
@@ -256,13 +489,9 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
if (ret)
return ret;
- if (!core_kernel_text(ip)) {
- if (!mod) {
- pr_err("0x%lx: No module provided for non-kernel address\n", ip);
- return -EFAULT;
- }
- rec->arch.mod = mod;
- }
+ /* Set up out-of-line stub */
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ return ftrace_init_ool_stub(mod, rec);
/* Nop-out the ftrace location */
new = ppc_inst(PPC_RAW_NOP());
@@ -302,6 +531,13 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
ppc_inst_t old, new;
int ret;
+ /*
+ * When using CALL_OPS, the function to call is associated with the
+ * call site, and we don't have a global function pointer to update.
+ */
+ if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
+ return 0;
+
old = ppc_inst_read((u32 *)&ftrace_call);
new = ftrace_create_branch_inst(ip, ppc_function_entry(func), 1);
ret = ftrace_modify_code(ip, old, new);
@@ -421,7 +657,7 @@ int __init ftrace_dyn_arch_init(void)
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- unsigned long sp = fregs->regs.gpr[1];
+ unsigned long sp = arch_ftrace_regs(fregs)->regs.gpr[1];
int bit;
if (unlikely(ftrace_graph_is_dead()))
@@ -439,6 +675,6 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
ftrace_test_recursion_unlock(bit);
out:
- fregs->regs.link = parent_ip;
+ arch_ftrace_regs(fregs)->regs.link = parent_ip;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/powerpc/kernel/trace/ftrace_64_pg.c b/arch/powerpc/kernel/trace/ftrace_64_pg.c
index 12fab1803bcf..98787376eb87 100644
--- a/arch/powerpc/kernel/trace/ftrace_64_pg.c
+++ b/arch/powerpc/kernel/trace/ftrace_64_pg.c
@@ -23,7 +23,7 @@
#include <linux/list.h>
#include <asm/cacheflush.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/ftrace.h>
#include <asm/syscall.h>
#include <asm/inst.h>
@@ -116,6 +116,20 @@ static unsigned long find_bl_target(unsigned long ip, ppc_inst_t op)
}
#ifdef CONFIG_MODULES
+static struct module *ftrace_lookup_module(struct dyn_ftrace *rec)
+{
+ struct module *mod;
+
+ preempt_disable();
+ mod = __module_text_address(rec->ip);
+ preempt_enable();
+
+ if (!mod)
+ pr_err("No module loaded at addr=%lx\n", rec->ip);
+
+ return mod;
+}
+
static int
__ftrace_make_nop(struct module *mod,
struct dyn_ftrace *rec, unsigned long addr)
@@ -124,6 +138,12 @@ __ftrace_make_nop(struct module *mod,
unsigned long ip = rec->ip;
ppc_inst_t op, pop;
+ if (!mod) {
+ mod = ftrace_lookup_module(rec);
+ if (!mod)
+ return -EINVAL;
+ }
+
/* read where this goes */
if (copy_inst_from_kernel_nofault(&op, (void *)ip)) {
pr_err("Fetching opcode failed.\n");
@@ -366,27 +386,6 @@ int ftrace_make_nop(struct module *mod,
return -EINVAL;
}
- /*
- * Out of range jumps are called from modules.
- * We should either already have a pointer to the module
- * or it has been passed in.
- */
- if (!rec->arch.mod) {
- if (!mod) {
- pr_err("No module loaded addr=%lx\n", addr);
- return -EFAULT;
- }
- rec->arch.mod = mod;
- } else if (mod) {
- if (mod != rec->arch.mod) {
- pr_err("Record mod %p not equal to passed in mod %p\n",
- rec->arch.mod, mod);
- return -EINVAL;
- }
- /* nothing to do if mod == rec->arch.mod */
- } else
- mod = rec->arch.mod;
-
return __ftrace_make_nop(mod, rec, addr);
}
@@ -411,7 +410,10 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
ppc_inst_t op[2];
void *ip = (void *)rec->ip;
unsigned long entry, ptr, tramp;
- struct module *mod = rec->arch.mod;
+ struct module *mod = ftrace_lookup_module(rec);
+
+ if (!mod)
+ return -EINVAL;
/* read where this goes */
if (copy_inst_from_kernel_nofault(op, ip))
@@ -533,16 +535,6 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
return -EINVAL;
}
- /*
- * Out of range jumps are called from modules.
- * Being that we are converting from nop, it had better
- * already have a module defined.
- */
- if (!rec->arch.mod) {
- pr_err("No module loaded\n");
- return -EINVAL;
- }
-
return __ftrace_make_call(rec, addr);
}
@@ -555,7 +547,10 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
ppc_inst_t op;
unsigned long ip = rec->ip;
unsigned long entry, ptr, tramp;
- struct module *mod = rec->arch.mod;
+ struct module *mod = ftrace_lookup_module(rec);
+
+ if (!mod)
+ return -EINVAL;
/* If we never set up ftrace trampolines, then bail */
if (!mod->arch.tramp || !mod->arch.tramp_regs) {
@@ -668,14 +663,6 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
return -EINVAL;
}
- /*
- * Out of range jumps are called from modules.
- */
- if (!rec->arch.mod) {
- pr_err("No module loaded\n");
- return -EINVAL;
- }
-
return __ftrace_modify_call(rec, old_addr, addr);
}
#endif
@@ -829,7 +816,7 @@ out:
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- fregs->regs.link = __prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]);
+ arch_ftrace_regs(fregs)->regs.link = __prepare_ftrace_return(parent_ip, ip, arch_ftrace_regs(fregs)->regs.gpr[1]);
}
#else
unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
diff --git a/arch/powerpc/kernel/trace/ftrace_entry.S b/arch/powerpc/kernel/trace/ftrace_entry.S
index 76dbe9fd2c0f..2c1b24100eca 100644
--- a/arch/powerpc/kernel/trace/ftrace_entry.S
+++ b/arch/powerpc/kernel/trace/ftrace_entry.S
@@ -39,13 +39,37 @@
/* Create our stack frame + pt_regs */
PPC_STLU r1,-SWITCH_FRAME_SIZE(r1)
+ .if \allregs == 1
+ SAVE_GPRS(11, 12, r1)
+ .endif
+
+ /* Get the _mcount() call site out of LR */
+ mflr r11
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ /* Load the ftrace_op */
+ PPC_LL r12, -(MCOUNT_INSN_SIZE*2 + SZL)(r11)
+
+ /* Load direct_call from the ftrace_op */
+ PPC_LL r12, FTRACE_OPS_DIRECT_CALL(r12)
+ PPC_LCMPI r12, 0
+ .if \allregs == 1
+ bne .Lftrace_direct_call_regs
+ .else
+ bne .Lftrace_direct_call
+ .endif
+#endif
+
+ /* Save the previous LR in pt_regs->link */
+ PPC_STL r0, _LINK(r1)
+ /* Also save it in A's stack frame */
+ PPC_STL r0, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE+LRSAVE(r1)
+
/* Save all gprs to pt_regs */
SAVE_GPR(0, r1)
SAVE_GPRS(3, 10, r1)
#ifdef CONFIG_PPC64
- /* Save the original return address in A's stack frame */
- std r0, LRSAVE+SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE(r1)
/* Ok to continue? */
lbz r3, PACA_FTRACE_ENABLED(r13)
cmpdi r3, 0
@@ -54,9 +78,9 @@
.if \allregs == 1
SAVE_GPR(2, r1)
- SAVE_GPRS(11, 31, r1)
+ SAVE_GPRS(13, 31, r1)
.else
-#ifdef CONFIG_LIVEPATCH_64
+#if defined(CONFIG_LIVEPATCH_64) || defined(CONFIG_PPC_FTRACE_OUT_OF_LINE)
SAVE_GPR(14, r1)
#endif
.endif
@@ -67,80 +91,143 @@
.if \allregs == 1
/* Load special regs for save below */
+ mfcr r7
mfmsr r8
mfctr r9
mfxer r10
- mfcr r11
.else
/* Clear MSR to flag as ftrace_caller versus frace_regs_caller */
li r8, 0
.endif
- /* Get the _mcount() call site out of LR */
- mflr r7
- /* Save it as pt_regs->nip */
- PPC_STL r7, _NIP(r1)
- /* Also save it in B's stackframe header for proper unwind */
- PPC_STL r7, LRSAVE+SWITCH_FRAME_SIZE(r1)
- /* Save the read LR in pt_regs->link */
- PPC_STL r0, _LINK(r1)
-
#ifdef CONFIG_PPC64
/* Save callee's TOC in the ABI compliant location */
std r2, STK_GOT(r1)
LOAD_PACA_TOC() /* get kernel TOC in r2 */
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
+ /* r11 points to the instruction following the call to ftrace */
+ PPC_LL r5, -(MCOUNT_INSN_SIZE*2 + SZL)(r11)
+ PPC_LL r12, FTRACE_OPS_FUNC(r5)
+ mtctr r12
+#else /* !CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS */
+#ifdef CONFIG_PPC64
LOAD_REG_ADDR(r3, function_trace_op)
ld r5,0(r3)
#else
lis r3,function_trace_op@ha
lwz r5,function_trace_op@l(r3)
#endif
-
-#ifdef CONFIG_LIVEPATCH_64
- mr r14, r7 /* remember old NIP */
#endif
- /* Calculate ip from nip-4 into r3 for call below */
- subi r3, r7, MCOUNT_INSN_SIZE
-
- /* Put the original return address in r4 as parent_ip */
- mr r4, r0
-
/* Save special regs */
PPC_STL r8, _MSR(r1)
.if \allregs == 1
+ PPC_STL r7, _CCR(r1)
PPC_STL r9, _CTR(r1)
PPC_STL r10, _XER(r1)
- PPC_STL r11, _CCR(r1)
.endif
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ /* Clear orig_gpr3 to later detect ftrace_direct call */
+ li r7, 0
+ PPC_STL r7, ORIG_GPR3(r1)
+#endif
+
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ /* Save our real return address in nvr for return */
+ .if \allregs == 0
+ SAVE_GPR(15, r1)
+ .endif
+ mr r15, r11
+ /*
+ * We want the ftrace location in the function, but our lr (in r11)
+ * points at the 'mtlr r0' instruction in the out of line stub. To
+ * recover the ftrace location, we read the branch instruction in the
+ * stub, and adjust our lr by the branch offset.
+ *
+ * See ftrace_init_ool_stub() for the profile sequence.
+ */
+ lwz r8, MCOUNT_INSN_SIZE(r11)
+ slwi r8, r8, 6
+ srawi r8, r8, 6
+ add r3, r11, r8
+ /*
+ * Override our nip to point past the branch in the original function.
+ * This allows reliable stack trace and the ftrace stack tracer to work as-is.
+ */
+ addi r11, r3, MCOUNT_INSN_SIZE
+#else
+ /* Calculate ip from nip-4 into r3 for call below */
+ subi r3, r11, MCOUNT_INSN_SIZE
+#endif
+
+ /* Save NIP as pt_regs->nip */
+ PPC_STL r11, _NIP(r1)
+ /* Also save it in B's stackframe header for proper unwind */
+ PPC_STL r11, LRSAVE+SWITCH_FRAME_SIZE(r1)
+#if defined(CONFIG_LIVEPATCH_64) || defined(CONFIG_PPC_FTRACE_OUT_OF_LINE)
+ mr r14, r11 /* remember old NIP */
+#endif
+
+ /* Put the original return address in r4 as parent_ip */
+ mr r4, r0
+
/* Load &pt_regs in r6 for call below */
addi r6, r1, STACK_INT_FRAME_REGS
.endm
.macro ftrace_regs_exit allregs
- /* Load ctr with the possibly modified NIP */
- PPC_LL r3, _NIP(r1)
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ /* Check orig_gpr3 to detect ftrace_direct call */
+ PPC_LL r3, ORIG_GPR3(r1)
+ PPC_LCMPI cr1, r3, 0
mtctr r3
+#endif
+ /* Restore possibly modified LR */
+ PPC_LL r0, _LINK(r1)
+
+#ifndef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ /* Load ctr with the possibly modified NIP */
+ PPC_LL r3, _NIP(r1)
#ifdef CONFIG_LIVEPATCH_64
cmpd r14, r3 /* has NIP been altered? */
#endif
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ beq cr1,2f
+ mtlr r3
+ b 3f
+#endif
+2: mtctr r3
+ mtlr r0
+3:
+
+#else /* !CONFIG_PPC_FTRACE_OUT_OF_LINE */
+ /* Load LR with the possibly modified NIP */
+ PPC_LL r3, _NIP(r1)
+ cmpd r14, r3 /* has NIP been altered? */
+ bne- 1f
+
+ mr r3, r15
+ .if \allregs == 0
+ REST_GPR(15, r1)
+ .endif
+1: mtlr r3
+#endif
+
/* Restore gprs */
.if \allregs == 1
REST_GPRS(2, 31, r1)
.else
REST_GPRS(3, 10, r1)
-#ifdef CONFIG_LIVEPATCH_64
+#if defined(CONFIG_LIVEPATCH_64) || defined(CONFIG_PPC_FTRACE_OUT_OF_LINE)
REST_GPR(14, r1)
#endif
.endif
- /* Restore possibly modified LR */
- PPC_LL r0, _LINK(r1)
- mtlr r0
-
#ifdef CONFIG_PPC64
/* Restore callee's TOC */
ld r2, STK_GOT(r1)
@@ -153,23 +240,46 @@
/* Based on the cmpd above, if the NIP was altered handle livepatch */
bne- livepatch_handler
#endif
- bctr /* jump after _mcount site */
+
+ /* jump after _mcount site */
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ bnectr cr1
+#endif
+ /*
+ * Return with blr to keep the link stack balanced. The function profiling sequence
+ * uses 'mtlr r0' to restore LR.
+ */
+ blr
+#else
+ bctr
+#endif
.endm
-_GLOBAL(ftrace_regs_caller)
- ftrace_regs_entry 1
- /* ftrace_call(r3, r4, r5, r6) */
+.macro ftrace_regs_func allregs
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
+ bctrl
+#else
+ .if \allregs == 1
.globl ftrace_regs_call
ftrace_regs_call:
+ .else
+.globl ftrace_call
+ftrace_call:
+ .endif
+ /* ftrace_call(r3, r4, r5, r6) */
bl ftrace_stub
+#endif
+.endm
+
+_GLOBAL(ftrace_regs_caller)
+ ftrace_regs_entry 1
+ ftrace_regs_func 1
ftrace_regs_exit 1
_GLOBAL(ftrace_caller)
ftrace_regs_entry 0
- /* ftrace_call(r3, r4, r5, r6) */
-.globl ftrace_call
-ftrace_call:
- bl ftrace_stub
+ ftrace_regs_func 0
ftrace_regs_exit 0
_GLOBAL(ftrace_stub)
@@ -177,6 +287,11 @@ _GLOBAL(ftrace_stub)
#ifdef CONFIG_PPC64
ftrace_no_trace:
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ REST_GPR(3, r1)
+ addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
+ blr
+#else
mflr r3
mtctr r3
REST_GPR(3, r1)
@@ -184,6 +299,22 @@ ftrace_no_trace:
mtlr r0
bctr
#endif
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+.Lftrace_direct_call_regs:
+ mtctr r12
+ REST_GPRS(11, 12, r1)
+ addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
+ bctr
+.Lftrace_direct_call:
+ mtctr r12
+ addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
+ bctr
+SYM_FUNC_START(ftrace_stub_direct_tramp)
+ blr
+SYM_FUNC_END(ftrace_stub_direct_tramp)
+#endif
#ifdef CONFIG_LIVEPATCH_64
/*
@@ -194,11 +325,17 @@ ftrace_no_trace:
* We get here when a function A, calls another function B, but B has
* been live patched with a new function C.
*
- * On entry:
- * - we have no stack frame and can not allocate one
+ * On entry, we have no stack frame and can not allocate one.
+ *
+ * With PPC_FTRACE_OUT_OF_LINE=n, on entry:
* - LR points back to the original caller (in A)
* - CTR holds the new NIP in C
* - r0, r11 & r12 are free
+ *
+ * With PPC_FTRACE_OUT_OF_LINE=y, on entry:
+ * - r0 points back to the original caller (in A)
+ * - LR holds the new NIP in C
+ * - r11 & r12 are free
*/
livepatch_handler:
ld r12, PACA_THREAD_INFO(r13)
@@ -208,18 +345,23 @@ livepatch_handler:
addi r11, r11, 24
std r11, TI_livepatch_sp(r12)
- /* Save toc & real LR on livepatch stack */
- std r2, -24(r11)
- mflr r12
- std r12, -16(r11)
-
/* Store stack end marker */
lis r12, STACK_END_MAGIC@h
ori r12, r12, STACK_END_MAGIC@l
std r12, -8(r11)
- /* Put ctr in r12 for global entry and branch there */
+ /* Save toc & real LR on livepatch stack */
+ std r2, -24(r11)
+#ifndef CONFIG_PPC_FTRACE_OUT_OF_LINE
+ mflr r12
+ std r12, -16(r11)
mfctr r12
+#else
+ std r0, -16(r11)
+ mflr r12
+ /* Put ctr in r12 for global entry and branch there */
+ mtctr r12
+#endif
bctrl
/*
@@ -308,6 +450,14 @@ _GLOBAL(return_to_handler)
blr
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+SYM_DATA(ftrace_ool_stub_text_count, .long CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE)
+
+SYM_START(ftrace_ool_stub_text, SYM_L_GLOBAL, .balign SZL)
+ .space CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE * FTRACE_OOL_STUB_SIZE
+SYM_CODE_END(ftrace_ool_stub_text)
+#endif
+
.pushsection ".tramp.ftrace.text","aw",@progbits;
.globl ftrace_tramp_text
ftrace_tramp_text:
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 4b99208f5adc..0a72a537f879 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -39,9 +39,6 @@ void __init udbg_early_init(void)
#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE)
/* RTAS console debug */
udbg_init_rtas_console();
-#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
- /* Maple real mode debug */
- udbg_init_maple_realmode();
#elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
udbg_init_pas_realmode();
#elif defined(CONFIG_PPC_EARLY_DEBUG_BOOTX)
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 313802aff571..dfe8ed2192e8 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -205,29 +205,6 @@ void __init udbg_uart_init_mmio(void __iomem *addr, unsigned int stride)
udbg_use_uart();
}
-#ifdef CONFIG_PPC_MAPLE
-
-#define UDBG_UART_MAPLE_ADDR ((void __iomem *)0xf40003f8)
-
-static u8 udbg_uart_in_maple(unsigned int reg)
-{
- return real_readb(UDBG_UART_MAPLE_ADDR + reg);
-}
-
-static void udbg_uart_out_maple(unsigned int reg, u8 val)
-{
- real_writeb(val, UDBG_UART_MAPLE_ADDR + reg);
-}
-
-void __init udbg_init_maple_realmode(void)
-{
- udbg_uart_in = udbg_uart_in_maple;
- udbg_uart_out = udbg_uart_out_maple;
- udbg_use_uart();
-}
-
-#endif /* CONFIG_PPC_MAPLE */
-
#ifdef CONFIG_PPC_PASEMI
#define UDBG_UART_PAS_ADDR ((void __iomem *)0xfcff03f8UL)
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ee4b9d676cff..43379365ce1b 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -16,7 +16,6 @@
#include <linux/user.h>
#include <linux/elf.h>
#include <linux/security.h>
-#include <linux/memblock.h>
#include <linux/syscalls.h>
#include <linux/time_namespace.h>
#include <vdso/datapage.h>
@@ -48,12 +47,13 @@ long sys_ni_syscall(void);
*/
static union {
struct vdso_arch_data data;
- u8 page[PAGE_SIZE];
+ u8 page[2 * PAGE_SIZE];
} vdso_data_store __page_aligned_data;
struct vdso_arch_data *vdso_data = &vdso_data_store.data;
enum vvar_pages {
- VVAR_DATA_PAGE_OFFSET,
+ VVAR_BASE_PAGE_OFFSET,
+ VVAR_TIME_PAGE_OFFSET,
VVAR_TIMENS_PAGE_OFFSET,
VVAR_NR_PAGES,
};
@@ -119,7 +119,7 @@ static struct vm_special_mapping vdso64_spec __ro_after_init = {
#ifdef CONFIG_TIME_NS
struct vdso_data *arch_get_vdso_data(void *vvar_page)
{
- return ((struct vdso_arch_data *)vvar_page)->data;
+ return vvar_page;
}
/*
@@ -153,11 +153,14 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
unsigned long pfn;
switch (vmf->pgoff) {
- case VVAR_DATA_PAGE_OFFSET:
+ case VVAR_BASE_PAGE_OFFSET:
+ pfn = virt_to_pfn(vdso_data);
+ break;
+ case VVAR_TIME_PAGE_OFFSET:
if (timens_page)
pfn = page_to_pfn(timens_page);
else
- pfn = virt_to_pfn(vdso_data);
+ pfn = virt_to_pfn(vdso_data->data);
break;
#ifdef CONFIG_TIME_NS
case VVAR_TIMENS_PAGE_OFFSET:
@@ -170,7 +173,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
*/
if (!timens_page)
return VM_FAULT_SIGBUS;
- pfn = virt_to_pfn(vdso_data);
+ pfn = virt_to_pfn(vdso_data->data);
break;
#endif /* CONFIG_TIME_NS */
default:
@@ -349,25 +352,6 @@ static struct page ** __init vdso_setup_pages(void *start, void *end)
static int __init vdso_init(void)
{
#ifdef CONFIG_PPC64
- /*
- * Fill up the "systemcfg" stuff for backward compatibility
- */
- strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
- vdso_data->version.major = SYSTEMCFG_MAJOR;
- vdso_data->version.minor = SYSTEMCFG_MINOR;
- vdso_data->processor = mfspr(SPRN_PVR);
- /*
- * Fake the old platform number for pSeries and add
- * in LPAR bit if necessary
- */
- vdso_data->platform = 0x100;
- if (firmware_has_feature(FW_FEATURE_LPAR))
- vdso_data->platform |= 1;
- vdso_data->physicalMemorySize = memblock_phys_mem_size();
- vdso_data->dcache_size = ppc64_caches.l1d.size;
- vdso_data->dcache_line_size = ppc64_caches.l1d.line_size;
- vdso_data->icache_size = ppc64_caches.l1i.size;
- vdso_data->icache_line_size = ppc64_caches.l1i.line_size;
vdso_data->dcache_block_size = ppc64_caches.l1d.block_size;
vdso_data->icache_block_size = ppc64_caches.l1i.block_size;
vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;
diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
index 31ca5a547004..0e3ed6fb199f 100644
--- a/arch/powerpc/kernel/vdso/Makefile
+++ b/arch/powerpc/kernel/vdso/Makefile
@@ -50,14 +50,18 @@ ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl,--orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
# Filter flags that clang will warn are unused for linking
-ldflags-y += $(filter-out $(CC_AUTO_VAR_INIT_ZERO_ENABLER) $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS))
+ldflags-y += $(filter-out $(CC_AUTO_VAR_INIT_ZERO_ENABLER) $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
CC32FLAGS := -m32
CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
- # This flag is supported by clang for 64-bit but not 32-bit so it will cause
- # an unused command line flag warning for this file.
ifdef CONFIG_CC_IS_CLANG
+# This flag is supported by clang for 64-bit but not 32-bit so it will cause
+# an unused command line flag warning for this file.
CC32FLAGSREMOVE += -fno-stack-clash-protection
+# -mstack-protector-guard values from the 64-bit build are not valid for the
+# 32-bit one. clang validates the values passed to these arguments during
+# parsing, even when -fno-stack-protector is passed afterwards.
+CC32FLAGSREMOVE += -mstack-protector-guard%
endif
LD32FLAGS := -Wl,-soname=linux-vdso32.so.1
AS32FLAGS := -D__VDSO32__
diff --git a/arch/powerpc/kernel/vdso/cacheflush.S b/arch/powerpc/kernel/vdso/cacheflush.S
index 3b2479bd2f9a..0085ae464dac 100644
--- a/arch/powerpc/kernel/vdso/cacheflush.S
+++ b/arch/powerpc/kernel/vdso/cacheflush.S
@@ -30,7 +30,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
#ifdef CONFIG_PPC64
mflr r12
.cfi_register lr,r12
- get_realdatapage r10, r11
+ get_datapage r10
mtlr r12
.cfi_restore lr
#endif
diff --git a/arch/powerpc/kernel/vdso/datapage.S b/arch/powerpc/kernel/vdso/datapage.S
index 2b19b6201a33..db8e167f0166 100644
--- a/arch/powerpc/kernel/vdso/datapage.S
+++ b/arch/powerpc/kernel/vdso/datapage.S
@@ -28,7 +28,7 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
mflr r12
.cfi_register lr,r12
mr. r4,r3
- get_realdatapage r3, r11
+ get_datapage r3
mtlr r12
#ifdef __powerpc64__
addi r3,r3,CFG_SYSCALL_MAP64
@@ -52,7 +52,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
.cfi_startproc
mflr r12
.cfi_register lr,r12
- get_realdatapage r3, r11
+ get_datapage r3
#ifndef __powerpc64__
lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
#endif
diff --git a/arch/powerpc/kernel/vdso/getrandom.S b/arch/powerpc/kernel/vdso/getrandom.S
index f3bbf931931c..a80d9fb436f7 100644
--- a/arch/powerpc/kernel/vdso/getrandom.S
+++ b/arch/powerpc/kernel/vdso/getrandom.S
@@ -31,8 +31,6 @@
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
#endif
- get_realdatapage r8, r11
- addi r8, r8, VDSO_RNG_DATA_OFFSET
bl CFUNC(DOTSYM(\funct))
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
#ifdef __powerpc64__
diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S
index 5540d7021fa2..5333848322ca 100644
--- a/arch/powerpc/kernel/vdso/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso/gettimeofday.S
@@ -32,11 +32,10 @@
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
#endif
- get_datapage r5
.ifeq \call_time
- addi r5, r5, VDSO_DATA_OFFSET
+ get_datapage r5 VDSO_DATA_OFFSET
.else
- addi r4, r5, VDSO_DATA_OFFSET
+ get_datapage r4 VDSO_DATA_OFFSET
.endif
bl CFUNC(DOTSYM(\funct))
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
diff --git a/arch/powerpc/kernel/vdso/vdso32.lds.S b/arch/powerpc/kernel/vdso/vdso32.lds.S
index 7b41d5d256e8..1a1b0b6d681a 100644
--- a/arch/powerpc/kernel/vdso/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso/vdso32.lds.S
@@ -16,7 +16,7 @@ OUTPUT_ARCH(powerpc:common)
SECTIONS
{
- PROVIDE(_vdso_datapage = . - 2 * PAGE_SIZE);
+ PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
. = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
diff --git a/arch/powerpc/kernel/vdso/vdso64.lds.S b/arch/powerpc/kernel/vdso/vdso64.lds.S
index 9481e4b892ed..e21b5506cad6 100644
--- a/arch/powerpc/kernel/vdso/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso/vdso64.lds.S
@@ -16,7 +16,7 @@ OUTPUT_ARCH(powerpc:common64)
SECTIONS
{
- PROVIDE(_vdso_datapage = . - 2 * PAGE_SIZE);
+ PROVIDE(_vdso_datapage = . - 3 * PAGE_SIZE);
. = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
diff --git a/arch/powerpc/kernel/vdso/vgetrandom.c b/arch/powerpc/kernel/vdso/vgetrandom.c
index 5f855d45fb7b..cc79b960a541 100644
--- a/arch/powerpc/kernel/vdso/vgetrandom.c
+++ b/arch/powerpc/kernel/vdso/vgetrandom.c
@@ -8,7 +8,7 @@
#include <linux/types.h>
ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state,
- size_t opaque_len, const struct vdso_rng_data *vd)
+ size_t opaque_len)
{
- return __cvdso_getrandom_data(vd, buffer, len, flags, opaque_state, opaque_len);
+ return __cvdso_getrandom(buffer, len, flags, opaque_state, opaque_len);
}
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7ab4e2fb28b1..b4c9decc7a75 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -265,14 +265,13 @@ SECTIONS
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
_sinittext = .;
INIT_TEXT
-
+ *(.tramp.ftrace.init);
/*
*.init.text might be RO so we must ensure this section ends on
* a page boundary.
*/
. = ALIGN(PAGE_SIZE);
_einittext = .;
- *(.tramp.ftrace.init);
} :text
/* .exit.text is discarded at runtime, not link time,
diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
index 9738adabeb1f..dc65c1391157 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -736,13 +736,18 @@ int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
if (dn) {
u64 val;
- of_property_read_u64(dn, "opal-base-address", &val);
+ ret = of_property_read_u64(dn, "opal-base-address", &val);
+ if (ret)
+ goto out;
+
ret = kexec_purgatory_get_set_symbol(image, "opal_base", &val,
sizeof(val), false);
if (ret)
goto out;
- of_property_read_u64(dn, "opal-entry-address", &val);
+ ret = of_property_read_u64(dn, "opal-entry-address", &val);
+ if (ret)
+ goto out;
ret = kexec_purgatory_get_set_symbol(image, "opal_entry", &val,
sizeof(val), false);
}
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index ff6c38373957..d79c5d1098c0 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -422,7 +422,7 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
EXPORT_SYMBOL_GPL(kvmppc_core_prepare_to_enter);
kvm_pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing,
- bool *writable)
+ bool *writable, struct page **page)
{
ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM;
gfn_t gfn = gpa >> PAGE_SHIFT;
@@ -437,13 +437,14 @@ kvm_pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing,
kvm_pfn_t pfn;
pfn = (kvm_pfn_t)virt_to_phys((void*)shared_page) >> PAGE_SHIFT;
- get_page(pfn_to_page(pfn));
+ *page = pfn_to_page(pfn);
+ get_page(*page);
if (writable)
*writable = true;
return pfn;
}
- return gfn_to_pfn_prot(vcpu->kvm, gfn, writing, writable);
+ return kvm_faultin_pfn(vcpu, gfn, writing, writable, page);
}
EXPORT_SYMBOL_GPL(kvmppc_gpa_to_pfn);
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 4b3a8d80cfa3..5b7212edbb13 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -130,6 +130,7 @@ extern char etext[];
int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
bool iswrite)
{
+ struct page *page;
kvm_pfn_t hpaddr;
u64 vpn;
u64 vsid;
@@ -145,7 +146,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
bool writable;
/* Get host physical address for gpa */
- hpaddr = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable);
+ hpaddr = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable, &page);
if (is_error_noslot_pfn(hpaddr)) {
printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n",
orig_pte->raddr);
@@ -232,7 +233,7 @@ next_pteg:
pte = kvmppc_mmu_hpte_cache_next(vcpu);
if (!pte) {
- kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
+ kvm_release_page_unused(page);
r = -EAGAIN;
goto out;
}
@@ -250,7 +251,7 @@ next_pteg:
kvmppc_mmu_hpte_cache_map(vcpu, pte);
- kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
+ kvm_release_page_clean(page);
out:
return r;
}
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index bc6a381b5346..be20aee6fd7d 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -88,13 +88,14 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
struct hpte_cache *cpte;
unsigned long gfn = orig_pte->raddr >> PAGE_SHIFT;
unsigned long pfn;
+ struct page *page;
/* used to check for invalidations in progress */
mmu_seq = kvm->mmu_invalidate_seq;
smp_rmb();
/* Get host physical address for gpa */
- pfn = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable);
+ pfn = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable, &page);
if (is_error_noslot_pfn(pfn)) {
printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n",
orig_pte->raddr);
@@ -121,13 +122,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
vpn = hpt_vpn(orig_pte->eaddr, map->host_vsid, MMU_SEGSIZE_256M);
- kvm_set_pfn_accessed(pfn);
if (!orig_pte->may_write || !writable)
rflags |= PP_RXRX;
- else {
+ else
mark_page_dirty(vcpu->kvm, gfn);
- kvm_set_pfn_dirty(pfn);
- }
if (!orig_pte->may_execute)
rflags |= HPTE_R_N;
@@ -202,8 +200,10 @@ map_again:
}
out_unlock:
+ /* FIXME: Don't unconditionally pass unused=false. */
+ kvm_release_faultin_page(kvm, page, false,
+ orig_pte->may_write && writable);
spin_unlock(&kvm->mmu_lock);
- kvm_release_pfn_clean(pfn);
if (cpte)
kvmppc_mmu_hpte_cache_free(cpte);
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 1b51b1c4713b..f305395cf26e 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -603,27 +603,10 @@ int kvmppc_book3s_hv_page_fault(struct kvm_vcpu *vcpu,
write_ok = writing;
hva = gfn_to_hva_memslot(memslot, gfn);
- /*
- * Do a fast check first, since __gfn_to_pfn_memslot doesn't
- * do it with !atomic && !async, which is how we call it.
- * We always ask for write permission since the common case
- * is that the page is writable.
- */
- if (get_user_page_fast_only(hva, FOLL_WRITE, &page)) {
- write_ok = true;
- } else {
- /* Call KVM generic code to do the slow-path check */
- pfn = __gfn_to_pfn_memslot(memslot, gfn, false, false, NULL,
- writing, &write_ok, NULL);
- if (is_error_noslot_pfn(pfn))
- return -EFAULT;
- page = NULL;
- if (pfn_valid(pfn)) {
- page = pfn_to_page(pfn);
- if (PageReserved(page))
- page = NULL;
- }
- }
+ pfn = __kvm_faultin_pfn(memslot, gfn, writing ? FOLL_WRITE : 0,
+ &write_ok, &page);
+ if (is_error_noslot_pfn(pfn))
+ return -EFAULT;
/*
* Read the PTE from the process' radix tree and use that
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index 408d98f8a514..b3e6e73d6a08 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -821,7 +821,7 @@ bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested, bool writing,
int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
unsigned long gpa,
struct kvm_memory_slot *memslot,
- bool writing, bool kvm_ro,
+ bool writing,
pte_t *inserted_pte, unsigned int *levelp)
{
struct kvm *kvm = vcpu->kvm;
@@ -829,40 +829,21 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
unsigned long mmu_seq;
unsigned long hva, gfn = gpa >> PAGE_SHIFT;
bool upgrade_write = false;
- bool *upgrade_p = &upgrade_write;
pte_t pte, *ptep;
unsigned int shift, level;
int ret;
bool large_enable;
+ kvm_pfn_t pfn;
/* used to check for invalidations in progress */
mmu_seq = kvm->mmu_invalidate_seq;
smp_rmb();
- /*
- * Do a fast check first, since __gfn_to_pfn_memslot doesn't
- * do it with !atomic && !async, which is how we call it.
- * We always ask for write permission since the common case
- * is that the page is writable.
- */
hva = gfn_to_hva_memslot(memslot, gfn);
- if (!kvm_ro && get_user_page_fast_only(hva, FOLL_WRITE, &page)) {
- upgrade_write = true;
- } else {
- unsigned long pfn;
-
- /* Call KVM generic code to do the slow-path check */
- pfn = __gfn_to_pfn_memslot(memslot, gfn, false, false, NULL,
- writing, upgrade_p, NULL);
- if (is_error_noslot_pfn(pfn))
- return -EFAULT;
- page = NULL;
- if (pfn_valid(pfn)) {
- page = pfn_to_page(pfn);
- if (PageReserved(page))
- page = NULL;
- }
- }
+ pfn = __kvm_faultin_pfn(memslot, gfn, writing ? FOLL_WRITE : 0,
+ &upgrade_write, &page);
+ if (is_error_noslot_pfn(pfn))
+ return -EFAULT;
/*
* Read the PTE from the process' radix tree and use that
@@ -950,7 +931,6 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,
struct kvm_memory_slot *memslot;
long ret;
bool writing = !!(dsisr & DSISR_ISSTORE);
- bool kvm_ro = false;
/* Check for unusual errors */
if (dsisr & DSISR_UNSUPP_MMU) {
@@ -1003,7 +983,6 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,
ea, DSISR_ISSTORE | DSISR_PROTFAULT);
return RESUME_GUEST;
}
- kvm_ro = true;
}
/* Failed to set the reference/change bits */
@@ -1021,7 +1000,7 @@ int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu,
/* Try to insert a pte */
ret = kvmppc_book3s_instantiate_page(vcpu, gpa, memslot, writing,
- kvm_ro, NULL, NULL);
+ NULL, NULL);
if (ret == 0 || ret == -EAGAIN)
ret = RESUME_GUEST;
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 34c0adb9fdbf..742aa58a7c7e 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -115,10 +115,9 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
struct iommu_table_group *table_group;
long i;
struct kvmppc_spapr_tce_iommu_table *stit;
- struct fd f;
+ CLASS(fd, f)(tablefd);
- f = fdget(tablefd);
- if (!fd_file(f))
+ if (fd_empty(f))
return -EBADF;
rcu_read_lock();
@@ -130,16 +129,12 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
}
rcu_read_unlock();
- if (!found) {
- fdput(f);
+ if (!found)
return -EINVAL;
- }
table_group = iommu_group_get_iommudata(grp);
- if (WARN_ON(!table_group)) {
- fdput(f);
+ if (WARN_ON(!table_group))
return -EFAULT;
- }
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
struct iommu_table *tbltmp = table_group->tables[i];
@@ -160,10 +155,8 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
break;
}
}
- if (!tbl) {
- fdput(f);
+ if (!tbl)
return -EINVAL;
- }
rcu_read_lock();
list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
@@ -174,7 +167,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
/* stit is being destroyed */
iommu_tce_table_put(tbl);
rcu_read_unlock();
- fdput(f);
return -ENOTTY;
}
/*
@@ -182,7 +174,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
* its KVM reference counter and can return.
*/
rcu_read_unlock();
- fdput(f);
return 0;
}
rcu_read_unlock();
@@ -190,7 +181,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
stit = kzalloc(sizeof(*stit), GFP_KERNEL);
if (!stit) {
iommu_tce_table_put(tbl);
- fdput(f);
return -ENOMEM;
}
@@ -199,7 +189,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
list_add_rcu(&stit->next, &stt->iommu_tables);
- fdput(f);
return 0;
}
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index ba0492f9de65..25429905ae90 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -400,7 +400,10 @@ static inline unsigned long map_pcr_to_cap(unsigned long pcr)
cap = H_GUEST_CAP_POWER9;
break;
case PCR_ARCH_31:
- cap = H_GUEST_CAP_POWER10;
+ if (cpu_has_feature(CPU_FTR_P11_PVR))
+ cap = H_GUEST_CAP_POWER11;
+ else
+ cap = H_GUEST_CAP_POWER10;
break;
default:
break;
@@ -415,7 +418,7 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
struct kvmppc_vcore *vc = vcpu->arch.vcore;
/* We can (emulate) our own architecture version and anything older */
- if (cpu_has_feature(CPU_FTR_ARCH_31))
+ if (cpu_has_feature(CPU_FTR_P11_PVR) || cpu_has_feature(CPU_FTR_ARCH_31))
host_pcr_bit = PCR_ARCH_31;
else if (cpu_has_feature(CPU_FTR_ARCH_300))
host_pcr_bit = PCR_ARCH_300;
@@ -2060,36 +2063,9 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu)
fallthrough; /* go to facility unavailable handler */
#endif
- case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: {
- u64 cause = vcpu->arch.hfscr >> 56;
-
- /*
- * Only pass HFU interrupts to the L1 if the facility is
- * permitted but disabled by the L1's HFSCR, otherwise
- * the interrupt does not make sense to the L1 so turn
- * it into a HEAI.
- */
- if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) ||
- (vcpu->arch.nested_hfscr & (1UL << cause))) {
- ppc_inst_t pinst;
- vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST;
-
- /*
- * If the fetch failed, return to guest and
- * try executing it again.
- */
- r = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
- vcpu->arch.emul_inst = ppc_inst_val(pinst);
- if (r != EMULATE_DONE)
- r = RESUME_GUEST;
- else
- r = RESUME_HOST;
- } else {
- r = RESUME_HOST;
- }
-
+ case BOOK3S_INTERRUPT_H_FAC_UNAVAIL:
+ r = RESUME_HOST;
break;
- }
case BOOK3S_INTERRUPT_HV_RM_HARD:
vcpu->arch.trap = 0;
@@ -4153,8 +4129,9 @@ void kvmhv_set_l2_counters_status(int cpu, bool status)
else
lppaca_of(cpu).l2_counters_enable = 0;
}
+EXPORT_SYMBOL(kvmhv_set_l2_counters_status);
-int kmvhv_counters_tracepoint_regfunc(void)
+int kvmhv_counters_tracepoint_regfunc(void)
{
int cpu;
@@ -4164,7 +4141,7 @@ int kmvhv_counters_tracepoint_regfunc(void)
return 0;
}
-void kmvhv_counters_tracepoint_unregfunc(void)
+void kvmhv_counters_tracepoint_unregfunc(void)
{
int cpu;
@@ -4190,8 +4167,74 @@ static void do_trace_nested_cs_time(struct kvm_vcpu *vcpu)
*l1_to_l2_cs_ptr = l1_to_l2_ns;
*l2_to_l1_cs_ptr = l2_to_l1_ns;
*l2_runtime_agg_ptr = l2_runtime_ns;
+ vcpu->arch.l1_to_l2_cs = l1_to_l2_ns;
+ vcpu->arch.l2_to_l1_cs = l2_to_l1_ns;
+ vcpu->arch.l2_runtime_agg = l2_runtime_ns;
}
+u64 kvmhv_get_l1_to_l2_cs_time(void)
+{
+ return tb_to_ns(be64_to_cpu(get_lppaca()->l1_to_l2_cs_tb));
+}
+EXPORT_SYMBOL(kvmhv_get_l1_to_l2_cs_time);
+
+u64 kvmhv_get_l2_to_l1_cs_time(void)
+{
+ return tb_to_ns(be64_to_cpu(get_lppaca()->l2_to_l1_cs_tb));
+}
+EXPORT_SYMBOL(kvmhv_get_l2_to_l1_cs_time);
+
+u64 kvmhv_get_l2_runtime_agg(void)
+{
+ return tb_to_ns(be64_to_cpu(get_lppaca()->l2_runtime_tb));
+}
+EXPORT_SYMBOL(kvmhv_get_l2_runtime_agg);
+
+u64 kvmhv_get_l1_to_l2_cs_time_vcpu(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vcpu_arch *arch;
+
+ vcpu = local_paca->kvm_hstate.kvm_vcpu;
+ if (vcpu) {
+ arch = &vcpu->arch;
+ return arch->l1_to_l2_cs;
+ } else {
+ return 0;
+ }
+}
+EXPORT_SYMBOL(kvmhv_get_l1_to_l2_cs_time_vcpu);
+
+u64 kvmhv_get_l2_to_l1_cs_time_vcpu(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vcpu_arch *arch;
+
+ vcpu = local_paca->kvm_hstate.kvm_vcpu;
+ if (vcpu) {
+ arch = &vcpu->arch;
+ return arch->l2_to_l1_cs;
+ } else {
+ return 0;
+ }
+}
+EXPORT_SYMBOL(kvmhv_get_l2_to_l1_cs_time_vcpu);
+
+u64 kvmhv_get_l2_runtime_agg_vcpu(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_vcpu_arch *arch;
+
+ vcpu = local_paca->kvm_hstate.kvm_vcpu;
+ if (vcpu) {
+ arch = &vcpu->arch;
+ return arch->l2_runtime_agg;
+ } else {
+ return 0;
+ }
+}
+EXPORT_SYMBOL(kvmhv_get_l2_runtime_agg_vcpu);
+
#else
int kvmhv_get_l2_counters_status(void)
{
@@ -4310,6 +4353,15 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns
hvregs.hdec_expiry = time_limit;
/*
+ * hvregs has the doorbell status, so zero it here which
+ * enables us to receive doorbells when H_ENTER_NESTED is
+ * in progress for this vCPU
+ */
+
+ if (vcpu->arch.doorbell_request)
+ vcpu->arch.doorbell_request = 0;
+
+ /*
* When setting DEC, we must always deal with irq_work_raise
* via NMI vs setting DEC. The problem occurs right as we
* switch into guest mode if a NMI hits and sets pending work
@@ -4898,9 +4950,20 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
BOOK3S_INTERRUPT_EXTERNAL, 0);
else
lpcr |= LPCR_MER;
+ } else {
+ /*
+ * L1's copy of L2's LPCR (vcpu->arch.vcore->lpcr) can get its MER bit
+ * unexpectedly set - for e.g. during NMI handling when all register
+ * states are synchronized from L0 to L1. L1 needs to inform L0 about
+ * MER=1 only when there are pending external interrupts.
+ * In the above if check, MER bit is set if there are pending
+ * external interrupts. Hence, explicity mask off MER bit
+ * here as otherwise it may generate spurious interrupts in L2 KVM
+ * causing an endless loop, which results in L2 guest getting hung.
+ */
+ lpcr &= ~LPCR_MER;
}
} else if (vcpu->arch.pending_exceptions ||
- vcpu->arch.doorbell_request ||
xive_interrupt_pending(vcpu)) {
vcpu->arch.ret = RESUME_HOST;
goto out;
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 05f5220960c6..5f8c2321cfb5 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -32,7 +32,7 @@ void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
struct kvmppc_vcore *vc = vcpu->arch.vcore;
hr->pcr = vc->pcr | PCR_MASK;
- hr->dpdes = vc->dpdes;
+ hr->dpdes = vcpu->arch.doorbell_request;
hr->hfscr = vcpu->arch.hfscr;
hr->tb_offset = vc->tb_offset;
hr->dawr0 = vcpu->arch.dawr0;
@@ -105,7 +105,7 @@ static void save_hv_return_state(struct kvm_vcpu *vcpu,
{
struct kvmppc_vcore *vc = vcpu->arch.vcore;
- hr->dpdes = vc->dpdes;
+ hr->dpdes = vcpu->arch.doorbell_request;
hr->purr = vcpu->arch.purr;
hr->spurr = vcpu->arch.spurr;
hr->ic = vcpu->arch.ic;
@@ -143,7 +143,7 @@ static void restore_hv_regs(struct kvm_vcpu *vcpu, const struct hv_guest_state *
struct kvmppc_vcore *vc = vcpu->arch.vcore;
vc->pcr = hr->pcr | PCR_MASK;
- vc->dpdes = hr->dpdes;
+ vcpu->arch.doorbell_request = hr->dpdes;
vcpu->arch.hfscr = hr->hfscr;
vcpu->arch.dawr0 = hr->dawr0;
vcpu->arch.dawrx0 = hr->dawrx0;
@@ -170,7 +170,13 @@ void kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu,
{
struct kvmppc_vcore *vc = vcpu->arch.vcore;
- vc->dpdes = hr->dpdes;
+ /*
+ * This L2 vCPU might have received a doorbell while H_ENTER_NESTED was being handled.
+ * Make sure we preserve the doorbell if it was either:
+ * a) Sent after H_ENTER_NESTED was called on this vCPU (arch.doorbell_request would be 1)
+ * b) Doorbell was not handled and L2 exited for some other reason (hr->dpdes would be 1)
+ */
+ vcpu->arch.doorbell_request = vcpu->arch.doorbell_request | hr->dpdes;
vcpu->arch.hfscr = hr->hfscr;
vcpu->arch.purr = hr->purr;
vcpu->arch.spurr = hr->spurr;
@@ -445,6 +451,8 @@ long kvmhv_nested_init(void)
if (rc == H_SUCCESS) {
unsigned long capabilities = 0;
+ if (cpu_has_feature(CPU_FTR_P11_PVR))
+ capabilities |= H_GUEST_CAP_POWER11;
if (cpu_has_feature(CPU_FTR_ARCH_31))
capabilities |= H_GUEST_CAP_POWER10;
if (cpu_has_feature(CPU_FTR_ARCH_300))
@@ -1527,7 +1535,6 @@ static long int __kvmhv_nested_page_fault(struct kvm_vcpu *vcpu,
unsigned long n_gpa, gpa, gfn, perm = 0UL;
unsigned int shift, l1_shift, level;
bool writing = !!(dsisr & DSISR_ISSTORE);
- bool kvm_ro = false;
long int ret;
if (!gp->l1_gr_to_hr) {
@@ -1607,7 +1614,6 @@ static long int __kvmhv_nested_page_fault(struct kvm_vcpu *vcpu,
ea, DSISR_ISSTORE | DSISR_PROTFAULT);
return RESUME_GUEST;
}
- kvm_ro = true;
}
/* 2. Find the host pte for this L1 guest real address */
@@ -1629,7 +1635,7 @@ static long int __kvmhv_nested_page_fault(struct kvm_vcpu *vcpu,
if (!pte_present(pte) || (writing && !(pte_val(pte) & _PAGE_WRITE))) {
/* No suitable pte found -> try to insert a mapping */
ret = kvmppc_book3s_instantiate_page(vcpu, gpa, memslot,
- writing, kvm_ro, &pte, &level);
+ writing, &pte, &level);
if (ret == -EAGAIN)
return RESUME_GUEST;
else if (ret)
diff --git a/arch/powerpc/kvm/book3s_hv_nestedv2.c b/arch/powerpc/kvm/book3s_hv_nestedv2.c
index eeecea8f202b..e5c7ce1fb761 100644
--- a/arch/powerpc/kvm/book3s_hv_nestedv2.c
+++ b/arch/powerpc/kvm/book3s_hv_nestedv2.c
@@ -370,7 +370,9 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb,
* default to L1's PVR.
*/
if (!vcpu->arch.vcore->arch_compat) {
- if (cpu_has_feature(CPU_FTR_ARCH_31))
+ if (cpu_has_feature(CPU_FTR_P11_PVR))
+ arch_compat = PVR_ARCH_31_P11;
+ else if (cpu_has_feature(CPU_FTR_ARCH_31))
arch_compat = PVR_ARCH_31;
else if (cpu_has_feature(CPU_FTR_ARCH_300))
arch_compat = PVR_ARCH_300;
diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c
index 92f33115144b..3a6592a31a10 100644
--- a/arch/powerpc/kvm/book3s_hv_uvmem.c
+++ b/arch/powerpc/kvm/book3s_hv_uvmem.c
@@ -879,9 +879,8 @@ static unsigned long kvmppc_share_page(struct kvm *kvm, unsigned long gpa,
{
int ret = H_PARAMETER;
- struct page *uvmem_page;
+ struct page *page, *uvmem_page;
struct kvmppc_uvmem_page_pvt *pvt;
- unsigned long pfn;
unsigned long gfn = gpa >> page_shift;
int srcu_idx;
unsigned long uvmem_pfn;
@@ -901,8 +900,8 @@ static unsigned long kvmppc_share_page(struct kvm *kvm, unsigned long gpa,
retry:
mutex_unlock(&kvm->arch.uvmem_lock);
- pfn = gfn_to_pfn(kvm, gfn);
- if (is_error_noslot_pfn(pfn))
+ page = gfn_to_page(kvm, gfn);
+ if (!page)
goto out;
mutex_lock(&kvm->arch.uvmem_lock);
@@ -911,16 +910,16 @@ retry:
pvt = uvmem_page->zone_device_data;
pvt->skip_page_out = true;
pvt->remove_gfn = false; /* it continues to be a valid GFN */
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_unused(page);
goto retry;
}
- if (!uv_page_in(kvm->arch.lpid, pfn << page_shift, gpa, 0,
+ if (!uv_page_in(kvm->arch.lpid, page_to_pfn(page) << page_shift, gpa, 0,
page_shift)) {
kvmppc_gfn_shared(gfn, kvm);
ret = H_SUCCESS;
}
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_clean(page);
mutex_unlock(&kvm->arch.uvmem_lock);
out:
srcu_read_unlock(&kvm->srcu, srcu_idx);
@@ -1083,21 +1082,21 @@ out:
int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
{
- unsigned long pfn;
+ struct page *page;
int ret = U_SUCCESS;
- pfn = gfn_to_pfn(kvm, gfn);
- if (is_error_noslot_pfn(pfn))
+ page = gfn_to_page(kvm, gfn);
+ if (!page)
return -EFAULT;
mutex_lock(&kvm->arch.uvmem_lock);
if (kvmppc_gfn_is_uvmem_pfn(gfn, kvm, NULL))
goto out;
- ret = uv_page_in(kvm->arch.lpid, pfn << PAGE_SHIFT, gfn << PAGE_SHIFT,
- 0, PAGE_SHIFT);
+ ret = uv_page_in(kvm->arch.lpid, page_to_pfn(page) << PAGE_SHIFT,
+ gfn << PAGE_SHIFT, 0, PAGE_SHIFT);
out:
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_clean(page);
mutex_unlock(&kvm->arch.uvmem_lock);
return (ret == U_SUCCESS) ? RESUME_GUEST : -EFAULT;
}
diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c b/arch/powerpc/kvm/book3s_mmu_hpte.c
index ce79ac33e8d3..d904e13e069b 100644
--- a/arch/powerpc/kvm/book3s_mmu_hpte.c
+++ b/arch/powerpc/kvm/book3s_mmu_hpte.c
@@ -92,12 +92,6 @@ void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
spin_unlock(&vcpu3s->mmu_lock);
}
-static void free_pte_rcu(struct rcu_head *head)
-{
- struct hpte_cache *pte = container_of(head, struct hpte_cache, rcu_head);
- kmem_cache_free(hpte_cache, pte);
-}
-
static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
{
struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
@@ -126,7 +120,7 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
spin_unlock(&vcpu3s->mmu_lock);
- call_rcu(&pte->rcu_head, free_pte_rcu);
+ kfree_rcu(pte, rcu_head);
}
static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 7b8ae509328f..83bcdc80ce51 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -639,29 +639,27 @@ static void kvmppc_set_pvr_pr(struct kvm_vcpu *vcpu, u32 pvr)
*/
static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
{
- struct page *hpage;
+ struct kvm_host_map map;
u64 hpage_offset;
u32 *page;
- int i;
+ int i, r;
- hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
- if (is_error_page(hpage))
+ r = kvm_vcpu_map(vcpu, pte->raddr >> PAGE_SHIFT, &map);
+ if (r)
return;
hpage_offset = pte->raddr & ~PAGE_MASK;
hpage_offset &= ~0xFFFULL;
hpage_offset /= 4;
- get_page(hpage);
- page = kmap_atomic(hpage);
+ page = map.hva;
/* patch dcbz into reserved instruction, so we trap */
for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
if ((be32_to_cpu(page[i]) & 0xff0007ff) == INS_DCBZ)
page[i] &= cpu_to_be32(0xfffffff7);
- kunmap_atomic(page);
- put_page(hpage);
+ kvm_vcpu_unmap(vcpu, &map);
}
static bool kvmppc_visible_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c
index 6e2ebbd8aaac..d9bf1bc3ff61 100644
--- a/arch/powerpc/kvm/book3s_xive_native.c
+++ b/arch/powerpc/kvm/book3s_xive_native.c
@@ -654,7 +654,7 @@ static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive,
}
page = gfn_to_page(kvm, gfn);
- if (is_error_page(page)) {
+ if (!page) {
srcu_read_unlock(&kvm->srcu, srcu_idx);
pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr);
return -EINVAL;
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index c664fdec75b1..e5a145b578a4 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -242,7 +242,7 @@ static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
return tlbe->mas7_3 & (MAS3_SW|MAS3_UW);
}
-static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
+static inline bool kvmppc_e500_ref_setup(struct tlbe_ref *ref,
struct kvm_book3e_206_tlb_entry *gtlbe,
kvm_pfn_t pfn, unsigned int wimg)
{
@@ -252,11 +252,7 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
/* Use guest supplied MAS2_G and MAS2_E */
ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg;
- /* Mark the page accessed */
- kvm_set_pfn_accessed(pfn);
-
- if (tlbe_is_writable(gtlbe))
- kvm_set_pfn_dirty(pfn);
+ return tlbe_is_writable(gtlbe);
}
static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
@@ -326,6 +322,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
{
struct kvm_memory_slot *slot;
unsigned long pfn = 0; /* silence GCC warning */
+ struct page *page = NULL;
unsigned long hva;
int pfnmap = 0;
int tsize = BOOK3E_PAGESZ_4K;
@@ -337,6 +334,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
unsigned int wimg = 0;
pgd_t *pgdir;
unsigned long flags;
+ bool writable = false;
/* used to check for invalidations in progress */
mmu_seq = kvm->mmu_invalidate_seq;
@@ -446,7 +444,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
if (likely(!pfnmap)) {
tsize_pages = 1UL << (tsize + 10 - PAGE_SHIFT);
- pfn = gfn_to_pfn_memslot(slot, gfn);
+ pfn = __kvm_faultin_pfn(slot, gfn, FOLL_WRITE, NULL, &page);
if (is_error_noslot_pfn(pfn)) {
if (printk_ratelimit())
pr_err("%s: real page not found for gfn %lx\n",
@@ -490,7 +488,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
goto out;
}
}
- kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
+ writable = kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
ref, gvaddr, stlbe);
@@ -499,11 +497,8 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
kvmppc_mmu_flush_icache(pfn);
out:
+ kvm_release_faultin_page(kvm, page, !!ret, writable);
spin_unlock(&kvm->mmu_lock);
-
- /* Drop refcount on page, so that mmu notifiers can clear it */
- kvm_release_pfn_clean(pfn);
-
return ret;
}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index f14329989e9a..ce1d91eed231 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -612,9 +612,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = 8 | 4 | 2 | 1;
}
break;
- case KVM_CAP_PPC_RMA:
- r = 0;
- break;
case KVM_CAP_PPC_HWRNG:
r = kvmppc_hwrng_present();
break;
@@ -1933,12 +1930,11 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
#endif
#ifdef CONFIG_KVM_MPIC
case KVM_CAP_IRQ_MPIC: {
- struct fd f;
+ CLASS(fd, f)(cap->args[0]);
struct kvm_device *dev;
r = -EBADF;
- f = fdget(cap->args[0]);
- if (!fd_file(f))
+ if (fd_empty(f))
break;
r = -EPERM;
@@ -1946,18 +1942,16 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
if (dev)
r = kvmppc_mpic_connect_vcpu(dev, vcpu, cap->args[1]);
- fdput(f);
break;
}
#endif
#ifdef CONFIG_KVM_XICS
case KVM_CAP_IRQ_XICS: {
- struct fd f;
+ CLASS(fd, f)(cap->args[0]);
struct kvm_device *dev;
r = -EBADF;
- f = fdget(cap->args[0]);
- if (!fd_file(f))
+ if (fd_empty(f))
break;
r = -EPERM;
@@ -1968,34 +1962,27 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
else
r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]);
}
-
- fdput(f);
break;
}
#endif /* CONFIG_KVM_XICS */
#ifdef CONFIG_KVM_XIVE
case KVM_CAP_PPC_IRQ_XIVE: {
- struct fd f;
+ CLASS(fd, f)(cap->args[0]);
struct kvm_device *dev;
r = -EBADF;
- f = fdget(cap->args[0]);
- if (!fd_file(f))
+ if (fd_empty(f))
break;
r = -ENXIO;
- if (!xive_enabled()) {
- fdput(f);
+ if (!xive_enabled())
break;
- }
r = -EPERM;
dev = kvm_device_from_filp(fd_file(f));
if (dev)
r = kvmppc_xive_native_connect_vcpu(dev, vcpu,
cap->args[1]);
-
- fdput(f);
break;
}
#endif /* CONFIG_KVM_XIVE */
diff --git a/arch/powerpc/kvm/trace_hv.h b/arch/powerpc/kvm/trace_hv.h
index 77ebc724e6cd..35fccaa575cc 100644
--- a/arch/powerpc/kvm/trace_hv.h
+++ b/arch/powerpc/kvm/trace_hv.h
@@ -538,7 +538,7 @@ TRACE_EVENT_FN_COND(kvmppc_vcpu_stats,
TP_printk("VCPU %d: l1_to_l2_cs_time=%llu ns l2_to_l1_cs_time=%llu ns l2_runtime=%llu ns",
__entry->vcpu_id, __entry->l1_to_l2_cs,
__entry->l2_to_l1_cs, __entry->l2_runtime),
- kmvhv_counters_tracepoint_regfunc, kmvhv_counters_tracepoint_unregfunc
+ kvmhv_counters_tracepoint_regfunc, kvmhv_counters_tracepoint_unregfunc
);
#endif
#endif /* _TRACE_KVM_HV_H */
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index acdab294b340..af97fbb3c257 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -17,7 +17,7 @@
#include <asm/tlb.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/inst.h>
static int __patch_mem(void *exec_addr, unsigned long val, void *patch_addr, bool is_dword)
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index b7201ba50b2e..587c8cf1230f 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -16,7 +16,7 @@
#include <linux/sched/mm.h>
#include <linux/stop_machine.h>
#include <asm/cputable.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/interrupt.h>
#include <asm/page.h>
#include <asm/sections.h>
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index e65f3fb68d06..ac3ee19531d8 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -780,8 +780,8 @@ static nokprobe_inline int emulate_stq(struct pt_regs *regs, unsigned long ea,
#endif /* __powerpc64 */
#ifdef CONFIG_VSX
-void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
- const void *mem, bool rev)
+static nokprobe_inline void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
+ const void *mem, bool rev)
{
int size, read_size;
int i, j;
@@ -863,11 +863,9 @@ void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
break;
}
}
-EXPORT_SYMBOL_GPL(emulate_vsx_load);
-NOKPROBE_SYMBOL(emulate_vsx_load);
-void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
- void *mem, bool rev)
+static nokprobe_inline void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
+ void *mem, bool rev)
{
int size, write_size;
int i, j;
@@ -955,8 +953,6 @@ void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
break;
}
}
-EXPORT_SYMBOL_GPL(emulate_vsx_store);
-NOKPROBE_SYMBOL(emulate_vsx_store);
static nokprobe_inline int do_vsx_load(struct instruction_op *op,
unsigned long ea, struct pt_regs *regs,
diff --git a/arch/powerpc/lib/test-code-patching.c b/arch/powerpc/lib/test-code-patching.c
index 8cd3b32f805b..1440d99630b3 100644
--- a/arch/powerpc/lib/test-code-patching.c
+++ b/arch/powerpc/lib/test-code-patching.c
@@ -6,7 +6,7 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
static int __init instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
{
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 23c7805fb7b3..66b5b4fa1686 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -11,7 +11,7 @@
#include <asm/cpu_has_feature.h>
#include <asm/sstep.h>
#include <asm/ppc-opcode.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/inst.h>
#define MAX_SUBTESTS 16
diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c
index 2db167f4233f..6978344edcb4 100644
--- a/arch/powerpc/mm/book3s32/mmu.c
+++ b/arch/powerpc/mm/book3s32/mmu.c
@@ -25,7 +25,7 @@
#include <asm/mmu.h>
#include <asm/machdep.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/sections.h>
#include <mm/mmu_decl.h>
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
index e1eadd03f133..c8b4fa71d4a7 100644
--- a/arch/powerpc/mm/book3s64/hash_utils.c
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -40,6 +40,7 @@
#include <linux/random.h>
#include <linux/elf-randomize.h>
#include <linux/of_fdt.h>
+#include <linux/kfence.h>
#include <asm/interrupt.h>
#include <asm/processor.h>
@@ -57,7 +58,7 @@
#include <asm/sections.h>
#include <asm/copro.h>
#include <asm/udbg.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/fadump.h>
#include <asm/firmware.h>
#include <asm/tm.h>
@@ -66,6 +67,7 @@
#include <asm/pte-walk.h>
#include <asm/asm-prototypes.h>
#include <asm/ultravisor.h>
+#include <asm/kfence.h>
#include <mm/mmu_decl.h>
@@ -123,8 +125,6 @@ EXPORT_SYMBOL_GPL(mmu_slb_size);
#ifdef CONFIG_PPC_64K_PAGES
int mmu_ci_restrictions;
#endif
-static u8 *linear_map_hash_slots;
-static unsigned long linear_map_hash_count;
struct mmu_hash_ops mmu_hash_ops __ro_after_init;
EXPORT_SYMBOL(mmu_hash_ops);
@@ -273,6 +273,270 @@ void hash__tlbiel_all(unsigned int action)
WARN(1, "%s called on pre-POWER7 CPU\n", __func__);
}
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
+static void kernel_map_linear_page(unsigned long vaddr, unsigned long idx,
+ u8 *slots, raw_spinlock_t *lock)
+{
+ unsigned long hash;
+ unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
+ unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
+ unsigned long mode = htab_convert_pte_flags(pgprot_val(PAGE_KERNEL), HPTE_USE_KERNEL_KEY);
+ long ret;
+
+ hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
+
+ /* Don't create HPTE entries for bad address */
+ if (!vsid)
+ return;
+
+ if (slots[idx] & 0x80)
+ return;
+
+ ret = hpte_insert_repeating(hash, vpn, __pa(vaddr), mode,
+ HPTE_V_BOLTED,
+ mmu_linear_psize, mmu_kernel_ssize);
+
+ BUG_ON (ret < 0);
+ raw_spin_lock(lock);
+ BUG_ON(slots[idx] & 0x80);
+ slots[idx] = ret | 0x80;
+ raw_spin_unlock(lock);
+}
+
+static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long idx,
+ u8 *slots, raw_spinlock_t *lock)
+{
+ unsigned long hash, hslot, slot;
+ unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
+ unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
+
+ hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
+ raw_spin_lock(lock);
+ if (!(slots[idx] & 0x80)) {
+ raw_spin_unlock(lock);
+ return;
+ }
+ hslot = slots[idx] & 0x7f;
+ slots[idx] = 0;
+ raw_spin_unlock(lock);
+ if (hslot & _PTEIDX_SECONDARY)
+ hash = ~hash;
+ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+ slot += hslot & _PTEIDX_GROUP_IX;
+ mmu_hash_ops.hpte_invalidate(slot, vpn, mmu_linear_psize,
+ mmu_linear_psize,
+ mmu_kernel_ssize, 0);
+}
+#endif
+
+static inline bool hash_supports_debug_pagealloc(void)
+{
+ unsigned long max_hash_count = ppc64_rma_size / 4;
+ unsigned long linear_map_count = memblock_end_of_DRAM() >> PAGE_SHIFT;
+
+ if (!debug_pagealloc_enabled() || linear_map_count > max_hash_count)
+ return false;
+ return true;
+}
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+static u8 *linear_map_hash_slots;
+static unsigned long linear_map_hash_count;
+static DEFINE_RAW_SPINLOCK(linear_map_hash_lock);
+static void hash_debug_pagealloc_alloc_slots(void)
+{
+ if (!hash_supports_debug_pagealloc())
+ return;
+
+ linear_map_hash_count = memblock_end_of_DRAM() >> PAGE_SHIFT;
+ linear_map_hash_slots = memblock_alloc_try_nid(
+ linear_map_hash_count, 1, MEMBLOCK_LOW_LIMIT,
+ ppc64_rma_size, NUMA_NO_NODE);
+ if (!linear_map_hash_slots)
+ panic("%s: Failed to allocate %lu bytes max_addr=%pa\n",
+ __func__, linear_map_hash_count, &ppc64_rma_size);
+}
+
+static inline void hash_debug_pagealloc_add_slot(phys_addr_t paddr,
+ int slot)
+{
+ if (!debug_pagealloc_enabled() || !linear_map_hash_count)
+ return;
+ if ((paddr >> PAGE_SHIFT) < linear_map_hash_count)
+ linear_map_hash_slots[paddr >> PAGE_SHIFT] = slot | 0x80;
+}
+
+static int hash_debug_pagealloc_map_pages(struct page *page, int numpages,
+ int enable)
+{
+ unsigned long flags, vaddr, lmi;
+ int i;
+
+ if (!debug_pagealloc_enabled() || !linear_map_hash_count)
+ return 0;
+
+ local_irq_save(flags);
+ for (i = 0; i < numpages; i++, page++) {
+ vaddr = (unsigned long)page_address(page);
+ lmi = __pa(vaddr) >> PAGE_SHIFT;
+ if (lmi >= linear_map_hash_count)
+ continue;
+ if (enable)
+ kernel_map_linear_page(vaddr, lmi,
+ linear_map_hash_slots, &linear_map_hash_lock);
+ else
+ kernel_unmap_linear_page(vaddr, lmi,
+ linear_map_hash_slots, &linear_map_hash_lock);
+ }
+ local_irq_restore(flags);
+ return 0;
+}
+
+#else /* CONFIG_DEBUG_PAGEALLOC */
+static inline void hash_debug_pagealloc_alloc_slots(void) {}
+static inline void hash_debug_pagealloc_add_slot(phys_addr_t paddr, int slot) {}
+static int __maybe_unused
+hash_debug_pagealloc_map_pages(struct page *page, int numpages, int enable)
+{
+ return 0;
+}
+#endif /* CONFIG_DEBUG_PAGEALLOC */
+
+#ifdef CONFIG_KFENCE
+static u8 *linear_map_kf_hash_slots;
+static unsigned long linear_map_kf_hash_count;
+static DEFINE_RAW_SPINLOCK(linear_map_kf_hash_lock);
+
+static phys_addr_t kfence_pool;
+
+static inline void hash_kfence_alloc_pool(void)
+{
+ if (!kfence_early_init_enabled())
+ goto err;
+
+ /* allocate linear map for kfence within RMA region */
+ linear_map_kf_hash_count = KFENCE_POOL_SIZE >> PAGE_SHIFT;
+ linear_map_kf_hash_slots = memblock_alloc_try_nid(
+ linear_map_kf_hash_count, 1,
+ MEMBLOCK_LOW_LIMIT, ppc64_rma_size,
+ NUMA_NO_NODE);
+ if (!linear_map_kf_hash_slots) {
+ pr_err("%s: memblock for linear map (%lu) failed\n", __func__,
+ linear_map_kf_hash_count);
+ goto err;
+ }
+
+ /* allocate kfence pool early */
+ kfence_pool = memblock_phys_alloc_range(KFENCE_POOL_SIZE, PAGE_SIZE,
+ MEMBLOCK_LOW_LIMIT, MEMBLOCK_ALLOC_ANYWHERE);
+ if (!kfence_pool) {
+ pr_err("%s: memblock for kfence pool (%lu) failed\n", __func__,
+ KFENCE_POOL_SIZE);
+ memblock_free(linear_map_kf_hash_slots,
+ linear_map_kf_hash_count);
+ linear_map_kf_hash_count = 0;
+ goto err;
+ }
+ memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE);
+
+ return;
+err:
+ pr_info("Disabling kfence\n");
+ disable_kfence();
+}
+
+static inline void hash_kfence_map_pool(void)
+{
+ unsigned long kfence_pool_start, kfence_pool_end;
+ unsigned long prot = pgprot_val(PAGE_KERNEL);
+
+ if (!kfence_pool)
+ return;
+
+ kfence_pool_start = (unsigned long) __va(kfence_pool);
+ kfence_pool_end = kfence_pool_start + KFENCE_POOL_SIZE;
+ __kfence_pool = (char *) kfence_pool_start;
+ BUG_ON(htab_bolt_mapping(kfence_pool_start, kfence_pool_end,
+ kfence_pool, prot, mmu_linear_psize,
+ mmu_kernel_ssize));
+ memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE);
+}
+
+static inline void hash_kfence_add_slot(phys_addr_t paddr, int slot)
+{
+ unsigned long vaddr = (unsigned long) __va(paddr);
+ unsigned long lmi = (vaddr - (unsigned long)__kfence_pool)
+ >> PAGE_SHIFT;
+
+ if (!kfence_pool)
+ return;
+ BUG_ON(!is_kfence_address((void *)vaddr));
+ BUG_ON(lmi >= linear_map_kf_hash_count);
+ linear_map_kf_hash_slots[lmi] = slot | 0x80;
+}
+
+static int hash_kfence_map_pages(struct page *page, int numpages, int enable)
+{
+ unsigned long flags, vaddr, lmi;
+ int i;
+
+ WARN_ON_ONCE(!linear_map_kf_hash_count);
+ local_irq_save(flags);
+ for (i = 0; i < numpages; i++, page++) {
+ vaddr = (unsigned long)page_address(page);
+ lmi = (vaddr - (unsigned long)__kfence_pool) >> PAGE_SHIFT;
+
+ /* Ideally this should never happen */
+ if (lmi >= linear_map_kf_hash_count) {
+ WARN_ON_ONCE(1);
+ continue;
+ }
+
+ if (enable)
+ kernel_map_linear_page(vaddr, lmi,
+ linear_map_kf_hash_slots,
+ &linear_map_kf_hash_lock);
+ else
+ kernel_unmap_linear_page(vaddr, lmi,
+ linear_map_kf_hash_slots,
+ &linear_map_kf_hash_lock);
+ }
+ local_irq_restore(flags);
+ return 0;
+}
+#else
+static inline void hash_kfence_alloc_pool(void) {}
+static inline void hash_kfence_map_pool(void) {}
+static inline void hash_kfence_add_slot(phys_addr_t paddr, int slot) {}
+static int __maybe_unused
+hash_kfence_map_pages(struct page *page, int numpages, int enable)
+{
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
+int hash__kernel_map_pages(struct page *page, int numpages, int enable)
+{
+ void *vaddr = page_address(page);
+
+ if (is_kfence_address(vaddr))
+ return hash_kfence_map_pages(page, numpages, enable);
+ else
+ return hash_debug_pagealloc_map_pages(page, numpages, enable);
+}
+
+static void hash_linear_map_add_slot(phys_addr_t paddr, int slot)
+{
+ if (is_kfence_address(__va(paddr)))
+ hash_kfence_add_slot(paddr, slot);
+ else
+ hash_debug_pagealloc_add_slot(paddr, slot);
+}
+#else
+static void hash_linear_map_add_slot(phys_addr_t paddr, int slot) {}
+#endif
+
/*
* 'R' and 'C' update notes:
* - Under pHyp or KVM, the updatepp path will not set C, thus it *will*
@@ -431,9 +695,8 @@ repeat:
break;
cond_resched();
- if (debug_pagealloc_enabled_or_kfence() &&
- (paddr >> PAGE_SHIFT) < linear_map_hash_count)
- linear_map_hash_slots[paddr >> PAGE_SHIFT] = ret | 0x80;
+ /* add slot info in debug_pagealloc / kfence linear map */
+ hash_linear_map_add_slot(paddr, ret);
}
return ret < 0 ? ret : 0;
}
@@ -814,7 +1077,7 @@ static void __init htab_init_page_sizes(void)
bool aligned = true;
init_hpte_page_sizes();
- if (!debug_pagealloc_enabled_or_kfence()) {
+ if (!hash_supports_debug_pagealloc() && !kfence_early_init_enabled()) {
/*
* Pick a size for the linear mapping. Currently, we only
* support 16M, 1M and 4K which is the default
@@ -1134,16 +1397,8 @@ static void __init htab_initialize(void)
prot = pgprot_val(PAGE_KERNEL);
- if (debug_pagealloc_enabled_or_kfence()) {
- linear_map_hash_count = memblock_end_of_DRAM() >> PAGE_SHIFT;
- linear_map_hash_slots = memblock_alloc_try_nid(
- linear_map_hash_count, 1, MEMBLOCK_LOW_LIMIT,
- ppc64_rma_size, NUMA_NO_NODE);
- if (!linear_map_hash_slots)
- panic("%s: Failed to allocate %lu bytes max_addr=%pa\n",
- __func__, linear_map_hash_count, &ppc64_rma_size);
- }
-
+ hash_debug_pagealloc_alloc_slots();
+ hash_kfence_alloc_pool();
/* create bolted the linear mapping in the hash table */
for_each_mem_range(i, &base, &end) {
size = end - base;
@@ -1160,6 +1415,7 @@ static void __init htab_initialize(void)
BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
prot, mmu_linear_psize, mmu_kernel_ssize));
}
+ hash_kfence_map_pool();
memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
/*
@@ -2120,82 +2376,6 @@ void hpt_do_stress(unsigned long ea, unsigned long hpte_group)
}
}
-#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
-static DEFINE_RAW_SPINLOCK(linear_map_hash_lock);
-
-static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
-{
- unsigned long hash;
- unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
- unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
- unsigned long mode = htab_convert_pte_flags(pgprot_val(PAGE_KERNEL), HPTE_USE_KERNEL_KEY);
- long ret;
-
- hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
-
- /* Don't create HPTE entries for bad address */
- if (!vsid)
- return;
-
- if (linear_map_hash_slots[lmi] & 0x80)
- return;
-
- ret = hpte_insert_repeating(hash, vpn, __pa(vaddr), mode,
- HPTE_V_BOLTED,
- mmu_linear_psize, mmu_kernel_ssize);
-
- BUG_ON (ret < 0);
- raw_spin_lock(&linear_map_hash_lock);
- BUG_ON(linear_map_hash_slots[lmi] & 0x80);
- linear_map_hash_slots[lmi] = ret | 0x80;
- raw_spin_unlock(&linear_map_hash_lock);
-}
-
-static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
-{
- unsigned long hash, hidx, slot;
- unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
- unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
-
- hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
- raw_spin_lock(&linear_map_hash_lock);
- if (!(linear_map_hash_slots[lmi] & 0x80)) {
- raw_spin_unlock(&linear_map_hash_lock);
- return;
- }
- hidx = linear_map_hash_slots[lmi] & 0x7f;
- linear_map_hash_slots[lmi] = 0;
- raw_spin_unlock(&linear_map_hash_lock);
- if (hidx & _PTEIDX_SECONDARY)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += hidx & _PTEIDX_GROUP_IX;
- mmu_hash_ops.hpte_invalidate(slot, vpn, mmu_linear_psize,
- mmu_linear_psize,
- mmu_kernel_ssize, 0);
-}
-
-int hash__kernel_map_pages(struct page *page, int numpages, int enable)
-{
- unsigned long flags, vaddr, lmi;
- int i;
-
- local_irq_save(flags);
- for (i = 0; i < numpages; i++, page++) {
- vaddr = (unsigned long)page_address(page);
- lmi = __pa(vaddr) >> PAGE_SHIFT;
- if (lmi >= linear_map_hash_count)
- continue;
- if (enable)
- kernel_map_linear_page(vaddr, lmi);
- else
- kernel_unmap_linear_page(vaddr, lmi);
- }
- local_irq_restore(flags);
- return 0;
-}
-#endif /* CONFIG_DEBUG_PAGEALLOC || CONFIG_KFENCE */
-
void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
{
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
index 5a4a75369043..374542528080 100644
--- a/arch/powerpc/mm/book3s64/pgtable.c
+++ b/arch/powerpc/mm/book3s64/pgtable.c
@@ -37,6 +37,19 @@ EXPORT_SYMBOL(__pmd_frag_nr);
unsigned long __pmd_frag_size_shift;
EXPORT_SYMBOL(__pmd_frag_size_shift);
+#ifdef CONFIG_KFENCE
+extern bool kfence_early_init;
+static int __init parse_kfence_early_init(char *arg)
+{
+ int val;
+
+ if (get_option(&arg, &val))
+ kfence_early_init = !!val;
+ return 0;
+}
+early_param("kfence.sample_interval", parse_kfence_early_init);
+#endif
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
/*
* This is called when relaxing access to a hugepage. It's also called in the page
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
index b0d927009af8..311e2112d782 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -363,18 +363,6 @@ static int __meminit create_physical_mapping(unsigned long start,
}
#ifdef CONFIG_KFENCE
-static bool __ro_after_init kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL;
-
-static int __init parse_kfence_early_init(char *arg)
-{
- int val;
-
- if (get_option(&arg, &val))
- kfence_early_init = !!val;
- return 0;
-}
-early_param("kfence.sample_interval", parse_kfence_early_init);
-
static inline phys_addr_t alloc_kfence_pool(void)
{
phys_addr_t kfence_pool;
diff --git a/arch/powerpc/mm/book3s64/slb.c b/arch/powerpc/mm/book3s64/slb.c
index f2708c8629a5..6b783552403c 100644
--- a/arch/powerpc/mm/book3s64/slb.c
+++ b/arch/powerpc/mm/book3s64/slb.c
@@ -24,7 +24,7 @@
#include <linux/pgtable.h>
#include <asm/udbg.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include "internal.h"
diff --git a/arch/powerpc/mm/book3s64/slice.c b/arch/powerpc/mm/book3s64/slice.c
index 87307d0fc3b8..bc9a39821d1c 100644
--- a/arch/powerpc/mm/book3s64/slice.c
+++ b/arch/powerpc/mm/book3s64/slice.c
@@ -633,6 +633,20 @@ return_addr:
}
EXPORT_SYMBOL_GPL(slice_get_unmapped_area);
+#ifdef CONFIG_HUGETLB_PAGE
+static int file_to_psize(struct file *file)
+{
+ struct hstate *hstate = hstate_file(file);
+
+ return shift_to_mmu_psize(huge_page_shift(hstate));
+}
+#else
+static int file_to_psize(struct file *file)
+{
+ return 0;
+}
+#endif
+
unsigned long arch_get_unmapped_area(struct file *filp,
unsigned long addr,
unsigned long len,
@@ -640,11 +654,17 @@ unsigned long arch_get_unmapped_area(struct file *filp,
unsigned long flags,
vm_flags_t vm_flags)
{
+ unsigned int psize;
+
if (radix_enabled())
return generic_get_unmapped_area(filp, addr, len, pgoff, flags, vm_flags);
- return slice_get_unmapped_area(addr, len, flags,
- mm_ctx_user_psize(&current->mm->context), 0);
+ if (filp && is_file_hugepages(filp))
+ psize = file_to_psize(filp);
+ else
+ psize = mm_ctx_user_psize(&current->mm->context);
+
+ return slice_get_unmapped_area(addr, len, flags, psize, 0);
}
unsigned long arch_get_unmapped_area_topdown(struct file *filp,
@@ -654,11 +674,17 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
const unsigned long flags,
vm_flags_t vm_flags)
{
+ unsigned int psize;
+
if (radix_enabled())
return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags, vm_flags);
- return slice_get_unmapped_area(addr0, len, flags,
- mm_ctx_user_psize(&current->mm->context), 1);
+ if (filp && is_file_hugepages(filp))
+ psize = file_to_psize(filp);
+ else
+ psize = mm_ctx_user_psize(&current->mm->context);
+
+ return slice_get_unmapped_area(addr0, len, flags, psize, 1);
}
unsigned int notrace get_slice_psize(struct mm_struct *mm, unsigned long addr)
@@ -788,20 +814,4 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
return 1UL << mmu_psize_to_shift(get_slice_psize(vma->vm_mm, vma->vm_start));
}
-
-static int file_to_psize(struct file *file)
-{
- struct hstate *hstate = hstate_file(file);
- return shift_to_mmu_psize(huge_page_shift(hstate));
-}
-
-unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags)
-{
- if (radix_enabled())
- return generic_hugetlb_get_unmapped_area(file, addr, len, pgoff, flags);
-
- return slice_get_unmapped_area(addr, len, flags, file_to_psize(file), 1);
-}
#endif
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 81c77ddce2e3..c156fe0d53c3 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -439,10 +439,16 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
/*
* The kernel should never take an execute fault nor should it
* take a page fault to a kernel address or a page fault to a user
- * address outside of dedicated places
+ * address outside of dedicated places.
+ *
+ * Rather than kfence directly reporting false negatives, search whether
+ * the NIP belongs to the fixup table for cases where fault could come
+ * from functions like copy_from_kernel_nofault().
*/
if (unlikely(!is_user && bad_kernel_fault(regs, error_code, address, is_write))) {
- if (kfence_handle_page_fault(address, is_write, regs))
+ if (is_kfence_address((void *)address) &&
+ !search_exception_tables(instruction_pointer(regs)) &&
+ kfence_handle_page_fault(address, is_write, regs))
return 0;
return SIGSEGV;
diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c
index 2978fcbe307e..745097554bea 100644
--- a/arch/powerpc/mm/init-common.c
+++ b/arch/powerpc/mm/init-common.c
@@ -33,6 +33,7 @@ bool disable_kuep = !IS_ENABLED(CONFIG_PPC_KUEP);
bool disable_kuap = !IS_ENABLED(CONFIG_PPC_KUAP);
#ifdef CONFIG_KFENCE
bool __ro_after_init kfence_disabled;
+bool __ro_after_init kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL;
#endif
static int __init parse_nosmep(char *p)
diff --git a/arch/powerpc/mm/kasan/init_32.c b/arch/powerpc/mm/kasan/init_32.c
index aa9aa11927b2..03666d790a53 100644
--- a/arch/powerpc/mm/kasan/init_32.c
+++ b/arch/powerpc/mm/kasan/init_32.c
@@ -7,7 +7,7 @@
#include <linux/memblock.h>
#include <linux/sched/task.h>
#include <asm/pgalloc.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <mm/mmu_decl.h>
static pgprot_t __init kasan_prot_ro(void)
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 1221c561b43a..c7708c8fad29 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -26,7 +26,7 @@
#include <asm/svm.h>
#include <asm/mmzone.h>
#include <asm/ftrace.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/setup.h>
#include <asm/fixmap.h>
diff --git a/arch/powerpc/mm/nohash/44x.c b/arch/powerpc/mm/nohash/44x.c
index 1beae802bb1c..6d10c6d8be71 100644
--- a/arch/powerpc/mm/nohash/44x.c
+++ b/arch/powerpc/mm/nohash/44x.c
@@ -24,7 +24,7 @@
#include <asm/mmu.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/smp.h>
#include <mm/mmu_decl.h>
diff --git a/arch/powerpc/mm/nohash/book3e_pgtable.c b/arch/powerpc/mm/nohash/book3e_pgtable.c
index ad2a7c26f2a0..062e8785c1bb 100644
--- a/arch/powerpc/mm/nohash/book3e_pgtable.c
+++ b/arch/powerpc/mm/nohash/book3e_pgtable.c
@@ -10,7 +10,7 @@
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#include <asm/dma.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <mm/mmu_decl.h>
diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
index b653a7be4cb1..0a650742f3a0 100644
--- a/arch/powerpc/mm/nohash/tlb.c
+++ b/arch/powerpc/mm/nohash/tlb.c
@@ -37,7 +37,7 @@
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/cputhreads.h>
#include <asm/hugetlb.h>
#include <asm/paca.h>
diff --git a/arch/powerpc/mm/nohash/tlb_64e.c b/arch/powerpc/mm/nohash/tlb_64e.c
index d26656b07b72..4f925adf2695 100644
--- a/arch/powerpc/mm/nohash/tlb_64e.c
+++ b/arch/powerpc/mm/nohash/tlb_64e.c
@@ -24,7 +24,7 @@
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/cputhreads.h>
#include <mm/mmu_decl.h>
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 7316396e452d..61df5aed7989 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -398,7 +398,7 @@ void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
*/
if (pmd_none(*pmd))
return;
- pte = pte_offset_map_nolock(mm, pmd, addr, &ptl);
+ pte = pte_offset_map_ro_nolock(mm, pmd, addr, &ptl);
BUG_ON(!pte);
assert_spin_locked(ptl);
pte_unmap(pte);
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index cdea5dccaefe..6beacaec63d3 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -12,6 +12,7 @@
#include <asm/types.h>
#include <asm/ppc-opcode.h>
+#include <linux/build_bug.h>
#ifdef CONFIG_PPC64_ELF_ABI_V1
#define FUNCTION_DESCR_SIZE 24
@@ -21,6 +22,9 @@
#define CTX_NIA(ctx) ((unsigned long)ctx->idx * 4)
+#define SZL sizeof(unsigned long)
+#define BPF_INSN_SAFETY 64
+
#define PLANT_INSTR(d, idx, instr) \
do { if (d) { (d)[idx] = instr; } idx++; } while (0)
#define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr)
@@ -81,6 +85,18 @@
EMIT(PPC_RAW_ORI(d, d, (uintptr_t)(i) & \
0xffff)); \
} } while (0)
+#define PPC_LI_ADDR PPC_LI64
+
+#ifndef CONFIG_PPC_KERNEL_PCREL
+#define PPC64_LOAD_PACA() \
+ EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)))
+#else
+#define PPC64_LOAD_PACA() do {} while (0)
+#endif
+#else
+#define PPC_LI64(d, i) BUILD_BUG()
+#define PPC_LI_ADDR PPC_LI32
+#define PPC64_LOAD_PACA() BUILD_BUG()
#endif
/*
@@ -165,6 +181,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
u32 *addrs, int pass, bool extra_pass);
void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
+void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx);
void bpf_jit_realloc_regs(struct codegen_context *ctx);
int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr);
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 2a36cc2e7e9e..2991bb171a9b 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -18,15 +18,85 @@
#include <linux/bpf.h>
#include <asm/kprobes.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include "bpf_jit.h"
+/* These offsets are from bpf prog end and stay the same across progs */
+static int bpf_jit_ool_stub, bpf_jit_long_branch_stub;
+
static void bpf_jit_fill_ill_insns(void *area, unsigned int size)
{
memset32(area, BREAKPOINT_INSTRUCTION, size / 4);
}
+void dummy_tramp(void);
+
+asm (
+" .pushsection .text, \"ax\", @progbits ;"
+" .global dummy_tramp ;"
+" .type dummy_tramp, @function ;"
+"dummy_tramp: ;"
+#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
+" blr ;"
+#else
+/* LR is always in r11, so we don't need a 'mflr r11' here */
+" mtctr 11 ;"
+" mtlr 0 ;"
+" bctr ;"
+#endif
+" .size dummy_tramp, .-dummy_tramp ;"
+" .popsection ;"
+);
+
+void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx)
+{
+ int ool_stub_idx, long_branch_stub_idx;
+
+ /*
+ * Out-of-line stub:
+ * mflr r0
+ * [b|bl] tramp
+ * mtlr r0 // only with CONFIG_PPC_FTRACE_OUT_OF_LINE
+ * b bpf_func + 4
+ */
+ ool_stub_idx = ctx->idx;
+ EMIT(PPC_RAW_MFLR(_R0));
+ EMIT(PPC_RAW_NOP());
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ EMIT(PPC_RAW_MTLR(_R0));
+ WARN_ON_ONCE(!is_offset_in_branch_range(4 - (long)ctx->idx * 4));
+ EMIT(PPC_RAW_BRANCH(4 - (long)ctx->idx * 4));
+
+ /*
+ * Long branch stub:
+ * .long <dummy_tramp_addr>
+ * mflr r11
+ * bcl 20,31,$+4
+ * mflr r12
+ * ld r12, -8-SZL(r12)
+ * mtctr r12
+ * mtlr r11 // needed to retain ftrace ABI
+ * bctr
+ */
+ if (image)
+ *((unsigned long *)&image[ctx->idx]) = (unsigned long)dummy_tramp;
+ ctx->idx += SZL / 4;
+ long_branch_stub_idx = ctx->idx;
+ EMIT(PPC_RAW_MFLR(_R11));
+ EMIT(PPC_RAW_BCL4());
+ EMIT(PPC_RAW_MFLR(_R12));
+ EMIT(PPC_RAW_LL(_R12, _R12, -8-SZL));
+ EMIT(PPC_RAW_MTCTR(_R12));
+ EMIT(PPC_RAW_MTLR(_R11));
+ EMIT(PPC_RAW_BCTR());
+
+ if (!bpf_jit_ool_stub) {
+ bpf_jit_ool_stub = (ctx->idx - ool_stub_idx) * 4;
+ bpf_jit_long_branch_stub = (ctx->idx - long_branch_stub_idx) * 4;
+ }
+}
+
int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr)
{
if (!exit_addr || is_offset_in_branch_range(exit_addr - (ctx->idx * 4))) {
@@ -222,7 +292,7 @@ skip_init_ctx:
fp->bpf_func = (void *)fimage;
fp->jited = 1;
- fp->jited_len = proglen + FUNCTION_DESCR_SIZE;
+ fp->jited_len = cgctx.idx * 4 + FUNCTION_DESCR_SIZE;
if (!fp->is_func || extra_pass) {
if (bpf_jit_binary_pack_finalize(fhdr, hdr)) {
@@ -369,3 +439,778 @@ bool bpf_jit_supports_far_kfunc_call(void)
{
return IS_ENABLED(CONFIG_PPC64);
}
+
+void *arch_alloc_bpf_trampoline(unsigned int size)
+{
+ return bpf_prog_pack_alloc(size, bpf_jit_fill_ill_insns);
+}
+
+void arch_free_bpf_trampoline(void *image, unsigned int size)
+{
+ bpf_prog_pack_free(image, size);
+}
+
+int arch_protect_bpf_trampoline(void *image, unsigned int size)
+{
+ return 0;
+}
+
+static int invoke_bpf_prog(u32 *image, u32 *ro_image, struct codegen_context *ctx,
+ struct bpf_tramp_link *l, int regs_off, int retval_off,
+ int run_ctx_off, bool save_ret)
+{
+ struct bpf_prog *p = l->link.prog;
+ ppc_inst_t branch_insn;
+ u32 jmp_idx;
+ int ret = 0;
+
+ /* Save cookie */
+ if (IS_ENABLED(CONFIG_PPC64)) {
+ PPC_LI64(_R3, l->cookie);
+ EMIT(PPC_RAW_STD(_R3, _R1, run_ctx_off + offsetof(struct bpf_tramp_run_ctx,
+ bpf_cookie)));
+ } else {
+ PPC_LI32(_R3, l->cookie >> 32);
+ PPC_LI32(_R4, l->cookie);
+ EMIT(PPC_RAW_STW(_R3, _R1,
+ run_ctx_off + offsetof(struct bpf_tramp_run_ctx, bpf_cookie)));
+ EMIT(PPC_RAW_STW(_R4, _R1,
+ run_ctx_off + offsetof(struct bpf_tramp_run_ctx, bpf_cookie) + 4));
+ }
+
+ /* __bpf_prog_enter(p, &bpf_tramp_run_ctx) */
+ PPC_LI_ADDR(_R3, p);
+ EMIT(PPC_RAW_MR(_R25, _R3));
+ EMIT(PPC_RAW_ADDI(_R4, _R1, run_ctx_off));
+ ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
+ (unsigned long)bpf_trampoline_enter(p));
+ if (ret)
+ return ret;
+
+ /* Remember prog start time returned by __bpf_prog_enter */
+ EMIT(PPC_RAW_MR(_R26, _R3));
+
+ /*
+ * if (__bpf_prog_enter(p) == 0)
+ * goto skip_exec_of_prog;
+ *
+ * Emit a nop to be later patched with conditional branch, once offset is known
+ */
+ EMIT(PPC_RAW_CMPLI(_R3, 0));
+ jmp_idx = ctx->idx;
+ EMIT(PPC_RAW_NOP());
+
+ /* p->bpf_func(ctx) */
+ EMIT(PPC_RAW_ADDI(_R3, _R1, regs_off));
+ if (!p->jited)
+ PPC_LI_ADDR(_R4, (unsigned long)p->insnsi);
+ if (!create_branch(&branch_insn, (u32 *)&ro_image[ctx->idx], (unsigned long)p->bpf_func,
+ BRANCH_SET_LINK)) {
+ if (image)
+ image[ctx->idx] = ppc_inst_val(branch_insn);
+ ctx->idx++;
+ } else {
+ EMIT(PPC_RAW_LL(_R12, _R25, offsetof(struct bpf_prog, bpf_func)));
+ EMIT(PPC_RAW_MTCTR(_R12));
+ EMIT(PPC_RAW_BCTRL());
+ }
+
+ if (save_ret)
+ EMIT(PPC_RAW_STL(_R3, _R1, retval_off));
+
+ /* Fix up branch */
+ if (image) {
+ if (create_cond_branch(&branch_insn, &image[jmp_idx],
+ (unsigned long)&image[ctx->idx], COND_EQ << 16))
+ return -EINVAL;
+ image[jmp_idx] = ppc_inst_val(branch_insn);
+ }
+
+ /* __bpf_prog_exit(p, start_time, &bpf_tramp_run_ctx) */
+ EMIT(PPC_RAW_MR(_R3, _R25));
+ EMIT(PPC_RAW_MR(_R4, _R26));
+ EMIT(PPC_RAW_ADDI(_R5, _R1, run_ctx_off));
+ ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
+ (unsigned long)bpf_trampoline_exit(p));
+
+ return ret;
+}
+
+static int invoke_bpf_mod_ret(u32 *image, u32 *ro_image, struct codegen_context *ctx,
+ struct bpf_tramp_links *tl, int regs_off, int retval_off,
+ int run_ctx_off, u32 *branches)
+{
+ int i;
+
+ /*
+ * The first fmod_ret program will receive a garbage return value.
+ * Set this to 0 to avoid confusing the program.
+ */
+ EMIT(PPC_RAW_LI(_R3, 0));
+ EMIT(PPC_RAW_STL(_R3, _R1, retval_off));
+ for (i = 0; i < tl->nr_links; i++) {
+ if (invoke_bpf_prog(image, ro_image, ctx, tl->links[i], regs_off, retval_off,
+ run_ctx_off, true))
+ return -EINVAL;
+
+ /*
+ * mod_ret prog stored return value after prog ctx. Emit:
+ * if (*(u64 *)(ret_val) != 0)
+ * goto do_fexit;
+ */
+ EMIT(PPC_RAW_LL(_R3, _R1, retval_off));
+ EMIT(PPC_RAW_CMPLI(_R3, 0));
+
+ /*
+ * Save the location of the branch and generate a nop, which is
+ * replaced with a conditional jump once do_fexit (i.e. the
+ * start of the fexit invocation) is finalized.
+ */
+ branches[i] = ctx->idx;
+ EMIT(PPC_RAW_NOP());
+ }
+
+ return 0;
+}
+
+static void bpf_trampoline_setup_tail_call_cnt(u32 *image, struct codegen_context *ctx,
+ int func_frame_offset, int r4_off)
+{
+ if (IS_ENABLED(CONFIG_PPC64)) {
+ /* See bpf_jit_stack_tailcallcnt() */
+ int tailcallcnt_offset = 6 * 8;
+
+ EMIT(PPC_RAW_LL(_R3, _R1, func_frame_offset - tailcallcnt_offset));
+ EMIT(PPC_RAW_STL(_R3, _R1, -tailcallcnt_offset));
+ } else {
+ /* See bpf_jit_stack_offsetof() and BPF_PPC_TC */
+ EMIT(PPC_RAW_LL(_R4, _R1, r4_off));
+ }
+}
+
+static void bpf_trampoline_restore_tail_call_cnt(u32 *image, struct codegen_context *ctx,
+ int func_frame_offset, int r4_off)
+{
+ if (IS_ENABLED(CONFIG_PPC64)) {
+ /* See bpf_jit_stack_tailcallcnt() */
+ int tailcallcnt_offset = 6 * 8;
+
+ EMIT(PPC_RAW_LL(_R3, _R1, -tailcallcnt_offset));
+ EMIT(PPC_RAW_STL(_R3, _R1, func_frame_offset - tailcallcnt_offset));
+ } else {
+ /* See bpf_jit_stack_offsetof() and BPF_PPC_TC */
+ EMIT(PPC_RAW_STL(_R4, _R1, r4_off));
+ }
+}
+
+static void bpf_trampoline_save_args(u32 *image, struct codegen_context *ctx, int func_frame_offset,
+ int nr_regs, int regs_off)
+{
+ int param_save_area_offset;
+
+ param_save_area_offset = func_frame_offset; /* the two frames we alloted */
+ param_save_area_offset += STACK_FRAME_MIN_SIZE; /* param save area is past frame header */
+
+ for (int i = 0; i < nr_regs; i++) {
+ if (i < 8) {
+ EMIT(PPC_RAW_STL(_R3 + i, _R1, regs_off + i * SZL));
+ } else {
+ EMIT(PPC_RAW_LL(_R3, _R1, param_save_area_offset + i * SZL));
+ EMIT(PPC_RAW_STL(_R3, _R1, regs_off + i * SZL));
+ }
+ }
+}
+
+/* Used when restoring just the register parameters when returning back */
+static void bpf_trampoline_restore_args_regs(u32 *image, struct codegen_context *ctx,
+ int nr_regs, int regs_off)
+{
+ for (int i = 0; i < nr_regs && i < 8; i++)
+ EMIT(PPC_RAW_LL(_R3 + i, _R1, regs_off + i * SZL));
+}
+
+/* Used when we call into the traced function. Replicate parameter save area */
+static void bpf_trampoline_restore_args_stack(u32 *image, struct codegen_context *ctx,
+ int func_frame_offset, int nr_regs, int regs_off)
+{
+ int param_save_area_offset;
+
+ param_save_area_offset = func_frame_offset; /* the two frames we alloted */
+ param_save_area_offset += STACK_FRAME_MIN_SIZE; /* param save area is past frame header */
+
+ for (int i = 8; i < nr_regs; i++) {
+ EMIT(PPC_RAW_LL(_R3, _R1, param_save_area_offset + i * SZL));
+ EMIT(PPC_RAW_STL(_R3, _R1, STACK_FRAME_MIN_SIZE + i * SZL));
+ }
+ bpf_trampoline_restore_args_regs(image, ctx, nr_regs, regs_off);
+}
+
+static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_image,
+ void *rw_image_end, void *ro_image,
+ const struct btf_func_model *m, u32 flags,
+ struct bpf_tramp_links *tlinks,
+ void *func_addr)
+{
+ int regs_off, nregs_off, ip_off, run_ctx_off, retval_off, nvr_off, alt_lr_off, r4_off = 0;
+ int i, ret, nr_regs, bpf_frame_size = 0, bpf_dummy_frame_size = 0, func_frame_offset;
+ struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
+ struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
+ struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
+ struct codegen_context codegen_ctx, *ctx;
+ u32 *image = (u32 *)rw_image;
+ ppc_inst_t branch_insn;
+ u32 *branches = NULL;
+ bool save_ret;
+
+ if (IS_ENABLED(CONFIG_PPC32))
+ return -EOPNOTSUPP;
+
+ nr_regs = m->nr_args;
+ /* Extra registers for struct arguments */
+ for (i = 0; i < m->nr_args; i++)
+ if (m->arg_size[i] > SZL)
+ nr_regs += round_up(m->arg_size[i], SZL) / SZL - 1;
+
+ if (nr_regs > MAX_BPF_FUNC_ARGS)
+ return -EOPNOTSUPP;
+
+ ctx = &codegen_ctx;
+ memset(ctx, 0, sizeof(*ctx));
+
+ /*
+ * Generated stack layout:
+ *
+ * func prev back chain [ back chain ]
+ * [ ]
+ * bpf prog redzone/tailcallcnt [ ... ] 64 bytes (64-bit powerpc)
+ * [ ] --
+ * LR save area [ r0 save (64-bit) ] | header
+ * [ r0 save (32-bit) ] |
+ * dummy frame for unwind [ back chain 1 ] --
+ * [ padding ] align stack frame
+ * r4_off [ r4 (tailcallcnt) ] optional - 32-bit powerpc
+ * alt_lr_off [ real lr (ool stub)] optional - actual lr
+ * [ r26 ]
+ * nvr_off [ r25 ] nvr save area
+ * retval_off [ return value ]
+ * [ reg argN ]
+ * [ ... ]
+ * regs_off [ reg_arg1 ] prog ctx context
+ * nregs_off [ args count ]
+ * ip_off [ traced function ]
+ * [ ... ]
+ * run_ctx_off [ bpf_tramp_run_ctx ]
+ * [ reg argN ]
+ * [ ... ]
+ * param_save_area [ reg_arg1 ] min 8 doublewords, per ABI
+ * [ TOC save (64-bit) ] --
+ * [ LR save (64-bit) ] | header
+ * [ LR save (32-bit) ] |
+ * bpf trampoline frame [ back chain 2 ] --
+ *
+ */
+
+ /* Minimum stack frame header */
+ bpf_frame_size = STACK_FRAME_MIN_SIZE;
+
+ /*
+ * Room for parameter save area.
+ *
+ * As per the ABI, this is required if we call into the traced
+ * function (BPF_TRAMP_F_CALL_ORIG):
+ * - if the function takes more than 8 arguments for the rest to spill onto the stack
+ * - or, if the function has variadic arguments
+ * - or, if this functions's prototype was not available to the caller
+ *
+ * Reserve space for at least 8 registers for now. This can be optimized later.
+ */
+ bpf_frame_size += (nr_regs > 8 ? nr_regs : 8) * SZL;
+
+ /* Room for struct bpf_tramp_run_ctx */
+ run_ctx_off = bpf_frame_size;
+ bpf_frame_size += round_up(sizeof(struct bpf_tramp_run_ctx), SZL);
+
+ /* Room for IP address argument */
+ ip_off = bpf_frame_size;
+ if (flags & BPF_TRAMP_F_IP_ARG)
+ bpf_frame_size += SZL;
+
+ /* Room for args count */
+ nregs_off = bpf_frame_size;
+ bpf_frame_size += SZL;
+
+ /* Room for args */
+ regs_off = bpf_frame_size;
+ bpf_frame_size += nr_regs * SZL;
+
+ /* Room for return value of func_addr or fentry prog */
+ retval_off = bpf_frame_size;
+ save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
+ if (save_ret)
+ bpf_frame_size += SZL;
+
+ /* Room for nvr save area */
+ nvr_off = bpf_frame_size;
+ bpf_frame_size += 2 * SZL;
+
+ /* Optional save area for actual LR in case of ool ftrace */
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
+ alt_lr_off = bpf_frame_size;
+ bpf_frame_size += SZL;
+ }
+
+ if (IS_ENABLED(CONFIG_PPC32)) {
+ if (nr_regs < 2) {
+ r4_off = bpf_frame_size;
+ bpf_frame_size += SZL;
+ } else {
+ r4_off = regs_off + SZL;
+ }
+ }
+
+ /* Padding to align stack frame, if any */
+ bpf_frame_size = round_up(bpf_frame_size, SZL * 2);
+
+ /* Dummy frame size for proper unwind - includes 64-bytes red zone for 64-bit powerpc */
+ bpf_dummy_frame_size = STACK_FRAME_MIN_SIZE + 64;
+
+ /* Offset to the traced function's stack frame */
+ func_frame_offset = bpf_dummy_frame_size + bpf_frame_size;
+
+ /* Create dummy frame for unwind, store original return value */
+ EMIT(PPC_RAW_STL(_R0, _R1, PPC_LR_STKOFF));
+ /* Protect red zone where tail call count goes */
+ EMIT(PPC_RAW_STLU(_R1, _R1, -bpf_dummy_frame_size));
+
+ /* Create our stack frame */
+ EMIT(PPC_RAW_STLU(_R1, _R1, -bpf_frame_size));
+
+ /* 64-bit: Save TOC and load kernel TOC */
+ if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && !IS_ENABLED(CONFIG_PPC_KERNEL_PCREL)) {
+ EMIT(PPC_RAW_STD(_R2, _R1, 24));
+ PPC64_LOAD_PACA();
+ }
+
+ /* 32-bit: save tail call count in r4 */
+ if (IS_ENABLED(CONFIG_PPC32) && nr_regs < 2)
+ EMIT(PPC_RAW_STL(_R4, _R1, r4_off));
+
+ bpf_trampoline_save_args(image, ctx, func_frame_offset, nr_regs, regs_off);
+
+ /* Save our return address */
+ EMIT(PPC_RAW_MFLR(_R3));
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ EMIT(PPC_RAW_STL(_R3, _R1, alt_lr_off));
+ else
+ EMIT(PPC_RAW_STL(_R3, _R1, bpf_frame_size + PPC_LR_STKOFF));
+
+ /*
+ * Save ip address of the traced function.
+ * We could recover this from LR, but we will need to address for OOL trampoline,
+ * and optional GEP area.
+ */
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE) || flags & BPF_TRAMP_F_IP_ARG) {
+ EMIT(PPC_RAW_LWZ(_R4, _R3, 4));
+ EMIT(PPC_RAW_SLWI(_R4, _R4, 6));
+ EMIT(PPC_RAW_SRAWI(_R4, _R4, 6));
+ EMIT(PPC_RAW_ADD(_R3, _R3, _R4));
+ EMIT(PPC_RAW_ADDI(_R3, _R3, 4));
+ }
+
+ if (flags & BPF_TRAMP_F_IP_ARG)
+ EMIT(PPC_RAW_STL(_R3, _R1, ip_off));
+
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
+ /* Fake our LR for unwind */
+ EMIT(PPC_RAW_STL(_R3, _R1, bpf_frame_size + PPC_LR_STKOFF));
+
+ /* Save function arg count -- see bpf_get_func_arg_cnt() */
+ EMIT(PPC_RAW_LI(_R3, nr_regs));
+ EMIT(PPC_RAW_STL(_R3, _R1, nregs_off));
+
+ /* Save nv regs */
+ EMIT(PPC_RAW_STL(_R25, _R1, nvr_off));
+ EMIT(PPC_RAW_STL(_R26, _R1, nvr_off + SZL));
+
+ if (flags & BPF_TRAMP_F_CALL_ORIG) {
+ PPC_LI_ADDR(_R3, (unsigned long)im);
+ ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
+ (unsigned long)__bpf_tramp_enter);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < fentry->nr_links; i++)
+ if (invoke_bpf_prog(image, ro_image, ctx, fentry->links[i], regs_off, retval_off,
+ run_ctx_off, flags & BPF_TRAMP_F_RET_FENTRY_RET))
+ return -EINVAL;
+
+ if (fmod_ret->nr_links) {
+ branches = kcalloc(fmod_ret->nr_links, sizeof(u32), GFP_KERNEL);
+ if (!branches)
+ return -ENOMEM;
+
+ if (invoke_bpf_mod_ret(image, ro_image, ctx, fmod_ret, regs_off, retval_off,
+ run_ctx_off, branches)) {
+ ret = -EINVAL;
+ goto cleanup;
+ }
+ }
+
+ /* Call the traced function */
+ if (flags & BPF_TRAMP_F_CALL_ORIG) {
+ /*
+ * The address in LR save area points to the correct point in the original function
+ * with both PPC_FTRACE_OUT_OF_LINE as well as with traditional ftrace instruction
+ * sequence
+ */
+ EMIT(PPC_RAW_LL(_R3, _R1, bpf_frame_size + PPC_LR_STKOFF));
+ EMIT(PPC_RAW_MTCTR(_R3));
+
+ /* Replicate tail_call_cnt before calling the original BPF prog */
+ if (flags & BPF_TRAMP_F_TAIL_CALL_CTX)
+ bpf_trampoline_setup_tail_call_cnt(image, ctx, func_frame_offset, r4_off);
+
+ /* Restore args */
+ bpf_trampoline_restore_args_stack(image, ctx, func_frame_offset, nr_regs, regs_off);
+
+ /* Restore TOC for 64-bit */
+ if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && !IS_ENABLED(CONFIG_PPC_KERNEL_PCREL))
+ EMIT(PPC_RAW_LD(_R2, _R1, 24));
+ EMIT(PPC_RAW_BCTRL());
+ if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && !IS_ENABLED(CONFIG_PPC_KERNEL_PCREL))
+ PPC64_LOAD_PACA();
+
+ /* Store return value for bpf prog to access */
+ EMIT(PPC_RAW_STL(_R3, _R1, retval_off));
+
+ /* Restore updated tail_call_cnt */
+ if (flags & BPF_TRAMP_F_TAIL_CALL_CTX)
+ bpf_trampoline_restore_tail_call_cnt(image, ctx, func_frame_offset, r4_off);
+
+ /* Reserve space to patch branch instruction to skip fexit progs */
+ im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
+ EMIT(PPC_RAW_NOP());
+ }
+
+ /* Update branches saved in invoke_bpf_mod_ret with address of do_fexit */
+ for (i = 0; i < fmod_ret->nr_links && image; i++) {
+ if (create_cond_branch(&branch_insn, &image[branches[i]],
+ (unsigned long)&image[ctx->idx], COND_NE << 16)) {
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ image[branches[i]] = ppc_inst_val(branch_insn);
+ }
+
+ for (i = 0; i < fexit->nr_links; i++)
+ if (invoke_bpf_prog(image, ro_image, ctx, fexit->links[i], regs_off, retval_off,
+ run_ctx_off, false)) {
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ if (flags & BPF_TRAMP_F_CALL_ORIG) {
+ im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
+ PPC_LI_ADDR(_R3, im);
+ ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
+ (unsigned long)__bpf_tramp_exit);
+ if (ret)
+ goto cleanup;
+ }
+
+ if (flags & BPF_TRAMP_F_RESTORE_REGS)
+ bpf_trampoline_restore_args_regs(image, ctx, nr_regs, regs_off);
+
+ /* Restore return value of func_addr or fentry prog */
+ if (save_ret)
+ EMIT(PPC_RAW_LL(_R3, _R1, retval_off));
+
+ /* Restore nv regs */
+ EMIT(PPC_RAW_LL(_R26, _R1, nvr_off + SZL));
+ EMIT(PPC_RAW_LL(_R25, _R1, nvr_off));
+
+ /* Epilogue */
+ if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && !IS_ENABLED(CONFIG_PPC_KERNEL_PCREL))
+ EMIT(PPC_RAW_LD(_R2, _R1, 24));
+ if (flags & BPF_TRAMP_F_SKIP_FRAME) {
+ /* Skip the traced function and return to parent */
+ EMIT(PPC_RAW_ADDI(_R1, _R1, func_frame_offset));
+ EMIT(PPC_RAW_LL(_R0, _R1, PPC_LR_STKOFF));
+ EMIT(PPC_RAW_MTLR(_R0));
+ EMIT(PPC_RAW_BLR());
+ } else {
+ if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
+ EMIT(PPC_RAW_LL(_R0, _R1, alt_lr_off));
+ EMIT(PPC_RAW_MTLR(_R0));
+ EMIT(PPC_RAW_ADDI(_R1, _R1, func_frame_offset));
+ EMIT(PPC_RAW_LL(_R0, _R1, PPC_LR_STKOFF));
+ EMIT(PPC_RAW_BLR());
+ } else {
+ EMIT(PPC_RAW_LL(_R0, _R1, bpf_frame_size + PPC_LR_STKOFF));
+ EMIT(PPC_RAW_MTCTR(_R0));
+ EMIT(PPC_RAW_ADDI(_R1, _R1, func_frame_offset));
+ EMIT(PPC_RAW_LL(_R0, _R1, PPC_LR_STKOFF));
+ EMIT(PPC_RAW_MTLR(_R0));
+ EMIT(PPC_RAW_BCTR());
+ }
+ }
+
+ /* Make sure the trampoline generation logic doesn't overflow */
+ if (image && WARN_ON_ONCE(&image[ctx->idx] > (u32 *)rw_image_end - BPF_INSN_SAFETY)) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ ret = ctx->idx * 4 + BPF_INSN_SAFETY * 4;
+
+cleanup:
+ kfree(branches);
+ return ret;
+}
+
+int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
+ struct bpf_tramp_links *tlinks, void *func_addr)
+{
+ struct bpf_tramp_image im;
+ void *image;
+ int ret;
+
+ /*
+ * Allocate a temporary buffer for __arch_prepare_bpf_trampoline().
+ * This will NOT cause fragmentation in direct map, as we do not
+ * call set_memory_*() on this buffer.
+ *
+ * We cannot use kvmalloc here, because we need image to be in
+ * module memory range.
+ */
+ image = bpf_jit_alloc_exec(PAGE_SIZE);
+ if (!image)
+ return -ENOMEM;
+
+ ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image,
+ m, flags, tlinks, func_addr);
+ bpf_jit_free_exec(image);
+
+ return ret;
+}
+
+int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
+ const struct btf_func_model *m, u32 flags,
+ struct bpf_tramp_links *tlinks,
+ void *func_addr)
+{
+ u32 size = image_end - image;
+ void *rw_image, *tmp;
+ int ret;
+
+ /*
+ * rw_image doesn't need to be in module memory range, so we can
+ * use kvmalloc.
+ */
+ rw_image = kvmalloc(size, GFP_KERNEL);
+ if (!rw_image)
+ return -ENOMEM;
+
+ ret = __arch_prepare_bpf_trampoline(im, rw_image, rw_image + size, image, m,
+ flags, tlinks, func_addr);
+ if (ret < 0)
+ goto out;
+
+ if (bpf_jit_enable > 1)
+ bpf_jit_dump(1, ret - BPF_INSN_SAFETY * 4, 1, rw_image);
+
+ tmp = bpf_arch_text_copy(image, rw_image, size);
+ if (IS_ERR(tmp))
+ ret = PTR_ERR(tmp);
+
+out:
+ kvfree(rw_image);
+ return ret;
+}
+
+static int bpf_modify_inst(void *ip, ppc_inst_t old_inst, ppc_inst_t new_inst)
+{
+ ppc_inst_t org_inst;
+
+ if (copy_inst_from_kernel_nofault(&org_inst, ip)) {
+ pr_err("0x%lx: fetching instruction failed\n", (unsigned long)ip);
+ return -EFAULT;
+ }
+
+ if (!ppc_inst_equal(org_inst, old_inst)) {
+ pr_err("0x%lx: expected (%08lx) != found (%08lx)\n",
+ (unsigned long)ip, ppc_inst_as_ulong(old_inst), ppc_inst_as_ulong(org_inst));
+ return -EINVAL;
+ }
+
+ if (ppc_inst_equal(old_inst, new_inst))
+ return 0;
+
+ return patch_instruction(ip, new_inst);
+}
+
+static void do_isync(void *info __maybe_unused)
+{
+ isync();
+}
+
+/*
+ * A 3-step process for bpf prog entry:
+ * 1. At bpf prog entry, a single nop/b:
+ * bpf_func:
+ * [nop|b] ool_stub
+ * 2. Out-of-line stub:
+ * ool_stub:
+ * mflr r0
+ * [b|bl] <bpf_prog>/<long_branch_stub>
+ * mtlr r0 // CONFIG_PPC_FTRACE_OUT_OF_LINE only
+ * b bpf_func + 4
+ * 3. Long branch stub:
+ * long_branch_stub:
+ * .long <branch_addr>/<dummy_tramp>
+ * mflr r11
+ * bcl 20,31,$+4
+ * mflr r12
+ * ld r12, -16(r12)
+ * mtctr r12
+ * mtlr r11 // needed to retain ftrace ABI
+ * bctr
+ *
+ * dummy_tramp is used to reduce synchronization requirements.
+ *
+ * When attaching a bpf trampoline to a bpf prog, we do not need any
+ * synchronization here since we always have a valid branch target regardless
+ * of the order in which the above stores are seen. dummy_tramp ensures that
+ * the long_branch stub goes to a valid destination on other cpus, even when
+ * the branch to the long_branch stub is seen before the updated trampoline
+ * address.
+ *
+ * However, when detaching a bpf trampoline from a bpf prog, or if changing
+ * the bpf trampoline address, we need synchronization to ensure that other
+ * cpus can no longer branch into the older trampoline so that it can be
+ * safely freed. bpf_tramp_image_put() uses rcu_tasks to ensure all cpus
+ * make forward progress, but we still need to ensure that other cpus
+ * execute isync (or some CSI) so that they don't go back into the
+ * trampoline again.
+ */
+int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
+ void *old_addr, void *new_addr)
+{
+ unsigned long bpf_func, bpf_func_end, size, offset;
+ ppc_inst_t old_inst, new_inst;
+ int ret = 0, branch_flags;
+ char name[KSYM_NAME_LEN];
+
+ if (IS_ENABLED(CONFIG_PPC32))
+ return -EOPNOTSUPP;
+
+ bpf_func = (unsigned long)ip;
+ branch_flags = poke_type == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;
+
+ /* We currently only support poking bpf programs */
+ if (!__bpf_address_lookup(bpf_func, &size, &offset, name)) {
+ pr_err("%s (0x%lx): kernel/modules are not supported\n", __func__, bpf_func);
+ return -EOPNOTSUPP;
+ }
+
+ /*
+ * If we are not poking at bpf prog entry, then we are simply patching in/out
+ * an unconditional branch instruction at im->ip_after_call
+ */
+ if (offset) {
+ if (poke_type != BPF_MOD_JUMP) {
+ pr_err("%s (0x%lx): calls are not supported in bpf prog body\n", __func__,
+ bpf_func);
+ return -EOPNOTSUPP;
+ }
+ old_inst = ppc_inst(PPC_RAW_NOP());
+ if (old_addr)
+ if (create_branch(&old_inst, ip, (unsigned long)old_addr, 0))
+ return -ERANGE;
+ new_inst = ppc_inst(PPC_RAW_NOP());
+ if (new_addr)
+ if (create_branch(&new_inst, ip, (unsigned long)new_addr, 0))
+ return -ERANGE;
+ mutex_lock(&text_mutex);
+ ret = bpf_modify_inst(ip, old_inst, new_inst);
+ mutex_unlock(&text_mutex);
+
+ /* Make sure all cpus see the new instruction */
+ smp_call_function(do_isync, NULL, 1);
+ return ret;
+ }
+
+ bpf_func_end = bpf_func + size;
+
+ /* Address of the jmp/call instruction in the out-of-line stub */
+ ip = (void *)(bpf_func_end - bpf_jit_ool_stub + 4);
+
+ if (!is_offset_in_branch_range((long)ip - 4 - bpf_func)) {
+ pr_err("%s (0x%lx): bpf prog too large, ool stub out of branch range\n", __func__,
+ bpf_func);
+ return -ERANGE;
+ }
+
+ old_inst = ppc_inst(PPC_RAW_NOP());
+ if (old_addr) {
+ if (is_offset_in_branch_range(ip - old_addr))
+ create_branch(&old_inst, ip, (unsigned long)old_addr, branch_flags);
+ else
+ create_branch(&old_inst, ip, bpf_func_end - bpf_jit_long_branch_stub,
+ branch_flags);
+ }
+ new_inst = ppc_inst(PPC_RAW_NOP());
+ if (new_addr) {
+ if (is_offset_in_branch_range(ip - new_addr))
+ create_branch(&new_inst, ip, (unsigned long)new_addr, branch_flags);
+ else
+ create_branch(&new_inst, ip, bpf_func_end - bpf_jit_long_branch_stub,
+ branch_flags);
+ }
+
+ mutex_lock(&text_mutex);
+
+ /*
+ * 1. Update the address in the long branch stub:
+ * If new_addr is out of range, we will have to use the long branch stub, so patch new_addr
+ * here. Otherwise, revert to dummy_tramp, but only if we had patched old_addr here.
+ */
+ if ((new_addr && !is_offset_in_branch_range(new_addr - ip)) ||
+ (old_addr && !is_offset_in_branch_range(old_addr - ip)))
+ ret = patch_ulong((void *)(bpf_func_end - bpf_jit_long_branch_stub - SZL),
+ (new_addr && !is_offset_in_branch_range(new_addr - ip)) ?
+ (unsigned long)new_addr : (unsigned long)dummy_tramp);
+ if (ret)
+ goto out;
+
+ /* 2. Update the branch/call in the out-of-line stub */
+ ret = bpf_modify_inst(ip, old_inst, new_inst);
+ if (ret)
+ goto out;
+
+ /* 3. Update instruction at bpf prog entry */
+ ip = (void *)bpf_func;
+ if (!old_addr || !new_addr) {
+ if (!old_addr) {
+ old_inst = ppc_inst(PPC_RAW_NOP());
+ create_branch(&new_inst, ip, bpf_func_end - bpf_jit_ool_stub, 0);
+ } else {
+ new_inst = ppc_inst(PPC_RAW_NOP());
+ create_branch(&old_inst, ip, bpf_func_end - bpf_jit_ool_stub, 0);
+ }
+ ret = bpf_modify_inst(ip, old_inst, new_inst);
+ }
+
+out:
+ mutex_unlock(&text_mutex);
+
+ /*
+ * Sync only if we are not attaching a trampoline to a bpf prog so the older
+ * trampoline can be freed safely.
+ */
+ if (old_addr)
+ smp_call_function(do_isync, NULL, 1);
+
+ return ret;
+}
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index a0c4f1bde83e..c4db278dae36 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -127,13 +127,16 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
{
int i;
+ /* Instruction for trampoline attach */
+ EMIT(PPC_RAW_NOP());
+
/* Initialize tail_call_cnt, to be skipped if we do tail calls. */
if (ctx->seen & SEEN_TAILCALL)
EMIT(PPC_RAW_LI(_R4, 0));
else
EMIT(PPC_RAW_NOP());
-#define BPF_TAILCALL_PROLOGUE_SIZE 4
+#define BPF_TAILCALL_PROLOGUE_SIZE 8
if (bpf_has_stack_frame(ctx))
EMIT(PPC_RAW_STWU(_R1, _R1, -BPF_PPC_STACKFRAME(ctx)));
@@ -198,6 +201,8 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
bpf_jit_emit_common_epilogue(image, ctx);
EMIT(PPC_RAW_BLR());
+
+ bpf_jit_build_fentry_stubs(image, ctx);
}
/* Relative offset needs to be calculated based on final image location */
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 2cbcdf93cc19..233703b06d7c 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -84,7 +84,7 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx)
}
/*
- * When not setting up our own stackframe, the redzone usage is:
+ * When not setting up our own stackframe, the redzone (288 bytes) usage is:
*
* [ prev sp ] <-------------
* [ ... ] |
@@ -92,7 +92,7 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx)
* [ nv gpr save area ] 5*8
* [ tail_call_cnt ] 8
* [ local_tmp_var ] 16
- * [ unused red zone ] 208 bytes protected
+ * [ unused red zone ] 224
*/
static int bpf_jit_stack_local(struct codegen_context *ctx)
{
@@ -126,6 +126,9 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
{
int i;
+ /* Instruction for trampoline attach */
+ EMIT(PPC_RAW_NOP());
+
#ifndef CONFIG_PPC_KERNEL_PCREL
if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2))
EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)));
@@ -200,16 +203,26 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_0)));
EMIT(PPC_RAW_BLR());
+
+ bpf_jit_build_fentry_stubs(image, ctx);
}
-static int
-bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
+int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
{
unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0;
long reladdr;
- if (WARN_ON_ONCE(!kernel_text_address(func_addr)))
- return -EINVAL;
+ /* bpf to bpf call, func is not known in the initial pass. Emit 5 nops as a placeholder */
+ if (!func) {
+ for (int i = 0; i < 5; i++)
+ EMIT(PPC_RAW_NOP());
+ /* elfv1 needs an additional instruction to load addr from descriptor */
+ if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1))
+ EMIT(PPC_RAW_NOP());
+ EMIT(PPC_RAW_MTCTR(_R12));
+ EMIT(PPC_RAW_BCTRL());
+ return 0;
+ }
#ifdef CONFIG_PPC_KERNEL_PCREL
reladdr = func_addr - local_paca->kernelbase;
@@ -266,7 +279,8 @@ bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx,
* We can clobber r2 since we get called through a
* function pointer (so caller will save/restore r2).
*/
- EMIT(PPC_RAW_LD(_R2, bpf_to_ppc(TMP_REG_2), 8));
+ if (is_module_text_address(func_addr))
+ EMIT(PPC_RAW_LD(_R2, bpf_to_ppc(TMP_REG_2), 8));
} else {
PPC_LI64(_R12, func);
EMIT(PPC_RAW_MTCTR(_R12));
@@ -276,46 +290,14 @@ bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx,
* Load r2 with kernel TOC as kernel TOC is used if function address falls
* within core kernel text.
*/
- EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)));
+ if (is_module_text_address(func_addr))
+ EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)));
}
#endif
return 0;
}
-int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
-{
- unsigned int i, ctx_idx = ctx->idx;
-
- if (WARN_ON_ONCE(func && is_module_text_address(func)))
- return -EINVAL;
-
- /* skip past descriptor if elf v1 */
- func += FUNCTION_DESCR_SIZE;
-
- /* Load function address into r12 */
- PPC_LI64(_R12, func);
-
- /* For bpf-to-bpf function calls, the callee's address is unknown
- * until the last extra pass. As seen above, we use PPC_LI64() to
- * load the callee's address, but this may optimize the number of
- * instructions required based on the nature of the address.
- *
- * Since we don't want the number of instructions emitted to increase,
- * we pad the optimized PPC_LI64() call with NOPs to guarantee that
- * we always have a five-instruction sequence, which is the maximum
- * that PPC_LI64() can emit.
- */
- if (!image)
- for (i = ctx->idx - ctx_idx; i < 5; i++)
- EMIT(PPC_RAW_NOP());
-
- EMIT(PPC_RAW_MTCTR(_R12));
- EMIT(PPC_RAW_BCTRL());
-
- return 0;
-}
-
static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
{
/*
@@ -326,7 +308,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
*/
int b2p_bpf_array = bpf_to_ppc(BPF_REG_2);
int b2p_index = bpf_to_ppc(BPF_REG_3);
- int bpf_tailcall_prologue_size = 8;
+ int bpf_tailcall_prologue_size = 12;
if (!IS_ENABLED(CONFIG_PPC_KERNEL_PCREL) && IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2))
bpf_tailcall_prologue_size += 4; /* skip past the toc load */
@@ -1102,11 +1084,7 @@ emit_clear:
if (ret < 0)
return ret;
- if (func_addr_fixed)
- ret = bpf_jit_emit_func_call_hlp(image, fimage, ctx, func_addr);
- else
- ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
-
+ ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
if (ret)
return ret;
diff --git a/arch/powerpc/perf/8xx-pmu.c b/arch/powerpc/perf/8xx-pmu.c
index 308a2e40d7be..1d2972229e3a 100644
--- a/arch/powerpc/perf/8xx-pmu.c
+++ b/arch/powerpc/perf/8xx-pmu.c
@@ -14,7 +14,7 @@
#include <asm/machdep.h>
#include <asm/firmware.h>
#include <asm/ptrace.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/inst.h>
#define PERF_8xx_ID_CPU_CYCLES 1
diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile
index 4f53d0b97539..ac2cf58d62db 100644
--- a/arch/powerpc/perf/Makefile
+++ b/arch/powerpc/perf/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o e6500-pmu.o
obj-$(CONFIG_HV_PERF_CTRS) += hv-24x7.o hv-gpci.o hv-common.o
+obj-$(CONFIG_VPA_PMU) += vpa-pmu.o
+
obj-$(CONFIG_PPC_8xx) += 8xx-pmu.o
obj-$(CONFIG_PPC64) += $(obj64-y)
diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c
index 6b4434dd0ff3..26aa26482c9a 100644
--- a/arch/powerpc/perf/callchain.c
+++ b/arch/powerpc/perf/callchain.c
@@ -51,7 +51,7 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
lr = regs->link;
sp = regs->gpr[1];
- perf_callchain_store(entry, perf_instruction_pointer(regs));
+ perf_callchain_store(entry, perf_arch_instruction_pointer(regs));
if (!validate_sp(sp, current))
return;
diff --git a/arch/powerpc/perf/callchain_32.c b/arch/powerpc/perf/callchain_32.c
index ea8cfe3806dc..ddcc2d8aa64a 100644
--- a/arch/powerpc/perf/callchain_32.c
+++ b/arch/powerpc/perf/callchain_32.c
@@ -139,7 +139,7 @@ void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
long level = 0;
unsigned int __user *fp, *uregs;
- next_ip = perf_instruction_pointer(regs);
+ next_ip = perf_arch_instruction_pointer(regs);
lr = regs->link;
sp = regs->gpr[1];
perf_callchain_store(entry, next_ip);
diff --git a/arch/powerpc/perf/callchain_64.c b/arch/powerpc/perf/callchain_64.c
index 488e8a21a11e..115d1c105e8a 100644
--- a/arch/powerpc/perf/callchain_64.c
+++ b/arch/powerpc/perf/callchain_64.c
@@ -74,7 +74,7 @@ void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
struct signal_frame_64 __user *sigframe;
unsigned long __user *fp, *uregs;
- next_ip = perf_instruction_pointer(regs);
+ next_ip = perf_arch_instruction_pointer(regs);
lr = regs->link;
sp = regs->gpr[1];
perf_callchain_store(entry, next_ip);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 42867469752d..2b79171ee185 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -16,7 +16,7 @@
#include <asm/machdep.h>
#include <asm/firmware.h>
#include <asm/ptrace.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/hw_irq.h>
#include <asm/interrupt.h>
@@ -2332,7 +2332,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
* Called from generic code to get the misc flags (i.e. processor mode)
* for an event_id.
*/
-unsigned long perf_misc_flags(struct pt_regs *regs)
+unsigned long perf_arch_misc_flags(struct pt_regs *regs)
{
u32 flags = perf_get_misc_flags(regs);
@@ -2346,7 +2346,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
* Called from generic code to get the instruction pointer
* for an event_id.
*/
-unsigned long perf_instruction_pointer(struct pt_regs *regs)
+unsigned long perf_arch_instruction_pointer(struct pt_regs *regs)
{
unsigned long siar = mfspr(SPRN_SIAR);
diff --git a/arch/powerpc/perf/vpa-pmu.c b/arch/powerpc/perf/vpa-pmu.c
new file mode 100644
index 000000000000..6a5bfd2a13b5
--- /dev/null
+++ b/arch/powerpc/perf/vpa-pmu.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Performance monitoring support for Virtual Processor Area(VPA) based counters
+ *
+ * Copyright (C) 2024 IBM Corporation
+ */
+#define pr_fmt(fmt) "vpa_pmu: " fmt
+
+#include <linux/module.h>
+#include <linux/perf_event.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s_64.h>
+
+#define MODULE_VERS "1.0"
+#define MODULE_NAME "pseries_vpa_pmu"
+
+#define EVENT(_name, _code) enum{_name = _code}
+
+#define VPA_PMU_EVENT_VAR(_id) event_attr_##_id
+#define VPA_PMU_EVENT_PTR(_id) (&event_attr_##_id.attr.attr)
+
+static ssize_t vpa_pmu_events_sysfs_show(struct device *dev,
+ struct device_attribute *attr, char *page)
+{
+ struct perf_pmu_events_attr *pmu_attr;
+
+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+
+ return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
+}
+
+#define VPA_PMU_EVENT_ATTR(_name, _id) \
+ PMU_EVENT_ATTR(_name, VPA_PMU_EVENT_VAR(_id), _id, \
+ vpa_pmu_events_sysfs_show)
+
+EVENT(L1_TO_L2_CS_LAT, 0x1);
+EVENT(L2_TO_L1_CS_LAT, 0x2);
+EVENT(L2_RUNTIME_AGG, 0x3);
+
+VPA_PMU_EVENT_ATTR(l1_to_l2_lat, L1_TO_L2_CS_LAT);
+VPA_PMU_EVENT_ATTR(l2_to_l1_lat, L2_TO_L1_CS_LAT);
+VPA_PMU_EVENT_ATTR(l2_runtime_agg, L2_RUNTIME_AGG);
+
+static struct attribute *vpa_pmu_events_attr[] = {
+ VPA_PMU_EVENT_PTR(L1_TO_L2_CS_LAT),
+ VPA_PMU_EVENT_PTR(L2_TO_L1_CS_LAT),
+ VPA_PMU_EVENT_PTR(L2_RUNTIME_AGG),
+ NULL
+};
+
+static const struct attribute_group vpa_pmu_events_group = {
+ .name = "events",
+ .attrs = vpa_pmu_events_attr,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-31");
+static struct attribute *vpa_pmu_format_attr[] = {
+ &format_attr_event.attr,
+ NULL,
+};
+
+static struct attribute_group vpa_pmu_format_group = {
+ .name = "format",
+ .attrs = vpa_pmu_format_attr,
+};
+
+static const struct attribute_group *vpa_pmu_attr_groups[] = {
+ &vpa_pmu_events_group,
+ &vpa_pmu_format_group,
+ NULL
+};
+
+static int vpa_pmu_event_init(struct perf_event *event)
+{
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ /* it does not support event sampling mode */
+ if (is_sampling_event(event))
+ return -EOPNOTSUPP;
+
+ /* no branch sampling */
+ if (has_branch_stack(event))
+ return -EOPNOTSUPP;
+
+ /* Invalid event code */
+ if ((event->attr.config <= 0) || (event->attr.config > 3))
+ return -EINVAL;
+
+ return 0;
+}
+
+static unsigned long get_counter_data(struct perf_event *event)
+{
+ unsigned int config = event->attr.config;
+ u64 data;
+
+ switch (config) {
+ case L1_TO_L2_CS_LAT:
+ if (event->attach_state & PERF_ATTACH_TASK)
+ data = kvmhv_get_l1_to_l2_cs_time_vcpu();
+ else
+ data = kvmhv_get_l1_to_l2_cs_time();
+ break;
+ case L2_TO_L1_CS_LAT:
+ if (event->attach_state & PERF_ATTACH_TASK)
+ data = kvmhv_get_l2_to_l1_cs_time_vcpu();
+ else
+ data = kvmhv_get_l2_to_l1_cs_time();
+ break;
+ case L2_RUNTIME_AGG:
+ if (event->attach_state & PERF_ATTACH_TASK)
+ data = kvmhv_get_l2_runtime_agg_vcpu();
+ else
+ data = kvmhv_get_l2_runtime_agg();
+ break;
+ default:
+ data = 0;
+ break;
+ }
+
+ return data;
+}
+
+static int vpa_pmu_add(struct perf_event *event, int flags)
+{
+ u64 data;
+
+ kvmhv_set_l2_counters_status(smp_processor_id(), true);
+
+ data = get_counter_data(event);
+ local64_set(&event->hw.prev_count, data);
+
+ return 0;
+}
+
+static void vpa_pmu_read(struct perf_event *event)
+{
+ u64 prev_data, new_data, final_data;
+
+ prev_data = local64_read(&event->hw.prev_count);
+ new_data = get_counter_data(event);
+ final_data = new_data - prev_data;
+
+ local64_add(final_data, &event->count);
+}
+
+static void vpa_pmu_del(struct perf_event *event, int flags)
+{
+ vpa_pmu_read(event);
+
+ /*
+ * Disable vpa counter accumulation
+ */
+ kvmhv_set_l2_counters_status(smp_processor_id(), false);
+}
+
+static struct pmu vpa_pmu = {
+ .task_ctx_nr = perf_sw_context,
+ .name = "vpa_pmu",
+ .event_init = vpa_pmu_event_init,
+ .add = vpa_pmu_add,
+ .del = vpa_pmu_del,
+ .read = vpa_pmu_read,
+ .attr_groups = vpa_pmu_attr_groups,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
+};
+
+static int __init pseries_vpa_pmu_init(void)
+{
+ /*
+ * List of current Linux on Power platforms and
+ * this driver is supported only in PowerVM LPAR
+ * (L1) platform.
+ *
+ * Enabled Linux on Power Platforms
+ * ----------------------------------------
+ * [X] PowerVM LPAR (L1)
+ * [ ] KVM Guest On PowerVM KoP(L2)
+ * [ ] Baremetal(PowerNV)
+ * [ ] KVM Guest On PowerNV
+ */
+ if (!firmware_has_feature(FW_FEATURE_LPAR) || is_kvm_guest())
+ return -ENODEV;
+
+ perf_pmu_register(&vpa_pmu, vpa_pmu.name, -1);
+ pr_info("Virtual Processor Area PMU registered.\n");
+
+ return 0;
+}
+
+static void __exit pseries_vpa_pmu_cleanup(void)
+{
+ perf_pmu_unregister(&vpa_pmu);
+ pr_info("Virtual Processor Area PMU unregistered.\n");
+}
+
+module_init(pseries_vpa_pmu_init);
+module_exit(pseries_vpa_pmu_cleanup);
+MODULE_DESCRIPTION("Perf Driver for pSeries VPA pmu counter");
+MODULE_AUTHOR("Kajol Jain <kjain@linux.ibm.com>");
+MODULE_AUTHOR("Madhavan Srinivasan <maddy@linux.ibm.com>");
+MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/platforms/44x/pci.c b/arch/powerpc/platforms/44x/pci.c
index db6d33ca753f..364aeb86ab64 100644
--- a/arch/powerpc/platforms/44x/pci.c
+++ b/arch/powerpc/platforms/44x/pci.c
@@ -94,10 +94,8 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
struct resource *res)
{
u64 size;
- const u32 *ranges;
- int rlen;
- int pna = of_n_addr_cells(hose->dn);
- int np = pna + 5;
+ struct of_range_parser parser;
+ struct of_range range;
/* Default */
res->start = 0;
@@ -105,18 +103,15 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
res->end = size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
- /* Get dma-ranges property */
- ranges = of_get_property(hose->dn, "dma-ranges", &rlen);
- if (ranges == NULL)
+ if (of_pci_dma_range_parser_init(&parser, hose->dn))
goto out;
- /* Walk it */
- while ((rlen -= np * 4) >= 0) {
- u32 pci_space = ranges[0];
- u64 pci_addr = of_read_number(ranges + 1, 2);
- u64 cpu_addr = of_translate_dma_address(hose->dn, ranges + 3);
- size = of_read_number(ranges + pna + 3, 2);
- ranges += np;
+ for_each_of_range(&parser, &range) {
+ u32 pci_space = range.flags;
+ u64 pci_addr = range.bus_addr;
+ u64 cpu_addr = range.cpu_addr;
+ size = range.size;
+
if (cpu_addr == OF_BAD_ADDR || size == 0)
continue;
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 37a67120f257..a7172f9ebaad 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -13,6 +13,7 @@
#include <generated/utsrelease.h>
#include <linux/pci.h>
#include <linux/of.h>
+#include <linux/seq_file.h>
#include <asm/dma.h>
#include <asm/time.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
index 3dc65ce1f175..8f918916e631 100644
--- a/arch/powerpc/platforms/82xx/ep8248e.c
+++ b/arch/powerpc/platforms/82xx/ep8248e.c
@@ -128,7 +128,7 @@ static int ep8248e_mdio_probe(struct platform_device *ofdev)
bus->name = "ep8248e-mdio-bitbang";
bus->parent = &ofdev->dev;
- snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res.start);
ret = of_mdiobus_register(bus, ofdev->dev.of_node);
if (ret)
diff --git a/arch/powerpc/platforms/82xx/km82xx.c b/arch/powerpc/platforms/82xx/km82xx.c
index c86da3f2b74b..99f0f0f41876 100644
--- a/arch/powerpc/platforms/82xx/km82xx.c
+++ b/arch/powerpc/platforms/82xx/km82xx.c
@@ -27,15 +27,15 @@
static void __init km82xx_pic_init(void)
{
- struct device_node *np = of_find_compatible_node(NULL, NULL,
- "fsl,pq2-pic");
+ struct device_node *np __free(device_node);
+ np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic");
+
if (!np) {
pr_err("PIC init: can not find cpm-pic node\n");
return;
}
cpm2_pic_init(np);
- of_node_put(np);
}
struct cpm_pin {
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 9315a3b69d6d..604c1b4b6d45 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -40,27 +40,6 @@ config BSC9132_QDS
and dual StarCore SC3850 DSP cores.
Manufacturer : Freescale Semiconductor, Inc
-config MPC8540_ADS
- bool "Freescale MPC8540 ADS"
- select DEFAULT_UIMAGE
- help
- This option enables support for the MPC 8540 ADS board
-
-config MPC8560_ADS
- bool "Freescale MPC8560 ADS"
- select DEFAULT_UIMAGE
- select CPM2
- help
- This option enables support for the MPC 8560 ADS board
-
-config MPC85xx_CDS
- bool "Freescale MPC85xx CDS"
- select DEFAULT_UIMAGE
- select PPC_I8259
- select HAVE_RAPIDIO
- help
- This option enables support for the MPC85xx CDS board
-
config MPC85xx_MDS
bool "Freescale MPC8568 MDS / MPC8569 MDS / P1021 MDS"
select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index e52b848b64b7..32fa5fb557c0 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -23,7 +23,7 @@
#include <asm/mpic.h>
#include <asm/cacheflush.h>
#include <asm/dbell.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/cputhreads.h>
#include <asm/fsl_pm.h>
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index 8a7e55acf090..9be33e41af6d 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -12,7 +12,7 @@
#include <linux/delay.h>
#include <linux/pgtable.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/page.h>
#include <asm/pci-bridge.h>
#include <asm/mpic.h>
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 1112a5831619..a454149ae02f 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -7,7 +7,6 @@ source "arch/powerpc/platforms/chrp/Kconfig"
source "arch/powerpc/platforms/512x/Kconfig"
source "arch/powerpc/platforms/52xx/Kconfig"
source "arch/powerpc/platforms/powermac/Kconfig"
-source "arch/powerpc/platforms/maple/Kconfig"
source "arch/powerpc/platforms/pasemi/Kconfig"
source "arch/powerpc/platforms/ps3/Kconfig"
source "arch/powerpc/platforms/cell/Kconfig"
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 786d374bff31..3cee4a842736 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_FSL_SOC_BOOKE) += 85xx/
obj-$(CONFIG_PPC_86xx) += 86xx/
obj-$(CONFIG_PPC_POWERNV) += powernv/
obj-$(CONFIG_PPC_PSERIES) += pseries/
-obj-$(CONFIG_PPC_MAPLE) += maple/
obj-$(CONFIG_PPC_PASEMI) += pasemi/
obj-$(CONFIG_PPC_CELL) += cell/
obj-$(CONFIG_PPC_PS3) += ps3/
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 28dc86744cac..d243f7fd8982 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -112,7 +112,7 @@ static void axon_msi_cascade(struct irq_desc *desc)
pr_devel("axon_msi: woff %x roff %x msi %x\n",
write_offset, msic->read_offset, msi);
- if (msi < nr_irqs && irq_get_chip_data(msi) == msic) {
+ if (msi < irq_get_nr_irqs() && irq_get_chip_data(msi) == msic) {
generic_handle_irq(msi);
msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
} else {
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 4cd9c0de22c2..62c9679b8ca3 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -779,58 +779,41 @@ static int __init cell_iommu_init_disabled(void)
static u64 cell_iommu_get_fixed_address(struct device *dev)
{
- u64 cpu_addr, size, best_size, dev_addr = OF_BAD_ADDR;
+ u64 best_size, dev_addr = OF_BAD_ADDR;
struct device_node *np;
- const u32 *ranges = NULL;
- int i, len, best, naddr, nsize, pna, range_size;
+ struct of_range_parser parser;
+ struct of_range range;
/* We can be called for platform devices that have no of_node */
np = of_node_get(dev->of_node);
if (!np)
goto out;
- while (1) {
- naddr = of_n_addr_cells(np);
- nsize = of_n_size_cells(np);
- np = of_get_next_parent(np);
- if (!np)
- break;
-
- ranges = of_get_property(np, "dma-ranges", &len);
+ while ((np = of_get_next_parent(np))) {
+ if (of_pci_dma_range_parser_init(&parser, np))
+ continue;
- /* Ignore empty ranges, they imply no translation required */
- if (ranges && len > 0)
+ if (of_range_count(&parser))
break;
}
- if (!ranges) {
+ if (!np) {
dev_dbg(dev, "iommu: no dma-ranges found\n");
goto out;
}
- len /= sizeof(u32);
-
- pna = of_n_addr_cells(np);
- range_size = naddr + nsize + pna;
-
- /* dma-ranges format:
- * child addr : naddr cells
- * parent addr : pna cells
- * size : nsize cells
- */
- for (i = 0, best = -1, best_size = 0; i < len; i += range_size) {
- cpu_addr = of_translate_dma_address(np, ranges + i + naddr);
- size = of_read_number(ranges + i + naddr + pna, nsize);
+ best_size = 0;
+ for_each_of_range(&parser, &range) {
+ if (!range.cpu_addr)
+ continue;
- if (cpu_addr == 0 && size > best_size) {
- best = i;
- best_size = size;
+ if (range.size > best_size) {
+ best_size = range.size;
+ dev_addr = range.bus_addr;
}
}
- if (best >= 0) {
- dev_addr = of_read_number(ranges + best, naddr);
- } else
+ if (!best_size)
dev_dbg(dev, "iommu: no suitable range found!\n");
out:
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index fee638fd8970..0e8f20ecca08 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -35,7 +35,7 @@
#include <asm/firmware.h>
#include <asm/rtas.h>
#include <asm/cputhreads.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include "interrupt.h"
#include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index cd7d42fc12a6..000894e07b02 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -36,6 +36,9 @@ static inline struct spufs_calls *spufs_calls_get(void)
static inline void spufs_calls_put(struct spufs_calls *calls)
{
+ if (!calls)
+ return;
+
BUG_ON(calls != spufs_calls);
/* we don't need to rcu this, as we hold a reference to the module */
@@ -53,82 +56,55 @@ static inline void spufs_calls_put(struct spufs_calls *calls) { }
#endif /* CONFIG_SPU_FS_MODULE */
+DEFINE_CLASS(spufs_calls, struct spufs_calls *, spufs_calls_put(_T), spufs_calls_get(), void)
+
SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
umode_t, mode, int, neighbor_fd)
{
- long ret;
- struct spufs_calls *calls;
-
- calls = spufs_calls_get();
+ CLASS(spufs_calls, calls)();
if (!calls)
return -ENOSYS;
if (flags & SPU_CREATE_AFFINITY_SPU) {
- struct fd neighbor = fdget(neighbor_fd);
- ret = -EBADF;
- if (fd_file(neighbor)) {
- ret = calls->create_thread(name, flags, mode, fd_file(neighbor));
- fdput(neighbor);
- }
- } else
- ret = calls->create_thread(name, flags, mode, NULL);
-
- spufs_calls_put(calls);
- return ret;
+ CLASS(fd, neighbor)(neighbor_fd);
+ if (fd_empty(neighbor))
+ return -EBADF;
+ return calls->create_thread(name, flags, mode, fd_file(neighbor));
+ } else {
+ return calls->create_thread(name, flags, mode, NULL);
+ }
}
SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus)
{
- long ret;
- struct fd arg;
- struct spufs_calls *calls;
-
- calls = spufs_calls_get();
+ CLASS(spufs_calls, calls)();
if (!calls)
return -ENOSYS;
- ret = -EBADF;
- arg = fdget(fd);
- if (fd_file(arg)) {
- ret = calls->spu_run(fd_file(arg), unpc, ustatus);
- fdput(arg);
- }
+ CLASS(fd, arg)(fd);
+ if (fd_empty(arg))
+ return -EBADF;
- spufs_calls_put(calls);
- return ret;
+ return calls->spu_run(fd_file(arg), unpc, ustatus);
}
#ifdef CONFIG_COREDUMP
int elf_coredump_extra_notes_size(void)
{
- struct spufs_calls *calls;
- int ret;
-
- calls = spufs_calls_get();
+ CLASS(spufs_calls, calls)();
if (!calls)
return 0;
- ret = calls->coredump_extra_notes_size();
-
- spufs_calls_put(calls);
-
- return ret;
+ return calls->coredump_extra_notes_size();
}
int elf_coredump_extra_notes_write(struct coredump_params *cprm)
{
- struct spufs_calls *calls;
- int ret;
-
- calls = spufs_calls_get();
+ CLASS(spufs_calls, calls)();
if (!calls)
return 0;
- ret = calls->coredump_extra_notes_write(cprm);
-
- spufs_calls_put(calls);
-
- return ret;
+ return calls->coredump_extra_notes_write(cprm);
}
#endif
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 18daafbe2e65..301ee7d8b7df 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -73,9 +73,7 @@ static struct spu_context *coredump_next_context(int *fd)
return NULL;
*fd = n - 1;
- rcu_read_lock();
- file = lookup_fdget_rcu(*fd);
- rcu_read_unlock();
+ file = fget_raw(*fd);
if (file) {
ctx = SPUFS_I(file_inode(file))->i_ctx;
get_spu_context(ctx);
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index e265f026eee2..4012f206ec63 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/initrd.h>
#include <linux/of_platform.h>
+#include <linux/seq_file.h>
#include <asm/time.h>
#include <asm/mpic.h>
diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c
index 00bec0f051be..5ca41972ef22 100644
--- a/arch/powerpc/platforms/embedded6xx/mvme5100.c
+++ b/arch/powerpc/platforms/embedded6xx/mvme5100.c
@@ -14,6 +14,7 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/seq_file.h>
#include <asm/i8259.h>
#include <asm/pci-bridge.h>
diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig
deleted file mode 100644
index 4c058cc57c90..000000000000
--- a/arch/powerpc/platforms/maple/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config PPC_MAPLE
- depends on PPC64 && PPC_BOOK3S && CPU_BIG_ENDIAN
- bool "Maple 970FX Evaluation Board"
- select FORCE_PCI
- select MPIC
- select U3_DART
- select MPIC_U3_HT_IRQS
- select GENERIC_TBSYNC
- select PPC_UDBG_16550
- select PPC_970_NAP
- select PPC_64S_HASH_MMU
- select PPC_HASH_MMU_NATIVE
- select PPC_RTAS
- select MMIO_NVRAM
- select ATA_NONSTANDARD if ATA
- help
- This option enables support for the Maple 970FX Evaluation Board.
- For more information, refer to <http://www.970eval.com>
diff --git a/arch/powerpc/platforms/maple/Makefile b/arch/powerpc/platforms/maple/Makefile
deleted file mode 100644
index 19f35ab828a7..000000000000
--- a/arch/powerpc/platforms/maple/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-y += setup.o pci.o time.o
diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h
deleted file mode 100644
index 8ddbaa4ebd0b..000000000000
--- a/arch/powerpc/platforms/maple/maple.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Declarations for maple-specific code.
- *
- * Maple is the name of a PPC970 evaluation board.
- */
-extern int maple_set_rtc_time(struct rtc_time *tm);
-extern void maple_get_rtc_time(struct rtc_time *tm);
-extern time64_t maple_get_boot_time(void);
-extern void maple_pci_init(void);
-extern void maple_pci_irq_fixup(struct pci_dev *dev);
-extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
-
-extern struct pci_controller_ops maple_pci_controller_ops;
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
deleted file mode 100644
index b9ff37c7f6f0..000000000000
--- a/arch/powerpc/platforms/maple/pci.c
+++ /dev/null
@@ -1,672 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
- * IBM Corp.
- */
-
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/iommu.h>
-#include <asm/ppc-pci.h>
-#include <asm/isa-bridge.h>
-
-#include "maple.h"
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-static struct pci_controller *u3_agp, *u3_ht, *u4_pcie;
-
-static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
-{
- for (; node; node = node->sibling) {
- const int *bus_range;
- const unsigned int *class_code;
- int len;
-
- /* For PCI<->PCI bridges or CardBus bridges, we go down */
- class_code = of_get_property(node, "class-code", NULL);
- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
- continue;
- bus_range = of_get_property(node, "bus-range", &len);
- if (bus_range != NULL && len > 2 * sizeof(int)) {
- if (bus_range[1] > higher)
- higher = bus_range[1];
- }
- higher = fixup_one_level_bus_range(node->child, higher);
- }
- return higher;
-}
-
-/* This routine fixes the "bus-range" property of all bridges in the
- * system since they tend to have their "last" member wrong on macs
- *
- * Note that the bus numbers manipulated here are OF bus numbers, they
- * are not Linux bus numbers.
- */
-static void __init fixup_bus_range(struct device_node *bridge)
-{
- int *bus_range;
- struct property *prop;
- int len;
-
- /* Lookup the "bus-range" property for the hose */
- prop = of_find_property(bridge, "bus-range", &len);
- if (prop == NULL || prop->value == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %pOF\n",
- bridge);
- return;
- }
- bus_range = prop->value;
- bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
-}
-
-
-static unsigned long u3_agp_cfa0(u8 devfn, u8 off)
-{
- return (1 << (unsigned long)PCI_SLOT(devfn)) |
- ((unsigned long)PCI_FUNC(devfn) << 8) |
- ((unsigned long)off & 0xFCUL);
-}
-
-static unsigned long u3_agp_cfa1(u8 bus, u8 devfn, u8 off)
-{
- return ((unsigned long)bus << 16) |
- ((unsigned long)devfn << 8) |
- ((unsigned long)off & 0xFCUL) |
- 1UL;
-}
-
-static volatile void __iomem *u3_agp_cfg_access(struct pci_controller* hose,
- u8 bus, u8 dev_fn, u8 offset)
-{
- unsigned int caddr;
-
- if (bus == hose->first_busno) {
- if (dev_fn < (11 << 3))
- return NULL;
- caddr = u3_agp_cfa0(dev_fn, offset);
- } else
- caddr = u3_agp_cfa1(bus, dev_fn, offset);
-
- /* Uninorth will return garbage if we don't read back the value ! */
- do {
- out_le32(hose->cfg_addr, caddr);
- } while (in_le32(hose->cfg_addr) != caddr);
-
- offset &= 0x07;
- return hose->cfg_data + offset;
-}
-
-static int u3_agp_read_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 *val)
-{
- struct pci_controller *hose;
- volatile void __iomem *addr;
-
- hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- *val = in_8(addr);
- break;
- case 2:
- *val = in_le16(addr);
- break;
- default:
- *val = in_le32(addr);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 val)
-{
- struct pci_controller *hose;
- volatile void __iomem *addr;
-
- hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- out_8(addr, val);
- break;
- case 2:
- out_le16(addr, val);
- break;
- default:
- out_le32(addr, val);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops u3_agp_pci_ops =
-{
- .read = u3_agp_read_config,
- .write = u3_agp_write_config,
-};
-
-static unsigned long u3_ht_cfa0(u8 devfn, u8 off)
-{
- return (devfn << 8) | off;
-}
-
-static unsigned long u3_ht_cfa1(u8 bus, u8 devfn, u8 off)
-{
- return u3_ht_cfa0(devfn, off) + (bus << 16) + 0x01000000UL;
-}
-
-static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose,
- u8 bus, u8 devfn, u8 offset)
-{
- if (bus == hose->first_busno) {
- if (PCI_SLOT(devfn) == 0)
- return NULL;
- return hose->cfg_data + u3_ht_cfa0(devfn, offset);
- } else
- return hose->cfg_data + u3_ht_cfa1(bus, devfn, offset);
-}
-
-static int u3_ht_root_read_config(struct pci_controller *hose, u8 offset,
- int len, u32 *val)
-{
- volatile void __iomem *addr;
-
- addr = hose->cfg_addr;
- addr += ((offset & ~3) << 2) + (4 - len - (offset & 3));
-
- switch (len) {
- case 1:
- *val = in_8(addr);
- break;
- case 2:
- *val = in_be16(addr);
- break;
- default:
- *val = in_be32(addr);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int u3_ht_root_write_config(struct pci_controller *hose, u8 offset,
- int len, u32 val)
-{
- volatile void __iomem *addr;
-
- addr = hose->cfg_addr + ((offset & ~3) << 2) + (4 - len - (offset & 3));
-
- if (offset >= PCI_BASE_ADDRESS_0 && offset < PCI_CAPABILITY_LIST)
- return PCIBIOS_SUCCESSFUL;
-
- switch (len) {
- case 1:
- out_8(addr, val);
- break;
- case 2:
- out_be16(addr, val);
- break;
- default:
- out_be32(addr, val);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 *val)
-{
- struct pci_controller *hose;
- volatile void __iomem *addr;
-
- hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if (bus->number == hose->first_busno && devfn == PCI_DEVFN(0, 0))
- return u3_ht_root_read_config(hose, offset, len, val);
-
- if (offset > 0xff)
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- *val = in_8(addr);
- break;
- case 2:
- *val = in_le16(addr);
- break;
- default:
- *val = in_le32(addr);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 val)
-{
- struct pci_controller *hose;
- volatile void __iomem *addr;
-
- hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if (bus->number == hose->first_busno && devfn == PCI_DEVFN(0, 0))
- return u3_ht_root_write_config(hose, offset, len, val);
-
- if (offset > 0xff)
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- out_8(addr, val);
- break;
- case 2:
- out_le16(addr, val);
- break;
- default:
- out_le32(addr, val);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops u3_ht_pci_ops =
-{
- .read = u3_ht_read_config,
- .write = u3_ht_write_config,
-};
-
-static unsigned int u4_pcie_cfa0(unsigned int devfn, unsigned int off)
-{
- return (1 << PCI_SLOT(devfn)) |
- (PCI_FUNC(devfn) << 8) |
- ((off >> 8) << 28) |
- (off & 0xfcu);
-}
-
-static unsigned int u4_pcie_cfa1(unsigned int bus, unsigned int devfn,
- unsigned int off)
-{
- return (bus << 16) |
- (devfn << 8) |
- ((off >> 8) << 28) |
- (off & 0xfcu) | 1u;
-}
-
-static volatile void __iomem *u4_pcie_cfg_access(struct pci_controller* hose,
- u8 bus, u8 dev_fn, int offset)
-{
- unsigned int caddr;
-
- if (bus == hose->first_busno)
- caddr = u4_pcie_cfa0(dev_fn, offset);
- else
- caddr = u4_pcie_cfa1(bus, dev_fn, offset);
-
- /* Uninorth will return garbage if we don't read back the value ! */
- do {
- out_le32(hose->cfg_addr, caddr);
- } while (in_le32(hose->cfg_addr) != caddr);
-
- offset &= 0x03;
- return hose->cfg_data + offset;
-}
-
-static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 *val)
-{
- struct pci_controller *hose;
- volatile void __iomem *addr;
-
- hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset >= 0x1000)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- *val = in_8(addr);
- break;
- case 2:
- *val = in_le16(addr);
- break;
- default:
- *val = in_le32(addr);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 val)
-{
- struct pci_controller *hose;
- volatile void __iomem *addr;
-
- hose = pci_bus_to_host(bus);
- if (hose == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset >= 0x1000)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- out_8(addr, val);
- break;
- case 2:
- out_le16(addr, val);
- break;
- default:
- out_le32(addr, val);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops u4_pcie_pci_ops =
-{
- .read = u4_pcie_read_config,
- .write = u4_pcie_write_config,
-};
-
-static void __init setup_u3_agp(struct pci_controller* hose)
-{
- /* On G5, we move AGP up to high bus number so we don't need
- * to reassign bus numbers for HT. If we ever have P2P bridges
- * on AGP, we'll have to move pci_assign_all_buses to the
- * pci_controller structure so we enable it for AGP and not for
- * HT childs.
- * We hard code the address because of the different size of
- * the reg address cell, we shall fix that by killing struct
- * reg_property and using some accessor functions instead
- */
- hose->first_busno = 0xf0;
- hose->last_busno = 0xff;
- hose->ops = &u3_agp_pci_ops;
- hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
- hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
-
- u3_agp = hose;
-}
-
-static void __init setup_u4_pcie(struct pci_controller* hose)
-{
- /* We currently only implement the "non-atomic" config space, to
- * be optimised later.
- */
- hose->ops = &u4_pcie_pci_ops;
- hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
- hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
-
- u4_pcie = hose;
-}
-
-static void __init setup_u3_ht(struct pci_controller* hose)
-{
- hose->ops = &u3_ht_pci_ops;
-
- /* We hard code the address because of the different size of
- * the reg address cell, we shall fix that by killing struct
- * reg_property and using some accessor functions instead
- */
- hose->cfg_data = ioremap(0xf2000000, 0x02000000);
- hose->cfg_addr = ioremap(0xf8070000, 0x1000);
-
- hose->first_busno = 0;
- hose->last_busno = 0xef;
-
- u3_ht = hose;
-}
-
-static int __init maple_add_bridge(struct device_node *dev)
-{
- int len;
- struct pci_controller *hose;
- char* disp_name;
- const int *bus_range;
- int primary = 1;
-
- DBG("Adding PCI host bridge %pOF\n", dev);
-
- bus_range = of_get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %pOF, assume bus 0\n",
- dev);
- }
-
- hose = pcibios_alloc_controller(dev);
- if (hose == NULL)
- return -ENOMEM;
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
- hose->controller_ops = maple_pci_controller_ops;
-
- disp_name = NULL;
- if (of_device_is_compatible(dev, "u3-agp")) {
- setup_u3_agp(hose);
- disp_name = "U3-AGP";
- primary = 0;
- } else if (of_device_is_compatible(dev, "u3-ht")) {
- setup_u3_ht(hose);
- disp_name = "U3-HT";
- primary = 1;
- } else if (of_device_is_compatible(dev, "u4-pcie")) {
- setup_u4_pcie(hose);
- disp_name = "U4-PCIE";
- primary = 0;
- }
- printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
- disp_name, hose->first_busno, hose->last_busno);
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev, primary);
-
- /* Fixup "bus-range" OF property */
- fixup_bus_range(dev);
-
- /* Check for legacy IOs */
- isa_bridge_find_early(hose);
-
- /* create pci_dn's for DT nodes under this PHB */
- pci_devs_phb_init_dynamic(hose);
-
- return 0;
-}
-
-
-void maple_pci_irq_fixup(struct pci_dev *dev)
-{
- DBG(" -> maple_pci_irq_fixup\n");
-
- /* Fixup IRQ for PCIe host */
- if (u4_pcie != NULL && dev->bus->number == 0 &&
- pci_bus_to_host(dev->bus) == u4_pcie) {
- printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n");
- dev->irq = irq_create_mapping(NULL, 1);
- if (dev->irq)
- irq_set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
- }
-
- /* Hide AMD8111 IDE interrupt when in legacy mode so
- * the driver calls pci_get_legacy_ide_irq()
- */
- if (dev->vendor == PCI_VENDOR_ID_AMD &&
- dev->device == PCI_DEVICE_ID_AMD_8111_IDE &&
- (dev->class & 5) != 5) {
- dev->irq = 0;
- }
-
- DBG(" <- maple_pci_irq_fixup\n");
-}
-
-static int maple_pci_root_bridge_prepare(struct pci_host_bridge *bridge)
-{
- struct pci_controller *hose = pci_bus_to_host(bridge->bus);
- struct device_node *np, *child;
-
- if (hose != u3_agp)
- return 0;
-
- /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
- * assume there is no P2P bridge on the AGP bus, which should be a
- * safe assumptions hopefully.
- */
- np = hose->dn;
- PCI_DN(np)->busno = 0xf0;
- for_each_child_of_node(np, child)
- PCI_DN(child)->busno = 0xf0;
-
- return 0;
-}
-
-void __init maple_pci_init(void)
-{
- struct device_node *np, *root;
- struct device_node *ht = NULL;
-
- /* Probe root PCI hosts, that is on U3 the AGP host and the
- * HyperTransport host. That one is actually "kept" around
- * and actually added last as its resource management relies
- * on the AGP resources to have been setup first
- */
- root = of_find_node_by_path("/");
- if (root == NULL) {
- printk(KERN_CRIT "maple_find_bridges: can't find root of device tree\n");
- return;
- }
- for_each_child_of_node(root, np) {
- if (!of_node_is_type(np, "pci") && !of_node_is_type(np, "ht"))
- continue;
- if ((of_device_is_compatible(np, "u4-pcie") ||
- of_device_is_compatible(np, "u3-agp")) &&
- maple_add_bridge(np) == 0)
- of_node_get(np);
-
- if (of_device_is_compatible(np, "u3-ht")) {
- of_node_get(np);
- ht = np;
- }
- }
- of_node_put(root);
-
- /* Now setup the HyperTransport host if we found any
- */
- if (ht && maple_add_bridge(ht) != 0)
- of_node_put(ht);
-
- ppc_md.pcibios_root_bridge_prepare = maple_pci_root_bridge_prepare;
-
- /* Tell pci.c to not change any resource allocations. */
- pci_add_flags(PCI_PROBE_ONLY);
-}
-
-int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
-{
- struct device_node *np;
- unsigned int defirq = channel ? 15 : 14;
- unsigned int irq;
-
- if (pdev->vendor != PCI_VENDOR_ID_AMD ||
- pdev->device != PCI_DEVICE_ID_AMD_8111_IDE)
- return defirq;
-
- np = pci_device_to_OF_node(pdev);
- if (np == NULL) {
- printk("Failed to locate OF node for IDE %s\n",
- pci_name(pdev));
- return defirq;
- }
- irq = irq_of_parse_and_map(np, channel & 0x1);
- if (!irq) {
- printk("Failed to map onboard IDE interrupt for channel %d\n",
- channel);
- return defirq;
- }
- return irq;
-}
-
-static void quirk_ipr_msi(struct pci_dev *dev)
-{
- /* Something prevents MSIs from the IPR from working on Bimini,
- * and the driver has no smarts to recover. So disable MSI
- * on it for now. */
-
- if (machine_is(maple)) {
- dev->no_msi = 1;
- dev_info(&dev->dev, "Quirk disabled MSI\n");
- }
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
- quirk_ipr_msi);
-
-struct pci_controller_ops maple_pci_controller_ops = {
-};
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
deleted file mode 100644
index f329a03edf4a..000000000000
--- a/arch/powerpc/platforms/maple/setup.c
+++ /dev/null
@@ -1,363 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Maple (970 eval board) setup code
- *
- * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org),
- * IBM Corp.
- */
-
-#undef DEBUG
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/tty.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/vt_kern.h>
-#include <linux/console.h>
-#include <linux/pci.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/serial.h>
-#include <linux/smp.h>
-#include <linux/bitops.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/memblock.h>
-
-#include <asm/processor.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/iommu.h>
-#include <asm/machdep.h>
-#include <asm/dma.h>
-#include <asm/cputable.h>
-#include <asm/time.h>
-#include <asm/mpic.h>
-#include <asm/rtas.h>
-#include <asm/udbg.h>
-#include <asm/nvram.h>
-
-#include "maple.h"
-
-#ifdef DEBUG
-#define DBG(fmt...) udbg_printf(fmt)
-#else
-#define DBG(fmt...)
-#endif
-
-static unsigned long maple_find_nvram_base(void)
-{
- struct device_node *rtcs;
- unsigned long result = 0;
-
- /* find NVRAM device */
- rtcs = of_find_compatible_node(NULL, "nvram", "AMD8111");
- if (rtcs) {
- struct resource r;
- if (of_address_to_resource(rtcs, 0, &r)) {
- printk(KERN_EMERG "Maple: Unable to translate NVRAM"
- " address\n");
- goto bail;
- }
- if (!(r.flags & IORESOURCE_IO)) {
- printk(KERN_EMERG "Maple: NVRAM address isn't PIO!\n");
- goto bail;
- }
- result = r.start;
- } else
- printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
- bail:
- of_node_put(rtcs);
- return result;
-}
-
-static void __noreturn maple_restart(char *cmd)
-{
- unsigned int maple_nvram_base;
- const unsigned int *maple_nvram_offset, *maple_nvram_command;
- struct device_node *sp;
-
- maple_nvram_base = maple_find_nvram_base();
- if (maple_nvram_base == 0)
- goto fail;
-
- /* find service processor device */
- sp = of_find_node_by_name(NULL, "service-processor");
- if (!sp) {
- printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
- goto fail;
- }
- maple_nvram_offset = of_get_property(sp, "restart-addr", NULL);
- maple_nvram_command = of_get_property(sp, "restart-value", NULL);
- of_node_put(sp);
-
- /* send command */
- outb_p(*maple_nvram_command, maple_nvram_base + *maple_nvram_offset);
- for (;;) ;
- fail:
- printk(KERN_EMERG "Maple: Manual Restart Required\n");
- for (;;) ;
-}
-
-static void __noreturn maple_power_off(void)
-{
- unsigned int maple_nvram_base;
- const unsigned int *maple_nvram_offset, *maple_nvram_command;
- struct device_node *sp;
-
- maple_nvram_base = maple_find_nvram_base();
- if (maple_nvram_base == 0)
- goto fail;
-
- /* find service processor device */
- sp = of_find_node_by_name(NULL, "service-processor");
- if (!sp) {
- printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
- goto fail;
- }
- maple_nvram_offset = of_get_property(sp, "power-off-addr", NULL);
- maple_nvram_command = of_get_property(sp, "power-off-value", NULL);
- of_node_put(sp);
-
- /* send command */
- outb_p(*maple_nvram_command, maple_nvram_base + *maple_nvram_offset);
- for (;;) ;
- fail:
- printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
- for (;;) ;
-}
-
-static void __noreturn maple_halt(void)
-{
- maple_power_off();
-}
-
-#ifdef CONFIG_SMP
-static struct smp_ops_t maple_smp_ops = {
- .probe = smp_mpic_probe,
- .message_pass = smp_mpic_message_pass,
- .kick_cpu = smp_generic_kick_cpu,
- .setup_cpu = smp_mpic_setup_cpu,
- .give_timebase = smp_generic_give_timebase,
- .take_timebase = smp_generic_take_timebase,
-};
-#endif /* CONFIG_SMP */
-
-static void __init maple_use_rtas_reboot_and_halt_if_present(void)
-{
- if (rtas_function_implemented(RTAS_FN_SYSTEM_REBOOT) &&
- rtas_function_implemented(RTAS_FN_POWER_OFF)) {
- ppc_md.restart = rtas_restart;
- pm_power_off = rtas_power_off;
- ppc_md.halt = rtas_halt;
- }
-}
-
-static void __init maple_setup_arch(void)
-{
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000;
-
- /* Setup SMP callback */
-#ifdef CONFIG_SMP
- smp_ops = &maple_smp_ops;
-#endif
- maple_use_rtas_reboot_and_halt_if_present();
-
- printk(KERN_DEBUG "Using native/NAP idle loop\n");
-
- mmio_nvram_init();
-}
-
-/*
- * This is almost identical to pSeries and CHRP. We need to make that
- * code generic at one point, with appropriate bits in the device-tree to
- * identify the presence of an HT APIC
- */
-static void __init maple_init_IRQ(void)
-{
- struct device_node *root, *np, *mpic_node = NULL;
- const unsigned int *opprop;
- unsigned long openpic_addr = 0;
- int naddr, n, i, opplen, has_isus = 0;
- struct mpic *mpic;
- unsigned int flags = 0;
-
- /* Locate MPIC in the device-tree. Note that there is a bug
- * in Maple device-tree where the type of the controller is
- * open-pic and not interrupt-controller
- */
-
- for_each_node_by_type(np, "interrupt-controller")
- if (of_device_is_compatible(np, "open-pic")) {
- mpic_node = np;
- break;
- }
- if (mpic_node == NULL)
- for_each_node_by_type(np, "open-pic") {
- mpic_node = np;
- break;
- }
- if (mpic_node == NULL) {
- printk(KERN_ERR
- "Failed to locate the MPIC interrupt controller\n");
- return;
- }
-
- /* Find address list in /platform-open-pic */
- root = of_find_node_by_path("/");
- naddr = of_n_addr_cells(root);
- opprop = of_get_property(root, "platform-open-pic", &opplen);
- if (opprop) {
- openpic_addr = of_read_number(opprop, naddr);
- has_isus = (opplen > naddr);
- printk(KERN_DEBUG "OpenPIC addr: %lx, has ISUs: %d\n",
- openpic_addr, has_isus);
- }
-
- BUG_ON(openpic_addr == 0);
-
- /* Check for a big endian MPIC */
- if (of_property_read_bool(np, "big-endian"))
- flags |= MPIC_BIG_ENDIAN;
-
- /* XXX Maple specific bits */
- flags |= MPIC_U3_HT_IRQS;
- /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
- flags |= MPIC_BIG_ENDIAN;
-
- /* Setup the openpic driver. More device-tree junks, we hard code no
- * ISUs for now. I'll have to revisit some stuffs with the folks doing
- * the firmware for those
- */
- mpic = mpic_alloc(mpic_node, openpic_addr, flags,
- /*has_isus ? 16 :*/ 0, 0, " MPIC ");
- BUG_ON(mpic == NULL);
-
- /* Add ISUs */
- opplen /= sizeof(u32);
- for (n = 0, i = naddr; i < opplen; i += naddr, n++) {
- unsigned long isuaddr = of_read_number(opprop + i, naddr);
- mpic_assign_isu(mpic, n, isuaddr);
- }
-
- /* All ISUs are setup, complete initialization */
- mpic_init(mpic);
- ppc_md.get_irq = mpic_get_irq;
- of_node_put(mpic_node);
- of_node_put(root);
-}
-
-static void __init maple_progress(char *s, unsigned short hex)
-{
- printk("*** %04x : %s\n", hex, s ? s : "");
-}
-
-
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init maple_probe(void)
-{
- if (!of_machine_is_compatible("Momentum,Maple") &&
- !of_machine_is_compatible("Momentum,Apache"))
- return 0;
-
- pm_power_off = maple_power_off;
-
- iommu_init_early_dart(&maple_pci_controller_ops);
-
- return 1;
-}
-
-#ifdef CONFIG_EDAC
-/*
- * Register a platform device for CPC925 memory controller on
- * all boards with U3H (CPC925) bridge.
- */
-static int __init maple_cpc925_edac_setup(void)
-{
- struct platform_device *pdev;
- struct device_node *np = NULL;
- struct resource r;
- int ret;
- volatile void __iomem *mem;
- u32 rev;
-
- np = of_find_node_by_type(NULL, "memory-controller");
- if (!np) {
- printk(KERN_ERR "%s: Unable to find memory-controller node\n",
- __func__);
- return -ENODEV;
- }
-
- ret = of_address_to_resource(np, 0, &r);
- of_node_put(np);
-
- if (ret < 0) {
- printk(KERN_ERR "%s: Unable to get memory-controller reg\n",
- __func__);
- return -ENODEV;
- }
-
- mem = ioremap(r.start, resource_size(&r));
- if (!mem) {
- printk(KERN_ERR "%s: Unable to map memory-controller memory\n",
- __func__);
- return -ENOMEM;
- }
-
- rev = __raw_readl(mem);
- iounmap(mem);
-
- if (rev < 0x34 || rev > 0x3f) { /* U3H */
- printk(KERN_ERR "%s: Non-CPC925(U3H) bridge revision: %02x\n",
- __func__, rev);
- return 0;
- }
-
- pdev = platform_device_register_simple("cpc925_edac", 0, &r, 1);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- printk(KERN_INFO "%s: CPC925 platform device created\n", __func__);
-
- return 0;
-}
-machine_device_initcall(maple, maple_cpc925_edac_setup);
-#endif
-
-define_machine(maple) {
- .name = "Maple",
- .probe = maple_probe,
- .setup_arch = maple_setup_arch,
- .discover_phbs = maple_pci_init,
- .init_IRQ = maple_init_IRQ,
- .pci_irq_fixup = maple_pci_irq_fixup,
- .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
- .restart = maple_restart,
- .halt = maple_halt,
- .get_boot_time = maple_get_boot_time,
- .set_rtc_time = maple_set_rtc_time,
- .get_rtc_time = maple_get_rtc_time,
- .progress = maple_progress,
- .power_save = power4_idle,
-};
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c
deleted file mode 100644
index 91606411d2e0..000000000000
--- a/arch/powerpc/platforms/maple/time.c
+++ /dev/null
@@ -1,170 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org),
- * IBM Corp.
- */
-
-#undef DEBUG
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
-#include <linux/bcd.h>
-#include <linux/of_address.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-
-#include "maple.h"
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-static int maple_rtc_addr;
-
-static int maple_clock_read(int addr)
-{
- outb_p(addr, maple_rtc_addr);
- return inb_p(maple_rtc_addr+1);
-}
-
-static void maple_clock_write(unsigned long val, int addr)
-{
- outb_p(addr, maple_rtc_addr);
- outb_p(val, maple_rtc_addr+1);
-}
-
-void maple_get_rtc_time(struct rtc_time *tm)
-{
- do {
- tm->tm_sec = maple_clock_read(RTC_SECONDS);
- tm->tm_min = maple_clock_read(RTC_MINUTES);
- tm->tm_hour = maple_clock_read(RTC_HOURS);
- tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH);
- tm->tm_mon = maple_clock_read(RTC_MONTH);
- tm->tm_year = maple_clock_read(RTC_YEAR);
- } while (tm->tm_sec != maple_clock_read(RTC_SECONDS));
-
- if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
- || RTC_ALWAYS_BCD) {
- tm->tm_sec = bcd2bin(tm->tm_sec);
- tm->tm_min = bcd2bin(tm->tm_min);
- tm->tm_hour = bcd2bin(tm->tm_hour);
- tm->tm_mday = bcd2bin(tm->tm_mday);
- tm->tm_mon = bcd2bin(tm->tm_mon);
- tm->tm_year = bcd2bin(tm->tm_year);
- }
- if ((tm->tm_year + 1900) < 1970)
- tm->tm_year += 100;
-
- tm->tm_wday = -1;
-}
-
-int maple_set_rtc_time(struct rtc_time *tm)
-{
- unsigned char save_control, save_freq_select;
- int sec, min, hour, mon, mday, year;
-
- spin_lock(&rtc_lock);
-
- save_control = maple_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
- maple_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = maple_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
-
- maple_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- sec = tm->tm_sec;
- min = tm->tm_min;
- hour = tm->tm_hour;
- mon = tm->tm_mon;
- mday = tm->tm_mday;
- year = tm->tm_year;
-
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- sec = bin2bcd(sec);
- min = bin2bcd(min);
- hour = bin2bcd(hour);
- mon = bin2bcd(mon);
- mday = bin2bcd(mday);
- year = bin2bcd(year);
- }
- maple_clock_write(sec, RTC_SECONDS);
- maple_clock_write(min, RTC_MINUTES);
- maple_clock_write(hour, RTC_HOURS);
- maple_clock_write(mon, RTC_MONTH);
- maple_clock_write(mday, RTC_DAY_OF_MONTH);
- maple_clock_write(year, RTC_YEAR);
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- maple_clock_write(save_control, RTC_CONTROL);
- maple_clock_write(save_freq_select, RTC_FREQ_SELECT);
-
- spin_unlock(&rtc_lock);
-
- return 0;
-}
-
-static struct resource rtc_iores = {
- .name = "rtc",
- .flags = IORESOURCE_IO | IORESOURCE_BUSY,
-};
-
-time64_t __init maple_get_boot_time(void)
-{
- struct rtc_time tm;
- struct device_node *rtcs;
-
- rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00");
- if (rtcs) {
- struct resource r;
- if (of_address_to_resource(rtcs, 0, &r)) {
- printk(KERN_EMERG "Maple: Unable to translate RTC"
- " address\n");
- goto bail;
- }
- if (!(r.flags & IORESOURCE_IO)) {
- printk(KERN_EMERG "Maple: RTC address isn't PIO!\n");
- goto bail;
- }
- maple_rtc_addr = r.start;
- printk(KERN_INFO "Maple: Found RTC at IO 0x%x\n",
- maple_rtc_addr);
- }
- bail:
- of_node_put(rtcs);
- if (maple_rtc_addr == 0) {
- maple_rtc_addr = RTC_PORT(0); /* legacy address */
- printk(KERN_INFO "Maple: No device node for RTC, assuming "
- "legacy address (0x%x)\n", maple_rtc_addr);
- }
-
- rtc_iores.start = maple_rtc_addr;
- rtc_iores.end = maple_rtc_addr + 7;
- request_resource(&ioport_resource, &rtc_iores);
-
- maple_get_rtc_time(&tm);
- return rtc_tm_to_time64(&tm);
-}
-
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index 12bc01353bd3..79741370c40c 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -57,18 +57,10 @@ struct backlight_device *pmac_backlight;
int pmac_has_backlight_type(const char *type)
{
struct device_node* bk_node = of_find_node_by_name(NULL, "backlight");
+ int i = of_property_match_string(bk_node, "backlight-control", type);
- if (bk_node) {
- const char *prop = of_get_property(bk_node,
- "backlight-control", NULL);
- if (prop && strncmp(prop, type, strlen(type)) == 0) {
- of_node_put(bk_node);
- return 1;
- }
- of_node_put(bk_node);
- }
-
- return 0;
+ of_node_put(bk_node);
+ return i >= 0;
}
static void pmac_backlight_key_worker(struct work_struct *work)
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index d21b681f52fb..09e7fe24fac1 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -35,7 +35,7 @@
#include <asm/ptrace.h>
#include <linux/atomic.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/sections.h>
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index ad41dffe4d92..d98b933e4984 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -18,7 +18,7 @@
#include <asm/opal.h>
#include <asm/cputhreads.h>
#include <asm/cpuidle.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/smp.h>
#include <asm/runlatch.h>
#include <asm/dbell.h>
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 8f14f0581a21..8f41ef364fc6 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -28,7 +28,7 @@
#include <asm/xive.h>
#include <asm/opal.h>
#include <asm/runlatch.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/dbell.h>
#include <asm/kvm_ppc.h>
#include <asm/ppc-opcode.h>
@@ -36,6 +36,7 @@
#include <asm/kexec.h>
#include <asm/reg.h>
#include <asm/powernv.h>
+#include <asm/systemcfg.h>
#include "powernv.h"
@@ -136,7 +137,9 @@ static int pnv_smp_cpu_disable(void)
* the generic fixup_irqs. --BenH.
*/
set_cpu_online(cpu, false);
- vdso_data->processorCount--;
+#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
+ systemcfg->processorCount--;
+#endif
if (cpu == boot_cpuid)
boot_cpuid = cpumask_any(cpu_online_mask);
if (xive_enabled())
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
index b18e1c92e554..61722133eb2d 100644
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -178,7 +178,7 @@ fail_malloc:
return result;
}
-static int __ref ps3_setup_uhc_device(
+static int __init ps3_setup_uhc_device(
const struct ps3_repository_device *repo, enum ps3_match_id match_id,
enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
{
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 49871427f599..af3fe9f04f24 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -378,9 +378,9 @@ int ps3_send_event_locally(unsigned int virq)
/**
* ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
+ * @dev: The system bus device instance.
* @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
* serviced on.
- * @dev: The system bus device instance.
* @virq: The assigned Linux virq.
*
* An event irq represents a virtual device interrupt. The interrupt_id
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index 1abe33fbe529..b8c030eab138 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -940,7 +940,7 @@ int __init ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
/**
* ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
- * address: lpar address of cell_ext_os_area
+ * @lpar_addr: lpar address of cell_ext_os_area
* @size: size of cell_ext_os_area
*/
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index b9a7d9bae687..afbaabf182d0 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -453,10 +453,9 @@ static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
char *buf)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
- int len = snprintf(buf, PAGE_SIZE, "ps3:%d:%d\n", dev->match_id,
- dev->match_sub_id);
- return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+ return sysfs_emit(buf, "ps3:%d:%d\n", dev->match_id,
+ dev->match_sub_id);
}
static DEVICE_ATTR_RO(modalias);
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index afc0f6a61337..42fc66e97539 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -140,6 +140,20 @@ config HV_PERF_CTRS
If unsure, select Y.
+config VPA_PMU
+ tristate "VPA PMU events"
+ depends on KVM_BOOK3S_64_HV && HV_PERF_CTRS
+ help
+ Enable access to the VPA PMU counters via perf. This enables
+ code that support measurement for KVM on PowerVM(KoP) feature.
+ PAPR hypervisor has introduced three new counters in the VPA area
+ of LPAR CPUs for KVM L2 guest observability. Two for context switches
+ from host to guest and vice versa, and one counter for getting
+ the total time spent inside the KVM guest. This config enables code
+ that access these software counters via perf.
+
+ If unsure, Select N.
+
config IBMVIO
depends on PPC_PSERIES
bool
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index 8cb9d36ea491..f293588b8c7b 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -191,7 +191,7 @@ static int dtl_enable(struct dtl *dtl)
return -EBUSY;
/* ensure there are no other conflicting dtl users */
- if (!read_trylock(&dtl_access_lock))
+ if (!down_read_trylock(&dtl_access_lock))
return -EBUSY;
n_entries = dtl_buf_entries;
@@ -199,7 +199,7 @@ static int dtl_enable(struct dtl *dtl)
if (!buf) {
printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
__func__, dtl->cpu);
- read_unlock(&dtl_access_lock);
+ up_read(&dtl_access_lock);
return -ENOMEM;
}
@@ -217,7 +217,7 @@ static int dtl_enable(struct dtl *dtl)
spin_unlock(&dtl->lock);
if (rc) {
- read_unlock(&dtl_access_lock);
+ up_read(&dtl_access_lock);
kmem_cache_free(dtl_cache, buf);
}
@@ -232,7 +232,7 @@ static void dtl_disable(struct dtl *dtl)
dtl->buf = NULL;
dtl->buf_entries = 0;
spin_unlock(&dtl->lock);
- read_unlock(&dtl_access_lock);
+ up_read(&dtl_access_lock);
}
/* file interface */
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 6838a0fcda29..bc6926dbf148 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -33,6 +33,7 @@
#include <asm/xive.h>
#include <asm/plpar_wrappers.h>
#include <asm/topology.h>
+#include <asm/systemcfg.h>
#include "pseries.h"
@@ -83,7 +84,9 @@ static int pseries_cpu_disable(void)
int cpu = smp_processor_id();
set_cpu_online(cpu, false);
- vdso_data->processorCount--;
+#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
+ systemcfg->processorCount--;
+#endif
/*fix boot_cpuid here*/
if (cpu == boot_cpuid)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index c1d8bee8f701..6a415febc53b 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/jump_label.h>
#include <linux/delay.h>
+#include <linux/seq_file.h>
#include <linux/stop_machine.h>
#include <linux/spinlock.h>
#include <linux/cpuhotplug.h>
@@ -169,7 +170,7 @@ struct vcpu_dispatch_data {
*/
#define NR_CPUS_H NR_CPUS
-DEFINE_RWLOCK(dtl_access_lock);
+DECLARE_RWSEM(dtl_access_lock);
static DEFINE_PER_CPU(struct vcpu_dispatch_data, vcpu_disp_data);
static DEFINE_PER_CPU(u64, dtl_entry_ridx);
static DEFINE_PER_CPU(struct dtl_worker, dtl_workers);
@@ -463,7 +464,7 @@ static int dtl_worker_enable(unsigned long *time_limit)
{
int rc = 0, state;
- if (!write_trylock(&dtl_access_lock)) {
+ if (!down_write_trylock(&dtl_access_lock)) {
rc = -EBUSY;
goto out;
}
@@ -479,7 +480,7 @@ static int dtl_worker_enable(unsigned long *time_limit)
pr_err("vcpudispatch_stats: unable to setup workqueue for DTL processing\n");
free_dtl_buffers(time_limit);
reset_global_dtl_mask();
- write_unlock(&dtl_access_lock);
+ up_write(&dtl_access_lock);
rc = -EINVAL;
goto out;
}
@@ -494,7 +495,7 @@ static void dtl_worker_disable(unsigned long *time_limit)
cpuhp_remove_state(dtl_worker_state);
free_dtl_buffers(time_limit);
reset_global_dtl_mask();
- write_unlock(&dtl_access_lock);
+ up_write(&dtl_access_lock);
}
static ssize_t vcpudispatch_stats_write(struct file *file, const char __user *p,
diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c
index 62da20f9700a..cc22924f159f 100644
--- a/arch/powerpc/platforms/pseries/lparcfg.c
+++ b/arch/powerpc/platforms/pseries/lparcfg.c
@@ -29,7 +29,6 @@
#include <asm/firmware.h>
#include <asm/rtas.h>
#include <asm/time.h>
-#include <asm/vdso_datapage.h>
#include <asm/vio.h>
#include <asm/mmu.h>
#include <asm/machdep.h>
@@ -530,7 +529,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL);
if (lrdrp == NULL) {
- partition_potential_processors = vdso_data->processorCount;
+ partition_potential_processors = num_possible_cpus();
} else {
partition_potential_processors = be32_to_cpup(lrdrp + 4);
}
@@ -553,7 +552,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
} else { /* non SPLPAR case */
seq_printf(m, "system_active_processors=%d\n",
- partition_potential_processors);
+ partition_active_processors);
seq_printf(m, "system_potential_processors=%d\n",
partition_potential_processors);
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 6dfb55b52d36..fdc2f7f38dc9 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -9,6 +9,7 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/msi.h>
+#include <linux/seq_file.h>
#include <asm/rtas.h>
#include <asm/hw_irq.h>
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 9e297f88adc5..f84ac9fbe203 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioport.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/ndctl.h>
#include <linux/sched.h>
diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
index 4a595493d28a..b1667ed05f98 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -683,7 +683,7 @@ void __init plpks_early_init_devtree(void)
out:
fdt_nop_property(fdt, chosen_node, "ibm,plpks-pw");
// Since we've cleared the password, we must update the FDT checksum
- early_init_dt_verify(fdt);
+ early_init_dt_verify(fdt, __pa(fdt));
}
static __init int pseries_plpks_init(void)
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index c597711ef20a..db99725e752b 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -39,7 +39,7 @@
#include <asm/xive.h>
#include <asm/dbell.h>
#include <asm/plpar_wrappers.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/svm.h>
#include <asm/kvm_guest.h>
diff --git a/arch/powerpc/platforms/pseries/svm.c b/arch/powerpc/platforms/pseries/svm.c
index 3b4045d508ec..384c9dc1899a 100644
--- a/arch/powerpc/platforms/pseries/svm.c
+++ b/arch/powerpc/platforms/pseries/svm.c
@@ -8,6 +8,7 @@
#include <linux/mm.h>
#include <linux/memblock.h>
+#include <linux/mem_encrypt.h>
#include <linux/cc_platform.h>
#include <asm/machdep.h>
#include <asm/svm.h>
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
index fa01818c1972..a6c388bdf5d0 100644
--- a/arch/powerpc/sysdev/xive/common.c
+++ b/arch/powerpc/sysdev/xive/common.c
@@ -726,7 +726,7 @@ static int xive_irq_set_affinity(struct irq_data *d,
pr_debug("%s: irq %d/0x%x\n", __func__, d->irq, hw_irq);
/* Is this valid ? */
- if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids)
+ if (!cpumask_intersects(cpumask, cpu_online_mask))
return -EINVAL;
/*
diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c
index f2fa985a2c77..5aedbe3e8e6a 100644
--- a/arch/powerpc/sysdev/xive/spapr.c
+++ b/arch/powerpc/sysdev/xive/spapr.c
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/irq.h>
+#include <linux/seq_file.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/init.h>
diff --git a/scripts/selinux/genheaders/.gitignore b/arch/powerpc/tools/.gitignore
index 5fcadd307908..ec380a14a09a 100644
--- a/scripts/selinux/genheaders/.gitignore
+++ b/arch/powerpc/tools/.gitignore
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-genheaders
+/vmlinux.arch.S
diff --git a/arch/powerpc/tools/Makefile b/arch/powerpc/tools/Makefile
new file mode 100644
index 000000000000..e1f7afcd9fdf
--- /dev/null
+++ b/arch/powerpc/tools/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+quiet_cmd_gen_ftrace_ool_stubs = GEN $@
+ cmd_gen_ftrace_ool_stubs = $< "$(CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE)" "$(CONFIG_64BIT)" \
+ "$(OBJDUMP)" vmlinux.o $@
+
+$(obj)/vmlinux.arch.S: $(src)/ftrace-gen-ool-stubs.sh vmlinux.o FORCE
+ $(call if_changed,gen_ftrace_ool_stubs)
+
+targets += vmlinux.arch.S
diff --git a/arch/powerpc/tools/ftrace-gen-ool-stubs.sh b/arch/powerpc/tools/ftrace-gen-ool-stubs.sh
new file mode 100755
index 000000000000..bac186bdf64a
--- /dev/null
+++ b/arch/powerpc/tools/ftrace-gen-ool-stubs.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Error out on error
+set -e
+
+num_ool_stubs_text_builtin="$1"
+is_64bit="$2"
+objdump="$3"
+vmlinux_o="$4"
+arch_vmlinux_S="$5"
+
+RELOCATION=R_PPC64_ADDR64
+if [ -z "$is_64bit" ]; then
+ RELOCATION=R_PPC_ADDR32
+fi
+
+num_ool_stubs_total=$($objdump -r -j __patchable_function_entries "$vmlinux_o" |
+ grep -c "$RELOCATION")
+num_ool_stubs_inittext=$($objdump -r -j __patchable_function_entries "$vmlinux_o" |
+ grep -e ".init.text" -e ".text.startup" | grep -c "$RELOCATION")
+num_ool_stubs_text=$((num_ool_stubs_total - num_ool_stubs_inittext))
+
+if [ "$num_ool_stubs_text" -gt "$num_ool_stubs_text_builtin" ]; then
+ num_ool_stubs_text_end=$((num_ool_stubs_text - num_ool_stubs_text_builtin))
+else
+ num_ool_stubs_text_end=0
+fi
+
+cat > "$arch_vmlinux_S" <<EOF
+#include <asm/asm-offsets.h>
+#include <asm/ppc_asm.h>
+#include <linux/linkage.h>
+
+.pushsection .tramp.ftrace.text,"aw"
+SYM_DATA(ftrace_ool_stub_text_end_count, .long $num_ool_stubs_text_end)
+
+SYM_START(ftrace_ool_stub_text_end, SYM_L_GLOBAL, .balign SZL)
+#if $num_ool_stubs_text_end
+ .space $num_ool_stubs_text_end * FTRACE_OOL_STUB_SIZE
+#endif
+SYM_CODE_END(ftrace_ool_stub_text_end)
+.popsection
+
+.pushsection .tramp.ftrace.init,"aw"
+SYM_DATA(ftrace_ool_stub_inittext_count, .long $num_ool_stubs_inittext)
+
+SYM_START(ftrace_ool_stub_inittext, SYM_L_GLOBAL, .balign SZL)
+ .space $num_ool_stubs_inittext * FTRACE_OOL_STUB_SIZE
+SYM_CODE_END(ftrace_ool_stub_inittext)
+.popsection
+EOF
diff --git a/arch/powerpc/tools/ftrace_check.sh b/arch/powerpc/tools/ftrace_check.sh
new file mode 100755
index 000000000000..405e7e306617
--- /dev/null
+++ b/arch/powerpc/tools/ftrace_check.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# This script checks vmlinux to ensure that all functions can call ftrace_caller() either directly,
+# or through the stub, ftrace_tramp_text, at the end of kernel text.
+
+# Error out if any command fails
+set -e
+
+# Allow for verbose output
+if [ "$V" = "1" ]; then
+ set -x
+fi
+
+if [ $# -lt 2 ]; then
+ echo "$0 [path to nm] [path to vmlinux]" 1>&2
+ exit 1
+fi
+
+# Have Kbuild supply the path to nm so we handle cross compilation.
+nm="$1"
+vmlinux="$2"
+
+stext_addr=$($nm "$vmlinux" | grep -e " [TA] _stext$" | \
+ cut -d' ' -f1 | tr '[:lower:]' '[:upper:]')
+ftrace_caller_addr=$($nm "$vmlinux" | grep -e " T ftrace_caller$" | \
+ cut -d' ' -f1 | tr '[:lower:]' '[:upper:]')
+ftrace_tramp_addr=$($nm "$vmlinux" | grep -e " T ftrace_tramp_text$" | \
+ cut -d' ' -f1 | tr '[:lower:]' '[:upper:]')
+
+ftrace_caller_offset=$(echo "ibase=16;$ftrace_caller_addr - $stext_addr" | bc)
+ftrace_tramp_offset=$(echo "ibase=16;$ftrace_tramp_addr - $ftrace_caller_addr" | bc)
+sz_32m=$(printf "%d" 0x2000000)
+sz_64m=$(printf "%d" 0x4000000)
+
+# ftrace_caller - _stext < 32M
+if [ "$ftrace_caller_offset" -ge "$sz_32m" ]; then
+ echo "ERROR: ftrace_caller (0x$ftrace_caller_addr) is beyond 32MiB of _stext" 1>&2
+ echo "ERROR: consider disabling CONFIG_FUNCTION_TRACER, or reducing the size \
+ of kernel text" 1>&2
+ exit 1
+fi
+
+# ftrace_tramp_text - ftrace_caller < 64M
+if [ "$ftrace_tramp_offset" -ge "$sz_64m" ]; then
+ echo "ERROR: kernel text extends beyond 64MiB from ftrace_caller" 1>&2
+ echo "ERROR: consider disabling CONFIG_FUNCTION_TRACER, or reducing the size \
+ of kernel text" 1>&2
+ exit 1
+fi
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index e6cddbb2305f..f4e841a36458 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -50,7 +50,7 @@
#include <asm/xive.h>
#include <asm/opal.h>
#include <asm/firmware.h>
-#include <asm/code-patching.h>
+#include <asm/text-patching.h>
#include <asm/sections.h>
#include <asm/inst.h>
#include <asm/interrupt.h>
@@ -3662,7 +3662,7 @@ symbol_lookup(void)
int type = inchar();
unsigned long addr, cpu;
void __percpu *ptr = NULL;
- static char tmp[64];
+ static char tmp[KSYM_NAME_LEN];
switch (type) {
case 'a':
@@ -3671,7 +3671,7 @@ symbol_lookup(void)
termch = 0;
break;
case 's':
- getstring(tmp, 64);
+ getstring(tmp, KSYM_NAME_LEN);
if (setjmp(bus_error_jmp) == 0) {
catch_memory_errors = 1;
sync();
@@ -3686,7 +3686,7 @@ symbol_lookup(void)
termch = 0;
break;
case 'p':
- getstring(tmp, 64);
+ getstring(tmp, KSYM_NAME_LEN);
if (setjmp(bus_error_jmp) == 0) {
catch_memory_errors = 1;
sync();
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index f4c570538d55..d4a7ca0388c0 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -32,6 +32,7 @@ config RISCV
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
+ select ARCH_HAS_HW_PTE_YOUNG
select ARCH_HAS_KCOV
select ARCH_HAS_KERNEL_FPU_SUPPORT if 64BIT && FPU
select ARCH_HAS_MEMBARRIER_CALLBACKS
@@ -39,6 +40,7 @@ config RISCV
select ARCH_HAS_MMIOWB
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PMEM_API
+ select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PREPARE_SYNC_CORE_CMD
select ARCH_HAS_PTE_DEVMAP if 64BIT && MMU
select ARCH_HAS_PTE_SPECIAL
@@ -50,7 +52,7 @@ config RISCV
select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN
- select ARCH_HAS_VDSO_DATA
+ select ARCH_HAS_VDSO_TIME_DATA
select ARCH_KEEP_MEMBLOCK if ACPI
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
@@ -82,6 +84,7 @@ config RISCV
select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP
select ARCH_WANTS_NO_INSTR
select ARCH_WANTS_THP_SWAP if HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ select ARCH_WEAK_RELEASE_ACQUIRE if ARCH_USE_QUEUED_SPINLOCKS
select BINFMT_FLAT_NO_DATA_START_OFFSET if !MMU
select BUILDTIME_TABLE_SORT if MMU
select CLINT_TIMER if RISCV_M_MODE
@@ -115,6 +118,7 @@ config RISCV
select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
select HARDIRQS_SW_RESEND
select HAS_IOPORT if MMU
+ select HAVE_ALIGNED_STRUCT_PAGE
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP
select HAVE_ARCH_HUGE_VMAP if MMU && 64BIT
@@ -506,6 +510,39 @@ config NODES_SHIFT
Specify the maximum number of NUMA Nodes available on the target
system. Increases memory reserved to accommodate various tables.
+choice
+ prompt "RISC-V spinlock type"
+ default RISCV_COMBO_SPINLOCKS
+
+config RISCV_TICKET_SPINLOCKS
+ bool "Using ticket spinlock"
+
+config RISCV_QUEUED_SPINLOCKS
+ bool "Using queued spinlock"
+ depends on SMP && MMU && NONPORTABLE
+ select ARCH_USE_QUEUED_SPINLOCKS
+ help
+ The queued spinlock implementation requires the forward progress
+ guarantee of cmpxchg()/xchg() atomic operations: CAS with Zabha or
+ LR/SC with Ziccrse provide such guarantee.
+
+ Select this if and only if Zabha or Ziccrse is available on your
+ platform, RISCV_QUEUED_SPINLOCKS must not be selected for platforms
+ without one of those extensions.
+
+ If unsure, select RISCV_COMBO_SPINLOCKS, which will use qspinlocks
+ when supported and otherwise ticket spinlocks.
+
+config RISCV_COMBO_SPINLOCKS
+ bool "Using combo spinlock"
+ depends on SMP && MMU
+ select ARCH_USE_QUEUED_SPINLOCKS
+ help
+ Embed both queued spinlock and ticket lock so that the spinlock
+ implementation can be chosen at runtime.
+
+endchoice
+
config RISCV_ALTERNATIVE
bool
depends on !XIP_KERNEL
@@ -531,6 +568,17 @@ config RISCV_ISA_C
If you don't know what to do here, say Y.
+config RISCV_ISA_SUPM
+ bool "Supm extension for userspace pointer masking"
+ depends on 64BIT
+ default y
+ help
+ Add support for pointer masking in userspace (Supm) when the
+ underlying hardware extension (Smnpm or Ssnpm) is detected at boot.
+
+ If this option is disabled, userspace will be unable to use
+ the prctl(PR_{SET,GET}_TAGGED_ADDR_CTRL) API.
+
config RISCV_ISA_SVNAPOT
bool "Svnapot extension support for supervisor mode NAPOT pages"
depends on 64BIT && MMU
@@ -632,6 +680,40 @@ config RISCV_ISA_ZAWRS
use of these instructions in the kernel when the Zawrs extension is
detected at boot.
+config TOOLCHAIN_HAS_ZABHA
+ bool
+ default y
+ depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zabha)
+ depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zabha)
+ depends on AS_HAS_OPTION_ARCH
+
+config RISCV_ISA_ZABHA
+ bool "Zabha extension support for atomic byte/halfword operations"
+ depends on TOOLCHAIN_HAS_ZABHA
+ depends on RISCV_ALTERNATIVE
+ default y
+ help
+ Enable the use of the Zabha ISA-extension to implement kernel
+ byte/halfword atomic memory operations when it is detected at boot.
+
+ If you don't know what to do here, say Y.
+
+config TOOLCHAIN_HAS_ZACAS
+ bool
+ default y
+ depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zacas)
+ depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zacas)
+ depends on AS_HAS_OPTION_ARCH
+
+config RISCV_ISA_ZACAS
+ bool "Zacas extension support for atomic CAS"
+ depends on TOOLCHAIN_HAS_ZACAS
+ depends on RISCV_ALTERNATIVE
+ default y
+ help
+ Enable the use of the Zacas ISA-extension to implement kernel atomic
+ cmpxchg operations when it is detected at boot.
+
If you don't know what to do here, say Y.
config TOOLCHAIN_HAS_ZBB
@@ -785,10 +867,24 @@ config THREAD_SIZE_ORDER
config RISCV_MISALIGNED
bool
+ help
+ Embed support for detecting and emulating misaligned
+ scalar or vector loads and stores.
+
+config RISCV_SCALAR_MISALIGNED
+ bool
+ select RISCV_MISALIGNED
select SYSCTL_ARCH_UNALIGN_ALLOW
help
Embed support for emulating misaligned loads and stores.
+config RISCV_VECTOR_MISALIGNED
+ bool
+ select RISCV_MISALIGNED
+ depends on RISCV_ISA_V
+ help
+ Enable detecting support for vector misaligned loads and stores.
+
choice
prompt "Unaligned Accesses Support"
default RISCV_PROBE_UNALIGNED_ACCESS
@@ -800,7 +896,7 @@ choice
config RISCV_PROBE_UNALIGNED_ACCESS
bool "Probe for hardware unaligned access support"
- select RISCV_MISALIGNED
+ select RISCV_SCALAR_MISALIGNED
help
During boot, the kernel will run a series of tests to determine the
speed of unaligned accesses. This probing will dynamically determine
@@ -811,7 +907,7 @@ config RISCV_PROBE_UNALIGNED_ACCESS
config RISCV_EMULATED_UNALIGNED_ACCESS
bool "Emulate unaligned access where system support is missing"
- select RISCV_MISALIGNED
+ select RISCV_SCALAR_MISALIGNED
help
If unaligned memory accesses trap into the kernel as they are not
supported by the system, the kernel will emulate the unaligned
@@ -840,6 +936,46 @@ config RISCV_EFFICIENT_UNALIGNED_ACCESS
endchoice
+choice
+ prompt "Vector unaligned Accesses Support"
+ depends on RISCV_ISA_V
+ default RISCV_PROBE_VECTOR_UNALIGNED_ACCESS
+ help
+ This determines the level of support for vector unaligned accesses. This
+ information is used by the kernel to perform optimizations. It is also
+ exposed to user space via the hwprobe syscall. The hardware will be
+ probed at boot by default.
+
+config RISCV_PROBE_VECTOR_UNALIGNED_ACCESS
+ bool "Probe speed of vector unaligned accesses"
+ select RISCV_VECTOR_MISALIGNED
+ depends on RISCV_ISA_V
+ help
+ During boot, the kernel will run a series of tests to determine the
+ speed of vector unaligned accesses if they are supported. This probing
+ will dynamically determine the speed of vector unaligned accesses on
+ the underlying system if they are supported.
+
+config RISCV_SLOW_VECTOR_UNALIGNED_ACCESS
+ bool "Assume the system supports slow vector unaligned memory accesses"
+ depends on NONPORTABLE
+ help
+ Assume that the system supports slow vector unaligned memory accesses. The
+ kernel and userspace programs may not be able to run at all on systems
+ that do not support unaligned memory accesses.
+
+config RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS
+ bool "Assume the system supports fast vector unaligned memory accesses"
+ depends on NONPORTABLE
+ help
+ Assume that the system supports fast vector unaligned memory accesses. When
+ enabled, this option improves the performance of the kernel on such
+ systems. However, the kernel and userspace programs will run much more
+ slowly, or will not be able to run at all, on systems that do not
+ support efficient unaligned memory accesses.
+
+endchoice
+
source "arch/riscv/Kconfig.vendor"
endmenu # "Platform type"
@@ -898,6 +1034,9 @@ config ARCH_SUPPORTS_KEXEC_PURGATORY
config ARCH_SUPPORTS_CRASH_DUMP
def_bool y
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
def_bool CRASH_RESERVE
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index d469db9f46f4..13fbc0f94238 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -82,6 +82,12 @@ else
riscv-march-$(CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI) := $(riscv-march-y)_zicsr_zifencei
endif
+# Check if the toolchain supports Zacas
+riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZACAS) := $(riscv-march-y)_zacas
+
+# Check if the toolchain supports Zabha
+riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZABHA) := $(riscv-march-y)_zabha
+
# Remove F,D,V from isa string for all. Keep extensions between "fd" and "v" by
# matching non-v and non-multi-letter extensions out with the filter ([^v_]*)
KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/')
@@ -129,7 +135,7 @@ stack_protector_prepare: prepare0
-mstack-protector-guard-reg=tp \
-mstack-protector-guard-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
endif
# arch specific predefines for sparse
diff --git a/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi b/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
index 5e808242649e..86b2f15375ec 100644
--- a/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
+++ b/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
@@ -6,3 +6,7 @@
*/
#include <arm64/renesas/rzg2ul-smarc-som.dtsi>
+
+&sbc {
+ status = "disabled";
+};
diff --git a/arch/riscv/boot/dts/sophgo/Makefile b/arch/riscv/boot/dts/sophgo/Makefile
index 57ad82a61ea6..47d4243a8f35 100644
--- a/arch/riscv/boot/dts/sophgo/Makefile
+++ b/arch/riscv/boot/dts/sophgo/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_SOPHGO) += cv1800b-milkv-duo.dtb
dtb-$(CONFIG_ARCH_SOPHGO) += cv1812h-huashan-pi.dtb
+dtb-$(CONFIG_ARCH_SOPHGO) += sg2002-licheerv-nano-b.dtb
dtb-$(CONFIG_ARCH_SOPHGO) += sg2042-milkv-pioneer.dtb
diff --git a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
index 375ff2661b6e..9feb520eaec4 100644
--- a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+++ b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
@@ -39,7 +39,54 @@
clock-frequency = <25000000>;
};
+&pinctrl {
+ uart0_cfg: uart0-cfg {
+ uart0-pins {
+ pinmux = <PINMUX(PIN_UART0_TX, 0)>,
+ <PINMUX(PIN_UART0_RX, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+ };
+
+ sdhci0_cfg: sdhci0-cfg {
+ sdhci0-clk-pins {
+ pinmux = <PINMUX(PIN_SD0_CLK, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <16100>;
+ power-source = <3300>;
+ };
+
+ sdhci0-cmd-pins {
+ pinmux = <PINMUX(PIN_SD0_CMD, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+
+ sdhci0-data-pins {
+ pinmux = <PINMUX(PIN_SD0_D0, 0)>,
+ <PINMUX(PIN_SD0_D1, 0)>,
+ <PINMUX(PIN_SD0_D2, 0)>,
+ <PINMUX(PIN_SD0_D3, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+
+ sdhci0-cd-pins {
+ pinmux = <PINMUX(PIN_SD0_CD, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+ };
+};
+
&sdhci0 {
+ pinctrl-0 = <&sdhci0_cfg>;
+ pinctrl-names = "default";
status = "okay";
bus-width = <4>;
no-1-8-v;
@@ -49,5 +96,7 @@
};
&uart0 {
+ pinctrl-0 = <&uart0_cfg>;
+ pinctrl-names = "default";
status = "okay";
};
diff --git a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
index ec9530972ae2..aa1f5df100f0 100644
--- a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+++ b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
@@ -3,6 +3,7 @@
* Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
*/
+#include <dt-bindings/pinctrl/pinctrl-cv1800b.h>
#include "cv18xx.dtsi"
/ {
@@ -12,6 +13,15 @@
device_type = "memory";
reg = <0x80000000 0x4000000>;
};
+
+ soc {
+ pinctrl: pinctrl@3001000 {
+ compatible = "sophgo,cv1800b-pinctrl";
+ reg = <0x03001000 0x1000>,
+ <0x05027000 0x1000>;
+ reg-names = "sys", "rtc";
+ };
+ };
};
&plic {
diff --git a/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts b/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts
index 7b5f57853690..26b57e15adc1 100644
--- a/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts
+++ b/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts
@@ -43,6 +43,18 @@
clock-frequency = <25000000>;
};
+&emmc {
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <200000000>;
+ mmc-ddr-1_8v;
+ mmc-ddr-3_3v;
+ mmc-hs200-1_8v;
+ no-sd;
+ no-sdio;
+ non-removable;
+};
+
&sdhci0 {
status = "okay";
bus-width = <4>;
@@ -52,6 +64,17 @@
disable-wp;
};
+&sdhci1 {
+ status = "okay";
+ bus-width = <4>;
+ cap-sdio-irq;
+ max-frequency = <50000000>;
+ no-mmc;
+ no-sd;
+ disable-wp;
+ non-removable;
+};
+
&uart0 {
status = "okay";
};
diff --git a/arch/riscv/boot/dts/sophgo/cv1812h.dtsi b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
index 7fa4c1e2d1da..8a1b95c5116b 100644
--- a/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
+++ b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
@@ -4,7 +4,9 @@
*/
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/pinctrl-cv1812h.h>
#include "cv18xx.dtsi"
+#include "cv181x.dtsi"
/ {
compatible = "sophgo,cv1812h";
@@ -13,6 +15,15 @@
device_type = "memory";
reg = <0x80000000 0x10000000>;
};
+
+ soc {
+ pinctrl: pinctrl@3001000 {
+ compatible = "sophgo,cv1812h-pinctrl";
+ reg = <0x03001000 0x1000>,
+ <0x05027000 0x1000>;
+ reg-names = "sys", "rtc";
+ };
+ };
};
&plic {
diff --git a/arch/riscv/boot/dts/sophgo/cv181x.dtsi b/arch/riscv/boot/dts/sophgo/cv181x.dtsi
new file mode 100644
index 000000000000..5fd14dd1b14f
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/cv181x.dtsi
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
+ */
+
+#include <dt-bindings/clock/sophgo,cv1800.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ soc {
+ emmc: mmc@4300000 {
+ compatible = "sophgo,cv1800b-dwcmshc";
+ reg = <0x4300000 0x1000>;
+ interrupts = <34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk CLK_AXI4_EMMC>,
+ <&clk CLK_EMMC>;
+ clock-names = "core", "bus";
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
index b724fb6d9689..c18822ec849f 100644
--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
@@ -133,6 +133,28 @@
};
};
+ saradc: adc@30f0000 {
+ compatible = "sophgo,cv1800b-saradc";
+ reg = <0x030f0000 0x1000>;
+ clocks = <&clk CLK_SARADC>;
+ interrupts = <100 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ channel@0 {
+ reg = <0>;
+ };
+
+ channel@1 {
+ reg = <1>;
+ };
+
+ channel@2 {
+ reg = <2>;
+ };
+ };
+
i2c0: i2c@4000000 {
compatible = "snps,designware-i2c";
reg = <0x04000000 0x10000>;
@@ -297,6 +319,16 @@
status = "disabled";
};
+ sdhci1: mmc@4320000 {
+ compatible = "sophgo,cv1800b-dwcmshc";
+ reg = <0x4320000 0x1000>;
+ interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk CLK_AXI4_SD1>,
+ <&clk CLK_SD1>;
+ clock-names = "core", "bus";
+ status = "disabled";
+ };
+
dmac: dma-controller@4330000 {
compatible = "snps,axi-dma-1.01a";
reg = <0x04330000 0x1000>;
diff --git a/arch/riscv/boot/dts/sophgo/sg2002-licheerv-nano-b.dts b/arch/riscv/boot/dts/sophgo/sg2002-licheerv-nano-b.dts
new file mode 100644
index 000000000000..86a712b953a5
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/sg2002-licheerv-nano-b.dts
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Thomas Bonnefille <thomas.bonnefille@bootlin.com>
+ */
+
+/dts-v1/;
+
+#include "sg2002.dtsi"
+
+/ {
+ model = "LicheeRV Nano B";
+ compatible = "sipeed,licheerv-nano-b", "sipeed,licheerv-nano", "sophgo,sg2002";
+
+ aliases {
+ gpio0 = &gpio0;
+ gpio1 = &gpio1;
+ gpio2 = &gpio2;
+ gpio3 = &gpio3;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&osc {
+ clock-frequency = <25000000>;
+};
+
+&pinctrl {
+ uart0_cfg: uart0-cfg {
+ uart0-pins {
+ pinmux = <PINMUX(PIN_UART0_TX, 0)>,
+ <PINMUX(PIN_UART0_RX, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+ };
+
+ sdhci0_cfg: sdhci0-cfg {
+ sdhci0-clk-pins {
+ pinmux = <PINMUX(PIN_SD0_CLK, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <16100>;
+ power-source = <3300>;
+ };
+
+ sdhci0-cmd-pins {
+ pinmux = <PINMUX(PIN_SD0_CMD, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+
+ sdhci0-data-pins {
+ pinmux = <PINMUX(PIN_SD0_D0, 0)>,
+ <PINMUX(PIN_SD0_D1, 0)>,
+ <PINMUX(PIN_SD0_D2, 0)>,
+ <PINMUX(PIN_SD0_D3, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+
+ sdhci0-cd-pins {
+ pinmux = <PINMUX(PIN_SD0_CD, 0)>;
+ bias-pull-up;
+ drive-strength-microamp = <10800>;
+ power-source = <3300>;
+ };
+ };
+};
+
+&sdhci0 {
+ pinctrl-0 = <&sdhci0_cfg>;
+ pinctrl-names = "default";
+ status = "okay";
+ bus-width = <4>;
+ no-1-8-v;
+ no-mmc;
+ no-sdio;
+ disable-wp;
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_cfg>;
+ pinctrl-names = "default";
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/sophgo/sg2002.dtsi b/arch/riscv/boot/dts/sophgo/sg2002.dtsi
new file mode 100644
index 000000000000..7f79de33163c
--- /dev/null
+++ b/arch/riscv/boot/dts/sophgo/sg2002.dtsi
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2024 Thomas Bonnefille <thomas.bonnefille@bootlin.com>
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/pinctrl-sg2002.h>
+#include "cv18xx.dtsi"
+#include "cv181x.dtsi"
+
+/ {
+ compatible = "sophgo,sg2002";
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>;
+ };
+
+ soc {
+ pinctrl: pinctrl@3001000 {
+ compatible = "sophgo,sg2002-pinctrl";
+ reg = <0x03001000 0x1000>,
+ <0x05027000 0x1000>;
+ reg-names = "sys", "rtc";
+ };
+ };
+};
+
+&plic {
+ compatible = "sophgo,sg2002-plic", "thead,c900-plic";
+};
+
+&clint {
+ compatible = "sophgo,sg2002-clint", "thead,c900-clint";
+};
+
+&clk {
+ compatible = "sophgo,sg2000-clk";
+};
+
+&sdhci0 {
+ compatible = "sophgo,sg2002-dwcmshc";
+};
diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
index a3f9d6f22566..be596d01ff8d 100644
--- a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
+++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
@@ -5,6 +5,9 @@
#include "sg2042.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
/ {
model = "Milk-V Pioneer";
compatible = "milkv,pioneer", "sophgo,sg2042";
@@ -12,6 +15,18 @@
chosen {
stdout-path = "serial0";
};
+
+ gpio-power {
+ compatible = "gpio-keys";
+
+ key-power {
+ label = "Power Key";
+ linux,code = <KEY_POWER>;
+ gpios = <&port0a 22 GPIO_ACTIVE_HIGH>;
+ linux,input-type = <EV_KEY>;
+ debounce-interval = <100>;
+ };
+ };
};
&cgi_main {
diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
index 4e5fa6591623..e62ac51ac55a 100644
--- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi
+++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
@@ -112,7 +112,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <32>;
+ ngpios = <32>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -134,7 +134,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <32>;
+ ngpios = <32>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -156,7 +156,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <32>;
+ ngpios = <32>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile
index 7a163a7d6ba3..b3bb12f78e7d 100644
--- a/arch/riscv/boot/dts/starfive/Makefile
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -8,6 +8,7 @@ DTC_FLAGS_jh7110-starfive-visionfive-2-v1.3b := -@
dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.dtb
+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-deepcomputing-fml13v01.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-milkv-mars.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-pine64-star64.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
index c7771b3b6475..48fb5091b817 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
@@ -128,7 +128,6 @@
assigned-clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
<&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>;
assigned-clock-rates = <49500000>, <198000000>;
- status = "okay";
ports {
#address-cells = <1>;
@@ -151,7 +150,6 @@
&csi2rx {
assigned-clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>;
assigned-clock-rates = <297000000>;
- status = "okay";
ports {
#address-cells = <1>;
@@ -176,7 +174,6 @@
&gmac0 {
phy-handle = <&phy0>;
phy-mode = "rgmii-id";
- status = "okay";
mdio {
#address-cells = <1>;
@@ -196,7 +193,6 @@
i2c-scl-falling-time-ns = <510>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
- status = "okay";
};
&i2c2 {
@@ -311,7 +307,6 @@
&pwmdac {
pinctrl-names = "default";
pinctrl-0 = <&pwmdac_pins>;
- status = "okay";
};
&qspi {
@@ -350,13 +345,11 @@
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm_pins>;
- status = "okay";
};
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
- status = "okay";
spi_dev0: spi@0 {
compatible = "rohm,dh2228fv";
@@ -642,11 +635,6 @@
status = "okay";
};
-&usb0 {
- dr_mode = "peripheral";
- status = "okay";
-};
-
&U74_1 {
cpu-supply = <&vdd_cpu>;
};
diff --git a/arch/riscv/boot/dts/starfive/jh7110-deepcomputing-fml13v01.dts b/arch/riscv/boot/dts/starfive/jh7110-deepcomputing-fml13v01.dts
new file mode 100644
index 000000000000..30b0715196b6
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-deepcomputing-fml13v01.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2024 DeepComputing (HK) Limited
+ */
+
+/dts-v1/;
+#include "jh7110-common.dtsi"
+
+/ {
+ model = "DeepComputing FML13V01";
+ compatible = "deepcomputing,fml13v01", "starfive,jh7110";
+};
+
+&usb0 {
+ dr_mode = "host";
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts b/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts
index 5cb9e99e1dac..0d248b671d4b 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts
+++ b/arch/riscv/boot/dts/starfive/jh7110-milkv-mars.dts
@@ -15,6 +15,11 @@
starfive,tx-use-rgmii-clk;
assigned-clocks = <&aoncrg JH7110_AONCLK_GMAC0_TX>;
assigned-clock-parents = <&aoncrg JH7110_AONCLK_GMAC0_RMII_RTX>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
};
&pcie0 {
@@ -35,3 +40,20 @@
rx-internal-delay-ps = <1500>;
tx-internal-delay-ps = <1500>;
};
+
+&pwm {
+ status = "okay";
+};
+
+&pwmdac {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&usb0 {
+ dr_mode = "peripheral";
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts b/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts
index b720cdd15ed6..fe4a490ecc61 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts
+++ b/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts
@@ -18,6 +18,7 @@
starfive,tx-use-rgmii-clk;
assigned-clocks = <&aoncrg JH7110_AONCLK_GMAC0_TX>;
assigned-clock-parents = <&aoncrg JH7110_AONCLK_GMAC0_RMII_RTX>;
+ status = "okay";
};
&gmac1 {
@@ -39,13 +40,16 @@
};
};
+&i2c0 {
+ status = "okay";
+};
+
&pcie1 {
status = "okay";
};
&phy0 {
- rx-internal-delay-ps = <1900>;
- tx-internal-delay-ps = <1500>;
+ rx-internal-delay-ps = <1500>;
motorcomm,rx-clk-drv-microamp = <2910>;
motorcomm,rx-data-drv-microamp = <2910>;
motorcomm,tx-clk-adj-enabled;
@@ -63,3 +67,20 @@
motorcomm,tx-clk-10-inverted;
motorcomm,tx-clk-100-inverted;
};
+
+&pwm {
+ status = "okay";
+};
+
+&pwmdac {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&usb0 {
+ dr_mode = "peripheral";
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
index 18f38fc790a4..5f14afb2c24d 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
@@ -13,6 +13,10 @@
};
};
+&gmac0 {
+ status = "okay";
+};
+
&gmac1 {
phy-handle = <&phy1>;
phy-mode = "rgmii-id";
@@ -29,6 +33,10 @@
};
};
+&i2c0 {
+ status = "okay";
+};
+
&mmc0 {
non-removable;
};
@@ -40,3 +48,20 @@
&pcie1 {
status = "okay";
};
+
+&pwm {
+ status = "okay";
+};
+
+&pwmdac {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&usb0 {
+ dr_mode = "peripheral";
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts b/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts
index 497d961456f3..21c33f165ba9 100644
--- a/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts
+++ b/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts
@@ -7,16 +7,21 @@
/dts-v1/;
#include "th1520.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
/ {
model = "BeagleV Ahead";
compatible = "beagle,beaglev-ahead", "thead,th1520";
aliases {
+ ethernet0 = &gmac0;
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
gpio3 = &gpio3;
+ gpio4 = &gpio4;
+ gpio5 = &aogpio;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
@@ -33,7 +38,42 @@
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x1 0x00000000>;
+ };
+
+ leds {
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins>;
+ compatible = "gpio-leds";
+
+ led-1 {
+ gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_BLUE>;
+ label = "led1";
+ };
+
+ led-2 {
+ gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_BLUE>;
+ label = "led2";
+ };
+ led-3 {
+ gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_BLUE>;
+ label = "led3";
+ };
+
+ led-4 {
+ gpios = <&gpio4 11 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_BLUE>;
+ label = "led4";
+ };
+
+ led-5 {
+ gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_BLUE>;
+ label = "led5";
+ };
};
};
@@ -59,6 +99,137 @@
status = "okay";
};
+&gmac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_pins>;
+ phy-handle = <&phy0>;
+ phy-mode = "rgmii-id";
+ status = "okay";
+};
+
+&mdio0 {
+ phy0: ethernet-phy@1 {
+ reg = <1>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio3 21 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <10000>;
+ reset-post-delay-us = <50000>;
+ };
+};
+
+&padctrl_aosys {
+ led_pins: led-0 {
+ led-pins {
+ pins = "AUDIO_PA8", /* GPIO4_8 */
+ "AUDIO_PA9", /* GPIO4_9 */
+ "AUDIO_PA10", /* GPIO4_10 */
+ "AUDIO_PA11", /* GPIO4_11 */
+ "AUDIO_PA12"; /* GPIO4_12 */
+ bias-disable;
+ drive-strength = <3>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+};
+
+&padctrl0_apsys {
+ gmac0_pins: gmac0-0 {
+ tx-pins {
+ pins = "GMAC0_TX_CLK",
+ "GMAC0_TXEN",
+ "GMAC0_TXD0",
+ "GMAC0_TXD1",
+ "GMAC0_TXD2",
+ "GMAC0_TXD3";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <25>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ rx-pins {
+ pins = "GMAC0_RX_CLK",
+ "GMAC0_RXDV",
+ "GMAC0_RXD0",
+ "GMAC0_RXD1",
+ "GMAC0_RXD2",
+ "GMAC0_RXD3";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <1>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ mdc-pins {
+ pins = "GMAC0_MDC";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <13>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ mdio-pins {
+ pins = "GMAC0_MDIO";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <13>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+
+ phy-reset-pins {
+ pins = "GMAC0_COL"; /* GPIO3_21 */
+ bias-disable;
+ drive-strength = <3>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ phy-interrupt-pins {
+ pins = "GMAC0_CRS"; /* GPIO3_22 */
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <1>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+ };
+
+ uart0_pins: uart0-0 {
+ tx-pins {
+ pins = "UART0_TXD";
+ function = "uart";
+ bias-disable;
+ drive-strength = <3>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ rx-pins {
+ pins = "UART0_RXD";
+ function = "uart";
+ bias-pull-up;
+ drive-strength = <1>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+ };
+};
+
&sdio0 {
bus-width = <4>;
max-frequency = <198000000>;
@@ -66,9 +237,7 @@
};
&uart0 {
- status = "okay";
-};
-
-&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
status = "okay";
};
diff --git a/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi b/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi
index 78977bdbbe3d..8e76b63e0100 100644
--- a/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi
+++ b/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi
@@ -11,6 +11,11 @@
model = "Sipeed Lichee Module 4A";
compatible = "sipeed,lichee-module-4a", "thead,th1520";
+ aliases {
+ ethernet0 = &gmac0;
+ ethernet1 = &gmac1;
+ };
+
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x2 0x00000000>;
@@ -25,6 +30,12 @@
clock-frequency = <32768>;
};
+&aogpio {
+ gpio-line-names = "", "", "",
+ "GPIO00",
+ "GPIO04";
+};
+
&dmac0 {
status = "okay";
};
@@ -39,6 +50,153 @@
status = "okay";
};
+&gmac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_pins>, <&mdio0_pins>;
+ phy-handle = <&phy0>;
+ phy-mode = "rgmii-id";
+ status = "okay";
+};
+
+&gmac1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1_pins>;
+ phy-handle = <&phy1>;
+ phy-mode = "rgmii-id";
+ status = "okay";
+};
+
+&gpio0 {
+ gpio-line-names = "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "",
+ "GPIO07",
+ "GPIO08",
+ "",
+ "GPIO01",
+ "GPIO02";
+};
+
+&gpio1 {
+ gpio-line-names = "", "", "",
+ "GPIO11",
+ "GPIO12",
+ "GPIO13",
+ "GPIO14",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "",
+ "GPIO06";
+};
+
+&gpio2 {
+ gpio-line-names = "GPIO03",
+ "GPIO05";
+};
+
+&gpio3 {
+ gpio-line-names = "", "",
+ "GPIO09",
+ "GPIO10";
+};
+
+&mdio0 {
+ phy0: ethernet-phy@1 {
+ reg = <1>;
+ };
+
+ phy1: ethernet-phy@2 {
+ reg = <2>;
+ };
+};
+
+&padctrl0_apsys {
+ gmac0_pins: gmac0-0 {
+ tx-pins {
+ pins = "GMAC0_TX_CLK",
+ "GMAC0_TXEN",
+ "GMAC0_TXD0",
+ "GMAC0_TXD1",
+ "GMAC0_TXD2",
+ "GMAC0_TXD3";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <25>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ rx-pins {
+ pins = "GMAC0_RX_CLK",
+ "GMAC0_RXDV",
+ "GMAC0_RXD0",
+ "GMAC0_RXD1",
+ "GMAC0_RXD2",
+ "GMAC0_RXD3";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <1>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ gmac1_pins: gmac1-0 {
+ tx-pins {
+ pins = "GPIO2_18", /* GMAC1_TX_CLK */
+ "GPIO2_20", /* GMAC1_TXEN */
+ "GPIO2_21", /* GMAC1_TXD0 */
+ "GPIO2_22", /* GMAC1_TXD1 */
+ "GPIO2_23", /* GMAC1_TXD2 */
+ "GPIO2_24"; /* GMAC1_TXD3 */
+ function = "gmac1";
+ bias-disable;
+ drive-strength = <25>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ rx-pins {
+ pins = "GPIO2_19", /* GMAC1_RX_CLK */
+ "GPIO2_25", /* GMAC1_RXDV */
+ "GPIO2_30", /* GMAC1_RXD0 */
+ "GPIO2_31", /* GMAC1_RXD1 */
+ "GPIO3_0", /* GMAC1_RXD2 */
+ "GPIO3_1"; /* GMAC1_RXD3 */
+ function = "gmac1";
+ bias-disable;
+ drive-strength = <1>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ mdio0_pins: mdio0-0 {
+ mdc-pins {
+ pins = "GMAC0_MDC";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <13>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ mdio-pins {
+ pins = "GMAC0_MDIO";
+ function = "gmac0";
+ bias-disable;
+ drive-strength = <13>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+ };
+};
+
&sdio0 {
bus-width = <4>;
max-frequency = <198000000>;
diff --git a/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts b/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts
index 7738d2895c5a..4020c727f09e 100644
--- a/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts
+++ b/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts
@@ -14,6 +14,8 @@
gpio1 = &gpio1;
gpio2 = &gpio2;
gpio3 = &gpio3;
+ gpio4 = &gpio4;
+ gpio5 = &aogpio;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
@@ -28,10 +30,32 @@
};
};
-&uart0 {
- status = "okay";
+&padctrl0_apsys {
+ uart0_pins: uart0-0 {
+ tx-pins {
+ pins = "UART0_TXD";
+ function = "uart";
+ bias-disable;
+ drive-strength = <3>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ rx-pins {
+ pins = "UART0_RXD";
+ function = "uart";
+ bias-disable;
+ drive-strength = <1>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+ };
};
-&spi0 {
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
status = "okay";
};
diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi
index 6992060e6a54..acfe030e803a 100644
--- a/arch/riscv/boot/dts/thead/th1520.dtsi
+++ b/arch/riscv/boot/dts/thead/th1520.dtsi
@@ -216,6 +216,19 @@
#clock-cells = <0>;
};
+ aonsys_clk: clock-73728000 {
+ compatible = "fixed-clock";
+ clock-frequency = <73728000>;
+ clock-output-names = "aonsys_clk";
+ #clock-cells = <0>;
+ };
+
+ stmmac_axi_config: stmmac-axi-config {
+ snps,wr_osr_lmt = <15>;
+ snps,rd_osr_lmt = <15>;
+ snps,blen = <0 0 64 32 0 0 0>;
+ };
+
soc {
compatible = "simple-bus";
interrupt-parent = <&plic>;
@@ -267,6 +280,50 @@
status = "disabled";
};
+ gmac1: ethernet@ffe7060000 {
+ compatible = "thead,th1520-gmac", "snps,dwmac-3.70a";
+ reg = <0xff 0xe7060000 0x0 0x2000>, <0xff 0xec004000 0x0 0x1000>;
+ reg-names = "dwmac", "apb";
+ interrupts = <67 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC1>;
+ clock-names = "stmmaceth", "pclk";
+ snps,pbl = <32>;
+ snps,fixed-burst;
+ snps,multicast-filter-bins = <64>;
+ snps,perfect-filter-entries = <32>;
+ snps,axi-config = <&stmmac_axi_config>;
+ status = "disabled";
+
+ mdio1: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ gmac0: ethernet@ffe7070000 {
+ compatible = "thead,th1520-gmac", "snps,dwmac-3.70a";
+ reg = <0xff 0xe7070000 0x0 0x2000>, <0xff 0xec003000 0x0 0x1000>;
+ reg-names = "dwmac", "apb";
+ interrupts = <66 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC0>;
+ clock-names = "stmmaceth", "pclk";
+ snps,pbl = <32>;
+ snps,fixed-burst;
+ snps,multicast-filter-bins = <64>;
+ snps,perfect-filter-entries = <32>;
+ snps,axi-config = <&stmmac_axi_config>;
+ status = "disabled";
+
+ mdio0: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
emmc: mmc@ffe7080000 {
compatible = "thead,th1520-dwcmshc";
reg = <0xff 0xe7080000 0x0 0x10000>;
@@ -316,18 +373,20 @@
status = "disabled";
};
- gpio2: gpio@ffe7f34000 {
+ gpio@ffe7f34000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xe7f34000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk CLK_GPIO2>;
+ clock-names = "bus";
- portc: gpio-controller@0 {
+ gpio2: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
+ gpio-ranges = <&padctrl0_apsys 0 0 32>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -335,18 +394,20 @@
};
};
- gpio3: gpio@ffe7f38000 {
+ gpio@ffe7f38000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xe7f38000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk CLK_GPIO3>;
+ clock-names = "bus";
- portd: gpio-controller@0 {
+ gpio3: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- ngpios = <32>;
+ ngpios = <23>;
+ gpio-ranges = <&padctrl0_apsys 0 32 23>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -354,18 +415,27 @@
};
};
- gpio0: gpio@ffec005000 {
+ padctrl1_apsys: pinctrl@ffe7f3c000 {
+ compatible = "thead,th1520-pinctrl";
+ reg = <0xff 0xe7f3c000 0x0 0x1000>;
+ clocks = <&clk CLK_PADCTRL1>;
+ thead,pad-group = <2>;
+ };
+
+ gpio@ffec005000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xec005000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk CLK_GPIO0>;
+ clock-names = "bus";
- porta: gpio-controller@0 {
+ gpio0: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
+ gpio-ranges = <&padctrl1_apsys 0 0 32>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -373,18 +443,20 @@
};
};
- gpio1: gpio@ffec006000 {
+ gpio@ffec006000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xec006000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk CLK_GPIO1>;
+ clock-names = "bus";
- portb: gpio-controller@0 {
+ gpio1: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- ngpios = <32>;
+ ngpios = <31>;
+ gpio-ranges = <&padctrl1_apsys 0 32 31>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -392,6 +464,13 @@
};
};
+ padctrl0_apsys: pinctrl@ffec007000 {
+ compatible = "thead,th1520-pinctrl";
+ reg = <0xff 0xec007000 0x0 0x1000>;
+ clocks = <&clk CLK_PADCTRL0>;
+ thead,pad-group = <3>;
+ };
+
uart2: serial@ffec010000 {
compatible = "snps,dw-apb-uart";
reg = <0xff 0xec010000 0x0 0x4000>;
@@ -520,17 +599,18 @@
status = "disabled";
};
- ao_gpio0: gpio@fffff41000 {
+ gpio@fffff41000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xfff41000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
- porte: gpio-controller@0 {
+ aogpio: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- ngpios = <32>;
+ ngpios = <16>;
+ gpio-ranges = <&padctrl_aosys 0 9 16>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -538,17 +618,25 @@
};
};
- ao_gpio1: gpio@fffff52000 {
+ padctrl_aosys: pinctrl@fffff4a000 {
+ compatible = "thead,th1520-pinctrl";
+ reg = <0xff 0xfff4a000 0x0 0x2000>;
+ clocks = <&aonsys_clk>;
+ thead,pad-group = <1>;
+ };
+
+ gpio@fffff52000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xfff52000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
- portf: gpio-controller@0 {
+ gpio4: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- ngpios = <32>;
+ ngpios = <23>;
+ gpio-ranges = <&padctrl_aosys 0 25 22>, <&padctrl_aosys 22 7 1>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 2341393cfac1..b4a37345703e 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -167,6 +167,7 @@ CONFIG_PINCTRL_SOPHGO_CV1800B=y
CONFIG_PINCTRL_SOPHGO_CV1812H=y
CONFIG_PINCTRL_SOPHGO_SG2000=y
CONFIG_PINCTRL_SOPHGO_SG2002=y
+CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_SIFIVE=y
CONFIG_POWER_RESET_GPIO_RESTART=y
CONFIG_SENSORS_SFCTEMP=m
@@ -256,6 +257,7 @@ CONFIG_RPMSG_CTRL=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_PM_DEVFREQ=y
CONFIG_IIO=y
+CONFIG_THEAD_C900_ACLINT_SSWI=y
CONFIG_PHY_SUN4I_USB=m
CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=m
CONFIG_PHY_STARFIVE_JH7110_PCIE=m
@@ -301,7 +303,6 @@ CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_PER_CPU_MAPS=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_WQ_WATCHDOG=y
-CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/riscv/errata/andes/errata.c b/arch/riscv/errata/andes/errata.c
index fc1a34faa5f3..dcc9d1ee5ffd 100644
--- a/arch/riscv/errata/andes/errata.c
+++ b/arch/riscv/errata/andes/errata.c
@@ -13,7 +13,7 @@
#include <asm/alternative.h>
#include <asm/cacheflush.h>
#include <asm/errata_list.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/processor.h>
#include <asm/sbi.h>
#include <asm/vendorid_list.h>
diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
index cea3b96ade11..38aac2c47845 100644
--- a/arch/riscv/errata/sifive/errata.c
+++ b/arch/riscv/errata/sifive/errata.c
@@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/bug.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/alternative.h>
#include <asm/vendorid_list.h>
#include <asm/errata_list.h>
diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
index f5120e07c318..e24770a77932 100644
--- a/arch/riscv/errata/thead/errata.c
+++ b/arch/riscv/errata/thead/errata.c
@@ -16,7 +16,7 @@
#include <asm/errata_list.h>
#include <asm/hwprobe.h>
#include <asm/io.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/vendorid_list.h>
#include <asm/vendor_extensions.h>
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 1461af12da6e..de13d5a234f8 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -6,10 +6,12 @@ generic-y += early_ioremap.h
generic-y += flat.h
generic-y += kvm_para.h
generic-y += mmzone.h
+generic-y += mcs_spinlock.h
generic-y += parport.h
-generic-y += spinlock.h
generic-y += spinlock_types.h
+generic-y += ticket_spinlock.h
generic-y += qrwlock.h
generic-y += qrwlock_types.h
+generic-y += qspinlock.h
generic-y += user.h
generic-y += vmlinux.lds.h
diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
index ebbce134917c..4cadc56220fe 100644
--- a/arch/riscv/include/asm/cmpxchg.h
+++ b/arch/riscv/include/asm/cmpxchg.h
@@ -12,30 +12,43 @@
#include <asm/fence.h>
#include <asm/hwcap.h>
#include <asm/insn-def.h>
-
-#define __arch_xchg_masked(sc_sfx, prepend, append, r, p, n) \
-({ \
- u32 *__ptr32b = (u32 *)((ulong)(p) & ~0x3); \
- ulong __s = ((ulong)(p) & (0x4 - sizeof(*p))) * BITS_PER_BYTE; \
- ulong __mask = GENMASK(((sizeof(*p)) * BITS_PER_BYTE) - 1, 0) \
- << __s; \
- ulong __newx = (ulong)(n) << __s; \
- ulong __retx; \
- ulong __rc; \
- \
- __asm__ __volatile__ ( \
- prepend \
- "0: lr.w %0, %2\n" \
- " and %1, %0, %z4\n" \
- " or %1, %1, %z3\n" \
- " sc.w" sc_sfx " %1, %1, %2\n" \
- " bnez %1, 0b\n" \
- append \
- : "=&r" (__retx), "=&r" (__rc), "+A" (*(__ptr32b)) \
- : "rJ" (__newx), "rJ" (~__mask) \
- : "memory"); \
- \
- r = (__typeof__(*(p)))((__retx & __mask) >> __s); \
+#include <asm/cpufeature-macros.h>
+
+#define __arch_xchg_masked(sc_sfx, swap_sfx, prepend, sc_append, \
+ swap_append, r, p, n) \
+({ \
+ if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) && \
+ riscv_has_extension_unlikely(RISCV_ISA_EXT_ZABHA)) { \
+ __asm__ __volatile__ ( \
+ prepend \
+ " amoswap" swap_sfx " %0, %z2, %1\n" \
+ swap_append \
+ : "=&r" (r), "+A" (*(p)) \
+ : "rJ" (n) \
+ : "memory"); \
+ } else { \
+ u32 *__ptr32b = (u32 *)((ulong)(p) & ~0x3); \
+ ulong __s = ((ulong)(p) & (0x4 - sizeof(*p))) * BITS_PER_BYTE; \
+ ulong __mask = GENMASK(((sizeof(*p)) * BITS_PER_BYTE) - 1, 0) \
+ << __s; \
+ ulong __newx = (ulong)(n) << __s; \
+ ulong __retx; \
+ ulong __rc; \
+ \
+ __asm__ __volatile__ ( \
+ prepend \
+ "0: lr.w %0, %2\n" \
+ " and %1, %0, %z4\n" \
+ " or %1, %1, %z3\n" \
+ " sc.w" sc_sfx " %1, %1, %2\n" \
+ " bnez %1, 0b\n" \
+ sc_append \
+ : "=&r" (__retx), "=&r" (__rc), "+A" (*(__ptr32b)) \
+ : "rJ" (__newx), "rJ" (~__mask) \
+ : "memory"); \
+ \
+ r = (__typeof__(*(p)))((__retx & __mask) >> __s); \
+ } \
})
#define __arch_xchg(sfx, prepend, append, r, p, n) \
@@ -58,8 +71,13 @@
\
switch (sizeof(*__ptr)) { \
case 1: \
+ __arch_xchg_masked(sc_sfx, ".b" swap_sfx, \
+ prepend, sc_append, swap_append, \
+ __ret, __ptr, __new); \
+ break; \
case 2: \
- __arch_xchg_masked(sc_sfx, prepend, sc_append, \
+ __arch_xchg_masked(sc_sfx, ".h" swap_sfx, \
+ prepend, sc_append, swap_append, \
__ret, __ptr, __new); \
break; \
case 4: \
@@ -106,55 +124,90 @@
* store NEW in MEM. Return the initial value in MEM. Success is
* indicated by comparing RETURN with OLD.
*/
-
-#define __arch_cmpxchg_masked(sc_sfx, prepend, append, r, p, o, n) \
-({ \
- u32 *__ptr32b = (u32 *)((ulong)(p) & ~0x3); \
- ulong __s = ((ulong)(p) & (0x4 - sizeof(*p))) * BITS_PER_BYTE; \
- ulong __mask = GENMASK(((sizeof(*p)) * BITS_PER_BYTE) - 1, 0) \
- << __s; \
- ulong __newx = (ulong)(n) << __s; \
- ulong __oldx = (ulong)(o) << __s; \
- ulong __retx; \
- ulong __rc; \
- \
- __asm__ __volatile__ ( \
- prepend \
- "0: lr.w %0, %2\n" \
- " and %1, %0, %z5\n" \
- " bne %1, %z3, 1f\n" \
- " and %1, %0, %z6\n" \
- " or %1, %1, %z4\n" \
- " sc.w" sc_sfx " %1, %1, %2\n" \
- " bnez %1, 0b\n" \
- append \
- "1:\n" \
- : "=&r" (__retx), "=&r" (__rc), "+A" (*(__ptr32b)) \
- : "rJ" ((long)__oldx), "rJ" (__newx), \
- "rJ" (__mask), "rJ" (~__mask) \
- : "memory"); \
- \
- r = (__typeof__(*(p)))((__retx & __mask) >> __s); \
+#define __arch_cmpxchg_masked(sc_sfx, cas_sfx, \
+ sc_prepend, sc_append, \
+ cas_prepend, cas_append, \
+ r, p, o, n) \
+({ \
+ if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) && \
+ IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) && \
+ riscv_has_extension_unlikely(RISCV_ISA_EXT_ZABHA) && \
+ riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)) { \
+ r = o; \
+ \
+ __asm__ __volatile__ ( \
+ cas_prepend \
+ " amocas" cas_sfx " %0, %z2, %1\n" \
+ cas_append \
+ : "+&r" (r), "+A" (*(p)) \
+ : "rJ" (n) \
+ : "memory"); \
+ } else { \
+ u32 *__ptr32b = (u32 *)((ulong)(p) & ~0x3); \
+ ulong __s = ((ulong)(p) & (0x4 - sizeof(*p))) * BITS_PER_BYTE; \
+ ulong __mask = GENMASK(((sizeof(*p)) * BITS_PER_BYTE) - 1, 0) \
+ << __s; \
+ ulong __newx = (ulong)(n) << __s; \
+ ulong __oldx = (ulong)(o) << __s; \
+ ulong __retx; \
+ ulong __rc; \
+ \
+ __asm__ __volatile__ ( \
+ sc_prepend \
+ "0: lr.w %0, %2\n" \
+ " and %1, %0, %z5\n" \
+ " bne %1, %z3, 1f\n" \
+ " and %1, %0, %z6\n" \
+ " or %1, %1, %z4\n" \
+ " sc.w" sc_sfx " %1, %1, %2\n" \
+ " bnez %1, 0b\n" \
+ sc_append \
+ "1:\n" \
+ : "=&r" (__retx), "=&r" (__rc), "+A" (*(__ptr32b)) \
+ : "rJ" ((long)__oldx), "rJ" (__newx), \
+ "rJ" (__mask), "rJ" (~__mask) \
+ : "memory"); \
+ \
+ r = (__typeof__(*(p)))((__retx & __mask) >> __s); \
+ } \
})
-#define __arch_cmpxchg(lr_sfx, sc_sfx, prepend, append, r, p, co, o, n) \
+#define __arch_cmpxchg(lr_sfx, sc_sfx, cas_sfx, \
+ sc_prepend, sc_append, \
+ cas_prepend, cas_append, \
+ r, p, co, o, n) \
({ \
- register unsigned int __rc; \
+ if (IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) && \
+ riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)) { \
+ r = o; \
\
- __asm__ __volatile__ ( \
- prepend \
- "0: lr" lr_sfx " %0, %2\n" \
- " bne %0, %z3, 1f\n" \
- " sc" sc_sfx " %1, %z4, %2\n" \
- " bnez %1, 0b\n" \
- append \
- "1:\n" \
- : "=&r" (r), "=&r" (__rc), "+A" (*(p)) \
- : "rJ" (co o), "rJ" (n) \
- : "memory"); \
+ __asm__ __volatile__ ( \
+ cas_prepend \
+ " amocas" cas_sfx " %0, %z2, %1\n" \
+ cas_append \
+ : "+&r" (r), "+A" (*(p)) \
+ : "rJ" (n) \
+ : "memory"); \
+ } else { \
+ register unsigned int __rc; \
+ \
+ __asm__ __volatile__ ( \
+ sc_prepend \
+ "0: lr" lr_sfx " %0, %2\n" \
+ " bne %0, %z3, 1f\n" \
+ " sc" sc_sfx " %1, %z4, %2\n" \
+ " bnez %1, 0b\n" \
+ sc_append \
+ "1:\n" \
+ : "=&r" (r), "=&r" (__rc), "+A" (*(p)) \
+ : "rJ" (co o), "rJ" (n) \
+ : "memory"); \
+ } \
})
-#define _arch_cmpxchg(ptr, old, new, sc_sfx, prepend, append) \
+#define _arch_cmpxchg(ptr, old, new, sc_sfx, cas_sfx, \
+ sc_prepend, sc_append, \
+ cas_prepend, cas_append) \
({ \
__typeof__(ptr) __ptr = (ptr); \
__typeof__(*(__ptr)) __old = (old); \
@@ -163,17 +216,28 @@
\
switch (sizeof(*__ptr)) { \
case 1: \
+ __arch_cmpxchg_masked(sc_sfx, ".b" cas_sfx, \
+ sc_prepend, sc_append, \
+ cas_prepend, cas_append, \
+ __ret, __ptr, __old, __new); \
+ break; \
case 2: \
- __arch_cmpxchg_masked(sc_sfx, prepend, append, \
- __ret, __ptr, __old, __new); \
+ __arch_cmpxchg_masked(sc_sfx, ".h" cas_sfx, \
+ sc_prepend, sc_append, \
+ cas_prepend, cas_append, \
+ __ret, __ptr, __old, __new); \
break; \
case 4: \
- __arch_cmpxchg(".w", ".w" sc_sfx, prepend, append, \
- __ret, __ptr, (long), __old, __new); \
+ __arch_cmpxchg(".w", ".w" sc_sfx, ".w" cas_sfx, \
+ sc_prepend, sc_append, \
+ cas_prepend, cas_append, \
+ __ret, __ptr, (long), __old, __new); \
break; \
case 8: \
- __arch_cmpxchg(".d", ".d" sc_sfx, prepend, append, \
- __ret, __ptr, /**/, __old, __new); \
+ __arch_cmpxchg(".d", ".d" sc_sfx, ".d" cas_sfx, \
+ sc_prepend, sc_append, \
+ cas_prepend, cas_append, \
+ __ret, __ptr, /**/, __old, __new); \
break; \
default: \
BUILD_BUG(); \
@@ -181,17 +245,40 @@
(__typeof__(*(__ptr)))__ret; \
})
+/*
+ * These macros are here to improve the readability of the arch_cmpxchg_XXX()
+ * macros.
+ */
+#define SC_SFX(x) x
+#define CAS_SFX(x) x
+#define SC_PREPEND(x) x
+#define SC_APPEND(x) x
+#define CAS_PREPEND(x) x
+#define CAS_APPEND(x) x
+
#define arch_cmpxchg_relaxed(ptr, o, n) \
- _arch_cmpxchg((ptr), (o), (n), "", "", "")
+ _arch_cmpxchg((ptr), (o), (n), \
+ SC_SFX(""), CAS_SFX(""), \
+ SC_PREPEND(""), SC_APPEND(""), \
+ CAS_PREPEND(""), CAS_APPEND(""))
#define arch_cmpxchg_acquire(ptr, o, n) \
- _arch_cmpxchg((ptr), (o), (n), "", "", RISCV_ACQUIRE_BARRIER)
+ _arch_cmpxchg((ptr), (o), (n), \
+ SC_SFX(""), CAS_SFX(""), \
+ SC_PREPEND(""), SC_APPEND(RISCV_ACQUIRE_BARRIER), \
+ CAS_PREPEND(""), CAS_APPEND(RISCV_ACQUIRE_BARRIER))
#define arch_cmpxchg_release(ptr, o, n) \
- _arch_cmpxchg((ptr), (o), (n), "", RISCV_RELEASE_BARRIER, "")
+ _arch_cmpxchg((ptr), (o), (n), \
+ SC_SFX(""), CAS_SFX(""), \
+ SC_PREPEND(RISCV_RELEASE_BARRIER), SC_APPEND(""), \
+ CAS_PREPEND(RISCV_RELEASE_BARRIER), CAS_APPEND(""))
#define arch_cmpxchg(ptr, o, n) \
- _arch_cmpxchg((ptr), (o), (n), ".rl", "", " fence rw, rw\n")
+ _arch_cmpxchg((ptr), (o), (n), \
+ SC_SFX(".rl"), CAS_SFX(".aqrl"), \
+ SC_PREPEND(""), SC_APPEND(RISCV_FULL_BARRIER), \
+ CAS_PREPEND(""), CAS_APPEND(""))
#define arch_cmpxchg_local(ptr, o, n) \
arch_cmpxchg_relaxed((ptr), (o), (n))
@@ -226,6 +313,44 @@
arch_cmpxchg_release((ptr), (o), (n)); \
})
+#if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS)
+
+#define system_has_cmpxchg128() riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
+
+union __u128_halves {
+ u128 full;
+ struct {
+ u64 low, high;
+ };
+};
+
+#define __arch_cmpxchg128(p, o, n, cas_sfx) \
+({ \
+ __typeof__(*(p)) __o = (o); \
+ union __u128_halves __hn = { .full = (n) }; \
+ union __u128_halves __ho = { .full = (__o) }; \
+ register unsigned long t1 asm ("t1") = __hn.low; \
+ register unsigned long t2 asm ("t2") = __hn.high; \
+ register unsigned long t3 asm ("t3") = __ho.low; \
+ register unsigned long t4 asm ("t4") = __ho.high; \
+ \
+ __asm__ __volatile__ ( \
+ " amocas.q" cas_sfx " %0, %z3, %2" \
+ : "+&r" (t3), "+&r" (t4), "+A" (*(p)) \
+ : "rJ" (t1), "rJ" (t2) \
+ : "memory"); \
+ \
+ ((u128)t4 << 64) | t3; \
+})
+
+#define arch_cmpxchg128(ptr, o, n) \
+ __arch_cmpxchg128((ptr), (o), (n), ".aqrl")
+
+#define arch_cmpxchg128_local(ptr, o, n) \
+ __arch_cmpxchg128((ptr), (o), (n), "")
+
+#endif /* CONFIG_64BIT && CONFIG_RISCV_ISA_ZACAS */
+
#ifdef CONFIG_RISCV_ISA_ZAWRS
/*
* Despite wrs.nto being "WRS-with-no-timeout", in the absence of changes to
@@ -245,6 +370,11 @@ static __always_inline void __cmpwait(volatile void *ptr,
: : : : no_zawrs);
switch (size) {
+ case 1:
+ fallthrough;
+ case 2:
+ /* RISC-V doesn't have lr instructions on byte and half-word. */
+ goto no_zawrs;
case 4:
asm volatile(
" lr.w %0, %1\n"
diff --git a/arch/riscv/include/asm/compat.h b/arch/riscv/include/asm/compat.h
index aa103530a5c8..6081327e55f5 100644
--- a/arch/riscv/include/asm/compat.h
+++ b/arch/riscv/include/asm/compat.h
@@ -9,7 +9,6 @@
*/
#include <linux/types.h>
#include <linux/sched.h>
-#include <linux/sched/task_stack.h>
#include <asm-generic/compat.h>
static inline int is_compat_task(void)
diff --git a/arch/riscv/include/asm/cpufeature-macros.h b/arch/riscv/include/asm/cpufeature-macros.h
new file mode 100644
index 000000000000..a8103edbf51f
--- /dev/null
+++ b/arch/riscv/include/asm/cpufeature-macros.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright 2022-2024 Rivos, Inc
+ */
+
+#ifndef _ASM_CPUFEATURE_MACROS_H
+#define _ASM_CPUFEATURE_MACROS_H
+
+#include <asm/hwcap.h>
+#include <asm/alternative-macros.h>
+
+#define STANDARD_EXT 0
+
+bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned int bit);
+#define riscv_isa_extension_available(isa_bitmap, ext) \
+ __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
+
+static __always_inline bool __riscv_has_extension_likely(const unsigned long vendor,
+ const unsigned long ext)
+{
+ asm goto(ALTERNATIVE("j %l[l_no]", "nop", %[vendor], %[ext], 1)
+ :
+ : [vendor] "i" (vendor), [ext] "i" (ext)
+ :
+ : l_no);
+
+ return true;
+l_no:
+ return false;
+}
+
+static __always_inline bool __riscv_has_extension_unlikely(const unsigned long vendor,
+ const unsigned long ext)
+{
+ asm goto(ALTERNATIVE("nop", "j %l[l_yes]", %[vendor], %[ext], 1)
+ :
+ : [vendor] "i" (vendor), [ext] "i" (ext)
+ :
+ : l_yes);
+
+ return false;
+l_yes:
+ return true;
+}
+
+static __always_inline bool riscv_has_extension_unlikely(const unsigned long ext)
+{
+ compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
+
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
+ return __riscv_has_extension_unlikely(STANDARD_EXT, ext);
+
+ return __riscv_isa_extension_available(NULL, ext);
+}
+
+static __always_inline bool riscv_has_extension_likely(const unsigned long ext)
+{
+ compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
+
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
+ return __riscv_has_extension_likely(STANDARD_EXT, ext);
+
+ return __riscv_isa_extension_available(NULL, ext);
+}
+
+#endif /* _ASM_CPUFEATURE_MACROS_H */
diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h
index 45f9c1171a48..4bd054c54c21 100644
--- a/arch/riscv/include/asm/cpufeature.h
+++ b/arch/riscv/include/asm/cpufeature.h
@@ -8,9 +8,12 @@
#include <linux/bitmap.h>
#include <linux/jump_label.h>
+#include <linux/workqueue.h>
+#include <linux/kconfig.h>
+#include <linux/percpu-defs.h>
+#include <linux/threads.h>
#include <asm/hwcap.h>
-#include <asm/alternative-macros.h>
-#include <asm/errno.h>
+#include <asm/cpufeature-macros.h>
/*
* These are probed via a device_initcall(), via either the SBI or directly
@@ -31,7 +34,7 @@ DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
/* Per-cpu ISA extensions. */
extern struct riscv_isainfo hart_isa[NR_CPUS];
-void riscv_user_isa_enable(void);
+void __init riscv_user_isa_enable(void);
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
.name = #_name, \
@@ -58,8 +61,9 @@ void riscv_user_isa_enable(void);
#define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
-#if defined(CONFIG_RISCV_MISALIGNED)
bool check_unaligned_access_emulated_all_cpus(void);
+#if defined(CONFIG_RISCV_SCALAR_MISALIGNED)
+void check_unaligned_access_emulated(struct work_struct *work __always_unused);
void unaligned_emulation_finish(void);
bool unaligned_ctl_available(void);
DECLARE_PER_CPU(long, misaligned_access_speed);
@@ -70,6 +74,12 @@ static inline bool unaligned_ctl_available(void)
}
#endif
+bool check_vector_unaligned_access_emulated_all_cpus(void);
+#if defined(CONFIG_RISCV_VECTOR_MISALIGNED)
+void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused);
+DECLARE_PER_CPU(long, vector_misaligned_access);
+#endif
+
#if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS)
DECLARE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key);
@@ -103,61 +113,6 @@ extern const size_t riscv_isa_ext_count;
extern bool riscv_isa_fallback;
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
-
-#define STANDARD_EXT 0
-
-bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned int bit);
-#define riscv_isa_extension_available(isa_bitmap, ext) \
- __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
-
-static __always_inline bool __riscv_has_extension_likely(const unsigned long vendor,
- const unsigned long ext)
-{
- asm goto(ALTERNATIVE("j %l[l_no]", "nop", %[vendor], %[ext], 1)
- :
- : [vendor] "i" (vendor), [ext] "i" (ext)
- :
- : l_no);
-
- return true;
-l_no:
- return false;
-}
-
-static __always_inline bool __riscv_has_extension_unlikely(const unsigned long vendor,
- const unsigned long ext)
-{
- asm goto(ALTERNATIVE("nop", "j %l[l_yes]", %[vendor], %[ext], 1)
- :
- : [vendor] "i" (vendor), [ext] "i" (ext)
- :
- : l_yes);
-
- return false;
-l_yes:
- return true;
-}
-
-static __always_inline bool riscv_has_extension_unlikely(const unsigned long ext)
-{
- compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
-
- if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
- return __riscv_has_extension_unlikely(STANDARD_EXT, ext);
-
- return __riscv_isa_extension_available(NULL, ext);
-}
-
-static __always_inline bool riscv_has_extension_likely(const unsigned long ext)
-{
- compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
-
- if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
- return __riscv_has_extension_likely(STANDARD_EXT, ext);
-
- return __riscv_isa_extension_available(NULL, ext);
-}
-
static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
{
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 25966995da04..37bdea65bbd8 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -119,6 +119,10 @@
/* HSTATUS flags */
#ifdef CONFIG_64BIT
+#define HSTATUS_HUPMM _AC(0x3000000000000, UL)
+#define HSTATUS_HUPMM_PMLEN_0 _AC(0x0000000000000, UL)
+#define HSTATUS_HUPMM_PMLEN_7 _AC(0x2000000000000, UL)
+#define HSTATUS_HUPMM_PMLEN_16 _AC(0x3000000000000, UL)
#define HSTATUS_VSXL _AC(0x300000000, UL)
#define HSTATUS_VSXL_SHIFT 32
#endif
@@ -195,6 +199,11 @@
/* xENVCFG flags */
#define ENVCFG_STCE (_AC(1, ULL) << 63)
#define ENVCFG_PBMTE (_AC(1, ULL) << 62)
+#define ENVCFG_ADUE (_AC(1, ULL) << 61)
+#define ENVCFG_PMM (_AC(0x3, ULL) << 32)
+#define ENVCFG_PMM_PMLEN_0 (_AC(0x0, ULL) << 32)
+#define ENVCFG_PMM_PMLEN_7 (_AC(0x2, ULL) << 32)
+#define ENVCFG_PMM_PMLEN_16 (_AC(0x3, ULL) << 32)
#define ENVCFG_CBZE (_AC(1, UL) << 7)
#define ENVCFG_CBCFE (_AC(1, UL) << 6)
#define ENVCFG_CBIE_SHIFT 4
@@ -216,6 +225,12 @@
#define SMSTATEEN0_SSTATEEN0_SHIFT 63
#define SMSTATEEN0_SSTATEEN0 (_ULL(1) << SMSTATEEN0_SSTATEEN0_SHIFT)
+/* mseccfg bits */
+#define MSECCFG_PMM ENVCFG_PMM
+#define MSECCFG_PMM_PMLEN_0 ENVCFG_PMM_PMLEN_0
+#define MSECCFG_PMM_PMLEN_7 ENVCFG_PMM_PMLEN_7
+#define MSECCFG_PMM_PMLEN_16 ENVCFG_PMM_PMLEN_16
+
/* symbolic CSR names: */
#define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01
@@ -382,6 +397,8 @@
#define CSR_MIP 0x344
#define CSR_PMPCFG0 0x3a0
#define CSR_PMPADDR0 0x3b0
+#define CSR_MSECCFG 0x747
+#define CSR_MSECCFGH 0x757
#define CSR_MVENDORID 0xf11
#define CSR_MARCHID 0xf12
#define CSR_MIMPID 0xf13
diff --git a/arch/riscv/include/asm/entry-common.h b/arch/riscv/include/asm/entry-common.h
index 2293e535f865..b28ccc6cdeea 100644
--- a/arch/riscv/include/asm/entry-common.h
+++ b/arch/riscv/include/asm/entry-common.h
@@ -33,6 +33,7 @@ static inline int handle_misaligned_load(struct pt_regs *regs)
{
return -1;
}
+
static inline int handle_misaligned_store(struct pt_regs *regs)
{
return -1;
diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
index 2cddd79ff21b..3d66437a1029 100644
--- a/arch/riscv/include/asm/ftrace.h
+++ b/arch/riscv/include/asm/ftrace.h
@@ -125,8 +125,12 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
#define arch_ftrace_get_regs(regs) NULL
+#define HAVE_ARCH_FTRACE_REGS
struct ftrace_ops;
-struct ftrace_regs {
+struct ftrace_regs;
+#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
+
+struct __arch_ftrace_regs {
unsigned long epc;
unsigned long ra;
unsigned long sp;
@@ -150,42 +154,42 @@ struct ftrace_regs {
static __always_inline unsigned long ftrace_regs_get_instruction_pointer(const struct ftrace_regs
*fregs)
{
- return fregs->epc;
+ return arch_ftrace_regs(fregs)->epc;
}
static __always_inline void ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
unsigned long pc)
{
- fregs->epc = pc;
+ arch_ftrace_regs(fregs)->epc = pc;
}
static __always_inline unsigned long ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs)
{
- return fregs->sp;
+ return arch_ftrace_regs(fregs)->sp;
}
static __always_inline unsigned long ftrace_regs_get_argument(struct ftrace_regs *fregs,
unsigned int n)
{
if (n < 8)
- return fregs->args[n];
+ return arch_ftrace_regs(fregs)->args[n];
return 0;
}
static __always_inline unsigned long ftrace_regs_get_return_value(const struct ftrace_regs *fregs)
{
- return fregs->a0;
+ return arch_ftrace_regs(fregs)->a0;
}
static __always_inline void ftrace_regs_set_return_value(struct ftrace_regs *fregs,
unsigned long ret)
{
- fregs->a0 = ret;
+ arch_ftrace_regs(fregs)->a0 = ret;
}
static __always_inline void ftrace_override_function_with_return(struct ftrace_regs *fregs)
{
- fregs->epc = fregs->ra;
+ arch_ftrace_regs(fregs)->epc = arch_ftrace_regs(fregs)->ra;
}
int ftrace_regs_query_register_offset(const char *name);
@@ -196,7 +200,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
{
- fregs->t1 = addr;
+ arch_ftrace_regs(fregs)->t1 = addr;
}
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 46d9de54179e..869da082252a 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -93,6 +93,13 @@
#define RISCV_ISA_EXT_ZCMOP 84
#define RISCV_ISA_EXT_ZAWRS 85
#define RISCV_ISA_EXT_SVVPTC 86
+#define RISCV_ISA_EXT_SMMPM 87
+#define RISCV_ISA_EXT_SMNPM 88
+#define RISCV_ISA_EXT_SSNPM 89
+#define RISCV_ISA_EXT_ZABHA 90
+#define RISCV_ISA_EXT_ZICCRSE 91
+#define RISCV_ISA_EXT_SVADE 92
+#define RISCV_ISA_EXT_SVADU 93
#define RISCV_ISA_EXT_XLINUXENVCFG 127
@@ -101,8 +108,10 @@
#ifdef CONFIG_RISCV_M_MODE
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA
+#define RISCV_ISA_EXT_SUPM RISCV_ISA_EXT_SMNPM
#else
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA
+#define RISCV_ISA_EXT_SUPM RISCV_ISA_EXT_SSNPM
#endif
#endif /* _ASM_RISCV_HWCAP_H */
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index ffb9484531af..1ce1df6d0ff3 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,7 +8,7 @@
#include <uapi/asm/hwprobe.h>
-#define RISCV_HWPROBE_MAX_KEY 9
+#define RISCV_HWPROBE_MAX_KEY 10
static inline bool riscv_hwprobe_key_is_valid(__s64 key)
{
diff --git a/arch/riscv/include/asm/jump_label.h b/arch/riscv/include/asm/jump_label.h
index 1c768d02bd0c..87a71cc6d146 100644
--- a/arch/riscv/include/asm/jump_label.h
+++ b/arch/riscv/include/asm/jump_label.h
@@ -16,21 +16,28 @@
#define JUMP_LABEL_NOP_SIZE 4
+#define JUMP_TABLE_ENTRY(key, label) \
+ ".pushsection __jump_table, \"aw\" \n\t" \
+ ".align " RISCV_LGPTR " \n\t" \
+ ".long 1b - ., " label " - . \n\t" \
+ "" RISCV_PTR " " key " - . \n\t" \
+ ".popsection \n\t"
+
+/* This macro is also expanded on the Rust side. */
+#define ARCH_STATIC_BRANCH_ASM(key, label) \
+ " .align 2 \n\t" \
+ " .option push \n\t" \
+ " .option norelax \n\t" \
+ " .option norvc \n\t" \
+ "1: nop \n\t" \
+ " .option pop \n\t" \
+ JUMP_TABLE_ENTRY(key, label)
+
static __always_inline bool arch_static_branch(struct static_key * const key,
const bool branch)
{
asm goto(
- " .align 2 \n\t"
- " .option push \n\t"
- " .option norelax \n\t"
- " .option norvc \n\t"
- "1: nop \n\t"
- " .option pop \n\t"
- " .pushsection __jump_table, \"aw\" \n\t"
- " .align " RISCV_LGPTR " \n\t"
- " .long 1b - ., %l[label] - . \n\t"
- " " RISCV_PTR " %0 - . \n\t"
- " .popsection \n\t"
+ ARCH_STATIC_BRANCH_ASM("%0", "%l[label]")
: : "i"(&((char *)key)[branch]) : : label);
return false;
@@ -38,21 +45,20 @@ label:
return true;
}
+#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \
+ " .align 2 \n\t" \
+ " .option push \n\t" \
+ " .option norelax \n\t" \
+ " .option norvc \n\t" \
+ "1: j " label " \n\t" \
+ " .option pop \n\t" \
+ JUMP_TABLE_ENTRY(key, label)
+
static __always_inline bool arch_static_branch_jump(struct static_key * const key,
const bool branch)
{
asm goto(
- " .align 2 \n\t"
- " .option push \n\t"
- " .option norelax \n\t"
- " .option norvc \n\t"
- "1: j %l[label] \n\t"
- " .option pop \n\t"
- " .pushsection __jump_table, \"aw\" \n\t"
- " .align " RISCV_LGPTR " \n\t"
- " .long 1b - ., %l[label] - . \n\t"
- " " RISCV_PTR " %0 - . \n\t"
- " .popsection \n\t"
+ ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[label]")
: : "i"(&((char *)key)[branch]) : : label);
return false;
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index 2e2254fd2a2a..35eab6e0f4ae 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -286,6 +286,16 @@ struct kvm_vcpu_arch {
} sta;
};
+/*
+ * Returns true if a Performance Monitoring Interrupt (PMI), a.k.a. perf event,
+ * arrived in guest context. For riscv, any event that arrives while a vCPU is
+ * loaded is considered to be "in guest".
+ */
+static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)
+{
+ return IS_ENABLED(CONFIG_GUEST_PERF_EVENTS) && !!vcpu;
+}
+
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
#define KVM_RISCV_GSTAGE_TLB_MIN_ORDER 12
diff --git a/arch/riscv/include/asm/kvm_nacl.h b/arch/riscv/include/asm/kvm_nacl.h
new file mode 100644
index 000000000000..4124d5e06a0f
--- /dev/null
+++ b/arch/riscv/include/asm/kvm_nacl.h
@@ -0,0 +1,245 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ */
+
+#ifndef __KVM_NACL_H
+#define __KVM_NACL_H
+
+#include <linux/jump_label.h>
+#include <linux/percpu.h>
+#include <asm/byteorder.h>
+#include <asm/csr.h>
+#include <asm/sbi.h>
+
+struct kvm_vcpu_arch;
+
+DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_available);
+#define kvm_riscv_nacl_available() \
+ static_branch_unlikely(&kvm_riscv_nacl_available)
+
+DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_csr_available);
+#define kvm_riscv_nacl_sync_csr_available() \
+ static_branch_unlikely(&kvm_riscv_nacl_sync_csr_available)
+
+DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_hfence_available);
+#define kvm_riscv_nacl_sync_hfence_available() \
+ static_branch_unlikely(&kvm_riscv_nacl_sync_hfence_available)
+
+DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_sret_available);
+#define kvm_riscv_nacl_sync_sret_available() \
+ static_branch_unlikely(&kvm_riscv_nacl_sync_sret_available)
+
+DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_autoswap_csr_available);
+#define kvm_riscv_nacl_autoswap_csr_available() \
+ static_branch_unlikely(&kvm_riscv_nacl_autoswap_csr_available)
+
+struct kvm_riscv_nacl {
+ void *shmem;
+ phys_addr_t shmem_phys;
+};
+DECLARE_PER_CPU(struct kvm_riscv_nacl, kvm_riscv_nacl);
+
+void __kvm_riscv_nacl_hfence(void *shmem,
+ unsigned long control,
+ unsigned long page_num,
+ unsigned long page_count);
+
+void __kvm_riscv_nacl_switch_to(struct kvm_vcpu_arch *vcpu_arch,
+ unsigned long sbi_ext_id,
+ unsigned long sbi_func_id);
+
+int kvm_riscv_nacl_enable(void);
+
+void kvm_riscv_nacl_disable(void);
+
+void kvm_riscv_nacl_exit(void);
+
+int kvm_riscv_nacl_init(void);
+
+#ifdef CONFIG_32BIT
+#define lelong_to_cpu(__x) le32_to_cpu(__x)
+#define cpu_to_lelong(__x) cpu_to_le32(__x)
+#else
+#define lelong_to_cpu(__x) le64_to_cpu(__x)
+#define cpu_to_lelong(__x) cpu_to_le64(__x)
+#endif
+
+#define nacl_shmem() \
+ this_cpu_ptr(&kvm_riscv_nacl)->shmem
+
+#define nacl_scratch_read_long(__shmem, __offset) \
+({ \
+ unsigned long *__p = (__shmem) + \
+ SBI_NACL_SHMEM_SCRATCH_OFFSET + \
+ (__offset); \
+ lelong_to_cpu(*__p); \
+})
+
+#define nacl_scratch_write_long(__shmem, __offset, __val) \
+do { \
+ unsigned long *__p = (__shmem) + \
+ SBI_NACL_SHMEM_SCRATCH_OFFSET + \
+ (__offset); \
+ *__p = cpu_to_lelong(__val); \
+} while (0)
+
+#define nacl_scratch_write_longs(__shmem, __offset, __array, __count) \
+do { \
+ unsigned int __i; \
+ unsigned long *__p = (__shmem) + \
+ SBI_NACL_SHMEM_SCRATCH_OFFSET + \
+ (__offset); \
+ for (__i = 0; __i < (__count); __i++) \
+ __p[__i] = cpu_to_lelong((__array)[__i]); \
+} while (0)
+
+#define nacl_sync_hfence(__e) \
+ sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SYNC_HFENCE, \
+ (__e), 0, 0, 0, 0, 0)
+
+#define nacl_hfence_mkconfig(__type, __order, __vmid, __asid) \
+({ \
+ unsigned long __c = SBI_NACL_SHMEM_HFENCE_CONFIG_PEND; \
+ __c |= ((__type) & SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_MASK) \
+ << SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_SHIFT; \
+ __c |= (((__order) - SBI_NACL_SHMEM_HFENCE_ORDER_BASE) & \
+ SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_MASK) \
+ << SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_SHIFT; \
+ __c |= ((__vmid) & SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_MASK) \
+ << SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_SHIFT; \
+ __c |= ((__asid) & SBI_NACL_SHMEM_HFENCE_CONFIG_ASID_MASK); \
+ __c; \
+})
+
+#define nacl_hfence_mkpnum(__order, __addr) \
+ ((__addr) >> (__order))
+
+#define nacl_hfence_mkpcount(__order, __size) \
+ ((__size) >> (__order))
+
+#define nacl_hfence_gvma(__shmem, __gpa, __gpsz, __order) \
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA, \
+ __order, 0, 0), \
+ nacl_hfence_mkpnum(__order, __gpa), \
+ nacl_hfence_mkpcount(__order, __gpsz))
+
+#define nacl_hfence_gvma_all(__shmem) \
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_ALL, \
+ 0, 0, 0), 0, 0)
+
+#define nacl_hfence_gvma_vmid(__shmem, __vmid, __gpa, __gpsz, __order) \
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_VMID, \
+ __order, __vmid, 0), \
+ nacl_hfence_mkpnum(__order, __gpa), \
+ nacl_hfence_mkpcount(__order, __gpsz))
+
+#define nacl_hfence_gvma_vmid_all(__shmem, __vmid) \
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_VMID_ALL, \
+ 0, __vmid, 0), 0, 0)
+
+#define nacl_hfence_vvma(__shmem, __vmid, __gva, __gvsz, __order) \
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA, \
+ __order, __vmid, 0), \
+ nacl_hfence_mkpnum(__order, __gva), \
+ nacl_hfence_mkpcount(__order, __gvsz))
+
+#define nacl_hfence_vvma_all(__shmem, __vmid) \
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ALL, \
+ 0, __vmid, 0), 0, 0)
+
+#define nacl_hfence_vvma_asid(__shmem, __vmid, __asid, __gva, __gvsz, __order)\
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ASID, \
+ __order, __vmid, __asid), \
+ nacl_hfence_mkpnum(__order, __gva), \
+ nacl_hfence_mkpcount(__order, __gvsz))
+
+#define nacl_hfence_vvma_asid_all(__shmem, __vmid, __asid) \
+__kvm_riscv_nacl_hfence(__shmem, \
+ nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ASID_ALL, \
+ 0, __vmid, __asid), 0, 0)
+
+#define nacl_csr_read(__shmem, __csr) \
+({ \
+ unsigned long *__a = (__shmem) + SBI_NACL_SHMEM_CSR_OFFSET; \
+ lelong_to_cpu(__a[SBI_NACL_SHMEM_CSR_INDEX(__csr)]); \
+})
+
+#define nacl_csr_write(__shmem, __csr, __val) \
+do { \
+ void *__s = (__shmem); \
+ unsigned int __i = SBI_NACL_SHMEM_CSR_INDEX(__csr); \
+ unsigned long *__a = (__s) + SBI_NACL_SHMEM_CSR_OFFSET; \
+ u8 *__b = (__s) + SBI_NACL_SHMEM_DBITMAP_OFFSET; \
+ __a[__i] = cpu_to_lelong(__val); \
+ __b[__i >> 3] |= 1U << (__i & 0x7); \
+} while (0)
+
+#define nacl_csr_swap(__shmem, __csr, __val) \
+({ \
+ void *__s = (__shmem); \
+ unsigned int __i = SBI_NACL_SHMEM_CSR_INDEX(__csr); \
+ unsigned long *__a = (__s) + SBI_NACL_SHMEM_CSR_OFFSET; \
+ u8 *__b = (__s) + SBI_NACL_SHMEM_DBITMAP_OFFSET; \
+ unsigned long __r = lelong_to_cpu(__a[__i]); \
+ __a[__i] = cpu_to_lelong(__val); \
+ __b[__i >> 3] |= 1U << (__i & 0x7); \
+ __r; \
+})
+
+#define nacl_sync_csr(__csr) \
+ sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SYNC_CSR, \
+ (__csr), 0, 0, 0, 0, 0)
+
+/*
+ * Each ncsr_xyz() macro defined below has it's own static-branch so every
+ * use of ncsr_xyz() macro emits a patchable direct jump. This means multiple
+ * back-to-back ncsr_xyz() macro usage will emit multiple patchable direct
+ * jumps which is sub-optimal.
+ *
+ * Based on the above, it is recommended to avoid multiple back-to-back
+ * ncsr_xyz() macro usage.
+ */
+
+#define ncsr_read(__csr) \
+({ \
+ unsigned long __r; \
+ if (kvm_riscv_nacl_available()) \
+ __r = nacl_csr_read(nacl_shmem(), __csr); \
+ else \
+ __r = csr_read(__csr); \
+ __r; \
+})
+
+#define ncsr_write(__csr, __val) \
+do { \
+ if (kvm_riscv_nacl_sync_csr_available()) \
+ nacl_csr_write(nacl_shmem(), __csr, __val); \
+ else \
+ csr_write(__csr, __val); \
+} while (0)
+
+#define ncsr_swap(__csr, __val) \
+({ \
+ unsigned long __r; \
+ if (kvm_riscv_nacl_sync_csr_available()) \
+ __r = nacl_csr_swap(nacl_shmem(), __csr, __val); \
+ else \
+ __r = csr_swap(__csr, __val); \
+ __r; \
+})
+
+#define nsync_csr(__csr) \
+do { \
+ if (kvm_riscv_nacl_sync_csr_available()) \
+ nacl_sync_csr(__csr); \
+} while (0)
+
+#endif
diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h
index c9e03e9da3dc..1cc90465d75b 100644
--- a/arch/riscv/include/asm/mmu.h
+++ b/arch/riscv/include/asm/mmu.h
@@ -26,8 +26,15 @@ typedef struct {
unsigned long exec_fdpic_loadmap;
unsigned long interp_fdpic_loadmap;
#endif
+ unsigned long flags;
+#ifdef CONFIG_RISCV_ISA_SUPM
+ u8 pmlen;
+#endif
} mm_context_t;
+/* Lock the pointer masking mode because this mm is multithreaded */
+#define MM_CONTEXT_LOCK_PMLEN 0
+
#define cntx2asid(cntx) ((cntx) & SATP_ASID_MASK)
#define cntx2version(cntx) ((cntx) & ~SATP_ASID_MASK)
diff --git a/arch/riscv/include/asm/mmu_context.h b/arch/riscv/include/asm/mmu_context.h
index 7030837adc1a..8c4bc49a3a0f 100644
--- a/arch/riscv/include/asm/mmu_context.h
+++ b/arch/riscv/include/asm/mmu_context.h
@@ -20,6 +20,9 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
static inline void activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
+#ifdef CONFIG_RISCV_ISA_SUPM
+ next->context.pmlen = 0;
+#endif
switch_mm(prev, next, NULL);
}
@@ -30,11 +33,21 @@ static inline int init_new_context(struct task_struct *tsk,
#ifdef CONFIG_MMU
atomic_long_set(&mm->context.id, 0);
#endif
+ if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM))
+ clear_bit(MM_CONTEXT_LOCK_PMLEN, &mm->context.flags);
return 0;
}
DECLARE_STATIC_KEY_FALSE(use_asid_allocator);
+#ifdef CONFIG_RISCV_ISA_SUPM
+#define mm_untag_mask mm_untag_mask
+static inline unsigned long mm_untag_mask(struct mm_struct *mm)
+{
+ return -1UL >> mm->context.pmlen;
+}
+#endif
+
#include <asm-generic/mmu_context.h>
#endif /* _ASM_RISCV_MMU_CONTEXT_H */
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
index 32d308a3355f..71aabc5c6713 100644
--- a/arch/riscv/include/asm/page.h
+++ b/arch/riscv/include/asm/page.h
@@ -12,9 +12,7 @@
#include <linux/pfn.h>
#include <linux/const.h>
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE - 1))
+#include <vdso/page.h>
#define HPAGE_SHIFT PMD_SHIFT
#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
@@ -194,9 +192,6 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x);
#define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr)))
#define page_to_virt(page) (pfn_to_virt(page_to_pfn(page)))
-#define page_to_phys(page) (pfn_to_phys(page_to_pfn(page)))
-#define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr)))
-
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
unsigned long kaslr_offset(void);
diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h
index 665bbc9b2f84..bcc928fd3785 100644
--- a/arch/riscv/include/asm/perf_event.h
+++ b/arch/riscv/include/asm/perf_event.h
@@ -8,6 +8,7 @@
#ifndef _ASM_RISCV_PERF_EVENT_H
#define _ASM_RISCV_PERF_EVENT_H
+#ifdef CONFIG_PERF_EVENTS
#include <linux/perf_event.h>
#define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs
@@ -17,4 +18,6 @@
(regs)->sp = current_stack_pointer; \
(regs)->status = SR_PP; \
}
+#endif
+
#endif /* _ASM_RISCV_PERF_EVENT_H */
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index e79f15293492..d4e99eef90ac 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -113,6 +113,7 @@
#include <asm/tlbflush.h>
#include <linux/mm_types.h>
#include <asm/compat.h>
+#include <asm/cpufeature.h>
#define __page_val_to_pfn(_val) (((_val) & _PAGE_PFN_MASK) >> _PAGE_PFN_SHIFT)
@@ -284,7 +285,6 @@ static inline pte_t pud_pte(pud_t pud)
}
#ifdef CONFIG_RISCV_ISA_SVNAPOT
-#include <asm/cpufeature.h>
static __always_inline bool has_svnapot(void)
{
@@ -656,6 +656,17 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
}
/*
+ * Both Svade and Svadu control the hardware behavior when the PTE A/D bits need to be set. By
+ * default the M-mode firmware enables the hardware updating scheme when only Svadu is present in
+ * DT.
+ */
+#define arch_has_hw_pte_young arch_has_hw_pte_young
+static inline bool arch_has_hw_pte_young(void)
+{
+ return riscv_has_extension_unlikely(RISCV_ISA_EXT_SVADU);
+}
+
+/*
* THP functions
*/
static inline pmd_t pte_pmd(pte_t pte)
@@ -963,6 +974,25 @@ void misc_mem_init(void);
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+/*
+ * Use set_p*_safe(), and elide TLB flushing, when confident that *no*
+ * TLB flush will be required as a result of the "set". For example, use
+ * in scenarios where it is known ahead of time that the routine is
+ * setting non-present entries, or re-setting an existing entry to the
+ * same value. Otherwise, use the typical "set" helpers and flush the
+ * TLB.
+ */
+#define set_p4d_safe(p4dp, p4d) \
+({ \
+ WARN_ON_ONCE(p4d_present(*p4dp) && !p4d_same(*p4dp, p4d)); \
+ set_p4d(p4dp, p4d); \
+})
+
+#define set_pgd_safe(pgdp, pgd) \
+({ \
+ WARN_ON_ONCE(pgd_present(*pgdp) && !pgd_same(*pgdp, pgd)); \
+ set_pgd(pgdp, pgd); \
+})
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_RISCV_PGTABLE_H */
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index efa1b3519b23..5f56eb9d114a 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -102,6 +102,7 @@ struct thread_struct {
unsigned long s[12]; /* s[0]: frame pointer */
struct __riscv_d_ext_state fstate;
unsigned long bad_cause;
+ unsigned long envcfg;
u32 riscv_v_flags;
u32 vstate_ctrl;
struct __riscv_v_ext_state vstate;
@@ -177,6 +178,14 @@ extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
#define RISCV_SET_ICACHE_FLUSH_CTX(arg1, arg2) riscv_set_icache_flush_ctx(arg1, arg2)
extern int riscv_set_icache_flush_ctx(unsigned long ctx, unsigned long per_thread);
+#ifdef CONFIG_RISCV_ISA_SUPM
+/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */
+long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg);
+long get_tagged_addr_ctrl(struct task_struct *task);
+#define SET_TAGGED_ADDR_CTRL(arg) set_tagged_addr_ctrl(current, arg)
+#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl(current)
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_RISCV_PROCESSOR_H */
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index 98f631b051db..6c82318065cf 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -34,6 +34,7 @@ enum sbi_ext_id {
SBI_EXT_PMU = 0x504D55,
SBI_EXT_DBCN = 0x4442434E,
SBI_EXT_STA = 0x535441,
+ SBI_EXT_NACL = 0x4E41434C,
/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
@@ -281,6 +282,125 @@ struct sbi_sta_struct {
#define SBI_SHMEM_DISABLE -1
+enum sbi_ext_nacl_fid {
+ SBI_EXT_NACL_PROBE_FEATURE = 0x0,
+ SBI_EXT_NACL_SET_SHMEM = 0x1,
+ SBI_EXT_NACL_SYNC_CSR = 0x2,
+ SBI_EXT_NACL_SYNC_HFENCE = 0x3,
+ SBI_EXT_NACL_SYNC_SRET = 0x4,
+};
+
+enum sbi_ext_nacl_feature {
+ SBI_NACL_FEAT_SYNC_CSR = 0x0,
+ SBI_NACL_FEAT_SYNC_HFENCE = 0x1,
+ SBI_NACL_FEAT_SYNC_SRET = 0x2,
+ SBI_NACL_FEAT_AUTOSWAP_CSR = 0x3,
+};
+
+#define SBI_NACL_SHMEM_ADDR_SHIFT 12
+#define SBI_NACL_SHMEM_SCRATCH_OFFSET 0x0000
+#define SBI_NACL_SHMEM_SCRATCH_SIZE 0x1000
+#define SBI_NACL_SHMEM_SRET_OFFSET 0x0000
+#define SBI_NACL_SHMEM_SRET_SIZE 0x0200
+#define SBI_NACL_SHMEM_AUTOSWAP_OFFSET (SBI_NACL_SHMEM_SRET_OFFSET + \
+ SBI_NACL_SHMEM_SRET_SIZE)
+#define SBI_NACL_SHMEM_AUTOSWAP_SIZE 0x0080
+#define SBI_NACL_SHMEM_UNUSED_OFFSET (SBI_NACL_SHMEM_AUTOSWAP_OFFSET + \
+ SBI_NACL_SHMEM_AUTOSWAP_SIZE)
+#define SBI_NACL_SHMEM_UNUSED_SIZE 0x0580
+#define SBI_NACL_SHMEM_HFENCE_OFFSET (SBI_NACL_SHMEM_UNUSED_OFFSET + \
+ SBI_NACL_SHMEM_UNUSED_SIZE)
+#define SBI_NACL_SHMEM_HFENCE_SIZE 0x0780
+#define SBI_NACL_SHMEM_DBITMAP_OFFSET (SBI_NACL_SHMEM_HFENCE_OFFSET + \
+ SBI_NACL_SHMEM_HFENCE_SIZE)
+#define SBI_NACL_SHMEM_DBITMAP_SIZE 0x0080
+#define SBI_NACL_SHMEM_CSR_OFFSET (SBI_NACL_SHMEM_DBITMAP_OFFSET + \
+ SBI_NACL_SHMEM_DBITMAP_SIZE)
+#define SBI_NACL_SHMEM_CSR_SIZE ((__riscv_xlen / 8) * 1024)
+#define SBI_NACL_SHMEM_SIZE (SBI_NACL_SHMEM_CSR_OFFSET + \
+ SBI_NACL_SHMEM_CSR_SIZE)
+
+#define SBI_NACL_SHMEM_CSR_INDEX(__csr_num) \
+ ((((__csr_num) & 0xc00) >> 2) | ((__csr_num) & 0xff))
+
+#define SBI_NACL_SHMEM_HFENCE_ENTRY_SZ ((__riscv_xlen / 8) * 4)
+#define SBI_NACL_SHMEM_HFENCE_ENTRY_MAX \
+ (SBI_NACL_SHMEM_HFENCE_SIZE / \
+ SBI_NACL_SHMEM_HFENCE_ENTRY_SZ)
+#define SBI_NACL_SHMEM_HFENCE_ENTRY(__num) \
+ (SBI_NACL_SHMEM_HFENCE_OFFSET + \
+ (__num) * SBI_NACL_SHMEM_HFENCE_ENTRY_SZ)
+#define SBI_NACL_SHMEM_HFENCE_ENTRY_CONFIG(__num) \
+ SBI_NACL_SHMEM_HFENCE_ENTRY(__num)
+#define SBI_NACL_SHMEM_HFENCE_ENTRY_PNUM(__num)\
+ (SBI_NACL_SHMEM_HFENCE_ENTRY(__num) + (__riscv_xlen / 8))
+#define SBI_NACL_SHMEM_HFENCE_ENTRY_PCOUNT(__num)\
+ (SBI_NACL_SHMEM_HFENCE_ENTRY(__num) + \
+ ((__riscv_xlen / 8) * 3))
+
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_BITS 1
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_SHIFT \
+ (__riscv_xlen - SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_BITS)
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_MASK \
+ ((1UL << SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_BITS) - 1)
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_PEND \
+ (SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_MASK << \
+ SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_SHIFT)
+
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD1_BITS 3
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD1_SHIFT \
+ (SBI_NACL_SHMEM_HFENCE_CONFIG_PEND_SHIFT - \
+ SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD1_BITS)
+
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_BITS 4
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_SHIFT \
+ (SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD1_SHIFT - \
+ SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_BITS)
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_MASK \
+ ((1UL << SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_BITS) - 1)
+
+#define SBI_NACL_SHMEM_HFENCE_TYPE_GVMA 0x0
+#define SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_ALL 0x1
+#define SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_VMID 0x2
+#define SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_VMID_ALL 0x3
+#define SBI_NACL_SHMEM_HFENCE_TYPE_VVMA 0x4
+#define SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ALL 0x5
+#define SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ASID 0x6
+#define SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ASID_ALL 0x7
+
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD2_BITS 1
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD2_SHIFT \
+ (SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_SHIFT - \
+ SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD2_BITS)
+
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_BITS 7
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_SHIFT \
+ (SBI_NACL_SHMEM_HFENCE_CONFIG_RSVD2_SHIFT - \
+ SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_BITS)
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_MASK \
+ ((1UL << SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_BITS) - 1)
+#define SBI_NACL_SHMEM_HFENCE_ORDER_BASE 12
+
+#if __riscv_xlen == 32
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_ASID_BITS 9
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_BITS 7
+#else
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_ASID_BITS 16
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_BITS 14
+#endif
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_SHIFT \
+ SBI_NACL_SHMEM_HFENCE_CONFIG_ASID_BITS
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_ASID_MASK \
+ ((1UL << SBI_NACL_SHMEM_HFENCE_CONFIG_ASID_BITS) - 1)
+#define SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_MASK \
+ ((1UL << SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_BITS) - 1)
+
+#define SBI_NACL_SHMEM_AUTOSWAP_FLAG_HSTATUS BIT(0)
+#define SBI_NACL_SHMEM_AUTOSWAP_HSTATUS ((__riscv_xlen / 8) * 1)
+
+#define SBI_NACL_SHMEM_SRET_X(__i) ((__riscv_xlen / 8) * (__i))
+#define SBI_NACL_SHMEM_SRET_X_LAST 31
+
/* SBI spec version fields */
#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
index ab92fc84e1fc..ea263d3683ef 100644
--- a/arch/riscv/include/asm/set_memory.h
+++ b/arch/riscv/include/asm/set_memory.h
@@ -42,6 +42,7 @@ static inline int set_kernel_memory(char *startp, char *endp,
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
bool kernel_page_present(struct page *page);
#endif /* __ASSEMBLY__ */
diff --git a/arch/riscv/include/asm/spinlock.h b/arch/riscv/include/asm/spinlock.h
new file mode 100644
index 000000000000..e5121b89acea
--- /dev/null
+++ b/arch/riscv/include/asm/spinlock.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_RISCV_SPINLOCK_H
+#define __ASM_RISCV_SPINLOCK_H
+
+#ifdef CONFIG_RISCV_COMBO_SPINLOCKS
+#define _Q_PENDING_LOOPS (1 << 9)
+
+#define __no_arch_spinlock_redefine
+#include <asm/ticket_spinlock.h>
+#include <asm/qspinlock.h>
+#include <asm/jump_label.h>
+
+/*
+ * TODO: Use an alternative instead of a static key when we are able to parse
+ * the extensions string earlier in the boot process.
+ */
+DECLARE_STATIC_KEY_TRUE(qspinlock_key);
+
+#define SPINLOCK_BASE_DECLARE(op, type, type_lock) \
+static __always_inline type arch_spin_##op(type_lock lock) \
+{ \
+ if (static_branch_unlikely(&qspinlock_key)) \
+ return queued_spin_##op(lock); \
+ return ticket_spin_##op(lock); \
+}
+
+SPINLOCK_BASE_DECLARE(lock, void, arch_spinlock_t *)
+SPINLOCK_BASE_DECLARE(unlock, void, arch_spinlock_t *)
+SPINLOCK_BASE_DECLARE(is_locked, int, arch_spinlock_t *)
+SPINLOCK_BASE_DECLARE(is_contended, int, arch_spinlock_t *)
+SPINLOCK_BASE_DECLARE(trylock, bool, arch_spinlock_t *)
+SPINLOCK_BASE_DECLARE(value_unlocked, int, arch_spinlock_t)
+
+#elif defined(CONFIG_RISCV_QUEUED_SPINLOCKS)
+
+#include <asm/qspinlock.h>
+
+#else
+
+#include <asm/ticket_spinlock.h>
+
+#endif
+
+#include <asm/qrwlock.h>
+
+#endif /* __ASM_RISCV_SPINLOCK_H */
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index 7594df37cc9f..94e33216b2d9 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -70,6 +70,24 @@ static __always_inline bool has_fpu(void) { return false; }
#define __switch_to_fpu(__prev, __next) do { } while (0)
#endif
+static inline void envcfg_update_bits(struct task_struct *task,
+ unsigned long mask, unsigned long val)
+{
+ unsigned long envcfg;
+
+ envcfg = (task->thread.envcfg & ~mask) | val;
+ task->thread.envcfg = envcfg;
+ if (task == current)
+ csr_write(CSR_ENVCFG, envcfg);
+}
+
+static inline void __switch_to_envcfg(struct task_struct *next)
+{
+ asm volatile (ALTERNATIVE("nop", "csrw " __stringify(CSR_ENVCFG) ", %0",
+ 0, RISCV_ISA_EXT_XLINUXENVCFG, 1)
+ :: "r" (next->thread.envcfg) : "memory");
+}
+
extern struct task_struct *__switch_to(struct task_struct *,
struct task_struct *);
@@ -103,6 +121,7 @@ do { \
__switch_to_vector(__prev, __next); \
if (switch_to_should_flush_icache(__next)) \
local_flush_icache_all(); \
+ __switch_to_envcfg(__next); \
((last) = __switch_to(__prev, __next)); \
} while (0)
diff --git a/arch/riscv/include/asm/patch.h b/arch/riscv/include/asm/text-patching.h
index 7228e266b9a1..7228e266b9a1 100644
--- a/arch/riscv/include/asm/patch.h
+++ b/arch/riscv/include/asm/text-patching.h
diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h
index 9c10fb180f43..f5916a70879a 100644
--- a/arch/riscv/include/asm/thread_info.h
+++ b/arch/riscv/include/asm/thread_info.h
@@ -107,9 +107,10 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
* - pending work-to-be-done flags are in lowest half-word
* - other flags in upper half-word(s)
*/
-#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
-#define TIF_SIGPENDING 2 /* signal pending */
-#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_NEED_RESCHED 0 /* rescheduling necessary */
+#define TIF_NEED_RESCHED_LAZY 1 /* Lazy rescheduling needed */
+#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
+#define TIF_SIGPENDING 3 /* signal pending */
#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
#define TIF_NOTIFY_SIGNAL 9 /* signal notifications exist */
@@ -117,9 +118,10 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
#define TIF_32BIT 11 /* compat-mode 32bit process */
#define TIF_RISCV_V_DEFER_RESTORE 12 /* restore Vector before returing to user */
+#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
#define _TIF_UPROBE (1 << TIF_UPROBE)
#define _TIF_RISCV_V_DEFER_RESTORE (1 << TIF_RISCV_V_DEFER_RESTORE)
diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h
index 72ec1d9bd3f3..fee56b0c8058 100644
--- a/arch/riscv/include/asm/uaccess.h
+++ b/arch/riscv/include/asm/uaccess.h
@@ -9,8 +9,41 @@
#define _ASM_RISCV_UACCESS_H
#include <asm/asm-extable.h>
+#include <asm/cpufeature.h>
#include <asm/pgtable.h> /* for TASK_SIZE */
+#ifdef CONFIG_RISCV_ISA_SUPM
+static inline unsigned long __untagged_addr_remote(struct mm_struct *mm, unsigned long addr)
+{
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) {
+ u8 pmlen = mm->context.pmlen;
+
+ /* Virtual addresses are sign-extended; physical addresses are zero-extended. */
+ if (IS_ENABLED(CONFIG_MMU))
+ return (long)(addr << pmlen) >> pmlen;
+ else
+ return (addr << pmlen) >> pmlen;
+ }
+
+ return addr;
+}
+
+#define untagged_addr(addr) ({ \
+ unsigned long __addr = (__force unsigned long)(addr); \
+ (__force __typeof__(addr))__untagged_addr_remote(current->mm, __addr); \
+})
+
+#define untagged_addr_remote(mm, addr) ({ \
+ unsigned long __addr = (__force unsigned long)(addr); \
+ mmap_assert_locked(mm); \
+ (__force __typeof__(addr))__untagged_addr_remote(mm, __addr); \
+})
+
+#define access_ok(addr, size) likely(__access_ok(untagged_addr(addr), size))
+#else
+#define untagged_addr(addr) (addr)
+#endif
+
/*
* User space memory access functions
*/
@@ -130,7 +163,7 @@ do { \
*/
#define __get_user(x, ptr) \
({ \
- const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
+ const __typeof__(*(ptr)) __user *__gu_ptr = untagged_addr(ptr); \
long __gu_err = 0; \
\
__chk_user_ptr(__gu_ptr); \
@@ -246,7 +279,7 @@ do { \
*/
#define __put_user(x, ptr) \
({ \
- __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
+ __typeof__(*(ptr)) __user *__gu_ptr = untagged_addr(ptr); \
__typeof__(*__gu_ptr) __val = (x); \
long __pu_err = 0; \
\
@@ -293,13 +326,13 @@ unsigned long __must_check __asm_copy_from_user(void *to,
static inline unsigned long
raw_copy_from_user(void *to, const void __user *from, unsigned long n)
{
- return __asm_copy_from_user(to, from, n);
+ return __asm_copy_from_user(to, untagged_addr(from), n);
}
static inline unsigned long
raw_copy_to_user(void __user *to, const void *from, unsigned long n)
{
- return __asm_copy_to_user(to, from, n);
+ return __asm_copy_to_user(untagged_addr(to), from, n);
}
extern long strncpy_from_user(char *dest, const char __user *src, long count);
@@ -314,7 +347,7 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
{
might_fault();
return access_ok(to, n) ?
- __clear_user(to, n) : n;
+ __clear_user(untagged_addr(to), n) : n;
}
#define __get_kernel_nofault(dst, src, type, err_label) \
diff --git a/arch/riscv/include/asm/uprobes.h b/arch/riscv/include/asm/uprobes.h
index 3fc7deda9190..5008f76cdc27 100644
--- a/arch/riscv/include/asm/uprobes.h
+++ b/arch/riscv/include/asm/uprobes.h
@@ -4,7 +4,7 @@
#define _ASM_RISCV_UPROBES_H
#include <asm/probes.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/bug.h>
#define MAX_UINSN_BYTES 8
diff --git a/arch/riscv/include/asm/vdso/data.h b/arch/riscv/include/asm/vdso/time_data.h
index dc2f76f58b76..dfa65228999b 100644
--- a/arch/riscv/include/asm/vdso/data.h
+++ b/arch/riscv/include/asm/vdso/time_data.h
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __RISCV_ASM_VDSO_DATA_H
-#define __RISCV_ASM_VDSO_DATA_H
+#ifndef __RISCV_ASM_VDSO_TIME_DATA_H
+#define __RISCV_ASM_VDSO_TIME_DATA_H
#include <linux/types.h>
#include <vdso/datapage.h>
#include <asm/hwprobe.h>
-struct arch_vdso_data {
+struct arch_vdso_time_data {
/* Stash static answers to the hwprobe queries when all CPUs are selected. */
__u64 all_cpu_hwprobe_values[RISCV_HWPROBE_MAX_KEY + 1];
@@ -14,4 +14,4 @@ struct arch_vdso_data {
__u8 homogeneous_cpus;
};
-#endif /* __RISCV_ASM_VDSO_DATA_H */
+#endif /* __RISCV_ASM_VDSO_TIME_DATA_H */
diff --git a/arch/riscv/include/asm/vdso/vsyscall.h b/arch/riscv/include/asm/vdso/vsyscall.h
index 82fd5d83bd60..e8a9c4b53c0c 100644
--- a/arch/riscv/include/asm/vdso/vsyscall.h
+++ b/arch/riscv/include/asm/vdso/vsyscall.h
@@ -4,14 +4,10 @@
#ifndef __ASSEMBLY__
-#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
extern struct vdso_data *vdso_data;
-/*
- * Update the vDSO data page to keep in sync with kernel timekeeping.
- */
static __always_inline struct vdso_data *__riscv_get_k_vdso_data(void)
{
return vdso_data;
diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h
index be7d309cca8a..c7c023afbacd 100644
--- a/arch/riscv/include/asm/vector.h
+++ b/arch/riscv/include/asm/vector.h
@@ -21,6 +21,7 @@
extern unsigned long riscv_v_vsize;
int riscv_v_setup_vsize(void);
+bool insn_is_vector(u32 insn_buf);
bool riscv_v_first_use_handler(struct pt_regs *regs);
void kernel_vector_begin(void);
void kernel_vector_end(void);
@@ -268,6 +269,7 @@ struct pt_regs;
static inline int riscv_v_setup_vsize(void) { return -EOPNOTSUPP; }
static __always_inline bool has_vector(void) { return false; }
+static __always_inline bool insn_is_vector(u32 insn_buf) { return false; }
static inline bool riscv_v_first_use_handler(struct pt_regs *regs) { return false; }
static inline bool riscv_v_vstate_query(struct pt_regs *regs) { return false; }
static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; }
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
index 1e153cda57db..3af142b99f77 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -72,6 +72,7 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46)
#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47)
#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48)
+#define RISCV_HWPROBE_EXT_SUPM (1ULL << 49)
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
@@ -88,6 +89,11 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW 2
#define RISCV_HWPROBE_MISALIGNED_SCALAR_FAST 3
#define RISCV_HWPROBE_MISALIGNED_SCALAR_UNSUPPORTED 4
+#define RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF 10
+#define RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN 0
+#define RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW 2
+#define RISCV_HWPROBE_MISALIGNED_VECTOR_FAST 3
+#define RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED 4
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
/* Flags */
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index e97db3296456..3482c9a73d1b 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -175,6 +175,10 @@ enum KVM_RISCV_ISA_EXT_ID {
KVM_RISCV_ISA_EXT_ZCF,
KVM_RISCV_ISA_EXT_ZCMOP,
KVM_RISCV_ISA_EXT_ZAWRS,
+ KVM_RISCV_ISA_EXT_SMNPM,
+ KVM_RISCV_ISA_EXT_SSNPM,
+ KVM_RISCV_ISA_EXT_SVADE,
+ KVM_RISCV_ISA_EXT_SVADU,
KVM_RISCV_ISA_EXT_MAX,
};
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 69dc8aaab3fb..063d1faf5a53 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -75,7 +75,8 @@ obj-$(CONFIG_MMU) += vdso.o vdso/
obj-$(CONFIG_RISCV_MISALIGNED) += traps_misaligned.o
obj-$(CONFIG_RISCV_MISALIGNED) += unaligned_access_speed.o
-obj-$(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS) += copy-unaligned.o
+obj-$(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS) += copy-unaligned.o
+obj-$(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS) += vec-copy-unaligned.o
obj-$(CONFIG_FPU) += fpu.o
obj-$(CONFIG_FPU) += kernel_mode_fpu.o
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index 0128b161bfda..7eb3cb1215c6 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -18,7 +18,7 @@
#include <asm/sbi.h>
#include <asm/csr.h>
#include <asm/insn.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
struct cpu_manufacturer_info_t {
unsigned long vendor_id;
diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c
index c2f3129a8e5c..e89455a6a0e5 100644
--- a/arch/riscv/kernel/asm-offsets.c
+++ b/arch/riscv/kernel/asm-offsets.c
@@ -496,19 +496,19 @@ void asm_offsets(void)
OFFSET(STACKFRAME_RA, stackframe, ra);
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
- DEFINE(FREGS_SIZE_ON_STACK, ALIGN(sizeof(struct ftrace_regs), STACK_ALIGN));
- DEFINE(FREGS_EPC, offsetof(struct ftrace_regs, epc));
- DEFINE(FREGS_RA, offsetof(struct ftrace_regs, ra));
- DEFINE(FREGS_SP, offsetof(struct ftrace_regs, sp));
- DEFINE(FREGS_S0, offsetof(struct ftrace_regs, s0));
- DEFINE(FREGS_T1, offsetof(struct ftrace_regs, t1));
- DEFINE(FREGS_A0, offsetof(struct ftrace_regs, a0));
- DEFINE(FREGS_A1, offsetof(struct ftrace_regs, a1));
- DEFINE(FREGS_A2, offsetof(struct ftrace_regs, a2));
- DEFINE(FREGS_A3, offsetof(struct ftrace_regs, a3));
- DEFINE(FREGS_A4, offsetof(struct ftrace_regs, a4));
- DEFINE(FREGS_A5, offsetof(struct ftrace_regs, a5));
- DEFINE(FREGS_A6, offsetof(struct ftrace_regs, a6));
- DEFINE(FREGS_A7, offsetof(struct ftrace_regs, a7));
+ DEFINE(FREGS_SIZE_ON_STACK, ALIGN(sizeof(struct __arch_ftrace_regs), STACK_ALIGN));
+ DEFINE(FREGS_EPC, offsetof(struct __arch_ftrace_regs, epc));
+ DEFINE(FREGS_RA, offsetof(struct __arch_ftrace_regs, ra));
+ DEFINE(FREGS_SP, offsetof(struct __arch_ftrace_regs, sp));
+ DEFINE(FREGS_S0, offsetof(struct __arch_ftrace_regs, s0));
+ DEFINE(FREGS_T1, offsetof(struct __arch_ftrace_regs, t1));
+ DEFINE(FREGS_A0, offsetof(struct __arch_ftrace_regs, a0));
+ DEFINE(FREGS_A1, offsetof(struct __arch_ftrace_regs, a1));
+ DEFINE(FREGS_A2, offsetof(struct __arch_ftrace_regs, a2));
+ DEFINE(FREGS_A3, offsetof(struct __arch_ftrace_regs, a3));
+ DEFINE(FREGS_A4, offsetof(struct __arch_ftrace_regs, a4));
+ DEFINE(FREGS_A5, offsetof(struct __arch_ftrace_regs, a5));
+ DEFINE(FREGS_A6, offsetof(struct __arch_ftrace_regs, a6));
+ DEFINE(FREGS_A7, offsetof(struct __arch_ftrace_regs, a7));
#endif
}
diff --git a/arch/riscv/kernel/copy-unaligned.h b/arch/riscv/kernel/copy-unaligned.h
index e3d70d35b708..85d4d11450cb 100644
--- a/arch/riscv/kernel/copy-unaligned.h
+++ b/arch/riscv/kernel/copy-unaligned.h
@@ -10,4 +10,9 @@
void __riscv_copy_words_unaligned(void *dst, const void *src, size_t size);
void __riscv_copy_bytes_unaligned(void *dst, const void *src, size_t size);
+#ifdef CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS
+void __riscv_copy_vec_words_unaligned(void *dst, const void *src, size_t size);
+void __riscv_copy_vec_bytes_unaligned(void *dst, const void *src, size_t size);
+#endif
+
#endif /* __RISCV_KERNEL_COPY_UNALIGNED_H */
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 3a8eeaa9310c..c0916ed318c2 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -20,7 +20,8 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
#include <asm/hwcap.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
+#include <asm/hwprobe.h>
#include <asm/processor.h>
#include <asm/sbi.h>
#include <asm/vector.h>
@@ -28,6 +29,8 @@
#define NUM_ALPHA_EXTS ('z' - 'a' + 1)
+static bool any_cpu_has_zicboz;
+
unsigned long elf_hwcap __read_mostly;
/* Host ISA bitmap */
@@ -98,6 +101,7 @@ static int riscv_ext_zicboz_validate(const struct riscv_isa_ext_data *data,
pr_err("Zicboz disabled as cboz-block-size present, but is not a power-of-2\n");
return -EINVAL;
}
+ any_cpu_has_zicboz = true;
return 0;
}
@@ -132,6 +136,16 @@ static int riscv_ext_zcf_validate(const struct riscv_isa_ext_data *data,
return -EPROBE_DEFER;
}
+static int riscv_ext_svadu_validate(const struct riscv_isa_ext_data *data,
+ const unsigned long *isa_bitmap)
+{
+ /* SVADE has already been detected, use SVADE only */
+ if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_SVADE))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
static const unsigned int riscv_zk_bundled_exts[] = {
RISCV_ISA_EXT_ZBKB,
RISCV_ISA_EXT_ZBKC,
@@ -314,6 +328,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
riscv_ext_zicbom_validate),
__RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts,
riscv_ext_zicboz_validate),
+ __RISCV_ISA_EXT_DATA(ziccrse, RISCV_ISA_EXT_ZICCRSE),
__RISCV_ISA_EXT_DATA(zicntr, RISCV_ISA_EXT_ZICNTR),
__RISCV_ISA_EXT_DATA(zicond, RISCV_ISA_EXT_ZICOND),
__RISCV_ISA_EXT_DATA(zicsr, RISCV_ISA_EXT_ZICSR),
@@ -322,6 +337,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
__RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM),
__RISCV_ISA_EXT_DATA(zimop, RISCV_ISA_EXT_ZIMOP),
+ __RISCV_ISA_EXT_DATA(zabha, RISCV_ISA_EXT_ZABHA),
__RISCV_ISA_EXT_DATA(zacas, RISCV_ISA_EXT_ZACAS),
__RISCV_ISA_EXT_DATA(zawrs, RISCV_ISA_EXT_ZAWRS),
__RISCV_ISA_EXT_DATA(zfa, RISCV_ISA_EXT_ZFA),
@@ -374,10 +390,15 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_BUNDLE(zvksg, riscv_zvksg_bundled_exts),
__RISCV_ISA_EXT_DATA(zvkt, RISCV_ISA_EXT_ZVKT),
__RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA),
+ __RISCV_ISA_EXT_DATA(smmpm, RISCV_ISA_EXT_SMMPM),
+ __RISCV_ISA_EXT_SUPERSET(smnpm, RISCV_ISA_EXT_SMNPM, riscv_xlinuxenvcfg_exts),
__RISCV_ISA_EXT_DATA(smstateen, RISCV_ISA_EXT_SMSTATEEN),
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
+ __RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
+ __RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE),
+ __RISCV_ISA_EXT_DATA_VALIDATE(svadu, RISCV_ISA_EXT_SVADU, riscv_ext_svadu_validate),
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
__RISCV_ISA_EXT_DATA(svnapot, RISCV_ISA_EXT_SVNAPOT),
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
@@ -917,10 +938,12 @@ unsigned long riscv_get_elf_hwcap(void)
return hwcap;
}
-void riscv_user_isa_enable(void)
+void __init riscv_user_isa_enable(void)
{
- if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_ZICBOZ))
- csr_set(CSR_ENVCFG, ENVCFG_CBZE);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICBOZ))
+ current->thread.envcfg |= ENVCFG_CBZE;
+ else if (any_cpu_has_zicboz)
+ pr_warn("Zicboz disabled as it is unavailable on some harts\n");
}
#ifdef CONFIG_RISCV_ALTERNATIVE
diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S
index 327cf527dd7e..f74f6b60e347 100644
--- a/arch/riscv/kernel/fpu.S
+++ b/arch/riscv/kernel/fpu.S
@@ -170,7 +170,7 @@ SYM_FUNC_END(__fstate_restore)
__access_func(f31)
-#ifdef CONFIG_RISCV_MISALIGNED
+#ifdef CONFIG_RISCV_SCALAR_MISALIGNED
/*
* Disable compressed instructions set to keep a constant offset between FP
@@ -224,4 +224,4 @@ SYM_FUNC_START(get_f64_reg)
fp_access_epilogue
SYM_FUNC_END(get_f64_reg)
-#endif /* CONFIG_RISCV_MISALIGNED */
+#endif /* CONFIG_RISCV_SCALAR_MISALIGNED */
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index 4b95c574fd04..8cb9b211611d 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -10,7 +10,7 @@
#include <linux/memory.h>
#include <linux/stop_machine.h>
#include <asm/cacheflush.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#ifdef CONFIG_DYNAMIC_FTRACE
void ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex)
@@ -214,7 +214,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- prepare_ftrace_return(&fregs->ra, ip, fregs->s0);
+ prepare_ftrace_return(&arch_ftrace_regs(fregs)->ra, ip, arch_ftrace_regs(fregs)->s0);
}
#else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
extern void ftrace_graph_call(void);
diff --git a/arch/riscv/kernel/jump_label.c b/arch/riscv/kernel/jump_label.c
index 11ad789c60c6..6eee6f736f68 100644
--- a/arch/riscv/kernel/jump_label.c
+++ b/arch/riscv/kernel/jump_label.c
@@ -10,7 +10,7 @@
#include <linux/mutex.h>
#include <asm/bug.h>
#include <asm/cacheflush.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#define RISCV_INSN_NOP 0x00000013U
#define RISCV_INSN_JAL 0x0000006fU
diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
index 34ef522f07a8..db13c9ddf9e3 100644
--- a/arch/riscv/kernel/patch.c
+++ b/arch/riscv/kernel/patch.c
@@ -13,7 +13,7 @@
#include <asm/cacheflush.h>
#include <asm/fixmap.h>
#include <asm/ftrace.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/sections.h>
struct patch_insn {
diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
index c7468af77c66..b465bc9eb870 100644
--- a/arch/riscv/kernel/perf_callchain.c
+++ b/arch/riscv/kernel/perf_callchain.c
@@ -28,11 +28,21 @@ static bool fill_callchain(void *entry, unsigned long pc)
void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
{
+ if (perf_guest_state()) {
+ /* TODO: We don't support guest os callchain now */
+ return;
+ }
+
arch_stack_walk_user(fill_callchain, entry, regs);
}
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
{
+ if (perf_guest_state()) {
+ /* TODO: We don't support guest os callchain now */
+ return;
+ }
+
walk_stackframe(NULL, regs, fill_callchain, entry);
}
diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
index 474a65213657..380a0e8cecc0 100644
--- a/arch/riscv/kernel/probes/kprobes.c
+++ b/arch/riscv/kernel/probes/kprobes.c
@@ -12,7 +12,7 @@
#include <asm/sections.h>
#include <asm/cacheflush.h>
#include <asm/bug.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include "decode-insn.h"
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index e3142d8a6e28..58b6482c2bf6 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -7,6 +7,7 @@
* Copyright (C) 2017 SiFive
*/
+#include <linux/bitfield.h>
#include <linux/cpu.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -180,6 +181,10 @@ void flush_thread(void)
memset(&current->thread.vstate, 0, sizeof(struct __riscv_v_ext_state));
clear_tsk_thread_flag(current, TIF_RISCV_V_DEFER_RESTORE);
#endif
+#ifdef CONFIG_RISCV_ISA_SUPM
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM))
+ envcfg_update_bits(current, ENVCFG_PMM, ENVCFG_PMM_PMLEN_0);
+#endif
}
void arch_release_task_struct(struct task_struct *tsk)
@@ -208,6 +213,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
unsigned long tls = args->tls;
struct pt_regs *childregs = task_pt_regs(p);
+ /* Ensure all threads in this mm have the same pointer masking mode. */
+ if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM) && p->mm && (clone_flags & CLONE_VM))
+ set_bit(MM_CONTEXT_LOCK_PMLEN, &p->mm->context.flags);
+
memset(&p->thread.s, 0, sizeof(p->thread.s));
/* p->thread holds context to be restored by __switch_to() */
@@ -242,3 +251,148 @@ void __init arch_task_cache_init(void)
{
riscv_v_setup_ctx_cache();
}
+
+#ifdef CONFIG_RISCV_ISA_SUPM
+enum {
+ PMLEN_0 = 0,
+ PMLEN_7 = 7,
+ PMLEN_16 = 16,
+};
+
+static bool have_user_pmlen_7;
+static bool have_user_pmlen_16;
+
+/*
+ * Control the relaxed ABI allowing tagged user addresses into the kernel.
+ */
+static unsigned int tagged_addr_disabled;
+
+long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
+{
+ unsigned long valid_mask = PR_PMLEN_MASK | PR_TAGGED_ADDR_ENABLE;
+ struct thread_info *ti = task_thread_info(task);
+ struct mm_struct *mm = task->mm;
+ unsigned long pmm;
+ u8 pmlen;
+
+ if (is_compat_thread(ti))
+ return -EINVAL;
+
+ if (arg & ~valid_mask)
+ return -EINVAL;
+
+ /*
+ * Prefer the smallest PMLEN that satisfies the user's request,
+ * in case choosing a larger PMLEN has a performance impact.
+ */
+ pmlen = FIELD_GET(PR_PMLEN_MASK, arg);
+ if (pmlen == PMLEN_0) {
+ pmm = ENVCFG_PMM_PMLEN_0;
+ } else if (pmlen <= PMLEN_7 && have_user_pmlen_7) {
+ pmlen = PMLEN_7;
+ pmm = ENVCFG_PMM_PMLEN_7;
+ } else if (pmlen <= PMLEN_16 && have_user_pmlen_16) {
+ pmlen = PMLEN_16;
+ pmm = ENVCFG_PMM_PMLEN_16;
+ } else {
+ return -EINVAL;
+ }
+
+ /*
+ * Do not allow the enabling of the tagged address ABI if globally
+ * disabled via sysctl abi.tagged_addr_disabled, if pointer masking
+ * is disabled for userspace.
+ */
+ if (arg & PR_TAGGED_ADDR_ENABLE && (tagged_addr_disabled || !pmlen))
+ return -EINVAL;
+
+ if (!(arg & PR_TAGGED_ADDR_ENABLE))
+ pmlen = PMLEN_0;
+
+ if (mmap_write_lock_killable(mm))
+ return -EINTR;
+
+ if (test_bit(MM_CONTEXT_LOCK_PMLEN, &mm->context.flags) && mm->context.pmlen != pmlen) {
+ mmap_write_unlock(mm);
+ return -EBUSY;
+ }
+
+ envcfg_update_bits(task, ENVCFG_PMM, pmm);
+ mm->context.pmlen = pmlen;
+
+ mmap_write_unlock(mm);
+
+ return 0;
+}
+
+long get_tagged_addr_ctrl(struct task_struct *task)
+{
+ struct thread_info *ti = task_thread_info(task);
+ long ret = 0;
+
+ if (is_compat_thread(ti))
+ return -EINVAL;
+
+ /*
+ * The mm context's pmlen is set only when the tagged address ABI is
+ * enabled, so the effective PMLEN must be extracted from envcfg.PMM.
+ */
+ switch (task->thread.envcfg & ENVCFG_PMM) {
+ case ENVCFG_PMM_PMLEN_7:
+ ret = FIELD_PREP(PR_PMLEN_MASK, PMLEN_7);
+ break;
+ case ENVCFG_PMM_PMLEN_16:
+ ret = FIELD_PREP(PR_PMLEN_MASK, PMLEN_16);
+ break;
+ }
+
+ if (task->mm->context.pmlen)
+ ret |= PR_TAGGED_ADDR_ENABLE;
+
+ return ret;
+}
+
+static bool try_to_set_pmm(unsigned long value)
+{
+ csr_set(CSR_ENVCFG, value);
+ return (csr_read_clear(CSR_ENVCFG, ENVCFG_PMM) & ENVCFG_PMM) == value;
+}
+
+/*
+ * Global sysctl to disable the tagged user addresses support. This control
+ * only prevents the tagged address ABI enabling via prctl() and does not
+ * disable it for tasks that already opted in to the relaxed ABI.
+ */
+
+static struct ctl_table tagged_addr_sysctl_table[] = {
+ {
+ .procname = "tagged_addr_disabled",
+ .mode = 0644,
+ .data = &tagged_addr_disabled,
+ .maxlen = sizeof(int),
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
+};
+
+static int __init tagged_addr_init(void)
+{
+ if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM))
+ return 0;
+
+ /*
+ * envcfg.PMM is a WARL field. Detect which values are supported.
+ * Assume the supported PMLEN values are the same on all harts.
+ */
+ csr_clear(CSR_ENVCFG, ENVCFG_PMM);
+ have_user_pmlen_7 = try_to_set_pmm(ENVCFG_PMM_PMLEN_7);
+ have_user_pmlen_16 = try_to_set_pmm(ENVCFG_PMM_PMLEN_16);
+
+ if (!register_sysctl("abi", tagged_addr_sysctl_table))
+ return -EINVAL;
+
+ return 0;
+}
+core_initcall(tagged_addr_init);
+#endif /* CONFIG_RISCV_ISA_SUPM */
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index 92731ff8c79a..ea67e9fb7a58 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -28,6 +28,9 @@ enum riscv_regset {
#ifdef CONFIG_RISCV_ISA_V
REGSET_V,
#endif
+#ifdef CONFIG_RISCV_ISA_SUPM
+ REGSET_TAGGED_ADDR_CTRL,
+#endif
};
static int riscv_gpr_get(struct task_struct *target,
@@ -152,6 +155,35 @@ static int riscv_vr_set(struct task_struct *target,
}
#endif
+#ifdef CONFIG_RISCV_ISA_SUPM
+static int tagged_addr_ctrl_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ long ctrl = get_tagged_addr_ctrl(target);
+
+ if (IS_ERR_VALUE(ctrl))
+ return ctrl;
+
+ return membuf_write(&to, &ctrl, sizeof(ctrl));
+}
+
+static int tagged_addr_ctrl_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+ long ctrl;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 0, -1);
+ if (ret)
+ return ret;
+
+ return set_tagged_addr_ctrl(target, ctrl);
+}
+#endif
+
static const struct user_regset riscv_user_regset[] = {
[REGSET_X] = {
.core_note_type = NT_PRSTATUS,
@@ -182,6 +214,16 @@ static const struct user_regset riscv_user_regset[] = {
.set = riscv_vr_set,
},
#endif
+#ifdef CONFIG_RISCV_ISA_SUPM
+ [REGSET_TAGGED_ADDR_CTRL] = {
+ .core_note_type = NT_RISCV_TAGGED_ADDR_CTRL,
+ .n = 1,
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .regset_get = tagged_addr_ctrl_get,
+ .set = tagged_addr_ctrl_set,
+ },
+#endif
};
static const struct user_regset_view riscv_user_native_view = {
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index a2cde65b69e9..016b48fcd6f2 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -227,7 +227,7 @@ static void __init init_resources(void)
static void __init parse_dtb(void)
{
/* Early scan of device tree from init memory */
- if (early_init_dt_scan(dtb_early_va)) {
+ if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) {
const char *name = of_flat_dt_get_machine_name();
if (name) {
@@ -244,6 +244,42 @@ static void __init parse_dtb(void)
#endif
}
+#if defined(CONFIG_RISCV_COMBO_SPINLOCKS)
+DEFINE_STATIC_KEY_TRUE(qspinlock_key);
+EXPORT_SYMBOL(qspinlock_key);
+#endif
+
+static void __init riscv_spinlock_init(void)
+{
+ char *using_ext = NULL;
+
+ if (IS_ENABLED(CONFIG_RISCV_TICKET_SPINLOCKS)) {
+ pr_info("Ticket spinlock: enabled\n");
+ return;
+ }
+
+ if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) &&
+ IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) &&
+ riscv_isa_extension_available(NULL, ZABHA) &&
+ riscv_isa_extension_available(NULL, ZACAS)) {
+ using_ext = "using Zabha";
+ } else if (riscv_isa_extension_available(NULL, ZICCRSE)) {
+ using_ext = "using Ziccrse";
+ }
+#if defined(CONFIG_RISCV_COMBO_SPINLOCKS)
+ else {
+ static_branch_disable(&qspinlock_key);
+ pr_info("Ticket spinlock: enabled\n");
+ return;
+ }
+#endif
+
+ if (!using_ext)
+ pr_err("Queued spinlock without Zabha or Ziccrse");
+ else
+ pr_info("Queued spinlock %s: enabled\n", using_ext);
+}
+
extern void __init init_rt_signal_env(void);
void __init setup_arch(char **cmdline_p)
@@ -297,6 +333,7 @@ void __init setup_arch(char **cmdline_p)
riscv_set_dma_cache_alignment();
riscv_user_isa_enable();
+ riscv_spinlock_init();
}
bool arch_cpu_is_hotpluggable(int cpu)
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
index 0f8f1c95ac38..e36d20205bd7 100644
--- a/arch/riscv/kernel/smpboot.c
+++ b/arch/riscv/kernel/smpboot.c
@@ -233,8 +233,6 @@ asmlinkage __visible void smp_callin(void)
numa_add_cpu(curr_cpuid);
set_cpu_online(curr_cpuid, true);
- riscv_user_isa_enable();
-
/*
* Remote cache and TLB flushes are ignored while the CPU is offline,
* so flush them both right now just in case.
diff --git a/arch/riscv/kernel/suspend.c b/arch/riscv/kernel/suspend.c
index c8cec0cc5833..9a8a0dc035b2 100644
--- a/arch/riscv/kernel/suspend.c
+++ b/arch/riscv/kernel/suspend.c
@@ -14,7 +14,7 @@
void suspend_save_csrs(struct suspend_context *context)
{
- if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_XLINUXENVCFG))
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_XLINUXENVCFG))
context->envcfg = csr_read(CSR_ENVCFG);
context->tvec = csr_read(CSR_TVEC);
context->ie = csr_read(CSR_IE);
@@ -37,7 +37,7 @@ void suspend_save_csrs(struct suspend_context *context)
void suspend_restore_csrs(struct suspend_context *context)
{
csr_write(CSR_SCRATCH, 0);
- if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_XLINUXENVCFG))
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_XLINUXENVCFG))
csr_write(CSR_ENVCFG, context->envcfg);
csr_write(CSR_TVEC, context->tvec);
csr_write(CSR_IE, context->ie);
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index cea0ca2bf2a2..cb93adfffc48 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -150,6 +150,9 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(ZFH);
EXT_KEY(ZFHMIN);
}
+
+ if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM))
+ EXT_KEY(SUPM);
#undef EXT_KEY
}
@@ -201,6 +204,43 @@ static u64 hwprobe_misaligned(const struct cpumask *cpus)
}
#endif
+#ifdef CONFIG_RISCV_VECTOR_MISALIGNED
+static u64 hwprobe_vec_misaligned(const struct cpumask *cpus)
+{
+ int cpu;
+ u64 perf = -1ULL;
+
+ /* Return if supported or not even if speed wasn't probed */
+ for_each_cpu(cpu, cpus) {
+ int this_perf = per_cpu(vector_misaligned_access, cpu);
+
+ if (perf == -1ULL)
+ perf = this_perf;
+
+ if (perf != this_perf) {
+ perf = RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN;
+ break;
+ }
+ }
+
+ if (perf == -1ULL)
+ return RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN;
+
+ return perf;
+}
+#else
+static u64 hwprobe_vec_misaligned(const struct cpumask *cpus)
+{
+ if (IS_ENABLED(CONFIG_RISCV_EFFICIENT_VECTOR_UNALIGNED_ACCESS))
+ return RISCV_HWPROBE_MISALIGNED_VECTOR_FAST;
+
+ if (IS_ENABLED(CONFIG_RISCV_SLOW_VECTOR_UNALIGNED_ACCESS))
+ return RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW;
+
+ return RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN;
+}
+#endif
+
static void hwprobe_one_pair(struct riscv_hwprobe *pair,
const struct cpumask *cpus)
{
@@ -229,6 +269,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
pair->value = hwprobe_misaligned(cpus);
break;
+ case RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF:
+ pair->value = hwprobe_vec_misaligned(cpus);
+ break;
+
case RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE:
pair->value = 0;
if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOZ))
@@ -402,7 +446,7 @@ static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs,
static int __init init_hwprobe_vdso_data(void)
{
struct vdso_data *vd = __arch_get_k_vdso_data();
- struct arch_vdso_data *avd = &vd->arch_data;
+ struct arch_vdso_time_data *avd = &vd->arch_data;
u64 id_bitsmash = 0;
struct riscv_hwprobe pair;
int key;
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 1b9867136b61..7cc108aed74e 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -16,6 +16,7 @@
#include <asm/entry-common.h>
#include <asm/hwprobe.h>
#include <asm/cpufeature.h>
+#include <asm/vector.h>
#define INSN_MATCH_LB 0x3
#define INSN_MASK_LB 0x707f
@@ -320,12 +321,37 @@ union reg_data {
u64 data_u64;
};
-static bool unaligned_ctl __read_mostly;
-
/* sysctl hooks */
int unaligned_enabled __read_mostly = 1; /* Enabled by default */
-int handle_misaligned_load(struct pt_regs *regs)
+#ifdef CONFIG_RISCV_VECTOR_MISALIGNED
+static int handle_vector_misaligned_load(struct pt_regs *regs)
+{
+ unsigned long epc = regs->epc;
+ unsigned long insn;
+
+ if (get_insn(regs, epc, &insn))
+ return -1;
+
+ /* Only return 0 when in check_vector_unaligned_access_emulated */
+ if (*this_cpu_ptr(&vector_misaligned_access) == RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN) {
+ *this_cpu_ptr(&vector_misaligned_access) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED;
+ regs->epc = epc + INSN_LEN(insn);
+ return 0;
+ }
+
+ /* If vector instruction we don't emulate it yet */
+ regs->epc = epc;
+ return -1;
+}
+#else
+static int handle_vector_misaligned_load(struct pt_regs *regs)
+{
+ return -1;
+}
+#endif
+
+static int handle_scalar_misaligned_load(struct pt_regs *regs)
{
union reg_data val;
unsigned long epc = regs->epc;
@@ -433,7 +459,7 @@ int handle_misaligned_load(struct pt_regs *regs)
return 0;
}
-int handle_misaligned_store(struct pt_regs *regs)
+static int handle_scalar_misaligned_store(struct pt_regs *regs)
{
union reg_data val;
unsigned long epc = regs->epc;
@@ -524,11 +550,96 @@ int handle_misaligned_store(struct pt_regs *regs)
return 0;
}
-static bool check_unaligned_access_emulated(int cpu)
+int handle_misaligned_load(struct pt_regs *regs)
+{
+ unsigned long epc = regs->epc;
+ unsigned long insn;
+
+ if (IS_ENABLED(CONFIG_RISCV_VECTOR_MISALIGNED)) {
+ if (get_insn(regs, epc, &insn))
+ return -1;
+
+ if (insn_is_vector(insn))
+ return handle_vector_misaligned_load(regs);
+ }
+
+ if (IS_ENABLED(CONFIG_RISCV_SCALAR_MISALIGNED))
+ return handle_scalar_misaligned_load(regs);
+
+ return -1;
+}
+
+int handle_misaligned_store(struct pt_regs *regs)
{
+ if (IS_ENABLED(CONFIG_RISCV_SCALAR_MISALIGNED))
+ return handle_scalar_misaligned_store(regs);
+
+ return -1;
+}
+
+#ifdef CONFIG_RISCV_VECTOR_MISALIGNED
+void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused)
+{
+ long *mas_ptr = this_cpu_ptr(&vector_misaligned_access);
+ unsigned long tmp_var;
+
+ *mas_ptr = RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN;
+
+ kernel_vector_begin();
+ /*
+ * In pre-13.0.0 versions of GCC, vector registers cannot appear in
+ * the clobber list. This inline asm clobbers v0, but since we do not
+ * currently build the kernel with V enabled, the v0 clobber arg is not
+ * needed (as the compiler will not emit vector code itself). If the kernel
+ * is changed to build with V enabled, the clobber arg will need to be
+ * added here.
+ */
+ __asm__ __volatile__ (
+ ".balign 4\n\t"
+ ".option push\n\t"
+ ".option arch, +zve32x\n\t"
+ " vsetivli zero, 1, e16, m1, ta, ma\n\t" // Vectors of 16b
+ " vle16.v v0, (%[ptr])\n\t" // Load bytes
+ ".option pop\n\t"
+ : : [ptr] "r" ((u8 *)&tmp_var + 1));
+ kernel_vector_end();
+}
+
+bool check_vector_unaligned_access_emulated_all_cpus(void)
+{
+ int cpu;
+
+ if (!has_vector()) {
+ for_each_online_cpu(cpu)
+ per_cpu(vector_misaligned_access, cpu) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED;
+ return false;
+ }
+
+ schedule_on_each_cpu(check_vector_unaligned_access_emulated);
+
+ for_each_online_cpu(cpu)
+ if (per_cpu(vector_misaligned_access, cpu)
+ == RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN)
+ return false;
+
+ return true;
+}
+#else
+bool check_vector_unaligned_access_emulated_all_cpus(void)
+{
+ return false;
+}
+#endif
+
+#ifdef CONFIG_RISCV_SCALAR_MISALIGNED
+
+static bool unaligned_ctl __read_mostly;
+
+void check_unaligned_access_emulated(struct work_struct *work __always_unused)
+{
+ int cpu = smp_processor_id();
long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
unsigned long tmp_var, tmp_val;
- bool misaligned_emu_detected;
*mas_ptr = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN;
@@ -536,19 +647,16 @@ static bool check_unaligned_access_emulated(int cpu)
" "REG_L" %[tmp], 1(%[ptr])\n"
: [tmp] "=r" (tmp_val) : [ptr] "r" (&tmp_var) : "memory");
- misaligned_emu_detected = (*mas_ptr == RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED);
/*
* If unaligned_ctl is already set, this means that we detected that all
* CPUS uses emulated misaligned access at boot time. If that changed
* when hotplugging the new cpu, this is something we don't handle.
*/
- if (unlikely(unaligned_ctl && !misaligned_emu_detected)) {
+ if (unlikely(unaligned_ctl && (*mas_ptr != RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED))) {
pr_crit("CPU misaligned accesses non homogeneous (expected all emulated)\n");
while (true)
cpu_relax();
}
-
- return misaligned_emu_detected;
}
bool check_unaligned_access_emulated_all_cpus(void)
@@ -560,8 +668,11 @@ bool check_unaligned_access_emulated_all_cpus(void)
* accesses emulated since tasks requesting such control can run on any
* CPU.
*/
+ schedule_on_each_cpu(check_unaligned_access_emulated);
+
for_each_online_cpu(cpu)
- if (!check_unaligned_access_emulated(cpu))
+ if (per_cpu(misaligned_access_speed, cpu)
+ != RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED)
return false;
unaligned_ctl = true;
@@ -572,3 +683,9 @@ bool unaligned_ctl_available(void)
{
return unaligned_ctl;
}
+#else
+bool check_unaligned_access_emulated_all_cpus(void)
+{
+ return false;
+}
+#endif
diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c
index 160628a2116d..91f189cf1611 100644
--- a/arch/riscv/kernel/unaligned_access_speed.c
+++ b/arch/riscv/kernel/unaligned_access_speed.c
@@ -6,11 +6,13 @@
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/jump_label.h>
+#include <linux/kthread.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/types.h>
#include <asm/cpufeature.h>
#include <asm/hwprobe.h>
+#include <asm/vector.h>
#include "copy-unaligned.h"
@@ -19,7 +21,8 @@
#define MISALIGNED_BUFFER_ORDER get_order(MISALIGNED_BUFFER_SIZE)
#define MISALIGNED_COPY_SIZE ((MISALIGNED_BUFFER_SIZE / 2) - 0x80)
-DEFINE_PER_CPU(long, misaligned_access_speed);
+DEFINE_PER_CPU(long, misaligned_access_speed) = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN;
+DEFINE_PER_CPU(long, vector_misaligned_access) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED;
#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS
static cpumask_t fast_misaligned_access;
@@ -191,6 +194,7 @@ static int riscv_online_cpu(unsigned int cpu)
if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN)
goto exit;
+ check_unaligned_access_emulated(NULL);
buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
if (!buf) {
pr_warn("Allocation failure, not measuring misaligned performance\n");
@@ -259,23 +263,159 @@ out:
kfree(bufs);
return 0;
}
+#else /* CONFIG_RISCV_PROBE_UNALIGNED_ACCESS */
+static int check_unaligned_access_speed_all_cpus(void)
+{
+ return 0;
+}
+#endif
-static int check_unaligned_access_all_cpus(void)
+#ifdef CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS
+static void check_vector_unaligned_access(struct work_struct *work __always_unused)
{
- bool all_cpus_emulated = check_unaligned_access_emulated_all_cpus();
+ int cpu = smp_processor_id();
+ u64 start_cycles, end_cycles;
+ u64 word_cycles;
+ u64 byte_cycles;
+ int ratio;
+ unsigned long start_jiffies, now;
+ struct page *page;
+ void *dst;
+ void *src;
+ long speed = RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW;
- if (!all_cpus_emulated)
- return check_unaligned_access_speed_all_cpus();
+ if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN)
+ return;
+
+ page = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
+ if (!page) {
+ pr_warn("Allocation failure, not measuring vector misaligned performance\n");
+ return;
+ }
+
+ /* Make an unaligned destination buffer. */
+ dst = (void *)((unsigned long)page_address(page) | 0x1);
+ /* Unalign src as well, but differently (off by 1 + 2 = 3). */
+ src = dst + (MISALIGNED_BUFFER_SIZE / 2);
+ src += 2;
+ word_cycles = -1ULL;
+
+ /* Do a warmup. */
+ kernel_vector_begin();
+ __riscv_copy_vec_words_unaligned(dst, src, MISALIGNED_COPY_SIZE);
+ start_jiffies = jiffies;
+ while ((now = jiffies) == start_jiffies)
+ cpu_relax();
+
+ /*
+ * For a fixed amount of time, repeatedly try the function, and take
+ * the best time in cycles as the measurement.
+ */
+ while (time_before(jiffies, now + (1 << MISALIGNED_ACCESS_JIFFIES_LG2))) {
+ start_cycles = get_cycles64();
+ /* Ensure the CSR read can't reorder WRT to the copy. */
+ mb();
+ __riscv_copy_vec_words_unaligned(dst, src, MISALIGNED_COPY_SIZE);
+ /* Ensure the copy ends before the end time is snapped. */
+ mb();
+ end_cycles = get_cycles64();
+ if ((end_cycles - start_cycles) < word_cycles)
+ word_cycles = end_cycles - start_cycles;
+ }
+
+ byte_cycles = -1ULL;
+ __riscv_copy_vec_bytes_unaligned(dst, src, MISALIGNED_COPY_SIZE);
+ start_jiffies = jiffies;
+ while ((now = jiffies) == start_jiffies)
+ cpu_relax();
+
+ while (time_before(jiffies, now + (1 << MISALIGNED_ACCESS_JIFFIES_LG2))) {
+ start_cycles = get_cycles64();
+ /* Ensure the CSR read can't reorder WRT to the copy. */
+ mb();
+ __riscv_copy_vec_bytes_unaligned(dst, src, MISALIGNED_COPY_SIZE);
+ /* Ensure the copy ends before the end time is snapped. */
+ mb();
+ end_cycles = get_cycles64();
+ if ((end_cycles - start_cycles) < byte_cycles)
+ byte_cycles = end_cycles - start_cycles;
+ }
+
+ kernel_vector_end();
+
+ /* Don't divide by zero. */
+ if (!word_cycles || !byte_cycles) {
+ pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned vector access speed\n",
+ cpu);
+
+ return;
+ }
+
+ if (word_cycles < byte_cycles)
+ speed = RISCV_HWPROBE_MISALIGNED_VECTOR_FAST;
+
+ ratio = div_u64((byte_cycles * 100), word_cycles);
+ pr_info("cpu%d: Ratio of vector byte access time to vector unaligned word access is %d.%02d, unaligned accesses are %s\n",
+ cpu,
+ ratio / 100,
+ ratio % 100,
+ (speed == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST) ? "fast" : "slow");
+
+ per_cpu(vector_misaligned_access, cpu) = speed;
+}
+
+static int riscv_online_cpu_vec(unsigned int cpu)
+{
+ if (!has_vector())
+ return 0;
+
+ if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED)
+ return 0;
+
+ check_vector_unaligned_access_emulated(NULL);
+ check_vector_unaligned_access(NULL);
return 0;
}
-#else /* CONFIG_RISCV_PROBE_UNALIGNED_ACCESS */
-static int check_unaligned_access_all_cpus(void)
+
+/* Measure unaligned access speed on all CPUs present at boot in parallel. */
+static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused)
{
- check_unaligned_access_emulated_all_cpus();
+ schedule_on_each_cpu(check_vector_unaligned_access);
+
+ /*
+ * Setup hotplug callbacks for any new CPUs that come online or go
+ * offline.
+ */
+ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online",
+ riscv_online_cpu_vec, NULL);
return 0;
}
+#else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */
+static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused)
+{
+ return 0;
+}
#endif
+static int check_unaligned_access_all_cpus(void)
+{
+ bool all_cpus_emulated, all_cpus_vec_unsupported;
+
+ all_cpus_emulated = check_unaligned_access_emulated_all_cpus();
+ all_cpus_vec_unsupported = check_vector_unaligned_access_emulated_all_cpus();
+
+ if (!all_cpus_vec_unsupported &&
+ IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) {
+ kthread_run(vec_check_unaligned_access_speed_all_cpus,
+ NULL, "vec_check_unaligned_access_speed_all_cpus");
+ }
+
+ if (!all_cpus_emulated)
+ return check_unaligned_access_speed_all_cpus();
+
+ return 0;
+}
+
arch_initcall(check_unaligned_access_all_cpus);
diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
index 98315b98256d..3ca3ae4277e1 100644
--- a/arch/riscv/kernel/vdso.c
+++ b/arch/riscv/kernel/vdso.c
@@ -23,11 +23,6 @@ enum vvar_pages {
VVAR_NR_PAGES,
};
-enum rv_vdso_map {
- RV_VDSO_MAP_VVAR,
- RV_VDSO_MAP_VDSO,
-};
-
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
static union vdso_data_store vdso_data_store __page_aligned_data;
@@ -38,8 +33,6 @@ struct __vdso_info {
const char *vdso_code_start;
const char *vdso_code_end;
unsigned long vdso_pages;
- /* Data Mapping */
- struct vm_special_mapping *dm;
/* Code Mapping */
struct vm_special_mapping *cm;
};
@@ -92,6 +85,8 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page)
return (struct vdso_data *)(vvar_page);
}
+static const struct vm_special_mapping rv_vvar_map;
+
/*
* The vvar mapping contains data for a specific time namespace, so when a task
* changes namespace we must unmap its vvar data for the old namespace.
@@ -108,12 +103,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_lock(mm);
for_each_vma(vmi, vma) {
- if (vma_is_special_mapping(vma, vdso_info.dm))
- zap_vma_pages(vma);
-#ifdef CONFIG_COMPAT
- if (vma_is_special_mapping(vma, compat_vdso_info.dm))
+ if (vma_is_special_mapping(vma, &rv_vvar_map))
zap_vma_pages(vma);
-#endif
}
mmap_read_unlock(mm);
@@ -155,43 +146,34 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
return vmf_insert_pfn(vma, vmf->address, pfn);
}
-static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = {
- [RV_VDSO_MAP_VVAR] = {
- .name = "[vvar]",
- .fault = vvar_fault,
- },
- [RV_VDSO_MAP_VDSO] = {
- .name = "[vdso]",
- .mremap = vdso_mremap,
- },
+static const struct vm_special_mapping rv_vvar_map = {
+ .name = "[vvar]",
+ .fault = vvar_fault,
+};
+
+static struct vm_special_mapping rv_vdso_map __ro_after_init = {
+ .name = "[vdso]",
+ .mremap = vdso_mremap,
};
static struct __vdso_info vdso_info __ro_after_init = {
.name = "vdso",
.vdso_code_start = vdso_start,
.vdso_code_end = vdso_end,
- .dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR],
- .cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO],
+ .cm = &rv_vdso_map,
};
#ifdef CONFIG_COMPAT
-static struct vm_special_mapping rv_compat_vdso_maps[] __ro_after_init = {
- [RV_VDSO_MAP_VVAR] = {
- .name = "[vvar]",
- .fault = vvar_fault,
- },
- [RV_VDSO_MAP_VDSO] = {
- .name = "[vdso]",
- .mremap = vdso_mremap,
- },
+static struct vm_special_mapping rv_compat_vdso_map __ro_after_init = {
+ .name = "[vdso]",
+ .mremap = vdso_mremap,
};
static struct __vdso_info compat_vdso_info __ro_after_init = {
.name = "compat_vdso",
.vdso_code_start = compat_vdso_start,
.vdso_code_end = compat_vdso_end,
- .dm = &rv_compat_vdso_maps[RV_VDSO_MAP_VVAR],
- .cm = &rv_compat_vdso_maps[RV_VDSO_MAP_VDSO],
+ .cm = &rv_compat_vdso_map,
};
#endif
@@ -227,7 +209,7 @@ static int __setup_additional_pages(struct mm_struct *mm,
}
ret = _install_special_mapping(mm, vdso_base, VVAR_SIZE,
- (VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info->dm);
+ (VM_READ | VM_MAYREAD | VM_PFNMAP), &rv_vvar_map);
if (IS_ERR(ret))
goto up_fail;
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
index 3f1c4b2d0b06..9a1b555e8733 100644
--- a/arch/riscv/kernel/vdso/Makefile
+++ b/arch/riscv/kernel/vdso/Makefile
@@ -45,7 +45,7 @@ $(obj)/vdso.o: $(obj)/vdso.so
# link rule for the .so file, .lds has to be first
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
- $(call if_changed,vdsold)
+ $(call if_changed,vdsold_and_check)
LDFLAGS_vdso.so.dbg = -shared -soname=linux-vdso.so.1 \
--build-id=sha1 --hash-style=both --eh-frame-hdr
@@ -65,7 +65,8 @@ include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
# actual build commands
# The DSO images are built using a special linker script
# Make sure only to export the intended __vdso_xxx symbol offsets.
-quiet_cmd_vdsold = VDSOLD $@
- cmd_vdsold = $(LD) $(ld_flags) -T $(filter-out FORCE,$^) -o $@.tmp && \
+quiet_cmd_vdsold_and_check = VDSOLD $@
+ cmd_vdsold_and_check = $(LD) $(ld_flags) -T $(filter-out FORCE,$^) -o $@.tmp && \
$(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
- rm $@.tmp
+ rm $@.tmp && \
+ $(cmd_vdso_check)
diff --git a/arch/riscv/kernel/vdso/hwprobe.c b/arch/riscv/kernel/vdso/hwprobe.c
index 1e926e4b5881..a158c029344f 100644
--- a/arch/riscv/kernel/vdso/hwprobe.c
+++ b/arch/riscv/kernel/vdso/hwprobe.c
@@ -17,7 +17,7 @@ static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count,
unsigned int flags)
{
const struct vdso_data *vd = __arch_get_vdso_data();
- const struct arch_vdso_data *avd = &vd->arch_data;
+ const struct arch_vdso_time_data *avd = &vd->arch_data;
bool all_cpus = !cpusetsize && !cpus;
struct riscv_hwprobe *p = pairs;
struct riscv_hwprobe *end = pairs + pair_count;
@@ -52,7 +52,7 @@ static int riscv_vdso_get_cpus(struct riscv_hwprobe *pairs, size_t pair_count,
unsigned int flags)
{
const struct vdso_data *vd = __arch_get_vdso_data();
- const struct arch_vdso_data *avd = &vd->arch_data;
+ const struct arch_vdso_time_data *avd = &vd->arch_data;
struct riscv_hwprobe *p = pairs;
struct riscv_hwprobe *end = pairs + pair_count;
unsigned char *c = (unsigned char *)cpus;
diff --git a/arch/riscv/kernel/vec-copy-unaligned.S b/arch/riscv/kernel/vec-copy-unaligned.S
new file mode 100644
index 000000000000..d16f19f1b3b6
--- /dev/null
+++ b/arch/riscv/kernel/vec-copy-unaligned.S
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2024 Rivos Inc. */
+
+#include <linux/args.h>
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+ .text
+
+#define WORD_EEW 32
+
+#define WORD_SEW CONCATENATE(e, WORD_EEW)
+#define VEC_L CONCATENATE(vle, WORD_EEW).v
+#define VEC_S CONCATENATE(vle, WORD_EEW).v
+
+/* void __riscv_copy_vec_words_unaligned(void *, const void *, size_t) */
+/* Performs a memcpy without aligning buffers, using word loads and stores. */
+/* Note: The size is truncated to a multiple of WORD_EEW */
+SYM_FUNC_START(__riscv_copy_vec_words_unaligned)
+ andi a4, a2, ~(WORD_EEW-1)
+ beqz a4, 2f
+ add a3, a1, a4
+ .option push
+ .option arch, +zve32x
+1:
+ vsetivli t0, 8, WORD_SEW, m8, ta, ma
+ VEC_L v0, (a1)
+ VEC_S v0, (a0)
+ addi a0, a0, WORD_EEW
+ addi a1, a1, WORD_EEW
+ bltu a1, a3, 1b
+
+2:
+ .option pop
+ ret
+SYM_FUNC_END(__riscv_copy_vec_words_unaligned)
+
+/* void __riscv_copy_vec_bytes_unaligned(void *, const void *, size_t) */
+/* Performs a memcpy without aligning buffers, using only byte accesses. */
+/* Note: The size is truncated to a multiple of 8 */
+SYM_FUNC_START(__riscv_copy_vec_bytes_unaligned)
+ andi a4, a2, ~(8-1)
+ beqz a4, 2f
+ add a3, a1, a4
+ .option push
+ .option arch, +zve32x
+1:
+ vsetivli t0, 8, e8, m8, ta, ma
+ vle8.v v0, (a1)
+ vse8.v v0, (a0)
+ addi a0, a0, 8
+ addi a1, a1, 8
+ bltu a1, a3, 1b
+
+2:
+ .option pop
+ ret
+SYM_FUNC_END(__riscv_copy_vec_bytes_unaligned)
diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c
index 682b3feee451..821818886fab 100644
--- a/arch/riscv/kernel/vector.c
+++ b/arch/riscv/kernel/vector.c
@@ -66,7 +66,7 @@ void __init riscv_v_setup_ctx_cache(void)
#endif
}
-static bool insn_is_vector(u32 insn_buf)
+bool insn_is_vector(u32 insn_buf)
{
u32 opcode = insn_buf & __INSN_OPCODE_MASK;
u32 width, csr;
diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig
index 26d1727f0550..0c3cbb0915ff 100644
--- a/arch/riscv/kvm/Kconfig
+++ b/arch/riscv/kvm/Kconfig
@@ -32,6 +32,7 @@ config KVM
select KVM_XFER_TO_GUEST_WORK
select KVM_GENERIC_MMU_NOTIFIER
select SCHED_INFO
+ select GUEST_PERF_EVENTS if PERF_EVENTS
help
Support hosting virtualized guest machines.
diff --git a/arch/riscv/kvm/Makefile b/arch/riscv/kvm/Makefile
index c2cacfbc06a0..0fb1840c3e0a 100644
--- a/arch/riscv/kvm/Makefile
+++ b/arch/riscv/kvm/Makefile
@@ -9,27 +9,30 @@ include $(srctree)/virt/kvm/Makefile.kvm
obj-$(CONFIG_KVM) += kvm.o
+# Ordered alphabetically
+kvm-y += aia.o
+kvm-y += aia_aplic.o
+kvm-y += aia_device.o
+kvm-y += aia_imsic.o
kvm-y += main.o
-kvm-y += vm.o
-kvm-y += vmid.o
-kvm-y += tlb.o
kvm-y += mmu.o
+kvm-y += nacl.o
+kvm-y += tlb.o
kvm-y += vcpu.o
kvm-y += vcpu_exit.o
kvm-y += vcpu_fp.o
-kvm-y += vcpu_vector.o
kvm-y += vcpu_insn.o
kvm-y += vcpu_onereg.o
-kvm-y += vcpu_switch.o
+kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o
kvm-y += vcpu_sbi.o
-kvm-$(CONFIG_RISCV_SBI_V01) += vcpu_sbi_v01.o
kvm-y += vcpu_sbi_base.o
-kvm-y += vcpu_sbi_replace.o
kvm-y += vcpu_sbi_hsm.o
+kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_sbi_pmu.o
+kvm-y += vcpu_sbi_replace.o
kvm-y += vcpu_sbi_sta.o
+kvm-$(CONFIG_RISCV_SBI_V01) += vcpu_sbi_v01.o
+kvm-y += vcpu_switch.o
kvm-y += vcpu_timer.o
-kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o vcpu_sbi_pmu.o
-kvm-y += aia.o
-kvm-y += aia_device.o
-kvm-y += aia_aplic.o
-kvm-y += aia_imsic.o
+kvm-y += vcpu_vector.o
+kvm-y += vm.o
+kvm-y += vmid.o
diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
index 2967d305c442..dcced4db7fe8 100644
--- a/arch/riscv/kvm/aia.c
+++ b/arch/riscv/kvm/aia.c
@@ -16,6 +16,7 @@
#include <linux/percpu.h>
#include <linux/spinlock.h>
#include <asm/cpufeature.h>
+#include <asm/kvm_nacl.h>
struct aia_hgei_control {
raw_spinlock_t lock;
@@ -51,7 +52,7 @@ static int aia_find_hgei(struct kvm_vcpu *owner)
return hgei;
}
-static void aia_set_hvictl(bool ext_irq_pending)
+static inline unsigned long aia_hvictl_value(bool ext_irq_pending)
{
unsigned long hvictl;
@@ -62,7 +63,7 @@ static void aia_set_hvictl(bool ext_irq_pending)
hvictl = (IRQ_S_EXT << HVICTL_IID_SHIFT) & HVICTL_IID;
hvictl |= ext_irq_pending;
- csr_write(CSR_HVICTL, hvictl);
+ return hvictl;
}
#ifdef CONFIG_32BIT
@@ -88,7 +89,7 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
if (kvm_riscv_aia_available())
- csr->vsieh = csr_read(CSR_VSIEH);
+ csr->vsieh = ncsr_read(CSR_VSIEH);
}
#endif
@@ -115,7 +116,7 @@ bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
hgei = aia_find_hgei(vcpu);
if (hgei > 0)
- return !!(csr_read(CSR_HGEIP) & BIT(hgei));
+ return !!(ncsr_read(CSR_HGEIP) & BIT(hgei));
return false;
}
@@ -128,45 +129,73 @@ void kvm_riscv_vcpu_aia_update_hvip(struct kvm_vcpu *vcpu)
return;
#ifdef CONFIG_32BIT
- csr_write(CSR_HVIPH, vcpu->arch.aia_context.guest_csr.hviph);
+ ncsr_write(CSR_HVIPH, vcpu->arch.aia_context.guest_csr.hviph);
#endif
- aia_set_hvictl(!!(csr->hvip & BIT(IRQ_VS_EXT)));
+ ncsr_write(CSR_HVICTL, aia_hvictl_value(!!(csr->hvip & BIT(IRQ_VS_EXT))));
}
void kvm_riscv_vcpu_aia_load(struct kvm_vcpu *vcpu, int cpu)
{
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
+ void *nsh;
if (!kvm_riscv_aia_available())
return;
- csr_write(CSR_VSISELECT, csr->vsiselect);
- csr_write(CSR_HVIPRIO1, csr->hviprio1);
- csr_write(CSR_HVIPRIO2, csr->hviprio2);
+ if (kvm_riscv_nacl_sync_csr_available()) {
+ nsh = nacl_shmem();
+ nacl_csr_write(nsh, CSR_VSISELECT, csr->vsiselect);
+ nacl_csr_write(nsh, CSR_HVIPRIO1, csr->hviprio1);
+ nacl_csr_write(nsh, CSR_HVIPRIO2, csr->hviprio2);
+#ifdef CONFIG_32BIT
+ nacl_csr_write(nsh, CSR_VSIEH, csr->vsieh);
+ nacl_csr_write(nsh, CSR_HVIPH, csr->hviph);
+ nacl_csr_write(nsh, CSR_HVIPRIO1H, csr->hviprio1h);
+ nacl_csr_write(nsh, CSR_HVIPRIO2H, csr->hviprio2h);
+#endif
+ } else {
+ csr_write(CSR_VSISELECT, csr->vsiselect);
+ csr_write(CSR_HVIPRIO1, csr->hviprio1);
+ csr_write(CSR_HVIPRIO2, csr->hviprio2);
#ifdef CONFIG_32BIT
- csr_write(CSR_VSIEH, csr->vsieh);
- csr_write(CSR_HVIPH, csr->hviph);
- csr_write(CSR_HVIPRIO1H, csr->hviprio1h);
- csr_write(CSR_HVIPRIO2H, csr->hviprio2h);
+ csr_write(CSR_VSIEH, csr->vsieh);
+ csr_write(CSR_HVIPH, csr->hviph);
+ csr_write(CSR_HVIPRIO1H, csr->hviprio1h);
+ csr_write(CSR_HVIPRIO2H, csr->hviprio2h);
#endif
+ }
}
void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu)
{
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
+ void *nsh;
if (!kvm_riscv_aia_available())
return;
- csr->vsiselect = csr_read(CSR_VSISELECT);
- csr->hviprio1 = csr_read(CSR_HVIPRIO1);
- csr->hviprio2 = csr_read(CSR_HVIPRIO2);
+ if (kvm_riscv_nacl_available()) {
+ nsh = nacl_shmem();
+ csr->vsiselect = nacl_csr_read(nsh, CSR_VSISELECT);
+ csr->hviprio1 = nacl_csr_read(nsh, CSR_HVIPRIO1);
+ csr->hviprio2 = nacl_csr_read(nsh, CSR_HVIPRIO2);
#ifdef CONFIG_32BIT
- csr->vsieh = csr_read(CSR_VSIEH);
- csr->hviph = csr_read(CSR_HVIPH);
- csr->hviprio1h = csr_read(CSR_HVIPRIO1H);
- csr->hviprio2h = csr_read(CSR_HVIPRIO2H);
+ csr->vsieh = nacl_csr_read(nsh, CSR_VSIEH);
+ csr->hviph = nacl_csr_read(nsh, CSR_HVIPH);
+ csr->hviprio1h = nacl_csr_read(nsh, CSR_HVIPRIO1H);
+ csr->hviprio2h = nacl_csr_read(nsh, CSR_HVIPRIO2H);
#endif
+ } else {
+ csr->vsiselect = csr_read(CSR_VSISELECT);
+ csr->hviprio1 = csr_read(CSR_HVIPRIO1);
+ csr->hviprio2 = csr_read(CSR_HVIPRIO2);
+#ifdef CONFIG_32BIT
+ csr->vsieh = csr_read(CSR_VSIEH);
+ csr->hviph = csr_read(CSR_HVIPH);
+ csr->hviprio1h = csr_read(CSR_HVIPRIO1H);
+ csr->hviprio2h = csr_read(CSR_HVIPRIO2H);
+#endif
+ }
}
int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
@@ -250,20 +279,20 @@ static u8 aia_get_iprio8(struct kvm_vcpu *vcpu, unsigned int irq)
switch (bitpos / BITS_PER_LONG) {
case 0:
- hviprio = csr_read(CSR_HVIPRIO1);
+ hviprio = ncsr_read(CSR_HVIPRIO1);
break;
case 1:
#ifndef CONFIG_32BIT
- hviprio = csr_read(CSR_HVIPRIO2);
+ hviprio = ncsr_read(CSR_HVIPRIO2);
break;
#else
- hviprio = csr_read(CSR_HVIPRIO1H);
+ hviprio = ncsr_read(CSR_HVIPRIO1H);
break;
case 2:
- hviprio = csr_read(CSR_HVIPRIO2);
+ hviprio = ncsr_read(CSR_HVIPRIO2);
break;
case 3:
- hviprio = csr_read(CSR_HVIPRIO2H);
+ hviprio = ncsr_read(CSR_HVIPRIO2H);
break;
#endif
default:
@@ -283,20 +312,20 @@ static void aia_set_iprio8(struct kvm_vcpu *vcpu, unsigned int irq, u8 prio)
switch (bitpos / BITS_PER_LONG) {
case 0:
- hviprio = csr_read(CSR_HVIPRIO1);
+ hviprio = ncsr_read(CSR_HVIPRIO1);
break;
case 1:
#ifndef CONFIG_32BIT
- hviprio = csr_read(CSR_HVIPRIO2);
+ hviprio = ncsr_read(CSR_HVIPRIO2);
break;
#else
- hviprio = csr_read(CSR_HVIPRIO1H);
+ hviprio = ncsr_read(CSR_HVIPRIO1H);
break;
case 2:
- hviprio = csr_read(CSR_HVIPRIO2);
+ hviprio = ncsr_read(CSR_HVIPRIO2);
break;
case 3:
- hviprio = csr_read(CSR_HVIPRIO2H);
+ hviprio = ncsr_read(CSR_HVIPRIO2H);
break;
#endif
default:
@@ -308,20 +337,20 @@ static void aia_set_iprio8(struct kvm_vcpu *vcpu, unsigned int irq, u8 prio)
switch (bitpos / BITS_PER_LONG) {
case 0:
- csr_write(CSR_HVIPRIO1, hviprio);
+ ncsr_write(CSR_HVIPRIO1, hviprio);
break;
case 1:
#ifndef CONFIG_32BIT
- csr_write(CSR_HVIPRIO2, hviprio);
+ ncsr_write(CSR_HVIPRIO2, hviprio);
break;
#else
- csr_write(CSR_HVIPRIO1H, hviprio);
+ ncsr_write(CSR_HVIPRIO1H, hviprio);
break;
case 2:
- csr_write(CSR_HVIPRIO2, hviprio);
+ ncsr_write(CSR_HVIPRIO2, hviprio);
break;
case 3:
- csr_write(CSR_HVIPRIO2H, hviprio);
+ ncsr_write(CSR_HVIPRIO2H, hviprio);
break;
#endif
default:
@@ -377,7 +406,7 @@ int kvm_riscv_vcpu_aia_rmw_ireg(struct kvm_vcpu *vcpu, unsigned int csr_num,
return KVM_INSN_ILLEGAL_TRAP;
/* First try to emulate in kernel space */
- isel = csr_read(CSR_VSISELECT) & ISELECT_MASK;
+ isel = ncsr_read(CSR_VSISELECT) & ISELECT_MASK;
if (isel >= ISELECT_IPRIO0 && isel <= ISELECT_IPRIO15)
return aia_rmw_iprio(vcpu, isel, val, new_val, wr_mask);
else if (isel >= IMSIC_FIRST && isel <= IMSIC_LAST &&
@@ -499,6 +528,10 @@ static int aia_hgei_init(void)
hgctrl->free_bitmap = 0;
}
+ /* Skip SGEI interrupt setup for zero guest external interrupts */
+ if (!kvm_riscv_aia_nr_hgei)
+ goto skip_sgei_interrupt;
+
/* Find INTC irq domain */
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(),
DOMAIN_BUS_ANY);
@@ -522,11 +555,16 @@ static int aia_hgei_init(void)
return rc;
}
+skip_sgei_interrupt:
return 0;
}
static void aia_hgei_exit(void)
{
+ /* Do nothing for zero guest external interrupts */
+ if (!kvm_riscv_aia_nr_hgei)
+ return;
+
/* Free per-CPU SGEI interrupt */
free_percpu_irq(hgei_parent_irq, &aia_hgei);
}
@@ -536,7 +574,7 @@ void kvm_riscv_aia_enable(void)
if (!kvm_riscv_aia_available())
return;
- aia_set_hvictl(false);
+ csr_write(CSR_HVICTL, aia_hvictl_value(false));
csr_write(CSR_HVIPRIO1, 0x0);
csr_write(CSR_HVIPRIO2, 0x0);
#ifdef CONFIG_32BIT
@@ -572,7 +610,7 @@ void kvm_riscv_aia_disable(void)
csr_clear(CSR_HIE, BIT(IRQ_S_GEXT));
disable_percpu_irq(hgei_parent_irq);
- aia_set_hvictl(false);
+ csr_write(CSR_HVICTL, aia_hvictl_value(false));
raw_spin_lock_irqsave(&hgctrl->lock, flags);
diff --git a/arch/riscv/kvm/aia_aplic.c b/arch/riscv/kvm/aia_aplic.c
index da6ff1bade0d..f59d1c0c8c43 100644
--- a/arch/riscv/kvm/aia_aplic.c
+++ b/arch/riscv/kvm/aia_aplic.c
@@ -143,7 +143,7 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending)
if (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH ||
sm == APLIC_SOURCECFG_SM_LEVEL_LOW) {
if (!pending)
- goto skip_write_pending;
+ goto noskip_write_pending;
if ((irqd->state & APLIC_IRQ_STATE_INPUT) &&
sm == APLIC_SOURCECFG_SM_LEVEL_LOW)
goto skip_write_pending;
@@ -152,6 +152,7 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending)
goto skip_write_pending;
}
+noskip_write_pending:
if (pending)
irqd->state |= APLIC_IRQ_STATE_PENDING;
else
diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c
index f3427f6de608..1fa8be5ee509 100644
--- a/arch/riscv/kvm/main.c
+++ b/arch/riscv/kvm/main.c
@@ -10,8 +10,8 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/kvm_host.h>
-#include <asm/csr.h>
#include <asm/cpufeature.h>
+#include <asm/kvm_nacl.h>
#include <asm/sbi.h>
long kvm_arch_dev_ioctl(struct file *filp,
@@ -22,6 +22,12 @@ long kvm_arch_dev_ioctl(struct file *filp,
int kvm_arch_enable_virtualization_cpu(void)
{
+ int rc;
+
+ rc = kvm_riscv_nacl_enable();
+ if (rc)
+ return rc;
+
csr_write(CSR_HEDELEG, KVM_HEDELEG_DEFAULT);
csr_write(CSR_HIDELEG, KVM_HIDELEG_DEFAULT);
@@ -49,11 +55,21 @@ void kvm_arch_disable_virtualization_cpu(void)
csr_write(CSR_HVIP, 0);
csr_write(CSR_HEDELEG, 0);
csr_write(CSR_HIDELEG, 0);
+
+ kvm_riscv_nacl_disable();
+}
+
+static void kvm_riscv_teardown(void)
+{
+ kvm_riscv_aia_exit();
+ kvm_riscv_nacl_exit();
+ kvm_unregister_perf_callbacks();
}
static int __init riscv_kvm_init(void)
{
int rc;
+ char slist[64];
const char *str;
if (!riscv_isa_extension_available(NULL, h)) {
@@ -71,16 +87,53 @@ static int __init riscv_kvm_init(void)
return -ENODEV;
}
+ rc = kvm_riscv_nacl_init();
+ if (rc && rc != -ENODEV)
+ return rc;
+
kvm_riscv_gstage_mode_detect();
kvm_riscv_gstage_vmid_detect();
rc = kvm_riscv_aia_init();
- if (rc && rc != -ENODEV)
+ if (rc && rc != -ENODEV) {
+ kvm_riscv_nacl_exit();
return rc;
+ }
kvm_info("hypervisor extension available\n");
+ if (kvm_riscv_nacl_available()) {
+ rc = 0;
+ slist[0] = '\0';
+ if (kvm_riscv_nacl_sync_csr_available()) {
+ if (rc)
+ strcat(slist, ", ");
+ strcat(slist, "sync_csr");
+ rc++;
+ }
+ if (kvm_riscv_nacl_sync_hfence_available()) {
+ if (rc)
+ strcat(slist, ", ");
+ strcat(slist, "sync_hfence");
+ rc++;
+ }
+ if (kvm_riscv_nacl_sync_sret_available()) {
+ if (rc)
+ strcat(slist, ", ");
+ strcat(slist, "sync_sret");
+ rc++;
+ }
+ if (kvm_riscv_nacl_autoswap_csr_available()) {
+ if (rc)
+ strcat(slist, ", ");
+ strcat(slist, "autoswap_csr");
+ rc++;
+ }
+ kvm_info("using SBI nested acceleration with %s\n",
+ (rc) ? slist : "no features");
+ }
+
switch (kvm_riscv_gstage_mode()) {
case HGATP_MODE_SV32X4:
str = "Sv32x4";
@@ -105,9 +158,11 @@ static int __init riscv_kvm_init(void)
kvm_info("AIA available with %d guest external interrupts\n",
kvm_riscv_aia_nr_hgei);
+ kvm_register_perf_callbacks(NULL);
+
rc = kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
if (rc) {
- kvm_riscv_aia_exit();
+ kvm_riscv_teardown();
return rc;
}
@@ -117,7 +172,7 @@ module_init(riscv_kvm_init);
static void __exit riscv_kvm_exit(void)
{
- kvm_riscv_aia_exit();
+ kvm_riscv_teardown();
kvm_exit();
}
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index b63650f9b966..1087ea74567b 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -15,7 +15,7 @@
#include <linux/vmalloc.h>
#include <linux/kvm_host.h>
#include <linux/sched/signal.h>
-#include <asm/csr.h>
+#include <asm/kvm_nacl.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -601,6 +601,7 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
bool logging = (memslot->dirty_bitmap &&
!(memslot->flags & KVM_MEM_READONLY)) ? true : false;
unsigned long vma_pagesize, mmu_seq;
+ struct page *page;
/* We need minimum second+third level pages */
ret = kvm_mmu_topup_memory_cache(pcache, gstage_pgd_levels);
@@ -631,7 +632,7 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
/*
* Read mmu_invalidate_seq so that KVM can detect if the results of
- * vma_lookup() or gfn_to_pfn_prot() become stale priort to acquiring
+ * vma_lookup() or __kvm_faultin_pfn() become stale prior to acquiring
* kvm->mmu_lock.
*
* Rely on mmap_read_unlock() for an implicit smp_rmb(), which pairs
@@ -647,7 +648,7 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
return -EFAULT;
}
- hfn = gfn_to_pfn_prot(kvm, gfn, is_write, &writable);
+ hfn = kvm_faultin_pfn(vcpu, gfn, is_write, &writable, &page);
if (hfn == KVM_PFN_ERR_HWPOISON) {
send_sig_mceerr(BUS_MCEERR_AR, (void __user *)hva,
vma_pageshift, current);
@@ -669,7 +670,6 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
goto out_unlock;
if (writable) {
- kvm_set_pfn_dirty(hfn);
mark_page_dirty(kvm, gfn);
ret = gstage_map_page(kvm, pcache, gpa, hfn << PAGE_SHIFT,
vma_pagesize, false, true);
@@ -682,9 +682,8 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,
kvm_err("Failed to map in G-stage\n");
out_unlock:
+ kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
spin_unlock(&kvm->mmu_lock);
- kvm_set_pfn_accessed(hfn);
- kvm_release_pfn_clean(hfn);
return ret;
}
@@ -732,7 +731,7 @@ void kvm_riscv_gstage_update_hgatp(struct kvm_vcpu *vcpu)
hgatp |= (READ_ONCE(k->vmid.vmid) << HGATP_VMID_SHIFT) & HGATP_VMID;
hgatp |= (k->pgd_phys >> PAGE_SHIFT) & HGATP_PPN;
- csr_write(CSR_HGATP, hgatp);
+ ncsr_write(CSR_HGATP, hgatp);
if (!kvm_riscv_gstage_vmid_bits())
kvm_riscv_local_hfence_gvma_all();
diff --git a/arch/riscv/kvm/nacl.c b/arch/riscv/kvm/nacl.c
new file mode 100644
index 000000000000..08a95ad9ada2
--- /dev/null
+++ b/arch/riscv/kvm/nacl.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/vmalloc.h>
+#include <asm/kvm_nacl.h>
+
+DEFINE_STATIC_KEY_FALSE(kvm_riscv_nacl_available);
+DEFINE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_csr_available);
+DEFINE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_hfence_available);
+DEFINE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_sret_available);
+DEFINE_STATIC_KEY_FALSE(kvm_riscv_nacl_autoswap_csr_available);
+DEFINE_PER_CPU(struct kvm_riscv_nacl, kvm_riscv_nacl);
+
+void __kvm_riscv_nacl_hfence(void *shmem,
+ unsigned long control,
+ unsigned long page_num,
+ unsigned long page_count)
+{
+ int i, ent = -1, try_count = 5;
+ unsigned long *entp;
+
+again:
+ for (i = 0; i < SBI_NACL_SHMEM_HFENCE_ENTRY_MAX; i++) {
+ entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_CONFIG(i);
+ if (lelong_to_cpu(*entp) & SBI_NACL_SHMEM_HFENCE_CONFIG_PEND)
+ continue;
+
+ ent = i;
+ break;
+ }
+
+ if (ent < 0) {
+ if (try_count) {
+ nacl_sync_hfence(-1UL);
+ goto again;
+ } else {
+ pr_warn("KVM: No free entry in NACL shared memory\n");
+ return;
+ }
+ }
+
+ entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_CONFIG(i);
+ *entp = cpu_to_lelong(control);
+ entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_PNUM(i);
+ *entp = cpu_to_lelong(page_num);
+ entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_PCOUNT(i);
+ *entp = cpu_to_lelong(page_count);
+}
+
+int kvm_riscv_nacl_enable(void)
+{
+ int rc;
+ struct sbiret ret;
+ struct kvm_riscv_nacl *nacl;
+
+ if (!kvm_riscv_nacl_available())
+ return 0;
+ nacl = this_cpu_ptr(&kvm_riscv_nacl);
+
+ ret = sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SET_SHMEM,
+ nacl->shmem_phys, 0, 0, 0, 0, 0);
+ rc = sbi_err_map_linux_errno(ret.error);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+void kvm_riscv_nacl_disable(void)
+{
+ if (!kvm_riscv_nacl_available())
+ return;
+
+ sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SET_SHMEM,
+ SBI_SHMEM_DISABLE, SBI_SHMEM_DISABLE, 0, 0, 0, 0);
+}
+
+void kvm_riscv_nacl_exit(void)
+{
+ int cpu;
+ struct kvm_riscv_nacl *nacl;
+
+ if (!kvm_riscv_nacl_available())
+ return;
+
+ /* Allocate per-CPU shared memory */
+ for_each_possible_cpu(cpu) {
+ nacl = per_cpu_ptr(&kvm_riscv_nacl, cpu);
+ if (!nacl->shmem)
+ continue;
+
+ free_pages((unsigned long)nacl->shmem,
+ get_order(SBI_NACL_SHMEM_SIZE));
+ nacl->shmem = NULL;
+ nacl->shmem_phys = 0;
+ }
+}
+
+static long nacl_probe_feature(long feature_id)
+{
+ struct sbiret ret;
+
+ if (!kvm_riscv_nacl_available())
+ return 0;
+
+ ret = sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_PROBE_FEATURE,
+ feature_id, 0, 0, 0, 0, 0);
+ return ret.value;
+}
+
+int kvm_riscv_nacl_init(void)
+{
+ int cpu;
+ struct page *shmem_page;
+ struct kvm_riscv_nacl *nacl;
+
+ if (sbi_spec_version < sbi_mk_version(1, 0) ||
+ sbi_probe_extension(SBI_EXT_NACL) <= 0)
+ return -ENODEV;
+
+ /* Enable NACL support */
+ static_branch_enable(&kvm_riscv_nacl_available);
+
+ /* Probe NACL features */
+ if (nacl_probe_feature(SBI_NACL_FEAT_SYNC_CSR))
+ static_branch_enable(&kvm_riscv_nacl_sync_csr_available);
+ if (nacl_probe_feature(SBI_NACL_FEAT_SYNC_HFENCE))
+ static_branch_enable(&kvm_riscv_nacl_sync_hfence_available);
+ if (nacl_probe_feature(SBI_NACL_FEAT_SYNC_SRET))
+ static_branch_enable(&kvm_riscv_nacl_sync_sret_available);
+ if (nacl_probe_feature(SBI_NACL_FEAT_AUTOSWAP_CSR))
+ static_branch_enable(&kvm_riscv_nacl_autoswap_csr_available);
+
+ /* Allocate per-CPU shared memory */
+ for_each_possible_cpu(cpu) {
+ nacl = per_cpu_ptr(&kvm_riscv_nacl, cpu);
+
+ shmem_page = alloc_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(SBI_NACL_SHMEM_SIZE));
+ if (!shmem_page) {
+ kvm_riscv_nacl_exit();
+ return -ENOMEM;
+ }
+ nacl->shmem = page_to_virt(shmem_page);
+ nacl->shmem_phys = page_to_phys(shmem_page);
+ }
+
+ return 0;
+}
diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c
index 23c0e82b5103..2f91ea5f8493 100644
--- a/arch/riscv/kvm/tlb.c
+++ b/arch/riscv/kvm/tlb.c
@@ -14,6 +14,7 @@
#include <asm/csr.h>
#include <asm/cpufeature.h>
#include <asm/insn-def.h>
+#include <asm/kvm_nacl.h>
#define has_svinval() riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
@@ -186,18 +187,24 @@ void kvm_riscv_fence_i_process(struct kvm_vcpu *vcpu)
void kvm_riscv_hfence_gvma_vmid_all_process(struct kvm_vcpu *vcpu)
{
- struct kvm_vmid *vmid;
+ struct kvm_vmid *v = &vcpu->kvm->arch.vmid;
+ unsigned long vmid = READ_ONCE(v->vmid);
- vmid = &vcpu->kvm->arch.vmid;
- kvm_riscv_local_hfence_gvma_vmid_all(READ_ONCE(vmid->vmid));
+ if (kvm_riscv_nacl_available())
+ nacl_hfence_gvma_vmid_all(nacl_shmem(), vmid);
+ else
+ kvm_riscv_local_hfence_gvma_vmid_all(vmid);
}
void kvm_riscv_hfence_vvma_all_process(struct kvm_vcpu *vcpu)
{
- struct kvm_vmid *vmid;
+ struct kvm_vmid *v = &vcpu->kvm->arch.vmid;
+ unsigned long vmid = READ_ONCE(v->vmid);
- vmid = &vcpu->kvm->arch.vmid;
- kvm_riscv_local_hfence_vvma_all(READ_ONCE(vmid->vmid));
+ if (kvm_riscv_nacl_available())
+ nacl_hfence_vvma_all(nacl_shmem(), vmid);
+ else
+ kvm_riscv_local_hfence_vvma_all(vmid);
}
static bool vcpu_hfence_dequeue(struct kvm_vcpu *vcpu,
@@ -251,6 +258,7 @@ static bool vcpu_hfence_enqueue(struct kvm_vcpu *vcpu,
void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)
{
+ unsigned long vmid;
struct kvm_riscv_hfence d = { 0 };
struct kvm_vmid *v = &vcpu->kvm->arch.vmid;
@@ -259,26 +267,41 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)
case KVM_RISCV_HFENCE_UNKNOWN:
break;
case KVM_RISCV_HFENCE_GVMA_VMID_GPA:
- kvm_riscv_local_hfence_gvma_vmid_gpa(
- READ_ONCE(v->vmid),
- d.addr, d.size, d.order);
+ vmid = READ_ONCE(v->vmid);
+ if (kvm_riscv_nacl_available())
+ nacl_hfence_gvma_vmid(nacl_shmem(), vmid,
+ d.addr, d.size, d.order);
+ else
+ kvm_riscv_local_hfence_gvma_vmid_gpa(vmid, d.addr,
+ d.size, d.order);
break;
case KVM_RISCV_HFENCE_VVMA_ASID_GVA:
kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD);
- kvm_riscv_local_hfence_vvma_asid_gva(
- READ_ONCE(v->vmid), d.asid,
- d.addr, d.size, d.order);
+ vmid = READ_ONCE(v->vmid);
+ if (kvm_riscv_nacl_available())
+ nacl_hfence_vvma_asid(nacl_shmem(), vmid, d.asid,
+ d.addr, d.size, d.order);
+ else
+ kvm_riscv_local_hfence_vvma_asid_gva(vmid, d.asid, d.addr,
+ d.size, d.order);
break;
case KVM_RISCV_HFENCE_VVMA_ASID_ALL:
kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD);
- kvm_riscv_local_hfence_vvma_asid_all(
- READ_ONCE(v->vmid), d.asid);
+ vmid = READ_ONCE(v->vmid);
+ if (kvm_riscv_nacl_available())
+ nacl_hfence_vvma_asid_all(nacl_shmem(), vmid, d.asid);
+ else
+ kvm_riscv_local_hfence_vvma_asid_all(vmid, d.asid);
break;
case KVM_RISCV_HFENCE_VVMA_GVA:
kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_RCVD);
- kvm_riscv_local_hfence_vvma_gva(
- READ_ONCE(v->vmid),
- d.addr, d.size, d.order);
+ vmid = READ_ONCE(v->vmid);
+ if (kvm_riscv_nacl_available())
+ nacl_hfence_vvma(nacl_shmem(), vmid,
+ d.addr, d.size, d.order);
+ else
+ kvm_riscv_local_hfence_vvma_gva(vmid, d.addr,
+ d.size, d.order);
break;
default:
break;
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 8d7d381737ee..e048dcc6e65e 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -17,8 +17,8 @@
#include <linux/sched/signal.h>
#include <linux/fs.h>
#include <linux/kvm_host.h>
-#include <asm/csr.h>
#include <asm/cacheflush.h>
+#include <asm/kvm_nacl.h>
#include <asm/kvm_vcpu_vector.h>
#define CREATE_TRACE_POINTS
@@ -226,6 +226,13 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
return (vcpu->arch.guest_context.sstatus & SR_SPP) ? true : false;
}
+#ifdef CONFIG_GUEST_PERF_EVENTS
+unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.guest_context.sepc;
+}
+#endif
+
vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
@@ -361,10 +368,10 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
/* Read current HVIP and VSIE CSRs */
- csr->vsie = csr_read(CSR_VSIE);
+ csr->vsie = ncsr_read(CSR_VSIE);
/* Sync-up HVIP.VSSIP bit changes does by Guest */
- hvip = csr_read(CSR_HVIP);
+ hvip = ncsr_read(CSR_HVIP);
if ((csr->hvip ^ hvip) & (1UL << IRQ_VS_SOFT)) {
if (hvip & (1UL << IRQ_VS_SOFT)) {
if (!test_and_set_bit(IRQ_VS_SOFT,
@@ -544,6 +551,10 @@ static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
if (riscv_isa_extension_available(isa, ZICBOZ))
cfg->henvcfg |= ENVCFG_CBZE;
+ if (riscv_isa_extension_available(isa, SVADU) &&
+ !riscv_isa_extension_available(isa, SVADE))
+ cfg->henvcfg |= ENVCFG_ADUE;
+
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
cfg->hstateen0 |= SMSTATEEN0_HSENVCFG;
if (riscv_isa_extension_available(isa, SSAIA))
@@ -561,26 +572,49 @@ static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
+ void *nsh;
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
- csr_write(CSR_VSSTATUS, csr->vsstatus);
- csr_write(CSR_VSIE, csr->vsie);
- csr_write(CSR_VSTVEC, csr->vstvec);
- csr_write(CSR_VSSCRATCH, csr->vsscratch);
- csr_write(CSR_VSEPC, csr->vsepc);
- csr_write(CSR_VSCAUSE, csr->vscause);
- csr_write(CSR_VSTVAL, csr->vstval);
- csr_write(CSR_HEDELEG, cfg->hedeleg);
- csr_write(CSR_HVIP, csr->hvip);
- csr_write(CSR_VSATP, csr->vsatp);
- csr_write(CSR_HENVCFG, cfg->henvcfg);
- if (IS_ENABLED(CONFIG_32BIT))
- csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
- if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
- csr_write(CSR_HSTATEEN0, cfg->hstateen0);
+ if (kvm_riscv_nacl_sync_csr_available()) {
+ nsh = nacl_shmem();
+ nacl_csr_write(nsh, CSR_VSSTATUS, csr->vsstatus);
+ nacl_csr_write(nsh, CSR_VSIE, csr->vsie);
+ nacl_csr_write(nsh, CSR_VSTVEC, csr->vstvec);
+ nacl_csr_write(nsh, CSR_VSSCRATCH, csr->vsscratch);
+ nacl_csr_write(nsh, CSR_VSEPC, csr->vsepc);
+ nacl_csr_write(nsh, CSR_VSCAUSE, csr->vscause);
+ nacl_csr_write(nsh, CSR_VSTVAL, csr->vstval);
+ nacl_csr_write(nsh, CSR_HEDELEG, cfg->hedeleg);
+ nacl_csr_write(nsh, CSR_HVIP, csr->hvip);
+ nacl_csr_write(nsh, CSR_VSATP, csr->vsatp);
+ nacl_csr_write(nsh, CSR_HENVCFG, cfg->henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ nacl_csr_write(nsh, CSR_HENVCFGH, cfg->henvcfg >> 32);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
+ nacl_csr_write(nsh, CSR_HSTATEEN0, cfg->hstateen0);
+ if (IS_ENABLED(CONFIG_32BIT))
+ nacl_csr_write(nsh, CSR_HSTATEEN0H, cfg->hstateen0 >> 32);
+ }
+ } else {
+ csr_write(CSR_VSSTATUS, csr->vsstatus);
+ csr_write(CSR_VSIE, csr->vsie);
+ csr_write(CSR_VSTVEC, csr->vstvec);
+ csr_write(CSR_VSSCRATCH, csr->vsscratch);
+ csr_write(CSR_VSEPC, csr->vsepc);
+ csr_write(CSR_VSCAUSE, csr->vscause);
+ csr_write(CSR_VSTVAL, csr->vstval);
+ csr_write(CSR_HEDELEG, cfg->hedeleg);
+ csr_write(CSR_HVIP, csr->hvip);
+ csr_write(CSR_VSATP, csr->vsatp);
+ csr_write(CSR_HENVCFG, cfg->henvcfg);
if (IS_ENABLED(CONFIG_32BIT))
- csr_write(CSR_HSTATEEN0H, cfg->hstateen0 >> 32);
+ csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
+ csr_write(CSR_HSTATEEN0, cfg->hstateen0);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_HSTATEEN0H, cfg->hstateen0 >> 32);
+ }
}
kvm_riscv_gstage_update_hgatp(vcpu);
@@ -603,6 +637,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
+ void *nsh;
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
vcpu->cpu = -1;
@@ -618,15 +653,28 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
vcpu->arch.isa);
kvm_riscv_vcpu_host_vector_restore(&vcpu->arch.host_context);
- csr->vsstatus = csr_read(CSR_VSSTATUS);
- csr->vsie = csr_read(CSR_VSIE);
- csr->vstvec = csr_read(CSR_VSTVEC);
- csr->vsscratch = csr_read(CSR_VSSCRATCH);
- csr->vsepc = csr_read(CSR_VSEPC);
- csr->vscause = csr_read(CSR_VSCAUSE);
- csr->vstval = csr_read(CSR_VSTVAL);
- csr->hvip = csr_read(CSR_HVIP);
- csr->vsatp = csr_read(CSR_VSATP);
+ if (kvm_riscv_nacl_available()) {
+ nsh = nacl_shmem();
+ csr->vsstatus = nacl_csr_read(nsh, CSR_VSSTATUS);
+ csr->vsie = nacl_csr_read(nsh, CSR_VSIE);
+ csr->vstvec = nacl_csr_read(nsh, CSR_VSTVEC);
+ csr->vsscratch = nacl_csr_read(nsh, CSR_VSSCRATCH);
+ csr->vsepc = nacl_csr_read(nsh, CSR_VSEPC);
+ csr->vscause = nacl_csr_read(nsh, CSR_VSCAUSE);
+ csr->vstval = nacl_csr_read(nsh, CSR_VSTVAL);
+ csr->hvip = nacl_csr_read(nsh, CSR_HVIP);
+ csr->vsatp = nacl_csr_read(nsh, CSR_VSATP);
+ } else {
+ csr->vsstatus = csr_read(CSR_VSSTATUS);
+ csr->vsie = csr_read(CSR_VSIE);
+ csr->vstvec = csr_read(CSR_VSTVEC);
+ csr->vsscratch = csr_read(CSR_VSSCRATCH);
+ csr->vsepc = csr_read(CSR_VSEPC);
+ csr->vscause = csr_read(CSR_VSCAUSE);
+ csr->vstval = csr_read(CSR_VSTVAL);
+ csr->hvip = csr_read(CSR_HVIP);
+ csr->vsatp = csr_read(CSR_VSATP);
+ }
}
static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu)
@@ -681,7 +729,7 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
{
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
- csr_write(CSR_HVIP, csr->hvip);
+ ncsr_write(CSR_HVIP, csr->hvip);
kvm_riscv_vcpu_aia_update_hvip(vcpu);
}
@@ -691,6 +739,7 @@ static __always_inline void kvm_riscv_vcpu_swap_in_guest_state(struct kvm_vcpu *
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+ vcpu->arch.host_scounteren = csr_swap(CSR_SCOUNTEREN, csr->scounteren);
vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
(cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
@@ -704,6 +753,7 @@ static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *v
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+ csr->scounteren = csr_swap(CSR_SCOUNTEREN, vcpu->arch.host_scounteren);
csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
(cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
@@ -718,11 +768,81 @@ static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *v
* This must be noinstr as instrumentation may make use of RCU, and this is not
* safe during the EQS.
*/
-static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu)
+static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu,
+ struct kvm_cpu_trap *trap)
{
+ void *nsh;
+ struct kvm_cpu_context *gcntx = &vcpu->arch.guest_context;
+ struct kvm_cpu_context *hcntx = &vcpu->arch.host_context;
+
+ /*
+ * We save trap CSRs (such as SEPC, SCAUSE, STVAL, HTVAL, and
+ * HTINST) here because we do local_irq_enable() after this
+ * function in kvm_arch_vcpu_ioctl_run() which can result in
+ * an interrupt immediately after local_irq_enable() and can
+ * potentially change trap CSRs.
+ */
+
kvm_riscv_vcpu_swap_in_guest_state(vcpu);
guest_state_enter_irqoff();
- __kvm_riscv_switch_to(&vcpu->arch);
+
+ if (kvm_riscv_nacl_sync_sret_available()) {
+ nsh = nacl_shmem();
+
+ if (kvm_riscv_nacl_autoswap_csr_available()) {
+ hcntx->hstatus =
+ nacl_csr_read(nsh, CSR_HSTATUS);
+ nacl_scratch_write_long(nsh,
+ SBI_NACL_SHMEM_AUTOSWAP_OFFSET +
+ SBI_NACL_SHMEM_AUTOSWAP_HSTATUS,
+ gcntx->hstatus);
+ nacl_scratch_write_long(nsh,
+ SBI_NACL_SHMEM_AUTOSWAP_OFFSET,
+ SBI_NACL_SHMEM_AUTOSWAP_FLAG_HSTATUS);
+ } else if (kvm_riscv_nacl_sync_csr_available()) {
+ hcntx->hstatus = nacl_csr_swap(nsh,
+ CSR_HSTATUS, gcntx->hstatus);
+ } else {
+ hcntx->hstatus = csr_swap(CSR_HSTATUS, gcntx->hstatus);
+ }
+
+ nacl_scratch_write_longs(nsh,
+ SBI_NACL_SHMEM_SRET_OFFSET +
+ SBI_NACL_SHMEM_SRET_X(1),
+ &gcntx->ra,
+ SBI_NACL_SHMEM_SRET_X_LAST);
+
+ __kvm_riscv_nacl_switch_to(&vcpu->arch, SBI_EXT_NACL,
+ SBI_EXT_NACL_SYNC_SRET);
+
+ if (kvm_riscv_nacl_autoswap_csr_available()) {
+ nacl_scratch_write_long(nsh,
+ SBI_NACL_SHMEM_AUTOSWAP_OFFSET,
+ 0);
+ gcntx->hstatus = nacl_scratch_read_long(nsh,
+ SBI_NACL_SHMEM_AUTOSWAP_OFFSET +
+ SBI_NACL_SHMEM_AUTOSWAP_HSTATUS);
+ } else {
+ gcntx->hstatus = csr_swap(CSR_HSTATUS, hcntx->hstatus);
+ }
+
+ trap->htval = nacl_csr_read(nsh, CSR_HTVAL);
+ trap->htinst = nacl_csr_read(nsh, CSR_HTINST);
+ } else {
+ hcntx->hstatus = csr_swap(CSR_HSTATUS, gcntx->hstatus);
+
+ __kvm_riscv_switch_to(&vcpu->arch);
+
+ gcntx->hstatus = csr_swap(CSR_HSTATUS, hcntx->hstatus);
+
+ trap->htval = csr_read(CSR_HTVAL);
+ trap->htinst = csr_read(CSR_HTINST);
+ }
+
+ trap->sepc = gcntx->sepc;
+ trap->scause = csr_read(CSR_SCAUSE);
+ trap->stval = csr_read(CSR_STVAL);
+
vcpu->arch.last_exit_cpu = vcpu->cpu;
guest_state_exit_irqoff();
kvm_riscv_vcpu_swap_in_host_state(vcpu);
@@ -839,22 +959,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
guest_timing_enter_irqoff();
- kvm_riscv_vcpu_enter_exit(vcpu);
+ kvm_riscv_vcpu_enter_exit(vcpu, &trap);
vcpu->mode = OUTSIDE_GUEST_MODE;
vcpu->stat.exits++;
- /*
- * Save SCAUSE, STVAL, HTVAL, and HTINST because we might
- * get an interrupt between __kvm_riscv_switch_to() and
- * local_irq_enable() which can potentially change CSRs.
- */
- trap.sepc = vcpu->arch.guest_context.sepc;
- trap.scause = csr_read(CSR_SCAUSE);
- trap.stval = csr_read(CSR_STVAL);
- trap.htval = csr_read(CSR_HTVAL);
- trap.htinst = csr_read(CSR_HTINST);
-
/* Syncup interrupts state with HW */
kvm_riscv_vcpu_sync_interrupts(vcpu);
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index b319c4c13c54..753f66c8b70a 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -15,6 +15,7 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
#include <asm/kvm_vcpu_vector.h>
+#include <asm/pgtable.h>
#include <asm/vector.h>
#define KVM_RISCV_BASE_ISA_MASK GENMASK(25, 0)
@@ -34,10 +35,14 @@ static const unsigned long kvm_isa_ext_arr[] = {
[KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
[KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
/* Multi letter extensions (alphabetically sorted) */
+ [KVM_RISCV_ISA_EXT_SMNPM] = RISCV_ISA_EXT_SSNPM,
KVM_ISA_EXT_ARR(SMSTATEEN),
KVM_ISA_EXT_ARR(SSAIA),
KVM_ISA_EXT_ARR(SSCOFPMF),
+ KVM_ISA_EXT_ARR(SSNPM),
KVM_ISA_EXT_ARR(SSTC),
+ KVM_ISA_EXT_ARR(SVADE),
+ KVM_ISA_EXT_ARR(SVADU),
KVM_ISA_EXT_ARR(SVINVAL),
KVM_ISA_EXT_ARR(SVNAPOT),
KVM_ISA_EXT_ARR(SVPBMT),
@@ -110,6 +115,12 @@ static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
case KVM_RISCV_ISA_EXT_SSCOFPMF:
/* Sscofpmf depends on interrupt filtering defined in ssaia */
return __riscv_isa_extension_available(NULL, RISCV_ISA_EXT_SSAIA);
+ case KVM_RISCV_ISA_EXT_SVADU:
+ /*
+ * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
+ * Guest OS can use Svadu only when host OS enable Svadu.
+ */
+ return arch_has_hw_pte_young();
case KVM_RISCV_ISA_EXT_V:
return riscv_v_vstate_ctrl_user_allowed();
default:
@@ -127,8 +138,10 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
case KVM_RISCV_ISA_EXT_C:
case KVM_RISCV_ISA_EXT_I:
case KVM_RISCV_ISA_EXT_M:
+ case KVM_RISCV_ISA_EXT_SMNPM:
/* There is not architectural config bit to disable sscofpmf completely */
case KVM_RISCV_ISA_EXT_SSCOFPMF:
+ case KVM_RISCV_ISA_EXT_SSNPM:
case KVM_RISCV_ISA_EXT_SSTC:
case KVM_RISCV_ISA_EXT_SVINVAL:
case KVM_RISCV_ISA_EXT_SVNAPOT:
@@ -181,6 +194,12 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
/* Extensions which can be disabled using Smstateen */
case KVM_RISCV_ISA_EXT_SSAIA:
return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
+ case KVM_RISCV_ISA_EXT_SVADE:
+ /*
+ * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
+ * Svade is not allowed to disable when the platform use Svade.
+ */
+ return arch_has_hw_pte_young();
default:
break;
}
diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
index 7de128be8db9..6e704ed86a83 100644
--- a/arch/riscv/kvm/vcpu_sbi.c
+++ b/arch/riscv/kvm/vcpu_sbi.c
@@ -486,19 +486,22 @@ void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
const struct kvm_riscv_sbi_extension_entry *entry;
const struct kvm_vcpu_sbi_extension *ext;
- int i;
+ int idx, i;
for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
entry = &sbi_ext[i];
ext = entry->ext_ptr;
+ idx = entry->ext_idx;
+
+ if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
+ continue;
if (ext->probe && !ext->probe(vcpu)) {
- scontext->ext_status[entry->ext_idx] =
- KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
+ scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
continue;
}
- scontext->ext_status[entry->ext_idx] = ext->default_disabled ?
+ scontext->ext_status[idx] = ext->default_disabled ?
KVM_RISCV_SBI_EXT_STATUS_DISABLED :
KVM_RISCV_SBI_EXT_STATUS_ENABLED;
}
diff --git a/arch/riscv/kvm/vcpu_switch.S b/arch/riscv/kvm/vcpu_switch.S
index 0c26189aa01c..47686bcb21e0 100644
--- a/arch/riscv/kvm/vcpu_switch.S
+++ b/arch/riscv/kvm/vcpu_switch.S
@@ -11,11 +11,7 @@
#include <asm/asm-offsets.h>
#include <asm/csr.h>
- .text
- .altmacro
- .option norelax
-
-SYM_FUNC_START(__kvm_riscv_switch_to)
+.macro SAVE_HOST_GPRS
/* Save Host GPRs (except A0 and T0-T6) */
REG_S ra, (KVM_ARCH_HOST_RA)(a0)
REG_S sp, (KVM_ARCH_HOST_SP)(a0)
@@ -40,39 +36,33 @@ SYM_FUNC_START(__kvm_riscv_switch_to)
REG_S s9, (KVM_ARCH_HOST_S9)(a0)
REG_S s10, (KVM_ARCH_HOST_S10)(a0)
REG_S s11, (KVM_ARCH_HOST_S11)(a0)
+.endm
+.macro SAVE_HOST_AND_RESTORE_GUEST_CSRS __resume_addr
/* Load Guest CSR values */
REG_L t0, (KVM_ARCH_GUEST_SSTATUS)(a0)
- REG_L t1, (KVM_ARCH_GUEST_HSTATUS)(a0)
- REG_L t2, (KVM_ARCH_GUEST_SCOUNTEREN)(a0)
- la t4, .Lkvm_switch_return
- REG_L t5, (KVM_ARCH_GUEST_SEPC)(a0)
+ la t1, \__resume_addr
+ REG_L t2, (KVM_ARCH_GUEST_SEPC)(a0)
/* Save Host and Restore Guest SSTATUS */
csrrw t0, CSR_SSTATUS, t0
- /* Save Host and Restore Guest HSTATUS */
- csrrw t1, CSR_HSTATUS, t1
-
- /* Save Host and Restore Guest SCOUNTEREN */
- csrrw t2, CSR_SCOUNTEREN, t2
-
/* Save Host STVEC and change it to return path */
- csrrw t4, CSR_STVEC, t4
+ csrrw t1, CSR_STVEC, t1
+
+ /* Restore Guest SEPC */
+ csrw CSR_SEPC, t2
/* Save Host SSCRATCH and change it to struct kvm_vcpu_arch pointer */
csrrw t3, CSR_SSCRATCH, a0
- /* Restore Guest SEPC */
- csrw CSR_SEPC, t5
-
/* Store Host CSR values */
REG_S t0, (KVM_ARCH_HOST_SSTATUS)(a0)
- REG_S t1, (KVM_ARCH_HOST_HSTATUS)(a0)
- REG_S t2, (KVM_ARCH_HOST_SCOUNTEREN)(a0)
+ REG_S t1, (KVM_ARCH_HOST_STVEC)(a0)
REG_S t3, (KVM_ARCH_HOST_SSCRATCH)(a0)
- REG_S t4, (KVM_ARCH_HOST_STVEC)(a0)
+.endm
+.macro RESTORE_GUEST_GPRS
/* Restore Guest GPRs (except A0) */
REG_L ra, (KVM_ARCH_GUEST_RA)(a0)
REG_L sp, (KVM_ARCH_GUEST_SP)(a0)
@@ -107,13 +97,9 @@ SYM_FUNC_START(__kvm_riscv_switch_to)
/* Restore Guest A0 */
REG_L a0, (KVM_ARCH_GUEST_A0)(a0)
+.endm
- /* Resume Guest */
- sret
-
- /* Back to Host */
- .align 2
-.Lkvm_switch_return:
+.macro SAVE_GUEST_GPRS
/* Swap Guest A0 with SSCRATCH */
csrrw a0, CSR_SSCRATCH, a0
@@ -148,39 +134,33 @@ SYM_FUNC_START(__kvm_riscv_switch_to)
REG_S t4, (KVM_ARCH_GUEST_T4)(a0)
REG_S t5, (KVM_ARCH_GUEST_T5)(a0)
REG_S t6, (KVM_ARCH_GUEST_T6)(a0)
+.endm
+.macro SAVE_GUEST_AND_RESTORE_HOST_CSRS
/* Load Host CSR values */
- REG_L t1, (KVM_ARCH_HOST_STVEC)(a0)
- REG_L t2, (KVM_ARCH_HOST_SSCRATCH)(a0)
- REG_L t3, (KVM_ARCH_HOST_SCOUNTEREN)(a0)
- REG_L t4, (KVM_ARCH_HOST_HSTATUS)(a0)
- REG_L t5, (KVM_ARCH_HOST_SSTATUS)(a0)
-
- /* Save Guest SEPC */
- csrr t0, CSR_SEPC
+ REG_L t0, (KVM_ARCH_HOST_STVEC)(a0)
+ REG_L t1, (KVM_ARCH_HOST_SSCRATCH)(a0)
+ REG_L t2, (KVM_ARCH_HOST_SSTATUS)(a0)
/* Save Guest A0 and Restore Host SSCRATCH */
- csrrw t2, CSR_SSCRATCH, t2
+ csrrw t1, CSR_SSCRATCH, t1
- /* Restore Host STVEC */
- csrw CSR_STVEC, t1
-
- /* Save Guest and Restore Host SCOUNTEREN */
- csrrw t3, CSR_SCOUNTEREN, t3
+ /* Save Guest SEPC */
+ csrr t3, CSR_SEPC
- /* Save Guest and Restore Host HSTATUS */
- csrrw t4, CSR_HSTATUS, t4
+ /* Restore Host STVEC */
+ csrw CSR_STVEC, t0
/* Save Guest and Restore Host SSTATUS */
- csrrw t5, CSR_SSTATUS, t5
+ csrrw t2, CSR_SSTATUS, t2
/* Store Guest CSR values */
- REG_S t0, (KVM_ARCH_GUEST_SEPC)(a0)
- REG_S t2, (KVM_ARCH_GUEST_A0)(a0)
- REG_S t3, (KVM_ARCH_GUEST_SCOUNTEREN)(a0)
- REG_S t4, (KVM_ARCH_GUEST_HSTATUS)(a0)
- REG_S t5, (KVM_ARCH_GUEST_SSTATUS)(a0)
+ REG_S t1, (KVM_ARCH_GUEST_A0)(a0)
+ REG_S t2, (KVM_ARCH_GUEST_SSTATUS)(a0)
+ REG_S t3, (KVM_ARCH_GUEST_SEPC)(a0)
+.endm
+.macro RESTORE_HOST_GPRS
/* Restore Host GPRs (except A0 and T0-T6) */
REG_L ra, (KVM_ARCH_HOST_RA)(a0)
REG_L sp, (KVM_ARCH_HOST_SP)(a0)
@@ -205,11 +185,68 @@ SYM_FUNC_START(__kvm_riscv_switch_to)
REG_L s9, (KVM_ARCH_HOST_S9)(a0)
REG_L s10, (KVM_ARCH_HOST_S10)(a0)
REG_L s11, (KVM_ARCH_HOST_S11)(a0)
+.endm
+
+ .text
+ .altmacro
+ .option norelax
+
+ /*
+ * Parameters:
+ * A0 <= Pointer to struct kvm_vcpu_arch
+ */
+SYM_FUNC_START(__kvm_riscv_switch_to)
+ SAVE_HOST_GPRS
+
+ SAVE_HOST_AND_RESTORE_GUEST_CSRS .Lkvm_switch_return
+
+ RESTORE_GUEST_GPRS
+
+ /* Resume Guest using SRET */
+ sret
+
+ /* Back to Host */
+ .align 2
+.Lkvm_switch_return:
+ SAVE_GUEST_GPRS
+
+ SAVE_GUEST_AND_RESTORE_HOST_CSRS
+
+ RESTORE_HOST_GPRS
/* Return to C code */
ret
SYM_FUNC_END(__kvm_riscv_switch_to)
+ /*
+ * Parameters:
+ * A0 <= Pointer to struct kvm_vcpu_arch
+ * A1 <= SBI extension ID
+ * A2 <= SBI function ID
+ */
+SYM_FUNC_START(__kvm_riscv_nacl_switch_to)
+ SAVE_HOST_GPRS
+
+ SAVE_HOST_AND_RESTORE_GUEST_CSRS .Lkvm_nacl_switch_return
+
+ /* Resume Guest using SBI nested acceleration */
+ add a6, a2, zero
+ add a7, a1, zero
+ ecall
+
+ /* Back to Host */
+ .align 2
+.Lkvm_nacl_switch_return:
+ SAVE_GUEST_GPRS
+
+ SAVE_GUEST_AND_RESTORE_HOST_CSRS
+
+ RESTORE_HOST_GPRS
+
+ /* Return to C code */
+ ret
+SYM_FUNC_END(__kvm_riscv_nacl_switch_to)
+
SYM_CODE_START(__kvm_riscv_unpriv_trap)
/*
* We assume that faulting unpriv load/store instruction is
diff --git a/arch/riscv/kvm/vcpu_timer.c b/arch/riscv/kvm/vcpu_timer.c
index 75486b25ac45..96e7a4e463f7 100644
--- a/arch/riscv/kvm/vcpu_timer.c
+++ b/arch/riscv/kvm/vcpu_timer.c
@@ -11,8 +11,8 @@
#include <linux/kvm_host.h>
#include <linux/uaccess.h>
#include <clocksource/timer-riscv.h>
-#include <asm/csr.h>
#include <asm/delay.h>
+#include <asm/kvm_nacl.h>
#include <asm/kvm_vcpu_timer.h>
static u64 kvm_riscv_current_cycles(struct kvm_guest_timer *gt)
@@ -72,12 +72,12 @@ static int kvm_riscv_vcpu_timer_cancel(struct kvm_vcpu_timer *t)
static int kvm_riscv_vcpu_update_vstimecmp(struct kvm_vcpu *vcpu, u64 ncycles)
{
#if defined(CONFIG_32BIT)
- csr_write(CSR_VSTIMECMP, ncycles & 0xFFFFFFFF);
- csr_write(CSR_VSTIMECMPH, ncycles >> 32);
+ ncsr_write(CSR_VSTIMECMP, ncycles & 0xFFFFFFFF);
+ ncsr_write(CSR_VSTIMECMPH, ncycles >> 32);
#else
- csr_write(CSR_VSTIMECMP, ncycles);
+ ncsr_write(CSR_VSTIMECMP, ncycles);
#endif
- return 0;
+ return 0;
}
static int kvm_riscv_vcpu_update_hrtimer(struct kvm_vcpu *vcpu, u64 ncycles)
@@ -289,10 +289,10 @@ static void kvm_riscv_vcpu_update_timedelta(struct kvm_vcpu *vcpu)
struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
#if defined(CONFIG_32BIT)
- csr_write(CSR_HTIMEDELTA, (u32)(gt->time_delta));
- csr_write(CSR_HTIMEDELTAH, (u32)(gt->time_delta >> 32));
+ ncsr_write(CSR_HTIMEDELTA, (u32)(gt->time_delta));
+ ncsr_write(CSR_HTIMEDELTAH, (u32)(gt->time_delta >> 32));
#else
- csr_write(CSR_HTIMEDELTA, gt->time_delta);
+ ncsr_write(CSR_HTIMEDELTA, gt->time_delta);
#endif
}
@@ -306,10 +306,10 @@ void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
return;
#if defined(CONFIG_32BIT)
- csr_write(CSR_VSTIMECMP, (u32)t->next_cycles);
- csr_write(CSR_VSTIMECMPH, (u32)(t->next_cycles >> 32));
+ ncsr_write(CSR_VSTIMECMP, (u32)t->next_cycles);
+ ncsr_write(CSR_VSTIMECMPH, (u32)(t->next_cycles >> 32));
#else
- csr_write(CSR_VSTIMECMP, t->next_cycles);
+ ncsr_write(CSR_VSTIMECMP, t->next_cycles);
#endif
/* timer should be enabled for the remaining operations */
@@ -327,10 +327,10 @@ void kvm_riscv_vcpu_timer_sync(struct kvm_vcpu *vcpu)
return;
#if defined(CONFIG_32BIT)
- t->next_cycles = csr_read(CSR_VSTIMECMP);
- t->next_cycles |= (u64)csr_read(CSR_VSTIMECMPH) << 32;
+ t->next_cycles = ncsr_read(CSR_VSTIMECMP);
+ t->next_cycles |= (u64)ncsr_read(CSR_VSTIMECMPH) << 32;
#else
- t->next_cycles = csr_read(CSR_VSTIMECMP);
+ t->next_cycles = ncsr_read(CSR_VSTIMECMP);
#endif
}
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index 271d01a5ba4d..d815448758a1 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -386,6 +386,21 @@ int set_direct_map_default_noflush(struct page *page)
PAGE_KERNEL, __pgprot(_PAGE_EXEC));
}
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
+{
+ pgprot_t set, clear;
+
+ if (valid) {
+ set = PAGE_KERNEL;
+ clear = __pgprot(_PAGE_EXEC);
+ } else {
+ set = __pgprot(0);
+ clear = __pgprot(_PAGE_PRESENT);
+ }
+
+ return __set_memory((unsigned long)page_address(page), nr, set, clear);
+}
+
#ifdef CONFIG_DEBUG_PAGEALLOC
static int debug_pagealloc_set_page(pte_t *pte, unsigned long addr, void *data)
{
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 4cc631fa7039..ca60db75199d 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -10,7 +10,7 @@
#include <linux/filter.h>
#include <linux/memory.h>
#include <linux/stop_machine.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/cfi.h>
#include <asm/percpu.h>
#include "bpf_jit.h"
diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
index 6de753c667f4..f8cd2f70a7fb 100644
--- a/arch/riscv/net/bpf_jit_core.c
+++ b/arch/riscv/net/bpf_jit_core.c
@@ -9,7 +9,7 @@
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/memory.h>
-#include <asm/patch.h>
+#include <asm/text-patching.h>
#include <asm/cfi.h>
#include "bpf_jit.h"
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index d339fe4fdedf..0077969170e8 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -52,6 +52,13 @@ config KASAN_SHADOW_OFFSET
depends on KASAN
default 0x1C000000000000
+config GCC_ASM_FLAG_OUTPUT_BROKEN
+ def_bool CC_IS_GCC && GCC_VERSION < 140200
+ help
+ GCC versions before 14.2.0 may die with an internal
+ compiler error in some configurations if flag output
+ operands are used within inline assemblies.
+
config S390
def_bool y
#
@@ -80,6 +87,7 @@ config S390
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_MEM_ENCRYPT
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
+ select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SCALED_CPUTIME
select ARCH_HAS_SET_DIRECT_MAP
@@ -88,7 +96,7 @@ config S390
select ARCH_HAS_STRICT_MODULE_RWX
select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_HAS_UBSAN
- select ARCH_HAS_VDSO_DATA
+ select ARCH_HAS_VDSO_TIME_DATA
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_INLINE_READ_LOCK
select ARCH_INLINE_READ_LOCK_BH
@@ -211,6 +219,7 @@ config S390
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_DYNAMIC_KEY
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE
select HAVE_RETHOOK
@@ -224,6 +233,7 @@ config S390
select HAVE_VIRT_CPU_ACCOUNTING_IDLE
select IOMMU_HELPER if PCI
select IOMMU_SUPPORT if PCI
+ select LOCK_MM_AND_FIND_VMA
select MMU_GATHER_MERGE_VMAS
select MMU_GATHER_NO_GATHER
select MMU_GATHER_RCU_TABLE_FREE
@@ -276,6 +286,9 @@ config ARCH_SUPPORTS_CRASH_DUMP
This option also enables s390 zfcpdump.
See also <file:Documentation/arch/s390/zfcpdump.rst>
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
menu "Processor type and features"
config HAVE_MARCH_Z10_FEATURES
diff --git a/arch/s390/boot/physmem_info.c b/arch/s390/boot/physmem_info.c
index 1d131a81cb8b..7617aa2d2f7e 100644
--- a/arch/s390/boot/physmem_info.c
+++ b/arch/s390/boot/physmem_info.c
@@ -9,6 +9,7 @@
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/sclp.h>
+#include <asm/asm.h>
#include <asm/uv.h>
#include "decompressor.h"
#include "boot.h"
@@ -59,13 +60,13 @@ static int __diag260(unsigned long rx1, unsigned long rx2)
{
unsigned long reg1, reg2, ry;
union register_pair rx;
+ int cc, exception;
psw_t old;
- int rc;
rx.even = rx1;
rx.odd = rx2;
ry = 0x10; /* storage configuration */
- rc = -1; /* fail */
+ exception = 1;
asm volatile(
" mvc 0(16,%[psw_old]),0(%[psw_pgm])\n"
" epsw %[reg1],%[reg2]\n"
@@ -74,20 +75,22 @@ static int __diag260(unsigned long rx1, unsigned long rx2)
" larl %[reg1],1f\n"
" stg %[reg1],8(%[psw_pgm])\n"
" diag %[rx],%[ry],0x260\n"
- " ipm %[rc]\n"
- " srl %[rc],28\n"
+ " lhi %[exc],0\n"
"1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n"
- : [reg1] "=&d" (reg1),
+ CC_IPM(cc)
+ : CC_OUT(cc, cc),
+ [exc] "+d" (exception),
+ [reg1] "=&d" (reg1),
[reg2] "=&a" (reg2),
- [rc] "+&d" (rc),
[ry] "+&d" (ry),
"+Q" (get_lowcore()->program_new_psw),
"=Q" (old)
: [rx] "d" (rx.pair),
[psw_old] "a" (&old),
[psw_pgm] "a" (&get_lowcore()->program_new_psw)
- : "cc", "memory");
- return rc == 0 ? ry : -1;
+ : CC_CLOBBER_LIST("memory"));
+ cc = exception ? -1 : CC_TRANSFORM(cc);
+ return cc == 0 ? ry : -1;
}
static int diag260(void)
@@ -109,12 +112,49 @@ static int diag260(void)
return 0;
}
+#define DIAG500_SC_STOR_LIMIT 4
+
+static int diag500_storage_limit(unsigned long *max_physmem_end)
+{
+ unsigned long storage_limit;
+ unsigned long reg1, reg2;
+ psw_t old;
+
+ asm volatile(
+ " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n"
+ " epsw %[reg1],%[reg2]\n"
+ " st %[reg1],0(%[psw_pgm])\n"
+ " st %[reg2],4(%[psw_pgm])\n"
+ " larl %[reg1],1f\n"
+ " stg %[reg1],8(%[psw_pgm])\n"
+ " lghi 1,%[subcode]\n"
+ " lghi 2,0\n"
+ " diag 2,4,0x500\n"
+ "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n"
+ " lgr %[slimit],2\n"
+ : [reg1] "=&d" (reg1),
+ [reg2] "=&a" (reg2),
+ [slimit] "=d" (storage_limit),
+ "=Q" (get_lowcore()->program_new_psw),
+ "=Q" (old)
+ : [psw_old] "a" (&old),
+ [psw_pgm] "a" (&get_lowcore()->program_new_psw),
+ [subcode] "i" (DIAG500_SC_STOR_LIMIT)
+ : "memory", "1", "2");
+ if (!storage_limit)
+ return -EINVAL;
+ /* Convert inclusive end to exclusive end */
+ *max_physmem_end = storage_limit + 1;
+ return 0;
+}
+
static int tprot(unsigned long addr)
{
unsigned long reg1, reg2;
- int rc = -EFAULT;
+ int cc, exception;
psw_t old;
+ exception = 1;
asm volatile(
" mvc 0(16,%[psw_old]),0(%[psw_pgm])\n"
" epsw %[reg1],%[reg2]\n"
@@ -123,19 +163,21 @@ static int tprot(unsigned long addr)
" larl %[reg1],1f\n"
" stg %[reg1],8(%[psw_pgm])\n"
" tprot 0(%[addr]),0\n"
- " ipm %[rc]\n"
- " srl %[rc],28\n"
+ " lhi %[exc],0\n"
"1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n"
- : [reg1] "=&d" (reg1),
+ CC_IPM(cc)
+ : CC_OUT(cc, cc),
+ [exc] "+d" (exception),
+ [reg1] "=&d" (reg1),
[reg2] "=&a" (reg2),
- [rc] "+&d" (rc),
"=Q" (get_lowcore()->program_new_psw.addr),
"=Q" (old)
: [psw_old] "a" (&old),
[psw_pgm] "a" (&get_lowcore()->program_new_psw),
[addr] "a" (addr)
- : "cc", "memory");
- return rc;
+ : CC_CLOBBER_LIST("memory"));
+ cc = exception ? -EFAULT : CC_TRANSFORM(cc);
+ return cc;
}
static unsigned long search_mem_end(void)
@@ -157,7 +199,9 @@ unsigned long detect_max_physmem_end(void)
{
unsigned long max_physmem_end = 0;
- if (!sclp_early_get_memsize(&max_physmem_end)) {
+ if (!diag500_storage_limit(&max_physmem_end)) {
+ physmem_info.info_source = MEM_DETECT_DIAG500_STOR_LIMIT;
+ } else if (!sclp_early_get_memsize(&max_physmem_end)) {
physmem_info.info_source = MEM_DETECT_SCLP_READ_INFO;
} else {
max_physmem_end = search_mem_end();
@@ -170,6 +214,13 @@ void detect_physmem_online_ranges(unsigned long max_physmem_end)
{
if (!sclp_early_read_storage_info()) {
physmem_info.info_source = MEM_DETECT_SCLP_STOR_INFO;
+ } else if (physmem_info.info_source == MEM_DETECT_DIAG500_STOR_LIMIT) {
+ unsigned long online_end;
+
+ if (!sclp_early_get_memsize(&online_end)) {
+ physmem_info.info_source = MEM_DETECT_SCLP_READ_INFO;
+ add_physmem_online_range(0, online_end);
+ }
} else if (!diag260()) {
physmem_info.info_source = MEM_DETECT_DIAG260;
} else if (max_physmem_end) {
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index c8f149ad77e5..abe6e6c0ab98 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -182,12 +182,15 @@ static void kaslr_adjust_got(unsigned long offset)
* Merge information from several sources into a single ident_map_size value.
* "ident_map_size" represents the upper limit of physical memory we may ever
* reach. It might not be all online memory, but also include standby (offline)
- * memory. "ident_map_size" could be lower then actual standby or even online
+ * memory or memory areas reserved for other means (e.g., memory devices such as
+ * virtio-mem).
+ *
+ * "ident_map_size" could be lower then actual standby/reserved or even online
* memory present, due to limiting factors. We should never go above this limit.
* It is the size of our identity mapping.
*
* Consider the following factors:
- * 1. max_physmem_end - end of physical memory online or standby.
+ * 1. max_physmem_end - end of physical memory online, standby or reserved.
* Always >= end of the last online memory range (get_physmem_online_end()).
* 2. CONFIG_MAX_PHYSMEM_BITS - the maximum size of physical memory the
* kernel is able to support.
@@ -480,7 +483,7 @@ void startup_kernel(void)
* __vmlinux_relocs_64_end as the lower range address. However,
* .amode31 section is written to by the decompressed kernel - at
* that time the contents of .vmlinux.relocs is not needed anymore.
- * Conversly, .vmlinux.relocs is read only by the decompressor, even
+ * Conversely, .vmlinux.relocs is read only by the decompressor, even
* before the kernel started. Therefore, in case the two sections
* overlap there is no risk of corrupting any data.
*/
diff --git a/arch/s390/boot/uv.c b/arch/s390/boot/uv.c
index 318e6ba95bfd..4568e8f81dac 100644
--- a/arch/s390/boot/uv.c
+++ b/arch/s390/boot/uv.c
@@ -22,8 +22,8 @@ void uv_query_info(void)
if (!test_facility(158))
return;
- /* rc==0x100 means that there is additional data we do not process */
- if (uv_call(0, (uint64_t)&uvcb) && uvcb.header.rc != 0x100)
+ /* Ignore that there might be more data we do not process */
+ if (uv_call(0, (uint64_t)&uvcb) && uvcb.header.rc != UVC_RC_MORE_DATA)
return;
if (IS_ENABLED(CONFIG_KVM)) {
@@ -46,7 +46,8 @@ void uv_query_info(void)
uv_info.supp_add_secret_req_ver = uvcb.supp_add_secret_req_ver;
uv_info.supp_add_secret_pcf = uvcb.supp_add_secret_pcf;
uv_info.supp_secret_types = uvcb.supp_secret_types;
- uv_info.max_secrets = uvcb.max_secrets;
+ uv_info.max_assoc_secrets = uvcb.max_assoc_secrets;
+ uv_info.max_retr_secrets = uvcb.max_retr_secrets;
}
if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) &&
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index fb0e9a1d9be2..d8d227ab82de 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -625,6 +625,7 @@ CONFIG_VFIO_PCI=m
CONFIG_MLX5_VFIO_PCI=m
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m
+CONFIG_VIRTIO_MEM=m
CONFIG_VIRTIO_INPUT=y
CONFIG_VHOST_NET=m
CONFIG_VHOST_VSOCK=m
@@ -810,6 +811,7 @@ CONFIG_PKEY=m
CONFIG_PKEY_CCA=m
CONFIG_PKEY_EP11=m
CONFIG_PKEY_PCKMO=m
+CONFIG_PKEY_UV=m
CONFIG_CRYPTO_PAES_S390=m
CONFIG_CRYPTO_DEV_VIRTIO=m
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig
index 88be0a734b60..6c2f2bb4fbf8 100644
--- a/arch/s390/configs/defconfig
+++ b/arch/s390/configs/defconfig
@@ -615,6 +615,7 @@ CONFIG_VFIO_PCI=m
CONFIG_MLX5_VFIO_PCI=m
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m
+CONFIG_VIRTIO_MEM=m
CONFIG_VIRTIO_INPUT=y
CONFIG_VHOST_NET=m
CONFIG_VHOST_VSOCK=m
@@ -797,6 +798,7 @@ CONFIG_PKEY=m
CONFIG_PKEY_CCA=m
CONFIG_PKEY_EP11=m
CONFIG_PKEY_PCKMO=m
+CONFIG_PKEY_UV=m
CONFIG_CRYPTO_PAES_S390=m
CONFIG_CRYPTO_DEV_VIRTIO=m
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c
index ef4491ccbbf8..511093713a6f 100644
--- a/arch/s390/crypto/paes_s390.c
+++ b/arch/s390/crypto/paes_s390.c
@@ -34,14 +34,22 @@
* is called. As paes can handle different kinds of key blobs
* and padding is also possible, the limits need to be generous.
*/
-#define PAES_MIN_KEYSIZE 16
-#define PAES_MAX_KEYSIZE MAXEP11AESKEYBLOBSIZE
+#define PAES_MIN_KEYSIZE 16
+#define PAES_MAX_KEYSIZE MAXEP11AESKEYBLOBSIZE
+#define PAES_256_PROTKEY_SIZE (32 + 32) /* key + verification pattern */
+#define PXTS_256_PROTKEY_SIZE (32 + 32 + 32) /* k1 + k2 + verification pattern */
static u8 *ctrblk;
static DEFINE_MUTEX(ctrblk_lock);
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
+struct paes_protkey {
+ u32 type;
+ u32 len;
+ u8 protkey[PXTS_256_PROTKEY_SIZE];
+};
+
struct key_blob {
/*
* Small keys will be stored in the keybuf. Larger keys are
@@ -55,31 +63,43 @@ struct key_blob {
unsigned int keylen;
};
-static inline int _key_to_kb(struct key_blob *kb,
- const u8 *key,
- unsigned int keylen)
+/*
+ * make_clrkey_token() - wrap the raw key ck with pkey clearkey token
+ * information.
+ * @returns the size of the clearkey token
+ */
+static inline u32 make_clrkey_token(const u8 *ck, size_t cklen, u8 *dest)
{
- struct clearkey_header {
+ struct clrkey_token {
u8 type;
u8 res0[3];
u8 version;
u8 res1[3];
u32 keytype;
u32 len;
- } __packed * h;
+ u8 key[];
+ } __packed *token = (struct clrkey_token *)dest;
+
+ token->type = 0x00;
+ token->version = 0x02;
+ token->keytype = (cklen - 8) >> 3;
+ token->len = cklen;
+ memcpy(token->key, ck, cklen);
+
+ return sizeof(*token) + cklen;
+}
+static inline int _key_to_kb(struct key_blob *kb,
+ const u8 *key,
+ unsigned int keylen)
+{
switch (keylen) {
case 16:
case 24:
case 32:
/* clear key value, prepare pkey clear key token in keybuf */
memset(kb->keybuf, 0, sizeof(kb->keybuf));
- h = (struct clearkey_header *) kb->keybuf;
- h->version = 0x02; /* TOKVER_CLEAR_KEY */
- h->keytype = (keylen - 8) >> 3;
- h->len = keylen;
- memcpy(kb->keybuf + sizeof(*h), key, keylen);
- kb->keylen = sizeof(*h) + keylen;
+ kb->keylen = make_clrkey_token(key, keylen, kb->keybuf);
kb->key = kb->keybuf;
break;
default:
@@ -99,6 +119,40 @@ static inline int _key_to_kb(struct key_blob *kb,
return 0;
}
+static inline int _xts_key_to_kb(struct key_blob *kb,
+ const u8 *key,
+ unsigned int keylen)
+{
+ size_t cklen = keylen / 2;
+
+ memset(kb->keybuf, 0, sizeof(kb->keybuf));
+
+ switch (keylen) {
+ case 32:
+ case 64:
+ /* clear key value, prepare pkey clear key tokens in keybuf */
+ kb->key = kb->keybuf;
+ kb->keylen = make_clrkey_token(key, cklen, kb->key);
+ kb->keylen += make_clrkey_token(key + cklen, cklen,
+ kb->key + kb->keylen);
+ break;
+ default:
+ /* other key material, let pkey handle this */
+ if (keylen <= sizeof(kb->keybuf)) {
+ kb->key = kb->keybuf;
+ } else {
+ kb->key = kmalloc(keylen, GFP_KERNEL);
+ if (!kb->key)
+ return -ENOMEM;
+ }
+ memcpy(kb->key, key, keylen);
+ kb->keylen = keylen;
+ break;
+ }
+
+ return 0;
+}
+
static inline void _free_kb_keybuf(struct key_blob *kb)
{
if (kb->key && kb->key != kb->keybuf
@@ -106,52 +160,53 @@ static inline void _free_kb_keybuf(struct key_blob *kb)
kfree_sensitive(kb->key);
kb->key = NULL;
}
+ memzero_explicit(kb->keybuf, sizeof(kb->keybuf));
}
struct s390_paes_ctx {
struct key_blob kb;
- struct pkey_protkey pk;
+ struct paes_protkey pk;
spinlock_t pk_lock;
unsigned long fc;
};
struct s390_pxts_ctx {
- struct key_blob kb[2];
- struct pkey_protkey pk[2];
+ struct key_blob kb;
+ struct paes_protkey pk[2];
spinlock_t pk_lock;
unsigned long fc;
};
-static inline int __paes_keyblob2pkey(struct key_blob *kb,
- struct pkey_protkey *pk)
+static inline int __paes_keyblob2pkey(const u8 *key, unsigned int keylen,
+ struct paes_protkey *pk)
{
- int i, ret = -EIO;
+ int i, rc = -EIO;
/* try three times in case of busy card */
- for (i = 0; ret && i < 3; i++) {
- if (ret == -EBUSY && in_task()) {
+ for (i = 0; rc && i < 3; i++) {
+ if (rc == -EBUSY && in_task()) {
if (msleep_interruptible(1000))
return -EINTR;
}
- ret = pkey_key2protkey(kb->key, kb->keylen,
- pk->protkey, &pk->len, &pk->type);
+ rc = pkey_key2protkey(key, keylen, pk->protkey, &pk->len,
+ &pk->type);
}
- return ret;
+ return rc;
}
static inline int __paes_convert_key(struct s390_paes_ctx *ctx)
{
- int ret;
- struct pkey_protkey pkey;
+ struct paes_protkey pk;
+ int rc;
- pkey.len = sizeof(pkey.protkey);
- ret = __paes_keyblob2pkey(&ctx->kb, &pkey);
- if (ret)
- return ret;
+ pk.len = sizeof(pk.protkey);
+ rc = __paes_keyblob2pkey(ctx->kb.key, ctx->kb.keylen, &pk);
+ if (rc)
+ return rc;
spin_lock_bh(&ctx->pk_lock);
- memcpy(&ctx->pk, &pkey, sizeof(pkey));
+ memcpy(&ctx->pk, &pk, sizeof(pk));
spin_unlock_bh(&ctx->pk_lock);
return 0;
@@ -176,8 +231,8 @@ static void ecb_paes_exit(struct crypto_skcipher *tfm)
static inline int __ecb_paes_set_key(struct s390_paes_ctx *ctx)
{
- int rc;
unsigned long fc;
+ int rc;
rc = __paes_convert_key(ctx);
if (rc)
@@ -197,8 +252,8 @@ static inline int __ecb_paes_set_key(struct s390_paes_ctx *ctx)
static int ecb_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
unsigned int key_len)
{
- int rc;
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
+ int rc;
_free_kb_keybuf(&ctx->kb);
rc = _key_to_kb(&ctx->kb, in_key, key_len);
@@ -212,19 +267,19 @@ static int ecb_paes_crypt(struct skcipher_request *req, unsigned long modifier)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct skcipher_walk walk;
- unsigned int nbytes, n, k;
- int ret;
struct {
- u8 key[MAXPROTKEYSIZE];
+ u8 key[PAES_256_PROTKEY_SIZE];
} param;
+ struct skcipher_walk walk;
+ unsigned int nbytes, n, k;
+ int rc;
- ret = skcipher_walk_virt(&walk, req, false);
- if (ret)
- return ret;
+ rc = skcipher_walk_virt(&walk, req, false);
+ if (rc)
+ return rc;
spin_lock_bh(&ctx->pk_lock);
- memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+ memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE);
spin_unlock_bh(&ctx->pk_lock);
while ((nbytes = walk.nbytes) != 0) {
@@ -233,16 +288,16 @@ static int ecb_paes_crypt(struct skcipher_request *req, unsigned long modifier)
k = cpacf_km(ctx->fc | modifier, &param,
walk.dst.virt.addr, walk.src.virt.addr, n);
if (k)
- ret = skcipher_walk_done(&walk, nbytes - k);
+ rc = skcipher_walk_done(&walk, nbytes - k);
if (k < n) {
if (__paes_convert_key(ctx))
return skcipher_walk_done(&walk, -EIO);
spin_lock_bh(&ctx->pk_lock);
- memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+ memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE);
spin_unlock_bh(&ctx->pk_lock);
}
}
- return ret;
+ return rc;
}
static int ecb_paes_encrypt(struct skcipher_request *req)
@@ -291,8 +346,8 @@ static void cbc_paes_exit(struct crypto_skcipher *tfm)
static inline int __cbc_paes_set_key(struct s390_paes_ctx *ctx)
{
- int rc;
unsigned long fc;
+ int rc;
rc = __paes_convert_key(ctx);
if (rc)
@@ -312,8 +367,8 @@ static inline int __cbc_paes_set_key(struct s390_paes_ctx *ctx)
static int cbc_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
unsigned int key_len)
{
- int rc;
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
+ int rc;
_free_kb_keybuf(&ctx->kb);
rc = _key_to_kb(&ctx->kb, in_key, key_len);
@@ -327,21 +382,21 @@ static int cbc_paes_crypt(struct skcipher_request *req, unsigned long modifier)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct skcipher_walk walk;
- unsigned int nbytes, n, k;
- int ret;
struct {
u8 iv[AES_BLOCK_SIZE];
- u8 key[MAXPROTKEYSIZE];
+ u8 key[PAES_256_PROTKEY_SIZE];
} param;
+ struct skcipher_walk walk;
+ unsigned int nbytes, n, k;
+ int rc;
- ret = skcipher_walk_virt(&walk, req, false);
- if (ret)
- return ret;
+ rc = skcipher_walk_virt(&walk, req, false);
+ if (rc)
+ return rc;
memcpy(param.iv, walk.iv, AES_BLOCK_SIZE);
spin_lock_bh(&ctx->pk_lock);
- memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+ memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE);
spin_unlock_bh(&ctx->pk_lock);
while ((nbytes = walk.nbytes) != 0) {
@@ -351,17 +406,17 @@ static int cbc_paes_crypt(struct skcipher_request *req, unsigned long modifier)
walk.dst.virt.addr, walk.src.virt.addr, n);
if (k) {
memcpy(walk.iv, param.iv, AES_BLOCK_SIZE);
- ret = skcipher_walk_done(&walk, nbytes - k);
+ rc = skcipher_walk_done(&walk, nbytes - k);
}
if (k < n) {
if (__paes_convert_key(ctx))
return skcipher_walk_done(&walk, -EIO);
spin_lock_bh(&ctx->pk_lock);
- memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+ memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE);
spin_unlock_bh(&ctx->pk_lock);
}
}
- return ret;
+ return rc;
}
static int cbc_paes_encrypt(struct skcipher_request *req)
@@ -396,8 +451,7 @@ static int xts_paes_init(struct crypto_skcipher *tfm)
{
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
- ctx->kb[0].key = NULL;
- ctx->kb[1].key = NULL;
+ ctx->kb.key = NULL;
spin_lock_init(&ctx->pk_lock);
return 0;
@@ -407,24 +461,51 @@ static void xts_paes_exit(struct crypto_skcipher *tfm)
{
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
- _free_kb_keybuf(&ctx->kb[0]);
- _free_kb_keybuf(&ctx->kb[1]);
+ _free_kb_keybuf(&ctx->kb);
}
static inline int __xts_paes_convert_key(struct s390_pxts_ctx *ctx)
{
- struct pkey_protkey pkey0, pkey1;
+ struct paes_protkey pk0, pk1;
+ size_t split_keylen;
+ int rc;
- pkey0.len = sizeof(pkey0.protkey);
- pkey1.len = sizeof(pkey1.protkey);
+ pk0.len = sizeof(pk0.protkey);
+ pk1.len = sizeof(pk1.protkey);
- if (__paes_keyblob2pkey(&ctx->kb[0], &pkey0) ||
- __paes_keyblob2pkey(&ctx->kb[1], &pkey1))
+ rc = __paes_keyblob2pkey(ctx->kb.key, ctx->kb.keylen, &pk0);
+ if (rc)
+ return rc;
+
+ switch (pk0.type) {
+ case PKEY_KEYTYPE_AES_128:
+ case PKEY_KEYTYPE_AES_256:
+ /* second keytoken required */
+ if (ctx->kb.keylen % 2)
+ return -EINVAL;
+ split_keylen = ctx->kb.keylen / 2;
+
+ rc = __paes_keyblob2pkey(ctx->kb.key + split_keylen,
+ split_keylen, &pk1);
+ if (rc)
+ return rc;
+
+ if (pk0.type != pk1.type)
+ return -EINVAL;
+ break;
+ case PKEY_KEYTYPE_AES_XTS_128:
+ case PKEY_KEYTYPE_AES_XTS_256:
+ /* single key */
+ pk1.type = 0;
+ break;
+ default:
+ /* unsupported protected keytype */
return -EINVAL;
+ }
spin_lock_bh(&ctx->pk_lock);
- memcpy(&ctx->pk[0], &pkey0, sizeof(pkey0));
- memcpy(&ctx->pk[1], &pkey1, sizeof(pkey1));
+ ctx->pk[0] = pk0;
+ ctx->pk[1] = pk1;
spin_unlock_bh(&ctx->pk_lock);
return 0;
@@ -433,17 +514,30 @@ static inline int __xts_paes_convert_key(struct s390_pxts_ctx *ctx)
static inline int __xts_paes_set_key(struct s390_pxts_ctx *ctx)
{
unsigned long fc;
+ int rc;
- if (__xts_paes_convert_key(ctx))
- return -EINVAL;
-
- if (ctx->pk[0].type != ctx->pk[1].type)
- return -EINVAL;
+ rc = __xts_paes_convert_key(ctx);
+ if (rc)
+ return rc;
/* Pick the correct function code based on the protected key type */
- fc = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PXTS_128 :
- (ctx->pk[0].type == PKEY_KEYTYPE_AES_256) ?
- CPACF_KM_PXTS_256 : 0;
+ switch (ctx->pk[0].type) {
+ case PKEY_KEYTYPE_AES_128:
+ fc = CPACF_KM_PXTS_128;
+ break;
+ case PKEY_KEYTYPE_AES_256:
+ fc = CPACF_KM_PXTS_256;
+ break;
+ case PKEY_KEYTYPE_AES_XTS_128:
+ fc = CPACF_KM_PXTS_128_FULL;
+ break;
+ case PKEY_KEYTYPE_AES_XTS_256:
+ fc = CPACF_KM_PXTS_256_FULL;
+ break;
+ default:
+ fc = 0;
+ break;
+ }
/* Check if the function code is available */
ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0;
@@ -452,24 +546,19 @@ static inline int __xts_paes_set_key(struct s390_pxts_ctx *ctx)
}
static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
- unsigned int xts_key_len)
+ unsigned int in_keylen)
{
- int rc;
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
u8 ckey[2 * AES_MAX_KEY_SIZE];
- unsigned int ckey_len, key_len;
+ unsigned int ckey_len;
+ int rc;
- if (xts_key_len % 2)
+ if ((in_keylen == 32 || in_keylen == 64) &&
+ xts_verify_key(tfm, in_key, in_keylen))
return -EINVAL;
- key_len = xts_key_len / 2;
-
- _free_kb_keybuf(&ctx->kb[0]);
- _free_kb_keybuf(&ctx->kb[1]);
- rc = _key_to_kb(&ctx->kb[0], in_key, key_len);
- if (rc)
- return rc;
- rc = _key_to_kb(&ctx->kb[1], in_key + key_len, key_len);
+ _free_kb_keybuf(&ctx->kb);
+ rc = _xts_key_to_kb(&ctx->kb, in_key, in_keylen);
if (rc)
return rc;
@@ -478,6 +567,13 @@ static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
return rc;
/*
+ * It is not possible on a single protected key (e.g. full AES-XTS) to
+ * check, if k1 and k2 are the same.
+ */
+ if (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128 ||
+ ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_256)
+ return 0;
+ /*
* xts_verify_key verifies the key length is not odd and makes
* sure that the two keys are not the same. This can be done
* on the two protected keys as well
@@ -489,28 +585,82 @@ static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
return xts_verify_key(tfm, ckey, 2*ckey_len);
}
-static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier)
+static int paes_xts_crypt_full(struct skcipher_request *req,
+ unsigned long modifier)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
+ unsigned int keylen, offset, nbytes, n, k;
+ struct {
+ u8 key[64];
+ u8 tweak[16];
+ u8 nap[16];
+ u8 wkvp[32];
+ } fxts_param = {
+ .nap = {0},
+ };
struct skcipher_walk walk;
+ int rc;
+
+ rc = skcipher_walk_virt(&walk, req, false);
+ if (rc)
+ return rc;
+
+ keylen = (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128) ? 32 : 64;
+ offset = (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128) ? 32 : 0;
+
+ spin_lock_bh(&ctx->pk_lock);
+ memcpy(fxts_param.key + offset, ctx->pk[0].protkey, keylen);
+ memcpy(fxts_param.wkvp, ctx->pk[0].protkey + keylen,
+ sizeof(fxts_param.wkvp));
+ spin_unlock_bh(&ctx->pk_lock);
+ memcpy(fxts_param.tweak, walk.iv, sizeof(fxts_param.tweak));
+ fxts_param.nap[0] = 0x01; /* initial alpha power (1, little-endian) */
+
+ while ((nbytes = walk.nbytes) != 0) {
+ /* only use complete blocks */
+ n = nbytes & ~(AES_BLOCK_SIZE - 1);
+ k = cpacf_km(ctx->fc | modifier, fxts_param.key + offset,
+ walk.dst.virt.addr, walk.src.virt.addr, n);
+ if (k)
+ rc = skcipher_walk_done(&walk, nbytes - k);
+ if (k < n) {
+ if (__xts_paes_convert_key(ctx))
+ return skcipher_walk_done(&walk, -EIO);
+ spin_lock_bh(&ctx->pk_lock);
+ memcpy(fxts_param.key + offset, ctx->pk[0].protkey,
+ keylen);
+ memcpy(fxts_param.wkvp, ctx->pk[0].protkey + keylen,
+ sizeof(fxts_param.wkvp));
+ spin_unlock_bh(&ctx->pk_lock);
+ }
+ }
+
+ return rc;
+}
+
+static int paes_xts_crypt(struct skcipher_request *req, unsigned long modifier)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
unsigned int keylen, offset, nbytes, n, k;
- int ret;
struct {
- u8 key[MAXPROTKEYSIZE]; /* key + verification pattern */
+ u8 key[PAES_256_PROTKEY_SIZE];
u8 tweak[16];
u8 block[16];
u8 bit[16];
u8 xts[16];
} pcc_param;
struct {
- u8 key[MAXPROTKEYSIZE]; /* key + verification pattern */
+ u8 key[PAES_256_PROTKEY_SIZE];
u8 init[16];
} xts_param;
+ struct skcipher_walk walk;
+ int rc;
- ret = skcipher_walk_virt(&walk, req, false);
- if (ret)
- return ret;
+ rc = skcipher_walk_virt(&walk, req, false);
+ if (rc)
+ return rc;
keylen = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 48 : 64;
offset = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 16 : 0;
@@ -530,7 +680,7 @@ static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier)
k = cpacf_km(ctx->fc | modifier, xts_param.key + offset,
walk.dst.virt.addr, walk.src.virt.addr, n);
if (k)
- ret = skcipher_walk_done(&walk, nbytes - k);
+ rc = skcipher_walk_done(&walk, nbytes - k);
if (k < n) {
if (__xts_paes_convert_key(ctx))
return skcipher_walk_done(&walk, -EIO);
@@ -541,7 +691,24 @@ static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier)
}
}
- return ret;
+ return rc;
+}
+
+static inline int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+ switch (ctx->fc) {
+ case CPACF_KM_PXTS_128:
+ case CPACF_KM_PXTS_256:
+ return paes_xts_crypt(req, modifier);
+ case CPACF_KM_PXTS_128_FULL:
+ case CPACF_KM_PXTS_256_FULL:
+ return paes_xts_crypt_full(req, modifier);
+ default:
+ return -EINVAL;
+ }
}
static int xts_paes_encrypt(struct skcipher_request *req)
@@ -591,8 +758,8 @@ static void ctr_paes_exit(struct crypto_skcipher *tfm)
static inline int __ctr_paes_set_key(struct s390_paes_ctx *ctx)
{
- int rc;
unsigned long fc;
+ int rc;
rc = __paes_convert_key(ctx);
if (rc)
@@ -613,8 +780,8 @@ static inline int __ctr_paes_set_key(struct s390_paes_ctx *ctx)
static int ctr_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
unsigned int key_len)
{
- int rc;
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
+ int rc;
_free_kb_keybuf(&ctx->kb);
rc = _key_to_kb(&ctx->kb, in_key, key_len);
@@ -644,19 +811,19 @@ static int ctr_paes_crypt(struct skcipher_request *req)
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
u8 buf[AES_BLOCK_SIZE], *ctrptr;
- struct skcipher_walk walk;
- unsigned int nbytes, n, k;
- int ret, locked;
struct {
- u8 key[MAXPROTKEYSIZE];
+ u8 key[PAES_256_PROTKEY_SIZE];
} param;
+ struct skcipher_walk walk;
+ unsigned int nbytes, n, k;
+ int rc, locked;
- ret = skcipher_walk_virt(&walk, req, false);
- if (ret)
- return ret;
+ rc = skcipher_walk_virt(&walk, req, false);
+ if (rc)
+ return rc;
spin_lock_bh(&ctx->pk_lock);
- memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+ memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE);
spin_unlock_bh(&ctx->pk_lock);
locked = mutex_trylock(&ctrblk_lock);
@@ -673,7 +840,7 @@ static int ctr_paes_crypt(struct skcipher_request *req)
memcpy(walk.iv, ctrptr + k - AES_BLOCK_SIZE,
AES_BLOCK_SIZE);
crypto_inc(walk.iv, AES_BLOCK_SIZE);
- ret = skcipher_walk_done(&walk, nbytes - k);
+ rc = skcipher_walk_done(&walk, nbytes - k);
}
if (k < n) {
if (__paes_convert_key(ctx)) {
@@ -682,7 +849,7 @@ static int ctr_paes_crypt(struct skcipher_request *req)
return skcipher_walk_done(&walk, -EIO);
}
spin_lock_bh(&ctx->pk_lock);
- memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+ memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE);
spin_unlock_bh(&ctx->pk_lock);
}
}
@@ -702,15 +869,15 @@ static int ctr_paes_crypt(struct skcipher_request *req)
if (__paes_convert_key(ctx))
return skcipher_walk_done(&walk, -EIO);
spin_lock_bh(&ctx->pk_lock);
- memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+ memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE);
spin_unlock_bh(&ctx->pk_lock);
}
memcpy(walk.dst.virt.addr, buf, nbytes);
crypto_inc(walk.iv, AES_BLOCK_SIZE);
- ret = skcipher_walk_done(&walk, nbytes);
+ rc = skcipher_walk_done(&walk, nbytes);
}
- return ret;
+ return rc;
}
static struct skcipher_alg ctr_paes_alg = {
@@ -750,7 +917,7 @@ static void paes_s390_fini(void)
static int __init paes_s390_init(void)
{
- int ret;
+ int rc;
/* Query available functions for KM, KMC and KMCTR */
cpacf_query(CPACF_KM, &km_functions);
@@ -760,23 +927,23 @@ static int __init paes_s390_init(void)
if (cpacf_test_func(&km_functions, CPACF_KM_PAES_128) ||
cpacf_test_func(&km_functions, CPACF_KM_PAES_192) ||
cpacf_test_func(&km_functions, CPACF_KM_PAES_256)) {
- ret = crypto_register_skcipher(&ecb_paes_alg);
- if (ret)
+ rc = crypto_register_skcipher(&ecb_paes_alg);
+ if (rc)
goto out_err;
}
if (cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) ||
cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) ||
cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) {
- ret = crypto_register_skcipher(&cbc_paes_alg);
- if (ret)
+ rc = crypto_register_skcipher(&cbc_paes_alg);
+ if (rc)
goto out_err;
}
if (cpacf_test_func(&km_functions, CPACF_KM_PXTS_128) ||
cpacf_test_func(&km_functions, CPACF_KM_PXTS_256)) {
- ret = crypto_register_skcipher(&xts_paes_alg);
- if (ret)
+ rc = crypto_register_skcipher(&xts_paes_alg);
+ if (rc)
goto out_err;
}
@@ -785,18 +952,18 @@ static int __init paes_s390_init(void)
cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_256)) {
ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
if (!ctrblk) {
- ret = -ENOMEM;
+ rc = -ENOMEM;
goto out_err;
}
- ret = crypto_register_skcipher(&ctr_paes_alg);
- if (ret)
+ rc = crypto_register_skcipher(&ctr_paes_alg);
+ if (rc)
goto out_err;
}
return 0;
out_err:
paes_s390_fini();
- return ret;
+ return rc;
}
module_init(paes_s390_init);
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index a077087bc6cc..2becd77df741 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -679,7 +679,7 @@ static ssize_t prng_chunksize_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
+ return sysfs_emit(buf, "%u\n", prng_chunk_size);
}
static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL);
@@ -698,7 +698,7 @@ static ssize_t prng_counter_show(struct device *dev,
counter = prng_data->prngws.byte_counter;
mutex_unlock(&prng_data->mutex);
- return scnprintf(buf, PAGE_SIZE, "%llu\n", counter);
+ return sysfs_emit(buf, "%llu\n", counter);
}
static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL);
@@ -707,7 +707,7 @@ static ssize_t prng_errorflag_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
+ return sysfs_emit(buf, "%d\n", prng_errorflag);
}
static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL);
@@ -717,9 +717,9 @@ static ssize_t prng_mode_show(struct device *dev,
char *buf)
{
if (prng_mode == PRNG_MODE_TDES)
- return scnprintf(buf, PAGE_SIZE, "TDES\n");
+ return sysfs_emit(buf, "TDES\n");
else
- return scnprintf(buf, PAGE_SIZE, "SHA512\n");
+ return sysfs_emit(buf, "SHA512\n");
}
static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
@@ -742,7 +742,7 @@ static ssize_t prng_reseed_limit_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
+ return sysfs_emit(buf, "%u\n", prng_reseed_limit);
}
static ssize_t prng_reseed_limit_store(struct device *dev,
struct device_attribute *attr,
@@ -773,7 +773,7 @@ static ssize_t prng_strength_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "256\n");
+ return sysfs_emit(buf, "256\n");
}
static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL);
diff --git a/arch/s390/include/asm/asm.h b/arch/s390/include/asm/asm.h
new file mode 100644
index 000000000000..ec011b94af2a
--- /dev/null
+++ b/arch/s390/include/asm/asm.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_S390_ASM_H
+#define _ASM_S390_ASM_H
+
+#include <linux/stringify.h>
+
+/*
+ * Helper macros to be used for flag output operand handling.
+ * Inline assemblies must use four of the five supplied macros:
+ *
+ * Use CC_IPM(sym) at the end of the inline assembly; this extracts the
+ * condition code and program mask with the ipm instruction and writes it to
+ * the variable with symbolic name [sym] if the compiler has no support for
+ * flag output operands. If the compiler has support for flag output operands
+ * this generates no code.
+ *
+ * Use CC_OUT(sym, var) at the output operand list of an inline assembly. This
+ * defines an output operand with symbolic name [sym] for the variable
+ * [var]. [var] must be an int variable and [sym] must be identical with [sym]
+ * used with CC_IPM().
+ *
+ * Use either CC_CLOBBER or CC_CLOBBER_LIST() for the clobber list. Use
+ * CC_CLOBBER if the clobber list contains only "cc", otherwise use
+ * CC_CLOBBER_LIST() and add all clobbers as argument to the macro.
+ *
+ * Use CC_TRANSFORM() to convert the variable [var] which contains the
+ * extracted condition code. If the condition code is extracted with ipm, the
+ * [var] also contains the program mask. CC_TRANSFORM() moves the condition
+ * code to the two least significant bits and sets all other bits to zero.
+ */
+#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_GCC_ASM_FLAG_OUTPUT_BROKEN))
+
+#define __HAVE_ASM_FLAG_OUTPUTS__
+
+#define CC_IPM(sym)
+#define CC_OUT(sym, var) "=@cc" (var)
+#define CC_TRANSFORM(cc) ({ cc; })
+#define CC_CLOBBER
+#define CC_CLOBBER_LIST(...) __VA_ARGS__
+
+#else
+
+#define CC_IPM(sym) " ipm %[" __stringify(sym) "]\n"
+#define CC_OUT(sym, var) [sym] "=d" (var)
+#define CC_TRANSFORM(cc) ({ (cc) >> 28; })
+#define CC_CLOBBER "cc"
+#define CC_CLOBBER_LIST(...) "cc", __VA_ARGS__
+
+#endif
+
+#endif /* _ASM_S390_ASM_H */
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index 0c4cad7d5a5b..6723fca64018 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -72,14 +72,24 @@ ATOMIC_OPS(xor)
#define arch_atomic_fetch_or arch_atomic_fetch_or
#define arch_atomic_fetch_xor arch_atomic_fetch_xor
-#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new))
+static __always_inline int arch_atomic_xchg(atomic_t *v, int new)
+{
+ return arch_xchg(&v->counter, new);
+}
+#define arch_atomic_xchg arch_atomic_xchg
static __always_inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new)
{
- return __atomic_cmpxchg(&v->counter, old, new);
+ return arch_cmpxchg(&v->counter, old, new);
}
#define arch_atomic_cmpxchg arch_atomic_cmpxchg
+static __always_inline bool arch_atomic_try_cmpxchg(atomic_t *v, int *old, int new)
+{
+ return arch_try_cmpxchg(&v->counter, old, new);
+}
+#define arch_atomic_try_cmpxchg arch_atomic_try_cmpxchg
+
#define ATOMIC64_INIT(i) { (i) }
static __always_inline s64 arch_atomic64_read(const atomic64_t *v)
@@ -112,14 +122,24 @@ static __always_inline void arch_atomic64_add(s64 i, atomic64_t *v)
}
#define arch_atomic64_add arch_atomic64_add
-#define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), new))
+static __always_inline s64 arch_atomic64_xchg(atomic64_t *v, s64 new)
+{
+ return arch_xchg(&v->counter, new);
+}
+#define arch_atomic64_xchg arch_atomic64_xchg
static __always_inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)
{
- return __atomic64_cmpxchg((long *)&v->counter, old, new);
+ return arch_cmpxchg(&v->counter, old, new);
}
#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg
+static __always_inline bool arch_atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)
+{
+ return arch_try_cmpxchg(&v->counter, old, new);
+}
+#define arch_atomic64_try_cmpxchg arch_atomic64_try_cmpxchg
+
#define ATOMIC64_OPS(op) \
static __always_inline void arch_atomic64_##op(s64 i, atomic64_t *v) \
{ \
diff --git a/arch/s390/include/asm/atomic_ops.h b/arch/s390/include/asm/atomic_ops.h
index 65380da9e75f..1d6b2056fad8 100644
--- a/arch/s390/include/asm/atomic_ops.h
+++ b/arch/s390/include/asm/atomic_ops.h
@@ -169,79 +169,4 @@ __ATOMIC64_OPS(__atomic64_xor, "xgr")
#endif /* MARCH_HAS_Z196_FEATURES */
-static __always_inline int __atomic_cmpxchg(int *ptr, int old, int new)
-{
- asm volatile(
- " cs %[old],%[new],%[ptr]"
- : [old] "+d" (old), [ptr] "+Q" (*ptr)
- : [new] "d" (new)
- : "cc", "memory");
- return old;
-}
-
-static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new)
-{
- asm volatile(
- " csg %[old],%[new],%[ptr]"
- : [old] "+d" (old), [ptr] "+QS" (*ptr)
- : [new] "d" (new)
- : "cc", "memory");
- return old;
-}
-
-/* GCC versions before 14.2.0 may die with an ICE in some configurations. */
-#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_IS_GCC) && (GCC_VERSION < 140200))
-
-static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new)
-{
- int cc;
-
- asm volatile(
- " cs %[old],%[new],%[ptr]"
- : [old] "+d" (old), [ptr] "+Q" (*ptr), "=@cc" (cc)
- : [new] "d" (new)
- : "memory");
- return cc == 0;
-}
-
-static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new)
-{
- int cc;
-
- asm volatile(
- " csg %[old],%[new],%[ptr]"
- : [old] "+d" (old), [ptr] "+QS" (*ptr), "=@cc" (cc)
- : [new] "d" (new)
- : "memory");
- return cc == 0;
-}
-
-#else /* __GCC_ASM_FLAG_OUTPUTS__ */
-
-static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new)
-{
- int old_expected = old;
-
- asm volatile(
- " cs %[old],%[new],%[ptr]"
- : [old] "+d" (old), [ptr] "+Q" (*ptr)
- : [new] "d" (new)
- : "cc", "memory");
- return old == old_expected;
-}
-
-static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new)
-{
- long old_expected = old;
-
- asm volatile(
- " csg %[old],%[new],%[ptr]"
- : [old] "+d" (old), [ptr] "+QS" (*ptr)
- : [new] "d" (new)
- : "cc", "memory");
- return old == old_expected;
-}
-
-#endif /* __GCC_ASM_FLAG_OUTPUTS__ */
-
#endif /* __ARCH_S390_ATOMIC_OPS__ */
diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h
index aae0315374de..a9e2006033b7 100644
--- a/arch/s390/include/asm/cmpxchg.h
+++ b/arch/s390/include/asm/cmpxchg.h
@@ -11,185 +11,231 @@
#include <linux/mmdebug.h>
#include <linux/types.h>
#include <linux/bug.h>
+#include <asm/asm.h>
-void __xchg_called_with_bad_pointer(void);
+void __cmpxchg_called_with_bad_pointer(void);
+
+static __always_inline u32 __cs_asm(u64 ptr, u32 old, u32 new)
+{
+ asm volatile(
+ " cs %[old],%[new],%[ptr]\n"
+ : [old] "+d" (old), [ptr] "+Q" (*(u32 *)ptr)
+ : [new] "d" (new)
+ : "memory", "cc");
+ return old;
+}
+
+static __always_inline u64 __csg_asm(u64 ptr, u64 old, u64 new)
+{
+ asm volatile(
+ " csg %[old],%[new],%[ptr]\n"
+ : [old] "+d" (old), [ptr] "+QS" (*(u64 *)ptr)
+ : [new] "d" (new)
+ : "memory", "cc");
+ return old;
+}
-static __always_inline unsigned long
-__arch_xchg(unsigned long x, unsigned long address, int size)
+static inline u8 __arch_cmpxchg1(u64 ptr, u8 old, u8 new)
{
- unsigned long old;
- int shift;
+ union {
+ u8 b[4];
+ u32 w;
+ } old32, new32;
+ u32 prev;
+ int i;
+
+ i = ptr & 3;
+ ptr &= ~0x3;
+ prev = READ_ONCE(*(u32 *)ptr);
+ do {
+ old32.w = prev;
+ if (old32.b[i] != old)
+ return old32.b[i];
+ new32.w = old32.w;
+ new32.b[i] = new;
+ prev = __cs_asm(ptr, old32.w, new32.w);
+ } while (prev != old32.w);
+ return old;
+}
+
+static inline u16 __arch_cmpxchg2(u64 ptr, u16 old, u16 new)
+{
+ union {
+ u16 b[2];
+ u32 w;
+ } old32, new32;
+ u32 prev;
+ int i;
+
+ i = (ptr & 3) >> 1;
+ ptr &= ~0x3;
+ prev = READ_ONCE(*(u32 *)ptr);
+ do {
+ old32.w = prev;
+ if (old32.b[i] != old)
+ return old32.b[i];
+ new32.w = old32.w;
+ new32.b[i] = new;
+ prev = __cs_asm(ptr, old32.w, new32.w);
+ } while (prev != old32.w);
+ return old;
+}
+static __always_inline u64 __arch_cmpxchg(u64 ptr, u64 old, u64 new, int size)
+{
switch (size) {
- case 1:
- shift = (3 ^ (address & 3)) << 3;
- address ^= address & 3;
- asm volatile(
- " l %0,%1\n"
- "0: lr 0,%0\n"
- " nr 0,%3\n"
- " or 0,%2\n"
- " cs %0,0,%1\n"
- " jl 0b\n"
- : "=&d" (old), "+Q" (*(int *) address)
- : "d" ((x & 0xff) << shift), "d" (~(0xff << shift))
- : "memory", "cc", "0");
- return old >> shift;
- case 2:
- shift = (2 ^ (address & 2)) << 3;
- address ^= address & 2;
- asm volatile(
- " l %0,%1\n"
- "0: lr 0,%0\n"
- " nr 0,%3\n"
- " or 0,%2\n"
- " cs %0,0,%1\n"
- " jl 0b\n"
- : "=&d" (old), "+Q" (*(int *) address)
- : "d" ((x & 0xffff) << shift), "d" (~(0xffff << shift))
- : "memory", "cc", "0");
- return old >> shift;
- case 4:
- asm volatile(
- " l %0,%1\n"
- "0: cs %0,%2,%1\n"
- " jl 0b\n"
- : "=&d" (old), "+Q" (*(int *) address)
- : "d" (x)
- : "memory", "cc");
- return old;
- case 8:
- asm volatile(
- " lg %0,%1\n"
- "0: csg %0,%2,%1\n"
- " jl 0b\n"
- : "=&d" (old), "+QS" (*(long *) address)
- : "d" (x)
- : "memory", "cc");
- return old;
+ case 1: return __arch_cmpxchg1(ptr, old & 0xff, new & 0xff);
+ case 2: return __arch_cmpxchg2(ptr, old & 0xffff, new & 0xffff);
+ case 4: return __cs_asm(ptr, old & 0xffffffff, new & 0xffffffff);
+ case 8: return __csg_asm(ptr, old, new);
+ default: __cmpxchg_called_with_bad_pointer();
}
- __xchg_called_with_bad_pointer();
- return x;
+ return old;
}
-#define arch_xchg(ptr, x) \
+#define arch_cmpxchg(ptr, o, n) \
({ \
- __typeof__(*(ptr)) __ret; \
+ (__typeof__(*(ptr)))__arch_cmpxchg((unsigned long)(ptr), \
+ (unsigned long)(o), \
+ (unsigned long)(n), \
+ sizeof(*(ptr))); \
+})
+
+#define arch_cmpxchg64 arch_cmpxchg
+#define arch_cmpxchg_local arch_cmpxchg
+#define arch_cmpxchg64_local arch_cmpxchg
+
+#ifdef __HAVE_ASM_FLAG_OUTPUTS__
+
+#define arch_try_cmpxchg(ptr, oldp, new) \
+({ \
+ __typeof__(ptr) __oldp = (__typeof__(ptr))(oldp); \
+ __typeof__(*(ptr)) __old = *__oldp; \
+ __typeof__(*(ptr)) __new = (new); \
+ __typeof__(*(ptr)) __prev; \
+ int __cc; \
\
- __ret = (__typeof__(*(ptr))) \
- __arch_xchg((unsigned long)(x), (unsigned long)(ptr), \
- sizeof(*(ptr))); \
- __ret; \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+ case 2: { \
+ __prev = arch_cmpxchg((ptr), (__old), (__new)); \
+ __cc = (__prev != __old); \
+ if (unlikely(__cc)) \
+ *__oldp = __prev; \
+ break; \
+ } \
+ case 4: { \
+ asm volatile( \
+ " cs %[__old],%[__new],%[__ptr]\n" \
+ : [__old] "+d" (*__oldp), \
+ [__ptr] "+Q" (*(ptr)), \
+ "=@cc" (__cc) \
+ : [__new] "d" (__new) \
+ : "memory"); \
+ break; \
+ } \
+ case 8: { \
+ asm volatile( \
+ " csg %[__old],%[__new],%[__ptr]\n" \
+ : [__old] "+d" (*__oldp), \
+ [__ptr] "+QS" (*(ptr)), \
+ "=@cc" (__cc) \
+ : [__new] "d" (__new) \
+ : "memory"); \
+ break; \
+ } \
+ default: \
+ __cmpxchg_called_with_bad_pointer(); \
+ } \
+ likely(__cc == 0); \
})
-void __cmpxchg_called_with_bad_pointer(void);
+#else /* __HAVE_ASM_FLAG_OUTPUTS__ */
-static __always_inline unsigned long __cmpxchg(unsigned long address,
- unsigned long old,
- unsigned long new, int size)
+#define arch_try_cmpxchg(ptr, oldp, new) \
+({ \
+ __typeof__((ptr)) __oldp = (__typeof__(ptr))(oldp); \
+ __typeof__(*(ptr)) __old = *__oldp; \
+ __typeof__(*(ptr)) __new = (new); \
+ __typeof__(*(ptr)) __prev; \
+ \
+ __prev = arch_cmpxchg((ptr), (__old), (__new)); \
+ if (unlikely(__prev != __old)) \
+ *__oldp = __prev; \
+ likely(__prev == __old); \
+})
+
+#endif /* __HAVE_ASM_FLAG_OUTPUTS__ */
+
+#define arch_try_cmpxchg64 arch_try_cmpxchg
+#define arch_try_cmpxchg_local arch_try_cmpxchg
+#define arch_try_cmpxchg64_local arch_try_cmpxchg
+
+void __xchg_called_with_bad_pointer(void);
+
+static inline u8 __arch_xchg1(u64 ptr, u8 x)
+{
+ int shift = (3 ^ (ptr & 3)) << 3;
+ u32 mask, old, new;
+
+ ptr &= ~0x3;
+ mask = ~(0xff << shift);
+ old = READ_ONCE(*(u32 *)ptr);
+ do {
+ new = old & mask;
+ new |= x << shift;
+ } while (!arch_try_cmpxchg((u32 *)ptr, &old, new));
+ return old >> shift;
+}
+
+static inline u16 __arch_xchg2(u64 ptr, u16 x)
+{
+ int shift = (2 ^ (ptr & 2)) << 3;
+ u32 mask, old, new;
+
+ ptr &= ~0x3;
+ mask = ~(0xffff << shift);
+ old = READ_ONCE(*(u32 *)ptr);
+ do {
+ new = old & mask;
+ new |= x << shift;
+ } while (!arch_try_cmpxchg((u32 *)ptr, &old, new));
+ return old >> shift;
+}
+
+static __always_inline u64 __arch_xchg(u64 ptr, u64 x, int size)
{
switch (size) {
- case 1: {
- unsigned int prev, shift, mask;
-
- shift = (3 ^ (address & 3)) << 3;
- address ^= address & 3;
- old = (old & 0xff) << shift;
- new = (new & 0xff) << shift;
- mask = ~(0xff << shift);
- asm volatile(
- " l %[prev],%[address]\n"
- " nr %[prev],%[mask]\n"
- " xilf %[mask],0xffffffff\n"
- " or %[new],%[prev]\n"
- " or %[prev],%[tmp]\n"
- "0: lr %[tmp],%[prev]\n"
- " cs %[prev],%[new],%[address]\n"
- " jnl 1f\n"
- " xr %[tmp],%[prev]\n"
- " xr %[new],%[tmp]\n"
- " nr %[tmp],%[mask]\n"
- " jz 0b\n"
- "1:"
- : [prev] "=&d" (prev),
- [address] "+Q" (*(int *)address),
- [tmp] "+&d" (old),
- [new] "+&d" (new),
- [mask] "+&d" (mask)
- :: "memory", "cc");
- return prev >> shift;
- }
- case 2: {
- unsigned int prev, shift, mask;
-
- shift = (2 ^ (address & 2)) << 3;
- address ^= address & 2;
- old = (old & 0xffff) << shift;
- new = (new & 0xffff) << shift;
- mask = ~(0xffff << shift);
- asm volatile(
- " l %[prev],%[address]\n"
- " nr %[prev],%[mask]\n"
- " xilf %[mask],0xffffffff\n"
- " or %[new],%[prev]\n"
- " or %[prev],%[tmp]\n"
- "0: lr %[tmp],%[prev]\n"
- " cs %[prev],%[new],%[address]\n"
- " jnl 1f\n"
- " xr %[tmp],%[prev]\n"
- " xr %[new],%[tmp]\n"
- " nr %[tmp],%[mask]\n"
- " jz 0b\n"
- "1:"
- : [prev] "=&d" (prev),
- [address] "+Q" (*(int *)address),
- [tmp] "+&d" (old),
- [new] "+&d" (new),
- [mask] "+&d" (mask)
- :: "memory", "cc");
- return prev >> shift;
- }
+ case 1:
+ return __arch_xchg1(ptr, x & 0xff);
+ case 2:
+ return __arch_xchg2(ptr, x & 0xffff);
case 4: {
- unsigned int prev = old;
-
- asm volatile(
- " cs %[prev],%[new],%[address]\n"
- : [prev] "+&d" (prev),
- [address] "+Q" (*(int *)address)
- : [new] "d" (new)
- : "memory", "cc");
- return prev;
+ u32 old = READ_ONCE(*(u32 *)ptr);
+
+ do {
+ } while (!arch_try_cmpxchg((u32 *)ptr, &old, x & 0xffffffff));
+ return old;
}
case 8: {
- unsigned long prev = old;
-
- asm volatile(
- " csg %[prev],%[new],%[address]\n"
- : [prev] "+&d" (prev),
- [address] "+QS" (*(long *)address)
- : [new] "d" (new)
- : "memory", "cc");
- return prev;
+ u64 old = READ_ONCE(*(u64 *)ptr);
+
+ do {
+ } while (!arch_try_cmpxchg((u64 *)ptr, &old, x));
+ return old;
}
}
- __cmpxchg_called_with_bad_pointer();
- return old;
+ __xchg_called_with_bad_pointer();
+ return x;
}
-#define arch_cmpxchg(ptr, o, n) \
+#define arch_xchg(ptr, x) \
({ \
- __typeof__(*(ptr)) __ret; \
- \
- __ret = (__typeof__(*(ptr))) \
- __cmpxchg((unsigned long)(ptr), (unsigned long)(o), \
- (unsigned long)(n), sizeof(*(ptr))); \
- __ret; \
+ (__typeof__(*(ptr)))__arch_xchg((unsigned long)(ptr), \
+ (unsigned long)(x), \
+ sizeof(*(ptr))); \
})
-#define arch_cmpxchg64 arch_cmpxchg
-#define arch_cmpxchg_local arch_cmpxchg
-#define arch_cmpxchg64_local arch_cmpxchg
-
#define system_has_cmpxchg128() 1
static __always_inline u128 arch_cmpxchg128(volatile u128 *ptr, u128 old, u128 new)
@@ -203,5 +249,25 @@ static __always_inline u128 arch_cmpxchg128(volatile u128 *ptr, u128 old, u128 n
}
#define arch_cmpxchg128 arch_cmpxchg128
+#define arch_cmpxchg128_local arch_cmpxchg128
+
+#ifdef __HAVE_ASM_FLAG_OUTPUTS__
+
+static __always_inline bool arch_try_cmpxchg128(volatile u128 *ptr, u128 *oldp, u128 new)
+{
+ int cc;
+
+ asm volatile(
+ " cdsg %[old],%[new],%[ptr]\n"
+ : [old] "+d" (*oldp), [ptr] "+QS" (*ptr), "=@cc" (cc)
+ : [new] "d" (new)
+ : "memory");
+ return likely(cc == 0);
+}
+
+#define arch_try_cmpxchg128 arch_try_cmpxchg128
+#define arch_try_cmpxchg128_local arch_try_cmpxchg128
+
+#endif /* __HAVE_ASM_FLAG_OUTPUTS__ */
#endif /* __ASM_CMPXCHG_H */
diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h
index 1d3a4b0c650f..59ab1192e2d5 100644
--- a/arch/s390/include/asm/cpacf.h
+++ b/arch/s390/include/asm/cpacf.h
@@ -56,6 +56,8 @@
#define CPACF_KM_PXTS_256 0x3c
#define CPACF_KM_XTS_128_FULL 0x52
#define CPACF_KM_XTS_256_FULL 0x54
+#define CPACF_KM_PXTS_128_FULL 0x5a
+#define CPACF_KM_PXTS_256_FULL 0x5c
/*
* Function codes for the KMC (CIPHER MESSAGE WITH CHAINING)
diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h
index 9e4bbc3e53f8..e1a279e0d6a6 100644
--- a/arch/s390/include/asm/cpu_mf.h
+++ b/arch/s390/include/asm/cpu_mf.h
@@ -13,6 +13,7 @@
#include <linux/kmsan-checks.h>
#include <asm/asm-extable.h>
#include <asm/facility.h>
+#include <asm/asm.h>
asm(".include \"asm/cpu_mf-insn.h\"\n");
@@ -185,11 +186,12 @@ static inline int lcctl(u64 ctl)
int cc;
asm volatile (
- " lcctl %1\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc) : "Q" (ctl) : "cc");
- return cc;
+ " lcctl %[ctl]\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
+ : [ctl] "Q" (ctl)
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc);
}
/* Extract CPU counter */
@@ -199,12 +201,13 @@ static inline int __ecctr(u64 ctr, u64 *content)
int cc;
asm volatile (
- " ecctr %0,%2\n"
- " ipm %1\n"
- " srl %1,28\n"
- : "=d" (_content), "=d" (cc) : "d" (ctr) : "cc");
+ " ecctr %[_content],%[ctr]\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [_content] "=d" (_content)
+ : [ctr] "d" (ctr)
+ : CC_CLOBBER);
*content = _content;
- return cc;
+ return CC_TRANSFORM(cc);
}
/* Extract CPU counter */
@@ -234,18 +237,17 @@ static __always_inline int stcctm(enum stcctm_ctr_set set, u64 range, u64 *dest)
int cc;
asm volatile (
- " STCCTM %2,%3,%1\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc)
- : "Q" (*dest), "d" (range), "i" (set)
- : "cc", "memory");
+ " STCCTM %[range],%[set],%[dest]\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
+ : [dest] "Q" (*dest), [range] "d" (range), [set] "i" (set)
+ : CC_CLOBBER_LIST("memory"));
/*
* If cc == 2, less than RANGE counters are stored, but it's not easy
* to tell how many. Always unpoison the whole range for simplicity.
*/
kmsan_unpoison_memory(dest, range * sizeof(u64));
- return cc;
+ return CC_TRANSFORM(cc);
}
/* Query sampling information */
@@ -265,19 +267,20 @@ static inline int qsi(struct hws_qsi_info_block *info)
/* Load sampling controls */
static inline int lsctl(struct hws_lsctl_request_block *req)
{
- int cc;
+ int cc, exception;
- cc = 1;
+ exception = 1;
asm volatile(
- "0: lsctl 0(%1)\n"
- "1: ipm %0\n"
- " srl %0,28\n"
+ "0: lsctl %[req]\n"
+ "1: lhi %[exc],0\n"
"2:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
- : "+d" (cc), "+a" (req)
- : "m" (*req)
- : "cc", "memory");
-
- return cc ? -EINVAL : 0;
+ : CC_OUT(cc, cc), [exc] "+d" (exception)
+ : [req] "Q" (*req)
+ : CC_CLOBBER);
+ if (exception || CC_TRANSFORM(cc))
+ return -EINVAL;
+ return 0;
}
#endif /* _ASM_S390_CPU_MF_H */
diff --git a/arch/s390/include/asm/debug.h b/arch/s390/include/asm/debug.h
index ccd4e148b5ed..a7f7bdc9e19c 100644
--- a/arch/s390/include/asm/debug.h
+++ b/arch/s390/include/asm/debug.h
@@ -66,14 +66,15 @@ typedef int (debug_header_proc_t) (debug_info_t *id,
struct debug_view *view,
int area,
debug_entry_t *entry,
- char *out_buf);
+ char *out_buf, size_t out_buf_size);
typedef int (debug_format_proc_t) (debug_info_t *id,
struct debug_view *view, char *out_buf,
+ size_t out_buf_size,
const char *in_buf);
typedef int (debug_prolog_proc_t) (debug_info_t *id,
struct debug_view *view,
- char *out_buf);
+ char *out_buf, size_t out_buf_size);
typedef int (debug_input_proc_t) (debug_info_t *id,
struct debug_view *view,
struct file *file,
@@ -81,7 +82,8 @@ typedef int (debug_input_proc_t) (debug_info_t *id,
size_t in_buf_size, loff_t *offset);
int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
- int area, debug_entry_t *entry, char *out_buf);
+ int area, debug_entry_t *entry,
+ char *out_buf, size_t out_buf_size);
struct debug_view {
char name[DEBUG_MAX_NAME_LEN];
diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h
index 715bcf8fb69a..5f5b1aa6c233 100644
--- a/arch/s390/include/asm/facility.h
+++ b/arch/s390/include/asm/facility.h
@@ -88,7 +88,7 @@ static __always_inline bool test_facility(unsigned long nr)
return __test_facility(nr, &stfle_fac_list);
}
-static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size)
+static inline unsigned long __stfle_asm(u64 *fac_list, int size)
{
unsigned long reg0 = size - 1;
@@ -96,7 +96,7 @@ static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size)
" lgr 0,%[reg0]\n"
" .insn s,0xb2b00000,%[list]\n" /* stfle */
" lgr %[reg0],0\n"
- : [reg0] "+&d" (reg0), [list] "+Q" (*stfle_fac_list)
+ : [reg0] "+&d" (reg0), [list] "+Q" (*fac_list)
:
: "memory", "cc", "0");
return reg0;
@@ -104,10 +104,10 @@ static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size)
/**
* stfle - Store facility list extended
- * @stfle_fac_list: array where facility list can be stored
+ * @fac_list: array where facility list can be stored
* @size: size of passed in array in double words
*/
-static inline void __stfle(u64 *stfle_fac_list, int size)
+static inline void __stfle(u64 *fac_list, int size)
{
unsigned long nr;
u32 stfl_fac_list;
@@ -116,20 +116,20 @@ static inline void __stfle(u64 *stfle_fac_list, int size)
" stfl 0(0)\n"
: "=m" (get_lowcore()->stfl_fac_list));
stfl_fac_list = get_lowcore()->stfl_fac_list;
- memcpy(stfle_fac_list, &stfl_fac_list, 4);
+ memcpy(fac_list, &stfl_fac_list, 4);
nr = 4; /* bytes stored by stfl */
if (stfl_fac_list & 0x01000000) {
/* More facility bits available with stfle */
- nr = __stfle_asm(stfle_fac_list, size);
+ nr = __stfle_asm(fac_list, size);
nr = min_t(unsigned long, (nr + 1) * 8, size * 8);
}
- memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
+ memset((char *)fac_list + nr, 0, size * 8 - nr);
}
-static inline void stfle(u64 *stfle_fac_list, int size)
+static inline void stfle(u64 *fac_list, int size)
{
preempt_disable();
- __stfle(stfle_fac_list, size);
+ __stfle(fac_list, size);
preempt_enable();
}
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h
index 406746666eb7..fc97d75dc752 100644
--- a/arch/s390/include/asm/ftrace.h
+++ b/arch/s390/include/asm/ftrace.h
@@ -51,13 +51,11 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
return addr;
}
-struct ftrace_regs {
- struct pt_regs regs;
-};
+#include <linux/ftrace_regs.h>
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
{
- struct pt_regs *regs = &fregs->regs;
+ struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
if (test_pt_regs_flag(regs, PIF_FTRACE_FULL_REGS))
return regs;
@@ -81,32 +79,13 @@ static __always_inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-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;
+ arch_ftrace_regs(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
@@ -117,7 +96,7 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
*/
static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
{
- struct pt_regs *regs = &fregs->regs;
+ struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
regs->orig_gpr2 = addr;
}
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h
index 9725586f4259..13f51a6a5bb1 100644
--- a/arch/s390/include/asm/gmap.h
+++ b/arch/s390/include/asm/gmap.h
@@ -17,8 +17,8 @@
#define GMAP_NOTIFY_MPROT 0x1
/* Status bits only for huge segment entries */
-#define _SEGMENT_ENTRY_GMAP_IN 0x8000 /* invalidation notify bit */
-#define _SEGMENT_ENTRY_GMAP_UC 0x4000 /* dirty (migration) */
+#define _SEGMENT_ENTRY_GMAP_IN 0x0800 /* invalidation notify bit */
+#define _SEGMENT_ENTRY_GMAP_UC 0x0002 /* dirty (migration) */
/**
* struct gmap_struct - guest address space
@@ -107,9 +107,6 @@ void gmap_remove(struct gmap *gmap);
struct gmap *gmap_get(struct gmap *gmap);
void gmap_put(struct gmap *gmap);
-void gmap_enable(struct gmap *gmap);
-void gmap_disable(struct gmap *gmap);
-struct gmap *gmap_get_enabled(void);
int gmap_map_segment(struct gmap *gmap, unsigned long from,
unsigned long to, unsigned long len);
int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index cf1b5d6fb1a6..a40664b236e9 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -10,41 +10,30 @@
#define _ASM_S390_HUGETLB_H
#include <linux/pgtable.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
#include <asm/page.h>
-#define hugetlb_free_pgd_range free_pgd_range
#define hugepages_supported() (MACHINE_HAS_EDAT1)
+#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte, unsigned long sz);
void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte);
-pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+#define __HAVE_ARCH_HUGE_PTEP_GET
+extern pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
+extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep);
-/*
- * If the arch doesn't supply something else, assume that hugepage
- * size aligned regions are ok without further preparation.
- */
-static inline int prepare_hugepage_range(struct file *file,
- unsigned long addr, unsigned long len)
-{
- struct hstate *h = hstate_file(file);
-
- if (len & ~huge_page_mask(h))
- return -EINVAL;
- if (addr & ~huge_page_mask(h))
- return -EINVAL;
- return 0;
-}
-
static inline void arch_clear_hugetlb_flags(struct folio *folio)
{
clear_bit(PG_arch_1, &folio->flags);
}
#define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
+#define __HAVE_ARCH_HUGE_PTE_CLEAR
static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, unsigned long sz)
{
@@ -54,12 +43,14 @@ static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
set_pte(ptep, __pte(_SEGMENT_ENTRY_EMPTY));
}
+#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep)
{
return huge_ptep_get_and_clear(vma->vm_mm, address, ptep);
}
+#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep,
pte_t pte, int dirty)
@@ -72,6 +63,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
return changed;
}
+#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
@@ -79,69 +71,36 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
__set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte));
}
-static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
-{
- return mk_pte(page, pgprot);
-}
-
+#define __HAVE_ARCH_HUGE_PTE_NONE
static inline int huge_pte_none(pte_t pte)
{
return pte_none(pte);
}
+#define __HAVE_ARCH_HUGE_PTE_NONE_MOSTLY
static inline int huge_pte_none_mostly(pte_t pte)
{
- return huge_pte_none(pte);
-}
-
-static inline int huge_pte_write(pte_t pte)
-{
- return pte_write(pte);
-}
-
-static inline int huge_pte_dirty(pte_t pte)
-{
- return pte_dirty(pte);
-}
-
-static inline pte_t huge_pte_mkwrite(pte_t pte)
-{
- return pte_mkwrite_novma(pte);
-}
-
-static inline pte_t huge_pte_mkdirty(pte_t pte)
-{
- return pte_mkdirty(pte);
-}
-
-static inline pte_t huge_pte_wrprotect(pte_t pte)
-{
- return pte_wrprotect(pte);
-}
-
-static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
-{
- return pte_modify(pte, newprot);
+ return huge_pte_none(pte) || is_pte_marker(pte);
}
+#define __HAVE_ARCH_HUGE_PTE_MKUFFD_WP
static inline pte_t huge_pte_mkuffd_wp(pte_t pte)
{
return pte;
}
+#define __HAVE_ARCH_HUGE_PTE_CLEAR_UFFD_WP
static inline pte_t huge_pte_clear_uffd_wp(pte_t pte)
{
return pte;
}
+#define __HAVE_ARCH_HUGE_PTE_UFFD_WP
static inline int huge_pte_uffd_wp(pte_t pte)
{
return 0;
}
-static inline bool gigantic_page_runtime_supported(void)
-{
- return true;
-}
+#include <asm-generic/hugetlb.h>
#endif /* _ASM_S390_HUGETLB_H */
diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h
index 1bd08eb56d5f..9084b750350d 100644
--- a/arch/s390/include/asm/kexec.h
+++ b/arch/s390/include/asm/kexec.h
@@ -94,6 +94,9 @@ void arch_kexec_protect_crashkres(void);
void arch_kexec_unprotect_crashkres(void);
#define arch_kexec_unprotect_crashkres arch_kexec_unprotect_crashkres
+
+bool is_kdump_kernel(void);
+#define is_kdump_kernel is_kdump_kernel
#endif
#ifdef CONFIG_KEXEC_FILE
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 8e77afbed58e..97c7c8127543 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -94,11 +94,16 @@ union ipte_control {
};
};
+/*
+ * Utility is defined as two bytes but having it four bytes wide
+ * generates more efficient code. Since the following bytes are
+ * reserved this makes no functional difference.
+ */
union sca_utility {
- __u16 val;
+ __u32 val;
struct {
- __u16 mtcr : 1;
- __u16 reserved : 15;
+ __u32 mtcr : 1;
+ __u32 : 31;
};
};
@@ -107,7 +112,7 @@ struct bsca_block {
__u64 reserved[5];
__u64 mcn;
union sca_utility utility;
- __u8 reserved2[6];
+ __u8 reserved2[4];
struct bsca_entry cpu[KVM_S390_BSCA_CPU_SLOTS];
};
@@ -115,7 +120,7 @@ struct esca_block {
union ipte_control ipte_control;
__u64 reserved1[6];
union sca_utility utility;
- __u8 reserved2[6];
+ __u8 reserved2[4];
__u64 mcn[4];
__u64 reserved3[20];
struct esca_entry cpu[KVM_S390_ESCA_CPU_SLOTS];
@@ -356,6 +361,7 @@ struct kvm_s390_sie_block {
#define ECD_MEF 0x08000000
#define ECD_ETOKENF 0x02000000
#define ECD_ECC 0x00200000
+#define ECD_HMAC 0x00004000
__u32 ecd; /* 0x01c8 */
__u8 reserved1cc[18]; /* 0x01cc */
__u64 pp; /* 0x01de */
@@ -527,6 +533,9 @@ struct kvm_vcpu_stat {
#define PGM_REGION_FIRST_TRANS 0x39
#define PGM_REGION_SECOND_TRANS 0x3a
#define PGM_REGION_THIRD_TRANS 0x3b
+#define PGM_SECURE_STORAGE_ACCESS 0x3d
+#define PGM_NON_SECURE_STORAGE_ACCESS 0x3e
+#define PGM_SECURE_STORAGE_VIOLATION 0x3f
#define PGM_MONITOR 0x40
#define PGM_PER 0x80
#define PGM_CRYPTO_OPERATION 0x119
@@ -747,8 +756,6 @@ struct kvm_vcpu_arch {
struct hrtimer ckc_timer;
struct kvm_s390_pgm_info pgm;
struct gmap *gmap;
- /* backup location for the currently enabled gmap when scheduled out */
- struct gmap *enabled_gmap;
struct kvm_guestdbg_info_arch guestdbg;
unsigned long pfault_token;
unsigned long pfault_select;
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 48c64716d1f2..42a092fa1029 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -165,8 +165,7 @@ struct lowcore {
__u64 percpu_offset; /* 0x03b8 */
__u8 pad_0x03c0[0x03c8-0x03c0]; /* 0x03c0 */
__u64 machine_flags; /* 0x03c8 */
- __u64 gmap; /* 0x03d0 */
- __u8 pad_0x03d8[0x0400-0x03d8]; /* 0x03d8 */
+ __u8 pad_0x03d0[0x0400-0x03d0]; /* 0x03d0 */
__u32 return_lpswe; /* 0x0400 */
__u32 return_mcck_lpswe; /* 0x0404 */
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index 73e1e03317b4..4f43cdd9835b 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -10,15 +10,10 @@
#include <linux/const.h>
#include <asm/types.h>
+#include <asm/asm.h>
-#define _PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define _PAGE_SIZE (_AC(1, UL) << _PAGE_SHIFT)
-#define _PAGE_MASK (~(_PAGE_SIZE - 1))
+#include <vdso/page.h>
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT _PAGE_SHIFT
-#define PAGE_SIZE _PAGE_SIZE
-#define PAGE_MASK _PAGE_MASK
#define PAGE_DEFAULT_ACC _AC(0, UL)
/* storage-protection override */
#define PAGE_SPO_ACC 9
@@ -74,7 +69,7 @@ static inline void copy_page(void *to, void *from)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
#define vma_alloc_zeroed_movable_folio(vma, vaddr) \
- vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr, false)
+ vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr)
/*
* These are used to make use of C type-checking..
@@ -148,11 +143,12 @@ static inline int page_reset_referenced(unsigned long addr)
int cc;
asm volatile(
- " rrbe 0,%1\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc) : "a" (addr) : "cc");
- return cc;
+ " rrbe 0,%[addr]\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
+ : [addr] "a" (addr)
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc);
}
/* Bits int the storage key */
@@ -245,9 +241,7 @@ static inline unsigned long __phys_addr(unsigned long x, bool is_31bit)
#define phys_to_pfn(phys) ((phys) >> PAGE_SHIFT)
#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
-#define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys))
#define phys_to_folio(phys) page_folio(phys_to_page(phys))
-#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
#define folio_to_phys(page) pfn_to_phys(folio_pfn(folio))
static inline void *pfn_to_virt(unsigned long pfn)
diff --git a/arch/s390/include/asm/pai.h b/arch/s390/include/asm/pai.h
index 25f2077ba3c9..ebeabd0aaa51 100644
--- a/arch/s390/include/asm/pai.h
+++ b/arch/s390/include/asm/pai.h
@@ -11,6 +11,7 @@
#include <linux/jump_label.h>
#include <asm/lowcore.h>
#include <asm/ptrace.h>
+#include <asm/asm.h>
struct qpaci_info_block {
u64 header;
@@ -33,12 +34,11 @@ static inline int qpaci(struct qpaci_info_block *info)
" lgr 0,%[size]\n"
" .insn s,0xb28f0000,%[info]\n"
" lgr %[size],0\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [info] "=Q" (*info), [size] "+&d" (size)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [info] "=Q" (*info), [size] "+&d" (size)
:
- : "0", "cc", "memory");
- return cc ? (size + 1) * sizeof(u64) : 0;
+ : CC_CLOBBER_LIST("0", "memory"));
+ return CC_TRANSFORM(cc) ? (size + 1) * sizeof(u64) : 0;
}
#define PAI_CRYPTO_BASE 0x1000 /* First event number */
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 9d920ced6047..474e1f8d1d3c 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -96,7 +96,6 @@ struct zpci_bar_struct {
u8 size; /* order 2 exponent */
};
-struct s390_domain;
struct kvm_zdev;
#define ZPCI_FUNCTIONS_PER_BUS 256
@@ -107,9 +106,10 @@ struct zpci_bus {
struct list_head resources;
struct list_head bus_next;
struct resource bus_resource;
- int pchid;
+ int topo; /* TID if topo_is_tid, PCHID otherwise */
int domain_nr;
- bool multifunction;
+ u8 multifunction : 1;
+ u8 topo_is_tid : 1;
enum pci_bus_speed max_bus_speed;
};
@@ -130,9 +130,12 @@ struct zpci_dev {
u16 vfn; /* virtual function number */
u16 pchid; /* physical channel ID */
u16 maxstbl; /* Maximum store block size */
+ u16 rid; /* RID as supplied by firmware */
+ u16 tid; /* Topology for which RID is valid */
u8 pfgid; /* function group ID */
u8 pft; /* pci function type */
u8 port;
+ u8 fidparm;
u8 dtsm; /* Supported DT mask */
u8 rid_available : 1;
u8 has_hp_slot : 1;
@@ -140,7 +143,8 @@ struct zpci_dev {
u8 is_physfn : 1;
u8 util_str_avail : 1;
u8 irqs_registered : 1;
- u8 reserved : 2;
+ u8 tid_avail : 1;
+ u8 reserved : 1;
unsigned int devfn; /* DEVFN part of the RID*/
u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */
@@ -181,9 +185,10 @@ struct zpci_dev {
struct dentry *debugfs_dev;
/* IOMMU and passthrough */
- struct s390_domain *s390_domain; /* s390 IOMMU domain data */
+ struct iommu_domain *s390_domain; /* attached IOMMU domain */
struct kvm_zdev *kzdev;
struct mutex kzdev_lock;
+ spinlock_t dom_lock; /* protect s390_domain change */
};
static inline bool zdev_enabled(struct zpci_dev *zdev)
@@ -210,12 +215,14 @@ extern struct airq_iv *zpci_aif_sbv;
----------------------------------------------------------------------------- */
/* Base stuff */
struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state);
+int zpci_add_device(struct zpci_dev *zdev);
int zpci_enable_device(struct zpci_dev *);
int zpci_disable_device(struct zpci_dev *);
int zpci_scan_configured_device(struct zpci_dev *zdev, u32 fh);
int zpci_deconfigure_device(struct zpci_dev *zdev);
void zpci_device_reserved(struct zpci_dev *zdev);
bool zpci_is_device_configured(struct zpci_dev *zdev);
+int zpci_scan_devices(void);
int zpci_hot_reset_device(struct zpci_dev *zdev);
int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64, u8 *);
@@ -225,7 +232,7 @@ void zpci_update_fh(struct zpci_dev *zdev, u32 fh);
/* CLP */
int clp_setup_writeback_mio(void);
-int clp_scan_pci_devices(void);
+int clp_scan_pci_devices(struct list_head *scan_list);
int clp_query_pci_fn(struct zpci_dev *zdev);
int clp_enable_fh(struct zpci_dev *zdev, u32 *fh, u8 nr_dma_as);
int clp_disable_fh(struct zpci_dev *zdev, u32 *fh);
diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h
index f0c677ddd270..3fff2f7095c8 100644
--- a/arch/s390/include/asm/pci_clp.h
+++ b/arch/s390/include/asm/pci_clp.h
@@ -110,7 +110,8 @@ struct clp_req_query_pci {
struct clp_rsp_query_pci {
struct clp_rsp_hdr hdr;
u16 vfn; /* virtual fn number */
- u16 : 3;
+ u16 : 2;
+ u16 tid_avail : 1;
u16 rid_avail : 1;
u16 is_physfn : 1;
u16 reserved1 : 1;
@@ -122,16 +123,18 @@ struct clp_rsp_query_pci {
u16 pchid;
__le32 bar[PCI_STD_NUM_BARS];
u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */
- u16 : 12;
- u16 port : 4;
+ u8 fidparm;
+ u8 reserved3 : 4;
+ u8 port : 4;
u8 fmb_len;
u8 pft; /* pci function type */
u64 sdma; /* start dma as */
u64 edma; /* end dma as */
#define ZPCI_RID_MASK_DEVFN 0x00ff
u16 rid; /* BUS/DEVFN PCI address */
- u16 reserved0;
- u32 reserved[10];
+ u32 reserved0;
+ u16 tid;
+ u32 reserved[9];
u32 uid; /* user defined id */
u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */
u32 reserved2[16];
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h
index 2686bee800e3..43a5ea4ee20f 100644
--- a/arch/s390/include/asm/pci_io.h
+++ b/arch/s390/include/asm/pci_io.h
@@ -143,7 +143,7 @@ static inline int zpci_get_max_io_size(u64 src, u64 dst, int len, int max)
static inline int zpci_memcpy_fromio(void *dst,
const volatile void __iomem *src,
- unsigned long n)
+ size_t n)
{
int size, rc = 0;
@@ -162,7 +162,7 @@ static inline int zpci_memcpy_fromio(void *dst,
}
static inline int zpci_memcpy_toio(volatile void __iomem *dst,
- const void *src, unsigned long n)
+ const void *src, size_t n)
{
int size, rc = 0;
@@ -187,7 +187,7 @@ static inline int zpci_memcpy_toio(volatile void __iomem *dst,
}
static inline int zpci_memset_io(volatile void __iomem *dst,
- unsigned char val, size_t count)
+ int val, size_t count)
{
u8 *src = kmalloc(count, GFP_KERNEL);
int rc;
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h
index 29ee289108c5..e53894cedf08 100644
--- a/arch/s390/include/asm/perf_event.h
+++ b/arch/s390/include/asm/perf_event.h
@@ -37,9 +37,9 @@ extern ssize_t cpumf_events_sysfs_show(struct device *dev,
/* Perf callbacks */
struct pt_regs;
-extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
-extern unsigned long perf_misc_flags(struct pt_regs *regs);
-#define perf_misc_flags(regs) perf_misc_flags(regs)
+extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs);
+extern unsigned long perf_arch_misc_flags(struct pt_regs *regs);
+#define perf_arch_misc_flags(regs) perf_arch_misc_flags(regs)
#define perf_arch_bpf_user_pt_regs(regs) &regs->user_regs
/* Perf pt_regs extension for sample-data-entry indicators */
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 0ffbaf741955..48268095b0a3 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -277,7 +277,8 @@ static inline int is_module_addr(void *addr)
#define _REGION1_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID)
#define _REGION2_ENTRY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH)
#define _REGION2_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID)
-#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
+#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH | \
+ _REGION3_ENTRY_PRESENT)
#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID)
#define _REGION3_ENTRY_HARDWARE_BITS 0xfffffffffffff6ffUL
@@ -285,18 +286,27 @@ static inline int is_module_addr(void *addr)
#define _REGION3_ENTRY_ORIGIN_LARGE ~0x7fffffffUL /* large page address */
#define _REGION3_ENTRY_DIRTY 0x2000 /* SW region dirty bit */
#define _REGION3_ENTRY_YOUNG 0x1000 /* SW region young bit */
+#define _REGION3_ENTRY_COMM 0x0010 /* Common-Region, marks swap entry */
#define _REGION3_ENTRY_LARGE 0x0400 /* RTTE-format control, large page */
-#define _REGION3_ENTRY_WRITE 0x0002 /* SW region write bit */
-#define _REGION3_ENTRY_READ 0x0001 /* SW region read bit */
+#define _REGION3_ENTRY_WRITE 0x8000 /* SW region write bit */
+#define _REGION3_ENTRY_READ 0x4000 /* SW region read bit */
#ifdef CONFIG_MEM_SOFT_DIRTY
-#define _REGION3_ENTRY_SOFT_DIRTY 0x4000 /* SW region soft dirty bit */
+#define _REGION3_ENTRY_SOFT_DIRTY 0x0002 /* SW region soft dirty bit */
#else
#define _REGION3_ENTRY_SOFT_DIRTY 0x0000 /* SW region soft dirty bit */
#endif
#define _REGION_ENTRY_BITS 0xfffffffffffff22fUL
+/*
+ * SW region present bit. For non-leaf region-third-table entries, bits 62-63
+ * indicate the TABLE LENGTH and both must be set to 1. But such entries
+ * would always be considered as present, so it is safe to use bit 63 as
+ * PRESENT bit for PUD.
+ */
+#define _REGION3_ENTRY_PRESENT 0x0001
+
/* Bits in the segment table entry */
#define _SEGMENT_ENTRY_BITS 0xfffffffffffffe3fUL
#define _SEGMENT_ENTRY_HARDWARE_BITS 0xfffffffffffffe3cUL
@@ -308,21 +318,29 @@ static inline int is_module_addr(void *addr)
#define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */
#define _SEGMENT_ENTRY_TYPE_MASK 0x0c /* segment table type mask */
-#define _SEGMENT_ENTRY (0)
+#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PRESENT)
#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INVALID)
#define _SEGMENT_ENTRY_DIRTY 0x2000 /* SW segment dirty bit */
#define _SEGMENT_ENTRY_YOUNG 0x1000 /* SW segment young bit */
+
+#define _SEGMENT_ENTRY_COMM 0x0010 /* Common-Segment, marks swap entry */
#define _SEGMENT_ENTRY_LARGE 0x0400 /* STE-format control, large page */
-#define _SEGMENT_ENTRY_WRITE 0x0002 /* SW segment write bit */
-#define _SEGMENT_ENTRY_READ 0x0001 /* SW segment read bit */
+#define _SEGMENT_ENTRY_WRITE 0x8000 /* SW segment write bit */
+#define _SEGMENT_ENTRY_READ 0x4000 /* SW segment read bit */
#ifdef CONFIG_MEM_SOFT_DIRTY
-#define _SEGMENT_ENTRY_SOFT_DIRTY 0x4000 /* SW segment soft dirty bit */
+#define _SEGMENT_ENTRY_SOFT_DIRTY 0x0002 /* SW segment soft dirty bit */
#else
#define _SEGMENT_ENTRY_SOFT_DIRTY 0x0000 /* SW segment soft dirty bit */
#endif
+#define _SEGMENT_ENTRY_PRESENT 0x0001 /* SW segment present bit */
+
+/* Common bits in region and segment table entries, for swap entries */
+#define _RST_ENTRY_COMM 0x0010 /* Common-Region/Segment, marks swap entry */
+#define _RST_ENTRY_INVALID 0x0020 /* invalid region/segment table entry */
+
#define _CRST_ENTRIES 2048 /* number of region/segment table entries */
#define _PAGE_ENTRIES 256 /* number of page table entries */
@@ -338,7 +356,7 @@ static inline int is_module_addr(void *addr)
#define _REGION2_INDEX (0x7ffUL << _REGION2_SHIFT)
#define _REGION3_INDEX (0x7ffUL << _REGION3_SHIFT)
#define _SEGMENT_INDEX (0x7ffUL << _SEGMENT_SHIFT)
-#define _PAGE_INDEX (0xffUL << _PAGE_SHIFT)
+#define _PAGE_INDEX (0xffUL << PAGE_SHIFT)
#define _REGION1_SIZE (1UL << _REGION1_SHIFT)
#define _REGION2_SIZE (1UL << _REGION2_SHIFT)
@@ -454,17 +472,22 @@ static inline int is_module_addr(void *addr)
/*
* Segment entry (large page) protection definitions.
*/
-#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_INVALID | \
+#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_INVALID | \
_SEGMENT_ENTRY_PROTECT)
-#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PROTECT | \
+#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_PROTECT | \
_SEGMENT_ENTRY_READ | \
_SEGMENT_ENTRY_NOEXEC)
-#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PROTECT | \
+#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_PROTECT | \
_SEGMENT_ENTRY_READ)
-#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_READ | \
+#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_READ | \
_SEGMENT_ENTRY_WRITE | \
_SEGMENT_ENTRY_NOEXEC)
-#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_READ | \
+#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_READ | \
_SEGMENT_ENTRY_WRITE)
#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY | \
_SEGMENT_ENTRY_LARGE | \
@@ -491,6 +514,7 @@ static inline int is_module_addr(void *addr)
*/
#define REGION3_KERNEL __pgprot(_REGION_ENTRY_TYPE_R3 | \
+ _REGION3_ENTRY_PRESENT | \
_REGION3_ENTRY_LARGE | \
_REGION3_ENTRY_READ | \
_REGION3_ENTRY_WRITE | \
@@ -498,12 +522,14 @@ static inline int is_module_addr(void *addr)
_REGION3_ENTRY_DIRTY | \
_REGION_ENTRY_NOEXEC)
#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \
+ _REGION3_ENTRY_PRESENT | \
_REGION3_ENTRY_LARGE | \
_REGION3_ENTRY_READ | \
_REGION3_ENTRY_YOUNG | \
_REGION_ENTRY_PROTECT | \
_REGION_ENTRY_NOEXEC)
#define REGION3_KERNEL_EXEC __pgprot(_REGION_ENTRY_TYPE_R3 | \
+ _REGION3_ENTRY_PRESENT | \
_REGION3_ENTRY_LARGE | \
_REGION3_ENTRY_READ | \
_REGION3_ENTRY_WRITE | \
@@ -746,7 +772,7 @@ static inline int pud_present(pud_t pud)
{
if (pud_folded(pud))
return 1;
- return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL;
+ return (pud_val(pud) & _REGION3_ENTRY_PRESENT) != 0;
}
static inline int pud_none(pud_t pud)
@@ -761,13 +787,18 @@ static inline bool pud_leaf(pud_t pud)
{
if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3)
return 0;
- return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
+ return (pud_present(pud) && (pud_val(pud) & _REGION3_ENTRY_LARGE) != 0);
+}
+
+static inline int pmd_present(pmd_t pmd)
+{
+ return (pmd_val(pmd) & _SEGMENT_ENTRY_PRESENT) != 0;
}
#define pmd_leaf pmd_leaf
static inline bool pmd_leaf(pmd_t pmd)
{
- return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
+ return (pmd_present(pmd) && (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0);
}
static inline int pmd_bad(pmd_t pmd)
@@ -799,11 +830,6 @@ static inline int p4d_bad(p4d_t p4d)
return (p4d_val(p4d) & ~_REGION_ENTRY_BITS) != 0;
}
-static inline int pmd_present(pmd_t pmd)
-{
- return pmd_val(pmd) != _SEGMENT_ENTRY_EMPTY;
-}
-
static inline int pmd_none(pmd_t pmd)
{
return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY;
@@ -1851,7 +1877,7 @@ static inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
static inline int pmd_trans_huge(pmd_t pmd)
{
- return pmd_val(pmd) & _SEGMENT_ENTRY_LARGE;
+ return pmd_leaf(pmd);
}
#define has_transparent_hugepage has_transparent_hugepage
@@ -1911,6 +1937,53 @@ static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+/*
+ * 64 bit swap entry format for REGION3 and SEGMENT table entries (RSTE)
+ * Bits 59 and 63 are used to indicate the swap entry. Bit 58 marks the rste
+ * as invalid.
+ * A swap entry is indicated by bit pattern (rste & 0x011) == 0x010
+ * | offset |Xtype |11TT|S0|
+ * |0000000000111111111122222222223333333333444444444455|555555|5566|66|
+ * |0123456789012345678901234567890123456789012345678901|234567|8901|23|
+ *
+ * Bits 0-51 store the offset.
+ * Bits 53-57 store the type.
+ * Bit 62 (S) is used for softdirty tracking.
+ * Bits 60-61 (TT) indicate the table type: 0x01 for REGION3 and 0x00 for SEGMENT.
+ * Bit 52 (X) is unused.
+ */
+
+#define __SWP_OFFSET_MASK_RSTE ((1UL << 52) - 1)
+#define __SWP_OFFSET_SHIFT_RSTE 12
+#define __SWP_TYPE_MASK_RSTE ((1UL << 5) - 1)
+#define __SWP_TYPE_SHIFT_RSTE 6
+
+/*
+ * TT bits set to 0x00 == SEGMENT. For REGION3 entries, caller must add R3
+ * bits 0x01. See also __set_huge_pte_at().
+ */
+static inline unsigned long mk_swap_rste(unsigned long type, unsigned long offset)
+{
+ unsigned long rste;
+
+ rste = _RST_ENTRY_INVALID | _RST_ENTRY_COMM;
+ rste |= (offset & __SWP_OFFSET_MASK_RSTE) << __SWP_OFFSET_SHIFT_RSTE;
+ rste |= (type & __SWP_TYPE_MASK_RSTE) << __SWP_TYPE_SHIFT_RSTE;
+ return rste;
+}
+
+static inline unsigned long __swp_type_rste(swp_entry_t entry)
+{
+ return (entry.val >> __SWP_TYPE_SHIFT_RSTE) & __SWP_TYPE_MASK_RSTE;
+}
+
+static inline unsigned long __swp_offset_rste(swp_entry_t entry)
+{
+ return (entry.val >> __SWP_OFFSET_SHIFT_RSTE) & __SWP_OFFSET_MASK_RSTE;
+}
+
+#define __rste_to_swp_entry(rste) ((swp_entry_t) { rste })
+
extern int vmem_add_mapping(unsigned long start, unsigned long size);
extern void vmem_remove_mapping(unsigned long start, unsigned long size);
extern int __vmem_map_4k_page(unsigned long addr, unsigned long phys, pgprot_t prot, bool alloc);
diff --git a/arch/s390/include/asm/physmem_info.h b/arch/s390/include/asm/physmem_info.h
index f45cfc8bc233..51b68a43e195 100644
--- a/arch/s390/include/asm/physmem_info.h
+++ b/arch/s390/include/asm/physmem_info.h
@@ -9,6 +9,7 @@ enum physmem_info_source {
MEM_DETECT_NONE = 0,
MEM_DETECT_SCLP_STOR_INFO,
MEM_DETECT_DIAG260,
+ MEM_DETECT_DIAG500_STOR_LIMIT,
MEM_DETECT_SCLP_READ_INFO,
MEM_DETECT_BIN_SEARCH
};
@@ -107,6 +108,8 @@ static inline const char *get_physmem_info_source(void)
return "sclp storage info";
case MEM_DETECT_DIAG260:
return "diag260";
+ case MEM_DETECT_DIAG500_STOR_LIMIT:
+ return "diag500 storage limit";
case MEM_DETECT_SCLP_READ_INFO:
return "sclp read info";
case MEM_DETECT_BIN_SEARCH:
diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h
index deca3f221836..2c29bdf12127 100644
--- a/arch/s390/include/asm/preempt.h
+++ b/arch/s390/include/asm/preempt.h
@@ -5,6 +5,7 @@
#include <asm/current.h>
#include <linux/thread_info.h>
#include <asm/atomic_ops.h>
+#include <asm/cmpxchg.h>
#include <asm/march.h>
#ifdef MARCH_HAS_Z196_FEATURES
@@ -22,12 +23,10 @@ static __always_inline void preempt_count_set(int pc)
{
int old, new;
+ old = READ_ONCE(get_lowcore()->preempt_count);
do {
- old = READ_ONCE(get_lowcore()->preempt_count);
- new = (old & PREEMPT_NEED_RESCHED) |
- (pc & ~PREEMPT_NEED_RESCHED);
- } while (__atomic_cmpxchg(&get_lowcore()->preempt_count,
- old, new) != old);
+ new = (old & PREEMPT_NEED_RESCHED) | (pc & ~PREEMPT_NEED_RESCHED);
+ } while (!arch_try_cmpxchg(&get_lowcore()->preempt_count, &old, new));
}
static __always_inline void set_preempt_need_resched(void)
@@ -131,10 +130,24 @@ static __always_inline bool should_resched(int preempt_offset)
#define init_idle_preempt_count(p, cpu) do { } while (0)
#ifdef CONFIG_PREEMPTION
-extern void preempt_schedule(void);
-#define __preempt_schedule() preempt_schedule()
-extern void preempt_schedule_notrace(void);
-#define __preempt_schedule_notrace() preempt_schedule_notrace()
+
+void preempt_schedule(void);
+void preempt_schedule_notrace(void);
+
+#ifdef CONFIG_PREEMPT_DYNAMIC
+
+void dynamic_preempt_schedule(void);
+void dynamic_preempt_schedule_notrace(void);
+#define __preempt_schedule() dynamic_preempt_schedule()
+#define __preempt_schedule_notrace() dynamic_preempt_schedule_notrace()
+
+#else /* CONFIG_PREEMPT_DYNAMIC */
+
+#define __preempt_schedule() preempt_schedule()
+#define __preempt_schedule_notrace() preempt_schedule_notrace()
+
+#endif /* CONFIG_PREEMPT_DYNAMIC */
+
#endif /* CONFIG_PREEMPTION */
#endif /* __ASM_PREEMPT_H */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 9a5236acc0a8..8761fd01a9f0 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -39,6 +39,7 @@
#include <asm/runtime_instr.h>
#include <asm/irqflags.h>
#include <asm/alternative.h>
+#include <asm/fault.h>
struct pcpu {
unsigned long ec_mask; /* bit mask for ec_xxx functions */
@@ -187,10 +188,8 @@ struct thread_struct {
unsigned long hardirq_timer; /* task cputime in hardirq context */
unsigned long softirq_timer; /* task cputime in softirq context */
const sys_call_ptr_t *sys_call_table; /* system call table address */
- unsigned long gmap_addr; /* address of last gmap fault. */
- unsigned int gmap_write_flag; /* gmap fault write indication */
+ union teid gmap_teid; /* address and flags of last gmap fault */
unsigned int gmap_int_code; /* int code of last gmap fault */
- unsigned int gmap_pfault; /* signal of a pending guest pfault */
int ufpu_flags; /* user fpu flags */
int kfpu_flags; /* kernel fpu flags */
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 2ad9324f6338..788bc4467445 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -14,11 +14,13 @@
#define PIF_SYSCALL 0 /* inside a system call */
#define PIF_EXECVE_PGSTE_RESTART 1 /* restart execve for PGSTE binaries */
#define PIF_SYSCALL_RET_SET 2 /* return value was set via ptrace */
+#define PIF_GUEST_FAULT 3 /* indicates program check in sie64a */
#define PIF_FTRACE_FULL_REGS 4 /* all register contents valid (ftrace) */
#define _PIF_SYSCALL BIT(PIF_SYSCALL)
#define _PIF_EXECVE_PGSTE_RESTART BIT(PIF_EXECVE_PGSTE_RESTART)
#define _PIF_SYSCALL_RET_SET BIT(PIF_SYSCALL_RET_SET)
+#define _PIF_GUEST_FAULT BIT(PIF_GUEST_FAULT)
#define _PIF_FTRACE_FULL_REGS BIT(PIF_FTRACE_FULL_REGS)
#define PSW32_MASK_PER _AC(0x40000000, UL)
diff --git a/arch/s390/include/asm/set_memory.h b/arch/s390/include/asm/set_memory.h
index 06fbabe2f66c..94092f4ae764 100644
--- a/arch/s390/include/asm/set_memory.h
+++ b/arch/s390/include/asm/set_memory.h
@@ -62,5 +62,7 @@ __SET_MEMORY_FUNC(set_memory_4k, SET_MEMORY_4K)
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
+bool kernel_page_present(struct page *page);
#endif
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h
index edee63da08e7..472943b77066 100644
--- a/arch/s390/include/asm/sigp.h
+++ b/arch/s390/include/asm/sigp.h
@@ -38,6 +38,8 @@
#ifndef __ASSEMBLY__
+#include <asm/asm.h>
+
static inline int ____pcpu_sigp(u16 addr, u8 order, unsigned long parm,
u32 *status)
{
@@ -46,13 +48,12 @@ static inline int ____pcpu_sigp(u16 addr, u8 order, unsigned long parm,
asm volatile(
" sigp %[r1],%[addr],0(%[order])\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=&d" (cc), [r1] "+&d" (r1.pair)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [r1] "+d" (r1.pair)
: [addr] "d" (addr), [order] "a" (order)
- : "cc");
+ : CC_CLOBBER);
*status = r1.even;
- return cc;
+ return CC_TRANSFORM(cc);
}
static inline int __pcpu_sigp(u16 addr, u8 order, unsigned long parm,
diff --git a/arch/s390/include/asm/sparsemem.h b/arch/s390/include/asm/sparsemem.h
index c549893602ea..668dfc5de538 100644
--- a/arch/s390/include/asm/sparsemem.h
+++ b/arch/s390/include/asm/sparsemem.h
@@ -2,7 +2,23 @@
#ifndef _ASM_S390_SPARSEMEM_H
#define _ASM_S390_SPARSEMEM_H
-#define SECTION_SIZE_BITS 28
+#define SECTION_SIZE_BITS 27
#define MAX_PHYSMEM_BITS CONFIG_MAX_PHYSMEM_BITS
+#ifdef CONFIG_NUMA
+
+static inline int memory_add_physaddr_to_nid(u64 addr)
+{
+ return 0;
+}
+#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
+
+static inline int phys_to_target_node(u64 start)
+{
+ return 0;
+}
+#define phys_to_target_node phys_to_target_node
+
+#endif /* CONFIG_NUMA */
+
#endif /* _ASM_S390_SPARSEMEM_H */
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index 77d5e804af93..f87dd0a84855 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -57,8 +57,10 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lp)
static inline int arch_spin_trylock_once(arch_spinlock_t *lp)
{
+ int old = 0;
+
barrier();
- return likely(__atomic_cmpxchg_bool(&lp->lock, 0, SPINLOCK_LOCKVAL));
+ return likely(arch_try_cmpxchg(&lp->lock, &old, SPINLOCK_LOCKVAL));
}
static inline void arch_spin_lock(arch_spinlock_t *lp)
@@ -80,9 +82,10 @@ static inline void arch_spin_unlock(arch_spinlock_t *lp)
kcsan_release();
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,7,0", ALT_FACILITY(49)) /* NIAI 7 */
- " sth %1,%0\n"
- : "=R" (((unsigned short *) &lp->lock)[1])
- : "d" (0) : "cc", "memory");
+ " mvhhi %[lock],0\n"
+ : [lock] "=Q" (((unsigned short *)&lp->lock)[1])
+ :
+ : "memory");
}
/*
@@ -118,7 +121,9 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
static inline void arch_write_lock(arch_rwlock_t *rw)
{
- if (!__atomic_cmpxchg_bool(&rw->cnts, 0, 0x30000))
+ int old = 0;
+
+ if (!arch_try_cmpxchg(&rw->cnts, &old, 0x30000))
arch_write_lock_wait(rw);
}
@@ -133,8 +138,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
int old;
old = READ_ONCE(rw->cnts);
- return (!(old & 0xffff0000) &&
- __atomic_cmpxchg_bool(&rw->cnts, old, old + 1));
+ return (!(old & 0xffff0000) && arch_try_cmpxchg(&rw->cnts, &old, old + 1));
}
static inline int arch_write_trylock(arch_rwlock_t *rw)
@@ -142,7 +146,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
int old;
old = READ_ONCE(rw->cnts);
- return !old && __atomic_cmpxchg_bool(&rw->cnts, 0, 0x30000);
+ return !old && arch_try_cmpxchg(&rw->cnts, &old, 0x30000);
}
#endif /* __ASM_SPINLOCK_H */
diff --git a/arch/s390/include/asm/spinlock_types.h b/arch/s390/include/asm/spinlock_types.h
index b69695e39957..3653ff57d6d9 100644
--- a/arch/s390/include/asm/spinlock_types.h
+++ b/arch/s390/include/asm/spinlock_types.h
@@ -3,7 +3,7 @@
#define __ASM_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
typedef struct {
diff --git a/arch/s390/include/asm/stp.h b/arch/s390/include/asm/stp.h
index 4d74d7e33340..827cb208de86 100644
--- a/arch/s390/include/asm/stp.h
+++ b/arch/s390/include/asm/stp.h
@@ -94,5 +94,6 @@ struct stp_stzi {
int stp_sync_check(void);
int stp_island_check(void);
void stp_queue_work(void);
+bool stp_enabled(void);
#endif /* __S390_STP_H */
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 00ac01874a12..c33f7144d1b9 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -61,44 +61,45 @@ void arch_setup_new_exec(void);
/*
* thread information flags bit numbers
*/
-/* _TIF_WORK bits */
#define TIF_NOTIFY_RESUME 0 /* callback before returning to user */
#define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
-#define TIF_UPROBE 3 /* breakpointed or single-stepping */
-#define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */
+#define TIF_NEED_RESCHED_LAZY 3 /* lazy rescheduling needed */
+#define TIF_UPROBE 4 /* breakpointed or single-stepping */
#define TIF_PATCH_PENDING 5 /* pending live patching update */
#define TIF_PGSTE 6 /* New mm's will use 4K page tables */
#define TIF_NOTIFY_SIGNAL 7 /* signal notifications exist */
+#define TIF_GUARDED_STORAGE 8 /* load guarded storage control block */
#define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP */
#define TIF_PER_TRAP 10 /* Need to handle PER trap on exit to usermode */
-
#define TIF_31BIT 16 /* 32bit process */
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal() */
#define TIF_SINGLE_STEP 19 /* This task is single stepped */
#define TIF_BLOCK_STEP 20 /* This task is block stepped */
#define TIF_UPROBE_SINGLESTEP 21 /* This task is uprobe single stepped */
-
-/* _TIF_TRACE bits */
#define TIF_SYSCALL_TRACE 24 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 25 /* syscall auditing active */
#define TIF_SECCOMP 26 /* secure computing */
#define TIF_SYSCALL_TRACEPOINT 27 /* syscall tracepoint instrumentation */
#define _TIF_NOTIFY_RESUME BIT(TIF_NOTIFY_RESUME)
-#define _TIF_NOTIFY_SIGNAL BIT(TIF_NOTIFY_SIGNAL)
#define _TIF_SIGPENDING BIT(TIF_SIGPENDING)
#define _TIF_NEED_RESCHED BIT(TIF_NEED_RESCHED)
+#define _TIF_NEED_RESCHED_LAZY BIT(TIF_NEED_RESCHED_LAZY)
#define _TIF_UPROBE BIT(TIF_UPROBE)
-#define _TIF_GUARDED_STORAGE BIT(TIF_GUARDED_STORAGE)
#define _TIF_PATCH_PENDING BIT(TIF_PATCH_PENDING)
+#define _TIF_PGSTE BIT(TIF_PGSTE)
+#define _TIF_NOTIFY_SIGNAL BIT(TIF_NOTIFY_SIGNAL)
+#define _TIF_GUARDED_STORAGE BIT(TIF_GUARDED_STORAGE)
#define _TIF_ISOLATE_BP_GUEST BIT(TIF_ISOLATE_BP_GUEST)
#define _TIF_PER_TRAP BIT(TIF_PER_TRAP)
-
#define _TIF_31BIT BIT(TIF_31BIT)
+#define _TIF_MEMDIE BIT(TIF_MEMDIE)
+#define _TIF_RESTORE_SIGMASK BIT(TIF_RESTORE_SIGMASK)
#define _TIF_SINGLE_STEP BIT(TIF_SINGLE_STEP)
-
+#define _TIF_BLOCK_STEP BIT(TIF_BLOCK_STEP)
+#define _TIF_UPROBE_SINGLESTEP BIT(TIF_UPROBE_SINGLESTEP)
#define _TIF_SYSCALL_TRACE BIT(TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT BIT(TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP BIT(TIF_SECCOMP)
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index 640901f2fbc3..a9460bd6555b 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -13,6 +13,7 @@
#include <linux/preempt.h>
#include <linux/time64.h>
#include <asm/lowcore.h>
+#include <asm/asm.h>
/* The value of the TOD clock for 1.1.1970. */
#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
@@ -44,11 +45,12 @@ static inline int set_tod_clock(__u64 time)
int cc;
asm volatile(
- " sck %1\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc) : "Q" (time) : "cc");
- return cc;
+ " sck %[time]\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
+ : [time] "Q" (time)
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc);
}
static inline int store_tod_clock_ext_cc(union tod_clock *clk)
@@ -56,11 +58,12 @@ static inline int store_tod_clock_ext_cc(union tod_clock *clk)
int cc;
asm volatile(
- " stcke %1\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc), "=Q" (*clk) : : "cc");
- return cc;
+ " stcke %[clk]\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [clk] "=Q" (*clk)
+ :
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc);
}
static __always_inline void store_tod_clock_ext(union tod_clock *tod)
@@ -93,6 +96,7 @@ extern unsigned char ptff_function_mask[16];
#define PTFF_QAF 0x00 /* query available functions */
#define PTFF_QTO 0x01 /* query tod offset */
#define PTFF_QSI 0x02 /* query steering information */
+#define PTFF_QPT 0x03 /* query physical clock */
#define PTFF_QUI 0x04 /* query UTC information */
#define PTFF_ATO 0x40 /* adjust tod offset */
#define PTFF_STO 0x41 /* set tod offset */
@@ -149,12 +153,11 @@ struct ptff_qui {
" lgr 0,%[reg0]\n" \
" lgr 1,%[reg1]\n" \
" ptff\n" \
- " ipm %[rc]\n" \
- " srl %[rc],28\n" \
- : [rc] "=&d" (rc), "+m" (*(struct addrtype *)reg1) \
+ CC_IPM(rc) \
+ : CC_OUT(rc, rc), "+m" (*(struct addrtype *)reg1) \
: [reg0] "d" (reg0), [reg1] "d" (reg1) \
- : "cc", "0", "1"); \
- rc; \
+ : CC_CLOBBER_LIST("0", "1")); \
+ CC_TRANSFORM(rc); \
})
static inline unsigned long local_tick_disable(void)
@@ -250,6 +253,11 @@ static __always_inline unsigned long tod_to_ns(unsigned long todval)
return ((todval >> 9) * 125) + (((todval & 0x1ff) * 125) >> 9);
}
+static __always_inline u128 eitod_to_ns(u128 todval)
+{
+ return (todval * 125) >> 9;
+}
+
/**
* tod_after - compare two 64 bit TOD values
* @a: first 64 bit TOD timestamp
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index a6e2cd89b609..9dfd46dd03c6 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -46,11 +46,6 @@ static inline void __tlb_flush_mm(struct mm_struct *mm)
{
unsigned long gmap_asce;
- /*
- * If the machine has IDTE we prefer to do a per mm flush
- * on all cpus instead of doing a local flush if the mm
- * only ran on the local cpu.
- */
preempt_disable();
atomic_inc(&mm->context.flush_count);
/* Reset TLB flush mask */
diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
index 153d93468b77..dc332609f2c3 100644
--- a/arch/s390/include/asm/uv.h
+++ b/arch/s390/include/asm/uv.h
@@ -2,7 +2,7 @@
/*
* Ultravisor Interfaces
*
- * Copyright IBM Corp. 2019, 2022
+ * Copyright IBM Corp. 2019, 2024
*
* Author(s):
* Vasily Gorbik <gor@linux.ibm.com>
@@ -17,6 +17,7 @@
#include <linux/sched.h>
#include <asm/page.h>
#include <asm/gmap.h>
+#include <asm/asm.h>
#define UVC_CC_OK 0
#define UVC_CC_ERROR 1
@@ -28,9 +29,11 @@
#define UVC_RC_INV_STATE 0x0003
#define UVC_RC_INV_LEN 0x0005
#define UVC_RC_NO_RESUME 0x0007
+#define UVC_RC_MORE_DATA 0x0100
#define UVC_RC_NEED_DESTROY 0x8000
#define UVC_CMD_QUI 0x0001
+#define UVC_CMD_QUERY_KEYS 0x0002
#define UVC_CMD_INIT_UV 0x000f
#define UVC_CMD_CREATE_SEC_CONF 0x0100
#define UVC_CMD_DESTROY_SEC_CONF 0x0101
@@ -61,6 +64,7 @@
#define UVC_CMD_ADD_SECRET 0x1031
#define UVC_CMD_LIST_SECRETS 0x1033
#define UVC_CMD_LOCK_SECRETS 0x1034
+#define UVC_CMD_RETR_SECRET 0x1035
/* Bits in installed uv calls */
enum uv_cmds_inst {
@@ -94,6 +98,8 @@ enum uv_cmds_inst {
BIT_UVC_CMD_ADD_SECRET = 29,
BIT_UVC_CMD_LIST_SECRETS = 30,
BIT_UVC_CMD_LOCK_SECRETS = 31,
+ BIT_UVC_CMD_RETR_SECRET = 33,
+ BIT_UVC_CMD_QUERY_KEYS = 34,
};
enum uv_feat_ind {
@@ -140,11 +146,27 @@ struct uv_cb_qui {
u64 reservedf0; /* 0x00f0 */
u64 supp_add_secret_req_ver; /* 0x00f8 */
u64 supp_add_secret_pcf; /* 0x0100 */
- u64 supp_secret_types; /* 0x0180 */
- u16 max_secrets; /* 0x0110 */
- u8 reserved112[0x120 - 0x112]; /* 0x0112 */
+ u64 supp_secret_types; /* 0x0108 */
+ u16 max_assoc_secrets; /* 0x0110 */
+ u16 max_retr_secrets; /* 0x0112 */
+ u8 reserved114[0x120 - 0x114]; /* 0x0114 */
} __packed __aligned(8);
+struct uv_key_hash {
+ u64 dword[4];
+} __packed __aligned(8);
+
+#define UVC_QUERY_KEYS_IDX_HK 0
+#define UVC_QUERY_KEYS_IDX_BACK_HK 1
+
+/* Query Ultravisor Keys */
+struct uv_cb_query_keys {
+ struct uv_cb_header header; /* 0x0000 */
+ u64 reserved08[3]; /* 0x0008 */
+ struct uv_key_hash key_hashes[15]; /* 0x0020 */
+} __packed __aligned(8);
+static_assert(sizeof(struct uv_cb_query_keys) == 0x200);
+
/* Initialize Ultravisor */
struct uv_cb_init {
struct uv_cb_header header;
@@ -317,7 +339,6 @@ struct uv_cb_dump_complete {
* A common UV call struct for pv guests that contains a single address
* Examples:
* Add Secret
- * List Secrets
*/
struct uv_cb_guest_addr {
struct uv_cb_header header;
@@ -326,18 +347,102 @@ struct uv_cb_guest_addr {
u64 reserved28[4];
} __packed __aligned(8);
+#define UVC_RC_RETR_SECR_BUF_SMALL 0x0109
+#define UVC_RC_RETR_SECR_STORE_EMPTY 0x010f
+#define UVC_RC_RETR_SECR_INV_IDX 0x0110
+#define UVC_RC_RETR_SECR_INV_SECRET 0x0111
+
+struct uv_cb_retr_secr {
+ struct uv_cb_header header;
+ u64 reserved08[2];
+ u16 secret_idx;
+ u16 reserved1a;
+ u32 buf_size;
+ u64 buf_addr;
+ u64 reserved28[4];
+} __packed __aligned(8);
+
+struct uv_cb_list_secrets {
+ struct uv_cb_header header;
+ u64 reserved08[2];
+ u8 reserved18[6];
+ u16 start_idx;
+ u64 list_addr;
+ u64 reserved28[4];
+} __packed __aligned(8);
+
+enum uv_secret_types {
+ UV_SECRET_INVAL = 0x0,
+ UV_SECRET_NULL = 0x1,
+ UV_SECRET_ASSOCIATION = 0x2,
+ UV_SECRET_PLAIN = 0x3,
+ UV_SECRET_AES_128 = 0x4,
+ UV_SECRET_AES_192 = 0x5,
+ UV_SECRET_AES_256 = 0x6,
+ UV_SECRET_AES_XTS_128 = 0x7,
+ UV_SECRET_AES_XTS_256 = 0x8,
+ UV_SECRET_HMAC_SHA_256 = 0x9,
+ UV_SECRET_HMAC_SHA_512 = 0xa,
+ /* 0x0b - 0x10 reserved */
+ UV_SECRET_ECDSA_P256 = 0x11,
+ UV_SECRET_ECDSA_P384 = 0x12,
+ UV_SECRET_ECDSA_P521 = 0x13,
+ UV_SECRET_ECDSA_ED25519 = 0x14,
+ UV_SECRET_ECDSA_ED448 = 0x15,
+};
+
+/**
+ * uv_secret_list_item_hdr - UV secret metadata.
+ * @index: Index of the secret in the secret list.
+ * @type: Type of the secret. See `enum uv_secret_types`.
+ * @length: Length of the stored secret.
+ */
+struct uv_secret_list_item_hdr {
+ u16 index;
+ u16 type;
+ u32 length;
+} __packed __aligned(8);
+
+#define UV_SECRET_ID_LEN 32
+/**
+ * uv_secret_list_item - UV secret entry.
+ * @hdr: The metadata of this secret.
+ * @id: The ID of this secret, not the secret itself.
+ */
+struct uv_secret_list_item {
+ struct uv_secret_list_item_hdr hdr;
+ u64 reserverd08;
+ u8 id[UV_SECRET_ID_LEN];
+} __packed __aligned(8);
+
+/**
+ * uv_secret_list - UV secret-metadata list.
+ * @num_secr_stored: Number of secrets stored in this list.
+ * @total_num_secrets: Number of secrets stored in the UV for this guest.
+ * @next_secret_idx: positive number if there are more secrets available or zero.
+ * @secrets: Up to 85 UV-secret metadata entries.
+ */
+struct uv_secret_list {
+ u16 num_secr_stored;
+ u16 total_num_secrets;
+ u16 next_secret_idx;
+ u16 reserved_06;
+ u64 reserved_08;
+ struct uv_secret_list_item secrets[85];
+} __packed __aligned(8);
+static_assert(sizeof(struct uv_secret_list) == PAGE_SIZE);
+
static inline int __uv_call(unsigned long r1, unsigned long r2)
{
int cc;
asm volatile(
- " .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc)
+ " .insn rrf,0xb9a40000,%[r1],%[r2],0,0\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
: [r1] "a" (r1), [r2] "a" (r2)
- : "memory", "cc");
- return cc;
+ : CC_CLOBBER_LIST("memory"));
+ return CC_TRANSFORM(cc);
}
static inline int uv_call(unsigned long r1, unsigned long r2)
@@ -382,6 +487,48 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u16 *rc, u16 *rrc)
return cc ? -EINVAL : 0;
}
+/**
+ * uv_list_secrets() - Do a List Secrets UVC.
+ *
+ * @buf: Buffer to write list into; size of one page.
+ * @start_idx: The smallest index that should be included in the list.
+ * For the fist invocation use 0.
+ * @rc: Pointer to store the return code or NULL.
+ * @rrc: Pointer to store the return reason code or NULL.
+ *
+ * This function calls the List Secrets UVC. The result is written into `buf`,
+ * that needs to be at least one page of writable memory.
+ * `buf` consists of:
+ * * %struct uv_secret_list_hdr
+ * * %struct uv_secret_list_item (multiple)
+ *
+ * For `start_idx` use _0_ for the first call. If there are more secrets available
+ * but could not fit into the page then `rc` is `UVC_RC_MORE_DATA`.
+ * In this case use `uv_secret_list_hdr.next_secret_idx` for `start_idx`.
+ *
+ * Context: might sleep.
+ *
+ * Return: The UVC condition code.
+ */
+static inline int uv_list_secrets(struct uv_secret_list *buf, u16 start_idx,
+ u16 *rc, u16 *rrc)
+{
+ struct uv_cb_list_secrets uvcb = {
+ .header.len = sizeof(uvcb),
+ .header.cmd = UVC_CMD_LIST_SECRETS,
+ .start_idx = start_idx,
+ .list_addr = (u64)buf,
+ };
+ int cc = uv_call_sched(0, (u64)&uvcb);
+
+ if (rc)
+ *rc = uvcb.header.rc;
+ if (rrc)
+ *rrc = uvcb.header.rrc;
+
+ return cc;
+}
+
struct uv_info {
unsigned long inst_calls_list[4];
unsigned long uv_base_stor_len;
@@ -402,7 +549,8 @@ struct uv_info {
unsigned long supp_add_secret_req_ver;
unsigned long supp_add_secret_pcf;
unsigned long supp_secret_types;
- unsigned short max_secrets;
+ unsigned short max_assoc_secrets;
+ unsigned short max_retr_secrets;
};
extern struct uv_info uv_info;
@@ -468,6 +616,10 @@ static inline int uv_remove_shared(unsigned long addr)
return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
}
+int uv_get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN],
+ struct uv_secret_list_item_hdr *secret);
+int uv_retrieve_secret(u16 secret_idx, u8 *buf, size_t buf_size);
+
extern int prot_virt_host;
static inline int is_prot_virt_host(void)
diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h
index 91061f0279be..92c73e4d97a9 100644
--- a/arch/s390/include/asm/vdso.h
+++ b/arch/s390/include/asm/vdso.h
@@ -12,9 +12,6 @@ int vdso_getcpu_init(void);
#endif /* __ASSEMBLY__ */
-/* Default link address for the vDSO */
-#define VDSO_LBASE 0
-
#define __VVAR_PAGES 2
#define VDSO_VERSION_STRING LINUX_2.6.29
diff --git a/arch/s390/include/asm/vdso/data.h b/arch/s390/include/asm/vdso/data.h
deleted file mode 100644
index 0e2b40ef69b0..000000000000
--- a/arch/s390/include/asm/vdso/data.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __S390_ASM_VDSO_DATA_H
-#define __S390_ASM_VDSO_DATA_H
-
-#include <linux/types.h>
-
-struct arch_vdso_data {
- __s64 tod_steering_delta;
- __u64 tod_steering_end;
-};
-
-#endif /* __S390_ASM_VDSO_DATA_H */
diff --git a/arch/s390/include/asm/vdso/time_data.h b/arch/s390/include/asm/vdso/time_data.h
new file mode 100644
index 000000000000..8a08752422e6
--- /dev/null
+++ b/arch/s390/include/asm/vdso/time_data.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __S390_ASM_VDSO_TIME_DATA_H
+#define __S390_ASM_VDSO_TIME_DATA_H
+
+#include <linux/types.h>
+
+struct arch_vdso_time_data {
+ __s64 tod_steering_delta;
+ __u64 tod_steering_end;
+};
+
+#endif /* __S390_ASM_VDSO_TIME_DATA_H */
diff --git a/arch/s390/include/asm/vdso/vsyscall.h b/arch/s390/include/asm/vdso/vsyscall.h
index 3c5d5e47814e..3eb576ecd3bd 100644
--- a/arch/s390/include/asm/vdso/vsyscall.h
+++ b/arch/s390/include/asm/vdso/vsyscall.h
@@ -7,7 +7,6 @@
#ifndef __ASSEMBLY__
#include <linux/hrtimer.h>
-#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
#include <asm/vdso.h>
@@ -17,10 +16,6 @@ enum vvar_pages {
VVAR_NR_PAGES
};
-/*
- * Update the vDSO data page to keep in sync with kernel timekeeping.
- */
-
static __always_inline struct vdso_data *__s390_get_k_vdso_data(void)
{
return vdso_data;
diff --git a/arch/s390/include/uapi/asm/dasd.h b/arch/s390/include/uapi/asm/dasd.h
index b11d98800458..7c364b33c84d 100644
--- a/arch/s390/include/uapi/asm/dasd.h
+++ b/arch/s390/include/uapi/asm/dasd.h
@@ -294,7 +294,7 @@ struct dasd_snid_ioctl_data {
/********************************************************************************
* SECTION: Definition of IOCTLs
*
- * Here ist how the ioctl-nr should be used:
+ * Here is how the ioctl-nr should be used:
* 0 - 31 DASD driver itself
* 32 - 239 still open
* 240 - 255 reserved for EMC
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index 05eaf6db3ad4..60345dd2cba2 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -469,7 +469,8 @@ struct kvm_s390_vm_cpu_subfunc {
__u8 kdsa[16]; /* with MSA9 */
__u8 sortl[32]; /* with STFLE.150 */
__u8 dfltcc[32]; /* with STFLE.151 */
- __u8 reserved[1728];
+ __u8 pfcr[16]; /* with STFLE.201 */
+ __u8 reserved[1712];
};
#define KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST 6
diff --git a/arch/s390/include/uapi/asm/pkey.h b/arch/s390/include/uapi/asm/pkey.h
index 60431d00e6bd..ca42e941675d 100644
--- a/arch/s390/include/uapi/asm/pkey.h
+++ b/arch/s390/include/uapi/asm/pkey.h
@@ -48,21 +48,22 @@
/* the newer ioctls use a pkey_key_type enum for type information */
enum pkey_key_type {
- PKEY_TYPE_CCA_DATA = (__u32) 1,
- PKEY_TYPE_CCA_CIPHER = (__u32) 2,
- PKEY_TYPE_EP11 = (__u32) 3,
- PKEY_TYPE_CCA_ECC = (__u32) 0x1f,
- PKEY_TYPE_EP11_AES = (__u32) 6,
- PKEY_TYPE_EP11_ECC = (__u32) 7,
- PKEY_TYPE_PROTKEY = (__u32) 8,
+ PKEY_TYPE_CCA_DATA = (__u32)1,
+ PKEY_TYPE_CCA_CIPHER = (__u32)2,
+ PKEY_TYPE_EP11 = (__u32)3,
+ PKEY_TYPE_CCA_ECC = (__u32)0x1f,
+ PKEY_TYPE_EP11_AES = (__u32)6,
+ PKEY_TYPE_EP11_ECC = (__u32)7,
+ PKEY_TYPE_PROTKEY = (__u32)8,
+ PKEY_TYPE_UVSECRET = (__u32)9,
};
/* the newer ioctls use a pkey_key_size enum for key size information */
enum pkey_key_size {
- PKEY_SIZE_AES_128 = (__u32) 128,
- PKEY_SIZE_AES_192 = (__u32) 192,
- PKEY_SIZE_AES_256 = (__u32) 256,
- PKEY_SIZE_UNKNOWN = (__u32) 0xFFFFFFFF,
+ PKEY_SIZE_AES_128 = (__u32)128,
+ PKEY_SIZE_AES_192 = (__u32)192,
+ PKEY_SIZE_AES_256 = (__u32)256,
+ PKEY_SIZE_UNKNOWN = (__u32)0xFFFFFFFF,
};
/* some of the newer ioctls use these flags */
@@ -125,6 +126,7 @@ struct pkey_genseck {
__u32 keytype; /* in: key type to generate */
struct pkey_seckey seckey; /* out: the secure key blob */
};
+
#define PKEY_GENSECK _IOWR(PKEY_IOCTL_MAGIC, 0x01, struct pkey_genseck)
/*
@@ -137,6 +139,7 @@ struct pkey_clr2seck {
struct pkey_clrkey clrkey; /* in: the clear key value */
struct pkey_seckey seckey; /* out: the secure key blob */
};
+
#define PKEY_CLR2SECK _IOWR(PKEY_IOCTL_MAGIC, 0x02, struct pkey_clr2seck)
/*
@@ -148,6 +151,7 @@ struct pkey_sec2protk {
struct pkey_seckey seckey; /* in: the secure key blob */
struct pkey_protkey protkey; /* out: the protected key */
};
+
#define PKEY_SEC2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x03, struct pkey_sec2protk)
/*
@@ -158,6 +162,7 @@ struct pkey_clr2protk {
struct pkey_clrkey clrkey; /* in: the clear key value */
struct pkey_protkey protkey; /* out: the protected key */
};
+
#define PKEY_CLR2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x04, struct pkey_clr2protk)
/*
@@ -169,6 +174,7 @@ struct pkey_findcard {
__u16 cardnr; /* out: card number */
__u16 domain; /* out: domain number */
};
+
#define PKEY_FINDCARD _IOWR(PKEY_IOCTL_MAGIC, 0x05, struct pkey_findcard)
/*
@@ -178,6 +184,7 @@ struct pkey_skey2pkey {
struct pkey_seckey seckey; /* in: the secure key blob */
struct pkey_protkey protkey; /* out: the protected key */
};
+
#define PKEY_SKEY2PKEY _IOWR(PKEY_IOCTL_MAGIC, 0x06, struct pkey_skey2pkey)
/*
@@ -195,6 +202,7 @@ struct pkey_verifykey {
__u16 keysize; /* out: key size in bits */
__u32 attributes; /* out: attribute bits */
};
+
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
#define PKEY_VERIFY_ATTR_AES 0x00000001 /* key is an AES key */
#define PKEY_VERIFY_ATTR_OLD_MKVP 0x00000100 /* key has old MKVP value */
@@ -226,6 +234,7 @@ struct pkey_kblob2pkey {
__u32 keylen; /* in: the key blob length */
struct pkey_protkey protkey; /* out: the protected key */
};
+
#define PKEY_KBLOB2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x0A, struct pkey_kblob2pkey)
/*
@@ -258,6 +267,7 @@ struct pkey_genseck2 {
__u32 keylen; /* in: available key blob buffer size */
/* out: actual key blob size */
};
+
#define PKEY_GENSECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x11, struct pkey_genseck2)
/*
@@ -292,6 +302,7 @@ struct pkey_clr2seck2 {
__u32 keylen; /* in: available key blob buffer size */
/* out: actual key blob size */
};
+
#define PKEY_CLR2SECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x12, struct pkey_clr2seck2)
/*
@@ -329,6 +340,7 @@ struct pkey_verifykey2 {
enum pkey_key_size size; /* out: the key size */
__u32 flags; /* out: additional key info flags */
};
+
#define PKEY_VERIFYKEY2 _IOWR(PKEY_IOCTL_MAGIC, 0x17, struct pkey_verifykey2)
/*
@@ -351,6 +363,7 @@ struct pkey_kblob2pkey2 {
__u32 apqn_entries; /* in: # of apqn target list entries */
struct pkey_protkey protkey; /* out: the protected key */
};
+
#define PKEY_KBLOB2PROTK2 _IOWR(PKEY_IOCTL_MAGIC, 0x1A, struct pkey_kblob2pkey2)
/*
@@ -387,6 +400,7 @@ struct pkey_apqns4key {
__u32 apqn_entries; /* in: max # of apqn entries in the list */
/* out: # apqns stored into the list */
};
+
#define PKEY_APQNS4K _IOWR(PKEY_IOCTL_MAGIC, 0x1B, struct pkey_apqns4key)
/*
@@ -426,6 +440,7 @@ struct pkey_apqns4keytype {
__u32 apqn_entries; /* in: max # of apqn entries in the list */
/* out: # apqns stored into the list */
};
+
#define PKEY_APQNS4KT _IOWR(PKEY_IOCTL_MAGIC, 0x1C, struct pkey_apqns4keytype)
/*
@@ -452,6 +467,7 @@ struct pkey_kblob2pkey3 {
__u32 pkeylen; /* in/out: size of pkey buffer/actual len of pkey */
__u8 __user *pkey; /* in: pkey blob buffer space ptr */
};
+
#define PKEY_KBLOB2PROTK3 _IOWR(PKEY_IOCTL_MAGIC, 0x1D, struct pkey_kblob2pkey3)
#endif /* _UAPI_PKEY_H */
diff --git a/arch/s390/include/uapi/asm/uvdevice.h b/arch/s390/include/uapi/asm/uvdevice.h
index b9c2f14a6af3..4947f26ad9fb 100644
--- a/arch/s390/include/uapi/asm/uvdevice.h
+++ b/arch/s390/include/uapi/asm/uvdevice.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
- * Copyright IBM Corp. 2022
+ * Copyright IBM Corp. 2022, 2024
* Author(s): Steffen Eiden <seiden@linux.ibm.com>
*/
#ifndef __S390_ASM_UVDEVICE_H
@@ -52,7 +52,7 @@ struct uvio_uvdev_info {
__u64 supp_uvio_cmds;
/*
* If bit `n` is set, the Ultravisor(UV) supports the UV-call
- * corresponding to the IOCTL with nr `n` in the calling contextx (host
+ * corresponding to the IOCTL with nr `n` in the calling context (host
* or guest). The value is only valid if the corresponding bit in
* @supp_uvio_cmds is set as well.
*/
@@ -71,6 +71,7 @@ struct uvio_uvdev_info {
#define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000
#define UVIO_ADD_SECRET_MAX_LEN 0x100000
#define UVIO_LIST_SECRETS_LEN 0x1000
+#define UVIO_RETR_SECRET_MAX_LEN 0x2000
#define UVIO_DEVICE_NAME "uv"
#define UVIO_TYPE_UVC 'u'
@@ -81,22 +82,25 @@ enum UVIO_IOCTL_NR {
UVIO_IOCTL_ADD_SECRET_NR,
UVIO_IOCTL_LIST_SECRETS_NR,
UVIO_IOCTL_LOCK_SECRETS_NR,
+ UVIO_IOCTL_RETR_SECRET_NR,
/* must be the last entry */
UVIO_IOCTL_NUM_IOCTLS
};
-#define UVIO_IOCTL(nr) _IOWR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb)
-#define UVIO_IOCTL_UVDEV_INFO UVIO_IOCTL(UVIO_IOCTL_UVDEV_INFO_NR)
-#define UVIO_IOCTL_ATT UVIO_IOCTL(UVIO_IOCTL_ATT_NR)
-#define UVIO_IOCTL_ADD_SECRET UVIO_IOCTL(UVIO_IOCTL_ADD_SECRET_NR)
-#define UVIO_IOCTL_LIST_SECRETS UVIO_IOCTL(UVIO_IOCTL_LIST_SECRETS_NR)
-#define UVIO_IOCTL_LOCK_SECRETS UVIO_IOCTL(UVIO_IOCTL_LOCK_SECRETS_NR)
+#define UVIO_IOCTL(nr) _IOWR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb)
+#define UVIO_IOCTL_UVDEV_INFO UVIO_IOCTL(UVIO_IOCTL_UVDEV_INFO_NR)
+#define UVIO_IOCTL_ATT UVIO_IOCTL(UVIO_IOCTL_ATT_NR)
+#define UVIO_IOCTL_ADD_SECRET UVIO_IOCTL(UVIO_IOCTL_ADD_SECRET_NR)
+#define UVIO_IOCTL_LIST_SECRETS UVIO_IOCTL(UVIO_IOCTL_LIST_SECRETS_NR)
+#define UVIO_IOCTL_LOCK_SECRETS UVIO_IOCTL(UVIO_IOCTL_LOCK_SECRETS_NR)
+#define UVIO_IOCTL_RETR_SECRET UVIO_IOCTL(UVIO_IOCTL_RETR_SECRET_NR)
-#define UVIO_SUPP_CALL(nr) (1ULL << (nr))
-#define UVIO_SUPP_UDEV_INFO UVIO_SUPP_CALL(UVIO_IOCTL_UDEV_INFO_NR)
-#define UVIO_SUPP_ATT UVIO_SUPP_CALL(UVIO_IOCTL_ATT_NR)
-#define UVIO_SUPP_ADD_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_ADD_SECRET_NR)
-#define UVIO_SUPP_LIST_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LIST_SECRETS_NR)
-#define UVIO_SUPP_LOCK_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LOCK_SECRETS_NR)
+#define UVIO_SUPP_CALL(nr) (1ULL << (nr))
+#define UVIO_SUPP_UDEV_INFO UVIO_SUPP_CALL(UVIO_IOCTL_UDEV_INFO_NR)
+#define UVIO_SUPP_ATT UVIO_SUPP_CALL(UVIO_IOCTL_ATT_NR)
+#define UVIO_SUPP_ADD_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_ADD_SECRET_NR)
+#define UVIO_SUPP_LIST_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LIST_SECRETS_NR)
+#define UVIO_SUPP_LOCK_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LOCK_SECRETS_NR)
+#define UVIO_SUPP_RETR_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_RETR_SECRET_NR)
#endif /* __S390_ASM_UVDEVICE_H */
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 5529248d84fb..862a9140528e 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -13,7 +13,6 @@
#include <linux/purgatory.h>
#include <linux/pgtable.h>
#include <linux/ftrace.h>
-#include <asm/gmap.h>
#include <asm/stacktrace.h>
int main(void)
@@ -138,7 +137,6 @@ int main(void)
OFFSET(__LC_USER_ASCE, lowcore, user_asce);
OFFSET(__LC_LPP, lowcore, lpp);
OFFSET(__LC_CURRENT_PID, lowcore, current_pid);
- OFFSET(__LC_GMAP, lowcore, gmap);
OFFSET(__LC_LAST_BREAK, lowcore, last_break);
/* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
OFFSET(__LC_DUMP_REIPL, lowcore, ipib);
@@ -161,7 +159,6 @@ int main(void)
OFFSET(__LC_PGM_TDB, lowcore, pgm_tdb);
BLANK();
/* gmap/sie offsets */
- OFFSET(__GMAP_ASCE, gmap, asce);
OFFSET(__SIE_PROG0C, kvm_s390_sie_block, prog0c);
OFFSET(__SIE_PROG20, kvm_s390_sie_block, prog20);
/* kexec_sha_region */
@@ -184,8 +181,8 @@ int main(void)
OFFSET(__FGRAPH_RET_FP, fgraph_ret_regs, fp);
DEFINE(__FGRAPH_RET_SIZE, sizeof(struct fgraph_ret_regs));
#endif
- OFFSET(__FTRACE_REGS_PT_REGS, ftrace_regs, regs);
- DEFINE(__FTRACE_REGS_SIZE, sizeof(struct ftrace_regs));
+ OFFSET(__FTRACE_REGS_PT_REGS, __arch_ftrace_regs, regs);
+ DEFINE(__FTRACE_REGS_SIZE, sizeof(struct __arch_ftrace_regs));
OFFSET(__PCPU_FLAGS, pcpu, flags);
return 0;
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index b210a29d3ee9..2f4174b961de 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -20,6 +20,7 @@
#include <asm/diag.h>
#include <asm/ebcdic.h>
#include <asm/cpcmd.h>
+#include <asm/asm.h>
static DEFINE_SPINLOCK(cpcmd_lock);
static char cpcmd_buf[241];
@@ -45,12 +46,11 @@ static int diag8_response(int cmdlen, char *response, int *rlen)
ry.odd = *rlen;
asm volatile(
" diag %[rx],%[ry],0x8\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=&d" (cc), [ry] "+&d" (ry.pair)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [ry] "+d" (ry.pair)
: [rx] "d" (rx.pair)
- : "cc");
- if (cc)
+ : CC_CLOBBER);
+ if (CC_TRANSFORM(cc))
*rlen += ry.odd;
else
*rlen = ry.odd;
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index edae13416196..cd0c93a8fb8b 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -237,6 +237,17 @@ int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
prot);
}
+/*
+ * Return true only when in a kdump or stand-alone kdump environment.
+ * Note that /proc/vmcore might also be available in "standard zfcp/nvme dump"
+ * environments, where this function returns false; see dump_available().
+ */
+bool is_kdump_kernel(void)
+{
+ return oldmem_data.start;
+}
+EXPORT_SYMBOL_GPL(is_kdump_kernel);
+
static const char *nt_name(Elf64_Word type)
{
const char *name = "LINUX";
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index e62bea9ab21e..de19fd8a6a95 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -38,13 +38,13 @@
typedef struct file_private_info {
loff_t offset; /* offset of last read in file */
- int act_area; /* number of last formated area */
+ int act_area; /* number of last formatted area */
int act_page; /* act page in given area */
- int act_entry; /* last formated entry (offset */
+ int act_entry; /* last formatted entry (offset */
/* relative to beginning of last */
- /* formated page) */
+ /* formatted page) */
size_t act_entry_offset; /* up to this offset we copied */
- /* in last read the last formated */
+ /* in last read the last formatted */
/* entry to userland */
char temp_buf[2048]; /* buffer for output */
debug_info_t *debug_info_org; /* original debug information */
@@ -63,7 +63,7 @@ typedef struct {
long args[];
} debug_sprintf_entry_t;
-/* internal function prototyes */
+/* internal function prototypes */
static int debug_init(void);
static ssize_t debug_output(struct file *file, char __user *user_buf,
@@ -77,12 +77,14 @@ static debug_info_t *debug_info_create(const char *name, int pages_per_area,
static void debug_info_get(debug_info_t *);
static void debug_info_put(debug_info_t *);
static int debug_prolog_level_fn(debug_info_t *id,
- struct debug_view *view, char *out_buf);
+ struct debug_view *view, char *out_buf,
+ size_t out_buf_size);
static int debug_input_level_fn(debug_info_t *id, struct debug_view *view,
struct file *file, const char __user *user_buf,
size_t user_buf_size, loff_t *offset);
static int debug_prolog_pages_fn(debug_info_t *id,
- struct debug_view *view, char *out_buf);
+ struct debug_view *view, char *out_buf,
+ size_t out_buf_size);
static int debug_input_pages_fn(debug_info_t *id, struct debug_view *view,
struct file *file, const char __user *user_buf,
size_t user_buf_size, loff_t *offset);
@@ -90,9 +92,11 @@ static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
struct file *file, const char __user *user_buf,
size_t user_buf_size, loff_t *offset);
static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *in_buf);
+ char *out_buf, size_t out_buf_size,
+ const char *in_buf);
static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *inbuf);
+ char *out_buf, size_t out_buf_size,
+ 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);
@@ -380,7 +384,7 @@ static void debug_info_put(debug_info_t *db_info)
/*
* debug_format_entry:
- * - format one debug entry and return size of formated data
+ * - format one debug entry and return size of formatted data
*/
static int debug_format_entry(file_private_info_t *p_info)
{
@@ -391,8 +395,10 @@ static int debug_format_entry(file_private_info_t *p_info)
if (p_info->act_entry == DEBUG_PROLOG_ENTRY) {
/* print prolog */
- if (view->prolog_proc)
- len += view->prolog_proc(id_snap, view, p_info->temp_buf);
+ if (view->prolog_proc) {
+ len += view->prolog_proc(id_snap, view, p_info->temp_buf,
+ sizeof(p_info->temp_buf));
+ }
goto out;
}
if (!id_snap->areas) /* this is true, if we have a prolog only view */
@@ -402,12 +408,16 @@ static int debug_format_entry(file_private_info_t *p_info)
if (act_entry->clock == 0LL)
goto out; /* empty entry */
- if (view->header_proc)
+ if (view->header_proc) {
len += view->header_proc(id_snap, view, p_info->act_area,
- act_entry, p_info->temp_buf + len);
- if (view->format_proc)
+ act_entry, p_info->temp_buf + len,
+ sizeof(p_info->temp_buf) - len);
+ }
+ if (view->format_proc) {
len += view->format_proc(id_snap, view, p_info->temp_buf + len,
+ sizeof(p_info->temp_buf) - len,
DEBUG_DATA(act_entry));
+ }
out:
return len;
}
@@ -449,7 +459,7 @@ out:
/*
* debug_output:
* - called for user read()
- * - copies formated debug entries to the user buffer
+ * - copies formatted debug entries to the user buffer
*/
static ssize_t debug_output(struct file *file, /* file descriptor */
char __user *user_buf, /* user buffer */
@@ -523,7 +533,7 @@ static ssize_t debug_input(struct file *file, const char __user *user_buf,
/*
* debug_open:
* - called for user open()
- * - copies formated output to private_data area of the file
+ * - copies formatted output to private_data area of the file
* handle
*/
static int debug_open(struct inode *inode, struct file *file)
@@ -1292,9 +1302,9 @@ static inline int debug_get_uint(char *buf)
*/
static int debug_prolog_pages_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf)
+ char *out_buf, size_t out_buf_size)
{
- return sprintf(out_buf, "%i\n", id->pages_per_area);
+ return scnprintf(out_buf, out_buf_size, "%i\n", id->pages_per_area);
}
/*
@@ -1341,14 +1351,14 @@ out:
* prints out actual debug level
*/
static int debug_prolog_level_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf)
+ char *out_buf, size_t out_buf_size)
{
int rc = 0;
if (id->level == DEBUG_OFF_LEVEL)
- rc = sprintf(out_buf, "-\n");
+ rc = scnprintf(out_buf, out_buf_size, "-\n");
else
- rc = sprintf(out_buf, "%i\n", id->level);
+ rc = scnprintf(out_buf, out_buf_size, "%i\n", id->level);
return rc;
}
@@ -1465,22 +1475,24 @@ out:
* prints debug data in hex/ascii format
*/
static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *in_buf)
+ char *out_buf, size_t out_buf_size, const char *in_buf)
{
int i, rc = 0;
- for (i = 0; i < id->buf_size; i++)
- rc += sprintf(out_buf + rc, "%02x ", ((unsigned char *) in_buf)[i]);
- rc += sprintf(out_buf + rc, "| ");
+ for (i = 0; i < id->buf_size; i++) {
+ rc += scnprintf(out_buf + rc, out_buf_size - rc,
+ "%02x ", ((unsigned char *)in_buf)[i]);
+ }
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, "| ");
for (i = 0; i < id->buf_size; i++) {
unsigned char c = in_buf[i];
if (isascii(c) && isprint(c))
- rc += sprintf(out_buf + rc, "%c", c);
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, "%c", c);
else
- rc += sprintf(out_buf + rc, ".");
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, ".");
}
- rc += sprintf(out_buf + rc, "\n");
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, "\n");
return rc;
}
@@ -1488,7 +1500,8 @@ static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
* prints header for debug entry
*/
int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
- int area, debug_entry_t *entry, char *out_buf)
+ int area, debug_entry_t *entry, char *out_buf,
+ size_t out_buf_size)
{
unsigned long sec, usec;
unsigned long caller;
@@ -1505,22 +1518,22 @@ int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
else
except_str = "-";
caller = (unsigned long) entry->caller;
- rc += sprintf(out_buf, "%02i %011ld:%06lu %1u %1s %04u %px ",
- area, sec, usec, level, except_str,
- entry->cpu, (void *)caller);
+ rc += scnprintf(out_buf, out_buf_size, "%02i %011ld:%06lu %1u %1s %04u %px ",
+ area, sec, usec, level, except_str,
+ entry->cpu, (void *)caller);
return rc;
}
EXPORT_SYMBOL(debug_dflt_header_fn);
/*
- * prints debug data sprintf-formated:
+ * prints debug data sprintf-formatted:
* debug_sprinf_event/exception calls must be used together with this view
*/
#define DEBUG_SPRINTF_MAX_ARGS 10
static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *inbuf)
+ char *out_buf, size_t out_buf_size, const char *inbuf)
{
debug_sprintf_entry_t *curr_event = (debug_sprintf_entry_t *)inbuf;
int num_longs, num_used_args = 0, i, rc = 0;
@@ -1533,8 +1546,9 @@ static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
goto out; /* bufsize of entry too small */
if (num_longs == 1) {
/* no args, we use only the string */
- strcpy(out_buf, curr_event->string);
- rc = strlen(curr_event->string);
+ rc = strscpy(out_buf, curr_event->string, out_buf_size);
+ if (rc == -E2BIG)
+ rc = out_buf_size;
goto out;
}
@@ -1546,12 +1560,13 @@ static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
for (i = 0; i < num_used_args; i++)
index[i] = i;
- rc = sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
- curr_event->args[index[1]], curr_event->args[index[2]],
- curr_event->args[index[3]], curr_event->args[index[4]],
- curr_event->args[index[5]], curr_event->args[index[6]],
- curr_event->args[index[7]], curr_event->args[index[8]],
- curr_event->args[index[9]]);
+ rc = scnprintf(out_buf, out_buf_size,
+ curr_event->string, curr_event->args[index[0]],
+ curr_event->args[index[1]], curr_event->args[index[2]],
+ curr_event->args[index[3]], curr_event->args[index[4]],
+ curr_event->args[index[5]], curr_event->args[index[6]],
+ curr_event->args[index[7]], curr_event->args[index[8]],
+ curr_event->args[index[9]]);
out:
return rc;
}
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c
index 007e1795670e..cdd6e31344fa 100644
--- a/arch/s390/kernel/diag.c
+++ b/arch/s390/kernel/diag.c
@@ -16,6 +16,7 @@
#include <asm/diag.h>
#include <asm/trace/diag.h>
#include <asm/sections.h>
+#include <asm/asm.h>
#include "entry.h"
struct diag_stat {
@@ -307,16 +308,15 @@ EXPORT_SYMBOL(diag26c);
int diag49c(unsigned long subcode)
{
- int rc;
+ int cc;
diag_stat_inc(DIAG_STAT_X49C);
asm volatile(
" diag %[subcode],0,0x49c\n"
- " ipm %[rc]\n"
- " srl %[rc],28\n"
- : [rc] "=d" (rc)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
: [subcode] "d" (subcode)
- : "cc");
- return rc;
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc);
}
EXPORT_SYMBOL(diag49c);
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index d6d5317f768e..960c08700cf6 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -222,17 +222,6 @@ SYM_FUNC_START(__sie64a)
lctlg %c1,%c1,__LC_KERNEL_ASCE(%r14) # load primary asce
lg %r14,__LC_CURRENT(%r14)
mvi __TI_sie(%r14),0
-# some program checks are suppressing. C code (e.g. do_protection_exception)
-# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
-# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
-# Other instructions between __sie64a and .Lsie_done should not cause program
-# interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
-.Lrewind_pad6:
- nopr 7
-.Lrewind_pad4:
- nopr 7
-.Lrewind_pad2:
- nopr 7
SYM_INNER_LABEL(sie_exit, SYM_L_GLOBAL)
lg %r14,__SF_SIE_SAVEAREA(%r15) # load guest register save area
stmg %r0,%r13,0(%r14) # save guest gprs 0-13
@@ -244,15 +233,6 @@ SYM_INNER_LABEL(sie_exit, SYM_L_GLOBAL)
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
lg %r2,__SF_SIE_REASON(%r15) # return exit reason code
BR_EX %r14
-.Lsie_fault:
- lghi %r14,-EFAULT
- stg %r14,__SF_SIE_REASON(%r15) # set exit reason code
- j sie_exit
-
- EX_TABLE(.Lrewind_pad6,.Lsie_fault)
- EX_TABLE(.Lrewind_pad4,.Lsie_fault)
- EX_TABLE(.Lrewind_pad2,.Lsie_fault)
- EX_TABLE(sie_exit,.Lsie_fault)
SYM_FUNC_END(__sie64a)
EXPORT_SYMBOL(__sie64a)
EXPORT_SYMBOL(sie_exit)
@@ -327,13 +307,21 @@ SYM_CODE_START(pgm_check_handler)
GET_LC %r13
stpt __LC_SYS_ENTER_TIMER(%r13)
BPOFF
- lgr %r10,%r15
lmg %r8,%r9,__LC_PGM_OLD_PSW(%r13)
+ xgr %r10,%r10
tmhh %r8,0x0001 # coming from user space?
jno .Lpgm_skip_asce
lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13)
j 3f # -> fault in user space
.Lpgm_skip_asce:
+#if IS_ENABLED(CONFIG_KVM)
+ lg %r11,__LC_CURRENT(%r13)
+ tm __TI_sie(%r11),0xff
+ jz 1f
+ BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST
+ SIEEXIT __SF_SIE_CONTROL(%r15),%r13
+ lghi %r10,_PIF_GUEST_FAULT
+#endif
1: tmhh %r8,0x4000 # PER bit set in old PSW ?
jnz 2f # -> enabled, can't be a double fault
tm __LC_PGM_ILC+3(%r13),0x80 # check for per exception
@@ -344,21 +332,12 @@ SYM_CODE_START(pgm_check_handler)
CHECK_VMAP_STACK __LC_SAVE_AREA,%r13,4f
3: lg %r15,__LC_KERNEL_STACK(%r13)
4: la %r11,STACK_FRAME_OVERHEAD(%r15)
- xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
+ stg %r10,__PT_FLAGS(%r11)
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
stmg %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(64,%r11),__LC_SAVE_AREA(%r13)
mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK(%r13)
- stctg %c1,%c1,__PT_CR1(%r11)
-#if IS_ENABLED(CONFIG_KVM)
- ltg %r12,__LC_GMAP(%r13)
- jz 5f
- clc __GMAP_ASCE(8,%r12), __PT_CR1(%r11)
- jne 5f
- BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST
- SIEEXIT __SF_SIE_CONTROL(%r10),%r13
-#endif
-5: stmg %r8,%r9,__PT_PSW(%r11)
+ stmg %r8,%r9,__PT_PSW(%r11)
# clear user controlled registers to prevent speculative use
xgr %r0,%r0
xgr %r1,%r1
@@ -367,6 +346,7 @@ SYM_CODE_START(pgm_check_handler)
xgr %r5,%r5
xgr %r6,%r6
xgr %r7,%r7
+ xgr %r12,%r12
lgr %r2,%r11
brasl %r14,__do_pgm_check
tmhh %r8,0x0001 # returning to user space?
@@ -450,9 +430,13 @@ SYM_CODE_START(\name)
SYM_CODE_END(\name)
.endm
+ .section .irqentry.text, "ax"
+
INT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
INT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
+ .section .kprobes.text, "ax"
+
/*
* Machine check handler routines
*/
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 0b6e62d1d8b8..51439a71e392 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -318,7 +318,7 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
if (bit < 0)
return;
- kmsan_unpoison_memory(fregs, sizeof(*fregs));
+ kmsan_unpoison_memory(fregs, ftrace_regs_size());
regs = ftrace_get_regs(fregs);
p = get_kprobe((kprobe_opcode_t *)ip);
if (!regs || unlikely(!p) || kprobe_disabled(p))
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index f17bb7bf9392..edbb52ce3f1e 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -209,7 +209,7 @@ static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
struct kobj_attribute *attr, \
char *page) \
{ \
- return scnprintf(page, PAGE_SIZE, _format, ##args); \
+ return sysfs_emit(page, _format, ##args); \
}
#define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk) \
@@ -372,7 +372,7 @@ EXPORT_SYMBOL_GPL(ipl_info);
static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
char *page)
{
- return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
+ return sysfs_emit(page, "%s\n", ipl_type_str(ipl_info.type));
}
static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
@@ -380,7 +380,7 @@ static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
static ssize_t ipl_secure_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%i\n", !!ipl_secure_flag);
+ return sysfs_emit(page, "%i\n", !!ipl_secure_flag);
}
static struct kobj_attribute sys_ipl_secure_attr =
@@ -389,7 +389,7 @@ static struct kobj_attribute sys_ipl_secure_attr =
static ssize_t ipl_has_secure_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%i\n", !!sclp.has_sipl);
+ return sysfs_emit(page, "%i\n", !!sclp.has_sipl);
}
static struct kobj_attribute sys_ipl_has_secure_attr =
@@ -402,7 +402,7 @@ static ssize_t ipl_vm_parm_show(struct kobject *kobj,
if (ipl_block_valid && (ipl_block.pb0_hdr.pbt == IPL_PBT_CCW))
ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block);
- return sprintf(page, "%s\n", parm);
+ return sysfs_emit(page, "%s\n", parm);
}
static struct kobj_attribute sys_ipl_vm_parm_attr =
@@ -413,18 +413,18 @@ static ssize_t sys_ipl_device_show(struct kobject *kobj,
{
switch (ipl_info.type) {
case IPL_TYPE_CCW:
- return sprintf(page, "0.%x.%04x\n", ipl_block.ccw.ssid,
- ipl_block.ccw.devno);
+ return sysfs_emit(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);
+ return sysfs_emit(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);
+ return sysfs_emit(page, "0.0.%04x\n", ipl_block.fcp.devno);
case IPL_TYPE_NVME:
case IPL_TYPE_NVME_DUMP:
- return sprintf(page, "%08ux\n", ipl_block.nvme.fid);
+ return sysfs_emit(page, "%08ux\n", ipl_block.nvme.fid);
default:
return 0;
}
@@ -503,12 +503,12 @@ static ssize_t eckd_##_name##_br_chr_show(struct kobject *kobj, \
if (!ipb->br_chr.cyl && \
!ipb->br_chr.head && \
!ipb->br_chr.record) \
- return sprintf(buf, "auto\n"); \
+ return sysfs_emit(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); \
+ return sysfs_emit(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) \
@@ -573,11 +573,11 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
char loadparm[LOADPARM_LEN + 1] = {};
if (!sclp_ipl_info.is_valid)
- return sprintf(page, "#unknown#\n");
+ return sysfs_emit(page, "#unknown#\n");
memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
EBCASC(loadparm, LOADPARM_LEN);
strim(loadparm);
- return sprintf(page, "%s\n", loadparm);
+ return sysfs_emit(page, "%s\n", loadparm);
}
static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
@@ -731,7 +731,7 @@ static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
- return sprintf(page, "%s\n", vmparm);
+ return sysfs_emit(page, "%s\n", vmparm);
}
static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
@@ -839,7 +839,7 @@ static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
char buf[LOADPARM_LEN + 1];
reipl_get_ascii_loadparm(buf, ipb);
- return sprintf(page, "%s\n", buf);
+ return sysfs_emit(page, "%s\n", buf);
}
static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
@@ -895,7 +895,7 @@ DEFINE_GENERIC_LOADPARM(eckd);
static ssize_t reipl_fcp_clear_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%u\n", reipl_fcp_clear);
+ return sysfs_emit(page, "%u\n", reipl_fcp_clear);
}
static ssize_t reipl_fcp_clear_store(struct kobject *kobj,
@@ -963,7 +963,7 @@ static struct attribute_group reipl_nvme_attr_group = {
static ssize_t reipl_nvme_clear_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%u\n", reipl_nvme_clear);
+ return sysfs_emit(page, "%u\n", reipl_nvme_clear);
}
static ssize_t reipl_nvme_clear_store(struct kobject *kobj,
@@ -984,7 +984,7 @@ DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw);
static ssize_t reipl_ccw_clear_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%u\n", reipl_ccw_clear);
+ return sysfs_emit(page, "%u\n", reipl_ccw_clear);
}
static ssize_t reipl_ccw_clear_store(struct kobject *kobj,
@@ -1056,7 +1056,7 @@ static struct attribute_group reipl_eckd_attr_group = {
static ssize_t reipl_eckd_clear_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%u\n", reipl_eckd_clear);
+ return sysfs_emit(page, "%u\n", reipl_eckd_clear);
}
static ssize_t reipl_eckd_clear_store(struct kobject *kobj,
@@ -1086,7 +1086,7 @@ static ssize_t reipl_nss_name_show(struct kobject *kobj,
char nss_name[NSS_NAME_SIZE + 1] = {};
reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
- return sprintf(page, "%s\n", nss_name);
+ return sysfs_emit(page, "%s\n", nss_name);
}
static ssize_t reipl_nss_name_store(struct kobject *kobj,
@@ -1171,7 +1171,7 @@ static int reipl_set_type(enum ipl_type type)
static ssize_t reipl_type_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%s\n", ipl_type_str(reipl_type));
+ return sysfs_emit(page, "%s\n", ipl_type_str(reipl_type));
}
static ssize_t reipl_type_store(struct kobject *kobj,
@@ -1692,7 +1692,7 @@ static int dump_set_type(enum dump_type type)
static ssize_t dump_type_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%s\n", dump_type_str(dump_type));
+ return sysfs_emit(page, "%s\n", dump_type_str(dump_type));
}
static ssize_t dump_type_store(struct kobject *kobj,
@@ -1717,6 +1717,24 @@ static ssize_t dump_type_store(struct kobject *kobj,
static struct kobj_attribute dump_type_attr =
__ATTR(dump_type, 0644, dump_type_show, dump_type_store);
+static ssize_t dump_area_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *page)
+{
+ return sysfs_emit(page, "%lu\n", sclp.hsa_size);
+}
+
+static struct kobj_attribute dump_area_size_attr = __ATTR_RO(dump_area_size);
+
+static struct attribute *dump_attrs[] = {
+ &dump_type_attr.attr,
+ &dump_area_size_attr.attr,
+ NULL,
+};
+
+static struct attribute_group dump_attr_group = {
+ .attrs = dump_attrs,
+};
+
static struct kset *dump_kset;
static void diag308_dump(void *dump_block)
@@ -1853,7 +1871,7 @@ static int __init dump_init(void)
dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
if (!dump_kset)
return -ENOMEM;
- rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
+ rc = sysfs_create_group(&dump_kset->kobj, &dump_attr_group);
if (rc) {
kset_unregister(dump_kset);
return rc;
@@ -2034,7 +2052,7 @@ static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
static ssize_t on_reboot_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%s\n", on_reboot_trigger.action->name);
+ return sysfs_emit(page, "%s\n", on_reboot_trigger.action->name);
}
static ssize_t on_reboot_store(struct kobject *kobj,
@@ -2060,7 +2078,7 @@ static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
static ssize_t on_panic_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%s\n", on_panic_trigger.action->name);
+ return sysfs_emit(page, "%s\n", on_panic_trigger.action->name);
}
static ssize_t on_panic_store(struct kobject *kobj,
@@ -2086,7 +2104,7 @@ static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR,
static ssize_t on_restart_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%s\n", on_restart_trigger.action->name);
+ return sysfs_emit(page, "%s\n", on_restart_trigger.action->name);
}
static ssize_t on_restart_store(struct kobject *kobj,
@@ -2122,7 +2140,7 @@ static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
static ssize_t on_halt_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%s\n", on_halt_trigger.action->name);
+ return sysfs_emit(page, "%s\n", on_halt_trigger.action->name);
}
static ssize_t on_halt_store(struct kobject *kobj,
@@ -2148,7 +2166,7 @@ static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
static ssize_t on_poff_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
- return sprintf(page, "%s\n", on_poff_trigger.action->name);
+ return sysfs_emit(page, "%s\n", on_poff_trigger.action->name);
}
static ssize_t on_poff_store(struct kobject *kobj,
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 2639a3d12736..ef7be599e1f7 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -30,6 +30,7 @@
#include <asm/stacktrace.h>
#include <asm/softirq_stack.h>
#include <asm/vtime.h>
+#include <asm/asm.h>
#include "entry.h"
DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
@@ -129,9 +130,13 @@ static int irq_pending(struct pt_regs *regs)
{
int cc;
- asm volatile("tpi 0\n"
- "ipm %0" : "=d" (cc) : : "cc");
- return cc >> 28;
+ asm volatile(
+ " tpi 0\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
+ :
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc);
}
void noinstr do_io_irq(struct pt_regs *regs)
@@ -253,7 +258,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
goto out;
}
- if (index < nr_irqs) {
+ if (index < irq_get_nr_irqs()) {
show_msi_interrupt(p, index);
goto out;
}
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 6295faf0987d..8b80ea57125f 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -489,6 +489,12 @@ int __init arch_init_kprobes(void)
return 0;
}
+int __init arch_populate_kprobe_blacklist(void)
+{
+ return kprobe_add_area_blacklist((unsigned long)__irqentry_text_start,
+ (unsigned long)__irqentry_text_end);
+}
+
int arch_trampoline_kprobe(struct kprobe *p)
{
return 0;
diff --git a/arch/s390/kernel/nospec-sysfs.c b/arch/s390/kernel/nospec-sysfs.c
index a95188818637..5970dd3ee7c5 100644
--- a/arch/s390/kernel/nospec-sysfs.c
+++ b/arch/s390/kernel/nospec-sysfs.c
@@ -7,17 +7,17 @@
ssize_t cpu_show_spectre_v1(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+ return sysfs_emit(buf, "Mitigation: __user pointer sanitization\n");
}
ssize_t cpu_show_spectre_v2(struct device *dev,
struct device_attribute *attr, char *buf)
{
if (test_facility(156))
- return sprintf(buf, "Mitigation: etokens\n");
+ return sysfs_emit(buf, "Mitigation: etokens\n");
if (nospec_uses_trampoline())
- return sprintf(buf, "Mitigation: execute trampolines\n");
+ return sysfs_emit(buf, "Mitigation: execute trampolines\n");
if (nobp_enabled())
- return sprintf(buf, "Mitigation: limited branch prediction\n");
- return sprintf(buf, "Vulnerable\n");
+ return sysfs_emit(buf, "Mitigation: limited branch prediction\n");
+ return sysfs_emit(buf, "Vulnerable\n");
}
diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c
index b695f980bbde..29080d6d5d8d 100644
--- a/arch/s390/kernel/os_info.c
+++ b/arch/s390/kernel/os_info.c
@@ -180,7 +180,7 @@ fail:
}
/*
- * Return pointer to os infor entry and its size
+ * Return pointer to os info entry and its size
*/
void *os_info_old_entry(int nr, unsigned long *size)
{
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
index e2e0aa463fbd..b0bc68da6a11 100644
--- a/arch/s390/kernel/perf_cpum_cf.c
+++ b/arch/s390/kernel/perf_cpum_cf.c
@@ -835,7 +835,7 @@ static int __hw_perf_event_init(struct perf_event *event, unsigned int type)
return validate_ctr_version(hwc->config, set);
}
-/* Events CPU_CYLCES and INSTRUCTIONS can be submitted with two different
+/* Events CPU_CYCLES and INSTRUCTIONS can be submitted with two different
* attribute::type values:
* - PERF_TYPE_HARDWARE:
* - pmu->type:
@@ -879,8 +879,8 @@ static int hw_perf_event_reset(struct perf_event *event)
u64 prev, new;
int err;
+ prev = local64_read(&event->hw.prev_count);
do {
- prev = local64_read(&event->hw.prev_count);
err = ecctr(event->hw.config, &new);
if (err) {
if (err != 3)
@@ -892,7 +892,7 @@ static int hw_perf_event_reset(struct perf_event *event)
*/
new = 0;
}
- } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev);
+ } while (!local64_try_cmpxchg(&event->hw.prev_count, &prev, new));
return err;
}
@@ -902,12 +902,12 @@ static void hw_perf_event_update(struct perf_event *event)
u64 prev, new, delta;
int err;
+ prev = local64_read(&event->hw.prev_count);
do {
- prev = local64_read(&event->hw.prev_count);
err = ecctr(event->hw.config, &new);
if (err)
return;
- } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev);
+ } while (!local64_try_cmpxchg(&event->hw.prev_count, &prev, new));
delta = (prev <= new) ? new - prev
: (-1ULL - prev) + new + 1; /* overflow */
@@ -1054,7 +1054,7 @@ static void cpumf_pmu_del(struct perf_event *event, int flags)
*
* When a new perf event has been added but not yet started, this can
* clear enable control and resets all counters in a set. Therefore,
- * cpumf_pmu_start() always has to reenable a counter set.
+ * cpumf_pmu_start() always has to re-enable a counter set.
*/
for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i)
if (!atomic_read(&cpuhw->ctr_set[i]))
@@ -1863,7 +1863,7 @@ static const struct attribute_group *cfdiag_attr_groups[] = {
/* Performance monitoring unit for event CF_DIAG. Since this event
* is also started and stopped via the perf_event_open() system call, use
* the same event enable/disable call back functions. They do not
- * have a pointer to the perf_event strcture as first parameter.
+ * have a pointer to the perf_event structure as first parameter.
*
* The functions XXX_add, XXX_del, XXX_start and XXX_stop are also common.
* Reuse them and distinguish the event (always first parameter) via
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
index 5b765e3ccf0c..1e99514fb7ae 100644
--- a/arch/s390/kernel/perf_cpum_sf.c
+++ b/arch/s390/kernel/perf_cpum_sf.c
@@ -180,39 +180,27 @@ static int sf_buffer_available(struct cpu_hw_sf *cpuhw)
*/
static void free_sampling_buffer(struct sf_buffer *sfb)
{
- unsigned long *sdbt, *curr;
-
- if (!sfb->sdbt)
- return;
+ unsigned long *sdbt, *curr, *head;
sdbt = sfb->sdbt;
- curr = sdbt;
-
+ if (!sdbt)
+ return;
+ sfb->sdbt = NULL;
/* Free the SDBT after all SDBs are processed... */
- while (1) {
- if (!*curr || !sdbt)
- break;
-
- /* Process table-link entries */
+ head = sdbt;
+ curr = sdbt;
+ do {
if (is_link_entry(curr)) {
+ /* Process table-link entries */
curr = get_next_sdbt(curr);
- if (sdbt)
- free_page((unsigned long)sdbt);
-
- /* If the origin is reached, sampling buffer is freed */
- if (curr == sfb->sdbt)
- break;
- else
- sdbt = curr;
+ free_page((unsigned long)sdbt);
+ sdbt = curr;
} else {
/* Process SDB pointer */
- if (*curr) {
- free_page((unsigned long)phys_to_virt(*curr));
- curr++;
- }
+ free_page((unsigned long)phys_to_virt(*curr));
+ curr++;
}
- }
-
+ } while (curr != head);
memset(sfb, 0, sizeof(*sfb));
}
@@ -404,7 +392,7 @@ static void sfb_init_allocs(unsigned long num, struct hw_perf_event *hwc)
static void deallocate_buffers(struct cpu_hw_sf *cpuhw)
{
- if (cpuhw->sfb.sdbt)
+ if (sf_buffer_available(cpuhw))
free_sampling_buffer(&cpuhw->sfb);
}
@@ -559,16 +547,15 @@ static void setup_pmc_cpu(void *flags)
{
struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf);
+ sf_disable();
switch (*((int *)flags)) {
case PMC_INIT:
memset(cpuhw, 0, sizeof(*cpuhw));
qsi(&cpuhw->qsi);
cpuhw->flags |= PMU_F_RESERVED;
- sf_disable();
break;
case PMC_RELEASE:
cpuhw->flags &= ~PMU_F_RESERVED;
- sf_disable();
deallocate_buffers(cpuhw);
break;
}
@@ -759,7 +746,6 @@ static int __hw_perf_event_init(struct perf_event *event)
reserve_pmc_hardware();
refcount_set(&num_events, 1);
}
- mutex_unlock(&pmc_reserve_mutex);
event->destroy = hw_perf_event_destroy;
/* Access per-CPU sampling information (query sampling info) */
@@ -818,7 +804,7 @@ static int __hw_perf_event_init(struct perf_event *event)
/* Use AUX buffer. No need to allocate it by ourself */
if (attr->config == PERF_EVENT_CPUM_SF_DIAG)
- return 0;
+ goto out;
/* Allocate the per-CPU sampling buffer using the CPU information
* from the event. If the event is not pinned to a particular
@@ -848,6 +834,7 @@ static int __hw_perf_event_init(struct perf_event *event)
if (is_default_overflow_handler(event))
event->overflow_handler = cpumsf_output_event_pid;
out:
+ mutex_unlock(&pmc_reserve_mutex);
return err;
}
@@ -910,10 +897,14 @@ static void cpumsf_pmu_enable(struct pmu *pmu)
struct hw_perf_event *hwc;
int err;
- if (cpuhw->flags & PMU_F_ENABLED)
- return;
-
- if (cpuhw->flags & PMU_F_ERR_MASK)
+ /*
+ * Event must be
+ * - added/started on this CPU (PMU_F_IN_USE set)
+ * - and CPU must be available (PMU_F_RESERVED set)
+ * - and not already enabled (PMU_F_ENABLED not set)
+ * - and not in error condition (PMU_F_ERR_MASK not set)
+ */
+ if (cpuhw->flags != (PMU_F_IN_USE | PMU_F_RESERVED))
return;
/* Check whether to extent the sampling buffer.
@@ -927,33 +918,27 @@ static void cpumsf_pmu_enable(struct pmu *pmu)
* facility, but it can be fully re-enabled using sampling controls that
* have been saved in cpumsf_pmu_disable().
*/
- if (cpuhw->event) {
- hwc = &cpuhw->event->hw;
- if (!(SAMPL_DIAG_MODE(hwc))) {
- /*
- * Account number of overflow-designated
- * buffer extents
- */
- sfb_account_overflows(cpuhw, hwc);
- extend_sampling_buffer(&cpuhw->sfb, hwc);
- }
- /* Rate may be adjusted with ioctl() */
- cpuhw->lsctl.interval = SAMPL_RATE(hwc);
+ hwc = &cpuhw->event->hw;
+ if (!(SAMPL_DIAG_MODE(hwc))) {
+ /*
+ * Account number of overflow-designated buffer extents
+ */
+ sfb_account_overflows(cpuhw, hwc);
+ extend_sampling_buffer(&cpuhw->sfb, hwc);
}
+ /* Rate may be adjusted with ioctl() */
+ cpuhw->lsctl.interval = SAMPL_RATE(hwc);
/* (Re)enable the PMU and sampling facility */
- cpuhw->flags |= PMU_F_ENABLED;
- barrier();
-
err = lsctl(&cpuhw->lsctl);
if (err) {
- cpuhw->flags &= ~PMU_F_ENABLED;
pr_err("Loading sampling controls failed: op 1 err %i\n", err);
return;
}
/* Load current program parameter */
lpp(&get_lowcore()->lpp);
+ cpuhw->flags |= PMU_F_ENABLED;
}
static void cpumsf_pmu_disable(struct pmu *pmu)
@@ -1191,8 +1176,8 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
static void hw_perf_event_update(struct perf_event *event, int flush_all)
{
unsigned long long event_overflow, sampl_overflow, num_sdb;
- union hws_trailer_header old, prev, new;
struct hw_perf_event *hwc = &event->hw;
+ union hws_trailer_header prev, new;
struct hws_trailer_entry *te;
unsigned long *sdbt, sdb;
int done;
@@ -1236,13 +1221,11 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
/* Reset trailer (using compare-double-and-swap) */
prev.val = READ_ONCE_ALIGNED_128(te->header.val);
do {
- old.val = prev.val;
new.val = prev.val;
new.f = 0;
new.a = 1;
new.overflow = 0;
- prev.val = cmpxchg128(&te->header.val, old.val, new.val);
- } while (prev.val != old.val);
+ } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val));
/* Advance to next sample-data-block */
sdbt++;
@@ -1408,16 +1391,15 @@ static int aux_output_begin(struct perf_output_handle *handle,
static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
unsigned long long *overflow)
{
- union hws_trailer_header old, prev, new;
+ union hws_trailer_header prev, new;
struct hws_trailer_entry *te;
te = aux_sdb_trailer(aux, alert_index);
prev.val = READ_ONCE_ALIGNED_128(te->header.val);
do {
- old.val = prev.val;
new.val = prev.val;
- *overflow = old.overflow;
- if (old.f) {
+ *overflow = prev.overflow;
+ if (prev.f) {
/*
* SDB is already set by hardware.
* Abort and try to set somewhere
@@ -1427,8 +1409,7 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
}
new.a = 1;
new.overflow = 0;
- prev.val = cmpxchg128(&te->header.val, old.val, new.val);
- } while (prev.val != old.val);
+ } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val));
return true;
}
@@ -1457,7 +1438,7 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
unsigned long long *overflow)
{
- union hws_trailer_header old, prev, new;
+ union hws_trailer_header prev, new;
unsigned long i, range_scan, idx;
unsigned long long orig_overflow;
struct hws_trailer_entry *te;
@@ -1489,17 +1470,15 @@ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
te = aux_sdb_trailer(aux, idx);
prev.val = READ_ONCE_ALIGNED_128(te->header.val);
do {
- old.val = prev.val;
new.val = prev.val;
- orig_overflow = old.overflow;
+ orig_overflow = prev.overflow;
new.f = 0;
new.overflow = 0;
if (idx == aux->alert_mark)
new.a = 1;
else
new.a = 0;
- prev.val = cmpxchg128(&te->header.val, old.val, new.val);
- } while (prev.val != old.val);
+ } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val));
*overflow += orig_overflow;
}
@@ -1780,7 +1759,9 @@ static void cpumsf_pmu_stop(struct perf_event *event, int flags)
event->hw.state |= PERF_HES_STOPPED;
if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) {
- hw_perf_event_update(event, 1);
+ /* CPU hotplug off removes SDBs. No samples to extract. */
+ if (cpuhw->flags & PMU_F_RESERVED)
+ hw_perf_event_update(event, 1);
event->hw.state |= PERF_HES_UPTODATE;
}
perf_pmu_enable(event->pmu);
@@ -1795,7 +1776,7 @@ static int cpumsf_pmu_add(struct perf_event *event, int flags)
if (cpuhw->flags & PMU_F_IN_USE)
return -EAGAIN;
- if (!SAMPL_DIAG_MODE(&event->hw) && !cpuhw->sfb.sdbt)
+ if (!SAMPL_DIAG_MODE(&event->hw) && !sf_buffer_available(cpuhw))
return -EINVAL;
perf_pmu_disable(event->pmu);
@@ -1957,13 +1938,12 @@ static void cpumf_measurement_alert(struct ext_code ext_code,
/* Program alert request */
if (alert & CPU_MF_INT_SF_PRA) {
- if (cpuhw->flags & PMU_F_IN_USE)
+ if (cpuhw->flags & PMU_F_IN_USE) {
if (SAMPL_DIAG_MODE(&cpuhw->event->hw))
hw_collect_aux(cpuhw);
else
hw_perf_event_update(cpuhw->event, 0);
- else
- WARN_ON_ONCE(!(cpuhw->flags & PMU_F_IN_USE));
+ }
}
/* Report measurement alerts only for non-PRA codes */
@@ -1984,7 +1964,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code,
/* Invalid sampling buffer entry */
if (alert & (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE)) {
- pr_err("A sampling buffer entry is incorrect (alert=0x%x)\n",
+ pr_err("A sampling buffer entry is incorrect (alert=%#x)\n",
alert);
cpuhw->flags |= PMU_F_ERR_IBE;
sf_disable();
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c
index 5fff629b1a89..2b9611c4718e 100644
--- a/arch/s390/kernel/perf_event.c
+++ b/arch/s390/kernel/perf_event.c
@@ -57,7 +57,7 @@ static unsigned long instruction_pointer_guest(struct pt_regs *regs)
return sie_block(regs)->gpsw.addr;
}
-unsigned long perf_instruction_pointer(struct pt_regs *regs)
+unsigned long perf_arch_instruction_pointer(struct pt_regs *regs)
{
return is_in_guest(regs) ? instruction_pointer_guest(regs)
: instruction_pointer(regs);
@@ -84,7 +84,7 @@ static unsigned long perf_misc_flags_sf(struct pt_regs *regs)
return flags;
}
-unsigned long perf_misc_flags(struct pt_regs *regs)
+unsigned long perf_arch_misc_flags(struct pt_regs *regs)
{
/* Check if the cpum_sf PMU has created the pt_regs structure.
* In this case, perf misc flags can be easily extracted. Otherwise,
@@ -228,5 +228,5 @@ ssize_t cpumf_events_sysfs_show(struct device *dev,
struct perf_pmu_events_attr *pmu_attr;
pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
- return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
+ return sysfs_emit(page, "event=0x%04llx\n", pmu_attr->id);
}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 4df56fdb2488..822d8e6f8717 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -574,7 +574,7 @@ int smp_store_status(int cpu)
/*
* Collect CPU state of the previous, crashed system.
- * There are four cases:
+ * There are three cases:
* 1) standard zfcp/nvme dump
* condition: OLDMEM_BASE == NULL && is_ipl_type_dump() == true
* The state for all CPUs except the boot CPU needs to be collected
@@ -587,16 +587,16 @@ int smp_store_status(int cpu)
* with sigp stop-and-store-status. The firmware or the boot-loader
* stored the registers of the boot CPU in the absolute lowcore in the
* memory of the old system.
- * 3) kdump and the old kernel did not store the CPU state,
- * or stand-alone kdump for DASD
- * condition: OLDMEM_BASE != NULL && !is_kdump_kernel()
+ * 3) kdump or stand-alone kdump for DASD
+ * condition: OLDMEM_BASE != NULL && is_ipl_type_dump() == false
* The state for all CPUs except the boot CPU needs to be collected
* with sigp stop-and-store-status. The kexec code or the boot-loader
* stored the registers of the boot CPU in the memory of the old system.
- * 4) kdump and the old kernel stored the CPU state
- * condition: OLDMEM_BASE != NULL && is_kdump_kernel()
- * This case does not exist for s390 anymore, setup_arch explicitly
- * deactivates the elfcorehdr= kernel parameter
+ *
+ * Note that the legacy kdump mode where the old kernel stored the CPU states
+ * does no longer exist: setup_arch() explicitly deactivates the elfcorehdr=
+ * kernel parameter. The is_kdump_kernel() implementation on s390 is independent
+ * of the elfcorehdr= parameter.
*/
static bool dump_available(void)
{
@@ -1011,7 +1011,7 @@ static ssize_t cpu_configure_show(struct device *dev,
ssize_t count;
mutex_lock(&smp_cpu_state_mutex);
- count = sprintf(buf, "%d\n", per_cpu(pcpu_devices, dev->id).state);
+ count = sysfs_emit(buf, "%d\n", per_cpu(pcpu_devices, dev->id).state);
mutex_unlock(&smp_cpu_state_mutex);
return count;
}
@@ -1083,7 +1083,7 @@ static DEVICE_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
static ssize_t show_cpu_address(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", per_cpu(pcpu_devices, dev->id).address);
+ return sysfs_emit(buf, "%d\n", per_cpu(pcpu_devices, dev->id).address);
}
static DEVICE_ATTR(address, 0444, show_cpu_address, NULL);
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 9f59837d159e..40edfde25f5b 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -151,7 +151,7 @@ void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *coo
break;
}
if (!store_ip(consume_entry, cookie, entry, perf, ip))
- return;
+ break;
first = false;
}
pagefault_enable();
diff --git a/arch/s390/kernel/sthyi.c b/arch/s390/kernel/sthyi.c
index 1cf2ad04f8e9..d40f0b983e74 100644
--- a/arch/s390/kernel/sthyi.c
+++ b/arch/s390/kernel/sthyi.c
@@ -17,6 +17,7 @@
#include <asm/ebcdic.h>
#include <asm/facility.h>
#include <asm/sthyi.h>
+#include <asm/asm.h>
#include "entry.h"
#define DED_WEIGHT 0xffff
@@ -425,13 +426,12 @@ static int sthyi(u64 vaddr, u64 *rc)
asm volatile(
".insn rre,0xB2560000,%[r1],%[r2]\n"
- "ipm %[cc]\n"
- "srl %[cc],28\n"
- : [cc] "=&d" (cc), [r2] "+&d" (r2.pair)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [r2] "+&d" (r2.pair)
: [r1] "d" (r1.pair)
- : "memory", "cc");
+ : CC_CLOBBER_LIST("memory"));
*rc = r2.odd;
- return cc;
+ return CC_TRANSFORM(cc);
}
static int fill_dst(void *dst, u64 *rc)
diff --git a/arch/s390/kernel/syscalls/Makefile b/arch/s390/kernel/syscalls/Makefile
index 1bb78b9468e8..c5d958a09ff4 100644
--- a/arch/s390/kernel/syscalls/Makefile
+++ b/arch/s390/kernel/syscalls/Makefile
@@ -12,7 +12,7 @@ kapi-hdrs-y := $(kapi)/unistd_nr.h
uapi-hdrs-y := $(uapi)/unistd_32.h
uapi-hdrs-y += $(uapi)/unistd_64.h
-targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y))
+targets += $(addprefix ../../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y))
PHONY += kapi uapi
@@ -23,23 +23,26 @@ uapi: $(uapi-hdrs-y)
# Create output directory if not already present
$(shell mkdir -p $(uapi) $(kapi))
-filechk_syshdr = $(CONFIG_SHELL) '$(systbl)' -H -a $(syshdr_abi_$(basetarget)) -f "$2" < $<
+quiet_cmd_syshdr = SYSHDR $@
+ cmd_syshdr = $(CONFIG_SHELL) '$(systbl)' -H -a $(syshdr_abi_$(basetarget)) -f "$@" < $< > $@
-filechk_sysnr = $(CONFIG_SHELL) '$(systbl)' -N -a $(sysnr_abi_$(basetarget)) < $<
+quiet_cmd_sysnr = SYSNR $@
+ cmd_sysnr = $(CONFIG_SHELL) '$(systbl)' -N -a $(sysnr_abi_$(basetarget)) < $< > $@
-filechk_syscalls = $(CONFIG_SHELL) '$(systbl)' -S < $<
+quiet_cmd_syscalls = SYSTBL $@
+ cmd_syscalls = $(CONFIG_SHELL) '$(systbl)' -S < $< > $@
syshdr_abi_unistd_32 := common,32
-$(uapi)/unistd_32.h: $(syscall) FORCE
- $(call filechk,syshdr,$@)
+$(uapi)/unistd_32.h: $(syscall) $(systbl) FORCE
+ $(call if_changed,syshdr)
syshdr_abi_unistd_64 := common,64
-$(uapi)/unistd_64.h: $(syscall) FORCE
- $(call filechk,syshdr,$@)
+$(uapi)/unistd_64.h: $(syscall) $(systbl) FORCE
+ $(call if_changed,syshdr)
-$(kapi)/syscall_table.h: $(syscall) FORCE
- $(call filechk,syscalls)
+$(kapi)/syscall_table.h: $(syscall) $(systbl) FORCE
+ $(call if_changed,syscalls)
sysnr_abi_unistd_nr := common,32,64
-$(kapi)/unistd_nr.h: $(syscall) FORCE
- $(call filechk,sysnr)
+$(kapi)/unistd_nr.h: $(syscall) $(systbl) FORCE
+ $(call if_changed,sysnr)
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index 01071182763e..e9115b4d8b63 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -465,3 +465,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal sys_mseal
+463 common setxattrat sys_setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat sys_removexattrat
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index b713effe0579..34a65c141ea0 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -36,7 +36,6 @@
#include <linux/profile.h>
#include <linux/timex.h>
#include <linux/notifier.h>
-#include <linux/timekeeper_internal.h>
#include <linux/clockchips.h>
#include <linux/gfp.h>
#include <linux/kprobes.h>
@@ -255,6 +254,7 @@ static struct clocksource clocksource_tod = {
.shift = 24,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
.vdso_clock_mode = VDSO_CLOCKMODE_TOD,
+ .id = CSID_S390_TOD,
};
struct clocksource * __init clocksource_default_clock(void)
@@ -468,6 +468,12 @@ static void __init stp_reset(void)
}
}
+bool stp_enabled(void)
+{
+ return test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags) && stp_online;
+}
+EXPORT_SYMBOL(stp_enabled);
+
static void stp_timeout(struct timer_list *unused)
{
queue_work(time_sync_wq, &stp_work);
@@ -729,8 +735,8 @@ static ssize_t ctn_id_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid())
- ret = sprintf(buf, "%016lx\n",
- *(unsigned long *) stp_info.ctnid);
+ ret = sysfs_emit(buf, "%016lx\n",
+ *(unsigned long *)stp_info.ctnid);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -745,7 +751,7 @@ static ssize_t ctn_type_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid())
- ret = sprintf(buf, "%i\n", stp_info.ctn);
+ ret = sysfs_emit(buf, "%i\n", stp_info.ctn);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -760,7 +766,7 @@ static ssize_t dst_offset_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid() && (stp_info.vbits & 0x2000))
- ret = sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
+ ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.dsto);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -775,7 +781,7 @@ static ssize_t leap_seconds_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid() && (stp_info.vbits & 0x8000))
- ret = sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
+ ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.leaps);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -801,11 +807,11 @@ static ssize_t leap_seconds_scheduled_show(struct device *dev,
return ret;
if (!stzi.lsoib.p)
- return sprintf(buf, "0,0\n");
+ return sysfs_emit(buf, "0,0\n");
- return sprintf(buf, "%lu,%d\n",
- tod_to_ns(stzi.lsoib.nlsout - TOD_UNIX_EPOCH) / NSEC_PER_SEC,
- stzi.lsoib.nlso - stzi.lsoib.also);
+ return sysfs_emit(buf, "%lu,%d\n",
+ tod_to_ns(stzi.lsoib.nlsout - TOD_UNIX_EPOCH) / NSEC_PER_SEC,
+ stzi.lsoib.nlso - stzi.lsoib.also);
}
static DEVICE_ATTR_RO(leap_seconds_scheduled);
@@ -818,7 +824,7 @@ static ssize_t stratum_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid())
- ret = sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
+ ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.stratum);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -833,7 +839,7 @@ static ssize_t time_offset_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid() && (stp_info.vbits & 0x0800))
- ret = sprintf(buf, "%i\n", (int) stp_info.tto);
+ ret = sysfs_emit(buf, "%i\n", (int)stp_info.tto);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -848,7 +854,7 @@ static ssize_t time_zone_offset_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid() && (stp_info.vbits & 0x4000))
- ret = sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
+ ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.tzo);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -863,7 +869,7 @@ static ssize_t timing_mode_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid())
- ret = sprintf(buf, "%i\n", stp_info.tmd);
+ ret = sysfs_emit(buf, "%i\n", stp_info.tmd);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -878,7 +884,7 @@ static ssize_t timing_state_show(struct device *dev,
mutex_lock(&stp_mutex);
if (stpinfo_valid())
- ret = sprintf(buf, "%i\n", stp_info.tst);
+ ret = sysfs_emit(buf, "%i\n", stp_info.tst);
mutex_unlock(&stp_mutex);
return ret;
}
@@ -889,7 +895,7 @@ static ssize_t online_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%i\n", stp_online);
+ return sysfs_emit(buf, "%i\n", stp_online);
}
static ssize_t online_store(struct device *dev,
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 813e5da9a973..4f9c301a705b 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -26,6 +26,7 @@
#include <linux/node.h>
#include <asm/hiperdispatch.h>
#include <asm/sysinfo.h>
+#include <asm/asm.h>
#define PTF_HORIZONTAL (0UL)
#define PTF_VERTICAL (1UL)
@@ -224,15 +225,15 @@ static void topology_update_polarization_simple(void)
static int ptf(unsigned long fc)
{
- int rc;
+ int cc;
asm volatile(
- " .insn rre,0xb9a20000,%1,%1\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (rc)
- : "d" (fc) : "cc");
- return rc;
+ " .insn rre,0xb9a20000,%[fc],%[fc]\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
+ : [fc] "d" (fc)
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc);
}
int topology_set_cpu_management(int fc)
@@ -412,7 +413,7 @@ static ssize_t dispatching_show(struct device *dev,
ssize_t count;
mutex_lock(&smp_cpu_state_mutex);
- count = sprintf(buf, "%d\n", cpu_management);
+ count = sysfs_emit(buf, "%d\n", cpu_management);
mutex_unlock(&smp_cpu_state_mutex);
return count;
}
@@ -443,19 +444,19 @@ static ssize_t cpu_polarization_show(struct device *dev,
mutex_lock(&smp_cpu_state_mutex);
switch (smp_cpu_get_polarization(cpu)) {
case POLARIZATION_HRZ:
- count = sprintf(buf, "horizontal\n");
+ count = sysfs_emit(buf, "horizontal\n");
break;
case POLARIZATION_VL:
- count = sprintf(buf, "vertical:low\n");
+ count = sysfs_emit(buf, "vertical:low\n");
break;
case POLARIZATION_VM:
- count = sprintf(buf, "vertical:medium\n");
+ count = sysfs_emit(buf, "vertical:medium\n");
break;
case POLARIZATION_VH:
- count = sprintf(buf, "vertical:high\n");
+ count = sysfs_emit(buf, "vertical:high\n");
break;
default:
- count = sprintf(buf, "unknown\n");
+ count = sysfs_emit(buf, "unknown\n");
break;
}
mutex_unlock(&smp_cpu_state_mutex);
@@ -479,7 +480,7 @@ static ssize_t cpu_dedicated_show(struct device *dev,
ssize_t count;
mutex_lock(&smp_cpu_state_mutex);
- count = sprintf(buf, "%d\n", topology_cpu_dedicated(cpu));
+ count = sysfs_emit(buf, "%d\n", topology_cpu_dedicated(cpu));
mutex_unlock(&smp_cpu_state_mutex);
return count;
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 160b2acba8db..24fee11b030d 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -31,6 +31,7 @@
#include <asm/asm-extable.h>
#include <asm/vtime.h>
#include <asm/fpu.h>
+#include <asm/fault.h>
#include "entry.h"
static inline void __user *get_trap_ip(struct pt_regs *regs)
@@ -317,9 +318,24 @@ void noinstr __do_pgm_check(struct pt_regs *regs)
struct lowcore *lc = get_lowcore();
irqentry_state_t state;
unsigned int trapnr;
+ union teid teid;
+ teid.val = lc->trans_exc_code;
regs->int_code = lc->pgm_int_code;
- regs->int_parm_long = lc->trans_exc_code;
+ regs->int_parm_long = teid.val;
+
+ /*
+ * In case of a guest fault, short-circuit the fault handler and return.
+ * This way the sie64a() function will return 0; fault address and
+ * other relevant bits are saved in current->thread.gmap_teid, and
+ * the fault number in current->thread.gmap_int_code. KVM will be
+ * able to use this information to handle the fault.
+ */
+ if (test_pt_regs_flag(regs, PIF_GUEST_FAULT)) {
+ current->thread.gmap_teid.val = regs->int_parm_long;
+ current->thread.gmap_int_code = regs->int_code & 0xffff;
+ return;
+ }
state = irqentry_enter(regs);
@@ -408,8 +424,8 @@ static void (*pgm_check_table[128])(struct pt_regs *regs) = {
[0x3b] = do_dat_exception,
[0x3c] = default_trap_handler,
[0x3d] = do_secure_storage_access,
- [0x3e] = do_non_secure_storage_access,
- [0x3f] = do_secure_storage_violation,
+ [0x3e] = default_trap_handler,
+ [0x3f] = default_trap_handler,
[0x40] = monitor_event_exception,
[0x41 ... 0x7f] = default_trap_handler,
};
@@ -420,5 +436,3 @@ static void (*pgm_check_table[128])(struct pt_regs *regs) = {
__stringify(default_trap_handler))
COND_TRAP(do_secure_storage_access);
-COND_TRAP(do_non_secure_storage_access);
-COND_TRAP(do_secure_storage_violation);
diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c
index 9646f773208a..6f9654a191ad 100644
--- a/arch/s390/kernel/uv.c
+++ b/arch/s390/kernel/uv.c
@@ -2,7 +2,7 @@
/*
* Common Ultravisor functions and initialization
*
- * Copyright IBM Corp. 2019, 2020
+ * Copyright IBM Corp. 2019, 2024
*/
#define KMSG_COMPONENT "prot_virt"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
@@ -696,12 +696,32 @@ static struct kobj_attribute uv_query_supp_secret_types_attr =
static ssize_t uv_query_max_secrets(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
- return sysfs_emit(buf, "%d\n", uv_info.max_secrets);
+ return sysfs_emit(buf, "%d\n",
+ uv_info.max_assoc_secrets + uv_info.max_retr_secrets);
}
static struct kobj_attribute uv_query_max_secrets_attr =
__ATTR(max_secrets, 0444, uv_query_max_secrets, NULL);
+static ssize_t uv_query_max_retr_secrets(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%d\n", uv_info.max_retr_secrets);
+}
+
+static struct kobj_attribute uv_query_max_retr_secrets_attr =
+ __ATTR(max_retr_secrets, 0444, uv_query_max_retr_secrets, NULL);
+
+static ssize_t uv_query_max_assoc_secrets(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%d\n", uv_info.max_assoc_secrets);
+}
+
+static struct kobj_attribute uv_query_max_assoc_secrets_attr =
+ __ATTR(max_assoc_secrets, 0444, uv_query_max_assoc_secrets, NULL);
+
static struct attribute *uv_query_attrs[] = {
&uv_query_facilities_attr.attr,
&uv_query_feature_indications_attr.attr,
@@ -719,13 +739,81 @@ static struct attribute *uv_query_attrs[] = {
&uv_query_supp_add_secret_pcf_attr.attr,
&uv_query_supp_secret_types_attr.attr,
&uv_query_max_secrets_attr.attr,
+ &uv_query_max_assoc_secrets_attr.attr,
+ &uv_query_max_retr_secrets_attr.attr,
NULL,
};
+static inline struct uv_cb_query_keys uv_query_keys(void)
+{
+ struct uv_cb_query_keys uvcb = {
+ .header.cmd = UVC_CMD_QUERY_KEYS,
+ .header.len = sizeof(uvcb)
+ };
+
+ uv_call(0, (uint64_t)&uvcb);
+ return uvcb;
+}
+
+static inline ssize_t emit_hash(struct uv_key_hash *hash, char *buf, int at)
+{
+ return sysfs_emit_at(buf, at, "%016llx%016llx%016llx%016llx\n",
+ hash->dword[0], hash->dword[1], hash->dword[2], hash->dword[3]);
+}
+
+static ssize_t uv_keys_host_key(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct uv_cb_query_keys uvcb = uv_query_keys();
+
+ return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_HK], buf, 0);
+}
+
+static struct kobj_attribute uv_keys_host_key_attr =
+ __ATTR(host_key, 0444, uv_keys_host_key, NULL);
+
+static ssize_t uv_keys_backup_host_key(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct uv_cb_query_keys uvcb = uv_query_keys();
+
+ return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_BACK_HK], buf, 0);
+}
+
+static struct kobj_attribute uv_keys_backup_host_key_attr =
+ __ATTR(backup_host_key, 0444, uv_keys_backup_host_key, NULL);
+
+static ssize_t uv_keys_all(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct uv_cb_query_keys uvcb = uv_query_keys();
+ ssize_t len = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(uvcb.key_hashes); i++)
+ len += emit_hash(uvcb.key_hashes + i, buf, len);
+
+ return len;
+}
+
+static struct kobj_attribute uv_keys_all_attr =
+ __ATTR(all, 0444, uv_keys_all, NULL);
+
static struct attribute_group uv_query_attr_group = {
.attrs = uv_query_attrs,
};
+static struct attribute *uv_keys_attrs[] = {
+ &uv_keys_host_key_attr.attr,
+ &uv_keys_backup_host_key_attr.attr,
+ &uv_keys_all_attr.attr,
+ NULL,
+};
+
+static struct attribute_group uv_keys_attr_group = {
+ .attrs = uv_keys_attrs,
+};
+
static ssize_t uv_is_prot_virt_guest(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -751,9 +839,27 @@ static const struct attribute *uv_prot_virt_attrs[] = {
};
static struct kset *uv_query_kset;
+static struct kset *uv_keys_kset;
static struct kobject *uv_kobj;
-static int __init uv_info_init(void)
+static int __init uv_sysfs_dir_init(const struct attribute_group *grp,
+ struct kset **uv_dir_kset, const char *name)
+{
+ struct kset *kset;
+ int rc;
+
+ kset = kset_create_and_add(name, NULL, uv_kobj);
+ if (!kset)
+ return -ENOMEM;
+ *uv_dir_kset = kset;
+
+ rc = sysfs_create_group(&kset->kobj, grp);
+ if (rc)
+ kset_unregister(kset);
+ return rc;
+}
+
+static int __init uv_sysfs_init(void)
{
int rc = -ENOMEM;
@@ -768,17 +874,16 @@ static int __init uv_info_init(void)
if (rc)
goto out_kobj;
- uv_query_kset = kset_create_and_add("query", NULL, uv_kobj);
- if (!uv_query_kset) {
- rc = -ENOMEM;
+ rc = uv_sysfs_dir_init(&uv_query_attr_group, &uv_query_kset, "query");
+ if (rc)
goto out_ind_files;
- }
- rc = sysfs_create_group(&uv_query_kset->kobj, &uv_query_attr_group);
- if (!rc)
- return 0;
+ /* Get installed key hashes if available, ignore any errors */
+ if (test_bit_inv(BIT_UVC_CMD_QUERY_KEYS, uv_info.inst_calls_list))
+ uv_sysfs_dir_init(&uv_keys_attr_group, &uv_keys_kset, "keys");
+
+ return 0;
- kset_unregister(uv_query_kset);
out_ind_files:
sysfs_remove_files(uv_kobj, uv_prot_virt_attrs);
out_kobj:
@@ -786,4 +891,131 @@ out_kobj:
kobject_put(uv_kobj);
return rc;
}
-device_initcall(uv_info_init);
+device_initcall(uv_sysfs_init);
+
+/*
+ * Find the secret with the secret_id in the provided list.
+ *
+ * Context: might sleep.
+ */
+static int find_secret_in_page(const u8 secret_id[UV_SECRET_ID_LEN],
+ const struct uv_secret_list *list,
+ struct uv_secret_list_item_hdr *secret)
+{
+ u16 i;
+
+ for (i = 0; i < list->total_num_secrets; i++) {
+ if (memcmp(secret_id, list->secrets[i].id, UV_SECRET_ID_LEN) == 0) {
+ *secret = list->secrets[i].hdr;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+/*
+ * Do the actual search for `uv_get_secret_metadata`.
+ *
+ * Context: might sleep.
+ */
+static int find_secret(const u8 secret_id[UV_SECRET_ID_LEN],
+ struct uv_secret_list *list,
+ struct uv_secret_list_item_hdr *secret)
+{
+ u16 start_idx = 0;
+ u16 list_rc;
+ int ret;
+
+ do {
+ uv_list_secrets(list, start_idx, &list_rc, NULL);
+ if (list_rc != UVC_RC_EXECUTED && list_rc != UVC_RC_MORE_DATA) {
+ if (list_rc == UVC_RC_INV_CMD)
+ return -ENODEV;
+ else
+ return -EIO;
+ }
+ ret = find_secret_in_page(secret_id, list, secret);
+ if (ret == 0)
+ return ret;
+ start_idx = list->next_secret_idx;
+ } while (list_rc == UVC_RC_MORE_DATA && start_idx < list->next_secret_idx);
+
+ return -ENOENT;
+}
+
+/**
+ * uv_get_secret_metadata() - get secret metadata for a given secret id.
+ * @secret_id: search pattern.
+ * @secret: output data, containing the secret's metadata.
+ *
+ * Search for a secret with the given secret_id in the Ultravisor secret store.
+ *
+ * Context: might sleep.
+ *
+ * Return:
+ * * %0: - Found entry; secret->idx and secret->type are valid.
+ * * %ENOENT - No entry found.
+ * * %ENODEV: - Not supported: UV not available or command not available.
+ * * %EIO: - Other unexpected UV error.
+ */
+int uv_get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN],
+ struct uv_secret_list_item_hdr *secret)
+{
+ struct uv_secret_list *buf;
+ int rc;
+
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ rc = find_secret(secret_id, buf, secret);
+ kfree(buf);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(uv_get_secret_metadata);
+
+/**
+ * uv_retrieve_secret() - get the secret value for the secret index.
+ * @secret_idx: Secret index for which the secret should be retrieved.
+ * @buf: Buffer to store retrieved secret.
+ * @buf_size: Size of the buffer. The correct buffer size is reported as part of
+ * the result from `uv_get_secret_metadata`.
+ *
+ * Calls the Retrieve Secret UVC and translates the UV return code into an errno.
+ *
+ * Context: might sleep.
+ *
+ * Return:
+ * * %0 - Entry found; buffer contains a valid secret.
+ * * %ENOENT: - No entry found or secret at the index is non-retrievable.
+ * * %ENODEV: - Not supported: UV not available or command not available.
+ * * %EINVAL: - Buffer too small for content.
+ * * %EIO: - Other unexpected UV error.
+ */
+int uv_retrieve_secret(u16 secret_idx, u8 *buf, size_t buf_size)
+{
+ struct uv_cb_retr_secr uvcb = {
+ .header.len = sizeof(uvcb),
+ .header.cmd = UVC_CMD_RETR_SECRET,
+ .secret_idx = secret_idx,
+ .buf_addr = (u64)buf,
+ .buf_size = buf_size,
+ };
+
+ uv_call_sched(0, (u64)&uvcb);
+
+ switch (uvcb.header.rc) {
+ case UVC_RC_EXECUTED:
+ return 0;
+ case UVC_RC_INV_CMD:
+ return -ENODEV;
+ case UVC_RC_RETR_SECR_STORE_EMPTY:
+ case UVC_RC_RETR_SECR_INV_SECRET:
+ case UVC_RC_RETR_SECR_INV_IDX:
+ return -ENOENT;
+ case UVC_RC_RETR_SECR_BUF_SMALL:
+ return -EINVAL;
+ default:
+ return -EIO;
+ }
+}
+EXPORT_SYMBOL_GPL(uv_retrieve_secret);
diff --git a/arch/s390/kernel/vdso32/vdso32.lds.S b/arch/s390/kernel/vdso32/vdso32.lds.S
index 65b9513a5a0e..c916c4f73f76 100644
--- a/arch/s390/kernel/vdso32/vdso32.lds.S
+++ b/arch/s390/kernel/vdso32/vdso32.lds.S
@@ -16,7 +16,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
#endif
- . = VDSO_LBASE + SIZEOF_HEADERS;
+ . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) }
diff --git a/arch/s390/kernel/vdso64/vdso64.lds.S b/arch/s390/kernel/vdso64/vdso64.lds.S
index 753040a4b5ab..ec42b7d9cb53 100644
--- a/arch/s390/kernel/vdso64/vdso64.lds.S
+++ b/arch/s390/kernel/vdso64/vdso64.lds.S
@@ -18,7 +18,7 @@ SECTIONS
#ifdef CONFIG_TIME_NS
PROVIDE(_timens_data = _vdso_data + PAGE_SIZE);
#endif
- . = VDSO_LBASE + SIZEOF_HEADERS;
+ . = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) }
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index a688351f4ab5..9816b0060fbe 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -129,8 +129,8 @@ static void ipte_lock_simple(struct kvm *kvm)
retry:
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
if (old.k) {
read_unlock(&kvm->arch.sca_lock);
cond_resched();
@@ -138,7 +138,7 @@ retry:
}
new = old;
new.k = 1;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
out:
mutex_unlock(&kvm->arch.ipte_mutex);
@@ -154,11 +154,11 @@ static void ipte_unlock_simple(struct kvm *kvm)
goto out;
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
new = old;
new.k = 0;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
wake_up(&kvm->arch.ipte_wq);
out:
@@ -172,8 +172,8 @@ static void ipte_lock_siif(struct kvm *kvm)
retry:
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
if (old.kg) {
read_unlock(&kvm->arch.sca_lock);
cond_resched();
@@ -182,7 +182,7 @@ retry:
new = old;
new.k = 1;
new.kh++;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
}
@@ -192,13 +192,13 @@ static void ipte_unlock_siif(struct kvm *kvm)
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
new = old;
new.kh--;
if (!new.kh)
new.k = 0;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
if (!new.kh)
wake_up(&kvm->arch.ipte_wq);
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index b16352083ff9..5bbaadf75dc6 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -367,7 +367,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
reg2, &srcaddr, GACC_FETCH, 0);
if (rc)
return kvm_s390_inject_prog_cond(vcpu, rc);
- rc = kvm_arch_fault_in_page(vcpu, srcaddr, 0);
+ rc = gmap_fault(vcpu->arch.gmap, srcaddr, 0);
if (rc != 0)
return rc;
@@ -376,7 +376,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
reg1, &dstaddr, GACC_STORE, 0);
if (rc)
return kvm_s390_inject_prog_cond(vcpu, rc);
- rc = kvm_arch_fault_in_page(vcpu, dstaddr, 1);
+ rc = gmap_fault(vcpu->arch.gmap, dstaddr, FAULT_FLAG_WRITE);
if (rc != 0)
return rc;
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 4f0e7f61edf7..ea8dce299954 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -118,8 +118,6 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
{
- int rc, expect;
-
if (!kvm_s390_use_sca_entries())
return;
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
@@ -128,23 +126,16 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
- union esca_sigp_ctrl old;
- old = READ_ONCE(*sigp_ctrl);
- expect = old.value;
- rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
+ WRITE_ONCE(sigp_ctrl->value, 0);
} else {
struct bsca_block *sca = vcpu->kvm->arch.sca;
union bsca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
- union bsca_sigp_ctrl old;
- old = READ_ONCE(*sigp_ctrl);
- expect = old.value;
- rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
+ WRITE_ONCE(sigp_ctrl->value, 0);
}
read_unlock(&vcpu->kvm->arch.sca_lock);
- WARN_ON(rc != expect); /* cannot clear? */
}
int psw_extint_disabled(struct kvm_vcpu *vcpu)
@@ -247,12 +238,12 @@ static inline int gisa_set_iam(struct kvm_s390_gisa *gisa, u8 iam)
{
u64 word, _word;
+ word = READ_ONCE(gisa->u64.word[0]);
do {
- word = READ_ONCE(gisa->u64.word[0]);
if ((u64)gisa != word >> 32)
return -EBUSY;
_word = (word & ~0xffUL) | iam;
- } while (cmpxchg(&gisa->u64.word[0], word, _word) != word);
+ } while (!try_cmpxchg(&gisa->u64.word[0], &word, _word));
return 0;
}
@@ -270,10 +261,10 @@ static inline void gisa_clear_ipm(struct kvm_s390_gisa *gisa)
{
u64 word, _word;
+ word = READ_ONCE(gisa->u64.word[0]);
do {
- word = READ_ONCE(gisa->u64.word[0]);
_word = word & ~(0xffUL << 24);
- } while (cmpxchg(&gisa->u64.word[0], word, _word) != word);
+ } while (!try_cmpxchg(&gisa->u64.word[0], &word, _word));
}
/**
@@ -291,14 +282,14 @@ static inline u8 gisa_get_ipm_or_restore_iam(struct kvm_s390_gisa_interrupt *gi)
u8 pending_mask, alert_mask;
u64 word, _word;
+ word = READ_ONCE(gi->origin->u64.word[0]);
do {
- word = READ_ONCE(gi->origin->u64.word[0]);
alert_mask = READ_ONCE(gi->alert.mask);
pending_mask = (u8)(word >> 24) & alert_mask;
if (pending_mask)
return pending_mask;
_word = (word & ~0xffUL) | alert_mask;
- } while (cmpxchg(&gi->origin->u64.word[0], word, _word) != word);
+ } while (!try_cmpxchg(&gi->origin->u64.word[0], &word, _word));
return 0;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index bb7134faaebf..d8080c27d45b 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -43,6 +43,7 @@
#include <asm/sclp.h>
#include <asm/cpacf.h>
#include <asm/timex.h>
+#include <asm/asm.h>
#include <asm/fpu.h>
#include <asm/ap.h>
#include <asm/uv.h>
@@ -340,12 +341,21 @@ static inline int plo_test_bit(unsigned char nr)
" lgr 0,%[function]\n"
/* Parameter registers are ignored for "test bit" */
" plo 0,0,0,0(0)\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc)
: [function] "d" (function)
+ : CC_CLOBBER_LIST("0"));
+ return CC_TRANSFORM(cc) == 0;
+}
+
+static __always_inline void pfcr_query(u8 (*query)[16])
+{
+ asm volatile(
+ " lghi 0,0\n"
+ " .insn rsy,0xeb0000000016,0,0,%[query]\n"
+ : [query] "=QS" (*query)
+ :
: "cc", "0");
- return cc == 0;
}
static __always_inline void __sortl_query(u8 (*query)[32])
@@ -429,6 +439,9 @@ static void __init kvm_s390_cpu_feat_init(void)
if (test_facility(151)) /* DFLTCC */
__dfltcc_query(&kvm_s390_available_subfunc.dfltcc);
+ if (test_facility(201)) /* PFCR */
+ pfcr_query(&kvm_s390_available_subfunc.pfcr);
+
if (MACHINE_HAS_ESOP)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP);
/*
@@ -799,6 +812,14 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
set_kvm_facility(kvm->arch.model.fac_mask, 192);
set_kvm_facility(kvm->arch.model.fac_list, 192);
}
+ if (test_facility(198)) {
+ set_kvm_facility(kvm->arch.model.fac_mask, 198);
+ set_kvm_facility(kvm->arch.model.fac_list, 198);
+ }
+ if (test_facility(199)) {
+ set_kvm_facility(kvm->arch.model.fac_mask, 199);
+ set_kvm_facility(kvm->arch.model.fac_list, 199);
+ }
r = 0;
} else
r = -EINVAL;
@@ -1543,6 +1564,9 @@ static int kvm_s390_set_processor_subfunc(struct kvm *kvm,
((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[1],
((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[2],
((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[3]);
+ VM_EVENT(kvm, 3, "GET: guest PFCR subfunc 0x%16.16lx.%16.16lx",
+ ((unsigned long *) &kvm_s390_available_subfunc.pfcr)[0],
+ ((unsigned long *) &kvm_s390_available_subfunc.pfcr)[1]);
return 0;
}
@@ -1757,6 +1781,9 @@ static int kvm_s390_get_processor_subfunc(struct kvm *kvm,
((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[1],
((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[2],
((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[3]);
+ VM_EVENT(kvm, 3, "GET: guest PFCR subfunc 0x%16.16lx.%16.16lx",
+ ((unsigned long *) &kvm_s390_available_subfunc.pfcr)[0],
+ ((unsigned long *) &kvm_s390_available_subfunc.pfcr)[1]);
return 0;
}
@@ -1825,6 +1852,9 @@ static int kvm_s390_get_machine_subfunc(struct kvm *kvm,
((unsigned long *) &kvm_s390_available_subfunc.dfltcc)[1],
((unsigned long *) &kvm_s390_available_subfunc.dfltcc)[2],
((unsigned long *) &kvm_s390_available_subfunc.dfltcc)[3]);
+ VM_EVENT(kvm, 3, "GET: host PFCR subfunc 0x%16.16lx.%16.16lx",
+ ((unsigned long *) &kvm_s390_available_subfunc.pfcr)[0],
+ ((unsigned long *) &kvm_s390_available_subfunc.pfcr)[1]);
return 0;
}
@@ -1907,11 +1937,11 @@ static void kvm_s390_update_topology_change_report(struct kvm *kvm, bool val)
read_lock(&kvm->arch.sca_lock);
sca = kvm->arch.sca;
+ old = READ_ONCE(sca->utility);
do {
- old = READ_ONCE(sca->utility);
new = old;
new.mtcr = val;
- } while (cmpxchg(&sca->utility.val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&sca->utility.val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
}
@@ -3719,7 +3749,6 @@ __u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
- gmap_enable(vcpu->arch.enabled_gmap);
kvm_s390_set_cpuflags(vcpu, CPUSTAT_RUNNING);
if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
__start_cpu_timer_accounting(vcpu);
@@ -3732,8 +3761,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
__stop_cpu_timer_accounting(vcpu);
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_RUNNING);
- vcpu->arch.enabled_gmap = gmap_get_enabled();
- gmap_disable(vcpu->arch.enabled_gmap);
}
@@ -3751,8 +3778,6 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
}
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0)
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
- /* make vcpu_load load the right gmap on the first trigger */
- vcpu->arch.enabled_gmap = vcpu->arch.gmap;
}
static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
@@ -3774,6 +3799,13 @@ static bool kvm_has_pckmo_ecc(struct kvm *kvm)
}
+static bool kvm_has_pckmo_hmac(struct kvm *kvm)
+{
+ /* At least one HMAC subfunction must be present */
+ return kvm_has_pckmo_subfunc(kvm, 118) ||
+ kvm_has_pckmo_subfunc(kvm, 122);
+}
+
static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
{
/*
@@ -3786,7 +3818,7 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd;
vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA);
vcpu->arch.sie_block->eca &= ~ECA_APIE;
- vcpu->arch.sie_block->ecd &= ~ECD_ECC;
+ vcpu->arch.sie_block->ecd &= ~(ECD_ECC | ECD_HMAC);
if (vcpu->kvm->arch.crypto.apie)
vcpu->arch.sie_block->eca |= ECA_APIE;
@@ -3794,9 +3826,11 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
/* Set up protected key support */
if (vcpu->kvm->arch.crypto.aes_kw) {
vcpu->arch.sie_block->ecb3 |= ECB3_AES;
- /* ecc is also wrapped with AES key */
+ /* ecc/hmac is also wrapped with AES key */
if (kvm_has_pckmo_ecc(vcpu->kvm))
vcpu->arch.sie_block->ecd |= ECD_ECC;
+ if (kvm_has_pckmo_hmac(vcpu->kvm))
+ vcpu->arch.sie_block->ecd |= ECD_HMAC;
}
if (vcpu->kvm->arch.crypto.dea_kw)
@@ -4579,22 +4613,6 @@ int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clo
return 1;
}
-/**
- * kvm_arch_fault_in_page - fault-in guest page if necessary
- * @vcpu: The corresponding virtual cpu
- * @gpa: Guest physical address
- * @writable: Whether the page should be writable or not
- *
- * Make sure that a guest page has been faulted-in on the host.
- *
- * Return: Zero on success, negative error code otherwise.
- */
-long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable)
-{
- return gmap_fault(vcpu->arch.gmap, gpa,
- writable ? FAULT_FLAG_WRITE : 0);
-}
-
static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token,
unsigned long token)
{
@@ -4662,12 +4680,11 @@ static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)
if (!vcpu->arch.gmap->pfault_enabled)
return false;
- hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(current->thread.gmap_addr));
- hva += current->thread.gmap_addr & ~PAGE_MASK;
+ hva = gfn_to_hva(vcpu->kvm, current->thread.gmap_teid.addr);
if (read_guest_real(vcpu, vcpu->arch.pfault_token, &arch.pfault_token, 8))
return false;
- return kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch);
+ return kvm_setup_async_pf(vcpu, current->thread.gmap_teid.addr * PAGE_SIZE, hva, &arch);
}
static int vcpu_pre_run(struct kvm_vcpu *vcpu)
@@ -4705,6 +4722,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.gisa_int.kicked_mask);
vcpu->arch.sie_block->icptcode = 0;
+ current->thread.gmap_int_code = 0;
cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags);
VCPU_EVENT(vcpu, 6, "entering sie flags %x", cpuflags);
trace_kvm_s390_sie_enter(vcpu, cpuflags);
@@ -4712,7 +4730,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
return 0;
}
-static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu)
+static int vcpu_post_run_addressing_exception(struct kvm_vcpu *vcpu)
{
struct kvm_s390_pgm_info pgm_info = {
.code = PGM_ADDRESSING,
@@ -4748,10 +4766,106 @@ static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu)
return kvm_s390_inject_prog_irq(vcpu, &pgm_info);
}
+static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
+{
+ unsigned int flags = 0;
+ unsigned long gaddr;
+ int rc = 0;
+
+ gaddr = current->thread.gmap_teid.addr * PAGE_SIZE;
+ if (kvm_s390_cur_gmap_fault_is_write())
+ flags = FAULT_FLAG_WRITE;
+
+ switch (current->thread.gmap_int_code & PGM_INT_CODE_MASK) {
+ case 0:
+ vcpu->stat.exit_null++;
+ break;
+ case PGM_NON_SECURE_STORAGE_ACCESS:
+ KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm,
+ "Unexpected program interrupt 0x%x, TEID 0x%016lx",
+ current->thread.gmap_int_code, current->thread.gmap_teid.val);
+ /*
+ * This is normal operation; a page belonging to a protected
+ * guest has not been imported yet. Try to import the page into
+ * the protected guest.
+ */
+ if (gmap_convert_to_secure(vcpu->arch.gmap, gaddr) == -EINVAL)
+ send_sig(SIGSEGV, current, 0);
+ break;
+ case PGM_SECURE_STORAGE_ACCESS:
+ case PGM_SECURE_STORAGE_VIOLATION:
+ KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm,
+ "Unexpected program interrupt 0x%x, TEID 0x%016lx",
+ current->thread.gmap_int_code, current->thread.gmap_teid.val);
+ /*
+ * This can happen after a reboot with asynchronous teardown;
+ * the new guest (normal or protected) will run on top of the
+ * previous protected guest. The old pages need to be destroyed
+ * so the new guest can use them.
+ */
+ if (gmap_destroy_page(vcpu->arch.gmap, gaddr)) {
+ /*
+ * Either KVM messed up the secure guest mapping or the
+ * same page is mapped into multiple secure guests.
+ *
+ * This exception is only triggered when a guest 2 is
+ * running and can therefore never occur in kernel
+ * context.
+ */
+ pr_warn_ratelimited("Secure storage violation (%x) in task: %s, pid %d\n",
+ current->thread.gmap_int_code, current->comm,
+ current->pid);
+ send_sig(SIGSEGV, current, 0);
+ }
+ break;
+ case PGM_PROTECTION:
+ case PGM_SEGMENT_TRANSLATION:
+ case PGM_PAGE_TRANSLATION:
+ case PGM_ASCE_TYPE:
+ case PGM_REGION_FIRST_TRANS:
+ case PGM_REGION_SECOND_TRANS:
+ case PGM_REGION_THIRD_TRANS:
+ KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm,
+ "Unexpected program interrupt 0x%x, TEID 0x%016lx",
+ current->thread.gmap_int_code, current->thread.gmap_teid.val);
+ if (vcpu->arch.gmap->pfault_enabled) {
+ rc = gmap_fault(vcpu->arch.gmap, gaddr, flags | FAULT_FLAG_RETRY_NOWAIT);
+ if (rc == -EFAULT)
+ return vcpu_post_run_addressing_exception(vcpu);
+ if (rc == -EAGAIN) {
+ trace_kvm_s390_major_guest_pfault(vcpu);
+ if (kvm_arch_setup_async_pf(vcpu))
+ return 0;
+ vcpu->stat.pfault_sync++;
+ } else {
+ return rc;
+ }
+ }
+ rc = gmap_fault(vcpu->arch.gmap, gaddr, flags);
+ if (rc == -EFAULT) {
+ if (kvm_is_ucontrol(vcpu->kvm)) {
+ vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL;
+ vcpu->run->s390_ucontrol.trans_exc_code = gaddr;
+ vcpu->run->s390_ucontrol.pgm_code = 0x10;
+ return -EREMOTE;
+ }
+ return vcpu_post_run_addressing_exception(vcpu);
+ }
+ break;
+ default:
+ KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx",
+ current->thread.gmap_int_code, current->thread.gmap_teid.val);
+ send_sig(SIGSEGV, current, 0);
+ break;
+ }
+ return rc;
+}
+
static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
{
struct mcck_volatile_info *mcck_info;
struct sie_page *sie_page;
+ int rc;
VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
vcpu->arch.sie_block->icptcode);
@@ -4773,7 +4887,7 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
}
if (vcpu->arch.sie_block->icptcode > 0) {
- int rc = kvm_handle_sie_intercept(vcpu);
+ rc = kvm_handle_sie_intercept(vcpu);
if (rc != -EOPNOTSUPP)
return rc;
@@ -4782,24 +4896,9 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
vcpu->run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
vcpu->run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
return -EREMOTE;
- } else if (exit_reason != -EFAULT) {
- vcpu->stat.exit_null++;
- return 0;
- } else if (kvm_is_ucontrol(vcpu->kvm)) {
- vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL;
- vcpu->run->s390_ucontrol.trans_exc_code =
- current->thread.gmap_addr;
- vcpu->run->s390_ucontrol.pgm_code = 0x10;
- return -EREMOTE;
- } else if (current->thread.gmap_pfault) {
- trace_kvm_s390_major_guest_pfault(vcpu);
- current->thread.gmap_pfault = 0;
- if (kvm_arch_setup_async_pf(vcpu))
- return 0;
- vcpu->stat.pfault_sync++;
- return kvm_arch_fault_in_page(vcpu, current->thread.gmap_addr, 1);
}
- return vcpu_post_run_fault_in_sie(vcpu);
+
+ return vcpu_post_run_handle_fault(vcpu);
}
#define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK)
@@ -4835,7 +4934,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
}
exit_reason = sie64a(vcpu->arch.sie_block,
vcpu->run->s.regs.gprs,
- gmap_get_enabled()->asce);
+ vcpu->arch.gmap->asce);
if (kvm_s390_pv_cpu_is_protected(vcpu)) {
memcpy(vcpu->run->s.regs.gprs,
sie_page->pv_grregs,
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index e680c6bf0c9d..597d7a71deeb 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -394,7 +394,6 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
/* implemented in kvm-s390.c */
int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
-long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);
int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr);
int kvm_s390_vcpu_start(struct kvm_vcpu *vcpu);
@@ -529,6 +528,13 @@ static inline int kvm_s390_use_sca_entries(void)
void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
struct mcck_volatile_info *mcck_info);
+static inline bool kvm_s390_cur_gmap_fault_is_write(void)
+{
+ if (current->thread.gmap_int_code == PGM_PROTECTION)
+ return true;
+ return test_facility(75) && (current->thread.gmap_teid.fsi == TEID_FSI_STORE);
+}
+
/**
* kvm_s390_vcpu_crypto_reset_all
*
diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c
index ffa7739c7a28..9b9e7fdd5380 100644
--- a/arch/s390/kvm/pci.c
+++ b/arch/s390/kvm/pci.c
@@ -103,7 +103,7 @@ static int zpci_reset_aipb(u8 nisc)
/*
* AEN registration can only happen once per system boot. If
* an aipb already exists then AEN was already registered and
- * we can re-use the aipb contents. This can only happen if
+ * we can reuse the aipb contents. This can only happen if
* the KVM module was removed and re-inserted. However, we must
* ensure that the same forwarding ISC is used as this is assigned
* during KVM module load.
@@ -208,13 +208,12 @@ static inline int account_mem(unsigned long nr_pages)
page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+ cur_pages = atomic_long_read(&user->locked_vm);
do {
- cur_pages = atomic_long_read(&user->locked_vm);
new_pages = cur_pages + nr_pages;
if (new_pages > page_limit)
return -ENOMEM;
- } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages,
- new_pages) != cur_pages);
+ } while (!atomic_long_try_cmpxchg(&user->locked_vm, &cur_pages, new_pages));
atomic64_add(nr_pages, &current->mm->pinned_vm);
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c
index 89cafea4c41f..150b9387860a 100644
--- a/arch/s390/kvm/vsie.c
+++ b/arch/s390/kvm/vsie.c
@@ -335,7 +335,8 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
/* we may only allow it if enabled for guest 2 */
ecb3_flags = scb_o->ecb3 & vcpu->arch.sie_block->ecb3 &
(ECB3_AES | ECB3_DEA);
- ecd_flags = scb_o->ecd & vcpu->arch.sie_block->ecd & ECD_ECC;
+ ecd_flags = scb_o->ecd & vcpu->arch.sie_block->ecd &
+ (ECD_ECC | ECD_HMAC);
if (!ecb3_flags && !ecd_flags)
goto end;
@@ -661,7 +662,7 @@ static int pin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t *hpa)
struct page *page;
page = gfn_to_page(kvm, gpa_to_gfn(gpa));
- if (is_error_page(page))
+ if (!page)
return -EINVAL;
*hpa = (hpa_t)page_to_phys(page) + (gpa & ~PAGE_MASK);
return 0;
@@ -670,7 +671,7 @@ static int pin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t *hpa)
/* Unpins a page previously pinned via pin_guest_page, marking it as dirty. */
static void unpin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t hpa)
{
- kvm_release_pfn_dirty(hpa >> PAGE_SHIFT);
+ kvm_release_page_dirty(pfn_to_page(hpa >> PAGE_SHIFT));
/* mark the page always as dirty for migration */
mark_page_dirty(kvm, gpa_to_gfn(gpa));
}
@@ -922,19 +923,19 @@ static int handle_fault(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
{
int rc;
- if (current->thread.gmap_int_code == PGM_PROTECTION)
+ if ((current->thread.gmap_int_code & PGM_INT_CODE_MASK) == PGM_PROTECTION)
/* we can directly forward all protection exceptions */
return inject_fault(vcpu, PGM_PROTECTION,
- current->thread.gmap_addr, 1);
+ current->thread.gmap_teid.addr * PAGE_SIZE, 1);
rc = kvm_s390_shadow_fault(vcpu, vsie_page->gmap,
- current->thread.gmap_addr, NULL);
+ current->thread.gmap_teid.addr * PAGE_SIZE, NULL);
if (rc > 0) {
rc = inject_fault(vcpu, rc,
- current->thread.gmap_addr,
- current->thread.gmap_write_flag);
+ current->thread.gmap_teid.addr * PAGE_SIZE,
+ kvm_s390_cur_gmap_fault_is_write());
if (rc >= 0)
- vsie_page->fault_addr = current->thread.gmap_addr;
+ vsie_page->fault_addr = current->thread.gmap_teid.addr * PAGE_SIZE;
}
return rc;
}
@@ -1148,9 +1149,10 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
* also kick the vSIE.
*/
vcpu->arch.sie_block->prog0c |= PROG_IN_SIE;
+ current->thread.gmap_int_code = 0;
barrier();
if (!kvm_s390_vcpu_sie_inhibited(vcpu))
- rc = sie64a(scb_s, vcpu->run->s.regs.gprs, gmap_get_enabled()->asce);
+ rc = sie64a(scb_s, vcpu->run->s.regs.gprs, vsie_page->gmap->asce);
barrier();
vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE;
@@ -1172,7 +1174,7 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
if (rc > 0)
rc = 0; /* we could still have an icpt */
- else if (rc == -EFAULT)
+ else if (current->thread.gmap_int_code)
return handle_fault(vcpu, vsie_page);
switch (scb_s->icptcode) {
@@ -1295,10 +1297,8 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
if (!rc)
rc = map_prefix(vcpu, vsie_page);
if (!rc) {
- gmap_enable(vsie_page->gmap);
update_intervention_requests(vsie_page);
rc = do_vsie_run(vcpu, vsie_page);
- gmap_enable(vcpu->arch.gmap);
}
atomic_andnot(PROG_BLOCK_SIE, &scb_s->prog20);
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 9f86ad8fa8b4..a81a01c44927 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -15,6 +15,7 @@
#include <linux/percpu.h>
#include <linux/io.h>
#include <asm/alternative.h>
+#include <asm/asm.h>
int spin_retry = -1;
@@ -76,24 +77,43 @@ static inline int arch_load_niai4(int *lock)
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,4,0", ALT_FACILITY(49)) /* NIAI 4 */
- " l %0,%1\n"
- : "=d" (owner) : "Q" (*lock) : "memory");
+ " l %[owner],%[lock]\n"
+ : [owner] "=d" (owner) : [lock] "R" (*lock) : "memory");
return owner;
}
-static inline int arch_cmpxchg_niai8(int *lock, int old, int new)
+#ifdef __HAVE_ASM_FLAG_OUTPUTS__
+
+static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
+{
+ int cc;
+
+ asm_inline volatile(
+ ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */
+ " cs %[old],%[new],%[lock]\n"
+ : [old] "+d" (old), [lock] "+Q" (*lock), "=@cc" (cc)
+ : [new] "d" (new)
+ : "memory");
+ return cc == 0;
+}
+
+#else /* __HAVE_ASM_FLAG_OUTPUTS__ */
+
+static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
{
int expected = old;
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */
- " cs %0,%3,%1\n"
- : "=d" (old), "=Q" (*lock)
- : "0" (old), "d" (new), "Q" (*lock)
+ " cs %[old],%[new],%[lock]\n"
+ : [old] "+d" (old), [lock] "+Q" (*lock)
+ : [new] "d" (new)
: "cc", "memory");
return expected == old;
}
+#endif /* __HAVE_ASM_FLAG_OUTPUTS__ */
+
static inline struct spin_wait *arch_spin_decode_tail(int lock)
{
int ix, cpu;
@@ -127,8 +147,8 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp)
node_id = node->node_id;
/* Enqueue the node for this CPU in the spinlock wait queue */
+ old = READ_ONCE(lp->lock);
while (1) {
- old = READ_ONCE(lp->lock);
if ((old & _Q_LOCK_CPU_MASK) == 0 &&
(old & _Q_LOCK_STEAL_MASK) != _Q_LOCK_STEAL_MASK) {
/*
@@ -139,7 +159,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp)
* waiter will get the lock.
*/
new = (old ? (old + _Q_LOCK_STEAL_ADD) : 0) | lockval;
- if (__atomic_cmpxchg_bool(&lp->lock, old, new))
+ if (arch_try_cmpxchg(&lp->lock, &old, new))
/* Got the lock */
goto out;
/* lock passing in progress */
@@ -147,7 +167,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp)
}
/* Make the node of this CPU the new tail. */
new = node_id | (old & _Q_LOCK_MASK);
- if (__atomic_cmpxchg_bool(&lp->lock, old, new))
+ if (arch_try_cmpxchg(&lp->lock, &old, new))
break;
}
/* Set the 'next' pointer of the tail node in the queue */
@@ -184,7 +204,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp)
if (!owner) {
tail_id = old & _Q_TAIL_MASK;
new = ((tail_id != node_id) ? tail_id : 0) | lockval;
- if (__atomic_cmpxchg_bool(&lp->lock, old, new))
+ if (arch_try_cmpxchg(&lp->lock, &old, new))
/* Got the lock */
break;
continue;
@@ -226,7 +246,7 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp)
/* Try to get the lock if it is free. */
if (!owner) {
new = (old & _Q_TAIL_MASK) | lockval;
- if (arch_cmpxchg_niai8(&lp->lock, old, new)) {
+ if (arch_try_cmpxchg_niai8(&lp->lock, old, new)) {
/* Got the lock */
return;
}
@@ -258,7 +278,7 @@ int arch_spin_trylock_retry(arch_spinlock_t *lp)
owner = READ_ONCE(lp->lock);
/* Try to get the lock if it is free. */
if (!owner) {
- if (__atomic_cmpxchg_bool(&lp->lock, 0, cpu))
+ if (arch_try_cmpxchg(&lp->lock, &owner, cpu))
return 1;
}
}
@@ -300,7 +320,7 @@ void arch_write_lock_wait(arch_rwlock_t *rw)
while (1) {
old = READ_ONCE(rw->cnts);
if ((old & 0x1ffff) == 0 &&
- __atomic_cmpxchg_bool(&rw->cnts, old, old | 0x10000))
+ arch_try_cmpxchg(&rw->cnts, &old, old | 0x10000))
/* Got the lock */
break;
barrier();
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c
index 7d8741818239..373fa1f01937 100644
--- a/arch/s390/lib/string.c
+++ b/arch/s390/lib/string.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/string.h>
#include <linux/export.h>
+#include <asm/asm.h>
/*
* Helper functions to find the end of a string
@@ -238,12 +239,11 @@ static inline int clcle(const char *s1, unsigned long l1,
asm volatile(
"0: clcle %[r1],%[r3],0\n"
" jo 0b\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=&d" (cc), [r1] "+&d" (r1.pair), [r3] "+&d" (r3.pair)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [r1] "+d" (r1.pair), [r3] "+d" (r3.pair)
:
- : "cc", "memory");
- return cc;
+ : CC_CLOBBER_LIST("memory"));
+ return CC_TRANSFORM(cc);
}
/**
diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c
index 8b7f981e6f34..6e42100875e7 100644
--- a/arch/s390/lib/test_unwind.c
+++ b/arch/s390/lib/test_unwind.c
@@ -270,9 +270,9 @@ static void notrace __used test_unwind_ftrace_handler(unsigned long ip,
struct ftrace_ops *fops,
struct ftrace_regs *fregs)
{
- struct unwindme *u = (struct unwindme *)fregs->regs.gprs[2];
+ struct unwindme *u = (struct unwindme *)arch_ftrace_regs(fregs)->regs.gprs[2];
- u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? &fregs->regs : NULL,
+ u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? &arch_ftrace_regs(fregs)->regs : NULL,
(u->flags & UWM_SP) ? u->sp : 0);
}
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 282fefe107a2..4692136c0af1 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -28,6 +28,7 @@
#include <asm/extmem.h>
#include <asm/cpcmd.h>
#include <asm/setup.h>
+#include <asm/asm.h>
#define DCSS_PURGESEG 0x08
#define DCSS_LOADSHRX 0x20
@@ -134,20 +135,21 @@ dcss_diag(int *func, void *parameter,
unsigned long *ret1, unsigned long *ret2)
{
unsigned long rx, ry;
- int rc;
+ int cc;
rx = virt_to_phys(parameter);
ry = (unsigned long) *func;
diag_stat_inc(DIAG_STAT_X064);
asm volatile(
- " diag %0,%1,0x64\n"
- " ipm %2\n"
- " srl %2,28\n"
- : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
+ " diag %[rx],%[ry],0x64\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [rx] "+d" (rx), [ry] "+d" (ry)
+ :
+ : CC_CLOBBER);
*ret1 = rx;
*ret2 = ry;
- return rc;
+ return CC_TRANSFORM(cc);
}
static inline int
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index ad8b0d6b77ea..9b681f74dccc 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -46,12 +46,6 @@
#include <asm/uv.h>
#include "../kernel/entry.h"
-enum fault_type {
- KERNEL_FAULT,
- USER_FAULT,
- GMAP_FAULT,
-};
-
static DEFINE_STATIC_KEY_FALSE(have_store_indication);
static int __init fault_init(void)
@@ -65,28 +59,15 @@ early_initcall(fault_init);
/*
* Find out which address space caused the exception.
*/
-static enum fault_type get_fault_type(struct pt_regs *regs)
+static bool is_kernel_fault(struct pt_regs *regs)
{
union teid teid = { .val = regs->int_parm_long };
- struct gmap *gmap;
- if (likely(teid.as == PSW_BITS_AS_PRIMARY)) {
- if (user_mode(regs))
- return USER_FAULT;
- if (!IS_ENABLED(CONFIG_PGSTE))
- return KERNEL_FAULT;
- gmap = (struct gmap *)get_lowcore()->gmap;
- if (gmap && gmap->asce == regs->cr1)
- return GMAP_FAULT;
- return KERNEL_FAULT;
- }
+ if (user_mode(regs))
+ return false;
if (teid.as == PSW_BITS_AS_SECONDARY)
- return USER_FAULT;
- /* Access register mode, not used in the kernel */
- if (teid.as == PSW_BITS_AS_ACCREG)
- return USER_FAULT;
- /* Home space -> access via kernel ASCE */
- return KERNEL_FAULT;
+ return false;
+ return true;
}
static unsigned long get_fault_address(struct pt_regs *regs)
@@ -147,7 +128,7 @@ static void dump_pagetable(unsigned long asce, unsigned long address)
goto out;
table = __va(entry & _SEGMENT_ENTRY_ORIGIN);
}
- table += (address & _PAGE_INDEX) >> _PAGE_SHIFT;
+ table += (address & _PAGE_INDEX) >> PAGE_SHIFT;
if (get_kernel_nofault(entry, table))
goto bad;
pr_cont("P:%016lx ", entry);
@@ -181,21 +162,12 @@ static void dump_fault_info(struct pt_regs *regs)
break;
}
pr_cont("mode while using ");
- switch (get_fault_type(regs)) {
- case USER_FAULT:
- asce = get_lowcore()->user_asce.val;
- pr_cont("user ");
- break;
- case GMAP_FAULT:
- asce = ((struct gmap *)get_lowcore()->gmap)->asce;
- pr_cont("gmap ");
- break;
- case KERNEL_FAULT:
+ if (is_kernel_fault(regs)) {
asce = get_lowcore()->kernel_asce.val;
pr_cont("kernel ");
- break;
- default:
- unreachable();
+ } else {
+ asce = get_lowcore()->user_asce.val;
+ pr_cont("user ");
}
pr_cont("ASCE.\n");
dump_pagetable(asce, get_fault_address(regs));
@@ -230,7 +202,6 @@ static void do_sigsegv(struct pt_regs *regs, int si_code)
static void handle_fault_error_nolock(struct pt_regs *regs, int si_code)
{
- enum fault_type fault_type;
unsigned long address;
bool is_write;
@@ -241,17 +212,15 @@ static void handle_fault_error_nolock(struct pt_regs *regs, int si_code)
}
if (fixup_exception(regs))
return;
- fault_type = get_fault_type(regs);
- if (fault_type == KERNEL_FAULT) {
+ if (is_kernel_fault(regs)) {
address = get_fault_address(regs);
is_write = fault_is_write(regs);
if (kfence_handle_page_fault(address, is_write, regs))
return;
- }
- if (fault_type == KERNEL_FAULT)
pr_alert("Unable to handle kernel pointer dereference in virtual kernel address space\n");
- else
+ } else {
pr_alert("Unable to handle kernel paging request in virtual user address space\n");
+ }
dump_fault_info(regs);
die(regs, "Oops");
}
@@ -285,9 +254,7 @@ static void do_exception(struct pt_regs *regs, int access)
struct vm_area_struct *vma;
unsigned long address;
struct mm_struct *mm;
- enum fault_type type;
unsigned int flags;
- struct gmap *gmap;
vm_fault_t fault;
bool is_write;
@@ -301,16 +268,8 @@ static void do_exception(struct pt_regs *regs, int access)
mm = current->mm;
address = get_fault_address(regs);
is_write = fault_is_write(regs);
- type = get_fault_type(regs);
- switch (type) {
- case KERNEL_FAULT:
+ if (is_kernel_fault(regs) || faulthandler_disabled() || !mm)
return handle_fault_error_nolock(regs, 0);
- case USER_FAULT:
- case GMAP_FAULT:
- if (faulthandler_disabled() || !mm)
- return handle_fault_error_nolock(regs, 0);
- break;
- }
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
flags = FAULT_FLAG_DEFAULT;
if (user_mode(regs))
@@ -334,14 +293,11 @@ static void do_exception(struct pt_regs *regs, int access)
vma_end_read(vma);
if (!(fault & VM_FAULT_RETRY)) {
count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
- if (unlikely(fault & VM_FAULT_ERROR))
- goto error;
- return;
+ goto done;
}
count_vm_vma_lock_event(VMA_LOCK_RETRY);
if (fault & VM_FAULT_MAJOR)
flags |= FAULT_FLAG_TRIED;
-
/* Quick path to respond to signals */
if (fault_signal_pending(fault, regs)) {
if (!user_mode(regs))
@@ -349,81 +305,29 @@ static void do_exception(struct pt_regs *regs, int access)
return;
}
lock_mmap:
- mmap_read_lock(mm);
- gmap = NULL;
- if (IS_ENABLED(CONFIG_PGSTE) && type == GMAP_FAULT) {
- gmap = (struct gmap *)get_lowcore()->gmap;
- current->thread.gmap_addr = address;
- current->thread.gmap_write_flag = !!(flags & FAULT_FLAG_WRITE);
- current->thread.gmap_int_code = regs->int_code & 0xffff;
- address = __gmap_translate(gmap, address);
- if (address == -EFAULT)
- return handle_fault_error(regs, SEGV_MAPERR);
- if (gmap->pfault_enabled)
- flags |= FAULT_FLAG_RETRY_NOWAIT;
- }
retry:
- vma = find_vma(mm, address);
+ vma = lock_mm_and_find_vma(mm, address, regs);
if (!vma)
- return handle_fault_error(regs, SEGV_MAPERR);
- if (unlikely(vma->vm_start > address)) {
- if (!(vma->vm_flags & VM_GROWSDOWN))
- return handle_fault_error(regs, SEGV_MAPERR);
- vma = expand_stack(mm, address);
- if (!vma)
- return handle_fault_error_nolock(regs, SEGV_MAPERR);
- }
+ return handle_fault_error_nolock(regs, SEGV_MAPERR);
if (unlikely(!(vma->vm_flags & access)))
return handle_fault_error(regs, SEGV_ACCERR);
fault = handle_mm_fault(vma, address, flags, regs);
if (fault_signal_pending(fault, regs)) {
- if (flags & FAULT_FLAG_RETRY_NOWAIT)
- mmap_read_unlock(mm);
if (!user_mode(regs))
handle_fault_error_nolock(regs, 0);
return;
}
/* The fault is fully completed (including releasing mmap lock) */
- if (fault & VM_FAULT_COMPLETED) {
- if (gmap) {
- mmap_read_lock(mm);
- goto gmap;
- }
+ if (fault & VM_FAULT_COMPLETED)
return;
- }
- if (unlikely(fault & VM_FAULT_ERROR)) {
- mmap_read_unlock(mm);
- goto error;
- }
if (fault & VM_FAULT_RETRY) {
- if (IS_ENABLED(CONFIG_PGSTE) && gmap && (flags & FAULT_FLAG_RETRY_NOWAIT)) {
- /*
- * FAULT_FLAG_RETRY_NOWAIT has been set,
- * mmap_lock has not been released
- */
- current->thread.gmap_pfault = 1;
- return handle_fault_error(regs, 0);
- }
- flags &= ~FAULT_FLAG_RETRY_NOWAIT;
flags |= FAULT_FLAG_TRIED;
- mmap_read_lock(mm);
goto retry;
}
-gmap:
- if (IS_ENABLED(CONFIG_PGSTE) && gmap) {
- address = __gmap_link(gmap, current->thread.gmap_addr,
- address);
- if (address == -EFAULT)
- return handle_fault_error(regs, SEGV_MAPERR);
- if (address == -ENOMEM) {
- fault = VM_FAULT_OOM;
- mmap_read_unlock(mm);
- goto error;
- }
- }
mmap_read_unlock(mm);
- return;
-error:
+done:
+ if (!(fault & VM_FAULT_ERROR))
+ return;
if (fault & VM_FAULT_OOM) {
if (!user_mode(regs))
handle_fault_error_nolock(regs, 0);
@@ -434,7 +338,8 @@ error:
handle_fault_error_nolock(regs, 0);
else
do_sigsegv(regs, SEGV_MAPERR);
- } else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON)) {
+ } else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON |
+ VM_FAULT_HWPOISON_LARGE)) {
if (!user_mode(regs))
handle_fault_error_nolock(regs, 0);
else
@@ -496,7 +401,6 @@ void do_secure_storage_access(struct pt_regs *regs)
struct folio_walk fw;
struct mm_struct *mm;
struct folio *folio;
- struct gmap *gmap;
int rc;
/*
@@ -521,17 +425,15 @@ void do_secure_storage_access(struct pt_regs *regs)
*/
panic("Unexpected PGM 0x3d with TEID bit 61=0");
}
- switch (get_fault_type(regs)) {
- case GMAP_FAULT:
- mm = current->mm;
- gmap = (struct gmap *)get_lowcore()->gmap;
- mmap_read_lock(mm);
- addr = __gmap_translate(gmap, addr);
- mmap_read_unlock(mm);
- if (IS_ERR_VALUE(addr))
- return handle_fault_error_nolock(regs, SEGV_MAPERR);
- fallthrough;
- case USER_FAULT:
+ if (is_kernel_fault(regs)) {
+ folio = phys_to_folio(addr);
+ if (unlikely(!folio_try_get(folio)))
+ return;
+ rc = arch_make_folio_accessible(folio);
+ folio_put(folio);
+ if (rc)
+ BUG();
+ } else {
mm = current->mm;
mmap_read_lock(mm);
vma = find_vma(mm, addr);
@@ -540,7 +442,7 @@ void do_secure_storage_access(struct pt_regs *regs)
folio = folio_walk_start(&fw, vma, addr, 0);
if (!folio) {
mmap_read_unlock(mm);
- break;
+ return;
}
/* arch_make_folio_accessible() needs a raised refcount. */
folio_get(folio);
@@ -550,56 +452,8 @@ void do_secure_storage_access(struct pt_regs *regs)
if (rc)
send_sig(SIGSEGV, current, 0);
mmap_read_unlock(mm);
- break;
- case KERNEL_FAULT:
- folio = phys_to_folio(addr);
- if (unlikely(!folio_try_get(folio)))
- break;
- rc = arch_make_folio_accessible(folio);
- folio_put(folio);
- if (rc)
- BUG();
- break;
- default:
- unreachable();
}
}
NOKPROBE_SYMBOL(do_secure_storage_access);
-void do_non_secure_storage_access(struct pt_regs *regs)
-{
- struct gmap *gmap = (struct gmap *)get_lowcore()->gmap;
- unsigned long gaddr = get_fault_address(regs);
-
- if (WARN_ON_ONCE(get_fault_type(regs) != GMAP_FAULT))
- return handle_fault_error_nolock(regs, SEGV_MAPERR);
- if (gmap_convert_to_secure(gmap, gaddr) == -EINVAL)
- send_sig(SIGSEGV, current, 0);
-}
-NOKPROBE_SYMBOL(do_non_secure_storage_access);
-
-void do_secure_storage_violation(struct pt_regs *regs)
-{
- struct gmap *gmap = (struct gmap *)get_lowcore()->gmap;
- unsigned long gaddr = get_fault_address(regs);
-
- /*
- * If the VM has been rebooted, its address space might still contain
- * secure pages from the previous boot.
- * Clear the page so it can be reused.
- */
- if (!gmap_destroy_page(gmap, gaddr))
- return;
- /*
- * Either KVM messed up the secure guest mapping or the same
- * page is mapped into multiple secure guests.
- *
- * This exception is only triggered when a guest 2 is running
- * and can therefore never occur in kernel context.
- */
- pr_warn_ratelimited("Secure storage violation in task: %s, pid %d\n",
- current->comm, current->pid);
- send_sig(SIGSEGV, current, 0);
-}
-
#endif /* CONFIG_PGSTE */
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index eb0b51a36be0..16b8a36c56de 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -281,37 +281,6 @@ void gmap_remove(struct gmap *gmap)
}
EXPORT_SYMBOL_GPL(gmap_remove);
-/**
- * gmap_enable - switch primary space to the guest address space
- * @gmap: pointer to the guest address space structure
- */
-void gmap_enable(struct gmap *gmap)
-{
- get_lowcore()->gmap = (unsigned long)gmap;
-}
-EXPORT_SYMBOL_GPL(gmap_enable);
-
-/**
- * gmap_disable - switch back to the standard primary address space
- * @gmap: pointer to the guest address space structure
- */
-void gmap_disable(struct gmap *gmap)
-{
- get_lowcore()->gmap = 0UL;
-}
-EXPORT_SYMBOL_GPL(gmap_disable);
-
-/**
- * gmap_get_enabled - get a pointer to the currently enabled gmap
- *
- * Returns a pointer to the currently enabled gmap. 0 if none is enabled.
- */
-struct gmap *gmap_get_enabled(void)
-{
- return (struct gmap *)get_lowcore()->gmap;
-}
-EXPORT_SYMBOL_GPL(gmap_get_enabled);
-
/*
* gmap_alloc_table is assumed to be called with mmap_lock held
*/
@@ -618,7 +587,8 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
if (pmd_leaf(*pmd)) {
*table = (pmd_val(*pmd) &
_SEGMENT_ENTRY_HARDWARE_BITS_LARGE)
- | _SEGMENT_ENTRY_GMAP_UC;
+ | _SEGMENT_ENTRY_GMAP_UC
+ | _SEGMENT_ENTRY;
} else
*table = pmd_val(*pmd) &
_SEGMENT_ENTRY_HARDWARE_BITS;
@@ -637,44 +607,124 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
}
/**
- * gmap_fault - resolve a fault on a guest address
+ * fixup_user_fault_nowait - manually resolve a user page fault without waiting
+ * @mm: mm_struct of target mm
+ * @address: user address
+ * @fault_flags:flags to pass down to handle_mm_fault()
+ * @unlocked: did we unlock the mmap_lock while retrying
+ *
+ * This function behaves similarly to fixup_user_fault(), but it guarantees
+ * that the fault will be resolved without waiting. The function might drop
+ * and re-acquire the mm lock, in which case @unlocked will be set to true.
+ *
+ * The guarantee is that the fault is handled without waiting, but the
+ * function itself might sleep, due to the lock.
+ *
+ * Context: Needs to be called with mm->mmap_lock held in read mode, and will
+ * return with the lock held in read mode; @unlocked will indicate whether
+ * the lock has been dropped and re-acquired. This is the same behaviour as
+ * fixup_user_fault().
+ *
+ * Return: 0 on success, -EAGAIN if the fault cannot be resolved without
+ * waiting, -EFAULT if the fault cannot be resolved, -ENOMEM if out of
+ * memory.
+ */
+static int fixup_user_fault_nowait(struct mm_struct *mm, unsigned long address,
+ unsigned int fault_flags, bool *unlocked)
+{
+ struct vm_area_struct *vma;
+ unsigned int test_flags;
+ vm_fault_t fault;
+ int rc;
+
+ fault_flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT;
+ test_flags = fault_flags & FAULT_FLAG_WRITE ? VM_WRITE : VM_READ;
+
+ vma = find_vma(mm, address);
+ if (unlikely(!vma || address < vma->vm_start))
+ return -EFAULT;
+ if (unlikely(!(vma->vm_flags & test_flags)))
+ return -EFAULT;
+
+ fault = handle_mm_fault(vma, address, fault_flags, NULL);
+ /* the mm lock has been dropped, take it again */
+ if (fault & VM_FAULT_COMPLETED) {
+ *unlocked = true;
+ mmap_read_lock(mm);
+ return 0;
+ }
+ /* the mm lock has not been dropped */
+ if (fault & VM_FAULT_ERROR) {
+ rc = vm_fault_to_errno(fault, 0);
+ BUG_ON(!rc);
+ return rc;
+ }
+ /* the mm lock has not been dropped because of FAULT_FLAG_RETRY_NOWAIT */
+ if (fault & VM_FAULT_RETRY)
+ return -EAGAIN;
+ /* nothing needed to be done and the mm lock has not been dropped */
+ return 0;
+}
+
+/**
+ * __gmap_fault - resolve a fault on a guest address
* @gmap: pointer to guest mapping meta data structure
* @gaddr: guest address
* @fault_flags: flags to pass down to handle_mm_fault()
*
- * Returns 0 on success, -ENOMEM for out of memory conditions, and -EFAULT
- * if the vm address is already mapped to a different guest segment.
+ * Context: Needs to be called with mm->mmap_lock held in read mode. Might
+ * drop and re-acquire the lock. Will always return with the lock held.
*/
-int gmap_fault(struct gmap *gmap, unsigned long gaddr,
- unsigned int fault_flags)
+static int __gmap_fault(struct gmap *gmap, unsigned long gaddr, unsigned int fault_flags)
{
unsigned long vmaddr;
- int rc;
bool unlocked;
-
- mmap_read_lock(gmap->mm);
+ int rc = 0;
retry:
unlocked = false;
+
vmaddr = __gmap_translate(gmap, gaddr);
- if (IS_ERR_VALUE(vmaddr)) {
- rc = vmaddr;
- goto out_up;
- }
- if (fixup_user_fault(gmap->mm, vmaddr, fault_flags,
- &unlocked)) {
- rc = -EFAULT;
- goto out_up;
- }
+ if (IS_ERR_VALUE(vmaddr))
+ return vmaddr;
+
+ if (fault_flags & FAULT_FLAG_RETRY_NOWAIT)
+ rc = fixup_user_fault_nowait(gmap->mm, vmaddr, fault_flags, &unlocked);
+ else
+ rc = fixup_user_fault(gmap->mm, vmaddr, fault_flags, &unlocked);
+ if (rc)
+ return rc;
/*
* In the case that fixup_user_fault unlocked the mmap_lock during
- * faultin redo __gmap_translate to not race with a map/unmap_segment.
+ * fault-in, redo __gmap_translate() to avoid racing with a
+ * map/unmap_segment.
+ * In particular, __gmap_translate(), fixup_user_fault{,_nowait}(),
+ * and __gmap_link() must all be called atomically in one go; if the
+ * lock had been dropped in between, a retry is needed.
*/
if (unlocked)
goto retry;
- rc = __gmap_link(gmap, gaddr, vmaddr);
-out_up:
+ return __gmap_link(gmap, gaddr, vmaddr);
+}
+
+/**
+ * gmap_fault - resolve a fault on a guest address
+ * @gmap: pointer to guest mapping meta data structure
+ * @gaddr: guest address
+ * @fault_flags: flags to pass down to handle_mm_fault()
+ *
+ * Returns 0 on success, -ENOMEM for out of memory conditions, -EFAULT if the
+ * vm address is already mapped to a different guest segment, and -EAGAIN if
+ * FAULT_FLAG_RETRY_NOWAIT was specified and the fault could not be processed
+ * immediately.
+ */
+int gmap_fault(struct gmap *gmap, unsigned long gaddr, unsigned int fault_flags)
+{
+ int rc;
+
+ mmap_read_lock(gmap->mm);
+ rc = __gmap_fault(gmap, gaddr, fault_flags);
mmap_read_unlock(gmap->mm);
return rc;
}
@@ -851,7 +901,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
if (*table & _REGION_ENTRY_INVALID)
return NULL;
table = __va(*table & _SEGMENT_ENTRY_ORIGIN);
- table += (gaddr & _PAGE_INDEX) >> _PAGE_SHIFT;
+ table += (gaddr & _PAGE_INDEX) >> PAGE_SHIFT;
}
return table;
}
@@ -1317,7 +1367,7 @@ static void gmap_unshadow_page(struct gmap *sg, unsigned long raddr)
table = gmap_table_walk(sg, raddr, 0); /* get page table pointer */
if (!table || *table & _PAGE_INVALID)
return;
- gmap_call_notifier(sg, raddr, raddr + _PAGE_SIZE - 1);
+ gmap_call_notifier(sg, raddr, raddr + PAGE_SIZE - 1);
ptep_unshadow_pte(sg->mm, raddr, (pte_t *) table);
}
@@ -1335,7 +1385,7 @@ static void __gmap_unshadow_pgt(struct gmap *sg, unsigned long raddr,
int i;
BUG_ON(!gmap_is_shadow(sg));
- for (i = 0; i < _PAGE_ENTRIES; i++, raddr += _PAGE_SIZE)
+ for (i = 0; i < _PAGE_ENTRIES; i++, raddr += PAGE_SIZE)
pgt[i] = _PAGE_INVALID;
}
@@ -2347,7 +2397,8 @@ static void gmap_pmdp_clear(struct mm_struct *mm, unsigned long vmaddr,
gaddr = __gmap_segment_gaddr((unsigned long *)pmdp);
pmdp_notify_gmap(gmap, pmdp, gaddr);
WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
- _SEGMENT_ENTRY_GMAP_UC));
+ _SEGMENT_ENTRY_GMAP_UC |
+ _SEGMENT_ENTRY));
if (purge)
__pmdp_csp(pmdp);
set_pmd(pmdp, __pmd(_SEGMENT_ENTRY_EMPTY));
@@ -2401,7 +2452,8 @@ void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr)
gaddr = __gmap_segment_gaddr(entry);
pmdp_notify_gmap(gmap, pmdp, gaddr);
WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
- _SEGMENT_ENTRY_GMAP_UC));
+ _SEGMENT_ENTRY_GMAP_UC |
+ _SEGMENT_ENTRY));
if (MACHINE_HAS_TLB_GUEST)
__pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE,
gmap->asce, IDTE_LOCAL);
@@ -2436,7 +2488,8 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr)
gaddr = __gmap_segment_gaddr(entry);
pmdp_notify_gmap(gmap, pmdp, gaddr);
WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
- _SEGMENT_ENTRY_GMAP_UC));
+ _SEGMENT_ENTRY_GMAP_UC |
+ _SEGMENT_ENTRY));
if (MACHINE_HAS_TLB_GUEST)
__pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE,
gmap->asce, IDTE_GLOBAL);
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index ded0eff58a19..d9ce199953de 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -24,6 +24,7 @@
static inline unsigned long __pte_to_rste(pte_t pte)
{
+ swp_entry_t arch_entry;
unsigned long rste;
/*
@@ -48,6 +49,7 @@ static inline unsigned long __pte_to_rste(pte_t pte)
*/
if (pte_present(pte)) {
rste = pte_val(pte) & PAGE_MASK;
+ rste |= _SEGMENT_ENTRY_PRESENT;
rste |= move_set_bit(pte_val(pte), _PAGE_READ,
_SEGMENT_ENTRY_READ);
rste |= move_set_bit(pte_val(pte), _PAGE_WRITE,
@@ -66,6 +68,10 @@ static inline unsigned long __pte_to_rste(pte_t pte)
#endif
rste |= move_set_bit(pte_val(pte), _PAGE_NOEXEC,
_SEGMENT_ENTRY_NOEXEC);
+ } else if (!pte_none(pte)) {
+ /* swap pte */
+ arch_entry = __pte_to_swp_entry(pte);
+ rste = mk_swap_rste(__swp_type(arch_entry), __swp_offset(arch_entry));
} else
rste = _SEGMENT_ENTRY_EMPTY;
return rste;
@@ -73,13 +79,18 @@ static inline unsigned long __pte_to_rste(pte_t pte)
static inline pte_t __rste_to_pte(unsigned long rste)
{
+ swp_entry_t arch_entry;
unsigned long pteval;
- int present;
+ int present, none;
+ pte_t pte;
- if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
+ if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
present = pud_present(__pud(rste));
- else
+ none = pud_none(__pud(rste));
+ } else {
present = pmd_present(__pmd(rste));
+ none = pmd_none(__pmd(rste));
+ }
/*
* Convert encoding pmd / pud bits pte bits
@@ -114,6 +125,11 @@ static inline pte_t __rste_to_pte(unsigned long rste)
pteval |= move_set_bit(rste, _SEGMENT_ENTRY_SOFT_DIRTY, _PAGE_SOFT_DIRTY);
#endif
pteval |= move_set_bit(rste, _SEGMENT_ENTRY_NOEXEC, _PAGE_NOEXEC);
+ } else if (!none) {
+ /* swap rste */
+ arch_entry = __rste_to_swp_entry(rste);
+ pte = mk_swap_pte(__swp_type_rste(arch_entry), __swp_offset_rste(arch_entry));
+ pteval = pte_val(pte);
} else
pteval = _PAGE_INVALID;
return __pte(pteval);
@@ -148,8 +164,6 @@ void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
unsigned long rste;
rste = __pte_to_rste(pte);
- if (!MACHINE_HAS_NX)
- rste &= ~_SEGMENT_ENTRY_NOEXEC;
/* Set correct table type for 2G hugepages */
if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
@@ -223,11 +237,10 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
p4dp = p4d_offset(pgdp, addr);
if (p4d_present(*p4dp)) {
pudp = pud_offset(p4dp, addr);
- if (pud_present(*pudp)) {
- if (pud_leaf(*pudp))
- return (pte_t *) pudp;
+ if (sz == PUD_SIZE)
+ return (pte_t *)pudp;
+ if (pud_present(*pudp))
pmdp = pmd_offset(pudp, addr);
- }
}
}
return (pte_t *) pmdp;
@@ -242,88 +255,3 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
else
return false;
}
-
-static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
- unsigned long addr, unsigned long len,
- unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
- struct vm_unmapped_area_info info = {};
-
- info.length = len;
- info.low_limit = current->mm->mmap_base;
- info.high_limit = TASK_SIZE;
- info.align_mask = PAGE_MASK & ~huge_page_mask(h);
- return vm_unmapped_area(&info);
-}
-
-static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
- unsigned long addr0, unsigned long len,
- unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
- struct vm_unmapped_area_info info = {};
- unsigned long addr;
-
- info.flags = VM_UNMAPPED_AREA_TOPDOWN;
- info.length = len;
- info.low_limit = PAGE_SIZE;
- info.high_limit = current->mm->mmap_base;
- info.align_mask = PAGE_MASK & ~huge_page_mask(h);
- addr = vm_unmapped_area(&info);
-
- /*
- * A failed mmap() very likely causes application failure,
- * so fall back to the bottom-up function here. This scenario
- * can happen with large stack limits and large mmap()
- * allocations.
- */
- if (addr & ~PAGE_MASK) {
- VM_BUG_ON(addr != -ENOMEM);
- info.flags = 0;
- info.low_limit = TASK_UNMAPPED_BASE;
- info.high_limit = TASK_SIZE;
- addr = vm_unmapped_area(&info);
- }
-
- return addr;
-}
-
-unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
-
- if (len & ~huge_page_mask(h))
- return -EINVAL;
- if (len > TASK_SIZE - mmap_min_addr)
- return -ENOMEM;
-
- if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(file, addr, len))
- return -EINVAL;
- goto check_asce_limit;
- }
-
- if (addr) {
- addr = ALIGN(addr, huge_page_size(h));
- vma = find_vma(mm, addr);
- if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
- (!vma || addr + len <= vm_start_gap(vma)))
- goto check_asce_limit;
- }
-
- if (!test_bit(MMF_TOPDOWN, &mm->flags))
- addr = hugetlb_get_unmapped_area_bottomup(file, addr, len,
- pgoff, flags);
- else
- addr = hugetlb_get_unmapped_area_topdown(file, addr, len,
- pgoff, flags);
- if (offset_in_page(addr))
- return addr;
-
-check_asce_limit:
- return check_asce_limit(mm, addr, len);
-}
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index 96efa061ce01..33f3504be90b 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -17,6 +17,7 @@
#include <linux/random.h>
#include <linux/compat.h>
#include <linux/security.h>
+#include <linux/hugetlb.h>
#include <asm/elf.h>
static unsigned long stack_maxrandom_size(void)
@@ -73,6 +74,8 @@ static inline unsigned long mmap_base(unsigned long rnd,
static int get_align_mask(struct file *filp, unsigned long flags)
{
+ if (filp && is_file_hugepages(filp))
+ return huge_page_mask_align(filp);
if (!(current->flags & PF_RANDOMIZE))
return 0;
if (filp || (flags & MAP_SHARED))
@@ -106,7 +109,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
info.low_limit = mm->mmap_base;
info.high_limit = TASK_SIZE;
info.align_mask = get_align_mask(filp, flags);
- info.align_offset = pgoff << PAGE_SHIFT;
+ if (!(filp && is_file_hugepages(filp)))
+ info.align_offset = pgoff << PAGE_SHIFT;
addr = vm_unmapped_area(&info);
if (offset_in_page(addr))
return addr;
@@ -144,7 +148,8 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long ad
info.low_limit = PAGE_SIZE;
info.high_limit = mm->mmap_base;
info.align_mask = get_align_mask(filp, flags);
- info.align_offset = pgoff << PAGE_SHIFT;
+ if (!(filp && is_file_hugepages(filp)))
+ info.align_offset = pgoff << PAGE_SHIFT;
addr = vm_unmapped_area(&info);
/*
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 5f805ad42d4c..8f56a21a077f 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -12,6 +12,7 @@
#include <asm/pgalloc.h>
#include <asm/kfence.h>
#include <asm/page.h>
+#include <asm/asm.h>
#include <asm/set_memory.h>
static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
@@ -406,6 +407,33 @@ int set_direct_map_default_noflush(struct page *page)
return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_DEF);
}
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
+{
+ unsigned long flags;
+
+ if (valid)
+ flags = SET_MEMORY_DEF;
+ else
+ flags = SET_MEMORY_INV;
+
+ return __set_memory((unsigned long)page_to_virt(page), nr, flags);
+}
+
+bool kernel_page_present(struct page *page)
+{
+ unsigned long addr;
+ unsigned int cc;
+
+ addr = (unsigned long)page_address(page);
+ asm volatile(
+ " lra %[addr],0(%[addr])\n"
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [addr] "+a" (addr)
+ :
+ : CC_CLOBBER);
+ return CC_TRANSFORM(cc) == 0;
+}
+
#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
static void ipte_range(pte_t *pte, unsigned long address, int nr)
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index f691e0fb66a2..58696a0c4e4a 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -278,7 +278,7 @@ static inline unsigned long base_##NAME##_addr_end(unsigned long addr, \
return (next - 1) < (end - 1) ? next : end; \
}
-BASE_ADDR_END_FUNC(page, _PAGE_SIZE)
+BASE_ADDR_END_FUNC(page, PAGE_SIZE)
BASE_ADDR_END_FUNC(segment, _SEGMENT_SIZE)
BASE_ADDR_END_FUNC(region3, _REGION3_SIZE)
BASE_ADDR_END_FUNC(region2, _REGION2_SIZE)
@@ -302,7 +302,7 @@ static int base_page_walk(unsigned long *origin, unsigned long addr,
if (!alloc)
return 0;
pte = origin;
- pte += (addr & _PAGE_INDEX) >> _PAGE_SHIFT;
+ pte += (addr & _PAGE_INDEX) >> PAGE_SHIFT;
do {
next = base_page_addr_end(addr, end);
*pte = base_lra(addr);
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 2c944bafb030..cea5dba80468 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -525,7 +525,7 @@ static inline void pudp_idte_global(struct mm_struct *mm,
else
/*
* Invalid bit position is the same for pmd and pud, so we can
- * re-use _pmd_csp() here
+ * reuse _pmd_csp() here
*/
__pmdp_csp((pmd_t *) pudp);
}
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index bd9624c20b80..88f72745fa59 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -29,6 +29,7 @@
#include <linux/pci.h>
#include <linux/printk.h>
#include <linux/lockdep.h>
+#include <linux/list_sort.h>
#include <asm/isc.h>
#include <asm/airq.h>
@@ -160,6 +161,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_SET_MEASURE);
struct zpci_iommu_ctrs *ctrs;
struct zpci_fib fib = {0};
+ unsigned long flags;
u8 cc, status;
if (zdev->fmb || sizeof(*zdev->fmb) < zdev->fmb_length)
@@ -171,6 +173,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
WARN_ON((u64) zdev->fmb & 0xf);
/* reset software counters */
+ spin_lock_irqsave(&zdev->dom_lock, flags);
ctrs = zpci_get_iommu_ctrs(zdev);
if (ctrs) {
atomic64_set(&ctrs->mapped_pages, 0);
@@ -179,6 +182,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
atomic64_set(&ctrs->sync_map_rpcits, 0);
atomic64_set(&ctrs->sync_rpcits, 0);
}
+ spin_unlock_irqrestore(&zdev->dom_lock, flags);
fib.fmb_addr = virt_to_phys(zdev->fmb);
@@ -775,8 +779,9 @@ int zpci_hot_reset_device(struct zpci_dev *zdev)
* @fh: Current Function Handle of the device to be created
* @state: Initial state after creation either Standby or Configured
*
- * Creates a new zpci device and adds it to its, possibly newly created, zbus
- * as well as zpci_list.
+ * Allocates a new struct zpci_dev and queries the platform for its details.
+ * If successful the device can subsequently be added to the zPCI subsystem
+ * using zpci_add_device().
*
* Returns: the zdev on success or an error pointer otherwise
*/
@@ -785,7 +790,6 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state)
struct zpci_dev *zdev;
int rc;
- zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", fid, fh, state);
zdev = kzalloc(sizeof(*zdev), GFP_KERNEL);
if (!zdev)
return ERR_PTR(-ENOMEM);
@@ -800,11 +804,34 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state)
goto error;
zdev->state = state;
- kref_init(&zdev->kref);
mutex_init(&zdev->state_lock);
mutex_init(&zdev->fmb_lock);
mutex_init(&zdev->kzdev_lock);
+ return zdev;
+
+error:
+ zpci_dbg(0, "crt fid:%x, rc:%d\n", fid, rc);
+ kfree(zdev);
+ return ERR_PTR(rc);
+}
+
+/**
+ * zpci_add_device() - Add a previously created zPCI device to the zPCI subsystem
+ * @zdev: The zPCI device to be added
+ *
+ * A struct zpci_dev is added to the zPCI subsystem and to a virtual PCI bus creating
+ * a new one as necessary. A hotplug slot is created and events start to be handled.
+ * If successful from this point on zpci_zdev_get() and zpci_zdev_put() must be used.
+ * If adding the struct zpci_dev fails the device was not added and should be freed.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int zpci_add_device(struct zpci_dev *zdev)
+{
+ int rc;
+
+ zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", zdev->fid, zdev->fh, zdev->state);
rc = zpci_init_iommu(zdev);
if (rc)
goto error;
@@ -813,18 +840,17 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state)
if (rc)
goto error_destroy_iommu;
+ kref_init(&zdev->kref);
spin_lock(&zpci_list_lock);
list_add_tail(&zdev->entry, &zpci_list);
spin_unlock(&zpci_list_lock);
-
- return zdev;
+ return 0;
error_destroy_iommu:
zpci_destroy_iommu(zdev);
error:
- zpci_dbg(0, "add fid:%x, rc:%d\n", fid, rc);
- kfree(zdev);
- return ERR_PTR(rc);
+ zpci_dbg(0, "add fid:%x, rc:%d\n", zdev->fid, rc);
+ return rc;
}
bool zpci_is_device_configured(struct zpci_dev *zdev)
@@ -914,10 +940,8 @@ void zpci_device_reserved(struct zpci_dev *zdev)
void zpci_release_device(struct kref *kref)
{
struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
- int ret;
- if (zdev->has_hp_slot)
- zpci_exit_slot(zdev);
+ WARN_ON(zdev->state != ZPCI_FN_STATE_RESERVED);
if (zdev->zbus->bus)
zpci_bus_remove_device(zdev, false);
@@ -925,28 +949,14 @@ void zpci_release_device(struct kref *kref)
if (zdev_enabled(zdev))
zpci_disable_device(zdev);
- switch (zdev->state) {
- case ZPCI_FN_STATE_CONFIGURED:
- ret = sclp_pci_deconfigure(zdev->fid);
- zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
- fallthrough;
- case ZPCI_FN_STATE_STANDBY:
- if (zdev->has_hp_slot)
- zpci_exit_slot(zdev);
- spin_lock(&zpci_list_lock);
- list_del(&zdev->entry);
- spin_unlock(&zpci_list_lock);
- zpci_dbg(3, "rsv fid:%x\n", zdev->fid);
- fallthrough;
- case ZPCI_FN_STATE_RESERVED:
- if (zdev->has_resources)
- zpci_cleanup_bus_resources(zdev);
- zpci_bus_device_unregister(zdev);
- zpci_destroy_iommu(zdev);
- fallthrough;
- default:
- break;
- }
+ if (zdev->has_hp_slot)
+ zpci_exit_slot(zdev);
+
+ if (zdev->has_resources)
+ zpci_cleanup_bus_resources(zdev);
+
+ zpci_bus_device_unregister(zdev);
+ zpci_destroy_iommu(zdev);
zpci_dbg(3, "rem fid:%x\n", zdev->fid);
kfree_rcu(zdev, rcu);
}
@@ -1082,6 +1092,50 @@ bool zpci_is_enabled(void)
return s390_pci_initialized;
}
+static int zpci_cmp_rid(void *priv, const struct list_head *a,
+ const struct list_head *b)
+{
+ struct zpci_dev *za = container_of(a, struct zpci_dev, entry);
+ struct zpci_dev *zb = container_of(b, struct zpci_dev, entry);
+
+ /*
+ * PCI functions without RID available maintain original order
+ * between themselves but sort before those with RID.
+ */
+ if (za->rid == zb->rid)
+ return za->rid_available > zb->rid_available;
+ /*
+ * PCI functions with RID sort by RID ascending.
+ */
+ return za->rid > zb->rid;
+}
+
+static void zpci_add_devices(struct list_head *scan_list)
+{
+ struct zpci_dev *zdev, *tmp;
+
+ list_sort(NULL, scan_list, &zpci_cmp_rid);
+ list_for_each_entry_safe(zdev, tmp, scan_list, entry) {
+ list_del_init(&zdev->entry);
+ if (zpci_add_device(zdev))
+ kfree(zdev);
+ }
+}
+
+int zpci_scan_devices(void)
+{
+ LIST_HEAD(scan_list);
+ int rc;
+
+ rc = clp_scan_pci_devices(&scan_list);
+ if (rc)
+ return rc;
+
+ zpci_add_devices(&scan_list);
+ zpci_bus_scan_busses();
+ return 0;
+}
+
static int __init pci_base_init(void)
{
int rc;
@@ -1111,10 +1165,9 @@ static int __init pci_base_init(void)
if (rc)
goto out_irq;
- rc = clp_scan_pci_devices();
+ rc = zpci_scan_devices();
if (rc)
goto out_find;
- zpci_bus_scan_busses();
s390_pci_initialized = 1;
return 0;
diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c
index daa5d7450c7d..d5ace00d10f0 100644
--- a/arch/s390/pci/pci_bus.c
+++ b/arch/s390/pci/pci_bus.c
@@ -53,7 +53,7 @@ static int zpci_bus_prepare_device(struct zpci_dev *zdev)
zpci_setup_bus_resources(zdev);
for (i = 0; i < PCI_STD_NUM_BARS; i++) {
if (zdev->bars[i].res)
- pci_bus_add_resource(zdev->zbus->bus, zdev->bars[i].res, 0);
+ pci_bus_add_resource(zdev->zbus->bus, zdev->bars[i].res);
}
}
@@ -168,9 +168,16 @@ void zpci_bus_scan_busses(void)
mutex_unlock(&zbus_list_lock);
}
+static bool zpci_bus_is_multifunction_root(struct zpci_dev *zdev)
+{
+ return !s390_pci_no_rid && zdev->rid_available &&
+ zpci_is_device_configured(zdev) &&
+ !zdev->vfn;
+}
+
/* zpci_bus_create_pci_bus - Create the PCI bus associated with this zbus
* @zbus: the zbus holding the zdevices
- * @fr: PCI root function that will determine the bus's domain, and bus speeed
+ * @fr: PCI root function that will determine the bus's domain, and bus speed
* @ops: the pci operations
*
* The PCI function @fr determines the domain (its UID), multifunction property
@@ -188,7 +195,7 @@ static int zpci_bus_create_pci_bus(struct zpci_bus *zbus, struct zpci_dev *fr, s
return domain;
zbus->domain_nr = domain;
- zbus->multifunction = fr->rid_available;
+ zbus->multifunction = zpci_bus_is_multifunction_root(fr);
zbus->max_bus_speed = fr->max_bus_speed;
/*
@@ -232,13 +239,15 @@ static void zpci_bus_put(struct zpci_bus *zbus)
kref_put(&zbus->kref, zpci_bus_release);
}
-static struct zpci_bus *zpci_bus_get(int pchid)
+static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid)
{
struct zpci_bus *zbus;
mutex_lock(&zbus_list_lock);
list_for_each_entry(zbus, &zbus_list, bus_next) {
- if (pchid == zbus->pchid) {
+ if (!zbus->multifunction)
+ continue;
+ if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) {
kref_get(&zbus->kref);
goto out_unlock;
}
@@ -249,7 +258,7 @@ out_unlock:
return zbus;
}
-static struct zpci_bus *zpci_bus_alloc(int pchid)
+static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid)
{
struct zpci_bus *zbus;
@@ -257,7 +266,8 @@ static struct zpci_bus *zpci_bus_alloc(int pchid)
if (!zbus)
return NULL;
- zbus->pchid = pchid;
+ zbus->topo = topo;
+ zbus->topo_is_tid = topo_is_tid;
INIT_LIST_HEAD(&zbus->bus_next);
mutex_lock(&zbus_list_lock);
list_add_tail(&zbus->bus_next, &zbus_list);
@@ -292,19 +302,22 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
{
int rc = -EINVAL;
+ if (zbus->multifunction) {
+ if (!zdev->rid_available) {
+ WARN_ONCE(1, "rid_available not set for multifunction\n");
+ return rc;
+ }
+ zdev->devfn = zdev->rid & ZPCI_RID_MASK_DEVFN;
+ }
+
if (zbus->function[zdev->devfn]) {
pr_err("devfn %04x is already assigned\n", zdev->devfn);
return rc;
}
-
zdev->zbus = zbus;
zbus->function[zdev->devfn] = zdev;
zpci_nb_devices++;
- if (zbus->multifunction && !zdev->rid_available) {
- WARN_ONCE(1, "rid_available not set for multifunction\n");
- goto error;
- }
rc = zpci_init_slot(zdev);
if (rc)
goto error;
@@ -321,8 +334,9 @@ error:
int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops)
{
+ bool topo_is_tid = zdev->tid_avail;
struct zpci_bus *zbus = NULL;
- int rc = -EBADF;
+ int topo, rc = -EBADF;
if (zpci_nb_devices == ZPCI_NR_DEVICES) {
pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n",
@@ -330,14 +344,10 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops)
return -ENOSPC;
}
- if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS)
- return -EINVAL;
-
- if (!s390_pci_no_rid && zdev->rid_available)
- zbus = zpci_bus_get(zdev->pchid);
-
+ topo = topo_is_tid ? zdev->tid : zdev->pchid;
+ zbus = zpci_bus_get(topo, topo_is_tid);
if (!zbus) {
- zbus = zpci_bus_alloc(zdev->pchid);
+ zbus = zpci_bus_alloc(topo, topo_is_tid);
if (!zbus)
return -ENOMEM;
}
diff --git a/arch/s390/pci/pci_bus.h b/arch/s390/pci/pci_bus.h
index af9f0ac79a1b..e86a9419d233 100644
--- a/arch/s390/pci/pci_bus.h
+++ b/arch/s390/pci/pci_bus.h
@@ -6,6 +6,10 @@
* Pierre Morel <pmorel@linux.ibm.com>
*
*/
+#ifndef __S390_PCI_BUS_H
+#define __S390_PCI_BUS_H
+
+#include <linux/pci.h>
int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops);
void zpci_bus_device_unregister(struct zpci_dev *zdev);
@@ -40,3 +44,4 @@ static inline struct zpci_dev *zdev_from_bus(struct pci_bus *bus,
return (devfn >= ZPCI_FUNCTIONS_PER_BUS) ? NULL : zbus->function[devfn];
}
+#endif /* __S390_PCI_BUS_H */
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
index 6f55a59a0871..14bf7e8d06b7 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -20,6 +20,7 @@
#include <asm/asm-extable.h>
#include <asm/pci_debug.h>
#include <asm/pci_clp.h>
+#include <asm/asm.h>
#include <asm/clp.h>
#include <uapi/asm/clp.h>
@@ -52,18 +53,20 @@ static inline void zpci_err_clp(unsigned int rsp, int rc)
static inline int clp_get_ilp(unsigned long *ilp)
{
unsigned long mask;
- int cc = 3;
+ int cc, exception;
+ exception = 1;
asm volatile (
" .insn rrf,0xb9a00000,%[mask],%[cmd],8,0\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [mask] "=d" (mask) : [cmd] "a" (1)
- : "cc");
+ : CC_OUT(cc, cc), [mask] "=d" (mask), [exc] "+d" (exception)
+ : [cmd] "a" (1)
+ : CC_CLOBBER);
*ilp = mask;
- return cc;
+ return exception ? 3 : CC_TRANSFORM(cc);
}
/*
@@ -72,19 +75,20 @@ static inline int clp_get_ilp(unsigned long *ilp)
static __always_inline int clp_req(void *data, unsigned int lps)
{
struct { u8 _[CLP_BLK_SIZE]; } *req = data;
+ int cc, exception;
u64 ignored;
- int cc = 3;
+ exception = 1;
asm volatile (
" .insn rrf,0xb9a00000,%[ign],%[req],0,%[lps]\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [ign] "=d" (ignored), "+m" (*req)
+ : CC_OUT(cc, cc), [ign] "=d" (ignored), "+m" (*req), [exc] "+d" (exception)
: [req] "a" (req), [lps] "i" (lps)
- : "cc");
- return cc;
+ : CC_CLOBBER);
+ return exception ? 3 : CC_TRANSFORM(cc);
}
static void *clp_alloc_block(gfp_t gfp_mask)
@@ -162,12 +166,16 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev,
zdev->pft = response->pft;
zdev->vfn = response->vfn;
zdev->port = response->port;
+ zdev->fidparm = response->fidparm;
zdev->uid = response->uid;
zdev->fmb_length = sizeof(u32) * response->fmb_len;
- zdev->rid_available = response->rid_avail;
zdev->is_physfn = response->is_physfn;
- if (!s390_pci_no_rid && zdev->rid_available)
- zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN;
+ zdev->rid_available = response->rid_avail;
+ if (zdev->rid_available)
+ zdev->rid = response->rid;
+ zdev->tid_avail = response->tid_avail;
+ if (zdev->tid_avail)
+ zdev->tid = response->tid;
memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip));
if (response->util_str_avail) {
@@ -407,6 +415,7 @@ static int clp_find_pci(struct clp_req_rsp_list_pci *rrb, u32 fid,
static void __clp_add(struct clp_fh_list_entry *entry, void *data)
{
+ struct list_head *scan_list = data;
struct zpci_dev *zdev;
if (!entry->vendor_id)
@@ -417,10 +426,11 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data)
zpci_zdev_put(zdev);
return;
}
- zpci_create_device(entry->fid, entry->fh, entry->config_state);
+ zdev = zpci_create_device(entry->fid, entry->fh, entry->config_state);
+ list_add_tail(&zdev->entry, scan_list);
}
-int clp_scan_pci_devices(void)
+int clp_scan_pci_devices(struct list_head *scan_list)
{
struct clp_req_rsp_list_pci *rrb;
int rc;
@@ -429,7 +439,7 @@ int clp_scan_pci_devices(void)
if (!rrb)
return -ENOMEM;
- rc = clp_list_pci(rrb, NULL, __clp_add);
+ rc = clp_list_pci(rrb, scan_list, __clp_add);
clp_free_block(rrb);
return rc;
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c
index 2cb5043a997d..38014206c16b 100644
--- a/arch/s390/pci/pci_debug.c
+++ b/arch/s390/pci/pci_debug.c
@@ -71,17 +71,23 @@ static void pci_fmb_show(struct seq_file *m, char *name[], int length,
static void pci_sw_counter_show(struct seq_file *m)
{
- struct zpci_iommu_ctrs *ctrs = zpci_get_iommu_ctrs(m->private);
+ struct zpci_dev *zdev = m->private;
+ struct zpci_iommu_ctrs *ctrs;
atomic64_t *counter;
+ unsigned long flags;
int i;
+ spin_lock_irqsave(&zdev->dom_lock, flags);
+ ctrs = zpci_get_iommu_ctrs(m->private);
if (!ctrs)
- return;
+ goto unlock;
counter = &ctrs->mapped_pages;
for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++)
seq_printf(m, "%26s:\t%llu\n", pci_sw_names[i],
atomic64_read(counter));
+unlock:
+ spin_unlock_irqrestore(&zdev->dom_lock, flags);
}
static int pci_perf_show(struct seq_file *m, void *v)
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index d4f19d33914c..7f7b732b3f3e 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -340,6 +340,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED);
if (IS_ERR(zdev))
break;
+ if (zpci_add_device(zdev)) {
+ kfree(zdev);
+ break;
+ }
} else {
/* the configuration request may be stale */
if (zdev->state != ZPCI_FN_STATE_STANDBY)
@@ -349,10 +353,17 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
zpci_scan_configured_device(zdev, ccdf->fh);
break;
case 0x0302: /* Reserved -> Standby */
- if (!zdev)
- zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY);
- else
+ if (!zdev) {
+ zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY);
+ if (IS_ERR(zdev))
+ break;
+ if (zpci_add_device(zdev)) {
+ kfree(zdev);
+ break;
+ }
+ } else {
zpci_update_fh(zdev, ccdf->fh);
+ }
break;
case 0x0303: /* Deconfiguration requested */
if (zdev) {
@@ -381,7 +392,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
break;
case 0x0306: /* 0x308 or 0x302 for multiple devices */
zpci_remove_reserved_devices();
- clp_scan_pci_devices();
+ zpci_scan_devices();
break;
case 0x0308: /* Standby -> Reserved */
if (!zdev)
diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c
index 56480be48244..f5a75ea7629a 100644
--- a/arch/s390/pci/pci_insn.c
+++ b/arch/s390/pci/pci_insn.c
@@ -15,6 +15,7 @@
#include <asm/pci_debug.h>
#include <asm/pci_io.h>
#include <asm/processor.h>
+#include <asm/asm.h>
#define ZPCI_INSN_BUSY_DELAY 1 /* 1 microsecond */
@@ -57,16 +58,16 @@ static inline void zpci_err_insn_addr(int lvl, u8 insn, u8 cc, u8 status,
/* Modify PCI Function Controls */
static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
{
- u8 cc;
+ int cc;
asm volatile (
" .insn rxy,0xe300000000d0,%[req],%[fib]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib)
- : : "cc");
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [req] "+d" (req), [fib] "+Q" (*fib)
+ :
+ : CC_CLOBBER);
*status = req >> 24 & 0xff;
- return cc;
+ return CC_TRANSFORM(cc);
}
u8 zpci_mod_fc(u64 req, struct zpci_fib *fib, u8 *status)
@@ -98,17 +99,16 @@ EXPORT_SYMBOL_GPL(zpci_mod_fc);
static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
{
union register_pair addr_range = {.even = addr, .odd = range};
- u8 cc;
+ int cc;
asm volatile (
" .insn rre,0xb9d30000,%[fn],%[addr_range]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [fn] "+d" (fn)
+ CC_IPM(cc)
+ : CC_OUT(cc, cc), [fn] "+d" (fn)
: [addr_range] "d" (addr_range.pair)
- : "cc");
+ : CC_CLOBBER);
*status = fn >> 24 & 0xff;
- return cc;
+ return CC_TRANSFORM(cc);
}
int zpci_refresh_trans(u64 fn, u64 addr, u64 range)
@@ -156,20 +156,23 @@ EXPORT_SYMBOL_GPL(zpci_set_irq_ctrl);
static inline int ____pcilg(u64 *data, u64 req, u64 offset, u8 *status)
{
union register_pair req_off = {.even = req, .odd = offset};
- int cc = -ENXIO;
+ int cc, exception;
u64 __data;
+ exception = 1;
asm volatile (
" .insn rre,0xb9d20000,%[data],%[req_off]\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [data] "=d" (__data),
- [req_off] "+&d" (req_off.pair) :: "cc");
+ : CC_OUT(cc, cc), [data] "=d" (__data),
+ [req_off] "+d" (req_off.pair), [exc] "+d" (exception)
+ :
+ : CC_CLOBBER);
*status = req_off.even >> 24 & 0xff;
*data = __data;
- return cc;
+ return exception ? -ENXIO : CC_TRANSFORM(cc);
}
static inline int __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
@@ -222,20 +225,23 @@ static inline int zpci_load_fh(u64 *data, const volatile void __iomem *addr,
static inline int __pcilg_mio(u64 *data, u64 ioaddr, u64 len, u8 *status)
{
union register_pair ioaddr_len = {.even = ioaddr, .odd = len};
- int cc = -ENXIO;
+ int cc, exception;
u64 __data;
+ exception = 1;
asm volatile (
" .insn rre,0xb9d60000,%[data],%[ioaddr_len]\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [data] "=d" (__data),
- [ioaddr_len] "+&d" (ioaddr_len.pair) :: "cc");
+ : CC_OUT(cc, cc), [data] "=d" (__data),
+ [ioaddr_len] "+d" (ioaddr_len.pair), [exc] "+d" (exception)
+ :
+ : CC_CLOBBER);
*status = ioaddr_len.odd >> 24 & 0xff;
*data = __data;
- return cc;
+ return exception ? -ENXIO : CC_TRANSFORM(cc);
}
int zpci_load(u64 *data, const volatile void __iomem *addr, unsigned long len)
@@ -258,19 +264,20 @@ EXPORT_SYMBOL_GPL(zpci_load);
static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status)
{
union register_pair req_off = {.even = req, .odd = offset};
- int cc = -ENXIO;
+ int cc, exception;
+ exception = 1;
asm volatile (
" .insn rre,0xb9d00000,%[data],%[req_off]\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [req_off] "+&d" (req_off.pair)
+ : CC_OUT(cc, cc), [req_off] "+d" (req_off.pair), [exc] "+d" (exception)
: [data] "d" (data)
- : "cc");
+ : CC_CLOBBER);
*status = req_off.even >> 24 & 0xff;
- return cc;
+ return exception ? -ENXIO : CC_TRANSFORM(cc);
}
int __zpci_store(u64 data, u64 req, u64 offset)
@@ -311,19 +318,20 @@ static inline int zpci_store_fh(const volatile void __iomem *addr, u64 data,
static inline int __pcistg_mio(u64 data, u64 ioaddr, u64 len, u8 *status)
{
union register_pair ioaddr_len = {.even = ioaddr, .odd = len};
- int cc = -ENXIO;
+ int cc, exception;
+ exception = 1;
asm volatile (
" .insn rre,0xb9d40000,%[data],%[ioaddr_len]\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [ioaddr_len] "+&d" (ioaddr_len.pair)
+ : CC_OUT(cc, cc), [ioaddr_len] "+d" (ioaddr_len.pair), [exc] "+d" (exception)
: [data] "d" (data)
- : "cc", "memory");
+ : CC_CLOBBER_LIST("memory"));
*status = ioaddr_len.odd >> 24 & 0xff;
- return cc;
+ return exception ? -ENXIO : CC_TRANSFORM(cc);
}
int zpci_store(const volatile void __iomem *addr, u64 data, unsigned long len)
@@ -345,19 +353,20 @@ EXPORT_SYMBOL_GPL(zpci_store);
/* PCI Store Block */
static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
{
- int cc = -ENXIO;
+ int cc, exception;
+ exception = 1;
asm volatile (
" .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [req] "+d" (req)
+ : CC_OUT(cc, cc), [req] "+d" (req), [exc] "+d" (exception)
: [offset] "d" (offset), [data] "Q" (*data)
- : "cc");
+ : CC_CLOBBER);
*status = req >> 24 & 0xff;
- return cc;
+ return exception ? -ENXIO : CC_TRANSFORM(cc);
}
int __zpci_store_block(const u64 *data, u64 req, u64 offset)
@@ -398,19 +407,20 @@ static inline int zpci_write_block_fh(volatile void __iomem *dst,
static inline int __pcistb_mio(const u64 *data, u64 ioaddr, u64 len, u8 *status)
{
- int cc = -ENXIO;
+ int cc, exception;
+ exception = 1;
asm volatile (
" .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[data]\n"
- "0: ipm %[cc]\n"
- " srl %[cc],28\n"
+ "0: lhi %[exc],0\n"
"1:\n"
+ CC_IPM(cc)
EX_TABLE(0b, 1b)
- : [cc] "+d" (cc), [len] "+d" (len)
+ : CC_OUT(cc, cc), [len] "+d" (len), [exc] "+d" (exception)
: [ioaddr] "d" (ioaddr), [data] "Q" (*data)
- : "cc");
+ : CC_CLOBBER);
*status = len >> 24 & 0xff;
- return cc;
+ return exception ? -ENXIO : CC_TRANSFORM(cc);
}
int zpci_write_block(volatile void __iomem *dst,
diff --git a/arch/s390/pci/pci_iov.h b/arch/s390/pci/pci_iov.h
index b2c828003bad..e3fa4e77fc86 100644
--- a/arch/s390/pci/pci_iov.h
+++ b/arch/s390/pci/pci_iov.h
@@ -10,6 +10,8 @@
#ifndef __S390_PCI_IOV_H
#define __S390_PCI_IOV_H
+#include <linux/pci.h>
+
#ifdef CONFIG_PCI_IOV
void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn);
diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c
index de5c0b389a3e..46f99dc164ad 100644
--- a/arch/s390/pci/pci_mmio.c
+++ b/arch/s390/pci/pci_mmio.c
@@ -14,6 +14,7 @@
#include <asm/asm-extable.h>
#include <asm/pci_io.h>
#include <asm/pci_debug.h>
+#include <asm/asm.h>
static inline void zpci_err_mmio(u8 cc, u8 status, u64 offset)
{
@@ -30,20 +31,21 @@ static inline int __pcistb_mio_inuser(
void __iomem *ioaddr, const void __user *src,
u64 len, u8 *status)
{
- int cc = -ENXIO;
+ int cc, exception;
+ exception = 1;
asm volatile (
- " sacf 256\n"
- "0: .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[src]\n"
- "1: ipm %[cc]\n"
- " srl %[cc],28\n"
- "2: sacf 768\n"
+ " sacf 256\n"
+ "0: .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[src]\n"
+ "1: lhi %[exc],0\n"
+ "2: sacf 768\n"
+ CC_IPM(cc)
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
- : [cc] "+d" (cc), [len] "+d" (len)
+ : CC_OUT(cc, cc), [len] "+d" (len), [exc] "+d" (exception)
: [ioaddr] "a" (ioaddr), [src] "Q" (*((u8 __force *)src))
- : "cc", "memory");
+ : CC_CLOBBER_LIST("memory"));
*status = len >> 24 & 0xff;
- return cc;
+ return exception ? -ENXIO : CC_TRANSFORM(cc);
}
static inline int __pcistg_mio_inuser(
@@ -51,7 +53,7 @@ static inline int __pcistg_mio_inuser(
u64 ulen, u8 *status)
{
union register_pair ioaddr_len = {.even = (u64 __force)ioaddr, .odd = ulen};
- int cc = -ENXIO;
+ int cc, exception;
u64 val = 0;
u64 cnt = ulen;
u8 tmp;
@@ -61,25 +63,27 @@ static inline int __pcistg_mio_inuser(
* a register, then store it to PCI at @ioaddr while in secondary
* address space. pcistg then uses the user mappings.
*/
+ exception = 1;
asm volatile (
- " sacf 256\n"
- "0: llgc %[tmp],0(%[src])\n"
+ " sacf 256\n"
+ "0: llgc %[tmp],0(%[src])\n"
"4: sllg %[val],%[val],8\n"
- " aghi %[src],1\n"
- " ogr %[val],%[tmp]\n"
- " brctg %[cnt],0b\n"
- "1: .insn rre,0xb9d40000,%[val],%[ioaddr_len]\n"
- "2: ipm %[cc]\n"
- " srl %[cc],28\n"
- "3: sacf 768\n"
+ " aghi %[src],1\n"
+ " ogr %[val],%[tmp]\n"
+ " brctg %[cnt],0b\n"
+ "1: .insn rre,0xb9d40000,%[val],%[ioaddr_len]\n"
+ "2: lhi %[exc],0\n"
+ "3: sacf 768\n"
+ CC_IPM(cc)
EX_TABLE(0b, 3b) EX_TABLE(4b, 3b) EX_TABLE(1b, 3b) EX_TABLE(2b, 3b)
+ : [src] "+a" (src), [cnt] "+d" (cnt),
+ [val] "+d" (val), [tmp] "=d" (tmp), [exc] "+d" (exception),
+ CC_OUT(cc, cc), [ioaddr_len] "+&d" (ioaddr_len.pair)
:
- [src] "+a" (src), [cnt] "+d" (cnt),
- [val] "+d" (val), [tmp] "=d" (tmp),
- [cc] "+d" (cc), [ioaddr_len] "+&d" (ioaddr_len.pair)
- :: "cc", "memory");
+ : CC_CLOBBER_LIST("memory"));
*status = ioaddr_len.odd >> 24 & 0xff;
+ cc = exception ? -ENXIO : CC_TRANSFORM(cc);
/* did we read everything from user memory? */
if (!cc && cnt != 0)
cc = -EFAULT;
@@ -198,7 +202,7 @@ static inline int __pcilg_mio_inuser(
union register_pair ioaddr_len = {.even = (u64 __force)ioaddr, .odd = ulen};
u64 cnt = ulen;
int shift = ulen * 8;
- int cc = -ENXIO;
+ int cc, exception;
u64 val, tmp;
/*
@@ -206,27 +210,33 @@ static inline int __pcilg_mio_inuser(
* user space) into a register using pcilg then store these bytes at
* user address @dst
*/
+ exception = 1;
asm volatile (
- " sacf 256\n"
- "0: .insn rre,0xb9d60000,%[val],%[ioaddr_len]\n"
- "1: ipm %[cc]\n"
- " srl %[cc],28\n"
- " ltr %[cc],%[cc]\n"
- " jne 4f\n"
- "2: ahi %[shift],-8\n"
- " srlg %[tmp],%[val],0(%[shift])\n"
- "3: stc %[tmp],0(%[dst])\n"
+ " sacf 256\n"
+ "0: .insn rre,0xb9d60000,%[val],%[ioaddr_len]\n"
+ "1: lhi %[exc],0\n"
+ " jne 4f\n"
+ "2: ahi %[shift],-8\n"
+ " srlg %[tmp],%[val],0(%[shift])\n"
+ "3: stc %[tmp],0(%[dst])\n"
"5: aghi %[dst],1\n"
- " brctg %[cnt],2b\n"
- "4: sacf 768\n"
+ " brctg %[cnt],2b\n"
+ /*
+ * Use xr to clear exc and set condition code to zero
+ * to ensure flag output is correct for this branch.
+ */
+ " xr %[exc],%[exc]\n"
+ "4: sacf 768\n"
+ CC_IPM(cc)
EX_TABLE(0b, 4b) EX_TABLE(1b, 4b) EX_TABLE(3b, 4b) EX_TABLE(5b, 4b)
+ : [ioaddr_len] "+&d" (ioaddr_len.pair), [exc] "+d" (exception),
+ CC_OUT(cc, cc), [val] "=d" (val),
+ [dst] "+a" (dst), [cnt] "+d" (cnt), [tmp] "=d" (tmp),
+ [shift] "+d" (shift)
:
- [ioaddr_len] "+&d" (ioaddr_len.pair),
- [cc] "+d" (cc), [val] "=d" (val),
- [dst] "+a" (dst), [cnt] "+d" (cnt), [tmp] "=d" (tmp),
- [shift] "+d" (shift)
- :: "cc", "memory");
+ : CC_CLOBBER_LIST("memory"));
+ cc = exception ? -ENXIO : CC_TRANSFORM(cc);
/* did we write everything to the user space buffer? */
if (!cc && cnt != 0)
cc = -EFAULT;
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c
index 1f81f6ff7b95..5f46ad58dcd1 100644
--- a/arch/s390/pci/pci_sysfs.c
+++ b/arch/s390/pci/pci_sysfs.c
@@ -23,7 +23,7 @@ static ssize_t name##_show(struct device *dev, \
{ \
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev)); \
\
- return sprintf(buf, fmt, zdev->member); \
+ return sysfs_emit(buf, fmt, zdev->member); \
} \
static DEVICE_ATTR_RO(name)
@@ -34,6 +34,7 @@ zpci_attr(pfgid, "0x%02x\n", pfgid);
zpci_attr(vfn, "0x%04x\n", vfn);
zpci_attr(pft, "0x%02x\n", pft);
zpci_attr(port, "%d\n", port);
+zpci_attr(fidparm, "0x%02x\n", fidparm);
zpci_attr(uid, "0x%x\n", uid);
zpci_attr(segment0, "0x%02x\n", pfip[0]);
zpci_attr(segment1, "0x%02x\n", pfip[1]);
@@ -45,7 +46,7 @@ static ssize_t mio_enabled_show(struct device *dev,
{
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- return sprintf(buf, zpci_use_mio(zdev) ? "1\n" : "0\n");
+ return sysfs_emit(buf, zpci_use_mio(zdev) ? "1\n" : "0\n");
}
static DEVICE_ATTR_RO(mio_enabled);
@@ -215,6 +216,7 @@ static struct attribute *zpci_dev_attrs[] = {
&dev_attr_pfgid.attr,
&dev_attr_pft.attr,
&dev_attr_port.attr,
+ &dev_attr_fidparm.attr,
&dev_attr_vfn.attr,
&dev_attr_uid.attr,
&dev_attr_recover.attr,
diff --git a/arch/s390/purgatory/head.S b/arch/s390/purgatory/head.S
index 0f93f2e72eba..db3ab2402621 100644
--- a/arch/s390/purgatory/head.S
+++ b/arch/s390/purgatory/head.S
@@ -156,7 +156,7 @@ SYM_CODE_START(purgatory_start)
agr %r10,%r9
/* Buffer location (in crash memory) and size. As the purgatory is
- * behind the point of no return it can re-use the stack as buffer.
+ * behind the point of no return it can reuse the stack as buffer.
*/
larl %r11,purgatory_end
larl %r12,stack
diff --git a/arch/s390/tools/gen_facilities.c b/arch/s390/tools/gen_facilities.c
index 68580cbea4e6..855f818deb98 100644
--- a/arch/s390/tools/gen_facilities.c
+++ b/arch/s390/tools/gen_facilities.c
@@ -109,10 +109,12 @@ static struct facility_def facility_defs[] = {
15, /* AP Facilities Test */
156, /* etoken facility */
165, /* nnpa facility */
+ 170, /* ineffective-nonconstrained-transaction facility */
193, /* bear enhancement facility */
194, /* rdp enhancement facility */
196, /* processor activity instrumentation facility */
197, /* processor activity instrumentation extension 1 */
+ 201, /* concurrent-functions facility */
-1 /* END */
}
},
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index e9103998cca9..04ff5fb9242e 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -550,6 +550,9 @@ config ARCH_SUPPORTS_KEXEC
config ARCH_SUPPORTS_CRASH_DUMP
def_bool BROKEN_ON_SMP
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
config ARCH_SUPPORTS_KEXEC_JUMP
def_bool y
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
index 0311380160f4..d871623955c5 100644
--- a/arch/sh/configs/landisk_defconfig
+++ b/arch/sh/configs/landisk_defconfig
@@ -95,7 +95,6 @@ CONFIG_USB_SISUSBVGA=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_REISERFS_FS=y
CONFIG_ISO9660_FS=m
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
index c1032559ecd4..99bc0e889287 100644
--- a/arch/sh/configs/titan_defconfig
+++ b/arch/sh/configs/titan_defconfig
@@ -220,7 +220,6 @@ CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_REISERFS_FS=m
CONFIG_XFS_FS=m
CONFIG_FUSE_FS=m
CONFIG_ISO9660_FS=m
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index fc44d9c88b41..4d3f10ed8275 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -3,3 +3,4 @@ generated-y += syscall_table.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += parport.h
+generic-y += text-patching.h
diff --git a/arch/sh/include/asm/hugetlb.h b/arch/sh/include/asm/hugetlb.h
index 75028bd568ba..4a92e6e4d627 100644
--- a/arch/sh/include/asm/hugetlb.h
+++ b/arch/sh/include/asm/hugetlb.h
@@ -5,21 +5,6 @@
#include <asm/cacheflush.h>
#include <asm/page.h>
-/*
- * If the arch doesn't supply something else, assume that hugepage
- * size aligned regions are ok without further preparation.
- */
-#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE
-static inline int prepare_hugepage_range(struct file *file,
- unsigned long addr, unsigned long len)
-{
- if (len & ~HPAGE_MASK)
- return -EINVAL;
- if (addr & ~HPAGE_MASK)
- return -EINVAL;
- return 0;
-}
-
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep)
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index f780b467e75d..3990cbd9aa04 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -8,10 +8,8 @@
#include <linux/const.h>
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
+
#define PTE_MASK PAGE_MASK
#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
@@ -147,7 +145,6 @@ typedef struct page *pgtable_t;
#endif
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
/*
* PFN = physical frame number (ie PFN 0 == physical address 0)
diff --git a/arch/sh/include/asm/spinlock_types.h b/arch/sh/include/asm/spinlock_types.h
index 907bda4b1619..7cb50e68448f 100644
--- a/arch/sh/include/asm/spinlock_types.h
+++ b/arch/sh/include/asm/spinlock_types.h
@@ -3,7 +3,7 @@
#define __ASM_SH_SPINLOCK_TYPES_H
#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
typedef struct {
diff --git a/arch/sh/include/asm/vga.h b/arch/sh/include/asm/vga.h
deleted file mode 100644
index 089fbdc6c0b1..000000000000
--- a/arch/sh/include/asm/vga.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_SH_VGA_H
-#define __ASM_SH_VGA_H
-
-/* Stupid drivers. */
-
-#endif /* __ASM_SH_VGA_H */
diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
index a306bcd6b341..5f6d0e827bae 100644
--- a/arch/sh/kernel/cpu/proc.c
+++ b/arch/sh/kernel/cpu/proc.c
@@ -132,7 +132,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
static void *c_start(struct seq_file *m, loff_t *pos)
{
- return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+ return *pos < nr_cpu_ids ? cpu_data + *pos : NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 620e5cf8ae1e..f2b6f16a46b8 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -255,7 +255,7 @@ void __ref sh_fdt_init(phys_addr_t dt_phys)
dt_virt = phys_to_virt(dt_phys);
#endif
- if (!dt_virt || !early_init_dt_scan(dt_virt)) {
+ if (!dt_virt || !early_init_dt_scan(dt_virt, __pa(dt_virt))) {
pr_crit("Error: invalid device tree blob"
" at physical address %p\n", (void *)dt_phys);
diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
index c55fd7696d40..c8cad33bf250 100644
--- a/arch/sh/kernel/syscalls/syscall.tbl
+++ b/arch/sh/kernel/syscalls/syscall.tbl
@@ -466,3 +466,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 757451c3ea1d..0400078076e5 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -29,7 +29,7 @@ UTS_MACHINE := sparc
# versions of gcc. Some gcc versions won't pass -Av8 to binutils when you
# give -mcpu=v8. This silently worked with older bintutils versions but
# does not any more.
-KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu $(call cc-option,-fcall-used-g5) $(call cc-option,-fcall-used-g7)
KBUILD_CFLAGS += -Wa,-Av8
KBUILD_AFLAGS += -m32 -Wa,-Av8
@@ -45,7 +45,7 @@ export BITS := 64
UTS_MACHINE := sparc64
KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow
-KBUILD_CFLAGS += -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare
+KBUILD_CFLAGS += -ffixed-g4 -ffixed-g5 $(call cc-option,-fcall-used-g7) -Wno-sign-compare
KBUILD_CFLAGS += -Wa,--undeclared-regs
KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3)
KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 43b0ae4c2c21..17ee8a273aa6 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -4,3 +4,4 @@ generated-y += syscall_table_64.h
generic-y += agp.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
+generic-y += text-patching.h
diff --git a/arch/sparc/include/asm/hvtramp.h b/arch/sparc/include/asm/hvtramp.h
index 688ea43af0f5..ce2453ea4f2b 100644
--- a/arch/sparc/include/asm/hvtramp.h
+++ b/arch/sparc/include/asm/hvtramp.h
@@ -17,7 +17,7 @@ struct hvtramp_descr {
__u64 fault_info_va;
__u64 fault_info_pa;
__u64 thread_reg;
- struct hvtramp_mapping maps[1];
+ struct hvtramp_mapping maps[];
};
void hv_cpu_startup(unsigned long hvdescr_pa);
diff --git a/arch/sparc/include/asm/page.h b/arch/sparc/include/asm/page.h
index 5e44cdf2a8f2..1a00cc0a1893 100644
--- a/arch/sparc/include/asm/page.h
+++ b/arch/sparc/include/asm/page.h
@@ -2,8 +2,6 @@
#ifndef ___ASM_SPARC_PAGE_H
#define ___ASM_SPARC_PAGE_H
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-
#if defined(__sparc__) && defined(__arch64__)
#include <asm/page_64.h>
#else
diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h
index 9977c77374cd..9954254ea569 100644
--- a/arch/sparc/include/asm/page_32.h
+++ b/arch/sparc/include/asm/page_32.h
@@ -11,9 +11,7 @@
#include <linux/const.h>
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h
index e9bd24821c93..2a68ff5b6eab 100644
--- a/arch/sparc/include/asm/page_64.h
+++ b/arch/sparc/include/asm/page_64.h
@@ -4,9 +4,7 @@
#include <linux/const.h>
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
/* Flushing for D-cache alias handling is only needed if
* the page size is smaller than 16K.
diff --git a/arch/sparc/include/asm/vga.h b/arch/sparc/include/asm/vga.h
deleted file mode 100644
index 2952d667d936..000000000000
--- a/arch/sparc/include/asm/vga.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Access to VGA videoram
- *
- * (c) 1998 Martin Mares <mj@ucw.cz>
- */
-
-#ifndef _LINUX_ASM_VGA_H_
-#define _LINUX_ASM_VGA_H_
-
-#include <linux/bug.h>
-#include <linux/string.h>
-#include <asm/types.h>
-
-#define VT_BUF_HAVE_RW
-#define VT_BUF_HAVE_MEMSETW
-#define VT_BUF_HAVE_MEMCPYW
-#define VT_BUF_HAVE_MEMMOVEW
-
-#undef scr_writew
-#undef scr_readw
-
-static inline void scr_writew(u16 val, u16 *addr)
-{
- BUG_ON((long) addr >= 0);
-
- *addr = val;
-}
-
-static inline u16 scr_readw(const u16 *addr)
-{
- BUG_ON((long) addr >= 0);
-
- return *addr;
-}
-
-static inline void scr_memsetw(u16 *p, u16 v, unsigned int n)
-{
- BUG_ON((long) p >= 0);
-
- memset16(p, cpu_to_le16(v), n / 2);
-}
-
-static inline void scr_memcpyw(u16 *d, u16 *s, unsigned int n)
-{
- BUG_ON((long) d >= 0);
-
- memcpy(d, s, n);
-}
-
-static inline void scr_memmovew(u16 *d, u16 *s, unsigned int n)
-{
- BUG_ON((long) d >= 0);
-
- memmove(d, s, n);
-}
-
-#define VGA_MAP_MEM(x,s) (x)
-
-#endif
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 57084ed2f3c4..113cd9f353e3 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -139,6 +139,8 @@
#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF
#define SO_DEVMEM_DONTNEED 0x0059
+#define SCM_TS_OPT_ID 0x005a
+
#if !defined(__KERNEL__)
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index e40c395db202..5cbd6ed5ef6f 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -297,9 +297,7 @@ static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg,
unsigned long hv_err;
int i;
- hdesc = kzalloc(sizeof(*hdesc) +
- (sizeof(struct hvtramp_mapping) *
- num_kernel_image_mappings - 1),
+ hdesc = kzalloc(struct_size(hdesc, maps, num_kernel_image_mappings),
GFP_KERNEL);
if (!hdesc) {
printk(KERN_ERR "ldom_startcpu_cpuid: Cannot allocate "
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 80822f922e76..fb31bc0c5b48 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -23,6 +23,7 @@
#include <linux/utsname.h>
#include <linux/smp.h>
#include <linux/ipc.h>
+#include <linux/hugetlb.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
@@ -42,12 +43,16 @@ SYSCALL_DEFINE0(getpagesize)
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
{
struct vm_unmapped_area_info info = {};
+ bool file_hugepage = false;
+
+ if (filp && is_file_hugepages(filp))
+ file_hugepage = true;
if (flags & MAP_FIXED) {
/* We do not accept a shared mapping if it would violate
* cache aliasing constraints.
*/
- if ((flags & MAP_SHARED) &&
+ if (!file_hugepage && (flags & MAP_SHARED) &&
((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
return -EINVAL;
return addr;
@@ -62,9 +67,13 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
info.length = len;
info.low_limit = addr;
info.high_limit = TASK_SIZE;
- info.align_mask = (flags & MAP_SHARED) ?
- (PAGE_MASK & (SHMLBA - 1)) : 0;
- info.align_offset = pgoff << PAGE_SHIFT;
+ if (!file_hugepage) {
+ info.align_mask = (flags & MAP_SHARED) ?
+ (PAGE_MASK & (SHMLBA - 1)) : 0;
+ info.align_offset = pgoff << PAGE_SHIFT;
+ } else {
+ info.align_mask = huge_page_mask_align(filp);
+ }
return vm_unmapped_area(&info);
}
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index acade309dc2f..c5a284df7b41 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -30,6 +30,7 @@
#include <linux/context_tracking.h>
#include <linux/timex.h>
#include <linux/uaccess.h>
+#include <linux/hugetlb.h>
#include <asm/utrap.h>
#include <asm/unistd.h>
@@ -87,6 +88,16 @@ static inline unsigned long COLOR_ALIGN(unsigned long addr,
return base + off;
}
+static unsigned long get_align_mask(struct file *filp, unsigned long flags)
+{
+ if (filp && is_file_hugepages(filp))
+ return huge_page_mask_align(filp);
+ if (filp || (flags & MAP_SHARED))
+ return PAGE_MASK & (SHMLBA - 1);
+
+ return 0;
+}
+
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
{
struct mm_struct *mm = current->mm;
@@ -94,12 +105,16 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
unsigned long task_size = TASK_SIZE;
int do_color_align;
struct vm_unmapped_area_info info = {};
+ bool file_hugepage = false;
+
+ if (filp && is_file_hugepages(filp))
+ file_hugepage = true;
if (flags & MAP_FIXED) {
/* We do not accept a shared mapping if it would violate
* cache aliasing constraints.
*/
- if ((flags & MAP_SHARED) &&
+ if (!file_hugepage && (flags & MAP_SHARED) &&
((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
return -EINVAL;
return addr;
@@ -111,7 +126,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
return -ENOMEM;
do_color_align = 0;
- if (filp || (flags & MAP_SHARED))
+ if ((filp || (flags & MAP_SHARED)) && !file_hugepage)
do_color_align = 1;
if (addr) {
@@ -129,8 +144,9 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
info.length = len;
info.low_limit = TASK_UNMAPPED_BASE;
info.high_limit = min(task_size, VA_EXCLUDE_START);
- info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
- info.align_offset = pgoff << PAGE_SHIFT;
+ info.align_mask = get_align_mask(filp, flags);
+ if (!file_hugepage)
+ info.align_offset = pgoff << PAGE_SHIFT;
addr = vm_unmapped_area(&info);
if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
@@ -154,15 +170,19 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
unsigned long addr = addr0;
int do_color_align;
struct vm_unmapped_area_info info = {};
+ bool file_hugepage = false;
/* This should only ever run for 32-bit processes. */
BUG_ON(!test_thread_flag(TIF_32BIT));
+ if (filp && is_file_hugepages(filp))
+ file_hugepage = true;
+
if (flags & MAP_FIXED) {
/* We do not accept a shared mapping if it would violate
* cache aliasing constraints.
*/
- if ((flags & MAP_SHARED) &&
+ if (!file_hugepage && (flags & MAP_SHARED) &&
((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
return -EINVAL;
return addr;
@@ -172,7 +192,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
return -ENOMEM;
do_color_align = 0;
- if (filp || (flags & MAP_SHARED))
+ if ((filp || (flags & MAP_SHARED)) && !file_hugepage)
do_color_align = 1;
/* requesting a specific address */
@@ -192,8 +212,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
info.length = len;
info.low_limit = PAGE_SIZE;
info.high_limit = mm->mmap_base;
- info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
- info.align_offset = pgoff << PAGE_SHIFT;
+ info.align_mask = get_align_mask(filp, flags);
+ if (!file_hugepage)
+ info.align_offset = pgoff << PAGE_SHIFT;
addr = vm_unmapped_area(&info);
/*
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
index cfdfb3707c16..727f99d333b3 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
@@ -508,3 +508,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 08bbdc458596..578fd0d49f30 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -255,6 +255,7 @@ static void mostek_write_byte(struct device *dev, u32 ofs, u8 val)
static struct m48t59_plat_data m48t59_data = {
.read_byte = mostek_read_byte,
.write_byte = mostek_write_byte,
+ .yy_offset = 68,
};
/* resource is set at runtime */
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index 60f1c8cc5363..b32f27f929d1 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -544,6 +544,7 @@ static void mostek_write_byte(struct device *dev, u32 ofs, u8 val)
static struct m48t59_plat_data m48t59_data = {
.read_byte = mostek_read_byte,
.write_byte = mostek_write_byte,
+ .yy_offset = 68,
};
static struct platform_device m48t59_rtc = {
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index d317a843f7ea..f1b86eb30340 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -48,6 +48,11 @@ SECTIONS
{
_text = .;
HEAD_TEXT
+ ALIGN_FUNCTION();
+#ifdef CONFIG_SPARC64
+ /* Match text section symbols in head_64.S first */
+ *head_64.o(.text)
+#endif
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
index cc91ca7a1e18..eee601a0d2cf 100644
--- a/arch/sparc/mm/hugetlbpage.c
+++ b/arch/sparc/mm/hugetlbpage.c
@@ -19,114 +19,6 @@
#include <asm/cacheflush.h>
#include <asm/mmu_context.h>
-/* Slightly simplified from the non-hugepage variant because by
- * definition we don't have to worry about any page coloring stuff
- */
-
-static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
- unsigned long addr,
- unsigned long len,
- unsigned long pgoff,
- unsigned long flags)
-{
- struct hstate *h = hstate_file(filp);
- unsigned long task_size = TASK_SIZE;
- struct vm_unmapped_area_info info = {};
-
- if (test_thread_flag(TIF_32BIT))
- task_size = STACK_TOP32;
-
- info.length = len;
- info.low_limit = TASK_UNMAPPED_BASE;
- info.high_limit = min(task_size, VA_EXCLUDE_START);
- info.align_mask = PAGE_MASK & ~huge_page_mask(h);
- addr = vm_unmapped_area(&info);
-
- if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
- VM_BUG_ON(addr != -ENOMEM);
- info.low_limit = VA_EXCLUDE_END;
- info.high_limit = task_size;
- addr = vm_unmapped_area(&info);
- }
-
- return addr;
-}
-
-static unsigned long
-hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
- const unsigned long len,
- const unsigned long pgoff,
- const unsigned long flags)
-{
- struct hstate *h = hstate_file(filp);
- struct mm_struct *mm = current->mm;
- unsigned long addr = addr0;
- struct vm_unmapped_area_info info = {};
-
- /* This should only ever run for 32-bit processes. */
- BUG_ON(!test_thread_flag(TIF_32BIT));
-
- info.flags = VM_UNMAPPED_AREA_TOPDOWN;
- info.length = len;
- info.low_limit = PAGE_SIZE;
- info.high_limit = mm->mmap_base;
- info.align_mask = PAGE_MASK & ~huge_page_mask(h);
- addr = vm_unmapped_area(&info);
-
- /*
- * A failed mmap() very likely causes application failure,
- * so fall back to the bottom-up function here. This scenario
- * can happen with large stack limits and large mmap()
- * allocations.
- */
- if (addr & ~PAGE_MASK) {
- VM_BUG_ON(addr != -ENOMEM);
- info.flags = 0;
- info.low_limit = TASK_UNMAPPED_BASE;
- info.high_limit = STACK_TOP32;
- addr = vm_unmapped_area(&info);
- }
-
- return addr;
-}
-
-unsigned long
-hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
- unsigned long task_size = TASK_SIZE;
-
- if (test_thread_flag(TIF_32BIT))
- task_size = STACK_TOP32;
-
- if (len & ~huge_page_mask(h))
- return -EINVAL;
- if (len > task_size)
- return -ENOMEM;
-
- if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(file, addr, len))
- return -EINVAL;
- return addr;
- }
-
- if (addr) {
- addr = ALIGN(addr, huge_page_size(h));
- vma = find_vma(mm, addr);
- if (task_size - len >= addr &&
- (!vma || addr + len <= vm_start_gap(vma)))
- return addr;
- }
- if (!test_bit(MMF_TOPDOWN, &mm->flags))
- return hugetlb_get_unmapped_area_bottomup(file, addr, len,
- pgoff, flags);
- else
- return hugetlb_get_unmapped_area_topdown(file, addr, len,
- pgoff, flags);
-}
static pte_t sun4u_hugepage_shift_to_tte(pte_t entry, unsigned int shift)
{
diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile
index 243dbfc4609d..50ec2978cda5 100644
--- a/arch/sparc/vdso/Makefile
+++ b/arch/sparc/vdso/Makefile
@@ -46,7 +46,7 @@ CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables -m64
-fno-omit-frame-pointer -foptimize-sibling-calls \
-DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
-SPARC_REG_CFLAGS = -ffixed-g4 -ffixed-g5 -fcall-used-g5 -fcall-used-g7
+SPARC_REG_CFLAGS = -ffixed-g4 -ffixed-g5 $(call cc-option,-fcall-used-g5) $(call cc-option,-fcall-used-g7)
$(vobjs): KBUILD_CFLAGS := $(filter-out $(RANDSTRUCT_CFLAGS) $(GCC_PLUGINS_CFLAGS) $(SPARC_REG_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index e794edde6755..79607804ea1b 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -86,6 +86,11 @@ notrace static long vdso_fallback_gettimeofday(struct __kernel_old_timeval *tv,
}
#ifdef CONFIG_SPARC64
+notrace static __always_inline u64 __shr64(u64 val, int amt)
+{
+ return val >> amt;
+}
+
notrace static __always_inline u64 vread_tick(void)
{
u64 ret;
@@ -102,6 +107,21 @@ notrace static __always_inline u64 vread_tick_stick(void)
return ret;
}
#else
+notrace static __always_inline u64 __shr64(u64 val, int amt)
+{
+ u64 ret;
+
+ __asm__ __volatile__("sllx %H1, 32, %%g1\n\t"
+ "srl %L1, 0, %L1\n\t"
+ "or %%g1, %L1, %%g1\n\t"
+ "srlx %%g1, %2, %L0\n\t"
+ "srlx %L0, 32, %H0"
+ : "=r" (ret)
+ : "r" (val), "r" (amt)
+ : "g1");
+ return ret;
+}
+
notrace static __always_inline u64 vread_tick(void)
{
register unsigned long long ret asm("o4");
@@ -154,7 +174,7 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar,
ts->tv_sec = vvar->wall_time_sec;
ns = vvar->wall_time_snsec;
ns += vgetsns(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
@@ -174,7 +194,7 @@ notrace static __always_inline int do_realtime_stick(struct vvar_data *vvar,
ts->tv_sec = vvar->wall_time_sec;
ns = vvar->wall_time_snsec;
ns += vgetsns_stick(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
@@ -194,7 +214,7 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
ts->tv_sec = vvar->monotonic_time_sec;
ns = vvar->monotonic_time_snsec;
ns += vgetsns(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
@@ -214,7 +234,7 @@ notrace static __always_inline int do_monotonic_stick(struct vvar_data *vvar,
ts->tv_sec = vvar->monotonic_time_sec;
ns = vvar->monotonic_time_snsec;
ns += vgetsns_stick(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c89575d05021..18051b1cfce0 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -5,6 +5,7 @@ menu "UML-specific options"
config UML
bool
default y
+ select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_HAS_CPU_FINALIZE_INIT
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
@@ -32,6 +33,8 @@ config UML
select HAVE_ARCH_VMAP_STACK
select HAVE_RUST
select ARCH_HAS_UBSAN
+ select HAVE_ARCH_TRACEHOOK
+ select THREAD_INFO_IN_TASK
config MMU
bool
@@ -94,7 +97,7 @@ config MAY_HAVE_RUNTIME_DEPS
config STATIC_LINK
bool "Force a static link"
- depends on CC_CAN_LINK_STATIC_NO_RUNTIME_DEPS || !MAY_HAVE_RUNTIME_DEPS
+ depends on !MAY_HAVE_RUNTIME_DEPS
help
This option gives you the ability to force a static link of UML.
Normally, UML is linked as a shared binary. This is inconvenient for
@@ -209,8 +212,8 @@ config MMAPPER
config PGTABLE_LEVELS
int
- default 3 if 3_LEVEL_PGTABLES
- default 2
+ default 4 if 64BIT
+ default 2 if !64BIT
config UML_TIME_TRAVEL_SUPPORT
bool
@@ -227,6 +230,21 @@ config UML_TIME_TRAVEL_SUPPORT
It is safe to say Y, but you probably don't need this.
+config UML_MAX_USERSPACE_ITERATIONS
+ int
+ prompt "Maximum number of unscheduled userspace iterations"
+ default 10000
+ depends on UML_TIME_TRAVEL_SUPPORT
+ help
+ In UML inf-cpu and ext time-travel mode userspace can run without being
+ interrupted. This will eventually overwhelm the kernel and create OOM
+ situations (mainly RCU not running). This setting specifies the number
+ of kernel/userspace switches (minor/major page fault, signal or syscall)
+ for the same userspace thread before the sched_clock is advanced by a
+ jiffie to trigger scheduling.
+
+ Setting it to zero disables the feature.
+
config KASAN_SHADOW_OFFSET
hex
depends on KASAN
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 00b63bac5eff..1d36a613aad8 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -61,7 +61,8 @@ KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
-Dlongjmp=kernel_longjmp -Dsetjmp=kernel_setjmp \
-Din6addr_loopback=kernel_in6addr_loopback \
- -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr
+ -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr \
+ -D__close_range=kernel__close_range
KBUILD_RUSTFLAGS += -Crelocation-model=pie
@@ -70,7 +71,9 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
$(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
-D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
- -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__
+ -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__ \
+ -include $(srctree)/include/linux/compiler-version.h \
+ -include $(srctree)/include/linux/kconfig.h
#This will adjust *FLAGS accordingly to the platform.
include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux
diff --git a/arch/um/Makefile-skas b/arch/um/Makefile-skas
index 67323b028999..1a27e65bcb9c 100644
--- a/arch/um/Makefile-skas
+++ b/arch/um/Makefile-skas
@@ -3,15 +3,15 @@
# Licensed under the GPL
#
-GPROF_OPT += -pg
+export UM_GPROF_OPT += -pg
ifdef CONFIG_CC_IS_CLANG
-GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping
+export UM_GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping
else
-GCOV_OPT += -fprofile-arcs -ftest-coverage
+export UM_GCOV_OPT += -fprofile-arcs -ftest-coverage
endif
-CFLAGS-$(CONFIG_GCOV) += $(GCOV_OPT)
-CFLAGS-$(CONFIG_GPROF) += $(GPROF_OPT)
-LINK-$(CONFIG_GCOV) += $(GCOV_OPT)
-LINK-$(CONFIG_GPROF) += $(GPROF_OPT)
+CFLAGS-$(CONFIG_GCOV) += $(UM_GCOV_OPT)
+CFLAGS-$(CONFIG_GPROF) += $(UM_GPROF_OPT)
+LINK-$(CONFIG_GCOV) += $(UM_GCOV_OPT)
+LINK-$(CONFIG_GPROF) += $(UM_GPROF_OPT)
diff --git a/arch/um/configs/i386_defconfig b/arch/um/configs/i386_defconfig
index e543cbac8792..1ffa088739f4 100644
--- a/arch/um/configs/i386_defconfig
+++ b/arch/um/configs/i386_defconfig
@@ -1,4 +1,3 @@
-CONFIG_3_LEVEL_PGTABLES=y
# CONFIG_COMPACTION is not set
CONFIG_BINFMT_MISC=m
CONFIG_HOSTFS=y
@@ -61,7 +60,6 @@ CONFIG_UML_NET_DAEMON=y
CONFIG_UML_NET_MCAST=y
CONFIG_UML_NET_SLIRP=y
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS_FS=m
CONFIG_ISO9660_FS=m
diff --git a/arch/um/configs/x86_64_defconfig b/arch/um/configs/x86_64_defconfig
index 939cb12318ca..03b10d3f6816 100644
--- a/arch/um/configs/x86_64_defconfig
+++ b/arch/um/configs/x86_64_defconfig
@@ -59,7 +59,6 @@ CONFIG_UML_NET_DAEMON=y
CONFIG_UML_NET_MCAST=y
CONFIG_UML_NET_SLIRP=y
CONFIG_EXT4_FS=y
-CONFIG_REISERFS_FS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS_FS=m
CONFIG_ISO9660_FS=m
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index a66e556012c4..35f9beeb19b3 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -161,6 +161,8 @@ static __noreturn int winch_thread(void *arg)
int count;
char c = 1;
+ os_set_pdeathsig();
+
pty_fd = data->pty_fd;
pipe_fd = data->pipe_fd;
count = write(pipe_fd, &c, sizeof(c));
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 9d228878cea2..0ac149de1ac0 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -48,6 +48,7 @@ MODULE_PARM_DESC(mixer, MIXER_HELP);
#ifndef MODULE
static int set_dsp(char *name, int *add)
{
+ *add = 0;
dsp = name;
return 0;
}
@@ -56,6 +57,7 @@ __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
static int set_mixer(char *name, int *add)
{
+ *add = 0;
mixer = name;
return 0;
}
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 77c4afb8ab90..75d04fb4994a 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -336,7 +336,7 @@ static struct platform_driver uml_net_driver = {
static void net_device_release(struct device *dev)
{
- struct uml_net *device = dev_get_drvdata(dev);
+ struct uml_net *device = container_of(dev, struct uml_net, pdev.dev);
struct net_device *netdev = device->dev;
struct uml_net_private *lp = netdev_priv(netdev);
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 7f28ec1929dc..66c1a8835e36 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -779,7 +779,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
static void ubd_device_release(struct device *dev)
{
- struct ubd *ubd_dev = dev_get_drvdata(dev);
+ struct ubd *ubd_dev = container_of(dev, struct ubd, pdev.dev);
blk_mq_free_tag_set(&ubd_dev->tag_set);
*ubd_dev = ((struct ubd) DEFAULT_UBD);
@@ -898,6 +898,8 @@ static int ubd_add(int n, char **error_out)
if (err)
goto out_cleanup_disk;
+ ubd_dev->disk = disk;
+
return 0;
out_cleanup_disk:
@@ -1499,6 +1501,7 @@ int io_thread(void *arg)
{
int n, count, written, res;
+ os_set_pdeathsig();
os_fix_helper_signals();
while(1){
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index c992da83268d..64c09db392c1 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -815,7 +815,8 @@ static struct platform_driver uml_net_driver = {
static void vector_device_release(struct device *dev)
{
- struct vector_device *device = dev_get_drvdata(dev);
+ struct vector_device *device =
+ container_of(dev, struct vector_device, pdev.dev);
struct net_device *netdev = device->dev;
list_del(&device->list);
diff --git a/arch/um/drivers/vhost_user.h b/arch/um/drivers/vhost_user.h
index 6f147cd3c9f7..fcfa3b7e021b 100644
--- a/arch/um/drivers/vhost_user.h
+++ b/arch/um/drivers/vhost_user.h
@@ -10,6 +10,7 @@
/* Feature bits */
#define VHOST_USER_F_PROTOCOL_FEATURES 30
/* Protocol feature bits */
+#define VHOST_USER_PROTOCOL_F_MQ 0
#define VHOST_USER_PROTOCOL_F_REPLY_ACK 3
#define VHOST_USER_PROTOCOL_F_SLAVE_REQ 5
#define VHOST_USER_PROTOCOL_F_CONFIG 9
@@ -23,7 +24,8 @@
/* Supported transport features */
#define VHOST_USER_SUPPORTED_F BIT_ULL(VHOST_USER_F_PROTOCOL_FEATURES)
/* Supported protocol features */
-#define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
+#define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_MQ) | \
+ BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
BIT_ULL(VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \
BIT_ULL(VHOST_USER_PROTOCOL_F_CONFIG) | \
BIT_ULL(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS))
diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index 2b6e701776b6..cc3be48a9d6e 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -56,6 +56,7 @@ struct virtio_uml_device {
int sock, req_fd, irq;
u64 features;
u64 protocol_features;
+ u64 max_vqs;
u8 status;
u8 registered:1;
u8 suspended:1;
@@ -72,8 +73,6 @@ struct virtio_uml_vq_info {
bool suspended;
};
-extern unsigned long long physmem_size, highmem;
-
#define vu_err(vu_dev, ...) dev_err(&(vu_dev)->pdev->dev, ##__VA_ARGS__)
/* Vhost-user protocol */
@@ -343,6 +342,17 @@ static int vhost_user_set_protocol_features(struct virtio_uml_device *vu_dev,
protocol_features);
}
+static int vhost_user_get_queue_num(struct virtio_uml_device *vu_dev,
+ u64 *queue_num)
+{
+ int rc = vhost_user_send_no_payload(vu_dev, true,
+ VHOST_USER_GET_QUEUE_NUM);
+
+ if (rc)
+ return rc;
+ return vhost_user_recv_u64(vu_dev, queue_num);
+}
+
static void vhost_user_reply(struct virtio_uml_device *vu_dev,
struct vhost_user_msg *msg, int response)
{
@@ -516,6 +526,15 @@ static int vhost_user_init(struct virtio_uml_device *vu_dev)
return rc;
}
+ if (vu_dev->protocol_features &
+ BIT_ULL(VHOST_USER_PROTOCOL_F_MQ)) {
+ rc = vhost_user_get_queue_num(vu_dev, &vu_dev->max_vqs);
+ if (rc)
+ return rc;
+ } else {
+ vu_dev->max_vqs = U64_MAX;
+ }
+
return 0;
}
@@ -625,7 +644,7 @@ static int vhost_user_set_mem_table(struct virtio_uml_device *vu_dev)
{
struct vhost_user_msg msg = {
.header.request = VHOST_USER_SET_MEM_TABLE,
- .header.size = sizeof(msg.payload.mem_regions),
+ .header.size = offsetof(typeof(msg.payload.mem_regions), regions[1]),
.payload.mem_regions.num = 1,
};
unsigned long reserved = uml_reserved - uml_physmem;
@@ -673,13 +692,6 @@ static int vhost_user_set_mem_table(struct virtio_uml_device *vu_dev)
if (rc < 0)
return rc;
- if (highmem) {
- msg.payload.mem_regions.num++;
- rc = vhost_user_init_mem_region(__pa(end_iomem), highmem,
- &fds[1], &msg.payload.mem_regions.regions[1]);
- if (rc < 0)
- return rc;
- }
return vhost_user_send(vu_dev, false, &msg, fds,
msg.payload.mem_regions.num);
@@ -897,7 +909,7 @@ static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
{
struct virtio_uml_vq_info *info = vq->priv;
int call_fds[2];
- int rc;
+ int rc, irq;
/* no call FD needed/desired in this case */
if (vu_dev->protocol_features &
@@ -914,19 +926,23 @@ static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
return rc;
info->call_fd = call_fds[0];
- rc = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ,
- vu_interrupt, IRQF_SHARED, info->name, vq);
- if (rc < 0)
+ irq = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ,
+ vu_interrupt, IRQF_SHARED, info->name, vq);
+ if (irq < 0) {
+ rc = irq;
goto close_both;
+ }
rc = vhost_user_set_vring_call(vu_dev, vq->index, call_fds[1]);
if (rc)
goto release_irq;
+ vu_dev->irq = irq;
+
goto out;
release_irq:
- um_free_irq(vu_dev->irq, vq);
+ um_free_irq(irq, vq);
close_both:
os_close_file(call_fds[0]);
out:
@@ -1023,7 +1039,9 @@ static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
struct virtqueue *vq;
/* not supported for now */
- if (WARN_ON(nvqs > 64))
+ if (WARN(nvqs > 64 || nvqs > vu_dev->max_vqs,
+ "%d VQs requested, only up to 64 or %lld supported\n",
+ nvqs, vu_dev->max_vqs))
return -EINVAL;
rc = vhost_user_set_mem_table(vu_dev);
@@ -1210,6 +1228,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
vu_dev->vdev.id.vendor = VIRTIO_DEV_ANY_ID;
vu_dev->pdev = pdev;
vu_dev->req_fd = -1;
+ vu_dev->irq = UM_IRQ_ALLOC;
time_travel_propagate_time();
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 18f902da8e99..428f2c5158c2 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
generic-y += bug.h
generic-y += compat.h
-generic-y += current.h
generic-y += device.h
generic-y += dma-mapping.h
generic-y += emergency-restart.h
diff --git a/arch/um/include/asm/current.h b/arch/um/include/asm/current.h
new file mode 100644
index 000000000000..de64e032d66c
--- /dev/null
+++ b/arch/um/include/asm/current.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_CURRENT_H
+#define __ASM_CURRENT_H
+
+#include <linux/compiler.h>
+#include <linux/threads.h>
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+extern struct task_struct *cpu_tasks[NR_CPUS];
+
+static __always_inline struct task_struct *get_current(void)
+{
+ return cpu_tasks[0];
+}
+
+
+#define current get_current()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CURRENT_H */
diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h
index 9ef9a8aedfa6..3d516f3ca9c7 100644
--- a/arch/um/include/asm/page.h
+++ b/arch/um/include/asm/page.h
@@ -9,10 +9,7 @@
#include <linux/const.h>
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#ifndef __ASSEMBLY__
@@ -32,51 +29,35 @@ struct page;
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64BIT)
-
typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
-#define pte_val(p) ((p).pte)
-#define pte_get_bits(p, bits) ((p).pte & (bits))
-#define pte_set_bits(p, bits) ((p).pte |= (bits))
-#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
-#define pte_copy(to, from) ({ (to).pte = (from).pte; })
-#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
-#define pte_set_val(p, phys, prot) \
- ({ (p).pte = (phys) | pgprot_val(prot); })
+#if CONFIG_PGTABLE_LEVELS > 2
+typedef struct { unsigned long pmd; } pmd_t;
#define pmd_val(x) ((x).pmd)
#define __pmd(x) ((pmd_t) { (x) } )
-typedef unsigned long long phys_t;
+#if CONFIG_PGTABLE_LEVELS > 3
-#else
-
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pud; } pud_t;
+#define pud_val(x) ((x).pud)
+#define __pud(x) ((pud_t) { (x) } )
-#ifdef CONFIG_3_LEVEL_PGTABLES
-typedef struct { unsigned long pmd; } pmd_t;
-#define pmd_val(x) ((x).pmd)
-#define __pmd(x) ((pmd_t) { (x) } )
-#endif
+#endif /* CONFIG_PGTABLE_LEVELS > 3 */
+#endif /* CONFIG_PGTABLE_LEVELS > 2 */
#define pte_val(x) ((x).pte)
-
#define pte_get_bits(p, bits) ((p).pte & (bits))
#define pte_set_bits(p, bits) ((p).pte |= (bits))
#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
#define pte_copy(to, from) ((to).pte = (from).pte)
-#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
+#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEEDSYNC))
#define pte_set_val(p, phys, prot) (p).pte = (phys | pgprot_val(prot))
typedef unsigned long phys_t;
-#endif
-
typedef struct { unsigned long pgprot; } pgprot_t;
typedef struct page *pgtable_t;
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h
index de5e31c64793..04fb4e6969a4 100644
--- a/arch/um/include/asm/pgalloc.h
+++ b/arch/um/include/asm/pgalloc.h
@@ -31,7 +31,7 @@ do { \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
-#ifdef CONFIG_3_LEVEL_PGTABLES
+#if CONFIG_PGTABLE_LEVELS > 2
#define __pmd_free_tlb(tlb, pmd, address) \
do { \
@@ -39,6 +39,15 @@ do { \
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \
} while (0)
+#if CONFIG_PGTABLE_LEVELS > 3
+
+#define __pud_free_tlb(tlb, pud, address) \
+do { \
+ pagetable_pud_dtor(virt_to_ptdesc(pud)); \
+ tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pud)); \
+} while (0)
+
+#endif
#endif
#endif
diff --git a/arch/um/include/asm/pgtable-2level.h b/arch/um/include/asm/pgtable-2level.h
index 8256ecc5b919..ab0c8dd86564 100644
--- a/arch/um/include/asm/pgtable-2level.h
+++ b/arch/um/include/asm/pgtable-2level.h
@@ -31,7 +31,7 @@
printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), \
pgd_val(e))
-static inline int pgd_newpage(pgd_t pgd) { return 0; }
+static inline int pgd_needsync(pgd_t pgd) { return 0; }
static inline void pgd_mkuptodate(pgd_t pgd) { }
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
diff --git a/arch/um/include/asm/pgtable-3level.h b/arch/um/include/asm/pgtable-4level.h
index 8a5032ec231f..0d279caee93c 100644
--- a/arch/um/include/asm/pgtable-3level.h
+++ b/arch/um/include/asm/pgtable-4level.h
@@ -4,21 +4,25 @@
* Derived from include/asm-i386/pgtable.h
*/
-#ifndef __UM_PGTABLE_3LEVEL_H
-#define __UM_PGTABLE_3LEVEL_H
+#ifndef __UM_PGTABLE_4LEVEL_H
+#define __UM_PGTABLE_4LEVEL_H
-#include <asm-generic/pgtable-nopud.h>
+#include <asm-generic/pgtable-nop4d.h>
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
+/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
-#ifdef CONFIG_64BIT
-#define PGDIR_SHIFT 30
-#else
-#define PGDIR_SHIFT 31
-#endif
+#define PGDIR_SHIFT 39
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
+/* PUD_SHIFT determines the size of the area a third-level page table can
+ * map
+ */
+
+#define PUD_SHIFT 30
+#define PUD_SIZE (1UL << PUD_SHIFT)
+#define PUD_MASK (~(PUD_SIZE-1))
+
/* PMD_SHIFT determines the size of the area a second-level page table can
* map
*/
@@ -32,13 +36,9 @@
*/
#define PTRS_PER_PTE 512
-#ifdef CONFIG_64BIT
#define PTRS_PER_PMD 512
+#define PTRS_PER_PUD 512
#define PTRS_PER_PGD 512
-#else
-#define PTRS_PER_PMD 1024
-#define PTRS_PER_PGD 1024
-#endif
#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
@@ -48,11 +48,14 @@
#define pmd_ERROR(e) \
printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
pmd_val(e))
+#define pud_ERROR(e) \
+ printk("%s:%d: bad pud %p(%016lx).\n", __FILE__, __LINE__, &(e), \
+ pud_val(e))
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
pgd_val(e))
-#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEWPAGE))
+#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEEDSYNC))
#define pud_bad(x) ((pud_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
#define pud_present(x) (pud_val(x) & _PAGE_PRESENT)
#define pud_populate(mm, pud, pmd) \
@@ -60,23 +63,40 @@
#define set_pud(pudptr, pudval) (*(pudptr) = (pudval))
-static inline int pgd_newpage(pgd_t pgd)
+#define p4d_none(x) (!(p4d_val(x) & ~_PAGE_NEEDSYNC))
+#define p4d_bad(x) ((p4d_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+#define p4d_present(x) (p4d_val(x) & _PAGE_PRESENT)
+#define p4d_populate(mm, p4d, pud) \
+ set_p4d(p4d, __p4d(_PAGE_TABLE + __pa(pud)))
+
+#define set_p4d(p4dptr, p4dval) (*(p4dptr) = (p4dval))
+
+
+static inline int pgd_needsync(pgd_t pgd)
{
- return(pgd_val(pgd) & _PAGE_NEWPAGE);
+ return pgd_val(pgd) & _PAGE_NEEDSYNC;
}
-static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; }
+static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEEDSYNC; }
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
static inline void pud_clear (pud_t *pud)
{
- set_pud(pud, __pud(_PAGE_NEWPAGE));
+ set_pud(pud, __pud(_PAGE_NEEDSYNC));
+}
+
+static inline void p4d_clear (p4d_t *p4d)
+{
+ set_p4d(p4d, __p4d(_PAGE_NEEDSYNC));
}
#define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK)
#define pud_pgtable(pud) ((pmd_t *) __va(pud_val(pud) & PAGE_MASK))
+#define p4d_page(p4d) phys_to_page(p4d_val(p4d) & PAGE_MASK)
+#define p4d_pgtable(p4d) ((pud_t *) __va(p4d_val(p4d) & PAGE_MASK))
+
static inline unsigned long pte_pfn(pte_t pte)
{
return phys_to_pfn(pte_val(pte));
@@ -97,4 +117,3 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
}
#endif
-
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index 83373c9963e7..0bd60afcc37d 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -11,8 +11,7 @@
#include <asm/fixmap.h>
#define _PAGE_PRESENT 0x001
-#define _PAGE_NEWPAGE 0x002
-#define _PAGE_NEWPROT 0x004
+#define _PAGE_NEEDSYNC 0x002
#define _PAGE_RW 0x020
#define _PAGE_USER 0x040
#define _PAGE_ACCESSED 0x080
@@ -24,10 +23,12 @@
/* We borrow bit 10 to store the exclusive marker in swap PTEs. */
#define _PAGE_SWP_EXCLUSIVE 0x400
-#ifdef CONFIG_3_LEVEL_PGTABLES
-#include <asm/pgtable-3level.h>
-#else
+#if CONFIG_PGTABLE_LEVELS == 4
+#include <asm/pgtable-4level.h>
+#elif CONFIG_PGTABLE_LEVELS == 2
#include <asm/pgtable-2level.h>
+#else
+#error "Unsupported number of page table levels"
#endif
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
@@ -78,22 +79,22 @@ extern unsigned long end_iomem;
*/
#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
-#define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
+#define pte_clear(mm, addr, xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEEDSYNC))
-#define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEWPAGE))
+#define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEEDSYNC))
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
-#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
+#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEEDSYNC; } while (0)
-#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE)
-#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE)
+#define pmd_needsync(x) (pmd_val(x) & _PAGE_NEEDSYNC)
+#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEEDSYNC)
-#define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE)
-#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE)
+#define pud_needsync(x) (pud_val(x) & _PAGE_NEEDSYNC)
+#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEEDSYNC)
-#define p4d_newpage(x) (p4d_val(x) & _PAGE_NEWPAGE)
-#define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEWPAGE)
+#define p4d_needsync(x) (p4d_val(x) & _PAGE_NEEDSYNC)
+#define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEEDSYNC)
#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT)
#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
@@ -144,14 +145,9 @@ static inline int pte_young(pte_t pte)
return pte_get_bits(pte, _PAGE_ACCESSED);
}
-static inline int pte_newpage(pte_t pte)
+static inline int pte_needsync(pte_t pte)
{
- return pte_get_bits(pte, _PAGE_NEWPAGE);
-}
-
-static inline int pte_newprot(pte_t pte)
-{
- return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT)));
+ return pte_get_bits(pte, _PAGE_NEEDSYNC);
}
/*
@@ -160,12 +156,6 @@ static inline int pte_newprot(pte_t pte)
* =================================
*/
-static inline pte_t pte_mknewprot(pte_t pte)
-{
- pte_set_bits(pte, _PAGE_NEWPROT);
- return(pte);
-}
-
static inline pte_t pte_mkclean(pte_t pte)
{
pte_clear_bits(pte, _PAGE_DIRTY);
@@ -180,19 +170,14 @@ static inline pte_t pte_mkold(pte_t pte)
static inline pte_t pte_wrprotect(pte_t pte)
{
- if (likely(pte_get_bits(pte, _PAGE_RW)))
- pte_clear_bits(pte, _PAGE_RW);
- else
- return pte;
- return(pte_mknewprot(pte));
+ pte_clear_bits(pte, _PAGE_RW);
+ return pte;
}
static inline pte_t pte_mkread(pte_t pte)
{
- if (unlikely(pte_get_bits(pte, _PAGE_USER)))
- return pte;
pte_set_bits(pte, _PAGE_USER);
- return(pte_mknewprot(pte));
+ return pte;
}
static inline pte_t pte_mkdirty(pte_t pte)
@@ -209,23 +194,19 @@ static inline pte_t pte_mkyoung(pte_t pte)
static inline pte_t pte_mkwrite_novma(pte_t pte)
{
- if (unlikely(pte_get_bits(pte, _PAGE_RW)))
- return pte;
pte_set_bits(pte, _PAGE_RW);
- return(pte_mknewprot(pte));
+ return pte;
}
static inline pte_t pte_mkuptodate(pte_t pte)
{
- pte_clear_bits(pte, _PAGE_NEWPAGE);
- if(pte_present(pte))
- pte_clear_bits(pte, _PAGE_NEWPROT);
- return(pte);
+ pte_clear_bits(pte, _PAGE_NEEDSYNC);
+ return pte;
}
-static inline pte_t pte_mknewpage(pte_t pte)
+static inline pte_t pte_mkneedsync(pte_t pte)
{
- pte_set_bits(pte, _PAGE_NEWPAGE);
+ pte_set_bits(pte, _PAGE_NEEDSYNC);
return(pte);
}
@@ -233,13 +214,11 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
{
pte_copy(*pteptr, pteval);
- /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
- * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
- * mapped pages.
+ /* If it's a swap entry, it needs to be marked _PAGE_NEEDSYNC so
+ * update_pte_range knows to unmap it.
*/
- *pteptr = pte_mknewpage(*pteptr);
- if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
+ *pteptr = pte_mkneedsync(*pteptr);
}
#define PFN_PTE_SHIFT PAGE_SHIFT
@@ -279,7 +258,7 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
#define __HAVE_ARCH_PTE_SAME
static inline int pte_same(pte_t pte_a, pte_t pte_b)
{
- return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE);
+ return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEEDSYNC);
}
/*
@@ -287,17 +266,13 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
* and a page entry and page directory to the page they refer to.
*/
-#define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys))
#define __virt_to_page(virt) phys_to_page(__pa(virt))
-#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
#define mk_pte(page, pgprot) \
({ pte_t pte; \
\
pte_set_val(pte, page_to_phys(page), (pgprot)); \
- if (pte_present(pte)) \
- pte_mknewprot(pte_mknewpage(pte)); \
pte;})
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
@@ -331,7 +306,7 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
* <--------------- offset ----------------> E < type -> 0 0 0 1 0
*
* E is the exclusive marker that is not stored in swap entries.
- * _PAGE_NEWPAGE (bit 1) is always set to 1 in set_pte().
+ * _PAGE_NEEDSYNC (bit 1) is always set to 1 in set_pte().
*/
#define __swp_type(x) (((x).val >> 5) & 0x1f)
#define __swp_offset(x) ((x).val >> 11)
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index bce4595798da..5d6356eafffe 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -20,10 +20,7 @@ struct task_struct;
struct mm_struct;
struct thread_struct {
- struct pt_regs regs;
struct pt_regs *segv_regs;
- void *fault_addr;
- jmp_buf *fault_catcher;
struct task_struct *prev_sched;
struct arch_thread arch;
jmp_buf switch_buf;
@@ -33,12 +30,14 @@ struct thread_struct {
void *arg;
} thread;
} request;
+
+ /* Contains variable sized FP registers */
+ struct pt_regs regs;
};
#define INIT_THREAD \
{ \
.regs = EMPTY_REGS, \
- .fault_addr = NULL, \
.prev_sched = NULL, \
.arch = INIT_ARCH_THREAD, \
.request = { } \
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h
index c7b4b49826a2..f9ad06fcc991 100644
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -17,35 +17,17 @@
#include <sysdep/ptrace_user.h>
struct thread_info {
- struct task_struct *task; /* main task structure */
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable,
<0 => BUG */
- struct thread_info *real_thread; /* Points to non-IRQ stack */
- unsigned long aux_fp_regs[FP_SIZE]; /* auxiliary fp_regs to save/restore
- them out-of-band */
};
#define INIT_THREAD_INFO(tsk) \
{ \
- .task = &tsk, \
.flags = 0, \
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
- .real_thread = NULL, \
-}
-
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
- struct thread_info *ti;
- unsigned long mask = THREAD_SIZE - 1;
- void *p;
-
- asm volatile ("" : "=r" (p) : "0" (&ti));
- ti = (struct thread_info *) (((unsigned long)p) & ~mask);
- return ti;
}
#endif
diff --git a/arch/um/include/asm/tlbflush.h b/arch/um/include/asm/tlbflush.h
index db997976b6ea..13a3009942be 100644
--- a/arch/um/include/asm/tlbflush.h
+++ b/arch/um/include/asm/tlbflush.h
@@ -9,8 +9,8 @@
#include <linux/mm.h>
/*
- * In UML, we need to sync the TLB over by using mmap/munmap/mprotect syscalls
- * from the process handling the MM (which can be the kernel itself).
+ * In UML, we need to sync the TLB over by using mmap/munmap syscalls from
+ * the process handling the MM (which can be the kernel itself).
*
* To track updates, we can hook into set_ptes and flush_tlb_*. With set_ptes
* we catch all PTE transitions where memory that was unusable becomes usable.
diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h
index 06292fca5a4d..ea65f151bf48 100644
--- a/arch/um/include/shared/as-layout.h
+++ b/arch/um/include/shared/as-layout.h
@@ -30,25 +30,23 @@
#include <sysdep/ptrace.h>
-struct cpu_task {
- void *task;
-};
+struct task_struct;
+extern struct task_struct *cpu_tasks[];
-extern struct cpu_task cpu_tasks[];
+extern unsigned long long physmem_size;
extern unsigned long high_physmem;
extern unsigned long uml_physmem;
extern unsigned long uml_reserved;
extern unsigned long end_vm;
extern unsigned long start_vm;
-extern unsigned long long highmem;
extern unsigned long brk_start;
extern unsigned long host_task_size;
extern unsigned long stub_start;
-extern int linux_main(int argc, char **argv);
+extern int linux_main(int argc, char **argv, char **envp);
extern void uml_finishsetup(void);
struct siginfo;
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h
index 579ed946a3a9..73f3a4792ed8 100644
--- a/arch/um/include/shared/common-offsets.h
+++ b/arch/um/include/shared/common-offsets.h
@@ -6,7 +6,6 @@ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
-DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE(UM_GFP_KERNEL, GFP_KERNEL);
DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC);
@@ -15,17 +14,3 @@ DEFINE(UM_THREAD_SIZE, THREAD_SIZE);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC);
-
-#ifdef CONFIG_PRINTK
-DEFINE(UML_CONFIG_PRINTK, CONFIG_PRINTK);
-#endif
-#ifdef CONFIG_UML_X86
-DEFINE(UML_CONFIG_UML_X86, CONFIG_UML_X86);
-#endif
-#ifdef CONFIG_64BIT
-DEFINE(UML_CONFIG_64BIT, CONFIG_64BIT);
-#endif
-#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
-DEFINE(UML_CONFIG_UML_TIME_TRAVEL_SUPPORT, CONFIG_UML_TIME_TRAVEL_SUPPORT);
-#endif
-
diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h
index d8ffd2db168e..f21dc8517538 100644
--- a/arch/um/include/shared/kern_util.h
+++ b/arch/um/include/shared/kern_util.h
@@ -60,7 +60,6 @@ extern unsigned long from_irq_stack(int nested);
extern int singlestepping(void);
extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
-extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs);
extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
extern void fatal_sigsegv(void) __attribute__ ((noreturn));
diff --git a/arch/um/include/shared/mem_user.h b/arch/um/include/shared/mem_user.h
index 11a723a58545..adfa08062f88 100644
--- a/arch/um/include/shared/mem_user.h
+++ b/arch/um/include/shared/mem_user.h
@@ -47,10 +47,9 @@ extern int iomem_size;
#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-extern void mem_total_pages(unsigned long physmem, unsigned long iomem,
- unsigned long highmem);
+extern void mem_total_pages(unsigned long physmem, unsigned long iomem);
extern void setup_physmem(unsigned long start, unsigned long usable,
- unsigned long len, unsigned long long highmem);
+ unsigned long len);
extern void map_memory(unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 9a039d6f1f74..5babad8c5f75 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -145,7 +145,6 @@ extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
extern int os_get_ifname(int fd, char *namebuf);
extern int os_set_slip(int fd);
extern int os_mode_fd(int fd, int mode);
-extern int os_fsync_file(int fd);
extern int os_seek_file(int fd, unsigned long long offset);
extern int os_open_file(const char *file, struct openflags flags, int mode);
@@ -199,15 +198,11 @@ extern int create_mem_file(unsigned long long len);
extern void report_enomem(void);
/* process.c */
-extern unsigned long os_process_pc(int pid);
-extern int os_process_parent(int pid);
extern void os_alarm_process(int pid);
-extern void os_stop_process(int pid);
extern void os_kill_process(int pid, int reap_child);
extern void os_kill_ptraced_process(int pid, int reap_child);
extern int os_getpid(void);
-extern int os_getpgrp(void);
extern void init_new_thread_signals(void);
@@ -220,6 +215,8 @@ extern int os_drop_memory(void *addr, int length);
extern int can_drop_memory(void);
extern int os_mincore(void *addr, unsigned long len);
+void os_set_pdeathsig(void);
+
/* execvp.c */
extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
/* helper.c */
@@ -244,7 +241,6 @@ extern void block_signals(void);
extern void unblock_signals(void);
extern int um_set_signals(int enable);
extern int um_set_signals_trace(int enable);
-extern int os_is_signal_stack(void);
extern void deliver_alarm(void);
extern void register_pm_wake_signal(void);
extern void block_signals_hard(void);
@@ -283,13 +279,11 @@ int map(struct mm_id *mm_idp, unsigned long virt,
unsigned long len, int prot, int phys_fd,
unsigned long long offset);
int unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len);
-int protect(struct mm_id *mm_idp, unsigned long addr,
- unsigned long len, unsigned int prot);
/* skas/process.c */
extern int is_skas_winch(int pid, int fd, void *data);
extern int start_userspace(unsigned long stub_stack);
-extern void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs);
+extern void userspace(struct uml_pt_regs *regs);
extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
extern void switch_threads(jmp_buf *me, jmp_buf *you);
extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
@@ -329,9 +323,6 @@ extern int __ignore_sigio_fd(int fd);
/* tty.c */
extern int get_pty(void);
-/* sys-$ARCH/task_size.c */
-extern unsigned long os_get_top_address(void);
-
long syscall(long number, ...);
/* irqflags tracing */
diff --git a/arch/um/include/shared/registers.h b/arch/um/include/shared/registers.h
index a0450326521c..7d81b2339a48 100644
--- a/arch/um/include/shared/registers.h
+++ b/arch/um/include/shared/registers.h
@@ -8,12 +8,6 @@
#include <sysdep/ptrace.h>
-extern int save_i387_registers(int pid, unsigned long *fp_regs);
-extern int restore_i387_registers(int pid, unsigned long *fp_regs);
-extern int save_fp_registers(int pid, unsigned long *fp_regs);
-extern int restore_fp_registers(int pid, unsigned long *fp_regs);
-extern int save_fpx_registers(int pid, unsigned long *fp_regs);
-extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
extern int init_pid_registers(int pid);
extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs);
extern int get_fp_registers(int pid, unsigned long *regs);
diff --git a/arch/um/include/shared/skas/stub-data.h b/arch/um/include/shared/skas/stub-data.h
index 2b6b44759dfa..81a4cace032c 100644
--- a/arch/um/include/shared/skas/stub-data.h
+++ b/arch/um/include/shared/skas/stub-data.h
@@ -12,6 +12,17 @@
#include <as-layout.h>
#include <sysdep/tls.h>
+struct stub_init_data {
+ unsigned long stub_start;
+
+ int stub_code_fd;
+ unsigned long stub_code_offset;
+ int stub_data_fd;
+ unsigned long stub_data_offset;
+
+ unsigned long segv_handler;
+};
+
#define STUB_NEXT_SYSCALL(s) \
((struct stub_syscall *) (((unsigned long) s) + (s)->cmd_len))
@@ -19,7 +30,6 @@ enum stub_syscall_type {
STUB_SYSCALL_UNSET = 0,
STUB_SYSCALL_MMAP,
STUB_SYSCALL_MUNMAP,
- STUB_SYSCALL_MPROTECT,
};
struct stub_syscall {
diff --git a/arch/um/include/shared/timetravel.h b/arch/um/include/shared/timetravel.h
index c8db2f213dba..7c2b277b7eb0 100644
--- a/arch/um/include/shared/timetravel.h
+++ b/arch/um/include/shared/timetravel.h
@@ -12,14 +12,13 @@ enum time_travel_mode {
TT_MODE_EXTERNAL,
};
-#if defined(UML_CONFIG_UML_TIME_TRAVEL_SUPPORT) || \
- defined(CONFIG_UML_TIME_TRAVEL_SUPPORT)
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
extern enum time_travel_mode time_travel_mode;
extern int time_travel_should_print_bc_msg;
#else
#define time_travel_mode TT_MODE_OFF
#define time_travel_should_print_bc_msg 0
-#endif /* (UML_)CONFIG_UML_TIME_TRAVEL_SUPPORT */
+#endif /* CONFIG_UML_TIME_TRAVEL_SUPPORT */
void _time_travel_print_bc_msg(void);
static inline void time_travel_print_bc_msg(void)
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h
index bbab79c0c074..139eb78a4767 100644
--- a/arch/um/include/shared/user.h
+++ b/arch/um/include/shared/user.h
@@ -38,7 +38,7 @@ extern void panic(const char *fmt, ...)
#define UM_KERN_DEBUG KERN_DEBUG
#define UM_KERN_CONT KERN_CONT
-#ifdef UML_CONFIG_PRINTK
+#if IS_ENABLED(CONFIG_PRINTK)
#define printk(...) _printk(__VA_ARGS__)
extern int _printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
diff --git a/arch/um/kernel/dtb.c b/arch/um/kernel/dtb.c
index 4954188a6a09..15c342426489 100644
--- a/arch/um/kernel/dtb.c
+++ b/arch/um/kernel/dtb.c
@@ -17,7 +17,7 @@ void uml_dtb_init(void)
area = uml_load_file(dtb, &size);
if (area) {
- if (!early_init_dt_scan(area)) {
+ if (!early_init_dt_scan(area, __pa(area))) {
pr_err("invalid DTB %s\n", dtb);
memblock_free(area, size);
return;
@@ -31,6 +31,7 @@ void uml_dtb_init(void)
static int __init uml_dtb_setup(char *line, int *add)
{
+ *add = 0;
dtb = line;
return 0;
}
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 3385d653ebd0..a36b7918a011 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -116,8 +116,6 @@ SECTIONS
.fini_array : { *(.fini_array) }
.data : {
INIT_TASK_DATA(KERNEL_STACK_SIZE)
- . = ALIGN(KERNEL_STACK_SIZE);
- *(.data..init_irqstack)
DATA_DATA
*(.data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
@@ -178,3 +176,6 @@ SECTIONS
DISCARDS
}
+
+ASSERT(__syscall_stub_end - __syscall_stub_start <= PAGE_SIZE,
+ "STUB code must not be larger than one page");
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 47b8cb1a1156..99dba827461c 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -34,6 +34,7 @@ int __init read_initrd(void)
static int __init uml_initrd_setup(char *line, int *add)
{
+ *add = 0;
initrd = line;
return 0;
}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 534e91797f89..338450741aac 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -674,115 +674,3 @@ void __init init_IRQ(void)
/* Initialize EPOLL Loop */
os_setup_epoll();
}
-
-/*
- * IRQ stack entry and exit:
- *
- * Unlike i386, UML doesn't receive IRQs on the normal kernel stack
- * and switch over to the IRQ stack after some preparation. We use
- * sigaltstack to receive signals on a separate stack from the start.
- * These two functions make sure the rest of the kernel won't be too
- * upset by being on a different stack. The IRQ stack has a
- * thread_info structure at the bottom so that current et al continue
- * to work.
- *
- * to_irq_stack copies the current task's thread_info to the IRQ stack
- * thread_info and sets the tasks's stack to point to the IRQ stack.
- *
- * from_irq_stack copies the thread_info struct back (flags may have
- * been modified) and resets the task's stack pointer.
- *
- * Tricky bits -
- *
- * What happens when two signals race each other? UML doesn't block
- * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal
- * could arrive while a previous one is still setting up the
- * thread_info.
- *
- * There are three cases -
- * The first interrupt on the stack - sets up the thread_info and
- * handles the interrupt
- * A nested interrupt interrupting the copying of the thread_info -
- * can't handle the interrupt, as the stack is in an unknown state
- * A nested interrupt not interrupting the copying of the
- * thread_info - doesn't do any setup, just handles the interrupt
- *
- * The first job is to figure out whether we interrupted stack setup.
- * This is done by xchging the signal mask with thread_info->pending.
- * If the value that comes back is zero, then there is no setup in
- * progress, and the interrupt can be handled. If the value is
- * non-zero, then there is stack setup in progress. In order to have
- * the interrupt handled, we leave our signal in the mask, and it will
- * be handled by the upper handler after it has set up the stack.
- *
- * Next is to figure out whether we are the outer handler or a nested
- * one. As part of setting up the stack, thread_info->real_thread is
- * set to non-NULL (and is reset to NULL on exit). This is the
- * nesting indicator. If it is non-NULL, then the stack is already
- * set up and the handler can run.
- */
-
-static unsigned long pending_mask;
-
-unsigned long to_irq_stack(unsigned long *mask_out)
-{
- struct thread_info *ti;
- unsigned long mask, old;
- int nested;
-
- mask = xchg(&pending_mask, *mask_out);
- if (mask != 0) {
- /*
- * If any interrupts come in at this point, we want to
- * make sure that their bits aren't lost by our
- * putting our bit in. So, this loop accumulates bits
- * until xchg returns the same value that we put in.
- * When that happens, there were no new interrupts,
- * and pending_mask contains a bit for each interrupt
- * that came in.
- */
- old = *mask_out;
- do {
- old |= mask;
- mask = xchg(&pending_mask, old);
- } while (mask != old);
- return 1;
- }
-
- ti = current_thread_info();
- nested = (ti->real_thread != NULL);
- if (!nested) {
- struct task_struct *task;
- struct thread_info *tti;
-
- task = cpu_tasks[ti->cpu].task;
- tti = task_thread_info(task);
-
- *ti = *tti;
- ti->real_thread = tti;
- task->stack = ti;
- }
-
- mask = xchg(&pending_mask, 0);
- *mask_out |= mask | nested;
- return 0;
-}
-
-unsigned long from_irq_stack(int nested)
-{
- struct thread_info *ti, *to;
- unsigned long mask;
-
- ti = current_thread_info();
-
- pending_mask = 1;
-
- to = ti->real_thread;
- current->stack = to;
- ti->real_thread = NULL;
- *to = *ti;
-
- mask = xchg(&pending_mask, 0);
- return mask & ~1;
-}
-
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index a5b4fe2ad931..53248ed04771 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -6,7 +6,6 @@
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/memblock.h>
-#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/slab.h>
@@ -51,8 +50,6 @@ EXPORT_SYMBOL(empty_zero_page);
pgd_t swapper_pg_dir[PTRS_PER_PGD];
/* Initialized at boot time, and readonly after that */
-unsigned long long highmem;
-EXPORT_SYMBOL(highmem);
int kmalloc_ok = 0;
/* Used during early boot */
@@ -98,7 +95,7 @@ static void __init one_page_table_init(pmd_t *pmd)
static void __init one_md_table_init(pud_t *pud)
{
-#ifdef CONFIG_3_LEVEL_PGTABLES
+#if CONFIG_PGTABLE_LEVELS > 2
pmd_t *pmd_table = (pmd_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
if (!pmd_table)
panic("%s: Failed to allocate %lu bytes align=%lx\n",
@@ -109,6 +106,19 @@ static void __init one_md_table_init(pud_t *pud)
#endif
}
+static void __init one_ud_table_init(p4d_t *p4d)
+{
+#if CONFIG_PGTABLE_LEVELS > 3
+ pud_t *pud_table = (pud_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+ if (!pud_table)
+ panic("%s: Failed to allocate %lu bytes align=%lx\n",
+ __func__, PAGE_SIZE, PAGE_SIZE);
+
+ set_p4d(p4d, __p4d(_KERNPG_TABLE + (unsigned long) __pa(pud_table)));
+ BUG_ON(pud_table != pud_offset(p4d, 0));
+#endif
+}
+
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
@@ -126,6 +136,8 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
p4d = p4d_offset(pgd, vaddr);
+ if (p4d_none(*p4d))
+ one_ud_table_init(p4d);
pud = pud_offset(p4d, vaddr);
if (pud_none(*pud))
one_md_table_init(pud);
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index fb2adfb49945..a74f17b033c4 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -22,19 +22,14 @@ static int physmem_fd = -1;
unsigned long high_physmem;
EXPORT_SYMBOL(high_physmem);
-extern unsigned long long physmem_size;
-
-void __init mem_total_pages(unsigned long physmem, unsigned long iomem,
- unsigned long highmem)
+void __init mem_total_pages(unsigned long physmem, unsigned long iomem)
{
- unsigned long phys_pages, highmem_pages;
- unsigned long iomem_pages, total_pages;
+ unsigned long phys_pages, iomem_pages, total_pages;
- phys_pages = physmem >> PAGE_SHIFT;
- iomem_pages = iomem >> PAGE_SHIFT;
- highmem_pages = highmem >> PAGE_SHIFT;
+ phys_pages = physmem >> PAGE_SHIFT;
+ iomem_pages = iomem >> PAGE_SHIFT;
- total_pages = phys_pages + iomem_pages + highmem_pages;
+ total_pages = phys_pages + iomem_pages;
max_mapnr = total_pages;
}
@@ -64,13 +59,12 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
* @reserve_end: end address of the physical kernel memory.
* @len: Length of total physical memory that should be mapped/made
* available, in bytes.
- * @highmem: Number of highmem bytes that should be mapped/made available.
*
- * Creates an unlinked temporary file of size (len + highmem) and memory maps
+ * Creates an unlinked temporary file of size (len) and memory maps
* it on the last executable image address (uml_reserved).
*
* The offset is needed as the length of the total physical memory
- * (len + highmem) includes the size of the memory used be the executable image,
+ * (len) includes the size of the memory used be the executable image,
* but the mapped-to address is the last address of the executable image
* (uml_reserved == end address of executable image).
*
@@ -78,24 +72,24 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
* of all user space processes/kernel tasks.
*/
void __init setup_physmem(unsigned long start, unsigned long reserve_end,
- unsigned long len, unsigned long long highmem)
+ unsigned long len)
{
unsigned long reserve = reserve_end - start;
- long map_size = len - reserve;
+ unsigned long map_size = len - reserve;
int err;
- if(map_size <= 0) {
+ if (len <= reserve) {
os_warn("Too few physical memory! Needed=%lu, given=%lu\n",
reserve, len);
exit(1);
}
- physmem_fd = create_mem_file(len + highmem);
+ physmem_fd = create_mem_file(len);
err = os_map_memory((void *) reserve_end, physmem_fd, reserve,
map_size, 1, 1, 1);
if (err < 0) {
- os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p "
+ os_warn("setup_physmem - mapping %lu bytes of memory at 0x%p "
"failed - errno = %d\n", map_size,
(void *) reserve_end, err);
exit(1);
@@ -107,9 +101,8 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
*/
os_seek_file(physmem_fd, __pa(__syscall_stub_start));
os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE);
- os_fsync_file(physmem_fd);
- memblock_add(__pa(start), len + highmem);
+ memblock_add(__pa(start), len);
memblock_reserve(__pa(start), reserve);
min_low_pfn = PFN_UP(__pa(reserve_end));
@@ -137,10 +130,6 @@ int phys_mapping(unsigned long phys, unsigned long long *offset_out)
region = region->next;
}
}
- else if (phys < __pa(end_iomem) + highmem) {
- fd = physmem_fd;
- *offset_out = phys - iomem_size;
- }
return fd;
}
@@ -149,6 +138,8 @@ EXPORT_SYMBOL(phys_mapping);
static int __init uml_mem_setup(char *line, int *add)
{
char *retptr;
+
+ *add = 0;
physmem_size = memparse(line,&retptr);
return 0;
}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index be2856af6d4c..30bdc0a87dc8 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -43,7 +43,8 @@
* cares about its entry, so it's OK if another processor is modifying its
* entry.
*/
-struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { NULL } };
+struct task_struct *cpu_tasks[NR_CPUS];
+EXPORT_SYMBOL(cpu_tasks);
void free_stack(unsigned long stack, int order)
{
@@ -64,7 +65,7 @@ unsigned long alloc_stack(int order, int atomic)
static inline void set_current(struct task_struct *task)
{
- cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) { task });
+ cpu_tasks[task_thread_info(task)->cpu] = task;
}
struct task_struct *__switch_to(struct task_struct *from, struct task_struct *to)
@@ -116,7 +117,7 @@ void new_thread_handler(void)
* callback returns only if the kernel thread execs a process
*/
fn(arg);
- userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
+ userspace(&current->thread.regs.regs);
}
/* Called magically, see new_thread_handler above */
@@ -133,7 +134,7 @@ static void fork_handler(void)
current->thread.prev_sched = NULL;
- userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
+ userspace(&current->thread.regs.regs);
}
int copy_thread(struct task_struct * p, const struct kernel_clone_args *args)
@@ -187,6 +188,13 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
kmalloc_ok = save_kmalloc_ok;
}
+int arch_dup_task_struct(struct task_struct *dst,
+ struct task_struct *src)
+{
+ memcpy(dst, src, arch_task_struct_size);
+ return 0;
+}
+
void um_idle_sleep(void)
{
if (time_travel_mode != TT_MODE_OFF)
@@ -287,11 +295,3 @@ unsigned long __get_wchan(struct task_struct *p)
return 0;
}
-
-int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
-{
- int cpu = current_thread_info()->cpu;
-
- return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
-}
-
diff --git a/arch/um/kernel/skas/.gitignore b/arch/um/kernel/skas/.gitignore
new file mode 100644
index 000000000000..c3409ced0f38
--- /dev/null
+++ b/arch/um/kernel/skas/.gitignore
@@ -0,0 +1,2 @@
+stub_exe
+stub_exe.dbg
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 6f86d53e3d69..3384be42691f 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,14 +3,48 @@
# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
#
-obj-y := stub.o mmu.o process.o syscall.o uaccess.o
+obj-y := stub.o mmu.o process.o syscall.o uaccess.o \
+ stub_exe_embed.o
+
+# Stub executable
+
+stub_exe_objs-y := stub_exe.o
+
+stub_exe_objs := $(foreach F,$(stub_exe_objs-y),$(obj)/$F)
+
+# Object file containing the ELF executable
+$(obj)/stub_exe_embed.o: $(src)/stub_exe_embed.S $(obj)/stub_exe
+
+$(obj)/stub_exe.dbg: $(stub_exe_objs) FORCE
+ $(call if_changed,stub_exe)
+
+$(obj)/stub_exe: OBJCOPYFLAGS := -S
+$(obj)/stub_exe: $(obj)/stub_exe.dbg FORCE
+ $(call if_changed,objcopy)
+
+quiet_cmd_stub_exe = STUB_EXE $@
+ cmd_stub_exe = $(CC) -nostdlib -o $@ \
+ $(filter-out $(UM_GPROF_OPT) $(UM_GCOV_OPT),$(KBUILD_CFLAGS)) $(STUB_EXE_LDFLAGS) \
+ $(filter %.o,$^)
+
+STUB_EXE_LDFLAGS = -Wl,-n -static
+
+targets += stub_exe.dbg stub_exe $(stub_exe_objs-y)
+
+# end
# stub.o is in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
# disable it
CFLAGS_stub.o := $(CFLAGS_NO_HARDENING)
-UNPROFILE_OBJS := stub.o
+CFLAGS_stub_exe.o := $(CFLAGS_NO_HARDENING)
+
+# Clang will call memset() from __builtin_alloca() when stack variable
+# initialization is enabled, which is used in stub_exe.c.
+CFLAGS_stub_exe.o += $(call cc-option, -ftrivial-auto-var-init=uninitialized)
+
+UNPROFILE_OBJS := stub.o stub_exe.o
KCOV_INSTRUMENT := n
include $(srctree)/arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 886ed5e65674..0eb5a1d3ba70 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -40,35 +40,13 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
goto out_free;
}
- /*
- * Ensure the new MM is clean and nothing unwanted is mapped.
- *
- * TODO: We should clear the memory up to STUB_START to ensure there is
- * nothing mapped there, i.e. we (currently) have:
- *
- * |- user memory -|- unused -|- stub -|- unused -|
- * ^ TASK_SIZE ^ STUB_START
- *
- * Meaning we have two unused areas where we may still have valid
- * mappings from our internal clone(). That isn't really a problem as
- * userspace is not going to access them, but it is definitely not
- * correct.
- *
- * However, we are "lucky" and if rseq is configured, then on 32 bit
- * it will fall into the first empty range while on 64 bit it is going
- * to use an anonymous mapping in the second range. As such, things
- * continue to work for now as long as we don't start unmapping these
- * areas.
- *
- * Change this to STUB_START once we have a clean userspace.
- */
- unmap(new_id, 0, TASK_SIZE);
+ /* Ensure the new MM is clean and nothing unwanted is mapped */
+ unmap(new_id, 0, STUB_START);
return 0;
out_free:
- if (new_id->stack != 0)
- free_pages(new_id->stack, ilog2(STUB_DATA_PAGES));
+ free_pages(new_id->stack, ilog2(STUB_DATA_PAGES));
out:
return ret;
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 68657988c8d1..05dcdc057af9 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -22,15 +22,13 @@ static int __init start_kernel_proc(void *unused)
{
block_signals_trace();
- cpu_tasks[0].task = current;
-
start_kernel();
return 0;
}
extern int userspace_pid[];
-extern char cpu0_irqstack[];
+static char cpu0_irqstack[THREAD_SIZE] __aligned(THREAD_SIZE);
int __init start_uml(void)
{
diff --git a/arch/um/kernel/skas/stub.c b/arch/um/kernel/skas/stub.c
index 5d52ffa682dc..796fc266d3bb 100644
--- a/arch/um/kernel/skas/stub.c
+++ b/arch/um/kernel/skas/stub.c
@@ -35,16 +35,6 @@ static __always_inline int syscall_handler(struct stub_data *d)
return -1;
}
break;
- case STUB_SYSCALL_MPROTECT:
- res = stub_syscall3(__NR_mprotect,
- sc->mem.addr, sc->mem.length,
- sc->mem.prot);
- if (res) {
- d->err = res;
- d->syscall_data_len = i;
- return -1;
- }
- break;
default:
d->err = -95; /* EOPNOTSUPP */
d->syscall_data_len = i;
diff --git a/arch/um/kernel/skas/stub_exe.c b/arch/um/kernel/skas/stub_exe.c
new file mode 100644
index 000000000000..23c99b285e82
--- /dev/null
+++ b/arch/um/kernel/skas/stub_exe.c
@@ -0,0 +1,95 @@
+#include <sys/ptrace.h>
+#include <sys/prctl.h>
+#include <asm/unistd.h>
+#include <sysdep/stub.h>
+#include <stub-data.h>
+
+void _start(void);
+
+noinline static void real_init(void)
+{
+ struct stub_init_data init_data;
+ unsigned long res;
+ struct {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+ } stack = {
+ .ss_size = STUB_DATA_PAGES * UM_KERN_PAGE_SIZE,
+ };
+ struct {
+ void *sa_handler_;
+ unsigned long sa_flags;
+ void *sa_restorer;
+ unsigned long long sa_mask;
+ } sa = {
+ /* Need to set SA_RESTORER (but the handler never returns) */
+ .sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO | 0x04000000,
+ /* no need to mask any signals */
+ .sa_mask = 0,
+ };
+
+ /* set a nice name */
+ stub_syscall2(__NR_prctl, PR_SET_NAME, (unsigned long)"uml-userspace");
+
+ /* Make sure this process dies if the kernel dies */
+ stub_syscall2(__NR_prctl, PR_SET_PDEATHSIG, SIGKILL);
+
+ /* read information from STDIN and close it */
+ res = stub_syscall3(__NR_read, 0,
+ (unsigned long)&init_data, sizeof(init_data));
+ if (res != sizeof(init_data))
+ stub_syscall1(__NR_exit, 10);
+
+ stub_syscall1(__NR_close, 0);
+
+ /* map stub code + data */
+ res = stub_syscall6(STUB_MMAP_NR,
+ init_data.stub_start, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED,
+ init_data.stub_code_fd, init_data.stub_code_offset);
+ if (res != init_data.stub_start)
+ stub_syscall1(__NR_exit, 11);
+
+ res = stub_syscall6(STUB_MMAP_NR,
+ init_data.stub_start + UM_KERN_PAGE_SIZE,
+ STUB_DATA_PAGES * UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
+ init_data.stub_data_fd, init_data.stub_data_offset);
+ if (res != init_data.stub_start + UM_KERN_PAGE_SIZE)
+ stub_syscall1(__NR_exit, 12);
+
+ /* setup signal stack inside stub data */
+ stack.ss_sp = (void *)init_data.stub_start + UM_KERN_PAGE_SIZE;
+ stub_syscall2(__NR_sigaltstack, (unsigned long)&stack, 0);
+
+ /* register SIGSEGV handler */
+ sa.sa_handler_ = (void *) init_data.segv_handler;
+ res = stub_syscall4(__NR_rt_sigaction, SIGSEGV, (unsigned long)&sa, 0,
+ sizeof(sa.sa_mask));
+ if (res != 0)
+ stub_syscall1(__NR_exit, 13);
+
+ stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
+
+ stub_syscall2(__NR_kill, stub_syscall0(__NR_getpid), SIGSTOP);
+
+ stub_syscall1(__NR_exit, 14);
+
+ __builtin_unreachable();
+}
+
+__attribute__((naked)) void _start(void)
+{
+ /*
+ * Since the stack after exec() starts at the top-most address,
+ * but that's exactly where we also want to map the stub data
+ * and code, this must:
+ * - push the stack by 1 code and STUB_DATA_PAGES data pages
+ * - call real_init()
+ * This way, real_init() can use the stack normally, while the
+ * original stack further down (higher address) will become
+ * inaccessible after the mmap() calls above.
+ */
+ stub_start(real_init);
+}
diff --git a/arch/um/kernel/skas/stub_exe_embed.S b/arch/um/kernel/skas/stub_exe_embed.S
new file mode 100644
index 000000000000..6d8914fbe8f1
--- /dev/null
+++ b/arch/um/kernel/skas/stub_exe_embed.S
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/init.h>
+#include <linux/linkage.h>
+
+__INITDATA
+
+SYM_DATA_START(stub_exe_start)
+ .incbin "arch/um/kernel/skas/stub_exe"
+SYM_DATA_END_LABEL(stub_exe_start, SYM_L_GLOBAL, stub_exe_end)
+
+__FINIT
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 4bb8622dc512..13ee5666668d 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -32,12 +32,6 @@ void show_stack(struct task_struct *task, unsigned long *stack,
struct pt_regs *segv_regs = current->thread.segv_regs;
int i;
- if (!segv_regs && os_is_signal_stack()) {
- pr_err("Received SIGSEGV in SIGSEGV handler,"
- " aborting stack trace!\n");
- return;
- }
-
if (!stack)
stack = get_stack_pointer(task, segv_regs);
@@ -52,5 +46,5 @@ void show_stack(struct task_struct *task, unsigned long *stack,
}
printk("%sCall Trace:\n", loglvl);
- dump_trace(current, &stackops, (void *)loglvl);
+ dump_trace(task ?: current, &stackops, (void *)loglvl);
}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 29b27b90581f..1394568c0210 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -25,6 +25,8 @@
#include <shared/init.h>
#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
+#include <linux/sched/clock.h>
+
enum time_travel_mode time_travel_mode;
EXPORT_SYMBOL_GPL(time_travel_mode);
@@ -47,6 +49,15 @@ static u16 time_travel_shm_id;
static struct um_timetravel_schedshm *time_travel_shm;
static union um_timetravel_schedshm_client *time_travel_shm_client;
+unsigned long tt_extra_sched_jiffies;
+
+notrace unsigned long long sched_clock(void)
+{
+ return (unsigned long long)(jiffies - INITIAL_JIFFIES +
+ tt_extra_sched_jiffies)
+ * (NSEC_PER_SEC / HZ);
+}
+
static void time_travel_set_time(unsigned long long ns)
{
if (unlikely(ns < time_travel_time))
@@ -443,6 +454,11 @@ static void time_travel_periodic_timer(struct time_travel_event *e)
{
time_travel_add_event(&time_travel_timer_event,
time_travel_time + time_travel_timer_interval);
+
+ /* clock tick; decrease extra jiffies by keeping sched_clock constant */
+ if (tt_extra_sched_jiffies > 0)
+ tt_extra_sched_jiffies -= 1;
+
deliver_alarm();
}
@@ -594,6 +610,10 @@ EXPORT_SYMBOL_GPL(time_travel_add_irq_event);
static void time_travel_oneshot_timer(struct time_travel_event *e)
{
+ /* clock tick; decrease extra jiffies by keeping sched_clock constant */
+ if (tt_extra_sched_jiffies > 0)
+ tt_extra_sched_jiffies -= 1;
+
deliver_alarm();
}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 548af31d4111..cf7e0d4407f2 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -23,9 +23,6 @@ struct vm_ops {
int phys_fd, unsigned long long offset);
int (*unmap)(struct mm_id *mm_idp,
unsigned long virt, unsigned long len);
- int (*mprotect)(struct mm_id *mm_idp,
- unsigned long virt, unsigned long len,
- unsigned int prot);
};
static int kern_map(struct mm_id *mm_idp,
@@ -44,15 +41,6 @@ static int kern_unmap(struct mm_id *mm_idp,
return os_unmap_memory((void *)virt, len);
}
-static int kern_mprotect(struct mm_id *mm_idp,
- unsigned long virt, unsigned long len,
- unsigned int prot)
-{
- return os_protect_memory((void *)virt, len,
- prot & UM_PROT_READ, prot & UM_PROT_WRITE,
- 1);
-}
-
void report_enomem(void)
{
printk(KERN_ERR "UML ran out of memory on the host side! "
@@ -65,33 +53,37 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
struct vm_ops *ops)
{
pte_t *pte;
- int r, w, x, prot, ret = 0;
+ int ret = 0;
pte = pte_offset_kernel(pmd, addr);
do {
- r = pte_read(*pte);
- w = pte_write(*pte);
- x = pte_exec(*pte);
- if (!pte_young(*pte)) {
- r = 0;
- w = 0;
- } else if (!pte_dirty(*pte))
- w = 0;
-
- prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
- (x ? UM_PROT_EXEC : 0));
- if (pte_newpage(*pte)) {
- if (pte_present(*pte)) {
- __u64 offset;
- unsigned long phys = pte_val(*pte) & PAGE_MASK;
- int fd = phys_mapping(phys, &offset);
-
- ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE,
- prot, fd, offset);
- } else
- ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE);
- } else if (pte_newprot(*pte))
- ret = ops->mprotect(ops->mm_idp, addr, PAGE_SIZE, prot);
+ if (!pte_needsync(*pte))
+ continue;
+
+ if (pte_present(*pte)) {
+ __u64 offset;
+ unsigned long phys = pte_val(*pte) & PAGE_MASK;
+ int fd = phys_mapping(phys, &offset);
+ int r, w, x, prot;
+
+ r = pte_read(*pte);
+ w = pte_write(*pte);
+ x = pte_exec(*pte);
+ if (!pte_young(*pte)) {
+ r = 0;
+ w = 0;
+ } else if (!pte_dirty(*pte))
+ w = 0;
+
+ prot = (r ? UM_PROT_READ : 0) |
+ (w ? UM_PROT_WRITE : 0) |
+ (x ? UM_PROT_EXEC : 0);
+
+ ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE,
+ prot, fd, offset);
+ } else
+ ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE);
+
*pte = pte_mkuptodate(*pte);
} while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
return ret;
@@ -109,7 +101,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
do {
next = pmd_addr_end(addr, end);
if (!pmd_present(*pmd)) {
- if (pmd_newpage(*pmd)) {
+ if (pmd_needsync(*pmd)) {
ret = ops->unmap(ops->mm_idp, addr,
next - addr);
pmd_mkuptodate(*pmd);
@@ -132,7 +124,7 @@ static inline int update_pud_range(p4d_t *p4d, unsigned long addr,
do {
next = pud_addr_end(addr, end);
if (!pud_present(*pud)) {
- if (pud_newpage(*pud)) {
+ if (pud_needsync(*pud)) {
ret = ops->unmap(ops->mm_idp, addr,
next - addr);
pud_mkuptodate(*pud);
@@ -155,7 +147,7 @@ static inline int update_p4d_range(pgd_t *pgd, unsigned long addr,
do {
next = p4d_addr_end(addr, end);
if (!p4d_present(*p4d)) {
- if (p4d_newpage(*p4d)) {
+ if (p4d_needsync(*p4d)) {
ret = ops->unmap(ops->mm_idp, addr,
next - addr);
p4d_mkuptodate(*p4d);
@@ -180,18 +172,16 @@ int um_tlb_sync(struct mm_struct *mm)
if (mm == &init_mm) {
ops.mmap = kern_map;
ops.unmap = kern_unmap;
- ops.mprotect = kern_mprotect;
} else {
ops.mmap = map;
ops.unmap = unmap;
- ops.mprotect = protect;
}
pgd = pgd_offset(mm, addr);
do {
next = pgd_addr_end(addr, mm->context.sync_tlb_range_to);
if (!pgd_present(*pgd)) {
- if (pgd_newpage(*pgd)) {
+ if (pgd_needsync(*pgd)) {
ret = ops.unmap(ops.mm_idp, addr,
next - addr);
pgd_mkuptodate(*pgd);
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 97c8df9c4401..cdaee3e94273 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -201,7 +201,6 @@ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
struct uml_pt_regs *regs)
{
- jmp_buf *catcher;
int si_code;
int err;
int is_write = FAULT_WRITE(fi);
@@ -246,15 +245,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
address = 0;
}
- catcher = current->thread.fault_catcher;
if (!err)
goto out;
- else if (catcher != NULL) {
- current->thread.fault_addr = (void *) address;
- UML_LONGJMP(catcher, 1);
- }
- else if (current->thread.fault_addr != NULL)
- panic("fault_addr set but no fault catcher");
else if (!is_user && arch_fixup(ip, regs))
goto out;
@@ -310,14 +302,6 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
}
}
-void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs)
-{
- if (current->thread.fault_catcher != NULL)
- UML_LONGJMP(current->thread.fault_catcher, 1);
- else
- relay_signal(sig, si, regs);
-}
-
void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
{
do_IRQ(WINCH_IRQ, regs);
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 8e594cda6d77..8037a967225d 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -65,9 +65,6 @@ struct cpuinfo_um boot_cpu_data = {
EXPORT_SYMBOL(boot_cpu_data);
-union thread_union cpu0_irqstack
- __section(".data..init_irqstack") =
- { .thread_info = INIT_THREAD_INFO(init_task) };
/* Changed in setup_arch, which is called in early boot */
static char host_info[(__NEW_UTS_LEN + 1) * 5];
@@ -131,7 +128,7 @@ static int have_root __initdata;
static int have_console __initdata;
/* Set in uml_mem_setup and modified in linux_main */
-long long physmem_size = 64 * 1024 * 1024;
+unsigned long long physmem_size = 64 * 1024 * 1024;
EXPORT_SYMBOL(physmem_size);
static const char *usage_string =
@@ -167,19 +164,6 @@ __uml_setup("root=", uml_root_setup,
" root=/dev/ubd5\n\n"
);
-static int __init no_skas_debug_setup(char *line, int *add)
-{
- os_warn("'debug' is not necessary to gdb UML in skas mode - run\n");
- os_warn("'gdb linux'\n");
-
- return 0;
-}
-
-__uml_setup("debug", no_skas_debug_setup,
-"debug\n"
-" this flag is not needed to run gdb on UML in skas mode\n\n"
-);
-
static int __init uml_console_setup(char *line, int *add)
{
have_console = 1;
@@ -257,6 +241,8 @@ static struct notifier_block panic_exit_notifier = {
void uml_finishsetup(void)
{
+ cpu_tasks[0] = &init_task;
+
atomic_notifier_chain_register(&panic_notifier_list,
&panic_exit_notifier);
@@ -302,7 +288,24 @@ static void parse_cache_line(char *line)
}
}
-int __init linux_main(int argc, char **argv)
+static unsigned long get_top_address(char **envp)
+{
+ unsigned long top_addr = (unsigned long) &top_addr;
+ int i;
+
+ /* The earliest variable should be after the program name in ELF */
+ for (i = 0; envp[i]; i++) {
+ if ((unsigned long) envp[i] > top_addr)
+ top_addr = (unsigned long) envp[i];
+ }
+
+ top_addr &= ~(UM_KERN_PAGE_SIZE - 1);
+ top_addr += UM_KERN_PAGE_SIZE;
+
+ return top_addr;
+}
+
+int __init linux_main(int argc, char **argv, char **envp)
{
unsigned long avail, diff;
unsigned long virtmem_size, max_physmem;
@@ -324,20 +327,23 @@ int __init linux_main(int argc, char **argv)
if (have_console == 0)
add_arg(DEFAULT_COMMAND_LINE_CONSOLE);
- host_task_size = os_get_top_address();
- /* reserve a few pages for the stubs (taking care of data alignment) */
- /* align the data portion */
- BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES));
- stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1);
+ host_task_size = get_top_address(envp);
+ /* reserve a few pages for the stubs */
+ stub_start = host_task_size - STUB_DATA_PAGES * PAGE_SIZE;
/* another page for the code portion */
stub_start -= PAGE_SIZE;
host_task_size = stub_start;
+ /* Limit TASK_SIZE to what is addressable by the page table */
+ task_size = host_task_size;
+ if (task_size > (unsigned long long) PTRS_PER_PGD * PGDIR_SIZE)
+ task_size = PTRS_PER_PGD * PGDIR_SIZE;
+
/*
* TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps
* out
*/
- task_size = host_task_size & PGDIR_MASK;
+ task_size = task_size & PGDIR_MASK;
/* OS sanity checks that need to happen before the kernel runs */
os_early_checks();
@@ -366,18 +372,15 @@ int __init linux_main(int argc, char **argv)
setup_machinename(init_utsname()->machine);
- highmem = 0;
+ physmem_size = (physmem_size + PAGE_SIZE - 1) & PAGE_MASK;
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
+
max_physmem = TASK_SIZE - uml_physmem - iomem_size - MIN_VMALLOC;
- /*
- * Zones have to begin on a 1 << MAX_PAGE_ORDER page boundary,
- * so this makes sure that's true for highmem
- */
- max_physmem &= ~((1 << (PAGE_SHIFT + MAX_PAGE_ORDER)) - 1);
if (physmem_size + iomem_size > max_physmem) {
- highmem = physmem_size + iomem_size - max_physmem;
- physmem_size -= highmem;
+ physmem_size = max_physmem - iomem_size;
+ os_info("Physical memory size shrunk to %llu bytes\n",
+ physmem_size);
}
high_physmem = uml_physmem + physmem_size;
@@ -398,6 +401,8 @@ int __init linux_main(int argc, char **argv)
os_info("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
+ arch_task_struct_size = sizeof(struct task_struct) + host_fp_size;
+
os_flush_stdout();
return start_uml();
@@ -412,9 +417,9 @@ void __init setup_arch(char **cmdline_p)
{
u8 rng_seed[32];
- stack_protections((unsigned long) &init_thread_info);
- setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
- mem_total_pages(physmem_size, iomem_size, highmem);
+ stack_protections((unsigned long) init_task.stack);
+ setup_physmem(uml_physmem, uml_reserved, physmem_size);
+ mem_total_pages(physmem_size, iomem_size);
uml_dtb_init();
read_initrd();
@@ -435,24 +440,25 @@ void __init arch_cpu_finalize_init(void)
os_check_bugs();
}
-void apply_seal_endbr(s32 *start, s32 *end)
+void apply_seal_endbr(s32 *start, s32 *end, struct module *mod)
{
}
-void apply_retpolines(s32 *start, s32 *end)
+void apply_retpolines(s32 *start, s32 *end, struct module *mod)
{
}
-void apply_returns(s32 *start, s32 *end)
+void apply_returns(s32 *start, s32 *end, struct module *mod)
{
}
void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
- s32 *start_cfi, s32 *end_cfi)
+ s32 *start_cfi, s32 *end_cfi, struct module *mod)
{
}
-void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
+ struct module *mod)
{
}
@@ -468,6 +474,11 @@ void *text_poke(void *addr, const void *opcode, size_t len)
return memcpy(addr, opcode, len);
}
+void *text_poke_copy(void *addr, const void *opcode, size_t len)
+{
+ return text_poke(addr, opcode, len);
+}
+
void text_poke_sync(void)
{
}
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 5c92d58a78e8..a409d4b66114 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -77,8 +77,6 @@ SECTIONS
.data :
{
INIT_TASK_DATA(KERNEL_STACK_SIZE)
- . = ALIGN(KERNEL_STACK_SIZE);
- *(.data..init_irqstack)
DATA_DATA
*(.gnu.linkonce.d*)
CONSTRUCTORS
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 544e0b344c75..049dfa5bc9c6 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -12,6 +12,8 @@ obj-y = execvp.o file.o helper.o irq.o main.o mem.o process.o \
CFLAGS_signal.o += -Wframe-larger-than=4096
+CFLAGS_main.o += -Wno-frame-larger-than
+
obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
USER_OBJS := $(user-objs-y) elf_aux.o execvp.o file.o helper.o irq.o \
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index f1d03cf3957f..a0d01c68ce3e 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -255,12 +255,6 @@ void os_close_file(int fd)
{
close(fd);
}
-int os_fsync_file(int fd)
-{
- if (fsync(fd) < 0)
- return -errno;
- return 0;
-}
int os_seek_file(int fd, unsigned long long offset)
{
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index f98ff79cdbf7..0afcdeb8995b 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -11,6 +11,7 @@
#include <signal.h>
#include <string.h>
#include <sys/resource.h>
+#include <sys/personality.h>
#include <as-layout.h>
#include <init.h>
#include <kern_util.h>
@@ -108,6 +109,21 @@ int __init main(int argc, char **argv, char **envp)
char **new_argv;
int ret, i, err;
+ /* Disable randomization and re-exec if it was changed successfully */
+ ret = personality(PER_LINUX | ADDR_NO_RANDOMIZE);
+ if (ret >= 0 && (ret & (PER_LINUX | ADDR_NO_RANDOMIZE)) !=
+ (PER_LINUX | ADDR_NO_RANDOMIZE)) {
+ char buf[4096] = {};
+ ssize_t ret;
+
+ ret = readlink("/proc/self/exe", buf, sizeof(buf));
+ if (ret < 0 || ret >= sizeof(buf)) {
+ perror("readlink failure");
+ exit(1);
+ }
+ execve(buf, argv, envp);
+ }
+
set_stklim();
setup_env_path();
@@ -140,7 +156,7 @@ int __init main(int argc, char **argv, char **envp)
#endif
change_sig(SIGPIPE, 0);
- ret = linux_main(argc, argv);
+ ret = linux_main(argc, argv, envp);
/*
* Disable SIGPROF - I have no idea why libc doesn't do this or turn
@@ -182,6 +198,7 @@ int __init main(int argc, char **argv, char **envp)
}
extern void *__real_malloc(int);
+extern void __real_free(void *);
/* workaround for -Wmissing-prototypes warnings */
void *__wrap_malloc(int size);
@@ -219,10 +236,6 @@ void *__wrap_calloc(int n, int size)
return ptr;
}
-extern void __real_free(void *);
-
-extern unsigned long high_physmem;
-
void __wrap_free(void *ptr)
{
unsigned long addr = (unsigned long) ptr;
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index cf44d386f23c..72f302f4d197 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -39,10 +39,22 @@ void kasan_map_memory(void *start, size_t len)
strerror(errno));
exit(1);
}
+
+ if (madvise(start, len, MADV_DONTDUMP)) {
+ os_info("Couldn't set MAD_DONTDUMP on shadow memory: %s\n.",
+ strerror(errno));
+ exit(1);
+ }
+
+ if (madvise(start, len, MADV_DONTFORK)) {
+ os_info("Couldn't set MADV_DONTFORK on shadow memory: %s\n.",
+ strerror(errno));
+ exit(1);
+ }
}
/* Set by make_tempfile() during early boot. */
-static char *tempdir = NULL;
+char *tempdir = NULL;
/* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */
static int __init check_tmpfs(const char *dir)
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index e52dd37ddadc..9f086f939420 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -12,94 +12,18 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
+#include <sys/prctl.h>
#include <sys/wait.h>
#include <asm/unistd.h>
#include <init.h>
#include <longjmp.h>
#include <os.h>
-#define ARBITRARY_ADDR -1
-#define FAILURE_PID -1
-
-#define STAT_PATH_LEN sizeof("/proc/#######/stat\0")
-#define COMM_SCANF "%*[^)])"
-
-unsigned long os_process_pc(int pid)
-{
- char proc_stat[STAT_PATH_LEN], buf[256];
- unsigned long pc = ARBITRARY_ADDR;
- int fd, err;
-
- sprintf(proc_stat, "/proc/%d/stat", pid);
- fd = open(proc_stat, O_RDONLY, 0);
- if (fd < 0) {
- printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', "
- "errno = %d\n", proc_stat, errno);
- goto out;
- }
- CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
- if (err < 0) {
- printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', "
- "err = %d\n", proc_stat, errno);
- goto out_close;
- }
- os_close_file(fd);
- pc = ARBITRARY_ADDR;
- if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %lu", &pc) != 1)
- printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n",
- buf);
- out_close:
- close(fd);
- out:
- return pc;
-}
-
-int os_process_parent(int pid)
-{
- char stat[STAT_PATH_LEN];
- char data[256];
- int parent = FAILURE_PID, n, fd;
-
- if (pid == -1)
- return parent;
-
- snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
- fd = open(stat, O_RDONLY, 0);
- if (fd < 0) {
- printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat,
- errno);
- return parent;
- }
-
- CATCH_EINTR(n = read(fd, data, sizeof(data)));
- close(fd);
-
- if (n < 0) {
- printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat,
- errno);
- return parent;
- }
-
- parent = FAILURE_PID;
- n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
- if (n != 1)
- printk(UM_KERN_ERR "Failed to scan '%s'\n", data);
-
- return parent;
-}
-
void os_alarm_process(int pid)
{
kill(pid, SIGALRM);
}
-void os_stop_process(int pid)
-{
- kill(pid, SIGSTOP);
-}
-
void os_kill_process(int pid, int reap_child)
{
kill(pid, SIGKILL);
@@ -130,11 +54,6 @@ int os_getpid(void)
return syscall(__NR_getpid);
}
-int os_getpgrp(void)
-{
- return getpgrp();
-}
-
int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
int r, int w, int x)
{
@@ -285,3 +204,8 @@ void init_new_thread_signals(void)
set_handler(SIGIO);
signal(SIGWINCH, SIG_IGN);
}
+
+void os_set_pdeathsig(void)
+{
+ prctl(PR_SET_PDEATHSIG, SIGKILL);
+}
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
index bd80b921add0..d7ca148807b2 100644
--- a/arch/um/os-Linux/registers.c
+++ b/arch/um/os-Linux/registers.c
@@ -10,11 +10,12 @@
#include <sysdep/ptrace.h>
#include <sysdep/ptrace_user.h>
#include <registers.h>
+#include <stdlib.h>
/* This is set once at boot time and not changed thereafter */
static unsigned long exec_regs[MAX_REG_NR];
-static unsigned long exec_fp_regs[FP_SIZE];
+static unsigned long *exec_fp_regs;
int init_pid_registers(int pid)
{
@@ -24,7 +25,11 @@ int init_pid_registers(int pid)
if (err < 0)
return -errno;
- arch_init_registers(pid);
+ err = arch_init_registers(pid);
+ if (err < 0)
+ return err;
+
+ exec_fp_regs = malloc(host_fp_size);
get_fp_registers(pid, exec_fp_regs);
return 0;
}
@@ -34,5 +39,5 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
memcpy(regs, exec_regs, sizeof(exec_regs));
if (fp_regs)
- memcpy(fp_regs, exec_fp_regs, sizeof(exec_fp_regs));
+ memcpy(fp_regs, exec_fp_regs, host_fp_size);
}
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 9e71794839e8..9aac8def4d63 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -55,6 +55,7 @@ static int write_sigio_thread(void *unused)
int i, n, respond_fd;
char c;
+ os_set_pdeathsig();
os_fix_helper_signals();
fds = &current_poll;
while (1) {
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index b11ed66c8bb0..9ea7269ffb77 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -26,7 +26,7 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
[SIGFPE] = relay_signal,
[SIGILL] = relay_signal,
[SIGWINCH] = winch,
- [SIGBUS] = bus_handler,
+ [SIGBUS] = relay_signal,
[SIGSEGV] = segv_handler,
[SIGIO] = sigio_handler,
};
@@ -65,7 +65,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
#define SIGALRM_MASK (1 << SIGALRM_BIT)
int signals_enabled;
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
static int signals_blocked, signals_blocked_pending;
#endif
static unsigned int signals_pending;
@@ -75,7 +75,7 @@ static void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
{
int enabled = signals_enabled;
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
if ((signals_blocked ||
__atomic_load_n(&signals_blocked_pending, __ATOMIC_SEQ_CST)) &&
(sig == SIGIO)) {
@@ -190,43 +190,8 @@ static void hard_handler(int sig, siginfo_t *si, void *p)
{
ucontext_t *uc = p;
mcontext_t *mc = &uc->uc_mcontext;
- unsigned long pending = 1UL << sig;
- do {
- int nested, bail;
-
- /*
- * pending comes back with one bit set for each
- * interrupt that arrived while setting up the stack,
- * plus a bit for this interrupt, plus the zero bit is
- * set if this is a nested interrupt.
- * If bail is true, then we interrupted another
- * handler setting up the stack. In this case, we
- * have to return, and the upper handler will deal
- * with this interrupt.
- */
- bail = to_irq_stack(&pending);
- if (bail)
- return;
-
- nested = pending & 1;
- pending &= ~1;
-
- while ((sig = ffs(pending)) != 0){
- sig--;
- pending &= ~(1 << sig);
- (*handlers[sig])(sig, (struct siginfo *)si, mc);
- }
-
- /*
- * Again, pending comes back with a mask of signals
- * that arrived while tearing down the stack. If this
- * is non-zero, we just go back, set up the stack
- * again, and handle the new interrupts.
- */
- if (!nested)
- pending = from_irq_stack(nested);
- } while (pending);
+ (*handlers[sig])(sig, (struct siginfo *)si, mc);
}
void set_handler(int sig)
@@ -297,7 +262,7 @@ void unblock_signals(void)
return;
signals_enabled = 1;
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
deliver_time_travel_irqs();
#endif
@@ -389,7 +354,7 @@ int um_set_signals_trace(int enable)
return ret;
}
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
void mark_sigio_pending(void)
{
/*
@@ -487,11 +452,3 @@ void unblock_signals_hard(void)
unblocking = false;
}
#endif
-
-int os_is_signal_stack(void)
-{
- stack_t ss;
- sigaltstack(NULL, &ss);
-
- return ss.ss_flags & SS_ONSTACK;
-}
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 9a13ac23c606..d7f1814b0e5a 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -217,24 +217,3 @@ int unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len)
return 0;
}
-
-int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
- unsigned int prot)
-{
- struct stub_syscall *sc;
-
- /* Compress with previous syscall if that is possible */
- sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MPROTECT, addr);
- if (sc && sc->mem.prot == prot) {
- sc->mem.length += len;
- return 0;
- }
-
- sc = syscall_stub_alloc(mm_idp);
- sc->syscall = STUB_SYSCALL_MPROTECT;
- sc->mem.addr = addr;
- sc->mem.length = len;
- sc->mem.prot = prot;
-
- return 0;
-}
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index b6f656bcffb1..f683cfc9e51a 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -10,8 +10,11 @@
#include <sched.h>
#include <errno.h>
#include <string.h>
+#include <fcntl.h>
+#include <mem_user.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#include <sys/stat.h>
#include <asm/unistd.h>
#include <as-layout.h>
#include <init.h>
@@ -141,16 +144,10 @@ bad_wait:
extern unsigned long current_stub_stack(void);
-static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs)
+static void get_skas_faultinfo(int pid, struct faultinfo *fi)
{
int err;
- err = get_fp_registers(pid, aux_fp_regs);
- if (err < 0) {
- printk(UM_KERN_ERR "save_fp_registers returned %d\n",
- err);
- fatal_sigsegv();
- }
err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
if (err) {
printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
@@ -164,18 +161,11 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux
* the stub stack page. We just have to copy it.
*/
memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
-
- err = put_fp_registers(pid, aux_fp_regs);
- if (err < 0) {
- printk(UM_KERN_ERR "put_fp_registers returned %d\n",
- err);
- fatal_sigsegv();
- }
}
-static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
+static void handle_segv(int pid, struct uml_pt_regs *regs)
{
- get_skas_faultinfo(pid, &regs->faultinfo, aux_fp_regs);
+ get_skas_faultinfo(pid, &regs->faultinfo);
segv(regs->faultinfo, 0, 1, NULL);
}
@@ -189,69 +179,131 @@ static void handle_trap(int pid, struct uml_pt_regs *regs)
extern char __syscall_stub_start[];
-/**
- * userspace_tramp() - userspace trampoline
- * @stack: pointer to the new userspace stack page
- *
- * The userspace trampoline is used to setup a new userspace process in start_userspace() after it was clone()'ed.
- * This function will run on a temporary stack page.
- * It ptrace()'es itself, then
- * Two pages are mapped into the userspace address space:
- * - STUB_CODE (with EXEC), which contains the skas stub code
- * - STUB_DATA (with R/W), which contains a data page that is used to transfer certain data between the UML userspace process and the UML kernel.
- * Also for the userspace process a SIGSEGV handler is installed to catch pagefaults in the userspace process.
- * And last the process stops itself to give control to the UML kernel for this userspace process.
- *
- * Return: Always zero, otherwise the current userspace process is ended with non null exit() call
- */
+static int stub_exe_fd;
+
static int userspace_tramp(void *stack)
{
- struct sigaction sa;
- void *addr;
- int fd;
+ char *const argv[] = { "uml-userspace", NULL };
+ int pipe_fds[2];
unsigned long long offset;
- unsigned long segv_handler = STUB_CODE +
- (unsigned long) stub_segv_handler -
- (unsigned long) __syscall_stub_start;
-
- ptrace(PTRACE_TRACEME, 0, 0, 0);
-
- signal(SIGTERM, SIG_DFL);
- signal(SIGWINCH, SIG_IGN);
-
- fd = phys_mapping(uml_to_phys(__syscall_stub_start), &offset);
- addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
- PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
- if (addr == MAP_FAILED) {
- os_info("mapping mmap stub at 0x%lx failed, errno = %d\n",
- STUB_CODE, errno);
- exit(1);
+ struct stub_init_data init_data = {
+ .stub_start = STUB_START,
+ .segv_handler = STUB_CODE +
+ (unsigned long) stub_segv_handler -
+ (unsigned long) __syscall_stub_start,
+ };
+ struct iomem_region *iomem;
+ int ret;
+
+ init_data.stub_code_fd = phys_mapping(uml_to_phys(__syscall_stub_start),
+ &offset);
+ init_data.stub_code_offset = MMAP_OFFSET(offset);
+
+ init_data.stub_data_fd = phys_mapping(uml_to_phys(stack), &offset);
+ init_data.stub_data_offset = MMAP_OFFSET(offset);
+
+ /* Set CLOEXEC on all FDs and then unset on all memory related FDs */
+ close_range(0, ~0U, CLOSE_RANGE_CLOEXEC);
+
+ fcntl(init_data.stub_data_fd, F_SETFD, 0);
+ for (iomem = iomem_regions; iomem; iomem = iomem->next)
+ fcntl(iomem->fd, F_SETFD, 0);
+
+ /* Create a pipe for init_data (no CLOEXEC) and dup2 to STDIN */
+ if (pipe(pipe_fds))
+ exit(2);
+
+ if (dup2(pipe_fds[0], 0) < 0)
+ exit(3);
+ close(pipe_fds[0]);
+
+ /* Write init_data and close write side */
+ ret = write(pipe_fds[1], &init_data, sizeof(init_data));
+ close(pipe_fds[1]);
+
+ if (ret != sizeof(init_data))
+ exit(4);
+
+ execveat(stub_exe_fd, "", argv, NULL, AT_EMPTY_PATH);
+
+ exit(5);
+}
+
+extern char stub_exe_start[];
+extern char stub_exe_end[];
+
+extern char *tempdir;
+
+#define STUB_EXE_NAME_TEMPLATE "/uml-userspace-XXXXXX"
+
+#ifndef MFD_EXEC
+#define MFD_EXEC 0x0010U
+#endif
+
+static int __init init_stub_exe_fd(void)
+{
+ size_t written = 0;
+ char *tmpfile = NULL;
+
+ stub_exe_fd = memfd_create("uml-userspace",
+ MFD_EXEC | MFD_CLOEXEC | MFD_ALLOW_SEALING);
+
+ if (stub_exe_fd < 0) {
+ printk(UM_KERN_INFO "Could not create executable memfd, using temporary file!");
+
+ tmpfile = malloc(strlen(tempdir) +
+ strlen(STUB_EXE_NAME_TEMPLATE) + 1);
+ if (tmpfile == NULL)
+ panic("Failed to allocate memory for stub binary name");
+
+ strcpy(tmpfile, tempdir);
+ strcat(tmpfile, STUB_EXE_NAME_TEMPLATE);
+
+ stub_exe_fd = mkstemp(tmpfile);
+ if (stub_exe_fd < 0)
+ panic("Could not create temporary file for stub binary: %d",
+ -errno);
}
- fd = phys_mapping(uml_to_phys(stack), &offset);
- addr = mmap((void *) STUB_DATA,
- STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_SHARED, fd, offset);
- if (addr == MAP_FAILED) {
- os_info("mapping segfault stack at 0x%lx failed, errno = %d\n",
- STUB_DATA, errno);
- exit(1);
+ while (written < stub_exe_end - stub_exe_start) {
+ ssize_t res = write(stub_exe_fd, stub_exe_start + written,
+ stub_exe_end - stub_exe_start - written);
+ if (res < 0) {
+ if (errno == EINTR)
+ continue;
+
+ if (tmpfile)
+ unlink(tmpfile);
+ panic("Failed write stub binary: %d", -errno);
+ }
+
+ written += res;
}
- set_sigstack((void *) STUB_DATA, STUB_DATA_PAGES * UM_KERN_PAGE_SIZE);
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
- sa.sa_sigaction = (void *) segv_handler;
- sa.sa_restorer = NULL;
- if (sigaction(SIGSEGV, &sa, NULL) < 0) {
- os_info("%s - setting SIGSEGV handler failed - errno = %d\n",
- __func__, errno);
- exit(1);
+ if (!tmpfile) {
+ fcntl(stub_exe_fd, F_ADD_SEALS,
+ F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL);
+ } else {
+ if (fchmod(stub_exe_fd, 00500) < 0) {
+ unlink(tmpfile);
+ panic("Could not make stub binary executable: %d",
+ -errno);
+ }
+
+ close(stub_exe_fd);
+ stub_exe_fd = open(tmpfile, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+ if (stub_exe_fd < 0) {
+ unlink(tmpfile);
+ panic("Could not reopen stub binary: %d", -errno);
+ }
+
+ unlink(tmpfile);
+ free(tmpfile);
}
- kill(os_getpid(), SIGSTOP);
return 0;
}
+__initcall(init_stub_exe_fd);
int userspace_pid[NR_CPUS];
@@ -270,7 +322,7 @@ int start_userspace(unsigned long stub_stack)
{
void *stack;
unsigned long sp;
- int pid, status, n, flags, err;
+ int pid, status, n, err;
/* setup a temporary stack page */
stack = mmap(NULL, UM_KERN_PAGE_SIZE,
@@ -286,10 +338,10 @@ int start_userspace(unsigned long stub_stack)
/* set stack pointer to the end of the stack page, so it can grow downwards */
sp = (unsigned long)stack + UM_KERN_PAGE_SIZE;
- flags = CLONE_FILES | SIGCHLD;
-
/* clone into new userspace process */
- pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
+ pid = clone(userspace_tramp, (void *) sp,
+ CLONE_VFORK | CLONE_VM | SIGCHLD,
+ (void *)stub_stack);
if (pid < 0) {
err = -errno;
printk(UM_KERN_ERR "%s : clone failed, errno = %d\n",
@@ -336,7 +388,10 @@ int start_userspace(unsigned long stub_stack)
return err;
}
-void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
+int unscheduled_userspace_iterations;
+extern unsigned long tt_extra_sched_jiffies;
+
+void userspace(struct uml_pt_regs *regs)
{
int err, status, op, pid = userspace_pid[0];
siginfo_t si;
@@ -345,6 +400,29 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
interrupt_end();
while (1) {
+ /*
+ * When we are in time-travel mode, userspace can theoretically
+ * do a *lot* of work without being scheduled. The problem with
+ * this is that it will prevent kernel bookkeeping (primarily
+ * the RCU) from running and this can for example cause OOM
+ * situations.
+ *
+ * This code accounts a jiffie against the scheduling clock
+ * after the defined userspace iterations in the same thread.
+ * By doing so the situation is effectively prevented.
+ */
+ if (time_travel_mode == TT_MODE_INFCPU ||
+ time_travel_mode == TT_MODE_EXTERNAL) {
+#ifdef CONFIG_UML_MAX_USERSPACE_ITERATIONS
+ if (CONFIG_UML_MAX_USERSPACE_ITERATIONS &&
+ unscheduled_userspace_iterations++ >
+ CONFIG_UML_MAX_USERSPACE_ITERATIONS) {
+ tt_extra_sched_jiffies += 1;
+ unscheduled_userspace_iterations = 0;
+ }
+#endif
+ }
+
time_travel_print_bc_msg();
current_mm_sync();
@@ -435,11 +513,11 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
case SIGSEGV:
if (PTRACE_FULL_FAULTINFO) {
get_skas_faultinfo(pid,
- &regs->faultinfo, aux_fp_regs);
+ &regs->faultinfo);
(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
regs);
}
- else handle_segv(pid, regs, aux_fp_regs);
+ else handle_segv(pid, regs);
break;
case SIGTRAP + 0x80:
handle_trap(pid, regs);
@@ -487,6 +565,8 @@ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
void switch_threads(jmp_buf *me, jmp_buf *you)
{
+ unscheduled_userspace_iterations = 0;
+
if (UML_SETJMP(me) == 0)
UML_LONGJMP(you, 1);
}
@@ -570,6 +650,7 @@ static bool noreboot;
static int __init noreboot_cmd_param(char *str, int *add)
{
+ *add = 0;
noreboot = true;
return 0;
}
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index e09d65b05d1c..eb523ab1e218 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -358,6 +358,8 @@ char *get_umid(void)
static int __init set_uml_dir(char *name, int *add)
{
+ *add = 0;
+
if (*name == '\0') {
os_warn("uml_dir can't be an empty string\n");
return 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 1dca4ffbd572..4193e04d7e4a 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -52,8 +52,8 @@ void setup_machinename(char *machine_out)
struct utsname host;
uname(&host);
-#ifdef UML_CONFIG_UML_X86
-# ifndef UML_CONFIG_64BIT
+#if IS_ENABLED(CONFIG_UML_X86)
+# if !IS_ENABLED(CONFIG_64BIT)
if (!strcmp(host.machine, "x86_64")) {
strcpy(machine_out, "i686");
return;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 16354dfa6d96..9d7bd0ae48c4 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -83,6 +83,7 @@ config X86
select ARCH_HAS_DMA_OPS if GART_IOMMU || XEN
select ARCH_HAS_EARLY_DEBUG if KGDB
select ARCH_HAS_ELF_RANDOMIZE
+ select ARCH_HAS_EXECMEM_ROX if X86_64
select ARCH_HAS_FAST_MULTIPLIER
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
@@ -93,6 +94,7 @@ config X86
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_PREEMPT_LAZY
select ARCH_HAS_PTE_DEVMAP if X86_64
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_HW_PTE_YOUNG
@@ -126,6 +128,8 @@ config X86
select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_LTO_CLANG_THIN
select ARCH_SUPPORTS_RT
+ select ARCH_SUPPORTS_AUTOFDO_CLANG
+ select ARCH_SUPPORTS_PROPELLER_CLANG if X86_64
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if X86_CMPXCHG64
select ARCH_USE_MEMTEST
@@ -145,7 +149,6 @@ config X86
select ARCH_HAS_PARANOID_L1D_FLUSH
select BUILDTIME_TABLE_SORT
select CLKEVT_I8253
- select CLOCKSOURCE_VALIDATE_LAST_CYCLE
select CLOCKSOURCE_WATCHDOG
# Word-size accesses may read uninitialized data past the trailing \0
# in strings and cause false KMSAN reports.
@@ -1954,6 +1957,7 @@ config X86_USER_SHADOW_STACK
depends on AS_WRUSS
depends on X86_64
select ARCH_USES_HIGH_VMA_FLAGS
+ select ARCH_HAS_USER_SHADOW_STACK
select X86_CET
help
Shadow stack protection is a hardware feature that detects function
@@ -2084,6 +2088,9 @@ config ARCH_SUPPORTS_KEXEC_JUMP
config ARCH_SUPPORTS_CRASH_DUMP
def_bool X86_64 || (X86_32 && HIGHMEM)
+config ARCH_DEFAULT_CRASH_DUMP
+ def_bool y
+
config ARCH_SUPPORTS_CRASH_HOTPLUG
def_bool y
@@ -2424,6 +2431,14 @@ config CFI_AUTO_DEFAULT
source "kernel/livepatch/Kconfig"
+config X86_BUS_LOCK_DETECT
+ bool "Split Lock Detect and Bus Lock Detect support"
+ depends on CPU_SUP_INTEL || CPU_SUP_AMD
+ default y
+ help
+ Enable Split Lock Detect and Bus Lock Detect functionalities.
+ See <file:Documentation/arch/x86/buslock.rst> for more information.
+
endmenu
config CC_HAS_NAMED_AS
@@ -2552,15 +2567,14 @@ config MITIGATION_CALL_DEPTH_TRACKING
default y
help
Compile the kernel with call depth tracking to mitigate the Intel
- SKL Return-Speculation-Buffer (RSB) underflow issue. The
- mitigation is off by default and needs to be enabled on the
- kernel command line via the retbleed=stuff option. For
- non-affected systems the overhead of this option is marginal as
- the call depth tracking is using run-time generated call thunks
- in a compiler generated padding area and call patching. This
- increases text size by ~5%. For non affected systems this space
- is unused. On affected SKL systems this results in a significant
- performance gain over the IBRS mitigation.
+ SKL Return-Stack-Buffer (RSB) underflow issue. The mitigation is off
+ by default and needs to be enabled on the kernel command line via the
+ retbleed=stuff option. For non-affected systems the overhead of this
+ option is marginal as the call depth tracking is using run-time
+ generated call thunks in a compiler generated padding area and call
+ patching. This increases text size by ~5%. For non affected systems
+ this space is unused. On affected SKL systems this results in a
+ significant performance gain over the IBRS mitigation.
config CALL_THUNKS_DEBUG
bool "Enable call thunks and call depth tracking debugging"
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index cd75e78a06c1..5b773b34768d 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -142,9 +142,10 @@ ifeq ($(CONFIG_X86_32),y)
ifeq ($(CONFIG_STACKPROTECTOR),y)
ifeq ($(CONFIG_SMP),y)
- KBUILD_CFLAGS += -mstack-protector-guard-reg=fs -mstack-protector-guard-symbol=__stack_chk_guard
+ KBUILD_CFLAGS += -mstack-protector-guard-reg=fs \
+ -mstack-protector-guard-symbol=__ref_stack_chk_guard
else
- KBUILD_CFLAGS += -mstack-protector-guard=global
+ KBUILD_CFLAGS += -mstack-protector-guard=global
endif
endif
else
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 148ba5c5106e..0f24f7ebec9b 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -305,7 +305,6 @@ void initregs(struct biosregs *regs);
int strcmp(const char *str1, const char *str2);
int strncmp(const char *cs, const char *ct, size_t count);
size_t strnlen(const char *s, size_t maxlen);
-unsigned int atou(const char *s);
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);
size_t strlen(const char *s);
char *strchr(const char *s, int c);
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 04a35b2c26e9..0d37420cad02 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -385,6 +385,19 @@ static void parse_mem_encrypt(struct setup_header *hdr)
hdr->xloadflags |= XLF_MEM_ENCRYPTION;
}
+static void early_sev_detect(void)
+{
+ /*
+ * Accessing video memory causes guest termination because
+ * the boot stage2 #VC handler of SEV-ES/SNP guests does not
+ * support MMIO handling and kexec -c adds screen_info to the
+ * boot parameters passed to the kexec kernel, which causes
+ * console output to be dumped to both video and serial.
+ */
+ if (sev_status & MSR_AMD64_SEV_ES_ENABLED)
+ lines = cols = 0;
+}
+
/*
* The compressed kernel image (ZO), has been moved so that its position
* is against the end of the buffer used to hold the uncompressed kernel
@@ -440,6 +453,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
*/
early_tdx_detect();
+ early_sev_detect();
+
console_init();
/*
diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c
index c23f3b9c84fe..84f7a883ce1e 100644
--- a/arch/x86/boot/string.c
+++ b/arch/x86/boot/string.c
@@ -88,14 +88,6 @@ size_t strnlen(const char *s, size_t maxlen)
return (es - s);
}
-unsigned int atou(const char *s)
-{
- unsigned int i = 0;
- while (isdigit(*s))
- i = i * 10 + (*s++ - '0');
- return i;
-}
-
/* Works only for digits and letters, but small and fast */
#define TOLOWER(x) ((x) | 0x20)
diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h
index e5d2c6b8c2f1..a5b05ebc037d 100644
--- a/arch/x86/boot/string.h
+++ b/arch/x86/boot/string.h
@@ -24,7 +24,6 @@ extern size_t strlen(const char *s);
extern char *strstr(const char *s1, const char *s2);
extern char *strchr(const char *s, int c);
extern size_t strnlen(const char *s, size_t maxlen);
-extern unsigned int atou(const char *s);
extern unsigned long long simple_strtoull(const char *cp, char **endp,
unsigned int base);
long simple_strtol(const char *cp, char **endp, unsigned int base);
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index de1df0cb45da..c5b0148b8c0a 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -92,6 +92,9 @@ static struct ghcb *boot_ghcb __section(".data");
/* Bitmap of SEV features supported by the hypervisor */
static u64 sev_hv_features __ro_after_init;
+/* Secrets page physical address from the CC blob */
+static u64 secrets_pa __ro_after_init;
+
/* #VC handler runtime per-CPU data */
struct sev_es_runtime_data {
struct ghcb ghcb_page;
@@ -141,33 +144,6 @@ static DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa);
static DEFINE_PER_CPU(struct svsm_ca *, svsm_caa);
static DEFINE_PER_CPU(u64, svsm_caa_pa);
-struct sev_config {
- __u64 debug : 1,
-
- /*
- * Indicates when the per-CPU GHCB has been created and registered
- * and thus can be used by the BSP instead of the early boot GHCB.
- *
- * For APs, the per-CPU GHCB is created before they are started
- * and registered upon startup, so this flag can be used globally
- * for the BSP and APs.
- */
- ghcbs_initialized : 1,
-
- /*
- * Indicates when the per-CPU SVSM CA is to be used instead of the
- * boot SVSM CA.
- *
- * For APs, the per-CPU SVSM CA is created as part of the AP
- * bringup, so this flag can be used globally for the BSP and APs.
- */
- use_cas : 1,
-
- __reserved : 61;
-};
-
-static struct sev_config sev_cfg __read_mostly;
-
static __always_inline bool on_vc_stack(struct pt_regs *regs)
{
unsigned long sp = regs->sp;
@@ -722,45 +698,13 @@ void noinstr __sev_es_nmi_complete(void)
__sev_put_ghcb(&state);
}
-static u64 __init get_secrets_page(void)
-{
- u64 pa_data = boot_params.cc_blob_address;
- struct cc_blob_sev_info info;
- void *map;
-
- /*
- * The CC blob contains the address of the secrets page, check if the
- * blob is present.
- */
- if (!pa_data)
- return 0;
-
- map = early_memremap(pa_data, sizeof(info));
- if (!map) {
- pr_err("Unable to locate SNP secrets page: failed to map the Confidential Computing blob.\n");
- return 0;
- }
- memcpy(&info, map, sizeof(info));
- early_memunmap(map, sizeof(info));
-
- /* smoke-test the secrets page passed */
- if (!info.secrets_phys || info.secrets_len != PAGE_SIZE)
- return 0;
-
- return info.secrets_phys;
-}
-
static u64 __init get_snp_jump_table_addr(void)
{
struct snp_secrets_page *secrets;
void __iomem *mem;
- u64 pa, addr;
+ u64 addr;
- pa = get_secrets_page();
- if (!pa)
- return 0;
-
- mem = ioremap_encrypted(pa, PAGE_SIZE);
+ mem = ioremap_encrypted(secrets_pa, PAGE_SIZE);
if (!mem) {
pr_err("Unable to locate AP jump table address: failed to map the SNP secrets page.\n");
return 0;
@@ -1010,6 +954,137 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end)
set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE);
}
+static void set_pte_enc(pte_t *kpte, int level, void *va)
+{
+ struct pte_enc_desc d = {
+ .kpte = kpte,
+ .pte_level = level,
+ .va = va,
+ .encrypt = true
+ };
+
+ prepare_pte_enc(&d);
+ set_pte_enc_mask(kpte, d.pfn, d.new_pgprot);
+}
+
+static void unshare_all_memory(void)
+{
+ unsigned long addr, end, size, ghcb;
+ struct sev_es_runtime_data *data;
+ unsigned int npages, level;
+ bool skipped_addr;
+ pte_t *pte;
+ int cpu;
+
+ /* Unshare the direct mapping. */
+ addr = PAGE_OFFSET;
+ end = PAGE_OFFSET + get_max_mapped();
+
+ while (addr < end) {
+ pte = lookup_address(addr, &level);
+ size = page_level_size(level);
+ npages = size / PAGE_SIZE;
+ skipped_addr = false;
+
+ if (!pte || !pte_decrypted(*pte) || pte_none(*pte)) {
+ addr += size;
+ continue;
+ }
+
+ /*
+ * Ensure that all the per-CPU GHCBs are made private at the
+ * end of the unsharing loop so that the switch to the slower
+ * MSR protocol happens last.
+ */
+ for_each_possible_cpu(cpu) {
+ data = per_cpu(runtime_data, cpu);
+ ghcb = (unsigned long)&data->ghcb_page;
+
+ if (addr <= ghcb && ghcb <= addr + size) {
+ skipped_addr = true;
+ break;
+ }
+ }
+
+ if (!skipped_addr) {
+ set_pte_enc(pte, level, (void *)addr);
+ snp_set_memory_private(addr, npages);
+ }
+ addr += size;
+ }
+
+ /* Unshare all bss decrypted memory. */
+ addr = (unsigned long)__start_bss_decrypted;
+ end = (unsigned long)__start_bss_decrypted_unused;
+ npages = (end - addr) >> PAGE_SHIFT;
+
+ for (; addr < end; addr += PAGE_SIZE) {
+ pte = lookup_address(addr, &level);
+ if (!pte || !pte_decrypted(*pte) || pte_none(*pte))
+ continue;
+
+ set_pte_enc(pte, level, (void *)addr);
+ }
+ addr = (unsigned long)__start_bss_decrypted;
+ snp_set_memory_private(addr, npages);
+
+ __flush_tlb_all();
+}
+
+/* Stop new private<->shared conversions */
+void snp_kexec_begin(void)
+{
+ if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+ return;
+
+ if (!IS_ENABLED(CONFIG_KEXEC_CORE))
+ return;
+
+ /*
+ * Crash kernel ends up here with interrupts disabled: can't wait for
+ * conversions to finish.
+ *
+ * If race happened, just report and proceed.
+ */
+ if (!set_memory_enc_stop_conversion())
+ pr_warn("Failed to stop shared<->private conversions\n");
+}
+
+void snp_kexec_finish(void)
+{
+ struct sev_es_runtime_data *data;
+ unsigned int level, cpu;
+ unsigned long size;
+ struct ghcb *ghcb;
+ pte_t *pte;
+
+ if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+ return;
+
+ if (!IS_ENABLED(CONFIG_KEXEC_CORE))
+ return;
+
+ unshare_all_memory();
+
+ /*
+ * Switch to using the MSR protocol to change per-CPU GHCBs to
+ * private. All the per-CPU GHCBs have been switched back to private,
+ * so can't do any more GHCB calls to the hypervisor beyond this point
+ * until the kexec'ed kernel starts running.
+ */
+ boot_ghcb = NULL;
+ sev_cfg.ghcbs_initialized = false;
+
+ for_each_possible_cpu(cpu) {
+ data = per_cpu(runtime_data, cpu);
+ ghcb = &data->ghcb_page;
+ pte = lookup_address((unsigned long)ghcb, &level);
+ size = page_level_size(level);
+ set_pte_enc(pte, level, (void *)ghcb);
+ snp_set_memory_private((unsigned long)ghcb, (size / PAGE_SIZE));
+ }
+}
+
static int snp_set_vmsa(void *va, void *caa, int apic_id, bool make_vmsa)
{
int ret;
@@ -1331,35 +1406,39 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
return 0;
}
+/* Writes to the SVSM CAA MSR are ignored */
+static enum es_result __vc_handle_msr_caa(struct pt_regs *regs, bool write)
+{
+ if (write)
+ return ES_OK;
+
+ regs->ax = lower_32_bits(this_cpu_read(svsm_caa_pa));
+ regs->dx = upper_32_bits(this_cpu_read(svsm_caa_pa));
+
+ return ES_OK;
+}
+
static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
{
struct pt_regs *regs = ctxt->regs;
enum es_result ret;
- u64 exit_info_1;
+ bool write;
/* Is it a WRMSR? */
- exit_info_1 = (ctxt->insn.opcode.bytes[1] == 0x30) ? 1 : 0;
+ write = ctxt->insn.opcode.bytes[1] == 0x30;
- if (regs->cx == MSR_SVSM_CAA) {
- /* Writes to the SVSM CAA msr are ignored */
- if (exit_info_1)
- return ES_OK;
-
- regs->ax = lower_32_bits(this_cpu_read(svsm_caa_pa));
- regs->dx = upper_32_bits(this_cpu_read(svsm_caa_pa));
-
- return ES_OK;
- }
+ if (regs->cx == MSR_SVSM_CAA)
+ return __vc_handle_msr_caa(regs, write);
ghcb_set_rcx(ghcb, regs->cx);
- if (exit_info_1) {
+ if (write) {
ghcb_set_rax(ghcb, regs->ax);
ghcb_set_rdx(ghcb, regs->dx);
}
- ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_MSR, exit_info_1, 0);
+ ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_MSR, write, 0);
- if ((ret == ES_OK) && (!exit_info_1)) {
+ if ((ret == ES_OK) && !write) {
regs->ax = ghcb->save.rax;
regs->dx = ghcb->save.rdx;
}
@@ -2300,6 +2379,11 @@ bool __head snp_init(struct boot_params *bp)
if (!cc_info)
return false;
+ if (cc_info->secrets_phys && cc_info->secrets_len == PAGE_SIZE)
+ secrets_pa = cc_info->secrets_phys;
+ else
+ return false;
+
setup_cpuid_table(cc_info);
svsm_setup(cc_info);
@@ -2374,23 +2458,6 @@ static int __init report_snp_info(void)
}
arch_initcall(report_snp_info);
-static int __init init_sev_config(char *str)
-{
- char *s;
-
- while ((s = strsep(&str, ","))) {
- if (!strcmp(s, "debug")) {
- sev_cfg.debug = true;
- continue;
- }
-
- pr_info("SEV command-line option '%s' was not recognized\n", s);
- }
-
- return 1;
-}
-__setup("sev=", init_sev_config);
-
static void update_attest_input(struct svsm_call *call, struct svsm_attest_call *input)
{
/* If (new) lengths have been returned, propagate them up */
@@ -2441,7 +2508,8 @@ int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call,
}
EXPORT_SYMBOL_GPL(snp_issue_svsm_attest_req);
-int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
+int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input,
+ struct snp_guest_request_ioctl *rio)
{
struct ghcb_state state;
struct es_em_ctxt ctxt;
@@ -2465,12 +2533,12 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct sn
vc_ghcb_invalidate(ghcb);
- if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
+ if (req->exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
ghcb_set_rax(ghcb, input->data_gpa);
ghcb_set_rbx(ghcb, input->data_npages);
}
- ret = sev_es_ghcb_hv_call(ghcb, &ctxt, exit_code, input->req_gpa, input->resp_gpa);
+ ret = sev_es_ghcb_hv_call(ghcb, &ctxt, req->exit_code, input->req_gpa, input->resp_gpa);
if (ret)
goto e_put;
@@ -2485,7 +2553,7 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct sn
case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN):
/* Number of expected pages are returned in RBX */
- if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
+ if (req->exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
input->data_npages = ghcb_get_rbx(ghcb);
ret = -ENOSPC;
break;
@@ -2513,16 +2581,11 @@ static struct platform_device sev_guest_device = {
static int __init snp_init_platform_device(void)
{
struct sev_guest_platform_data data;
- u64 gpa;
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
return -ENODEV;
- gpa = get_secrets_page();
- if (!gpa)
- return -ENODEV;
-
- data.secrets_gpa = gpa;
+ data.secrets_gpa = secrets_pa;
if (platform_device_add_data(&sev_guest_device, &data, sizeof(data)))
return -ENODEV;
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 327c45c5013f..0d9b090b4880 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -78,6 +78,32 @@ static inline void tdcall(u64 fn, struct tdx_module_args *args)
panic("TDCALL %lld failed (Buggy TDX module!)\n", fn);
}
+/* Read TD-scoped metadata */
+static inline u64 tdg_vm_rd(u64 field, u64 *value)
+{
+ struct tdx_module_args args = {
+ .rdx = field,
+ };
+ u64 ret;
+
+ ret = __tdcall_ret(TDG_VM_RD, &args);
+ *value = args.r8;
+
+ return ret;
+}
+
+/* Write TD-scoped metadata */
+static inline u64 tdg_vm_wr(u64 field, u64 value, u64 mask)
+{
+ struct tdx_module_args args = {
+ .rdx = field,
+ .r8 = value,
+ .r9 = mask,
+ };
+
+ return __tdcall(TDG_VM_WR, &args);
+}
+
/**
* tdx_mcall_get_report0() - Wrapper to get TDREPORT0 (a.k.a. TDREPORT
* subtype 0) using TDG.MR.REPORT TDCALL.
@@ -168,7 +194,87 @@ static void __noreturn tdx_panic(const char *msg)
__tdx_hypercall(&args);
}
-static void tdx_parse_tdinfo(u64 *cc_mask)
+/*
+ * The kernel cannot handle #VEs when accessing normal kernel memory. Ensure
+ * that no #VE will be delivered for accesses to TD-private memory.
+ *
+ * TDX 1.0 does not allow the guest to disable SEPT #VE on its own. The VMM
+ * controls if the guest will receive such #VE with TD attribute
+ * ATTR_SEPT_VE_DISABLE.
+ *
+ * Newer TDX modules allow the guest to control if it wants to receive SEPT
+ * violation #VEs.
+ *
+ * Check if the feature is available and disable SEPT #VE if possible.
+ *
+ * If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISABLE
+ * attribute is no longer reliable. It reflects the initial state of the
+ * control for the TD, but it will not be updated if someone (e.g. bootloader)
+ * changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to
+ * determine if SEPT #VEs are enabled or disabled.
+ */
+static void disable_sept_ve(u64 td_attr)
+{
+ const char *msg = "TD misconfiguration: SEPT #VE has to be disabled";
+ bool debug = td_attr & ATTR_DEBUG;
+ u64 config, controls;
+
+ /* Is this TD allowed to disable SEPT #VE */
+ tdg_vm_rd(TDCS_CONFIG_FLAGS, &config);
+ if (!(config & TDCS_CONFIG_FLEXIBLE_PENDING_VE)) {
+ /* No SEPT #VE controls for the guest: check the attribute */
+ if (td_attr & ATTR_SEPT_VE_DISABLE)
+ return;
+
+ /* Relax SEPT_VE_DISABLE check for debug TD for backtraces */
+ if (debug)
+ pr_warn("%s\n", msg);
+ else
+ tdx_panic(msg);
+ return;
+ }
+
+ /* Check if SEPT #VE has been disabled before us */
+ tdg_vm_rd(TDCS_TD_CTLS, &controls);
+ if (controls & TD_CTLS_PENDING_VE_DISABLE)
+ return;
+
+ /* Keep #VEs enabled for splats in debugging environments */
+ if (debug)
+ return;
+
+ /* Disable SEPT #VEs */
+ tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_PENDING_VE_DISABLE,
+ TD_CTLS_PENDING_VE_DISABLE);
+}
+
+/*
+ * TDX 1.0 generates a #VE when accessing topology-related CPUID leafs (0xB and
+ * 0x1F) and the X2APIC_APICID MSR. The kernel returns all zeros on CPUID #VEs.
+ * In practice, this means that the kernel can only boot with a plain topology.
+ * Any complications will cause problems.
+ *
+ * The ENUM_TOPOLOGY feature allows the VMM to provide topology information.
+ * Enabling the feature eliminates topology-related #VEs: the TDX module
+ * virtualizes accesses to the CPUID leafs and the MSR.
+ *
+ * Enable ENUM_TOPOLOGY if it is available.
+ */
+static void enable_cpu_topology_enumeration(void)
+{
+ u64 configured;
+
+ /* Has the VMM provided a valid topology configuration? */
+ tdg_vm_rd(TDCS_TOPOLOGY_ENUM_CONFIGURED, &configured);
+ if (!configured) {
+ pr_err("VMM did not configure X2APIC_IDs properly\n");
+ return;
+ }
+
+ tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_ENUM_TOPOLOGY, TD_CTLS_ENUM_TOPOLOGY);
+}
+
+static void tdx_setup(u64 *cc_mask)
{
struct tdx_module_args args = {};
unsigned int gpa_width;
@@ -193,21 +299,13 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
gpa_width = args.rcx & GENMASK(5, 0);
*cc_mask = BIT_ULL(gpa_width - 1);
- /*
- * The kernel can not handle #VE's when accessing normal kernel
- * memory. Ensure that no #VE will be delivered for accesses to
- * TD-private memory. Only VMM-shared memory (MMIO) will #VE.
- */
td_attr = args.rdx;
- if (!(td_attr & ATTR_SEPT_VE_DISABLE)) {
- const char *msg = "TD misconfiguration: SEPT_VE_DISABLE attribute must be set.";
- /* Relax SEPT_VE_DISABLE check for debug TD. */
- if (td_attr & ATTR_DEBUG)
- pr_warn("%s\n", msg);
- else
- tdx_panic(msg);
- }
+ /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */
+ tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL);
+
+ disable_sept_ve(td_attr);
+ enable_cpu_topology_enumeration();
}
/*
@@ -929,10 +1027,6 @@ static void tdx_kexec_finish(void)
void __init tdx_early_init(void)
{
- struct tdx_module_args args = {
- .rdx = TDCS_NOTIFY_ENABLES,
- .r9 = -1ULL,
- };
u64 cc_mask;
u32 eax, sig[3];
@@ -947,11 +1041,11 @@ void __init tdx_early_init(void)
setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
cc_vendor = CC_VENDOR_INTEL;
- tdx_parse_tdinfo(&cc_mask);
- cc_set_mask(cc_mask);
- /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */
- tdcall(TDG_VM_WR, &args);
+ /* Configure the TD */
+ tdx_setup(&cc_mask);
+
+ cc_set_mask(cc_mask);
/*
* All bits above GPA width are reserved and kernel treats shared bit
diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig
index 7b1bebed879d..3d2e38ba5240 100644
--- a/arch/x86/crypto/Kconfig
+++ b/arch/x86/crypto/Kconfig
@@ -363,7 +363,7 @@ config CRYPTO_CHACHA20_X86_64
- AVX-512VL (Advanced Vector Extensions-512VL)
config CRYPTO_AEGIS128_AESNI_SSE2
- tristate "AEAD ciphers: AEGIS-128 (AES-NI/SSE2)"
+ tristate "AEAD ciphers: AEGIS-128 (AES-NI/SSE4.1)"
depends on X86 && 64BIT
select CRYPTO_AEAD
select CRYPTO_SIMD
@@ -372,7 +372,7 @@ config CRYPTO_AEGIS128_AESNI_SSE2
Architecture: x86_64 using:
- AES-NI (AES New Instructions)
- - SSE2 (Streaming SIMD Extensions 2)
+ - SSE4.1 (Streaming SIMD Extensions 4.1)
config CRYPTO_NHPOLY1305_SSE2
tristate "Hash functions: NHPoly1305 (SSE2)"
diff --git a/arch/x86/crypto/aegis128-aesni-asm.S b/arch/x86/crypto/aegis128-aesni-asm.S
index ad7f4c891625..7294dc0ee7ba 100644
--- a/arch/x86/crypto/aegis128-aesni-asm.S
+++ b/arch/x86/crypto/aegis128-aesni-asm.S
@@ -1,14 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * AES-NI + SSE2 implementation of AEGIS-128
+ * AES-NI + SSE4.1 implementation of AEGIS-128
*
* Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com>
* Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
+ * Copyright 2024 Google LLC
*/
#include <linux/linkage.h>
-#include <linux/cfi_types.h>
-#include <asm/frame.h>
#define STATE0 %xmm0
#define STATE1 %xmm1
@@ -20,11 +19,6 @@
#define T0 %xmm6
#define T1 %xmm7
-#define STATEP %rdi
-#define LEN %rsi
-#define SRC %rdx
-#define DST %rcx
-
.section .rodata.cst16.aegis128_const, "aM", @progbits, 32
.align 16
.Laegis128_const_0:
@@ -34,11 +28,11 @@
.byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1
.byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd
-.section .rodata.cst16.aegis128_counter, "aM", @progbits, 16
-.align 16
-.Laegis128_counter:
- .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
- .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+.section .rodata.cst32.zeropad_mask, "aM", @progbits, 32
+.align 32
+.Lzeropad_mask:
+ .octa 0xffffffffffffffffffffffffffffffff
+ .octa 0
.text
@@ -61,140 +55,102 @@
.endm
/*
- * __load_partial: internal ABI
- * input:
- * LEN - bytes
- * SRC - src
- * output:
- * MSG - message block
- * changed:
- * T0
- * %r8
- * %r9
+ * Load 1 <= LEN (%ecx) <= 15 bytes from the pointer SRC into the xmm register
+ * MSG and zeroize any remaining bytes. Clobbers %rax, %rcx, and %r8.
*/
-SYM_FUNC_START_LOCAL(__load_partial)
- xor %r9d, %r9d
- pxor MSG, MSG
-
- mov LEN, %r8
- and $0x1, %r8
- jz .Lld_partial_1
-
- mov LEN, %r8
- and $0x1E, %r8
- add SRC, %r8
- mov (%r8), %r9b
-
-.Lld_partial_1:
- mov LEN, %r8
- and $0x2, %r8
- jz .Lld_partial_2
-
- mov LEN, %r8
- and $0x1C, %r8
- add SRC, %r8
- shl $0x10, %r9
- mov (%r8), %r9w
-
-.Lld_partial_2:
- mov LEN, %r8
- and $0x4, %r8
- jz .Lld_partial_4
-
- mov LEN, %r8
- and $0x18, %r8
- add SRC, %r8
- shl $32, %r9
- mov (%r8), %r8d
- xor %r8, %r9
-
-.Lld_partial_4:
- movq %r9, MSG
-
- mov LEN, %r8
- and $0x8, %r8
- jz .Lld_partial_8
-
- mov LEN, %r8
- and $0x10, %r8
- add SRC, %r8
- pslldq $8, MSG
- movq (%r8), T0
- pxor T0, MSG
-
-.Lld_partial_8:
- RET
-SYM_FUNC_END(__load_partial)
+.macro load_partial
+ sub $8, %ecx /* LEN - 8 */
+ jle .Lle8\@
+
+ /* Load 9 <= LEN <= 15 bytes: */
+ movq (SRC), MSG /* Load first 8 bytes */
+ mov (SRC, %rcx), %rax /* Load last 8 bytes */
+ neg %ecx
+ shl $3, %ecx
+ shr %cl, %rax /* Discard overlapping bytes */
+ pinsrq $1, %rax, MSG
+ jmp .Ldone\@
+
+.Lle8\@:
+ add $4, %ecx /* LEN - 4 */
+ jl .Llt4\@
+
+ /* Load 4 <= LEN <= 8 bytes: */
+ mov (SRC), %eax /* Load first 4 bytes */
+ mov (SRC, %rcx), %r8d /* Load last 4 bytes */
+ jmp .Lcombine\@
+
+.Llt4\@:
+ /* Load 1 <= LEN <= 3 bytes: */
+ add $2, %ecx /* LEN - 2 */
+ movzbl (SRC), %eax /* Load first byte */
+ jl .Lmovq\@
+ movzwl (SRC, %rcx), %r8d /* Load last 2 bytes */
+.Lcombine\@:
+ shl $3, %ecx
+ shl %cl, %r8
+ or %r8, %rax /* Combine the two parts */
+.Lmovq\@:
+ movq %rax, MSG
+.Ldone\@:
+.endm
/*
- * __store_partial: internal ABI
- * input:
- * LEN - bytes
- * DST - dst
- * output:
- * T0 - message block
- * changed:
- * %r8
- * %r9
- * %r10
+ * Store 1 <= LEN (%ecx) <= 15 bytes from the xmm register \msg to the pointer
+ * DST. Clobbers %rax, %rcx, and %r8.
*/
-SYM_FUNC_START_LOCAL(__store_partial)
- mov LEN, %r8
- mov DST, %r9
-
- movq T0, %r10
-
- cmp $8, %r8
- jl .Lst_partial_8
-
- mov %r10, (%r9)
- psrldq $8, T0
- movq T0, %r10
-
- sub $8, %r8
- add $8, %r9
-
-.Lst_partial_8:
- cmp $4, %r8
- jl .Lst_partial_4
-
- mov %r10d, (%r9)
- shr $32, %r10
-
- sub $4, %r8
- add $4, %r9
-
-.Lst_partial_4:
- cmp $2, %r8
- jl .Lst_partial_2
-
- mov %r10w, (%r9)
- shr $0x10, %r10
-
- sub $2, %r8
- add $2, %r9
-
-.Lst_partial_2:
- cmp $1, %r8
- jl .Lst_partial_1
-
- mov %r10b, (%r9)
-
-.Lst_partial_1:
- RET
-SYM_FUNC_END(__store_partial)
+.macro store_partial msg
+ sub $8, %ecx /* LEN - 8 */
+ jl .Llt8\@
+
+ /* Store 8 <= LEN <= 15 bytes: */
+ pextrq $1, \msg, %rax
+ mov %ecx, %r8d
+ shl $3, %ecx
+ ror %cl, %rax
+ mov %rax, (DST, %r8) /* Store last LEN - 8 bytes */
+ movq \msg, (DST) /* Store first 8 bytes */
+ jmp .Ldone\@
+
+.Llt8\@:
+ add $4, %ecx /* LEN - 4 */
+ jl .Llt4\@
+
+ /* Store 4 <= LEN <= 7 bytes: */
+ pextrd $1, \msg, %eax
+ mov %ecx, %r8d
+ shl $3, %ecx
+ ror %cl, %eax
+ mov %eax, (DST, %r8) /* Store last LEN - 4 bytes */
+ movd \msg, (DST) /* Store first 4 bytes */
+ jmp .Ldone\@
+
+.Llt4\@:
+ /* Store 1 <= LEN <= 3 bytes: */
+ pextrb $0, \msg, 0(DST)
+ cmp $-2, %ecx /* LEN - 4 == -2, i.e. LEN == 2? */
+ jl .Ldone\@
+ pextrb $1, \msg, 1(DST)
+ je .Ldone\@
+ pextrb $2, \msg, 2(DST)
+.Ldone\@:
+.endm
/*
- * void crypto_aegis128_aesni_init(void *state, const void *key, const void *iv);
+ * void aegis128_aesni_init(struct aegis_state *state,
+ * const struct aegis_block *key,
+ * const u8 iv[AEGIS128_NONCE_SIZE]);
*/
-SYM_FUNC_START(crypto_aegis128_aesni_init)
- FRAME_BEGIN
+SYM_FUNC_START(aegis128_aesni_init)
+ .set STATEP, %rdi
+ .set KEYP, %rsi
+ .set IVP, %rdx
/* load IV: */
- movdqu (%rdx), T1
+ movdqu (IVP), T1
/* load key: */
- movdqa (%rsi), KEY
+ movdqa (KEYP), KEY
pxor KEY, T1
movdqa T1, STATE0
movdqa KEY, STATE3
@@ -224,20 +180,22 @@ SYM_FUNC_START(crypto_aegis128_aesni_init)
movdqu STATE2, 0x20(STATEP)
movdqu STATE3, 0x30(STATEP)
movdqu STATE4, 0x40(STATEP)
-
- FRAME_END
RET
-SYM_FUNC_END(crypto_aegis128_aesni_init)
+SYM_FUNC_END(aegis128_aesni_init)
/*
- * void crypto_aegis128_aesni_ad(void *state, unsigned int length,
- * const void *data);
+ * void aegis128_aesni_ad(struct aegis_state *state, const u8 *data,
+ * unsigned int len);
+ *
+ * len must be a multiple of 16.
*/
-SYM_FUNC_START(crypto_aegis128_aesni_ad)
- FRAME_BEGIN
+SYM_FUNC_START(aegis128_aesni_ad)
+ .set STATEP, %rdi
+ .set SRC, %rsi
+ .set LEN, %edx
- cmp $0x10, LEN
- jb .Lad_out
+ test LEN, LEN
+ jz .Lad_out
/* load the state: */
movdqu 0x00(STATEP), STATE0
@@ -246,89 +204,40 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
movdqu 0x30(STATEP), STATE3
movdqu 0x40(STATEP), STATE4
- mov SRC, %r8
- and $0xF, %r8
- jnz .Lad_u_loop
-
-.align 8
-.Lad_a_loop:
- movdqa 0x00(SRC), MSG
- aegis128_update
- pxor MSG, STATE4
- sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_1
-
- movdqa 0x10(SRC), MSG
- aegis128_update
- pxor MSG, STATE3
- sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_2
-
- movdqa 0x20(SRC), MSG
- aegis128_update
- pxor MSG, STATE2
- sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_3
-
- movdqa 0x30(SRC), MSG
- aegis128_update
- pxor MSG, STATE1
- sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_4
-
- movdqa 0x40(SRC), MSG
- aegis128_update
- pxor MSG, STATE0
- sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_0
-
- add $0x50, SRC
- jmp .Lad_a_loop
-
.align 8
-.Lad_u_loop:
+.Lad_loop:
movdqu 0x00(SRC), MSG
aegis128_update
pxor MSG, STATE4
sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_1
+ jz .Lad_out_1
movdqu 0x10(SRC), MSG
aegis128_update
pxor MSG, STATE3
sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_2
+ jz .Lad_out_2
movdqu 0x20(SRC), MSG
aegis128_update
pxor MSG, STATE2
sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_3
+ jz .Lad_out_3
movdqu 0x30(SRC), MSG
aegis128_update
pxor MSG, STATE1
sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_4
+ jz .Lad_out_4
movdqu 0x40(SRC), MSG
aegis128_update
pxor MSG, STATE0
sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lad_out_0
+ jz .Lad_out_0
add $0x50, SRC
- jmp .Lad_u_loop
+ jmp .Lad_loop
/* store the state: */
.Lad_out_0:
@@ -337,7 +246,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
movdqu STATE2, 0x20(STATEP)
movdqu STATE3, 0x30(STATEP)
movdqu STATE4, 0x40(STATEP)
- FRAME_END
RET
.Lad_out_1:
@@ -346,7 +254,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
movdqu STATE1, 0x20(STATEP)
movdqu STATE2, 0x30(STATEP)
movdqu STATE3, 0x40(STATEP)
- FRAME_END
RET
.Lad_out_2:
@@ -355,7 +262,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
movdqu STATE0, 0x20(STATEP)
movdqu STATE1, 0x30(STATEP)
movdqu STATE2, 0x40(STATEP)
- FRAME_END
RET
.Lad_out_3:
@@ -364,7 +270,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
movdqu STATE4, 0x20(STATEP)
movdqu STATE0, 0x30(STATEP)
movdqu STATE1, 0x40(STATEP)
- FRAME_END
RET
.Lad_out_4:
@@ -373,41 +278,38 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad)
movdqu STATE3, 0x20(STATEP)
movdqu STATE4, 0x30(STATEP)
movdqu STATE0, 0x40(STATEP)
- FRAME_END
- RET
-
.Lad_out:
- FRAME_END
RET
-SYM_FUNC_END(crypto_aegis128_aesni_ad)
+SYM_FUNC_END(aegis128_aesni_ad)
-.macro encrypt_block a s0 s1 s2 s3 s4 i
- movdq\a (\i * 0x10)(SRC), MSG
+.macro encrypt_block s0 s1 s2 s3 s4 i
+ movdqu (\i * 0x10)(SRC), MSG
movdqa MSG, T0
pxor \s1, T0
pxor \s4, T0
movdqa \s2, T1
pand \s3, T1
pxor T1, T0
- movdq\a T0, (\i * 0x10)(DST)
+ movdqu T0, (\i * 0x10)(DST)
aegis128_update
pxor MSG, \s4
sub $0x10, LEN
- cmp $0x10, LEN
- jl .Lenc_out_\i
+ jz .Lenc_out_\i
.endm
/*
- * void crypto_aegis128_aesni_enc(void *state, unsigned int length,
- * const void *src, void *dst);
+ * void aegis128_aesni_enc(struct aegis_state *state, const u8 *src, u8 *dst,
+ * unsigned int len);
+ *
+ * len must be nonzero and a multiple of 16.
*/
-SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
- FRAME_BEGIN
-
- cmp $0x10, LEN
- jb .Lenc_out
+SYM_FUNC_START(aegis128_aesni_enc)
+ .set STATEP, %rdi
+ .set SRC, %rsi
+ .set DST, %rdx
+ .set LEN, %ecx
/* load the state: */
movdqu 0x00(STATEP), STATE0
@@ -416,34 +318,17 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
movdqu 0x30(STATEP), STATE3
movdqu 0x40(STATEP), STATE4
- mov SRC, %r8
- or DST, %r8
- and $0xF, %r8
- jnz .Lenc_u_loop
-
.align 8
-.Lenc_a_loop:
- encrypt_block a STATE0 STATE1 STATE2 STATE3 STATE4 0
- encrypt_block a STATE4 STATE0 STATE1 STATE2 STATE3 1
- encrypt_block a STATE3 STATE4 STATE0 STATE1 STATE2 2
- encrypt_block a STATE2 STATE3 STATE4 STATE0 STATE1 3
- encrypt_block a STATE1 STATE2 STATE3 STATE4 STATE0 4
+.Lenc_loop:
+ encrypt_block STATE0 STATE1 STATE2 STATE3 STATE4 0
+ encrypt_block STATE4 STATE0 STATE1 STATE2 STATE3 1
+ encrypt_block STATE3 STATE4 STATE0 STATE1 STATE2 2
+ encrypt_block STATE2 STATE3 STATE4 STATE0 STATE1 3
+ encrypt_block STATE1 STATE2 STATE3 STATE4 STATE0 4
add $0x50, SRC
add $0x50, DST
- jmp .Lenc_a_loop
-
-.align 8
-.Lenc_u_loop:
- encrypt_block u STATE0 STATE1 STATE2 STATE3 STATE4 0
- encrypt_block u STATE4 STATE0 STATE1 STATE2 STATE3 1
- encrypt_block u STATE3 STATE4 STATE0 STATE1 STATE2 2
- encrypt_block u STATE2 STATE3 STATE4 STATE0 STATE1 3
- encrypt_block u STATE1 STATE2 STATE3 STATE4 STATE0 4
-
- add $0x50, SRC
- add $0x50, DST
- jmp .Lenc_u_loop
+ jmp .Lenc_loop
/* store the state: */
.Lenc_out_0:
@@ -452,7 +337,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
movdqu STATE1, 0x20(STATEP)
movdqu STATE2, 0x30(STATEP)
movdqu STATE3, 0x40(STATEP)
- FRAME_END
RET
.Lenc_out_1:
@@ -461,7 +345,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
movdqu STATE0, 0x20(STATEP)
movdqu STATE1, 0x30(STATEP)
movdqu STATE2, 0x40(STATEP)
- FRAME_END
RET
.Lenc_out_2:
@@ -470,7 +353,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
movdqu STATE4, 0x20(STATEP)
movdqu STATE0, 0x30(STATEP)
movdqu STATE1, 0x40(STATEP)
- FRAME_END
RET
.Lenc_out_3:
@@ -479,7 +361,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
movdqu STATE3, 0x20(STATEP)
movdqu STATE4, 0x30(STATEP)
movdqu STATE0, 0x40(STATEP)
- FRAME_END
RET
.Lenc_out_4:
@@ -488,20 +369,19 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc)
movdqu STATE2, 0x20(STATEP)
movdqu STATE3, 0x30(STATEP)
movdqu STATE4, 0x40(STATEP)
- FRAME_END
- RET
-
.Lenc_out:
- FRAME_END
RET
-SYM_FUNC_END(crypto_aegis128_aesni_enc)
+SYM_FUNC_END(aegis128_aesni_enc)
/*
- * void crypto_aegis128_aesni_enc_tail(void *state, unsigned int length,
- * const void *src, void *dst);
+ * void aegis128_aesni_enc_tail(struct aegis_state *state, const u8 *src,
+ * u8 *dst, unsigned int len);
*/
-SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail)
- FRAME_BEGIN
+SYM_FUNC_START(aegis128_aesni_enc_tail)
+ .set STATEP, %rdi
+ .set SRC, %rsi
+ .set DST, %rdx
+ .set LEN, %ecx /* {load,store}_partial rely on this being %ecx */
/* load the state: */
movdqu 0x00(STATEP), STATE0
@@ -511,7 +391,8 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail)
movdqu 0x40(STATEP), STATE4
/* encrypt message: */
- call __load_partial
+ mov LEN, %r9d
+ load_partial
movdqa MSG, T0
pxor STATE1, T0
@@ -520,7 +401,8 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail)
pand STATE3, T1
pxor T1, T0
- call __store_partial
+ mov %r9d, LEN
+ store_partial T0
aegis128_update
pxor MSG, STATE4
@@ -531,37 +413,36 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail)
movdqu STATE1, 0x20(STATEP)
movdqu STATE2, 0x30(STATEP)
movdqu STATE3, 0x40(STATEP)
-
- FRAME_END
RET
-SYM_FUNC_END(crypto_aegis128_aesni_enc_tail)
+SYM_FUNC_END(aegis128_aesni_enc_tail)
-.macro decrypt_block a s0 s1 s2 s3 s4 i
- movdq\a (\i * 0x10)(SRC), MSG
+.macro decrypt_block s0 s1 s2 s3 s4 i
+ movdqu (\i * 0x10)(SRC), MSG
pxor \s1, MSG
pxor \s4, MSG
movdqa \s2, T1
pand \s3, T1
pxor T1, MSG
- movdq\a MSG, (\i * 0x10)(DST)
+ movdqu MSG, (\i * 0x10)(DST)
aegis128_update
pxor MSG, \s4
sub $0x10, LEN
- cmp $0x10, LEN
- jl .Ldec_out_\i
+ jz .Ldec_out_\i
.endm
/*
- * void crypto_aegis128_aesni_dec(void *state, unsigned int length,
- * const void *src, void *dst);
+ * void aegis128_aesni_dec(struct aegis_state *state, const u8 *src, u8 *dst,
+ * unsigned int len);
+ *
+ * len must be nonzero and a multiple of 16.
*/
-SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
- FRAME_BEGIN
-
- cmp $0x10, LEN
- jb .Ldec_out
+SYM_FUNC_START(aegis128_aesni_dec)
+ .set STATEP, %rdi
+ .set SRC, %rsi
+ .set DST, %rdx
+ .set LEN, %ecx
/* load the state: */
movdqu 0x00(STATEP), STATE0
@@ -570,34 +451,17 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
movdqu 0x30(STATEP), STATE3
movdqu 0x40(STATEP), STATE4
- mov SRC, %r8
- or DST, %r8
- and $0xF, %r8
- jnz .Ldec_u_loop
-
.align 8
-.Ldec_a_loop:
- decrypt_block a STATE0 STATE1 STATE2 STATE3 STATE4 0
- decrypt_block a STATE4 STATE0 STATE1 STATE2 STATE3 1
- decrypt_block a STATE3 STATE4 STATE0 STATE1 STATE2 2
- decrypt_block a STATE2 STATE3 STATE4 STATE0 STATE1 3
- decrypt_block a STATE1 STATE2 STATE3 STATE4 STATE0 4
+.Ldec_loop:
+ decrypt_block STATE0 STATE1 STATE2 STATE3 STATE4 0
+ decrypt_block STATE4 STATE0 STATE1 STATE2 STATE3 1
+ decrypt_block STATE3 STATE4 STATE0 STATE1 STATE2 2
+ decrypt_block STATE2 STATE3 STATE4 STATE0 STATE1 3
+ decrypt_block STATE1 STATE2 STATE3 STATE4 STATE0 4
add $0x50, SRC
add $0x50, DST
- jmp .Ldec_a_loop
-
-.align 8
-.Ldec_u_loop:
- decrypt_block u STATE0 STATE1 STATE2 STATE3 STATE4 0
- decrypt_block u STATE4 STATE0 STATE1 STATE2 STATE3 1
- decrypt_block u STATE3 STATE4 STATE0 STATE1 STATE2 2
- decrypt_block u STATE2 STATE3 STATE4 STATE0 STATE1 3
- decrypt_block u STATE1 STATE2 STATE3 STATE4 STATE0 4
-
- add $0x50, SRC
- add $0x50, DST
- jmp .Ldec_u_loop
+ jmp .Ldec_loop
/* store the state: */
.Ldec_out_0:
@@ -606,7 +470,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
movdqu STATE1, 0x20(STATEP)
movdqu STATE2, 0x30(STATEP)
movdqu STATE3, 0x40(STATEP)
- FRAME_END
RET
.Ldec_out_1:
@@ -615,7 +478,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
movdqu STATE0, 0x20(STATEP)
movdqu STATE1, 0x30(STATEP)
movdqu STATE2, 0x40(STATEP)
- FRAME_END
RET
.Ldec_out_2:
@@ -624,7 +486,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
movdqu STATE4, 0x20(STATEP)
movdqu STATE0, 0x30(STATEP)
movdqu STATE1, 0x40(STATEP)
- FRAME_END
RET
.Ldec_out_3:
@@ -633,7 +494,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
movdqu STATE3, 0x20(STATEP)
movdqu STATE4, 0x30(STATEP)
movdqu STATE0, 0x40(STATEP)
- FRAME_END
RET
.Ldec_out_4:
@@ -642,20 +502,19 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec)
movdqu STATE2, 0x20(STATEP)
movdqu STATE3, 0x30(STATEP)
movdqu STATE4, 0x40(STATEP)
- FRAME_END
- RET
-
.Ldec_out:
- FRAME_END
RET
-SYM_FUNC_END(crypto_aegis128_aesni_dec)
+SYM_FUNC_END(aegis128_aesni_dec)
/*
- * void crypto_aegis128_aesni_dec_tail(void *state, unsigned int length,
- * const void *src, void *dst);
+ * void aegis128_aesni_dec_tail(struct aegis_state *state, const u8 *src,
+ * u8 *dst, unsigned int len);
*/
-SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail)
- FRAME_BEGIN
+SYM_FUNC_START(aegis128_aesni_dec_tail)
+ .set STATEP, %rdi
+ .set SRC, %rsi
+ .set DST, %rdx
+ .set LEN, %ecx /* {load,store}_partial rely on this being %ecx */
/* load the state: */
movdqu 0x00(STATEP), STATE0
@@ -665,7 +524,8 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail)
movdqu 0x40(STATEP), STATE4
/* decrypt message: */
- call __load_partial
+ mov LEN, %r9d
+ load_partial
pxor STATE1, MSG
pxor STATE4, MSG
@@ -673,17 +533,13 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail)
pand STATE3, T1
pxor T1, MSG
- movdqa MSG, T0
- call __store_partial
+ mov %r9d, LEN
+ store_partial MSG
/* mask with byte count: */
- movq LEN, T0
- punpcklbw T0, T0
- punpcklbw T0, T0
- punpcklbw T0, T0
- punpcklbw T0, T0
- movdqa .Laegis128_counter(%rip), T1
- pcmpgtb T1, T0
+ lea .Lzeropad_mask+16(%rip), %rax
+ sub %r9, %rax
+ movdqu (%rax), T0
pand T0, MSG
aegis128_update
@@ -695,17 +551,19 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail)
movdqu STATE1, 0x20(STATEP)
movdqu STATE2, 0x30(STATEP)
movdqu STATE3, 0x40(STATEP)
-
- FRAME_END
RET
-SYM_FUNC_END(crypto_aegis128_aesni_dec_tail)
+SYM_FUNC_END(aegis128_aesni_dec_tail)
/*
- * void crypto_aegis128_aesni_final(void *state, void *tag_xor,
- * u64 assoclen, u64 cryptlen);
+ * void aegis128_aesni_final(struct aegis_state *state,
+ * struct aegis_block *tag_xor,
+ * unsigned int assoclen, unsigned int cryptlen);
*/
-SYM_FUNC_START(crypto_aegis128_aesni_final)
- FRAME_BEGIN
+SYM_FUNC_START(aegis128_aesni_final)
+ .set STATEP, %rdi
+ .set TAG_XOR, %rsi
+ .set ASSOCLEN, %edx
+ .set CRYPTLEN, %ecx
/* load the state: */
movdqu 0x00(STATEP), STATE0
@@ -715,10 +573,8 @@ SYM_FUNC_START(crypto_aegis128_aesni_final)
movdqu 0x40(STATEP), STATE4
/* prepare length block: */
- movq %rdx, MSG
- movq %rcx, T0
- pslldq $8, T0
- pxor T0, MSG
+ movd ASSOCLEN, MSG
+ pinsrd $2, CRYPTLEN, MSG
psllq $3, MSG /* multiply by 8 (to get bit count) */
pxor STATE3, MSG
@@ -733,7 +589,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_final)
aegis128_update; pxor MSG, STATE3
/* xor tag: */
- movdqu (%rsi), MSG
+ movdqu (TAG_XOR), MSG
pxor STATE0, MSG
pxor STATE1, MSG
@@ -741,8 +597,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_final)
pxor STATE3, MSG
pxor STATE4, MSG
- movdqu MSG, (%rsi)
-
- FRAME_END
+ movdqu MSG, (TAG_XOR)
RET
-SYM_FUNC_END(crypto_aegis128_aesni_final)
+SYM_FUNC_END(aegis128_aesni_final)
diff --git a/arch/x86/crypto/aegis128-aesni-glue.c b/arch/x86/crypto/aegis128-aesni-glue.c
index 4623189000d8..c19d8e3d96a3 100644
--- a/arch/x86/crypto/aegis128-aesni-glue.c
+++ b/arch/x86/crypto/aegis128-aesni-glue.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* The AEGIS-128 Authenticated-Encryption Algorithm
- * Glue for AES-NI + SSE2 implementation
+ * Glue for AES-NI + SSE4.1 implementation
*
* Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com>
* Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
@@ -23,27 +23,6 @@
#define AEGIS128_MIN_AUTH_SIZE 8
#define AEGIS128_MAX_AUTH_SIZE 16
-asmlinkage void crypto_aegis128_aesni_init(void *state, void *key, void *iv);
-
-asmlinkage void crypto_aegis128_aesni_ad(
- void *state, unsigned int length, const void *data);
-
-asmlinkage void crypto_aegis128_aesni_enc(
- void *state, unsigned int length, const void *src, void *dst);
-
-asmlinkage void crypto_aegis128_aesni_dec(
- void *state, unsigned int length, const void *src, void *dst);
-
-asmlinkage void crypto_aegis128_aesni_enc_tail(
- void *state, unsigned int length, const void *src, void *dst);
-
-asmlinkage void crypto_aegis128_aesni_dec_tail(
- void *state, unsigned int length, const void *src, void *dst);
-
-asmlinkage void crypto_aegis128_aesni_final(
- void *state, void *tag_xor, unsigned int cryptlen,
- unsigned int assoclen);
-
struct aegis_block {
u8 bytes[AEGIS128_BLOCK_SIZE] __aligned(AEGIS128_BLOCK_ALIGN);
};
@@ -56,15 +35,31 @@ struct aegis_ctx {
struct aegis_block key;
};
-struct aegis_crypt_ops {
- int (*skcipher_walk_init)(struct skcipher_walk *walk,
- struct aead_request *req, bool atomic);
+asmlinkage void aegis128_aesni_init(struct aegis_state *state,
+ const struct aegis_block *key,
+ const u8 iv[AEGIS128_NONCE_SIZE]);
- void (*crypt_blocks)(void *state, unsigned int length, const void *src,
- void *dst);
- void (*crypt_tail)(void *state, unsigned int length, const void *src,
- void *dst);
-};
+asmlinkage void aegis128_aesni_ad(struct aegis_state *state, const u8 *data,
+ unsigned int len);
+
+asmlinkage void aegis128_aesni_enc(struct aegis_state *state, const u8 *src,
+ u8 *dst, unsigned int len);
+
+asmlinkage void aegis128_aesni_dec(struct aegis_state *state, const u8 *src,
+ u8 *dst, unsigned int len);
+
+asmlinkage void aegis128_aesni_enc_tail(struct aegis_state *state,
+ const u8 *src, u8 *dst,
+ unsigned int len);
+
+asmlinkage void aegis128_aesni_dec_tail(struct aegis_state *state,
+ const u8 *src, u8 *dst,
+ unsigned int len);
+
+asmlinkage void aegis128_aesni_final(struct aegis_state *state,
+ struct aegis_block *tag_xor,
+ unsigned int assoclen,
+ unsigned int cryptlen);
static void crypto_aegis128_aesni_process_ad(
struct aegis_state *state, struct scatterlist *sg_src,
@@ -85,16 +80,15 @@ static void crypto_aegis128_aesni_process_ad(
if (pos > 0) {
unsigned int fill = AEGIS128_BLOCK_SIZE - pos;
memcpy(buf.bytes + pos, src, fill);
- crypto_aegis128_aesni_ad(state,
- AEGIS128_BLOCK_SIZE,
- buf.bytes);
+ aegis128_aesni_ad(state, buf.bytes,
+ AEGIS128_BLOCK_SIZE);
pos = 0;
left -= fill;
src += fill;
}
- crypto_aegis128_aesni_ad(state, left, src);
-
+ aegis128_aesni_ad(state, src,
+ left & ~(AEGIS128_BLOCK_SIZE - 1));
src += left & ~(AEGIS128_BLOCK_SIZE - 1);
left &= AEGIS128_BLOCK_SIZE - 1;
}
@@ -110,24 +104,37 @@ static void crypto_aegis128_aesni_process_ad(
if (pos > 0) {
memset(buf.bytes + pos, 0, AEGIS128_BLOCK_SIZE - pos);
- crypto_aegis128_aesni_ad(state, AEGIS128_BLOCK_SIZE, buf.bytes);
+ aegis128_aesni_ad(state, buf.bytes, AEGIS128_BLOCK_SIZE);
}
}
-static void crypto_aegis128_aesni_process_crypt(
- struct aegis_state *state, struct skcipher_walk *walk,
- const struct aegis_crypt_ops *ops)
+static __always_inline void
+crypto_aegis128_aesni_process_crypt(struct aegis_state *state,
+ struct skcipher_walk *walk, bool enc)
{
while (walk->nbytes >= AEGIS128_BLOCK_SIZE) {
- ops->crypt_blocks(state,
- round_down(walk->nbytes, AEGIS128_BLOCK_SIZE),
- walk->src.virt.addr, walk->dst.virt.addr);
+ if (enc)
+ aegis128_aesni_enc(state, walk->src.virt.addr,
+ walk->dst.virt.addr,
+ round_down(walk->nbytes,
+ AEGIS128_BLOCK_SIZE));
+ else
+ aegis128_aesni_dec(state, walk->src.virt.addr,
+ walk->dst.virt.addr,
+ round_down(walk->nbytes,
+ AEGIS128_BLOCK_SIZE));
skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE);
}
if (walk->nbytes) {
- ops->crypt_tail(state, walk->nbytes, walk->src.virt.addr,
- walk->dst.virt.addr);
+ if (enc)
+ aegis128_aesni_enc_tail(state, walk->src.virt.addr,
+ walk->dst.virt.addr,
+ walk->nbytes);
+ else
+ aegis128_aesni_dec_tail(state, walk->src.virt.addr,
+ walk->dst.virt.addr,
+ walk->nbytes);
skcipher_walk_done(walk, 0);
}
}
@@ -162,42 +169,39 @@ static int crypto_aegis128_aesni_setauthsize(struct crypto_aead *tfm,
return 0;
}
-static void crypto_aegis128_aesni_crypt(struct aead_request *req,
- struct aegis_block *tag_xor,
- unsigned int cryptlen,
- const struct aegis_crypt_ops *ops)
+static __always_inline void
+crypto_aegis128_aesni_crypt(struct aead_request *req,
+ struct aegis_block *tag_xor,
+ unsigned int cryptlen, bool enc)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct aegis_ctx *ctx = crypto_aegis128_aesni_ctx(tfm);
struct skcipher_walk walk;
struct aegis_state state;
- ops->skcipher_walk_init(&walk, req, true);
+ if (enc)
+ skcipher_walk_aead_encrypt(&walk, req, true);
+ else
+ skcipher_walk_aead_decrypt(&walk, req, true);
kernel_fpu_begin();
- crypto_aegis128_aesni_init(&state, ctx->key.bytes, req->iv);
+ aegis128_aesni_init(&state, &ctx->key, req->iv);
crypto_aegis128_aesni_process_ad(&state, req->src, req->assoclen);
- crypto_aegis128_aesni_process_crypt(&state, &walk, ops);
- crypto_aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen);
+ crypto_aegis128_aesni_process_crypt(&state, &walk, enc);
+ aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen);
kernel_fpu_end();
}
static int crypto_aegis128_aesni_encrypt(struct aead_request *req)
{
- static const struct aegis_crypt_ops OPS = {
- .skcipher_walk_init = skcipher_walk_aead_encrypt,
- .crypt_blocks = crypto_aegis128_aesni_enc,
- .crypt_tail = crypto_aegis128_aesni_enc_tail,
- };
-
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct aegis_block tag = {};
unsigned int authsize = crypto_aead_authsize(tfm);
unsigned int cryptlen = req->cryptlen;
- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, &OPS);
+ crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true);
scatterwalk_map_and_copy(tag.bytes, req->dst,
req->assoclen + cryptlen, authsize, 1);
@@ -208,12 +212,6 @@ static int crypto_aegis128_aesni_decrypt(struct aead_request *req)
{
static const struct aegis_block zeros = {};
- static const struct aegis_crypt_ops OPS = {
- .skcipher_walk_init = skcipher_walk_aead_decrypt,
- .crypt_blocks = crypto_aegis128_aesni_dec,
- .crypt_tail = crypto_aegis128_aesni_dec_tail,
- };
-
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct aegis_block tag;
unsigned int authsize = crypto_aead_authsize(tfm);
@@ -222,27 +220,16 @@ static int crypto_aegis128_aesni_decrypt(struct aead_request *req)
scatterwalk_map_and_copy(tag.bytes, req->src,
req->assoclen + cryptlen, authsize, 0);
- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, &OPS);
+ crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false);
return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0;
}
-static int crypto_aegis128_aesni_init_tfm(struct crypto_aead *aead)
-{
- return 0;
-}
-
-static void crypto_aegis128_aesni_exit_tfm(struct crypto_aead *aead)
-{
-}
-
static struct aead_alg crypto_aegis128_aesni_alg = {
.setkey = crypto_aegis128_aesni_setkey,
.setauthsize = crypto_aegis128_aesni_setauthsize,
.encrypt = crypto_aegis128_aesni_encrypt,
.decrypt = crypto_aegis128_aesni_decrypt,
- .init = crypto_aegis128_aesni_init_tfm,
- .exit = crypto_aegis128_aesni_exit_tfm,
.ivsize = AEGIS128_NONCE_SIZE,
.maxauthsize = AEGIS128_MAX_AUTH_SIZE,
@@ -267,7 +254,7 @@ static struct simd_aead_alg *simd_alg;
static int __init crypto_aegis128_aesni_module_init(void)
{
- if (!boot_cpu_has(X86_FEATURE_XMM2) ||
+ if (!boot_cpu_has(X86_FEATURE_XMM4_1) ||
!boot_cpu_has(X86_FEATURE_AES) ||
!cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL))
return -ENODEV;
@@ -286,6 +273,6 @@ module_exit(crypto_aegis128_aesni_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>");
-MODULE_DESCRIPTION("AEGIS-128 AEAD algorithm -- AESNI+SSE2 implementation");
+MODULE_DESCRIPTION("AEGIS-128 AEAD algorithm -- AESNI+SSE4.1 implementation");
MODULE_ALIAS_CRYPTO("aegis128");
MODULE_ALIAS_CRYPTO("aegis128-aesni");
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index b0dd83555499..fbf43482e1f5 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -1747,7 +1747,7 @@ static void __exit aesni_exit(void)
unregister_avx_algs();
}
-late_initcall(aesni_init);
+module_init(aesni_init);
module_exit(aesni_exit);
MODULE_DESCRIPTION("AES cipher and modes, optimized with AES-NI or VAES instructions");
diff --git a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
index b4e460a87f18..fb95a614249d 100644
--- a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
@@ -487,79 +487,3 @@ SYM_FUNC_START(cast5_cbc_dec_16way)
FRAME_END
RET;
SYM_FUNC_END(cast5_cbc_dec_16way)
-
-SYM_FUNC_START(cast5_ctr_16way)
- /* input:
- * %rdi: ctx
- * %rsi: dst
- * %rdx: src
- * %rcx: iv (big endian, 64bit)
- */
- FRAME_BEGIN
- pushq %r12;
- pushq %r15;
-
- movq %rdi, CTX;
- movq %rsi, %r11;
- movq %rdx, %r12;
-
- vpcmpeqd RTMP, RTMP, RTMP;
- vpsrldq $8, RTMP, RTMP; /* low: -1, high: 0 */
-
- vpcmpeqd RKR, RKR, RKR;
- vpaddq RKR, RKR, RKR; /* low: -2, high: -2 */
- vmovdqa .Lbswap_iv_mask(%rip), R1ST;
- vmovdqa .Lbswap128_mask(%rip), RKM;
-
- /* load IV and byteswap */
- vmovq (%rcx), RX;
- vpshufb R1ST, RX, RX;
-
- /* construct IVs */
- vpsubq RTMP, RX, RX; /* le: IV1, IV0 */
- vpshufb RKM, RX, RL1; /* be: IV0, IV1 */
- vpsubq RKR, RX, RX;
- vpshufb RKM, RX, RR1; /* be: IV2, IV3 */
- vpsubq RKR, RX, RX;
- vpshufb RKM, RX, RL2; /* be: IV4, IV5 */
- vpsubq RKR, RX, RX;
- vpshufb RKM, RX, RR2; /* be: IV6, IV7 */
- vpsubq RKR, RX, RX;
- vpshufb RKM, RX, RL3; /* be: IV8, IV9 */
- vpsubq RKR, RX, RX;
- vpshufb RKM, RX, RR3; /* be: IV10, IV11 */
- vpsubq RKR, RX, RX;
- vpshufb RKM, RX, RL4; /* be: IV12, IV13 */
- vpsubq RKR, RX, RX;
- vpshufb RKM, RX, RR4; /* be: IV14, IV15 */
-
- /* store last IV */
- vpsubq RTMP, RX, RX; /* le: IV16, IV14 */
- vpshufb R1ST, RX, RX; /* be: IV16, IV16 */
- vmovq RX, (%rcx);
-
- call __cast5_enc_blk16;
-
- /* dst = src ^ iv */
- vpxor (0*16)(%r12), RR1, RR1;
- vpxor (1*16)(%r12), RL1, RL1;
- vpxor (2*16)(%r12), RR2, RR2;
- vpxor (3*16)(%r12), RL2, RL2;
- vpxor (4*16)(%r12), RR3, RR3;
- vpxor (5*16)(%r12), RL3, RL3;
- vpxor (6*16)(%r12), RR4, RR4;
- vpxor (7*16)(%r12), RL4, RL4;
- vmovdqu RR1, (0*16)(%r11);
- vmovdqu RL1, (1*16)(%r11);
- vmovdqu RR2, (2*16)(%r11);
- vmovdqu RL2, (3*16)(%r11);
- vmovdqu RR3, (4*16)(%r11);
- vmovdqu RL3, (5*16)(%r11);
- vmovdqu RR4, (6*16)(%r11);
- vmovdqu RL4, (7*16)(%r11);
-
- popq %r15;
- popq %r12;
- FRAME_END
- RET;
-SYM_FUNC_END(cast5_ctr_16way)
diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c
index feccb5254c7e..52c5d47ef5a1 100644
--- a/arch/x86/crypto/crc32c-intel_glue.c
+++ b/arch/x86/crypto/crc32c-intel_glue.c
@@ -41,7 +41,7 @@
*/
#define CRC32C_PCL_BREAKEVEN 512
-asmlinkage unsigned int crc_pcl(const u8 *buffer, int len,
+asmlinkage unsigned int crc_pcl(const u8 *buffer, unsigned int len,
unsigned int crc_init);
#endif /* CONFIG_X86_64 */
diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
index bbcff1fb78cb..752812bc4991 100644
--- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
@@ -7,6 +7,7 @@
* http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-paper.pdf
*
* Copyright (C) 2012 Intel Corporation.
+ * Copyright 2024 Google LLC
*
* Authors:
* Wajdi Feghali <wajdi.k.feghali@intel.com>
@@ -44,185 +45,129 @@
*/
#include <linux/linkage.h>
-#include <asm/nospec-branch.h>
## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction
-.macro LABEL prefix n
-.L\prefix\n\():
-.endm
-
-.macro JMPTBL_ENTRY i
-.quad .Lcrc_\i
-.endm
-
-.macro JNC_LESS_THAN j
- jnc .Lless_than_\j
-.endm
-
-# Define threshold where buffers are considered "small" and routed to more
-# efficient "by-1" code. This "by-1" code only handles up to 255 bytes, so
-# SMALL_SIZE can be no larger than 255.
-
+# Define threshold below which buffers are considered "small" and routed to
+# regular CRC code that does not interleave the CRC instructions.
#define SMALL_SIZE 200
-.if (SMALL_SIZE > 255)
-.error "SMALL_ SIZE must be < 256"
-.endif
-
-# unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init);
+# unsigned int crc_pcl(const u8 *buffer, unsigned int len, unsigned int crc_init);
.text
SYM_FUNC_START(crc_pcl)
-#define bufp rdi
-#define bufp_dw %edi
-#define bufp_w %di
-#define bufp_b %dil
-#define bufptmp %rcx
-#define block_0 %rcx
-#define block_1 %rdx
-#define block_2 %r11
-#define len %rsi
-#define len_dw %esi
-#define len_w %si
-#define len_b %sil
-#define crc_init_arg %rdx
-#define tmp %rbx
-#define crc_init %r8
-#define crc_init_dw %r8d
-#define crc1 %r9
-#define crc2 %r10
-
- pushq %rbx
- pushq %rdi
- pushq %rsi
-
- ## Move crc_init for Linux to a different
- mov crc_init_arg, crc_init
+#define bufp %rdi
+#define bufp_d %edi
+#define len %esi
+#define crc_init %edx
+#define crc_init_q %rdx
+#define n_misaligned %ecx /* overlaps chunk_bytes! */
+#define n_misaligned_q %rcx
+#define chunk_bytes %ecx /* overlaps n_misaligned! */
+#define chunk_bytes_q %rcx
+#define crc1 %r8
+#define crc2 %r9
+
+ cmp $SMALL_SIZE, len
+ jb .Lsmall
################################################################
## 1) ALIGN:
################################################################
-
- mov %bufp, bufptmp # rdi = *buf
- neg %bufp
- and $7, %bufp # calculate the unalignment amount of
+ mov bufp_d, n_misaligned
+ neg n_misaligned
+ and $7, n_misaligned # calculate the misalignment amount of
# the address
- je .Lproc_block # Skip if aligned
-
- ## If len is less than 8 and we're unaligned, we need to jump
- ## to special code to avoid reading beyond the end of the buffer
- cmp $8, len
- jae .Ldo_align
- # less_than_8 expects length in upper 3 bits of len_dw
- # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
- shl $32-3+1, len_dw
- jmp .Lless_than_8_post_shl1
+ je .Laligned # Skip if aligned
+ # Process 1 <= n_misaligned <= 7 bytes individually in order to align
+ # the remaining data to an 8-byte boundary.
.Ldo_align:
- #### Calculate CRC of unaligned bytes of the buffer (if any)
- movq (bufptmp), tmp # load a quadward from the buffer
- add %bufp, bufptmp # align buffer pointer for quadword
- # processing
- sub %bufp, len # update buffer length
+ movq (bufp), %rax
+ add n_misaligned_q, bufp
+ sub n_misaligned, len
.Lalign_loop:
- crc32b %bl, crc_init_dw # compute crc32 of 1-byte
- shr $8, tmp # get next byte
- dec %bufp
+ crc32b %al, crc_init # compute crc32 of 1-byte
+ shr $8, %rax # get next byte
+ dec n_misaligned
jne .Lalign_loop
-
-.Lproc_block:
+.Laligned:
################################################################
- ## 2) PROCESS BLOCKS:
+ ## 2) PROCESS BLOCK:
################################################################
- ## compute num of bytes to be processed
- movq len, tmp # save num bytes in tmp
-
- cmpq $128*24, len
+ cmp $128*24, len
jae .Lfull_block
-.Lcontinue_block:
- cmpq $SMALL_SIZE, len
- jb .Lsmall
-
- ## len < 128*24
- movq $2731, %rax # 2731 = ceil(2^16 / 24)
- mul len_dw
- shrq $16, %rax
-
- ## eax contains floor(bytes / 24) = num 24-byte chunks to do
-
- ## process rax 24-byte chunks (128 >= rax >= 0)
-
- ## compute end address of each block
- ## block 0 (base addr + RAX * 8)
- ## block 1 (base addr + RAX * 16)
- ## block 2 (base addr + RAX * 24)
- lea (bufptmp, %rax, 8), block_0
- lea (block_0, %rax, 8), block_1
- lea (block_1, %rax, 8), block_2
+.Lpartial_block:
+ # Compute floor(len / 24) to get num qwords to process from each lane.
+ imul $2731, len, %eax # 2731 = ceil(2^16 / 24)
+ shr $16, %eax
+ jmp .Lcrc_3lanes
- xor crc1, crc1
- xor crc2, crc2
-
- ## branch into array
- leaq jump_table(%rip), %bufp
- mov (%bufp,%rax,8), %bufp
- JMP_NOSPEC bufp
-
- ################################################################
- ## 2a) PROCESS FULL BLOCKS:
- ################################################################
.Lfull_block:
- movl $128,%eax
- lea 128*8*2(block_0), block_1
- lea 128*8*3(block_0), block_2
- add $128*8*1, block_0
-
- xor crc1,crc1
- xor crc2,crc2
-
- # Fall through into top of crc array (crc_128)
+ # Processing 128 qwords from each lane.
+ mov $128, %eax
################################################################
- ## 3) CRC Array:
+ ## 3) CRC each of three lanes:
################################################################
- i=128
-.rept 128-1
-.altmacro
-LABEL crc_ %i
-.noaltmacro
- ENDBR
- crc32q -i*8(block_0), crc_init
- crc32q -i*8(block_1), crc1
- crc32q -i*8(block_2), crc2
- i=(i-1)
-.endr
-
-.altmacro
-LABEL crc_ %i
-.noaltmacro
- ENDBR
- crc32q -i*8(block_0), crc_init
- crc32q -i*8(block_1), crc1
-# SKIP crc32 -i*8(block_2), crc2 ; Don't do this one yet
-
- mov block_2, block_0
+.Lcrc_3lanes:
+ xor crc1,crc1
+ xor crc2,crc2
+ mov %eax, chunk_bytes
+ shl $3, chunk_bytes # num bytes to process from each lane
+ sub $5, %eax # 4 for 4x_loop, 1 for special last iter
+ jl .Lcrc_3lanes_4x_done
+
+ # Unroll the loop by a factor of 4 to reduce the overhead of the loop
+ # bookkeeping instructions, which can compete with crc32q for the ALUs.
+.Lcrc_3lanes_4x_loop:
+ crc32q (bufp), crc_init_q
+ crc32q (bufp,chunk_bytes_q), crc1
+ crc32q (bufp,chunk_bytes_q,2), crc2
+ crc32q 8(bufp), crc_init_q
+ crc32q 8(bufp,chunk_bytes_q), crc1
+ crc32q 8(bufp,chunk_bytes_q,2), crc2
+ crc32q 16(bufp), crc_init_q
+ crc32q 16(bufp,chunk_bytes_q), crc1
+ crc32q 16(bufp,chunk_bytes_q,2), crc2
+ crc32q 24(bufp), crc_init_q
+ crc32q 24(bufp,chunk_bytes_q), crc1
+ crc32q 24(bufp,chunk_bytes_q,2), crc2
+ add $32, bufp
+ sub $4, %eax
+ jge .Lcrc_3lanes_4x_loop
+
+.Lcrc_3lanes_4x_done:
+ add $4, %eax
+ jz .Lcrc_3lanes_last_qword
+
+.Lcrc_3lanes_1x_loop:
+ crc32q (bufp), crc_init_q
+ crc32q (bufp,chunk_bytes_q), crc1
+ crc32q (bufp,chunk_bytes_q,2), crc2
+ add $8, bufp
+ dec %eax
+ jnz .Lcrc_3lanes_1x_loop
+
+.Lcrc_3lanes_last_qword:
+ crc32q (bufp), crc_init_q
+ crc32q (bufp,chunk_bytes_q), crc1
+# SKIP crc32q (bufp,chunk_bytes_q,2), crc2 ; Don't do this one yet
################################################################
## 4) Combine three results:
################################################################
- lea (K_table-8)(%rip), %bufp # first entry is for idx 1
- shlq $3, %rax # rax *= 8
- pmovzxdq (%bufp,%rax), %xmm0 # 2 consts: K1:K2
- leal (%eax,%eax,2), %eax # rax *= 3 (total *24)
- subq %rax, tmp # tmp -= rax*24
+ lea (K_table-8)(%rip), %rax # first entry is for idx 1
+ pmovzxdq (%rax,chunk_bytes_q), %xmm0 # 2 consts: K1:K2
+ lea (chunk_bytes,chunk_bytes,2), %eax # chunk_bytes * 3
+ sub %eax, len # len -= chunk_bytes * 3
- movq crc_init, %xmm1 # CRC for block 1
+ movq crc_init_q, %xmm1 # CRC for block 1
pclmulqdq $0x00, %xmm0, %xmm1 # Multiply by K2
movq crc1, %xmm2 # CRC for block 2
@@ -230,103 +175,54 @@ LABEL crc_ %i
pxor %xmm2,%xmm1
movq %xmm1, %rax
- xor -i*8(block_2), %rax
- mov crc2, crc_init
- crc32 %rax, crc_init
+ xor (bufp,chunk_bytes_q,2), %rax
+ mov crc2, crc_init_q
+ crc32 %rax, crc_init_q
+ lea 8(bufp,chunk_bytes_q,2), bufp
################################################################
- ## 5) Check for end:
+ ## 5) If more blocks remain, goto (2):
################################################################
-LABEL crc_ 0
- ENDBR
- mov tmp, len
- cmp $128*24, tmp
- jae .Lfull_block
- cmp $24, tmp
- jae .Lcontinue_block
-
-.Lless_than_24:
- shl $32-4, len_dw # less_than_16 expects length
- # in upper 4 bits of len_dw
- jnc .Lless_than_16
- crc32q (bufptmp), crc_init
- crc32q 8(bufptmp), crc_init
- jz .Ldo_return
- add $16, bufptmp
- # len is less than 8 if we got here
- # less_than_8 expects length in upper 3 bits of len_dw
- # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
- shl $2, len_dw
- jmp .Lless_than_8_post_shl1
+ cmp $128*24, len
+ jae .Lfull_block
+ cmp $SMALL_SIZE, len
+ jae .Lpartial_block
#######################################################################
- ## 6) LESS THAN 256-bytes REMAIN AT THIS POINT (8-bits of len are full)
+ ## 6) Process any remainder without interleaving:
#######################################################################
.Lsmall:
- shl $32-8, len_dw # Prepare len_dw for less_than_256
- j=256
-.rept 5 # j = {256, 128, 64, 32, 16}
-.altmacro
-LABEL less_than_ %j # less_than_j: Length should be in
- # upper lg(j) bits of len_dw
- j=(j/2)
- shl $1, len_dw # Get next MSB
- JNC_LESS_THAN %j
-.noaltmacro
- i=0
-.rept (j/8)
- crc32q i(bufptmp), crc_init # Compute crc32 of 8-byte data
- i=i+8
-.endr
- jz .Ldo_return # Return if remaining length is zero
- add $j, bufptmp # Advance buf
-.endr
-
-.Lless_than_8: # Length should be stored in
- # upper 3 bits of len_dw
- shl $1, len_dw
-.Lless_than_8_post_shl1:
- jnc .Lless_than_4
- crc32l (bufptmp), crc_init_dw # CRC of 4 bytes
- jz .Ldo_return # return if remaining data is zero
- add $4, bufptmp
-.Lless_than_4: # Length should be stored in
- # upper 2 bits of len_dw
- shl $1, len_dw
- jnc .Lless_than_2
- crc32w (bufptmp), crc_init_dw # CRC of 2 bytes
- jz .Ldo_return # return if remaining data is zero
- add $2, bufptmp
-.Lless_than_2: # Length should be stored in the MSB
- # of len_dw
- shl $1, len_dw
- jnc .Lless_than_1
- crc32b (bufptmp), crc_init_dw # CRC of 1 byte
-.Lless_than_1: # Length should be zero
-.Ldo_return:
- movq crc_init, %rax
- popq %rsi
- popq %rdi
- popq %rbx
+ test len, len
+ jz .Ldone
+ mov len, %eax
+ shr $3, %eax
+ jz .Ldo_dword
+.Ldo_qwords:
+ crc32q (bufp), crc_init_q
+ add $8, bufp
+ dec %eax
+ jnz .Ldo_qwords
+.Ldo_dword:
+ test $4, len
+ jz .Ldo_word
+ crc32l (bufp), crc_init
+ add $4, bufp
+.Ldo_word:
+ test $2, len
+ jz .Ldo_byte
+ crc32w (bufp), crc_init
+ add $2, bufp
+.Ldo_byte:
+ test $1, len
+ jz .Ldone
+ crc32b (bufp), crc_init
+.Ldone:
+ mov crc_init, %eax
RET
SYM_FUNC_END(crc_pcl)
.section .rodata, "a", @progbits
- ################################################################
- ## jump table Table is 129 entries x 2 bytes each
- ################################################################
-.align 4
-jump_table:
- i=0
-.rept 129
-.altmacro
-JMPTBL_ENTRY %i
-.noaltmacro
- i=i+1
-.endr
-
-
################################################################
## PCLMULQDQ tables
## Table is 128 entries x 2 words (8 bytes) each
diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S
index 324686bca368..b7ea3e8e9ecc 100644
--- a/arch/x86/entry/entry.S
+++ b/arch/x86/entry/entry.S
@@ -51,3 +51,19 @@ EXPORT_SYMBOL_GPL(mds_verw_sel);
.popsection
THUNK warn_thunk_thunk, __warn_thunk
+
+#ifndef CONFIG_X86_64
+/*
+ * Clang's implementation of TLS stack cookies requires the variable in
+ * question to be a TLS variable. If the variable happens to be defined as an
+ * ordinary variable with external linkage in the same compilation unit (which
+ * amounts to the whole of vmlinux with LTO enabled), Clang will drop the
+ * segment register prefix from the references, resulting in broken code. Work
+ * around this by avoiding the symbol used in -mstack-protector-guard-symbol=
+ * entirely in the C code, and use an alias emitted by the linker script
+ * instead.
+ */
+#ifdef CONFIG_STACKPROTECTOR
+EXPORT_SYMBOL(__ref_stack_chk_guard);
+#endif
+#endif
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 534c74b14fab..4d0fb2fba7e2 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -468,3 +468,7 @@
460 i386 lsm_set_self_attr sys_lsm_set_self_attr
461 i386 lsm_list_modules sys_lsm_list_modules
462 i386 mseal sys_mseal
+463 i386 setxattrat sys_setxattrat
+464 i386 getxattrat sys_getxattrat
+465 i386 listxattrat sys_listxattrat
+466 i386 removexattrat sys_removexattrat
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 7093ee21c0d1..5eb708bff1c7 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -386,6 +386,10 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
#
# Due to a historical design error, certain syscalls are numbered differently
diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S
index bafa73f09e92..872947c1004c 100644
--- a/arch/x86/entry/vdso/vdso-layout.lds.S
+++ b/arch/x86/entry/vdso/vdso-layout.lds.S
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <asm/vdso.h>
+#include <asm/vdso/vsyscall.h>
/*
* Linker script for vDSO. This is an ELF shared object prelinked to
@@ -16,23 +17,16 @@ SECTIONS
* segment.
*/
- vvar_start = . - 4 * PAGE_SIZE;
+ vvar_start = . - __VVAR_PAGES * PAGE_SIZE;
vvar_page = vvar_start;
- /* Place all vvars at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
-#include <asm/vvar.h>
-#undef EMIT_VVAR
+ vdso_rng_data = vvar_page + __VDSO_RND_DATA_OFFSET;
- pvclock_page = vvar_start + PAGE_SIZE;
- hvclock_page = vvar_start + 2 * PAGE_SIZE;
- timens_page = vvar_start + 3 * PAGE_SIZE;
+ timens_page = vvar_start + PAGE_SIZE;
-#undef _ASM_X86_VVAR_H
- /* Place all vvars in timens too at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset) timens_ ## name = timens_page + offset;
-#include <asm/vvar.h>
-#undef EMIT_VVAR
+ vclock_pages = vvar_start + VDSO_NR_VCLOCK_PAGES * PAGE_SIZE;
+ pvclock_page = vclock_pages + VDSO_PAGE_PVCLOCK_OFFSET * PAGE_SIZE;
+ hvclock_page = vclock_pages + VDSO_PAGE_HVCLOCK_OFFSET * PAGE_SIZE;
. = SIZEOF_HEADERS;
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index b8fed8b8b9cc..39e6efc1a9ca 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -20,26 +20,20 @@
#include <asm/vgtod.h>
#include <asm/proto.h>
#include <asm/vdso.h>
-#include <asm/vvar.h>
#include <asm/tlb.h>
#include <asm/page.h>
#include <asm/desc.h>
#include <asm/cpufeature.h>
+#include <asm/vdso/vsyscall.h>
#include <clocksource/hyperv_timer.h>
-#undef _ASM_X86_VVAR_H
-#define EMIT_VVAR(name, offset) \
- const size_t name ## _offset = offset;
-#include <asm/vvar.h>
-
struct vdso_data *arch_get_vdso_data(void *vvar_page)
{
- return (struct vdso_data *)(vvar_page + _vdso_data_offset);
+ return (struct vdso_data *)vvar_page;
}
-#undef EMIT_VVAR
-DEFINE_VVAR(struct vdso_data, _vdso_data);
-DEFINE_VVAR_SINGLE(struct vdso_rng_data, _vdso_rng_data);
+static union vdso_data_store vdso_data_store __page_aligned_data;
+struct vdso_data *vdso_data = vdso_data_store.data;
unsigned int vclocks_used __read_mostly;
@@ -54,7 +48,8 @@ int __init init_vdso_image(const struct vdso_image *image)
apply_alternatives((struct alt_instr *)(image->data + image->alt),
(struct alt_instr *)(image->data + image->alt +
- image->alt_len));
+ image->alt_len),
+ NULL);
return 0;
}
@@ -154,7 +149,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
if (sym_offset == image->sym_vvar_page) {
struct page *timens_page = find_timens_vvar_page(vma);
- pfn = __pa_symbol(&__vvar_page) >> PAGE_SHIFT;
+ pfn = __pa_symbol(vdso_data) >> PAGE_SHIFT;
/*
* If a task belongs to a time namespace then a namespace
@@ -182,32 +177,52 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
}
return vmf_insert_pfn(vma, vmf->address, pfn);
- } else if (sym_offset == image->sym_pvclock_page) {
- struct pvclock_vsyscall_time_info *pvti =
- pvclock_get_pvti_cpu0_va();
- if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK)) {
- return vmf_insert_pfn_prot(vma, vmf->address,
- __pa(pvti) >> PAGE_SHIFT,
- pgprot_decrypted(vma->vm_page_prot));
- }
- } else if (sym_offset == image->sym_hvclock_page) {
- pfn = hv_get_tsc_pfn();
- 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);
if (!timens_page)
return VM_FAULT_SIGBUS;
- pfn = __pa_symbol(&__vvar_page) >> PAGE_SHIFT;
+ pfn = __pa_symbol(vdso_data) >> PAGE_SHIFT;
return vmf_insert_pfn(vma, vmf->address, pfn);
}
return VM_FAULT_SIGBUS;
}
+static vm_fault_t vvar_vclock_fault(const struct vm_special_mapping *sm,
+ struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ switch (vmf->pgoff) {
+#ifdef CONFIG_PARAVIRT_CLOCK
+ case VDSO_PAGE_PVCLOCK_OFFSET:
+ {
+ struct pvclock_vsyscall_time_info *pvti =
+ pvclock_get_pvti_cpu0_va();
+
+ if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK))
+ return vmf_insert_pfn_prot(vma, vmf->address,
+ __pa(pvti) >> PAGE_SHIFT,
+ pgprot_decrypted(vma->vm_page_prot));
+ break;
+ }
+#endif /* CONFIG_PARAVIRT_CLOCK */
+#ifdef CONFIG_HYPERV_TIMER
+ case VDSO_PAGE_HVCLOCK_OFFSET:
+ {
+ unsigned long pfn = hv_get_tsc_pfn();
+
+ if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
+ return vmf_insert_pfn(vma, vmf->address, pfn);
+ break;
+ }
+#endif /* CONFIG_HYPERV_TIMER */
+ }
+
+ return VM_FAULT_SIGBUS;
+}
+
static const struct vm_special_mapping vdso_mapping = {
.name = "[vdso]",
.fault = vdso_fault,
@@ -217,6 +232,10 @@ static const struct vm_special_mapping vvar_mapping = {
.name = "[vvar]",
.fault = vvar_fault,
};
+static const struct vm_special_mapping vvar_vclock_mapping = {
+ .name = "[vvar_vclock]",
+ .fault = vvar_vclock_fault,
+};
/*
* Add vdso and vvar mappings to current process.
@@ -259,7 +278,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
vma = _install_special_mapping(mm,
addr,
- -image->sym_vvar_start,
+ (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE,
VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP|
VM_PFNMAP,
&vvar_mapping);
@@ -267,11 +286,26 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
do_munmap(mm, text_start, image->size, NULL);
- } else {
- current->mm->context.vdso = (void __user *)text_start;
- current->mm->context.vdso_image = image;
+ goto up_fail;
}
+ vma = _install_special_mapping(mm,
+ addr + (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE,
+ VDSO_NR_VCLOCK_PAGES * PAGE_SIZE,
+ VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP|
+ VM_PFNMAP,
+ &vvar_vclock_mapping);
+
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
+ do_munmap(mm, text_start, image->size, NULL);
+ do_munmap(mm, addr, image->size, NULL);
+ goto up_fail;
+ }
+
+ current->mm->context.vdso = (void __user *)text_start;
+ current->mm->context.vdso_image = image;
+
up_fail:
mmap_write_unlock(mm);
return ret;
@@ -293,7 +327,8 @@ int map_vdso_once(const struct vdso_image *image, unsigned long addr)
*/
for_each_vma(vmi, vma) {
if (vma_is_special_mapping(vma, &vdso_mapping) ||
- vma_is_special_mapping(vma, &vvar_mapping)) {
+ vma_is_special_mapping(vma, &vvar_mapping) ||
+ vma_is_special_mapping(vma, &vvar_vclock_mapping)) {
mmap_write_unlock(mm);
return -EEXIST;
}
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
index 920e3a640cad..b4a1a2576510 100644
--- a/arch/x86/events/amd/core.c
+++ b/arch/x86/events/amd/core.c
@@ -943,11 +943,12 @@ static int amd_pmu_v2_snapshot_branch_stack(struct perf_branch_entry *entries, u
static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ static atomic64_t status_warned = ATOMIC64_INIT(0);
+ u64 reserved, status, mask, new_bits, prev_bits;
struct perf_sample_data data;
struct hw_perf_event *hwc;
struct perf_event *event;
int handled = 0, idx;
- u64 reserved, status, mask;
bool pmu_enabled;
/*
@@ -1012,7 +1013,12 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
* the corresponding PMCs are expected to be inactive according to the
* active_mask
*/
- WARN_ON(status > 0);
+ if (status > 0) {
+ prev_bits = atomic64_fetch_or(status, &status_warned);
+ // A new bit was set for the very first time.
+ new_bits = status & ~prev_bits;
+ WARN(new_bits, "New overflows for inactive PMCs: %llx\n", new_bits);
+ }
/* Clear overflow and freeze bits */
amd_pmu_ack_global_status(~status);
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index 0bfde2ea5cb8..49c26ce2b115 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -916,7 +916,8 @@ int amd_uncore_umc_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
u8 group_num_pmcs[UNCORE_GROUP_MAX] = { 0 };
union amd_uncore_info info;
struct amd_uncore_pmu *pmu;
- int index = 0, gid, i;
+ int gid, i;
+ u16 index = 0;
if (pmu_version < 2)
return 0;
@@ -948,7 +949,7 @@ int amd_uncore_umc_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
for_each_set_bit(gid, gmask, UNCORE_GROUP_MAX) {
for (i = 0; i < group_num_pmus[gid]; i++) {
pmu = &uncore->pmus[index];
- snprintf(pmu->name, sizeof(pmu->name), "amd_umc_%d", index);
+ snprintf(pmu->name, sizeof(pmu->name), "amd_umc_%hu", index);
pmu->num_counters = group_num_pmcs[gid] / group_num_pmus[gid];
pmu->msr_base = MSR_F19H_UMC_PERF_CTL + i * pmu->num_counters * 2;
pmu->rdpmc_base = -1;
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 65ab6460aed4..c75c482d4c52 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -3003,35 +3003,57 @@ static unsigned long code_segment_base(struct pt_regs *regs)
return 0;
}
-unsigned long perf_instruction_pointer(struct pt_regs *regs)
+unsigned long perf_arch_instruction_pointer(struct pt_regs *regs)
{
- if (perf_guest_state())
- return perf_guest_get_ip();
-
return regs->ip + code_segment_base(regs);
}
-unsigned long perf_misc_flags(struct pt_regs *regs)
+static unsigned long common_misc_flags(struct pt_regs *regs)
{
- unsigned int guest_state = perf_guest_state();
- int misc = 0;
+ if (regs->flags & PERF_EFLAGS_EXACT)
+ return PERF_RECORD_MISC_EXACT_IP;
- if (guest_state) {
- if (guest_state & PERF_GUEST_USER)
- misc |= PERF_RECORD_MISC_GUEST_USER;
- else
- misc |= PERF_RECORD_MISC_GUEST_KERNEL;
- } else {
- if (user_mode(regs))
- misc |= PERF_RECORD_MISC_USER;
- else
- misc |= PERF_RECORD_MISC_KERNEL;
- }
+ return 0;
+}
- if (regs->flags & PERF_EFLAGS_EXACT)
- misc |= PERF_RECORD_MISC_EXACT_IP;
+static unsigned long guest_misc_flags(struct pt_regs *regs)
+{
+ unsigned long guest_state = perf_guest_state();
+
+ if (!(guest_state & PERF_GUEST_ACTIVE))
+ return 0;
+
+ if (guest_state & PERF_GUEST_USER)
+ return PERF_RECORD_MISC_GUEST_USER;
+ else
+ return PERF_RECORD_MISC_GUEST_KERNEL;
+
+}
+
+static unsigned long host_misc_flags(struct pt_regs *regs)
+{
+ if (user_mode(regs))
+ return PERF_RECORD_MISC_USER;
+ else
+ return PERF_RECORD_MISC_KERNEL;
+}
+
+unsigned long perf_arch_guest_misc_flags(struct pt_regs *regs)
+{
+ unsigned long flags = common_misc_flags(regs);
+
+ flags |= guest_misc_flags(regs);
+
+ return flags;
+}
+
+unsigned long perf_arch_misc_flags(struct pt_regs *regs)
+{
+ unsigned long flags = common_misc_flags(regs);
+
+ flags |= host_misc_flags(regs);
- return misc;
+ return flags;
}
void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index d879478db3f5..bb284aff7bfd 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3962,8 +3962,8 @@ static int intel_pmu_hw_config(struct perf_event *event)
if (!(event->attr.freq || (event->attr.wakeup_events && !event->attr.watermark))) {
event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
- if (!(event->attr.sample_type &
- ~intel_pmu_large_pebs_flags(event))) {
+ if (!(event->attr.sample_type & ~intel_pmu_large_pebs_flags(event)) &&
+ !has_aux_action(event)) {
event->hw.flags |= PERF_X86_EVENT_LARGE_PEBS;
event->attach_state |= PERF_ATTACH_SCHED_CB;
}
@@ -4599,6 +4599,28 @@ static inline bool erratum_hsw11(struct perf_event *event)
X86_CONFIG(.event=0xc0, .umask=0x01);
}
+static struct event_constraint *
+arl_h_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+ struct perf_event *event)
+{
+ struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
+
+ if (pmu->pmu_type == hybrid_tiny)
+ return cmt_get_event_constraints(cpuc, idx, event);
+
+ return mtl_get_event_constraints(cpuc, idx, event);
+}
+
+static int arl_h_hw_config(struct perf_event *event)
+{
+ struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
+
+ if (pmu->pmu_type == hybrid_tiny)
+ return intel_pmu_hw_config(event);
+
+ return adl_hw_config(event);
+}
+
/*
* The HSW11 requires a period larger than 100 which is the same as the BDM11.
* A minimum period of 128 is enforced as well for the INST_RETIRED.ALL.
@@ -4924,17 +4946,26 @@ static struct x86_hybrid_pmu *find_hybrid_pmu_for_cpu(void)
/*
* This essentially just maps between the 'hybrid_cpu_type'
- * and 'hybrid_pmu_type' enums:
+ * and 'hybrid_pmu_type' enums except for ARL-H processor
+ * which needs to compare atom uarch native id since ARL-H
+ * contains two different atom uarchs.
*/
for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) {
enum hybrid_pmu_type pmu_type = x86_pmu.hybrid_pmu[i].pmu_type;
+ u32 native_id;
- if (cpu_type == HYBRID_INTEL_CORE &&
- pmu_type == hybrid_big)
- return &x86_pmu.hybrid_pmu[i];
- if (cpu_type == HYBRID_INTEL_ATOM &&
- pmu_type == hybrid_small)
+ if (cpu_type == HYBRID_INTEL_CORE && pmu_type == hybrid_big)
return &x86_pmu.hybrid_pmu[i];
+ if (cpu_type == HYBRID_INTEL_ATOM) {
+ if (x86_pmu.num_hybrid_pmus == 2 && pmu_type == hybrid_small)
+ return &x86_pmu.hybrid_pmu[i];
+
+ native_id = get_this_hybrid_cpu_native_id();
+ if (native_id == skt_native_id && pmu_type == hybrid_small)
+ return &x86_pmu.hybrid_pmu[i];
+ if (native_id == cmt_native_id && pmu_type == hybrid_tiny)
+ return &x86_pmu.hybrid_pmu[i];
+ }
}
return NULL;
@@ -5965,6 +5996,37 @@ static struct attribute *lnl_hybrid_events_attrs[] = {
NULL
};
+/* The event string must be in PMU IDX order. */
+EVENT_ATTR_STR_HYBRID(topdown-retiring,
+ td_retiring_arl_h,
+ "event=0xc2,umask=0x02;event=0x00,umask=0x80;event=0xc2,umask=0x0",
+ hybrid_big_small_tiny);
+EVENT_ATTR_STR_HYBRID(topdown-bad-spec,
+ td_bad_spec_arl_h,
+ "event=0x73,umask=0x0;event=0x00,umask=0x81;event=0x73,umask=0x0",
+ hybrid_big_small_tiny);
+EVENT_ATTR_STR_HYBRID(topdown-fe-bound,
+ td_fe_bound_arl_h,
+ "event=0x9c,umask=0x01;event=0x00,umask=0x82;event=0x71,umask=0x0",
+ hybrid_big_small_tiny);
+EVENT_ATTR_STR_HYBRID(topdown-be-bound,
+ td_be_bound_arl_h,
+ "event=0xa4,umask=0x02;event=0x00,umask=0x83;event=0x74,umask=0x0",
+ hybrid_big_small_tiny);
+
+static struct attribute *arl_h_hybrid_events_attrs[] = {
+ EVENT_PTR(slots_adl),
+ EVENT_PTR(td_retiring_arl_h),
+ EVENT_PTR(td_bad_spec_arl_h),
+ EVENT_PTR(td_fe_bound_arl_h),
+ EVENT_PTR(td_be_bound_arl_h),
+ EVENT_PTR(td_heavy_ops_adl),
+ EVENT_PTR(td_br_mis_adl),
+ EVENT_PTR(td_fetch_lat_adl),
+ EVENT_PTR(td_mem_bound_adl),
+ NULL,
+};
+
/* Must be in IDX order */
EVENT_ATTR_STR_HYBRID(mem-loads, mem_ld_adl, "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3", hybrid_big_small);
EVENT_ATTR_STR_HYBRID(mem-stores, mem_st_adl, "event=0xd0,umask=0x6;event=0xcd,umask=0x2", hybrid_big_small);
@@ -5983,6 +6045,21 @@ static struct attribute *mtl_hybrid_mem_attrs[] = {
NULL
};
+EVENT_ATTR_STR_HYBRID(mem-loads,
+ mem_ld_arl_h,
+ "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3;event=0xd0,umask=0x5,ldlat=3",
+ hybrid_big_small_tiny);
+EVENT_ATTR_STR_HYBRID(mem-stores,
+ mem_st_arl_h,
+ "event=0xd0,umask=0x6;event=0xcd,umask=0x2;event=0xd0,umask=0x6",
+ hybrid_big_small_tiny);
+
+static struct attribute *arl_h_hybrid_mem_attrs[] = {
+ EVENT_PTR(mem_ld_arl_h),
+ EVENT_PTR(mem_st_arl_h),
+ NULL,
+};
+
EVENT_ATTR_STR_HYBRID(tx-start, tx_start_adl, "event=0xc9,umask=0x1", hybrid_big);
EVENT_ATTR_STR_HYBRID(tx-commit, tx_commit_adl, "event=0xc9,umask=0x2", hybrid_big);
EVENT_ATTR_STR_HYBRID(tx-abort, tx_abort_adl, "event=0xc9,umask=0x4", hybrid_big);
@@ -6006,8 +6083,8 @@ static struct attribute *adl_hybrid_tsx_attrs[] = {
FORMAT_ATTR_HYBRID(in_tx, hybrid_big);
FORMAT_ATTR_HYBRID(in_tx_cp, hybrid_big);
-FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small);
-FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small);
+FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small_tiny);
+FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small_tiny);
FORMAT_ATTR_HYBRID(frontend, hybrid_big);
#define ADL_HYBRID_RTM_FORMAT_ATTR \
@@ -6030,7 +6107,7 @@ static struct attribute *adl_hybrid_extra_attr[] = {
NULL
};
-FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small);
+FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small_tiny);
static struct attribute *mtl_hybrid_extra_attr_rtm[] = {
ADL_HYBRID_RTM_FORMAT_ATTR,
@@ -6238,8 +6315,9 @@ static inline int intel_pmu_v6_addr_offset(int index, bool eventsel)
}
static const struct { enum hybrid_pmu_type id; char *name; } intel_hybrid_pmu_type_map[] __initconst = {
- { hybrid_small, "cpu_atom" },
- { hybrid_big, "cpu_core" },
+ { hybrid_small, "cpu_atom" },
+ { hybrid_big, "cpu_core" },
+ { hybrid_tiny, "cpu_lowpower" },
};
static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
@@ -6272,7 +6350,7 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities;
- if (pmu->pmu_type & hybrid_small) {
+ if (pmu->pmu_type & hybrid_small_tiny) {
pmu->intel_cap.perf_metrics = 0;
pmu->intel_cap.pebs_output_pt_available = 1;
pmu->mid_ack = true;
@@ -7111,6 +7189,37 @@ __init int intel_pmu_init(void)
name = "lunarlake_hybrid";
break;
+ case INTEL_ARROWLAKE_H:
+ intel_pmu_init_hybrid(hybrid_big_small_tiny);
+
+ x86_pmu.pebs_latency_data = arl_h_latency_data;
+ x86_pmu.get_event_constraints = arl_h_get_event_constraints;
+ x86_pmu.hw_config = arl_h_hw_config;
+
+ td_attr = arl_h_hybrid_events_attrs;
+ mem_attr = arl_h_hybrid_mem_attrs;
+ tsx_attr = adl_hybrid_tsx_attrs;
+ extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
+ mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr;
+
+ /* Initialize big core specific PerfMon capabilities. */
+ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX];
+ intel_pmu_init_lnc(&pmu->pmu);
+
+ /* Initialize Atom core specific PerfMon capabilities. */
+ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX];
+ intel_pmu_init_skt(&pmu->pmu);
+
+ /* Initialize Lower Power Atom specific PerfMon capabilities. */
+ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX];
+ intel_pmu_init_grt(&pmu->pmu);
+ pmu->extra_regs = intel_cmt_extra_regs;
+
+ intel_pmu_pebs_data_source_arl_h();
+ pr_cont("ArrowLake-H Hybrid events, ");
+ name = "arrowlake_h_hybrid";
+ break;
+
default:
switch (x86_pmu.version) {
case 1:
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index fa5ea65de0d0..8afc4ad3cd16 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -177,6 +177,17 @@ void __init intel_pmu_pebs_data_source_mtl(void)
__intel_pmu_pebs_data_source_cmt(data_source);
}
+void __init intel_pmu_pebs_data_source_arl_h(void)
+{
+ u64 *data_source;
+
+ intel_pmu_pebs_data_source_lnl();
+
+ data_source = x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX].pebs_data_source;
+ memcpy(data_source, pebs_data_source, sizeof(pebs_data_source));
+ __intel_pmu_pebs_data_source_cmt(data_source);
+}
+
void __init intel_pmu_pebs_data_source_cmt(void)
{
__intel_pmu_pebs_data_source_cmt(pebs_data_source);
@@ -388,6 +399,16 @@ u64 lnl_latency_data(struct perf_event *event, u64 status)
return lnc_latency_data(event, status);
}
+u64 arl_h_latency_data(struct perf_event *event, u64 status)
+{
+ struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
+
+ if (pmu->pmu_type == hybrid_tiny)
+ return cmt_latency_data(event, status);
+
+ return lnl_latency_data(event, status);
+}
+
static u64 load_latency_data(struct perf_event *event, u64 status)
{
union intel_x86_pebs_dse dse;
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index fd4670a6694e..4b0373bc8ab4 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -418,6 +418,9 @@ static void pt_config_start(struct perf_event *event)
struct pt *pt = this_cpu_ptr(&pt_ctx);
u64 ctl = event->hw.aux_config;
+ if (READ_ONCE(event->hw.aux_paused))
+ return;
+
ctl |= RTIT_CTL_TRACEEN;
if (READ_ONCE(pt->vmx_on))
perf_aux_output_flag(&pt->handle, PERF_AUX_FLAG_PARTIAL);
@@ -534,7 +537,24 @@ static void pt_config(struct perf_event *event)
reg |= (event->attr.config & PT_CONFIG_MASK);
event->hw.aux_config = reg;
+
+ /*
+ * Allow resume before starting so as not to overwrite a value set by a
+ * PMI.
+ */
+ barrier();
+ WRITE_ONCE(pt->resume_allowed, 1);
+ /* Configuration is complete, it is now OK to handle an NMI */
+ barrier();
+ WRITE_ONCE(pt->handle_nmi, 1);
+ barrier();
pt_config_start(event);
+ barrier();
+ /*
+ * Allow pause after starting so its pt_config_stop() doesn't race with
+ * pt_config_start().
+ */
+ WRITE_ONCE(pt->pause_allowed, 1);
}
static void pt_config_stop(struct perf_event *event)
@@ -828,11 +848,13 @@ static void pt_buffer_advance(struct pt_buffer *buf)
buf->cur_idx++;
if (buf->cur_idx == buf->cur->last) {
- if (buf->cur == buf->last)
+ if (buf->cur == buf->last) {
buf->cur = buf->first;
- else
+ buf->wrapped = true;
+ } else {
buf->cur = list_entry(buf->cur->list.next, struct topa,
list);
+ }
buf->cur_idx = 0;
}
}
@@ -846,8 +868,11 @@ static void pt_buffer_advance(struct pt_buffer *buf)
static void pt_update_head(struct pt *pt)
{
struct pt_buffer *buf = perf_get_aux(&pt->handle);
+ bool wrapped = buf->wrapped;
u64 topa_idx, base, old;
+ buf->wrapped = false;
+
if (buf->single) {
local_set(&buf->data_size, buf->output_off);
return;
@@ -865,7 +890,7 @@ static void pt_update_head(struct pt *pt)
} else {
old = (local64_xchg(&buf->head, base) &
((buf->nr_pages << PAGE_SHIFT) - 1));
- if (base < old)
+ if (base < old || (base == old && wrapped))
base += buf->nr_pages << PAGE_SHIFT;
local_add(base - old, &buf->data_size);
@@ -1511,6 +1536,7 @@ void intel_pt_interrupt(void)
buf = perf_aux_output_begin(&pt->handle, event);
if (!buf) {
event->hw.state = PERF_HES_STOPPED;
+ WRITE_ONCE(pt->resume_allowed, 0);
return;
}
@@ -1519,6 +1545,7 @@ void intel_pt_interrupt(void)
ret = pt_buffer_reset_markers(buf, &pt->handle);
if (ret) {
perf_aux_output_end(&pt->handle, 0);
+ WRITE_ONCE(pt->resume_allowed, 0);
return;
}
@@ -1573,6 +1600,26 @@ static void pt_event_start(struct perf_event *event, int mode)
struct pt *pt = this_cpu_ptr(&pt_ctx);
struct pt_buffer *buf;
+ if (mode & PERF_EF_RESUME) {
+ if (READ_ONCE(pt->resume_allowed)) {
+ u64 status;
+
+ /*
+ * Only if the trace is not active and the error and
+ * stopped bits are clear, is it safe to start, but a
+ * PMI might have just cleared these, so resume_allowed
+ * must be checked again also.
+ */
+ rdmsrl(MSR_IA32_RTIT_STATUS, status);
+ if (!(status & (RTIT_STATUS_TRIGGEREN |
+ RTIT_STATUS_ERROR |
+ RTIT_STATUS_STOPPED)) &&
+ READ_ONCE(pt->resume_allowed))
+ pt_config_start(event);
+ }
+ return;
+ }
+
buf = perf_aux_output_begin(&pt->handle, event);
if (!buf)
goto fail_stop;
@@ -1583,7 +1630,6 @@ static void pt_event_start(struct perf_event *event, int mode)
goto fail_end_stop;
}
- WRITE_ONCE(pt->handle_nmi, 1);
hwc->state = 0;
pt_config_buffer(buf);
@@ -1601,6 +1647,12 @@ static void pt_event_stop(struct perf_event *event, int mode)
{
struct pt *pt = this_cpu_ptr(&pt_ctx);
+ if (mode & PERF_EF_PAUSE) {
+ if (READ_ONCE(pt->pause_allowed))
+ pt_config_stop(event);
+ return;
+ }
+
/*
* Protect against the PMI racing with disabling wrmsr,
* see comment in intel_pt_interrupt().
@@ -1608,6 +1660,15 @@ static void pt_event_stop(struct perf_event *event, int mode)
WRITE_ONCE(pt->handle_nmi, 0);
barrier();
+ /*
+ * Prevent a resume from attempting to restart tracing, or a pause
+ * during a subsequent start. Do this after clearing handle_nmi so that
+ * pt_event_snapshot_aux() will not re-allow them.
+ */
+ WRITE_ONCE(pt->pause_allowed, 0);
+ WRITE_ONCE(pt->resume_allowed, 0);
+ barrier();
+
pt_config_stop(event);
if (event->hw.state == PERF_HES_STOPPED)
@@ -1657,6 +1718,10 @@ static long pt_event_snapshot_aux(struct perf_event *event,
if (WARN_ON_ONCE(!buf->snapshot))
return 0;
+ /* Prevent pause/resume from attempting to start/stop tracing */
+ WRITE_ONCE(pt->pause_allowed, 0);
+ WRITE_ONCE(pt->resume_allowed, 0);
+ barrier();
/*
* There is no PT interrupt in this mode, so stop the trace and it will
* remain stopped while the buffer is copied.
@@ -1676,8 +1741,13 @@ static long pt_event_snapshot_aux(struct perf_event *event,
* Here, handle_nmi tells us if the tracing was on.
* If the tracing was on, restart it.
*/
- if (READ_ONCE(pt->handle_nmi))
+ if (READ_ONCE(pt->handle_nmi)) {
+ WRITE_ONCE(pt->resume_allowed, 1);
+ barrier();
pt_config_start(event);
+ barrier();
+ WRITE_ONCE(pt->pause_allowed, 1);
+ }
return ret;
}
@@ -1793,7 +1863,9 @@ static __init int pt_init(void)
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
pt_pmu.pmu.capabilities = PERF_PMU_CAP_AUX_NO_SG;
- pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE;
+ pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE |
+ PERF_PMU_CAP_ITRACE |
+ PERF_PMU_CAP_AUX_PAUSE;
pt_pmu.pmu.attr_groups = pt_attr_groups;
pt_pmu.pmu.task_ctx_nr = perf_sw_context;
pt_pmu.pmu.event_init = pt_event_init;
diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h
index f5e46c04c145..7ee94fc6d7cb 100644
--- a/arch/x86/events/intel/pt.h
+++ b/arch/x86/events/intel/pt.h
@@ -65,6 +65,7 @@ struct pt_pmu {
* @head: logical write offset inside the buffer
* @snapshot: if this is for a snapshot/overwrite counter
* @single: use Single Range Output instead of ToPA
+ * @wrapped: buffer advance wrapped back to the first topa table
* @stop_pos: STOP topa entry index
* @intr_pos: INT topa entry index
* @stop_te: STOP topa entry pointer
@@ -82,6 +83,7 @@ struct pt_buffer {
local64_t head;
bool snapshot;
bool single;
+ bool wrapped;
long stop_pos, intr_pos;
struct topa_entry *stop_te, *intr_te;
void **data_pages;
@@ -117,6 +119,8 @@ struct pt_filters {
* @filters: last configured filters
* @handle_nmi: do handle PT PMI on this cpu, there's an active event
* @vmx_on: 1 if VMX is ON on this cpu
+ * @pause_allowed: PERF_EF_PAUSE is allowed to stop tracing
+ * @resume_allowed: PERF_EF_RESUME is allowed to start tracing
* @output_base: cached RTIT_OUTPUT_BASE MSR value
* @output_mask: cached RTIT_OUTPUT_MASK MSR value
*/
@@ -125,6 +129,8 @@ struct pt {
struct pt_filters filters;
int handle_nmi;
int vmx_on;
+ int pause_allowed;
+ int resume_allowed;
u64 output_base;
u64 output_mask;
};
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index ac1182141bf6..82c6f45ce975 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -668,24 +668,38 @@ enum {
#define PERF_PEBS_DATA_SOURCE_GRT_MAX 0x10
#define PERF_PEBS_DATA_SOURCE_GRT_MASK (PERF_PEBS_DATA_SOURCE_GRT_MAX - 1)
+/*
+ * CPUID.1AH.EAX[31:0] uniquely identifies the microarchitecture
+ * of the core. Bits 31-24 indicates its core type (Core or Atom)
+ * and Bits [23:0] indicates the native model ID of the core.
+ * Core type and native model ID are defined in below enumerations.
+ */
enum hybrid_cpu_type {
HYBRID_INTEL_NONE,
HYBRID_INTEL_ATOM = 0x20,
HYBRID_INTEL_CORE = 0x40,
};
+#define X86_HYBRID_PMU_ATOM_IDX 0
+#define X86_HYBRID_PMU_CORE_IDX 1
+#define X86_HYBRID_PMU_TINY_IDX 2
+
enum hybrid_pmu_type {
not_hybrid,
- hybrid_small = BIT(0),
- hybrid_big = BIT(1),
-
- hybrid_big_small = hybrid_big | hybrid_small, /* only used for matching */
+ hybrid_small = BIT(X86_HYBRID_PMU_ATOM_IDX),
+ hybrid_big = BIT(X86_HYBRID_PMU_CORE_IDX),
+ hybrid_tiny = BIT(X86_HYBRID_PMU_TINY_IDX),
+
+ /* The belows are only used for matching */
+ hybrid_big_small = hybrid_big | hybrid_small,
+ hybrid_small_tiny = hybrid_small | hybrid_tiny,
+ hybrid_big_small_tiny = hybrid_big | hybrid_small_tiny,
};
-#define X86_HYBRID_PMU_ATOM_IDX 0
-#define X86_HYBRID_PMU_CORE_IDX 1
-
-#define X86_HYBRID_NUM_PMUS 2
+enum atom_native_id {
+ cmt_native_id = 0x2, /* Crestmont */
+ skt_native_id = 0x3, /* Skymont */
+};
struct x86_hybrid_pmu {
struct pmu pmu;
@@ -1578,6 +1592,8 @@ u64 cmt_latency_data(struct perf_event *event, u64 status);
u64 lnl_latency_data(struct perf_event *event, u64 status);
+u64 arl_h_latency_data(struct perf_event *event, u64 status);
+
extern struct event_constraint intel_core2_pebs_event_constraints[];
extern struct event_constraint intel_atom_pebs_event_constraints[];
@@ -1697,6 +1713,8 @@ void intel_pmu_pebs_data_source_grt(void);
void intel_pmu_pebs_data_source_mtl(void);
+void intel_pmu_pebs_data_source_arl_h(void);
+
void intel_pmu_pebs_data_source_cmt(void);
void intel_pmu_pebs_data_source_lnl(void);
diff --git a/arch/x86/events/rapl.c b/arch/x86/events/rapl.c
index a481a939862e..a8defc813c36 100644
--- a/arch/x86/events/rapl.c
+++ b/arch/x86/events/rapl.c
@@ -148,7 +148,6 @@ struct rapl_model {
/* 1/2^hw_unit Joule */
static int rapl_hw_unit[NR_RAPL_DOMAINS] __read_mostly;
static struct rapl_pmus *rapl_pmus;
-static cpumask_t rapl_cpu_mask;
static unsigned int rapl_cntr_mask;
static u64 rapl_timer_ms;
static struct perf_msr *rapl_msrs;
@@ -369,8 +368,6 @@ static int rapl_pmu_event_init(struct perf_event *event)
if (event->cpu < 0)
return -EINVAL;
- event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG;
-
if (!cfg || cfg >= NR_RAPL_DOMAINS + 1)
return -EINVAL;
@@ -389,7 +386,6 @@ static int rapl_pmu_event_init(struct perf_event *event)
pmu = cpu_to_rapl_pmu(event->cpu);
if (!pmu)
return -EINVAL;
- event->cpu = pmu->cpu;
event->pmu_private = pmu;
event->hw.event_base = rapl_msrs[bit].msr;
event->hw.config = cfg;
@@ -403,23 +399,6 @@ static void rapl_pmu_event_read(struct perf_event *event)
rapl_event_update(event);
}
-static ssize_t rapl_get_attr_cpumask(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return cpumap_print_to_pagebuf(true, buf, &rapl_cpu_mask);
-}
-
-static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL);
-
-static struct attribute *rapl_pmu_attrs[] = {
- &dev_attr_cpumask.attr,
- NULL,
-};
-
-static struct attribute_group rapl_pmu_attr_group = {
- .attrs = rapl_pmu_attrs,
-};
-
RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");
RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");
@@ -467,7 +446,6 @@ static struct attribute_group rapl_pmu_format_group = {
};
static const struct attribute_group *rapl_attr_groups[] = {
- &rapl_pmu_attr_group,
&rapl_pmu_format_group,
&rapl_pmu_events_group,
NULL,
@@ -570,65 +548,6 @@ static struct perf_msr amd_rapl_msrs[] = {
[PERF_RAPL_PSYS] = { 0, &rapl_events_psys_group, NULL, false, 0 },
};
-static int rapl_cpu_offline(unsigned int cpu)
-{
- struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
- int target;
-
- /* Check if exiting cpu is used for collecting rapl events */
- if (!cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask))
- return 0;
-
- pmu->cpu = -1;
- /* Find a new cpu to collect rapl events */
- target = cpumask_any_but(get_rapl_pmu_cpumask(cpu), cpu);
-
- /* Migrate rapl events to the new target */
- if (target < nr_cpu_ids) {
- cpumask_set_cpu(target, &rapl_cpu_mask);
- pmu->cpu = target;
- perf_pmu_migrate_context(pmu->pmu, cpu, target);
- }
- return 0;
-}
-
-static int rapl_cpu_online(unsigned int cpu)
-{
- s32 rapl_pmu_idx = get_rapl_pmu_idx(cpu);
- if (rapl_pmu_idx < 0) {
- pr_err("topology_logical_(package/die)_id() returned a negative value");
- return -EINVAL;
- }
- struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
- int target;
-
- if (!pmu) {
- pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
- if (!pmu)
- return -ENOMEM;
-
- raw_spin_lock_init(&pmu->lock);
- INIT_LIST_HEAD(&pmu->active_list);
- pmu->pmu = &rapl_pmus->pmu;
- pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
- rapl_hrtimer_init(pmu);
-
- rapl_pmus->pmus[rapl_pmu_idx] = pmu;
- }
-
- /*
- * Check if there is an online cpu in the package which collects rapl
- * events already.
- */
- target = cpumask_any_and(&rapl_cpu_mask, get_rapl_pmu_cpumask(cpu));
- if (target < nr_cpu_ids)
- return 0;
-
- cpumask_set_cpu(cpu, &rapl_cpu_mask);
- pmu->cpu = cpu;
- return 0;
-}
-
static int rapl_check_hw_unit(struct rapl_model *rm)
{
u64 msr_rapl_power_unit_bits;
@@ -707,12 +626,41 @@ static const struct attribute_group *rapl_attr_update[] = {
NULL,
};
+static int __init init_rapl_pmu(void)
+{
+ struct rapl_pmu *pmu;
+ int idx;
+
+ for (idx = 0; idx < rapl_pmus->nr_rapl_pmu; idx++) {
+ pmu = kzalloc(sizeof(*pmu), GFP_KERNEL);
+ if (!pmu)
+ goto free;
+
+ raw_spin_lock_init(&pmu->lock);
+ INIT_LIST_HEAD(&pmu->active_list);
+ pmu->pmu = &rapl_pmus->pmu;
+ pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
+ rapl_hrtimer_init(pmu);
+
+ rapl_pmus->pmus[idx] = pmu;
+ }
+
+ return 0;
+free:
+ for (; idx > 0; idx--)
+ kfree(rapl_pmus->pmus[idx - 1]);
+ return -ENOMEM;
+}
+
static int __init init_rapl_pmus(void)
{
int nr_rapl_pmu = topology_max_packages();
+ int rapl_pmu_scope = PERF_PMU_SCOPE_PKG;
- if (!rapl_pmu_is_pkg_scope())
+ if (!rapl_pmu_is_pkg_scope()) {
nr_rapl_pmu *= topology_max_dies_per_package();
+ rapl_pmu_scope = PERF_PMU_SCOPE_DIE;
+ }
rapl_pmus = kzalloc(struct_size(rapl_pmus, pmus, nr_rapl_pmu), GFP_KERNEL);
if (!rapl_pmus)
@@ -728,9 +676,11 @@ static int __init init_rapl_pmus(void)
rapl_pmus->pmu.start = rapl_pmu_event_start;
rapl_pmus->pmu.stop = rapl_pmu_event_stop;
rapl_pmus->pmu.read = rapl_pmu_event_read;
+ rapl_pmus->pmu.scope = rapl_pmu_scope;
rapl_pmus->pmu.module = THIS_MODULE;
rapl_pmus->pmu.capabilities = PERF_PMU_CAP_NO_EXCLUDE;
- return 0;
+
+ return init_rapl_pmu();
}
static struct rapl_model model_snb = {
@@ -876,24 +826,13 @@ static int __init rapl_pmu_init(void)
if (ret)
return ret;
- /*
- * Install callbacks. Core will call them for each online cpu.
- */
- ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_RAPL_ONLINE,
- "perf/x86/rapl:online",
- rapl_cpu_online, rapl_cpu_offline);
- if (ret)
- goto out;
-
ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1);
if (ret)
- goto out1;
+ goto out;
rapl_advertise();
return 0;
-out1:
- cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
out:
pr_warn("Initialization failed (%d), disabled\n", ret);
cleanup_rapl_pmus();
@@ -903,7 +842,6 @@ module_init(rapl_pmu_init);
static void __exit intel_rapl_exit(void)
{
- cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_RAPL_ONLINE);
perf_pmu_unregister(&rapl_pmus->pmu);
cleanup_rapl_pmus();
}
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index ca9ae606aab9..dc03a647776d 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -96,16 +96,16 @@ extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
* instructions were patched in already:
*/
extern int alternatives_patched;
+struct module;
extern void alternative_instructions(void);
-extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
-extern void apply_retpolines(s32 *start, s32 *end);
-extern void apply_returns(s32 *start, s32 *end);
-extern void apply_seal_endbr(s32 *start, s32 *end);
+extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
+ struct module *mod);
+extern void apply_retpolines(s32 *start, s32 *end, struct module *mod);
+extern void apply_returns(s32 *start, s32 *end, struct module *mod);
+extern void apply_seal_endbr(s32 *start, s32 *end, struct module *mod);
extern void apply_fineibt(s32 *start_retpoline, s32 *end_retpoine,
- s32 *start_cfi, s32 *end_cfi);
-
-struct module;
+ s32 *start_cfi, s32 *end_cfi, struct module *mod);
struct callthunk_sites {
s32 *call_start, *call_end;
diff --git a/arch/x86/include/asm/asm-prototypes.h b/arch/x86/include/asm/asm-prototypes.h
index 25466c4d2134..3674006e3974 100644
--- a/arch/x86/include/asm/asm-prototypes.h
+++ b/arch/x86/include/asm/asm-prototypes.h
@@ -20,3 +20,6 @@
extern void cmpxchg8b_emu(void);
#endif
+#if defined(__GENKSYMS__) && defined(CONFIG_STACKPROTECTOR)
+extern unsigned long __ref_stack_chk_guard;
+#endif
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
index 1f650b4dde50..6c6e9b9f98a4 100644
--- a/arch/x86/include/asm/atomic64_32.h
+++ b/arch/x86/include/asm/atomic64_32.h
@@ -51,7 +51,8 @@ static __always_inline s64 arch_atomic64_read_nonatomic(const atomic64_t *v)
#ifdef CONFIG_X86_CMPXCHG64
#define __alternative_atomic64(f, g, out, in...) \
asm volatile("call %c[func]" \
- : out : [func] "i" (atomic64_##g##_cx8), ## in)
+ : ALT_OUTPUT_SP(out) \
+ : [func] "i" (atomic64_##g##_cx8), ## in)
#define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8)
#else
diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index 62cef2113ca7..fd1282a783dd 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -94,7 +94,7 @@ static __always_inline bool __try_cmpxchg64_local(volatile u64 *ptr, u64 *oldp,
asm volatile(ALTERNATIVE(_lock_loc \
"call cmpxchg8b_emu", \
_lock "cmpxchg8b %a[ptr]", X86_FEATURE_CX8) \
- : "+a" (o.low), "+d" (o.high) \
+ : ALT_OUTPUT_SP("+a" (o.low), "+d" (o.high)) \
: "b" (n.low), "c" (n.high), [ptr] "S" (_ptr) \
: "memory"); \
\
@@ -123,8 +123,8 @@ static __always_inline u64 arch_cmpxchg64_local(volatile u64 *ptr, u64 old, u64
"call cmpxchg8b_emu", \
_lock "cmpxchg8b %a[ptr]", X86_FEATURE_CX8) \
CC_SET(e) \
- : CC_OUT(e) (ret), \
- "+a" (o.low), "+d" (o.high) \
+ : ALT_OUTPUT_SP(CC_OUT(e) (ret), \
+ "+a" (o.low), "+d" (o.high)) \
: "b" (n.low), "c" (n.high), [ptr] "S" (_ptr) \
: "memory"); \
\
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index aa30fd8cad7f..98eced5084ca 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -26,12 +26,13 @@ int mwait_usable(const struct cpuinfo_x86 *);
unsigned int x86_family(unsigned int sig);
unsigned int x86_model(unsigned int sig);
unsigned int x86_stepping(unsigned int sig);
-#ifdef CONFIG_CPU_SUP_INTEL
+#ifdef CONFIG_X86_BUS_LOCK_DETECT
extern void __init sld_setup(struct cpuinfo_x86 *c);
extern bool handle_user_split_lock(struct pt_regs *regs, long error_code);
extern bool handle_guest_split_lock(unsigned long ip);
extern void handle_bus_lock(struct pt_regs *regs);
-u8 get_this_hybrid_cpu_type(void);
+void split_lock_init(void);
+void bus_lock_init(void);
#else
static inline void __init sld_setup(struct cpuinfo_x86 *c) {}
static inline bool handle_user_split_lock(struct pt_regs *regs, long error_code)
@@ -45,11 +46,23 @@ static inline bool handle_guest_split_lock(unsigned long ip)
}
static inline void handle_bus_lock(struct pt_regs *regs) {}
+static inline void split_lock_init(void) {}
+static inline void bus_lock_init(void) {}
+#endif
+#ifdef CONFIG_CPU_SUP_INTEL
+u8 get_this_hybrid_cpu_type(void);
+u32 get_this_hybrid_cpu_native_id(void);
+#else
static inline u8 get_this_hybrid_cpu_type(void)
{
return 0;
}
+
+static inline u32 get_this_hybrid_cpu_native_id(void)
+{
+ return 0;
+}
#endif
#ifdef CONFIG_IA32_FEAT_CTL
void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 913fd3a7bac6..17b6590748c0 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -317,6 +317,9 @@
#define X86_FEATURE_ZEN1 (11*32+31) /* CPU based on Zen1 microarchitecture */
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
+#define X86_FEATURE_SHA512 (12*32+ 0) /* SHA512 instructions */
+#define X86_FEATURE_SM3 (12*32+ 1) /* SM3 instructions */
+#define X86_FEATURE_SM4 (12*32+ 2) /* SM4 instructions */
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* "avx_vnni" AVX VNNI instructions */
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* "avx512_bf16" AVX512 BFLOAT16 instructions */
#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* CMPccXADD instructions */
@@ -473,7 +476,9 @@
#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* BHI_DIS_S HW control available */
#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* BHI_DIS_S HW control enabled */
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* Clear branch history at vmexit using SW loop */
-#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */
+#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */
+#define X86_FEATURE_AMD_HETEROGENEOUS_CORES (21*32 + 6) /* Heterogeneous Core Topology */
+#define X86_FEATURE_AMD_WORKLOAD_CLASS (21*32 + 7) /* Workload Classification */
/*
* BUG word(s)
diff --git a/arch/x86/include/asm/cpuid.h b/arch/x86/include/asm/cpuid.h
index ca4243318aad..239b9ba5c398 100644
--- a/arch/x86/include/asm/cpuid.h
+++ b/arch/x86/include/asm/cpuid.h
@@ -6,6 +6,8 @@
#ifndef _ASM_X86_CPUID_H
#define _ASM_X86_CPUID_H
+#include <linux/types.h>
+
#include <asm/string.h>
struct cpuid_regs {
@@ -20,11 +22,11 @@ enum cpuid_regs_idx {
};
#ifdef CONFIG_X86_32
-extern int have_cpuid_p(void);
+bool have_cpuid_p(void);
#else
-static inline int have_cpuid_p(void)
+static inline bool have_cpuid_p(void)
{
- return 1;
+ return true;
}
#endif
static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index b4d719de2c84..6e8cf0fa48fc 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -35,37 +35,21 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
}
#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
-struct ftrace_regs {
- struct pt_regs regs;
-};
+
+#include <linux/ftrace_regs.h>
static __always_inline struct pt_regs *
arch_ftrace_get_regs(struct ftrace_regs *fregs)
{
/* Only when FL_SAVE_REGS is set, cs will be non zero */
- if (!fregs->regs.cs)
+ if (!arch_ftrace_regs(fregs)->regs.cs)
return NULL;
- return &fregs->regs;
+ return &arch_ftrace_regs(fregs)->regs;
}
#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)
+ do { arch_ftrace_regs(fregs)->regs.ip = (_ip); } while (0)
+
struct ftrace_ops;
#define ftrace_graph_func ftrace_graph_func
@@ -90,7 +74,7 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
regs->orig_ax = addr;
}
#define arch_ftrace_set_direct_caller(fregs, addr) \
- __arch_ftrace_set_direct_caller(&(fregs)->regs, addr)
+ __arch_ftrace_set_direct_caller(&arch_ftrace_regs(fregs)->regs, addr)
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
#ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 99d345b686fa..6e2458088800 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -48,7 +48,9 @@ do { \
static __always_inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{
- if (!user_access_begin(uaddr, sizeof(u32)))
+ if (can_do_masked_user_access())
+ uaddr = masked_user_access_begin(uaddr);
+ else if (!user_access_begin(uaddr, sizeof(u32)))
return -EFAULT;
switch (op) {
@@ -84,7 +86,9 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
{
int ret = 0;
- if (!user_access_begin(uaddr, sizeof(u32)))
+ if (can_do_masked_user_access())
+ uaddr = masked_user_access_begin(uaddr);
+ else if (!user_access_begin(uaddr, sizeof(u32)))
return -EFAULT;
asm volatile("\n"
"1:\t" LOCK_PREFIX "cmpxchgl %3, %2\n"
diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h
index 1a42f829667a..6d7b04ffc5fd 100644
--- a/arch/x86/include/asm/intel-family.h
+++ b/arch/x86/include/asm/intel-family.h
@@ -177,10 +177,15 @@
#define INTEL_XEON_PHI_KNM IFM(6, 0x85) /* Knights Mill */
/* Family 5 */
-#define INTEL_FAM5_QUARK_X1000 0x09 /* Quark X1000 SoC */
#define INTEL_QUARK_X1000 IFM(5, 0x09) /* Quark X1000 SoC */
/* Family 19 */
#define INTEL_PANTHERCOVE_X IFM(19, 0x01) /* Diamond Rapids */
+/* CPU core types */
+enum intel_cpu_type {
+ INTEL_CPU_TYPE_ATOM = 0x20,
+ INTEL_CPU_TYPE_CORE = 0x40,
+};
+
#endif /* _ASM_X86_INTEL_FAMILY_H */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 1d60427379c9..ed580c7f9d0a 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -152,11 +152,6 @@ static inline void *phys_to_virt(phys_addr_t address)
#define phys_to_virt phys_to_virt
/*
- * Change "struct page" to physical address.
- */
-#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
-
-/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
* However, we truncate the address to unsigned int to avoid undesirable
* promotions in legacy drivers.
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index cbbef32517f0..3f1c1d6c0da1 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -12,35 +12,28 @@
#include <linux/stringify.h>
#include <linux/types.h>
-#define JUMP_TABLE_ENTRY \
+#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\" \n\t" \
_ASM_ALIGN "\n\t" \
".long 1b - . \n\t" \
- ".long %l[l_yes] - . \n\t" \
- _ASM_PTR "%c0 + %c1 - .\n\t" \
+ ".long " label " - . \n\t" \
+ _ASM_PTR " " key " - . \n\t" \
".popsection \n\t"
+/* This macro is also expanded on the Rust side. */
#ifdef CONFIG_HAVE_JUMP_LABEL_HACK
-
-static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
-{
- asm goto("1:"
- "jmp %l[l_yes] # objtool NOPs this \n\t"
- JUMP_TABLE_ENTRY
- : : "i" (key), "i" (2 | branch) : : l_yes);
-
- return false;
-l_yes:
- return true;
-}
-
+#define ARCH_STATIC_BRANCH_ASM(key, label) \
+ "1: jmp " label " # objtool NOPs this \n\t" \
+ JUMP_TABLE_ENTRY(key " + 2", label)
#else /* !CONFIG_HAVE_JUMP_LABEL_HACK */
+#define ARCH_STATIC_BRANCH_ASM(key, label) \
+ "1: .byte " __stringify(BYTES_NOP5) "\n\t" \
+ JUMP_TABLE_ENTRY(key, label)
+#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */
static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
{
- asm goto("1:"
- ".byte " __stringify(BYTES_NOP5) "\n\t"
- JUMP_TABLE_ENTRY
+ asm goto(ARCH_STATIC_BRANCH_ASM("%c0 + %c1", "%l[l_yes]")
: : "i" (key), "i" (branch) : : l_yes);
return false;
@@ -48,13 +41,11 @@ l_yes:
return true;
}
-#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */
-
static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
{
asm goto("1:"
"jmp %l[l_yes]\n\t"
- JUMP_TABLE_ENTRY
+ JUMP_TABLE_ENTRY("%c0 + %c1", "%l[l_yes]")
: : "i" (key), "i" (branch) : : l_yes);
return false;
diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
index 861d080ed4c6..5aff7222e40f 100644
--- a/arch/x86/include/asm/kvm-x86-ops.h
+++ b/arch/x86/include/asm/kvm-x86-ops.h
@@ -34,6 +34,7 @@ KVM_X86_OP(set_msr)
KVM_X86_OP(get_segment_base)
KVM_X86_OP(get_segment)
KVM_X86_OP(get_cpl)
+KVM_X86_OP(get_cpl_no_cache)
KVM_X86_OP(set_segment)
KVM_X86_OP(get_cs_db_l_bits)
KVM_X86_OP(is_valid_cr0)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6d9f763a7bb9..e159e44a6a1b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -26,6 +26,7 @@
#include <linux/irqbypass.h>
#include <linux/hyperv.h>
#include <linux/kfifo.h>
+#include <linux/sched/vhost_task.h>
#include <asm/apic.h>
#include <asm/pvclock-abi.h>
@@ -1306,7 +1307,6 @@ struct kvm_arch {
bool pre_fault_allowed;
struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
struct list_head active_mmu_pages;
- struct list_head zapped_obsolete_pages;
/*
* A list of kvm_mmu_page structs that, if zapped, could possibly be
* replaced by an NX huge page. A shadow page is on this list if its
@@ -1443,7 +1443,8 @@ struct kvm_arch {
bool sgx_provisioning_allowed;
struct kvm_x86_pmu_event_filter __rcu *pmu_event_filter;
- struct task_struct *nx_huge_page_recovery_thread;
+ struct vhost_task *nx_huge_page_recovery_thread;
+ u64 nx_huge_page_last;
#ifdef CONFIG_X86_64
/* The number of TDP MMU pages across all roots. */
@@ -1656,6 +1657,7 @@ struct kvm_x86_ops {
void (*get_segment)(struct kvm_vcpu *vcpu,
struct kvm_segment *var, int seg);
int (*get_cpl)(struct kvm_vcpu *vcpu);
+ int (*get_cpl_no_cache)(struct kvm_vcpu *vcpu);
void (*set_segment)(struct kvm_vcpu *vcpu,
struct kvm_segment *var, int seg);
void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
@@ -1955,8 +1957,8 @@ void kvm_mmu_try_split_huge_pages(struct kvm *kvm,
const struct kvm_memory_slot *memslot,
u64 start, u64 end,
int target_level);
-void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
- const struct kvm_memory_slot *memslot);
+void kvm_mmu_recover_huge_pages(struct kvm *kvm,
+ const struct kvm_memory_slot *memslot);
void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
const struct kvm_memory_slot *memslot);
void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen);
@@ -2359,7 +2361,8 @@ int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages);
KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT | \
KVM_X86_QUIRK_FIX_HYPERCALL_INSN | \
KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS | \
- KVM_X86_QUIRK_SLOT_ZAP_ALL)
+ KVM_X86_QUIRK_SLOT_ZAP_ALL | \
+ KVM_X86_QUIRK_STUFF_FEATURE_MSRS)
/*
* KVM previously used a u32 field in kvm_run to indicate the hypercall was
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 3b9970117a0f..4543cf2eb5e8 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -61,6 +61,7 @@
* - TCC bit is present in MCx_STATUS.
*/
#define MCI_CONFIG_MCAX 0x1
+#define MCI_CONFIG_FRUTEXT BIT_ULL(9)
#define MCI_IPID_MCATYPE 0xFFFF0000
#define MCI_IPID_HWID 0xFFF
@@ -122,6 +123,9 @@
#define MSR_AMD64_SMCA_MC0_DESTAT 0xc0002008
#define MSR_AMD64_SMCA_MC0_DEADDR 0xc0002009
#define MSR_AMD64_SMCA_MC0_MISC1 0xc000200a
+/* Registers MISC2 to MISC4 are at offsets B to D. */
+#define MSR_AMD64_SMCA_MC0_SYND1 0xc000200e
+#define MSR_AMD64_SMCA_MC0_SYND2 0xc000200f
#define MSR_AMD64_SMCA_MCx_CTL(x) (MSR_AMD64_SMCA_MC0_CTL + 0x10*(x))
#define MSR_AMD64_SMCA_MCx_STATUS(x) (MSR_AMD64_SMCA_MC0_STATUS + 0x10*(x))
#define MSR_AMD64_SMCA_MCx_ADDR(x) (MSR_AMD64_SMCA_MC0_ADDR + 0x10*(x))
@@ -132,6 +136,8 @@
#define MSR_AMD64_SMCA_MCx_DESTAT(x) (MSR_AMD64_SMCA_MC0_DESTAT + 0x10*(x))
#define MSR_AMD64_SMCA_MCx_DEADDR(x) (MSR_AMD64_SMCA_MC0_DEADDR + 0x10*(x))
#define MSR_AMD64_SMCA_MCx_MISCy(x, y) ((MSR_AMD64_SMCA_MC0_MISC1 + y) + (0x10*(x)))
+#define MSR_AMD64_SMCA_MCx_SYND1(x) (MSR_AMD64_SMCA_MC0_SYND1 + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_SYND2(x) (MSR_AMD64_SMCA_MC0_SYND2 + 0x10*(x))
#define XEC(x, mask) (((x) >> 16) & mask)
@@ -187,6 +193,32 @@ enum mce_notifier_prios {
MCE_PRIO_HIGHEST = MCE_PRIO_CEC
};
+/**
+ * struct mce_hw_err - Hardware Error Record.
+ * @m: Machine Check record.
+ * @vendor: Vendor-specific error information.
+ *
+ * Vendor-specific fields should not be added to struct mce. Instead, vendors
+ * should export their vendor-specific data through their structure in the
+ * vendor union below.
+ *
+ * AMD's vendor data is parsed by error decoding tools for supplemental error
+ * information. Thus, current offsets of existing fields must be maintained.
+ * Only add new fields at the end of AMD's vendor structure.
+ */
+struct mce_hw_err {
+ struct mce m;
+
+ union vendor_info {
+ struct {
+ u64 synd1; /* MCA_SYND1 MSR */
+ u64 synd2; /* MCA_SYND2 MSR */
+ } amd;
+ } vendor;
+};
+
+#define to_mce_hw_err(mce) container_of(mce, struct mce_hw_err, m)
+
struct notifier_block;
extern void mce_register_decode_chain(struct notifier_block *nb);
extern void mce_unregister_decode_chain(struct notifier_block *nb);
@@ -221,8 +253,8 @@ static inline int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info,
u64 lapic_id) { return -EINVAL; }
#endif
-void mce_prep_record(struct mce *m);
-void mce_log(struct mce *m);
+void mce_prep_record(struct mce_hw_err *err);
+void mce_log(struct mce_hw_err *err);
DECLARE_PER_CPU(struct device *, mce_device);
/* Maximum number of MCA banks per CPU. */
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 1b93ff80b43b..c9fe207916f4 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -35,7 +35,7 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
}
#define vma_alloc_zeroed_movable_folio(vma, vaddr) \
- vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr, false)
+ vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr)
#ifndef __pa
#define __pa(x) __phys_addr((unsigned long)(x))
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h
index f3d257c45225..d63576608ce7 100644
--- a/arch/x86/include/asm/page_64.h
+++ b/arch/x86/include/asm/page_64.h
@@ -17,7 +17,7 @@ extern unsigned long phys_base;
extern unsigned long page_offset_base;
extern unsigned long vmalloc_base;
extern unsigned long vmemmap_base;
-extern unsigned long physmem_end;
+extern unsigned long direct_map_physmem_end;
static __always_inline unsigned long __phys_addr_nodebug(unsigned long x)
{
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index 52f1b4ff0cc1..974688973cf6 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -6,10 +6,7 @@
#include <linux/types.h>
#include <linux/mem_encrypt.h>
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index c55a79d5feae..e525cd85f999 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -234,9 +234,10 @@ do { \
*/
#define percpu_add_op(size, qual, var, val) \
do { \
- const int pao_ID__ = (__builtin_constant_p(val) && \
- ((val) == 1 || (val) == -1)) ? \
- (int)(val) : 0; \
+ const int pao_ID__ = \
+ (__builtin_constant_p(val) && \
+ ((val) == 1 || \
+ (val) == (typeof(val))-1)) ? (int)(val) : 0; \
\
if (0) { \
typeof(var) pao_tmp__; \
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 91b73571412f..d95f902acc52 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -536,15 +536,17 @@ struct x86_perf_regs {
u64 *xmm_regs;
};
-extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
-extern unsigned long perf_misc_flags(struct pt_regs *regs);
-#define perf_misc_flags(regs) perf_misc_flags(regs)
+extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs);
+extern unsigned long perf_arch_misc_flags(struct pt_regs *regs);
+extern unsigned long perf_arch_guest_misc_flags(struct pt_regs *regs);
+#define perf_arch_misc_flags(regs) perf_arch_misc_flags(regs)
+#define perf_arch_guest_misc_flags(regs) perf_arch_guest_misc_flags(regs)
#include <asm/stacktrace.h>
/*
- * We abuse bit 3 from flags to pass exact information, see perf_misc_flags
- * and the comment with PERF_EFLAGS_EXACT.
+ * We abuse bit 3 from flags to pass exact information, see
+ * perf_arch_misc_flags() and the comment with PERF_EFLAGS_EXACT.
*/
#define perf_arch_fetch_caller_regs(regs, __ip) { \
(regs)->ip = (__ip); \
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 4c2d080d26b4..593f10aabd45 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1775,6 +1775,43 @@ bool arch_is_platform_page(u64 paddr);
#define arch_is_platform_page arch_is_platform_page
#endif
+/*
+ * Use set_p*_safe(), and elide TLB flushing, when confident that *no*
+ * TLB flush will be required as a result of the "set". For example, use
+ * in scenarios where it is known ahead of time that the routine is
+ * setting non-present entries, or re-setting an existing entry to the
+ * same value. Otherwise, use the typical "set" helpers and flush the
+ * TLB.
+ */
+#define set_pte_safe(ptep, pte) \
+({ \
+ WARN_ON_ONCE(pte_present(*ptep) && !pte_same(*ptep, pte)); \
+ set_pte(ptep, pte); \
+})
+
+#define set_pmd_safe(pmdp, pmd) \
+({ \
+ WARN_ON_ONCE(pmd_present(*pmdp) && !pmd_same(*pmdp, pmd)); \
+ set_pmd(pmdp, pmd); \
+})
+
+#define set_pud_safe(pudp, pud) \
+({ \
+ WARN_ON_ONCE(pud_present(*pudp) && !pud_same(*pudp, pud)); \
+ set_pud(pudp, pud); \
+})
+
+#define set_p4d_safe(p4dp, p4d) \
+({ \
+ WARN_ON_ONCE(p4d_present(*p4dp) && !p4d_same(*p4dp, p4d)); \
+ set_p4d(p4dp, p4d); \
+})
+
+#define set_pgd_safe(pgdp, pgd) \
+({ \
+ WARN_ON_ONCE(pgd_present(*pgdp) && !pgd_same(*pgdp, pgd)); \
+ set_pgd(pgdp, pgd); \
+})
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_PGTABLE_H */
diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h
index a98e53491a4e..ec68f8369bdc 100644
--- a/arch/x86/include/asm/pgtable_64_types.h
+++ b/arch/x86/include/asm/pgtable_64_types.h
@@ -141,7 +141,7 @@ extern unsigned int ptrs_per_p4d;
#endif /* CONFIG_DYNAMIC_MEMORY_LAYOUT */
#ifdef CONFIG_RANDOMIZE_MEMORY
-# define PHYSMEM_END physmem_end
+# define DIRECT_MAP_PHYSMEM_END direct_map_physmem_end
#endif
/*
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 4a686f0e5dbf..c0975815980c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -105,6 +105,24 @@ struct cpuinfo_topology {
// Cache level topology IDs
u32 llc_id;
u32 l2c_id;
+
+ // Hardware defined CPU-type
+ union {
+ u32 cpu_type;
+ struct {
+ // CPUID.1A.EAX[23-0]
+ u32 intel_native_model_id :24;
+ // CPUID.1A.EAX[31-24]
+ u32 intel_type :8;
+ };
+ struct {
+ // CPUID 0x80000026.EBX
+ u32 amd_num_processors :16,
+ amd_power_eff_ranking :8,
+ amd_native_model_id :4,
+ amd_type :4;
+ };
+ };
};
struct cpuinfo_x86 {
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index 4b2abce2e3e7..cc62ef70ccc0 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -89,6 +89,7 @@ int set_pages_rw(struct page *page, int numpages);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
bool kernel_page_present(struct page *page);
extern int kernel_set_to_readonly;
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 98726c2b04f8..50f5666938c0 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -220,4 +220,31 @@ struct snp_psc_desc {
#define GHCB_ERR_INVALID_INPUT 5
#define GHCB_ERR_INVALID_EVENT 6
+struct sev_config {
+ __u64 debug : 1,
+
+ /*
+ * Indicates when the per-CPU GHCB has been created and registered
+ * and thus can be used by the BSP instead of the early boot GHCB.
+ *
+ * For APs, the per-CPU GHCB is created before they are started
+ * and registered upon startup, so this flag can be used globally
+ * for the BSP and APs.
+ */
+ ghcbs_initialized : 1,
+
+ /*
+ * Indicates when the per-CPU SVSM CA is to be used instead of the
+ * boot SVSM CA.
+ *
+ * For APs, the per-CPU SVSM CA is created as part of the AP
+ * bringup, so this flag can be used globally for the BSP and APs.
+ */
+ use_cas : 1,
+
+ __reserved : 61;
+};
+
+extern struct sev_config sev_cfg;
+
#endif
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index ee34ab00a8d6..91f08af31078 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -120,6 +120,9 @@ struct snp_req_data {
};
#define MAX_AUTHTAG_LEN 32
+#define AUTHTAG_LEN 16
+#define AAD_LEN 48
+#define MSG_HDR_VER 1
/* See SNP spec SNP_GUEST_REQUEST section for the structure */
enum msg_type {
@@ -171,6 +174,19 @@ struct sev_guest_platform_data {
u64 secrets_gpa;
};
+struct snp_guest_req {
+ void *req_buf;
+ size_t req_sz;
+
+ void *resp_buf;
+ size_t resp_sz;
+
+ u64 exit_code;
+ unsigned int vmpck_id;
+ u8 msg_version;
+ u8 msg_type;
+};
+
/*
* The secrets page contains 96-bytes of reserved field that can be used by
* the guest OS. The guest OS uses the area to save the message sequence
@@ -218,6 +234,27 @@ struct snp_secrets_page {
u8 rsvd4[3744];
} __packed;
+struct snp_msg_desc {
+ /* request and response are in unencrypted memory */
+ struct snp_guest_msg *request, *response;
+
+ /*
+ * Avoid information leakage by double-buffering shared messages
+ * in fields that are in regular encrypted memory.
+ */
+ struct snp_guest_msg secret_request, secret_response;
+
+ struct snp_secrets_page *secrets;
+ struct snp_req_data input;
+
+ void *certs_data;
+
+ struct aesgcm_ctx *ctx;
+
+ u32 *os_area_msg_seqno;
+ u8 *vmpck;
+};
+
/*
* The SVSM Calling Area (CA) related structures.
*/
@@ -285,6 +322,22 @@ struct svsm_attest_call {
u8 rsvd[4];
};
+/* PTE descriptor used for the prepare_pte_enc() operations. */
+struct pte_enc_desc {
+ pte_t *kpte;
+ int pte_level;
+ bool encrypt;
+ /* pfn of the kpte above */
+ unsigned long pfn;
+ /* physical address of @pfn */
+ unsigned long pa;
+ /* virtual address of @pfn */
+ void *va;
+ /* memory covered by the pte */
+ unsigned long size;
+ pgprot_t new_pgprot;
+};
+
/*
* SVSM protocol structure
*/
@@ -392,13 +445,18 @@ void snp_set_wakeup_secondary_cpu(void);
bool snp_init(struct boot_params *bp);
void __noreturn snp_abort(void);
void snp_dmi_setup(void);
-int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
+int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input,
+ struct snp_guest_request_ioctl *rio);
int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, struct svsm_attest_call *input);
void snp_accept_memory(phys_addr_t start, phys_addr_t end);
u64 snp_get_unsupported_features(u64 status);
u64 sev_get_status(void);
void sev_show_status(void);
void snp_update_svsm_ca(void);
+int prepare_pte_enc(struct pte_enc_desc *d);
+void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot);
+void snp_kexec_finish(void);
+void snp_kexec_begin(void);
#else /* !CONFIG_AMD_MEM_ENCRYPT */
@@ -422,7 +480,8 @@ static inline void snp_set_wakeup_secondary_cpu(void) { }
static inline bool snp_init(struct boot_params *bp) { return false; }
static inline void snp_abort(void) { }
static inline void snp_dmi_setup(void) { }
-static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
+static inline int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input,
+ struct snp_guest_request_ioctl *rio)
{
return -ENOTTY;
}
@@ -435,6 +494,10 @@ static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
static inline u64 sev_get_status(void) { return 0; }
static inline void sev_show_status(void) { }
static inline void snp_update_svsm_ca(void) { }
+static inline int prepare_pte_enc(struct pte_enc_desc *d) { return 0; }
+static inline void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot) { }
+static inline void snp_kexec_finish(void) { }
+static inline void snp_kexec_begin(void) { }
#endif /* CONFIG_AMD_MEM_ENCRYPT */
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index fdfd41511b02..89f7fcade8ae 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -16,10 +16,21 @@
#define TDG_VP_VEINFO_GET 3
#define TDG_MR_REPORT 4
#define TDG_MEM_PAGE_ACCEPT 6
+#define TDG_VM_RD 7
#define TDG_VM_WR 8
-/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */
+/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
+#define TDCS_CONFIG_FLAGS 0x1110000300000016
+#define TDCS_TD_CTLS 0x1110000300000017
#define TDCS_NOTIFY_ENABLES 0x9100000000000010
+#define TDCS_TOPOLOGY_ENUM_CONFIGURED 0x9100000000000019
+
+/* TDCS_CONFIG_FLAGS bits */
+#define TDCS_CONFIG_FLEXIBLE_PENDING_VE BIT_ULL(1)
+
+/* TDCS_TD_CTLS bits */
+#define TD_CTLS_PENDING_VE_DISABLE BIT_ULL(0)
+#define TD_CTLS_ENUM_TOPOLOGY BIT_ULL(1)
/* TDX hypercall Leaf IDs */
#define TDVMCALL_MAP_GPA 0x10001
diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
index 6259f1937fe7..ab9e143ec9fe 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -35,6 +35,7 @@ extern void *text_poke(void *addr, const void *opcode, size_t len);
extern void text_poke_sync(void);
extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
extern void *text_poke_copy(void *addr, const void *opcode, size_t len);
+#define text_poke_copy text_poke_copy
extern void *text_poke_copy_locked(void *addr, const void *opcode, size_t len, bool core_ok);
extern void *text_poke_set(void *addr, int c, size_t len);
extern int poke_int3_handler(struct pt_regs *regs);
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 12da7dfd5ef1..a55c214f3ba6 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -87,8 +87,9 @@ struct thread_info {
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
-#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
-#define TIF_SSBD 5 /* Speculative store bypass disable */
+#define TIF_NEED_RESCHED_LAZY 4 /* Lazy rescheduling needed */
+#define TIF_SINGLESTEP 5 /* reenable singlestep on user return*/
+#define TIF_SSBD 6 /* Speculative store bypass disable */
#define TIF_SPEC_IB 9 /* Indirect branch speculation mitigation */
#define TIF_SPEC_L1D_FLUSH 10 /* Flush L1D on mm switches (processes) */
#define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */
@@ -110,6 +111,7 @@ struct thread_info {
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_SSBD (1 << TIF_SSBD)
#define _TIF_SPEC_IB (1 << TIF_SPEC_IB)
diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
index 7365dd4acffb..23baf8c9b34c 100644
--- a/arch/x86/include/asm/timer.h
+++ b/arch/x86/include/asm/timer.h
@@ -6,8 +6,6 @@
#include <linux/interrupt.h>
#include <linux/math64.h>
-#define TICK_SIZE (tick_nsec / 1000)
-
unsigned long long native_sched_clock(void);
extern void recalibrate_cpu_khz(void);
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index 580636cdc257..4d3c9d00d6b6 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -34,4 +34,8 @@ static inline void __tlb_remove_table(void *table)
free_page_and_swap_cache(table);
}
+static inline void invlpg(unsigned long addr)
+{
+ asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
+}
#endif /* _ASM_X86_TLB_H */
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index aef70336d624..fd41103ad342 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -114,6 +114,12 @@ enum x86_topology_domains {
TOPO_MAX_DOMAIN,
};
+enum x86_topology_cpu_type {
+ TOPO_CPU_TYPE_PERFORMANCE,
+ TOPO_CPU_TYPE_EFFICIENCY,
+ TOPO_CPU_TYPE_UNKNOWN,
+};
+
struct x86_topology_system {
unsigned int dom_shifts[TOPO_MAX_DOMAIN];
unsigned int dom_size[TOPO_MAX_DOMAIN];
@@ -149,6 +155,9 @@ extern unsigned int __max_threads_per_core;
extern unsigned int __num_threads_per_package;
extern unsigned int __num_cores_per_package;
+const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c);
+enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c);
+
static inline unsigned int topology_max_packages(void)
{
return __max_logical_packages;
@@ -305,9 +314,4 @@ static inline void freq_invariance_set_perf_ratio(u64 ratio, bool turbo_disabled
extern void arch_scale_freq_tick(void);
#define arch_scale_freq_tick arch_scale_freq_tick
-#ifdef CONFIG_ACPI_CPPC_LIB
-void init_freq_invariance_cppc(void);
-#define arch_init_invariance_cppc init_freq_invariance_cppc
-#endif
-
#endif /* _ASM_X86_TOPOLOGY_H */
diff --git a/arch/x86/include/asm/vdso/getrandom.h b/arch/x86/include/asm/vdso/getrandom.h
index ff5334ad32a0..2bf9c0e970c3 100644
--- a/arch/x86/include/asm/vdso/getrandom.h
+++ b/arch/x86/include/asm/vdso/getrandom.h
@@ -8,7 +8,6 @@
#ifndef __ASSEMBLY__
#include <asm/unistd.h>
-#include <asm/vvar.h>
/**
* getrandom_syscall - Invoke the getrandom() syscall.
@@ -28,13 +27,14 @@ static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsig
return ret;
}
-#define __vdso_rng_data (VVAR(_vdso_rng_data))
+extern struct vdso_rng_data vdso_rng_data
+ __attribute__((visibility("hidden")));
static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{
- if (IS_ENABLED(CONFIG_TIME_NS) && __vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS)
- return (void *)&__vdso_rng_data + ((void *)&__timens_vdso_data - (void *)&__vdso_data);
- return &__vdso_rng_data;
+ if (IS_ENABLED(CONFIG_TIME_NS) && __arch_get_vdso_data()->clock_mode == VDSO_CLOCKMODE_TIMENS)
+ return (void *)&vdso_rng_data + ((void *)&timens_page - (void *)__arch_get_vdso_data());
+ return &vdso_rng_data;
}
#endif /* !__ASSEMBLY__ */
diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h
index b2d2df026f6e..375a34b0f365 100644
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -14,14 +14,16 @@
#include <uapi/linux/time.h>
#include <asm/vgtod.h>
-#include <asm/vvar.h>
#include <asm/unistd.h>
#include <asm/msr.h>
#include <asm/pvclock.h>
#include <clocksource/hyperv_timer.h>
-#define __vdso_data (VVAR(_vdso_data))
-#define __timens_vdso_data (TIMENS(_vdso_data))
+extern struct vdso_data vvar_page
+ __attribute__((visibility("hidden")));
+
+extern struct vdso_data timens_page
+ __attribute__((visibility("hidden")));
#define VDSO_HAS_TIME 1
@@ -61,7 +63,7 @@ extern struct ms_hyperv_tsc_page hvclock_page
static __always_inline
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
{
- return __timens_vdso_data;
+ return &timens_page;
}
#endif
@@ -275,7 +277,7 @@ static inline u64 __arch_get_hw_counter(s32 clock_mode,
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{
- return __vdso_data;
+ return &vvar_page;
}
static inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd)
diff --git a/arch/x86/include/asm/vdso/vsyscall.h b/arch/x86/include/asm/vdso/vsyscall.h
index 67fedf1698b5..37b4a70559a8 100644
--- a/arch/x86/include/asm/vdso/vsyscall.h
+++ b/arch/x86/include/asm/vdso/vsyscall.h
@@ -2,12 +2,19 @@
#ifndef __ASM_VDSO_VSYSCALL_H
#define __ASM_VDSO_VSYSCALL_H
+#define __VDSO_RND_DATA_OFFSET 640
+#define __VVAR_PAGES 4
+
+#define VDSO_NR_VCLOCK_PAGES 2
+#define VDSO_PAGE_PVCLOCK_OFFSET 0
+#define VDSO_PAGE_HVCLOCK_OFFSET 1
+
#ifndef __ASSEMBLY__
-#include <linux/timekeeper_internal.h>
#include <vdso/datapage.h>
#include <asm/vgtod.h>
-#include <asm/vvar.h>
+
+extern struct vdso_data *vdso_data;
/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
@@ -15,14 +22,14 @@
static __always_inline
struct vdso_data *__x86_get_k_vdso_data(void)
{
- return _vdso_data;
+ return vdso_data;
}
#define __arch_get_k_vdso_data __x86_get_k_vdso_data
static __always_inline
struct vdso_rng_data *__x86_get_k_vdso_rng_data(void)
{
- return &_vdso_rng_data;
+ return (void *)vdso_data + __VDSO_RND_DATA_OFFSET;
}
#define __arch_get_k_vdso_rng_data __x86_get_k_vdso_rng_data
diff --git a/arch/x86/include/asm/vvar.h b/arch/x86/include/asm/vvar.h
deleted file mode 100644
index 9d9af37f7cab..000000000000
--- a/arch/x86/include/asm/vvar.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vvar.h: Shared vDSO/kernel variable declarations
- * Copyright (c) 2011 Andy Lutomirski
- *
- * A handful of variables are accessible (read-only) from userspace
- * code in the vsyscall page and the vdso. They are declared here.
- * Some other file must define them with DEFINE_VVAR.
- *
- * In normal kernel code, they are used like any other variable.
- * In user code, they are accessed through the VVAR macro.
- *
- * These variables live in a page of kernel data that has an extra RO
- * mapping for userspace. Each variable needs a unique offset within
- * that page; specify that offset with the DECLARE_VVAR macro. (If
- * you mess up, the linker will catch it.)
- */
-
-#ifndef _ASM_X86_VVAR_H
-#define _ASM_X86_VVAR_H
-
-#ifdef EMIT_VVAR
-/*
- * EMIT_VVAR() is used by the kernel linker script to put vvars in the
- * right place. Also, it's used by kernel code to import offsets values.
- */
-#define DECLARE_VVAR(offset, type, name) \
- EMIT_VVAR(name, offset)
-#define DECLARE_VVAR_SINGLE(offset, type, name) \
- EMIT_VVAR(name, offset)
-
-#else
-
-extern char __vvar_page;
-
-#define DECLARE_VVAR(offset, type, name) \
- extern type vvar_ ## name[CS_BASES] \
- __attribute__((visibility("hidden"))); \
- extern type timens_ ## name[CS_BASES] \
- __attribute__((visibility("hidden"))); \
-
-#define DECLARE_VVAR_SINGLE(offset, type, name) \
- extern type vvar_ ## name \
- __attribute__((visibility("hidden"))); \
-
-#define VVAR(name) (vvar_ ## name)
-#define TIMENS(name) (timens_ ## name)
-
-#define DEFINE_VVAR(type, name) \
- type name[CS_BASES] \
- __attribute__((section(".vvar_" #name), aligned(16))) __visible
-
-#define DEFINE_VVAR_SINGLE(type, name) \
- type name \
- __attribute__((section(".vvar_" #name), aligned(16))) __visible
-
-#endif
-
-/* DECLARE_VVAR(offset, type, name) */
-
-DECLARE_VVAR(128, struct vdso_data, _vdso_data)
-
-#if !defined(_SINGLE_DATA)
-#define _SINGLE_DATA
-DECLARE_VVAR_SINGLE(640, struct vdso_rng_data, _vdso_rng_data)
-#endif
-
-#undef DECLARE_VVAR
-#undef DECLARE_VVAR_SINGLE
-
-#endif
diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h
index e5d182c7373c..4a7cace06204 100644
--- a/arch/x86/include/uapi/asm/amd_hsmp.h
+++ b/arch/x86/include/uapi/asm/amd_hsmp.h
@@ -88,7 +88,8 @@ struct hsmp_msg_desc {
*
* Not supported messages would return -ENOMSG.
*/
-static const struct hsmp_msg_desc hsmp_msg_desc_table[] = {
+static const struct hsmp_msg_desc hsmp_msg_desc_table[]
+ __attribute__((unused)) = {
/* RESERVED */
{0, 0, HSMP_RSVD},
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index a8debbf2f702..88585c1de416 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -440,6 +440,7 @@ struct kvm_sync_regs {
#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5)
#define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6)
#define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7)
+#define KVM_X86_QUIRK_STUFF_FEATURE_MSRS (1 << 8)
#define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1
diff --git a/arch/x86/include/uapi/asm/mce.h b/arch/x86/include/uapi/asm/mce.h
index db9adc081c5a..cb6b48a7c22b 100644
--- a/arch/x86/include/uapi/asm/mce.h
+++ b/arch/x86/include/uapi/asm/mce.h
@@ -8,7 +8,8 @@
/*
* Fields are zero when not available. Also, this struct is shared with
* userspace mcelog and thus must keep existing fields at current offsets.
- * Only add new fields to the end of the structure
+ * Only add new, shared fields to the end of the structure.
+ * Do not add vendor-specific fields.
*/
struct mce {
__u64 status; /* Bank's MCi_STATUS MSR */
diff --git a/arch/x86/include/uapi/asm/mman.h b/arch/x86/include/uapi/asm/mman.h
index 46cdc941f958..ac1e6277212b 100644
--- a/arch/x86/include/uapi/asm/mman.h
+++ b/arch/x86/include/uapi/asm/mman.h
@@ -5,9 +5,6 @@
#define MAP_32BIT 0x40 /* only give out 32bit addresses */
#define MAP_ABOVE4G 0x80 /* only map above 4GB */
-/* Flags for map_shadow_stack(2) */
-#define SHADOW_STACK_SET_TOKEN (1ULL << 0) /* Set up a restore token in the shadow stack */
-
#include <asm-generic/mman.h>
#endif /* _ASM_X86_MMAN_H */
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 4efecac49863..3a44a9dc3fb7 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1171,7 +1171,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
}
count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
- acpi_parse_int_src_ovr, nr_irqs);
+ acpi_parse_int_src_ovr,
+ irq_get_nr_irqs());
if (count < 0) {
pr_err("Error parsing interrupt source overrides entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -1191,7 +1192,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
mp_config_acpi_legacy_irqs();
count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
- acpi_parse_nmi_src, nr_irqs);
+ acpi_parse_nmi_src,
+ irq_get_nr_irqs());
if (count < 0) {
pr_err("Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c
index 956984054bf3..d745dd586303 100644
--- a/arch/x86/kernel/acpi/cppc.c
+++ b/arch/x86/kernel/acpi/cppc.c
@@ -110,7 +110,7 @@ static void amd_set_max_freq_ratio(void)
static DEFINE_MUTEX(freq_invariance_lock);
-void init_freq_invariance_cppc(void)
+static inline void init_freq_invariance_cppc(void)
{
static bool init_done;
@@ -127,6 +127,11 @@ void init_freq_invariance_cppc(void)
mutex_unlock(&freq_invariance_lock);
}
+void acpi_processor_init_invariance_cppc(void)
+{
+ init_freq_invariance_cppc();
+}
+
/*
* Get the highest performance register value.
* @cpu: CPU from which to get highest performance.
@@ -234,8 +239,10 @@ EXPORT_SYMBOL_GPL(amd_detect_prefcore);
*/
int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
{
+ enum x86_topology_cpu_type core_type = get_topology_cpu_type(&cpu_data(cpu));
bool prefcore;
int ret;
+ u32 tmp;
ret = amd_detect_prefcore(&prefcore);
if (ret)
@@ -261,6 +268,27 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
break;
}
}
+
+ /* detect if running on heterogeneous design */
+ if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) {
+ switch (core_type) {
+ case TOPO_CPU_TYPE_UNKNOWN:
+ pr_warn("Undefined core type found for cpu %d\n", cpu);
+ break;
+ case TOPO_CPU_TYPE_PERFORMANCE:
+ /* use the max scale for performance cores */
+ *numerator = CPPC_HIGHEST_PERF_PERFORMANCE;
+ return 0;
+ case TOPO_CPU_TYPE_EFFICIENCY:
+ /* use the highest perf value for efficiency cores */
+ ret = amd_get_highest_perf(cpu, &tmp);
+ if (ret)
+ return ret;
+ *numerator = tmp;
+ return 0;
+ }
+ }
+
*numerator = CPPC_HIGHEST_PERF_PREFCORE;
return 0;
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 94ff83f3d3fe..b200a193beeb 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -87,6 +87,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
.align 4
.Lresume_point:
+ ANNOTATE_NOENDBR
/* We don't restore %rax, it must be 0 anyway */
movq $saved_context, %rax
movq saved_context_cr4(%rax), %rbx
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index d17518ca19b8..243843e44e89 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -392,8 +392,10 @@ EXPORT_SYMBOL(BUG_func);
* Rewrite the "call BUG_func" replacement to point to the target of the
* indirect pv_ops call "call *disp(%ip)".
*/
-static int alt_replace_call(u8 *instr, u8 *insn_buff, struct alt_instr *a)
+static int alt_replace_call(u8 *instr, u8 *insn_buff, struct alt_instr *a,
+ struct module *mod)
{
+ u8 *wr_instr = module_writable_address(mod, instr);
void *target, *bug = &BUG_func;
s32 disp;
@@ -403,14 +405,14 @@ static int alt_replace_call(u8 *instr, u8 *insn_buff, struct alt_instr *a)
}
if (a->instrlen != 6 ||
- instr[0] != CALL_RIP_REL_OPCODE ||
- instr[1] != CALL_RIP_REL_MODRM) {
+ wr_instr[0] != CALL_RIP_REL_OPCODE ||
+ wr_instr[1] != CALL_RIP_REL_MODRM) {
pr_err("ALT_FLAG_DIRECT_CALL set for unrecognized indirect call\n");
BUG();
}
/* Skip CALL_RIP_REL_OPCODE and CALL_RIP_REL_MODRM */
- disp = *(s32 *)(instr + 2);
+ disp = *(s32 *)(wr_instr + 2);
#ifdef CONFIG_X86_64
/* ff 15 00 00 00 00 call *0x0(%rip) */
/* target address is stored at "next instruction + disp". */
@@ -448,7 +450,8 @@ static inline u8 * instr_va(struct alt_instr *i)
* to refetch changed I$ lines.
*/
void __init_or_module noinline apply_alternatives(struct alt_instr *start,
- struct alt_instr *end)
+ struct alt_instr *end,
+ struct module *mod)
{
u8 insn_buff[MAX_PATCH_LEN];
u8 *instr, *replacement;
@@ -477,6 +480,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
*/
for (a = start; a < end; a++) {
int insn_buff_sz = 0;
+ u8 *wr_instr, *wr_replacement;
/*
* In case of nested ALTERNATIVE()s the outer alternative might
@@ -490,7 +494,11 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
}
instr = instr_va(a);
+ wr_instr = module_writable_address(mod, instr);
+
replacement = (u8 *)&a->repl_offset + a->repl_offset;
+ wr_replacement = module_writable_address(mod, replacement);
+
BUG_ON(a->instrlen > sizeof(insn_buff));
BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
@@ -501,9 +509,9 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
* patch if feature is *NOT* present.
*/
if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT)) {
- memcpy(insn_buff, instr, a->instrlen);
+ memcpy(insn_buff, wr_instr, a->instrlen);
optimize_nops(instr, insn_buff, a->instrlen);
- text_poke_early(instr, insn_buff, a->instrlen);
+ text_poke_early(wr_instr, insn_buff, a->instrlen);
continue;
}
@@ -513,11 +521,12 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
instr, instr, a->instrlen,
replacement, a->replacementlen, a->flags);
- memcpy(insn_buff, replacement, a->replacementlen);
+ memcpy(insn_buff, wr_replacement, a->replacementlen);
insn_buff_sz = a->replacementlen;
if (a->flags & ALT_FLAG_DIRECT_CALL) {
- insn_buff_sz = alt_replace_call(instr, insn_buff, a);
+ insn_buff_sz = alt_replace_call(instr, insn_buff, a,
+ mod);
if (insn_buff_sz < 0)
continue;
}
@@ -527,11 +536,11 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
apply_relocation(insn_buff, instr, a->instrlen, replacement, a->replacementlen);
- DUMP_BYTES(ALT, instr, a->instrlen, "%px: old_insn: ", instr);
+ DUMP_BYTES(ALT, wr_instr, a->instrlen, "%px: old_insn: ", instr);
DUMP_BYTES(ALT, replacement, a->replacementlen, "%px: rpl_insn: ", replacement);
DUMP_BYTES(ALT, insn_buff, insn_buff_sz, "%px: final_insn: ", instr);
- text_poke_early(instr, insn_buff, insn_buff_sz);
+ text_poke_early(wr_instr, insn_buff, insn_buff_sz);
}
kasan_enable_current();
@@ -722,18 +731,20 @@ static int patch_retpoline(void *addr, struct insn *insn, u8 *bytes)
/*
* Generated by 'objtool --retpoline'.
*/
-void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
+void __init_or_module noinline apply_retpolines(s32 *start, s32 *end,
+ struct module *mod)
{
s32 *s;
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr = module_writable_address(mod, addr);
struct insn insn;
int len, ret;
u8 bytes[16];
u8 op1, op2;
- ret = insn_decode_kernel(&insn, addr);
+ ret = insn_decode_kernel(&insn, wr_addr);
if (WARN_ON_ONCE(ret < 0))
continue;
@@ -761,9 +772,9 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
len = patch_retpoline(addr, &insn, bytes);
if (len == insn.length) {
optimize_nops(addr, bytes, len);
- DUMP_BYTES(RETPOLINE, ((u8*)addr), len, "%px: orig: ", addr);
+ DUMP_BYTES(RETPOLINE, ((u8*)wr_addr), len, "%px: orig: ", addr);
DUMP_BYTES(RETPOLINE, ((u8*)bytes), len, "%px: repl: ", addr);
- text_poke_early(addr, bytes, len);
+ text_poke_early(wr_addr, bytes, len);
}
}
}
@@ -799,7 +810,8 @@ static int patch_return(void *addr, struct insn *insn, u8 *bytes)
return i;
}
-void __init_or_module noinline apply_returns(s32 *start, s32 *end)
+void __init_or_module noinline apply_returns(s32 *start, s32 *end,
+ struct module *mod)
{
s32 *s;
@@ -808,12 +820,13 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end)
for (s = start; s < end; s++) {
void *dest = NULL, *addr = (void *)s + *s;
+ void *wr_addr = module_writable_address(mod, addr);
struct insn insn;
int len, ret;
u8 bytes[16];
u8 op;
- ret = insn_decode_kernel(&insn, addr);
+ ret = insn_decode_kernel(&insn, wr_addr);
if (WARN_ON_ONCE(ret < 0))
continue;
@@ -833,32 +846,35 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end)
len = patch_return(addr, &insn, bytes);
if (len == insn.length) {
- DUMP_BYTES(RET, ((u8*)addr), len, "%px: orig: ", addr);
+ DUMP_BYTES(RET, ((u8*)wr_addr), len, "%px: orig: ", addr);
DUMP_BYTES(RET, ((u8*)bytes), len, "%px: repl: ", addr);
- text_poke_early(addr, bytes, len);
+ text_poke_early(wr_addr, bytes, len);
}
}
}
#else
-void __init_or_module noinline apply_returns(s32 *start, s32 *end) { }
+void __init_or_module noinline apply_returns(s32 *start, s32 *end,
+ struct module *mod) { }
#endif /* CONFIG_MITIGATION_RETHUNK */
#else /* !CONFIG_MITIGATION_RETPOLINE || !CONFIG_OBJTOOL */
-void __init_or_module noinline apply_retpolines(s32 *start, s32 *end) { }
-void __init_or_module noinline apply_returns(s32 *start, s32 *end) { }
+void __init_or_module noinline apply_retpolines(s32 *start, s32 *end,
+ struct module *mod) { }
+void __init_or_module noinline apply_returns(s32 *start, s32 *end,
+ struct module *mod) { }
#endif /* CONFIG_MITIGATION_RETPOLINE && CONFIG_OBJTOOL */
#ifdef CONFIG_X86_KERNEL_IBT
-static void poison_cfi(void *addr);
+static void poison_cfi(void *addr, void *wr_addr);
-static void __init_or_module poison_endbr(void *addr, bool warn)
+static void __init_or_module poison_endbr(void *addr, void *wr_addr, bool warn)
{
u32 endbr, poison = gen_endbr_poison();
- if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr)))
+ if (WARN_ON_ONCE(get_kernel_nofault(endbr, wr_addr)))
return;
if (!is_endbr(endbr)) {
@@ -873,7 +889,7 @@ static void __init_or_module poison_endbr(void *addr, bool warn)
*/
DUMP_BYTES(ENDBR, ((u8*)addr), 4, "%px: orig: ", addr);
DUMP_BYTES(ENDBR, ((u8*)&poison), 4, "%px: repl: ", addr);
- text_poke_early(addr, &poison, 4);
+ text_poke_early(wr_addr, &poison, 4);
}
/*
@@ -882,22 +898,23 @@ static void __init_or_module poison_endbr(void *addr, bool warn)
* Seal the functions for indirect calls by clobbering the ENDBR instructions
* and the kCFI hash value.
*/
-void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end)
+void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end, struct module *mod)
{
s32 *s;
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr = module_writable_address(mod, addr);
- poison_endbr(addr, true);
+ poison_endbr(addr, wr_addr, true);
if (IS_ENABLED(CONFIG_FINEIBT))
- poison_cfi(addr - 16);
+ poison_cfi(addr - 16, wr_addr - 16);
}
}
#else
-void __init_or_module apply_seal_endbr(s32 *start, s32 *end) { }
+void __init_or_module apply_seal_endbr(s32 *start, s32 *end, struct module *mod) { }
#endif /* CONFIG_X86_KERNEL_IBT */
@@ -1119,7 +1136,7 @@ static u32 decode_caller_hash(void *addr)
}
/* .retpoline_sites */
-static int cfi_disable_callers(s32 *start, s32 *end)
+static int cfi_disable_callers(s32 *start, s32 *end, struct module *mod)
{
/*
* Disable kCFI by patching in a JMP.d8, this leaves the hash immediate
@@ -1131,20 +1148,23 @@ static int cfi_disable_callers(s32 *start, s32 *end)
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr;
u32 hash;
addr -= fineibt_caller_size;
- hash = decode_caller_hash(addr);
+ wr_addr = module_writable_address(mod, addr);
+ hash = decode_caller_hash(wr_addr);
+
if (!hash) /* nocfi callers */
continue;
- text_poke_early(addr, jmp, 2);
+ text_poke_early(wr_addr, jmp, 2);
}
return 0;
}
-static int cfi_enable_callers(s32 *start, s32 *end)
+static int cfi_enable_callers(s32 *start, s32 *end, struct module *mod)
{
/*
* Re-enable kCFI, undo what cfi_disable_callers() did.
@@ -1154,106 +1174,115 @@ static int cfi_enable_callers(s32 *start, s32 *end)
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr;
u32 hash;
addr -= fineibt_caller_size;
- hash = decode_caller_hash(addr);
+ wr_addr = module_writable_address(mod, addr);
+ hash = decode_caller_hash(wr_addr);
if (!hash) /* nocfi callers */
continue;
- text_poke_early(addr, mov, 2);
+ text_poke_early(wr_addr, mov, 2);
}
return 0;
}
/* .cfi_sites */
-static int cfi_rand_preamble(s32 *start, s32 *end)
+static int cfi_rand_preamble(s32 *start, s32 *end, struct module *mod)
{
s32 *s;
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr = module_writable_address(mod, addr);
u32 hash;
- hash = decode_preamble_hash(addr);
+ hash = decode_preamble_hash(wr_addr);
if (WARN(!hash, "no CFI hash found at: %pS %px %*ph\n",
addr, addr, 5, addr))
return -EINVAL;
hash = cfi_rehash(hash);
- text_poke_early(addr + 1, &hash, 4);
+ text_poke_early(wr_addr + 1, &hash, 4);
}
return 0;
}
-static int cfi_rewrite_preamble(s32 *start, s32 *end)
+static int cfi_rewrite_preamble(s32 *start, s32 *end, struct module *mod)
{
s32 *s;
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr = module_writable_address(mod, addr);
u32 hash;
- hash = decode_preamble_hash(addr);
+ hash = decode_preamble_hash(wr_addr);
if (WARN(!hash, "no CFI hash found at: %pS %px %*ph\n",
addr, addr, 5, addr))
return -EINVAL;
- text_poke_early(addr, fineibt_preamble_start, fineibt_preamble_size);
- WARN_ON(*(u32 *)(addr + fineibt_preamble_hash) != 0x12345678);
- text_poke_early(addr + fineibt_preamble_hash, &hash, 4);
+ text_poke_early(wr_addr, fineibt_preamble_start, fineibt_preamble_size);
+ WARN_ON(*(u32 *)(wr_addr + fineibt_preamble_hash) != 0x12345678);
+ text_poke_early(wr_addr + fineibt_preamble_hash, &hash, 4);
}
return 0;
}
-static void cfi_rewrite_endbr(s32 *start, s32 *end)
+static void cfi_rewrite_endbr(s32 *start, s32 *end, struct module *mod)
{
s32 *s;
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr = module_writable_address(mod, addr);
- poison_endbr(addr+16, false);
+ poison_endbr(addr + 16, wr_addr + 16, false);
}
}
/* .retpoline_sites */
-static int cfi_rand_callers(s32 *start, s32 *end)
+static int cfi_rand_callers(s32 *start, s32 *end, struct module *mod)
{
s32 *s;
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr;
u32 hash;
addr -= fineibt_caller_size;
- hash = decode_caller_hash(addr);
+ wr_addr = module_writable_address(mod, addr);
+ hash = decode_caller_hash(wr_addr);
if (hash) {
hash = -cfi_rehash(hash);
- text_poke_early(addr + 2, &hash, 4);
+ text_poke_early(wr_addr + 2, &hash, 4);
}
}
return 0;
}
-static int cfi_rewrite_callers(s32 *start, s32 *end)
+static int cfi_rewrite_callers(s32 *start, s32 *end, struct module *mod)
{
s32 *s;
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
+ void *wr_addr;
u32 hash;
addr -= fineibt_caller_size;
- hash = decode_caller_hash(addr);
+ wr_addr = module_writable_address(mod, addr);
+ hash = decode_caller_hash(wr_addr);
if (hash) {
- text_poke_early(addr, fineibt_caller_start, fineibt_caller_size);
- WARN_ON(*(u32 *)(addr + fineibt_caller_hash) != 0x12345678);
- text_poke_early(addr + fineibt_caller_hash, &hash, 4);
+ text_poke_early(wr_addr, fineibt_caller_start, fineibt_caller_size);
+ WARN_ON(*(u32 *)(wr_addr + fineibt_caller_hash) != 0x12345678);
+ text_poke_early(wr_addr + fineibt_caller_hash, &hash, 4);
}
/* rely on apply_retpolines() */
}
@@ -1262,8 +1291,9 @@ static int cfi_rewrite_callers(s32 *start, s32 *end)
}
static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
- s32 *start_cfi, s32 *end_cfi, bool builtin)
+ s32 *start_cfi, s32 *end_cfi, struct module *mod)
{
+ bool builtin = mod ? false : true;
int ret;
if (WARN_ONCE(fineibt_preamble_size != 16,
@@ -1281,7 +1311,7 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
* rewrite them. This disables all CFI. If this succeeds but any of the
* later stages fails, we're without CFI.
*/
- ret = cfi_disable_callers(start_retpoline, end_retpoline);
+ ret = cfi_disable_callers(start_retpoline, end_retpoline, mod);
if (ret)
goto err;
@@ -1292,11 +1322,11 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
cfi_bpf_subprog_hash = cfi_rehash(cfi_bpf_subprog_hash);
}
- ret = cfi_rand_preamble(start_cfi, end_cfi);
+ ret = cfi_rand_preamble(start_cfi, end_cfi, mod);
if (ret)
goto err;
- ret = cfi_rand_callers(start_retpoline, end_retpoline);
+ ret = cfi_rand_callers(start_retpoline, end_retpoline, mod);
if (ret)
goto err;
}
@@ -1308,7 +1338,7 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
return;
case CFI_KCFI:
- ret = cfi_enable_callers(start_retpoline, end_retpoline);
+ ret = cfi_enable_callers(start_retpoline, end_retpoline, mod);
if (ret)
goto err;
@@ -1318,17 +1348,17 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
case CFI_FINEIBT:
/* place the FineIBT preamble at func()-16 */
- ret = cfi_rewrite_preamble(start_cfi, end_cfi);
+ ret = cfi_rewrite_preamble(start_cfi, end_cfi, mod);
if (ret)
goto err;
/* rewrite the callers to target func()-16 */
- ret = cfi_rewrite_callers(start_retpoline, end_retpoline);
+ ret = cfi_rewrite_callers(start_retpoline, end_retpoline, mod);
if (ret)
goto err;
/* now that nobody targets func()+0, remove ENDBR there */
- cfi_rewrite_endbr(start_cfi, end_cfi);
+ cfi_rewrite_endbr(start_cfi, end_cfi, mod);
if (builtin)
pr_info("Using FineIBT CFI\n");
@@ -1347,7 +1377,7 @@ static inline void poison_hash(void *addr)
*(u32 *)addr = 0;
}
-static void poison_cfi(void *addr)
+static void poison_cfi(void *addr, void *wr_addr)
{
switch (cfi_mode) {
case CFI_FINEIBT:
@@ -1359,8 +1389,8 @@ static void poison_cfi(void *addr)
* ud2
* 1: nop
*/
- poison_endbr(addr, false);
- poison_hash(addr + fineibt_preamble_hash);
+ poison_endbr(addr, wr_addr, false);
+ poison_hash(wr_addr + fineibt_preamble_hash);
break;
case CFI_KCFI:
@@ -1369,7 +1399,7 @@ static void poison_cfi(void *addr)
* movl $0, %eax
* .skip 11, 0x90
*/
- poison_hash(addr + 1);
+ poison_hash(wr_addr + 1);
break;
default:
@@ -1380,22 +1410,21 @@ static void poison_cfi(void *addr)
#else
static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
- s32 *start_cfi, s32 *end_cfi, bool builtin)
+ s32 *start_cfi, s32 *end_cfi, struct module *mod)
{
}
#ifdef CONFIG_X86_KERNEL_IBT
-static void poison_cfi(void *addr) { }
+static void poison_cfi(void *addr, void *wr_addr) { }
#endif
#endif
void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
- s32 *start_cfi, s32 *end_cfi)
+ s32 *start_cfi, s32 *end_cfi, struct module *mod)
{
return __apply_fineibt(start_retpoline, end_retpoline,
- start_cfi, end_cfi,
- /* .builtin = */ false);
+ start_cfi, end_cfi, mod);
}
#ifdef CONFIG_SMP
@@ -1692,16 +1721,16 @@ void __init alternative_instructions(void)
paravirt_set_cap();
__apply_fineibt(__retpoline_sites, __retpoline_sites_end,
- __cfi_sites, __cfi_sites_end, true);
+ __cfi_sites, __cfi_sites_end, NULL);
/*
* Rewrite the retpolines, must be done before alternatives since
* those can rewrite the retpoline thunks.
*/
- apply_retpolines(__retpoline_sites, __retpoline_sites_end);
- apply_returns(__return_sites, __return_sites_end);
+ apply_retpolines(__retpoline_sites, __retpoline_sites_end, NULL);
+ apply_returns(__return_sites, __return_sites_end, NULL);
- apply_alternatives(__alt_instructions, __alt_instructions_end);
+ apply_alternatives(__alt_instructions, __alt_instructions_end, NULL);
/*
* Now all calls are established. Apply the call thunks if
@@ -1712,7 +1741,7 @@ void __init alternative_instructions(void)
/*
* Seal all functions that do not have their address taken.
*/
- apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end);
+ apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end, NULL);
#ifdef CONFIG_SMP
/* Patch to UP if other cpus not imminent. */
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 557318145038..736f62812f5c 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -712,8 +712,8 @@ int __init arch_probe_nr_irqs(void)
{
int nr;
- if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
- nr_irqs = NR_VECTORS * nr_cpu_ids;
+ if (irq_get_nr_irqs() > NR_VECTORS * nr_cpu_ids)
+ irq_set_nr_irqs(NR_VECTORS * nr_cpu_ids);
nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids;
#if defined(CONFIG_PCI_MSI)
@@ -725,8 +725,8 @@ int __init arch_probe_nr_irqs(void)
else
nr += gsi_top * 16;
#endif
- if (nr < nr_irqs)
- nr_irqs = nr;
+ if (nr < irq_get_nr_irqs())
+ irq_set_nr_irqs(nr);
/*
* We don't know if PIC is present at this point so we need to do
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 5857a0f5d514..4efdf5c2efc8 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -59,6 +59,8 @@ obj-$(CONFIG_ACRN_GUEST) += acrn.o
obj-$(CONFIG_DEBUG_FS) += debugfs.o
+obj-$(CONFIG_X86_BUS_LOCK_DETECT) += bus_lock.o
+
quiet_cmd_mkcapflags = MKCAP $@
cmd_mkcapflags = $(CONFIG_SHELL) $(src)/mkcapflags.sh $@ $^
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index fab5caec0b72..d8408aafeed9 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -798,6 +798,7 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
static const struct x86_cpu_desc erratum_1386_microcode[] = {
AMD_CPU_DESC(0x17, 0x1, 0x2, 0x0800126e),
AMD_CPU_DESC(0x17, 0x31, 0x0, 0x08301052),
+ {},
};
static void fix_erratum_1386(struct cpuinfo_x86 *c)
@@ -924,6 +925,17 @@ static void init_amd_zen4(struct cpuinfo_x86 *c)
{
if (!cpu_has(c, X86_FEATURE_HYPERVISOR))
msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT);
+
+ /*
+ * These Zen4 SoCs advertise support for virtualized VMLOAD/VMSAVE
+ * in some BIOS versions but they can lead to random host reboots.
+ */
+ switch (c->x86_model) {
+ case 0x18 ... 0x1f:
+ case 0x60 ... 0x7f:
+ clear_cpu_cap(c, X86_FEATURE_V_VMSAVE_VMLOAD);
+ break;
+ }
}
static void init_amd_zen5(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/bus_lock.c b/arch/x86/kernel/cpu/bus_lock.c
new file mode 100644
index 000000000000..704e9241b964
--- /dev/null
+++ b/arch/x86/kernel/cpu/bus_lock.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) "x86/split lock detection: " fmt
+
+#include <linux/semaphore.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/cpuhotplug.h>
+#include <asm/cpu_device_id.h>
+#include <asm/cmdline.h>
+#include <asm/traps.h>
+#include <asm/cpu.h>
+
+enum split_lock_detect_state {
+ sld_off = 0,
+ sld_warn,
+ sld_fatal,
+ sld_ratelimit,
+};
+
+/*
+ * Default to sld_off because most systems do not support split lock detection.
+ * sld_state_setup() will switch this to sld_warn on systems that support
+ * split lock/bus lock detect, unless there is a command line override.
+ */
+static enum split_lock_detect_state sld_state __ro_after_init = sld_off;
+static u64 msr_test_ctrl_cache __ro_after_init;
+
+/*
+ * With a name like MSR_TEST_CTL it should go without saying, but don't touch
+ * MSR_TEST_CTL unless the CPU is one of the whitelisted models. Writing it
+ * on CPUs that do not support SLD can cause fireworks, even when writing '0'.
+ */
+static bool cpu_model_supports_sld __ro_after_init;
+
+static const struct {
+ const char *option;
+ enum split_lock_detect_state state;
+} sld_options[] __initconst = {
+ { "off", sld_off },
+ { "warn", sld_warn },
+ { "fatal", sld_fatal },
+ { "ratelimit:", sld_ratelimit },
+};
+
+static struct ratelimit_state bld_ratelimit;
+
+static unsigned int sysctl_sld_mitigate = 1;
+static DEFINE_SEMAPHORE(buslock_sem, 1);
+
+#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;
+
+ if (strncmp(arg, opt, len))
+ return false;
+
+ /*
+ * Min ratelimit is 1 bus lock/sec.
+ * Max ratelimit is 1000 bus locks/sec.
+ */
+ if (sscanf(arg, "ratelimit:%d", &ratelimit) == 1 &&
+ ratelimit > 0 && ratelimit <= 1000) {
+ ratelimit_state_init(&bld_ratelimit, HZ, ratelimit);
+ ratelimit_set_flags(&bld_ratelimit, RATELIMIT_MSG_ON_RELEASE);
+ return true;
+ }
+
+ return len == arglen;
+}
+
+static bool split_lock_verify_msr(bool on)
+{
+ u64 ctrl, tmp;
+
+ if (rdmsrl_safe(MSR_TEST_CTRL, &ctrl))
+ return false;
+ if (on)
+ ctrl |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT;
+ else
+ ctrl &= ~MSR_TEST_CTRL_SPLIT_LOCK_DETECT;
+ if (wrmsrl_safe(MSR_TEST_CTRL, ctrl))
+ return false;
+ rdmsrl(MSR_TEST_CTRL, tmp);
+ return ctrl == tmp;
+}
+
+static void __init sld_state_setup(void)
+{
+ enum split_lock_detect_state state = sld_warn;
+ char arg[20];
+ int i, ret;
+
+ if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) &&
+ !boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
+ return;
+
+ ret = cmdline_find_option(boot_command_line, "split_lock_detect",
+ arg, sizeof(arg));
+ if (ret >= 0) {
+ for (i = 0; i < ARRAY_SIZE(sld_options); i++) {
+ if (match_option(arg, ret, sld_options[i].option)) {
+ state = sld_options[i].state;
+ break;
+ }
+ }
+ }
+ sld_state = state;
+}
+
+static void __init __split_lock_setup(void)
+{
+ if (!split_lock_verify_msr(false)) {
+ pr_info("MSR access failed: Disabled\n");
+ return;
+ }
+
+ rdmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache);
+
+ if (!split_lock_verify_msr(true)) {
+ pr_info("MSR access failed: Disabled\n");
+ return;
+ }
+
+ /* Restore the MSR to its cached value. */
+ wrmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache);
+
+ setup_force_cpu_cap(X86_FEATURE_SPLIT_LOCK_DETECT);
+}
+
+/*
+ * MSR_TEST_CTRL is per core, but we treat it like a per CPU MSR. Locking
+ * is not implemented as one thread could undo the setting of the other
+ * thread immediately after dropping the lock anyway.
+ */
+static void sld_update_msr(bool on)
+{
+ u64 test_ctrl_val = msr_test_ctrl_cache;
+
+ if (on)
+ test_ctrl_val |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT;
+
+ wrmsrl(MSR_TEST_CTRL, test_ctrl_val);
+}
+
+void split_lock_init(void)
+{
+ /*
+ * #DB for bus lock handles ratelimit and #AC for split lock is
+ * disabled.
+ */
+ if (sld_state == sld_ratelimit) {
+ split_lock_verify_msr(false);
+ return;
+ }
+
+ if (cpu_model_supports_sld)
+ split_lock_verify_msr(sld_state != sld_off);
+}
+
+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
+ * handles releasing the buslock_sem, but because it executes on a
+ * different CPU probably won't re-enable split lock detection. This is a
+ * problem on HT systems since the sibling CPU on the same core may then be
+ * left running with split lock detection disabled.
+ *
+ * Unconditionally re-enable detection here.
+ */
+static int splitlock_cpu_offline(unsigned int cpu)
+{
+ sld_update_msr(true);
+
+ return 0;
+}
+
+static void split_lock_warn(unsigned long ip)
+{
+ struct delayed_work *work;
+ int cpu;
+
+ if (!current->reported_split_lock)
+ pr_warn_ratelimited("#AC: %s/%d took a split_lock trap at address: 0x%lx\n",
+ current->comm, current->pid, ip);
+ current->reported_split_lock = 1;
+
+ 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, work, 2);
+
+ /* Disable split lock detection on this CPU to make progress */
+ sld_update_msr(false);
+ put_cpu();
+}
+
+bool handle_guest_split_lock(unsigned long ip)
+{
+ if (sld_state == sld_warn) {
+ split_lock_warn(ip);
+ return true;
+ }
+
+ pr_warn_once("#AC: %s/%d %s split_lock trap at address: 0x%lx\n",
+ current->comm, current->pid,
+ sld_state == sld_fatal ? "fatal" : "bogus", ip);
+
+ current->thread.error_code = 0;
+ current->thread.trap_nr = X86_TRAP_AC;
+ force_sig_fault(SIGBUS, BUS_ADRALN, NULL);
+ return false;
+}
+EXPORT_SYMBOL_GPL(handle_guest_split_lock);
+
+void bus_lock_init(void)
+{
+ u64 val;
+
+ if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
+ return;
+
+ rdmsrl(MSR_IA32_DEBUGCTLMSR, val);
+
+ if ((boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) &&
+ (sld_state == sld_warn || sld_state == sld_fatal)) ||
+ sld_state == sld_off) {
+ /*
+ * Warn and fatal are handled by #AC for split lock if #AC for
+ * split lock is supported.
+ */
+ val &= ~DEBUGCTLMSR_BUS_LOCK_DETECT;
+ } else {
+ val |= DEBUGCTLMSR_BUS_LOCK_DETECT;
+ }
+
+ wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
+}
+
+bool handle_user_split_lock(struct pt_regs *regs, long error_code)
+{
+ if ((regs->flags & X86_EFLAGS_AC) || sld_state == sld_fatal)
+ return false;
+ split_lock_warn(regs->ip);
+ return true;
+}
+
+void handle_bus_lock(struct pt_regs *regs)
+{
+ switch (sld_state) {
+ case sld_off:
+ break;
+ case sld_ratelimit:
+ /* Enforce no more than bld_ratelimit bus locks/sec. */
+ while (!__ratelimit(&bld_ratelimit))
+ msleep(20);
+ /* Warn on the bus lock. */
+ fallthrough;
+ case sld_warn:
+ pr_warn_ratelimited("#DB: %s/%d took a bus_lock trap at address: 0x%lx\n",
+ current->comm, current->pid, regs->ip);
+ break;
+ case sld_fatal:
+ force_sig_fault(SIGBUS, BUS_ADRALN, NULL);
+ break;
+ }
+}
+
+/*
+ * CPU models that are known to have the per-core split-lock detection
+ * feature even though they do not enumerate IA32_CORE_CAPABILITIES.
+ */
+static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
+ X86_MATCH_VFM(INTEL_ICELAKE_X, 0),
+ X86_MATCH_VFM(INTEL_ICELAKE_L, 0),
+ X86_MATCH_VFM(INTEL_ICELAKE_D, 0),
+ {}
+};
+
+static void __init split_lock_setup(struct cpuinfo_x86 *c)
+{
+ const struct x86_cpu_id *m;
+ u64 ia32_core_caps;
+
+ if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+ return;
+
+ /* Check for CPUs that have support but do not enumerate it: */
+ m = x86_match_cpu(split_lock_cpu_ids);
+ if (m)
+ goto supported;
+
+ if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
+ return;
+
+ /*
+ * Not all bits in MSR_IA32_CORE_CAPS are architectural, but
+ * MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT is. All CPUs that set
+ * it have split lock detection.
+ */
+ rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
+ if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT)
+ goto supported;
+
+ /* CPU is not in the model list and does not have the MSR bit: */
+ return;
+
+supported:
+ cpu_model_supports_sld = true;
+ __split_lock_setup();
+}
+
+static void sld_state_show(void)
+{
+ if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT) &&
+ !boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
+ return;
+
+ switch (sld_state) {
+ case sld_off:
+ pr_info("disabled\n");
+ break;
+ case sld_warn:
+ if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) {
+ pr_info("#AC: crashing the kernel on kernel split_locks and warning on user-space split_locks\n");
+ if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+ "x86/splitlock", NULL, splitlock_cpu_offline) < 0)
+ pr_warn("No splitlock CPU offline handler\n");
+ } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) {
+ pr_info("#DB: warning on user-space bus_locks\n");
+ }
+ break;
+ case sld_fatal:
+ if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) {
+ pr_info("#AC: crashing the kernel on kernel split_locks and sending SIGBUS on user-space split_locks\n");
+ } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) {
+ pr_info("#DB: sending SIGBUS on user-space bus_locks%s\n",
+ boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ?
+ " from non-WB" : "");
+ }
+ break;
+ case sld_ratelimit:
+ if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
+ pr_info("#DB: setting system wide bus lock rate limit to %u/sec\n", bld_ratelimit.burst);
+ break;
+ }
+}
+
+void __init sld_setup(struct cpuinfo_x86 *c)
+{
+ split_lock_setup(c);
+ sld_state_setup();
+ sld_state_show();
+}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index a5f221ea5688..a5c28975c608 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -169,7 +169,7 @@ static void ppin_init(struct cpuinfo_x86 *c)
}
clear_ppin:
- clear_cpu_cap(c, info->feature);
+ setup_clear_cpu_cap(info->feature);
}
static void default_init(struct cpuinfo_x86 *c)
@@ -276,21 +276,13 @@ static int __init x86_noinvpcid_setup(char *s)
}
early_param("noinvpcid", x86_noinvpcid_setup);
-#ifdef CONFIG_X86_32
-static int cachesize_override = -1;
-static int disable_x86_serial_nr = 1;
-
-static int __init cachesize_setup(char *str)
-{
- get_option(&str, &cachesize_override);
- return 1;
-}
-__setup("cachesize=", cachesize_setup);
-
/* Standard macro to see if a specific flag is changeable */
-static inline int flag_is_changeable_p(u32 flag)
+static inline bool flag_is_changeable_p(unsigned long flag)
{
- u32 f1, f2;
+ unsigned long f1, f2;
+
+ if (!IS_ENABLED(CONFIG_X86_32))
+ return true;
/*
* Cyrix and IDT cpus allow disabling of CPUID
@@ -313,11 +305,22 @@ static inline int flag_is_changeable_p(u32 flag)
: "=&r" (f1), "=&r" (f2)
: "ir" (flag));
- return ((f1^f2) & flag) != 0;
+ return (f1 ^ f2) & flag;
}
+#ifdef CONFIG_X86_32
+static int cachesize_override = -1;
+static int disable_x86_serial_nr = 1;
+
+static int __init cachesize_setup(char *str)
+{
+ get_option(&str, &cachesize_override);
+ return 1;
+}
+__setup("cachesize=", cachesize_setup);
+
/* Probe for the CPUID instruction */
-int have_cpuid_p(void)
+bool have_cpuid_p(void)
{
return flag_is_changeable_p(X86_EFLAGS_ID);
}
@@ -349,10 +352,6 @@ static int __init x86_serial_nr_setup(char *s)
}
__setup("serialnumber", x86_serial_nr_setup);
#else
-static inline int flag_is_changeable_p(u32 flag)
-{
- return 1;
-}
static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
{
}
@@ -1088,7 +1087,6 @@ void get_cpu_address_sizes(struct cpuinfo_x86 *c)
static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_X86_32
int i;
/*
@@ -1109,7 +1107,6 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
break;
}
}
-#endif
}
#define NO_SPECULATION BIT(0)
@@ -1841,6 +1838,8 @@ static void identify_cpu(struct cpuinfo_x86 *c)
if (this_cpu->c_init)
this_cpu->c_init(c);
+ bus_lock_init();
+
/* Disable the PN if appropriate */
squash_the_stupid_serial_number(c);
@@ -1906,9 +1905,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
/* Init Machine Check Exception if available. */
mcheck_cpu_init(c);
-#ifdef CONFIG_NUMA
numa_add_cpu(smp_processor_id());
-#endif
}
/*
@@ -2089,8 +2086,10 @@ void syscall_init(void)
#ifdef CONFIG_STACKPROTECTOR
DEFINE_PER_CPU(unsigned long, __stack_chk_guard);
+#ifndef CONFIG_SMP
EXPORT_PER_CPU_SYMBOL(__stack_chk_guard);
#endif
+#endif
#endif /* CONFIG_X86_64 */
@@ -2390,12 +2389,12 @@ void __init arch_cpu_finalize_init(void)
alternative_instructions();
if (IS_ENABLED(CONFIG_X86_64)) {
- unsigned long USER_PTR_MAX = TASK_SIZE_MAX-1;
+ unsigned long USER_PTR_MAX = TASK_SIZE_MAX;
/*
* Enable this when LAM is gated on LASS support
if (cpu_feature_enabled(X86_FEATURE_LAM))
- USER_PTR_MAX = (1ul << 63) - PAGE_SIZE - 1;
+ USER_PTR_MAX = (1ul << 63) - PAGE_SIZE;
*/
runtime_const_init(ptr, USER_PTR_MAX);
diff --git a/arch/x86/kernel/cpu/debugfs.c b/arch/x86/kernel/cpu/debugfs.c
index 3baf3e435834..10719aba6276 100644
--- a/arch/x86/kernel/cpu/debugfs.c
+++ b/arch/x86/kernel/cpu/debugfs.c
@@ -22,6 +22,7 @@ static int cpu_debug_show(struct seq_file *m, void *p)
seq_printf(m, "die_id: %u\n", c->topo.die_id);
seq_printf(m, "cu_id: %u\n", c->topo.cu_id);
seq_printf(m, "core_id: %u\n", c->topo.core_id);
+ seq_printf(m, "cpu_type: %s\n", get_topology_cpu_type_name(c));
seq_printf(m, "logical_pkg_id: %u\n", c->topo.logical_pkg_id);
seq_printf(m, "logical_die_id: %u\n", c->topo.logical_die_id);
seq_printf(m, "llc_id: %u\n", c->topo.llc_id);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index e7656cbef68d..d1de300af173 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -7,13 +7,9 @@
#include <linux/smp.h>
#include <linux/sched.h>
#include <linux/sched/clock.h>
-#include <linux/semaphore.h>
#include <linux/thread_info.h>
#include <linux/init.h>
#include <linux/uaccess.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/cpuhotplug.h>
#include <asm/cpufeature.h>
#include <asm/msr.h>
@@ -24,8 +20,6 @@
#include <asm/hwcap2.h>
#include <asm/elf.h>
#include <asm/cpu_device_id.h>
-#include <asm/cmdline.h>
-#include <asm/traps.h>
#include <asm/resctrl.h>
#include <asm/numa.h>
#include <asm/thermal.h>
@@ -41,28 +35,6 @@
#include <asm/apic.h>
#endif
-enum split_lock_detect_state {
- sld_off = 0,
- sld_warn,
- sld_fatal,
- sld_ratelimit,
-};
-
-/*
- * Default to sld_off because most systems do not support split lock detection.
- * sld_state_setup() will switch this to sld_warn on systems that support
- * split lock/bus lock detect, unless there is a command line override.
- */
-static enum split_lock_detect_state sld_state __ro_after_init = sld_off;
-static u64 msr_test_ctrl_cache __ro_after_init;
-
-/*
- * With a name like MSR_TEST_CTL it should go without saying, but don't touch
- * MSR_TEST_CTL unless the CPU is one of the whitelisted models. Writing it
- * on CPUs that do not support SLD can cause fireworks, even when writing '0'.
- */
-static bool cpu_model_supports_sld __ro_after_init;
-
/*
* Processors which have self-snooping capability can handle conflicting
* memory type across CPUs by snooping its own cache. However, there exists
@@ -549,9 +521,6 @@ static void init_intel_misc_features(struct cpuinfo_x86 *c)
wrmsrl(MSR_MISC_FEATURES_ENABLES, msr);
}
-static void split_lock_init(void);
-static void bus_lock_init(void);
-
static void init_intel(struct cpuinfo_x86 *c)
{
early_init_intel(c);
@@ -643,7 +612,6 @@ static void init_intel(struct cpuinfo_x86 *c)
init_intel_misc_features(c);
split_lock_init();
- bus_lock_init();
intel_init_thermal(c);
}
@@ -909,381 +877,6 @@ static const struct cpu_dev intel_cpu_dev = {
cpu_dev_register(intel_cpu_dev);
-#undef pr_fmt
-#define pr_fmt(fmt) "x86/split lock detection: " fmt
-
-static const struct {
- const char *option;
- enum split_lock_detect_state state;
-} sld_options[] __initconst = {
- { "off", sld_off },
- { "warn", sld_warn },
- { "fatal", sld_fatal },
- { "ratelimit:", sld_ratelimit },
-};
-
-static struct ratelimit_state bld_ratelimit;
-
-static unsigned int sysctl_sld_mitigate = 1;
-static DEFINE_SEMAPHORE(buslock_sem, 1);
-
-#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;
-
- if (strncmp(arg, opt, len))
- return false;
-
- /*
- * Min ratelimit is 1 bus lock/sec.
- * Max ratelimit is 1000 bus locks/sec.
- */
- if (sscanf(arg, "ratelimit:%d", &ratelimit) == 1 &&
- ratelimit > 0 && ratelimit <= 1000) {
- ratelimit_state_init(&bld_ratelimit, HZ, ratelimit);
- ratelimit_set_flags(&bld_ratelimit, RATELIMIT_MSG_ON_RELEASE);
- return true;
- }
-
- return len == arglen;
-}
-
-static bool split_lock_verify_msr(bool on)
-{
- u64 ctrl, tmp;
-
- if (rdmsrl_safe(MSR_TEST_CTRL, &ctrl))
- return false;
- if (on)
- ctrl |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT;
- else
- ctrl &= ~MSR_TEST_CTRL_SPLIT_LOCK_DETECT;
- if (wrmsrl_safe(MSR_TEST_CTRL, ctrl))
- return false;
- rdmsrl(MSR_TEST_CTRL, tmp);
- return ctrl == tmp;
-}
-
-static void __init sld_state_setup(void)
-{
- enum split_lock_detect_state state = sld_warn;
- char arg[20];
- int i, ret;
-
- if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) &&
- !boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
- return;
-
- ret = cmdline_find_option(boot_command_line, "split_lock_detect",
- arg, sizeof(arg));
- if (ret >= 0) {
- for (i = 0; i < ARRAY_SIZE(sld_options); i++) {
- if (match_option(arg, ret, sld_options[i].option)) {
- state = sld_options[i].state;
- break;
- }
- }
- }
- sld_state = state;
-}
-
-static void __init __split_lock_setup(void)
-{
- if (!split_lock_verify_msr(false)) {
- pr_info("MSR access failed: Disabled\n");
- return;
- }
-
- rdmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache);
-
- if (!split_lock_verify_msr(true)) {
- pr_info("MSR access failed: Disabled\n");
- return;
- }
-
- /* Restore the MSR to its cached value. */
- wrmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache);
-
- setup_force_cpu_cap(X86_FEATURE_SPLIT_LOCK_DETECT);
-}
-
-/*
- * MSR_TEST_CTRL is per core, but we treat it like a per CPU MSR. Locking
- * is not implemented as one thread could undo the setting of the other
- * thread immediately after dropping the lock anyway.
- */
-static void sld_update_msr(bool on)
-{
- u64 test_ctrl_val = msr_test_ctrl_cache;
-
- if (on)
- test_ctrl_val |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT;
-
- wrmsrl(MSR_TEST_CTRL, test_ctrl_val);
-}
-
-static void split_lock_init(void)
-{
- /*
- * #DB for bus lock handles ratelimit and #AC for split lock is
- * disabled.
- */
- if (sld_state == sld_ratelimit) {
- split_lock_verify_msr(false);
- return;
- }
-
- if (cpu_model_supports_sld)
- split_lock_verify_msr(sld_state != sld_off);
-}
-
-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
- * handles releasing the buslock_sem, but because it executes on a
- * different CPU probably won't re-enable split lock detection. This is a
- * problem on HT systems since the sibling CPU on the same core may then be
- * left running with split lock detection disabled.
- *
- * Unconditionally re-enable detection here.
- */
-static int splitlock_cpu_offline(unsigned int cpu)
-{
- sld_update_msr(true);
-
- return 0;
-}
-
-static void split_lock_warn(unsigned long ip)
-{
- struct delayed_work *work;
- int cpu;
-
- if (!current->reported_split_lock)
- pr_warn_ratelimited("#AC: %s/%d took a split_lock trap at address: 0x%lx\n",
- current->comm, current->pid, ip);
- current->reported_split_lock = 1;
-
- 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, work, 2);
-
- /* Disable split lock detection on this CPU to make progress */
- sld_update_msr(false);
- put_cpu();
-}
-
-bool handle_guest_split_lock(unsigned long ip)
-{
- if (sld_state == sld_warn) {
- split_lock_warn(ip);
- return true;
- }
-
- pr_warn_once("#AC: %s/%d %s split_lock trap at address: 0x%lx\n",
- current->comm, current->pid,
- sld_state == sld_fatal ? "fatal" : "bogus", ip);
-
- current->thread.error_code = 0;
- current->thread.trap_nr = X86_TRAP_AC;
- force_sig_fault(SIGBUS, BUS_ADRALN, NULL);
- return false;
-}
-EXPORT_SYMBOL_GPL(handle_guest_split_lock);
-
-static void bus_lock_init(void)
-{
- u64 val;
-
- if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
- return;
-
- rdmsrl(MSR_IA32_DEBUGCTLMSR, val);
-
- if ((boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) &&
- (sld_state == sld_warn || sld_state == sld_fatal)) ||
- sld_state == sld_off) {
- /*
- * Warn and fatal are handled by #AC for split lock if #AC for
- * split lock is supported.
- */
- val &= ~DEBUGCTLMSR_BUS_LOCK_DETECT;
- } else {
- val |= DEBUGCTLMSR_BUS_LOCK_DETECT;
- }
-
- wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
-}
-
-bool handle_user_split_lock(struct pt_regs *regs, long error_code)
-{
- if ((regs->flags & X86_EFLAGS_AC) || sld_state == sld_fatal)
- return false;
- split_lock_warn(regs->ip);
- return true;
-}
-
-void handle_bus_lock(struct pt_regs *regs)
-{
- switch (sld_state) {
- case sld_off:
- break;
- case sld_ratelimit:
- /* Enforce no more than bld_ratelimit bus locks/sec. */
- while (!__ratelimit(&bld_ratelimit))
- msleep(20);
- /* Warn on the bus lock. */
- fallthrough;
- case sld_warn:
- pr_warn_ratelimited("#DB: %s/%d took a bus_lock trap at address: 0x%lx\n",
- current->comm, current->pid, regs->ip);
- break;
- case sld_fatal:
- force_sig_fault(SIGBUS, BUS_ADRALN, NULL);
- break;
- }
-}
-
-/*
- * CPU models that are known to have the per-core split-lock detection
- * feature even though they do not enumerate IA32_CORE_CAPABILITIES.
- */
-static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
- X86_MATCH_VFM(INTEL_ICELAKE_X, 0),
- X86_MATCH_VFM(INTEL_ICELAKE_L, 0),
- X86_MATCH_VFM(INTEL_ICELAKE_D, 0),
- {}
-};
-
-static void __init split_lock_setup(struct cpuinfo_x86 *c)
-{
- const struct x86_cpu_id *m;
- u64 ia32_core_caps;
-
- if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
- return;
-
- /* Check for CPUs that have support but do not enumerate it: */
- m = x86_match_cpu(split_lock_cpu_ids);
- if (m)
- goto supported;
-
- if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
- return;
-
- /*
- * Not all bits in MSR_IA32_CORE_CAPS are architectural, but
- * MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT is. All CPUs that set
- * it have split lock detection.
- */
- rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
- if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT)
- goto supported;
-
- /* CPU is not in the model list and does not have the MSR bit: */
- return;
-
-supported:
- cpu_model_supports_sld = true;
- __split_lock_setup();
-}
-
-static void sld_state_show(void)
-{
- if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT) &&
- !boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
- return;
-
- switch (sld_state) {
- case sld_off:
- pr_info("disabled\n");
- break;
- case sld_warn:
- if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) {
- pr_info("#AC: crashing the kernel on kernel split_locks and warning on user-space split_locks\n");
- if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
- "x86/splitlock", NULL, splitlock_cpu_offline) < 0)
- pr_warn("No splitlock CPU offline handler\n");
- } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) {
- pr_info("#DB: warning on user-space bus_locks\n");
- }
- break;
- case sld_fatal:
- if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) {
- pr_info("#AC: crashing the kernel on kernel split_locks and sending SIGBUS on user-space split_locks\n");
- } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) {
- pr_info("#DB: sending SIGBUS on user-space bus_locks%s\n",
- boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ?
- " from non-WB" : "");
- }
- break;
- case sld_ratelimit:
- if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
- pr_info("#DB: setting system wide bus lock rate limit to %u/sec\n", bld_ratelimit.burst);
- break;
- }
-}
-
-void __init sld_setup(struct cpuinfo_x86 *c)
-{
- split_lock_setup(c);
- sld_state_setup();
- sld_state_show();
-}
-
#define X86_HYBRID_CPU_TYPE_ID_SHIFT 24
/**
@@ -1299,3 +892,18 @@ u8 get_this_hybrid_cpu_type(void)
return cpuid_eax(0x0000001a) >> X86_HYBRID_CPU_TYPE_ID_SHIFT;
}
+
+/**
+ * get_this_hybrid_cpu_native_id() - Get the native id of this hybrid CPU
+ *
+ * Returns the uarch native ID [23:0] of a CPU in a hybrid processor.
+ * If the processor is not hybrid, returns 0.
+ */
+u32 get_this_hybrid_cpu_native_id(void)
+{
+ if (!cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
+ return 0;
+
+ return cpuid_eax(0x0000001a) &
+ (BIT_ULL(X86_HYBRID_CPU_TYPE_ID_SHIFT) - 1);
+}
diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
index 14bf8c232e45..6ca80fff1fea 100644
--- a/arch/x86/kernel/cpu/mce/amd.c
+++ b/arch/x86/kernel/cpu/mce/amd.c
@@ -778,29 +778,33 @@ bool amd_mce_usable_address(struct mce *m)
static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
{
- struct mce m;
+ struct mce_hw_err err;
+ struct mce *m = &err.m;
- mce_prep_record(&m);
+ mce_prep_record(&err);
- m.status = status;
- m.misc = misc;
- m.bank = bank;
- m.tsc = rdtsc();
+ m->status = status;
+ m->misc = misc;
+ m->bank = bank;
+ m->tsc = rdtsc();
- if (m.status & MCI_STATUS_ADDRV) {
- m.addr = addr;
+ if (m->status & MCI_STATUS_ADDRV) {
+ m->addr = addr;
- smca_extract_err_addr(&m);
+ smca_extract_err_addr(m);
}
if (mce_flags.smca) {
- rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), m.ipid);
+ rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), m->ipid);
- if (m.status & MCI_STATUS_SYNDV)
- rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m.synd);
+ if (m->status & MCI_STATUS_SYNDV) {
+ rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m->synd);
+ rdmsrl(MSR_AMD64_SMCA_MCx_SYND1(bank), err.vendor.amd.synd1);
+ rdmsrl(MSR_AMD64_SMCA_MCx_SYND2(bank), err.vendor.amd.synd2);
+ }
}
- mce_log(&m);
+ mce_log(&err);
}
DEFINE_IDTENTRY_SYSVEC(sysvec_deferred_error)
diff --git a/arch/x86/kernel/cpu/mce/apei.c b/arch/x86/kernel/cpu/mce/apei.c
index 3885fe05f01e..0a89947e47bc 100644
--- a/arch/x86/kernel/cpu/mce/apei.c
+++ b/arch/x86/kernel/cpu/mce/apei.c
@@ -28,7 +28,8 @@
void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err)
{
- struct mce m;
+ struct mce_hw_err err;
+ struct mce *m;
int lsb;
if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
@@ -44,31 +45,33 @@ void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err)
else
lsb = PAGE_SHIFT;
- mce_prep_record(&m);
- m.bank = -1;
+ mce_prep_record(&err);
+ m = &err.m;
+ m->bank = -1;
/* Fake a memory read error with unknown channel */
- m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | MCI_STATUS_MISCV | 0x9f;
- m.misc = (MCI_MISC_ADDR_PHYS << 6) | lsb;
+ m->status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | MCI_STATUS_MISCV | 0x9f;
+ m->misc = (MCI_MISC_ADDR_PHYS << 6) | lsb;
if (severity >= GHES_SEV_RECOVERABLE)
- m.status |= MCI_STATUS_UC;
+ m->status |= MCI_STATUS_UC;
if (severity >= GHES_SEV_PANIC) {
- m.status |= MCI_STATUS_PCC;
- m.tsc = rdtsc();
+ m->status |= MCI_STATUS_PCC;
+ m->tsc = rdtsc();
}
- m.addr = mem_err->physical_addr;
- mce_log(&m);
+ m->addr = mem_err->physical_addr;
+ mce_log(&err);
}
EXPORT_SYMBOL_GPL(apei_mce_report_mem_error);
int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
{
const u64 *i_mce = ((const u64 *) (ctx_info + 1));
+ unsigned int cpu, num_regs;
bool apicid_found = false;
- unsigned int cpu;
- struct mce m;
+ struct mce_hw_err err;
+ struct mce *m;
if (!boot_cpu_has(X86_FEATURE_SMCA))
return -EINVAL;
@@ -86,16 +89,12 @@ int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
return -EINVAL;
/*
- * The register array size must be large enough to include all the
- * SMCA registers which need to be extracted.
- *
* The number of registers in the register array is determined by
* Register Array Size/8 as defined in UEFI spec v2.8, sec N.2.4.2.2.
- * The register layout is fixed and currently the raw data in the
- * register array includes 6 SMCA registers which the kernel can
- * extract.
+ * Sanity-check registers array size.
*/
- if (ctx_info->reg_arr_size < 48)
+ num_regs = ctx_info->reg_arr_size >> 3;
+ if (!num_regs)
return -EINVAL;
for_each_possible_cpu(cpu) {
@@ -108,18 +107,68 @@ int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
if (!apicid_found)
return -EINVAL;
- mce_prep_record_common(&m);
- mce_prep_record_per_cpu(cpu, &m);
+ m = &err.m;
+ memset(&err, 0, sizeof(struct mce_hw_err));
+ mce_prep_record_common(m);
+ mce_prep_record_per_cpu(cpu, m);
+
+ m->bank = (ctx_info->msr_addr >> 4) & 0xFF;
- m.bank = (ctx_info->msr_addr >> 4) & 0xFF;
- m.status = *i_mce;
- m.addr = *(i_mce + 1);
- m.misc = *(i_mce + 2);
- /* Skipping MCA_CONFIG */
- m.ipid = *(i_mce + 4);
- m.synd = *(i_mce + 5);
+ /*
+ * The SMCA register layout is fixed and includes 16 registers.
+ * The end of the array may be variable, but the beginning is known.
+ * Cap the number of registers to expected max (15).
+ */
+ if (num_regs > 15)
+ num_regs = 15;
+
+ switch (num_regs) {
+ /* MCA_SYND2 */
+ case 15:
+ err.vendor.amd.synd2 = *(i_mce + 14);
+ fallthrough;
+ /* MCA_SYND1 */
+ case 14:
+ err.vendor.amd.synd1 = *(i_mce + 13);
+ fallthrough;
+ /* MCA_MISC4 */
+ case 13:
+ /* MCA_MISC3 */
+ case 12:
+ /* MCA_MISC2 */
+ case 11:
+ /* MCA_MISC1 */
+ case 10:
+ /* MCA_DEADDR */
+ case 9:
+ /* MCA_DESTAT */
+ case 8:
+ /* reserved */
+ case 7:
+ /* MCA_SYND */
+ case 6:
+ m->synd = *(i_mce + 5);
+ fallthrough;
+ /* MCA_IPID */
+ case 5:
+ m->ipid = *(i_mce + 4);
+ fallthrough;
+ /* MCA_CONFIG */
+ case 4:
+ /* MCA_MISC0 */
+ case 3:
+ m->misc = *(i_mce + 2);
+ fallthrough;
+ /* MCA_ADDR */
+ case 2:
+ m->addr = *(i_mce + 1);
+ fallthrough;
+ /* MCA_STATUS */
+ case 1:
+ m->status = *i_mce;
+ }
- mce_log(&m);
+ mce_log(&err);
return 0;
}
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 2a938f429c4d..7fb5556a0b53 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -88,7 +88,7 @@ struct mca_config mca_cfg __read_mostly = {
.monarch_timeout = -1
};
-static DEFINE_PER_CPU(struct mce, mces_seen);
+static DEFINE_PER_CPU(struct mce_hw_err, hw_errs_seen);
static unsigned long mce_need_notify;
/*
@@ -119,8 +119,6 @@ BLOCKING_NOTIFIER_HEAD(x86_mce_decoder_chain);
void mce_prep_record_common(struct mce *m)
{
- memset(m, 0, sizeof(struct mce));
-
m->cpuid = cpuid_eax(1);
m->cpuvendor = boot_cpu_data.x86_vendor;
m->mcgcap = __rdmsr(MSR_IA32_MCG_CAP);
@@ -138,9 +136,12 @@ void mce_prep_record_per_cpu(unsigned int cpu, struct mce *m)
m->socketid = topology_physical_package_id(cpu);
}
-/* Do initial initialization of a struct mce */
-void mce_prep_record(struct mce *m)
+/* Do initial initialization of struct mce_hw_err */
+void mce_prep_record(struct mce_hw_err *err)
{
+ struct mce *m = &err->m;
+
+ memset(err, 0, sizeof(struct mce_hw_err));
mce_prep_record_common(m);
mce_prep_record_per_cpu(smp_processor_id(), m);
}
@@ -148,9 +149,9 @@ void mce_prep_record(struct mce *m)
DEFINE_PER_CPU(struct mce, injectm);
EXPORT_PER_CPU_SYMBOL_GPL(injectm);
-void mce_log(struct mce *m)
+void mce_log(struct mce_hw_err *err)
{
- if (!mce_gen_pool_add(m))
+ if (!mce_gen_pool_add(err))
irq_work_queue(&mce_irq_work);
}
EXPORT_SYMBOL_GPL(mce_log);
@@ -171,8 +172,10 @@ void mce_unregister_decode_chain(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(mce_unregister_decode_chain);
-static void __print_mce(struct mce *m)
+static void __print_mce(struct mce_hw_err *err)
{
+ struct mce *m = &err->m;
+
pr_emerg(HW_ERR "CPU %d: Machine Check%s: %Lx Bank %d: %016Lx\n",
m->extcpu,
(m->mcgstatus & MCG_STATUS_MCIP ? " Exception" : ""),
@@ -199,6 +202,10 @@ static void __print_mce(struct mce *m)
if (mce_flags.smca) {
if (m->synd)
pr_cont("SYND %llx ", m->synd);
+ if (err->vendor.amd.synd1)
+ pr_cont("SYND1 %llx ", err->vendor.amd.synd1);
+ if (err->vendor.amd.synd2)
+ pr_cont("SYND2 %llx ", err->vendor.amd.synd2);
if (m->ipid)
pr_cont("IPID %llx ", m->ipid);
}
@@ -214,9 +221,11 @@ static void __print_mce(struct mce *m)
m->microcode);
}
-static void print_mce(struct mce *m)
+static void print_mce(struct mce_hw_err *err)
{
- __print_mce(m);
+ struct mce *m = &err->m;
+
+ __print_mce(err);
if (m->cpuvendor != X86_VENDOR_AMD && m->cpuvendor != X86_VENDOR_HYGON)
pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n");
@@ -251,7 +260,7 @@ static const char *mce_dump_aux_info(struct mce *m)
return NULL;
}
-static noinstr void mce_panic(const char *msg, struct mce *final, char *exp)
+static noinstr void mce_panic(const char *msg, struct mce_hw_err *final, char *exp)
{
struct llist_node *pending;
struct mce_evt_llist *l;
@@ -282,20 +291,22 @@ static noinstr void mce_panic(const char *msg, struct mce *final, char *exp)
pending = mce_gen_pool_prepare_records();
/* First print corrected ones that are still unlogged */
llist_for_each_entry(l, pending, llnode) {
- struct mce *m = &l->mce;
+ struct mce_hw_err *err = &l->err;
+ struct mce *m = &err->m;
if (!(m->status & MCI_STATUS_UC)) {
- print_mce(m);
+ print_mce(err);
if (!apei_err)
apei_err = apei_write_mce(m);
}
}
/* Now print uncorrected but with the final one last */
llist_for_each_entry(l, pending, llnode) {
- struct mce *m = &l->mce;
+ struct mce_hw_err *err = &l->err;
+ struct mce *m = &err->m;
if (!(m->status & MCI_STATUS_UC))
continue;
- if (!final || mce_cmp(m, final)) {
- print_mce(m);
+ if (!final || mce_cmp(m, &final->m)) {
+ print_mce(err);
if (!apei_err)
apei_err = apei_write_mce(m);
}
@@ -303,12 +314,12 @@ static noinstr void mce_panic(const char *msg, struct mce *final, char *exp)
if (final) {
print_mce(final);
if (!apei_err)
- apei_err = apei_write_mce(final);
+ apei_err = apei_write_mce(&final->m);
}
if (exp)
pr_emerg(HW_ERR "Machine check: %s\n", exp);
- memmsg = mce_dump_aux_info(final);
+ memmsg = mce_dump_aux_info(&final->m);
if (memmsg)
pr_emerg(HW_ERR "Machine check: %s\n", memmsg);
@@ -323,9 +334,9 @@ static noinstr void mce_panic(const char *msg, struct mce *final, char *exp)
* panic.
*/
if (kexec_crash_loaded()) {
- if (final && (final->status & MCI_STATUS_ADDRV)) {
+ if (final && (final->m.status & MCI_STATUS_ADDRV)) {
struct page *p;
- p = pfn_to_online_page(final->addr >> PAGE_SHIFT);
+ p = pfn_to_online_page(final->m.addr >> PAGE_SHIFT);
if (p)
SetPageHWPoison(p);
}
@@ -445,16 +456,18 @@ static noinstr void mce_wrmsrl(u32 msr, u64 v)
* check into our "mce" struct so that we can use it later to assess
* the severity of the problem as we read per-bank specific details.
*/
-static noinstr void mce_gather_info(struct mce *m, struct pt_regs *regs)
+static noinstr void mce_gather_info(struct mce_hw_err *err, struct pt_regs *regs)
{
+ struct mce *m;
/*
* Enable instrumentation around mce_prep_record() which calls external
* facilities.
*/
instrumentation_begin();
- mce_prep_record(m);
+ mce_prep_record(err);
instrumentation_end();
+ m = &err->m;
m->mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
if (regs) {
/*
@@ -574,13 +587,13 @@ EXPORT_SYMBOL_GPL(mce_is_correctable);
static int mce_early_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
- struct mce *m = (struct mce *)data;
+ struct mce_hw_err *err = to_mce_hw_err(data);
- if (!m)
+ if (!err)
return NOTIFY_DONE;
/* Emit the trace record: */
- trace_mce_record(m);
+ trace_mce_record(err);
set_bit(0, &mce_need_notify);
@@ -624,13 +637,13 @@ static struct notifier_block mce_uc_nb = {
static int mce_default_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
- struct mce *m = (struct mce *)data;
+ struct mce_hw_err *err = to_mce_hw_err(data);
- if (!m)
+ if (!err)
return NOTIFY_DONE;
- if (mca_cfg.print_all || !m->kflags)
- __print_mce(m);
+ if (mca_cfg.print_all || !(err->m.kflags))
+ __print_mce(err);
return NOTIFY_DONE;
}
@@ -644,8 +657,10 @@ static struct notifier_block mce_default_nb = {
/*
* Read ADDR and MISC registers.
*/
-static noinstr void mce_read_aux(struct mce *m, int i)
+static noinstr void mce_read_aux(struct mce_hw_err *err, int i)
{
+ struct mce *m = &err->m;
+
if (m->status & MCI_STATUS_MISCV)
m->misc = mce_rdmsrl(mca_msr_reg(i, MCA_MISC));
@@ -667,8 +682,11 @@ static noinstr void mce_read_aux(struct mce *m, int i)
if (mce_flags.smca) {
m->ipid = mce_rdmsrl(MSR_AMD64_SMCA_MCx_IPID(i));
- if (m->status & MCI_STATUS_SYNDV)
+ if (m->status & MCI_STATUS_SYNDV) {
m->synd = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND(i));
+ err->vendor.amd.synd1 = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND1(i));
+ err->vendor.amd.synd2 = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND2(i));
+ }
}
}
@@ -692,26 +710,28 @@ DEFINE_PER_CPU(unsigned, mce_poll_count);
void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
{
struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array);
- struct mce m;
+ struct mce_hw_err err;
+ struct mce *m;
int i;
this_cpu_inc(mce_poll_count);
- mce_gather_info(&m, NULL);
+ mce_gather_info(&err, NULL);
+ m = &err.m;
if (flags & MCP_TIMESTAMP)
- m.tsc = rdtsc();
+ m->tsc = rdtsc();
for (i = 0; i < this_cpu_read(mce_num_banks); i++) {
if (!mce_banks[i].ctl || !test_bit(i, *b))
continue;
- m.misc = 0;
- m.addr = 0;
- m.bank = i;
+ m->misc = 0;
+ m->addr = 0;
+ m->bank = i;
barrier();
- m.status = mce_rdmsrl(mca_msr_reg(i, MCA_STATUS));
+ m->status = mce_rdmsrl(mca_msr_reg(i, MCA_STATUS));
/*
* Update storm tracking here, before checking for the
@@ -721,17 +741,17 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
* storm status.
*/
if (!mca_cfg.cmci_disabled)
- mce_track_storm(&m);
+ mce_track_storm(m);
/* If this entry is not valid, ignore it */
- if (!(m.status & MCI_STATUS_VAL))
+ if (!(m->status & MCI_STATUS_VAL))
continue;
/*
* If we are logging everything (at CPU online) or this
* is a corrected error, then we must log it.
*/
- if ((flags & MCP_UC) || !(m.status & MCI_STATUS_UC))
+ if ((flags & MCP_UC) || !(m->status & MCI_STATUS_UC))
goto log_it;
/*
@@ -741,20 +761,20 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
* everything else.
*/
if (!mca_cfg.ser) {
- if (m.status & MCI_STATUS_UC)
+ if (m->status & MCI_STATUS_UC)
continue;
goto log_it;
}
/* Log "not enabled" (speculative) errors */
- if (!(m.status & MCI_STATUS_EN))
+ if (!(m->status & MCI_STATUS_EN))
goto log_it;
/*
* Log UCNA (SDM: 15.6.3 "UCR Error Classification")
* UC == 1 && PCC == 0 && S == 0
*/
- if (!(m.status & MCI_STATUS_PCC) && !(m.status & MCI_STATUS_S))
+ if (!(m->status & MCI_STATUS_PCC) && !(m->status & MCI_STATUS_S))
goto log_it;
/*
@@ -768,20 +788,20 @@ log_it:
if (flags & MCP_DONTLOG)
goto clear_it;
- mce_read_aux(&m, i);
- m.severity = mce_severity(&m, NULL, NULL, false);
+ mce_read_aux(&err, i);
+ m->severity = mce_severity(m, NULL, NULL, false);
/*
* Don't get the IP here because it's unlikely to
* have anything to do with the actual error location.
*/
- if (mca_cfg.dont_log_ce && !mce_usable_address(&m))
+ if (mca_cfg.dont_log_ce && !mce_usable_address(m))
goto clear_it;
if (flags & MCP_QUEUE_LOG)
- mce_gen_pool_add(&m);
+ mce_gen_pool_add(&err);
else
- mce_log(&m);
+ mce_log(&err);
clear_it:
/*
@@ -905,9 +925,10 @@ static __always_inline void quirk_zen_ifu(int bank, struct mce *m, struct pt_reg
* Do a quick check if any of the events requires a panic.
* This decides if we keep the events around or clear them.
*/
-static __always_inline int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
+static __always_inline int mce_no_way_out(struct mce_hw_err *err, char **msg, unsigned long *validp,
struct pt_regs *regs)
{
+ struct mce *m = &err->m;
char *tmp = *msg;
int i;
@@ -925,7 +946,7 @@ static __always_inline int mce_no_way_out(struct mce *m, char **msg, unsigned lo
m->bank = i;
if (mce_severity(m, regs, &tmp, true) >= MCE_PANIC_SEVERITY) {
- mce_read_aux(m, i);
+ mce_read_aux(err, i);
*msg = tmp;
return 1;
}
@@ -1016,10 +1037,11 @@ out:
*/
static void mce_reign(void)
{
- int cpu;
+ struct mce_hw_err *err = NULL;
struct mce *m = NULL;
int global_worst = 0;
char *msg = NULL;
+ int cpu;
/*
* This CPU is the Monarch and the other CPUs have run
@@ -1027,11 +1049,13 @@ static void mce_reign(void)
* Grade the severity of the errors of all the CPUs.
*/
for_each_possible_cpu(cpu) {
- struct mce *mtmp = &per_cpu(mces_seen, cpu);
+ struct mce_hw_err *etmp = &per_cpu(hw_errs_seen, cpu);
+ struct mce *mtmp = &etmp->m;
if (mtmp->severity > global_worst) {
global_worst = mtmp->severity;
- m = &per_cpu(mces_seen, cpu);
+ err = &per_cpu(hw_errs_seen, cpu);
+ m = &err->m;
}
}
@@ -1043,7 +1067,7 @@ static void mce_reign(void)
if (m && global_worst >= MCE_PANIC_SEVERITY) {
/* call mce_severity() to get "msg" for panic */
mce_severity(m, NULL, &msg, true);
- mce_panic("Fatal machine check", m, msg);
+ mce_panic("Fatal machine check", err, msg);
}
/*
@@ -1060,11 +1084,11 @@ static void mce_reign(void)
mce_panic("Fatal machine check from unknown source", NULL, NULL);
/*
- * Now clear all the mces_seen so that they don't reappear on
+ * Now clear all the hw_errs_seen so that they don't reappear on
* the next mce.
*/
for_each_possible_cpu(cpu)
- memset(&per_cpu(mces_seen, cpu), 0, sizeof(struct mce));
+ memset(&per_cpu(hw_errs_seen, cpu), 0, sizeof(struct mce_hw_err));
}
static atomic_t global_nwo;
@@ -1268,13 +1292,14 @@ static noinstr bool mce_check_crashing_cpu(void)
}
static __always_inline int
-__mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final,
- unsigned long *toclear, unsigned long *valid_banks, int no_way_out,
- int *worst)
+__mc_scan_banks(struct mce_hw_err *err, struct pt_regs *regs,
+ struct mce_hw_err *final, unsigned long *toclear,
+ unsigned long *valid_banks, int no_way_out, int *worst)
{
struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array);
struct mca_config *cfg = &mca_cfg;
int severity, i, taint = 0;
+ struct mce *m = &err->m;
for (i = 0; i < this_cpu_read(mce_num_banks); i++) {
arch___clear_bit(i, toclear);
@@ -1319,7 +1344,7 @@ __mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final,
if (severity == MCE_NO_SEVERITY)
continue;
- mce_read_aux(m, i);
+ mce_read_aux(err, i);
/* assuming valid severity level != 0 */
m->severity = severity;
@@ -1329,17 +1354,17 @@ __mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final,
* done in #MC context, where instrumentation is disabled.
*/
instrumentation_begin();
- mce_log(m);
+ mce_log(err);
instrumentation_end();
if (severity > *worst) {
- *final = *m;
+ *final = *err;
*worst = severity;
}
}
/* mce_clear_state will clear *final, save locally for use later */
- *m = *final;
+ *err = *final;
return taint;
}
@@ -1399,9 +1424,10 @@ static void kill_me_never(struct callback_head *cb)
set_mce_nospec(pfn);
}
-static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *))
+static void queue_task_work(struct mce_hw_err *err, char *msg, void (*func)(struct callback_head *))
{
int count = ++current->mce_count;
+ struct mce *m = &err->m;
/* First call, save all the details */
if (count == 1) {
@@ -1414,11 +1440,12 @@ static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callba
/* Ten is likely overkill. Don't expect more than two faults before task_work() */
if (count > 10)
- mce_panic("Too many consecutive machine checks while accessing user data", m, msg);
+ mce_panic("Too many consecutive machine checks while accessing user data",
+ err, msg);
/* Second or later call, make sure page address matches the one from first call */
if (count > 1 && (current->mce_addr >> PAGE_SHIFT) != (m->addr >> PAGE_SHIFT))
- mce_panic("Consecutive machine checks to different user pages", m, msg);
+ mce_panic("Consecutive machine checks to different user pages", err, msg);
/* Do not call task_work_add() more than once */
if (count > 1)
@@ -1467,8 +1494,10 @@ noinstr void do_machine_check(struct pt_regs *regs)
int worst = 0, order, no_way_out, kill_current_task, lmce, taint = 0;
DECLARE_BITMAP(valid_banks, MAX_NR_BANKS) = { 0 };
DECLARE_BITMAP(toclear, MAX_NR_BANKS) = { 0 };
- struct mce m, *final;
+ struct mce_hw_err *final;
+ struct mce_hw_err err;
char *msg = NULL;
+ struct mce *m;
if (unlikely(mce_flags.p5))
return pentium_machine_check(regs);
@@ -1506,13 +1535,14 @@ noinstr void do_machine_check(struct pt_regs *regs)
this_cpu_inc(mce_exception_count);
- mce_gather_info(&m, regs);
- m.tsc = rdtsc();
+ mce_gather_info(&err, regs);
+ m = &err.m;
+ m->tsc = rdtsc();
- final = this_cpu_ptr(&mces_seen);
- *final = m;
+ final = this_cpu_ptr(&hw_errs_seen);
+ *final = err;
- no_way_out = mce_no_way_out(&m, &msg, valid_banks, regs);
+ no_way_out = mce_no_way_out(&err, &msg, valid_banks, regs);
barrier();
@@ -1521,15 +1551,15 @@ noinstr void do_machine_check(struct pt_regs *regs)
* Assume the worst for now, but if we find the
* severity is MCE_AR_SEVERITY we have other options.
*/
- if (!(m.mcgstatus & MCG_STATUS_RIPV))
+ if (!(m->mcgstatus & MCG_STATUS_RIPV))
kill_current_task = 1;
/*
* Check if this MCE is signaled to only this logical processor,
* on Intel, Zhaoxin only.
*/
- if (m.cpuvendor == X86_VENDOR_INTEL ||
- m.cpuvendor == X86_VENDOR_ZHAOXIN)
- lmce = m.mcgstatus & MCG_STATUS_LMCES;
+ if (m->cpuvendor == X86_VENDOR_INTEL ||
+ m->cpuvendor == X86_VENDOR_ZHAOXIN)
+ lmce = m->mcgstatus & MCG_STATUS_LMCES;
/*
* Local machine check may already know that we have to panic.
@@ -1540,12 +1570,12 @@ noinstr void do_machine_check(struct pt_regs *regs)
*/
if (lmce) {
if (no_way_out)
- mce_panic("Fatal local machine check", &m, msg);
+ mce_panic("Fatal local machine check", &err, msg);
} else {
order = mce_start(&no_way_out);
}
- taint = __mc_scan_banks(&m, regs, final, toclear, valid_banks, no_way_out, &worst);
+ taint = __mc_scan_banks(&err, regs, final, toclear, valid_banks, no_way_out, &worst);
if (!no_way_out)
mce_clear_state(toclear);
@@ -1560,7 +1590,7 @@ noinstr void do_machine_check(struct pt_regs *regs)
no_way_out = worst >= MCE_PANIC_SEVERITY;
if (no_way_out)
- mce_panic("Fatal machine check on current CPU", &m, msg);
+ mce_panic("Fatal machine check on current CPU", &err, msg);
}
} else {
/*
@@ -1572,8 +1602,8 @@ noinstr void do_machine_check(struct pt_regs *regs)
* make sure we have the right "msg".
*/
if (worst >= MCE_PANIC_SEVERITY) {
- mce_severity(&m, regs, &msg, true);
- mce_panic("Local fatal machine check!", &m, msg);
+ mce_severity(m, regs, &msg, true);
+ mce_panic("Local fatal machine check!", &err, msg);
}
}
@@ -1591,16 +1621,16 @@ noinstr void do_machine_check(struct pt_regs *regs)
goto out;
/* Fault was in user mode and we need to take some action */
- if ((m.cs & 3) == 3) {
+ if ((m->cs & 3) == 3) {
/* If this triggers there is no way to recover. Die hard. */
BUG_ON(!on_thread_stack() || !user_mode(regs));
- if (!mce_usable_address(&m))
- queue_task_work(&m, msg, kill_me_now);
+ if (!mce_usable_address(m))
+ queue_task_work(&err, msg, kill_me_now);
else
- queue_task_work(&m, msg, kill_me_maybe);
+ queue_task_work(&err, msg, kill_me_maybe);
- } else if (m.mcgstatus & MCG_STATUS_SEAM_NR) {
+ } else if (m->mcgstatus & MCG_STATUS_SEAM_NR) {
/*
* Saved RIP on stack makes it look like the machine check
* was taken in the kernel on the instruction following
@@ -1612,8 +1642,8 @@ noinstr void do_machine_check(struct pt_regs *regs)
* not occur there. Mark the page as poisoned so it won't
* be added to free list when the guest is terminated.
*/
- if (mce_usable_address(&m)) {
- struct page *p = pfn_to_online_page(m.addr >> PAGE_SHIFT);
+ if (mce_usable_address(m)) {
+ struct page *p = pfn_to_online_page(m->addr >> PAGE_SHIFT);
if (p)
SetPageHWPoison(p);
@@ -1628,13 +1658,13 @@ noinstr void do_machine_check(struct pt_regs *regs)
* corresponding exception handler which would do that is the
* proper one.
*/
- if (m.kflags & MCE_IN_KERNEL_RECOV) {
+ if (m->kflags & MCE_IN_KERNEL_RECOV) {
if (!fixup_exception(regs, X86_TRAP_MC, 0, 0))
- mce_panic("Failed kernel mode recovery", &m, msg);
+ mce_panic("Failed kernel mode recovery", &err, msg);
}
- if (m.kflags & MCE_IN_KERNEL_COPYIN)
- queue_task_work(&m, msg, kill_me_never);
+ if (m->kflags & MCE_IN_KERNEL_COPYIN)
+ queue_task_work(&err, msg, kill_me_never);
}
out:
diff --git a/arch/x86/kernel/cpu/mce/dev-mcelog.c b/arch/x86/kernel/cpu/mce/dev-mcelog.c
index af44fd5dbd7c..8d023239ce18 100644
--- a/arch/x86/kernel/cpu/mce/dev-mcelog.c
+++ b/arch/x86/kernel/cpu/mce/dev-mcelog.c
@@ -264,15 +264,8 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
return put_user(sizeof(struct mce), p);
case MCE_GET_LOG_LEN:
return put_user(mcelog->len, p);
- case MCE_GETCLEAR_FLAGS: {
- unsigned flags;
-
- do {
- flags = mcelog->flags;
- } while (cmpxchg(&mcelog->flags, flags, 0) != flags);
-
- return put_user(flags, p);
- }
+ case MCE_GETCLEAR_FLAGS:
+ return put_user(xchg(&mcelog->flags, 0), p);
default:
return -ENOTTY;
}
diff --git a/arch/x86/kernel/cpu/mce/genpool.c b/arch/x86/kernel/cpu/mce/genpool.c
index 4284749ec803..d0be6dda0c14 100644
--- a/arch/x86/kernel/cpu/mce/genpool.c
+++ b/arch/x86/kernel/cpu/mce/genpool.c
@@ -31,15 +31,15 @@ static LLIST_HEAD(mce_event_llist);
*/
static bool is_duplicate_mce_record(struct mce_evt_llist *t, struct mce_evt_llist *l)
{
+ struct mce_hw_err *err1, *err2;
struct mce_evt_llist *node;
- struct mce *m1, *m2;
- m1 = &t->mce;
+ err1 = &t->err;
llist_for_each_entry(node, &l->llnode, llnode) {
- m2 = &node->mce;
+ err2 = &node->err;
- if (!mce_cmp(m1, m2))
+ if (!mce_cmp(&err1->m, &err2->m))
return true;
}
return false;
@@ -73,8 +73,8 @@ struct llist_node *mce_gen_pool_prepare_records(void)
void mce_gen_pool_process(struct work_struct *__unused)
{
- struct llist_node *head;
struct mce_evt_llist *node, *tmp;
+ struct llist_node *head;
struct mce *mce;
head = llist_del_all(&mce_event_llist);
@@ -83,7 +83,7 @@ void mce_gen_pool_process(struct work_struct *__unused)
head = llist_reverse_order(head);
llist_for_each_entry_safe(node, tmp, head, llnode) {
- mce = &node->mce;
+ mce = &node->err.m;
blocking_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
gen_pool_free(mce_evt_pool, (unsigned long)node, sizeof(*node));
}
@@ -94,11 +94,11 @@ bool mce_gen_pool_empty(void)
return llist_empty(&mce_event_llist);
}
-int mce_gen_pool_add(struct mce *mce)
+int mce_gen_pool_add(struct mce_hw_err *err)
{
struct mce_evt_llist *node;
- if (filter_mce(mce))
+ if (filter_mce(&err->m))
return -EINVAL;
if (!mce_evt_pool)
@@ -110,7 +110,7 @@ int mce_gen_pool_add(struct mce *mce)
return -ENOMEM;
}
- memcpy(&node->mce, mce, sizeof(*mce));
+ memcpy(&node->err, err, sizeof(*err));
llist_add(&node->llnode, &mce_event_llist);
return 0;
diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c
index 49ed3428785d..313fe682db33 100644
--- a/arch/x86/kernel/cpu/mce/inject.c
+++ b/arch/x86/kernel/cpu/mce/inject.c
@@ -502,8 +502,9 @@ static void prepare_msrs(void *info)
static void do_inject(void)
{
- u64 mcg_status = 0;
unsigned int cpu = i_mce.extcpu;
+ struct mce_hw_err err;
+ u64 mcg_status = 0;
u8 b = i_mce.bank;
i_mce.tsc = rdtsc_ordered();
@@ -517,7 +518,8 @@ static void do_inject(void)
i_mce.status |= MCI_STATUS_SYNDV;
if (inj_type == SW_INJ) {
- mce_log(&i_mce);
+ err.m = i_mce;
+ mce_log(&err);
return;
}
diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c
index f6103e6bf69a..b3cd2c61b11d 100644
--- a/arch/x86/kernel/cpu/mce/intel.c
+++ b/arch/x86/kernel/cpu/mce/intel.c
@@ -94,7 +94,7 @@ static int cmci_supported(int *banks)
if (!boot_cpu_has(X86_FEATURE_APIC) || lapic_get_maxlvt() < 6)
return 0;
rdmsrl(MSR_IA32_MCG_CAP, cap);
- *banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
+ *banks = min_t(unsigned, MAX_NR_BANKS, cap & MCG_BANKCNT_MASK);
return !!(cap & MCG_CMCI_P);
}
diff --git a/arch/x86/kernel/cpu/mce/internal.h b/arch/x86/kernel/cpu/mce/internal.h
index 43c7f3b71df5..84f810598231 100644
--- a/arch/x86/kernel/cpu/mce/internal.h
+++ b/arch/x86/kernel/cpu/mce/internal.h
@@ -26,12 +26,12 @@ extern struct blocking_notifier_head x86_mce_decoder_chain;
struct mce_evt_llist {
struct llist_node llnode;
- struct mce mce;
+ struct mce_hw_err err;
};
void mce_gen_pool_process(struct work_struct *__unused);
bool mce_gen_pool_empty(void);
-int mce_gen_pool_add(struct mce *mce);
+int mce_gen_pool_add(struct mce_hw_err *err);
int mce_gen_pool_init(void);
struct llist_node *mce_gen_pool_prepare_records(void);
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 31a73715d755..fb5d0c67fbab 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -34,6 +34,7 @@
#include <asm/setup.h>
#include <asm/cpu.h>
#include <asm/msr.h>
+#include <asm/tlb.h>
#include "internal.h"
@@ -483,11 +484,25 @@ static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc)
}
}
-static int __apply_microcode_amd(struct microcode_amd *mc)
+static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
{
+ unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
u32 rev, dummy;
- native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc->hdr.data_code);
+ native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
+
+ if (x86_family(bsp_cpuid_1_eax) == 0x17) {
+ unsigned long p_addr_end = p_addr + psize - 1;
+
+ invlpg(p_addr);
+
+ /*
+ * Flush next page too if patch image is crossing a page
+ * boundary.
+ */
+ if (p_addr >> PAGE_SHIFT != p_addr_end >> PAGE_SHIFT)
+ invlpg(p_addr_end);
+ }
/* verify patch application was successful */
native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
@@ -529,7 +544,7 @@ static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size)
if (old_rev > mc->hdr.patch_id)
return ret;
- return !__apply_microcode_amd(mc);
+ return !__apply_microcode_amd(mc, desc.psize);
}
static bool get_builtin_microcode(struct cpio_data *cp)
@@ -745,7 +760,7 @@ void reload_ucode_amd(unsigned int cpu)
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
if (rev < mc->hdr.patch_id) {
- if (!__apply_microcode_amd(mc))
+ if (!__apply_microcode_amd(mc, p->size))
pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
}
}
@@ -798,7 +813,7 @@ static enum ucode_state apply_microcode_amd(int cpu)
goto out;
}
- if (__apply_microcode_amd(mc_amd)) {
+ if (__apply_microcode_amd(mc_amd, p->size)) {
pr_err("CPU%d: update failed for patch_level=0x%08x\n",
cpu, mc_amd->hdr.patch_id);
return UCODE_ERROR;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 815fa67356a2..f3d534807d91 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -319,12 +319,6 @@ static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci,
return UCODE_OK;
}
- /*
- * Writeback and invalidate caches before updating microcode to avoid
- * internal issues depending on what the microcode is updating.
- */
- native_wbinvd();
-
/* write microcode via MSR 0x79 */
native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
@@ -574,14 +568,14 @@ static bool is_blacklisted(unsigned int cpu)
/*
* Late loading on model 79 with microcode revision less than 0x0b000021
* and LLC size per core bigger than 2.5MB may result in a system hang.
- * This behavior is documented in item BDF90, #334165 (Intel Xeon
+ * This behavior is documented in item BDX90, #334165 (Intel Xeon
* Processor E7-8800/4800 v4 Product Family).
*/
if (c->x86_vfm == INTEL_BROADWELL_X &&
c->x86_stepping == 0x01 &&
llc_size_per_core > 2621440 &&
c->microcode < 0x0b000021) {
- pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
+ pr_err_once("Erratum BDX90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
return true;
}
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index e65fae63660e..41ed01f46bd9 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -41,11 +41,11 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
"fpu_exception\t: %s\n"
"cpuid level\t: %d\n"
"wp\t\t: yes\n",
- boot_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no",
- boot_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no",
- boot_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no",
- boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
- boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
+ str_yes_no(boot_cpu_has_bug(X86_BUG_FDIV)),
+ str_yes_no(boot_cpu_has_bug(X86_BUG_F00F)),
+ str_yes_no(boot_cpu_has_bug(X86_BUG_COMA)),
+ str_yes_no(boot_cpu_has(X86_FEATURE_FPU)),
+ str_yes_no(boot_cpu_has(X86_FEATURE_FPU)),
c->cpuid_level);
}
#else
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 851b561850e0..5fcb3d635d91 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -1158,11 +1158,12 @@ static __init int snc_get_config(void)
ret = cpus_per_l3 / cpus_per_node;
- /* sanity check: Only valid results are 1, 2, 3, 4 */
+ /* sanity check: Only valid results are 1, 2, 3, 4, 6 */
switch (ret) {
case 1:
break;
case 2 ... 4:
+ case 6:
pr_info("Sub-NUMA Cluster mode detected with %d nodes per L3 cache\n", ret);
rdt_resources_all[RDT_RESOURCE_L3].r_resctrl.mon_scope = RESCTRL_L3_NODE;
break;
diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index d7163b764c62..d906a1cd8491 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -1596,7 +1596,7 @@ static void mondata_config_read(struct rdt_mon_domain *d, struct mon_config_info
static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid)
{
- struct mon_config_info mon_info = {0};
+ struct mon_config_info mon_info;
struct rdt_mon_domain *dom;
bool sep = false;
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index c84c30188fdf..16f3ca30626a 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -24,34 +24,36 @@ struct cpuid_bit {
* levels are different and there is a separate entry for each.
*/
static const struct cpuid_bit cpuid_bits[] = {
- { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 },
- { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
- { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 },
- { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 },
- { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 },
- { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 },
- { X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 },
- { X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 },
- { X86_FEATURE_CQM_MBM_LOCAL, CPUID_EDX, 2, 0x0000000f, 1 },
- { X86_FEATURE_CAT_L3, CPUID_EBX, 1, 0x00000010, 0 },
- { X86_FEATURE_CAT_L2, CPUID_EBX, 2, 0x00000010, 0 },
- { X86_FEATURE_CDP_L3, CPUID_ECX, 2, 0x00000010, 1 },
- { X86_FEATURE_CDP_L2, CPUID_ECX, 2, 0x00000010, 2 },
- { X86_FEATURE_MBA, CPUID_EBX, 3, 0x00000010, 0 },
- { 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 },
- { X86_FEATURE_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 },
- { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
- { X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 },
- { X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 },
- { X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 },
- { X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 },
+ { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 },
+ { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
+ { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 },
+ { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 },
+ { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 },
+ { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 },
+ { X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 },
+ { X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 },
+ { X86_FEATURE_CQM_MBM_LOCAL, CPUID_EDX, 2, 0x0000000f, 1 },
+ { X86_FEATURE_CAT_L3, CPUID_EBX, 1, 0x00000010, 0 },
+ { X86_FEATURE_CAT_L2, CPUID_EBX, 2, 0x00000010, 0 },
+ { X86_FEATURE_CDP_L3, CPUID_ECX, 2, 0x00000010, 1 },
+ { X86_FEATURE_CDP_L2, CPUID_ECX, 2, 0x00000010, 2 },
+ { X86_FEATURE_MBA, CPUID_EBX, 3, 0x00000010, 0 },
+ { 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 },
+ { X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 },
+ { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
+ { X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 },
+ { X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 },
+ { X86_FEATURE_AMD_WORKLOAD_CLASS, CPUID_EAX, 22, 0x80000021, 0 },
+ { X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 },
+ { X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 },
{ X86_FEATURE_AMD_LBR_PMC_FREEZE, CPUID_EAX, 2, 0x80000022, 0 },
+ { X86_FEATURE_AMD_HETEROGENEOUS_CORES, CPUID_EAX, 30, 0x80000026, 0 },
{ 0, 0, 0, 0, 0 }
};
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 9ace84486499..8ce352fc72ac 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -630,7 +630,7 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size,
if (!section->virt_addr)
return false;
- section->pages = vmalloc(nr_pages * sizeof(struct sgx_epc_page));
+ section->pages = vmalloc_array(nr_pages, sizeof(struct sgx_epc_page));
if (!section->pages) {
memunmap(section->virt_addr);
return false;
@@ -901,19 +901,15 @@ static struct miscdevice sgx_dev_provision = {
int sgx_set_attribute(unsigned long *allowed_attributes,
unsigned int attribute_fd)
{
- struct fd f = fdget(attribute_fd);
+ CLASS(fd, f)(attribute_fd);
- if (!fd_file(f))
+ if (fd_empty(f))
return -EINVAL;
- if (fd_file(f)->f_op != &sgx_provision_fops) {
- fdput(f);
+ if (fd_file(f)->f_op != &sgx_provision_fops)
return -EINVAL;
- }
*allowed_attributes |= SGX_ATTR_PROVISIONKEY;
-
- fdput(f);
return 0;
}
EXPORT_SYMBOL_GPL(sgx_set_attribute);
diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c
index 7d476fa697ca..03b3c9c3a45e 100644
--- a/arch/x86/kernel/cpu/topology_amd.c
+++ b/arch/x86/kernel/cpu/topology_amd.c
@@ -182,6 +182,9 @@ static void parse_topology_amd(struct topo_scan *tscan)
if (cpu_feature_enabled(X86_FEATURE_TOPOEXT))
has_topoext = cpu_parse_topology_ext(tscan);
+ if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES))
+ tscan->c->topo.cpu_type = cpuid_ebx(0x80000026);
+
if (!has_topoext && !parse_8000_0008(tscan))
return;
diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c
index 9a6069e7133c..8277c64f88db 100644
--- a/arch/x86/kernel/cpu/topology_common.c
+++ b/arch/x86/kernel/cpu/topology_common.c
@@ -3,6 +3,7 @@
#include <xen/xen.h>
+#include <asm/intel-family.h>
#include <asm/apic.h>
#include <asm/processor.h>
#include <asm/smp.h>
@@ -27,6 +28,36 @@ void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom,
}
}
+enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c)
+{
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
+ switch (c->topo.intel_type) {
+ case INTEL_CPU_TYPE_ATOM: return TOPO_CPU_TYPE_EFFICIENCY;
+ case INTEL_CPU_TYPE_CORE: return TOPO_CPU_TYPE_PERFORMANCE;
+ }
+ }
+ if (c->x86_vendor == X86_VENDOR_AMD) {
+ switch (c->topo.amd_type) {
+ case 0: return TOPO_CPU_TYPE_PERFORMANCE;
+ case 1: return TOPO_CPU_TYPE_EFFICIENCY;
+ }
+ }
+
+ return TOPO_CPU_TYPE_UNKNOWN;
+}
+
+const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c)
+{
+ switch (get_topology_cpu_type(c)) {
+ case TOPO_CPU_TYPE_PERFORMANCE:
+ return "performance";
+ case TOPO_CPU_TYPE_EFFICIENCY:
+ return "efficiency";
+ default:
+ return "unknown";
+ }
+}
+
static unsigned int __maybe_unused parse_num_cores_legacy(struct cpuinfo_x86 *c)
{
struct {
@@ -87,6 +118,7 @@ static void parse_topology(struct topo_scan *tscan, bool early)
.cu_id = 0xff,
.llc_id = BAD_APICID,
.l2c_id = BAD_APICID,
+ .cpu_type = TOPO_CPU_TYPE_UNKNOWN,
};
struct cpuinfo_x86 *c = tscan->c;
struct {
@@ -132,6 +164,8 @@ static void parse_topology(struct topo_scan *tscan, bool early)
case X86_VENDOR_INTEL:
if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan))
parse_legacy(tscan);
+ if (c->cpuid_level >= 0x1a)
+ c->topo.cpu_type = cpuid_eax(0x1a);
break;
case X86_VENDOR_HYGON:
if (IS_ENABLED(CONFIG_CPU_SUP_HYGON))
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 64280879c68c..59d23cdf4ed0 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -305,7 +305,7 @@ void __init x86_flattree_get_config(void)
map_len = size;
}
- early_init_dt_verify(dt);
+ early_init_dt_verify(dt, __pa(dt));
}
unflatten_and_copy_device_tree();
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 29d1f9104e94..6b6f32f40cbe 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -18,7 +18,7 @@
#include <linux/bcma/bcma_regs.h>
#include <linux/platform_data/x86/apple.h>
#include <drm/intel/i915_drm.h>
-#include <drm/intel/i915_pciids.h>
+#include <drm/intel/pciids.h>
#include <asm/pci-direct.h>
#include <asm/dma.h>
#include <asm/io_apic.h>
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 8da0e66ca22d..4dd0ad6c94d6 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -118,10 +118,13 @@ ftrace_modify_code_direct(unsigned long ip, const char *old_code,
return ret;
/* replace the text with the new text */
- if (ftrace_poke_late)
+ if (ftrace_poke_late) {
text_poke_queue((void *)ip, new_code, MCOUNT_INSN_SIZE, NULL);
- else
- text_poke_early((void *)ip, new_code, MCOUNT_INSN_SIZE);
+ } else {
+ mutex_lock(&text_mutex);
+ text_poke((void *)ip, new_code, MCOUNT_INSN_SIZE);
+ mutex_unlock(&text_mutex);
+ }
return 0;
}
@@ -318,7 +321,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 };
unsigned const char retq[] = { RET_INSN_OPCODE, INT3_INSN_OPCODE };
union ftrace_op_code_union op_ptr;
- int ret;
+ void *ret;
if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
start_offset = (unsigned long)ftrace_regs_caller;
@@ -349,15 +352,15 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
/* Copy ftrace_caller onto the trampoline memory */
- ret = copy_from_kernel_nofault(trampoline, (void *)start_offset, size);
- if (WARN_ON(ret < 0))
+ ret = text_poke_copy(trampoline, (void *)start_offset, size);
+ if (WARN_ON(!ret))
goto fail;
ip = trampoline + size;
if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
__text_gen_insn(ip, JMP32_INSN_OPCODE, ip, x86_return_thunk, JMP32_INSN_SIZE);
else
- memcpy(ip, retq, sizeof(retq));
+ text_poke_copy(ip, retq, sizeof(retq));
/* No need to test direct calls on created trampolines */
if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
@@ -365,8 +368,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
ip = trampoline + (jmp_offset - start_offset);
if (WARN_ON(*(char *)ip != 0x75))
goto fail;
- ret = copy_from_kernel_nofault(ip, x86_nops[2], 2);
- if (ret < 0)
+ if (!text_poke_copy(ip, x86_nops[2], 2))
goto fail;
}
@@ -379,7 +381,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
*/
ptr = (unsigned long *)(trampoline + size + RET_SIZE);
- *ptr = (unsigned long)ops;
+ text_poke_copy(ptr, &ops, sizeof(unsigned long));
op_offset -= start_offset;
memcpy(&op_ptr, trampoline + op_offset, OP_REF_SIZE);
@@ -395,7 +397,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
op_ptr.offset = offset;
/* put in the new offset to the ftrace_ops */
- memcpy(trampoline + op_offset, &op_ptr, OP_REF_SIZE);
+ text_poke_copy(trampoline + op_offset, &op_ptr, OP_REF_SIZE);
/* put in the call to the function */
mutex_lock(&text_mutex);
@@ -405,9 +407,9 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
* the depth accounting before the call already.
*/
dest = ftrace_ops_get_func(ops);
- memcpy(trampoline + call_offset,
- text_gen_insn(CALL_INSN_OPCODE, trampoline + call_offset, dest),
- CALL_INSN_SIZE);
+ text_poke_copy_locked(trampoline + call_offset,
+ text_gen_insn(CALL_INSN_OPCODE, trampoline + call_offset, dest),
+ CALL_INSN_SIZE, false);
mutex_unlock(&text_mutex);
/* ALLOC_TRAMP flags lets us know we created it */
@@ -647,7 +649,7 @@ void prepare_ftrace_return(unsigned long ip, unsigned long *parent,
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- struct pt_regs *regs = &fregs->regs;
+ struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
unsigned long *stack = (unsigned long *)kernel_stack_pointer(regs);
prepare_ftrace_return(ip, (unsigned long *)stack, 0);
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 16752b8dfa89..56163e2124cf 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -77,6 +77,7 @@ SYM_CODE_START_NOALIGN(startup_64)
lretq
.Lon_kernel_cs:
+ ANNOTATE_NOENDBR
UNWIND_HINT_END_OF_STACK
#ifdef CONFIG_AMD_MEM_ENCRYPT
diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
index 15af7e98e161..2be55ec3f392 100644
--- a/arch/x86/kernel/kprobes/ftrace.c
+++ b/arch/x86/kernel/kprobes/ftrace.c
@@ -9,6 +9,7 @@
#include <linux/hardirq.h>
#include <linux/preempt.h>
#include <linux/ftrace.h>
+#include <asm/text-patching.h>
#include "common.h"
@@ -36,23 +37,25 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
if (kprobe_running()) {
kprobes_inc_nmissed_count(p);
} else {
- unsigned long orig_ip = regs->ip;
+ unsigned long orig_ip = instruction_pointer(regs);
+
/* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
- regs->ip = ip + sizeof(kprobe_opcode_t);
+ instruction_pointer_set(regs, ip + INT3_INSN_SIZE);
__this_cpu_write(current_kprobe, p);
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
if (!p->pre_handler || !p->pre_handler(p, regs)) {
- /*
- * Emulate singlestep (and also recover regs->ip)
- * as if there is a 5byte nop
- */
- regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE;
if (unlikely(p->post_handler)) {
+ /*
+ * Emulate singlestep (and also recover regs->ip)
+ * as if there is a 5byte nop
+ */
+ instruction_pointer_set(regs, ip + MCOUNT_INSN_SIZE);
kcb->kprobe_status = KPROBE_HIT_SSDONE;
p->post_handler(p, regs, 0);
}
- regs->ip = orig_ip;
+ /* Recover IP address */
+ instruction_pointer_set(regs, orig_ip);
}
/*
* If pre_handler returns !0, it changes regs->ip. We have to
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index 837450b6e882..8984abd91c00 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -146,18 +146,21 @@ static int __write_relocate_add(Elf64_Shdr *sechdrs,
}
if (apply) {
- if (memcmp(loc, &zero, size)) {
+ void *wr_loc = module_writable_address(me, loc);
+
+ if (memcmp(wr_loc, &zero, size)) {
pr_err("x86/modules: Invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n",
(int)ELF64_R_TYPE(rel[i].r_info), loc, val);
return -ENOEXEC;
}
- write(loc, &val, size);
+ write(wr_loc, &val, size);
} else {
if (memcmp(loc, &val, size)) {
pr_warn("x86/modules: Invalid relocation target, existing value does not match expected value for type %d, loc %p, val %Lx\n",
(int)ELF64_R_TYPE(rel[i].r_info), loc, val);
return -ENOEXEC;
}
+ /* FIXME: needs care for ROX module allocations */
write(loc, &zero, size);
}
}
@@ -224,7 +227,7 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
- const Elf_Shdr *s, *alt = NULL, *locks = NULL,
+ const Elf_Shdr *s, *alt = NULL,
*orc = NULL, *orc_ip = NULL,
*retpolines = NULL, *returns = NULL, *ibt_endbr = NULL,
*calls = NULL, *cfi = NULL;
@@ -233,8 +236,6 @@ int module_finalize(const Elf_Ehdr *hdr,
for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
if (!strcmp(".altinstructions", secstrings + s->sh_name))
alt = s;
- if (!strcmp(".smp_locks", secstrings + s->sh_name))
- locks = s;
if (!strcmp(".orc_unwind", secstrings + s->sh_name))
orc = s;
if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name))
@@ -265,20 +266,20 @@ int module_finalize(const Elf_Ehdr *hdr,
csize = cfi->sh_size;
}
- apply_fineibt(rseg, rseg + rsize, cseg, cseg + csize);
+ apply_fineibt(rseg, rseg + rsize, cseg, cseg + csize, me);
}
if (retpolines) {
void *rseg = (void *)retpolines->sh_addr;
- apply_retpolines(rseg, rseg + retpolines->sh_size);
+ apply_retpolines(rseg, rseg + retpolines->sh_size, me);
}
if (returns) {
void *rseg = (void *)returns->sh_addr;
- apply_returns(rseg, rseg + returns->sh_size);
+ apply_returns(rseg, rseg + returns->sh_size, me);
}
if (alt) {
/* patch .altinstructions */
void *aseg = (void *)alt->sh_addr;
- apply_alternatives(aseg, aseg + alt->sh_size);
+ apply_alternatives(aseg, aseg + alt->sh_size, me);
}
if (calls || alt) {
struct callthunk_sites cs = {};
@@ -297,8 +298,28 @@ int module_finalize(const Elf_Ehdr *hdr,
}
if (ibt_endbr) {
void *iseg = (void *)ibt_endbr->sh_addr;
- apply_seal_endbr(iseg, iseg + ibt_endbr->sh_size);
+ apply_seal_endbr(iseg, iseg + ibt_endbr->sh_size, me);
}
+
+ if (orc && orc_ip)
+ unwind_module_init(me, (void *)orc_ip->sh_addr, orc_ip->sh_size,
+ (void *)orc->sh_addr, orc->sh_size);
+
+ return 0;
+}
+
+int module_post_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ const Elf_Shdr *s, *locks = NULL;
+ char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+ if (!strcmp(".smp_locks", secstrings + s->sh_name))
+ locks = s;
+ }
+
if (locks) {
void *lseg = (void *)locks->sh_addr;
void *text = me->mem[MOD_TEXT].base;
@@ -308,10 +329,6 @@ int module_finalize(const Elf_Ehdr *hdr,
text, text_end);
}
- if (orc && orc_ip)
- unwind_module_init(me, (void *)orc_ip->sh_addr, orc_ip->sh_size,
- (void *)orc->sh_addr, orc->sh_size);
-
return 0;
}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 766f092dab80..b5a8f0891135 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -497,8 +497,9 @@ static int x86_cluster_flags(void)
static int x86_die_flags(void)
{
- if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
- return x86_sched_itmt_flags();
+ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU) ||
+ cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES))
+ return x86_sched_itmt_flags();
return 0;
}
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index 87f8c9a71c49..776ae6fa7f2d 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -18,6 +18,7 @@
#include <linux/random.h>
#include <linux/uaccess.h>
#include <linux/elf.h>
+#include <linux/hugetlb.h>
#include <asm/elf.h>
#include <asm/ia32.h>
@@ -25,8 +26,10 @@
/*
* Align a virtual address to avoid aliasing in the I$ on AMD F15h.
*/
-static unsigned long get_align_mask(void)
+static unsigned long get_align_mask(struct file *filp)
{
+ if (filp && is_file_hugepages(filp))
+ return huge_page_mask_align(filp);
/* handle 32- and 64-bit case with a single conditional */
if (va_align.flags < 0 || !(va_align.flags & (2 - mmap_is_ia32())))
return 0;
@@ -49,7 +52,7 @@ static unsigned long get_align_mask(void)
*/
static unsigned long get_align_bits(void)
{
- return va_align.bits & get_align_mask();
+ return va_align.bits & get_align_mask(NULL);
}
static int __init control_va_addr_alignment(char *str)
@@ -148,12 +151,15 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len,
info.length = len;
info.low_limit = begin;
info.high_limit = end;
- info.align_offset = pgoff << PAGE_SHIFT;
- info.start_gap = stack_guard_placement(vm_flags);
+ if (!(filp && is_file_hugepages(filp))) {
+ info.align_offset = pgoff << PAGE_SHIFT;
+ info.start_gap = stack_guard_placement(vm_flags);
+ }
if (filp) {
- info.align_mask = get_align_mask();
+ info.align_mask = get_align_mask(filp);
info.align_offset += get_align_bits();
}
+
return vm_unmapped_area(&info);
}
@@ -199,7 +205,10 @@ get_unmapped_area:
info.low_limit = PAGE_SIZE;
info.high_limit = get_mmap_base(0);
- info.start_gap = stack_guard_placement(vm_flags);
+ if (!(filp && is_file_hugepages(filp))) {
+ info.start_gap = stack_guard_placement(vm_flags);
+ info.align_offset = pgoff << PAGE_SHIFT;
+ }
/*
* If hint address is above DEFAULT_MAP_WINDOW, look for unmapped area
@@ -211,9 +220,8 @@ get_unmapped_area:
if (addr > DEFAULT_MAP_WINDOW && !in_32bit_syscall())
info.high_limit += TASK_SIZE_MAX - DEFAULT_MAP_WINDOW;
- info.align_offset = pgoff << PAGE_SHIFT;
if (filp) {
- info.align_mask = get_align_mask();
+ info.align_mask = get_align_mask(filp);
info.align_offset += get_align_bits();
}
addr = vm_unmapped_area(&info);
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index dfe6847fd99e..67aeaba4ba9c 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -174,10 +174,11 @@ static void __set_cyc2ns_scale(unsigned long khz, int cpu, unsigned long long ts
c2n = per_cpu_ptr(&cyc2ns, cpu);
- raw_write_seqcount_latch(&c2n->seq);
+ write_seqcount_latch_begin(&c2n->seq);
c2n->data[0] = data;
- raw_write_seqcount_latch(&c2n->seq);
+ write_seqcount_latch(&c2n->seq);
c2n->data[1] = data;
+ write_seqcount_latch_end(&c2n->seq);
}
static void set_cyc2ns_scale(unsigned long khz, int cpu, unsigned long long tsc_now)
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index d00c28aaa5be..d4705a348a80 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -723,7 +723,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
state->sp = task->thread.sp + sizeof(*frame);
state->bp = READ_ONCE_NOCHECK(frame->bp);
state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
- state->signal = (void *)state->ip == ret_from_fork;
+ state->signal = (void *)state->ip == ret_from_fork_asm;
}
if (get_stack_info((unsigned long *)state->sp, state->task,
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index b8c5741d2fb4..fab3ac9a4574 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -193,29 +193,6 @@ SECTIONS
ORC_UNWIND_TABLE
- . = ALIGN(PAGE_SIZE);
- __vvar_page = .;
-
- .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) {
- /* work around gold bug 13023 */
- __vvar_beginning_hack = .;
-
- /* Place all vvars at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset) \
- . = __vvar_beginning_hack + offset; \
- *(.vvar_ ## name)
-#include <asm/vvar.h>
-#undef EMIT_VVAR
-
- /*
- * Pad the rest of the page with zeros. Otherwise the loader
- * can leave garbage here.
- */
- . = __vvar_beginning_hack + PAGE_SIZE;
- } :data
-
- . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
-
/* Init code and data - will be freed after init */
. = ALIGN(PAGE_SIZE);
.init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
@@ -443,6 +420,10 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
+#ifdef CONFIG_PROPELLER_CLANG
+ .llvm_bb_addr_map : { *(.llvm_bb_addr_map) }
+#endif
+
ELF_DETAILS
DISCARDS
@@ -491,6 +472,9 @@ SECTIONS
. = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
"kernel image bigger than KERNEL_IMAGE_SIZE");
+/* needed for Clang - see arch/x86/entry/entry.S */
+PROVIDE(__ref_stack_chk_guard = __stack_chk_guard);
+
#ifdef CONFIG_X86_64
/*
* Per-cpu symbols which need to be offset from __per_cpu_load
@@ -528,3 +512,22 @@ INIT_PER_CPU(irq_stack_backing_store);
#endif
#endif /* CONFIG_X86_64 */
+
+/*
+ * The symbols below are referenced using relative relocations in the
+ * respective ELF notes. This produces build time constants that the
+ * linker will never mark as relocatable. (Using just ABSOLUTE() is not
+ * sufficient for that).
+ */
+#ifdef CONFIG_XEN
+#ifdef CONFIG_XEN_PV
+xen_elfnote_entry_value =
+ ABSOLUTE(xen_elfnote_entry) + ABSOLUTE(startup_xen);
+#endif
+xen_elfnote_hypercall_page_value =
+ ABSOLUTE(xen_elfnote_hypercall_page) + ABSOLUTE(hypercall_page);
+#endif
+#ifdef CONFIG_PVH
+xen_elfnote_phys32_entry_value =
+ ABSOLUTE(xen_elfnote_phys32_entry) + ABSOLUTE(pvh_start_xen - LOAD_OFFSET);
+#endif
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index f09f13c01c6b..ea2c4f21c1ca 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -18,10 +18,10 @@ menuconfig VIRTUALIZATION
if VIRTUALIZATION
config KVM_X86
- def_tristate KVM if KVM_INTEL || KVM_AMD
- depends on X86_LOCAL_APIC
+ def_tristate KVM if (KVM_INTEL != n || KVM_AMD != n)
select KVM_COMMON
select KVM_GENERIC_MMU_NOTIFIER
+ select KVM_ELIDE_TLB_FLUSH_IF_YOUNG
select HAVE_KVM_IRQCHIP
select HAVE_KVM_PFNCACHE
select HAVE_KVM_DIRTY_RING_TSO
@@ -29,6 +29,7 @@ config KVM_X86
select HAVE_KVM_IRQ_BYPASS
select HAVE_KVM_IRQ_ROUTING
select HAVE_KVM_READONLY_MEM
+ select VHOST_TASK
select KVM_ASYNC_PF
select USER_RETURN_NOTIFIER
select KVM_MMIO
@@ -49,6 +50,7 @@ config KVM_X86
config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
+ depends on X86_LOCAL_APIC
help
Support hosting fully virtualized guest machines using hardware
virtualization extensions. You will need a fairly recent
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 41786b834b16..097bdc022d0f 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -690,7 +690,9 @@ void kvm_set_cpu_caps(void)
kvm_cpu_cap_set(X86_FEATURE_TSC_ADJUST);
kvm_cpu_cap_set(X86_FEATURE_ARCH_CAPABILITIES);
- if (boot_cpu_has(X86_FEATURE_IBPB) && boot_cpu_has(X86_FEATURE_IBRS))
+ if (boot_cpu_has(X86_FEATURE_AMD_IBPB_RET) &&
+ boot_cpu_has(X86_FEATURE_AMD_IBPB) &&
+ boot_cpu_has(X86_FEATURE_AMD_IBRS))
kvm_cpu_cap_set(X86_FEATURE_SPEC_CTRL);
if (boot_cpu_has(X86_FEATURE_STIBP))
kvm_cpu_cap_set(X86_FEATURE_INTEL_STIBP);
@@ -698,14 +700,14 @@ void kvm_set_cpu_caps(void)
kvm_cpu_cap_set(X86_FEATURE_SPEC_CTRL_SSBD);
kvm_cpu_cap_mask(CPUID_7_1_EAX,
- F(AVX_VNNI) | F(AVX512_BF16) | F(CMPCCXADD) |
- F(FZRM) | F(FSRS) | F(FSRC) |
- F(AMX_FP16) | F(AVX_IFMA) | F(LAM)
+ F(SHA512) | F(SM3) | F(SM4) | F(AVX_VNNI) | F(AVX512_BF16) |
+ F(CMPCCXADD) | F(FZRM) | F(FSRS) | F(FSRC) | F(AMX_FP16) |
+ F(AVX_IFMA) | F(LAM)
);
kvm_cpu_cap_init_kvm_defined(CPUID_7_1_EDX,
- F(AVX_VNNI_INT8) | F(AVX_NE_CONVERT) | F(PREFETCHITI) |
- F(AMX_COMPLEX) | F(AVX10)
+ F(AVX_VNNI_INT8) | F(AVX_NE_CONVERT) | F(AMX_COMPLEX) |
+ F(AVX_VNNI_INT16) | F(PREFETCHITI) | F(AVX10)
);
kvm_cpu_cap_init_kvm_defined(CPUID_7_2_EDX,
@@ -755,7 +757,7 @@ void kvm_set_cpu_caps(void)
F(CLZERO) | F(XSAVEERPTR) |
F(WBNOINVD) | F(AMD_IBPB) | F(AMD_IBRS) | F(AMD_SSBD) | F(VIRT_SSBD) |
F(AMD_SSB_NO) | F(AMD_STIBP) | F(AMD_STIBP_ALWAYS_ON) |
- F(AMD_PSFD)
+ F(AMD_PSFD) | F(AMD_IBPB_RET)
);
/*
@@ -763,8 +765,12 @@ void kvm_set_cpu_caps(void)
* arch/x86/kernel/cpu/bugs.c is kind enough to
* record that in cpufeatures so use them.
*/
- if (boot_cpu_has(X86_FEATURE_IBPB))
+ if (boot_cpu_has(X86_FEATURE_IBPB)) {
kvm_cpu_cap_set(X86_FEATURE_AMD_IBPB);
+ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL) &&
+ !boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB))
+ kvm_cpu_cap_set(X86_FEATURE_AMD_IBPB_RET);
+ }
if (boot_cpu_has(X86_FEATURE_IBRS))
kvm_cpu_cap_set(X86_FEATURE_AMD_IBRS);
if (boot_cpu_has(X86_FEATURE_STIBP))
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 41697cca354e..c8dc66eddefd 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -2,7 +2,6 @@
#ifndef ARCH_X86_KVM_CPUID_H
#define ARCH_X86_KVM_CPUID_H
-#include "x86.h"
#include "reverse_cpuid.h"
#include <asm/cpu.h>
#include <asm/processor.h>
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index e72aed25d721..60986f67c35a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -651,9 +651,10 @@ static inline u8 ctxt_virt_addr_bits(struct x86_emulate_ctxt *ctxt)
}
static inline bool emul_is_noncanonical_address(u64 la,
- struct x86_emulate_ctxt *ctxt)
+ struct x86_emulate_ctxt *ctxt,
+ unsigned int flags)
{
- return !__is_canonical_address(la, ctxt_virt_addr_bits(ctxt));
+ return !ctxt->ops->is_canonical_addr(ctxt, la, flags);
}
/*
@@ -1733,7 +1734,8 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
if (ret != X86EMUL_CONTINUE)
return ret;
if (emul_is_noncanonical_address(get_desc_base(&seg_desc) |
- ((u64)base3 << 32), ctxt))
+ ((u64)base3 << 32), ctxt,
+ X86EMUL_F_DT_LOAD))
return emulate_gp(ctxt, err_code);
}
@@ -2516,8 +2518,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
ss_sel = cs_sel + 8;
cs.d = 0;
cs.l = 1;
- if (emul_is_noncanonical_address(rcx, ctxt) ||
- emul_is_noncanonical_address(rdx, ctxt))
+ if (emul_is_noncanonical_address(rcx, ctxt, 0) ||
+ emul_is_noncanonical_address(rdx, ctxt, 0))
return emulate_gp(ctxt, 0);
break;
}
@@ -3494,7 +3496,8 @@ static int em_lgdt_lidt(struct x86_emulate_ctxt *ctxt, bool lgdt)
if (rc != X86EMUL_CONTINUE)
return rc;
if (ctxt->mode == X86EMUL_MODE_PROT64 &&
- emul_is_noncanonical_address(desc_ptr.address, ctxt))
+ emul_is_noncanonical_address(desc_ptr.address, ctxt,
+ X86EMUL_F_DT_LOAD))
return emulate_gp(ctxt, 0);
if (lgdt)
ctxt->ops->set_gdt(ctxt, &desc_ptr);
diff --git a/arch/x86/kvm/kvm_cache_regs.h b/arch/x86/kvm/kvm_cache_regs.h
index b1eb46e26b2e..36a8786db291 100644
--- a/arch/x86/kvm/kvm_cache_regs.h
+++ b/arch/x86/kvm/kvm_cache_regs.h
@@ -44,6 +44,18 @@ BUILD_KVM_GPR_ACCESSORS(r15, R15)
#endif
/*
+ * Using the register cache from interrupt context is generally not allowed, as
+ * caching a register and marking it available/dirty can't be done atomically,
+ * i.e. accesses from interrupt context may clobber state or read stale data if
+ * the vCPU task is in the process of updating the cache. The exception is if
+ * KVM is handling a PMI IRQ/NMI VM-Exit, as that bound code sequence doesn't
+ * touch the cache, it runs after the cache is reset (post VM-Exit), and PMIs
+ * need to access several registers that are cacheable.
+ */
+#define kvm_assert_register_caching_allowed(vcpu) \
+ lockdep_assert_once(in_task() || kvm_arch_pmi_in_guest(vcpu))
+
+/*
* avail dirty
* 0 0 register in VMCS/VMCB
* 0 1 *INVALID*
@@ -53,24 +65,28 @@ BUILD_KVM_GPR_ACCESSORS(r15, R15)
static inline bool kvm_register_is_available(struct kvm_vcpu *vcpu,
enum kvm_reg reg)
{
+ kvm_assert_register_caching_allowed(vcpu);
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
}
static inline bool kvm_register_is_dirty(struct kvm_vcpu *vcpu,
enum kvm_reg reg)
{
+ kvm_assert_register_caching_allowed(vcpu);
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
}
static inline void kvm_register_mark_available(struct kvm_vcpu *vcpu,
enum kvm_reg reg)
{
+ kvm_assert_register_caching_allowed(vcpu);
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
}
static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
enum kvm_reg reg)
{
+ kvm_assert_register_caching_allowed(vcpu);
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
}
@@ -84,6 +100,7 @@ static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
static __always_inline bool kvm_register_test_and_mark_available(struct kvm_vcpu *vcpu,
enum kvm_reg reg)
{
+ kvm_assert_register_caching_allowed(vcpu);
return arch___test_and_set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
}
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index 55a18e2f2dcd..10495fffb890 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -94,6 +94,8 @@ struct x86_instruction_info {
#define X86EMUL_F_FETCH BIT(1)
#define X86EMUL_F_IMPLICIT BIT(2)
#define X86EMUL_F_INVLPG BIT(3)
+#define X86EMUL_F_MSR BIT(4)
+#define X86EMUL_F_DT_LOAD BIT(5)
struct x86_emulate_ops {
void (*vm_bugged)(struct x86_emulate_ctxt *ctxt);
@@ -235,6 +237,9 @@ struct x86_emulate_ops {
gva_t (*get_untagged_addr)(struct x86_emulate_ctxt *ctxt, gva_t addr,
unsigned int flags);
+
+ bool (*is_canonical_addr)(struct x86_emulate_ctxt *ctxt, gva_t addr,
+ unsigned int flags);
};
/* Type, address-of, and value of an instruction's operand. */
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2098dc689088..3c83951c619e 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -382,7 +382,7 @@ enum {
DIRTY
};
-void kvm_recalculate_apic_map(struct kvm *kvm)
+static void kvm_recalculate_apic_map(struct kvm *kvm)
{
struct kvm_apic_map *new, *old = NULL;
struct kvm_vcpu *vcpu;
@@ -2577,7 +2577,7 @@ u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
return (tpr & 0xf0) >> 4;
}
-void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
+static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value)
{
u64 old_value = vcpu->arch.apic_base;
struct kvm_lapic *apic = vcpu->arch.apic;
@@ -2625,29 +2625,60 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
}
}
+int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated)
+{
+ enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
+ enum lapic_mode new_mode = kvm_apic_mode(value);
+
+ if (vcpu->arch.apic_base == value)
+ return 0;
+
+ u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
+ (guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
+
+ if ((value & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
+ return 1;
+ if (!host_initiated) {
+ if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
+ return 1;
+ if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
+ return 1;
+ }
+
+ __kvm_apic_set_base(vcpu, value);
+ kvm_recalculate_apic_map(vcpu->kvm);
+ return 0;
+}
+
void kvm_apic_update_apicv(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;
- if (apic->apicv_active) {
- /* irr_pending is always true when apicv is activated. */
- apic->irr_pending = true;
+ /*
+ * When APICv is enabled, KVM must always search the IRR for a pending
+ * IRQ, as other vCPUs and devices can set IRR bits even if the vCPU
+ * isn't running. If APICv is disabled, KVM _should_ search the IRR
+ * for a pending IRQ. But KVM currently doesn't ensure *all* hardware,
+ * e.g. CPUs and IOMMUs, has seen the change in state, i.e. searching
+ * the IRR at this time could race with IRQ delivery from hardware that
+ * still sees APICv as being enabled.
+ *
+ * FIXME: Ensure other vCPUs and devices observe the change in APICv
+ * state prior to updating KVM's metadata caches, so that KVM
+ * can safely search the IRR and set irr_pending accordingly.
+ */
+ apic->irr_pending = true;
+
+ if (apic->apicv_active)
apic->isr_count = 1;
- } else {
- /*
- * Don't clear irr_pending, searching the IRR can race with
- * updates from the CPU as APICv is still active from hardware's
- * perspective. The flag will be cleared as appropriate when
- * KVM injects the interrupt.
- */
+ else
apic->isr_count = count_vectors(apic->regs + APIC_ISR);
- }
+
apic->highest_isr_cache = -1;
}
int kvm_alloc_apic_access_page(struct kvm *kvm)
{
- struct page *page;
void __user *hva;
int ret = 0;
@@ -2663,17 +2694,6 @@ int kvm_alloc_apic_access_page(struct kvm *kvm)
goto out;
}
- page = gfn_to_page(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
- if (is_error_page(page)) {
- ret = -EFAULT;
- goto out;
- }
-
- /*
- * Do not pin the page in memory, so that memory hot-unplug
- * is able to migrate it.
- */
- put_page(page);
kvm->arch.apic_access_memslot_enabled = true;
out:
mutex_unlock(&kvm->slots_lock);
@@ -2728,7 +2748,14 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
msr_val = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
if (kvm_vcpu_is_reset_bsp(vcpu))
msr_val |= MSR_IA32_APICBASE_BSP;
- kvm_lapic_set_base(vcpu, msr_val);
+
+ /*
+ * Use the inner helper to avoid an extra recalcuation of the
+ * optimized APIC map if some other task has dirtied the map.
+ * The recalculation needed for this vCPU will be done after
+ * all APIC state has been initialized (see below).
+ */
+ __kvm_apic_set_base(vcpu, msr_val);
}
if (!apic)
@@ -3069,7 +3096,6 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
kvm_x86_call(apicv_pre_state_restore)(vcpu);
- kvm_lapic_set_base(vcpu, vcpu->arch.apic_base);
/* set SPIV separately to get count of SW disabled APICs right */
apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 1b8ef9856422..24add38beaf0 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -95,8 +95,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event);
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
-void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
-void kvm_recalculate_apic_map(struct kvm *kvm);
void kvm_apic_set_version(struct kvm_vcpu *vcpu);
void kvm_apic_after_set_mcg_cap(struct kvm_vcpu *vcpu);
bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
@@ -117,11 +115,9 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
-u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
-int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
+int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated);
int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
-enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu);
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
@@ -271,6 +267,11 @@ static inline enum lapic_mode kvm_apic_mode(u64 apic_base)
return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
}
+static inline enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
+{
+ return kvm_apic_mode(vcpu->arch.apic_base);
+}
+
static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
{
return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 9dc5dd43ae7f..e9322358678b 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -4,6 +4,7 @@
#include <linux/kvm_host.h>
#include "kvm_cache_regs.h"
+#include "x86.h"
#include "cpuid.h"
extern bool __read_mostly enable_mmio_caching;
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 8e853a5fc867..22e7ad235123 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -179,7 +179,6 @@ struct kvm_shadow_walk_iterator {
static struct kmem_cache *pte_list_desc_cache;
struct kmem_cache *mmu_page_header_cache;
-static struct percpu_counter kvm_total_used_mmu_pages;
static void mmu_spte_set(u64 *sptep, u64 spte);
@@ -485,11 +484,12 @@ static void mmu_spte_set(u64 *sptep, u64 new_spte)
__set_spte(sptep, new_spte);
}
-/*
- * Update the SPTE (excluding the PFN), but do not track changes in its
- * accessed/dirty status.
+/* Rules for using mmu_spte_update:
+ * Update the state bits, it means the mapped pfn is not changed.
+ *
+ * Returns true if the TLB needs to be flushed
*/
-static u64 mmu_spte_update_no_track(u64 *sptep, u64 new_spte)
+static bool mmu_spte_update(u64 *sptep, u64 new_spte)
{
u64 old_spte = *sptep;
@@ -498,7 +498,7 @@ static u64 mmu_spte_update_no_track(u64 *sptep, u64 new_spte)
if (!is_shadow_present_pte(old_spte)) {
mmu_spte_set(sptep, new_spte);
- return old_spte;
+ return false;
}
if (!spte_has_volatile_bits(old_spte))
@@ -506,53 +506,10 @@ static u64 mmu_spte_update_no_track(u64 *sptep, u64 new_spte)
else
old_spte = __update_clear_spte_slow(sptep, new_spte);
- WARN_ON_ONCE(spte_to_pfn(old_spte) != spte_to_pfn(new_spte));
+ WARN_ON_ONCE(!is_shadow_present_pte(old_spte) ||
+ spte_to_pfn(old_spte) != spte_to_pfn(new_spte));
- return old_spte;
-}
-
-/* Rules for using mmu_spte_update:
- * Update the state bits, it means the mapped pfn is not changed.
- *
- * Whenever an MMU-writable SPTE is overwritten with a read-only SPTE, remote
- * TLBs must be flushed. Otherwise rmap_write_protect will find a read-only
- * spte, even though the writable spte might be cached on a CPU's TLB.
- *
- * Returns true if the TLB needs to be flushed
- */
-static bool mmu_spte_update(u64 *sptep, u64 new_spte)
-{
- bool flush = false;
- u64 old_spte = mmu_spte_update_no_track(sptep, new_spte);
-
- if (!is_shadow_present_pte(old_spte))
- return false;
-
- /*
- * For the spte updated out of mmu-lock is safe, since
- * we always atomically update it, see the comments in
- * spte_has_volatile_bits().
- */
- if (is_mmu_writable_spte(old_spte) &&
- !is_writable_pte(new_spte))
- flush = true;
-
- /*
- * Flush TLB when accessed/dirty states are changed in the page tables,
- * to guarantee consistency between TLB and page tables.
- */
-
- if (is_accessed_spte(old_spte) && !is_accessed_spte(new_spte)) {
- flush = true;
- kvm_set_pfn_accessed(spte_to_pfn(old_spte));
- }
-
- if (is_dirty_spte(old_spte) && !is_dirty_spte(new_spte)) {
- flush = true;
- kvm_set_pfn_dirty(spte_to_pfn(old_spte));
- }
-
- return flush;
+ return leaf_spte_change_needs_tlb_flush(old_spte, new_spte);
}
/*
@@ -563,10 +520,8 @@ static bool mmu_spte_update(u64 *sptep, u64 new_spte)
*/
static u64 mmu_spte_clear_track_bits(struct kvm *kvm, u64 *sptep)
{
- kvm_pfn_t pfn;
u64 old_spte = *sptep;
int level = sptep_to_sp(sptep)->role.level;
- struct page *page;
if (!is_shadow_present_pte(old_spte) ||
!spte_has_volatile_bits(old_spte))
@@ -578,24 +533,6 @@ static u64 mmu_spte_clear_track_bits(struct kvm *kvm, u64 *sptep)
return old_spte;
kvm_update_page_stats(kvm, level, -1);
-
- pfn = spte_to_pfn(old_spte);
-
- /*
- * KVM doesn't hold a reference to any pages mapped into the guest, and
- * instead uses the mmu_notifier to ensure that KVM unmaps any pages
- * before they are reclaimed. Sanity check that, if the pfn is backed
- * by a refcounted page, the refcount is elevated.
- */
- page = kvm_pfn_to_refcounted_page(pfn);
- WARN_ON_ONCE(page && !page_count(page));
-
- if (is_accessed_spte(old_spte))
- kvm_set_pfn_accessed(pfn);
-
- if (is_dirty_spte(old_spte))
- kvm_set_pfn_dirty(pfn);
-
return old_spte;
}
@@ -1250,16 +1187,6 @@ static bool spte_clear_dirty(u64 *sptep)
return mmu_spte_update(sptep, spte);
}
-static bool spte_wrprot_for_clear_dirty(u64 *sptep)
-{
- bool was_writable = test_and_clear_bit(PT_WRITABLE_SHIFT,
- (unsigned long *)sptep);
- if (was_writable && !spte_ad_enabled(*sptep))
- kvm_set_pfn_dirty(spte_to_pfn(*sptep));
-
- return was_writable;
-}
-
/*
* Gets the GFN ready for another round of dirty logging by clearing the
* - D bit on ad-enabled SPTEs, and
@@ -1275,7 +1202,8 @@ static bool __rmap_clear_dirty(struct kvm *kvm, struct kvm_rmap_head *rmap_head,
for_each_rmap_spte(rmap_head, &iter, sptep)
if (spte_ad_need_write_protect(*sptep))
- flush |= spte_wrprot_for_clear_dirty(sptep);
+ flush |= test_and_clear_bit(PT_WRITABLE_SHIFT,
+ (unsigned long *)sptep);
else
flush |= spte_clear_dirty(sptep);
@@ -1640,15 +1568,12 @@ static bool kvm_rmap_age_gfn_range(struct kvm *kvm,
(unsigned long *)sptep);
} else {
/*
- * Capture the dirty status of the page, so that
- * it doesn't get lost when the SPTE is marked
- * for access tracking.
+ * WARN if mmu_spte_update() signals the need
+ * for a TLB flush, as Access tracking a SPTE
+ * should never trigger an _immediate_ flush.
*/
- if (is_writable_pte(spte))
- kvm_set_pfn_dirty(spte_to_pfn(spte));
-
spte = mark_spte_for_access_track(spte);
- mmu_spte_update_no_track(sptep, spte);
+ WARN_ON_ONCE(mmu_spte_update(sptep, spte));
}
young = true;
}
@@ -1696,27 +1621,15 @@ static void kvm_mmu_check_sptes_at_free(struct kvm_mmu_page *sp)
#endif
}
-/*
- * This value is the sum of all of the kvm instances's
- * kvm->arch.n_used_mmu_pages values. We need a global,
- * aggregate version in order to make the slab shrinker
- * faster
- */
-static inline void kvm_mod_used_mmu_pages(struct kvm *kvm, long nr)
-{
- kvm->arch.n_used_mmu_pages += nr;
- percpu_counter_add(&kvm_total_used_mmu_pages, nr);
-}
-
static void kvm_account_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
- kvm_mod_used_mmu_pages(kvm, +1);
+ kvm->arch.n_used_mmu_pages++;
kvm_account_pgtable_pages((void *)sp->spt, +1);
}
static void kvm_unaccount_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
- kvm_mod_used_mmu_pages(kvm, -1);
+ kvm->arch.n_used_mmu_pages--;
kvm_account_pgtable_pages((void *)sp->spt, -1);
}
@@ -2802,7 +2715,7 @@ static void kvm_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp)
* be write-protected.
*/
int mmu_try_to_unsync_pages(struct kvm *kvm, const struct kvm_memory_slot *slot,
- gfn_t gfn, bool can_unsync, bool prefetch)
+ gfn_t gfn, bool synchronizing, bool prefetch)
{
struct kvm_mmu_page *sp;
bool locked = false;
@@ -2817,12 +2730,12 @@ int mmu_try_to_unsync_pages(struct kvm *kvm, const struct kvm_memory_slot *slot,
/*
* The page is not write-tracked, mark existing shadow pages unsync
- * unless KVM is synchronizing an unsync SP (can_unsync = false). In
- * that case, KVM must complete emulation of the guest TLB flush before
- * allowing shadow pages to become unsync (writable by the guest).
+ * unless KVM is synchronizing an unsync SP. In that case, KVM must
+ * complete emulation of the guest TLB flush before allowing shadow
+ * pages to become unsync (writable by the guest).
*/
for_each_gfn_valid_sp_with_gptes(kvm, sp, gfn) {
- if (!can_unsync)
+ if (synchronizing)
return -EPERM;
if (sp->unsync)
@@ -2926,6 +2839,9 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
}
if (is_shadow_present_pte(*sptep)) {
+ if (prefetch)
+ return RET_PF_SPURIOUS;
+
/*
* If we overwrite a PTE page pointer with a 2MB PMD, unlink
* the parent of the now unreachable PTE.
@@ -2945,7 +2861,7 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
}
wrprot = make_spte(vcpu, sp, slot, pte_access, gfn, pfn, *sptep, prefetch,
- true, host_writable, &spte);
+ false, host_writable, &spte);
if (*sptep == spte) {
ret = RET_PF_SPURIOUS;
@@ -2971,32 +2887,51 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
return ret;
}
-static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *sp,
- u64 *start, u64 *end)
+static bool kvm_mmu_prefetch_sptes(struct kvm_vcpu *vcpu, gfn_t gfn, u64 *sptep,
+ int nr_pages, unsigned int access)
{
struct page *pages[PTE_PREFETCH_NUM];
struct kvm_memory_slot *slot;
- unsigned int access = sp->role.access;
- int i, ret;
- gfn_t gfn;
+ int i;
+
+ if (WARN_ON_ONCE(nr_pages > PTE_PREFETCH_NUM))
+ return false;
- gfn = kvm_mmu_page_get_gfn(sp, spte_index(start));
slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, access & ACC_WRITE_MASK);
if (!slot)
- return -1;
+ return false;
- ret = gfn_to_page_many_atomic(slot, gfn, pages, end - start);
- if (ret <= 0)
- return -1;
+ nr_pages = kvm_prefetch_pages(slot, gfn, pages, nr_pages);
+ if (nr_pages <= 0)
+ return false;
- for (i = 0; i < ret; i++, gfn++, start++) {
- mmu_set_spte(vcpu, slot, start, access, gfn,
+ for (i = 0; i < nr_pages; i++, gfn++, sptep++) {
+ mmu_set_spte(vcpu, slot, sptep, access, gfn,
page_to_pfn(pages[i]), NULL);
- put_page(pages[i]);
+
+ /*
+ * KVM always prefetches writable pages from the primary MMU,
+ * and KVM can make its SPTE writable in the fast page handler,
+ * without notifying the primary MMU. Mark pages/folios dirty
+ * now to ensure file data is written back if it ends up being
+ * written by the guest. Because KVM's prefetching GUPs
+ * writable PTEs, the probability of unnecessary writeback is
+ * extremely low.
+ */
+ kvm_release_page_dirty(pages[i]);
}
- return 0;
+ return true;
+}
+
+static bool direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *sp,
+ u64 *start, u64 *end)
+{
+ gfn_t gfn = kvm_mmu_page_get_gfn(sp, spte_index(start));
+ unsigned int access = sp->role.access;
+
+ return kvm_mmu_prefetch_sptes(vcpu, gfn, start, end - start, access);
}
static void __direct_pte_prefetch(struct kvm_vcpu *vcpu,
@@ -3014,8 +2949,9 @@ static void __direct_pte_prefetch(struct kvm_vcpu *vcpu,
if (is_shadow_present_pte(*spte) || spte == sptep) {
if (!start)
continue;
- if (direct_pte_prefetch_many(vcpu, sp, start, spte) < 0)
+ if (!direct_pte_prefetch_many(vcpu, sp, start, spte))
return;
+
start = NULL;
} else if (!start)
start = spte;
@@ -3165,13 +3101,12 @@ static int __kvm_mmu_max_mapping_level(struct kvm *kvm,
}
int kvm_mmu_max_mapping_level(struct kvm *kvm,
- const struct kvm_memory_slot *slot, gfn_t gfn,
- int max_level)
+ const struct kvm_memory_slot *slot, gfn_t gfn)
{
bool is_private = kvm_slot_can_be_private(slot) &&
kvm_mem_is_private(kvm, gfn);
- return __kvm_mmu_max_mapping_level(kvm, slot, gfn, max_level, is_private);
+ return __kvm_mmu_max_mapping_level(kvm, slot, gfn, PG_LEVEL_NUM, is_private);
}
void kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
@@ -3322,7 +3257,6 @@ static int kvm_handle_noslot_fault(struct kvm_vcpu *vcpu,
fault->slot = NULL;
fault->pfn = KVM_PFN_NOSLOT;
fault->map_writable = false;
- fault->hva = KVM_HVA_ERR_BAD;
/*
* If MMIO caching is disabled, emulate immediately without
@@ -3392,7 +3326,7 @@ static bool page_fault_can_be_fast(struct kvm *kvm, struct kvm_page_fault *fault
* by setting the Writable bit, which can be done out of mmu_lock.
*/
if (!fault->present)
- return !kvm_ad_enabled();
+ return !kvm_ad_enabled;
/*
* Note, instruction fetches and writes are mutually exclusive, ignore
@@ -3419,7 +3353,7 @@ static bool fast_pf_fix_direct_spte(struct kvm_vcpu *vcpu,
* harm. This also avoids the TLB flush needed after setting dirty bit
* so non-PML cases won't be impacted.
*
- * Compare with set_spte where instead shadow_dirty_mask is set.
+ * Compare with make_spte() where instead shadow_dirty_mask is set.
*/
if (!try_cmpxchg64(sptep, &old_spte, new_spte))
return false;
@@ -3527,8 +3461,9 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
* uses A/D bits for non-nested MMUs. Thus, if A/D bits are
* enabled, the SPTE can't be an access-tracked SPTE.
*/
- if (unlikely(!kvm_ad_enabled()) && is_access_track_spte(spte))
- new_spte = restore_acc_track_spte(new_spte);
+ if (unlikely(!kvm_ad_enabled) && is_access_track_spte(spte))
+ new_spte = restore_acc_track_spte(new_spte) |
+ shadow_accessed_mask;
/*
* To keep things simple, only SPTEs that are MMU-writable can
@@ -4376,8 +4311,15 @@ static u8 kvm_max_private_mapping_level(struct kvm *kvm, kvm_pfn_t pfn,
return max_level;
}
-static int kvm_faultin_pfn_private(struct kvm_vcpu *vcpu,
- struct kvm_page_fault *fault)
+static void kvm_mmu_finish_page_fault(struct kvm_vcpu *vcpu,
+ struct kvm_page_fault *fault, int r)
+{
+ kvm_release_faultin_page(vcpu->kvm, fault->refcounted_page,
+ r == RET_PF_RETRY, fault->map_writable);
+}
+
+static int kvm_mmu_faultin_pfn_private(struct kvm_vcpu *vcpu,
+ struct kvm_page_fault *fault)
{
int max_order, r;
@@ -4387,7 +4329,7 @@ static int kvm_faultin_pfn_private(struct kvm_vcpu *vcpu,
}
r = kvm_gmem_get_pfn(vcpu->kvm, fault->slot, fault->gfn, &fault->pfn,
- &max_order);
+ &fault->refcounted_page, &max_order);
if (r) {
kvm_mmu_prepare_memory_fault_exit(vcpu, fault);
return r;
@@ -4400,19 +4342,26 @@ static int kvm_faultin_pfn_private(struct kvm_vcpu *vcpu,
return RET_PF_CONTINUE;
}
-static int __kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
+static int __kvm_mmu_faultin_pfn(struct kvm_vcpu *vcpu,
+ struct kvm_page_fault *fault)
{
- bool async;
+ unsigned int foll = fault->write ? FOLL_WRITE : 0;
if (fault->is_private)
- return kvm_faultin_pfn_private(vcpu, fault);
+ return kvm_mmu_faultin_pfn_private(vcpu, fault);
- async = false;
- fault->pfn = __gfn_to_pfn_memslot(fault->slot, fault->gfn, false, false,
- &async, fault->write,
- &fault->map_writable, &fault->hva);
- if (!async)
- return RET_PF_CONTINUE; /* *pfn has correct page already */
+ foll |= FOLL_NOWAIT;
+ fault->pfn = __kvm_faultin_pfn(fault->slot, fault->gfn, foll,
+ &fault->map_writable, &fault->refcounted_page);
+
+ /*
+ * If resolving the page failed because I/O is needed to fault-in the
+ * page, then either set up an asynchronous #PF to do the I/O, or if
+ * doing an async #PF isn't possible, retry with I/O allowed. All
+ * other failures are terminal, i.e. retrying won't help.
+ */
+ if (fault->pfn != KVM_PFN_ERR_NEEDS_IO)
+ return RET_PF_CONTINUE;
if (!fault->prefetch && kvm_can_do_async_pf(vcpu)) {
trace_kvm_try_async_get_page(fault->addr, fault->gfn);
@@ -4430,14 +4379,16 @@ static int __kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
* to wait for IO. Note, gup always bails if it is unable to quickly
* get a page and a fatal signal, i.e. SIGKILL, is pending.
*/
- fault->pfn = __gfn_to_pfn_memslot(fault->slot, fault->gfn, false, true,
- NULL, fault->write,
- &fault->map_writable, &fault->hva);
+ foll |= FOLL_INTERRUPTIBLE;
+ foll &= ~FOLL_NOWAIT;
+ fault->pfn = __kvm_faultin_pfn(fault->slot, fault->gfn, foll,
+ &fault->map_writable, &fault->refcounted_page);
+
return RET_PF_CONTINUE;
}
-static int kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault,
- unsigned int access)
+static int kvm_mmu_faultin_pfn(struct kvm_vcpu *vcpu,
+ struct kvm_page_fault *fault, unsigned int access)
{
struct kvm_memory_slot *slot = fault->slot;
int ret;
@@ -4520,7 +4471,7 @@ static int kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault,
if (mmu_invalidate_retry_gfn_unsafe(vcpu->kvm, fault->mmu_seq, fault->gfn))
return RET_PF_RETRY;
- ret = __kvm_faultin_pfn(vcpu, fault);
+ ret = __kvm_mmu_faultin_pfn(vcpu, fault);
if (ret != RET_PF_CONTINUE)
return ret;
@@ -4538,7 +4489,7 @@ static int kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault,
* mmu_lock is acquired.
*/
if (mmu_invalidate_retry_gfn_unsafe(vcpu->kvm, fault->mmu_seq, fault->gfn)) {
- kvm_release_pfn_clean(fault->pfn);
+ kvm_mmu_finish_page_fault(vcpu, fault, RET_PF_RETRY);
return RET_PF_RETRY;
}
@@ -4597,7 +4548,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
if (r)
return r;
- r = kvm_faultin_pfn(vcpu, fault, ACC_ALL);
+ r = kvm_mmu_faultin_pfn(vcpu, fault, ACC_ALL);
if (r != RET_PF_CONTINUE)
return r;
@@ -4614,8 +4565,8 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
r = direct_map(vcpu, fault);
out_unlock:
+ kvm_mmu_finish_page_fault(vcpu, fault, r);
write_unlock(&vcpu->kvm->mmu_lock);
- kvm_release_pfn_clean(fault->pfn);
return r;
}
@@ -4688,7 +4639,7 @@ static int kvm_tdp_mmu_page_fault(struct kvm_vcpu *vcpu,
if (r)
return r;
- r = kvm_faultin_pfn(vcpu, fault, ACC_ALL);
+ r = kvm_mmu_faultin_pfn(vcpu, fault, ACC_ALL);
if (r != RET_PF_CONTINUE)
return r;
@@ -4701,8 +4652,8 @@ static int kvm_tdp_mmu_page_fault(struct kvm_vcpu *vcpu,
r = kvm_tdp_mmu_map(vcpu, fault);
out_unlock:
+ kvm_mmu_finish_page_fault(vcpu, fault, r);
read_unlock(&vcpu->kvm->mmu_lock);
- kvm_release_pfn_clean(fault->pfn);
return r;
}
#endif
@@ -5488,7 +5439,7 @@ kvm_calc_tdp_mmu_root_page_role(struct kvm_vcpu *vcpu,
role.efer_nx = true;
role.smm = cpu_role.base.smm;
role.guest_mode = cpu_role.base.guest_mode;
- role.ad_disabled = !kvm_ad_enabled();
+ role.ad_disabled = !kvm_ad_enabled;
role.level = kvm_mmu_get_tdp_level(vcpu);
role.direct = true;
role.has_4_byte_gpte = false;
@@ -6228,7 +6179,7 @@ void kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
/* It's actually a GPA for vcpu->arch.guest_mmu. */
if (mmu != &vcpu->arch.guest_mmu) {
/* INVLPG on a non-canonical address is a NOP according to the SDM. */
- if (is_noncanonical_address(addr, vcpu))
+ if (is_noncanonical_invlpg_address(addr, vcpu))
return;
kvm_x86_call(flush_tlb_gva)(vcpu, addr);
@@ -6416,8 +6367,11 @@ static void kvm_zap_obsolete_pages(struct kvm *kvm)
{
struct kvm_mmu_page *sp, *node;
int nr_zapped, batch = 0;
+ LIST_HEAD(invalid_list);
bool unstable;
+ lockdep_assert_held(&kvm->slots_lock);
+
restart:
list_for_each_entry_safe_reverse(sp, node,
&kvm->arch.active_mmu_pages, link) {
@@ -6449,7 +6403,7 @@ restart:
}
unstable = __kvm_mmu_prepare_zap_page(kvm, sp,
- &kvm->arch.zapped_obsolete_pages, &nr_zapped);
+ &invalid_list, &nr_zapped);
batch += nr_zapped;
if (unstable)
@@ -6465,7 +6419,7 @@ restart:
* kvm_mmu_load()), and the reload in the caller ensure no vCPUs are
* running with an obsolete MMU.
*/
- kvm_mmu_commit_zap_page(kvm, &kvm->arch.zapped_obsolete_pages);
+ kvm_mmu_commit_zap_page(kvm, &invalid_list);
}
/*
@@ -6528,16 +6482,10 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
kvm_tdp_mmu_zap_invalidated_roots(kvm);
}
-static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm)
-{
- return unlikely(!list_empty_careful(&kvm->arch.zapped_obsolete_pages));
-}
-
void kvm_mmu_init_vm(struct kvm *kvm)
{
kvm->arch.shadow_mmio_value = shadow_mmio_value;
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
- INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
INIT_LIST_HEAD(&kvm->arch.possible_nx_huge_pages);
spin_lock_init(&kvm->arch.mmu_unsync_pages_lock);
@@ -6771,7 +6719,7 @@ static void shadow_mmu_split_huge_page(struct kvm *kvm,
continue;
}
- spte = make_huge_page_split_spte(kvm, huge_spte, sp->role, index);
+ spte = make_small_spte(kvm, huge_spte, sp->role, index);
mmu_spte_set(sptep, spte);
__rmap_add(kvm, cache, slot, sptep, gfn, sp->role.access);
}
@@ -6954,8 +6902,7 @@ restart:
* mapping if the indirect sp has level = 1.
*/
if (sp->role.direct &&
- sp->role.level < kvm_mmu_max_mapping_level(kvm, slot, sp->gfn,
- PG_LEVEL_NUM)) {
+ sp->role.level < kvm_mmu_max_mapping_level(kvm, slot, sp->gfn)) {
kvm_zap_one_rmap_spte(kvm, rmap_head, sptep);
if (kvm_available_flush_remote_tlbs_range())
@@ -6983,8 +6930,8 @@ static void kvm_rmap_zap_collapsible_sptes(struct kvm *kvm,
kvm_flush_remote_tlbs_memslot(kvm, slot);
}
-void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
- const struct kvm_memory_slot *slot)
+void kvm_mmu_recover_huge_pages(struct kvm *kvm,
+ const struct kvm_memory_slot *slot)
{
if (kvm_memslots_have_rmaps(kvm)) {
write_lock(&kvm->mmu_lock);
@@ -6994,7 +6941,7 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
if (tdp_mmu_enabled) {
read_lock(&kvm->mmu_lock);
- kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot);
+ kvm_tdp_mmu_recover_huge_pages(kvm, slot);
read_unlock(&kvm->mmu_lock);
}
}
@@ -7149,72 +7096,6 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen)
}
}
-static unsigned long mmu_shrink_scan(struct shrinker *shrink,
- struct shrink_control *sc)
-{
- struct kvm *kvm;
- int nr_to_scan = sc->nr_to_scan;
- unsigned long freed = 0;
-
- mutex_lock(&kvm_lock);
-
- list_for_each_entry(kvm, &vm_list, vm_list) {
- int idx;
-
- /*
- * Never scan more than sc->nr_to_scan VM instances.
- * Will not hit this condition practically since we do not try
- * to shrink more than one VM and it is very unlikely to see
- * !n_used_mmu_pages so many times.
- */
- if (!nr_to_scan--)
- break;
- /*
- * n_used_mmu_pages is accessed without holding kvm->mmu_lock
- * here. We may skip a VM instance errorneosly, but we do not
- * want to shrink a VM that only started to populate its MMU
- * anyway.
- */
- if (!kvm->arch.n_used_mmu_pages &&
- !kvm_has_zapped_obsolete_pages(kvm))
- continue;
-
- idx = srcu_read_lock(&kvm->srcu);
- write_lock(&kvm->mmu_lock);
-
- if (kvm_has_zapped_obsolete_pages(kvm)) {
- kvm_mmu_commit_zap_page(kvm,
- &kvm->arch.zapped_obsolete_pages);
- goto unlock;
- }
-
- freed = kvm_mmu_zap_oldest_mmu_pages(kvm, sc->nr_to_scan);
-
-unlock:
- write_unlock(&kvm->mmu_lock);
- srcu_read_unlock(&kvm->srcu, idx);
-
- /*
- * unfair on small ones
- * per-vm shrinkers cry out
- * sadness comes quickly
- */
- list_move_tail(&kvm->vm_list, &vm_list);
- break;
- }
-
- mutex_unlock(&kvm_lock);
- return freed;
-}
-
-static unsigned long mmu_shrink_count(struct shrinker *shrink,
- struct shrink_control *sc)
-{
- return percpu_counter_read_positive(&kvm_total_used_mmu_pages);
-}
-
-static struct shrinker *mmu_shrinker;
-
static void mmu_destroy_caches(void)
{
kmem_cache_destroy(pte_list_desc_cache);
@@ -7281,7 +7162,7 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp)
kvm_mmu_zap_all_fast(kvm);
mutex_unlock(&kvm->slots_lock);
- wake_up_process(kvm->arch.nx_huge_page_recovery_thread);
+ vhost_task_wake(kvm->arch.nx_huge_page_recovery_thread);
}
mutex_unlock(&kvm_lock);
}
@@ -7341,23 +7222,8 @@ int kvm_mmu_vendor_module_init(void)
if (!mmu_page_header_cache)
goto out;
- if (percpu_counter_init(&kvm_total_used_mmu_pages, 0, GFP_KERNEL))
- goto out;
-
- mmu_shrinker = shrinker_alloc(0, "x86-mmu");
- if (!mmu_shrinker)
- goto out_shrinker;
-
- mmu_shrinker->count_objects = mmu_shrink_count;
- mmu_shrinker->scan_objects = mmu_shrink_scan;
- mmu_shrinker->seeks = DEFAULT_SEEKS * 10;
-
- shrinker_register(mmu_shrinker);
-
return 0;
-out_shrinker:
- percpu_counter_destroy(&kvm_total_used_mmu_pages);
out:
mmu_destroy_caches();
return ret;
@@ -7374,8 +7240,6 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
void kvm_mmu_vendor_module_exit(void)
{
mmu_destroy_caches();
- percpu_counter_destroy(&kvm_total_used_mmu_pages);
- shrinker_free(mmu_shrinker);
}
/*
@@ -7427,7 +7291,7 @@ static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel
mutex_lock(&kvm_lock);
list_for_each_entry(kvm, &vm_list, vm_list)
- wake_up_process(kvm->arch.nx_huge_page_recovery_thread);
+ vhost_task_wake(kvm->arch.nx_huge_page_recovery_thread);
mutex_unlock(&kvm_lock);
}
@@ -7530,62 +7394,56 @@ static void kvm_recover_nx_huge_pages(struct kvm *kvm)
srcu_read_unlock(&kvm->srcu, rcu_idx);
}
-static long get_nx_huge_page_recovery_timeout(u64 start_time)
+static void kvm_nx_huge_page_recovery_worker_kill(void *data)
{
- bool enabled;
- uint period;
-
- enabled = calc_nx_huge_pages_recovery_period(&period);
-
- return enabled ? start_time + msecs_to_jiffies(period) - get_jiffies_64()
- : MAX_SCHEDULE_TIMEOUT;
}
-static int kvm_nx_huge_page_recovery_worker(struct kvm *kvm, uintptr_t data)
+static bool kvm_nx_huge_page_recovery_worker(void *data)
{
- u64 start_time;
+ struct kvm *kvm = data;
+ bool enabled;
+ uint period;
long remaining_time;
- while (true) {
- start_time = get_jiffies_64();
- remaining_time = get_nx_huge_page_recovery_timeout(start_time);
-
- set_current_state(TASK_INTERRUPTIBLE);
- while (!kthread_should_stop() && remaining_time > 0) {
- schedule_timeout(remaining_time);
- remaining_time = get_nx_huge_page_recovery_timeout(start_time);
- set_current_state(TASK_INTERRUPTIBLE);
- }
-
- set_current_state(TASK_RUNNING);
-
- if (kthread_should_stop())
- return 0;
+ enabled = calc_nx_huge_pages_recovery_period(&period);
+ if (!enabled)
+ return false;
- kvm_recover_nx_huge_pages(kvm);
+ remaining_time = kvm->arch.nx_huge_page_last + msecs_to_jiffies(period)
+ - get_jiffies_64();
+ if (remaining_time > 0) {
+ schedule_timeout(remaining_time);
+ /* check for signals and come back */
+ return true;
}
+
+ __set_current_state(TASK_RUNNING);
+ kvm_recover_nx_huge_pages(kvm);
+ kvm->arch.nx_huge_page_last = get_jiffies_64();
+ return true;
}
int kvm_mmu_post_init_vm(struct kvm *kvm)
{
- int err;
-
if (nx_hugepage_mitigation_hard_disabled)
return 0;
- err = kvm_vm_create_worker_thread(kvm, kvm_nx_huge_page_recovery_worker, 0,
- "kvm-nx-lpage-recovery",
- &kvm->arch.nx_huge_page_recovery_thread);
- if (!err)
- kthread_unpark(kvm->arch.nx_huge_page_recovery_thread);
+ kvm->arch.nx_huge_page_last = get_jiffies_64();
+ kvm->arch.nx_huge_page_recovery_thread = vhost_task_create(
+ kvm_nx_huge_page_recovery_worker, kvm_nx_huge_page_recovery_worker_kill,
+ kvm, "kvm-nx-lpage-recovery");
- return err;
+ if (!kvm->arch.nx_huge_page_recovery_thread)
+ return -ENOMEM;
+
+ vhost_task_start(kvm->arch.nx_huge_page_recovery_thread);
+ return 0;
}
void kvm_mmu_pre_destroy_vm(struct kvm *kvm)
{
if (kvm->arch.nx_huge_page_recovery_thread)
- kthread_stop(kvm->arch.nx_huge_page_recovery_thread);
+ vhost_task_stop(kvm->arch.nx_huge_page_recovery_thread);
}
#ifdef CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES
diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.h
index c98827840e07..b00abbe3f6cf 100644
--- a/arch/x86/kvm/mmu/mmu_internal.h
+++ b/arch/x86/kvm/mmu/mmu_internal.h
@@ -164,7 +164,7 @@ static inline gfn_t gfn_round_for_level(gfn_t gfn, int level)
}
int mmu_try_to_unsync_pages(struct kvm *kvm, const struct kvm_memory_slot *slot,
- gfn_t gfn, bool can_unsync, bool prefetch);
+ gfn_t gfn, bool synchronizing, bool prefetch);
void kvm_mmu_gfn_disallow_lpage(const struct kvm_memory_slot *slot, gfn_t gfn);
void kvm_mmu_gfn_allow_lpage(const struct kvm_memory_slot *slot, gfn_t gfn);
@@ -235,10 +235,10 @@ struct kvm_page_fault {
/* The memslot containing gfn. May be NULL. */
struct kvm_memory_slot *slot;
- /* Outputs of kvm_faultin_pfn. */
+ /* Outputs of kvm_mmu_faultin_pfn(). */
unsigned long mmu_seq;
kvm_pfn_t pfn;
- hva_t hva;
+ struct page *refcounted_page;
bool map_writable;
/*
@@ -313,7 +313,6 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
.is_private = err & PFERR_PRIVATE_ACCESS,
.pfn = KVM_PFN_ERR_FAULT,
- .hva = KVM_HVA_ERR_BAD,
};
int r;
@@ -347,8 +346,7 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
}
int kvm_mmu_max_mapping_level(struct kvm *kvm,
- const struct kvm_memory_slot *slot, gfn_t gfn,
- int max_level);
+ const struct kvm_memory_slot *slot, gfn_t gfn);
void kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault);
void disallowed_hugepage_adjust(struct kvm_page_fault *fault, u64 spte, int cur_level);
diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
index ae7d39ff2d07..f4711674c47b 100644
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -533,10 +533,8 @@ static bool
FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
u64 *spte, pt_element_t gpte)
{
- struct kvm_memory_slot *slot;
unsigned pte_access;
gfn_t gfn;
- kvm_pfn_t pfn;
if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
return false;
@@ -545,17 +543,7 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
pte_access = sp->role.access & FNAME(gpte_access)(gpte);
FNAME(protect_clean_gpte)(vcpu->arch.mmu, &pte_access, gpte);
- slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, pte_access & ACC_WRITE_MASK);
- if (!slot)
- return false;
-
- pfn = gfn_to_pfn_memslot_atomic(slot, gfn);
- if (is_error_pfn(pfn))
- return false;
-
- mmu_set_spte(vcpu, slot, spte, pte_access, gfn, pfn, NULL);
- kvm_release_pfn_clean(pfn);
- return true;
+ return kvm_mmu_prefetch_sptes(vcpu, gfn, spte, 1, pte_access);
}
static bool FNAME(gpte_changed)(struct kvm_vcpu *vcpu,
@@ -813,7 +801,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
if (r)
return r;
- r = kvm_faultin_pfn(vcpu, fault, walker.pte_access);
+ r = kvm_mmu_faultin_pfn(vcpu, fault, walker.pte_access);
if (r != RET_PF_CONTINUE)
return r;
@@ -848,8 +836,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
r = FNAME(fetch)(vcpu, fault, &walker);
out_unlock:
+ kvm_mmu_finish_page_fault(vcpu, fault, r);
write_unlock(&vcpu->kvm->mmu_lock);
- kvm_release_pfn_clean(fault->pfn);
return r;
}
@@ -892,9 +880,9 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
/*
* Using the information in sp->shadowed_translation (kvm_mmu_page_get_gfn()) is
- * safe because:
- * - The spte has a reference to the struct page, so the pfn for a given gfn
- * can't change unless all sptes pointing to it are nuked first.
+ * safe because SPTEs are protected by mmu_notifiers and memslot generations, so
+ * the pfn for a given gfn can't change unless all SPTEs pointing to the gfn are
+ * nuked first.
*
* Returns
* < 0: failed to sync spte
@@ -963,9 +951,14 @@ static int FNAME(sync_spte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, int
host_writable = spte & shadow_host_writable_mask;
slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
make_spte(vcpu, sp, slot, pte_access, gfn,
- spte_to_pfn(spte), spte, true, false,
+ spte_to_pfn(spte), spte, true, true,
host_writable, &spte);
+ /*
+ * There is no need to mark the pfn dirty, as the new protections must
+ * be a subset of the old protections, i.e. synchronizing a SPTE cannot
+ * change the SPTE from read-only to writable.
+ */
return mmu_spte_update(sptep, spte);
}
diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c
index 8f7eb3ad88fc..22551e2f1d00 100644
--- a/arch/x86/kvm/mmu/spte.c
+++ b/arch/x86/kvm/mmu/spte.c
@@ -24,6 +24,8 @@ static bool __ro_after_init allow_mmio_caching;
module_param_named(mmio_caching, enable_mmio_caching, bool, 0444);
EXPORT_SYMBOL_GPL(enable_mmio_caching);
+bool __read_mostly kvm_ad_enabled;
+
u64 __read_mostly shadow_host_writable_mask;
u64 __read_mostly shadow_mmu_writable_mask;
u64 __read_mostly shadow_nx_mask;
@@ -133,12 +135,6 @@ static bool kvm_is_mmio_pfn(kvm_pfn_t pfn)
*/
bool spte_has_volatile_bits(u64 spte)
{
- /*
- * Always atomically update spte if it can be updated
- * out of mmu-lock, it can ensure dirty bit is not lost,
- * also, it can help us to get a stable is_writable_pte()
- * to ensure tlb flush is not missed.
- */
if (!is_writable_pte(spte) && is_mmu_writable_spte(spte))
return true;
@@ -157,7 +153,7 @@ bool spte_has_volatile_bits(u64 spte)
bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
const struct kvm_memory_slot *slot,
unsigned int pte_access, gfn_t gfn, kvm_pfn_t pfn,
- u64 old_spte, bool prefetch, bool can_unsync,
+ u64 old_spte, bool prefetch, bool synchronizing,
bool host_writable, u64 *new_spte)
{
int level = sp->role.level;
@@ -178,8 +174,8 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
spte |= SPTE_TDP_AD_WRPROT_ONLY;
spte |= shadow_present_mask;
- if (!prefetch)
- spte |= spte_shadow_accessed_mask(spte);
+ if (!prefetch || synchronizing)
+ spte |= shadow_accessed_mask;
/*
* For simplicity, enforce the NX huge page mitigation even if not
@@ -223,41 +219,39 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
spte |= (u64)pfn << PAGE_SHIFT;
if (pte_access & ACC_WRITE_MASK) {
- spte |= PT_WRITABLE_MASK | shadow_mmu_writable_mask;
-
- /*
- * Optimization: for pte sync, if spte was writable the hash
- * lookup is unnecessary (and expensive). Write protection
- * is responsibility of kvm_mmu_get_page / kvm_mmu_sync_roots.
- * Same reasoning can be applied to dirty page accounting.
- */
- if (is_writable_pte(old_spte))
- goto out;
-
/*
* Unsync shadow pages that are reachable by the new, writable
* SPTE. Write-protect the SPTE if the page can't be unsync'd,
* e.g. it's write-tracked (upper-level SPs) or has one or more
* shadow pages and unsync'ing pages is not allowed.
+ *
+ * When overwriting an existing leaf SPTE, and the old SPTE was
+ * writable, skip trying to unsync shadow pages as any relevant
+ * shadow pages must already be unsync, i.e. the hash lookup is
+ * unnecessary (and expensive). Note, this relies on KVM not
+ * changing PFNs without first zapping the old SPTE, which is
+ * guaranteed by both the shadow MMU and the TDP MMU.
*/
- if (mmu_try_to_unsync_pages(vcpu->kvm, slot, gfn, can_unsync, prefetch)) {
+ if ((!is_last_spte(old_spte, level) || !is_writable_pte(old_spte)) &&
+ mmu_try_to_unsync_pages(vcpu->kvm, slot, gfn, synchronizing, prefetch))
wrprot = true;
- pte_access &= ~ACC_WRITE_MASK;
- spte &= ~(PT_WRITABLE_MASK | shadow_mmu_writable_mask);
- }
+ else
+ spte |= PT_WRITABLE_MASK | shadow_mmu_writable_mask |
+ shadow_dirty_mask;
}
- if (pte_access & ACC_WRITE_MASK)
- spte |= spte_shadow_dirty_mask(spte);
-
-out:
- if (prefetch)
+ if (prefetch && !synchronizing)
spte = mark_spte_for_access_track(spte);
WARN_ONCE(is_rsvd_spte(&vcpu->arch.mmu->shadow_zero_check, spte, level),
"spte = 0x%llx, level = %d, rsvd bits = 0x%llx", spte, level,
get_rsvd_bits(&vcpu->arch.mmu->shadow_zero_check, spte, level));
+ /*
+ * Mark the memslot dirty *after* modifying it for access tracking.
+ * Unlike folios, memslots can be safely marked dirty out of mmu_lock,
+ * i.e. in the fast page fault handler.
+ */
if ((spte & PT_WRITABLE_MASK) && kvm_slot_dirty_track_enabled(slot)) {
/* Enforced by kvm_mmu_hugepage_adjust. */
WARN_ON_ONCE(level > PG_LEVEL_4K);
@@ -268,15 +262,15 @@ out:
return wrprot;
}
-static u64 make_spte_executable(u64 spte)
+static u64 modify_spte_protections(u64 spte, u64 set, u64 clear)
{
bool is_access_track = is_access_track_spte(spte);
if (is_access_track)
spte = restore_acc_track_spte(spte);
- spte &= ~shadow_nx_mask;
- spte |= shadow_x_mask;
+ KVM_MMU_WARN_ON(set & clear);
+ spte = (spte | set) & ~clear;
if (is_access_track)
spte = mark_spte_for_access_track(spte);
@@ -284,6 +278,16 @@ static u64 make_spte_executable(u64 spte)
return spte;
}
+static u64 make_spte_executable(u64 spte)
+{
+ return modify_spte_protections(spte, shadow_x_mask, shadow_nx_mask);
+}
+
+static u64 make_spte_nonexecutable(u64 spte)
+{
+ return modify_spte_protections(spte, shadow_nx_mask, shadow_x_mask);
+}
+
/*
* Construct an SPTE that maps a sub-page of the given huge page SPTE where
* `index` identifies which sub-page.
@@ -291,8 +295,8 @@ static u64 make_spte_executable(u64 spte)
* This is used during huge page splitting to build the SPTEs that make up the
* new page table.
*/
-u64 make_huge_page_split_spte(struct kvm *kvm, u64 huge_spte,
- union kvm_mmu_page_role role, int index)
+u64 make_small_spte(struct kvm *kvm, u64 huge_spte,
+ union kvm_mmu_page_role role, int index)
{
u64 child_spte = huge_spte;
@@ -320,6 +324,26 @@ u64 make_huge_page_split_spte(struct kvm *kvm, u64 huge_spte,
return child_spte;
}
+u64 make_huge_spte(struct kvm *kvm, u64 small_spte, int level)
+{
+ u64 huge_spte;
+
+ KVM_BUG_ON(!is_shadow_present_pte(small_spte) || level == PG_LEVEL_4K, kvm);
+
+ huge_spte = small_spte | PT_PAGE_SIZE_MASK;
+
+ /*
+ * huge_spte already has the address of the sub-page being collapsed
+ * from small_spte, so just clear the lower address bits to create the
+ * huge page address.
+ */
+ huge_spte &= KVM_HPAGE_MASK(level) | ~PAGE_MASK;
+
+ if (is_nx_huge_page_enabled(kvm))
+ huge_spte = make_spte_nonexecutable(huge_spte);
+
+ return huge_spte;
+}
u64 make_nonleaf_spte(u64 *child_pt, bool ad_disabled)
{
@@ -352,7 +376,7 @@ u64 mark_spte_for_access_track(u64 spte)
spte |= (spte & SHADOW_ACC_TRACK_SAVED_BITS_MASK) <<
SHADOW_ACC_TRACK_SAVED_BITS_SHIFT;
- spte &= ~shadow_acc_track_mask;
+ spte &= ~(shadow_acc_track_mask | shadow_accessed_mask);
return spte;
}
@@ -422,9 +446,11 @@ EXPORT_SYMBOL_GPL(kvm_mmu_set_me_spte_mask);
void kvm_mmu_set_ept_masks(bool has_ad_bits, bool has_exec_only)
{
+ kvm_ad_enabled = has_ad_bits;
+
shadow_user_mask = VMX_EPT_READABLE_MASK;
- shadow_accessed_mask = has_ad_bits ? VMX_EPT_ACCESS_BIT : 0ull;
- shadow_dirty_mask = has_ad_bits ? VMX_EPT_DIRTY_BIT : 0ull;
+ shadow_accessed_mask = VMX_EPT_ACCESS_BIT;
+ shadow_dirty_mask = VMX_EPT_DIRTY_BIT;
shadow_nx_mask = 0ull;
shadow_x_mask = VMX_EPT_EXECUTABLE_MASK;
/* VMX_EPT_SUPPRESS_VE_BIT is needed for W or X violation. */
@@ -455,6 +481,8 @@ void kvm_mmu_reset_all_pte_masks(void)
u8 low_phys_bits;
u64 mask;
+ kvm_ad_enabled = true;
+
/*
* If the CPU has 46 or less physical address bits, then set an
* appropriate mask to guard against L1TF attacks. Otherwise, it is
diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h
index 2cb816ea2430..f332b33bc817 100644
--- a/arch/x86/kvm/mmu/spte.h
+++ b/arch/x86/kvm/mmu/spte.h
@@ -167,6 +167,15 @@ static_assert(!(SHADOW_NONPRESENT_VALUE & SPTE_MMU_PRESENT_MASK));
#define SHADOW_NONPRESENT_VALUE 0ULL
#endif
+
+/*
+ * True if A/D bits are supported in hardware and are enabled by KVM. When
+ * enabled, KVM uses A/D bits for all non-nested MMUs. Because L1 can disable
+ * A/D bits in EPTP12, SP and SPTE variants are needed to handle the scenario
+ * where KVM is using A/D bits for L1, but not L2.
+ */
+extern bool __read_mostly kvm_ad_enabled;
+
extern u64 __read_mostly shadow_host_writable_mask;
extern u64 __read_mostly shadow_mmu_writable_mask;
extern u64 __read_mostly shadow_nx_mask;
@@ -285,17 +294,6 @@ static inline bool is_ept_ve_possible(u64 spte)
(spte & VMX_EPT_RWX_MASK) != VMX_EPT_MISCONFIG_WX_VALUE;
}
-/*
- * Returns true if A/D bits are supported in hardware and are enabled by KVM.
- * When enabled, KVM uses A/D bits for all non-nested MMUs. Because L1 can
- * disable A/D bits in EPTP12, SP and SPTE variants are needed to handle the
- * scenario where KVM is using A/D bits for L1, but not L2.
- */
-static inline bool kvm_ad_enabled(void)
-{
- return !!shadow_accessed_mask;
-}
-
static inline bool sp_ad_disabled(struct kvm_mmu_page *sp)
{
return sp->role.ad_disabled;
@@ -318,18 +316,6 @@ static inline bool spte_ad_need_write_protect(u64 spte)
return (spte & SPTE_TDP_AD_MASK) != SPTE_TDP_AD_ENABLED;
}
-static inline u64 spte_shadow_accessed_mask(u64 spte)
-{
- KVM_MMU_WARN_ON(!is_shadow_present_pte(spte));
- return spte_ad_enabled(spte) ? shadow_accessed_mask : 0;
-}
-
-static inline u64 spte_shadow_dirty_mask(u64 spte)
-{
- KVM_MMU_WARN_ON(!is_shadow_present_pte(spte));
- return spte_ad_enabled(spte) ? shadow_dirty_mask : 0;
-}
-
static inline bool is_access_track_spte(u64 spte)
{
return !spte_ad_enabled(spte) && (spte & shadow_acc_track_mask) == 0;
@@ -357,17 +343,7 @@ static inline kvm_pfn_t spte_to_pfn(u64 pte)
static inline bool is_accessed_spte(u64 spte)
{
- u64 accessed_mask = spte_shadow_accessed_mask(spte);
-
- return accessed_mask ? spte & accessed_mask
- : !is_access_track_spte(spte);
-}
-
-static inline bool is_dirty_spte(u64 spte)
-{
- u64 dirty_mask = spte_shadow_dirty_mask(spte);
-
- return dirty_mask ? spte & dirty_mask : spte & PT_WRITABLE_MASK;
+ return spte & shadow_accessed_mask;
}
static inline u64 get_rsvd_bits(struct rsvd_bits_validate *rsvd_check, u64 pte,
@@ -485,6 +461,33 @@ static inline bool is_mmu_writable_spte(u64 spte)
return spte & shadow_mmu_writable_mask;
}
+/*
+ * If the MMU-writable flag is cleared, i.e. the SPTE is write-protected for
+ * write-tracking, remote TLBs must be flushed, even if the SPTE was read-only,
+ * as KVM allows stale Writable TLB entries to exist. When dirty logging, KVM
+ * flushes TLBs based on whether or not dirty bitmap/ring entries were reaped,
+ * not whether or not SPTEs were modified, i.e. only the write-tracking case
+ * needs to flush at the time the SPTEs is modified, before dropping mmu_lock.
+ *
+ * Don't flush if the Accessed bit is cleared, as access tracking tolerates
+ * false negatives, e.g. KVM x86 omits TLB flushes even when aging SPTEs for a
+ * mmu_notifier.clear_flush_young() event.
+ *
+ * Lastly, don't flush if the Dirty bit is cleared, as KVM unconditionally
+ * flushes when enabling dirty logging (see kvm_mmu_slot_apply_flags()), and
+ * when clearing dirty logs, KVM flushes based on whether or not dirty entries
+ * were reaped from the bitmap/ring, not whether or not dirty SPTEs were found.
+ *
+ * Note, this logic only applies to shadow-present leaf SPTEs. The caller is
+ * responsible for checking that the old SPTE is shadow-present, and is also
+ * responsible for determining whether or not a TLB flush is required when
+ * modifying a shadow-present non-leaf SPTE.
+ */
+static inline bool leaf_spte_change_needs_tlb_flush(u64 old_spte, u64 new_spte)
+{
+ return is_mmu_writable_spte(old_spte) && !is_mmu_writable_spte(new_spte);
+}
+
static inline u64 get_mmio_spte_generation(u64 spte)
{
u64 gen;
@@ -499,10 +502,11 @@ bool spte_has_volatile_bits(u64 spte);
bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
const struct kvm_memory_slot *slot,
unsigned int pte_access, gfn_t gfn, kvm_pfn_t pfn,
- u64 old_spte, bool prefetch, bool can_unsync,
+ u64 old_spte, bool prefetch, bool synchronizing,
bool host_writable, u64 *new_spte);
-u64 make_huge_page_split_spte(struct kvm *kvm, u64 huge_spte,
- union kvm_mmu_page_role role, int index);
+u64 make_small_spte(struct kvm *kvm, u64 huge_spte,
+ union kvm_mmu_page_role role, int index);
+u64 make_huge_spte(struct kvm *kvm, u64 small_spte, int level);
u64 make_nonleaf_spte(u64 *child_pt, bool ad_disabled);
u64 make_mmio_spte(struct kvm_vcpu *vcpu, u64 gfn, unsigned int access);
u64 mark_spte_for_access_track(u64 spte);
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index 3b996c1fdaab..4508d868f1cd 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -511,10 +511,6 @@ static void handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn,
if (is_leaf != was_leaf)
kvm_update_page_stats(kvm, level, is_leaf ? 1 : -1);
- if (was_leaf && is_dirty_spte(old_spte) &&
- (!is_present || !is_dirty_spte(new_spte) || pfn_changed))
- kvm_set_pfn_dirty(spte_to_pfn(old_spte));
-
/*
* Recursively handle child PTs if the change removed a subtree from
* the paging structure. Note the WARN on the PFN changing without the
@@ -524,10 +520,6 @@ static void handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn,
if (was_present && !was_leaf &&
(is_leaf || !is_present || WARN_ON_ONCE(pfn_changed)))
handle_removed_pt(kvm, spte_to_child_pt(old_spte, level), shared);
-
- if (was_leaf && is_accessed_spte(old_spte) &&
- (!is_present || !is_accessed_spte(new_spte) || pfn_changed))
- kvm_set_pfn_accessed(spte_to_pfn(old_spte));
}
static inline int __must_check __tdp_mmu_set_spte_atomic(struct tdp_iter *iter,
@@ -591,48 +583,6 @@ static inline int __must_check tdp_mmu_set_spte_atomic(struct kvm *kvm,
return 0;
}
-static inline int __must_check tdp_mmu_zap_spte_atomic(struct kvm *kvm,
- struct tdp_iter *iter)
-{
- int ret;
-
- lockdep_assert_held_read(&kvm->mmu_lock);
-
- /*
- * Freeze the SPTE by setting it to a special, non-present value. This
- * will stop other threads from immediately installing a present entry
- * in its place before the TLBs are flushed.
- *
- * Delay processing of the zapped SPTE until after TLBs are flushed and
- * the FROZEN_SPTE is replaced (see below).
- */
- ret = __tdp_mmu_set_spte_atomic(iter, FROZEN_SPTE);
- if (ret)
- return ret;
-
- kvm_flush_remote_tlbs_gfn(kvm, iter->gfn, iter->level);
-
- /*
- * No other thread can overwrite the frozen SPTE as they must either
- * wait on the MMU lock or use tdp_mmu_set_spte_atomic() which will not
- * overwrite the special frozen SPTE value. Use the raw write helper to
- * avoid an unnecessary check on volatile bits.
- */
- __kvm_tdp_mmu_write_spte(iter->sptep, SHADOW_NONPRESENT_VALUE);
-
- /*
- * Process the zapped SPTE after flushing TLBs, and after replacing
- * FROZEN_SPTE with 0. This minimizes the amount of time vCPUs are
- * blocked by the FROZEN_SPTE and reduces contention on the child
- * SPTEs.
- */
- handle_changed_spte(kvm, iter->as_id, iter->gfn, iter->old_spte,
- SHADOW_NONPRESENT_VALUE, iter->level, true);
-
- return 0;
-}
-
-
/*
* tdp_mmu_set_spte - Set a TDP MMU SPTE and handle the associated bookkeeping
* @kvm: KVM instance
@@ -688,6 +638,16 @@ static inline void tdp_mmu_iter_set_spte(struct kvm *kvm, struct tdp_iter *iter,
#define tdp_mmu_for_each_pte(_iter, _mmu, _start, _end) \
for_each_tdp_pte(_iter, root_to_sp(_mmu->root.hpa), _start, _end)
+static inline bool __must_check tdp_mmu_iter_need_resched(struct kvm *kvm,
+ struct tdp_iter *iter)
+{
+ if (!need_resched() && !rwlock_needbreak(&kvm->mmu_lock))
+ return false;
+
+ /* Ensure forward progress has been made before yielding. */
+ return iter->next_last_level_gfn != iter->yielded_gfn;
+}
+
/*
* Yield if the MMU lock is contended or this thread needs to return control
* to the scheduler.
@@ -706,31 +666,27 @@ static inline bool __must_check tdp_mmu_iter_cond_resched(struct kvm *kvm,
struct tdp_iter *iter,
bool flush, bool shared)
{
- WARN_ON_ONCE(iter->yielded);
+ KVM_MMU_WARN_ON(iter->yielded);
- /* Ensure forward progress has been made before yielding. */
- if (iter->next_last_level_gfn == iter->yielded_gfn)
+ if (!tdp_mmu_iter_need_resched(kvm, iter))
return false;
- if (need_resched() || rwlock_needbreak(&kvm->mmu_lock)) {
- if (flush)
- kvm_flush_remote_tlbs(kvm);
-
- rcu_read_unlock();
+ if (flush)
+ kvm_flush_remote_tlbs(kvm);
- if (shared)
- cond_resched_rwlock_read(&kvm->mmu_lock);
- else
- cond_resched_rwlock_write(&kvm->mmu_lock);
+ rcu_read_unlock();
- rcu_read_lock();
+ if (shared)
+ cond_resched_rwlock_read(&kvm->mmu_lock);
+ else
+ cond_resched_rwlock_write(&kvm->mmu_lock);
- WARN_ON_ONCE(iter->gfn > iter->next_last_level_gfn);
+ rcu_read_lock();
- iter->yielded = true;
- }
+ WARN_ON_ONCE(iter->gfn > iter->next_last_level_gfn);
- return iter->yielded;
+ iter->yielded = true;
+ return true;
}
static inline gfn_t tdp_mmu_max_gfn_exclusive(void)
@@ -1026,19 +982,23 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu,
if (WARN_ON_ONCE(sp->role.level != fault->goal_level))
return RET_PF_RETRY;
+ if (fault->prefetch && is_shadow_present_pte(iter->old_spte))
+ return RET_PF_SPURIOUS;
+
if (unlikely(!fault->slot))
new_spte = make_mmio_spte(vcpu, iter->gfn, ACC_ALL);
else
wrprot = make_spte(vcpu, sp, fault->slot, ACC_ALL, iter->gfn,
- fault->pfn, iter->old_spte, fault->prefetch, true,
- fault->map_writable, &new_spte);
+ fault->pfn, iter->old_spte, fault->prefetch,
+ false, fault->map_writable, &new_spte);
if (new_spte == iter->old_spte)
ret = RET_PF_SPURIOUS;
else if (tdp_mmu_set_spte_atomic(vcpu->kvm, iter, new_spte))
return RET_PF_RETRY;
else if (is_shadow_present_pte(iter->old_spte) &&
- !is_last_spte(iter->old_spte, iter->level))
+ (!is_last_spte(iter->old_spte, iter->level) ||
+ WARN_ON_ONCE(leaf_spte_change_needs_tlb_flush(iter->old_spte, new_spte))))
kvm_flush_remote_tlbs_gfn(vcpu->kvm, iter->gfn, iter->level);
/*
@@ -1078,7 +1038,7 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu,
static int tdp_mmu_link_sp(struct kvm *kvm, struct tdp_iter *iter,
struct kvm_mmu_page *sp, bool shared)
{
- u64 spte = make_nonleaf_spte(sp->spt, !kvm_ad_enabled());
+ u64 spte = make_nonleaf_spte(sp->spt, !kvm_ad_enabled);
int ret = 0;
if (shared) {
@@ -1195,33 +1155,6 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
return flush;
}
-typedef bool (*tdp_handler_t)(struct kvm *kvm, struct tdp_iter *iter,
- struct kvm_gfn_range *range);
-
-static __always_inline bool kvm_tdp_mmu_handle_gfn(struct kvm *kvm,
- struct kvm_gfn_range *range,
- tdp_handler_t handler)
-{
- struct kvm_mmu_page *root;
- struct tdp_iter iter;
- bool ret = false;
-
- /*
- * Don't support rescheduling, none of the MMU notifiers that funnel
- * into this helper allow blocking; it'd be dead, wasteful code.
- */
- for_each_tdp_mmu_root(kvm, root, range->slot->as_id) {
- rcu_read_lock();
-
- tdp_root_for_each_leaf_pte(iter, root, range->start, range->end)
- ret |= handler(kvm, &iter, range);
-
- rcu_read_unlock();
- }
-
- return ret;
-}
-
/*
* Mark the SPTEs range of GFNs [start, end) unaccessed and return non-zero
* if any of the GFNs in the range have been accessed.
@@ -1230,15 +1163,10 @@ static __always_inline bool kvm_tdp_mmu_handle_gfn(struct kvm *kvm,
* from the clear_young() or clear_flush_young() notifier, which uses the
* return value to determine if the page has been accessed.
*/
-static bool age_gfn_range(struct kvm *kvm, struct tdp_iter *iter,
- struct kvm_gfn_range *range)
+static void kvm_tdp_mmu_age_spte(struct tdp_iter *iter)
{
u64 new_spte;
- /* If we have a non-accessed entry we don't need to change the pte. */
- if (!is_accessed_spte(iter->old_spte))
- return false;
-
if (spte_ad_enabled(iter->old_spte)) {
iter->old_spte = tdp_mmu_clear_spte_bits(iter->sptep,
iter->old_spte,
@@ -1246,13 +1174,6 @@ static bool age_gfn_range(struct kvm *kvm, struct tdp_iter *iter,
iter->level);
new_spte = iter->old_spte & ~shadow_accessed_mask;
} else {
- /*
- * Capture the dirty status of the page, so that it doesn't get
- * lost when the SPTE is marked for access tracking.
- */
- if (is_writable_pte(iter->old_spte))
- kvm_set_pfn_dirty(spte_to_pfn(iter->old_spte));
-
new_spte = mark_spte_for_access_track(iter->old_spte);
iter->old_spte = kvm_tdp_mmu_write_spte(iter->sptep,
iter->old_spte, new_spte,
@@ -1261,23 +1182,48 @@ static bool age_gfn_range(struct kvm *kvm, struct tdp_iter *iter,
trace_kvm_tdp_mmu_spte_changed(iter->as_id, iter->gfn, iter->level,
iter->old_spte, new_spte);
- return true;
}
-bool kvm_tdp_mmu_age_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
+static bool __kvm_tdp_mmu_age_gfn_range(struct kvm *kvm,
+ struct kvm_gfn_range *range,
+ bool test_only)
{
- return kvm_tdp_mmu_handle_gfn(kvm, range, age_gfn_range);
+ struct kvm_mmu_page *root;
+ struct tdp_iter iter;
+ bool ret = false;
+
+ /*
+ * Don't support rescheduling, none of the MMU notifiers that funnel
+ * into this helper allow blocking; it'd be dead, wasteful code. Note,
+ * this helper must NOT be used to unmap GFNs, as it processes only
+ * valid roots!
+ */
+ for_each_valid_tdp_mmu_root(kvm, root, range->slot->as_id) {
+ guard(rcu)();
+
+ tdp_root_for_each_leaf_pte(iter, root, range->start, range->end) {
+ if (!is_accessed_spte(iter.old_spte))
+ continue;
+
+ if (test_only)
+ return true;
+
+ ret = true;
+ kvm_tdp_mmu_age_spte(&iter);
+ }
+ }
+
+ return ret;
}
-static bool test_age_gfn(struct kvm *kvm, struct tdp_iter *iter,
- struct kvm_gfn_range *range)
+bool kvm_tdp_mmu_age_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
{
- return is_accessed_spte(iter->old_spte);
+ return __kvm_tdp_mmu_age_gfn_range(kvm, range, false);
}
bool kvm_tdp_mmu_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{
- return kvm_tdp_mmu_handle_gfn(kvm, range, test_age_gfn);
+ return __kvm_tdp_mmu_age_gfn_range(kvm, range, true);
}
/*
@@ -1368,7 +1314,7 @@ static int tdp_mmu_split_huge_page(struct kvm *kvm, struct tdp_iter *iter,
* not been linked in yet and thus is not reachable from any other CPU.
*/
for (i = 0; i < SPTE_ENT_PER_PAGE; i++)
- sp->spt[i] = make_huge_page_split_spte(kvm, huge_spte, sp->role, i);
+ sp->spt[i] = make_small_spte(kvm, huge_spte, sp->role, i);
/*
* Replace the huge spte with a pointer to the populated lower level
@@ -1501,16 +1447,15 @@ static bool tdp_mmu_need_write_protect(struct kvm_mmu_page *sp)
* from level, so it is valid to key off any shadow page to determine if
* write protection is needed for an entire tree.
*/
- return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled();
+ return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled;
}
-static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
- gfn_t start, gfn_t end)
+static void clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
+ gfn_t start, gfn_t end)
{
const u64 dbit = tdp_mmu_need_write_protect(root) ? PT_WRITABLE_MASK :
shadow_dirty_mask;
struct tdp_iter iter;
- bool spte_set = false;
rcu_read_lock();
@@ -1531,31 +1476,24 @@ retry:
if (tdp_mmu_set_spte_atomic(kvm, &iter, iter.old_spte & ~dbit))
goto retry;
-
- spte_set = true;
}
rcu_read_unlock();
- return spte_set;
}
/*
* Clear the dirty status (D-bit or W-bit) of all the SPTEs mapping GFNs in the
- * memslot. Returns true if an SPTE has been changed and the TLBs need to be
- * flushed.
+ * memslot.
*/
-bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
+void kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
const struct kvm_memory_slot *slot)
{
struct kvm_mmu_page *root;
- bool spte_set = false;
lockdep_assert_held_read(&kvm->mmu_lock);
for_each_valid_tdp_mmu_root_yield_safe(kvm, root, slot->as_id)
- spte_set |= clear_dirty_gfn_range(kvm, root, slot->base_gfn,
- slot->base_gfn + slot->npages);
-
- return spte_set;
+ clear_dirty_gfn_range(kvm, root, slot->base_gfn,
+ slot->base_gfn + slot->npages);
}
static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
@@ -1593,7 +1531,6 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
trace_kvm_tdp_mmu_spte_changed(iter.as_id, iter.gfn, iter.level,
iter.old_spte,
iter.old_spte & ~dbit);
- kvm_set_pfn_dirty(spte_to_pfn(iter.old_spte));
}
rcu_read_unlock();
@@ -1615,21 +1552,55 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
clear_dirty_pt_masked(kvm, root, gfn, mask, wrprot);
}
-static void zap_collapsible_spte_range(struct kvm *kvm,
- struct kvm_mmu_page *root,
- const struct kvm_memory_slot *slot)
+static int tdp_mmu_make_huge_spte(struct kvm *kvm,
+ struct tdp_iter *parent,
+ u64 *huge_spte)
+{
+ struct kvm_mmu_page *root = spte_to_child_sp(parent->old_spte);
+ gfn_t start = parent->gfn;
+ gfn_t end = start + KVM_PAGES_PER_HPAGE(parent->level);
+ struct tdp_iter iter;
+
+ tdp_root_for_each_leaf_pte(iter, root, start, end) {
+ /*
+ * Use the parent iterator when checking for forward progress so
+ * that KVM doesn't get stuck continuously trying to yield (i.e.
+ * returning -EAGAIN here and then failing the forward progress
+ * check in the caller ad nauseam).
+ */
+ if (tdp_mmu_iter_need_resched(kvm, parent))
+ return -EAGAIN;
+
+ *huge_spte = make_huge_spte(kvm, iter.old_spte, parent->level);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static void recover_huge_pages_range(struct kvm *kvm,
+ struct kvm_mmu_page *root,
+ const struct kvm_memory_slot *slot)
{
gfn_t start = slot->base_gfn;
gfn_t end = start + slot->npages;
struct tdp_iter iter;
int max_mapping_level;
+ bool flush = false;
+ u64 huge_spte;
+ int r;
+
+ if (WARN_ON_ONCE(kvm_slot_dirty_track_enabled(slot)))
+ return;
rcu_read_lock();
for_each_tdp_pte_min_level(iter, root, PG_LEVEL_2M, start, end) {
retry:
- if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true))
+ if (tdp_mmu_iter_cond_resched(kvm, &iter, flush, true)) {
+ flush = false;
continue;
+ }
if (iter.level > KVM_MAX_HUGEPAGE_LEVEL ||
!is_shadow_present_pte(iter.old_spte))
@@ -1653,31 +1624,40 @@ retry:
if (iter.gfn < start || iter.gfn >= end)
continue;
- max_mapping_level = kvm_mmu_max_mapping_level(kvm, slot,
- iter.gfn, PG_LEVEL_NUM);
+ max_mapping_level = kvm_mmu_max_mapping_level(kvm, slot, iter.gfn);
if (max_mapping_level < iter.level)
continue;
- /* Note, a successful atomic zap also does a remote TLB flush. */
- if (tdp_mmu_zap_spte_atomic(kvm, &iter))
+ r = tdp_mmu_make_huge_spte(kvm, &iter, &huge_spte);
+ if (r == -EAGAIN)
+ goto retry;
+ else if (r)
+ continue;
+
+ if (tdp_mmu_set_spte_atomic(kvm, &iter, huge_spte))
goto retry;
+
+ flush = true;
}
+ if (flush)
+ kvm_flush_remote_tlbs_memslot(kvm, slot);
+
rcu_read_unlock();
}
/*
- * Zap non-leaf SPTEs (and free their associated page tables) which could
- * be replaced by huge pages, for GFNs within the slot.
+ * Recover huge page mappings within the slot by replacing non-leaf SPTEs with
+ * huge SPTEs where possible.
*/
-void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm,
- const struct kvm_memory_slot *slot)
+void kvm_tdp_mmu_recover_huge_pages(struct kvm *kvm,
+ const struct kvm_memory_slot *slot)
{
struct kvm_mmu_page *root;
lockdep_assert_held_read(&kvm->mmu_lock);
for_each_valid_tdp_mmu_root_yield_safe(kvm, root, slot->as_id)
- zap_collapsible_spte_range(kvm, root, slot);
+ recover_huge_pages_range(kvm, root, slot);
}
/*
diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h
index 1b74e058a81c..f03ca0dd13d9 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.h
+++ b/arch/x86/kvm/mmu/tdp_mmu.h
@@ -34,14 +34,14 @@ bool kvm_tdp_mmu_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range);
bool kvm_tdp_mmu_wrprot_slot(struct kvm *kvm,
const struct kvm_memory_slot *slot, int min_level);
-bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
+void kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
const struct kvm_memory_slot *slot);
void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
struct kvm_memory_slot *slot,
gfn_t gfn, unsigned long mask,
bool wrprot);
-void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm,
- const struct kvm_memory_slot *slot);
+void kvm_tdp_mmu_recover_huge_pages(struct kvm *kvm,
+ const struct kvm_memory_slot *slot);
bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm,
struct kvm_memory_slot *slot, gfn_t gfn,
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
index 05490b9d8a43..6f74e2b27c1e 100644
--- a/arch/x86/kvm/mtrr.c
+++ b/arch/x86/kvm/mtrr.c
@@ -19,6 +19,7 @@
#include <asm/mtrr.h>
#include "cpuid.h"
+#include "x86.h"
static u64 *find_mtrr(struct kvm_vcpu *vcpu, unsigned int msr)
{
diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h
index 0d17d6b70639..e46220ece83c 100644
--- a/arch/x86/kvm/reverse_cpuid.h
+++ b/arch/x86/kvm/reverse_cpuid.h
@@ -46,6 +46,7 @@ enum kvm_only_cpuid_leafs {
#define X86_FEATURE_AVX_VNNI_INT8 KVM_X86_FEATURE(CPUID_7_1_EDX, 4)
#define X86_FEATURE_AVX_NE_CONVERT KVM_X86_FEATURE(CPUID_7_1_EDX, 5)
#define X86_FEATURE_AMX_COMPLEX KVM_X86_FEATURE(CPUID_7_1_EDX, 8)
+#define X86_FEATURE_AVX_VNNI_INT16 KVM_X86_FEATURE(CPUID_7_1_EDX, 10)
#define X86_FEATURE_PREFETCHITI KVM_X86_FEATURE(CPUID_7_1_EDX, 14)
#define X86_FEATURE_AVX10 KVM_X86_FEATURE(CPUID_7_1_EDX, 19)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index cf84103ce38b..b708bdf7eaff 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -926,7 +926,7 @@ out_exit_err:
nested_svm_vmexit(svm);
out:
- kvm_vcpu_unmap(vcpu, &map, true);
+ kvm_vcpu_unmap(vcpu, &map);
return ret;
}
@@ -1130,7 +1130,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
vmcb12->control.exit_int_info_err,
KVM_ISA_SVM);
- kvm_vcpu_unmap(vcpu, &map, true);
+ kvm_vcpu_unmap(vcpu, &map);
nested_svm_transition_tlb_flush(vcpu);
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 0b851ef937f2..943bd074a5d3 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -450,8 +450,11 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
goto e_free;
/* This needs to happen after SEV/SNP firmware initialization. */
- if (vm_type == KVM_X86_SNP_VM && snp_guest_req_init(kvm))
- goto e_free;
+ if (vm_type == KVM_X86_SNP_VM) {
+ ret = snp_guest_req_init(kvm);
+ if (ret)
+ goto e_free;
+ }
INIT_LIST_HEAD(&sev->regions_list);
INIT_LIST_HEAD(&sev->mirror_vms);
@@ -530,17 +533,12 @@ static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error)
static int __sev_issue_cmd(int fd, int id, void *data, int *error)
{
- struct fd f;
- int ret;
+ CLASS(fd, f)(fd);
- f = fdget(fd);
- if (!fd_file(f))
+ if (fd_empty(f))
return -EBADF;
- ret = sev_issue_cmd_external_user(fd_file(f), id, data, error);
-
- fdput(f);
- return ret;
+ return sev_issue_cmd_external_user(fd_file(f), id, data, error);
}
static int sev_issue_cmd(struct kvm *kvm, int id, void *data, int *error)
@@ -2073,23 +2071,21 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
{
struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info;
struct kvm_sev_info *src_sev, *cg_cleanup_sev;
- struct fd f = fdget(source_fd);
+ CLASS(fd, f)(source_fd);
struct kvm *source_kvm;
bool charged = false;
int ret;
- if (!fd_file(f))
+ if (fd_empty(f))
return -EBADF;
- if (!file_is_kvm(fd_file(f))) {
- ret = -EBADF;
- goto out_fput;
- }
+ if (!file_is_kvm(fd_file(f)))
+ return -EBADF;
source_kvm = fd_file(f)->private_data;
ret = sev_lock_two_vms(kvm, source_kvm);
if (ret)
- goto out_fput;
+ return ret;
if (kvm->arch.vm_type != source_kvm->arch.vm_type ||
sev_guest(kvm) || !sev_guest(source_kvm)) {
@@ -2136,8 +2132,6 @@ out_dst_cgroup:
cg_cleanup_sev->misc_cg = NULL;
out_unlock:
sev_unlock_two_vms(kvm, source_kvm);
-out_fput:
- fdput(f);
return ret;
}
@@ -2212,10 +2206,6 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
if (sev->snp_context)
return -EINVAL;
- sev->snp_context = snp_context_create(kvm, argp);
- if (!sev->snp_context)
- return -ENOTTY;
-
if (params.flags)
return -EINVAL;
@@ -2230,6 +2220,10 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
if (params.policy & SNP_POLICY_MASK_SINGLE_SOCKET)
return -EINVAL;
+ sev->snp_context = snp_context_create(kvm, argp);
+ if (!sev->snp_context)
+ return -ENOTTY;
+
start.gctx_paddr = __psp_pa(sev->snp_context);
start.policy = params.policy;
memcpy(start.gosvw, params.gosvw, sizeof(params.gosvw));
@@ -2798,23 +2792,21 @@ failed:
int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
{
- struct fd f = fdget(source_fd);
+ CLASS(fd, f)(source_fd);
struct kvm *source_kvm;
struct kvm_sev_info *source_sev, *mirror_sev;
int ret;
- if (!fd_file(f))
+ if (fd_empty(f))
return -EBADF;
- if (!file_is_kvm(fd_file(f))) {
- ret = -EBADF;
- goto e_source_fput;
- }
+ if (!file_is_kvm(fd_file(f)))
+ return -EBADF;
source_kvm = fd_file(f)->private_data;
ret = sev_lock_two_vms(kvm, source_kvm);
if (ret)
- goto e_source_fput;
+ return ret;
/*
* Mirrors of mirrors should work, but let's not get silly. Also
@@ -2857,8 +2849,6 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
e_unlock:
sev_unlock_two_vms(kvm, source_kvm);
-e_source_fput:
- fdput(f);
return ret;
}
@@ -3468,7 +3458,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
sev_es_sync_to_ghcb(svm);
- kvm_vcpu_unmap(&svm->vcpu, &svm->sev_es.ghcb_map, true);
+ kvm_vcpu_unmap(&svm->vcpu, &svm->sev_es.ghcb_map);
svm->sev_es.ghcb = NULL;
}
@@ -3849,6 +3839,7 @@ static int __sev_snp_update_protected_guest_state(struct kvm_vcpu *vcpu)
if (VALID_PAGE(svm->sev_es.snp_vmsa_gpa)) {
gfn_t gfn = gpa_to_gfn(svm->sev_es.snp_vmsa_gpa);
struct kvm_memory_slot *slot;
+ struct page *page;
kvm_pfn_t pfn;
slot = gfn_to_memslot(vcpu->kvm, gfn);
@@ -3859,7 +3850,7 @@ static int __sev_snp_update_protected_guest_state(struct kvm_vcpu *vcpu)
* The new VMSA will be private memory guest memory, so
* retrieve the PFN from the gmem backend.
*/
- if (kvm_gmem_get_pfn(vcpu->kvm, slot, gfn, &pfn, NULL))
+ if (kvm_gmem_get_pfn(vcpu->kvm, slot, gfn, &pfn, &page, NULL))
return -EINVAL;
/*
@@ -3888,7 +3879,7 @@ static int __sev_snp_update_protected_guest_state(struct kvm_vcpu *vcpu)
* changes then care should be taken to ensure
* svm->sev_es.vmsa is pinned through some other means.
*/
- kvm_release_pfn_clean(pfn);
+ kvm_release_page_clean(page);
}
/*
@@ -4688,6 +4679,7 @@ void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code)
struct kvm_memory_slot *slot;
struct kvm *kvm = vcpu->kvm;
int order, rmp_level, ret;
+ struct page *page;
bool assigned;
kvm_pfn_t pfn;
gfn_t gfn;
@@ -4714,7 +4706,7 @@ void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code)
return;
}
- ret = kvm_gmem_get_pfn(kvm, slot, gfn, &pfn, &order);
+ ret = kvm_gmem_get_pfn(kvm, slot, gfn, &pfn, &page, &order);
if (ret) {
pr_warn_ratelimited("SEV: Unexpected RMP fault, no backing page for private GPA 0x%llx\n",
gpa);
@@ -4772,7 +4764,7 @@ void sev_handle_rmp_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code)
out:
trace_kvm_rmp_fault(vcpu, gpa, pfn, error_code, rmp_level, ret);
out_no_trace:
- put_page(pfn_to_page(pfn));
+ kvm_release_page_unused(page);
}
static bool is_pfn_range_shared(kvm_pfn_t start, kvm_pfn_t end)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 9df3e1e5ae81..dd15cc635655 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1390,7 +1390,9 @@ static void __svm_vcpu_reset(struct kvm_vcpu *vcpu)
svm_vcpu_init_msrpm(vcpu, svm->msrpm);
svm_init_osvw(vcpu);
- vcpu->arch.microcode_version = 0x01000065;
+
+ if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
+ vcpu->arch.microcode_version = 0x01000065;
svm->tsc_ratio_msr = kvm_caps.default_tsc_scaling_ratio;
svm->nmi_masked = false;
@@ -2299,7 +2301,7 @@ static int vmload_vmsave_interception(struct kvm_vcpu *vcpu, bool vmload)
svm_copy_vmloadsave_state(vmcb12, svm->vmcb);
}
- kvm_vcpu_unmap(vcpu, &map, true);
+ kvm_vcpu_unmap(vcpu, &map);
return ret;
}
@@ -4714,7 +4716,7 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram)
svm_copy_vmrun_state(map_save.hva + 0x400,
&svm->vmcb01.ptr->save);
- kvm_vcpu_unmap(vcpu, &map_save, true);
+ kvm_vcpu_unmap(vcpu, &map_save);
return 0;
}
@@ -4774,9 +4776,9 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram)
svm->nested.nested_run_pending = 1;
unmap_save:
- kvm_vcpu_unmap(vcpu, &map_save, true);
+ kvm_vcpu_unmap(vcpu, &map_save);
unmap_map:
- kvm_vcpu_unmap(vcpu, &map, true);
+ kvm_vcpu_unmap(vcpu, &map);
return ret;
}
@@ -5031,6 +5033,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
.get_segment = svm_get_segment,
.set_segment = svm_set_segment,
.get_cpl = svm_get_cpl,
+ .get_cpl_no_cache = svm_get_cpl,
.get_cs_db_l_bits = svm_get_cs_db_l_bits,
.is_valid_cr0 = svm_is_valid_cr0,
.set_cr0 = svm_set_cr0,
diff --git a/arch/x86/kvm/vmx/hyperv.c b/arch/x86/kvm/vmx/hyperv.c
index fab6a1ad98dc..fa41d036acd4 100644
--- a/arch/x86/kvm/vmx/hyperv.c
+++ b/arch/x86/kvm/vmx/hyperv.c
@@ -4,6 +4,7 @@
#include <linux/errno.h>
#include <linux/smp.h>
+#include "x86.h"
#include "../cpuid.h"
#include "hyperv.h"
#include "nested.h"
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 7668e2fb8043..92d35cc6cd15 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -50,6 +50,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
.get_segment = vmx_get_segment,
.set_segment = vmx_set_segment,
.get_cpl = vmx_get_cpl,
+ .get_cpl_no_cache = vmx_get_cpl_no_cache,
.get_cs_db_l_bits = vmx_get_cs_db_l_bits,
.is_valid_cr0 = vmx_is_valid_cr0,
.set_cr0 = vmx_set_cr0,
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index a8e7bc04d9bf..aa78b6f38dfe 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -7,6 +7,7 @@
#include <asm/debugreg.h>
#include <asm/mmu_context.h>
+#include "x86.h"
#include "cpuid.h"
#include "hyperv.h"
#include "mmu.h"
@@ -16,7 +17,6 @@
#include "sgx.h"
#include "trace.h"
#include "vmx.h"
-#include "x86.h"
#include "smm.h"
static bool __read_mostly enable_shadow_vmcs = 1;
@@ -231,11 +231,8 @@ static inline void nested_release_evmcs(struct kvm_vcpu *vcpu)
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
struct vcpu_vmx *vmx = to_vmx(vcpu);
- if (nested_vmx_is_evmptr12_valid(vmx)) {
- kvm_vcpu_unmap(vcpu, &vmx->nested.hv_evmcs_map, true);
- vmx->nested.hv_evmcs = NULL;
- }
-
+ kvm_vcpu_unmap(vcpu, &vmx->nested.hv_evmcs_map);
+ vmx->nested.hv_evmcs = NULL;
vmx->nested.hv_evmcs_vmptr = EVMPTR_INVALID;
if (hv_vcpu) {
@@ -317,6 +314,16 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
vcpu->arch.regs_dirty = 0;
}
+static void nested_put_vmcs12_pages(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ kvm_vcpu_unmap(vcpu, &vmx->nested.apic_access_page_map);
+ kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map);
+ kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map);
+ vmx->nested.pi_desc = NULL;
+}
+
/*
* Free whatever needs to be freed from vmx->nested when L1 goes down, or
* just stops using VMX.
@@ -349,15 +356,8 @@ static void free_nested(struct kvm_vcpu *vcpu)
vmx->nested.cached_vmcs12 = NULL;
kfree(vmx->nested.cached_shadow_vmcs12);
vmx->nested.cached_shadow_vmcs12 = NULL;
- /*
- * Unpin physical memory we referred to in the vmcs02. The APIC access
- * page's backing page (yeah, confusing) shouldn't actually be accessed,
- * and if it is written, the contents are irrelevant.
- */
- kvm_vcpu_unmap(vcpu, &vmx->nested.apic_access_page_map, false);
- kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);
- kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map, true);
- vmx->nested.pi_desc = NULL;
+
+ nested_put_vmcs12_pages(vcpu);
kvm_mmu_free_roots(vcpu->kvm, &vcpu->arch.guest_mmu, KVM_MMU_ROOTS_ALL);
@@ -624,7 +624,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
int msr;
unsigned long *msr_bitmap_l1;
unsigned long *msr_bitmap_l0 = vmx->nested.vmcs02.msr_bitmap;
- struct kvm_host_map *map = &vmx->nested.msr_bitmap_map;
+ struct kvm_host_map map;
/* Nothing to do if the MSR bitmap is not in use. */
if (!cpu_has_vmx_msr_bitmap() ||
@@ -647,10 +647,10 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
return true;
}
- if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcs12->msr_bitmap), map))
+ if (kvm_vcpu_map_readonly(vcpu, gpa_to_gfn(vmcs12->msr_bitmap), &map))
return false;
- msr_bitmap_l1 = (unsigned long *)map->hva;
+ msr_bitmap_l1 = (unsigned long *)map.hva;
/*
* To keep the control flow simple, pay eight 8-byte writes (sixteen
@@ -714,7 +714,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
MSR_IA32_FLUSH_CMD, MSR_TYPE_W);
- kvm_vcpu_unmap(vcpu, &vmx->nested.msr_bitmap_map, false);
+ kvm_vcpu_unmap(vcpu, &map);
vmx->nested.force_msr_bitmap_recalc = false;
@@ -1197,11 +1197,14 @@ static void nested_vmx_transition_tlb_flush(struct kvm_vcpu *vcpu,
kvm_hv_nested_transtion_tlb_flush(vcpu, enable_ept);
/*
- * If vmcs12 doesn't use VPID, L1 expects linear and combined mappings
- * for *all* contexts to be flushed on VM-Enter/VM-Exit, i.e. it's a
- * full TLB flush from the guest's perspective. This is required even
- * if VPID is disabled in the host as KVM may need to synchronize the
- * MMU in response to the guest TLB flush.
+ * If VPID is disabled, then guest TLB accesses use VPID=0, i.e. the
+ * same VPID as the host, and so architecturally, linear and combined
+ * mappings for VPID=0 must be flushed at VM-Enter and VM-Exit. KVM
+ * emulates L2 sharing L1's VPID=0 by using vpid01 while running L2,
+ * and so KVM must also emulate TLB flush of VPID=0, i.e. vpid01. This
+ * is required if VPID is disabled in KVM, as a TLB flush (there are no
+ * VPIDs) still occurs from L1's perspective, and KVM may need to
+ * synchronize the MMU in response to the guest TLB flush.
*
* Note, using TLB_FLUSH_GUEST is correct even if nested EPT is in use.
* EPT is a special snowflake, as guest-physical mappings aren't
@@ -2315,6 +2318,17 @@ static void prepare_vmcs02_early_rare(struct vcpu_vmx *vmx,
vmcs_write64(VMCS_LINK_POINTER, INVALID_GPA);
+ /*
+ * If VPID is disabled, then guest TLB accesses use VPID=0, i.e. the
+ * same VPID as the host. Emulate this behavior by using vpid01 for L2
+ * if VPID is disabled in vmcs12. Note, if VPID is disabled, VM-Enter
+ * and VM-Exit are architecturally required to flush VPID=0, but *only*
+ * VPID=0. I.e. using vpid02 would be ok (so long as KVM emulates the
+ * required flushes), but doing so would cause KVM to over-flush. E.g.
+ * if L1 runs L2 X with VPID12=1, then runs L2 Y with VPID12 disabled,
+ * and then runs L2 X again, then KVM can and should retain TLB entries
+ * for VPID12=1.
+ */
if (enable_vpid) {
if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02)
vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->nested.vpid02);
@@ -2996,6 +3010,17 @@ static int nested_vmx_check_address_space_size(struct kvm_vcpu *vcpu,
return 0;
}
+static bool is_l1_noncanonical_address_on_vmexit(u64 la, struct vmcs12 *vmcs12)
+{
+ /*
+ * Check that the given linear address is canonical after a VM exit
+ * from L2, based on HOST_CR4.LA57 value that will be loaded for L1.
+ */
+ u8 l1_address_bits_on_exit = (vmcs12->host_cr4 & X86_CR4_LA57) ? 57 : 48;
+
+ return !__is_canonical_address(la, l1_address_bits_on_exit);
+}
+
static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
struct vmcs12 *vmcs12)
{
@@ -3006,8 +3031,8 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
CC(!kvm_vcpu_is_legal_cr3(vcpu, vmcs12->host_cr3)))
return -EINVAL;
- if (CC(is_noncanonical_address(vmcs12->host_ia32_sysenter_esp, vcpu)) ||
- CC(is_noncanonical_address(vmcs12->host_ia32_sysenter_eip, vcpu)))
+ if (CC(is_noncanonical_msr_address(vmcs12->host_ia32_sysenter_esp, vcpu)) ||
+ CC(is_noncanonical_msr_address(vmcs12->host_ia32_sysenter_eip, vcpu)))
return -EINVAL;
if ((vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT) &&
@@ -3041,12 +3066,12 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
CC(vmcs12->host_ss_selector == 0 && !ia32e))
return -EINVAL;
- if (CC(is_noncanonical_address(vmcs12->host_fs_base, vcpu)) ||
- CC(is_noncanonical_address(vmcs12->host_gs_base, vcpu)) ||
- CC(is_noncanonical_address(vmcs12->host_gdtr_base, vcpu)) ||
- CC(is_noncanonical_address(vmcs12->host_idtr_base, vcpu)) ||
- CC(is_noncanonical_address(vmcs12->host_tr_base, vcpu)) ||
- CC(is_noncanonical_address(vmcs12->host_rip, vcpu)))
+ if (CC(is_noncanonical_base_address(vmcs12->host_fs_base, vcpu)) ||
+ CC(is_noncanonical_base_address(vmcs12->host_gs_base, vcpu)) ||
+ CC(is_noncanonical_base_address(vmcs12->host_gdtr_base, vcpu)) ||
+ CC(is_noncanonical_base_address(vmcs12->host_idtr_base, vcpu)) ||
+ CC(is_noncanonical_base_address(vmcs12->host_tr_base, vcpu)) ||
+ CC(is_l1_noncanonical_address_on_vmexit(vmcs12->host_rip, vmcs12)))
return -EINVAL;
/*
@@ -3164,7 +3189,7 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
}
if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS) &&
- (CC(is_noncanonical_address(vmcs12->guest_bndcfgs & PAGE_MASK, vcpu)) ||
+ (CC(is_noncanonical_msr_address(vmcs12->guest_bndcfgs & PAGE_MASK, vcpu)) ||
CC((vmcs12->guest_bndcfgs & MSR_IA32_BNDCFGS_RSVD))))
return -EINVAL;
@@ -5013,11 +5038,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
vmx_update_cpu_dirty_logging(vcpu);
}
- /* Unpin physical memory we referred to in vmcs02 */
- kvm_vcpu_unmap(vcpu, &vmx->nested.apic_access_page_map, false);
- kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);
- kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map, true);
- vmx->nested.pi_desc = NULL;
+ nested_put_vmcs12_pages(vcpu);
if (vmx->nested.reload_vmcs01_apic_access_page) {
vmx->nested.reload_vmcs01_apic_access_page = false;
@@ -5153,7 +5174,7 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
* non-canonical form. This is the only check on the memory
* destination for long mode!
*/
- exn = is_noncanonical_address(*ret, vcpu);
+ exn = is_noncanonical_address(*ret, vcpu, 0);
} else {
/*
* When not in long mode, the virtual/linear address is
@@ -5950,6 +5971,12 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
return nested_vmx_fail(vcpu,
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+ /*
+ * Always flush the effective vpid02, i.e. never flush the current VPID
+ * and never explicitly flush vpid01. INVVPID targets a VPID, not a
+ * VMCS, and so whether or not the current vmcs12 has VPID enabled is
+ * irrelevant (and there may not be a loaded vmcs12).
+ */
vpid02 = nested_get_vpid02(vcpu);
switch (type) {
case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
@@ -5958,7 +5985,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
* invalidation.
*/
if (!operand.vpid ||
- is_noncanonical_address(operand.gla, vcpu))
+ is_noncanonical_invlpg_address(operand.gla, vcpu))
return nested_vmx_fail(vcpu,
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
vpid_sync_vcpu_addr(vpid02, operand.gla);
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 83382a4d1d66..9c9d4a336166 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -365,7 +365,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
}
break;
case MSR_IA32_DS_AREA:
- if (is_noncanonical_address(data, vcpu))
+ if (is_noncanonical_msr_address(data, vcpu))
return 1;
pmu->ds_area = data;
diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c
index a3c3d2a51f47..b352a3ba7354 100644
--- a/arch/x86/kvm/vmx/sgx.c
+++ b/arch/x86/kvm/vmx/sgx.c
@@ -4,12 +4,11 @@
#include <asm/sgx.h>
-#include "cpuid.h"
+#include "x86.h"
#include "kvm_cache_regs.h"
#include "nested.h"
#include "sgx.h"
#include "vmx.h"
-#include "x86.h"
bool __read_mostly enable_sgx = 1;
module_param_named(sgx, enable_sgx, bool, 0444);
@@ -38,7 +37,7 @@ static int sgx_get_encls_gva(struct kvm_vcpu *vcpu, unsigned long offset,
fault = true;
} else if (likely(is_64_bit_mode(vcpu))) {
*gva = vmx_get_untagged_addr(vcpu, *gva, 0);
- fault = is_noncanonical_address(*gva, vcpu);
+ fault = is_noncanonical_address(*gva, vcpu, 0);
} else {
*gva &= 0xffffffff;
fault = (s.unusable) ||
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 81ed596e4454..893366e53732 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -217,9 +217,11 @@ module_param(ple_window_shrink, uint, 0444);
static unsigned int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
module_param(ple_window_max, uint, 0444);
-/* Default is SYSTEM mode, 1 for host-guest mode */
+/* Default is SYSTEM mode, 1 for host-guest mode (which is BROKEN) */
int __read_mostly pt_mode = PT_MODE_SYSTEM;
+#ifdef CONFIG_BROKEN
module_param(pt_mode, int, S_IRUGO);
+#endif
struct x86_pmu_lbr __ro_after_init vmx_lbr_caps;
@@ -481,10 +483,9 @@ noinline void invvpid_error(unsigned long ext, u16 vpid, gva_t gva)
ext, vpid, gva);
}
-noinline void invept_error(unsigned long ext, u64 eptp, gpa_t gpa)
+noinline void invept_error(unsigned long ext, u64 eptp)
{
- vmx_insn_failed("invept failed: ext=0x%lx eptp=%llx gpa=0x%llx\n",
- ext, eptp, gpa);
+ vmx_insn_failed("invept failed: ext=0x%lx eptp=%llx\n", ext, eptp);
}
static DEFINE_PER_CPU(struct vmcs *, vmxarea);
@@ -2283,7 +2284,7 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
(!msr_info->host_initiated &&
!guest_cpuid_has(vcpu, X86_FEATURE_MPX)))
return 1;
- if (is_noncanonical_address(data & PAGE_MASK, vcpu) ||
+ if (is_noncanonical_msr_address(data & PAGE_MASK, vcpu) ||
(data & MSR_IA32_BNDCFGS_RSVD))
return 1;
@@ -2448,7 +2449,7 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
index = msr_info->index - MSR_IA32_RTIT_ADDR0_A;
if (index >= 2 * vmx->pt_desc.num_address_ranges)
return 1;
- if (is_noncanonical_address(data, vcpu))
+ if (is_noncanonical_msr_address(data, vcpu))
return 1;
if (index % 2)
vmx->pt_desc.guest.addr_b[index / 2] = data;
@@ -2456,8 +2457,6 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
vmx->pt_desc.guest.addr_a[index / 2] = data;
break;
case MSR_IA32_PERF_CAPABILITIES:
- if (data && !vcpu_to_pmu(vcpu)->version)
- return 1;
if (data & PMU_CAP_LBR_FMT) {
if ((data & PMU_CAP_LBR_FMT) !=
(kvm_caps.supported_perf_cap & PMU_CAP_LBR_FMT))
@@ -2549,28 +2548,6 @@ static bool cpu_has_sgx(void)
return cpuid_eax(0) >= 0x12 && (cpuid_eax(0x12) & BIT(0));
}
-/*
- * Some cpus support VM_{ENTRY,EXIT}_IA32_PERF_GLOBAL_CTRL but they
- * can't be used due to errata where VM Exit may incorrectly clear
- * IA32_PERF_GLOBAL_CTRL[34:32]. Work around the errata by using the
- * MSR load mechanism to switch IA32_PERF_GLOBAL_CTRL.
- */
-static bool cpu_has_perf_global_ctrl_bug(void)
-{
- switch (boot_cpu_data.x86_vfm) {
- case INTEL_NEHALEM_EP: /* AAK155 */
- case INTEL_NEHALEM: /* AAP115 */
- case INTEL_WESTMERE: /* AAT100 */
- case INTEL_WESTMERE_EP: /* BC86,AAY89,BD102 */
- case INTEL_NEHALEM_EX: /* BA97 */
- return true;
- default:
- break;
- }
-
- return false;
-}
-
static int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, u32 msr, u32 *result)
{
u32 vmx_msr_low, vmx_msr_high;
@@ -2730,6 +2707,27 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
_vmexit_control &= ~x_ctrl;
}
+ /*
+ * Some cpus support VM_{ENTRY,EXIT}_IA32_PERF_GLOBAL_CTRL but they
+ * can't be used due to an errata where VM Exit may incorrectly clear
+ * IA32_PERF_GLOBAL_CTRL[34:32]. Workaround the errata by using the
+ * MSR load mechanism to switch IA32_PERF_GLOBAL_CTRL.
+ */
+ switch (boot_cpu_data.x86_vfm) {
+ case INTEL_NEHALEM_EP: /* AAK155 */
+ case INTEL_NEHALEM: /* AAP115 */
+ case INTEL_WESTMERE: /* AAT100 */
+ case INTEL_WESTMERE_EP: /* BC86,AAY89,BD102 */
+ case INTEL_NEHALEM_EX: /* BA97 */
+ _vmentry_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+ _vmexit_control &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
+ pr_warn_once("VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
+ "does not work properly. Using workaround\n");
+ break;
+ default:
+ break;
+ }
+
rdmsrl(MSR_IA32_VMX_BASIC, basic_msr);
/* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
@@ -3216,7 +3214,7 @@ void vmx_flush_tlb_all(struct kvm_vcpu *vcpu)
static inline int vmx_get_current_vpid(struct kvm_vcpu *vcpu)
{
- if (is_guest_mode(vcpu))
+ if (is_guest_mode(vcpu) && nested_cpu_has_vpid(get_vmcs12(vcpu)))
return nested_get_vpid02(vcpu);
return to_vmx(vcpu)->vpid;
}
@@ -3568,16 +3566,29 @@ u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
return vmx_read_guest_seg_base(to_vmx(vcpu), seg);
}
-int vmx_get_cpl(struct kvm_vcpu *vcpu)
+static int __vmx_get_cpl(struct kvm_vcpu *vcpu, bool no_cache)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int ar;
if (unlikely(vmx->rmode.vm86_active))
return 0;
- else {
- int ar = vmx_read_guest_seg_ar(vmx, VCPU_SREG_SS);
- return VMX_AR_DPL(ar);
- }
+
+ if (no_cache)
+ ar = vmcs_read32(GUEST_SS_AR_BYTES);
+ else
+ ar = vmx_read_guest_seg_ar(vmx, VCPU_SREG_SS);
+ return VMX_AR_DPL(ar);
+}
+
+int vmx_get_cpl(struct kvm_vcpu *vcpu)
+{
+ return __vmx_get_cpl(vcpu, false);
+}
+
+int vmx_get_cpl_no_cache(struct kvm_vcpu *vcpu)
+{
+ return __vmx_get_cpl(vcpu, true);
}
static u32 vmx_segment_access_rights(struct kvm_segment *var)
@@ -4420,9 +4431,6 @@ static u32 vmx_vmentry_ctrl(void)
VM_ENTRY_LOAD_IA32_EFER |
VM_ENTRY_IA32E_MODE);
- if (cpu_has_perf_global_ctrl_bug())
- vmentry_ctrl &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
-
return vmentry_ctrl;
}
@@ -4440,10 +4448,6 @@ static u32 vmx_vmexit_ctrl(void)
if (vmx_pt_mode_is_system())
vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP |
VM_EXIT_CLEAR_IA32_RTIT_CTL);
-
- if (cpu_has_perf_global_ctrl_bug())
- vmexit_ctrl &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
-
/* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
return vmexit_ctrl &
~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER);
@@ -4559,7 +4563,8 @@ vmx_adjust_secondary_exec_control(struct vcpu_vmx *vmx, u32 *exec_control,
* Update the nested MSR settings so that a nested VMM can/can't set
* controls for features that are/aren't exposed to the guest.
*/
- if (nested) {
+ if (nested &&
+ kvm_check_has_quirk(vmx->vcpu.kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS)) {
/*
* All features that can be added or removed to VMX MSRs must
* be supported in the first place for nested virtualization.
@@ -4849,7 +4854,8 @@ static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu)
init_vmcs(vmx);
- if (nested)
+ if (nested &&
+ kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
memcpy(&vmx->nested.msrs, &vmcs_config.nested, sizeof(vmx->nested.msrs));
vcpu_setup_sgx_lepubkeyhash(vcpu);
@@ -4862,7 +4868,8 @@ static void __vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmx->nested.hv_evmcs_vmptr = EVMPTR_INVALID;
#endif
- vcpu->arch.microcode_version = 0x100000000ULL;
+ if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
+ vcpu->arch.microcode_version = 0x100000000ULL;
vmx->msr_ia32_feature_control_valid_bits = FEAT_CTL_LOCKED;
/*
@@ -6790,8 +6797,10 @@ void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu)
struct kvm *kvm = vcpu->kvm;
struct kvm_memslots *slots = kvm_memslots(kvm);
struct kvm_memory_slot *slot;
+ struct page *refcounted_page;
unsigned long mmu_seq;
kvm_pfn_t pfn;
+ bool writable;
/* Defer reload until vmcs01 is the current VMCS. */
if (is_guest_mode(vcpu)) {
@@ -6827,30 +6836,30 @@ void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu)
* controls the APIC-access page memslot, and only deletes the memslot
* if APICv is permanently inhibited, i.e. the memslot won't reappear.
*/
- pfn = gfn_to_pfn_memslot(slot, gfn);
+ pfn = __kvm_faultin_pfn(slot, gfn, FOLL_WRITE, &writable, &refcounted_page);
if (is_error_noslot_pfn(pfn))
return;
read_lock(&vcpu->kvm->mmu_lock);
- if (mmu_invalidate_retry_gfn(kvm, mmu_seq, gfn)) {
+ if (mmu_invalidate_retry_gfn(kvm, mmu_seq, gfn))
kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
- read_unlock(&vcpu->kvm->mmu_lock);
- goto out;
- }
+ else
+ vmcs_write64(APIC_ACCESS_ADDR, pfn_to_hpa(pfn));
- vmcs_write64(APIC_ACCESS_ADDR, pfn_to_hpa(pfn));
- read_unlock(&vcpu->kvm->mmu_lock);
+ /*
+ * Do not pin the APIC access page in memory so that it can be freely
+ * migrated, the MMU notifier will call us again if it is migrated or
+ * swapped out. KVM backs the memslot with anonymous memory, the pfn
+ * should always point at a refcounted page (if the pfn is valid).
+ */
+ if (!WARN_ON_ONCE(!refcounted_page))
+ kvm_release_page_clean(refcounted_page);
/*
* No need for a manual TLB flush at this point, KVM has already done a
* flush if there were SPTEs pointing at the previous page.
*/
-out:
- /*
- * Do not pin apic access page in memory, the MMU notifier
- * will call us again if it is migrated or swapped out.
- */
- kvm_release_pfn_clean(pfn);
+ read_unlock(&vcpu->kvm->mmu_lock);
}
void vmx_hwapic_isr_update(int max_isr)
@@ -8398,10 +8407,6 @@ __init int vmx_hardware_setup(void)
if (setup_vmcs_config(&vmcs_config, &vmx_capability) < 0)
return -EIO;
- if (cpu_has_perf_global_ctrl_bug())
- pr_warn_once("VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
- "does not work properly. Using workaround\n");
-
if (boot_cpu_has(X86_FEATURE_NX))
kvm_enable_efer_bits(EFER_NX);
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 2325f773a20b..43f573f6ca46 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -200,8 +200,6 @@ struct nested_vmx {
struct kvm_host_map virtual_apic_map;
struct kvm_host_map pi_desc_map;
- struct kvm_host_map msr_bitmap_map;
-
struct pi_desc *pi_desc;
bool pi_pending;
u16 posted_intr_nv;
@@ -385,6 +383,7 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu);
void vmx_set_host_fs_gs(struct vmcs_host_state *host, u16 fs_sel, u16 gs_sel,
unsigned long fs_base, unsigned long gs_base);
int vmx_get_cpl(struct kvm_vcpu *vcpu);
+int vmx_get_cpl_no_cache(struct kvm_vcpu *vcpu);
bool vmx_emulation_required(struct kvm_vcpu *vcpu);
unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu);
void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
diff --git a/arch/x86/kvm/vmx/vmx_ops.h b/arch/x86/kvm/vmx/vmx_ops.h
index 93e020dc88f6..633c87e2fd92 100644
--- a/arch/x86/kvm/vmx/vmx_ops.h
+++ b/arch/x86/kvm/vmx/vmx_ops.h
@@ -15,7 +15,7 @@ void vmwrite_error(unsigned long field, unsigned long value);
void vmclear_error(struct vmcs *vmcs, u64 phys_addr);
void vmptrld_error(struct vmcs *vmcs, u64 phys_addr);
void invvpid_error(unsigned long ext, u16 vpid, gva_t gva);
-void invept_error(unsigned long ext, u64 eptp, gpa_t gpa);
+void invept_error(unsigned long ext, u64 eptp);
#ifndef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
/*
@@ -312,13 +312,13 @@ static inline void __invvpid(unsigned long ext, u16 vpid, gva_t gva)
vmx_asm2(invvpid, "r"(ext), "m"(operand), ext, vpid, gva);
}
-static inline void __invept(unsigned long ext, u64 eptp, gpa_t gpa)
+static inline void __invept(unsigned long ext, u64 eptp)
{
struct {
- u64 eptp, gpa;
- } operand = {eptp, gpa};
-
- vmx_asm2(invept, "r"(ext), "m"(operand), ext, eptp, gpa);
+ u64 eptp;
+ u64 reserved_0;
+ } operand = { eptp, 0 };
+ vmx_asm2(invept, "r"(ext), "m"(operand), ext, eptp);
}
static inline void vpid_sync_vcpu_single(int vpid)
@@ -355,13 +355,13 @@ static inline void vpid_sync_vcpu_addr(int vpid, gva_t addr)
static inline void ept_sync_global(void)
{
- __invept(VMX_EPT_EXTENT_GLOBAL, 0, 0);
+ __invept(VMX_EPT_EXTENT_GLOBAL, 0);
}
static inline void ept_sync_context(u64 eptp)
{
if (cpu_has_vmx_invept_context())
- __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
+ __invept(VMX_EPT_EXTENT_CONTEXT, eptp);
else
ept_sync_global();
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 83fe0a78146f..2e713480933a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -451,6 +451,7 @@ static const u32 msr_based_features_all_except_vmx[] = {
MSR_IA32_UCODE_REV,
MSR_IA32_ARCH_CAPABILITIES,
MSR_IA32_PERF_CAPABILITIES,
+ MSR_PLATFORM_INFO,
};
static u32 msr_based_features[ARRAY_SIZE(msr_based_features_all_except_vmx) +
@@ -667,38 +668,6 @@ static void drop_user_return_notifiers(void)
kvm_on_user_return(&msrs->urn);
}
-u64 kvm_get_apic_base(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.apic_base;
-}
-
-enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
-{
- return kvm_apic_mode(kvm_get_apic_base(vcpu));
-}
-EXPORT_SYMBOL_GPL(kvm_get_apic_mode);
-
-int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
-{
- enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
- enum lapic_mode new_mode = kvm_apic_mode(msr_info->data);
- u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
- (guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
-
- if ((msr_info->data & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
- return 1;
- if (!msr_info->host_initiated) {
- if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
- return 1;
- if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
- return 1;
- }
-
- kvm_lapic_set_base(vcpu, msr_info->data);
- kvm_recalculate_apic_map(vcpu->kvm);
- return 0;
-}
-
/*
* Handle a fault on a hardware virtualization (VMX or SVM) instruction.
*
@@ -1706,6 +1675,9 @@ static int kvm_get_feature_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data,
case MSR_IA32_PERF_CAPABILITIES:
*data = kvm_caps.supported_perf_cap;
break;
+ case MSR_PLATFORM_INFO:
+ *data = MSR_PLATFORM_INFO_CPUID_FAULT;
+ break;
case MSR_IA32_UCODE_REV:
rdmsrl_safe(index, data);
break;
@@ -1854,7 +1826,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
case MSR_KERNEL_GS_BASE:
case MSR_CSTAR:
case MSR_LSTAR:
- if (is_noncanonical_address(data, vcpu))
+ if (is_noncanonical_msr_address(data, vcpu))
return 1;
break;
case MSR_IA32_SYSENTER_EIP:
@@ -1871,7 +1843,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
* value, and that something deterministic happens if the guest
* invokes 64-bit SYSENTER.
*/
- data = __canonical_address(data, vcpu_virt_addr_bits(vcpu));
+ data = __canonical_address(data, max_host_virt_addr_bits());
break;
case MSR_TSC_AUX:
if (!kvm_is_supported_user_return_msr(MSR_TSC_AUX))
@@ -2144,8 +2116,9 @@ EXPORT_SYMBOL_GPL(kvm_emulate_monitor);
static inline bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu)
{
xfer_to_guest_mode_prepare();
- return vcpu->mode == EXITING_GUEST_MODE || kvm_request_pending(vcpu) ||
- xfer_to_guest_mode_work_pending();
+
+ return READ_ONCE(vcpu->mode) == EXITING_GUEST_MODE ||
+ kvm_request_pending(vcpu) || xfer_to_guest_mode_work_pending();
}
/*
@@ -3793,13 +3766,16 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
vcpu->arch.microcode_version = data;
break;
case MSR_IA32_ARCH_CAPABILITIES:
- if (!msr_info->host_initiated)
- return 1;
+ if (!msr_info->host_initiated ||
+ !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
+ return KVM_MSR_RET_UNSUPPORTED;
vcpu->arch.arch_capabilities = data;
break;
case MSR_IA32_PERF_CAPABILITIES:
- if (!msr_info->host_initiated)
- return 1;
+ if (!msr_info->host_initiated ||
+ !guest_cpuid_has(vcpu, X86_FEATURE_PDCM))
+ return KVM_MSR_RET_UNSUPPORTED;
+
if (data & ~kvm_caps.supported_perf_cap)
return 1;
@@ -3890,7 +3866,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_MTRRdefType:
return kvm_mtrr_set_msr(vcpu, msr, data);
case MSR_IA32_APICBASE:
- return kvm_set_apic_base(vcpu, msr_info);
+ return kvm_apic_set_base(vcpu, data, msr_info->host_initiated);
case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
return kvm_x2apic_msr_write(vcpu, msr, data);
case MSR_IA32_TSC_DEADLINE:
@@ -4111,9 +4087,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
vcpu->arch.osvw.status = data;
break;
case MSR_PLATFORM_INFO:
- if (!msr_info->host_initiated ||
- (!(data & MSR_PLATFORM_INFO_CPUID_FAULT) &&
- cpuid_fault_enabled(vcpu)))
+ if (!msr_info->host_initiated)
return 1;
vcpu->arch.msr_platform_info = data;
break;
@@ -4252,15 +4226,13 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = vcpu->arch.microcode_version;
break;
case MSR_IA32_ARCH_CAPABILITIES:
- if (!msr_info->host_initiated &&
- !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
- return 1;
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
+ return KVM_MSR_RET_UNSUPPORTED;
msr_info->data = vcpu->arch.arch_capabilities;
break;
case MSR_IA32_PERF_CAPABILITIES:
- if (!msr_info->host_initiated &&
- !guest_cpuid_has(vcpu, X86_FEATURE_PDCM))
- return 1;
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_PDCM))
+ return KVM_MSR_RET_UNSUPPORTED;
msr_info->data = vcpu->arch.perf_capabilities;
break;
case MSR_IA32_POWER_CTL:
@@ -4314,7 +4286,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = 1 << 24;
break;
case MSR_IA32_APICBASE:
- msr_info->data = kvm_get_apic_base(vcpu);
+ msr_info->data = vcpu->arch.apic_base;
break;
case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
return kvm_x2apic_msr_read(vcpu, msr_info->index, &msr_info->data);
@@ -5094,7 +5066,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
int idx;
if (vcpu->preempted) {
- vcpu->arch.preempted_in_kernel = kvm_arch_vcpu_in_kernel(vcpu);
+ /*
+ * Assume protected guests are in-kernel. Inefficient yielding
+ * due to false positives is preferable to never yielding due
+ * to false negatives.
+ */
+ vcpu->arch.preempted_in_kernel = vcpu->arch.guest_state_protected ||
+ !kvm_x86_call(get_cpl_no_cache)(vcpu);
/*
* Take the srcu lock as memslots will be accessed to check the gfn
@@ -8612,6 +8590,12 @@ static gva_t emulator_get_untagged_addr(struct x86_emulate_ctxt *ctxt,
addr, flags);
}
+static bool emulator_is_canonical_addr(struct x86_emulate_ctxt *ctxt,
+ gva_t addr, unsigned int flags)
+{
+ return !is_noncanonical_address(addr, emul_to_vcpu(ctxt), flags);
+}
+
static const struct x86_emulate_ops emulate_ops = {
.vm_bugged = emulator_vm_bugged,
.read_gpr = emulator_read_gpr,
@@ -8658,6 +8642,7 @@ static const struct x86_emulate_ops emulate_ops = {
.triple_fault = emulator_triple_fault,
.set_xcr = emulator_set_xcr,
.get_untagged_addr = emulator_get_untagged_addr,
+ .is_canonical_addr = emulator_is_canonical_addr,
};
static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
@@ -10159,7 +10144,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
kvm_run->if_flag = kvm_x86_call(get_if_flag)(vcpu);
kvm_run->cr8 = kvm_get_cr8(vcpu);
- kvm_run->apic_base = kvm_get_apic_base(vcpu);
+ kvm_run->apic_base = vcpu->arch.apic_base;
kvm_run->ready_for_interrupt_injection =
pic_in_kernel(vcpu->kvm) ||
@@ -10576,8 +10561,8 @@ static void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
* deleted if any vCPU has xAPIC virtualization and x2APIC enabled, but
* and hardware doesn't support x2APIC virtualization. E.g. some AMD
* CPUs support AVIC but not x2APIC. KVM still allows enabling AVIC in
- * this case so that KVM can the AVIC doorbell to inject interrupts to
- * running vCPUs, but KVM must not create SPTEs for the APIC base as
+ * this case so that KVM can use the AVIC doorbell to inject interrupts
+ * to running vCPUs, but KVM must not create SPTEs for the APIC base as
* the vCPU would incorrectly be able to access the vAPIC page via MMIO
* despite being in x2APIC mode. For simplicity, inhibiting the APIC
* access page is sticky.
@@ -10606,11 +10591,11 @@ void __kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
if (!!old != !!new) {
/*
* Kick all vCPUs before setting apicv_inhibit_reasons to avoid
- * false positives in the sanity check WARN in svm_vcpu_run().
+ * false positives in the sanity check WARN in vcpu_enter_guest().
* This task will wait for all vCPUs to ack the kick IRQ before
* updating apicv_inhibit_reasons, and all other vCPUs will
* block on acquiring apicv_update_lock so that vCPUs can't
- * redo svm_vcpu_run() without seeing the new inhibit state.
+ * redo vcpu_enter_guest() without seeing the new inhibit state.
*
* Note, holding apicv_update_lock and taking it in the read
* side (handling the request) also prevents other vCPUs from
@@ -11711,7 +11696,7 @@ skip_protected_regs:
sregs->cr4 = kvm_read_cr4(vcpu);
sregs->cr8 = kvm_get_cr8(vcpu);
sregs->efer = vcpu->arch.efer;
- sregs->apic_base = kvm_get_apic_base(vcpu);
+ sregs->apic_base = vcpu->arch.apic_base;
}
static void __get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
@@ -11888,16 +11873,13 @@ static bool kvm_is_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
int *mmu_reset_needed, bool update_pdptrs)
{
- struct msr_data apic_base_msr;
int idx;
struct desc_ptr dt;
if (!kvm_is_valid_sregs(vcpu, sregs))
return -EINVAL;
- apic_base_msr.data = sregs->apic_base;
- apic_base_msr.host_initiated = true;
- if (kvm_set_apic_base(vcpu, &apic_base_msr))
+ if (kvm_apic_set_base(vcpu, sregs->apic_base, true))
return -EINVAL;
if (vcpu->arch.guest_state_protected)
@@ -12299,7 +12281,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
kvm_async_pf_hash_reset(vcpu);
- vcpu->arch.perf_capabilities = kvm_caps.supported_perf_cap;
+ if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_STUFF_FEATURE_MSRS)) {
+ vcpu->arch.arch_capabilities = kvm_get_arch_capabilities();
+ vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
+ vcpu->arch.perf_capabilities = kvm_caps.supported_perf_cap;
+ }
kvm_pmu_init(vcpu);
vcpu->arch.pending_external_vector = -1;
@@ -12313,8 +12299,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
if (r)
goto free_guest_fpu;
- vcpu->arch.arch_capabilities = kvm_get_arch_capabilities();
- vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
kvm_xen_init_vcpu(vcpu);
vcpu_load(vcpu);
kvm_set_tsc_khz(vcpu, vcpu->kvm->arch.default_tsc_khz);
@@ -13104,19 +13088,15 @@ static void kvm_mmu_slot_apply_flags(struct kvm *kvm,
if (!log_dirty_pages) {
/*
- * Dirty logging tracks sptes in 4k granularity, meaning that
- * large sptes have to be split. If live migration succeeds,
- * the guest in the source machine will be destroyed and large
- * sptes will be created in the destination. However, if the
- * guest continues to run in the source machine (for example if
- * live migration fails), small sptes will remain around and
- * cause bad performance.
+ * Recover huge page mappings in the slot now that dirty logging
+ * is disabled, i.e. now that KVM does not have to track guest
+ * writes at 4KiB granularity.
*
- * Scan sptes if dirty logging has been stopped, dropping those
- * which can be collapsed into a single large-page spte. Later
- * page faults will create the large-page sptes.
+ * Dirty logging might be disabled by userspace if an ongoing VM
+ * live migration is cancelled and the VM must continue running
+ * on the source.
*/
- kvm_mmu_zap_collapsible_sptes(kvm, new);
+ kvm_mmu_recover_huge_pages(kvm, new);
} else {
/*
* Initially-all-set does not require write protecting any page,
@@ -13207,6 +13187,8 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
{
+ WARN_ON_ONCE(!kvm_arch_pmi_in_guest(vcpu));
+
if (vcpu->arch.guest_state_protected)
return true;
@@ -13215,6 +13197,11 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu)
{
+ WARN_ON_ONCE(!kvm_arch_pmi_in_guest(vcpu));
+
+ if (vcpu->arch.guest_state_protected)
+ return 0;
+
return kvm_rip_read(vcpu);
}
@@ -13730,7 +13717,7 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva)
* invalidation.
*/
if ((!pcid_enabled && (operand.pcid != 0)) ||
- is_noncanonical_address(operand.gla, vcpu)) {
+ is_noncanonical_invlpg_address(operand.gla, vcpu)) {
kvm_inject_gp(vcpu, 0);
return 1;
}
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index a84c48ef5278..ec623d23d13d 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -8,6 +8,7 @@
#include <asm/pvclock.h>
#include "kvm_cache_regs.h"
#include "kvm_emulate.h"
+#include "cpuid.h"
struct kvm_caps {
/* control of guest tsc rate supported? */
@@ -233,9 +234,52 @@ static inline u8 vcpu_virt_addr_bits(struct kvm_vcpu *vcpu)
return kvm_is_cr4_bit_set(vcpu, X86_CR4_LA57) ? 57 : 48;
}
-static inline bool is_noncanonical_address(u64 la, struct kvm_vcpu *vcpu)
+static inline u8 max_host_virt_addr_bits(void)
{
- return !__is_canonical_address(la, vcpu_virt_addr_bits(vcpu));
+ return kvm_cpu_cap_has(X86_FEATURE_LA57) ? 57 : 48;
+}
+
+/*
+ * x86 MSRs which contain linear addresses, x86 hidden segment bases, and
+ * IDT/GDT bases have static canonicality checks, the size of which depends
+ * only on the CPU's support for 5-level paging, rather than on the state of
+ * CR4.LA57. This applies to both WRMSR and to other instructions that set
+ * their values, e.g. SGDT.
+ *
+ * KVM passes through most of these MSRS and also doesn't intercept the
+ * instructions that set the hidden segment bases.
+ *
+ * Because of this, to be consistent with hardware, even if the guest doesn't
+ * have LA57 enabled in its CPUID, perform canonicality checks based on *host*
+ * support for 5 level paging.
+ *
+ * Finally, instructions which are related to MMU invalidation of a given
+ * linear address, also have a similar static canonical check on address.
+ * This allows for example to invalidate 5-level addresses of a guest from a
+ * host which uses 4-level paging.
+ */
+static inline bool is_noncanonical_address(u64 la, struct kvm_vcpu *vcpu,
+ unsigned int flags)
+{
+ if (flags & (X86EMUL_F_INVLPG | X86EMUL_F_MSR | X86EMUL_F_DT_LOAD))
+ return !__is_canonical_address(la, max_host_virt_addr_bits());
+ else
+ return !__is_canonical_address(la, vcpu_virt_addr_bits(vcpu));
+}
+
+static inline bool is_noncanonical_msr_address(u64 la, struct kvm_vcpu *vcpu)
+{
+ return is_noncanonical_address(la, vcpu, X86EMUL_F_MSR);
+}
+
+static inline bool is_noncanonical_base_address(u64 la, struct kvm_vcpu *vcpu)
+{
+ return is_noncanonical_address(la, vcpu, X86EMUL_F_DT_LOAD);
+}
+
+static inline bool is_noncanonical_invlpg_address(u64 la, struct kvm_vcpu *vcpu)
+{
+ return is_noncanonical_address(la, vcpu, X86EMUL_F_INVLPG);
}
static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 622fe24da910..a909b817b9c0 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -263,13 +263,6 @@ static void kvm_xen_stop_timer(struct kvm_vcpu *vcpu)
atomic_set(&vcpu->arch.xen.timer_pending, 0);
}
-static void kvm_xen_init_timer(struct kvm_vcpu *vcpu)
-{
- hrtimer_init(&vcpu->arch.xen.timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_ABS_HARD);
- vcpu->arch.xen.timer.function = xen_timer_callback;
-}
-
static void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, bool atomic)
{
struct kvm_vcpu_xen *vx = &v->arch.xen;
@@ -1070,9 +1063,6 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
break;
}
- if (!vcpu->arch.xen.timer.function)
- kvm_xen_init_timer(vcpu);
-
/* Stop the timer (if it's running) before changing the vector */
kvm_xen_stop_timer(vcpu);
vcpu->arch.xen.timer_virq = data->u.timer.port;
@@ -2235,6 +2225,8 @@ void kvm_xen_init_vcpu(struct kvm_vcpu *vcpu)
vcpu->arch.xen.poll_evtchn = 0;
timer_setup(&vcpu->arch.xen.poll_timer, cancel_evtchn_poll, 0);
+ hrtimer_init(&vcpu->arch.xen.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
+ vcpu->arch.xen.timer.function = xen_timer_callback;
kvm_gpc_init(&vcpu->arch.xen.runstate_cache, vcpu->kvm);
kvm_gpc_init(&vcpu->arch.xen.runstate2_cache, vcpu->kvm);
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 807a5859a3c4..58f7f2bd535d 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -19,107 +19,6 @@
#include <asm/tlbflush.h>
#include <asm/elf.h>
-#ifdef CONFIG_HUGETLB_PAGE
-static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
- unsigned long addr, unsigned long len,
- unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
- struct vm_unmapped_area_info info = {};
-
- info.length = len;
- info.low_limit = get_mmap_base(1);
-
- /*
- * If hint address is above DEFAULT_MAP_WINDOW, look for unmapped area
- * in the full address space.
- */
- info.high_limit = in_32bit_syscall() ?
- task_size_32bit() : task_size_64bit(addr > DEFAULT_MAP_WINDOW);
-
- info.align_mask = PAGE_MASK & ~huge_page_mask(h);
- return vm_unmapped_area(&info);
-}
-
-static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
- unsigned long addr, unsigned long len,
- unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
- struct vm_unmapped_area_info info = {};
-
- info.flags = VM_UNMAPPED_AREA_TOPDOWN;
- info.length = len;
- info.low_limit = PAGE_SIZE;
- info.high_limit = get_mmap_base(0);
-
- /*
- * If hint address is above DEFAULT_MAP_WINDOW, look for unmapped area
- * in the full address space.
- */
- if (addr > DEFAULT_MAP_WINDOW && !in_32bit_syscall())
- info.high_limit += TASK_SIZE_MAX - DEFAULT_MAP_WINDOW;
-
- info.align_mask = PAGE_MASK & ~huge_page_mask(h);
- addr = vm_unmapped_area(&info);
-
- /*
- * A failed mmap() very likely causes application failure,
- * so fall back to the bottom-up function here. This scenario
- * can happen with large stack limits and large mmap()
- * allocations.
- */
- if (addr & ~PAGE_MASK) {
- VM_BUG_ON(addr != -ENOMEM);
- info.flags = 0;
- info.low_limit = TASK_UNMAPPED_BASE;
- info.high_limit = TASK_SIZE_LOW;
- addr = vm_unmapped_area(&info);
- }
-
- return addr;
-}
-
-unsigned long
-hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
-{
- struct hstate *h = hstate_file(file);
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
-
- if (len & ~huge_page_mask(h))
- return -EINVAL;
-
- if (len > TASK_SIZE)
- return -ENOMEM;
-
- /* No address checking. See comment at mmap_address_hint_valid() */
- if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(file, addr, len))
- return -EINVAL;
- return addr;
- }
-
- if (addr) {
- addr &= huge_page_mask(h);
- if (!mmap_address_hint_valid(addr, len))
- goto get_unmapped_area;
-
- vma = find_vma(mm, addr);
- if (!vma || addr + len <= vm_start_gap(vma))
- return addr;
- }
-
-get_unmapped_area:
- if (!test_bit(MMF_TOPDOWN, &mm->flags))
- return hugetlb_get_unmapped_area_bottomup(file, addr, len,
- pgoff, flags);
- else
- return hugetlb_get_unmapped_area_topdown(file, addr, len,
- pgoff, flags);
-}
-#endif /* CONFIG_HUGETLB_PAGE */
#ifdef CONFIG_X86_64
bool __init arch_hugetlb_valid_size(unsigned long size)
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index eb503f53c319..c6d29f283001 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -263,28 +263,33 @@ static void __init probe_page_size_mask(void)
}
/*
- * INVLPG may not properly flush Global entries
- * on these CPUs when PCIDs are enabled.
+ * INVLPG may not properly flush Global entries on
+ * these CPUs. New microcode fixes the issue.
*/
static const struct x86_cpu_id invlpg_miss_ids[] = {
- X86_MATCH_VFM(INTEL_ALDERLAKE, 0),
- X86_MATCH_VFM(INTEL_ALDERLAKE_L, 0),
- X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, 0),
- X86_MATCH_VFM(INTEL_RAPTORLAKE, 0),
- X86_MATCH_VFM(INTEL_RAPTORLAKE_P, 0),
- X86_MATCH_VFM(INTEL_RAPTORLAKE_S, 0),
+ X86_MATCH_VFM(INTEL_ALDERLAKE, 0x2e),
+ X86_MATCH_VFM(INTEL_ALDERLAKE_L, 0x42c),
+ X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, 0x11),
+ X86_MATCH_VFM(INTEL_RAPTORLAKE, 0x118),
+ X86_MATCH_VFM(INTEL_RAPTORLAKE_P, 0x4117),
+ X86_MATCH_VFM(INTEL_RAPTORLAKE_S, 0x2e),
{}
};
static void setup_pcid(void)
{
+ const struct x86_cpu_id *invlpg_miss_match;
+
if (!IS_ENABLED(CONFIG_X86_64))
return;
if (!boot_cpu_has(X86_FEATURE_PCID))
return;
- if (x86_match_cpu(invlpg_miss_ids)) {
+ invlpg_miss_match = x86_match_cpu(invlpg_miss_ids);
+
+ if (invlpg_miss_match &&
+ boot_cpu_data.microcode < invlpg_miss_match->driver_data) {
pr_info("Incomplete global flushes, disabling PCID");
setup_clear_cpu_cap(X86_FEATURE_PCID);
return;
@@ -1053,18 +1058,53 @@ unsigned long arch_max_swapfile_size(void)
#ifdef CONFIG_EXECMEM
static struct execmem_info execmem_info __ro_after_init;
+#ifdef CONFIG_ARCH_HAS_EXECMEM_ROX
+void execmem_fill_trapping_insns(void *ptr, size_t size, bool writeable)
+{
+ /* fill memory with INT3 instructions */
+ if (writeable)
+ memset(ptr, INT3_INSN_OPCODE, size);
+ else
+ text_poke_set(ptr, INT3_INSN_OPCODE, size);
+}
+#endif
+
struct execmem_info __init *execmem_arch_setup(void)
{
unsigned long start, offset = 0;
+ enum execmem_range_flags flags;
+ pgprot_t pgprot;
if (kaslr_enabled())
offset = get_random_u32_inclusive(1, 1024) * PAGE_SIZE;
start = MODULES_VADDR + offset;
+ if (IS_ENABLED(CONFIG_ARCH_HAS_EXECMEM_ROX)) {
+ pgprot = PAGE_KERNEL_ROX;
+ flags = EXECMEM_KASAN_SHADOW | EXECMEM_ROX_CACHE;
+ } else {
+ pgprot = PAGE_KERNEL;
+ flags = EXECMEM_KASAN_SHADOW;
+ }
+
execmem_info = (struct execmem_info){
.ranges = {
- [EXECMEM_DEFAULT] = {
+ [EXECMEM_MODULE_TEXT] = {
+ .flags = flags,
+ .start = start,
+ .end = MODULES_END,
+ .pgprot = pgprot,
+ .alignment = MODULE_ALIGN,
+ },
+ [EXECMEM_KPROBES ... EXECMEM_BPF] = {
+ .flags = EXECMEM_KASAN_SHADOW,
+ .start = start,
+ .end = MODULES_END,
+ .pgprot = PAGE_KERNEL,
+ .alignment = MODULE_ALIGN,
+ },
+ [EXECMEM_MODULE_DATA] = {
.flags = EXECMEM_KASAN_SHADOW,
.start = start,
.end = MODULES_END,
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index ff253648706f..01ea7c6df303 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -961,7 +961,7 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
unsigned long end = ((start_pfn + nr_pages) << PAGE_SHIFT) - 1;
int ret;
- if (WARN_ON_ONCE(end > PHYSMEM_END))
+ if (WARN_ON_ONCE(end > DIRECT_MAP_PHYSMEM_END))
return -ERANGE;
ret = __add_pages(nid, start_pfn, nr_pages, params);
@@ -985,22 +985,32 @@ int arch_add_memory(int nid, u64 start, u64 size,
return add_pages(nid, start_pfn, nr_pages, params);
}
-static void __meminit free_pagetable(struct page *page, int order)
+static void free_reserved_pages(struct page *page, unsigned long nr_pages)
{
- unsigned long magic;
- unsigned int nr_pages = 1 << order;
+ while (nr_pages--)
+ free_reserved_page(page++);
+}
+static void __meminit free_pagetable(struct page *page, int order)
+{
/* bootmem page has reserved flag */
if (PageReserved(page)) {
- magic = page->index;
- if (magic == SECTION_INFO || magic == MIX_SECTION_INFO) {
+ unsigned long nr_pages = 1 << order;
+#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
+ enum bootmem_type type = bootmem_type(page);
+
+ if (type == SECTION_INFO || type == MIX_SECTION_INFO) {
while (nr_pages--)
put_page_bootmem(page++);
- } else
- while (nr_pages--)
- free_reserved_page(page++);
- } else
+ } else {
+ free_reserved_pages(page, nr_pages);
+ }
+#else
+ free_reserved_pages(page, nr_pages);
+#endif
+ } else {
free_pages((unsigned long)page_address(page), order);
+ }
}
static void __meminit free_hugepage_table(struct page *page,
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 70b02fc61d93..8d29163568a7 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -656,7 +656,8 @@ static bool memremap_is_setup_data(resource_size_t phys_addr,
paddr_next = data->next;
len = data->len;
- if ((phys_addr > paddr) && (phys_addr < (paddr + len))) {
+ if ((phys_addr > paddr) &&
+ (phys_addr < (paddr + sizeof(struct setup_data) + len))) {
memunmap(data);
return true;
}
@@ -718,7 +719,8 @@ static bool __init early_memremap_is_setup_data(resource_size_t phys_addr,
paddr_next = data->next;
len = data->len;
- if ((phys_addr > paddr) && (phys_addr < (paddr + len))) {
+ if ((phys_addr > paddr) &&
+ (phys_addr < (paddr + sizeof(struct setup_data) + len))) {
early_memunmap(data, sizeof(*data));
return true;
}
diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c
index 230f1dee4f09..11a93542d198 100644
--- a/arch/x86/mm/kaslr.c
+++ b/arch/x86/mm/kaslr.c
@@ -22,7 +22,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include <linux/memblock.h>
#include <linux/pgtable.h>
@@ -52,7 +52,7 @@ static __initdata struct kaslr_memory_region {
} kaslr_regions[] = {
{
.base = &page_offset_base,
- .end = &physmem_end,
+ .end = &direct_map_physmem_end,
},
{
.base = &vmalloc_base,
@@ -62,8 +62,12 @@ static __initdata struct kaslr_memory_region {
},
};
-/* The end of the possible address space for physical memory */
-unsigned long physmem_end __ro_after_init;
+/*
+ * The end of the physical address space that can be mapped directly by the
+ * kernel. This starts out at (1<<MAX_PHYSMEM_BITS) - 1), but KASLR may reduce
+ * that in order to increase the available entropy for mapping other regions.
+ */
+unsigned long direct_map_physmem_end __ro_after_init;
/* Get size in bytes used by the memory region */
static inline unsigned long get_padding(struct kaslr_memory_region *region)
@@ -94,7 +98,7 @@ void __init kernel_randomize_memory(void)
BUILD_BUG_ON(vaddr_end > __START_KERNEL_map);
/* Preset the end of the possible address space for physical memory */
- physmem_end = ((1ULL << MAX_PHYSMEM_BITS) - 1);
+ direct_map_physmem_end = ((1ULL << MAX_PHYSMEM_BITS) - 1);
if (!kaslr_memory_enabled())
return;
@@ -145,7 +149,7 @@ void __init kernel_randomize_memory(void)
vaddr += get_padding(&kaslr_regions[i]);
/*
* KASLR trims the maximum possible size of the
- * direct-map. Update the physmem_end boundary.
+ * direct-map. Update the direct_map_physmem_end boundary.
* No rounding required as the region starts
* PUD aligned and size is in units of TB.
*/
diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
index 86a476a426c2..774f9677458f 100644
--- a/arch/x86/mm/mem_encrypt_amd.c
+++ b/arch/x86/mm/mem_encrypt_amd.c
@@ -311,59 +311,82 @@ static int amd_enc_status_change_finish(unsigned long vaddr, int npages, bool en
return 0;
}
-static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
+int prepare_pte_enc(struct pte_enc_desc *d)
{
- pgprot_t old_prot, new_prot;
- unsigned long pfn, pa, size;
- pte_t new_pte;
+ pgprot_t old_prot;
- pfn = pg_level_to_pfn(level, kpte, &old_prot);
- if (!pfn)
- return;
+ d->pfn = pg_level_to_pfn(d->pte_level, d->kpte, &old_prot);
+ if (!d->pfn)
+ return 1;
- new_prot = old_prot;
- if (enc)
- pgprot_val(new_prot) |= _PAGE_ENC;
+ d->new_pgprot = old_prot;
+ if (d->encrypt)
+ pgprot_val(d->new_pgprot) |= _PAGE_ENC;
else
- pgprot_val(new_prot) &= ~_PAGE_ENC;
+ pgprot_val(d->new_pgprot) &= ~_PAGE_ENC;
/* If prot is same then do nothing. */
- if (pgprot_val(old_prot) == pgprot_val(new_prot))
- return;
+ if (pgprot_val(old_prot) == pgprot_val(d->new_pgprot))
+ return 1;
- pa = pfn << PAGE_SHIFT;
- size = page_level_size(level);
+ d->pa = d->pfn << PAGE_SHIFT;
+ d->size = page_level_size(d->pte_level);
/*
- * We are going to perform in-place en-/decryption and change the
- * physical page attribute from C=1 to C=0 or vice versa. Flush the
- * caches to ensure that data gets accessed with the correct C-bit.
+ * In-place en-/decryption and physical page attribute change
+ * from C=1 to C=0 or vice versa will be performed. Flush the
+ * caches to ensure that data gets accessed with the correct
+ * C-bit.
*/
- clflush_cache_range(__va(pa), size);
+ if (d->va)
+ clflush_cache_range(d->va, d->size);
+ else
+ clflush_cache_range(__va(d->pa), d->size);
+
+ return 0;
+}
+
+void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot)
+{
+ pte_t new_pte;
+
+ /* Change the page encryption mask. */
+ new_pte = pfn_pte(pfn, new_prot);
+ set_pte_atomic(kpte, new_pte);
+}
+
+static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
+{
+ struct pte_enc_desc d = {
+ .kpte = kpte,
+ .pte_level = level,
+ .encrypt = enc
+ };
+
+ if (prepare_pte_enc(&d))
+ return;
/* Encrypt/decrypt the contents in-place */
if (enc) {
- sme_early_encrypt(pa, size);
+ sme_early_encrypt(d.pa, d.size);
} else {
- sme_early_decrypt(pa, size);
+ sme_early_decrypt(d.pa, d.size);
/*
* ON SNP, the page state in the RMP table must happen
* before the page table updates.
*/
- early_snp_set_memory_shared((unsigned long)__va(pa), pa, 1);
+ early_snp_set_memory_shared((unsigned long)__va(d.pa), d.pa, 1);
}
- /* Change the page encryption mask. */
- new_pte = pfn_pte(pfn, new_prot);
- set_pte_atomic(kpte, new_pte);
+ set_pte_enc_mask(kpte, d.pfn, d.new_pgprot);
/*
* If page is set encrypted in the page table, then update the RMP table to
* add this page as private.
*/
if (enc)
- early_snp_set_memory_private((unsigned long)__va(pa), pa, 1);
+ early_snp_set_memory_private((unsigned long)__va(d.pa), d.pa, 1);
}
static int __init early_set_memory_enc_dec(unsigned long vaddr,
@@ -467,6 +490,8 @@ void __init sme_early_init(void)
x86_platform.guest.enc_status_change_finish = amd_enc_status_change_finish;
x86_platform.guest.enc_tlb_flush_required = amd_enc_tlb_flush_required;
x86_platform.guest.enc_cache_flush_required = amd_enc_cache_flush_required;
+ x86_platform.guest.enc_kexec_begin = snp_kexec_begin;
+ x86_platform.guest.enc_kexec_finish = snp_kexec_finish;
/*
* AMD-SEV-ES intercepts the RDMSR to read the X2APIC ID in the
diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
index ac33b2263a43..e6c7686f443a 100644
--- a/arch/x86/mm/mem_encrypt_identity.c
+++ b/arch/x86/mm/mem_encrypt_identity.c
@@ -495,10 +495,10 @@ void __head sme_enable(struct boot_params *bp)
unsigned int eax, ebx, ecx, edx;
unsigned long feature_mask;
unsigned long me_mask;
- bool snp;
+ bool snp_en;
u64 msr;
- snp = snp_init(bp);
+ snp_en = snp_init(bp);
/* Check for the SME/SEV support leaf */
eax = 0x80000000;
@@ -531,8 +531,11 @@ void __head sme_enable(struct boot_params *bp)
RIP_REL_REF(sev_status) = msr = __rdmsr(MSR_AMD64_SEV);
feature_mask = (msr & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
- /* The SEV-SNP CC blob should never be present unless SEV-SNP is enabled. */
- if (snp && !(msr & MSR_AMD64_SEV_SNP_ENABLED))
+ /*
+ * Any discrepancies between the presence of a CC blob and SNP
+ * enablement abort the guest.
+ */
+ if (snp_en ^ !!(msr & MSR_AMD64_SEV_SNP_ENABLED))
snp_abort();
/* Check if memory encryption is enabled */
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index a2cabb1c81e1..b8a6ffffb451 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -163,11 +163,6 @@ unsigned long get_mmap_base(int is_legacy)
return is_legacy ? mm->mmap_legacy_base : mm->mmap_base;
}
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
- return NULL;
-}
-
/**
* mmap_address_hint_valid - Validate the address hint of mmap
* @addr: Address hint
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 44f7b2ea6a07..069e421c2247 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -2444,6 +2444,14 @@ int set_direct_map_default_noflush(struct page *page)
return __set_pages_p(page, 1);
}
+int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
+{
+ if (valid)
+ return __set_pages_p(page, nr);
+
+ return __set_pages_np(page, nr);
+}
+
#ifdef CONFIG_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 86593d1b787d..a2becb85bea7 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -20,6 +20,7 @@
#include <asm/cacheflush.h>
#include <asm/apic.h>
#include <asm/perf_event.h>
+#include <asm/tlb.h>
#include "mm_internal.h"
@@ -568,7 +569,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next,
* mm_cpumask. The TLB shootdown code can figure out from
* cpu_tlbstate_shared.is_lazy whether or not to send an IPI.
*/
- if (WARN_ON_ONCE(prev != &init_mm &&
+ if (IS_ENABLED(CONFIG_DEBUG_VM) && WARN_ON_ONCE(prev != &init_mm &&
!cpumask_test_cpu(cpu, mm_cpumask(next))))
cpumask_set_cpu(cpu, mm_cpumask(next));
@@ -1140,7 +1141,7 @@ STATIC_NOPV void native_flush_tlb_one_user(unsigned long addr)
bool cpu_pcide;
/* Flush 'addr' from the kernel PCID: */
- asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
+ invlpg(addr);
/* If PTI is off there is no user PCID and nothing to flush. */
if (!static_cpu_has(X86_FEATURE_PTI))
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 06b080b61aa5..a43fc5af973d 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -325,6 +325,22 @@ struct jit_context {
/* Number of bytes that will be skipped on tailcall */
#define X86_TAIL_CALL_OFFSET (12 + ENDBR_INSN_SIZE)
+static void push_r9(u8 **pprog)
+{
+ u8 *prog = *pprog;
+
+ EMIT2(0x41, 0x51); /* push r9 */
+ *pprog = prog;
+}
+
+static void pop_r9(u8 **pprog)
+{
+ u8 *prog = *pprog;
+
+ EMIT2(0x41, 0x59); /* pop r9 */
+ *pprog = prog;
+}
+
static void push_r12(u8 **pprog)
{
u8 *prog = *pprog;
@@ -1404,6 +1420,24 @@ static void emit_shiftx(u8 **pprog, u32 dst_reg, u8 src_reg, bool is64, u8 op)
*pprog = prog;
}
+static void emit_priv_frame_ptr(u8 **pprog, void __percpu *priv_frame_ptr)
+{
+ u8 *prog = *pprog;
+
+ /* movabs r9, priv_frame_ptr */
+ emit_mov_imm64(&prog, X86_REG_R9, (__force long) priv_frame_ptr >> 32,
+ (u32) (__force long) priv_frame_ptr);
+
+#ifdef CONFIG_SMP
+ /* add <r9>, gs:[<off>] */
+ EMIT2(0x65, 0x4c);
+ EMIT3(0x03, 0x0c, 0x25);
+ EMIT((u32)(unsigned long)&this_cpu_off, 4);
+#endif
+
+ *pprog = prog;
+}
+
#define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp)))
#define __LOAD_TCC_PTR(off) \
@@ -1412,6 +1446,10 @@ static void emit_shiftx(u8 **pprog, u32 dst_reg, u8 src_reg, bool is64, u8 op)
#define LOAD_TAIL_CALL_CNT_PTR(stack) \
__LOAD_TCC_PTR(BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack))
+/* Memory size/value to protect private stack overflow/underflow */
+#define PRIV_STACK_GUARD_SZ 8
+#define PRIV_STACK_GUARD_VAL 0xEB9F12345678eb9fULL
+
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
int oldproglen, struct jit_context *ctx, bool jmp_padding)
{
@@ -1421,18 +1459,28 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
int insn_cnt = bpf_prog->len;
bool seen_exit = false;
u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY];
+ void __percpu *priv_frame_ptr = NULL;
u64 arena_vm_start, user_vm_start;
+ void __percpu *priv_stack_ptr;
int i, excnt = 0;
int ilen, proglen = 0;
u8 *prog = temp;
+ u32 stack_depth;
int err;
+ stack_depth = bpf_prog->aux->stack_depth;
+ priv_stack_ptr = bpf_prog->aux->priv_stack_ptr;
+ if (priv_stack_ptr) {
+ priv_frame_ptr = priv_stack_ptr + PRIV_STACK_GUARD_SZ + round_up(stack_depth, 8);
+ stack_depth = 0;
+ }
+
arena_vm_start = bpf_arena_get_kern_vm_start(bpf_prog->aux->arena);
user_vm_start = bpf_arena_get_user_vm_start(bpf_prog->aux->arena);
detect_reg_usage(insn, insn_cnt, callee_regs_used);
- emit_prologue(&prog, bpf_prog->aux->stack_depth,
+ emit_prologue(&prog, stack_depth,
bpf_prog_was_classic(bpf_prog), tail_call_reachable,
bpf_is_subprog(bpf_prog), bpf_prog->aux->exception_cb);
/* Exception callback will clobber callee regs for its own use, and
@@ -1454,6 +1502,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
emit_mov_imm64(&prog, X86_REG_R12,
arena_vm_start >> 32, (u32) arena_vm_start);
+ if (priv_frame_ptr)
+ emit_priv_frame_ptr(&prog, priv_frame_ptr);
+
ilen = prog - temp;
if (rw_image)
memcpy(rw_image + proglen, temp, ilen);
@@ -1473,6 +1524,14 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
u8 *func;
int nops;
+ if (priv_frame_ptr) {
+ if (src_reg == BPF_REG_FP)
+ src_reg = X86_REG_R9;
+
+ if (dst_reg == BPF_REG_FP)
+ dst_reg = X86_REG_R9;
+ }
+
switch (insn->code) {
/* ALU */
case BPF_ALU | BPF_ADD | BPF_X:
@@ -2127,15 +2186,21 @@ populate_extable:
u8 *ip = image + addrs[i - 1];
func = (u8 *) __bpf_call_base + imm32;
- if (tail_call_reachable) {
- LOAD_TAIL_CALL_CNT_PTR(bpf_prog->aux->stack_depth);
+ if (src_reg == BPF_PSEUDO_CALL && tail_call_reachable) {
+ LOAD_TAIL_CALL_CNT_PTR(stack_depth);
ip += 7;
}
if (!imm32)
return -EINVAL;
+ if (priv_frame_ptr) {
+ push_r9(&prog);
+ ip += 2;
+ }
ip += x86_call_depth_emit_accounting(&prog, func, ip);
if (emit_call(&prog, func, ip))
return -EINVAL;
+ if (priv_frame_ptr)
+ pop_r9(&prog);
break;
}
@@ -2145,13 +2210,13 @@ populate_extable:
&bpf_prog->aux->poke_tab[imm32 - 1],
&prog, image + addrs[i - 1],
callee_regs_used,
- bpf_prog->aux->stack_depth,
+ stack_depth,
ctx);
else
emit_bpf_tail_call_indirect(bpf_prog,
&prog,
callee_regs_used,
- bpf_prog->aux->stack_depth,
+ stack_depth,
image + addrs[i - 1],
ctx);
break;
@@ -3303,6 +3368,42 @@ int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_func
return emit_bpf_dispatcher(&prog, 0, num_funcs - 1, funcs, image, buf);
}
+static const char *bpf_get_prog_name(struct bpf_prog *prog)
+{
+ if (prog->aux->ksym.prog)
+ return prog->aux->ksym.name;
+ return prog->aux->name;
+}
+
+static void priv_stack_init_guard(void __percpu *priv_stack_ptr, int alloc_size)
+{
+ int cpu, underflow_idx = (alloc_size - PRIV_STACK_GUARD_SZ) >> 3;
+ u64 *stack_ptr;
+
+ for_each_possible_cpu(cpu) {
+ stack_ptr = per_cpu_ptr(priv_stack_ptr, cpu);
+ stack_ptr[0] = PRIV_STACK_GUARD_VAL;
+ stack_ptr[underflow_idx] = PRIV_STACK_GUARD_VAL;
+ }
+}
+
+static void priv_stack_check_guard(void __percpu *priv_stack_ptr, int alloc_size,
+ struct bpf_prog *prog)
+{
+ int cpu, underflow_idx = (alloc_size - PRIV_STACK_GUARD_SZ) >> 3;
+ u64 *stack_ptr;
+
+ for_each_possible_cpu(cpu) {
+ stack_ptr = per_cpu_ptr(priv_stack_ptr, cpu);
+ if (stack_ptr[0] != PRIV_STACK_GUARD_VAL ||
+ stack_ptr[underflow_idx] != PRIV_STACK_GUARD_VAL) {
+ pr_err("BPF private stack overflow/underflow detected for prog %sx\n",
+ bpf_get_prog_name(prog));
+ break;
+ }
+ }
+}
+
struct x64_jit_data {
struct bpf_binary_header *rw_header;
struct bpf_binary_header *header;
@@ -3320,7 +3421,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
struct bpf_binary_header *rw_header = NULL;
struct bpf_binary_header *header = NULL;
struct bpf_prog *tmp, *orig_prog = prog;
+ void __percpu *priv_stack_ptr = NULL;
struct x64_jit_data *jit_data;
+ int priv_stack_alloc_sz;
int proglen, oldproglen = 0;
struct jit_context ctx = {};
bool tmp_blinded = false;
@@ -3356,6 +3459,23 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
}
prog->aux->jit_data = jit_data;
}
+ priv_stack_ptr = prog->aux->priv_stack_ptr;
+ if (!priv_stack_ptr && prog->aux->jits_use_priv_stack) {
+ /* Allocate actual private stack size with verifier-calculated
+ * stack size plus two memory guards to protect overflow and
+ * underflow.
+ */
+ priv_stack_alloc_sz = round_up(prog->aux->stack_depth, 8) +
+ 2 * PRIV_STACK_GUARD_SZ;
+ priv_stack_ptr = __alloc_percpu_gfp(priv_stack_alloc_sz, 8, GFP_KERNEL);
+ if (!priv_stack_ptr) {
+ prog = orig_prog;
+ goto out_priv_stack;
+ }
+
+ priv_stack_init_guard(priv_stack_ptr, priv_stack_alloc_sz);
+ prog->aux->priv_stack_ptr = priv_stack_ptr;
+ }
addrs = jit_data->addrs;
if (addrs) {
ctx = jit_data->ctx;
@@ -3491,6 +3611,11 @@ out_image:
bpf_prog_fill_jited_linfo(prog, addrs + 1);
out_addrs:
kvfree(addrs);
+ if (!image && priv_stack_ptr) {
+ free_percpu(priv_stack_ptr);
+ prog->aux->priv_stack_ptr = NULL;
+ }
+out_priv_stack:
kfree(jit_data);
prog->aux->jit_data = NULL;
}
@@ -3529,6 +3654,8 @@ void bpf_jit_free(struct bpf_prog *prog)
if (prog->jited) {
struct x64_jit_data *jit_data = prog->aux->jit_data;
struct bpf_binary_header *hdr;
+ void __percpu *priv_stack_ptr;
+ int priv_stack_alloc_sz;
/*
* If we fail the final pass of JIT (from jit_subprogs),
@@ -3544,6 +3671,13 @@ void bpf_jit_free(struct bpf_prog *prog)
prog->bpf_func = (void *)prog->bpf_func - cfi_get_offset();
hdr = bpf_jit_binary_pack_hdr(prog);
bpf_jit_binary_pack_free(hdr, NULL);
+ priv_stack_ptr = prog->aux->priv_stack_ptr;
+ if (priv_stack_ptr) {
+ priv_stack_alloc_sz = round_up(prog->aux->stack_depth, 8) +
+ 2 * PRIV_STACK_GUARD_SZ;
+ priv_stack_check_guard(priv_stack_ptr, priv_stack_alloc_sz, prog);
+ free_percpu(prog->aux->priv_stack_ptr);
+ }
WARN_ON_ONCE(!bpf_prog_kallsyms_verify_off(prog));
}
@@ -3559,6 +3693,11 @@ bool bpf_jit_supports_exceptions(void)
return IS_ENABLED(CONFIG_UNWINDER_ORC);
}
+bool bpf_jit_supports_private_stack(void)
+{
+ return true;
+}
+
void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie)
{
#if defined(CONFIG_UNWINDER_ORC)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 55c4b07ec1f6..0c316bae1726 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -250,6 +250,125 @@ void __init pci_acpi_crs_quirks(void)
pr_info("Please notify linux-pci@vger.kernel.org so future kernels can do this automatically\n");
}
+/*
+ * Check if pdev is part of a PCIe switch that is directly below the
+ * specified bridge.
+ */
+static bool pcie_switch_directly_under(struct pci_dev *bridge,
+ struct pci_dev *pdev)
+{
+ struct pci_dev *parent = pci_upstream_bridge(pdev);
+
+ /* If the device doesn't have a parent, it's not under anything */
+ if (!parent)
+ return false;
+
+ /*
+ * If the device has a PCIe type, check if it is below the
+ * corresponding PCIe switch components (if applicable). Then check
+ * if its upstream port is directly beneath the specified bridge.
+ */
+ switch (pci_pcie_type(pdev)) {
+ case PCI_EXP_TYPE_UPSTREAM:
+ return parent == bridge;
+
+ case PCI_EXP_TYPE_DOWNSTREAM:
+ if (pci_pcie_type(parent) != PCI_EXP_TYPE_UPSTREAM)
+ return false;
+ parent = pci_upstream_bridge(parent);
+ return parent == bridge;
+
+ case PCI_EXP_TYPE_ENDPOINT:
+ if (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM)
+ return false;
+ parent = pci_upstream_bridge(parent);
+ if (!parent || pci_pcie_type(parent) != PCI_EXP_TYPE_UPSTREAM)
+ return false;
+ parent = pci_upstream_bridge(parent);
+ return parent == bridge;
+ }
+
+ return false;
+}
+
+static bool pcie_has_usb4_host_interface(struct pci_dev *pdev)
+{
+ struct fwnode_handle *fwnode;
+
+ /*
+ * For USB4, the tunneled PCIe Root or Downstream Ports are marked
+ * with the "usb4-host-interface" ACPI property, so we look for
+ * that first. This should cover most cases.
+ */
+ fwnode = fwnode_find_reference(dev_fwnode(&pdev->dev),
+ "usb4-host-interface", 0);
+ if (!IS_ERR(fwnode)) {
+ fwnode_handle_put(fwnode);
+ return true;
+ }
+
+ /*
+ * Any integrated Thunderbolt 3/4 PCIe Root Ports from Intel
+ * before Alder Lake do not have the "usb4-host-interface"
+ * property so we use their PCI IDs instead. All these are
+ * tunneled. This list is not expected to grow.
+ */
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+ switch (pdev->device) {
+ /* Ice Lake Thunderbolt 3 PCIe Root Ports */
+ case 0x8a1d:
+ case 0x8a1f:
+ case 0x8a21:
+ case 0x8a23:
+ /* Tiger Lake-LP Thunderbolt 4 PCIe Root Ports */
+ case 0x9a23:
+ case 0x9a25:
+ case 0x9a27:
+ case 0x9a29:
+ /* Tiger Lake-H Thunderbolt 4 PCIe Root Ports */
+ case 0x9a2b:
+ case 0x9a2d:
+ case 0x9a2f:
+ case 0x9a31:
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool arch_pci_dev_is_removable(struct pci_dev *pdev)
+{
+ struct pci_dev *parent, *root;
+
+ /* pdev without a parent or Root Port is never tunneled */
+ parent = pci_upstream_bridge(pdev);
+ if (!parent)
+ return false;
+ root = pcie_find_root_port(pdev);
+ if (!root)
+ return false;
+
+ /* Internal PCIe devices are not tunneled */
+ if (!root->external_facing)
+ return false;
+
+ /* Anything directly behind a "usb4-host-interface" is tunneled */
+ if (pcie_has_usb4_host_interface(parent))
+ return true;
+
+ /*
+ * Check if this is a discrete Thunderbolt/USB4 controller that is
+ * directly behind the non-USB4 PCIe Root Port marked as
+ * "ExternalFacingPort". Those are not behind a PCIe tunnel.
+ */
+ if (pcie_switch_directly_under(root, pdev))
+ return false;
+
+ /* PCIe devices after the discrete chip are tunneled */
+ return true;
+}
+
#ifdef CONFIG_PCI_MMCONFIG
static int check_segment(u16 seg, struct device *dev, char *estr)
{
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 98a9bb92d75c..0681ecfe3430 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -757,7 +757,7 @@ static void pci_amd_enable_64bit_bar(struct pci_dev *dev)
dev_info(&dev->dev, "adding root bus resource %pR (tainting kernel)\n",
res);
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
- pci_bus_add_resource(dev->bus, res, 0);
+ pci_bus_add_resource(dev->bus, res);
}
base = ((res->start >> 8) & AMD_141b_MMIO_BASE_MMIOBASE_MASK) |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 88a96816de9a..a7ff189421c3 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -54,14 +54,12 @@
#include <asm/uv/uv.h>
static unsigned long efi_systab_phys __initdata;
-static unsigned long prop_phys = EFI_INVALID_TABLE_ADDR;
static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR;
static unsigned long efi_runtime, efi_nr_tables;
unsigned long efi_fw_vendor, efi_config_table;
static const efi_config_table_type_t arch_tables[] __initconst = {
- {EFI_PROPERTIES_TABLE_GUID, &prop_phys, "PROP" },
{UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" },
#ifdef CONFIG_X86_UV
{UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" },
@@ -82,7 +80,6 @@ static const unsigned long * const efi_tables[] = {
&efi_runtime,
&efi_config_table,
&efi.esrt,
- &prop_phys,
&efi_mem_attr_table,
#ifdef CONFIG_EFI_RCI2_TABLE
&rci2_table_phys,
@@ -502,22 +499,6 @@ void __init efi_init(void)
return;
}
- /* Parse the EFI Properties table if it exists */
- if (prop_phys != EFI_INVALID_TABLE_ADDR) {
- efi_properties_table_t *tbl;
-
- tbl = early_memremap_ro(prop_phys, sizeof(*tbl));
- if (tbl == NULL) {
- pr_err("Could not map Properties table!\n");
- } else {
- if (tbl->memory_protection_attribute &
- EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
- set_bit(EFI_NX_PE_DATA, &efi.flags);
-
- early_memunmap(tbl, sizeof(*tbl));
- }
- }
-
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
efi_clean_memmap();
@@ -784,6 +765,7 @@ static void __init kexec_enter_virtual_mode(void)
efi_sync_low_kernel_mappings();
efi_native_runtime_setup();
+ efi_runtime_update_mappings();
#endif
}
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 91d31ac422d6..ac57259a432b 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -412,51 +412,9 @@ static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *m
void __init efi_runtime_update_mappings(void)
{
- efi_memory_desc_t *md;
-
- /*
- * Use the EFI Memory Attribute Table for mapping permissions if it
- * exists, since it is intended to supersede EFI_PROPERTIES_TABLE.
- */
if (efi_enabled(EFI_MEM_ATTR)) {
efi_disable_ibt_for_runtime = false;
efi_memattr_apply_permissions(NULL, efi_update_mem_attr);
- return;
- }
-
- /*
- * EFI_MEMORY_ATTRIBUTES_TABLE is intended to replace
- * EFI_PROPERTIES_TABLE. So, use EFI_PROPERTIES_TABLE to update
- * permissions only if EFI_MEMORY_ATTRIBUTES_TABLE is not
- * published by the firmware. Even if we find a buggy implementation of
- * EFI_MEMORY_ATTRIBUTES_TABLE, don't fall back to
- * EFI_PROPERTIES_TABLE, because of the same reason.
- */
-
- if (!efi_enabled(EFI_NX_PE_DATA))
- return;
-
- for_each_efi_memory_desc(md) {
- unsigned long pf = 0;
-
- if (!(md->attribute & EFI_MEMORY_RUNTIME))
- continue;
-
- if (!(md->attribute & EFI_MEMORY_WB))
- pf |= _PAGE_PCD;
-
- if ((md->attribute & EFI_MEMORY_XP) ||
- (md->type == EFI_RUNTIME_SERVICES_DATA))
- pf |= _PAGE_NX;
-
- if (!(md->attribute & EFI_MEMORY_RO) &&
- (md->type != EFI_RUNTIME_SERVICES_CODE))
- pf |= _PAGE_RW;
-
- if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
- pf |= _PAGE_ENC;
-
- efi_update_mappings(md, pf);
}
}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index f0cc00032751..846bf49f2508 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -656,8 +656,7 @@ static int qrk_capsule_setup_info(struct capsule_info *cap_info, void **pkbuff,
}
static const struct x86_cpu_id efi_capsule_quirk_ids[] = {
- X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000,
- &qrk_capsule_setup_info),
+ X86_MATCH_VFM(INTEL_QUARK_X1000, &qrk_capsule_setup_info),
{ }
};
diff --git a/arch/x86/platform/intel-mid/pwr.c b/arch/x86/platform/intel-mid/pwr.c
index 27288d8d3f71..cd7e0c71adde 100644
--- a/arch/x86/platform/intel-mid/pwr.c
+++ b/arch/x86/platform/intel-mid/pwr.c
@@ -358,18 +358,18 @@ static int mid_pwr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
}
- ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
- if (ret) {
- dev_err(&pdev->dev, "I/O memory remapping failed\n");
- return ret;
- }
-
pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL);
if (!pwr)
return -ENOMEM;
+ pwr->regs = pcim_iomap_region(pdev, 0, "intel_mid_pwr");
+ ret = PTR_ERR_OR_ZERO(pwr->regs);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not request / ioremap I/O-Mem: %d\n", ret);
+ return ret;
+ }
+
pwr->dev = dev;
- pwr->regs = pcim_iomap_table(pdev)[0];
pwr->irq = pdev->irq;
mutex_init(&pwr->lock);
diff --git a/arch/x86/platform/intel-quark/imr.c b/arch/x86/platform/intel-quark/imr.c
index d3d456925b2a..ee25b032c0b3 100644
--- a/arch/x86/platform/intel-quark/imr.c
+++ b/arch/x86/platform/intel-quark/imr.c
@@ -569,7 +569,7 @@ static void __init imr_fixup_memmap(struct imr_device *idev)
}
static const struct x86_cpu_id imr_ids[] __initconst = {
- X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL),
+ X86_MATCH_VFM(INTEL_QUARK_X1000, NULL),
{}
};
diff --git a/arch/x86/platform/intel-quark/imr_selftest.c b/arch/x86/platform/intel-quark/imr_selftest.c
index 84ba715f44d1..657925b0f428 100644
--- a/arch/x86/platform/intel-quark/imr_selftest.c
+++ b/arch/x86/platform/intel-quark/imr_selftest.c
@@ -105,7 +105,7 @@ static void __init imr_self_test(void)
}
static const struct x86_cpu_id imr_ids[] __initconst = {
- X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL),
+ X86_MATCH_VFM(INTEL_QUARK_X1000, NULL),
{}
};
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c
index c5f3bbdbdcfe..5591a2d9cfe8 100644
--- a/arch/x86/platform/iris/iris.c
+++ b/arch/x86/platform/iris/iris.c
@@ -73,7 +73,7 @@ static struct platform_driver iris_driver = {
.name = "iris",
},
.probe = iris_probe,
- .remove_new = iris_remove,
+ .remove = iris_remove,
};
static struct resource iris_resources[] = {
diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
index 6a9c42de74e7..424eeae12759 100644
--- a/arch/x86/platform/olpc/olpc-xo1-pm.c
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -159,7 +159,7 @@ static struct platform_driver cs5535_pms_driver = {
.name = "cs5535-pms",
},
.probe = xo1_pm_probe,
- .remove_new = xo1_pm_remove,
+ .remove = xo1_pm_remove,
};
static struct platform_driver cs5535_acpi_driver = {
@@ -167,7 +167,7 @@ static struct platform_driver cs5535_acpi_driver = {
.name = "olpc-xo1-pm-acpi",
},
.probe = xo1_pm_probe,
- .remove_new = xo1_pm_remove,
+ .remove = xo1_pm_remove,
};
static int __init xo1_pm_init(void)
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
index 46d42ff6e18a..ccb23c73cbe8 100644
--- a/arch/x86/platform/olpc/olpc-xo1-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -616,7 +616,7 @@ static struct platform_driver xo1_sci_driver = {
.dev_groups = lid_groups,
},
.probe = xo1_sci_probe,
- .remove_new = xo1_sci_remove,
+ .remove = xo1_sci_remove,
.suspend = xo1_sci_suspend,
.resume = xo1_sci_resume,
};
diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
index 64fca49cd88f..4733a5f467b8 100644
--- a/arch/x86/platform/pvh/head.S
+++ b/arch/x86/platform/pvh/head.S
@@ -6,7 +6,9 @@
.code32
.text
+#ifdef CONFIG_X86_32
#define _pa(x) ((x) - __START_KERNEL_map)
+#endif
#define rva(x) ((x) - pvh_start_xen)
#include <linux/elfnote.h>
@@ -52,7 +54,7 @@
#define PVH_CS_SEL (PVH_GDT_ENTRY_CS * 8)
#define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8)
-SYM_CODE_START_LOCAL(pvh_start_xen)
+SYM_CODE_START(pvh_start_xen)
UNWIND_HINT_END_OF_STACK
cld
@@ -72,8 +74,7 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
movl $0, %esp
leal rva(gdt)(%ebp), %eax
- leal rva(gdt_start)(%ebp), %ecx
- movl %ecx, 2(%eax)
+ addl %eax, 2(%eax)
lgdt (%eax)
mov $PVH_DS_SEL,%eax
@@ -103,10 +104,23 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
btsl $_EFER_LME, %eax
wrmsr
+ /*
+ * Reuse the non-relocatable symbol emitted for the ELF note to
+ * subtract the build time physical address of pvh_start_xen() from
+ * its actual runtime address, without relying on absolute 32-bit ELF
+ * relocations, as these are not supported by the linker when running
+ * in -pie mode, and should be avoided in .head.text in general.
+ */
mov %ebp, %ebx
- subl $_pa(pvh_start_xen), %ebx /* offset */
+ subl rva(xen_elfnote_phys32_entry)(%ebp), %ebx
jz .Lpagetable_done
+ /*
+ * Store the resulting load offset in phys_base. __pa() needs
+ * phys_base set to calculate the hypercall page in xen_pvh_init().
+ */
+ movl %ebx, rva(phys_base)(%ebp)
+
/* Fixup page-tables for relocation. */
leal rva(pvh_init_top_pgt)(%ebp), %edi
movl $PTRS_PER_PGD, %ecx
@@ -165,20 +179,12 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
xor %edx, %edx
wrmsr
- /*
- * Calculate load offset and store in phys_base. __pa() needs
- * phys_base set to calculate the hypercall page in xen_pvh_init().
- */
- movq %rbp, %rbx
- subq $_pa(pvh_start_xen), %rbx
- movq %rbx, phys_base(%rip)
- call xen_prepare_pvh
- /*
- * Clear phys_base. __startup_64 will *add* to its value,
- * so reset to 0.
- */
- xor %rbx, %rbx
- movq %rbx, phys_base(%rip)
+ /* Call xen_prepare_pvh() via the kernel virtual mapping */
+ leaq xen_prepare_pvh(%rip), %rax
+ subq phys_base(%rip), %rax
+ addq $__START_KERNEL_map, %rax
+ ANNOTATE_RETPOLINE_SAFE
+ call *%rax
/* startup_64 expects boot_params in %rsi. */
lea pvh_bootparams(%rip), %rsi
@@ -217,8 +223,8 @@ SYM_CODE_END(pvh_start_xen)
.section ".init.data","aw"
.balign 8
SYM_DATA_START_LOCAL(gdt)
- .word gdt_end - gdt_start
- .long _pa(gdt_start) /* x86-64 will overwrite if relocated. */
+ .word gdt_end - gdt_start - 1
+ .long gdt_start - gdt
.word 0
SYM_DATA_END(gdt)
SYM_DATA_START_LOCAL(gdt_start)
@@ -300,5 +306,5 @@ SYM_DATA_END(pvh_level2_kernel_pgt)
.long KERNEL_IMAGE_SIZE - 1)
#endif
- ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY,
- _ASM_PTR (pvh_start_xen - __START_KERNEL_map))
+ ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .global xen_elfnote_phys32_entry;
+ xen_elfnote_phys32_entry: _ASM_PTR xen_elfnote_phys32_entry_value - .)
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index c101bed61940..27441e5863b2 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -56,6 +56,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
[S_ABS] =
"^(xen_irq_disable_direct_reloc$|"
"xen_save_fl_direct_reloc$|"
+ "xen_elfnote_.+_offset$|"
"VDSO|"
"__kcfi_typeid_|"
"__crc_)",
@@ -89,7 +90,6 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
"init_per_cpu__.*|"
"__end_rodata_hpage_align|"
#endif
- "__vvar_page|"
"_end)$"
};
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 186f13268401..986045d5e638 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -10,6 +10,7 @@ config UML_X86
def_bool y
select ARCH_BINFMT_ELF_EXTRA_PHDRS if X86_32
select DCACHE_WORD_ACCESS
+ select HAVE_EFFICIENT_UNALIGNED_ACCESS
config 64BIT
bool "64-bit kernel" if "$(SUBARCH)" = "x86"
@@ -28,17 +29,6 @@ config X86_64
def_bool 64BIT
select MODULES_USE_ELF_RELA
-config 3_LEVEL_PGTABLES
- bool "Three-level pagetables" if !64BIT
- default 64BIT
- help
- Three-level pagetables will let UML have more than 4G of physical
- memory. All the memory that can't be mapped directly will be treated
- as high memory.
-
- However, this it experimental on 32-bit architectures, so if unsure say
- N (on x86-64 it's automatically enabled, instead, as it's safe there).
-
config ARCH_HAS_SC_SIGNALS
def_bool !64BIT
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
index 36e67fc97c22..b42c31cd2390 100644
--- a/arch/x86/um/Makefile
+++ b/arch/x86/um/Makefile
@@ -10,7 +10,7 @@ else
endif
obj-y = bugs_$(BITS).o delay.o fault.o \
- ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
+ ptrace.o ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
stub_segv.o \
sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \
mem_$(BITS).o subarch.o os-Linux/
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
index 6052200fe925..62ed5d68a978 100644
--- a/arch/x86/um/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -8,6 +8,8 @@
#include <asm/user.h>
#include <skas.h>
+#define CORE_DUMP_USE_REGSET
+
#ifdef CONFIG_X86_32
#define R_386_NONE 0
diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h
index 2fef3da55533..2641d28d115c 100644
--- a/arch/x86/um/asm/ptrace.h
+++ b/arch/x86/um/asm/ptrace.h
@@ -2,6 +2,16 @@
#ifndef __UM_X86_PTRACE_H
#define __UM_X86_PTRACE_H
+/* This is here because signal.c needs the REGSET_FP_LEGACY definition */
+enum {
+ REGSET_GENERAL,
+#ifdef CONFIG_X86_32
+ REGSET_FP_LEGACY,
+#endif
+ REGSET_FP,
+ REGSET_XSTATE,
+};
+
#include <linux/compiler.h>
#ifndef CONFIG_X86_32
#define __FRAME_OFFSETS /* Needed to get the R* macros */
diff --git a/arch/x86/um/os-Linux/Makefile b/arch/x86/um/os-Linux/Makefile
index 5249bbc30dcd..77a308aaa5ec 100644
--- a/arch/x86/um/os-Linux/Makefile
+++ b/arch/x86/um/os-Linux/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-y = registers.o task_size.o mcontext.o
+obj-y = registers.o mcontext.o
obj-$(CONFIG_X86_32) += tls.o
diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c
index f3638dd09cec..76eaeb93928c 100644
--- a/arch/x86/um/os-Linux/registers.c
+++ b/arch/x86/um/os-Linux/registers.c
@@ -16,133 +16,58 @@
#include <asm/sigcontext.h>
#include <linux/elf.h>
#include <registers.h>
+#include <sys/mman.h>
-static int have_xstate_support;
+unsigned long host_fp_size;
-int save_i387_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
- return -errno;
- return 0;
-}
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
+int get_fp_registers(int pid, unsigned long *regs)
{
-#ifdef PTRACE_GETREGSET
- struct iovec iov;
+ struct iovec iov = {
+ .iov_base = regs,
+ .iov_len = host_fp_size,
+ };
- if (have_xstate_support) {
- iov.iov_base = fp_regs;
- iov.iov_len = FP_SIZE * sizeof(unsigned long);
- if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
- return -errno;
- return 0;
- } else
-#endif
- return save_i387_registers(pid, fp_regs);
-}
-
-int restore_i387_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
return -errno;
return 0;
}
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-#ifdef PTRACE_SETREGSET
- struct iovec iov;
- if (have_xstate_support) {
- iov.iov_base = fp_regs;
- iov.iov_len = FP_SIZE * sizeof(unsigned long);
- if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
- return -errno;
- return 0;
- } else
-#endif
- return restore_i387_registers(pid, fp_regs);
-}
-
-#ifdef __i386__
-int have_fpx_regs = 1;
-int save_fpx_registers(int pid, unsigned long *fp_regs)
+int put_fp_registers(int pid, unsigned long *regs)
{
- if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
- return -errno;
- return 0;
-}
+ struct iovec iov = {
+ .iov_base = regs,
+ .iov_len = host_fp_size,
+ };
-int restore_fpx_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
return -errno;
return 0;
}
-int get_fp_registers(int pid, unsigned long *regs)
-{
- if (have_fpx_regs)
- return save_fpx_registers(pid, regs);
- else
- return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
- if (have_fpx_regs)
- return restore_fpx_registers(pid, regs);
- else
- return restore_fp_registers(pid, regs);
-}
-
-void arch_init_registers(int pid)
-{
- struct user_fpxregs_struct fpx_regs;
- int err;
-
- err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
- if (!err)
- return;
-
- if (errno != EIO)
- panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
- errno);
-
- have_fpx_regs = 0;
-}
-#else
-
-int get_fp_registers(int pid, unsigned long *regs)
+int arch_init_registers(int pid)
{
- return save_fp_registers(pid, regs);
+ struct iovec iov = {
+ /* Just use plenty of space, it does not cost us anything */
+ .iov_len = 2 * 1024 * 1024,
+ };
+ int ret;
+
+ iov.iov_base = mmap(NULL, iov.iov_len, PROT_WRITE | PROT_READ,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (iov.iov_base == MAP_FAILED)
+ return -ENOMEM;
+
+ /* GDB has x86_xsave_length, which uses x86_cpuid_count */
+ ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov);
+ if (ret)
+ ret = -errno;
+ munmap(iov.iov_base, 2 * 1024 * 1024);
+
+ host_fp_size = iov.iov_len;
+
+ return ret;
}
-int put_fp_registers(int pid, unsigned long *regs)
-{
- return restore_fp_registers(pid, regs);
-}
-
-void arch_init_registers(int pid)
-{
-#ifdef PTRACE_GETREGSET
- void * fp_regs;
- struct iovec iov;
-
- fp_regs = malloc(FP_SIZE * sizeof(unsigned long));
- if(fp_regs == NULL)
- return;
-
- iov.iov_base = fp_regs;
- iov.iov_len = FP_SIZE * sizeof(unsigned long);
- if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
- have_xstate_support = 1;
-
- free(fp_regs);
-#endif
-}
-#endif
-
unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
switch (reg) {
diff --git a/arch/x86/um/os-Linux/task_size.c b/arch/x86/um/os-Linux/task_size.c
deleted file mode 100644
index 1dc9adc20b1c..000000000000
--- a/arch/x86/um/os-Linux/task_size.c
+++ /dev/null
@@ -1,151 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <longjmp.h>
-
-#ifdef __i386__
-
-static jmp_buf buf;
-
-static void segfault(int sig)
-{
- longjmp(buf, 1);
-}
-
-static int page_ok(unsigned long page)
-{
- unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
- unsigned long n = ~0UL;
- void *mapped = NULL;
- int ok = 0;
-
- /*
- * First see if the page is readable. If it is, it may still
- * be a VDSO, so we go on to see if it's writable. If not
- * then try mapping memory there. If that fails, then we're
- * still in the kernel area. As a sanity check, we'll fail if
- * the mmap succeeds, but gives us an address different from
- * what we wanted.
- */
- if (setjmp(buf) == 0)
- n = *address;
- else {
- mapped = mmap(address, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (mapped == MAP_FAILED)
- return 0;
- if (mapped != address)
- goto out;
- }
-
- /*
- * Now, is it writeable? If so, then we're in user address
- * space. If not, then try mprotecting it and try the write
- * again.
- */
- if (setjmp(buf) == 0) {
- *address = n;
- ok = 1;
- goto out;
- } else if (mprotect(address, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE) != 0)
- goto out;
-
- if (setjmp(buf) == 0) {
- *address = n;
- ok = 1;
- }
-
- out:
- if (mapped != NULL)
- munmap(mapped, UM_KERN_PAGE_SIZE);
- return ok;
-}
-
-unsigned long os_get_top_address(void)
-{
- struct sigaction sa, old;
- unsigned long bottom = 0;
- /*
- * A 32-bit UML on a 64-bit host gets confused about the VDSO at
- * 0xffffe000. It is mapped, is readable, can be reprotected writeable
- * and written. However, exec discovers later that it can't be
- * unmapped. So, just set the highest address to be checked to just
- * below it. This might waste some address space on 4G/4G 32-bit
- * hosts, but shouldn't hurt otherwise.
- */
- unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
- unsigned long test, original;
-
- printf("Locating the bottom of the address space ... ");
- fflush(stdout);
-
- /*
- * We're going to be longjmping out of the signal handler, so
- * SA_DEFER needs to be set.
- */
- sa.sa_handler = segfault;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_NODEFER;
- if (sigaction(SIGSEGV, &sa, &old)) {
- perror("os_get_top_address");
- exit(1);
- }
-
- /* Manually scan the address space, bottom-up, until we find
- * the first valid page (or run out of them).
- */
- for (bottom = 0; bottom < top; bottom++) {
- if (page_ok(bottom))
- break;
- }
-
- /* If we've got this far, we ran out of pages. */
- if (bottom == top) {
- fprintf(stderr, "Unable to determine bottom of address "
- "space.\n");
- exit(1);
- }
-
- printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT);
- printf("Locating the top of the address space ... ");
- fflush(stdout);
-
- original = bottom;
-
- /* This could happen with a 4G/4G split */
- if (page_ok(top))
- goto out;
-
- do {
- test = bottom + (top - bottom) / 2;
- if (page_ok(test))
- bottom = test;
- else
- top = test;
- } while (top - bottom > 1);
-
-out:
- /* Restore the old SIGSEGV handling */
- if (sigaction(SIGSEGV, &old, NULL)) {
- perror("os_get_top_address");
- exit(1);
- }
- top <<= UM_KERN_PAGE_SHIFT;
- printf("0x%lx\n", top);
-
- return top;
-}
-
-#else
-
-unsigned long os_get_top_address(void)
-{
- /* The old value of CONFIG_TOP_ADDR */
- return 0x7fc0002000;
-}
-
-#endif
diff --git a/arch/x86/um/ptrace.c b/arch/x86/um/ptrace.c
new file mode 100644
index 000000000000..57c504fd5626
--- /dev/null
+++ b/arch/x86/um/ptrace.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/sched.h>
+#include <linux/elf.h>
+#include <linux/regset.h>
+#include <asm/user32.h>
+#include <asm/sigcontext.h>
+
+#ifdef CONFIG_X86_32
+/*
+ * FPU tag word conversions.
+ */
+
+static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
+{
+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */
+ tmp = ~twd;
+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+ /* and move the valid bits to the lower byte. */
+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+ return tmp;
+}
+
+static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
+{
+ struct _fpxreg *st = NULL;
+ unsigned long twd = (unsigned long) fxsave->twd;
+ unsigned long tag;
+ unsigned long ret = 0xffff0000;
+ int i;
+
+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16)
+
+ for (i = 0; i < 8; i++) {
+ if (twd & 0x1) {
+ st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
+
+ switch (st->exponent & 0x7fff) {
+ case 0x7fff:
+ tag = 2; /* Special */
+ break;
+ case 0x0000:
+ if (!st->significand[0] &&
+ !st->significand[1] &&
+ !st->significand[2] &&
+ !st->significand[3]) {
+ tag = 1; /* Zero */
+ } else {
+ tag = 2; /* Special */
+ }
+ break;
+ default:
+ if (st->significand[3] & 0x8000)
+ tag = 0; /* Valid */
+ else
+ tag = 2; /* Special */
+ break;
+ }
+ } else {
+ tag = 3; /* Empty */
+ }
+ ret |= (tag << (2 * i));
+ twd = twd >> 1;
+ }
+ return ret;
+}
+
+/* Get/set the old 32bit i387 registers (pre-FPX) */
+static int fpregs_legacy_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp;
+ int i;
+
+ membuf_store(&to, (unsigned long)fxsave->cwd | 0xffff0000ul);
+ membuf_store(&to, (unsigned long)fxsave->swd | 0xffff0000ul);
+ membuf_store(&to, twd_fxsr_to_i387(fxsave));
+ membuf_store(&to, fxsave->fip);
+ membuf_store(&to, fxsave->fcs | ((unsigned long)fxsave->fop << 16));
+ membuf_store(&to, fxsave->foo);
+ membuf_store(&to, fxsave->fos);
+
+ for (i = 0; i < 8; i++)
+ membuf_write(&to, (void *)fxsave->st_space + i * 16, 10);
+
+ return 0;
+}
+
+static int fpregs_legacy_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp;
+ const struct user_i387_struct *from;
+ struct user_i387_struct buf;
+ int i;
+
+ if (ubuf) {
+ if (copy_from_user(&buf, ubuf, sizeof(buf)))
+ return -EFAULT;
+ from = &buf;
+ } else {
+ from = kbuf;
+ }
+
+ fxsave->cwd = (unsigned short)(from->cwd & 0xffff);
+ fxsave->swd = (unsigned short)(from->swd & 0xffff);
+ fxsave->twd = twd_i387_to_fxsr((unsigned short)(from->twd & 0xffff));
+ fxsave->fip = from->fip;
+ fxsave->fop = (unsigned short)((from->fcs & 0xffff0000ul) >> 16);
+ fxsave->fcs = (from->fcs & 0xffff);
+ fxsave->foo = from->foo;
+ fxsave->fos = from->fos;
+
+ for (i = 0; i < 8; i++) {
+ memcpy((void *)fxsave->st_space + i * 16,
+ (void *)from->st_space + i * 10, 10);
+ }
+
+ return 0;
+}
+#endif
+
+static int genregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ int reg;
+
+ for (reg = 0; to.left; reg++)
+ membuf_store(&to, getreg(target, reg * sizeof(unsigned long)));
+ return 0;
+}
+
+static int genregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret = 0;
+
+ if (kbuf) {
+ const unsigned long *k = kbuf;
+
+ while (count >= sizeof(*k) && !ret) {
+ ret = putreg(target, pos, *k++);
+ count -= sizeof(*k);
+ pos += sizeof(*k);
+ }
+ } else {
+ const unsigned long __user *u = ubuf;
+
+ while (count >= sizeof(*u) && !ret) {
+ unsigned long word;
+
+ ret = __get_user(word, u++);
+ if (ret)
+ break;
+ ret = putreg(target, pos, word);
+ count -= sizeof(*u);
+ pos += sizeof(*u);
+ }
+ }
+ return ret;
+}
+
+static int generic_fpregs_active(struct task_struct *target, const struct user_regset *regset)
+{
+ return regset->n;
+}
+
+static int generic_fpregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ void *fpregs = task_pt_regs(target)->regs.fp;
+
+ membuf_write(&to, fpregs, regset->size * regset->n);
+ return 0;
+}
+
+static int generic_fpregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ void *fpregs = task_pt_regs(target)->regs.fp;
+
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ fpregs, 0, regset->size * regset->n);
+}
+
+static struct user_regset uml_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
+ },
+#ifdef CONFIG_X86_32
+ /* Old FP registers, they are needed in signal frames */
+ [REGSET_FP_LEGACY] = {
+ .core_note_type = NT_PRFPREG,
+ .n = sizeof(struct user_i387_ia32_struct) / sizeof(long),
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = generic_fpregs_active,
+ .regset_get = fpregs_legacy_get,
+ .set = fpregs_legacy_set,
+ },
+#endif
+ [REGSET_FP] = {
+#ifdef CONFIG_X86_32
+ .core_note_type = NT_PRXFPREG,
+ .n = sizeof(struct user32_fxsr_struct) / sizeof(long),
+#else
+ .core_note_type = NT_PRFPREG,
+ .n = sizeof(struct user_i387_struct) / sizeof(long),
+#endif
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = generic_fpregs_active,
+ .regset_get = generic_fpregs_get,
+ .set = generic_fpregs_set,
+ },
+ [REGSET_XSTATE] = {
+ .core_note_type = NT_X86_XSTATE,
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = generic_fpregs_active,
+ .regset_get = generic_fpregs_get,
+ .set = generic_fpregs_set,
+ },
+ /* TODO: Add TLS regset for 32bit */
+};
+
+static const struct user_regset_view user_uml_view = {
+#ifdef CONFIG_X86_32
+ .name = "i386", .e_machine = EM_386,
+#else
+ .name = "x86_64", .e_machine = EM_X86_64,
+#endif
+ .regsets = uml_regsets, .n = ARRAY_SIZE(uml_regsets)
+};
+
+const struct user_regset_view *
+task_user_regset_view(struct task_struct *tsk)
+{
+ return &user_uml_view;
+}
+
+static int __init init_regset_xstate_info(void)
+{
+ uml_regsets[REGSET_XSTATE].n =
+ host_fp_size / uml_regsets[REGSET_XSTATE].size;
+
+ return 0;
+}
+arch_initcall(init_regset_xstate_info);
diff --git a/arch/x86/um/ptrace_32.c b/arch/x86/um/ptrace_32.c
index b0a71c6cdc6e..3af3cb821524 100644
--- a/arch/x86/um/ptrace_32.c
+++ b/arch/x86/um/ptrace_32.c
@@ -6,6 +6,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
+#include <linux/regset.h>
#include <asm/ptrace-abi.h>
#include <registers.h>
#include <skas.h>
@@ -168,65 +169,6 @@ int peek_user(struct task_struct *child, long addr, long data)
return put_user(tmp, (unsigned long __user *) data);
}
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int err, n, cpu = task_cpu(child);
- struct user_i387_struct fpregs;
-
- err = save_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
- if (err)
- return err;
-
- n = copy_to_user(buf, &fpregs, sizeof(fpregs));
- if(n > 0)
- return -EFAULT;
-
- return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int n, cpu = task_cpu(child);
- struct user_i387_struct fpregs;
-
- n = copy_from_user(&fpregs, buf, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return restore_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
-}
-
-static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
- int err, n, cpu = task_cpu(child);
- struct user_fxsr_struct fpregs;
-
- err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
- if (err)
- return err;
-
- n = copy_to_user(buf, &fpregs, sizeof(fpregs));
- if(n > 0)
- return -EFAULT;
-
- return n;
-}
-
-static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
- int n, cpu = task_cpu(child);
- struct user_fxsr_struct fpregs;
-
- n = copy_from_user(&fpregs, buf, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return restore_fpx_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
-}
-
long subarch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -234,17 +176,25 @@ long subarch_ptrace(struct task_struct *child, long request,
void __user *datap = (void __user *) data;
switch (request) {
case PTRACE_GETFPREGS: /* Get the child FPU state. */
- ret = get_fpregs(datap, child);
- break;
+ return copy_regset_to_user(child, task_user_regset_view(child),
+ REGSET_FP_LEGACY,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_SETFPREGS: /* Set the child FPU state. */
- ret = set_fpregs(datap, child);
- break;
+ return copy_regset_from_user(child, task_user_regset_view(child),
+ REGSET_FP_LEGACY,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_GETFPXREGS: /* Get the child FPU state. */
- ret = get_fpxregs(datap, child);
- break;
+ return copy_regset_to_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_fxsr_struct),
+ datap);
case PTRACE_SETFPXREGS: /* Set the child FPU state. */
- ret = set_fpxregs(datap, child);
- break;
+ return copy_regset_from_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_fxsr_struct),
+ datap);
default:
ret = -EIO;
}
diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c
index aa68d83d3f44..e0d4120a45c8 100644
--- a/arch/x86/um/ptrace_64.c
+++ b/arch/x86/um/ptrace_64.c
@@ -8,6 +8,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/regset.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
#include <linux/uaccess.h>
@@ -188,36 +189,6 @@ int peek_user(struct task_struct *child, long addr, long data)
return put_user(tmp, (unsigned long *) data);
}
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
- struct user_i387_struct fpregs;
-
- err = save_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
- if (err)
- return err;
-
- n = copy_to_user(buf, &fpregs, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int n, cpu = ((struct thread_info *) child->stack)->cpu;
- struct user_i387_struct fpregs;
-
- n = copy_from_user(&fpregs, buf, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return restore_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
-}
-
long subarch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -226,11 +197,15 @@ long subarch_ptrace(struct task_struct *child, long request,
switch (request) {
case PTRACE_GETFPREGS: /* Get the child FPU state. */
- ret = get_fpregs(datap, child);
- break;
+ return copy_regset_to_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_SETFPREGS: /* Set the child FPU state. */
- ret = set_fpregs(datap, child);
- break;
+ return copy_regset_from_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_ARCH_PRCTL:
/* XXX Calls ptrace on the host - needs some SMP thinking */
ret = arch_prctl(child, data, (void __user *) addr);
diff --git a/arch/x86/um/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace.h
index 6ca4ecabc55b..2dd4ca6713f8 100644
--- a/arch/x86/um/shared/sysdep/ptrace.h
+++ b/arch/x86/um/shared/sysdep/ptrace.h
@@ -56,12 +56,16 @@ struct syscall_args {
UPT_SYSCALL_ARG5(r), \
UPT_SYSCALL_ARG6(r) } } )
+extern unsigned long host_fp_size;
+
struct uml_pt_regs {
unsigned long gp[MAX_REG_NR];
- unsigned long fp[MAX_FP_NR];
struct faultinfo faultinfo;
long syscall;
int is_user;
+
+ /* Dynamically sized FP registers (holds an XSTATE) */
+ unsigned long fp[];
};
#define EMPTY_UML_PT_REGS { }
@@ -72,4 +76,6 @@ struct uml_pt_regs {
extern int user_context(unsigned long sp);
+extern int arch_init_registers(int pid);
+
#endif /* __SYSDEP_X86_PTRACE_H */
diff --git a/arch/x86/um/shared/sysdep/ptrace_32.h b/arch/x86/um/shared/sysdep/ptrace_32.h
index 0c4989842fbe..2392470cac4d 100644
--- a/arch/x86/um/shared/sysdep/ptrace_32.h
+++ b/arch/x86/um/shared/sysdep/ptrace_32.h
@@ -6,8 +6,6 @@
#ifndef __SYSDEP_I386_PTRACE_H
#define __SYSDEP_I386_PTRACE_H
-#define MAX_FP_NR HOST_FPX_SIZE
-
#define UPT_SYSCALL_ARG1(r) UPT_BX(r)
#define UPT_SYSCALL_ARG2(r) UPT_CX(r)
#define UPT_SYSCALL_ARG3(r) UPT_DX(r)
@@ -15,6 +13,4 @@
#define UPT_SYSCALL_ARG5(r) UPT_DI(r)
#define UPT_SYSCALL_ARG6(r) UPT_BP(r)
-extern void arch_init_registers(int pid);
-
#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace_64.h b/arch/x86/um/shared/sysdep/ptrace_64.h
index 0dc223aa1c2d..e73573ac871f 100644
--- a/arch/x86/um/shared/sysdep/ptrace_64.h
+++ b/arch/x86/um/shared/sysdep/ptrace_64.h
@@ -8,8 +8,6 @@
#ifndef __SYSDEP_X86_64_PTRACE_H
#define __SYSDEP_X86_64_PTRACE_H
-#define MAX_FP_NR HOST_FP_SIZE
-
#define REGS_R8(r) ((r)[HOST_R8])
#define REGS_R9(r) ((r)[HOST_R9])
#define REGS_R10(r) ((r)[HOST_R10])
@@ -57,6 +55,4 @@
#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
-extern void arch_init_registers(int pid);
-
#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace_user.h b/arch/x86/um/shared/sysdep/ptrace_user.h
index 1d1a824fa652..98da23120538 100644
--- a/arch/x86/um/shared/sysdep/ptrace_user.h
+++ b/arch/x86/um/shared/sysdep/ptrace_user.h
@@ -11,12 +11,6 @@
#define REGS_IP_INDEX HOST_IP
#define REGS_SP_INDEX HOST_SP
-#ifdef __i386__
-#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
-#else
-#define FP_SIZE HOST_FP_SIZE
-#endif
-
/*
* glibc before 2.27 does not include PTRACE_SYSEMU_SINGLESTEP in its enum,
* ensure we have a definition by (re-)defining it here.
diff --git a/arch/x86/um/shared/sysdep/stub_32.h b/arch/x86/um/shared/sysdep/stub_32.h
index 0b44a86dd346..390988132c0a 100644
--- a/arch/x86/um/shared/sysdep/stub_32.h
+++ b/arch/x86/um/shared/sysdep/stub_32.h
@@ -112,11 +112,23 @@ static __always_inline void *get_stub_data(void)
unsigned long ret;
asm volatile (
- "movl %%esp,%0 ;"
- "andl %1,%0"
+ "call _here_%=;"
+ "_here_%=:"
+ "popl %0;"
+ "andl %1, %0 ;"
+ "addl %2, %0 ;"
: "=a" (ret)
- : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)));
+ : "g" (~(UM_KERN_PAGE_SIZE - 1)),
+ "g" (UM_KERN_PAGE_SIZE));
return (void *)ret;
}
+
+#define stub_start(fn) \
+ asm volatile ( \
+ "subl %0,%%esp ;" \
+ "movl %1, %%eax ; " \
+ "call *%%eax ;" \
+ :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE), \
+ "i" (&fn))
#endif
diff --git a/arch/x86/um/shared/sysdep/stub_64.h b/arch/x86/um/shared/sysdep/stub_64.h
index 67f44284f1aa..294affbec742 100644
--- a/arch/x86/um/shared/sysdep/stub_64.h
+++ b/arch/x86/um/shared/sysdep/stub_64.h
@@ -28,6 +28,17 @@ static __always_inline long stub_syscall0(long syscall)
return ret;
}
+static __always_inline long stub_syscall1(long syscall, long arg1)
+{
+ long ret;
+
+ __asm__ volatile (__syscall
+ : "=a" (ret)
+ : "0" (syscall), "D" (arg1) : __syscall_clobber );
+
+ return ret;
+}
+
static __always_inline long stub_syscall2(long syscall, long arg1, long arg2)
{
long ret;
@@ -106,11 +117,21 @@ static __always_inline void *get_stub_data(void)
unsigned long ret;
asm volatile (
- "movq %%rsp,%0 ;"
- "andq %1,%0"
+ "lea 0(%%rip), %0;"
+ "andq %1, %0 ;"
+ "addq %2, %0 ;"
: "=a" (ret)
- : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)));
+ : "g" (~(UM_KERN_PAGE_SIZE - 1)),
+ "g" (UM_KERN_PAGE_SIZE));
return (void *)ret;
}
+
+#define stub_start(fn) \
+ asm volatile ( \
+ "subq %0,%%rsp ;" \
+ "movq %1,%%rax ;" \
+ "call *%%rax ;" \
+ :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE), \
+ "i" (&fn))
#endif
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index 2cc8c2309022..75087e85b6fd 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -16,145 +16,24 @@
#include <registers.h>
#include <skas.h>
-#ifdef CONFIG_X86_32
-
-/*
- * FPU tag word conversions.
- */
-
-static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
-{
- unsigned int tmp; /* to avoid 16 bit prefixes in the code */
-
- /* Transform each pair of bits into 01 (valid) or 00 (empty) */
- tmp = ~twd;
- tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
- /* and move the valid bits to the lower byte. */
- tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
- tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
- tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
- return tmp;
-}
-
-static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
-{
- struct _fpxreg *st = NULL;
- unsigned long twd = (unsigned long) fxsave->twd;
- unsigned long tag;
- unsigned long ret = 0xffff0000;
- int i;
-
-#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16)
-
- for (i = 0; i < 8; i++) {
- if (twd & 0x1) {
- st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
-
- switch (st->exponent & 0x7fff) {
- case 0x7fff:
- tag = 2; /* Special */
- break;
- case 0x0000:
- if ( !st->significand[0] &&
- !st->significand[1] &&
- !st->significand[2] &&
- !st->significand[3] ) {
- tag = 1; /* Zero */
- } else {
- tag = 2; /* Special */
- }
- break;
- default:
- if (st->significand[3] & 0x8000) {
- tag = 0; /* Valid */
- } else {
- tag = 2; /* Special */
- }
- break;
- }
- } else {
- tag = 3; /* Empty */
- }
- ret |= (tag << (2 * i));
- twd = twd >> 1;
- }
- return ret;
-}
-
-static int convert_fxsr_to_user(struct _fpstate __user *buf,
- struct user_fxsr_struct *fxsave)
-{
- unsigned long env[7];
- struct _fpreg __user *to;
- struct _fpxreg *from;
- int i;
-
- env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
- env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
- env[2] = twd_fxsr_to_i387(fxsave);
- env[3] = fxsave->fip;
- env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
- env[5] = fxsave->foo;
- env[6] = fxsave->fos;
-
- if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
- return 1;
-
- to = &buf->_st[0];
- from = (struct _fpxreg *) &fxsave->st_space[0];
- for (i = 0; i < 8; i++, to++, from++) {
- unsigned long __user *t = (unsigned long __user *)to;
- unsigned long *f = (unsigned long *)from;
-
- if (__put_user(*f, t) ||
- __put_user(*(f + 1), t + 1) ||
- __put_user(from->exponent, &to->exponent))
- return 1;
- }
- return 0;
-}
-
-static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
- struct _fpstate __user *buf)
-{
- unsigned long env[7];
- struct _fpxreg *to;
- struct _fpreg __user *from;
- int i;
-
- if (copy_from_user( env, buf, 7 * sizeof(long)))
- return 1;
-
- fxsave->cwd = (unsigned short)(env[0] & 0xffff);
- fxsave->swd = (unsigned short)(env[1] & 0xffff);
- fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
- fxsave->fip = env[3];
- fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
- fxsave->fcs = (env[4] & 0xffff);
- fxsave->foo = env[5];
- fxsave->fos = env[6];
-
- to = (struct _fpxreg *) &fxsave->st_space[0];
- from = &buf->_st[0];
- for (i = 0; i < 8; i++, to++, from++) {
- unsigned long *t = (unsigned long *)to;
- unsigned long __user *f = (unsigned long __user *)from;
-
- if (__get_user(*t, f) ||
- __get_user(*(t + 1), f + 1) ||
- __get_user(to->exponent, &from->exponent))
- return 1;
- }
- return 0;
-}
-
-extern int have_fpx_regs;
+#include <linux/regset.h>
+#include <asm/sigframe.h>
+#ifdef CONFIG_X86_32
+struct _xstate_64 {
+ struct _fpstate_64 fpstate;
+ struct _header xstate_hdr;
+ struct _ymmh_state ymmh;
+ /* New processor state extensions go here: */
+};
+#else
+#define _xstate_64 _xstate
#endif
static int copy_sc_from_user(struct pt_regs *regs,
struct sigcontext __user *from)
{
+ struct _xstate_64 __user *from_fp64;
struct sigcontext sc;
int err;
@@ -203,35 +82,27 @@ static int copy_sc_from_user(struct pt_regs *regs,
#undef GETREG
#ifdef CONFIG_X86_32
- if (have_fpx_regs) {
- struct user_fxsr_struct fpx;
- int pid = userspace_pid[current_thread_info()->cpu];
+ from_fp64 = ((void __user *)sc.fpstate) +
+ offsetof(struct _fpstate_32, _fxsr_env);
+#else
+ from_fp64 = (void __user *)sc.fpstate;
+#endif
- err = copy_from_user(&fpx,
- &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
- sizeof(struct user_fxsr_struct));
- if (err)
- return 1;
+ err = copy_from_user(regs->regs.fp, from_fp64, host_fp_size);
+ if (err)
+ return 1;
- err = convert_fxsr_from_user(&fpx, (void *)sc.fpstate);
- if (err)
- return 1;
-
- err = restore_fpx_registers(pid, (unsigned long *) &fpx);
- if (err < 0) {
- printk(KERN_ERR "copy_sc_from_user - "
- "restore_fpx_registers failed, errno = %d\n",
- -err);
- return 1;
- }
- } else
+#ifdef CONFIG_X86_32
+ /* Data is duplicated and this copy is the important one */
+ err = copy_regset_from_user(current,
+ task_user_regset_view(current),
+ REGSET_FP_LEGACY, 0,
+ sizeof(struct user_i387_struct),
+ (void __user *)sc.fpstate);
+ if (err < 0)
+ return err;
#endif
- {
- err = copy_from_user(regs->regs.fp, (void *)sc.fpstate,
- sizeof(struct _xstate));
- if (err)
- return 1;
- }
+
return 0;
}
@@ -239,6 +110,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
struct _xstate __user *to_fp, struct pt_regs *regs,
unsigned long mask)
{
+ struct _xstate_64 __user *to_fp64;
struct sigcontext sc;
struct faultinfo * fi = &current->thread.arch.faultinfo;
int err;
@@ -290,35 +162,46 @@ static int copy_sc_to_user(struct sigcontext __user *to,
return 1;
#ifdef CONFIG_X86_32
- if (have_fpx_regs) {
- int pid = userspace_pid[current_thread_info()->cpu];
- struct user_fxsr_struct fpx;
-
- err = save_fpx_registers(pid, (unsigned long *) &fpx);
- if (err < 0){
- printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
- "failed, errno = %d\n", err);
- return 1;
- }
-
- err = convert_fxsr_to_user(&to_fp->fpstate, &fpx);
- if (err)
- return 1;
+ err = copy_regset_to_user(current,
+ task_user_regset_view(current),
+ REGSET_FP_LEGACY, 0,
+ sizeof(struct _fpstate_32), to_fp);
+ if (err < 0)
+ return err;
- err |= __put_user(fpx.swd, &to_fp->fpstate.status);
- err |= __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic);
- if (err)
- return 1;
+ __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic);
+
+ BUILD_BUG_ON(offsetof(struct _xstate, xstate_hdr) !=
+ offsetof(struct _xstate_64, xstate_hdr) +
+ offsetof(struct _fpstate_32, _fxsr_env));
+ to_fp64 = (void __user *)to_fp +
+ offsetof(struct _fpstate_32, _fxsr_env);
+#else
+ to_fp64 = to_fp;
+#endif /* CONFIG_X86_32 */
+
+ if (copy_to_user(to_fp64, regs->regs.fp, host_fp_size))
+ return 1;
- if (copy_to_user(&to_fp->fpstate._fxsr_env[0], &fpx,
- sizeof(struct user_fxsr_struct)))
- return 1;
- } else
+ /*
+ * Put magic/size values for userspace. We do not bother to verify them
+ * later on, however, userspace needs them should it try to read the
+ * XSTATE data. And ptrace does not fill in these parts.
+ */
+ BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE);
+#ifdef CONFIG_X86_32
+ __put_user(offsetof(struct _fpstate_32, _fxsr_env) +
+ host_fp_size + FP_XSTATE_MAGIC2_SIZE,
+ &to_fp64->fpstate.sw_reserved.extended_size);
+#else
+ __put_user(host_fp_size + FP_XSTATE_MAGIC2_SIZE,
+ &to_fp64->fpstate.sw_reserved.extended_size);
#endif
- {
- if (copy_to_user(to_fp, regs->regs.fp, sizeof(struct _xstate)))
- return 1;
- }
+ __put_user(host_fp_size, &to_fp64->fpstate.sw_reserved.xstate_size);
+
+ __put_user(FP_XSTATE_MAGIC1, &to_fp64->fpstate.sw_reserved.magic1);
+ __put_user(FP_XSTATE_MAGIC2,
+ (int __user *)((void __user *)to_fp64 + host_fp_size));
return 0;
}
@@ -336,34 +219,15 @@ static int copy_ucontext_to_user(struct ucontext __user *uc,
return err;
}
-struct sigframe
-{
- char __user *pretcode;
- int sig;
- struct sigcontext sc;
- struct _xstate fpstate;
- unsigned long extramask[_NSIG_WORDS-1];
- char retcode[8];
-};
-
-struct rt_sigframe
-{
- char __user *pretcode;
- int sig;
- struct siginfo __user *pinfo;
- void __user *puc;
- struct siginfo info;
- struct ucontext uc;
- struct _xstate fpstate;
- char retcode[8];
-};
-
int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *mask)
{
+ size_t math_size = offsetof(struct _fpstate_32, _fxsr_env) +
+ host_fp_size + FP_XSTATE_MAGIC2_SIZE;
struct sigframe __user *frame;
void __user *restorer;
int err = 0, sig = ksig->sig;
+ unsigned long fp_to;
/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
stack_top = ((stack_top + 4) & -16UL) - 4;
@@ -371,13 +235,21 @@ int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
if (!access_ok(frame, sizeof(*frame)))
return 1;
+ /* Add required space for math frame */
+ frame = (struct sigframe __user *)((unsigned long)frame - math_size);
+
restorer = frame->retcode;
if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ksig->ka.sa.sa_restorer;
- err |= __put_user(restorer, &frame->pretcode);
+ err |= __put_user(restorer, (void __user * __user *)&frame->pretcode);
err |= __put_user(sig, &frame->sig);
- err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]);
+
+ fp_to = (unsigned long)frame + sizeof(*frame);
+
+ err |= copy_sc_to_user(&frame->sc,
+ (struct _xstate __user *)fp_to,
+ regs, mask->sig[0]);
if (_NSIG_WORDS > 1)
err |= __copy_to_user(&frame->extramask, &mask->sig[1],
sizeof(frame->extramask));
@@ -407,26 +279,35 @@ int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *mask)
{
+ size_t math_size = offsetof(struct _fpstate_32, _fxsr_env) +
+ host_fp_size + FP_XSTATE_MAGIC2_SIZE;
struct rt_sigframe __user *frame;
void __user *restorer;
int err = 0, sig = ksig->sig;
+ unsigned long fp_to;
stack_top &= -8UL;
frame = (struct rt_sigframe __user *) stack_top - 1;
if (!access_ok(frame, sizeof(*frame)))
return 1;
+ /* Add required space for math frame */
+ frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size);
+
restorer = frame->retcode;
if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ksig->ka.sa.sa_restorer;
- err |= __put_user(restorer, &frame->pretcode);
+ err |= __put_user(restorer, (void __user * __user *)&frame->pretcode);
err |= __put_user(sig, &frame->sig);
- err |= __put_user(&frame->info, &frame->pinfo);
- err |= __put_user(&frame->uc, &frame->puc);
+ err |= __put_user(&frame->info, (void __user * __user *)&frame->pinfo);
+ err |= __put_user(&frame->uc, (void __user * __user *)&frame->puc);
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
- err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
- PT_REGS_SP(regs));
+
+ fp_to = (unsigned long)frame + sizeof(*frame);
+
+ err |= copy_ucontext_to_user(&frame->uc, (struct _xstate __user *)fp_to,
+ mask, PT_REGS_SP(regs));
/*
* This is movl $,%eax ; int $0x80
@@ -478,27 +359,24 @@ SYSCALL_DEFINE0(sigreturn)
#else
-struct rt_sigframe
-{
- char __user *pretcode;
- struct ucontext uc;
- struct siginfo info;
- struct _xstate fpstate;
-};
-
int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *set)
{
+ unsigned long math_size = host_fp_size + FP_XSTATE_MAGIC2_SIZE;
struct rt_sigframe __user *frame;
int err = 0, sig = ksig->sig;
unsigned long fp_to;
frame = (struct rt_sigframe __user *)
round_down(stack_top - sizeof(struct rt_sigframe), 16);
+
+ /* Add required space for math frame */
+ frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size);
+
/* Subtract 128 for a red zone and 8 for proper alignment */
frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
- if (!access_ok(frame, sizeof(*frame)))
+ if (!access_ok(frame, sizeof(*frame) + math_size))
goto out;
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
@@ -509,12 +387,14 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(NULL, &frame->uc.uc_link);
err |= __save_altstack(&frame->uc.uc_stack, PT_REGS_SP(regs));
- err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
- set->sig[0]);
- fp_to = (unsigned long)&frame->fpstate;
+ fp_to = (unsigned long)frame + sizeof(*frame);
+
+ err |= copy_sc_to_user(&frame->uc.uc_mcontext,
+ (struct _xstate __user *)fp_to,
+ regs, set->sig[0]);
err |= __put_user(fp_to, &frame->uc.uc_mcontext.fpstate);
if (sizeof(*set) == 16) {
@@ -531,7 +411,7 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
*/
/* x86-64 should always use SA_RESTORER. */
if (ksig->ka.sa.sa_flags & SA_RESTORER)
- err |= __put_user((void *)ksig->ka.sa.sa_restorer,
+ err |= __put_user((void __user *)ksig->ka.sa.sa_restorer,
&frame->pretcode);
else
/* could use a vstub here */
diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c
index 1c77d9946199..d6e1cd9956bf 100644
--- a/arch/x86/um/user-offsets.c
+++ b/arch/x86/um/user-offsets.c
@@ -20,9 +20,6 @@ void foo(void);
void foo(void)
{
#ifdef __i386__
- DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
- DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
-
DEFINE(HOST_IP, EIP);
DEFINE(HOST_SP, UESP);
DEFINE(HOST_EFLAGS, EFL);
@@ -41,11 +38,6 @@ void foo(void)
DEFINE(HOST_GS, GS);
DEFINE(HOST_ORIG_AX, ORIG_EAX);
#else
-#ifdef FP_XSTATE_MAGIC1
- DEFINE_LONGS(HOST_FP_SIZE, 2696);
-#else
- DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
-#endif
DEFINE_LONGS(HOST_BX, RBX);
DEFINE_LONGS(HOST_CX, RCX);
DEFINE_LONGS(HOST_DI, RDI);
diff --git a/arch/x86/um/vdso/Makefile b/arch/x86/um/vdso/Makefile
index 6a77ea6434ff..7478d11dacb7 100644
--- a/arch/x86/um/vdso/Makefile
+++ b/arch/x86/um/vdso/Makefile
@@ -56,7 +56,6 @@ CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage
quiet_cmd_vdso = VDSO $@
cmd_vdso = $(CC) -nostdlib -o $@ \
$(CC_FLAGS_LTO) $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
- -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
- sh $(src)/checkundef.sh '$(NM)' '$@'
+ -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^)
-VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack
+VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack -Wl,--no-undefined
diff --git a/arch/x86/um/vdso/checkundef.sh b/arch/x86/um/vdso/checkundef.sh
deleted file mode 100644
index 8e3ea6bb956f..000000000000
--- a/arch/x86/um/vdso/checkundef.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-nm="$1"
-file="$2"
-$nm "$file" | grep '^ *U' > /dev/null 2>&1
-if [ $? -eq 1 ]; then
- exit 0
-else
- echo "$file: undefined symbols found" >&2
- exit 1
-fi
diff --git a/arch/x86/virt/svm/Makefile b/arch/x86/virt/svm/Makefile
index ef2a31bdcc70..eca6d71355fa 100644
--- a/arch/x86/virt/svm/Makefile
+++ b/arch/x86/virt/svm/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_KVM_AMD_SEV) += sev.o
+obj-$(CONFIG_CPU_SUP_AMD) += cmdline.o
diff --git a/arch/x86/virt/svm/cmdline.c b/arch/x86/virt/svm/cmdline.c
new file mode 100644
index 000000000000..affa2759fa20
--- /dev/null
+++ b/arch/x86/virt/svm/cmdline.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD SVM-SEV command line parsing support
+ *
+ * Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc.
+ *
+ * Author: Michael Roth <michael.roth@amd.com>
+ */
+
+#include <linux/string.h>
+#include <linux/printk.h>
+#include <linux/cache.h>
+#include <linux/cpufeature.h>
+
+#include <asm/sev-common.h>
+
+struct sev_config sev_cfg __read_mostly;
+
+static int __init init_sev_config(char *str)
+{
+ char *s;
+
+ while ((s = strsep(&str, ","))) {
+ if (!strcmp(s, "debug")) {
+ sev_cfg.debug = true;
+ continue;
+ }
+
+ if (!strcmp(s, "nosnp")) {
+ if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) {
+ setup_clear_cpu_cap(X86_FEATURE_SEV_SNP);
+ cc_platform_clear(CC_ATTR_HOST_SEV_SNP);
+ continue;
+ } else {
+ goto warn;
+ }
+ }
+
+warn:
+ pr_info("SEV command-line option '%s' was not recognized\n", s);
+ }
+
+ return 1;
+}
+__setup("sev=", init_sev_config);
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 758bcd47b72d..7f6c69dbb816 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -94,7 +94,8 @@ SYM_CODE_END(xen_cpu_bringup_again)
ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR __START_KERNEL_map)
/* Map the p2m table to a 512GB-aligned user address. */
ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M, .quad (PUD_SIZE * PTRS_PER_PUD))
- ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen)
+ ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .globl xen_elfnote_entry;
+ xen_elfnote_entry: _ASM_PTR xen_elfnote_entry_value - .)
ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .ascii "!writable_page_tables")
ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes")
ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
@@ -115,7 +116,8 @@ SYM_CODE_END(xen_cpu_bringup_again)
#else
# define FEATURES_DOM0 0
#endif
- ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
+ ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .globl xen_elfnote_hypercall_page;
+ xen_elfnote_hypercall_page: _ASM_PTR xen_elfnote_hypercall_page_value - .)
ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
.long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0)
ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic")
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index fa07c686cbcc..cc5dba738389 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += parport.h
generic-y += qrwlock.h
generic-y += qspinlock.h
generic-y += user.h
+generic-y += text-patching.h
diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h
index 4db56ef052d2..644413792bf3 100644
--- a/arch/xtensa/include/asm/page.h
+++ b/arch/xtensa/include/asm/page.h
@@ -18,13 +18,7 @@
#include <asm/cache.h>
#include <asm/kmem_layout.h>
-/*
- * PAGE_SHIFT determines the page size
- */
-
-#define PAGE_SHIFT CONFIG_PAGE_SHIFT
-#define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#include <vdso/page.h>
#ifdef CONFIG_MMU
#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
@@ -109,26 +103,8 @@ typedef struct page *pgtable_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/*
- * Pure 2^n version of get_order
- * Use 'nsau' instructions if supported by the processor or the generic version.
- */
-
-#if XCHAL_HAVE_NSA
-
-static inline __attribute_const__ int get_order(unsigned long size)
-{
- int lz;
- asm ("nsau %0, %1" : "=r" (lz) : "r" ((size - 1) >> PAGE_SHIFT));
- return 32 - lz;
-}
-
-#else
-
# include <asm-generic/getorder.h>
-#endif
-
struct page;
struct vm_area_struct;
extern void clear_page(void *page);
@@ -195,7 +171,6 @@ static inline unsigned long ___pa(unsigned long va)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#endif /* __ASSEMBLY__ */
diff --git a/arch/xtensa/include/asm/spinlock_types.h b/arch/xtensa/include/asm/spinlock_types.h
index 797aed7df3dd..6baaeac6248b 100644
--- a/arch/xtensa/include/asm/spinlock_types.h
+++ b/arch/xtensa/include/asm/spinlock_types.h
@@ -3,7 +3,7 @@
#define __ASM_SPINLOCK_TYPES_H
#if !defined(__LINUX_SPINLOCK_TYPES_RAW_H) && !defined(__ASM_SPINLOCK_H)
-# error "please don't include this file directly"
+# error "Please do not include this file directly."
#endif
#include <asm-generic/qspinlock_types.h>
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index 1ff0c858544f..99d4ccee7f6e 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -113,6 +113,9 @@
#define MADV_COLLAPSE 25 /* Synchronous hugepage collapse */
+#define MADV_GUARD_INSTALL 102 /* fatal signal on access to range */
+#define MADV_GUARD_REMOVE 103 /* unguard range */
+
/* compatibility flags */
#define MAP_FILE 0
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index bdec4a773af0..e51f2060e830 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -216,7 +216,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
void __init early_init_devtree(void *params)
{
- early_init_dt_scan(params);
+ early_init_dt_scan(params, __pa(params));
of_scan_flat_dt(xtensa_dt_io_area, NULL);
if (!command_line[0])
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index 67083fc1b2f5..37effc1b134e 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -433,3 +433,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index e831aedb4643..9fb9f3533150 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -736,6 +736,7 @@ static void bfq_sync_bfqq_move(struct bfq_data *bfqd,
*/
bfq_put_cooperator(sync_bfqq);
bic_set_bfqq(bic, NULL, true, act_idx);
+ bfq_release_process_ref(bfqd, sync_bfqq);
}
}
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 0747d9d0e48c..95dd7b795935 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -582,23 +582,31 @@ static struct request *bfq_choose_req(struct bfq_data *bfqd,
#define BFQ_LIMIT_INLINE_DEPTH 16
#ifdef CONFIG_BFQ_GROUP_IOSCHED
-static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
+static bool bfqq_request_over_limit(struct bfq_data *bfqd,
+ struct bfq_io_cq *bic, blk_opf_t opf,
+ unsigned int act_idx, int limit)
{
- struct bfq_data *bfqd = bfqq->bfqd;
- struct bfq_entity *entity = &bfqq->entity;
struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH];
struct bfq_entity **entities = inline_entities;
- int depth, level, alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
- int class_idx = bfqq->ioprio_class - 1;
+ int alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
struct bfq_sched_data *sched_data;
+ struct bfq_entity *entity;
+ struct bfq_queue *bfqq;
unsigned long wsum;
bool ret = false;
-
- if (!entity->on_st_or_in_serv)
- return false;
+ int depth;
+ int level;
retry:
spin_lock_irq(&bfqd->lock);
+ bfqq = bic_to_bfqq(bic, op_is_sync(opf), act_idx);
+ if (!bfqq)
+ goto out;
+
+ entity = &bfqq->entity;
+ if (!entity->on_st_or_in_serv)
+ goto out;
+
/* +1 for bfqq entity, root cgroup not included */
depth = bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css.cgroup->level + 1;
if (depth > alloc_depth) {
@@ -643,7 +651,7 @@ retry:
* class.
*/
wsum = 0;
- for (i = 0; i <= class_idx; i++) {
+ for (i = 0; i <= bfqq->ioprio_class - 1; i++) {
wsum = wsum * IOPRIO_BE_NR +
sched_data->service_tree[i].wsum;
}
@@ -666,7 +674,9 @@ out:
return ret;
}
#else
-static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
+static bool bfqq_request_over_limit(struct bfq_data *bfqd,
+ struct bfq_io_cq *bic, blk_opf_t opf,
+ unsigned int act_idx, int limit)
{
return false;
}
@@ -704,8 +714,9 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
}
for (act_idx = 0; bic && act_idx < bfqd->num_actuators; act_idx++) {
- struct bfq_queue *bfqq =
- bic_to_bfqq(bic, op_is_sync(opf), act_idx);
+ /* Fast path to check if bfqq is already allocated. */
+ if (!bic_to_bfqq(bic, op_is_sync(opf), act_idx))
+ continue;
/*
* Does queue (or any parent entity) exceed number of
@@ -713,7 +724,7 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
* limit depth so that it cannot consume more
* available requests and thus starve other entities.
*/
- if (bfqq && bfqq_request_over_limit(bfqq, limit)) {
+ if (bfqq_request_over_limit(bfqd, bic, opf, act_idx, limit)) {
depth = 1;
break;
}
@@ -5434,8 +5445,6 @@ void bfq_put_cooperator(struct bfq_queue *bfqq)
bfq_put_queue(__bfqq);
__bfqq = next;
}
-
- bfq_release_process_ref(bfqq->bfqd, bfqq);
}
static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
@@ -5448,6 +5457,8 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, bfqq->ref);
bfq_put_cooperator(bfqq);
+
+ bfq_release_process_ref(bfqd, bfqq);
}
static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync,
@@ -6734,6 +6745,8 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq)
bic_set_bfqq(bic, NULL, true, bfqq->actuator_idx);
bfq_put_cooperator(bfqq);
+
+ bfq_release_process_ref(bfqq->bfqd, bfqq);
return NULL;
}
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index 88e3ad73c385..2a4bd6611692 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(bio_integrity_add_page);
static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec,
int nr_vecs, unsigned int len,
- unsigned int direction, u32 seed)
+ unsigned int direction)
{
bool write = direction == ITER_SOURCE;
struct bio_integrity_payload *bip;
@@ -247,7 +247,6 @@ static int bio_integrity_copy_user(struct bio *bio, struct bio_vec *bvec,
}
bip->bip_flags |= BIP_COPY_USER;
- bip->bip_iter.bi_sector = seed;
bip->bip_vcnt = nr_vecs;
return 0;
free_bip:
@@ -258,7 +257,7 @@ free_buf:
}
static int bio_integrity_init_user(struct bio *bio, struct bio_vec *bvec,
- int nr_vecs, unsigned int len, u32 seed)
+ int nr_vecs, unsigned int len)
{
struct bio_integrity_payload *bip;
@@ -267,7 +266,6 @@ static int bio_integrity_init_user(struct bio *bio, struct bio_vec *bvec,
return PTR_ERR(bip);
memcpy(bip->bip_vec, bvec, nr_vecs * sizeof(*bvec));
- bip->bip_iter.bi_sector = seed;
bip->bip_iter.bi_size = len;
bip->bip_vcnt = nr_vecs;
return 0;
@@ -303,8 +301,7 @@ static unsigned int bvec_from_pages(struct bio_vec *bvec, struct page **pages,
return nr_bvecs;
}
-int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t bytes,
- u32 seed)
+int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t bytes)
{
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
unsigned int align = blk_lim_dma_alignment_and_pad(&q->limits);
@@ -350,9 +347,9 @@ int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t bytes,
if (copy)
ret = bio_integrity_copy_user(bio, bvec, nr_bvecs, bytes,
- direction, seed);
+ direction);
else
- ret = bio_integrity_init_user(bio, bvec, nr_bvecs, bytes, seed);
+ ret = bio_integrity_init_user(bio, bvec, nr_bvecs, bytes);
if (ret)
goto release_pages;
if (bvec != stack_vec)
diff --git a/block/bio.c b/block/bio.c
index ac4d77c88932..699a78c85c75 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1065,39 +1065,6 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio,
EXPORT_SYMBOL(bio_add_pc_page);
/**
- * bio_add_zone_append_page - attempt to add page to zone-append bio
- * @bio: destination bio
- * @page: page to add
- * @len: vec entry length
- * @offset: vec entry offset
- *
- * Attempt to add a page to the bio_vec maplist of a bio that will be submitted
- * for a zone-append request. This can fail for a number of reasons, such as the
- * bio being full or the target block device is not a zoned block device or
- * other limitations of the target block device. The target block device must
- * allow bio's up to PAGE_SIZE, so it is always possible to add a single page
- * to an empty bio.
- *
- * Returns: number of bytes added to the bio, or 0 in case of a failure.
- */
-int bio_add_zone_append_page(struct bio *bio, struct page *page,
- unsigned int len, unsigned int offset)
-{
- struct request_queue *q = bdev_get_queue(bio->bi_bdev);
- bool same_page = false;
-
- if (WARN_ON_ONCE(bio_op(bio) != REQ_OP_ZONE_APPEND))
- return 0;
-
- if (WARN_ON_ONCE(!bdev_is_zoned(bio->bi_bdev)))
- return 0;
-
- return bio_add_hw_page(q, bio, page, len, offset,
- queue_max_zone_append_sectors(q), &same_page);
-}
-EXPORT_SYMBOL_GPL(bio_add_zone_append_page);
-
-/**
* __bio_add_page - add page(s) to a bio in a new segment
* @bio: destination bio
* @page: start page to add
@@ -1206,21 +1173,12 @@ EXPORT_SYMBOL_GPL(__bio_release_pages);
void bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
{
- size_t size = iov_iter_count(iter);
-
WARN_ON_ONCE(bio->bi_max_vecs);
- if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
- struct request_queue *q = bdev_get_queue(bio->bi_bdev);
- size_t max_sectors = queue_max_zone_append_sectors(q);
-
- size = min(size, max_sectors << SECTOR_SHIFT);
- }
-
bio->bi_vcnt = iter->nr_segs;
bio->bi_io_vec = (struct bio_vec *)iter->bvec;
bio->bi_iter.bi_bvec_done = iter->iov_offset;
- bio->bi_iter.bi_size = size;
+ bio->bi_iter.bi_size = iov_iter_count(iter);
bio_set_flag(bio, BIO_CLONED);
}
@@ -1245,20 +1203,6 @@ static int bio_iov_add_folio(struct bio *bio, struct folio *folio, size_t len,
return 0;
}
-static int bio_iov_add_zone_append_folio(struct bio *bio, struct folio *folio,
- size_t len, size_t offset)
-{
- struct request_queue *q = bdev_get_queue(bio->bi_bdev);
- bool same_page = false;
-
- if (bio_add_hw_folio(q, bio, folio, len, offset,
- queue_max_zone_append_sectors(q), &same_page) != len)
- return -EINVAL;
- if (same_page && bio_flagged(bio, BIO_PAGE_PINNED))
- unpin_user_folio(folio, 1);
- return 0;
-}
-
static unsigned int get_contig_folio_len(unsigned int *num_pages,
struct page **pages, unsigned int i,
struct folio *folio, size_t left,
@@ -1365,14 +1309,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
len = get_contig_folio_len(&num_pages, pages, i,
folio, left, offset);
- if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
- ret = bio_iov_add_zone_append_folio(bio, folio, len,
- folio_offset);
- if (ret)
- break;
- } else
- bio_iov_add_folio(bio, folio, len, folio_offset);
-
+ bio_iov_add_folio(bio, folio, len, folio_offset);
offset = 0;
}
@@ -1728,16 +1665,22 @@ struct bio *bio_split(struct bio *bio, int sectors,
{
struct bio *split;
- BUG_ON(sectors <= 0);
- BUG_ON(sectors >= bio_sectors(bio));
+ if (WARN_ON_ONCE(sectors <= 0))
+ return ERR_PTR(-EINVAL);
+ if (WARN_ON_ONCE(sectors >= bio_sectors(bio)))
+ return ERR_PTR(-EINVAL);
/* Zone append commands cannot be split */
if (WARN_ON_ONCE(bio_op(bio) == REQ_OP_ZONE_APPEND))
- return NULL;
+ return ERR_PTR(-EINVAL);
+
+ /* atomic writes cannot be split */
+ if (bio->bi_opf & REQ_ATOMIC)
+ return ERR_PTR(-EINVAL);
split = bio_alloc_clone(bio->bi_bdev, bio, gfp, bs);
if (!split)
- return NULL;
+ return ERR_PTR(-ENOMEM);
split->bi_iter.bi_size = sectors << 9;
diff --git a/block/blk-core.c b/block/blk-core.c
index bc5e8c5eaac9..666efe8fa202 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -261,6 +261,8 @@ static void blk_free_queue(struct request_queue *q)
blk_mq_release(q);
ida_free(&blk_queue_ida, q->id);
+ lockdep_unregister_key(&q->io_lock_cls_key);
+ lockdep_unregister_key(&q->q_lock_cls_key);
call_rcu(&q->rcu_head, blk_free_queue_rcu);
}
@@ -278,18 +280,20 @@ void blk_put_queue(struct request_queue *q)
}
EXPORT_SYMBOL(blk_put_queue);
-void blk_queue_start_drain(struct request_queue *q)
+bool blk_queue_start_drain(struct request_queue *q)
{
/*
* When queue DYING flag is set, we need to block new req
* entering queue, so we call blk_freeze_queue_start() to
* prevent I/O from crossing blk_queue_enter().
*/
- blk_freeze_queue_start(q);
+ bool freeze = __blk_freeze_queue_start(q, current);
if (queue_is_mq(q))
blk_mq_wake_waiters(q);
/* Make blk_queue_enter() reexamine the DYING flag. */
wake_up_all(&q->mq_freeze_wq);
+
+ return freeze;
}
/**
@@ -321,6 +325,8 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
return -ENODEV;
}
+ rwsem_acquire_read(&q->q_lockdep_map, 0, 0, _RET_IP_);
+ rwsem_release(&q->q_lockdep_map, _RET_IP_);
return 0;
}
@@ -352,6 +358,8 @@ int __bio_queue_enter(struct request_queue *q, struct bio *bio)
goto dead;
}
+ rwsem_acquire_read(&q->io_lockdep_map, 0, 0, _RET_IP_);
+ rwsem_release(&q->io_lockdep_map, _RET_IP_);
return 0;
dead:
bio_io_error(bio);
@@ -441,6 +449,12 @@ struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id)
PERCPU_REF_INIT_ATOMIC, GFP_KERNEL);
if (error)
goto fail_stats;
+ lockdep_register_key(&q->io_lock_cls_key);
+ lockdep_register_key(&q->q_lock_cls_key);
+ lockdep_init_map(&q->io_lockdep_map, "&q->q_usage_counter(io)",
+ &q->io_lock_cls_key, 0);
+ lockdep_init_map(&q->q_lockdep_map, "&q->q_usage_counter(queue)",
+ &q->q_lock_cls_key, 0);
q->nr_requests = BLKDEV_DEFAULT_RQ;
@@ -593,7 +607,7 @@ static inline blk_status_t blk_check_zone_append(struct request_queue *q,
return BLK_STS_IOERR;
/* Make sure the BIO is small enough and will not get split */
- if (nr_sectors > queue_max_zone_append_sectors(q))
+ if (nr_sectors > q->limits.max_zone_append_sectors)
return BLK_STS_IOERR;
bio->bi_opf |= REQ_NOMERGE;
@@ -1106,8 +1120,8 @@ void blk_start_plug_nr_ios(struct blk_plug *plug, unsigned short nr_ios)
return;
plug->cur_ktime = 0;
- plug->mq_list = NULL;
- plug->cached_rq = NULL;
+ rq_list_init(&plug->mq_list);
+ rq_list_init(&plug->cached_rqs);
plug->nr_ios = min_t(unsigned short, nr_ios, BLK_MAX_REQUEST_COUNT);
plug->rq_count = 0;
plug->multiple_queues = false;
@@ -1203,7 +1217,7 @@ void __blk_flush_plug(struct blk_plug *plug, bool from_schedule)
* queue for cached requests, we don't want a blocked task holding
* up a queue freeze/quiesce event.
*/
- if (unlikely(!rq_list_empty(plug->cached_rq)))
+ if (unlikely(!rq_list_empty(&plug->cached_rqs)))
blk_mq_free_plug_rqs(plug);
plug->cur_ktime = 0;
diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c
index b1e7415f8439..29a205482617 100644
--- a/block/blk-crypto-fallback.c
+++ b/block/blk-crypto-fallback.c
@@ -226,7 +226,7 @@ static bool blk_crypto_fallback_split_bio_if_needed(struct bio **bio_ptr)
split_bio = bio_split(bio, num_sectors, GFP_NOIO,
&crypto_bio_split);
- if (!split_bio) {
+ if (IS_ERR(split_bio)) {
bio->bi_status = BLK_STS_RESOURCE;
return false;
}
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 83b696ba0cac..b180cac61a9d 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -113,9 +113,9 @@ new_segment:
EXPORT_SYMBOL(blk_rq_map_integrity_sg);
int blk_rq_integrity_map_user(struct request *rq, void __user *ubuf,
- ssize_t bytes, u32 seed)
+ ssize_t bytes)
{
- int ret = bio_integrity_map_user(rq->bio, ubuf, bytes, seed);
+ int ret = bio_integrity_map_user(rq->bio, ubuf, bytes);
if (ret)
return ret;
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 25dd4db11121..ce82770c72ab 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -32,13 +32,6 @@ static void get_io_context(struct io_context *ioc)
atomic_long_inc(&ioc->refcount);
}
-static void icq_free_icq_rcu(struct rcu_head *head)
-{
- struct io_cq *icq = container_of(head, struct io_cq, __rcu_head);
-
- kmem_cache_free(icq->__rcu_icq_cache, icq);
-}
-
/*
* Exit an icq. Called with ioc locked for blk-mq, and with both ioc
* and queue locked for legacy.
@@ -102,7 +95,7 @@ static void ioc_destroy_icq(struct io_cq *icq)
*/
icq->__rcu_icq_cache = et->icq_cache;
icq->flags |= ICQ_DESTROYED;
- call_rcu(&icq->__rcu_head, icq_free_icq_rcu);
+ kfree_rcu(icq, __rcu_head);
}
/*
diff --git a/block/blk-merge.c b/block/blk-merge.c
index ad763ec313b6..e01383c6e534 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -107,17 +107,18 @@ static unsigned int bio_allowed_max_sectors(const struct queue_limits *lim)
static struct bio *bio_submit_split(struct bio *bio, int split_sectors)
{
- if (unlikely(split_sectors < 0)) {
- bio->bi_status = errno_to_blk_status(split_sectors);
- bio_endio(bio);
- return NULL;
- }
+ if (unlikely(split_sectors < 0))
+ goto error;
if (split_sectors) {
struct bio *split;
split = bio_split(bio, split_sectors, GFP_NOIO,
&bio->bi_bdev->bd_disk->bio_split);
+ if (IS_ERR(split)) {
+ split_sectors = PTR_ERR(split);
+ goto error;
+ }
split->bi_opf |= REQ_NOMERGE;
blkcg_bio_issue_init(split);
bio_chain(split, bio);
@@ -128,6 +129,10 @@ static struct bio *bio_submit_split(struct bio *bio, int split_sectors)
}
return bio;
+error:
+ bio->bi_status = errno_to_blk_status(split_sectors);
+ bio_endio(bio);
+ return NULL;
}
struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim,
@@ -166,17 +171,6 @@ struct bio *bio_split_discard(struct bio *bio, const struct queue_limits *lim,
return bio_submit_split(bio, split_sectors);
}
-struct bio *bio_split_write_zeroes(struct bio *bio,
- const struct queue_limits *lim, unsigned *nsegs)
-{
- *nsegs = 0;
- if (!lim->max_write_zeroes_sectors)
- return bio;
- if (bio_sectors(bio) <= lim->max_write_zeroes_sectors)
- return bio;
- return bio_submit_split(bio, lim->max_write_zeroes_sectors);
-}
-
static inline unsigned int blk_boundary_sectors(const struct queue_limits *lim,
bool is_atomic)
{
@@ -211,7 +205,9 @@ static inline unsigned get_max_io_size(struct bio *bio,
* We ignore lim->max_sectors for atomic writes because it may less
* than the actual bio size, which we cannot tolerate.
*/
- if (is_atomic)
+ if (bio_op(bio) == REQ_OP_WRITE_ZEROES)
+ max_sectors = lim->max_write_zeroes_sectors;
+ else if (is_atomic)
max_sectors = lim->atomic_write_max_sectors;
else
max_sectors = lim->max_sectors;
@@ -296,6 +292,14 @@ static bool bvec_split_segs(const struct queue_limits *lim,
return len > 0 || bv->bv_len > max_len;
}
+static unsigned int bio_split_alignment(struct bio *bio,
+ const struct queue_limits *lim)
+{
+ if (op_is_write(bio_op(bio)) && lim->zone_write_granularity)
+ return lim->zone_write_granularity;
+ return lim->logical_block_size;
+}
+
/**
* bio_split_rw_at - check if and where to split a read/write bio
* @bio: [in] bio to be split
@@ -358,7 +362,7 @@ split:
* split size so that each bio is properly block size aligned, even if
* we do not use the full hardware limits.
*/
- bytes = ALIGN_DOWN(bytes, lim->logical_block_size);
+ bytes = ALIGN_DOWN(bytes, bio_split_alignment(bio, lim));
/*
* Bio splitting may cause subtle trouble such as hang when doing sync
@@ -388,16 +392,35 @@ struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
struct bio *bio_split_zone_append(struct bio *bio,
const struct queue_limits *lim, unsigned *nr_segs)
{
- unsigned int max_sectors = queue_limits_max_zone_append_sectors(lim);
int split_sectors;
split_sectors = bio_split_rw_at(bio, lim, nr_segs,
- max_sectors << SECTOR_SHIFT);
+ lim->max_zone_append_sectors << SECTOR_SHIFT);
if (WARN_ON_ONCE(split_sectors > 0))
split_sectors = -EINVAL;
return bio_submit_split(bio, split_sectors);
}
+struct bio *bio_split_write_zeroes(struct bio *bio,
+ const struct queue_limits *lim, unsigned *nsegs)
+{
+ unsigned int max_sectors = get_max_io_size(bio, lim);
+
+ *nsegs = 0;
+
+ /*
+ * An unset limit should normally not happen, as bio submission is keyed
+ * off having a non-zero limit. But SCSI can clear the limit in the
+ * I/O completion handler, and we can race and see this. Splitting to a
+ * zero limit obviously doesn't make sense, so band-aid it here.
+ */
+ if (!max_sectors)
+ return bio;
+ if (bio_sectors(bio) <= max_sectors)
+ return bio;
+ return bio_submit_split(bio, max_sectors);
+}
+
/**
* bio_split_to_limits - split a bio to fit the queue limits
* @bio: bio to be split
@@ -411,10 +434,9 @@ struct bio *bio_split_zone_append(struct bio *bio,
*/
struct bio *bio_split_to_limits(struct bio *bio)
{
- const struct queue_limits *lim = &bdev_get_queue(bio->bi_bdev)->limits;
unsigned int nr_segs;
- return __bio_split_to_limits(bio, lim, &nr_segs);
+ return __bio_split_to_limits(bio, bdev_limits(bio->bi_bdev), &nr_segs);
}
EXPORT_SYMBOL(bio_split_to_limits);
@@ -797,7 +819,7 @@ static inline void blk_update_mixed_merge(struct request *req,
static void blk_account_io_merge_request(struct request *req)
{
- if (blk_do_io_stat(req)) {
+ if (req->rq_flags & RQF_IO_STAT) {
part_stat_lock();
part_stat_inc(req->part, merges[op_stat_group(req_op(req))]);
part_stat_local_dec(req->part,
@@ -842,16 +864,10 @@ static struct request *attempt_merge(struct request_queue *q,
if (req_op(req) != req_op(next))
return NULL;
- if (rq_data_dir(req) != rq_data_dir(next))
+ if (req->bio->bi_write_hint != next->bio->bi_write_hint)
return NULL;
-
- /* Don't merge requests with different write hints. */
- if (req->write_hint != next->write_hint)
+ if (req->bio->bi_ioprio != next->bio->bi_ioprio)
return NULL;
-
- if (req->ioprio != next->ioprio)
- return NULL;
-
if (!blk_atomic_write_mergeable_rqs(req, next))
return NULL;
@@ -963,29 +979,16 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
if (req_op(rq) != bio_op(bio))
return false;
- /* different data direction or already started, don't merge */
- if (bio_data_dir(bio) != rq_data_dir(rq))
- return false;
-
- /* don't merge across cgroup boundaries */
if (!blk_cgroup_mergeable(rq, bio))
return false;
-
- /* only merge integrity protected bio into ditto rq */
if (blk_integrity_merge_bio(rq->q, rq, bio) == false)
return false;
-
- /* Only merge if the crypt contexts are compatible */
if (!bio_crypt_rq_ctx_compatible(rq, bio))
return false;
-
- /* Don't merge requests with different write hints. */
- if (rq->write_hint != bio->bi_write_hint)
+ if (rq->bio->bi_write_hint != bio->bi_write_hint)
return false;
-
- if (rq->ioprio != bio_prio(bio))
+ if (rq->bio->bi_ioprio != bio->bi_ioprio)
return false;
-
if (blk_atomic_write_mergeable_rq_bio(rq, bio) == false)
return false;
@@ -1005,12 +1008,11 @@ enum elv_merge blk_try_merge(struct request *rq, struct bio *bio)
static void blk_account_io_merge_bio(struct request *req)
{
- if (!blk_do_io_stat(req))
- return;
-
- part_stat_lock();
- part_stat_inc(req->part, merges[op_stat_group(req_op(req))]);
- part_stat_unlock();
+ if (req->rq_flags & RQF_IO_STAT) {
+ part_stat_lock();
+ part_stat_inc(req->part, merges[op_stat_group(req_op(req))]);
+ part_stat_unlock();
+ }
}
enum bio_merge_status bio_attempt_back_merge(struct request *req,
@@ -1156,7 +1158,7 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
struct blk_plug *plug = current->plug;
struct request *rq;
- if (!plug || rq_list_empty(plug->mq_list))
+ if (!plug || rq_list_empty(&plug->mq_list))
return false;
rq_list_for_each(&plug->mq_list, rq) {
diff --git a/block/blk-mq.c b/block/blk-mq.c
index cf626e061dd7..424239c075e2 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -92,7 +92,7 @@ static bool blk_mq_check_inflight(struct request *rq, void *priv)
{
struct mq_inflight *mi = priv;
- if (rq->part && blk_do_io_stat(rq) &&
+ if (rq->rq_flags & RQF_IO_STAT &&
(!bdev_is_partition(mi->part) || rq->part == mi->part) &&
blk_mq_rq_state(rq) == MQ_RQ_IN_FLIGHT)
mi->inflight[rq_data_dir(rq)]++;
@@ -120,9 +120,59 @@ void blk_mq_in_flight_rw(struct request_queue *q, struct block_device *part,
inflight[1] = mi.inflight[1];
}
-void blk_freeze_queue_start(struct request_queue *q)
+#ifdef CONFIG_LOCKDEP
+static bool blk_freeze_set_owner(struct request_queue *q,
+ struct task_struct *owner)
+{
+ if (!owner)
+ return false;
+
+ if (!q->mq_freeze_depth) {
+ q->mq_freeze_owner = owner;
+ q->mq_freeze_owner_depth = 1;
+ return true;
+ }
+
+ if (owner == q->mq_freeze_owner)
+ q->mq_freeze_owner_depth += 1;
+ return false;
+}
+
+/* verify the last unfreeze in owner context */
+static bool blk_unfreeze_check_owner(struct request_queue *q)
{
+ if (!q->mq_freeze_owner)
+ return false;
+ if (q->mq_freeze_owner != current)
+ return false;
+ if (--q->mq_freeze_owner_depth == 0) {
+ q->mq_freeze_owner = NULL;
+ return true;
+ }
+ return false;
+}
+
+#else
+
+static bool blk_freeze_set_owner(struct request_queue *q,
+ struct task_struct *owner)
+{
+ return false;
+}
+
+static bool blk_unfreeze_check_owner(struct request_queue *q)
+{
+ return false;
+}
+#endif
+
+bool __blk_freeze_queue_start(struct request_queue *q,
+ struct task_struct *owner)
+{
+ bool freeze;
+
mutex_lock(&q->mq_freeze_lock);
+ freeze = blk_freeze_set_owner(q, owner);
if (++q->mq_freeze_depth == 1) {
percpu_ref_kill(&q->q_usage_counter);
mutex_unlock(&q->mq_freeze_lock);
@@ -131,6 +181,14 @@ void blk_freeze_queue_start(struct request_queue *q)
} else {
mutex_unlock(&q->mq_freeze_lock);
}
+
+ return freeze;
+}
+
+void blk_freeze_queue_start(struct request_queue *q)
+{
+ if (__blk_freeze_queue_start(q, current))
+ blk_freeze_acquire_lock(q, false, false);
}
EXPORT_SYMBOL_GPL(blk_freeze_queue_start);
@@ -149,35 +207,17 @@ int blk_mq_freeze_queue_wait_timeout(struct request_queue *q,
}
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue_wait_timeout);
-/*
- * Guarantee no request is in use, so we can change any data structure of
- * the queue afterward.
- */
-void blk_freeze_queue(struct request_queue *q)
+void blk_mq_freeze_queue(struct request_queue *q)
{
- /*
- * In the !blk_mq case we are only calling this to kill the
- * q_usage_counter, otherwise this increases the freeze depth
- * and waits for it to return to zero. For this reason there is
- * no blk_unfreeze_queue(), and blk_freeze_queue() is not
- * exported to drivers as the only user for unfreeze is blk_mq.
- */
blk_freeze_queue_start(q);
blk_mq_freeze_queue_wait(q);
}
-
-void blk_mq_freeze_queue(struct request_queue *q)
-{
- /*
- * ...just an alias to keep freeze and unfreeze actions balanced
- * in the blk_mq_* namespace
- */
- blk_freeze_queue(q);
-}
EXPORT_SYMBOL_GPL(blk_mq_freeze_queue);
-void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)
+bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)
{
+ bool unfreeze;
+
mutex_lock(&q->mq_freeze_lock);
if (force_atomic)
q->q_usage_counter.data->force_atomic = true;
@@ -187,16 +227,40 @@ void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic)
percpu_ref_resurrect(&q->q_usage_counter);
wake_up_all(&q->mq_freeze_wq);
}
+ unfreeze = blk_unfreeze_check_owner(q);
mutex_unlock(&q->mq_freeze_lock);
+
+ return unfreeze;
}
void blk_mq_unfreeze_queue(struct request_queue *q)
{
- __blk_mq_unfreeze_queue(q, false);
+ if (__blk_mq_unfreeze_queue(q, false))
+ blk_unfreeze_release_lock(q, false, false);
}
EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);
/*
+ * non_owner variant of blk_freeze_queue_start
+ *
+ * Unlike blk_freeze_queue_start, the queue doesn't need to be unfrozen
+ * by the same task. This is fragile and should not be used if at all
+ * possible.
+ */
+void blk_freeze_queue_start_non_owner(struct request_queue *q)
+{
+ __blk_freeze_queue_start(q, NULL);
+}
+EXPORT_SYMBOL_GPL(blk_freeze_queue_start_non_owner);
+
+/* non_owner variant of blk_mq_unfreeze_queue */
+void blk_mq_unfreeze_queue_non_owner(struct request_queue *q)
+{
+ __blk_mq_unfreeze_queue(q, false);
+}
+EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue_non_owner);
+
+/*
* FIXME: replace the scsi_internal_device_*block_nowait() calls in the
* mpt3sas driver such that this function can be removed.
*/
@@ -283,8 +347,9 @@ void blk_mq_quiesce_tagset(struct blk_mq_tag_set *set)
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);
+
+ blk_mq_wait_quiesce_done(set);
}
EXPORT_SYMBOL_GPL(blk_mq_quiesce_tagset);
@@ -323,7 +388,6 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
rq->tag = BLK_MQ_NO_TAG;
rq->internal_tag = BLK_MQ_NO_TAG;
rq->start_time_ns = blk_time_get_ns();
- rq->part = NULL;
blk_crypto_rq_set_defaults(rq);
}
EXPORT_SYMBOL(blk_rq_init);
@@ -331,14 +395,9 @@ EXPORT_SYMBOL(blk_rq_init);
/* Set start and alloc time when the allocated request is actually used */
static inline void blk_mq_rq_time_init(struct request *rq, u64 alloc_time_ns)
{
- if (blk_mq_need_time_stamp(rq))
- rq->start_time_ns = blk_time_get_ns();
- else
- rq->start_time_ns = 0;
-
#ifdef CONFIG_BLK_RQ_ALLOC_TIME
if (blk_queue_rq_alloc_time(rq->q))
- rq->alloc_time_ns = alloc_time_ns ?: rq->start_time_ns;
+ rq->alloc_time_ns = alloc_time_ns;
else
rq->alloc_time_ns = 0;
#endif
@@ -359,8 +418,6 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
if (data->flags & BLK_MQ_REQ_PM)
data->rq_flags |= RQF_PM;
- if (blk_queue_io_stat(q))
- data->rq_flags |= RQF_IO_STAT;
rq->rq_flags = data->rq_flags;
if (data->rq_flags & RQF_SCHED_TAGS) {
@@ -420,7 +477,7 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data)
prefetch(tags->static_rqs[tag]);
tag_mask &= ~(1UL << i);
rq = blk_mq_rq_ctx_init(data, tags, tag);
- rq_list_add(data->cached_rq, rq);
+ rq_list_add_head(data->cached_rqs, rq);
nr++;
}
if (!(data->rq_flags & RQF_SCHED_TAGS))
@@ -429,7 +486,7 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data)
percpu_ref_get_many(&data->q->q_usage_counter, nr - 1);
data->nr_tags -= nr;
- return rq_list_pop(data->cached_rq);
+ return rq_list_pop(data->cached_rqs);
}
static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)
@@ -526,7 +583,7 @@ static struct request *blk_mq_rq_cache_fill(struct request_queue *q,
.flags = flags,
.cmd_flags = opf,
.nr_tags = plug->nr_ios,
- .cached_rq = &plug->cached_rq,
+ .cached_rqs = &plug->cached_rqs,
};
struct request *rq;
@@ -551,14 +608,14 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
if (!plug)
return NULL;
- if (rq_list_empty(plug->cached_rq)) {
+ if (rq_list_empty(&plug->cached_rqs)) {
if (plug->nr_ios == 1)
return NULL;
rq = blk_mq_rq_cache_fill(q, plug, opf, flags);
if (!rq)
return NULL;
} else {
- rq = rq_list_peek(&plug->cached_rq);
+ rq = rq_list_peek(&plug->cached_rqs);
if (!rq || rq->q != q)
return NULL;
@@ -567,8 +624,8 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
return NULL;
- plug->cached_rq = rq_list_next(rq);
- blk_mq_rq_time_init(rq, 0);
+ rq_list_pop(&plug->cached_rqs);
+ blk_mq_rq_time_init(rq, blk_time_get_ns());
}
rq->cmd_flags = opf;
@@ -744,7 +801,7 @@ void blk_mq_free_plug_rqs(struct blk_plug *plug)
{
struct request *rq;
- while ((rq = rq_list_pop(&plug->cached_rq)) != NULL)
+ while ((rq = rq_list_pop(&plug->cached_rqs)) != NULL)
blk_mq_free_request(rq);
}
@@ -764,7 +821,7 @@ EXPORT_SYMBOL(blk_dump_rq_flags);
static void blk_account_io_completion(struct request *req, unsigned int bytes)
{
- if (req->part && blk_do_io_stat(req)) {
+ if (req->rq_flags & RQF_IO_STAT) {
const int sgrp = op_stat_group(req_op(req));
part_stat_lock();
@@ -784,7 +841,7 @@ static void blk_print_req_error(struct request *req, blk_status_t status)
blk_op_str(req_op(req)),
(__force u32)(req->cmd_flags & ~REQ_OP_MASK),
req->nr_phys_segments,
- IOPRIO_PRIO_CLASS(req->ioprio));
+ IOPRIO_PRIO_CLASS(req_get_ioprio(req)));
}
/*
@@ -982,8 +1039,7 @@ static inline void blk_account_io_done(struct request *req, u64 now)
* normal IO on queueing nor completion. Accounting the
* containing request is enough.
*/
- if (blk_do_io_stat(req) && req->part &&
- !(req->rq_flags & RQF_FLUSH_SEQ)) {
+ if ((req->rq_flags & (RQF_IO_STAT|RQF_FLUSH_SEQ)) == RQF_IO_STAT) {
const int sgrp = op_stat_group(req_op(req));
part_stat_lock();
@@ -996,28 +1052,63 @@ static inline void blk_account_io_done(struct request *req, u64 now)
}
}
+static inline bool blk_rq_passthrough_stats(struct request *req)
+{
+ struct bio *bio = req->bio;
+
+ if (!blk_queue_passthrough_stat(req->q))
+ return false;
+
+ /* Requests without a bio do not transfer data. */
+ if (!bio)
+ return false;
+
+ /*
+ * Stats are accumulated in the bdev, so must have one attached to a
+ * bio to track stats. Most drivers do not set the bdev for passthrough
+ * requests, but nvme is one that will set it.
+ */
+ if (!bio->bi_bdev)
+ return false;
+
+ /*
+ * We don't know what a passthrough command does, but we know the
+ * payload size and data direction. Ensuring the size is aligned to the
+ * block size filters out most commands with payloads that don't
+ * represent sector access.
+ */
+ if (blk_rq_bytes(req) & (bdev_logical_block_size(bio->bi_bdev) - 1))
+ return false;
+ return true;
+}
+
static inline void blk_account_io_start(struct request *req)
{
trace_block_io_start(req);
- if (blk_do_io_stat(req)) {
- /*
- * All non-passthrough requests are created from a bio with one
- * exception: when a flush command that is part of a flush sequence
- * generated by the state machine in blk-flush.c is cloned onto the
- * lower device by dm-multipath we can get here without a bio.
- */
- if (req->bio)
- req->part = req->bio->bi_bdev;
- else
- req->part = req->q->disk->part0;
+ if (!blk_queue_io_stat(req->q))
+ return;
+ if (blk_rq_is_passthrough(req) && !blk_rq_passthrough_stats(req))
+ return;
- part_stat_lock();
- update_io_ticks(req->part, jiffies, false);
- part_stat_local_inc(req->part,
- in_flight[op_is_write(req_op(req))]);
- part_stat_unlock();
- }
+ req->rq_flags |= RQF_IO_STAT;
+ req->start_time_ns = blk_time_get_ns();
+
+ /*
+ * All non-passthrough requests are created from a bio with one
+ * exception: when a flush command that is part of a flush sequence
+ * generated by the state machine in blk-flush.c is cloned onto the
+ * lower device by dm-multipath we can get here without a bio.
+ */
+ if (req->bio)
+ req->part = req->bio->bi_bdev;
+ else
+ req->part = req->q->disk->part0;
+
+ part_stat_lock();
+ update_io_ticks(req->part, jiffies, false);
+ part_stat_local_inc(req->part, in_flight[op_is_write(req_op(req))]);
+ part_stat_unlock();
}
static inline void __blk_mq_end_request_acct(struct request *rq, u64 now)
@@ -1300,8 +1391,7 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq)
*/
if (!plug->has_elevator && (rq->rq_flags & RQF_SCHED_TAGS))
plug->has_elevator = true;
- rq->rq_next = NULL;
- rq_list_add(&plug->mq_list, rq);
+ rq_list_add_tail(&plug->mq_list, rq);
plug->rq_count++;
}
@@ -1698,7 +1788,6 @@ void blk_mq_flush_busy_ctxs(struct blk_mq_hw_ctx *hctx, struct list_head *list)
sbitmap_for_each_set(&hctx->ctx_map, flush_busy_ctx, &data);
}
-EXPORT_SYMBOL_GPL(blk_mq_flush_busy_ctxs);
struct dispatch_rq_data {
struct blk_mq_hw_ctx *hctx;
@@ -2200,6 +2289,24 @@ void blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
}
EXPORT_SYMBOL(blk_mq_delay_run_hw_queue);
+static inline bool blk_mq_hw_queue_need_run(struct blk_mq_hw_ctx *hctx)
+{
+ bool need_run;
+
+ /*
+ * When queue is quiesced, we may be switching io scheduler, or
+ * updating nr_hw_queues, or other things, and we can't run queue
+ * any more, even blk_mq_hctx_has_pending() can't be called safely.
+ *
+ * And queue will be rerun in blk_mq_unquiesce_queue() if it is
+ * quiesced.
+ */
+ __blk_mq_run_dispatch_ops(hctx->queue, false,
+ need_run = !blk_queue_quiesced(hctx->queue) &&
+ blk_mq_hctx_has_pending(hctx));
+ return need_run;
+}
+
/**
* blk_mq_run_hw_queue - Start to run a hardware queue.
* @hctx: Pointer to the hardware queue to run.
@@ -2220,20 +2327,23 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
might_sleep_if(!async && hctx->flags & BLK_MQ_F_BLOCKING);
- /*
- * When queue is quiesced, we may be switching io scheduler, or
- * updating nr_hw_queues, or other things, and we can't run queue
- * any more, even __blk_mq_hctx_has_pending() can't be called safely.
- *
- * And queue will be rerun in blk_mq_unquiesce_queue() if it is
- * quiesced.
- */
- __blk_mq_run_dispatch_ops(hctx->queue, false,
- need_run = !blk_queue_quiesced(hctx->queue) &&
- blk_mq_hctx_has_pending(hctx));
+ need_run = blk_mq_hw_queue_need_run(hctx);
+ if (!need_run) {
+ unsigned long flags;
- if (!need_run)
- return;
+ /*
+ * Synchronize with blk_mq_unquiesce_queue(), because we check
+ * if hw queue is quiesced locklessly above, we need the use
+ * ->queue_lock to make sure we see the up-to-date status to
+ * not miss rerunning the hw queue.
+ */
+ spin_lock_irqsave(&hctx->queue->queue_lock, flags);
+ need_run = blk_mq_hw_queue_need_run(hctx);
+ spin_unlock_irqrestore(&hctx->queue->queue_lock, flags);
+
+ if (!need_run)
+ return;
+ }
if (async || !cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask)) {
blk_mq_delay_run_hw_queue(hctx, 0);
@@ -2390,6 +2500,12 @@ void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
return;
clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
+ /*
+ * Pairs with the smp_mb() in blk_mq_hctx_stopped() to order the
+ * clearing of BLK_MQ_S_STOPPED above and the checking of dispatch
+ * list in the subsequent routine.
+ */
+ smp_mb__after_atomic();
blk_mq_run_hw_queue(hctx, async);
}
EXPORT_SYMBOL_GPL(blk_mq_start_stopped_hw_queue);
@@ -2542,7 +2658,6 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio,
rq->cmd_flags |= REQ_FAILFAST_MASK;
rq->__sector = bio->bi_iter.bi_sector;
- rq->write_hint = bio->bi_write_hint;
blk_rq_bio_prep(rq, bio, nr_segs);
if (bio_integrity(bio))
rq->nr_integrity_segments = blk_rq_count_integrity_sg(rq->q,
@@ -2620,6 +2735,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
if (blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(rq->q)) {
blk_mq_insert_request(rq, 0);
+ blk_mq_run_hw_queue(hctx, false);
return;
}
@@ -2650,6 +2766,7 @@ static blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last)
if (blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(rq->q)) {
blk_mq_insert_request(rq, 0);
+ blk_mq_run_hw_queue(hctx, false);
return BLK_STS_OK;
}
@@ -2666,7 +2783,7 @@ static void blk_mq_plug_issue_direct(struct blk_plug *plug)
blk_status_t ret = BLK_STS_OK;
while ((rq = rq_list_pop(&plug->mq_list))) {
- bool last = rq_list_empty(plug->mq_list);
+ bool last = rq_list_empty(&plug->mq_list);
if (hctx != rq->mq_hctx) {
if (hctx) {
@@ -2709,8 +2826,7 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
{
struct blk_mq_hw_ctx *this_hctx = NULL;
struct blk_mq_ctx *this_ctx = NULL;
- struct request *requeue_list = NULL;
- struct request **requeue_lastp = &requeue_list;
+ struct rq_list requeue_list = {};
unsigned int depth = 0;
bool is_passthrough = false;
LIST_HEAD(list);
@@ -2724,12 +2840,12 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
is_passthrough = blk_rq_is_passthrough(rq);
} else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx ||
is_passthrough != blk_rq_is_passthrough(rq)) {
- rq_list_add_tail(&requeue_lastp, rq);
+ rq_list_add_tail(&requeue_list, rq);
continue;
}
- list_add(&rq->queuelist, &list);
+ list_add_tail(&rq->queuelist, &list);
depth++;
- } while (!rq_list_empty(plug->mq_list));
+ } while (!rq_list_empty(&plug->mq_list));
plug->mq_list = requeue_list;
trace_block_unplug(this_hctx->queue, depth, !from_sched);
@@ -2784,19 +2900,19 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
if (q->mq_ops->queue_rqs) {
blk_mq_run_dispatch_ops(q,
__blk_mq_flush_plug_list(q, plug));
- if (rq_list_empty(plug->mq_list))
+ if (rq_list_empty(&plug->mq_list))
return;
}
blk_mq_run_dispatch_ops(q,
blk_mq_plug_issue_direct(plug));
- if (rq_list_empty(plug->mq_list))
+ if (rq_list_empty(&plug->mq_list))
return;
}
do {
blk_mq_dispatch_plug_list(plug, from_schedule);
- } while (!rq_list_empty(plug->mq_list));
+ } while (!rq_list_empty(&plug->mq_list));
}
static void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
@@ -2861,7 +2977,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q,
if (plug) {
data.nr_tags = plug->nr_ios;
plug->nr_ios = 1;
- data.cached_rq = &plug->cached_rq;
+ data.cached_rqs = &plug->cached_rqs;
}
rq = __blk_mq_alloc_requests(&data);
@@ -2884,7 +3000,7 @@ static struct request *blk_mq_peek_cached_request(struct blk_plug *plug,
if (!plug)
return NULL;
- rq = rq_list_peek(&plug->cached_rq);
+ rq = rq_list_peek(&plug->cached_rqs);
if (!rq || rq->q != q)
return NULL;
if (type != rq->mq_hctx->type &&
@@ -2898,17 +3014,17 @@ static struct request *blk_mq_peek_cached_request(struct blk_plug *plug,
static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug,
struct bio *bio)
{
- WARN_ON_ONCE(rq_list_peek(&plug->cached_rq) != rq);
+ if (rq_list_pop(&plug->cached_rqs) != rq)
+ WARN_ON_ONCE(1);
/*
* If any qos ->throttle() end up blocking, we will have flushed the
* plug and hence killed the cached_rq list as well. Pop this entry
* before we throttle.
*/
- plug->cached_rq = rq_list_next(rq);
rq_qos_throttle(rq->q, bio);
- blk_mq_rq_time_init(rq, 0);
+ blk_mq_rq_time_init(rq, blk_time_get_ns());
rq->cmd_flags = bio->bi_opf;
INIT_LIST_HEAD(&rq->queuelist);
}
@@ -3156,19 +3272,21 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
int (*bio_ctr)(struct bio *, struct bio *, void *),
void *data)
{
- struct bio *bio, *bio_src;
+ struct bio *bio_src;
if (!bs)
bs = &fs_bio_set;
__rq_for_each_bio(bio_src, rq_src) {
- bio = bio_alloc_clone(rq->q->disk->part0, bio_src, gfp_mask,
- bs);
+ struct bio *bio = bio_alloc_clone(rq->q->disk->part0, bio_src,
+ gfp_mask, bs);
if (!bio)
goto free_and_out;
- if (bio_ctr && bio_ctr(bio, bio_src, data))
+ if (bio_ctr && bio_ctr(bio, bio_src, data)) {
+ bio_put(bio);
goto free_and_out;
+ }
if (rq->bio) {
rq->biotail->bi_next = bio;
@@ -3176,7 +3294,6 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
} else {
rq->bio = rq->biotail = bio;
}
- bio = NULL;
}
/* Copy attributes of the original request to the clone request. */
@@ -3187,8 +3304,6 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
rq->special_vec = rq_src->special_vec;
}
rq->nr_phys_segments = rq_src->nr_phys_segments;
- rq->ioprio = rq_src->ioprio;
- rq->write_hint = rq_src->write_hint;
if (rq->bio && blk_crypto_rq_bio_prep(rq, rq->bio, gfp_mask) < 0)
goto free_and_out;
@@ -3196,8 +3311,6 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
return 0;
free_and_out:
- if (bio)
- bio_put(bio);
blk_rq_unprep_clone(rq);
return -ENOMEM;
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 3bd43b10032f..89a20fffa4b1 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -155,7 +155,7 @@ struct blk_mq_alloc_data {
/* allocate multiple requests/tags in one go */
unsigned int nr_tags;
- struct request **cached_rq;
+ struct rq_list *cached_rqs;
/* input & output parameter */
struct blk_mq_ctx *ctx;
@@ -230,6 +230,19 @@ static inline struct blk_mq_tags *blk_mq_tags_from_data(struct blk_mq_alloc_data
static inline bool blk_mq_hctx_stopped(struct blk_mq_hw_ctx *hctx)
{
+ /* Fast path: hardware queue is not stopped most of the time. */
+ if (likely(!test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
+ return false;
+
+ /*
+ * This barrier is used to order adding of dispatch list before and
+ * the test of BLK_MQ_S_STOPPED below. Pairs with the memory barrier
+ * in blk_mq_start_stopped_hw_queue() so that dispatch code could
+ * either see BLK_MQ_S_STOPPED is cleared or dispatch list is not
+ * empty to avoid missing dispatching requests.
+ */
+ smp_mb();
+
return test_bit(BLK_MQ_S_STOPPED, &hctx->state);
}
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c
index 058f92c4f9d5..eb9618cd68ad 100644
--- a/block/blk-rq-qos.c
+++ b/block/blk-rq-qos.c
@@ -218,7 +218,6 @@ static int rq_qos_wake_function(struct wait_queue_entry *curr,
return -1;
data->got_token = true;
- smp_wmb();
wake_up_process(data->task);
list_del_init_careful(&curr->entry);
return 1;
@@ -274,10 +273,9 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
* which means we now have two. Put our local token
* and wake anyone else potentially waiting for one.
*/
- smp_rmb();
if (data.got_token)
cleanup_cb(rqw, private_data);
- break;
+ return;
}
io_schedule();
has_sleeper = true;
diff --git a/block/blk-settings.c b/block/blk-settings.c
index a446654ddee5..8f09e33f41f6 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -50,7 +50,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
lim->max_sectors = UINT_MAX;
lim->max_dev_sectors = UINT_MAX;
lim->max_write_zeroes_sectors = UINT_MAX;
- lim->max_zone_append_sectors = UINT_MAX;
+ lim->max_hw_zone_append_sectors = UINT_MAX;
lim->max_user_discard_sectors = UINT_MAX;
}
EXPORT_SYMBOL(blk_set_stacking_limits);
@@ -91,17 +91,16 @@ static int blk_validate_zoned_limits(struct queue_limits *lim)
if (lim->zone_write_granularity < lim->logical_block_size)
lim->zone_write_granularity = lim->logical_block_size;
- if (lim->max_zone_append_sectors) {
- /*
- * The Zone Append size is limited by the maximum I/O size
- * and the zone size given that it can't span zones.
- */
- lim->max_zone_append_sectors =
- min3(lim->max_hw_sectors,
- lim->max_zone_append_sectors,
- lim->chunk_sectors);
- }
-
+ /*
+ * The Zone Append size is limited by the maximum I/O size and the zone
+ * size given that it can't span zones.
+ *
+ * If no max_hw_zone_append_sectors limit is provided, the block layer
+ * will emulated it, else we're also bound by the hardware limit.
+ */
+ lim->max_zone_append_sectors =
+ min_not_zero(lim->max_hw_zone_append_sectors,
+ min(lim->chunk_sectors, lim->max_hw_sectors));
return 0;
}
@@ -179,9 +178,26 @@ static void blk_validate_atomic_write_limits(struct queue_limits *lim)
if (!lim->atomic_write_hw_max)
goto unsupported;
+ if (WARN_ON_ONCE(!is_power_of_2(lim->atomic_write_hw_unit_min)))
+ goto unsupported;
+
+ if (WARN_ON_ONCE(!is_power_of_2(lim->atomic_write_hw_unit_max)))
+ goto unsupported;
+
+ if (WARN_ON_ONCE(lim->atomic_write_hw_unit_min >
+ lim->atomic_write_hw_unit_max))
+ goto unsupported;
+
+ if (WARN_ON_ONCE(lim->atomic_write_hw_unit_max >
+ lim->atomic_write_hw_max))
+ goto unsupported;
+
boundary_sectors = lim->atomic_write_hw_boundary >> SECTOR_SHIFT;
if (boundary_sectors) {
+ if (WARN_ON_ONCE(lim->atomic_write_hw_max >
+ lim->atomic_write_hw_boundary))
+ goto unsupported;
/*
* A feature of boundary support is that it disallows bios to
* be merged which would result in a merged request which
@@ -223,7 +239,7 @@ unsupported:
* Check that the limits in lim are valid, initialize defaults for unset
* values, and cap values based on others where needed.
*/
-static int blk_validate_limits(struct queue_limits *lim)
+int blk_validate_limits(struct queue_limits *lim)
{
unsigned int max_hw_sectors;
unsigned int logical_block_sectors;
@@ -250,6 +266,13 @@ static int blk_validate_limits(struct queue_limits *lim)
lim->io_min = lim->physical_block_size;
/*
+ * The optimal I/O size may not be aligned to physical block size
+ * (because it may be limited by dma engines which have no clue about
+ * block size of the disks attached to them), so we round it down here.
+ */
+ lim->io_opt = round_down(lim->io_opt, lim->physical_block_size);
+
+ /*
* max_hw_sectors has a somewhat weird default for historical reason,
* but driver really should set their own instead of relying on this
* value.
@@ -366,6 +389,7 @@ static int blk_validate_limits(struct queue_limits *lim)
return err;
return blk_validate_zoned_limits(lim);
}
+EXPORT_SYMBOL_GPL(blk_validate_limits);
/*
* Set the default limits for a newly allocated queue. @lim contains the
@@ -458,8 +482,6 @@ static unsigned int queue_limit_discard_alignment(
/* Why are these in bytes, not sectors? */
alignment = lim->discard_alignment >> SECTOR_SHIFT;
granularity = lim->discard_granularity >> SECTOR_SHIFT;
- if (!granularity)
- return 0;
/* Offset of the partition start in 'granularity' sectors */
offset = sector_div(sector, granularity);
@@ -479,6 +501,119 @@ static unsigned int blk_round_down_sectors(unsigned int sectors, unsigned int lb
return sectors;
}
+/* Check if second and later bottom devices are compliant */
+static bool blk_stack_atomic_writes_tail(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ /* We're not going to support different boundary sizes.. yet */
+ if (t->atomic_write_hw_boundary != b->atomic_write_hw_boundary)
+ return false;
+
+ /* Can't support this */
+ if (t->atomic_write_hw_unit_min > b->atomic_write_hw_unit_max)
+ return false;
+
+ /* Or this */
+ if (t->atomic_write_hw_unit_max < b->atomic_write_hw_unit_min)
+ return false;
+
+ t->atomic_write_hw_max = min(t->atomic_write_hw_max,
+ b->atomic_write_hw_max);
+ t->atomic_write_hw_unit_min = max(t->atomic_write_hw_unit_min,
+ b->atomic_write_hw_unit_min);
+ t->atomic_write_hw_unit_max = min(t->atomic_write_hw_unit_max,
+ b->atomic_write_hw_unit_max);
+ return true;
+}
+
+/* Check for valid boundary of first bottom device */
+static bool blk_stack_atomic_writes_boundary_head(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ /*
+ * Ensure atomic write boundary is aligned with chunk sectors. Stacked
+ * devices store chunk sectors in t->io_min.
+ */
+ if (b->atomic_write_hw_boundary > t->io_min &&
+ b->atomic_write_hw_boundary % t->io_min)
+ return false;
+ if (t->io_min > b->atomic_write_hw_boundary &&
+ t->io_min % b->atomic_write_hw_boundary)
+ return false;
+
+ t->atomic_write_hw_boundary = b->atomic_write_hw_boundary;
+ return true;
+}
+
+
+/* Check stacking of first bottom device */
+static bool blk_stack_atomic_writes_head(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ if (b->atomic_write_hw_boundary &&
+ !blk_stack_atomic_writes_boundary_head(t, b))
+ return false;
+
+ if (t->io_min <= SECTOR_SIZE) {
+ /* No chunk sectors, so use bottom device values directly */
+ t->atomic_write_hw_unit_max = b->atomic_write_hw_unit_max;
+ t->atomic_write_hw_unit_min = b->atomic_write_hw_unit_min;
+ t->atomic_write_hw_max = b->atomic_write_hw_max;
+ return true;
+ }
+
+ /*
+ * Find values for limits which work for chunk size.
+ * b->atomic_write_hw_unit_{min, max} may not be aligned with chunk
+ * size (t->io_min), as chunk size is not restricted to a power-of-2.
+ * So we need to find highest power-of-2 which works for the chunk
+ * size.
+ * As an example scenario, we could have b->unit_max = 16K and
+ * t->io_min = 24K. For this case, reduce t->unit_max to a value
+ * aligned with both limits, i.e. 8K in this example.
+ */
+ t->atomic_write_hw_unit_max = b->atomic_write_hw_unit_max;
+ while (t->io_min % t->atomic_write_hw_unit_max)
+ t->atomic_write_hw_unit_max /= 2;
+
+ t->atomic_write_hw_unit_min = min(b->atomic_write_hw_unit_min,
+ t->atomic_write_hw_unit_max);
+ t->atomic_write_hw_max = min(b->atomic_write_hw_max, t->io_min);
+
+ return true;
+}
+
+static void blk_stack_atomic_writes_limits(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ if (!(t->features & BLK_FEAT_ATOMIC_WRITES_STACKED))
+ goto unsupported;
+
+ if (!b->atomic_write_unit_min)
+ goto unsupported;
+
+ /*
+ * If atomic_write_hw_max is set, we have already stacked 1x bottom
+ * device, so check for compliance.
+ */
+ if (t->atomic_write_hw_max) {
+ if (!blk_stack_atomic_writes_tail(t, b))
+ goto unsupported;
+ return;
+ }
+
+ if (!blk_stack_atomic_writes_head(t, b))
+ goto unsupported;
+ return;
+
+unsupported:
+ t->atomic_write_hw_max = 0;
+ t->atomic_write_hw_unit_max = 0;
+ t->atomic_write_hw_unit_min = 0;
+ t->atomic_write_hw_boundary = 0;
+ t->features &= ~BLK_FEAT_ATOMIC_WRITES_STACKED;
+}
+
/**
* blk_stack_limits - adjust queue_limits for stacked devices
* @t: the stacking driver limits (top device)
@@ -508,10 +643,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->features |= (b->features & BLK_FEAT_INHERIT_MASK);
/*
- * BLK_FEAT_NOWAIT and BLK_FEAT_POLL need to be supported both by the
- * stacking driver and all underlying devices. The stacking driver sets
- * the flags before stacking the limits, and this will clear the flags
- * if any of the underlying devices does not support it.
+ * Some feaures need to be supported both by the stacking driver and all
+ * underlying devices. The stacking driver sets these flags before
+ * stacking the limits, and this will clear the flags if any of the
+ * underlying devices does not support it.
*/
if (!(b->features & BLK_FEAT_NOWAIT))
t->features &= ~BLK_FEAT_NOWAIT;
@@ -527,8 +662,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors);
t->max_write_zeroes_sectors = min(t->max_write_zeroes_sectors,
b->max_write_zeroes_sectors);
- t->max_zone_append_sectors = min(queue_limits_max_zone_append_sectors(t),
- queue_limits_max_zone_append_sectors(b));
+ t->max_hw_zone_append_sectors = min(t->max_hw_zone_append_sectors,
+ b->max_hw_zone_append_sectors);
t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
b->seg_boundary_mask);
@@ -639,6 +774,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->zone_write_granularity = 0;
t->max_zone_append_sectors = 0;
}
+ blk_stack_atomic_writes_limits(t, b);
+
return ret;
}
EXPORT_SYMBOL(blk_stack_limits);
@@ -661,7 +798,7 @@ EXPORT_SYMBOL(blk_stack_limits);
void queue_limits_stack_bdev(struct queue_limits *t, struct block_device *bdev,
sector_t offset, const char *pfx)
{
- if (blk_stack_limits(t, &bdev_get_queue(bdev)->limits,
+ if (blk_stack_limits(t, bdev_limits(bdev),
get_start_sect(bdev) + offset))
pr_notice("%s: Warning: Device %pg is misaligned\n",
pfx, bdev);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index e85941bec857..4241aea84161 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -23,14 +23,14 @@
struct queue_sysfs_entry {
struct attribute attr;
ssize_t (*show)(struct gendisk *disk, char *page);
- int (*load_module)(struct gendisk *disk, const char *page, size_t count);
ssize_t (*store)(struct gendisk *disk, const char *page, size_t count);
+ void (*load_module)(struct gendisk *disk, const char *page, size_t count);
};
static ssize_t
queue_var_show(unsigned long var, char *page)
{
- return sprintf(page, "%lu\n", var);
+ return sysfs_emit(page, "%lu\n", var);
}
static ssize_t
@@ -121,7 +121,7 @@ QUEUE_SYSFS_LIMIT_SHOW(atomic_write_unit_max)
#define QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(_field) \
static ssize_t queue_##_field##_show(struct gendisk *disk, char *page) \
{ \
- return sprintf(page, "%llu\n", \
+ return sysfs_emit(page, "%llu\n", \
(unsigned long long)disk->queue->limits._field << \
SECTOR_SHIFT); \
}
@@ -131,6 +131,7 @@ QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_hw_discard_sectors)
QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_write_zeroes_sectors)
QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(atomic_write_max_sectors)
QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(atomic_write_boundary_sectors)
+QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_zone_append_sectors)
#define QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_KB(_field) \
static ssize_t queue_##_field##_show(struct gendisk *disk, char *page) \
@@ -144,7 +145,7 @@ QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_KB(max_hw_sectors)
#define QUEUE_SYSFS_SHOW_CONST(_name, _val) \
static ssize_t queue_##_name##_show(struct gendisk *disk, char *page) \
{ \
- return sprintf(page, "%d\n", _val); \
+ return sysfs_emit(page, "%d\n", _val); \
}
/* deprecated fields */
@@ -178,18 +179,6 @@ static ssize_t queue_max_discard_sectors_store(struct gendisk *disk,
return ret;
}
-/*
- * For zone append queue_max_zone_append_sectors does not just return the
- * underlying queue limits, but actually contains a calculation. Because of
- * that we can't simply use QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES here.
- */
-static ssize_t queue_zone_append_max_show(struct gendisk *disk, char *page)
-{
- return sprintf(page, "%llu\n",
- (u64)queue_max_zone_append_sectors(disk->queue) <<
- SECTOR_SHIFT);
-}
-
static ssize_t
queue_max_sectors_store(struct gendisk *disk, const char *page, size_t count)
{
@@ -235,7 +224,7 @@ static ssize_t queue_feature_store(struct gendisk *disk, const char *page,
#define QUEUE_SYSFS_FEATURE(_name, _feature) \
static ssize_t queue_##_name##_show(struct gendisk *disk, char *page) \
{ \
- return sprintf(page, "%u\n", \
+ return sysfs_emit(page, "%u\n", \
!!(disk->queue->limits.features & _feature)); \
} \
static ssize_t queue_##_name##_store(struct gendisk *disk, \
@@ -252,7 +241,7 @@ QUEUE_SYSFS_FEATURE(stable_writes, BLK_FEAT_STABLE_WRITES);
#define QUEUE_SYSFS_FEATURE_SHOW(_name, _feature) \
static ssize_t queue_##_name##_show(struct gendisk *disk, char *page) \
{ \
- return sprintf(page, "%u\n", \
+ return sysfs_emit(page, "%u\n", \
!!(disk->queue->limits.features & _feature)); \
}
@@ -263,8 +252,8 @@ QUEUE_SYSFS_FEATURE_SHOW(dax, BLK_FEAT_DAX);
static ssize_t queue_zoned_show(struct gendisk *disk, char *page)
{
if (blk_queue_is_zoned(disk->queue))
- return sprintf(page, "host-managed\n");
- return sprintf(page, "none\n");
+ return sysfs_emit(page, "host-managed\n");
+ return sysfs_emit(page, "none\n");
}
static ssize_t queue_nr_zones_show(struct gendisk *disk, char *page)
@@ -272,6 +261,34 @@ static ssize_t queue_nr_zones_show(struct gendisk *disk, char *page)
return queue_var_show(disk_nr_zones(disk), page);
}
+static ssize_t queue_iostats_passthrough_show(struct gendisk *disk, char *page)
+{
+ return queue_var_show(blk_queue_passthrough_stat(disk->queue), page);
+}
+
+static ssize_t queue_iostats_passthrough_store(struct gendisk *disk,
+ const char *page, size_t count)
+{
+ struct queue_limits lim;
+ unsigned long ios;
+ ssize_t ret;
+
+ ret = queue_var_store(&ios, page, count);
+ if (ret < 0)
+ return ret;
+
+ lim = queue_limits_start_update(disk->queue);
+ if (ios)
+ lim.flags |= BLK_FLAG_IOSTATS_PASSTHROUGH;
+ else
+ lim.flags &= ~BLK_FLAG_IOSTATS_PASSTHROUGH;
+
+ ret = queue_limits_commit_update(disk->queue, &lim);
+ if (ret)
+ return ret;
+
+ return count;
+}
static ssize_t queue_nomerges_show(struct gendisk *disk, char *page)
{
return queue_var_show((blk_queue_nomerges(disk->queue) << 1) |
@@ -349,7 +366,7 @@ static ssize_t queue_poll_store(struct gendisk *disk, const char *page,
static ssize_t queue_io_timeout_show(struct gendisk *disk, char *page)
{
- return sprintf(page, "%u\n", jiffies_to_msecs(disk->queue->rq_timeout));
+ return sysfs_emit(page, "%u\n", jiffies_to_msecs(disk->queue->rq_timeout));
}
static ssize_t queue_io_timeout_store(struct gendisk *disk, const char *page,
@@ -370,8 +387,8 @@ static ssize_t queue_io_timeout_store(struct gendisk *disk, const char *page,
static ssize_t queue_wc_show(struct gendisk *disk, char *page)
{
if (blk_queue_write_cache(disk->queue))
- return sprintf(page, "write back\n");
- return sprintf(page, "write through\n");
+ return sysfs_emit(page, "write back\n");
+ return sysfs_emit(page, "write through\n");
}
static ssize_t queue_wc_store(struct gendisk *disk, const char *page,
@@ -451,7 +468,7 @@ QUEUE_RO_ENTRY(queue_atomic_write_unit_min, "atomic_write_unit_min_bytes");
QUEUE_RO_ENTRY(queue_write_same_max, "write_same_max_bytes");
QUEUE_RO_ENTRY(queue_max_write_zeroes_sectors, "write_zeroes_max_bytes");
-QUEUE_RO_ENTRY(queue_zone_append_max, "zone_append_max_bytes");
+QUEUE_RO_ENTRY(queue_max_zone_append_sectors, "zone_append_max_bytes");
QUEUE_RO_ENTRY(queue_zone_write_granularity, "zone_write_granularity");
QUEUE_RO_ENTRY(queue_zoned, "zoned");
@@ -460,6 +477,7 @@ QUEUE_RO_ENTRY(queue_max_open_zones, "max_open_zones");
QUEUE_RO_ENTRY(queue_max_active_zones, "max_active_zones");
QUEUE_RW_ENTRY(queue_nomerges, "nomerges");
+QUEUE_RW_ENTRY(queue_iostats_passthrough, "iostats_passthrough");
QUEUE_RW_ENTRY(queue_rq_affinity, "rq_affinity");
QUEUE_RW_ENTRY(queue_poll, "io_poll");
QUEUE_RW_ENTRY(queue_poll_delay, "io_poll_delay");
@@ -501,9 +519,9 @@ static ssize_t queue_wb_lat_show(struct gendisk *disk, char *page)
return -EINVAL;
if (wbt_disabled(disk->queue))
- return sprintf(page, "0\n");
+ return sysfs_emit(page, "0\n");
- return sprintf(page, "%llu\n",
+ return sysfs_emit(page, "%llu\n",
div_u64(wbt_get_min_lat(disk->queue), 1000));
}
@@ -578,7 +596,7 @@ static struct attribute *queue_attrs[] = {
&queue_atomic_write_unit_max_entry.attr,
&queue_write_same_max_entry.attr,
&queue_max_write_zeroes_sectors_entry.attr,
- &queue_zone_append_max_entry.attr,
+ &queue_max_zone_append_sectors_entry.attr,
&queue_zone_write_granularity_entry.attr,
&queue_rotational_entry.attr,
&queue_zoned_entry.attr,
@@ -586,6 +604,7 @@ static struct attribute *queue_attrs[] = {
&queue_max_open_zones_entry.attr,
&queue_max_active_zones_entry.attr,
&queue_nomerges_entry.attr,
+ &queue_iostats_passthrough_entry.attr,
&queue_iostats_entry.attr,
&queue_stable_writes_entry.attr,
&queue_add_random_entry.attr,
@@ -684,11 +703,8 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
* queue to ensure that the module file can be read when the request
* queue is the one for the device storing the module file.
*/
- if (entry->load_module) {
- res = entry->load_module(disk, page, length);
- if (res)
- return res;
- }
+ if (entry->load_module)
+ entry->load_module(disk, page, length);
blk_mq_freeze_queue(q);
mutex_lock(&q->sysfs_lock);
@@ -794,10 +810,8 @@ int blk_register_queue(struct gendisk *disk)
* faster to shut down and is made fully functional here as
* request_queues for non-existent devices never get registered.
*/
- if (!blk_queue_init_done(q)) {
- blk_queue_flag_set(QUEUE_FLAG_INIT_DONE, q);
- percpu_ref_switch_to_percpu(&q->q_usage_counter);
- }
+ blk_queue_flag_set(QUEUE_FLAG_INIT_DONE, q);
+ percpu_ref_switch_to_percpu(&q->q_usage_counter);
return ret;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 2c4192e12efa..82dbaefcfa3b 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1485,13 +1485,13 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
goto out_finish;
ret = -EINVAL;
- if (!strcmp(tok, "rbps") && val > 1)
+ if (!strcmp(tok, "rbps"))
v[0] = val;
- else if (!strcmp(tok, "wbps") && val > 1)
+ else if (!strcmp(tok, "wbps"))
v[1] = val;
- else if (!strcmp(tok, "riops") && val > 1)
+ else if (!strcmp(tok, "riops"))
v[2] = min_t(u64, val, UINT_MAX);
- else if (!strcmp(tok, "wiops") && val > 1)
+ else if (!strcmp(tok, "wiops"))
v[3] = min_t(u64, val, UINT_MAX);
else
goto out_finish;
@@ -1526,6 +1526,42 @@ static void throtl_shutdown_wq(struct request_queue *q)
cancel_work_sync(&td->dispatch_work);
}
+static void tg_flush_bios(struct throtl_grp *tg)
+{
+ struct throtl_service_queue *sq = &tg->service_queue;
+
+ if (tg->flags & THROTL_TG_CANCELING)
+ return;
+ /*
+ * Set the flag to make sure throtl_pending_timer_fn() won't
+ * stop until all throttled bios are dispatched.
+ */
+ 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))
+ return;
+
+ /*
+ * Update disptime after setting the above flag to make sure
+ * throtl_select_dispatch() won't exit without dispatching.
+ */
+ tg_update_disptime(tg);
+
+ throtl_schedule_pending_timer(sq, jiffies + 1);
+}
+
+static void throtl_pd_offline(struct blkg_policy_data *pd)
+{
+ tg_flush_bios(pd_to_tg(pd));
+}
+
struct blkcg_policy blkcg_policy_throtl = {
.dfl_cftypes = throtl_files,
.legacy_cftypes = throtl_legacy_files,
@@ -1533,6 +1569,7 @@ struct blkcg_policy blkcg_policy_throtl = {
.pd_alloc_fn = throtl_pd_alloc,
.pd_init_fn = throtl_pd_init,
.pd_online_fn = throtl_pd_online,
+ .pd_offline_fn = throtl_pd_offline,
.pd_free_fn = throtl_pd_free,
};
@@ -1553,32 +1590,15 @@ void blk_throtl_cancel_bios(struct gendisk *disk)
*/
rcu_read_lock();
blkg_for_each_descendant_post(blkg, pos_css, q->root_blkg) {
- struct throtl_grp *tg = blkg_to_tg(blkg);
- struct throtl_service_queue *sq = &tg->service_queue;
-
- /*
- * Set the flag to make sure throtl_pending_timer_fn() won't
- * stop until all throttled bios are dispatched.
- */
- 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.
+ * disk_release will call pd_offline_fn to cancel bios.
+ * However, disk_release can't be called if someone get
+ * the refcount of device and issued bios which are
+ * inflight after del_gendisk.
+ * Cancel bios here to ensure no bios are inflight after
+ * del_gendisk.
*/
- 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.
- */
- tg_update_disptime(tg);
-
- throtl_schedule_pending_timer(sq, jiffies + 1);
+ tg_flush_bios(blkg_to_tg(blkg));
}
rcu_read_unlock();
spin_unlock_irq(&q->queue_lock);
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index af19296fa50d..263e28b72053 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -18,7 +18,7 @@
#include <linux/vmalloc.h>
#include <linux/sched/mm.h>
#include <linux/spinlock.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
#include <linux/mempool.h>
#include "blk.h"
@@ -64,7 +64,7 @@ static const char *const zone_cond_name[] = {
struct blk_zone_wplug {
struct hlist_node node;
struct list_head link;
- atomic_t ref;
+ refcount_t ref;
spinlock_t lock;
unsigned int flags;
unsigned int zone_no;
@@ -348,13 +348,6 @@ fail:
return ret;
}
-static inline bool disk_zone_is_conv(struct gendisk *disk, sector_t sector)
-{
- if (!disk->conv_zones_bitmap)
- return false;
- return test_bit(disk_zone_no(disk, sector), disk->conv_zones_bitmap);
-}
-
static bool disk_zone_is_last(struct gendisk *disk, struct blk_zone *zone)
{
return zone->start + zone->len >= get_capacity(disk);
@@ -411,7 +404,7 @@ static struct blk_zone_wplug *disk_get_zone_wplug(struct gendisk *disk,
hlist_for_each_entry_rcu(zwplug, &disk->zone_wplugs_hash[idx], node) {
if (zwplug->zone_no == zno &&
- atomic_inc_not_zero(&zwplug->ref)) {
+ refcount_inc_not_zero(&zwplug->ref)) {
rcu_read_unlock();
return zwplug;
}
@@ -432,7 +425,7 @@ static void disk_free_zone_wplug_rcu(struct rcu_head *rcu_head)
static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug)
{
- if (atomic_dec_and_test(&zwplug->ref)) {
+ if (refcount_dec_and_test(&zwplug->ref)) {
WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list));
WARN_ON_ONCE(!list_empty(&zwplug->link));
WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED));
@@ -463,7 +456,7 @@ static inline bool disk_should_remove_zone_wplug(struct gendisk *disk,
* taken when the plug was allocated and another reference taken by the
* caller context).
*/
- if (atomic_read(&zwplug->ref) > 2)
+ if (refcount_read(&zwplug->ref) > 2)
return false;
/* We can remove zone write plugs for zones that are empty or full. */
@@ -533,7 +526,7 @@ again:
INIT_HLIST_NODE(&zwplug->node);
INIT_LIST_HEAD(&zwplug->link);
- atomic_set(&zwplug->ref, 2);
+ refcount_set(&zwplug->ref, 2);
spin_lock_init(&zwplug->lock);
zwplug->flags = 0;
zwplug->zone_no = zno;
@@ -624,7 +617,7 @@ static inline void disk_zone_wplug_set_error(struct gendisk *disk,
* finished.
*/
zwplug->flags |= BLK_ZONE_WPLUG_ERROR;
- atomic_inc(&zwplug->ref);
+ refcount_inc(&zwplug->ref);
spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
list_add_tail(&zwplug->link, &disk->zone_wplugs_err_list);
@@ -709,7 +702,7 @@ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
struct blk_zone_wplug *zwplug;
/* Conventional zones cannot be reset nor finished. */
- if (disk_zone_is_conv(disk, sector)) {
+ if (!bdev_zone_is_seq(bio->bi_bdev, sector)) {
bio_io_error(bio);
return true;
}
@@ -963,7 +956,7 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
}
/* Conventional zones do not need write plugging. */
- if (disk_zone_is_conv(disk, sector)) {
+ if (!bdev_zone_is_seq(bio->bi_bdev, sector)) {
/* Zone append to conventional zones is not allowed. */
if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
bio_io_error(bio);
@@ -1099,7 +1092,7 @@ static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
* reference we take here.
*/
WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
- atomic_inc(&zwplug->ref);
+ refcount_inc(&zwplug->ref);
queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
}
@@ -1444,7 +1437,7 @@ static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk)
while (!hlist_empty(&disk->zone_wplugs_hash[i])) {
zwplug = hlist_entry(disk->zone_wplugs_hash[i].first,
struct blk_zone_wplug, node);
- atomic_inc(&zwplug->ref);
+ refcount_inc(&zwplug->ref);
disk_remove_zone_wplug(disk, zwplug);
disk_put_zone_wplug(zwplug);
}
@@ -1455,6 +1448,24 @@ static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk)
disk->zone_wplugs_hash_bits = 0;
}
+static unsigned int disk_set_conv_zones_bitmap(struct gendisk *disk,
+ unsigned long *bitmap)
+{
+ unsigned int nr_conv_zones = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+ if (bitmap)
+ nr_conv_zones = bitmap_weight(bitmap, disk->nr_zones);
+ bitmap = rcu_replace_pointer(disk->conv_zones_bitmap, bitmap,
+ lockdep_is_held(&disk->zone_wplugs_lock));
+ spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+
+ kfree_rcu_mightsleep(bitmap);
+
+ return nr_conv_zones;
+}
+
void disk_free_zone_resources(struct gendisk *disk)
{
if (!disk->zone_wplugs_pool)
@@ -1478,8 +1489,7 @@ void disk_free_zone_resources(struct gendisk *disk)
mempool_destroy(disk->zone_wplugs_pool);
disk->zone_wplugs_pool = NULL;
- bitmap_free(disk->conv_zones_bitmap);
- disk->conv_zones_bitmap = NULL;
+ disk_set_conv_zones_bitmap(disk, NULL);
disk->zone_capacity = 0;
disk->last_zone_capacity = 0;
disk->nr_zones = 0;
@@ -1538,17 +1548,16 @@ static int disk_update_zone_resources(struct gendisk *disk,
struct blk_revalidate_zone_args *args)
{
struct request_queue *q = disk->queue;
- unsigned int nr_seq_zones, nr_conv_zones = 0;
+ unsigned int nr_seq_zones, nr_conv_zones;
unsigned int pool_size;
struct queue_limits lim;
+ int ret;
disk->nr_zones = args->nr_zones;
disk->zone_capacity = args->zone_capacity;
disk->last_zone_capacity = args->last_zone_capacity;
- swap(disk->conv_zones_bitmap, args->conv_zones_bitmap);
- if (disk->conv_zones_bitmap)
- nr_conv_zones = bitmap_weight(disk->conv_zones_bitmap,
- disk->nr_zones);
+ nr_conv_zones =
+ disk_set_conv_zones_bitmap(disk, args->conv_zones_bitmap);
if (nr_conv_zones >= disk->nr_zones) {
pr_warn("%s: Invalid number of conventional zones %u / %u\n",
disk->disk_name, nr_conv_zones, disk->nr_zones);
@@ -1593,7 +1602,11 @@ static int disk_update_zone_resources(struct gendisk *disk,
}
commit:
- return queue_limits_commit_update(q, &lim);
+ blk_mq_freeze_queue(q);
+ ret = queue_limits_commit_update(q, &lim);
+ blk_mq_unfreeze_queue(q);
+
+ return ret;
}
static int blk_revalidate_conv_zone(struct blk_zone *zone, unsigned int idx,
@@ -1774,12 +1787,6 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
return -ENODEV;
}
- if (!queue_max_zone_append_sectors(q)) {
- pr_warn("%s: Invalid 0 maximum zone append limit\n",
- disk->disk_name);
- return -ENODEV;
- }
-
/*
* Ensure that all memory allocations in this context are done as if
* GFP_NOIO was specified.
@@ -1814,16 +1821,15 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
* Set the new disk zone parameters only once the queue is frozen and
* all I/Os are completed.
*/
- blk_mq_freeze_queue(q);
if (ret > 0)
ret = disk_update_zone_resources(disk, &args);
else
pr_warn("%s: failed to revalidate zones\n", disk->disk_name);
- if (ret)
+ if (ret) {
+ blk_mq_freeze_queue(q);
disk_free_zone_resources(disk);
- blk_mq_unfreeze_queue(q);
-
- kfree(args.conv_zones_bitmap);
+ blk_mq_unfreeze_queue(q);
+ }
return ret;
}
@@ -1851,7 +1857,7 @@ int queue_zone_wplugs_show(void *data, struct seq_file *m)
spin_lock_irqsave(&zwplug->lock, flags);
zwp_zone_no = zwplug->zone_no;
zwp_flags = zwplug->flags;
- zwp_ref = atomic_read(&zwplug->ref);
+ zwp_ref = refcount_read(&zwplug->ref);
zwp_wp_offset = zwplug->wp_offset;
zwp_bio_list_size = bio_list_size(&zwplug->bio_list);
spin_unlock_irqrestore(&zwplug->lock, flags);
diff --git a/block/blk.h b/block/blk.h
index c718e4291db0..2c26abf505b8 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -4,6 +4,7 @@
#include <linux/bio-integrity.h>
#include <linux/blk-crypto.h>
+#include <linux/lockdep.h>
#include <linux/memblock.h> /* for max_pfn/max_low_pfn */
#include <linux/sched/sysctl.h>
#include <linux/timekeeping.h>
@@ -34,9 +35,10 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
gfp_t flags);
void blk_free_flush_queue(struct blk_flush_queue *q);
-void blk_freeze_queue(struct request_queue *q);
-void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic);
-void blk_queue_start_drain(struct request_queue *q);
+bool __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic);
+bool blk_queue_start_drain(struct request_queue *q);
+bool __blk_freeze_queue_start(struct request_queue *q,
+ struct task_struct *owner);
int __bio_queue_enter(struct request_queue *q, struct bio *bio);
void submit_bio_noacct_nocheck(struct bio *bio);
void bio_await_chain(struct bio *bio);
@@ -69,8 +71,11 @@ static inline int bio_queue_enter(struct bio *bio)
{
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
- if (blk_try_enter_queue(q, false))
+ if (blk_try_enter_queue(q, false)) {
+ rwsem_acquire_read(&q->io_lockdep_map, 0, 0, _RET_IP_);
+ rwsem_release(&q->io_lockdep_map, _RET_IP_);
return 0;
+ }
return __bio_queue_enter(q, bio);
}
@@ -405,17 +410,6 @@ void blk_apply_bdi_limits(struct backing_dev_info *bdi,
struct queue_limits *lim);
int blk_dev_init(void);
-/*
- * Contribute to IO statistics IFF:
- *
- * a) it's attached to a gendisk, and
- * b) the queue had IO stats enabled when this request was started
- */
-static inline bool blk_do_io_stat(struct request *rq)
-{
- return (rq->rq_flags & RQF_IO_STAT) && !blk_rq_is_passthrough(rq);
-}
-
void update_io_ticks(struct block_device *part, unsigned long now, bool end);
unsigned int part_in_flight(struct block_device *part);
@@ -463,11 +457,6 @@ static inline bool bio_zone_write_plugging(struct bio *bio)
{
return bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING);
}
-static inline bool bio_is_zone_append(struct bio *bio)
-{
- return bio_op(bio) == REQ_OP_ZONE_APPEND ||
- bio_flagged(bio, BIO_EMULATES_ZONE_APPEND);
-}
void blk_zone_write_plug_bio_merged(struct bio *bio);
void blk_zone_write_plug_init_request(struct request *rq);
static inline void blk_zone_update_request_bio(struct request *rq,
@@ -516,10 +505,6 @@ static inline bool bio_zone_write_plugging(struct bio *bio)
{
return false;
}
-static inline bool bio_is_zone_append(struct bio *bio)
-{
- return false;
-}
static inline void blk_zone_write_plug_bio_merged(struct bio *bio)
{
}
@@ -558,6 +543,7 @@ void blk_free_ext_minor(unsigned int minor);
#define ADDPART_FLAG_NONE 0
#define ADDPART_FLAG_RAID 1
#define ADDPART_FLAG_WHOLEDISK 2
+#define ADDPART_FLAG_READONLY 4
int bdev_add_partition(struct gendisk *disk, int partno, sector_t start,
sector_t length);
int bdev_del_partition(struct gendisk *disk, int partno);
@@ -734,4 +720,22 @@ void blk_integrity_verify(struct bio *bio);
void blk_integrity_prepare(struct request *rq);
void blk_integrity_complete(struct request *rq, unsigned int nr_bytes);
+static inline void blk_freeze_acquire_lock(struct request_queue *q, bool
+ disk_dead, bool queue_dying)
+{
+ if (!disk_dead)
+ rwsem_acquire(&q->io_lockdep_map, 0, 1, _RET_IP_);
+ if (!queue_dying)
+ rwsem_acquire(&q->q_lockdep_map, 0, 1, _RET_IP_);
+}
+
+static inline void blk_unfreeze_release_lock(struct request_queue *q, bool
+ disk_dead, bool queue_dying)
+{
+ if (!queue_dying)
+ rwsem_release(&q->q_lockdep_map, _RET_IP_);
+ if (!disk_dead)
+ rwsem_release(&q->io_lockdep_map, _RET_IP_);
+}
+
#endif /* BLK_INTERNAL_H */
diff --git a/block/elevator.c b/block/elevator.c
index 9430cde13d1a..7c3ba80e5ff4 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -598,13 +598,19 @@ void elevator_init_mq(struct request_queue *q)
* drain any dispatch activities originated from passthrough
* requests, then no need to quiesce queue which may add long boot
* latency, especially when lots of disks are involved.
+ *
+ * Disk isn't added yet, so verifying queue lock only manually.
*/
- blk_mq_freeze_queue(q);
+ blk_freeze_queue_start_non_owner(q);
+ blk_freeze_acquire_lock(q, true, false);
+ blk_mq_freeze_queue_wait(q);
+
blk_mq_cancel_work_sync(q);
err = blk_mq_init_sched(q, e);
- blk_mq_unfreeze_queue(q);
+ blk_unfreeze_release_lock(q, true, false);
+ blk_mq_unfreeze_queue_non_owner(q);
if (err) {
pr_warn("\"%s\" elevator initialization failed, "
@@ -704,15 +710,15 @@ static int elevator_change(struct request_queue *q, const char *elevator_name)
return ret;
}
-int elv_iosched_load_module(struct gendisk *disk, const char *buf,
- size_t count)
+void elv_iosched_load_module(struct gendisk *disk, const char *buf,
+ size_t count)
{
char elevator_name[ELV_NAME_MAX];
struct elevator_type *found;
const char *name;
if (!elv_support_iosched(disk->queue))
- return -EOPNOTSUPP;
+ return;
strscpy(elevator_name, buf, sizeof(elevator_name));
name = strstrip(elevator_name);
@@ -723,8 +729,6 @@ int elv_iosched_load_module(struct gendisk *disk, const char *buf,
if (!found)
request_module("%s-iosched", name);
-
- return 0;
}
ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
diff --git a/block/elevator.h b/block/elevator.h
index 2a78544bf201..dbf357ef4fab 100644
--- a/block/elevator.h
+++ b/block/elevator.h
@@ -148,8 +148,8 @@ extern void elv_unregister(struct elevator_type *);
* io scheduler sysfs switching
*/
ssize_t elv_iosched_show(struct gendisk *disk, char *page);
-int elv_iosched_load_module(struct gendisk *disk, const char *page,
- size_t count);
+void elv_iosched_load_module(struct gendisk *disk, const char *page,
+ size_t count);
ssize_t elv_iosched_store(struct gendisk *disk, const char *page, size_t count);
extern bool elv_bio_merge_ok(struct request *, struct bio *);
diff --git a/block/fops.c b/block/fops.c
index e696ae53bf1e..13a67940d040 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -35,13 +35,10 @@ static blk_opf_t dio_bio_write_op(struct kiocb *iocb)
return opf;
}
-static bool blkdev_dio_invalid(struct block_device *bdev, loff_t pos,
- struct iov_iter *iter, bool is_atomic)
+static bool blkdev_dio_invalid(struct block_device *bdev, struct kiocb *iocb,
+ struct iov_iter *iter)
{
- if (is_atomic && !generic_atomic_write_valid(iter, pos))
- return true;
-
- return pos & (bdev_logical_block_size(bdev) - 1) ||
+ return iocb->ki_pos & (bdev_logical_block_size(bdev) - 1) ||
!bdev_iter_is_aligned(bdev, iter);
}
@@ -368,13 +365,12 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
{
struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
- bool is_atomic = iocb->ki_flags & IOCB_ATOMIC;
unsigned int nr_pages;
if (!iov_iter_count(iter))
return 0;
- if (blkdev_dio_invalid(bdev, iocb->ki_pos, iter, is_atomic))
+ if (blkdev_dio_invalid(bdev, iocb, iter))
return -EINVAL;
nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS + 1);
@@ -383,7 +379,7 @@ static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
return __blkdev_direct_IO_simple(iocb, iter, bdev,
nr_pages);
return __blkdev_direct_IO_async(iocb, iter, bdev, nr_pages);
- } else if (is_atomic) {
+ } else if (iocb->ki_flags & IOCB_ATOMIC) {
return -EINVAL;
}
return __blkdev_direct_IO(iocb, iter, bdev, bio_max_segs(nr_pages));
@@ -625,7 +621,7 @@ static int blkdev_open(struct inode *inode, struct file *filp)
if (!bdev)
return -ENXIO;
- if (bdev_can_atomic_write(bdev) && filp->f_flags & O_DIRECT)
+ if (bdev_can_atomic_write(bdev))
filp->f_mode |= FMODE_CAN_ATOMIC_WRITE;
ret = bdev_open(bdev, mode, filp->private_data, NULL, filp);
@@ -681,6 +677,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp;
struct inode *bd_inode = bdev_file_inode(file);
struct block_device *bdev = I_BDEV(bd_inode);
+ bool atomic = iocb->ki_flags & IOCB_ATOMIC;
loff_t size = bdev_nr_bytes(bdev);
size_t shorted = 0;
ssize_t ret;
@@ -700,8 +697,16 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT)
return -EOPNOTSUPP;
+ if (atomic) {
+ ret = generic_atomic_write_valid(iocb, from);
+ if (ret)
+ return ret;
+ }
+
size -= iocb->ki_pos;
if (iov_iter_count(from) > size) {
+ if (atomic)
+ return -EINVAL;
shorted = iov_iter_count(from) - size;
iov_iter_truncate(from, size);
}
diff --git a/block/genhd.c b/block/genhd.c
index 1c05dd4c6980..79230c109fca 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -383,16 +383,18 @@ int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode)
}
/**
- * device_add_disk - add disk information to kernel list
+ * add_disk_fwnode - add disk information to kernel list with fwnode
* @parent: parent device for the disk
* @disk: per-device partitioning information
* @groups: Additional per-device sysfs groups
+ * @fwnode: attached disk fwnode
*
* This function registers the partitioning information in @disk
- * with the kernel.
+ * with the kernel. Also attach a fwnode to the disk device.
*/
-int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
- const struct attribute_group **groups)
+int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk,
+ const struct attribute_group **groups,
+ struct fwnode_handle *fwnode)
{
struct device *ddev = disk_to_dev(disk);
@@ -452,6 +454,8 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
ddev->parent = parent;
ddev->groups = groups;
dev_set_name(ddev, "%s", disk->disk_name);
+ if (fwnode)
+ device_set_node(ddev, fwnode);
if (!(disk->flags & GENHD_FL_HIDDEN))
ddev->devt = MKDEV(disk->major, disk->first_minor);
ret = device_add(ddev);
@@ -553,6 +557,22 @@ out_exit_elevator:
elevator_exit(disk->queue);
return ret;
}
+EXPORT_SYMBOL_GPL(add_disk_fwnode);
+
+/**
+ * device_add_disk - add disk information to kernel list
+ * @parent: parent device for the disk
+ * @disk: per-device partitioning information
+ * @groups: Additional per-device sysfs groups
+ *
+ * This function registers the partitioning information in @disk
+ * with the kernel.
+ */
+int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
+ const struct attribute_group **groups)
+{
+ return add_disk_fwnode(parent, disk, groups, NULL);
+}
EXPORT_SYMBOL(device_add_disk);
static void blk_report_disk_dead(struct gendisk *disk, bool surprise)
@@ -581,13 +601,13 @@ static void blk_report_disk_dead(struct gendisk *disk, bool surprise)
rcu_read_unlock();
}
-static void __blk_mark_disk_dead(struct gendisk *disk)
+static bool __blk_mark_disk_dead(struct gendisk *disk)
{
/*
* Fail any new I/O.
*/
if (test_and_set_bit(GD_DEAD, &disk->state))
- return;
+ return false;
if (test_bit(GD_OWNS_QUEUE, &disk->state))
blk_queue_flag_set(QUEUE_FLAG_DYING, disk->queue);
@@ -600,7 +620,7 @@ static void __blk_mark_disk_dead(struct gendisk *disk)
/*
* Prevent new I/O from crossing bio_queue_enter().
*/
- blk_queue_start_drain(disk->queue);
+ return blk_queue_start_drain(disk->queue);
}
/**
@@ -641,6 +661,7 @@ void del_gendisk(struct gendisk *disk)
struct request_queue *q = disk->queue;
struct block_device *part;
unsigned long idx;
+ bool start_drain, queue_dying;
might_sleep();
@@ -668,7 +689,10 @@ void del_gendisk(struct gendisk *disk)
* Drop all partitions now that the disk is marked dead.
*/
mutex_lock(&disk->open_mutex);
- __blk_mark_disk_dead(disk);
+ start_drain = __blk_mark_disk_dead(disk);
+ queue_dying = blk_queue_dying(q);
+ if (start_drain)
+ blk_freeze_acquire_lock(q, true, queue_dying);
xa_for_each_start(&disk->part_tbl, idx, part, 1)
drop_partition(part);
mutex_unlock(&disk->open_mutex);
@@ -718,13 +742,13 @@ void del_gendisk(struct gendisk *disk)
* If the disk does not own the queue, allow using passthrough requests
* again. Else leave the queue frozen to fail all I/O.
*/
- if (!test_bit(GD_OWNS_QUEUE, &disk->state)) {
- blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q);
+ if (!test_bit(GD_OWNS_QUEUE, &disk->state))
__blk_mq_unfreeze_queue(q, true);
- } else {
- if (queue_is_mq(q))
- blk_mq_exit_queue(q);
- }
+ else if (queue_is_mq(q))
+ blk_mq_exit_queue(q);
+
+ if (start_drain)
+ blk_unfreeze_release_lock(q, true, queue_dying);
}
EXPORT_SYMBOL(del_gendisk);
@@ -756,7 +780,7 @@ static ssize_t disk_badblocks_show(struct device *dev,
struct gendisk *disk = dev_to_disk(dev);
if (!disk->bb)
- return sprintf(page, "\n");
+ return sysfs_emit(page, "\n");
return badblocks_show(disk->bb, page, 0);
}
@@ -904,7 +928,7 @@ static ssize_t disk_range_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n", disk->minors);
+ return sysfs_emit(buf, "%d\n", disk->minors);
}
static ssize_t disk_ext_range_show(struct device *dev,
@@ -912,7 +936,7 @@ static ssize_t disk_ext_range_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n",
+ return sysfs_emit(buf, "%d\n",
(disk->flags & GENHD_FL_NO_PART) ? 1 : DISK_MAX_PARTS);
}
@@ -921,7 +945,7 @@ static ssize_t disk_removable_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n",
+ return sysfs_emit(buf, "%d\n",
(disk->flags & GENHD_FL_REMOVABLE ? 1 : 0));
}
@@ -930,7 +954,7 @@ static ssize_t disk_hidden_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n",
+ return sysfs_emit(buf, "%d\n",
(disk->flags & GENHD_FL_HIDDEN ? 1 : 0));
}
@@ -939,13 +963,13 @@ static ssize_t disk_ro_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n", get_disk_ro(disk) ? 1 : 0);
+ return sysfs_emit(buf, "%d\n", get_disk_ro(disk) ? 1 : 0);
}
ssize_t part_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%llu\n", bdev_nr_sectors(dev_to_bdev(dev)));
+ return sysfs_emit(buf, "%llu\n", bdev_nr_sectors(dev_to_bdev(dev)));
}
ssize_t part_stat_show(struct device *dev,
@@ -962,7 +986,7 @@ ssize_t part_stat_show(struct device *dev,
part_stat_unlock();
}
part_stat_read_all(bdev, &stat);
- return sprintf(buf,
+ return sysfs_emit(buf,
"%8lu %8lu %8llu %8u "
"%8lu %8lu %8llu %8u "
"%8u %8u %8u "
@@ -1004,14 +1028,14 @@ ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,
else
part_in_flight_rw(bdev, inflight);
- return sprintf(buf, "%8u %8u\n", inflight[0], inflight[1]);
+ return sysfs_emit(buf, "%8u %8u\n", inflight[0], inflight[1]);
}
static ssize_t disk_capability_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
dev_warn_once(dev, "the capability attribute has been deprecated.\n");
- return sprintf(buf, "0\n");
+ return sysfs_emit(buf, "0\n");
}
static ssize_t disk_alignment_offset_show(struct device *dev,
@@ -1020,7 +1044,7 @@ static ssize_t disk_alignment_offset_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n", bdev_alignment_offset(disk->part0));
+ return sysfs_emit(buf, "%d\n", bdev_alignment_offset(disk->part0));
}
static ssize_t disk_discard_alignment_show(struct device *dev,
@@ -1029,7 +1053,7 @@ static ssize_t disk_discard_alignment_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%d\n", bdev_alignment_offset(disk->part0));
+ return sysfs_emit(buf, "%d\n", bdev_alignment_offset(disk->part0));
}
static ssize_t diskseq_show(struct device *dev,
@@ -1037,13 +1061,13 @@ static ssize_t diskseq_show(struct device *dev,
{
struct gendisk *disk = dev_to_disk(dev);
- return sprintf(buf, "%llu\n", disk->diskseq);
+ return sysfs_emit(buf, "%llu\n", disk->diskseq);
}
static ssize_t partscan_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%u\n", disk_has_partscan(dev_to_disk(dev)));
+ return sysfs_emit(buf, "%u\n", disk_has_partscan(dev_to_disk(dev)));
}
static DEVICE_ATTR(range, 0444, disk_range_show, NULL);
@@ -1065,7 +1089,7 @@ static DEVICE_ATTR(partscan, 0444, partscan_show, NULL);
ssize_t part_fail_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n",
+ return sysfs_emit(buf, "%d\n",
bdev_test_flag(dev_to_bdev(dev), BD_MAKE_IT_FAIL));
}
@@ -1264,40 +1288,35 @@ static int diskstats_show(struct seq_file *seqf, void *v)
part_stat_unlock();
}
part_stat_read_all(hd, &stat);
- seq_printf(seqf, "%4d %7d %pg "
- "%lu %lu %lu %u "
- "%lu %lu %lu %u "
- "%u %u %u "
- "%lu %lu %lu %u "
- "%lu %u"
- "\n",
- MAJOR(hd->bd_dev), MINOR(hd->bd_dev), hd,
- stat.ios[STAT_READ],
- stat.merges[STAT_READ],
- stat.sectors[STAT_READ],
- (unsigned int)div_u64(stat.nsecs[STAT_READ],
- NSEC_PER_MSEC),
- stat.ios[STAT_WRITE],
- stat.merges[STAT_WRITE],
- stat.sectors[STAT_WRITE],
- (unsigned int)div_u64(stat.nsecs[STAT_WRITE],
- NSEC_PER_MSEC),
- inflight,
- jiffies_to_msecs(stat.io_ticks),
- (unsigned int)div_u64(stat.nsecs[STAT_READ] +
- stat.nsecs[STAT_WRITE] +
- stat.nsecs[STAT_DISCARD] +
- stat.nsecs[STAT_FLUSH],
- NSEC_PER_MSEC),
- stat.ios[STAT_DISCARD],
- stat.merges[STAT_DISCARD],
- stat.sectors[STAT_DISCARD],
- (unsigned int)div_u64(stat.nsecs[STAT_DISCARD],
- NSEC_PER_MSEC),
- stat.ios[STAT_FLUSH],
- (unsigned int)div_u64(stat.nsecs[STAT_FLUSH],
- NSEC_PER_MSEC)
- );
+ seq_put_decimal_ull_width(seqf, "", MAJOR(hd->bd_dev), 4);
+ seq_put_decimal_ull_width(seqf, " ", MINOR(hd->bd_dev), 7);
+ seq_printf(seqf, " %pg", hd);
+ seq_put_decimal_ull(seqf, " ", stat.ios[STAT_READ]);
+ seq_put_decimal_ull(seqf, " ", stat.merges[STAT_READ]);
+ seq_put_decimal_ull(seqf, " ", stat.sectors[STAT_READ]);
+ seq_put_decimal_ull(seqf, " ", (unsigned int)div_u64(stat.nsecs[STAT_READ],
+ NSEC_PER_MSEC));
+ seq_put_decimal_ull(seqf, " ", stat.ios[STAT_WRITE]);
+ seq_put_decimal_ull(seqf, " ", stat.merges[STAT_WRITE]);
+ seq_put_decimal_ull(seqf, " ", stat.sectors[STAT_WRITE]);
+ seq_put_decimal_ull(seqf, " ", (unsigned int)div_u64(stat.nsecs[STAT_WRITE],
+ NSEC_PER_MSEC));
+ seq_put_decimal_ull(seqf, " ", inflight);
+ seq_put_decimal_ull(seqf, " ", jiffies_to_msecs(stat.io_ticks));
+ seq_put_decimal_ull(seqf, " ", (unsigned int)div_u64(stat.nsecs[STAT_READ] +
+ stat.nsecs[STAT_WRITE] +
+ stat.nsecs[STAT_DISCARD] +
+ stat.nsecs[STAT_FLUSH],
+ NSEC_PER_MSEC));
+ seq_put_decimal_ull(seqf, " ", stat.ios[STAT_DISCARD]);
+ seq_put_decimal_ull(seqf, " ", stat.merges[STAT_DISCARD]);
+ seq_put_decimal_ull(seqf, " ", stat.sectors[STAT_DISCARD]);
+ seq_put_decimal_ull(seqf, " ", (unsigned int)div_u64(stat.nsecs[STAT_DISCARD],
+ NSEC_PER_MSEC));
+ seq_put_decimal_ull(seqf, " ", stat.ios[STAT_FLUSH]);
+ seq_put_decimal_ull(seqf, " ", (unsigned int)div_u64(stat.nsecs[STAT_FLUSH],
+ NSEC_PER_MSEC));
+ seq_putc(seqf, '\n');
}
rcu_read_unlock();
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index acdc28756d9d..91b3789f710e 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -685,10 +685,9 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
prio = ioprio_class_to_prio[ioprio_class];
per_prio = &dd->per_prio[prio];
- if (!rq->elv.priv[0]) {
+ if (!rq->elv.priv[0])
per_prio->stats.inserted++;
- rq->elv.priv[0] = (void *)(uintptr_t)1;
- }
+ rq->elv.priv[0] = per_prio;
if (blk_mq_sched_try_insert_merge(q, rq, free))
return;
@@ -753,18 +752,14 @@ static void dd_prepare_request(struct request *rq)
*/
static void dd_finish_request(struct request *rq)
{
- struct request_queue *q = rq->q;
- struct deadline_data *dd = q->elevator->elevator_data;
- const u8 ioprio_class = dd_rq_ioclass(rq);
- const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
- struct dd_per_prio *per_prio = &dd->per_prio[prio];
+ struct dd_per_prio *per_prio = rq->elv.priv[0];
/*
* The block layer core may call dd_finish_request() without having
* called dd_insert_requests(). Skip requests that bypassed I/O
* scheduling. See also blk_mq_request_bypass_insert().
*/
- if (rq->elv.priv[0])
+ if (per_prio)
atomic_inc(&per_prio->stats.completed);
}
diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig
index 7aff4eb81c60..ce17e41451af 100644
--- a/block/partitions/Kconfig
+++ b/block/partitions/Kconfig
@@ -270,4 +270,13 @@ config CMDLINE_PARTITION
Say Y here if you want to read the partition table from bootargs.
The format for the command line is just like mtdparts.
+config OF_PARTITION
+ bool "Device Tree partition support" if PARTITION_ADVANCED
+ depends on OF
+ help
+ Say Y here if you want to enable support for partition table
+ defined in Device Tree. (mainly for eMMC)
+ The format for the device tree node is just like MTD fixed-partition
+ schema.
+
endmenu
diff --git a/block/partitions/Makefile b/block/partitions/Makefile
index a7f05cdb02a8..25d424922c6e 100644
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o
obj-$(CONFIG_MAC_PARTITION) += mac.o
obj-$(CONFIG_LDM_PARTITION) += ldm.o
obj-$(CONFIG_MSDOS_PARTITION) += msdos.o
+obj-$(CONFIG_OF_PARTITION) += of.o
obj-$(CONFIG_OSF_PARTITION) += osf.o
obj-$(CONFIG_SGI_PARTITION) += sgi.o
obj-$(CONFIG_SUN_PARTITION) += sun.o
diff --git a/block/partitions/check.h b/block/partitions/check.h
index 8d70a880c372..e5c1c61eb353 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -62,6 +62,7 @@ int karma_partition(struct parsed_partitions *state);
int ldm_partition(struct parsed_partitions *state);
int mac_partition(struct parsed_partitions *state);
int msdos_partition(struct parsed_partitions *state);
+int of_partition(struct parsed_partitions *state);
int osf_partition(struct parsed_partitions *state);
int sgi_partition(struct parsed_partitions *state);
int sun_partition(struct parsed_partitions *state);
diff --git a/block/partitions/cmdline.c b/block/partitions/cmdline.c
index 152c85df92b2..da3e719d8e51 100644
--- a/block/partitions/cmdline.c
+++ b/block/partitions/cmdline.c
@@ -237,6 +237,9 @@ static int add_part(int slot, struct cmdline_subpart *subpart,
put_partition(state, slot, subpart->from >> 9,
subpart->size >> 9);
+ if (subpart->flags & PF_RDONLY)
+ state->parts[slot].flags |= ADDPART_FLAG_READONLY;
+
info = &state->parts[slot].info;
strscpy(info->volname, subpart->name, sizeof(info->volname));
diff --git a/block/partitions/core.c b/block/partitions/core.c
index 5bd7a603092e..815ed33caa1b 100644
--- a/block/partitions/core.c
+++ b/block/partitions/core.c
@@ -43,6 +43,9 @@ static int (*const check_part[])(struct parsed_partitions *) = {
#ifdef CONFIG_CMDLINE_PARTITION
cmdline_partition,
#endif
+#ifdef CONFIG_OF_PARTITION
+ of_partition, /* cmdline have priority to OF */
+#endif
#ifdef CONFIG_EFI_PARTITION
efi_partition, /* this must come before msdos */
#endif
@@ -253,6 +256,8 @@ static int part_uevent(const struct device *dev, struct kobj_uevent_env *env)
add_uevent_var(env, "PARTN=%u", bdev_partno(part));
if (part->bd_meta_info && part->bd_meta_info->volname[0])
add_uevent_var(env, "PARTNAME=%s", part->bd_meta_info->volname);
+ if (part->bd_meta_info && part->bd_meta_info->uuid[0])
+ add_uevent_var(env, "PARTUUID=%s", part->bd_meta_info->uuid);
return 0;
}
@@ -373,6 +378,9 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
goto out_del;
}
+ if (flags & ADDPART_FLAG_READONLY)
+ bdev_set_flag(bdev, BD_READ_ONLY);
+
/* everything is up and running, commence */
err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL);
if (err)
diff --git a/block/partitions/of.c b/block/partitions/of.c
new file mode 100644
index 000000000000..4e760fdffb3f
--- /dev/null
+++ b/block/partitions/of.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/blkdev.h>
+#include <linux/major.h>
+#include <linux/of.h>
+#include <linux/string.h>
+#include "check.h"
+
+static int validate_of_partition(struct device_node *np, int slot)
+{
+ u64 offset, size;
+ int len;
+
+ const __be32 *reg = of_get_property(np, "reg", &len);
+ int a_cells = of_n_addr_cells(np);
+ int s_cells = of_n_size_cells(np);
+
+ /* Make sure reg len match the expected addr and size cells */
+ if (len / sizeof(*reg) != a_cells + s_cells)
+ return -EINVAL;
+
+ /* Validate offset conversion from bytes to sectors */
+ offset = of_read_number(reg, a_cells);
+ if (offset % SECTOR_SIZE)
+ return -EINVAL;
+
+ /* Validate size conversion from bytes to sectors */
+ size = of_read_number(reg + a_cells, s_cells);
+ if (!size || size % SECTOR_SIZE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void add_of_partition(struct parsed_partitions *state, int slot,
+ struct device_node *np)
+{
+ struct partition_meta_info *info;
+ char tmp[sizeof(info->volname) + 4];
+ const char *partname;
+ int len;
+
+ const __be32 *reg = of_get_property(np, "reg", &len);
+ int a_cells = of_n_addr_cells(np);
+ int s_cells = of_n_size_cells(np);
+
+ /* Convert bytes to sector size */
+ u64 offset = of_read_number(reg, a_cells) / SECTOR_SIZE;
+ u64 size = of_read_number(reg + a_cells, s_cells) / SECTOR_SIZE;
+
+ put_partition(state, slot, offset, size);
+
+ if (of_property_read_bool(np, "read-only"))
+ state->parts[slot].flags |= ADDPART_FLAG_READONLY;
+
+ /*
+ * Follow MTD label logic, search for label property,
+ * fallback to node name if not found.
+ */
+ info = &state->parts[slot].info;
+ partname = of_get_property(np, "label", &len);
+ if (!partname)
+ partname = of_get_property(np, "name", &len);
+ strscpy(info->volname, partname, sizeof(info->volname));
+
+ snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
+ strlcat(state->pp_buf, tmp, PAGE_SIZE);
+}
+
+int of_partition(struct parsed_partitions *state)
+{
+ struct device *ddev = disk_to_dev(state->disk);
+ struct device_node *np;
+ int slot;
+
+ struct device_node *partitions_np = of_node_get(ddev->of_node);
+
+ if (!partitions_np ||
+ !of_device_is_compatible(partitions_np, "fixed-partitions"))
+ return 0;
+
+ slot = 1;
+ /* Validate parition offset and size */
+ for_each_child_of_node(partitions_np, np) {
+ if (validate_of_partition(np, slot)) {
+ of_node_put(np);
+ of_node_put(partitions_np);
+
+ return -1;
+ }
+
+ slot++;
+ }
+
+ slot = 1;
+ for_each_child_of_node(partitions_np, np) {
+ if (slot >= state->limit) {
+ of_node_put(np);
+ break;
+ }
+
+ add_of_partition(state, slot, np);
+
+ slot++;
+ }
+
+ strlcat(state->pp_buf, "\n", PAGE_SIZE);
+
+ return 1;
+}
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 598fd3e7fcc8..5a28f23f7f22 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3037,6 +3037,29 @@ static int opal_set_new_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
return ret;
}
+static int opal_set_new_sid_pw(struct opal_dev *dev, struct opal_new_pw *opal_pw)
+{
+ int ret;
+ struct opal_key *newkey = &opal_pw->new_user_pw.opal_key;
+ struct opal_key *oldkey = &opal_pw->session.opal_key;
+
+ const struct opal_step pw_steps[] = {
+ { start_SIDASP_opal_session, oldkey },
+ { set_sid_cpin_pin, newkey },
+ { end_opal_session, }
+ };
+
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->dev_lock);
+ setup_opal_dev(dev);
+ ret = execute_steps(dev, pw_steps, ARRAY_SIZE(pw_steps));
+ mutex_unlock(&dev->dev_lock);
+
+ return ret;
+}
+
static int opal_activate_user(struct opal_dev *dev,
struct opal_session_info *opal_session)
{
@@ -3286,6 +3309,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_DISCOVERY:
ret = opal_get_discv(dev, p);
break;
+ case IOC_OPAL_SET_SID_PW:
+ ret = opal_set_new_sid_pw(dev, p);
+ break;
default:
break;
diff --git a/crypto/Kconfig b/crypto/Kconfig
index a779cab668c2..6b0bfbccac08 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -250,6 +250,7 @@ config CRYPTO_RSA
tristate "RSA (Rivest-Shamir-Adleman)"
select CRYPTO_AKCIPHER
select CRYPTO_MANAGER
+ select CRYPTO_SIG
select MPILIB
select ASN1
help
@@ -290,19 +291,19 @@ config CRYPTO_ECDH
config CRYPTO_ECDSA
tristate "ECDSA (Elliptic Curve Digital Signature Algorithm)"
select CRYPTO_ECC
- select CRYPTO_AKCIPHER
+ select CRYPTO_SIG
select ASN1
help
ECDSA (Elliptic Curve Digital Signature Algorithm) (FIPS 186,
ISO/IEC 14888-3)
- using curves P-192, P-256, and P-384
+ using curves P-192, P-256, P-384 and P-521
Only signature verification is implemented.
config CRYPTO_ECRDSA
tristate "EC-RDSA (Elliptic Curve Russian Digital Signature Algorithm)"
select CRYPTO_ECC
- select CRYPTO_AKCIPHER
+ select CRYPTO_SIG
select CRYPTO_STREEBOG
select OID_REGISTRY
select ASN1
diff --git a/crypto/Makefile b/crypto/Makefile
index 4c99e5d376f6..77abca715445 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -48,11 +48,14 @@ rsa_generic-y += rsaprivkey.asn1.o
rsa_generic-y += rsa.o
rsa_generic-y += rsa_helper.o
rsa_generic-y += rsa-pkcs1pad.o
+rsa_generic-y += rsassa-pkcs1.o
obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
$(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h
-$(obj)/ecdsa.o: $(obj)/ecdsasignature.asn1.h
+$(obj)/ecdsa-x962.o: $(obj)/ecdsasignature.asn1.h
ecdsa_generic-y += ecdsa.o
+ecdsa_generic-y += ecdsa-x962.o
+ecdsa_generic-y += ecdsa-p1363.o
ecdsa_generic-y += ecdsasignature.asn1.o
obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o
@@ -152,6 +155,8 @@ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o
obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o
+CFLAGS_crc32c_generic.o += -DARCH=$(ARCH)
+CFLAGS_crc32_generic.o += -DARCH=$(ARCH)
obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o
obj-$(CONFIG_CRYPTO_CRC64_ROCKSOFT) += crc64_rocksoft_generic.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
diff --git a/crypto/akcipher.c b/crypto/akcipher.c
index e0ff5f4dda6d..72c82d9aa077 100644
--- a/crypto/akcipher.c
+++ b/crypto/akcipher.c
@@ -20,6 +20,19 @@
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
+struct crypto_akcipher_sync_data {
+ struct crypto_akcipher *tfm;
+ const void *src;
+ void *dst;
+ unsigned int slen;
+ unsigned int dlen;
+
+ struct akcipher_request *req;
+ struct crypto_wait cwait;
+ struct scatterlist sg;
+ u8 *buf;
+};
+
static int __maybe_unused crypto_akcipher_report(
struct sk_buff *skb, struct crypto_alg *alg)
{
@@ -126,10 +139,6 @@ int crypto_register_akcipher(struct akcipher_alg *alg)
{
struct crypto_alg *base = &alg->base;
- if (!alg->sign)
- alg->sign = akcipher_default_op;
- if (!alg->verify)
- alg->verify = akcipher_default_op;
if (!alg->encrypt)
alg->encrypt = akcipher_default_op;
if (!alg->decrypt)
@@ -158,7 +167,7 @@ int akcipher_register_instance(struct crypto_template *tmpl,
}
EXPORT_SYMBOL_GPL(akcipher_register_instance);
-int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
+static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
{
unsigned int reqsize = crypto_akcipher_reqsize(data->tfm);
struct akcipher_request *req;
@@ -167,10 +176,7 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
unsigned int len;
u8 *buf;
- if (data->dst)
- mlen = max(data->slen, data->dlen);
- else
- mlen = data->slen + data->dlen;
+ mlen = max(data->slen, data->dlen);
len = sizeof(*req) + reqsize + mlen;
if (len < mlen)
@@ -189,8 +195,7 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
sg = &data->sg;
sg_init_one(sg, buf, mlen);
- akcipher_request_set_crypt(req, sg, data->dst ? sg : NULL,
- data->slen, data->dlen);
+ akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen);
crypto_init_wait(&data->cwait);
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
@@ -198,18 +203,16 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
return 0;
}
-EXPORT_SYMBOL_GPL(crypto_akcipher_sync_prep);
-int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err)
+static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data,
+ int err)
{
err = crypto_wait_req(err, &data->cwait);
- if (data->dst)
- memcpy(data->dst, data->buf, data->dlen);
+ memcpy(data->dst, data->buf, data->dlen);
data->dlen = data->req->dst_len;
kfree_sensitive(data->req);
return err;
}
-EXPORT_SYMBOL_GPL(crypto_akcipher_sync_post);
int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
const void *src, unsigned int slen,
@@ -248,34 +251,5 @@ int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
}
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt);
-static void crypto_exit_akcipher_ops_sig(struct crypto_tfm *tfm)
-{
- struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
-
- crypto_free_akcipher(*ctx);
-}
-
-int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm)
-{
- struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
- struct crypto_alg *calg = tfm->__crt_alg;
- struct crypto_akcipher *akcipher;
-
- if (!crypto_mod_get(calg))
- return -EAGAIN;
-
- akcipher = crypto_create_tfm(calg, &crypto_akcipher_type);
- if (IS_ERR(akcipher)) {
- crypto_mod_put(calg);
- return PTR_ERR(akcipher);
- }
-
- *ctx = akcipher;
- tfm->exit = crypto_exit_akcipher_ops_sig;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(crypto_init_akcipher_ops_sig);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic public key cipher type");
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 004d27e41315..16f7c7a9d8ab 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -6,7 +6,6 @@
*/
#include <crypto/algapi.h>
-#include <crypto/internal/simd.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/fips.h>
@@ -23,11 +22,6 @@
static LIST_HEAD(crypto_template_list);
-#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
-DEFINE_PER_CPU(bool, crypto_simd_disabled_for_test);
-EXPORT_PER_CPU_SYMBOL_GPL(crypto_simd_disabled_for_test);
-#endif
-
static inline void crypto_check_module_sig(struct module *mod)
{
if (fips_enabled && mod && !module_sig_ok(mod))
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 422940a6706a..bbd07a9022e6 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -83,13 +83,19 @@ software_key_determine_akcipher(const struct public_key *pkey,
if (strcmp(encoding, "pkcs1") == 0) {
*sig = op == kernel_pkey_sign ||
op == kernel_pkey_verify;
- if (!hash_algo) {
+ if (!*sig) {
+ /*
+ * For encrypt/decrypt, hash_algo is not used
+ * but allowed to be set for historic reasons.
+ */
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
"pkcs1pad(%s)",
pkey->pkey_algo);
} else {
+ if (!hash_algo)
+ hash_algo = "none";
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
- "pkcs1pad(%s,%s)",
+ "pkcs1(%s,%s)",
pkey->pkey_algo, hash_algo);
}
return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
@@ -104,7 +110,8 @@ software_key_determine_akcipher(const struct public_key *pkey,
return -EINVAL;
*sig = false;
} else if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
- if (strcmp(encoding, "x962") != 0)
+ if (strcmp(encoding, "x962") != 0 &&
+ strcmp(encoding, "p1363") != 0)
return -EINVAL;
/*
* ECDSA signatures are taken over a raw hash, so they don't
@@ -124,6 +131,9 @@ software_key_determine_akcipher(const struct public_key *pkey,
strcmp(hash_algo, "sha3-384") != 0 &&
strcmp(hash_algo, "sha3-512") != 0)
return -EINVAL;
+ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
+ encoding, pkey->pkey_algo);
+ return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
} else if (strcmp(pkey->pkey_algo, "ecrdsa") == 0) {
if (strcmp(encoding, "raw") != 0)
return -EINVAL;
@@ -192,7 +202,9 @@ static int software_key_query(const struct kernel_pkey_params *params,
if (ret < 0)
goto error_free_tfm;
- len = crypto_sig_maxsize(sig);
+ len = crypto_sig_keysize(sig);
+ info->max_sig_size = crypto_sig_maxsize(sig);
+ info->max_data_size = crypto_sig_digestsize(sig);
info->supported_ops = KEYCTL_SUPPORTS_VERIFY;
if (pkey->key_is_private)
@@ -218,6 +230,8 @@ static int software_key_query(const struct kernel_pkey_params *params,
goto error_free_tfm;
len = crypto_akcipher_maxsize(tfm);
+ info->max_sig_size = len;
+ info->max_data_size = len;
info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT;
if (pkey->key_is_private)
@@ -225,40 +239,6 @@ static int software_key_query(const struct kernel_pkey_params *params,
}
info->key_size = len * 8;
-
- if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
- int slen = len;
- /*
- * ECDSA key sizes are much smaller than RSA, and thus could
- * operate on (hashed) inputs that are larger than key size.
- * For example SHA384-hashed input used with secp256r1
- * based keys. Set max_data_size to be at least as large as
- * the largest supported hash size (SHA512)
- */
- info->max_data_size = 64;
-
- /*
- * Verify takes ECDSA-Sig (described in RFC 5480) as input,
- * which is actually 2 'key_size'-bit integers encoded in
- * ASN.1. Account for the ASN.1 encoding overhead here.
- *
- * NIST P192/256/384 may prepend a '0' to a coordinate to
- * indicate a positive integer. NIST P521 never needs it.
- */
- if (strcmp(pkey->pkey_algo, "ecdsa-nist-p521") != 0)
- slen += 1;
- /* Length of encoding the x & y coordinates */
- slen = 2 * (slen + 2);
- /*
- * If coordinate encoding takes at least 128 bytes then an
- * additional byte for length encoding is needed.
- */
- info->max_sig_size = 1 + (slen >= 128) + 1 + slen;
- } else {
- info->max_data_size = len;
- info->max_sig_size = len;
- }
-
info->max_enc_size = len;
info->max_dec_size = len;
@@ -323,7 +303,7 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
if (ret)
goto error_free_tfm;
- ksz = crypto_sig_maxsize(sig);
+ ksz = crypto_sig_keysize(sig);
} else {
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
if (IS_ERR(tfm)) {
diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c
index 2deff81f8af5..041d04b5c953 100644
--- a/crypto/asymmetric_keys/signature.c
+++ b/crypto/asymmetric_keys/signature.c
@@ -65,69 +65,6 @@ int query_asymmetric_key(const struct kernel_pkey_params *params,
EXPORT_SYMBOL_GPL(query_asymmetric_key);
/**
- * encrypt_blob - Encrypt data using an asymmetric key
- * @params: Various parameters
- * @data: Data blob to be encrypted, length params->data_len
- * @enc: Encrypted data buffer, length params->enc_len
- *
- * Encrypt the specified data blob using the private key specified by
- * params->key. The encrypted data is wrapped in an encoding if
- * params->encoding is specified (eg. "pkcs1").
- *
- * Returns the length of the data placed in the encrypted data buffer or an
- * error.
- */
-int encrypt_blob(struct kernel_pkey_params *params,
- const void *data, void *enc)
-{
- params->op = kernel_pkey_encrypt;
- return asymmetric_key_eds_op(params, data, enc);
-}
-EXPORT_SYMBOL_GPL(encrypt_blob);
-
-/**
- * decrypt_blob - Decrypt data using an asymmetric key
- * @params: Various parameters
- * @enc: Encrypted data to be decrypted, length params->enc_len
- * @data: Decrypted data buffer, length params->data_len
- *
- * Decrypt the specified data blob using the private key specified by
- * params->key. The decrypted data is wrapped in an encoding if
- * params->encoding is specified (eg. "pkcs1").
- *
- * Returns the length of the data placed in the decrypted data buffer or an
- * error.
- */
-int decrypt_blob(struct kernel_pkey_params *params,
- const void *enc, void *data)
-{
- params->op = kernel_pkey_decrypt;
- return asymmetric_key_eds_op(params, enc, data);
-}
-EXPORT_SYMBOL_GPL(decrypt_blob);
-
-/**
- * create_signature - Sign some data using an asymmetric key
- * @params: Various parameters
- * @data: Data blob to be signed, length params->data_len
- * @enc: Signature buffer, length params->enc_len
- *
- * Sign the specified data blob using the private key specified by params->key.
- * The signature is wrapped in an encoding if params->encoding is specified
- * (eg. "pkcs1"). If the encoding needs to know the digest type, this can be
- * passed through params->hash_algo (eg. "sha1").
- *
- * Returns the length of the data placed in the signature buffer or an error.
- */
-int create_signature(struct kernel_pkey_params *params,
- const void *data, void *enc)
-{
- params->op = kernel_pkey_sign;
- return asymmetric_key_eds_op(params, data, enc);
-}
-EXPORT_SYMBOL_GPL(create_signature);
-
-/**
* verify_signature - Initiate the use of an asymmetric key to verify a signature
* @key: The asymmetric key to verify against
* @sig: The signature to check
diff --git a/crypto/crc32_generic.c b/crypto/crc32_generic.c
index d1251663ed66..6a55d206fab3 100644
--- a/crypto/crc32_generic.c
+++ b/crypto/crc32_generic.c
@@ -59,6 +59,15 @@ static int crc32_update(struct shash_desc *desc, const u8 *data,
{
u32 *crcp = shash_desc_ctx(desc);
+ *crcp = crc32_le_base(*crcp, data, len);
+ return 0;
+}
+
+static int crc32_update_arch(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ u32 *crcp = shash_desc_ctx(desc);
+
*crcp = crc32_le(*crcp, data, len);
return 0;
}
@@ -67,6 +76,13 @@ static int crc32_update(struct shash_desc *desc, const u8 *data,
static int __crc32_finup(u32 *crcp, const u8 *data, unsigned int len,
u8 *out)
{
+ put_unaligned_le32(crc32_le_base(*crcp, data, len), out);
+ return 0;
+}
+
+static int __crc32_finup_arch(u32 *crcp, const u8 *data, unsigned int len,
+ u8 *out)
+{
put_unaligned_le32(crc32_le(*crcp, data, len), out);
return 0;
}
@@ -77,6 +93,12 @@ static int crc32_finup(struct shash_desc *desc, const u8 *data,
return __crc32_finup(shash_desc_ctx(desc), data, len, out);
}
+static int crc32_finup_arch(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return __crc32_finup_arch(shash_desc_ctx(desc), data, len, out);
+}
+
static int crc32_final(struct shash_desc *desc, u8 *out)
{
u32 *crcp = shash_desc_ctx(desc);
@@ -88,38 +110,62 @@ static int crc32_final(struct shash_desc *desc, u8 *out)
static int crc32_digest(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
- return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len,
- out);
+ return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len, out);
}
-static struct shash_alg alg = {
- .setkey = crc32_setkey,
- .init = crc32_init,
- .update = crc32_update,
- .final = crc32_final,
- .finup = crc32_finup,
- .digest = crc32_digest,
- .descsize = sizeof(u32),
- .digestsize = CHKSUM_DIGEST_SIZE,
- .base = {
- .cra_name = "crc32",
- .cra_driver_name = "crc32-generic",
- .cra_priority = 100,
- .cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
- .cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_ctxsize = sizeof(u32),
- .cra_module = THIS_MODULE,
- .cra_init = crc32_cra_init,
- }
-};
+
+static int crc32_digest_arch(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ return __crc32_finup_arch(crypto_shash_ctx(desc->tfm), data, len, out);
+}
+
+static struct shash_alg algs[] = {{
+ .setkey = crc32_setkey,
+ .init = crc32_init,
+ .update = crc32_update,
+ .final = crc32_final,
+ .finup = crc32_finup,
+ .digest = crc32_digest,
+ .descsize = sizeof(u32),
+ .digestsize = CHKSUM_DIGEST_SIZE,
+
+ .base.cra_name = "crc32",
+ .base.cra_driver_name = "crc32-generic",
+ .base.cra_priority = 100,
+ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
+ .base.cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .base.cra_ctxsize = sizeof(u32),
+ .base.cra_module = THIS_MODULE,
+ .base.cra_init = crc32_cra_init,
+}, {
+ .setkey = crc32_setkey,
+ .init = crc32_init,
+ .update = crc32_update_arch,
+ .final = crc32_final,
+ .finup = crc32_finup_arch,
+ .digest = crc32_digest_arch,
+ .descsize = sizeof(u32),
+ .digestsize = CHKSUM_DIGEST_SIZE,
+
+ .base.cra_name = "crc32",
+ .base.cra_driver_name = "crc32-" __stringify(ARCH),
+ .base.cra_priority = 150,
+ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
+ .base.cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .base.cra_ctxsize = sizeof(u32),
+ .base.cra_module = THIS_MODULE,
+ .base.cra_init = crc32_cra_init,
+}};
static int __init crc32_mod_init(void)
{
- return crypto_register_shash(&alg);
+ /* register the arch flavor only if it differs from the generic one */
+ return crypto_register_shashes(algs, 1 + (&crc32_le != &crc32_le_base));
}
static void __exit crc32_mod_fini(void)
{
- crypto_unregister_shash(&alg);
+ crypto_unregister_shashes(algs, 1 + (&crc32_le != &crc32_le_base));
}
subsys_initcall(crc32_mod_init);
diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c
index a8c90b3f4c6c..7c2357c30fdf 100644
--- a/crypto/crc32c_generic.c
+++ b/crypto/crc32c_generic.c
@@ -85,6 +85,15 @@ static int chksum_update(struct shash_desc *desc, const u8 *data,
{
struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+ ctx->crc = __crc32c_le_base(ctx->crc, data, length);
+ return 0;
+}
+
+static int chksum_update_arch(struct shash_desc *desc, const u8 *data,
+ unsigned int length)
+{
+ struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+
ctx->crc = __crc32c_le(ctx->crc, data, length);
return 0;
}
@@ -99,6 +108,13 @@ static int chksum_final(struct shash_desc *desc, u8 *out)
static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
{
+ put_unaligned_le32(~__crc32c_le_base(*crcp, data, len), out);
+ return 0;
+}
+
+static int __chksum_finup_arch(u32 *crcp, const u8 *data, unsigned int len,
+ u8 *out)
+{
put_unaligned_le32(~__crc32c_le(*crcp, data, len), out);
return 0;
}
@@ -111,6 +127,14 @@ static int chksum_finup(struct shash_desc *desc, const u8 *data,
return __chksum_finup(&ctx->crc, data, len, out);
}
+static int chksum_finup_arch(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+
+ return __chksum_finup_arch(&ctx->crc, data, len, out);
+}
+
static int chksum_digest(struct shash_desc *desc, const u8 *data,
unsigned int length, u8 *out)
{
@@ -119,6 +143,14 @@ static int chksum_digest(struct shash_desc *desc, const u8 *data,
return __chksum_finup(&mctx->key, data, length, out);
}
+static int chksum_digest_arch(struct shash_desc *desc, const u8 *data,
+ unsigned int length, u8 *out)
+{
+ struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
+
+ return __chksum_finup_arch(&mctx->key, data, length, out);
+}
+
static int crc32c_cra_init(struct crypto_tfm *tfm)
{
struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
@@ -127,35 +159,53 @@ static int crc32c_cra_init(struct crypto_tfm *tfm)
return 0;
}
-static struct shash_alg alg = {
- .digestsize = CHKSUM_DIGEST_SIZE,
- .setkey = chksum_setkey,
- .init = chksum_init,
- .update = chksum_update,
- .final = chksum_final,
- .finup = chksum_finup,
- .digest = chksum_digest,
- .descsize = sizeof(struct chksum_desc_ctx),
- .base = {
- .cra_name = "crc32c",
- .cra_driver_name = "crc32c-generic",
- .cra_priority = 100,
- .cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
- .cra_blocksize = CHKSUM_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct chksum_ctx),
- .cra_module = THIS_MODULE,
- .cra_init = crc32c_cra_init,
- }
-};
+static struct shash_alg algs[] = {{
+ .digestsize = CHKSUM_DIGEST_SIZE,
+ .setkey = chksum_setkey,
+ .init = chksum_init,
+ .update = chksum_update,
+ .final = chksum_final,
+ .finup = chksum_finup,
+ .digest = chksum_digest,
+ .descsize = sizeof(struct chksum_desc_ctx),
+
+ .base.cra_name = "crc32c",
+ .base.cra_driver_name = "crc32c-generic",
+ .base.cra_priority = 100,
+ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
+ .base.cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .base.cra_ctxsize = sizeof(struct chksum_ctx),
+ .base.cra_module = THIS_MODULE,
+ .base.cra_init = crc32c_cra_init,
+}, {
+ .digestsize = CHKSUM_DIGEST_SIZE,
+ .setkey = chksum_setkey,
+ .init = chksum_init,
+ .update = chksum_update_arch,
+ .final = chksum_final,
+ .finup = chksum_finup_arch,
+ .digest = chksum_digest_arch,
+ .descsize = sizeof(struct chksum_desc_ctx),
+
+ .base.cra_name = "crc32c",
+ .base.cra_driver_name = "crc32c-" __stringify(ARCH),
+ .base.cra_priority = 150,
+ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
+ .base.cra_blocksize = CHKSUM_BLOCK_SIZE,
+ .base.cra_ctxsize = sizeof(struct chksum_ctx),
+ .base.cra_module = THIS_MODULE,
+ .base.cra_init = crc32c_cra_init,
+}};
static int __init crc32c_mod_init(void)
{
- return crypto_register_shash(&alg);
+ /* register the arch flavor only if it differs from the generic one */
+ return crypto_register_shashes(algs, 1 + (&__crc32c_le != &__crc32c_le_base));
}
static void __exit crc32c_mod_fini(void)
{
- crypto_unregister_shash(&alg);
+ crypto_unregister_shashes(algs, 1 + (&__crc32c_le != &__crc32c_le_base));
}
subsys_initcall(crc32c_mod_init);
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 3addce90930c..c323f40bed4f 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -101,6 +101,7 @@
#include <crypto/internal/cipher.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
+#include <linux/string_choices.h>
/***************************************************************
* Backend cipher definitions available to DRBG
@@ -1412,7 +1413,7 @@ static int drbg_generate(struct drbg_state *drbg,
if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) {
pr_devel("DRBG: reseeding before generation (prediction "
"resistance: %s, state %s)\n",
- drbg->pr ? "true" : "false",
+ str_true_false(drbg->pr),
(drbg->seeded == DRBG_SEED_STATE_FULL ?
"seeded" : "unseeded"));
/* 9.3.1 steps 7.1 through 7.3 */
@@ -1562,7 +1563,7 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
bool reseed = true;
pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
- "%s\n", coreref, pr ? "enabled" : "disabled");
+ "%s\n", coreref, str_enabled_disabled(pr));
mutex_lock(&drbg->drbg_mutex);
/* 9.1 step 1 is implicit with the selected DRBG type */
diff --git a/crypto/ecdsa-p1363.c b/crypto/ecdsa-p1363.c
new file mode 100644
index 000000000000..eaae7214d69b
--- /dev/null
+++ b/crypto/ecdsa-p1363.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ECDSA P1363 signature encoding
+ *
+ * Copyright (c) 2024 Intel Corporation
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <crypto/algapi.h>
+#include <crypto/sig.h>
+#include <crypto/internal/ecc.h>
+#include <crypto/internal/sig.h>
+
+struct ecdsa_p1363_ctx {
+ struct crypto_sig *child;
+};
+
+static int ecdsa_p1363_verify(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ const void *digest, unsigned int dlen)
+{
+ struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+ unsigned int keylen = crypto_sig_keysize(ctx->child);
+ unsigned int ndigits = DIV_ROUND_UP(keylen, sizeof(u64));
+ struct ecdsa_raw_sig sig;
+
+ if (slen != 2 * keylen)
+ return -EINVAL;
+
+ ecc_digits_from_bytes(src, keylen, sig.r, ndigits);
+ ecc_digits_from_bytes(src + keylen, keylen, sig.s, ndigits);
+
+ return crypto_sig_verify(ctx->child, &sig, sizeof(sig), digest, dlen);
+}
+
+static unsigned int ecdsa_p1363_key_size(struct crypto_sig *tfm)
+{
+ struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return crypto_sig_keysize(ctx->child);
+}
+
+static unsigned int ecdsa_p1363_max_size(struct crypto_sig *tfm)
+{
+ struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return 2 * crypto_sig_keysize(ctx->child);
+}
+
+static unsigned int ecdsa_p1363_digest_size(struct crypto_sig *tfm)
+{
+ struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return crypto_sig_digestsize(ctx->child);
+}
+
+static int ecdsa_p1363_set_pub_key(struct crypto_sig *tfm,
+ const void *key, unsigned int keylen)
+{
+ struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return crypto_sig_set_pubkey(ctx->child, key, keylen);
+}
+
+static int ecdsa_p1363_init_tfm(struct crypto_sig *tfm)
+{
+ struct sig_instance *inst = sig_alg_instance(tfm);
+ struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+ struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+ struct crypto_sig *child_tfm;
+
+ child_tfm = crypto_spawn_sig(spawn);
+ if (IS_ERR(child_tfm))
+ return PTR_ERR(child_tfm);
+
+ ctx->child = child_tfm;
+
+ return 0;
+}
+
+static void ecdsa_p1363_exit_tfm(struct crypto_sig *tfm)
+{
+ struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+ crypto_free_sig(ctx->child);
+}
+
+static void ecdsa_p1363_free(struct sig_instance *inst)
+{
+ struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+
+ crypto_drop_sig(spawn);
+ kfree(inst);
+}
+
+static int ecdsa_p1363_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+ struct crypto_sig_spawn *spawn;
+ struct sig_instance *inst;
+ struct sig_alg *ecdsa_alg;
+ u32 mask;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SIG, &mask);
+ if (err)
+ return err;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return -ENOMEM;
+
+ spawn = sig_instance_ctx(inst);
+
+ err = crypto_grab_sig(spawn, sig_crypto_instance(inst),
+ crypto_attr_alg_name(tb[1]), 0, mask);
+ if (err)
+ goto err_free_inst;
+
+ ecdsa_alg = crypto_spawn_sig_alg(spawn);
+
+ err = -EINVAL;
+ if (strncmp(ecdsa_alg->base.cra_name, "ecdsa", 5) != 0)
+ goto err_free_inst;
+
+ err = crypto_inst_setname(sig_crypto_instance(inst), tmpl->name,
+ &ecdsa_alg->base);
+ if (err)
+ goto err_free_inst;
+
+ inst->alg.base.cra_priority = ecdsa_alg->base.cra_priority;
+ inst->alg.base.cra_ctxsize = sizeof(struct ecdsa_p1363_ctx);
+
+ inst->alg.init = ecdsa_p1363_init_tfm;
+ inst->alg.exit = ecdsa_p1363_exit_tfm;
+
+ inst->alg.verify = ecdsa_p1363_verify;
+ inst->alg.key_size = ecdsa_p1363_key_size;
+ inst->alg.max_size = ecdsa_p1363_max_size;
+ inst->alg.digest_size = ecdsa_p1363_digest_size;
+ inst->alg.set_pub_key = ecdsa_p1363_set_pub_key;
+
+ inst->free = ecdsa_p1363_free;
+
+ err = sig_register_instance(tmpl, inst);
+ if (err) {
+err_free_inst:
+ ecdsa_p1363_free(inst);
+ }
+ return err;
+}
+
+struct crypto_template ecdsa_p1363_tmpl = {
+ .name = "p1363",
+ .create = ecdsa_p1363_create,
+ .module = THIS_MODULE,
+};
+
+MODULE_ALIAS_CRYPTO("p1363");
diff --git a/crypto/ecdsa-x962.c b/crypto/ecdsa-x962.c
new file mode 100644
index 000000000000..6a77c13e192b
--- /dev/null
+++ b/crypto/ecdsa-x962.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ECDSA X9.62 signature encoding
+ *
+ * Copyright (c) 2021 IBM Corporation
+ * Copyright (c) 2024 Intel Corporation
+ */
+
+#include <linux/asn1_decoder.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <crypto/algapi.h>
+#include <crypto/sig.h>
+#include <crypto/internal/ecc.h>
+#include <crypto/internal/sig.h>
+
+#include "ecdsasignature.asn1.h"
+
+struct ecdsa_x962_ctx {
+ struct crypto_sig *child;
+};
+
+struct ecdsa_x962_signature_ctx {
+ struct ecdsa_raw_sig sig;
+ unsigned int ndigits;
+};
+
+/* Get the r and s components of a signature from the X.509 certificate. */
+static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen,
+ unsigned int ndigits)
+{
+ size_t bufsize = ndigits * sizeof(u64);
+ const char *d = value;
+
+ if (!value || !vlen || vlen > bufsize + 1)
+ return -EINVAL;
+
+ /*
+ * vlen may be 1 byte larger than bufsize due to a leading zero byte
+ * (necessary if the most significant bit of the integer is set).
+ */
+ if (vlen > bufsize) {
+ /* skip over leading zeros that make 'value' a positive int */
+ if (*d == 0) {
+ vlen -= 1;
+ d++;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ ecc_digits_from_bytes(d, vlen, dest, ndigits);
+
+ return 0;
+}
+
+int ecdsa_get_signature_r(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct ecdsa_x962_signature_ctx *sig_ctx = context;
+
+ return ecdsa_get_signature_rs(sig_ctx->sig.r, hdrlen, tag, value, vlen,
+ sig_ctx->ndigits);
+}
+
+int ecdsa_get_signature_s(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct ecdsa_x962_signature_ctx *sig_ctx = context;
+
+ return ecdsa_get_signature_rs(sig_ctx->sig.s, hdrlen, tag, value, vlen,
+ sig_ctx->ndigits);
+}
+
+static int ecdsa_x962_verify(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ const void *digest, unsigned int dlen)
+{
+ struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+ struct ecdsa_x962_signature_ctx sig_ctx;
+ int err;
+
+ sig_ctx.ndigits = DIV_ROUND_UP(crypto_sig_keysize(ctx->child),
+ sizeof(u64));
+
+ err = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen);
+ if (err < 0)
+ return err;
+
+ return crypto_sig_verify(ctx->child, &sig_ctx.sig, sizeof(sig_ctx.sig),
+ digest, dlen);
+}
+
+static unsigned int ecdsa_x962_key_size(struct crypto_sig *tfm)
+{
+ struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return crypto_sig_keysize(ctx->child);
+}
+
+static unsigned int ecdsa_x962_max_size(struct crypto_sig *tfm)
+{
+ struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+ struct sig_alg *alg = crypto_sig_alg(ctx->child);
+ int slen = crypto_sig_keysize(ctx->child);
+
+ /*
+ * Verify takes ECDSA-Sig-Value (described in RFC 5480) as input,
+ * which is actually 2 'key_size'-bit integers encoded in ASN.1.
+ * Account for the ASN.1 encoding overhead here.
+ *
+ * NIST P192/256/384 may prepend a '0' to a coordinate to indicate
+ * a positive integer. NIST P521 never needs it.
+ */
+ if (strcmp(alg->base.cra_name, "ecdsa-nist-p521") != 0)
+ slen += 1;
+
+ /* Length of encoding the x & y coordinates */
+ slen = 2 * (slen + 2);
+
+ /*
+ * If coordinate encoding takes at least 128 bytes then an
+ * additional byte for length encoding is needed.
+ */
+ return 1 + (slen >= 128) + 1 + slen;
+}
+
+static unsigned int ecdsa_x962_digest_size(struct crypto_sig *tfm)
+{
+ struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return crypto_sig_digestsize(ctx->child);
+}
+
+static int ecdsa_x962_set_pub_key(struct crypto_sig *tfm,
+ const void *key, unsigned int keylen)
+{
+ struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return crypto_sig_set_pubkey(ctx->child, key, keylen);
+}
+
+static int ecdsa_x962_init_tfm(struct crypto_sig *tfm)
+{
+ struct sig_instance *inst = sig_alg_instance(tfm);
+ struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+ struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+ struct crypto_sig *child_tfm;
+
+ child_tfm = crypto_spawn_sig(spawn);
+ if (IS_ERR(child_tfm))
+ return PTR_ERR(child_tfm);
+
+ ctx->child = child_tfm;
+
+ return 0;
+}
+
+static void ecdsa_x962_exit_tfm(struct crypto_sig *tfm)
+{
+ struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+ crypto_free_sig(ctx->child);
+}
+
+static void ecdsa_x962_free(struct sig_instance *inst)
+{
+ struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+
+ crypto_drop_sig(spawn);
+ kfree(inst);
+}
+
+static int ecdsa_x962_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+ struct crypto_sig_spawn *spawn;
+ struct sig_instance *inst;
+ struct sig_alg *ecdsa_alg;
+ u32 mask;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SIG, &mask);
+ if (err)
+ return err;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ if (!inst)
+ return -ENOMEM;
+
+ spawn = sig_instance_ctx(inst);
+
+ err = crypto_grab_sig(spawn, sig_crypto_instance(inst),
+ crypto_attr_alg_name(tb[1]), 0, mask);
+ if (err)
+ goto err_free_inst;
+
+ ecdsa_alg = crypto_spawn_sig_alg(spawn);
+
+ err = -EINVAL;
+ if (strncmp(ecdsa_alg->base.cra_name, "ecdsa", 5) != 0)
+ goto err_free_inst;
+
+ err = crypto_inst_setname(sig_crypto_instance(inst), tmpl->name,
+ &ecdsa_alg->base);
+ if (err)
+ goto err_free_inst;
+
+ inst->alg.base.cra_priority = ecdsa_alg->base.cra_priority;
+ inst->alg.base.cra_ctxsize = sizeof(struct ecdsa_x962_ctx);
+
+ inst->alg.init = ecdsa_x962_init_tfm;
+ inst->alg.exit = ecdsa_x962_exit_tfm;
+
+ inst->alg.verify = ecdsa_x962_verify;
+ inst->alg.key_size = ecdsa_x962_key_size;
+ inst->alg.max_size = ecdsa_x962_max_size;
+ inst->alg.digest_size = ecdsa_x962_digest_size;
+ inst->alg.set_pub_key = ecdsa_x962_set_pub_key;
+
+ inst->free = ecdsa_x962_free;
+
+ err = sig_register_instance(tmpl, inst);
+ if (err) {
+err_free_inst:
+ ecdsa_x962_free(inst);
+ }
+ return err;
+}
+
+struct crypto_template ecdsa_x962_tmpl = {
+ .name = "x962",
+ .create = ecdsa_x962_create,
+ .module = THIS_MODULE,
+};
+
+MODULE_ALIAS_CRYPTO("x962");
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index d5a10959ec28..117526d15dde 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -4,14 +4,11 @@
*/
#include <linux/module.h>
-#include <crypto/internal/akcipher.h>
#include <crypto/internal/ecc.h>
-#include <crypto/akcipher.h>
+#include <crypto/internal/sig.h>
#include <crypto/ecdh.h>
-#include <linux/asn1_decoder.h>
-#include <linux/scatterlist.h>
-
-#include "ecdsasignature.asn1.h"
+#include <crypto/sha2.h>
+#include <crypto/sig.h>
struct ecc_ctx {
unsigned int curve_id;
@@ -23,66 +20,6 @@ struct ecc_ctx {
struct ecc_point pub_key;
};
-struct ecdsa_signature_ctx {
- const struct ecc_curve *curve;
- u64 r[ECC_MAX_DIGITS];
- u64 s[ECC_MAX_DIGITS];
-};
-
-/*
- * Get the r and s components of a signature from the X509 certificate.
- */
-static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen, unsigned int ndigits)
-{
- size_t bufsize = ndigits * sizeof(u64);
- ssize_t diff = vlen - bufsize;
- const char *d = value;
-
- if (!value || !vlen)
- return -EINVAL;
-
- /* diff = 0: 'value' has exacly the right size
- * diff > 0: 'value' has too many bytes; one leading zero is allowed that
- * makes the value a positive integer; error on more
- * diff < 0: 'value' is missing leading zeros
- */
- if (diff > 0) {
- /* skip over leading zeros that make 'value' a positive int */
- if (*d == 0) {
- vlen -= 1;
- diff--;
- d++;
- }
- if (diff)
- return -EINVAL;
- }
- if (-diff >= bufsize)
- return -EINVAL;
-
- ecc_digits_from_bytes(d, vlen, dest, ndigits);
-
- return 0;
-}
-
-int ecdsa_get_signature_r(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
-{
- struct ecdsa_signature_ctx *sig = context;
-
- return ecdsa_get_signature_rs(sig->r, hdrlen, tag, value, vlen,
- sig->curve->g.ndigits);
-}
-
-int ecdsa_get_signature_s(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
-{
- struct ecdsa_signature_ctx *sig = context;
-
- return ecdsa_get_signature_rs(sig->s, hdrlen, tag, value, vlen,
- sig->curve->g.ndigits);
-}
-
static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, const u64 *s)
{
const struct ecc_curve *curve = ctx->curve;
@@ -126,46 +63,27 @@ static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, con
/*
* Verify an ECDSA signature.
*/
-static int ecdsa_verify(struct akcipher_request *req)
+static int ecdsa_verify(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ const void *digest, unsigned int dlen)
{
- struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
size_t bufsize = ctx->curve->g.ndigits * sizeof(u64);
- struct ecdsa_signature_ctx sig_ctx = {
- .curve = ctx->curve,
- };
+ const struct ecdsa_raw_sig *sig = src;
u64 hash[ECC_MAX_DIGITS];
- unsigned char *buffer;
- int ret;
if (unlikely(!ctx->pub_key_set))
return -EINVAL;
- buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- sg_pcopy_to_buffer(req->src,
- sg_nents_for_len(req->src, req->src_len + req->dst_len),
- buffer, req->src_len + req->dst_len, 0);
-
- ret = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx,
- buffer, req->src_len);
- if (ret < 0)
- goto error;
-
- if (bufsize > req->dst_len)
- bufsize = req->dst_len;
-
- ecc_digits_from_bytes(buffer + req->src_len, bufsize,
- hash, ctx->curve->g.ndigits);
+ if (slen != sizeof(*sig))
+ return -EINVAL;
- ret = _ecdsa_verify(ctx, hash, sig_ctx.r, sig_ctx.s);
+ if (bufsize > dlen)
+ bufsize = dlen;
-error:
- kfree(buffer);
+ ecc_digits_from_bytes(digest, bufsize, hash, ctx->curve->g.ndigits);
- return ret;
+ return _ecdsa_verify(ctx, hash, sig->r, sig->s);
}
static int ecdsa_ecc_ctx_init(struct ecc_ctx *ctx, unsigned int curve_id)
@@ -201,9 +119,10 @@ static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx)
* Set the public ECC key as defined by RFC5480 section 2.2 "Subject Public
* Key". Only the uncompressed format is supported.
*/
-static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
+static int ecdsa_set_pub_key(struct crypto_sig *tfm, const void *key,
+ unsigned int keylen)
{
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
unsigned int digitlen, ndigits;
const unsigned char *d = key;
int ret;
@@ -237,31 +156,43 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
return ret;
}
-static void ecdsa_exit_tfm(struct crypto_akcipher *tfm)
+static void ecdsa_exit_tfm(struct crypto_sig *tfm)
{
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
ecdsa_ecc_ctx_deinit(ctx);
}
-static unsigned int ecdsa_max_size(struct crypto_akcipher *tfm)
+static unsigned int ecdsa_key_size(struct crypto_sig *tfm)
{
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
return DIV_ROUND_UP(ctx->curve->nbits, 8);
}
-static int ecdsa_nist_p521_init_tfm(struct crypto_akcipher *tfm)
+static unsigned int ecdsa_digest_size(struct crypto_sig *tfm)
{
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ /*
+ * ECDSA key sizes are much smaller than RSA, and thus could
+ * operate on (hashed) inputs that are larger than the key size.
+ * E.g. SHA384-hashed input used with secp256r1 based keys.
+ * Return the largest supported hash size (SHA512).
+ */
+ return SHA512_DIGEST_SIZE;
+}
+
+static int ecdsa_nist_p521_init_tfm(struct crypto_sig *tfm)
+{
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P521);
}
-static struct akcipher_alg ecdsa_nist_p521 = {
+static struct sig_alg ecdsa_nist_p521 = {
.verify = ecdsa_verify,
.set_pub_key = ecdsa_set_pub_key,
- .max_size = ecdsa_max_size,
+ .key_size = ecdsa_key_size,
+ .digest_size = ecdsa_digest_size,
.init = ecdsa_nist_p521_init_tfm,
.exit = ecdsa_exit_tfm,
.base = {
@@ -273,17 +204,18 @@ static struct akcipher_alg ecdsa_nist_p521 = {
},
};
-static int ecdsa_nist_p384_init_tfm(struct crypto_akcipher *tfm)
+static int ecdsa_nist_p384_init_tfm(struct crypto_sig *tfm)
{
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P384);
}
-static struct akcipher_alg ecdsa_nist_p384 = {
+static struct sig_alg ecdsa_nist_p384 = {
.verify = ecdsa_verify,
.set_pub_key = ecdsa_set_pub_key,
- .max_size = ecdsa_max_size,
+ .key_size = ecdsa_key_size,
+ .digest_size = ecdsa_digest_size,
.init = ecdsa_nist_p384_init_tfm,
.exit = ecdsa_exit_tfm,
.base = {
@@ -295,17 +227,18 @@ static struct akcipher_alg ecdsa_nist_p384 = {
},
};
-static int ecdsa_nist_p256_init_tfm(struct crypto_akcipher *tfm)
+static int ecdsa_nist_p256_init_tfm(struct crypto_sig *tfm)
{
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P256);
}
-static struct akcipher_alg ecdsa_nist_p256 = {
+static struct sig_alg ecdsa_nist_p256 = {
.verify = ecdsa_verify,
.set_pub_key = ecdsa_set_pub_key,
- .max_size = ecdsa_max_size,
+ .key_size = ecdsa_key_size,
+ .digest_size = ecdsa_digest_size,
.init = ecdsa_nist_p256_init_tfm,
.exit = ecdsa_exit_tfm,
.base = {
@@ -317,17 +250,18 @@ static struct akcipher_alg ecdsa_nist_p256 = {
},
};
-static int ecdsa_nist_p192_init_tfm(struct crypto_akcipher *tfm)
+static int ecdsa_nist_p192_init_tfm(struct crypto_sig *tfm)
{
- struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P192);
}
-static struct akcipher_alg ecdsa_nist_p192 = {
+static struct sig_alg ecdsa_nist_p192 = {
.verify = ecdsa_verify,
.set_pub_key = ecdsa_set_pub_key,
- .max_size = ecdsa_max_size,
+ .key_size = ecdsa_key_size,
+ .digest_size = ecdsa_digest_size,
.init = ecdsa_nist_p192_init_tfm,
.exit = ecdsa_exit_tfm,
.base = {
@@ -345,42 +279,59 @@ static int __init ecdsa_init(void)
int ret;
/* NIST p192 may not be available in FIPS mode */
- ret = crypto_register_akcipher(&ecdsa_nist_p192);
+ ret = crypto_register_sig(&ecdsa_nist_p192);
ecdsa_nist_p192_registered = ret == 0;
- ret = crypto_register_akcipher(&ecdsa_nist_p256);
+ ret = crypto_register_sig(&ecdsa_nist_p256);
if (ret)
goto nist_p256_error;
- ret = crypto_register_akcipher(&ecdsa_nist_p384);
+ ret = crypto_register_sig(&ecdsa_nist_p384);
if (ret)
goto nist_p384_error;
- ret = crypto_register_akcipher(&ecdsa_nist_p521);
+ ret = crypto_register_sig(&ecdsa_nist_p521);
if (ret)
goto nist_p521_error;
+ ret = crypto_register_template(&ecdsa_x962_tmpl);
+ if (ret)
+ goto x962_tmpl_error;
+
+ ret = crypto_register_template(&ecdsa_p1363_tmpl);
+ if (ret)
+ goto p1363_tmpl_error;
+
return 0;
+p1363_tmpl_error:
+ crypto_unregister_template(&ecdsa_x962_tmpl);
+
+x962_tmpl_error:
+ crypto_unregister_sig(&ecdsa_nist_p521);
+
nist_p521_error:
- crypto_unregister_akcipher(&ecdsa_nist_p384);
+ crypto_unregister_sig(&ecdsa_nist_p384);
nist_p384_error:
- crypto_unregister_akcipher(&ecdsa_nist_p256);
+ crypto_unregister_sig(&ecdsa_nist_p256);
nist_p256_error:
if (ecdsa_nist_p192_registered)
- crypto_unregister_akcipher(&ecdsa_nist_p192);
+ crypto_unregister_sig(&ecdsa_nist_p192);
return ret;
}
static void __exit ecdsa_exit(void)
{
+ crypto_unregister_template(&ecdsa_x962_tmpl);
+ crypto_unregister_template(&ecdsa_p1363_tmpl);
+
if (ecdsa_nist_p192_registered)
- crypto_unregister_akcipher(&ecdsa_nist_p192);
- crypto_unregister_akcipher(&ecdsa_nist_p256);
- crypto_unregister_akcipher(&ecdsa_nist_p384);
- crypto_unregister_akcipher(&ecdsa_nist_p521);
+ crypto_unregister_sig(&ecdsa_nist_p192);
+ crypto_unregister_sig(&ecdsa_nist_p256);
+ crypto_unregister_sig(&ecdsa_nist_p384);
+ crypto_unregister_sig(&ecdsa_nist_p521);
}
subsys_initcall(ecdsa_init);
diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c
index 3811f3805b5d..b3dd8a3ddeb7 100644
--- a/crypto/ecrdsa.c
+++ b/crypto/ecrdsa.c
@@ -18,12 +18,11 @@
#include <linux/module.h>
#include <linux/crypto.h>
+#include <crypto/sig.h>
#include <crypto/streebog.h>
-#include <crypto/internal/akcipher.h>
#include <crypto/internal/ecc.h>
-#include <crypto/akcipher.h>
+#include <crypto/internal/sig.h>
#include <linux/oid_registry.h>
-#include <linux/scatterlist.h>
#include "ecrdsa_params.asn1.h"
#include "ecrdsa_pub_key.asn1.h"
#include "ecrdsa_defs.h"
@@ -68,13 +67,12 @@ static const struct ecc_curve *get_curve_by_oid(enum OID oid)
}
}
-static int ecrdsa_verify(struct akcipher_request *req)
+static int ecrdsa_verify(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ const void *digest, unsigned int dlen)
{
- struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
- unsigned char sig[ECRDSA_MAX_SIG_SIZE];
- unsigned char digest[STREEBOG512_DIGEST_SIZE];
- unsigned int ndigits = req->dst_len / sizeof(u64);
+ struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
+ unsigned int ndigits = dlen / sizeof(u64);
u64 r[ECRDSA_MAX_DIGITS]; /* witness (r) */
u64 _r[ECRDSA_MAX_DIGITS]; /* -r */
u64 s[ECRDSA_MAX_DIGITS]; /* second part of sig (s) */
@@ -91,25 +89,19 @@ static int ecrdsa_verify(struct akcipher_request *req)
*/
if (!ctx->curve ||
!ctx->digest ||
- !req->src ||
+ !src ||
+ !digest ||
!ctx->pub_key.x ||
- req->dst_len != ctx->digest_len ||
- req->dst_len != ctx->curve->g.ndigits * sizeof(u64) ||
+ dlen != ctx->digest_len ||
+ dlen != ctx->curve->g.ndigits * sizeof(u64) ||
ctx->pub_key.ndigits != ctx->curve->g.ndigits ||
- req->dst_len * 2 != req->src_len ||
- WARN_ON(req->src_len > sizeof(sig)) ||
- WARN_ON(req->dst_len > sizeof(digest)))
+ dlen * 2 != slen ||
+ WARN_ON(slen > ECRDSA_MAX_SIG_SIZE) ||
+ WARN_ON(dlen > STREEBOG512_DIGEST_SIZE))
return -EBADMSG;
- sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, req->src_len),
- sig, req->src_len);
- sg_pcopy_to_buffer(req->src,
- sg_nents_for_len(req->src,
- req->src_len + req->dst_len),
- digest, req->dst_len, req->src_len);
-
- vli_from_be64(s, sig, ndigits);
- vli_from_be64(r, sig + ndigits * sizeof(u64), ndigits);
+ vli_from_be64(s, src, ndigits);
+ vli_from_be64(r, src + ndigits * sizeof(u64), ndigits);
/* Step 1: verify that 0 < r < q, 0 < s < q */
if (vli_is_zero(r, ndigits) ||
@@ -188,10 +180,10 @@ static u8 *ecrdsa_unpack_u32(u32 *dst, void *src)
}
/* Parse BER encoded subjectPublicKey. */
-static int ecrdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+static int ecrdsa_set_pub_key(struct crypto_sig *tfm, const void *key,
unsigned int keylen)
{
- struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
unsigned int ndigits;
u32 algo, paramlen;
u8 *params;
@@ -249,9 +241,9 @@ static int ecrdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
return 0;
}
-static unsigned int ecrdsa_max_size(struct crypto_akcipher *tfm)
+static unsigned int ecrdsa_key_size(struct crypto_sig *tfm)
{
- struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
/*
* Verify doesn't need any output, so it's just informational
@@ -260,13 +252,21 @@ static unsigned int ecrdsa_max_size(struct crypto_akcipher *tfm)
return ctx->pub_key.ndigits * sizeof(u64);
}
-static void ecrdsa_exit_tfm(struct crypto_akcipher *tfm)
+static unsigned int ecrdsa_max_size(struct crypto_sig *tfm)
+{
+ struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return 2 * ctx->pub_key.ndigits * sizeof(u64);
+}
+
+static void ecrdsa_exit_tfm(struct crypto_sig *tfm)
{
}
-static struct akcipher_alg ecrdsa_alg = {
+static struct sig_alg ecrdsa_alg = {
.verify = ecrdsa_verify,
.set_pub_key = ecrdsa_set_pub_key,
+ .key_size = ecrdsa_key_size,
.max_size = ecrdsa_max_size,
.exit = ecrdsa_exit_tfm,
.base = {
@@ -280,12 +280,12 @@ static struct akcipher_alg ecrdsa_alg = {
static int __init ecrdsa_mod_init(void)
{
- return crypto_register_akcipher(&ecrdsa_alg);
+ return crypto_register_sig(&ecrdsa_alg);
}
static void __exit ecrdsa_mod_fini(void)
{
- crypto_unregister_akcipher(&ecrdsa_alg);
+ crypto_unregister_sig(&ecrdsa_alg);
}
module_init(ecrdsa_mod_init);
diff --git a/crypto/internal.h b/crypto/internal.h
index 711a6a5bfa2b..46b661be0f90 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -22,8 +22,6 @@
#include <linux/sched.h>
#include <linux/types.h>
-struct akcipher_request;
-struct crypto_akcipher;
struct crypto_instance;
struct crypto_template;
@@ -35,19 +33,6 @@ struct crypto_larval {
bool test_started;
};
-struct crypto_akcipher_sync_data {
- struct crypto_akcipher *tfm;
- const void *src;
- void *dst;
- unsigned int slen;
- unsigned int dlen;
-
- struct akcipher_request *req;
- struct crypto_wait cwait;
- struct scatterlist sg;
- u8 *buf;
-};
-
enum {
CRYPTOA_UNSPEC,
CRYPTOA_ALG,
@@ -129,10 +114,6 @@ void *crypto_create_tfm_node(struct crypto_alg *alg,
void *crypto_clone_tfm(const struct crypto_type *frontend,
struct crypto_tfm *otfm);
-int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data);
-int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err);
-int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm);
-
static inline void *crypto_create_tfm(struct crypto_alg *alg,
const struct crypto_type *frontend)
{
diff --git a/crypto/jitterentropy-testing.c b/crypto/jitterentropy-testing.c
index 5cb6a77b8e3b..21c9d7c3269a 100644
--- a/crypto/jitterentropy-testing.c
+++ b/crypto/jitterentropy-testing.c
@@ -15,7 +15,7 @@
#define JENT_TEST_RINGBUFFER_MASK (JENT_TEST_RINGBUFFER_SIZE - 1)
struct jent_testing {
- u32 jent_testing_rb[JENT_TEST_RINGBUFFER_SIZE];
+ u64 jent_testing_rb[JENT_TEST_RINGBUFFER_SIZE];
u32 rb_reader;
atomic_t rb_writer;
atomic_t jent_testing_enabled;
@@ -72,7 +72,7 @@ static void jent_testing_fini(struct jent_testing *data, u32 boot)
pr_warn("Disabling data collection\n");
}
-static bool jent_testing_store(struct jent_testing *data, u32 value,
+static bool jent_testing_store(struct jent_testing *data, u64 value,
u32 *boot)
{
unsigned long flags;
@@ -156,20 +156,20 @@ static int jent_testing_reader(struct jent_testing *data, u32 *boot,
}
/* We copy out word-wise */
- if (outbuflen < sizeof(u32)) {
+ if (outbuflen < sizeof(u64)) {
spin_unlock_irqrestore(&data->lock, flags);
goto out;
}
memcpy(outbuf, &data->jent_testing_rb[data->rb_reader],
- sizeof(u32));
+ sizeof(u64));
data->rb_reader++;
spin_unlock_irqrestore(&data->lock, flags);
- outbuf += sizeof(u32);
- outbuflen -= sizeof(u32);
- collected_data += sizeof(u32);
+ outbuf += sizeof(u64);
+ outbuflen -= sizeof(u64);
+ collected_data += sizeof(u64);
}
out:
@@ -189,16 +189,17 @@ static int jent_testing_extract_user(struct file *file, char __user *buf,
/*
* The intention of this interface is for collecting at least
- * 1000 samples due to the SP800-90B requirements. So, we make no
- * effort in avoiding allocating more memory that actually needed
- * by the user. Hence, we allocate sufficient memory to always hold
- * that amount of data.
+ * 1000 samples due to the SP800-90B requirements. However, due to
+ * memory and performance constraints, it is not desirable to allocate
+ * 8000 bytes of memory. Instead, we allocate space for only 125
+ * samples, which will allow the user to collect all 1000 samples using
+ * 8 calls to this interface.
*/
- tmp = kmalloc(JENT_TEST_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
+ tmp = kmalloc(125 * sizeof(u64) + sizeof(u64), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
- tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
+ tmp_aligned = PTR_ALIGN(tmp, sizeof(u64));
while (nbytes) {
int i;
@@ -212,7 +213,7 @@ static int jent_testing_extract_user(struct file *file, char __user *buf,
schedule();
}
- i = min_t(int, nbytes, JENT_TEST_RINGBUFFER_SIZE);
+ i = min_t(int, nbytes, 125 * sizeof(u64));
i = reader(tmp_aligned, i);
if (i <= 0) {
if (i < 0)
@@ -251,7 +252,7 @@ static struct jent_testing jent_raw_hires = {
.read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(jent_raw_hires.read_wait)
};
-int jent_raw_hires_entropy_store(__u32 value)
+int jent_raw_hires_entropy_store(__u64 value)
{
return jent_testing_store(&jent_raw_hires, value, &boot_raw_hires_test);
}
diff --git a/crypto/jitterentropy.h b/crypto/jitterentropy.h
index aa4728675ae2..4c5dbf2a8d8f 100644
--- a/crypto/jitterentropy.h
+++ b/crypto/jitterentropy.h
@@ -22,11 +22,11 @@ extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
#ifdef CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE
-int jent_raw_hires_entropy_store(__u32 value);
+int jent_raw_hires_entropy_store(__u64 value);
void jent_testing_init(void);
void jent_testing_exit(void);
#else /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */
-static inline int jent_raw_hires_entropy_store(__u32 value) { return 0; }
+static inline int jent_raw_hires_entropy_store(__u64 value) { return 0; }
static inline void jent_testing_init(void) { }
static inline void jent_testing_exit(void) { }
#endif /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
index d0d954fe9d54..7fc79e7dce44 100644
--- a/crypto/pcrypt.c
+++ b/crypto/pcrypt.c
@@ -117,8 +117,10 @@ static int pcrypt_aead_encrypt(struct aead_request *req)
err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu);
if (!err)
return -EINPROGRESS;
- if (err == -EBUSY)
- return -EAGAIN;
+ if (err == -EBUSY) {
+ /* try non-parallel mode */
+ return crypto_aead_encrypt(creq);
+ }
return err;
}
@@ -166,8 +168,10 @@ static int pcrypt_aead_decrypt(struct aead_request *req)
err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu);
if (!err)
return -EINPROGRESS;
- if (err == -EBUSY)
- return -EAGAIN;
+ if (err == -EBUSY) {
+ /* try non-parallel mode */
+ return crypto_aead_decrypt(creq);
+ }
return err;
}
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index cd501195f34a..50bdb18e7b48 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -16,101 +16,6 @@
#include <linux/random.h>
#include <linux/scatterlist.h>
-/*
- * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
- */
-static const u8 rsa_digest_info_md5[] = {
- 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
- 0x05, 0x00, 0x04, 0x10
-};
-
-static const u8 rsa_digest_info_sha1[] = {
- 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
- 0x2b, 0x0e, 0x03, 0x02, 0x1a,
- 0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 rsa_digest_info_rmd160[] = {
- 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
- 0x2b, 0x24, 0x03, 0x02, 0x01,
- 0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 rsa_digest_info_sha224[] = {
- 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
- 0x05, 0x00, 0x04, 0x1c
-};
-
-static const u8 rsa_digest_info_sha256[] = {
- 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
- 0x05, 0x00, 0x04, 0x20
-};
-
-static const u8 rsa_digest_info_sha384[] = {
- 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
- 0x05, 0x00, 0x04, 0x30
-};
-
-static const u8 rsa_digest_info_sha512[] = {
- 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
- 0x05, 0x00, 0x04, 0x40
-};
-
-static const u8 rsa_digest_info_sha3_256[] = {
- 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08,
- 0x05, 0x00, 0x04, 0x20
-};
-
-static const u8 rsa_digest_info_sha3_384[] = {
- 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09,
- 0x05, 0x00, 0x04, 0x30
-};
-
-static const u8 rsa_digest_info_sha3_512[] = {
- 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A,
- 0x05, 0x00, 0x04, 0x40
-};
-
-static const struct rsa_asn1_template {
- const char *name;
- const u8 *data;
- size_t size;
-} rsa_asn1_templates[] = {
-#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
- _(md5),
- _(sha1),
- _(rmd160),
- _(sha256),
- _(sha384),
- _(sha512),
- _(sha224),
-#undef _
-#define _(X) { "sha3-" #X, rsa_digest_info_sha3_##X, sizeof(rsa_digest_info_sha3_##X) }
- _(256),
- _(384),
- _(512),
-#undef _
- { NULL }
-};
-
-static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
-{
- const struct rsa_asn1_template *p;
-
- for (p = rsa_asn1_templates; p->name; p++)
- if (strcmp(name, p->name) == 0)
- return p;
- return NULL;
-}
-
struct pkcs1pad_ctx {
struct crypto_akcipher *child;
unsigned int key_size;
@@ -118,7 +23,6 @@ struct pkcs1pad_ctx {
struct pkcs1pad_inst_ctx {
struct crypto_akcipher_spawn spawn;
- const struct rsa_asn1_template *digest_info;
};
struct pkcs1pad_request {
@@ -131,42 +35,16 @@ static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
- int err;
-
- ctx->key_size = 0;
-
- err = crypto_akcipher_set_pub_key(ctx->child, key, keylen);
- if (err)
- return err;
-
- /* Find out new modulus size from rsa implementation */
- err = crypto_akcipher_maxsize(ctx->child);
- if (err > PAGE_SIZE)
- return -ENOTSUPP;
- ctx->key_size = err;
- return 0;
+ return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
}
static int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
- int err;
-
- ctx->key_size = 0;
-
- err = crypto_akcipher_set_priv_key(ctx->child, key, keylen);
- if (err)
- return err;
- /* Find out new modulus size from rsa implementation */
- err = crypto_akcipher_maxsize(ctx->child);
- if (err > PAGE_SIZE)
- return -ENOTSUPP;
-
- ctx->key_size = err;
- return 0;
+ return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
}
static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
@@ -174,9 +52,9 @@ static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
/*
- * The maximum destination buffer size for the encrypt/sign operations
+ * The maximum destination buffer size for the encrypt operation
* will be the same as for RSA, even though it's smaller for
- * decrypt/verify.
+ * decrypt.
*/
return ctx->key_size;
@@ -194,7 +72,7 @@ static void pkcs1pad_sg_set_buf(struct scatterlist *sg, void *buf, size_t len,
sg_chain(sg, nsegs, next);
}
-static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
+static int pkcs1pad_encrypt_complete(struct akcipher_request *req, int err)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
@@ -233,14 +111,14 @@ out:
return err;
}
-static void pkcs1pad_encrypt_sign_complete_cb(void *data, int err)
+static void pkcs1pad_encrypt_complete_cb(void *data, int err)
{
struct akcipher_request *req = data;
if (err == -EINPROGRESS)
goto out;
- err = pkcs1pad_encrypt_sign_complete(req, err);
+ err = pkcs1pad_encrypt_complete(req, err);
out:
akcipher_request_complete(req, err);
@@ -281,7 +159,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
- pkcs1pad_encrypt_sign_complete_cb, req);
+ pkcs1pad_encrypt_complete_cb, req);
/* Reuse output buffer */
akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
@@ -289,7 +167,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
err = crypto_akcipher_encrypt(&req_ctx->child_req);
if (err != -EINPROGRESS && err != -EBUSY)
- return pkcs1pad_encrypt_sign_complete(req, err);
+ return pkcs1pad_encrypt_complete(req, err);
return err;
}
@@ -394,195 +272,6 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
return err;
}
-static int pkcs1pad_sign(struct akcipher_request *req)
-{
- struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
- struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
- struct akcipher_instance *inst = akcipher_alg_instance(tfm);
- struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
- const struct rsa_asn1_template *digest_info = ictx->digest_info;
- int err;
- unsigned int ps_end, digest_info_size = 0;
-
- if (!ctx->key_size)
- return -EINVAL;
-
- if (digest_info)
- digest_info_size = digest_info->size;
-
- if (req->src_len + digest_info_size > ctx->key_size - 11)
- return -EOVERFLOW;
-
- if (req->dst_len < ctx->key_size) {
- req->dst_len = ctx->key_size;
- return -EOVERFLOW;
- }
-
- req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
- GFP_KERNEL);
- if (!req_ctx->in_buf)
- return -ENOMEM;
-
- ps_end = ctx->key_size - digest_info_size - req->src_len - 2;
- req_ctx->in_buf[0] = 0x01;
- memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
- req_ctx->in_buf[ps_end] = 0x00;
-
- if (digest_info)
- memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
- digest_info->size);
-
- pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
- ctx->key_size - 1 - req->src_len, req->src);
-
- akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
- akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
- pkcs1pad_encrypt_sign_complete_cb, req);
-
- /* Reuse output buffer */
- akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
- req->dst, ctx->key_size - 1, req->dst_len);
-
- err = crypto_akcipher_decrypt(&req_ctx->child_req);
- if (err != -EINPROGRESS && err != -EBUSY)
- return pkcs1pad_encrypt_sign_complete(req, err);
-
- return err;
-}
-
-static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
-{
- struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
- struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
- struct akcipher_instance *inst = akcipher_alg_instance(tfm);
- struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
- const struct rsa_asn1_template *digest_info = ictx->digest_info;
- const unsigned int sig_size = req->src_len;
- const unsigned int digest_size = req->dst_len;
- unsigned int dst_len;
- unsigned int pos;
- u8 *out_buf;
-
- if (err)
- goto done;
-
- err = -EINVAL;
- dst_len = req_ctx->child_req.dst_len;
- if (dst_len < ctx->key_size - 1)
- goto done;
-
- out_buf = req_ctx->out_buf;
- if (dst_len == ctx->key_size) {
- if (out_buf[0] != 0x00)
- /* Decrypted value had no leading 0 byte */
- goto done;
-
- dst_len--;
- out_buf++;
- }
-
- err = -EBADMSG;
- if (out_buf[0] != 0x01)
- goto done;
-
- for (pos = 1; pos < dst_len; pos++)
- if (out_buf[pos] != 0xff)
- break;
-
- if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00)
- goto done;
- pos++;
-
- if (digest_info) {
- if (digest_info->size > dst_len - pos)
- goto done;
- if (crypto_memneq(out_buf + pos, digest_info->data,
- digest_info->size))
- goto done;
-
- pos += digest_info->size;
- }
-
- err = 0;
-
- if (digest_size != dst_len - pos) {
- err = -EKEYREJECTED;
- req->dst_len = dst_len - pos;
- goto done;
- }
- /* Extract appended digest. */
- sg_pcopy_to_buffer(req->src,
- sg_nents_for_len(req->src, sig_size + digest_size),
- req_ctx->out_buf + ctx->key_size,
- digest_size, sig_size);
- /* Do the actual verification step. */
- if (memcmp(req_ctx->out_buf + ctx->key_size, out_buf + pos,
- digest_size) != 0)
- err = -EKEYREJECTED;
-done:
- kfree_sensitive(req_ctx->out_buf);
-
- return err;
-}
-
-static void pkcs1pad_verify_complete_cb(void *data, int err)
-{
- struct akcipher_request *req = data;
-
- if (err == -EINPROGRESS)
- goto out;
-
- err = pkcs1pad_verify_complete(req, err);
-
-out:
- akcipher_request_complete(req, err);
-}
-
-/*
- * The verify operation is here for completeness similar to the verification
- * defined in RFC2313 section 10.2 except that block type 0 is not accepted,
- * as in RFC2437. RFC2437 section 9.2 doesn't define any operation to
- * retrieve the DigestInfo from a signature, instead the user is expected
- * to call the sign operation to generate the expected signature and compare
- * signatures instead of the message-digests.
- */
-static int pkcs1pad_verify(struct akcipher_request *req)
-{
- struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
- struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
- const unsigned int sig_size = req->src_len;
- const unsigned int digest_size = req->dst_len;
- int err;
-
- if (WARN_ON(req->dst) || WARN_ON(!digest_size) ||
- !ctx->key_size || sig_size != ctx->key_size)
- return -EINVAL;
-
- req_ctx->out_buf = kmalloc(ctx->key_size + digest_size, GFP_KERNEL);
- if (!req_ctx->out_buf)
- return -ENOMEM;
-
- pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
- ctx->key_size, NULL);
-
- akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
- akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
- pkcs1pad_verify_complete_cb, req);
-
- /* Reuse input buffer, output to a new buffer */
- akcipher_request_set_crypt(&req_ctx->child_req, req->src,
- req_ctx->out_sg, sig_size, ctx->key_size);
-
- err = crypto_akcipher_encrypt(&req_ctx->child_req);
- if (err != -EINPROGRESS && err != -EBUSY)
- return pkcs1pad_verify_complete(req, err);
-
- return err;
-}
-
static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
{
struct akcipher_instance *inst = akcipher_alg_instance(tfm);
@@ -624,7 +313,6 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
struct akcipher_instance *inst;
struct pkcs1pad_inst_ctx *ctx;
struct akcipher_alg *rsa_alg;
- const char *hash_name;
int err;
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AKCIPHER, &mask);
@@ -650,36 +338,15 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
}
err = -ENAMETOOLONG;
- hash_name = crypto_attr_alg_name(tb[2]);
- if (IS_ERR(hash_name)) {
- if (snprintf(inst->alg.base.cra_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
- rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
-
- if (snprintf(inst->alg.base.cra_driver_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
- rsa_alg->base.cra_driver_name) >=
- CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
- } else {
- ctx->digest_info = rsa_lookup_asn1(hash_name);
- if (!ctx->digest_info) {
- err = -EINVAL;
- goto err_free_inst;
- }
-
- if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
- "pkcs1pad(%s,%s)", rsa_alg->base.cra_name,
- hash_name) >= CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
-
- if (snprintf(inst->alg.base.cra_driver_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
- rsa_alg->base.cra_driver_name,
- hash_name) >= CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
- }
+ if (snprintf(inst->alg.base.cra_name,
+ CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+ rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ if (snprintf(inst->alg.base.cra_driver_name,
+ CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+ rsa_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);
@@ -689,8 +356,6 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.encrypt = pkcs1pad_encrypt;
inst->alg.decrypt = pkcs1pad_decrypt;
- inst->alg.sign = pkcs1pad_sign;
- inst->alg.verify = pkcs1pad_verify;
inst->alg.set_pub_key = pkcs1pad_set_pub_key;
inst->alg.set_priv_key = pkcs1pad_set_priv_key;
inst->alg.max_size = pkcs1pad_get_max_size;
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 78b28d14ced3..b7d21529c552 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -407,16 +407,25 @@ static int __init rsa_init(void)
return err;
err = crypto_register_template(&rsa_pkcs1pad_tmpl);
- if (err) {
- crypto_unregister_akcipher(&rsa);
- return err;
- }
+ if (err)
+ goto err_unregister_rsa;
+
+ err = crypto_register_template(&rsassa_pkcs1_tmpl);
+ if (err)
+ goto err_unregister_rsa_pkcs1pad;
return 0;
+
+err_unregister_rsa_pkcs1pad:
+ crypto_unregister_template(&rsa_pkcs1pad_tmpl);
+err_unregister_rsa:
+ crypto_unregister_akcipher(&rsa);
+ return err;
}
static void __exit rsa_exit(void)
{
+ crypto_unregister_template(&rsassa_pkcs1_tmpl);
crypto_unregister_template(&rsa_pkcs1pad_tmpl);
crypto_unregister_akcipher(&rsa);
}
diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
new file mode 100644
index 000000000000..4d077fc96076
--- /dev/null
+++ b/crypto/rsassa-pkcs1.c
@@ -0,0 +1,454 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RSA Signature Scheme with Appendix - PKCS #1 v1.5 (RFC 8017 sec 8.2)
+ *
+ * https://www.rfc-editor.org/rfc/rfc8017#section-8.2
+ *
+ * Copyright (c) 2015 - 2024 Intel Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <crypto/akcipher.h>
+#include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include <crypto/sig.h>
+#include <crypto/internal/akcipher.h>
+#include <crypto/internal/rsa.h>
+#include <crypto/internal/sig.h>
+
+/*
+ * Full Hash Prefix for EMSA-PKCS1-v1_5 encoding method (RFC 9580 table 24)
+ *
+ * RSA keys are usually much larger than the hash of the message to be signed.
+ * The hash is therefore prepended by the Full Hash Prefix and a 0xff padding.
+ * The Full Hash Prefix is an ASN.1 SEQUENCE containing the hash algorithm OID.
+ *
+ * https://www.rfc-editor.org/rfc/rfc9580#table-24
+ */
+
+static const u8 hash_prefix_none[] = { };
+
+static const u8 hash_prefix_md5[] = {
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, /* SEQUENCE (SEQUENCE (OID */
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* <algorithm>, */
+ 0x05, 0x00, 0x04, 0x10 /* NULL), OCTET STRING <hash>) */
+};
+
+static const u8 hash_prefix_sha1[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 hash_prefix_rmd160[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x24, 0x03, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 hash_prefix_sha224[] = {
+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+ 0x05, 0x00, 0x04, 0x1c
+};
+
+static const u8 hash_prefix_sha256[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 hash_prefix_sha384[] = {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+ 0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 hash_prefix_sha512[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+ 0x05, 0x00, 0x04, 0x40
+};
+
+static const u8 hash_prefix_sha3_256[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08,
+ 0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 hash_prefix_sha3_384[] = {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09,
+ 0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 hash_prefix_sha3_512[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a,
+ 0x05, 0x00, 0x04, 0x40
+};
+
+static const struct hash_prefix {
+ const char *name;
+ const u8 *data;
+ size_t size;
+} hash_prefixes[] = {
+#define _(X) { #X, hash_prefix_##X, sizeof(hash_prefix_##X) }
+ _(none),
+ _(md5),
+ _(sha1),
+ _(rmd160),
+ _(sha256),
+ _(sha384),
+ _(sha512),
+ _(sha224),
+#undef _
+#define _(X) { "sha3-" #X, hash_prefix_sha3_##X, sizeof(hash_prefix_sha3_##X) }
+ _(256),
+ _(384),
+ _(512),
+#undef _
+ { NULL }
+};
+
+static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
+{
+ const struct hash_prefix *p;
+
+ for (p = hash_prefixes; p->name; p++)
+ if (strcmp(name, p->name) == 0)
+ return p;
+ return NULL;
+}
+
+static bool rsassa_pkcs1_invalid_hash_len(unsigned int len,
+ const struct hash_prefix *p)
+{
+ /*
+ * Legacy protocols such as TLS 1.1 or earlier and IKE version 1
+ * do not prepend a Full Hash Prefix to the hash. In that case,
+ * the size of the Full Hash Prefix is zero.
+ */
+ if (p->data == hash_prefix_none)
+ return false;
+
+ /*
+ * The final byte of the Full Hash Prefix encodes the hash length.
+ *
+ * This needs to be revisited should hash algorithms with more than
+ * 1016 bits (127 bytes * 8) ever be added. The length would then
+ * be encoded into more than one byte by ASN.1.
+ */
+ static_assert(HASH_MAX_DIGESTSIZE <= 127);
+
+ return len != p->data[p->size - 1];
+}
+
+struct rsassa_pkcs1_ctx {
+ struct crypto_akcipher *child;
+ unsigned int key_size;
+};
+
+struct rsassa_pkcs1_inst_ctx {
+ struct crypto_akcipher_spawn spawn;
+ const struct hash_prefix *hash_prefix;
+};
+
+static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ void *dst, unsigned int dlen)
+{
+ struct sig_instance *inst = sig_alg_instance(tfm);
+ struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
+ const struct hash_prefix *hash_prefix = ictx->hash_prefix;
+ struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+ unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
+ struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
+ struct scatterlist in_sg[3], out_sg;
+ struct crypto_wait cwait;
+ unsigned int pad_len;
+ unsigned int ps_end;
+ unsigned int len;
+ u8 *in_buf;
+ int err;
+
+ if (!ctx->key_size)
+ return -EINVAL;
+
+ if (dlen < ctx->key_size)
+ return -EOVERFLOW;
+
+ if (rsassa_pkcs1_invalid_hash_len(slen, hash_prefix))
+ return -EINVAL;
+
+ if (slen + hash_prefix->size > ctx->key_size - 11)
+ return -EOVERFLOW;
+
+ pad_len = ctx->key_size - slen - hash_prefix->size - 1;
+
+ child_req = kmalloc(sizeof(*child_req) + child_reqsize + pad_len,
+ GFP_KERNEL);
+ if (!child_req)
+ return -ENOMEM;
+
+ /* RFC 8017 sec 8.2.1 step 1 - EMSA-PKCS1-v1_5 encoding generation */
+ in_buf = (u8 *)(child_req + 1) + child_reqsize;
+ ps_end = pad_len - 1;
+ in_buf[0] = 0x01;
+ memset(in_buf + 1, 0xff, ps_end - 1);
+ in_buf[ps_end] = 0x00;
+
+ /* RFC 8017 sec 8.2.1 step 2 - RSA signature */
+ crypto_init_wait(&cwait);
+ sg_init_table(in_sg, 3);
+ sg_set_buf(&in_sg[0], in_buf, pad_len);
+ sg_set_buf(&in_sg[1], hash_prefix->data, hash_prefix->size);
+ sg_set_buf(&in_sg[2], src, slen);
+ sg_init_one(&out_sg, dst, dlen);
+ akcipher_request_set_tfm(child_req, ctx->child);
+ akcipher_request_set_crypt(child_req, in_sg, &out_sg,
+ ctx->key_size - 1, dlen);
+ akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
+ crypto_req_done, &cwait);
+
+ err = crypto_akcipher_decrypt(child_req);
+ err = crypto_wait_req(err, &cwait);
+ if (err)
+ return err;
+
+ len = child_req->dst_len;
+ pad_len = ctx->key_size - len;
+
+ /* Four billion to one */
+ if (unlikely(pad_len)) {
+ memmove(dst + pad_len, dst, len);
+ memset(dst, 0, pad_len);
+ }
+
+ return 0;
+}
+
+static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ const void *digest, unsigned int dlen)
+{
+ struct sig_instance *inst = sig_alg_instance(tfm);
+ struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
+ const struct hash_prefix *hash_prefix = ictx->hash_prefix;
+ struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+ unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
+ struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
+ struct scatterlist in_sg, out_sg;
+ struct crypto_wait cwait;
+ unsigned int dst_len;
+ unsigned int pos;
+ u8 *out_buf;
+ int err;
+
+ /* RFC 8017 sec 8.2.2 step 1 - length checking */
+ if (!ctx->key_size ||
+ slen != ctx->key_size ||
+ rsassa_pkcs1_invalid_hash_len(dlen, hash_prefix))
+ return -EINVAL;
+
+ /* RFC 8017 sec 8.2.2 step 2 - RSA verification */
+ child_req = kmalloc(sizeof(*child_req) + child_reqsize + ctx->key_size,
+ GFP_KERNEL);
+ if (!child_req)
+ return -ENOMEM;
+
+ out_buf = (u8 *)(child_req + 1) + child_reqsize;
+
+ crypto_init_wait(&cwait);
+ sg_init_one(&in_sg, src, slen);
+ sg_init_one(&out_sg, out_buf, ctx->key_size);
+ akcipher_request_set_tfm(child_req, ctx->child);
+ akcipher_request_set_crypt(child_req, &in_sg, &out_sg,
+ slen, ctx->key_size);
+ akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
+ crypto_req_done, &cwait);
+
+ err = crypto_akcipher_encrypt(child_req);
+ err = crypto_wait_req(err, &cwait);
+ if (err)
+ return err;
+
+ /* RFC 8017 sec 8.2.2 step 3 - EMSA-PKCS1-v1_5 encoding verification */
+ dst_len = child_req->dst_len;
+ if (dst_len < ctx->key_size - 1)
+ return -EINVAL;
+
+ if (dst_len == ctx->key_size) {
+ if (out_buf[0] != 0x00)
+ /* Encrypted value had no leading 0 byte */
+ return -EINVAL;
+
+ dst_len--;
+ out_buf++;
+ }
+
+ if (out_buf[0] != 0x01)
+ return -EBADMSG;
+
+ for (pos = 1; pos < dst_len; pos++)
+ if (out_buf[pos] != 0xff)
+ break;
+
+ if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00)
+ return -EBADMSG;
+ pos++;
+
+ if (hash_prefix->size > dst_len - pos)
+ return -EBADMSG;
+ if (crypto_memneq(out_buf + pos, hash_prefix->data, hash_prefix->size))
+ return -EBADMSG;
+ pos += hash_prefix->size;
+
+ /* RFC 8017 sec 8.2.2 step 4 - comparison of digest with out_buf */
+ if (dlen != dst_len - pos)
+ return -EKEYREJECTED;
+ if (memcmp(digest, out_buf + pos, dlen) != 0)
+ return -EKEYREJECTED;
+
+ return 0;
+}
+
+static unsigned int rsassa_pkcs1_key_size(struct crypto_sig *tfm)
+{
+ struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return ctx->key_size;
+}
+
+static int rsassa_pkcs1_set_pub_key(struct crypto_sig *tfm,
+ const void *key, unsigned int keylen)
+{
+ struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
+}
+
+static int rsassa_pkcs1_set_priv_key(struct crypto_sig *tfm,
+ const void *key, unsigned int keylen)
+{
+ struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+ return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
+}
+
+static int rsassa_pkcs1_init_tfm(struct crypto_sig *tfm)
+{
+ struct sig_instance *inst = sig_alg_instance(tfm);
+ struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
+ struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+ struct crypto_akcipher *child_tfm;
+
+ child_tfm = crypto_spawn_akcipher(&ictx->spawn);
+ if (IS_ERR(child_tfm))
+ return PTR_ERR(child_tfm);
+
+ ctx->child = child_tfm;
+
+ return 0;
+}
+
+static void rsassa_pkcs1_exit_tfm(struct crypto_sig *tfm)
+{
+ struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+ crypto_free_akcipher(ctx->child);
+}
+
+static void rsassa_pkcs1_free(struct sig_instance *inst)
+{
+ struct rsassa_pkcs1_inst_ctx *ctx = sig_instance_ctx(inst);
+ struct crypto_akcipher_spawn *spawn = &ctx->spawn;
+
+ crypto_drop_akcipher(spawn);
+ kfree(inst);
+}
+
+static int rsassa_pkcs1_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+ struct rsassa_pkcs1_inst_ctx *ctx;
+ struct akcipher_alg *rsa_alg;
+ struct sig_instance *inst;
+ const char *hash_name;
+ u32 mask;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SIG, &mask);
+ if (err)
+ return err;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+ if (!inst)
+ return -ENOMEM;
+
+ ctx = sig_instance_ctx(inst);
+
+ err = crypto_grab_akcipher(&ctx->spawn, sig_crypto_instance(inst),
+ crypto_attr_alg_name(tb[1]), 0, mask);
+ if (err)
+ goto err_free_inst;
+
+ rsa_alg = crypto_spawn_akcipher_alg(&ctx->spawn);
+
+ if (strcmp(rsa_alg->base.cra_name, "rsa") != 0) {
+ err = -EINVAL;
+ goto err_free_inst;
+ }
+
+ hash_name = crypto_attr_alg_name(tb[2]);
+ if (IS_ERR(hash_name)) {
+ err = PTR_ERR(hash_name);
+ goto err_free_inst;
+ }
+
+ ctx->hash_prefix = rsassa_pkcs1_find_hash_prefix(hash_name);
+ if (!ctx->hash_prefix) {
+ err = -EINVAL;
+ goto err_free_inst;
+ }
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+ "pkcs1(%s,%s)", rsa_alg->base.cra_name,
+ hash_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "pkcs1(%s,%s)", rsa_alg->base.cra_driver_name,
+ hash_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
+ inst->alg.base.cra_ctxsize = sizeof(struct rsassa_pkcs1_ctx);
+
+ inst->alg.init = rsassa_pkcs1_init_tfm;
+ inst->alg.exit = rsassa_pkcs1_exit_tfm;
+
+ inst->alg.sign = rsassa_pkcs1_sign;
+ inst->alg.verify = rsassa_pkcs1_verify;
+ inst->alg.key_size = rsassa_pkcs1_key_size;
+ inst->alg.set_pub_key = rsassa_pkcs1_set_pub_key;
+ inst->alg.set_priv_key = rsassa_pkcs1_set_priv_key;
+
+ inst->free = rsassa_pkcs1_free;
+
+ err = sig_register_instance(tmpl, inst);
+ if (err) {
+err_free_inst:
+ rsassa_pkcs1_free(inst);
+ }
+ return err;
+}
+
+struct crypto_template rsassa_pkcs1_tmpl = {
+ .name = "pkcs1",
+ .create = rsassa_pkcs1_create,
+ .module = THIS_MODULE,
+};
+
+MODULE_ALIAS_CRYPTO("pkcs1");
diff --git a/crypto/sig.c b/crypto/sig.c
index 7645bedf3a1f..5e1f1f739da2 100644
--- a/crypto/sig.c
+++ b/crypto/sig.c
@@ -5,12 +5,10 @@
* Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
*/
-#include <crypto/akcipher.h>
#include <crypto/internal/sig.h>
#include <linux/cryptouser.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/scatterlist.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <net/netlink.h>
@@ -19,16 +17,35 @@
#define CRYPTO_ALG_TYPE_SIG_MASK 0x0000000e
-static const struct crypto_type crypto_sig_type;
+static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_sig *sig = __crypto_sig_tfm(tfm);
+ struct sig_alg *alg = crypto_sig_alg(sig);
+
+ alg->exit(sig);
+}
static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
{
- if (tfm->__crt_alg->cra_type != &crypto_sig_type)
- return crypto_init_akcipher_ops_sig(tfm);
+ struct crypto_sig *sig = __crypto_sig_tfm(tfm);
+ struct sig_alg *alg = crypto_sig_alg(sig);
+
+ if (alg->exit)
+ sig->base.exit = crypto_sig_exit_tfm;
+
+ if (alg->init)
+ return alg->init(sig);
return 0;
}
+static void crypto_sig_free_instance(struct crypto_instance *inst)
+{
+ struct sig_instance *sig = sig_instance(inst);
+
+ sig->free(sig);
+}
+
static void __maybe_unused crypto_sig_show(struct seq_file *m,
struct crypto_alg *alg)
{
@@ -38,16 +55,17 @@ static void __maybe_unused crypto_sig_show(struct seq_file *m,
static int __maybe_unused crypto_sig_report(struct sk_buff *skb,
struct crypto_alg *alg)
{
- struct crypto_report_akcipher rsig = {};
+ struct crypto_report_sig rsig = {};
strscpy(rsig.type, "sig", sizeof(rsig.type));
- return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig);
+ return nla_put(skb, CRYPTOCFGA_REPORT_SIG, sizeof(rsig), &rsig);
}
static const struct crypto_type crypto_sig_type = {
.extsize = crypto_alg_extsize,
.init_tfm = crypto_sig_init_tfm,
+ .free = crypto_sig_free_instance,
#ifdef CONFIG_PROC_FS
.show = crypto_sig_show,
#endif
@@ -66,74 +84,95 @@ struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask)
}
EXPORT_SYMBOL_GPL(crypto_alloc_sig);
-int crypto_sig_maxsize(struct crypto_sig *tfm)
+static int sig_default_sign(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ void *dst, unsigned int dlen)
+{
+ return -ENOSYS;
+}
+
+static int sig_default_verify(struct crypto_sig *tfm,
+ const void *src, unsigned int slen,
+ const void *dst, unsigned int dlen)
{
- struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
+ return -ENOSYS;
+}
- return crypto_akcipher_maxsize(*ctx);
+static int sig_default_set_key(struct crypto_sig *tfm,
+ const void *key, unsigned int keylen)
+{
+ return -ENOSYS;
}
-EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
-int crypto_sig_sign(struct crypto_sig *tfm,
- const void *src, unsigned int slen,
- void *dst, unsigned int dlen)
+static int sig_prepare_alg(struct sig_alg *alg)
{
- struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
- struct crypto_akcipher_sync_data data = {
- .tfm = *ctx,
- .src = src,
- .dst = dst,
- .slen = slen,
- .dlen = dlen,
- };
-
- return crypto_akcipher_sync_prep(&data) ?:
- crypto_akcipher_sync_post(&data,
- crypto_akcipher_sign(data.req));
+ struct crypto_alg *base = &alg->base;
+
+ if (!alg->sign)
+ alg->sign = sig_default_sign;
+ if (!alg->verify)
+ alg->verify = sig_default_verify;
+ if (!alg->set_priv_key)
+ alg->set_priv_key = sig_default_set_key;
+ if (!alg->set_pub_key)
+ return -EINVAL;
+ if (!alg->key_size)
+ return -EINVAL;
+ if (!alg->max_size)
+ alg->max_size = alg->key_size;
+ if (!alg->digest_size)
+ alg->digest_size = alg->key_size;
+
+ base->cra_type = &crypto_sig_type;
+ base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+ base->cra_flags |= CRYPTO_ALG_TYPE_SIG;
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(crypto_sig_sign);
-int crypto_sig_verify(struct crypto_sig *tfm,
- const void *src, unsigned int slen,
- const void *digest, unsigned int dlen)
+int crypto_register_sig(struct sig_alg *alg)
{
- struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
- struct crypto_akcipher_sync_data data = {
- .tfm = *ctx,
- .src = src,
- .slen = slen,
- .dlen = dlen,
- };
+ struct crypto_alg *base = &alg->base;
int err;
- err = crypto_akcipher_sync_prep(&data);
+ err = sig_prepare_alg(alg);
if (err)
return err;
- memcpy(data.buf + slen, digest, dlen);
+ return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_sig);
- return crypto_akcipher_sync_post(&data,
- crypto_akcipher_verify(data.req));
+void crypto_unregister_sig(struct sig_alg *alg)
+{
+ crypto_unregister_alg(&alg->base);
}
-EXPORT_SYMBOL_GPL(crypto_sig_verify);
+EXPORT_SYMBOL_GPL(crypto_unregister_sig);
-int crypto_sig_set_pubkey(struct crypto_sig *tfm,
- const void *key, unsigned int keylen)
+int sig_register_instance(struct crypto_template *tmpl,
+ struct sig_instance *inst)
{
- struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
+ int err;
+
+ if (WARN_ON(!inst->free))
+ return -EINVAL;
+
+ err = sig_prepare_alg(&inst->alg);
+ if (err)
+ return err;
- return crypto_akcipher_set_pub_key(*ctx, key, keylen);
+ return crypto_register_instance(tmpl, sig_crypto_instance(inst));
}
-EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
+EXPORT_SYMBOL_GPL(sig_register_instance);
-int crypto_sig_set_privkey(struct crypto_sig *tfm,
- const void *key, unsigned int keylen)
+int crypto_grab_sig(struct crypto_sig_spawn *spawn,
+ struct crypto_instance *inst,
+ const char *name, u32 type, u32 mask)
{
- struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
-
- return crypto_akcipher_set_priv_key(*ctx, key, keylen);
+ spawn->base.frontend = &crypto_sig_type;
+ return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
}
-EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
+EXPORT_SYMBOL_GPL(crypto_grab_sig);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Public Key Signature Algorithms");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 2f5f6b52b2d4..3fc908bac21a 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -23,7 +23,7 @@
#include <linux/fips.h>
#include <linux/module.h>
#include <linux/once.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -33,6 +33,7 @@
#include <crypto/akcipher.h>
#include <crypto/kpp.h>
#include <crypto/acompress.h>
+#include <crypto/sig.h>
#include <crypto/internal/cipher.h>
#include <crypto/internal/simd.h>
@@ -131,6 +132,11 @@ struct akcipher_test_suite {
unsigned int count;
};
+struct sig_test_suite {
+ const struct sig_testvec *vecs;
+ unsigned int count;
+};
+
struct kpp_test_suite {
const struct kpp_testvec *vecs;
unsigned int count;
@@ -151,6 +157,7 @@ struct alg_test_desc {
struct cprng_test_suite cprng;
struct drbg_test_suite drbg;
struct akcipher_test_suite akcipher;
+ struct sig_test_suite sig;
struct kpp_test_suite kpp;
} suite;
};
@@ -4123,11 +4130,9 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
struct crypto_wait wait;
unsigned int out_len_max, out_len = 0;
int err = -ENOMEM;
- struct scatterlist src, dst, src_tab[3];
- const char *m, *c;
- unsigned int m_size, c_size;
- const char *op;
- u8 *key, *ptr;
+ struct scatterlist src, dst, src_tab[2];
+ const char *c;
+ unsigned int c_size;
if (testmgr_alloc_buf(xbuf))
return err;
@@ -4138,92 +4143,53 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
crypto_init_wait(&wait);
- key = kmalloc(vecs->key_len + sizeof(u32) * 2 + vecs->param_len,
- GFP_KERNEL);
- if (!key)
- goto free_req;
- memcpy(key, vecs->key, vecs->key_len);
- ptr = key + vecs->key_len;
- ptr = test_pack_u32(ptr, vecs->algo);
- ptr = test_pack_u32(ptr, vecs->param_len);
- memcpy(ptr, vecs->params, vecs->param_len);
-
if (vecs->public_key_vec)
- err = crypto_akcipher_set_pub_key(tfm, key, vecs->key_len);
+ err = crypto_akcipher_set_pub_key(tfm, vecs->key,
+ vecs->key_len);
else
- err = crypto_akcipher_set_priv_key(tfm, key, vecs->key_len);
+ err = crypto_akcipher_set_priv_key(tfm, vecs->key,
+ vecs->key_len);
if (err)
- goto free_key;
+ goto free_req;
- /*
- * First run test which do not require a private key, such as
- * encrypt or verify.
- */
+ /* First run encrypt test which does not require a private key */
err = -ENOMEM;
out_len_max = crypto_akcipher_maxsize(tfm);
outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
if (!outbuf_enc)
- goto free_key;
-
- if (!vecs->siggen_sigver_test) {
- m = vecs->m;
- m_size = vecs->m_size;
- c = vecs->c;
- c_size = vecs->c_size;
- op = "encrypt";
- } else {
- /* Swap args so we could keep plaintext (digest)
- * in vecs->m, and cooked signature in vecs->c.
- */
- m = vecs->c; /* signature */
- m_size = vecs->c_size;
- c = vecs->m; /* digest */
- c_size = vecs->m_size;
- op = "verify";
- }
+ goto free_req;
+
+ c = vecs->c;
+ c_size = vecs->c_size;
err = -E2BIG;
- if (WARN_ON(m_size > PAGE_SIZE))
+ if (WARN_ON(vecs->m_size > PAGE_SIZE))
goto free_all;
- memcpy(xbuf[0], m, m_size);
+ memcpy(xbuf[0], vecs->m, vecs->m_size);
- sg_init_table(src_tab, 3);
+ sg_init_table(src_tab, 2);
sg_set_buf(&src_tab[0], xbuf[0], 8);
- sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
- if (vecs->siggen_sigver_test) {
- if (WARN_ON(c_size > PAGE_SIZE))
- goto free_all;
- memcpy(xbuf[1], c, c_size);
- sg_set_buf(&src_tab[2], xbuf[1], c_size);
- akcipher_request_set_crypt(req, src_tab, NULL, m_size, c_size);
- } else {
- sg_init_one(&dst, outbuf_enc, out_len_max);
- akcipher_request_set_crypt(req, src_tab, &dst, m_size,
- out_len_max);
- }
+ sg_set_buf(&src_tab[1], xbuf[0] + 8, vecs->m_size - 8);
+ sg_init_one(&dst, outbuf_enc, out_len_max);
+ akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
+ out_len_max);
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
crypto_req_done, &wait);
- err = crypto_wait_req(vecs->siggen_sigver_test ?
- /* Run asymmetric signature verification */
- crypto_akcipher_verify(req) :
- /* Run asymmetric encrypt */
- crypto_akcipher_encrypt(req), &wait);
+ err = crypto_wait_req(crypto_akcipher_encrypt(req), &wait);
if (err) {
- pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
+ pr_err("alg: akcipher: encrypt test failed. err %d\n", err);
goto free_all;
}
- if (!vecs->siggen_sigver_test && c) {
+ if (c) {
if (req->dst_len != c_size) {
- pr_err("alg: akcipher: %s test failed. Invalid output len\n",
- op);
+ pr_err("alg: akcipher: encrypt test failed. Invalid output len\n");
err = -EINVAL;
goto free_all;
}
/* verify that encrypted message is equal to expected */
if (memcmp(c, outbuf_enc, c_size) != 0) {
- pr_err("alg: akcipher: %s test failed. Invalid output\n",
- op);
+ pr_err("alg: akcipher: encrypt test failed. Invalid output\n");
hexdump(outbuf_enc, c_size);
err = -EINVAL;
goto free_all;
@@ -4231,7 +4197,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
}
/*
- * Don't invoke (decrypt or sign) test which require a private key
+ * Don't invoke decrypt test which requires a private key
* for vectors with only a public key.
*/
if (vecs->public_key_vec) {
@@ -4244,13 +4210,12 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
goto free_all;
}
- if (!vecs->siggen_sigver_test && !c) {
+ if (!c) {
c = outbuf_enc;
c_size = req->dst_len;
}
err = -E2BIG;
- op = vecs->siggen_sigver_test ? "sign" : "decrypt";
if (WARN_ON(c_size > PAGE_SIZE))
goto free_all;
memcpy(xbuf[0], c, c_size);
@@ -4260,34 +4225,29 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
crypto_init_wait(&wait);
akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
- err = crypto_wait_req(vecs->siggen_sigver_test ?
- /* Run asymmetric signature generation */
- crypto_akcipher_sign(req) :
- /* Run asymmetric decrypt */
- crypto_akcipher_decrypt(req), &wait);
+ err = crypto_wait_req(crypto_akcipher_decrypt(req), &wait);
if (err) {
- pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
+ pr_err("alg: akcipher: decrypt test failed. err %d\n", err);
goto free_all;
}
out_len = req->dst_len;
- if (out_len < m_size) {
- pr_err("alg: akcipher: %s test failed. Invalid output len %u\n",
- op, out_len);
+ if (out_len < vecs->m_size) {
+ pr_err("alg: akcipher: decrypt test failed. Invalid output len %u\n",
+ out_len);
err = -EINVAL;
goto free_all;
}
/* verify that decrypted message is equal to the original msg */
- if (memchr_inv(outbuf_dec, 0, out_len - m_size) ||
- memcmp(m, outbuf_dec + out_len - m_size, m_size)) {
- pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
+ if (memchr_inv(outbuf_dec, 0, out_len - vecs->m_size) ||
+ memcmp(vecs->m, outbuf_dec + out_len - vecs->m_size,
+ vecs->m_size)) {
+ pr_err("alg: akcipher: decrypt test failed. Invalid output\n");
hexdump(outbuf_dec, out_len);
err = -EINVAL;
}
free_all:
kfree(outbuf_dec);
kfree(outbuf_enc);
-free_key:
- kfree(key);
free_req:
akcipher_request_free(req);
free_xbuf:
@@ -4337,6 +4297,113 @@ static int alg_test_akcipher(const struct alg_test_desc *desc,
return err;
}
+static int test_sig_one(struct crypto_sig *tfm, const struct sig_testvec *vecs)
+{
+ u8 *ptr, *key __free(kfree);
+ int err, sig_size;
+
+ key = kmalloc(vecs->key_len + 2 * sizeof(u32) + vecs->param_len,
+ GFP_KERNEL);
+ if (!key)
+ return -ENOMEM;
+
+ /* ecrdsa expects additional parameters appended to the key */
+ memcpy(key, vecs->key, vecs->key_len);
+ ptr = key + vecs->key_len;
+ ptr = test_pack_u32(ptr, vecs->algo);
+ ptr = test_pack_u32(ptr, vecs->param_len);
+ memcpy(ptr, vecs->params, vecs->param_len);
+
+ if (vecs->public_key_vec)
+ err = crypto_sig_set_pubkey(tfm, key, vecs->key_len);
+ else
+ err = crypto_sig_set_privkey(tfm, key, vecs->key_len);
+ if (err)
+ return err;
+
+ /*
+ * Run asymmetric signature verification first
+ * (which does not require a private key)
+ */
+ err = crypto_sig_verify(tfm, vecs->c, vecs->c_size,
+ vecs->m, vecs->m_size);
+ if (err) {
+ pr_err("alg: sig: verify test failed: err %d\n", err);
+ return err;
+ }
+
+ /*
+ * Don't invoke sign test (which requires a private key)
+ * for vectors with only a public key.
+ */
+ if (vecs->public_key_vec)
+ return 0;
+
+ sig_size = crypto_sig_keysize(tfm);
+ if (sig_size < vecs->c_size) {
+ pr_err("alg: sig: invalid maxsize %u\n", sig_size);
+ return -EINVAL;
+ }
+
+ u8 *sig __free(kfree) = kzalloc(sig_size, GFP_KERNEL);
+ if (!sig)
+ return -ENOMEM;
+
+ /* Run asymmetric signature generation */
+ err = crypto_sig_sign(tfm, vecs->m, vecs->m_size, sig, sig_size);
+ if (err) {
+ pr_err("alg: sig: sign test failed: err %d\n", err);
+ return err;
+ }
+
+ /* Verify that generated signature equals cooked signature */
+ if (memcmp(sig, vecs->c, vecs->c_size) ||
+ memchr_inv(sig + vecs->c_size, 0, sig_size - vecs->c_size)) {
+ pr_err("alg: sig: sign test failed: invalid output\n");
+ hexdump(sig, sig_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int test_sig(struct crypto_sig *tfm, const char *alg,
+ const struct sig_testvec *vecs, unsigned int tcount)
+{
+ const char *algo = crypto_tfm_alg_driver_name(crypto_sig_tfm(tfm));
+ int ret, i;
+
+ for (i = 0; i < tcount; i++) {
+ ret = test_sig_one(tfm, vecs++);
+ if (ret) {
+ pr_err("alg: sig: test %d failed for %s: err %d\n",
+ i + 1, algo, ret);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int alg_test_sig(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ struct crypto_sig *tfm;
+ int err = 0;
+
+ tfm = crypto_alloc_sig(driver, type, mask);
+ if (IS_ERR(tfm)) {
+ pr_err("alg: sig: Failed to load tfm for %s: %ld\n",
+ driver, PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+ if (desc->suite.sig.vecs)
+ err = test_sig(tfm, desc->alg, desc->suite.sig.vecs,
+ desc->suite.sig.count);
+
+ crypto_free_sig(tfm);
+ return err;
+}
+
static int alg_test_null(const struct alg_test_desc *desc,
const char *driver, u32 type, u32 mask)
{
@@ -5126,36 +5193,36 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}, {
.alg = "ecdsa-nist-p192",
- .test = alg_test_akcipher,
+ .test = alg_test_sig,
.suite = {
- .akcipher = __VECS(ecdsa_nist_p192_tv_template)
+ .sig = __VECS(ecdsa_nist_p192_tv_template)
}
}, {
.alg = "ecdsa-nist-p256",
- .test = alg_test_akcipher,
+ .test = alg_test_sig,
.fips_allowed = 1,
.suite = {
- .akcipher = __VECS(ecdsa_nist_p256_tv_template)
+ .sig = __VECS(ecdsa_nist_p256_tv_template)
}
}, {
.alg = "ecdsa-nist-p384",
- .test = alg_test_akcipher,
+ .test = alg_test_sig,
.fips_allowed = 1,
.suite = {
- .akcipher = __VECS(ecdsa_nist_p384_tv_template)
+ .sig = __VECS(ecdsa_nist_p384_tv_template)
}
}, {
.alg = "ecdsa-nist-p521",
- .test = alg_test_akcipher,
+ .test = alg_test_sig,
.fips_allowed = 1,
.suite = {
- .akcipher = __VECS(ecdsa_nist_p521_tv_template)
+ .sig = __VECS(ecdsa_nist_p521_tv_template)
}
}, {
.alg = "ecrdsa",
- .test = alg_test_akcipher,
+ .test = alg_test_sig,
.suite = {
- .akcipher = __VECS(ecrdsa_tv_template)
+ .sig = __VECS(ecrdsa_tv_template)
}
}, {
.alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)",
@@ -5448,40 +5515,68 @@ static const struct alg_test_desc alg_test_descs[] = {
.hash = __VECS(nhpoly1305_tv_template)
}
}, {
+ .alg = "p1363(ecdsa-nist-p192)",
+ .test = alg_test_null,
+ }, {
+ .alg = "p1363(ecdsa-nist-p256)",
+ .test = alg_test_sig,
+ .fips_allowed = 1,
+ .suite = {
+ .sig = __VECS(p1363_ecdsa_nist_p256_tv_template)
+ }
+ }, {
+ .alg = "p1363(ecdsa-nist-p384)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "p1363(ecdsa-nist-p521)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
.alg = "pcbc(fcrypt)",
.test = alg_test_skcipher,
.suite = {
.cipher = __VECS(fcrypt_pcbc_tv_template)
}
}, {
- .alg = "pkcs1pad(rsa,sha224)",
+ .alg = "pkcs1(rsa,none)",
+ .test = alg_test_sig,
+ .suite = {
+ .sig = __VECS(pkcs1_rsa_none_tv_template)
+ }
+ }, {
+ .alg = "pkcs1(rsa,sha224)",
.test = alg_test_null,
.fips_allowed = 1,
}, {
- .alg = "pkcs1pad(rsa,sha256)",
- .test = alg_test_akcipher,
+ .alg = "pkcs1(rsa,sha256)",
+ .test = alg_test_sig,
.fips_allowed = 1,
.suite = {
- .akcipher = __VECS(pkcs1pad_rsa_tv_template)
+ .sig = __VECS(pkcs1_rsa_tv_template)
}
}, {
- .alg = "pkcs1pad(rsa,sha3-256)",
+ .alg = "pkcs1(rsa,sha3-256)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "pkcs1(rsa,sha3-384)",
.test = alg_test_null,
.fips_allowed = 1,
}, {
- .alg = "pkcs1pad(rsa,sha3-384)",
+ .alg = "pkcs1(rsa,sha3-512)",
.test = alg_test_null,
.fips_allowed = 1,
}, {
- .alg = "pkcs1pad(rsa,sha3-512)",
+ .alg = "pkcs1(rsa,sha384)",
.test = alg_test_null,
.fips_allowed = 1,
}, {
- .alg = "pkcs1pad(rsa,sha384)",
+ .alg = "pkcs1(rsa,sha512)",
.test = alg_test_null,
.fips_allowed = 1,
}, {
- .alg = "pkcs1pad(rsa,sha512)",
+ .alg = "pkcs1pad(rsa)",
.test = alg_test_null,
.fips_allowed = 1,
}, {
@@ -5679,6 +5774,33 @@ static const struct alg_test_desc alg_test_descs[] = {
.hash = __VECS(wp512_tv_template)
}
}, {
+ .alg = "x962(ecdsa-nist-p192)",
+ .test = alg_test_sig,
+ .suite = {
+ .sig = __VECS(x962_ecdsa_nist_p192_tv_template)
+ }
+ }, {
+ .alg = "x962(ecdsa-nist-p256)",
+ .test = alg_test_sig,
+ .fips_allowed = 1,
+ .suite = {
+ .sig = __VECS(x962_ecdsa_nist_p256_tv_template)
+ }
+ }, {
+ .alg = "x962(ecdsa-nist-p384)",
+ .test = alg_test_sig,
+ .fips_allowed = 1,
+ .suite = {
+ .sig = __VECS(x962_ecdsa_nist_p384_tv_template)
+ }
+ }, {
+ .alg = "x962(ecdsa-nist-p521)",
+ .test = alg_test_sig,
+ .fips_allowed = 1,
+ .suite = {
+ .sig = __VECS(x962_ecdsa_nist_p521_tv_template)
+ }
+ }, {
.alg = "xcbc(aes)",
.test = alg_test_hash,
.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 9b38501a17b2..430d33d9ac13 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -21,6 +21,7 @@
#define _CRYPTO_TESTMGR_H
#include <linux/oid_registry.h>
+#include <crypto/internal/ecc.h>
#define MAX_IVLEN 32
@@ -150,6 +151,16 @@ struct drbg_testvec {
struct akcipher_testvec {
const unsigned char *key;
+ const unsigned char *m;
+ const unsigned char *c;
+ unsigned int key_len;
+ unsigned int m_size;
+ unsigned int c_size;
+ bool public_key_vec;
+};
+
+struct sig_testvec {
+ const unsigned char *key;
const unsigned char *params;
const unsigned char *m;
const unsigned char *c;
@@ -158,7 +169,6 @@ struct akcipher_testvec {
unsigned int m_size;
unsigned int c_size;
bool public_key_vec;
- bool siggen_sigver_test;
enum OID algo;
};
@@ -647,26 +657,713 @@ static const struct akcipher_testvec rsa_tv_template[] = {
}
};
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define be64_to_cpua(b1, b2, b3, b4, b5, b6, b7, b8) \
+ 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8
+#else
+#define be64_to_cpua(b1, b2, b3, b4, b5, b6, b7, b8) \
+ 0x##b8, 0x##b7, 0x##b6, 0x##b5, 0x##b4, 0x##b3, 0x##b2, 0x##b1
+#endif
+
/*
* ECDSA test vectors.
*/
-static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
+static const struct sig_testvec ecdsa_nist_p192_tv_template[] = {
{
- .key =
+ .key = /* secp192r1(sha1) */
+ "\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
+ "\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68"
+ "\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08"
+ "\x98",
+ .key_len = 49,
+ .m =
+ "\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae"
+ "\x63\x85\xe7\x82",
+ .m_size = 20,
+ .c = (const unsigned char[]){
+ be64_to_cpua(ad, 59, ad, 88, 27, d6, 92, 6b),
+ be64_to_cpua(a0, 27, 91, c6, f6, 7f, c3, 09),
+ be64_to_cpua(ba, e5, 93, 83, 6e, b6, 3b, 63),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(86, 80, 6f, a5, 79, 77, da, d0),
+ be64_to_cpua(ef, 95, 52, 7b, a0, 0f, e4, 18),
+ be64_to_cpua(10, 68, 01, 9d, ba, ce, 83, 08),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp192r1(sha224) */
+ "\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
+ "\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75"
+ "\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee"
+ "\xa3",
+ .key_len = 49,
+ .m =
+ "\x8d\xd6\xb8\x3e\xe5\xff\x23\xf6\x25\xa2\x43\x42\x74\x45\xa7\x40"
+ "\x3a\xff\x2f\xe1\xd3\xf6\x9f\xe8\x33\xcb\x12\x11",
+ .m_size = 28,
+ .c = (const unsigned char[]){
+ be64_to_cpua(83, 7b, 12, e6, b6, 5b, cb, d4),
+ be64_to_cpua(14, f8, 11, 2b, 55, dc, ae, 37),
+ be64_to_cpua(5a, 8b, 82, 69, 7e, 8a, 0a, 09),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(a3, e3, 5c, 99, db, 92, 5b, 36),
+ be64_to_cpua(eb, c3, 92, 0f, 1e, 72, ee, c4),
+ be64_to_cpua(6a, 14, 4f, 53, 75, c8, 02, 48),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp192r1(sha256) */
+ "\x04\xe2\x51\x24\x9b\xf7\xb6\x32\x82\x39\x66\x3d\x5b\xec\x3b\xae"
+ "\x0c\xd5\xf2\x67\xd1\xc7\xe1\x02\xe4\xbf\x90\x62\xb8\x55\x75\x56"
+ "\x69\x20\x5e\xcb\x4e\xca\x33\xd6\xcb\x62\x6b\x94\xa9\xa2\xe9\x58"
+ "\x91",
+ .key_len = 49,
+ .m =
+ "\x35\xec\xa1\xa0\x9e\x14\xde\x33\x03\xb6\xf6\xbd\x0c\x2f\xb2\xfd"
+ "\x1f\x27\x82\xa5\xd7\x70\x3f\xef\xa0\x82\x69\x8e\x73\x31\x8e\xd7",
+ .m_size = 32,
+ .c = (const unsigned char[]){
+ be64_to_cpua(01, 48, fb, 5f, 72, 2a, d4, 8f),
+ be64_to_cpua(6b, 1a, 58, 56, f1, 8f, f7, fd),
+ be64_to_cpua(3f, 72, 3f, 1f, 42, d2, 3f, 1d),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(7d, 3a, 97, d9, cd, 1a, 6a, 49),
+ be64_to_cpua(32, dd, 41, 74, 6a, 51, c7, d9),
+ be64_to_cpua(b3, 69, 43, fd, 48, 19, 86, cf),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp192r1(sha384) */
+ "\x04\x5a\x13\xfe\x68\x86\x4d\xf4\x17\xc7\xa4\xe5\x8c\x65\x57\xb7"
+ "\x03\x73\x26\x57\xfb\xe5\x58\x40\xd8\xfd\x49\x05\xab\xf1\x66\x1f"
+ "\xe2\x9d\x93\x9e\xc2\x22\x5a\x8b\x4f\xf3\x77\x22\x59\x7e\xa6\x4e"
+ "\x8b",
+ .key_len = 49,
+ .m =
+ "\x9d\x2e\x1a\x8f\xed\x6c\x4b\x61\xae\xac\xd5\x19\x79\xce\x67\xf9"
+ "\xa0\x34\xeb\xb0\x81\xf9\xd9\xdc\x6e\xb3\x5c\xa8\x69\xfc\x8a\x61"
+ "\x39\x81\xfb\xfd\x5c\x30\x6b\xa8\xee\xed\x89\xaf\xa3\x05\xe4\x78",
+ .m_size = 48,
+ .c = (const unsigned char[]){
+ be64_to_cpua(dd, 15, bb, d6, 8c, a7, 03, 78),
+ be64_to_cpua(cf, 7f, 34, b4, b4, e5, c5, 00),
+ be64_to_cpua(f0, a3, 38, ce, 2b, f8, 9d, 1a),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(93, 12, 3b, 3b, 28, fb, 6d, e1),
+ be64_to_cpua(d1, 01, 77, 44, 5d, 53, a4, 7c),
+ be64_to_cpua(64, bc, 5a, 1f, 82, 96, 61, d7),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp192r1(sha512) */
+ "\x04\xd5\xf2\x6e\xc3\x94\x5c\x52\xbc\xdf\x86\x6c\x14\xd1\xca\xea"
+ "\xcc\x72\x3a\x8a\xf6\x7a\x3a\x56\x36\x3b\xca\xc6\x94\x0e\x17\x1d"
+ "\x9e\xa0\x58\x28\xf9\x4b\xe6\xd1\xa5\x44\x91\x35\x0d\xe7\xf5\x11"
+ "\x57",
+ .key_len = 49,
+ .m =
+ "\xd5\x4b\xe9\x36\xda\xd8\x6e\xc0\x50\x03\xbe\x00\x43\xff\xf0\x23"
+ "\xac\xa2\x42\xe7\x37\x77\x79\x52\x8f\x3e\xc0\x16\xc1\xfc\x8c\x67"
+ "\x16\xbc\x8a\x5d\x3b\xd3\x13\xbb\xb6\xc0\x26\x1b\xeb\x33\xcc\x70"
+ "\x4a\xf2\x11\x37\xe8\x1b\xba\x55\xac\x69\xe1\x74\x62\x7c\x6e\xb5",
+ .m_size = 64,
+ .c = (const unsigned char[]){
+ be64_to_cpua(2b, 11, 2d, 1c, b6, 06, c9, 6c),
+ be64_to_cpua(dd, 3f, 07, 87, 12, a0, d4, ac),
+ be64_to_cpua(88, 5b, 8f, 59, 43, bf, cf, c6),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(28, 6a, df, 97, fd, 82, 76, 24),
+ be64_to_cpua(a9, 14, 2a, 5e, f5, e5, fb, 72),
+ be64_to_cpua(73, b4, 22, 9a, 98, 73, 3c, 83),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ },
+};
+
+static const struct sig_testvec ecdsa_nist_p256_tv_template[] = {
+ {
+ .key = /* secp256r1(sha1) */
+ "\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
+ "\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9"
+ "\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc"
+ "\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8"
+ "\xaf",
+ .key_len = 65,
+ .m =
+ "\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c"
+ "\x0b\xde\x6a\x42",
+ .m_size = 20,
+ .c = (const unsigned char[]){
+ be64_to_cpua(ee, ca, 6a, 52, 0e, 48, 4d, cc),
+ be64_to_cpua(f7, d4, ad, 8d, 94, 5a, 69, 89),
+ be64_to_cpua(cf, d4, e7, b7, f0, 82, 56, 41),
+ be64_to_cpua(f9, 25, ce, 9f, 3a, a6, 35, 81),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(fb, 9d, 8b, de, d4, 8d, 6f, ad),
+ be64_to_cpua(f1, 03, 03, f3, 3b, e2, 73, f7),
+ be64_to_cpua(8a, fa, 54, 93, 29, a7, 70, 86),
+ be64_to_cpua(d7, e4, ef, 52, 66, d3, 5b, 9d),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp256r1(sha224) */
+ "\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
+ "\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0"
+ "\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88"
+ "\x43\x13\xbf\xf3\x1c\x05\x1a\x14\x18\x09\x3f\xd6\x28\x3e\xc5\xa0"
+ "\xd4",
+ .key_len = 65,
+ .m =
+ "\x1a\x15\xbc\xa3\xe4\xed\x3a\xb8\x23\x67\xc6\xc4\x34\xf8\x6c\x41"
+ "\x04\x0b\xda\xc5\x77\xfa\x1c\x2d\xe6\x2c\x3b\xe0",
+ .m_size = 28,
+ .c = (const unsigned char[]){
+ be64_to_cpua(7d, 25, d8, 25, f5, 81, d2, 1e),
+ be64_to_cpua(34, 62, 79, cb, 6a, 91, 67, 2e),
+ be64_to_cpua(ae, ce, 77, 59, 1a, db, 59, d5),
+ be64_to_cpua(20, 43, fa, c0, 9f, 9d, 7b, e7),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(ce, d5, 2e, 8b, de, 5a, 04, 0e),
+ be64_to_cpua(bf, 50, 05, 58, 39, 0e, 26, 92),
+ be64_to_cpua(76, 20, 4a, 77, 22, ec, c8, 66),
+ be64_to_cpua(5f, f8, 74, f8, 57, d0, 5e, 54),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp256r1(sha256) */
+ "\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
+ "\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00"
+ "\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9"
+ "\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e"
+ "\xb8",
+ .key_len = 65,
+ .m =
+ "\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b"
+ "\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4",
+ .m_size = 32,
+ .c = (const unsigned char[]){
+ be64_to_cpua(91, dc, 02, 67, dc, 0c, d0, 82),
+ be64_to_cpua(ac, 44, c3, e8, 24, 11, 2d, a4),
+ be64_to_cpua(09, dc, 29, 63, a8, 1a, ad, fc),
+ be64_to_cpua(08, 31, fa, 74, 0d, 1d, 21, 5d),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(4f, 2a, 65, 35, 23, e3, 1d, fa),
+ be64_to_cpua(0a, 6e, 1b, c4, af, e1, 83, c3),
+ be64_to_cpua(f9, a9, 81, ac, 4a, 50, d0, 91),
+ be64_to_cpua(bd, ff, ce, ee, 42, c3, 97, ff),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp256r1(sha384) */
+ "\x04\xc5\xc6\xea\x60\xc9\xce\xad\x02\x8d\xf5\x3e\x24\xe3\x52\x1d"
+ "\x28\x47\x3b\xc3\x6b\xa4\x99\x35\x99\x11\x88\x88\xc8\xf4\xee\x7e"
+ "\x8c\x33\x8f\x41\x03\x24\x46\x2b\x1a\x82\xf9\x9f\xe1\x97\x1b\x00"
+ "\xda\x3b\x24\x41\xf7\x66\x33\x58\x3d\x3a\x81\xad\xcf\x16\xe9\xe2"
+ "\x7c",
+ .key_len = 65,
+ .m =
+ "\x3e\x78\x70\xfb\xcd\x66\xba\x91\xa1\x79\xff\x1e\x1c\x6b\x78\xe6"
+ "\xc0\x81\x3a\x65\x97\x14\x84\x36\x14\x1a\x9a\xb7\xc5\xab\x84\x94"
+ "\x5e\xbb\x1b\x34\x71\xcb\x41\xe1\xf6\xfc\x92\x7b\x34\xbb\x86\xbb",
+ .m_size = 48,
+ .c = (const unsigned char[]){
+ be64_to_cpua(f2, e4, 6c, c7, 94, b1, d5, fe),
+ be64_to_cpua(08, b2, 6b, 24, 94, 48, 46, 5e),
+ be64_to_cpua(d0, 2e, 95, 54, d1, 95, 64, 93),
+ be64_to_cpua(8e, f3, 6f, dc, f8, 69, a6, 2e),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(c0, 60, 11, 92, dc, 17, 89, 12),
+ be64_to_cpua(69, f4, 3b, 4f, 47, cf, 9b, 16),
+ be64_to_cpua(19, fb, 5f, 92, f4, c9, 23, 37),
+ be64_to_cpua(eb, a7, 80, 26, dc, f9, 3a, 44),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp256r1(sha512) */
+ "\x04\xd7\x27\x46\x49\xf6\x26\x85\x12\x40\x76\x8e\xe2\xe6\x2a\x7a"
+ "\x83\xb1\x4e\x7a\xeb\x3b\x5c\x67\x4a\xb5\xa4\x92\x8c\x69\xff\x38"
+ "\xee\xd9\x4e\x13\x29\x59\xad\xde\x6b\xbb\x45\x31\xee\xfd\xd1\x1b"
+ "\x64\xd3\xb5\xfc\xaf\x9b\x4b\x88\x3b\x0e\xb7\xd6\xdf\xf1\xd5\x92"
+ "\xbf",
+ .key_len = 65,
+ .m =
+ "\x57\xb7\x9e\xe9\x05\x0a\x8c\x1b\xc9\x13\xe5\x4a\x24\xc7\xe2\xe9"
+ "\x43\xc3\xd1\x76\x62\xf4\x98\x1a\x9c\x13\xb0\x20\x1b\xe5\x39\xca"
+ "\x4f\xd9\x85\x34\x95\xa2\x31\xbc\xbb\xde\xdd\x76\xbb\x61\xe3\xcf"
+ "\x9d\xc0\x49\x7a\xf3\x7a\xc4\x7d\xa8\x04\x4b\x8d\xb4\x4d\x5b\xd6",
+ .m_size = 64,
+ .c = (const unsigned char[]){
+ be64_to_cpua(76, f6, 04, 99, 09, 37, 4d, fa),
+ be64_to_cpua(ed, 8c, 73, 30, 6c, 22, b3, 97),
+ be64_to_cpua(40, ea, 44, 81, 00, 4e, 29, 08),
+ be64_to_cpua(b8, 6d, 87, 81, 43, df, fb, 9f),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(76, 31, 79, 4a, e9, 81, 6a, ee),
+ be64_to_cpua(5c, ad, c3, 78, 1c, c2, c1, 19),
+ be64_to_cpua(f8, 00, dd, ab, d4, c0, 2b, e6),
+ be64_to_cpua(1e, b9, 75, 31, f6, 04, a5, 4d),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ },
+};
+
+static const struct sig_testvec ecdsa_nist_p384_tv_template[] = {
+ {
+ .key = /* secp384r1(sha1) */
+ "\x04\x89\x25\xf3\x97\x88\xcb\xb0\x78\xc5\x72\x9a\x14\x6e\x7a\xb1"
+ "\x5a\xa5\x24\xf1\x95\x06\x9e\x28\xfb\xc4\xb9\xbe\x5a\x0d\xd9\x9f"
+ "\xf3\xd1\x4d\x2d\x07\x99\xbd\xda\xa7\x66\xec\xbb\xea\xba\x79\x42"
+ "\xc9\x34\x89\x6a\xe7\x0b\xc3\xf2\xfe\x32\x30\xbe\xba\xf9\xdf\x7e"
+ "\x4b\x6a\x07\x8e\x26\x66\x3f\x1d\xec\xa2\x57\x91\x51\xdd\x17\x0e"
+ "\x0b\x25\xd6\x80\x5c\x3b\xe6\x1a\x98\x48\x91\x45\x7a\x73\xb0\xc3"
+ "\xf1",
+ .key_len = 97,
+ .m =
+ "\x12\x55\x28\xf0\x77\xd5\xb6\x21\x71\x32\x48\xcd\x28\xa8\x25\x22"
+ "\x3a\x69\xc1\x93",
+ .m_size = 20,
+ .c = (const unsigned char[]){
+ be64_to_cpua(ec, 7c, 7e, d0, 87, d7, d7, 6e),
+ be64_to_cpua(78, f1, 4c, 26, e6, 5b, 86, cf),
+ be64_to_cpua(3a, c6, f1, 32, 3c, ce, 70, 2b),
+ be64_to_cpua(8d, 26, 8e, ae, 63, 3f, bc, 20),
+ be64_to_cpua(57, 55, 07, 20, 43, 30, de, a0),
+ be64_to_cpua(f5, 0f, 24, 4c, 07, 93, 6f, 21),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(79, 12, 2a, b7, c5, 15, 92, c5),
+ be64_to_cpua(4a, a1, 59, f1, 1c, a4, 58, 26),
+ be64_to_cpua(74, a0, 0f, bf, af, c3, 36, 76),
+ be64_to_cpua(df, 28, 8c, 1b, fa, f9, 95, 88),
+ be64_to_cpua(5f, 63, b1, be, 5e, 4c, 0e, a1),
+ be64_to_cpua(cd, bb, 7e, 81, 5d, 8f, 63, c0),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp384r1(sha224) */
+ "\x04\x69\x6c\xcf\x62\xee\xd0\x0d\xe5\xb5\x2f\x70\x54\xcf\x26\xa0"
+ "\xd9\x98\x8d\x92\x2a\xab\x9b\x11\xcb\x48\x18\xa1\xa9\x0d\xd5\x18"
+ "\x3e\xe8\x29\x6e\xf6\xe4\xb5\x8e\xc7\x4a\xc2\x5f\x37\x13\x99\x05"
+ "\xb6\xa4\x9d\xf9\xfb\x79\x41\xe7\xd7\x96\x9f\x73\x3b\x39\x43\xdc"
+ "\xda\xf4\x06\xb9\xa5\x29\x01\x9d\x3b\xe1\xd8\x68\x77\x2a\xf4\x50"
+ "\x6b\x93\x99\x6c\x66\x4c\x42\x3f\x65\x60\x6c\x1c\x0b\x93\x9b\x9d"
+ "\xe0",
+ .key_len = 97,
+ .m =
+ "\x12\x80\xb6\xeb\x25\xe2\x3d\xf0\x21\x32\x96\x17\x3a\x38\x39\xfd"
+ "\x1f\x05\x34\x7b\xb8\xf9\x71\x66\x03\x4f\xd5\xe5",
+ .m_size = 28,
+ .c = (const unsigned char[]){
+ be64_to_cpua(3f, dd, 15, 1b, 68, 2b, 9d, 8b),
+ be64_to_cpua(c9, 9c, 11, b8, 10, 01, c5, 41),
+ be64_to_cpua(c5, da, b4, e3, 93, 07, e0, 99),
+ be64_to_cpua(97, f1, c8, 72, 26, cf, 5a, 5e),
+ be64_to_cpua(ec, cb, e4, 89, 47, b2, f7, bc),
+ be64_to_cpua(8a, 51, 84, ce, 13, 1e, d2, dc),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(88, 2b, 82, 26, 5e, 1c, da, fb),
+ be64_to_cpua(9f, 19, d0, 42, 8b, 93, c2, 11),
+ be64_to_cpua(4d, d0, c6, 6e, b0, e9, fc, 14),
+ be64_to_cpua(df, d8, 68, a2, 64, 42, 65, f3),
+ be64_to_cpua(4b, 00, 08, 31, 6c, f5, d5, f6),
+ be64_to_cpua(8b, 03, 2c, fc, 1f, d1, a9, a4),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp384r1(sha256) */
+ "\x04\xee\xd6\xda\x3e\x94\x90\x00\x27\xed\xf8\x64\x55\xd6\x51\x9a"
+ "\x1f\x52\x00\x63\x78\xf1\xa9\xfd\x75\x4c\x9e\xb2\x20\x1a\x91\x5a"
+ "\xba\x7a\xa3\xe5\x6c\xb6\x25\x68\x4b\xe8\x13\xa6\x54\x87\x2c\x0e"
+ "\xd0\x83\x95\xbc\xbf\xc5\x28\x4f\x77\x1c\x46\xa6\xf0\xbc\xd4\xa4"
+ "\x8d\xc2\x8f\xb3\x32\x37\x40\xd6\xca\xf8\xae\x07\x34\x52\x39\x52"
+ "\x17\xc3\x34\x29\xd6\x40\xea\x5c\xb9\x3f\xfb\x32\x2e\x12\x33\xbc"
+ "\xab",
+ .key_len = 97,
+ .m =
+ "\xaa\xe7\xfd\x03\x26\xcb\x94\x71\xe4\xce\x0f\xc5\xff\xa6\x29\xa3"
+ "\xe1\xcc\x4c\x35\x4e\xde\xca\x80\xab\x26\x0c\x25\xe6\x68\x11\xc2",
+ .m_size = 32,
+ .c = (const unsigned char[]){
+ be64_to_cpua(c8, 8d, 2c, 79, 3a, 8e, 32, c4),
+ be64_to_cpua(b6, c6, fc, 70, 2e, 66, 3c, 77),
+ be64_to_cpua(af, 06, 3f, 84, 04, e2, f9, 67),
+ be64_to_cpua(cc, 47, 53, 87, bc, bd, 83, 3f),
+ be64_to_cpua(8e, 3f, 7e, ce, 0a, 9b, aa, 59),
+ be64_to_cpua(08, 09, 12, 9d, 6e, 96, 64, a6),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(10, 0e, f4, 1f, 39, ca, 4d, 43),
+ be64_to_cpua(4f, 8d, de, 1e, 93, 8d, 95, bb),
+ be64_to_cpua(15, 68, c0, 75, 3e, 23, 5e, 36),
+ be64_to_cpua(dd, ce, bc, b2, 97, f4, 9c, f3),
+ be64_to_cpua(26, a2, b0, 89, 42, 0a, da, d9),
+ be64_to_cpua(40, 34, b8, 90, a9, 80, ab, 47),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp384r1(sha384) */
+ "\x04\x3a\x2f\x62\xe7\x1a\xcf\x24\xd0\x0b\x7c\xe0\xed\x46\x0a\x4f"
+ "\x74\x16\x43\xe9\x1a\x25\x7c\x55\xff\xf0\x29\x68\x66\x20\x91\xf9"
+ "\xdb\x2b\xf6\xb3\x6c\x54\x01\xca\xc7\x6a\x5c\x0d\xeb\x68\xd9\x3c"
+ "\xf1\x01\x74\x1f\xf9\x6c\xe5\x5b\x60\xe9\x7f\x5d\xb3\x12\x80\x2a"
+ "\xd8\x67\x92\xc9\x0e\x4c\x4c\x6b\xa1\xb2\xa8\x1e\xac\x1c\x97\xd9"
+ "\x21\x67\xe5\x1b\x5a\x52\x31\x68\xd6\xee\xf0\x19\xb0\x55\xed\x89"
+ "\x9e",
+ .key_len = 97,
+ .m =
+ "\x8d\xf2\xc0\xe9\xa8\xf3\x8e\x44\xc4\x8c\x1a\xa0\xb8\xd7\x17\xdf"
+ "\xf2\x37\x1b\xc6\xe3\xf5\x62\xcc\x68\xf5\xd5\x0b\xbf\x73\x2b\xb1"
+ "\xb0\x4c\x04\x00\x31\xab\xfe\xc8\xd6\x09\xc8\xf2\xea\xd3\x28\xff",
+ .m_size = 48,
+ .c = (const unsigned char[]){
+ be64_to_cpua(a2, a4, c8, f2, ea, 9d, 11, 1f),
+ be64_to_cpua(3b, 1f, 07, 8f, 15, 02, fe, 1d),
+ be64_to_cpua(29, e6, fb, ca, 8c, d6, b6, b4),
+ be64_to_cpua(2d, 7a, 91, 5f, 49, 2d, 22, 08),
+ be64_to_cpua(ee, 2e, 62, 35, 46, fa, 00, d8),
+ be64_to_cpua(9b, 28, 68, c0, a1, ea, 8c, 50),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(ab, 8d, 4e, de, e6, 6d, 9b, 66),
+ be64_to_cpua(96, 17, 04, c9, 05, 77, f1, 8e),
+ be64_to_cpua(44, 92, 8c, 86, 99, 65, b3, 97),
+ be64_to_cpua(71, cd, 8f, 18, 99, f0, 0f, 13),
+ be64_to_cpua(bf, e3, 75, 24, 49, ac, fb, c8),
+ be64_to_cpua(fc, 50, f6, 43, bd, 50, 82, 0e),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ }, {
+ .key = /* secp384r1(sha512) */
+ "\x04\xb4\xe7\xc1\xeb\x64\x25\x22\x46\xc3\x86\x61\x80\xbe\x1e\x46"
+ "\xcb\xf6\x05\xc2\xee\x73\x83\xbc\xea\x30\x61\x4d\x40\x05\x41\xf4"
+ "\x8c\xe3\x0e\x5c\xf0\x50\xf2\x07\x19\xe8\x4f\x25\xbe\xee\x0c\x95"
+ "\x54\x36\x86\xec\xc2\x20\x75\xf3\x89\xb5\x11\xa1\xb7\xf5\xaf\xbe"
+ "\x81\xe4\xc3\x39\x06\xbd\xe4\xfe\x68\x1c\x6d\x99\x2b\x1b\x63\xfa"
+ "\xdf\x42\x5c\xc2\x5a\xc7\x0c\xf4\x15\xf7\x1b\xa3\x2e\xd7\x00\xac"
+ "\xa3",
+ .key_len = 97,
+ .m =
+ "\xe8\xb7\x52\x7d\x1a\x44\x20\x05\x53\x6b\x3a\x68\xf2\xe7\x6c\xa1"
+ "\xae\x9d\x84\xbb\xba\x52\x43\x3e\x2c\x42\x78\x49\xbf\x78\xb2\x71"
+ "\xeb\xe1\xe0\xe8\x42\x7b\x11\xad\x2b\x99\x05\x1d\x36\xe6\xac\xfc"
+ "\x55\x73\xf0\x15\x63\x39\xb8\x6a\x6a\xc5\x91\x5b\xca\x6a\xa8\x0e",
+ .m_size = 64,
+ .c = (const unsigned char[]){
+ be64_to_cpua(3e, b3, c7, a8, b3, 17, 77, d1),
+ be64_to_cpua(dc, 2b, 43, 0e, 6a, b3, 53, 6f),
+ be64_to_cpua(4c, fc, 6f, 80, e3, af, b3, d9),
+ be64_to_cpua(9a, 02, de, 93, e8, 83, e4, 84),
+ be64_to_cpua(4d, c6, ef, da, 02, e7, 0f, 52),
+ be64_to_cpua(00, 1d, 20, 94, 77, fe, 31, fa),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(4e, 45, cf, 3c, 93, ff, 50, 5d),
+ be64_to_cpua(34, e4, 8b, 80, a5, b6, da, 2c),
+ be64_to_cpua(c4, 6a, 03, 5f, 8d, 7a, f9, fb),
+ be64_to_cpua(ec, 63, e3, 0c, ec, 50, dc, cc),
+ be64_to_cpua(de, 3a, 3d, 16, af, b4, 52, 6a),
+ be64_to_cpua(63, f6, f0, 3d, 5f, 5f, 99, 3f),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ },
+};
+
+static const struct sig_testvec ecdsa_nist_p521_tv_template[] = {
+ {
+ .key = /* secp521r1(sha224) */
+ "\x04\x01\x4f\x43\x18\xb6\xa9\xc9\x5d\x68\xd3\xa9\x42\xf8\x98\xc0"
+ "\xd2\xd1\xa9\x50\x3b\xe8\xc4\x40\xe6\x11\x78\x88\x4b\xbd\x76\xa7"
+ "\x9a\xe0\xdd\x31\xa4\x67\x78\x45\x33\x9e\x8c\xd1\xc7\x44\xac\x61"
+ "\x68\xc8\x04\xe7\x5c\x79\xb1\xf1\x41\x0c\x71\xc0\x53\xa8\xbc\xfb"
+ "\xf5\xca\xd4\x01\x40\xfd\xa3\x45\xda\x08\xe0\xb4\xcb\x28\x3b\x0a"
+ "\x02\x35\x5f\x02\x9f\x3f\xcd\xef\x08\x22\x40\x97\x74\x65\xb7\x76"
+ "\x85\xc7\xc0\x5c\xfb\x81\xe1\xa5\xde\x0c\x4e\x8b\x12\x31\xb6\x47"
+ "\xed\x37\x0f\x99\x3f\x26\xba\xa3\x8e\xff\x79\x34\x7c\x3a\xfe\x1f"
+ "\x3b\x83\x82\x2f\x14",
+ .key_len = 133,
+ .m =
+ "\xa2\x3a\x6a\x8c\x7b\x3c\xf2\x51\xf8\xbe\x5f\x4f\x3b\x15\x05\xc4"
+ "\xb5\xbc\x19\xe7\x21\x85\xe9\x23\x06\x33\x62\xfb",
+ .m_size = 28,
+ .c = (const unsigned char[]){
+ be64_to_cpua(46, 6b, c7, af, 7a, b9, 19, 0a),
+ be64_to_cpua(6c, a6, 9b, 89, 8b, 1e, fd, 09),
+ be64_to_cpua(98, 85, 29, 88, ff, 0b, 94, 94),
+ be64_to_cpua(18, c6, 37, 8a, cb, a7, d8, 7d),
+ be64_to_cpua(f8, 3f, 59, 0f, 74, f0, 3f, d8),
+ be64_to_cpua(e2, ef, 07, 92, ee, 60, 94, 06),
+ be64_to_cpua(35, f6, dc, 6d, 02, 7b, 22, ac),
+ be64_to_cpua(d6, 43, e7, ff, 42, b2, ba, 74),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 01),
+ be64_to_cpua(50, b1, a5, 98, 92, 2a, a5, 52),
+ be64_to_cpua(1c, ad, 22, da, 82, 00, 35, a3),
+ be64_to_cpua(0e, 64, cc, c4, e8, 43, d9, 0e),
+ be64_to_cpua(30, 90, 0f, 1c, 8f, 78, d3, 9f),
+ be64_to_cpua(26, 0b, 5f, 49, 32, 6b, 91, 99),
+ be64_to_cpua(0f, f8, 65, 97, 6b, 09, 4d, 22),
+ be64_to_cpua(5e, f9, 88, f3, d2, 32, 90, 57),
+ be64_to_cpua(26, 0d, 55, cd, 23, 1e, 7d, a0),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 3a) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ },
+ {
+ .key = /* secp521r1(sha256) */
+ "\x04\x01\x05\x3a\x6b\x3b\x5a\x0f\xa7\xb9\xb7\x32\x53\x4e\xe2\xae"
+ "\x0a\x52\xc5\xda\xdd\x5a\x79\x1c\x30\x2d\x33\x07\x79\xd5\x70\x14"
+ "\x61\x0c\xec\x26\x4d\xd8\x35\x57\x04\x1d\x88\x33\x4d\xce\x05\x36"
+ "\xa5\xaf\x56\x84\xfa\x0b\x9e\xff\x7b\x30\x4b\x92\x1d\x06\xf8\x81"
+ "\x24\x1e\x51\x00\x09\x21\x51\xf7\x46\x0a\x77\xdb\xb5\x0c\xe7\x9c"
+ "\xff\x27\x3c\x02\x71\xd7\x85\x36\xf1\xaa\x11\x59\xd8\xb8\xdc\x09"
+ "\xdc\x6d\x5a\x6f\x63\x07\x6c\xe1\xe5\x4d\x6e\x0f\x6e\xfb\x7c\x05"
+ "\x8a\xe9\x53\xa8\xcf\xce\x43\x0e\x82\x20\x86\xbc\x88\x9c\xb7\xe3"
+ "\xe6\x77\x1e\x1f\x8a",
+ .key_len = 133,
+ .m =
+ "\xcc\x97\x73\x0c\x73\xa2\x53\x2b\xfa\xd7\x83\x1d\x0c\x72\x1b\x39"
+ "\x80\x71\x8d\xdd\xc5\x9b\xff\x55\x32\x98\x25\xa2\x58\x2e\xb7\x73",
+ .m_size = 32,
+ .c = (const unsigned char[]){
+ be64_to_cpua(de, 7e, d7, 59, 10, e9, d9, d5),
+ be64_to_cpua(38, 1f, 46, 0b, 04, 64, 34, 79),
+ be64_to_cpua(ae, ce, 54, 76, 9a, c2, 8f, b8),
+ be64_to_cpua(95, 35, 6f, 02, 0e, af, e1, 4c),
+ be64_to_cpua(56, 3c, f6, f0, d8, e1, b7, 5d),
+ be64_to_cpua(50, 9f, 7d, 1f, ca, 8b, a8, 2d),
+ be64_to_cpua(06, 0f, fd, 83, fc, 0e, d9, ce),
+ be64_to_cpua(a5, 5f, 57, 52, 27, 78, 3a, b5),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, cd),
+ be64_to_cpua(55, 38, b6, f6, 34, 65, c7, bd),
+ be64_to_cpua(1c, 57, 56, 8f, 12, b7, 1d, 91),
+ be64_to_cpua(03, 42, 02, 5f, 50, f0, a2, 0d),
+ be64_to_cpua(fa, 10, dd, 9b, fb, 36, 1a, 31),
+ be64_to_cpua(e0, 87, 2c, 44, 4b, 5a, ee, af),
+ be64_to_cpua(a9, 79, 24, b9, 37, 35, dd, a0),
+ be64_to_cpua(6b, 35, ae, 65, b5, 99, 12, 0a),
+ be64_to_cpua(50, 85, 38, f9, 15, 83, 18, 04),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 01, cf) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ },
+ {
+ .key = /* secp521r1(sha384) */
+ "\x04\x00\x2e\xd6\x21\x04\x75\xc3\xdc\x7d\xff\x0e\xf3\x70\x25\x2b"
+ "\xad\x72\xfc\x5a\x91\xf1\xd5\x9c\x64\xf3\x1f\x47\x11\x10\x62\x33"
+ "\xfd\x2e\xe8\x32\xca\x9e\x6f\x0a\x4c\x5b\x35\x9a\x46\xc5\xe7\xd4"
+ "\x38\xda\xb2\xf0\xf4\x87\xf3\x86\xf4\xea\x70\xad\x1e\xd4\x78\x8c"
+ "\x36\x18\x17\x00\xa2\xa0\x34\x1b\x2e\x6a\xdf\x06\xd6\x99\x2d\x47"
+ "\x50\x92\x1a\x8a\x72\x9c\x23\x44\xfa\xa7\xa9\xed\xa6\xef\x26\x14"
+ "\xb3\x9d\xfe\x5e\xa3\x8c\xd8\x29\xf8\xdf\xad\xa6\xab\xfc\xdd\x46"
+ "\x22\x6e\xd7\x35\xc7\x23\xb7\x13\xae\xb6\x34\xff\xd7\x80\xe5\x39"
+ "\xb3\x3b\x5b\x1b\x94",
+ .key_len = 133,
+ .m =
+ "\x36\x98\xd6\x82\xfa\xad\xed\x3c\xb9\x40\xb6\x4d\x9e\xb7\x04\x26"
+ "\xad\x72\x34\x44\xd2\x81\xb4\x9b\xbe\x01\x04\x7a\xd8\x50\xf8\x59"
+ "\xba\xad\x23\x85\x6b\x59\xbe\xfb\xf6\x86\xd4\x67\xa8\x43\x28\x76",
+ .m_size = 48,
+ .c = (const unsigned char[]){
+ be64_to_cpua(b8, 6a, dd, fb, e6, 63, 4e, 28),
+ be64_to_cpua(84, 59, fd, 1a, c4, 40, dd, 43),
+ be64_to_cpua(32, 76, 06, d0, f9, c0, e4, e6),
+ be64_to_cpua(e4, df, 9b, 7d, 9e, 47, ca, 33),
+ be64_to_cpua(7e, 42, 71, 86, 57, 2d, f1, 7d),
+ be64_to_cpua(f2, 4b, 64, 98, f7, ec, da, c7),
+ be64_to_cpua(ec, 51, dc, e8, 35, 5e, ae, 16),
+ be64_to_cpua(96, 76, 3c, 27, ea, aa, 9c, 26),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 93),
+ be64_to_cpua(c6, 4f, ab, 2b, 62, c1, 42, b1),
+ be64_to_cpua(e5, 5a, 94, 56, cf, 8f, b4, 22),
+ be64_to_cpua(6a, c3, f3, 7a, d1, fa, e7, a7),
+ be64_to_cpua(df, c4, c0, db, 54, db, 8a, 0d),
+ be64_to_cpua(da, a7, cd, 26, 28, 76, 3b, 52),
+ be64_to_cpua(e4, 3c, bc, 93, 65, 57, 1c, 30),
+ be64_to_cpua(55, ce, 37, 97, c9, 05, 51, e5),
+ be64_to_cpua(c3, 6a, 87, 6e, b5, 13, 1f, 20),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 00, ff) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ },
+ {
+ .key = /* secp521r1(sha512) */
+ "\x04\x00\xc7\x65\xee\x0b\x86\x7d\x8f\x02\xf1\x74\x5b\xb0\x4c\x3f"
+ "\xa6\x35\x60\x9f\x55\x23\x11\xcc\xdf\xb8\x42\x99\xee\x6c\x96\x6a"
+ "\x27\xa2\x56\xb2\x2b\x03\xad\x0f\xe7\x97\xde\x09\x5d\xb4\xc5\x5f"
+ "\xbd\x87\x37\xbf\x5a\x16\x35\x56\x08\xfd\x6f\x06\x1a\x1c\x84\xee"
+ "\xc3\x64\xb3\x00\x9e\xbd\x6e\x60\x76\xee\x69\xfd\x3a\xb8\xcd\x7e"
+ "\x91\x68\x53\x57\x44\x13\x2e\x77\x09\x2a\xbe\x48\xbd\x91\xd8\xf6"
+ "\x21\x16\x53\x99\xd5\xf0\x40\xad\xa6\xf8\x58\x26\xb6\x9a\xf8\x77"
+ "\xfe\x3a\x05\x1a\xdb\xa9\x0f\xc0\x6c\x76\x30\x8c\xd8\xde\x44\xae"
+ "\xd0\x17\xdf\x49\x6a",
+ .key_len = 133,
+ .m =
+ "\x5c\xa6\xbc\x79\xb8\xa0\x1e\x11\x83\xf7\xe9\x05\xdf\xba\xf7\x69"
+ "\x97\x22\x32\xe4\x94\x7c\x65\xbd\x74\xc6\x9a\x8b\xbd\x0d\xdc\xed"
+ "\xf5\x9c\xeb\xe1\xc5\x68\x40\xf2\xc7\x04\xde\x9e\x0d\x76\xc5\xa3"
+ "\xf9\x3c\x6c\x98\x08\x31\xbd\x39\xe8\x42\x7f\x80\x39\x6f\xfe\x68",
+ .m_size = 64,
+ .c = (const unsigned char[]){
+ be64_to_cpua(28, b5, 04, b0, b6, 33, 1c, 7e),
+ be64_to_cpua(80, a6, 13, fc, b6, 90, f7, bb),
+ be64_to_cpua(27, 93, e8, 6c, 49, 7d, 28, fc),
+ be64_to_cpua(1f, 12, 3e, b7, 7e, 51, ff, 7f),
+ be64_to_cpua(fb, 62, 1e, 42, 03, 6c, 74, 8a),
+ be64_to_cpua(63, 0e, 02, cc, 94, a9, 05, b9),
+ be64_to_cpua(aa, 86, ec, a8, 05, 03, 52, 56),
+ be64_to_cpua(71, 86, 96, ac, 21, 33, 7e, 4e),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 01, 5c),
+ be64_to_cpua(46, 1e, 77, 44, 78, e0, d1, 04),
+ be64_to_cpua(72, 74, 13, 63, 39, a6, e5, 25),
+ be64_to_cpua(00, 55, bb, 6a, b4, 73, 00, d2),
+ be64_to_cpua(71, d0, e9, ca, a7, c0, cb, aa),
+ be64_to_cpua(7a, 76, 37, 51, 47, 49, 98, 12),
+ be64_to_cpua(88, 05, 3e, 43, 39, 01, bd, b7),
+ be64_to_cpua(95, 35, 89, 4f, 41, 5f, 9e, 19),
+ be64_to_cpua(43, 52, 1d, e3, c6, bd, 5a, 40),
+ be64_to_cpua(00, 00, 00, 00, 00, 00, 01, 70) },
+ .c_size = ECC_MAX_BYTES * 2,
+ .public_key_vec = true,
+ },
+};
+
+/*
+ * ECDSA X9.62 test vectors.
+ *
+ * Identical to ECDSA test vectors, except signature in "c" is X9.62 encoded.
+ */
+static const struct sig_testvec x962_ecdsa_nist_p192_tv_template[] = {
+ {
+ .key = /* secp192r1(sha1) */
"\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
"\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68"
"\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08"
"\x98",
.key_len = 49,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x01",
- .param_len = 21,
.m =
"\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae"
"\x63\x85\xe7\x82",
.m_size = 20,
- .algo = OID_id_ecdsa_with_sha1,
.c =
"\x30\x35\x02\x19\x00\xba\xe5\x93\x83\x6e\xb6\x3b\x63\xa0\x27\x91"
"\xc6\xf6\x7f\xc3\x09\xad\x59\xad\x88\x27\xd6\x92\x6b\x02\x18\x10"
@@ -674,23 +1371,17 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
"\x80\x6f\xa5\x79\x77\xda\xd0",
.c_size = 55,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp192r1(sha224) */
"\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
"\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75"
"\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee"
"\xa3",
.key_len = 49,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x01",
- .param_len = 21,
.m =
"\x8d\xd6\xb8\x3e\xe5\xff\x23\xf6\x25\xa2\x43\x42\x74\x45\xa7\x40"
"\x3a\xff\x2f\xe1\xd3\xf6\x9f\xe8\x33\xcb\x12\x11",
.m_size = 28,
- .algo = OID_id_ecdsa_with_sha224,
.c =
"\x30\x34\x02\x18\x5a\x8b\x82\x69\x7e\x8a\x0a\x09\x14\xf8\x11\x2b"
"\x55\xdc\xae\x37\x83\x7b\x12\xe6\xb6\x5b\xcb\xd4\x02\x18\x6a\x14"
@@ -698,23 +1389,17 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
"\x5c\x99\xdb\x92\x5b\x36",
.c_size = 54,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp192r1(sha256) */
"\x04\xe2\x51\x24\x9b\xf7\xb6\x32\x82\x39\x66\x3d\x5b\xec\x3b\xae"
"\x0c\xd5\xf2\x67\xd1\xc7\xe1\x02\xe4\xbf\x90\x62\xb8\x55\x75\x56"
"\x69\x20\x5e\xcb\x4e\xca\x33\xd6\xcb\x62\x6b\x94\xa9\xa2\xe9\x58"
"\x91",
.key_len = 49,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x01",
- .param_len = 21,
.m =
"\x35\xec\xa1\xa0\x9e\x14\xde\x33\x03\xb6\xf6\xbd\x0c\x2f\xb2\xfd"
"\x1f\x27\x82\xa5\xd7\x70\x3f\xef\xa0\x82\x69\x8e\x73\x31\x8e\xd7",
.m_size = 32,
- .algo = OID_id_ecdsa_with_sha256,
.c =
"\x30\x35\x02\x18\x3f\x72\x3f\x1f\x42\xd2\x3f\x1d\x6b\x1a\x58\x56"
"\xf1\x8f\xf7\xfd\x01\x48\xfb\x5f\x72\x2a\xd4\x8f\x02\x19\x00\xb3"
@@ -722,24 +1407,18 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
"\x3a\x97\xd9\xcd\x1a\x6a\x49",
.c_size = 55,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp192r1(sha384) */
"\x04\x5a\x13\xfe\x68\x86\x4d\xf4\x17\xc7\xa4\xe5\x8c\x65\x57\xb7"
"\x03\x73\x26\x57\xfb\xe5\x58\x40\xd8\xfd\x49\x05\xab\xf1\x66\x1f"
"\xe2\x9d\x93\x9e\xc2\x22\x5a\x8b\x4f\xf3\x77\x22\x59\x7e\xa6\x4e"
"\x8b",
.key_len = 49,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x01",
- .param_len = 21,
.m =
"\x9d\x2e\x1a\x8f\xed\x6c\x4b\x61\xae\xac\xd5\x19\x79\xce\x67\xf9"
"\xa0\x34\xeb\xb0\x81\xf9\xd9\xdc\x6e\xb3\x5c\xa8\x69\xfc\x8a\x61"
"\x39\x81\xfb\xfd\x5c\x30\x6b\xa8\xee\xed\x89\xaf\xa3\x05\xe4\x78",
.m_size = 48,
- .algo = OID_id_ecdsa_with_sha384,
.c =
"\x30\x35\x02\x19\x00\xf0\xa3\x38\xce\x2b\xf8\x9d\x1a\xcf\x7f\x34"
"\xb4\xb4\xe5\xc5\x00\xdd\x15\xbb\xd6\x8c\xa7\x03\x78\x02\x18\x64"
@@ -747,25 +1426,19 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
"\x12\x3b\x3b\x28\xfb\x6d\xe1",
.c_size = 55,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp192r1(sha512) */
"\x04\xd5\xf2\x6e\xc3\x94\x5c\x52\xbc\xdf\x86\x6c\x14\xd1\xca\xea"
"\xcc\x72\x3a\x8a\xf6\x7a\x3a\x56\x36\x3b\xca\xc6\x94\x0e\x17\x1d"
"\x9e\xa0\x58\x28\xf9\x4b\xe6\xd1\xa5\x44\x91\x35\x0d\xe7\xf5\x11"
"\x57",
.key_len = 49,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x01",
- .param_len = 21,
.m =
"\xd5\x4b\xe9\x36\xda\xd8\x6e\xc0\x50\x03\xbe\x00\x43\xff\xf0\x23"
"\xac\xa2\x42\xe7\x37\x77\x79\x52\x8f\x3e\xc0\x16\xc1\xfc\x8c\x67"
"\x16\xbc\x8a\x5d\x3b\xd3\x13\xbb\xb6\xc0\x26\x1b\xeb\x33\xcc\x70"
"\x4a\xf2\x11\x37\xe8\x1b\xba\x55\xac\x69\xe1\x74\x62\x7c\x6e\xb5",
.m_size = 64,
- .algo = OID_id_ecdsa_with_sha512,
.c =
"\x30\x35\x02\x19\x00\x88\x5b\x8f\x59\x43\xbf\xcf\xc6\xdd\x3f\x07"
"\x87\x12\xa0\xd4\xac\x2b\x11\x2d\x1c\xb6\x06\xc9\x6c\x02\x18\x73"
@@ -773,28 +1446,22 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
"\x6a\xdf\x97\xfd\x82\x76\x24",
.c_size = 55,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
};
-static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
+static const struct sig_testvec x962_ecdsa_nist_p256_tv_template[] = {
{
- .key =
+ .key = /* secp256r1(sha1) */
"\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
"\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9"
"\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc"
"\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8"
"\xaf",
.key_len = 65,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x07",
- .param_len = 21,
.m =
"\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c"
"\x0b\xde\x6a\x42",
.m_size = 20,
- .algo = OID_id_ecdsa_with_sha1,
.c =
"\x30\x46\x02\x21\x00\xf9\x25\xce\x9f\x3a\xa6\x35\x81\xcf\xd4\xe7"
"\xb7\xf0\x82\x56\x41\xf7\xd4\xad\x8d\x94\x5a\x69\x89\xee\xca\x6a"
@@ -803,24 +1470,18 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
"\xfb\x9d\x8b\xde\xd4\x8d\x6f\xad",
.c_size = 72,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp256r1(sha224) */
"\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
"\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0"
"\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88"
"\x43\x13\xbf\xf3\x1c\x05\x1a\x14\x18\x09\x3f\xd6\x28\x3e\xc5\xa0"
"\xd4",
.key_len = 65,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x07",
- .param_len = 21,
.m =
"\x1a\x15\xbc\xa3\xe4\xed\x3a\xb8\x23\x67\xc6\xc4\x34\xf8\x6c\x41"
"\x04\x0b\xda\xc5\x77\xfa\x1c\x2d\xe6\x2c\x3b\xe0",
.m_size = 28,
- .algo = OID_id_ecdsa_with_sha224,
.c =
"\x30\x44\x02\x20\x20\x43\xfa\xc0\x9f\x9d\x7b\xe7\xae\xce\x77\x59"
"\x1a\xdb\x59\xd5\x34\x62\x79\xcb\x6a\x91\x67\x2e\x7d\x25\xd8\x25"
@@ -829,24 +1490,18 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
"\x2e\x8b\xde\x5a\x04\x0e",
.c_size = 70,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp256r1(sha256) */
"\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
"\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00"
"\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9"
"\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e"
"\xb8",
.key_len = 65,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x07",
- .param_len = 21,
.m =
"\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b"
"\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4",
.m_size = 32,
- .algo = OID_id_ecdsa_with_sha256,
.c =
"\x30\x45\x02\x20\x08\x31\xfa\x74\x0d\x1d\x21\x5d\x09\xdc\x29\x63"
"\xa8\x1a\xad\xfc\xac\x44\xc3\xe8\x24\x11\x2d\xa4\x91\xdc\x02\x67"
@@ -855,25 +1510,19 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
"\x2a\x65\x35\x23\xe3\x1d\xfa",
.c_size = 71,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp256r1(sha384) */
"\x04\xc5\xc6\xea\x60\xc9\xce\xad\x02\x8d\xf5\x3e\x24\xe3\x52\x1d"
"\x28\x47\x3b\xc3\x6b\xa4\x99\x35\x99\x11\x88\x88\xc8\xf4\xee\x7e"
"\x8c\x33\x8f\x41\x03\x24\x46\x2b\x1a\x82\xf9\x9f\xe1\x97\x1b\x00"
"\xda\x3b\x24\x41\xf7\x66\x33\x58\x3d\x3a\x81\xad\xcf\x16\xe9\xe2"
"\x7c",
.key_len = 65,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x07",
- .param_len = 21,
.m =
"\x3e\x78\x70\xfb\xcd\x66\xba\x91\xa1\x79\xff\x1e\x1c\x6b\x78\xe6"
"\xc0\x81\x3a\x65\x97\x14\x84\x36\x14\x1a\x9a\xb7\xc5\xab\x84\x94"
"\x5e\xbb\x1b\x34\x71\xcb\x41\xe1\xf6\xfc\x92\x7b\x34\xbb\x86\xbb",
.m_size = 48,
- .algo = OID_id_ecdsa_with_sha384,
.c =
"\x30\x46\x02\x21\x00\x8e\xf3\x6f\xdc\xf8\x69\xa6\x2e\xd0\x2e\x95"
"\x54\xd1\x95\x64\x93\x08\xb2\x6b\x24\x94\x48\x46\x5e\xf2\xe4\x6c"
@@ -882,26 +1531,20 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
"\xc0\x60\x11\x92\xdc\x17\x89\x12",
.c_size = 72,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
- .key =
+ .key = /* secp256r1(sha512) */
"\x04\xd7\x27\x46\x49\xf6\x26\x85\x12\x40\x76\x8e\xe2\xe6\x2a\x7a"
"\x83\xb1\x4e\x7a\xeb\x3b\x5c\x67\x4a\xb5\xa4\x92\x8c\x69\xff\x38"
"\xee\xd9\x4e\x13\x29\x59\xad\xde\x6b\xbb\x45\x31\xee\xfd\xd1\x1b"
"\x64\xd3\xb5\xfc\xaf\x9b\x4b\x88\x3b\x0e\xb7\xd6\xdf\xf1\xd5\x92"
"\xbf",
.key_len = 65,
- .params =
- "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
- "\xce\x3d\x03\x01\x07",
- .param_len = 21,
.m =
"\x57\xb7\x9e\xe9\x05\x0a\x8c\x1b\xc9\x13\xe5\x4a\x24\xc7\xe2\xe9"
"\x43\xc3\xd1\x76\x62\xf4\x98\x1a\x9c\x13\xb0\x20\x1b\xe5\x39\xca"
"\x4f\xd9\x85\x34\x95\xa2\x31\xbc\xbb\xde\xdd\x76\xbb\x61\xe3\xcf"
"\x9d\xc0\x49\x7a\xf3\x7a\xc4\x7d\xa8\x04\x4b\x8d\xb4\x4d\x5b\xd6",
.m_size = 64,
- .algo = OID_id_ecdsa_with_sha512,
.c =
"\x30\x45\x02\x21\x00\xb8\x6d\x87\x81\x43\xdf\xfb\x9f\x40\xea\x44"
"\x81\x00\x4e\x29\x08\xed\x8c\x73\x30\x6c\x22\xb3\x97\x76\xf6\x04"
@@ -910,11 +1553,10 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
"\x31\x79\x4a\xe9\x81\x6a\xee",
.c_size = 71,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
};
-static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
+static const struct sig_testvec x962_ecdsa_nist_p384_tv_template[] = {
{
.key = /* secp384r1(sha1) */
"\x04\x89\x25\xf3\x97\x88\xcb\xb0\x78\xc5\x72\x9a\x14\x6e\x7a\xb1"
@@ -925,15 +1567,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\x0b\x25\xd6\x80\x5c\x3b\xe6\x1a\x98\x48\x91\x45\x7a\x73\xb0\xc3"
"\xf1",
.key_len = 97,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x22",
- .param_len = 18,
.m =
"\x12\x55\x28\xf0\x77\xd5\xb6\x21\x71\x32\x48\xcd\x28\xa8\x25\x22"
"\x3a\x69\xc1\x93",
.m_size = 20,
- .algo = OID_id_ecdsa_with_sha1,
.c =
"\x30\x66\x02\x31\x00\xf5\x0f\x24\x4c\x07\x93\x6f\x21\x57\x55\x07"
"\x20\x43\x30\xde\xa0\x8d\x26\x8e\xae\x63\x3f\xbc\x20\x3a\xc6\xf1"
@@ -944,7 +1581,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\x79\x12\x2a\xb7\xc5\x15\x92\xc5",
.c_size = 104,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
.key = /* secp384r1(sha224) */
"\x04\x69\x6c\xcf\x62\xee\xd0\x0d\xe5\xb5\x2f\x70\x54\xcf\x26\xa0"
@@ -955,15 +1591,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\x6b\x93\x99\x6c\x66\x4c\x42\x3f\x65\x60\x6c\x1c\x0b\x93\x9b\x9d"
"\xe0",
.key_len = 97,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x22",
- .param_len = 18,
.m =
"\x12\x80\xb6\xeb\x25\xe2\x3d\xf0\x21\x32\x96\x17\x3a\x38\x39\xfd"
"\x1f\x05\x34\x7b\xb8\xf9\x71\x66\x03\x4f\xd5\xe5",
.m_size = 28,
- .algo = OID_id_ecdsa_with_sha224,
.c =
"\x30\x66\x02\x31\x00\x8a\x51\x84\xce\x13\x1e\xd2\xdc\xec\xcb\xe4"
"\x89\x47\xb2\xf7\xbc\x97\xf1\xc8\x72\x26\xcf\x5a\x5e\xc5\xda\xb4"
@@ -974,7 +1605,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\x88\x2b\x82\x26\x5e\x1c\xda\xfb",
.c_size = 104,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
.key = /* secp384r1(sha256) */
"\x04\xee\xd6\xda\x3e\x94\x90\x00\x27\xed\xf8\x64\x55\xd6\x51\x9a"
@@ -985,15 +1615,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\x17\xc3\x34\x29\xd6\x40\xea\x5c\xb9\x3f\xfb\x32\x2e\x12\x33\xbc"
"\xab",
.key_len = 97,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x22",
- .param_len = 18,
.m =
"\xaa\xe7\xfd\x03\x26\xcb\x94\x71\xe4\xce\x0f\xc5\xff\xa6\x29\xa3"
"\xe1\xcc\x4c\x35\x4e\xde\xca\x80\xab\x26\x0c\x25\xe6\x68\x11\xc2",
.m_size = 32,
- .algo = OID_id_ecdsa_with_sha256,
.c =
"\x30\x64\x02\x30\x08\x09\x12\x9d\x6e\x96\x64\xa6\x8e\x3f\x7e\xce"
"\x0a\x9b\xaa\x59\xcc\x47\x53\x87\xbc\xbd\x83\x3f\xaf\x06\x3f\x84"
@@ -1004,7 +1629,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\xf4\x1f\x39\xca\x4d\x43",
.c_size = 102,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
.key = /* secp384r1(sha384) */
"\x04\x3a\x2f\x62\xe7\x1a\xcf\x24\xd0\x0b\x7c\xe0\xed\x46\x0a\x4f"
@@ -1015,16 +1639,11 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\x21\x67\xe5\x1b\x5a\x52\x31\x68\xd6\xee\xf0\x19\xb0\x55\xed\x89"
"\x9e",
.key_len = 97,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x22",
- .param_len = 18,
.m =
"\x8d\xf2\xc0\xe9\xa8\xf3\x8e\x44\xc4\x8c\x1a\xa0\xb8\xd7\x17\xdf"
"\xf2\x37\x1b\xc6\xe3\xf5\x62\xcc\x68\xf5\xd5\x0b\xbf\x73\x2b\xb1"
"\xb0\x4c\x04\x00\x31\xab\xfe\xc8\xd6\x09\xc8\xf2\xea\xd3\x28\xff",
.m_size = 48,
- .algo = OID_id_ecdsa_with_sha384,
.c =
"\x30\x66\x02\x31\x00\x9b\x28\x68\xc0\xa1\xea\x8c\x50\xee\x2e\x62"
"\x35\x46\xfa\x00\xd8\x2d\x7a\x91\x5f\x49\x2d\x22\x08\x29\xe6\xfb"
@@ -1035,7 +1654,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\xab\x8d\x4e\xde\xe6\x6d\x9b\x66",
.c_size = 104,
.public_key_vec = true,
- .siggen_sigver_test = true,
}, {
.key = /* secp384r1(sha512) */
"\x04\xb4\xe7\xc1\xeb\x64\x25\x22\x46\xc3\x86\x61\x80\xbe\x1e\x46"
@@ -1046,17 +1664,12 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\xdf\x42\x5c\xc2\x5a\xc7\x0c\xf4\x15\xf7\x1b\xa3\x2e\xd7\x00\xac"
"\xa3",
.key_len = 97,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x22",
- .param_len = 18,
.m =
"\xe8\xb7\x52\x7d\x1a\x44\x20\x05\x53\x6b\x3a\x68\xf2\xe7\x6c\xa1"
"\xae\x9d\x84\xbb\xba\x52\x43\x3e\x2c\x42\x78\x49\xbf\x78\xb2\x71"
"\xeb\xe1\xe0\xe8\x42\x7b\x11\xad\x2b\x99\x05\x1d\x36\xe6\xac\xfc"
"\x55\x73\xf0\x15\x63\x39\xb8\x6a\x6a\xc5\x91\x5b\xca\x6a\xa8\x0e",
.m_size = 64,
- .algo = OID_id_ecdsa_with_sha512,
.c =
"\x30\x63\x02\x2f\x1d\x20\x94\x77\xfe\x31\xfa\x4d\xc6\xef\xda\x02"
"\xe7\x0f\x52\x9a\x02\xde\x93\xe8\x83\xe4\x84\x4c\xfc\x6f\x80\xe3"
@@ -1067,11 +1680,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
"\x3c\x93\xff\x50\x5d",
.c_size = 101,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
};
-static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
+static const struct sig_testvec x962_ecdsa_nist_p521_tv_template[] = {
{
.key = /* secp521r1(sha224) */
"\x04\x01\x4f\x43\x18\xb6\xa9\xc9\x5d\x68\xd3\xa9\x42\xf8\x98\xc0"
@@ -1084,15 +1696,10 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\xed\x37\x0f\x99\x3f\x26\xba\xa3\x8e\xff\x79\x34\x7c\x3a\xfe\x1f"
"\x3b\x83\x82\x2f\x14",
.key_len = 133,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x23",
- .param_len = 18,
.m =
"\xa2\x3a\x6a\x8c\x7b\x3c\xf2\x51\xf8\xbe\x5f\x4f\x3b\x15\x05\xc4"
"\xb5\xbc\x19\xe7\x21\x85\xe9\x23\x06\x33\x62\xfb",
.m_size = 28,
- .algo = OID_id_ecdsa_with_sha224,
.c =
"\x30\x81\x86\x02\x41\x01\xd6\x43\xe7\xff\x42\xb2\xba\x74\x35\xf6"
"\xdc\x6d\x02\x7b\x22\xac\xe2\xef\x07\x92\xee\x60\x94\x06\xf8\x3f"
@@ -1105,7 +1712,6 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\xa3\x50\xb1\xa5\x98\x92\x2a\xa5\x52",
.c_size = 137,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
{
.key = /* secp521r1(sha256) */
@@ -1119,15 +1725,10 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\x8a\xe9\x53\xa8\xcf\xce\x43\x0e\x82\x20\x86\xbc\x88\x9c\xb7\xe3"
"\xe6\x77\x1e\x1f\x8a",
.key_len = 133,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x23",
- .param_len = 18,
.m =
"\xcc\x97\x73\x0c\x73\xa2\x53\x2b\xfa\xd7\x83\x1d\x0c\x72\x1b\x39"
"\x80\x71\x8d\xdd\xc5\x9b\xff\x55\x32\x98\x25\xa2\x58\x2e\xb7\x73",
.m_size = 32,
- .algo = OID_id_ecdsa_with_sha256,
.c =
"\x30\x81\x88\x02\x42\x00\xcd\xa5\x5f\x57\x52\x27\x78\x3a\xb5\x06"
"\x0f\xfd\x83\xfc\x0e\xd9\xce\x50\x9f\x7d\x1f\xca\x8b\xa8\x2d\x56"
@@ -1140,7 +1741,6 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\xb7\x1d\x91\x55\x38\xb6\xf6\x34\x65\xc7\xbd",
.c_size = 139,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
{
.key = /* secp521r1(sha384) */
@@ -1154,16 +1754,11 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\x22\x6e\xd7\x35\xc7\x23\xb7\x13\xae\xb6\x34\xff\xd7\x80\xe5\x39"
"\xb3\x3b\x5b\x1b\x94",
.key_len = 133,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x23",
- .param_len = 18,
.m =
"\x36\x98\xd6\x82\xfa\xad\xed\x3c\xb9\x40\xb6\x4d\x9e\xb7\x04\x26"
"\xad\x72\x34\x44\xd2\x81\xb4\x9b\xbe\x01\x04\x7a\xd8\x50\xf8\x59"
"\xba\xad\x23\x85\x6b\x59\xbe\xfb\xf6\x86\xd4\x67\xa8\x43\x28\x76",
.m_size = 48,
- .algo = OID_id_ecdsa_with_sha384,
.c =
"\x30\x81\x88\x02\x42\x00\x93\x96\x76\x3c\x27\xea\xaa\x9c\x26\xec"
"\x51\xdc\xe8\x35\x5e\xae\x16\xf2\x4b\x64\x98\xf7\xec\xda\xc7\x7e"
@@ -1176,7 +1771,6 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\x8f\xb4\x22\xc6\x4f\xab\x2b\x62\xc1\x42\xb1",
.c_size = 139,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
{
.key = /* secp521r1(sha512) */
@@ -1190,17 +1784,12 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\xfe\x3a\x05\x1a\xdb\xa9\x0f\xc0\x6c\x76\x30\x8c\xd8\xde\x44\xae"
"\xd0\x17\xdf\x49\x6a",
.key_len = 133,
- .params =
- "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
- "\x00\x23",
- .param_len = 18,
.m =
"\x5c\xa6\xbc\x79\xb8\xa0\x1e\x11\x83\xf7\xe9\x05\xdf\xba\xf7\x69"
"\x97\x22\x32\xe4\x94\x7c\x65\xbd\x74\xc6\x9a\x8b\xbd\x0d\xdc\xed"
"\xf5\x9c\xeb\xe1\xc5\x68\x40\xf2\xc7\x04\xde\x9e\x0d\x76\xc5\xa3"
"\xf9\x3c\x6c\x98\x08\x31\xbd\x39\xe8\x42\x7f\x80\x39\x6f\xfe\x68",
.m_size = 64,
- .algo = OID_id_ecdsa_with_sha512,
.c =
"\x30\x81\x88\x02\x42\x01\x5c\x71\x86\x96\xac\x21\x33\x7e\x4e\xaa"
"\x86\xec\xa8\x05\x03\x52\x56\x63\x0e\x02\xcc\x94\xa9\x05\xb9\xfb"
@@ -1213,14 +1802,41 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
"\xa6\xe5\x25\x46\x1e\x77\x44\x78\xe0\xd1\x04",
.c_size = 139,
.public_key_vec = true,
- .siggen_sigver_test = true,
+ },
+};
+
+/*
+ * ECDSA P1363 test vectors.
+ *
+ * Identical to ECDSA test vectors, except signature in "c" is P1363 encoded.
+ */
+static const struct sig_testvec p1363_ecdsa_nist_p256_tv_template[] = {
+ {
+ .key = /* secp256r1(sha256) */
+ "\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
+ "\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00"
+ "\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9"
+ "\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e"
+ "\xb8",
+ .key_len = 65,
+ .m =
+ "\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b"
+ "\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4",
+ .m_size = 32,
+ .c =
+ "\x08\x31\xfa\x74\x0d\x1d\x21\x5d\x09\xdc\x29\x63\xa8\x1a\xad\xfc"
+ "\xac\x44\xc3\xe8\x24\x11\x2d\xa4\x91\xdc\x02\x67\xdc\x0c\xd0\x82"
+ "\xbd\xff\xce\xee\x42\xc3\x97\xff\xf9\xa9\x81\xac\x4a\x50\xd0\x91"
+ "\x0a\x6e\x1b\xc4\xaf\xe1\x83\xc3\x4f\x2a\x65\x35\x23\xe3\x1d\xfa",
+ .c_size = 64,
+ .public_key_vec = true,
},
};
/*
* EC-RDSA test vectors are generated by gost-engine.
*/
-static const struct akcipher_testvec ecrdsa_tv_template[] = {
+static const struct sig_testvec ecrdsa_tv_template[] = {
{
.key =
"\x04\x40\xd5\xa7\x77\xf9\x26\x2f\x8c\xbd\xcc\xe3\x1f\x01\x94\x05"
@@ -1245,7 +1861,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
"\x79\xd2\x76\x64\xa3\xbd\x66\x10\x79\x05\x5a\x06\x42\xec\xb9\xc9",
.m_size = 32,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
{
.key =
@@ -1271,7 +1886,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
"\x11\x23\x4a\x70\x43\x52\x7a\x68\x11\x65\x45\x37\xbb\x25\xb7\x40",
.m_size = 32,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
{
.key =
@@ -1297,7 +1911,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
"\x9f\x16\xc6\x1c\xb1\x3f\x84\x41\x69\xec\x34\xfd\xf1\xf9\xa3\x39",
.m_size = 32,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
{
.key =
@@ -1332,7 +1945,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
"\xa8\xf6\x80\x01\xb9\x27\xac\xd8\x45\x96\x66\xa1\xee\x48\x08\x3f",
.m_size = 64,
.public_key_vec = true,
- .siggen_sigver_test = true,
},
{
.key =
@@ -1367,14 +1979,68 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
"\x6d\xf4\xd2\x45\xc2\x83\xa0\x42\x95\x05\x9d\x89\x8e\x0a\xca\xcc",
.m_size = 64,
.public_key_vec = true,
- .siggen_sigver_test = true,
+ },
+};
+
+/*
+ * PKCS#1 RSA test vectors for hash algorithm "none"
+ * (i.e. the hash in "m" is not prepended by a Full Hash Prefix)
+ *
+ * Obtained from:
+ * https://vcsjones.dev/sometimes-valid-rsa-dotnet/
+ * https://gist.github.com/vcsjones/ab4c2327b53ed018eada76b75ef4fd99
+ */
+static const struct sig_testvec pkcs1_rsa_none_tv_template[] = {
+ {
+ .key =
+ "\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa2\x63\x0b\x39\x44\xb8\xbb"
+ "\x23\xa7\x44\x49\xbb\x0e\xff\xa1\xf0\x61\x0a\x53\x93\xb0\x98\xdb"
+ "\xad\x2c\x0f\x4a\xc5\x6e\xff\x86\x3c\x53\x55\x0f\x15\xce\x04\x3f"
+ "\x2b\xfd\xa9\x96\x96\xd9\xbe\x61\x79\x0b\x5b\xc9\x4c\x86\x76\xe5"
+ "\xe0\x43\x4b\x22\x95\xee\xc2\x2b\x43\xc1\x9f\xd8\x68\xb4\x8e\x40"
+ "\x4f\xee\x85\x38\xb9\x11\xc5\x23\xf2\x64\x58\xf0\x15\x32\x6f\x4e"
+ "\x57\xa1\xae\x88\xa4\x02\xd7\x2a\x1e\xcd\x4b\xe1\xdd\x63\xd5\x17"
+ "\x89\x32\x5b\xb0\x5e\x99\x5a\xa8\x9d\x28\x50\x0e\x17\xee\x96\xdb"
+ "\x61\x3b\x45\x51\x1d\xcf\x12\x56\x0b\x92\x47\xfc\xab\xae\xf6\x66"
+ "\x3d\x47\xac\x70\x72\xe7\x92\xe7\x5f\xcd\x10\xb9\xc4\x83\x64\x94"
+ "\x19\xbd\x25\x80\xe1\xe8\xd2\x22\xa5\xd0\xba\x02\x7a\xa1\x77\x93"
+ "\x5b\x65\xc3\xee\x17\x74\xbc\x41\x86\x2a\xdc\x08\x4c\x8c\x92\x8c"
+ "\x91\x2d\x9e\x77\x44\x1f\x68\xd6\xa8\x74\x77\xdb\x0e\x5b\x32\x8b"
+ "\x56\x8b\x33\xbd\xd9\x63\xc8\x49\x9d\x3a\xc5\xc5\xea\x33\x0b\xd2"
+ "\xf1\xa3\x1b\xf4\x8b\xbe\xd9\xb3\x57\x8b\x3b\xde\x04\xa7\x7a\x22"
+ "\xb2\x24\xae\x2e\xc7\x70\xc5\xbe\x4e\x83\x26\x08\xfb\x0b\xbd\xa9"
+ "\x4f\x99\x08\xe1\x10\x28\x72\xaa\xcd\x02\x03\x01\x00\x01",
+ .key_len = 270,
+ .m =
+ "\x68\xb4\xf9\x26\x34\x31\x25\xdd\x26\x50\x13\x68\xc1\x99\x26\x71"
+ "\x19\xa2\xde\x81",
+ .m_size = 20,
+ .c =
+ "\x6a\xdb\x39\xe5\x63\xb3\x25\xde\x58\xca\xc3\xf1\x36\x9c\x0b\x36"
+ "\xb7\xd6\x69\xf9\xba\xa6\x68\x14\x8c\x24\x52\xd3\x25\xa5\xf3\xad"
+ "\xc9\x47\x44\xde\x06\xd8\x0f\x56\xca\x2d\xfb\x0f\xe9\x99\xe2\x9d"
+ "\x8a\xe8\x7f\xfb\x9a\x99\x96\xf1\x2c\x4a\xe4\xc0\xae\x4d\x29\x47"
+ "\x38\x96\x51\x2f\x6d\x8e\xb8\x88\xbd\x1a\x0a\x70\xbc\x23\x38\x67"
+ "\x62\x22\x01\x23\x71\xe5\xbb\x95\xea\x6b\x8d\x31\x62\xbf\xf0\xc4"
+ "\xb9\x46\xd6\x67\xfc\x4c\xe6\x1f\xd6\x5d\xf7\xa9\xad\x3a\xf1\xbf"
+ "\xa2\xf9\x66\xde\xb6\x8e\xec\x8f\x81\x8d\x1e\x3a\x12\x27\x6a\xfc"
+ "\xae\x92\x9f\xc3\x87\xc3\xba\x8d\x04\xb8\x8f\x0f\x61\x68\x9a\x96"
+ "\x2c\x80\x2c\x32\x40\xde\x9d\xb9\x9b\xe2\xe4\x45\x2e\x91\x47\x5c"
+ "\x47\xa4\x9d\x02\x57\x59\xf7\x75\x5d\x5f\x32\x82\x75\x5d\xe5\x78"
+ "\xc9\x19\x61\x46\x06\x9d\xa5\x1d\xd6\x32\x48\x9a\xdb\x09\x29\x81"
+ "\x14\x2e\xf0\x27\xe9\x37\x13\x74\xec\xa5\xcd\x67\x6b\x19\xf6\x88"
+ "\xf0\xc2\x8b\xa8\x7f\x2f\x76\x5a\x3e\x0c\x47\x5d\xe8\x82\x50\x27"
+ "\x40\xce\x27\x41\x45\xa0\xcf\xaa\x2f\xd3\xad\x3c\xbf\x73\xff\x93"
+ "\xe3\x78\x49\xd9\xa9\x78\x22\x81\x9a\xe5\xe2\x94\xe9\x40\xab\xf1",
+ .c_size = 256,
+ .public_key_vec = true,
},
};
/*
* PKCS#1 RSA test vectors. Obtained from CAVS testing.
*/
-static const struct akcipher_testvec pkcs1pad_rsa_tv_template[] = {
+static const struct sig_testvec pkcs1_rsa_tv_template[] = {
{
.key =
"\x30\x82\x04\xa5\x02\x01\x00\x02\x82\x01\x01\x00\xd7\x1e\x77\x82"
@@ -1486,7 +2152,6 @@ static const struct akcipher_testvec pkcs1pad_rsa_tv_template[] = {
"\xda\x62\x8d\xe1\x2a\x71\x91\x43\x40\x61\x3c\x5a\xbe\x86\xfc\x5b"
"\xe6\xf9\xa9\x16\x31\x1f\xaf\x25\x6d\xc2\x4a\x23\x6e\x63\x02\xa2",
.c_size = 256,
- .siggen_sigver_test = true,
}
};
diff --git a/drivers/accessibility/speakup/Makefile b/drivers/accessibility/speakup/Makefile
index 6f6a83565c0d..14ba1cca87f4 100644
--- a/drivers/accessibility/speakup/Makefile
+++ b/drivers/accessibility/speakup/Makefile
@@ -40,9 +40,7 @@ hostprogs += makemapdata
makemapdata-objs := makemapdata.o
quiet_cmd_mkmap = MKMAP $@
- cmd_mkmap = TOPDIR=$(srctree) \
- SPKDIR=$(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD),$(srctree)/drivers/accessibility/speakup) \
- $(obj)/makemapdata > $@
+ cmd_mkmap = TOPDIR=$(srctree) SPKDIR=$(src) $(obj)/makemapdata > $@
$(obj)/mapdata.h: $(obj)/makemapdata
$(call cmd,mkmap)
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index d67f63d93b2a..d65cd08ba8e1 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -132,8 +132,17 @@ config ACPI_REV_OVERRIDE_POSSIBLE
makes it possible to force the kernel to return "5" as the supported
ACPI revision via the "acpi_rev_override" command line switch.
+config ACPI_EC
+ bool "Embedded Controller"
+ depends on HAS_IOPORT
+ default X86
+ help
+ This driver handles communication with the microcontroller
+ on many x86 laptops and other machines.
+
config ACPI_EC_DEBUGFS
tristate "EC read/write access through /sys/kernel/debug/ec"
+ depends on ACPI_EC
help
Say N to disable Embedded Controller /sys/kernel/debug interface
@@ -433,7 +442,7 @@ config ACPI_HOTPLUG_IOAPIC
config ACPI_SBS
tristate "Smart Battery System"
- depends on X86
+ depends on X86 && ACPI_EC
select POWER_SUPPLY
help
This driver supports the Smart Battery System, another
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 61ca4afe83dc..40208a0f5dfb 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -41,7 +41,7 @@ acpi-y += resource.o
acpi-y += acpi_processor.o
acpi-y += processor_core.o
acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
-acpi-y += ec.o
+acpi-$(CONFIG_ACPI_EC) += ec.o
acpi-$(CONFIG_ACPI_DOCK) += dock.o
acpi-$(CONFIG_PCI) += pci_root.o pci_link.o pci_irq.o
obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 7c5b040a83e8..1f69be8f51a2 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -290,7 +290,7 @@ static void acpi_ac_remove(struct platform_device *pdev)
static struct platform_driver acpi_ac_driver = {
.probe = acpi_ac_probe,
- .remove_new = acpi_ac_remove,
+ .remove = acpi_ac_remove,
.driver = {
.name = "ac",
.acpi_match_table = ac_device_ids,
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 800f97868448..49539f7528c6 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -86,7 +86,7 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (!clk_data->name)
return -ENOMEM;
- strcpy(clk_data->name, obj->string.pointer);
+ strscpy(clk_data->name, obj->string.pointer, obj->string.length);
} else {
/* Set default name to mclk if entry missing in firmware */
clk_data->name = "mclk";
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 42b7220d4cfd..4ec20fd56985 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -462,7 +462,7 @@ MODULE_DEVICE_TABLE(acpi, pad_device_ids);
static struct platform_driver acpi_pad_driver = {
.probe = acpi_pad_probe,
- .remove_new = acpi_pad_remove,
+ .remove = acpi_pad_remove,
.driver = {
.dev_groups = acpi_pad_groups,
.name = "processor_aggregator",
diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c
index b831cb8e53dc..825c2a8acea4 100644
--- a/drivers/acpi/acpi_tad.c
+++ b/drivers/acpi/acpi_tad.c
@@ -684,7 +684,7 @@ static struct platform_driver acpi_tad_driver = {
.acpi_match_table = acpi_tad_ids,
},
.probe = acpi_tad_probe,
- .remove_new = acpi_tad_remove,
+ .remove = acpi_tad_remove,
};
MODULE_DEVICE_TABLE(acpi, acpi_tad_ids);
diff --git a/drivers/acpi/apei/einj-core.c b/drivers/acpi/apei/einj-core.c
index 5c22720f43cc..04731a5b01fa 100644
--- a/drivers/acpi/apei/einj-core.c
+++ b/drivers/acpi/apei/einj-core.c
@@ -880,7 +880,7 @@ static struct platform_device *einj_dev;
* triggering a section mismatch warning.
*/
static struct platform_driver einj_driver __refdata = {
- .remove_new = __exit_p(einj_remove),
+ .remove = __exit_p(einj_remove),
.driver = {
.name = "acpi-einj",
},
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index ada93cfde9ba..a2491905f165 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -1605,7 +1605,7 @@ static struct platform_driver ghes_platform_driver = {
.name = "GHES",
},
.probe = ghes_probe,
- .remove_new = ghes_remove,
+ .remove = ghes_remove,
};
void __init acpi_ghes_init(void)
diff --git a/drivers/acpi/arm64/agdi.c b/drivers/acpi/arm64/agdi.c
index f5f21dd0d277..e0df3daa4abf 100644
--- a/drivers/acpi/arm64/agdi.c
+++ b/drivers/acpi/arm64/agdi.c
@@ -88,7 +88,7 @@ static struct platform_driver agdi_driver = {
.name = "agdi",
},
.probe = agdi_probe,
- .remove_new = agdi_remove,
+ .remove = agdi_remove,
};
void __init acpi_agdi_init(void)
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index c0e77c1c8e09..3561553eff8b 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -36,19 +36,25 @@ struct acpi_gtdt_descriptor {
static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
-static inline __init void *next_platform_timer(void *platform_timer)
+static __init bool platform_timer_valid(void *platform_timer)
{
struct acpi_gtdt_header *gh = platform_timer;
- platform_timer += gh->length;
- if (platform_timer < acpi_gtdt_desc.gtdt_end)
- return platform_timer;
+ return (platform_timer >= (void *)(acpi_gtdt_desc.gtdt + 1) &&
+ platform_timer < acpi_gtdt_desc.gtdt_end &&
+ gh->length != 0 &&
+ platform_timer + gh->length <= acpi_gtdt_desc.gtdt_end);
+}
+
+static __init void *next_platform_timer(void *platform_timer)
+{
+ struct acpi_gtdt_header *gh = platform_timer;
- return NULL;
+ return platform_timer + gh->length;
}
#define for_each_platform_timer(_g) \
- for (_g = acpi_gtdt_desc.platform_timer; _g; \
+ for (_g = acpi_gtdt_desc.platform_timer; platform_timer_valid(_g);\
_g = next_platform_timer(_g))
static inline bool is_timer_block(void *platform_timer)
@@ -157,6 +163,7 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
{
void *platform_timer;
struct acpi_table_gtdt *gtdt;
+ int cnt = 0;
gtdt = container_of(table, struct acpi_table_gtdt, header);
acpi_gtdt_desc.gtdt = gtdt;
@@ -176,12 +183,16 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
return 0;
}
- platform_timer = (void *)gtdt + gtdt->platform_timer_offset;
- if (platform_timer < (void *)table + sizeof(struct acpi_table_gtdt)) {
+ acpi_gtdt_desc.platform_timer = (void *)gtdt + gtdt->platform_timer_offset;
+ for_each_platform_timer(platform_timer)
+ cnt++;
+
+ if (cnt != gtdt->platform_timer_count) {
+ acpi_gtdt_desc.platform_timer = NULL;
pr_err(FW_BUG "invalid timer data.\n");
return -EINVAL;
}
- acpi_gtdt_desc.platform_timer = platform_timer;
+
if (platform_timer_count)
*platform_timer_count = gtdt->platform_timer_count;
@@ -283,7 +294,7 @@ error:
if (frame->virt_irq > 0)
acpi_unregister_gsi(gtdt_frame->virtual_timer_interrupt);
frame->virt_irq = 0;
- } while (i-- >= 0 && gtdt_frame--);
+ } while (i-- > 0 && gtdt_frame--);
return -EINVAL;
}
@@ -352,7 +363,7 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
}
irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
- res[2] = (struct resource)DEFINE_RES_IRQ(irq);
+ res[2] = DEFINE_RES_IRQ(irq);
if (irq <= 0) {
pr_warn("failed to map the Watchdog interrupt.\n");
nr_res--;
diff --git a/drivers/acpi/arm64/init.c b/drivers/acpi/arm64/init.c
index d0c8aed90fd1..7a47d8095a7d 100644
--- a/drivers/acpi/arm64/init.c
+++ b/drivers/acpi/arm64/init.c
@@ -2,7 +2,7 @@
#include <linux/acpi.h>
#include "init.h"
-void __init acpi_arm_init(void)
+void __init acpi_arch_init(void)
{
if (IS_ENABLED(CONFIG_ACPI_AGDI))
acpi_agdi_init();
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 4c745a26226b..1f7e4c691d9e 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1218,6 +1218,17 @@ static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node)
return pci_rc->ats_attribute & ACPI_IORT_ATS_SUPPORTED;
}
+static bool iort_pci_rc_supports_canwbs(struct acpi_iort_node *node)
+{
+ struct acpi_iort_memory_access *memory_access;
+ struct acpi_iort_root_complex *pci_rc;
+
+ pci_rc = (struct acpi_iort_root_complex *)node->node_data;
+ memory_access =
+ (struct acpi_iort_memory_access *)&pci_rc->memory_properties;
+ return memory_access->memory_flags & ACPI_IORT_MF_CANWBS;
+}
+
static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,
u32 streamid)
{
@@ -1335,6 +1346,8 @@ int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
fwspec = dev_iommu_fwspec_get(dev);
if (fwspec && iort_pci_rc_supports_ats(node))
fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
+ if (fwspec && iort_pci_rc_supports_canwbs(node))
+ fwspec->flags |= IOMMU_FWSPEC_PCI_RC_CANWBS;
} else {
node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
iort_match_node_callback, dev);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 65fa3444367a..3d5342f8d7b3 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -853,6 +853,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
struct power_supply_config psy_cfg = {
.drv_data = battery,
.attr_grp = acpi_battery_groups,
+ .no_wakeup_source = true,
};
bool full_cap_broken = false;
@@ -888,7 +889,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat_desc.get_property = acpi_battery_get_property;
- battery->bat = power_supply_register_no_ws(&battery->device->dev,
+ battery->bat = power_supply_register(&battery->device->dev,
&battery->bat_desc, &psy_cfg);
if (IS_ERR(battery->bat)) {
@@ -1218,15 +1219,21 @@ static int acpi_battery_add(struct acpi_device *device)
if (device->dep_unmet)
return -EPROBE_DEFER;
- battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
+ battery = devm_kzalloc(&device->dev, sizeof(*battery), GFP_KERNEL);
if (!battery)
return -ENOMEM;
battery->device = device;
strscpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
strscpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
device->driver_data = battery;
- mutex_init(&battery->lock);
- mutex_init(&battery->sysfs_lock);
+ result = devm_mutex_init(&device->dev, &battery->lock);
+ if (result)
+ return result;
+
+ result = devm_mutex_init(&device->dev, &battery->sysfs_lock);
+ if (result)
+ return result;
+
if (acpi_has_method(battery->device->handle, "_BIX"))
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
@@ -1238,7 +1245,9 @@ static int acpi_battery_add(struct acpi_device *device)
device->status.battery_present ? "present" : "absent");
battery->pm_nb.notifier_call = battery_notify;
- register_pm_notifier(&battery->pm_nb);
+ result = register_pm_notifier(&battery->pm_nb);
+ if (result)
+ goto fail;
device_init_wakeup(&device->dev, 1);
@@ -1254,9 +1263,6 @@ fail_pm:
unregister_pm_notifier(&battery->pm_nb);
fail:
sysfs_remove_battery(battery);
- mutex_destroy(&battery->lock);
- mutex_destroy(&battery->sysfs_lock);
- kfree(battery);
return result;
}
@@ -1276,13 +1282,8 @@ static void acpi_battery_remove(struct acpi_device *device)
device_init_wakeup(&device->dev, 0);
unregister_pm_notifier(&battery->pm_nb);
sysfs_remove_battery(battery);
-
- mutex_destroy(&battery->lock);
- mutex_destroy(&battery->sysfs_lock);
- kfree(battery);
}
-#ifdef CONFIG_PM_SLEEP
/* this is needed to learn about changes made in suspended state */
static int acpi_battery_resume(struct device *dev)
{
@@ -1299,11 +1300,8 @@ static int acpi_battery_resume(struct device *dev)
acpi_battery_update(battery, true);
return 0;
}
-#else
-#define acpi_battery_resume NULL
-#endif
-static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
static struct acpi_driver acpi_battery_driver = {
.name = "battery",
@@ -1313,7 +1311,7 @@ static struct acpi_driver acpi_battery_driver = {
.add = acpi_battery_add,
.remove = acpi_battery_remove,
},
- .drv.pm = &acpi_battery_pm,
+ .drv.pm = pm_sleep_ptr(&acpi_battery_pm),
.drv.probe_type = PROBE_PREFER_ASYNCHRONOUS,
};
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 16917dc3ad60..058910af82bc 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1434,6 +1434,8 @@ static int __init acpi_bus_init(void)
struct kobject *acpi_kobj;
EXPORT_SYMBOL_GPL(acpi_kobj);
+void __weak __init acpi_arch_init(void) { }
+
static int __init acpi_init(void)
{
int result;
@@ -1461,8 +1463,7 @@ static int __init acpi_init(void)
acpi_viot_early_init();
acpi_hest_init();
acpi_ghes_init();
- acpi_arm_init();
- acpi_riscv_init();
+ acpi_arch_init();
acpi_scan_init();
acpi_ec_init();
acpi_debugfs_init();
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 1a40f0514eaa..f193e713825a 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -671,10 +671,6 @@ static int pcc_data_alloc(int pcc_ss_id)
* )
*/
-#ifndef arch_init_invariance_cppc
-static inline void arch_init_invariance_cppc(void) { }
-#endif
-
/**
* acpi_cppc_processor_probe - Search for per CPU _CPC objects.
* @pr: Ptr to acpi_processor containing this CPU's logical ID.
@@ -905,8 +901,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
goto out_free;
}
- arch_init_invariance_cppc();
-
kfree(output.pointer);
return 0;
@@ -1017,7 +1011,8 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
*val = 0;
size = GET_BIT_WIDTH(reg);
- if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+ if (IS_ENABLED(CONFIG_HAS_IOPORT) &&
+ reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
u32 val_u32;
acpi_status status;
@@ -1091,7 +1086,8 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
size = GET_BIT_WIDTH(reg);
- if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+ if (IS_ENABLED(CONFIG_HAS_IOPORT) &&
+ reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
acpi_status status;
status = acpi_os_write_port((acpi_io_address)reg->address,
@@ -1146,7 +1142,6 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
return -EFAULT;
}
val = MASK_VAL_WRITE(reg, prev_val, val);
- val |= prev_val;
}
switch (size) {
diff --git a/drivers/acpi/dptf/dptf_pch_fivr.c b/drivers/acpi/dptf/dptf_pch_fivr.c
index d202730fafd8..624fce67ce43 100644
--- a/drivers/acpi/dptf/dptf_pch_fivr.c
+++ b/drivers/acpi/dptf/dptf_pch_fivr.c
@@ -158,7 +158,7 @@ MODULE_DEVICE_TABLE(acpi, pch_fivr_device_ids);
static struct platform_driver pch_fivr_driver = {
.probe = pch_fivr_add,
- .remove_new = pch_fivr_remove,
+ .remove = pch_fivr_remove,
.driver = {
.name = "dptf_pch_fivr",
.acpi_match_table = pch_fivr_device_ids,
diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c
index 8023b3e23315..3d3edd81b172 100644
--- a/drivers/acpi/dptf/dptf_power.c
+++ b/drivers/acpi/dptf/dptf_power.c
@@ -242,7 +242,7 @@ MODULE_DEVICE_TABLE(acpi, int3407_device_ids);
static struct platform_driver dptf_power_driver = {
.probe = dptf_power_add,
- .remove_new = dptf_power_remove,
+ .remove = dptf_power_remove,
.driver = {
.name = "dptf_power",
.acpi_match_table = int3407_device_ids,
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 25399f6dde7e..8db09d81918f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1677,8 +1677,8 @@ static int acpi_ec_add(struct acpi_device *device)
struct acpi_ec *ec;
int ret;
- strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_EC_CLASS);
+ strscpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
+ strscpy(acpi_device_class(device), ACPI_EC_CLASS);
if (boot_ec && (boot_ec->handle == device->handle ||
!strcmp(acpi_device_hid(device), ACPI_ECDT_HID))) {
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index d199a19bb292..96a9aaaaf9f7 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -28,8 +28,8 @@ int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
{
struct acpi_bus_event event;
- strcpy(event.device_class, dev->pnp.device_class);
- strcpy(event.bus_id, dev->pnp.bus_id);
+ strscpy(event.device_class, dev->pnp.device_class);
+ strscpy(event.bus_id, dev->pnp.bus_id);
event.type = type;
event.data = data;
return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c
index 11778c93254b..5c35cbc7f6ff 100644
--- a/drivers/acpi/evged.c
+++ b/drivers/acpi/evged.c
@@ -185,7 +185,7 @@ static const struct acpi_device_id ged_acpi_ids[] = {
static struct platform_driver ged_driver = {
.probe = ged_probe,
- .remove_new = ged_remove,
+ .remove = ged_remove,
.shutdown = ged_shutdown,
.driver = {
.name = MODULE_NAME,
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index 7cea4495f19b..3ea9cfcff46e 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -448,7 +448,7 @@ static const struct dev_pm_ops acpi_fan_pm = {
static struct platform_driver acpi_fan_driver = {
.probe = acpi_fan_probe,
- .remove_new = acpi_fan_remove,
+ .remove = acpi_fan_remove,
.driver = {
.name = "acpi-fan",
.acpi_match_table = fan_device_ids,
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index ced7dff9a5db..00910ccd7eda 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -215,6 +215,8 @@ extern struct acpi_ec *first_ec;
/* External interfaces use first EC only, so remember */
typedef int (*acpi_ec_query_func) (void *data);
+#ifdef CONFIG_ACPI_EC
+
void acpi_ec_init(void);
void acpi_ec_ecdt_probe(void);
void acpi_ec_dsdt_probe(void);
@@ -231,6 +233,29 @@ void acpi_ec_flush_work(void);
bool acpi_ec_dispatch_gpe(void);
#endif
+#else
+
+static inline void acpi_ec_init(void) {}
+static inline void acpi_ec_ecdt_probe(void) {}
+static inline void acpi_ec_dsdt_probe(void) {}
+static inline void acpi_ec_block_transactions(void) {}
+static inline void acpi_ec_unblock_transactions(void) {}
+static inline int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
+ acpi_handle handle, acpi_ec_query_func func,
+ void *data)
+{
+ return -ENXIO;
+}
+static inline void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) {}
+static inline void acpi_ec_register_opregions(struct acpi_device *adev) {}
+
+static inline void acpi_ec_flush_work(void) {}
+static inline bool acpi_ec_dispatch_gpe(void)
+{
+ return false;
+}
+
+#endif
/*--------------------------------------------------------------------------
Suspend/Resume
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 70af3fbbebe5..fed446aace42 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -642,6 +642,15 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 *value, u32 width)
{
u32 dummy;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT)) {
+ /*
+ * set all-1 result as if reading from non-existing
+ * I/O port
+ */
+ *value = GENMASK(width, 0);
+ return AE_NOT_IMPLEMENTED;
+ }
+
if (value)
*value = 0;
else
@@ -665,6 +674,9 @@ EXPORT_SYMBOL(acpi_os_read_port);
acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return AE_NOT_IMPLEMENTED;
+
if (width <= 8) {
outb(value, port);
} else if (width <= 16) {
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index b727db968f33..08e10b6226dc 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -714,8 +714,8 @@ static int acpi_pci_link_add(struct acpi_device *device,
return -ENOMEM;
link->device = device;
- strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
+ strscpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
+ strscpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
device->driver_data = link;
mutex_lock(&acpi_link_lock);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index d0bfb3706801..d0b6a024daae 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -689,8 +689,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
root->device = device;
root->segment = segment & 0xFFFF;
- strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
+ strscpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
+ strscpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
if (hotadd && dmar_device_add(handle)) {
diff --git a/drivers/acpi/pfr_telemetry.c b/drivers/acpi/pfr_telemetry.c
index 998264a7333d..32bdf8cbe8f2 100644
--- a/drivers/acpi/pfr_telemetry.c
+++ b/drivers/acpi/pfr_telemetry.c
@@ -272,9 +272,6 @@ static long pfrt_log_ioctl(struct file *file, unsigned int cmd, unsigned long ar
case PFRT_LOG_IOC_GET_INFO:
info.log_level = get_pfrt_log_level(pfrt_log_dev);
- if (ret < 0)
- return ret;
-
info.log_type = pfrt_log_dev->info.log_type;
info.log_revid = pfrt_log_dev->info.log_revid;
if (copy_to_user(p, &info, sizeof(info)))
@@ -425,7 +422,7 @@ static struct platform_driver acpi_pfrt_log_driver = {
.acpi_match_table = acpi_pfrt_log_ids,
},
.probe = acpi_pfrt_log_probe,
- .remove_new = acpi_pfrt_log_remove,
+ .remove = acpi_pfrt_log_remove,
};
module_platform_driver(acpi_pfrt_log_driver);
diff --git a/drivers/acpi/pfr_update.c b/drivers/acpi/pfr_update.c
index 8b2910995fc1..031d1ba81b86 100644
--- a/drivers/acpi/pfr_update.c
+++ b/drivers/acpi/pfr_update.c
@@ -565,7 +565,7 @@ static struct platform_driver acpi_pfru_driver = {
.acpi_match_table = acpi_pfru_ids,
},
.probe = acpi_pfru_probe,
- .remove_new = acpi_pfru_remove,
+ .remove = acpi_pfru_remove,
};
module_platform_driver(acpi_pfru_driver);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index c2c70139c4f1..25174c24d3d7 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -950,8 +950,8 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
mutex_init(&resource->resource_lock);
INIT_LIST_HEAD(&resource->list_node);
INIT_LIST_HEAD(&resource->dependents);
- strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
+ strscpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
+ strscpy(acpi_device_class(device), ACPI_POWER_CLASS);
device->power.state = ACPI_STATE_UNKNOWN;
device->flags.match_driver = true;
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index cb52dd000b95..3b281bc1e73c 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -237,6 +237,9 @@ static struct notifier_block acpi_processor_notifier_block = {
.notifier_call = acpi_processor_notifier,
};
+void __weak acpi_processor_init_invariance_cppc(void)
+{ }
+
/*
* We keep the driver loaded even when ACPI is not running.
* This is needed for the powernow-k8 driver, that works even without
@@ -270,6 +273,12 @@ static int __init acpi_processor_driver_init(void)
NULL, acpi_soft_cpu_dead);
acpi_processor_throttling_init();
+
+ /*
+ * Frequency invariance calculations on AMD platforms can't be run until
+ * after acpi_cppc_processor_probe() has been called for all online CPUs
+ */
+ acpi_processor_init_invariance_cppc();
return 0;
err:
driver_unregister(&acpi_processor_driver);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 831fa4a12159..698897b29de2 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -578,7 +578,7 @@ static void __cpuidle acpi_idle_do_entry(struct acpi_processor_cx *cx)
* @dev: the target CPU
* @index: the index of suggested state
*/
-static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
+static void acpi_idle_play_dead(struct cpuidle_device *dev, int index)
{
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
@@ -591,11 +591,8 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
io_idle(cx->address);
} else
- return -ENODEV;
+ return;
}
-
- /* Never reached */
- return 0;
}
static __always_inline bool acpi_idle_fallback_to_c1(struct acpi_processor *pr)
@@ -803,12 +800,12 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
state->enter = acpi_idle_enter;
state->flags = 0;
- if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 ||
- cx->type == ACPI_STATE_C3) {
- state->enter_dead = acpi_idle_play_dead;
- if (cx->type != ACPI_STATE_C3)
- drv->safe_state_index = count;
- }
+
+ state->enter_dead = acpi_idle_play_dead;
+
+ if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2)
+ drv->safe_state_index = count;
+
/*
* Halt-induced C1 is not good for ->enter_s2idle, because it
* re-enables interrupts on exit. Moreover, C1 is generally not
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 4265814c74f8..53996f1a2d80 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -24,8 +24,6 @@
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
-static DEFINE_MUTEX(performance_mutex);
-
/*
* _PPC support is implemented as a CPUfreq policy notifier:
* This means each time a CPUfreq driver registered also with
@@ -209,6 +207,10 @@ void acpi_processor_ppc_exit(struct cpufreq_policy *policy)
}
}
+#ifdef CONFIG_X86
+
+static DEFINE_MUTEX(performance_mutex);
+
static int acpi_processor_get_performance_control(struct acpi_processor *pr)
{
int result = 0;
@@ -267,7 +269,6 @@ end:
return result;
}
-#ifdef CONFIG_X86
/*
* Some AMDs have 50MHz frequency multiples, but only provide 100MHz rounding
* in their ACPI data. Calculate the real values and fix up the _PSS data.
@@ -298,9 +299,6 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
px->core_frequency = (100 * (fid + 8)) >> did;
}
}
-#else
-static void amd_fixup_frequency(struct acpi_processor_px *px, int i) {};
-#endif
static int acpi_processor_get_performance_states(struct acpi_processor *pr)
{
@@ -440,13 +438,11 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr)
* the BIOS is older than the CPU and does not know its frequencies
*/
update_bios:
-#ifdef CONFIG_X86
if (acpi_has_method(pr->handle, "_PPC")) {
if(boot_cpu_has(X86_FEATURE_EST))
pr_warn(FW_BUG "BIOS needs update for CPU "
"frequency support\n");
}
-#endif
return result;
}
EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
@@ -788,3 +784,4 @@ unlock:
mutex_unlock(&performance_mutex);
}
EXPORT_SYMBOL(acpi_processor_unregister_performance);
+#endif
diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c
index 5ef97905a727..673e4d5dd752 100644
--- a/drivers/acpi/riscv/init.c
+++ b/drivers/acpi/riscv/init.c
@@ -7,7 +7,7 @@
#include <linux/acpi.h>
#include "init.h"
-void __init acpi_riscv_init(void)
+void __init acpi_arch_init(void)
{
riscv_acpi_init_gsi_mapping();
}
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 7a0914055fca..a3f95a3fffde 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -644,8 +644,8 @@ static int acpi_sbs_add(struct acpi_device *device)
sbs->hc = acpi_driver_data(acpi_dev_parent(device));
sbs->device = device;
- strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
+ strscpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
+ strscpy(acpi_device_class(device), ACPI_SBS_CLASS);
device->driver_data = sbs;
result = acpi_charger_add(sbs);
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index 16f2daaa2c45..1a2bf520be23 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include "sbshc.h"
+#include "internal.h"
#define ACPI_SMB_HC_CLASS "smbus_host_ctl"
#define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC"
@@ -236,12 +237,6 @@ static int smbus_alarm(void *context)
return 0;
}
-typedef int (*acpi_ec_query_func) (void *data);
-
-extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
- acpi_handle handle, acpi_ec_query_func func,
- void *data);
-
static int acpi_smbus_hc_add(struct acpi_device *device)
{
int status;
@@ -257,8 +252,8 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
return -EIO;
}
- strcpy(acpi_device_name(device), ACPI_SMB_HC_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_SMB_HC_CLASS);
+ strscpy(acpi_device_name(device), ACPI_SMB_HC_DEVICE_NAME);
+ strscpy(acpi_device_class(device), ACPI_SMB_HC_CLASS);
hc = kzalloc(sizeof(struct acpi_smb_hc), GFP_KERNEL);
if (!hc)
@@ -278,8 +273,6 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
return 0;
}
-extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
-
static void acpi_smbus_hc_remove(struct acpi_device *device)
{
struct acpi_smb_hc *hc;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 7ecc401fb97f..74dcccdc6482 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1179,19 +1179,19 @@ static void acpi_device_get_busid(struct acpi_device *device)
* TBD: Shouldn't this value be unique (within the ACPI namespace)?
*/
if (!acpi_dev_parent(device)) {
- strcpy(device->pnp.bus_id, "ACPI");
+ strscpy(device->pnp.bus_id, "ACPI");
return;
}
switch (device->device_type) {
case ACPI_BUS_TYPE_POWER_BUTTON:
- strcpy(device->pnp.bus_id, "PWRF");
+ strscpy(device->pnp.bus_id, "PWRF");
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
- strcpy(device->pnp.bus_id, "SLPF");
+ strscpy(device->pnp.bus_id, "SLPF");
break;
case ACPI_BUS_TYPE_ECDT_EC:
- strcpy(device->pnp.bus_id, "ECDT");
+ strscpy(device->pnp.bus_id, "ECDT");
break;
default:
acpi_get_name(device->handle, ACPI_SINGLE_NAME, &buffer);
@@ -1202,7 +1202,7 @@ static void acpi_device_get_busid(struct acpi_device *device)
else
break;
}
- strcpy(device->pnp.bus_id, bus_id);
+ strscpy(device->pnp.bus_id, bus_id);
break;
}
}
@@ -1453,8 +1453,8 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
acpi_object_is_system_bus(handle)) {
/* \_SB, \_TZ, LNXSYBUS */
acpi_add_id(pnp, ACPI_BUS_HID);
- strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME);
- strcpy(pnp->device_class, ACPI_BUS_CLASS);
+ strscpy(pnp->device_name, ACPI_BUS_DEVICE_NAME);
+ strscpy(pnp->device_class, ACPI_BUS_CLASS);
}
break;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 78db38c7076e..6671537cb4b7 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -796,9 +796,9 @@ static int acpi_thermal_add(struct acpi_device *device)
return -ENOMEM;
tz->device = device;
- strcpy(tz->name, device->pnp.bus_id);
- strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
+ strscpy(tz->name, device->pnp.bus_id);
+ strscpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
+ strscpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
device->driver_data = tz;
acpi_thermal_aml_dependency_fix(tz);
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 015bd8e66c1c..d507d5e08435 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -551,6 +551,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
{
.callback = video_detect_force_native,
+ /* Apple MacBook Air 7,2 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir7,2"),
+ },
+ },
+ {
+ .callback = video_detect_force_native,
/* Apple MacBook Air 9,1 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -566,6 +574,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
{
+ .callback = video_detect_force_native,
+ /* Apple MacBook Pro 11,2 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro11,2"),
+ },
+ },
+ {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
.callback = video_detect_force_native,
/* Apple MacBook Pro 12,1 */
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index 6af546b21574..cb45ef5240da 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -12,6 +12,7 @@
#include <linux/acpi.h>
#include <linux/dmi.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
@@ -295,6 +296,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
/*
* 2. Devices which also have the skip i2c/serdev quirks and which
* need the x86-android-tablets module to properly work.
+ * Sorted alphabetically.
*/
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
{
@@ -308,6 +310,19 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
+ /* Acer Iconia One 8 A1-840 (non FHD version) */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
+ /* Above strings are too generic also match BIOS date */
+ DMI_MATCH(DMI_BIOS_DATE, "04/01/2014"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+ ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
+ },
+ {
+ /* Asus ME176C tablet */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
@@ -318,23 +333,24 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
- /* Lenovo Yoga Book X90F/L */
+ /* Asus TF103C transformer 2-in-1 */
.matches = {
- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
- DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
- ACPI_QUIRK_UART1_SKIP |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
{
+ /* Lenovo Yoga Book X90F/L */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
},
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_UART1_SKIP |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
},
@@ -392,6 +408,19 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
},
{
+ /* Vexia Edu Atla 10 tablet 9V version */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Above strings are too generic, also match on BIOS date */
+ DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_UART1_SKIP |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+ ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
+ },
+ {
/* Whitelabel (sold as various brands) TM800A550L */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
@@ -411,6 +440,7 @@ static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
{ "10EC5651", 0 }, /* RealTek ALC5651 audio codec */
{ "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
+ { "INT33F5", 0 }, /* TI Dollar Cove PMIC */
{ "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
{ "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */
{ "NPCE69A", 0 }, /* Asus Transformer keyboard dock */
@@ -439,18 +469,35 @@ static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bo
struct acpi_device *adev = ACPI_COMPANION(controller_parent);
const struct dmi_system_id *dmi_id;
long quirks = 0;
- u64 uid;
- int ret;
+ u64 uid = 0;
- ret = acpi_dev_uid_to_integer(adev, &uid);
- if (ret)
+ dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
+ if (!dmi_id)
return 0;
- dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
- if (dmi_id)
- quirks = (unsigned long)dmi_id->driver_data;
+ quirks = (unsigned long)dmi_id->driver_data;
+
+ /* uid is left at 0 on errors and 0 is not a valid UART UID */
+ acpi_dev_uid_to_integer(adev, &uid);
+
+ /* For PCI UARTs without an UID */
+ if (!uid && dev_is_pci(controller_parent)) {
+ struct pci_dev *pdev = to_pci_dev(controller_parent);
+
+ /*
+ * Devfn values for PCI UARTs on Bay Trail SoCs, which are
+ * the only devices where this fallback is necessary.
+ */
+ if (pdev->devfn == PCI_DEVFN(0x1e, 3))
+ uid = 1;
+ else if (pdev->devfn == PCI_DEVFN(0x1e, 4))
+ uid = 2;
+ }
+
+ if (!uid)
+ return 0;
- if (!dev_is_platform(controller_parent)) {
+ if (!dev_is_platform(controller_parent) && !dev_is_pci(controller_parent)) {
/* PNP enumerated UARTs */
if ((quirks & ACPI_QUIRK_PNP_UART1_SKIP) && uid == 1)
*skip = true;
@@ -505,7 +552,7 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
* Set skip to true so that the tty core creates a serdev ctrl device.
* The backlight driver will manually create the serdev client device.
*/
- if (acpi_dev_hid_match(adev, "DELL0501")) {
+ if (adev && acpi_dev_hid_match(adev, "DELL0501")) {
*skip = true;
/*
* Create a platform dev for dell-uart-backlight to bind to.
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 0230c43377c1..8ef259b4d037 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -449,6 +449,12 @@ const struct bus_type amba_bustype = {
};
EXPORT_SYMBOL_GPL(amba_bustype);
+bool dev_is_amba(const struct device *dev)
+{
+ return dev->bus == &amba_bustype;
+}
+EXPORT_SYMBOL_GPL(dev_is_amba);
+
static int __init amba_init(void)
{
return bus_register(&amba_bustype);
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 978740537a1a..ef353ca13c35 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1225,6 +1225,12 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref)
binder_dequeue_work(ref->proc, &ref->death->work);
binder_stats_deleted(BINDER_STAT_DEATH);
}
+
+ if (ref->freeze) {
+ binder_dequeue_work(ref->proc, &ref->freeze->work);
+ binder_stats_deleted(BINDER_STAT_FREEZE);
+ }
+
binder_stats_deleted(BINDER_STAT_REF);
}
@@ -3850,7 +3856,6 @@ binder_request_freeze_notification(struct binder_proc *proc,
{
struct binder_ref_freeze *freeze;
struct binder_ref *ref;
- bool is_frozen;
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
if (!freeze)
@@ -3866,32 +3871,31 @@ binder_request_freeze_notification(struct binder_proc *proc,
}
binder_node_lock(ref->node);
-
- if (ref->freeze || !ref->node->proc) {
- binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
- proc->pid, thread->pid,
- ref->freeze ? "already set" : "dead node");
+ if (ref->freeze) {
+ binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION already set\n",
+ proc->pid, thread->pid);
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
kfree(freeze);
return -EINVAL;
}
- binder_inner_proc_lock(ref->node->proc);
- is_frozen = ref->node->proc->is_frozen;
- binder_inner_proc_unlock(ref->node->proc);
binder_stats_created(BINDER_STAT_FREEZE);
INIT_LIST_HEAD(&freeze->work.entry);
freeze->cookie = handle_cookie->cookie;
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
- freeze->is_frozen = is_frozen;
-
ref->freeze = freeze;
- binder_inner_proc_lock(proc);
- binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
- binder_wakeup_proc_ilocked(proc);
- binder_inner_proc_unlock(proc);
+ if (ref->node->proc) {
+ binder_inner_proc_lock(ref->node->proc);
+ freeze->is_frozen = ref->node->proc->is_frozen;
+ binder_inner_proc_unlock(ref->node->proc);
+
+ binder_inner_proc_lock(proc);
+ binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
+ binder_wakeup_proc_ilocked(proc);
+ binder_inner_proc_unlock(proc);
+ }
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
@@ -5151,6 +5155,16 @@ static void binder_release_work(struct binder_proc *proc,
} break;
case BINDER_WORK_NODE:
break;
+ case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
+ struct binder_ref_freeze *freeze;
+
+ freeze = container_of(w, struct binder_ref_freeze, work);
+ binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+ "undelivered freeze notification, %016llx\n",
+ (u64)freeze->cookie);
+ kfree(freeze);
+ binder_stats_deleted(BINDER_STAT_FREEZE);
+ } break;
default:
pr_err("unexpected work type, %d, not freed\n",
wtype);
@@ -5552,6 +5566,7 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
{
+ struct binder_node *prev = NULL;
struct rb_node *n;
struct binder_ref *ref;
@@ -5560,7 +5575,10 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
struct binder_node *node;
node = rb_entry(n, struct binder_node, rb_node);
+ binder_inc_node_tmpref_ilocked(node);
binder_inner_proc_unlock(proc);
+ if (prev)
+ binder_put_node(prev);
binder_node_lock(node);
hlist_for_each_entry(ref, &node->refs, node_entry) {
/*
@@ -5586,10 +5604,15 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
}
binder_inner_proc_unlock(ref->proc);
}
+ prev = node;
binder_node_unlock(node);
binder_inner_proc_lock(proc);
+ if (proc->is_dead)
+ break;
}
binder_inner_proc_unlock(proc);
+ if (prev)
+ binder_put_node(prev);
}
static int binder_ioctl_freeze(struct binder_freeze_info *info,
@@ -6260,6 +6283,7 @@ static void binder_deferred_release(struct binder_proc *proc)
binder_release_work(proc, &proc->todo);
binder_release_work(proc, &proc->delivered_death);
+ binder_release_work(proc, &proc->delivered_freeze);
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
"%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n",
@@ -6393,6 +6417,12 @@ static void print_binder_work_ilocked(struct seq_file *m,
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
seq_printf(m, "%shas cleared death notification\n", prefix);
break;
+ case BINDER_WORK_FROZEN_BINDER:
+ seq_printf(m, "%shas frozen binder\n", prefix);
+ break;
+ case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION:
+ seq_printf(m, "%shas cleared freeze notification\n", prefix);
+ break;
default:
seq_printf(m, "%sunknown work: type %d\n", prefix, w->type);
break;
@@ -6539,6 +6569,10 @@ static void print_binder_proc(struct seq_file *m,
seq_puts(m, " has delivered dead binder\n");
break;
}
+ list_for_each_entry(w, &proc->delivered_freeze, entry) {
+ seq_puts(m, " has delivered freeze binder\n");
+ break;
+ }
binder_inner_proc_unlock(proc);
if (!print_all && m->count == header_pos)
m->count = start_pos;
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index b3acbc4174fb..a738e7745865 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -1047,7 +1047,7 @@ void binder_alloc_vma_close(struct binder_alloc *alloc)
/**
* binder_alloc_free_page() - shrinker callback to free pages
* @item: item to free
- * @lock: lock protecting the item
+ * @lru: list_lru instance of the item
* @cb_arg: callback argument
*
* Called from list_lru_walk() in binder_shrink_scan() to free
@@ -1055,9 +1055,8 @@ void binder_alloc_vma_close(struct binder_alloc *alloc)
*/
enum lru_status binder_alloc_free_page(struct list_head *item,
struct list_lru_one *lru,
- spinlock_t *lock,
void *cb_arg)
- __must_hold(lock)
+ __must_hold(&lru->lock)
{
struct binder_lru_page *page = container_of(item, typeof(*page), lru);
struct binder_alloc *alloc = page->alloc;
@@ -1092,7 +1091,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
list_lru_isolate(lru, item);
spin_unlock(&alloc->lock);
- spin_unlock(lock);
+ spin_unlock(&lru->lock);
if (vma) {
trace_binder_unmap_user_start(alloc, index);
@@ -1106,7 +1105,6 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
mmput_async(mm);
__free_page(page_to_free);
- spin_lock(lock);
return LRU_REMOVED_RETRY;
err_invalid_vma:
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index 70387234477e..c02c8ebcb466 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -118,7 +118,7 @@ static inline void binder_selftest_alloc(struct binder_alloc *alloc) {}
#endif
enum lru_status binder_alloc_free_page(struct list_head *item,
struct list_lru_one *lru,
- spinlock_t *lock, void *cb_arg);
+ void *cb_arg);
struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
size_t data_size,
size_t offsets_size,
diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
index 547f56341705..3999305b5356 100644
--- a/drivers/ata/acard-ahci.c
+++ b/drivers/ata/acard-ahci.c
@@ -370,7 +370,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id
/* AHCI controllers often implement SFF compatible interface.
* Grab all PCI BARs just in case.
*/
- rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
+ rc = pcim_request_all_regions(pdev, DRV_NAME);
if (rc == -EBUSY)
pcim_pin_device(pdev);
if (rc)
@@ -386,7 +386,9 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id
if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
pci_enable_msi(pdev);
- hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
+ hpriv->mmio = pcim_iomap(pdev, AHCI_PCI_BAR, 0);
+ if (!hpriv->mmio)
+ return -ENOMEM;
/* save initial config */
ahci_save_initial_config(&pdev->dev, hpriv);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 45f63b09828a..8d27c567be1c 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1676,7 +1676,7 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
/*
* If number of MSIs is less than number of ports then Sharing Last
* Message mode could be enforced. In this case assume that advantage
- * of multipe MSIs is negated and use single MSI mode instead.
+ * of multiple MSIs is negated and use single MSI mode instead.
*/
if (n_ports > 1) {
nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
@@ -1869,7 +1869,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* AHCI controllers often implement SFF compatible interface.
* Grab all PCI BARs just in case.
*/
- rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
+ rc = pcim_request_all_regions(pdev, DRV_NAME);
if (rc == -EBUSY)
pcim_pin_device(pdev);
if (rc)
@@ -1893,7 +1893,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ahci_sb600_enable_64bit(pdev))
hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
- hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
+ hpriv->mmio = pcim_iomap(pdev, ahci_pci_bar, 0);
+ if (!hpriv->mmio)
+ return -ENOMEM;
/* detect remapped nvme devices */
ahci_remap_check(pdev, ahci_pci_bar, hpriv);
diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c
index 2f16524c2526..ef569eae4ce4 100644
--- a/drivers/ata/ahci_brcm.c
+++ b/drivers/ata/ahci_brcm.c
@@ -571,7 +571,7 @@ static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
static struct platform_driver brcm_ahci_driver = {
.probe = brcm_ahci_probe,
- .remove_new = brcm_ahci_remove,
+ .remove = brcm_ahci_remove,
.shutdown = brcm_ahci_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c
index 11a2c199a7c2..1ec35778903d 100644
--- a/drivers/ata/ahci_ceva.c
+++ b/drivers/ata/ahci_ceva.c
@@ -402,7 +402,7 @@ MODULE_DEVICE_TABLE(of, ceva_ahci_of_match);
static struct platform_driver ceva_ahci_driver = {
.probe = ceva_ahci_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ceva_ahci_of_match,
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index 55a6627d5450..ca0924dc5bd2 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -238,7 +238,7 @@ MODULE_DEVICE_TABLE(of, ahci_da850_of_match);
static struct platform_driver ahci_da850_driver = {
.probe = ahci_da850_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_da850_of_match,
diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c
index 4cb70064fb99..b08547b877a1 100644
--- a/drivers/ata/ahci_dm816.c
+++ b/drivers/ata/ahci_dm816.c
@@ -182,7 +182,7 @@ MODULE_DEVICE_TABLE(of, ahci_dm816_of_match);
static struct platform_driver ahci_dm816_driver = {
.probe = ahci_dm816_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = AHCI_DM816_DRV_NAME,
.of_match_table = ahci_dm816_of_match,
diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
index ed263de3fd70..aec6d793f51a 100644
--- a/drivers/ata/ahci_dwc.c
+++ b/drivers/ata/ahci_dwc.c
@@ -478,7 +478,7 @@ MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
static struct platform_driver ahci_dwc_driver = {
.probe = ahci_dwc_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.shutdown = ahci_platform_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 6f955e9105e8..f01f08048f97 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -511,7 +511,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
/*
- * set PHY Paremeters, two steps to configure the GPR13,
+ * set PHY Parameters, two steps to configure the GPR13,
* one write for rest of parameters, mask of first write
* is 0x07ffffff, and the other one write for setting
* the mpll_clk_en.
@@ -1027,7 +1027,7 @@ static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume);
static struct platform_driver imx_ahci_driver = {
.probe = imx_ahci_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = imx_ahci_of_match,
diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c
index adc851cd5578..7295b9066ae2 100644
--- a/drivers/ata/ahci_mtk.c
+++ b/drivers/ata/ahci_mtk.c
@@ -174,7 +174,7 @@ MODULE_DEVICE_TABLE(of, ahci_of_match);
static struct platform_driver mtk_ahci_driver = {
.probe = mtk_ahci_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_of_match,
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index f3187351e8a6..8744dae41612 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match);
static struct platform_driver ahci_mvebu_driver = {
.probe = ahci_mvebu_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.suspend = ahci_mvebu_suspend,
.resume = ahci_mvebu_resume,
.driver = {
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 81fc63f6b008..c18054333f7c 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
static struct platform_driver ahci_driver = {
.probe = ahci_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.shutdown = ahci_platform_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index b1a4e57578e2..30e39885b64e 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -357,7 +357,7 @@ static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend,
static struct platform_driver ahci_qoriq_driver = {
.probe = ahci_qoriq_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_qoriq_of_match,
diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c
index 59f97aa7ac75..3f16c1678402 100644
--- a/drivers/ata/ahci_seattle.c
+++ b/drivers/ata/ahci_seattle.c
@@ -185,7 +185,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
static struct platform_driver ahci_seattle_driver = {
.probe = ahci_seattle_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.acpi_match_table = ahci_acpi_match,
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index 79a8b0aa37bf..6b9b4a1dfa15 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -238,7 +238,7 @@ static struct platform_driver st_ahci_driver = {
.of_match_table = st_ahci_match,
},
.probe = st_ahci_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
};
module_platform_driver(st_ahci_driver);
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 58b2683954dd..5d4584570ae0 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
static struct platform_driver ahci_sunxi_driver = {
.probe = ahci_sunxi_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = ahci_sunxi_of_match,
diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c
index 8703c2a4658b..44584eed6374 100644
--- a/drivers/ata/ahci_tegra.c
+++ b/drivers/ata/ahci_tegra.c
@@ -608,7 +608,7 @@ deinit_controller:
static struct platform_driver tegra_ahci_driver = {
.probe = tegra_ahci_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = tegra_ahci_of_match,
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 81a1d838c0fc..dfbd8c53abcb 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -534,7 +534,7 @@ softreset_retry:
/**
* xgene_ahci_handle_broken_edge_irq - Handle the broken irq.
- * @host: Host that recieved the irq
+ * @host: Host that received the irq
* @irq_masked: HOST_IRQ_STAT value
*
* For hardware with broken edge trigger latch
@@ -859,7 +859,7 @@ disable_resources:
static struct platform_driver xgene_ahci_driver = {
.probe = xgene_ahci_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
.of_match_table = xgene_ahci_of_match,
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index d36e71f475ab..b7f0bf795521 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -86,7 +86,7 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
* @dev: ATA device ACPI event occurred (can be NULL)
* @event: ACPI event which occurred
*
- * All ACPI bay / device realted events end up in this function. If
+ * All ACPI bay / device related events end up in this function. If
* the event is port-wide @dev is NULL. If the event is specific to a
* device, @dev points to it.
*
@@ -832,7 +832,7 @@ void ata_acpi_on_resume(struct ata_port *ap)
dev->flags |= ATA_DFLAG_ACPI_PENDING;
}
} else {
- /* SATA _GTF needs to be evaulated after _SDD and
+ /* SATA _GTF needs to be evaluated after _SDD and
* there's no reason to evaluate IDE _GTF early
* without _STM. Clear cache and schedule _GTF.
*/
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index f915e3df57a9..2ce5befd2242 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1334,17 +1334,8 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc)
*/
static void scsi_6_lba_len(const u8 *cdb, u64 *plba, u32 *plen)
{
- u64 lba = 0;
- u32 len;
-
- lba |= ((u64)(cdb[1] & 0x1f)) << 16;
- lba |= ((u64)cdb[2]) << 8;
- lba |= ((u64)cdb[3]);
-
- len = cdb[4];
-
- *plba = lba;
- *plen = len;
+ *plba = get_unaligned_be24(&cdb[1]) & 0x1fffff;
+ *plen = cdb[4];
}
/**
@@ -1781,15 +1772,10 @@ defer:
return SCSI_MLQUEUE_HOST_BUSY;
}
-struct ata_scsi_args {
- struct ata_device *dev;
- u16 *id;
- struct scsi_cmnd *cmd;
-};
-
/**
* ata_scsi_rbuf_fill - wrapper for SCSI command simulators
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @actor: Callback hook for desired SCSI command simulator
*
* Takes care of the hard work of simulating a SCSI command...
@@ -1802,30 +1788,32 @@ struct ata_scsi_args {
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
- unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf))
+static void ata_scsi_rbuf_fill(struct ata_device *dev, struct scsi_cmnd *cmd,
+ unsigned int (*actor)(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf))
{
- unsigned int rc;
- struct scsi_cmnd *cmd = args->cmd;
unsigned long flags;
+ unsigned int len;
spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
- rc = actor(args, ata_scsi_rbuf);
- if (rc == 0)
+ len = actor(dev, cmd, ata_scsi_rbuf);
+ if (len) {
sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
+ cmd->result = SAM_STAT_GOOD;
+ if (scsi_bufflen(cmd) > len)
+ scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
+ }
spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags);
-
- if (rc == 0)
- cmd->result = SAM_STAT_GOOD;
}
/**
- * ata_scsiop_inq_std - Simulate INQUIRY command
- * @args: device IDENTIFY data / SCSI command of interest.
+ * ata_scsiop_inq_std - Simulate standard INQUIRY command
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Returns standard device identification data associated
@@ -1834,7 +1822,8 @@ static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_inq_std(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
static const u8 versions[] = {
0x00,
@@ -1875,40 +1864,45 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
* Set the SCSI Removable Media Bit (RMB) if the ATA removable media
* device bit (obsolete since ATA-8 ACS) is set.
*/
- if (ata_id_removable(args->id))
+ if (ata_id_removable(dev->id))
hdr[1] |= (1 << 7);
- if (args->dev->class == ATA_DEV_ZAC) {
+ if (dev->class == ATA_DEV_ZAC) {
hdr[0] = TYPE_ZBC;
hdr[2] = 0x7; /* claim SPC-5 version compatibility */
}
- if (args->dev->flags & ATA_DFLAG_CDL)
+ if (dev->flags & ATA_DFLAG_CDL)
hdr[2] = 0xd; /* claim SPC-6 version compatibility */
memcpy(rbuf, hdr, sizeof(hdr));
memcpy(&rbuf[8], "ATA ", 8);
- ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
+ ata_id_string(dev->id, &rbuf[16], ATA_ID_PROD, 16);
/* From SAT, use last 2 words from fw rev unless they are spaces */
- ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV + 2, 4);
+ ata_id_string(dev->id, &rbuf[32], ATA_ID_FW_REV + 2, 4);
if (strncmp(&rbuf[32], " ", 4) == 0)
- ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
+ ata_id_string(dev->id, &rbuf[32], ATA_ID_FW_REV, 4);
if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[32], "n/a ", 4);
- if (ata_id_zoned_cap(args->id) || args->dev->class == ATA_DEV_ZAC)
+ if (ata_id_zoned_cap(dev->id) || dev->class == ATA_DEV_ZAC)
memcpy(rbuf + 58, versions_zbc, sizeof(versions_zbc));
else
memcpy(rbuf + 58, versions, sizeof(versions));
- return 0;
+ /*
+ * Include all 8 possible version descriptors, even if not all of
+ * them are popoulated.
+ */
+ return 96;
}
/**
* ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Returns list of inquiry VPD pages available.
@@ -1916,7 +1910,8 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_inq_00(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
int i, num_pages = 0;
static const u8 pages[] = {
@@ -1933,18 +1928,20 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
for (i = 0; i < sizeof(pages); i++) {
if (pages[i] == 0xb6 &&
- !(args->dev->flags & ATA_DFLAG_ZAC))
+ !(dev->flags & ATA_DFLAG_ZAC))
continue;
rbuf[num_pages + 4] = pages[i];
num_pages++;
}
rbuf[3] = num_pages; /* number of supported VPD pages */
- return 0;
+
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
/**
* ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Returns ATA device serial number.
@@ -1952,7 +1949,8 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_inq_80(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
static const u8 hdr[] = {
0,
@@ -1962,14 +1960,16 @@ static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
};
memcpy(rbuf, hdr, sizeof(hdr));
- ata_id_string(args->id, (unsigned char *) &rbuf[4],
+ ata_id_string(dev->id, (unsigned char *) &rbuf[4],
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
- return 0;
+
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
/**
* ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Yields two logical unit device identification designators:
@@ -1980,7 +1980,8 @@ static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_inq_83(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
const int sat_model_serial_desc_len = 68;
int num;
@@ -1992,7 +1993,7 @@ static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
rbuf[num + 0] = 2;
rbuf[num + 3] = ATA_ID_SERNO_LEN;
num += 4;
- ata_id_string(args->id, (unsigned char *) rbuf + num,
+ ata_id_string(dev->id, (unsigned char *) rbuf + num,
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
num += ATA_ID_SERNO_LEN;
@@ -2004,31 +2005,33 @@ static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
num += 4;
memcpy(rbuf + num, "ATA ", 8);
num += 8;
- ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_PROD,
+ ata_id_string(dev->id, (unsigned char *) rbuf + num, ATA_ID_PROD,
ATA_ID_PROD_LEN);
num += ATA_ID_PROD_LEN;
- ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO,
+ ata_id_string(dev->id, (unsigned char *) rbuf + num, ATA_ID_SERNO,
ATA_ID_SERNO_LEN);
num += ATA_ID_SERNO_LEN;
- if (ata_id_has_wwn(args->id)) {
+ if (ata_id_has_wwn(dev->id)) {
/* SAT defined lu world wide name */
/* piv=0, assoc=lu, code_set=binary, designator=NAA */
rbuf[num + 0] = 1;
rbuf[num + 1] = 3;
rbuf[num + 3] = ATA_ID_WWN_LEN;
num += 4;
- ata_id_string(args->id, (unsigned char *) rbuf + num,
+ ata_id_string(dev->id, (unsigned char *) rbuf + num,
ATA_ID_WWN, ATA_ID_WWN_LEN);
num += ATA_ID_WWN_LEN;
}
rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
- return 0;
+
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
/**
* ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Yields SAT-specified ATA VPD page.
@@ -2036,7 +2039,8 @@ static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_inq_89(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
rbuf[1] = 0x89; /* our page code */
rbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
@@ -2057,13 +2061,25 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
rbuf[56] = ATA_CMD_ID_ATA;
- memcpy(&rbuf[60], &args->id[0], 512);
- return 0;
+ memcpy(&rbuf[60], &dev->id[0], 512);
+
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
-static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
+/**
+ * ata_scsiop_inq_b0 - Simulate INQUIRY VPD page B0, Block Limits
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *
+ * Return data for the VPD page B0h (Block Limits).
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static unsigned int ata_scsiop_inq_b0(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
- struct ata_device *dev = args->dev;
u16 min_io_sectors;
rbuf[1] = 0xb0;
@@ -2076,7 +2092,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
* logical than physical sector size we need to figure out what the
* latter is.
*/
- min_io_sectors = 1 << ata_id_log2_per_physical_sector(args->id);
+ min_io_sectors = 1 << ata_id_log2_per_physical_sector(dev->id);
put_unaligned_be16(min_io_sectors, &rbuf[6]);
/*
@@ -2088,7 +2104,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
* that we support some form of unmap - in thise case via WRITE SAME
* with the unmap bit set.
*/
- if (ata_id_has_trim(args->id)) {
+ if (ata_id_has_trim(dev->id)) {
u64 max_blocks = 65535 * ATA_MAX_TRIM_RNUM;
if (dev->quirks & ATA_QUIRK_MAX_TRIM_128M)
@@ -2098,14 +2114,27 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
put_unaligned_be32(1, &rbuf[28]);
}
- return 0;
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
-static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
+/**
+ * ata_scsiop_inq_b1 - Simulate INQUIRY VPD page B1, Block Device
+ * Characteristics
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *
+ * Return data for the VPD page B1h (Block Device Characteristics).
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static unsigned int ata_scsiop_inq_b1(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
- int form_factor = ata_id_form_factor(args->id);
- int media_rotation_rate = ata_id_rotation_rate(args->id);
- u8 zoned = ata_id_zoned_cap(args->id);
+ int form_factor = ata_id_form_factor(dev->id);
+ int media_rotation_rate = ata_id_rotation_rate(dev->id);
+ u8 zoned = ata_id_zoned_cap(dev->id);
rbuf[1] = 0xb1;
rbuf[3] = 0x3c;
@@ -2115,21 +2144,52 @@ static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
if (zoned)
rbuf[8] = (zoned << 4);
- return 0;
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
-static unsigned int ata_scsiop_inq_b2(struct ata_scsi_args *args, u8 *rbuf)
+/**
+ * ata_scsiop_inq_b2 - Simulate INQUIRY VPD page B2, Logical Block
+ * Provisioning
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *
+ * Return data for the VPD page B2h (Logical Block Provisioning).
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static unsigned int ata_scsiop_inq_b2(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
/* SCSI Thin Provisioning VPD page: SBC-3 rev 22 or later */
rbuf[1] = 0xb2;
rbuf[3] = 0x4;
rbuf[5] = 1 << 6; /* TPWS */
- return 0;
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
-static unsigned int ata_scsiop_inq_b6(struct ata_scsi_args *args, u8 *rbuf)
+/**
+ * ata_scsiop_inq_b6 - Simulate INQUIRY VPD page B6, Zoned Block Device
+ * Characteristics
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *
+ * Return data for the VPD page B2h (Zoned Block Device Characteristics).
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static unsigned int ata_scsiop_inq_b6(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
+ if (!(dev->flags & ATA_DFLAG_ZAC)) {
+ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+ return 0;
+ }
+
/*
* zbc-r05 SCSI Zoned Block device characteristics VPD page
*/
@@ -2139,21 +2199,39 @@ static unsigned int ata_scsiop_inq_b6(struct ata_scsi_args *args, u8 *rbuf)
/*
* URSWRZ bit is only meaningful for host-managed ZAC drives
*/
- if (args->dev->zac_zoned_cap & 1)
+ if (dev->zac_zoned_cap & 1)
rbuf[4] |= 1;
- put_unaligned_be32(args->dev->zac_zones_optimal_open, &rbuf[8]);
- put_unaligned_be32(args->dev->zac_zones_optimal_nonseq, &rbuf[12]);
- put_unaligned_be32(args->dev->zac_zones_max_open, &rbuf[16]);
+ put_unaligned_be32(dev->zac_zones_optimal_open, &rbuf[8]);
+ put_unaligned_be32(dev->zac_zones_optimal_nonseq, &rbuf[12]);
+ put_unaligned_be32(dev->zac_zones_max_open, &rbuf[16]);
- return 0;
+ return get_unaligned_be16(&rbuf[2]) + 4;
}
-static unsigned int ata_scsiop_inq_b9(struct ata_scsi_args *args, u8 *rbuf)
+/**
+ * ata_scsiop_inq_b9 - Simulate INQUIRY VPD page B9, Concurrent Positioning
+ * Ranges
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *
+ * Return data for the VPD page B9h (Concurrent Positioning Ranges).
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static unsigned int ata_scsiop_inq_b9(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
- struct ata_cpr_log *cpr_log = args->dev->cpr_log;
+ struct ata_cpr_log *cpr_log = dev->cpr_log;
u8 *desc = &rbuf[64];
int i;
+ if (!cpr_log) {
+ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+ return 0;
+ }
+
/* SCSI Concurrent Positioning Ranges VPD page: SBC-5 rev 1 or later */
rbuf[1] = 0xb9;
put_unaligned_be16(64 + (int)cpr_log->nr_cpr * 32 - 4, &rbuf[2]);
@@ -2165,7 +2243,58 @@ static unsigned int ata_scsiop_inq_b9(struct ata_scsi_args *args, u8 *rbuf)
put_unaligned_be64(cpr_log->cpr[i].num_lbas, &desc[16]);
}
- return 0;
+ return get_unaligned_be16(&rbuf[2]) + 4;
+}
+
+/**
+ * ata_scsiop_inquiry - Simulate INQUIRY command
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *
+ * Returns data associated with an INQUIRY command output.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+static unsigned int ata_scsiop_inquiry(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
+{
+ const u8 *scsicmd = cmd->cmnd;
+
+ /* is CmdDt set? */
+ if (scsicmd[1] & 2) {
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+ return 0;
+ }
+
+ /* Is EVPD clear? */
+ if ((scsicmd[1] & 1) == 0)
+ return ata_scsiop_inq_std(dev, cmd, rbuf);
+
+ switch (scsicmd[2]) {
+ case 0x00:
+ return ata_scsiop_inq_00(dev, cmd, rbuf);
+ case 0x80:
+ return ata_scsiop_inq_80(dev, cmd, rbuf);
+ case 0x83:
+ return ata_scsiop_inq_83(dev, cmd, rbuf);
+ case 0x89:
+ return ata_scsiop_inq_89(dev, cmd, rbuf);
+ case 0xb0:
+ return ata_scsiop_inq_b0(dev, cmd, rbuf);
+ case 0xb1:
+ return ata_scsiop_inq_b1(dev, cmd, rbuf);
+ case 0xb2:
+ return ata_scsiop_inq_b2(dev, cmd, rbuf);
+ case 0xb6:
+ return ata_scsiop_inq_b6(dev, cmd, rbuf);
+ case 0xb9:
+ return ata_scsiop_inq_b9(dev, cmd, rbuf);
+ default:
+ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+ return 0;
+ }
}
/**
@@ -2388,7 +2517,8 @@ static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable)
/**
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Simulate MODE SENSE commands. Assume this is invoked for direct
@@ -2398,10 +2528,10 @@ static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_mode_sense(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
- struct ata_device *dev = args->dev;
- u8 *scsicmd = args->cmd->cmnd, *p = rbuf;
+ u8 *scsicmd = cmd->cmnd, *p = rbuf;
static const u8 sat_blk_desc[] = {
0, 0, 0, 0, /* number of blocks: sat unspecified */
0,
@@ -2466,17 +2596,17 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
break;
case CACHE_MPAGE:
- p += ata_msense_caching(args->id, p, page_control == 1);
+ p += ata_msense_caching(dev->id, p, page_control == 1);
break;
case CONTROL_MPAGE:
- p += ata_msense_control(args->dev, p, spg, page_control == 1);
+ p += ata_msense_control(dev, p, spg, page_control == 1);
break;
case ALL_MPAGES:
p += ata_msense_rw_recovery(p, page_control == 1);
- p += ata_msense_caching(args->id, p, page_control == 1);
- p += ata_msense_control(args->dev, p, spg, page_control == 1);
+ p += ata_msense_caching(dev->id, p, page_control == 1);
+ p += ata_msense_control(dev, p, spg, page_control == 1);
break;
default: /* invalid page code */
@@ -2494,29 +2624,33 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
rbuf[3] = sizeof(sat_blk_desc);
memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
}
- } else {
- put_unaligned_be16(p - rbuf - 2, &rbuf[0]);
- rbuf[3] |= dpofua;
- if (ebd) {
- rbuf[7] = sizeof(sat_blk_desc);
- memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
- }
+
+ return rbuf[0] + 1;
}
- return 0;
+
+ put_unaligned_be16(p - rbuf - 2, &rbuf[0]);
+ rbuf[3] |= dpofua;
+ if (ebd) {
+ rbuf[7] = sizeof(sat_blk_desc);
+ memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
+ }
+
+ return get_unaligned_be16(&rbuf[0]) + 2;
invalid_fld:
- ata_scsi_set_invalid_field(dev, args->cmd, fp, bp);
- return 1;
+ ata_scsi_set_invalid_field(dev, cmd, fp, bp);
+ return 0;
saving_not_supp:
- ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
+ ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x39, 0x0);
/* "Saving parameters not supported" */
- return 1;
+ return 0;
}
/**
* ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Simulate READ CAPACITY commands.
@@ -2524,9 +2658,10 @@ saving_not_supp:
* LOCKING:
* None.
*/
-static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_read_cap(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
- struct ata_device *dev = args->dev;
+ u8 *scsicmd = cmd->cmnd;
u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */
u32 sector_size; /* physical sector size in bytes */
u8 log2_per_phys;
@@ -2536,7 +2671,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
log2_per_phys = ata_id_log2_per_physical_sector(dev->id);
lowest_aligned = ata_id_logical_sector_offset(dev->id, log2_per_phys);
- if (args->cmd->cmnd[0] == READ_CAPACITY) {
+ if (scsicmd[0] == READ_CAPACITY) {
if (last_lba >= 0xffffffffULL)
last_lba = 0xffffffff;
@@ -2551,48 +2686,59 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
rbuf[5] = sector_size >> (8 * 2);
rbuf[6] = sector_size >> (8 * 1);
rbuf[7] = sector_size;
- } else {
- /* sector count, 64-bit */
- rbuf[0] = last_lba >> (8 * 7);
- rbuf[1] = last_lba >> (8 * 6);
- rbuf[2] = last_lba >> (8 * 5);
- rbuf[3] = last_lba >> (8 * 4);
- rbuf[4] = last_lba >> (8 * 3);
- rbuf[5] = last_lba >> (8 * 2);
- rbuf[6] = last_lba >> (8 * 1);
- rbuf[7] = last_lba;
- /* sector size */
- rbuf[ 8] = sector_size >> (8 * 3);
- rbuf[ 9] = sector_size >> (8 * 2);
- rbuf[10] = sector_size >> (8 * 1);
- rbuf[11] = sector_size;
-
- rbuf[12] = 0;
- rbuf[13] = log2_per_phys;
- rbuf[14] = (lowest_aligned >> 8) & 0x3f;
- rbuf[15] = lowest_aligned;
-
- if (ata_id_has_trim(args->id) &&
- !(dev->quirks & ATA_QUIRK_NOTRIM)) {
- rbuf[14] |= 0x80; /* LBPME */
-
- if (ata_id_has_zero_after_trim(args->id) &&
- dev->quirks & ATA_QUIRK_ZERO_AFTER_TRIM) {
- ata_dev_info(dev, "Enabling discard_zeroes_data\n");
- rbuf[14] |= 0x40; /* LBPRZ */
- }
+ return 8;
+ }
+
+ /*
+ * READ CAPACITY 16 command is defined as a service action
+ * (SERVICE_ACTION_IN_16 command).
+ */
+ if (scsicmd[0] != SERVICE_ACTION_IN_16 ||
+ (scsicmd[1] & 0x1f) != SAI_READ_CAPACITY_16) {
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+ return 0;
+ }
+
+ /* sector count, 64-bit */
+ rbuf[0] = last_lba >> (8 * 7);
+ rbuf[1] = last_lba >> (8 * 6);
+ rbuf[2] = last_lba >> (8 * 5);
+ rbuf[3] = last_lba >> (8 * 4);
+ rbuf[4] = last_lba >> (8 * 3);
+ rbuf[5] = last_lba >> (8 * 2);
+ rbuf[6] = last_lba >> (8 * 1);
+ rbuf[7] = last_lba;
+
+ /* sector size */
+ rbuf[ 8] = sector_size >> (8 * 3);
+ rbuf[ 9] = sector_size >> (8 * 2);
+ rbuf[10] = sector_size >> (8 * 1);
+ rbuf[11] = sector_size;
+
+ if (ata_id_zoned_cap(dev->id) || dev->class == ATA_DEV_ZAC)
+ rbuf[12] = (1 << 4); /* RC_BASIS */
+ rbuf[13] = log2_per_phys;
+ rbuf[14] = (lowest_aligned >> 8) & 0x3f;
+ rbuf[15] = lowest_aligned;
+
+ if (ata_id_has_trim(dev->id) && !(dev->quirks & ATA_QUIRK_NOTRIM)) {
+ rbuf[14] |= 0x80; /* LBPME */
+
+ if (ata_id_has_zero_after_trim(dev->id) &&
+ dev->quirks & ATA_QUIRK_ZERO_AFTER_TRIM) {
+ ata_dev_info(dev, "Enabling discard_zeroes_data\n");
+ rbuf[14] |= 0x40; /* LBPRZ */
}
- if (ata_id_zoned_cap(args->id) ||
- args->dev->class == ATA_DEV_ZAC)
- rbuf[12] = (1 << 4); /* RC_BASIS */
}
- return 0;
+
+ return 16;
}
/**
* ata_scsiop_report_luns - Simulate REPORT LUNS command
- * @args: device IDENTIFY data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Simulate REPORT LUNS command.
@@ -2600,11 +2746,12 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_report_luns(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */
- return 0;
+ return 16;
}
/*
@@ -3312,7 +3459,8 @@ invalid_opcode:
/**
* ata_scsiop_maint_in - Simulate a subset of MAINTENANCE_IN
- * @args: device MAINTENANCE_IN data / SCSI command of interest.
+ * @dev: Target device.
+ * @cmd: SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
*
* Yields a subset to satisfy scsi_report_opcode()
@@ -3320,17 +3468,21 @@ invalid_opcode:
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
+static unsigned int ata_scsiop_maint_in(struct ata_device *dev,
+ struct scsi_cmnd *cmd, u8 *rbuf)
{
- struct ata_device *dev = args->dev;
- u8 *cdb = args->cmd->cmnd;
+ u8 *cdb = cmd->cmnd;
u8 supported = 0, cdlp = 0, rwcdlp = 0;
- unsigned int err = 0;
+
+ if ((cdb[1] & 0x1f) != MI_REPORT_SUPPORTED_OPERATION_CODES) {
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+ return 0;
+ }
if (cdb[2] != 1 && cdb[2] != 3) {
ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
- err = 2;
- goto out;
+ ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+ return 0;
}
switch (cdb[3]) {
@@ -3398,11 +3550,12 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
default:
break;
}
-out:
+
/* One command format */
rbuf[0] = rwcdlp;
rbuf[1] = cdlp | supported;
- return err;
+
+ return 4;
}
/**
@@ -4262,78 +4415,26 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
{
- struct ata_scsi_args args;
const u8 *scsicmd = cmd->cmnd;
u8 tmp8;
- args.dev = dev;
- args.id = dev->id;
- args.cmd = cmd;
-
switch(scsicmd[0]) {
case INQUIRY:
- if (scsicmd[1] & 2) /* is CmdDt set? */
- ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
- else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
- else switch (scsicmd[2]) {
- case 0x00:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
- break;
- case 0x80:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
- break;
- case 0x83:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
- break;
- case 0x89:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
- break;
- case 0xb0:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b0);
- break;
- case 0xb1:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1);
- break;
- case 0xb2:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);
- break;
- case 0xb6:
- if (dev->flags & ATA_DFLAG_ZAC)
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b6);
- else
- ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
- break;
- case 0xb9:
- if (dev->cpr_log)
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b9);
- else
- ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
- break;
- default:
- ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
- break;
- }
+ ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_inquiry);
break;
case MODE_SENSE:
case MODE_SENSE_10:
- ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
+ ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_mode_sense);
break;
case READ_CAPACITY:
- ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
- break;
-
case SERVICE_ACTION_IN_16:
- if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
- ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
- else
- ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+ ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_read_cap);
break;
case REPORT_LUNS:
- ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
+ ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_report_luns);
break;
case REQUEST_SENSE:
@@ -4361,10 +4462,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
break;
case MAINTENANCE_IN:
- if ((scsicmd[1] & 0x1f) == MI_REPORT_SUPPORTED_OPERATION_CODES)
- ata_scsi_rbuf_fill(&args, ata_scsiop_maint_in);
- else
- ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+ ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_maint_in);
break;
/* all other commands */
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index d0c6924d25b6..514d549286b5 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -964,7 +964,7 @@ MODULE_DEVICE_TABLE(of, arasan_cf_id_table);
static struct platform_driver arasan_cf_driver = {
.probe = arasan_cf_probe,
- .remove_new = arasan_cf_remove,
+ .remove = arasan_cf_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &arasan_cf_pm_ops,
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index f3f5b2b0ecc9..e8cda988feb5 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -1015,7 +1015,7 @@ static struct platform_driver ep93xx_pata_platform_driver = {
.of_match_table = ep93xx_pata_of_ids,
},
.probe = ep93xx_pata_probe,
- .remove_new = ep93xx_pata_remove,
+ .remove = ep93xx_pata_remove,
};
module_platform_driver(ep93xx_pata_platform_driver);
diff --git a/drivers/ata/pata_falcon.c b/drivers/ata/pata_falcon.c
index 18ceefd176df..334c4eea41ec 100644
--- a/drivers/ata/pata_falcon.c
+++ b/drivers/ata/pata_falcon.c
@@ -225,8 +225,8 @@ static void pata_falcon_remove_one(struct platform_device *pdev)
static struct platform_driver pata_falcon_driver = {
.probe = pata_falcon_init_one,
- .remove_new = pata_falcon_remove_one,
- .driver = {
+ .remove = pata_falcon_remove_one,
+ .driver = {
.name = "atari-falcon-ide",
},
};
diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c
index 73a9a5109238..c3a8384c3e04 100644
--- a/drivers/ata/pata_ftide010.c
+++ b/drivers/ata/pata_ftide010.c
@@ -557,7 +557,7 @@ static struct platform_driver pata_ftide010_driver = {
.of_match_table = pata_ftide010_of_match,
},
.probe = pata_ftide010_probe,
- .remove_new = pata_ftide010_remove,
+ .remove = pata_ftide010_remove,
};
module_platform_driver(pata_ftide010_driver);
diff --git a/drivers/ata/pata_gayle.c b/drivers/ata/pata_gayle.c
index 94df60ac2307..8602c3889948 100644
--- a/drivers/ata/pata_gayle.c
+++ b/drivers/ata/pata_gayle.c
@@ -202,9 +202,9 @@ static void pata_gayle_remove_one(struct platform_device *pdev)
static struct platform_driver pata_gayle_driver = {
.probe = pata_gayle_init_one,
- .remove_new = pata_gayle_remove_one,
- .driver = {
- .name = "amiga-gayle-ide",
+ .remove = pata_gayle_remove_one,
+ .driver = {
+ .name = "amiga-gayle-ide",
},
};
diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c
index d0aa8fc929b4..b37682b0578f 100644
--- a/drivers/ata/pata_imx.c
+++ b/drivers/ata/pata_imx.c
@@ -249,7 +249,7 @@ MODULE_DEVICE_TABLE(of, imx_pata_dt_ids);
static struct platform_driver pata_imx_driver = {
.probe = pata_imx_probe,
- .remove_new = pata_imx_remove,
+ .remove = pata_imx_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = imx_pata_dt_ids,
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index b7ac56103c8a..9cbe2132ce59 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -81,7 +81,7 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
int control = 0;
/*
- * See Intel Document 298600-004 for the timing programing rules
+ * See Intel Document 298600-004 for the timing programming rules
* for PIIX/ICH. The 8213 is a clone so very similar
*/
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 8a9ee828478f..80f6a91acf6f 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -298,7 +298,7 @@ static struct platform_driver ixp4xx_pata_platform_driver = {
.of_match_table = ixp4xx_pata_of_match,
},
.probe = ixp4xx_pata_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
};
module_platform_driver(ixp4xx_pata_platform_driver);
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 3f9258677915..210a63283f62 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -854,7 +854,7 @@ static const struct of_device_id mpc52xx_ata_of_match[] = {
static struct platform_driver mpc52xx_ata_of_platform_driver = {
.probe = mpc52xx_ata_probe,
- .remove_new = mpc52xx_ata_remove,
+ .remove = mpc52xx_ata_remove,
#ifdef CONFIG_PM_SLEEP
.suspend = mpc52xx_ata_suspend,
.resume = mpc52xx_ata_resume,
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index 0bb9607e7348..dce24806a052 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -183,7 +183,7 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
reg_tim.s.ale = 0;
/* Not used */
reg_tim.s.page = 0;
- /* Time after IORDY to coninue to assert the data */
+ /* Time after IORDY to continue to assert the data */
reg_tim.s.wait = 0;
/* Time to wait to complete the cycle. */
reg_tim.s.pause = pause;
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index 4956f0f5b93f..178b28eff170 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -89,7 +89,7 @@ static struct platform_driver pata_of_platform_driver = {
.of_match_table = pata_of_platform_match,
},
.probe = pata_of_platform_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
};
module_platform_driver(pata_of_platform_driver);
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index dca82d92b004..3d01b7000e41 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -70,7 +70,7 @@ static void oldpiix_set_piomode (struct ata_port *ap, struct ata_device *adev)
int control = 0;
/*
- * See Intel Document 298600-004 for the timing programing rules
+ * See Intel Document 298600-004 for the timing programming rules
* for PIIX/ICH. Note that the early PIIX does not have the slave
* timing port at 0x44.
*/
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 232c3dad7ee8..87479bc893b2 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -223,7 +223,7 @@ static int pata_platform_probe(struct platform_device *pdev)
static struct platform_driver pata_platform_driver = {
.probe = pata_platform_probe,
- .remove_new = ata_platform_remove_one,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 538bd3423d85..434f380114af 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -306,7 +306,7 @@ static void pxa_ata_remove(struct platform_device *pdev)
static struct platform_driver pxa_ata_driver = {
.probe = pxa_ata_probe,
- .remove_new = pxa_ata_remove,
+ .remove = pxa_ata_remove,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 84b001097093..40ef8072c159 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -45,7 +45,7 @@ static void radisys_set_piomode (struct ata_port *ap, struct ata_device *adev)
int control = 0;
/*
- * See Intel Document 298600-004 for the timing programing rules
+ * See Intel Document 298600-004 for the timing programming rules
* for PIIX/ICH. Note that the early PIIX does not have the slave
* timing port at 0x44. The Radisys is a relative of the PIIX
* but not the same so be careful.
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index 0fa253ad7c93..fd81e75c9402 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -164,7 +164,7 @@ static void rb532_pata_driver_remove(struct platform_device *pdev)
static struct platform_driver rb532_pata_platform_driver = {
.probe = rb532_pata_driver_probe,
- .remove_new = rb532_pata_driver_remove,
+ .remove = rb532_pata_driver_remove,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 52f5168e4db5..6e1dd0d9c035 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1240,7 +1240,7 @@ static struct platform_driver sata_dwc_driver = {
.of_match_table = sata_dwc_match,
},
.probe = sata_dwc_probe,
- .remove_new = sata_dwc_remove,
+ .remove = sata_dwc_remove,
};
module_platform_driver(sata_dwc_driver);
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 01aa05f4c3f5..87e91a937a44 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -1589,7 +1589,7 @@ static struct platform_driver fsl_sata_driver = {
.of_match_table = fsl_sata_match,
},
.probe = sata_fsl_probe,
- .remove_new = sata_fsl_remove,
+ .remove = sata_fsl_remove,
#ifdef CONFIG_PM_SLEEP
.suspend = sata_fsl_suspend,
.resume = sata_fsl_resume,
diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c
index f574e3c3f5b4..d040799bf9cb 100644
--- a/drivers/ata/sata_gemini.c
+++ b/drivers/ata/sata_gemini.c
@@ -425,7 +425,7 @@ static struct platform_driver gemini_sata_driver = {
.of_match_table = gemini_sata_of_match,
},
.probe = gemini_sata_probe,
- .remove_new = gemini_sata_remove,
+ .remove = gemini_sata_remove,
};
module_platform_driver(gemini_sata_driver);
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 63ef7bb073ce..b1b40e9551de 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -614,12 +614,12 @@ static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
ahci_highbank_suspend, ahci_highbank_resume);
static struct platform_driver ahci_highbank_driver = {
- .remove_new = ata_platform_remove_one,
- .driver = {
- .name = "highbank-ahci",
- .of_match_table = ahci_of_match,
- .pm = &ahci_highbank_pm_ops,
- },
+ .remove = ata_platform_remove_one,
+ .driver = {
+ .name = "highbank-ahci",
+ .of_match_table = ahci_of_match,
+ .pm = &ahci_highbank_pm_ops,
+ },
.probe = ahci_highbank_probe,
};
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 05c905827dc5..b8f363370e1a 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4255,7 +4255,7 @@ MODULE_DEVICE_TABLE(of, mv_sata_dt_ids);
static struct platform_driver mv_platform_driver = {
.probe = mv_platform_probe,
- .remove_new = mv_platform_remove,
+ .remove = mv_platform_remove,
.suspend = mv_platform_suspend,
.resume = mv_platform_resume,
.driver = {
diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
index c1469d076880..22820a02d740 100644
--- a/drivers/ata/sata_rcar.c
+++ b/drivers/ata/sata_rcar.c
@@ -1009,7 +1009,7 @@ static const struct dev_pm_ops sata_rcar_pm_ops = {
static struct platform_driver sata_rcar_driver = {
.probe = sata_rcar_probe,
- .remove_new = sata_rcar_remove,
+ .remove = sata_rcar_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = sata_rcar_match,
diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c
index 6526aa51fb1d..e1a94ae3eb0c 100644
--- a/drivers/auxdisplay/cfag12864b.c
+++ b/drivers/auxdisplay/cfag12864b.c
@@ -37,11 +37,6 @@ module_param(cfag12864b_rate, uint, 0444);
MODULE_PARM_DESC(cfag12864b_rate,
"Refresh rate (hertz)");
-unsigned int cfag12864b_getrate(void)
-{
- return cfag12864b_rate;
-}
-
/*
* cfag12864b Commands
*
@@ -249,11 +244,6 @@ void cfag12864b_disable(void)
mutex_unlock(&cfag12864b_mutex);
}
-unsigned char cfag12864b_isenabled(void)
-{
- return cfag12864b_updating;
-}
-
static void cfag12864b_update(struct work_struct *work)
{
unsigned char c;
@@ -293,10 +283,8 @@ static void cfag12864b_update(struct work_struct *work)
*/
EXPORT_SYMBOL_GPL(cfag12864b_buffer);
-EXPORT_SYMBOL_GPL(cfag12864b_getrate);
EXPORT_SYMBOL_GPL(cfag12864b_enable);
EXPORT_SYMBOL_GPL(cfag12864b_disable);
-EXPORT_SYMBOL_GPL(cfag12864b_isenabled);
/*
* Is the module inited?
diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
index a816f9e10255..09deb864b27a 100644
--- a/drivers/auxdisplay/ht16k33.c
+++ b/drivers/auxdisplay/ht16k33.c
@@ -657,7 +657,6 @@ static int ht16k33_seg_probe(struct device *dev, struct ht16k33_priv *priv,
static int ht16k33_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
- const struct of_device_id *id;
struct ht16k33_priv *priv;
uint32_t dft_brightness;
int err;
@@ -672,9 +671,8 @@ static int ht16k33_probe(struct i2c_client *client)
return -ENOMEM;
priv->client = client;
- id = i2c_of_match_device(dev->driver->of_match_table, client);
- if (id)
- priv->type = (uintptr_t)id->data;
+ priv->type = (uintptr_t)i2c_get_match_data(client);
+
i2c_set_clientdata(client, priv);
err = ht16k33_initialize(priv);
@@ -747,7 +745,9 @@ static void ht16k33_remove(struct i2c_client *client)
}
static const struct i2c_device_id ht16k33_i2c_match[] = {
- { "ht16k33", 0 },
+ { "3108", DISP_QUAD_7SEG },
+ { "3130", DISP_QUAD_14SEG },
+ { "ht16k33", DISP_MATRIX },
{ }
};
MODULE_DEVICE_TABLE(i2c, ht16k33_i2c_match);
diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c
index 6422be0dfe20..a28daa4ffbf7 100644
--- a/drivers/auxdisplay/lcd2s.c
+++ b/drivers/auxdisplay/lcd2s.c
@@ -349,7 +349,7 @@ static void lcd2s_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id lcd2s_i2c_id[] = {
- { "lcd2s", 0 },
+ { "lcd2s" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lcd2s_i2c_id);
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 75fcb75d5515..3ebe77566788 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -366,7 +366,7 @@ void __weak freq_inv_set_max_ratio(int cpu, u64 max_rate)
#ifdef CONFIG_ACPI_CPPC_LIB
#include <acpi/cppc_acpi.h>
-void topology_init_cpu_capacity_cppc(void)
+static inline void topology_init_cpu_capacity_cppc(void)
{
u64 capacity, capacity_scale = 0;
struct cppc_perf_caps perf_caps;
@@ -417,6 +417,10 @@ void topology_init_cpu_capacity_cppc(void)
exit:
free_raw_capacity();
}
+void acpi_processor_init_invariance_cppc(void)
+{
+ topology_init_cpu_capacity_cppc();
+}
#endif
#ifdef CONFIG_CPU_FREQ
diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c
index 7823888af4f6..afa4df4c5a3f 100644
--- a/drivers/base/auxiliary.c
+++ b/drivers/base/auxiliary.c
@@ -92,7 +92,7 @@
* Auxiliary devices are created and registered by a subsystem-level core
* device that needs to break up its functionality into smaller fragments. One
* way to extend the scope of an auxiliary_device is to encapsulate it within a
- * domain- pecific structure defined by the parent device. This structure
+ * domain-specific structure defined by the parent device. This structure
* contains the auxiliary_device and any associated shared data/callbacks
* needed to establish the connection with the parent.
*
@@ -336,35 +336,6 @@ int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname)
EXPORT_SYMBOL_GPL(__auxiliary_device_add);
/**
- * auxiliary_find_device - auxiliary device iterator for locating a particular device.
- * @start: Device to begin with
- * @data: Data to pass to match function
- * @match: Callback function to check device
- *
- * This function returns a reference to a device that is 'found'
- * for later use, as determined by the @match callback.
- *
- * The reference returned should be released with put_device().
- *
- * The callback should return 0 if the device doesn't match and non-zero
- * if it does. If the callback returns non-zero, this function will
- * return to the caller and not iterate over any more devices.
- */
-struct auxiliary_device *auxiliary_find_device(struct device *start,
- const void *data,
- device_match_t match)
-{
- struct device *dev;
-
- dev = bus_find_device(&auxiliary_bus_type, start, data, match);
- if (!dev)
- return NULL;
-
- return to_auxiliary_dev(dev);
-}
-EXPORT_SYMBOL_GPL(auxiliary_find_device);
-
-/**
* __auxiliary_driver_register - register a driver for auxiliary bus devices
* @auxdrv: auxiliary_driver structure
* @owner: owning module/driver
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 7a7609298e18..609935ad5091 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -254,11 +254,11 @@ static int of_count_cache_leaves(struct device_node *np)
{
unsigned int leaves = 0;
- if (of_property_read_bool(np, "cache-size"))
+ if (of_property_present(np, "cache-size"))
++leaves;
- if (of_property_read_bool(np, "i-cache-size"))
+ if (of_property_present(np, "i-cache-size"))
++leaves;
- if (of_property_read_bool(np, "d-cache-size"))
+ if (of_property_present(np, "d-cache-size"))
++leaves;
if (!leaves) {
@@ -367,9 +367,7 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)
cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
for_each_online_cpu(i) {
- struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i);
-
- if (i == cpu || !sib_cpu_ci->info_list)
+ if (i == cpu || !per_cpu_cacheinfo(i))
continue;/* skip if itself or no cacheinfo */
for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) {
sib_leaf = per_cpu_cacheinfo_idx(i, sib_index);
@@ -409,10 +407,7 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
for (index = 0; index < cache_leaves(cpu); index++) {
this_leaf = per_cpu_cacheinfo_idx(cpu, index);
for_each_cpu(sibling, &this_leaf->shared_cpu_map) {
- struct cpu_cacheinfo *sib_cpu_ci =
- get_cpu_cacheinfo(sibling);
-
- if (sibling == cpu || !sib_cpu_ci->info_list)
+ if (sibling == cpu || !per_cpu_cacheinfo(sibling))
continue;/* skip if itself or no cacheinfo */
for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) {
diff --git a/drivers/base/class.c b/drivers/base/class.c
index cb5359235c70..582b5a02a5c4 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -405,7 +405,7 @@ int class_for_each_device(const struct class *class, const struct device *start,
if (!class)
return -EINVAL;
if (!sp) {
- WARN(1, "%s called for class '%s' before it was initialized",
+ WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name);
return -EINVAL;
}
@@ -453,7 +453,7 @@ struct device *class_find_device(const struct class *class, const struct device
if (!class)
return NULL;
if (!sp) {
- WARN(1, "%s called for class '%s' before it was initialized",
+ WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name);
return NULL;
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 048ff98dbdfd..94865c9d8adc 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -552,7 +552,7 @@ void device_link_wait_removal(void)
}
EXPORT_SYMBOL_GPL(device_link_wait_removal);
-static struct class devlink_class = {
+static const struct class devlink_class = {
.name = "devlink",
.dev_groups = devlink_groups,
.dev_release = devlink_dev_release,
@@ -1971,7 +1971,7 @@ static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwn
/**
* __fw_devlink_relax_cycles - Relax and mark dependency cycles.
- * @con: Potential consumer device.
+ * @con_handle: Potential consumer device fwnode.
* @sup_handle: Potential supplier's fwnode.
*
* Needs to be called with fwnode_lock and device link lock held.
@@ -1989,10 +1989,10 @@ static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwn
*
* Return true if one or more cycles were found. Otherwise, return false.
*/
-static bool __fw_devlink_relax_cycles(struct device *con,
+static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
struct fwnode_handle *sup_handle)
{
- struct device *sup_dev = NULL, *par_dev = NULL;
+ struct device *sup_dev = NULL, *par_dev = NULL, *con_dev = NULL;
struct fwnode_link *link;
struct device_link *dev_link;
bool ret = false;
@@ -2009,22 +2009,22 @@ static bool __fw_devlink_relax_cycles(struct device *con,
sup_handle->flags |= FWNODE_FLAG_VISITED;
- sup_dev = get_dev_from_fwnode(sup_handle);
-
/* Termination condition. */
- if (sup_dev == con) {
+ if (sup_handle == con_handle) {
pr_debug("----- cycle: start -----\n");
ret = true;
goto out;
}
+ sup_dev = get_dev_from_fwnode(sup_handle);
+ con_dev = get_dev_from_fwnode(con_handle);
/*
* If sup_dev is bound to a driver and @con hasn't started binding to a
* driver, sup_dev can't be a consumer of @con. So, no need to check
* further.
*/
if (sup_dev && sup_dev->links.status == DL_DEV_DRIVER_BOUND &&
- con->links.status == DL_DEV_NO_DRIVER) {
+ con_dev && con_dev->links.status == DL_DEV_NO_DRIVER) {
ret = false;
goto out;
}
@@ -2033,7 +2033,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
if (link->flags & FWLINK_FLAG_IGNORE)
continue;
- if (__fw_devlink_relax_cycles(con, link->supplier)) {
+ if (__fw_devlink_relax_cycles(con_handle, link->supplier)) {
__fwnode_link_cycle(link);
ret = true;
}
@@ -2048,7 +2048,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
else
par_dev = fwnode_get_next_parent_dev(sup_handle);
- if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode)) {
+ if (par_dev && __fw_devlink_relax_cycles(con_handle, par_dev->fwnode)) {
pr_debug("%pfwf: cycle: child of %pfwf\n", sup_handle,
par_dev->fwnode);
ret = true;
@@ -2066,7 +2066,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
!(dev_link->flags & DL_FLAG_CYCLE))
continue;
- if (__fw_devlink_relax_cycles(con,
+ if (__fw_devlink_relax_cycles(con_handle,
dev_link->supplier->fwnode)) {
pr_debug("%pfwf: cycle: depends on %pfwf\n", sup_handle,
dev_link->supplier->fwnode);
@@ -2114,11 +2114,6 @@ static int fw_devlink_create_devlink(struct device *con,
if (link->flags & FWLINK_FLAG_IGNORE)
return 0;
- if (con->fwnode == link->consumer)
- flags = fw_devlink_get_flags(link->flags);
- else
- flags = FW_DEVLINK_FLAGS_PERMISSIVE;
-
/*
* In some cases, a device P might also be a supplier to its child node
* C. However, this would defer the probe of C until the probe of P
@@ -2139,25 +2134,23 @@ static int fw_devlink_create_devlink(struct device *con,
return -EINVAL;
/*
- * SYNC_STATE_ONLY device links don't block probing and supports cycles.
- * So, one might expect that cycle detection isn't necessary for them.
- * However, if the device link was marked as SYNC_STATE_ONLY because
- * it's part of a cycle, then we still need to do cycle detection. This
- * is because the consumer and supplier might be part of multiple cycles
- * and we need to detect all those cycles.
+ * Don't try to optimize by not calling the cycle detection logic under
+ * certain conditions. There's always some corner case that won't get
+ * detected.
*/
- if (!device_link_flag_is_sync_state_only(flags) ||
- flags & DL_FLAG_CYCLE) {
- device_links_write_lock();
- if (__fw_devlink_relax_cycles(con, sup_handle)) {
- __fwnode_link_cycle(link);
- flags = fw_devlink_get_flags(link->flags);
- pr_debug("----- cycle: end -----\n");
- dev_info(con, "Fixed dependency cycle(s) with %pfwf\n",
- sup_handle);
- }
- device_links_write_unlock();
+ device_links_write_lock();
+ if (__fw_devlink_relax_cycles(link->consumer, sup_handle)) {
+ __fwnode_link_cycle(link);
+ pr_debug("----- cycle: end -----\n");
+ pr_info("%pfwf: Fixed dependency cycle(s) with %pfwf\n",
+ link->consumer, sup_handle);
}
+ device_links_write_unlock();
+
+ if (con->fwnode == link->consumer)
+ flags = fw_devlink_get_flags(link->flags);
+ else
+ flags = FW_DEVLINK_FLAGS_PERMISSIVE;
if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
sup_dev = fwnode_get_next_parent_dev(sup_handle);
@@ -2180,8 +2173,8 @@ static int fw_devlink_create_devlink(struct device *con,
}
if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
- dev_err(con, "Failed to create device link (0x%x) with %s\n",
- flags, dev_name(sup_dev));
+ dev_err(con, "Failed to create device link (0x%x) with supplier %s for %pfwf\n",
+ flags, dev_name(sup_dev), link->consumer);
ret = -EINVAL;
}
@@ -5012,6 +5005,49 @@ define_dev_printk_level(_dev_info, KERN_INFO);
#endif
+static void __dev_probe_failed(const struct device *dev, int err, bool fatal,
+ const char *fmt, va_list vargsp)
+{
+ struct va_format vaf;
+ va_list vargs;
+
+ /*
+ * On x86_64 and possibly on other architectures, va_list is actually a
+ * size-1 array containing a structure. As a result, function parameter
+ * vargsp decays from T[1] to T*, and &vargsp has type T** rather than
+ * T(*)[1], which is expected by its assignment to vaf.va below.
+ *
+ * One standard way to solve this mess is by creating a copy in a local
+ * variable of type va_list and then using a pointer to that local copy
+ * instead, which is the approach employed here.
+ */
+ va_copy(vargs, vargsp);
+
+ vaf.fmt = fmt;
+ vaf.va = &vargs;
+
+ switch (err) {
+ case -EPROBE_DEFER:
+ device_set_deferred_probe_reason(dev, &vaf);
+ dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
+ break;
+
+ case -ENOMEM:
+ /* Don't print anything on -ENOMEM, there's already enough output */
+ break;
+
+ default:
+ /* Log fatal final failures as errors, otherwise produce warnings */
+ if (fatal)
+ dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
+ else
+ dev_warn(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
+ break;
+ }
+
+ va_end(vargs);
+}
+
/**
* dev_err_probe - probe error check and log helper
* @dev: the pointer to the struct device
@@ -5024,7 +5060,7 @@ define_dev_printk_level(_dev_info, KERN_INFO);
* -EPROBE_DEFER and propagate error upwards.
* In case of -EPROBE_DEFER it sets also defer probe reason, which can be
* checked later by reading devices_deferred debugfs attribute.
- * It replaces code sequence::
+ * It replaces the following code sequence::
*
* if (err != -EPROBE_DEFER)
* dev_err(dev, ...);
@@ -5036,47 +5072,77 @@ define_dev_printk_level(_dev_info, KERN_INFO);
*
* return dev_err_probe(dev, err, ...);
*
- * Using this helper in your probe function is totally fine even if @err is
- * known to never be -EPROBE_DEFER.
+ * Using this helper in your probe function is totally fine even if @err
+ * is known to never be -EPROBE_DEFER.
* The benefit compared to a normal dev_err() is the standardized format
- * of the error code, it being emitted symbolically (i.e. you get "EAGAIN"
- * instead of "-35") and the fact that the error code is returned which allows
- * more compact error paths.
+ * of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
+ * instead of "-35"), and having the error code returned allows more
+ * compact error paths.
*
* Returns @err.
*/
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
{
- struct va_format vaf;
- va_list args;
+ va_list vargs;
- va_start(args, fmt);
- vaf.fmt = fmt;
- vaf.va = &args;
+ va_start(vargs, fmt);
- switch (err) {
- case -EPROBE_DEFER:
- device_set_deferred_probe_reason(dev, &vaf);
- dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
- break;
+ /* Use dev_err() for logging when err doesn't equal -EPROBE_DEFER */
+ __dev_probe_failed(dev, err, true, fmt, vargs);
- case -ENOMEM:
- /*
- * We don't print anything on -ENOMEM, there is already enough
- * output.
- */
- break;
+ va_end(vargs);
- default:
- dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
- break;
- }
+ return err;
+}
+EXPORT_SYMBOL_GPL(dev_err_probe);
- va_end(args);
+/**
+ * dev_warn_probe - probe error check and log helper
+ * @dev: the pointer to the struct device
+ * @err: error value to test
+ * @fmt: printf-style format string
+ * @...: arguments as specified in the format string
+ *
+ * This helper implements common pattern present in probe functions for error
+ * checking: print debug or warning message depending if the error value is
+ * -EPROBE_DEFER and propagate error upwards.
+ * In case of -EPROBE_DEFER it sets also defer probe reason, which can be
+ * checked later by reading devices_deferred debugfs attribute.
+ * It replaces the following code sequence::
+ *
+ * if (err != -EPROBE_DEFER)
+ * dev_warn(dev, ...);
+ * else
+ * dev_dbg(dev, ...);
+ * return err;
+ *
+ * with::
+ *
+ * return dev_warn_probe(dev, err, ...);
+ *
+ * Using this helper in your probe function is totally fine even if @err
+ * is known to never be -EPROBE_DEFER.
+ * The benefit compared to a normal dev_warn() is the standardized format
+ * of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
+ * instead of "-35"), and having the error code returned allows more
+ * compact error paths.
+ *
+ * Returns @err.
+ */
+int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...)
+{
+ va_list vargs;
+
+ va_start(vargs, fmt);
+
+ /* Use dev_warn() for logging when err doesn't equal -EPROBE_DEFER */
+ __dev_probe_failed(dev, err, false, fmt, vargs);
+
+ va_end(vargs);
return err;
}
-EXPORT_SYMBOL_GPL(dev_err_probe);
+EXPORT_SYMBOL_GPL(dev_warn_probe);
static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
{
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 324a9a3c087a..cb0912ea3e62 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -829,19 +829,18 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, st
shash->tfm = alg;
if (crypto_shash_digest(shash, fw->data, fw->size, sha256buf) < 0)
- goto out_shash;
+ goto out_free;
for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
sprintf(&outbuf[i * 2], "%02x", sha256buf[i]);
outbuf[SHA256_BLOCK_SIZE] = 0;
dev_dbg(device, "Loaded FW: %s, sha256: %s\n", name, outbuf);
-out_shash:
- crypto_free_shash(alg);
out_free:
kfree(shash);
kfree(outbuf);
kfree(sha256buf);
+ crypto_free_shash(alg);
}
#else
static void fw_log_firmware_info(const struct firmware *fw, const char *name,
@@ -1075,8 +1074,8 @@ EXPORT_SYMBOL_GPL(firmware_request_platform);
/**
* firmware_request_cache() - cache firmware for suspend so resume can use it
- * @name: name of firmware file
* @device: device for which firmware should be cached for
+ * @name: name of firmware file
*
* There are some devices with an optimization that enables the device to not
* require loading firmware on system reboot. This optimization may still
diff --git a/drivers/base/node.c b/drivers/base/node.c
index eb72580288e6..0ea653fa3433 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -27,7 +27,7 @@ static const struct bus_type node_subsys = {
};
static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -45,10 +45,10 @@ static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
return n;
}
-static BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES);
static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -66,7 +66,7 @@ static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
return n;
}
-static BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
/**
* struct node_access_nodes - Access class device to hold user visible
@@ -578,7 +578,7 @@ static struct attribute *node_dev_attrs[] = {
NULL
};
-static struct bin_attribute *node_dev_bin_attrs[] = {
+static const struct bin_attribute *node_dev_bin_attrs[] = {
&bin_attr_cpumap,
&bin_attr_cpulist,
NULL
@@ -586,7 +586,7 @@ static struct bin_attribute *node_dev_bin_attrs[] = {
static const struct attribute_group node_dev_group = {
.attrs = node_dev_attrs,
- .bin_attrs = node_dev_bin_attrs
+ .bin_attrs_new = node_dev_bin_attrs,
};
static const struct attribute_group *node_dev_groups[] = {
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index cca2fd0a1aed..781968a128ff 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -11,6 +11,7 @@
#include <linux/pm_clock.h>
#include <linux/acpi.h>
#include <linux/pm_domain.h>
+#include <linux/pm_opp.h>
#include "power.h"
@@ -222,13 +223,15 @@ int dev_pm_domain_attach_list(struct device *dev,
if (!pds)
return -ENOMEM;
- size = sizeof(*pds->pd_devs) + sizeof(*pds->pd_links);
+ size = sizeof(*pds->pd_devs) + sizeof(*pds->pd_links) +
+ sizeof(*pds->opp_tokens);
pds->pd_devs = kcalloc(num_pds, size, GFP_KERNEL);
if (!pds->pd_devs) {
ret = -ENOMEM;
goto free_pds;
}
pds->pd_links = (void *)(pds->pd_devs + num_pds);
+ pds->opp_tokens = (void *)(pds->pd_links + num_pds);
if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
link_flags |= DL_FLAG_RPM_ACTIVE;
@@ -244,6 +247,19 @@ int dev_pm_domain_attach_list(struct device *dev,
goto err_attach;
}
+ if (pd_flags & PD_FLAG_REQUIRED_OPP) {
+ struct dev_pm_opp_config config = {
+ .required_dev = pd_dev,
+ .required_dev_index = i,
+ };
+
+ ret = dev_pm_opp_set_config(dev, &config);
+ if (ret < 0)
+ goto err_link;
+
+ pds->opp_tokens[i] = ret;
+ }
+
if (link_flags) {
struct device_link *link;
@@ -264,9 +280,11 @@ int dev_pm_domain_attach_list(struct device *dev,
return num_pds;
err_link:
+ dev_pm_opp_clear_config(pds->opp_tokens[i]);
dev_pm_domain_detach(pd_dev, true);
err_attach:
while (--i >= 0) {
+ dev_pm_opp_clear_config(pds->opp_tokens[i]);
if (pds->pd_links[i])
device_link_del(pds->pd_links[i]);
dev_pm_domain_detach(pds->pd_devs[i], true);
@@ -361,6 +379,7 @@ void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
return;
for (i = 0; i < list->num_pds; i++) {
+ dev_pm_opp_clear_config(list->opp_tokens[i]);
if (list->pd_links[i])
device_link_del(list->pd_links[i]);
dev_pm_domain_detach(list->pd_devs[i], true);
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index bd77f6734f14..ff393cba7649 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -137,6 +137,7 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
return ret;
}
+EXPORT_SYMBOL_GPL(dev_pm_qos_read_value);
/**
* apply_constraint - Add/modify/remove device PM QoS request.
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a1474fb67db9..f8163b559bf9 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -509,14 +509,6 @@ static ssize_t wakeup_last_time_ms_show(struct device *dev,
return sysfs_emit(buf, "%lld\n", msec);
}
-static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
- kgid_t kgid)
-{
- if (dev->power.wakeup && dev->power.wakeup->dev)
- return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
- return 0;
-}
-
static DEVICE_ATTR_RO(wakeup_last_time_ms);
#ifdef CONFIG_PM_AUTOSLEEP
@@ -541,6 +533,15 @@ static ssize_t wakeup_prevent_sleep_time_ms_show(struct device *dev,
static DEVICE_ATTR_RO(wakeup_prevent_sleep_time_ms);
#endif /* CONFIG_PM_AUTOSLEEP */
+
+static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
+ kgid_t kgid)
+{
+ if (dev->power.wakeup && dev->power.wakeup->dev)
+ return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
+ return 0;
+}
+
#else /* CONFIG_PM_SLEEP */
static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
kgid_t kgid)
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 83acccdc1008..bdb450436cbc 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -59,6 +59,7 @@ struct regmap {
unsigned long raw_spinlock_flags;
};
};
+ struct lock_class_key *lock_key;
regmap_lock lock;
regmap_unlock unlock;
void *lock_arg; /* This is passed to lock/unlock functions */
diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c
index 8d27d3653ea3..23da7b31d715 100644
--- a/drivers/base/regmap/regcache-maple.c
+++ b/drivers/base/regmap/regcache-maple.c
@@ -355,6 +355,9 @@ static int regcache_maple_init(struct regmap *map)
mt_init(mt);
+ if (!mt_external_lock(mt) && map->lock_key)
+ lockdep_set_class_and_subclass(&mt->ma_lock, map->lock_key, 1);
+
if (!map->num_reg_defaults)
return 0;
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index a750e48a26b8..0bcd81389a29 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -364,14 +364,11 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
memset32(data->status_buf, GENMASK(31, 0), chip->num_regs);
} else if (chip->num_main_regs) {
unsigned int max_main_bits;
- unsigned long size;
-
- size = chip->num_regs * sizeof(unsigned int);
max_main_bits = (chip->num_main_status_bits) ?
chip->num_main_status_bits : chip->num_regs;
/* Clear the status buf as we don't read all status regs */
- memset(data->status_buf, 0, size);
+ memset32(data->status_buf, 0, chip->num_regs);
/* We could support bulk read for main status registers
* but I don't expect to see devices with really many main
@@ -514,12 +511,16 @@ exit:
return IRQ_NONE;
}
+static struct lock_class_key regmap_irq_lock_class;
+static struct lock_class_key regmap_irq_request_class;
+
static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct regmap_irq_chip_data *data = h->host_data;
irq_set_chip_data(virq, data);
+ irq_set_lockdep_class(virq, &regmap_irq_lock_class, &regmap_irq_request_class);
irq_set_chip(virq, &data->irq_chip);
irq_set_nested_thread(virq, 1);
irq_set_parent(virq, data->irq);
diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c
index 4bf3f1e59ed7..64ea340950b6 100644
--- a/drivers/base/regmap/regmap-kunit.c
+++ b/drivers/base/regmap/regmap-kunit.c
@@ -126,7 +126,7 @@ static const struct regmap_test_param real_cache_types_list[] = {
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2003 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2004 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0 },
- { .cache = REGCACHE_RBTREE, .from_reg = 0, .fast_io = true },
+ { .cache = REGCACHE_MAPLE, .from_reg = 0, .fast_io = true },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2001 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2002 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2003 },
@@ -1499,6 +1499,48 @@ static void cache_present(struct kunit *test)
KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, param->from_reg + i));
}
+static void cache_write_zero(struct kunit *test)
+{
+ const struct regmap_test_param *param = test->param_value;
+ struct regmap *map;
+ struct regmap_config config;
+ struct regmap_ram_data *data;
+ unsigned int val;
+ int i;
+
+ config = test_regmap_config;
+
+ map = gen_regmap(test, &config, &data);
+ KUNIT_ASSERT_FALSE(test, IS_ERR(map));
+ if (IS_ERR(map))
+ return;
+
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ data->read[param->from_reg + i] = false;
+
+ /* No defaults so no registers cached. */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, param->from_reg + i));
+
+ /* We didn't trigger any reads */
+ for (i = 0; i < BLOCK_TEST_SIZE; i++)
+ KUNIT_ASSERT_FALSE(test, data->read[param->from_reg + i]);
+
+ /* Write a zero value */
+ KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 1, 0));
+
+ /* Read that zero value back */
+ KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 1, &val));
+ KUNIT_EXPECT_EQ(test, 0, val);
+
+ /* From the cache? */
+ KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, 1));
+
+ /* Try to throw it away */
+ KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, 1, 1));
+ KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, 1));
+}
+
/* Check that caching the window register works with sync */
static void cache_range_window_reg(struct kunit *test)
{
@@ -2012,6 +2054,7 @@ static struct kunit_case regmap_test_cases[] = {
KUNIT_CASE_PARAM(cache_drop_all_and_sync_no_defaults, sparse_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_drop_all_and_sync_has_defaults, sparse_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
+ KUNIT_CASE_PARAM(cache_write_zero, sparse_cache_types_gen_params),
KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_only_gen_params),
KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 4ded93687c1f..53131a7ede0a 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -745,6 +745,7 @@ struct regmap *__regmap_init(struct device *dev,
lock_key, lock_name);
}
map->lock_arg = map;
+ map->lock_key = lock_key;
}
/*
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 89f98be5c5b9..cf160dd2c27b 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -23,7 +23,7 @@ static ssize_t name##_show(struct device *dev, \
#define define_siblings_read_func(name, mask) \
static ssize_t name##_read(struct file *file, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
+ const struct bin_attribute *attr, char *buf, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
@@ -33,7 +33,7 @@ static ssize_t name##_read(struct file *file, struct kobject *kobj, \
} \
\
static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
+ const struct bin_attribute *attr, char *buf, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
@@ -62,50 +62,50 @@ define_id_show_func(ppin, "0x%llx");
static DEVICE_ATTR_ADMIN_RO(ppin);
define_siblings_read_func(thread_siblings, sibling_cpumask);
-static BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
define_siblings_read_func(core_cpus, sibling_cpumask);
-static BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
define_siblings_read_func(core_siblings, core_cpumask);
-static BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
#ifdef TOPOLOGY_CLUSTER_SYSFS
define_siblings_read_func(cluster_cpus, cluster_cpumask);
-static BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
#endif
#ifdef TOPOLOGY_DIE_SYSFS
define_siblings_read_func(die_cpus, die_cpumask);
-static BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
#endif
define_siblings_read_func(package_cpus, core_cpumask);
-static BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
#ifdef TOPOLOGY_BOOK_SYSFS
define_id_show_func(book_id, "%d");
static DEVICE_ATTR_RO(book_id);
define_siblings_read_func(book_siblings, book_cpumask);
-static BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
#endif
#ifdef TOPOLOGY_DRAWER_SYSFS
define_id_show_func(drawer_id, "%d");
static DEVICE_ATTR_RO(drawer_id);
define_siblings_read_func(drawer_siblings, drawer_cpumask);
-static BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
#endif
-static struct bin_attribute *bin_attrs[] = {
+static const struct bin_attribute *const bin_attrs[] = {
&bin_attr_core_cpus,
&bin_attr_core_cpus_list,
&bin_attr_thread_siblings,
@@ -163,7 +163,7 @@ static umode_t topology_is_visible(struct kobject *kobj,
static const struct attribute_group topology_attr_group = {
.attrs = default_attrs,
- .bin_attrs = bin_attrs,
+ .bin_attrs_new = bin_attrs,
.is_visible = topology_is_visible,
.name = "topology"
};
diff --git a/drivers/base/trace.h b/drivers/base/trace.h
index e52b6eae060d..3b83b13a57ff 100644
--- a/drivers/base/trace.h
+++ b/drivers/base/trace.h
@@ -24,18 +24,18 @@ DECLARE_EVENT_CLASS(devres,
__field(struct device *, dev)
__field(const char *, op)
__field(void *, node)
- __field(const char *, name)
+ __string(name, name)
__field(size_t, size)
),
TP_fast_assign(
__assign_str(devname);
__entry->op = op;
__entry->node = node;
- __entry->name = name;
+ __assign_str(name);
__entry->size = size;
),
TP_printk("%s %3s %p %s (%zu bytes)", __get_str(devname),
- __entry->op, __entry->node, __entry->name, __entry->size)
+ __entry->op, __entry->node, __get_str(name), __entry->size)
);
DEFINE_EVENT(devres, devres_log,
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ed209f4f2798..a97f2c40c640 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -130,7 +130,7 @@ config BLK_DEV_UBD_SYNC
kernel command line option. Alternatively, you can say Y here to
turn on synchronous operation by default for all block devices.
- If you're running a journalling file system (like reiserfs, for
+ If you're running a journalling file system (like xfs, for
example) in your virtual machine, you will want to say Y here. If
you care for the safety of the data in your virtual machine, Y is a
wise choice too. In all other cases (for example, if you're just
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 2fd1ed101748..292f127cae0a 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -231,8 +231,10 @@ static void brd_do_discard(struct brd_device *brd, sector_t sector, u32 size)
xa_lock(&brd->brd_pages);
while (size >= PAGE_SIZE && aligned_sector < rd_size * 2) {
page = __xa_erase(&brd->brd_pages, aligned_sector >> PAGE_SECTORS_SHIFT);
- if (page)
+ if (page) {
__free_page(page);
+ brd->brd_nr_pages--;
+ }
aligned_sector += PAGE_SECTORS;
size -= PAGE_SIZE;
}
@@ -316,8 +318,40 @@ __setup("ramdisk_size=", ramdisk_size);
* (should share code eventually).
*/
static LIST_HEAD(brd_devices);
+static DEFINE_MUTEX(brd_devices_mutex);
static struct dentry *brd_debugfs_dir;
+static struct brd_device *brd_find_or_alloc_device(int i)
+{
+ struct brd_device *brd;
+
+ mutex_lock(&brd_devices_mutex);
+ list_for_each_entry(brd, &brd_devices, brd_list) {
+ if (brd->brd_number == i) {
+ mutex_unlock(&brd_devices_mutex);
+ return ERR_PTR(-EEXIST);
+ }
+ }
+
+ brd = kzalloc(sizeof(*brd), GFP_KERNEL);
+ if (!brd) {
+ mutex_unlock(&brd_devices_mutex);
+ return ERR_PTR(-ENOMEM);
+ }
+ brd->brd_number = i;
+ list_add_tail(&brd->brd_list, &brd_devices);
+ mutex_unlock(&brd_devices_mutex);
+ return brd;
+}
+
+static void brd_free_device(struct brd_device *brd)
+{
+ mutex_lock(&brd_devices_mutex);
+ list_del(&brd->brd_list);
+ mutex_unlock(&brd_devices_mutex);
+ kfree(brd);
+}
+
static int brd_alloc(int i)
{
struct brd_device *brd;
@@ -340,14 +374,9 @@ static int brd_alloc(int i)
BLK_FEAT_NOWAIT,
};
- list_for_each_entry(brd, &brd_devices, brd_list)
- if (brd->brd_number == i)
- return -EEXIST;
- brd = kzalloc(sizeof(*brd), GFP_KERNEL);
- if (!brd)
- return -ENOMEM;
- brd->brd_number = i;
- list_add_tail(&brd->brd_list, &brd_devices);
+ brd = brd_find_or_alloc_device(i);
+ if (IS_ERR(brd))
+ return PTR_ERR(brd);
xa_init(&brd->brd_pages);
@@ -378,8 +407,7 @@ static int brd_alloc(int i)
out_cleanup_disk:
put_disk(disk);
out_free_dev:
- list_del(&brd->brd_list);
- kfree(brd);
+ brd_free_device(brd);
return err;
}
@@ -398,8 +426,7 @@ static void brd_cleanup(void)
del_gendisk(brd->brd_disk);
put_disk(brd->brd_disk);
brd_free_pages(brd);
- list_del(&brd->brd_list);
- kfree(brd);
+ brd_free_device(brd);
}
}
@@ -426,16 +453,6 @@ static int __init brd_init(void)
{
int err, i;
- brd_check_and_reset_par();
-
- brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);
-
- for (i = 0; i < rd_nr; i++) {
- err = brd_alloc(i);
- if (err)
- goto out_free;
- }
-
/*
* brd module now has a feature to instantiate underlying device
* structure on-demand, provided that there is an access dev node.
@@ -451,11 +468,18 @@ static int __init brd_init(void)
* dynamically.
*/
+ brd_check_and_reset_par();
+
+ brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);
+
if (__register_blkdev(RAMDISK_MAJOR, "ramdisk", brd_probe)) {
err = -EIO;
goto out_free;
}
+ for (i = 0; i < rd_nr; i++)
+ brd_alloc(i);
+
pr_info("brd: module loaded\n");
return 0;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 78a7bb28defe..8f6761c27c68 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -173,7 +173,7 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file)
static bool lo_bdev_can_use_dio(struct loop_device *lo,
struct block_device *backing_bdev)
{
- unsigned short sb_bsize = bdev_logical_block_size(backing_bdev);
+ unsigned int sb_bsize = bdev_logical_block_size(backing_bdev);
if (queue_logical_block_size(lo->lo_queue) < sb_bsize)
return false;
@@ -770,12 +770,11 @@ static void loop_sysfs_exit(struct loop_device *lo)
&loop_attribute_group);
}
-static void loop_config_discard(struct loop_device *lo,
- struct queue_limits *lim)
+static void loop_get_discard_config(struct loop_device *lo,
+ u32 *granularity, u32 *max_discard_sectors)
{
struct file *file = lo->lo_backing_file;
struct inode *inode = file->f_mapping->host;
- u32 granularity = 0, max_discard_sectors = 0;
struct kstatfs sbuf;
/*
@@ -786,27 +785,19 @@ static void loop_config_discard(struct loop_device *lo,
* file-backed loop devices: discarded regions read back as zero.
*/
if (S_ISBLK(inode->i_mode)) {
- struct request_queue *backingq = bdev_get_queue(I_BDEV(inode));
+ struct block_device *bdev = I_BDEV(inode);
- max_discard_sectors = backingq->limits.max_write_zeroes_sectors;
- granularity = bdev_discard_granularity(I_BDEV(inode)) ?:
- queue_physical_block_size(backingq);
+ *max_discard_sectors = bdev_write_zeroes_sectors(bdev);
+ *granularity = bdev_discard_granularity(bdev);
/*
* We use punch hole to reclaim the free space used by the
* image a.k.a. discard.
*/
} else if (file->f_op->fallocate && !vfs_statfs(&file->f_path, &sbuf)) {
- max_discard_sectors = UINT_MAX >> 9;
- granularity = sbuf.f_bsize;
+ *max_discard_sectors = UINT_MAX >> 9;
+ *granularity = sbuf.f_bsize;
}
-
- lim->max_hw_discard_sectors = max_discard_sectors;
- lim->max_write_zeroes_sectors = max_discard_sectors;
- if (max_discard_sectors)
- lim->discard_granularity = granularity;
- else
- lim->discard_granularity = 0;
}
struct loop_worker {
@@ -977,7 +968,7 @@ loop_set_status_from_info(struct loop_device *lo,
return 0;
}
-static unsigned short loop_default_blocksize(struct loop_device *lo,
+static unsigned int loop_default_blocksize(struct loop_device *lo,
struct block_device *backing_bdev)
{
/* In case of direct I/O, match underlying block size */
@@ -986,12 +977,13 @@ static unsigned short loop_default_blocksize(struct loop_device *lo,
return SECTOR_SIZE;
}
-static int loop_reconfigure_limits(struct loop_device *lo, unsigned short bsize)
+static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
{
struct file *file = lo->lo_backing_file;
struct inode *inode = file->f_mapping->host;
struct block_device *backing_bdev = NULL;
struct queue_limits lim;
+ u32 granularity = 0, max_discard_sectors = 0;
if (S_ISBLK(inode->i_mode))
backing_bdev = I_BDEV(inode);
@@ -1001,6 +993,8 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned short bsize)
if (!bsize)
bsize = loop_default_blocksize(lo, backing_bdev);
+ loop_get_discard_config(lo, &granularity, &max_discard_sectors);
+
lim = queue_limits_start_update(lo->lo_queue);
lim.logical_block_size = bsize;
lim.physical_block_size = bsize;
@@ -1010,7 +1004,12 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned short bsize)
lim.features |= BLK_FEAT_WRITE_CACHE;
if (backing_bdev && !bdev_nonrot(backing_bdev))
lim.features |= BLK_FEAT_ROTATIONAL;
- loop_config_discard(lo, &lim);
+ lim.max_hw_discard_sectors = max_discard_sectors;
+ lim.max_write_zeroes_sectors = max_discard_sectors;
+ if (max_discard_sectors)
+ lim.discard_granularity = granularity;
+ else
+ lim.discard_granularity = 0;
return queue_limits_commit_update(lo->lo_queue, &lim);
}
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 223faa9d5ffd..43701b7b10a7 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -2701,7 +2701,12 @@ static int mtip_hw_init(struct driver_data *dd)
int rv;
unsigned long timeout, timetaken;
- dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR];
+ dd->mmio = pcim_iomap_region(dd->pdev, MTIP_ABAR, MTIP_DRV_NAME);
+ if (IS_ERR(dd->mmio)) {
+ dev_err(&dd->pdev->dev, "Unable to request / ioremap PCI region\n");
+ return PTR_ERR(dd->mmio);
+ }
+
mtip_detect_product(dd);
if (dd->product_type == MTIP_PRODUCT_UNKNOWN) {
@@ -3710,13 +3715,6 @@ static int mtip_pci_probe(struct pci_dev *pdev,
goto iomap_err;
}
- /* Map BAR5 to memory. */
- rv = pcim_iomap_regions(pdev, 1 << MTIP_ABAR, MTIP_DRV_NAME);
- if (rv < 0) {
- dev_err(&pdev->dev, "Unable to map regions\n");
- goto iomap_err;
- }
-
rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (rv) {
dev_warn(&pdev->dev, "64-bit DMA enable failed\n");
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index 2f0431e42c49..3c3d8d200abb 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -1638,10 +1638,9 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_STS_OK;
}
-static void null_queue_rqs(struct request **rqlist)
+static void null_queue_rqs(struct rq_list *rqlist)
{
- struct request *requeue_list = NULL;
- struct request **requeue_lastp = &requeue_list;
+ struct rq_list requeue_list = {};
struct blk_mq_queue_data bd = { };
blk_status_t ret;
@@ -1651,8 +1650,8 @@ static void null_queue_rqs(struct request **rqlist)
bd.rq = rq;
ret = null_queue_rq(rq->mq_hctx, &bd);
if (ret != BLK_STS_OK)
- rq_list_add_tail(&requeue_lastp, rq);
- } while (!rq_list_empty(*rqlist));
+ rq_list_add_tail(&requeue_list, rq);
+ } while (!rq_list_empty(rqlist));
*rqlist = requeue_list;
}
diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c
index 9bc768b2ca56..0d5f9bf95229 100644
--- a/drivers/block/null_blk/zoned.c
+++ b/drivers/block/null_blk/zoned.c
@@ -166,7 +166,7 @@ int null_init_zoned_dev(struct nullb_device *dev,
lim->features |= BLK_FEAT_ZONED;
lim->chunk_sectors = dev->zone_size_sects;
- lim->max_zone_append_sectors = dev->zone_append_max_sectors;
+ lim->max_hw_zone_append_sectors = dev->zone_append_max_sectors;
lim->max_open_zones = dev->zone_max_open;
lim->max_active_zones = dev->zone_max_active;
return 0;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 9c8b19a22c2a..ac421dbeeb11 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -7284,6 +7284,7 @@ static ssize_t do_rbd_remove(const char *buf, size_t count)
*/
blk_mq_freeze_queue(rbd_dev->disk->queue);
blk_mark_disk_dead(rbd_dev->disk);
+ blk_mq_unfreeze_queue(rbd_dev->disk->queue);
}
del_gendisk(rbd_dev->disk);
diff --git a/drivers/block/rnull.rs b/drivers/block/rnull.rs
index b0227cf9ddd3..5de7223beb4d 100644
--- a/drivers/block/rnull.rs
+++ b/drivers/block/rnull.rs
@@ -32,7 +32,7 @@ module! {
}
struct NullBlkModule {
- _disk: Pin<Box<Mutex<GenDisk<NullBlkDevice>>>>,
+ _disk: Pin<KBox<Mutex<GenDisk<NullBlkDevice>>>>,
}
impl kernel::Module for NullBlkModule {
@@ -47,7 +47,7 @@ impl kernel::Module for NullBlkModule {
.rotational(false)
.build(format_args!("rnullb{}", 0), tagset)?;
- let disk = Box::pin_init(new_mutex!(disk, "nullb:disk"), flags::GFP_KERNEL)?;
+ let disk = KBox::pin_init(new_mutex!(disk, "nullb:disk"), flags::GFP_KERNEL)?;
Ok(Self { _disk: disk })
}
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 6ba2c1dd1d87..d4aed12dd436 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -60,7 +60,12 @@
| UBLK_F_UNPRIVILEGED_DEV \
| UBLK_F_CMD_IOCTL_ENCODE \
| UBLK_F_USER_COPY \
- | UBLK_F_ZONED)
+ | UBLK_F_ZONED \
+ | UBLK_F_USER_RECOVERY_FAIL_IO)
+
+#define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \
+ | UBLK_F_USER_RECOVERY_REISSUE \
+ | UBLK_F_USER_RECOVERY_FAIL_IO)
/* All UBLK_PARAM_TYPE_* should be included here */
#define UBLK_PARAM_TYPE_ALL \
@@ -143,6 +148,7 @@ struct ublk_queue {
bool force_abort;
bool timeout;
bool canceling;
+ bool fail_io; /* copy of dev->state == UBLK_S_DEV_FAIL_IO */
unsigned short nr_io_ready; /* how many ios setup */
spinlock_t cancel_lock;
struct ublk_device *dev;
@@ -179,8 +185,7 @@ struct ublk_device {
unsigned int nr_queues_ready;
unsigned int nr_privileged_daemon;
- struct work_struct quiesce_work;
- struct work_struct stop_work;
+ struct work_struct nosrv_work;
};
/* header of ublk_params */
@@ -664,30 +669,69 @@ static inline char *ublk_queue_cmd_buf(struct ublk_device *ub, int q_id)
return ublk_get_queue(ub, q_id)->io_cmd_buf;
}
+static inline int __ublk_queue_cmd_buf_size(int depth)
+{
+ return round_up(depth * sizeof(struct ublksrv_io_desc), PAGE_SIZE);
+}
+
static inline int ublk_queue_cmd_buf_size(struct ublk_device *ub, int q_id)
{
struct ublk_queue *ubq = ublk_get_queue(ub, q_id);
- return round_up(ubq->q_depth * sizeof(struct ublksrv_io_desc),
- PAGE_SIZE);
+ return __ublk_queue_cmd_buf_size(ubq->q_depth);
+}
+
+static int ublk_max_cmd_buf_size(void)
+{
+ return __ublk_queue_cmd_buf_size(UBLK_MAX_QUEUE_DEPTH);
+}
+
+/*
+ * Should I/O outstanding to the ublk server when it exits be reissued?
+ * If not, outstanding I/O will get errors.
+ */
+static inline bool ublk_nosrv_should_reissue_outstanding(struct ublk_device *ub)
+{
+ return (ub->dev_info.flags & UBLK_F_USER_RECOVERY) &&
+ (ub->dev_info.flags & UBLK_F_USER_RECOVERY_REISSUE);
+}
+
+/*
+ * Should I/O issued while there is no ublk server queue? If not, I/O
+ * issued while there is no ublk server will get errors.
+ */
+static inline bool ublk_nosrv_dev_should_queue_io(struct ublk_device *ub)
+{
+ return (ub->dev_info.flags & UBLK_F_USER_RECOVERY) &&
+ !(ub->dev_info.flags & UBLK_F_USER_RECOVERY_FAIL_IO);
}
-static inline bool ublk_queue_can_use_recovery_reissue(
- struct ublk_queue *ubq)
+/*
+ * Same as ublk_nosrv_dev_should_queue_io, but uses a queue-local copy
+ * of the device flags for smaller cache footprint - better for fast
+ * paths.
+ */
+static inline bool ublk_nosrv_should_queue_io(struct ublk_queue *ubq)
{
return (ubq->flags & UBLK_F_USER_RECOVERY) &&
- (ubq->flags & UBLK_F_USER_RECOVERY_REISSUE);
+ !(ubq->flags & UBLK_F_USER_RECOVERY_FAIL_IO);
}
-static inline bool ublk_queue_can_use_recovery(
- struct ublk_queue *ubq)
+/*
+ * Should ublk devices be stopped (i.e. no recovery possible) when the
+ * ublk server exits? If not, devices can be used again by a future
+ * incarnation of a ublk server via the start_recovery/end_recovery
+ * commands.
+ */
+static inline bool ublk_nosrv_should_stop_dev(struct ublk_device *ub)
{
- return ubq->flags & UBLK_F_USER_RECOVERY;
+ return !(ub->dev_info.flags & UBLK_F_USER_RECOVERY);
}
-static inline bool ublk_can_use_recovery(struct ublk_device *ub)
+static inline bool ublk_dev_in_recoverable_state(struct ublk_device *ub)
{
- return ub->dev_info.flags & UBLK_F_USER_RECOVERY;
+ return ub->dev_info.state == UBLK_S_DEV_QUIESCED ||
+ ub->dev_info.state == UBLK_S_DEV_FAIL_IO;
}
static void ublk_free_disk(struct gendisk *disk)
@@ -1063,7 +1107,7 @@ static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io,
{
WARN_ON_ONCE(io->flags & UBLK_IO_FLAG_ACTIVE);
- if (ublk_queue_can_use_recovery_reissue(ubq))
+ if (ublk_nosrv_should_reissue_outstanding(ubq->dev))
blk_mq_requeue_request(req, false);
else
ublk_put_req_ref(ubq, req);
@@ -1091,7 +1135,7 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
struct request *rq)
{
/* We cannot process this rq so just requeue it. */
- if (ublk_queue_can_use_recovery(ubq))
+ if (ublk_nosrv_dev_should_queue_io(ubq->dev))
blk_mq_requeue_request(rq, false);
else
blk_mq_end_request(rq, BLK_STS_IOERR);
@@ -1236,10 +1280,7 @@ static enum blk_eh_timer_return ublk_timeout(struct request *rq)
struct ublk_device *ub = ubq->dev;
if (ublk_abort_requests(ub, ubq)) {
- if (ublk_can_use_recovery(ub))
- schedule_work(&ub->quiesce_work);
- else
- schedule_work(&ub->stop_work);
+ schedule_work(&ub->nosrv_work);
}
return BLK_EH_DONE;
}
@@ -1254,6 +1295,10 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx,
struct request *rq = bd->rq;
blk_status_t res;
+ if (unlikely(ubq->fail_io)) {
+ return BLK_STS_TARGET;
+ }
+
/* fill iod to slot in io cmd buffer */
res = ublk_setup_iod(ubq, rq);
if (unlikely(res != BLK_STS_OK))
@@ -1268,7 +1313,7 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx,
* Note: force_abort is guaranteed to be seen because it is set
* before request queue is unqiuesced.
*/
- if (ublk_queue_can_use_recovery(ubq) && unlikely(ubq->force_abort))
+ if (ublk_nosrv_should_queue_io(ubq) && unlikely(ubq->force_abort))
return BLK_STS_IOERR;
if (unlikely(ubq->canceling)) {
@@ -1322,7 +1367,7 @@ static int ublk_ch_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct ublk_device *ub = filp->private_data;
size_t sz = vma->vm_end - vma->vm_start;
- unsigned max_sz = UBLK_MAX_QUEUE_DEPTH * sizeof(struct ublksrv_io_desc);
+ unsigned max_sz = ublk_max_cmd_buf_size();
unsigned long pfn, end, phys_off = vma->vm_pgoff << PAGE_SHIFT;
int q_id, ret = 0;
@@ -1489,10 +1534,7 @@ static void ublk_uring_cmd_cancel_fn(struct io_uring_cmd *cmd,
ublk_cancel_cmd(ubq, io, issue_flags);
if (need_schedule) {
- if (ublk_can_use_recovery(ub))
- schedule_work(&ub->quiesce_work);
- else
- schedule_work(&ub->stop_work);
+ schedule_work(&ub->nosrv_work);
}
}
@@ -1555,20 +1597,6 @@ static void __ublk_quiesce_dev(struct ublk_device *ub)
ub->dev_info.state = UBLK_S_DEV_QUIESCED;
}
-static void ublk_quiesce_work_fn(struct work_struct *work)
-{
- struct ublk_device *ub =
- container_of(work, struct ublk_device, quiesce_work);
-
- mutex_lock(&ub->mutex);
- if (ub->dev_info.state != UBLK_S_DEV_LIVE)
- goto unlock;
- __ublk_quiesce_dev(ub);
- unlock:
- mutex_unlock(&ub->mutex);
- ublk_cancel_dev(ub);
-}
-
static void ublk_unquiesce_dev(struct ublk_device *ub)
{
int i;
@@ -1597,7 +1625,7 @@ static void ublk_stop_dev(struct ublk_device *ub)
mutex_lock(&ub->mutex);
if (ub->dev_info.state == UBLK_S_DEV_DEAD)
goto unlock;
- if (ublk_can_use_recovery(ub)) {
+ if (ublk_nosrv_dev_should_queue_io(ub)) {
if (ub->dev_info.state == UBLK_S_DEV_LIVE)
__ublk_quiesce_dev(ub);
ublk_unquiesce_dev(ub);
@@ -1617,6 +1645,37 @@ static void ublk_stop_dev(struct ublk_device *ub)
ublk_cancel_dev(ub);
}
+static void ublk_nosrv_work(struct work_struct *work)
+{
+ struct ublk_device *ub =
+ container_of(work, struct ublk_device, nosrv_work);
+ int i;
+
+ if (ublk_nosrv_should_stop_dev(ub)) {
+ ublk_stop_dev(ub);
+ return;
+ }
+
+ mutex_lock(&ub->mutex);
+ if (ub->dev_info.state != UBLK_S_DEV_LIVE)
+ goto unlock;
+
+ if (ublk_nosrv_dev_should_queue_io(ub)) {
+ __ublk_quiesce_dev(ub);
+ } else {
+ blk_mq_quiesce_queue(ub->ub_disk->queue);
+ ub->dev_info.state = UBLK_S_DEV_FAIL_IO;
+ for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
+ ublk_get_queue(ub, i)->fail_io = true;
+ }
+ blk_mq_unquiesce_queue(ub->ub_disk->queue);
+ }
+
+ unlock:
+ mutex_unlock(&ub->mutex);
+ ublk_cancel_dev(ub);
+}
+
/* device can only be started after all IOs are ready */
static void ublk_mark_io_ready(struct ublk_device *ub, struct ublk_queue *ubq)
{
@@ -2130,14 +2189,6 @@ static int ublk_add_chdev(struct ublk_device *ub)
return ret;
}
-static void ublk_stop_work_fn(struct work_struct *work)
-{
- struct ublk_device *ub =
- container_of(work, struct ublk_device, stop_work);
-
- ublk_stop_dev(ub);
-}
-
/* align max io buffer size with PAGE_SIZE */
static void ublk_align_max_io_size(struct ublk_device *ub)
{
@@ -2162,8 +2213,7 @@ static int ublk_add_tag_set(struct ublk_device *ub)
static void ublk_remove(struct ublk_device *ub)
{
ublk_stop_dev(ub);
- cancel_work_sync(&ub->stop_work);
- cancel_work_sync(&ub->quiesce_work);
+ cancel_work_sync(&ub->nosrv_work);
cdev_device_del(&ub->cdev, &ub->cdev_dev);
ublk_put_device(ub);
ublks_added--;
@@ -2229,7 +2279,7 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
lim.features |= BLK_FEAT_ZONED;
lim.max_active_zones = p->max_active_zones;
lim.max_open_zones = p->max_open_zones;
- lim.max_zone_append_sectors = p->max_zone_append_sectors;
+ lim.max_hw_zone_append_sectors = p->max_zone_append_sectors;
}
if (ub->params.basic.attrs & UBLK_ATTR_VOLATILE_CACHE) {
@@ -2372,6 +2422,19 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
else if (!(info.flags & UBLK_F_UNPRIVILEGED_DEV))
return -EPERM;
+ /* forbid nonsense combinations of recovery flags */
+ switch (info.flags & UBLK_F_ALL_RECOVERY_FLAGS) {
+ case 0:
+ case UBLK_F_USER_RECOVERY:
+ case (UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_REISSUE):
+ case (UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_FAIL_IO):
+ break;
+ default:
+ pr_warn("%s: invalid recovery flags %llx\n", __func__,
+ info.flags & UBLK_F_ALL_RECOVERY_FLAGS);
+ return -EINVAL;
+ }
+
/*
* unprivileged device can't be trusted, but RECOVERY and
* RECOVERY_REISSUE still may hang error handling, so can't
@@ -2424,8 +2487,7 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
goto out_unlock;
mutex_init(&ub->mutex);
spin_lock_init(&ub->lock);
- INIT_WORK(&ub->quiesce_work, ublk_quiesce_work_fn);
- INIT_WORK(&ub->stop_work, ublk_stop_work_fn);
+ INIT_WORK(&ub->nosrv_work, ublk_nosrv_work);
ret = ublk_alloc_dev_number(ub, header->dev_id);
if (ret < 0)
@@ -2560,9 +2622,7 @@ static inline void ublk_ctrl_cmd_dump(struct io_uring_cmd *cmd)
static int ublk_ctrl_stop_dev(struct ublk_device *ub)
{
ublk_stop_dev(ub);
- cancel_work_sync(&ub->stop_work);
- cancel_work_sync(&ub->quiesce_work);
-
+ cancel_work_sync(&ub->nosrv_work);
return 0;
}
@@ -2699,7 +2759,7 @@ static int ublk_ctrl_start_recovery(struct ublk_device *ub,
int i;
mutex_lock(&ub->mutex);
- if (!ublk_can_use_recovery(ub))
+ if (ublk_nosrv_should_stop_dev(ub))
goto out_unlock;
if (!ub->nr_queues_ready)
goto out_unlock;
@@ -2710,14 +2770,18 @@ static int ublk_ctrl_start_recovery(struct ublk_device *ub,
* and related io_uring ctx is freed so file struct of /dev/ublkcX is
* released.
*
+ * and one of the following holds
+ *
* (2) UBLK_S_DEV_QUIESCED is set, which means the quiesce_work:
* (a)has quiesced request queue
* (b)has requeued every inflight rqs whose io_flags is ACTIVE
* (c)has requeued/aborted every inflight rqs whose io_flags is NOT ACTIVE
* (d)has completed/camceled all ioucmds owned by ther dying process
+ *
+ * (3) UBLK_S_DEV_FAIL_IO is set, which means the queue is not
+ * quiesced, but all I/O is being immediately errored
*/
- if (test_bit(UB_STATE_OPEN, &ub->state) ||
- ub->dev_info.state != UBLK_S_DEV_QUIESCED) {
+ if (test_bit(UB_STATE_OPEN, &ub->state) || !ublk_dev_in_recoverable_state(ub)) {
ret = -EBUSY;
goto out_unlock;
}
@@ -2741,6 +2805,7 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe);
int ublksrv_pid = (int)header->data[0];
int ret = -EINVAL;
+ int i;
pr_devel("%s: Waiting for new ubq_daemons(nr: %d) are ready, dev id %d...\n",
__func__, ub->dev_info.nr_hw_queues, header->dev_id);
@@ -2752,21 +2817,32 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
__func__, ub->dev_info.nr_hw_queues, header->dev_id);
mutex_lock(&ub->mutex);
- if (!ublk_can_use_recovery(ub))
+ if (ublk_nosrv_should_stop_dev(ub))
goto out_unlock;
- if (ub->dev_info.state != UBLK_S_DEV_QUIESCED) {
+ if (!ublk_dev_in_recoverable_state(ub)) {
ret = -EBUSY;
goto out_unlock;
}
ub->dev_info.ublksrv_pid = ublksrv_pid;
pr_devel("%s: new ublksrv_pid %d, dev id %d\n",
__func__, ublksrv_pid, header->dev_id);
- blk_mq_unquiesce_queue(ub->ub_disk->queue);
- pr_devel("%s: queue unquiesced, dev id %d.\n",
- __func__, header->dev_id);
- blk_mq_kick_requeue_list(ub->ub_disk->queue);
- ub->dev_info.state = UBLK_S_DEV_LIVE;
+
+ if (ublk_nosrv_dev_should_queue_io(ub)) {
+ ub->dev_info.state = UBLK_S_DEV_LIVE;
+ blk_mq_unquiesce_queue(ub->ub_disk->queue);
+ pr_devel("%s: queue unquiesced, dev id %d.\n",
+ __func__, header->dev_id);
+ blk_mq_kick_requeue_list(ub->ub_disk->queue);
+ } else {
+ blk_mq_quiesce_queue(ub->ub_disk->queue);
+ ub->dev_info.state = UBLK_S_DEV_LIVE;
+ for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
+ ublk_get_queue(ub, i)->fail_io = false;
+ }
+ blk_mq_unquiesce_queue(ub->ub_disk->queue);
+ }
+
ret = 0;
out_unlock:
mutex_unlock(&ub->mutex);
@@ -2965,7 +3041,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
ret = ublk_ctrl_end_recovery(ub, cmd);
break;
default:
- ret = -ENOTSUPP;
+ ret = -EOPNOTSUPP;
break;
}
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 194417abc105..c0cdba71f436 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -471,18 +471,18 @@ static bool virtblk_prep_rq_batch(struct request *req)
return virtblk_prep_rq(req->mq_hctx, vblk, req, vbr) == BLK_STS_OK;
}
-static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
- struct request **rqlist)
+static void virtblk_add_req_batch(struct virtio_blk_vq *vq,
+ struct rq_list *rqlist)
{
+ struct request *req;
unsigned long flags;
- int err;
bool kick;
spin_lock_irqsave(&vq->lock, flags);
- while (!rq_list_empty(*rqlist)) {
- struct request *req = rq_list_pop(rqlist);
+ while ((req = rq_list_pop(rqlist))) {
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
+ int err;
err = virtblk_add_req(vq->vq, vbr);
if (err) {
@@ -495,37 +495,32 @@ static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
kick = virtqueue_kick_prepare(vq->vq);
spin_unlock_irqrestore(&vq->lock, flags);
- return kick;
+ if (kick)
+ virtqueue_notify(vq->vq);
}
-static void virtio_queue_rqs(struct request **rqlist)
+static void virtio_queue_rqs(struct rq_list *rqlist)
{
- struct request *req, *next, *prev = NULL;
- struct request *requeue_list = NULL;
-
- rq_list_for_each_safe(rqlist, req, next) {
- struct virtio_blk_vq *vq = get_virtio_blk_vq(req->mq_hctx);
- bool kick;
-
- if (!virtblk_prep_rq_batch(req)) {
- rq_list_move(rqlist, &requeue_list, req, prev);
- req = prev;
- if (!req)
- continue;
- }
+ struct rq_list submit_list = { };
+ struct rq_list requeue_list = { };
+ struct virtio_blk_vq *vq = NULL;
+ struct request *req;
- if (!next || req->mq_hctx != next->mq_hctx) {
- req->rq_next = NULL;
- kick = virtblk_add_req_batch(vq, rqlist);
- if (kick)
- virtqueue_notify(vq->vq);
+ while ((req = rq_list_pop(rqlist))) {
+ struct virtio_blk_vq *this_vq = get_virtio_blk_vq(req->mq_hctx);
- *rqlist = next;
- prev = NULL;
- } else
- prev = req;
+ if (vq && vq != this_vq)
+ virtblk_add_req_batch(vq, &submit_list);
+ vq = this_vq;
+
+ if (virtblk_prep_rq_batch(req))
+ rq_list_add_tail(&submit_list, req);
+ else
+ rq_list_add_tail(&requeue_list, req);
}
+ if (vq)
+ virtblk_add_req_batch(vq, &submit_list);
*rqlist = requeue_list;
}
@@ -784,7 +779,7 @@ static int virtblk_read_zoned_limits(struct virtio_blk *vblk,
wg, v);
return -ENODEV;
}
- lim->max_zone_append_sectors = v;
+ lim->max_hw_zone_append_sectors = v;
dev_dbg(&vdev->dev, "max append sectors = %u\n", v);
return 0;
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index 6aea609b795c..402b7b175863 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig
@@ -94,6 +94,7 @@ endchoice
config ZRAM_DEF_COMP
string
+ depends on ZRAM
default "lzo-rle" if ZRAM_DEF_COMP_LZORLE
default "lzo" if ZRAM_DEF_COMP_LZO
default "lz4" if ZRAM_DEF_COMP_LZ4
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index ad9c9bc3ccfc..3dee026988dc 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -178,11 +178,105 @@ static inline u32 zram_get_priority(struct zram *zram, u32 index)
static void zram_accessed(struct zram *zram, u32 index)
{
zram_clear_flag(zram, index, ZRAM_IDLE);
+ zram_clear_flag(zram, index, ZRAM_PP_SLOT);
#ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME
zram->table[index].ac_time = ktime_get_boottime();
#endif
}
+#if defined CONFIG_ZRAM_WRITEBACK || defined CONFIG_ZRAM_MULTI_COMP
+struct zram_pp_slot {
+ unsigned long index;
+ struct list_head entry;
+};
+
+/*
+ * A post-processing bucket is, essentially, a size class, this defines
+ * the range (in bytes) of pp-slots sizes in particular bucket.
+ */
+#define PP_BUCKET_SIZE_RANGE 64
+#define NUM_PP_BUCKETS ((PAGE_SIZE / PP_BUCKET_SIZE_RANGE) + 1)
+
+struct zram_pp_ctl {
+ struct list_head pp_buckets[NUM_PP_BUCKETS];
+};
+
+static struct zram_pp_ctl *init_pp_ctl(void)
+{
+ struct zram_pp_ctl *ctl;
+ u32 idx;
+
+ ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
+ if (!ctl)
+ return NULL;
+
+ for (idx = 0; idx < NUM_PP_BUCKETS; idx++)
+ INIT_LIST_HEAD(&ctl->pp_buckets[idx]);
+ return ctl;
+}
+
+static void release_pp_slot(struct zram *zram, struct zram_pp_slot *pps)
+{
+ list_del_init(&pps->entry);
+
+ zram_slot_lock(zram, pps->index);
+ zram_clear_flag(zram, pps->index, ZRAM_PP_SLOT);
+ zram_slot_unlock(zram, pps->index);
+
+ kfree(pps);
+}
+
+static void release_pp_ctl(struct zram *zram, struct zram_pp_ctl *ctl)
+{
+ u32 idx;
+
+ if (!ctl)
+ return;
+
+ for (idx = 0; idx < NUM_PP_BUCKETS; idx++) {
+ while (!list_empty(&ctl->pp_buckets[idx])) {
+ struct zram_pp_slot *pps;
+
+ pps = list_first_entry(&ctl->pp_buckets[idx],
+ struct zram_pp_slot,
+ entry);
+ release_pp_slot(zram, pps);
+ }
+ }
+
+ kfree(ctl);
+}
+
+static void place_pp_slot(struct zram *zram, struct zram_pp_ctl *ctl,
+ struct zram_pp_slot *pps)
+{
+ u32 idx;
+
+ idx = zram_get_obj_size(zram, pps->index) / PP_BUCKET_SIZE_RANGE;
+ list_add(&pps->entry, &ctl->pp_buckets[idx]);
+
+ zram_set_flag(zram, pps->index, ZRAM_PP_SLOT);
+}
+
+static struct zram_pp_slot *select_pp_slot(struct zram_pp_ctl *ctl)
+{
+ struct zram_pp_slot *pps = NULL;
+ s32 idx = NUM_PP_BUCKETS - 1;
+
+ /* The higher the bucket id the more optimal slot post-processing is */
+ while (idx >= 0) {
+ pps = list_first_entry_or_null(&ctl->pp_buckets[idx],
+ struct zram_pp_slot,
+ entry);
+ if (pps)
+ break;
+
+ idx--;
+ }
+ return pps;
+}
+#endif
+
static inline void update_used_max(struct zram *zram,
const unsigned long pages)
{
@@ -296,19 +390,28 @@ static void mark_idle(struct zram *zram, ktime_t cutoff)
for (index = 0; index < nr_pages; index++) {
/*
- * Do not mark ZRAM_UNDER_WB slot as ZRAM_IDLE to close race.
- * See the comment in writeback_store.
+ * Do not mark ZRAM_SAME slots as ZRAM_IDLE, because no
+ * post-processing (recompress, writeback) happens to the
+ * ZRAM_SAME slot.
+ *
+ * And ZRAM_WB slots simply cannot be ZRAM_IDLE.
*/
zram_slot_lock(zram, index);
- if (zram_allocated(zram, index) &&
- !zram_test_flag(zram, index, ZRAM_UNDER_WB)) {
+ if (!zram_allocated(zram, index) ||
+ zram_test_flag(zram, index, ZRAM_WB) ||
+ zram_test_flag(zram, index, ZRAM_SAME)) {
+ zram_slot_unlock(zram, index);
+ continue;
+ }
+
#ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME
- is_idle = !cutoff || ktime_after(cutoff,
- zram->table[index].ac_time);
+ is_idle = !cutoff ||
+ ktime_after(cutoff, zram->table[index].ac_time);
#endif
- if (is_idle)
- zram_set_flag(zram, index, ZRAM_IDLE);
- }
+ if (is_idle)
+ zram_set_flag(zram, index, ZRAM_IDLE);
+ else
+ zram_clear_flag(zram, index, ZRAM_IDLE);
zram_slot_unlock(zram, index);
}
}
@@ -587,11 +690,57 @@ static void read_from_bdev_async(struct zram *zram, struct page *page,
#define IDLE_WRITEBACK (1<<1)
#define INCOMPRESSIBLE_WRITEBACK (1<<2)
+static int scan_slots_for_writeback(struct zram *zram, u32 mode,
+ unsigned long nr_pages,
+ unsigned long index,
+ struct zram_pp_ctl *ctl)
+{
+ struct zram_pp_slot *pps = NULL;
+
+ for (; nr_pages != 0; index++, nr_pages--) {
+ if (!pps)
+ pps = kmalloc(sizeof(*pps), GFP_KERNEL);
+ if (!pps)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&pps->entry);
+
+ zram_slot_lock(zram, index);
+ if (!zram_allocated(zram, index))
+ goto next;
+
+ if (zram_test_flag(zram, index, ZRAM_WB) ||
+ zram_test_flag(zram, index, ZRAM_SAME))
+ goto next;
+
+ if (mode & IDLE_WRITEBACK &&
+ !zram_test_flag(zram, index, ZRAM_IDLE))
+ goto next;
+ if (mode & HUGE_WRITEBACK &&
+ !zram_test_flag(zram, index, ZRAM_HUGE))
+ goto next;
+ if (mode & INCOMPRESSIBLE_WRITEBACK &&
+ !zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE))
+ goto next;
+
+ pps->index = index;
+ place_pp_slot(zram, ctl, pps);
+ pps = NULL;
+next:
+ zram_slot_unlock(zram, index);
+ }
+
+ kfree(pps);
+ return 0;
+}
+
static ssize_t writeback_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct zram *zram = dev_to_zram(dev);
unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
+ struct zram_pp_ctl *ctl = NULL;
+ struct zram_pp_slot *pps;
unsigned long index = 0;
struct bio bio;
struct bio_vec bio_vec;
@@ -626,6 +775,12 @@ static ssize_t writeback_store(struct device *dev,
goto release_init_lock;
}
+ /* Do not permit concurrent post-processing actions. */
+ if (atomic_xchg(&zram->pp_in_progress, 1)) {
+ up_read(&zram->init_lock);
+ return -EAGAIN;
+ }
+
if (!zram->backing_dev) {
ret = -ENODEV;
goto release_init_lock;
@@ -637,7 +792,15 @@ static ssize_t writeback_store(struct device *dev,
goto release_init_lock;
}
- for (; nr_pages != 0; index++, nr_pages--) {
+ ctl = init_pp_ctl();
+ if (!ctl) {
+ ret = -ENOMEM;
+ goto release_init_lock;
+ }
+
+ scan_slots_for_writeback(zram, mode, nr_pages, index, ctl);
+
+ while ((pps = select_pp_slot(ctl))) {
spin_lock(&zram->wb_limit_lock);
if (zram->wb_limit_enable && !zram->bd_wb_limit) {
spin_unlock(&zram->wb_limit_lock);
@@ -654,38 +817,20 @@ static ssize_t writeback_store(struct device *dev,
}
}
+ index = pps->index;
zram_slot_lock(zram, index);
- if (!zram_allocated(zram, index))
- goto next;
-
- if (zram_test_flag(zram, index, ZRAM_WB) ||
- zram_test_flag(zram, index, ZRAM_SAME) ||
- zram_test_flag(zram, index, ZRAM_UNDER_WB))
- goto next;
-
- if (mode & IDLE_WRITEBACK &&
- !zram_test_flag(zram, index, ZRAM_IDLE))
- goto next;
- if (mode & HUGE_WRITEBACK &&
- !zram_test_flag(zram, index, ZRAM_HUGE))
- goto next;
- if (mode & INCOMPRESSIBLE_WRITEBACK &&
- !zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE))
- goto next;
-
/*
- * Clearing ZRAM_UNDER_WB is duty of caller.
- * IOW, zram_free_page never clear it.
+ * scan_slots() sets ZRAM_PP_SLOT and relases slot lock, so
+ * slots can change in the meantime. If slots are accessed or
+ * freed they lose ZRAM_PP_SLOT flag and hence we don't
+ * post-process them.
*/
- zram_set_flag(zram, index, ZRAM_UNDER_WB);
- /* Need for hugepage writeback racing */
- zram_set_flag(zram, index, ZRAM_IDLE);
+ if (!zram_test_flag(zram, index, ZRAM_PP_SLOT))
+ goto next;
zram_slot_unlock(zram, index);
+
if (zram_read_page(zram, page, index, NULL)) {
- zram_slot_lock(zram, index);
- zram_clear_flag(zram, index, ZRAM_UNDER_WB);
- zram_clear_flag(zram, index, ZRAM_IDLE);
- zram_slot_unlock(zram, index);
+ release_pp_slot(zram, pps);
continue;
}
@@ -700,10 +845,7 @@ static ssize_t writeback_store(struct device *dev,
*/
err = submit_bio_wait(&bio);
if (err) {
- zram_slot_lock(zram, index);
- zram_clear_flag(zram, index, ZRAM_UNDER_WB);
- zram_clear_flag(zram, index, ZRAM_IDLE);
- zram_slot_unlock(zram, index);
+ release_pp_slot(zram, pps);
/*
* BIO errors are not fatal, we continue and simply
* attempt to writeback the remaining objects (pages).
@@ -717,25 +859,19 @@ static ssize_t writeback_store(struct device *dev,
}
atomic64_inc(&zram->stats.bd_writes);
+ zram_slot_lock(zram, index);
/*
- * We released zram_slot_lock so need to check if the slot was
- * changed. If there is freeing for the slot, we can catch it
- * easily by zram_allocated.
- * A subtle case is the slot is freed/reallocated/marked as
- * ZRAM_IDLE again. To close the race, idle_store doesn't
- * mark ZRAM_IDLE once it found the slot was ZRAM_UNDER_WB.
- * Thus, we could close the race by checking ZRAM_IDLE bit.
+ * Same as above, we release slot lock during writeback so
+ * slot can change under us: slot_free() or slot_free() and
+ * reallocation (zram_write_page()). In both cases slot loses
+ * ZRAM_PP_SLOT flag. No concurrent post-processing can set
+ * ZRAM_PP_SLOT on such slots until current post-processing
+ * finishes.
*/
- zram_slot_lock(zram, index);
- if (!zram_allocated(zram, index) ||
- !zram_test_flag(zram, index, ZRAM_IDLE)) {
- zram_clear_flag(zram, index, ZRAM_UNDER_WB);
- zram_clear_flag(zram, index, ZRAM_IDLE);
+ if (!zram_test_flag(zram, index, ZRAM_PP_SLOT))
goto next;
- }
zram_free_page(zram, index);
- zram_clear_flag(zram, index, ZRAM_UNDER_WB);
zram_set_flag(zram, index, ZRAM_WB);
zram_set_element(zram, index, blk_idx);
blk_idx = 0;
@@ -746,12 +882,15 @@ static ssize_t writeback_store(struct device *dev,
spin_unlock(&zram->wb_limit_lock);
next:
zram_slot_unlock(zram, index);
+ release_pp_slot(zram, pps);
}
if (blk_idx)
free_block_bdev(zram, blk_idx);
__free_page(page);
release_init_lock:
+ release_pp_ctl(zram, ctl);
+ atomic_set(&zram->pp_in_progress, 0);
up_read(&zram->init_lock);
return ret;
@@ -1342,19 +1481,17 @@ static void zram_free_page(struct zram *zram, size_t index)
#ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME
zram->table[index].ac_time = 0;
#endif
- if (zram_test_flag(zram, index, ZRAM_IDLE))
- zram_clear_flag(zram, index, ZRAM_IDLE);
+
+ zram_clear_flag(zram, index, ZRAM_IDLE);
+ zram_clear_flag(zram, index, ZRAM_INCOMPRESSIBLE);
+ zram_clear_flag(zram, index, ZRAM_PP_SLOT);
+ zram_set_priority(zram, index, 0);
if (zram_test_flag(zram, index, ZRAM_HUGE)) {
zram_clear_flag(zram, index, ZRAM_HUGE);
atomic64_dec(&zram->stats.huge_pages);
}
- if (zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE))
- zram_clear_flag(zram, index, ZRAM_INCOMPRESSIBLE);
-
- zram_set_priority(zram, index, 0);
-
if (zram_test_flag(zram, index, ZRAM_WB)) {
zram_clear_flag(zram, index, ZRAM_WB);
free_block_bdev(zram, zram_get_element(zram, index));
@@ -1378,13 +1515,11 @@ static void zram_free_page(struct zram *zram, size_t index)
zs_free(zram->mem_pool, handle);
atomic64_sub(zram_get_obj_size(zram, index),
- &zram->stats.compr_data_size);
+ &zram->stats.compr_data_size);
out:
atomic64_dec(&zram->stats.pages_stored);
zram_set_handle(zram, index, 0);
zram_set_obj_size(zram, index, 0);
- WARN_ON_ONCE(zram->table[index].flags &
- ~(1UL << ZRAM_UNDER_WB));
}
/*
@@ -1648,6 +1783,52 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
}
#ifdef CONFIG_ZRAM_MULTI_COMP
+#define RECOMPRESS_IDLE (1 << 0)
+#define RECOMPRESS_HUGE (1 << 1)
+
+static int scan_slots_for_recompress(struct zram *zram, u32 mode,
+ struct zram_pp_ctl *ctl)
+{
+ unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
+ struct zram_pp_slot *pps = NULL;
+ unsigned long index;
+
+ for (index = 0; index < nr_pages; index++) {
+ if (!pps)
+ pps = kmalloc(sizeof(*pps), GFP_KERNEL);
+ if (!pps)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&pps->entry);
+
+ zram_slot_lock(zram, index);
+ if (!zram_allocated(zram, index))
+ goto next;
+
+ if (mode & RECOMPRESS_IDLE &&
+ !zram_test_flag(zram, index, ZRAM_IDLE))
+ goto next;
+
+ if (mode & RECOMPRESS_HUGE &&
+ !zram_test_flag(zram, index, ZRAM_HUGE))
+ goto next;
+
+ if (zram_test_flag(zram, index, ZRAM_WB) ||
+ zram_test_flag(zram, index, ZRAM_SAME) ||
+ zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE))
+ goto next;
+
+ pps->index = index;
+ place_pp_slot(zram, ctl, pps);
+ pps = NULL;
+next:
+ zram_slot_unlock(zram, index);
+ }
+
+ kfree(pps);
+ return 0;
+}
+
/*
* This function will decompress (unless it's ZRAM_HUGE) the page and then
* attempt to compress it using provided compression algorithm priority
@@ -1655,7 +1836,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
*
* Corresponding ZRAM slot should be locked.
*/
-static int zram_recompress(struct zram *zram, u32 index, struct page *page,
+static int recompress_slot(struct zram *zram, u32 index, struct page *page,
u64 *num_recomp_pages, u32 threshold, u32 prio,
u32 prio_max)
{
@@ -1685,6 +1866,13 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
if (ret)
return ret;
+ /*
+ * We touched this entry so mark it as non-IDLE. This makes sure that
+ * we don't preserve IDLE flag and don't incorrectly pick this entry
+ * for different post-processing type (e.g. writeback).
+ */
+ zram_clear_flag(zram, index, ZRAM_IDLE);
+
class_index_old = zs_lookup_class_index(zram->mem_pool, comp_len_old);
/*
* Iterate the secondary comp algorithms list (in order of priority)
@@ -1798,20 +1986,17 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
return 0;
}
-#define RECOMPRESS_IDLE (1 << 0)
-#define RECOMPRESS_HUGE (1 << 1)
-
static ssize_t recompress_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
u32 prio = ZRAM_SECONDARY_COMP, prio_max = ZRAM_MAX_COMPS;
struct zram *zram = dev_to_zram(dev);
- unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
char *args, *param, *val, *algo = NULL;
u64 num_recomp_pages = ULLONG_MAX;
+ struct zram_pp_ctl *ctl = NULL;
+ struct zram_pp_slot *pps;
u32 mode = 0, threshold = 0;
- unsigned long index;
struct page *page;
ssize_t ret;
@@ -1881,6 +2066,12 @@ static ssize_t recompress_store(struct device *dev,
goto release_init_lock;
}
+ /* Do not permit concurrent post-processing actions. */
+ if (atomic_xchg(&zram->pp_in_progress, 1)) {
+ up_read(&zram->init_lock);
+ return -EAGAIN;
+ }
+
if (algo) {
bool found = false;
@@ -1907,36 +2098,32 @@ static ssize_t recompress_store(struct device *dev,
goto release_init_lock;
}
+ ctl = init_pp_ctl();
+ if (!ctl) {
+ ret = -ENOMEM;
+ goto release_init_lock;
+ }
+
+ scan_slots_for_recompress(zram, mode, ctl);
+
ret = len;
- for (index = 0; index < nr_pages; index++) {
+ while ((pps = select_pp_slot(ctl))) {
int err = 0;
if (!num_recomp_pages)
break;
- zram_slot_lock(zram, index);
-
- if (!zram_allocated(zram, index))
- goto next;
-
- if (mode & RECOMPRESS_IDLE &&
- !zram_test_flag(zram, index, ZRAM_IDLE))
- goto next;
-
- if (mode & RECOMPRESS_HUGE &&
- !zram_test_flag(zram, index, ZRAM_HUGE))
- goto next;
-
- if (zram_test_flag(zram, index, ZRAM_WB) ||
- zram_test_flag(zram, index, ZRAM_UNDER_WB) ||
- zram_test_flag(zram, index, ZRAM_SAME) ||
- zram_test_flag(zram, index, ZRAM_INCOMPRESSIBLE))
+ zram_slot_lock(zram, pps->index);
+ if (!zram_test_flag(zram, pps->index, ZRAM_PP_SLOT))
goto next;
- err = zram_recompress(zram, index, page, &num_recomp_pages,
- threshold, prio, prio_max);
+ err = recompress_slot(zram, pps->index, page,
+ &num_recomp_pages, threshold,
+ prio, prio_max);
next:
- zram_slot_unlock(zram, index);
+ zram_slot_unlock(zram, pps->index);
+ release_pp_slot(zram, pps);
+
if (err) {
ret = err;
break;
@@ -1948,6 +2135,8 @@ next:
__free_page(page);
release_init_lock:
+ release_pp_ctl(zram, ctl);
+ atomic_set(&zram->pp_in_progress, 0);
up_read(&zram->init_lock);
return ret;
}
@@ -2105,7 +2294,7 @@ static void zram_destroy_comps(struct zram *zram)
{
u32 prio;
- for (prio = 0; prio < ZRAM_MAX_COMPS; prio++) {
+ for (prio = ZRAM_PRIMARY_COMP; prio < ZRAM_MAX_COMPS; prio++) {
struct zcomp *comp = zram->comps[prio];
zram->comps[prio] = NULL;
@@ -2144,6 +2333,7 @@ static void zram_reset_device(struct zram *zram)
zram->disksize = 0;
zram_destroy_comps(zram);
memset(&zram->stats, 0, sizeof(zram->stats));
+ atomic_set(&zram->pp_in_progress, 0);
reset_bdev(zram);
comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
@@ -2176,7 +2366,7 @@ static ssize_t disksize_store(struct device *dev,
goto out_unlock;
}
- for (prio = 0; prio < ZRAM_MAX_COMPS; prio++) {
+ for (prio = ZRAM_PRIMARY_COMP; prio < ZRAM_MAX_COMPS; prio++) {
if (!zram->comp_algs[prio])
continue;
@@ -2381,6 +2571,9 @@ static int zram_add(void)
zram->disk->fops = &zram_devops;
zram->disk->private_data = zram;
snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
+ atomic_set(&zram->pp_in_progress, 0);
+ zram_comp_params_reset(zram);
+ comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
/* Actual capacity set using sysfs (/sys/block/zram<id>/disksize */
set_capacity(zram->disk, 0);
@@ -2388,9 +2581,6 @@ static int zram_add(void)
if (ret)
goto out_cleanup_disk;
- zram_comp_params_reset(zram);
- comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
-
zram_debugfs_register(zram);
pr_info("Added device: %s\n", zram->disk->disk_name);
return device_id;
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index cfc8c059db63..134be414e210 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -47,7 +47,7 @@
enum zram_pageflags {
ZRAM_SAME = ZRAM_FLAG_SHIFT, /* Page consists the same element */
ZRAM_WB, /* page is stored on backing_device */
- ZRAM_UNDER_WB, /* page is under writeback */
+ ZRAM_PP_SLOT, /* Selected for post-processing */
ZRAM_HUGE, /* Incompressible page */
ZRAM_IDLE, /* not accessed page since last idle marking */
ZRAM_INCOMPRESSIBLE, /* none of the algorithms could compress it */
@@ -139,5 +139,6 @@ struct zram {
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
struct dentry *debugfs_dir;
#endif
+ atomic_t pp_in_progress;
};
#endif
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 18767b54df35..4ab32abf0f48 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -336,7 +336,7 @@ config BT_HCIBFUSB
config BT_HCIDTL1
tristate "HCI DTL1 (PC Card) driver"
- depends on PCMCIA
+ depends on PCMCIA && HAS_IOPORT
help
Bluetooth HCI DTL1 (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with
@@ -349,7 +349,7 @@ config BT_HCIDTL1
config BT_HCIBT3C
tristate "HCI BT3C (PC Card) driver"
- depends on PCMCIA
+ depends on PCMCIA && HAS_IOPORT
select FW_LOADER
help
Bluetooth HCI BT3C (PC Card) driver.
@@ -363,7 +363,7 @@ config BT_HCIBT3C
config BT_HCIBLUECARD
tristate "HCI BlueCard (PC Card) driver"
- depends on PCMCIA
+ depends on PCMCIA && HAS_IOPORT
help
Bluetooth HCI BlueCard (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c
index eef00467905e..a1153ada74d2 100644
--- a/drivers/bluetooth/btbcm.c
+++ b/drivers/bluetooth/btbcm.c
@@ -541,11 +541,10 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = {
static const char *btbcm_get_board_name(struct device *dev)
{
#ifdef CONFIG_OF
- struct device_node *root;
+ struct device_node *root __free(device_node) = of_find_node_by_path("/");
char *board_type;
const char *tmp;
- root = of_find_node_by_path("/");
if (!root)
return NULL;
@@ -555,7 +554,6 @@ static const char *btbcm_get_board_name(struct device *dev)
/* get rid of any '/' in the compatible string */
board_type = devm_kstrdup(dev, tmp, GFP_KERNEL);
strreplace(board_type, '/', '-');
- of_node_put(root);
return board_type;
#else
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 438b92967bc3..d496cf2c3411 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -1040,7 +1040,7 @@ static int btintel_download_firmware_payload(struct hci_dev *hdev,
* as needed.
*
* Send set of commands with 4 byte alignment from the
- * firmware data buffer as a single Data fragement.
+ * firmware data buffer as a single Data fragment.
*/
if (!(frag_len % 4)) {
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
@@ -1252,6 +1252,12 @@ static void btintel_reset_to_bootloader(struct hci_dev *hdev)
struct intel_reset params;
struct sk_buff *skb;
+ /* PCIe transport uses shared hardware reset mechanism for recovery
+ * which gets triggered in pcie *setup* function on error.
+ */
+ if (hdev->bus == HCI_PCI)
+ return;
+
/* Send Intel Reset command. This will result in
* re-enumeration of BT controller.
*
@@ -1267,6 +1273,7 @@ static void btintel_reset_to_bootloader(struct hci_dev *hdev)
* boot_param: Boot address
*
*/
+
params.reset_type = 0x01;
params.patch_enable = 0x01;
params.ddc_reload = 0x01;
@@ -1841,6 +1848,37 @@ static int btintel_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
return 0;
}
+static int btintel_boot_wait_d0(struct hci_dev *hdev, ktime_t calltime,
+ int msec)
+{
+ ktime_t delta, rettime;
+ unsigned long long duration;
+ int err;
+
+ bt_dev_info(hdev, "Waiting for device transition to d0");
+
+ err = btintel_wait_on_flag_timeout(hdev, INTEL_WAIT_FOR_D0,
+ TASK_INTERRUPTIBLE,
+ msecs_to_jiffies(msec));
+ if (err == -EINTR) {
+ bt_dev_err(hdev, "Device d0 move interrupted");
+ return -EINTR;
+ }
+
+ if (err) {
+ bt_dev_err(hdev, "Device d0 move timeout");
+ return -ETIMEDOUT;
+ }
+
+ rettime = ktime_get();
+ delta = ktime_sub(rettime, calltime);
+ duration = (unsigned long long)ktime_to_ns(delta) >> 10;
+
+ bt_dev_info(hdev, "Device moved to D0 in %llu usecs", duration);
+
+ return 0;
+}
+
static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
{
ktime_t calltime;
@@ -1849,6 +1887,7 @@ static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
calltime = ktime_get();
btintel_set_flag(hdev, INTEL_BOOTING);
+ btintel_set_flag(hdev, INTEL_WAIT_FOR_D0);
err = btintel_send_intel_reset(hdev, boot_addr);
if (err) {
@@ -1861,13 +1900,28 @@ static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
* is done by the operational firmware sending bootup notification.
*
* Booting into operational firmware should not take longer than
- * 1 second. However if that happens, then just fail the setup
+ * 5 second. However if that happens, then just fail the setup
* since something went wrong.
*/
- err = btintel_boot_wait(hdev, calltime, 1000);
- if (err == -ETIMEDOUT)
+ err = btintel_boot_wait(hdev, calltime, 5000);
+ if (err == -ETIMEDOUT) {
btintel_reset_to_bootloader(hdev);
+ goto exit_error;
+ }
+
+ if (hdev->bus == HCI_PCI) {
+ /* In case of PCIe, after receiving bootup event, driver performs
+ * D0 entry by writing 0 to sleep control register (check
+ * btintel_pcie_recv_event())
+ * Firmware acks with alive interrupt indicating host is full ready to
+ * perform BT operation. Lets wait here till INTEL_WAIT_FOR_D0
+ * bit is cleared.
+ */
+ calltime = ktime_get();
+ err = btintel_boot_wait_d0(hdev, calltime, 2000);
+ }
+exit_error:
return err;
}
@@ -2693,20 +2747,32 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
struct btintel_dsbr_cmd cmd;
struct sk_buff *skb;
+ u32 dsbr, cnvi;
u8 status;
- u32 dsbr;
- bool apply_dsbr;
int err;
- /* DSBR command needs to be sent for BlazarI + B0 step product after
- * downloading IML image.
+ cnvi = ver->cnvi_top & 0xfff;
+ /* DSBR command needs to be sent for,
+ * 1. BlazarI or BlazarIW + B0 step product in IML image.
+ * 2. Gale Peak2 or BlazarU in OP image.
*/
- apply_dsbr = (ver->img_type == BTINTEL_IMG_IML &&
- ((ver->cnvi_top & 0xfff) == BTINTEL_CNVI_BLAZARI) &&
- INTEL_CNVX_TOP_STEP(ver->cnvi_top) == 0x01);
- if (!apply_dsbr)
+ switch (cnvi) {
+ case BTINTEL_CNVI_BLAZARI:
+ case BTINTEL_CNVI_BLAZARIW:
+ if (ver->img_type == BTINTEL_IMG_IML &&
+ INTEL_CNVX_TOP_STEP(ver->cnvi_top) == 0x01)
+ break;
return 0;
+ case BTINTEL_CNVI_GAP:
+ case BTINTEL_CNVI_BLAZARU:
+ if (ver->img_type == BTINTEL_IMG_OP &&
+ hdev->bus == HCI_USB)
+ break;
+ return 0;
+ default:
+ return 0;
+ }
dsbr = 0;
err = btintel_uefi_get_dsbr(&dsbr);
@@ -2749,6 +2815,13 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
*/
boot_param = 0x00000000;
+ /* In case of PCIe, this function might get called multiple times with
+ * same hdev instance if there is any error on firmware download.
+ * Need to clear stale bits of previous firmware download attempt.
+ */
+ for (int i = 0; i < __INTEL_NUM_FLAGS; i++)
+ btintel_clear_flag(hdev, i);
+
btintel_set_flag(hdev, INTEL_BOOTLOADER);
err = btintel_prepare_fw_download_tlv(hdev, ver, &boot_param);
@@ -2835,7 +2908,7 @@ void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant)
case 0x12: /* ThP */
case 0x13: /* HrP */
case 0x14: /* CcP */
- /* All Intel new genration controllers support the Microsoft vendor
+ /* All Intel new generation controllers support the Microsoft vendor
* extension are using 0xFC1E for VsMsftOpCode.
*/
case 0x17:
@@ -3273,7 +3346,7 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name)
}
EXPORT_SYMBOL_GPL(btintel_configure_setup);
-static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
+int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
{
struct intel_tlv *tlv = (void *)&skb->data[5];
@@ -3288,13 +3361,12 @@ static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
case INTEL_TLV_TEST_EXCEPTION:
/* Generate devcoredump from exception */
if (!hci_devcd_init(hdev, skb->len)) {
- hci_devcd_append(hdev, skb);
+ hci_devcd_append(hdev, skb_clone(skb, GFP_ATOMIC));
hci_devcd_complete(hdev);
} else {
bt_dev_err(hdev, "Failed to generate devcoredump");
- kfree_skb(skb);
}
- return 0;
+ break;
default:
bt_dev_err(hdev, "Invalid exception type %02X", tlv->val[0]);
}
@@ -3302,6 +3374,7 @@ static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
recv_frame:
return hci_recv_frame(hdev, skb);
}
+EXPORT_SYMBOL_GPL(btintel_diagnostics);
int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{
@@ -3321,7 +3394,8 @@ int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
* indicating that the bootup completed.
*/
btintel_bootup(hdev, ptr, len);
- break;
+ kfree_skb(skb);
+ return 0;
case 0x06:
/* When the firmware loading completes the
* device sends out a vendor specific event
@@ -3329,7 +3403,8 @@ int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
* loading.
*/
btintel_secure_send_result(hdev, ptr, len);
- break;
+ kfree_skb(skb);
+ return 0;
}
}
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index aa70e4c27416..fa43eb137821 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -53,6 +53,9 @@ struct intel_tlv {
} __packed;
#define BTINTEL_CNVI_BLAZARI 0x900
+#define BTINTEL_CNVI_BLAZARIW 0x901
+#define BTINTEL_CNVI_GAP 0x910
+#define BTINTEL_CNVI_BLAZARU 0x930
#define BTINTEL_IMG_BOOTLOADER 0x01 /* Bootloader image */
#define BTINTEL_IMG_IML 0x02 /* Intermediate image */
@@ -178,6 +181,7 @@ enum {
INTEL_ROM_LEGACY,
INTEL_ROM_LEGACY_NO_WBS_SUPPORT,
INTEL_ACPI_RESET_ACTIVE,
+ INTEL_WAIT_FOR_D0,
__INTEL_NUM_FLAGS,
};
@@ -249,6 +253,7 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
int btintel_shutdown_combined(struct hci_dev *hdev);
void btintel_hw_error(struct hci_dev *hdev, u8 code);
void btintel_print_fseq_info(struct hci_dev *hdev);
+int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb);
#else
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
@@ -382,4 +387,9 @@ static inline void btintel_hw_error(struct hci_dev *hdev, u8 code)
static inline void btintel_print_fseq_info(struct hci_dev *hdev)
{
}
+
+static inline int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ return -EOPNOTSUPP;
+}
#endif
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 5252125b003f..2b79952f3628 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -48,6 +48,17 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
#define BTINTEL_PCIE_HCI_EVT_PKT 0x00000004
#define BTINTEL_PCIE_HCI_ISO_PKT 0x00000005
+/* Alive interrupt context */
+enum {
+ BTINTEL_PCIE_ROM,
+ BTINTEL_PCIE_FW_DL,
+ BTINTEL_PCIE_HCI_RESET,
+ BTINTEL_PCIE_INTEL_HCI_RESET1,
+ BTINTEL_PCIE_INTEL_HCI_RESET2,
+ BTINTEL_PCIE_D0,
+ BTINTEL_PCIE_D3
+};
+
static inline void ipc_print_ia_ring(struct hci_dev *hdev, struct ia *ia,
u16 queue_num)
{
@@ -64,24 +75,6 @@ static inline void ipc_print_urbd1(struct hci_dev *hdev, struct urbd1 *urbd1,
index, urbd1->frbd_tag, urbd1->status, urbd1->fixed);
}
-static int btintel_pcie_poll_bit(struct btintel_pcie_data *data, u32 offset,
- u32 bits, u32 mask, int timeout_us)
-{
- int t = 0;
- u32 reg;
-
- do {
- reg = btintel_pcie_rd_reg32(data, offset);
-
- if ((reg & mask) == (bits & mask))
- return t;
- udelay(POLL_INTERVAL_US);
- t += POLL_INTERVAL_US;
- } while (t < timeout_us);
-
- return -ETIMEDOUT;
-}
-
static struct btintel_pcie_data *btintel_pcie_get_data(struct msix_entry *entry)
{
u8 queue = entry->entry;
@@ -237,10 +230,47 @@ static void btintel_pcie_reset_ia(struct btintel_pcie_data *data)
memset(data->ia.cr_tia, 0, sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES);
}
-static void btintel_pcie_reset_bt(struct btintel_pcie_data *data)
+static int btintel_pcie_reset_bt(struct btintel_pcie_data *data)
{
- btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG,
- BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET);
+ u32 reg;
+ int retry = 3;
+
+ reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
+
+ reg &= ~(BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_ENA |
+ BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT |
+ BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT);
+ reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON;
+
+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
+
+ do {
+ reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
+ if (reg & BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_STS)
+ break;
+ usleep_range(10000, 12000);
+
+ } while (--retry > 0);
+ usleep_range(10000, 12000);
+
+ reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
+
+ reg &= ~(BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_ENA |
+ BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT |
+ BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT);
+ reg |= BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET;
+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
+ usleep_range(10000, 12000);
+
+ reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
+ bt_dev_dbg(data->hdev, "csr register after reset: 0x%8.8x", reg);
+
+ reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_BOOT_STAGE_REG);
+
+ /* If shared hardware reset is success then boot stage register shall be
+ * set to 0
+ */
+ return reg == 0 ? 0 : -ENODEV;
}
/* This function enables BT function by setting BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT bit in
@@ -252,6 +282,7 @@ static void btintel_pcie_reset_bt(struct btintel_pcie_data *data)
static int btintel_pcie_enable_bt(struct btintel_pcie_data *data)
{
int err;
+ u32 reg;
data->gp0_received = false;
@@ -267,22 +298,17 @@ static int btintel_pcie_enable_bt(struct btintel_pcie_data *data)
data->boot_stage_cache = 0x0;
/* Set MAC_INIT bit to start primary bootloader */
- btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
+ reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
+ reg &= ~(BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT |
+ BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON |
+ BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET);
+ reg |= (BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_ENA |
+ BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT);
- btintel_pcie_set_reg_bits(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG,
- BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT);
-
- /* Wait until MAC_ACCESS is granted */
- err = btintel_pcie_poll_bit(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG,
- BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS,
- BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS,
- BTINTEL_DEFAULT_MAC_ACCESS_TIMEOUT_US);
- if (err < 0)
- return -ENODEV;
+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG, reg);
/* MAC is ready. Enable BT FUNC */
btintel_pcie_set_reg_bits(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG,
- BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_ENA |
BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT);
btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_FUNC_CTRL_REG);
@@ -290,8 +316,9 @@ static int btintel_pcie_enable_bt(struct btintel_pcie_data *data)
/* wait for interrupt from the device after booting up to primary
* bootloader.
*/
+ data->alive_intr_ctxt = BTINTEL_PCIE_ROM;
err = wait_event_timeout(data->gp0_wait_q, data->gp0_received,
- msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT));
+ msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
if (!err)
return -ETIME;
@@ -302,12 +329,77 @@ static int btintel_pcie_enable_bt(struct btintel_pcie_data *data)
return 0;
}
+/* BIT(0) - ROM, BIT(1) - IML and BIT(3) - OP
+ * Sometimes during firmware image switching from ROM to IML or IML to OP image,
+ * the previous image bit is not cleared by firmware when alive interrupt is
+ * received. Driver needs to take care of these sticky bits when deciding the
+ * current image running on controller.
+ * Ex: 0x10 and 0x11 - both represents that controller is running IML
+ */
+static inline bool btintel_pcie_in_rom(struct btintel_pcie_data *data)
+{
+ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ROM &&
+ !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML) &&
+ !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW);
+}
+
+static inline bool btintel_pcie_in_op(struct btintel_pcie_data *data)
+{
+ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW;
+}
+
+static inline bool btintel_pcie_in_iml(struct btintel_pcie_data *data)
+{
+ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML &&
+ !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW);
+}
+
+static inline bool btintel_pcie_in_d3(struct btintel_pcie_data *data)
+{
+ return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY;
+}
+
+static inline bool btintel_pcie_in_d0(struct btintel_pcie_data *data)
+{
+ return !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY);
+}
+
+static void btintel_pcie_wr_sleep_cntrl(struct btintel_pcie_data *data,
+ u32 dxstate)
+{
+ bt_dev_dbg(data->hdev, "writing sleep_ctl_reg: 0x%8.8x", dxstate);
+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG, dxstate);
+}
+
+static inline char *btintel_pcie_alivectxt_state2str(u32 alive_intr_ctxt)
+{
+ switch (alive_intr_ctxt) {
+ case BTINTEL_PCIE_ROM:
+ return "rom";
+ case BTINTEL_PCIE_FW_DL:
+ return "fw_dl";
+ case BTINTEL_PCIE_D0:
+ return "d0";
+ case BTINTEL_PCIE_D3:
+ return "d3";
+ case BTINTEL_PCIE_HCI_RESET:
+ return "hci_reset";
+ case BTINTEL_PCIE_INTEL_HCI_RESET1:
+ return "intel_reset1";
+ case BTINTEL_PCIE_INTEL_HCI_RESET2:
+ return "intel_reset2";
+ default:
+ return "unknown";
+ }
+}
+
/* This function handles the MSI-X interrupt for gp0 cause (bit 0 in
* BTINTEL_PCIE_CSR_MSIX_HW_INT_CAUSES) which is sent for boot stage and image response.
*/
static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data)
{
- u32 reg;
+ bool submit_rx, signal_waitq;
+ u32 reg, old_ctxt;
/* This interrupt is for three different causes and it is not easy to
* know what causes the interrupt. So, it compares each register value
@@ -317,20 +409,87 @@ static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data)
if (reg != data->boot_stage_cache)
data->boot_stage_cache = reg;
+ bt_dev_dbg(data->hdev, "Alive context: %s old_boot_stage: 0x%8.8x new_boot_stage: 0x%8.8x",
+ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt),
+ data->boot_stage_cache, reg);
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_IMG_RESPONSE_REG);
if (reg != data->img_resp_cache)
data->img_resp_cache = reg;
data->gp0_received = true;
- /* If the boot stage is OP or IML, reset IA and start RX again */
- if (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW ||
- data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_IML) {
+ old_ctxt = data->alive_intr_ctxt;
+ submit_rx = false;
+ signal_waitq = false;
+
+ switch (data->alive_intr_ctxt) {
+ case BTINTEL_PCIE_ROM:
+ data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL;
+ signal_waitq = true;
+ break;
+ case BTINTEL_PCIE_FW_DL:
+ /* Error case is already handled. Ideally control shall not
+ * reach here
+ */
+ break;
+ case BTINTEL_PCIE_INTEL_HCI_RESET1:
+ if (btintel_pcie_in_op(data)) {
+ submit_rx = true;
+ break;
+ }
+
+ if (btintel_pcie_in_iml(data)) {
+ submit_rx = true;
+ data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL;
+ break;
+ }
+ break;
+ case BTINTEL_PCIE_INTEL_HCI_RESET2:
+ if (btintel_test_and_clear_flag(data->hdev, INTEL_WAIT_FOR_D0)) {
+ btintel_wake_up_flag(data->hdev, INTEL_WAIT_FOR_D0);
+ data->alive_intr_ctxt = BTINTEL_PCIE_D0;
+ }
+ break;
+ case BTINTEL_PCIE_D0:
+ if (btintel_pcie_in_d3(data)) {
+ data->alive_intr_ctxt = BTINTEL_PCIE_D3;
+ signal_waitq = true;
+ break;
+ }
+ break;
+ case BTINTEL_PCIE_D3:
+ if (btintel_pcie_in_d0(data)) {
+ data->alive_intr_ctxt = BTINTEL_PCIE_D0;
+ submit_rx = true;
+ signal_waitq = true;
+ break;
+ }
+ break;
+ case BTINTEL_PCIE_HCI_RESET:
+ data->alive_intr_ctxt = BTINTEL_PCIE_D0;
+ submit_rx = true;
+ signal_waitq = true;
+ break;
+ default:
+ bt_dev_err(data->hdev, "Unknown state: 0x%2.2x",
+ data->alive_intr_ctxt);
+ break;
+ }
+
+ if (submit_rx) {
btintel_pcie_reset_ia(data);
btintel_pcie_start_rx(data);
}
- wake_up(&data->gp0_wait_q);
+ if (signal_waitq) {
+ bt_dev_dbg(data->hdev, "wake up gp0 wait_q");
+ wake_up(&data->gp0_wait_q);
+ }
+
+ if (old_ctxt != data->alive_intr_ctxt)
+ bt_dev_dbg(data->hdev, "alive context changed: %s -> %s",
+ btintel_pcie_alivectxt_state2str(old_ctxt),
+ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt));
}
/* This function handles the MSX-X interrupt for rx queue 0 which is for TX
@@ -364,6 +523,83 @@ static void btintel_pcie_msix_tx_handle(struct btintel_pcie_data *data)
}
}
+static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_event_hdr *hdr = (void *)skb->data;
+ const char diagnostics_hdr[] = { 0x87, 0x80, 0x03 };
+ struct btintel_pcie_data *data = hci_get_drvdata(hdev);
+
+ if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff &&
+ hdr->plen > 0) {
+ const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1;
+ unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1;
+
+ if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
+ switch (skb->data[2]) {
+ case 0x02:
+ /* When switching to the operational firmware
+ * the device sends a vendor specific event
+ * indicating that the bootup completed.
+ */
+ btintel_bootup(hdev, ptr, len);
+
+ /* If bootup event is from operational image,
+ * driver needs to write sleep control register to
+ * move into D0 state
+ */
+ if (btintel_pcie_in_op(data)) {
+ btintel_pcie_wr_sleep_cntrl(data, BTINTEL_PCIE_STATE_D0);
+ data->alive_intr_ctxt = BTINTEL_PCIE_INTEL_HCI_RESET2;
+ kfree_skb(skb);
+ return 0;
+ }
+
+ if (btintel_pcie_in_iml(data)) {
+ /* In case of IML, there is no concept
+ * of D0 transition. Just mimic as if
+ * IML moved to D0 by clearing INTEL_WAIT_FOR_D0
+ * bit and waking up the task waiting on
+ * INTEL_WAIT_FOR_D0. This is required
+ * as intel_boot() is common function for
+ * both IML and OP image loading.
+ */
+ if (btintel_test_and_clear_flag(data->hdev,
+ INTEL_WAIT_FOR_D0))
+ btintel_wake_up_flag(data->hdev,
+ INTEL_WAIT_FOR_D0);
+ }
+ kfree_skb(skb);
+ return 0;
+ case 0x06:
+ /* When the firmware loading completes the
+ * device sends out a vendor specific event
+ * indicating the result of the firmware
+ * loading.
+ */
+ btintel_secure_send_result(hdev, ptr, len);
+ kfree_skb(skb);
+ return 0;
+ }
+ }
+
+ /* Handle all diagnostics events separately. May still call
+ * hci_recv_frame.
+ */
+ if (len >= sizeof(diagnostics_hdr) &&
+ memcmp(&skb->data[2], diagnostics_hdr,
+ sizeof(diagnostics_hdr)) == 0) {
+ return btintel_diagnostics(hdev, skb);
+ }
+
+ /* This is a debug event that comes from IML and OP image when it
+ * starts execution. There is no need pass this event to stack.
+ */
+ if (skb->data[2] == 0x97)
+ return 0;
+ }
+
+ return hci_recv_frame(hdev, skb);
+}
/* Process the received rx data
* It check the frame header to identify the data type and create skb
* and calling HCI API
@@ -465,7 +701,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
hdev->stat.byte_rx += plen;
if (pcie_pkt_type == BTINTEL_PCIE_HCI_EVT_PKT)
- ret = btintel_recv_event(hdev, new_skb);
+ ret = btintel_pcie_recv_event(hdev, new_skb);
else
ret = hci_recv_frame(hdev, new_skb);
@@ -516,10 +752,8 @@ static int btintel_pcie_submit_rx_work(struct btintel_pcie_data *data, u8 status
buf += sizeof(*rfh_hdr);
skb = alloc_skb(len, GFP_ATOMIC);
- if (!skb) {
- ret = -ENOMEM;
+ if (!skb)
goto resubmit;
- }
skb_put_data(skb, buf, len);
skb_queue_tail(&data->rx_skb_q, skb);
@@ -734,13 +968,9 @@ static int btintel_pcie_config_pcie(struct pci_dev *pdev,
return err;
}
- err = pcim_iomap_regions(pdev, BIT(0), KBUILD_MODNAME);
- if (err)
- return err;
-
- data->base_addr = pcim_iomap_table(pdev)[0];
- if (!data->base_addr)
- return -ENODEV;
+ data->base_addr = pcim_iomap_region(pdev, 0, KBUILD_MODNAME);
+ if (IS_ERR(data->base_addr))
+ return PTR_ERR(data->base_addr);
err = btintel_pcie_setup_irq(data);
if (err)
@@ -1053,8 +1283,11 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
struct sk_buff *skb)
{
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
+ struct hci_command_hdr *cmd;
+ __u16 opcode = ~0;
int ret;
u32 type;
+ u32 old_ctxt;
/* Due to the fw limitation, the type header of the packet should be
* 4 bytes unlike 1 byte for UART. In UART, the firmware can read
@@ -1073,6 +1306,8 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
type = BTINTEL_PCIE_HCI_CMD_PKT;
+ cmd = (void *)skb->data;
+ opcode = le16_to_cpu(cmd->opcode);
if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
struct hci_command_hdr *cmd = (void *)skb->data;
__u16 opcode = le16_to_cpu(cmd->opcode);
@@ -1111,6 +1346,30 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
bt_dev_err(hdev, "Failed to send frame (%d)", ret);
goto exit_error;
}
+
+ if (type == BTINTEL_PCIE_HCI_CMD_PKT &&
+ (opcode == HCI_OP_RESET || opcode == 0xfc01)) {
+ old_ctxt = data->alive_intr_ctxt;
+ data->alive_intr_ctxt =
+ (opcode == 0xfc01 ? BTINTEL_PCIE_INTEL_HCI_RESET1 :
+ BTINTEL_PCIE_HCI_RESET);
+ bt_dev_dbg(data->hdev, "sent cmd: 0x%4.4x alive context changed: %s -> %s",
+ opcode, btintel_pcie_alivectxt_state2str(old_ctxt),
+ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt));
+ if (opcode == HCI_OP_RESET) {
+ data->gp0_received = false;
+ ret = wait_event_timeout(data->gp0_wait_q,
+ data->gp0_received,
+ msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
+ if (!ret) {
+ hdev->stat.err_tx++;
+ bt_dev_err(hdev, "No alive interrupt received for %s",
+ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt));
+ ret = -ETIME;
+ goto exit_error;
+ }
+ }
+ }
hdev->stat.byte_tx += skb->len;
kfree_skb(skb);
@@ -1128,7 +1387,7 @@ static void btintel_pcie_release_hdev(struct btintel_pcie_data *data)
data->hdev = NULL;
}
-static int btintel_pcie_setup(struct hci_dev *hdev)
+static int btintel_pcie_setup_internal(struct hci_dev *hdev)
{
const u8 param[1] = { 0xFF };
struct intel_version_tlv ver_tlv;
@@ -1219,6 +1478,32 @@ exit_error:
return err;
}
+static int btintel_pcie_setup(struct hci_dev *hdev)
+{
+ int err, fw_dl_retry = 0;
+ struct btintel_pcie_data *data = hci_get_drvdata(hdev);
+
+ while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) {
+ bt_dev_err(hdev, "Firmware download retry count: %d",
+ fw_dl_retry);
+ err = btintel_pcie_reset_bt(data);
+ if (err) {
+ bt_dev_err(hdev, "Failed to do shr reset: %d", err);
+ break;
+ }
+ usleep_range(10000, 12000);
+ btintel_pcie_reset_ia(data);
+ btintel_pcie_config_msix(data);
+ err = btintel_pcie_enable_bt(data);
+ if (err) {
+ bt_dev_err(hdev, "Failed to enable hardware: %d", err);
+ break;
+ }
+ btintel_pcie_start_rx(data);
+ }
+ return err;
+}
+
static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
{
int err;
diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
index baaff70420f5..f9aada0543c4 100644
--- a/drivers/bluetooth/btintel_pcie.h
+++ b/drivers/bluetooth/btintel_pcie.h
@@ -12,6 +12,7 @@
#define BTINTEL_PCIE_CSR_HW_REV_REG (BTINTEL_PCIE_CSR_BASE + 0x028)
#define BTINTEL_PCIE_CSR_RF_ID_REG (BTINTEL_PCIE_CSR_BASE + 0x09C)
#define BTINTEL_PCIE_CSR_BOOT_STAGE_REG (BTINTEL_PCIE_CSR_BASE + 0x108)
+#define BTINTEL_PCIE_CSR_IPC_SLEEP_CTL_REG (BTINTEL_PCIE_CSR_BASE + 0x114)
#define BTINTEL_PCIE_CSR_CI_ADDR_LSB_REG (BTINTEL_PCIE_CSR_BASE + 0x118)
#define BTINTEL_PCIE_CSR_CI_ADDR_MSB_REG (BTINTEL_PCIE_CSR_BASE + 0x11C)
#define BTINTEL_PCIE_CSR_IMG_RESPONSE_REG (BTINTEL_PCIE_CSR_BASE + 0x12C)
@@ -22,6 +23,8 @@
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_INIT (BIT(6))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_FUNC_INIT (BIT(7))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_MAC_ACCESS_STS (BIT(20))
+#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_STS (BIT(28))
+#define BTINTEL_PCIE_CSR_FUNC_CTRL_BUS_MASTER_DISCON (BIT(29))
#define BTINTEL_PCIE_CSR_FUNC_CTRL_SW_RESET (BIT(31))
/* Value for BTINTEL_PCIE_CSR_BOOT_STAGE register */
@@ -32,6 +35,7 @@
#define BTINTEL_PCIE_CSR_BOOT_STAGE_IML_LOCKDOWN (BIT(11))
#define BTINTEL_PCIE_CSR_BOOT_STAGE_MAC_ACCESS_ON (BIT(16))
#define BTINTEL_PCIE_CSR_BOOT_STAGE_ALIVE (BIT(23))
+#define BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY (BIT(24))
/* Registers for MSI-X */
#define BTINTEL_PCIE_CSR_MSIX_BASE (0x2000)
@@ -55,6 +59,16 @@ enum msix_hw_int_causes {
BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0 = BIT(0), /* cause 32 */
};
+/* PCIe device states
+ * Host-Device interface is active
+ * Host-Device interface is inactive(as reflected by IPC_SLEEP_CONTROL_CSR_AD)
+ * Host-Device interface is inactive(as reflected by IPC_SLEEP_CONTROL_CSR_AD)
+ */
+enum {
+ BTINTEL_PCIE_STATE_D0 = 0,
+ BTINTEL_PCIE_STATE_D3_HOT = 2,
+ BTINTEL_PCIE_STATE_D3_COLD = 3,
+};
#define BTINTEL_PCIE_MSIX_NON_AUTO_CLEAR_CAUSE BIT(7)
/* Minimum and Maximum number of MSI-X Vector
@@ -67,7 +81,7 @@ enum msix_hw_int_causes {
#define BTINTEL_DEFAULT_MAC_ACCESS_TIMEOUT_US 200000
/* Default interrupt timeout in msec */
-#define BTINTEL_DEFAULT_INTR_TIMEOUT 3000
+#define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000
/* The number of descriptors in TX/RX queues */
#define BTINTEL_DESCS_COUNT 16
@@ -343,6 +357,7 @@ struct rxq {
* @ia: Index Array struct
* @txq: TX Queue struct
* @rxq: RX Queue struct
+ * @alive_intr_ctxt: Alive interrupt context
*/
struct btintel_pcie_data {
struct pci_dev *pdev;
@@ -389,6 +404,7 @@ struct btintel_pcie_data {
struct ia ia;
struct txq txq;
struct rxq rxq;
+ u32 alive_intr_ctxt;
};
static inline u32 btintel_pcie_rd_reg32(struct btintel_pcie_data *data,
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 9bbf20502163..8a3f7c3fcfec 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -324,7 +324,7 @@ int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
wmt_params.data = NULL;
wmt_params.status = NULL;
- /* Activate funciton the firmware providing to */
+ /* Activate function the firmware providing to */
err = wmt_cmd_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
@@ -1215,7 +1215,6 @@ static int btmtk_usb_isointf_init(struct hci_dev *hdev)
struct sk_buff *skb;
int err;
- init_usb_anchor(&btmtk_data->isopkt_anchor);
spin_lock_init(&btmtk_data->isorxlock);
__set_mtk_intr_interface(hdev);
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index 11d33cd7b08f..a1dfcfe43d3a 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -681,7 +681,7 @@ static int btmtksdio_open(struct hci_dev *hdev)
if (err < 0)
goto err_release_irq;
- /* Explitly set write-1-clear method */
+ /* Explicitly set write-1-clear method */
val = sdio_readl(bdev->func, MTK_REG_CHCR, &err);
if (err < 0)
goto err_release_irq;
@@ -1328,6 +1328,8 @@ static int btmtksdio_probe(struct sdio_func *func,
{
struct btmtksdio_dev *bdev;
struct hci_dev *hdev;
+ struct device_node *old_node;
+ bool restore_node;
int err;
bdev = devm_kzalloc(&func->dev, sizeof(*bdev), GFP_KERNEL);
@@ -1396,7 +1398,7 @@ static int btmtksdio_probe(struct sdio_func *func,
if (pm_runtime_enabled(bdev->dev))
pm_runtime_disable(bdev->dev);
- /* As explaination in drivers/mmc/core/sdio_bus.c tells us:
+ /* As explanation in drivers/mmc/core/sdio_bus.c tells us:
* Unbound SDIO functions are always suspended.
* During probe, the function is set active and the usage count
* is incremented. If the driver supports runtime PM,
@@ -1411,13 +1413,24 @@ static int btmtksdio_probe(struct sdio_func *func,
if (err)
bt_dev_err(hdev, "failed to initialize device wakeup");
- bdev->dev->of_node = of_find_compatible_node(NULL, NULL,
- "mediatek,mt7921s-bluetooth");
+ restore_node = false;
+ if (!of_device_is_compatible(bdev->dev->of_node, "mediatek,mt7921s-bluetooth")) {
+ restore_node = true;
+ old_node = bdev->dev->of_node;
+ bdev->dev->of_node = of_find_compatible_node(NULL, NULL,
+ "mediatek,mt7921s-bluetooth");
+ }
+
bdev->reset = devm_gpiod_get_optional(bdev->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(bdev->reset))
err = PTR_ERR(bdev->reset);
+ if (restore_node) {
+ of_node_put(bdev->dev->of_node);
+ bdev->dev->of_node = old_node;
+ }
+
return err;
}
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
index 64e4d835af52..c97e260fcb0c 100644
--- a/drivers/bluetooth/btmtkuart.c
+++ b/drivers/bluetooth/btmtkuart.c
@@ -327,7 +327,7 @@ mtk_stp_split(struct btmtkuart_dev *bdev, const unsigned char *data, int count,
if (count <= 0)
return NULL;
- /* Tranlate to how much the size of data H4 can handle so far */
+ /* Translate to how much the size of data H4 can handle so far */
*sz_h4 = min_t(int, count, bdev->stp_dlen);
/* Update the remaining size of STP packet */
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 5ea0d23e88c0..569f5b7d6e46 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -16,6 +16,7 @@
#include <linux/crc8.h>
#include <linux/crc32.h>
#include <linux/string_helpers.h>
+#include <linux/gpio/consumer.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -34,16 +35,17 @@
/* NXP HW err codes */
#define BTNXPUART_IR_HW_ERR 0xb0
-#define FIRMWARE_W8987 "uart8987_bt_v0.bin"
+#define FIRMWARE_W8987 "uart8987_bt.bin"
#define FIRMWARE_W8987_OLD "uartuart8987_bt.bin"
#define FIRMWARE_W8997 "uart8997_bt_v4.bin"
#define FIRMWARE_W8997_OLD "uartuart8997_bt_v4.bin"
#define FIRMWARE_W9098 "uart9098_bt_v1.bin"
#define FIRMWARE_W9098_OLD "uartuart9098_bt_v1.bin"
-#define FIRMWARE_IW416 "uartiw416_bt_v0.bin"
+#define FIRMWARE_IW416 "uartiw416_bt.bin"
+#define FIRMWARE_IW416_OLD "uartiw416_bt_v0.bin"
#define FIRMWARE_IW612 "uartspi_n61x_v1.bin.se"
-#define FIRMWARE_IW615 "uartspi_iw610_v0.bin"
-#define FIRMWARE_SECURE_IW615 "uartspi_iw610_v0.bin.se"
+#define FIRMWARE_IW610 "uartspi_iw610.bin"
+#define FIRMWARE_SECURE_IW610 "uartspi_iw610.bin.se"
#define FIRMWARE_IW624 "uartiw624_bt.bin"
#define FIRMWARE_SECURE_IW624 "uartiw624_bt.bin.se"
#define FIRMWARE_AW693 "uartaw693_bt.bin"
@@ -59,8 +61,8 @@
#define CHIP_ID_IW624c 0x8001
#define CHIP_ID_AW693a0 0x8200
#define CHIP_ID_AW693a1 0x8201
-#define CHIP_ID_IW615a0 0x8800
-#define CHIP_ID_IW615a1 0x8801
+#define CHIP_ID_IW610a0 0x8800
+#define CHIP_ID_IW610a1 0x8801
#define FW_SECURE_MASK 0xc0
#define FW_OPEN 0x00
@@ -81,6 +83,7 @@
#define WAKEUP_METHOD_BREAK 1
#define WAKEUP_METHOD_EXT_BREAK 2
#define WAKEUP_METHOD_RTS 3
+#define WAKEUP_METHOD_GPIO 4
#define WAKEUP_METHOD_INVALID 0xff
/* power save mode status */
@@ -134,6 +137,7 @@ struct ps_data {
bool driver_sent_cmd;
u16 h2c_ps_interval;
u16 c2h_ps_interval;
+ struct gpio_desc *h2c_ps_gpio;
struct hci_dev *hdev;
struct work_struct work;
struct timer_list ps_timer;
@@ -364,7 +368,7 @@ static void ps_control(struct hci_dev *hdev, u8 ps_state)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
struct ps_data *psdata = &nxpdev->psdata;
- int status;
+ int status = 0;
if (psdata->ps_state == ps_state ||
!test_bit(BTNXPUART_SERDEV_OPEN, &nxpdev->tx_state))
@@ -372,6 +376,14 @@ static void ps_control(struct hci_dev *hdev, u8 ps_state)
mutex_lock(&psdata->ps_lock);
switch (psdata->cur_h2c_wakeupmode) {
+ case WAKEUP_METHOD_GPIO:
+ if (ps_state == PS_STATE_AWAKE)
+ gpiod_set_value_cansleep(psdata->h2c_ps_gpio, 0);
+ else
+ gpiod_set_value_cansleep(psdata->h2c_ps_gpio, 1);
+ bt_dev_dbg(hdev, "Set h2c_ps_gpio: %s",
+ str_high_low(ps_state == PS_STATE_SLEEP));
+ break;
case WAKEUP_METHOD_DTR:
if (ps_state == PS_STATE_AWAKE)
status = serdev_device_set_tiocm(nxpdev->serdev, TIOCM_DTR, 0);
@@ -421,15 +433,29 @@ static void ps_timeout_func(struct timer_list *t)
}
}
-static void ps_setup(struct hci_dev *hdev)
+static int ps_setup(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+ struct serdev_device *serdev = nxpdev->serdev;
struct ps_data *psdata = &nxpdev->psdata;
+ psdata->h2c_ps_gpio = devm_gpiod_get_optional(&serdev->dev, "device-wakeup",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(psdata->h2c_ps_gpio)) {
+ bt_dev_err(hdev, "Error fetching device-wakeup-gpios: %ld",
+ PTR_ERR(psdata->h2c_ps_gpio));
+ return PTR_ERR(psdata->h2c_ps_gpio);
+ }
+
+ if (!psdata->h2c_ps_gpio)
+ psdata->h2c_wakeup_gpio = 0xff;
+
psdata->hdev = hdev;
INIT_WORK(&psdata->work, ps_work_func);
mutex_init(&psdata->ps_lock);
timer_setup(&psdata->ps_timer, ps_timeout_func, 0);
+
+ return 0;
}
static bool ps_wakeup(struct btnxpuart_dev *nxpdev)
@@ -515,6 +541,9 @@ static int send_wakeup_method_cmd(struct hci_dev *hdev, void *data)
pcmd.c2h_wakeupmode = psdata->c2h_wakeupmode;
pcmd.c2h_wakeup_gpio = psdata->c2h_wakeup_gpio;
switch (psdata->h2c_wakeupmode) {
+ case WAKEUP_METHOD_GPIO:
+ pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_GPIO;
+ break;
case WAKEUP_METHOD_DTR:
pcmd.h2c_wakeupmode = BT_CTRL_WAKEUP_METHOD_DSR;
break;
@@ -549,6 +578,7 @@ static void ps_init(struct hci_dev *hdev)
{
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
struct ps_data *psdata = &nxpdev->psdata;
+ u8 default_h2c_wakeup_mode = DEFAULT_H2C_WAKEUP_MODE;
serdev_device_set_tiocm(nxpdev->serdev, 0, TIOCM_RTS);
usleep_range(5000, 10000);
@@ -560,8 +590,17 @@ static void ps_init(struct hci_dev *hdev)
psdata->c2h_wakeup_gpio = 0xff;
psdata->cur_h2c_wakeupmode = WAKEUP_METHOD_INVALID;
+ if (psdata->h2c_ps_gpio)
+ default_h2c_wakeup_mode = WAKEUP_METHOD_GPIO;
+
psdata->h2c_ps_interval = PS_DEFAULT_TIMEOUT_PERIOD_MS;
- switch (DEFAULT_H2C_WAKEUP_MODE) {
+
+ switch (default_h2c_wakeup_mode) {
+ case WAKEUP_METHOD_GPIO:
+ psdata->h2c_wakeupmode = WAKEUP_METHOD_GPIO;
+ gpiod_set_value_cansleep(psdata->h2c_ps_gpio, 0);
+ usleep_range(5000, 10000);
+ break;
case WAKEUP_METHOD_DTR:
psdata->h2c_wakeupmode = WAKEUP_METHOD_DTR;
serdev_device_set_tiocm(nxpdev->serdev, 0, TIOCM_DTR);
@@ -946,12 +985,12 @@ static char *nxp_get_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid,
else
bt_dev_err(hdev, "Illegal loader version %02x", loader_ver);
break;
- case CHIP_ID_IW615a0:
- case CHIP_ID_IW615a1:
+ case CHIP_ID_IW610a0:
+ case CHIP_ID_IW610a1:
if ((loader_ver & FW_SECURE_MASK) == FW_OPEN)
- fw_name = FIRMWARE_IW615;
+ fw_name = FIRMWARE_IW610;
else if ((loader_ver & FW_SECURE_MASK) != FW_AUTH_ILLEGAL)
- fw_name = FIRMWARE_SECURE_IW615;
+ fw_name = FIRMWARE_SECURE_IW610;
else
bt_dev_err(hdev, "Illegal loader version %02x", loader_ver);
break;
@@ -971,6 +1010,9 @@ static char *nxp_get_old_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid,
case CHIP_ID_W9098:
fw_name_old = FIRMWARE_W9098_OLD;
break;
+ case CHIP_ID_IW416:
+ fw_name_old = FIRMWARE_IW416_OLD;
+ break;
}
return fw_name_old;
}
@@ -1275,6 +1317,9 @@ static int nxp_enqueue(struct hci_dev *hdev, struct sk_buff *skb)
psdata->c2h_wakeup_gpio = wakeup_parm.c2h_wakeup_gpio;
psdata->h2c_wakeup_gpio = wakeup_parm.h2c_wakeup_gpio;
switch (wakeup_parm.h2c_wakeupmode) {
+ case BT_CTRL_WAKEUP_METHOD_GPIO:
+ psdata->h2c_wakeupmode = WAKEUP_METHOD_GPIO;
+ break;
case BT_CTRL_WAKEUP_METHOD_DSR:
psdata->h2c_wakeupmode = WAKEUP_METHOD_DTR;
break;
@@ -1505,13 +1550,17 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
if (hci_register_dev(hdev) < 0) {
dev_err(&serdev->dev, "Can't register HCI device\n");
- hci_free_dev(hdev);
- return -ENODEV;
+ goto probe_fail;
}
- ps_setup(hdev);
+ if (ps_setup(hdev))
+ goto probe_fail;
return 0;
+
+probe_fail:
+ hci_free_dev(hdev);
+ return -ENODEV;
}
static void nxp_serdev_remove(struct serdev_device *serdev)
diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index 0bcb44cf7b31..83025f457ca0 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -1371,7 +1371,7 @@ int btrtl_shutdown_realtek(struct hci_dev *hdev)
/* According to the vendor driver, BT must be reset on close to avoid
* firmware crash.
*/
- skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
+ skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
bt_dev_err(hdev, "HCI reset during shutdown failed");
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index e9534fbc92e3..279fe6c115fa 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -371,6 +371,12 @@ static const struct usb_device_id quirks_table[] = {
/* QCA WCN785x chipset */
{ USB_DEVICE(0x0cf3, 0xe700), .driver_info = BTUSB_QCA_WCN6855 |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe0fc), .driver_info = BTUSB_QCA_WCN6855 |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe0f3), .driver_info = BTUSB_QCA_WCN6855 |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x13d3, 0x3623), .driver_info = BTUSB_QCA_WCN6855 |
+ BTUSB_WIDEBAND_SPEECH },
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
@@ -524,6 +530,8 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe123), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
@@ -563,6 +571,16 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x043e, 0x3109), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
+ /* Additional MediaTek MT7920 Bluetooth devices */
+ { USB_DEVICE(0x0489, 0xe134), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x13d3, 0x3620), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x13d3, 0x3621), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x13d3, 0x3622), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+
/* Additional MediaTek MT7921 Bluetooth devices */
{ USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
@@ -630,12 +648,24 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
/* Additional MediaTek MT7925 Bluetooth devices */
+ { USB_DEVICE(0x0489, 0xe111), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe113), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe118), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe11e), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe124), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe139), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe14f), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe150), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe151), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3603), .driver_info = BTUSB_MEDIATEK |
@@ -846,6 +876,7 @@ struct btusb_data {
int (*suspend)(struct hci_dev *hdev);
int (*resume)(struct hci_dev *hdev);
+ int (*disconnect)(struct hci_dev *hdev);
int oob_wake_irq; /* irq for out-of-band wake-on-bt */
unsigned cmd_timeout_cnt;
@@ -1061,7 +1092,7 @@ static inline void btusb_free_frags(struct btusb_data *data)
static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
{
if (data->intr_interval) {
- /* Trigger dequeue immediatelly if an event is received */
+ /* Trigger dequeue immediately if an event is received */
schedule_delayed_work(&data->rx_work, 0);
}
@@ -2616,13 +2647,14 @@ static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
}
set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
+ init_usb_anchor(&btmtk_data->isopkt_anchor);
}
-static void btusb_mtk_release_iso_intf(struct btusb_data *data)
+static void btusb_mtk_release_iso_intf(struct hci_dev *hdev)
{
- struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
+ struct btmtk_data *btmtk_data = hci_get_priv(hdev);
- if (btmtk_data->isopkt_intf) {
+ if (test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) {
usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor);
clear_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags);
@@ -2636,6 +2668,16 @@ static void btusb_mtk_release_iso_intf(struct btusb_data *data)
clear_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
}
+static int btusb_mtk_disconnect(struct hci_dev *hdev)
+{
+ /* This function describes the specific additional steps taken by MediaTek
+ * when Bluetooth usb driver's resume function is called.
+ */
+ btusb_mtk_release_iso_intf(hdev);
+
+ return 0;
+}
+
static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
{
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -2652,8 +2694,8 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
if (err < 0)
return err;
- if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags))
- btusb_mtk_release_iso_intf(data);
+ /* Release MediaTek ISO data interface */
+ btusb_mtk_release_iso_intf(hdev);
btusb_stop_traffic(data);
usb_kill_anchored_urbs(&data->tx_anchor);
@@ -2698,22 +2740,24 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
btmtk_data->reset_sync = btusb_mtk_reset;
/* Claim ISO data interface and endpoint */
- btmtk_data->isopkt_intf = usb_ifnum_to_if(data->udev, MTK_ISO_IFNUM);
- if (btmtk_data->isopkt_intf)
+ if (!test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) {
+ btmtk_data->isopkt_intf = usb_ifnum_to_if(data->udev, MTK_ISO_IFNUM);
btusb_mtk_claim_iso_intf(data);
+ }
return btmtk_usb_setup(hdev);
}
static int btusb_mtk_shutdown(struct hci_dev *hdev)
{
- struct btusb_data *data = hci_get_drvdata(hdev);
- struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+ int ret;
- if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags))
- btusb_mtk_release_iso_intf(data);
+ ret = btmtk_usb_shutdown(hdev);
- return btmtk_usb_shutdown(hdev);
+ /* Release MediaTek iso interface after shutdown */
+ btusb_mtk_release_iso_intf(hdev);
+
+ return ret;
}
#ifdef CONFIG_PM
@@ -3825,6 +3869,7 @@ static int btusb_probe(struct usb_interface *intf,
data->recv_acl = btmtk_usb_recv_acl;
data->suspend = btmtk_usb_suspend;
data->resume = btmtk_usb_resume;
+ data->disconnect = btusb_mtk_disconnect;
}
if (id->driver_info & BTUSB_SWAVE) {
@@ -3896,6 +3941,8 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks);
+ set_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, &hdev->quirks);
+ set_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT, &hdev->quirks);
}
if (!reset)
@@ -4013,6 +4060,9 @@ static void btusb_disconnect(struct usb_interface *intf)
if (data->diag)
usb_set_intfdata(data->diag, NULL);
+ if (data->disconnect)
+ data->disconnect(hdev);
+
hci_unregister_dev(hdev);
if (intf == data->intf) {
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 89d4c2224546..521b785f2908 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -1068,17 +1068,17 @@ static struct clk *bcm_get_txco(struct device *dev)
struct clk *clk;
/* New explicit name */
- clk = devm_clk_get(dev, "txco");
- if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
+ clk = devm_clk_get_optional(dev, "txco");
+ if (clk)
return clk;
/* Deprecated name */
- clk = devm_clk_get(dev, "extclk");
- if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
+ clk = devm_clk_get_optional(dev, "extclk");
+ if (clk)
return clk;
/* Original code used no name at all */
- return devm_clk_get(dev, NULL);
+ return devm_clk_get_optional(dev, NULL);
}
static int bcm_get_resources(struct bcm_device *dev)
@@ -1093,21 +1093,12 @@ static int bcm_get_resources(struct bcm_device *dev)
return 0;
dev->txco_clk = bcm_get_txco(dev->dev);
-
- /* Handle deferred probing */
- if (dev->txco_clk == ERR_PTR(-EPROBE_DEFER))
- return PTR_ERR(dev->txco_clk);
-
- /* Ignore all other errors as before */
if (IS_ERR(dev->txco_clk))
- dev->txco_clk = NULL;
-
- dev->lpo_clk = devm_clk_get(dev->dev, "lpo");
- if (dev->lpo_clk == ERR_PTR(-EPROBE_DEFER))
- return PTR_ERR(dev->lpo_clk);
+ return PTR_ERR(dev->txco_clk);
+ dev->lpo_clk = devm_clk_get_optional(dev->dev, "lpo");
if (IS_ERR(dev->lpo_clk))
- dev->lpo_clk = NULL;
+ return PTR_ERR(dev->lpo_clk);
/* Check if we accidentally fetched the lpo clock twice */
if (dev->lpo_clk && clk_is_match(dev->lpo_clk, dev->txco_clk)) {
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 395d66e32a2e..d2d6ba8d2f8b 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -594,7 +594,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
* Called by tty low level driver when receive data is
* available.
*
- * Arguments: tty pointer to tty isntance data
+ * Arguments: tty pointer to tty instance data
* data pointer to received data
* flags pointer to flags for data
* count count of received data in bytes
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index 4a0b5c3160c2..e19e9bd49555 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -305,7 +305,7 @@ static void ll_device_woke_up(struct hci_uart *hu)
hci_uart_tx_wakeup(hu);
}
-/* Enqueue frame for transmittion (padding, crc, etc) */
+/* Enqueue frame for transmission (padding, crc, etc) */
/* may be called from two simultaneous tasklets */
static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
diff --git a/drivers/bluetooth/hci_nokia.c b/drivers/bluetooth/hci_nokia.c
index 49bbe4975be4..9fc10a16fd96 100644
--- a/drivers/bluetooth/hci_nokia.c
+++ b/drivers/bluetooth/hci_nokia.c
@@ -501,7 +501,7 @@ static int nokia_close(struct hci_uart *hu)
return 0;
}
-/* Enqueue frame for transmittion (padding, crc, etc) */
+/* Enqueue frame for transmission (padding, crc, etc) */
static int nokia_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct nokia_bt_dev *btdev = hu->priv;
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 37fddf6055be..37129e6cb0eb 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -873,7 +873,7 @@ static void device_woke_up(struct hci_uart *hu)
hci_uart_tx_wakeup(hu);
}
-/* Enqueue frame for transmittion (padding, crc, etc) may be called from
+/* Enqueue frame for transmission (padding, crc, etc) may be called from
* two simultaneous tasklets.
*/
static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb)
@@ -1059,7 +1059,7 @@ static void qca_controller_memdump(struct work_struct *work)
if (!seq_no) {
/* This is the first frame of memdump packet from
- * the controller, Disable IBS to recevie dump
+ * the controller, Disable IBS to receive dump
* with out any interruption, ideally time required for
* the controller to send the dump is 8 seconds. let us
* start timer to handle this asynchronous activity.
@@ -2294,13 +2294,6 @@ static int qca_init_regulators(struct qca_power *qca,
return 0;
}
-static void qca_clk_disable_unprepare(void *data)
-{
- struct clk *clk = data;
-
- clk_disable_unprepare(clk);
-}
-
static int qca_serdev_probe(struct serdev_device *serdev)
{
struct qca_serdev *qcadev;
@@ -2358,7 +2351,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
* Backward compatibility with old DT sources. If the
* node doesn't have the 'enable-gpios' property then
* let's use the power sequencer. Otherwise, let's
- * drive everything outselves.
+ * drive everything ourselves.
*/
qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev,
"bluetooth");
@@ -2433,25 +2426,12 @@ static int qca_serdev_probe(struct serdev_device *serdev)
if (!qcadev->bt_en)
power_ctrl_enabled = false;
- qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
+ qcadev->susclk = devm_clk_get_optional_enabled_with_rate(
+ &serdev->dev, NULL, SUSCLK_RATE_32KHZ);
if (IS_ERR(qcadev->susclk)) {
dev_warn(&serdev->dev, "failed to acquire clk\n");
return PTR_ERR(qcadev->susclk);
}
- err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ);
- if (err)
- return err;
-
- err = clk_prepare_enable(qcadev->susclk);
- if (err)
- return err;
-
- err = devm_add_action_or_reset(&serdev->dev,
- qca_clk_disable_unprepare,
- qcadev->susclk);
- if (err)
- return err;
-
}
err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto);
@@ -2530,7 +2510,7 @@ static void qca_serdev_shutdown(struct device *dev)
hci_dev_test_flag(hdev, HCI_SETUP))
return;
- /* The serdev must be in open state when conrol logic arrives
+ /* The serdev must be in open state when control logic arrives
* here, so also fix the use-after-free issue caused by that
* the serdev is flushed or wrote after it is closed.
*/
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 930d8a3ba722..2916d1333649 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -1210,7 +1210,7 @@ static struct platform_driver fsl_mc_bus_driver = {
.acpi_match_table = fsl_mc_bus_acpi_match_table,
},
.probe = fsl_mc_bus_probe,
- .remove_new = fsl_mc_bus_remove,
+ .remove = fsl_mc_bus_remove,
.shutdown = fsl_mc_bus_remove,
};
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 09340adbacc2..53dd1573e323 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -689,6 +689,6 @@ static struct platform_driver hisi_lpc_driver = {
.acpi_match_table = hisi_lpc_acpi_match,
},
.probe = hisi_lpc_probe,
- .remove_new = hisi_lpc_remove,
+ .remove = hisi_lpc_remove,
};
builtin_platform_driver(hisi_lpc_driver);
diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c
index dedd29ca8db3..e8c92972f9df 100644
--- a/drivers/bus/mhi/host/boot.c
+++ b/drivers/bus/mhi/host/boot.c
@@ -82,9 +82,9 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
* other cores to shutdown while we're collecting RDDM buffer. After
* returning from this function, we expect the device to reset.
*
- * Normaly, we read/write pm_state only after grabbing the
+ * Normally, we read/write pm_state only after grabbing the
* pm_lock, since we're in a panic, skipping it. Also there is no
- * gurantee that this state change would take effect since
+ * guarantee that this state change would take effect since
* we're setting it w/o grabbing pm_lock
*/
mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT;
diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h
index d057e877932e..3134f111be35 100644
--- a/drivers/bus/mhi/host/internal.h
+++ b/drivers/bus/mhi/host/internal.h
@@ -255,7 +255,7 @@ struct mhi_chan {
/*
* Important: When consuming, increment tre_ring first and when
* releasing, decrement buf_ring first. If tre_ring has space, buf_ring
- * is guranteed to have space so we do not need to check both rings.
+ * is guaranteed to have space so we do not need to check both rings.
*/
struct mhi_ring buf_ring;
struct mhi_ring tre_ring;
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index 9938bb034c1c..07645ce2119a 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -917,12 +917,12 @@ static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
return err;
}
- err = pcim_iomap_regions(pdev, 1 << bar_num, pci_name(pdev));
- if (err) {
+ mhi_cntrl->regs = pcim_iomap_region(pdev, 1 << bar_num, pci_name(pdev));
+ if (IS_ERR(mhi_cntrl->regs)) {
+ err = PTR_ERR(mhi_cntrl->regs);
dev_err(&pdev->dev, "failed to map pci region: %d\n", err);
return err;
}
- mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num];
mhi_cntrl->reg_len = pci_resource_len(pdev, bar_num);
err = dma_set_mask_and_coherent(&pdev->dev, dma_mask);
diff --git a/drivers/bus/mhi/host/trace.h b/drivers/bus/mhi/host/trace.h
index 95613c8ebe06..3e0c41777429 100644
--- a/drivers/bus/mhi/host/trace.h
+++ b/drivers/bus/mhi/host/trace.h
@@ -9,6 +9,7 @@
#if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_EVENT_MHI_HOST_H
+#include <linux/byteorder/generic.h>
#include <linux/tracepoint.h>
#include <linux/trace_seq.h>
#include "../common.h"
@@ -97,18 +98,18 @@ TRACE_EVENT(mhi_gen_tre,
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, ch_num)
__field(void *, wp)
- __field(__le64, tre_ptr)
- __field(__le32, dword0)
- __field(__le32, dword1)
+ __field(uint64_t, tre_ptr)
+ __field(uint32_t, dword0)
+ __field(uint32_t, dword1)
),
TP_fast_assign(
__assign_str(name);
__entry->ch_num = mhi_chan->chan;
__entry->wp = mhi_tre;
- __entry->tre_ptr = mhi_tre->ptr;
- __entry->dword0 = mhi_tre->dword[0];
- __entry->dword1 = mhi_tre->dword[1];
+ __entry->tre_ptr = le64_to_cpu(mhi_tre->ptr);
+ __entry->dword0 = le32_to_cpu(mhi_tre->dword[0]);
+ __entry->dword1 = le32_to_cpu(mhi_tre->dword[1]);
),
TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n",
@@ -176,19 +177,19 @@ DECLARE_EVENT_CLASS(mhi_process_event_ring,
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
- __field(__le32, dword0)
- __field(__le32, dword1)
+ __field(uint32_t, dword0)
+ __field(uint32_t, dword1)
__field(int, state)
- __field(__le64, ptr)
+ __field(uint64_t, ptr)
__field(void *, rp)
),
TP_fast_assign(
__assign_str(name);
__entry->rp = rp;
- __entry->ptr = rp->ptr;
- __entry->dword0 = rp->dword[0];
- __entry->dword1 = rp->dword[1];
+ __entry->ptr = le64_to_cpu(rp->ptr);
+ __entry->dword0 = le32_to_cpu(rp->dword[0]);
+ __entry->dword1 = le32_to_cpu(rp->dword[1]);
__entry->state = MHI_TRE_GET_EV_STATE(rp);
),
diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c
index 7d7479ba0a75..e4dfda7b3b10 100644
--- a/drivers/bus/omap-ocp2scp.c
+++ b/drivers/bus/omap-ocp2scp.c
@@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(of, omap_ocp2scp_id_table);
static struct platform_driver omap_ocp2scp_driver = {
.probe = omap_ocp2scp_probe,
- .remove_new = omap_ocp2scp_remove,
+ .remove = omap_ocp2scp_remove,
.driver = {
.name = "omap-ocp2scp",
.of_match_table = of_match_ptr(omap_ocp2scp_id_table),
diff --git a/drivers/bus/omap_l3_smx.c b/drivers/bus/omap_l3_smx.c
index ee6d29925e4d..7f0a8f8b3f4c 100644
--- a/drivers/bus/omap_l3_smx.c
+++ b/drivers/bus/omap_l3_smx.c
@@ -273,7 +273,7 @@ static void omap3_l3_remove(struct platform_device *pdev)
static struct platform_driver omap3_l3_driver = {
.probe = omap3_l3_probe,
- .remove_new = omap3_l3_remove,
+ .remove = omap3_l3_remove,
.driver = {
.name = "omap_l3_smx",
.of_match_table = of_match_ptr(omap3_l3_match),
diff --git a/drivers/bus/qcom-ssc-block-bus.c b/drivers/bus/qcom-ssc-block-bus.c
index 5931974a21fa..85d781a32df4 100644
--- a/drivers/bus/qcom-ssc-block-bus.c
+++ b/drivers/bus/qcom-ssc-block-bus.c
@@ -373,7 +373,7 @@ MODULE_DEVICE_TABLE(of, qcom_ssc_block_bus_of_match);
static struct platform_driver qcom_ssc_block_bus_driver = {
.probe = qcom_ssc_block_bus_probe,
- .remove_new = qcom_ssc_block_bus_remove,
+ .remove = qcom_ssc_block_bus_remove,
.driver = {
.name = "qcom-ssc-block-bus",
.of_match_table = qcom_ssc_block_bus_of_match,
diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c
index 50870c827889..5dea31769f9a 100644
--- a/drivers/bus/simple-pm-bus.c
+++ b/drivers/bus/simple-pm-bus.c
@@ -128,7 +128,7 @@ MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match);
static struct platform_driver simple_pm_bus_driver = {
.probe = simple_pm_bus_probe,
- .remove_new = simple_pm_bus_remove,
+ .remove = simple_pm_bus_remove,
.driver = {
.name = "simple-pm-bus",
.of_match_table = simple_pm_bus_of_match,
diff --git a/drivers/bus/sun50i-de2.c b/drivers/bus/sun50i-de2.c
index 3339311ce068..dfe588179aca 100644
--- a/drivers/bus/sun50i-de2.c
+++ b/drivers/bus/sun50i-de2.c
@@ -36,7 +36,7 @@ static const struct of_device_id sun50i_de2_bus_of_match[] = {
static struct platform_driver sun50i_de2_bus_driver = {
.probe = sun50i_de2_bus_probe,
- .remove_new = sun50i_de2_bus_remove,
+ .remove = sun50i_de2_bus_remove,
.driver = {
.name = "sun50i-de2-bus",
.of_match_table = sun50i_de2_bus_of_match,
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
index a89d78925637..7a33c3b31d1e 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
@@ -832,7 +832,7 @@ MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table);
static struct platform_driver sunxi_rsb_driver = {
.probe = sunxi_rsb_probe,
- .remove_new = sunxi_rsb_remove,
+ .remove = sunxi_rsb_remove,
.driver = {
.name = RSB_CTRL_NAME,
.of_match_table = sunxi_rsb_of_match_table,
diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c
index de80008bff92..90e3b0a10816 100644
--- a/drivers/bus/tegra-aconnect.c
+++ b/drivers/bus/tegra-aconnect.c
@@ -104,7 +104,7 @@ MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match);
static struct platform_driver tegra_aconnect_driver = {
.probe = tegra_aconnect_probe,
- .remove_new = tegra_aconnect_remove,
+ .remove = tegra_aconnect_remove,
.driver = {
.name = "tegra-aconnect",
.of_match_table = tegra_aconnect_of_match,
diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c
index f5d6414df9f2..9c09141961d8 100644
--- a/drivers/bus/tegra-gmi.c
+++ b/drivers/bus/tegra-gmi.c
@@ -303,7 +303,7 @@ MODULE_DEVICE_TABLE(of, tegra_gmi_id_table);
static struct platform_driver tegra_gmi_driver = {
.probe = tegra_gmi_probe,
- .remove_new = tegra_gmi_remove,
+ .remove = tegra_gmi_remove,
.driver = {
.name = "tegra-gmi",
.of_match_table = tegra_gmi_id_table,
diff --git a/drivers/bus/ti-pwmss.c b/drivers/bus/ti-pwmss.c
index 4969c556e752..1f2cab91e438 100644
--- a/drivers/bus/ti-pwmss.c
+++ b/drivers/bus/ti-pwmss.c
@@ -44,7 +44,7 @@ static struct platform_driver pwmss_driver = {
.of_match_table = pwmss_of_match,
},
.probe = pwmss_probe,
- .remove_new = pwmss_remove,
+ .remove = pwmss_remove,
};
module_platform_driver(pwmss_driver);
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 270a94a06e05..f67b927ae4ca 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -3345,7 +3345,7 @@ MODULE_DEVICE_TABLE(of, sysc_match);
static struct platform_driver sysc_driver = {
.probe = sysc_probe,
- .remove_new = sysc_remove,
+ .remove = sysc_remove,
.driver = {
.name = "ti-sysc",
.of_match_table = sysc_match,
diff --git a/drivers/bus/ts-nbus.c b/drivers/bus/ts-nbus.c
index b8af44c5cdbd..2328c48b9b12 100644
--- a/drivers/bus/ts-nbus.c
+++ b/drivers/bus/ts-nbus.c
@@ -336,7 +336,7 @@ MODULE_DEVICE_TABLE(of, ts_nbus_of_match);
static struct platform_driver ts_nbus_driver = {
.probe = ts_nbus_probe,
- .remove_new = ts_nbus_remove,
+ .remove = ts_nbus_remove,
.driver = {
.name = "ts_nbus",
.of_match_table = ts_nbus_of_match,
diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c
index 07371cb653d3..316bd89a95ca 100644
--- a/drivers/cdx/cdx.c
+++ b/drivers/cdx/cdx.c
@@ -707,7 +707,7 @@ static const struct vm_operations_struct cdx_phys_vm_ops = {
* Return: true on success, false otherwise.
*/
static int cdx_mmap_resource(struct file *fp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct cdx_device *cdx_dev = to_cdx_device(kobj_to_dev(kobj));
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 7c8dd0abcfdf..8fb33c90482f 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -238,6 +238,7 @@ config APPLICOM
config SONYPI
tristate "Sony Vaio Programmable I/O Control Device support"
depends on X86_32 && PCI && INPUT
+ depends on ACPI_EC || !ACPI
help
This driver enables access to the Sony Programmable I/O Control
Device which can be found in many (all ?) Sony Vaio laptops.
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index e904e476e49a..48fe96ab4649 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -162,6 +162,7 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
static void hpet_timer_set_irq(struct hpet_dev *devp)
{
+ const unsigned int nr_irqs = irq_get_nr_irqs();
unsigned long v;
int irq, gsi;
struct hpet_timer __iomem *timer;
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index b51d9e243f35..17854f052386 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -50,7 +50,7 @@ config HW_RANDOM_INTEL
config HW_RANDOM_AMD
tristate "AMD HW Random Number Generator support"
- depends on (X86 || PPC_MAPLE || COMPILE_TEST)
+ depends on (X86 || COMPILE_TEST)
depends on PCI && HAS_IOPORT_MAP
default HW_RANDOM
help
@@ -62,6 +62,19 @@ config HW_RANDOM_AMD
If unsure, say Y.
+config HW_RANDOM_AIROHA
+ tristate "Airoha True HW Random Number Generator support"
+ depends on ARCH_AIROHA || COMPILE_TEST
+ default HW_RANDOM
+ help
+ This driver provides kernel-side support for the True Random Number
+ Generator hardware found on Airoha SoC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called airoha-rng.
+
+ If unsure, say Y.
+
config HW_RANDOM_ATMEL
tristate "Atmel Random Number Generator support"
depends on (ARCH_AT91 || COMPILE_TEST)
@@ -99,9 +112,22 @@ config HW_RANDOM_BCM2835
If unsure, say Y.
+config HW_RANDOM_BCM74110
+ tristate "Broadcom BCM74110 Random Number Generator support"
+ depends on ARCH_BRCMSTB || COMPILE_TEST
+ default HW_RANDOM
+ help
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on the Broadcom BCM74110 SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bcm74110-rng
+
+ If unsure, say Y.
+
config HW_RANDOM_IPROC_RNG200
tristate "Broadcom iProc/STB RNG200 support"
- depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST
+ depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BCMBCA || ARCH_BRCMSTB || COMPILE_TEST
default HW_RANDOM
help
This driver provides kernel-side support for the RNG200
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 01f012eab440..b9132b3f5d21 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -8,6 +8,7 @@ rng-core-y := core.o
obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+obj-$(CONFIG_HW_RANDOM_AIROHA) += airoha-trng.o
obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
obj-$(CONFIG_HW_RANDOM_BA431) += ba431-rng.o
obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
@@ -31,6 +32,7 @@ obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o
obj-$(CONFIG_HW_RANDOM_HISTB) += histb-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
+obj-$(CONFIG_HW_RANDOM_BCM74110) += bcm74110-rng.o
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
diff --git a/drivers/char/hw_random/airoha-trng.c b/drivers/char/hw_random/airoha-trng.c
new file mode 100644
index 000000000000..1dbfa9505c21
--- /dev/null
+++ b/drivers/char/hw_random/airoha-trng.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2024 Christian Marangi */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/hw_random.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/platform_device.h>
+
+#define TRNG_IP_RDY 0x800
+#define CNT_TRANS GENMASK(15, 8)
+#define SAMPLE_RDY BIT(0)
+#define TRNG_NS_SEK_AND_DAT_EN 0x804
+#define RNG_EN BIT(31) /* referenced as ring_en */
+#define RAW_DATA_EN BIT(16)
+#define TRNG_HEALTH_TEST_SW_RST 0x808
+#define SW_RST BIT(0) /* Active High */
+#define TRNG_INTR_EN 0x818
+#define INTR_MASK BIT(16)
+#define CONTINUOUS_HEALTH_INITR_EN BIT(2)
+#define SW_STARTUP_INITR_EN BIT(1)
+#define RST_STARTUP_INITR_EN BIT(0)
+/* Notice that Health Test are done only out of Reset and with RNG_EN */
+#define TRNG_HEALTH_TEST_STATUS 0x824
+#define CONTINUOUS_HEALTH_AP_TEST_FAIL BIT(23)
+#define CONTINUOUS_HEALTH_RC_TEST_FAIL BIT(22)
+#define SW_STARTUP_TEST_DONE BIT(21)
+#define SW_STARTUP_AP_TEST_FAIL BIT(20)
+#define SW_STARTUP_RC_TEST_FAIL BIT(19)
+#define RST_STARTUP_TEST_DONE BIT(18)
+#define RST_STARTUP_AP_TEST_FAIL BIT(17)
+#define RST_STARTUP_RC_TEST_FAIL BIT(16)
+#define RAW_DATA_VALID BIT(7)
+
+#define TRNG_RAW_DATA_OUT 0x828
+
+#define TRNG_CNT_TRANS_VALID 0x80
+#define BUSY_LOOP_SLEEP 10
+#define BUSY_LOOP_TIMEOUT (BUSY_LOOP_SLEEP * 10000)
+
+struct airoha_trng {
+ void __iomem *base;
+ struct hwrng rng;
+ struct device *dev;
+
+ struct completion rng_op_done;
+};
+
+static int airoha_trng_irq_mask(struct airoha_trng *trng)
+{
+ u32 val;
+
+ val = readl(trng->base + TRNG_INTR_EN);
+ val |= INTR_MASK;
+ writel(val, trng->base + TRNG_INTR_EN);
+
+ return 0;
+}
+
+static int airoha_trng_irq_unmask(struct airoha_trng *trng)
+{
+ u32 val;
+
+ val = readl(trng->base + TRNG_INTR_EN);
+ val &= ~INTR_MASK;
+ writel(val, trng->base + TRNG_INTR_EN);
+
+ return 0;
+}
+
+static int airoha_trng_init(struct hwrng *rng)
+{
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
+ int ret;
+ u32 val;
+
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
+ val |= RNG_EN;
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
+
+ /* Set out of SW Reset */
+ airoha_trng_irq_unmask(trng);
+ writel(0, trng->base + TRNG_HEALTH_TEST_SW_RST);
+
+ ret = wait_for_completion_timeout(&trng->rng_op_done, BUSY_LOOP_TIMEOUT);
+ if (ret <= 0) {
+ dev_err(trng->dev, "Timeout waiting for Health Check\n");
+ airoha_trng_irq_mask(trng);
+ return -ENODEV;
+ }
+
+ /* Check if Health Test Failed */
+ val = readl(trng->base + TRNG_HEALTH_TEST_STATUS);
+ if (val & (RST_STARTUP_AP_TEST_FAIL | RST_STARTUP_RC_TEST_FAIL)) {
+ dev_err(trng->dev, "Health Check fail: %s test fail\n",
+ val & RST_STARTUP_AP_TEST_FAIL ? "AP" : "RC");
+ return -ENODEV;
+ }
+
+ /* Check if IP is ready */
+ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val,
+ val & SAMPLE_RDY, 10, 1000);
+ if (ret < 0) {
+ dev_err(trng->dev, "Timeout waiting for IP ready");
+ return -ENODEV;
+ }
+
+ /* CNT_TRANS must be 0x80 for IP to be considered ready */
+ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val,
+ FIELD_GET(CNT_TRANS, val) == TRNG_CNT_TRANS_VALID,
+ 10, 1000);
+ if (ret < 0) {
+ dev_err(trng->dev, "Timeout waiting for IP ready");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void airoha_trng_cleanup(struct hwrng *rng)
+{
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
+ u32 val;
+
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
+ val &= ~RNG_EN;
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
+
+ /* Put it in SW Reset */
+ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST);
+}
+
+static int airoha_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
+ u32 *data = buf;
+ u32 status;
+ int ret;
+
+ ret = readl_poll_timeout(trng->base + TRNG_HEALTH_TEST_STATUS, status,
+ status & RAW_DATA_VALID, 10, 1000);
+ if (ret < 0) {
+ dev_err(trng->dev, "Timeout waiting for TRNG RAW Data valid\n");
+ return ret;
+ }
+
+ *data = readl(trng->base + TRNG_RAW_DATA_OUT);
+
+ return 4;
+}
+
+static irqreturn_t airoha_trng_irq(int irq, void *priv)
+{
+ struct airoha_trng *trng = (struct airoha_trng *)priv;
+
+ airoha_trng_irq_mask(trng);
+ /* Just complete the task, we will read the value later */
+ complete(&trng->rng_op_done);
+
+ return IRQ_HANDLED;
+}
+
+static int airoha_trng_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct airoha_trng *trng;
+ int irq, ret;
+ u32 val;
+
+ trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL);
+ if (!trng)
+ return -ENOMEM;
+
+ trng->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(trng->base))
+ return PTR_ERR(trng->base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ airoha_trng_irq_mask(trng);
+ ret = devm_request_irq(&pdev->dev, irq, airoha_trng_irq, 0,
+ pdev->name, (void *)trng);
+ if (ret) {
+ dev_err(dev, "Can't get interrupt working.\n");
+ return ret;
+ }
+
+ init_completion(&trng->rng_op_done);
+
+ /* Enable interrupt for SW reset Health Check */
+ val = readl(trng->base + TRNG_INTR_EN);
+ val |= RST_STARTUP_INITR_EN;
+ writel(val, trng->base + TRNG_INTR_EN);
+
+ /* Set output to raw data */
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
+ val |= RAW_DATA_EN;
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
+
+ /* Put it in SW Reset */
+ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST);
+
+ trng->dev = dev;
+ trng->rng.name = pdev->name;
+ trng->rng.init = airoha_trng_init;
+ trng->rng.cleanup = airoha_trng_cleanup;
+ trng->rng.read = airoha_trng_read;
+
+ ret = devm_hwrng_register(dev, &trng->rng);
+ if (ret) {
+ dev_err(dev, "failed to register rng device: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id airoha_trng_of_match[] = {
+ { .compatible = "airoha,en7581-trng", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, airoha_trng_of_match);
+
+static struct platform_driver airoha_trng_driver = {
+ .driver = {
+ .name = "airoha-trng",
+ .of_match_table = airoha_trng_of_match,
+ },
+ .probe = airoha_trng_probe,
+};
+
+module_platform_driver(airoha_trng_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_DESCRIPTION("Airoha True Random Number Generator driver");
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index e9157255f851..143406bc6939 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -216,7 +216,7 @@ MODULE_DEVICE_TABLE(of, atmel_trng_dt_ids);
static struct platform_driver atmel_trng_driver = {
.probe = atmel_trng_probe,
- .remove_new = atmel_trng_remove,
+ .remove = atmel_trng_remove,
.driver = {
.name = "atmel-trng",
.pm = pm_ptr(&atmel_trng_pm_ops),
diff --git a/drivers/char/hw_random/bcm74110-rng.c b/drivers/char/hw_random/bcm74110-rng.c
new file mode 100644
index 000000000000..5c64148e91f1
--- /dev/null
+++ b/drivers/char/hw_random/bcm74110-rng.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Broadcom
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/hw_random.h>
+
+#define HOST_REV_ID 0x00
+#define HOST_FIFO_DEPTH 0x04
+#define HOST_FIFO_COUNT 0x08
+#define HOST_FIFO_THRESHOLD 0x0c
+#define HOST_FIFO_DATA 0x10
+
+#define HOST_FIFO_COUNT_MASK 0xffff
+
+/* Delay range in microseconds */
+#define FIFO_DELAY_MIN_US 3
+#define FIFO_DELAY_MAX_US 7
+#define FIFO_DELAY_MAX_COUNT 10
+
+struct bcm74110_priv {
+ void __iomem *base;
+};
+
+static inline int bcm74110_rng_fifo_count(void __iomem *mem)
+{
+ return readl_relaxed(mem) & HOST_FIFO_COUNT_MASK;
+}
+
+static int bcm74110_rng_read(struct hwrng *rng, void *buf, size_t max,
+ bool wait)
+{
+ struct bcm74110_priv *priv = (struct bcm74110_priv *)rng->priv;
+ void __iomem *fc_addr = priv->base + HOST_FIFO_COUNT;
+ void __iomem *fd_addr = priv->base + HOST_FIFO_DATA;
+ unsigned underrun_count = 0;
+ u32 max_words = max / sizeof(u32);
+ u32 num_words;
+ unsigned i;
+
+ /*
+ * We need to check how many words are available in the RNG FIFO. If
+ * there aren't any, we need to wait for some to become available.
+ */
+ while ((num_words = bcm74110_rng_fifo_count(fc_addr)) == 0) {
+ if (!wait)
+ return 0;
+ /*
+ * As a precaution, limit how long we wait. If the FIFO doesn't
+ * refill within the allotted time, return 0 (=no data) to the
+ * caller.
+ */
+ if (likely(underrun_count < FIFO_DELAY_MAX_COUNT))
+ usleep_range(FIFO_DELAY_MIN_US, FIFO_DELAY_MAX_US);
+ else
+ return 0;
+ underrun_count++;
+ }
+ if (num_words > max_words)
+ num_words = max_words;
+
+ /* Bail early if we run out of random numbers unexpectedly */
+ for (i = 0; i < num_words && bcm74110_rng_fifo_count(fc_addr) > 0; i++)
+ ((u32 *)buf)[i] = readl_relaxed(fd_addr);
+
+ return i * sizeof(u32);
+}
+
+static struct hwrng bcm74110_hwrng = {
+ .read = bcm74110_rng_read,
+};
+
+static int bcm74110_rng_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bcm74110_priv *priv;
+ int rc;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ bcm74110_hwrng.name = pdev->name;
+ bcm74110_hwrng.priv = (unsigned long)priv;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ rc = devm_hwrng_register(dev, &bcm74110_hwrng);
+ if (rc)
+ dev_err(dev, "hwrng registration failed (%d)\n", rc);
+ else
+ dev_info(dev, "hwrng registered\n");
+
+ return rc;
+}
+
+static const struct of_device_id bcm74110_rng_match[] = {
+ { .compatible = "brcm,bcm74110-rng", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm74110_rng_match);
+
+static struct platform_driver bcm74110_rng_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = bcm74110_rng_match,
+ },
+ .probe = bcm74110_rng_probe,
+};
+module_platform_driver(bcm74110_rng_driver);
+
+MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
+MODULE_DESCRIPTION("BCM 74110 Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c
index 4c50efc46483..4db198849695 100644
--- a/drivers/char/hw_random/cctrng.c
+++ b/drivers/char/hw_random/cctrng.c
@@ -653,7 +653,7 @@ static struct platform_driver cctrng_driver = {
.pm = &cctrng_pm,
},
.probe = cctrng_probe,
- .remove_new = cctrng_remove,
+ .remove = cctrng_remove,
};
module_platform_driver(cctrng_driver);
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 57c51efa5613..018316f54621 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -181,8 +181,15 @@ static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
int present;
BUG_ON(!mutex_is_locked(&reading_mutex));
- if (rng->read)
- return rng->read(rng, (void *)buffer, size, wait);
+ if (rng->read) {
+ int err;
+
+ err = rng->read(rng, buffer, size, wait);
+ if (WARN_ON_ONCE(err > 0 && err > size))
+ err = size;
+
+ return err;
+ }
if (rng->data_present)
present = rng->data_present(rng, wait);
diff --git a/drivers/char/hw_random/exynos-trng.c b/drivers/char/hw_random/exynos-trng.c
index 9f039fddaee3..02e207c09e81 100644
--- a/drivers/char/hw_random/exynos-trng.c
+++ b/drivers/char/hw_random/exynos-trng.c
@@ -335,7 +335,7 @@ static struct platform_driver exynos_trng_driver = {
.of_match_table = exynos_trng_dt_match,
},
.probe = exynos_trng_probe,
- .remove_new = exynos_trng_remove,
+ .remove = exynos_trng_remove,
};
module_platform_driver(exynos_trng_driver);
diff --git a/drivers/char/hw_random/histb-rng.c b/drivers/char/hw_random/histb-rng.c
index f652e1135e4b..1b91e88cc4c0 100644
--- a/drivers/char/hw_random/histb-rng.c
+++ b/drivers/char/hw_random/histb-rng.c
@@ -89,7 +89,7 @@ depth_show(struct device *dev, struct device_attribute *attr, char *buf)
struct histb_rng_priv *priv = dev_get_drvdata(dev);
void __iomem *base = priv->base;
- return sprintf(buf, "%d\n", histb_rng_get_depth(base));
+ return sprintf(buf, "%u\n", histb_rng_get_depth(base));
}
static ssize_t
diff --git a/drivers/char/hw_random/ingenic-rng.c b/drivers/char/hw_random/ingenic-rng.c
index 2f9b6483c4a1..bbfd662d25a6 100644
--- a/drivers/char/hw_random/ingenic-rng.c
+++ b/drivers/char/hw_random/ingenic-rng.c
@@ -132,7 +132,7 @@ MODULE_DEVICE_TABLE(of, ingenic_rng_of_match);
static struct platform_driver ingenic_rng_driver = {
.probe = ingenic_rng_probe,
- .remove_new = ingenic_rng_remove,
+ .remove = ingenic_rng_remove,
.driver = {
.name = "ingenic-rng",
.of_match_table = ingenic_rng_of_match,
diff --git a/drivers/char/hw_random/ks-sa-rng.c b/drivers/char/hw_random/ks-sa-rng.c
index 36c34252b4f6..d8fd8a354482 100644
--- a/drivers/char/hw_random/ks-sa-rng.c
+++ b/drivers/char/hw_random/ks-sa-rng.c
@@ -261,7 +261,7 @@ static struct platform_driver ks_sa_rng_driver = {
.of_match_table = ks_sa_rng_dt_match,
},
.probe = ks_sa_rng_probe,
- .remove_new = ks_sa_rng_remove,
+ .remove = ks_sa_rng_remove,
};
module_platform_driver(ks_sa_rng_driver);
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index f01eb95bee31..e3fcb8bcc29b 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -188,7 +188,7 @@ static struct platform_driver mxc_rnga_driver = {
.of_match_table = mxc_rnga_of_match,
},
.probe = mxc_rnga_probe,
- .remove_new = mxc_rnga_remove,
+ .remove = mxc_rnga_remove,
};
module_platform_driver(mxc_rnga_driver);
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index 1b49e3a86d57..ea6d5599242f 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -858,7 +858,7 @@ static struct platform_driver n2rng_driver = {
.of_match_table = n2rng_match,
},
.probe = n2rng_probe,
- .remove_new = n2rng_remove,
+ .remove = n2rng_remove,
};
module_platform_driver(n2rng_driver);
diff --git a/drivers/char/hw_random/npcm-rng.c b/drivers/char/hw_random/npcm-rng.c
index bce8c4829a1f..9ff00f096f38 100644
--- a/drivers/char/hw_random/npcm-rng.c
+++ b/drivers/char/hw_random/npcm-rng.c
@@ -176,7 +176,7 @@ static struct platform_driver npcm_rng_driver = {
.of_match_table = of_match_ptr(rng_dt_id),
},
.probe = npcm_rng_probe,
- .remove_new = npcm_rng_remove,
+ .remove = npcm_rng_remove,
};
module_platform_driver(npcm_rng_driver);
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 4914a8720e58..5e8b50f15db7 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -558,7 +558,7 @@ static struct platform_driver omap_rng_driver = {
.of_match_table = of_match_ptr(omap_rng_of_match),
},
.probe = omap_rng_probe,
- .remove_new = omap_rng_remove,
+ .remove = omap_rng_remove,
};
module_platform_driver(omap_rng_driver);
diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 9d041a67c295..98edbe796bc5 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -4,6 +4,7 @@
*/
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/hw_random.h>
#include <linux/io.h>
@@ -49,6 +50,7 @@
struct stm32_rng_data {
uint max_clock_rate;
+ uint nb_clock;
u32 cr;
u32 nscr;
u32 htcr;
@@ -72,7 +74,7 @@ struct stm32_rng_private {
struct hwrng rng;
struct device *dev;
void __iomem *base;
- struct clk *clk;
+ struct clk_bulk_data *clk_bulk;
struct reset_control *rst;
struct stm32_rng_config pm_conf;
const struct stm32_rng_data *data;
@@ -266,7 +268,7 @@ static uint stm32_rng_clock_freq_restrain(struct hwrng *rng)
unsigned long clock_rate = 0;
uint clock_div = 0;
- clock_rate = clk_get_rate(priv->clk);
+ clock_rate = clk_get_rate(priv->clk_bulk[0].clk);
/*
* Get the exponent to apply on the CLKDIV field in RNG_CR register
@@ -276,7 +278,7 @@ static uint stm32_rng_clock_freq_restrain(struct hwrng *rng)
while ((clock_rate >> clock_div) > priv->data->max_clock_rate)
clock_div++;
- pr_debug("RNG clk rate : %lu\n", clk_get_rate(priv->clk) >> clock_div);
+ pr_debug("RNG clk rate : %lu\n", clk_get_rate(priv->clk_bulk[0].clk) >> clock_div);
return clock_div;
}
@@ -288,7 +290,7 @@ static int stm32_rng_init(struct hwrng *rng)
int err;
u32 reg;
- err = clk_prepare_enable(priv->clk);
+ err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk);
if (err)
return err;
@@ -328,7 +330,7 @@ static int stm32_rng_init(struct hwrng *rng)
(!(reg & RNG_CR_CONDRST)),
10, 50000);
if (err) {
- clk_disable_unprepare(priv->clk);
+ clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk);
dev_err(priv->dev, "%s: timeout %x!\n", __func__, reg);
return -EINVAL;
}
@@ -356,12 +358,13 @@ static int stm32_rng_init(struct hwrng *rng)
reg & RNG_SR_DRDY,
10, 100000);
if (err || (reg & ~RNG_SR_DRDY)) {
- clk_disable_unprepare(priv->clk);
+ clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk);
dev_err(priv->dev, "%s: timeout:%x SR: %x!\n", __func__, err, reg);
+
return -EINVAL;
}
- clk_disable_unprepare(priv->clk);
+ clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk);
return 0;
}
@@ -379,7 +382,8 @@ static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev)
reg = readl_relaxed(priv->base + RNG_CR);
reg &= ~RNG_CR_RNGEN;
writel_relaxed(reg, priv->base + RNG_CR);
- clk_disable_unprepare(priv->clk);
+
+ clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk);
return 0;
}
@@ -389,7 +393,7 @@ static int __maybe_unused stm32_rng_suspend(struct device *dev)
struct stm32_rng_private *priv = dev_get_drvdata(dev);
int err;
- err = clk_prepare_enable(priv->clk);
+ err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk);
if (err)
return err;
@@ -403,7 +407,7 @@ static int __maybe_unused stm32_rng_suspend(struct device *dev)
writel_relaxed(priv->pm_conf.cr, priv->base + RNG_CR);
- clk_disable_unprepare(priv->clk);
+ clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk);
return 0;
}
@@ -414,7 +418,7 @@ static int __maybe_unused stm32_rng_runtime_resume(struct device *dev)
int err;
u32 reg;
- err = clk_prepare_enable(priv->clk);
+ err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk);
if (err)
return err;
@@ -434,7 +438,7 @@ static int __maybe_unused stm32_rng_resume(struct device *dev)
int err;
u32 reg;
- err = clk_prepare_enable(priv->clk);
+ err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk);
if (err)
return err;
@@ -462,7 +466,7 @@ static int __maybe_unused stm32_rng_resume(struct device *dev)
reg & ~RNG_CR_CONDRST, 10, 100000);
if (err) {
- clk_disable_unprepare(priv->clk);
+ clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk);
dev_err(priv->dev, "%s: timeout:%x CR: %x!\n", __func__, err, reg);
return -EINVAL;
}
@@ -472,7 +476,7 @@ static int __maybe_unused stm32_rng_resume(struct device *dev)
writel_relaxed(reg, priv->base + RNG_CR);
}
- clk_disable_unprepare(priv->clk);
+ clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk);
return 0;
}
@@ -484,9 +488,19 @@ static const struct dev_pm_ops __maybe_unused stm32_rng_pm_ops = {
stm32_rng_resume)
};
+static const struct stm32_rng_data stm32mp25_rng_data = {
+ .has_cond_reset = true,
+ .max_clock_rate = 48000000,
+ .nb_clock = 2,
+ .cr = 0x00F00D00,
+ .nscr = 0x2B5BB,
+ .htcr = 0x969D,
+};
+
static const struct stm32_rng_data stm32mp13_rng_data = {
.has_cond_reset = true,
.max_clock_rate = 48000000,
+ .nb_clock = 1,
.cr = 0x00F00D00,
.nscr = 0x2B5BB,
.htcr = 0x969D,
@@ -494,11 +508,16 @@ static const struct stm32_rng_data stm32mp13_rng_data = {
static const struct stm32_rng_data stm32_rng_data = {
.has_cond_reset = false,
- .max_clock_rate = 3000000,
+ .max_clock_rate = 48000000,
+ .nb_clock = 1,
};
static const struct of_device_id stm32_rng_match[] = {
{
+ .compatible = "st,stm32mp25-rng",
+ .data = &stm32mp25_rng_data,
+ },
+ {
.compatible = "st,stm32mp13-rng",
.data = &stm32mp13_rng_data,
},
@@ -516,6 +535,7 @@ static int stm32_rng_probe(struct platform_device *ofdev)
struct device_node *np = ofdev->dev.of_node;
struct stm32_rng_private *priv;
struct resource *res;
+ int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -525,10 +545,6 @@ static int stm32_rng_probe(struct platform_device *ofdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
- priv->clk = devm_clk_get(&ofdev->dev, NULL);
- if (IS_ERR(priv->clk))
- return PTR_ERR(priv->clk);
-
priv->rst = devm_reset_control_get(&ofdev->dev, NULL);
if (!IS_ERR(priv->rst)) {
reset_control_assert(priv->rst);
@@ -551,6 +567,28 @@ static int stm32_rng_probe(struct platform_device *ofdev)
priv->rng.read = stm32_rng_read;
priv->rng.quality = 900;
+ if (!priv->data->nb_clock || priv->data->nb_clock > 2)
+ return -EINVAL;
+
+ ret = devm_clk_bulk_get_all(dev, &priv->clk_bulk);
+ if (ret != priv->data->nb_clock)
+ return dev_err_probe(dev, -EINVAL, "Failed to get clocks: %d\n", ret);
+
+ if (priv->data->nb_clock == 2) {
+ const char *id = priv->clk_bulk[1].id;
+ struct clk *clk = priv->clk_bulk[1].clk;
+
+ if (!priv->clk_bulk[0].id || !priv->clk_bulk[1].id)
+ return dev_err_probe(dev, -EINVAL, "Missing clock name\n");
+
+ if (strcmp(priv->clk_bulk[0].id, "core")) {
+ priv->clk_bulk[1].id = priv->clk_bulk[0].id;
+ priv->clk_bulk[1].clk = priv->clk_bulk[0].clk;
+ priv->clk_bulk[0].id = id;
+ priv->clk_bulk[0].clk = clk;
+ }
+ }
+
pm_runtime_set_autosuspend_delay(dev, 100);
pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);
@@ -565,7 +603,7 @@ static struct platform_driver stm32_rng_driver = {
.of_match_table = stm32_rng_match,
},
.probe = stm32_rng_probe,
- .remove_new = stm32_rng_remove,
+ .remove = stm32_rng_remove,
};
module_platform_driver(stm32_rng_driver);
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index 65b8260339f5..7174bfccc7b3 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -193,7 +193,7 @@ static struct platform_driver timeriomem_rng_driver = {
.of_match_table = timeriomem_rng_match,
},
.probe = timeriomem_rng_probe,
- .remove_new = timeriomem_rng_remove,
+ .remove = timeriomem_rng_remove,
};
module_platform_driver(timeriomem_rng_driver);
diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c
index 642d13519464..39acaa503fec 100644
--- a/drivers/char/hw_random/xgene-rng.c
+++ b/drivers/char/hw_random/xgene-rng.c
@@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(of, xgene_rng_of_match);
static struct platform_driver xgene_rng_driver = {
.probe = xgene_rng_probe,
- .remove_new = xgene_rng_remove,
+ .remove = xgene_rng_remove,
.driver = {
.name = "xgene-rng",
.of_match_table = xgene_rng_of_match,
diff --git a/drivers/char/powernv-op-panel.c b/drivers/char/powernv-op-panel.c
index f2cff1a6fed5..53467b0a6187 100644
--- a/drivers/char/powernv-op-panel.c
+++ b/drivers/char/powernv-op-panel.c
@@ -213,7 +213,7 @@ static struct platform_driver oppanel_driver = {
.of_match_table = oppanel_match,
},
.probe = oppanel_probe,
- .remove_new = oppanel_remove,
+ .remove = oppanel_remove,
};
module_platform_driver(oppanel_driver);
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 0f8185e541ed..f887569fd3d0 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1467,7 +1467,7 @@ static struct platform_driver sonypi_driver = {
.pm = SONYPI_PM,
},
.probe = sonypi_probe,
- .remove_new = sonypi_remove,
+ .remove = sonypi_remove,
.shutdown = sonypi_shutdown,
};
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index cf0be8a7939d..0fc9a510e059 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -162,7 +162,7 @@ config TCG_NSC
config TCG_ATMEL
tristate "Atmel TPM Interface"
- depends on PPC64 || HAS_IOPORT_MAP
+ depends on HAS_IOPORT_MAP
depends on HAS_IOPORT
help
If you have a TPM security chip from Atmel say Yes and it
diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c
index cad0048bcc3c..e49a19fea3bd 100644
--- a/drivers/char/tpm/tpm-buf.c
+++ b/drivers/char/tpm/tpm-buf.c
@@ -147,6 +147,26 @@ void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
EXPORT_SYMBOL_GPL(tpm_buf_append_u32);
/**
+ * tpm_buf_append_handle() - Add a handle
+ * @chip: &tpm_chip instance
+ * @buf: &tpm_buf instance
+ * @handle: a TPM object handle
+ *
+ * Add a handle to the buffer, and increase the count tracking the number of
+ * handles in the command buffer. Works only for command buffers.
+ */
+void tpm_buf_append_handle(struct tpm_chip *chip, struct tpm_buf *buf, u32 handle)
+{
+ if (buf->flags & TPM_BUF_TPM2B) {
+ dev_err(&chip->dev, "Invalid buffer type (TPM2B)\n");
+ return;
+ }
+
+ tpm_buf_append_u32(buf, handle);
+ buf->handles++;
+}
+
+/**
* tpm_buf_read() - Read from a TPM buffer
* @buf: &tpm_buf instance
* @offset: offset within the buffer
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 1ff99a7091bb..7df7abaf3e52 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -525,10 +525,6 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
- /* Give back zero bytes, as TPM chip has not yet fully resumed: */
- if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
- return 0;
-
return tpm_get_random(chip, data, max);
}
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 8134f002b121..b1daa0d7b341 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -370,6 +370,13 @@ int tpm_pm_suspend(struct device *dev)
if (!chip)
return -ENODEV;
+ rc = tpm_try_get_ops(chip);
+ if (rc) {
+ /* Can be safely set out of locks, as no action cannot race: */
+ chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
+ goto out;
+ }
+
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
goto suspended;
@@ -377,21 +384,19 @@ int tpm_pm_suspend(struct device *dev)
!pm_suspend_via_firmware())
goto suspended;
- rc = tpm_try_get_ops(chip);
- if (!rc) {
- if (chip->flags & TPM_CHIP_FLAG_TPM2) {
- tpm2_end_auth_session(chip);
- tpm2_shutdown(chip, TPM2_SU_STATE);
- } else {
- rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
- }
-
- tpm_put_ops(chip);
+ if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+ tpm2_end_auth_session(chip);
+ tpm2_shutdown(chip, TPM2_SU_STATE);
+ goto suspended;
}
+ rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
+
suspended:
chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
+ tpm_put_ops(chip);
+out:
if (rc)
dev_err(dev, "Ignoring error %d while suspending\n", rc);
return 0;
@@ -440,11 +445,18 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
if (!chip)
return -ENODEV;
+ /* Give back zero bytes, as TPM chip has not yet fully resumed: */
+ if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) {
+ rc = 0;
+ goto out;
+ }
+
if (chip->flags & TPM_CHIP_FLAG_TPM2)
rc = tpm2_get_random(chip, out, max);
else
rc = tpm1_get_random(chip, out, max);
+out:
tpm_put_ops(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 1e856259219e..dfdcbd009720 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -14,6 +14,10 @@
#include "tpm.h"
#include <crypto/hash_info.h>
+static bool disable_pcr_integrity;
+module_param(disable_pcr_integrity, bool, 0444);
+MODULE_PARM_DESC(disable_pcr_integrity, "Disable integrity protection of TPM2_PCR_Extend");
+
static struct tpm2_hash tpm2_hash_map[] = {
{HASH_ALGO_SHA1, TPM_ALG_SHA1},
{HASH_ALGO_SHA256, TPM_ALG_SHA256},
@@ -232,18 +236,26 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
int rc;
int i;
- rc = tpm2_start_auth_session(chip);
- if (rc)
- return rc;
+ if (!disable_pcr_integrity) {
+ rc = tpm2_start_auth_session(chip);
+ if (rc)
+ return rc;
+ }
rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
if (rc) {
- tpm2_end_auth_session(chip);
+ if (!disable_pcr_integrity)
+ tpm2_end_auth_session(chip);
return rc;
}
- tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
- tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
+ if (!disable_pcr_integrity) {
+ tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
+ tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
+ } else {
+ tpm_buf_append_handle(chip, &buf, pcr_idx);
+ tpm_buf_append_auth(chip, &buf, 0, NULL, 0);
+ }
tpm_buf_append_u32(&buf, chip->nr_allocated_banks);
@@ -253,9 +265,11 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
chip->allocated_banks[i].digest_size);
}
- tpm_buf_fill_hmac_session(chip, &buf);
+ if (!disable_pcr_integrity)
+ tpm_buf_fill_hmac_session(chip, &buf);
rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
- rc = tpm_buf_check_hmac_response(chip, &buf, rc);
+ if (!disable_pcr_integrity)
+ rc = tpm_buf_check_hmac_response(chip, &buf, rc);
tpm_buf_destroy(&buf);
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index 0739830904b2..b70165b588ec 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -237,9 +237,7 @@ void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
#endif
if (!tpm2_chip_auth(chip)) {
- tpm_buf_append_u32(buf, handle);
- /* count the number of handles in the upper bits of flags */
- buf->handles++;
+ tpm_buf_append_handle(chip, buf, handle);
return;
}
@@ -272,6 +270,31 @@ void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
}
EXPORT_SYMBOL_GPL(tpm_buf_append_name);
+void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf,
+ u8 attributes, u8 *passphrase, int passphrase_len)
+{
+ /* offset tells us where the sessions area begins */
+ int offset = buf->handles * 4 + TPM_HEADER_SIZE;
+ u32 len = 9 + passphrase_len;
+
+ if (tpm_buf_length(buf) != offset) {
+ /* not the first session so update the existing length */
+ len += get_unaligned_be32(&buf->data[offset]);
+ put_unaligned_be32(len, &buf->data[offset]);
+ } else {
+ tpm_buf_append_u32(buf, len);
+ }
+ /* auth handle */
+ tpm_buf_append_u32(buf, TPM2_RS_PW);
+ /* nonce */
+ tpm_buf_append_u16(buf, 0);
+ /* attributes */
+ tpm_buf_append_u8(buf, 0);
+ /* passphrase */
+ tpm_buf_append_u16(buf, passphrase_len);
+ tpm_buf_append(buf, passphrase, passphrase_len);
+}
+
/**
* tpm_buf_append_hmac_session() - Append a TPM session element
* @chip: the TPM chip structure
@@ -309,26 +332,8 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
#endif
if (!tpm2_chip_auth(chip)) {
- /* offset tells us where the sessions area begins */
- int offset = buf->handles * 4 + TPM_HEADER_SIZE;
- u32 len = 9 + passphrase_len;
-
- if (tpm_buf_length(buf) != offset) {
- /* not the first session so update the existing length */
- len += get_unaligned_be32(&buf->data[offset]);
- put_unaligned_be32(len, &buf->data[offset]);
- } else {
- tpm_buf_append_u32(buf, len);
- }
- /* auth handle */
- tpm_buf_append_u32(buf, TPM2_RS_PW);
- /* nonce */
- tpm_buf_append_u16(buf, 0);
- /* attributes */
- tpm_buf_append_u8(buf, 0);
- /* passphrase */
- tpm_buf_append_u16(buf, passphrase_len);
- tpm_buf_append(buf, passphrase, passphrase_len);
+ tpm_buf_append_auth(chip, buf, attributes, passphrase,
+ passphrase_len);
return;
}
@@ -948,10 +953,13 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
/* Deduce from the name change TPM interference: */
dev_err(&chip->dev, "null key integrity check failed\n");
tpm2_flush_context(chip, tmp_null_key);
- chip->flags |= TPM_CHIP_FLAG_DISABLE;
err:
- return rc ? -ENODEV : 0;
+ if (rc) {
+ chip->flags |= TPM_CHIP_FLAG_DISABLE;
+ rc = -ENODEV;
+ }
+ return rc;
}
/**
@@ -1382,5 +1390,4 @@ int tpm2_sessions_init(struct tpm_chip *chip)
return rc;
}
-EXPORT_SYMBOL(tpm2_sessions_init);
#endif /* CONFIG_TCG_TPM2_HMAC */
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index 9fb2defa9dc4..54a0360a3c95 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -15,7 +15,66 @@
*/
#include "tpm.h"
-#include "tpm_atmel.h"
+
+struct tpm_atmel_priv {
+ int region_size;
+ int have_region;
+ unsigned long base;
+ void __iomem *iobase;
+};
+
+#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + (offset))
+#define atmel_putb(val, chip, offset) \
+ outb(val, atmel_get_priv(chip)->base + (offset))
+#define atmel_request_region request_region
+#define atmel_release_region release_region
+/* Atmel definitions */
+enum tpm_atmel_addr {
+ TPM_ATMEL_BASE_ADDR_LO = 0x08,
+ TPM_ATMEL_BASE_ADDR_HI = 0x09
+};
+
+static inline int tpm_read_index(int base, int index)
+{
+ outb(index, base);
+ return inb(base + 1) & 0xFF;
+}
+
+/* Verify this is a 1.1 Atmel TPM */
+static int atmel_verify_tpm11(void)
+{
+ /* verify that it is an Atmel part */
+ if (tpm_read_index(TPM_ADDR, 4) != 'A' ||
+ tpm_read_index(TPM_ADDR, 5) != 'T' ||
+ tpm_read_index(TPM_ADDR, 6) != 'M' ||
+ tpm_read_index(TPM_ADDR, 7) != 'L')
+ return 1;
+
+ /* query chip for its version number */
+ if (tpm_read_index(TPM_ADDR, 0x00) != 1 ||
+ tpm_read_index(TPM_ADDR, 0x01) != 1)
+ return 1;
+
+ /* This is an atmel supported part */
+ return 0;
+}
+
+/* Determine where to talk to device */
+static void __iomem *atmel_get_base_addr(unsigned long *base, int *region_size)
+{
+ int lo, hi;
+
+ if (atmel_verify_tpm11() != 0)
+ return NULL;
+
+ lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
+ hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
+
+ *base = (hi << 8) | lo;
+ *region_size = 2;
+
+ return ioport_map(*base, *region_size);
+}
/* write status bits */
enum tpm_atmel_write_status {
@@ -142,7 +201,6 @@ static void atml_plat_remove(void)
tpm_chip_unregister(chip);
if (priv->have_region)
atmel_release_region(priv->base, priv->region_size);
- atmel_put_base_addr(priv->iobase);
platform_device_unregister(pdev);
}
@@ -211,7 +269,6 @@ static int __init init_atmel(void)
err_unreg_dev:
platform_device_unregister(pdev);
err_rel_reg:
- atmel_put_base_addr(iobase);
if (have_region)
atmel_release_region(base,
region_size);
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h
deleted file mode 100644
index 7ac3f69dcf0f..000000000000
--- a/drivers/char/tpm/tpm_atmel.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2005 IBM Corporation
- *
- * Authors:
- * Kylene Hall <kjhall@us.ibm.com>
- *
- * Maintained by: <tpmdd-devel@lists.sourceforge.net>
- *
- * Device driver for TCG/TCPA TPM (trusted platform module).
- * Specifications at www.trustedcomputinggroup.org
- *
- * These difference are required on power because the device must be
- * discovered through the device tree and iomap must be used to get
- * around the need for holes in the io_page_mask. This does not happen
- * automatically because the tpm is not a normal pci device and lives
- * under the root node.
- */
-
-struct tpm_atmel_priv {
- int region_size;
- int have_region;
- unsigned long base;
- void __iomem *iobase;
-};
-
-#ifdef CONFIG_PPC64
-
-#include <linux/of.h>
-
-#define atmel_getb(priv, offset) readb(priv->iobase + offset)
-#define atmel_putb(val, priv, offset) writeb(val, priv->iobase + offset)
-#define atmel_request_region request_mem_region
-#define atmel_release_region release_mem_region
-
-static inline void atmel_put_base_addr(void __iomem *iobase)
-{
- iounmap(iobase);
-}
-
-static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
-{
- struct device_node *dn;
- unsigned long address, size;
- const unsigned int *reg;
- int reglen;
- int naddrc;
- int nsizec;
-
- dn = of_find_node_by_name(NULL, "tpm");
-
- if (!dn)
- return NULL;
-
- if (!of_device_is_compatible(dn, "AT97SC3201")) {
- of_node_put(dn);
- return NULL;
- }
-
- reg = of_get_property(dn, "reg", &reglen);
- naddrc = of_n_addr_cells(dn);
- nsizec = of_n_size_cells(dn);
-
- of_node_put(dn);
-
-
- if (naddrc == 2)
- address = ((unsigned long) reg[0] << 32) | reg[1];
- else
- address = reg[0];
-
- if (nsizec == 2)
- size =
- ((unsigned long) reg[naddrc] << 32) | reg[naddrc + 1];
- else
- size = reg[naddrc];
-
- *base = address;
- *region_size = size;
- return ioremap(*base, *region_size);
-}
-#else
-#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + offset)
-#define atmel_putb(val, chip, offset) \
- outb(val, atmel_get_priv(chip)->base + offset)
-#define atmel_request_region request_region
-#define atmel_release_region release_region
-/* Atmel definitions */
-enum tpm_atmel_addr {
- TPM_ATMEL_BASE_ADDR_LO = 0x08,
- TPM_ATMEL_BASE_ADDR_HI = 0x09
-};
-
-static inline int tpm_read_index(int base, int index)
-{
- outb(index, base);
- return inb(base+1) & 0xFF;
-}
-
-/* Verify this is a 1.1 Atmel TPM */
-static int atmel_verify_tpm11(void)
-{
-
- /* verify that it is an Atmel part */
- if (tpm_read_index(TPM_ADDR, 4) != 'A' ||
- tpm_read_index(TPM_ADDR, 5) != 'T' ||
- tpm_read_index(TPM_ADDR, 6) != 'M' ||
- tpm_read_index(TPM_ADDR, 7) != 'L')
- return 1;
-
- /* query chip for its version number */
- if (tpm_read_index(TPM_ADDR, 0x00) != 1 ||
- tpm_read_index(TPM_ADDR, 0x01) != 1)
- return 1;
-
- /* This is an atmel supported part */
- return 0;
-}
-
-static inline void atmel_put_base_addr(void __iomem *iobase)
-{
-}
-
-/* Determine where to talk to device */
-static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
-{
- int lo, hi;
-
- if (atmel_verify_tpm11() != 0)
- return NULL;
-
- lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
- hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
-
- *base = (hi << 8) | lo;
- *region_size = 2;
-
- return ioport_map(*base, *region_size);
-}
-#endif
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index 1e5b107d1f3b..76d048f63d55 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -450,6 +450,7 @@ static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
}
static const struct tpm_class_ops tpm_ibmvtpm = {
+ .flags = TPM_OPS_AUTO_STARTUP,
.recv = tpm_ibmvtpm_recv,
.send = tpm_ibmvtpm_send,
.cancel = tpm_ibmvtpm_cancel,
@@ -690,20 +691,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
if (!strcmp(id->compat, "IBM,vtpm20"))
chip->flags |= TPM_CHIP_FLAG_TPM2;
- rc = tpm_get_timeouts(chip);
- if (rc)
- goto init_irq_cleanup;
-
- if (chip->flags & TPM_CHIP_FLAG_TPM2) {
- rc = tpm2_get_cc_attrs_tbl(chip);
- if (rc)
- goto init_irq_cleanup;
-
- rc = tpm2_sessions_init(chip);
- if (rc)
- goto init_irq_cleanup;
- }
-
return tpm_chip_register(chip);
init_irq_cleanup:
do {
diff --git a/drivers/char/tpm/tpm_tis_i2c_cr50.c b/drivers/char/tpm/tpm_tis_i2c_cr50.c
index adf22992138e..3b55a7b05c46 100644
--- a/drivers/char/tpm/tpm_tis_i2c_cr50.c
+++ b/drivers/char/tpm/tpm_tis_i2c_cr50.c
@@ -17,6 +17,7 @@
*/
#include <linux/acpi.h>
+#include <linux/bug.h>
#include <linux/completion.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@@ -30,11 +31,13 @@
#define TPM_CR50_MAX_BUFSIZE 64
#define TPM_CR50_TIMEOUT_SHORT_MS 2 /* Short timeout during transactions */
#define TPM_CR50_TIMEOUT_NOIRQ_MS 20 /* Timeout for TPM ready without IRQ */
-#define TPM_CR50_I2C_DID_VID 0x00281ae0L /* Device and vendor ID reg value */
-#define TPM_TI50_I2C_DID_VID 0x504a6666L /* Device and vendor ID reg value */
+#define TPM_CR50_I2C_DID_VID 0x00281ae0L /* Device and vendor ID for Cr50 H1 */
+#define TPM_TI50_DT_I2C_DID_VID 0x504a6666L /* Device and vendor ID for Ti50 DT */
+#define TPM_TI50_OT_I2C_DID_VID 0x50666666L /* Device and vendor ID for TI50 OT */
#define TPM_CR50_I2C_MAX_RETRIES 3 /* Max retries due to I2C errors */
#define TPM_CR50_I2C_RETRY_DELAY_LO 55 /* Min usecs between retries on I2C */
#define TPM_CR50_I2C_RETRY_DELAY_HI 65 /* Max usecs between retries on I2C */
+#define TPM_CR50_I2C_DEFAULT_LOC 0
#define TPM_I2C_ACCESS(l) (0x0000 | ((l) << 4))
#define TPM_I2C_STS(l) (0x0001 | ((l) << 4))
@@ -199,8 +202,6 @@ static int tpm_cr50_i2c_read(struct tpm_chip *chip, u8 addr, u8 *buffer, size_t
};
int rc;
- i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
-
/* Prepare for completion interrupt */
tpm_cr50_i2c_enable_tpm_irq(chip);
@@ -219,7 +220,6 @@ static int tpm_cr50_i2c_read(struct tpm_chip *chip, u8 addr, u8 *buffer, size_t
out:
tpm_cr50_i2c_disable_tpm_irq(chip);
- i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (rc < 0)
return rc;
@@ -261,8 +261,6 @@ static int tpm_cr50_i2c_write(struct tpm_chip *chip, u8 addr, u8 *buffer,
priv->buf[0] = addr;
memcpy(priv->buf + 1, buffer, len);
- i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
-
/* Prepare for completion interrupt */
tpm_cr50_i2c_enable_tpm_irq(chip);
@@ -276,7 +274,6 @@ static int tpm_cr50_i2c_write(struct tpm_chip *chip, u8 addr, u8 *buffer,
out:
tpm_cr50_i2c_disable_tpm_irq(chip);
- i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (rc < 0)
return rc;
@@ -285,25 +282,26 @@ out:
}
/**
- * tpm_cr50_check_locality() - Verify TPM locality 0 is active.
+ * tpm_cr50_check_locality() - Verify if required TPM locality is active.
* @chip: A TPM chip.
+ * @loc: Locality to be verified
*
* Return:
- * - 0: Success.
+ * - loc: Success.
* - -errno: A POSIX error code.
*/
-static int tpm_cr50_check_locality(struct tpm_chip *chip)
+static int tpm_cr50_check_locality(struct tpm_chip *chip, int loc)
{
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY;
u8 buf;
int rc;
- rc = tpm_cr50_i2c_read(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
+ rc = tpm_cr50_i2c_read(chip, TPM_I2C_ACCESS(loc), &buf, sizeof(buf));
if (rc < 0)
return rc;
if ((buf & mask) == mask)
- return 0;
+ return loc;
return -EIO;
}
@@ -311,53 +309,72 @@ static int tpm_cr50_check_locality(struct tpm_chip *chip)
/**
* tpm_cr50_release_locality() - Release TPM locality.
* @chip: A TPM chip.
- * @force: Flag to force release if set.
+ * @loc: Locality to be released
+ *
+ * Return:
+ * - 0: Success.
+ * - -errno: A POSIX error code.
*/
-static void tpm_cr50_release_locality(struct tpm_chip *chip, bool force)
+static int tpm_cr50_release_locality(struct tpm_chip *chip, int loc)
{
+ struct i2c_client *client = to_i2c_client(chip->dev.parent);
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_REQUEST_PENDING;
- u8 addr = TPM_I2C_ACCESS(0);
+ u8 addr = TPM_I2C_ACCESS(loc);
u8 buf;
+ int rc;
- if (tpm_cr50_i2c_read(chip, addr, &buf, sizeof(buf)) < 0)
- return;
+ rc = tpm_cr50_i2c_read(chip, addr, &buf, sizeof(buf));
+ if (rc < 0)
+ goto unlock_out;
- if (force || (buf & mask) == mask) {
+ if ((buf & mask) == mask) {
buf = TPM_ACCESS_ACTIVE_LOCALITY;
- tpm_cr50_i2c_write(chip, addr, &buf, sizeof(buf));
+ rc = tpm_cr50_i2c_write(chip, addr, &buf, sizeof(buf));
}
+
+unlock_out:
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
+ return rc;
}
/**
- * tpm_cr50_request_locality() - Request TPM locality 0.
+ * tpm_cr50_request_locality() - Request TPM locality.
* @chip: A TPM chip.
+ * @loc: Locality to be requested.
*
* Return:
- * - 0: Success.
+ * - loc: Success.
* - -errno: A POSIX error code.
*/
-static int tpm_cr50_request_locality(struct tpm_chip *chip)
+static int tpm_cr50_request_locality(struct tpm_chip *chip, int loc)
{
+ struct i2c_client *client = to_i2c_client(chip->dev.parent);
u8 buf = TPM_ACCESS_REQUEST_USE;
unsigned long stop;
int rc;
- if (!tpm_cr50_check_locality(chip))
- return 0;
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
- rc = tpm_cr50_i2c_write(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
+ if (tpm_cr50_check_locality(chip, loc) == loc)
+ return loc;
+
+ rc = tpm_cr50_i2c_write(chip, TPM_I2C_ACCESS(loc), &buf, sizeof(buf));
if (rc < 0)
- return rc;
+ goto unlock_out;
stop = jiffies + chip->timeout_a;
do {
- if (!tpm_cr50_check_locality(chip))
- return 0;
+ if (tpm_cr50_check_locality(chip, loc) == loc)
+ return loc;
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
} while (time_before(jiffies, stop));
- return -ETIMEDOUT;
+ rc = -ETIMEDOUT;
+
+unlock_out:
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
+ return rc;
}
/**
@@ -373,7 +390,7 @@ static u8 tpm_cr50_i2c_tis_status(struct tpm_chip *chip)
{
u8 buf[4];
- if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0)
+ if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf)) < 0)
return 0;
return buf[0];
@@ -389,7 +406,7 @@ static void tpm_cr50_i2c_tis_set_ready(struct tpm_chip *chip)
{
u8 buf[4] = { TPM_STS_COMMAND_READY };
- tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), buf, sizeof(buf));
+ tpm_cr50_i2c_write(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf));
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
}
@@ -419,7 +436,7 @@ static int tpm_cr50_i2c_get_burst_and_status(struct tpm_chip *chip, u8 mask,
stop = jiffies + chip->timeout_b;
do {
- if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0) {
+ if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf)) < 0) {
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
continue;
}
@@ -453,7 +470,7 @@ static int tpm_cr50_i2c_tis_recv(struct tpm_chip *chip, u8 *buf, size_t buf_len)
u8 mask = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
size_t burstcnt, cur, len, expected;
- u8 addr = TPM_I2C_DATA_FIFO(0);
+ u8 addr = TPM_I2C_DATA_FIFO(chip->locality);
u32 status;
int rc;
@@ -515,7 +532,6 @@ static int tpm_cr50_i2c_tis_recv(struct tpm_chip *chip, u8 *buf, size_t buf_len)
goto out_err;
}
- tpm_cr50_release_locality(chip, false);
return cur;
out_err:
@@ -523,7 +539,6 @@ out_err:
if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
tpm_cr50_i2c_tis_set_ready(chip);
- tpm_cr50_release_locality(chip, false);
return rc;
}
@@ -545,10 +560,6 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
u32 status;
int rc;
- rc = tpm_cr50_request_locality(chip);
- if (rc < 0)
- return rc;
-
/* Wait until TPM is ready for a command */
stop = jiffies + chip->timeout_b;
while (!(tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)) {
@@ -577,7 +588,8 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
* that is inserted by tpm_cr50_i2c_write()
*/
limit = min_t(size_t, burstcnt - 1, len);
- rc = tpm_cr50_i2c_write(chip, TPM_I2C_DATA_FIFO(0), &buf[sent], limit);
+ rc = tpm_cr50_i2c_write(chip, TPM_I2C_DATA_FIFO(chip->locality),
+ &buf[sent], limit);
if (rc < 0) {
dev_err(&chip->dev, "Write failed\n");
goto out_err;
@@ -598,7 +610,7 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
}
/* Start the TPM command */
- rc = tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), tpm_go,
+ rc = tpm_cr50_i2c_write(chip, TPM_I2C_STS(chip->locality), tpm_go,
sizeof(tpm_go));
if (rc < 0) {
dev_err(&chip->dev, "Start command failed\n");
@@ -611,7 +623,6 @@ out_err:
if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
tpm_cr50_i2c_tis_set_ready(chip);
- tpm_cr50_release_locality(chip, false);
return rc;
}
@@ -650,6 +661,8 @@ static const struct tpm_class_ops cr50_i2c = {
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
.req_canceled = &tpm_cr50_i2c_req_canceled,
+ .request_locality = &tpm_cr50_request_locality,
+ .relinquish_locality = &tpm_cr50_release_locality,
};
#ifdef CONFIG_ACPI
@@ -669,6 +682,27 @@ MODULE_DEVICE_TABLE(of, of_cr50_i2c_match);
#endif
/**
+ * tpm_cr50_vid_to_name() - Maps VID to name.
+ * @vendor: Vendor identifier to map to name
+ *
+ * Return:
+ * A valid string for the vendor or empty string
+ */
+static const char *tpm_cr50_vid_to_name(u32 vendor)
+{
+ switch (vendor) {
+ case TPM_CR50_I2C_DID_VID:
+ return "cr50";
+ case TPM_TI50_DT_I2C_DID_VID:
+ return "ti50 DT";
+ case TPM_TI50_OT_I2C_DID_VID:
+ return "ti50 OT";
+ default:
+ return "unknown";
+ }
+}
+
+/**
* tpm_cr50_i2c_probe() - Driver probe function.
* @client: I2C client information.
*
@@ -684,6 +718,7 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client)
u32 vendor;
u8 buf[4];
int rc;
+ int loc;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -726,29 +761,37 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client)
TPM_CR50_TIMEOUT_NOIRQ_MS);
}
- rc = tpm_cr50_request_locality(chip);
- if (rc < 0) {
+ loc = tpm_cr50_request_locality(chip, TPM_CR50_I2C_DEFAULT_LOC);
+ if (loc < 0) {
dev_err(dev, "Could not request locality\n");
- return rc;
+ return loc;
}
/* Read four bytes from DID_VID register */
- rc = tpm_cr50_i2c_read(chip, TPM_I2C_DID_VID(0), buf, sizeof(buf));
+ rc = tpm_cr50_i2c_read(chip, TPM_I2C_DID_VID(loc), buf, sizeof(buf));
if (rc < 0) {
dev_err(dev, "Could not read vendor id\n");
- tpm_cr50_release_locality(chip, true);
+ if (tpm_cr50_release_locality(chip, loc))
+ dev_err(dev, "Could not release locality\n");
+ return rc;
+ }
+
+ rc = tpm_cr50_release_locality(chip, loc);
+ if (rc) {
+ dev_err(dev, "Could not release locality\n");
return rc;
}
vendor = le32_to_cpup((__le32 *)buf);
- if (vendor != TPM_CR50_I2C_DID_VID && vendor != TPM_TI50_I2C_DID_VID) {
+ if (vendor != TPM_CR50_I2C_DID_VID &&
+ vendor != TPM_TI50_DT_I2C_DID_VID &&
+ vendor != TPM_TI50_OT_I2C_DID_VID) {
dev_err(dev, "Vendor ID did not match! ID was %08x\n", vendor);
- tpm_cr50_release_locality(chip, true);
return -ENODEV;
}
dev_info(dev, "%s TPM 2.0 (i2c 0x%02x irq %d id 0x%x)\n",
- vendor == TPM_TI50_I2C_DID_VID ? "ti50" : "cr50",
+ tpm_cr50_vid_to_name(vendor),
client->addr, client->irq, vendor >> 16);
return tpm_chip_register(chip);
}
@@ -772,7 +815,6 @@ static void tpm_cr50_i2c_remove(struct i2c_client *client)
}
tpm_chip_unregister(chip);
- tpm_cr50_release_locality(chip, true);
}
static SIMPLE_DEV_PM_OPS(cr50_i2c_pm, tpm_pm_suspend, tpm_pm_resume);
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 4f6c3cb8aa41..34a345dc5e72 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -738,7 +738,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match);
static struct platform_driver hwicap_platform_driver = {
.probe = hwicap_drv_probe,
- .remove_new = hwicap_drv_remove,
+ .remove = hwicap_drv_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = hwicap_of_match,
diff --git a/drivers/char/xillybus/xillybus_of.c b/drivers/char/xillybus/xillybus_of.c
index 8802e2a6fd20..1a1e64133315 100644
--- a/drivers/char/xillybus/xillybus_of.c
+++ b/drivers/char/xillybus/xillybus_of.c
@@ -74,7 +74,7 @@ static void xilly_drv_remove(struct platform_device *op)
static struct platform_driver xillybus_platform_driver = {
.probe = xilly_drv_probe,
- .remove_new = xilly_drv_remove,
+ .remove = xilly_drv_remove,
.driver = {
.name = xillyname,
.of_match_table = xillybus_of_match,
diff --git a/drivers/clk/.kunitconfig b/drivers/clk/.kunitconfig
index 54ece9207055..08e26137f3d9 100644
--- a/drivers/clk/.kunitconfig
+++ b/drivers/clk/.kunitconfig
@@ -1,5 +1,6 @@
CONFIG_KUNIT=y
CONFIG_OF=y
+CONFIG_OF_OVERLAY=y
CONFIG_COMMON_CLK=y
CONFIG_CLK_KUNIT_TEST=y
CONFIG_CLK_FIXED_RATE_KUNIT_TEST=y
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 299bc678ed1b..713573b6c86c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -226,6 +226,17 @@ config COMMON_CLK_EP93XX
help
This driver supports the SoC clocks on the Cirrus Logic ep93xx.
+config COMMON_CLK_EYEQ
+ bool "Clock driver for the Mobileye EyeQ platform"
+ depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST
+ select AUXILIARY_BUS
+ default MACH_EYEQ5 || MACH_EYEQ6H
+ help
+ This driver provides clocks found on Mobileye EyeQ5, EyeQ6L and Eye6H
+ SoCs. Controllers live in shared register regions called OLB. Driver
+ provides read-only PLLs, derived from the main crystal clock (which
+ must be constant). It also exposes some divider clocks.
+
config COMMON_CLK_FSL_FLEXSPI
tristate "Clock driver for FlexSPI on Layerscape SoCs"
depends on ARCH_LAYERSCAPE || COMPILE_TEST
@@ -259,7 +270,7 @@ config COMMON_CLK_LAN966X
tristate "Generic Clock Controller driver for LAN966X SoC"
depends on HAS_IOMEM
depends on OF
- depends on SOC_LAN966 || COMPILE_TEST
+ depends on SOC_LAN966 || ARCH_LAN969X || COMPILE_TEST
help
This driver provides support for Generic Clock Controller(GCK) on
LAN966X SoC. GCK generates and supplies clock to various peripherals
@@ -291,7 +302,7 @@ config CLK_TWL
help
Enable support for controlling the clock resources on TWL family
PMICs. These devices have some 32K clock outputs which can be
- controlled by software. For now, only the TWL6032 clocks are
+ controlled by software. For now, the TWL6032 and TWL6030 clocks are
supported.
config CLK_TWL6040
@@ -342,6 +353,14 @@ config COMMON_CLK_LOCHNAGAR
This driver supports the clocking features of the Cirrus Logic
Lochnagar audio development board.
+config COMMON_CLK_NPCM8XX
+ tristate "Clock driver for the NPCM8XX SoC Family"
+ depends on ARCH_NPCM || COMPILE_TEST
+ help
+ This driver supports the clocks on the Nuvoton BMC NPCM8XX SoC Family,
+ all the clocks are initialized by the bootloader, so this driver
+ allows only reading of current settings directly from the hardware.
+
config COMMON_CLK_LOONGSON2
bool "Clock driver for Loongson-2 SoC"
depends on LOONGARCH || COMPILE_TEST
@@ -517,7 +536,6 @@ config CLK_KUNIT_TEST
tristate "Basic Clock Framework Kunit Tests" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
- select OF_OVERLAY if OF
select DTC
help
Kunit tests for the common clock framework.
@@ -526,7 +544,6 @@ config CLK_FIXED_RATE_KUNIT_TEST
tristate "Basic fixed rate clk type KUnit test" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
- select OF_OVERLAY if OF
select DTC
help
KUnit tests for the basic fixed rate clk type.
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index fb8878a5d7d9..bf4bd45adc3a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -4,6 +4,20 @@ obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o clkdev.o
obj-$(CONFIG_COMMON_CLK) += clk.o
obj-$(CONFIG_CLK_KUNIT_TEST) += clk-test.o
clk-test-y := clk_test.o \
+ kunit_clk_assigned_rates_u64_one.dtbo.o \
+ kunit_clk_assigned_rates_u64_one_consumer.dtbo.o \
+ kunit_clk_assigned_rates_u64_multiple.dtbo.o \
+ kunit_clk_assigned_rates_u64_multiple_consumer.dtbo.o \
+ kunit_clk_assigned_rates_multiple.dtbo.o \
+ kunit_clk_assigned_rates_multiple_consumer.dtbo.o \
+ kunit_clk_assigned_rates_null.dtbo.o \
+ kunit_clk_assigned_rates_null_consumer.dtbo.o \
+ kunit_clk_assigned_rates_one.dtbo.o \
+ kunit_clk_assigned_rates_one_consumer.dtbo.o \
+ kunit_clk_assigned_rates_without.dtbo.o \
+ kunit_clk_assigned_rates_without_consumer.dtbo.o \
+ kunit_clk_assigned_rates_zero.dtbo.o \
+ kunit_clk_assigned_rates_zero_consumer.dtbo.o \
kunit_clk_parent_data_test.dtbo.o
obj-$(CONFIG_COMMON_CLK) += clk-divider.o
obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
@@ -42,6 +56,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
obj-$(CONFIG_COMMON_CLK_EP93XX) += clk-ep93xx.o
obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o
obj-$(CONFIG_COMMON_CLK_EN7523) += clk-en7523.o
+obj-$(CONFIG_COMMON_CLK_EYEQ) += clk-eyeq.o
obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o
obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI) += clk-fsl-flexspi.o
obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o
@@ -62,6 +77,7 @@ obj-$(CONFIG_ARCH_MILBEAUT_M10V) += clk-milbeaut.o
obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NPCM7XX) += clk-npcm7xx.o
+obj-$(CONFIG_COMMON_CLK_NPCM8XX) += clk-npcm8xx.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
obj-$(CONFIG_CLK_LS1028A_PLLDIG) += clk-plldig.o
diff --git a/drivers/clk/clk-apple-nco.c b/drivers/clk/clk-apple-nco.c
index 39472a51530a..457a48d48941 100644
--- a/drivers/clk/clk-apple-nco.c
+++ b/drivers/clk/clk-apple-nco.c
@@ -297,6 +297,9 @@ static int applnco_probe(struct platform_device *pdev)
memset(&init, 0, sizeof(init));
init.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%s-%d", np->name, i);
+ if (!init.name)
+ return -ENOMEM;
+
init.ops = &applnco_ops;
init.parent_data = &pdata;
init.num_parents = 1;
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index bf4d8ddc93ae..934e53a96ddd 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -7,6 +7,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/io.h>
@@ -512,6 +513,7 @@ static int axi_clkgen_probe(struct platform_device *pdev)
struct clk_init_data init;
const char *parent_names[2];
const char *clk_name;
+ struct clk *axi_clk;
unsigned int i;
int ret;
@@ -528,8 +530,24 @@ static int axi_clkgen_probe(struct platform_device *pdev)
return PTR_ERR(axi_clkgen->base);
init.num_parents = of_clk_get_parent_count(pdev->dev.of_node);
- if (init.num_parents < 1 || init.num_parents > 2)
- return -EINVAL;
+
+ axi_clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
+ if (!IS_ERR(axi_clk)) {
+ if (init.num_parents < 2 || init.num_parents > 3)
+ return -EINVAL;
+
+ init.num_parents -= 1;
+ } else {
+ /*
+ * Legacy... So that old DTs which do not have clock-names still
+ * work. In this case we don't explicitly enable the AXI bus
+ * clock.
+ */
+ if (PTR_ERR(axi_clk) != -ENOENT)
+ return PTR_ERR(axi_clk);
+ if (init.num_parents < 1 || init.num_parents > 2)
+ return -EINVAL;
+ }
for (i = 0; i < init.num_parents; i++) {
parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i);
diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
index dd3d42d9ad86..d0705bb03a2a 100644
--- a/drivers/clk/clk-cdce706.c
+++ b/drivers/clk/clk-cdce706.c
@@ -678,7 +678,7 @@ MODULE_DEVICE_TABLE(of, cdce706_dt_match);
#endif
static const struct i2c_device_id cdce706_id[] = {
- { "cdce706", 0 },
+ { "cdce706" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cdce706_id);
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
index e48be7a6c0e2..c51818c1af98 100644
--- a/drivers/clk/clk-cdce925.c
+++ b/drivers/clk/clk-cdce925.c
@@ -601,7 +601,7 @@ static int cdce925_regulator_enable(struct device *dev, const char *name)
/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
* just weird, so just use the single byte mode exclusively. */
-static struct regmap_bus regmap_cdce925_bus = {
+static const struct regmap_bus regmap_cdce925_bus = {
.write = cdce925_regmap_i2c_write,
.read = cdce925_regmap_i2c_read,
};
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 82ae1f26e634..5368d92d9b39 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -218,8 +218,8 @@ static void devm_clk_bulk_release_all_enable(struct device *dev, void *res)
clk_bulk_put_all(devres->num_clks, devres->clks);
}
-int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
- struct clk_bulk_data **clks)
+int __must_check devm_clk_bulk_get_all_enabled(struct device *dev,
+ struct clk_bulk_data **clks)
{
struct clk_bulk_devres *devres;
int ret;
@@ -244,11 +244,12 @@ int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
} else {
clk_bulk_put_all(devres->num_clks, devres->clks);
devres_free(devres);
+ return ret;
}
- return ret;
+ return devres->num_clks;
}
-EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enable);
+EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enabled);
static int devm_clk_match(struct device *dev, void *res, void *data)
{
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index a2c2b5203b0a..c1f426b8a504 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -72,6 +72,8 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
return clk_div_mask(width);
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << clk_div_mask(width);
+ if (flags & CLK_DIVIDER_EVEN_INTEGERS)
+ return 2 * (clk_div_mask(width) + 1);
if (table)
return _get_table_maxdiv(table, width);
return clk_div_mask(width) + 1;
@@ -97,6 +99,8 @@ static unsigned int _get_div(const struct clk_div_table *table,
return 1 << val;
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return val ? val : clk_div_mask(width) + 1;
+ if (flags & CLK_DIVIDER_EVEN_INTEGERS)
+ return 2 * (val + 1);
if (table)
return _get_table_div(table, val);
return val + 1;
@@ -122,6 +126,8 @@ static unsigned int _get_val(const struct clk_div_table *table,
return __ffs(div);
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return (div == clk_div_mask(width) + 1) ? 0 : div;
+ if (flags & CLK_DIVIDER_EVEN_INTEGERS)
+ return (div >> 1) - 1;
if (table)
return _get_table_val(table, div);
return div - 1;
@@ -538,7 +544,8 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
struct device_node *np, const char *name,
const char *parent_name, const struct clk_hw *parent_hw,
const struct clk_parent_data *parent_data, unsigned long flags,
- void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+ void __iomem *reg, u8 shift, u8 width,
+ unsigned long clk_divider_flags,
const struct clk_div_table *table, spinlock_t *lock)
{
struct clk_divider *div;
@@ -610,8 +617,8 @@ EXPORT_SYMBOL_GPL(__clk_hw_register_divider);
struct clk *clk_register_divider_table(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
- u8 clk_divider_flags, const struct clk_div_table *table,
- spinlock_t *lock)
+ unsigned long clk_divider_flags,
+ const struct clk_div_table *table, spinlock_t *lock)
{
struct clk_hw *hw;
@@ -664,7 +671,8 @@ struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
struct device_node *np, const char *name,
const char *parent_name, const struct clk_hw *parent_hw,
const struct clk_parent_data *parent_data, unsigned long flags,
- void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+ void __iomem *reg, u8 shift, u8 width,
+ unsigned long clk_divider_flags,
const struct clk_div_table *table, spinlock_t *lock)
{
struct clk_hw **ptr, *hw;
diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 22fbea61c3dc..e52c5460e927 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -3,8 +3,10 @@
#include <linux/delay.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
+#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/property.h>
+#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include <dt-bindings/clock/en7523-clk.h>
#include <dt-bindings/reset/airoha,en7581-reset.h>
@@ -31,19 +33,14 @@
#define REG_RESET_CONTROL_PCIE1 BIT(27)
#define REG_RESET_CONTROL_PCIE2 BIT(26)
/* EN7581 */
-#define REG_PCIE0_MEM 0x00
-#define REG_PCIE0_MEM_MASK 0x04
-#define REG_PCIE1_MEM 0x08
-#define REG_PCIE1_MEM_MASK 0x0c
-#define REG_PCIE2_MEM 0x10
-#define REG_PCIE2_MEM_MASK 0x14
#define REG_NP_SCU_PCIC 0x88
#define REG_NP_SCU_SSTR 0x9c
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
+#define REG_CRYPTO_CLKSRC2 0x20c
-#define REG_RST_CTRL2 0x00
-#define REG_RST_CTRL1 0x04
+#define REG_RST_CTRL2 0x830
+#define REG_RST_CTRL1 0x834
struct en_clk_desc {
int id;
@@ -79,12 +76,8 @@ struct en_rst_data {
struct en_clk_soc_data {
const struct clk_ops pcie_ops;
- struct {
- const u16 *bank_ofs;
- const u16 *idx_map;
- u16 idx_map_nr;
- } reset;
- int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
+ int (*hw_init)(struct platform_device *pdev,
+ struct clk_hw_onecell_data *clk_data);
};
static const u32 gsw_base[] = { 400000000, 500000000 };
@@ -92,6 +85,10 @@ static const u32 emi_base[] = { 333000000, 400000000 };
static const u32 bus_base[] = { 500000000, 540000000 };
static const u32 slic_base[] = { 100000000, 3125000 };
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
+/* EN7581 */
+static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
+static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
+static const u32 crypto_base[] = { 540000000, 480000000 };
static const struct en_clk_desc en7523_base_clks[] = {
{
@@ -189,6 +186,102 @@ static const struct en_clk_desc en7523_base_clks[] = {
}
};
+static const struct en_clk_desc en7581_base_clks[] = {
+ {
+ .id = EN7523_CLK_GSW,
+ .name = "gsw",
+
+ .base_reg = REG_GSW_CLK_DIV_SEL,
+ .base_bits = 1,
+ .base_shift = 8,
+ .base_values = gsw_base,
+ .n_base_values = ARRAY_SIZE(gsw_base),
+
+ .div_bits = 3,
+ .div_shift = 0,
+ .div_step = 1,
+ .div_offset = 1,
+ }, {
+ .id = EN7523_CLK_EMI,
+ .name = "emi",
+
+ .base_reg = REG_EMI_CLK_DIV_SEL,
+ .base_bits = 2,
+ .base_shift = 8,
+ .base_values = emi7581_base,
+ .n_base_values = ARRAY_SIZE(emi7581_base),
+
+ .div_bits = 3,
+ .div_shift = 0,
+ .div_step = 1,
+ .div_offset = 1,
+ }, {
+ .id = EN7523_CLK_BUS,
+ .name = "bus",
+
+ .base_reg = REG_BUS_CLK_DIV_SEL,
+ .base_bits = 1,
+ .base_shift = 8,
+ .base_values = bus_base,
+ .n_base_values = ARRAY_SIZE(bus_base),
+
+ .div_bits = 3,
+ .div_shift = 0,
+ .div_step = 1,
+ .div_offset = 1,
+ }, {
+ .id = EN7523_CLK_SLIC,
+ .name = "slic",
+
+ .base_reg = REG_SPI_CLK_FREQ_SEL,
+ .base_bits = 1,
+ .base_shift = 0,
+ .base_values = slic_base,
+ .n_base_values = ARRAY_SIZE(slic_base),
+
+ .div_reg = REG_SPI_CLK_DIV_SEL,
+ .div_bits = 5,
+ .div_shift = 24,
+ .div_val0 = 20,
+ .div_step = 2,
+ }, {
+ .id = EN7523_CLK_SPI,
+ .name = "spi",
+
+ .base_reg = REG_SPI_CLK_DIV_SEL,
+
+ .base_value = 400000000,
+
+ .div_bits = 5,
+ .div_shift = 8,
+ .div_val0 = 40,
+ .div_step = 2,
+ }, {
+ .id = EN7523_CLK_NPU,
+ .name = "npu",
+
+ .base_reg = REG_NPU_CLK_DIV_SEL,
+ .base_bits = 2,
+ .base_shift = 8,
+ .base_values = npu7581_base,
+ .n_base_values = ARRAY_SIZE(npu7581_base),
+
+ .div_bits = 3,
+ .div_shift = 0,
+ .div_step = 1,
+ .div_offset = 1,
+ }, {
+ .id = EN7523_CLK_CRYPTO,
+ .name = "crypto",
+
+ .base_reg = REG_CRYPTO_CLKSRC2,
+ .base_bits = 1,
+ .base_shift = 0,
+ .base_values = crypto_base,
+ .n_base_values = ARRAY_SIZE(crypto_base),
+ }
+};
+
static const u16 en7581_rst_ofs[] = {
REG_RST_CTRL2,
REG_RST_CTRL1,
@@ -252,15 +345,11 @@ static const u16 en7581_rst_map[] = {
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
};
-static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
+static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
{
- const struct en_clk_desc *desc = &en7523_base_clks[i];
- u32 val;
-
if (!desc->base_bits)
return desc->base_value;
- val = readl(base + desc->base_reg);
val >>= desc->base_shift;
val &= (1 << desc->base_bits) - 1;
@@ -270,16 +359,11 @@ static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
return desc->base_values[val];
}
-static u32 en7523_get_div(void __iomem *base, int i)
+static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val)
{
- const struct en_clk_desc *desc = &en7523_base_clks[i];
- u32 reg, val;
-
if (!desc->div_bits)
return 1;
- reg = desc->div_reg ? desc->div_reg : desc->base_reg;
- val = readl(base + reg);
val >>= desc->div_shift;
val &= (1 << desc->div_bits) - 1;
@@ -412,44 +496,83 @@ static void en7581_pci_disable(struct clk_hw *hw)
usleep_range(1000, 2000);
}
-static int en7581_clk_hw_init(struct platform_device *pdev,
- void __iomem *np_base)
+static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, void __iomem *np_base)
{
- void __iomem *pb_base;
- u32 val;
+ struct clk_hw *hw;
+ u32 rate;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
+ const struct en_clk_desc *desc = &en7523_base_clks[i];
+ u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+ u32 val = readl(base + desc->base_reg);
- pb_base = devm_platform_ioremap_resource(pdev, 3);
- if (IS_ERR(pb_base))
- return PTR_ERR(pb_base);
+ rate = en7523_get_base_rate(desc, val);
+ val = readl(base + reg);
+ rate /= en7523_get_div(desc, val);
- val = readl(np_base + REG_NP_SCU_SSTR);
- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
- writel(val, np_base + REG_NP_SCU_SSTR);
- val = readl(np_base + REG_NP_SCU_PCIC);
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
+ hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
+ if (IS_ERR(hw)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ desc->name, PTR_ERR(hw));
+ continue;
+ }
+
+ clk_data->hws[desc->id] = hw;
+ }
+
+ hw = en7523_register_pcie_clk(dev, np_base);
+ clk_data->hws[EN7523_CLK_PCIE] = hw;
+
+ clk_data->num = EN7523_NUM_CLOCKS;
+}
+
+static int en7523_clk_hw_init(struct platform_device *pdev,
+ struct clk_hw_onecell_data *clk_data)
+{
+ void __iomem *base, *np_base;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- writel(0x20000000, pb_base + REG_PCIE0_MEM);
- writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
- writel(0x24000000, pb_base + REG_PCIE1_MEM);
- writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
- writel(0x28000000, pb_base + REG_PCIE2_MEM);
- writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
+ np_base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(np_base))
+ return PTR_ERR(np_base);
+
+ en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
return 0;
}
-static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
- void __iomem *base, void __iomem *np_base)
+static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+ struct regmap *map, void __iomem *base)
{
struct clk_hw *hw;
u32 rate;
int i;
- for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
- const struct en_clk_desc *desc = &en7523_base_clks[i];
+ for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
+ const struct en_clk_desc *desc = &en7581_base_clks[i];
+ u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+ int err;
+
+ err = regmap_read(map, desc->base_reg, &val);
+ if (err) {
+ pr_err("Failed reading fixed clk rate %s: %d\n",
+ desc->name, err);
+ continue;
+ }
+ rate = en7523_get_base_rate(desc, val);
- rate = en7523_get_base_rate(base, i);
- rate /= en7523_get_div(base, i);
+ err = regmap_read(map, reg, &val);
+ if (err) {
+ pr_err("Failed reading fixed clk div %s: %d\n",
+ desc->name, err);
+ continue;
+ }
+ rate /= en7523_get_div(desc, val);
hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
if (IS_ERR(hw)) {
@@ -461,7 +584,7 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
clk_data->hws[desc->id] = hw;
}
- hw = en7523_register_pcie_clk(dev, np_base);
+ hw = en7523_register_pcie_clk(dev, base);
clk_data->hws[EN7523_CLK_PCIE] = hw;
clk_data->num = EN7523_NUM_CLOCKS;
@@ -516,38 +639,27 @@ static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
return rst_data->idx_map[reset_spec->args[0]];
}
-static const struct reset_control_ops en7523_reset_ops = {
+static const struct reset_control_ops en7581_reset_ops = {
.assert = en7523_reset_assert,
.deassert = en7523_reset_deassert,
.status = en7523_reset_status,
};
-static int en7523_reset_register(struct platform_device *pdev,
- const struct en_clk_soc_data *soc_data)
+static int en7581_reset_register(struct device *dev, void __iomem *base)
{
- struct device *dev = &pdev->dev;
struct en_rst_data *rst_data;
- void __iomem *base;
-
- /* no reset lines available */
- if (!soc_data->reset.idx_map_nr)
- return 0;
-
- base = devm_platform_ioremap_resource(pdev, 2);
- if (IS_ERR(base))
- return PTR_ERR(base);
rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
if (!rst_data)
return -ENOMEM;
- rst_data->bank_ofs = soc_data->reset.bank_ofs;
- rst_data->idx_map = soc_data->reset.idx_map;
+ rst_data->bank_ofs = en7581_rst_ofs;
+ rst_data->idx_map = en7581_rst_map;
rst_data->base = base;
- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
+ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
rst_data->rcdev.of_xlate = en7523_reset_xlate;
- rst_data->rcdev.ops = &en7523_reset_ops;
+ rst_data->rcdev.ops = &en7581_reset_ops;
rst_data->rcdev.of_node = dev->of_node;
rst_data->rcdev.of_reset_n_cells = 1;
rst_data->rcdev.owner = THIS_MODULE;
@@ -556,28 +668,38 @@ static int en7523_reset_register(struct platform_device *pdev,
return devm_reset_controller_register(dev, &rst_data->rcdev);
}
-static int en7523_clk_probe(struct platform_device *pdev)
+static int en7581_clk_hw_init(struct platform_device *pdev,
+ struct clk_hw_onecell_data *clk_data)
{
- struct device_node *node = pdev->dev.of_node;
- const struct en_clk_soc_data *soc_data;
- struct clk_hw_onecell_data *clk_data;
- void __iomem *base, *np_base;
- int r;
+ struct regmap *map;
+ void __iomem *base;
+ u32 val;
+
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+ if (IS_ERR(map))
+ return PTR_ERR(map);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
- np_base = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(np_base))
- return PTR_ERR(np_base);
+ en7581_register_clocks(&pdev->dev, clk_data, map, base);
- soc_data = device_get_match_data(&pdev->dev);
- if (soc_data->hw_init) {
- r = soc_data->hw_init(pdev, np_base);
- if (r)
- return r;
- }
+ val = readl(base + REG_NP_SCU_SSTR);
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+ writel(val, base + REG_NP_SCU_SSTR);
+ val = readl(base + REG_NP_SCU_PCIC);
+ writel(val | 3, base + REG_NP_SCU_PCIC);
+
+ return en7581_reset_register(&pdev->dev, base);
+}
+
+static int en7523_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ const struct en_clk_soc_data *soc_data;
+ struct clk_hw_onecell_data *clk_data;
+ int r;
clk_data = devm_kzalloc(&pdev->dev,
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
@@ -585,21 +707,12 @@ static int en7523_clk_probe(struct platform_device *pdev)
if (!clk_data)
return -ENOMEM;
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
-
- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+ soc_data = device_get_match_data(&pdev->dev);
+ r = soc_data->hw_init(pdev, clk_data);
if (r)
- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
- pdev->name);
-
- r = en7523_reset_register(pdev, soc_data);
- if (r) {
- of_clk_del_provider(node);
- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
- pdev->name);
- }
+ return r;
- return 0;
+ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
}
static const struct en_clk_soc_data en7523_data = {
@@ -608,6 +721,7 @@ static const struct en_clk_soc_data en7523_data = {
.prepare = en7523_pci_prepare,
.unprepare = en7523_pci_unprepare,
},
+ .hw_init = en7523_clk_hw_init,
};
static const struct en_clk_soc_data en7581_data = {
@@ -616,11 +730,6 @@ static const struct en_clk_soc_data en7581_data = {
.enable = en7581_pci_enable,
.disable = en7581_pci_disable,
},
- .reset = {
- .bank_ofs = en7581_rst_ofs,
- .idx_map = en7581_rst_map,
- .idx_map_nr = ARRAY_SIZE(en7581_rst_map),
- },
.hw_init = en7581_clk_hw_init,
};
diff --git a/drivers/clk/clk-eyeq.c b/drivers/clk/clk-eyeq.c
new file mode 100644
index 000000000000..640c25788487
--- /dev/null
+++ b/drivers/clk/clk-eyeq.c
@@ -0,0 +1,859 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * PLL clock driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms.
+ *
+ * This controller handles:
+ * - Read-only PLLs, all derived from the same main crystal clock.
+ * - It also exposes divider clocks, those are children to PLLs.
+ * - Fixed factor clocks, children to PLLs.
+ *
+ * Parent clock is expected to be constant. This driver's registers live in a
+ * shared region called OLB. Some PLLs and fixed-factors are initialised early
+ * by of_clk_init(); if so, two clk providers are registered.
+ *
+ * We use eqc_ as prefix, as-in "EyeQ Clock", but way shorter.
+ *
+ * Copyright (C) 2024 Mobileye Vision Technologies Ltd.
+ */
+
+/*
+ * Set pr_fmt() for printing from eqc_early_init().
+ * It is called at of_clk_init() stage (read: really early).
+ */
+#define pr_fmt(fmt) "clk-eyeq: " fmt
+
+#include <linux/array_size.h>
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io-64-nonatomic-hi-lo.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
+
+/* In frac mode, it enables fractional noise canceling DAC. Else, no function. */
+#define PCSR0_DAC_EN BIT(0)
+/* Fractional or integer mode */
+#define PCSR0_DSM_EN BIT(1)
+#define PCSR0_PLL_EN BIT(2)
+/* All clocks output held at 0 */
+#define PCSR0_FOUTPOSTDIV_EN BIT(3)
+#define PCSR0_POST_DIV1 GENMASK(6, 4)
+#define PCSR0_POST_DIV2 GENMASK(9, 7)
+#define PCSR0_REF_DIV GENMASK(15, 10)
+#define PCSR0_INTIN GENMASK(27, 16)
+#define PCSR0_BYPASS BIT(28)
+/* Bits 30..29 are reserved */
+#define PCSR0_PLL_LOCKED BIT(31)
+
+#define PCSR1_RESET BIT(0)
+#define PCSR1_SSGC_DIV GENMASK(4, 1)
+/* Spread amplitude (% = 0.1 * SPREAD[4:0]) */
+#define PCSR1_SPREAD GENMASK(9, 5)
+#define PCSR1_DIS_SSCG BIT(10)
+/* Down-spread or center-spread */
+#define PCSR1_DOWN_SPREAD BIT(11)
+#define PCSR1_FRAC_IN GENMASK(31, 12)
+
+struct eqc_pll {
+ unsigned int index;
+ const char *name;
+ unsigned int reg64;
+};
+
+/*
+ * Divider clock. Divider is 2*(v+1), with v the register value.
+ * Min divider is 2, max is 2*(2^width).
+ */
+struct eqc_div {
+ unsigned int index;
+ const char *name;
+ unsigned int parent;
+ unsigned int reg;
+ u8 shift;
+ u8 width;
+};
+
+struct eqc_fixed_factor {
+ unsigned int index;
+ const char *name;
+ unsigned int mult;
+ unsigned int div;
+ unsigned int parent;
+};
+
+struct eqc_match_data {
+ unsigned int pll_count;
+ const struct eqc_pll *plls;
+
+ unsigned int div_count;
+ const struct eqc_div *divs;
+
+ unsigned int fixed_factor_count;
+ const struct eqc_fixed_factor *fixed_factors;
+
+ const char *reset_auxdev_name;
+ const char *pinctrl_auxdev_name;
+
+ unsigned int early_clk_count;
+};
+
+struct eqc_early_match_data {
+ unsigned int early_pll_count;
+ const struct eqc_pll *early_plls;
+
+ unsigned int early_fixed_factor_count;
+ const struct eqc_fixed_factor *early_fixed_factors;
+
+ /*
+ * We want our of_xlate callback to EPROBE_DEFER instead of dev_err()
+ * and EINVAL. For that, we must know the total clock count.
+ */
+ unsigned int late_clk_count;
+};
+
+/*
+ * Both factors (mult and div) must fit in 32 bits. When an operation overflows,
+ * this function throws away low bits so that factors still fit in 32 bits.
+ *
+ * Precision loss depends on amplitude of mult and div. Worst theorical
+ * loss is: (UINT_MAX+1) / UINT_MAX - 1 = 2.3e-10.
+ * This is 1Hz every 4.3GHz.
+ */
+static void eqc_pll_downshift_factors(unsigned long *mult, unsigned long *div)
+{
+ unsigned long biggest;
+ unsigned int shift;
+
+ /* This function can be removed if mult/div switch to unsigned long. */
+ static_assert(sizeof_field(struct clk_fixed_factor, mult) == sizeof(unsigned int));
+ static_assert(sizeof_field(struct clk_fixed_factor, div) == sizeof(unsigned int));
+
+ /* No overflow, nothing to be done. */
+ if (*mult <= UINT_MAX && *div <= UINT_MAX)
+ return;
+
+ /*
+ * Compute the shift required to bring the biggest factor into unsigned
+ * int range. That is, shift its highest set bit to the unsigned int
+ * most significant bit.
+ */
+ biggest = max(*mult, *div);
+ shift = __fls(biggest) - (BITS_PER_BYTE * sizeof(unsigned int)) + 1;
+
+ *mult >>= shift;
+ *div >>= shift;
+}
+
+static int eqc_pll_parse_registers(u32 r0, u32 r1, unsigned long *mult,
+ unsigned long *div, unsigned long *acc)
+{
+ u32 spread;
+
+ if (r0 & PCSR0_BYPASS) {
+ *mult = 1;
+ *div = 1;
+ *acc = 0;
+ return 0;
+ }
+
+ if (!(r0 & PCSR0_PLL_LOCKED))
+ return -EINVAL;
+
+ *mult = FIELD_GET(PCSR0_INTIN, r0);
+ *div = FIELD_GET(PCSR0_REF_DIV, r0);
+ if (r0 & PCSR0_FOUTPOSTDIV_EN)
+ *div *= FIELD_GET(PCSR0_POST_DIV1, r0) * FIELD_GET(PCSR0_POST_DIV2, r0);
+
+ /* Fractional mode, in 2^20 (0x100000) parts. */
+ if (r0 & PCSR0_DSM_EN) {
+ *div *= (1ULL << 20);
+ *mult = *mult * (1ULL << 20) + FIELD_GET(PCSR1_FRAC_IN, r1);
+ }
+
+ if (!*mult || !*div)
+ return -EINVAL;
+
+ if (r1 & (PCSR1_RESET | PCSR1_DIS_SSCG)) {
+ *acc = 0;
+ return 0;
+ }
+
+ /*
+ * Spread spectrum.
+ *
+ * Spread is 1/1000 parts of frequency, accuracy is half of
+ * that. To get accuracy, convert to ppb (parts per billion).
+ *
+ * acc = spread * 1e6 / 2
+ * with acc in parts per billion and,
+ * spread in parts per thousand.
+ */
+ spread = FIELD_GET(PCSR1_SPREAD, r1);
+ *acc = spread * 500000;
+
+ if (r1 & PCSR1_DOWN_SPREAD) {
+ /*
+ * Downspreading: the central frequency is half a
+ * spread lower.
+ */
+ *mult *= 2000 - spread;
+ *div *= 2000;
+
+ /*
+ * Previous operation might overflow 32 bits. If it
+ * does, throw away the least amount of low bits.
+ */
+ eqc_pll_downshift_factors(mult, div);
+ }
+
+ return 0;
+}
+
+static void eqc_probe_init_plls(struct device *dev, const struct eqc_match_data *data,
+ void __iomem *base, struct clk_hw_onecell_data *cells)
+{
+ unsigned long mult, div, acc;
+ const struct eqc_pll *pll;
+ struct clk_hw *hw;
+ unsigned int i;
+ u32 r0, r1;
+ u64 val;
+ int ret;
+
+ for (i = 0; i < data->pll_count; i++) {
+ pll = &data->plls[i];
+
+ val = readq(base + pll->reg64);
+ r0 = val;
+ r1 = val >> 32;
+
+ ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc);
+ if (ret) {
+ dev_warn(dev, "failed parsing state of %s\n", pll->name);
+ cells->hws[pll->index] = ERR_PTR(ret);
+ continue;
+ }
+
+ hw = clk_hw_register_fixed_factor_with_accuracy_fwname(dev,
+ dev->of_node, pll->name, "ref", 0, mult, div, acc);
+ cells->hws[pll->index] = hw;
+ if (IS_ERR(hw))
+ dev_warn(dev, "failed registering %s: %pe\n", pll->name, hw);
+ }
+}
+
+static void eqc_probe_init_divs(struct device *dev, const struct eqc_match_data *data,
+ void __iomem *base, struct clk_hw_onecell_data *cells)
+{
+ struct clk_parent_data parent_data = { };
+ const struct eqc_div *div;
+ struct clk_hw *parent;
+ void __iomem *reg;
+ struct clk_hw *hw;
+ unsigned int i;
+
+ for (i = 0; i < data->div_count; i++) {
+ div = &data->divs[i];
+ reg = base + div->reg;
+ parent = cells->hws[div->parent];
+
+ if (IS_ERR(parent)) {
+ /* Parent is in early clk provider. */
+ parent_data.index = div->parent;
+ parent_data.hw = NULL;
+ } else {
+ /* Avoid clock lookup when we already have the hw reference. */
+ parent_data.index = 0;
+ parent_data.hw = parent;
+ }
+
+ hw = clk_hw_register_divider_table_parent_data(dev, div->name,
+ &parent_data, 0, reg, div->shift, div->width,
+ CLK_DIVIDER_EVEN_INTEGERS, NULL, NULL);
+ cells->hws[div->index] = hw;
+ if (IS_ERR(hw))
+ dev_warn(dev, "failed registering %s: %pe\n",
+ div->name, hw);
+ }
+}
+
+static void eqc_probe_init_fixed_factors(struct device *dev,
+ const struct eqc_match_data *data,
+ struct clk_hw_onecell_data *cells)
+{
+ const struct eqc_fixed_factor *ff;
+ struct clk_hw *hw, *parent_hw;
+ unsigned int i;
+
+ for (i = 0; i < data->fixed_factor_count; i++) {
+ ff = &data->fixed_factors[i];
+ parent_hw = cells->hws[ff->parent];
+
+ if (IS_ERR(parent_hw)) {
+ /* Parent is in early clk provider. */
+ hw = clk_hw_register_fixed_factor_index(dev, ff->name,
+ ff->parent, 0, ff->mult, ff->div);
+ } else {
+ /* Avoid clock lookup when we already have the hw reference. */
+ hw = clk_hw_register_fixed_factor_parent_hw(dev, ff->name,
+ parent_hw, 0, ff->mult, ff->div);
+ }
+
+ cells->hws[ff->index] = hw;
+ if (IS_ERR(hw))
+ dev_warn(dev, "failed registering %s: %pe\n",
+ ff->name, hw);
+ }
+}
+
+static void eqc_auxdev_release(struct device *dev)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(dev);
+
+ kfree(adev);
+}
+
+static int eqc_auxdev_create(struct device *dev, void __iomem *base,
+ const char *name, u32 id)
+{
+ struct auxiliary_device *adev;
+ int ret;
+
+ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+ if (!adev)
+ return -ENOMEM;
+
+ adev->name = name;
+ adev->dev.parent = dev;
+ adev->dev.platform_data = (void __force *)base;
+ adev->dev.release = eqc_auxdev_release;
+ adev->id = id;
+
+ ret = auxiliary_device_init(adev);
+ if (ret)
+ return ret;
+
+ ret = auxiliary_device_add(adev);
+ if (ret)
+ auxiliary_device_uninit(adev);
+
+ return ret;
+}
+
+static int eqc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct eqc_match_data *data;
+ struct clk_hw_onecell_data *cells;
+ unsigned int i, clk_count;
+ struct resource *res;
+ void __iomem *base;
+ int ret;
+
+ data = device_get_match_data(dev);
+ if (!data)
+ return 0; /* No clocks nor auxdevs, we are done. */
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ base = ioremap(res->start, resource_size(res));
+ if (!base)
+ return -ENOMEM;
+
+ /* Init optional reset auxiliary device. */
+ if (data->reset_auxdev_name) {
+ ret = eqc_auxdev_create(dev, base, data->reset_auxdev_name, 0);
+ if (ret)
+ dev_warn(dev, "failed creating auxiliary device %s.%s: %d\n",
+ KBUILD_MODNAME, data->reset_auxdev_name, ret);
+ }
+
+ /* Init optional pinctrl auxiliary device. */
+ if (data->pinctrl_auxdev_name) {
+ ret = eqc_auxdev_create(dev, base, data->pinctrl_auxdev_name, 0);
+ if (ret)
+ dev_warn(dev, "failed creating auxiliary device %s.%s: %d\n",
+ KBUILD_MODNAME, data->pinctrl_auxdev_name, ret);
+ }
+
+ if (data->pll_count + data->div_count + data->fixed_factor_count == 0)
+ return 0; /* Zero clocks, we are done. */
+
+ clk_count = data->pll_count + data->div_count +
+ data->fixed_factor_count + data->early_clk_count;
+ cells = kzalloc(struct_size(cells, hws, clk_count), GFP_KERNEL);
+ if (!cells)
+ return -ENOMEM;
+
+ cells->num = clk_count;
+
+ /* Early PLLs are marked as errors: the early provider will get queried. */
+ for (i = 0; i < clk_count; i++)
+ cells->hws[i] = ERR_PTR(-EINVAL);
+
+ eqc_probe_init_plls(dev, data, base, cells);
+
+ eqc_probe_init_divs(dev, data, base, cells);
+
+ eqc_probe_init_fixed_factors(dev, data, cells);
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, cells);
+}
+
+/* Required early for GIC timer (pll-cpu) and UARTs (pll-per). */
+static const struct eqc_pll eqc_eyeq5_early_plls[] = {
+ { .index = EQ5C_PLL_CPU, .name = "pll-cpu", .reg64 = 0x02C },
+ { .index = EQ5C_PLL_PER, .name = "pll-per", .reg64 = 0x05C },
+};
+
+static const struct eqc_pll eqc_eyeq5_plls[] = {
+ { .index = EQ5C_PLL_VMP, .name = "pll-vmp", .reg64 = 0x034 },
+ { .index = EQ5C_PLL_PMA, .name = "pll-pma", .reg64 = 0x03C },
+ { .index = EQ5C_PLL_VDI, .name = "pll-vdi", .reg64 = 0x044 },
+ { .index = EQ5C_PLL_DDR0, .name = "pll-ddr0", .reg64 = 0x04C },
+ { .index = EQ5C_PLL_PCI, .name = "pll-pci", .reg64 = 0x054 },
+ { .index = EQ5C_PLL_PMAC, .name = "pll-pmac", .reg64 = 0x064 },
+ { .index = EQ5C_PLL_MPC, .name = "pll-mpc", .reg64 = 0x06C },
+ { .index = EQ5C_PLL_DDR1, .name = "pll-ddr1", .reg64 = 0x074 },
+};
+
+enum {
+ /*
+ * EQ5C_PLL_CPU children.
+ * EQ5C_PER_OCC_PCI is the last clock exposed in dt-bindings.
+ */
+ EQ5C_CPU_OCC = EQ5C_PER_OCC_PCI + 1,
+ EQ5C_CPU_SI_CSS0,
+ EQ5C_CPU_CPC,
+ EQ5C_CPU_CM,
+ EQ5C_CPU_MEM,
+ EQ5C_CPU_OCC_ISRAM,
+ EQ5C_CPU_ISRAM,
+ EQ5C_CPU_OCC_DBU,
+ EQ5C_CPU_SI_DBU_TP,
+
+ /*
+ * EQ5C_PLL_VDI children.
+ */
+ EQ5C_VDI_OCC_VDI,
+ EQ5C_VDI_VDI,
+ EQ5C_VDI_OCC_CAN_SER,
+ EQ5C_VDI_CAN_SER,
+ EQ5C_VDI_I2C_SER,
+
+ /*
+ * EQ5C_PLL_PER children.
+ */
+ EQ5C_PER_PERIPH,
+ EQ5C_PER_CAN,
+ EQ5C_PER_TIMER,
+ EQ5C_PER_CCF,
+ EQ5C_PER_OCC_MJPEG,
+ EQ5C_PER_HSM,
+ EQ5C_PER_MJPEG,
+ EQ5C_PER_FCMU_A,
+};
+
+static const struct eqc_fixed_factor eqc_eyeq5_early_fixed_factors[] = {
+ /* EQ5C_PLL_CPU children */
+ { EQ5C_CPU_OCC, "occ-cpu", 1, 1, EQ5C_PLL_CPU },
+ { EQ5C_CPU_SI_CSS0, "si-css0", 1, 1, EQ5C_CPU_OCC },
+ { EQ5C_CPU_CORE0, "core0", 1, 1, EQ5C_CPU_SI_CSS0 },
+ { EQ5C_CPU_CORE1, "core1", 1, 1, EQ5C_CPU_SI_CSS0 },
+ { EQ5C_CPU_CORE2, "core2", 1, 1, EQ5C_CPU_SI_CSS0 },
+ { EQ5C_CPU_CORE3, "core3", 1, 1, EQ5C_CPU_SI_CSS0 },
+
+ /* EQ5C_PLL_PER children */
+ { EQ5C_PER_OCC, "occ-periph", 1, 16, EQ5C_PLL_PER },
+ { EQ5C_PER_UART, "uart", 1, 1, EQ5C_PER_OCC },
+};
+
+static const struct eqc_fixed_factor eqc_eyeq5_fixed_factors[] = {
+ /* EQ5C_PLL_CPU children */
+ { EQ5C_CPU_CPC, "cpc", 1, 1, EQ5C_CPU_SI_CSS0 },
+ { EQ5C_CPU_CM, "cm", 1, 1, EQ5C_CPU_SI_CSS0 },
+ { EQ5C_CPU_MEM, "mem", 1, 1, EQ5C_CPU_SI_CSS0 },
+ { EQ5C_CPU_OCC_ISRAM, "occ-isram", 1, 2, EQ5C_PLL_CPU },
+ { EQ5C_CPU_ISRAM, "isram", 1, 1, EQ5C_CPU_OCC_ISRAM },
+ { EQ5C_CPU_OCC_DBU, "occ-dbu", 1, 10, EQ5C_PLL_CPU },
+ { EQ5C_CPU_SI_DBU_TP, "si-dbu-tp", 1, 1, EQ5C_CPU_OCC_DBU },
+
+ /* EQ5C_PLL_VDI children */
+ { EQ5C_VDI_OCC_VDI, "occ-vdi", 1, 2, EQ5C_PLL_VDI },
+ { EQ5C_VDI_VDI, "vdi", 1, 1, EQ5C_VDI_OCC_VDI },
+ { EQ5C_VDI_OCC_CAN_SER, "occ-can-ser", 1, 16, EQ5C_PLL_VDI },
+ { EQ5C_VDI_CAN_SER, "can-ser", 1, 1, EQ5C_VDI_OCC_CAN_SER },
+ { EQ5C_VDI_I2C_SER, "i2c-ser", 1, 20, EQ5C_PLL_VDI },
+
+ /* EQ5C_PLL_PER children */
+ { EQ5C_PER_PERIPH, "periph", 1, 1, EQ5C_PER_OCC },
+ { EQ5C_PER_CAN, "can", 1, 1, EQ5C_PER_OCC },
+ { EQ5C_PER_SPI, "spi", 1, 1, EQ5C_PER_OCC },
+ { EQ5C_PER_I2C, "i2c", 1, 1, EQ5C_PER_OCC },
+ { EQ5C_PER_TIMER, "timer", 1, 1, EQ5C_PER_OCC },
+ { EQ5C_PER_GPIO, "gpio", 1, 1, EQ5C_PER_OCC },
+ { EQ5C_PER_EMMC, "emmc-sys", 1, 10, EQ5C_PLL_PER },
+ { EQ5C_PER_CCF, "ccf-ctrl", 1, 4, EQ5C_PLL_PER },
+ { EQ5C_PER_OCC_MJPEG, "occ-mjpeg", 1, 2, EQ5C_PLL_PER },
+ { EQ5C_PER_HSM, "hsm", 1, 1, EQ5C_PER_OCC_MJPEG },
+ { EQ5C_PER_MJPEG, "mjpeg", 1, 1, EQ5C_PER_OCC_MJPEG },
+ { EQ5C_PER_FCMU_A, "fcmu-a", 1, 20, EQ5C_PLL_PER },
+ { EQ5C_PER_OCC_PCI, "occ-pci-sys", 1, 8, EQ5C_PLL_PER },
+};
+
+static const struct eqc_div eqc_eyeq5_divs[] = {
+ {
+ .index = EQ5C_DIV_OSPI,
+ .name = "div-ospi",
+ .parent = EQ5C_PLL_PER,
+ .reg = 0x11C,
+ .shift = 0,
+ .width = 4,
+ },
+};
+
+static const struct eqc_early_match_data eqc_eyeq5_early_match_data __initconst = {
+ .early_pll_count = ARRAY_SIZE(eqc_eyeq5_early_plls),
+ .early_plls = eqc_eyeq5_early_plls,
+
+ .early_fixed_factor_count = ARRAY_SIZE(eqc_eyeq5_early_fixed_factors),
+ .early_fixed_factors = eqc_eyeq5_early_fixed_factors,
+
+ .late_clk_count = ARRAY_SIZE(eqc_eyeq5_plls) + ARRAY_SIZE(eqc_eyeq5_divs) +
+ ARRAY_SIZE(eqc_eyeq5_fixed_factors),
+};
+
+static const struct eqc_match_data eqc_eyeq5_match_data = {
+ .pll_count = ARRAY_SIZE(eqc_eyeq5_plls),
+ .plls = eqc_eyeq5_plls,
+
+ .div_count = ARRAY_SIZE(eqc_eyeq5_divs),
+ .divs = eqc_eyeq5_divs,
+
+ .fixed_factor_count = ARRAY_SIZE(eqc_eyeq5_fixed_factors),
+ .fixed_factors = eqc_eyeq5_fixed_factors,
+
+ .reset_auxdev_name = "reset",
+ .pinctrl_auxdev_name = "pinctrl",
+
+ .early_clk_count = ARRAY_SIZE(eqc_eyeq5_early_plls) +
+ ARRAY_SIZE(eqc_eyeq5_early_fixed_factors),
+};
+
+static const struct eqc_pll eqc_eyeq6l_plls[] = {
+ { .index = EQ6LC_PLL_DDR, .name = "pll-ddr", .reg64 = 0x02C },
+ { .index = EQ6LC_PLL_CPU, .name = "pll-cpu", .reg64 = 0x034 }, /* also acc */
+ { .index = EQ6LC_PLL_PER, .name = "pll-per", .reg64 = 0x03C },
+ { .index = EQ6LC_PLL_VDI, .name = "pll-vdi", .reg64 = 0x044 },
+};
+
+static const struct eqc_match_data eqc_eyeq6l_match_data = {
+ .pll_count = ARRAY_SIZE(eqc_eyeq6l_plls),
+ .plls = eqc_eyeq6l_plls,
+
+ .reset_auxdev_name = "reset",
+};
+
+static const struct eqc_match_data eqc_eyeq6h_west_match_data = {
+ .reset_auxdev_name = "reset_west",
+};
+
+static const struct eqc_pll eqc_eyeq6h_east_plls[] = {
+ { .index = 0, .name = "pll-east", .reg64 = 0x074 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_east_match_data = {
+ .pll_count = ARRAY_SIZE(eqc_eyeq6h_east_plls),
+ .plls = eqc_eyeq6h_east_plls,
+
+ .reset_auxdev_name = "reset_east",
+};
+
+static const struct eqc_pll eqc_eyeq6h_south_plls[] = {
+ { .index = EQ6HC_SOUTH_PLL_VDI, .name = "pll-vdi", .reg64 = 0x000 },
+ { .index = EQ6HC_SOUTH_PLL_PCIE, .name = "pll-pcie", .reg64 = 0x008 },
+ { .index = EQ6HC_SOUTH_PLL_PER, .name = "pll-per", .reg64 = 0x010 },
+ { .index = EQ6HC_SOUTH_PLL_ISP, .name = "pll-isp", .reg64 = 0x018 },
+};
+
+static const struct eqc_div eqc_eyeq6h_south_divs[] = {
+ {
+ .index = EQ6HC_SOUTH_DIV_EMMC,
+ .name = "div-emmc",
+ .parent = EQ6HC_SOUTH_PLL_PER,
+ .reg = 0x070,
+ .shift = 4,
+ .width = 4,
+ },
+ {
+ .index = EQ6HC_SOUTH_DIV_OSPI_REF,
+ .name = "div-ospi-ref",
+ .parent = EQ6HC_SOUTH_PLL_PER,
+ .reg = 0x090,
+ .shift = 4,
+ .width = 4,
+ },
+ {
+ .index = EQ6HC_SOUTH_DIV_OSPI_SYS,
+ .name = "div-ospi-sys",
+ .parent = EQ6HC_SOUTH_PLL_PER,
+ .reg = 0x090,
+ .shift = 8,
+ .width = 1,
+ },
+ {
+ .index = EQ6HC_SOUTH_DIV_TSU,
+ .name = "div-tsu",
+ .parent = EQ6HC_SOUTH_PLL_PCIE,
+ .reg = 0x098,
+ .shift = 4,
+ .width = 8,
+ },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_south_match_data = {
+ .pll_count = ARRAY_SIZE(eqc_eyeq6h_south_plls),
+ .plls = eqc_eyeq6h_south_plls,
+
+ .div_count = ARRAY_SIZE(eqc_eyeq6h_south_divs),
+ .divs = eqc_eyeq6h_south_divs,
+};
+
+static const struct eqc_pll eqc_eyeq6h_ddr0_plls[] = {
+ { .index = 0, .name = "pll-ddr0", .reg64 = 0x074 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_ddr0_match_data = {
+ .pll_count = ARRAY_SIZE(eqc_eyeq6h_ddr0_plls),
+ .plls = eqc_eyeq6h_ddr0_plls,
+};
+
+static const struct eqc_pll eqc_eyeq6h_ddr1_plls[] = {
+ { .index = 0, .name = "pll-ddr1", .reg64 = 0x074 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_ddr1_match_data = {
+ .pll_count = ARRAY_SIZE(eqc_eyeq6h_ddr1_plls),
+ .plls = eqc_eyeq6h_ddr1_plls,
+};
+
+static const struct eqc_pll eqc_eyeq6h_acc_plls[] = {
+ { .index = EQ6HC_ACC_PLL_XNN, .name = "pll-xnn", .reg64 = 0x040 },
+ { .index = EQ6HC_ACC_PLL_VMP, .name = "pll-vmp", .reg64 = 0x050 },
+ { .index = EQ6HC_ACC_PLL_PMA, .name = "pll-pma", .reg64 = 0x05C },
+ { .index = EQ6HC_ACC_PLL_MPC, .name = "pll-mpc", .reg64 = 0x068 },
+ { .index = EQ6HC_ACC_PLL_NOC, .name = "pll-noc", .reg64 = 0x070 },
+};
+
+static const struct eqc_match_data eqc_eyeq6h_acc_match_data = {
+ .pll_count = ARRAY_SIZE(eqc_eyeq6h_acc_plls),
+ .plls = eqc_eyeq6h_acc_plls,
+
+ .reset_auxdev_name = "reset_acc",
+};
+
+static const struct of_device_id eqc_match_table[] = {
+ { .compatible = "mobileye,eyeq5-olb", .data = &eqc_eyeq5_match_data },
+ { .compatible = "mobileye,eyeq6l-olb", .data = &eqc_eyeq6l_match_data },
+ { .compatible = "mobileye,eyeq6h-west-olb", .data = &eqc_eyeq6h_west_match_data },
+ { .compatible = "mobileye,eyeq6h-east-olb", .data = &eqc_eyeq6h_east_match_data },
+ { .compatible = "mobileye,eyeq6h-south-olb", .data = &eqc_eyeq6h_south_match_data },
+ { .compatible = "mobileye,eyeq6h-ddr0-olb", .data = &eqc_eyeq6h_ddr0_match_data },
+ { .compatible = "mobileye,eyeq6h-ddr1-olb", .data = &eqc_eyeq6h_ddr1_match_data },
+ { .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqc_eyeq6h_acc_match_data },
+ {}
+};
+
+static struct platform_driver eqc_driver = {
+ .probe = eqc_probe,
+ .driver = {
+ .name = "clk-eyeq",
+ .of_match_table = eqc_match_table,
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(eqc_driver);
+
+/* Required early for GIC timer. */
+static const struct eqc_pll eqc_eyeq6h_central_early_plls[] = {
+ { .index = EQ6HC_CENTRAL_PLL_CPU, .name = "pll-cpu", .reg64 = 0x02C },
+};
+
+static const struct eqc_fixed_factor eqc_eyeq6h_central_early_fixed_factors[] = {
+ { EQ6HC_CENTRAL_CPU_OCC, "occ-cpu", 1, 1, EQ6HC_CENTRAL_PLL_CPU },
+};
+
+static const struct eqc_early_match_data eqc_eyeq6h_central_early_match_data __initconst = {
+ .early_pll_count = ARRAY_SIZE(eqc_eyeq6h_central_early_plls),
+ .early_plls = eqc_eyeq6h_central_early_plls,
+
+ .early_fixed_factor_count = ARRAY_SIZE(eqc_eyeq6h_central_early_fixed_factors),
+ .early_fixed_factors = eqc_eyeq6h_central_early_fixed_factors,
+};
+
+/* Required early for UART. */
+static const struct eqc_pll eqc_eyeq6h_west_early_plls[] = {
+ { .index = EQ6HC_WEST_PLL_PER, .name = "pll-west", .reg64 = 0x074 },
+};
+
+static const struct eqc_fixed_factor eqc_eyeq6h_west_early_fixed_factors[] = {
+ { EQ6HC_WEST_PER_OCC, "west-per-occ", 1, 10, EQ6HC_WEST_PLL_PER },
+ { EQ6HC_WEST_PER_UART, "west-per-uart", 1, 1, EQ6HC_WEST_PER_OCC },
+};
+
+static const struct eqc_early_match_data eqc_eyeq6h_west_early_match_data __initconst = {
+ .early_pll_count = ARRAY_SIZE(eqc_eyeq6h_west_early_plls),
+ .early_plls = eqc_eyeq6h_west_early_plls,
+
+ .early_fixed_factor_count = ARRAY_SIZE(eqc_eyeq6h_west_early_fixed_factors),
+ .early_fixed_factors = eqc_eyeq6h_west_early_fixed_factors,
+};
+
+static void __init eqc_early_init(struct device_node *np,
+ const struct eqc_early_match_data *early_data)
+{
+ struct clk_hw_onecell_data *cells;
+ unsigned int i, clk_count;
+ void __iomem *base;
+ int ret;
+
+ clk_count = early_data->early_pll_count + early_data->early_fixed_factor_count +
+ early_data->late_clk_count;
+ cells = kzalloc(struct_size(cells, hws, clk_count), GFP_KERNEL);
+ if (!cells) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ cells->num = clk_count;
+
+ /*
+ * Mark all clocks as deferred; some are registered here, the rest at
+ * platform device probe.
+ *
+ * Once the platform device is probed, its provider will take priority
+ * when looking up clocks.
+ */
+ for (i = 0; i < clk_count; i++)
+ cells->hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+ /* Offsets (reg64) of early PLLs are relative to OLB block. */
+ base = of_iomap(np, 0);
+ if (!base) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ for (i = 0; i < early_data->early_pll_count; i++) {
+ const struct eqc_pll *pll = &early_data->early_plls[i];
+ unsigned long mult, div, acc;
+ struct clk_hw *hw;
+ u32 r0, r1;
+ u64 val;
+
+ val = readq(base + pll->reg64);
+ r0 = val;
+ r1 = val >> 32;
+
+ ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc);
+ if (ret) {
+ pr_err("failed parsing state of %s\n", pll->name);
+ goto err;
+ }
+
+ hw = clk_hw_register_fixed_factor_with_accuracy_fwname(NULL,
+ np, pll->name, "ref", 0, mult, div, acc);
+ cells->hws[pll->index] = hw;
+ if (IS_ERR(hw)) {
+ pr_err("failed registering %s: %pe\n", pll->name, hw);
+ ret = PTR_ERR(hw);
+ goto err;
+ }
+ }
+
+ for (i = 0; i < early_data->early_fixed_factor_count; i++) {
+ const struct eqc_fixed_factor *ff = &early_data->early_fixed_factors[i];
+ struct clk_hw *parent_hw = cells->hws[ff->parent];
+ struct clk_hw *hw;
+
+ hw = clk_hw_register_fixed_factor_parent_hw(NULL, ff->name,
+ parent_hw, 0, ff->mult, ff->div);
+ cells->hws[ff->index] = hw;
+ if (IS_ERR(hw)) {
+ pr_err("failed registering %s: %pe\n", ff->name, hw);
+ ret = PTR_ERR(hw);
+ goto err;
+ }
+ }
+
+ ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, cells);
+ if (ret) {
+ pr_err("failed registering clk provider: %d\n", ret);
+ goto err;
+ }
+
+ return;
+
+err:
+ /*
+ * We are doomed. The system will not be able to boot.
+ *
+ * Let's still try to be good citizens by freeing resources and print
+ * a last error message that might help debugging.
+ */
+
+ pr_err("failed clk init: %d\n", ret);
+
+ if (cells) {
+ of_clk_del_provider(np);
+
+ for (i = 0; i < early_data->early_pll_count; i++) {
+ const struct eqc_pll *pll = &early_data->early_plls[i];
+ struct clk_hw *hw = cells->hws[pll->index];
+
+ if (!IS_ERR_OR_NULL(hw))
+ clk_hw_unregister_fixed_factor(hw);
+ }
+
+ kfree(cells);
+ }
+}
+
+static void __init eqc_eyeq5_early_init(struct device_node *np)
+{
+ eqc_early_init(np, &eqc_eyeq5_early_match_data);
+}
+CLK_OF_DECLARE_DRIVER(eqc_eyeq5, "mobileye,eyeq5-olb", eqc_eyeq5_early_init);
+
+static void __init eqc_eyeq6h_central_early_init(struct device_node *np)
+{
+ eqc_early_init(np, &eqc_eyeq6h_central_early_match_data);
+}
+CLK_OF_DECLARE_DRIVER(eqc_eyeq6h_central, "mobileye,eyeq6h-central-olb",
+ eqc_eyeq6h_central_early_init);
+
+static void __init eqc_eyeq6h_west_early_init(struct device_node *np)
+{
+ eqc_early_init(np, &eqc_eyeq6h_west_early_match_data);
+}
+CLK_OF_DECLARE_DRIVER(eqc_eyeq6h_west, "mobileye,eyeq6h-west-olb",
+ eqc_eyeq6h_west_early_init);
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index 8fba63fc70c5..e62ae8794d44 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -241,6 +241,17 @@ struct clk_hw *clk_hw_register_fixed_factor_with_accuracy_fwname(struct device *
}
EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_with_accuracy_fwname);
+struct clk_hw *clk_hw_register_fixed_factor_index(struct device *dev,
+ const char *name, unsigned int index, unsigned long flags,
+ unsigned int mult, unsigned int div)
+{
+ const struct clk_parent_data pdata = { .index = index };
+
+ return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, NULL, &pdata,
+ flags, mult, div, 0, 0, false);
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_index);
+
struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div)
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
index 5b114043771d..9099c57e2715 100644
--- a/drivers/clk/clk-gpio.c
+++ b/drivers/clk/clk-gpio.c
@@ -17,13 +17,15 @@
#include <linux/device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
/**
* DOC: basic gpio gated clock which can be enabled and disabled
* with gpio output
* Traits of this clock:
- * prepare - clk_(un)prepare only ensures parent is (un)prepared
- * enable - clk_enable and clk_disable are functional & control gpio
+ * prepare - clk_(un)prepare are functional and control a gpio that can sleep
+ * enable - clk_enable and clk_disable are functional & control
+ * non-sleeping gpio
* rate - inherits rate from parent. No clk_set_rate support
* parent - fixed parent. No clk_set_parent support
*/
@@ -199,7 +201,6 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
struct gpio_desc *gpiod;
struct clk_hw *hw;
bool is_mux;
- int ret;
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
@@ -211,17 +212,9 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
gpio_name = is_mux ? "select" : "enable";
gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW);
- if (IS_ERR(gpiod)) {
- ret = PTR_ERR(gpiod);
- if (ret == -EPROBE_DEFER)
- pr_debug("%pOFn: %s: GPIOs not yet available, retry later\n",
- node, __func__);
- else
- pr_err("%pOFn: %s: Can't get '%s' named GPIO property\n",
- node, __func__,
- gpio_name);
- return ret;
- }
+ if (IS_ERR(gpiod))
+ return dev_err_probe(dev, PTR_ERR(gpiod),
+ "Can't get '%s' named GPIO property\n", gpio_name);
if (is_mux)
hw = clk_hw_register_gpio_mux(dev, gpiod);
@@ -247,3 +240,187 @@ static struct platform_driver gpio_clk_driver = {
},
};
builtin_platform_driver(gpio_clk_driver);
+
+/**
+ * DOC: gated fixed clock, controlled with a gpio output and a regulator
+ * Traits of this clock:
+ * prepare - clk_prepare and clk_unprepare are function & control regulator
+ * optionally a gpio that can sleep
+ * enable - clk_enable and clk_disable are functional & control gpio
+ * rate - rate is fixed and set on clock registration
+ * parent - fixed clock is a root clock and has no parent
+ */
+
+/**
+ * struct clk_gated_fixed - Gateable fixed rate clock
+ * @clk_gpio: instance of clk_gpio for gate-gpio
+ * @supply: supply regulator
+ * @rate: fixed rate
+ */
+struct clk_gated_fixed {
+ struct clk_gpio clk_gpio;
+ struct regulator *supply;
+ unsigned long rate;
+};
+
+#define to_clk_gated_fixed(_clk_gpio) container_of(_clk_gpio, struct clk_gated_fixed, clk_gpio)
+
+static unsigned long clk_gated_fixed_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return to_clk_gated_fixed(to_clk_gpio(hw))->rate;
+}
+
+static int clk_gated_fixed_prepare(struct clk_hw *hw)
+{
+ struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
+
+ if (!clk->supply)
+ return 0;
+
+ return regulator_enable(clk->supply);
+}
+
+static void clk_gated_fixed_unprepare(struct clk_hw *hw)
+{
+ struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
+
+ if (!clk->supply)
+ return;
+
+ regulator_disable(clk->supply);
+}
+
+static int clk_gated_fixed_is_prepared(struct clk_hw *hw)
+{
+ struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw));
+
+ if (!clk->supply)
+ return true;
+
+ return regulator_is_enabled(clk->supply);
+}
+
+/*
+ * Fixed gated clock with non-sleeping gpio.
+ *
+ * Prepare operation turns on the supply regulator
+ * and the enable operation switches the enable-gpio.
+ */
+static const struct clk_ops clk_gated_fixed_ops = {
+ .prepare = clk_gated_fixed_prepare,
+ .unprepare = clk_gated_fixed_unprepare,
+ .is_prepared = clk_gated_fixed_is_prepared,
+ .enable = clk_gpio_gate_enable,
+ .disable = clk_gpio_gate_disable,
+ .is_enabled = clk_gpio_gate_is_enabled,
+ .recalc_rate = clk_gated_fixed_recalc_rate,
+};
+
+static int clk_sleeping_gated_fixed_prepare(struct clk_hw *hw)
+{
+ int ret;
+
+ ret = clk_gated_fixed_prepare(hw);
+ if (ret)
+ return ret;
+
+ ret = clk_sleeping_gpio_gate_prepare(hw);
+ if (ret)
+ clk_gated_fixed_unprepare(hw);
+
+ return ret;
+}
+
+static void clk_sleeping_gated_fixed_unprepare(struct clk_hw *hw)
+{
+ clk_gated_fixed_unprepare(hw);
+ clk_sleeping_gpio_gate_unprepare(hw);
+}
+
+/*
+ * Fixed gated clock with non-sleeping gpio.
+ *
+ * Enabling the supply regulator and switching the enable-gpio happens
+ * both in the prepare step.
+ * is_prepared only needs to check the gpio state, as toggling the
+ * gpio is the last step when preparing.
+ */
+static const struct clk_ops clk_sleeping_gated_fixed_ops = {
+ .prepare = clk_sleeping_gated_fixed_prepare,
+ .unprepare = clk_sleeping_gated_fixed_unprepare,
+ .is_prepared = clk_sleeping_gpio_gate_is_prepared,
+ .recalc_rate = clk_gated_fixed_recalc_rate,
+};
+
+static int clk_gated_fixed_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct clk_gated_fixed *clk;
+ const struct clk_ops *ops;
+ const char *clk_name;
+ u32 rate;
+ int ret;
+
+ clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return -ENOMEM;
+
+ ret = device_property_read_u32(dev, "clock-frequency", &rate);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get clock-frequency\n");
+ clk->rate = rate;
+
+ ret = device_property_read_string(dev, "clock-output-names", &clk_name);
+ if (ret)
+ clk_name = fwnode_get_name(dev->fwnode);
+
+ clk->supply = devm_regulator_get_optional(dev, "vdd");
+ if (IS_ERR(clk->supply)) {
+ if (PTR_ERR(clk->supply) != -ENODEV)
+ return dev_err_probe(dev, PTR_ERR(clk->supply),
+ "Failed to get regulator\n");
+ clk->supply = NULL;
+ }
+
+ clk->clk_gpio.gpiod = devm_gpiod_get_optional(dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(clk->clk_gpio.gpiod))
+ return dev_err_probe(dev, PTR_ERR(clk->clk_gpio.gpiod),
+ "Failed to get gpio\n");
+
+ if (gpiod_cansleep(clk->clk_gpio.gpiod))
+ ops = &clk_sleeping_gated_fixed_ops;
+ else
+ ops = &clk_gated_fixed_ops;
+
+ clk->clk_gpio.hw.init = CLK_HW_INIT_NO_PARENT(clk_name, ops, 0);
+
+ /* register the clock */
+ ret = devm_clk_hw_register(dev, &clk->clk_gpio.hw);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register clock\n");
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ &clk->clk_gpio.hw);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register clock provider\n");
+
+ return 0;
+}
+
+static const struct of_device_id gated_fixed_clk_match_table[] = {
+ { .compatible = "gated-fixed-clock" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver gated_fixed_clk_driver = {
+ .probe = clk_gated_fixed_probe,
+ .driver = {
+ .name = "gated-fixed-clk",
+ .of_match_table = gated_fixed_clk_match_table,
+ },
+};
+builtin_platform_driver(gated_fixed_clk_driver);
diff --git a/drivers/clk/clk-lan966x.c b/drivers/clk/clk-lan966x.c
index 870fd7df50c1..16e0405fe28b 100644
--- a/drivers/clk/clk-lan966x.c
+++ b/drivers/clk/clk-lan966x.c
@@ -24,13 +24,20 @@
#define DIV_MAX 255
-static const char *clk_names[N_CLOCKS] = {
+static const char * const lan966x_clk_names[] = {
"qspi0", "qspi1", "qspi2", "sdmmc0",
"pi", "mcan0", "mcan1", "flexcom0",
"flexcom1", "flexcom2", "flexcom3",
"flexcom4", "timer1", "usb_refclk",
};
+static const char * const lan969x_clk_names[] = {
+ "qspi0", "qspi2", "sdmmc0", "sdmmc1",
+ "mcan0", "mcan1", "flexcom0",
+ "flexcom1", "flexcom2", "flexcom3",
+ "timer1", "usb_refclk",
+};
+
struct lan966x_gck {
struct clk_hw hw;
void __iomem *reg;
@@ -53,7 +60,7 @@ struct clk_gate_soc_desc {
int bit_idx;
};
-static const struct clk_gate_soc_desc clk_gate_desc[] = {
+static const struct clk_gate_soc_desc lan966x_clk_gate_desc[] = {
{ "uhphs", 11 },
{ "udphs", 10 },
{ "mcramc", 9 },
@@ -61,6 +68,37 @@ static const struct clk_gate_soc_desc clk_gate_desc[] = {
{ }
};
+static const struct clk_gate_soc_desc lan969x_clk_gate_desc[] = {
+ { "usb_drd", 10 },
+ { "mcramc", 9 },
+ { "hmatrix", 8 },
+ { }
+};
+
+struct lan966x_match_data {
+ char *name;
+ const char * const *clk_name;
+ const struct clk_gate_soc_desc *clk_gate_desc;
+ u8 num_generic_clks;
+ u8 num_total_clks;
+};
+
+static struct lan966x_match_data lan966x_desc = {
+ .name = "lan966x",
+ .clk_name = lan966x_clk_names,
+ .clk_gate_desc = lan966x_clk_gate_desc,
+ .num_total_clks = 18,
+ .num_generic_clks = 14,
+};
+
+static struct lan966x_match_data lan969x_desc = {
+ .name = "lan969x",
+ .clk_name = lan969x_clk_names,
+ .clk_gate_desc = lan969x_clk_gate_desc,
+ .num_total_clks = 15,
+ .num_generic_clks = 12,
+};
+
static DEFINE_SPINLOCK(clk_gate_lock);
static void __iomem *base;
@@ -186,24 +224,26 @@ static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i)
};
static int lan966x_gate_clk_register(struct device *dev,
+ const struct lan966x_match_data *data,
struct clk_hw_onecell_data *hw_data,
void __iomem *gate_base)
{
- int i;
+ for (int i = data->num_generic_clks; i < data->num_total_clks; ++i) {
+ int idx = i - data->num_generic_clks;
+ const struct clk_gate_soc_desc *desc;
- for (i = GCK_GATE_UHPHS; i < N_CLOCKS; ++i) {
- int idx = i - GCK_GATE_UHPHS;
+ desc = &data->clk_gate_desc[idx];
hw_data->hws[i] =
- devm_clk_hw_register_gate(dev, clk_gate_desc[idx].name,
- "lan966x", 0, gate_base,
- clk_gate_desc[idx].bit_idx,
+ devm_clk_hw_register_gate(dev, desc->name,
+ data->name, 0, gate_base,
+ desc->bit_idx,
0, &clk_gate_lock);
if (IS_ERR(hw_data->hws[i]))
return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]),
"failed to register %s clock\n",
- clk_gate_desc[idx].name);
+ desc->name);
}
return 0;
@@ -211,13 +251,18 @@ static int lan966x_gate_clk_register(struct device *dev,
static int lan966x_clk_probe(struct platform_device *pdev)
{
+ const struct lan966x_match_data *data;
struct clk_hw_onecell_data *hw_data;
struct device *dev = &pdev->dev;
void __iomem *gate_base;
struct resource *res;
int i, ret;
- hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, N_CLOCKS),
+ data = device_get_match_data(dev);
+ if (!data)
+ return -EINVAL;
+
+ hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, data->num_total_clks),
GFP_KERNEL);
if (!hw_data)
return -ENOMEM;
@@ -228,10 +273,10 @@ static int lan966x_clk_probe(struct platform_device *pdev)
init.ops = &lan966x_gck_ops;
- hw_data->num = GCK_GATE_UHPHS;
+ hw_data->num = data->num_generic_clks;
- for (i = 0; i < GCK_GATE_UHPHS; i++) {
- init.name = clk_names[i];
+ for (i = 0; i < data->num_generic_clks; i++) {
+ init.name = data->clk_name[i];
hw_data->hws[i] = lan966x_gck_clk_register(dev, i);
if (IS_ERR(hw_data->hws[i])) {
dev_err(dev, "failed to register %s clock\n",
@@ -246,9 +291,9 @@ static int lan966x_clk_probe(struct platform_device *pdev)
if (IS_ERR(gate_base))
return PTR_ERR(gate_base);
- hw_data->num = N_CLOCKS;
+ hw_data->num = data->num_total_clks;
- ret = lan966x_gate_clk_register(dev, hw_data, gate_base);
+ ret = lan966x_gate_clk_register(dev, data, hw_data, gate_base);
if (ret)
return ret;
}
@@ -257,7 +302,8 @@ static int lan966x_clk_probe(struct platform_device *pdev)
}
static const struct of_device_id lan966x_clk_dt_ids[] = {
- { .compatible = "microchip,lan966x-gck", },
+ { .compatible = "microchip,lan966x-gck", .data = &lan966x_desc },
+ { .compatible = "microchip,lan9691-gck", .data = &lan969x_desc },
{ }
};
MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids);
diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c
index 820bb1e9e3b7..7082b4309c6f 100644
--- a/drivers/clk/clk-loongson2.c
+++ b/drivers/clk/clk-loongson2.c
@@ -29,8 +29,10 @@ enum loongson2_clk_type {
struct loongson2_clk_provider {
void __iomem *base;
struct device *dev;
- struct clk_hw_onecell_data clk_data;
spinlock_t clk_lock; /* protect access to DIV registers */
+
+ /* Must be last --ends in a flexible-array member. */
+ struct clk_hw_onecell_data clk_data;
};
struct loongson2_clk_data {
@@ -304,7 +306,7 @@ static int loongson2_clk_probe(struct platform_device *pdev)
return PTR_ERR(clp->base);
spin_lock_init(&clp->clk_lock);
- clp->clk_data.num = clks_num + 1;
+ clp->clk_data.num = clks_num;
clp->dev = dev;
for (i = 0; i < clks_num; i++) {
diff --git a/drivers/clk/clk-npcm8xx.c b/drivers/clk/clk-npcm8xx.c
new file mode 100644
index 000000000000..2138c011411d
--- /dev/null
+++ b/drivers/clk/clk-npcm8xx.c
@@ -0,0 +1,430 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Nuvoton NPCM8xx Clock Generator
+ * All the clocks are initialized by the bootloader, so this driver allows only
+ * reading of current settings directly from the hardware.
+ *
+ * Copyright (C) 2020 Nuvoton Technologies
+ * Author: Tomer Maimon <tomer.maimon@nuvoton.com>
+ */
+
+#define pr_fmt(fmt) "npcm8xx_clk: " fmt
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/nuvoton,npcm845-clk.h>
+#include <soc/nuvoton/clock-npcm8xx.h>
+
+/* npcm8xx clock registers*/
+#define NPCM8XX_CLKSEL 0x04
+#define NPCM8XX_CLKDIV1 0x08
+#define NPCM8XX_CLKDIV2 0x2C
+#define NPCM8XX_CLKDIV3 0x58
+#define NPCM8XX_CLKDIV4 0x7C
+#define NPCM8XX_PLLCON0 0x0C
+#define NPCM8XX_PLLCON1 0x10
+#define NPCM8XX_PLLCON2 0x54
+#define NPCM8XX_PLLCONG 0x60
+#define NPCM8XX_THRTL_CNT 0xC0
+
+#define PLLCON_LOKI BIT(31)
+#define PLLCON_LOKS BIT(30)
+#define PLLCON_FBDV GENMASK(27, 16)
+#define PLLCON_OTDV2 GENMASK(15, 13)
+#define PLLCON_PWDEN BIT(12)
+#define PLLCON_OTDV1 GENMASK(10, 8)
+#define PLLCON_INDV GENMASK(5, 0)
+
+static void __iomem *clk_base;
+
+struct npcm8xx_clk_pll {
+ void __iomem *pllcon;
+ unsigned int id;
+ const char *name;
+ unsigned long flags;
+ struct clk_hw hw;
+};
+
+#define to_npcm8xx_clk_pll(_hw) container_of(_hw, struct npcm8xx_clk_pll, hw)
+
+struct npcm8xx_clk_pll_data {
+ const char *name;
+ struct clk_parent_data parent;
+ unsigned int reg;
+ unsigned long flags;
+ struct clk_hw hw;
+};
+
+struct npcm8xx_clk_div_data {
+ u32 reg;
+ u8 shift;
+ u8 width;
+ const char *name;
+ const struct clk_hw *parent_hw;
+ unsigned long clk_divider_flags;
+ unsigned long flags;
+ int onecell_idx;
+ struct clk_hw hw;
+};
+
+struct npcm8xx_clk_mux_data {
+ u8 shift;
+ u32 mask;
+ const u32 *table;
+ const char *name;
+ const struct clk_parent_data *parent_data;
+ u8 num_parents;
+ unsigned long flags;
+ struct clk_hw hw;
+};
+
+static struct clk_hw hw_pll1_div2, hw_pll2_div2, hw_gfx_div2, hw_pre_clk;
+static struct npcm8xx_clk_pll_data npcm8xx_pll_clks[] = {
+ { "pll0", { .index = 0 }, NPCM8XX_PLLCON0, 0 },
+ { "pll1", { .index = 0 }, NPCM8XX_PLLCON1, 0 },
+ { "pll2", { .index = 0 }, NPCM8XX_PLLCON2, 0 },
+ { "pll_gfx", { .index = 0 }, NPCM8XX_PLLCONG, 0 },
+};
+
+static const u32 cpuck_mux_table[] = { 0, 1, 2, 7 };
+static const struct clk_parent_data cpuck_mux_parents[] = {
+ { .hw = &npcm8xx_pll_clks[0].hw },
+ { .hw = &npcm8xx_pll_clks[1].hw },
+ { .index = 0 },
+ { .hw = &npcm8xx_pll_clks[2].hw }
+};
+
+static const u32 pixcksel_mux_table[] = { 0, 2 };
+static const struct clk_parent_data pixcksel_mux_parents[] = {
+ { .hw = &npcm8xx_pll_clks[3].hw },
+ { .index = 0 }
+};
+
+static const u32 default_mux_table[] = { 0, 1, 2, 3 };
+static const struct clk_parent_data default_mux_parents[] = {
+ { .hw = &npcm8xx_pll_clks[0].hw },
+ { .hw = &npcm8xx_pll_clks[1].hw },
+ { .index = 0 },
+ { .hw = &hw_pll2_div2 }
+};
+
+static const u32 sucksel_mux_table[] = { 2, 3 };
+static const struct clk_parent_data sucksel_mux_parents[] = {
+ { .index = 0 },
+ { .hw = &hw_pll2_div2 }
+};
+
+static const u32 mccksel_mux_table[] = { 0, 2 };
+static const struct clk_parent_data mccksel_mux_parents[] = {
+ { .hw = &hw_pll1_div2 },
+ { .index = 0 }
+};
+
+static const u32 clkoutsel_mux_table[] = { 0, 1, 2, 3, 4 };
+static const struct clk_parent_data clkoutsel_mux_parents[] = {
+ { .hw = &npcm8xx_pll_clks[0].hw },
+ { .hw = &npcm8xx_pll_clks[1].hw },
+ { .index = 0 },
+ { .hw = &hw_gfx_div2 },
+ { .hw = &hw_pll2_div2 }
+};
+
+static const u32 gfxmsel_mux_table[] = { 2, 3 };
+static const struct clk_parent_data gfxmsel_mux_parents[] = {
+ { .index = 0 },
+ { .hw = &npcm8xx_pll_clks[2].hw }
+};
+
+static const u32 dvcssel_mux_table[] = { 2, 3 };
+static const struct clk_parent_data dvcssel_mux_parents[] = {
+ { .index = 0 },
+ { .hw = &npcm8xx_pll_clks[2].hw }
+};
+
+static const u32 default3_mux_table[] = { 0, 1, 2 };
+static const struct clk_parent_data default3_mux_parents[] = {
+ { .hw = &npcm8xx_pll_clks[0].hw },
+ { .hw = &npcm8xx_pll_clks[1].hw },
+ { .index = 0 }
+};
+
+static struct npcm8xx_clk_mux_data npcm8xx_muxes[] = {
+ { 0, 3, cpuck_mux_table, "cpu_mux", cpuck_mux_parents,
+ ARRAY_SIZE(cpuck_mux_parents), CLK_IS_CRITICAL },
+ { 4, 2, pixcksel_mux_table, "gfx_pixel_mux", pixcksel_mux_parents,
+ ARRAY_SIZE(pixcksel_mux_parents), 0 },
+ { 6, 2, default_mux_table, "sd_mux", default_mux_parents,
+ ARRAY_SIZE(default_mux_parents), 0 },
+ { 8, 2, default_mux_table, "uart_mux", default_mux_parents,
+ ARRAY_SIZE(default_mux_parents), 0 },
+ { 10, 2, sucksel_mux_table, "serial_usb_mux", sucksel_mux_parents,
+ ARRAY_SIZE(sucksel_mux_parents), 0 },
+ { 12, 2, mccksel_mux_table, "mc_mux", mccksel_mux_parents,
+ ARRAY_SIZE(mccksel_mux_parents), 0 },
+ { 14, 2, default_mux_table, "adc_mux", default_mux_parents,
+ ARRAY_SIZE(default_mux_parents), 0 },
+ { 16, 2, default_mux_table, "gfx_mux", default_mux_parents,
+ ARRAY_SIZE(default_mux_parents), 0 },
+ { 18, 3, clkoutsel_mux_table, "clkout_mux", clkoutsel_mux_parents,
+ ARRAY_SIZE(clkoutsel_mux_parents), 0 },
+ { 21, 2, gfxmsel_mux_table, "gfxm_mux", gfxmsel_mux_parents,
+ ARRAY_SIZE(gfxmsel_mux_parents), 0 },
+ { 23, 2, dvcssel_mux_table, "dvc_mux", dvcssel_mux_parents,
+ ARRAY_SIZE(dvcssel_mux_parents), 0 },
+ { 25, 2, default3_mux_table, "rg_mux", default3_mux_parents,
+ ARRAY_SIZE(default3_mux_parents), 0 },
+ { 27, 2, default3_mux_table, "rcp_mux", default3_mux_parents,
+ ARRAY_SIZE(default3_mux_parents), 0 },
+};
+
+/* configurable pre dividers: */
+static struct npcm8xx_clk_div_data npcm8xx_pre_divs[] = {
+ { NPCM8XX_CLKDIV1, 21, 5, "pre_adc", &npcm8xx_muxes[6].hw, CLK_DIVIDER_READ_ONLY, 0, -1 },
+ { NPCM8XX_CLKDIV1, 26, 2, "ahb", &hw_pre_clk, CLK_DIVIDER_READ_ONLY, CLK_IS_CRITICAL, NPCM8XX_CLK_AHB },
+};
+
+/* configurable dividers: */
+static struct npcm8xx_clk_div_data npcm8xx_divs[] = {
+ { NPCM8XX_CLKDIV1, 28, 3, "adc", &npcm8xx_pre_divs[0].hw, CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0, NPCM8XX_CLK_ADC },
+ { NPCM8XX_CLKDIV1, 16, 5, "uart", &npcm8xx_muxes[3].hw, 0, 0, NPCM8XX_CLK_UART },
+ { NPCM8XX_CLKDIV1, 11, 5, "mmc", &npcm8xx_muxes[2].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_MMC },
+ { NPCM8XX_CLKDIV1, 6, 5, "spi3", &npcm8xx_pre_divs[1].hw, 0, 0, NPCM8XX_CLK_SPI3 },
+ { NPCM8XX_CLKDIV1, 2, 4, "pci", &npcm8xx_muxes[7].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_PCI },
+
+ { NPCM8XX_CLKDIV2, 30, 2, "apb4", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0, NPCM8XX_CLK_APB4 },
+ { NPCM8XX_CLKDIV2, 28, 2, "apb3", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0, NPCM8XX_CLK_APB3 },
+ { NPCM8XX_CLKDIV2, 26, 2, "apb2", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0, NPCM8XX_CLK_APB2 },
+ { NPCM8XX_CLKDIV2, 24, 2, "apb1", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0, NPCM8XX_CLK_APB1 },
+ { NPCM8XX_CLKDIV2, 22, 2, "apb5", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0, NPCM8XX_CLK_APB5 },
+ { NPCM8XX_CLKDIV2, 16, 5, "clkout", &npcm8xx_muxes[8].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_CLKOUT },
+ { NPCM8XX_CLKDIV2, 13, 3, "gfx", &npcm8xx_muxes[7].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_GFX },
+ { NPCM8XX_CLKDIV2, 8, 5, "usb_bridge", &npcm8xx_muxes[4].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_SU },
+ { NPCM8XX_CLKDIV2, 4, 4, "usb_host", &npcm8xx_muxes[4].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_SU48 },
+ { NPCM8XX_CLKDIV2, 0, 4, "sdhc", &npcm8xx_muxes[2].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_SDHC },
+
+ { NPCM8XX_CLKDIV3, 16, 8, "spi1", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_SPI1 },
+ { NPCM8XX_CLKDIV3, 11, 5, "uart2", &npcm8xx_muxes[3].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_UART2 },
+ { NPCM8XX_CLKDIV3, 6, 5, "spi0", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_SPI0 },
+ { NPCM8XX_CLKDIV3, 1, 5, "spix", &npcm8xx_pre_divs[1].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_SPIX },
+
+ { NPCM8XX_CLKDIV4, 28, 4, "rg", &npcm8xx_muxes[11].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_RG },
+ { NPCM8XX_CLKDIV4, 12, 4, "rcp", &npcm8xx_muxes[12].hw, CLK_DIVIDER_READ_ONLY, 0, NPCM8XX_CLK_RCP },
+
+ { NPCM8XX_THRTL_CNT, 0, 2, "th", &npcm8xx_muxes[0].hw, CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0, NPCM8XX_CLK_TH },
+};
+
+static unsigned long npcm8xx_clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct npcm8xx_clk_pll *pll = to_npcm8xx_clk_pll(hw);
+ unsigned long fbdv, indv, otdv1, otdv2;
+ unsigned int val;
+ u64 ret;
+
+ if (parent_rate == 0) {
+ pr_debug("%s: parent rate is zero\n", __func__);
+ return 0;
+ }
+
+ val = readl_relaxed(pll->pllcon);
+
+ indv = FIELD_GET(PLLCON_INDV, val);
+ fbdv = FIELD_GET(PLLCON_FBDV, val);
+ otdv1 = FIELD_GET(PLLCON_OTDV1, val);
+ otdv2 = FIELD_GET(PLLCON_OTDV2, val);
+
+ ret = (u64)parent_rate * fbdv;
+ do_div(ret, indv * otdv1 * otdv2);
+
+ return ret;
+}
+
+static const struct clk_ops npcm8xx_clk_pll_ops = {
+ .recalc_rate = npcm8xx_clk_pll_recalc_rate,
+};
+
+static struct clk_hw *
+npcm8xx_clk_register_pll(struct device *dev, void __iomem *pllcon,
+ const char *name, const struct clk_parent_data *parent,
+ unsigned long flags)
+{
+ struct npcm8xx_clk_pll *pll;
+ struct clk_init_data init = {};
+ int ret;
+
+ pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &npcm8xx_clk_pll_ops;
+ init.parent_data = parent;
+ init.num_parents = 1;
+ init.flags = flags;
+
+ pll->pllcon = pllcon;
+ pll->hw.init = &init;
+
+ ret = devm_clk_hw_register(dev, &pll->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &pll->hw;
+}
+
+static DEFINE_SPINLOCK(npcm8xx_clk_lock);
+
+static int npcm8xx_clk_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct npcm_clock_adev *rdev = to_npcm_clock_adev(adev);
+ struct clk_hw_onecell_data *npcm8xx_clk_data;
+ struct device *dev = &adev->dev;
+ struct clk_hw *hw;
+ unsigned int i;
+
+ npcm8xx_clk_data = devm_kzalloc(dev, struct_size(npcm8xx_clk_data, hws,
+ NPCM8XX_NUM_CLOCKS),
+ GFP_KERNEL);
+ if (!npcm8xx_clk_data)
+ return -ENOMEM;
+
+ clk_base = rdev->base;
+
+ npcm8xx_clk_data->num = NPCM8XX_NUM_CLOCKS;
+
+ for (i = 0; i < NPCM8XX_NUM_CLOCKS; i++)
+ npcm8xx_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+ /* Register plls */
+ for (i = 0; i < ARRAY_SIZE(npcm8xx_pll_clks); i++) {
+ struct npcm8xx_clk_pll_data *pll_clk = &npcm8xx_pll_clks[i];
+
+ hw = npcm8xx_clk_register_pll(dev, clk_base + pll_clk->reg,
+ pll_clk->name, &pll_clk->parent,
+ pll_clk->flags);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register pll\n");
+ pll_clk->hw = *hw;
+ }
+
+ /* Register fixed dividers */
+ hw = devm_clk_hw_register_fixed_factor(dev, "pll1_div2", "pll1", 0, 1, 2);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register fixed div\n");
+ hw_pll1_div2 = *hw;
+
+ hw = devm_clk_hw_register_fixed_factor(dev, "pll2_div2", "pll2", 0, 1, 2);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register pll2 div2\n");
+ hw_pll2_div2 = *hw;
+
+ hw = devm_clk_hw_register_fixed_factor(dev, "pll_gfx_div2", "pll_gfx", 0, 1, 2);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register gfx div2\n");
+ hw_gfx_div2 = *hw;
+
+ /* Register muxes */
+ for (i = 0; i < ARRAY_SIZE(npcm8xx_muxes); i++) {
+ struct npcm8xx_clk_mux_data *mux_data = &npcm8xx_muxes[i];
+
+ hw = devm_clk_hw_register_mux_parent_data_table(dev,
+ mux_data->name,
+ mux_data->parent_data,
+ mux_data->num_parents,
+ mux_data->flags,
+ clk_base + NPCM8XX_CLKSEL,
+ mux_data->shift,
+ mux_data->mask,
+ 0,
+ mux_data->table,
+ &npcm8xx_clk_lock);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register mux\n");
+ mux_data->hw = *hw;
+ }
+
+ hw = devm_clk_hw_register_fixed_factor(dev, "pre_clk", "cpu_mux", 0, 1, 2);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register pre clk div2\n");
+ hw_pre_clk = *hw;
+
+ hw = devm_clk_hw_register_fixed_factor(dev, "axi", "th", 0, 1, 2);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register axi div2\n");
+ npcm8xx_clk_data->hws[NPCM8XX_CLK_AXI] = hw;
+
+ hw = devm_clk_hw_register_fixed_factor(dev, "atb", "axi", 0, 1, 2);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register atb div2\n");
+ npcm8xx_clk_data->hws[NPCM8XX_CLK_ATB] = hw;
+
+ /* Register pre dividers */
+ for (i = 0; i < ARRAY_SIZE(npcm8xx_pre_divs); i++) {
+ struct npcm8xx_clk_div_data *div_data = &npcm8xx_pre_divs[i];
+
+ hw = devm_clk_hw_register_divider_parent_hw(dev, div_data->name,
+ div_data->parent_hw,
+ div_data->flags,
+ clk_base + div_data->reg,
+ div_data->shift,
+ div_data->width,
+ div_data->clk_divider_flags,
+ &npcm8xx_clk_lock);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register pre div\n");
+ div_data->hw = *hw;
+
+ if (div_data->onecell_idx >= 0)
+ npcm8xx_clk_data->hws[div_data->onecell_idx] = hw;
+ }
+
+ /* Register dividers */
+ for (i = 0; i < ARRAY_SIZE(npcm8xx_divs); i++) {
+ struct npcm8xx_clk_div_data *div_data = &npcm8xx_divs[i];
+
+ hw = devm_clk_hw_register_divider_parent_hw(dev, div_data->name,
+ div_data->parent_hw,
+ div_data->flags,
+ clk_base + div_data->reg,
+ div_data->shift,
+ div_data->width,
+ div_data->clk_divider_flags,
+ &npcm8xx_clk_lock);
+ if (IS_ERR(hw))
+ return dev_err_probe(dev, PTR_ERR(hw), "Can't register div\n");
+
+ if (div_data->onecell_idx >= 0)
+ npcm8xx_clk_data->hws[div_data->onecell_idx] = hw;
+ }
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ npcm8xx_clk_data);
+}
+
+static const struct auxiliary_device_id npcm8xx_clock_ids[] = {
+ {
+ .name = "reset_npcm.clk-npcm8xx",
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(auxiliary, npcm8xx_clock_ids);
+
+static struct auxiliary_driver npcm8xx_clock_driver = {
+ .probe = npcm8xx_clk_probe,
+ .id_table = npcm8xx_clock_ids,
+};
+module_auxiliary_driver(npcm8xx_clock_driver);
+
+MODULE_DESCRIPTION("Clock driver for Nuvoton NPCM8XX BMC SoC");
+MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 4dcde305944c..a560edeb4b55 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -9,6 +9,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <dt-bindings/clock/fsl,qoriq-clockgen.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
@@ -1065,11 +1066,8 @@ static void __init _clockgen_init(struct device_node *np, bool legacy);
static void __init legacy_init_clockgen(struct device_node *np)
{
if (!clockgen.node) {
- struct device_node *parent_np;
-
- parent_np = of_get_parent(np);
+ struct device_node *parent_np __free(device_node) = of_get_parent(np);
_clockgen_init(parent_np, true);
- of_node_put(parent_np);
}
}
diff --git a/drivers/clk/clk-si514.c b/drivers/clk/clk-si514.c
index 6ee148e5469d..1127c35ce57d 100644
--- a/drivers/clk/clk-si514.c
+++ b/drivers/clk/clk-si514.c
@@ -371,7 +371,7 @@ static int si514_probe(struct i2c_client *client)
}
static const struct i2c_device_id si514_id[] = {
- { "si514", 0 },
+ { "si514" },
{ }
};
MODULE_DEVICE_TABLE(i2c, si514_id);
diff --git a/drivers/clk/clk-twl.c b/drivers/clk/clk-twl.c
index eab9d3c8ed8a..20bc3bf8fd62 100644
--- a/drivers/clk/clk-twl.c
+++ b/drivers/clk/clk-twl.c
@@ -11,13 +11,29 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#define VREG_STATE 2
+#define VREG_STATE 2
+#define VREG_GRP 0
#define TWL6030_CFG_STATE_OFF 0x00
#define TWL6030_CFG_STATE_ON 0x01
#define TWL6030_CFG_STATE_MASK 0x03
+#define TWL6030_CFG_STATE_GRP_SHIFT 5
+#define TWL6030_CFG_STATE_APP_SHIFT 2
+#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
+#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
+ TWL6030_CFG_STATE_APP_SHIFT)
+#define P1_GRP BIT(0) /* processor power group */
+#define P2_GRP BIT(1)
+#define P3_GRP BIT(2)
+#define ALL_GRP (P1_GRP | P2_GRP | P3_GRP)
+
+enum twl_type {
+ TWL_TYPE_6030,
+ TWL_TYPE_6032,
+};
struct twl_clock_info {
struct device *dev;
+ enum twl_type type;
u8 base;
struct clk_hw hw;
};
@@ -56,14 +72,21 @@ static unsigned long twl_clks_recalc_rate(struct clk_hw *hw,
static int twl6032_clks_prepare(struct clk_hw *hw)
{
struct twl_clock_info *cinfo = to_twl_clks_info(hw);
- int ret;
- ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
- TWL6030_CFG_STATE_ON);
- if (ret < 0)
- dev_err(cinfo->dev, "clk prepare failed\n");
+ if (cinfo->type == TWL_TYPE_6030) {
+ int grp;
+
+ grp = twlclk_read(cinfo, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+ if (grp < 0)
+ return grp;
- return ret;
+ return twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ grp << TWL6030_CFG_STATE_GRP_SHIFT |
+ TWL6030_CFG_STATE_ON);
+ }
+
+ return twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ TWL6030_CFG_STATE_ON);
}
static void twl6032_clks_unprepare(struct clk_hw *hw)
@@ -71,32 +94,21 @@ static void twl6032_clks_unprepare(struct clk_hw *hw)
struct twl_clock_info *cinfo = to_twl_clks_info(hw);
int ret;
- ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
- TWL6030_CFG_STATE_OFF);
+ if (cinfo->type == TWL_TYPE_6030)
+ ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ ALL_GRP << TWL6030_CFG_STATE_GRP_SHIFT |
+ TWL6030_CFG_STATE_OFF);
+ else
+ ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+ TWL6030_CFG_STATE_OFF);
+
if (ret < 0)
dev_err(cinfo->dev, "clk unprepare failed\n");
}
-static int twl6032_clks_is_prepared(struct clk_hw *hw)
-{
- struct twl_clock_info *cinfo = to_twl_clks_info(hw);
- int val;
-
- val = twlclk_read(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE);
- if (val < 0) {
- dev_err(cinfo->dev, "clk read failed\n");
- return val;
- }
-
- val &= TWL6030_CFG_STATE_MASK;
-
- return val == TWL6030_CFG_STATE_ON;
-}
-
static const struct clk_ops twl6032_clks_ops = {
.prepare = twl6032_clks_prepare,
.unprepare = twl6032_clks_unprepare,
- .is_prepared = twl6032_clks_is_prepared,
.recalc_rate = twl_clks_recalc_rate,
};
@@ -155,6 +167,7 @@ static int twl_clks_probe(struct platform_device *pdev)
for (i = 0; i < count; i++) {
cinfo[i].base = hw_data[i].base;
cinfo[i].dev = &pdev->dev;
+ cinfo[i].type = platform_get_device_id(pdev)->driver_data;
cinfo[i].hw.init = &hw_data[i].init;
ret = devm_clk_hw_register(&pdev->dev, &cinfo[i].hw);
if (ret) {
@@ -176,7 +189,11 @@ static int twl_clks_probe(struct platform_device *pdev)
static const struct platform_device_id twl_clks_id[] = {
{
+ .name = "twl6030-clk",
+ .driver_data = TWL_TYPE_6030,
+ }, {
.name = "twl6032-clk",
+ .driver_data = TWL_TYPE_6032,
}, {
/* sentinel */
}
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d02451f951cf..bdc6e5b90da5 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -608,12 +608,6 @@ bool clk_hw_is_prepared(const struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(clk_hw_is_prepared);
-bool clk_hw_rate_is_protected(const struct clk_hw *hw)
-{
- return clk_core_rate_is_protected(hw->core);
-}
-EXPORT_SYMBOL_GPL(clk_hw_rate_is_protected);
-
bool clk_hw_is_enabled(const struct clk_hw *hw)
{
return clk_core_is_enabled(hw->core);
@@ -2536,7 +2530,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
rate = clk_core_req_round_rate_nolock(core, req_rate);
/* bail early if nothing to do */
- if (rate == clk_core_get_rate_nolock(core))
+ if (rate == clk_core_get_rate_recalc(core))
return 0;
/* fail on a direct rate set of a protected provider */
diff --git a/drivers/clk/clk_kunit_helpers.c b/drivers/clk/clk_kunit_helpers.c
index 52fd25594c96..68a28e70bb61 100644
--- a/drivers/clk/clk_kunit_helpers.c
+++ b/drivers/clk/clk_kunit_helpers.c
@@ -203,5 +203,35 @@ int of_clk_hw_register_kunit(struct kunit *test, struct device_node *node, struc
}
EXPORT_SYMBOL_GPL(of_clk_hw_register_kunit);
+KUNIT_DEFINE_ACTION_WRAPPER(of_clk_del_provider_wrapper,
+ of_clk_del_provider, struct device_node *);
+
+/**
+ * of_clk_add_hw_provider_kunit() - Test managed of_clk_add_hw_provider()
+ * @test: The test context
+ * @np: Device node pointer associated with clock provider
+ * @get: Callback for decoding clk_hw
+ * @data: Context pointer for @get callback.
+ *
+ * Just like of_clk_add_hw_provider(), except the clk_hw provider is managed by
+ * the test case and is automatically unregistered after the test case
+ * concludes.
+ *
+ * Return: 0 on success or a negative errno value on failure.
+ */
+int of_clk_add_hw_provider_kunit(struct kunit *test, struct device_node *np,
+ struct clk_hw *(*get)(struct of_phandle_args *clkspec, void *data),
+ void *data)
+{
+ int ret;
+
+ ret = of_clk_add_hw_provider(np, get, data);
+ if (ret)
+ return ret;
+
+ return kunit_add_action_or_reset(test, of_clk_del_provider_wrapper, np);
+}
+EXPORT_SYMBOL_GPL(of_clk_add_hw_provider_kunit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("KUnit helpers for clk providers and consumers");
diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
index aa3ddcfc00eb..f08feeaa3750 100644
--- a/drivers/clk/clk_test.c
+++ b/drivers/clk/clk_test.c
@@ -4,6 +4,7 @@
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/clk/clk-conf.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -15,6 +16,7 @@
#include <kunit/platform_device.h>
#include <kunit/test.h>
+#include "kunit_clk_assigned_rates.h"
#include "clk_parent_data_test.h"
static const struct clk_ops empty_clk_ops = { };
@@ -3075,7 +3077,326 @@ static struct kunit_suite clk_register_clk_parent_data_device_suite = {
.test_cases = clk_register_clk_parent_data_device_test_cases,
};
+struct clk_assigned_rates_context {
+ struct clk_dummy_context clk0;
+ struct clk_dummy_context clk1;
+};
+
+/*
+ * struct clk_assigned_rates_test_param - Test parameters for clk_assigned_rates test
+ * @desc: Test description
+ * @overlay_begin: Pointer to start of DT overlay to apply for test
+ * @overlay_end: Pointer to end of DT overlay to apply for test
+ * @rate0: Initial rate of first clk
+ * @rate1: Initial rate of second clk
+ * @consumer_test: true if a consumer is being tested
+ */
+struct clk_assigned_rates_test_param {
+ const char *desc;
+ u8 *overlay_begin;
+ u8 *overlay_end;
+ unsigned long rate0;
+ unsigned long rate1;
+ bool consumer_test;
+};
+
+#define TEST_PARAM_OVERLAY(overlay_name) \
+ .overlay_begin = of_overlay_begin(overlay_name), \
+ .overlay_end = of_overlay_end(overlay_name)
+
+static void
+clk_assigned_rates_register_clk(struct kunit *test,
+ struct clk_dummy_context *ctx,
+ struct device_node *np, const char *name,
+ unsigned long rate)
+{
+ struct clk_init_data init = { };
+
+ init.name = name;
+ init.ops = &clk_dummy_rate_ops;
+ ctx->hw.init = &init;
+ ctx->rate = rate;
+
+ KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, np, &ctx->hw));
+ KUNIT_ASSERT_EQ(test, ctx->rate, rate);
+}
+
+/*
+ * Does most of the work of the test:
+ *
+ * 1. Apply the overlay to test
+ * 2. Register the clk or clks to test
+ * 3. Register the clk provider
+ * 4. Apply clk defaults to the consumer device if this is a consumer test
+ *
+ * The tests will set different test_param values to test different scenarios
+ * and validate that in their test functions.
+ */
+static int clk_assigned_rates_test_init(struct kunit *test)
+{
+ struct device_node *np, *consumer;
+ struct clk_hw_onecell_data *data;
+ struct clk_assigned_rates_context *ctx;
+ u32 clk_cells;
+ const struct clk_assigned_rates_test_param *test_param;
+
+ test_param = test->param_value;
+
+ KUNIT_ASSERT_EQ(test, 0, __of_overlay_apply_kunit(test,
+ test_param->overlay_begin,
+ test_param->overlay_end));
+
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
+ ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL));
+ test->priv = ctx;
+
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
+ np = of_find_compatible_node(NULL, NULL, "test,clk-assigned-rates"));
+ of_node_put_kunit(test, np);
+
+ KUNIT_ASSERT_EQ(test, 0, of_property_read_u32(np, "#clock-cells", &clk_cells));
+ /* Only support #clock-cells = <0> or <1> */
+ KUNIT_ASSERT_LT(test, clk_cells, 2);
+
+ clk_assigned_rates_register_clk(test, &ctx->clk0, np,
+ "test_assigned_rate0", test_param->rate0);
+ if (clk_cells == 0) {
+ KUNIT_ASSERT_EQ(test, 0,
+ of_clk_add_hw_provider_kunit(test, np, of_clk_hw_simple_get,
+ &ctx->clk0.hw));
+ } else if (clk_cells == 1) {
+ clk_assigned_rates_register_clk(test, &ctx->clk1, np,
+ "test_assigned_rate1", test_param->rate1);
+
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
+ data = kunit_kzalloc(test, struct_size(data, hws, 2), GFP_KERNEL));
+ data->num = 2;
+ data->hws[0] = &ctx->clk0.hw;
+ data->hws[1] = &ctx->clk1.hw;
+
+ KUNIT_ASSERT_EQ(test, 0,
+ of_clk_add_hw_provider_kunit(test, np, of_clk_hw_onecell_get, data));
+ }
+
+ /* Consumers are optional */
+ if (test_param->consumer_test) {
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
+ consumer = of_find_compatible_node(NULL, NULL, "test,clk-consumer"));
+ of_node_put_kunit(test, consumer);
+
+ KUNIT_ASSERT_EQ(test, 0, of_clk_set_defaults(consumer, false));
+ }
+
+ return 0;
+}
+
+static void clk_assigned_rates_assigns_one(struct kunit *test)
+{
+ struct clk_assigned_rates_context *ctx = test->priv;
+
+ KUNIT_EXPECT_EQ(test, ctx->clk0.rate, ASSIGNED_RATES_0_RATE);
+}
+
+static void clk_assigned_rates_assigns_multiple(struct kunit *test)
+{
+ struct clk_assigned_rates_context *ctx = test->priv;
+
+ KUNIT_EXPECT_EQ(test, ctx->clk0.rate, ASSIGNED_RATES_0_RATE);
+ KUNIT_EXPECT_EQ(test, ctx->clk1.rate, ASSIGNED_RATES_1_RATE);
+}
+
+static void clk_assigned_rates_skips(struct kunit *test)
+{
+ struct clk_assigned_rates_context *ctx = test->priv;
+ const struct clk_assigned_rates_test_param *test_param = test->param_value;
+
+ KUNIT_EXPECT_NE(test, ctx->clk0.rate, ASSIGNED_RATES_0_RATE);
+ KUNIT_EXPECT_EQ(test, ctx->clk0.rate, test_param->rate0);
+}
+
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_one);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_one_consumer);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_one);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_one_consumer);
+
+/* Test cases that assign one rate */
+static const struct clk_assigned_rates_test_param clk_assigned_rates_assigns_one_test_params[] = {
+ {
+ /*
+ * Test that a single cell assigned-clock-rates property
+ * assigns the rate when the property is in the provider.
+ */
+ .desc = "provider assigns",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_one),
+ },
+ {
+ /*
+ * Test that a single cell assigned-clock-rates property
+ * assigns the rate when the property is in the consumer.
+ */
+ .desc = "consumer assigns",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_one_consumer),
+ .consumer_test = true,
+ },
+ {
+ /*
+ * Test that a single cell assigned-clock-rates-u64 property
+ * assigns the rate when the property is in the provider.
+ */
+ .desc = "provider assigns u64",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_one),
+ },
+ {
+ /*
+ * Test that a single cell assigned-clock-rates-u64 property
+ * assigns the rate when the property is in the consumer.
+ */
+ .desc = "consumer assigns u64",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_one_consumer),
+ .consumer_test = true,
+ },
+};
+KUNIT_ARRAY_PARAM_DESC(clk_assigned_rates_assigns_one,
+ clk_assigned_rates_assigns_one_test_params, desc)
+
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_multiple);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_multiple_consumer);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_multiple);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_u64_multiple_consumer);
+
+/* Test cases that assign multiple rates */
+static const struct clk_assigned_rates_test_param clk_assigned_rates_assigns_multiple_test_params[] = {
+ {
+ /*
+ * Test that a multiple cell assigned-clock-rates property
+ * assigns the rates when the property is in the provider.
+ */
+ .desc = "provider assigns",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_multiple),
+ },
+ {
+ /*
+ * Test that a multiple cell assigned-clock-rates property
+ * assigns the rates when the property is in the consumer.
+ */
+ .desc = "consumer assigns",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_multiple_consumer),
+ .consumer_test = true,
+ },
+ {
+ /*
+ * Test that a single cell assigned-clock-rates-u64 property
+ * assigns the rate when the property is in the provider.
+ */
+ .desc = "provider assigns u64",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_multiple),
+ },
+ {
+ /*
+ * Test that a multiple cell assigned-clock-rates-u64 property
+ * assigns the rates when the property is in the consumer.
+ */
+ .desc = "consumer assigns u64",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_u64_multiple_consumer),
+ .consumer_test = true,
+ },
+};
+KUNIT_ARRAY_PARAM_DESC(clk_assigned_rates_assigns_multiple,
+ clk_assigned_rates_assigns_multiple_test_params,
+ desc)
+
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_without);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_without_consumer);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_zero);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_zero_consumer);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_null);
+OF_OVERLAY_DECLARE(kunit_clk_assigned_rates_null_consumer);
+
+/* Test cases that skip changing the rate due to malformed DT */
+static const struct clk_assigned_rates_test_param clk_assigned_rates_skips_test_params[] = {
+ {
+ /*
+ * Test that an assigned-clock-rates property without an assigned-clocks
+ * property fails when the property is in the provider.
+ */
+ .desc = "provider missing assigned-clocks",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_without),
+ .rate0 = 3000,
+ },
+ {
+ /*
+ * Test that an assigned-clock-rates property without an assigned-clocks
+ * property fails when the property is in the consumer.
+ */
+ .desc = "consumer missing assigned-clocks",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_without_consumer),
+ .rate0 = 3000,
+ .consumer_test = true,
+ },
+ {
+ /*
+ * Test that an assigned-clock-rates property of zero doesn't
+ * set a rate when the property is in the provider.
+ */
+ .desc = "provider assigned-clock-rates of zero",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_zero),
+ .rate0 = 3000,
+ },
+ {
+ /*
+ * Test that an assigned-clock-rates property of zero doesn't
+ * set a rate when the property is in the consumer.
+ */
+ .desc = "consumer assigned-clock-rates of zero",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_zero_consumer),
+ .rate0 = 3000,
+ .consumer_test = true,
+ },
+ {
+ /*
+ * Test that an assigned-clocks property with a null phandle
+ * doesn't set a rate when the property is in the provider.
+ */
+ .desc = "provider assigned-clocks null phandle",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_null),
+ .rate0 = 3000,
+ },
+ {
+ /*
+ * Test that an assigned-clocks property with a null phandle
+ * doesn't set a rate when the property is in the consumer.
+ */
+ .desc = "provider assigned-clocks null phandle",
+ TEST_PARAM_OVERLAY(kunit_clk_assigned_rates_null_consumer),
+ .rate0 = 3000,
+ .consumer_test = true,
+ },
+};
+KUNIT_ARRAY_PARAM_DESC(clk_assigned_rates_skips,
+ clk_assigned_rates_skips_test_params,
+ desc)
+
+static struct kunit_case clk_assigned_rates_test_cases[] = {
+ KUNIT_CASE_PARAM(clk_assigned_rates_assigns_one,
+ clk_assigned_rates_assigns_one_gen_params),
+ KUNIT_CASE_PARAM(clk_assigned_rates_assigns_multiple,
+ clk_assigned_rates_assigns_multiple_gen_params),
+ KUNIT_CASE_PARAM(clk_assigned_rates_skips,
+ clk_assigned_rates_skips_gen_params),
+ {}
+};
+
+/*
+ * Test suite for assigned-clock-rates{-u64} DT property.
+ */
+static struct kunit_suite clk_assigned_rates_suite = {
+ .name = "clk_assigned_rates",
+ .test_cases = clk_assigned_rates_test_cases,
+ .init = clk_assigned_rates_test_init,
+};
+
kunit_test_suites(
+ &clk_assigned_rates_suite,
&clk_leaf_mux_set_rate_parent_test_suite,
&clk_test_suite,
&clk_multiple_parents_mux_test_suite,
diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c
index 591e0364ee5c..85771afd4698 100644
--- a/drivers/clk/imx/clk-fracn-gppll.c
+++ b/drivers/clk/imx/clk-fracn-gppll.c
@@ -254,9 +254,11 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
FIELD_PREP(PLL_MFI_MASK, rate->mfi);
writel_relaxed(pll_div, pll->base + PLL_DIV);
+ readl(pll->base + PLL_DIV);
if (pll->flags & CLK_FRACN_GPPLL_FRACN) {
writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
+ readl(pll->base + PLL_NUMERATOR);
}
/* Wait for 5us according to fracn mode pll doc */
@@ -265,6 +267,7 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
/* Enable Powerup */
tmp |= POWERUP_MASK;
writel_relaxed(tmp, pll->base + PLL_CTRL);
+ readl(pll->base + PLL_CTRL);
/* Wait Lock */
ret = clk_fracn_gppll_wait_lock(pll);
@@ -302,14 +305,15 @@ static int clk_fracn_gppll_prepare(struct clk_hw *hw)
val |= POWERUP_MASK;
writel_relaxed(val, pll->base + PLL_CTRL);
-
- val |= CLKMUX_EN;
- writel_relaxed(val, pll->base + PLL_CTRL);
+ readl(pll->base + PLL_CTRL);
ret = clk_fracn_gppll_wait_lock(pll);
if (ret)
return ret;
+ val |= CLKMUX_EN;
+ writel_relaxed(val, pll->base + PLL_CTRL);
+
val &= ~CLKMUX_BYPASS;
writel_relaxed(val, pll->base + PLL_CTRL);
diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c
index 6c351050b82a..c169fe53a35f 100644
--- a/drivers/clk/imx/clk-imx8-acm.c
+++ b/drivers/clk/imx/clk-imx8-acm.c
@@ -294,9 +294,9 @@ static int clk_imx_acm_attach_pm_domains(struct device *dev,
DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE);
- if (IS_ERR(dev_pm->pd_dev_link[i])) {
+ if (!dev_pm->pd_dev_link[i]) {
dev_pm_domain_detach(dev_pm->pd_dev[i], false);
- ret = PTR_ERR(dev_pm->pd_dev_link[i]);
+ ret = -EINVAL;
goto detach_pm;
}
}
diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index c6a9bc8ecc1f..58a516dd385b 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -15,6 +15,11 @@
#include "clk.h"
+#define IMX93_CLK_END 207
+
+#define PLAT_IMX93 BIT(0)
+#define PLAT_IMX91 BIT(1)
+
enum clk_sel {
LOW_SPEED_IO_SEL,
NON_IO_SEL,
@@ -53,6 +58,7 @@ static const struct imx93_clk_root {
u32 off;
enum clk_sel sel;
unsigned long flags;
+ unsigned long plat;
} root_array[] = {
/* a55/m33/bus critical clk for system run */
{ IMX93_CLK_A55_PERIPH, "a55_periph_root", 0x0000, FAST_SEL, CLK_IS_CRITICAL },
@@ -63,7 +69,7 @@ static const struct imx93_clk_root {
{ IMX93_CLK_BUS_AON, "bus_aon_root", 0x0300, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_WAKEUP_AXI, "wakeup_axi_root", 0x0380, FAST_SEL, CLK_IS_CRITICAL },
{ IMX93_CLK_SWO_TRACE, "swo_trace_root", 0x0400, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, },
{ IMX93_CLK_FLEXIO1, "flexio1_root", 0x0500, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_FLEXIO2, "flexio2_root", 0x0580, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_LPTMR1, "lptmr1_root", 0x0700, LOW_SPEED_IO_SEL, },
@@ -120,15 +126,15 @@ static const struct imx93_clk_root {
{ 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, },
{ IMX93_CLK_NIC_AXI, "nic_axi_root", 0x2080, FAST_SEL, CLK_IS_CRITICAL, },
- { IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, },
+ { IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, },
+ { IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, 0, PLAT_IMX93, },
{ IMX93_CLK_MEDIA_AXI, "media_axi_root", 0x2280, FAST_SEL, },
{ IMX93_CLK_MEDIA_APB, "media_apb_root", 0x2300, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_MEDIA_LDB, "media_ldb_root", 0x2380, VIDEO_SEL, },
+ { IMX93_CLK_MEDIA_LDB, "media_ldb_root", 0x2380, VIDEO_SEL, 0, PLAT_IMX93, },
{ IMX93_CLK_MEDIA_DISP_PIX, "media_disp_pix_root", 0x2400, VIDEO_SEL, },
{ IMX93_CLK_CAM_PIX, "cam_pix_root", 0x2480, VIDEO_SEL, },
- { IMX93_CLK_MIPI_TEST_BYTE, "mipi_test_byte_root", 0x2500, VIDEO_SEL, },
- { IMX93_CLK_MIPI_PHY_CFG, "mipi_phy_cfg_root", 0x2580, VIDEO_SEL, },
+ { IMX93_CLK_MIPI_TEST_BYTE, "mipi_test_byte_root", 0x2500, VIDEO_SEL, 0, PLAT_IMX93, },
+ { IMX93_CLK_MIPI_PHY_CFG, "mipi_phy_cfg_root", 0x2580, VIDEO_SEL, 0, PLAT_IMX93, },
{ IMX93_CLK_ADC, "adc_root", 0x2700, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_PDM, "pdm_root", 0x2780, AUDIO_SEL, },
{ IMX93_CLK_TSTMR1, "tstmr1_root", 0x2800, LOW_SPEED_IO_SEL, },
@@ -137,13 +143,16 @@ static const struct imx93_clk_root {
{ IMX93_CLK_MQS2, "mqs2_root", 0x2980, AUDIO_SEL, },
{ IMX93_CLK_AUDIO_XCVR, "audio_xcvr_root", 0x2a00, NON_IO_SEL, },
{ IMX93_CLK_SPDIF, "spdif_root", 0x2a80, AUDIO_SEL, },
- { IMX93_CLK_ENET, "enet_root", 0x2b00, NON_IO_SEL, },
- { IMX93_CLK_ENET_TIMER1, "enet_timer1_root", 0x2b80, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_ENET_TIMER2, "enet_timer2_root", 0x2c00, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_ENET_REF, "enet_ref_root", 0x2c80, NON_IO_SEL, },
- { IMX93_CLK_ENET_REF_PHY, "enet_ref_phy_root", 0x2d00, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_I3C1_SLOW, "i3c1_slow_root", 0x2d80, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_I3C2_SLOW, "i3c2_slow_root", 0x2e00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_ENET, "enet_root", 0x2b00, NON_IO_SEL, 0, PLAT_IMX93, },
+ { IMX93_CLK_ENET_TIMER1, "enet_timer1_root", 0x2b80, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, },
+ { IMX93_CLK_ENET_TIMER2, "enet_timer2_root", 0x2c00, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, },
+ { IMX93_CLK_ENET_REF, "enet_ref_root", 0x2c80, NON_IO_SEL, 0, PLAT_IMX93, },
+ { IMX93_CLK_ENET_REF_PHY, "enet_ref_phy_root", 0x2d00, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, },
+ { IMX91_CLK_ENET1_QOS_TSN, "enet1_qos_tsn_root", 0x2b00, NON_IO_SEL, 0, PLAT_IMX91, },
+ { IMX91_CLK_ENET_TIMER, "enet_timer_root", 0x2b80, LOW_SPEED_IO_SEL, 0, PLAT_IMX91, },
+ { IMX91_CLK_ENET2_REGULAR, "enet2_regular_root", 0x2c80, NON_IO_SEL, 0, PLAT_IMX91, },
+ { IMX93_CLK_I3C1_SLOW, "i3c1_slow_root", 0x2d80, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, },
+ { IMX93_CLK_I3C2_SLOW, "i3c2_slow_root", 0x2e00, LOW_SPEED_IO_SEL, 0, PLAT_IMX93, },
{ IMX93_CLK_USB_PHY_BURUNIN, "usb_phy_root", 0x2e80, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_PAL_CAME_SCAN, "pal_came_scan_root", 0x2f00, MISC_SEL, }
};
@@ -155,6 +164,7 @@ static const struct imx93_clk_ccgr {
u32 off;
unsigned long flags;
u32 *shared_count;
+ unsigned long plat;
} ccgr_array[] = {
{ IMX93_CLK_A55_GATE, "a55_alt", "a55_alt_root", 0x8000, },
/* M33 critical clk for system run */
@@ -244,8 +254,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", "wakeup_axi_root", 0x9e00, },
- { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, },
+ { IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, 0, NULL, PLAT_IMX93, },
+ { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, 0, NULL, PLAT_IMX93, },
+ { IMX91_CLK_ENET2_REGULAR_GATE, "enet2_regular", "wakeup_axi_root", 0x9e00, 0, NULL, PLAT_IMX91, },
+ { IMX91_CLK_ENET1_QOS_TSN_GATE, "enet1_qos_tsn", "wakeup_axi_root", 0x9e40, 0, NULL, PLAT_IMX91, },
/* 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, },
@@ -265,6 +277,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
const struct imx93_clk_ccgr *ccgr;
void __iomem *base, *anatop_base;
int i, ret;
+ const unsigned long plat = (unsigned long)device_get_match_data(&pdev->dev);
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws,
IMX93_CLK_END), GFP_KERNEL);
@@ -314,17 +327,20 @@ static int imx93_clocks_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(root_array); i++) {
root = &root_array[i];
- clks[root->clk] = imx93_clk_composite_flags(root->name,
- parent_names[root->sel],
- 4, base + root->off, 3,
- root->flags);
+ if (!root->plat || root->plat & plat)
+ clks[root->clk] = imx93_clk_composite_flags(root->name,
+ parent_names[root->sel],
+ 4, base + root->off, 3,
+ root->flags);
}
for (i = 0; i < ARRAY_SIZE(ccgr_array); i++) {
ccgr = &ccgr_array[i];
- clks[ccgr->clk] = imx93_clk_gate(NULL, ccgr->name, ccgr->parent_name,
- ccgr->flags, base + ccgr->off, 0, 1, 1, 3,
- ccgr->shared_count);
+ if (!ccgr->plat || ccgr->plat & plat)
+ clks[ccgr->clk] = imx93_clk_gate(NULL,
+ ccgr->name, ccgr->parent_name,
+ ccgr->flags, base + ccgr->off, 0, 1, 1, 3,
+ ccgr->shared_count);
}
clks[IMX93_CLK_A55_SEL] = imx_clk_hw_mux2("a55_sel", base + 0x4820, 0, 1, a55_core_sels,
@@ -354,7 +370,8 @@ unregister_hws:
}
static const struct of_device_id imx93_clk_of_match[] = {
- { .compatible = "fsl,imx93-ccm" },
+ { .compatible = "fsl,imx93-ccm", .data = (void *)PLAT_IMX93 },
+ { .compatible = "fsl,imx91-ccm", .data = (void *)PLAT_IMX91 },
{ /* Sentinel */ },
};
MODULE_DEVICE_TABLE(of, imx93_clk_of_match);
diff --git a/drivers/clk/imx/clk-imx95-blk-ctl.c b/drivers/clk/imx/clk-imx95-blk-ctl.c
index 19a62da74be4..25974947ad0c 100644
--- a/drivers/clk/imx/clk-imx95-blk-ctl.c
+++ b/drivers/clk/imx/clk-imx95-blk-ctl.c
@@ -277,6 +277,25 @@ static const struct imx95_blk_ctl_dev_data netcmix_dev_data = {
.clk_reg_offset = 0,
};
+static const struct imx95_blk_ctl_clk_dev_data hsio_blk_ctl_clk_dev_data[] = {
+ [0] = {
+ .name = "hsio_blk_ctl_clk",
+ .parent_names = (const char *[]){ "hsio_pll", },
+ .num_parents = 1,
+ .reg = 0,
+ .bit_idx = 6,
+ .bit_width = 1,
+ .type = CLK_GATE,
+ .flags = CLK_SET_RATE_PARENT,
+ }
+};
+
+static const struct imx95_blk_ctl_dev_data hsio_blk_ctl_dev_data = {
+ .num_clks = 1,
+ .clk_dev_data = hsio_blk_ctl_clk_dev_data,
+ .clk_reg_offset = 0,
+};
+
static int imx95_bc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -447,6 +466,7 @@ static const struct of_device_id imx95_bc_of_match[] = {
{ .compatible = "nxp,imx95-display-master-csr", },
{ .compatible = "nxp,imx95-lvds-csr", .data = &lvds_csr_dev_data },
{ .compatible = "nxp,imx95-display-csr", .data = &dispmix_csr_dev_data },
+ { .compatible = "nxp,imx95-hsio-blk-ctl", .data = &hsio_blk_ctl_dev_data },
{ .compatible = "nxp,imx95-vpu-csr", .data = &vpublk_dev_data },
{ .compatible = "nxp,imx95-netcmix-blk-ctrl", .data = &netcmix_dev_data},
{ /* Sentinel */ },
diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
index dd5abd09f3e2..6376557a3c3d 100644
--- a/drivers/clk/imx/clk-lpcg-scu.c
+++ b/drivers/clk/imx/clk-lpcg-scu.c
@@ -6,10 +6,12 @@
#include <linux/bits.h>
#include <linux/clk-provider.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/units.h>
#include "clk-scu.h"
@@ -41,6 +43,29 @@ struct clk_lpcg_scu {
#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
+/* e10858 -LPCG clock gating register synchronization errata */
+static void lpcg_e10858_writel(unsigned long rate, void __iomem *reg, u32 val)
+{
+ writel(val, reg);
+
+ if (rate >= 24 * HZ_PER_MHZ || rate == 0) {
+ /*
+ * The time taken to access the LPCG registers from the AP core
+ * through the interconnect is longer than the minimum delay
+ * of 4 clock cycles required by the errata.
+ * Adding a readl will provide sufficient delay to prevent
+ * back-to-back writes.
+ */
+ readl(reg);
+ } else {
+ /*
+ * For clocks running below 24MHz, wait a minimum of
+ * 4 clock cycles.
+ */
+ ndelay(4 * (DIV_ROUND_UP(1000 * HZ_PER_MHZ, rate)));
+ }
+}
+
static int clk_lpcg_scu_enable(struct clk_hw *hw)
{
struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
@@ -57,7 +82,8 @@ static int clk_lpcg_scu_enable(struct clk_hw *hw)
val |= CLK_GATE_SCU_LPCG_HW_SEL;
reg |= val << clk->bit_idx;
- writel(reg, clk->reg);
+
+ lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg);
spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
@@ -74,7 +100,7 @@ static void clk_lpcg_scu_disable(struct clk_hw *hw)
reg = readl_relaxed(clk->reg);
reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
- writel(reg, clk->reg);
+ lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg);
spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
}
@@ -135,6 +161,9 @@ static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev)
{
struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
+ if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg")))
+ return 0;
+
clk->state = readl_relaxed(clk->reg);
dev_dbg(dev, "save lpcg state 0x%x\n", clk->state);
@@ -145,13 +174,11 @@ static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev)
{
struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
- /*
- * FIXME: Sometimes writes don't work unless the CPU issues
- * them twice
- */
+ if (!strncmp("hdmi_lpcg", clk_hw_get_name(&clk->hw), strlen("hdmi_lpcg")))
+ return 0;
writel(clk->state, clk->reg);
- writel(clk->state, clk->reg);
+ lpcg_e10858_writel(0, clk->reg, clk->state);
dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
return 0;
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index b1dd0c08e091..b27186aaf2a1 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -596,7 +596,7 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev)
clk->rate = clk_scu_recalc_rate(&clk->hw, 0);
else
clk->rate = clk_hw_get_rate(&clk->hw);
- clk->is_enabled = clk_hw_is_enabled(&clk->hw);
+ clk->is_enabled = clk_hw_is_prepared(&clk->hw);
if (clk->parent)
dev_dbg(dev, "save parent %s idx %u\n", clk_hw_get_name(clk->parent),
diff --git a/drivers/clk/kunit_clk_assigned_rates.h b/drivers/clk/kunit_clk_assigned_rates.h
new file mode 100644
index 000000000000..df2d84dcaa93
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _KUNIT_CLK_ASSIGNED_RATES_H
+#define _KUNIT_CLK_ASSIGNED_RATES_H
+
+#define ASSIGNED_RATES_0_RATE 1600000
+#define ASSIGNED_RATES_1_RATE 9700000
+
+#endif
diff --git a/drivers/clk/kunit_clk_assigned_rates_multiple.dtso b/drivers/clk/kunit_clk_assigned_rates_multiple.dtso
new file mode 100644
index 000000000000..e600736e70f5
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_multiple.dtso
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <1>;
+ assigned-clocks = <&clk 0>,
+ <&clk 1>;
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>,
+ <ASSIGNED_RATES_1_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_multiple_consumer.dtso b/drivers/clk/kunit_clk_assigned_rates_multiple_consumer.dtso
new file mode 100644
index 000000000000..260aba458daf
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_multiple_consumer.dtso
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <1>;
+ };
+
+ kunit-clock-consumer {
+ compatible = "test,clk-consumer";
+ assigned-clocks = <&clk 0>,
+ <&clk 1>;
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>,
+ <ASSIGNED_RATES_1_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_null.dtso b/drivers/clk/kunit_clk_assigned_rates_null.dtso
new file mode 100644
index 000000000000..0b27b38a9130
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_null.dtso
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ assigned-clocks = <0>;
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_null_consumer.dtso b/drivers/clk/kunit_clk_assigned_rates_null_consumer.dtso
new file mode 100644
index 000000000000..99fb332ae83d
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_null_consumer.dtso
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ };
+
+ kunit-clock-consumer {
+ compatible = "test,clk-consumer";
+ assigned-clocks = <0>;
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_one.dtso b/drivers/clk/kunit_clk_assigned_rates_one.dtso
new file mode 100644
index 000000000000..dd95ec9b1cf9
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_one.dtso
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ assigned-clocks = <&clk>;
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_one_consumer.dtso b/drivers/clk/kunit_clk_assigned_rates_one_consumer.dtso
new file mode 100644
index 000000000000..a41dca806318
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_one_consumer.dtso
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ };
+
+ kunit-clock-consumer {
+ compatible = "test,clk-consumer";
+ assigned-clocks = <&clk>;
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_u64_multiple.dtso b/drivers/clk/kunit_clk_assigned_rates_u64_multiple.dtso
new file mode 100644
index 000000000000..389b4e2eb7f7
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_u64_multiple.dtso
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <1>;
+ assigned-clocks = <&clk 0>,
+ <&clk 1>;
+ assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>,
+ /bits/ 64 <ASSIGNED_RATES_1_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_u64_multiple_consumer.dtso b/drivers/clk/kunit_clk_assigned_rates_u64_multiple_consumer.dtso
new file mode 100644
index 000000000000..3e117fd59b7d
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_u64_multiple_consumer.dtso
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <1>;
+ };
+
+ kunit-clock-consumer {
+ compatible = "test,clk-consumer";
+ assigned-clocks = <&clk 0>,
+ <&clk 1>;
+ assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>,
+ /bits/ 64 <ASSIGNED_RATES_1_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_u64_one.dtso b/drivers/clk/kunit_clk_assigned_rates_u64_one.dtso
new file mode 100644
index 000000000000..87041264e8f5
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_u64_one.dtso
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ assigned-clocks = <&clk>;
+ assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_u64_one_consumer.dtso b/drivers/clk/kunit_clk_assigned_rates_u64_one_consumer.dtso
new file mode 100644
index 000000000000..3259c003aec0
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_u64_one_consumer.dtso
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ };
+
+ kunit-clock-consumer {
+ compatible = "test,clk-consumer";
+ assigned-clocks = <&clk>;
+ assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_without.dtso b/drivers/clk/kunit_clk_assigned_rates_without.dtso
new file mode 100644
index 000000000000..22d333495cf2
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_without.dtso
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_without_consumer.dtso b/drivers/clk/kunit_clk_assigned_rates_without_consumer.dtso
new file mode 100644
index 000000000000..75ac09140f83
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_without_consumer.dtso
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "kunit_clk_assigned_rates.h"
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ };
+
+ kunit-clock-consumer {
+ compatible = "test,clk-consumer";
+ assigned-clock-rates = <ASSIGNED_RATES_0_RATE>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_zero.dtso b/drivers/clk/kunit_clk_assigned_rates_zero.dtso
new file mode 100644
index 000000000000..08e042c2eafe
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_zero.dtso
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ assigned-clocks = <&clk>;
+ assigned-clock-rates = <0>;
+ };
+};
diff --git a/drivers/clk/kunit_clk_assigned_rates_zero_consumer.dtso b/drivers/clk/kunit_clk_assigned_rates_zero_consumer.dtso
new file mode 100644
index 000000000000..1d964672e855
--- /dev/null
+++ b/drivers/clk/kunit_clk_assigned_rates_zero_consumer.dtso
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&{/} {
+ clk: kunit-clock {
+ compatible = "test,clk-assigned-rates";
+ #clock-cells = <0>;
+ };
+
+ kunit-clock-consumer {
+ compatible = "test,clk-consumer";
+ assigned-clocks = <&clk>;
+ assigned-clock-rates = <0>;
+ };
+};
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 70a005e7e1b1..5f8e6d68fa14 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -124,6 +124,43 @@ config COMMON_CLK_MT2712_VENCSYS
help
This driver supports MediaTek MT2712 vencsys clocks.
+config COMMON_CLK_MT6735
+ tristate "Main clock drivers for MediaTek MT6735"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ help
+ This enables drivers for clocks and resets provided
+ by apmixedsys, topckgen, infracfg and pericfg on the
+ MediaTek MT6735 SoC.
+
+config COMMON_CLK_MT6735_IMGSYS
+ tristate "Clock driver for MediaTek MT6735 imgsys"
+ depends on COMMON_CLK_MT6735
+ help
+ This enables a driver for clocks provided by imgsys
+ on the MediaTek MT6735 SoC.
+
+config COMMON_CLK_MT6735_MFGCFG
+ tristate "Clock driver for MediaTek MT6735 mfgcfg"
+ depends on COMMON_CLK_MT6735
+ help
+ This enables a driver for clocks and resets provided
+ by mfgcfg on the MediaTek MT6735 SoC.
+
+config COMMON_CLK_MT6735_VDECSYS
+ tristate "Clock driver for MediaTek MT6735 vdecsys"
+ depends on COMMON_CLK_MT6735
+ help
+ This enables a driver for clocks and resets provided
+ by vdecsys on the MediaTek MT6735 SoC.
+
+config COMMON_CLK_MT6735_VENCSYS
+ tristate "Clock driver for MediaTek MT6735 vencsys"
+ depends on COMMON_CLK_MT6735
+ help
+ This enables a driver for clocks provided by vencsys
+ on the MediaTek MT6735 SoC.
+
config COMMON_CLK_MT6765
bool "Clock driver for MediaTek MT6765"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
@@ -887,13 +924,6 @@ config COMMON_CLK_MT8195_APUSYS
help
This driver supports MediaTek MT8195 AI Processor Unit System clocks.
-config COMMON_CLK_MT8195_AUDSYS
- tristate "Clock driver for MediaTek MT8195 audsys"
- depends on COMMON_CLK_MT8195
- default COMMON_CLK_MT8195
- help
- This driver supports MediaTek MT8195 audsys clocks.
-
config COMMON_CLK_MT8195_IMP_IIC_WRAP
tristate "Clock driver for MediaTek MT8195 imp_iic_wrap"
depends on COMMON_CLK_MT8195
@@ -908,14 +938,6 @@ config COMMON_CLK_MT8195_MFGCFG
help
This driver supports MediaTek MT8195 mfgcfg clocks.
-config COMMON_CLK_MT8195_MSDC
- tristate "Clock driver for MediaTek MT8195 msdc"
- depends on COMMON_CLK_MT8195
- default COMMON_CLK_MT8195
- help
- This driver supports MediaTek MT8195 MMC and SD Controller's
- msdc and msdc_top clocks.
-
config COMMON_CLK_MT8195_SCP_ADSP
tristate "Clock driver for MediaTek MT8195 scp_adsp"
depends on COMMON_CLK_MT8195
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index eeccfa039896..6efec95406bd 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -2,6 +2,11 @@
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_MT6735) += clk-mt6735-apmixedsys.o clk-mt6735-infracfg.o clk-mt6735-pericfg.o clk-mt6735-topckgen.o
+obj-$(CONFIG_COMMON_CLK_MT6735_IMGSYS) += clk-mt6735-imgsys.o
+obj-$(CONFIG_COMMON_CLK_MT6735_MFGCFG) += clk-mt6735-mfgcfg.o
+obj-$(CONFIG_COMMON_CLK_MT6735_VDECSYS) += clk-mt6735-vdecsys.o
+obj-$(CONFIG_COMMON_CLK_MT6735_VENCSYS) += clk-mt6735-vencsys.o
obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o
obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o
obj-$(CONFIG_COMMON_CLK_MT6765_CAMSYS) += clk-mt6765-cam.o
diff --git a/drivers/clk/mediatek/clk-mt6735-apmixedsys.c b/drivers/clk/mediatek/clk-mt6735-apmixedsys.c
new file mode 100644
index 000000000000..e0949911e8f7
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-apmixedsys.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-pll.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-apmixedsys.h>
+
+#define AP_PLL_CON_5 0x014
+#define ARMPLL_CON0 0x200
+#define ARMPLL_CON1 0x204
+#define ARMPLL_PWR_CON0 0x20c
+#define MAINPLL_CON0 0x210
+#define MAINPLL_CON1 0x214
+#define MAINPLL_PWR_CON0 0x21c
+#define UNIVPLL_CON0 0x220
+#define UNIVPLL_CON1 0x224
+#define UNIVPLL_PWR_CON0 0x22c
+#define MMPLL_CON0 0x230
+#define MMPLL_CON1 0x234
+#define MMPLL_PWR_CON0 0x23c
+#define MSDCPLL_CON0 0x240
+#define MSDCPLL_CON1 0x244
+#define MSDCPLL_PWR_CON0 0x24c
+#define VENCPLL_CON0 0x250
+#define VENCPLL_CON1 0x254
+#define VENCPLL_PWR_CON0 0x25c
+#define TVDPLL_CON0 0x260
+#define TVDPLL_CON1 0x264
+#define TVDPLL_PWR_CON0 0x26c
+#define APLL1_CON0 0x270
+#define APLL1_CON1 0x274
+#define APLL1_CON2 0x278
+#define APLL1_PWR_CON0 0x280
+#define APLL2_CON0 0x284
+#define APLL2_CON1 0x288
+#define APLL2_CON2 0x28c
+#define APLL2_PWR_CON0 0x294
+
+#define CON0_RST_BAR BIT(24)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _rst_bar_mask, \
+ _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
+ _tuner_en_bit, _pcw_reg, _pcwbits, _flags) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = "clk26m", \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .rst_bar_mask = _rst_bar_mask, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .tuner_en_reg = _tuner_en_reg, \
+ .tuner_en_bit = _tuner_en_bit, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_chg_reg = _pcw_reg, \
+ .pcwbits = _pcwbits, \
+ .flags = _flags, \
+ }
+
+static const struct mtk_pll_data apmixedsys_plls[] = {
+ PLL(CLK_APMIXED_ARMPLL, "armpll", ARMPLL_CON0, ARMPLL_PWR_CON0, 0x00000001, 0, ARMPLL_CON1, 24, 0, 0, 0, ARMPLL_CON1, 21, PLL_AO),
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", MAINPLL_CON0, MAINPLL_PWR_CON0, 0xf0000101, CON0_RST_BAR, MAINPLL_CON1, 24, 0, 0, 0, MAINPLL_CON1, 21, HAVE_RST_BAR),
+ PLL(CLK_APMIXED_UNIVPLL, "univpll", UNIVPLL_CON0, UNIVPLL_PWR_CON0, 0xfc000001, CON0_RST_BAR, UNIVPLL_CON1, 24, 0, 0, 0, UNIVPLL_CON1, 21, HAVE_RST_BAR),
+ PLL(CLK_APMIXED_MMPLL, "mmpll", MMPLL_CON0, MMPLL_PWR_CON0, 0x00000001, 0, MMPLL_CON1, 24, 0, 0, 0, MMPLL_CON1, 21, 0),
+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", MSDCPLL_CON0, MSDCPLL_PWR_CON0, 0x00000001, 0, MSDCPLL_CON1, 24, 0, 0, 0, MSDCPLL_CON1, 21, 0),
+ PLL(CLK_APMIXED_VENCPLL, "vencpll", VENCPLL_CON0, VENCPLL_PWR_CON0, 0x00000001, CON0_RST_BAR, VENCPLL_CON1, 24, 0, 0, 0, VENCPLL_CON1, 21, HAVE_RST_BAR),
+ PLL(CLK_APMIXED_TVDPLL, "tvdpll", TVDPLL_CON0, TVDPLL_PWR_CON0, 0x00000001, 0, TVDPLL_CON1, 24, 0, 0, 0, TVDPLL_CON1, 21, 0),
+ PLL(CLK_APMIXED_APLL1, "apll1", APLL1_CON0, APLL1_PWR_CON0, 0x00000001, 0, APLL1_CON0, 4, APLL1_CON2, AP_PLL_CON_5, 0, APLL1_CON1, 31, 0),
+ PLL(CLK_APMIXED_APLL2, "apll2", APLL2_CON0, APLL2_PWR_CON0, 0x00000001, 0, APLL2_CON0, 4, APLL2_CON2, AP_PLL_CON_5, 1, APLL2_CON1, 31, 0)
+};
+
+static int clk_mt6735_apmixed_probe(struct platform_device *pdev)
+{
+ void __iomem *base;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct clk_hw_onecell_data *clk_data;
+ int ret;
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ clk_data = mtk_devm_alloc_clk_data(&pdev->dev, ARRAY_SIZE(apmixedsys_plls));
+ if (!clk_data)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, clk_data);
+
+ ret = mtk_clk_register_plls(pdev->dev.of_node, apmixedsys_plls,
+ ARRAY_SIZE(apmixedsys_plls), clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register PLLs: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
+ clk_data);
+ if (ret)
+ dev_err(&pdev->dev,
+ "Failed to register clock provider: %d\n", ret);
+
+ return ret;
+}
+
+static void clk_mt6735_apmixed_remove(struct platform_device *pdev)
+{
+ struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+
+ mtk_clk_unregister_plls(apmixedsys_plls, ARRAY_SIZE(apmixedsys_plls), clk_data);
+}
+
+static const struct of_device_id of_match_mt6735_apmixedsys[] = {
+ { .compatible = "mediatek,mt6735-apmixedsys" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_mt6735_apmixedsys);
+
+static struct platform_driver clk_mt6735_apmixedsys = {
+ .probe = clk_mt6735_apmixed_probe,
+ .remove = clk_mt6735_apmixed_remove,
+ .driver = {
+ .name = "clk-mt6735-apmixedsys",
+ .of_match_table = of_match_mt6735_apmixedsys,
+ },
+};
+module_platform_driver(clk_mt6735_apmixedsys);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("MediaTek MT6735 apmixedsys clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt6735-imgsys.c b/drivers/clk/mediatek/clk-mt6735-imgsys.c
new file mode 100644
index 000000000000..c564f8f72432
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-imgsys.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-imgsys.h>
+
+#define IMG_CG_CON 0x00
+#define IMG_CG_SET 0x04
+#define IMG_CG_CLR 0x08
+
+static struct mtk_gate_regs imgsys_cg_regs = {
+ .set_ofs = IMG_CG_SET,
+ .clr_ofs = IMG_CG_CLR,
+ .sta_ofs = IMG_CG_CON,
+};
+
+static const struct mtk_gate imgsys_gates[] = {
+ GATE_MTK(CLK_IMG_SMI_LARB2, "smi_larb2", "mm_sel", &imgsys_cg_regs, 0, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_IMG_CAM_SMI, "cam_smi", "mm_sel", &imgsys_cg_regs, 5, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_IMG_CAM_CAM, "cam_cam", "mm_sel", &imgsys_cg_regs, 6, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_IMG_SEN_TG, "sen_tg", "mm_sel", &imgsys_cg_regs, 7, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_IMG_SEN_CAM, "sen_cam", "mm_sel", &imgsys_cg_regs, 8, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_IMG_CAM_SV, "cam_sv", "mm_sel", &imgsys_cg_regs, 9, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_IMG_SUFOD, "sufod", "mm_sel", &imgsys_cg_regs, 10, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_IMG_FD, "fd", "mm_sel", &imgsys_cg_regs, 11, &mtk_clk_gate_ops_setclr),
+};
+
+static const struct mtk_clk_desc imgsys_clks = {
+ .clks = imgsys_gates,
+ .num_clks = ARRAY_SIZE(imgsys_gates),
+};
+
+static const struct of_device_id of_match_mt6735_imgsys[] = {
+ { .compatible = "mediatek,mt6735-imgsys", .data = &imgsys_clks },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt6735_imgsys = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt6735-imgsys",
+ .of_match_table = of_match_mt6735_imgsys,
+ },
+};
+module_platform_driver(clk_mt6735_imgsys);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("MediaTek MT6735 imgsys clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt6735-infracfg.c b/drivers/clk/mediatek/clk-mt6735-infracfg.c
new file mode 100644
index 000000000000..c1171f903cfa
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-infracfg.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-infracfg.h>
+#include <dt-bindings/reset/mediatek,mt6735-infracfg.h>
+
+#define INFRA_RST0 0x30
+#define INFRA_GLOBALCON_PDN0 0x40
+#define INFRA_PDN1 0x44
+#define INFRA_PDN_STA 0x48
+
+#define RST_NR_PER_BANK 32
+
+static struct mtk_gate_regs infra_cg_regs = {
+ .set_ofs = INFRA_GLOBALCON_PDN0,
+ .clr_ofs = INFRA_PDN1,
+ .sta_ofs = INFRA_PDN_STA,
+};
+
+static const struct mtk_gate infracfg_gates[] = {
+ GATE_MTK(CLK_INFRA_DBG, "dbg", "axi_sel", &infra_cg_regs, 0, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_GCE, "gce", "axi_sel", &infra_cg_regs, 1, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_TRBG, "trbg", "axi_sel", &infra_cg_regs, 2, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_CPUM, "cpum", "axi_sel", &infra_cg_regs, 3, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_DEVAPC, "devapc", "axi_sel", &infra_cg_regs, 4, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_AUDIO, "audio", "aud_intbus_sel", &infra_cg_regs, 5, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_GCPU, "gcpu", "axi_sel", &infra_cg_regs, 6, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_L2C_SRAM, "l2csram", "axi_sel", &infra_cg_regs, 7, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_M4U, "m4u", "axi_sel", &infra_cg_regs, 8, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_CLDMA, "cldma", "axi_sel", &infra_cg_regs, 12, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_CONNMCU_BUS, "connmcu_bus", "axi_sel", &infra_cg_regs, 15, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_KP, "kp", "axi_sel", &infra_cg_regs, 16, &mtk_clk_gate_ops_setclr),
+ GATE_MTK_FLAGS(CLK_INFRA_APXGPT, "apxgpt", "axi_sel", &infra_cg_regs, 18, &mtk_clk_gate_ops_setclr, CLK_IS_CRITICAL),
+ GATE_MTK(CLK_INFRA_SEJ, "sej", "axi_sel", &infra_cg_regs, 19, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_CCIF0_AP, "ccif0ap", "axi_sel", &infra_cg_regs, 20, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_CCIF1_AP, "ccif1ap", "axi_sel", &infra_cg_regs, 21, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_PMIC_SPI, "pmicspi", "pmicspi_sel", &infra_cg_regs, 22, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_INFRA_PMIC_WRAP, "pmicwrap", "axi_sel", &infra_cg_regs, 23, &mtk_clk_gate_ops_setclr)
+};
+
+static u16 infracfg_rst_bank_ofs[] = { INFRA_RST0 };
+
+static u16 infracfg_rst_idx_map[] = {
+ [MT6735_INFRA_RST0_EMI_REG] = 0 * RST_NR_PER_BANK + 0,
+ [MT6735_INFRA_RST0_DRAMC0_AO] = 0 * RST_NR_PER_BANK + 1,
+ [MT6735_INFRA_RST0_AP_CIRQ_EINT] = 0 * RST_NR_PER_BANK + 3,
+ [MT6735_INFRA_RST0_APXGPT] = 0 * RST_NR_PER_BANK + 4,
+ [MT6735_INFRA_RST0_SCPSYS] = 0 * RST_NR_PER_BANK + 5,
+ [MT6735_INFRA_RST0_KP] = 0 * RST_NR_PER_BANK + 6,
+ [MT6735_INFRA_RST0_PMIC_WRAP] = 0 * RST_NR_PER_BANK + 7,
+ [MT6735_INFRA_RST0_CLDMA_AO_TOP] = 0 * RST_NR_PER_BANK + 8,
+ [MT6735_INFRA_RST0_USBSIF_TOP] = 0 * RST_NR_PER_BANK + 9,
+ [MT6735_INFRA_RST0_EMI] = 0 * RST_NR_PER_BANK + 16,
+ [MT6735_INFRA_RST0_CCIF] = 0 * RST_NR_PER_BANK + 17,
+ [MT6735_INFRA_RST0_DRAMC0] = 0 * RST_NR_PER_BANK + 18,
+ [MT6735_INFRA_RST0_EMI_AO_REG] = 0 * RST_NR_PER_BANK + 19,
+ [MT6735_INFRA_RST0_CCIF_AO] = 0 * RST_NR_PER_BANK + 20,
+ [MT6735_INFRA_RST0_TRNG] = 0 * RST_NR_PER_BANK + 21,
+ [MT6735_INFRA_RST0_SYS_CIRQ] = 0 * RST_NR_PER_BANK + 22,
+ [MT6735_INFRA_RST0_GCE] = 0 * RST_NR_PER_BANK + 23,
+ [MT6735_INFRA_RST0_M4U] = 0 * RST_NR_PER_BANK + 24,
+ [MT6735_INFRA_RST0_CCIF1] = 0 * RST_NR_PER_BANK + 25,
+ [MT6735_INFRA_RST0_CLDMA_TOP_PD] = 0 * RST_NR_PER_BANK + 26
+};
+
+static const struct mtk_clk_rst_desc infracfg_resets = {
+ .version = MTK_RST_SIMPLE,
+ .rst_bank_ofs = infracfg_rst_bank_ofs,
+ .rst_bank_nr = ARRAY_SIZE(infracfg_rst_bank_ofs),
+ .rst_idx_map = infracfg_rst_idx_map,
+ .rst_idx_map_nr = ARRAY_SIZE(infracfg_rst_idx_map)
+};
+
+static const struct mtk_clk_desc infracfg_clks = {
+ .clks = infracfg_gates,
+ .num_clks = ARRAY_SIZE(infracfg_gates),
+
+ .rst_desc = &infracfg_resets
+};
+
+static const struct of_device_id of_match_mt6735_infracfg[] = {
+ { .compatible = "mediatek,mt6735-infracfg", .data = &infracfg_clks },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_mt6735_infracfg);
+
+static struct platform_driver clk_mt6735_infracfg = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt6735-infracfg",
+ .of_match_table = of_match_mt6735_infracfg,
+ },
+};
+module_platform_driver(clk_mt6735_infracfg);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("MediaTek MT6735 infracfg clock and reset driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt6735-mfgcfg.c b/drivers/clk/mediatek/clk-mt6735-mfgcfg.c
new file mode 100644
index 000000000000..1f5aedddf209
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-mfgcfg.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-mfgcfg.h>
+
+#define MFG_CG_CON 0x00
+#define MFG_CG_SET 0x04
+#define MFG_CG_CLR 0x08
+#define MFG_RESET 0x0c
+
+static struct mtk_gate_regs mfgcfg_cg_regs = {
+ .set_ofs = MFG_CG_SET,
+ .clr_ofs = MFG_CG_CLR,
+ .sta_ofs = MFG_CG_CON,
+};
+
+static const struct mtk_gate mfgcfg_gates[] = {
+ GATE_MTK(CLK_MFG_BG3D, "bg3d", "mfg_sel", &mfgcfg_cg_regs, 0, &mtk_clk_gate_ops_setclr),
+};
+
+static u16 mfgcfg_rst_ofs[] = { MFG_RESET };
+
+static const struct mtk_clk_rst_desc mfgcfg_resets = {
+ .version = MTK_RST_SIMPLE,
+ .rst_bank_ofs = mfgcfg_rst_ofs,
+ .rst_bank_nr = ARRAY_SIZE(mfgcfg_rst_ofs)
+};
+
+static const struct mtk_clk_desc mfgcfg_clks = {
+ .clks = mfgcfg_gates,
+ .num_clks = ARRAY_SIZE(mfgcfg_gates),
+
+ .rst_desc = &mfgcfg_resets
+};
+
+static const struct of_device_id of_match_mt6735_mfgcfg[] = {
+ { .compatible = "mediatek,mt6735-mfgcfg", .data = &mfgcfg_clks },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt6735_mfgcfg = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt6735-mfgcfg",
+ .of_match_table = of_match_mt6735_mfgcfg,
+ },
+};
+module_platform_driver(clk_mt6735_mfgcfg);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Mediatek MT6735 mfgcfg clock and reset driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt6735-pericfg.c b/drivers/clk/mediatek/clk-mt6735-pericfg.c
new file mode 100644
index 000000000000..cbdf6d25c1b2
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-pericfg.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-pericfg.h>
+#include <dt-bindings/reset/mediatek,mt6735-pericfg.h>
+
+#define PERI_GLOBALCON_RST0 0x00
+#define PERI_GLOBALCON_RST1 0x04
+#define PERI_GLOBALCON_PDN0_SET 0x08
+#define PERI_GLOBALCON_PDN0_CLR 0x10
+#define PERI_GLOBALCON_PDN0_STA 0x18
+
+#define RST_NR_PER_BANK 32
+
+static struct mtk_gate_regs peri_cg_regs = {
+ .set_ofs = PERI_GLOBALCON_PDN0_SET,
+ .clr_ofs = PERI_GLOBALCON_PDN0_CLR,
+ .sta_ofs = PERI_GLOBALCON_PDN0_STA,
+};
+
+static const struct mtk_gate pericfg_gates[] = {
+ GATE_MTK(CLK_PERI_DISP_PWM, "disp_pwm", "disppwm_sel", &peri_cg_regs, 0, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_THERM, "therm", "axi_sel", &peri_cg_regs, 1, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM1, "pwm1", "axi_sel", &peri_cg_regs, 2, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM2, "pwm2", "axi_sel", &peri_cg_regs, 3, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM3, "pwm3", "axi_sel", &peri_cg_regs, 4, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM4, "pwm4", "axi_sel", &peri_cg_regs, 5, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM5, "pwm5", "axi_sel", &peri_cg_regs, 6, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM6, "pwm6", "axi_sel", &peri_cg_regs, 7, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM7, "pwm7", "axi_sel", &peri_cg_regs, 8, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_PWM, "pwm", "axi_sel", &peri_cg_regs, 9, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_USB0, "usb0", "usb20_sel", &peri_cg_regs, 10, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_IRDA, "irda", "irda_sel", &peri_cg_regs, 11, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_APDMA, "apdma", "axi_sel", &peri_cg_regs, 12, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_MSDC30_0, "msdc30_0", "msdc30_0_sel", &peri_cg_regs, 13, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_MSDC30_1, "msdc30_1", "msdc30_1_sel", &peri_cg_regs, 14, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_MSDC30_2, "msdc30_2", "msdc30_2_sel", &peri_cg_regs, 15, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_MSDC30_3, "msdc30_3", "msdc30_3_sel", &peri_cg_regs, 16, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_UART0, "uart0", "uart_sel", &peri_cg_regs, 17, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_UART1, "uart1", "uart_sel", &peri_cg_regs, 18, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_UART2, "uart2", "uart_sel", &peri_cg_regs, 19, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_UART3, "uart3", "uart_sel", &peri_cg_regs, 20, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_UART4, "uart4", "uart_sel", &peri_cg_regs, 21, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_BTIF, "btif", "axi_sel", &peri_cg_regs, 22, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_I2C0, "i2c0", "axi_sel", &peri_cg_regs, 23, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_I2C1, "i2c1", "axi_sel", &peri_cg_regs, 24, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_I2C2, "i2c2", "axi_sel", &peri_cg_regs, 25, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_I2C3, "i2c3", "axi_sel", &peri_cg_regs, 26, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_AUXADC, "auxadc", "axi_sel", &peri_cg_regs, 27, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_SPI0, "spi0", "spi_sel", &peri_cg_regs, 28, &mtk_clk_gate_ops_setclr),
+ GATE_MTK(CLK_PERI_IRTX, "irtx", "irtx_sel", &peri_cg_regs, 29, &mtk_clk_gate_ops_setclr)
+};
+
+static u16 pericfg_rst_bank_ofs[] = { PERI_GLOBALCON_RST0, PERI_GLOBALCON_RST1 };
+
+static u16 pericfg_rst_idx_map[] = {
+ [MT6735_PERI_RST0_UART0] = 0 * RST_NR_PER_BANK + 0,
+ [MT6735_PERI_RST0_UART1] = 0 * RST_NR_PER_BANK + 1,
+ [MT6735_PERI_RST0_UART2] = 0 * RST_NR_PER_BANK + 2,
+ [MT6735_PERI_RST0_UART3] = 0 * RST_NR_PER_BANK + 3,
+ [MT6735_PERI_RST0_UART4] = 0 * RST_NR_PER_BANK + 4,
+ [MT6735_PERI_RST0_BTIF] = 0 * RST_NR_PER_BANK + 6,
+ [MT6735_PERI_RST0_DISP_PWM_PERI] = 0 * RST_NR_PER_BANK + 7,
+ [MT6735_PERI_RST0_PWM] = 0 * RST_NR_PER_BANK + 8,
+ [MT6735_PERI_RST0_AUXADC] = 0 * RST_NR_PER_BANK + 10,
+ [MT6735_PERI_RST0_DMA] = 0 * RST_NR_PER_BANK + 11,
+ [MT6735_PERI_RST0_IRDA] = 0 * RST_NR_PER_BANK + 12,
+ [MT6735_PERI_RST0_IRTX] = 0 * RST_NR_PER_BANK + 13,
+ [MT6735_PERI_RST0_THERM] = 0 * RST_NR_PER_BANK + 16,
+ [MT6735_PERI_RST0_MSDC2] = 0 * RST_NR_PER_BANK + 17,
+ [MT6735_PERI_RST0_MSDC3] = 0 * RST_NR_PER_BANK + 18,
+ [MT6735_PERI_RST0_MSDC0] = 0 * RST_NR_PER_BANK + 19,
+ [MT6735_PERI_RST0_MSDC1] = 0 * RST_NR_PER_BANK + 20,
+ [MT6735_PERI_RST0_I2C0] = 0 * RST_NR_PER_BANK + 22,
+ [MT6735_PERI_RST0_I2C1] = 0 * RST_NR_PER_BANK + 23,
+ [MT6735_PERI_RST0_I2C2] = 0 * RST_NR_PER_BANK + 24,
+ [MT6735_PERI_RST0_I2C3] = 0 * RST_NR_PER_BANK + 25,
+ [MT6735_PERI_RST0_USB] = 0 * RST_NR_PER_BANK + 28,
+
+ [MT6735_PERI_RST1_SPI0] = 1 * RST_NR_PER_BANK + 1,
+};
+
+static const struct mtk_clk_rst_desc pericfg_resets = {
+ .version = MTK_RST_SIMPLE,
+ .rst_bank_ofs = pericfg_rst_bank_ofs,
+ .rst_bank_nr = ARRAY_SIZE(pericfg_rst_bank_ofs),
+ .rst_idx_map = pericfg_rst_idx_map,
+ .rst_idx_map_nr = ARRAY_SIZE(pericfg_rst_idx_map)
+};
+
+static const struct mtk_clk_desc pericfg_clks = {
+ .clks = pericfg_gates,
+ .num_clks = ARRAY_SIZE(pericfg_gates),
+
+ .rst_desc = &pericfg_resets
+};
+
+static const struct of_device_id of_match_mt6735_pericfg[] = {
+ { .compatible = "mediatek,mt6735-pericfg", .data = &pericfg_clks },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_mt6735_pericfg);
+
+static struct platform_driver clk_mt6735_pericfg = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt6735-pericfg",
+ .of_match_table = of_match_mt6735_pericfg,
+ },
+};
+module_platform_driver(clk_mt6735_pericfg);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("MediaTek MT6735 pericfg clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt6735-topckgen.c b/drivers/clk/mediatek/clk-mt6735-topckgen.c
new file mode 100644
index 000000000000..2589ebfe2271
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-topckgen.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-topckgen.h>
+
+#define CLK_CFG_0 0x40
+#define CLK_CFG_0_SET 0x44
+#define CLK_CFG_0_CLR 0x48
+#define CLK_CFG_1 0x50
+#define CLK_CFG_1_SET 0x54
+#define CLK_CFG_1_CLR 0x58
+#define CLK_CFG_2 0x60
+#define CLK_CFG_2_SET 0x64
+#define CLK_CFG_2_CLR 0x68
+#define CLK_CFG_3 0x70
+#define CLK_CFG_3_SET 0x74
+#define CLK_CFG_3_CLR 0x78
+#define CLK_CFG_4 0x80
+#define CLK_CFG_4_SET 0x84
+#define CLK_CFG_4_CLR 0x88
+#define CLK_CFG_5 0x90
+#define CLK_CFG_5_SET 0x94
+#define CLK_CFG_5_CLR 0x98
+#define CLK_CFG_6 0xa0
+#define CLK_CFG_6_SET 0xa4
+#define CLK_CFG_6_CLR 0xa8
+#define CLK_CFG_7 0xb0
+#define CLK_CFG_7_SET 0xb4
+#define CLK_CFG_7_CLR 0xb8
+
+static DEFINE_SPINLOCK(mt6735_topckgen_lock);
+
+/* Some clocks with unknown details are modeled as fixed clocks */
+static const struct mtk_fixed_clk topckgen_fixed_clks[] = {
+ /*
+ * This clock is available as a parent option for multiple
+ * muxes and seems like an alternative name for clk26m at first,
+ * but it appears alongside it in several muxes which should
+ * mean it is a separate clock.
+ */
+ FIXED_CLK(CLK_TOP_AD_SYS_26M_CK, "ad_sys_26m_ck", "clk26m", 26 * MHZ),
+ /*
+ * This clock is the parent of DMPLL divisors. It might be MEMPLL
+ * or its parent, as DMPLL appears to be an alternative name for
+ * MEMPLL.
+ */
+ FIXED_CLK(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", NULL, 0),
+ /*
+ * DMPLL clock (dmpll_ck), controlled by DDRPHY.
+ */
+ FIXED_CLK(CLK_TOP_DMPLL, "dmpll", "clkph_mck_o", 0),
+ /*
+ * MIPI DPI clock. Parent option for dpi0_sel. Unknown parent.
+ */
+ FIXED_CLK(CLK_TOP_DPI_CK, "dpi_ck", NULL, 0),
+ /*
+ * This clock is a child of WHPLL which is controlled by
+ * the modem.
+ */
+ FIXED_CLK(CLK_TOP_WHPLL_AUDIO_CK, "whpll_audio_ck", NULL, 0)
+};
+
+static const struct mtk_fixed_factor topckgen_factors[] = {
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "mainpll", 1, 16),
+ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 4),
+ 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_VENCPLL_D3, "vencpll_d3", "vencpll", 1, 3),
+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+ FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
+ FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
+ FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
+ FACTOR(CLK_TOP_AD_SYS_26M_D2, "ad_sys_26m_d2", "clk26m", 1, 2)
+};
+
+static const char * const axi_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "dmpll",
+ "dmpll_d2"
+};
+
+static const char * const mem_sel_parents[] = {
+ "clk26m",
+ "dmpll"
+};
+
+static const char * const ddrphycfg_parents[] = {
+ "clk26m",
+ "syspll1_d8"
+};
+
+static const char * const mm_sel_parents[] = {
+ "clk26m",
+ "vencpll",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "dmpll"
+};
+
+static const char * const pwm_sel_parents[] = {
+ "clk26m",
+ "univpll2_d4",
+ "univpll3_d2",
+ "univpll1_d4"
+};
+
+static const char * const vdec_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "syspll_d2",
+ "syspll2_d2",
+ "msdcpll_d2"
+};
+
+static const char * const mfg_sel_parents[] = {
+ "clk26m",
+ "mmpll",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "syspll_d3",
+ "syspll1_d2",
+ "syspll_d5",
+ "univpll_d3",
+ "univpll1_d2"
+};
+
+static const char * const camtg_sel_parents[] = {
+ "clk26m",
+ "univpll_d26",
+ "univpll2_d2",
+ "syspll3_d2",
+ "syspll3_d4",
+ "msdcpll_d4"
+};
+
+static const char * const uart_sel_parents[] = {
+ "clk26m",
+ "univpll2_d8"
+};
+
+static const char * const spi_sel_parents[] = {
+ "clk26m",
+ "syspll3_d2",
+ "msdcpll_d8",
+ "syspll2_d4",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8"
+};
+
+static const char * const usb20_sel_parents[] = {
+ "clk26m",
+ "univpll1_d8",
+ "univpll3_d4"
+};
+
+static const char * const msdc50_0_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll2_d2",
+ "syspll4_d2",
+ "univpll_d5",
+ "univpll1_d4"
+};
+
+static const char * const msdc30_0_sel_parents[] = {
+ "clk26m",
+ "msdcpll",
+ "msdcpll_d2",
+ "msdcpll_d4",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll_d3",
+ "univpll_d26",
+ "syspll2_d4",
+ "univpll_d2"
+};
+
+static const char * const msdc30_1_2_sel_parents[] = {
+ "clk26m",
+ "univpll2_d2",
+ "msdcpll_d4",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll_d26",
+ "syspll2_d4"
+};
+
+static const char * const msdc30_3_sel_parents[] = {
+ "clk26m",
+ "univpll2_d2",
+ "msdcpll_d4",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll_d26",
+ "msdcpll_d16",
+ "syspll2_d4"
+};
+
+static const char * const audio_sel_parents[] = {
+ "clk26m",
+ "syspll3_d4",
+ "syspll4_d4",
+ "syspll1_d16"
+};
+
+static const char * const aud_intbus_sel_parents[] = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll4_d2",
+ "dmpll_d4"
+};
+
+static const char * const pmicspi_sel_parents[] = {
+ "clk26m",
+ "syspll1_d8",
+ "syspll3_d4",
+ "syspll1_d16",
+ "univpll3_d4",
+ "univpll_d26",
+ "dmpll_d4",
+ "dmpll_d8"
+};
+
+static const char * const scp_sel_parents[] = {
+ "clk26m",
+ "syspll1_d8",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const atb_sel_parents[] = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "dmpll"
+};
+
+static const char * const dpi0_sel_parents[] = {
+ "clk26m",
+ "tvdpll",
+ "tvdpll_d2",
+ "tvdpll_d4",
+ "dpi_ck"
+};
+
+static const char * const scam_sel_parents[] = {
+ "clk26m",
+ "syspll3_d2",
+ "univpll2_d4",
+ "vencpll_d3"
+};
+
+static const char * const mfg13m_sel_parents[] = {
+ "clk26m",
+ "ad_sys_26m_d2"
+};
+
+static const char * const aud_1_2_sel_parents[] = {
+ "clk26m",
+ "apll1"
+};
+
+static const char * const irda_sel_parents[] = {
+ "clk26m",
+ "univpll2_d4"
+};
+
+static const char * const irtx_sel_parents[] = {
+ "clk26m",
+ "ad_sys_26m_ck"
+};
+
+static const char * const disppwm_sel_parents[] = {
+ "clk26m",
+ "univpll2_d4",
+ "syspll4_d2_d8",
+ "ad_sys_26m_ck"
+};
+
+static const struct mtk_mux topckgen_muxes[] = {
+ MUX_CLR_SET_UPD(CLK_TOP_AXI_SEL, "axi_sel", axi_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 0, 3, 0, 0),
+ MUX_CLR_SET_UPD(CLK_TOP_MEM_SEL, "mem_sel", mem_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 8, 1, 0, 0),
+ MUX_CLR_SET_UPD(CLK_TOP_DDRPHY_SEL, "ddrphycfg_sel", ddrphycfg_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 1, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 24, 3, 31, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 0, 2, 7, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 8, 3, 15, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_SEL, "mfg_sel", mfg_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 16, 4, 23, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 24, 3, 31, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 0, 1, 7, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 8, 3, 15, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB20_SEL, "usb20_sel", usb20_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 16, 2, 23, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 3, 31, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 0, 4, 7, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_2_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 8, 3, 15, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_1_2_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 16, 3, 23, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 24, 4, 31, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 0, 2, 7, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 8, 2, 15, 0, 0),
+ MUX_CLR_SET_UPD(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 16, 3, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", scp_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 24, 2, 31, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel", atb_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 0, 2, 7, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 8, 3, 15, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SCAM_SEL, "scam_sel", scam_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 16, 2, 23, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG13M_SEL, "mfg13m_sel", mfg13m_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 24, 1, 31, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD1_SEL, "aud_1_sel", aud_1_2_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 0, 1, 7, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD2_SEL, "aud_2_sel", aud_1_2_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 8, 1, 15, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IRDA_SEL, "irda_sel", irda_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 16, 1, 23, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IRTX_SEL, "irtx_sel", irtx_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 24, 1, 31, 0, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DISPPWM_SEL, "disppwm_sel", disppwm_sel_parents, CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 0, 2, 7, 0, 0),
+};
+
+static const struct mtk_clk_desc topckgen_desc = {
+ .fixed_clks = topckgen_fixed_clks,
+ .num_fixed_clks = ARRAY_SIZE(topckgen_fixed_clks),
+ .factor_clks = topckgen_factors,
+ .num_factor_clks = ARRAY_SIZE(topckgen_factors),
+ .mux_clks = topckgen_muxes,
+ .num_mux_clks = ARRAY_SIZE(topckgen_muxes),
+ .clk_lock = &mt6735_topckgen_lock,
+};
+
+static const struct of_device_id of_match_mt6735_topckgen[] = {
+ { .compatible = "mediatek,mt6735-topckgen", .data = &topckgen_desc},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_mt6735_topckgen);
+
+static struct platform_driver clk_mt6735_topckgen = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt6735-topckgen",
+ .of_match_table = of_match_mt6735_topckgen,
+ },
+};
+module_platform_driver(clk_mt6735_topckgen);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("MediaTek MT6735 topckgen clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt6735-vdecsys.c b/drivers/clk/mediatek/clk-mt6735-vdecsys.c
new file mode 100644
index 000000000000..8817085fc1db
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-vdecsys.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-vdecsys.h>
+#include <dt-bindings/reset/mediatek,mt6735-vdecsys.h>
+
+#define VDEC_CKEN_SET 0x00
+#define VDEC_CKEN_CLR 0x04
+#define SMI_LARB1_CKEN_SET 0x08
+#define SMI_LARB1_CKEN_CLR 0x0c
+#define VDEC_RESETB_CON 0x10
+#define SMI_LARB1_RESETB_CON 0x14
+
+#define RST_NR_PER_BANK 32
+
+static struct mtk_gate_regs vdec_cg_regs = {
+ .set_ofs = VDEC_CKEN_SET,
+ .clr_ofs = VDEC_CKEN_CLR,
+ .sta_ofs = VDEC_CKEN_SET,
+};
+
+static struct mtk_gate_regs smi_larb1_cg_regs = {
+ .set_ofs = SMI_LARB1_CKEN_SET,
+ .clr_ofs = SMI_LARB1_CKEN_CLR,
+ .sta_ofs = SMI_LARB1_CKEN_SET,
+};
+
+static const struct mtk_gate vdecsys_gates[] = {
+ GATE_MTK(CLK_VDEC_VDEC, "vdec", "vdec_sel", &vdec_cg_regs, 0, &mtk_clk_gate_ops_setclr_inv),
+ GATE_MTK(CLK_VDEC_SMI_LARB1, "smi_larb1", "vdec_sel", &smi_larb1_cg_regs, 0, &mtk_clk_gate_ops_setclr_inv),
+};
+
+static u16 vdecsys_rst_bank_ofs[] = { VDEC_RESETB_CON, SMI_LARB1_RESETB_CON };
+
+static u16 vdecsys_rst_idx_map[] = {
+ [MT6735_VDEC_RST0_VDEC] = 0 * RST_NR_PER_BANK + 0,
+ [MT6735_VDEC_RST1_SMI_LARB1] = 1 * RST_NR_PER_BANK + 0,
+};
+
+static const struct mtk_clk_rst_desc vdecsys_resets = {
+ .version = MTK_RST_SIMPLE,
+ .rst_bank_ofs = vdecsys_rst_bank_ofs,
+ .rst_bank_nr = ARRAY_SIZE(vdecsys_rst_bank_ofs),
+ .rst_idx_map = vdecsys_rst_idx_map,
+ .rst_idx_map_nr = ARRAY_SIZE(vdecsys_rst_idx_map)
+};
+
+static const struct mtk_clk_desc vdecsys_clks = {
+ .clks = vdecsys_gates,
+ .num_clks = ARRAY_SIZE(vdecsys_gates),
+ .rst_desc = &vdecsys_resets
+};
+
+static const struct of_device_id of_match_mt6735_vdecsys[] = {
+ { .compatible = "mediatek,mt6735-vdecsys", .data = &vdecsys_clks },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt6735_vdecsys = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt6735-vdecsys",
+ .of_match_table = of_match_mt6735_vdecsys,
+ },
+};
+module_platform_driver(clk_mt6735_vdecsys);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("MediaTek MT6735 vdecsys clock and reset driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt6735-vencsys.c b/drivers/clk/mediatek/clk-mt6735-vencsys.c
new file mode 100644
index 000000000000..8dec7f98492a
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt6735-vencsys.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-gate.h"
+#include "clk-mtk.h"
+
+#include <dt-bindings/clock/mediatek,mt6735-vencsys.h>
+
+#define VENC_CG_CON 0x00
+#define VENC_CG_SET 0x04
+#define VENC_CG_CLR 0x08
+
+static struct mtk_gate_regs venc_cg_regs = {
+ .set_ofs = VENC_CG_SET,
+ .clr_ofs = VENC_CG_CLR,
+ .sta_ofs = VENC_CG_CON,
+};
+
+static const struct mtk_gate vencsys_gates[] = {
+ GATE_MTK(CLK_VENC_SMI_LARB3, "smi_larb3", "mm_sel", &venc_cg_regs, 0, &mtk_clk_gate_ops_setclr_inv),
+ GATE_MTK(CLK_VENC_VENC, "venc", "mm_sel", &venc_cg_regs, 4, &mtk_clk_gate_ops_setclr_inv),
+ GATE_MTK(CLK_VENC_JPGENC, "jpgenc", "mm_sel", &venc_cg_regs, 8, &mtk_clk_gate_ops_setclr_inv),
+ GATE_MTK(CLK_VENC_JPGDEC, "jpgdec", "mm_sel", &venc_cg_regs, 12, &mtk_clk_gate_ops_setclr_inv),
+};
+
+static const struct mtk_clk_desc vencsys_clks = {
+ .clks = vencsys_gates,
+ .num_clks = ARRAY_SIZE(vencsys_gates),
+};
+
+static const struct of_device_id of_match_mt6735_vencsys[] = {
+ { .compatible = "mediatek,mt6735-vencsys", .data = &vencsys_clks },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt6735_vencsys = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt6735-vencsys",
+ .of_match_table = of_match_mt6735_vencsys,
+ },
+};
+module_platform_driver(clk_mt6735_vencsys);
+
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Mediatek MT6735 vencsys clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mediatek/clk-mt8188-topckgen.c b/drivers/clk/mediatek/clk-mt8188-topckgen.c
index c4baf4076ed6..6b07abe9a8f5 100644
--- a/drivers/clk/mediatek/clk-mt8188-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8188-topckgen.c
@@ -342,11 +342,14 @@ static const char * const dsp7_parents[] = {
"univpll_d3"
};
+/*
+ * MFG can be also parented to "univpll_d6" and "univpll_d7":
+ * these have been removed from the parents list to let us
+ * achieve GPU DVFS without any special clock handlers.
+ */
static const char * const mfg_core_tmp_parents[] = {
"clk26m",
- "mainpll_d5_d2",
- "univpll_d6",
- "univpll_d7"
+ "mainpll_d5_d2"
};
static const char * const camtg_parents[] = {
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 78f648c9c97d..febb5d7348ff 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -106,6 +106,7 @@ config COMMON_CLK_AXG_AUDIO
select COMMON_CLK_MESON_SCLK_DIV
select COMMON_CLK_MESON_CLKC_UTILS
select REGMAP_MMIO
+ depends on RESET_MESON_AUX
help
Support for the audio clock controller on AmLogic A113D devices,
aka axg, Say Y if you want audio subsystem to work.
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index beda86349389..7714bde5ffc0 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -15,6 +15,8 @@
#include <linux/reset-controller.h>
#include <linux/slab.h>
+#include <soc/amlogic/reset-meson-aux.h>
+
#include "meson-clkc-utils.h"
#include "axg-audio.h"
#include "clk-regmap.h"
@@ -1678,84 +1680,6 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
&sm1_earcrx_dmac_clk,
};
-struct axg_audio_reset_data {
- struct reset_controller_dev rstc;
- struct regmap *map;
- unsigned int offset;
-};
-
-static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
- unsigned long id,
- unsigned int *reg,
- unsigned int *bit)
-{
- unsigned int stride = regmap_get_reg_stride(rst->map);
-
- *reg = (id / (stride * BITS_PER_BYTE)) * stride;
- *reg += rst->offset;
- *bit = id % (stride * BITS_PER_BYTE);
-}
-
-static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
- unsigned long id, bool assert)
-{
- struct axg_audio_reset_data *rst =
- container_of(rcdev, struct axg_audio_reset_data, rstc);
- unsigned int offset, bit;
-
- axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
-
- regmap_update_bits(rst->map, offset, BIT(bit),
- assert ? BIT(bit) : 0);
-
- return 0;
-}
-
-static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct axg_audio_reset_data *rst =
- container_of(rcdev, struct axg_audio_reset_data, rstc);
- unsigned int val, offset, bit;
-
- axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
-
- regmap_read(rst->map, offset, &val);
-
- return !!(val & BIT(bit));
-}
-
-static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- return axg_audio_reset_update(rcdev, id, true);
-}
-
-static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- return axg_audio_reset_update(rcdev, id, false);
-}
-
-static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- int ret;
-
- ret = axg_audio_reset_assert(rcdev, id);
- if (ret)
- return ret;
-
- return axg_audio_reset_deassert(rcdev, id);
-}
-
-static const struct reset_control_ops axg_audio_rstc_ops = {
- .assert = axg_audio_reset_assert,
- .deassert = axg_audio_reset_deassert,
- .reset = axg_audio_reset_toggle,
- .status = axg_audio_reset_status,
-};
-
static struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
@@ -1766,16 +1690,14 @@ struct audioclk_data {
struct clk_regmap *const *regmap_clks;
unsigned int regmap_clk_num;
struct meson_clk_hw_data hw_clks;
- unsigned int reset_offset;
- unsigned int reset_num;
unsigned int max_register;
+ const char *rst_drvname;
};
static int axg_audio_clkc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct audioclk_data *data;
- struct axg_audio_reset_data *rst;
struct regmap *map;
void __iomem *regs;
struct clk_hw *hw;
@@ -1834,22 +1756,11 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
if (ret)
return ret;
- /* Stop here if there is no reset */
- if (!data->reset_num)
- return 0;
-
- rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
- if (!rst)
- return -ENOMEM;
-
- rst->map = map;
- rst->offset = data->reset_offset;
- rst->rstc.nr_resets = data->reset_num;
- rst->rstc.ops = &axg_audio_rstc_ops;
- rst->rstc.of_node = dev->of_node;
- rst->rstc.owner = THIS_MODULE;
+ /* Register auxiliary reset driver when applicable */
+ if (data->rst_drvname)
+ ret = devm_meson_rst_aux_register(dev, map, data->rst_drvname);
- return devm_reset_controller_register(dev, &rst->rstc);
+ return ret;
}
static const struct audioclk_data axg_audioclk_data = {
@@ -1869,9 +1780,8 @@ static const struct audioclk_data g12a_audioclk_data = {
.hws = g12a_audio_hw_clks,
.num = ARRAY_SIZE(g12a_audio_hw_clks),
},
- .reset_offset = AUDIO_SW_RESET,
- .reset_num = 26,
.max_register = AUDIO_CLK_SPDIFOUT_B_CTRL,
+ .rst_drvname = "rst-g12a",
};
static const struct audioclk_data sm1_audioclk_data = {
@@ -1881,9 +1791,8 @@ static const struct audioclk_data sm1_audioclk_data = {
.hws = sm1_audio_hw_clks,
.num = ARRAY_SIZE(sm1_audio_hw_clks),
},
- .reset_offset = AUDIO_SM1_SW_RESET0,
- .reset_num = 39,
.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
+ .rst_drvname = "rst-sm1",
};
static const struct of_device_id clkc_match_table[] = {
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 757c7a28c53d..1b08daf579b2 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -23,8 +23,6 @@
#include <dt-bindings/clock/axg-clkc.h>
-static DEFINE_SPINLOCK(meson_clk_lock);
-
static struct clk_regmap axg_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
@@ -506,7 +504,6 @@ static struct clk_regmap axg_mpll0_div = {
.shift = 0,
.width = 1,
},
- .lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
@@ -557,7 +554,6 @@ static struct clk_regmap axg_mpll1_div = {
.shift = 1,
.width = 1,
},
- .lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
@@ -613,7 +609,6 @@ static struct clk_regmap axg_mpll2_div = {
.shift = 2,
.width = 1,
},
- .lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
@@ -664,7 +659,6 @@ static struct clk_regmap axg_mpll3_div = {
.shift = 3,
.width = 1,
},
- .lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
diff --git a/drivers/clk/meson/c3-pll.c b/drivers/clk/meson/c3-pll.c
index 32bd2ed9d304..35fda31a19e2 100644
--- a/drivers/clk/meson/c3-pll.c
+++ b/drivers/clk/meson/c3-pll.c
@@ -361,6 +361,7 @@ static struct clk_regmap hifi_pll_dco = {
.range = &c3_gp0_pll_mult_range,
.init_regs = c3_hifi_init_regs,
.init_count = ARRAY_SIZE(c3_hifi_init_regs),
+ .frac_max = 100000,
},
.hw.init = &(struct clk_init_data) {
.name = "hifi_pll_dco",
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index f639d56f0fd3..aa9abd06ae65 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -112,26 +112,15 @@ static int mpll_set_rate(struct clk_hw *hw,
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
unsigned int sdm, n2;
- unsigned long flags = 0;
params_from_rate(rate, parent_rate, &sdm, &n2, mpll->flags);
- if (mpll->lock)
- spin_lock_irqsave(mpll->lock, flags);
- else
- __acquire(mpll->lock);
-
/* Set the fractional part */
meson_parm_write(clk->map, &mpll->sdm, sdm);
/* Set the integer divider part */
meson_parm_write(clk->map, &mpll->n2, n2);
- if (mpll->lock)
- spin_unlock_irqrestore(mpll->lock, flags);
- else
- __release(mpll->lock);
-
return 0;
}
diff --git a/drivers/clk/meson/clk-mpll.h b/drivers/clk/meson/clk-mpll.h
index a991d568c43a..4ffd3aeef799 100644
--- a/drivers/clk/meson/clk-mpll.h
+++ b/drivers/clk/meson/clk-mpll.h
@@ -20,7 +20,6 @@ struct meson_clk_mpll_data {
struct parm misc;
const struct reg_sequence *init_regs;
unsigned int init_count;
- spinlock_t *lock;
u8 flags;
};
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index bc570a2ff3a3..89f0f04a16ab 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -57,12 +57,13 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
struct meson_clk_pll_data *pll)
{
u64 rate = (u64)parent_rate * m;
+ unsigned int frac_max = pll->frac_max ? pll->frac_max :
+ (1 << pll->frac.width);
if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
u64 frac_rate = (u64)parent_rate * frac;
- rate += DIV_ROUND_UP_ULL(frac_rate,
- (1 << pll->frac.width));
+ rate += DIV_ROUND_UP_ULL(frac_rate, frac_max);
}
return DIV_ROUND_UP_ULL(rate, n);
@@ -100,7 +101,8 @@ static unsigned int __pll_params_with_frac(unsigned long rate,
unsigned int n,
struct meson_clk_pll_data *pll)
{
- unsigned int frac_max = (1 << pll->frac.width);
+ unsigned int frac_max = pll->frac_max ? pll->frac_max :
+ (1 << pll->frac.width);
u64 val = (u64)rate * n;
/* Bail out if we are already over the requested rate */
diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h
index 7b6b87274073..949157fb7bf5 100644
--- a/drivers/clk/meson/clk-pll.h
+++ b/drivers/clk/meson/clk-pll.h
@@ -43,6 +43,7 @@ struct meson_clk_pll_data {
unsigned int init_count;
const struct pll_params_table *table;
const struct pll_mult_range *range;
+ unsigned int frac_max;
u8 flags;
};
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
index 02dda57105b1..d3539fe9f7af 100644
--- a/drivers/clk/meson/g12a.c
+++ b/drivers/clk/meson/g12a.c
@@ -28,8 +28,6 @@
#include <dt-bindings/clock/g12a-clkc.h>
-static DEFINE_SPINLOCK(meson_clk_lock);
-
static struct clk_regmap g12a_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
@@ -2225,7 +2223,6 @@ static struct clk_regmap g12a_mpll0_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = g12a_mpll0_init_regs,
.init_count = ARRAY_SIZE(g12a_mpll0_init_regs),
},
@@ -2279,7 +2276,6 @@ static struct clk_regmap g12a_mpll1_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = g12a_mpll1_init_regs,
.init_count = ARRAY_SIZE(g12a_mpll1_init_regs),
},
@@ -2333,7 +2329,6 @@ static struct clk_regmap g12a_mpll2_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = g12a_mpll2_init_regs,
.init_count = ARRAY_SIZE(g12a_mpll2_init_regs),
},
@@ -2387,7 +2382,6 @@ static struct clk_regmap g12a_mpll3_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = g12a_mpll3_init_regs,
.init_count = ARRAY_SIZE(g12a_mpll3_init_regs),
},
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index f071faad1ebb..262c318edbd5 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -19,8 +19,6 @@
#include <dt-bindings/clock/gxbb-clkc.h>
-static DEFINE_SPINLOCK(meson_clk_lock);
-
static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
PLL_PARAMS(32, 1),
PLL_PARAMS(33, 1),
@@ -731,7 +729,6 @@ static struct clk_regmap gxbb_mpll0_div = {
.shift = 16,
.width = 9,
},
- .lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
@@ -760,7 +757,6 @@ static struct clk_regmap gxl_mpll0_div = {
.shift = 16,
.width = 9,
},
- .lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
@@ -812,7 +808,6 @@ static struct clk_regmap gxbb_mpll1_div = {
.shift = 16,
.width = 9,
},
- .lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
@@ -855,7 +850,6 @@ static struct clk_regmap gxbb_mpll2_div = {
.shift = 16,
.width = 9,
},
- .lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index b7417ac262d3..e4b474c5f86c 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -25,8 +25,6 @@
#include <dt-bindings/clock/meson8b-clkc.h>
#include <dt-bindings/reset/amlogic,meson8b-clkc-reset.h>
-static DEFINE_SPINLOCK(meson_clk_lock);
-
struct meson8b_clk_reset {
struct reset_controller_dev reset;
struct regmap *regmap;
@@ -492,7 +490,6 @@ static struct clk_regmap meson8b_mpll0_div = {
.shift = 25,
.width = 1,
},
- .lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
@@ -537,7 +534,6 @@ static struct clk_regmap meson8b_mpll1_div = {
.shift = 16,
.width = 9,
},
- .lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
@@ -582,7 +578,6 @@ static struct clk_regmap meson8b_mpll2_div = {
.shift = 16,
.width = 9,
},
- .lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
@@ -3702,7 +3697,6 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
container_of(rcdev, struct meson8b_clk_reset, reset);
const struct meson8b_clk_reset_line *reset;
unsigned int value = 0;
- unsigned long flags;
if (id >= ARRAY_SIZE(meson8b_clk_reset_bits))
return -EINVAL;
@@ -3712,13 +3706,9 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
if (assert != reset->active_low)
value = BIT(reset->bit_idx);
- spin_lock_irqsave(&meson_clk_lock, flags);
-
regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
BIT(reset->bit_idx), value);
- spin_unlock_irqrestore(&meson_clk_lock, flags);
-
return 0;
}
diff --git a/drivers/clk/meson/s4-pll.c b/drivers/clk/meson/s4-pll.c
index b0258933fb9d..d8e621e79428 100644
--- a/drivers/clk/meson/s4-pll.c
+++ b/drivers/clk/meson/s4-pll.c
@@ -17,8 +17,6 @@
#include "meson-clkc-utils.h"
#include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
-static DEFINE_SPINLOCK(meson_clk_lock);
-
/*
* These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode.
* The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable
@@ -329,7 +327,6 @@ static struct clk_regmap s4_gp0_pll = {
* Internal hifi pll emulation configuration parameters
*/
static const struct reg_sequence s4_hifi_init_regs[] = {
- { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x00010e56 },
{ .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 },
{ .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
{ .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
@@ -354,6 +351,11 @@ static struct clk_regmap s4_hifi_pll_dco = {
.shift = 10,
.width = 5,
},
+ .frac = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL1,
+ .shift = 0,
+ .width = 17,
+ },
.l = {
.reg_off = ANACTRL_HIFIPLL_CTRL0,
.shift = 31,
@@ -367,6 +369,7 @@ static struct clk_regmap s4_hifi_pll_dco = {
.range = &s4_gp0_pll_mult_range,
.init_regs = s4_hifi_init_regs,
.init_count = ARRAY_SIZE(s4_hifi_init_regs),
+ .frac_max = 100000,
.flags = CLK_MESON_PLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
@@ -542,7 +545,6 @@ static struct clk_regmap s4_mpll0_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = s4_mpll0_init_regs,
.init_count = ARRAY_SIZE(s4_mpll0_init_regs),
},
@@ -596,7 +598,6 @@ static struct clk_regmap s4_mpll1_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = s4_mpll1_init_regs,
.init_count = ARRAY_SIZE(s4_mpll1_init_regs),
},
@@ -650,7 +651,6 @@ static struct clk_regmap s4_mpll2_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = s4_mpll2_init_regs,
.init_count = ARRAY_SIZE(s4_mpll2_init_regs),
},
@@ -704,7 +704,6 @@ static struct clk_regmap s4_mpll3_div = {
.shift = 29,
.width = 1,
},
- .lock = &meson_clk_lock,
.init_regs = s4_mpll3_init_regs,
.init_count = ARRAY_SIZE(s4_mpll3_init_regs),
},
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 441bf83080a1..062cd87fa8dd 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -11,4 +11,4 @@ obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o
obj-$(CONFIG_COMMON_CLK_MMP2_AUDIO) += clk-audio.o
-obj-y += clk-of-pxa1928.o
+obj-$(CONFIG_ARCH_MMP) += clk-of-pxa1928.o clk-pxa1908-apbc.o clk-pxa1908-apbcp.o clk-pxa1908-apmu.o clk-pxa1908-mpmu.o
diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 1b90867b60c4..6556f6ada2e8 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -26,14 +26,15 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
u64 rate = 0, prev_rate;
+ struct u32_fract *d;
int i;
for (i = 0; i < factor->ftbl_cnt; i++) {
- prev_rate = rate;
- rate = *prate;
- rate *= factor->ftbl[i].den;
- do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+ d = &factor->ftbl[i];
+ prev_rate = rate;
+ rate = (u64)(*prate) * d->denominator;
+ do_div(rate, d->numerator * factor->masks->factor);
if (rate > drate)
break;
}
@@ -52,23 +53,22 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
- unsigned int val, num, den;
+ struct u32_fract d;
+ unsigned int val;
u64 rate;
val = readl_relaxed(factor->base);
/* calculate numerator */
- num = (val >> masks->num_shift) & masks->num_mask;
+ d.numerator = (val >> masks->num_shift) & masks->num_mask;
/* calculate denominator */
- den = (val >> masks->den_shift) & masks->den_mask;
-
- if (!den)
+ d.denominator = (val >> masks->den_shift) & masks->den_mask;
+ if (!d.denominator)
return 0;
- rate = parent_rate;
- rate *= den;
- do_div(rate, num * factor->masks->factor);
+ rate = (u64)parent_rate * d.denominator;
+ do_div(rate, d.numerator * factor->masks->factor);
return rate;
}
@@ -82,18 +82,18 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
int i;
unsigned long val;
unsigned long flags = 0;
+ struct u32_fract *d;
u64 rate = 0;
for (i = 0; i < factor->ftbl_cnt; i++) {
- rate = prate;
- rate *= factor->ftbl[i].den;
- do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+ d = &factor->ftbl[i];
+ rate = (u64)prate * d->denominator;
+ do_div(rate, d->numerator * factor->masks->factor);
if (rate > drate)
break;
}
- if (i > 0)
- i--;
+ d = i ? &factor->ftbl[i - 1] : &factor->ftbl[0];
if (factor->lock)
spin_lock_irqsave(factor->lock, flags);
@@ -101,10 +101,10 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
val = readl_relaxed(factor->base);
val &= ~(masks->num_mask << masks->num_shift);
- val |= (factor->ftbl[i].num & masks->num_mask) << masks->num_shift;
+ val |= (d->numerator & masks->num_mask) << masks->num_shift;
val &= ~(masks->den_mask << masks->den_shift);
- val |= (factor->ftbl[i].den & masks->den_mask) << masks->den_shift;
+ val |= (d->denominator & masks->den_mask) << masks->den_shift;
writel_relaxed(val, factor->base);
@@ -118,7 +118,8 @@ static int clk_factor_init(struct clk_hw *hw)
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
- u32 val, num, den;
+ struct u32_fract d;
+ u32 val;
int i;
unsigned long flags = 0;
@@ -128,23 +129,22 @@ static int clk_factor_init(struct clk_hw *hw)
val = readl(factor->base);
/* calculate numerator */
- num = (val >> masks->num_shift) & masks->num_mask;
+ d.numerator = (val >> masks->num_shift) & masks->num_mask;
/* calculate denominator */
- den = (val >> masks->den_shift) & masks->den_mask;
+ d.denominator = (val >> masks->den_shift) & masks->den_mask;
for (i = 0; i < factor->ftbl_cnt; i++)
- if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
+ if (d.denominator == factor->ftbl[i].denominator &&
+ d.numerator == factor->ftbl[i].numerator)
break;
if (i >= factor->ftbl_cnt) {
val &= ~(masks->num_mask << masks->num_shift);
- val |= (factor->ftbl[0].num & masks->num_mask) <<
- masks->num_shift;
+ val |= (factor->ftbl[0].numerator & masks->num_mask) << masks->num_shift;
val &= ~(masks->den_mask << masks->den_shift);
- val |= (factor->ftbl[0].den & masks->den_mask) <<
- masks->den_shift;
+ val |= (factor->ftbl[0].denominator & masks->den_mask) << masks->den_shift;
}
if (!(val & masks->enable_mask) || i >= factor->ftbl_cnt) {
@@ -168,8 +168,7 @@ static const struct clk_ops clk_factor_ops = {
struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
unsigned long flags, void __iomem *base,
struct mmp_clk_factor_masks *masks,
- struct mmp_clk_factor_tbl *ftbl,
- unsigned int ftbl_cnt, spinlock_t *lock)
+ struct u32_fract *ftbl, unsigned int ftbl_cnt, spinlock_t *lock)
{
struct mmp_clk_factor *factor;
struct clk_init_data init;
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index eaad36ee323d..a4f15cee630e 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -143,9 +143,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
.den_shift = 0,
};
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
- {.num = 8125, .den = 1536}, /*14.745MHZ */
- {.num = 3521, .den = 689}, /*19.23MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+ { .numerator = 8125, .denominator = 1536 }, /* 14.745MHZ */
+ { .numerator = 3521, .denominator = 689 }, /* 19.23MHZ */
};
static struct mmp_clk_factor_masks i2s_factor_masks = {
@@ -157,16 +157,16 @@ static struct mmp_clk_factor_masks i2s_factor_masks = {
.enable_mask = 0xd0000000,
};
-static struct mmp_clk_factor_tbl i2s_factor_tbl[] = {
- {.num = 24868, .den = 511}, /* 2.0480 MHz */
- {.num = 28003, .den = 793}, /* 2.8224 MHz */
- {.num = 24941, .den = 1025}, /* 4.0960 MHz */
- {.num = 28003, .den = 1586}, /* 5.6448 MHz */
- {.num = 31158, .den = 2561}, /* 8.1920 MHz */
- {.num = 16288, .den = 1845}, /* 11.2896 MHz */
- {.num = 20772, .den = 2561}, /* 12.2880 MHz */
- {.num = 8144, .den = 1845}, /* 22.5792 MHz */
- {.num = 10386, .den = 2561}, /* 24.5760 MHz */
+static struct u32_fract i2s_factor_tbl[] = {
+ { .numerator = 24868, .denominator = 511 }, /* 2.0480 MHz */
+ { .numerator = 28003, .denominator = 793 }, /* 2.8224 MHz */
+ { .numerator = 24941, .denominator = 1025 }, /* 4.0960 MHz */
+ { .numerator = 28003, .denominator = 1586 }, /* 5.6448 MHz */
+ { .numerator = 31158, .denominator = 2561 }, /* 8.1920 MHz */
+ { .numerator = 16288, .denominator = 1845 }, /* 11.2896 MHz */
+ { .numerator = 20772, .denominator = 2561 }, /* 12.2880 MHz */
+ { .numerator = 8144, .denominator = 1845 }, /* 22.5792 MHz */
+ { .numerator = 10386, .denominator = 2561 }, /* 24.5760 MHz */
};
static DEFINE_SPINLOCK(acgr_lock);
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index c5a7ba1deaa3..5f250427e60d 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -106,8 +106,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
.den_shift = 0,
};
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
- {.num = 8125, .den = 1536}, /*14.745MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+ { .numerator = 8125, .denominator = 1536 }, /* 14.745MHZ */
};
static void pxa168_pll_init(struct pxa168_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c
index 9def4b5f10e9..ebb6e278eda3 100644
--- a/drivers/clk/mmp/clk-of-pxa1928.c
+++ b/drivers/clk/mmp/clk-of-pxa1928.c
@@ -61,9 +61,9 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
.den_shift = 0,
};
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
- {.num = 832, .den = 234}, /*58.5MHZ */
- {.num = 1, .den = 1}, /*26MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+ { .numerator = 832, .denominator = 234 }, /* 58.5MHZ */
+ { .numerator = 1, .denominator = 1 }, /* 26MHZ */
};
static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 7a38c424782e..fe65e7bdb411 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -86,8 +86,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
.den_shift = 0,
};
-static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
- {.num = 8125, .den = 1536}, /*14.745MHZ */
+static struct u32_fract uart_factor_tbl[] = {
+ { .numerator = 8125, .denominator = 1536 }, /* 14.745MHZ */
};
static void pxa910_pll_init(struct pxa910_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-pxa1908-apbc.c b/drivers/clk/mmp/clk-pxa1908-apbc.c
new file mode 100644
index 000000000000..b93d08466198
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa1908-apbc.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/marvell,pxa1908.h>
+
+#include "clk.h"
+
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO 0x8
+#define APBC_PWM0 0xc
+#define APBC_PWM1 0x10
+#define APBC_PWM2 0x14
+#define APBC_PWM3 0x18
+#define APBC_SSP0 0x1c
+#define APBC_SSP1 0x20
+#define APBC_IPC_RST 0x24
+#define APBC_RTC 0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC 0x30
+#define APBC_SWJTAG 0x40
+#define APBC_SSP2 0x4c
+#define APBC_TWSI1 0x60
+#define APBC_THERMAL 0x6c
+#define APBC_TWSI3 0x70
+
+#define APBC_NR_CLKS 19
+
+struct pxa1908_clk_unit {
+ struct mmp_clk_unit unit;
+ void __iomem *base;
+};
+
+static DEFINE_SPINLOCK(pwm0_lock);
+static DEFINE_SPINLOCK(pwm2_lock);
+
+static DEFINE_SPINLOCK(uart0_lock);
+static DEFINE_SPINLOCK(uart1_lock);
+
+static const char * const uart_parent_names[] = {"pll1_117", "uart_pll"};
+static const char * const ssp_parent_names[] = {"pll1_d16", "pll1_d48", "pll1_d24", "pll1_d12"};
+
+static struct mmp_param_gate_clk apbc_gate_clks[] = {
+ {PXA1908_CLK_TWSI0, "twsi0_clk", "pll1_32", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x7, 3, 0, 0, NULL},
+ {PXA1908_CLK_TWSI1, "twsi1_clk", "pll1_32", CLK_SET_RATE_PARENT, APBC_TWSI1, 0x7, 3, 0, 0, NULL},
+ {PXA1908_CLK_TWSI3, "twsi3_clk", "pll1_32", CLK_SET_RATE_PARENT, APBC_TWSI3, 0x7, 3, 0, 0, NULL},
+ {PXA1908_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x7, 3, 0, 0, NULL},
+ {PXA1908_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x7, 3, 0, MMP_CLK_GATE_NEED_DELAY, NULL},
+ {PXA1908_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x87, 0x83, 0, MMP_CLK_GATE_NEED_DELAY, NULL},
+ {PXA1908_CLK_PWM0, "pwm0_clk", "pwm01_apb_share", CLK_SET_RATE_PARENT, APBC_PWM0, 0x2, 2, 0, 0, &pwm0_lock},
+ {PXA1908_CLK_PWM1, "pwm1_clk", "pwm01_apb_share", CLK_SET_RATE_PARENT, APBC_PWM1, 0x6, 2, 0, 0, NULL},
+ {PXA1908_CLK_PWM2, "pwm2_clk", "pwm23_apb_share", CLK_SET_RATE_PARENT, APBC_PWM2, 0x2, 2, 0, 0, NULL},
+ {PXA1908_CLK_PWM3, "pwm3_clk", "pwm23_apb_share", CLK_SET_RATE_PARENT, APBC_PWM3, 0x6, 2, 0, 0, NULL},
+ {PXA1908_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x7, 3, 0, 0, &uart0_lock},
+ {PXA1908_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x7, 3, 0, 0, &uart1_lock},
+ {PXA1908_CLK_THERMAL, "thermal_clk", NULL, 0, APBC_THERMAL, 0x7, 3, 0, 0, NULL},
+ {PXA1908_CLK_IPC_RST, "ipc_clk", NULL, 0, APBC_IPC_RST, 0x7, 3, 0, 0, NULL},
+ {PXA1908_CLK_SSP0, "ssp0_clk", "ssp0_mux", 0, APBC_SSP0, 0x7, 3, 0, 0, NULL},
+ {PXA1908_CLK_SSP2, "ssp2_clk", "ssp2_mux", 0, APBC_SSP2, 0x7, 3, 0, 0, NULL},
+};
+
+static struct mmp_param_mux_clk apbc_mux_clks[] = {
+ {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock},
+ {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock},
+ {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 0, APBC_SSP0, 4, 3, 0, NULL},
+ {0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 0, APBC_SSP2, 4, 3, 0, NULL},
+};
+
+static void pxa1908_apb_periph_clk_init(struct pxa1908_clk_unit *pxa_unit)
+{
+ struct mmp_clk_unit *unit = &pxa_unit->unit;
+ struct clk *clk;
+
+ mmp_clk_register_gate(NULL, "pwm01_apb_share", "pll1_d48",
+ CLK_SET_RATE_PARENT,
+ pxa_unit->base + APBC_PWM0,
+ 0x5, 1, 0, 0, &pwm0_lock);
+ mmp_clk_register_gate(NULL, "pwm23_apb_share", "pll1_d48",
+ CLK_SET_RATE_PARENT,
+ pxa_unit->base + APBC_PWM2,
+ 0x5, 1, 0, 0, &pwm2_lock);
+ clk = mmp_clk_register_apbc("swjtag", NULL,
+ pxa_unit->base + APBC_SWJTAG, 10, 0, NULL);
+ mmp_clk_add(unit, PXA1908_CLK_SWJTAG, clk);
+ mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->base,
+ ARRAY_SIZE(apbc_mux_clks));
+ mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->base,
+ ARRAY_SIZE(apbc_gate_clks));
+}
+
+static int pxa1908_apbc_probe(struct platform_device *pdev)
+{
+ struct pxa1908_clk_unit *pxa_unit;
+
+ pxa_unit = devm_kzalloc(&pdev->dev, sizeof(*pxa_unit), GFP_KERNEL);
+ if (IS_ERR(pxa_unit))
+ return PTR_ERR(pxa_unit);
+
+ pxa_unit->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pxa_unit->base))
+ return PTR_ERR(pxa_unit->base);
+
+ mmp_clk_init(pdev->dev.of_node, &pxa_unit->unit, APBC_NR_CLKS);
+
+ pxa1908_apb_periph_clk_init(pxa_unit);
+
+ return 0;
+}
+
+static const struct of_device_id pxa1908_apbc_match_table[] = {
+ { .compatible = "marvell,pxa1908-apbc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pxa1908_apbc_match_table);
+
+static struct platform_driver pxa1908_apbc_driver = {
+ .probe = pxa1908_apbc_probe,
+ .driver = {
+ .name = "pxa1908-apbc",
+ .of_match_table = pxa1908_apbc_match_table
+ }
+};
+module_platform_driver(pxa1908_apbc_driver);
+
+MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>");
+MODULE_DESCRIPTION("Marvell PXA1908 APBC Clock Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mmp/clk-pxa1908-apbcp.c b/drivers/clk/mmp/clk-pxa1908-apbcp.c
new file mode 100644
index 000000000000..08f3845cbb1b
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa1908-apbcp.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/marvell,pxa1908.h>
+
+#include "clk.h"
+
+#define APBCP_UART2 0x1c
+#define APBCP_TWSI2 0x28
+#define APBCP_AICER 0x38
+
+#define APBCP_NR_CLKS 4
+
+struct pxa1908_clk_unit {
+ struct mmp_clk_unit unit;
+ void __iomem *base;
+};
+
+static DEFINE_SPINLOCK(uart2_lock);
+
+static const char * const uart_parent_names[] = {"pll1_117", "uart_pll"};
+
+static struct mmp_param_gate_clk apbcp_gate_clks[] = {
+ {PXA1908_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBCP_UART2, 0x7, 0x3, 0x0, 0, &uart2_lock},
+ {PXA1908_CLK_TWSI2, "twsi2_clk", "pll1_32", CLK_SET_RATE_PARENT, APBCP_TWSI2, 0x7, 0x3, 0x0, 0, NULL},
+ {PXA1908_CLK_AICER, "ripc_clk", NULL, 0, APBCP_AICER, 0x7, 0x2, 0x0, 0, NULL},
+};
+
+static struct mmp_param_mux_clk apbcp_mux_clks[] = {
+ {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBCP_UART2, 4, 3, 0, &uart2_lock},
+};
+
+static void pxa1908_apb_p_periph_clk_init(struct pxa1908_clk_unit *pxa_unit)
+{
+ struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+ mmp_register_mux_clks(unit, apbcp_mux_clks, pxa_unit->base,
+ ARRAY_SIZE(apbcp_mux_clks));
+ mmp_register_gate_clks(unit, apbcp_gate_clks, pxa_unit->base,
+ ARRAY_SIZE(apbcp_gate_clks));
+}
+
+static int pxa1908_apbcp_probe(struct platform_device *pdev)
+{
+ struct pxa1908_clk_unit *pxa_unit;
+
+ pxa_unit = devm_kzalloc(&pdev->dev, sizeof(*pxa_unit), GFP_KERNEL);
+ if (IS_ERR(pxa_unit))
+ return PTR_ERR(pxa_unit);
+
+ pxa_unit->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pxa_unit->base))
+ return PTR_ERR(pxa_unit->base);
+
+ mmp_clk_init(pdev->dev.of_node, &pxa_unit->unit, APBCP_NR_CLKS);
+
+ pxa1908_apb_p_periph_clk_init(pxa_unit);
+
+ return 0;
+}
+
+static const struct of_device_id pxa1908_apbcp_match_table[] = {
+ { .compatible = "marvell,pxa1908-apbcp" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pxa1908_apbcp_match_table);
+
+static struct platform_driver pxa1908_apbcp_driver = {
+ .probe = pxa1908_apbcp_probe,
+ .driver = {
+ .name = "pxa1908-apbcp",
+ .of_match_table = pxa1908_apbcp_match_table
+ }
+};
+module_platform_driver(pxa1908_apbcp_driver);
+
+MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>");
+MODULE_DESCRIPTION("Marvell PXA1908 APBCP Clock Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mmp/clk-pxa1908-apmu.c b/drivers/clk/mmp/clk-pxa1908-apmu.c
new file mode 100644
index 000000000000..8cfb1258202f
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa1908-apmu.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/marvell,pxa1908.h>
+
+#include "clk.h"
+
+#define APMU_CLK_GATE_CTRL 0x40
+#define APMU_CCIC1 0x24
+#define APMU_ISP 0x38
+#define APMU_DSI1 0x44
+#define APMU_DISP1 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_SDH0 0x54
+#define APMU_SDH1 0x58
+#define APMU_USB 0x5c
+#define APMU_NF 0x60
+#define APMU_VPU 0xa4
+#define APMU_GC 0xcc
+#define APMU_SDH2 0xe0
+#define APMU_GC2D 0xf4
+#define APMU_TRACE 0x108
+#define APMU_DVC_DFC_DEBUG 0x140
+
+#define APMU_NR_CLKS 17
+
+struct pxa1908_clk_unit {
+ struct mmp_clk_unit unit;
+ void __iomem *base;
+};
+
+static DEFINE_SPINLOCK(pll1_lock);
+static struct mmp_param_general_gate_clk pll1_gate_clks[] = {
+ {PXA1908_CLK_PLL1_D2_GATE, "pll1_d2_gate", "pll1_d2", 0, APMU_CLK_GATE_CTRL, 29, 0, &pll1_lock},
+ {PXA1908_CLK_PLL1_416_GATE, "pll1_416_gate", "pll1_416", 0, APMU_CLK_GATE_CTRL, 27, 0, &pll1_lock},
+ {PXA1908_CLK_PLL1_624_GATE, "pll1_624_gate", "pll1_624", 0, APMU_CLK_GATE_CTRL, 26, 0, &pll1_lock},
+ {PXA1908_CLK_PLL1_832_GATE, "pll1_832_gate", "pll1_832", 0, APMU_CLK_GATE_CTRL, 30, 0, &pll1_lock},
+ {PXA1908_CLK_PLL1_1248_GATE, "pll1_1248_gate", "pll1_1248", 0, APMU_CLK_GATE_CTRL, 28, 0, &pll1_lock},
+};
+
+static DEFINE_SPINLOCK(sdh0_lock);
+static DEFINE_SPINLOCK(sdh1_lock);
+static DEFINE_SPINLOCK(sdh2_lock);
+
+static const char * const sdh_parent_names[] = {"pll1_416", "pll1_624"};
+
+static struct mmp_clk_mix_config sdh_mix_config = {
+ .reg_info = DEFINE_MIX_REG_INFO(3, 8, 2, 6, 11),
+};
+
+static struct mmp_param_gate_clk apmu_gate_clks[] = {
+ {PXA1908_CLK_USB, "usb_clk", NULL, 0, APMU_USB, 0x9, 0x9, 0x1, 0, NULL},
+ {PXA1908_CLK_SDH0, "sdh0_clk", "sdh0_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH0, 0x12, 0x12, 0x0, 0, &sdh0_lock},
+ {PXA1908_CLK_SDH1, "sdh1_clk", "sdh1_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH1, 0x12, 0x12, 0x0, 0, &sdh1_lock},
+ {PXA1908_CLK_SDH2, "sdh2_clk", "sdh2_mix_clk", CLK_SET_RATE_PARENT | CLK_SET_RATE_UNGATE, APMU_SDH2, 0x12, 0x12, 0x0, 0, &sdh2_lock}
+};
+
+static void pxa1908_axi_periph_clk_init(struct pxa1908_clk_unit *pxa_unit)
+{
+ struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+ mmp_register_general_gate_clks(unit, pll1_gate_clks,
+ pxa_unit->base, ARRAY_SIZE(pll1_gate_clks));
+
+ sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->base + APMU_SDH0;
+ mmp_clk_register_mix(NULL, "sdh0_mix_clk", sdh_parent_names,
+ ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
+ &sdh_mix_config, &sdh0_lock);
+ sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->base + APMU_SDH1;
+ mmp_clk_register_mix(NULL, "sdh1_mix_clk", sdh_parent_names,
+ ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
+ &sdh_mix_config, &sdh1_lock);
+ sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->base + APMU_SDH2;
+ mmp_clk_register_mix(NULL, "sdh2_mix_clk", sdh_parent_names,
+ ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT,
+ &sdh_mix_config, &sdh2_lock);
+
+ mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->base,
+ ARRAY_SIZE(apmu_gate_clks));
+}
+
+static int pxa1908_apmu_probe(struct platform_device *pdev)
+{
+ struct pxa1908_clk_unit *pxa_unit;
+
+ pxa_unit = devm_kzalloc(&pdev->dev, sizeof(*pxa_unit), GFP_KERNEL);
+ if (IS_ERR(pxa_unit))
+ return PTR_ERR(pxa_unit);
+
+ pxa_unit->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pxa_unit->base))
+ return PTR_ERR(pxa_unit->base);
+
+ mmp_clk_init(pdev->dev.of_node, &pxa_unit->unit, APMU_NR_CLKS);
+
+ pxa1908_axi_periph_clk_init(pxa_unit);
+
+ return 0;
+}
+
+static const struct of_device_id pxa1908_apmu_match_table[] = {
+ { .compatible = "marvell,pxa1908-apmu" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pxa1908_apmu_match_table);
+
+static struct platform_driver pxa1908_apmu_driver = {
+ .probe = pxa1908_apmu_probe,
+ .driver = {
+ .name = "pxa1908-apmu",
+ .of_match_table = pxa1908_apmu_match_table
+ }
+};
+module_platform_driver(pxa1908_apmu_driver);
+
+MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>");
+MODULE_DESCRIPTION("Marvell PXA1908 APMU Clock Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mmp/clk-pxa1908-mpmu.c b/drivers/clk/mmp/clk-pxa1908-mpmu.c
new file mode 100644
index 000000000000..e3337bacaadd
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa1908-mpmu.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/units.h>
+
+#include <dt-bindings/clock/marvell,pxa1908.h>
+
+#include "clk.h"
+
+#define MPMU_UART_PLL 0x14
+
+#define MPMU_NR_CLKS 39
+
+struct pxa1908_clk_unit {
+ struct mmp_clk_unit unit;
+ void __iomem *base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+ {PXA1908_CLK_CLK32, "clk32", NULL, 0, 32768},
+ {PXA1908_CLK_VCTCXO, "vctcxo", NULL, 0, 26 * HZ_PER_MHZ},
+ {PXA1908_CLK_PLL1_624, "pll1_624", NULL, 0, 624 * HZ_PER_MHZ},
+ {PXA1908_CLK_PLL1_416, "pll1_416", NULL, 0, 416 * HZ_PER_MHZ},
+ {PXA1908_CLK_PLL1_499, "pll1_499", NULL, 0, 499 * HZ_PER_MHZ},
+ {PXA1908_CLK_PLL1_832, "pll1_832", NULL, 0, 832 * HZ_PER_MHZ},
+ {PXA1908_CLK_PLL1_1248, "pll1_1248", NULL, 0, 1248 * HZ_PER_MHZ},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+ {PXA1908_CLK_PLL1_D2, "pll1_d2", "pll1_624", 1, 2, 0},
+ {PXA1908_CLK_PLL1_D4, "pll1_d4", "pll1_d2", 1, 2, 0},
+ {PXA1908_CLK_PLL1_D6, "pll1_d6", "pll1_d2", 1, 3, 0},
+ {PXA1908_CLK_PLL1_D8, "pll1_d8", "pll1_d4", 1, 2, 0},
+ {PXA1908_CLK_PLL1_D12, "pll1_d12", "pll1_d6", 1, 2, 0},
+ {PXA1908_CLK_PLL1_D13, "pll1_d13", "pll1_624", 1, 13, 0},
+ {PXA1908_CLK_PLL1_D16, "pll1_d16", "pll1_d8", 1, 2, 0},
+ {PXA1908_CLK_PLL1_D24, "pll1_d24", "pll1_d12", 1, 2, 0},
+ {PXA1908_CLK_PLL1_D48, "pll1_d48", "pll1_d24", 1, 2, 0},
+ {PXA1908_CLK_PLL1_D96, "pll1_d96", "pll1_d48", 1, 2, 0},
+ {PXA1908_CLK_PLL1_32, "pll1_32", "pll1_d13", 2, 3, 0},
+ {PXA1908_CLK_PLL1_208, "pll1_208", "pll1_d2", 2, 3, 0},
+ {PXA1908_CLK_PLL1_117, "pll1_117", "pll1_624", 3, 16, 0},
+};
+
+static struct u32_fract uart_factor_tbl[] = {
+ {.numerator = 8125, .denominator = 1536}, /* 14.745MHz */
+};
+
+static struct mmp_clk_factor_masks uart_factor_masks = {
+ .factor = 2,
+ .num_mask = GENMASK(12, 0),
+ .den_mask = GENMASK(12, 0),
+ .num_shift = 16,
+ .den_shift = 0,
+};
+
+static void pxa1908_pll_init(struct pxa1908_clk_unit *pxa_unit)
+{
+ struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+ mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
+ ARRAY_SIZE(fixed_rate_clks));
+
+ mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
+ ARRAY_SIZE(fixed_factor_clks));
+
+ mmp_clk_register_factor("uart_pll", "pll1_d4",
+ CLK_SET_RATE_PARENT,
+ pxa_unit->base + MPMU_UART_PLL,
+ &uart_factor_masks, uart_factor_tbl,
+ ARRAY_SIZE(uart_factor_tbl), NULL);
+}
+
+static int pxa1908_mpmu_probe(struct platform_device *pdev)
+{
+ struct pxa1908_clk_unit *pxa_unit;
+
+ pxa_unit = devm_kzalloc(&pdev->dev, sizeof(*pxa_unit), GFP_KERNEL);
+ if (IS_ERR(pxa_unit))
+ return PTR_ERR(pxa_unit);
+
+ pxa_unit->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pxa_unit->base))
+ return PTR_ERR(pxa_unit->base);
+
+ mmp_clk_init(pdev->dev.of_node, &pxa_unit->unit, MPMU_NR_CLKS);
+
+ pxa1908_pll_init(pxa_unit);
+
+ return 0;
+}
+
+static const struct of_device_id pxa1908_mpmu_match_table[] = {
+ { .compatible = "marvell,pxa1908-mpmu" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pxa1908_mpmu_match_table);
+
+static struct platform_driver pxa1908_mpmu_driver = {
+ .probe = pxa1908_mpmu_probe,
+ .driver = {
+ .name = "pxa1908-mpmu",
+ .of_match_table = pxa1908_mpmu_match_table
+ }
+};
+module_platform_driver(pxa1908_mpmu_driver);
+
+MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>");
+MODULE_DESCRIPTION("Marvell PXA1908 MPMU Clock Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 55ac05379781..c83cec169ddc 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -3,6 +3,7 @@
#define __MACH_MMP_CLK_H
#include <linux/clk-provider.h>
+#include <linux/math.h>
#include <linux/pm_domain.h>
#include <linux/clkdev.h>
@@ -20,16 +21,11 @@ struct mmp_clk_factor_masks {
unsigned int enable_mask;
};
-struct mmp_clk_factor_tbl {
- unsigned int num;
- unsigned int den;
-};
-
struct mmp_clk_factor {
struct clk_hw hw;
void __iomem *base;
struct mmp_clk_factor_masks *masks;
- struct mmp_clk_factor_tbl *ftbl;
+ struct u32_fract *ftbl;
unsigned int ftbl_cnt;
spinlock_t *lock;
};
@@ -37,7 +33,7 @@ struct mmp_clk_factor {
extern struct clk *mmp_clk_register_factor(const char *name,
const char *parent_name, unsigned long flags,
void __iomem *base, struct mmp_clk_factor_masks *masks,
- struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
+ struct u32_fract *ftbl, unsigned int ftbl_cnt,
spinlock_t *lock);
/* Clock type "mix" */
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index a3e2a09e2105..ef89d686cbc4 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -213,6 +213,14 @@ config IPQ_GCC_5332
Say Y if you want to use peripheral devices such as UART, SPI,
i2c, USB, SD/eMMC, etc.
+config IPQ_GCC_5424
+ tristate "IPQ5424 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ help
+ Support for the global clock controller on ipq5424 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2c, USB, SD/eMMC, etc.
+
config IPQ_GCC_6018
tristate "IPQ6018 Global Clock Controller"
help
@@ -467,6 +475,26 @@ config QCS_GCC_404
Say Y if you want to use multimedia devices or peripheral
devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe etc.
+config SA_CAMCC_8775P
+ tristate "SA8775P Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select SA_GCC_8775P
+ help
+ Support for the camera clock controller on Qualcomm Technologies, Inc
+ SA8775P devices.
+ Say Y if you want to support camera devices and functionality such as
+ capturing pictures.
+
+config QCS_GCC_8300
+ tristate "QCS8300 Global Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select QCOM_GDSC
+ help
+ Support for the global clock controller on Qualcomm Technologies, Inc
+ QCS8300 devices.
+ Say Y if you want to use peripheral devices such as UART,
+ SPI, I2C, USB, SD/UFS, PCIe etc.
+
config SC_CAMCC_7180
tristate "SC7180 Camera Clock Controller"
depends on ARM64 || COMPILE_TEST
@@ -497,6 +525,16 @@ config SC_CAMCC_8280XP
Say Y if you want to support camera devices and functionality such as
capturing pictures.
+config SA_DISPCC_8775P
+ tristate "SA8775P Display Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select SA_GCC_8775P
+ help
+ Support for the two display clock controllers on Qualcomm
+ Technologies, Inc. SA8775P devices.
+ Say Y if you want to support display devices and functionality such as
+ splash screen.
+
config SC_DISPCC_7180
tristate "SC7180 Display Clock Controller"
depends on ARM64 || COMPILE_TEST
@@ -545,6 +583,24 @@ config SA_GPUCC_8775P
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics.
+config SAR_GCC_2130P
+ tristate "SAR2130P Global Clock Controller"
+ select QCOM_GDSC
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the global clock controller on SAR2130P devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ I2C, USB, SDCC, etc.
+
+config SAR_GPUCC_2130P
+ tristate "SAR2130P Graphics clock controller"
+ select QCOM_GDSC
+ select SAR_GCC_2130P
+ help
+ Support for the graphics clock controller on SAR2130P devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
config SC_GCC_7180
tristate "SC7180 Global Clock Controller"
select QCOM_GDSC
@@ -857,7 +913,7 @@ config SM_CAMCC_8450
depends on ARM64 || COMPILE_TEST
select SM_GCC_8450
help
- Support for the camera clock controller on SM8450 devices.
+ Support for the camera clock controller on SM8450 or SM8475 devices.
Say Y if you want to support camera devices and camera functionality.
config SM_CAMCC_8550
@@ -952,17 +1008,17 @@ config SM_DISPCC_8450
depends on SM_GCC_8450
help
Support for the display clock controller on Qualcomm Technologies, Inc
- SM8450 devices.
+ SM8450 or SM8475 devices.
Say Y if you want to support display devices and functionality such as
splash screen.
config SM_DISPCC_8550
tristate "SM8550 Display Clock Controller"
depends on ARM64 || COMPILE_TEST
- depends on SM_GCC_8550 || SM_GCC_8650
+ depends on SM_GCC_8550 || SM_GCC_8650 || SAR_GCC_2130P
help
Support for the display clock controller on Qualcomm Technologies, Inc
- SM8550 or SM8650 devices.
+ SAR2130P, SM8550 or SM8650 devices.
Say Y if you want to support display devices and functionality such as
splash screen.
@@ -987,6 +1043,7 @@ config SM_GCC_6115
config SM_GCC_6125
tristate "SM6125 Global Clock Controller"
depends on ARM64 || COMPILE_TEST
+ select QCOM_GDSC
help
Support for the global clock controller on SM6125 devices.
Say Y if you want to use peripheral devices such as UART,
@@ -1050,7 +1107,8 @@ config SM_GCC_8450
depends on ARM64 || COMPILE_TEST
select QCOM_GDSC
help
- Support for the global clock controller on SM8450 devices.
+ Support for the global clock controller on SM8450 or SM8475
+ devices.
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
@@ -1149,7 +1207,8 @@ config SM_GPUCC_8450
depends on ARM64 || COMPILE_TEST
select SM_GCC_8450
help
- Support for the graphics clock controller on SM8450 devices.
+ Support for the graphics clock controller on SM8450 or SM8475
+ devices.
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics.
@@ -1187,6 +1246,17 @@ config SM_TCSRCC_8650
Support for the TCSR clock controller on SM8650 devices.
Say Y if you want to use peripheral devices such as SD/UFS.
+config SA_VIDEOCC_8775P
+ tristate "SA8775P Video Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select SA_GCC_8775P
+ select QCOM_GDSC
+ help
+ Support for the video clock controller on Qualcomm Technologies, Inc.
+ SA8775P devices.
+ Say Y if you want to support video devices and functionality such as
+ video encode/decode.
+
config SM_VIDEOCC_7150
tristate "SM7150 Video Clock Controller"
depends on ARM64 || COMPILE_TEST
@@ -1230,11 +1300,11 @@ config SM_VIDEOCC_8350
config SM_VIDEOCC_8550
tristate "SM8550 Video Clock Controller"
depends on ARM64 || COMPILE_TEST
- select SM_GCC_8550
+ depends on SM_GCC_8550 || SM_GCC_8650
select QCOM_GDSC
help
Support for the video clock controller on Qualcomm Technologies, Inc.
- SM8550 devices.
+ SM8550 or SM8650 devices.
Say Y if you want to support video devices and functionality such as
video encode/decode.
@@ -1283,7 +1353,7 @@ config SM_VIDEOCC_8450
select QCOM_GDSC
help
Support for the video clock controller on Qualcomm Technologies, Inc.
- SM8450 devices.
+ SM8450 or SM8475 devices.
Say Y if you want to support video devices and functionality such as
video encode/decode.
endif
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 2b378667a63f..b09dbdc210eb 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
obj-$(CONFIG_IPQ_GCC_5018) += gcc-ipq5018.o
obj-$(CONFIG_IPQ_GCC_5332) += gcc-ipq5332.o
+obj-$(CONFIG_IPQ_GCC_5424) += gcc-ipq5424.o
obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o
@@ -70,6 +71,7 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
obj-$(CONFIG_QCM_GCC_2290) += gcc-qcm2290.o
obj-$(CONFIG_QCM_DISPCC_2290) += dispcc-qcm2290.o
obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
+obj-$(CONFIG_QCS_GCC_8300) += gcc-qcs8300.o
obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o
obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o
obj-$(CONFIG_QDU_ECPRICC_1000) += ecpricc-qdu1000.o
@@ -80,8 +82,13 @@ obj-$(CONFIG_SC_CAMCC_8280XP) += camcc-sc8280xp.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_SA_CAMCC_8775P) += camcc-sa8775p.o
+obj-$(CONFIG_SA_DISPCC_8775P) += dispcc0-sa8775p.o dispcc1-sa8775p.o
obj-$(CONFIG_SA_GCC_8775P) += gcc-sa8775p.o
obj-$(CONFIG_SA_GPUCC_8775P) += gpucc-sa8775p.o
+obj-$(CONFIG_SA_VIDEOCC_8775P) += videocc-sa8775p.o
+obj-$(CONFIG_SAR_GCC_2130P) += gcc-sar2130p.o
+obj-$(CONFIG_SAR_GPUCC_2130P) += gpucc-sar2130p.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
diff --git a/drivers/clk/qcom/camcc-sa8775p.c b/drivers/clk/qcom/camcc-sa8775p.c
new file mode 100644
index 000000000000..c04801a5af35
--- /dev/null
+++ b/drivers/clk/qcom/camcc-sa8775p.c
@@ -0,0 +1,1868 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sa8775p-camcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_IFACE,
+ DT_BI_TCXO,
+ DT_BI_TCXO_AO,
+ DT_SLEEP_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_BI_TCXO_AO,
+ P_CAM_CC_PLL0_OUT_EVEN,
+ P_CAM_CC_PLL0_OUT_MAIN,
+ P_CAM_CC_PLL0_OUT_ODD,
+ P_CAM_CC_PLL2_OUT_EVEN,
+ P_CAM_CC_PLL2_OUT_MAIN,
+ P_CAM_CC_PLL3_OUT_EVEN,
+ P_CAM_CC_PLL4_OUT_EVEN,
+ P_CAM_CC_PLL5_OUT_EVEN,
+ P_SLEEP_CLK,
+};
+
+static const struct pll_vco lucid_evo_vco[] = {
+ { 249600000, 2020000000, 0 },
+};
+
+static const struct pll_vco rivian_evo_vco[] = {
+ { 864000000, 1056000000, 0 },
+};
+
+static const struct alpha_pll_config cam_cc_pll0_config = {
+ .l = 0x3e,
+ .alpha = 0x8000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00008400,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll cam_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll0_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = {
+ { 0x2, 3 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = {
+ .offset = 0x0,
+ .post_div_shift = 14,
+ .post_div_table = post_div_table_cam_cc_pll0_out_odd,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0_out_odd",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll2_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x90008820,
+ .config_ctl_hi_val = 0x00890263,
+ .config_ctl_hi1_val = 0x00000247,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00400000,
+};
+
+static struct clk_alpha_pll cam_cc_pll2 = {
+ .offset = 0x1000,
+ .vco_table = rivian_evo_vco,
+ .num_vco = ARRAY_SIZE(rivian_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll2",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_rivian_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll3_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll cam_cc_pll3 = {
+ .offset = 0x2000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll3",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = {
+ .offset = 0x2000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll3_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll3_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll3.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll4_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll cam_cc_pll4 = {
+ .offset = 0x3000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll4",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = {
+ .offset = 0x3000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll4_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll4_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll4.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static const struct alpha_pll_config cam_cc_pll5_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll cam_cc_pll5 = {
+ .offset = 0x4000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll5",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = {
+ .offset = 0x4000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll5_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll5_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll5.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static const struct parent_map cam_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL0_OUT_MAIN, 1 },
+ { P_CAM_CC_PLL0_OUT_EVEN, 2 },
+ { P_CAM_CC_PLL0_OUT_ODD, 3 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll0.clkr.hw },
+ { .hw = &cam_cc_pll0_out_even.clkr.hw },
+ { .hw = &cam_cc_pll0_out_odd.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL2_OUT_EVEN, 3 },
+ { P_CAM_CC_PLL2_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll2.clkr.hw },
+ { .hw = &cam_cc_pll2.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL4_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll4_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL5_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll5_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL3_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll3_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_5[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_5[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map cam_cc_parent_map_6_ao[] = {
+ { P_BI_TCXO_AO, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_6_ao[] = {
+ { .index = DT_BI_TCXO_AO },
+};
+
+static const struct freq_tbl ftbl_cam_cc_camnoc_axi_clk_src[] = {
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = {
+ .cmd_rcgr = 0x13170,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_camnoc_axi_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_axi_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = {
+ F(37500000, P_CAM_CC_PLL0_OUT_MAIN, 16, 1, 2),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cci_0_clk_src = {
+ .cmd_rcgr = 0x130a0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_0_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_cci_1_clk_src = {
+ .cmd_rcgr = 0x130bc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_1_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_cci_2_clk_src = {
+ .cmd_rcgr = 0x130d8,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_2_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_cci_3_clk_src = {
+ .cmd_rcgr = 0x130f4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_3_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = {
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cphy_rx_clk_src = {
+ .cmd_rcgr = 0x11034,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cphy_rx_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x15074,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi0phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = {
+ .cmd_rcgr = 0x15098,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi1phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = {
+ .cmd_rcgr = 0x150b8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi2phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = {
+ .cmd_rcgr = 0x150d8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi3phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csid_clk_src = {
+ .cmd_rcgr = 0x13150,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = {
+ F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_fast_ahb_clk_src = {
+ .cmd_rcgr = 0x13120,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_fast_ahb_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_icp_clk_src[] = {
+ F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_icp_clk_src = {
+ .cmd_rcgr = 0x1307c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_icp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = {
+ F(480000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_clk_src = {
+ .cmd_rcgr = 0x11004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_2,
+ .freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_clk_src",
+ .parent_data = cam_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_1_clk_src[] = {
+ F(480000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_1_clk_src = {
+ .cmd_rcgr = 0x12004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_3,
+ .freq_tbl = ftbl_cam_cc_ife_1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_clk_src",
+ .parent_data = cam_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_lite_clk_src[] = {
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_clk_src = {
+ .cmd_rcgr = 0x13000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_ife_lite_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = {
+ .cmd_rcgr = 0x13020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_csid_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ipe_clk_src[] = {
+ F(480000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ipe_clk_src = {
+ .cmd_rcgr = 0x10004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_4,
+ .freq_tbl = ftbl_cam_cc_ipe_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_clk_src",
+ .parent_data = cam_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = {
+ F(19200000, P_CAM_CC_PLL2_OUT_MAIN, 1, 1, 50),
+ F(24000000, P_CAM_CC_PLL2_OUT_MAIN, 10, 1, 4),
+ F(64000000, P_CAM_CC_PLL2_OUT_MAIN, 15, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_mclk0_clk_src = {
+ .cmd_rcgr = 0x15004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk0_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk1_clk_src = {
+ .cmd_rcgr = 0x15020,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk1_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk2_clk_src = {
+ .cmd_rcgr = 0x1503c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk2_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_mclk3_clk_src = {
+ .cmd_rcgr = 0x15058,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk3_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x131f0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_5,
+ .freq_tbl = ftbl_cam_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sleep_clk_src",
+ .parent_data = cam_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = {
+ F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
+ .cmd_rcgr = 0x13138,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_slow_ahb_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO_AO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_xo_clk_src = {
+ .cmd_rcgr = 0x131d4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_6_ao,
+ .freq_tbl = ftbl_cam_cc_xo_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_xo_clk_src",
+ .parent_data = cam_cc_parent_data_6_ao,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_6_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_axi_clk = {
+ .halt_reg = 0x13188,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13188,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_camnoc_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_dcd_xo_clk = {
+ .halt_reg = 0x13190,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13190,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_dcd_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_qdss_debug_xo_clk = {
+ .halt_reg = 0x131b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x131b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_0_clk = {
+ .halt_reg = 0x130b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x130b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_1_clk = {
+ .halt_reg = 0x130d4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x130d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_2_clk = {
+ .halt_reg = 0x130f0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x130f0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_3_clk = {
+ .halt_reg = 0x1310c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1310c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_core_ahb_clk = {
+ .halt_reg = 0x131d0,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x131d0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_core_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ahb_clk = {
+ .halt_reg = 0x13110,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13110,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_fast_ahb_clk = {
+ .halt_reg = 0x13118,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13118,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ife_0_clk = {
+ .halt_reg = 0x11024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ife_1_clk = {
+ .halt_reg = 0x12024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ife_lite_clk = {
+ .halt_reg = 0x1301c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1301c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ife_lite_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_ipe_clk = {
+ .halt_reg = 0x10024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_ipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_sfe_lite_0_clk = {
+ .halt_reg = 0x13050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sfe_lite_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cpas_sfe_lite_1_clk = {
+ .halt_reg = 0x13068,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cpas_sfe_lite_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi0phytimer_clk = {
+ .halt_reg = 0x1508c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1508c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi0phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi0phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi1phytimer_clk = {
+ .halt_reg = 0x150b0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi1phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi1phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi2phytimer_clk = {
+ .halt_reg = 0x150d0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150d0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi2phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi2phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi3phytimer_clk = {
+ .halt_reg = 0x150f0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150f0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi3phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi3phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csid_clk = {
+ .halt_reg = 0x13168,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13168,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csid_csiphy_rx_clk = {
+ .halt_reg = 0x15094,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15094,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_csiphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy0_clk = {
+ .halt_reg = 0x15090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15090,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy1_clk = {
+ .halt_reg = 0x150b4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy2_clk = {
+ .halt_reg = 0x150d4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy3_clk = {
+ .halt_reg = 0x150f4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x150f4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_ahb_clk = {
+ .halt_reg = 0x1309c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1309c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_clk = {
+ .halt_reg = 0x13094,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13094,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_icp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_0_clk = {
+ .halt_reg = 0x1101c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1101c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_0_fast_ahb_clk = {
+ .halt_reg = 0x11030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_0_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_1_clk = {
+ .halt_reg = 0x1201c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1201c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_1_fast_ahb_clk = {
+ .halt_reg = 0x12030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x12030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_1_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_ahb_clk = {
+ .halt_reg = 0x13044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_clk = {
+ .halt_reg = 0x13018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = {
+ .halt_reg = 0x13040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_cphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_csid_clk = {
+ .halt_reg = 0x13038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_csid_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_ahb_clk = {
+ .halt_reg = 0x10030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_clk = {
+ .halt_reg = 0x1001c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1001c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_fast_ahb_clk = {
+ .halt_reg = 0x10034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk0_clk = {
+ .halt_reg = 0x1501c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1501c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk1_clk = {
+ .halt_reg = 0x15038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk2_clk = {
+ .halt_reg = 0x15054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_mclk3_clk = {
+ .halt_reg = 0x15070,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x15070,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_mclk3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_mclk3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_lite_0_clk = {
+ .halt_reg = 0x1304c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1304c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_lite_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_lite_0_fast_ahb_clk = {
+ .halt_reg = 0x1305c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1305c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_lite_0_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_lite_1_clk = {
+ .halt_reg = 0x13064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_lite_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sfe_lite_1_fast_ahb_clk = {
+ .halt_reg = 0x13074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x13074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sfe_lite_1_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_sm_obs_clk = {
+ .halt_reg = 0x1510c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x1510c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sm_obs_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc cam_cc_titan_top_gdsc = {
+ .gdscr = 0x131bc,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_titan_top_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *cam_cc_sa8775p_clocks[] = {
+ [CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr,
+ [CAM_CC_CAMNOC_AXI_CLK_SRC] = &cam_cc_camnoc_axi_clk_src.clkr,
+ [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr,
+ [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr,
+ [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr,
+ [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr,
+ [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr,
+ [CAM_CC_CCI_2_CLK] = &cam_cc_cci_2_clk.clkr,
+ [CAM_CC_CCI_2_CLK_SRC] = &cam_cc_cci_2_clk_src.clkr,
+ [CAM_CC_CCI_3_CLK] = &cam_cc_cci_3_clk.clkr,
+ [CAM_CC_CCI_3_CLK_SRC] = &cam_cc_cci_3_clk_src.clkr,
+ [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr,
+ [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr,
+ [CAM_CC_CPAS_FAST_AHB_CLK] = &cam_cc_cpas_fast_ahb_clk.clkr,
+ [CAM_CC_CPAS_IFE_0_CLK] = &cam_cc_cpas_ife_0_clk.clkr,
+ [CAM_CC_CPAS_IFE_1_CLK] = &cam_cc_cpas_ife_1_clk.clkr,
+ [CAM_CC_CPAS_IFE_LITE_CLK] = &cam_cc_cpas_ife_lite_clk.clkr,
+ [CAM_CC_CPAS_IPE_CLK] = &cam_cc_cpas_ipe_clk.clkr,
+ [CAM_CC_CPAS_SFE_LITE_0_CLK] = &cam_cc_cpas_sfe_lite_0_clk.clkr,
+ [CAM_CC_CPAS_SFE_LITE_1_CLK] = &cam_cc_cpas_sfe_lite_1_clk.clkr,
+ [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr,
+ [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr,
+ [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr,
+ [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr,
+ [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr,
+ [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr,
+ [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr,
+ [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr,
+ [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr,
+ [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr,
+ [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr,
+ [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.clkr,
+ [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr,
+ [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr,
+ [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr,
+ [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr,
+ [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr,
+ [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr,
+ [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr,
+ [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr,
+ [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr,
+ [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr,
+ [CAM_CC_IFE_0_FAST_AHB_CLK] = &cam_cc_ife_0_fast_ahb_clk.clkr,
+ [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr,
+ [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr,
+ [CAM_CC_IFE_1_FAST_AHB_CLK] = &cam_cc_ife_1_fast_ahb_clk.clkr,
+ [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr,
+ [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr,
+ [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr,
+ [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr,
+ [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr,
+ [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr,
+ [CAM_CC_IPE_AHB_CLK] = &cam_cc_ipe_ahb_clk.clkr,
+ [CAM_CC_IPE_CLK] = &cam_cc_ipe_clk.clkr,
+ [CAM_CC_IPE_CLK_SRC] = &cam_cc_ipe_clk_src.clkr,
+ [CAM_CC_IPE_FAST_AHB_CLK] = &cam_cc_ipe_fast_ahb_clk.clkr,
+ [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr,
+ [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr,
+ [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr,
+ [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr,
+ [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr,
+ [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr,
+ [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr,
+ [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr,
+ [CAM_CC_PLL0] = &cam_cc_pll0.clkr,
+ [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr,
+ [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr,
+ [CAM_CC_PLL2] = &cam_cc_pll2.clkr,
+ [CAM_CC_PLL3] = &cam_cc_pll3.clkr,
+ [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr,
+ [CAM_CC_PLL4] = &cam_cc_pll4.clkr,
+ [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr,
+ [CAM_CC_PLL5] = &cam_cc_pll5.clkr,
+ [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr,
+ [CAM_CC_SFE_LITE_0_CLK] = &cam_cc_sfe_lite_0_clk.clkr,
+ [CAM_CC_SFE_LITE_0_FAST_AHB_CLK] = &cam_cc_sfe_lite_0_fast_ahb_clk.clkr,
+ [CAM_CC_SFE_LITE_1_CLK] = &cam_cc_sfe_lite_1_clk.clkr,
+ [CAM_CC_SFE_LITE_1_FAST_AHB_CLK] = &cam_cc_sfe_lite_1_fast_ahb_clk.clkr,
+ [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr,
+ [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr,
+ [CAM_CC_SM_OBS_CLK] = &cam_cc_sm_obs_clk.clkr,
+ [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr,
+ [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr,
+};
+
+static struct gdsc *cam_cc_sa8775p_gdscs[] = {
+ [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc,
+};
+
+static const struct qcom_reset_map cam_cc_sa8775p_resets[] = {
+ [CAM_CC_ICP_BCR] = { 0x13078 },
+ [CAM_CC_IFE_0_BCR] = { 0x11000 },
+ [CAM_CC_IFE_1_BCR] = { 0x12000 },
+ [CAM_CC_IPE_0_BCR] = { 0x10000 },
+ [CAM_CC_SFE_LITE_0_BCR] = { 0x13048 },
+ [CAM_CC_SFE_LITE_1_BCR] = { 0x13060 },
+};
+
+static const struct regmap_config cam_cc_sa8775p_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x16218,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc cam_cc_sa8775p_desc = {
+ .config = &cam_cc_sa8775p_regmap_config,
+ .clks = cam_cc_sa8775p_clocks,
+ .num_clks = ARRAY_SIZE(cam_cc_sa8775p_clocks),
+ .resets = cam_cc_sa8775p_resets,
+ .num_resets = ARRAY_SIZE(cam_cc_sa8775p_resets),
+ .gdscs = cam_cc_sa8775p_gdscs,
+ .num_gdscs = ARRAY_SIZE(cam_cc_sa8775p_gdscs),
+};
+
+static const struct of_device_id cam_cc_sa8775p_match_table[] = {
+ { .compatible = "qcom,sa8775p-camcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cam_cc_sa8775p_match_table);
+
+static int cam_cc_sa8775p_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &cam_cc_sa8775p_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_evo_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
+ clk_rivian_evo_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config);
+
+ /* Keep some clocks always enabled */
+ qcom_branch_set_clk_en(regmap, 0x13194); /* CAM_CC_CAMNOC_XO_CLK */
+ qcom_branch_set_clk_en(regmap, 0x131ec); /* CAM_CC_GDSC_CLK */
+ qcom_branch_set_clk_en(regmap, 0x13208); /* CAM_CC_SLEEP_CLK */
+
+ ret = qcom_cc_really_probe(&pdev->dev, &cam_cc_sa8775p_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver cam_cc_sa8775p_driver = {
+ .probe = cam_cc_sa8775p_probe,
+ .driver = {
+ .name = "camcc-sa8775p",
+ .of_match_table = cam_cc_sa8775p_match_table,
+ },
+};
+
+module_platform_driver(cam_cc_sa8775p_driver);
+
+MODULE_DESCRIPTION("QTI CAMCC SA8775P Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/camcc-sm8450.c b/drivers/clk/qcom/camcc-sm8450.c
index 26b78eed15ef..08982737e490 100644
--- a/drivers/clk/qcom/camcc-sm8450.c
+++ b/drivers/clk/qcom/camcc-sm8450.c
@@ -54,6 +54,10 @@ static const struct pll_vco rivian_evo_vco[] = {
{ 864000000, 1056000000, 0 },
};
+static const struct pll_vco rivian_ole_vco[] = {
+ { 864000000, 1075000000, 0 },
+};
+
static const struct clk_parent_data pll_parent_data_tcxo = { .index = DT_BI_TCXO };
static const struct alpha_pll_config cam_cc_pll0_config = {
@@ -66,6 +70,20 @@ static const struct alpha_pll_config cam_cc_pll0_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll0_config = {
+ .l = 0x3e,
+ .alpha = 0x8000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00008400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll0 = {
.offset = 0x0,
.vco_table = lucid_evo_vco,
@@ -86,6 +104,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll0_out_even_init = {
+ .name = "cam_cc_pll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = {
.offset = 0x0,
.post_div_shift = 10,
@@ -109,6 +137,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll0_out_odd_init = {
+ .name = "cam_cc_pll0_out_odd",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = {
.offset = 0x0,
.post_div_shift = 14,
@@ -137,6 +175,20 @@ static const struct alpha_pll_config cam_cc_pll1_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll1_config = {
+ .l = 0x25,
+ .alpha = 0xeaaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll1 = {
.offset = 0x1000,
.vco_table = lucid_evo_vco,
@@ -157,6 +209,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll1_out_even_init = {
+ .name = "cam_cc_pll1_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll1.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = {
.offset = 0x1000,
.post_div_shift = 10,
@@ -183,6 +245,16 @@ static const struct alpha_pll_config cam_cc_pll2_config = {
.config_ctl_hi1_val = 0x00000217,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll2_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x10000030,
+ .config_ctl_hi_val = 0x80890263,
+ .config_ctl_hi1_val = 0x00000217,
+ .user_ctl_val = 0x00000001,
+ .user_ctl_hi_val = 0x00000000,
+};
+
static struct clk_alpha_pll cam_cc_pll2 = {
.offset = 0x2000,
.vco_table = rivian_evo_vco,
@@ -208,6 +280,20 @@ static const struct alpha_pll_config cam_cc_pll3_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll3_config = {
+ .l = 0x2d,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll3 = {
.offset = 0x3000,
.vco_table = lucid_evo_vco,
@@ -228,6 +314,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll3_out_even_init = {
+ .name = "cam_cc_pll3_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll3.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = {
.offset = 0x3000,
.post_div_shift = 10,
@@ -256,6 +352,20 @@ static const struct alpha_pll_config cam_cc_pll4_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll4_config = {
+ .l = 0x2d,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll4 = {
.offset = 0x4000,
.vco_table = lucid_evo_vco,
@@ -276,6 +386,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll4_out_even_init = {
+ .name = "cam_cc_pll4_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll4.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = {
.offset = 0x4000,
.post_div_shift = 10,
@@ -304,6 +424,20 @@ static const struct alpha_pll_config cam_cc_pll5_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll5_config = {
+ .l = 0x2d,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll5 = {
.offset = 0x5000,
.vco_table = lucid_evo_vco,
@@ -324,6 +458,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll5_out_even_init = {
+ .name = "cam_cc_pll5_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll5.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = {
.offset = 0x5000,
.post_div_shift = 10,
@@ -352,6 +496,20 @@ static const struct alpha_pll_config cam_cc_pll6_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll6_config = {
+ .l = 0x2d,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll6 = {
.offset = 0x6000,
.vco_table = lucid_evo_vco,
@@ -372,6 +530,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll6_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll6_out_even_init = {
+ .name = "cam_cc_pll6_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll6.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll6_out_even = {
.offset = 0x6000,
.post_div_shift = 10,
@@ -400,6 +568,20 @@ static const struct alpha_pll_config cam_cc_pll7_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll7_config = {
+ .l = 0x2d,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll7 = {
.offset = 0x7000,
.vco_table = lucid_evo_vco,
@@ -420,6 +602,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll7_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll7_out_even_init = {
+ .name = "cam_cc_pll7_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll7.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll7_out_even = {
.offset = 0x7000,
.post_div_shift = 10,
@@ -448,6 +640,20 @@ static const struct alpha_pll_config cam_cc_pll8_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_cam_cc_pll8_config = {
+ .l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll cam_cc_pll8 = {
.offset = 0x8000,
.vco_table = lucid_evo_vco,
@@ -468,6 +674,16 @@ static const struct clk_div_table post_div_table_cam_cc_pll8_out_even[] = {
{ }
};
+static struct clk_init_data sm8475_cam_cc_pll8_out_even_init = {
+ .name = "cam_cc_pll8_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll8.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static struct clk_alpha_pll_postdiv cam_cc_pll8_out_even = {
.offset = 0x8000,
.post_div_shift = 10,
@@ -2817,6 +3033,7 @@ static const struct qcom_cc_desc cam_cc_sm8450_desc = {
static const struct of_device_id cam_cc_sm8450_match_table[] = {
{ .compatible = "qcom,sm8450-camcc" },
+ { .compatible = "qcom,sm8475-camcc" },
{ }
};
MODULE_DEVICE_TABLE(of, cam_cc_sm8450_match_table);
@@ -2829,15 +3046,72 @@ static int cam_cc_sm8450_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- clk_lucid_evo_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
- clk_lucid_evo_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config);
- clk_rivian_evo_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config);
- clk_lucid_evo_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
- clk_lucid_evo_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config);
- clk_lucid_evo_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config);
- clk_lucid_evo_pll_configure(&cam_cc_pll6, regmap, &cam_cc_pll6_config);
- clk_lucid_evo_pll_configure(&cam_cc_pll7, regmap, &cam_cc_pll7_config);
- clk_lucid_evo_pll_configure(&cam_cc_pll8, regmap, &cam_cc_pll8_config);
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8475-camcc")) {
+ /* Update CAMCC PLL0 */
+ cam_cc_pll0.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll0_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll0_out_even.clkr.hw.init = &sm8475_cam_cc_pll0_out_even_init;
+ cam_cc_pll0_out_odd.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll0_out_odd.clkr.hw.init = &sm8475_cam_cc_pll0_out_odd_init;
+
+ /* Update CAMCC PLL1 */
+ cam_cc_pll1.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll1_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll1_out_even.clkr.hw.init = &sm8475_cam_cc_pll1_out_even_init;
+
+ /* Update CAMCC PLL2 */
+ cam_cc_pll2.vco_table = rivian_ole_vco;
+
+ /* Update CAMCC PLL3 */
+ cam_cc_pll3.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll3_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll3_out_even.clkr.hw.init = &sm8475_cam_cc_pll3_out_even_init;
+
+ /* Update CAMCC PLL4 */
+ cam_cc_pll4.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll4_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll4_out_even.clkr.hw.init = &sm8475_cam_cc_pll4_out_even_init;
+
+ /* Update CAMCC PLL5 */
+ cam_cc_pll5.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll5_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll5_out_even.clkr.hw.init = &sm8475_cam_cc_pll5_out_even_init;
+
+ /* Update CAMCC PLL6 */
+ cam_cc_pll6.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll6_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll6_out_even.clkr.hw.init = &sm8475_cam_cc_pll6_out_even_init;
+
+ /* Update CAMCC PLL7 */
+ cam_cc_pll7.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll7_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll7_out_even.clkr.hw.init = &sm8475_cam_cc_pll7_out_even_init;
+
+ /* Update CAMCC PLL8 */
+ cam_cc_pll8.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll8_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ cam_cc_pll8_out_even.clkr.hw.init = &sm8475_cam_cc_pll8_out_even_init;
+
+ clk_lucid_ole_pll_configure(&cam_cc_pll0, regmap, &sm8475_cam_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll1, regmap, &sm8475_cam_cc_pll1_config);
+ clk_rivian_evo_pll_configure(&cam_cc_pll2, regmap, &sm8475_cam_cc_pll2_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll3, regmap, &sm8475_cam_cc_pll3_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll4, regmap, &sm8475_cam_cc_pll4_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll5, regmap, &sm8475_cam_cc_pll5_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll6, regmap, &sm8475_cam_cc_pll6_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll7, regmap, &sm8475_cam_cc_pll7_config);
+ clk_lucid_ole_pll_configure(&cam_cc_pll8, regmap, &sm8475_cam_cc_pll8_config);
+ } else {
+ clk_lucid_evo_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config);
+ clk_rivian_evo_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll6, regmap, &cam_cc_pll6_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll7, regmap, &cam_cc_pll7_config);
+ clk_lucid_evo_pll_configure(&cam_cc_pll8, regmap, &cam_cc_pll8_config);
+ }
return qcom_cc_really_probe(&pdev->dev, &cam_cc_sm8450_desc, regmap);
}
@@ -2852,5 +3126,5 @@ static struct platform_driver cam_cc_sm8450_driver = {
module_platform_driver(cam_cc_sm8450_driver);
-MODULE_DESCRIPTION("QCOM CAMCC SM8450 Driver");
+MODULE_DESCRIPTION("QCOM CAMCC SM8450 / SM8475 Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index f9105443d7db..b8351f8c0b84 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -40,7 +40,7 @@
#define PLL_USER_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL])
# define PLL_POST_DIV_SHIFT 8
-# define PLL_POST_DIV_MASK(p) GENMASK((p)->width - 1, 0)
+# define PLL_POST_DIV_MASK(p) GENMASK((p)->width ? (p)->width - 1 : 3, 0)
# define PLL_ALPHA_MSB BIT(15)
# define PLL_ALPHA_EN BIT(24)
# define PLL_ALPHA_MODE BIT(25)
@@ -267,6 +267,17 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
[PLL_OFF_OPMODE] = 0x30,
[PLL_OFF_STATUS] = 0x3c,
},
+ [CLK_ALPHA_PLL_TYPE_NSS_HUAYRA] = {
+ [PLL_OFF_L_VAL] = 0x04,
+ [PLL_OFF_ALPHA_VAL] = 0x08,
+ [PLL_OFF_TEST_CTL] = 0x0c,
+ [PLL_OFF_TEST_CTL_U] = 0x10,
+ [PLL_OFF_USER_CTL] = 0x14,
+ [PLL_OFF_CONFIG_CTL] = 0x18,
+ [PLL_OFF_CONFIG_CTL_U] = 0x1c,
+ [PLL_OFF_STATUS] = 0x20,
+ },
+
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
@@ -1903,9 +1914,8 @@ static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw)
}
/* Check if PLL is already enabled, return if enabled */
- ret = trion_pll_is_enabled(pll, pll->clkr.regmap);
- if (ret < 0)
- return ret;
+ if (trion_pll_is_enabled(pll, pll->clkr.regmap))
+ return 0;
ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
if (ret)
@@ -2318,13 +2328,8 @@ static int alpha_pll_lucid_evo_enable(struct clk_hw *hw)
}
/* Check if PLL is already enabled */
- ret = trion_pll_is_enabled(pll, regmap);
- if (ret < 0) {
- return ret;
- } else if (ret) {
- pr_warn("%s PLL is already enabled\n", clk_hw_get_name(&pll->clkr.hw));
+ if (trion_pll_is_enabled(pll, regmap))
return 0;
- }
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
if (ret)
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 55eca04b23a1..c6d1b8429f95 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -32,6 +32,7 @@ enum {
CLK_ALPHA_PLL_TYPE_BRAMMO_EVO,
CLK_ALPHA_PLL_TYPE_STROMER,
CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
+ CLK_ALPHA_PLL_TYPE_NSS_HUAYRA,
CLK_ALPHA_PLL_TYPE_MAX,
};
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 8e0f3372dc7a..80f1f4fcd52a 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -198,6 +198,7 @@ extern const struct clk_ops clk_byte2_ops;
extern const struct clk_ops clk_pixel_ops;
extern const struct clk_ops clk_gfx3d_ops;
extern const struct clk_ops clk_rcg2_shared_ops;
+extern const struct clk_ops clk_rcg2_shared_floor_ops;
extern const struct clk_ops clk_rcg2_shared_no_init_park_ops;
extern const struct clk_ops clk_dp_ops;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index bf26c5448f00..bf6406f5279a 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -1186,15 +1186,23 @@ clk_rcg2_shared_force_enable_clear(struct clk_hw *hw, const struct freq_tbl *f)
return clk_rcg2_clear_force_enable(hw);
}
-static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
+static int __clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate,
+ enum freq_policy policy)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
const struct freq_tbl *f;
- f = qcom_find_freq(rcg->freq_tbl, rate);
- if (!f)
+ switch (policy) {
+ case FLOOR:
+ f = qcom_find_freq_floor(rcg->freq_tbl, rate);
+ break;
+ case CEIL:
+ f = qcom_find_freq(rcg->freq_tbl, rate);
+ break;
+ default:
return -EINVAL;
+ }
/*
* In case clock is disabled, update the M, N and D registers, cache
@@ -1207,10 +1215,28 @@ static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
return clk_rcg2_shared_force_enable_clear(hw, f);
}
+static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return __clk_rcg2_shared_set_rate(hw, rate, parent_rate, CEIL);
+}
+
static int clk_rcg2_shared_set_rate_and_parent(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate, u8 index)
{
- return clk_rcg2_shared_set_rate(hw, rate, parent_rate);
+ return __clk_rcg2_shared_set_rate(hw, rate, parent_rate, CEIL);
+}
+
+static int clk_rcg2_shared_set_floor_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return __clk_rcg2_shared_set_rate(hw, rate, parent_rate, FLOOR);
+}
+
+static int clk_rcg2_shared_set_floor_rate_and_parent(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate, u8 index)
+{
+ return __clk_rcg2_shared_set_rate(hw, rate, parent_rate, FLOOR);
}
static int clk_rcg2_shared_enable(struct clk_hw *hw)
@@ -1348,6 +1374,18 @@ const struct clk_ops clk_rcg2_shared_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops);
+const struct clk_ops clk_rcg2_shared_floor_ops = {
+ .enable = clk_rcg2_shared_enable,
+ .disable = clk_rcg2_shared_disable,
+ .get_parent = clk_rcg2_shared_get_parent,
+ .set_parent = clk_rcg2_shared_set_parent,
+ .recalc_rate = clk_rcg2_shared_recalc_rate,
+ .determine_rate = clk_rcg2_determine_floor_rate,
+ .set_rate = clk_rcg2_shared_set_floor_rate,
+ .set_rate_and_parent = clk_rcg2_shared_set_floor_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_shared_floor_ops);
+
static int clk_rcg2_shared_no_init_park(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c
index 4acde937114a..eefc322ce367 100644
--- a/drivers/clk/qcom/clk-rpmh.c
+++ b/drivers/clk/qcom/clk-rpmh.c
@@ -389,6 +389,18 @@ DEFINE_CLK_RPMH_BCM(ipa, "IP0");
DEFINE_CLK_RPMH_BCM(pka, "PKA0");
DEFINE_CLK_RPMH_BCM(qpic_clk, "QP0");
+static struct clk_hw *sar2130p_rpmh_clocks[] = {
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div1.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div1_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw,
+};
+
+static const struct clk_rpmh_desc clk_rpmh_sar2130p = {
+ .clks = sar2130p_rpmh_clocks,
+ .num_clks = ARRAY_SIZE(sar2130p_rpmh_clocks),
+};
+
static struct clk_hw *sdm845_rpmh_clocks[] = {
[RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
[RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
@@ -880,6 +892,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,sa8775p-rpmh-clk", .data = &clk_rpmh_sa8775p},
+ { .compatible = "qcom,sar2130p-rpmh-clk", .data = &clk_rpmh_sar2130p},
{ .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/common.h b/drivers/clk/qcom/common.h
index 7e57f8fe8ea6..7ace5d7f5836 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -35,7 +35,7 @@ struct qcom_cc_desc {
size_t num_gdscs;
struct clk_hw **clk_hws;
size_t num_clk_hws;
- struct qcom_icc_hws_data *icc_hws;
+ const struct qcom_icc_hws_data *icc_hws;
size_t num_icc_hws;
unsigned int icc_first_node_id;
};
diff --git a/drivers/clk/qcom/dispcc-sm8450.c b/drivers/clk/qcom/dispcc-sm8450.c
index d1d3f60789ee..a1f183e6c636 100644
--- a/drivers/clk/qcom/dispcc-sm8450.c
+++ b/drivers/clk/qcom/dispcc-sm8450.c
@@ -85,6 +85,29 @@ static const struct alpha_pll_config disp_cc_pll0_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_disp_cc_pll0_config = {
+ .l = 0xd,
+ .alpha = 0x6492,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_init_data sm8475_disp_cc_pll0_init = {
+ .name = "disp_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_reset_lucid_ole_ops,
+};
+
static struct clk_alpha_pll disp_cc_pll0 = {
.offset = 0x0,
.vco_table = lucid_evo_vco,
@@ -112,6 +135,29 @@ static const struct alpha_pll_config disp_cc_pll1_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_disp_cc_pll1_config = {
+ .l = 0x1f,
+ .alpha = 0x4000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_init_data sm8475_disp_cc_pll1_init = {
+ .name = "disp_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_reset_lucid_ole_ops,
+};
+
static struct clk_alpha_pll disp_cc_pll1 = {
.offset = 0x1000,
.vco_table = lucid_evo_vco,
@@ -1746,6 +1792,7 @@ static struct qcom_cc_desc disp_cc_sm8450_desc = {
static const struct of_device_id disp_cc_sm8450_match_table[] = {
{ .compatible = "qcom,sm8450-dispcc" },
+ { .compatible = "qcom,sm8475-dispcc" },
{ }
};
MODULE_DEVICE_TABLE(of, disp_cc_sm8450_match_table);
@@ -1769,8 +1816,21 @@ static int disp_cc_sm8450_probe(struct platform_device *pdev)
goto err_put_rpm;
}
- clk_lucid_evo_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
- clk_lucid_evo_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll1_config);
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8475-dispcc")) {
+ /* Update DISPCC PLL0 */
+ disp_cc_pll0.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ disp_cc_pll0.clkr.hw.init = &sm8475_disp_cc_pll0_init;
+
+ /* Update DISPCC PLL1 */
+ disp_cc_pll1.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ disp_cc_pll1.clkr.hw.init = &sm8475_disp_cc_pll1_init;
+
+ clk_lucid_ole_pll_configure(&disp_cc_pll0, regmap, &sm8475_disp_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&disp_cc_pll1, regmap, &sm8475_disp_cc_pll1_config);
+ } else {
+ clk_lucid_evo_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll1_config);
+ }
/* Enable clock gating for MDP clocks */
regmap_update_bits(regmap, DISP_CC_MISC_CMD, 0x10, 0x10);
@@ -1802,5 +1862,5 @@ static struct platform_driver disp_cc_sm8450_driver = {
module_platform_driver(disp_cc_sm8450_driver);
-MODULE_DESCRIPTION("QTI DISPCC SM8450 Driver");
+MODULE_DESCRIPTION("QTI DISPCC SM8450 / SM8475 Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/dispcc-sm8550.c b/drivers/clk/qcom/dispcc-sm8550.c
index 7f9021ca0ecb..e41d4104d770 100644
--- a/drivers/clk/qcom/dispcc-sm8550.c
+++ b/drivers/clk/qcom/dispcc-sm8550.c
@@ -75,7 +75,7 @@ static struct pll_vco lucid_ole_vco[] = {
{ 249600000, 2000000000, 0 },
};
-static const struct alpha_pll_config disp_cc_pll0_config = {
+static struct alpha_pll_config disp_cc_pll0_config = {
.l = 0xd,
.alpha = 0x6492,
.config_ctl_val = 0x20485699,
@@ -106,7 +106,7 @@ static struct clk_alpha_pll disp_cc_pll0 = {
},
};
-static const struct alpha_pll_config disp_cc_pll1_config = {
+static struct alpha_pll_config disp_cc_pll1_config = {
.l = 0x1f,
.alpha = 0x4000,
.config_ctl_val = 0x20485699,
@@ -594,6 +594,13 @@ static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
{ }
};
+static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src_sar2130p[] = {
+ F(200000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(325000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(514000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src_sm8650[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(85714286, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
@@ -1750,6 +1757,7 @@ static struct qcom_cc_desc disp_cc_sm8550_desc = {
};
static const struct of_device_id disp_cc_sm8550_match_table[] = {
+ { .compatible = "qcom,sar2130p-dispcc" },
{ .compatible = "qcom,sm8550-dispcc" },
{ .compatible = "qcom,sm8650-dispcc" },
{ }
@@ -1780,6 +1788,12 @@ static int disp_cc_sm8550_probe(struct platform_device *pdev)
disp_cc_mdss_mdp_clk_src.freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src_sm8650;
disp_cc_mdss_dptx1_usb_router_link_intf_clk.clkr.hw.init->parent_hws[0] =
&disp_cc_mdss_dptx1_link_div_clk_src.clkr.hw;
+ } else if (of_device_is_compatible(pdev->dev.of_node, "qcom,sar2130p-dispcc")) {
+ disp_cc_pll0_config.l = 0x1f;
+ disp_cc_pll0_config.alpha = 0x4000;
+ disp_cc_pll0_config.user_ctl_val = 0x1;
+ disp_cc_pll1_config.user_ctl_val = 0x1;
+ disp_cc_mdss_mdp_clk_src.freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src_sar2130p;
}
clk_lucid_ole_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
diff --git a/drivers/clk/qcom/dispcc0-sa8775p.c b/drivers/clk/qcom/dispcc0-sa8775p.c
new file mode 100644
index 000000000000..6e399b5f1383
--- /dev/null
+++ b/drivers/clk/qcom/dispcc0-sa8775p.c
@@ -0,0 +1,1481 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sa8775p-dispcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_IFACE,
+ DT_BI_TCXO,
+ DT_BI_TCXO_AO,
+ 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_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_DSI0_PHY_PLL_OUT_BYTECLK,
+ P_DSI0_PHY_PLL_OUT_DSICLK,
+ P_DSI1_PHY_PLL_OUT_BYTECLK,
+ P_DSI1_PHY_PLL_OUT_DSICLK,
+ P_MDSS_0_DISP_CC_PLL0_OUT_MAIN,
+ P_MDSS_0_DISP_CC_PLL1_OUT_EVEN,
+ P_MDSS_0_DISP_CC_PLL1_OUT_MAIN,
+ P_SLEEP_CLK,
+};
+
+static const struct pll_vco lucid_evo_vco[] = {
+ { 249600000, 2020000000, 0 },
+};
+
+static const struct alpha_pll_config mdss_0_disp_cc_pll0_config = {
+ .l = 0x3a,
+ .alpha = 0x9800,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll mdss_0_disp_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config mdss_0_disp_cc_pll1_config = {
+ .l = 0x1f,
+ .alpha = 0x4000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll mdss_0_disp_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map disp_cc_0_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_DP0_PHY_PLL_LINK_CLK, 1 },
+ { P_DP0_PHY_PLL_VCO_DIV_CLK, 2 },
+ { P_DP1_PHY_PLL_VCO_DIV_CLK, 4 },
+};
+
+static const struct clk_parent_data disp_cc_0_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP0_PHY_PLL_VCO_DIV_CLK },
+ { .index = DT_DP1_PHY_PLL_VCO_DIV_CLK },
+};
+
+static const struct parent_map disp_cc_0_parent_map_1[] = {
+ { 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_0_parent_data_1[] = {
+ { .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_0_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data disp_cc_0_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct clk_parent_data disp_cc_0_parent_data_2_ao[] = {
+ { .index = DT_BI_TCXO_AO },
+};
+
+static const struct parent_map disp_cc_0_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_DP0_PHY_PLL_LINK_CLK, 1 },
+ { P_DP1_PHY_PLL_LINK_CLK, 2 },
+};
+
+static const struct clk_parent_data disp_cc_0_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP1_PHY_PLL_LINK_CLK },
+};
+
+static const struct parent_map disp_cc_0_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_0_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_0_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_MDSS_0_DISP_CC_PLL1_OUT_MAIN, 4 },
+ { P_MDSS_0_DISP_CC_PLL1_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data disp_cc_0_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &mdss_0_disp_cc_pll1.clkr.hw },
+ { .hw = &mdss_0_disp_cc_pll1.clkr.hw },
+};
+
+static const struct parent_map disp_cc_0_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_MDSS_0_DISP_CC_PLL0_OUT_MAIN, 1 },
+ { P_MDSS_0_DISP_CC_PLL1_OUT_MAIN, 4 },
+ { P_MDSS_0_DISP_CC_PLL1_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data disp_cc_0_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &mdss_0_disp_cc_pll0.clkr.hw },
+ { .hw = &mdss_0_disp_cc_pll1.clkr.hw },
+ { .hw = &mdss_0_disp_cc_pll1.clkr.hw },
+};
+
+static const struct parent_map disp_cc_0_parent_map_7[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data disp_cc_0_parent_data_7[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct freq_tbl ftbl_mdss_0_disp_cc_mdss_ahb_clk_src[] = {
+ F(37500000, P_MDSS_0_DISP_CC_PLL1_OUT_MAIN, 16, 0, 0),
+ F(75000000, P_MDSS_0_DISP_CC_PLL1_OUT_MAIN, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_ahb_clk_src = {
+ .cmd_rcgr = 0x824c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_5,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_ahb_clk_src",
+ .parent_data = disp_cc_0_parent_data_5,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mdss_0_disp_cc_mdss_byte0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_byte0_clk_src = {
+ .cmd_rcgr = 0x80ec,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_1,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte0_clk_src",
+ .parent_data = disp_cc_0_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_byte1_clk_src = {
+ .cmd_rcgr = 0x8108,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_1,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte1_clk_src",
+ .parent_data = disp_cc_0_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx0_aux_clk_src = {
+ .cmd_rcgr = 0x81b8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_2,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_aux_clk_src",
+ .parent_data = disp_cc_0_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx0_crypto_clk_src = {
+ .cmd_rcgr = 0x8170,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_3,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_crypto_clk_src",
+ .parent_data = disp_cc_0_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx0_link_clk_src = {
+ .cmd_rcgr = 0x8154,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_3,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_link_clk_src",
+ .parent_data = disp_cc_0_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx0_pixel0_clk_src = {
+ .cmd_rcgr = 0x8188,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_0,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel0_clk_src",
+ .parent_data = disp_cc_0_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx0_pixel1_clk_src = {
+ .cmd_rcgr = 0x81a0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_0,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel1_clk_src",
+ .parent_data = disp_cc_0_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx0_pixel2_clk_src = {
+ .cmd_rcgr = 0x826c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_0,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel2_clk_src",
+ .parent_data = disp_cc_0_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx0_pixel3_clk_src = {
+ .cmd_rcgr = 0x8284,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_0,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel3_clk_src",
+ .parent_data = disp_cc_0_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx1_aux_clk_src = {
+ .cmd_rcgr = 0x8234,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_2,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_aux_clk_src",
+ .parent_data = disp_cc_0_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx1_crypto_clk_src = {
+ .cmd_rcgr = 0x821c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_3,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_crypto_clk_src",
+ .parent_data = disp_cc_0_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx1_link_clk_src = {
+ .cmd_rcgr = 0x8200,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_3,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_link_clk_src",
+ .parent_data = disp_cc_0_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx1_pixel0_clk_src = {
+ .cmd_rcgr = 0x81d0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_0,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_pixel0_clk_src",
+ .parent_data = disp_cc_0_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_dptx1_pixel1_clk_src = {
+ .cmd_rcgr = 0x81e8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_0,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_pixel1_clk_src",
+ .parent_data = disp_cc_0_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_esc0_clk_src = {
+ .cmd_rcgr = 0x8124,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_4,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_esc0_clk_src",
+ .parent_data = disp_cc_0_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_esc1_clk_src = {
+ .cmd_rcgr = 0x813c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_4,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_esc1_clk_src",
+ .parent_data = disp_cc_0_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mdss_0_disp_cc_mdss_mdp_clk_src[] = {
+ F(375000000, P_MDSS_0_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(500000000, P_MDSS_0_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(575000000, P_MDSS_0_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(650000000, P_MDSS_0_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_mdp_clk_src = {
+ .cmd_rcgr = 0x80bc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_6,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_mdp_clk_src",
+ .parent_data = disp_cc_0_parent_data_6,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_pclk0_clk_src = {
+ .cmd_rcgr = 0x808c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_1,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_pclk0_clk_src",
+ .parent_data = disp_cc_0_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_pclk1_clk_src = {
+ .cmd_rcgr = 0x80a4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_1,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_pclk1_clk_src",
+ .parent_data = disp_cc_0_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_mdss_vsync_clk_src = {
+ .cmd_rcgr = 0x80d4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_2,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_vsync_clk_src",
+ .parent_data = disp_cc_0_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mdss_0_disp_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_sleep_clk_src = {
+ .cmd_rcgr = 0xc058,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_7,
+ .freq_tbl = ftbl_mdss_0_disp_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_sleep_clk_src",
+ .parent_data = disp_cc_0_parent_data_7,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_7),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_0_disp_cc_xo_clk_src = {
+ .cmd_rcgr = 0xc03c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_0_parent_map_2,
+ .freq_tbl = ftbl_mdss_0_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_xo_clk_src",
+ .parent_data = disp_cc_0_parent_data_2_ao,
+ .num_parents = ARRAY_SIZE(disp_cc_0_parent_data_2_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div mdss_0_disp_cc_mdss_byte0_div_clk_src = {
+ .reg = 0x8104,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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 mdss_0_disp_cc_mdss_byte1_div_clk_src = {
+ .reg = 0x8120,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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 mdss_0_disp_cc_mdss_dptx0_link_div_clk_src = {
+ .reg = 0x816c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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 mdss_0_disp_cc_mdss_dptx1_link_div_clk_src = {
+ .reg = 0x8218,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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_branch mdss_0_disp_cc_mdss_ahb1_clk = {
+ .halt_reg = 0x8088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_ahb1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_ahb_clk = {
+ .halt_reg = 0x8084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_byte0_clk = {
+ .halt_reg = 0x8034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_byte0_intf_clk = {
+ .halt_reg = 0x8038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte0_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_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 mdss_0_disp_cc_mdss_byte1_clk = {
+ .halt_reg = 0x803c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x803c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_byte1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_byte1_intf_clk = {
+ .halt_reg = 0x8040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_byte1_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_byte1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_aux_clk = {
+ .halt_reg = 0x805c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x805c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx0_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_crypto_clk = {
+ .halt_reg = 0x8058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_crypto_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx0_crypto_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_link_clk = {
+ .halt_reg = 0x804c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x804c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_link_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx0_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_link_intf_clk = {
+ .halt_reg = 0x8050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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 mdss_0_disp_cc_mdss_dptx0_pixel0_clk = {
+ .halt_reg = 0x8060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx0_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_pixel1_clk = {
+ .halt_reg = 0x8064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx0_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_pixel2_clk = {
+ .halt_reg = 0x8264,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8264,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx0_pixel2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_pixel3_clk = {
+ .halt_reg = 0x8268,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8268,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_pixel3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx0_pixel3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx0_usb_router_link_intf_clk = {
+ .halt_reg = 0x8054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx0_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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 mdss_0_disp_cc_mdss_dptx1_aux_clk = {
+ .halt_reg = 0x8080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx1_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx1_crypto_clk = {
+ .halt_reg = 0x807c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x807c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_crypto_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx1_crypto_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx1_link_clk = {
+ .halt_reg = 0x8070,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8070,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_link_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx1_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx1_link_intf_clk = {
+ .halt_reg = 0x8074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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 mdss_0_disp_cc_mdss_dptx1_pixel0_clk = {
+ .halt_reg = 0x8068,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx1_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx1_pixel1_clk = {
+ .halt_reg = 0x806c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x806c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_dptx1_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_dptx1_usb_router_link_intf_clk = {
+ .halt_reg = 0x8078,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_dptx1_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_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 mdss_0_disp_cc_mdss_esc0_clk = {
+ .halt_reg = 0x8044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_esc0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_esc1_clk = {
+ .halt_reg = 0x8048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_esc1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_esc1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_mdp1_clk = {
+ .halt_reg = 0x8014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_mdp1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_mdp_clk = {
+ .halt_reg = 0x800c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x800c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_mdp_lut1_clk = {
+ .halt_reg = 0x8024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_mdp_lut1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_mdp_lut_clk = {
+ .halt_reg = 0x801c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x801c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_mdp_lut_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_non_gdsc_ahb_clk = {
+ .halt_reg = 0xa004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0xa004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_non_gdsc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_pclk0_clk = {
+ .halt_reg = 0x8004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_pclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_pclk1_clk = {
+ .halt_reg = 0x8008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_pclk1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_pclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_pll_lock_monitor_clk = {
+ .halt_reg = 0xe000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xe000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_pll_lock_monitor_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_rscc_ahb_clk = {
+ .halt_reg = 0xa00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xa00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_rscc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_rscc_vsync_clk = {
+ .halt_reg = 0xa008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xa008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_rscc_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_vsync1_clk = {
+ .halt_reg = 0x8030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_vsync1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_mdss_vsync_clk = {
+ .halt_reg = 0x802c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x802c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_0_disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_0_disp_cc_sm_obs_clk = {
+ .halt_reg = 0x11014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x11014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_0_disp_cc_sm_obs_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc mdss_0_disp_cc_mdss_core_gdsc = {
+ .gdscr = 0x9000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "mdss_0_disp_cc_mdss_core_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct gdsc mdss_0_disp_cc_mdss_core_int2_gdsc = {
+ .gdscr = 0xd000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "mdss_0_disp_cc_mdss_core_int2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct clk_regmap *disp_cc_0_sa8775p_clocks[] = {
+ [MDSS_DISP_CC_MDSS_AHB1_CLK] = &mdss_0_disp_cc_mdss_ahb1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_AHB_CLK] = &mdss_0_disp_cc_mdss_ahb_clk.clkr,
+ [MDSS_DISP_CC_MDSS_AHB_CLK_SRC] = &mdss_0_disp_cc_mdss_ahb_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_CLK] = &mdss_0_disp_cc_mdss_byte0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_CLK_SRC] = &mdss_0_disp_cc_mdss_byte0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &mdss_0_disp_cc_mdss_byte0_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_INTF_CLK] = &mdss_0_disp_cc_mdss_byte0_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_CLK] = &mdss_0_disp_cc_mdss_byte1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_CLK_SRC] = &mdss_0_disp_cc_mdss_byte1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_DIV_CLK_SRC] = &mdss_0_disp_cc_mdss_byte1_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_INTF_CLK] = &mdss_0_disp_cc_mdss_byte1_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK] = &mdss_0_disp_cc_mdss_dptx0_aux_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx0_aux_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_CRYPTO_CLK] = &mdss_0_disp_cc_mdss_dptx0_crypto_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_CRYPTO_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx0_crypto_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK] = &mdss_0_disp_cc_mdss_dptx0_link_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx0_link_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_DIV_CLK_SRC] =
+ &mdss_0_disp_cc_mdss_dptx0_link_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_INTF_CLK] = &mdss_0_disp_cc_mdss_dptx0_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK] = &mdss_0_disp_cc_mdss_dptx0_pixel0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx0_pixel0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK] = &mdss_0_disp_cc_mdss_dptx0_pixel1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx0_pixel1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK] = &mdss_0_disp_cc_mdss_dptx0_pixel2_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx0_pixel2_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK] = &mdss_0_disp_cc_mdss_dptx0_pixel3_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx0_pixel3_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_USB_ROUTER_LINK_INTF_CLK] =
+ &mdss_0_disp_cc_mdss_dptx0_usb_router_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK] = &mdss_0_disp_cc_mdss_dptx1_aux_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx1_aux_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_CRYPTO_CLK] = &mdss_0_disp_cc_mdss_dptx1_crypto_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_CRYPTO_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx1_crypto_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK] = &mdss_0_disp_cc_mdss_dptx1_link_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx1_link_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_DIV_CLK_SRC] =
+ &mdss_0_disp_cc_mdss_dptx1_link_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_INTF_CLK] = &mdss_0_disp_cc_mdss_dptx1_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK] = &mdss_0_disp_cc_mdss_dptx1_pixel0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx1_pixel0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK] = &mdss_0_disp_cc_mdss_dptx1_pixel1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK_SRC] = &mdss_0_disp_cc_mdss_dptx1_pixel1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_USB_ROUTER_LINK_INTF_CLK] =
+ &mdss_0_disp_cc_mdss_dptx1_usb_router_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_ESC0_CLK] = &mdss_0_disp_cc_mdss_esc0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_ESC0_CLK_SRC] = &mdss_0_disp_cc_mdss_esc0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_ESC1_CLK] = &mdss_0_disp_cc_mdss_esc1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_ESC1_CLK_SRC] = &mdss_0_disp_cc_mdss_esc1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_MDP1_CLK] = &mdss_0_disp_cc_mdss_mdp1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_CLK] = &mdss_0_disp_cc_mdss_mdp_clk.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_CLK_SRC] = &mdss_0_disp_cc_mdss_mdp_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_LUT1_CLK] = &mdss_0_disp_cc_mdss_mdp_lut1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_LUT_CLK] = &mdss_0_disp_cc_mdss_mdp_lut_clk.clkr,
+ [MDSS_DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &mdss_0_disp_cc_mdss_non_gdsc_ahb_clk.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK0_CLK] = &mdss_0_disp_cc_mdss_pclk0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK0_CLK_SRC] = &mdss_0_disp_cc_mdss_pclk0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK1_CLK] = &mdss_0_disp_cc_mdss_pclk1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK1_CLK_SRC] = &mdss_0_disp_cc_mdss_pclk1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_PLL_LOCK_MONITOR_CLK] = &mdss_0_disp_cc_mdss_pll_lock_monitor_clk.clkr,
+ [MDSS_DISP_CC_MDSS_RSCC_AHB_CLK] = &mdss_0_disp_cc_mdss_rscc_ahb_clk.clkr,
+ [MDSS_DISP_CC_MDSS_RSCC_VSYNC_CLK] = &mdss_0_disp_cc_mdss_rscc_vsync_clk.clkr,
+ [MDSS_DISP_CC_MDSS_VSYNC1_CLK] = &mdss_0_disp_cc_mdss_vsync1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_VSYNC_CLK] = &mdss_0_disp_cc_mdss_vsync_clk.clkr,
+ [MDSS_DISP_CC_MDSS_VSYNC_CLK_SRC] = &mdss_0_disp_cc_mdss_vsync_clk_src.clkr,
+ [MDSS_DISP_CC_PLL0] = &mdss_0_disp_cc_pll0.clkr,
+ [MDSS_DISP_CC_PLL1] = &mdss_0_disp_cc_pll1.clkr,
+ [MDSS_DISP_CC_SLEEP_CLK_SRC] = &mdss_0_disp_cc_sleep_clk_src.clkr,
+ [MDSS_DISP_CC_SM_OBS_CLK] = &mdss_0_disp_cc_sm_obs_clk.clkr,
+ [MDSS_DISP_CC_XO_CLK_SRC] = &mdss_0_disp_cc_xo_clk_src.clkr,
+};
+
+static struct gdsc *disp_cc_0_sa8775p_gdscs[] = {
+ [MDSS_DISP_CC_MDSS_CORE_GDSC] = &mdss_0_disp_cc_mdss_core_gdsc,
+ [MDSS_DISP_CC_MDSS_CORE_INT2_GDSC] = &mdss_0_disp_cc_mdss_core_int2_gdsc,
+};
+
+static const struct qcom_reset_map disp_cc_0_sa8775p_resets[] = {
+ [MDSS_DISP_CC_MDSS_CORE_BCR] = { 0x8000 },
+ [MDSS_DISP_CC_MDSS_RSCC_BCR] = { 0xa000 },
+};
+
+static const struct regmap_config disp_cc_0_sa8775p_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x12414,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc disp_cc_0_sa8775p_desc = {
+ .config = &disp_cc_0_sa8775p_regmap_config,
+ .clks = disp_cc_0_sa8775p_clocks,
+ .num_clks = ARRAY_SIZE(disp_cc_0_sa8775p_clocks),
+ .resets = disp_cc_0_sa8775p_resets,
+ .num_resets = ARRAY_SIZE(disp_cc_0_sa8775p_resets),
+ .gdscs = disp_cc_0_sa8775p_gdscs,
+ .num_gdscs = ARRAY_SIZE(disp_cc_0_sa8775p_gdscs),
+};
+
+static const struct of_device_id disp_cc_0_sa8775p_match_table[] = {
+ { .compatible = "qcom,sa8775p-dispcc0" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, disp_cc_0_sa8775p_match_table);
+
+static int disp_cc_0_sa8775p_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &disp_cc_0_sa8775p_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_evo_pll_configure(&mdss_0_disp_cc_pll0, regmap, &mdss_0_disp_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&mdss_0_disp_cc_pll1, regmap, &mdss_0_disp_cc_pll1_config);
+
+ /* Keep some clocks always enabled */
+ qcom_branch_set_clk_en(regmap, 0xc070); /* MDSS_0_DISP_CC_SLEEP_CLK */
+ qcom_branch_set_clk_en(regmap, 0xc054); /* MDSS_0_DISP_CC_XO_CLK */
+
+ ret = qcom_cc_really_probe(&pdev->dev, &disp_cc_0_sa8775p_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver disp_cc_0_sa8775p_driver = {
+ .probe = disp_cc_0_sa8775p_probe,
+ .driver = {
+ .name = "dispcc0-sa8775p",
+ .of_match_table = disp_cc_0_sa8775p_match_table,
+ },
+};
+
+module_platform_driver(disp_cc_0_sa8775p_driver);
+
+MODULE_DESCRIPTION("QTI DISPCC0 SA8775P Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/dispcc1-sa8775p.c b/drivers/clk/qcom/dispcc1-sa8775p.c
new file mode 100644
index 000000000000..30ccea59415a
--- /dev/null
+++ b/drivers/clk/qcom/dispcc1-sa8775p.c
@@ -0,0 +1,1481 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sa8775p-dispcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_IFACE,
+ DT_BI_TCXO,
+ DT_BI_TCXO_AO,
+ 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_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_DSI0_PHY_PLL_OUT_BYTECLK,
+ P_DSI0_PHY_PLL_OUT_DSICLK,
+ P_DSI1_PHY_PLL_OUT_BYTECLK,
+ P_DSI1_PHY_PLL_OUT_DSICLK,
+ P_MDSS_1_DISP_CC_PLL0_OUT_MAIN,
+ P_MDSS_1_DISP_CC_PLL1_OUT_EVEN,
+ P_MDSS_1_DISP_CC_PLL1_OUT_MAIN,
+ P_SLEEP_CLK,
+};
+
+static const struct pll_vco lucid_evo_vco[] = {
+ { 249600000, 2020000000, 0 },
+};
+
+static const struct alpha_pll_config mdss_1_disp_cc_pll0_config = {
+ .l = 0x3a,
+ .alpha = 0x9800,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll mdss_1_disp_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config mdss_1_disp_cc_pll1_config = {
+ .l = 0x1f,
+ .alpha = 0x4000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll mdss_1_disp_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map disp_cc_1_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_DP0_PHY_PLL_LINK_CLK, 1 },
+ { P_DP0_PHY_PLL_VCO_DIV_CLK, 2 },
+ { P_DP1_PHY_PLL_VCO_DIV_CLK, 4 },
+};
+
+static const struct clk_parent_data disp_cc_1_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP0_PHY_PLL_VCO_DIV_CLK },
+ { .index = DT_DP1_PHY_PLL_VCO_DIV_CLK },
+};
+
+static const struct parent_map disp_cc_1_parent_map_1[] = {
+ { 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_1_parent_data_1[] = {
+ { .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_1_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data disp_cc_1_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct clk_parent_data disp_cc_1_parent_data_2_ao[] = {
+ { .index = DT_BI_TCXO_AO },
+};
+
+static const struct parent_map disp_cc_1_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_DP0_PHY_PLL_LINK_CLK, 1 },
+ { P_DP1_PHY_PLL_LINK_CLK, 2 },
+};
+
+static const struct clk_parent_data disp_cc_1_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP1_PHY_PLL_LINK_CLK },
+};
+
+static const struct parent_map disp_cc_1_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_1_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_1_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_MDSS_1_DISP_CC_PLL1_OUT_MAIN, 4 },
+ { P_MDSS_1_DISP_CC_PLL1_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data disp_cc_1_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &mdss_1_disp_cc_pll1.clkr.hw },
+ { .hw = &mdss_1_disp_cc_pll1.clkr.hw },
+};
+
+static const struct parent_map disp_cc_1_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_MDSS_1_DISP_CC_PLL0_OUT_MAIN, 1 },
+ { P_MDSS_1_DISP_CC_PLL1_OUT_MAIN, 4 },
+ { P_MDSS_1_DISP_CC_PLL1_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data disp_cc_1_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &mdss_1_disp_cc_pll0.clkr.hw },
+ { .hw = &mdss_1_disp_cc_pll1.clkr.hw },
+ { .hw = &mdss_1_disp_cc_pll1.clkr.hw },
+};
+
+static const struct parent_map disp_cc_1_parent_map_7[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data disp_cc_1_parent_data_7_ao[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct freq_tbl ftbl_mdss_1_disp_cc_mdss_ahb_clk_src[] = {
+ F(37500000, P_MDSS_1_DISP_CC_PLL1_OUT_MAIN, 16, 0, 0),
+ F(75000000, P_MDSS_1_DISP_CC_PLL1_OUT_MAIN, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_ahb_clk_src = {
+ .cmd_rcgr = 0x824c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_5,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_ahb_clk_src",
+ .parent_data = disp_cc_1_parent_data_5,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mdss_1_disp_cc_mdss_byte0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_byte0_clk_src = {
+ .cmd_rcgr = 0x80ec,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_1,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte0_clk_src",
+ .parent_data = disp_cc_1_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_byte1_clk_src = {
+ .cmd_rcgr = 0x8108,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_1,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte1_clk_src",
+ .parent_data = disp_cc_1_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx0_aux_clk_src = {
+ .cmd_rcgr = 0x81b8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_2,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_aux_clk_src",
+ .parent_data = disp_cc_1_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx0_crypto_clk_src = {
+ .cmd_rcgr = 0x8170,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_3,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_crypto_clk_src",
+ .parent_data = disp_cc_1_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx0_link_clk_src = {
+ .cmd_rcgr = 0x8154,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_3,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_link_clk_src",
+ .parent_data = disp_cc_1_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx0_pixel0_clk_src = {
+ .cmd_rcgr = 0x8188,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_0,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel0_clk_src",
+ .parent_data = disp_cc_1_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx0_pixel1_clk_src = {
+ .cmd_rcgr = 0x81a0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_0,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel1_clk_src",
+ .parent_data = disp_cc_1_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx0_pixel2_clk_src = {
+ .cmd_rcgr = 0x826c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_0,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel2_clk_src",
+ .parent_data = disp_cc_1_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx0_pixel3_clk_src = {
+ .cmd_rcgr = 0x8284,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_0,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel3_clk_src",
+ .parent_data = disp_cc_1_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx1_aux_clk_src = {
+ .cmd_rcgr = 0x8234,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_2,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_aux_clk_src",
+ .parent_data = disp_cc_1_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx1_crypto_clk_src = {
+ .cmd_rcgr = 0x821c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_3,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_crypto_clk_src",
+ .parent_data = disp_cc_1_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx1_link_clk_src = {
+ .cmd_rcgr = 0x8200,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_3,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_link_clk_src",
+ .parent_data = disp_cc_1_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx1_pixel0_clk_src = {
+ .cmd_rcgr = 0x81d0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_0,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_pixel0_clk_src",
+ .parent_data = disp_cc_1_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_dptx1_pixel1_clk_src = {
+ .cmd_rcgr = 0x81e8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_0,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_pixel1_clk_src",
+ .parent_data = disp_cc_1_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_esc0_clk_src = {
+ .cmd_rcgr = 0x8124,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_4,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_esc0_clk_src",
+ .parent_data = disp_cc_1_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_esc1_clk_src = {
+ .cmd_rcgr = 0x813c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_4,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_esc1_clk_src",
+ .parent_data = disp_cc_1_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mdss_1_disp_cc_mdss_mdp_clk_src[] = {
+ F(375000000, P_MDSS_1_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(500000000, P_MDSS_1_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(575000000, P_MDSS_1_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(650000000, P_MDSS_1_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_mdp_clk_src = {
+ .cmd_rcgr = 0x80bc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_6,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_mdp_clk_src",
+ .parent_data = disp_cc_1_parent_data_6,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_pclk0_clk_src = {
+ .cmd_rcgr = 0x808c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_1,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_pclk0_clk_src",
+ .parent_data = disp_cc_1_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_pclk1_clk_src = {
+ .cmd_rcgr = 0x80a4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_1,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_pclk1_clk_src",
+ .parent_data = disp_cc_1_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_mdss_vsync_clk_src = {
+ .cmd_rcgr = 0x80d4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_2,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_vsync_clk_src",
+ .parent_data = disp_cc_1_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_mdss_1_disp_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_sleep_clk_src = {
+ .cmd_rcgr = 0xc058,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_7,
+ .freq_tbl = ftbl_mdss_1_disp_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_sleep_clk_src",
+ .parent_data = disp_cc_1_parent_data_7_ao,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_7_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 mdss_1_disp_cc_xo_clk_src = {
+ .cmd_rcgr = 0xc03c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_1_parent_map_2,
+ .freq_tbl = ftbl_mdss_1_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_xo_clk_src",
+ .parent_data = disp_cc_1_parent_data_2_ao,
+ .num_parents = ARRAY_SIZE(disp_cc_1_parent_data_2_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div mdss_1_disp_cc_mdss_byte0_div_clk_src = {
+ .reg = 0x8104,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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 mdss_1_disp_cc_mdss_byte1_div_clk_src = {
+ .reg = 0x8120,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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 mdss_1_disp_cc_mdss_dptx0_link_div_clk_src = {
+ .reg = 0x816c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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 mdss_1_disp_cc_mdss_dptx1_link_div_clk_src = {
+ .reg = 0x8218,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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_branch mdss_1_disp_cc_mdss_ahb1_clk = {
+ .halt_reg = 0x8088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_ahb1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_ahb_clk = {
+ .halt_reg = 0x8084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_byte0_clk = {
+ .halt_reg = 0x8034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_byte0_intf_clk = {
+ .halt_reg = 0x8038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte0_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_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 mdss_1_disp_cc_mdss_byte1_clk = {
+ .halt_reg = 0x803c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x803c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_byte1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_byte1_intf_clk = {
+ .halt_reg = 0x8040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_byte1_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_byte1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_aux_clk = {
+ .halt_reg = 0x805c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x805c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx0_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_crypto_clk = {
+ .halt_reg = 0x8058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_crypto_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx0_crypto_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_link_clk = {
+ .halt_reg = 0x804c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x804c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_link_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx0_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_link_intf_clk = {
+ .halt_reg = 0x8050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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 mdss_1_disp_cc_mdss_dptx0_pixel0_clk = {
+ .halt_reg = 0x8060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx0_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_pixel1_clk = {
+ .halt_reg = 0x8064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx0_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_pixel2_clk = {
+ .halt_reg = 0x8264,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8264,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx0_pixel2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_pixel3_clk = {
+ .halt_reg = 0x8268,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8268,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_pixel3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx0_pixel3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx0_usb_router_link_intf_clk = {
+ .halt_reg = 0x8054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx0_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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 mdss_1_disp_cc_mdss_dptx1_aux_clk = {
+ .halt_reg = 0x8080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx1_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx1_crypto_clk = {
+ .halt_reg = 0x807c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x807c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_crypto_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx1_crypto_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx1_link_clk = {
+ .halt_reg = 0x8070,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8070,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_link_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx1_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx1_link_intf_clk = {
+ .halt_reg = 0x8074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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 mdss_1_disp_cc_mdss_dptx1_pixel0_clk = {
+ .halt_reg = 0x8068,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx1_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx1_pixel1_clk = {
+ .halt_reg = 0x806c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x806c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_dptx1_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_dptx1_usb_router_link_intf_clk = {
+ .halt_reg = 0x8078,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_dptx1_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_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 mdss_1_disp_cc_mdss_esc0_clk = {
+ .halt_reg = 0x8044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_esc0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_esc1_clk = {
+ .halt_reg = 0x8048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_esc1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_esc1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_mdp1_clk = {
+ .halt_reg = 0x8014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_mdp1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_mdp_clk = {
+ .halt_reg = 0x800c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x800c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_mdp_lut1_clk = {
+ .halt_reg = 0x8024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x8024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_mdp_lut1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_mdp_lut_clk = {
+ .halt_reg = 0x801c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x801c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_mdp_lut_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_non_gdsc_ahb_clk = {
+ .halt_reg = 0xa004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0xa004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_non_gdsc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_pclk0_clk = {
+ .halt_reg = 0x8004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_pclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_pclk1_clk = {
+ .halt_reg = 0x8008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_pclk1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_pclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_pll_lock_monitor_clk = {
+ .halt_reg = 0xe000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xe000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_pll_lock_monitor_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_rscc_ahb_clk = {
+ .halt_reg = 0xa00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xa00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_rscc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_rscc_vsync_clk = {
+ .halt_reg = 0xa008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xa008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_rscc_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_vsync1_clk = {
+ .halt_reg = 0x8030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_vsync1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_mdss_vsync_clk = {
+ .halt_reg = 0x802c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x802c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &mdss_1_disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_1_disp_cc_sm_obs_clk = {
+ .halt_reg = 0x11014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x11014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "mdss_1_disp_cc_sm_obs_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc mdss_1_disp_cc_mdss_core_gdsc = {
+ .gdscr = 0x9000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "mdss_1_disp_cc_mdss_core_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct gdsc mdss_1_disp_cc_mdss_core_int2_gdsc = {
+ .gdscr = 0xd000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "mdss_1_disp_cc_mdss_core_int2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL,
+};
+
+static struct clk_regmap *disp_cc_1_sa8775p_clocks[] = {
+ [MDSS_DISP_CC_MDSS_AHB1_CLK] = &mdss_1_disp_cc_mdss_ahb1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_AHB_CLK] = &mdss_1_disp_cc_mdss_ahb_clk.clkr,
+ [MDSS_DISP_CC_MDSS_AHB_CLK_SRC] = &mdss_1_disp_cc_mdss_ahb_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_CLK] = &mdss_1_disp_cc_mdss_byte0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_CLK_SRC] = &mdss_1_disp_cc_mdss_byte0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &mdss_1_disp_cc_mdss_byte0_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE0_INTF_CLK] = &mdss_1_disp_cc_mdss_byte0_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_CLK] = &mdss_1_disp_cc_mdss_byte1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_CLK_SRC] = &mdss_1_disp_cc_mdss_byte1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_DIV_CLK_SRC] = &mdss_1_disp_cc_mdss_byte1_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_BYTE1_INTF_CLK] = &mdss_1_disp_cc_mdss_byte1_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK] = &mdss_1_disp_cc_mdss_dptx0_aux_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx0_aux_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_CRYPTO_CLK] = &mdss_1_disp_cc_mdss_dptx0_crypto_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_CRYPTO_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx0_crypto_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK] = &mdss_1_disp_cc_mdss_dptx0_link_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx0_link_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_DIV_CLK_SRC] =
+ &mdss_1_disp_cc_mdss_dptx0_link_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_LINK_INTF_CLK] = &mdss_1_disp_cc_mdss_dptx0_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK] = &mdss_1_disp_cc_mdss_dptx0_pixel0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx0_pixel0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK] = &mdss_1_disp_cc_mdss_dptx0_pixel1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx0_pixel1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK] = &mdss_1_disp_cc_mdss_dptx0_pixel2_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx0_pixel2_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK] = &mdss_1_disp_cc_mdss_dptx0_pixel3_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx0_pixel3_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX0_USB_ROUTER_LINK_INTF_CLK] =
+ &mdss_1_disp_cc_mdss_dptx0_usb_router_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK] = &mdss_1_disp_cc_mdss_dptx1_aux_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx1_aux_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_CRYPTO_CLK] = &mdss_1_disp_cc_mdss_dptx1_crypto_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_CRYPTO_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx1_crypto_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK] = &mdss_1_disp_cc_mdss_dptx1_link_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx1_link_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_DIV_CLK_SRC] =
+ &mdss_1_disp_cc_mdss_dptx1_link_div_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_LINK_INTF_CLK] = &mdss_1_disp_cc_mdss_dptx1_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK] = &mdss_1_disp_cc_mdss_dptx1_pixel0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx1_pixel0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK] = &mdss_1_disp_cc_mdss_dptx1_pixel1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK_SRC] = &mdss_1_disp_cc_mdss_dptx1_pixel1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_DPTX1_USB_ROUTER_LINK_INTF_CLK] =
+ &mdss_1_disp_cc_mdss_dptx1_usb_router_link_intf_clk.clkr,
+ [MDSS_DISP_CC_MDSS_ESC0_CLK] = &mdss_1_disp_cc_mdss_esc0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_ESC0_CLK_SRC] = &mdss_1_disp_cc_mdss_esc0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_ESC1_CLK] = &mdss_1_disp_cc_mdss_esc1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_ESC1_CLK_SRC] = &mdss_1_disp_cc_mdss_esc1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_MDP1_CLK] = &mdss_1_disp_cc_mdss_mdp1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_CLK] = &mdss_1_disp_cc_mdss_mdp_clk.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_CLK_SRC] = &mdss_1_disp_cc_mdss_mdp_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_LUT1_CLK] = &mdss_1_disp_cc_mdss_mdp_lut1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_MDP_LUT_CLK] = &mdss_1_disp_cc_mdss_mdp_lut_clk.clkr,
+ [MDSS_DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &mdss_1_disp_cc_mdss_non_gdsc_ahb_clk.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK0_CLK] = &mdss_1_disp_cc_mdss_pclk0_clk.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK0_CLK_SRC] = &mdss_1_disp_cc_mdss_pclk0_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK1_CLK] = &mdss_1_disp_cc_mdss_pclk1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_PCLK1_CLK_SRC] = &mdss_1_disp_cc_mdss_pclk1_clk_src.clkr,
+ [MDSS_DISP_CC_MDSS_PLL_LOCK_MONITOR_CLK] = &mdss_1_disp_cc_mdss_pll_lock_monitor_clk.clkr,
+ [MDSS_DISP_CC_MDSS_RSCC_AHB_CLK] = &mdss_1_disp_cc_mdss_rscc_ahb_clk.clkr,
+ [MDSS_DISP_CC_MDSS_RSCC_VSYNC_CLK] = &mdss_1_disp_cc_mdss_rscc_vsync_clk.clkr,
+ [MDSS_DISP_CC_MDSS_VSYNC1_CLK] = &mdss_1_disp_cc_mdss_vsync1_clk.clkr,
+ [MDSS_DISP_CC_MDSS_VSYNC_CLK] = &mdss_1_disp_cc_mdss_vsync_clk.clkr,
+ [MDSS_DISP_CC_MDSS_VSYNC_CLK_SRC] = &mdss_1_disp_cc_mdss_vsync_clk_src.clkr,
+ [MDSS_DISP_CC_PLL0] = &mdss_1_disp_cc_pll0.clkr,
+ [MDSS_DISP_CC_PLL1] = &mdss_1_disp_cc_pll1.clkr,
+ [MDSS_DISP_CC_SLEEP_CLK_SRC] = &mdss_1_disp_cc_sleep_clk_src.clkr,
+ [MDSS_DISP_CC_SM_OBS_CLK] = &mdss_1_disp_cc_sm_obs_clk.clkr,
+ [MDSS_DISP_CC_XO_CLK_SRC] = &mdss_1_disp_cc_xo_clk_src.clkr,
+};
+
+static struct gdsc *disp_cc_1_sa8775p_gdscs[] = {
+ [MDSS_DISP_CC_MDSS_CORE_GDSC] = &mdss_1_disp_cc_mdss_core_gdsc,
+ [MDSS_DISP_CC_MDSS_CORE_INT2_GDSC] = &mdss_1_disp_cc_mdss_core_int2_gdsc,
+};
+
+static const struct qcom_reset_map disp_cc_1_sa8775p_resets[] = {
+ [MDSS_DISP_CC_MDSS_CORE_BCR] = { 0x8000 },
+ [MDSS_DISP_CC_MDSS_RSCC_BCR] = { 0xa000 },
+};
+
+static const struct regmap_config disp_cc_1_sa8775p_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x12414,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc disp_cc_1_sa8775p_desc = {
+ .config = &disp_cc_1_sa8775p_regmap_config,
+ .clks = disp_cc_1_sa8775p_clocks,
+ .num_clks = ARRAY_SIZE(disp_cc_1_sa8775p_clocks),
+ .resets = disp_cc_1_sa8775p_resets,
+ .num_resets = ARRAY_SIZE(disp_cc_1_sa8775p_resets),
+ .gdscs = disp_cc_1_sa8775p_gdscs,
+ .num_gdscs = ARRAY_SIZE(disp_cc_1_sa8775p_gdscs),
+};
+
+static const struct of_device_id disp_cc_1_sa8775p_match_table[] = {
+ { .compatible = "qcom,sa8775p-dispcc1" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, disp_cc_1_sa8775p_match_table);
+
+static int disp_cc_1_sa8775p_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &disp_cc_1_sa8775p_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_evo_pll_configure(&mdss_1_disp_cc_pll0, regmap, &mdss_1_disp_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&mdss_1_disp_cc_pll1, regmap, &mdss_1_disp_cc_pll1_config);
+
+ /* Keep some clocks always enabled */
+ qcom_branch_set_clk_en(regmap, 0xc070); /* MDSS_1_DISP_CC_SLEEP_CLK */
+ qcom_branch_set_clk_en(regmap, 0xc054); /* MDSS_1_DISP_CC_XO_CLK */
+
+ ret = qcom_cc_really_probe(&pdev->dev, &disp_cc_1_sa8775p_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver disp_cc_1_sa8775p_driver = {
+ .probe = disp_cc_1_sa8775p_probe,
+ .driver = {
+ .name = "dispcc1-sa8775p",
+ .of_match_table = disp_cc_1_sa8775p_match_table,
+ },
+};
+
+module_platform_driver(disp_cc_1_sa8775p_driver);
+
+MODULE_DESCRIPTION("QTI DISPCC1 SA8775P Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gcc-ipq5332.c b/drivers/clk/qcom/gcc-ipq5332.c
index 9536b2b7d07c..9246e97d785a 100644
--- a/drivers/clk/qcom/gcc-ipq5332.c
+++ b/drivers/clk/qcom/gcc-ipq5332.c
@@ -2185,150 +2185,6 @@ static struct clk_branch gcc_prng_ahb_clk = {
},
};
-static struct clk_branch gcc_q6_ahb_clk = {
- .halt_reg = 0x25014,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x25014,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_ahb_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_wcss_ahb_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6_ahb_s_clk = {
- .halt_reg = 0x25018,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x25018,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_ahb_s_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_wcss_ahb_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6_axim_clk = {
- .halt_reg = 0x2500c,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x2500c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_axim_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_q6_axim_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6_axis_clk = {
- .halt_reg = 0x25010,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x25010,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_axis_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_system_noc_bfdcd_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6_tsctr_1to2_clk = {
- .halt_reg = 0x25020,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x25020,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_tsctr_1to2_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_tsctr_div2_clk_src.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6ss_atbm_clk = {
- .halt_reg = 0x2501c,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x2501c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6ss_atbm_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_at_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6ss_pclkdbg_clk = {
- .halt_reg = 0x25024,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x25024,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6ss_pclkdbg_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_dap_div_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6ss_trig_clk = {
- .halt_reg = 0x250a0,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x250a0,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6ss_trig_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_dap_div_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_qdss_at_clk = {
.halt_reg = 0x2d038,
.halt_check = BRANCH_HALT_VOTED,
@@ -2756,24 +2612,6 @@ static struct clk_branch gcc_sys_noc_at_clk = {
},
};
-static struct clk_branch gcc_sys_noc_wcss_ahb_clk = {
- .halt_reg = 0x2e030,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x2e030,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_sys_noc_wcss_ahb_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_wcss_ahb_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_uniphy0_ahb_clk = {
.halt_reg = 0x16010,
.halt_check = BRANCH_HALT,
@@ -2989,204 +2827,6 @@ static struct clk_branch gcc_usb0_sleep_clk = {
},
};
-static struct clk_branch gcc_wcss_axim_clk = {
- .halt_reg = 0x2505c,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x2505c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_axim_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_system_noc_bfdcd_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_axis_clk = {
- .halt_reg = 0x25060,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x25060,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_axis_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_system_noc_bfdcd_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_apb_bdg_clk = {
- .halt_reg = 0x25048,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x25048,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_apb_bdg_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_dap_div_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_apb_clk = {
- .halt_reg = 0x25038,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x25038,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_apb_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_dap_div_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_atb_bdg_clk = {
- .halt_reg = 0x2504c,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x2504c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_atb_bdg_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_at_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_atb_clk = {
- .halt_reg = 0x2503c,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x2503c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_atb_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_at_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_nts_bdg_clk = {
- .halt_reg = 0x25050,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x25050,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_nts_bdg_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_tsctr_div2_clk_src.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_nts_clk = {
- .halt_reg = 0x25040,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x25040,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_nts_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_qdss_tsctr_div2_clk_src.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_ecahb_clk = {
- .halt_reg = 0x25058,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x25058,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_ecahb_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_wcss_ahb_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_mst_async_bdg_clk = {
- .halt_reg = 0x2e0b0,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x2e0b0,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_mst_async_bdg_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_system_noc_bfdcd_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_slv_async_bdg_clk = {
- .halt_reg = 0x2e0b4,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x2e0b4,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_slv_async_bdg_clk",
- .parent_hws = (const struct clk_hw*[]) {
- &gcc_system_noc_bfdcd_clk_src.clkr.hw,
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_xo_clk = {
.halt_reg = 0x34018,
.halt_check = BRANCH_HALT,
@@ -3362,15 +3002,7 @@ static struct clk_regmap *gcc_ipq5332_clocks[] = {
[GCC_PCNOC_BFDCD_CLK_SRC] = &gcc_pcnoc_bfdcd_clk_src.clkr,
[GCC_PCNOC_LPASS_CLK] = &gcc_pcnoc_lpass_clk.clkr,
[GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
- [GCC_Q6_AHB_CLK] = &gcc_q6_ahb_clk.clkr,
- [GCC_Q6_AHB_S_CLK] = &gcc_q6_ahb_s_clk.clkr,
- [GCC_Q6_AXIM_CLK] = &gcc_q6_axim_clk.clkr,
[GCC_Q6_AXIM_CLK_SRC] = &gcc_q6_axim_clk_src.clkr,
- [GCC_Q6_AXIS_CLK] = &gcc_q6_axis_clk.clkr,
- [GCC_Q6_TSCTR_1TO2_CLK] = &gcc_q6_tsctr_1to2_clk.clkr,
- [GCC_Q6SS_ATBM_CLK] = &gcc_q6ss_atbm_clk.clkr,
- [GCC_Q6SS_PCLKDBG_CLK] = &gcc_q6ss_pclkdbg_clk.clkr,
- [GCC_Q6SS_TRIG_CLK] = &gcc_q6ss_trig_clk.clkr,
[GCC_QDSS_AT_CLK] = &gcc_qdss_at_clk.clkr,
[GCC_QDSS_AT_CLK_SRC] = &gcc_qdss_at_clk_src.clkr,
[GCC_QDSS_CFG_AHB_CLK] = &gcc_qdss_cfg_ahb_clk.clkr,
@@ -3400,7 +3032,6 @@ static struct clk_regmap *gcc_ipq5332_clocks[] = {
[GCC_SNOC_PCIE3_2LANE_S_CLK] = &gcc_snoc_pcie3_2lane_s_clk.clkr,
[GCC_SNOC_USB_CLK] = &gcc_snoc_usb_clk.clkr,
[GCC_SYS_NOC_AT_CLK] = &gcc_sys_noc_at_clk.clkr,
- [GCC_SYS_NOC_WCSS_AHB_CLK] = &gcc_sys_noc_wcss_ahb_clk.clkr,
[GCC_SYSTEM_NOC_BFDCD_CLK_SRC] = &gcc_system_noc_bfdcd_clk_src.clkr,
[GCC_UNIPHY0_AHB_CLK] = &gcc_uniphy0_ahb_clk.clkr,
[GCC_UNIPHY0_SYS_CLK] = &gcc_uniphy0_sys_clk.clkr,
@@ -3421,17 +3052,6 @@ static struct clk_regmap *gcc_ipq5332_clocks[] = {
[GCC_USB0_PIPE_CLK] = &gcc_usb0_pipe_clk.clkr,
[GCC_USB0_SLEEP_CLK] = &gcc_usb0_sleep_clk.clkr,
[GCC_WCSS_AHB_CLK_SRC] = &gcc_wcss_ahb_clk_src.clkr,
- [GCC_WCSS_AXIM_CLK] = &gcc_wcss_axim_clk.clkr,
- [GCC_WCSS_AXIS_CLK] = &gcc_wcss_axis_clk.clkr,
- [GCC_WCSS_DBG_IFC_APB_BDG_CLK] = &gcc_wcss_dbg_ifc_apb_bdg_clk.clkr,
- [GCC_WCSS_DBG_IFC_APB_CLK] = &gcc_wcss_dbg_ifc_apb_clk.clkr,
- [GCC_WCSS_DBG_IFC_ATB_BDG_CLK] = &gcc_wcss_dbg_ifc_atb_bdg_clk.clkr,
- [GCC_WCSS_DBG_IFC_ATB_CLK] = &gcc_wcss_dbg_ifc_atb_clk.clkr,
- [GCC_WCSS_DBG_IFC_NTS_BDG_CLK] = &gcc_wcss_dbg_ifc_nts_bdg_clk.clkr,
- [GCC_WCSS_DBG_IFC_NTS_CLK] = &gcc_wcss_dbg_ifc_nts_clk.clkr,
- [GCC_WCSS_ECAHB_CLK] = &gcc_wcss_ecahb_clk.clkr,
- [GCC_WCSS_MST_ASYNC_BDG_CLK] = &gcc_wcss_mst_async_bdg_clk.clkr,
- [GCC_WCSS_SLV_ASYNC_BDG_CLK] = &gcc_wcss_slv_async_bdg_clk.clkr,
[GCC_XO_CLK] = &gcc_xo_clk.clkr,
[GCC_XO_CLK_SRC] = &gcc_xo_clk_src.clkr,
[GCC_XO_DIV4_CLK] = &gcc_xo_div4_clk.clkr,
@@ -3622,7 +3242,7 @@ static const struct qcom_reset_map gcc_ipq5332_resets[] = {
#define IPQ_APPS_ID 5332 /* some unique value */
-static struct qcom_icc_hws_data icc_ipq5332_hws[] = {
+static const struct qcom_icc_hws_data icc_ipq5332_hws[] = {
{ MASTER_SNOC_PCIE3_1_M, SLAVE_SNOC_PCIE3_1_M, GCC_SNOC_PCIE3_1LANE_M_CLK },
{ MASTER_ANOC_PCIE3_1_S, SLAVE_ANOC_PCIE3_1_S, GCC_SNOC_PCIE3_1LANE_S_CLK },
{ MASTER_SNOC_PCIE3_2_M, SLAVE_SNOC_PCIE3_2_M, GCC_SNOC_PCIE3_2LANE_M_CLK },
diff --git a/drivers/clk/qcom/gcc-ipq5424.c b/drivers/clk/qcom/gcc-ipq5424.c
new file mode 100644
index 000000000000..88a7d5b2e751
--- /dev/null
+++ b/drivers/clk/qcom/gcc-ipq5424.c
@@ -0,0 +1,3291 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,ipq5424-gcc.h>
+#include <dt-bindings/reset/qcom,ipq5424-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 "common.h"
+#include "reset.h"
+
+enum {
+ DT_XO,
+ DT_SLEEP_CLK,
+ DT_PCIE30_PHY0_PIPE_CLK,
+ DT_PCIE30_PHY1_PIPE_CLK,
+ DT_PCIE30_PHY2_PIPE_CLK,
+ DT_PCIE30_PHY3_PIPE_CLK,
+ DT_USB_PCIE_WRAPPER_PIPE_CLK,
+};
+
+enum {
+ P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC,
+ P_GPLL0_OUT_AUX,
+ P_GPLL0_OUT_MAIN,
+ P_GPLL2_OUT_AUX,
+ P_GPLL2_OUT_MAIN,
+ P_GPLL4_OUT_AUX,
+ P_GPLL4_OUT_MAIN,
+ P_SLEEP_CLK,
+ P_XO,
+ P_USB3PHY_0_PIPE,
+};
+
+static const struct clk_parent_data gcc_parent_data_xo = { .index = DT_XO };
+
+static struct clk_alpha_pll gpll0 = {
+ .offset = 0x20000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO],
+ .clkr = {
+ .enable_reg = 0xb000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll0",
+ .parent_data = &gcc_parent_data_xo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll0_div2 = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll0_div2",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gpll0.clkr.hw
+ },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll2 = {
+ .offset = 0x21000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA],
+ .clkr = {
+ .enable_reg = 0xb000,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll2",
+ .parent_data = &gcc_parent_data_xo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_gpll2_out_main[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gpll2_out_main = {
+ .offset = 0x21000,
+ .post_div_table = post_div_table_gpll2_out_main,
+ .num_post_div = ARRAY_SIZE(post_div_table_gpll2_out_main),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpll2_out_main",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpll2.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ro_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll4 = {
+ .offset = 0x22000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO],
+ .clkr = {
+ .enable_reg = 0xb000,
+ .enable_mask = BIT(2),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpll4",
+ .parent_data = &gcc_parent_data_xo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ /*
+ * There are no consumers for this GPLL in kernel yet,
+ * (will be added soon), so the clock framework
+ * disables this source. But some of the clocks
+ * initialized by boot loaders uses this source. So we
+ * need to keep this clock ON. Add the
+ * CLK_IGNORE_UNUSED flag so the clock will not be
+ * disabled. Once the consumer in kernel is added, we
+ * can get rid of this flag.
+ */
+ .flags = CLK_IGNORE_UNUSED,
+ },
+ },
+};
+
+static const struct parent_map gcc_parent_map_xo[] = {
+ { P_XO, 0 },
+};
+
+static const struct parent_map gcc_parent_map_0[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 4 },
+};
+
+static const struct clk_parent_data gcc_parent_data_0[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_div2.hw },
+};
+
+static const struct parent_map gcc_parent_map_1[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data gcc_parent_data_1[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_2[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL4_OUT_MAIN, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_2[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_3[] = {
+ { P_XO, 0 },
+ { P_GPLL4_OUT_MAIN, 1 },
+ { P_GPLL0_OUT_AUX, 2 },
+ { P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 4 },
+};
+
+static const struct clk_parent_data gcc_parent_data_3[] = {
+ { .index = DT_XO },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_div2.hw },
+};
+
+static const struct parent_map gcc_parent_map_4[] = {
+ { P_XO, 0 },
+};
+
+static const struct clk_parent_data gcc_parent_data_4[] = {
+ { .index = DT_XO },
+};
+
+static const struct parent_map gcc_parent_map_5[] = {
+ { P_XO, 0 },
+ { P_GPLL4_OUT_AUX, 1 },
+ { P_GPLL0_OUT_MAIN, 3 },
+ { P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 4 },
+};
+
+static const struct clk_parent_data gcc_parent_data_5[] = {
+ { .index = DT_XO },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_div2.hw },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_SLEEP_CLK, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_6[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_7[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL0_OUT_AUX, 2 },
+ { P_SLEEP_CLK, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_7[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL2_OUT_MAIN, 2 },
+ { P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 4 },
+};
+
+static const struct clk_parent_data gcc_parent_data_8[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll2_out_main.clkr.hw },
+ { .hw = &gpll0_div2.hw },
+};
+
+static const struct parent_map gcc_parent_map_9[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL4_OUT_MAIN, 2 },
+ { P_GCC_GPLL0_OUT_MAIN_DIV_CLK_SRC, 4 },
+};
+
+static const struct clk_parent_data gcc_parent_data_9[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll0_div2.hw },
+};
+
+static const struct parent_map gcc_parent_map_10[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_AUX, 2 },
+ { P_SLEEP_CLK, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_10[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_11[] = {
+ { P_XO, 0 },
+ { P_GPLL0_OUT_MAIN, 1 },
+ { P_GPLL2_OUT_AUX, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_11[] = {
+ { .index = DT_XO },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+};
+
+static const struct freq_tbl ftbl_gcc_adss_pwm_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0_OUT_MAIN, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_adss_pwm_clk_src = {
+ .cmd_rcgr = 0x1c004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_adss_pwm_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_adss_pwm_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_nss_ts_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_xo_clk_src = {
+ .cmd_rcgr = 0x34004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo,
+ .freq_tbl = ftbl_gcc_nss_ts_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_xo_clk_src",
+ .parent_data = &gcc_parent_data_xo,
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_fixed_factor gcc_xo_div4_clk_src = {
+ .mult = 1,
+ .div = 4,
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_xo_div4_clk_src",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_xo_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_nss_ts_clk_src = {
+ .cmd_rcgr = 0x17088,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_nss_ts_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nss_ts_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie0_axi_m_clk_src[] = {
+ F(240000000, P_GPLL4_OUT_MAIN, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie0_axi_m_clk_src = {
+ .cmd_rcgr = 0x28018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie0_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_axi_m_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie0_axi_s_clk_src = {
+ .cmd_rcgr = 0x28020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie0_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_axi_s_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie1_axi_m_clk_src = {
+ .cmd_rcgr = 0x29018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie0_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_axi_m_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie1_axi_s_clk_src = {
+ .cmd_rcgr = 0x29020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie0_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_axi_s_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie2_axi_m_clk_src[] = {
+ F(266666667, P_GPLL4_OUT_MAIN, 4.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie2_axi_m_clk_src = {
+ .cmd_rcgr = 0x2a018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie2_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_axi_m_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie2_axi_s_clk_src = {
+ .cmd_rcgr = 0x2a020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie0_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_axi_s_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie3_axi_m_clk_src = {
+ .cmd_rcgr = 0x2b018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie2_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_axi_m_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie3_axi_s_clk_src = {
+ .cmd_rcgr = 0x2b020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie0_axi_m_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_axi_s_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_aux_clk_src[] = {
+ F(20000000, P_GPLL0_OUT_MAIN, 10, 1, 4),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie_aux_clk_src = {
+ .cmd_rcgr = 0x28004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_7,
+ .freq_tbl = ftbl_gcc_pcie_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_aux_clk_src",
+ .parent_data = gcc_parent_data_7,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_7),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_i2c0_clk_src[] = {
+ F(4800000, P_XO, 5, 0, 0),
+ F(9600000, P_XO, 2.5, 0, 0),
+ F(24000000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0_OUT_MAIN, 16, 0, 0),
+ F(64000000, P_GPLL0_OUT_MAIN, 12.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c0_clk_src = {
+ .cmd_rcgr = 0x2018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_i2c0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_i2c0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c1_clk_src = {
+ .cmd_rcgr = 0x3018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_i2c0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_i2c1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_spi0_clk_src[] = {
+ F(960000, P_XO, 10, 2, 5),
+ F(4800000, P_XO, 5, 0, 0),
+ F(9600000, P_XO, 2, 4, 5),
+ F(16000000, P_GPLL0_OUT_MAIN, 10, 1, 5),
+ F(24000000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_MAIN, 16, 1, 2),
+ F(32000000, P_GPLL0_OUT_MAIN, 10, 2, 5),
+ F(50000000, P_GPLL0_OUT_MAIN, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_qupv3_spi0_clk_src = {
+ .cmd_rcgr = 0x4004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_spi0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_spi0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_spi1_clk_src = {
+ .cmd_rcgr = 0x5004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_spi0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_spi1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_uart0_clk_src[] = {
+ F(960000, P_XO, 10, 2, 5),
+ F(4800000, P_XO, 5, 0, 0),
+ F(9600000, P_XO, 2, 4, 5),
+ F(16000000, P_GPLL0_OUT_MAIN, 10, 1, 5),
+ F(24000000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_MAIN, 16, 1, 2),
+ F(50000000, P_GPLL0_OUT_MAIN, 16, 0, 0),
+ F(64000000, P_GPLL0_OUT_MAIN, 12.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_qupv3_uart0_clk_src = {
+ .cmd_rcgr = 0x202c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_uart0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_uart0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_uart1_clk_src = {
+ .cmd_rcgr = 0x302c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_uart0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_uart1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+ F(144000, P_XO, 16, 12, 125),
+ F(400000, P_XO, 12, 1, 5),
+ F(24000000, P_XO, 1, 0, 0),
+ F(48000000, P_GPLL2_OUT_MAIN, 12, 1, 2),
+ F(96000000, P_GPLL2_OUT_MAIN, 6, 1, 2),
+ F(177777778, P_GPLL0_OUT_MAIN, 4.5, 0, 0),
+ F(192000000, P_GPLL2_OUT_MAIN, 6, 0, 0),
+ F(200000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x33004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_8,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk_src",
+ .parent_data = gcc_parent_data_8,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_8),
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = {
+ F(300000000, P_GPLL4_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x33018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_9,
+ .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk_src",
+ .parent_data = gcc_parent_data_9,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_9),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_uniphy_sys_clk_src = {
+ .cmd_rcgr = 0x17090,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_nss_ts_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_uniphy_sys_clk_src",
+ .parent_data = &gcc_parent_data_xo,
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb0_aux_clk_src = {
+ .cmd_rcgr = 0x2c018,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_10,
+ .freq_tbl = ftbl_gcc_nss_ts_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_aux_clk_src",
+ .parent_data = gcc_parent_data_10,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_10),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb0_master_clk_src[] = {
+ F(200000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb0_master_clk_src = {
+ .cmd_rcgr = 0x2c004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb0_master_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_master_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb0_mock_utmi_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL4_OUT_AUX, 10, 1, 2),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb0_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x2c02c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_usb0_mock_utmi_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_mock_utmi_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb1_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x3c004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_usb0_mock_utmi_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb1_mock_utmi_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_wcss_ahb_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
+ F(133333333, P_GPLL0_OUT_MAIN, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_wcss_ahb_clk_src = {
+ .cmd_rcgr = 0x25030,
+ .freq_tbl = ftbl_gcc_wcss_ahb_clk_src,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_wcss_ahb_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qdss_at_clk_src[] = {
+ F(240000000, P_GPLL4_OUT_MAIN, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_qdss_at_clk_src = {
+ .cmd_rcgr = 0x2d004,
+ .freq_tbl = ftbl_gcc_qdss_at_clk_src,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qdss_at_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qdss_tsctr_clk_src[] = {
+ F(600000000, P_GPLL4_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_qdss_tsctr_clk_src = {
+ .cmd_rcgr = 0x2d01c,
+ .freq_tbl = ftbl_gcc_qdss_tsctr_clk_src,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qdss_tsctr_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_fixed_factor gcc_qdss_tsctr_div2_clk_src = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qdss_tsctr_div2_clk_src",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_qdss_tsctr_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_fixed_factor gcc_qdss_dap_sync_clk_src = {
+ .mult = 1,
+ .div = 4,
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qdss_dap_sync_clk_src",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_qdss_tsctr_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_system_noc_bfdcd_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
+ F(133333333, P_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(200000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(266666667, P_GPLL4_OUT_MAIN, 4.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_system_noc_bfdcd_clk_src = {
+ .cmd_rcgr = 0x2e004,
+ .freq_tbl = ftbl_gcc_system_noc_bfdcd_clk_src,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_9,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_system_noc_bfdcd_clk_src",
+ .parent_data = gcc_parent_data_9,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_9),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcnoc_bfdcd_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0_OUT_MAIN, 16, 0, 0),
+ F(100000000, P_GPLL0_OUT_MAIN, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcnoc_bfdcd_clk_src = {
+ .cmd_rcgr = 0x31004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcnoc_bfdcd_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcnoc_bfdcd_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_lpass_sway_clk_src[] = {
+ F(133333333, P_GPLL0_OUT_MAIN, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_lpass_sway_clk_src = {
+ .cmd_rcgr = 0x27004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_lpass_sway_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_lpass_sway_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_lpass_axim_clk_src = {
+ .cmd_rcgr = 0x2700c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_lpass_sway_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_lpass_axim_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_fixed_factor gcc_eud_at_div_clk_src = {
+ .mult = 1,
+ .div = 6,
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_eud_at_div_clk_src",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_qdss_at_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sleep_clk_src = {
+ .cmd_rcgr = 0x3400c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sleep_clk_src",
+ .parent_data = gcc_parent_data_6,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_6),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qpic_io_macro_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0_OUT_MAIN, 8, 0, 0),
+ F(200000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(320000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
+ F(400000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_qpic_io_macro_clk_src = {
+ .cmd_rcgr = 0x32004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_11,
+ .freq_tbl = ftbl_gcc_qpic_io_macro_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qpic_io_macro_clk_src",
+ .parent_data = gcc_parent_data_11,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_11),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qpic_clk_src = {
+ .cmd_rcgr = 0x32020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_11,
+ .freq_tbl = ftbl_gcc_qpic_io_macro_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qpic_clk_src",
+ .parent_data = gcc_parent_data_11,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_11),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie0_rchng_clk_src = {
+ .cmd_rcgr = 0x28028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_adss_pwm_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_rchng_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie1_rchng_clk_src = {
+ .cmd_rcgr = 0x29028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_adss_pwm_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_rchng_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie2_rchng_clk_src = {
+ .cmd_rcgr = 0x2a028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_adss_pwm_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_rchng_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie3_rchng_clk_src = {
+ .cmd_rcgr = 0x2b028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_adss_pwm_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_rchng_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_qupv3_i2c0_div_clk_src = {
+ .reg = 0x2020,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_i2c0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_i2c0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_qupv3_i2c1_div_clk_src = {
+ .reg = 0x3020,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_i2c1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_i2c1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb0_mock_utmi_div_clk_src = {
+ .reg = 0x2c040,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_mock_utmi_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb0_mock_utmi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb1_mock_utmi_div_clk_src = {
+ .reg = 0x3c018,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb1_mock_utmi_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb1_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_adss_pwm_clk = {
+ .halt_reg = 0x1c00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1c00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_adss_pwm_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_adss_pwm_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_apss_dbg_clk = {
+ .halt_reg = 0x2402c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2402c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_apss_dbg_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qdss_dap_sync_clk_src.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cnoc_pcie0_1lane_s_clk = {
+ .halt_reg = 0x31088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x31088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cnoc_pcie0_1lane_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie0_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cnoc_pcie1_1lane_s_clk = {
+ .halt_reg = 0x3108c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3108c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cnoc_pcie1_1lane_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie1_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cnoc_pcie2_2lane_s_clk = {
+ .halt_reg = 0x31090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x31090,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cnoc_pcie2_2lane_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie2_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cnoc_pcie3_2lane_s_clk = {
+ .halt_reg = 0x31094,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x31094,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cnoc_pcie3_2lane_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie3_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cnoc_usb_clk = {
+ .halt_reg = 0x310a8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x310a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cnoc_usb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb0_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mdio_ahb_clk = {
+ .halt_reg = 0x17040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_mdio_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nss_ts_clk = {
+ .halt_reg = 0x17018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x17018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nss_ts_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_nss_ts_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nsscc_clk = {
+ .halt_reg = 0x17034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nsscc_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nsscfg_clk = {
+ .halt_reg = 0x1702c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1702c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nsscfg_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_atb_clk = {
+ .halt_reg = 0x17014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_atb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qdss_at_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_nsscc_clk = {
+ .halt_reg = 0x17030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_nsscc_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_pcnoc_1_clk = {
+ .halt_reg = 0x17080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_pcnoc_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_qosgen_ref_clk = {
+ .halt_reg = 0x1701c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1701c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_qosgen_ref_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_xo_div4_clk_src.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_snoc_1_clk = {
+ .halt_reg = 0x1707c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1707c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_snoc_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_system_noc_bfdcd_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_snoc_clk = {
+ .halt_reg = 0x17028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_snoc_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_system_noc_bfdcd_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_timeout_ref_clk = {
+ .halt_reg = 0x17020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_timeout_ref_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_xo_div4_clk_src.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_nssnoc_xo_dcd_clk = {
+ .halt_reg = 0x17074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x17074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_nssnoc_xo_dcd_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie0_ahb_clk = {
+ .halt_reg = 0x28030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie0_aux_clk = {
+ .halt_reg = 0x28070,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28070,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie0_axi_m_clk = {
+ .halt_reg = 0x28038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_axi_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie0_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_anoc_pcie0_1lane_m_clk = {
+ .halt_reg = 0x2e07c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2e07c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_anoc_pcie0_1lane_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie0_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie0_axi_s_bridge_clk = {
+ .halt_reg = 0x28048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_axi_s_bridge_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie0_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie0_axi_s_clk = {
+ .halt_reg = 0x28040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_axi_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie0_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie0_pipe_clk_src = {
+ .reg = 0x28064,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "pcie0_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE30_PHY0_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie0_pipe_clk = {
+ .halt_reg = 0x28068,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x28068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_pipe_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie0_pipe_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie1_ahb_clk = {
+ .halt_reg = 0x29030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie1_aux_clk = {
+ .halt_reg = 0x29074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie1_axi_m_clk = {
+ .halt_reg = 0x29038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_axi_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie1_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_anoc_pcie1_1lane_m_clk = {
+ .halt_reg = 0x2e084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2e084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_anoc_pcie1_1lane_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie1_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie1_axi_s_bridge_clk = {
+ .halt_reg = 0x29048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_axi_s_bridge_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie1_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie1_axi_s_clk = {
+ .halt_reg = 0x29040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_axi_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie1_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie1_pipe_clk_src = {
+ .reg = 0x29064,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "pcie1_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE30_PHY1_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie1_pipe_clk = {
+ .halt_reg = 0x29068,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x29068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_pipe_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie1_pipe_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie2_ahb_clk = {
+ .halt_reg = 0x2a030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie2_aux_clk = {
+ .halt_reg = 0x2a078,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie2_axi_m_clk = {
+ .halt_reg = 0x2a038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_axi_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie2_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_anoc_pcie2_2lane_m_clk = {
+ .halt_reg = 0x2e080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2e080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_anoc_pcie2_2lane_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie2_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie2_axi_s_bridge_clk = {
+ .halt_reg = 0x2a048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_axi_s_bridge_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie2_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie2_axi_s_clk = {
+ .halt_reg = 0x2a040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_axi_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie2_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie2_pipe_clk_src = {
+ .reg = 0x2a064,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "pcie2_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE30_PHY2_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie2_pipe_clk = {
+ .halt_reg = 0x2a068,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x2a068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_pipe_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie2_pipe_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie3_ahb_clk = {
+ .halt_reg = 0x2b030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2b030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie3_aux_clk = {
+ .halt_reg = 0x2b07c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2b07c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie3_axi_m_clk = {
+ .halt_reg = 0x2b038,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2b038,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_axi_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie3_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_anoc_pcie3_2lane_m_clk = {
+ .halt_reg = 0x2e090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2e090,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_anoc_pcie3_2lane_m_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie3_axi_m_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie3_axi_s_bridge_clk = {
+ .halt_reg = 0x2b048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2b048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_axi_s_bridge_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie3_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie3_axi_s_clk = {
+ .halt_reg = 0x2b040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2b040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_axi_s_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie3_axi_s_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie3_pipe_clk_src = {
+ .reg = 0x2b064,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "pcie3_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE30_PHY3_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie3_pipe_clk = {
+ .halt_reg = 0x2b068,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x2b068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_pipe_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie3_pipe_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x13024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0xb004,
+ .enable_mask = BIT(10),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_prng_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_ahb_mst_clk = {
+ .halt_reg = 0x1014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0xb004,
+ .enable_mask = BIT(14),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_ahb_mst_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_ahb_slv_clk = {
+ .halt_reg = 0x102c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0xb004,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_ahb_slv_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c0_clk = {
+ .halt_reg = 0x2024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_i2c0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_i2c0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c1_clk = {
+ .halt_reg = 0x3024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_i2c1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_i2c1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_spi0_clk = {
+ .halt_reg = 0x4020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_spi0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_spi0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_spi1_clk = {
+ .halt_reg = 0x5020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_spi1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_spi1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_uart0_clk = {
+ .halt_reg = 0x2040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_uart0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_uart0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_uart1_clk = {
+ .halt_reg = 0x3040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_uart1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_uart1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x3303c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3303c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x3302c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3302c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x33034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x33034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_uniphy0_ahb_clk = {
+ .halt_reg = 0x1704c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1704c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_uniphy0_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_uniphy0_sys_clk = {
+ .halt_reg = 0x17048,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x17048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_uniphy0_sys_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_uniphy_sys_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_uniphy1_ahb_clk = {
+ .halt_reg = 0x1705c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1705c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_uniphy1_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_uniphy1_sys_clk = {
+ .halt_reg = 0x17058,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x17058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_uniphy1_sys_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_uniphy_sys_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_uniphy2_ahb_clk = {
+ .halt_reg = 0x1706c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1706c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_uniphy2_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_uniphy2_sys_clk = {
+ .halt_reg = 0x17068,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x17068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_uniphy2_sys_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_uniphy_sys_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb0_aux_clk = {
+ .halt_reg = 0x2c04c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2c04c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb0_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb0_master_clk = {
+ .halt_reg = 0x2c044,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2c044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_master_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb0_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb0_mock_utmi_clk = {
+ .halt_reg = 0x2c050,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2c050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb0_mock_utmi_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb1_mock_utmi_clk = {
+ .halt_reg = 0x3c024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x3c024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb1_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb1_mock_utmi_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb0_phy_cfg_ahb_clk = {
+ .halt_reg = 0x2c05c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2c05c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_phy_cfg_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb1_phy_cfg_ahb_clk = {
+ .halt_reg = 0x3c01c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x3c01c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb1_phy_cfg_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb1_master_clk = {
+ .halt_reg = 0x3c028,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x3c028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb1_master_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_usb0_pipe_clk_src = {
+ .reg = 0x2c074,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_USB_PCIE_WRAPPER_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb0_pipe_clk = {
+ .halt_reg = 0x2c054,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x2c054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_pipe_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_usb0_pipe_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb0_sleep_clk = {
+ .halt_reg = 0x2c058,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2c058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_sleep_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sleep_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb1_sleep_clk = {
+ .halt_reg = 0x3c020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x3c020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb1_sleep_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sleep_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cmn_12gpll_ahb_clk = {
+ .halt_reg = 0x3a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cmn_12gpll_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cmn_12gpll_sys_clk = {
+ .halt_reg = 0x3a008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3a008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cmn_12gpll_sys_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_uniphy_sys_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_lpass_sway_clk = {
+ .halt_reg = 0x27014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_lpass_sway_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_lpass_sway_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cnoc_lpass_cfg_clk = {
+ .halt_reg = 0x2e028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2e028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cnoc_lpass_cfg_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_lpass_sway_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_lpass_core_axim_clk = {
+ .halt_reg = 0x27018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x27018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_lpass_core_axim_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_lpass_axim_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_snoc_lpass_clk = {
+ .halt_reg = 0x31020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x31020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_snoc_lpass_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_lpass_axim_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb0_eud_at_clk = {
+ .halt_reg = 0x30004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x30004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb0_eud_at_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_eud_at_div_clk_src.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qpic_ahb_clk = {
+ .halt_reg = 0x32010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x32010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qpic_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcnoc_bfdcd_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qpic_clk = {
+ .halt_reg = 0x32028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x32028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qpic_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qpic_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qpic_io_macro_clk = {
+ .halt_reg = 0x3200c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qpic_io_macro_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qpic_io_macro_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qdss_dap_clk = {
+ .halt_reg = 0x2d058,
+ .clkr = {
+ .enable_reg = 0x2d058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qdss_dap_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_qdss_dap_sync_clk_src.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qdss_at_clk = {
+ .halt_reg = 0x2d034,
+ .clkr = {
+ .enable_reg = 0x2d034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qdss_at_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_qdss_at_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie0_rchng_clk = {
+ .halt_reg = 0x28028,
+ .clkr = {
+ .enable_reg = 0x28028,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie0_rchng_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie0_rchng_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie1_rchng_clk = {
+ .halt_reg = 0x29028,
+ .clkr = {
+ .enable_reg = 0x29028,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie1_rchng_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie1_rchng_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie2_rchng_clk = {
+ .halt_reg = 0x2a028,
+ .clkr = {
+ .enable_reg = 0x2a028,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie2_rchng_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie2_rchng_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie3_rchng_clk = {
+ .halt_reg = 0x2b028,
+ .clkr = {
+ .enable_reg = 0x2b028,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie3_rchng_clk",
+ .parent_hws = (const struct clk_hw *[]) {
+ &gcc_pcie3_rchng_clk_src.clkr.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap *gcc_ipq5424_clocks[] = {
+ [GCC_ADSS_PWM_CLK] = &gcc_adss_pwm_clk.clkr,
+ [GCC_ADSS_PWM_CLK_SRC] = &gcc_adss_pwm_clk_src.clkr,
+ [GCC_APSS_DBG_CLK] = &gcc_apss_dbg_clk.clkr,
+ [GCC_CNOC_PCIE0_1LANE_S_CLK] = &gcc_cnoc_pcie0_1lane_s_clk.clkr,
+ [GCC_CNOC_PCIE1_1LANE_S_CLK] = &gcc_cnoc_pcie1_1lane_s_clk.clkr,
+ [GCC_CNOC_PCIE2_2LANE_S_CLK] = &gcc_cnoc_pcie2_2lane_s_clk.clkr,
+ [GCC_CNOC_PCIE3_2LANE_S_CLK] = &gcc_cnoc_pcie3_2lane_s_clk.clkr,
+ [GCC_CNOC_USB_CLK] = &gcc_cnoc_usb_clk.clkr,
+ [GCC_MDIO_AHB_CLK] = &gcc_mdio_ahb_clk.clkr,
+ [GCC_NSS_TS_CLK] = &gcc_nss_ts_clk.clkr,
+ [GCC_NSS_TS_CLK_SRC] = &gcc_nss_ts_clk_src.clkr,
+ [GCC_NSSCC_CLK] = &gcc_nsscc_clk.clkr,
+ [GCC_NSSCFG_CLK] = &gcc_nsscfg_clk.clkr,
+ [GCC_NSSNOC_ATB_CLK] = &gcc_nssnoc_atb_clk.clkr,
+ [GCC_NSSNOC_NSSCC_CLK] = &gcc_nssnoc_nsscc_clk.clkr,
+ [GCC_NSSNOC_PCNOC_1_CLK] = &gcc_nssnoc_pcnoc_1_clk.clkr,
+ [GCC_NSSNOC_QOSGEN_REF_CLK] = &gcc_nssnoc_qosgen_ref_clk.clkr,
+ [GCC_NSSNOC_SNOC_1_CLK] = &gcc_nssnoc_snoc_1_clk.clkr,
+ [GCC_NSSNOC_SNOC_CLK] = &gcc_nssnoc_snoc_clk.clkr,
+ [GCC_NSSNOC_TIMEOUT_REF_CLK] = &gcc_nssnoc_timeout_ref_clk.clkr,
+ [GCC_NSSNOC_XO_DCD_CLK] = &gcc_nssnoc_xo_dcd_clk.clkr,
+ [GCC_PCIE0_AHB_CLK] = &gcc_pcie0_ahb_clk.clkr,
+ [GCC_PCIE0_AUX_CLK] = &gcc_pcie0_aux_clk.clkr,
+ [GCC_PCIE0_AXI_M_CLK] = &gcc_pcie0_axi_m_clk.clkr,
+ [GCC_PCIE0_AXI_M_CLK_SRC] = &gcc_pcie0_axi_m_clk_src.clkr,
+ [GCC_PCIE0_AXI_S_BRIDGE_CLK] = &gcc_pcie0_axi_s_bridge_clk.clkr,
+ [GCC_PCIE0_AXI_S_CLK] = &gcc_pcie0_axi_s_clk.clkr,
+ [GCC_PCIE0_AXI_S_CLK_SRC] = &gcc_pcie0_axi_s_clk_src.clkr,
+ [GCC_PCIE0_PIPE_CLK] = &gcc_pcie0_pipe_clk.clkr,
+ [GCC_ANOC_PCIE0_1LANE_M_CLK] = &gcc_anoc_pcie0_1lane_m_clk.clkr,
+ [GCC_PCIE0_PIPE_CLK_SRC] = &gcc_pcie0_pipe_clk_src.clkr,
+ [GCC_PCIE0_RCHNG_CLK_SRC] = &gcc_pcie0_rchng_clk_src.clkr,
+ [GCC_PCIE0_RCHNG_CLK] = &gcc_pcie0_rchng_clk.clkr,
+ [GCC_PCIE1_AHB_CLK] = &gcc_pcie1_ahb_clk.clkr,
+ [GCC_PCIE1_AUX_CLK] = &gcc_pcie1_aux_clk.clkr,
+ [GCC_PCIE1_AXI_M_CLK] = &gcc_pcie1_axi_m_clk.clkr,
+ [GCC_PCIE1_AXI_M_CLK_SRC] = &gcc_pcie1_axi_m_clk_src.clkr,
+ [GCC_PCIE1_AXI_S_BRIDGE_CLK] = &gcc_pcie1_axi_s_bridge_clk.clkr,
+ [GCC_PCIE1_AXI_S_CLK] = &gcc_pcie1_axi_s_clk.clkr,
+ [GCC_PCIE1_AXI_S_CLK_SRC] = &gcc_pcie1_axi_s_clk_src.clkr,
+ [GCC_PCIE1_PIPE_CLK] = &gcc_pcie1_pipe_clk.clkr,
+ [GCC_ANOC_PCIE1_1LANE_M_CLK] = &gcc_anoc_pcie1_1lane_m_clk.clkr,
+ [GCC_PCIE1_PIPE_CLK_SRC] = &gcc_pcie1_pipe_clk_src.clkr,
+ [GCC_PCIE1_RCHNG_CLK_SRC] = &gcc_pcie1_rchng_clk_src.clkr,
+ [GCC_PCIE1_RCHNG_CLK] = &gcc_pcie1_rchng_clk.clkr,
+ [GCC_PCIE2_AHB_CLK] = &gcc_pcie2_ahb_clk.clkr,
+ [GCC_PCIE2_AUX_CLK] = &gcc_pcie2_aux_clk.clkr,
+ [GCC_PCIE2_AXI_M_CLK] = &gcc_pcie2_axi_m_clk.clkr,
+ [GCC_PCIE2_AXI_M_CLK_SRC] = &gcc_pcie2_axi_m_clk_src.clkr,
+ [GCC_PCIE2_AXI_S_BRIDGE_CLK] = &gcc_pcie2_axi_s_bridge_clk.clkr,
+ [GCC_PCIE2_AXI_S_CLK] = &gcc_pcie2_axi_s_clk.clkr,
+ [GCC_PCIE2_AXI_S_CLK_SRC] = &gcc_pcie2_axi_s_clk_src.clkr,
+ [GCC_PCIE2_PIPE_CLK] = &gcc_pcie2_pipe_clk.clkr,
+ [GCC_ANOC_PCIE2_2LANE_M_CLK] = &gcc_anoc_pcie2_2lane_m_clk.clkr,
+ [GCC_PCIE2_PIPE_CLK_SRC] = &gcc_pcie2_pipe_clk_src.clkr,
+ [GCC_PCIE2_RCHNG_CLK_SRC] = &gcc_pcie2_rchng_clk_src.clkr,
+ [GCC_PCIE2_RCHNG_CLK] = &gcc_pcie2_rchng_clk.clkr,
+ [GCC_PCIE3_AHB_CLK] = &gcc_pcie3_ahb_clk.clkr,
+ [GCC_PCIE3_AUX_CLK] = &gcc_pcie3_aux_clk.clkr,
+ [GCC_PCIE3_AXI_M_CLK] = &gcc_pcie3_axi_m_clk.clkr,
+ [GCC_PCIE3_AXI_M_CLK_SRC] = &gcc_pcie3_axi_m_clk_src.clkr,
+ [GCC_PCIE3_AXI_S_BRIDGE_CLK] = &gcc_pcie3_axi_s_bridge_clk.clkr,
+ [GCC_PCIE3_AXI_S_CLK] = &gcc_pcie3_axi_s_clk.clkr,
+ [GCC_PCIE3_AXI_S_CLK_SRC] = &gcc_pcie3_axi_s_clk_src.clkr,
+ [GCC_PCIE3_PIPE_CLK] = &gcc_pcie3_pipe_clk.clkr,
+ [GCC_ANOC_PCIE3_2LANE_M_CLK] = &gcc_anoc_pcie3_2lane_m_clk.clkr,
+ [GCC_PCIE3_PIPE_CLK_SRC] = &gcc_pcie3_pipe_clk_src.clkr,
+ [GCC_PCIE3_RCHNG_CLK_SRC] = &gcc_pcie3_rchng_clk_src.clkr,
+ [GCC_PCIE3_RCHNG_CLK] = &gcc_pcie3_rchng_clk.clkr,
+ [GCC_PCIE_AUX_CLK_SRC] = &gcc_pcie_aux_clk_src.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_QUPV3_AHB_MST_CLK] = &gcc_qupv3_ahb_mst_clk.clkr,
+ [GCC_QUPV3_AHB_SLV_CLK] = &gcc_qupv3_ahb_slv_clk.clkr,
+ [GCC_QUPV3_I2C0_CLK] = &gcc_qupv3_i2c0_clk.clkr,
+ [GCC_QUPV3_I2C0_CLK_SRC] = &gcc_qupv3_i2c0_clk_src.clkr,
+ [GCC_QUPV3_I2C0_DIV_CLK_SRC] = &gcc_qupv3_i2c0_div_clk_src.clkr,
+ [GCC_QUPV3_I2C1_CLK] = &gcc_qupv3_i2c1_clk.clkr,
+ [GCC_QUPV3_I2C1_CLK_SRC] = &gcc_qupv3_i2c1_clk_src.clkr,
+ [GCC_QUPV3_I2C1_DIV_CLK_SRC] = &gcc_qupv3_i2c1_div_clk_src.clkr,
+ [GCC_QUPV3_SPI0_CLK] = &gcc_qupv3_spi0_clk.clkr,
+ [GCC_QUPV3_SPI0_CLK_SRC] = &gcc_qupv3_spi0_clk_src.clkr,
+ [GCC_QUPV3_SPI1_CLK] = &gcc_qupv3_spi1_clk.clkr,
+ [GCC_QUPV3_SPI1_CLK_SRC] = &gcc_qupv3_spi1_clk_src.clkr,
+ [GCC_QUPV3_UART0_CLK] = &gcc_qupv3_uart0_clk.clkr,
+ [GCC_QUPV3_UART0_CLK_SRC] = &gcc_qupv3_uart0_clk_src.clkr,
+ [GCC_QUPV3_UART1_CLK] = &gcc_qupv3_uart1_clk.clkr,
+ [GCC_QUPV3_UART1_CLK_SRC] = &gcc_qupv3_uart1_clk_src.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr,
+ [GCC_UNIPHY0_AHB_CLK] = &gcc_uniphy0_ahb_clk.clkr,
+ [GCC_UNIPHY0_SYS_CLK] = &gcc_uniphy0_sys_clk.clkr,
+ [GCC_UNIPHY1_AHB_CLK] = &gcc_uniphy1_ahb_clk.clkr,
+ [GCC_UNIPHY1_SYS_CLK] = &gcc_uniphy1_sys_clk.clkr,
+ [GCC_UNIPHY2_AHB_CLK] = &gcc_uniphy2_ahb_clk.clkr,
+ [GCC_UNIPHY2_SYS_CLK] = &gcc_uniphy2_sys_clk.clkr,
+ [GCC_UNIPHY_SYS_CLK_SRC] = &gcc_uniphy_sys_clk_src.clkr,
+ [GCC_USB0_AUX_CLK] = &gcc_usb0_aux_clk.clkr,
+ [GCC_USB0_AUX_CLK_SRC] = &gcc_usb0_aux_clk_src.clkr,
+ [GCC_USB0_MASTER_CLK] = &gcc_usb0_master_clk.clkr,
+ [GCC_USB0_MASTER_CLK_SRC] = &gcc_usb0_master_clk_src.clkr,
+ [GCC_USB0_MOCK_UTMI_CLK] = &gcc_usb0_mock_utmi_clk.clkr,
+ [GCC_USB0_MOCK_UTMI_CLK_SRC] = &gcc_usb0_mock_utmi_clk_src.clkr,
+ [GCC_USB0_MOCK_UTMI_DIV_CLK_SRC] = &gcc_usb0_mock_utmi_div_clk_src.clkr,
+ [GCC_USB0_EUD_AT_CLK] = &gcc_usb0_eud_at_clk.clkr,
+ [GCC_USB0_PIPE_CLK_SRC] = &gcc_usb0_pipe_clk_src.clkr,
+ [GCC_USB1_MOCK_UTMI_CLK] = &gcc_usb1_mock_utmi_clk.clkr,
+ [GCC_USB1_MOCK_UTMI_CLK_SRC] = &gcc_usb1_mock_utmi_clk_src.clkr,
+ [GCC_USB1_MOCK_UTMI_DIV_CLK_SRC] = &gcc_usb1_mock_utmi_div_clk_src.clkr,
+ [GCC_USB0_PHY_CFG_AHB_CLK] = &gcc_usb0_phy_cfg_ahb_clk.clkr,
+ [GCC_USB1_PHY_CFG_AHB_CLK] = &gcc_usb1_phy_cfg_ahb_clk.clkr,
+ [GCC_USB0_PIPE_CLK] = &gcc_usb0_pipe_clk.clkr,
+ [GCC_USB0_SLEEP_CLK] = &gcc_usb0_sleep_clk.clkr,
+ [GCC_USB1_SLEEP_CLK] = &gcc_usb1_sleep_clk.clkr,
+ [GCC_USB1_MASTER_CLK] = &gcc_usb1_master_clk.clkr,
+ [GCC_WCSS_AHB_CLK_SRC] = &gcc_wcss_ahb_clk_src.clkr,
+ [GCC_CMN_12GPLL_AHB_CLK] = &gcc_cmn_12gpll_ahb_clk.clkr,
+ [GCC_CMN_12GPLL_SYS_CLK] = &gcc_cmn_12gpll_sys_clk.clkr,
+ [GCC_LPASS_SWAY_CLK] = &gcc_lpass_sway_clk.clkr,
+ [GCC_CNOC_LPASS_CFG_CLK] = &gcc_cnoc_lpass_cfg_clk.clkr,
+ [GCC_LPASS_CORE_AXIM_CLK] = &gcc_lpass_core_axim_clk.clkr,
+ [GCC_SNOC_LPASS_CLK] = &gcc_snoc_lpass_clk.clkr,
+ [GCC_QDSS_AT_CLK_SRC] = &gcc_qdss_at_clk_src.clkr,
+ [GCC_QDSS_TSCTR_CLK_SRC] = &gcc_qdss_tsctr_clk_src.clkr,
+ [GCC_SYSTEM_NOC_BFDCD_CLK_SRC] = &gcc_system_noc_bfdcd_clk_src.clkr,
+ [GCC_PCNOC_BFDCD_CLK_SRC] = &gcc_pcnoc_bfdcd_clk_src.clkr,
+ [GCC_LPASS_SWAY_CLK_SRC] = &gcc_lpass_sway_clk_src.clkr,
+ [GCC_LPASS_AXIM_CLK_SRC] = &gcc_lpass_axim_clk_src.clkr,
+ [GCC_SLEEP_CLK_SRC] = &gcc_sleep_clk_src.clkr,
+ [GCC_QPIC_IO_MACRO_CLK] = &gcc_qpic_io_macro_clk.clkr,
+ [GCC_QPIC_IO_MACRO_CLK_SRC] = &gcc_qpic_io_macro_clk_src.clkr,
+ [GCC_QPIC_CLK] = &gcc_qpic_clk.clkr,
+ [GCC_QPIC_CLK_SRC] = &gcc_qpic_clk_src.clkr,
+ [GCC_QPIC_AHB_CLK] = &gcc_qpic_ahb_clk.clkr,
+ [GCC_XO_CLK_SRC] = &gcc_xo_clk_src.clkr,
+ [GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr,
+ [GCC_QDSS_AT_CLK] = &gcc_qdss_at_clk.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL2] = &gpll2.clkr,
+ [GPLL2_OUT_MAIN] = &gpll2_out_main.clkr,
+ [GPLL4] = &gpll4.clkr,
+};
+
+static const struct qcom_reset_map gcc_ipq5424_resets[] = {
+ [GCC_QUPV3_BCR] = { 0x01000, 0 },
+ [GCC_QUPV3_I2C0_BCR] = { 0x02000, 0 },
+ [GCC_QUPV3_UART0_BCR] = { 0x02020, 0 },
+ [GCC_QUPV3_I2C1_BCR] = { 0x03000, 0 },
+ [GCC_QUPV3_UART1_BCR] = { 0x03028, 0 },
+ [GCC_QUPV3_SPI0_BCR] = { 0x04000, 0 },
+ [GCC_QUPV3_SPI1_BCR] = { 0x05000, 0 },
+ [GCC_IMEM_BCR] = { 0x0e000, 0 },
+ [GCC_TME_BCR] = { 0x100000, 0 },
+ [GCC_DDRSS_BCR] = { 0x11000, 0 },
+ [GCC_PRNG_BCR] = { 0x13020, 0 },
+ [GCC_BOOT_ROM_BCR] = { 0x13028, 0 },
+ [GCC_NSS_BCR] = { 0x17000, 0 },
+ [GCC_MDIO_BCR] = { 0x1703c, 0 },
+ [GCC_UNIPHY0_BCR] = { 0x17044, 0 },
+ [GCC_UNIPHY1_BCR] = { 0x17054, 0 },
+ [GCC_UNIPHY2_BCR] = { 0x17064, 0 },
+ [GCC_WCSS_BCR] = { 0x18004, 0 },
+ [GCC_SEC_CTRL_BCR] = { 0x1a000, 0 },
+ [GCC_TME_SEC_BUS_BCR] = { 0xa1030, 0 },
+ [GCC_ADSS_BCR] = { 0x1c000, 0 },
+ [GCC_LPASS_BCR] = { 0x27000, 0 },
+ [GCC_PCIE0_BCR] = { 0x28000, 0 },
+ [GCC_PCIE0_LINK_DOWN_BCR] = { 0x28054, 0 },
+ [GCC_PCIE0PHY_PHY_BCR] = { 0x2805c, 0 },
+ [GCC_PCIE0_PHY_BCR] = { 0x28060, 0 },
+ [GCC_PCIE1_BCR] = { 0x29000, 0 },
+ [GCC_PCIE1_LINK_DOWN_BCR] = { 0x29054, 0 },
+ [GCC_PCIE1PHY_PHY_BCR] = { 0x2905c, 0 },
+ [GCC_PCIE1_PHY_BCR] = { 0x29060, 0 },
+ [GCC_PCIE2_BCR] = { 0x2a000, 0 },
+ [GCC_PCIE2_LINK_DOWN_BCR] = { 0x2a054, 0 },
+ [GCC_PCIE2PHY_PHY_BCR] = { 0x2a05c, 0 },
+ [GCC_PCIE2_PHY_BCR] = { 0x2a060, 0 },
+ [GCC_PCIE3_BCR] = { 0x2b000, 0 },
+ [GCC_PCIE3_LINK_DOWN_BCR] = { 0x2b054, 0 },
+ [GCC_PCIE3PHY_PHY_BCR] = { 0x2b05c, 0 },
+ [GCC_PCIE3_PHY_BCR] = { 0x2b060, 0 },
+ [GCC_USB_BCR] = { 0x2c000, 0 },
+ [GCC_QUSB2_0_PHY_BCR] = { 0x2c068, 0 },
+ [GCC_USB0_PHY_BCR] = { 0x2c06c, 0 },
+ [GCC_USB3PHY_0_PHY_BCR] = { 0x2c070, 0 },
+ [GCC_QDSS_BCR] = { 0x2d000, 0 },
+ [GCC_SNOC_BCR] = { 0x2e000, 0 },
+ [GCC_ANOC_BCR] = { 0x2e074, 0 },
+ [GCC_PCNOC_BCR] = { 0x31000, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT0_BCR] = { 0x31030, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT1_BCR] = { 0x31038, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT2_BCR] = { 0x31040, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT3_BCR] = { 0x31048, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT4_BCR] = { 0x31050, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT5_BCR] = { 0x31058, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT6_BCR] = { 0x31060, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT7_BCR] = { 0x31068, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT8_BCR] = { 0x31070, 0 },
+ [GCC_PCNOC_BUS_TIMEOUT9_BCR] = { 0x31078, 0 },
+ [GCC_QPIC_BCR] = { 0x32000, 0 },
+ [GCC_SDCC_BCR] = { 0x33000, 0 },
+ [GCC_DCC_BCR] = { 0x35000, 0 },
+ [GCC_SPDM_BCR] = { 0x36000, 0 },
+ [GCC_MPM_BCR] = { 0x37000, 0 },
+ [GCC_APC0_VOLTAGE_DROOP_DETECTOR_BCR] = { 0x38000, 0 },
+ [GCC_RBCPR_BCR] = { 0x39000, 0 },
+ [GCC_CMN_BLK_BCR] = { 0x3a000, 0 },
+ [GCC_TCSR_BCR] = { 0x3d000, 0 },
+ [GCC_TLMM_BCR] = { 0x3e000, 0 },
+ [GCC_QUPV3_AHB_MST_ARES] = { 0x01014, 2 },
+ [GCC_QUPV3_CORE_ARES] = { 0x01018, 2 },
+ [GCC_QUPV3_2X_CORE_ARES] = { 0x01020, 2 },
+ [GCC_QUPV3_SLEEP_ARES] = { 0x01028, 2 },
+ [GCC_QUPV3_AHB_SLV_ARES] = { 0x0102c, 2 },
+ [GCC_QUPV3_I2C0_ARES] = { 0x02024, 2 },
+ [GCC_QUPV3_UART0_ARES] = { 0x02040, 2 },
+ [GCC_QUPV3_I2C1_ARES] = { 0x03024, 2 },
+ [GCC_QUPV3_UART1_ARES] = { 0x03040, 2 },
+ [GCC_QUPV3_SPI0_ARES] = { 0x04020, 2 },
+ [GCC_QUPV3_SPI1_ARES] = { 0x05020, 2 },
+ [GCC_DEBUG_ARES] = { 0x06068, 2 },
+ [GCC_GP1_ARES] = { 0x08018, 2 },
+ [GCC_GP2_ARES] = { 0x09018, 2 },
+ [GCC_GP3_ARES] = { 0x0a018, 2 },
+ [GCC_IMEM_AXI_ARES] = { 0x0e004, 2 },
+ [GCC_IMEM_CFG_AHB_ARES] = { 0x0e00c, 2 },
+ [GCC_TME_ARES] = { 0x100b4, 2 },
+ [GCC_TME_TS_ARES] = { 0x100c0, 2 },
+ [GCC_TME_SLOW_ARES] = { 0x100d0, 2 },
+ [GCC_TME_RTC_TOGGLE_ARES] = { 0x100d8, 2 },
+ [GCC_TIC_ARES] = { 0x12004, 2 },
+ [GCC_PRNG_AHB_ARES] = { 0x13024, 2 },
+ [GCC_BOOT_ROM_AHB_ARES] = { 0x1302c, 2 },
+ [GCC_NSSNOC_ATB_ARES] = { 0x17014, 2 },
+ [GCC_NSS_TS_ARES] = { 0x17018, 2 },
+ [GCC_NSSNOC_QOSGEN_REF_ARES] = { 0x1701c, 2 },
+ [GCC_NSSNOC_TIMEOUT_REF_ARES] = { 0x17020, 2 },
+ [GCC_NSSNOC_MEMNOC_ARES] = { 0x17024, 2 },
+ [GCC_NSSNOC_SNOC_ARES] = { 0x17028, 2 },
+ [GCC_NSSCFG_ARES] = { 0x1702c, 2 },
+ [GCC_NSSNOC_NSSCC_ARES] = { 0x17030, 2 },
+ [GCC_NSSCC_ARES] = { 0x17034, 2 },
+ [GCC_MDIO_AHB_ARES] = { 0x17040, 2 },
+ [GCC_UNIPHY0_SYS_ARES] = { 0x17048, 2 },
+ [GCC_UNIPHY0_AHB_ARES] = { 0x1704c, 2 },
+ [GCC_UNIPHY1_SYS_ARES] = { 0x17058, 2 },
+ [GCC_UNIPHY1_AHB_ARES] = { 0x1705c, 2 },
+ [GCC_UNIPHY2_SYS_ARES] = { 0x17068, 2 },
+ [GCC_UNIPHY2_AHB_ARES] = { 0x1706c, 2 },
+ [GCC_NSSNOC_XO_DCD_ARES] = { 0x17074, 2 },
+ [GCC_NSSNOC_SNOC_1_ARES] = { 0x1707c, 2 },
+ [GCC_NSSNOC_PCNOC_1_ARES] = { 0x17080, 2 },
+ [GCC_NSSNOC_MEMNOC_1_ARES] = { 0x17084, 2 },
+ [GCC_DDRSS_ATB_ARES] = { 0x19004, 2 },
+ [GCC_DDRSS_AHB_ARES] = { 0x19008, 2 },
+ [GCC_GEMNOC_AHB_ARES] = { 0x1900c, 2 },
+ [GCC_GEMNOC_Q6_AXI_ARES] = { 0x19010, 2 },
+ [GCC_GEMNOC_NSSNOC_ARES] = { 0x19014, 2 },
+ [GCC_GEMNOC_SNOC_ARES] = { 0x19018, 2 },
+ [GCC_GEMNOC_APSS_ARES] = { 0x1901c, 2 },
+ [GCC_GEMNOC_QOSGEN_EXTREF_ARES] = { 0x19024, 2 },
+ [GCC_GEMNOC_TS_ARES] = { 0x19028, 2 },
+ [GCC_DDRSS_SMS_SLOW_ARES] = { 0x1902c, 2 },
+ [GCC_GEMNOC_CNOC_ARES] = { 0x19038, 2 },
+ [GCC_GEMNOC_XO_DBG_ARES] = { 0x19040, 2 },
+ [GCC_GEMNOC_ANOC_ARES] = { 0x19048, 2 },
+ [GCC_DDRSS_LLCC_ATB_ARES] = { 0x1904c, 2 },
+ [GCC_LLCC_TPDM_CFG_ARES] = { 0x19050, 2 },
+ [GCC_TME_BUS_ARES] = { 0x1a014, 2 },
+ [GCC_SEC_CTRL_ACC_ARES] = { 0x1a018, 2 },
+ [GCC_SEC_CTRL_ARES] = { 0x1a020, 2 },
+ [GCC_SEC_CTRL_SENSE_ARES] = { 0x1a028, 2 },
+ [GCC_SEC_CTRL_AHB_ARES] = { 0x1a038, 2 },
+ [GCC_SEC_CTRL_BOOT_ROM_PATCH_ARES] = { 0x1a03c, 2 },
+ [GCC_ADSS_PWM_ARES] = { 0x1c00c, 2 },
+ [GCC_TME_ATB_ARES] = { 0x1e030, 2 },
+ [GCC_TME_DBGAPB_ARES] = { 0x1e034, 2 },
+ [GCC_TME_DEBUG_ARES] = { 0x1e038, 2 },
+ [GCC_TME_AT_ARES] = { 0x1e03C, 2 },
+ [GCC_TME_APB_ARES] = { 0x1e040, 2 },
+ [GCC_TME_DMI_DBG_HS_ARES] = { 0x1e044, 2 },
+ [GCC_APSS_AHB_ARES] = { 0x24014, 2 },
+ [GCC_APSS_AXI_ARES] = { 0x24018, 2 },
+ [GCC_CPUSS_TRIG_ARES] = { 0x2401c, 2 },
+ [GCC_APSS_DBG_ARES] = { 0x2402c, 2 },
+ [GCC_APSS_TS_ARES] = { 0x24030, 2 },
+ [GCC_APSS_ATB_ARES] = { 0x24034, 2 },
+ [GCC_Q6_AXIM_ARES] = { 0x2500c, 2 },
+ [GCC_Q6_AXIS_ARES] = { 0x25010, 2 },
+ [GCC_Q6_AHB_ARES] = { 0x25014, 2 },
+ [GCC_Q6_AHB_S_ARES] = { 0x25018, 2 },
+ [GCC_Q6SS_ATBM_ARES] = { 0x2501c, 2 },
+ [GCC_Q6_TSCTR_1TO2_ARES] = { 0x25020, 2 },
+ [GCC_Q6SS_PCLKDBG_ARES] = { 0x25024, 2 },
+ [GCC_Q6SS_TRIG_ARES] = { 0x25028, 2 },
+ [GCC_Q6SS_BOOT_CBCR_ARES] = { 0x2502c, 2 },
+ [GCC_WCSS_DBG_IFC_APB_ARES] = { 0x25038, 2 },
+ [GCC_WCSS_DBG_IFC_ATB_ARES] = { 0x2503c, 2 },
+ [GCC_WCSS_DBG_IFC_NTS_ARES] = { 0x25040, 2 },
+ [GCC_WCSS_DBG_IFC_DAPBUS_ARES] = { 0x25044, 2 },
+ [GCC_WCSS_DBG_IFC_APB_BDG_ARES] = { 0x25048, 2 },
+ [GCC_WCSS_DBG_IFC_NTS_BDG_ARES] = { 0x25050, 2 },
+ [GCC_WCSS_DBG_IFC_DAPBUS_BDG_ARES] = { 0x25054, 2 },
+ [GCC_WCSS_ECAHB_ARES] = { 0x25058, 2 },
+ [GCC_WCSS_ACMT_ARES] = { 0x2505c, 2 },
+ [GCC_WCSS_AHB_S_ARES] = { 0x25060, 2 },
+ [GCC_WCSS_AXI_M_ARES] = { 0x25064, 2 },
+ [GCC_PCNOC_WAPSS_ARES] = { 0x25080, 2 },
+ [GCC_SNOC_WAPSS_ARES] = { 0x25090, 2 },
+ [GCC_LPASS_SWAY_ARES] = { 0x27014, 2 },
+ [GCC_LPASS_CORE_AXIM_ARES] = { 0x27018, 2 },
+ [GCC_PCIE0_AHB_ARES] = { 0x28030, 2 },
+ [GCC_PCIE0_AXI_M_ARES] = { 0x28038, 2 },
+ [GCC_PCIE0_AXI_S_ARES] = { 0x28040, 2 },
+ [GCC_PCIE0_AXI_S_BRIDGE_ARES] = { 0x28048, 2},
+ [GCC_PCIE0_PIPE_ARES] = { 0x28068, 2},
+ [GCC_PCIE0_AUX_ARES] = { 0x28070, 2 },
+ [GCC_PCIE1_AHB_ARES] = { 0x29030, 2 },
+ [GCC_PCIE1_AXI_M_ARES] = { 0x29038, 2 },
+ [GCC_PCIE1_AXI_S_ARES] = { 0x29040, 2 },
+ [GCC_PCIE1_AXI_S_BRIDGE_ARES] = { 0x29048, 2 },
+ [GCC_PCIE1_PIPE_ARES] = { 0x29068, 2 },
+ [GCC_PCIE1_AUX_ARES] = { 0x29074, 2 },
+ [GCC_PCIE2_AHB_ARES] = { 0x2a030, 2 },
+ [GCC_PCIE2_AXI_M_ARES] = { 0x2a038, 2 },
+ [GCC_PCIE2_AXI_S_ARES] = { 0x2a040, 2 },
+ [GCC_PCIE2_AXI_S_BRIDGE_ARES] = { 0x2a048, 2 },
+ [GCC_PCIE2_PIPE_ARES] = { 0x2a068, 2 },
+ [GCC_PCIE2_AUX_ARES] = { 0x2a078, 2 },
+ [GCC_PCIE3_AHB_ARES] = { 0x2b030, 2 },
+ [GCC_PCIE3_AXI_M_ARES] = { 0x2b038, 2 },
+ [GCC_PCIE3_AXI_S_ARES] = { 0x2b040, 2 },
+ [GCC_PCIE3_AXI_S_BRIDGE_ARES] = { 0x2b048, 2 },
+ [GCC_PCIE3_PIPE_ARES] = { 0x2b068, 2 },
+ [GCC_PCIE3_AUX_ARES] = { 0x2b07C, 2 },
+ [GCC_USB0_MASTER_ARES] = { 0x2c044, 2 },
+ [GCC_USB0_AUX_ARES] = { 0x2c04c, 2 },
+ [GCC_USB0_MOCK_UTMI_ARES] = { 0x2c050, 2 },
+ [GCC_USB0_PIPE_ARES] = { 0x2c054, 2 },
+ [GCC_USB0_SLEEP_ARES] = { 0x2c058, 2 },
+ [GCC_USB0_PHY_CFG_AHB_ARES] = { 0x2c05c, 2 },
+ [GCC_QDSS_AT_ARES] = { 0x2d034, 2 },
+ [GCC_QDSS_STM_ARES] = { 0x2d03C, 2 },
+ [GCC_QDSS_TRACECLKIN_ARES] = { 0x2d040, 2 },
+ [GCC_QDSS_TSCTR_DIV2_ARES] = { 0x2d044, 2 },
+ [GCC_QDSS_TSCTR_DIV3_ARES] = { 0x2d048, 2 },
+ [GCC_QDSS_TSCTR_DIV4_ARES] = { 0x2d04c, 2 },
+ [GCC_QDSS_TSCTR_DIV8_ARES] = { 0x2d050, 2 },
+ [GCC_QDSS_TSCTR_DIV16_ARES] = { 0x2d054, 2 },
+ [GCC_QDSS_DAP_ARES] = { 0x2d058, 2 },
+ [GCC_QDSS_APB2JTAG_ARES] = { 0x2d05c, 2 },
+ [GCC_QDSS_ETR_USB_ARES] = { 0x2d060, 2 },
+ [GCC_QDSS_DAP_AHB_ARES] = { 0x2d064, 2 },
+ [GCC_QDSS_CFG_AHB_ARES] = { 0x2d068, 2 },
+ [GCC_QDSS_EUD_AT_ARES] = { 0x2d06c, 2 },
+ [GCC_QDSS_TS_ARES] = { 0x2d078, 2 },
+ [GCC_QDSS_USB_ARES] = { 0x2d07c, 2 },
+ [GCC_SYS_NOC_AXI_ARES] = { 0x2e01c, 2 },
+ [GCC_SNOC_QOSGEN_EXTREF_ARES] = { 0x2e020, 2 },
+ [GCC_CNOC_LPASS_CFG_ARES] = { 0x2e028, 2 },
+ [GCC_SYS_NOC_AT_ARES] = { 0x2e038, 2 },
+ [GCC_SNOC_PCNOC_AHB_ARES] = { 0x2e03c, 2 },
+ [GCC_SNOC_TME_ARES] = { 0x2e05c, 2 },
+ [GCC_SNOC_XO_DCD_ARES] = { 0x2e060, 2 },
+ [GCC_SNOC_TS_ARES] = { 0x2e068, 2 },
+ [GCC_ANOC0_AXI_ARES] = { 0x2e078, 2 },
+ [GCC_ANOC_PCIE0_1LANE_M_ARES] = { 0x2e07c, 2 },
+ [GCC_ANOC_PCIE2_2LANE_M_ARES] = { 0x2e080, 2 },
+ [GCC_ANOC_PCIE1_1LANE_M_ARES] = { 0x2e084, 2 },
+ [GCC_ANOC_PCIE3_2LANE_M_ARES] = { 0x2e090, 2 },
+ [GCC_ANOC_PCNOC_AHB_ARES] = { 0x2e094, 2 },
+ [GCC_ANOC_QOSGEN_EXTREF_ARES] = { 0x2e098, 2 },
+ [GCC_ANOC_XO_DCD_ARES] = { 0x2e09C, 2 },
+ [GCC_SNOC_XO_DBG_ARES] = { 0x2e0a0, 2 },
+ [GCC_AGGRNOC_ATB_ARES] = { 0x2e0ac, 2 },
+ [GCC_AGGRNOC_TS_ARES] = { 0x2e0b0, 2 },
+ [GCC_USB0_EUD_AT_ARES] = { 0x30004, 2 },
+ [GCC_PCNOC_TIC_ARES] = { 0x31014, 2 },
+ [GCC_PCNOC_AHB_ARES] = { 0x31018, 2 },
+ [GCC_PCNOC_XO_DBG_ARES] = { 0x3101c, 2 },
+ [GCC_SNOC_LPASS_ARES] = { 0x31020, 2 },
+ [GCC_PCNOC_AT_ARES] = { 0x31024, 2 },
+ [GCC_PCNOC_XO_DCD_ARES] = { 0x31028, 2 },
+ [GCC_PCNOC_TS_ARES] = { 0x3102c, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT0_AHB_ARES] = { 0x31034, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT1_AHB_ARES] = { 0x3103c, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT2_AHB_ARES] = { 0x31044, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT3_AHB_ARES] = { 0x3104c, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT4_AHB_ARES] = { 0x31054, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT5_AHB_ARES] = { 0x3105c, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT6_AHB_ARES] = { 0x31064, 2 },
+ [GCC_PCNOC_BUS_TIMEOUT7_AHB_ARES] = { 0x3106c, 2 },
+ [GCC_Q6_AXIM_RESET] = { 0x2506c, 0 },
+ [GCC_Q6_AXIS_RESET] = { 0x2506c, 1 },
+ [GCC_Q6_AHB_S_RESET] = { 0x2506c, 2 },
+ [GCC_Q6_AHB_RESET] = { 0x2506c, 3 },
+ [GCC_Q6SS_DBG_RESET] = { 0x2506c, 4 },
+ [GCC_WCSS_ECAHB_RESET] = { 0x25070, 0 },
+ [GCC_WCSS_DBG_BDG_RESET] = { 0x25070, 1 },
+ [GCC_WCSS_DBG_RESET] = { 0x25070, 2 },
+ [GCC_WCSS_AXI_M_RESET] = { 0x25070, 3 },
+ [GCC_WCSS_AHB_S_RESET] = { 0x25070, 4 },
+ [GCC_WCSS_ACMT_RESET] = { 0x25070, 5 },
+ [GCC_WCSSAON_RESET] = { 0x25074, 0 },
+ [GCC_PCIE0_PIPE_RESET] = { 0x28058, 0 },
+ [GCC_PCIE0_CORE_STICKY_RESET] = { 0x28058, 1 },
+ [GCC_PCIE0_AXI_S_STICKY_RESET] = { 0x28058, 2 },
+ [GCC_PCIE0_AXI_S_RESET] = { 0x28058, 3 },
+ [GCC_PCIE0_AXI_M_STICKY_RESET] = { 0x28058, 4 },
+ [GCC_PCIE0_AXI_M_RESET] = { 0x28058, 5 },
+ [GCC_PCIE0_AUX_RESET] = { 0x28058, 6 },
+ [GCC_PCIE0_AHB_RESET] = { 0x28058, 7 },
+ [GCC_PCIE1_PIPE_RESET] = { 0x29058, 0 },
+ [GCC_PCIE1_CORE_STICKY_RESET] = { 0x29058, 1 },
+ [GCC_PCIE1_AXI_S_STICKY_RESET] = { 0x29058, 2 },
+ [GCC_PCIE1_AXI_S_RESET] = { 0x29058, 3 },
+ [GCC_PCIE1_AXI_M_STICKY_RESET] = { 0x29058, 4 },
+ [GCC_PCIE1_AXI_M_RESET] = { 0x29058, 5 },
+ [GCC_PCIE1_AUX_RESET] = { 0x29058, 6 },
+ [GCC_PCIE1_AHB_RESET] = { 0x29058, 7 },
+ [GCC_PCIE2_PIPE_RESET] = { 0x2a058, 0 },
+ [GCC_PCIE2_CORE_STICKY_RESET] = { 0x2a058, 1 },
+ [GCC_PCIE2_AXI_S_STICKY_RESET] = { 0x2a058, 2 },
+ [GCC_PCIE2_AXI_S_RESET] = { 0x2a058, 3 },
+ [GCC_PCIE2_AXI_M_STICKY_RESET] = { 0x2a058, 4 },
+ [GCC_PCIE2_AXI_M_RESET] = { 0x2a058, 5 },
+ [GCC_PCIE2_AUX_RESET] = { 0x2a058, 6 },
+ [GCC_PCIE2_AHB_RESET] = { 0x2a058, 7 },
+ [GCC_PCIE3_PIPE_RESET] = { 0x2b058, 0 },
+ [GCC_PCIE3_CORE_STICKY_RESET] = { 0x2b058, 1 },
+ [GCC_PCIE3_AXI_S_STICKY_RESET] = { 0x2b058, 2 },
+ [GCC_PCIE3_AXI_S_RESET] = { 0x2b058, 3 },
+ [GCC_PCIE3_AXI_M_STICKY_RESET] = { 0x2b058, 4 },
+ [GCC_PCIE3_AXI_M_RESET] = { 0x2b058, 5 },
+ [GCC_PCIE3_AUX_RESET] = { 0x2b058, 6 },
+ [GCC_PCIE3_AHB_RESET] = { 0x2b058, 7 },
+ [GCC_NSS_PARTIAL_RESET] = { 0x17078, 0 },
+ [GCC_UNIPHY0_XPCS_ARES] = { 0x17050, 2 },
+ [GCC_UNIPHY1_XPCS_ARES] = { 0x17060, 2 },
+ [GCC_UNIPHY2_XPCS_ARES] = { 0x17070, 2 },
+ [GCC_USB1_BCR] = { 0x3C000, 0 },
+ [GCC_QUSB2_1_PHY_BCR] = { 0x3C030, 0 },
+};
+
+static const struct of_device_id gcc_ipq5424_match_table[] = {
+ { .compatible = "qcom,ipq5424-gcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_ipq5424_match_table);
+
+static const struct regmap_config gcc_ipq5424_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x3f024,
+ .fast_io = true,
+};
+
+static struct clk_hw *gcc_ipq5424_hws[] = {
+ &gpll0_div2.hw,
+ &gcc_xo_div4_clk_src.hw,
+ &gcc_qdss_tsctr_div2_clk_src.hw,
+ &gcc_qdss_dap_sync_clk_src.hw,
+ &gcc_eud_at_div_clk_src.hw,
+};
+
+static const struct qcom_cc_desc gcc_ipq5424_desc = {
+ .config = &gcc_ipq5424_regmap_config,
+ .clks = gcc_ipq5424_clocks,
+ .num_clks = ARRAY_SIZE(gcc_ipq5424_clocks),
+ .resets = gcc_ipq5424_resets,
+ .num_resets = ARRAY_SIZE(gcc_ipq5424_resets),
+ .clk_hws = gcc_ipq5424_hws,
+ .num_clk_hws = ARRAY_SIZE(gcc_ipq5424_hws),
+};
+
+static int gcc_ipq5424_probe(struct platform_device *pdev)
+{
+ return qcom_cc_probe(pdev, &gcc_ipq5424_desc);
+}
+
+static struct platform_driver gcc_ipq5424_driver = {
+ .probe = gcc_ipq5424_probe,
+ .driver = {
+ .name = "qcom,gcc-ipq5424",
+ .of_match_table = gcc_ipq5424_match_table,
+ },
+};
+
+static int __init gcc_ipq5424_init(void)
+{
+ return platform_driver_register(&gcc_ipq5424_driver);
+}
+core_initcall(gcc_ipq5424_init);
+
+static void __exit gcc_ipq5424_exit(void)
+{
+ platform_driver_unregister(&gcc_ipq5424_driver);
+}
+module_exit(gcc_ipq5424_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. GCC IPQ5424 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c
index 645109f75b46..6bb66a7e1fb6 100644
--- a/drivers/clk/qcom/gcc-ipq9574.c
+++ b/drivers/clk/qcom/gcc-ipq9574.c
@@ -2645,24 +2645,6 @@ static struct clk_rcg2 system_noc_bfdcd_clk_src = {
},
};
-static struct clk_branch gcc_q6ss_boot_clk = {
- .halt_reg = 0x25080,
- .halt_check = BRANCH_HALT_SKIP,
- .clkr = {
- .enable_reg = 0x25080,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6ss_boot_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &system_noc_bfdcd_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_nssnoc_snoc_clk = {
.halt_reg = 0x17028,
.clkr = {
@@ -2733,91 +2715,6 @@ static struct clk_rcg2 wcss_ahb_clk_src = {
},
};
-static struct clk_branch gcc_q6_ahb_clk = {
- .halt_reg = 0x25014,
- .clkr = {
- .enable_reg = 0x25014,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_ahb_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &wcss_ahb_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6_ahb_s_clk = {
- .halt_reg = 0x25018,
- .clkr = {
- .enable_reg = 0x25018,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_ahb_s_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &wcss_ahb_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_ecahb_clk = {
- .halt_reg = 0x25058,
- .clkr = {
- .enable_reg = 0x25058,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_ecahb_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &wcss_ahb_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_acmt_clk = {
- .halt_reg = 0x2505c,
- .clkr = {
- .enable_reg = 0x2505c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_acmt_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &wcss_ahb_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_sys_noc_wcss_ahb_clk = {
- .halt_reg = 0x2e030,
- .clkr = {
- .enable_reg = 0x2e030,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_sys_noc_wcss_ahb_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &wcss_ahb_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static const struct freq_tbl ftbl_wcss_axi_m_clk_src[] = {
F(24000000, P_XO, 1, 0, 0),
F(133333333, P_GPLL0, 6, 0, 0),
@@ -2838,23 +2735,6 @@ static struct clk_rcg2 wcss_axi_m_clk_src = {
},
};
-static struct clk_branch gcc_anoc_wcss_axi_m_clk = {
- .halt_reg = 0x2e0a8,
- .clkr = {
- .enable_reg = 0x2e0a8,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_anoc_wcss_axi_m_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &wcss_axi_m_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static const struct freq_tbl ftbl_qdss_at_clk_src[] = {
F(240000000, P_GPLL4, 5, 0, 0),
{ }
@@ -2873,40 +2753,6 @@ static struct clk_rcg2 qdss_at_clk_src = {
},
};
-static struct clk_branch gcc_q6ss_atbm_clk = {
- .halt_reg = 0x2501c,
- .clkr = {
- .enable_reg = 0x2501c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6ss_atbm_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_at_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_atb_clk = {
- .halt_reg = 0x2503c,
- .clkr = {
- .enable_reg = 0x2503c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_atb_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_at_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_nssnoc_atb_clk = {
.halt_reg = 0x17014,
.clkr = {
@@ -3143,40 +2989,6 @@ static struct clk_fixed_factor qdss_tsctr_div2_clk_src = {
},
};
-static struct clk_branch gcc_q6_tsctr_1to2_clk = {
- .halt_reg = 0x25020,
- .clkr = {
- .enable_reg = 0x25020,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_tsctr_1to2_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_tsctr_div2_clk_src.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_nts_clk = {
- .halt_reg = 0x25040,
- .clkr = {
- .enable_reg = 0x25040,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_nts_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_tsctr_div2_clk_src.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_qdss_tsctr_div2_clk = {
.halt_reg = 0x2d044,
.clkr = {
@@ -3351,74 +3163,6 @@ static struct clk_branch gcc_qdss_tsctr_div16_clk = {
},
};
-static struct clk_branch gcc_q6ss_pclkdbg_clk = {
- .halt_reg = 0x25024,
- .clkr = {
- .enable_reg = 0x25024,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6ss_pclkdbg_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_dap_sync_clk_src.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_q6ss_trig_clk = {
- .halt_reg = 0x25068,
- .clkr = {
- .enable_reg = 0x25068,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6ss_trig_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_dap_sync_clk_src.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_apb_clk = {
- .halt_reg = 0x25038,
- .clkr = {
- .enable_reg = 0x25038,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_apb_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_dap_sync_clk_src.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_dbg_ifc_dapbus_clk = {
- .halt_reg = 0x25044,
- .clkr = {
- .enable_reg = 0x25044,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_dbg_ifc_dapbus_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &qdss_dap_sync_clk_src.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_qdss_dap_clk = {
.halt_reg = 0x2d058,
.clkr = {
@@ -3540,58 +3284,6 @@ static struct clk_rcg2 q6_axi_clk_src = {
},
};
-static struct clk_branch gcc_q6_axim_clk = {
- .halt_reg = 0x2500c,
- .clkr = {
- .enable_reg = 0x2500c,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_q6_axim_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &q6_axi_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_wcss_q6_tbu_clk = {
- .halt_reg = 0x12050,
- .halt_check = BRANCH_HALT_DELAY,
- .clkr = {
- .enable_reg = 0xb00c,
- .enable_mask = BIT(6),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_wcss_q6_tbu_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &q6_axi_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_mem_noc_q6_axi_clk = {
- .halt_reg = 0x19010,
- .clkr = {
- .enable_reg = 0x19010,
- .enable_mask = BIT(0),
- .hw.init = &(const struct clk_init_data) {
- .name = "gcc_mem_noc_q6_axi_clk",
- .parent_hws = (const struct clk_hw *[]) {
- &q6_axi_clk_src.clkr.hw
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static const struct freq_tbl ftbl_q6_axim2_clk_src[] = {
F(342857143, P_GPLL4, 3.5, 0, 0),
{ }
@@ -4141,16 +3833,8 @@ static struct clk_regmap *gcc_ipq9574_clks[] = {
[GCC_NSSNOC_SNOC_1_CLK] = &gcc_nssnoc_snoc_1_clk.clkr,
[GCC_QDSS_ETR_USB_CLK] = &gcc_qdss_etr_usb_clk.clkr,
[WCSS_AHB_CLK_SRC] = &wcss_ahb_clk_src.clkr,
- [GCC_Q6_AHB_CLK] = &gcc_q6_ahb_clk.clkr,
- [GCC_Q6_AHB_S_CLK] = &gcc_q6_ahb_s_clk.clkr,
- [GCC_WCSS_ECAHB_CLK] = &gcc_wcss_ecahb_clk.clkr,
- [GCC_WCSS_ACMT_CLK] = &gcc_wcss_acmt_clk.clkr,
- [GCC_SYS_NOC_WCSS_AHB_CLK] = &gcc_sys_noc_wcss_ahb_clk.clkr,
[WCSS_AXI_M_CLK_SRC] = &wcss_axi_m_clk_src.clkr,
- [GCC_ANOC_WCSS_AXI_M_CLK] = &gcc_anoc_wcss_axi_m_clk.clkr,
[QDSS_AT_CLK_SRC] = &qdss_at_clk_src.clkr,
- [GCC_Q6SS_ATBM_CLK] = &gcc_q6ss_atbm_clk.clkr,
- [GCC_WCSS_DBG_IFC_ATB_CLK] = &gcc_wcss_dbg_ifc_atb_clk.clkr,
[GCC_NSSNOC_ATB_CLK] = &gcc_nssnoc_atb_clk.clkr,
[GCC_QDSS_AT_CLK] = &gcc_qdss_at_clk.clkr,
[GCC_SYS_NOC_AT_CLK] = &gcc_sys_noc_at_clk.clkr,
@@ -4163,27 +3847,18 @@ static struct clk_regmap *gcc_ipq9574_clks[] = {
[QDSS_TRACECLKIN_CLK_SRC] = &qdss_traceclkin_clk_src.clkr,
[GCC_QDSS_TRACECLKIN_CLK] = &gcc_qdss_traceclkin_clk.clkr,
[QDSS_TSCTR_CLK_SRC] = &qdss_tsctr_clk_src.clkr,
- [GCC_Q6_TSCTR_1TO2_CLK] = &gcc_q6_tsctr_1to2_clk.clkr,
- [GCC_WCSS_DBG_IFC_NTS_CLK] = &gcc_wcss_dbg_ifc_nts_clk.clkr,
[GCC_QDSS_TSCTR_DIV2_CLK] = &gcc_qdss_tsctr_div2_clk.clkr,
[GCC_QDSS_TS_CLK] = &gcc_qdss_ts_clk.clkr,
[GCC_QDSS_TSCTR_DIV4_CLK] = &gcc_qdss_tsctr_div4_clk.clkr,
[GCC_NSS_TS_CLK] = &gcc_nss_ts_clk.clkr,
[GCC_QDSS_TSCTR_DIV8_CLK] = &gcc_qdss_tsctr_div8_clk.clkr,
[GCC_QDSS_TSCTR_DIV16_CLK] = &gcc_qdss_tsctr_div16_clk.clkr,
- [GCC_Q6SS_PCLKDBG_CLK] = &gcc_q6ss_pclkdbg_clk.clkr,
- [GCC_Q6SS_TRIG_CLK] = &gcc_q6ss_trig_clk.clkr,
- [GCC_WCSS_DBG_IFC_APB_CLK] = &gcc_wcss_dbg_ifc_apb_clk.clkr,
- [GCC_WCSS_DBG_IFC_DAPBUS_CLK] = &gcc_wcss_dbg_ifc_dapbus_clk.clkr,
[GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr,
[GCC_QDSS_APB2JTAG_CLK] = &gcc_qdss_apb2jtag_clk.clkr,
[GCC_QDSS_TSCTR_DIV3_CLK] = &gcc_qdss_tsctr_div3_clk.clkr,
[QPIC_IO_MACRO_CLK_SRC] = &qpic_io_macro_clk_src.clkr,
[GCC_QPIC_IO_MACRO_CLK] = &gcc_qpic_io_macro_clk.clkr,
[Q6_AXI_CLK_SRC] = &q6_axi_clk_src.clkr,
- [GCC_Q6_AXIM_CLK] = &gcc_q6_axim_clk.clkr,
- [GCC_WCSS_Q6_TBU_CLK] = &gcc_wcss_q6_tbu_clk.clkr,
- [GCC_MEM_NOC_Q6_AXI_CLK] = &gcc_mem_noc_q6_axi_clk.clkr,
[Q6_AXIM2_CLK_SRC] = &q6_axim2_clk_src.clkr,
[NSSNOC_MEMNOC_BFDCD_CLK_SRC] = &nssnoc_memnoc_bfdcd_clk_src.clkr,
[GCC_NSSNOC_MEMNOC_CLK] = &gcc_nssnoc_memnoc_clk.clkr,
@@ -4207,7 +3882,6 @@ static struct clk_regmap *gcc_ipq9574_clks[] = {
[GCC_UNIPHY1_SYS_CLK] = &gcc_uniphy1_sys_clk.clkr,
[GCC_UNIPHY2_SYS_CLK] = &gcc_uniphy2_sys_clk.clkr,
[GCC_CMN_12GPLL_SYS_CLK] = &gcc_cmn_12gpll_sys_clk.clkr,
- [GCC_Q6SS_BOOT_CLK] = &gcc_q6ss_boot_clk.clkr,
[UNIPHY_SYS_CLK_SRC] = &uniphy_sys_clk_src.clkr,
[NSS_TS_CLK_SRC] = &nss_ts_clk_src.clkr,
[GCC_ANOC_PCIE0_1LANE_M_CLK] = &gcc_anoc_pcie0_1lane_m_clk.clkr,
@@ -4384,7 +4058,7 @@ static const struct qcom_reset_map gcc_ipq9574_resets[] = {
#define IPQ_APPS_ID 9574 /* some unique value */
-static struct qcom_icc_hws_data icc_ipq9574_hws[] = {
+static const struct qcom_icc_hws_data icc_ipq9574_hws[] = {
{ MASTER_ANOC_PCIE0, SLAVE_ANOC_PCIE0, GCC_ANOC_PCIE0_1LANE_M_CLK },
{ MASTER_SNOC_PCIE0, SLAVE_SNOC_PCIE0, GCC_SNOC_PCIE0_1LANE_S_CLK },
{ MASTER_ANOC_PCIE1, SLAVE_ANOC_PCIE1, GCC_ANOC_PCIE1_1LANE_M_CLK },
diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c
index c3cfd572e7c1..5ca003c9bfba 100644
--- a/drivers/clk/qcom/gcc-qcs404.c
+++ b/drivers/clk/qcom/gcc-qcs404.c
@@ -131,6 +131,7 @@ static struct clk_alpha_pll gpll1_out_main = {
/* 930MHz configuration */
static const struct alpha_pll_config gpll3_config = {
.l = 48,
+ .alpha_hi = 0x70,
.alpha = 0x0,
.alpha_en_mask = BIT(24),
.post_div_mask = 0xf << 8,
diff --git a/drivers/clk/qcom/gcc-qcs8300.c b/drivers/clk/qcom/gcc-qcs8300.c
new file mode 100644
index 000000000000..80831c7dea3b
--- /dev/null
+++ b/drivers/clk/qcom/gcc-qcs8300.c
@@ -0,0 +1,3640 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,qcs8300-gcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "clk-regmap-phy-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+ DT_PCIE_0_PIPE_CLK,
+ DT_PCIE_1_PIPE_CLK,
+ DT_PCIE_PHY_AUX_CLK,
+ DT_RXC0_REF_CLK,
+ DT_UFS_PHY_RX_SYMBOL_0_CLK,
+ DT_UFS_PHY_RX_SYMBOL_1_CLK,
+ DT_UFS_PHY_TX_SYMBOL_0_CLK,
+ DT_USB3_PHY_WRAPPER_GCC_USB30_PRIM_PIPE_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_GCC_GPLL0_OUT_EVEN,
+ P_GCC_GPLL0_OUT_MAIN,
+ P_GCC_GPLL1_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_PIPE_CLK,
+ P_PCIE_PHY_AUX_CLK,
+ P_RXC0_REF_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_PRIM_PIPE_CLK,
+};
+
+static struct clk_alpha_pll gcc_gpll0 = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x4b028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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_evo_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_EVO],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_evo_ops,
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll1 = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x4b028,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_evo_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll4 = {
+ .offset = 0x4000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x4b028,
+ .enable_mask = BIT(4),
+ .hw.init = &(const 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_evo_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll7 = {
+ .offset = 0x7000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x4b028,
+ .enable_mask = BIT(7),
+ .hw.init = &(const 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_evo_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll9 = {
+ .offset = 0x9000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .enable_reg = 0x4b028,
+ .enable_mask = BIT(9),
+ .hw.init = &(const 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_evo_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_GPLL1_OUT_MAIN, 4 },
+ { 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_gpll1.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 },
+ { 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_4[] = {
+ { .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_5[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data gcc_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL7_OUT_MAIN, 2 },
+ { P_GCC_GPLL4_OUT_MAIN, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll7.clkr.hw },
+ { .hw = &gcc_gpll4.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_7[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL7_OUT_MAIN, 2 },
+ { P_RXC0_REF_CLK, 3 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_7[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll7.clkr.hw },
+ { .index = DT_RXC0_REF_CLK },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_PCIE_PHY_AUX_CLK, 1 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_8[] = {
+ { .index = DT_PCIE_PHY_AUX_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_10[] = {
+ { P_PCIE_PHY_AUX_CLK, 1 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_10[] = {
+ { .index = DT_PCIE_PHY_AUX_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_12[] = {
+ { 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_12[] = {
+ { .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_13[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data gcc_parent_data_13[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_14[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL4_OUT_MAIN, 3 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_14[] = {
+ { .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_15[] = {
+ { P_UFS_PHY_RX_SYMBOL_0_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_15[] = {
+ { .index = DT_UFS_PHY_RX_SYMBOL_0_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_16[] = {
+ { P_UFS_PHY_RX_SYMBOL_1_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_16[] = {
+ { .index = DT_UFS_PHY_RX_SYMBOL_1_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_17[] = {
+ { P_UFS_PHY_TX_SYMBOL_0_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_17[] = {
+ { .index = DT_UFS_PHY_TX_SYMBOL_0_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_18[] = {
+ { P_USB3_PHY_WRAPPER_GCC_USB30_PRIM_PIPE_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_18[] = {
+ { .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PRIM_PIPE_CLK },
+ { .index = DT_BI_TCXO },
+};
+
+static struct clk_regmap_mux gcc_pcie_0_phy_aux_clk_src = {
+ .reg = 0xa9074,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_8,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_8,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_8),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie_0_pipe_clk_src = {
+ .reg = 0xa906c,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE_0_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_pcie_1_phy_aux_clk_src = {
+ .reg = 0x77074,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_10,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_phy_aux_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_phy_mux gcc_pcie_1_pipe_clk_src = {
+ .reg = 0x7706c,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE_1_PIPE_CLK,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_0_clk_src = {
+ .reg = 0x83060,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_15,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_0_clk_src",
+ .parent_data = gcc_parent_data_15,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_15),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_1_clk_src = {
+ .reg = 0x830d0,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_16,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_1_clk_src",
+ .parent_data = gcc_parent_data_16,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_16),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_ufs_phy_tx_symbol_0_clk_src = {
+ .reg = 0x83050,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_17,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_tx_symbol_0_clk_src",
+ .parent_data = gcc_parent_data_17,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_17),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_usb3_prim_phy_pipe_clk_src = {
+ .reg = 0x1b068,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_18,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_pipe_clk_src",
+ .parent_data = gcc_parent_data_18,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_18),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_emac0_phy_aux_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_emac0_phy_aux_clk_src = {
+ .cmd_rcgr = 0xb6028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_emac0_ptp_clk_src[] = {
+ F(125000000, P_GCC_GPLL7_OUT_MAIN, 8, 0, 0),
+ F(230400000, P_GCC_GPLL4_OUT_MAIN, 3.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_emac0_ptp_clk_src = {
+ .cmd_rcgr = 0xb6060,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_emac0_ptp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_ptp_clk_src",
+ .parent_data = gcc_parent_data_6,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_emac0_rgmii_clk_src[] = {
+ F(5000000, P_GCC_GPLL0_OUT_EVEN, 10, 1, 6),
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(125000000, P_GCC_GPLL7_OUT_MAIN, 8, 0, 0),
+ F(250000000, P_GCC_GPLL7_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_emac0_rgmii_clk_src = {
+ .cmd_rcgr = 0xb6048,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_7,
+ .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_rgmii_clk_src",
+ .parent_data = gcc_parent_data_7,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_7),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+ 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 = 0x70004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+ .cmd_rcgr = 0x71004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+ .cmd_rcgr = 0x62004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp4_clk_src = {
+ .cmd_rcgr = 0x1e004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp4_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp5_clk_src = {
+ .cmd_rcgr = 0x1f004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp5_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_0_aux_clk_src = {
+ .cmd_rcgr = 0xa9078,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const 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_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = {
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie_0_phy_rchng_clk_src = {
+ .cmd_rcgr = 0xa9054,
+ .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 = &(const 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_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_1_aux_clk_src = {
+ .cmd_rcgr = 0x77078,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const 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_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = {
+ .cmd_rcgr = 0x77054,
+ .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 = &(const 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_shared_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 = 0x3f010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_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(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(120000000, P_GCC_GPLL0_OUT_MAIN, 5, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
+ .cmd_rcgr = 0x23154,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
+ .cmd_rcgr = 0x23288,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_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(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75),
+ 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_wrap0_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
+ .cmd_rcgr = 0x233bc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
+ .cmd_rcgr = 0x234f0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s4_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
+ .cmd_rcgr = 0x23624,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
+ .cmd_rcgr = 0x23758,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s6_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = {
+ .cmd_rcgr = 0x2388c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s7_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = {
+ .cmd_rcgr = 0x239c0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init,
+};
+
+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_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
+ .cmd_rcgr = 0x24154,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_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_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
+ .cmd_rcgr = 0x24288,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
+};
+
+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_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
+ .cmd_rcgr = 0x243bc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_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_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
+ .cmd_rcgr = 0x244f0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_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_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
+ .cmd_rcgr = 0x24624,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_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_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = {
+ .cmd_rcgr = 0x24758,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_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_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s6_clk_src = {
+ .cmd_rcgr = 0x2488c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_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_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s7_clk_src = {
+ .cmd_rcgr = 0x249c0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s7_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap3_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(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(403200000, P_GCC_GPLL4_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap3_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap3_s0_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap3_s0_clk_src = {
+ .cmd_rcgr = 0xc4158,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_qupv3_wrap3_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap3_s0_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+ F(144000, P_BI_TCXO, 16, 3, 25),
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(20000000, P_GCC_GPLL0_OUT_EVEN, 5, 1, 3),
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(192000000, P_GCC_GPLL9_OUT_MAIN, 4, 0, 0),
+ F(384000000, P_GCC_GPLL9_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x20014,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_12,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk_src",
+ .parent_data = gcc_parent_data_12,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_12),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = {
+ 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_sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x2002c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_13,
+ .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk_src",
+ .parent_data = gcc_parent_data_13,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_13),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_floor_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 = 0x8302c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src,
+ .clkr.hw.init = &(const 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_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = {
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(201600000, P_GCC_GPLL4_OUT_MAIN, 4, 0, 0),
+ F(403200000, P_GCC_GPLL4_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = {
+ .cmd_rcgr = 0x83074,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_14,
+ .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_ice_core_clk_src",
+ .parent_data = gcc_parent_data_14,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_14),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = {
+ .cmd_rcgr = 0x830a8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_5,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_5,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_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 = 0x8308c,
+ .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 = &(const 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_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb20_master_clk_src[] = {
+ F(120000000, P_GCC_GPLL0_OUT_MAIN, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb20_master_clk_src = {
+ .cmd_rcgr = 0x1c028,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb20_master_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb20_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_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb20_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x1c040,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb20_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_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = {
+ 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 = 0x1b028,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src,
+ .clkr.hw.init = &(const 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_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x1b040,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_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_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
+ .cmd_rcgr = 0x1b06c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src,
+ .clkr.hw.init = &(const 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_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_pcie_0_pipe_div_clk_src = {
+ .reg = 0xa9070,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_pcie_1_pipe_div_clk_src = {
+ .reg = 0x77070,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_qupv3_wrap3_s0_div_clk_src = {
+ .reg = 0xc4288,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap3_s0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap3_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb20_mock_utmi_postdiv_clk_src = {
+ .reg = 0x1c058,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb20_mock_utmi_postdiv_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb20_mock_utmi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = {
+ .reg = 0x1b058,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src",
+ .parent_hws = (const struct clk_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_qupv3_axi_clk = {
+ .halt_reg = 0x8e200,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8e200,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(28),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_noc_qupv3_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_ufs_phy_axi_clk = {
+ .halt_reg = 0x830d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x830d4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x830d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_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_usb2_prim_axi_clk = {
+ .halt_reg = 0x1c05c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x1c05c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1c05c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_usb2_prim_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb20_master_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 = 0x1b084,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x1b084,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1b084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_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_ahb2phy0_clk = {
+ .halt_reg = 0x76004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x76004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x76004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ahb2phy0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ahb2phy2_clk = {
+ .halt_reg = 0x76008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x76008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x76008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ahb2phy2_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ahb2phy3_clk = {
+ .halt_reg = 0x7600c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7600c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ahb2phy3_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x44004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x44004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(10),
+ .hw.init = &(const 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 = 0x32010,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x32010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x32010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x32018,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x32018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x32018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_camera_sf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_throttle_xo_clk = {
+ .halt_reg = 0x32024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x32024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_camera_throttle_xo_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb2_prim_axi_clk = {
+ .halt_reg = 0x1c060,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x1c060,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1c060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cfg_noc_usb2_prim_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb20_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = {
+ .halt_reg = 0x1b088,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x1b088,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1b088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cfg_noc_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_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_ddrss_gpu_axi_clk = {
+ .halt_reg = 0x7d164,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7d164,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d164,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ddrss_gpu_axi_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_hf_axi_clk = {
+ .halt_reg = 0x33010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x33010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x33010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_disp_hf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_edp_ref_clkref_en = {
+ .halt_reg = 0x97448,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x97448,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_edp_ref_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_axi_clk = {
+ .halt_reg = 0xb6018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xb6018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0xb6018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_phy_aux_clk = {
+ .halt_reg = 0xb6024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xb6024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_ptp_clk = {
+ .halt_reg = 0xb6040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xb6040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_ptp_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_ptp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_rgmii_clk = {
+ .halt_reg = 0xb6044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xb6044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_rgmii_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_emac0_rgmii_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_emac0_slv_ahb_clk = {
+ .halt_reg = 0xb6020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xb6020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0xb6020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_emac0_slv_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x70000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x70000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x71000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x71000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x62000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp4_clk = {
+ .halt_reg = 0x1e000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1e000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp5_clk = {
+ .halt_reg = 0x1f000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1f000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp5_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 = 0x4b000,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_gpll0_clk_src",
+ .parent_hws = (const struct clk_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 = 0x4b000,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_gpll0_div_clk_src",
+ .parent_hws = (const struct clk_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_center_pipeline_clk = {
+ .halt_reg = 0x7d160,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7d160,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d160,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_memnoc_gfx_center_pipeline_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_memnoc_gfx_clk = {
+ .halt_reg = 0x7d010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7d010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_memnoc_gfx_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = {
+ .halt_reg = 0x7d01c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7d01c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_snoc_dvm_gfx_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_tcu_throttle_ahb_clk = {
+ .halt_reg = 0x7d008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7d008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_tcu_throttle_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_tcu_throttle_clk = {
+ .halt_reg = 0x7d014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7d014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x7d014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_tcu_throttle_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+ .halt_reg = 0xa9038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b010,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_aux_clk",
+ .parent_hws = (const struct clk_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 = 0xa902c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xa902c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b010,
+ .enable_mask = BIT(12),
+ .hw.init = &(const 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 = 0xa9024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b010,
+ .enable_mask = BIT(11),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_phy_aux_clk = {
+ .halt_reg = 0xa9030,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b010,
+ .enable_mask = BIT(13),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_phy_aux_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_phy_rchng_clk = {
+ .halt_reg = 0xa9050,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b010,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_phy_rchng_clk",
+ .parent_hws = (const struct clk_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 = 0xa9040,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x4b010,
+ .enable_mask = BIT(14),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_clk",
+ .parent_hws = (const struct clk_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_pipediv2_clk = {
+ .halt_reg = 0xa9048,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x4b018,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipediv2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_0_pipe_div_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 = 0xa901c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b010,
+ .enable_mask = BIT(10),
+ .hw.init = &(const 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 = 0xa9018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b018,
+ .enable_mask = BIT(12),
+ .hw.init = &(const 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 = 0x77038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(31),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x7702c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7702c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(2),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+ .halt_reg = 0x77024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_phy_aux_clk = {
+ .halt_reg = 0x77030,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(3),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_phy_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x77050,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_phy_rchng_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_phy_rchng_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+ .halt_reg = 0x77040,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_pipediv2_clk = {
+ .halt_reg = 0x77048,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x4b018,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipediv2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_pipe_div_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 = 0x7701c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_slv_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_slv_q2a_axi_clk = {
+ .halt_reg = 0x77018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(5),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_slv_q2a_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_clkref_en = {
+ .halt_reg = 0x9746c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x9746c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_throttle_cfg_clk = {
+ .halt_reg = 0xb2034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b020,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_throttle_cfg_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x3f00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3f00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pdm2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x3f004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3f004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+ .halt_reg = 0x3f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_xo4_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_camera_nrt_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 = &(const 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 = 0x3200c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3200c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x33008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x33008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x33008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_disp_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_disp_rot_ahb_clk = {
+ .halt_reg = 0x3300c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x3300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_disp_rot_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_cvp_ahb_clk = {
+ .halt_reg = 0x34008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x34008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x34008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_video_cvp_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = {
+ .halt_reg = 0x3400c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3400c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3400c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_video_vcodec_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_vcpu_ahb_clk = {
+ .halt_reg = 0x34010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x34010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x34010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_video_vcpu_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = {
+ .halt_reg = 0x23018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(9),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_clk = {
+ .halt_reg = 0x2300c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(8),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s0_clk = {
+ .halt_reg = 0x2314c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(10),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s1_clk = {
+ .halt_reg = 0x23280,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(11),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s2_clk = {
+ .halt_reg = 0x233b4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(12),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s3_clk = {
+ .halt_reg = 0x234e8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(13),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s4_clk = {
+ .halt_reg = 0x2361c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(14),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s5_clk = {
+ .halt_reg = 0x23750,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s6_clk = {
+ .halt_reg = 0x23884,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s6_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s7_clk = {
+ .halt_reg = 0x239b8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(17),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s7_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = {
+ .halt_reg = 0x24018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(18),
+ .hw.init = &(const 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 = 0x2400c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(19),
+ .hw.init = &(const 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 = 0x2414c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s0_clk",
+ .parent_hws = (const struct clk_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 = 0x24280,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(23),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s1_clk",
+ .parent_hws = (const struct clk_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 = 0x243b4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(24),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s2_clk",
+ .parent_hws = (const struct clk_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 = 0x244e8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(25),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s3_clk",
+ .parent_hws = (const struct clk_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 = 0x2461c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s4_clk",
+ .parent_hws = (const struct clk_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 = 0x24750,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(27),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s5_clk",
+ .parent_hws = (const struct clk_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 = 0x24884,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b018,
+ .enable_mask = BIT(27),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s6_clk",
+ .parent_hws = (const struct clk_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 = 0x249b8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b018,
+ .enable_mask = BIT(28),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s7_clk",
+ .parent_hws = (const struct clk_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_wrap3_core_2x_clk = {
+ .halt_reg = 0xc4018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(24),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap3_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap3_core_clk = {
+ .halt_reg = 0xc400c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(23),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap3_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap3_qspi_clk = {
+ .halt_reg = 0xc4284,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap3_qspi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap3_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap3_s0_clk = {
+ .halt_reg = 0xc4150,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(25),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap3_s0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap3_s0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = {
+ .halt_reg = 0x23004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x23004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(6),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = {
+ .halt_reg = 0x23008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x23008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(7),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = {
+ .halt_reg = 0x24004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x24004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(20),
+ .hw.init = &(const 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 = 0x24008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x24008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b008,
+ .enable_mask = BIT(21),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_1_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_3_m_ahb_clk = {
+ .halt_reg = 0xc4004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xc4004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(27),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_3_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_3_s_ahb_clk = {
+ .halt_reg = 0xc4008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0xc4008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4b000,
+ .enable_mask = BIT(20),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_3_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x2000c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2000c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x20004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x20044,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x20044,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x20044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sgmi_clkref_en = {
+ .halt_reg = 0x97034,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x97034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sgmi_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ahb_clk = {
+ .halt_reg = 0x83020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x83020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x83020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x83018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x83018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x83018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_axi_clk",
+ .parent_hws = (const struct clk_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 = 0x8306c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8306c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8306c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_ice_core_clk",
+ .parent_hws = (const struct clk_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 = 0x830a4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x830a4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x830a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_phy_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x83028,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x83028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_0_clk",
+ .parent_hws = (const struct clk_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 = 0x830c0,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x830c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_rx_symbol_1_clk",
+ .parent_hws = (const struct clk_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 = 0x83024,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x83024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_tx_symbol_0_clk",
+ .parent_hws = (const struct clk_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 = 0x83064,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x83064,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x83064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ufs_phy_unipro_core_clk",
+ .parent_hws = (const struct clk_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_usb20_master_clk = {
+ .halt_reg = 0x1c018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1c018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb20_master_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb20_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_mock_utmi_clk = {
+ .halt_reg = 0x1c024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1c024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb20_mock_utmi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_usb20_mock_utmi_postdiv_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_sleep_clk = {
+ .halt_reg = 0x1c020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1c020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb20_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_master_clk = {
+ .halt_reg = 0x1b018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_master_clk",
+ .parent_hws = (const struct clk_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 = 0x1b024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_clk",
+ .parent_hws = (const struct clk_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 = 0x1b020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x1b05c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b05c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x1b060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_com_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x1b064,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x1b064,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x1b064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_pipe_clk",
+ .parent_hws = (const struct clk_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_usb_clkref_en = {
+ .halt_reg = 0x97468,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x97468,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb_clkref_en",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_axi0_clk = {
+ .halt_reg = 0x34014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x34014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x34014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_axi0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_axi1_clk = {
+ .halt_reg = 0x3401c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3401c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3401c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_axi1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc gcc_emac0_gdsc = {
+ .gdscr = 0xb6004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_emac0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gcc_pcie_0_gdsc = {
+ .gdscr = 0xa9004,
+ .collapse_ctrl = 0x4b104,
+ .collapse_mask = BIT(0),
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_pcie_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE | POLL_CFG_GDSCR,
+};
+
+static struct gdsc gcc_pcie_1_gdsc = {
+ .gdscr = 0x77004,
+ .collapse_ctrl = 0x4b104,
+ .collapse_mask = BIT(1),
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_pcie_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE | POLL_CFG_GDSCR,
+};
+
+static struct gdsc gcc_ufs_phy_gdsc = {
+ .gdscr = 0x83004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_ufs_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR,
+};
+
+static struct gdsc gcc_usb20_prim_gdsc = {
+ .gdscr = 0x1c004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_usb20_prim_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR,
+};
+
+static struct gdsc gcc_usb30_prim_gdsc = {
+ .gdscr = 0x1b004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gcc_usb30_prim_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR,
+};
+
+static struct clk_regmap *gcc_qcs8300_clocks[] = {
+ [GCC_AGGRE_NOC_QUPV3_AXI_CLK] = &gcc_aggre_noc_qupv3_axi_clk.clkr,
+ [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr,
+ [GCC_AGGRE_USB2_PRIM_AXI_CLK] = &gcc_aggre_usb2_prim_axi_clk.clkr,
+ [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr,
+ [GCC_AHB2PHY0_CLK] = &gcc_ahb2phy0_clk.clkr,
+ [GCC_AHB2PHY2_CLK] = &gcc_ahb2phy2_clk.clkr,
+ [GCC_AHB2PHY3_CLK] = &gcc_ahb2phy3_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_CAMERA_THROTTLE_XO_CLK] = &gcc_camera_throttle_xo_clk.clkr,
+ [GCC_CFG_NOC_USB2_PRIM_AXI_CLK] = &gcc_cfg_noc_usb2_prim_axi_clk.clkr,
+ [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr,
+ [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr,
+ [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr,
+ [GCC_EDP_REF_CLKREF_EN] = &gcc_edp_ref_clkref_en.clkr,
+ [GCC_EMAC0_AXI_CLK] = &gcc_emac0_axi_clk.clkr,
+ [GCC_EMAC0_PHY_AUX_CLK] = &gcc_emac0_phy_aux_clk.clkr,
+ [GCC_EMAC0_PHY_AUX_CLK_SRC] = &gcc_emac0_phy_aux_clk_src.clkr,
+ [GCC_EMAC0_PTP_CLK] = &gcc_emac0_ptp_clk.clkr,
+ [GCC_EMAC0_PTP_CLK_SRC] = &gcc_emac0_ptp_clk_src.clkr,
+ [GCC_EMAC0_RGMII_CLK] = &gcc_emac0_rgmii_clk.clkr,
+ [GCC_EMAC0_RGMII_CLK_SRC] = &gcc_emac0_rgmii_clk_src.clkr,
+ [GCC_EMAC0_SLV_AHB_CLK] = &gcc_emac0_slv_ahb_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_GP4_CLK] = &gcc_gp4_clk.clkr,
+ [GCC_GP4_CLK_SRC] = &gcc_gp4_clk_src.clkr,
+ [GCC_GP5_CLK] = &gcc_gp5_clk.clkr,
+ [GCC_GP5_CLK_SRC] = &gcc_gp5_clk_src.clkr,
+ [GCC_GPLL0] = &gcc_gpll0.clkr,
+ [GCC_GPLL0_OUT_EVEN] = &gcc_gpll0_out_even.clkr,
+ [GCC_GPLL1] = &gcc_gpll1.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_CENTER_PIPELINE_CLK] = &gcc_gpu_memnoc_gfx_center_pipeline_clk.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_GPU_TCU_THROTTLE_AHB_CLK] = &gcc_gpu_tcu_throttle_ahb_clk.clkr,
+ [GCC_GPU_TCU_THROTTLE_CLK] = &gcc_gpu_tcu_throttle_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_AUX_CLK] = &gcc_pcie_0_phy_aux_clk.clkr,
+ [GCC_PCIE_0_PHY_AUX_CLK_SRC] = &gcc_pcie_0_phy_aux_clk_src.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_PIPE_DIV_CLK_SRC] = &gcc_pcie_0_pipe_div_clk_src.clkr,
+ [GCC_PCIE_0_PIPEDIV2_CLK] = &gcc_pcie_0_pipediv2_clk.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_PIPE_DIV_CLK_SRC] = &gcc_pcie_1_pipe_div_clk_src.clkr,
+ [GCC_PCIE_1_PIPEDIV2_CLK] = &gcc_pcie_1_pipediv2_clk.clkr,
+ [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr,
+ [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = &gcc_pcie_1_slv_q2a_axi_clk.clkr,
+ [GCC_PCIE_CLKREF_EN] = &gcc_pcie_clkref_en.clkr,
+ [GCC_PCIE_THROTTLE_CFG_CLK] = &gcc_pcie_throttle_cfg_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_DISP_ROT_AHB_CLK] = &gcc_qmip_disp_rot_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_CVP_AHB_CLK] = &gcc_qmip_video_cvp_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_VCPU_AHB_CLK] = &gcc_qmip_video_vcpu_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.clkr,
+ [GCC_QUPV3_WRAP0_S6_CLK_SRC] = &gcc_qupv3_wrap0_s6_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.clkr,
+ [GCC_QUPV3_WRAP0_S7_CLK_SRC] = &gcc_qupv3_wrap0_s7_clk_src.clkr,
+ [GCC_QUPV3_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_WRAP3_CORE_2X_CLK] = &gcc_qupv3_wrap3_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP3_CORE_CLK] = &gcc_qupv3_wrap3_core_clk.clkr,
+ [GCC_QUPV3_WRAP3_QSPI_CLK] = &gcc_qupv3_wrap3_qspi_clk.clkr,
+ [GCC_QUPV3_WRAP3_S0_CLK] = &gcc_qupv3_wrap3_s0_clk.clkr,
+ [GCC_QUPV3_WRAP3_S0_CLK_SRC] = &gcc_qupv3_wrap3_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP3_S0_DIV_CLK_SRC] = &gcc_qupv3_wrap3_s0_div_clk_src.clkr,
+ [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
+ [GCC_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_3_M_AHB_CLK] = &gcc_qupv3_wrap_3_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_3_S_AHB_CLK] = &gcc_qupv3_wrap_3_s_ahb_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr,
+ [GCC_SGMI_CLKREF_EN] = &gcc_sgmi_clkref_en.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_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_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_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_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr,
+ [GCC_USB20_MASTER_CLK_SRC] = &gcc_usb20_master_clk_src.clkr,
+ [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr,
+ [GCC_USB20_MOCK_UTMI_CLK_SRC] = &gcc_usb20_mock_utmi_clk_src.clkr,
+ [GCC_USB20_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb20_mock_utmi_postdiv_clk_src.clkr,
+ [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_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_USB_CLKREF_EN] = &gcc_usb_clkref_en.clkr,
+ [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr,
+ [GCC_VIDEO_AXI1_CLK] = &gcc_video_axi1_clk.clkr,
+};
+
+static struct gdsc *gcc_qcs8300_gdscs[] = {
+ [GCC_EMAC0_GDSC] = &gcc_emac0_gdsc,
+ [GCC_PCIE_0_GDSC] = &gcc_pcie_0_gdsc,
+ [GCC_PCIE_1_GDSC] = &gcc_pcie_1_gdsc,
+ [GCC_UFS_PHY_GDSC] = &gcc_ufs_phy_gdsc,
+ [GCC_USB20_PRIM_GDSC] = &gcc_usb20_prim_gdsc,
+ [GCC_USB30_PRIM_GDSC] = &gcc_usb30_prim_gdsc,
+};
+
+static const struct qcom_reset_map gcc_qcs8300_resets[] = {
+ [GCC_EMAC0_BCR] = { 0xb6000 },
+ [GCC_PCIE_0_BCR] = { 0xa9000 },
+ [GCC_PCIE_0_LINK_DOWN_BCR] = { 0xbf000 },
+ [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0xbf008 },
+ [GCC_PCIE_0_PHY_BCR] = { 0xa9144 },
+ [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0xbf00c },
+ [GCC_PCIE_1_BCR] = { 0x77000 },
+ [GCC_PCIE_1_LINK_DOWN_BCR] = { 0xae084 },
+ [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0xae090 },
+ [GCC_PCIE_1_PHY_BCR] = { 0xae08c },
+ [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0xae094 },
+ [GCC_SDCC1_BCR] = { 0x20000 },
+ [GCC_UFS_PHY_BCR] = { 0x83000 },
+ [GCC_USB20_PRIM_BCR] = { 0x1c000 },
+ [GCC_USB2_PHY_PRIM_BCR] = { 0x5c01c },
+ [GCC_USB2_PHY_SEC_BCR] = { 0x5c020 },
+ [GCC_USB30_PRIM_BCR] = { 0x1b000 },
+ [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x5c008 },
+ [GCC_USB3_PHY_PRIM_BCR] = { 0x5c000 },
+ [GCC_USB3_PHY_TERT_BCR] = { 0x5c024 },
+ [GCC_USB3_UNIPHY_MP0_BCR] = { 0x5c00c },
+ [GCC_USB3_UNIPHY_MP1_BCR] = { 0x5c010 },
+ [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x5c004 },
+ [GCC_USB3UNIPHY_PHY_MP0_BCR] = { 0x5c014 },
+ [GCC_USB3UNIPHY_PHY_MP1_BCR] = { 0x5c018 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x76000 },
+ [GCC_VIDEO_AXI0_CLK_ARES] = { 0x34014, 2 },
+ [GCC_VIDEO_AXI1_CLK_ARES] = { 0x3401c, 2 },
+ [GCC_VIDEO_BCR] = { 0x34000 },
+};
+
+static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_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_wrap3_s0_clk_src),
+};
+
+static const struct regmap_config gcc_qcs8300_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x472cffc,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_qcs8300_desc = {
+ .config = &gcc_qcs8300_regmap_config,
+ .clks = gcc_qcs8300_clocks,
+ .num_clks = ARRAY_SIZE(gcc_qcs8300_clocks),
+ .resets = gcc_qcs8300_resets,
+ .num_resets = ARRAY_SIZE(gcc_qcs8300_resets),
+ .gdscs = gcc_qcs8300_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_qcs8300_gdscs),
+};
+
+static const struct of_device_id gcc_qcs8300_match_table[] = {
+ { .compatible = "qcom,qcs8300-gcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_qcs8300_match_table);
+
+static int gcc_qcs8300_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = qcom_cc_map(pdev, &gcc_qcs8300_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
+ ARRAY_SIZE(gcc_dfs_clocks));
+ if (ret)
+ return ret;
+
+ /* Keep some clocks always enabled */
+ qcom_branch_set_clk_en(regmap, 0x32004); /* GCC_CAMERA_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x32020); /* GCC_CAMERA_XO_CLK */
+ qcom_branch_set_clk_en(regmap, 0x33004); /* GCC_DISP_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x33018); /* GCC_DISP_XO_CLK */
+ qcom_branch_set_clk_en(regmap, 0x7d004); /* GCC_GPU_CFG_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x34004); /* GCC_VIDEO_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x34024); /* GCC_VIDEO_XO_CLK */
+
+ /* FORCE_MEM_CORE_ON for ufs phy ice core clocks */
+ qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true);
+
+ return qcom_cc_really_probe(&pdev->dev, &gcc_qcs8300_desc, regmap);
+}
+
+static struct platform_driver gcc_qcs8300_driver = {
+ .probe = gcc_qcs8300_probe,
+ .driver = {
+ .name = "gcc-qcs8300",
+ .of_match_table = gcc_qcs8300_match_table,
+ },
+};
+
+static int __init gcc_qcs8300_init(void)
+{
+ return platform_driver_register(&gcc_qcs8300_driver);
+}
+subsys_initcall(gcc_qcs8300_init);
+
+static void __exit gcc_qcs8300_exit(void)
+{
+ platform_driver_unregister(&gcc_qcs8300_driver);
+}
+module_exit(gcc_qcs8300_exit);
+
+MODULE_DESCRIPTION("QTI GCC QCS8300 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gcc-sar2130p.c b/drivers/clk/qcom/gcc-sar2130p.c
new file mode 100644
index 000000000000..475e2cda3618
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sar2130p.c
@@ -0,0 +1,2366 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021-2023, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sar2130p-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"
+
+/* Need to match the order of clocks in DT binding */
+enum {
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+
+ DT_PCIE_0_PIPE,
+ DT_PCIE_1_PIPE,
+
+ DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE,
+};
+
+enum {
+ P_BI_TCXO,
+ P_GCC_GPLL0_OUT_EVEN,
+ P_GCC_GPLL0_OUT_MAIN,
+ P_GCC_GPLL1_OUT_EVEN,
+ P_GCC_GPLL1_OUT_MAIN,
+ P_GCC_GPLL4_OUT_MAIN,
+ P_GCC_GPLL5_OUT_MAIN,
+ P_GCC_GPLL7_OUT_MAIN,
+ P_GCC_GPLL9_OUT_EVEN,
+ P_PCIE_0_PIPE_CLK,
+ P_PCIE_1_PIPE_CLK,
+ P_SLEEP_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 = 0x62018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = &(const struct clk_init_data) {
+ .name = "gcc_gpll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll1 = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll1",
+ .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_gpll4 = {
+ .offset = 0x4000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(4),
+ .hw.init = &(const 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_gpll5 = {
+ .offset = 0x5000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(5),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll5",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll7 = {
+ .offset = 0x7000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(7),
+ .hw.init = &(const 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 = 0x62018,
+ .enable_mask = BIT(9),
+ .hw.init = &(const 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 clk_div_table post_div_table_gcc_gpll9_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gcc_gpll9_out_even = {
+ .offset = 0x9000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_gcc_gpll9_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_gcc_gpll9_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpll9_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll9.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_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_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL7_OUT_MAIN, 2 },
+ { P_GCC_GPLL5_OUT_MAIN, 3 },
+ { P_GCC_GPLL1_OUT_MAIN, 4 },
+ { P_GCC_GPLL4_OUT_MAIN, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll7.clkr.hw },
+ { .hw = &gcc_gpll5.clkr.hw },
+ { .hw = &gcc_gpll1.clkr.hw },
+ { .hw = &gcc_gpll4.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL9_OUT_EVEN, 2 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll9_out_even.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_7[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL1_OUT_EVEN, 2 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_7[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll1.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_8[] = {
+ { .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 = 0x7b070,
+ .clkr = {
+ .hw.init = &(const 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_phy_mux gcc_pcie_1_pipe_clk_src = {
+ .reg = 0x9d06c,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_PCIE_1_PIPE,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_usb3_prim_phy_pipe_clk_src = {
+ .reg = 0x4906c,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_8,
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_pipe_clk_src",
+ .parent_data = gcc_parent_data_8,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_8),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ddrss_spad_clk_src[] = {
+ F(300000000, P_GCC_GPLL0_OUT_EVEN, 1, 0, 0),
+ F(403000000, P_GCC_GPLL4_OUT_MAIN, 2, 0, 0),
+ F(426400000, P_GCC_GPLL1_OUT_MAIN, 2.5, 0, 0),
+ F(500000000, P_GCC_GPLL7_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ddrss_spad_clk_src = {
+ .cmd_rcgr = 0x70004,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_ddrss_spad_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ddrss_spad_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_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 = 0x74004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+ .cmd_rcgr = 0x75004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+ .cmd_rcgr = 0x76004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .ops = &clk_rcg2_shared_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 = 0x7b074,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_aux_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_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 = 0x7b058,
+ .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 = &(const 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),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_1_aux_clk_src = {
+ .cmd_rcgr = 0x9d070,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_aux_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = {
+ .cmd_rcgr = 0x9d054,
+ .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 = &(const 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),
+ .ops = &clk_rcg2_shared_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 = 0x43010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
+ F(7372800, P_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(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_wrap0_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
+ .cmd_rcgr = 0x28018,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s1_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(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_wrap0_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
+ .cmd_rcgr = 0x28150,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
+ .cmd_rcgr = 0x28288,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
+ .cmd_rcgr = 0x283c0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
+ .cmd_rcgr = 0x284f8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap0_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
+ .cmd_rcgr = 0x28630,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
+};
+
+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),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
+ .cmd_rcgr = 0x2e018,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_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),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
+ .cmd_rcgr = 0x2e150,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
+};
+
+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),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
+ .cmd_rcgr = 0x2e288,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
+ .cmd_rcgr = 0x2e3c0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
+ .cmd_rcgr = 0x2e4f8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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),
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = {
+ .cmd_rcgr = 0x2e630,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
+ F(144000, P_BI_TCXO, 16, 3, 25),
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(20000000, P_GCC_GPLL0_OUT_EVEN, 5, 1, 3),
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(192000000, P_GCC_GPLL9_OUT_EVEN, 2, 0, 0),
+ F(384000000, P_GCC_GPLL9_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x26018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_6,
+ .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk_src",
+ .parent_data = gcc_parent_data_6,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_6),
+ .ops = &clk_rcg2_shared_floor_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = {
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(150000000, P_GCC_GPLL0_OUT_EVEN, 2, 0, 0),
+ F(300000000, P_GCC_GPLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x2603c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_7,
+ .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk_src",
+ .parent_data = gcc_parent_data_7,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_7),
+ .ops = &clk_rcg2_shared_floor_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),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_master_clk_src = {
+ .cmd_rcgr = 0x4902c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src,
+ .clkr.hw.init = &(const 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),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x49044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(const 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),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
+ .cmd_rcgr = 0x49070,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = {
+ .reg = 0x4905c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src",
+ .parent_hws = (const struct clk_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_1_axi_clk = {
+ .halt_reg = 0x7b094,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x7b094,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(17),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_noc_pcie_1_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_usb3_prim_axi_clk = {
+ .halt_reg = 0x4908c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x4908c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4908c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_aggre_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_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 = 0x48004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x48004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(10),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_pcie_anoc_ahb_clk = {
+ .halt_reg = 0x20034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x20034,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(20),
+ .hw.init = &(const 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 = 0x49088,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x49088,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x49088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_cfg_noc_usb3_prim_axi_clk",
+ .parent_hws = (const struct clk_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_ddrss_gpu_axi_clk = {
+ .halt_reg = 0x81154,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x81154,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x81154,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ddrss_gpu_axi_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ddrss_pcie_sf_clk = {
+ .halt_reg = 0x9d098,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x9d098,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(19),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ddrss_pcie_sf_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ddrss_spad_clk = {
+ .halt_reg = 0x70000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x70000,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x70000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_ddrss_spad_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ddrss_spad_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_hf_axi_clk = {
+ .halt_reg = 0x37008,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x37008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x37008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_disp_hf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x74000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x74000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x75000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x76000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gp3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(15),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_gpll0_clk_src",
+ .parent_hws = (const struct clk_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 = 0x62000,
+ .enable_mask = BIT(16),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_gpll0_div_clk_src",
+ .parent_hws = (const struct clk_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 = 0x9b010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x9b010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x9b010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x9b018,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x9b018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_gpu_snoc_dvm_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_iris_ss_hf_axi1_clk = {
+ .halt_reg = 0x42030,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x42030,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_iris_ss_hf_axi1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_iris_ss_spd_axi1_clk = {
+ .halt_reg = 0x70020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x70020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x70020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_iris_ss_spd_axi1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_ddrss_spad_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+ .halt_reg = 0x7b03c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(3),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x7b038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7b038,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(2),
+ .hw.init = &(const 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 = 0x7b02c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x7b02c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(1),
+ .hw.init = &(const 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 = 0x7b054,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_phy_rchng_clk",
+ .parent_hws = (const struct clk_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 = 0x7b048,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_0_pipe_clk",
+ .parent_hws = (const struct clk_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 = 0x7b020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7b020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x7b01c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(5),
+ .hw.init = &(const 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 = 0x9d038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(29),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x9d034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x9d034,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(28),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+ .halt_reg = 0x9d028,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x9d028,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(27),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_phy_rchng_clk = {
+ .halt_reg = 0x9d050,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(23),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_phy_rchng_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_phy_rchng_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+ .halt_reg = 0x9d044,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(30),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_pipe_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pcie_1_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_slv_axi_clk = {
+ .halt_reg = 0x9d01c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x9d01c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pcie_1_slv_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_slv_q2a_axi_clk = {
+ .halt_reg = 0x9d018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(25),
+ .hw.init = &(const 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 = 0x4300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_pdm2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x43004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x43004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x43004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+ .halt_reg = 0x43008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x43008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_pdm_xo4_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_gpu_ahb_clk = {
+ .halt_reg = 0x9b008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x9b008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x9b008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x7b018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x7b018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62000,
+ .enable_mask = BIT(11),
+ .hw.init = &(const 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 = 0x42014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x42014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x42008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x42008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_video_cvp_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_lsr_ahb_clk = {
+ .halt_reg = 0x4204c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x4204c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4204c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_video_lsr_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_v_cpu_ahb_clk = {
+ .halt_reg = 0x42010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x42010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x4200c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x4200c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x4200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qmip_video_vcodec_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = {
+ .halt_reg = 0x33034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(18),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_core_clk = {
+ .halt_reg = 0x33024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(19),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s0_clk = {
+ .halt_reg = 0x2800c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(22),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s1_clk = {
+ .halt_reg = 0x28144,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(23),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s2_clk = {
+ .halt_reg = 0x2827c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(24),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s3_clk = {
+ .halt_reg = 0x283b4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(25),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s4_clk = {
+ .halt_reg = 0x284ec,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(26),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap0_s5_clk = {
+ .halt_reg = 0x28624,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(27),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap0_s5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_qupv3_wrap0_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = {
+ .halt_reg = 0x3317c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(3),
+ .hw.init = &(const 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 = 0x3316c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x2e00c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(4),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s0_clk",
+ .parent_hws = (const struct clk_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 = 0x2e144,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(5),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s1_clk",
+ .parent_hws = (const struct clk_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 = 0x2e27c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(6),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s2_clk",
+ .parent_hws = (const struct clk_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 = 0x2e3b4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(7),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s3_clk",
+ .parent_hws = (const struct clk_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 = 0x2e4ec,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(8),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s4_clk",
+ .parent_hws = (const struct clk_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 = 0x2e624,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(9),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap1_s5_clk",
+ .parent_hws = (const struct clk_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_wrap_0_m_ahb_clk = {
+ .halt_reg = 0x28004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x28004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(20),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = {
+ .halt_reg = 0x28008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x28008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62008,
+ .enable_mask = BIT(21),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_0_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = {
+ .halt_reg = 0x2e004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2e004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(2),
+ .hw.init = &(const 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 = 0x2e008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2e008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x62010,
+ .enable_mask = BIT(1),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_qupv3_wrap_1_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x26010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26010,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x26004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x26030,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x26030,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x26030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_sdcc1_ice_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 = 0x49018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_master_clk",
+ .parent_hws = (const struct clk_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 = 0x49028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49028,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_clk",
+ .parent_hws = (const struct clk_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 = 0x49024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const 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 = 0x49060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x49064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x49064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_com_aux_clk",
+ .parent_hws = (const struct clk_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 = 0x49068,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x49068,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x49068,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_usb3_prim_phy_pipe_clk",
+ .parent_hws = (const struct clk_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 = 0x42018,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x42018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_axi0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_axi1_clk = {
+ .halt_reg = 0x42024,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x42024,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x42024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gcc_video_axi1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_hf0_gdsc = {
+ .gdscr = 0x8d204,
+ .pd = {
+ .name = "hlos1_vote_mm_snoc_mmu_tbu_hf0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_sf0_gdsc = {
+ .gdscr = 0x8d054,
+ .pd = {
+ .name = "hlos1_vote_mm_snoc_mmu_tbu_sf0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc hlos1_vote_turing_mmu_tbu0_gdsc = {
+ .gdscr = 0x8d05c,
+ .pd = {
+ .name = "hlos1_vote_turing_mmu_tbu0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc hlos1_vote_turing_mmu_tbu1_gdsc = {
+ .gdscr = 0x8d060,
+ .pd = {
+ .name = "hlos1_vote_turing_mmu_tbu1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc pcie_0_gdsc = {
+ .gdscr = 0x7b004,
+ .collapse_ctrl = 0x62200,
+ .collapse_mask = BIT(0),
+ .pd = {
+ .name = "pcie_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc pcie_0_phy_gdsc = {
+ .gdscr = 0x7c000,
+ .collapse_ctrl = 0x62200,
+ .collapse_mask = BIT(3),
+ .pd = {
+ .name = "pcie_0_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc pcie_1_gdsc = {
+ .gdscr = 0x9d004,
+ .collapse_ctrl = 0x62200,
+ .collapse_mask = BIT(1),
+ .pd = {
+ .name = "pcie_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc pcie_1_phy_gdsc = {
+ .gdscr = 0x9e000,
+ .collapse_ctrl = 0x62200,
+ .collapse_mask = BIT(4),
+ .pd = {
+ .name = "pcie_1_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc usb30_prim_gdsc = {
+ .gdscr = 0x49004,
+ .pd = {
+ .name = "usb30_prim_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct gdsc usb3_phy_gdsc = {
+ .gdscr = 0x60018,
+ .pd = {
+ .name = "usb3_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *gcc_sar2130p_clocks[] = {
+ [GCC_AGGRE_NOC_PCIE_1_AXI_CLK] = &gcc_aggre_noc_pcie_1_axi_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_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_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr,
+ [GCC_DDRSS_PCIE_SF_CLK] = &gcc_ddrss_pcie_sf_clk.clkr,
+ [GCC_DDRSS_SPAD_CLK] = &gcc_ddrss_spad_clk.clkr,
+ [GCC_DDRSS_SPAD_CLK_SRC] = &gcc_ddrss_spad_clk_src.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_GPLL1] = &gcc_gpll1.clkr,
+ [GCC_GPLL4] = &gcc_gpll4.clkr,
+ [GCC_GPLL5] = &gcc_gpll5.clkr,
+ [GCC_GPLL7] = &gcc_gpll7.clkr,
+ [GCC_GPLL9] = &gcc_gpll9.clkr,
+ [GCC_GPLL9_OUT_EVEN] = &gcc_gpll9_out_even.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_IRIS_SS_HF_AXI1_CLK] = &gcc_iris_ss_hf_axi1_clk.clkr,
+ [GCC_IRIS_SS_SPD_AXI1_CLK] = &gcc_iris_ss_spd_axi1_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_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_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_LSR_AHB_CLK] = &gcc_qmip_video_lsr_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_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr,
+ [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr,
+ [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr,
+ [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr,
+ [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr,
+ [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr,
+ [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr,
+ [GCC_QUPV3_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_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
+ [GCC_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_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.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_sar2130p_resets[] = {
+ [GCC_DISPLAY_BCR] = { 0x37000 },
+ [GCC_GPU_BCR] = { 0x9b000 },
+ [GCC_PCIE_0_BCR] = { 0x7b000 },
+ [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x7c014 },
+ [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0x7c020 },
+ [GCC_PCIE_0_PHY_BCR] = { 0x7c01c },
+ [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0x7c028 },
+ [GCC_PCIE_1_BCR] = { 0x9d000 },
+ [GCC_PCIE_1_LINK_DOWN_BCR] = { 0x9e014 },
+ [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0x9e020 },
+ [GCC_PCIE_1_PHY_BCR] = { 0x9e01c },
+ [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0x9e024 },
+ [GCC_PCIE_PHY_BCR] = { 0x7f000 },
+ [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x7f00c },
+ [GCC_PCIE_PHY_COM_BCR] = { 0x7f010 },
+ [GCC_PDM_BCR] = { 0x43000 },
+ [GCC_QUPV3_WRAPPER_0_BCR] = { 0x28000 },
+ [GCC_QUPV3_WRAPPER_1_BCR] = { 0x2e000 },
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x22000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x22004 },
+ [GCC_SDCC1_BCR] = { 0x26000 },
+ [GCC_USB30_PRIM_BCR] = { 0x49000 },
+ [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x60008 },
+ [GCC_USB3_DP_PHY_SEC_BCR] = { 0x60014 },
+ [GCC_USB3_PHY_PRIM_BCR] = { 0x60000 },
+ [GCC_USB3_PHY_SEC_BCR] = { 0x6000c },
+ [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x60004 },
+ [GCC_USB3PHY_PHY_SEC_BCR] = { 0x60010 },
+ [GCC_VIDEO_AXI0_CLK_ARES] = { .reg = 0x42018, .bit = 2, .udelay = 1000 },
+ [GCC_VIDEO_AXI1_CLK_ARES] = { .reg = 0x42024, .bit = 2, .udelay = 1000 },
+ [GCC_VIDEO_BCR] = { 0x42000 },
+ [GCC_IRIS_SS_HF_AXI_CLK_ARES] = { .reg = 0x42030, .bit = 2 },
+ [GCC_IRIS_SS_SPD_AXI_CLK_ARES] = { .reg = 0x70020, .bit = 2 },
+ [GCC_DDRSS_SPAD_CLK_ARES] = { .reg = 0x70000, .bit = 2 },
+};
+
+static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_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),
+};
+
+static struct gdsc *gcc_sar2130p_gdscs[] = {
+ [HLOS1_VOTE_MM_SNOC_MMU_TBU_HF0_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_hf0_gdsc,
+ [HLOS1_VOTE_MM_SNOC_MMU_TBU_SF0_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_sf0_gdsc,
+ [HLOS1_VOTE_TURING_MMU_TBU0_GDSC] = &hlos1_vote_turing_mmu_tbu0_gdsc,
+ [HLOS1_VOTE_TURING_MMU_TBU1_GDSC] = &hlos1_vote_turing_mmu_tbu1_gdsc,
+ [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,
+ [USB30_PRIM_GDSC] = &usb30_prim_gdsc,
+ [USB3_PHY_GDSC] = &usb3_phy_gdsc,
+};
+
+static const struct regmap_config gcc_sar2130p_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1f1030,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_sar2130p_desc = {
+ .config = &gcc_sar2130p_regmap_config,
+ .clks = gcc_sar2130p_clocks,
+ .num_clks = ARRAY_SIZE(gcc_sar2130p_clocks),
+ .resets = gcc_sar2130p_resets,
+ .num_resets = ARRAY_SIZE(gcc_sar2130p_resets),
+ .gdscs = gcc_sar2130p_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_sar2130p_gdscs),
+};
+
+static const struct of_device_id gcc_sar2130p_match_table[] = {
+ { .compatible = "qcom,sar2130p-gcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_sar2130p_match_table);
+
+static int gcc_sar2130p_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = qcom_cc_map(pdev, &gcc_sar2130p_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
+ ARRAY_SIZE(gcc_dfs_clocks));
+ if (ret)
+ return ret;
+
+ /* Keep some clocks always-on */
+ qcom_branch_set_clk_en(regmap, 0x37004); /* GCC_DISP_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x42004); /* GCC_VIDEO_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x42028); /* GCC_VIDEO_XO_CLK */
+ qcom_branch_set_clk_en(regmap, 0x9b004); /* GCC_GPU_CFG_AHB_CLK */
+
+ /* Clear GDSC_SLEEP_ENA_VOTE to stop votes being auto-removed in sleep. */
+ regmap_write(regmap, 0x62204, 0x0);
+
+ return qcom_cc_really_probe(&pdev->dev, &gcc_sar2130p_desc, regmap);
+}
+
+static struct platform_driver gcc_sar2130p_driver = {
+ .probe = gcc_sar2130p_probe,
+ .driver = {
+ .name = "gcc-sar2130p",
+ .of_match_table = gcc_sar2130p_match_table,
+ },
+};
+
+static int __init gcc_sar2130p_init(void)
+{
+ return platform_driver_register(&gcc_sar2130p_driver);
+}
+subsys_initcall(gcc_sar2130p_init);
+
+static void __exit gcc_sar2130p_exit(void)
+{
+ platform_driver_unregister(&gcc_sar2130p_driver);
+}
+module_exit(gcc_sar2130p_exit);
+
+MODULE_DESCRIPTION("QTI GCC SAR2130P Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gcc-sm8450.c b/drivers/clk/qcom/gcc-sm8450.c
index c445c271678a..65d7d52bce03 100644
--- a/drivers/clk/qcom/gcc-sm8450.c
+++ b/drivers/clk/qcom/gcc-sm8450.c
@@ -26,6 +26,8 @@ enum {
P_BI_TCXO,
P_GCC_GPLL0_OUT_EVEN,
P_GCC_GPLL0_OUT_MAIN,
+ P_SM8475_GCC_GPLL2_OUT_EVEN,
+ P_SM8475_GCC_GPLL3_OUT_EVEN,
P_GCC_GPLL4_OUT_MAIN,
P_GCC_GPLL9_OUT_MAIN,
P_PCIE_1_PHY_AUX_CLK,
@@ -36,6 +38,15 @@ enum {
P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK,
};
+static struct clk_init_data sm8475_gcc_gpll0_init = {
+ .name = "gcc_gpll0",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+};
+
static struct clk_alpha_pll gcc_gpll0 = {
.offset = 0x0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
@@ -53,6 +64,15 @@ static struct clk_alpha_pll gcc_gpll0 = {
},
};
+static struct clk_init_data sm8475_gcc_gpll0_out_even_init = {
+ .name = "gcc_gpll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+};
+
static const struct clk_div_table post_div_table_gcc_gpll0_out_even[] = {
{ 0x1, 2 },
{ }
@@ -75,6 +95,49 @@ static struct clk_alpha_pll_postdiv gcc_gpll0_out_even = {
},
};
+static struct clk_alpha_pll sm8475_gcc_gpll2 = {
+ .offset = 0x2000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpll2",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll sm8475_gcc_gpll3 = {
+ .offset = 0x3000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x62018,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpll3",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+ },
+ },
+};
+
+static struct clk_init_data sm8475_gcc_gpll4_init = {
+ .name = "gcc_gpll4",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "bi_tcxo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_fixed_lucid_ole_ops,
+};
+
static struct clk_alpha_pll gcc_gpll4 = {
.offset = 0x4000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
@@ -92,6 +155,15 @@ static struct clk_alpha_pll gcc_gpll4 = {
},
};
+static struct clk_init_data sm8475_gcc_gpll9_init = {
+ .name = "gcc_gpll9",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "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_EVO],
@@ -153,6 +225,22 @@ static const struct clk_parent_data gcc_parent_data_3[] = {
{ .fw_name = "bi_tcxo" },
};
+static const struct parent_map sm8475_gcc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_SM8475_GCC_GPLL2_OUT_EVEN, 2 },
+ { P_SM8475_GCC_GPLL3_OUT_EVEN, 3 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data sm8475_gcc_parent_data_3[] = {
+ { .fw_name = "bi_tcxo" },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &sm8475_gcc_gpll2.clkr.hw },
+ { .hw = &sm8475_gcc_gpll3.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
static const struct parent_map gcc_parent_map_5[] = {
{ P_PCIE_1_PHY_AUX_CLK, 0 },
{ P_BI_TCXO, 2 },
@@ -915,6 +1003,16 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s6_clk_src = {
.clkr.hw.init = &gcc_qupv3_wrap2_s6_clk_src_init,
};
+static const struct freq_tbl sm8475_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(37000000, P_GCC_GPLL9_OUT_MAIN, 16, 0, 0),
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(148000000, P_GCC_GPLL9_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
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),
@@ -963,6 +1061,25 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = {
},
};
+static const struct freq_tbl sm8475_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),
+ F(600000000, P_GCC_GPLL0_OUT_MAIN, 1, 0, 0),
+ F(806400000, P_SM8475_GCC_GPLL2_OUT_EVEN, 1, 0, 0),
+ F(850000000, P_SM8475_GCC_GPLL2_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_init_data sm8475_gcc_ufs_phy_axi_clk_src_init = {
+ .name = "gcc_ufs_phy_axi_clk_src",
+ .parent_data = sm8475_gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(sm8475_gcc_parent_map_3),
+ .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),
@@ -987,6 +1104,24 @@ static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = {
},
};
+static const struct freq_tbl sm8475_ftbl_gcc_ufs_phy_ice_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),
+ F(600000000, P_GCC_GPLL0_OUT_MAIN, 1, 0, 0),
+ F(806400000, P_SM8475_GCC_GPLL2_OUT_EVEN, 1, 0, 0),
+ F(850000000, P_SM8475_GCC_GPLL2_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_init_data sm8475_gcc_ufs_phy_ice_core_clk_src_init = {
+ .name = "gcc_ufs_phy_ice_core_clk_src",
+ .parent_data = sm8475_gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(sm8475_gcc_parent_map_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = {
F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0),
@@ -1032,6 +1167,14 @@ static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = {
},
};
+static struct clk_init_data sm8475_gcc_ufs_phy_unipro_core_clk_src_init = {
+ .name = "gcc_ufs_phy_unipro_core_clk_src",
+ .parent_data = sm8475_gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(sm8475_gcc_parent_map_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = {
.cmd_rcgr = 0x8708c,
.mnd_width = 0,
@@ -3166,6 +3309,8 @@ static struct clk_regmap *gcc_sm8450_clocks[] = {
[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,
+ [SM8475_GCC_GPLL2] = NULL,
+ [SM8475_GCC_GPLL3] = NULL,
};
static const struct qcom_reset_map gcc_sm8450_resets[] = {
@@ -3259,6 +3404,7 @@ static const struct qcom_cc_desc gcc_sm8450_desc = {
static const struct of_device_id gcc_sm8450_match_table[] = {
{ .compatible = "qcom,gcc-sm8450" },
+ { .compatible = "qcom,sm8475-gcc" },
{ }
};
MODULE_DEVICE_TABLE(of, gcc_sm8450_match_table);
@@ -3277,6 +3423,39 @@ static int gcc_sm8450_probe(struct platform_device *pdev)
if (ret)
return ret;
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8475-gcc")) {
+ /* Update GCC PLL0 */
+ gcc_gpll0.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ gcc_gpll0.clkr.hw.init = &sm8475_gcc_gpll0_init;
+ gcc_gpll0_out_even.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ gcc_gpll0_out_even.clkr.hw.init = &sm8475_gcc_gpll0_out_even_init;
+
+ /* Update GCC PLL4 */
+ gcc_gpll4.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ gcc_gpll4.clkr.hw.init = &sm8475_gcc_gpll4_init;
+
+ /* Update GCC PLL9 */
+ gcc_gpll9.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+ gcc_gpll9.clkr.hw.init = &sm8475_gcc_gpll9_init;
+
+ gcc_sdcc2_apps_clk_src.freq_tbl = sm8475_ftbl_gcc_sdcc2_apps_clk_src;
+
+ gcc_ufs_phy_axi_clk_src.parent_map = sm8475_gcc_parent_map_3;
+ gcc_ufs_phy_axi_clk_src.freq_tbl = sm8475_ftbl_gcc_ufs_phy_axi_clk_src;
+ gcc_ufs_phy_axi_clk_src.clkr.hw.init = &sm8475_gcc_ufs_phy_axi_clk_src_init;
+
+ gcc_ufs_phy_ice_core_clk_src.parent_map = sm8475_gcc_parent_map_3;
+ gcc_ufs_phy_ice_core_clk_src.freq_tbl = sm8475_ftbl_gcc_ufs_phy_ice_core_clk_src;
+ gcc_ufs_phy_ice_core_clk_src.clkr.hw.init = &sm8475_gcc_ufs_phy_ice_core_clk_src_init;
+
+ gcc_ufs_phy_unipro_core_clk_src.parent_map = sm8475_gcc_parent_map_3;
+ gcc_ufs_phy_unipro_core_clk_src.freq_tbl = sm8475_ftbl_gcc_ufs_phy_ice_core_clk_src;
+ gcc_ufs_phy_unipro_core_clk_src.clkr.hw.init = &sm8475_gcc_ufs_phy_unipro_core_clk_src_init;
+
+ gcc_sm8450_desc.clks[SM8475_GCC_GPLL2] = &sm8475_gcc_gpll2.clkr;
+ gcc_sm8450_desc.clks[SM8475_GCC_GPLL3] = &sm8475_gcc_gpll3.clkr;
+ }
+
/* 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));
@@ -3312,5 +3491,5 @@ static void __exit gcc_sm8450_exit(void)
}
module_exit(gcc_sm8450_exit);
-MODULE_DESCRIPTION("QTI GCC SM8450 Driver");
+MODULE_DESCRIPTION("QTI GCC SM8450 / SM8475 Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/gcc-x1e80100.c b/drivers/clk/qcom/gcc-x1e80100.c
index 0f578771071f..8ea25aa25dff 100644
--- a/drivers/clk/qcom/gcc-x1e80100.c
+++ b/drivers/clk/qcom/gcc-x1e80100.c
@@ -3123,7 +3123,7 @@ static struct clk_branch gcc_pcie_3_pipe_clk = {
static struct clk_branch gcc_pcie_3_pipediv2_clk = {
.halt_reg = 0x58060,
- .halt_check = BRANCH_HALT_VOTED,
+ .halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x52020,
.enable_mask = BIT(5),
@@ -3248,7 +3248,7 @@ static struct clk_branch gcc_pcie_4_pipe_clk = {
static struct clk_branch gcc_pcie_4_pipediv2_clk = {
.halt_reg = 0x6b054,
- .halt_check = BRANCH_HALT_VOTED,
+ .halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x52010,
.enable_mask = BIT(27),
@@ -3373,7 +3373,7 @@ static struct clk_branch gcc_pcie_5_pipe_clk = {
static struct clk_branch gcc_pcie_5_pipediv2_clk = {
.halt_reg = 0x2f054,
- .halt_check = BRANCH_HALT_VOTED,
+ .halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x52018,
.enable_mask = BIT(19),
@@ -3511,7 +3511,7 @@ static struct clk_branch gcc_pcie_6a_pipe_clk = {
static struct clk_branch gcc_pcie_6a_pipediv2_clk = {
.halt_reg = 0x31060,
- .halt_check = BRANCH_HALT_VOTED,
+ .halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x52018,
.enable_mask = BIT(28),
@@ -3649,7 +3649,7 @@ static struct clk_branch gcc_pcie_6b_pipe_clk = {
static struct clk_branch gcc_pcie_6b_pipediv2_clk = {
.halt_reg = 0x8d060,
- .halt_check = BRANCH_HALT_VOTED,
+ .halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x52010,
.enable_mask = BIT(28),
@@ -6155,7 +6155,7 @@ static struct gdsc gcc_usb3_mp_ss1_phy_gdsc = {
.pd = {
.name = "gcc_usb3_mp_ss1_phy_gdsc",
},
- .pwrsts = PWRSTS_OFF_ON,
+ .pwrsts = PWRSTS_RET_ON,
.flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
};
diff --git a/drivers/clk/qcom/gpucc-sar2130p.c b/drivers/clk/qcom/gpucc-sar2130p.c
new file mode 100644
index 000000000000..dd72b2a48c42
--- /dev/null
+++ b/drivers/clk/qcom/gpucc-sar2130p.c
@@ -0,0 +1,502 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sar2130p-gpucc.h>
+#include <dt-bindings/reset/qcom,sar2130p-gpucc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_GPLL0_OUT_MAIN,
+ DT_GPLL0_OUT_MAIN_DIV,
+};
+
+enum {
+ P_BI_TCXO,
+ P_GPLL0_OUT_MAIN,
+ P_GPLL0_OUT_MAIN_DIV,
+ P_GPU_CC_PLL0_OUT_MAIN,
+ P_GPU_CC_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2000000000, 0 },
+};
+
+/* 470MHz Configuration */
+static const struct alpha_pll_config gpu_cc_pll0_config = {
+ .l = 0x18,
+ .alpha = 0x7aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll gpu_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+/* 440MHz Configuration */
+static const struct alpha_pll_config gpu_cc_pll1_config = {
+ .l = 0x16,
+ .alpha = 0xeaaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll gpu_cc_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map gpu_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL0_OUT_MAIN, 1 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll0.clkr.hw },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = {
+ F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_ff_clk_src = {
+ .cmd_rcgr = 0x9474,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_0,
+ .freq_tbl = ftbl_gpu_cc_ff_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_ff_clk_src",
+ .parent_data = gpu_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_gmu_clk_src = {
+ .cmd_rcgr = 0x9318,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_1,
+ .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_gmu_clk_src",
+ .parent_data = gpu_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gpu_cc_hub_clk_src = {
+ .cmd_rcgr = 0x93ec,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_2,
+ .freq_tbl = ftbl_gpu_cc_ff_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_clk_src",
+ .parent_data = gpu_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_branch gpu_cc_ahb_clk = {
+ .halt_reg = 0x911c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x911c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_crc_ahb_clk = {
+ .halt_reg = 0x9120,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9120,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_crc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_ff_clk = {
+ .halt_reg = 0x914c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x914c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cx_ff_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_ff_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_gmu_clk = {
+ .halt_reg = 0x913c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x913c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_aon_clk = {
+ .halt_reg = 0x9004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cxo_aon_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_clk = {
+ .halt_reg = 0x9144,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9144,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cxo_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gx_gmu_clk = {
+ .halt_reg = 0x90bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x90bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_gx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_aon_clk = {
+ .halt_reg = 0x93e8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x93e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_aon_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_cx_int_clk = {
+ .halt_reg = 0x9148,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9148,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_cx_int_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_memnoc_gfx_clk = {
+ .halt_reg = 0x9150,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9150,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
+ .halt_reg = 0x7000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_sleep_clk = {
+ .halt_reg = 0x9134,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9134,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc gpu_cx_gdsc = {
+ .gdscr = 0x9108,
+ .gds_hw_ctrl = 0x953c,
+ .clk_dis_wait_val = 8,
+ .pd = {
+ .name = "gpu_cx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gpu_gx_gdsc = {
+ .gdscr = 0x905c,
+ .clamp_io_ctrl = 0x9504,
+ .resets = (unsigned int []){ GPUCC_GPU_CC_GX_BCR,
+ GPUCC_GPU_CC_ACD_BCR,
+ GPUCC_GPU_CC_GX_ACD_IROOT_BCR },
+ .reset_count = 3,
+ .pd = {
+ .name = "gpu_gx_gdsc",
+ .power_on = gdsc_gx_do_nothing_enable,
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = CLAMP_IO | AON_RESET | SW_RESET,
+};
+
+static struct clk_regmap *gpu_cc_sar2130p_clocks[] = {
+ [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
+ [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
+ [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr,
+ [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
+ [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
+ [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
+ [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr,
+ [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
+ [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
+ [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
+ [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
+ [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
+ [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
+ [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,
+ [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
+ [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
+ [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
+};
+
+static const struct qcom_reset_map gpu_cc_sar2130p_resets[] = {
+ [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 },
+ [GPUCC_GPU_CC_GX_ACD_IROOT_BCR] = { 0x958c },
+ [GPUCC_GPU_CC_GX_BCR] = { 0x9058 },
+};
+
+static struct gdsc *gpu_cc_sar2130p_gdscs[] = {
+ [GPU_CX_GDSC] = &gpu_cx_gdsc,
+ [GPU_GX_GDSC] = &gpu_gx_gdsc,
+};
+
+static const struct regmap_config gpu_cc_sar2130p_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xa000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gpu_cc_sar2130p_desc = {
+ .config = &gpu_cc_sar2130p_regmap_config,
+ .clks = gpu_cc_sar2130p_clocks,
+ .num_clks = ARRAY_SIZE(gpu_cc_sar2130p_clocks),
+ .resets = gpu_cc_sar2130p_resets,
+ .num_resets = ARRAY_SIZE(gpu_cc_sar2130p_resets),
+ .gdscs = gpu_cc_sar2130p_gdscs,
+ .num_gdscs = ARRAY_SIZE(gpu_cc_sar2130p_gdscs),
+};
+
+static const struct of_device_id gpu_cc_sar2130p_match_table[] = {
+ { .compatible = "qcom,sar2130p-gpucc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpu_cc_sar2130p_match_table);
+
+static int gpu_cc_sar2130p_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gpu_cc_sar2130p_desc);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap), "Couldn't map GPU_CC\n");
+
+ clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+
+ /* Keep some clocks always-on */
+ qcom_branch_set_clk_en(regmap, 0x900c); /* GPU_CC_DEMET_CLK */
+
+ return qcom_cc_really_probe(dev, &gpu_cc_sar2130p_desc, regmap);
+}
+
+static struct platform_driver gpu_cc_sar2130p_driver = {
+ .probe = gpu_cc_sar2130p_probe,
+ .driver = {
+ .name = "gpu_cc-sar2130p",
+ .of_match_table = gpu_cc_sar2130p_match_table,
+ },
+};
+module_platform_driver(gpu_cc_sar2130p_driver);
+
+MODULE_DESCRIPTION("QTI GPU_CC SAR2130P Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gpucc-sm8450.c b/drivers/clk/qcom/gpucc-sm8450.c
index b3c5d6923cd2..059df72deaa1 100644
--- a/drivers/clk/qcom/gpucc-sm8450.c
+++ b/drivers/clk/qcom/gpucc-sm8450.c
@@ -40,7 +40,7 @@ static const struct pll_vco lucid_evo_vco[] = {
{ 249600000, 2000000000, 0 },
};
-static struct alpha_pll_config gpu_cc_pll0_config = {
+static const struct alpha_pll_config gpu_cc_pll0_config = {
.l = 0x1d,
.alpha = 0xb000,
.config_ctl_val = 0x20485699,
@@ -50,6 +50,20 @@ static struct alpha_pll_config gpu_cc_pll0_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_gpu_cc_pll0_config = {
+ .l = 0x1d,
+ .alpha = 0xb000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll gpu_cc_pll0 = {
.offset = 0x0,
.vco_table = lucid_evo_vco,
@@ -67,7 +81,7 @@ static struct clk_alpha_pll gpu_cc_pll0 = {
},
};
-static struct alpha_pll_config gpu_cc_pll1_config = {
+static const struct alpha_pll_config gpu_cc_pll1_config = {
.l = 0x34,
.alpha = 0x1555,
.config_ctl_val = 0x20485699,
@@ -77,6 +91,20 @@ static struct alpha_pll_config gpu_cc_pll1_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_gpu_cc_pll1_config = {
+ .l = 0x34,
+ .alpha = 0x1555,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll gpu_cc_pll1 = {
.offset = 0x1000,
.vco_table = lucid_evo_vco,
@@ -736,6 +764,7 @@ static const struct qcom_cc_desc gpu_cc_sm8450_desc = {
static const struct of_device_id gpu_cc_sm8450_match_table[] = {
{ .compatible = "qcom,sm8450-gpucc" },
+ { .compatible = "qcom,sm8475-gpucc" },
{ }
};
MODULE_DEVICE_TABLE(of, gpu_cc_sm8450_match_table);
@@ -748,8 +777,19 @@ static int gpu_cc_sm8450_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
- clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8475-gpucc")) {
+ /* Update GPUCC PLL0 */
+ gpu_cc_pll0.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+
+ /* Update GPUCC PLL1 */
+ gpu_cc_pll1.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+
+ clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &sm8475_gpu_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &sm8475_gpu_cc_pll1_config);
+ } else {
+ clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
+ }
return qcom_cc_really_probe(&pdev->dev, &gpu_cc_sm8450_desc, regmap);
}
@@ -763,5 +803,5 @@ static struct platform_driver gpu_cc_sm8450_driver = {
};
module_platform_driver(gpu_cc_sm8450_driver);
-MODULE_DESCRIPTION("QTI GPU_CC SM8450 Driver");
+MODULE_DESCRIPTION("QTI GPU_CC SM8450 / SM8475 Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/tcsrcc-sm8550.c b/drivers/clk/qcom/tcsrcc-sm8550.c
index e5e8f2e82b94..41d73f92a000 100644
--- a/drivers/clk/qcom/tcsrcc-sm8550.c
+++ b/drivers/clk/qcom/tcsrcc-sm8550.c
@@ -129,6 +129,13 @@ static struct clk_branch tcsr_usb3_clkref_en = {
},
};
+static struct clk_regmap *tcsr_cc_sar2130p_clocks[] = {
+ [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr,
+ [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr,
+ [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr,
+ [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr,
+};
+
static struct clk_regmap *tcsr_cc_sm8550_clocks[] = {
[TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr,
[TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr,
@@ -146,6 +153,12 @@ static const struct regmap_config tcsr_cc_sm8550_regmap_config = {
.fast_io = true,
};
+static const struct qcom_cc_desc tcsr_cc_sar2130p_desc = {
+ .config = &tcsr_cc_sm8550_regmap_config,
+ .clks = tcsr_cc_sar2130p_clocks,
+ .num_clks = ARRAY_SIZE(tcsr_cc_sar2130p_clocks),
+};
+
static const struct qcom_cc_desc tcsr_cc_sm8550_desc = {
.config = &tcsr_cc_sm8550_regmap_config,
.clks = tcsr_cc_sm8550_clocks,
@@ -153,7 +166,8 @@ static const struct qcom_cc_desc tcsr_cc_sm8550_desc = {
};
static const struct of_device_id tcsr_cc_sm8550_match_table[] = {
- { .compatible = "qcom,sm8550-tcsr" },
+ { .compatible = "qcom,sar2130p-tcsr", .data = &tcsr_cc_sar2130p_desc },
+ { .compatible = "qcom,sm8550-tcsr", .data = &tcsr_cc_sm8550_desc },
{ }
};
MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table);
@@ -162,7 +176,7 @@ static int tcsr_cc_sm8550_probe(struct platform_device *pdev)
{
struct regmap *regmap;
- regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc);
+ regmap = qcom_cc_map(pdev, of_device_get_match_data(&pdev->dev));
if (IS_ERR(regmap))
return PTR_ERR(regmap);
diff --git a/drivers/clk/qcom/videocc-sa8775p.c b/drivers/clk/qcom/videocc-sa8775p.c
new file mode 100644
index 000000000000..bf5de411fd5d
--- /dev/null
+++ b/drivers/clk/qcom/videocc-sa8775p.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sa8775p-videocc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_IFACE,
+ DT_BI_TCXO,
+ DT_BI_TCXO_AO,
+ DT_SLEEP_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_BI_TCXO_AO,
+ P_SLEEP_CLK,
+ P_VIDEO_PLL0_OUT_MAIN,
+ P_VIDEO_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_evo_vco[] = {
+ { 249600000, 2020000000, 0 },
+};
+
+static const struct alpha_pll_config video_pll0_config = {
+ .l = 0x39,
+ .alpha = 0x3000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll video_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config video_pll1_config = {
+ .l = 0x39,
+ .alpha = 0x3000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x32aa299c,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00400805,
+};
+
+static struct clk_alpha_pll video_pll1 = {
+ .offset = 0x1000,
+ .vco_table = lucid_evo_vco,
+ .num_vco = ARRAY_SIZE(lucid_evo_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map video_cc_parent_map_0_ao[] = {
+ { P_BI_TCXO_AO, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_0_ao[] = {
+ { .index = DT_BI_TCXO_AO },
+};
+
+static const struct parent_map video_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_PLL0_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_pll0.clkr.hw },
+};
+
+static const struct parent_map video_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_PLL1_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_pll1.clkr.hw },
+};
+
+static const struct parent_map video_cc_parent_map_3[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_3[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO_AO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_ahb_clk_src = {
+ .cmd_rcgr = 0x8030,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0_ao,
+ .freq_tbl = ftbl_video_cc_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_ahb_clk_src",
+ .parent_data = video_cc_parent_data_0_ao,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
+ F(1098000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1332000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1599000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1680000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs0_clk_src = {
+ .cmd_rcgr = 0x8000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_1,
+ .freq_tbl = ftbl_video_cc_mvs0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk_src",
+ .parent_data = video_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
+ F(1098000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1332000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1600000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
+ F(1800000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs1_clk_src = {
+ .cmd_rcgr = 0x8018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_2,
+ .freq_tbl = ftbl_video_cc_mvs1_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk_src",
+ .parent_data = video_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x812c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_3,
+ .freq_tbl = ftbl_video_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_sleep_clk_src",
+ .parent_data = video_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 video_cc_xo_clk_src = {
+ .cmd_rcgr = 0x8110,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0_ao,
+ .freq_tbl = ftbl_video_cc_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_xo_clk_src",
+ .parent_data = video_cc_parent_data_0_ao,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
+ .reg = 0x80b8,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
+ .reg = 0x806c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1_div_clk_src = {
+ .reg = 0x80dc,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {
+ .reg = 0x8094,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_sm_div_clk_src = {
+ .reg = 0x8108,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_sm_div_clk_src",
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch video_cc_mvs0_clk = {
+ .halt_reg = 0x80b0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x80b0,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x80b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0c_clk = {
+ .halt_reg = 0x8064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1_clk = {
+ .halt_reg = 0x80d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x80d4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x80d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs1c_clk = {
+ .halt_reg = 0x808c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x808c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs1c_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_pll_lock_monitor_clk = {
+ .halt_reg = 0x9000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_pll_lock_monitor_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_sm_obs_clk = {
+ .halt_reg = 0x810c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x810c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_sm_obs_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_sm_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc video_cc_mvs0c_gdsc = {
+ .gdscr = 0x804c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0c_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR,
+};
+
+static struct gdsc video_cc_mvs0_gdsc = {
+ .gdscr = 0x809c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &video_cc_mvs0c_gdsc.pd,
+ .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR | HW_CTRL_TRIGGER,
+};
+
+static struct gdsc video_cc_mvs1c_gdsc = {
+ .gdscr = 0x8074,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs1c_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR,
+};
+
+static struct gdsc video_cc_mvs1_gdsc = {
+ .gdscr = 0x80c0,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &video_cc_mvs1c_gdsc.pd,
+ .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR | HW_CTRL_TRIGGER,
+};
+
+static struct clk_regmap *video_cc_sa8775p_clocks[] = {
+ [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr,
+ [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
+ [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
+ [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
+ [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
+ [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
+ [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr,
+ [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,
+ [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr,
+ [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,
+ [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
+ [VIDEO_CC_PLL_LOCK_MONITOR_CLK] = &video_cc_pll_lock_monitor_clk.clkr,
+ [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
+ [VIDEO_CC_SM_DIV_CLK_SRC] = &video_cc_sm_div_clk_src.clkr,
+ [VIDEO_CC_SM_OBS_CLK] = &video_cc_sm_obs_clk.clkr,
+ [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr,
+ [VIDEO_PLL0] = &video_pll0.clkr,
+ [VIDEO_PLL1] = &video_pll1.clkr,
+};
+
+static struct gdsc *video_cc_sa8775p_gdscs[] = {
+ [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
+ [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
+ [VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc,
+ [VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc,
+};
+
+static const struct qcom_reset_map video_cc_sa8775p_resets[] = {
+ [VIDEO_CC_INTERFACE_BCR] = { 0x80e8 },
+ [VIDEO_CC_MVS0_BCR] = { 0x8098 },
+ [VIDEO_CC_MVS0C_CLK_ARES] = { 0x8064, 2 },
+ [VIDEO_CC_MVS0C_BCR] = { 0x8048 },
+ [VIDEO_CC_MVS1_BCR] = { 0x80bc },
+ [VIDEO_CC_MVS1C_CLK_ARES] = { 0x808c, 2 },
+ [VIDEO_CC_MVS1C_BCR] = { 0x8070 },
+};
+
+static const struct regmap_config video_cc_sa8775p_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xb000,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc video_cc_sa8775p_desc = {
+ .config = &video_cc_sa8775p_regmap_config,
+ .clks = video_cc_sa8775p_clocks,
+ .num_clks = ARRAY_SIZE(video_cc_sa8775p_clocks),
+ .resets = video_cc_sa8775p_resets,
+ .num_resets = ARRAY_SIZE(video_cc_sa8775p_resets),
+ .gdscs = video_cc_sa8775p_gdscs,
+ .num_gdscs = ARRAY_SIZE(video_cc_sa8775p_gdscs),
+};
+
+static const struct of_device_id video_cc_sa8775p_match_table[] = {
+ { .compatible = "qcom,sa8775p-videocc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, video_cc_sa8775p_match_table);
+
+static int video_cc_sa8775p_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, &video_cc_sa8775p_desc);
+ if (IS_ERR(regmap)) {
+ pm_runtime_put(&pdev->dev);
+ return PTR_ERR(regmap);
+ }
+
+ clk_lucid_evo_pll_configure(&video_pll0, regmap, &video_pll0_config);
+ clk_lucid_evo_pll_configure(&video_pll1, regmap, &video_pll1_config);
+
+ /* Keep some clocks always enabled */
+ qcom_branch_set_clk_en(regmap, 0x80ec); /* VIDEO_CC_AHB_CLK */
+ qcom_branch_set_clk_en(regmap, 0x8144); /* VIDEO_CC_SLEEP_CLK */
+ qcom_branch_set_clk_en(regmap, 0x8128); /* VIDEO_CC_XO_CLK */
+
+ ret = qcom_cc_really_probe(&pdev->dev, &video_cc_sa8775p_desc, regmap);
+
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static struct platform_driver video_cc_sa8775p_driver = {
+ .probe = video_cc_sa8775p_probe,
+ .driver = {
+ .name = "videocc-sa8775p",
+ .of_match_table = video_cc_sa8775p_match_table,
+ },
+};
+
+module_platform_driver(video_cc_sa8775p_driver);
+
+MODULE_DESCRIPTION("QTI VIDEOCC SA8775P Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/videocc-sm8350.c b/drivers/clk/qcom/videocc-sm8350.c
index 5bd6fe3e1298..874d4da95ff8 100644
--- a/drivers/clk/qcom/videocc-sm8350.c
+++ b/drivers/clk/qcom/videocc-sm8350.c
@@ -452,7 +452,7 @@ static struct gdsc mvs0_gdsc = {
.pd = {
.name = "mvs0_gdsc",
},
- .flags = HW_CTRL | RETAIN_FF_ENABLE,
+ .flags = HW_CTRL_TRIGGER | RETAIN_FF_ENABLE,
.pwrsts = PWRSTS_OFF_ON,
};
@@ -461,7 +461,7 @@ static struct gdsc mvs1_gdsc = {
.pd = {
.name = "mvs1_gdsc",
},
- .flags = HW_CTRL | RETAIN_FF_ENABLE,
+ .flags = HW_CTRL_TRIGGER | RETAIN_FF_ENABLE,
.pwrsts = PWRSTS_OFF_ON,
};
diff --git a/drivers/clk/qcom/videocc-sm8450.c b/drivers/clk/qcom/videocc-sm8450.c
index ed9163d64244..f26c7eccb62e 100644
--- a/drivers/clk/qcom/videocc-sm8450.c
+++ b/drivers/clk/qcom/videocc-sm8450.c
@@ -46,6 +46,21 @@ static const struct alpha_pll_config video_cc_pll0_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_video_cc_pll0_config = {
+ /* .l includes CAL_L_VAL, L_VAL fields */
+ .l = 0x1e,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll video_cc_pll0 = {
.offset = 0x0,
.vco_table = lucid_evo_vco,
@@ -74,6 +89,21 @@ static const struct alpha_pll_config video_cc_pll1_config = {
.user_ctl_hi_val = 0x00000805,
};
+static const struct alpha_pll_config sm8475_video_cc_pll1_config = {
+ /* .l includes CAL_L_VAL, L_VAL fields */
+ .l = 0x2b,
+ .alpha = 0xc000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
static struct clk_alpha_pll video_cc_pll1 = {
.offset = 0x1000,
.vco_table = lucid_evo_vco,
@@ -397,6 +427,7 @@ static struct qcom_cc_desc video_cc_sm8450_desc = {
static const struct of_device_id video_cc_sm8450_match_table[] = {
{ .compatible = "qcom,sm8450-videocc" },
+ { .compatible = "qcom,sm8475-videocc" },
{ }
};
MODULE_DEVICE_TABLE(of, video_cc_sm8450_match_table);
@@ -420,8 +451,19 @@ static int video_cc_sm8450_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
- clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
- clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8475-videocc")) {
+ /* Update VideoCC PLL0 */
+ video_cc_pll0.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+
+ /* Update VideoCC PLL1 */
+ video_cc_pll1.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE];
+
+ clk_lucid_ole_pll_configure(&video_cc_pll0, regmap, &sm8475_video_cc_pll0_config);
+ clk_lucid_ole_pll_configure(&video_cc_pll1, regmap, &sm8475_video_cc_pll1_config);
+ } else {
+ clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config);
+ clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config);
+ }
/* Keep some clocks always-on */
qcom_branch_set_clk_en(regmap, 0x80e4); /* VIDEO_CC_AHB_CLK */
@@ -445,5 +487,5 @@ static struct platform_driver video_cc_sm8450_driver = {
module_platform_driver(video_cc_sm8450_driver);
-MODULE_DESCRIPTION("QTI VIDEOCC SM8450 Driver");
+MODULE_DESCRIPTION("QTI VIDEOCC SM8450 / SM8475 Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c
index 50a443bf79ec..97b8ca0f9181 100644
--- a/drivers/clk/ralink/clk-mtmips.c
+++ b/drivers/clk/ralink/clk-mtmips.c
@@ -207,6 +207,7 @@ static struct mtmips_clk mt7620_pherip_clks[] = {
{ CLK_PERIPH("10000b00.spi", "bus") },
{ CLK_PERIPH("10000b40.spi", "bus") },
{ CLK_PERIPH("10000c00.uartlite", "periph") },
+ { CLK_PERIPH("10130000.mmc", "sdhc") },
{ CLK_PERIPH("10180000.wmac", "xtal") }
};
@@ -220,6 +221,7 @@ static struct mtmips_clk mt76x8_pherip_clks[] = {
{ CLK_PERIPH("10000c00.uart0", "periph") },
{ CLK_PERIPH("10000d00.uart1", "periph") },
{ CLK_PERIPH("10000e00.uart2", "periph") },
+ { CLK_PERIPH("10130000.mmc", "sdhc") },
{ CLK_PERIPH("10300000.wmac", "xtal") }
};
@@ -263,16 +265,22 @@ err_clk_unreg:
.rate = _rate \
}
-static struct mtmips_clk_fixed rt305x_fixed_clocks[] = {
- CLK_FIXED("xtal", NULL, 40000000)
+static struct mtmips_clk_fixed rt3883_fixed_clocks[] = {
+ CLK_FIXED("xtal", NULL, 40000000),
+ CLK_FIXED("periph", "xtal", 40000000)
};
static struct mtmips_clk_fixed rt3352_fixed_clocks[] = {
CLK_FIXED("periph", "xtal", 40000000)
};
+static struct mtmips_clk_fixed mt7620_fixed_clocks[] = {
+ CLK_FIXED("bbppll", "xtal", 480000000)
+};
+
static struct mtmips_clk_fixed mt76x8_fixed_clocks[] = {
- CLK_FIXED("pcmi2s", "xtal", 480000000),
+ CLK_FIXED("bbppll", "xtal", 480000000),
+ CLK_FIXED("pcmi2s", "bbppll", 480000000),
CLK_FIXED("periph", "xtal", 40000000)
};
@@ -327,6 +335,15 @@ static struct mtmips_clk_factor rt305x_factor_clocks[] = {
CLK_FACTOR("bus", "cpu", 1, 3)
};
+static struct mtmips_clk_factor mt7620_factor_clocks[] = {
+ CLK_FACTOR("sdhc", "bbppll", 1, 10)
+};
+
+static struct mtmips_clk_factor mt76x8_factor_clocks[] = {
+ CLK_FACTOR("bus", "cpu", 1, 3),
+ CLK_FACTOR("sdhc", "bbppll", 1, 10)
+};
+
static int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data,
struct mtmips_clk_priv *priv)
{
@@ -366,6 +383,12 @@ static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw)
return container_of(hw, struct mtmips_clk, hw);
}
+static unsigned long rt2880_xtal_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return 40000000;
+}
+
static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -677,10 +700,12 @@ static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw,
}
static struct mtmips_clk rt2880_clks_base[] = {
+ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) },
{ CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) }
};
static struct mtmips_clk rt305x_clks_base[] = {
+ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) },
{ CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) }
};
@@ -690,6 +715,7 @@ static struct mtmips_clk rt3352_clks_base[] = {
};
static struct mtmips_clk rt3883_clks_base[] = {
+ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) },
{ CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) },
{ CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) }
};
@@ -746,8 +772,8 @@ err_clk_unreg:
static const struct mtmips_clk_data rt2880_clk_data = {
.clk_base = rt2880_clks_base,
.num_clk_base = ARRAY_SIZE(rt2880_clks_base),
- .clk_fixed = rt305x_fixed_clocks,
- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_fixed = NULL,
+ .num_clk_fixed = 0,
.clk_factor = rt2880_factor_clocks,
.num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks),
.clk_periph = rt2880_pherip_clks,
@@ -757,8 +783,8 @@ static const struct mtmips_clk_data rt2880_clk_data = {
static const struct mtmips_clk_data rt305x_clk_data = {
.clk_base = rt305x_clks_base,
.num_clk_base = ARRAY_SIZE(rt305x_clks_base),
- .clk_fixed = rt305x_fixed_clocks,
- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_fixed = NULL,
+ .num_clk_fixed = 0,
.clk_factor = rt305x_factor_clocks,
.num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
.clk_periph = rt305x_pherip_clks,
@@ -779,8 +805,8 @@ static const struct mtmips_clk_data rt3352_clk_data = {
static const struct mtmips_clk_data rt3883_clk_data = {
.clk_base = rt3883_clks_base,
.num_clk_base = ARRAY_SIZE(rt3883_clks_base),
- .clk_fixed = rt305x_fixed_clocks,
- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_fixed = rt3883_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt3883_fixed_clocks),
.clk_factor = NULL,
.num_clk_factor = 0,
.clk_periph = rt5350_pherip_clks,
@@ -801,10 +827,10 @@ static const struct mtmips_clk_data rt5350_clk_data = {
static const struct mtmips_clk_data mt7620_clk_data = {
.clk_base = mt7620_clks_base,
.num_clk_base = ARRAY_SIZE(mt7620_clks_base),
- .clk_fixed = NULL,
- .num_clk_fixed = 0,
- .clk_factor = NULL,
- .num_clk_factor = 0,
+ .clk_fixed = mt7620_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(mt7620_fixed_clocks),
+ .clk_factor = mt7620_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(mt7620_factor_clocks),
.clk_periph = mt7620_pherip_clks,
.num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks),
};
@@ -814,8 +840,8 @@ static const struct mtmips_clk_data mt76x8_clk_data = {
.num_clk_base = ARRAY_SIZE(mt76x8_clks_base),
.clk_fixed = mt76x8_fixed_clocks,
.num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks),
- .clk_factor = rt305x_factor_clocks,
- .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_factor = mt76x8_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(mt76x8_factor_clocks),
.clk_periph = mt76x8_pherip_clks,
.num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks),
};
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
index 76791a1c50ac..ff01f5f0ed20 100644
--- a/drivers/clk/renesas/Kconfig
+++ b/drivers/clk/renesas/Kconfig
@@ -237,6 +237,11 @@ config CLK_RZV2H
bool "RZ/V2H(P) family clock support" if COMPILE_TEST
select RESET_CONTROLLER
+config CLK_RENESAS_VBATTB
+ tristate "Renesas VBATTB clock controller"
+ depends on ARCH_RZG2L || COMPILE_TEST
+ select RESET_CONTROLLER
+
# Generic
config CLK_RENESAS_CPG_MSSR
bool "CPG/MSSR clock support" if COMPILE_TEST
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index 23d2e26051c8..82efaa835ac7 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_CLK_RZV2H) += rzv2h-cpg.o
obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o
obj-$(CONFIG_CLK_RENESAS_CPG_MSTP) += clk-mstp.o
obj-$(CONFIG_CLK_RENESAS_DIV6) += clk-div6.o
+obj-$(CONFIG_CLK_RENESAS_VBATTB) += clk-vbattb.o
diff --git a/drivers/clk/renesas/clk-r8a73a4.c b/drivers/clk/renesas/clk-r8a73a4.c
index 4b1815147f77..f331d8bc9daf 100644
--- a/drivers/clk/renesas/clk-r8a73a4.c
+++ b/drivers/clk/renesas/clk-r8a73a4.c
@@ -64,7 +64,6 @@ r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg,
unsigned int mult = 1;
unsigned int div = 1;
-
if (!strcmp(name, "main")) {
u32 ckscr = readl(base + CPG_CKSCR);
diff --git a/drivers/clk/renesas/clk-r8a7778.c b/drivers/clk/renesas/clk-r8a7778.c
index 797556259370..6ea173f22251 100644
--- a/drivers/clk/renesas/clk-r8a7778.c
+++ b/drivers/clk/renesas/clk-r8a7778.c
@@ -67,7 +67,6 @@ r8a7778_cpg_register_clock(struct device_node *np, const char *name)
return ERR_PTR(-EINVAL);
}
-
static void __init r8a7778_cpg_clocks_init(struct device_node *np)
{
struct clk_onecell_data *data;
diff --git a/drivers/clk/renesas/clk-vbattb.c b/drivers/clk/renesas/clk-vbattb.c
new file mode 100644
index 000000000000..ff9d1ead455c
--- /dev/null
+++ b/drivers/clk/renesas/clk-vbattb.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VBATTB clock driver
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#include <linux/cleanup.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
+
+#define VBATTB_BKSCCR 0x1c
+#define VBATTB_BKSCCR_SOSEL 6
+#define VBATTB_SOSCCR2 0x24
+#define VBATTB_SOSCCR2_SOSTP2 0
+#define VBATTB_XOSCCR 0x30
+#define VBATTB_XOSCCR_OUTEN 16
+#define VBATTB_XOSCCR_XSEL GENMASK(1, 0)
+#define VBATTB_XOSCCR_XSEL_4_PF 0x0
+#define VBATTB_XOSCCR_XSEL_7_PF 0x1
+#define VBATTB_XOSCCR_XSEL_9_PF 0x2
+#define VBATTB_XOSCCR_XSEL_12_5_PF 0x3
+
+/**
+ * struct vbattb_clk - VBATTB clock data structure
+ * @base: base address
+ * @lock: lock
+ */
+struct vbattb_clk {
+ void __iomem *base;
+ spinlock_t lock;
+};
+
+static int vbattb_clk_validate_load_capacitance(u32 *reg_lc, u32 of_lc)
+{
+ switch (of_lc) {
+ case 4000:
+ *reg_lc = VBATTB_XOSCCR_XSEL_4_PF;
+ break;
+ case 7000:
+ *reg_lc = VBATTB_XOSCCR_XSEL_7_PF;
+ break;
+ case 9000:
+ *reg_lc = VBATTB_XOSCCR_XSEL_9_PF;
+ break;
+ case 12500:
+ *reg_lc = VBATTB_XOSCCR_XSEL_12_5_PF;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void vbattb_clk_action(void *data)
+{
+ struct device *dev = data;
+ struct reset_control *rstc = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_assert(rstc);
+ if (ret)
+ dev_err(dev, "Failed to de-assert reset!");
+
+ ret = pm_runtime_put_sync(dev);
+ if (ret < 0)
+ dev_err(dev, "Failed to runtime suspend!");
+
+ of_clk_del_provider(dev->of_node);
+}
+
+static int vbattb_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct clk_parent_data parent_data = {};
+ struct clk_hw_onecell_data *clk_data;
+ const struct clk_hw *parent_hws[2];
+ struct device *dev = &pdev->dev;
+ struct reset_control *rstc;
+ struct vbattb_clk *vbclk;
+ u32 of_lc, reg_lc;
+ struct clk_hw *hw;
+ /* 4 clocks are exported: VBATTB_XC, VBATTB_XBYP, VBATTB_MUX, VBATTB_VBATTCLK. */
+ u8 num_clks = 4;
+ int ret;
+
+ /* Default to 4pF as this is not needed if external clock device is connected. */
+ of_lc = 4000;
+ of_property_read_u32(np, "quartz-load-femtofarads", &of_lc);
+
+ ret = vbattb_clk_validate_load_capacitance(&reg_lc, of_lc);
+ if (ret)
+ return ret;
+
+ vbclk = devm_kzalloc(dev, sizeof(*vbclk), GFP_KERNEL);
+ if (!vbclk)
+ return -ENOMEM;
+
+ clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, num_clks), GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+ clk_data->num = num_clks;
+
+ vbclk->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(vbclk->base))
+ return PTR_ERR(vbclk->base);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ rstc = devm_reset_control_get_shared(dev, NULL);
+ if (IS_ERR(rstc))
+ return PTR_ERR(rstc);
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(rstc);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ dev_set_drvdata(dev, rstc);
+ ret = devm_add_action_or_reset(dev, vbattb_clk_action, dev);
+ if (ret)
+ return ret;
+
+ spin_lock_init(&vbclk->lock);
+
+ parent_data.fw_name = "rtx";
+ hw = devm_clk_hw_register_gate_parent_data(dev, "xc", &parent_data, 0,
+ vbclk->base + VBATTB_SOSCCR2,
+ VBATTB_SOSCCR2_SOSTP2,
+ CLK_GATE_SET_TO_DISABLE, &vbclk->lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_XC] = hw;
+
+ hw = devm_clk_hw_register_fixed_factor_fwname(dev, np, "xbyp", "rtx", 0, 1, 1);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_XBYP] = hw;
+
+ parent_hws[0] = clk_data->hws[VBATTB_XC];
+ parent_hws[1] = clk_data->hws[VBATTB_XBYP];
+ hw = devm_clk_hw_register_mux_parent_hws(dev, "mux", parent_hws, 2, 0,
+ vbclk->base + VBATTB_BKSCCR,
+ VBATTB_BKSCCR_SOSEL,
+ 1, 0, &vbclk->lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_MUX] = hw;
+
+ /* Set load capacitance before registering the VBATTCLK clock. */
+ scoped_guard(spinlock, &vbclk->lock) {
+ u32 val = readl_relaxed(vbclk->base + VBATTB_XOSCCR);
+
+ val &= ~VBATTB_XOSCCR_XSEL;
+ val |= reg_lc;
+ writel_relaxed(val, vbclk->base + VBATTB_XOSCCR);
+ }
+
+ /* This feeds the RTC counter clock and it needs to stay on. */
+ hw = devm_clk_hw_register_gate_parent_hw(dev, "vbattclk", hw, CLK_IS_CRITICAL,
+ vbclk->base + VBATTB_XOSCCR,
+ VBATTB_XOSCCR_OUTEN, 0,
+ &vbclk->lock);
+
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ clk_data->hws[VBATTB_VBATTCLK] = hw;
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct of_device_id vbattb_clk_match[] = {
+ { .compatible = "renesas,r9a08g045-vbattb" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vbattb_clk_match);
+
+static struct platform_driver vbattb_clk_driver = {
+ .driver = {
+ .name = "renesas-vbattb-clk",
+ .of_match_table = vbattb_clk_match,
+ },
+ .probe = vbattb_clk_probe,
+};
+module_platform_driver(vbattb_clk_driver);
+
+MODULE_DESCRIPTION("Renesas VBATTB Clock Driver");
+MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
index 4c8e4c69c1bf..9c7e4094705c 100644
--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -266,7 +266,6 @@ static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] __initconst = {
{ 2, 128, 1, 192, 1, 32, },
};
-
static int __init r8a779a0_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c
index e20c048bfa9b..9067e407cbc6 100644
--- a/drivers/clk/renesas/r8a779h0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c
@@ -37,7 +37,6 @@ enum clk_ids {
CLK_PLL5,
CLK_PLL6,
CLK_PLL1_DIV2,
- CLK_PLL2_DIV2,
CLK_PLL3_DIV2,
CLK_PLL4_DIV2,
CLK_PLL4_DIV5,
@@ -78,7 +77,6 @@ static const struct cpg_core_clk r8a779h0_core_clks[] __initconst = {
DEF_GEN4_PLL_V8_25(".pll6", 6, CLK_PLL6, CLK_MAIN),
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
- DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1),
DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1),
DEF_FIXED(".pll4_div2", CLK_PLL4_DIV2, CLK_PLL4, 2, 1),
DEF_FIXED(".pll4_div5", CLK_PLL4_DIV5, CLK_PLL4, 5, 1),
@@ -101,10 +99,10 @@ static const struct cpg_core_clk r8a779h0_core_clks[] __initconst = {
DEF_RATE(".oco", CLK_OCO, 32768),
/* Core Clock Outputs */
- DEF_GEN4_Z("zc0", R8A779H0_CLK_ZC0, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 0),
- DEF_GEN4_Z("zc1", R8A779H0_CLK_ZC1, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 8),
- DEF_GEN4_Z("zc2", R8A779H0_CLK_ZC2, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 32),
- DEF_GEN4_Z("zc3", R8A779H0_CLK_ZC3, CLK_TYPE_GEN4_Z, CLK_PLL2_DIV2, 2, 40),
+ DEF_GEN4_Z("zc0", R8A779H0_CLK_ZC0, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 0),
+ DEF_GEN4_Z("zc1", R8A779H0_CLK_ZC1, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 8),
+ DEF_GEN4_Z("zc2", R8A779H0_CLK_ZC2, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 32),
+ DEF_GEN4_Z("zc3", R8A779H0_CLK_ZC3, CLK_TYPE_GEN4_Z, CLK_PLL2, 4, 40),
DEF_FIXED("s0d2", R8A779H0_CLK_S0D2, CLK_S0, 2, 1),
DEF_FIXED("s0d3", R8A779H0_CLK_S0D3, CLK_S0, 3, 1),
DEF_FIXED("s0d4", R8A779H0_CLK_S0D4, CLK_S0, 4, 1),
diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c
index 1ce40fb51f13..b2ae8cdc4723 100644
--- a/drivers/clk/renesas/r9a08g045-cpg.c
+++ b/drivers/clk/renesas/r9a08g045-cpg.c
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/pm_domain.h>
#include <dt-bindings/clock/r9a08g045-cpg.h>
@@ -266,61 +267,50 @@ static const struct rzg2l_cpg_pm_domain_init_data r9a08g045_pm_domains[] = {
/* Keep always-on domain on the first position for proper domains registration. */
DEF_PD("always-on", R9A08G045_PD_ALWAYS_ON,
DEF_REG_CONF(0, 0),
- RZG2L_PD_F_ALWAYS_ON),
+ GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE),
DEF_PD("gic", R9A08G045_PD_GIC,
DEF_REG_CONF(CPG_BUS_ACPU_MSTOP, BIT(3)),
- RZG2L_PD_F_ALWAYS_ON),
+ GENPD_FLAG_ALWAYS_ON),
DEF_PD("ia55", R9A08G045_PD_IA55,
DEF_REG_CONF(CPG_BUS_PERI_CPU_MSTOP, BIT(13)),
- RZG2L_PD_F_ALWAYS_ON),
+ GENPD_FLAG_ALWAYS_ON),
DEF_PD("dmac", R9A08G045_PD_DMAC,
DEF_REG_CONF(CPG_BUS_REG1_MSTOP, GENMASK(3, 0)),
- RZG2L_PD_F_ALWAYS_ON),
+ GENPD_FLAG_ALWAYS_ON),
DEF_PD("wdt0", R9A08G045_PD_WDT0,
DEF_REG_CONF(CPG_BUS_REG0_MSTOP, BIT(0)),
- RZG2L_PD_F_NONE),
+ GENPD_FLAG_IRQ_SAFE),
DEF_PD("sdhi0", R9A08G045_PD_SDHI0,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(0)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(0)), 0),
DEF_PD("sdhi1", R9A08G045_PD_SDHI1,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(1)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(1)), 0),
DEF_PD("sdhi2", R9A08G045_PD_SDHI2,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(11)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(11)), 0),
DEF_PD("usb0", R9A08G045_PD_USB0,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, GENMASK(6, 5)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, GENMASK(6, 5)), 0),
DEF_PD("usb1", R9A08G045_PD_USB1,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(7)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(7)), 0),
DEF_PD("usb-phy", R9A08G045_PD_USB_PHY,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(4)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(4)), 0),
DEF_PD("eth0", R9A08G045_PD_ETHER0,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(2)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(2)), 0),
DEF_PD("eth1", R9A08G045_PD_ETHER1,
- DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(3)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(3)), 0),
DEF_PD("i2c0", R9A08G045_PD_I2C0,
- DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(10)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(10)), 0),
DEF_PD("i2c1", R9A08G045_PD_I2C1,
- DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(11)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(11)), 0),
DEF_PD("i2c2", R9A08G045_PD_I2C2,
- DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(12)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(12)), 0),
DEF_PD("i2c3", R9A08G045_PD_I2C3,
- DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(13)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(13)), 0),
DEF_PD("scif0", R9A08G045_PD_SCIF0,
- DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(1)),
- RZG2L_PD_F_NONE),
+ DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(1)), 0),
DEF_PD("vbat", R9A08G045_PD_VBAT,
DEF_REG_CONF(CPG_BUS_MCPU3_MSTOP, BIT(8)),
- RZG2L_PD_F_ALWAYS_ON),
+ GENPD_FLAG_ALWAYS_ON),
+ DEF_PD("rtc", R9A08G045_PD_RTC,
+ DEF_REG_CONF(CPG_BUS_MCPU3_MSTOP, BIT(7)), 0),
};
const struct rzg2l_cpg_info r9a08g045_cpg_info = {
diff --git a/drivers/clk/renesas/r9a09g011-cpg.c b/drivers/clk/renesas/r9a09g011-cpg.c
index dda9f29dff33..22272279b104 100644
--- a/drivers/clk/renesas/r9a09g011-cpg.c
+++ b/drivers/clk/renesas/r9a09g011-cpg.c
@@ -98,7 +98,6 @@ static const struct clk_div_table dtable_divd[] = {
{0, 0},
};
-
static const struct clk_div_table dtable_divw[] = {
{0, 6},
{1, 7},
diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c
index 3ee32db5c0af..7c4507fd34e6 100644
--- a/drivers/clk/renesas/r9a09g057-cpg.c
+++ b/drivers/clk/renesas/r9a09g057-cpg.c
@@ -41,6 +41,14 @@ enum clk_ids {
MOD_CLK_BASE,
};
+static const struct clk_div_table dtable_1_8[] = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {3, 8},
+ {0, 0},
+};
+
static const struct clk_div_table dtable_2_64[] = {
{0, 2},
{1, 4},
@@ -74,10 +82,19 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
/* Core Clocks */
DEF_FIXED("sys_0_pclk", R9A09G057_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
+ DEF_DDIV("ca55_0_coreclk0", R9A09G057_CA55_0_CORE_CLK0, CLK_PLLCA55,
+ CDDIV1_DIVCTL0, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk1", R9A09G057_CA55_0_CORE_CLK1, CLK_PLLCA55,
+ CDDIV1_DIVCTL1, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk2", R9A09G057_CA55_0_CORE_CLK2, CLK_PLLCA55,
+ CDDIV1_DIVCTL2, dtable_1_8),
+ DEF_DDIV("ca55_0_coreclk3", R9A09G057_CA55_0_CORE_CLK3, CLK_PLLCA55,
+ CDDIV1_DIVCTL3, dtable_1_8),
DEF_FIXED("iotop_0_shclk", R9A09G057_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
};
static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
+ DEF_MOD_CRITICAL("icu_0_pclk_i", CLK_PLLCM33_DIV16, 0, 5, 0, 5),
DEF_MOD("gtm_0_pclk", CLK_PLLCM33_DIV16, 4, 3, 2, 3),
DEF_MOD("gtm_1_pclk", CLK_PLLCM33_DIV16, 4, 4, 2, 4),
DEF_MOD("gtm_2_pclk", CLK_PLLCLN_DIV16, 4, 5, 2, 5),
@@ -119,6 +136,7 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
};
static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
+ DEF_RST(3, 6, 1, 7), /* ICU_0_PRESETN_I */
DEF_RST(6, 13, 2, 30), /* GTM_0_PRESETZ */
DEF_RST(6, 14, 2, 31), /* GTM_1_PRESETZ */
DEF_RST(6, 15, 3, 0), /* GTM_2_PRESETZ */
diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c
index 42b126ea3e13..a45f8e7e9ab6 100644
--- a/drivers/clk/renesas/rcar-cpg-lib.c
+++ b/drivers/clk/renesas/rcar-cpg-lib.c
@@ -206,4 +206,3 @@ struct clk * __init cpg_rpcd2_clk_register(const char *name,
return clk;
}
-
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c
index 20b89eb6c35c..027100e84ee4 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.c
+++ b/drivers/clk/renesas/rcar-gen3-cpg.c
@@ -335,7 +335,6 @@ static u32 cpg_quirks __initdata;
#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
-
static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
{
.soc_id = "r8a7796", .revision = "ES1.0",
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index 1b421b809796..79e7a90c3b1b 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -39,7 +39,6 @@
#define WARN_DEBUG(x) do { } while (0)
#endif
-
/*
* Module Standby and Software Reset register offets.
*
@@ -716,7 +715,6 @@ static inline int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
}
#endif /* !CONFIG_RESET_CONTROLLER */
-
static const struct of_device_id cpg_mssr_match[] = {
#ifdef CONFIG_CLK_R7S9210
{
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 88bf39e8c79c..ddf722ca79eb 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -548,7 +548,7 @@ static unsigned long
rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
unsigned long rate)
{
- unsigned long foutpostdiv_rate;
+ unsigned long foutpostdiv_rate, foutvco_rate;
params->pl5_intin = rate / MEGA;
params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA);
@@ -557,10 +557,11 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
params->pl5_postdiv2 = 1;
params->pl5_spread = 0x16;
- foutpostdiv_rate =
- EXTAL_FREQ_IN_MEGA_HZ * MEGA / params->pl5_refdiv *
- ((((params->pl5_intin << 24) + params->pl5_fracin)) >> 24) /
- (params->pl5_postdiv1 * params->pl5_postdiv2);
+ foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA,
+ (params->pl5_intin << 24) + params->pl5_fracin),
+ params->pl5_refdiv) >> 24;
+ foutpostdiv_rate = DIV_ROUND_CLOSEST_ULL(foutvco_rate,
+ params->pl5_postdiv1 * params->pl5_postdiv2);
return foutpostdiv_rate;
}
@@ -1680,23 +1681,31 @@ static int rzg2l_cpg_power_off(struct generic_pm_domain *domain)
return 0;
}
-static int __init rzg2l_cpg_pd_setup(struct rzg2l_cpg_pd *pd, bool always_on)
+static int __init rzg2l_cpg_pd_setup(struct rzg2l_cpg_pd *pd)
{
+ bool always_on = !!(pd->genpd.flags & GENPD_FLAG_ALWAYS_ON);
struct dev_power_governor *governor;
+ int ret;
+
+ if (always_on)
+ governor = &pm_domain_always_on_gov;
+ else
+ governor = &simple_qos_governor;
pd->genpd.flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
pd->genpd.attach_dev = rzg2l_cpg_attach_dev;
pd->genpd.detach_dev = rzg2l_cpg_detach_dev;
- if (always_on) {
- pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
- governor = &pm_domain_always_on_gov;
- } else {
- pd->genpd.power_on = rzg2l_cpg_power_on;
- pd->genpd.power_off = rzg2l_cpg_power_off;
- governor = &simple_qos_governor;
- }
+ pd->genpd.power_on = rzg2l_cpg_power_on;
+ pd->genpd.power_off = rzg2l_cpg_power_off;
+
+ ret = pm_genpd_init(&pd->genpd, governor, !always_on);
+ if (ret)
+ return ret;
- return pm_genpd_init(&pd->genpd, governor, !always_on);
+ if (always_on)
+ ret = rzg2l_cpg_power_on(&pd->genpd);
+
+ return ret;
}
static int __init rzg2l_cpg_add_clk_domain(struct rzg2l_cpg_priv *priv)
@@ -1711,8 +1720,9 @@ static int __init rzg2l_cpg_add_clk_domain(struct rzg2l_cpg_priv *priv)
return -ENOMEM;
pd->genpd.name = np->name;
+ pd->genpd.flags = GENPD_FLAG_ALWAYS_ON;
pd->priv = priv;
- ret = rzg2l_cpg_pd_setup(pd, true);
+ ret = rzg2l_cpg_pd_setup(pd);
if (ret)
return ret;
@@ -1777,7 +1787,6 @@ static int __init rzg2l_cpg_add_pm_domains(struct rzg2l_cpg_priv *priv)
return ret;
for (unsigned int i = 0; i < info->num_pm_domains; i++) {
- bool always_on = !!(info->pm_domains[i].flags & RZG2L_PD_F_ALWAYS_ON);
struct rzg2l_cpg_pd *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
@@ -1785,20 +1794,15 @@ static int __init rzg2l_cpg_add_pm_domains(struct rzg2l_cpg_priv *priv)
return -ENOMEM;
pd->genpd.name = info->pm_domains[i].name;
+ pd->genpd.flags = info->pm_domains[i].genpd_flags;
pd->conf = info->pm_domains[i].conf;
pd->id = info->pm_domains[i].id;
pd->priv = priv;
- ret = rzg2l_cpg_pd_setup(pd, always_on);
+ ret = rzg2l_cpg_pd_setup(pd);
if (ret)
return ret;
- if (always_on) {
- ret = rzg2l_cpg_power_on(&pd->genpd);
- if (ret)
- return ret;
- }
-
domains->domains[i] = &pd->genpd;
/* Parent should be on the very first entry of info->pm_domains[]. */
if (!i) {
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index ecfe7e7ea8a1..881a89b5a710 100644
--- a/drivers/clk/renesas/rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -270,14 +270,14 @@ struct rzg2l_cpg_pm_domain_conf {
* struct rzg2l_cpg_pm_domain_init_data - PM domain init data
* @name: PM domain name
* @conf: PM domain configuration
- * @flags: RZG2L PM domain flags (see RZG2L_PD_F_*)
+ * @genpd_flags: genpd flags (see GENPD_FLAG_*)
* @id: PM domain ID (similar to the ones defined in
* include/dt-bindings/clock/<soc-id>-cpg.h)
*/
struct rzg2l_cpg_pm_domain_init_data {
const char * const name;
struct rzg2l_cpg_pm_domain_conf conf;
- u32 flags;
+ u32 genpd_flags;
u16 id;
};
@@ -288,13 +288,9 @@ struct rzg2l_cpg_pm_domain_init_data {
.conf = { \
.mstop = (_mstop_conf), \
}, \
- .flags = (_flags), \
+ .genpd_flags = (_flags), \
}
-/* Power domain flags. */
-#define RZG2L_PD_F_ALWAYS_ON BIT(0)
-#define RZG2L_PD_F_NONE (0)
-
/**
* struct rzg2l_cpg_info - SoC-specific CPG Description
*
diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h
index 1bd406c69015..819029c81904 100644
--- a/drivers/clk/renesas/rzv2h-cpg.h
+++ b/drivers/clk/renesas/rzv2h-cpg.h
@@ -32,8 +32,13 @@ struct ddiv {
})
#define CPG_CDDIV0 (0x400)
+#define CPG_CDDIV1 (0x404)
#define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2)
+#define CDDIV1_DIVCTL0 DDIV_PACK(CPG_CDDIV1, 0, 2, 4)
+#define CDDIV1_DIVCTL1 DDIV_PACK(CPG_CDDIV1, 4, 2, 5)
+#define CDDIV1_DIVCTL2 DDIV_PACK(CPG_CDDIV1, 8, 2, 6)
+#define CDDIV1_DIVCTL3 DDIV_PACK(CPG_CDDIV1, 12, 2, 7)
/**
* Definitions of CPG Core Clocks
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index f1ba48758c78..7a88331a658d 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos-arm64.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7885.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos850.o
+obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos8895.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov9.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov920.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-gs101.o
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index abd49edcf707..e11ac67819ef 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -4,7 +4,7 @@
* Author: Padmavathi Venna <padma.v@samsung.com>
*
* Common Clock Framework support for Audio Subsystem Clock Controller.
-*/
+ */
#include <linux/slab.h>
#include <linux/io.h>
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index cd4fec323a42..aec4d18c1f9e 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -260,7 +260,7 @@ static const struct samsung_mux_clock mux_clks[] __initconst = {
/* SRC_TOP0 */
MUX(CLK_MOUT_EBI, "mout_ebi", mout_ebi_p, SRC_TOP0, 28, 1),
- MUX(CLK_MOUT_ACLK_200, "mout_aclk_200", group_div_mpll_pre_p,SRC_TOP0, 24, 1),
+ MUX(CLK_MOUT_ACLK_200, "mout_aclk_200", group_div_mpll_pre_p, SRC_TOP0, 24, 1),
MUX(CLK_MOUT_ACLK_160, "mout_aclk_160", group_div_mpll_pre_p, SRC_TOP0, 20, 1),
MUX(CLK_MOUT_ACLK_100, "mout_aclk_100", group_div_mpll_pre_p, SRC_TOP0, 16, 1),
MUX(CLK_MOUT_ACLK_266_1, "mout_aclk_266_1", mout_aclk_266_1_p, SRC_TOP0, 14, 1),
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 28945b6b0ee1..16be0c53903c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -5,7 +5,7 @@
* Author: Thomas Abraham <thomas.ab@samsung.com>
*
* Common Clock Framework support for all Exynos4 SoCs.
-*/
+ */
#include <dt-bindings/clock/exynos4.h>
#include <linux/slab.h>
diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c
index a70c2b06a61a..29c5644f0593 100644
--- a/drivers/clk/samsung/clk-exynos4412-isp.c
+++ b/drivers/clk/samsung/clk-exynos4412-isp.c
@@ -4,7 +4,7 @@
* Author: Marek Szyprowski <m.szyprowski@samsung.com>
*
* Common Clock Framework support for Exynos4412 ISP module.
-*/
+ */
#include <dt-bindings/clock/exynos4.h>
#include <linux/slab.h>
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index e02e7c013f3d..47e9ac2275ee 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -5,7 +5,7 @@
* Author: Thomas Abraham <thomas.ab@samsung.com>
*
* Common Clock Framework support for Exynos5250 SoC.
-*/
+ */
#include <dt-bindings/clock/exynos5250.h>
#include <linux/clk-provider.h>
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index 16da6ef5ca0c..fd0520d204dc 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -1458,7 +1458,7 @@ static const struct samsung_fixed_rate_clock fixed_rate_clks[] __initconst = {
FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi",
NULL, 0, 125000000),
FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS,
- "phyclk_mipi_dphy_4l_m_txbyte_clkhs" , NULL,
+ "phyclk_mipi_dphy_4l_m_txbyte_clkhs", NULL,
0, 187500000),
FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m",
NULL, 0, 24000000),
@@ -1629,7 +1629,7 @@ static const struct samsung_mux_clock top_mux_clks[] __initconst = {
mout_isp1_media_400_p,
MUX_SEL_TOP_ISP10, 4, 1),
MUX(TOP_MOUT_ACLK_ISP1_400, "mout_aclk_isp1_400", mout_aclk_isp1_400_p,
- MUX_SEL_TOP_ISP10, 8 , 1),
+ MUX_SEL_TOP_ISP10, 8, 1),
MUX(TOP_MOUT_ISP1_MEDIA_266, "mout_isp1_media_266",
mout_isp1_media_266_p,
MUX_SEL_TOP_ISP10, 16, 1),
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 2654077211e7..99b1bb4539fd 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -4,7 +4,7 @@
* Author: Tarek Dakhran <t.dakhran@samsung.com>
*
* Common Clock Framework support for Exynos5410 SoC.
-*/
+ */
#include <dt-bindings/clock/exynos5410.h>
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index c630135c686b..333c52fda17f 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -5,7 +5,7 @@
* Chander Kashyap <k.chander@samsung.com>
*
* Common Clock Framework support for Exynos5420 SoC.
-*/
+ */
#include <dt-bindings/clock/exynos5420.h>
#include <linux/slab.h>
@@ -295,8 +295,8 @@ static const struct samsung_clk_reg_dump exynos5420_set_clksrc[] = {
/* list of all parent clocks */
PNAME(mout_mspll_cpu_p) = {"mout_sclk_cpll", "mout_sclk_dpll",
"mout_sclk_mpll", "mout_sclk_spll"};
-PNAME(mout_cpu_p) = {"mout_apll" , "mout_mspll_cpu"};
-PNAME(mout_kfc_p) = {"mout_kpll" , "mout_mspll_kfc"};
+PNAME(mout_cpu_p) = {"mout_apll", "mout_mspll_cpu"};
+PNAME(mout_kfc_p) = {"mout_kpll", "mout_mspll_kfc"};
PNAME(mout_apll_p) = {"fin_pll", "fout_apll"};
PNAME(mout_bpll_p) = {"fin_pll", "fout_bpll"};
PNAME(mout_cpll_p) = {"fin_pll", "fout_cpll"};
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index 4a5d2a914bd6..e6c938effa29 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -2,7 +2,7 @@
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* Author: Naveen Krishna Ch <naveenkrishna.ch@gmail.com>
-*/
+ */
#include <linux/clk-provider.h>
#include <linux/of.h>
diff --git a/drivers/clk/samsung/clk-exynos8895.c b/drivers/clk/samsung/clk-exynos8895.c
new file mode 100644
index 000000000000..29ec0c4a8635
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos8895.c
@@ -0,0 +1,2803 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+ * Author: Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+ *
+ * Common Clock Framework support for Exynos8895 SoC.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/samsung,exynos8895.h>
+
+#include "clk.h"
+#include "clk-exynos-arm64.h"
+
+/* NOTE: Must be equal to the last clock ID increased by one */
+#define CLKS_NR_TOP (CLK_GOUT_CMU_VPU_BUS + 1)
+#define CLKS_NR_FSYS0 (CLK_GOUT_FSYS0_XIU_P_FSYS0_ACLK + 1)
+#define CLKS_NR_FSYS1 (CLK_GOUT_FSYS1_XIU_P_FSYS1_ACLK + 1)
+#define CLKS_NR_PERIC0 (CLK_GOUT_PERIC0_USI03_I_SCLK_USI + 1)
+#define CLKS_NR_PERIC1 (CLK_GOUT_PERIC1_XIU_P_PERIC1_ACLK + 1)
+#define CLKS_NR_PERIS (CLK_GOUT_PERIS_XIU_P_PERIS_ACLK + 1)
+
+/* ---- CMU_TOP ------------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_TOP (0x15a80000) */
+#define PLL_LOCKTIME_PLL_SHARED0 0x0000
+#define PLL_LOCKTIME_PLL_SHARED1 0x0004
+#define PLL_LOCKTIME_PLL_SHARED2 0x0008
+#define PLL_LOCKTIME_PLL_SHARED3 0x000c
+#define PLL_LOCKTIME_PLL_SHARED4 0x0010
+#define PLL_CON0_MUX_CP2AP_MIF_CLK_USER 0x0100
+#define PLL_CON2_MUX_CP2AP_MIF_CLK_USER 0x0108
+#define PLL_CON0_PLL_SHARED0 0x0120
+#define PLL_CON0_PLL_SHARED1 0x0140
+#define PLL_CON0_PLL_SHARED2 0x0160
+#define PLL_CON0_PLL_SHARED3 0x0180
+#define PLL_CON0_PLL_SHARED4 0x01a0
+#define CLK_CON_MUX_MUX_CLKCMU_ABOX_CPUABOX 0x1000
+#define CLK_CON_MUX_MUX_CLKCMU_APM_BUS 0x1004
+#define CLK_CON_MUX_MUX_CLKCMU_BUS1_BUS 0x1008
+#define CLK_CON_MUX_MUX_CLKCMU_BUSC_BUS 0x100c
+#define CLK_CON_MUX_MUX_CLKCMU_BUSC_BUSPHSI2C 0x1010
+#define CLK_CON_MUX_MUX_CLKCMU_CAM_BUS 0x1014
+#define CLK_CON_MUX_MUX_CLKCMU_CAM_TPU0 0x1018
+#define CLK_CON_MUX_MUX_CLKCMU_CAM_TPU1 0x101c
+#define CLK_CON_MUX_MUX_CLKCMU_CAM_VRA 0x1020
+#define CLK_CON_MUX_MUX_CLKCMU_CIS_CLK0 0x1024
+#define CLK_CON_MUX_MUX_CLKCMU_CIS_CLK1 0x1028
+#define CLK_CON_MUX_MUX_CLKCMU_CIS_CLK2 0x102c
+#define CLK_CON_MUX_MUX_CLKCMU_CIS_CLK3 0x1030
+#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1034
+#define CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH 0x1038
+#define CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH 0x103c
+#define CLK_CON_MUX_MUX_CLKCMU_DBG_BUS 0x1040
+#define CLK_CON_MUX_MUX_CLKCMU_DCAM_BUS 0x1044
+#define CLK_CON_MUX_MUX_CLKCMU_DCAM_IMGD 0x1048
+#define CLK_CON_MUX_MUX_CLKCMU_DPU_BUS 0x104c
+#define CLK_CON_MUX_MUX_CLKCMU_DROOPDETECTOR 0x1050
+#define CLK_CON_MUX_MUX_CLKCMU_DSP_BUS 0x1054
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS0_BUS 0x1058
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS0_DPGTC 0x105c
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS0_MMC_EMBD 0x1060
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS0_UFS_EMBD 0x1064
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS0_USBDRD30 0x1068
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS1_BUS 0x106c
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS1_MMC_CARD 0x1070
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS1_PCIE 0x1074
+#define CLK_CON_MUX_MUX_CLKCMU_FSYS1_UFS_CARD 0x1078
+#define CLK_CON_MUX_MUX_CLKCMU_G2D_G2D 0x107c
+#define CLK_CON_MUX_MUX_CLKCMU_G2D_JPEG 0x1080
+#define CLK_CON_MUX_MUX_CLKCMU_HPM 0x1084
+#define CLK_CON_MUX_MUX_CLKCMU_IMEM_BUS 0x1088
+#define CLK_CON_MUX_MUX_CLKCMU_ISPHQ_BUS 0x108c
+#define CLK_CON_MUX_MUX_CLKCMU_ISPLP_BUS 0x1090
+#define CLK_CON_MUX_MUX_CLKCMU_IVA_BUS 0x1094
+#define CLK_CON_MUX_MUX_CLKCMU_MFC_BUS 0x1098
+#define CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH 0x109c
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_BUS 0x10a0
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_UART_DBG 0x10a4
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI00 0x10a8
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI01 0x10ac
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI02 0x10b0
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI03 0x10b4
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_BUS 0x10b8
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPEEDY2 0x10bc
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPI_CAM0 0x10c0
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPI_CAM1 0x10c4
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_UART_BT 0x10c8
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI04 0x10cc
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI05 0x10d0
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI06 0x10d4
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI07 0x10d8
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI08 0x10dc
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI09 0x10e0
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI10 0x10e4
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI11 0x10e8
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI12 0x10ec
+#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI13 0x10f0
+#define CLK_CON_MUX_MUX_CLKCMU_PERIS_BUS 0x10f4
+#define CLK_CON_MUX_MUX_CLKCMU_SRDZ_BUS 0x10f8
+#define CLK_CON_MUX_MUX_CLKCMU_SRDZ_IMGD 0x10fc
+#define CLK_CON_MUX_MUX_CLKCMU_VPU_BUS 0x1100
+#define CLK_CON_MUX_MUX_CLK_CMU_CMUREF 0x1104
+#define CLK_CON_MUX_MUX_CMU_CMUREF 0x1108
+#define CLK_CON_DIV_CLKCMU_ABOX_CPUABOX 0x1800
+#define CLK_CON_DIV_CLKCMU_APM_BUS 0x1804
+#define CLK_CON_DIV_CLKCMU_BUS1_BUS 0x1808
+#define CLK_CON_DIV_CLKCMU_BUSC_BUS 0x180c
+#define CLK_CON_DIV_CLKCMU_BUSC_BUSPHSI2C 0x1810
+#define CLK_CON_DIV_CLKCMU_CAM_BUS 0x1814
+#define CLK_CON_DIV_CLKCMU_CAM_TPU0 0x1818
+#define CLK_CON_DIV_CLKCMU_CAM_TPU1 0x181c
+#define CLK_CON_DIV_CLKCMU_CAM_VRA 0x1820
+#define CLK_CON_DIV_CLKCMU_CIS_CLK0 0x1824
+#define CLK_CON_DIV_CLKCMU_CIS_CLK1 0x1828
+#define CLK_CON_DIV_CLKCMU_CIS_CLK2 0x182c
+#define CLK_CON_DIV_CLKCMU_CIS_CLK3 0x1830
+#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x1834
+#define CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH 0x1838
+#define CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH 0x183c
+#define CLK_CON_DIV_CLKCMU_DBG_BUS 0x1840
+#define CLK_CON_DIV_CLKCMU_DCAM_BUS 0x1844
+#define CLK_CON_DIV_CLKCMU_DCAM_IMGD 0x1848
+#define CLK_CON_DIV_CLKCMU_DPU_BUS 0x184c
+#define CLK_CON_DIV_CLKCMU_DSP_BUS 0x1850
+#define CLK_CON_DIV_CLKCMU_FSYS0_BUS 0x1854
+#define CLK_CON_DIV_CLKCMU_FSYS0_DPGTC 0x1858
+#define CLK_CON_DIV_CLKCMU_FSYS0_MMC_EMBD 0x185c
+#define CLK_CON_DIV_CLKCMU_FSYS0_UFS_EMBD 0x1860
+#define CLK_CON_DIV_CLKCMU_FSYS0_USBDRD30 0x1864
+#define CLK_CON_DIV_CLKCMU_FSYS1_BUS 0x1868
+#define CLK_CON_DIV_CLKCMU_FSYS1_MMC_CARD 0x186c
+#define CLK_CON_DIV_CLKCMU_FSYS1_PCIE 0x1870
+#define CLK_CON_DIV_CLKCMU_FSYS1_UFS_CARD 0x1874
+#define CLK_CON_DIV_CLKCMU_G2D_G2D 0x1878
+#define CLK_CON_DIV_CLKCMU_G2D_JPEG 0x187c
+#define CLK_CON_DIV_CLKCMU_G3D_SWITCH 0x1880
+#define CLK_CON_DIV_CLKCMU_HPM 0x1884
+#define CLK_CON_DIV_CLKCMU_IMEM_BUS 0x1888
+#define CLK_CON_DIV_CLKCMU_ISPHQ_BUS 0x188c
+#define CLK_CON_DIV_CLKCMU_ISPLP_BUS 0x1890
+#define CLK_CON_DIV_CLKCMU_IVA_BUS 0x1894
+#define CLK_CON_DIV_CLKCMU_MFC_BUS 0x1898
+#define CLK_CON_DIV_CLKCMU_MODEM_SHARED0 0x189c
+#define CLK_CON_DIV_CLKCMU_MODEM_SHARED1 0x18a0
+#define CLK_CON_DIV_CLKCMU_OTP 0x18a4
+#define CLK_CON_DIV_CLKCMU_PERIC0_BUS 0x18a8
+#define CLK_CON_DIV_CLKCMU_PERIC0_UART_DBG 0x18ac
+#define CLK_CON_DIV_CLKCMU_PERIC0_USI00 0x18b0
+#define CLK_CON_DIV_CLKCMU_PERIC0_USI01 0x18b4
+#define CLK_CON_DIV_CLKCMU_PERIC0_USI02 0x18b8
+#define CLK_CON_DIV_CLKCMU_PERIC0_USI03 0x18bc
+#define CLK_CON_DIV_CLKCMU_PERIC1_BUS 0x18c0
+#define CLK_CON_DIV_CLKCMU_PERIC1_SPEEDY2 0x18c4
+#define CLK_CON_DIV_CLKCMU_PERIC1_SPI_CAM0 0x18c8
+#define CLK_CON_DIV_CLKCMU_PERIC1_SPI_CAM1 0x18cc
+#define CLK_CON_DIV_CLKCMU_PERIC1_UART_BT 0x18d0
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI04 0x18d4
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI05 0x18d8
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI06 0x18dc
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI07 0x18e0
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI08 0x18e4
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI09 0x18e8
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI10 0x18ec
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI11 0x18f0
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI12 0x18f4
+#define CLK_CON_DIV_CLKCMU_PERIC1_USI13 0x18f8
+#define CLK_CON_DIV_CLKCMU_PERIS_BUS 0x18fc
+#define CLK_CON_DIV_CLKCMU_SRDZ_BUS 0x1900
+#define CLK_CON_DIV_CLKCMU_SRDZ_IMGD 0x1904
+#define CLK_CON_DIV_CLKCMU_VPU_BUS 0x1908
+#define CLK_CON_DIV_DIV_CLK_CMU_CMUREF 0x190c
+#define CLK_CON_DIV_DIV_CP2AP_MIF_CLK_DIV2 0x1910
+#define CLK_CON_DIV_DIV_PLL_SHARED0_DIV2 0x1914
+#define CLK_CON_DIV_DIV_PLL_SHARED0_DIV4 0x1918
+#define CLK_CON_DIV_DIV_PLL_SHARED1_DIV2 0x191c
+#define CLK_CON_DIV_DIV_PLL_SHARED1_DIV4 0x1920
+#define CLK_CON_DIV_DIV_PLL_SHARED2_DIV2 0x1924
+#define CLK_CON_DIV_DIV_PLL_SHARED3_DIV2 0x1928
+#define CLK_CON_DIV_DIV_PLL_SHARED4_DIV2 0x192c
+#define CLK_CON_GAT_CLKCMU_DROOPDETECTOR 0x2000
+#define CLK_CON_GAT_CLKCMU_MIF_SWITCH 0x2004
+#define CLK_CON_GAT_GATE_CLKCMU_ABOX_CPUABOX 0x2008
+#define CLK_CON_GAT_GATE_CLKCMU_APM_BUS 0x200c
+#define CLK_CON_GAT_GATE_CLKCMU_BUS1_BUS 0x2010
+#define CLK_CON_GAT_GATE_CLKCMU_BUSC_BUS 0x2014
+#define CLK_CON_GAT_GATE_CLKCMU_BUSC_BUSPHSI2C 0x2018
+#define CLK_CON_GAT_GATE_CLKCMU_CAM_BUS 0x201c
+#define CLK_CON_GAT_GATE_CLKCMU_CAM_TPU0 0x2020
+#define CLK_CON_GAT_GATE_CLKCMU_CAM_TPU1 0x2024
+#define CLK_CON_GAT_GATE_CLKCMU_CAM_VRA 0x2028
+#define CLK_CON_GAT_GATE_CLKCMU_CIS_CLK0 0x202c
+#define CLK_CON_GAT_GATE_CLKCMU_CIS_CLK1 0x2030
+#define CLK_CON_GAT_GATE_CLKCMU_CIS_CLK2 0x2034
+#define CLK_CON_GAT_GATE_CLKCMU_CIS_CLK3 0x2038
+#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x203c
+#define CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH 0x2040
+#define CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH 0x2044
+#define CLK_CON_GAT_GATE_CLKCMU_DBG_BUS 0x2048
+#define CLK_CON_GAT_GATE_CLKCMU_DCAM_BUS 0x204c
+#define CLK_CON_GAT_GATE_CLKCMU_DCAM_IMGD 0x2050
+#define CLK_CON_GAT_GATE_CLKCMU_DPU_BUS 0x2054
+#define CLK_CON_GAT_GATE_CLKCMU_DSP_BUS 0x2058
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS0_BUS 0x205c
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS0_DPGTC 0x2060
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS0_MMC_EMBD 0x2064
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS0_UFS_EMBD 0x2068
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS0_USBDRD30 0x206c
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS1_BUS 0x2070
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS1_MMC_CARD 0x2074
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS1_PCIE 0x2078
+#define CLK_CON_GAT_GATE_CLKCMU_FSYS1_UFS_CARD 0x207c
+#define CLK_CON_GAT_GATE_CLKCMU_G2D_G2D 0x2080
+#define CLK_CON_GAT_GATE_CLKCMU_G2D_JPEG 0x2084
+#define CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH 0x2088
+#define CLK_CON_GAT_GATE_CLKCMU_HPM 0x208c
+#define CLK_CON_GAT_GATE_CLKCMU_IMEM_BUS 0x2090
+#define CLK_CON_GAT_GATE_CLKCMU_ISPHQ_BUS 0x2094
+#define CLK_CON_GAT_GATE_CLKCMU_ISPLP_BUS 0x2098
+#define CLK_CON_GAT_GATE_CLKCMU_IVA_BUS 0x209c
+#define CLK_CON_GAT_GATE_CLKCMU_MFC_BUS 0x20a0
+#define CLK_CON_GAT_GATE_CLKCMU_MODEM_SHARED0 0x20a4
+#define CLK_CON_GAT_GATE_CLKCMU_MODEM_SHARED1 0x20a8
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_BUS 0x20ac
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_UART_DBG 0x20b0
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI00 0x20b4
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI01 0x20b8
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI02 0x20bc
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI03 0x20c0
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_BUS 0x20c4
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPEEDY2 0x20c8
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPI_CAM0 0x20cc
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPI_CAM1 0x20d0
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_UART_BT 0x20d4
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI04 0x20d8
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI05 0x20dc
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI06 0x20e0
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI07 0x20e4
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI08 0x20e8
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI09 0x20ec
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI10 0x20f0
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI11 0x20f4
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI12 0x20f8
+#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI13 0x20fc
+#define CLK_CON_GAT_GATE_CLKCMU_PERIS_BUS 0x2100
+#define CLK_CON_GAT_GATE_CLKCMU_SRDZ_BUS 0x2104
+#define CLK_CON_GAT_GATE_CLKCMU_SRDZ_IMGD 0x2108
+#define CLK_CON_GAT_GATE_CLKCMU_VPU_BUS 0x210c
+
+static const unsigned long top_clk_regs[] __initconst = {
+ PLL_LOCKTIME_PLL_SHARED0,
+ PLL_LOCKTIME_PLL_SHARED1,
+ PLL_LOCKTIME_PLL_SHARED2,
+ PLL_LOCKTIME_PLL_SHARED3,
+ PLL_LOCKTIME_PLL_SHARED4,
+ PLL_CON0_MUX_CP2AP_MIF_CLK_USER,
+ PLL_CON2_MUX_CP2AP_MIF_CLK_USER,
+ PLL_CON0_PLL_SHARED0,
+ PLL_CON0_PLL_SHARED1,
+ PLL_CON0_PLL_SHARED2,
+ PLL_CON0_PLL_SHARED3,
+ PLL_CON0_PLL_SHARED4,
+ CLK_CON_MUX_MUX_CLKCMU_ABOX_CPUABOX,
+ CLK_CON_MUX_MUX_CLKCMU_APM_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_BUS1_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_BUSC_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_BUSC_BUSPHSI2C,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_TPU0,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_TPU1,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_VRA,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK0,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK1,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK2,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK3,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH,
+ CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH,
+ CLK_CON_MUX_MUX_CLKCMU_DBG_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_DCAM_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_DCAM_IMGD,
+ CLK_CON_MUX_MUX_CLKCMU_DPU_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_DROOPDETECTOR,
+ CLK_CON_MUX_MUX_CLKCMU_DSP_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS0_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS0_DPGTC,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS0_MMC_EMBD,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS0_UFS_EMBD,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS0_USBDRD30,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS1_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS1_MMC_CARD,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS1_PCIE,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS1_UFS_CARD,
+ CLK_CON_MUX_MUX_CLKCMU_G2D_G2D,
+ CLK_CON_MUX_MUX_CLKCMU_G2D_JPEG,
+ CLK_CON_MUX_MUX_CLKCMU_HPM,
+ CLK_CON_MUX_MUX_CLKCMU_IMEM_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_ISPHQ_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_ISPLP_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_IVA_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_MFC_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC0_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC0_UART_DBG,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI00,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI01,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI02,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI03,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPEEDY2,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPI_CAM0,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPI_CAM1,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_UART_BT,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI04,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI05,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI06,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI07,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI08,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI09,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI10,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI11,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI12,
+ CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI13,
+ CLK_CON_MUX_MUX_CLKCMU_PERIS_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_SRDZ_BUS,
+ CLK_CON_MUX_MUX_CLKCMU_SRDZ_IMGD,
+ CLK_CON_MUX_MUX_CLKCMU_VPU_BUS,
+ CLK_CON_MUX_MUX_CLK_CMU_CMUREF,
+ CLK_CON_MUX_MUX_CMU_CMUREF,
+ CLK_CON_DIV_CLKCMU_ABOX_CPUABOX,
+ CLK_CON_DIV_CLKCMU_APM_BUS,
+ CLK_CON_DIV_CLKCMU_BUS1_BUS,
+ CLK_CON_DIV_CLKCMU_BUSC_BUS,
+ CLK_CON_DIV_CLKCMU_BUSC_BUSPHSI2C,
+ CLK_CON_DIV_CLKCMU_CAM_BUS,
+ CLK_CON_DIV_CLKCMU_CAM_TPU0,
+ CLK_CON_DIV_CLKCMU_CAM_TPU1,
+ CLK_CON_DIV_CLKCMU_CAM_VRA,
+ CLK_CON_DIV_CLKCMU_CIS_CLK0,
+ CLK_CON_DIV_CLKCMU_CIS_CLK1,
+ CLK_CON_DIV_CLKCMU_CIS_CLK2,
+ CLK_CON_DIV_CLKCMU_CIS_CLK3,
+ CLK_CON_DIV_CLKCMU_CORE_BUS,
+ CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH,
+ CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH,
+ CLK_CON_DIV_CLKCMU_DBG_BUS,
+ CLK_CON_DIV_CLKCMU_DCAM_BUS,
+ CLK_CON_DIV_CLKCMU_DCAM_IMGD,
+ CLK_CON_DIV_CLKCMU_DPU_BUS,
+ CLK_CON_DIV_CLKCMU_DSP_BUS,
+ CLK_CON_DIV_CLKCMU_FSYS0_BUS,
+ CLK_CON_DIV_CLKCMU_FSYS0_DPGTC,
+ CLK_CON_DIV_CLKCMU_FSYS0_MMC_EMBD,
+ CLK_CON_DIV_CLKCMU_FSYS0_UFS_EMBD,
+ CLK_CON_DIV_CLKCMU_FSYS0_USBDRD30,
+ CLK_CON_DIV_CLKCMU_FSYS1_BUS,
+ CLK_CON_DIV_CLKCMU_FSYS1_MMC_CARD,
+ CLK_CON_DIV_CLKCMU_FSYS1_PCIE,
+ CLK_CON_DIV_CLKCMU_FSYS1_UFS_CARD,
+ CLK_CON_DIV_CLKCMU_G2D_G2D,
+ CLK_CON_DIV_CLKCMU_G2D_JPEG,
+ CLK_CON_DIV_CLKCMU_G3D_SWITCH,
+ CLK_CON_DIV_CLKCMU_HPM,
+ CLK_CON_DIV_CLKCMU_IMEM_BUS,
+ CLK_CON_DIV_CLKCMU_ISPHQ_BUS,
+ CLK_CON_DIV_CLKCMU_ISPLP_BUS,
+ CLK_CON_DIV_CLKCMU_IVA_BUS,
+ CLK_CON_DIV_CLKCMU_MFC_BUS,
+ CLK_CON_DIV_CLKCMU_MODEM_SHARED0,
+ CLK_CON_DIV_CLKCMU_MODEM_SHARED1,
+ CLK_CON_DIV_CLKCMU_OTP,
+ CLK_CON_DIV_CLKCMU_PERIC0_BUS,
+ CLK_CON_DIV_CLKCMU_PERIC0_UART_DBG,
+ CLK_CON_DIV_CLKCMU_PERIC0_USI00,
+ CLK_CON_DIV_CLKCMU_PERIC0_USI01,
+ CLK_CON_DIV_CLKCMU_PERIC0_USI02,
+ CLK_CON_DIV_CLKCMU_PERIC0_USI03,
+ CLK_CON_DIV_CLKCMU_PERIC1_BUS,
+ CLK_CON_DIV_CLKCMU_PERIC1_SPEEDY2,
+ CLK_CON_DIV_CLKCMU_PERIC1_SPI_CAM0,
+ CLK_CON_DIV_CLKCMU_PERIC1_SPI_CAM1,
+ CLK_CON_DIV_CLKCMU_PERIC1_UART_BT,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI04,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI05,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI06,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI07,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI08,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI09,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI10,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI11,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI12,
+ CLK_CON_DIV_CLKCMU_PERIC1_USI13,
+ CLK_CON_DIV_CLKCMU_PERIS_BUS,
+ CLK_CON_DIV_CLKCMU_SRDZ_BUS,
+ CLK_CON_DIV_CLKCMU_SRDZ_IMGD,
+ CLK_CON_DIV_CLKCMU_VPU_BUS,
+ CLK_CON_DIV_DIV_CLK_CMU_CMUREF,
+ CLK_CON_DIV_DIV_CP2AP_MIF_CLK_DIV2,
+ CLK_CON_DIV_DIV_PLL_SHARED0_DIV2,
+ CLK_CON_DIV_DIV_PLL_SHARED0_DIV4,
+ CLK_CON_DIV_DIV_PLL_SHARED1_DIV2,
+ CLK_CON_DIV_DIV_PLL_SHARED1_DIV4,
+ CLK_CON_DIV_DIV_PLL_SHARED2_DIV2,
+ CLK_CON_DIV_DIV_PLL_SHARED3_DIV2,
+ CLK_CON_DIV_DIV_PLL_SHARED4_DIV2,
+ CLK_CON_GAT_CLKCMU_DROOPDETECTOR,
+ CLK_CON_GAT_CLKCMU_MIF_SWITCH,
+ CLK_CON_GAT_GATE_CLKCMU_ABOX_CPUABOX,
+ CLK_CON_GAT_GATE_CLKCMU_APM_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_BUS1_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_BUSC_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_BUSC_BUSPHSI2C,
+ CLK_CON_GAT_GATE_CLKCMU_CAM_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_CAM_TPU0,
+ CLK_CON_GAT_GATE_CLKCMU_CAM_TPU1,
+ CLK_CON_GAT_GATE_CLKCMU_CAM_VRA,
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK0,
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK1,
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK2,
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK3,
+ CLK_CON_GAT_GATE_CLKCMU_CORE_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH,
+ CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH,
+ CLK_CON_GAT_GATE_CLKCMU_DBG_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_DCAM_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_DCAM_IMGD,
+ CLK_CON_GAT_GATE_CLKCMU_DPU_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_DSP_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS0_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS0_DPGTC,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS0_MMC_EMBD,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS0_UFS_EMBD,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS0_USBDRD30,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS1_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS1_MMC_CARD,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS1_PCIE,
+ CLK_CON_GAT_GATE_CLKCMU_FSYS1_UFS_CARD,
+ CLK_CON_GAT_GATE_CLKCMU_G2D_G2D,
+ CLK_CON_GAT_GATE_CLKCMU_G2D_JPEG,
+ CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH,
+ CLK_CON_GAT_GATE_CLKCMU_HPM,
+ CLK_CON_GAT_GATE_CLKCMU_IMEM_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_ISPHQ_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_ISPLP_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_IVA_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_MFC_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_MODEM_SHARED0,
+ CLK_CON_GAT_GATE_CLKCMU_MODEM_SHARED1,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC0_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC0_UART_DBG,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI00,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI01,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI02,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI03,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPEEDY2,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPI_CAM0,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPI_CAM1,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_UART_BT,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI04,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI05,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI06,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI07,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI08,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI09,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI10,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI11,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI12,
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI13,
+ CLK_CON_GAT_GATE_CLKCMU_PERIS_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_SRDZ_BUS,
+ CLK_CON_GAT_GATE_CLKCMU_SRDZ_IMGD,
+ CLK_CON_GAT_GATE_CLKCMU_VPU_BUS,
+};
+
+static const struct samsung_pll_rate_table pll_shared0_rate_table[] __initconst = {
+ PLL_35XX_RATE(26 * MHZ, 2132000000U, 328, 4, 0),
+};
+
+static const struct samsung_pll_rate_table pll_shared1_rate_table[] __initconst = {
+ PLL_35XX_RATE(26 * MHZ, 1865500000U, 287, 4, 0),
+};
+
+static const struct samsung_pll_rate_table pll_shared2_rate_table[] __initconst = {
+ PLL_35XX_RATE(26 * MHZ, 800000000U, 400, 13, 0),
+};
+
+static const struct samsung_pll_rate_table pll_shared3_rate_table[] __initconst = {
+ PLL_35XX_RATE(26 * MHZ, 630000000U, 315, 13, 0),
+};
+
+static const struct samsung_pll_rate_table pll_shared4_rate_table[] __initconst = {
+ PLL_35XX_RATE(26 * MHZ, 667333333U, 154, 6, 0),
+};
+
+static const struct samsung_pll_clock top_pll_clks[] __initconst = {
+ /* CMU_TOP_PURECLKCOMP */
+ PLL(pll_1051x, CLK_FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED0, PLL_CON0_PLL_SHARED0,
+ pll_shared0_rate_table),
+ PLL(pll_1051x, CLK_FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED1, PLL_CON0_PLL_SHARED1,
+ pll_shared1_rate_table),
+ PLL(pll_1052x, CLK_FOUT_SHARED2_PLL, "fout_shared2_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED2, PLL_CON0_PLL_SHARED2,
+ pll_shared2_rate_table),
+ PLL(pll_1052x, CLK_FOUT_SHARED3_PLL, "fout_shared3_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED3, PLL_CON0_PLL_SHARED3,
+ pll_shared3_rate_table),
+ PLL(pll_1052x, CLK_FOUT_SHARED4_PLL, "fout_shared4_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED4, PLL_CON0_PLL_SHARED4,
+ pll_shared4_rate_table),
+};
+
+/* List of parent clocks for Muxes in CMU_TOP */
+PNAME(mout_pll_shared0_p) = { "oscclk", "fout_shared0_pll" };
+PNAME(mout_pll_shared1_p) = { "oscclk", "fout_shared1_pll" };
+PNAME(mout_pll_shared2_p) = { "oscclk", "fout_shared2_pll" };
+PNAME(mout_pll_shared3_p) = { "oscclk", "fout_shared3_pll" };
+PNAME(mout_pll_shared4_p) = { "oscclk", "fout_shared4_pll" };
+PNAME(mout_cp2ap_mif_clk_user_p) = { "oscclk" };
+PNAME(mout_cmu_abox_cpuabox_p) = { "dout_cmu_shared0_div2",
+ "dout_cmu_shared1_div2",
+ "fout_shared2_pll",
+ "fout_shared4_pll" };
+PNAME(mout_cmu_apm_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_bus1_bus_p) = { "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_busc_bus_p) = { "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_cp2ap_mif_clk_div2",
+ "oscclk", "oscclk", "oscclk" };
+PNAME(mout_cmu_busc_busphsi2c_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_cp2ap_mif_clk_div2",
+ "oscclk" };
+PNAME(mout_cmu_cam_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_cam_tpu0_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_cam_tpu1_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_cam_vra_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_cis_clk0_p) = { "oscclk",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_cis_clk1_p) = { "oscclk",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_cis_clk2_p) = { "oscclk",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_cis_clk3_p) = { "oscclk",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_core_bus_p) = { "dout_cmu_shared0_div2",
+ "dout_cmu_shared1_div2",
+ "fout_shared2_pll",
+ "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_cp2ap_mif_clk_div2" };
+PNAME(mout_cmu_cpucl0_switch_p) = { "dout_cmu_shared0_div2",
+ "dout_cmu_shared1_div2",
+ "fout_shared2_pll",
+ "fout_shared4_pll" };
+PNAME(mout_cmu_cpucl1_switch_p) = { "dout_cmu_shared0_div2",
+ "dout_cmu_shared1_div2",
+ "fout_shared2_pll",
+ "fout_shared4_pll" };
+PNAME(mout_cmu_dbg_bus_p) = { "fout_shared2_pll",
+ "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4" };
+PNAME(mout_cmu_dcam_bus_p) = { "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_dcam_imgd_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_dpu_bus_p) = { "dout_cmu_shared0_div2",
+ "fout_shared3_pll",
+ "fout_shared4_pll",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "oscclk", "oscclk", "oscclk" };
+PNAME(mout_cmu_droopdetector_p) = { "oscclk", "dout_cmu_shared0_div2",
+ "dout_cmu_shared1_div2",
+ "fout_shared2_pll" };
+PNAME(mout_cmu_dsp_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_fsys0_bus_p) = { "dout_cmu_shared1_div2",
+ "fout_shared2_pll",
+ "fout_shared4_pll",
+ "dout_cmu_shared0_div4" };
+PNAME(mout_fsys0_dpgtc_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_fsys0_mmc_embd_p) = { "oscclk", "fout_shared2_pll",
+ "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "oscclk", "oscclk", "oscclk" };
+PNAME(mout_fsys0_ufs_embd_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_fsys0_usbdrd30_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_fsys1_bus_p) = { "fout_shared2_pll",
+ "dout_cmu_shared0_div4" };
+PNAME(mout_cmu_fsys1_mmc_card_p) = { "oscclk", "fout_shared2_pll",
+ "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "oscclk", "oscclk", "oscclk" };
+PNAME(mout_cmu_fsys1_pcie_p) = { "oscclk", "fout_shared2_pll" };
+PNAME(mout_cmu_fsys1_ufs_card_p) = { "oscclk",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_g2d_g2d_p) = { "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_g2d_jpeg_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_hpm_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_imem_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_isphq_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_isplp_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_iva_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_mfc_bus_p) = { "fout_shared4_pll",
+ "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_mif_switch_p) = { "fout_shared0_pll",
+ "fout_shared1_pll",
+ "dout_cmu_shared0_div2",
+ "dout_cmu_shared1_div2",
+ "fout_shared2_pll",
+ "mout_cp2ap_mif_clk_user",
+ "oscclk", "oscclk" };
+PNAME(mout_cmu_peric0_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_peric0_uart_dbg_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric0_usi00_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric0_usi01_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric0_usi02_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric0_usi03_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_peric1_speedy2_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "oscclk" };
+PNAME(mout_cmu_peric1_spi_cam0_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_spi_cam1_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_uart_bt_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi04_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi05_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi06_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi07_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi08_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi09_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi10_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi11_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi12_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peric1_usi13_p) = { "oscclk", "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_peris_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared2_div2" };
+PNAME(mout_cmu_srdz_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_srdz_imgd_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+PNAME(mout_cmu_vpu_bus_p) = { "dout_cmu_shared0_div4",
+ "dout_cmu_shared1_div4",
+ "dout_cmu_shared2_div2",
+ "dout_cmu_shared4_div2" };
+
+/*
+ * Register name to clock name mangling strategy used in this file
+ *
+ * Replace PLL_CON0_PLL with CLK_MOUT_PLL and mout_pll
+ * Replace CLK_CON_MUX_MUX_CLKCMU with CLK_MOUT_CMU and mout_cmu
+ * Replace CLK_CON_DIV_CLKCMU with CLK_DOUT_CMU and dout_cmu
+ * Replace CLK_CON_DIV_DIV_CLKCMU with CLK_DOUT_CMU and dout_cmu
+ * Replace CLK_CON_GAT_CLKCMU with CLK_GOUT_CMU and gout_cmu
+ * Replace CLK_CON_GAT_GATE_CLKCMU with CLK_GOUT_CMU and gout_cmu
+ *
+ * For gates remove _UID _BLK _IPCLKPORT and _RSTNSYNC
+ */
+
+static const struct samsung_mux_clock top_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_PLL_SHARED0, "mout_pll_shared0", mout_pll_shared0_p,
+ PLL_CON0_PLL_SHARED0, 4, 1),
+ MUX(CLK_MOUT_PLL_SHARED1, "mout_pll_shared1", mout_pll_shared1_p,
+ PLL_CON0_PLL_SHARED1, 4, 1),
+ MUX(CLK_MOUT_PLL_SHARED2, "mout_pll_shared2", mout_pll_shared2_p,
+ PLL_CON0_PLL_SHARED2, 4, 1),
+ MUX(CLK_MOUT_PLL_SHARED3, "mout_pll_shared3", mout_pll_shared3_p,
+ PLL_CON0_PLL_SHARED3, 4, 1),
+ MUX(CLK_MOUT_PLL_SHARED4, "mout_pll_shared4", mout_pll_shared4_p,
+ PLL_CON0_PLL_SHARED4, 4, 1),
+ MUX(CLK_MOUT_CP2AP_MIF_CLK_USER, "mout_cp2ap_mif_clk_user",
+ mout_cp2ap_mif_clk_user_p, PLL_CON0_MUX_CP2AP_MIF_CLK_USER, 4, 1),
+ MUX(CLK_MOUT_CMU_ABOX_CPUABOX, "mout_cmu_abox_cpuabox",
+ mout_cmu_abox_cpuabox_p, CLK_CON_MUX_MUX_CLKCMU_ABOX_CPUABOX,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_APM_BUS, "mout_cmu_apm_bus", mout_cmu_apm_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_APM_BUS, 0, 1),
+ MUX(CLK_MOUT_CMU_BUS1_BUS, "mout_cmu_bus1_bus", mout_cmu_bus1_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_BUS1_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_BUSC_BUS, "mout_cmu_busc_bus", mout_cmu_busc_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_BUSC_BUS, 0, 3),
+ MUX(CLK_MOUT_CMU_BUSC_BUSPHSI2C, "mout_cmu_busc_busphsi2c",
+ mout_cmu_busc_busphsi2c_p, CLK_CON_MUX_MUX_CLKCMU_BUSC_BUSPHSI2C,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_CAM_BUS, "mout_cmu_cam_bus", mout_cmu_cam_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_CAM_TPU0, "mout_cmu_cam_tpu0", mout_cmu_cam_tpu0_p,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_TPU0, 0, 2),
+ MUX(CLK_MOUT_CMU_CAM_TPU1, "mout_cmu_cam_tpu1", mout_cmu_cam_tpu1_p,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_TPU1, 0, 2),
+ MUX(CLK_MOUT_CMU_CAM_VRA, "mout_cmu_cam_vra", mout_cmu_cam_vra_p,
+ CLK_CON_MUX_MUX_CLKCMU_CAM_VRA, 0, 2),
+ MUX(CLK_MOUT_CMU_CIS_CLK0, "mout_cmu_cis_clk0", mout_cmu_cis_clk0_p,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK0, 0, 1),
+ MUX(CLK_MOUT_CMU_CIS_CLK1, "mout_cmu_cis_clk1", mout_cmu_cis_clk1_p,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK1, 0, 1),
+ MUX(CLK_MOUT_CMU_CIS_CLK2, "mout_cmu_cis_clk2", mout_cmu_cis_clk2_p,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK2, 0, 1),
+ MUX(CLK_MOUT_CMU_CIS_CLK3, "mout_cmu_cis_clk3", mout_cmu_cis_clk3_p,
+ CLK_CON_MUX_MUX_CLKCMU_CIS_CLK3, 0, 1),
+ MUX(CLK_MOUT_CMU_CORE_BUS, "mout_core_bus", mout_core_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 3),
+ MUX(CLK_MOUT_CMU_CPUCL0_SWITCH, "mout_cmu_cpucl0_switch",
+ mout_cmu_cpucl0_switch_p, CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_CPUCL1_SWITCH, "mout_cmu_cpucl1_switch",
+ mout_cmu_cpucl1_switch_p, CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_DBG_BUS, "mout_cmu_dbg_bus", mout_cmu_dbg_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_DBG_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_DCAM_BUS, "mout_cmu_dcam_bus", mout_cmu_dcam_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_DCAM_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_DCAM_IMGD, "mout_cmu_dcam_imgd", mout_cmu_dcam_imgd_p,
+ CLK_CON_MUX_MUX_CLKCMU_DCAM_IMGD, 0, 2),
+ MUX(CLK_MOUT_CMU_DPU_BUS, "mout_cmu_dpu_bus", mout_cmu_dpu_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_DPU_BUS, 0, 3),
+ MUX(CLK_MOUT_CMU_DROOPDETECTOR, "mout_cmu_droopdetector",
+ mout_cmu_droopdetector_p, CLK_CON_MUX_MUX_CLKCMU_DROOPDETECTOR,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_DSP_BUS, "mout_cmu_dsp_bus", mout_cmu_dsp_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_DSP_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_FSYS0_BUS, "mout_fsys0_bus", mout_fsys0_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS0_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_FSYS0_DPGTC, "mout_fsys0_dpgtc", mout_fsys0_dpgtc_p,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS0_DPGTC, 0, 2),
+ MUX(CLK_MOUT_CMU_FSYS0_MMC_EMBD, "mout_fsys0_mmc_embd",
+ mout_fsys0_mmc_embd_p, CLK_CON_MUX_MUX_CLKCMU_FSYS0_MMC_EMBD,
+ 0, 3),
+ MUX(CLK_MOUT_CMU_FSYS0_UFS_EMBD, "mout_fsys0_ufs_embd",
+ mout_fsys0_ufs_embd_p, CLK_CON_MUX_MUX_CLKCMU_FSYS0_UFS_EMBD,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_FSYS0_USBDRD30, "mout_fsys0_usbdrd30",
+ mout_fsys0_usbdrd30_p, CLK_CON_MUX_MUX_CLKCMU_FSYS0_USBDRD30,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_FSYS1_BUS, "mout_cmu_fsys1_bus", mout_cmu_fsys1_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_FSYS1_BUS, 0, 1),
+ MUX(CLK_MOUT_CMU_FSYS1_MMC_CARD, "mout_cmu_fsys1_mmc_card",
+ mout_cmu_fsys1_mmc_card_p, CLK_CON_MUX_MUX_CLKCMU_FSYS1_MMC_CARD,
+ 0, 3),
+ MUX(CLK_MOUT_CMU_FSYS1_PCIE, "mout_cmu_fsys1_pcie",
+ mout_cmu_fsys1_pcie_p, CLK_CON_MUX_MUX_CLKCMU_FSYS1_PCIE, 0, 1),
+ MUX(CLK_MOUT_CMU_FSYS1_UFS_CARD, "mout_cmu_fsys1_ufs_card",
+ mout_cmu_fsys1_ufs_card_p, CLK_CON_MUX_MUX_CLKCMU_FSYS1_UFS_CARD,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_G2D_G2D, "mout_cmu_g2d_g2d", mout_cmu_g2d_g2d_p,
+ CLK_CON_MUX_MUX_CLKCMU_G2D_G2D, 0, 2),
+ MUX(CLK_MOUT_CMU_G2D_JPEG, "mout_cmu_g2d_jpeg", mout_cmu_g2d_jpeg_p,
+ CLK_CON_MUX_MUX_CLKCMU_G2D_JPEG, 0, 2),
+ MUX(CLK_MOUT_CMU_HPM, "mout_cmu_hpm", mout_cmu_hpm_p,
+ CLK_CON_MUX_MUX_CLKCMU_HPM, 0, 2),
+ MUX(CLK_MOUT_CMU_IMEM_BUS, "mout_cmu_imem_bus", mout_cmu_imem_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_IMEM_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_ISPHQ_BUS, "mout_cmu_isphq_bus", mout_cmu_isphq_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_ISPHQ_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_ISPLP_BUS, "mout_cmu_isplp_bus", mout_cmu_isplp_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_ISPLP_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_IVA_BUS, "mout_cmu_iva_bus", mout_cmu_iva_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_IVA_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_MFC_BUS, "mout_cmu_mfc_bus", mout_cmu_mfc_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_MFC_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_MIF_SWITCH, "mout_cmu_mif_switch",
+ mout_cmu_mif_switch_p, CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH, 0, 3),
+ MUX(CLK_MOUT_CMU_PERIC0_BUS, "mout_cmu_peric0_bus",
+ mout_cmu_peric0_bus_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_BUS, 0, 1),
+ MUX(CLK_MOUT_CMU_PERIC0_UART_DBG, "mout_cmu_peric0_uart_dbg",
+ mout_cmu_peric0_uart_dbg_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_UART_DBG,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC0_USI00, "mout_cmu_peric0_usi00",
+ mout_cmu_peric0_usi00_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI00,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC0_USI01, "mout_cmu_peric0_usi01",
+ mout_cmu_peric0_usi01_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI01,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC0_USI02, "mout_cmu_peric0_usi02",
+ mout_cmu_peric0_usi02_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI02,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC0_USI03, "mout_cmu_peric0_usi03",
+ mout_cmu_peric0_usi03_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_USI03,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_BUS, "mout_cmu_peric1_bus",
+ mout_cmu_peric1_bus_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_BUS, 0, 1),
+ MUX(CLK_MOUT_CMU_PERIC1_SPEEDY2, "mout_cmu_peric1_speedy2",
+ mout_cmu_peric1_speedy2_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPEEDY2,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_SPI_CAM0, "mout_cmu_peric1_spi_cam0",
+ mout_cmu_peric1_spi_cam0_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPI_CAM0,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_SPI_CAM1, "mout_cmu_peric1_spi_cam1",
+ mout_cmu_peric1_spi_cam1_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_SPI_CAM1,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_UART_BT, "mout_cmu_peric1_uart_bt",
+ mout_cmu_peric1_uart_bt_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_UART_BT,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI04, "mout_cmu_peric1_usi04",
+ mout_cmu_peric1_usi04_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI04,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI05, "mout_cmu_peric1_usi05",
+ mout_cmu_peric1_usi05_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI05,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI06, "mout_cmu_peric1_usi06",
+ mout_cmu_peric1_usi06_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI06,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI07, "mout_cmu_peric1_usi07",
+ mout_cmu_peric1_usi07_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI07,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI08, "mout_cmu_peric1_usi08",
+ mout_cmu_peric1_usi08_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI08,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI09, "mout_cmu_peric1_usi09",
+ mout_cmu_peric1_usi09_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI09,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI10, "mout_cmu_peric1_usi10",
+ mout_cmu_peric1_usi10_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI10,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI11, "mout_cmu_peric1_usi11",
+ mout_cmu_peric1_usi11_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI11,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI12, "mout_cmu_peric1_usi12",
+ mout_cmu_peric1_usi12_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI12,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIC1_USI13, "mout_cmu_peric1_usi13",
+ mout_cmu_peric1_usi13_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_USI13,
+ 0, 2),
+ MUX(CLK_MOUT_CMU_PERIS_BUS, "mout_cmu_peris_bus", mout_cmu_peris_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_PERIS_BUS, 0, 1),
+ MUX(CLK_MOUT_CMU_SRDZ_BUS, "mout_cmu_srdz_bus", mout_cmu_srdz_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_SRDZ_BUS, 0, 2),
+ MUX(CLK_MOUT_CMU_SRDZ_IMGD, "mout_cmu_srdz_imgd", mout_cmu_srdz_imgd_p,
+ CLK_CON_MUX_MUX_CLKCMU_SRDZ_IMGD, 0, 2),
+ MUX(CLK_MOUT_CMU_VPU_BUS, "mout_cmu_vpu_bus", mout_cmu_vpu_bus_p,
+ CLK_CON_MUX_MUX_CLKCMU_VPU_BUS, 0, 2),
+};
+
+static const struct samsung_div_clock top_div_clks[] __initconst = {
+ DIV(CLK_DOUT_CMU_ABOX_CPUABOX, "dout_cmu_cmu_abox_cpuabox",
+ "gout_cmu_abox_cpuabox", CLK_CON_DIV_CLKCMU_ABOX_CPUABOX, 0, 3),
+ DIV(CLK_DOUT_CMU_APM_BUS, "dout_cmu_apm_bus", "gout_cmu_apm_bus",
+ CLK_CON_DIV_CLKCMU_APM_BUS, 0, 3),
+ DIV(CLK_DOUT_CMU_BUS1_BUS, "dout_cmu_bus1_bus", "gout_cmu_bus1_bus",
+ CLK_CON_DIV_CLKCMU_BUS1_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_BUSC_BUS, "dout_cmu_busc_bus",
+ "gout_cmu_clkcmu_busc_bus", CLK_CON_DIV_CLKCMU_BUSC_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_BUSC_BUSPHSI2C, "dout_cmu_busc_busphsi2c",
+ "gout_cmu_busc_busphsi2c", CLK_CON_DIV_CLKCMU_BUSC_BUSPHSI2C,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_CAM_BUS, "dout_cmu_cam_bus", "gout_cmu_cam_bus",
+ CLK_CON_DIV_CLKCMU_CAM_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_CAM_TPU0, "dout_cmu_cam_tpu0", "gout_cmu_cam_tpu0",
+ CLK_CON_DIV_CLKCMU_CAM_TPU0, 0, 4),
+ DIV(CLK_DOUT_CMU_CAM_TPU1, "dout_cmu_cam_tpu1", "gout_cmu_cam_tpu1",
+ CLK_CON_DIV_CLKCMU_CAM_TPU1, 0, 4),
+ DIV(CLK_DOUT_CMU_CAM_VRA, "dout_cmu_cam_vra", "gout_cmu_cam_vra",
+ CLK_CON_DIV_CLKCMU_CAM_VRA, 0, 4),
+ DIV(CLK_DOUT_CMU_CIS_CLK0, "dout_cmu_cis_clk0", "gout_cmu_cis_clk0",
+ CLK_CON_DIV_CLKCMU_CIS_CLK0, 0, 5),
+ DIV(CLK_DOUT_CMU_CIS_CLK1, "dout_cmu_cis_clk1", "gout_cmu_cis_clk1",
+ CLK_CON_DIV_CLKCMU_CIS_CLK1, 0, 5),
+ DIV(CLK_DOUT_CMU_CIS_CLK2, "dout_cmu_cis_clk2", "gout_cmu_cis_clk2",
+ CLK_CON_DIV_CLKCMU_CIS_CLK2, 0, 5),
+ DIV(CLK_DOUT_CMU_CIS_CLK3, "dout_cmu_cis_clk3", "gout_cmu_cis_clk3",
+ CLK_CON_DIV_CLKCMU_CIS_CLK3, 0, 5),
+ DIV(CLK_DOUT_CMU_CORE_BUS, "dout_cmu_core_bus", "gout_cmu_core_bus",
+ CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_CPUCL0_SWITCH, "dout_cmu_cpucl0_switch",
+ "gout_cmu_cpucl0_switch", CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH, 0, 3),
+ DIV(CLK_DOUT_CMU_CPUCL1_SWITCH, "dout_cmu_cpucl1_switch",
+ "gout_cmu_cpucl1_switch", CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH, 0, 3),
+ DIV(CLK_DOUT_CMU_DBG_BUS, "dout_cmu_dbg_bus", "gout_cmu_dbg_bus",
+ CLK_CON_DIV_CLKCMU_DBG_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_DCAM_BUS, "dout_cmu_dcam_bus", "gout_cmu_dcam_bus",
+ CLK_CON_DIV_CLKCMU_DCAM_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_DCAM_IMGD, "dout_cmu_dcam_imgd", "gout_cmu_dcam_imgd",
+ CLK_CON_DIV_CLKCMU_DCAM_IMGD, 0, 4),
+ DIV(CLK_DOUT_CMU_DPU_BUS, "dout_cmu_dpu_bus", "gout_cmu_dpu_bus",
+ CLK_CON_DIV_CLKCMU_DPU_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_DSP_BUS, "dout_cmu_dsp_bus", "gout_cmu_dsp_bus",
+ CLK_CON_DIV_CLKCMU_DSP_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_FSYS0_BUS, "dout_cmu_fsys0_bus", "gout_cmu_fsys0_bus",
+ CLK_CON_DIV_CLKCMU_FSYS0_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_FSYS0_DPGTC, "dout_cmu_fsys0_dpgtc",
+ "gout_cmu_fsys0_dpgtc", CLK_CON_DIV_CLKCMU_FSYS0_DPGTC, 0, 3),
+ DIV(CLK_DOUT_CMU_FSYS0_MMC_EMBD, "dout_cmu_fsys0_mmc_embd",
+ "gout_cmu_fsys0_mmc_embd", CLK_CON_DIV_CLKCMU_FSYS0_MMC_EMBD,
+ 0, 9),
+ DIV(CLK_DOUT_CMU_FSYS0_UFS_EMBD, "dout_cmu_fsys0_ufs_embd",
+ "gout_cmu_fsys0_ufs_embd", CLK_CON_DIV_CLKCMU_FSYS0_UFS_EMBD,
+ 0, 3),
+ DIV(CLK_DOUT_CMU_FSYS0_USBDRD30, "dout_cmu_fsys0_usbdrd30",
+ "gout_cmu_fsys0_usbdrd30", CLK_CON_DIV_CLKCMU_FSYS0_USBDRD30,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_FSYS1_BUS, "dout_cmu_fsys1_bus", "gout_cmu_fsys1_bus",
+ CLK_CON_DIV_CLKCMU_FSYS1_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_FSYS1_MMC_CARD, "dout_cmu_fsys1_mmc_card",
+ "gout_cmu_fsys1_mmc_card", CLK_CON_DIV_CLKCMU_FSYS1_MMC_CARD,
+ 0, 9),
+ DIV(CLK_DOUT_CMU_FSYS1_UFS_CARD, "dout_cmu_fsys1_ufs_card",
+ "gout_cmu_fsys1_ufs_card", CLK_CON_DIV_CLKCMU_FSYS1_UFS_CARD,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_G2D_G2D, "dout_cmu_g2d_g2d", "gout_cmu_g2d_g2d",
+ CLK_CON_DIV_CLKCMU_G2D_G2D, 0, 4),
+ DIV(CLK_DOUT_CMU_G2D_JPEG, "dout_cmu_g2d_jpeg", "gout_cmu_g2d_jpeg",
+ CLK_CON_DIV_CLKCMU_G2D_JPEG, 0, 4),
+ DIV(CLK_DOUT_CMU_G3D_SWITCH, "dout_cmu_g3d_switch",
+ "gout_cmu_g3d_switch", CLK_CON_DIV_CLKCMU_G3D_SWITCH, 0, 3),
+ DIV(CLK_DOUT_CMU_HPM, "dout_cmu_hpm", "gout_cmu_hpm",
+ CLK_CON_DIV_CLKCMU_HPM, 0, 2),
+ DIV(CLK_DOUT_CMU_IMEM_BUS, "dout_cmu_imem_bus", "gout_cmu_imem_bus",
+ CLK_CON_DIV_CLKCMU_IMEM_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_ISPHQ_BUS, "dout_cmu_isphq_bus", "gout_cmu_isphq_bus",
+ CLK_CON_DIV_CLKCMU_ISPHQ_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_ISPLP_BUS, "dout_cmu_isplp_bus", "gout_cmu_isplp_bus",
+ CLK_CON_DIV_CLKCMU_ISPLP_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_IVA_BUS, "dout_cmu_iva_bus", "gout_cmu_iva_bus",
+ CLK_CON_DIV_CLKCMU_IVA_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_MFC_BUS, "dout_cmu_mfc_bus", "gout_cmu_mfc_bus",
+ CLK_CON_DIV_CLKCMU_MFC_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_MODEM_SHARED0, "dout_cmu_modem_shared0",
+ "gout_cmu_modem_shared0", CLK_CON_DIV_CLKCMU_MODEM_SHARED0, 0, 3),
+ DIV(CLK_DOUT_CMU_MODEM_SHARED1, "dout_cmu_modem_shared1",
+ "gout_cmu_modem_shared1", CLK_CON_DIV_CLKCMU_MODEM_SHARED1, 0, 3),
+ DIV(CLK_DOUT_CMU_PERIC0_BUS, "dout_cmu_peric0_bus",
+ "gout_cmu_peric0_bus", CLK_CON_DIV_CLKCMU_PERIC0_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC0_UART_DBG, "dout_cmu_peric0_uart_dbg",
+ "gout_cmu_peric0_uart_dbg", CLK_CON_DIV_CLKCMU_PERIC0_UART_DBG,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC0_USI00, "dout_cmu_peric0_usi00",
+ "gout_cmu_peric0_usi00", CLK_CON_DIV_CLKCMU_PERIC0_USI00, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC0_USI01, "dout_cmu_peric0_usi01",
+ "gout_cmu_peric0_usi01", CLK_CON_DIV_CLKCMU_PERIC0_USI01, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC0_USI02, "dout_cmu_peric0_usi02",
+ "gout_cmu_peric0_usi02", CLK_CON_DIV_CLKCMU_PERIC0_USI02, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC0_USI03, "dout_cmu_peric0_usi03",
+ "gout_cmu_peric0_usi03", CLK_CON_DIV_CLKCMU_PERIC0_USI03, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_BUS, "dout_cmu_peric1_bus",
+ "gout_cmu_peric1_bus", CLK_CON_DIV_CLKCMU_PERIC1_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_SPEEDY2, "dout_cmu_peric1_speedy2",
+ "gout_cmu_peric1_speedy2", CLK_CON_DIV_CLKCMU_PERIC1_SPEEDY2,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_SPI_CAM0, "dout_cmu_peric1_spi_cam0",
+ "gout_cmu_peric1_spi_cam0", CLK_CON_DIV_CLKCMU_PERIC1_SPI_CAM0,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_SPI_CAM1, "dout_cmu_peric1_spi_cam1",
+ "gout_cmu_peric1_spi_cam1", CLK_CON_DIV_CLKCMU_PERIC1_SPI_CAM1,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_UART_BT, "dout_cmu_peric1_uart_bt",
+ "gout_cmu_peric1_uart_bt", CLK_CON_DIV_CLKCMU_PERIC1_UART_BT,
+ 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI04, "dout_cmu_peric1_usi04",
+ "gout_cmu_peric1_usi04", CLK_CON_DIV_CLKCMU_PERIC1_USI04, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI05, "dout_cmu_peric1_usi05",
+ "gout_cmu_peric1_usi05", CLK_CON_DIV_CLKCMU_PERIC1_USI05, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI06, "dout_cmu_peric1_usi06",
+ "gout_cmu_peric1_usi06", CLK_CON_DIV_CLKCMU_PERIC1_USI06, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI07, "dout_cmu_peric1_usi07",
+ "gout_cmu_peric1_usi07", CLK_CON_DIV_CLKCMU_PERIC1_USI07, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI08, "dout_cmu_peric1_usi08",
+ "gout_cmu_peric1_usi08", CLK_CON_DIV_CLKCMU_PERIC1_USI08, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI09, "dout_cmu_peric1_usi09",
+ "gout_cmu_peric1_usi09", CLK_CON_DIV_CLKCMU_PERIC1_USI09, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI10, "dout_cmu_peric1_usi10",
+ "gout_cmu_peric1_usi10", CLK_CON_DIV_CLKCMU_PERIC1_USI10, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI11, "dout_cmu_peric1_usi11",
+ "gout_cmu_peric1_usi11", CLK_CON_DIV_CLKCMU_PERIC1_USI11, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI12, "dout_cmu_peric1_usi12",
+ "gout_cmu_peric1_usi12", CLK_CON_DIV_CLKCMU_PERIC1_USI12, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIC1_USI13, "dout_cmu_peric1_usi13",
+ "gout_cmu_peric1_usi13", CLK_CON_DIV_CLKCMU_PERIC1_USI13, 0, 4),
+ DIV(CLK_DOUT_CMU_PERIS_BUS, "dout_cmu_peris_bus", "gout_cmu_peris_bus",
+ CLK_CON_DIV_CLKCMU_PERIS_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_SRDZ_BUS, "dout_cmu_srdz_bus", "gout_cmu_srdz_bus",
+ CLK_CON_DIV_CLKCMU_SRDZ_BUS, 0, 4),
+ DIV(CLK_DOUT_CMU_SRDZ_IMGD, "dout_cmu_srdz_imgd", "gout_cmu_srdz_imgd",
+ CLK_CON_DIV_CLKCMU_SRDZ_IMGD, 0, 4),
+ DIV(CLK_DOUT_CMU_VPU_BUS, "dout_cmu_vpu_bus", "gout_cmu_vpu_bus",
+ CLK_CON_DIV_CLKCMU_VPU_BUS, 0, 4),
+};
+
+static const struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initconst = {
+ FFACTOR(CLK_DOUT_CMU_SHARED0_DIV2, "dout_cmu_shared0_div2",
+ "mout_pll_shared0", 1, 2, 0),
+ FFACTOR(CLK_DOUT_CMU_SHARED0_DIV4, "dout_cmu_shared0_div4",
+ "mout_pll_shared0", 1, 4, 0),
+ FFACTOR(CLK_DOUT_CMU_SHARED1_DIV2, "dout_cmu_shared1_div2",
+ "mout_pll_shared1", 1, 2, 0),
+ FFACTOR(CLK_DOUT_CMU_SHARED1_DIV4, "dout_cmu_shared1_div4",
+ "mout_pll_shared1", 1, 4, 0),
+ FFACTOR(CLK_DOUT_CMU_SHARED2_DIV2, "dout_cmu_shared2_div2",
+ "mout_pll_shared2", 1, 2, 0),
+ FFACTOR(CLK_DOUT_CMU_SHARED3_DIV2, "dout_cmu_shared3_div2",
+ "mout_pll_shared3", 1, 2, 0),
+ FFACTOR(CLK_DOUT_CMU_SHARED4_DIV2, "dout_cmu_shared4_div2",
+ "mout_pll_shared4", 1, 2, 0),
+ FFACTOR(CLK_DOUT_CMU_FSYS1_PCIE, "dout_cmu_fsys1_pcie",
+ "gout_cmu_fsys1_pcie", 1, 8, 0),
+ FFACTOR(CLK_DOUT_CMU_CP2AP_MIF_CLK_DIV2, "dout_cmu_cp2ap_mif_clk_div2",
+ "mout_cp2ap_mif_clk_user", 1, 2, 0),
+ FFACTOR(CLK_DOUT_CMU_CMU_OTP, "dout_cmu_cmu_otp", "oscclk", 1, 8, 0),
+};
+
+static const struct samsung_gate_clock top_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_CMU_DROOPDETECTOR, "gout_droopdetector",
+ "mout_cmu_droopdetector", CLK_CON_GAT_CLKCMU_DROOPDETECTOR,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_MIF_SWITCH, "gout_cmu_mif_switch",
+ "mout_cmu_mif_switch", CLK_CON_GAT_CLKCMU_MIF_SWITCH, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_ABOX_CPUABOX, "gout_cmu_abox_cpuabox",
+ "mout_cmu_abox_cpuabox", CLK_CON_GAT_GATE_CLKCMU_ABOX_CPUABOX,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_APM_BUS, "gout_cmu_apm_bus", "mout_cmu_apm_bus",
+ CLK_CON_GAT_GATE_CLKCMU_APM_BUS, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_BUS1_BUS, "gout_cmu_bus1_bus", "mout_cmu_bus1_bus",
+ CLK_CON_GAT_GATE_CLKCMU_BUS1_BUS, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_BUSC_BUS, "gout_cmu_busc_bus", "mout_cmu_busc_bus",
+ CLK_CON_GAT_GATE_CLKCMU_BUSC_BUS, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_BUSC_BUSPHSI2C, "gout_cmu_busc_busphsi2c",
+ "mout_cmu_busc_busphsi2c", CLK_CON_GAT_GATE_CLKCMU_BUSC_BUSPHSI2C,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_CAM_BUS, "gout_cmu_cam_bus", "mout_cmu_cam_bus",
+ CLK_CON_GAT_GATE_CLKCMU_CAM_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CAM_TPU0, "gout_cmu_cam_tpu0", "mout_cmu_cam_tpu0",
+ CLK_CON_GAT_GATE_CLKCMU_CAM_TPU0, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CAM_TPU1, "gout_cmu_cam_tpu1", "mout_cmu_cam_tpu1",
+ CLK_CON_GAT_GATE_CLKCMU_CAM_TPU1, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CAM_VRA, "gout_cmu_cam_vra", "mout_cmu_cam_vra",
+ CLK_CON_GAT_GATE_CLKCMU_CAM_VRA, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CIS_CLK0, "gout_cmu_cis_clk0", "mout_cmu_cis_clk0",
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK0, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CIS_CLK1, "gout_cmu_cis_clk1", "mout_cmu_cis_clk1",
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK1, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CIS_CLK2, "gout_cmu_cis_clk2", "mout_cmu_cis_clk2",
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK2, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CIS_CLK3, "gout_cmu_cis_clk3", "mout_cmu_cis_clk3",
+ CLK_CON_GAT_GATE_CLKCMU_CIS_CLK3, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_CORE_BUS, "gout_cmu_core_bus", "mout_core_bus",
+ CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_CPUCL0_SWITCH, "gout_cmu_cpucl0_switch",
+ "mout_cmu_cpucl0_switch", CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_CPUCL1_SWITCH, "gout_cmu_cpucl1_switch",
+ "mout_cmu_cpucl1_switch", CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_DBG_BUS, "gout_cmu_dbg_bus", "mout_cmu_dbg_bus",
+ CLK_CON_GAT_GATE_CLKCMU_DBG_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_DCAM_BUS, "gout_cmu_dcam_bus", "mout_cmu_dcam_bus",
+ CLK_CON_GAT_GATE_CLKCMU_DCAM_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_DCAM_IMGD, "gout_cmu_dcam_imgd",
+ "mout_cmu_dcam_imgd", CLK_CON_GAT_GATE_CLKCMU_DCAM_IMGD,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_DPU_BUS, "gout_cmu_dpu_bus", "mout_cmu_dpu_bus",
+ CLK_CON_GAT_GATE_CLKCMU_DPU_BUS, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_DSP_BUS, "gout_cmu_dsp_bus", "mout_cmu_dsp_bus",
+ CLK_CON_GAT_GATE_CLKCMU_DSP_BUS, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMU_FSYS0_BUS, "gout_cmu_fsys0_bus", "mout_fsys0_bus",
+ CLK_CON_GAT_GATE_CLKCMU_FSYS0_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS0_DPGTC, "gout_cmu_fsys0_dpgtc",
+ "mout_fsys0_dpgtc", CLK_CON_GAT_GATE_CLKCMU_FSYS0_DPGTC,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS0_MMC_EMBD, "gout_cmu_fsys0_mmc_embd",
+ "mout_fsys0_mmc_embd", CLK_CON_GAT_GATE_CLKCMU_FSYS0_MMC_EMBD,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS0_UFS_EMBD, "gout_cmu_fsys0_ufs_embd",
+ "mout_fsys0_ufs_embd", CLK_CON_GAT_GATE_CLKCMU_FSYS0_UFS_EMBD,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS0_USBDRD30, "gout_cmu_fsys0_usbdrd30",
+ "mout_fsys0_usbdrd30", CLK_CON_GAT_GATE_CLKCMU_FSYS0_USBDRD30,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS1_BUS, "gout_cmu_fsys1_bus",
+ "mout_cmu_fsys1_bus", CLK_CON_GAT_GATE_CLKCMU_FSYS1_BUS,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS1_MMC_CARD, "gout_cmu_fsys1_mmc_card",
+ "mout_cmu_fsys1_mmc_card", CLK_CON_GAT_GATE_CLKCMU_FSYS1_MMC_CARD,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS1_PCIE, "gout_cmu_fsys1_pcie",
+ "mout_cmu_fsys1_pcie", CLK_CON_GAT_GATE_CLKCMU_FSYS1_PCIE,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_FSYS1_UFS_CARD, "gout_cmu_fsys1_ufs_card",
+ "mout_cmu_fsys1_ufs_card", CLK_CON_GAT_GATE_CLKCMU_FSYS1_UFS_CARD,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_G2D_G2D, "gout_cmu_g2d_g2d", "mout_cmu_g2d_g2d",
+ CLK_CON_GAT_GATE_CLKCMU_G2D_G2D, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_G2D_JPEG, "gout_cmu_g2d_jpeg", "mout_cmu_g2d_jpeg",
+ CLK_CON_GAT_GATE_CLKCMU_G2D_JPEG, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_G3D_SWITCH, "gout_cmu_g3d_switch",
+ "fout_shared2_pll", CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_HPM, "gout_cmu_hpm", "mout_cmu_hpm",
+ CLK_CON_GAT_GATE_CLKCMU_HPM, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_IMEM_BUS, "gout_cmu_imem_bus", "mout_cmu_imem_bus",
+ CLK_CON_GAT_GATE_CLKCMU_IMEM_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_ISPHQ_BUS, "gout_cmu_isphq_bus",
+ "mout_cmu_isphq_bus", CLK_CON_GAT_GATE_CLKCMU_ISPHQ_BUS,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_ISPLP_BUS, "gout_cmu_isplp_bus",
+ "mout_cmu_isplp_bus", CLK_CON_GAT_GATE_CLKCMU_ISPLP_BUS,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_IVA_BUS, "gout_cmu_iva_bus", "mout_cmu_iva_bus",
+ CLK_CON_GAT_GATE_CLKCMU_IVA_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_MFC_BUS, "gout_cmu_mfc_bus", "mout_cmu_mfc_bus",
+ CLK_CON_GAT_GATE_CLKCMU_MFC_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_MODEM_SHARED0, "gout_cmu_modem_shared0",
+ "dout_cmu_shared0_div2", CLK_CON_GAT_GATE_CLKCMU_MODEM_SHARED0,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_MODEM_SHARED1, "gout_cmu_modem_shared1",
+ "fout_shared2_pll", CLK_CON_GAT_GATE_CLKCMU_MODEM_SHARED1,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC0_BUS, "gout_cmu_peric0_bus",
+ "mout_cmu_peric0_bus", CLK_CON_GAT_GATE_CLKCMU_PERIC0_BUS,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC0_UART_DBG, "gout_cmu_peric0_uart_dbg",
+ "mout_cmu_peric0_uart_dbg",
+ CLK_CON_GAT_GATE_CLKCMU_PERIC0_UART_DBG, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC0_USI00, "gout_cmu_peric0_usi00",
+ "mout_cmu_peric0_usi00", CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI00,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC0_USI01, "gout_cmu_peric0_usi01",
+ "mout_cmu_peric0_usi01", CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI01,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC0_USI02, "gout_cmu_peric0_usi02",
+ "mout_cmu_peric0_usi02", CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI02,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC0_USI03, "gout_cmu_peric0_usi03",
+ "mout_cmu_peric0_usi03", CLK_CON_GAT_GATE_CLKCMU_PERIC0_USI03,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_BUS, "gout_cmu_peric1_bus",
+ "mout_cmu_peric1_bus", CLK_CON_GAT_GATE_CLKCMU_PERIC1_BUS,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_SPEEDY2, "gout_cmu_peric1_speedy2",
+ "mout_cmu_peric1_speedy2", CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPEEDY2,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_SPI_CAM0, "gout_cmu_peric1_spi_cam0",
+ "mout_cmu_peric1_spi_cam0",
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPI_CAM0, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_SPI_CAM1, "gout_cmu_peric1_spi_cam1",
+ "mout_cmu_peric1_spi_cam1",
+ CLK_CON_GAT_GATE_CLKCMU_PERIC1_SPI_CAM1, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_UART_BT, "gout_cmu_peric1_uart_bt",
+ "mout_cmu_peric1_uart_bt", CLK_CON_GAT_GATE_CLKCMU_PERIC1_UART_BT,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI04, "gout_cmu_peric1_usi04",
+ "mout_cmu_peric1_usi04", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI04,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI05, "gout_cmu_peric1_usi05",
+ "mout_cmu_peric1_usi05", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI05,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI06, "gout_cmu_peric1_usi06",
+ "mout_cmu_peric1_usi06", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI06,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI07, "gout_cmu_peric1_usi07",
+ "mout_cmu_peric1_usi07", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI07,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI08, "gout_cmu_peric1_usi08",
+ "mout_cmu_peric1_usi08", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI08,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI09, "gout_cmu_peric1_usi09",
+ "mout_cmu_peric1_usi09", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI09,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI10, "gout_cmu_peric1_usi10",
+ "mout_cmu_peric1_usi10", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI10,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI11, "gout_cmu_peric1_usi11",
+ "mout_cmu_peric1_usi11", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI11,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI12, "gout_cmu_peric1_usi12",
+ "mout_cmu_peric1_usi12", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI12,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIC1_USI13, "gout_cmu_peric1_usi13",
+ "mout_cmu_peric1_usi13", CLK_CON_GAT_GATE_CLKCMU_PERIC1_USI13,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_PERIS_BUS, "gout_cmu_peris_bus",
+ "mout_cmu_peris_bus", CLK_CON_GAT_GATE_CLKCMU_PERIS_BUS,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_SRDZ_BUS, "gout_cmu_srdz_bus", "mout_cmu_srdz_bus",
+ CLK_CON_GAT_GATE_CLKCMU_SRDZ_BUS, 21, 0, 0),
+ GATE(CLK_GOUT_CMU_SRDZ_IMGD, "gout_cmu_srdz_imgd",
+ "mout_cmu_srdz_imgd", CLK_CON_GAT_GATE_CLKCMU_SRDZ_IMGD,
+ 21, 0, 0),
+ GATE(CLK_GOUT_CMU_VPU_BUS, "gout_cmu_vpu_bus", "mout_cmu_vpu_bus",
+ CLK_CON_GAT_GATE_CLKCMU_VPU_BUS, 21, 0, 0),
+};
+
+static const struct samsung_cmu_info top_cmu_info __initconst = {
+ .pll_clks = top_pll_clks,
+ .nr_pll_clks = ARRAY_SIZE(top_pll_clks),
+ .mux_clks = top_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(top_mux_clks),
+ .div_clks = top_div_clks,
+ .nr_div_clks = ARRAY_SIZE(top_div_clks),
+ .fixed_factor_clks = top_fixed_factor_clks,
+ .nr_fixed_factor_clks = ARRAY_SIZE(top_fixed_factor_clks),
+ .gate_clks = top_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(top_gate_clks),
+ .nr_clk_ids = CLKS_NR_TOP,
+ .clk_regs = top_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(top_clk_regs),
+};
+
+static void __init exynos8895_cmu_top_init(struct device_node *np)
+{
+ exynos_arm64_register_cmu(NULL, np, &top_cmu_info);
+}
+
+/* Register CMU_TOP early, as it's a dependency for other early domains */
+CLK_OF_DECLARE(exynos8895_cmu_top, "samsung,exynos8895-cmu-top",
+ exynos8895_cmu_top_init);
+
+/* ---- CMU_PERIS ----------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_PERIS (0x10010000) */
+#define PLL_CON0_MUX_CLKCMU_PERIS_BUS_USER 0x0100
+#define PLL_CON2_MUX_CLKCMU_PERIS_BUS_USER 0x0108
+#define CLK_CON_MUX_MUX_CLK_PERIS_GIC 0x1000
+#define CLK_CON_GAT_CLK_BLK_PERIS_UID_PERIS_CMU_PERIS_IPCLKPORT_PCLK 0x2000
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_AD_AXI_P_PERIS_IPCLKPORT_ACLKM 0x2010
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_AD_AXI_P_PERIS_IPCLKPORT_ACLKS 0x2014
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_AXI2APB_PERISP0_IPCLKPORT_ACLK 0x2018
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_AXI2APB_PERISP1_IPCLKPORT_ACLK 0x201c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_BUSIF_TMU_IPCLKPORT_PCLK 0x2020
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_GIC_IPCLKPORT_CLK 0x2024
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_LHM_AXI_P_PERIS_IPCLKPORT_I_CLK 0x2028
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_MCT_IPCLKPORT_PCLK 0x202c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_OTP_CON_BIRA_IPCLKPORT_PCLK 0x2030
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_OTP_CON_TOP_IPCLKPORT_PCLK 0x2034
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_PMU_PERIS_IPCLKPORT_PCLK 0x2038
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_RSTNSYNC_CLK_PERIS_BUSP_IPCLKPORT_CLK 0x203c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_RSTNSYNC_CLK_PERIS_GIC_IPCLKPORT_CLK 0x2040
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_SYSREG_PERIS_IPCLKPORT_PCLK 0x2044
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC00_IPCLKPORT_PCLK 0x2048
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC01_IPCLKPORT_PCLK 0x204c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC02_IPCLKPORT_PCLK 0x2050
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC03_IPCLKPORT_PCLK 0x2054
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC04_IPCLKPORT_PCLK 0x2058
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC05_IPCLKPORT_PCLK 0x205c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC06_IPCLKPORT_PCLK 0x2060
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC07_IPCLKPORT_PCLK 0x2064
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC08_IPCLKPORT_PCLK 0x2068
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC09_IPCLKPORT_PCLK 0x206c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC10_IPCLKPORT_PCLK 0x2070
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC11_IPCLKPORT_PCLK 0x2074
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC12_IPCLKPORT_PCLK 0x2078
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC13_IPCLKPORT_PCLK 0x207c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC14_IPCLKPORT_PCLK 0x2080
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC15_IPCLKPORT_PCLK 0x2084
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER0_IPCLKPORT_PCLK 0x2088
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER1_IPCLKPORT_PCLK 0x208c
+#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_XIU_P_PERIS_IPCLKPORT_ACLK 0x2090
+
+static const unsigned long peris_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_PERIS_BUS_USER,
+ PLL_CON2_MUX_CLKCMU_PERIS_BUS_USER,
+ CLK_CON_MUX_MUX_CLK_PERIS_GIC,
+ CLK_CON_GAT_CLK_BLK_PERIS_UID_PERIS_CMU_PERIS_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AD_AXI_P_PERIS_IPCLKPORT_ACLKM,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AD_AXI_P_PERIS_IPCLKPORT_ACLKS,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AXI2APB_PERISP0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AXI2APB_PERISP1_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_BUSIF_TMU_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_GIC_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_LHM_AXI_P_PERIS_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_MCT_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_OTP_CON_BIRA_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_OTP_CON_TOP_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_PMU_PERIS_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_RSTNSYNC_CLK_PERIS_BUSP_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_RSTNSYNC_CLK_PERIS_GIC_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_SYSREG_PERIS_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC00_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC01_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC02_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC03_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC04_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC05_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC06_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC07_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC08_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC09_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC10_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC11_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC12_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC13_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC14_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC15_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_XIU_P_PERIS_IPCLKPORT_ACLK,
+};
+
+/* List of parent clocks for Muxes in CMU_PERIS */
+PNAME(mout_peris_bus_user_p) = { "oscclk", "dout_cmu_peris_bus" };
+PNAME(mout_peris_gic_p) = { "oscclk", "mout_peris_bus_user" };
+
+static const struct samsung_mux_clock peris_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_PERIS_BUS_USER, "mout_peris_bus_user",
+ mout_peris_bus_user_p, PLL_CON0_MUX_CLKCMU_PERIS_BUS_USER, 4, 1),
+ MUX(CLK_MOUT_PERIS_GIC, "mout_peris_gic",
+ mout_peris_gic_p, CLK_CON_MUX_MUX_CLK_PERIS_GIC, 0, 5),
+};
+
+static const struct samsung_gate_clock peris_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_PERIS_CMU_PERIS_PCLK, "gout_peris_cmu_peris_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_CLK_BLK_PERIS_UID_PERIS_CMU_PERIS_IPCLKPORT_PCLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIS_AD_AXI_P_PERIS_ACLKM,
+ "gout_peris_ad_axi_p_peris_aclkm", "mout_peris_gic",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AD_AXI_P_PERIS_IPCLKPORT_ACLKM,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIS_AD_AXI_P_PERIS_ACLKS,
+ "gout_peris_ad_axi_p_peris_aclks", "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AD_AXI_P_PERIS_IPCLKPORT_ACLKS,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIS_AXI2APB_PERISP0_ACLK,
+ "gout_peris_axi2apb_perisp0_aclk", "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AXI2APB_PERISP0_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIS_AXI2APB_PERISP1_ACLK,
+ "gout_peris_axi2apb_perisp1_aclk", "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_AXI2APB_PERISP1_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIS_BUSIF_TMU_PCLK, "gout_peris_busif_tmu_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_BUSIF_TMU_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ /* GIC (interrupt controller) clock must be always running */
+ GATE(CLK_GOUT_PERIS_GIC_CLK, "gout_peris_gic_clk",
+ "mout_peris_gic",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_GIC_IPCLKPORT_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIS_LHM_AXI_P_PERIS_I_CLK,
+ "gout_peris_lhm_axi_p_peris_i_clk", "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_LHM_AXI_P_PERIS_IPCLKPORT_I_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIS_MCT_PCLK, "gout_peris_mct_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_MCT_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_OTP_CON_BIRA_PCLK, "gout_peris_otp_con_bira_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_OTP_CON_BIRA_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_OTP_CON_TOP_PCLK, "gout_peris_otp_con_top_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_OTP_CON_TOP_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_PMU_PERIS_PCLK, "gout_peris_pmu_peris_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_PMU_PERIS_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_RSTNSYNC_CLK_PERIS_BUSP_CLK,
+ "gout_peris_rstnsync_clk_peris_busp_clk", "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_RSTNSYNC_CLK_PERIS_BUSP_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_RSTNSYNC_CLK_PERIS_GIC_CLK,
+ "gout_peris_rstnsync_clk_peris_gic_clk", "mout_peris_gic",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_RSTNSYNC_CLK_PERIS_GIC_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_SYSREG_PERIS_PCLK, "gout_peris_sysreg_peris_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_SYSREG_PERIS_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC00_PCLK, "gout_peris_tzpc00_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC00_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC01_PCLK, "gout_peris_tzpc01_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC01_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC02_PCLK, "gout_peris_tzpc02_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC02_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC03_PCLK, "gout_peris_tzpc03_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC03_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC04_PCLK, "gout_peris_tzpc04_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC04_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC05_PCLK, "gout_peris_tzpc05_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC05_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC06_PCLK, "gout_peris_tzpc06_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC06_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC07_PCLK, "gout_peris_tzpc07_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC07_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC08_PCLK, "gout_peris_tzpc08_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC08_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC09_PCLK, "gout_peris_tzpc09_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC09_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC10_PCLK, "gout_peris_tzpc10_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC10_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC11_PCLK, "gout_peris_tzpc11_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC11_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC12_PCLK, "gout_peris_tzpc12_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC12_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC13_PCLK, "gout_peris_tzpc13_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC13_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC14_PCLK, "gout_peris_tzpc14_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC14_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_TZPC15_PCLK, "gout_peris_tzpc15_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_TZPC15_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_WDT_CLUSTER0_PCLK, "gout_peris_wdt_cluster0_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER0_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_WDT_CLUSTER1_PCLK, "gout_peris_wdt_cluster1_pclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER1_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIS_XIU_P_PERIS_ACLK, "gout_peris_xiu_p_peris_aclk",
+ "mout_peris_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIS_UID_XIU_P_PERIS_IPCLKPORT_ACLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+};
+
+static const struct samsung_cmu_info peris_cmu_info __initconst = {
+ .mux_clks = peris_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(peris_mux_clks),
+ .gate_clks = peris_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(peris_gate_clks),
+ .nr_clk_ids = CLKS_NR_PERIS,
+ .clk_regs = peris_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(peris_clk_regs),
+ .clk_name = "bus",
+};
+
+static void __init exynos8895_cmu_peris_init(struct device_node *np)
+{
+ exynos_arm64_register_cmu(NULL, np, &peris_cmu_info);
+}
+
+/* Register CMU_PERIS early, as it's needed for MCT timer */
+CLK_OF_DECLARE(exynos8895_cmu_peris, "samsung,exynos8895-cmu-peris",
+ exynos8895_cmu_peris_init);
+
+/* ---- CMU_FSYS0 ---------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_FSYS0 (0x11000000) */
+#define PLL_CON0_MUX_CLKCMU_FSYS0_BUS_USER 0x0100
+#define PLL_CON2_MUX_CLKCMU_FSYS0_BUS_USER 0x0108
+#define PLL_CON0_MUX_CLKCMU_FSYS0_DPGTC_USER 0x0120
+#define PLL_CON2_MUX_CLKCMU_FSYS0_DPGTC_USER 0x0128
+#define PLL_CON0_MUX_CLKCMU_FSYS0_MMC_EMBD_USER 0x0140
+#define PLL_CON2_MUX_CLKCMU_FSYS0_MMC_EMBD_USER 0x0148
+#define PLL_CON0_MUX_CLKCMU_FSYS0_UFS_EMBD_USER 0x0160
+#define PLL_CON2_MUX_CLKCMU_FSYS0_UFS_EMBD_USER 0x0168
+#define PLL_CON0_MUX_CLKCMU_FSYS0_USBDRD30_USER 0x0180
+#define PLL_CON2_MUX_CLKCMU_FSYS0_USBDRD30_USER 0x0188
+#define CLK_CON_GAT_CLK_BLK_FSYS0_UID_FSYS0_CMU_FSYS0_IPCLKPORT_PCLK 0x2000
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AHBBR_FSYS0_IPCLKPORT_HCLK 0x2010
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2AHB_FSYS0_IPCLKPORT_ACLK 0x2014
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2AHB_USB_FSYS0_IPCLKPORT_ACLK 0x2018
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2APB_FSYS0_IPCLKPORT_ACLK 0x201c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BTM_FSYS0_IPCLKPORT_I_ACLK 0x2020
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BTM_FSYS0_IPCLKPORT_I_PCLK 0x2024
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_DP_LINK_IPCLKPORT_I_GTC_EXT_CLK 0x202c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_DP_LINK_IPCLKPORT_I_PCLK 0x2030
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_ETR_MIU_IPCLKPORT_I_ACLK 0x2034
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_ETR_MIU_IPCLKPORT_I_PCLK 0x2038
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_GPIO_FSYS0_IPCLKPORT_PCLK 0x203c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_D_USBTV_IPCLKPORT_I_CLK 0x2040
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_G_ETR_IPCLKPORT_I_CLK 0x2044
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_P_FSYS0_IPCLKPORT_I_CLK 0x2048
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHS_ACEL_D_FSYS0_IPCLKPORT_I_CLK 0x204c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_MMC_EMBD_IPCLKPORT_I_ACLK 0x2050
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_MMC_EMBD_IPCLKPORT_SDCLKIN 0x2054
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_PMU_FSYS0_IPCLKPORT_PCLK 0x2058
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BCM_FSYS0_IPCLKPORT_ACLK 0x205c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BCM_FSYS0_IPCLKPORT_PCLK 0x2060
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_RSTNSYNC_CLK_FSYS0_BUS_IPCLKPORT_CLK 0x2064
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_SYSREG_FSYS0_IPCLKPORT_PCLK 0x2068
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_ACLK 0x206c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_CLK_UNIPRO 0x2070
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_FMP_CLK 0x2074
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_ACLK 0x2078
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_REF_CLK 0x207c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_SUSPEND_CLK 0x2080
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_AHB_CLK 0x2084
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_CORE_CLK 0x2088
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_XIU_CLK 0x208c
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_US_D_FSYS0_USB_IPCLKPORT_ACLK 0x2090
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_D_FSYS0_IPCLKPORT_ACLK 0x2094
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_D_FSYS0_USB_IPCLKPORT_ACLK 0x2098
+#define CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_P_FSYS0_IPCLKPORT_ACLK 0x209c
+
+static const unsigned long fsys0_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_FSYS0_BUS_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS0_BUS_USER,
+ PLL_CON0_MUX_CLKCMU_FSYS0_DPGTC_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS0_DPGTC_USER,
+ PLL_CON0_MUX_CLKCMU_FSYS0_MMC_EMBD_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS0_MMC_EMBD_USER,
+ PLL_CON0_MUX_CLKCMU_FSYS0_UFS_EMBD_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS0_UFS_EMBD_USER,
+ PLL_CON0_MUX_CLKCMU_FSYS0_USBDRD30_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS0_USBDRD30_USER,
+ CLK_CON_GAT_CLK_BLK_FSYS0_UID_FSYS0_CMU_FSYS0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AHBBR_FSYS0_IPCLKPORT_HCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2AHB_FSYS0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2AHB_USB_FSYS0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2APB_FSYS0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BTM_FSYS0_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BTM_FSYS0_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_DP_LINK_IPCLKPORT_I_GTC_EXT_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_DP_LINK_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_ETR_MIU_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_ETR_MIU_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_GPIO_FSYS0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_D_USBTV_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_G_ETR_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_P_FSYS0_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHS_ACEL_D_FSYS0_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_MMC_EMBD_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_MMC_EMBD_IPCLKPORT_SDCLKIN,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_PMU_FSYS0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BCM_FSYS0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BCM_FSYS0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_RSTNSYNC_CLK_FSYS0_BUS_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_SYSREG_FSYS0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_CLK_UNIPRO,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_FMP_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_REF_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_SUSPEND_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_AHB_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_CORE_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_XIU_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_US_D_FSYS0_USB_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_D_FSYS0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_D_FSYS0_USB_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_P_FSYS0_IPCLKPORT_ACLK,
+};
+
+/* List of parent clocks for Muxes in CMU_FSYS0 */
+PNAME(mout_fsys0_bus_user_p) = { "oscclk", "dout_cmu_fsys0_bus" };
+PNAME(mout_fsys0_dpgtc_user_p) = { "oscclk", "dout_cmu_fsys0_dpgtc" };
+PNAME(mout_fsys0_mmc_embd_user_p) = { "oscclk",
+ "dout_cmu_fsys0_mmc_embd" };
+PNAME(mout_fsys0_ufs_embd_user_p) = { "oscclk",
+ "dout_cmu_fsys0_ufs_embd" };
+PNAME(mout_fsys0_usbdrd30_user_p) = { "oscclk",
+ "dout_cmu_fsys0_usbdrd30" };
+
+static const struct samsung_mux_clock fsys0_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_FSYS0_BUS_USER, "mout_fsys0_bus_user",
+ mout_fsys0_bus_user_p, PLL_CON0_MUX_CLKCMU_FSYS0_BUS_USER, 4, 1),
+ MUX(CLK_MOUT_FSYS0_DPGTC_USER, "mout_fsys0_dpgtc_user",
+ mout_fsys0_dpgtc_user_p, PLL_CON0_MUX_CLKCMU_FSYS0_DPGTC_USER,
+ 4, 1),
+ MUX_F(CLK_MOUT_FSYS0_MMC_EMBD_USER, "mout_fsys0_mmc_embd_user",
+ mout_fsys0_mmc_embd_user_p, PLL_CON0_MUX_CLKCMU_FSYS0_MMC_EMBD_USER,
+ 4, 1, CLK_SET_RATE_PARENT, 0),
+ MUX(CLK_MOUT_FSYS0_UFS_EMBD_USER, "mout_fsys0_ufs_embd_user",
+ mout_fsys0_ufs_embd_user_p, PLL_CON0_MUX_CLKCMU_FSYS0_UFS_EMBD_USER,
+ 4, 1),
+ MUX(CLK_MOUT_FSYS0_USBDRD30_USER, "mout_fsys0_usbdrd30_user",
+ mout_fsys0_usbdrd30_user_p, PLL_CON0_MUX_CLKCMU_FSYS0_USBDRD30_USER,
+ 4, 1),
+};
+
+static const struct samsung_gate_clock fsys0_gate_clks[] __initconst = {
+ /* Disabling this clock makes the system hang. Mark the clock as critical. */
+ GATE(CLK_GOUT_FSYS0_FSYS0_CMU_FSYS0_PCLK,
+ "gout_fsys0_fsys0_cmu_fsys0_pclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_CLK_BLK_FSYS0_UID_FSYS0_CMU_FSYS0_IPCLKPORT_PCLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS0_AHBBR_FSYS0_HCLK, "gout_fsys0_ahbbr_fsys0_hclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AHBBR_FSYS0_IPCLKPORT_HCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_AXI2AHB_FSYS0_ACLK,
+ "gout_fsys0_axi2ahb_fsys0_aclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2AHB_FSYS0_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS0_AXI2AHB_USB_FSYS0_ACLK,
+ "gout_fsys0_axi2ahb_usb_fsys0_aclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2AHB_USB_FSYS0_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS0_AXI2APB_FSYS0_ACLK,
+ "gout_fsys0_axi2apb_fsys0_aclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_AXI2APB_FSYS0_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS0_BTM_FSYS0_I_ACLK, "gout_fsys0_btm_fsys0_i_aclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BTM_FSYS0_IPCLKPORT_I_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_BTM_FSYS0_I_PCLK, "gout_fsys0_btm_fsys0_i_pclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BTM_FSYS0_IPCLKPORT_I_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_DP_LINK_I_GTC_EXT_CLK,
+ "gout_fsys0_dp_link_i_gtc_ext_clk", "mout_fsys0_dpgtc_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_DP_LINK_IPCLKPORT_I_GTC_EXT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_DP_LINK_I_PCLK, "gout_fsys0_dp_link_i_pclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_DP_LINK_IPCLKPORT_I_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_ETR_MIU_I_ACLK, "gout_fsys0_etr_miu_i_aclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_ETR_MIU_IPCLKPORT_I_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_ETR_MIU_I_PCLK, "gout_fsys0_etr_miu_i_pclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_ETR_MIU_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_GPIO_FSYS0_PCLK, "gout_fsys0_gpio_fsys0_pclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_GPIO_FSYS0_IPCLKPORT_PCLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_FSYS0_LHM_AXI_D_USBTV_I_CLK,
+ "gout_fsys0_lhm_axi_d_usbtv_i_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_D_USBTV_IPCLKPORT_I_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_LHM_AXI_G_ETR_I_CLK,
+ "gout_fsys0_lhm_axi_g_etr_i_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_G_ETR_IPCLKPORT_I_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_LHM_AXI_P_FSYS0_I_CLK,
+ "gout_fsys0_lhm_axi_p_fsys0_i_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHM_AXI_P_FSYS0_IPCLKPORT_I_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS0_LHS_ACEL_D_FSYS0_I_CLK,
+ "gout_fsys0_lhs_acel_d_fsys0_i_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_LHS_ACEL_D_FSYS0_IPCLKPORT_I_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS0_MMC_EMBD_I_ACLK, "gout_fsys0_mmc_embd_i_aclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_MMC_EMBD_IPCLKPORT_I_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_MMC_EMBD_SDCLKIN, "gout_fsys0_mmc_embd_sdclkin",
+ "mout_fsys0_mmc_embd_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_MMC_EMBD_IPCLKPORT_SDCLKIN,
+ 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS0_PMU_FSYS0_PCLK, "gout_fsys0_pmu_fsys0_pclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_PMU_FSYS0_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_BCM_FSYS0_ACLK, "gout_fsys0_bcm_fsys0_aclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BCM_FSYS0_IPCLKPORT_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_BCM_FSYS0_PCLK, "gout_fsys0_bcm_fsys0_pclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_BCM_FSYS0_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_RSTNSYNC_CLK_FSYS0_BUS_CLK,
+ "gout_fsys0_rstnsync_clk_fsys0_bus_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_RSTNSYNC_CLK_FSYS0_BUS_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_SYSREG_FSYS0_PCLK, "gout_fsys0_sysreg_fsys0_pclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_SYSREG_FSYS0_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_UFS_EMBD_I_ACLK, "gout_fsys0_ufs_embd_i_aclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_UFS_EMBD_I_CLK_UNIPRO,
+ "gout_fsys0_ufs_embd_i_clk_unipro", "mout_fsys0_ufs_embd_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_CLK_UNIPRO,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS0_UFS_EMBD_I_FMP_CLK,
+ "gout_fsys0_ufs_embd_i_fmp_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_UFS_EMBD_IPCLKPORT_I_FMP_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_USBTV_I_USB30DRD_ACLK,
+ "gout_fsys0_usbtv_i_usb30drd_aclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_USBTV_I_USB30DRD_REF_CLK,
+ "gout_fsys0_usbtv_i_usb30drd_ref_clk", "mout_fsys0_usbdrd30_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_REF_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_USBTV_I_USB30DRD_SUSPEND_CLK,
+ "gout_fsys0_usbtv_i_usb30drd_suspend_clk",
+ "mout_fsys0_usbdrd30_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USB30DRD_SUSPEND_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_USBTV_I_USBTVH_AHB_CLK,
+ "gout_fsys0_usbtv_i_usbtvh_ahb_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_AHB_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_USBTV_I_USBTVH_CORE_CLK,
+ "gout_fsys0_usbtv_i_usbtvh_core_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_CORE_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_USBTV_I_USBTVH_XIU_CLK,
+ "gout_fsys0_usbtv_i_usbtvh_xiu_clk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_USBTV_IPCLKPORT_I_USBTVH_XIU_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_US_D_FSYS0_USB_ACLK,
+ "gout_fsys0_us_d_fsys0_usb_aclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_US_D_FSYS0_USB_IPCLKPORT_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS0_XIU_D_FSYS0_ACLK, "gout_fsys0_xiu_d_fsys0_aclk",
+ "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_D_FSYS0_IPCLKPORT_ACLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_FSYS0_XIU_D_FSYS0_USB_ACLK,
+ "gout_fsys0_xiu_d_fsys0_usb_aclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_D_FSYS0_USB_IPCLKPORT_ACLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_FSYS0_XIU_P_FSYS0_ACLK,
+ "gout_fsys0_xiu_p_fsys0_aclk", "mout_fsys0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS0_UID_XIU_P_FSYS0_IPCLKPORT_ACLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+};
+
+static const struct samsung_cmu_info fsys0_cmu_info __initconst = {
+ .mux_clks = fsys0_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(fsys0_mux_clks),
+ .gate_clks = fsys0_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks),
+ .nr_clk_ids = CLKS_NR_FSYS0,
+ .clk_regs = fsys0_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs),
+ .clk_name = "bus",
+};
+
+/* ---- CMU_FSYS1 ---------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_FSYS1 (0x11400000) */
+#define PLL_CON0_MUX_CLKCMU_FSYS1_BUS_USER 0x0100
+#define PLL_CON2_MUX_CLKCMU_FSYS1_BUS_USER 0x0108
+#define PLL_CON0_MUX_CLKCMU_FSYS1_MMC_CARD_USER 0x0120
+#define PLL_CON2_MUX_CLKCMU_FSYS1_MMC_CARD_USER 0x0128
+#define PLL_CON0_MUX_CLKCMU_FSYS1_PCIE_USER 0x0140
+#define PLL_CON2_MUX_CLKCMU_FSYS1_PCIE_USER 0x0148
+#define PLL_CON0_MUX_CLKCMU_FSYS1_UFS_CARD_USER 0x0160
+#define PLL_CON2_MUX_CLKCMU_FSYS1_UFS_CARD_USER 0x0168
+#define CLK_CON_GAT_CLK_BLK_FSYS1_UID_PCIE_IPCLKPORT_PHY_REF_CLK_IN 0x2000
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_ADM_AHB_SSS_IPCLKPORT_HCLKM 0x2004
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AHBBR_FSYS1_IPCLKPORT_HCLK 0x2008
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2AHB_FSYS1_IPCLKPORT_ACLK 0x200c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2APB_FSYS1P0_IPCLKPORT_ACLK 0x2010
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2APB_FSYS1P1_IPCLKPORT_ACLK 0x2014
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BTM_FSYS1_IPCLKPORT_I_ACLK 0x2018
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BTM_FSYS1_IPCLKPORT_I_PCLK 0x201c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_FSYS1_CMU_FSYS1_IPCLKPORT_PCLK 0x2024
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_GPIO_FSYS1_IPCLKPORT_PCLK 0x2028
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_LHM_AXI_P_FSYS1_IPCLKPORT_I_CLK 0x202c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_LHS_ACEL_D_FSYS1_IPCLKPORT_I_CLK 0x2030
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_MMC_CARD_IPCLKPORT_I_ACLK 0x2034
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_MMC_CARD_IPCLKPORT_SDCLKIN 0x2038
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_DBI_ACLK_0 0x203c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_DBI_ACLK_1 0x2040
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_IEEE1500_WRAPPER_FOR_PCIE_PHY_LC_X2_INST_0_I_SCL_APB_PCLK 0x2044
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_MSTR_ACLK_0 0x2048
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_MSTR_ACLK_1 0x204c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK 0x2050
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PCIE_SUB_CTRL_INST_1_I_DRIVER_APB_CLK 0x2054
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PIPE2_DIGITAL_X2_WRAP_INST_0_I_APB_PCLK_SCL 0x2058
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_SLV_ACLK_0 0x205c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_SLV_ACLK_1 0x2060
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PMU_FSYS1_IPCLKPORT_PCLK 0x2068
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BCM_FSYS1_IPCLKPORT_ACLK 0x206c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BCM_FSYS1_IPCLKPORT_PCLK 0x2070
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RSTNSYNC_CLK_FSYS1_BUS_IPCLKPORT_CLK 0x2074
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RTIC_IPCLKPORT_I_ACLK 0x207c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RTIC_IPCLKPORT_I_PCLK 0x2080
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SSS_IPCLKPORT_I_ACLK 0x2084
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SSS_IPCLKPORT_I_PCLK 0x2088
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SYSREG_FSYS1_IPCLKPORT_PCLK 0x2090
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_TOE_WIFI0_IPCLKPORT_I_CLK 0x2094
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_TOE_WIFI1_IPCLKPORT_I_CLK 0x2098
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_ACLK 0x209c
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_CLK_UNIPRO 0x20a0
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_FMP_CLK 0x20a4
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_XIU_D_FSYS1_IPCLKPORT_ACLK 0x20a8
+#define CLK_CON_GAT_GOUT_BLK_FSYS1_UID_XIU_P_FSYS1_IPCLKPORT_ACLK 0x20ac
+
+static const unsigned long fsys1_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_FSYS1_BUS_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS1_BUS_USER,
+ PLL_CON0_MUX_CLKCMU_FSYS1_MMC_CARD_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS1_MMC_CARD_USER,
+ PLL_CON0_MUX_CLKCMU_FSYS1_PCIE_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS1_PCIE_USER,
+ PLL_CON0_MUX_CLKCMU_FSYS1_UFS_CARD_USER,
+ PLL_CON2_MUX_CLKCMU_FSYS1_UFS_CARD_USER,
+ CLK_CON_GAT_CLK_BLK_FSYS1_UID_PCIE_IPCLKPORT_PHY_REF_CLK_IN,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_ADM_AHB_SSS_IPCLKPORT_HCLKM,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AHBBR_FSYS1_IPCLKPORT_HCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2AHB_FSYS1_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2APB_FSYS1P0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2APB_FSYS1P1_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BTM_FSYS1_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BTM_FSYS1_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_FSYS1_CMU_FSYS1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_GPIO_FSYS1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_LHM_AXI_P_FSYS1_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_LHS_ACEL_D_FSYS1_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_MMC_CARD_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_MMC_CARD_IPCLKPORT_SDCLKIN,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_DBI_ACLK_0,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_DBI_ACLK_1,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_IEEE1500_WRAPPER_FOR_PCIE_PHY_LC_X2_INST_0_I_SCL_APB_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_MSTR_ACLK_0,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_MSTR_ACLK_1,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PCIE_SUB_CTRL_INST_1_I_DRIVER_APB_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PIPE2_DIGITAL_X2_WRAP_INST_0_I_APB_PCLK_SCL,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_SLV_ACLK_0,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_SLV_ACLK_1,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PMU_FSYS1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BCM_FSYS1_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BCM_FSYS1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RSTNSYNC_CLK_FSYS1_BUS_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RTIC_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RTIC_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SSS_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SSS_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SYSREG_FSYS1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_TOE_WIFI0_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_TOE_WIFI1_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_CLK_UNIPRO,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_FMP_CLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_XIU_D_FSYS1_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_XIU_P_FSYS1_IPCLKPORT_ACLK,
+};
+
+/* List of parent clocks for Muxes in CMU_FSYS1 */
+PNAME(mout_fsys1_bus_user_p) = { "oscclk", "dout_cmu_fsys1_bus" };
+PNAME(mout_fsys1_mmc_card_user_p) = { "oscclk",
+ "dout_cmu_fsys1_mmc_card" };
+PNAME(mout_fsys1_pcie_user_p) = { "oscclk", "dout_cmu_fsys1_pcie" };
+PNAME(mout_fsys1_ufs_card_user_p) = { "oscclk",
+ "dout_cmu_fsys1_ufs_card" };
+
+static const struct samsung_mux_clock fsys1_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_FSYS1_BUS_USER, "mout_fsys1_bus_user",
+ mout_fsys1_bus_user_p, PLL_CON0_MUX_CLKCMU_FSYS1_BUS_USER, 4, 1),
+ MUX_F(CLK_MOUT_FSYS1_MMC_CARD_USER, "mout_fsys1_mmc_card_user",
+ mout_fsys1_mmc_card_user_p,
+ PLL_CON0_MUX_CLKCMU_FSYS1_MMC_CARD_USER,
+ 4, 1, CLK_SET_RATE_PARENT, 0),
+ MUX(CLK_MOUT_FSYS1_PCIE_USER, "mout_fsys1_pcie_user",
+ mout_fsys1_pcie_user_p, PLL_CON0_MUX_CLKCMU_FSYS1_PCIE_USER, 4, 1),
+ MUX(CLK_MOUT_FSYS1_UFS_CARD_USER, "mout_fsys1_ufs_card_user",
+ mout_fsys1_ufs_card_user_p,
+ PLL_CON0_MUX_CLKCMU_FSYS1_UFS_CARD_USER, 4, 1),
+};
+
+static const struct samsung_gate_clock fsys1_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_FSYS1_PCIE_PHY_REF_CLK_IN,
+ "gout_clk_blk_fsys1_pcie_phy_ref_clk_in", "mout_fsys1_pcie_user",
+ CLK_CON_GAT_CLK_BLK_FSYS1_UID_PCIE_IPCLKPORT_PHY_REF_CLK_IN,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_ADM_AHB_SSS_HCLKM, "gout_fsys1_adm_ahb_sss_hclkm",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_ADM_AHB_SSS_IPCLKPORT_HCLKM,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_AHBBR_FSYS1_HCLK, "gout_fsys1_ahbbr_fsys1_hclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AHBBR_FSYS1_IPCLKPORT_HCLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS1_AXI2AHB_FSYS1_ACLK,
+ "gout_fsys1_axi2ahb_fsys1_aclk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2AHB_FSYS1_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS1_AXI2APB_FSYS1P0_ACLK,
+ "gout_fsys1_axi2apb_fsys1p0_aclk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2APB_FSYS1P0_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS1_AXI2APB_FSYS1P1_ACLK,
+ "gout_fsys1_axi2apb_fsys1p1_aclk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_AXI2APB_FSYS1P1_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS1_BTM_FSYS1_I_ACLK, "gout_fsys1_btm_fsys1_i_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BTM_FSYS1_IPCLKPORT_I_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_BTM_FSYS1_I_PCLK, "gout_fsys1_btm_fsys1_i_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BTM_FSYS1_IPCLKPORT_I_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_FSYS1_CMU_FSYS1_PCLK,
+ "gout_fsys1_fsys1_cmu_fsys1_pclk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_FSYS1_CMU_FSYS1_IPCLKPORT_PCLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS1_GPIO_FSYS1_PCLK, "gout_fsys1_gpio_fsys1_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_GPIO_FSYS1_IPCLKPORT_PCLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_FSYS1_LHM_AXI_P_FSYS1_I_CLK,
+ "gout_fsys1_lhm_axi_p_fsys1_i_clk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_LHM_AXI_P_FSYS1_IPCLKPORT_I_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS1_LHS_ACEL_D_FSYS1_I_CLK,
+ "gout_fsys1_lhs_acel_d_fsys1_i_clk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_LHS_ACEL_D_FSYS1_IPCLKPORT_I_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_FSYS1_MMC_CARD_I_ACLK, "gout_fsys1_mmc_card_i_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_MMC_CARD_IPCLKPORT_I_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_MMC_CARD_SDCLKIN, "gout_fsys1_mmc_card_sdclkin",
+ "mout_fsys1_mmc_card_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_MMC_CARD_IPCLKPORT_SDCLKIN,
+ 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_DBI_ACLK_0, "gout_fsys1_pcie_dbi_aclk_0",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_DBI_ACLK_0,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_DBI_ACLK_1, "gout_fsys1_pcie_dbi_aclk_1",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_DBI_ACLK_1,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_IEEE1500_WRAPPER_FOR_PCIE_PHY_LC_X2_INST_0_I_SCL_APB_PCLK,
+ "gout_fsys1_pcie_ieee1500_wrapper_for_pcie_phy_lc_x2_inst_0_i_scl_apb_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_IEEE1500_WRAPPER_FOR_PCIE_PHY_LC_X2_INST_0_I_SCL_APB_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_MSTR_ACLK_0,
+ "gout_fsys1_pcie_mstr_aclk_0", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_MSTR_ACLK_0,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_MSTR_ACLK_1,
+ "gout_fsys1_pcie_mstr_aclk_1", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_MSTR_ACLK_1,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK,
+ "gout_fsys1_pcie_pcie_sub_ctrl_inst_0_i_driver_apb_clk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_PCIE_SUB_CTRL_INST_1_I_DRIVER_APB_CLK,
+ "gout_fsys1_pcie_pcie_sub_ctrl_inst_1_i_driver_apb_clk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PCIE_SUB_CTRL_INST_1_I_DRIVER_APB_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_PIPE2_DIGITAL_X2_WRAP_INST_0_I_APB_PCLK_SCL,
+ "gout_fsys1_pcie_pipe2_digital_x2_wrap_inst_0_i_apb_pclk_scl",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_PIPE2_DIGITAL_X2_WRAP_INST_0_I_APB_PCLK_SCL,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_SLV_ACLK_0, "gout_fsys1_pcie_slv_aclk_0",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_SLV_ACLK_0,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PCIE_SLV_ACLK_1, "gout_fsys1_pcie_slv_aclk_1",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PCIE_IPCLKPORT_SLV_ACLK_1,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_PMU_FSYS1_PCLK, "gout_fsys1_pmu_fsys1_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_PMU_FSYS1_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_BCM_FSYS1_ACLK, "gout_fsys1_bcm_fsys1_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BCM_FSYS1_IPCLKPORT_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_BCM_FSYS1_PCLK, "gout_fsys1_bcm_fsys1_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_BCM_FSYS1_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_RSTNSYNC_CLK_FSYS1_BUS_CLK,
+ "gout_fsys1_rstnsync_clk_fsys1_bus_clk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RSTNSYNC_CLK_FSYS1_BUS_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_RTIC_I_ACLK, "gout_fsys1_rtic_i_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RTIC_IPCLKPORT_I_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_RTIC_I_PCLK, "gout_fsys1_rtic_i_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_RTIC_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_SSS_I_ACLK, "gout_fsys1_sss_i_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SSS_IPCLKPORT_I_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_SSS_I_PCLK, "gout_fsys1_sss_i_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SSS_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_SYSREG_FSYS1_PCLK, "gout_fsys1_sysreg_fsys1_pclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_SYSREG_FSYS1_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_TOE_WIFI0_I_CLK, "gout_fsys1_toe_wifi0_i_clk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_TOE_WIFI0_IPCLKPORT_I_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_TOE_WIFI1_I_CLK, "gout_fsys1_toe_wifi1_i_clk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_TOE_WIFI1_IPCLKPORT_I_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_UFS_CARD_I_ACLK, "gout_fsys1_ufs_card_i_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_ACLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_UFS_CARD_I_CLK_UNIPRO,
+ "gout_fsys1_ufs_card_i_clk_unipro", "mout_fsys1_ufs_card_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_CLK_UNIPRO,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_FSYS1_UFS_CARD_I_FMP_CLK,
+ "gout_fsys1_ufs_card_i_fmp_clk", "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_UFS_CARD_IPCLKPORT_I_FMP_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_FSYS1_XIU_D_FSYS1_ACLK, "gout_fsys1_xiu_d_fsys1_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_XIU_D_FSYS1_IPCLKPORT_ACLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_FSYS1_XIU_P_FSYS1_ACLK, "gout_fsys1_xiu_p_fsys1_aclk",
+ "mout_fsys1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_FSYS1_UID_XIU_P_FSYS1_IPCLKPORT_ACLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+};
+
+static const struct samsung_cmu_info fsys1_cmu_info __initconst = {
+ .mux_clks = fsys1_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks),
+ .gate_clks = fsys1_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks),
+ .nr_clk_ids = CLKS_NR_FSYS1,
+ .clk_regs = fsys1_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs),
+ .clk_name = "bus",
+};
+
+/* ---- CMU_PERIC0 ---------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_PERIC0 (0x10400000) */
+#define PLL_CON0_MUX_CLKCMU_PERIC0_BUS_USER 0x0100
+#define PLL_CON2_MUX_CLKCMU_PERIC0_BUS_USER 0x0108
+#define PLL_CON0_MUX_CLKCMU_PERIC0_UART_DBG_USER 0x0120
+#define PLL_CON2_MUX_CLKCMU_PERIC0_UART_DBG_USER 0x0128
+#define PLL_CON0_MUX_CLKCMU_PERIC0_USI00_USER 0x0140
+#define PLL_CON2_MUX_CLKCMU_PERIC0_USI00_USER 0x0148
+#define PLL_CON0_MUX_CLKCMU_PERIC0_USI01_USER 0x0160
+#define PLL_CON2_MUX_CLKCMU_PERIC0_USI01_USER 0x0168
+#define PLL_CON0_MUX_CLKCMU_PERIC0_USI02_USER 0x0180
+#define PLL_CON2_MUX_CLKCMU_PERIC0_USI02_USER 0x0188
+#define PLL_CON0_MUX_CLKCMU_PERIC0_USI03_USER 0x01a0
+#define PLL_CON2_MUX_CLKCMU_PERIC0_USI03_USER 0x01a8
+#define CLK_CON_GAT_CLK_BLK_PERIC0_UID_PERIC0_CMU_PERIC0_IPCLKPORT_PCLK 0x2000
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_AXI2APB_PERIC0_IPCLKPORT_ACLK 0x2014
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_GPIO_PERIC0_IPCLKPORT_PCLK 0x2018
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_LHM_AXI_P_PERIC0_IPCLKPORT_I_CLK 0x201c
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PMU_PERIC0_IPCLKPORT_PCLK 0x2020
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PWM_IPCLKPORT_I_PCLK_S0 0x2028
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_RSTNSYNC_CLK_PERIC0_BUSP_IPCLKPORT_CLK 0x202c
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_SPEEDY2_TSP_IPCLKPORT_CLK 0x2030
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_SYSREG_PERIC0_IPCLKPORT_PCLK 0x2034
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_UART_DBG_IPCLKPORT_EXT_UCLK 0x2038
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_UART_DBG_IPCLKPORT_PCLK 0x203c
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI00_IPCLKPORT_I_PCLK 0x2040
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI00_IPCLKPORT_I_SCLK_USI 0x2044
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI01_IPCLKPORT_I_PCLK 0x2048
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI01_IPCLKPORT_I_SCLK_USI 0x204c
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI02_IPCLKPORT_I_PCLK 0x2050
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI02_IPCLKPORT_I_SCLK_USI 0x2054
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI03_IPCLKPORT_I_PCLK 0x2058
+#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI03_IPCLKPORT_I_SCLK_USI 0x205c
+
+static const unsigned long peric0_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_PERIC0_BUS_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC0_BUS_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC0_UART_DBG_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC0_UART_DBG_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI00_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC0_USI00_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI01_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC0_USI01_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI02_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC0_USI02_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI03_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC0_USI03_USER,
+ CLK_CON_GAT_CLK_BLK_PERIC0_UID_PERIC0_CMU_PERIC0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_AXI2APB_PERIC0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_GPIO_PERIC0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_LHM_AXI_P_PERIC0_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PMU_PERIC0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PWM_IPCLKPORT_I_PCLK_S0,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_RSTNSYNC_CLK_PERIC0_BUSP_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_SPEEDY2_TSP_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_SYSREG_PERIC0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_UART_DBG_IPCLKPORT_EXT_UCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_UART_DBG_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI00_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI00_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI01_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI01_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI02_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI02_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI03_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI03_IPCLKPORT_I_SCLK_USI,
+};
+
+/* List of parent clocks for Muxes in CMU_PERIC0 */
+PNAME(mout_peric0_bus_user_p) = { "oscclk", "dout_cmu_peric0_bus" };
+PNAME(mout_peric0_uart_dbg_user_p) = { "oscclk",
+ "dout_cmu_peric0_uart_dbg" };
+PNAME(mout_peric0_usi00_user_p) = { "oscclk",
+ "dout_cmu_peric0_usi00" };
+PNAME(mout_peric0_usi01_user_p) = { "oscclk",
+ "dout_cmu_peric0_usi01" };
+PNAME(mout_peric0_usi02_user_p) = { "oscclk",
+ "dout_cmu_peric0_usi02" };
+PNAME(mout_peric0_usi03_user_p) = { "oscclk",
+ "dout_cmu_peric0_usi03" };
+
+static const struct samsung_mux_clock peric0_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_PERIC0_BUS_USER, "mout_peric0_bus_user",
+ mout_peric0_bus_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_BUS_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC0_UART_DBG_USER, "mout_peric0_uart_dbg_user",
+ mout_peric0_uart_dbg_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_UART_DBG_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC0_USI00_USER, "mout_peric0_usi00_user",
+ mout_peric0_usi00_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_USI00_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC0_USI01_USER, "mout_peric0_usi01_user",
+ mout_peric0_usi01_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_USI01_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC0_USI02_USER, "mout_peric0_usi02_user",
+ mout_peric0_usi02_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_USI02_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC0_USI03_USER, "mout_peric0_usi03_user",
+ mout_peric0_usi03_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_USI03_USER,
+ 4, 1),
+};
+
+static const struct samsung_gate_clock peric0_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_PERIC0_PERIC0_CMU_PERIC0_PCLK,
+ "gout_cperic0_peric0_cmu_peric0_pclk", "mout_peric0_bus_user",
+ CLK_CON_GAT_CLK_BLK_PERIC0_UID_PERIC0_CMU_PERIC0_IPCLKPORT_PCLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC0_AXI2APB_PERIC0_ACLK,
+ "gout_peric0_axi2apb_peric0_aclk", "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_AXI2APB_PERIC0_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC0_GPIO_PERIC0_PCLK, "gout_peric0_gpio_peric0_pclk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_GPIO_PERIC0_IPCLKPORT_PCLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_PERIC0_LHM_AXI_P_PERIC0_I_CLK,
+ "gout_peric0_lhm_axi_p_peric0_i_clk", "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_LHM_AXI_P_PERIC0_IPCLKPORT_I_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC0_PMU_PERIC0_PCLK, "gout_peric0_pmu_peric0_pclk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PMU_PERIC0_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_PWM_I_PCLK_S0, "gout_peric0_pwm_i_pclk_s0",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PWM_IPCLKPORT_I_PCLK_S0,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_RSTNSYNC_CLK_PERIC0_BUSP_CLK,
+ "gout_peric0_rstnsync_clk_peric0_busp_clk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_RSTNSYNC_CLK_PERIC0_BUSP_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_SPEEDY2_TSP_CLK, "gout_peric0_speedy2_tsp_clk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_SPEEDY2_TSP_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_SYSREG_PERIC0_PCLK,
+ "gout_peric0_sysreg_peric0_pclk", "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_SYSREG_PERIC0_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_UART_DBG_EXT_UCLK,
+ "gout_peric0_uart_dbg_ext_uclk", "mout_peric0_uart_dbg_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_UART_DBG_IPCLKPORT_EXT_UCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_UART_DBG_PCLK, "gout_peric0_uart_dbg_pclk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_UART_DBG_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI00_I_PCLK, "gout_peric0_usi00_i_pclk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI00_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI00_I_SCLK_USI, "gout_peric0_usi00_i_sclk_usi",
+ "mout_peric0_usi00_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI00_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI01_I_PCLK, "gout_peric0_usi01_i_pclk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI01_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI01_I_SCLK_USI, "gout_peric0_usi01_i_sclk_usi",
+ "mout_peric0_usi01_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI01_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI02_I_PCLK, "gout_peric0_usi02_i_pclk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI02_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI02_I_SCLK_USI, "gout_peric0_usi02_i_sclk_usi",
+ "mout_peric0_usi02_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI02_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI03_I_PCLK, "gout_peric0_usi03_i_pclk",
+ "mout_peric0_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI03_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC0_USI03_I_SCLK_USI, "gout_peric0_usi03_i_sclk_usi",
+ "mout_peric0_usi03_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC0_UID_USI03_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+};
+
+static const struct samsung_cmu_info peric0_cmu_info __initconst = {
+ .mux_clks = peric0_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(peric0_mux_clks),
+ .gate_clks = peric0_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(peric0_gate_clks),
+ .nr_clk_ids = CLKS_NR_PERIC0,
+ .clk_regs = peric0_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(peric0_clk_regs),
+ .clk_name = "bus",
+};
+
+/* ---- CMU_PERIC1 ---------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_PERIC1 (0x10800000) */
+#define PLL_CON0_MUX_CLKCMU_PERIC1_BUS_USER 0x0100
+#define PLL_CON2_MUX_CLKCMU_PERIC1_BUS_USER 0x0108
+#define PLL_CON0_MUX_CLKCMU_PERIC1_SPEEDY2_USER 0x0120
+#define PLL_CON2_MUX_CLKCMU_PERIC1_SPEEDY2_USER 0x0128
+#define PLL_CON0_MUX_CLKCMU_PERIC1_SPI_CAM0_USER 0x0140
+#define PLL_CON2_MUX_CLKCMU_PERIC1_SPI_CAM0_USER 0x0148
+#define PLL_CON0_MUX_CLKCMU_PERIC1_SPI_CAM1_USER 0x0160
+#define PLL_CON2_MUX_CLKCMU_PERIC1_SPI_CAM1_USER 0x0168
+#define PLL_CON0_MUX_CLKCMU_PERIC1_UART_BT_USER 0x0180
+#define PLL_CON2_MUX_CLKCMU_PERIC1_UART_BT_USER 0x0188
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI04_USER 0x01a0
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI04_USER 0x01a8
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI05_USER 0x01c0
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI05_USER 0x01c8
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI06_USER 0x01e0
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI06_USER 0x01e8
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI07_USER 0x0200
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI07_USER 0x0208
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI08_USER 0x0220
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI08_USER 0x0228
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI09_USER 0x0240
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI09_USER 0x0248
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USER 0x0260
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI10_USER 0x0268
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USER 0x0280
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI11_USER 0x0288
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USER 0x02a0
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI12_USER 0x02a8
+#define PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USER 0x02c0
+#define PLL_CON2_MUX_CLKCMU_PERIC1_USI13_USER 0x02c8
+#define CLK_CON_GAT_CLK_BLK_PERIC1_UID_PERIC1_CMU_PERIC1_IPCLKPORT_PCLK 0x2000
+#define CLK_CON_GAT_CLK_BLK_PERIC1_UID_RSTNSYNC_CLK_PERIC1_SPEEDY2_IPCLKPORT_CLK 0x200c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P0_IPCLKPORT_ACLK 0x201c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P1_IPCLKPORT_ACLK 0x2020
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P2_IPCLKPORT_ACLK 0x2024
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_GPIO_PERIC1_IPCLKPORT_PCLK 0x2028
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM0_IPCLKPORT_IPCLK 0x202c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM1_IPCLKPORT_IPCLK 0x2030
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM2_IPCLKPORT_IPCLK 0x2034
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM3_IPCLKPORT_IPCLK 0x2038
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_LHM_AXI_P_PERIC1_IPCLKPORT_I_CLK 0x203c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PMU_PERIC1_IPCLKPORT_PCLK 0x2040
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_RSTNSYNC_CLK_PERIC1_BUSP_IPCLKPORT_CLK 0x2044
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI1_IPCLKPORT_CLK 0x2048
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI1_IPCLKPORT_SCLK 0x204c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI2_IPCLKPORT_CLK 0x2050
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI2_IPCLKPORT_SCLK 0x2054
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI_IPCLKPORT_CLK 0x2058
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI_IPCLKPORT_SCLK 0x205c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_TSP1_IPCLKPORT_CLK 0x2060
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_TSP2_IPCLKPORT_CLK 0x2064
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM0_IPCLKPORT_PCLK 0x2068
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM0_IPCLKPORT_SPI_EXT_CLK 0x206c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM1_IPCLKPORT_PCLK 0x2070
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM1_IPCLKPORT_SPI_EXT_CLK 0x2074
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SYSREG_PERIC1_IPCLKPORT_PCLK 0x2078
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_UART_BT_IPCLKPORT_EXT_UCLK 0x207c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_UART_BT_IPCLKPORT_PCLK 0x2080
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI04_IPCLKPORT_I_PCLK 0x2084
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI04_IPCLKPORT_I_SCLK_USI 0x2088
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI05_IPCLKPORT_I_PCLK 0x208c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI05_IPCLKPORT_I_SCLK_USI 0x2090
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI06_IPCLKPORT_I_PCLK 0x2094
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI06_IPCLKPORT_I_SCLK_USI 0x2098
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI07_IPCLKPORT_I_PCLK 0x209c
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI07_IPCLKPORT_I_SCLK_USI 0x20a0
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI08_IPCLKPORT_I_PCLK 0x20a4
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI08_IPCLKPORT_I_SCLK_USI 0x20a8
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI09_IPCLKPORT_I_PCLK 0x20ac
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI09_IPCLKPORT_I_SCLK_USI 0x20b0
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI10_IPCLKPORT_I_PCLK 0x20b4
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI10_IPCLKPORT_I_SCLK_USI 0x20b8
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI11_IPCLKPORT_I_PCLK 0x20bc
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI11_IPCLKPORT_I_SCLK_USI 0x20c0
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI12_IPCLKPORT_I_PCLK 0x20c4
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI12_IPCLKPORT_I_SCLK_USI 0x20c8
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI13_IPCLKPORT_I_PCLK 0x20cc
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI13_IPCLKPORT_I_SCLK_USI 0x20d0
+#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_XIU_P_PERIC1_IPCLKPORT_ACLK 0x20d4
+
+static const unsigned long peric1_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_PERIC1_BUS_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_BUS_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_SPEEDY2_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_SPEEDY2_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_SPI_CAM0_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_SPI_CAM0_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_SPI_CAM1_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_SPI_CAM1_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_UART_BT_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_UART_BT_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI04_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI04_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI05_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI05_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI06_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI06_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI07_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI07_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI08_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI08_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI09_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI09_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI10_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI11_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI12_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USER,
+ PLL_CON2_MUX_CLKCMU_PERIC1_USI13_USER,
+ CLK_CON_GAT_CLK_BLK_PERIC1_UID_PERIC1_CMU_PERIC1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_CLK_BLK_PERIC1_UID_RSTNSYNC_CLK_PERIC1_SPEEDY2_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P0_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P1_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P2_IPCLKPORT_ACLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_GPIO_PERIC1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM0_IPCLKPORT_IPCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM1_IPCLKPORT_IPCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM2_IPCLKPORT_IPCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM3_IPCLKPORT_IPCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_LHM_AXI_P_PERIC1_IPCLKPORT_I_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PMU_PERIC1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_RSTNSYNC_CLK_PERIC1_BUSP_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI1_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI1_IPCLKPORT_SCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI2_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI2_IPCLKPORT_SCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI_IPCLKPORT_SCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_TSP1_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_TSP2_IPCLKPORT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM0_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM0_IPCLKPORT_SPI_EXT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM1_IPCLKPORT_SPI_EXT_CLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SYSREG_PERIC1_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_UART_BT_IPCLKPORT_EXT_UCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_UART_BT_IPCLKPORT_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI04_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI04_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI05_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI05_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI06_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI06_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI07_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI07_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI08_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI08_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI09_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI09_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI10_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI10_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI11_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI11_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI12_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI12_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI13_IPCLKPORT_I_PCLK,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI13_IPCLKPORT_I_SCLK_USI,
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_XIU_P_PERIC1_IPCLKPORT_ACLK,
+};
+
+/* List of parent clocks for Muxes in CMU_PERIC1 */
+PNAME(mout_peric1_bus_user_p) = { "oscclk", "dout_cmu_peric1_bus" };
+PNAME(mout_peric1_speedy2_user_p) = { "oscclk",
+ "dout_cmu_peric1_speedy2" };
+PNAME(mout_peric1_spi_cam0_user_p) = { "oscclk",
+ "dout_cmu_peric1_spi_cam0" };
+PNAME(mout_peric1_spi_cam1_user_p) = { "oscclk",
+ "dout_cmu_peric1_spi_cam1" };
+PNAME(mout_peric1_uart_bt_user_p) = { "oscclk",
+ "dout_cmu_peric1_uart_bt" };
+PNAME(mout_peric1_usi04_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi04" };
+PNAME(mout_peric1_usi05_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi05" };
+PNAME(mout_peric1_usi06_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi06" };
+PNAME(mout_peric1_usi07_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi07" };
+PNAME(mout_peric1_usi08_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi08" };
+PNAME(mout_peric1_usi09_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi09" };
+PNAME(mout_peric1_usi10_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi10" };
+PNAME(mout_peric1_usi11_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi11" };
+PNAME(mout_peric1_usi12_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi12" };
+PNAME(mout_peric1_usi13_user_p) = { "oscclk",
+ "dout_cmu_peric1_usi13" };
+
+static const struct samsung_mux_clock peric1_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_PERIC1_BUS_USER, "mout_peric1_bus_user",
+ mout_peric1_bus_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_BUS_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC1_SPEEDY2_USER, "mout_peric1_speedy2_user",
+ mout_peric1_speedy2_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_SPEEDY2_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC1_SPI_CAM0_USER, "mout_peric1_spi_cam0_user",
+ mout_peric1_spi_cam0_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_SPI_CAM0_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC1_SPI_CAM1_USER, "mout_peric1_spi_cam1_user",
+ mout_peric1_spi_cam1_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_SPI_CAM1_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC1_UART_BT_USER, "mout_peric1_uart_bt_user",
+ mout_peric1_uart_bt_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_UART_BT_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI04_USER, "mout_peric1_usi04_user",
+ mout_peric1_usi04_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI04_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI05_USER, "mout_peric1_usi05_user",
+ mout_peric1_usi05_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI05_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI06_USER, "mout_peric1_usi06_user",
+ mout_peric1_usi06_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI06_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI07_USER, "mout_peric1_usi07_user",
+ mout_peric1_usi07_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI07_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI08_USER, "mout_peric1_usi08_user",
+ mout_peric1_usi08_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI08_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI09_USER, "mout_peric1_usi09_user",
+ mout_peric1_usi09_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI09_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI10_USER, "mout_peric1_usi10_user",
+ mout_peric1_usi10_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI11_USER, "mout_peric1_usi11_user",
+ mout_peric1_usi11_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI12_USER, "mout_peric1_usi12_user",
+ mout_peric1_usi12_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USER,
+ 4, 1),
+ MUX(CLK_MOUT_PERIC1_USI13_USER, "mout_peric1_usi13_user",
+ mout_peric1_usi13_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USER,
+ 4, 1),
+};
+
+static const struct samsung_gate_clock peric1_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_PERIC1_PERIC1_CMU_PERIC1_PCLK,
+ "gout_peric1_peric1_cmu_peric1_pclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_CLK_BLK_PERIC1_UID_PERIC1_CMU_PERIC1_IPCLKPORT_PCLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC1_RSTNSYNC_CLK_PERIC1_SPEEDY2_CLK,
+ "gout_peric1_rstnsync_clk_peric1_speedy2_clk",
+ "mout_peric1_speedy2_user",
+ CLK_CON_GAT_CLK_BLK_PERIC1_UID_RSTNSYNC_CLK_PERIC1_SPEEDY2_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_AXI2APB_PERIC1P0_ACLK,
+ "gout_peric1_axi2apb_peric1p0_aclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P0_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC1_AXI2APB_PERIC1P1_ACLK,
+ "gout_peric1_axi2apb_peric1p1_aclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P1_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC1_AXI2APB_PERIC1P2_ACLK,
+ "gout_peric1_axi2apb_peric1p2_aclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_AXI2APB_PERIC1P2_IPCLKPORT_ACLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC1_GPIO_PERIC1_PCLK,
+ "gout_peric1_gpio_peric1_pclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_GPIO_PERIC1_IPCLKPORT_PCLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_PERIC1_HSI2C_CAM0_IPCLK, "gout_peric1_hsi2c_cam0_ipclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM0_IPCLKPORT_IPCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_HSI2C_CAM1_IPCLK,
+ "gout_peric1_hsi2c_cam1_ipclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM1_IPCLKPORT_IPCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_HSI2C_CAM2_IPCLK,
+ "gout_peric1_hsi2c_cam2_ipclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM2_IPCLKPORT_IPCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_HSI2C_CAM3_IPCLK, "gout_peric1_hsi2c_cam3_ipclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_HSI2C_CAM3_IPCLKPORT_IPCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_LHM_AXI_P_PERIC1_I_CLK,
+ "gout_peric1_lhm_axi_p_peric1_i_clk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_LHM_AXI_P_PERIC1_IPCLKPORT_I_CLK,
+ 21, CLK_IS_CRITICAL, 0),
+ GATE(CLK_GOUT_PERIC1_PMU_PERIC1_PCLK, "gout_peric1_pmu_peric1_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PMU_PERIC1_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_RSTNSYNC_CLK_PERIC1_BUSP_CLK,
+ "gout_peric1_rstnsync_clk_peric1_busp_clk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_RSTNSYNC_CLK_PERIC1_BUSP_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_DDI1_CLK, "gout_peric1_speedy2_ddi1_clk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI1_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_DDI1_SCLK,
+ "gout_peric1_speedy2_ddi1_sclk", "mout_peric1_speedy2_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI1_IPCLKPORT_SCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_DDI2_CLK, "gout_peric1_speedy2_ddi2_clk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI2_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_DDI2_SCLK,
+ "gout_peric1_speedy2_ddi2_sclk", "mout_peric1_speedy2_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI2_IPCLKPORT_SCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_DDI_CLK, "gout_peric1_speedy2_ddi_clk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_DDI_SCLK, "gout_peric1_speedy2_ddi_sclk",
+ "mout_peric1_speedy2_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_DDI_IPCLKPORT_SCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_TSP1_CLK, "gout_peric1_speedy2_tsp1_clk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_TSP1_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPEEDY2_TSP2_CLK, "gout_peric1_speedy2_tsp2_clk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPEEDY2_TSP2_IPCLKPORT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPI_CAM0_PCLK, "gout_peric1_spi_cam0_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM0_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPI_CAM0_SPI_EXT_CLK,
+ "gout_peric1_spi_cam0_spi_ext_clk", "mout_peric1_spi_cam0_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM0_IPCLKPORT_SPI_EXT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPI_CAM1_PCLK, "gout_peric1_spi_cam1_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM1_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SPI_CAM1_SPI_EXT_CLK,
+ "gout_peric1_spi_cam1_spi_ext_clk", "mout_peric1_spi_cam1_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SPI_CAM1_IPCLKPORT_SPI_EXT_CLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_SYSREG_PERIC1_PCLK,
+ "gout_peric1_sysreg_peric1_pclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_SYSREG_PERIC1_IPCLKPORT_PCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_UART_BT_EXT_UCLK, "gout_peric1_uart_bt_ext_uclk",
+ "mout_peric1_uart_bt_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_UART_BT_IPCLKPORT_EXT_UCLK,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_UART_BT_PCLK, "gout_peric1_uart_bt_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_UART_BT_IPCLKPORT_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI04_I_PCLK, "gout_peric1_usi04_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI04_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI04_I_SCLK_USI, "gout_peric1_usi04_i_sclk_usi",
+ "mout_peric1_usi04_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI04_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI05_I_PCLK, "gout_peric1_usi05_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI05_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI05_I_SCLK_USI, "gout_peric1_usi05_i_sclk_usi",
+ "mout_peric1_usi05_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI05_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI06_I_PCLK, "gout_peric1_usi06_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI06_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI06_I_SCLK_USI, "gout_peric1_usi06_i_sclk_usi",
+ "mout_peric1_usi06_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI06_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI07_I_PCLK, "gout_peric1_usi07_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI07_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI07_I_SCLK_USI, "gout_peric1_usi07_i_sclk_usi",
+ "mout_peric1_usi07_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI07_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI08_I_PCLK, "gout_peric1_usi08_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI08_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI08_I_SCLK_USI, "gout_peric1_usi08_i_sclk_usi",
+ "mout_peric1_usi08_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI08_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI09_I_PCLK, "gout_peric1_usi09_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI09_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI09_I_SCLK_USI, "gout_peric1_usi09_i_sclk_usi",
+ "mout_peric1_usi09_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI09_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI10_I_PCLK, "gout_peric1_usi10_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI10_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI10_I_SCLK_USI, "gout_peric1_usi10_i_sclk_usi",
+ "mout_peric1_usi10_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI10_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI11_I_PCLK, "gout_peric1_usi11_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI11_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI11_I_SCLK_USI, "gout_peric1_usi11_i_sclk_usi",
+ "mout_peric1_usi11_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI11_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI12_I_PCLK, "gout_peric1_usi12_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI12_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI12_I_SCLK_USI, "gout_peric1_usi12_i_sclk_usi",
+ "mout_peric1_usi12_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI12_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI13_I_PCLK, "gout_peric1_usi13_i_pclk",
+ "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI13_IPCLKPORT_I_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_USI13_I_SCLK_USI, "gout_peric1_usi13_i_sclk_usi",
+ "mout_peric1_usi13_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_USI13_IPCLKPORT_I_SCLK_USI,
+ 21, 0, 0),
+ GATE(CLK_GOUT_PERIC1_XIU_P_PERIC1_ACLK,
+ "gout_peric1_xiu_p_peric1_aclk", "mout_peric1_bus_user",
+ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_XIU_P_PERIC1_IPCLKPORT_ACLK,
+ 21, CLK_IGNORE_UNUSED, 0),
+};
+
+static const struct samsung_cmu_info peric1_cmu_info __initconst = {
+ .mux_clks = peric1_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(peric1_mux_clks),
+ .gate_clks = peric1_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(peric1_gate_clks),
+ .nr_clk_ids = CLKS_NR_PERIC1,
+ .clk_regs = peric1_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(peric1_clk_regs),
+ .clk_name = "bus",
+};
+
+static int __init exynos8895_cmu_probe(struct platform_device *pdev)
+{
+ const struct samsung_cmu_info *info;
+ struct device *dev = &pdev->dev;
+
+ info = of_device_get_match_data(dev);
+ exynos_arm64_register_cmu(dev, dev->of_node, info);
+
+ return 0;
+}
+
+static const struct of_device_id exynos8895_cmu_of_match[] = {
+ {
+ .compatible = "samsung,exynos8895-cmu-fsys0",
+ .data = &fsys0_cmu_info,
+ }, {
+ .compatible = "samsung,exynos8895-cmu-fsys1",
+ .data = &fsys1_cmu_info,
+ }, {
+ .compatible = "samsung,exynos8895-cmu-peric0",
+ .data = &peric0_cmu_info,
+ }, {
+ .compatible = "samsung,exynos8895-cmu-peric1",
+ .data = &peric1_cmu_info,
+ },
+ { }
+};
+
+static struct platform_driver exynos8895_cmu_driver __refdata = {
+ .driver = {
+ .name = "exynos8895-cmu",
+ .of_match_table = exynos8895_cmu_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = exynos8895_cmu_probe,
+};
+
+static int __init exynos8895_cmu_init(void)
+{
+ return platform_driver_register(&exynos8895_cmu_driver);
+}
+core_initcall(exynos8895_cmu_init);
diff --git a/drivers/clk/samsung/clk-exynosautov920.c b/drivers/clk/samsung/clk-exynosautov920.c
index f60f0a0c598d..2a8bfd5d9abc 100644
--- a/drivers/clk/samsung/clk-exynosautov920.c
+++ b/drivers/clk/samsung/clk-exynosautov920.c
@@ -19,6 +19,10 @@
/* NOTE: Must be equal to the last clock ID increased by one */
#define CLKS_NR_TOP (DOUT_CLKCMU_TAA_NOC + 1)
#define CLKS_NR_PERIC0 (CLK_DOUT_PERIC0_I3C + 1)
+#define CLKS_NR_PERIC1 (CLK_DOUT_PERIC1_I3C + 1)
+#define CLKS_NR_MISC (CLK_DOUT_MISC_OSC_DIV2 + 1)
+#define CLKS_NR_HSI0 (CLK_DOUT_HSI0_PCIE_APB + 1)
+#define CLKS_NR_HSI1 (CLK_MOUT_HSI1_USBDRD + 1)
/* ---- CMU_TOP ------------------------------------------------------------ */
@@ -974,6 +978,8 @@ static const struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initcon
"mout_shared5_pll", 1, 3, 0),
FFACTOR(DOUT_SHARED5_DIV4, "dout_shared5_div4",
"mout_shared5_pll", 1, 4, 0),
+ FFACTOR(DOUT_TCXO_DIV2, "dout_tcxo_div2",
+ "oscclk", 1, 2, 0),
};
static const struct samsung_cmu_info top_cmu_info __initconst = {
@@ -1139,6 +1145,277 @@ static const struct samsung_cmu_info peric0_cmu_info __initconst = {
.clk_name = "noc",
};
+/* ---- CMU_PERIC1 --------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_PERIC1 (0x10C00000) */
+#define PLL_CON0_MUX_CLKCMU_PERIC1_IP_USER 0x600
+#define PLL_CON0_MUX_CLKCMU_PERIC1_NOC_USER 0x610
+#define CLK_CON_MUX_MUX_CLK_PERIC1_I3C 0x1000
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI09_USI 0x1004
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI10_USI 0x1008
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI11_USI 0x100c
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI12_USI 0x1010
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI13_USI 0x1014
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI14_USI 0x1018
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI15_USI 0x101c
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI16_USI 0x1020
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI17_USI 0x1024
+#define CLK_CON_MUX_MUX_CLK_PERIC1_USI_I2C 0x1028
+#define CLK_CON_DIV_DIV_CLK_PERIC1_I3C 0x1800
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI09_USI 0x1804
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI 0x1808
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI 0x180c
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI 0x1810
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI 0x1814
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI14_USI 0x1818
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI15_USI 0x181c
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI16_USI 0x1820
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI17_USI 0x1824
+#define CLK_CON_DIV_DIV_CLK_PERIC1_USI_I2C 0x1828
+
+static const unsigned long peric1_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_PERIC1_IP_USER,
+ PLL_CON0_MUX_CLKCMU_PERIC1_NOC_USER,
+ CLK_CON_MUX_MUX_CLK_PERIC1_I3C,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI09_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI10_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI11_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI12_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI13_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI14_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI15_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI16_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI17_USI,
+ CLK_CON_MUX_MUX_CLK_PERIC1_USI_I2C,
+ CLK_CON_DIV_DIV_CLK_PERIC1_I3C,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI09_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI14_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI15_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI16_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI17_USI,
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI_I2C,
+};
+
+/* List of parent clocks for Muxes in CMU_PERIC1 */
+PNAME(mout_peric1_ip_user_p) = { "oscclk", "dout_clkcmu_peric1_ip" };
+PNAME(mout_peric1_noc_user_p) = { "oscclk", "dout_clkcmu_peric1_noc" };
+PNAME(mout_peric1_usi_p) = { "oscclk", "mout_peric1_ip_user" };
+
+static const struct samsung_mux_clock peric1_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_PERIC1_IP_USER, "mout_peric1_ip_user",
+ mout_peric1_ip_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_IP_USER, 4, 1),
+ MUX(CLK_MOUT_PERIC1_NOC_USER, "mout_peric1_noc_user",
+ mout_peric1_noc_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_NOC_USER, 4, 1),
+ /* USI09 ~ USI17 */
+ MUX(CLK_MOUT_PERIC1_USI09_USI, "mout_peric1_usi09_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI09_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI10_USI, "mout_peric1_usi10_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI10_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI11_USI, "mout_peric1_usi11_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI11_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI12_USI, "mout_peric1_usi12_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI12_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI13_USI, "mout_peric1_usi13_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI13_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI14_USI, "mout_peric1_usi14_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI14_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI15_USI, "mout_peric1_usi15_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI15_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI16_USI, "mout_peric1_usi16_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI16_USI, 0, 1),
+ MUX(CLK_MOUT_PERIC1_USI17_USI, "mout_peric1_usi17_usi",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI17_USI, 0, 1),
+ /* USI_I2C */
+ MUX(CLK_MOUT_PERIC1_USI_I2C, "mout_peric1_usi_i2c",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI_I2C, 0, 1),
+ /* USI_I3C */
+ MUX(CLK_MOUT_PERIC1_I3C, "mout_peric1_i3c",
+ mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_I3C, 0, 1),
+};
+
+static const struct samsung_div_clock peric1_div_clks[] __initconst = {
+ /* USI09 ~ USI17 */
+ DIV(CLK_DOUT_PERIC1_USI09_USI, "dout_peric1_usi09_usi",
+ "mout_peric1_usi09_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI09_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI10_USI, "dout_peric1_usi10_usi",
+ "mout_peric1_usi10_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI11_USI, "dout_peric1_usi11_usi",
+ "mout_peric1_usi11_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI12_USI, "dout_peric1_usi12_usi",
+ "mout_peric1_usi12_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI13_USI, "dout_peric1_usi13_usi",
+ "mout_peric1_usi13_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI14_USI, "dout_peric1_usi14_usi",
+ "mout_peric1_usi14_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI14_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI15_USI, "dout_peric1_usi15_usi",
+ "mout_peric1_usi15_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI15_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI16_USI, "dout_peric1_usi16_usi",
+ "mout_peric1_usi16_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI16_USI,
+ 0, 4),
+ DIV(CLK_DOUT_PERIC1_USI17_USI, "dout_peric1_usi17_usi",
+ "mout_peric1_usi17_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI17_USI,
+ 0, 4),
+ /* USI_I2C */
+ DIV(CLK_DOUT_PERIC1_USI_I2C, "dout_peric1_usi_i2c",
+ "mout_peric1_usi_i2c", CLK_CON_DIV_DIV_CLK_PERIC1_USI_I2C, 0, 4),
+ /* USI_I3C */
+ DIV(CLK_DOUT_PERIC1_I3C, "dout_peric1_i3c",
+ "mout_peric1_i3c", CLK_CON_DIV_DIV_CLK_PERIC1_I3C, 0, 4),
+};
+
+static const struct samsung_cmu_info peric1_cmu_info __initconst = {
+ .mux_clks = peric1_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(peric1_mux_clks),
+ .div_clks = peric1_div_clks,
+ .nr_div_clks = ARRAY_SIZE(peric1_div_clks),
+ .nr_clk_ids = CLKS_NR_PERIC1,
+ .clk_regs = peric1_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(peric1_clk_regs),
+ .clk_name = "noc",
+};
+
+/* ---- CMU_MISC --------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_MISC (0x10020000) */
+#define PLL_CON0_MUX_CLKCMU_MISC_NOC_USER 0x600
+#define CLK_CON_MUX_MUX_CLK_MISC_GIC 0x1000
+#define CLK_CON_DIV_CLKCMU_OTP 0x1800
+#define CLK_CON_DIV_DIV_CLK_MISC_NOCP 0x1804
+#define CLK_CON_DIV_DIV_CLK_MISC_OSC_DIV2 0x1808
+
+static const unsigned long misc_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_MISC_NOC_USER,
+ CLK_CON_MUX_MUX_CLK_MISC_GIC,
+ CLK_CON_DIV_CLKCMU_OTP,
+ CLK_CON_DIV_DIV_CLK_MISC_NOCP,
+ CLK_CON_DIV_DIV_CLK_MISC_OSC_DIV2,
+};
+
+/* List of parent clocks for Muxes in CMU_MISC */
+PNAME(mout_misc_noc_user_p) = { "oscclk", "dout_clkcmu_misc_noc" };
+PNAME(mout_misc_gic_p) = { "dout_misc_nocp", "oscclk" };
+
+static const struct samsung_mux_clock misc_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_MISC_NOC_USER, "mout_misc_noc_user",
+ mout_misc_noc_user_p, PLL_CON0_MUX_CLKCMU_MISC_NOC_USER, 4, 1),
+ MUX(CLK_MOUT_MISC_GIC, "mout_misc_gic",
+ mout_misc_gic_p, CLK_CON_MUX_MUX_CLK_MISC_GIC, 0, 1),
+};
+
+static const struct samsung_div_clock misc_div_clks[] __initconst = {
+ DIV(CLK_DOUT_MISC_NOCP, "dout_misc_nocp",
+ "mout_misc_noc_user", CLK_CON_DIV_DIV_CLK_MISC_NOCP,
+ 0, 3),
+};
+
+static const struct samsung_fixed_factor_clock misc_fixed_factor_clks[] __initconst = {
+ FFACTOR(CLK_DOUT_MISC_OTP, "dout_misc_otp",
+ "oscclk", 1, 10, 0),
+ FFACTOR(CLK_DOUT_MISC_OSC_DIV2, "dout_misc_osc_div2",
+ "oscclk", 1, 2, 0),
+};
+
+static const struct samsung_cmu_info misc_cmu_info __initconst = {
+ .mux_clks = misc_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(misc_mux_clks),
+ .div_clks = misc_div_clks,
+ .nr_div_clks = ARRAY_SIZE(misc_div_clks),
+ .fixed_factor_clks = misc_fixed_factor_clks,
+ .nr_fixed_factor_clks = ARRAY_SIZE(misc_fixed_factor_clks),
+ .nr_clk_ids = CLKS_NR_MISC,
+ .clk_regs = misc_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(misc_clk_regs),
+ .clk_name = "noc",
+};
+
+/* ---- CMU_HSI0 --------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_HSI0 (0x16000000) */
+#define PLL_CON0_MUX_CLKCMU_HSI0_NOC_USER 0x600
+#define CLK_CON_DIV_DIV_CLK_HSI0_PCIE_APB 0x1800
+
+static const unsigned long hsi0_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_HSI0_NOC_USER,
+ CLK_CON_DIV_DIV_CLK_HSI0_PCIE_APB,
+};
+
+/* List of parent clocks for Muxes in CMU_HSI0 */
+PNAME(mout_hsi0_noc_user_p) = { "oscclk", "dout_clkcmu_hsi0_noc" };
+
+static const struct samsung_mux_clock hsi0_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_HSI0_NOC_USER, "mout_hsi0_noc_user",
+ mout_hsi0_noc_user_p, PLL_CON0_MUX_CLKCMU_HSI0_NOC_USER, 4, 1),
+};
+
+static const struct samsung_div_clock hsi0_div_clks[] __initconst = {
+ DIV(CLK_DOUT_HSI0_PCIE_APB, "dout_hsi0_pcie_apb",
+ "mout_hsi0_noc_user", CLK_CON_DIV_DIV_CLK_HSI0_PCIE_APB,
+ 0, 4),
+};
+
+static const struct samsung_cmu_info hsi0_cmu_info __initconst = {
+ .mux_clks = hsi0_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(hsi0_mux_clks),
+ .div_clks = hsi0_div_clks,
+ .nr_div_clks = ARRAY_SIZE(hsi0_div_clks),
+ .nr_clk_ids = CLKS_NR_HSI0,
+ .clk_regs = hsi0_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(hsi0_clk_regs),
+ .clk_name = "noc",
+};
+
+/* ---- CMU_HSI1 --------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_HSI1 (0x16400000) */
+#define PLL_CON0_MUX_CLKCMU_HSI1_MMC_CARD_USER 0x600
+#define PLL_CON0_MUX_CLKCMU_HSI1_NOC_USER 0x610
+#define PLL_CON0_MUX_CLKCMU_HSI1_USBDRD_USER 0x620
+#define CLK_CON_MUX_MUX_CLK_HSI1_USBDRD 0x1000
+
+static const unsigned long hsi1_clk_regs[] __initconst = {
+ PLL_CON0_MUX_CLKCMU_HSI1_MMC_CARD_USER,
+ PLL_CON0_MUX_CLKCMU_HSI1_NOC_USER,
+ PLL_CON0_MUX_CLKCMU_HSI1_USBDRD_USER,
+ CLK_CON_MUX_MUX_CLK_HSI1_USBDRD,
+};
+
+/* List of parent clocks for Muxes in CMU_HSI1 */
+PNAME(mout_hsi1_mmc_card_user_p) = {"oscclk", "dout_clkcmu_hsi1_mmc_card"};
+PNAME(mout_hsi1_noc_user_p) = { "oscclk", "dout_clkcmu_hsi1_noc" };
+PNAME(mout_hsi1_usbdrd_user_p) = { "oscclk", "mout_clkcmu_hsi1_usbdrd" };
+PNAME(mout_hsi1_usbdrd_p) = { "dout_tcxo_div2", "mout_hsi1_usbdrd_user" };
+
+static const struct samsung_mux_clock hsi1_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_HSI1_MMC_CARD_USER, "mout_hsi1_mmc_card_user",
+ mout_hsi1_mmc_card_user_p, PLL_CON0_MUX_CLKCMU_HSI1_MMC_CARD_USER, 4, 1),
+ MUX(CLK_MOUT_HSI1_NOC_USER, "mout_hsi1_noc_user",
+ mout_hsi1_noc_user_p, PLL_CON0_MUX_CLKCMU_HSI1_NOC_USER, 4, 1),
+ MUX(CLK_MOUT_HSI1_USBDRD_USER, "mout_hsi1_usbdrd_user",
+ mout_hsi1_usbdrd_user_p, PLL_CON0_MUX_CLKCMU_HSI1_USBDRD_USER, 4, 1),
+ MUX(CLK_MOUT_HSI1_USBDRD, "mout_hsi1_usbdrd",
+ mout_hsi1_usbdrd_p, CLK_CON_MUX_MUX_CLK_HSI1_USBDRD, 4, 1),
+};
+
+static const struct samsung_cmu_info hsi1_cmu_info __initconst = {
+ .mux_clks = hsi1_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(hsi1_mux_clks),
+ .nr_clk_ids = CLKS_NR_HSI1,
+ .clk_regs = hsi1_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(hsi1_clk_regs),
+ .clk_name = "noc",
+};
+
static int __init exynosautov920_cmu_probe(struct platform_device *pdev)
{
const struct samsung_cmu_info *info;
@@ -1154,6 +1431,18 @@ static const struct of_device_id exynosautov920_cmu_of_match[] = {
{
.compatible = "samsung,exynosautov920-cmu-peric0",
.data = &peric0_cmu_info,
+ }, {
+ .compatible = "samsung,exynosautov920-cmu-peric1",
+ .data = &peric1_cmu_info,
+ }, {
+ .compatible = "samsung,exynosautov920-cmu-misc",
+ .data = &misc_cmu_info,
+ }, {
+ .compatible = "samsung,exynosautov920-cmu-hsi0",
+ .data = &hsi0_cmu_info,
+ }, {
+ .compatible = "samsung,exynosautov920-cmu-hsi1",
+ .data = &hsi1_cmu_info,
},
{ }
};
diff --git a/drivers/clk/samsung/clk-fsd.c b/drivers/clk/samsung/clk-fsd.c
index 6f984cfcd33c..9a6006c298c2 100644
--- a/drivers/clk/samsung/clk-fsd.c
+++ b/drivers/clk/samsung/clk-fsd.c
@@ -82,6 +82,15 @@
#define GAT_CMU_NS_BRDG_CMU_IPCLKPORT_CLK__PSOC_CMU__CLK_CMU 0x205c
#define GAT_CMU_SYSREG_CMU_IPCLKPORT_PCLK 0x2060
+/* NOTE: Must be equal to the last clock ID increased by one */
+#define CLKS_NR_CMU (GAT_CMU_FSYS0_SHARED0DIV4 + 1)
+#define CLKS_NR_PERIC (PERIC_DOUT_RGMII_CLK + 1)
+#define CLKS_NR_FSYS0 (FSYS0_DOUT_FSYS0_PERIBUS_GRP + 1)
+#define CLKS_NR_FSYS1 (PCIE_LINK1_IPCLKPORT_SLV_ACLK + 1)
+#define CLKS_NR_IMEM (IMEM_TMU_GT_IPCLKPORT_I_CLK_TS + 1)
+#define CLKS_NR_MFC (MFC_MFC_IPCLKPORT_ACLK + 1)
+#define CLKS_NR_CAM_CSI (CAM_CSI2_3_IPCLKPORT_I_ACLK + 1)
+
static const unsigned long cmu_clk_regs[] __initconst = {
PLL_LOCKTIME_PLL_SHARED0,
PLL_LOCKTIME_PLL_SHARED1,
@@ -300,7 +309,7 @@ static const struct samsung_cmu_info cmu_cmu_info __initconst = {
.nr_div_clks = ARRAY_SIZE(cmu_div_clks),
.gate_clks = cmu_gate_clks,
.nr_gate_clks = ARRAY_SIZE(cmu_gate_clks),
- .nr_clk_ids = CMU_NR_CLK,
+ .nr_clk_ids = CLKS_NR_CMU,
.clk_regs = cmu_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cmu_clk_regs),
};
@@ -665,7 +674,7 @@ static const struct samsung_cmu_info peric_cmu_info __initconst = {
.nr_gate_clks = ARRAY_SIZE(peric_gate_clks),
.fixed_clks = peric_fixed_clks,
.nr_fixed_clks = ARRAY_SIZE(peric_fixed_clks),
- .nr_clk_ids = PERIC_NR_CLK,
+ .nr_clk_ids = CLKS_NR_PERIC,
.clk_regs = peric_clk_regs,
.nr_clk_regs = ARRAY_SIZE(peric_clk_regs),
.clk_name = "dout_cmu_pll_shared0_div4",
@@ -964,7 +973,7 @@ static const struct samsung_cmu_info fsys0_cmu_info __initconst = {
.nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks),
.fixed_clks = fsys0_fixed_clks,
.nr_fixed_clks = ARRAY_SIZE(fsys0_fixed_clks),
- .nr_clk_ids = FSYS0_NR_CLK,
+ .nr_clk_ids = CLKS_NR_FSYS0,
.clk_regs = fsys0_clk_regs,
.nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs),
.clk_name = "dout_cmu_fsys0_shared1div4",
@@ -1136,7 +1145,7 @@ static const struct samsung_cmu_info fsys1_cmu_info __initconst = {
.nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks),
.fixed_clks = fsys1_fixed_clks,
.nr_fixed_clks = ARRAY_SIZE(fsys1_fixed_clks),
- .nr_clk_ids = FSYS1_NR_CLK,
+ .nr_clk_ids = CLKS_NR_FSYS1,
.clk_regs = fsys1_clk_regs,
.nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs),
.clk_name = "dout_cmu_fsys1_shared0div4",
@@ -1413,7 +1422,7 @@ static const struct samsung_cmu_info imem_cmu_info __initconst = {
.nr_div_clks = ARRAY_SIZE(imem_div_clks),
.gate_clks = imem_gate_clks,
.nr_gate_clks = ARRAY_SIZE(imem_gate_clks),
- .nr_clk_ids = IMEM_NR_CLK,
+ .nr_clk_ids = CLKS_NR_IMEM,
.clk_regs = imem_clk_regs,
.nr_clk_regs = ARRAY_SIZE(imem_clk_regs),
};
@@ -1538,7 +1547,7 @@ static const struct samsung_cmu_info mfc_cmu_info __initconst = {
.nr_div_clks = ARRAY_SIZE(mfc_div_clks),
.gate_clks = mfc_gate_clks,
.nr_gate_clks = ARRAY_SIZE(mfc_gate_clks),
- .nr_clk_ids = MFC_NR_CLK,
+ .nr_clk_ids = CLKS_NR_MFC,
.clk_regs = mfc_clk_regs,
.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs),
};
@@ -1742,7 +1751,7 @@ static const struct samsung_cmu_info cam_csi_cmu_info __initconst = {
.nr_div_clks = ARRAY_SIZE(cam_csi_div_clks),
.gate_clks = cam_csi_gate_clks,
.nr_gate_clks = ARRAY_SIZE(cam_csi_gate_clks),
- .nr_clk_ids = CAM_CSI_NR_CLK,
+ .nr_clk_ids = CLKS_NR_CAM_CSI,
.clk_regs = cam_csi_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cam_csi_clk_regs),
};
diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index 85098c61c15e..86b39edba122 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -2775,11 +2775,11 @@ static const struct samsung_gate_clock hsi2_gate_clks[] __initconst = {
GATE(CLK_GOUT_HSI2_QE_UFS_EMBD_HSI2_ACLK,
"gout_hsi2_qe_ufs_embd_hsi2_aclk", "mout_hsi2_bus_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_ACLK,
- 21, 0, 0),
+ 21, CLK_IS_CRITICAL, 0),
GATE(CLK_GOUT_HSI2_QE_UFS_EMBD_HSI2_PCLK,
"gout_hsi2_qe_ufs_embd_hsi2_pclk", "mout_hsi2_bus_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_PCLK,
- 21, 0, 0),
+ 21, CLK_IS_CRITICAL, 0),
GATE(CLK_GOUT_HSI2_CLK_HSI2_BUS_CLK,
"gout_hsi2_clk_hsi2_bus_clk", "mout_hsi2_bus_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_RSTNSYNC_CLK_HSI2_BUS_IPCLKPORT_CLK,
@@ -2806,7 +2806,7 @@ static const struct samsung_gate_clock hsi2_gate_clks[] __initconst = {
GATE(CLK_GOUT_HSI2_SYSREG_HSI2_PCLK,
"gout_hsi2_sysreg_hsi2_pclk", "mout_hsi2_bus_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_SYSREG_HSI2_IPCLKPORT_PCLK,
- 21, 0, 0),
+ 21, CLK_IS_CRITICAL, 0),
GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4A_DBI_1_ACLK,
"gout_hsi2_uasc_pcie_gen4a_dbi_1_aclk", "mout_hsi2_bus_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_DBI_1_IPCLKPORT_ACLK,
@@ -2842,7 +2842,7 @@ static const struct samsung_gate_clock hsi2_gate_clks[] __initconst = {
GATE(CLK_GOUT_HSI2_UFS_EMBD_I_ACLK,
"gout_hsi2_ufs_embd_i_aclk", "mout_hsi2_bus_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_ACLK,
- 21, 0, 0),
+ 21, CLK_IS_CRITICAL, 0),
GATE(CLK_GOUT_HSI2_UFS_EMBD_I_CLK_UNIPRO,
"gout_hsi2_ufs_embd_i_clk_unipro", "mout_hsi2_ufs_embd_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_CLK_UNIPRO,
@@ -2850,7 +2850,7 @@ static const struct samsung_gate_clock hsi2_gate_clks[] __initconst = {
GATE(CLK_GOUT_HSI2_UFS_EMBD_I_FMP_CLK,
"gout_hsi2_ufs_embd_i_fmp_clk", "mout_hsi2_bus_user",
CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_FMP_CLK,
- 21, 0, 0),
+ 21, CLK_IS_CRITICAL, 0),
/* TODO: should have a driver for this */
GATE(CLK_GOUT_HSI2_XIU_D_HSI2_ACLK,
"gout_hsi2_xiu_d_hsi2_aclk", "mout_hsi2_bus_user",
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index cca3e630922c..be6b51694919 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1370,6 +1370,8 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
break;
case pll_1417x:
case pll_1418x:
+ case pll_1051x:
+ case pll_1052x:
case pll_0818x:
case pll_0822x:
case pll_0516x:
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 3481941ba07a..858ab367eb65 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -43,6 +43,8 @@ enum samsung_pll_type {
pll_0517x,
pll_0518x,
pll_531x,
+ pll_1051x,
+ pll_1052x,
};
#define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index d27a1f73f077..e2ec8fe32e39 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -3,7 +3,7 @@
* Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com>
*
* Common Clock Framework support for all S3C64xx SoCs.
-*/
+ */
#include <linux/slab.h>
#include <linux/clk-provider.h>
diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c
index b31c00ea331f..d19a3d9fd452 100644
--- a/drivers/clk/samsung/clk-s5pv210-audss.c
+++ b/drivers/clk/samsung/clk-s5pv210-audss.c
@@ -8,7 +8,7 @@
* Author: Padmavathi Venna <padma.v@samsung.com>
*
* Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
-*/
+ */
#include <linux/io.h>
#include <linux/clk.h>
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index afa5760ed3a1..283c523763e6 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -6,7 +6,7 @@
*
* This file includes utility functions to register clocks to common
* clock framework for Samsung platforms.
-*/
+ */
#include <linux/slab.h>
#include <linux/clkdev.h>
diff --git a/drivers/clk/sophgo/clk-sg2042-pll.c b/drivers/clk/sophgo/clk-sg2042-pll.c
index ff9deeef509b..1537f4f05860 100644
--- a/drivers/clk/sophgo/clk-sg2042-pll.c
+++ b/drivers/clk/sophgo/clk-sg2042-pll.c
@@ -153,7 +153,7 @@ static unsigned long sg2042_pll_recalc_rate(unsigned int reg_value,
sg2042_pll_ctrl_decode(reg_value, &ctrl_table);
- numerator = parent_rate * ctrl_table.fbdiv;
+ numerator = (u64)parent_rate * ctrl_table.fbdiv;
denominator = ctrl_table.refdiv * ctrl_table.postdiv1 * ctrl_table.postdiv2;
do_div(numerator, denominator);
return numerator;
diff --git a/drivers/clk/starfive/clk-starfive-jh7110-pll.c b/drivers/clk/starfive/clk-starfive-jh7110-pll.c
index 3598390e8fd0..56dc58a04f8a 100644
--- a/drivers/clk/starfive/clk-starfive-jh7110-pll.c
+++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.c
@@ -453,7 +453,7 @@ static struct clk_hw *jh7110_pll_get(struct of_phandle_args *clkspec, void *data
return ERR_PTR(-EINVAL);
}
-static int jh7110_pll_probe(struct platform_device *pdev)
+static int __init jh7110_pll_probe(struct platform_device *pdev)
{
struct jh7110_pll_priv *priv;
unsigned int idx;
diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c
index de36e21d3eaf..4084714adb15 100644
--- a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c
@@ -91,7 +91,7 @@ static struct clk_hw_onecell_data sun20i_d1_r_hw_clks = {
},
};
-static struct ccu_reset_map sun20i_d1_r_ccu_resets[] = {
+static const struct ccu_reset_map sun20i_d1_r_ccu_resets[] = {
[RST_BUS_R_TIMER] = { 0x11c, BIT(16) },
[RST_BUS_R_TWD] = { 0x12c, BIT(16) },
[RST_BUS_R_PPU] = { 0x1ac, BIT(16) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
index 9b5cfac2ee70..c80ac2dfbb60 100644
--- a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
+++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
@@ -1232,7 +1232,7 @@ static struct clk_hw_onecell_data sun20i_d1_hw_clks = {
},
};
-static struct ccu_reset_map sun20i_d1_ccu_resets[] = {
+static const struct ccu_reset_map sun20i_d1_ccu_resets[] = {
[RST_MBUS] = { 0x540, BIT(30) },
[RST_BUS_DE] = { 0x60c, BIT(16) },
[RST_BUS_DI] = { 0x62c, BIT(16) },
@@ -1371,7 +1371,7 @@ static int sun20i_d1_ccu_probe(struct platform_device *pdev)
/* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */
val = readl(reg + SUN20I_D1_PLL_AUDIO0_REG);
- val &= ~BIT(1) | BIT(0);
+ val &= ~(BIT(1) | BIT(0));
writel(val, reg + SUN20I_D1_PLL_AUDIO0_REG);
/* Force fanout-27M factor N to 0. */
diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
index d1a1683baff4..54c794c50828 100644
--- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
+++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
@@ -1382,7 +1382,7 @@ static struct clk_hw_onecell_data sun7i_a20_hw_clks = {
.num = CLK_NUMBER_SUN7I,
};
-static struct ccu_reset_map sunxi_a10_a20_ccu_resets[] = {
+static const struct ccu_reset_map sunxi_a10_a20_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_PHY2] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
index 2c791761a646..cdd9721f9e7d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
@@ -166,7 +166,7 @@ static struct clk_hw_onecell_data sun50i_a100_r_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun50i_a100_r_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_a100_r_ccu_resets[] = {
[RST_R_APB1_TIMER] = { 0x11c, BIT(16) },
[RST_R_APB1_BUS_PWM] = { 0x13c, BIT(16) },
[RST_R_APB1_PPU] = { 0x17c, BIT(16) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
index bbaa82978716..1b6a49bc7184 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
@@ -1061,7 +1061,7 @@ static struct clk_hw_onecell_data sun50i_a100_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun50i_a100_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_a100_ccu_resets[] = {
[RST_MBUS] = { 0x540, BIT(30) },
[RST_BUS_DE] = { 0x60c, BIT(16) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index c255dba2c96d..82d7dcbca1cc 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -858,7 +858,7 @@ static struct clk_hw_onecell_data sun50i_a64_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun50i_a64_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_a64_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_HSIC] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
index c72815841111..d0ce2779c550 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
@@ -179,7 +179,7 @@ static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_TIMER] = { 0x11c, BIT(16) },
[RST_R_APB1_TWD] = { 0x12c, BIT(16) },
[RST_R_APB1_PWM] = { 0x13c, BIT(16) },
@@ -190,7 +190,7 @@ static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_W1] = { 0x1ec, BIT(16) },
};
-static struct ccu_reset_map sun50i_h616_r_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_h616_r_ccu_resets[] = {
[RST_R_APB1_TWD] = { 0x12c, BIT(16) },
[RST_R_APB2_I2C] = { 0x19c, BIT(16) },
[RST_R_APB2_RSB] = { 0x1bc, BIT(16) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index a20b621ad8f1..bd6fc3df911d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -1076,7 +1076,7 @@ static struct clk_hw_onecell_data sun50i_h6_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun50i_h6_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_h6_ccu_resets[] = {
[RST_MBUS] = { 0x540, BIT(30) },
[RST_BUS_DE] = { 0x60c, BIT(16) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
index 84e406ddf9d1..b001d0c03534 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -216,19 +216,29 @@ static struct ccu_nkmp pll_de_clk = {
};
/*
- * TODO: Determine SDM settings for the audio PLL. The manual suggests
- * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
- * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
- * pattern=0xe001288c for 22.5792 MHz.
- * This clashes with our fixed PLL_POST_DIV_P.
+ * Sigma-delta modulation settings table obtained from the vendor SDK driver.
+ * There are additional M0 and M1 divider bits not modelled here, so forced to
+ * fixed values in the probe routine. Sigma-delta modulation allows providing a
+ * fractional-N divider in the PLL, to help reaching those specific
+ * frequencies with less error.
*/
+static struct ccu_sdm_setting pll_audio_sdm_table[] = {
+ { .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
+ { .rate = 98304000, .pattern = 0xc001eb85, .m = 5, .n = 40 },
+};
+
#define SUN50I_H616_PLL_AUDIO_REG 0x078
static struct ccu_nm pll_audio_hs_clk = {
.enable = BIT(31),
.lock = BIT(28),
.n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
- .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .m = _SUNXI_CCU_DIV(16, 6),
+ .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table,
+ BIT(24), 0x178, BIT(31)),
+ .fixed_post_div = 2,
.common = {
+ .features = CCU_FEATURE_FIXED_POSTDIV |
+ CCU_FEATURE_SIGMA_DELTA_MOD,
.reg = 0x078,
.hw.init = CLK_HW_INIT("pll-audio-hs", "osc24M",
&ccu_nm_ops,
@@ -685,18 +695,20 @@ static const struct clk_hw *clk_parent_pll_audio[] = {
};
/*
- * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
- * rates can be set exactly in conjunction with sigma-delta modulation.
+ * The PLL_AUDIO_4X clock defaults to 24.5714 MHz according to the manual, with
+ * a final divider of 1. The 2X and 1X clocks use 2 and 4 respectively. The 1x
+ * clock is set to either 24576000 or 22579200 for 48Khz and 44.1Khz (and
+ * multiples).
*/
static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
clk_parent_pll_audio,
- 96, 1, CLK_SET_RATE_PARENT);
+ 4, 1, CLK_SET_RATE_PARENT);
static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
clk_parent_pll_audio,
- 48, 1, CLK_SET_RATE_PARENT);
+ 2, 1, CLK_SET_RATE_PARENT);
static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
clk_parent_pll_audio,
- 24, 1, CLK_SET_RATE_PARENT);
+ 1, 1, CLK_SET_RATE_PARENT);
static const struct clk_hw *pll_periph0_parents[] = {
&pll_periph0_clk.common.hw
@@ -990,7 +1002,7 @@ static struct clk_hw_onecell_data sun50i_h616_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun50i_h616_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_h616_ccu_resets[] = {
[RST_MBUS] = { 0x540, BIT(30) },
[RST_BUS_DE] = { 0x60c, BIT(16) },
@@ -1136,12 +1148,14 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev)
}
/*
- * Force the post-divider of pll-audio to 12 and the output divider
- * of it to 2, so 24576000 and 22579200 rates can be set exactly.
+ * Set the output-divider for the pll-audio clocks (M0) to 2 and the
+ * input divider (M1) to 1 as recommended by the manual when using
+ * SDM.
*/
val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
- val &= ~(GENMASK(21, 16) | BIT(0));
- writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
+ val &= ~BIT(1);
+ val |= BIT(0);
+ writel(val, reg + SUN50I_H616_PLL_AUDIO_REG);
/*
* First clock parent (osc32K) is unusable for CEC. But since there
diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c
index 1f4bc0e773a7..c9bf1fdb8a8a 100644
--- a/drivers/clk/sunxi-ng/ccu-sun5i.c
+++ b/drivers/clk/sunxi-ng/ccu-sun5i.c
@@ -731,7 +731,7 @@ static struct clk_hw_onecell_data sun5i_a10s_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun5i_a10s_ccu_resets[] = {
+static const struct ccu_reset_map sun5i_a10s_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
index e8b8d2dd7f2c..c2ad1209633e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
@@ -1146,7 +1146,7 @@ static struct clk_hw_onecell_data sun6i_a31_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun6i_a31_ccu_resets[] = {
+static const struct ccu_reset_map sun6i_a31_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_PHY2] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 87e23d16ed0f..724b202863a8 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -356,7 +356,7 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
const char *fw_name;
/* ext-osc32k was the only input clock in the old binding. */
- fw_name = of_property_read_bool(dev->of_node, "clock-names")
+ fw_name = of_property_present(dev->of_node, "clock-names")
? "ext-osc32k" : NULL;
ext_osc32k_clk = devm_clk_get_optional(dev, fw_name);
if (IS_ERR(ext_osc32k_clk))
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
index 6c2a08f722a8..9433dbac038e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
@@ -668,7 +668,7 @@ static struct clk_hw_onecell_data sun8i_a23_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun8i_a23_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_a23_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_HSIC] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
index 5e0bc08a9ce3..1ffc5ab9bc3c 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
@@ -712,7 +712,7 @@ static struct clk_hw_onecell_data sun8i_a33_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun8i_a33_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_a33_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_HSIC] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
index cb4c6b16c467..a51fb2c10c94 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
@@ -797,7 +797,7 @@ static struct clk_hw_onecell_data sun8i_a83t_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun8i_a83t_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_a83t_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_HSIC] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index 7683ea08d8e3..a742f83746d1 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -146,7 +146,7 @@ static struct clk_hw_onecell_data sun50i_a64_de2_hw_clks = {
.num = CLK_NUMBER_WITH_ROT,
};
-static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
+static const struct ccu_reset_map sun8i_a83t_de2_resets[] = {
[RST_MIXER0] = { 0x08, BIT(0) },
/*
* Mixer1 reset line is shared with wb, so only RST_WB is
@@ -156,7 +156,7 @@ static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
[RST_ROT] = { 0x08, BIT(3) },
};
-static struct ccu_reset_map sun8i_h3_de2_resets[] = {
+static const struct ccu_reset_map sun8i_h3_de2_resets[] = {
[RST_MIXER0] = { 0x08, BIT(0) },
/*
* Mixer1 reset line is shared with wb, so only RST_WB is
@@ -166,14 +166,14 @@ static struct ccu_reset_map sun8i_h3_de2_resets[] = {
[RST_WB] = { 0x08, BIT(2) },
};
-static struct ccu_reset_map sun50i_a64_de2_resets[] = {
+static const struct ccu_reset_map sun50i_a64_de2_resets[] = {
[RST_MIXER0] = { 0x08, BIT(0) },
[RST_MIXER1] = { 0x08, BIT(1) },
[RST_WB] = { 0x08, BIT(2) },
[RST_ROT] = { 0x08, BIT(3) },
};
-static struct ccu_reset_map sun50i_h5_de2_resets[] = {
+static const struct ccu_reset_map sun50i_h5_de2_resets[] = {
[RST_MIXER0] = { 0x08, BIT(0) },
[RST_MIXER1] = { 0x08, BIT(1) },
[RST_WB] = { 0x08, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 13e57db2f8d5..74da5d27af72 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -876,7 +876,7 @@ static struct clk_hw_onecell_data sun50i_h5_hw_clks = {
.num = CLK_NUMBER_H5,
};
-static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_h3_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_PHY2] = { 0x0cc, BIT(2) },
@@ -939,7 +939,7 @@ static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
[RST_BUS_SCR0] = { 0x2d8, BIT(20) },
};
-static struct ccu_reset_map sun50i_h5_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_h5_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_PHY2] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
index da6569334d68..2b3e094a32cb 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
@@ -178,7 +178,7 @@ static struct clk_hw_onecell_data sun50i_a64_r_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun8i_a83t_r_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_a83t_r_ccu_resets[] = {
[RST_APB0_IR] = { 0xb0, BIT(1) },
[RST_APB0_TIMER] = { 0xb0, BIT(2) },
[RST_APB0_RSB] = { 0xb0, BIT(3) },
@@ -186,14 +186,14 @@ static struct ccu_reset_map sun8i_a83t_r_ccu_resets[] = {
[RST_APB0_I2C] = { 0xb0, BIT(6) },
};
-static struct ccu_reset_map sun8i_h3_r_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_h3_r_ccu_resets[] = {
[RST_APB0_IR] = { 0xb0, BIT(1) },
[RST_APB0_TIMER] = { 0xb0, BIT(2) },
[RST_APB0_UART] = { 0xb0, BIT(4) },
[RST_APB0_I2C] = { 0xb0, BIT(6) },
};
-static struct ccu_reset_map sun50i_a64_r_ccu_resets[] = {
+static const struct ccu_reset_map sun50i_a64_r_ccu_resets[] = {
[RST_APB0_IR] = { 0xb0, BIT(1) },
[RST_APB0_TIMER] = { 0xb0, BIT(2) },
[RST_APB0_RSB] = { 0xb0, BIT(3) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
index 2f51ceab8016..a374aeeca3f4 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
@@ -1162,7 +1162,7 @@ static struct clk_hw_onecell_data sun8i_r40_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun8i_r40_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_r40_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_USB_PHY1] = { 0x0cc, BIT(1) },
[RST_USB_PHY2] = { 0x0cc, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index d24c0d8dfee4..00d04f7ad94d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -644,7 +644,7 @@ static struct clk_hw_onecell_data sun8i_v3_hw_clks = {
.num = CLK_I2S0 + 1,
};
-static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_MBUS] = { 0x0fc, BIT(31) },
@@ -679,7 +679,7 @@ static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
[RST_BUS_UART2] = { 0x2d8, BIT(18) },
};
-static struct ccu_reset_map sun8i_v3_ccu_resets[] = {
+static const struct ccu_reset_map sun8i_v3_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_MBUS] = { 0x0fc, BIT(31) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
index 0975ac58949f..d561c15f5122 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
@@ -177,7 +177,7 @@ static struct clk_hw_onecell_data sun9i_a80_de_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun9i_a80_de_resets[] = {
+static const struct ccu_reset_map sun9i_a80_de_resets[] = {
[RST_FE0] = { 0x0c, BIT(0) },
[RST_FE1] = { 0x0c, BIT(1) },
[RST_FE2] = { 0x0c, BIT(2) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
index e5527c8cc64f..9e2b8d47fc54 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
@@ -68,7 +68,7 @@ static struct clk_hw_onecell_data sun9i_a80_usb_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun9i_a80_usb_resets[] = {
+static const struct ccu_reset_map sun9i_a80_usb_resets[] = {
[RST_USB0_HCI] = { 0x0, BIT(17) },
[RST_USB1_HCI] = { 0x0, BIT(18) },
[RST_USB2_HCI] = { 0x0, BIT(19) },
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
index 756dd8fca6b0..5da9a16b4ec7 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
@@ -1108,7 +1108,7 @@ static struct clk_hw_onecell_data sun9i_a80_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map sun9i_a80_ccu_resets[] = {
+static const struct ccu_reset_map sun9i_a80_ccu_resets[] = {
/* AHB0 reset controls */
[RST_BUS_FD] = { 0x5a0, BIT(0) },
[RST_BUS_VE] = { 0x5a0, BIT(1) },
diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
index 52f1a04269f8..fb37c0fc4fde 100644
--- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
+++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
@@ -477,7 +477,7 @@ static struct clk_hw_onecell_data suniv_hw_clks = {
.num = CLK_NUMBER,
};
-static struct ccu_reset_map suniv_ccu_resets[] = {
+static const struct ccu_reset_map suniv_ccu_resets[] = {
[RST_USB_PHY0] = { 0x0cc, BIT(0) },
[RST_BUS_DMA] = { 0x2c0, BIT(6) },
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 329734f8cf42..dd330426a6e5 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -50,7 +50,7 @@ struct sunxi_ccu_desc {
struct clk_hw_onecell_data *hw_clks;
- struct ccu_reset_map *resets;
+ const struct ccu_reset_map *resets;
unsigned long num_resets;
};
diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h
index e9b973cae4af..941276a8ec2e 100644
--- a/drivers/clk/sunxi-ng/ccu_reset.h
+++ b/drivers/clk/sunxi-ng/ccu_reset.h
@@ -17,7 +17,7 @@ struct ccu_reset_map {
struct ccu_reset {
void __iomem *base;
- struct ccu_reset_map *reset_map;
+ const struct ccu_reset_map *reset_map;
spinlock_t *lock;
struct reset_controller_dev rcdev;
diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c
index 7bfba0afd778..b2323cb8eddc 100644
--- a/drivers/clk/tegra/clk-bpmp.c
+++ b/drivers/clk/tegra/clk-bpmp.c
@@ -174,7 +174,7 @@ static int tegra_bpmp_clk_determine_rate(struct clk_hw *hw,
unsigned long rate;
int err;
- rate = min(max(rate_req->rate, rate_req->min_rate), rate_req->max_rate);
+ rate = clamp(rate_req->rate, rate_req->min_rate, rate_req->max_rate);
memset(&request, 0, sizeof(request));
request.rate = min_t(u64, rate, S64_MAX);
diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
index 7a0269bdfbb3..b2233d3ff9a9 100644
--- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
+++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/math64.h>
#include <linux/module.h>
+#include <linux/overflow.h>
#include <linux/err.h>
#include <linux/iopoll.h>
@@ -121,26 +122,24 @@ enum clk_wzrd_int_clks {
/**
* struct clk_wzrd - Clock wizard private data structure
*
- * @clk_data: Clock data
* @nb: Notifier block
* @base: Memory base
* @clk_in1: Handle to input clock 'clk_in1'
* @axi_clk: Handle to input clock 's_axi_aclk'
* @clks_internal: Internal clocks
- * @clkout: Output clocks
* @speed_grade: Speed grade of the device
* @suspended: Flag indicating power state of the device
+ * @clk_data: Output clock data
*/
struct clk_wzrd {
- struct clk_onecell_data clk_data;
struct notifier_block nb;
void __iomem *base;
struct clk *clk_in1;
struct clk *axi_clk;
- struct clk *clks_internal[wzrd_clk_int_max];
- struct clk *clkout[WZRD_NUM_OUTPUTS];
+ struct clk_hw *clks_internal[wzrd_clk_int_max];
unsigned int speed_grade;
bool suspended;
+ struct clk_hw_onecell_data clk_data;
};
/**
@@ -765,7 +764,7 @@ static const struct clk_ops clk_wzrd_clk_divider_ops_f = {
.recalc_rate = clk_wzrd_recalc_ratef,
};
-static struct clk *clk_wzrd_register_divf(struct device *dev,
+static struct clk_hw *clk_wzrd_register_divf(struct device *dev,
const char *name,
const char *parent_name,
unsigned long flags,
@@ -805,10 +804,10 @@ static struct clk *clk_wzrd_register_divf(struct device *dev,
if (ret)
return ERR_PTR(ret);
- return hw->clk;
+ return hw;
}
-static struct clk *clk_wzrd_ver_register_divider(struct device *dev,
+static struct clk_hw *clk_wzrd_ver_register_divider(struct device *dev,
const char *name,
const char *parent_name,
unsigned long flags,
@@ -852,10 +851,10 @@ static struct clk *clk_wzrd_ver_register_divider(struct device *dev,
if (ret)
return ERR_PTR(ret);
- return hw->clk;
+ return hw;
}
-static struct clk *clk_wzrd_register_divider(struct device *dev,
+static struct clk_hw *clk_wzrd_register_divider(struct device *dev,
const char *name,
const char *parent_name,
unsigned long flags,
@@ -898,7 +897,7 @@ static struct clk *clk_wzrd_register_divider(struct device *dev,
if (ret)
return ERR_PTR(ret);
- return hw->clk;
+ return hw;
}
static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event,
@@ -963,81 +962,30 @@ static const struct versal_clk_data versal_data = {
.is_versal = true,
};
-static int clk_wzrd_probe(struct platform_device *pdev)
+static int clk_wzrd_register_output_clocks(struct device *dev, int nr_outputs)
{
const char *clkout_name, *clk_name, *clk_mul_name;
+ struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
u32 regl, regh, edge, regld, reghd, edged, div;
- struct device_node *np = pdev->dev.of_node;
const struct versal_clk_data *data;
- struct clk_wzrd *clk_wzrd;
unsigned long flags = 0;
+ bool is_versal = false;
void __iomem *ctrl_reg;
u32 reg, reg_f, mult;
- bool is_versal = false;
- unsigned long rate;
- int nr_outputs;
- int i, ret;
-
- clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL);
- if (!clk_wzrd)
- return -ENOMEM;
- platform_set_drvdata(pdev, clk_wzrd);
-
- clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(clk_wzrd->base))
- return PTR_ERR(clk_wzrd->base);
-
- ret = of_property_read_u32(np, "xlnx,speed-grade", &clk_wzrd->speed_grade);
- if (!ret) {
- if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) {
- dev_warn(&pdev->dev, "invalid speed grade '%d'\n",
- clk_wzrd->speed_grade);
- clk_wzrd->speed_grade = 0;
- }
- }
-
- clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1");
- if (IS_ERR(clk_wzrd->clk_in1))
- return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->clk_in1),
- "clk_in1 not found\n");
-
- clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
- if (IS_ERR(clk_wzrd->axi_clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->axi_clk),
- "s_axi_aclk not found\n");
- ret = clk_prepare_enable(clk_wzrd->axi_clk);
- if (ret) {
- dev_err(&pdev->dev, "enabling s_axi_aclk failed\n");
- return ret;
- }
- rate = clk_get_rate(clk_wzrd->axi_clk);
- if (rate > WZRD_ACLK_MAX_FREQ) {
- dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n",
- rate);
- ret = -EINVAL;
- goto err_disable_clk;
- }
+ int i;
- data = device_get_match_data(&pdev->dev);
+ data = device_get_match_data(dev);
if (data)
is_versal = data->is_versal;
- ret = of_property_read_u32(np, "xlnx,nr-outputs", &nr_outputs);
- if (ret || nr_outputs > WZRD_NUM_OUTPUTS) {
- ret = -EINVAL;
- goto err_disable_clk;
- }
-
- clkout_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_out0", dev_name(&pdev->dev));
- if (!clkout_name) {
- ret = -ENOMEM;
- goto err_disable_clk;
- }
+ clkout_name = devm_kasprintf(dev, GFP_KERNEL, "%s_out0", dev_name(dev));
+ if (!clkout_name)
+ return -ENOMEM;
if (is_versal) {
if (nr_outputs == 1) {
- clk_wzrd->clkout[0] = clk_wzrd_ver_register_divider
- (&pdev->dev, clkout_name,
+ clk_wzrd->clk_data.hws[0] = clk_wzrd_ver_register_divider
+ (dev, clkout_name,
__clk_get_name(clk_wzrd->clk_in1), 0,
clk_wzrd->base, WZRD_CLK_CFG_REG(is_versal, 3),
WZRD_CLKOUT_DIVIDE_SHIFT,
@@ -1045,7 +993,7 @@ static int clk_wzrd_probe(struct platform_device *pdev)
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
DIV_ALL, &clkwzrd_lock);
- goto out;
+ return 0;
}
/* register multiplier */
edge = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0)) &
@@ -1069,8 +1017,8 @@ static int clk_wzrd_probe(struct platform_device *pdev)
div = 64;
} else {
if (nr_outputs == 1) {
- clk_wzrd->clkout[0] = clk_wzrd_register_divider
- (&pdev->dev, clkout_name,
+ clk_wzrd->clk_data.hws[0] = clk_wzrd_register_divider
+ (dev, clkout_name,
__clk_get_name(clk_wzrd->clk_in1), 0,
clk_wzrd->base, WZRD_CLK_CFG_REG(is_versal, 3),
WZRD_CLKOUT_DIVIDE_SHIFT,
@@ -1078,7 +1026,7 @@ static int clk_wzrd_probe(struct platform_device *pdev)
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
DIV_ALL, &clkwzrd_lock);
- goto out;
+ return 0;
}
reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0));
reg_f = reg & WZRD_CLKFBOUT_FRAC_MASK;
@@ -1089,26 +1037,21 @@ static int clk_wzrd_probe(struct platform_device *pdev)
mult = (reg * 1000) + reg_f;
div = 1000;
}
- clk_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_mul", dev_name(&pdev->dev));
- if (!clk_name) {
- ret = -ENOMEM;
- goto err_disable_clk;
- }
- clk_wzrd->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor
- (&pdev->dev, clk_name,
+ clk_name = devm_kasprintf(dev, GFP_KERNEL, "%s_mul", dev_name(dev));
+ if (!clk_name)
+ return -ENOMEM;
+ clk_wzrd->clks_internal[wzrd_clk_mul] = devm_clk_hw_register_fixed_factor
+ (dev, clk_name,
__clk_get_name(clk_wzrd->clk_in1),
0, mult, div);
if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) {
- dev_err(&pdev->dev, "unable to register fixed-factor clock\n");
- ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]);
- goto err_disable_clk;
+ dev_err(dev, "unable to register fixed-factor clock\n");
+ return PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]);
}
- clk_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev));
- if (!clk_name) {
- ret = -ENOMEM;
- goto err_rm_int_clk;
- }
+ clk_name = devm_kasprintf(dev, GFP_KERNEL, "%s_mul_div", dev_name(dev));
+ if (!clk_name)
+ return -ENOMEM;
if (is_versal) {
edged = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 20)) &
@@ -1121,36 +1064,31 @@ static int clk_wzrd_probe(struct platform_device *pdev)
if (!div)
div = 1;
- clk_mul_name = __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]);
+ clk_mul_name = clk_hw_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]);
clk_wzrd->clks_internal[wzrd_clk_mul_div] =
- clk_register_fixed_factor(&pdev->dev, clk_name,
- clk_mul_name, 0, 1, div);
+ devm_clk_hw_register_fixed_factor(dev, clk_name, clk_mul_name, 0, 1, div);
} else {
ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0);
- clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider
- (&pdev->dev, clk_name,
- __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]),
+ clk_wzrd->clks_internal[wzrd_clk_mul_div] = devm_clk_hw_register_divider
+ (dev, clk_name,
+ clk_hw_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]),
flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ALLOW_ZERO, &clkwzrd_lock);
}
if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) {
- dev_err(&pdev->dev, "unable to register divider clock\n");
- ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]);
- goto err_rm_int_clk;
+ dev_err(dev, "unable to register divider clock\n");
+ return PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]);
}
/* register div per output */
for (i = nr_outputs - 1; i >= 0 ; i--) {
- clkout_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
- "%s_out%d", dev_name(&pdev->dev), i);
- if (!clkout_name) {
- ret = -ENOMEM;
- goto err_rm_int_clk;
- }
+ clkout_name = devm_kasprintf(dev, GFP_KERNEL, "%s_out%d", dev_name(dev), i);
+ if (!clkout_name)
+ return -ENOMEM;
if (is_versal) {
- clk_wzrd->clkout[i] = clk_wzrd_ver_register_divider
- (&pdev->dev,
+ clk_wzrd->clk_data.hws[i] = clk_wzrd_ver_register_divider
+ (dev,
clkout_name, clk_name, 0,
clk_wzrd->base,
(WZRD_CLK_CFG_REG(is_versal, 3) + i * 8),
@@ -1161,84 +1099,108 @@ static int clk_wzrd_probe(struct platform_device *pdev)
DIV_O, &clkwzrd_lock);
} else {
if (!i)
- clk_wzrd->clkout[i] = clk_wzrd_register_divf
- (&pdev->dev, clkout_name, clk_name, flags, clk_wzrd->base,
+ clk_wzrd->clk_data.hws[i] = clk_wzrd_register_divf
+ (dev, clkout_name, clk_name, flags, clk_wzrd->base,
(WZRD_CLK_CFG_REG(is_versal, 2) + i * 12),
WZRD_CLKOUT_DIVIDE_SHIFT,
WZRD_CLKOUT_DIVIDE_WIDTH,
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
DIV_O, &clkwzrd_lock);
else
- clk_wzrd->clkout[i] = clk_wzrd_register_divider
- (&pdev->dev, clkout_name, clk_name, 0, clk_wzrd->base,
+ clk_wzrd->clk_data.hws[i] = clk_wzrd_register_divider
+ (dev, clkout_name, clk_name, 0, clk_wzrd->base,
(WZRD_CLK_CFG_REG(is_versal, 2) + i * 12),
WZRD_CLKOUT_DIVIDE_SHIFT,
WZRD_CLKOUT_DIVIDE_WIDTH,
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
DIV_O, &clkwzrd_lock);
}
- if (IS_ERR(clk_wzrd->clkout[i])) {
- int j;
-
- for (j = i + 1; j < nr_outputs; j++)
- clk_unregister(clk_wzrd->clkout[j]);
- dev_err(&pdev->dev,
- "unable to register divider clock\n");
- ret = PTR_ERR(clk_wzrd->clkout[i]);
- goto err_rm_int_clks;
+ if (IS_ERR(clk_wzrd->clk_data.hws[i])) {
+ dev_err(dev, "unable to register divider clock\n");
+ return PTR_ERR(clk_wzrd->clk_data.hws[i]);
}
}
-out:
- clk_wzrd->clk_data.clks = clk_wzrd->clkout;
- clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout);
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data);
+ return 0;
+}
- if (clk_wzrd->speed_grade) {
- clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier;
+static int clk_wzrd_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct clk_wzrd *clk_wzrd;
+ unsigned long rate;
+ int nr_outputs;
+ int ret;
- ret = clk_notifier_register(clk_wzrd->clk_in1,
- &clk_wzrd->nb);
- if (ret)
- dev_warn(&pdev->dev,
- "unable to register clock notifier\n");
+ ret = of_property_read_u32(np, "xlnx,nr-outputs", &nr_outputs);
+ if (ret || nr_outputs > WZRD_NUM_OUTPUTS)
+ return -EINVAL;
- ret = clk_notifier_register(clk_wzrd->axi_clk, &clk_wzrd->nb);
- if (ret)
- dev_warn(&pdev->dev,
- "unable to register clock notifier\n");
- }
+ clk_wzrd = devm_kzalloc(&pdev->dev, struct_size(clk_wzrd, clk_data.hws, nr_outputs),
+ GFP_KERNEL);
+ if (!clk_wzrd)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, clk_wzrd);
- return 0;
+ clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(clk_wzrd->base))
+ return PTR_ERR(clk_wzrd->base);
-err_rm_int_clks:
- clk_unregister(clk_wzrd->clks_internal[1]);
-err_rm_int_clk:
- clk_unregister(clk_wzrd->clks_internal[0]);
-err_disable_clk:
- clk_disable_unprepare(clk_wzrd->axi_clk);
+ clk_wzrd->axi_clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
+ if (IS_ERR(clk_wzrd->axi_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->axi_clk),
+ "s_axi_aclk not found\n");
+ rate = clk_get_rate(clk_wzrd->axi_clk);
+ if (rate > WZRD_ACLK_MAX_FREQ) {
+ dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n", rate);
+ return -EINVAL;
+ }
- return ret;
-}
+ if (!of_property_present(np, "xlnx,static-config")) {
+ ret = of_property_read_u32(np, "xlnx,speed-grade", &clk_wzrd->speed_grade);
+ if (!ret) {
+ if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) {
+ dev_warn(&pdev->dev, "invalid speed grade '%d'\n",
+ clk_wzrd->speed_grade);
+ clk_wzrd->speed_grade = 0;
+ }
+ }
-static void clk_wzrd_remove(struct platform_device *pdev)
-{
- int i;
- struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev);
+ clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1");
+ if (IS_ERR(clk_wzrd->clk_in1))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->clk_in1),
+ "clk_in1 not found\n");
+
+ ret = clk_wzrd_register_output_clocks(&pdev->dev, nr_outputs);
+ if (ret)
+ return ret;
+
+ clk_wzrd->clk_data.num = nr_outputs;
+ ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
+ &clk_wzrd->clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to register clock provider\n");
+ return ret;
+ }
- of_clk_del_provider(pdev->dev.of_node);
+ if (clk_wzrd->speed_grade) {
+ clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier;
- for (i = 0; i < WZRD_NUM_OUTPUTS; i++)
- clk_unregister(clk_wzrd->clkout[i]);
- for (i = 0; i < wzrd_clk_int_max; i++)
- clk_unregister(clk_wzrd->clks_internal[i]);
+ ret = devm_clk_notifier_register(&pdev->dev, clk_wzrd->clk_in1,
+ &clk_wzrd->nb);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "unable to register clock notifier\n");
- if (clk_wzrd->speed_grade) {
- clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb);
- clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb);
+ ret = devm_clk_notifier_register(&pdev->dev, clk_wzrd->axi_clk,
+ &clk_wzrd->nb);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "unable to register clock notifier\n");
+ }
}
- clk_disable_unprepare(clk_wzrd->axi_clk);
+ return 0;
}
static const struct of_device_id clk_wzrd_ids[] = {
@@ -1257,7 +1219,6 @@ static struct platform_driver clk_wzrd_driver = {
.pm = &clk_wzrd_dev_pm_ops,
},
.probe = clk_wzrd_probe,
- .remove = clk_wzrd_remove,
};
module_platform_driver(clk_wzrd_driver);
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 95dd4660b5b6..487c85259967 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -400,7 +400,8 @@ config ARM_GT_INITIAL_PRESCALER_VAL
This affects CPU_FREQ max delta from the initial frequency.
config ARM_TIMER_SP804
- bool "Support for Dual Timer SP804 module" if COMPILE_TEST
+ bool "Support for Dual Timer SP804 module"
+ depends on ARM || ARM64 || COMPILE_TEST
depends on GENERIC_SCHED_CLOCK && HAVE_CLK
select CLKSRC_MMIO
select TIMER_OF if OF
@@ -753,4 +754,13 @@ config EP93XX_TIMER
Enables support for the Cirrus Logic timer block
EP93XX.
+config RALINK_TIMER
+ bool "Ralink System Tick Counter"
+ depends on SOC_RT305X || SOC_MT7620 || COMPILE_TEST
+ select CLKSRC_MMIO
+ select TIMER_OF
+ help
+ Enables support for system tick counter present on
+ Ralink SoCs RT3352 and MT7620.
+
endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 22743785299e..43ef16a4efa6 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -91,3 +91,4 @@ obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o
obj-$(CONFIG_GXP_TIMER) += timer-gxp.o
obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o
obj-$(CONFIG_EP93XX_TIMER) += timer-ep93xx.o
+obj-$(CONFIG_RALINK_TIMER) += timer-ralink.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 03733101e231..808f259781fd 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1179,8 +1179,6 @@ static void arch_timer_stop(struct clock_event_device *clk)
disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]);
if (arch_timer_has_nonsecure_ppi())
disable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]);
-
- clk->set_state_shutdown(clk);
}
static int arch_timer_dying_cpu(unsigned int cpu)
@@ -1430,7 +1428,7 @@ static int __init arch_timer_of_init(struct device_node *np)
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
- has_names = of_property_read_bool(np, "interrupt-names");
+ has_names = of_property_present(np, "interrupt-names");
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) {
if (has_names)
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index a05cfaab5f84..2d86bbc2764a 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -195,7 +195,6 @@ static int gt_dying_cpu(unsigned int cpu)
{
struct clock_event_device *clk = this_cpu_ptr(gt_evt);
- gt_clockevent_shutdown(clk);
disable_percpu_irq(clk->irq);
return 0;
}
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index f5f24a95ee82..3a55ae5fe225 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -68,25 +68,6 @@ static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val,
writel_relaxed(val, timer->base + offs);
}
-static void apbt_disable_int(struct dw_apb_timer *timer)
-{
- u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
-
- ctrl |= APBTMR_CONTROL_INT;
- apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
-}
-
-/**
- * dw_apb_clockevent_pause() - stop the clock_event_device from running
- *
- * @dw_ced: The APB clock to stop generating events.
- */
-void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)
-{
- disable_irq(dw_ced->timer.irq);
- apbt_disable_int(&dw_ced->timer);
-}
-
static void apbt_eoi(struct dw_apb_timer *timer)
{
apbt_readl_relaxed(timer, APBTMR_N_EOI);
@@ -285,26 +266,6 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
}
/**
- * dw_apb_clockevent_resume() - resume a clock that has been paused.
- *
- * @dw_ced: The APB clock to resume.
- */
-void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced)
-{
- enable_irq(dw_ced->timer.irq);
-}
-
-/**
- * dw_apb_clockevent_stop() - stop the clock_event_device and release the IRQ.
- *
- * @dw_ced: The APB clock to stop generating the events.
- */
-void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced)
-{
- free_irq(dw_ced->timer.irq, &dw_ced->ced);
-}
-
-/**
* dw_apb_clockevent_register() - register the clock with the generic layer
*
* @dw_ced: The APB clock to register as a clock_event_device.
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index ef8cb1b71be4..e6a02e351d77 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -496,7 +496,6 @@ static int exynos4_mct_dying_cpu(unsigned int cpu)
per_cpu_ptr(&percpu_mct_tick, cpu);
struct clock_event_device *evt = &mevt->evt;
- evt->set_state_shutdown(evt);
if (mct_int_type == MCT_INT_SPI) {
if (evt->irq != -1)
disable_irq_nosync(evt->irq);
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index 110347707ff9..7907b740497a 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -166,6 +166,37 @@ static u64 gic_hpt_read(struct clocksource *cs)
return gic_read_count();
}
+static u64 gic_hpt_read_multicluster(struct clocksource *cs)
+{
+ unsigned int hi, hi2, lo;
+ u64 count;
+
+ mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
+
+ if (mips_cm_is64) {
+ count = read_gic_redir_counter();
+ goto out;
+ }
+
+ hi = read_gic_redir_counter_32h();
+ while (true) {
+ lo = read_gic_redir_counter_32l();
+
+ /* If hi didn't change then lo didn't wrap & we're done */
+ hi2 = read_gic_redir_counter_32h();
+ if (hi2 == hi)
+ break;
+
+ /* Otherwise, repeat with the latest hi value */
+ hi = hi2;
+ }
+
+ count = (((u64)hi) << 32) + lo;
+out:
+ mips_cm_unlock_other();
+ return count;
+}
+
static struct clocksource gic_clocksource = {
.name = "GIC",
.read = gic_hpt_read,
@@ -203,6 +234,11 @@ static int __init __gic_clocksource_init(void)
gic_clocksource.rating = 200;
gic_clocksource.rating += clamp(gic_frequency / 10000000, 0, 99);
+ if (mips_cps_multicluster_cpus()) {
+ gic_clocksource.read = &gic_hpt_read_multicluster;
+ gic_clocksource.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
+ }
+
ret = clocksource_register_hz(&gic_clocksource, gic_frequency);
if (ret < 0)
pr_warn("Unable to register clocksource\n");
@@ -261,7 +297,8 @@ static int __init gic_clocksource_of_init(struct device_node *node)
* stable CPU frequency or on the platforms with CM3 and CPU frequency
* change performed by the CPC core clocks divider.
*/
- if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) {
+ if ((mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) &&
+ !mips_cps_multicluster_cpus()) {
sched_clock_register(mips_cm_is64 ?
gic_read_count_64 : gic_read_count_2x32,
gic_count_width, gic_frequency);
diff --git a/drivers/clocksource/timer-armada-370-xp.c b/drivers/clocksource/timer-armada-370-xp.c
index 6ec565d6939a..54284c1c0651 100644
--- a/drivers/clocksource/timer-armada-370-xp.c
+++ b/drivers/clocksource/timer-armada-370-xp.c
@@ -201,7 +201,6 @@ static int armada_370_xp_timer_dying_cpu(unsigned int cpu)
{
struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu);
- evt->set_state_shutdown(evt);
disable_percpu_irq(evt->irq);
return 0;
}
diff --git a/drivers/clocksource/timer-gxp.c b/drivers/clocksource/timer-gxp.c
index 57aa2e2cce53..48a73c101eb8 100644
--- a/drivers/clocksource/timer-gxp.c
+++ b/drivers/clocksource/timer-gxp.c
@@ -85,7 +85,7 @@ static int __init gxp_timer_init(struct device_node *node)
clk = of_clk_get(node, 0);
if (IS_ERR(clk)) {
- ret = (int)PTR_ERR(clk);
+ ret = PTR_ERR(clk);
pr_err("%pOFn clock not found: %d\n", node, ret);
goto err_free;
}
diff --git a/drivers/clocksource/timer-qcom.c b/drivers/clocksource/timer-qcom.c
index eac4c95c6127..ddb1debe6a6b 100644
--- a/drivers/clocksource/timer-qcom.c
+++ b/drivers/clocksource/timer-qcom.c
@@ -130,7 +130,6 @@ static int msm_local_timer_dying_cpu(unsigned int cpu)
{
struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu);
- evt->set_state_shutdown(evt);
disable_percpu_irq(evt->irq);
return 0;
}
diff --git a/arch/mips/ralink/cevt-rt3352.c b/drivers/clocksource/timer-ralink.c
index 269d4877d120..6ecdb4228f76 100644
--- a/arch/mips/ralink/cevt-rt3352.c
+++ b/drivers/clocksource/timer-ralink.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
+ * Ralink System Tick Counter driver present on RT3352 and MT7620 SoCs.
*
* Copyright (C) 2013 by John Crispin <john@phrozen.org>
*/
@@ -16,8 +15,6 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>
-#include <asm/mach-ralink/ralink_regs.h>
-
#define SYSTICK_FREQ (50 * 1000)
#define SYSTICK_CONFIG 0x00
@@ -40,7 +37,7 @@ static int systick_set_oneshot(struct clock_event_device *evt);
static int systick_shutdown(struct clock_event_device *evt);
static int systick_next_event(unsigned long delta,
- struct clock_event_device *evt)
+ struct clock_event_device *evt)
{
struct systick_device *sdev;
u32 count;
@@ -60,7 +57,7 @@ static void systick_event_handler(struct clock_event_device *dev)
static irqreturn_t systick_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *dev = (struct clock_event_device *) dev_id;
+ struct clock_event_device *dev = (struct clock_event_device *)dev_id;
dev->event_handler(dev);
diff --git a/drivers/clocksource/timer-tegra.c b/drivers/clocksource/timer-tegra.c
index e9635c25eef4..35b6ce9deffa 100644
--- a/drivers/clocksource/timer-tegra.c
+++ b/drivers/clocksource/timer-tegra.c
@@ -158,7 +158,6 @@ static int tegra_timer_stop(unsigned int cpu)
{
struct timer_of *to = per_cpu_ptr(&tegra_to, cpu);
- to->clkevt.set_state_shutdown(&to->clkevt);
disable_irq_nosync(to->clkevt.irq);
return 0;
diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c
index c2dcd8d68e45..985a6d08512b 100644
--- a/drivers/clocksource/timer-ti-dm-systimer.c
+++ b/drivers/clocksource/timer-ti-dm-systimer.c
@@ -202,10 +202,10 @@ static bool __init dmtimer_is_preferred(struct device_node *np)
/* Secure gptimer12 is always clocked with a fixed source */
if (!of_property_read_bool(np, "ti,timer-secure")) {
- if (!of_property_read_bool(np, "assigned-clocks"))
+ if (!of_property_present(np, "assigned-clocks"))
return false;
- if (!of_property_read_bool(np, "assigned-clock-parents"))
+ if (!of_property_present(np, "assigned-clock-parents"))
return false;
}
@@ -686,9 +686,9 @@ subsys_initcall(dmtimer_percpu_timer_startup);
static int __init dmtimer_percpu_quirk_init(struct device_node *np, u32 pa)
{
- struct device_node *arm_timer;
+ struct device_node *arm_timer __free(device_node) =
+ of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
- arm_timer = of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
if (of_device_is_available(arm_timer)) {
pr_warn_once("ARM architected timer wrap issue i940 detected\n");
return 0;
diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index b7a34b1a975e..3666d94cc8dd 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -1104,8 +1104,12 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
return -ENOMEM;
timer->irq = platform_get_irq(pdev, 0);
- if (timer->irq < 0)
- return timer->irq;
+ if (timer->irq < 0) {
+ if (of_property_read_bool(dev->of_node, "ti,timer-pwm"))
+ dev_info(dev, "Did not find timer interrupt, timer usable in PWM mode only\n");
+ else
+ return timer->irq;
+ }
timer->io_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(timer->io_base))
diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 1b481731df96..b9df9b19d4bd 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -2407,6 +2407,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
start += PAGE_SIZE;
}
+
+#ifdef CONFIG_MMU
+ /*
+ * Leaving behind a partial mapping of a buffer we're about to
+ * drop is unsafe, see remap_pfn_range_notrack().
+ * We need to zap the range here ourselves instead of relying
+ * on the automatic zapping in remap_pfn_range() because we call
+ * remap_pfn_range() in a loop.
+ */
+ if (retval)
+ zap_vma_ptes(vma, vma->vm_start, size);
+#endif
}
if (retval == 0) {
diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c
index 200876f3ec04..6ac4efb5658b 100644
--- a/drivers/counter/ftm-quaddec.c
+++ b/drivers/counter/ftm-quaddec.c
@@ -311,6 +311,7 @@ static const struct of_device_id ftm_quaddec_match[] = {
{ .compatible = "fsl,ftm-quaddec" },
{},
};
+MODULE_DEVICE_TABLE(of, ftm_quaddec_match);
static struct platform_driver ftm_quaddec_driver = {
.driver = {
diff --git a/drivers/counter/intel-qep.c b/drivers/counter/intel-qep.c
index af5942e66f7d..ee2bae27b728 100644
--- a/drivers/counter/intel-qep.c
+++ b/drivers/counter/intel-qep.c
@@ -408,13 +408,9 @@ static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id)
pci_set_master(pci);
- ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
- if (ret)
- return ret;
-
- regs = pcim_iomap_table(pci)[0];
- if (!regs)
- return -ENOMEM;
+ regs = pcim_iomap_region(pci, 0, pci_name(pci));
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
qep->dev = dev;
qep->regs = regs;
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 186e73d6ccb4..87b6ec567b54 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -214,11 +214,17 @@ static int stm32_count_enable_write(struct counter_device *counter,
{
struct stm32_timer_cnt *const priv = counter_priv(counter);
u32 cr1;
+ int ret;
if (enable) {
regmap_read(priv->regmap, TIM_CR1, &cr1);
- if (!(cr1 & TIM_CR1_CEN))
- clk_enable(priv->clk);
+ if (!(cr1 & TIM_CR1_CEN)) {
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(counter->parent, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
+ }
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
TIM_CR1_CEN);
@@ -694,6 +700,7 @@ static int stm32_timer_cnt_probe_encoder(struct device *dev,
}
ret = of_property_read_u32(tnode, "reg", &idx);
+ of_node_put(tnode);
if (ret) {
dev_err(dev, "Can't get index (%d)\n", ret);
return ret;
@@ -816,7 +823,11 @@ static int __maybe_unused stm32_timer_cnt_resume(struct device *dev)
return ret;
if (priv->enabled) {
- clk_enable(priv->clk);
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
/* Restore registers that may have been lost */
regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c
index 675447315caf..b119aeede693 100644
--- a/drivers/counter/ti-ecap-capture.c
+++ b/drivers/counter/ti-ecap-capture.c
@@ -574,8 +574,13 @@ static int ecap_cnt_resume(struct device *dev)
{
struct counter_device *counter_dev = dev_get_drvdata(dev);
struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev);
+ int ret;
- clk_enable(ecap_dev->clk);
+ ret = clk_enable(ecap_dev->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode);
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 2561b215432a..92a83a9bb2e1 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -217,6 +217,20 @@ config CPUFREQ_DT
If in doubt, say N.
+config CPUFREQ_VIRT
+ tristate "Virtual cpufreq driver"
+ depends on GENERIC_ARCH_TOPOLOGY
+ help
+ This adds a virtualized cpufreq driver for guest kernels that
+ read/writes to a MMIO region for a virtualized cpufreq device to
+ communicate with the host. It sends performance requests to the host
+ which gets used as a hint to schedule vCPU threads and select CPU
+ frequency. If a VM does not support a virtualized FIE such as AMUs,
+ it updates the frequency scaling factor by polling host CPU frequency
+ to enable accurate Per-Entity Load Tracking for tasks running in the guest.
+
+ If in doubt, say N.
+
config CPUFREQ_DT_PLATDEV
tristate "Generic DT based cpufreq platdev driver"
depends on OF
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
index 58151ca56695..eb678fa5260a 100644
--- a/drivers/cpufreq/Kconfig.powerpc
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -17,13 +17,6 @@ config CPU_FREQ_CBE_PMI
frequencies. Using PMI, the processor will not only be able to run at
lower speed, but also at lower core voltage.
-config CPU_FREQ_MAPLE
- bool "Support for Maple 970FX Evaluation Board"
- depends on PPC_MAPLE
- help
- This adds support for frequency switching on Maple 970FX
- Evaluation Board and compatible boards (IBM JS2x blades).
-
config CPU_FREQ_PMAC
bool "Support for Apple PowerBooks"
depends on ADB_PMU && PPC32
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0f184031dd12..d35a28dd9463 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o
obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o
obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
+obj-$(CONFIG_CPUFREQ_VIRT) += virtual-cpufreq.o
# Traces
CFLAGS_amd-pstate-trace.o := -I$(src)
@@ -92,7 +93,6 @@ obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
obj-$(CONFIG_CPU_FREQ_CBE) += ppc-cbe-cpufreq.o
ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o
obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o
-obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o
obj-$(CONFIG_QORIQ_CPUFREQ) += qoriq-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 0f04feb6cafa..c9ebacf5c88e 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -73,20 +73,17 @@ static unsigned int acpi_pstate_strict;
static bool boost_state(unsigned int cpu)
{
- u32 lo, hi;
u64 msr;
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
case X86_VENDOR_CENTAUR:
case X86_VENDOR_ZHAOXIN:
- rdmsr_on_cpu(cpu, MSR_IA32_MISC_ENABLE, &lo, &hi);
- msr = lo | ((u64)hi << 32);
+ rdmsrl_on_cpu(cpu, MSR_IA32_MISC_ENABLE, &msr);
return !(msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE);
case X86_VENDOR_HYGON:
case X86_VENDOR_AMD:
- rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
- msr = lo | ((u64)hi << 32);
+ rdmsrl_on_cpu(cpu, MSR_K7_HWCR, &msr);
return !(msr & MSR_K7_HWCR_CPB_DIS);
}
return false;
@@ -1028,7 +1025,7 @@ static struct platform_driver acpi_cpufreq_platdrv = {
.driver = {
.name = "acpi-cpufreq",
},
- .remove_new = acpi_cpufreq_remove,
+ .remove = acpi_cpufreq_remove,
};
static int __init acpi_cpufreq_init(void)
diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c
index f66701514d90..a261d7300951 100644
--- a/drivers/cpufreq/amd-pstate-ut.c
+++ b/drivers/cpufreq/amd-pstate-ut.c
@@ -227,10 +227,10 @@ static void amd_pstate_ut_check_freq(u32 index)
goto skip_test;
}
- if (cpudata->min_freq != policy->min) {
+ if (cpudata->lowest_nonlinear_freq != policy->min) {
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
- pr_err("%s cpu%d cpudata_min_freq=%d policy_min=%d, they should be equal!\n",
- __func__, cpu, cpudata->min_freq, policy->min);
+ pr_err("%s cpu%d cpudata_lowest_nonlinear_freq=%d policy_min=%d, they should be equal!\n",
+ __func__, cpu, cpudata->lowest_nonlinear_freq, policy->min);
goto skip_test;
}
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index b63863f77c67..d7630bab2516 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -233,7 +233,7 @@ static int amd_pstate_get_energy_pref_index(struct amd_cpudata *cpudata)
return index;
}
-static void pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
+static void msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
u32 des_perf, u32 max_perf, bool fast_switch)
{
if (fast_switch)
@@ -243,7 +243,7 @@ static void pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
READ_ONCE(cpudata->cppc_req_cached));
}
-DEFINE_STATIC_CALL(amd_pstate_update_perf, pstate_update_perf);
+DEFINE_STATIC_CALL(amd_pstate_update_perf, msr_update_perf);
static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata,
u32 min_perf, u32 des_perf,
@@ -306,11 +306,17 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
return ret;
}
-static inline int pstate_enable(bool enable)
+static inline int msr_cppc_enable(bool enable)
{
int ret, cpu;
unsigned long logical_proc_id_mask = 0;
+ /*
+ * MSR_AMD_CPPC_ENABLE is write-once, once set it cannot be cleared.
+ */
+ if (!enable)
+ return 0;
+
if (enable == cppc_enabled)
return 0;
@@ -332,7 +338,7 @@ static inline int pstate_enable(bool enable)
return 0;
}
-static int cppc_enable(bool enable)
+static int shmem_cppc_enable(bool enable)
{
int cpu, ret = 0;
struct cppc_perf_ctrls perf_ctrls;
@@ -359,14 +365,14 @@ static int cppc_enable(bool enable)
return ret;
}
-DEFINE_STATIC_CALL(amd_pstate_enable, pstate_enable);
+DEFINE_STATIC_CALL(amd_pstate_cppc_enable, msr_cppc_enable);
-static inline int amd_pstate_enable(bool enable)
+static inline int amd_pstate_cppc_enable(bool enable)
{
- return static_call(amd_pstate_enable)(enable);
+ return static_call(amd_pstate_cppc_enable)(enable);
}
-static int pstate_init_perf(struct amd_cpudata *cpudata)
+static int msr_init_perf(struct amd_cpudata *cpudata)
{
u64 cap1;
@@ -385,7 +391,7 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
return 0;
}
-static int cppc_init_perf(struct amd_cpudata *cpudata)
+static int shmem_init_perf(struct amd_cpudata *cpudata)
{
struct cppc_perf_caps cppc_perf;
@@ -420,14 +426,14 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
return ret;
}
-DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf);
+DEFINE_STATIC_CALL(amd_pstate_init_perf, msr_init_perf);
static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata)
{
return static_call(amd_pstate_init_perf)(cpudata);
}
-static void cppc_update_perf(struct amd_cpudata *cpudata,
+static void shmem_update_perf(struct amd_cpudata *cpudata,
u32 min_perf, u32 des_perf,
u32 max_perf, bool fast_switch)
{
@@ -527,9 +533,28 @@ cpufreq_policy_put:
cpufreq_cpu_put(policy);
}
-static int amd_pstate_verify(struct cpufreq_policy_data *policy)
+static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
{
- cpufreq_verify_within_cpu_limits(policy);
+ /*
+ * Initialize lower frequency limit (i.e.policy->min) with
+ * lowest_nonlinear_frequency which is the most energy efficient
+ * frequency. Override the initial value set by cpufreq core and
+ * amd-pstate qos_requests.
+ */
+ if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
+ struct cpufreq_policy *policy = cpufreq_cpu_get(policy_data->cpu);
+ struct amd_cpudata *cpudata;
+
+ if (!policy)
+ return -EINVAL;
+
+ cpudata = policy->driver_data;
+ policy_data->min = cpudata->lowest_nonlinear_freq;
+ cpufreq_cpu_put(policy);
+ }
+
+ cpufreq_verify_within_cpu_limits(policy_data);
+ pr_debug("policy_max =%d, policy_min=%d\n", policy_data->max, policy_data->min);
return 0;
}
@@ -665,34 +690,12 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
{
struct amd_cpudata *cpudata = policy->driver_data;
- struct cppc_perf_ctrls perf_ctrls;
- u32 highest_perf, nominal_perf, nominal_freq, max_freq;
+ u32 nominal_freq, max_freq;
int ret = 0;
- highest_perf = READ_ONCE(cpudata->highest_perf);
- nominal_perf = READ_ONCE(cpudata->nominal_perf);
nominal_freq = READ_ONCE(cpudata->nominal_freq);
max_freq = READ_ONCE(cpudata->max_freq);
- if (boot_cpu_has(X86_FEATURE_CPPC)) {
- u64 value = READ_ONCE(cpudata->cppc_req_cached);
-
- value &= ~GENMASK_ULL(7, 0);
- value |= on ? highest_perf : nominal_perf;
- WRITE_ONCE(cpudata->cppc_req_cached, value);
-
- wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
- } else {
- perf_ctrls.max_perf = on ? highest_perf : nominal_perf;
- ret = cppc_set_perf(cpudata->cpu, &perf_ctrls);
- if (ret) {
- cpufreq_cpu_release(policy);
- pr_debug("Failed to set max perf on CPU:%d. ret:%d\n",
- cpudata->cpu, ret);
- return ret;
- }
- }
-
if (on)
policy->cpuinfo.max_freq = max_freq;
else if (policy->cpuinfo.max_freq > nominal_freq * 1000)
@@ -847,7 +850,7 @@ static u32 amd_pstate_get_transition_delay_us(unsigned int cpu)
transition_delay_ns = cppc_get_transition_latency(cpu);
if (transition_delay_ns == CPUFREQ_ETERNAL) {
- if (cpu_feature_enabled(X86_FEATURE_FAST_CPPC))
+ if (cpu_feature_enabled(X86_FEATURE_AMD_FAST_CPPC))
return AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY;
else
return AMD_PSTATE_TRANSITION_DELAY;
@@ -1001,7 +1004,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
policy->fast_switch_possible = true;
ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
- FREQ_QOS_MIN, policy->cpuinfo.min_freq);
+ FREQ_QOS_MIN, FREQ_QOS_MIN_DEFAULT_VALUE);
if (ret < 0) {
dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret);
goto free_cpudata1;
@@ -1045,7 +1048,7 @@ static int amd_pstate_cpu_resume(struct cpufreq_policy *policy)
{
int ret;
- ret = amd_pstate_enable(true);
+ ret = amd_pstate_cppc_enable(true);
if (ret)
pr_err("failed to enable amd-pstate during resume, return %d\n", ret);
@@ -1056,7 +1059,7 @@ static int amd_pstate_cpu_suspend(struct cpufreq_policy *policy)
{
int ret;
- ret = amd_pstate_enable(false);
+ ret = amd_pstate_cppc_enable(false);
if (ret)
pr_err("failed to disable amd-pstate during suspend, return %d\n", ret);
@@ -1189,25 +1192,41 @@ static ssize_t show_energy_performance_preference(
static void amd_pstate_driver_cleanup(void)
{
- amd_pstate_enable(false);
+ amd_pstate_cppc_enable(false);
cppc_state = AMD_PSTATE_DISABLE;
current_pstate_driver = NULL;
}
+static int amd_pstate_set_driver(int mode_idx)
+{
+ if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) {
+ cppc_state = mode_idx;
+ if (cppc_state == AMD_PSTATE_DISABLE)
+ pr_info("driver is explicitly disabled\n");
+
+ if (cppc_state == AMD_PSTATE_ACTIVE)
+ current_pstate_driver = &amd_pstate_epp_driver;
+
+ if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED)
+ current_pstate_driver = &amd_pstate_driver;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static int amd_pstate_register_driver(int mode)
{
int ret;
- if (mode == AMD_PSTATE_PASSIVE || mode == AMD_PSTATE_GUIDED)
- current_pstate_driver = &amd_pstate_driver;
- else if (mode == AMD_PSTATE_ACTIVE)
- current_pstate_driver = &amd_pstate_epp_driver;
- else
- return -EINVAL;
+ ret = amd_pstate_set_driver(mode);
+ if (ret)
+ return ret;
cppc_state = mode;
- ret = amd_pstate_enable(true);
+ ret = amd_pstate_cppc_enable(true);
if (ret) {
pr_err("failed to enable cppc during amd-pstate driver registration, return %d\n",
ret);
@@ -1485,6 +1504,8 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
WRITE_ONCE(cpudata->cppc_cap1_cached, value);
}
+ current_pstate_driver->adjust_perf = NULL;
+
return 0;
free_cpudata1:
@@ -1507,26 +1528,13 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
{
struct amd_cpudata *cpudata = policy->driver_data;
- u32 max_perf, min_perf, min_limit_perf, max_limit_perf;
+ u32 max_perf, min_perf;
u64 value;
s16 epp;
- if (cpudata->boost_supported && !policy->boost_enabled)
- max_perf = READ_ONCE(cpudata->nominal_perf);
- else
- max_perf = READ_ONCE(cpudata->highest_perf);
+ max_perf = READ_ONCE(cpudata->highest_perf);
min_perf = READ_ONCE(cpudata->lowest_perf);
- max_limit_perf = div_u64(policy->max * max_perf, policy->cpuinfo.max_freq);
- min_limit_perf = div_u64(policy->min * max_perf, policy->cpuinfo.max_freq);
-
- if (min_limit_perf < min_perf)
- min_limit_perf = min_perf;
-
- if (max_limit_perf < min_limit_perf)
- max_limit_perf = min_limit_perf;
-
- WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
- WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
+ amd_pstate_update_min_max_limit(policy);
max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
cpudata->max_limit_perf);
@@ -1535,7 +1543,7 @@ static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
value = READ_ONCE(cpudata->cppc_req_cached);
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
- min_perf = max_perf;
+ min_perf = min(cpudata->nominal_perf, max_perf);
/* Initial min/max values for CPPC Performance Controls Register */
value &= ~AMD_CPPC_MIN_PERF(~0L);
@@ -1563,12 +1571,6 @@ static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
epp = 0;
- /* Set initial EPP value */
- if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
- value &= ~GENMASK_ULL(31, 24);
- value |= (u64)epp << 24;
- }
-
WRITE_ONCE(cpudata->cppc_req_cached, value);
return amd_pstate_set_epp(cpudata, epp);
}
@@ -1605,7 +1607,7 @@ static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
u64 value, max_perf;
int ret;
- ret = amd_pstate_enable(true);
+ ret = amd_pstate_cppc_enable(true);
if (ret)
pr_err("failed to enable amd pstate during resume, return %d\n", ret);
@@ -1616,8 +1618,9 @@ static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
} else {
perf_ctrls.max_perf = max_perf;
- perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(cpudata->epp_cached);
cppc_set_perf(cpudata->cpu, &perf_ctrls);
+ perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(cpudata->epp_cached);
+ cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
}
}
@@ -1657,9 +1660,11 @@ static void amd_pstate_epp_offline(struct cpufreq_policy *policy)
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
} else {
perf_ctrls.desired_perf = 0;
+ perf_ctrls.min_perf = min_perf;
perf_ctrls.max_perf = min_perf;
- perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(HWP_EPP_BALANCE_POWERSAVE);
cppc_set_perf(cpudata->cpu, &perf_ctrls);
+ perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(HWP_EPP_BALANCE_POWERSAVE);
+ cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
}
mutex_unlock(&amd_pstate_limits_lock);
}
@@ -1679,13 +1684,6 @@ static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy)
return 0;
}
-static int amd_pstate_epp_verify_policy(struct cpufreq_policy_data *policy)
-{
- cpufreq_verify_within_cpu_limits(policy);
- pr_debug("policy_max =%d, policy_min=%d\n", policy->max, policy->min);
- return 0;
-}
-
static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
{
struct amd_cpudata *cpudata = policy->driver_data;
@@ -1699,7 +1697,7 @@ static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
cpudata->suspended = true;
/* disable CPPC in lowlevel firmware */
- ret = amd_pstate_enable(false);
+ ret = amd_pstate_cppc_enable(false);
if (ret)
pr_err("failed to suspend, return %d\n", ret);
@@ -1741,7 +1739,7 @@ static struct cpufreq_driver amd_pstate_driver = {
static struct cpufreq_driver amd_pstate_epp_driver = {
.flags = CPUFREQ_CONST_LOOPS,
- .verify = amd_pstate_epp_verify_policy,
+ .verify = amd_pstate_verify,
.setpolicy = amd_pstate_epp_set_policy,
.init = amd_pstate_epp_cpu_init,
.exit = amd_pstate_epp_cpu_exit,
@@ -1755,26 +1753,7 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
.attr = amd_pstate_epp_attr,
};
-static int __init amd_pstate_set_driver(int mode_idx)
-{
- if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) {
- cppc_state = mode_idx;
- if (cppc_state == AMD_PSTATE_DISABLE)
- pr_info("driver is explicitly disabled\n");
-
- if (cppc_state == AMD_PSTATE_ACTIVE)
- current_pstate_driver = &amd_pstate_epp_driver;
-
- if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED)
- current_pstate_driver = &amd_pstate_driver;
-
- return 0;
- }
-
- return -EINVAL;
-}
-
-/**
+/*
* CPPC function is not supported for family ID 17H with model_ID ranging from 0x10 to 0x2F.
* show the debug message that helps to check if the CPU has CPPC support for loading issue.
*/
@@ -1864,10 +1843,10 @@ static int __init amd_pstate_init(void)
if (cppc_state == AMD_PSTATE_UNDEFINED) {
/* Disable on the following configs by default:
* 1. Undefined platforms
- * 2. Server platforms
+ * 2. Server platforms with CPUs older than Family 0x1A.
*/
if (amd_pstate_acpi_pm_profile_undefined() ||
- amd_pstate_acpi_pm_profile_server()) {
+ (amd_pstate_acpi_pm_profile_server() && boot_cpu_data.x86 < 0x1A)) {
pr_info("driver load is disabled, boot with specific mode to enable this\n");
return -ENODEV;
}
@@ -1875,50 +1854,31 @@ static int __init amd_pstate_init(void)
cppc_state = CONFIG_X86_AMD_PSTATE_DEFAULT_MODE;
}
- switch (cppc_state) {
- case AMD_PSTATE_DISABLE:
+ if (cppc_state == AMD_PSTATE_DISABLE) {
pr_info("driver load is disabled, boot with specific mode to enable this\n");
return -ENODEV;
- case AMD_PSTATE_PASSIVE:
- case AMD_PSTATE_ACTIVE:
- case AMD_PSTATE_GUIDED:
- ret = amd_pstate_set_driver(cppc_state);
- if (ret)
- return ret;
- break;
- default:
- return -EINVAL;
}
/* capability check */
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
pr_debug("AMD CPPC MSR based functionality is supported\n");
- if (cppc_state != AMD_PSTATE_ACTIVE)
- current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
} else {
pr_debug("AMD CPPC shared memory based functionality is supported\n");
- static_call_update(amd_pstate_enable, cppc_enable);
- static_call_update(amd_pstate_init_perf, cppc_init_perf);
- static_call_update(amd_pstate_update_perf, cppc_update_perf);
+ static_call_update(amd_pstate_cppc_enable, shmem_cppc_enable);
+ static_call_update(amd_pstate_init_perf, shmem_init_perf);
+ static_call_update(amd_pstate_update_perf, shmem_update_perf);
}
- if (amd_pstate_prefcore) {
- ret = amd_detect_prefcore(&amd_pstate_prefcore);
- if (ret)
- return ret;
- }
-
- /* enable amd pstate feature */
- ret = amd_pstate_enable(true);
+ ret = amd_pstate_register_driver(cppc_state);
if (ret) {
- pr_err("failed to enable driver mode(%d)\n", cppc_state);
+ pr_err("failed to register with return %d\n", ret);
return ret;
}
- ret = cpufreq_register_driver(current_pstate_driver);
- if (ret) {
- pr_err("failed to register with return %d\n", ret);
- goto disable_driver;
+ if (amd_pstate_prefcore) {
+ ret = amd_detect_prefcore(&amd_pstate_prefcore);
+ if (ret)
+ return ret;
}
dev_root = bus_get_dev_root(&cpu_subsys);
@@ -1935,8 +1895,7 @@ static int __init amd_pstate_init(void)
global_attr_free:
cpufreq_unregister_driver(current_pstate_driver);
-disable_driver:
- amd_pstate_enable(false);
+ amd_pstate_cppc_enable(false);
return ret;
}
device_initcall(amd_pstate_init);
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c
index ea8438550b49..2fd0f6be6fa3 100644
--- a/drivers/cpufreq/brcmstb-avs-cpufreq.c
+++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c
@@ -474,8 +474,8 @@ static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
rc = brcm_avs_get_pmap(priv, NULL);
magic = readl(priv->base + AVS_MBOX_MAGIC);
- return (magic == AVS_FIRMWARE_MAGIC) && ((rc != -ENOTSUPP) ||
- (rc != -EINVAL));
+ return (magic == AVS_FIRMWARE_MAGIC) && (rc != -ENOTSUPP) &&
+ (rc != -EINVAL);
}
static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
@@ -777,7 +777,7 @@ static struct platform_driver brcm_avs_cpufreq_platdrv = {
.of_match_table = brcm_avs_cpufreq_match,
},
.probe = brcm_avs_cpufreq_probe,
- .remove_new = brcm_avs_cpufreq_remove,
+ .remove = brcm_avs_cpufreq_remove,
};
module_platform_driver(brcm_avs_cpufreq_platdrv);
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 2b8708475ac7..bd8f75accfa0 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -36,33 +36,15 @@ static LIST_HEAD(cpu_data_list);
static bool boost_supported;
-struct cppc_workaround_oem_info {
- char oem_id[ACPI_OEM_ID_SIZE + 1];
- char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
- u32 oem_revision;
-};
-
-static struct cppc_workaround_oem_info wa_info[] = {
- {
- .oem_id = "HISI ",
- .oem_table_id = "HIP07 ",
- .oem_revision = 0,
- }, {
- .oem_id = "HISI ",
- .oem_table_id = "HIP08 ",
- .oem_revision = 0,
- }
-};
-
static struct cpufreq_driver cppc_cpufreq_driver;
+#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
static enum {
FIE_UNSET = -1,
FIE_ENABLED,
FIE_DISABLED
} fie_disabled = FIE_UNSET;
-#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
module_param(fie_disabled, int, 0444);
MODULE_PARM_DESC(fie_disabled, "Disable Frequency Invariance Engine (FIE)");
@@ -78,7 +60,6 @@ struct cppc_freq_invariance {
static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv);
static struct kthread_worker *kworker_fie;
-static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu);
static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
struct cppc_perf_fb_ctrs *fb_ctrs_t0,
struct cppc_perf_fb_ctrs *fb_ctrs_t1);
@@ -118,6 +99,9 @@ static void cppc_scale_freq_workfn(struct kthread_work *work)
perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs,
&fb_ctrs);
+ if (!perf)
+ return;
+
cppc_fi->prev_perf_fb_ctrs = fb_ctrs;
perf <<= SCHED_CAPACITY_SHIFT;
@@ -420,6 +404,9 @@ static int cppc_get_cpu_power(struct device *cpu_dev,
struct cppc_cpudata *cpu_data;
policy = cpufreq_cpu_get_raw(cpu_dev->id);
+ if (!policy)
+ return -EINVAL;
+
cpu_data = policy->driver_data;
perf_caps = &cpu_data->perf_caps;
max_cap = arch_scale_cpu_capacity(cpu_dev->id);
@@ -487,6 +474,9 @@ static int cppc_get_cpu_cost(struct device *cpu_dev, unsigned long KHz,
int step;
policy = cpufreq_cpu_get_raw(cpu_dev->id);
+ if (!policy)
+ return -EINVAL;
+
cpu_data = policy->driver_data;
perf_caps = &cpu_data->perf_caps;
max_cap = arch_scale_cpu_capacity(cpu_dev->id);
@@ -724,13 +714,31 @@ static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
delta_delivered = get_delta(fb_ctrs_t1->delivered,
fb_ctrs_t0->delivered);
- /* Check to avoid divide-by zero and invalid delivered_perf */
+ /*
+ * Avoid divide-by zero and unchanged feedback counters.
+ * Leave it for callers to handle.
+ */
if (!delta_reference || !delta_delivered)
- return cpu_data->perf_ctrls.desired_perf;
+ return 0;
return (reference_perf * delta_delivered) / delta_reference;
}
+static int cppc_get_perf_ctrs_sample(int cpu,
+ struct cppc_perf_fb_ctrs *fb_ctrs_t0,
+ struct cppc_perf_fb_ctrs *fb_ctrs_t1)
+{
+ int ret;
+
+ ret = cppc_get_perf_ctrs(cpu, fb_ctrs_t0);
+ if (ret)
+ return ret;
+
+ udelay(2); /* 2usec delay between sampling */
+
+ return cppc_get_perf_ctrs(cpu, fb_ctrs_t1);
+}
+
static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
{
struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
@@ -746,18 +754,32 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
cpufreq_cpu_put(policy);
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
- if (ret)
- return 0;
-
- udelay(2); /* 2usec delay between sampling */
-
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1);
- if (ret)
- return 0;
+ ret = cppc_get_perf_ctrs_sample(cpu, &fb_ctrs_t0, &fb_ctrs_t1);
+ if (ret) {
+ if (ret == -EFAULT)
+ /* Any of the associated CPPC regs is 0. */
+ goto out_invalid_counters;
+ else
+ return 0;
+ }
delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0,
&fb_ctrs_t1);
+ if (!delivered_perf)
+ goto out_invalid_counters;
+
+ return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf);
+
+out_invalid_counters:
+ /*
+ * Feedback counters could be unchanged or 0 when a cpu enters a
+ * low-power idle state, e.g. clock-gated or power-gated.
+ * Use desired perf for reflecting frequency. Get the latest register
+ * value first as some platforms may update the actual delivered perf
+ * there; if failed, resort to the cached desired perf.
+ */
+ if (cppc_get_desired_perf(cpu, &delivered_perf))
+ delivered_perf = cpu_data->perf_ctrls.desired_perf;
return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf);
}
@@ -812,57 +834,6 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
.name = "cppc_cpufreq",
};
-/*
- * HISI platform does not support delivered performance counter and
- * reference performance counter. It can calculate the performance using the
- * platform specific mechanism. We reuse the desired performance register to
- * store the real performance calculated by the platform.
- */
-static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu)
-{
- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
- struct cppc_cpudata *cpu_data;
- u64 desired_perf;
- int ret;
-
- if (!policy)
- return -ENODEV;
-
- cpu_data = policy->driver_data;
-
- cpufreq_cpu_put(policy);
-
- ret = cppc_get_desired_perf(cpu, &desired_perf);
- if (ret < 0)
- return -EIO;
-
- return cppc_perf_to_khz(&cpu_data->perf_caps, desired_perf);
-}
-
-static void cppc_check_hisi_workaround(void)
-{
- struct acpi_table_header *tbl;
- acpi_status status = AE_OK;
- int i;
-
- status = acpi_get_table(ACPI_SIG_PCCT, 0, &tbl);
- if (ACPI_FAILURE(status) || !tbl)
- return;
-
- for (i = 0; i < ARRAY_SIZE(wa_info); i++) {
- if (!memcmp(wa_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) &&
- !memcmp(wa_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
- wa_info[i].oem_revision == tbl->oem_revision) {
- /* Overwrite the get() callback */
- cppc_cpufreq_driver.get = hisi_cppc_cpufreq_get_rate;
- fie_disabled = FIE_DISABLED;
- break;
- }
- }
-
- acpi_put_table(tbl);
-}
-
static int __init cppc_cpufreq_init(void)
{
int ret;
@@ -870,7 +841,6 @@ static int __init cppc_cpufreq_init(void)
if (!acpi_cpc_valid())
return -ENODEV;
- cppc_check_hisi_workaround();
cppc_freq_invariance_init();
populate_efficiency_class();
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 18942bfe9c95..2a3e8bd317c9 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -103,6 +103,7 @@ static const struct of_device_id allowlist[] __initconst = {
* platforms using "operating-points-v2" property.
*/
static const struct of_device_id blocklist[] __initconst = {
+ { .compatible = "allwinner,sun50i-a100" },
{ .compatible = "allwinner,sun50i-h6", },
{ .compatible = "allwinner,sun50i-h616", },
{ .compatible = "allwinner,sun50i-h618", },
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 983443396f8f..3a7c3372bda7 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -345,7 +345,7 @@ static struct platform_driver dt_cpufreq_platdrv = {
.name = "cpufreq-dt",
},
.probe = dt_cpufreq_probe,
- .remove_new = dt_cpufreq_remove,
+ .remove = dt_cpufreq_remove,
};
module_platform_driver(dt_cpufreq_platdrv);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index f98c9438760c..1a4cae54a01b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1520,7 +1520,7 @@ static int cpufreq_online(unsigned int cpu)
* frequency for longer duration. Hence, a BUG_ON().
*/
BUG_ON(ret);
- pr_info("%s: CPU%d: Running at unlisted initial frequency: %u KHz, changing to: %u KHz\n",
+ pr_info("%s: CPU%d: Running at unlisted initial frequency: %u kHz, changing to: %u kHz\n",
__func__, policy->cpu, old_freq, policy->cur);
}
}
diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c
index 7d2754411d8c..8736be3a06ce 100644
--- a/drivers/cpufreq/davinci-cpufreq.c
+++ b/drivers/cpufreq/davinci-cpufreq.c
@@ -145,7 +145,7 @@ static struct platform_driver davinci_cpufreq_driver = {
.driver = {
.name = "cpufreq-davinci",
},
- .remove_new = __exit_p(davinci_cpufreq_remove),
+ .remove = __exit_p(davinci_cpufreq_remove),
};
int __init davinci_cpufreq_init(void)
diff --git a/drivers/cpufreq/imx-cpufreq-dt.c b/drivers/cpufreq/imx-cpufreq-dt.c
index 577bb9e2f112..1492c92ffc1a 100644
--- a/drivers/cpufreq/imx-cpufreq-dt.c
+++ b/drivers/cpufreq/imx-cpufreq-dt.c
@@ -183,7 +183,7 @@ static void imx_cpufreq_dt_remove(struct platform_device *pdev)
static struct platform_driver imx_cpufreq_dt_driver = {
.probe = imx_cpufreq_dt_probe,
- .remove_new = imx_cpufreq_dt_remove,
+ .remove = imx_cpufreq_dt_remove,
.driver = {
.name = "imx-cpufreq-dt",
},
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index c20d3ecc5a81..f3c99f378ad6 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -522,7 +522,7 @@ static struct platform_driver imx6q_cpufreq_platdrv = {
.name = "imx6q-cpufreq",
},
.probe = imx6q_cpufreq_probe,
- .remove_new = imx6q_cpufreq_remove,
+ .remove = imx6q_cpufreq_remove,
};
module_platform_driver(imx6q_cpufreq_platdrv);
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index b0018f371ea3..b8e2396a708a 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1028,26 +1028,29 @@ static void hybrid_update_cpu_capacity_scaling(void)
}
}
-static void __hybrid_init_cpu_capacity_scaling(void)
+static void __hybrid_refresh_cpu_capacity_scaling(void)
{
hybrid_max_perf_cpu = NULL;
hybrid_update_cpu_capacity_scaling();
}
-static void hybrid_init_cpu_capacity_scaling(void)
+static void hybrid_refresh_cpu_capacity_scaling(void)
{
- bool disable_itmt = false;
+ guard(mutex)(&hybrid_capacity_lock);
- mutex_lock(&hybrid_capacity_lock);
+ __hybrid_refresh_cpu_capacity_scaling();
+}
+static void hybrid_init_cpu_capacity_scaling(bool refresh)
+{
/*
* If hybrid_max_perf_cpu is set at this point, the hybrid CPU capacity
* scaling has been enabled already and the driver is just changing the
* operation mode.
*/
- if (hybrid_max_perf_cpu) {
- __hybrid_init_cpu_capacity_scaling();
- goto unlock;
+ if (refresh) {
+ hybrid_refresh_cpu_capacity_scaling();
+ return;
}
/*
@@ -1056,19 +1059,25 @@ static void hybrid_init_cpu_capacity_scaling(void)
* do not do that when SMT is in use.
*/
if (hwp_is_hybrid && !sched_smt_active() && arch_enable_hybrid_capacity_scale()) {
- __hybrid_init_cpu_capacity_scaling();
- disable_itmt = true;
+ hybrid_refresh_cpu_capacity_scaling();
+ /*
+ * Disabling ITMT causes sched domains to be rebuilt to disable asym
+ * packing and enable asym capacity.
+ */
+ sched_clear_itmt_support();
}
+}
-unlock:
- mutex_unlock(&hybrid_capacity_lock);
+static bool hybrid_clear_max_perf_cpu(void)
+{
+ bool ret;
- /*
- * Disabling ITMT causes sched domains to be rebuilt to disable asym
- * packing and enable asym capacity.
- */
- if (disable_itmt)
- sched_clear_itmt_support();
+ guard(mutex)(&hybrid_capacity_lock);
+
+ ret = !!hybrid_max_perf_cpu;
+ hybrid_max_perf_cpu = NULL;
+
+ return ret;
}
static void __intel_pstate_get_hwp_cap(struct cpudata *cpu)
@@ -1392,7 +1401,7 @@ static void intel_pstate_update_limits_for_all(void)
mutex_lock(&hybrid_capacity_lock);
if (hybrid_max_perf_cpu)
- __hybrid_init_cpu_capacity_scaling();
+ __hybrid_refresh_cpu_capacity_scaling();
mutex_unlock(&hybrid_capacity_lock);
}
@@ -2263,6 +2272,11 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
} else {
cpu->pstate.scaling = perf_ctl_scaling;
}
+ /*
+ * If the CPU is going online for the first time and it was
+ * offline initially, asym capacity scaling needs to be updated.
+ */
+ hybrid_update_capacity(cpu);
} else {
cpu->pstate.scaling = perf_ctl_scaling;
cpu->pstate.max_pstate = pstate_funcs.get_max(cpu->cpu);
@@ -3352,6 +3366,7 @@ static void intel_pstate_driver_cleanup(void)
static int intel_pstate_register_driver(struct cpufreq_driver *driver)
{
+ bool refresh_cpu_cap_scaling;
int ret;
if (driver == &intel_pstate)
@@ -3364,6 +3379,8 @@ static int intel_pstate_register_driver(struct cpufreq_driver *driver)
arch_set_max_freq_ratio(global.turbo_disabled);
+ refresh_cpu_cap_scaling = hybrid_clear_max_perf_cpu();
+
intel_pstate_driver = driver;
ret = cpufreq_register_driver(intel_pstate_driver);
if (ret) {
@@ -3373,7 +3390,7 @@ static int intel_pstate_register_driver(struct cpufreq_driver *driver)
global.min_perf_pct = min_perf_pct_min();
- hybrid_init_cpu_capacity_scaling();
+ hybrid_init_cpu_capacity_scaling(refresh_cpu_cap_scaling);
return 0;
}
@@ -3638,6 +3655,8 @@ static const struct x86_cpu_id intel_epp_default[] = {
X86_MATCH_VFM(INTEL_ALDERLAKE_L, HWP_SET_DEF_BALANCE_PERF_EPP(102)),
X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, HWP_SET_DEF_BALANCE_PERF_EPP(32)),
X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, HWP_SET_DEF_BALANCE_PERF_EPP(32)),
+ X86_MATCH_VFM(INTEL_GRANITERAPIDS_X, HWP_SET_DEF_BALANCE_PERF_EPP(32)),
+ X86_MATCH_VFM(INTEL_GRANITERAPIDS_D, HWP_SET_DEF_BALANCE_PERF_EPP(32)),
X86_MATCH_VFM(INTEL_METEORLAKE_L, HWP_SET_EPP_VALUES(HWP_EPP_POWERSAVE,
179, 64, 16)),
X86_MATCH_VFM(INTEL_ARROWLAKE, HWP_SET_EPP_VALUES(HWP_EPP_POWERSAVE,
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index fd20b986d1f2..312f2654d1d5 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -189,7 +189,7 @@ static void kirkwood_cpufreq_remove(struct platform_device *pdev)
static struct platform_driver kirkwood_cpufreq_platform_driver = {
.probe = kirkwood_cpufreq_probe,
- .remove_new = kirkwood_cpufreq_remove,
+ .remove = kirkwood_cpufreq_remove,
.driver = {
.name = "kirkwood-cpufreq",
},
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index 6a8e97896d38..ed1a6dbad638 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -148,7 +148,9 @@ static int __init cpufreq_init(void)
ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
- if (!ret && !nowait) {
+ if (ret) {
+ platform_driver_unregister(&platform_driver);
+ } else if (!nowait) {
saved_cpu_wait = cpu_wait;
cpu_wait = loongson2_cpu_wait;
}
diff --git a/drivers/cpufreq/loongson3_cpufreq.c b/drivers/cpufreq/loongson3_cpufreq.c
index 6b5e6798d9a2..bd34bf0fafa5 100644
--- a/drivers/cpufreq/loongson3_cpufreq.c
+++ b/drivers/cpufreq/loongson3_cpufreq.c
@@ -346,8 +346,11 @@ static int loongson3_cpufreq_probe(struct platform_device *pdev)
{
int i, ret;
- for (i = 0; i < MAX_PACKAGES; i++)
- devm_mutex_init(&pdev->dev, &cpufreq_mutex[i]);
+ for (i = 0; i < MAX_PACKAGES; i++) {
+ ret = devm_mutex_init(&pdev->dev, &cpufreq_mutex[i]);
+ if (ret)
+ return ret;
+ }
ret = do_service_request(0, 0, CMD_GET_VERSION, 0, 0);
if (ret <= 0)
@@ -386,7 +389,7 @@ static struct platform_driver loongson3_platform_driver = {
},
.id_table = cpufreq_id_table,
.probe = loongson3_cpufreq_probe,
- .remove_new = loongson3_cpufreq_remove,
+ .remove = loongson3_cpufreq_remove,
};
module_platform_driver(loongson3_platform_driver);
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
deleted file mode 100644
index 690da85c4865..000000000000
--- a/drivers/cpufreq/maple-cpufreq.c
+++ /dev/null
@@ -1,242 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2011 Dmitry Eremin-Solenikov
- * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * and Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
- *
- * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs,
- * that is iMac G5 and latest single CPU desktop.
- */
-
-#undef DEBUG
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/cpufreq.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-#include <linux/time.h>
-#include <linux/of.h>
-
-#define DBG(fmt...) pr_debug(fmt)
-
-/* see 970FX user manual */
-
-#define SCOM_PCR 0x0aa001 /* PCR scom addr */
-
-#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */
-#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */
-#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */
-#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */
-#define PCR_SPEED_MASK 0x000e0000U /* speed mask */
-#define PCR_SPEED_SHIFT 17
-#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */
-#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */
-#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */
-#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */
-#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */
-#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */
-
-#define SCOM_PSR 0x408001 /* PSR scom addr */
-/* warning: PSR is a 64 bits register */
-#define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */
-#define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */
-#define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */
-#define PSR_CUR_SPEED_SHIFT (56)
-
-/*
- * The G5 only supports two frequencies (Quarter speed is not supported)
- */
-#define CPUFREQ_HIGH 0
-#define CPUFREQ_LOW 1
-
-static struct cpufreq_frequency_table maple_cpu_freqs[] = {
- {0, CPUFREQ_HIGH, 0},
- {0, CPUFREQ_LOW, 0},
- {0, 0, CPUFREQ_TABLE_END},
-};
-
-/* Power mode data is an array of the 32 bits PCR values to use for
- * the various frequencies, retrieved from the device-tree
- */
-static int maple_pmode_cur;
-
-static const u32 *maple_pmode_data;
-static int maple_pmode_max;
-
-/*
- * SCOM based frequency switching for 970FX rev3
- */
-static int maple_scom_switch_freq(int speed_mode)
-{
- unsigned long flags;
- int to;
-
- local_irq_save(flags);
-
- /* Clear PCR high */
- scom970_write(SCOM_PCR, 0);
- /* Clear PCR low */
- scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0);
- /* Set PCR low */
- scom970_write(SCOM_PCR, PCR_HILO_SELECT |
- maple_pmode_data[speed_mode]);
-
- /* Wait for completion */
- for (to = 0; to < 10; to++) {
- unsigned long psr = scom970_read(SCOM_PSR);
-
- if ((psr & PSR_CMD_RECEIVED) == 0 &&
- (((psr >> PSR_CUR_SPEED_SHIFT) ^
- (maple_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3)
- == 0)
- break;
- if (psr & PSR_CMD_COMPLETED)
- break;
- udelay(100);
- }
-
- local_irq_restore(flags);
-
- maple_pmode_cur = speed_mode;
- ppc_proc_freq = maple_cpu_freqs[speed_mode].frequency * 1000ul;
-
- return 0;
-}
-
-static int maple_scom_query_freq(void)
-{
- unsigned long psr = scom970_read(SCOM_PSR);
- int i;
-
- for (i = 0; i <= maple_pmode_max; i++)
- if ((((psr >> PSR_CUR_SPEED_SHIFT) ^
- (maple_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0)
- break;
- return i;
-}
-
-/*
- * Common interface to the cpufreq core
- */
-
-static int maple_cpufreq_target(struct cpufreq_policy *policy,
- unsigned int index)
-{
- return maple_scom_switch_freq(index);
-}
-
-static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
-{
- return maple_cpu_freqs[maple_pmode_cur].frequency;
-}
-
-static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- cpufreq_generic_init(policy, maple_cpu_freqs, 12000);
- return 0;
-}
-
-static struct cpufreq_driver maple_cpufreq_driver = {
- .name = "maple",
- .flags = CPUFREQ_CONST_LOOPS,
- .init = maple_cpufreq_cpu_init,
- .verify = cpufreq_generic_frequency_table_verify,
- .target_index = maple_cpufreq_target,
- .get = maple_cpufreq_get_speed,
- .attr = cpufreq_generic_attr,
-};
-
-static int __init maple_cpufreq_init(void)
-{
- struct device_node *cpunode;
- unsigned int psize;
- unsigned long max_freq;
- const u32 *valp;
- u32 pvr_hi;
- int rc = -ENODEV;
-
- /*
- * Behave here like powermac driver which checks machine compatibility
- * to ease merging of two drivers in future.
- */
- if (!of_machine_is_compatible("Momentum,Maple") &&
- !of_machine_is_compatible("Momentum,Apache"))
- return 0;
-
- /* Get first CPU node */
- cpunode = of_cpu_device_node_get(0);
- if (cpunode == NULL) {
- pr_err("Can't find any CPU 0 node\n");
- goto bail_noprops;
- }
-
- /* Check 970FX for now */
- /* we actually don't care on which CPU to access PVR */
- pvr_hi = PVR_VER(mfspr(SPRN_PVR));
- if (pvr_hi != 0x3c && pvr_hi != 0x44) {
- pr_err("Unsupported CPU version (%x)\n", pvr_hi);
- goto bail_noprops;
- }
-
- /* Look for the powertune data in the device-tree */
- /*
- * On Maple this property is provided by PIBS in dual-processor config,
- * not provided by PIBS in CPU0 config and also not provided by SLOF,
- * so YMMV
- */
- maple_pmode_data = of_get_property(cpunode, "power-mode-data", &psize);
- if (!maple_pmode_data) {
- DBG("No power-mode-data !\n");
- goto bail_noprops;
- }
- maple_pmode_max = psize / sizeof(u32) - 1;
-
- /*
- * From what I see, clock-frequency is always the maximal frequency.
- * The current driver can not slew sysclk yet, so we really only deal
- * with powertune steps for now. We also only implement full freq and
- * half freq in this version. So far, I haven't yet seen a machine
- * supporting anything else.
- */
- valp = of_get_property(cpunode, "clock-frequency", NULL);
- if (!valp)
- goto bail_noprops;
- max_freq = (*valp)/1000;
- maple_cpu_freqs[0].frequency = max_freq;
- maple_cpu_freqs[1].frequency = max_freq/2;
-
- /* Force apply current frequency to make sure everything is in
- * sync (voltage is right for example). Firmware may leave us with
- * a strange setting ...
- */
- msleep(10);
- maple_pmode_cur = -1;
- maple_scom_switch_freq(maple_scom_query_freq());
-
- pr_info("Registering Maple CPU frequency driver\n");
- pr_info("Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
- maple_cpu_freqs[1].frequency/1000,
- maple_cpu_freqs[0].frequency/1000,
- maple_cpu_freqs[maple_pmode_cur].frequency/1000);
-
- rc = cpufreq_register_driver(&maple_cpufreq_driver);
-
-bail_noprops:
- of_node_put(cpunode);
-
- return rc;
-}
-
-module_init(maple_cpufreq_init);
-
-
-MODULE_DESCRIPTION("cpufreq driver for Maple 970FX/970MP boards");
-MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
index 8925e096d5b9..9252ebd60373 100644
--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
+++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
@@ -62,7 +62,7 @@ mtk_cpufreq_get_cpu_power(struct device *cpu_dev, unsigned long *uW,
policy = cpufreq_cpu_get_raw(cpu_dev->id);
if (!policy)
- return 0;
+ return -EINVAL;
data = policy->driver_data;
@@ -344,7 +344,7 @@ MODULE_DEVICE_TABLE(of, mtk_cpufreq_hw_match);
static struct platform_driver mtk_cpufreq_hw_driver = {
.probe = mtk_cpufreq_hw_driver_probe,
- .remove_new = mtk_cpufreq_hw_driver_remove,
+ .remove = mtk_cpufreq_hw_driver_remove,
.driver = {
.name = "mtk-cpufreq-hw",
.of_match_table = mtk_cpufreq_hw_match,
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index de8be0a8932d..106220c0fd11 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -188,7 +188,7 @@ static struct platform_driver omap_cpufreq_platdrv = {
.name = "omap-cpufreq",
},
.probe = omap_cpufreq_probe,
- .remove_new = omap_cpufreq_remove,
+ .remove = omap_cpufreq_remove,
};
module_platform_driver(omap_cpufreq_platdrv);
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index 771efbf51a48..ac2e90a65f0c 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -615,7 +615,7 @@ static struct platform_driver pcc_cpufreq_platdrv = {
.driver = {
.name = "pcc-cpufreq",
},
- .remove_new = pcc_cpufreq_remove,
+ .remove = pcc_cpufreq_remove,
};
static int __init pcc_cpufreq_init(void)
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 900d6844c43d..98129565acb8 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -736,7 +736,7 @@ static void qcom_cpufreq_hw_driver_remove(struct platform_device *pdev)
static struct platform_driver qcom_cpufreq_hw_driver = {
.probe = qcom_cpufreq_hw_driver_probe,
- .remove_new = qcom_cpufreq_hw_driver_remove,
+ .remove = qcom_cpufreq_hw_driver_remove,
.driver = {
.name = "qcom-cpufreq-hw",
.of_match_table = qcom_cpufreq_hw_match,
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index 703308fb891a..3a8ed723a23e 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -52,12 +52,13 @@ struct qcom_cpufreq_match_data {
struct nvmem_cell *speedbin_nvmem,
char **pvs_name,
struct qcom_cpufreq_drv *drv);
- const char **genpd_names;
+ const char **pd_names;
+ unsigned int num_pd_names;
};
struct qcom_cpufreq_drv_cpu {
int opp_token;
- struct device **virt_devs;
+ struct dev_pm_domain_list *pd_list;
};
struct qcom_cpufreq_drv {
@@ -395,8 +396,6 @@ static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev,
return 0;
}
-static const char *generic_genpd_names[] = { "perf", NULL };
-
static const struct qcom_cpufreq_match_data match_data_kryo = {
.get_version = qcom_cpufreq_kryo_name_version,
};
@@ -407,13 +406,13 @@ static const struct qcom_cpufreq_match_data match_data_krait = {
static const struct qcom_cpufreq_match_data match_data_msm8909 = {
.get_version = qcom_cpufreq_simple_get_version,
- .genpd_names = generic_genpd_names,
+ .pd_names = (const char *[]) { "perf" },
+ .num_pd_names = 1,
};
-static const char *qcs404_genpd_names[] = { "cpr", NULL };
-
static const struct qcom_cpufreq_match_data match_data_qcs404 = {
- .genpd_names = qcs404_genpd_names,
+ .pd_names = (const char *[]) { "cpr" },
+ .num_pd_names = 1,
};
static const struct qcom_cpufreq_match_data match_data_ipq6018 = {
@@ -428,28 +427,16 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
.get_version = qcom_cpufreq_ipq8074_name_version,
};
-static void qcom_cpufreq_suspend_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
-{
- const char * const *name = drv->data->genpd_names;
- int i;
-
- if (!drv->cpus[cpu].virt_devs)
- return;
-
- for (i = 0; *name; i++, name++)
- device_set_awake_path(drv->cpus[cpu].virt_devs[i]);
-}
-
-static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
+static void qcom_cpufreq_suspend_pd_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
{
- const char * const *name = drv->data->genpd_names;
+ struct dev_pm_domain_list *pd_list = drv->cpus[cpu].pd_list;
int i;
- if (!drv->cpus[cpu].virt_devs)
+ if (!pd_list)
return;
- for (i = 0; *name; i++, name++)
- pm_runtime_put(drv->cpus[cpu].virt_devs[i]);
+ for (i = 0; i < pd_list->num_pds; i++)
+ device_set_awake_path(pd_list->pd_devs[i]);
}
static int qcom_cpufreq_probe(struct platform_device *pdev)
@@ -503,7 +490,6 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
}
for_each_possible_cpu(cpu) {
- struct device **virt_devs = NULL;
struct dev_pm_opp_config config = {
.supported_hw = NULL,
};
@@ -522,12 +508,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
config.prop_name = pvs_name;
}
- if (drv->data->genpd_names) {
- config.genpd_names = drv->data->genpd_names;
- config.virt_devs = &virt_devs;
- }
-
- if (config.supported_hw || config.genpd_names) {
+ if (config.supported_hw) {
drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
if (drv->cpus[cpu].opp_token < 0) {
ret = drv->cpus[cpu].opp_token;
@@ -536,25 +517,18 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
}
}
- if (virt_devs) {
- const char * const *name = config.genpd_names;
- int i, j;
-
- for (i = 0; *name; i++, name++) {
- ret = pm_runtime_resume_and_get(virt_devs[i]);
- if (ret) {
- dev_err(cpu_dev, "failed to resume %s: %d\n",
- *name, ret);
-
- /* Rollback previous PM runtime calls */
- name = config.genpd_names;
- for (j = 0; *name && j < i; j++, name++)
- pm_runtime_put(virt_devs[j]);
-
- goto free_opp;
- }
- }
- drv->cpus[cpu].virt_devs = virt_devs;
+ if (drv->data->pd_names) {
+ struct dev_pm_domain_attach_data attach_data = {
+ .pd_names = drv->data->pd_names,
+ .num_pd_names = drv->data->num_pd_names,
+ .pd_flags = PD_FLAG_DEV_LINK_ON |
+ PD_FLAG_REQUIRED_OPP,
+ };
+
+ ret = dev_pm_domain_attach_list(cpu_dev, &attach_data,
+ &drv->cpus[cpu].pd_list);
+ if (ret < 0)
+ goto free_opp;
}
}
@@ -570,7 +544,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
free_opp:
for_each_possible_cpu(cpu) {
- qcom_cpufreq_put_virt_devs(drv, cpu);
+ dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
}
return ret;
@@ -584,7 +558,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
platform_device_unregister(cpufreq_dt_pdev);
for_each_possible_cpu(cpu) {
- qcom_cpufreq_put_virt_devs(drv, cpu);
+ dev_pm_domain_detach_list(drv->cpus[cpu].pd_list);
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
}
}
@@ -595,7 +569,7 @@ static int qcom_cpufreq_suspend(struct device *dev)
unsigned int cpu;
for_each_possible_cpu(cpu)
- qcom_cpufreq_suspend_virt_devs(drv, cpu);
+ qcom_cpufreq_suspend_pd_devs(drv, cpu);
return 0;
}
@@ -604,7 +578,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(qcom_cpufreq_pm_ops, qcom_cpufreq_suspend, NULL)
static struct platform_driver qcom_cpufreq_driver = {
.probe = qcom_cpufreq_probe,
- .remove_new = qcom_cpufreq_remove,
+ .remove = qcom_cpufreq_remove,
.driver = {
.name = "qcom-cpufreq-nvmem",
.pm = pm_sleep_ptr(&qcom_cpufreq_pm_ops),
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 3519bf34d397..a37ce051236c 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -296,7 +296,7 @@ static struct platform_driver qoriq_cpufreq_platform_driver = {
.name = "qoriq-cpufreq",
},
.probe = qoriq_cpufreq_probe,
- .remove_new = qoriq_cpufreq_remove,
+ .remove = qoriq_cpufreq_remove,
};
module_platform_driver(qoriq_cpufreq_platform_driver);
diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c b/drivers/cpufreq/raspberrypi-cpufreq.c
index e0705cc9a57d..5050932954e3 100644
--- a/drivers/cpufreq/raspberrypi-cpufreq.c
+++ b/drivers/cpufreq/raspberrypi-cpufreq.c
@@ -85,7 +85,7 @@ static struct platform_driver raspberrypi_cpufreq_driver = {
.name = "raspberrypi-cpufreq",
},
.probe = raspberrypi_cpufreq_probe,
- .remove_new = raspberrypi_cpufreq_remove,
+ .remove = raspberrypi_cpufreq_remove,
};
module_platform_driver(raspberrypi_cpufreq_driver);
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index 5892c73e129d..07d6f9a9b7c8 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -287,7 +287,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
ret = cpufreq_enable_boost_support();
if (ret) {
dev_warn(cpu_dev, "failed to enable boost: %d\n", ret);
- goto out_free_opp;
+ goto out_free_table;
} else {
scmi_cpufreq_hw_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
scmi_cpufreq_driver.boost_enabled = true;
@@ -296,6 +296,8 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
return 0;
+out_free_table:
+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_opp:
dev_pm_opp_remove_all_dynamic(cpu_dev);
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index 8d73e6e8be2a..cd89c1b9832c 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -217,7 +217,7 @@ static struct platform_driver scpi_cpufreq_platdrv = {
.name = "scpi-cpufreq",
},
.probe = scpi_cpufreq_probe,
- .remove_new = scpi_cpufreq_remove,
+ .remove = scpi_cpufreq_remove,
};
module_platform_driver(scpi_cpufreq_platdrv);
diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index 293921acec93..17d6a149f580 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -22,6 +22,9 @@
#define NVMEM_MASK 0x7
#define NVMEM_SHIFT 5
+#define SUN50I_A100_NVMEM_MASK 0xf
+#define SUN50I_A100_NVMEM_SHIFT 12
+
static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
struct sunxi_cpufreq_data {
@@ -45,6 +48,23 @@ static u32 sun50i_h6_efuse_xlate(u32 speedbin)
return 0;
}
+static u32 sun50i_a100_efuse_xlate(u32 speedbin)
+{
+ u32 efuse_value;
+
+ efuse_value = (speedbin >> SUN50I_A100_NVMEM_SHIFT) &
+ SUN50I_A100_NVMEM_MASK;
+
+ switch (efuse_value) {
+ case 0b100:
+ return 2;
+ case 0b010:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static int get_soc_id_revision(void)
{
#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY
@@ -108,6 +128,10 @@ static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = {
.efuse_xlate = sun50i_h6_efuse_xlate,
};
+static struct sunxi_cpufreq_data sun50i_a100_cpufreq_data = {
+ .efuse_xlate = sun50i_a100_efuse_xlate,
+};
+
static struct sunxi_cpufreq_data sun50i_h616_cpufreq_data = {
.efuse_xlate = sun50i_h616_efuse_xlate,
};
@@ -116,6 +140,9 @@ static const struct of_device_id cpu_opp_match_list[] = {
{ .compatible = "allwinner,sun50i-h6-operating-points",
.data = &sun50i_h6_cpufreq_data,
},
+ { .compatible = "allwinner,sun50i-a100-operating-points",
+ .data = &sun50i_a100_cpufreq_data,
+ },
{ .compatible = "allwinner,sun50i-h616-operating-points",
.data = &sun50i_h616_cpufreq_data,
},
@@ -283,7 +310,7 @@ static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
static struct platform_driver sun50i_cpufreq_driver = {
.probe = sun50i_cpufreq_nvmem_probe,
- .remove_new = sun50i_cpufreq_nvmem_remove,
+ .remove = sun50i_cpufreq_nvmem_remove,
.driver = {
.name = "sun50i-cpufreq-nvmem",
},
@@ -291,6 +318,7 @@ static struct platform_driver sun50i_cpufreq_driver = {
static const struct of_device_id sun50i_cpufreq_match_list[] = {
{ .compatible = "allwinner,sun50i-h6" },
+ { .compatible = "allwinner,sun50i-a100" },
{ .compatible = "allwinner,sun50i-h616" },
{ .compatible = "allwinner,sun50i-h618" },
{ .compatible = "allwinner,sun50i-h700" },
diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c
index 7b8fcfa55038..c7761eb99f3c 100644
--- a/drivers/cpufreq/tegra186-cpufreq.c
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -276,7 +276,7 @@ static struct platform_driver tegra186_cpufreq_platform_driver = {
.of_match_table = tegra186_cpufreq_of_match,
},
.probe = tegra186_cpufreq_probe,
- .remove_new = tegra186_cpufreq_remove,
+ .remove = tegra186_cpufreq_remove,
};
module_platform_driver(tegra186_cpufreq_platform_driver);
diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c
index 07ea7ed61b68..9055dd398e7f 100644
--- a/drivers/cpufreq/tegra194-cpufreq.c
+++ b/drivers/cpufreq/tegra194-cpufreq.c
@@ -818,7 +818,7 @@ static struct platform_driver tegra194_ccplex_driver = {
.of_match_table = tegra194_cpufreq_of_match,
},
.probe = tegra194_cpufreq_probe,
- .remove_new = tegra194_cpufreq_remove,
+ .remove = tegra194_cpufreq_remove,
};
module_platform_driver(tegra194_ccplex_driver);
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
index ba621ce1cdda..5a5147277cd0 100644
--- a/drivers/cpufreq/ti-cpufreq.c
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -93,6 +93,8 @@ struct ti_cpufreq_soc_data {
bool multi_regulator;
/* Backward compatibility hack: Might have missing syscon */
#define TI_QUIRK_SYSCON_MAY_BE_MISSING 0x1
+/* Backward compatibility hack: new syscon size is 1 register wide */
+#define TI_QUIRK_SYSCON_IS_SINGLE_REG 0x2
u8 quirks;
};
@@ -316,8 +318,8 @@ static struct ti_cpufreq_soc_data am625_soc_data = {
.efuse_offset = 0x0018,
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
- .rev_offset = 0x0014,
.multi_regulator = false,
+ .quirks = TI_QUIRK_SYSCON_IS_SINGLE_REG,
};
static struct ti_cpufreq_soc_data am62a7_soc_data = {
@@ -325,7 +327,6 @@ static struct ti_cpufreq_soc_data am62a7_soc_data = {
.efuse_offset = 0x0,
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
- .rev_offset = 0x0014,
.multi_regulator = false,
};
@@ -334,7 +335,6 @@ static struct ti_cpufreq_soc_data am62p5_soc_data = {
.efuse_offset = 0x0,
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
- .rev_offset = 0x0014,
.multi_regulator = false,
};
@@ -354,6 +354,10 @@ static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data,
ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset,
&efuse);
+
+ if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_IS_SINGLE_REG && ret == -EIO)
+ ret = regmap_read(opp_data->syscon, 0x0, &efuse);
+
if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) {
/* not a syscon register! */
void __iomem *regs = ioremap(OMAP3_SYSCON_BASE +
diff --git a/drivers/cpufreq/vexpress-spc-cpufreq.c b/drivers/cpufreq/vexpress-spc-cpufreq.c
index 3fadf536c429..0f86cdb7ec8a 100644
--- a/drivers/cpufreq/vexpress-spc-cpufreq.c
+++ b/drivers/cpufreq/vexpress-spc-cpufreq.c
@@ -565,7 +565,7 @@ static struct platform_driver ve_spc_cpufreq_platdrv = {
.name = "vexpress-spc-cpufreq",
},
.probe = ve_spc_cpufreq_probe,
- .remove_new = ve_spc_cpufreq_remove,
+ .remove = ve_spc_cpufreq_remove,
};
module_platform_driver(ve_spc_cpufreq_platdrv);
diff --git a/drivers/cpufreq/virtual-cpufreq.c b/drivers/cpufreq/virtual-cpufreq.c
new file mode 100644
index 000000000000..a050b3a6737f
--- /dev/null
+++ b/drivers/cpufreq/virtual-cpufreq.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Google LLC
+ */
+
+#include <linux/arch_topology.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/*
+ * CPU0..CPUn
+ * +-------------+-------------------------------+--------+-------+
+ * | Register | Description | Offset | Len |
+ * +-------------+-------------------------------+--------+-------+
+ * | cur_perf | read this register to get | 0x0 | 0x4 |
+ * | | the current perf (integer val | | |
+ * | | representing perf relative to | | |
+ * | | max performance) | | |
+ * | | that vCPU is running at | | |
+ * +-------------+-------------------------------+--------+-------+
+ * | set_perf | write to this register to set | 0x4 | 0x4 |
+ * | | perf value of the vCPU | | |
+ * +-------------+-------------------------------+--------+-------+
+ * | perftbl_len | number of entries in perf | 0x8 | 0x4 |
+ * | | table. A single entry in the | | |
+ * | | perf table denotes no table | | |
+ * | | and the entry contains | | |
+ * | | the maximum perf value | | |
+ * | | that this vCPU supports. | | |
+ * | | The guest can request any | | |
+ * | | value between 1 and max perf | | |
+ * | | when perftbls are not used. | | |
+ * +---------------------------------------------+--------+-------+
+ * | perftbl_sel | write to this register to | 0xc | 0x4 |
+ * | | select perf table entry to | | |
+ * | | read from | | |
+ * +---------------------------------------------+--------+-------+
+ * | perftbl_rd | read this register to get | 0x10 | 0x4 |
+ * | | perf value of the selected | | |
+ * | | entry based on perftbl_sel | | |
+ * +---------------------------------------------+--------+-------+
+ * | perf_domain | performance domain number | 0x14 | 0x4 |
+ * | | that this vCPU belongs to. | | |
+ * | | vCPUs sharing the same perf | | |
+ * | | domain number are part of the | | |
+ * | | same performance domain. | | |
+ * +-------------+-------------------------------+--------+-------+
+ */
+
+#define REG_CUR_PERF_STATE_OFFSET 0x0
+#define REG_SET_PERF_STATE_OFFSET 0x4
+#define REG_PERFTBL_LEN_OFFSET 0x8
+#define REG_PERFTBL_SEL_OFFSET 0xc
+#define REG_PERFTBL_RD_OFFSET 0x10
+#define REG_PERF_DOMAIN_OFFSET 0x14
+#define PER_CPU_OFFSET 0x1000
+
+#define PERFTBL_MAX_ENTRIES 64U
+
+static void __iomem *base;
+static DEFINE_PER_CPU(u32, perftbl_num_entries);
+
+static void virt_scale_freq_tick(void)
+{
+ int cpu = smp_processor_id();
+ u32 max_freq = (u32)cpufreq_get_hw_max_freq(cpu);
+ u64 cur_freq;
+ unsigned long scale;
+
+ cur_freq = (u64)readl_relaxed(base + cpu * PER_CPU_OFFSET
+ + REG_CUR_PERF_STATE_OFFSET);
+
+ cur_freq <<= SCHED_CAPACITY_SHIFT;
+ scale = (unsigned long)div_u64(cur_freq, max_freq);
+ scale = min(scale, SCHED_CAPACITY_SCALE);
+
+ this_cpu_write(arch_freq_scale, scale);
+}
+
+static struct scale_freq_data virt_sfd = {
+ .source = SCALE_FREQ_SOURCE_VIRT,
+ .set_freq_scale = virt_scale_freq_tick,
+};
+
+static unsigned int virt_cpufreq_set_perf(struct cpufreq_policy *policy,
+ unsigned int target_freq)
+{
+ writel_relaxed(target_freq,
+ base + policy->cpu * PER_CPU_OFFSET + REG_SET_PERF_STATE_OFFSET);
+ return 0;
+}
+
+static unsigned int virt_cpufreq_fast_switch(struct cpufreq_policy *policy,
+ unsigned int target_freq)
+{
+ virt_cpufreq_set_perf(policy, target_freq);
+ return target_freq;
+}
+
+static u32 virt_cpufreq_get_perftbl_entry(int cpu, u32 idx)
+{
+ writel_relaxed(idx, base + cpu * PER_CPU_OFFSET +
+ REG_PERFTBL_SEL_OFFSET);
+ return readl_relaxed(base + cpu * PER_CPU_OFFSET +
+ REG_PERFTBL_RD_OFFSET);
+}
+
+static int virt_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ int ret = 0;
+
+ freqs.old = policy->cur;
+ freqs.new = target_freq;
+
+ cpufreq_freq_transition_begin(policy, &freqs);
+ ret = virt_cpufreq_set_perf(policy, target_freq);
+ cpufreq_freq_transition_end(policy, &freqs, ret != 0);
+
+ return ret;
+}
+
+static int virt_cpufreq_get_sharing_cpus(struct cpufreq_policy *policy)
+{
+ u32 cur_perf_domain, perf_domain;
+ struct device *cpu_dev;
+ int cpu;
+
+ cur_perf_domain = readl_relaxed(base + policy->cpu *
+ PER_CPU_OFFSET + REG_PERF_DOMAIN_OFFSET);
+
+ for_each_possible_cpu(cpu) {
+ cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev)
+ continue;
+
+ perf_domain = readl_relaxed(base + cpu *
+ PER_CPU_OFFSET + REG_PERF_DOMAIN_OFFSET);
+
+ if (perf_domain == cur_perf_domain)
+ cpumask_set_cpu(cpu, policy->cpus);
+ }
+
+ return 0;
+}
+
+static int virt_cpufreq_get_freq_info(struct cpufreq_policy *policy)
+{
+ struct cpufreq_frequency_table *table;
+ u32 num_perftbl_entries, idx;
+
+ num_perftbl_entries = per_cpu(perftbl_num_entries, policy->cpu);
+
+ if (num_perftbl_entries == 1) {
+ policy->cpuinfo.min_freq = 1;
+ policy->cpuinfo.max_freq = virt_cpufreq_get_perftbl_entry(policy->cpu, 0);
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+
+ policy->cur = policy->max;
+ return 0;
+ }
+
+ table = kcalloc(num_perftbl_entries + 1, sizeof(*table), GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ for (idx = 0; idx < num_perftbl_entries; idx++)
+ table[idx].frequency = virt_cpufreq_get_perftbl_entry(policy->cpu, idx);
+
+ table[idx].frequency = CPUFREQ_TABLE_END;
+ policy->freq_table = table;
+
+ return 0;
+}
+
+static int virt_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ struct device *cpu_dev;
+ int ret;
+
+ cpu_dev = get_cpu_device(policy->cpu);
+ if (!cpu_dev)
+ return -ENODEV;
+
+ ret = virt_cpufreq_get_freq_info(policy);
+ if (ret) {
+ dev_warn(cpu_dev, "failed to get cpufreq info\n");
+ return ret;
+ }
+
+ ret = virt_cpufreq_get_sharing_cpus(policy);
+ if (ret) {
+ dev_warn(cpu_dev, "failed to get sharing cpumask\n");
+ return ret;
+ }
+
+ /*
+ * To simplify and improve latency of handling frequency requests on
+ * the host side, this ensures that the vCPU thread triggering the MMIO
+ * abort is the same thread whose performance constraints (Ex. uclamp
+ * settings) need to be updated. This simplifies the VMM (Virtual
+ * Machine Manager) having to find the correct vCPU thread and/or
+ * facing permission issues when configuring other threads.
+ */
+ policy->dvfs_possible_from_any_cpu = false;
+ policy->fast_switch_possible = true;
+
+ /*
+ * Using the default SCALE_FREQ_SOURCE_CPUFREQ is insufficient since
+ * the actual physical CPU frequency may not match requested frequency
+ * from the vCPU thread due to frequency update latencies or other
+ * inputs to the physical CPU frequency selection. This additional FIE
+ * source allows for more accurate freq_scale updates and only takes
+ * effect if another FIE source such as AMUs have not been registered.
+ */
+ topology_set_scale_freq_source(&virt_sfd, policy->cpus);
+
+ return 0;
+}
+
+static void virt_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+ topology_clear_scale_freq_source(SCALE_FREQ_SOURCE_VIRT, policy->related_cpus);
+ kfree(policy->freq_table);
+}
+
+static int virt_cpufreq_online(struct cpufreq_policy *policy)
+{
+ /* Nothing to restore. */
+ return 0;
+}
+
+static int virt_cpufreq_offline(struct cpufreq_policy *policy)
+{
+ /* Dummy offline() to avoid exit() being called and freeing resources. */
+ return 0;
+}
+
+static int virt_cpufreq_verify_policy(struct cpufreq_policy_data *policy)
+{
+ if (policy->freq_table)
+ return cpufreq_frequency_table_verify(policy, policy->freq_table);
+
+ cpufreq_verify_within_cpu_limits(policy);
+ return 0;
+}
+
+static struct cpufreq_driver cpufreq_virt_driver = {
+ .name = "virt-cpufreq",
+ .init = virt_cpufreq_cpu_init,
+ .exit = virt_cpufreq_cpu_exit,
+ .online = virt_cpufreq_online,
+ .offline = virt_cpufreq_offline,
+ .verify = virt_cpufreq_verify_policy,
+ .target = virt_cpufreq_target,
+ .fast_switch = virt_cpufreq_fast_switch,
+ .attr = cpufreq_generic_attr,
+};
+
+static int virt_cpufreq_driver_probe(struct platform_device *pdev)
+{
+ u32 num_perftbl_entries;
+ int ret, cpu;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ for_each_possible_cpu(cpu) {
+ num_perftbl_entries = readl_relaxed(base + cpu * PER_CPU_OFFSET +
+ REG_PERFTBL_LEN_OFFSET);
+
+ if (!num_perftbl_entries || num_perftbl_entries > PERFTBL_MAX_ENTRIES)
+ return -ENODEV;
+
+ per_cpu(perftbl_num_entries, cpu) = num_perftbl_entries;
+ }
+
+ ret = cpufreq_register_driver(&cpufreq_virt_driver);
+ if (ret) {
+ dev_err(&pdev->dev, "Virtual CPUFreq driver failed to register: %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(&pdev->dev, "Virtual CPUFreq driver initialized\n");
+ return 0;
+}
+
+static void virt_cpufreq_driver_remove(struct platform_device *pdev)
+{
+ cpufreq_unregister_driver(&cpufreq_virt_driver);
+}
+
+static const struct of_device_id virt_cpufreq_match[] = {
+ { .compatible = "qemu,virtual-cpufreq", .data = NULL},
+ {}
+};
+MODULE_DEVICE_TABLE(of, virt_cpufreq_match);
+
+static struct platform_driver virt_cpufreq_driver = {
+ .probe = virt_cpufreq_driver_probe,
+ .remove = virt_cpufreq_driver_remove,
+ .driver = {
+ .name = "virt-cpufreq",
+ .of_match_table = virt_cpufreq_match,
+ },
+};
+
+static int __init virt_cpufreq_init(void)
+{
+ return platform_driver_register(&virt_cpufreq_driver);
+}
+postcore_initcall(virt_cpufreq_init);
+
+static void __exit virt_cpufreq_exit(void)
+{
+ platform_driver_unregister(&virt_cpufreq_driver);
+}
+module_exit(virt_cpufreq_exit);
+
+MODULE_DESCRIPTION("Virtual cpufreq driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index 7cfb980a357d..caba6f4bb1b7 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -139,7 +139,7 @@ out_kfree_drv:
*
* Initializes arm cpuidle driver for all CPUs, if any CPU fails
* to register cpuidle driver then rollback to cancel all CPUs
- * registeration.
+ * registration.
*/
static int __init arm_idle_init(void)
{
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
index 14db9b7d985d..f68c65f1d023 100644
--- a/drivers/cpuidle/cpuidle-pseries.c
+++ b/drivers/cpuidle/cpuidle-pseries.c
@@ -22,6 +22,7 @@
#include <asm/idle.h>
#include <asm/plpar_wrappers.h>
#include <asm/rtas.h>
+#include <asm/time.h>
static struct cpuidle_driver pseries_idle_driver = {
.name = "pseries_idle",
diff --git a/drivers/cpuidle/cpuidle-qcom-spm.c b/drivers/cpuidle/cpuidle-qcom-spm.c
index 1fc9968eae19..3ab240e0e122 100644
--- a/drivers/cpuidle/cpuidle-qcom-spm.c
+++ b/drivers/cpuidle/cpuidle-qcom-spm.c
@@ -48,7 +48,7 @@ static int qcom_cpu_spc(struct spm_driver_data *drv)
ret = cpu_suspend(0, qcom_pm_collapse);
/*
* ARM common code executes WFI without calling into our driver and
- * if the SPM mode is not reset, then we may accidently power down the
+ * if the SPM mode is not reset, then we may accidentally power down the
* cpu when we intended only to gate the cpu clock.
* Ensure the state is set to standby before returning.
*/
diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c
index d228b4d18d56..14462c092039 100644
--- a/drivers/cpuidle/cpuidle-riscv-sbi.c
+++ b/drivers/cpuidle/cpuidle-riscv-sbi.c
@@ -26,6 +26,7 @@
#include <asm/smp.h>
#include <asm/suspend.h>
+#include "cpuidle.h"
#include "dt_idle_states.h"
#include "dt_idle_genpd.h"
@@ -329,6 +330,9 @@ static int sbi_cpuidle_init_cpu(struct device *dev, int cpu)
return ret;
}
+ if (cpuidle_disabled())
+ return 0;
+
ret = cpuidle_register(drv, NULL);
if (ret)
goto deinit;
@@ -538,7 +542,10 @@ static int sbi_cpuidle_probe(struct platform_device *pdev)
/* Setup CPU hotplut notifiers */
sbi_idle_init_cpuhp();
- pr_info("idle driver registered for all CPUs\n");
+ if (cpuidle_disabled())
+ pr_info("cpuidle is disabled\n");
+ else
+ pr_info("idle driver registered for all CPUs\n");
return 0;
@@ -582,4 +589,4 @@ static int __init sbi_cpuidle_init(void)
return 0;
}
-device_initcall(sbi_cpuidle_init);
+arch_initcall(sbi_cpuidle_init);
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 9e418aec1755..0835da449db8 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -69,11 +69,15 @@ int cpuidle_play_dead(void)
if (!drv)
return -ENODEV;
- /* Find lowest-power state that supports long-term idle */
- for (i = drv->state_count - 1; i >= 0; i--)
+ for (i = drv->state_count - 1; i >= 0; i--) {
if (drv->states[i].enter_dead)
- return drv->states[i].enter_dead(dev, i);
+ drv->states[i].enter_dead(dev, i);
+ }
+ /*
+ * If :enter_dead() is successful, it will never return, so reaching
+ * here means that all of them failed above or were not present.
+ */
return -ENODEV;
}
@@ -406,7 +410,7 @@ void cpuidle_reflect(struct cpuidle_device *dev, int index)
* Min polling interval of 10usec is a guess. It is assuming that
* for most users, the time for a single ping-pong workload like
* perf bench pipe would generally complete within 10usec but
- * this is hardware dependant. Actual time can be estimated with
+ * this is hardware dependent. Actual time can be estimated with
*
* perf bench sched pipe -l 10000
*
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index cf5873cc45dc..9bbfa594c442 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -261,7 +261,7 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
* @drv: a pointer to a valid struct cpuidle_driver
*
* Register the driver under a lock to prevent concurrent attempts to
- * [un]register the driver from occuring at the same time.
+ * [un]register the driver from occurring at the same time.
*
* Returns 0 on success, a negative error code (returned by
* __cpuidle_register_driver()) otherwise.
@@ -296,7 +296,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_driver);
* @drv: a pointer to a valid struct cpuidle_driver
*
* Unregisters the cpuidle driver under a lock to prevent concurrent attempts
- * to [un]register the driver from occuring at the same time. @drv has to
+ * to [un]register the driver from occurring at the same time. @drv has to
* match the currently registered driver.
*/
void cpuidle_unregister_driver(struct cpuidle_driver *drv)
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index f3c9d49f0f2a..28363bfa3e4c 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -19,7 +19,7 @@
#include "gov.h"
-#define BUCKETS 12
+#define BUCKETS 6
#define INTERVAL_SHIFT 3
#define INTERVALS (1UL << INTERVAL_SHIFT)
#define RESOLUTION 1024
@@ -29,12 +29,11 @@
/*
* Concepts and ideas behind the menu governor
*
- * For the menu governor, there are 3 decision factors for picking a C
+ * For the menu governor, there are 2 decision factors for picking a C
* state:
* 1) Energy break even point
- * 2) Performance impact
- * 3) Latency tolerance (from pmqos infrastructure)
- * These three factors are treated independently.
+ * 2) Latency tolerance (from pmqos infrastructure)
+ * These two factors are treated independently.
*
* Energy break even point
* -----------------------
@@ -75,30 +74,6 @@
* intervals and if the stand deviation of these 8 intervals is below a
* threshold value, we use the average of these intervals as prediction.
*
- * Limiting Performance Impact
- * ---------------------------
- * C states, especially those with large exit latencies, can have a real
- * noticeable impact on workloads, which is not acceptable for most sysadmins,
- * and in addition, less performance has a power price of its own.
- *
- * As a general rule of thumb, menu assumes that the following heuristic
- * holds:
- * The busier the system, the less impact of C states is acceptable
- *
- * This rule-of-thumb is implemented using a performance-multiplier:
- * If the exit latency times the performance multiplier is longer than
- * the predicted duration, the C state is not considered a candidate
- * for selection due to a too high performance impact. So the higher
- * this multiplier is, the longer we need to be idle to pick a deep C
- * state, and thus the less likely a busy CPU will hit such a deep
- * C state.
- *
- * Currently there is only one value determining the factor:
- * 10 points are added for each process that is waiting for IO on this CPU.
- * (This value was experimentally determined.)
- * Utilization is no longer a factor as it was shown that it never contributed
- * significantly to the performance multiplier in the first place.
- *
*/
struct menu_device {
@@ -112,19 +87,10 @@ struct menu_device {
int interval_ptr;
};
-static inline int which_bucket(u64 duration_ns, unsigned int nr_iowaiters)
+static inline int which_bucket(u64 duration_ns)
{
int bucket = 0;
- /*
- * We keep two groups of stats; one with no
- * IO pending, one without.
- * This allows us to calculate
- * E(duration)|iowait
- */
- if (nr_iowaiters)
- bucket = BUCKETS/2;
-
if (duration_ns < 10ULL * NSEC_PER_USEC)
return bucket;
if (duration_ns < 100ULL * NSEC_PER_USEC)
@@ -138,19 +104,6 @@ static inline int which_bucket(u64 duration_ns, unsigned int nr_iowaiters)
return bucket + 5;
}
-/*
- * Return a multiplier for the exit latency that is intended
- * to take performance requirements into account.
- * The more performance critical we estimate the system
- * to be, the higher this multiplier, and thus the higher
- * the barrier to go to an expensive C state.
- */
-static inline int performance_multiplier(unsigned int nr_iowaiters)
-{
- /* for IO wait tasks (per cpu!) we add 10x each */
- return 1 + 10 * nr_iowaiters;
-}
-
static DEFINE_PER_CPU(struct menu_device, menu_devices);
static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
@@ -258,8 +211,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
struct menu_device *data = this_cpu_ptr(&menu_devices);
s64 latency_req = cpuidle_governor_latency_req(dev->cpu);
u64 predicted_ns;
- u64 interactivity_req;
- unsigned int nr_iowaiters;
ktime_t delta, delta_tick;
int i, idx;
@@ -268,8 +219,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
data->needs_update = 0;
}
- nr_iowaiters = nr_iowait_cpu(dev->cpu);
-
/* Find the shortest expected idle interval. */
predicted_ns = get_typical_interval(data) * NSEC_PER_USEC;
if (predicted_ns > RESIDENCY_THRESHOLD_NS) {
@@ -283,7 +232,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
}
data->next_timer_ns = delta;
- data->bucket = which_bucket(data->next_timer_ns, nr_iowaiters);
+ data->bucket = which_bucket(data->next_timer_ns);
/* Round up the result for half microseconds. */
timer_us = div_u64((RESOLUTION * DECAY * NSEC_PER_USEC) / 2 +
@@ -301,7 +250,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
*/
data->next_timer_ns = KTIME_MAX;
delta_tick = TICK_NSEC / 2;
- data->bucket = which_bucket(KTIME_MAX, nr_iowaiters);
+ data->bucket = which_bucket(KTIME_MAX);
}
if (unlikely(drv->state_count <= 1 || latency_req == 0) ||
@@ -328,15 +277,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
*/
if (predicted_ns < TICK_NSEC)
predicted_ns = data->next_timer_ns;
- } else {
- /*
- * Use the performance multiplier and the user-configurable
- * latency_req to determine the maximum exit latency.
- */
- interactivity_req = div64_u64(predicted_ns,
- performance_multiplier(nr_iowaiters));
- if (latency_req > interactivity_req)
- latency_req = interactivity_req;
+ } else if (latency_req > predicted_ns) {
+ latency_req = predicted_ns;
}
/*
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 08b1238bcd7b..0a9cdd31cbd9 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -95,6 +95,9 @@ config PKEY
loaded when a CEX crypto card is available.
- A pkey EP11 kernel module (pkey-ep11.ko) which is automatically
loaded when a CEX crypto card is available.
+ - A pkey UV kernel module (pkey-uv.ko) which is automatically
+ loaded when the Ultravisor feature is available within a
+ protected execution environment.
Select this option if you want to enable the kernel and userspace
API for protected key handling.
@@ -152,6 +155,24 @@ config PKEY_PCKMO
this option unless you are sure you never need to derive protected
keys from clear key values directly via PCKMO.
+config PKEY_UV
+ tristate "PKEY UV support handler"
+ depends on PKEY
+ depends on S390_UV_UAPI
+ help
+ This is the PKEY Ultravisor support handler for deriving protected
+ keys from secrets stored within the Ultravisor (UV).
+
+ This module works together with the UV device and supports the
+ retrieval of protected keys from secrets stored within the
+ UV firmware layer. This service is only available within
+ a protected execution guest and thus this module will fail upon
+ modprobe if no protected execution environment is detected.
+
+ Enable this option if you intend to run this kernel with an KVM
+ guest with protected execution and you want to use UV retrievable
+ secrets via PKEY API.
+
config CRYPTO_PAES_S390
tristate "PAES cipher algorithms"
depends on S390
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
index 890664bd5f0f..58a76e2ba64e 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
@@ -542,7 +542,7 @@ MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table);
static struct platform_driver sun4i_ss_driver = {
.probe = sun4i_ss_probe,
- .remove_new = sun4i_ss_remove,
+ .remove = sun4i_ss_remove,
.driver = {
.name = "sun4i-ss",
.pm = &sun4i_ss_pm_ops,
diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
index e55e58e164db..ec1ffda9ea32 100644
--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
+++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c
@@ -1129,7 +1129,7 @@ MODULE_DEVICE_TABLE(of, sun8i_ce_crypto_of_match_table);
static struct platform_driver sun8i_ce_driver = {
.probe = sun8i_ce_probe,
- .remove_new = sun8i_ce_remove,
+ .remove = sun8i_ce_remove,
.driver = {
.name = "sun8i-ce",
.pm = &sun8i_ce_pm_ops,
diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
index 0dbc0220146c..f45685707e0d 100644
--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
+++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
@@ -929,7 +929,7 @@ MODULE_DEVICE_TABLE(of, sun8i_ss_crypto_of_match_table);
static struct platform_driver sun8i_ss_driver = {
.probe = sun8i_ss_probe,
- .remove_new = sun8i_ss_remove,
+ .remove = sun8i_ss_remove,
.driver = {
.name = "sun8i-ss",
.pm = &sun8i_ss_pm_ops,
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 6006703fb6d7..ec3ccfa60445 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -653,9 +653,6 @@ static void crypto4xx_stop_all(struct crypto4xx_core_device *core_dev)
crypto4xx_destroy_pdr(core_dev->dev);
crypto4xx_destroy_gdr(core_dev->dev);
crypto4xx_destroy_sdr(core_dev->dev);
- iounmap(core_dev->dev->ce_base);
- kfree(core_dev->dev);
- kfree(core_dev);
}
static u32 get_next_gd(u32 current)
@@ -1333,17 +1330,12 @@ static struct crypto4xx_alg_common crypto4xx_alg[] = {
static int crypto4xx_probe(struct platform_device *ofdev)
{
int rc;
- struct resource res;
struct device *dev = &ofdev->dev;
struct crypto4xx_core_device *core_dev;
struct device_node *np;
u32 pvr;
bool is_revb = true;
- rc = of_address_to_resource(ofdev->dev.of_node, 0, &res);
- if (rc)
- return -ENODEV;
-
np = of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-crypto");
if (np) {
mtdcri(SDR0, PPC460EX_SDR0_SRST,
@@ -1374,16 +1366,17 @@ static int crypto4xx_probe(struct platform_device *ofdev)
of_node_put(np);
- core_dev = kzalloc(sizeof(struct crypto4xx_core_device), GFP_KERNEL);
+ core_dev = devm_kzalloc(
+ &ofdev->dev, sizeof(struct crypto4xx_core_device), GFP_KERNEL);
if (!core_dev)
return -ENOMEM;
dev_set_drvdata(dev, core_dev);
core_dev->ofdev = ofdev;
- core_dev->dev = kzalloc(sizeof(struct crypto4xx_device), GFP_KERNEL);
- rc = -ENOMEM;
+ core_dev->dev = devm_kzalloc(
+ &ofdev->dev, sizeof(struct crypto4xx_device), GFP_KERNEL);
if (!core_dev->dev)
- goto err_alloc_dev;
+ return -ENOMEM;
/*
* Older version of 460EX/GT have a hardware bug.
@@ -1402,7 +1395,9 @@ static int crypto4xx_probe(struct platform_device *ofdev)
core_dev->dev->core_dev = core_dev;
core_dev->dev->is_revb = is_revb;
core_dev->device = dev;
- mutex_init(&core_dev->rng_lock);
+ rc = devm_mutex_init(&ofdev->dev, &core_dev->rng_lock);
+ if (rc)
+ return rc;
spin_lock_init(&core_dev->lock);
INIT_LIST_HEAD(&core_dev->dev->alg_list);
ratelimit_default_init(&core_dev->dev->aead_ratelimit);
@@ -1421,21 +1416,21 @@ static int crypto4xx_probe(struct platform_device *ofdev)
tasklet_init(&core_dev->tasklet, crypto4xx_bh_tasklet_cb,
(unsigned long) dev);
- core_dev->dev->ce_base = of_iomap(ofdev->dev.of_node, 0);
- if (!core_dev->dev->ce_base) {
- dev_err(dev, "failed to of_iomap\n");
- rc = -ENOMEM;
- goto err_iomap;
+ core_dev->dev->ce_base = devm_platform_ioremap_resource(ofdev, 0);
+ if (IS_ERR(core_dev->dev->ce_base)) {
+ dev_err(&ofdev->dev, "failed to ioremap resource");
+ rc = PTR_ERR(core_dev->dev->ce_base);
+ goto err_build_sdr;
}
/* Register for Crypto isr, Crypto Engine IRQ */
core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
- rc = request_irq(core_dev->irq, is_revb ?
- crypto4xx_ce_interrupt_handler_revb :
- crypto4xx_ce_interrupt_handler, 0,
- KBUILD_MODNAME, dev);
+ rc = devm_request_irq(&ofdev->dev, core_dev->irq,
+ is_revb ? crypto4xx_ce_interrupt_handler_revb :
+ crypto4xx_ce_interrupt_handler,
+ 0, KBUILD_MODNAME, dev);
if (rc)
- goto err_request_irq;
+ goto err_iomap;
/* need to setup pdr, rdr, gdr and sdr before this */
crypto4xx_hw_init(core_dev->dev);
@@ -1444,26 +1439,17 @@ static int crypto4xx_probe(struct platform_device *ofdev)
rc = crypto4xx_register_alg(core_dev->dev, crypto4xx_alg,
ARRAY_SIZE(crypto4xx_alg));
if (rc)
- goto err_start_dev;
+ goto err_iomap;
ppc4xx_trng_probe(core_dev);
return 0;
-err_start_dev:
- free_irq(core_dev->irq, dev);
-err_request_irq:
- irq_dispose_mapping(core_dev->irq);
- iounmap(core_dev->dev->ce_base);
err_iomap:
tasklet_kill(&core_dev->tasklet);
err_build_sdr:
crypto4xx_destroy_sdr(core_dev->dev);
crypto4xx_destroy_gdr(core_dev->dev);
crypto4xx_destroy_pdr(core_dev->dev);
- kfree(core_dev->dev);
-err_alloc_dev:
- kfree(core_dev);
-
return rc;
}
@@ -1474,13 +1460,9 @@ static void crypto4xx_remove(struct platform_device *ofdev)
ppc4xx_trng_remove(core_dev);
- free_irq(core_dev->irq, dev);
- irq_dispose_mapping(core_dev->irq);
-
tasklet_kill(&core_dev->tasklet);
/* Un-register with Linux CryptoAPI */
crypto4xx_unregister_alg(core_dev->dev);
- mutex_destroy(&core_dev->rng_lock);
/* Free all allocated memory */
crypto4xx_stop_all(core_dev);
}
@@ -1497,7 +1479,7 @@ static struct platform_driver crypto4xx_driver = {
.of_match_table = crypto4xx_match,
},
.probe = crypto4xx_probe,
- .remove_new = crypto4xx_remove,
+ .remove = crypto4xx_remove,
};
module_platform_driver(crypto4xx_driver);
diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c
index f54ab0d0b1e8..1c18a5b8470e 100644
--- a/drivers/crypto/amlogic/amlogic-gxl-core.c
+++ b/drivers/crypto/amlogic/amlogic-gxl-core.c
@@ -240,11 +240,9 @@ static int meson_crypto_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mc);
mc->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(mc->base)) {
- err = PTR_ERR(mc->base);
- dev_err(&pdev->dev, "Cannot request MMIO err=%d\n", err);
- return err;
- }
+ if (IS_ERR(mc->base))
+ return PTR_ERR(mc->base);
+
mc->busclk = devm_clk_get(&pdev->dev, "blkmv");
if (IS_ERR(mc->busclk)) {
err = PTR_ERR(mc->busclk);
@@ -322,7 +320,7 @@ MODULE_DEVICE_TABLE(of, meson_crypto_of_match_table);
static struct platform_driver meson_crypto_driver = {
.probe = meson_crypto_probe,
- .remove_new = meson_crypto_remove,
+ .remove = meson_crypto_remove,
.driver = {
.name = "gxl-crypto",
.of_match_table = meson_crypto_of_match_table,
diff --git a/drivers/crypto/aspeed/aspeed-acry.c b/drivers/crypto/aspeed/aspeed-acry.c
index b4613bd4ad96..8d1c79aaca07 100644
--- a/drivers/crypto/aspeed/aspeed-acry.c
+++ b/drivers/crypto/aspeed/aspeed-acry.c
@@ -601,8 +601,6 @@ static struct aspeed_acry_alg aspeed_acry_akcipher_algs[] = {
.akcipher.base = {
.encrypt = aspeed_acry_rsa_enc,
.decrypt = aspeed_acry_rsa_dec,
- .sign = aspeed_acry_rsa_dec,
- .verify = aspeed_acry_rsa_enc,
.set_pub_key = aspeed_acry_rsa_set_pub_key,
.set_priv_key = aspeed_acry_rsa_set_priv_key,
.max_size = aspeed_acry_rsa_max_size,
@@ -808,7 +806,7 @@ MODULE_DEVICE_TABLE(of, aspeed_acry_of_matches);
static struct platform_driver aspeed_acry_driver = {
.probe = aspeed_acry_probe,
- .remove_new = aspeed_acry_remove,
+ .remove = aspeed_acry_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = aspeed_acry_of_matches,
diff --git a/drivers/crypto/aspeed/aspeed-hace.c b/drivers/crypto/aspeed/aspeed-hace.c
index 062f2a66dd23..3fe644bfe037 100644
--- a/drivers/crypto/aspeed/aspeed-hace.c
+++ b/drivers/crypto/aspeed/aspeed-hace.c
@@ -266,7 +266,7 @@ MODULE_DEVICE_TABLE(of, aspeed_hace_of_matches);
static struct platform_driver aspeed_hace_driver = {
.probe = aspeed_hace_probe,
- .remove_new = aspeed_hace_remove,
+ .remove = aspeed_hace_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = aspeed_hace_of_matches,
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 0dd90785db9a..14bf86957d31 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -2453,7 +2453,7 @@ static void atmel_aes_remove(struct platform_device *pdev)
static struct platform_driver atmel_aes_driver = {
.probe = atmel_aes_probe,
- .remove_new = atmel_aes_remove,
+ .remove = atmel_aes_remove,
.driver = {
.name = "atmel_aes",
.of_match_table = atmel_aes_dt_ids,
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 590ea984c622..0d48e64d28b1 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -379,7 +379,7 @@ MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids);
#endif
static const struct i2c_device_id atmel_ecc_id[] = {
- { "atecc508a", 0 },
+ { "atecc508a" },
{ }
};
MODULE_DEVICE_TABLE(i2c, atmel_ecc_id);
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 8cc57df25778..67a170608566 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -2691,7 +2691,7 @@ static void atmel_sha_remove(struct platform_device *pdev)
static struct platform_driver atmel_sha_driver = {
.probe = atmel_sha_probe,
- .remove_new = atmel_sha_remove,
+ .remove = atmel_sha_remove,
.driver = {
.name = "atmel_sha",
.of_match_table = atmel_sha_dt_ids,
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index a02d496f4c41..75bebec2c757 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -202,8 +202,8 @@ static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids);
static const struct i2c_device_id atmel_sha204a_id[] = {
- { "atsha204", 0 },
- { "atsha204a", 0 },
+ { "atsha204" },
+ { "atsha204a" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id);
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index dcc2380a5889..de9717e221e4 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -872,7 +872,7 @@ static void atmel_tdes_done_task(unsigned long data)
if (!err)
err = atmel_tdes_crypt_start(dd);
if (!err)
- return; /* DMA started. Not fininishing. */
+ return; /* DMA started. Not finishing. */
}
atmel_tdes_finish_req(dd, err);
@@ -1074,7 +1074,7 @@ static void atmel_tdes_remove(struct platform_device *pdev)
static struct platform_driver atmel_tdes_driver = {
.probe = atmel_tdes_probe,
- .remove_new = atmel_tdes_remove,
+ .remove = atmel_tdes_remove,
.driver = {
.name = "atmel_tdes",
.of_match_table = atmel_tdes_dt_ids,
diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c
index 75440ea6206e..1c1f57baef0e 100644
--- a/drivers/crypto/axis/artpec6_crypto.c
+++ b/drivers/crypto/axis/artpec6_crypto.c
@@ -2975,7 +2975,7 @@ static void artpec6_crypto_remove(struct platform_device *pdev)
static struct platform_driver artpec6_crypto_driver = {
.probe = artpec6_crypto_probe,
- .remove_new = artpec6_crypto_remove,
+ .remove = artpec6_crypto_remove,
.driver = {
.name = "artpec6-crypto",
.of_match_table = artpec6_crypto_of_match,
diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c
index 1a3ecd44cbaf..9e6798efbfb7 100644
--- a/drivers/crypto/bcm/cipher.c
+++ b/drivers/crypto/bcm/cipher.c
@@ -2415,6 +2415,7 @@ static int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key,
static int ahash_hmac_init(struct ahash_request *req)
{
+ int ret;
struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
@@ -2424,7 +2425,9 @@ static int ahash_hmac_init(struct ahash_request *req)
flow_log("ahash_hmac_init()\n");
/* init the context as a hash */
- ahash_init(req);
+ ret = ahash_init(req);
+ if (ret)
+ return ret;
if (!spu_no_incr_hash(ctx)) {
/* SPU-M can do incr hashing but needs sw for outer HMAC */
@@ -4704,7 +4707,7 @@ static struct platform_driver bcm_spu_pdriver = {
.of_match_table = of_match_ptr(bcm_spu_dt_ids),
},
.probe = bcm_spu_probe,
- .remove_new = bcm_spu_remove,
+ .remove = bcm_spu_remove,
};
module_platform_driver(bcm_spu_pdriver);
diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
index 887a5f2fb927..cb001aa1de66 100644
--- a/drivers/crypto/caam/caampkc.c
+++ b/drivers/crypto/caam/caampkc.c
@@ -984,7 +984,7 @@ err:
return -ENOMEM;
}
-static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
+static int caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
struct rsa_key *raw_key)
{
struct caam_rsa_key *rsa_key = &ctx->key;
@@ -994,7 +994,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
rsa_key->p = caam_read_raw_data(raw_key->p, &p_sz);
if (!rsa_key->p)
- return;
+ return -ENOMEM;
rsa_key->p_sz = p_sz;
rsa_key->q = caam_read_raw_data(raw_key->q, &q_sz);
@@ -1029,7 +1029,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
rsa_key->priv_form = FORM3;
- return;
+ return 0;
free_dq:
kfree_sensitive(rsa_key->dq);
@@ -1043,6 +1043,7 @@ free_q:
kfree_sensitive(rsa_key->q);
free_p:
kfree_sensitive(rsa_key->p);
+ return -ENOMEM;
}
static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
@@ -1088,7 +1089,9 @@ static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
rsa_key->e_sz = raw_key.e_sz;
rsa_key->n_sz = raw_key.n_sz;
- caam_rsa_set_priv_key_form(ctx, &raw_key);
+ ret = caam_rsa_set_priv_key_form(ctx, &raw_key);
+ if (ret)
+ goto err;
return 0;
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 26eba7de3fb0..9fcdb64084ac 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -819,7 +819,7 @@ static struct platform_driver caam_jr_driver = {
.pm = pm_ptr(&caam_jr_pm_ops),
},
.probe = caam_jr_probe,
- .remove_new = caam_jr_remove,
+ .remove = caam_jr_remove,
.shutdown = caam_jr_remove,
};
diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c
index f6111ee9ed34..7701d00bcb3a 100644
--- a/drivers/crypto/caam/qi.c
+++ b/drivers/crypto/caam/qi.c
@@ -733,7 +733,7 @@ static void free_caam_qi_pcpu_netdev(const cpumask_t *cpus)
int caam_qi_init(struct platform_device *caam_pdev)
{
int err, i;
- struct device *ctrldev = &caam_pdev->dev, *qidev;
+ struct device *qidev = &caam_pdev->dev;
struct caam_drv_private *ctrlpriv;
const cpumask_t *cpus = qman_affine_cpus();
cpumask_var_t clean_mask;
@@ -742,8 +742,7 @@ int caam_qi_init(struct platform_device *caam_pdev)
if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
goto fail_cpumask;
- ctrlpriv = dev_get_drvdata(ctrldev);
- qidev = ctrldev;
+ ctrlpriv = dev_get_drvdata(qidev);
/* Initialize the congestion detection */
err = init_cgr(qidev);
@@ -794,7 +793,7 @@ int caam_qi_init(struct platform_device *caam_pdev)
caam_debugfs_qi_init(ctrlpriv);
- err = devm_add_action_or_reset(qidev, caam_qi_shutdown, ctrlpriv);
+ err = devm_add_action_or_reset(qidev, caam_qi_shutdown, qidev);
if (err)
goto fail2;
diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c
index 6872ac344001..54de869e5374 100644
--- a/drivers/crypto/cavium/cpt/cptpf_main.c
+++ b/drivers/crypto/cavium/cpt/cptpf_main.c
@@ -44,7 +44,7 @@ static void cpt_disable_cores(struct cpt_device *cpt, u64 coremask,
dev_err(dev, "Cores still busy %llx", coremask);
grp = cpt_read_csr64(cpt->reg_base,
CPTX_PF_EXEC_BUSY(0));
- if (timeout--)
+ if (!timeout--)
break;
udelay(CSR_DELAY);
@@ -302,6 +302,8 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae)
ret = do_cpt_init(cpt, mcode);
if (ret) {
+ dma_free_coherent(&cpt->pdev->dev, mcode->code_size,
+ mcode->code, mcode->phys_base);
dev_err(dev, "do_cpt_init failed with ret: %d\n", ret);
goto fw_release;
}
@@ -394,7 +396,7 @@ static void cpt_disable_all_cores(struct cpt_device *cpt)
dev_err(dev, "Cores still busy");
grp = cpt_read_csr64(cpt->reg_base,
CPTX_PF_EXEC_BUSY(0));
- if (timeout--)
+ if (!timeout--)
break;
udelay(CSR_DELAY);
diff --git a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c
index 153004bdfb5c..fb59bb282455 100644
--- a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c
+++ b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c
@@ -238,7 +238,7 @@ static int send_cpt_command(struct cpt_vf *cptvf, union cpt_inst_s *cmd,
qinfo = &cptvf->cqinfo;
queue = &qinfo->queue[qno];
- /* lock commad queue */
+ /* lock command queue */
spin_lock(&queue->lock);
ent = &queue->qhead->head[queue->idx * qinfo->cmd_size];
memcpy(ent, (void *)cmd, qinfo->cmd_size);
@@ -510,7 +510,7 @@ get_pending_entry:
info->time_in = jiffies;
info->req = req;
- /* Create the CPT_INST_S type command for HW intrepretation */
+ /* Create the CPT_INST_S type command for HW interpretation */
cptinst.s.doneint = true;
cptinst.s.res_addr = (u64)info->comp_baddr;
cptinst.s.tag = 0;
diff --git a/drivers/crypto/cavium/nitrox/nitrox_lib.c b/drivers/crypto/cavium/nitrox/nitrox_lib.c
index a5cdc2b48bd6..068265207ddd 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_lib.c
+++ b/drivers/crypto/cavium/nitrox/nitrox_lib.c
@@ -17,7 +17,7 @@
#define CRYPTO_CTX_SIZE 256
-/* packet inuput ring alignments */
+/* packet input ring alignments */
#define PKTIN_Q_ALIGN_BYTES 16
/* AQM Queue input alignments */
#define AQM_Q_ALIGN_BYTES 32
diff --git a/drivers/crypto/ccp/sp-platform.c b/drivers/crypto/ccp/sp-platform.c
index ff6ceb4feee0..3933cac1694d 100644
--- a/drivers/crypto/ccp/sp-platform.c
+++ b/drivers/crypto/ccp/sp-platform.c
@@ -210,7 +210,7 @@ static struct platform_driver sp_platform_driver = {
.of_match_table = sp_of_match,
},
.probe = sp_platform_probe,
- .remove_new = sp_platform_remove,
+ .remove = sp_platform_remove,
#ifdef CONFIG_PM
.suspend = sp_platform_suspend,
.resume = sp_platform_resume,
diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c
index 5ef39d682389..81533681f7fb 100644
--- a/drivers/crypto/ccree/cc_aead.c
+++ b/drivers/crypto/ccree/cc_aead.c
@@ -2226,7 +2226,7 @@ static int cc_rfc4543_gcm_encrypt(struct aead_request *req)
memset(areq_ctx, 0, sizeof(*areq_ctx));
- //plaintext is not encryped with rfc4543
+ //plaintext is not encrypted with rfc4543
areq_ctx->plaintext_authenticate_only = true;
/* No generated IV required */
@@ -2277,7 +2277,7 @@ static int cc_rfc4543_gcm_decrypt(struct aead_request *req)
memset(areq_ctx, 0, sizeof(*areq_ctx));
- //plaintext is not decryped with rfc4543
+ //plaintext is not decrypted with rfc4543
areq_ctx->plaintext_authenticate_only = true;
/* No generated IV required */
diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c
index 3fb667a17bbb..d39c067672fd 100644
--- a/drivers/crypto/ccree/cc_cipher.c
+++ b/drivers/crypto/ccree/cc_cipher.c
@@ -179,7 +179,7 @@ static int cc_cipher_init(struct crypto_tfm *tfm)
}
max_key_buf_size <<= 1;
- /* Alloc fallabck tfm or essiv when key size != 256 bit */
+ /* Alloc fallback tfm or essiv when key size != 256 bit */
ctx_p->fallback_tfm =
crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ASYNC);
diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c
index 9177b54bb0f5..061e68a31c36 100644
--- a/drivers/crypto/ccree/cc_driver.c
+++ b/drivers/crypto/ccree/cc_driver.c
@@ -643,7 +643,7 @@ static struct platform_driver ccree_driver = {
#endif
},
.probe = ccree_probe,
- .remove_new = ccree_remove,
+ .remove = ccree_remove,
};
static int __init ccree_init(void)
diff --git a/drivers/crypto/ccree/cc_hash.c b/drivers/crypto/ccree/cc_hash.c
index f418162932fe..d0612bec4d58 100644
--- a/drivers/crypto/ccree/cc_hash.c
+++ b/drivers/crypto/ccree/cc_hash.c
@@ -1577,7 +1577,7 @@ struct cc_hash_template {
/* hash descriptors */
static struct cc_hash_template driver_hash[] = {
- //Asynchronize hash template
+ //Asynchronous hash template
{
.name = "sha1",
.driver_name = "sha1-ccree",
diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
index 177428480c7d..af37477ffd8d 100644
--- a/drivers/crypto/chelsio/chcr_algo.c
+++ b/drivers/crypto/chelsio/chcr_algo.c
@@ -1186,7 +1186,7 @@ static int chcr_handle_cipher_resp(struct skcipher_request *req,
else
bytes = rounddown(bytes, 16);
} else {
- /*CTR mode counter overfloa*/
+ /*CTR mode counter overflow*/
bytes = req->cryptlen - reqctx->processed;
}
err = chcr_update_cipher_iv(req, fw6_pld, reqctx->iv);
diff --git a/drivers/crypto/exynos-rng.c b/drivers/crypto/exynos-rng.c
index 0dd8baf16cb4..2aaa98f9b44e 100644
--- a/drivers/crypto/exynos-rng.c
+++ b/drivers/crypto/exynos-rng.c
@@ -389,7 +389,7 @@ static struct platform_driver exynos_rng_driver = {
.of_match_table = exynos_rng_dt_match,
},
.probe = exynos_rng_probe,
- .remove_new = exynos_rng_remove,
+ .remove = exynos_rng_remove,
};
module_platform_driver(exynos_rng_driver);
diff --git a/drivers/crypto/gemini/sl3516-ce-core.c b/drivers/crypto/gemini/sl3516-ce-core.c
index 1d1a889599bb..f7e0e3fea15c 100644
--- a/drivers/crypto/gemini/sl3516-ce-core.c
+++ b/drivers/crypto/gemini/sl3516-ce-core.c
@@ -528,7 +528,7 @@ MODULE_DEVICE_TABLE(of, sl3516_ce_crypto_of_match_table);
static struct platform_driver sl3516_ce_driver = {
.probe = sl3516_ce_probe,
- .remove_new = sl3516_ce_remove,
+ .remove = sl3516_ce_remove,
.driver = {
.name = "sl3516-crypto",
.pm = &sl3516_ce_pm_ops,
diff --git a/drivers/crypto/hisilicon/hpre/hpre.h b/drivers/crypto/hisilicon/hpre/hpre.h
index 9f0b94c8e03d..0f3ddbadbcf9 100644
--- a/drivers/crypto/hisilicon/hpre/hpre.h
+++ b/drivers/crypto/hisilicon/hpre/hpre.h
@@ -100,6 +100,29 @@ struct hpre_sqe {
__le32 rsvd1[_HPRE_SQE_ALIGN_EXT];
};
+enum hpre_cap_table_type {
+ QM_RAS_NFE_TYPE = 0x0,
+ QM_RAS_NFE_RESET,
+ QM_RAS_CE_TYPE,
+ HPRE_RAS_NFE_TYPE,
+ HPRE_RAS_NFE_RESET,
+ HPRE_RAS_CE_TYPE,
+ HPRE_CORE_INFO,
+ HPRE_CORE_EN,
+ HPRE_DRV_ALG_BITMAP,
+ HPRE_ALG_BITMAP,
+ HPRE_CORE1_BITMAP_CAP,
+ HPRE_CORE2_BITMAP_CAP,
+ HPRE_CORE3_BITMAP_CAP,
+ HPRE_CORE4_BITMAP_CAP,
+ HPRE_CORE5_BITMAP_CAP,
+ HPRE_CORE6_BITMAP_CAP,
+ HPRE_CORE7_BITMAP_CAP,
+ HPRE_CORE8_BITMAP_CAP,
+ HPRE_CORE9_BITMAP_CAP,
+ HPRE_CORE10_BITMAP_CAP,
+};
+
struct hisi_qp *hpre_create_qp(u8 type);
int hpre_algs_register(struct hisi_qm *qm);
void hpre_algs_unregister(struct hisi_qm *qm);
diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index c167dbd6c7d6..2a2910261210 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -2006,8 +2006,6 @@ static void hpre_curve25519_exit_tfm(struct crypto_kpp *tfm)
}
static struct akcipher_alg rsa = {
- .sign = hpre_rsa_dec,
- .verify = hpre_rsa_enc,
.encrypt = hpre_rsa_enc,
.decrypt = hpre_rsa_dec,
.set_pub_key = hpre_rsa_setpubkey,
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
index 6b536ad2ada5..96fde9437b4b 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
@@ -13,6 +13,7 @@
#include <linux/uacce.h>
#include "hpre.h"
+#define CAP_FILE_PERMISSION 0444
#define HPRE_CTRL_CNT_CLR_CE_BIT BIT(0)
#define HPRE_CTRL_CNT_CLR_CE 0x301000
#define HPRE_FSM_MAX_CNT 0x301008
@@ -203,7 +204,7 @@ static const struct hisi_qm_cap_info hpre_basic_info[] = {
{HPRE_RESET_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0xBFFC3E},
{HPRE_OOO_SHUTDOWN_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x22, 0xBFFC3E},
{HPRE_CE_MASK_CAP, 0x3138, 0, GENMASK(31, 0), 0x0, 0x1, 0x1},
- {HPRE_CLUSTER_NUM_CAP, 0x313c, 20, GENMASK(3, 0), 0x0, 0x4, 0x1},
+ {HPRE_CLUSTER_NUM_CAP, 0x313c, 20, GENMASK(3, 0), 0x0, 0x4, 0x1},
{HPRE_CORE_TYPE_NUM_CAP, 0x313c, 16, GENMASK(3, 0), 0x0, 0x2, 0x2},
{HPRE_CORE_NUM_CAP, 0x313c, 8, GENMASK(7, 0), 0x0, 0x8, 0xA},
{HPRE_CLUSTER_CORE_NUM_CAP, 0x313c, 0, GENMASK(7, 0), 0x0, 0x2, 0xA},
@@ -222,18 +223,27 @@ static const struct hisi_qm_cap_info hpre_basic_info[] = {
{HPRE_CORE10_ALG_BITMAP_CAP, 0x3170, 0, GENMASK(31, 0), 0x0, 0x10, 0x10}
};
-enum hpre_pre_store_cap_idx {
- HPRE_CLUSTER_NUM_CAP_IDX = 0x0,
- HPRE_CORE_ENABLE_BITMAP_CAP_IDX,
- HPRE_DRV_ALG_BITMAP_CAP_IDX,
- HPRE_DEV_ALG_BITMAP_CAP_IDX,
-};
-
-static const u32 hpre_pre_store_caps[] = {
- HPRE_CLUSTER_NUM_CAP,
- HPRE_CORE_ENABLE_BITMAP_CAP,
- HPRE_DRV_ALG_BITMAP_CAP,
- HPRE_DEV_ALG_BITMAP_CAP,
+static const struct hisi_qm_cap_query_info hpre_cap_query_info[] = {
+ {QM_RAS_NFE_TYPE, "QM_RAS_NFE_TYPE ", 0x3124, 0x0, 0x1C37, 0x7C37},
+ {QM_RAS_NFE_RESET, "QM_RAS_NFE_RESET ", 0x3128, 0x0, 0xC77, 0x6C77},
+ {QM_RAS_CE_TYPE, "QM_RAS_CE_TYPE ", 0x312C, 0x0, 0x8, 0x8},
+ {HPRE_RAS_NFE_TYPE, "HPRE_RAS_NFE_TYPE ", 0x3130, 0x0, 0x3FFFFE, 0x1FFFC3E},
+ {HPRE_RAS_NFE_RESET, "HPRE_RAS_NFE_RESET ", 0x3134, 0x0, 0x3FFFFE, 0xBFFC3E},
+ {HPRE_RAS_CE_TYPE, "HPRE_RAS_CE_TYPE ", 0x3138, 0x0, 0x1, 0x1},
+ {HPRE_CORE_INFO, "HPRE_CORE_INFO ", 0x313c, 0x0, 0x420802, 0x120A0A},
+ {HPRE_CORE_EN, "HPRE_CORE_EN ", 0x3140, 0x0, 0xF, 0x3FF},
+ {HPRE_DRV_ALG_BITMAP, "HPRE_DRV_ALG_BITMAP ", 0x3144, 0x0, 0x03, 0x27},
+ {HPRE_ALG_BITMAP, "HPRE_ALG_BITMAP ", 0x3148, 0x0, 0x03, 0x7F},
+ {HPRE_CORE1_BITMAP_CAP, "HPRE_CORE1_BITMAP_CAP ", 0x314c, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE2_BITMAP_CAP, "HPRE_CORE2_BITMAP_CAP ", 0x3150, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE3_BITMAP_CAP, "HPRE_CORE3_BITMAP_CAP ", 0x3154, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE4_BITMAP_CAP, "HPRE_CORE4_BITMAP_CAP ", 0x3158, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE5_BITMAP_CAP, "HPRE_CORE5_BITMAP_CAP ", 0x315c, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE6_BITMAP_CAP, "HPRE_CORE6_BITMAP_CAP ", 0x3160, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE7_BITMAP_CAP, "HPRE_CORE7_BITMAP_CAP ", 0x3164, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE8_BITMAP_CAP, "HPRE_CORE8_BITMAP_CAP ", 0x3168, 0x0, 0x7F, 0x7F},
+ {HPRE_CORE9_BITMAP_CAP, "HPRE_CORE9_BITMAP_CAP ", 0x316c, 0x0, 0x10, 0x10},
+ {HPRE_CORE10_BITMAP_CAP, "HPRE_CORE10_BITMAP_CAP ", 0x3170, 0x0, 0x10, 0x10},
};
static const struct hpre_hw_error hpre_hw_errors[] = {
@@ -360,7 +370,7 @@ bool hpre_check_alg_support(struct hisi_qm *qm, u32 alg)
{
u32 cap_val;
- cap_val = qm->cap_tables.dev_cap_table[HPRE_DRV_ALG_BITMAP_CAP_IDX].cap_val;
+ cap_val = qm->cap_tables.dev_cap_table[HPRE_DRV_ALG_BITMAP].cap_val;
if (alg & cap_val)
return true;
@@ -415,7 +425,7 @@ static int pf_q_num_set(const char *val, const struct kernel_param *kp)
{
pf_q_num_flag = true;
- return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_HPRE_PF);
+ return hisi_qm_q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_HPRE_PF);
}
static const struct kernel_param_ops hpre_pf_q_num_ops = {
@@ -503,14 +513,17 @@ static int hpre_cfg_by_dsm(struct hisi_qm *qm)
static int hpre_set_cluster(struct hisi_qm *qm)
{
struct device *dev = &qm->pdev->dev;
- unsigned long offset;
u32 cluster_core_mask;
+ unsigned long offset;
+ u32 hpre_core_info;
u8 clusters_num;
u32 val = 0;
int ret, i;
- cluster_core_mask = qm->cap_tables.dev_cap_table[HPRE_CORE_ENABLE_BITMAP_CAP_IDX].cap_val;
- clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val;
+ cluster_core_mask = qm->cap_tables.dev_cap_table[HPRE_CORE_EN].cap_val;
+ hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
for (i = 0; i < clusters_num; i++) {
offset = i * HPRE_CLSTR_ADDR_INTRVL;
@@ -593,6 +606,9 @@ static void hpre_close_sva_prefetch(struct hisi_qm *qm)
static void hpre_enable_clock_gate(struct hisi_qm *qm)
{
+ unsigned long offset;
+ u8 clusters_num, i;
+ u32 hpre_core_info;
u32 val;
if (qm->ver < QM_HW_V3)
@@ -606,17 +622,26 @@ static void hpre_enable_clock_gate(struct hisi_qm *qm)
val |= HPRE_PEH_CFG_AUTO_GATE_EN;
writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE);
- val = readl(qm->io_base + HPRE_CLUSTER_DYN_CTL);
- val |= HPRE_CLUSTER_DYN_CTL_EN;
- writel(val, qm->io_base + HPRE_CLUSTER_DYN_CTL);
-
- val = readl_relaxed(qm->io_base + HPRE_CORE_SHB_CFG);
- val |= HPRE_CORE_GATE_EN;
- writel(val, qm->io_base + HPRE_CORE_SHB_CFG);
+ hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
+ for (i = 0; i < clusters_num; i++) {
+ offset = (unsigned long)i * HPRE_CLSTR_ADDR_INTRVL;
+ val = readl(qm->io_base + offset + HPRE_CLUSTER_DYN_CTL);
+ val |= HPRE_CLUSTER_DYN_CTL_EN;
+ writel(val, qm->io_base + offset + HPRE_CLUSTER_DYN_CTL);
+
+ val = readl(qm->io_base + offset + HPRE_CORE_SHB_CFG);
+ val |= HPRE_CORE_GATE_EN;
+ writel(val, qm->io_base + offset + HPRE_CORE_SHB_CFG);
+ }
}
static void hpre_disable_clock_gate(struct hisi_qm *qm)
{
+ unsigned long offset;
+ u8 clusters_num, i;
+ u32 hpre_core_info;
u32 val;
if (qm->ver < QM_HW_V3)
@@ -630,13 +655,19 @@ static void hpre_disable_clock_gate(struct hisi_qm *qm)
val &= ~HPRE_PEH_CFG_AUTO_GATE_EN;
writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE);
- val = readl(qm->io_base + HPRE_CLUSTER_DYN_CTL);
- val &= ~HPRE_CLUSTER_DYN_CTL_EN;
- writel(val, qm->io_base + HPRE_CLUSTER_DYN_CTL);
-
- val = readl_relaxed(qm->io_base + HPRE_CORE_SHB_CFG);
- val &= ~HPRE_CORE_GATE_EN;
- writel(val, qm->io_base + HPRE_CORE_SHB_CFG);
+ hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
+ for (i = 0; i < clusters_num; i++) {
+ offset = (unsigned long)i * HPRE_CLSTR_ADDR_INTRVL;
+ val = readl(qm->io_base + offset + HPRE_CLUSTER_DYN_CTL);
+ val &= ~HPRE_CLUSTER_DYN_CTL_EN;
+ writel(val, qm->io_base + offset + HPRE_CLUSTER_DYN_CTL);
+
+ val = readl(qm->io_base + offset + HPRE_CORE_SHB_CFG);
+ val &= ~HPRE_CORE_GATE_EN;
+ writel(val, qm->io_base + offset + HPRE_CORE_SHB_CFG);
+ }
}
static int hpre_set_user_domain_and_cache(struct hisi_qm *qm)
@@ -699,11 +730,14 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm)
static void hpre_cnt_regs_clear(struct hisi_qm *qm)
{
unsigned long offset;
+ u32 hpre_core_info;
u8 clusters_num;
int i;
/* clear clusterX/cluster_ctrl */
- clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val;
+ hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
for (i = 0; i < clusters_num; i++) {
offset = HPRE_CLSTR_BASE + i * HPRE_CLSTR_ADDR_INTRVL;
writel(0x0, qm->io_base + offset + HPRE_CLUSTER_INQURY);
@@ -995,10 +1029,13 @@ static int hpre_cluster_debugfs_init(struct hisi_qm *qm)
char buf[HPRE_DBGFS_VAL_MAX_LEN];
struct debugfs_regset32 *regset;
struct dentry *tmp_d;
+ u32 hpre_core_info;
u8 clusters_num;
int i, ret;
- clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val;
+ hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
for (i = 0; i < clusters_num; i++) {
ret = snprintf(buf, HPRE_DBGFS_VAL_MAX_LEN, "cluster%d", i);
if (ret >= HPRE_DBGFS_VAL_MAX_LEN)
@@ -1041,6 +1078,26 @@ static int hpre_ctrl_debug_init(struct hisi_qm *qm)
return hpre_cluster_debugfs_init(qm);
}
+static int hpre_cap_regs_show(struct seq_file *s, void *unused)
+{
+ struct hisi_qm *qm = s->private;
+ u32 i, size;
+
+ size = qm->cap_tables.qm_cap_size;
+ for (i = 0; i < size; i++)
+ seq_printf(s, "%s= 0x%08x\n", qm->cap_tables.qm_cap_table[i].name,
+ qm->cap_tables.qm_cap_table[i].cap_val);
+
+ size = qm->cap_tables.dev_cap_size;
+ for (i = 0; i < size; i++)
+ seq_printf(s, "%s= 0x%08x\n", qm->cap_tables.dev_cap_table[i].name,
+ qm->cap_tables.dev_cap_table[i].cap_val);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(hpre_cap_regs);
+
static void hpre_dfx_debug_init(struct hisi_qm *qm)
{
struct dfx_diff_registers *hpre_regs = qm->debug.acc_diff_regs;
@@ -1059,6 +1116,9 @@ static void hpre_dfx_debug_init(struct hisi_qm *qm)
if (qm->fun_type == QM_HW_PF && hpre_regs)
debugfs_create_file("diff_regs", 0444, parent,
qm, &hpre_diff_regs_fops);
+
+ debugfs_create_file("cap_regs", CAP_FILE_PERMISSION,
+ qm->debug.debug_root, qm, &hpre_cap_regs_fops);
}
static int hpre_debugfs_init(struct hisi_qm *qm)
@@ -1106,26 +1166,33 @@ static int hpre_pre_store_cap_reg(struct hisi_qm *qm)
{
struct hisi_qm_cap_record *hpre_cap;
struct device *dev = &qm->pdev->dev;
+ u32 hpre_core_info;
+ u8 clusters_num;
size_t i, size;
- size = ARRAY_SIZE(hpre_pre_store_caps);
+ size = ARRAY_SIZE(hpre_cap_query_info);
hpre_cap = devm_kzalloc(dev, sizeof(*hpre_cap) * size, GFP_KERNEL);
if (!hpre_cap)
return -ENOMEM;
for (i = 0; i < size; i++) {
- hpre_cap[i].type = hpre_pre_store_caps[i];
- hpre_cap[i].cap_val = hisi_qm_get_hw_info(qm, hpre_basic_info,
- hpre_pre_store_caps[i], qm->cap_ver);
+ hpre_cap[i].type = hpre_cap_query_info[i].type;
+ hpre_cap[i].name = hpre_cap_query_info[i].name;
+ hpre_cap[i].cap_val = hisi_qm_get_cap_value(qm, hpre_cap_query_info,
+ i, qm->cap_ver);
}
- if (hpre_cap[HPRE_CLUSTER_NUM_CAP_IDX].cap_val > HPRE_CLUSTERS_NUM_MAX) {
+ hpre_core_info = hpre_cap[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
+ if (clusters_num > HPRE_CLUSTERS_NUM_MAX) {
dev_err(dev, "Device cluster num %u is out of range for driver supports %d!\n",
- hpre_cap[HPRE_CLUSTER_NUM_CAP_IDX].cap_val, HPRE_CLUSTERS_NUM_MAX);
+ clusters_num, HPRE_CLUSTERS_NUM_MAX);
return -EINVAL;
}
qm->cap_tables.dev_cap_table = hpre_cap;
+ qm->cap_tables.dev_cap_size = size;
return 0;
}
@@ -1172,7 +1239,7 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
return ret;
}
- alg_msk = qm->cap_tables.dev_cap_table[HPRE_DEV_ALG_BITMAP_CAP_IDX].cap_val;
+ alg_msk = qm->cap_tables.dev_cap_table[HPRE_ALG_BITMAP].cap_val;
ret = hisi_qm_set_algs(qm, alg_msk, hpre_dev_algs, ARRAY_SIZE(hpre_dev_algs));
if (ret) {
pci_err(pdev, "Failed to set hpre algs!\n");
@@ -1188,10 +1255,13 @@ static int hpre_show_last_regs_init(struct hisi_qm *qm)
int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs);
struct qm_debug *debug = &qm->debug;
void __iomem *io_base;
+ u32 hpre_core_info;
u8 clusters_num;
int i, j, idx;
- clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val;
+ hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
debug->last_words = kcalloc(cluster_dfx_regs_num * clusters_num +
com_dfx_regs_num, sizeof(unsigned int), GFP_KERNEL);
if (!debug->last_words)
@@ -1231,6 +1301,7 @@ static void hpre_show_last_dfx_regs(struct hisi_qm *qm)
struct qm_debug *debug = &qm->debug;
struct pci_dev *pdev = qm->pdev;
void __iomem *io_base;
+ u32 hpre_core_info;
u8 clusters_num;
int i, j, idx;
u32 val;
@@ -1246,7 +1317,9 @@ static void hpre_show_last_dfx_regs(struct hisi_qm *qm)
hpre_com_dfx_regs[i].name, debug->last_words[i], val);
}
- clusters_num = qm->cap_tables.dev_cap_table[HPRE_CLUSTER_NUM_CAP_IDX].cap_val;
+ hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val;
+ clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) &
+ hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask;
for (i = 0; i < clusters_num; i++) {
io_base = qm->io_base + hpre_cluster_offsets[i];
for (j = 0; j < cluster_dfx_regs_num; j++) {
@@ -1280,11 +1353,15 @@ static u32 hpre_get_hw_err_status(struct hisi_qm *qm)
static void hpre_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)
{
- u32 nfe;
-
writel(err_sts, qm->io_base + HPRE_HAC_SOURCE_INT);
- nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver);
- writel(nfe, qm->io_base + HPRE_RAS_NFE_ENB);
+}
+
+static void hpre_disable_error_report(struct hisi_qm *qm, u32 err_type)
+{
+ u32 nfe_mask;
+
+ nfe_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver);
+ writel(nfe_mask & (~err_type), qm->io_base + HPRE_RAS_NFE_ENB);
}
static void hpre_open_axi_master_ooo(struct hisi_qm *qm)
@@ -1298,6 +1375,27 @@ static void hpre_open_axi_master_ooo(struct hisi_qm *qm)
qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB);
}
+static enum acc_err_result hpre_get_err_result(struct hisi_qm *qm)
+{
+ u32 err_status;
+
+ err_status = hpre_get_hw_err_status(qm);
+ if (err_status) {
+ if (err_status & qm->err_info.ecc_2bits_mask)
+ qm->err_status.is_dev_ecc_mbit = true;
+ hpre_log_hw_error(qm, err_status);
+
+ if (err_status & qm->err_info.dev_reset_mask) {
+ /* Disable the same error reporting until device is recovered. */
+ hpre_disable_error_report(qm, err_status);
+ return ACC_ERR_NEED_RESET;
+ }
+ hpre_clear_hw_err_status(qm, err_status);
+ }
+
+ return ACC_ERR_RECOVERED;
+}
+
static void hpre_err_info_init(struct hisi_qm *qm)
{
struct hisi_qm_err_info *err_info = &qm->err_info;
@@ -1324,12 +1422,12 @@ static const struct hisi_qm_err_ini hpre_err_ini = {
.hw_err_disable = hpre_hw_error_disable,
.get_dev_hw_err_status = hpre_get_hw_err_status,
.clear_dev_hw_err_status = hpre_clear_hw_err_status,
- .log_dev_hw_err = hpre_log_hw_error,
.open_axi_master_ooo = hpre_open_axi_master_ooo,
.open_sva_prefetch = hpre_open_sva_prefetch,
.close_sva_prefetch = hpre_close_sva_prefetch,
.show_last_dfx_regs = hpre_show_last_dfx_regs,
.err_info_init = hpre_err_info_init,
+ .get_err_result = hpre_get_err_result,
};
static int hpre_pf_probe_init(struct hpre *hpre)
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index 07983af9e3e2..19c1b5d3c954 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -271,12 +271,6 @@ enum vft_type {
SHAPER_VFT,
};
-enum acc_err_result {
- ACC_ERR_NONE,
- ACC_ERR_NEED_RESET,
- ACC_ERR_RECOVERED,
-};
-
enum qm_alg_type {
ALG_TYPE_0,
ALG_TYPE_1,
@@ -307,11 +301,29 @@ enum qm_basic_type {
QM_VF_IRQ_NUM_CAP,
};
-enum qm_pre_store_cap_idx {
- QM_EQ_IRQ_TYPE_CAP_IDX = 0x0,
- QM_AEQ_IRQ_TYPE_CAP_IDX,
- QM_ABN_IRQ_TYPE_CAP_IDX,
- QM_PF2VF_IRQ_TYPE_CAP_IDX,
+enum qm_cap_table_type {
+ QM_CAP_VF = 0x0,
+ QM_AEQE_NUM,
+ QM_SCQE_NUM,
+ QM_EQ_IRQ,
+ QM_AEQ_IRQ,
+ QM_ABNORMAL_IRQ,
+ QM_MB_IRQ,
+ MAX_IRQ_NUM,
+ EXT_BAR_INDEX,
+};
+
+static const struct hisi_qm_cap_query_info qm_cap_query_info[] = {
+ {QM_CAP_VF, "QM_CAP_VF ", 0x3100, 0x0, 0x0, 0x6F01},
+ {QM_AEQE_NUM, "QM_AEQE_NUM ", 0x3104, 0x800, 0x4000800, 0x4000800},
+ {QM_SCQE_NUM, "QM_SCQE_NUM ",
+ 0x3108, 0x4000400, 0x4000400, 0x4000400},
+ {QM_EQ_IRQ, "QM_EQ_IRQ ", 0x310c, 0x10000, 0x10000, 0x10000},
+ {QM_AEQ_IRQ, "QM_AEQ_IRQ ", 0x3110, 0x0, 0x10001, 0x10001},
+ {QM_ABNORMAL_IRQ, "QM_ABNORMAL_IRQ ", 0x3114, 0x0, 0x10003, 0x10003},
+ {QM_MB_IRQ, "QM_MB_IRQ ", 0x3118, 0x0, 0x0, 0x10002},
+ {MAX_IRQ_NUM, "MAX_IRQ_NUM ", 0x311c, 0x10001, 0x40002, 0x40003},
+ {EXT_BAR_INDEX, "EXT_BAR_INDEX ", 0x3120, 0x0, 0x0, 0x14},
};
static const struct hisi_qm_cap_info qm_cap_info_comm[] = {
@@ -344,13 +356,6 @@ static const struct hisi_qm_cap_info qm_basic_info[] = {
{QM_VF_IRQ_NUM_CAP, 0x311c, 0, GENMASK(15, 0), 0x1, 0x2, 0x3},
};
-static const u32 qm_pre_store_caps[] = {
- QM_EQ_IRQ_TYPE_CAP,
- QM_AEQ_IRQ_TYPE_CAP,
- QM_ABN_IRQ_TYPE_CAP,
- QM_PF2VF_IRQ_TYPE_CAP,
-};
-
struct qm_mailbox {
__le16 w0;
__le16 queue_num;
@@ -451,6 +456,37 @@ static struct qm_typical_qos_table shaper_cbs_s[] = {
static void qm_irqs_unregister(struct hisi_qm *qm);
static int qm_reset_device(struct hisi_qm *qm);
+int hisi_qm_q_num_set(const char *val, const struct kernel_param *kp,
+ unsigned int device)
+{
+ struct pci_dev *pdev;
+ u32 n, q_num;
+ int ret;
+
+ if (!val)
+ return -EINVAL;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, device, NULL);
+ if (!pdev) {
+ q_num = min_t(u32, QM_QNUM_V1, QM_QNUM_V2);
+ pr_info("No device found currently, suppose queue number is %u\n",
+ q_num);
+ } else {
+ if (pdev->revision == QM_HW_V1)
+ q_num = QM_QNUM_V1;
+ else
+ q_num = QM_QNUM_V2;
+
+ pci_dev_put(pdev);
+ }
+
+ ret = kstrtou32(val, 10, &n);
+ if (ret || n < QM_MIN_QNUM || n > q_num)
+ return -EINVAL;
+
+ return param_set_int(val, kp);
+}
+EXPORT_SYMBOL_GPL(hisi_qm_q_num_set);
static u32 qm_get_hw_error_status(struct hisi_qm *qm)
{
@@ -763,6 +799,27 @@ u32 hisi_qm_get_hw_info(struct hisi_qm *qm,
}
EXPORT_SYMBOL_GPL(hisi_qm_get_hw_info);
+u32 hisi_qm_get_cap_value(struct hisi_qm *qm,
+ const struct hisi_qm_cap_query_info *info_table,
+ u32 index, bool is_read)
+{
+ u32 val;
+
+ switch (qm->ver) {
+ case QM_HW_V1:
+ return info_table[index].v1_val;
+ case QM_HW_V2:
+ return info_table[index].v2_val;
+ default:
+ if (!is_read)
+ return info_table[index].v3_val;
+
+ val = readl(qm->io_base + info_table[index].offset);
+ return val;
+ }
+}
+EXPORT_SYMBOL_GPL(hisi_qm_get_cap_value);
+
static void qm_get_xqc_depth(struct hisi_qm *qm, u16 *low_bits,
u16 *high_bits, enum qm_basic_type type)
{
@@ -1425,22 +1482,25 @@ static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status)
static enum acc_err_result qm_hw_error_handle_v2(struct hisi_qm *qm)
{
- u32 error_status, tmp;
-
- /* read err sts */
- tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS);
- error_status = qm->error_mask & tmp;
+ u32 error_status;
- if (error_status) {
+ error_status = qm_get_hw_error_status(qm);
+ if (error_status & qm->error_mask) {
if (error_status & QM_ECC_MBIT)
qm->err_status.is_qm_ecc_mbit = true;
qm_log_hw_error(qm, error_status);
- if (error_status & qm->err_info.qm_reset_mask)
+ if (error_status & qm->err_info.qm_reset_mask) {
+ /* Disable the same error reporting until device is recovered. */
+ writel(qm->err_info.nfe & (~error_status),
+ qm->io_base + QM_RAS_NFE_ENABLE);
return ACC_ERR_NEED_RESET;
+ }
+ /* Clear error source if not need reset. */
writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE);
writel(qm->err_info.nfe, qm->io_base + QM_RAS_NFE_ENABLE);
+ writel(qm->err_info.ce, qm->io_base + QM_RAS_CE_ENABLE);
}
return ACC_ERR_RECOVERED;
@@ -3861,30 +3921,12 @@ EXPORT_SYMBOL_GPL(hisi_qm_sriov_configure);
static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm)
{
- u32 err_sts;
-
- if (!qm->err_ini->get_dev_hw_err_status) {
- dev_err(&qm->pdev->dev, "Device doesn't support get hw error status!\n");
+ if (!qm->err_ini->get_err_result) {
+ dev_err(&qm->pdev->dev, "Device doesn't support reset!\n");
return ACC_ERR_NONE;
}
- /* get device hardware error status */
- err_sts = qm->err_ini->get_dev_hw_err_status(qm);
- if (err_sts) {
- if (err_sts & qm->err_info.ecc_2bits_mask)
- qm->err_status.is_dev_ecc_mbit = true;
-
- if (qm->err_ini->log_dev_hw_err)
- qm->err_ini->log_dev_hw_err(qm, err_sts);
-
- if (err_sts & qm->err_info.dev_reset_mask)
- return ACC_ERR_NEED_RESET;
-
- if (qm->err_ini->clear_dev_hw_err_status)
- qm->err_ini->clear_dev_hw_err_status(qm, err_sts);
- }
-
- return ACC_ERR_RECOVERED;
+ return qm->err_ini->get_err_result(qm);
}
static enum acc_err_result qm_process_dev_error(struct hisi_qm *qm)
@@ -4866,7 +4908,7 @@ static void qm_unregister_abnormal_irq(struct hisi_qm *qm)
if (qm->fun_type == QM_HW_VF)
return;
- val = qm->cap_tables.qm_cap_table[QM_ABN_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_ABNORMAL_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_ABN_IRQ_TYPE_MASK))
return;
@@ -4883,7 +4925,7 @@ static int qm_register_abnormal_irq(struct hisi_qm *qm)
if (qm->fun_type == QM_HW_VF)
return 0;
- val = qm->cap_tables.qm_cap_table[QM_ABN_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_ABNORMAL_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_ABN_IRQ_TYPE_MASK))
return 0;
@@ -4900,7 +4942,7 @@ static void qm_unregister_mb_cmd_irq(struct hisi_qm *qm)
struct pci_dev *pdev = qm->pdev;
u32 irq_vector, val;
- val = qm->cap_tables.qm_cap_table[QM_PF2VF_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_MB_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK))
return;
@@ -4914,7 +4956,7 @@ static int qm_register_mb_cmd_irq(struct hisi_qm *qm)
u32 irq_vector, val;
int ret;
- val = qm->cap_tables.qm_cap_table[QM_PF2VF_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_MB_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK))
return 0;
@@ -4931,7 +4973,7 @@ static void qm_unregister_aeq_irq(struct hisi_qm *qm)
struct pci_dev *pdev = qm->pdev;
u32 irq_vector, val;
- val = qm->cap_tables.qm_cap_table[QM_AEQ_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_AEQ_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK))
return;
@@ -4945,7 +4987,7 @@ static int qm_register_aeq_irq(struct hisi_qm *qm)
u32 irq_vector, val;
int ret;
- val = qm->cap_tables.qm_cap_table[QM_AEQ_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_AEQ_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK))
return 0;
@@ -4963,7 +5005,7 @@ static void qm_unregister_eq_irq(struct hisi_qm *qm)
struct pci_dev *pdev = qm->pdev;
u32 irq_vector, val;
- val = qm->cap_tables.qm_cap_table[QM_EQ_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_EQ_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK))
return;
@@ -4977,7 +5019,7 @@ static int qm_register_eq_irq(struct hisi_qm *qm)
u32 irq_vector, val;
int ret;
- val = qm->cap_tables.qm_cap_table[QM_EQ_IRQ_TYPE_CAP_IDX].cap_val;
+ val = qm->cap_tables.qm_cap_table[QM_EQ_IRQ].cap_val;
if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK))
return 0;
@@ -5065,24 +5107,26 @@ static int qm_get_qp_num(struct hisi_qm *qm)
return 0;
}
-static int qm_pre_store_irq_type_caps(struct hisi_qm *qm)
+static int qm_pre_store_caps(struct hisi_qm *qm)
{
struct hisi_qm_cap_record *qm_cap;
struct pci_dev *pdev = qm->pdev;
size_t i, size;
- size = ARRAY_SIZE(qm_pre_store_caps);
+ size = ARRAY_SIZE(qm_cap_query_info);
qm_cap = devm_kzalloc(&pdev->dev, sizeof(*qm_cap) * size, GFP_KERNEL);
if (!qm_cap)
return -ENOMEM;
for (i = 0; i < size; i++) {
- qm_cap[i].type = qm_pre_store_caps[i];
- qm_cap[i].cap_val = hisi_qm_get_hw_info(qm, qm_basic_info,
- qm_pre_store_caps[i], qm->cap_ver);
+ qm_cap[i].type = qm_cap_query_info[i].type;
+ qm_cap[i].name = qm_cap_query_info[i].name;
+ qm_cap[i].cap_val = hisi_qm_get_cap_value(qm, qm_cap_query_info,
+ i, qm->cap_ver);
}
qm->cap_tables.qm_cap_table = qm_cap;
+ qm->cap_tables.qm_cap_size = size;
return 0;
}
@@ -5119,8 +5163,8 @@ static int qm_get_hw_caps(struct hisi_qm *qm)
set_bit(cap_info[i].type, &qm->caps);
}
- /* Fetch and save the value of irq type related capability registers */
- return qm_pre_store_irq_type_caps(qm);
+ /* Fetch and save the value of qm capability registers */
+ return qm_pre_store_caps(qm);
}
static int qm_get_pci_res(struct hisi_qm *qm)
diff --git a/drivers/crypto/hisilicon/sec/sec_drv.c b/drivers/crypto/hisilicon/sec/sec_drv.c
index 9bafcc5aa404..ef0cb733c92c 100644
--- a/drivers/crypto/hisilicon/sec/sec_drv.c
+++ b/drivers/crypto/hisilicon/sec/sec_drv.c
@@ -1304,7 +1304,7 @@ MODULE_DEVICE_TABLE(acpi, sec_acpi_match);
static struct platform_driver sec_driver = {
.probe = sec_probe,
- .remove_new = sec_remove,
+ .remove = sec_remove,
.driver = {
.name = "hisi_sec_platform_driver",
.of_match_table = sec_match,
diff --git a/drivers/crypto/hisilicon/sec2/sec.h b/drivers/crypto/hisilicon/sec2/sec.h
index 410c83712e28..356188bee6fb 100644
--- a/drivers/crypto/hisilicon/sec2/sec.h
+++ b/drivers/crypto/hisilicon/sec2/sec.h
@@ -220,11 +220,27 @@ enum sec_cap_type {
SEC_CORE4_ALG_BITMAP_HIGH,
};
-enum sec_cap_reg_record_idx {
- SEC_DRV_ALG_BITMAP_LOW_IDX = 0x0,
- SEC_DRV_ALG_BITMAP_HIGH_IDX,
- SEC_DEV_ALG_BITMAP_LOW_IDX,
- SEC_DEV_ALG_BITMAP_HIGH_IDX,
+enum sec_cap_table_type {
+ QM_RAS_NFE_TYPE = 0x0,
+ QM_RAS_NFE_RESET,
+ QM_RAS_CE_TYPE,
+ SEC_RAS_NFE_TYPE,
+ SEC_RAS_NFE_RESET,
+ SEC_RAS_CE_TYPE,
+ SEC_CORE_INFO,
+ SEC_CORE_EN,
+ SEC_DRV_ALG_BITMAP_LOW_TB,
+ SEC_DRV_ALG_BITMAP_HIGH_TB,
+ SEC_ALG_BITMAP_LOW,
+ SEC_ALG_BITMAP_HIGH,
+ SEC_CORE1_BITMAP_LOW,
+ SEC_CORE1_BITMAP_HIGH,
+ SEC_CORE2_BITMAP_LOW,
+ SEC_CORE2_BITMAP_HIGH,
+ SEC_CORE3_BITMAP_LOW,
+ SEC_CORE3_BITMAP_HIGH,
+ SEC_CORE4_BITMAP_LOW,
+ SEC_CORE4_BITMAP_HIGH,
};
void sec_destroy_qps(struct hisi_qp **qps, int qp_num);
diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c
index 0558f98e221f..ae9ebbb4103d 100644
--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c
+++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c
@@ -2520,8 +2520,8 @@ int sec_register_to_crypto(struct hisi_qm *qm)
u64 alg_mask;
int ret = 0;
- alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_IDX,
- SEC_DRV_ALG_BITMAP_LOW_IDX);
+ alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_TB,
+ SEC_DRV_ALG_BITMAP_LOW_TB);
mutex_lock(&sec_algs_lock);
if (sec_available_devs) {
@@ -2553,8 +2553,8 @@ void sec_unregister_from_crypto(struct hisi_qm *qm)
{
u64 alg_mask;
- alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_IDX,
- SEC_DRV_ALG_BITMAP_LOW_IDX);
+ alg_mask = sec_get_alg_bitmap(qm, SEC_DRV_ALG_BITMAP_HIGH_TB,
+ SEC_DRV_ALG_BITMAP_LOW_TB);
mutex_lock(&sec_algs_lock);
if (--sec_available_devs)
diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c
index c35533d8930b..8ec5333bb5aa 100644
--- a/drivers/crypto/hisilicon/sec2/sec_main.c
+++ b/drivers/crypto/hisilicon/sec2/sec_main.c
@@ -14,9 +14,9 @@
#include <linux/seq_file.h>
#include <linux/topology.h>
#include <linux/uacce.h>
-
#include "sec.h"
+#define CAP_FILE_PERMISSION 0444
#define SEC_VF_NUM 63
#define SEC_QUEUE_NUM_V1 4096
#define PCI_DEVICE_ID_HUAWEI_SEC_PF 0xa255
@@ -167,11 +167,34 @@ static const struct hisi_qm_cap_info sec_basic_info[] = {
{SEC_CORE4_ALG_BITMAP_HIGH, 0x3170, 0, GENMASK(31, 0), 0x3FFF, 0x3FFF, 0x3FFF},
};
-static const u32 sec_pre_store_caps[] = {
- SEC_DRV_ALG_BITMAP_LOW,
- SEC_DRV_ALG_BITMAP_HIGH,
- SEC_DEV_ALG_BITMAP_LOW,
- SEC_DEV_ALG_BITMAP_HIGH,
+static const struct hisi_qm_cap_query_info sec_cap_query_info[] = {
+ {QM_RAS_NFE_TYPE, "QM_RAS_NFE_TYPE ", 0x3124, 0x0, 0x1C77, 0x7C77},
+ {QM_RAS_NFE_RESET, "QM_RAS_NFE_RESET ", 0x3128, 0x0, 0xC77, 0x6C77},
+ {QM_RAS_CE_TYPE, "QM_RAS_CE_TYPE ", 0x312C, 0x0, 0x8, 0x8},
+ {SEC_RAS_NFE_TYPE, "SEC_RAS_NFE_TYPE ", 0x3130, 0x0, 0x177, 0x60177},
+ {SEC_RAS_NFE_RESET, "SEC_RAS_NFE_RESET ", 0x3134, 0x0, 0x177, 0x177},
+ {SEC_RAS_CE_TYPE, "SEC_RAS_CE_TYPE ", 0x3138, 0x0, 0x88, 0xC088},
+ {SEC_CORE_INFO, "SEC_CORE_INFO ", 0x313c, 0x110404, 0x110404, 0x110404},
+ {SEC_CORE_EN, "SEC_CORE_EN ", 0x3140, 0x17F, 0x17F, 0xF},
+ {SEC_DRV_ALG_BITMAP_LOW_TB, "SEC_DRV_ALG_BITMAP_LOW ",
+ 0x3144, 0x18050CB, 0x18050CB, 0x18670CF},
+ {SEC_DRV_ALG_BITMAP_HIGH_TB, "SEC_DRV_ALG_BITMAP_HIGH ",
+ 0x3148, 0x395C, 0x395C, 0x395C},
+ {SEC_ALG_BITMAP_LOW, "SEC_ALG_BITMAP_LOW ",
+ 0x314c, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ {SEC_ALG_BITMAP_HIGH, "SEC_ALG_BITMAP_HIGH ", 0x3150, 0x3FFF, 0x3FFF, 0x3FFF},
+ {SEC_CORE1_BITMAP_LOW, "SEC_CORE1_BITMAP_LOW ",
+ 0x3154, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ {SEC_CORE1_BITMAP_HIGH, "SEC_CORE1_BITMAP_HIGH ", 0x3158, 0x3FFF, 0x3FFF, 0x3FFF},
+ {SEC_CORE2_BITMAP_LOW, "SEC_CORE2_BITMAP_LOW ",
+ 0x315c, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ {SEC_CORE2_BITMAP_HIGH, "SEC_CORE2_BITMAP_HIGH ", 0x3160, 0x3FFF, 0x3FFF, 0x3FFF},
+ {SEC_CORE3_BITMAP_LOW, "SEC_CORE3_BITMAP_LOW ",
+ 0x3164, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ {SEC_CORE3_BITMAP_HIGH, "SEC_CORE3_BITMAP_HIGH ", 0x3168, 0x3FFF, 0x3FFF, 0x3FFF},
+ {SEC_CORE4_BITMAP_LOW, "SEC_CORE4_BITMAP_LOW ",
+ 0x316c, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ {SEC_CORE4_BITMAP_HIGH, "SEC_CORE4_BITMAP_HIGH ", 0x3170, 0x3FFF, 0x3FFF, 0x3FFF},
};
static const struct qm_dev_alg sec_dev_algs[] = { {
@@ -322,7 +345,7 @@ static int sec_pf_q_num_set(const char *val, const struct kernel_param *kp)
{
pf_q_num_flag = true;
- return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_SEC_PF);
+ return hisi_qm_q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_SEC_PF);
}
static const struct kernel_param_ops sec_pf_q_num_ops = {
@@ -838,6 +861,26 @@ static int sec_regs_show(struct seq_file *s, void *unused)
DEFINE_SHOW_ATTRIBUTE(sec_regs);
+static int sec_cap_regs_show(struct seq_file *s, void *unused)
+{
+ struct hisi_qm *qm = s->private;
+ u32 i, size;
+
+ size = qm->cap_tables.qm_cap_size;
+ for (i = 0; i < size; i++)
+ seq_printf(s, "%s= 0x%08x\n", qm->cap_tables.qm_cap_table[i].name,
+ qm->cap_tables.qm_cap_table[i].cap_val);
+
+ size = qm->cap_tables.dev_cap_size;
+ for (i = 0; i < size; i++)
+ seq_printf(s, "%s= 0x%08x\n", qm->cap_tables.dev_cap_table[i].name,
+ qm->cap_tables.dev_cap_table[i].cap_val);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(sec_cap_regs);
+
static int sec_core_debug_init(struct hisi_qm *qm)
{
struct dfx_diff_registers *sec_regs = qm->debug.acc_diff_regs;
@@ -872,6 +915,9 @@ static int sec_core_debug_init(struct hisi_qm *qm)
tmp_d, data, &sec_atomic64_ops);
}
+ debugfs_create_file("cap_regs", CAP_FILE_PERMISSION,
+ qm->debug.debug_root, qm, &sec_cap_regs_fops);
+
return 0;
}
@@ -1010,11 +1056,15 @@ static u32 sec_get_hw_err_status(struct hisi_qm *qm)
static void sec_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)
{
- u32 nfe;
-
writel(err_sts, qm->io_base + SEC_CORE_INT_SOURCE);
- nfe = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver);
- writel(nfe, qm->io_base + SEC_RAS_NFE_REG);
+}
+
+static void sec_disable_error_report(struct hisi_qm *qm, u32 err_type)
+{
+ u32 nfe_mask;
+
+ nfe_mask = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver);
+ writel(nfe_mask & (~err_type), qm->io_base + SEC_RAS_NFE_REG);
}
static void sec_open_axi_master_ooo(struct hisi_qm *qm)
@@ -1026,6 +1076,27 @@ static void sec_open_axi_master_ooo(struct hisi_qm *qm)
writel(val | SEC_AXI_SHUTDOWN_ENABLE, qm->io_base + SEC_CONTROL_REG);
}
+static enum acc_err_result sec_get_err_result(struct hisi_qm *qm)
+{
+ u32 err_status;
+
+ err_status = sec_get_hw_err_status(qm);
+ if (err_status) {
+ if (err_status & qm->err_info.ecc_2bits_mask)
+ qm->err_status.is_dev_ecc_mbit = true;
+ sec_log_hw_error(qm, err_status);
+
+ if (err_status & qm->err_info.dev_reset_mask) {
+ /* Disable the same error reporting until device is recovered. */
+ sec_disable_error_report(qm, err_status);
+ return ACC_ERR_NEED_RESET;
+ }
+ sec_clear_hw_err_status(qm, err_status);
+ }
+
+ return ACC_ERR_RECOVERED;
+}
+
static void sec_err_info_init(struct hisi_qm *qm)
{
struct hisi_qm_err_info *err_info = &qm->err_info;
@@ -1052,12 +1123,12 @@ static const struct hisi_qm_err_ini sec_err_ini = {
.hw_err_disable = sec_hw_error_disable,
.get_dev_hw_err_status = sec_get_hw_err_status,
.clear_dev_hw_err_status = sec_clear_hw_err_status,
- .log_dev_hw_err = sec_log_hw_error,
.open_axi_master_ooo = sec_open_axi_master_ooo,
.open_sva_prefetch = sec_open_sva_prefetch,
.close_sva_prefetch = sec_close_sva_prefetch,
.show_last_dfx_regs = sec_show_last_dfx_regs,
.err_info_init = sec_err_info_init,
+ .get_err_result = sec_get_err_result,
};
static int sec_pf_probe_init(struct sec_dev *sec)
@@ -1085,18 +1156,20 @@ static int sec_pre_store_cap_reg(struct hisi_qm *qm)
struct pci_dev *pdev = qm->pdev;
size_t i, size;
- size = ARRAY_SIZE(sec_pre_store_caps);
+ size = ARRAY_SIZE(sec_cap_query_info);
sec_cap = devm_kzalloc(&pdev->dev, sizeof(*sec_cap) * size, GFP_KERNEL);
if (!sec_cap)
return -ENOMEM;
for (i = 0; i < size; i++) {
- sec_cap[i].type = sec_pre_store_caps[i];
- sec_cap[i].cap_val = hisi_qm_get_hw_info(qm, sec_basic_info,
- sec_pre_store_caps[i], qm->cap_ver);
+ sec_cap[i].type = sec_cap_query_info[i].type;
+ sec_cap[i].name = sec_cap_query_info[i].name;
+ sec_cap[i].cap_val = hisi_qm_get_cap_value(qm, sec_cap_query_info,
+ i, qm->cap_ver);
}
qm->cap_tables.dev_cap_table = sec_cap;
+ qm->cap_tables.dev_cap_size = size;
return 0;
}
@@ -1146,8 +1219,7 @@ static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
hisi_qm_uninit(qm);
return ret;
}
-
- alg_msk = sec_get_alg_bitmap(qm, SEC_DEV_ALG_BITMAP_HIGH_IDX, SEC_DEV_ALG_BITMAP_LOW_IDX);
+ alg_msk = sec_get_alg_bitmap(qm, SEC_ALG_BITMAP_HIGH, SEC_ALG_BITMAP_LOW);
ret = hisi_qm_set_algs(qm, alg_msk, sec_dev_algs, ARRAY_SIZE(sec_dev_algs));
if (ret) {
pci_err(qm->pdev, "Failed to set sec algs!\n");
diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilicon/trng/trng.c
index 66c551ecdee8..ac74df4a9471 100644
--- a/drivers/crypto/hisilicon/trng/trng.c
+++ b/drivers/crypto/hisilicon/trng/trng.c
@@ -324,7 +324,7 @@ MODULE_DEVICE_TABLE(acpi, hisi_trng_acpi_match);
static struct platform_driver hisi_trng_driver = {
.probe = hisi_trng_probe,
- .remove_new = hisi_trng_remove,
+ .remove = hisi_trng_remove,
.driver = {
.name = "hisi-trng-v2",
.acpi_match_table = ACPI_PTR(hisi_trng_acpi_match),
diff --git a/drivers/crypto/hisilicon/zip/zip.h b/drivers/crypto/hisilicon/zip/zip.h
index f2e6da3240ae..2fecf346c3c9 100644
--- a/drivers/crypto/hisilicon/zip/zip.h
+++ b/drivers/crypto/hisilicon/zip/zip.h
@@ -81,6 +81,24 @@ struct hisi_zip_sqe {
u32 rsvd1[4];
};
+enum zip_cap_table_type {
+ QM_RAS_NFE_TYPE,
+ QM_RAS_NFE_RESET,
+ QM_RAS_CE_TYPE,
+ ZIP_RAS_NFE_TYPE,
+ ZIP_RAS_NFE_RESET,
+ ZIP_RAS_CE_TYPE,
+ ZIP_CORE_INFO,
+ ZIP_CORE_EN,
+ ZIP_DRV_ALG_BITMAP_TB,
+ ZIP_ALG_BITMAP,
+ ZIP_CORE1_BITMAP,
+ ZIP_CORE2_BITMAP,
+ ZIP_CORE3_BITMAP,
+ ZIP_CORE4_BITMAP,
+ ZIP_CORE5_BITMAP,
+};
+
int zip_create_qps(struct hisi_qp **qps, int qp_num, int node);
int hisi_zip_register_to_crypto(struct hisi_qm *qm);
void hisi_zip_unregister_from_crypto(struct hisi_qm *qm);
diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c
index d07e47b48be0..9239b251c2d7 100644
--- a/drivers/crypto/hisilicon/zip/zip_main.c
+++ b/drivers/crypto/hisilicon/zip/zip_main.c
@@ -14,6 +14,7 @@
#include <linux/uacce.h>
#include "zip.h"
+#define CAP_FILE_PERMISSION 0444
#define PCI_DEVICE_ID_HUAWEI_ZIP_PF 0xa250
#define HZIP_QUEUE_NUM_V1 4096
@@ -250,24 +251,22 @@ static struct hisi_qm_cap_info zip_basic_cap_info[] = {
{ZIP_CAP_MAX, 0x317c, 0, GENMASK(0, 0), 0x0, 0x0, 0x0}
};
-enum zip_pre_store_cap_idx {
- ZIP_CORE_NUM_CAP_IDX = 0x0,
- ZIP_CLUSTER_COMP_NUM_CAP_IDX,
- ZIP_CLUSTER_DECOMP_NUM_CAP_IDX,
- ZIP_DECOMP_ENABLE_BITMAP_IDX,
- ZIP_COMP_ENABLE_BITMAP_IDX,
- ZIP_DRV_ALG_BITMAP_IDX,
- ZIP_DEV_ALG_BITMAP_IDX,
-};
-
-static const u32 zip_pre_store_caps[] = {
- ZIP_CORE_NUM_CAP,
- ZIP_CLUSTER_COMP_NUM_CAP,
- ZIP_CLUSTER_DECOMP_NUM_CAP,
- ZIP_DECOMP_ENABLE_BITMAP,
- ZIP_COMP_ENABLE_BITMAP,
- ZIP_DRV_ALG_BITMAP,
- ZIP_DEV_ALG_BITMAP,
+static const struct hisi_qm_cap_query_info zip_cap_query_info[] = {
+ {QM_RAS_NFE_TYPE, "QM_RAS_NFE_TYPE ", 0x3124, 0x0, 0x1C57, 0x7C77},
+ {QM_RAS_NFE_RESET, "QM_RAS_NFE_RESET ", 0x3128, 0x0, 0xC57, 0x6C77},
+ {QM_RAS_CE_TYPE, "QM_RAS_CE_TYPE ", 0x312C, 0x0, 0x8, 0x8},
+ {ZIP_RAS_NFE_TYPE, "ZIP_RAS_NFE_TYPE ", 0x3130, 0x0, 0x7FE, 0x1FFE},
+ {ZIP_RAS_NFE_RESET, "ZIP_RAS_NFE_RESET ", 0x3134, 0x0, 0x7FE, 0x7FE},
+ {ZIP_RAS_CE_TYPE, "ZIP_RAS_CE_TYPE ", 0x3138, 0x0, 0x1, 0x1},
+ {ZIP_CORE_INFO, "ZIP_CORE_INFO ", 0x313C, 0x12080206, 0x12080206, 0x12050203},
+ {ZIP_CORE_EN, "ZIP_CORE_EN ", 0x3140, 0xFC0003, 0xFC0003, 0x1C0003},
+ {ZIP_DRV_ALG_BITMAP_TB, "ZIP_DRV_ALG_BITMAP ", 0x3144, 0x0, 0x0, 0x30},
+ {ZIP_ALG_BITMAP, "ZIP_ALG_BITMAP ", 0x3148, 0xF, 0xF, 0x3F},
+ {ZIP_CORE1_BITMAP, "ZIP_CORE1_BITMAP ", 0x314C, 0x5, 0x5, 0xD5},
+ {ZIP_CORE2_BITMAP, "ZIP_CORE2_BITMAP ", 0x3150, 0x5, 0x5, 0xD5},
+ {ZIP_CORE3_BITMAP, "ZIP_CORE3_BITMAP ", 0x3154, 0xA, 0xA, 0x2A},
+ {ZIP_CORE4_BITMAP, "ZIP_CORE4_BITMAP ", 0x3158, 0xA, 0xA, 0x2A},
+ {ZIP_CORE5_BITMAP, "ZIP_CORE5_BITMAP ", 0x315C, 0xA, 0xA, 0x2A},
};
static const struct debugfs_reg32 hzip_dfx_regs[] = {
@@ -402,7 +401,7 @@ static int pf_q_num_set(const char *val, const struct kernel_param *kp)
{
pf_q_num_flag = true;
- return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_ZIP_PF);
+ return hisi_qm_q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_ZIP_PF);
}
static const struct kernel_param_ops pf_q_num_ops = {
@@ -442,7 +441,7 @@ bool hisi_zip_alg_support(struct hisi_qm *qm, u32 alg)
{
u32 cap_val;
- cap_val = qm->cap_tables.dev_cap_table[ZIP_DRV_ALG_BITMAP_IDX].cap_val;
+ cap_val = qm->cap_tables.dev_cap_table[ZIP_DRV_ALG_BITMAP_TB].cap_val;
if ((alg & cap_val) == alg)
return true;
@@ -530,6 +529,7 @@ static int hisi_zip_set_user_domain_and_cache(struct hisi_qm *qm)
{
void __iomem *base = qm->io_base;
u32 dcomp_bm, comp_bm;
+ u32 zip_core_en;
/* qm user domain */
writel(AXUSER_BASE, base + QM_ARUSER_M_CFG_1);
@@ -567,8 +567,12 @@ static int hisi_zip_set_user_domain_and_cache(struct hisi_qm *qm)
}
/* let's open all compression/decompression cores */
- dcomp_bm = qm->cap_tables.dev_cap_table[ZIP_DECOMP_ENABLE_BITMAP_IDX].cap_val;
- comp_bm = qm->cap_tables.dev_cap_table[ZIP_COMP_ENABLE_BITMAP_IDX].cap_val;
+
+ zip_core_en = qm->cap_tables.dev_cap_table[ZIP_CORE_EN].cap_val;
+ dcomp_bm = (zip_core_en >> zip_basic_cap_info[ZIP_DECOMP_ENABLE_BITMAP].shift) &
+ zip_basic_cap_info[ZIP_DECOMP_ENABLE_BITMAP].mask;
+ comp_bm = (zip_core_en >> zip_basic_cap_info[ZIP_COMP_ENABLE_BITMAP].shift) &
+ zip_basic_cap_info[ZIP_COMP_ENABLE_BITMAP].mask;
writel(HZIP_DECOMP_CHECK_ENABLE | dcomp_bm | comp_bm, base + HZIP_CLOCK_GATE_CTRL);
/* enable sqc,cqc writeback */
@@ -788,7 +792,12 @@ DEFINE_SHOW_ATTRIBUTE(hisi_zip_regs);
static void __iomem *get_zip_core_addr(struct hisi_qm *qm, int core_num)
{
- u32 zip_comp_core_num = qm->cap_tables.dev_cap_table[ZIP_CLUSTER_COMP_NUM_CAP_IDX].cap_val;
+ u8 zip_comp_core_num;
+ u32 zip_core_info;
+
+ zip_core_info = qm->cap_tables.dev_cap_table[ZIP_CORE_INFO].cap_val;
+ zip_comp_core_num = (zip_core_info >> zip_basic_cap_info[ZIP_CLUSTER_COMP_NUM_CAP].shift) &
+ zip_basic_cap_info[ZIP_CLUSTER_COMP_NUM_CAP].mask;
if (core_num < zip_comp_core_num)
return qm->io_base + HZIP_CORE_DFX_BASE +
@@ -803,12 +812,16 @@ static int hisi_zip_core_debug_init(struct hisi_qm *qm)
u32 zip_core_num, zip_comp_core_num;
struct device *dev = &qm->pdev->dev;
struct debugfs_regset32 *regset;
+ u32 zip_core_info;
struct dentry *tmp_d;
char buf[HZIP_BUF_SIZE];
int i;
- zip_core_num = qm->cap_tables.dev_cap_table[ZIP_CORE_NUM_CAP_IDX].cap_val;
- zip_comp_core_num = qm->cap_tables.dev_cap_table[ZIP_CLUSTER_COMP_NUM_CAP_IDX].cap_val;
+ zip_core_info = qm->cap_tables.dev_cap_table[ZIP_CORE_INFO].cap_val;
+ zip_core_num = (zip_core_info >> zip_basic_cap_info[ZIP_CORE_NUM_CAP].shift) &
+ zip_basic_cap_info[ZIP_CORE_NUM_CAP].mask;
+ zip_comp_core_num = (zip_core_info >> zip_basic_cap_info[ZIP_CLUSTER_COMP_NUM_CAP].shift) &
+ zip_basic_cap_info[ZIP_CLUSTER_COMP_NUM_CAP].mask;
for (i = 0; i < zip_core_num; i++) {
if (i < zip_comp_core_num)
@@ -834,6 +847,26 @@ static int hisi_zip_core_debug_init(struct hisi_qm *qm)
return 0;
}
+static int zip_cap_regs_show(struct seq_file *s, void *unused)
+{
+ struct hisi_qm *qm = s->private;
+ u32 i, size;
+
+ size = qm->cap_tables.qm_cap_size;
+ for (i = 0; i < size; i++)
+ seq_printf(s, "%s= 0x%08x\n", qm->cap_tables.qm_cap_table[i].name,
+ qm->cap_tables.qm_cap_table[i].cap_val);
+
+ size = qm->cap_tables.dev_cap_size;
+ for (i = 0; i < size; i++)
+ seq_printf(s, "%s= 0x%08x\n", qm->cap_tables.dev_cap_table[i].name,
+ qm->cap_tables.dev_cap_table[i].cap_val);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(zip_cap_regs);
+
static void hisi_zip_dfx_debug_init(struct hisi_qm *qm)
{
struct dfx_diff_registers *hzip_regs = qm->debug.acc_diff_regs;
@@ -854,6 +887,9 @@ static void hisi_zip_dfx_debug_init(struct hisi_qm *qm)
if (qm->fun_type == QM_HW_PF && hzip_regs)
debugfs_create_file("diff_regs", 0444, tmp_dir,
qm, &hzip_diff_regs_fops);
+
+ debugfs_create_file("cap_regs", CAP_FILE_PERMISSION,
+ qm->debug.debug_root, qm, &zip_cap_regs_fops);
}
static int hisi_zip_ctrl_debug_init(struct hisi_qm *qm)
@@ -912,9 +948,14 @@ debugfs_remove:
/* hisi_zip_debug_regs_clear() - clear the zip debug regs */
static void hisi_zip_debug_regs_clear(struct hisi_qm *qm)
{
- u32 zip_core_num = qm->cap_tables.dev_cap_table[ZIP_CORE_NUM_CAP_IDX].cap_val;
+ u32 zip_core_info;
+ u8 zip_core_num;
int i, j;
+ zip_core_info = qm->cap_tables.dev_cap_table[ZIP_CORE_INFO].cap_val;
+ zip_core_num = (zip_core_info >> zip_basic_cap_info[ZIP_CORE_NUM_CAP].shift) &
+ zip_basic_cap_info[ZIP_CORE_NUM_CAP].mask;
+
/* enable register read_clear bit */
writel(HZIP_RD_CNT_CLR_CE_EN, qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE);
for (i = 0; i < zip_core_num; i++)
@@ -946,10 +987,13 @@ static int hisi_zip_show_last_regs_init(struct hisi_qm *qm)
int com_dfx_regs_num = ARRAY_SIZE(hzip_com_dfx_regs);
struct qm_debug *debug = &qm->debug;
void __iomem *io_base;
+ u32 zip_core_info;
u32 zip_core_num;
int i, j, idx;
- zip_core_num = qm->cap_tables.dev_cap_table[ZIP_CORE_NUM_CAP_IDX].cap_val;
+ zip_core_info = qm->cap_tables.dev_cap_table[ZIP_CORE_INFO].cap_val;
+ zip_core_num = (zip_core_info >> zip_basic_cap_info[ZIP_CORE_NUM_CAP].shift) &
+ zip_basic_cap_info[ZIP_CORE_NUM_CAP].mask;
debug->last_words = kcalloc(core_dfx_regs_num * zip_core_num + com_dfx_regs_num,
sizeof(unsigned int), GFP_KERNEL);
@@ -991,6 +1035,7 @@ static void hisi_zip_show_last_dfx_regs(struct hisi_qm *qm)
u32 zip_core_num, zip_comp_core_num;
struct qm_debug *debug = &qm->debug;
char buf[HZIP_BUF_SIZE];
+ u32 zip_core_info;
void __iomem *base;
int i, j, idx;
u32 val;
@@ -1005,8 +1050,11 @@ static void hisi_zip_show_last_dfx_regs(struct hisi_qm *qm)
hzip_com_dfx_regs[i].name, debug->last_words[i], val);
}
- zip_core_num = qm->cap_tables.dev_cap_table[ZIP_CORE_NUM_CAP_IDX].cap_val;
- zip_comp_core_num = qm->cap_tables.dev_cap_table[ZIP_CLUSTER_COMP_NUM_CAP_IDX].cap_val;
+ zip_core_info = qm->cap_tables.dev_cap_table[ZIP_CORE_INFO].cap_val;
+ zip_core_num = (zip_core_info >> zip_basic_cap_info[ZIP_CORE_NUM_CAP].shift) &
+ zip_basic_cap_info[ZIP_CORE_NUM_CAP].mask;
+ zip_comp_core_num = (zip_core_info >> zip_basic_cap_info[ZIP_CLUSTER_COMP_NUM_CAP].shift) &
+ zip_basic_cap_info[ZIP_CLUSTER_COMP_NUM_CAP].mask;
for (i = 0; i < zip_core_num; i++) {
if (i < zip_comp_core_num)
@@ -1059,11 +1107,15 @@ static u32 hisi_zip_get_hw_err_status(struct hisi_qm *qm)
static void hisi_zip_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)
{
- u32 nfe;
-
writel(err_sts, qm->io_base + HZIP_CORE_INT_SOURCE);
- nfe = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver);
- writel(nfe, qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB);
+}
+
+static void hisi_zip_disable_error_report(struct hisi_qm *qm, u32 err_type)
+{
+ u32 nfe_mask;
+
+ nfe_mask = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver);
+ writel(nfe_mask & (~err_type), qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB);
}
static void hisi_zip_open_axi_master_ooo(struct hisi_qm *qm)
@@ -1093,6 +1145,27 @@ static void hisi_zip_close_axi_master_ooo(struct hisi_qm *qm)
qm->io_base + HZIP_CORE_INT_SET);
}
+static enum acc_err_result hisi_zip_get_err_result(struct hisi_qm *qm)
+{
+ u32 err_status;
+
+ err_status = hisi_zip_get_hw_err_status(qm);
+ if (err_status) {
+ if (err_status & qm->err_info.ecc_2bits_mask)
+ qm->err_status.is_dev_ecc_mbit = true;
+ hisi_zip_log_hw_error(qm, err_status);
+
+ if (err_status & qm->err_info.dev_reset_mask) {
+ /* Disable the same error reporting until device is recovered. */
+ hisi_zip_disable_error_report(qm, err_status);
+ return ACC_ERR_NEED_RESET;
+ }
+ hisi_zip_clear_hw_err_status(qm, err_status);
+ }
+
+ return ACC_ERR_RECOVERED;
+}
+
static void hisi_zip_err_info_init(struct hisi_qm *qm)
{
struct hisi_qm_err_info *err_info = &qm->err_info;
@@ -1120,13 +1193,13 @@ static const struct hisi_qm_err_ini hisi_zip_err_ini = {
.hw_err_disable = hisi_zip_hw_error_disable,
.get_dev_hw_err_status = hisi_zip_get_hw_err_status,
.clear_dev_hw_err_status = hisi_zip_clear_hw_err_status,
- .log_dev_hw_err = hisi_zip_log_hw_error,
.open_axi_master_ooo = hisi_zip_open_axi_master_ooo,
.close_axi_master_ooo = hisi_zip_close_axi_master_ooo,
.open_sva_prefetch = hisi_zip_open_sva_prefetch,
.close_sva_prefetch = hisi_zip_close_sva_prefetch,
.show_last_dfx_regs = hisi_zip_show_last_dfx_regs,
.err_info_init = hisi_zip_err_info_init,
+ .get_err_result = hisi_zip_get_err_result,
};
static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip)
@@ -1167,18 +1240,20 @@ static int zip_pre_store_cap_reg(struct hisi_qm *qm)
struct pci_dev *pdev = qm->pdev;
size_t i, size;
- size = ARRAY_SIZE(zip_pre_store_caps);
+ size = ARRAY_SIZE(zip_cap_query_info);
zip_cap = devm_kzalloc(&pdev->dev, sizeof(*zip_cap) * size, GFP_KERNEL);
if (!zip_cap)
return -ENOMEM;
for (i = 0; i < size; i++) {
- zip_cap[i].type = zip_pre_store_caps[i];
- zip_cap[i].cap_val = hisi_qm_get_hw_info(qm, zip_basic_cap_info,
- zip_pre_store_caps[i], qm->cap_ver);
+ zip_cap[i].type = zip_cap_query_info[i].type;
+ zip_cap[i].name = zip_cap_query_info[i].name;
+ zip_cap[i].cap_val = hisi_qm_get_cap_value(qm, zip_cap_query_info,
+ i, qm->cap_ver);
}
qm->cap_tables.dev_cap_table = zip_cap;
+ qm->cap_tables.dev_cap_size = size;
return 0;
}
@@ -1230,7 +1305,7 @@ static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
return ret;
}
- alg_msk = qm->cap_tables.dev_cap_table[ZIP_DEV_ALG_BITMAP_IDX].cap_val;
+ alg_msk = qm->cap_tables.dev_cap_table[ZIP_ALG_BITMAP].cap_val;
ret = hisi_qm_set_algs(qm, alg_msk, zip_dev_algs, ARRAY_SIZE(zip_dev_algs));
if (ret) {
pci_err(qm->pdev, "Failed to set zip algs!\n");
diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c
index 7e93159c3b6b..1dc2378aa88b 100644
--- a/drivers/crypto/img-hash.c
+++ b/drivers/crypto/img-hash.c
@@ -1084,7 +1084,7 @@ static const struct dev_pm_ops img_hash_pm_ops = {
static struct platform_driver img_hash_driver = {
.probe = img_hash_probe,
- .remove_new = img_hash_remove,
+ .remove = img_hash_remove,
.driver = {
.name = "img-hash-accelerator",
.pm = &img_hash_pm_ops,
diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
index f5c1912aa564..45758c7aa80e 100644
--- a/drivers/crypto/inside-secure/safexcel.c
+++ b/drivers/crypto/inside-secure/safexcel.c
@@ -1868,7 +1868,7 @@ MODULE_DEVICE_TABLE(of, safexcel_of_match_table);
static struct platform_driver crypto_safexcel = {
.probe = safexcel_probe,
- .remove_new = safexcel_remove,
+ .remove = safexcel_remove,
.driver = {
.name = "crypto-safexcel",
.of_match_table = safexcel_of_match_table,
diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c
index e17577b785c3..f44c08f5f5ec 100644
--- a/drivers/crypto/inside-secure/safexcel_hash.c
+++ b/drivers/crypto/inside-secure/safexcel_hash.c
@@ -2093,7 +2093,7 @@ static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
safexcel_ahash_cra_init(tfm);
ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL);
- return PTR_ERR_OR_ZERO(ctx->aes);
+ return ctx->aes == NULL ? -ENOMEM : 0;
}
static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c
index 237f87000070..8fced88d3d06 100644
--- a/drivers/crypto/intel/iaa/iaa_crypto_main.c
+++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c
@@ -945,12 +945,22 @@ static inline int check_completion(struct device *dev,
bool only_once)
{
char *op_str = compress ? "compress" : "decompress";
+ int status_checks = 0;
int ret = 0;
while (!comp->status) {
if (only_once)
return -EAGAIN;
cpu_relax();
+ if (status_checks++ >= IAA_COMPLETION_TIMEOUT) {
+ /* Something is wrong with the hw, disable it. */
+ dev_err(dev, "%s completion timed out - "
+ "assuming broken hw, iaa_crypto now DISABLED\n",
+ op_str);
+ iaa_crypto_enabled = false;
+ ret = -ETIMEDOUT;
+ goto out;
+ }
}
if (comp->status != IAX_COMP_SUCCESS) {
diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
index f8a77bff8844..449c6d3ab2db 100644
--- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
+++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
@@ -1588,7 +1588,7 @@ static const struct of_device_id ixp4xx_crypto_of_match[] = {
static struct platform_driver ixp_crypto_driver = {
.probe = ixp_crypto_probe,
- .remove_new = ixp_crypto_remove,
+ .remove = ixp_crypto_remove,
.driver = {
.name = "ixp4xx_crypto",
.of_match_table = ixp4xx_crypto_of_match,
diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c
index 9b2d098e5eb2..8a8f6c81e010 100644
--- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c
+++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c
@@ -1656,7 +1656,7 @@ list_del:
/* The OCS driver is a platform device. */
static struct platform_driver kmb_ocs_aes_driver = {
.probe = kmb_ocs_aes_probe,
- .remove_new = kmb_ocs_aes_remove,
+ .remove = kmb_ocs_aes_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = kmb_ocs_aes_of_match,
diff --git a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c
index 5e24f2d8affc..59308926399d 100644
--- a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c
+++ b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c
@@ -991,7 +991,7 @@ static const struct of_device_id kmb_ocs_ecc_of_match[] = {
/* The OCS driver is a platform device. */
static struct platform_driver kmb_ocs_ecc_driver = {
.probe = kmb_ocs_ecc_probe,
- .remove_new = kmb_ocs_ecc_remove,
+ .remove = kmb_ocs_ecc_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = kmb_ocs_ecc_of_match,
diff --git a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
index e54c79890d44..95dc8979918d 100644
--- a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
+++ b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
@@ -1243,7 +1243,7 @@ list_del:
/* The OCS driver is a platform device. */
static struct platform_driver kmb_ocs_hcu_driver = {
.probe = kmb_ocs_hcu_probe,
- .remove_new = kmb_ocs_hcu_remove,
+ .remove = kmb_ocs_hcu_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = kmb_ocs_hcu_of_match,
diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
index 78f0ea49254d..9faef33e54bd 100644
--- a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
@@ -375,7 +375,7 @@ static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num,
else
id = -EINVAL;
- if (id < 0 || id > num_objs)
+ if (id < 0 || id >= num_objs)
return NULL;
return fw_objs[id];
diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c
index f49818a13013..788a11cdb34b 100644
--- a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c
@@ -129,16 +129,21 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Find and map all the device's BARS */
bar_mask = pci_select_bars(pdev, IORESOURCE_MEM) & ADF_GEN4_BAR_MASK;
- ret = pcim_iomap_regions_request_all(pdev, bar_mask, pci_name(pdev));
+ ret = pcim_request_all_regions(pdev, pci_name(pdev));
if (ret) {
- dev_err(&pdev->dev, "Failed to map pci regions.\n");
+ dev_err(&pdev->dev, "Failed to request PCI regions.\n");
goto out_err;
}
i = 0;
for_each_set_bit(bar_nr, &bar_mask, PCI_STD_NUM_BARS) {
bar = &accel_pci_dev->pci_bars[i++];
- bar->virt_addr = pcim_iomap_table(pdev)[bar_nr];
+ bar->virt_addr = pcim_iomap(pdev, bar_nr, 0);
+ if (!bar->virt_addr) {
+ dev_err(&pdev->dev, "Failed to ioremap PCI region.\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
}
pci_set_master(pdev);
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
index 9fd7ec53b9f3..bbd92c017c28 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
@@ -334,7 +334,7 @@ static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num,
else
id = -EINVAL;
- if (id < 0 || id > num_objs)
+ if (id < 0 || id >= num_objs)
return NULL;
return fw_objs[id];
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
index 659905e45950..115eabfd1f6b 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
@@ -131,16 +131,21 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Find and map all the device's BARS */
bar_mask = pci_select_bars(pdev, IORESOURCE_MEM) & ADF_GEN4_BAR_MASK;
- ret = pcim_iomap_regions_request_all(pdev, bar_mask, pci_name(pdev));
+ ret = pcim_request_all_regions(pdev, pci_name(pdev));
if (ret) {
- dev_err(&pdev->dev, "Failed to map pci regions.\n");
+ dev_err(&pdev->dev, "Failed to request PCI regions.\n");
goto out_err;
}
i = 0;
for_each_set_bit(bar_nr, &bar_mask, PCI_STD_NUM_BARS) {
bar = &accel_pci_dev->pci_bars[i++];
- bar->virt_addr = pcim_iomap_table(pdev)[bar_nr];
+ bar->virt_addr = pcim_iomap(pdev, bar_nr, 0);
+ if (!bar->virt_addr) {
+ dev_err(&pdev->dev, "Failed to ioremap PCI region.\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
}
pci_set_master(pdev);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c
index ec7913ab00a2..4cb8bd83f570 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_aer.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c
@@ -281,8 +281,11 @@ int adf_init_aer(void)
return -EFAULT;
device_sriov_wq = alloc_workqueue("qat_device_sriov_wq", 0, 0);
- if (!device_sriov_wq)
+ if (!device_sriov_wq) {
+ destroy_workqueue(device_reset_wq);
+ device_reset_wq = NULL;
return -EFAULT;
+ }
return 0;
}
diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
index f7ecabdf7805..eaa6388a6678 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
@@ -69,7 +69,6 @@ void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev,
struct adf_accel_dev *pf);
struct list_head *adf_devmgr_get_head(void);
struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id);
-struct adf_accel_dev *adf_devmgr_get_first(void);
struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev);
int adf_devmgr_verify_id(u32 id);
void adf_devmgr_get_num_dev(u32 *num);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
index c42f5c25aabd..4c11ad1ebcf0 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
@@ -22,18 +22,13 @@
void adf_dbgfs_init(struct adf_accel_dev *accel_dev)
{
char name[ADF_DEVICE_NAME_LENGTH];
- void *ret;
/* Create dev top level debugfs entry */
snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
accel_dev->hw_device->dev_class->name,
pci_name(accel_dev->accel_pci_dev.pci_dev));
- ret = debugfs_create_dir(name, NULL);
- if (IS_ERR_OR_NULL(ret))
- return;
-
- accel_dev->debugfs_dir = ret;
+ accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
adf_cfg_dev_dbgfs_add(accel_dev);
}
@@ -59,9 +54,6 @@ EXPORT_SYMBOL_GPL(adf_dbgfs_exit);
*/
void adf_dbgfs_add(struct adf_accel_dev *accel_dev)
{
- if (!accel_dev->debugfs_dir)
- return;
-
if (!accel_dev->is_vf) {
adf_fw_counters_dbgfs_add(accel_dev);
adf_heartbeat_dbgfs_add(accel_dev);
@@ -77,9 +69,6 @@ void adf_dbgfs_add(struct adf_accel_dev *accel_dev)
*/
void adf_dbgfs_rm(struct adf_accel_dev *accel_dev)
{
- if (!accel_dev->debugfs_dir)
- return;
-
if (!accel_dev->is_vf) {
adf_tl_dbgfs_rm(accel_dev);
adf_cnv_dbgfs_rm(accel_dev);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
index 96ddd1c419c4..34b9f7731c78 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
@@ -276,16 +276,6 @@ unlock:
}
EXPORT_SYMBOL_GPL(adf_devmgr_rm_dev);
-struct adf_accel_dev *adf_devmgr_get_first(void)
-{
- struct adf_accel_dev *dev = NULL;
-
- if (!list_empty(&accel_table))
- dev = list_first_entry(&accel_table, struct adf_accel_dev,
- list);
- return dev;
-}
-
/**
* adf_devmgr_pci_to_accel_dev() - Get accel_dev associated with the pci_dev.
* @pci_dev: Pointer to PCI device.
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
index ee0b5079de3e..2e4095c4c12c 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
@@ -42,13 +42,13 @@ struct pm_status_row {
const char *key;
};
-static struct pm_status_row pm_fuse_rows[] = {
+static const struct pm_status_row pm_fuse_rows[] = {
PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM),
PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_PM_IDLE),
PM_INFO_REGSET_ENTRY(fusectl0, ENABLE_DEEP_PM_IDLE),
};
-static struct pm_status_row pm_info_rows[] = {
+static const struct pm_status_row pm_info_rows[] = {
PM_INFO_REGSET_ENTRY(pm.status, CPM_PM_STATE),
PM_INFO_REGSET_ENTRY(pm.status, PENDING_WP),
PM_INFO_REGSET_ENTRY(pm.status, CURRENT_WP),
@@ -59,7 +59,7 @@ static struct pm_status_row pm_info_rows[] = {
PM_INFO_REGSET_ENTRY(pm.main, THR_VALUE),
};
-static struct pm_status_row pm_ssm_rows[] = {
+static const struct pm_status_row pm_ssm_rows[] = {
PM_INFO_REGSET_ENTRY(ssm.pm_enable, SSM_PM_ENABLE),
PM_INFO_REGSET_ENTRY32(ssm.active_constraint, ACTIVE_CONSTRAINT),
PM_INFO_REGSET_ENTRY(ssm.pm_domain_status, DOMAIN_POWER_GATED),
@@ -83,7 +83,7 @@ static struct pm_status_row pm_ssm_rows[] = {
PM_INFO_REGSET_ENTRY(ssm.pm_managed_status, WCP_MANAGED_COUNT),
};
-static struct pm_status_row pm_log_rows[] = {
+static const struct pm_status_row pm_log_rows[] = {
PM_INFO_REGSET_ENTRY32(event_counters.host_msg, HOST_MSG_EVENT_COUNT),
PM_INFO_REGSET_ENTRY32(event_counters.sys_pm, SYS_PM_EVENT_COUNT),
PM_INFO_REGSET_ENTRY32(event_counters.local_ssm, SSM_EVENT_COUNT),
@@ -91,7 +91,7 @@ static struct pm_status_row pm_log_rows[] = {
PM_INFO_REGSET_ENTRY32(event_counters.unknown, UNKNOWN_EVENT_COUNT),
};
-static struct pm_status_row pm_event_rows[ICP_QAT_NUMBER_OF_PM_EVENTS] = {
+static const struct pm_status_row pm_event_rows[ICP_QAT_NUMBER_OF_PM_EVENTS] = {
PM_INFO_REGSET_ENTRY32(event_log[0], EVENT0),
PM_INFO_REGSET_ENTRY32(event_log[1], EVENT1),
PM_INFO_REGSET_ENTRY32(event_log[2], EVENT2),
@@ -102,14 +102,14 @@ static struct pm_status_row pm_event_rows[ICP_QAT_NUMBER_OF_PM_EVENTS] = {
PM_INFO_REGSET_ENTRY32(event_log[7], EVENT7),
};
-static struct pm_status_row pm_csrs_rows[] = {
+static const struct pm_status_row pm_csrs_rows[] = {
PM_INFO_REGSET_ENTRY32(pm.fw_init, CPM_PM_FW_INIT),
PM_INFO_REGSET_ENTRY32(pm.status, CPM_PM_STATUS),
PM_INFO_REGSET_ENTRY32(pm.main, CPM_PM_MASTER_FW),
PM_INFO_REGSET_ENTRY32(pm.pwrreq, CPM_PM_PWRREQ),
};
-static int pm_scnprint_table(char *buff, struct pm_status_row *table,
+static int pm_scnprint_table(char *buff, const struct pm_status_row *table,
u32 *pm_info_regs, size_t buff_size, int table_len,
bool lowercase)
{
@@ -131,7 +131,7 @@ static int pm_scnprint_table(char *buff, struct pm_status_row *table,
return wr;
}
-static int pm_scnprint_table_upper_keys(char *buff, struct pm_status_row *table,
+static int pm_scnprint_table_upper_keys(char *buff, const struct pm_status_row *table,
u32 *pm_info_regs, size_t buff_size,
int table_len)
{
@@ -139,7 +139,7 @@ static int pm_scnprint_table_upper_keys(char *buff, struct pm_status_row *table,
table_len, false);
}
-static int pm_scnprint_table_lower_keys(char *buff, struct pm_status_row *table,
+static int pm_scnprint_table_lower_keys(char *buff, const struct pm_status_row *table,
u32 *pm_info_regs, size_t buff_size,
int table_len)
{
diff --git a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c
index 65bd26b25abc..f93d9cca70ce 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c
@@ -90,10 +90,6 @@ void adf_exit_arb(struct adf_accel_dev *accel_dev)
hw_data->get_arb_info(&info);
- /* Reset arbiter configuration */
- for (i = 0; i < ADF_ARB_NUM; i++)
- WRITE_CSR_ARB_SARCONFIG(csr, arb_off, i, 0);
-
/* Unmap worker threads to service arbiters */
for (i = 0; i < hw_data->num_engines; i++)
WRITE_CSR_ARB_WT2SAM(csr, arb_off, wt_off, i, 0);
diff --git a/drivers/crypto/intel/qat/qat_common/qat_hal.c b/drivers/crypto/intel/qat/qat_common/qat_hal.c
index 317cafa9d11f..ef8a9cf74f0c 100644
--- a/drivers/crypto/intel/qat/qat_common/qat_hal.c
+++ b/drivers/crypto/intel/qat/qat_common/qat_hal.c
@@ -163,7 +163,7 @@ int qat_hal_set_ae_ctx_mode(struct icp_qat_fw_loader_handle *handle,
return -EINVAL;
}
- /* Sets the accelaration engine context mode to either four or eight */
+ /* Sets the acceleration engine context mode to either four or eight */
csr = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES);
csr = IGNORE_W1C_MASK & csr;
new_csr = (mode == 4) ?
diff --git a/drivers/crypto/marvell/Kconfig b/drivers/crypto/marvell/Kconfig
index 78217577aa54..4c25a78ab3ed 100644
--- a/drivers/crypto/marvell/Kconfig
+++ b/drivers/crypto/marvell/Kconfig
@@ -7,7 +7,7 @@ config CRYPTO_DEV_MARVELL
config CRYPTO_DEV_MARVELL_CESA
tristate "Marvell's Cryptographic Engine driver"
- depends on PLAT_ORION || ARCH_MVEBU
+ depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
select CRYPTO_LIB_AES
select CRYPTO_LIB_DES
select CRYPTO_SKCIPHER
diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c
index 5fd31ba715c2..fa08f10e6f3f 100644
--- a/drivers/crypto/marvell/cesa/cesa.c
+++ b/drivers/crypto/marvell/cesa/cesa.c
@@ -375,7 +375,6 @@ static int mv_cesa_get_sram(struct platform_device *pdev, int idx)
{
struct mv_cesa_dev *cesa = platform_get_drvdata(pdev);
struct mv_cesa_engine *engine = &cesa->engines[idx];
- const char *res_name = "sram";
struct resource *res;
engine->pool = of_gen_pool_get(cesa->dev->of_node,
@@ -391,19 +390,7 @@ static int mv_cesa_get_sram(struct platform_device *pdev, int idx)
return -ENOMEM;
}
- if (cesa->caps->nengines > 1) {
- if (!idx)
- res_name = "sram0";
- else
- res_name = "sram1";
- }
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- res_name);
- if (!res || resource_size(res) < cesa->sram_size)
- return -EINVAL;
-
- engine->sram = devm_ioremap_resource(cesa->dev, res);
+ engine->sram = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
if (IS_ERR(engine->sram))
return PTR_ERR(engine->sram);
@@ -510,25 +497,21 @@ static int mv_cesa_probe(struct platform_device *pdev)
* if the clock does not exist.
*/
snprintf(res_name, sizeof(res_name), "cesa%u", i);
- engine->clk = devm_clk_get(dev, res_name);
+ engine->clk = devm_clk_get_optional_enabled(dev, res_name);
if (IS_ERR(engine->clk)) {
- engine->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(engine->clk))
- engine->clk = NULL;
+ engine->clk = devm_clk_get_optional_enabled(dev, NULL);
+ if (IS_ERR(engine->clk)) {
+ ret = PTR_ERR(engine->clk);
+ goto err_cleanup;
+ }
}
snprintf(res_name, sizeof(res_name), "cesaz%u", i);
- engine->zclk = devm_clk_get(dev, res_name);
- if (IS_ERR(engine->zclk))
- engine->zclk = NULL;
-
- ret = clk_prepare_enable(engine->clk);
- if (ret)
- goto err_cleanup;
-
- ret = clk_prepare_enable(engine->zclk);
- if (ret)
+ engine->zclk = devm_clk_get_optional_enabled(dev, res_name);
+ if (IS_ERR(engine->zclk)) {
+ ret = PTR_ERR(engine->zclk);
goto err_cleanup;
+ }
engine->regs = cesa->regs + CESA_ENGINE_OFF(i);
@@ -570,13 +553,8 @@ static int mv_cesa_probe(struct platform_device *pdev)
return 0;
err_cleanup:
- for (i = 0; i < caps->nengines; i++) {
- clk_disable_unprepare(cesa->engines[i].zclk);
- clk_disable_unprepare(cesa->engines[i].clk);
+ for (i = 0; i < caps->nengines; i++)
mv_cesa_put_sram(pdev, i);
- if (cesa->engines[i].irq > 0)
- irq_set_affinity_hint(cesa->engines[i].irq, NULL);
- }
return ret;
}
@@ -588,12 +566,8 @@ static void mv_cesa_remove(struct platform_device *pdev)
mv_cesa_remove_algs(cesa);
- for (i = 0; i < cesa->caps->nengines; i++) {
- clk_disable_unprepare(cesa->engines[i].zclk);
- clk_disable_unprepare(cesa->engines[i].clk);
+ for (i = 0; i < cesa->caps->nengines; i++)
mv_cesa_put_sram(pdev, i);
- irq_set_affinity_hint(cesa->engines[i].irq, NULL);
- }
}
static const struct platform_device_id mv_cesa_plat_id_table[] = {
@@ -604,7 +578,7 @@ MODULE_DEVICE_TABLE(platform, mv_cesa_plat_id_table);
static struct platform_driver marvell_cesa = {
.probe = mv_cesa_probe,
- .remove_new = mv_cesa_remove,
+ .remove = mv_cesa_remove,
.id_table = mv_cesa_plat_id_table,
.driver = {
.name = "marvell-cesa",
diff --git a/drivers/crypto/marvell/cesa/cipher.c b/drivers/crypto/marvell/cesa/cipher.c
index 0f37dfd42d85..cf62db50f958 100644
--- a/drivers/crypto/marvell/cesa/cipher.c
+++ b/drivers/crypto/marvell/cesa/cipher.c
@@ -489,7 +489,7 @@ static int mv_cesa_des_op(struct skcipher_request *req,
static int mv_cesa_ecb_des_encrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_ECB |
@@ -500,7 +500,7 @@ static int mv_cesa_ecb_des_encrypt(struct skcipher_request *req)
static int mv_cesa_ecb_des_decrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_ECB |
@@ -543,7 +543,7 @@ static int mv_cesa_cbc_des_op(struct skcipher_request *req,
static int mv_cesa_cbc_des_encrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_DIR_ENC);
@@ -552,7 +552,7 @@ static int mv_cesa_cbc_des_encrypt(struct skcipher_request *req)
static int mv_cesa_cbc_des_decrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_DIR_DEC);
@@ -596,7 +596,7 @@ static int mv_cesa_des3_op(struct skcipher_request *req,
static int mv_cesa_ecb_des3_ede_encrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_ECB |
@@ -608,7 +608,7 @@ static int mv_cesa_ecb_des3_ede_encrypt(struct skcipher_request *req)
static int mv_cesa_ecb_des3_ede_decrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_ECB |
@@ -649,7 +649,7 @@ static int mv_cesa_cbc_des3_op(struct skcipher_request *req,
static int mv_cesa_cbc_des3_ede_encrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_CBC |
@@ -661,7 +661,7 @@ static int mv_cesa_cbc_des3_ede_encrypt(struct skcipher_request *req)
static int mv_cesa_cbc_des3_ede_decrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_CBC |
@@ -725,7 +725,7 @@ static int mv_cesa_aes_op(struct skcipher_request *req,
static int mv_cesa_ecb_aes_encrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_ECB |
@@ -736,7 +736,7 @@ static int mv_cesa_ecb_aes_encrypt(struct skcipher_request *req)
static int mv_cesa_ecb_aes_decrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl,
CESA_SA_DESC_CFG_CRYPTCM_ECB |
@@ -778,7 +778,7 @@ static int mv_cesa_cbc_aes_op(struct skcipher_request *req,
static int mv_cesa_cbc_aes_encrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_DIR_ENC);
@@ -787,7 +787,7 @@ static int mv_cesa_cbc_aes_encrypt(struct skcipher_request *req)
static int mv_cesa_cbc_aes_decrypt(struct skcipher_request *req)
{
- struct mv_cesa_op_ctx tmpl;
+ struct mv_cesa_op_ctx tmpl = { };
mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_DIR_DEC);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
index 400e36d9908f..94d0e73e42de 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
@@ -739,18 +739,22 @@ static int otx2_cptpf_probe(struct pci_dev *pdev,
dev_err(dev, "Unable to get usable DMA configuration\n");
goto clear_drvdata;
}
- /* Map PF's configuration registers */
- err = pcim_iomap_regions_request_all(pdev, 1 << PCI_PF_REG_BAR_NUM,
- OTX2_CPT_DRV_NAME);
+ err = pcim_request_all_regions(pdev, OTX2_CPT_DRV_NAME);
if (err) {
- dev_err(dev, "Couldn't get PCI resources 0x%x\n", err);
+ dev_err(dev, "Couldn't request PCI resources 0x%x\n", err);
goto clear_drvdata;
}
pci_set_master(pdev);
pci_set_drvdata(pdev, cptpf);
cptpf->pdev = pdev;
- cptpf->reg_base = pcim_iomap_table(pdev)[PCI_PF_REG_BAR_NUM];
+ /* Map PF's configuration registers */
+ cptpf->reg_base = pcim_iomap(pdev, PCI_PF_REG_BAR_NUM, 0);
+ if (!cptpf->reg_base) {
+ err = -ENOMEM;
+ dev_err(dev, "Couldn't ioremap PCI resource 0x%x\n", err);
+ goto clear_drvdata;
+ }
/* Check if AF driver is up, otherwise defer probe */
err = cpt_is_pf_usable(cptpf);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
index 527d34cc258b..d0b6ee901f62 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
@@ -358,9 +358,8 @@ static int otx2_cptvf_probe(struct pci_dev *pdev,
dev_err(dev, "Unable to get usable DMA configuration\n");
goto clear_drvdata;
}
- /* Map VF's configuration registers */
- ret = pcim_iomap_regions_request_all(pdev, 1 << PCI_PF_REG_BAR_NUM,
- OTX2_CPTVF_DRV_NAME);
+
+ ret = pcim_request_all_regions(pdev, OTX2_CPTVF_DRV_NAME);
if (ret) {
dev_err(dev, "Couldn't get PCI resources 0x%x\n", ret);
goto clear_drvdata;
@@ -369,7 +368,13 @@ static int otx2_cptvf_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, cptvf);
cptvf->pdev = pdev;
- cptvf->reg_base = pcim_iomap_table(pdev)[PCI_PF_REG_BAR_NUM];
+ /* Map VF's configuration registers */
+ cptvf->reg_base = pcim_iomap(pdev, PCI_PF_REG_BAR_NUM, 0);
+ if (!cptvf->reg_base) {
+ ret = -ENOMEM;
+ dev_err(dev, "Couldn't ioremap PCI resource 0x%x\n", ret);
+ goto clear_drvdata;
+ }
otx2_cpt_set_hw_caps(pdev, &cptvf->cap_flag);
diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c
index c82775dbb557..d94a26c3541a 100644
--- a/drivers/crypto/mxs-dcp.c
+++ b/drivers/crypto/mxs-dcp.c
@@ -225,21 +225,22 @@ static int mxs_dcp_start_dma(struct dcp_async_ctx *actx)
static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
struct skcipher_request *req, int init)
{
- dma_addr_t key_phys = 0;
- dma_addr_t src_phys, dst_phys;
+ dma_addr_t key_phys, src_phys, dst_phys;
struct dcp *sdcp = global_sdcp;
struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req);
bool key_referenced = actx->key_referenced;
int ret;
- if (!key_referenced) {
+ if (key_referenced)
+ key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key + AES_KEYSIZE_128,
+ AES_KEYSIZE_128, DMA_TO_DEVICE);
+ else
key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
2 * AES_KEYSIZE_128, DMA_TO_DEVICE);
- ret = dma_mapping_error(sdcp->dev, key_phys);
- if (ret)
- return ret;
- }
+ ret = dma_mapping_error(sdcp->dev, key_phys);
+ if (ret)
+ return ret;
src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf,
DCP_BUF_SZ, DMA_TO_DEVICE);
@@ -300,7 +301,10 @@ aes_done_run:
err_dst:
dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
err_src:
- if (!key_referenced)
+ if (key_referenced)
+ dma_unmap_single(sdcp->dev, key_phys, AES_KEYSIZE_128,
+ DMA_TO_DEVICE);
+ else
dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128,
DMA_TO_DEVICE);
return ret;
@@ -1243,7 +1247,7 @@ MODULE_DEVICE_TABLE(of, mxs_dcp_dt_ids);
static struct platform_driver mxs_dcp_driver = {
.probe = mxs_dcp_probe,
- .remove_new = mxs_dcp_remove,
+ .remove = mxs_dcp_remove,
.driver = {
.name = "mxs-dcp",
.of_match_table = mxs_dcp_dt_ids,
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index b11545cc5cb7..14c302d2db79 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -2119,7 +2119,7 @@ static struct platform_driver n2_crypto_driver = {
.of_match_table = n2_crypto_match,
},
.probe = n2_crypto_probe,
- .remove_new = n2_crypto_remove,
+ .remove = n2_crypto_remove,
};
static const struct of_device_id n2_mau_match[] = {
@@ -2146,7 +2146,7 @@ static struct platform_driver n2_mau_driver = {
.of_match_table = n2_mau_match,
},
.probe = n2_mau_probe,
- .remove_new = n2_mau_remove,
+ .remove = n2_mau_remove,
};
static struct platform_driver * const drivers[] = {
diff --git a/drivers/crypto/nx/nx-common-pseries.c b/drivers/crypto/nx/nx-common-pseries.c
index 35f2d0d8507e..1660c5cf3641 100644
--- a/drivers/crypto/nx/nx-common-pseries.c
+++ b/drivers/crypto/nx/nx-common-pseries.c
@@ -133,7 +133,7 @@ struct nx842_devdata {
};
static struct nx842_devdata __rcu *devdata;
-static DEFINE_SPINLOCK(devdata_mutex);
+static DEFINE_SPINLOCK(devdata_spinlock);
#define NX842_COUNTER_INC(_x) \
static inline void nx842_inc_##_x( \
@@ -750,15 +750,15 @@ static int nx842_OF_upd(struct property *new_prop)
if (!new_devdata)
return -ENOMEM;
- spin_lock_irqsave(&devdata_mutex, flags);
+ spin_lock_irqsave(&devdata_spinlock, flags);
old_devdata = rcu_dereference_check(devdata,
- lockdep_is_held(&devdata_mutex));
+ lockdep_is_held(&devdata_spinlock));
if (old_devdata)
of_node = old_devdata->dev->of_node;
if (!old_devdata || !of_node) {
pr_err("%s: device is not available\n", __func__);
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
kfree(new_devdata);
return -ENODEV;
}
@@ -810,7 +810,7 @@ out:
old_devdata->max_sg_len);
rcu_assign_pointer(devdata, new_devdata);
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
synchronize_rcu();
dev_set_drvdata(new_devdata->dev, new_devdata);
kfree(old_devdata);
@@ -821,13 +821,13 @@ error_out:
dev_info(old_devdata->dev, "%s: device disabled\n", __func__);
nx842_OF_set_defaults(new_devdata);
rcu_assign_pointer(devdata, new_devdata);
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
synchronize_rcu();
dev_set_drvdata(new_devdata->dev, new_devdata);
kfree(old_devdata);
} else {
dev_err(old_devdata->dev, "%s: could not update driver from hardware\n", __func__);
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
}
if (!ret)
@@ -1045,9 +1045,9 @@ static int nx842_probe(struct vio_dev *viodev,
return -ENOMEM;
}
- spin_lock_irqsave(&devdata_mutex, flags);
+ spin_lock_irqsave(&devdata_spinlock, flags);
old_devdata = rcu_dereference_check(devdata,
- lockdep_is_held(&devdata_mutex));
+ lockdep_is_held(&devdata_spinlock));
if (old_devdata && old_devdata->vdev != NULL) {
dev_err(&viodev->dev, "%s: Attempt to register more than one instance of the hardware\n", __func__);
@@ -1062,7 +1062,7 @@ static int nx842_probe(struct vio_dev *viodev,
nx842_OF_set_defaults(new_devdata);
rcu_assign_pointer(devdata, new_devdata);
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
synchronize_rcu();
kfree(old_devdata);
@@ -1101,7 +1101,7 @@ static int nx842_probe(struct vio_dev *viodev,
return 0;
error_unlock:
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
if (new_devdata)
kfree(new_devdata->counters);
kfree(new_devdata);
@@ -1122,12 +1122,13 @@ static void nx842_remove(struct vio_dev *viodev)
crypto_unregister_alg(&nx842_pseries_alg);
- spin_lock_irqsave(&devdata_mutex, flags);
- old_devdata = rcu_dereference_check(devdata,
- lockdep_is_held(&devdata_mutex));
of_reconfig_notifier_unregister(&nx842_of_nb);
+
+ spin_lock_irqsave(&devdata_spinlock, flags);
+ old_devdata = rcu_dereference_check(devdata,
+ lockdep_is_held(&devdata_spinlock));
RCU_INIT_POINTER(devdata, NULL);
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
synchronize_rcu();
dev_set_drvdata(&viodev->dev, NULL);
if (old_devdata)
@@ -1257,11 +1258,11 @@ static void __exit nx842_pseries_exit(void)
crypto_unregister_alg(&nx842_pseries_alg);
- spin_lock_irqsave(&devdata_mutex, flags);
+ spin_lock_irqsave(&devdata_spinlock, flags);
old_devdata = rcu_dereference_check(devdata,
- lockdep_is_held(&devdata_mutex));
+ lockdep_is_held(&devdata_spinlock));
RCU_INIT_POINTER(devdata, NULL);
- spin_unlock_irqrestore(&devdata_mutex, flags);
+ spin_unlock_irqrestore(&devdata_spinlock, flags);
synchronize_rcu();
if (old_devdata && old_devdata->dev)
dev_set_drvdata(old_devdata->dev, NULL);
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index bad1adacbc84..e27b84616743 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -1305,7 +1305,7 @@ static SIMPLE_DEV_PM_OPS(omap_aes_pm_ops, omap_aes_suspend, omap_aes_resume);
static struct platform_driver omap_aes_driver = {
.probe = omap_aes_probe,
- .remove_new = omap_aes_remove,
+ .remove = omap_aes_remove,
.driver = {
.name = "omap-aes",
.pm = &omap_aes_pm_ops,
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index 209d3dc03a9b..498cbd585ed1 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -1115,7 +1115,7 @@ static SIMPLE_DEV_PM_OPS(omap_des_pm_ops, omap_des_suspend, omap_des_resume);
static struct platform_driver omap_des_driver = {
.probe = omap_des_probe,
- .remove_new = omap_des_remove,
+ .remove = omap_des_remove,
.driver = {
.name = "omap-des",
.pm = &omap_des_pm_ops,
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 5bcd9ab0f72a..7021481bf027 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -2216,7 +2216,7 @@ static void omap_sham_remove(struct platform_device *pdev)
static struct platform_driver omap_sham_driver = {
.probe = omap_sham_probe,
- .remove_new = omap_sham_remove,
+ .remove = omap_sham_remove,
.driver = {
.name = "omap-sham",
.of_match_table = omap_sham_of_match,
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
index 28b5fd823827..e228a31fe28d 100644
--- a/drivers/crypto/qce/core.c
+++ b/drivers/crypto/qce/core.c
@@ -299,7 +299,7 @@ MODULE_DEVICE_TABLE(of, qce_crypto_of_match);
static struct platform_driver qce_crypto_driver = {
.probe = qce_crypto_probe,
- .remove_new = qce_crypto_remove,
+ .remove = qce_crypto_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = qce_crypto_of_match,
diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
index 09419e79e34c..0685ba122e8a 100644
--- a/drivers/crypto/qcom-rng.c
+++ b/drivers/crypto/qcom-rng.c
@@ -262,7 +262,7 @@ MODULE_DEVICE_TABLE(of, qcom_rng_of_match);
static struct platform_driver qcom_rng_driver = {
.probe = qcom_rng_probe,
- .remove_new = qcom_rng_remove,
+ .remove = qcom_rng_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(qcom_rng_of_match),
diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c
index f74b3c81ba6d..b77bdce8e7fc 100644
--- a/drivers/crypto/rockchip/rk3288_crypto.c
+++ b/drivers/crypto/rockchip/rk3288_crypto.c
@@ -433,7 +433,7 @@ static void rk_crypto_remove(struct platform_device *pdev)
static struct platform_driver crypto_driver = {
.probe = rk_crypto_probe,
- .remove_new = rk_crypto_remove,
+ .remove = rk_crypto_remove,
.driver = {
.name = "rk3288-crypto",
.pm = &rk_crypto_pm_ops,
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index 8b6e3f5c94de..57ab237e899e 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -2335,7 +2335,7 @@ static void s5p_aes_remove(struct platform_device *pdev)
static struct platform_driver s5p_aes_crypto = {
.probe = s5p_aes_probe,
- .remove_new = s5p_aes_remove,
+ .remove = s5p_aes_remove,
.driver = {
.name = "s5p-secss",
.of_match_table = s5p_sss_dt_match,
diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c
index 461eca40e878..091612b066f1 100644
--- a/drivers/crypto/sa2ul.c
+++ b/drivers/crypto/sa2ul.c
@@ -574,7 +574,7 @@ static int sa_format_cmdl_gen(struct sa_cmdl_cfg *cfg, u8 *cmdl,
/* Clear the command label */
memzero_explicit(cmdl, (SA_MAX_CMDL_WORDS * sizeof(u32)));
- /* Iniialize the command update structure */
+ /* Initialize the command update structure */
memzero_explicit(upd_info, sizeof(*upd_info));
if (cfg->enc_eng_id && cfg->auth_eng_id) {
@@ -2489,7 +2489,7 @@ static void sa_ul_remove(struct platform_device *pdev)
static struct platform_driver sa_ul_driver = {
.probe = sa_ul_probe,
- .remove_new = sa_ul_remove,
+ .remove = sa_ul_remove,
.driver = {
.name = "saul-crypto",
.of_match_table = of_match,
diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c
index 96d4af5d48a6..533080b0cddc 100644
--- a/drivers/crypto/sahara.c
+++ b/drivers/crypto/sahara.c
@@ -1421,7 +1421,7 @@ static void sahara_remove(struct platform_device *pdev)
static struct platform_driver sahara_driver = {
.probe = sahara_probe,
- .remove_new = sahara_remove,
+ .remove = sahara_remove,
.driver = {
.name = SAHARA_NAME,
.of_match_table = sahara_dt_ids,
diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c
index e4dfed7ee0b0..42114e9364f0 100644
--- a/drivers/crypto/starfive/jh7110-cryp.c
+++ b/drivers/crypto/starfive/jh7110-cryp.c
@@ -151,7 +151,7 @@ static int starfive_cryp_probe(struct platform_device *pdev)
ret = starfive_aes_register_algs();
if (ret)
- goto err_algs_aes;
+ goto err_engine_start;
ret = starfive_hash_register_algs();
if (ret)
@@ -167,8 +167,6 @@ err_algs_rsa:
starfive_hash_unregister_algs();
err_algs_hash:
starfive_aes_unregister_algs();
-err_algs_aes:
- crypto_engine_stop(cryp->engine);
err_engine_start:
crypto_engine_exit(cryp->engine);
err_engine:
@@ -193,7 +191,6 @@ static void starfive_cryp_remove(struct platform_device *pdev)
starfive_hash_unregister_algs();
starfive_rsa_unregister_algs();
- crypto_engine_stop(cryp->engine);
crypto_engine_exit(cryp->engine);
starfive_dma_cleanup(cryp);
@@ -215,7 +212,7 @@ MODULE_DEVICE_TABLE(of, starfive_dt_ids);
static struct platform_driver starfive_cryp_driver = {
.probe = starfive_cryp_probe,
- .remove_new = starfive_cryp_remove,
+ .remove = starfive_cryp_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = starfive_dt_ids,
diff --git a/drivers/crypto/starfive/jh7110-rsa.c b/drivers/crypto/starfive/jh7110-rsa.c
index a778c4846025..d109c743f076 100644
--- a/drivers/crypto/starfive/jh7110-rsa.c
+++ b/drivers/crypto/starfive/jh7110-rsa.c
@@ -565,8 +565,6 @@ static void starfive_rsa_exit_tfm(struct crypto_akcipher *tfm)
static struct akcipher_alg starfive_rsa = {
.encrypt = starfive_rsa_enc,
.decrypt = starfive_rsa_dec,
- .sign = starfive_rsa_dec,
- .verify = starfive_rsa_enc,
.set_pub_key = starfive_rsa_set_pub_key,
.set_priv_key = starfive_rsa_set_priv_key,
.max_size = starfive_rsa_max_size,
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c
index e0faddbf8990..de4d0402f133 100644
--- a/drivers/crypto/stm32/stm32-crc32.c
+++ b/drivers/crypto/stm32/stm32-crc32.c
@@ -465,7 +465,7 @@ MODULE_DEVICE_TABLE(of, stm32_dt_ids);
static struct platform_driver stm32_crc_driver = {
.probe = stm32_crc_probe,
- .remove_new = stm32_crc_remove,
+ .remove = stm32_crc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_crc_pm_ops,
diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c
index 937f6dab8955..14c6339c2e43 100644
--- a/drivers/crypto/stm32/stm32-cryp.c
+++ b/drivers/crypto/stm32/stm32-cryp.c
@@ -2771,7 +2771,7 @@ static const struct dev_pm_ops stm32_cryp_pm_ops = {
static struct platform_driver stm32_cryp_driver = {
.probe = stm32_cryp_probe,
- .remove_new = stm32_cryp_remove,
+ .remove = stm32_cryp_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_cryp_pm_ops,
diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index 351827372ea6..768b27de4737 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -2532,7 +2532,7 @@ static const struct dev_pm_ops stm32_hash_pm_ops = {
static struct platform_driver stm32_hash_driver = {
.probe = stm32_hash_probe,
- .remove_new = stm32_hash_remove,
+ .remove = stm32_hash_remove,
.driver = {
.name = "stm32-hash",
.pm = &stm32_hash_pm_ops,
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 511ddcb0efd4..e8c0db687c57 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -3560,7 +3560,7 @@ static struct platform_driver talitos_driver = {
.of_match_table = talitos_match,
},
.probe = talitos_probe,
- .remove_new = talitos_remove,
+ .remove = talitos_remove,
};
module_platform_driver(talitos_driver);
diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c
index ae7a0f8435fc..9d130592cc0a 100644
--- a/drivers/crypto/tegra/tegra-se-aes.c
+++ b/drivers/crypto/tegra/tegra-se-aes.c
@@ -1180,8 +1180,6 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
goto out;
} else {
rctx->cryptlen = req->cryptlen - ctx->authsize;
- if (ret)
- goto out;
/* CTR operation */
ret = tegra_ccm_do_ctr(ctx, rctx);
diff --git a/drivers/crypto/tegra/tegra-se-main.c b/drivers/crypto/tegra/tegra-se-main.c
index f94c0331b148..918c0b10614d 100644
--- a/drivers/crypto/tegra/tegra-se-main.c
+++ b/drivers/crypto/tegra/tegra-se-main.c
@@ -312,7 +312,6 @@ static int tegra_se_probe(struct platform_device *pdev)
ret = tegra_se_host1x_register(se);
if (ret) {
- crypto_engine_stop(se->engine);
crypto_engine_exit(se->engine);
return dev_err_probe(dev, ret, "failed to init host1x params\n");
}
@@ -324,7 +323,6 @@ static void tegra_se_remove(struct platform_device *pdev)
{
struct tegra_se *se = platform_get_drvdata(pdev);
- crypto_engine_stop(se->engine);
crypto_engine_exit(se->engine);
host1x_client_unregister(&se->client);
}
@@ -387,7 +385,7 @@ static struct platform_driver tegra_se_driver = {
.of_match_table = tegra_se_of_match,
},
.probe = tegra_se_probe,
- .remove_new = tegra_se_remove,
+ .remove = tegra_se_remove,
};
static int tegra_se_host1x_probe(struct host1x_device *dev)
diff --git a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
index cb92b7fa99c6..48fee07b7e51 100644
--- a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
+++ b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
@@ -83,23 +83,16 @@ static void virtio_crypto_dataq_akcipher_callback(struct virtio_crypto_request *
case VIRTIO_CRYPTO_BADMSG:
error = -EBADMSG;
break;
-
- case VIRTIO_CRYPTO_KEY_REJECTED:
- error = -EKEYREJECTED;
- break;
-
default:
error = -EIO;
break;
}
akcipher_req = vc_akcipher_req->akcipher_req;
- if (vc_akcipher_req->opcode != VIRTIO_CRYPTO_AKCIPHER_VERIFY) {
- /* actuall length maybe less than dst buffer */
- akcipher_req->dst_len = len - sizeof(vc_req->status);
- sg_copy_from_buffer(akcipher_req->dst, sg_nents(akcipher_req->dst),
- vc_akcipher_req->dst_buf, akcipher_req->dst_len);
- }
+ /* actual length maybe less than dst buffer */
+ akcipher_req->dst_len = len - sizeof(vc_req->status);
+ sg_copy_from_buffer(akcipher_req->dst, sg_nents(akcipher_req->dst),
+ vc_akcipher_req->dst_buf, akcipher_req->dst_len);
virtio_crypto_akcipher_finalize_req(vc_akcipher_req, akcipher_req, error);
}
@@ -230,36 +223,27 @@ static int __virtio_crypto_akcipher_do_req(struct virtio_crypto_akcipher_request
int node = dev_to_node(&vcrypto->vdev->dev);
unsigned long flags;
int ret;
- bool verify = vc_akcipher_req->opcode == VIRTIO_CRYPTO_AKCIPHER_VERIFY;
- unsigned int src_len = verify ? req->src_len + req->dst_len : req->src_len;
/* out header */
sg_init_one(&outhdr_sg, req_data, sizeof(*req_data));
sgs[num_out++] = &outhdr_sg;
/* src data */
- src_buf = kcalloc_node(src_len, 1, GFP_KERNEL, node);
+ src_buf = kcalloc_node(req->src_len, 1, GFP_KERNEL, node);
if (!src_buf)
return -ENOMEM;
- if (verify) {
- /* for verify operation, both src and dst data work as OUT direction */
- sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len);
- sg_init_one(&srcdata_sg, src_buf, src_len);
- sgs[num_out++] = &srcdata_sg;
- } else {
- sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len);
- sg_init_one(&srcdata_sg, src_buf, src_len);
- sgs[num_out++] = &srcdata_sg;
+ sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, req->src_len);
+ sg_init_one(&srcdata_sg, src_buf, req->src_len);
+ sgs[num_out++] = &srcdata_sg;
- /* dst data */
- dst_buf = kcalloc_node(req->dst_len, 1, GFP_KERNEL, node);
- if (!dst_buf)
- goto free_src;
+ /* dst data */
+ dst_buf = kcalloc_node(req->dst_len, 1, GFP_KERNEL, node);
+ if (!dst_buf)
+ goto free_src;
- sg_init_one(&dstdata_sg, dst_buf, req->dst_len);
- sgs[num_out + num_in++] = &dstdata_sg;
- }
+ sg_init_one(&dstdata_sg, dst_buf, req->dst_len);
+ sgs[num_out + num_in++] = &dstdata_sg;
vc_akcipher_req->src_buf = src_buf;
vc_akcipher_req->dst_buf = dst_buf;
@@ -352,16 +336,6 @@ static int virtio_crypto_rsa_decrypt(struct akcipher_request *req)
return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_DECRYPT);
}
-static int virtio_crypto_rsa_sign(struct akcipher_request *req)
-{
- return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_SIGN);
-}
-
-static int virtio_crypto_rsa_verify(struct akcipher_request *req)
-{
- return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_VERIFY);
-}
-
static int virtio_crypto_rsa_set_key(struct crypto_akcipher *tfm,
const void *key,
unsigned int keylen,
@@ -524,16 +498,19 @@ static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = {
.algo.base = {
.encrypt = virtio_crypto_rsa_encrypt,
.decrypt = virtio_crypto_rsa_decrypt,
- .sign = virtio_crypto_rsa_sign,
- .verify = virtio_crypto_rsa_verify,
+ /*
+ * Must specify an arbitrary hash algorithm upon
+ * set_{pub,priv}_key (even though it's not used
+ * by encrypt/decrypt) because qemu checks for it.
+ */
.set_pub_key = virtio_crypto_p1pad_rsa_sha1_set_pub_key,
.set_priv_key = virtio_crypto_p1pad_rsa_sha1_set_priv_key,
.max_size = virtio_crypto_rsa_max_size,
.init = virtio_crypto_rsa_init_tfm,
.exit = virtio_crypto_rsa_exit_tfm,
.base = {
- .cra_name = "pkcs1pad(rsa,sha1)",
- .cra_driver_name = "virtio-pkcs1-rsa-with-sha1",
+ .cra_name = "pkcs1pad(rsa)",
+ .cra_driver_name = "virtio-pkcs1-rsa",
.cra_priority = 150,
.cra_module = THIS_MODULE,
.cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx),
diff --git a/drivers/crypto/xilinx/zynqmp-aes-gcm.c b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
index 7f0ec6887a39..6e72d9229410 100644
--- a/drivers/crypto/xilinx/zynqmp-aes-gcm.c
+++ b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
@@ -438,7 +438,7 @@ MODULE_DEVICE_TABLE(of, zynqmp_aes_dt_ids);
static struct platform_driver zynqmp_aes_driver = {
.probe = zynqmp_aes_aead_probe,
- .remove_new = zynqmp_aes_aead_remove,
+ .remove = zynqmp_aes_aead_remove,
.driver = {
.name = "zynqmp-aes",
.of_match_table = zynqmp_aes_dt_ids,
diff --git a/drivers/crypto/xilinx/zynqmp-sha.c b/drivers/crypto/xilinx/zynqmp-sha.c
index 1bcec6f46c9c..580649f9bff8 100644
--- a/drivers/crypto/xilinx/zynqmp-sha.c
+++ b/drivers/crypto/xilinx/zynqmp-sha.c
@@ -248,7 +248,7 @@ static void zynqmp_sha_remove(struct platform_device *pdev)
static struct platform_driver zynqmp_sha_driver = {
.probe = zynqmp_sha_probe,
- .remove_new = zynqmp_sha_remove,
+ .remove = zynqmp_sha_remove,
.driver = {
.name = "zynqmp-sha3-384",
},
diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c
index e9cd7939c407..2a1f164db98e 100644
--- a/drivers/cxl/core/cdat.c
+++ b/drivers/cxl/core/cdat.c
@@ -247,8 +247,8 @@ static void update_perf_entry(struct device *dev, struct dsmas_entry *dent,
dpa_perf->dpa_range = dent->dpa_range;
dpa_perf->qos_class = dent->qos_class;
dev_dbg(dev,
- "DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n",
- dent->dpa_range.start, dpa_perf->qos_class,
+ "DSMAS: dpa: %pra qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n",
+ &dent->dpa_range, dpa_perf->qos_class,
dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth,
dent->coord[ACCESS_COORDINATE_CPU].write_bandwidth,
dent->coord[ACCESS_COORDINATE_CPU].read_latency,
@@ -279,8 +279,8 @@ static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds,
range_contains(&pmem_range, &dent->dpa_range))
update_perf_entry(dev, dent, &mds->pmem_perf);
else
- dev_dbg(dev, "no partition for dsmas dpa: %#llx\n",
- dent->dpa_range.start);
+ dev_dbg(dev, "no partition for dsmas dpa: %pra\n",
+ &dent->dpa_range);
}
}
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 0c62b4069ba0..800466f96a68 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -89,6 +89,11 @@ resource_size_t __rcrb_to_component(struct device *dev,
enum cxl_rcrb which);
u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb);
+#define PCI_RCRB_CAP_LIST_ID_MASK GENMASK(7, 0)
+#define PCI_RCRB_CAP_HDR_ID_MASK GENMASK(7, 0)
+#define PCI_RCRB_CAP_HDR_NEXT_MASK GENMASK(15, 8)
+#define PCI_CAP_EXP_SIZEOF 0x3c
+
extern struct rw_semaphore cxl_dpa_rwsem;
extern struct rw_semaphore cxl_region_rwsem;
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 223c273c0cd1..ff0c96ade241 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -424,7 +424,6 @@ int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct device *dev = &cxled->cxld.dev;
- int rc;
switch (mode) {
case CXL_DECODER_RAM:
@@ -435,11 +434,9 @@ int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
return -EINVAL;
}
- down_write(&cxl_dpa_rwsem);
- if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
- rc = -EBUSY;
- goto out;
- }
+ guard(rwsem_write)(&cxl_dpa_rwsem);
+ if (cxled->cxld.flags & CXL_DECODER_F_ENABLE)
+ return -EBUSY;
/*
* Only allow modes that are supported by the current partition
@@ -447,21 +444,15 @@ int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
*/
if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) {
dev_dbg(dev, "no available pmem capacity\n");
- rc = -ENXIO;
- goto out;
+ return -ENXIO;
}
if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) {
dev_dbg(dev, "no available ram capacity\n");
- rc = -ENXIO;
- goto out;
+ return -ENXIO;
}
cxled->mode = mode;
- rc = 0;
-out:
- up_write(&cxl_dpa_rwsem);
-
- return rc;
+ return 0;
}
int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index dff618c708dc..70d0a017e99c 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2537,9 +2537,8 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM);
}
-static ssize_t create_pmem_region_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
+static ssize_t create_region_store(struct device *dev, const char *buf,
+ size_t len, enum cxl_decoder_mode mode)
{
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
struct cxl_region *cxlr;
@@ -2549,31 +2548,26 @@ static ssize_t create_pmem_region_store(struct device *dev,
if (rc != 1)
return -EINVAL;
- cxlr = __create_region(cxlrd, CXL_DECODER_PMEM, id);
+ cxlr = __create_region(cxlrd, mode, id);
if (IS_ERR(cxlr))
return PTR_ERR(cxlr);
return len;
}
+
+static ssize_t create_pmem_region_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ return create_region_store(dev, buf, len, CXL_DECODER_PMEM);
+}
DEVICE_ATTR_RW(create_pmem_region);
static ssize_t create_ram_region_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
- struct cxl_region *cxlr;
- int rc, id;
-
- rc = sscanf(buf, "region%d\n", &id);
- if (rc != 1)
- return -EINVAL;
-
- cxlr = __create_region(cxlrd, CXL_DECODER_RAM, id);
- if (IS_ERR(cxlr))
- return PTR_ERR(cxlr);
-
- return len;
+ return create_region_store(dev, buf, len, CXL_DECODER_RAM);
}
DEVICE_ATTR_RW(create_ram_region);
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index e1082e749c69..429973a2165b 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -52,7 +52,7 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
cap_array = readl(base + CXL_CM_CAP_HDR_OFFSET);
if (FIELD_GET(CXL_CM_CAP_HDR_ID_MASK, cap_array) != CM_CAP_HDR_CAP_ID) {
- dev_err(dev,
+ dev_dbg(dev,
"Couldn't locate the CXL.cache and CXL.mem capability array header.\n");
return;
}
@@ -506,6 +506,62 @@ out:
return offset;
}
+static resource_size_t cxl_rcrb_to_linkcap(struct device *dev, struct cxl_dport *dport)
+{
+ resource_size_t rcrb = dport->rcrb.base;
+ void __iomem *addr;
+ u32 cap_hdr;
+ u16 offset;
+
+ 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;
+ }
+
+ offset = FIELD_GET(PCI_RCRB_CAP_LIST_ID_MASK, readw(addr + PCI_CAPABILITY_LIST));
+ cap_hdr = readl(addr + offset);
+ while ((FIELD_GET(PCI_RCRB_CAP_HDR_ID_MASK, cap_hdr)) != PCI_CAP_ID_EXP) {
+ offset = FIELD_GET(PCI_RCRB_CAP_HDR_NEXT_MASK, cap_hdr);
+ if (offset == 0 || offset > SZ_4K) {
+ offset = 0;
+ break;
+ }
+ cap_hdr = readl(addr + offset);
+ }
+
+ iounmap(addr);
+ release_mem_region(rcrb, SZ_4K);
+ if (!offset)
+ return CXL_RESOURCE_NONE;
+
+ return offset;
+}
+
+int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport)
+{
+ void __iomem *dport_pcie_cap = NULL;
+ resource_size_t pos;
+ struct cxl_rcrb_info *ri;
+
+ ri = &dport->rcrb;
+ pos = cxl_rcrb_to_linkcap(&pdev->dev, dport);
+ if (pos == CXL_RESOURCE_NONE)
+ return -ENXIO;
+
+ dport_pcie_cap = devm_cxl_iomap_block(&pdev->dev,
+ ri->base + pos,
+ PCI_CAP_EXP_SIZEOF);
+ dport->regs.rcd_pcie_cap = dport_pcie_cap;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_dport_map_rcd_linkcap, CXL);
+
resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri,
enum cxl_rcrb which)
{
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 5406e3ab3d4a..f6015f24ad38 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -235,6 +235,14 @@ struct cxl_regs {
struct_group_tagged(cxl_rch_regs, rch_regs,
void __iomem *dport_aer;
);
+
+ /*
+ * RCD upstream port specific PCIe cap register
+ * @pcie_cap: CXL 3.0 8.2.1.2 RCD Upstream Port RCRB
+ */
+ struct_group_tagged(cxl_rcd_regs, rcd_regs,
+ void __iomem *rcd_pcie_cap;
+ );
};
struct cxl_reg_map {
@@ -304,6 +312,7 @@ int cxl_setup_regs(struct cxl_register_map *map);
struct cxl_dport;
resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
struct cxl_dport *dport);
+int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport);
#define CXL_RESOURCE_NONE ((resource_size_t) -1)
#define CXL_TARGET_STRLEN 20
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 188412d45e0d..b2cb81f6d9e7 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -475,9 +475,9 @@ static bool is_cxl_restricted(struct pci_dev *pdev)
}
static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
- struct cxl_register_map *map)
+ struct cxl_register_map *map,
+ struct cxl_dport *dport)
{
- struct cxl_dport *dport;
resource_size_t component_reg_phys;
*map = (struct cxl_register_map) {
@@ -513,11 +513,24 @@ static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
* is an RCH and try to extract the Component Registers from
* an RCRB.
*/
- if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev))
- rc = cxl_rcrb_get_comp_regs(pdev, map);
-
- if (rc)
+ if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) {
+ struct cxl_dport *dport;
+ struct cxl_port *port __free(put_cxl_port) =
+ cxl_pci_find_port(pdev, &dport);
+ if (!port)
+ return -EPROBE_DEFER;
+
+ rc = cxl_rcrb_get_comp_regs(pdev, map, dport);
+ if (rc)
+ return rc;
+
+ rc = cxl_dport_map_rcd_linkcap(pdev, dport);
+ if (rc)
+ return rc;
+
+ } else if (rc) {
return rc;
+ }
return cxl_setup_regs(map);
}
@@ -764,10 +777,6 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
return 0;
}
- rc = cxl_mem_alloc_event_buf(mds);
- if (rc)
- return rc;
-
rc = cxl_event_get_int_policy(mds, &policy);
if (rc)
return rc;
@@ -781,6 +790,10 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge,
return -EBUSY;
}
+ rc = cxl_mem_alloc_event_buf(mds);
+ if (rc)
+ return rc;
+
rc = cxl_event_irqsetup(mds);
if (rc)
return rc;
@@ -807,6 +820,83 @@ static int cxl_pci_type3_init_mailbox(struct cxl_dev_state *cxlds)
return 0;
}
+static ssize_t rcd_pcie_cap_emit(struct device *dev, u16 offset, char *buf, size_t width)
+{
+ struct cxl_dev_state *cxlds = dev_get_drvdata(dev);
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ struct device *root_dev;
+ struct cxl_dport *dport;
+ struct cxl_port *root __free(put_cxl_port) =
+ cxl_mem_find_port(cxlmd, &dport);
+
+ if (!root)
+ return -ENXIO;
+
+ root_dev = root->uport_dev;
+ if (!root_dev)
+ return -ENXIO;
+
+ guard(device)(root_dev);
+ if (!root_dev->driver)
+ return -ENXIO;
+
+ switch (width) {
+ case 2:
+ return sysfs_emit(buf, "%#x\n",
+ readw(dport->regs.rcd_pcie_cap + offset));
+ case 4:
+ return sysfs_emit(buf, "%#x\n",
+ readl(dport->regs.rcd_pcie_cap + offset));
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t rcd_link_cap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return rcd_pcie_cap_emit(dev, PCI_EXP_LNKCAP, buf, sizeof(u32));
+}
+static DEVICE_ATTR_RO(rcd_link_cap);
+
+static ssize_t rcd_link_ctrl_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return rcd_pcie_cap_emit(dev, PCI_EXP_LNKCTL, buf, sizeof(u16));
+}
+static DEVICE_ATTR_RO(rcd_link_ctrl);
+
+static ssize_t rcd_link_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return rcd_pcie_cap_emit(dev, PCI_EXP_LNKSTA, buf, sizeof(u16));
+}
+static DEVICE_ATTR_RO(rcd_link_status);
+
+static struct attribute *cxl_rcd_attrs[] = {
+ &dev_attr_rcd_link_cap.attr,
+ &dev_attr_rcd_link_ctrl.attr,
+ &dev_attr_rcd_link_status.attr,
+ NULL
+};
+
+static umode_t cxl_rcd_visible(struct kobject *kobj, struct attribute *a, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ if (is_cxl_restricted(pdev))
+ return a->mode;
+
+ return 0;
+}
+
+static struct attribute_group cxl_rcd_group = {
+ .attrs = cxl_rcd_attrs,
+ .is_visible = cxl_rcd_visible,
+};
+__ATTRIBUTE_GROUPS(cxl_rcd);
+
static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus);
@@ -1016,6 +1106,7 @@ static struct pci_driver cxl_pci_driver = {
.id_table = cxl_mem_pci_tbl,
.probe = cxl_pci_probe,
.err_handler = &cxl_error_handlers,
+ .dev_groups = cxl_rcd_groups,
.driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index 9dc394295e1f..24041cf85cfb 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -173,7 +173,7 @@ static ssize_t CDAT_read(struct file *filp, struct kobject *kobj,
static BIN_ATTR_ADMIN_RO(CDAT, 0);
static umode_t cxl_port_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr, int i)
{
struct device *dev = kobj_to_dev(kobj);
struct cxl_port *port = to_cxl_port(dev);
diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
index 446617b73aea..0867115aeef2 100644
--- a/drivers/dax/dax-private.h
+++ b/drivers/dax/dax-private.h
@@ -40,6 +40,12 @@ struct dax_region {
struct device *youngest;
};
+/**
+ * struct dax_mapping - device to display mapping range attributes
+ * @dev: device representing this range
+ * @range_id: index within dev_dax ranges array
+ * @id: ida of this mapping
+ */
struct dax_mapping {
struct device dev;
int range_id;
@@ -47,6 +53,18 @@ struct dax_mapping {
};
/**
+ * struct dev_dax_range - tuple represenging a range of memory used by dev_dax
+ * @pgoff: page offset
+ * @range: resource-span
+ * @mapping: reference to the dax_mapping for this range
+ */
+struct dev_dax_range {
+ unsigned long pgoff;
+ struct range range;
+ struct dax_mapping *mapping;
+};
+
+/**
* struct dev_dax - instance data for a subdivision of a dax region, and
* data while the device is activated in the driver.
* @region - parent region
@@ -58,7 +76,7 @@ struct dax_mapping {
* @dev - device core
* @pgmap - pgmap for memmap setup / lifetime (driver owned)
* @nr_range: size of @ranges
- * @ranges: resource-span + pgoff tuples for the instance
+ * @ranges: range tuples of memory used
*/
struct dev_dax {
struct dax_region *region;
@@ -72,11 +90,7 @@ struct dev_dax {
struct dev_pagemap *pgmap;
bool memmap_on_memory;
int nr_range;
- struct dev_dax_range {
- unsigned long pgoff;
- struct range range;
- struct dax_mapping *mapping;
- } *ranges;
+ struct dev_dax_range *ranges;
};
/*
diff --git a/drivers/dax/pmem/Makefile b/drivers/dax/pmem/Makefile
deleted file mode 100644
index 191c31f0d4f0..000000000000
--- a/drivers/dax/pmem/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
-obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem_core.o
-
-dax_pmem-y := pmem.o
-dax_pmem_core-y := core.o
-dax_pmem_compat-y := compat.o
diff --git a/drivers/dax/pmem/pmem.c b/drivers/dax/pmem/pmem.c
deleted file mode 100644
index dfe91a2990fe..000000000000
--- a/drivers/dax/pmem/pmem.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
-#include <linux/percpu-refcount.h>
-#include <linux/memremap.h>
-#include <linux/module.h>
-#include <linux/pfn_t.h>
-#include <linux/nd.h>
-#include "../bus.h"
-
-
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d9ec1e69e428..e994d6e0779e 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -378,6 +378,20 @@ config LOONGSON1_APB_DMA
This selects support for the APB DMA controller in Loongson1 SoCs,
which is required by Loongson1 NAND and audio support.
+config LOONGSON2_APB_DMA
+ tristate "Loongson2 APB DMA support"
+ depends on LOONGARCH || COMPILE_TEST
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Support for the Loongson2 APB DMA controller driver. The
+ DMA controller is having single DMA channel which can be
+ configured for different peripherals like audio, nand, sdio
+ etc which is in APB bus.
+
+ This DMA controller transfers data from memory to peripheral fifo.
+ It does not support memory to memory data transfer.
+
config LPC18XX_DMAMUX
bool "NXP LPC18xx/43xx DMA MUX for PL080"
depends on ARCH_LPC18XX || COMPILE_TEST
@@ -396,20 +410,6 @@ config LPC32XX_DMAMUX
Support for PL080 multiplexed DMA request lines on
LPC32XX platrofm.
-config LS2X_APB_DMA
- tristate "Loongson LS2X APB DMA support"
- depends on LOONGARCH || COMPILE_TEST
- select DMA_ENGINE
- select DMA_VIRTUAL_CHANNELS
- help
- Support for the Loongson LS2X APB DMA controller driver. The
- DMA controller is having single DMA channel which can be
- configured for different peripherals like audio, nand, sdio
- etc which is in APB bus.
-
- This DMA controller transfers data from memory to peripheral fifo.
- It does not support memory to memory data transfer.
-
config MCF_EDMA
tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
depends on M5441x || (COMPILE_TEST && FSL_EDMA=n)
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index ad6a03c052ec..5b2a52f4f2ee 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -50,9 +50,9 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-y += idxd/
obj-$(CONFIG_K3_DMA) += k3dma.o
obj-$(CONFIG_LOONGSON1_APB_DMA) += loongson1-apb-dma.o
+obj-$(CONFIG_LOONGSON2_APB_DMA) += loongson2-apb-dma.o
obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
obj-$(CONFIG_LPC32XX_DMAMUX) += lpc32xx-dmamux.o
-obj-$(CONFIG_LS2X_APB_DMA) += ls2x-apb-dma.o
obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
index a58a1600dd65..2abbe11e797e 100644
--- a/drivers/dma/acpi-dma.c
+++ b/drivers/dma/acpi-dma.c
@@ -9,18 +9,21 @@
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
+#include <linux/acpi.h>
+#include <linux/acpi_dma.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
-#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/acpi.h>
-#include <linux/acpi_dma.h>
#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
static LIST_HEAD(acpi_dma_list);
static DEFINE_MUTEX(acpi_dma_lock);
@@ -236,7 +239,7 @@ int acpi_dma_controller_free(struct device *dev)
}
EXPORT_SYMBOL_GPL(acpi_dma_controller_free);
-static void devm_acpi_dma_release(struct device *dev, void *res)
+static void devm_acpi_dma_free(void *dev)
{
acpi_dma_controller_free(dev);
}
@@ -259,37 +262,15 @@ int devm_acpi_dma_controller_register(struct device *dev,
(struct acpi_dma_spec *, struct acpi_dma *),
void *data)
{
- void *res;
int ret;
- res = devres_alloc(devm_acpi_dma_release, 0, GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
ret = acpi_dma_controller_register(dev, acpi_dma_xlate, data);
- if (ret) {
- devres_free(res);
+ if (ret)
return ret;
- }
- devres_add(dev, res);
- return 0;
-}
-EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
-/**
- * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free()
- * @dev: device that is unregistering as DMA controller
- *
- * Unregister a DMA controller registered with
- * devm_acpi_dma_controller_register(). Normally this function will not need to
- * be called and the resource management code will ensure that the resource is
- * freed.
- */
-void devm_acpi_dma_controller_free(struct device *dev)
-{
- WARN_ON(devres_release(dev, devm_acpi_dma_release, NULL, NULL));
+ return devm_add_action_or_reset(dev, devm_acpi_dma_free, dev);
}
-EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
+EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
/**
* acpi_dma_update_dma_spec - prepare dma specifier to pass to translation function
diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c
index e6a6566b309e..a203fdd84950 100644
--- a/drivers/dma/altera-msgdma.c
+++ b/drivers/dma/altera-msgdma.c
@@ -954,7 +954,7 @@ static struct platform_driver msgdma_driver = {
.of_match_table = of_match_ptr(msgdma_match),
},
.probe = msgdma_probe,
- .remove_new = msgdma_remove,
+ .remove = msgdma_remove,
};
module_platform_driver(msgdma_driver);
diff --git a/drivers/dma/amd/qdma/qdma.c b/drivers/dma/amd/qdma/qdma.c
index b0a1f3ad851b..6d9079458fe9 100644
--- a/drivers/dma/amd/qdma/qdma.c
+++ b/drivers/dma/amd/qdma/qdma.c
@@ -1133,7 +1133,7 @@ static struct platform_driver amd_qdma_driver = {
.name = "amd-qdma",
},
.probe = amd_qdma_probe,
- .remove_new = amd_qdma_remove,
+ .remove = amd_qdma_remove,
};
module_platform_driver(amd_qdma_driver);
diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index 9588773dd2eb..c499173d80b2 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -950,7 +950,7 @@ static struct platform_driver apple_admac_driver = {
.of_match_table = admac_of_match,
},
.probe = admac_probe,
- .remove_new = admac_remove,
+ .remove = admac_remove,
};
module_platform_driver(apple_admac_driver);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index baebddc740b0..2d147712cbc6 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -2250,7 +2250,7 @@ static const struct dev_pm_ops __maybe_unused at_dma_dev_pm_ops = {
};
static struct platform_driver at_dma_driver = {
- .remove_new = at_dma_remove,
+ .remove = at_dma_remove,
.shutdown = at_dma_shutdown,
.id_table = atdma_devtypes,
.driver = {
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 299396121e6d..9c7b40220004 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -2476,7 +2476,7 @@ MODULE_DEVICE_TABLE(of, atmel_xdmac_dt_ids);
static struct platform_driver at_xdmac_driver = {
.probe = at_xdmac_probe,
- .remove_new = at_xdmac_remove,
+ .remove = at_xdmac_remove,
.driver = {
.name = "at_xdmac",
.of_match_table = of_match_ptr(atmel_xdmac_dt_ids),
diff --git a/drivers/dma/bcm-sba-raid.c b/drivers/dma/bcm-sba-raid.c
index cfa6e1167a1f..7f0e76439ce5 100644
--- a/drivers/dma/bcm-sba-raid.c
+++ b/drivers/dma/bcm-sba-raid.c
@@ -1756,7 +1756,7 @@ MODULE_DEVICE_TABLE(of, sba_of_match);
static struct platform_driver sba_driver = {
.probe = sba_probe,
- .remove_new = sba_remove,
+ .remove = sba_remove,
.driver = {
.name = "bcm-sba-raid",
.of_match_table = sba_of_match,
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index e1b92b4d7b05..7ba52dee40a9 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -1029,7 +1029,7 @@ static void bcm2835_dma_remove(struct platform_device *pdev)
static struct platform_driver bcm2835_dma_driver = {
.probe = bcm2835_dma_probe,
- .remove_new = bcm2835_dma_remove,
+ .remove = bcm2835_dma_remove,
.driver = {
.name = "bcm2835-dma",
.of_match_table = of_match_ptr(bcm2835_dma_of_match),
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
index 0bbaa7620bdd..6c4d655ffe77 100644
--- a/drivers/dma/bestcomm/bestcomm.c
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -486,7 +486,7 @@ MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
static struct platform_driver mpc52xx_bcom_of_platform_driver = {
.probe = mpc52xx_bcom_probe,
- .remove_new = mpc52xx_bcom_remove,
+ .remove = mpc52xx_bcom_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = mpc52xx_bcom_of_match,
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index c9cfa341db51..100057603fd4 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -1122,7 +1122,7 @@ MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
static struct platform_driver jz4780_dma_driver = {
.probe = jz4780_dma_probe,
- .remove_new = jz4780_dma_remove,
+ .remove = jz4780_dma_remove,
.driver = {
.name = "jz4780-dma",
.of_match_table = jz4780_dma_dt_match,
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index fffafa86d964..b23536645ff7 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -1676,7 +1676,7 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
static struct platform_driver dw_driver = {
.probe = dw_probe,
- .remove_new = dw_remove,
+ .remove = dw_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = dw_dma_of_id_table,
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c
index 47c58ad468cb..2606cf9cd429 100644
--- a/drivers/dma/dw/platform.c
+++ b/drivers/dma/dw/platform.c
@@ -191,7 +191,7 @@ static const struct dev_pm_ops dw_dev_pm_ops = {
static struct platform_driver dw_driver = {
.probe = dw_probe,
- .remove_new = dw_remove,
+ .remove = dw_remove,
.shutdown = dw_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 6b98a23e3332..e424bb5c40e7 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -929,8 +929,7 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
/* Sanity check the channel parameters */
if (!edmac->edma->m2m) {
- if (edmac->dma_cfg.port < EP93XX_DMA_I2S1 ||
- edmac->dma_cfg.port > EP93XX_DMA_IRDA)
+ if (edmac->dma_cfg.port > EP93XX_DMA_IRDA)
return -EINVAL;
if (edmac->dma_cfg.dir != ep93xx_dma_chan_direction(chan))
return -EINVAL;
diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
index f9f1eda79254..60de1003193a 100644
--- a/drivers/dma/fsl-edma-main.c
+++ b/drivers/dma/fsl-edma-main.c
@@ -740,7 +740,7 @@ static struct platform_driver fsl_edma_driver = {
.pm = &fsl_edma_pm_ops,
},
.probe = fsl_edma_probe,
- .remove_new = fsl_edma_remove,
+ .remove = fsl_edma_remove,
};
static int __init fsl_edma_init(void)
diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c
index 5005e138fc23..823f5c6bc2e1 100644
--- a/drivers/dma/fsl-qdma.c
+++ b/drivers/dma/fsl-qdma.c
@@ -1288,7 +1288,7 @@ static struct platform_driver fsl_qdma_driver = {
.of_match_table = fsl_qdma_dt_ids,
},
.probe = fsl_qdma_probe,
- .remove_new = fsl_qdma_remove,
+ .remove = fsl_qdma_remove,
};
module_platform_driver(fsl_qdma_driver);
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
index 014ff523d5ec..6aa97e258a55 100644
--- a/drivers/dma/fsl_raid.c
+++ b/drivers/dma/fsl_raid.c
@@ -886,7 +886,7 @@ static struct platform_driver fsl_re_driver = {
.of_match_table = fsl_re_ids,
},
.probe = fsl_re_probe,
- .remove_new = fsl_re_remove,
+ .remove = fsl_re_remove,
};
module_platform_driver(fsl_re_driver);
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 18a6c4bf6275..b5e7d18b9766 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1404,7 +1404,7 @@ static struct platform_driver fsldma_of_driver = {
#endif
},
.probe = fsldma_of_probe,
- .remove_new = fsldma_of_remove,
+ .remove = fsldma_of_remove,
};
/*----------------------------------------------------------------------------*/
diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
index 3c648308a54a..d147353d47ab 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -693,7 +693,7 @@ static const struct dev_pm_ops idma64_dev_pm_ops = {
static struct platform_driver idma64_platform_driver = {
.probe = idma64_platform_probe,
- .remove_new = idma64_platform_remove,
+ .remove = idma64_platform_remove,
.driver = {
.name = LPSS_IDMA64_DRIVER_NAME,
.pm = &idma64_dev_pm_ops,
diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h
index e16dbf9ab324..c426511f2104 100644
--- a/drivers/dma/idxd/registers.h
+++ b/drivers/dma/idxd/registers.h
@@ -6,6 +6,10 @@
#include <uapi/linux/idxd.h>
/* PCI Config */
+#define PCI_DEVICE_ID_INTEL_DSA_GNRD 0x11fb
+#define PCI_DEVICE_ID_INTEL_DSA_DMR 0x1212
+#define PCI_DEVICE_ID_INTEL_IAA_DMR 0x1216
+
#define DEVICE_VERSION_1 0x100
#define DEVICE_VERSION_2 0x200
diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c
index 0532dd2640dc..4127c1bdcca7 100644
--- a/drivers/dma/img-mdc-dma.c
+++ b/drivers/dma/img-mdc-dma.c
@@ -1076,7 +1076,7 @@ static struct platform_driver mdc_dma_driver = {
.of_match_table = of_match_ptr(mdc_dma_of_match),
},
.probe = mdc_dma_probe,
- .remove_new = mdc_dma_remove,
+ .remove = mdc_dma_remove,
};
module_platform_driver(mdc_dma_driver);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index e913f0db99da..a651e0995ce8 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -1233,7 +1233,7 @@ static struct platform_driver imxdma_driver = {
.name = "imx-dma",
.of_match_table = imx_dma_of_dev_id,
},
- .remove_new = imxdma_remove,
+ .remove = imxdma_remove,
};
static int __init imxdma_module_init(void)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 72299a08af44..3449006cd14b 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2440,7 +2440,7 @@ static struct platform_driver sdma_driver = {
.name = "imx-sdma",
.of_match_table = sdma_dt_ids,
},
- .remove_new = sdma_remove,
+ .remove = sdma_remove,
.probe = sdma_probe,
};
diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index 5de8c21d41e7..acc2983e28e0 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -1028,7 +1028,7 @@ static struct platform_driver k3_pdma_driver = {
.of_match_table = k3_pdma_dt_ids,
},
.probe = k3_dma_probe,
- .remove_new = k3_dma_remove,
+ .remove = k3_dma_remove,
};
module_platform_driver(k3_pdma_driver);
diff --git a/drivers/dma/ls2x-apb-dma.c b/drivers/dma/loongson2-apb-dma.c
index 9652e8666722..367ed34ce4da 100644
--- a/drivers/dma/ls2x-apb-dma.c
+++ b/drivers/dma/loongson2-apb-dma.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Driver for the Loongson LS2X APB DMA Controller
+ * Driver for the Loongson-2 APB DMA Controller
*
* Copyright (C) 2017-2023 Loongson Corporation
*/
@@ -692,7 +692,7 @@ MODULE_DEVICE_TABLE(of, ls2x_dma_of_match_table);
static struct platform_driver ls2x_dmac_driver = {
.probe = ls2x_dma_probe,
- .remove_new = ls2x_dma_remove,
+ .remove = ls2x_dma_remove,
.driver = {
.name = "ls2x-apbdma",
.of_match_table = ls2x_dma_of_match_table,
@@ -700,6 +700,6 @@ static struct platform_driver ls2x_dmac_driver = {
};
module_platform_driver(ls2x_dmac_driver);
-MODULE_DESCRIPTION("Loongson LS2X APB DMA Controller driver");
+MODULE_DESCRIPTION("Loongson-2 APB DMA Controller driver");
MODULE_AUTHOR("Loongson Technology Corporation Limited");
MODULE_LICENSE("GPL");
diff --git a/drivers/dma/mcf-edma-main.c b/drivers/dma/mcf-edma-main.c
index 0c5862bf26f8..9e1c6400c77b 100644
--- a/drivers/dma/mcf-edma-main.c
+++ b/drivers/dma/mcf-edma-main.c
@@ -267,7 +267,7 @@ static struct platform_driver mcf_edma_driver = {
.name = "mcf-edma",
},
.probe = mcf_edma_probe,
- .remove_new = mcf_edma_remove,
+ .remove = mcf_edma_remove,
};
bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c
index b69eabf12a24..d5ddb4e30e71 100644
--- a/drivers/dma/mediatek/mtk-cqdma.c
+++ b/drivers/dma/mediatek/mtk-cqdma.c
@@ -922,7 +922,7 @@ static void mtk_cqdma_remove(struct platform_device *pdev)
static struct platform_driver mtk_cqdma_driver = {
.probe = mtk_cqdma_probe,
- .remove_new = mtk_cqdma_remove,
+ .remove = mtk_cqdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = mtk_cqdma_match,
diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c
index 58c7961ab9ad..fa77bb24a430 100644
--- a/drivers/dma/mediatek/mtk-hsdma.c
+++ b/drivers/dma/mediatek/mtk-hsdma.c
@@ -1038,7 +1038,7 @@ static void mtk_hsdma_remove(struct platform_device *pdev)
static struct platform_driver mtk_hsdma_driver = {
.probe = mtk_hsdma_probe,
- .remove_new = mtk_hsdma_remove,
+ .remove = mtk_hsdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = mtk_hsdma_match,
diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c
index 1bdc1500be40..08e15177427b 100644
--- a/drivers/dma/mediatek/mtk-uart-apdma.c
+++ b/drivers/dma/mediatek/mtk-uart-apdma.c
@@ -637,7 +637,7 @@ static const struct dev_pm_ops mtk_uart_apdma_pm_ops = {
static struct platform_driver mtk_uart_apdma_driver = {
.probe = mtk_uart_apdma_probe,
- .remove_new = mtk_uart_apdma_remove,
+ .remove = mtk_uart_apdma_remove,
.driver = {
.name = KBUILD_MODNAME,
.pm = &mtk_uart_apdma_pm_ops,
diff --git a/drivers/dma/milbeaut-hdmac.c b/drivers/dma/milbeaut-hdmac.c
index 7b41c670970a..9a5ec247ed6d 100644
--- a/drivers/dma/milbeaut-hdmac.c
+++ b/drivers/dma/milbeaut-hdmac.c
@@ -571,7 +571,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_hdmac_match);
static struct platform_driver milbeaut_hdmac_driver = {
.probe = milbeaut_hdmac_probe,
- .remove_new = milbeaut_hdmac_remove,
+ .remove = milbeaut_hdmac_remove,
.driver = {
.name = "milbeaut-m10v-hdmac",
.of_match_table = milbeaut_hdmac_match,
diff --git a/drivers/dma/milbeaut-xdmac.c b/drivers/dma/milbeaut-xdmac.c
index 2cce529b448e..58d4fd6df0bf 100644
--- a/drivers/dma/milbeaut-xdmac.c
+++ b/drivers/dma/milbeaut-xdmac.c
@@ -409,7 +409,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_xdmac_match);
static struct platform_driver milbeaut_xdmac_driver = {
.probe = milbeaut_xdmac_probe,
- .remove_new = milbeaut_xdmac_remove,
+ .remove = milbeaut_xdmac_remove,
.driver = {
.name = "milbeaut-m10v-xdmac",
.of_match_table = milbeaut_xdmac_match,
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 136fcaeff8dd..a95d31103d30 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -1137,7 +1137,7 @@ static struct platform_driver mmp_pdma_driver = {
},
.id_table = mmp_pdma_id_table,
.probe = mmp_pdma_probe,
- .remove_new = mmp_pdma_remove,
+ .remove = mmp_pdma_remove,
};
module_platform_driver(mmp_pdma_driver);
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index b76fe99e1151..c8dc504510f1 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -736,7 +736,7 @@ static struct platform_driver mmp_tdma_driver = {
.of_match_table = mmp_tdma_dt_ids,
},
.probe = mmp_tdma_probe,
- .remove_new = mmp_tdma_remove,
+ .remove = mmp_tdma_remove,
};
module_platform_driver(mmp_tdma_driver);
diff --git a/drivers/dma/moxart-dma.c b/drivers/dma/moxart-dma.c
index 66dc6d31b603..de09e1ab7767 100644
--- a/drivers/dma/moxart-dma.c
+++ b/drivers/dma/moxart-dma.c
@@ -644,7 +644,7 @@ MODULE_DEVICE_TABLE(of, moxart_dma_match);
static struct platform_driver moxart_driver = {
.probe = moxart_probe,
- .remove_new = moxart_remove,
+ .remove = moxart_remove,
.driver = {
.name = "moxart-dma-engine",
.of_match_table = moxart_dma_match,
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 68c247a46321..bf131cb5db66 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -1110,7 +1110,7 @@ MODULE_DEVICE_TABLE(of, mpc_dma_match);
static struct platform_driver mpc_dma_driver = {
.probe = mpc_dma_probe,
- .remove_new = mpc_dma_remove,
+ .remove = mpc_dma_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = mpc_dma_match,
diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c
index c8c67f4d982c..cad4d4fb51ac 100644
--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -635,7 +635,7 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
writel(MV_XOR_V2_DESC_NUM,
xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_SIZE_OFF);
- /* write the DESQ address to the DMA enngine*/
+ /* write the DESQ address to the DMA engine*/
writel(lower_32_bits(xor_dev->hw_desq),
xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_BALR_OFF);
writel(upper_32_bits(xor_dev->hw_desq),
@@ -884,7 +884,7 @@ static struct platform_driver mv_xor_v2_driver = {
.probe = mv_xor_v2_probe,
.suspend = mv_xor_v2_suspend,
.resume = mv_xor_v2_resume,
- .remove_new = mv_xor_v2_remove,
+ .remove = mv_xor_v2_remove,
.driver = {
.name = "mv_xor_v2",
.of_match_table = of_match_ptr(mv_xor_v2_dt_ids),
diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c
index 3b011a91d48e..0d6324c4e2be 100644
--- a/drivers/dma/nbpfaxi.c
+++ b/drivers/dma/nbpfaxi.c
@@ -1515,7 +1515,7 @@ static struct platform_driver nbpf_driver = {
},
.id_table = nbpf_ids,
.probe = nbpf_probe,
- .remove_new = nbpf_remove,
+ .remove = nbpf_remove,
};
module_platform_driver(nbpf_driver);
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index aa436f9e3571..57cec757d8f5 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -1252,7 +1252,7 @@ static void owl_dma_remove(struct platform_device *pdev)
static struct platform_driver owl_dma_driver = {
.probe = owl_dma_probe,
- .remove_new = owl_dma_remove,
+ .remove = owl_dma_remove,
.driver = {
.name = "dma-owl",
.of_match_table = of_match_ptr(owl_dma_match),
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 7b78759ac734..9d2a5a967a99 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4549,7 +4549,7 @@ MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
static struct platform_driver ppc440spe_adma_driver = {
.probe = ppc440spe_adma_probe,
- .remove_new = ppc440spe_adma_remove,
+ .remove = ppc440spe_adma_remove,
.driver = {
.name = "PPC440SP(E)-ADMA",
.of_match_table = ppc440spe_adma_of_match,
diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
index 31f8da810c05..e50cf3357e5e 100644
--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -1442,7 +1442,7 @@ static struct platform_driver pxad_driver = {
},
.id_table = pxad_id_table,
.probe = pxad_probe,
- .remove_new = pxad_remove,
+ .remove = pxad_remove,
};
static bool pxad_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index d43a881e43b9..bbc3276992bb 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -1469,7 +1469,7 @@ static const struct dev_pm_ops bam_dma_pm_ops = {
static struct platform_driver bam_dma_driver = {
.probe = bam_dma_probe,
- .remove_new = bam_dma_remove,
+ .remove = bam_dma_remove,
.driver = {
.name = "bam-dma-engine",
.pm = &bam_dma_pm_ops,
diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 4d2cd8d9ec74..c2b3e4452e71 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -948,7 +948,7 @@ MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
static struct platform_driver hidma_driver = {
.probe = hidma_probe,
- .remove_new = hidma_remove,
+ .remove = hidma_remove,
.shutdown = hidma_shutdown,
.driver = {
.name = "hidma",
diff --git a/drivers/dma/qcom/qcom_adm.c b/drivers/dma/qcom/qcom_adm.c
index c1db398adc84..6be54fddcee1 100644
--- a/drivers/dma/qcom/qcom_adm.c
+++ b/drivers/dma/qcom/qcom_adm.c
@@ -937,7 +937,7 @@ MODULE_DEVICE_TABLE(of, adm_of_match);
static struct platform_driver adm_dma_driver = {
.probe = adm_dma_probe,
- .remove_new = adm_dma_remove,
+ .remove = adm_dma_remove,
.driver = {
.name = "adm-dma-engine",
.of_match_table = adm_of_match,
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index 01e656c69e6c..dc1a9a05252e 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -1079,7 +1079,7 @@ static struct platform_driver sa11x0_dma_driver = {
.pm = &sa11x0_dma_pm_ops,
},
.probe = sa11x0_dma_probe,
- .remove_new = sa11x0_dma_remove,
+ .remove = sa11x0_dma_remove,
};
static int __init sa11x0_dma_init(void)
diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c
index 428473611115..7ad3c29be146 100644
--- a/drivers/dma/sf-pdma/sf-pdma.c
+++ b/drivers/dma/sf-pdma/sf-pdma.c
@@ -354,7 +354,7 @@ static irqreturn_t sf_pdma_done_isr(int irq, void *dev_id)
if (!residue) {
tasklet_hi_schedule(&chan->done_tasklet);
} else {
- /* submit next trascatioin if possible */
+ /* submit next transaction if possible */
struct sf_pdma_desc *desc = chan->desc;
desc->src_addr += desc->xfer_size - residue;
@@ -633,7 +633,7 @@ MODULE_DEVICE_TABLE(of, sf_pdma_dt_ids);
static struct platform_driver sf_pdma_driver = {
.probe = sf_pdma_probe,
- .remove_new = sf_pdma_remove,
+ .remove = sf_pdma_remove,
.driver = {
.name = "sf-pdma",
.of_match_table = sf_pdma_dt_ids,
diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig
index c0b2997ab7fd..6ea5a880b433 100644
--- a/drivers/dma/sh/Kconfig
+++ b/drivers/dma/sh/Kconfig
@@ -49,10 +49,10 @@ config RENESAS_USB_DMAC
SoCs.
config RZ_DMAC
- tristate "Renesas RZ/{G2L,V2L} DMA Controller"
- depends on ARCH_RZG2L || COMPILE_TEST
+ tristate "Renesas RZ DMA Controller"
+ depends on ARCH_R7S72100 || ARCH_RZG2L || COMPILE_TEST
select RENESAS_DMA
select DMA_VIRTUAL_CHANNELS
help
- This driver supports the general purpose DMA controller found in the
- Renesas RZ/{G2L,V2L} SoC variants.
+ This driver supports the general purpose DMA controller typically
+ found in the Renesas RZ SoC variants.
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 1094a2f82164..2679c1f09faf 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -2037,7 +2037,7 @@ static struct platform_driver rcar_dmac_driver = {
.of_match_table = rcar_dmac_of_ids,
},
.probe = rcar_dmac_probe,
- .remove_new = rcar_dmac_remove,
+ .remove = rcar_dmac_remove,
.shutdown = rcar_dmac_shutdown,
};
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 811389fc9cb8..9235db551026 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -893,7 +893,7 @@ static int rz_dmac_probe(struct platform_device *pdev)
/* Initialize the channels. */
INIT_LIST_HEAD(&dmac->engine.channels);
- dmac->rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
+ dmac->rstc = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
if (IS_ERR(dmac->rstc))
return dev_err_probe(&pdev->dev, PTR_ERR(dmac->rstc),
"failed to get resets\n");
@@ -1004,7 +1004,7 @@ static struct platform_driver rz_dmac_driver = {
.of_match_table = of_rz_dmac_match,
},
.probe = rz_dmac_probe,
- .remove_new = rz_dmac_remove,
+ .remove = rz_dmac_remove,
};
module_platform_driver(rz_dmac_driver);
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index 588c5f409a80..fdd41e1c2263 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -961,7 +961,7 @@ void shdma_chan_probe(struct shdma_dev *sdev,
spin_lock_init(&schan->chan_lock);
- /* Init descripter manage list */
+ /* Init descriptor manage list */
INIT_LIST_HEAD(&schan->ld_queue);
INIT_LIST_HEAD(&schan->ld_free);
diff --git a/drivers/dma/sh/shdmac.c b/drivers/dma/sh/shdmac.c
index 8ead0a1fd237..093e449e19ee 100644
--- a/drivers/dma/sh/shdmac.c
+++ b/drivers/dma/sh/shdmac.c
@@ -906,7 +906,7 @@ static struct platform_driver sh_dmae_driver = {
.pm = &sh_dmae_pm,
.name = SH_DMAE_DRV_NAME,
},
- .remove_new = sh_dmae_remove,
+ .remove = sh_dmae_remove,
};
static int __init sh_dmae_init(void)
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
index f7cd0cad056c..7e2b6c97fa2f 100644
--- a/drivers/dma/sh/usb-dmac.c
+++ b/drivers/dma/sh/usb-dmac.c
@@ -301,7 +301,7 @@ static struct usb_dmac_desc *usb_dmac_desc_get(struct usb_dmac_chan *chan,
struct usb_dmac_desc *desc = NULL;
unsigned long flags;
- /* Get a freed descritpor */
+ /* Get a freed descriptor */
spin_lock_irqsave(&chan->vc.lock, flags);
list_for_each_entry(desc, &chan->desc_freed, node) {
if (sg_len <= desc->sg_allocated_len) {
@@ -899,7 +899,7 @@ static struct platform_driver usb_dmac_driver = {
.of_match_table = usb_dmac_of_ids,
},
.probe = usb_dmac_probe,
- .remove_new = usb_dmac_remove,
+ .remove = usb_dmac_remove,
.shutdown = usb_dmac_shutdown,
};
diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c
index 3f54ff37c5e0..187a090463ce 100644
--- a/drivers/dma/sprd-dma.c
+++ b/drivers/dma/sprd-dma.c
@@ -1298,7 +1298,7 @@ static const struct dev_pm_ops sprd_dma_pm_ops = {
static struct platform_driver sprd_dma_driver = {
.probe = sprd_dma_probe,
- .remove_new = sprd_dma_remove,
+ .remove = sprd_dma_remove,
.driver = {
.name = "sprd-dma",
.of_match_table = sprd_dma_match,
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
index 8880b5e336f8..c65ee0c7bfbd 100644
--- a/drivers/dma/st_fdma.c
+++ b/drivers/dma/st_fdma.c
@@ -858,7 +858,7 @@ static struct platform_driver st_fdma_platform_driver = {
.of_match_table = st_fdma_match,
},
.probe = st_fdma_probe,
- .remove_new = st_fdma_remove,
+ .remove = st_fdma_remove,
};
module_platform_driver(st_fdma_platform_driver);
diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c
index 0be6e944df6f..0c6c4258b195 100644
--- a/drivers/dma/stm32/stm32-dma3.c
+++ b/drivers/dma/stm32/stm32-dma3.c
@@ -221,6 +221,8 @@ enum stm32_dma3_port_data_width {
#define STM32_DMA3_DT_BREQ BIT(8) /* CTR2_BREQ */
#define STM32_DMA3_DT_PFREQ BIT(9) /* CTR2_PFREQ */
#define STM32_DMA3_DT_TCEM GENMASK(13, 12) /* CTR2_TCEM */
+#define STM32_DMA3_DT_NOPACK BIT(16) /* CTR1_PAM */
+#define STM32_DMA3_DT_NOREFACT BIT(17)
/* struct stm32_dma3_chan .config_set bitfield */
#define STM32_DMA3_CFG_SET_DT BIT(0)
@@ -228,6 +230,8 @@ enum stm32_dma3_port_data_width {
#define STM32_DMA3_CFG_SET_BOTH (STM32_DMA3_CFG_SET_DT | STM32_DMA3_CFG_SET_DMA)
#define STM32_DMA3_MAX_BLOCK_SIZE ALIGN_DOWN(CBR1_BNDT, 64)
+#define STM32_DMA3_MAX_BURST_LEN (1 + min_t(u32, FIELD_MAX(CTR1_SBL_1), \
+ FIELD_MAX(CTR1_DBL_1)))
#define port_is_ahb(maxdw) ({ typeof(maxdw) (_maxdw) = (maxdw); \
((_maxdw) != DW_INVALID) && ((_maxdw) == DW_32); })
#define port_is_axi(maxdw) ({ typeof(maxdw) (_maxdw) = (maxdw); \
@@ -293,6 +297,10 @@ struct stm32_dma3_chan {
u32 dma_status;
};
+struct stm32_dma3_pdata {
+ u32 axi_max_burst_len;
+};
+
struct stm32_dma3_ddata {
struct dma_device dma_dev;
void __iomem *base;
@@ -301,6 +309,7 @@ struct stm32_dma3_ddata {
u32 dma_channels;
u32 dma_requests;
enum stm32_dma3_port_data_width ports_max_dw[2];
+ u32 axi_max_burst_len;
};
static inline struct stm32_dma3_ddata *to_stm32_dma3_ddata(struct stm32_dma3_chan *chan)
@@ -533,7 +542,8 @@ static enum dma_slave_buswidth stm32_dma3_get_max_dw(u32 chan_max_burst,
return 1 << __ffs(len | addr | max_dw);
}
-static u32 stm32_dma3_get_max_burst(u32 len, enum dma_slave_buswidth dw, u32 chan_max_burst)
+static u32 stm32_dma3_get_max_burst(u32 len, enum dma_slave_buswidth dw,
+ u32 chan_max_burst, u32 bus_max_burst)
{
u32 max_burst = chan_max_burst ? chan_max_burst / dw : 1;
@@ -544,8 +554,9 @@ static u32 stm32_dma3_get_max_burst(u32 len, enum dma_slave_buswidth dw, u32 cha
/*
* HW doesn't modify the burst if burst size <= half of the fifo size.
* If len is not a multiple of burst size, last burst is shortened by HW.
+ * Take care of maximum burst supported on interconnect bus.
*/
- return max_burst;
+ return min_t(u32, max_burst, bus_max_burst);
}
static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transfer_direction dir,
@@ -554,6 +565,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
{
struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan);
struct dma_device dma_device = ddata->dma_dev;
+ u32 src_max_burst = STM32_DMA3_MAX_BURST_LEN, dst_max_burst = STM32_DMA3_MAX_BURST_LEN;
u32 sdw, ddw, sbl_max, dbl_max, tcem, init_dw, init_bl_max;
u32 _ctr1 = 0, _ctr2 = 0;
u32 ch_conf = chan->dt_config.ch_conf;
@@ -594,10 +606,14 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
_ctr1 |= CTR1_SINC;
if (sap)
_ctr1 |= CTR1_SAP;
+ if (port_is_axi(sap_max_dw)) /* AXI - apply axi maximum burst limitation */
+ src_max_burst = ddata->axi_max_burst_len;
if (FIELD_GET(STM32_DMA3_DT_DINC, tr_conf))
_ctr1 |= CTR1_DINC;
if (dap)
_ctr1 |= CTR1_DAP;
+ if (port_is_axi(dap_max_dw)) /* AXI - apply axi maximum burst limitation */
+ dst_max_burst = ddata->axi_max_burst_len;
_ctr2 |= FIELD_PREP(CTR2_REQSEL, chan->dt_config.req_line) & ~CTR2_SWREQ;
if (FIELD_GET(STM32_DMA3_DT_BREQ, tr_conf))
@@ -617,11 +633,16 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
/* Set destination (device) data width and burst */
ddw = min_t(u32, ddw, stm32_dma3_get_max_dw(chan->max_burst, dap_max_dw,
len, dst_addr));
- dbl_max = min_t(u32, dbl_max, stm32_dma3_get_max_burst(len, ddw, chan->max_burst));
+ dbl_max = min_t(u32, dbl_max, stm32_dma3_get_max_burst(len, ddw, chan->max_burst,
+ dst_max_burst));
/* Set source (memory) data width and burst */
sdw = stm32_dma3_get_max_dw(chan->max_burst, sap_max_dw, len, src_addr);
- sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst);
+ sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst, src_max_burst);
+ if (!!FIELD_GET(STM32_DMA3_DT_NOPACK, tr_conf)) {
+ sdw = ddw;
+ sbl_max = dbl_max;
+ }
_ctr1 |= FIELD_PREP(CTR1_SDW_LOG2, ilog2(sdw));
_ctr1 |= FIELD_PREP(CTR1_SBL_1, sbl_max - 1);
@@ -647,11 +668,17 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
/* Set source (device) data width and burst */
sdw = min_t(u32, sdw, stm32_dma3_get_max_dw(chan->max_burst, sap_max_dw,
len, src_addr));
- sbl_max = min_t(u32, sbl_max, stm32_dma3_get_max_burst(len, sdw, chan->max_burst));
+ sbl_max = min_t(u32, sbl_max, stm32_dma3_get_max_burst(len, sdw, chan->max_burst,
+ src_max_burst));
/* Set destination (memory) data width and burst */
ddw = stm32_dma3_get_max_dw(chan->max_burst, dap_max_dw, len, dst_addr);
- dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst);
+ dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst, dst_max_burst);
+ if (!!FIELD_GET(STM32_DMA3_DT_NOPACK, tr_conf) ||
+ ((_ctr2 & CTR2_PFREQ) && ddw > sdw)) { /* Packing to wider ddw not supported */
+ ddw = sdw;
+ dbl_max = sbl_max;
+ }
_ctr1 |= FIELD_PREP(CTR1_SDW_LOG2, ilog2(sdw));
_ctr1 |= FIELD_PREP(CTR1_SBL_1, sbl_max - 1);
@@ -678,22 +705,24 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
init_dw = sdw;
init_bl_max = sbl_max;
sdw = stm32_dma3_get_max_dw(chan->max_burst, sap_max_dw, len, src_addr);
- sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst);
+ sbl_max = stm32_dma3_get_max_burst(len, sdw, chan->max_burst, src_max_burst);
if (chan->config_set & STM32_DMA3_CFG_SET_DMA) {
sdw = min_t(u32, init_dw, sdw);
- sbl_max = min_t(u32, init_bl_max,
- stm32_dma3_get_max_burst(len, sdw, chan->max_burst));
+ sbl_max = min_t(u32, init_bl_max, stm32_dma3_get_max_burst(len, sdw,
+ chan->max_burst,
+ src_max_burst));
}
/* Set destination (memory) data width and burst */
init_dw = ddw;
init_bl_max = dbl_max;
ddw = stm32_dma3_get_max_dw(chan->max_burst, dap_max_dw, len, dst_addr);
- dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst);
+ dbl_max = stm32_dma3_get_max_burst(len, ddw, chan->max_burst, dst_max_burst);
if (chan->config_set & STM32_DMA3_CFG_SET_DMA) {
ddw = min_t(u32, init_dw, ddw);
- dbl_max = min_t(u32, init_bl_max,
- stm32_dma3_get_max_burst(len, ddw, chan->max_burst));
+ dbl_max = min_t(u32, init_bl_max, stm32_dma3_get_max_burst(len, ddw,
+ chan->max_burst,
+ dst_max_burst));
}
_ctr1 |= FIELD_PREP(CTR1_SDW_LOG2, ilog2(sdw));
@@ -1116,6 +1145,28 @@ static void stm32_dma3_free_chan_resources(struct dma_chan *c)
chan->config_set = 0;
}
+static u32 stm32_dma3_get_ll_count(struct stm32_dma3_chan *chan, size_t len, bool prevent_refactor)
+{
+ u32 count;
+
+ if (prevent_refactor)
+ return DIV_ROUND_UP(len, STM32_DMA3_MAX_BLOCK_SIZE);
+
+ count = len / STM32_DMA3_MAX_BLOCK_SIZE;
+ len -= (len / STM32_DMA3_MAX_BLOCK_SIZE) * STM32_DMA3_MAX_BLOCK_SIZE;
+
+ if (len >= chan->max_burst) {
+ count += 1; /* len < STM32_DMA3_MAX_BLOCK_SIZE here, so it fits in one item */
+ len -= (len / chan->max_burst) * chan->max_burst;
+ }
+
+ /* Unaligned remainder fits in one extra item */
+ if (len > 0)
+ count += 1;
+
+ return count;
+}
+
static void stm32_dma3_init_chan_config_for_memcpy(struct stm32_dma3_chan *chan,
dma_addr_t dst, dma_addr_t src)
{
@@ -1150,8 +1201,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_memcpy(struct dma_cha
struct stm32_dma3_swdesc *swdesc;
size_t next_size, offset;
u32 count, i, ctr1, ctr2;
+ bool prevent_refactor = !!FIELD_GET(STM32_DMA3_DT_NOPACK, chan->dt_config.tr_conf) ||
+ !!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf);
- count = DIV_ROUND_UP(len, STM32_DMA3_MAX_BLOCK_SIZE);
+ count = stm32_dma3_get_ll_count(chan, len, prevent_refactor);
swdesc = stm32_dma3_chan_desc_alloc(chan, count);
if (!swdesc)
@@ -1167,6 +1220,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_memcpy(struct dma_cha
remaining = len - offset;
next_size = min_t(size_t, remaining, STM32_DMA3_MAX_BLOCK_SIZE);
+ if (!prevent_refactor &&
+ (next_size < STM32_DMA3_MAX_BLOCK_SIZE && next_size >= chan->max_burst))
+ next_size = chan->max_burst * (remaining / chan->max_burst);
+
ret = stm32_dma3_chan_prep_hw(chan, DMA_MEM_TO_MEM, &swdesc->ccr, &ctr1, &ctr2,
src + offset, dst + offset, next_size);
if (ret)
@@ -1203,14 +1260,13 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan
size_t len;
dma_addr_t sg_addr, dev_addr, src, dst;
u32 i, j, count, ctr1, ctr2;
+ bool prevent_refactor = !!FIELD_GET(STM32_DMA3_DT_NOPACK, chan->dt_config.tr_conf) ||
+ !!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf);
int ret;
- count = sg_len;
- for_each_sg(sgl, sg, sg_len, i) {
- len = sg_dma_len(sg);
- if (len > STM32_DMA3_MAX_BLOCK_SIZE)
- count += DIV_ROUND_UP(len, STM32_DMA3_MAX_BLOCK_SIZE) - 1;
- }
+ count = 0;
+ for_each_sg(sgl, sg, sg_len, i)
+ count += stm32_dma3_get_ll_count(chan, sg_dma_len(sg), prevent_refactor);
swdesc = stm32_dma3_chan_desc_alloc(chan, count);
if (!swdesc)
@@ -1227,6 +1283,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan
do {
size_t chunk = min_t(size_t, len, STM32_DMA3_MAX_BLOCK_SIZE);
+ if (!prevent_refactor &&
+ (chunk < STM32_DMA3_MAX_BLOCK_SIZE && chunk >= chan->max_burst))
+ chunk = chan->max_burst * (len / chan->max_burst);
+
if (dir == DMA_MEM_TO_DEV) {
src = sg_addr;
dst = dev_addr;
@@ -1259,6 +1319,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan
} while (len);
}
+ if (count != sg_len && chan->tcem != CTR2_TCEM_CHANNEL)
+ dev_warn(chan2dev(chan), "Linked-list refactored, %d items instead of %d\n",
+ count, sg_len);
+
/* Enable Error interrupts */
swdesc->ccr |= CCR_USEIE | CCR_ULEIE | CCR_DTEIE;
/* Enable Transfer state interrupts */
@@ -1601,8 +1665,12 @@ static u32 stm32_dma3_check_rif(struct stm32_dma3_ddata *ddata)
return chan_reserved;
}
+static struct stm32_dma3_pdata stm32mp25_pdata = {
+ .axi_max_burst_len = 16,
+};
+
static const struct of_device_id stm32_dma3_of_match[] = {
- { .compatible = "st,stm32mp25-dma3", },
+ { .compatible = "st,stm32mp25-dma3", .data = &stm32mp25_pdata, },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, stm32_dma3_of_match);
@@ -1610,6 +1678,7 @@ MODULE_DEVICE_TABLE(of, stm32_dma3_of_match);
static int stm32_dma3_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ const struct stm32_dma3_pdata *pdata;
struct stm32_dma3_ddata *ddata;
struct reset_control *reset;
struct stm32_dma3_chan *chan;
@@ -1704,6 +1773,16 @@ static int stm32_dma3_probe(struct platform_device *pdev)
else /* Dual master ports */
ddata->ports_max_dw[1] = FIELD_GET(G_M1_DATA_WIDTH_ENC, hwcfgr);
+ /* axi_max_burst_len is optional, if not defined, use STM32_DMA3_MAX_BURST_LEN */
+ ddata->axi_max_burst_len = STM32_DMA3_MAX_BURST_LEN;
+ pdata = device_get_match_data(&pdev->dev);
+ if (pdata && pdata->axi_max_burst_len) {
+ ddata->axi_max_burst_len = min_t(u32, pdata->axi_max_burst_len,
+ STM32_DMA3_MAX_BURST_LEN);
+ dev_dbg(&pdev->dev, "Burst is limited to %u beats through AXI port\n",
+ ddata->axi_max_burst_len);
+ }
+
ddata->chans = devm_kcalloc(&pdev->dev, ddata->dma_channels, sizeof(*ddata->chans),
GFP_KERNEL);
if (!ddata->chans) {
@@ -1827,7 +1906,7 @@ static const struct dev_pm_ops stm32_dma3_pm_ops = {
static struct platform_driver stm32_dma3_driver = {
.probe = stm32_dma3_probe,
- .remove_new = stm32_dma3_remove,
+ .remove = stm32_dma3_remove,
.driver = {
.name = "stm32-dma3",
.of_match_table = stm32_dma3_of_match,
diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 2e7f9b07fdd2..f37cdf6f2179 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -1292,7 +1292,7 @@ MODULE_DEVICE_TABLE(of, sun4i_dma_match);
static struct platform_driver sun4i_dma_driver = {
.probe = sun4i_dma_probe,
- .remove_new = sun4i_dma_remove,
+ .remove = sun4i_dma_remove,
.driver = {
.name = "sun4i-dma",
.of_match_table = sun4i_dma_match,
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 583bf49031cf..95ecb12caaa5 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1488,7 +1488,7 @@ static void sun6i_dma_remove(struct platform_device *pdev)
static struct platform_driver sun6i_dma_driver = {
.probe = sun6i_dma_probe,
- .remove_new = sun6i_dma_remove,
+ .remove = sun6i_dma_remove,
.driver = {
.name = "sun6i-dma",
.of_match_table = sun6i_dma_match,
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 3642508e88bb..cacf3757adc2 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -1532,7 +1532,7 @@ static struct platform_driver tegra_dma_driver = {
.of_match_table = tegra_dma_of_match,
},
.probe = tegra_dma_probe,
- .remove_new = tegra_dma_remove,
+ .remove = tegra_dma_remove,
};
module_platform_driver(tegra_dma_driver);
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 7d1acda2d72b..14a61e53a41b 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1675,7 +1675,7 @@ static struct platform_driver tegra_dmac_driver = {
.of_match_table = tegra_dma_of_match,
},
.probe = tegra_dma_probe,
- .remove_new = tegra_dma_remove,
+ .remove = tegra_dma_remove,
};
module_platform_driver(tegra_dmac_driver);
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 24ad7077c53b..2953008d42ef 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -1008,7 +1008,7 @@ static struct platform_driver tegra_admac_driver = {
.of_match_table = tegra_adma_of_match,
},
.probe = tegra_adma_probe,
- .remove_new = tegra_adma_remove,
+ .remove = tegra_adma_remove,
};
module_platform_driver(tegra_admac_driver);
diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
index a8bb70c2d109..8d8c3d6038fc 100644
--- a/drivers/dma/ti/cppi41.c
+++ b/drivers/dma/ti/cppi41.c
@@ -1243,7 +1243,7 @@ static const struct dev_pm_ops cppi41_pm_ops = {
static struct platform_driver cpp41_dma_driver = {
.probe = cppi41_dma_probe,
- .remove_new = cppi41_dma_remove,
+ .remove = cppi41_dma_remove,
.driver = {
.name = "cppi41-dma-engine",
.pm = &cppi41_pm_ops,
diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c
index 5f8d2e93ff3f..343e986e66e7 100644
--- a/drivers/dma/ti/edma.c
+++ b/drivers/dma/ti/edma.c
@@ -2636,7 +2636,7 @@ static const struct dev_pm_ops edma_pm_ops = {
static struct platform_driver edma_driver = {
.probe = edma_probe,
- .remove_new = edma_remove,
+ .remove = edma_remove,
.driver = {
.name = "edma",
.pm = &edma_pm_ops,
diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
index 6ab9bfbdc480..8c023c6e623a 100644
--- a/drivers/dma/ti/omap-dma.c
+++ b/drivers/dma/ti/omap-dma.c
@@ -1915,7 +1915,7 @@ MODULE_DEVICE_TABLE(of, omap_dma_match);
static struct platform_driver omap_dma_driver = {
.probe = omap_dma_probe,
- .remove_new = omap_dma_remove,
+ .remove = omap_dma_remove,
.driver = {
.name = "omap-dma-engine",
.of_match_table = omap_dma_match,
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 7410025605e0..ecaf002558af 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -761,7 +761,7 @@ static struct platform_driver td_driver = {
.name = DRIVER_NAME,
},
.probe = td_probe,
- .remove_new = td_remove,
+ .remove = td_remove,
};
module_platform_driver(td_driver);
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 44ba377b4b5a..35d5221683b2 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -1260,14 +1260,14 @@ static const struct dev_pm_ops txx9dmac_dev_pm_ops = {
};
static struct platform_driver txx9dmac_chan_driver = {
- .remove_new = txx9dmac_chan_remove,
+ .remove = txx9dmac_chan_remove,
.driver = {
.name = "txx9dmac-chan",
},
};
static struct platform_driver txx9dmac_driver = {
- .remove_new = txx9dmac_remove,
+ .remove = txx9dmac_remove,
.shutdown = txx9dmac_shutdown,
.driver = {
.name = "txx9dmac",
diff --git a/drivers/dma/uniphier-mdmac.c b/drivers/dma/uniphier-mdmac.c
index ad7125f6e2ca..7a99f86ecb5a 100644
--- a/drivers/dma/uniphier-mdmac.c
+++ b/drivers/dma/uniphier-mdmac.c
@@ -493,7 +493,7 @@ MODULE_DEVICE_TABLE(of, uniphier_mdmac_match);
static struct platform_driver uniphier_mdmac_driver = {
.probe = uniphier_mdmac_probe,
- .remove_new = uniphier_mdmac_remove,
+ .remove = uniphier_mdmac_remove,
.driver = {
.name = "uniphier-mio-dmac",
.of_match_table = uniphier_mdmac_match,
diff --git a/drivers/dma/uniphier-xdmac.c b/drivers/dma/uniphier-xdmac.c
index 3ce2dc2ad9de..ceeb6171c9d1 100644
--- a/drivers/dma/uniphier-xdmac.c
+++ b/drivers/dma/uniphier-xdmac.c
@@ -603,7 +603,7 @@ MODULE_DEVICE_TABLE(of, uniphier_xdmac_match);
static struct platform_driver uniphier_xdmac_driver = {
.probe = uniphier_xdmac_probe,
- .remove_new = uniphier_xdmac_remove,
+ .remove = uniphier_xdmac_remove,
.driver = {
.name = "uniphier-xdmac",
.of_match_table = uniphier_xdmac_match,
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
index 275848a9c450..f64624ea44ad 100644
--- a/drivers/dma/xgene-dma.c
+++ b/drivers/dma/xgene-dma.c
@@ -1815,7 +1815,7 @@ MODULE_DEVICE_TABLE(of, xgene_dma_of_match_ptr);
static struct platform_driver xgene_dma_driver = {
.probe = xgene_dma_probe,
- .remove_new = xgene_dma_remove,
+ .remove = xgene_dma_remove,
.driver = {
.name = "X-Gene-DMA",
.of_match_table = xgene_dma_of_match_ptr,
diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
index 718842fdaf98..93772abc3b49 100644
--- a/drivers/dma/xilinx/xdma.c
+++ b/drivers/dma/xilinx/xdma.c
@@ -1315,7 +1315,7 @@ static struct platform_driver xdma_driver = {
},
.id_table = xdma_id_table,
.probe = xdma_probe,
- .remove_new = xdma_remove,
+ .remove = xdma_remove,
};
module_platform_driver(xdma_driver);
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 5eb51ae93e89..1bdd57de87a6 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -3271,7 +3271,7 @@ static struct platform_driver xilinx_vdma_driver = {
.of_match_table = xilinx_dma_of_ids,
},
.probe = xilinx_dma_probe,
- .remove_new = xilinx_dma_remove,
+ .remove = xilinx_dma_remove,
};
module_platform_driver(xilinx_vdma_driver);
diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
index be87764af9e8..ee5d9fdbfd7f 100644
--- a/drivers/dma/xilinx/xilinx_dpdma.c
+++ b/drivers/dma/xilinx/xilinx_dpdma.c
@@ -1863,7 +1863,7 @@ MODULE_DEVICE_TABLE(of, xilinx_dpdma_of_match);
static struct platform_driver xilinx_dpdma_driver = {
.probe = xilinx_dpdma_probe,
- .remove_new = xilinx_dpdma_remove,
+ .remove = xilinx_dpdma_remove,
.driver = {
.name = "xilinx-zynqmp-dpdma",
.of_match_table = xilinx_dpdma_of_match,
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index 9ae46f1198fe..d05fc5fcc77d 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -366,7 +366,7 @@ static void zynqmp_dma_init(struct zynqmp_dma_chan *chan)
}
writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
- /* Clearing the interrupt account rgisters */
+ /* Clearing the interrupt account registers */
val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT);
val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
@@ -1192,7 +1192,7 @@ static struct platform_driver zynqmp_dma_driver = {
.pm = &zynqmp_dma_dev_pm_ops,
},
.probe = zynqmp_dma_probe,
- .remove_new = zynqmp_dma_remove,
+ .remove = zynqmp_dma_remove,
};
module_platform_driver(zynqmp_dma_driver);
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index fc0280dcddd1..c130f87147fa 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -170,6 +170,27 @@ dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll,
}
static int
+dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_device_ops *ops = dpll_device_ops(dpll);
+ DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 };
+ enum dpll_clock_quality_level ql;
+ int ret;
+
+ if (!ops->clock_quality_level_get)
+ return 0;
+ ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack);
+ if (ret)
+ return ret;
+ for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX)
+ if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int
dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin,
struct dpll_pin_ref *ref,
struct netlink_ext_ack *extack)
@@ -559,6 +580,9 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
ret = dpll_msg_add_lock_status(msg, dpll, extack);
if (ret)
return ret;
+ ret = dpll_msg_add_clock_quality_level(msg, dpll, extack);
+ if (ret)
+ return ret;
ret = dpll_msg_add_mode(msg, dpll, extack);
if (ret)
return ret;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 81af6c344d6b..06f7b43a6f78 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -311,24 +311,6 @@ config EDAC_CELL
Cell Broadband Engine internal memory controller
on platform without a hypervisor
-config EDAC_AMD8131
- tristate "AMD8131 HyperTransport PCI-X Tunnel"
- depends on PCI && PPC_MAPLE
- help
- Support for error detection and correction on the
- AMD8131 HyperTransport PCI-X Tunnel chip.
- Note, add more Kconfig dependency if it's adopted
- on some machine other than Maple.
-
-config EDAC_AMD8111
- tristate "AMD8111 HyperTransport I/O Hub"
- depends on PCI && PPC_MAPLE
- help
- Support for error detection and correction on the
- AMD8111 HyperTransport I/O Hub chip.
- Note, add more Kconfig dependency if it's adopted
- on some machine other than Maple.
-
config EDAC_CPC925
tristate "IBM CPC925 Memory Controller (PPC970FX)"
depends on PPC64
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index faf310eec4a6..f9cf19d8d13d 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -63,8 +63,6 @@ i10nm_edac-y := i10nm_base.o
obj-$(CONFIG_EDAC_I10NM) += i10nm_edac.o skx_edac_common.o
obj-$(CONFIG_EDAC_CELL) += cell_edac.o
-obj-$(CONFIG_EDAC_AMD8111) += amd8111_edac.o
-obj-$(CONFIG_EDAC_AMD8131) += amd8131_edac.o
obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o
obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o
diff --git a/drivers/edac/amd8111_edac.c b/drivers/edac/amd8111_edac.c
deleted file mode 100644
index a6d3013d5823..000000000000
--- a/drivers/edac/amd8111_edac.c
+++ /dev/null
@@ -1,596 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * amd8111_edac.c, AMD8111 Hyper Transport chip EDAC kernel module
- *
- * Copyright (c) 2008 Wind River Systems, Inc.
- *
- * Authors: Cao Qingtao <qingtao.cao@windriver.com>
- * Benjamin Walsh <benjamin.walsh@windriver.com>
- * Hu Yongqi <yongqi.hu@windriver.com>
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/edac.h>
-#include <linux/pci_ids.h>
-#include <asm/io.h>
-
-#include "edac_module.h"
-#include "amd8111_edac.h"
-
-#define AMD8111_EDAC_REVISION " Ver: 1.0.0"
-#define AMD8111_EDAC_MOD_STR "amd8111_edac"
-
-#define PCI_DEVICE_ID_AMD_8111_PCI 0x7460
-
-enum amd8111_edac_devs {
- LPC_BRIDGE = 0,
-};
-
-enum amd8111_edac_pcis {
- PCI_BRIDGE = 0,
-};
-
-/* Wrapper functions for accessing PCI configuration space */
-static int edac_pci_read_dword(struct pci_dev *dev, int reg, u32 *val32)
-{
- int ret;
-
- ret = pci_read_config_dword(dev, reg, val32);
- if (ret != 0)
- printk(KERN_ERR AMD8111_EDAC_MOD_STR
- " PCI Access Read Error at 0x%x\n", reg);
-
- return ret;
-}
-
-static void edac_pci_read_byte(struct pci_dev *dev, int reg, u8 *val8)
-{
- int ret;
-
- ret = pci_read_config_byte(dev, reg, val8);
- if (ret != 0)
- printk(KERN_ERR AMD8111_EDAC_MOD_STR
- " PCI Access Read Error at 0x%x\n", reg);
-}
-
-static void edac_pci_write_dword(struct pci_dev *dev, int reg, u32 val32)
-{
- int ret;
-
- ret = pci_write_config_dword(dev, reg, val32);
- if (ret != 0)
- printk(KERN_ERR AMD8111_EDAC_MOD_STR
- " PCI Access Write Error at 0x%x\n", reg);
-}
-
-static void edac_pci_write_byte(struct pci_dev *dev, int reg, u8 val8)
-{
- int ret;
-
- ret = pci_write_config_byte(dev, reg, val8);
- if (ret != 0)
- printk(KERN_ERR AMD8111_EDAC_MOD_STR
- " PCI Access Write Error at 0x%x\n", reg);
-}
-
-/*
- * device-specific methods for amd8111 PCI Bridge Controller
- *
- * Error Reporting and Handling for amd8111 chipset could be found
- * in its datasheet 3.1.2 section, P37
- */
-static void amd8111_pci_bridge_init(struct amd8111_pci_info *pci_info)
-{
- u32 val32;
- struct pci_dev *dev = pci_info->dev;
-
- /* First clear error detection flags on the host interface */
-
- /* Clear SSE/SMA/STA flags in the global status register*/
- edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
- if (val32 & PCI_STSCMD_CLEAR_MASK)
- edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
-
- /* Clear CRC and Link Fail flags in HT Link Control reg */
- edac_pci_read_dword(dev, REG_HT_LINK, &val32);
- if (val32 & HT_LINK_CLEAR_MASK)
- edac_pci_write_dword(dev, REG_HT_LINK, val32);
-
- /* Second clear all fault on the secondary interface */
-
- /* Clear error flags in the memory-base limit reg. */
- edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
- if (val32 & MEM_LIMIT_CLEAR_MASK)
- edac_pci_write_dword(dev, REG_MEM_LIM, val32);
-
- /* Clear Discard Timer Expired flag in Interrupt/Bridge Control reg */
- edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
- if (val32 & PCI_INTBRG_CTRL_CLEAR_MASK)
- edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
-
- /* Last enable error detections */
- if (edac_op_state == EDAC_OPSTATE_POLL) {
- /* Enable System Error reporting in global status register */
- edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
- val32 |= PCI_STSCMD_SERREN;
- edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
-
- /* Enable CRC Sync flood packets to HyperTransport Link */
- edac_pci_read_dword(dev, REG_HT_LINK, &val32);
- val32 |= HT_LINK_CRCFEN;
- edac_pci_write_dword(dev, REG_HT_LINK, val32);
-
- /* Enable SSE reporting etc in Interrupt control reg */
- edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
- val32 |= PCI_INTBRG_CTRL_POLL_MASK;
- edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
- }
-}
-
-static void amd8111_pci_bridge_exit(struct amd8111_pci_info *pci_info)
-{
- u32 val32;
- struct pci_dev *dev = pci_info->dev;
-
- if (edac_op_state == EDAC_OPSTATE_POLL) {
- /* Disable System Error reporting */
- edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
- val32 &= ~PCI_STSCMD_SERREN;
- edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
-
- /* Disable CRC flood packets */
- edac_pci_read_dword(dev, REG_HT_LINK, &val32);
- val32 &= ~HT_LINK_CRCFEN;
- edac_pci_write_dword(dev, REG_HT_LINK, val32);
-
- /* Disable DTSERREN/MARSP/SERREN in Interrupt Control reg */
- edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
- val32 &= ~PCI_INTBRG_CTRL_POLL_MASK;
- edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
- }
-}
-
-static void amd8111_pci_bridge_check(struct edac_pci_ctl_info *edac_dev)
-{
- struct amd8111_pci_info *pci_info = edac_dev->pvt_info;
- struct pci_dev *dev = pci_info->dev;
- u32 val32;
-
- /* Check out PCI Bridge Status and Command Register */
- edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
- if (val32 & PCI_STSCMD_CLEAR_MASK) {
- printk(KERN_INFO "Error(s) in PCI bridge status and command"
- "register on device %s\n", pci_info->ctl_name);
- printk(KERN_INFO "SSE: %d, RMA: %d, RTA: %d\n",
- (val32 & PCI_STSCMD_SSE) != 0,
- (val32 & PCI_STSCMD_RMA) != 0,
- (val32 & PCI_STSCMD_RTA) != 0);
-
- val32 |= PCI_STSCMD_CLEAR_MASK;
- edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-
- /* Check out HyperTransport Link Control Register */
- edac_pci_read_dword(dev, REG_HT_LINK, &val32);
- if (val32 & HT_LINK_LKFAIL) {
- printk(KERN_INFO "Error(s) in hypertransport link control"
- "register on device %s\n", pci_info->ctl_name);
- printk(KERN_INFO "LKFAIL: %d\n",
- (val32 & HT_LINK_LKFAIL) != 0);
-
- val32 |= HT_LINK_LKFAIL;
- edac_pci_write_dword(dev, REG_HT_LINK, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-
- /* Check out PCI Interrupt and Bridge Control Register */
- edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
- if (val32 & PCI_INTBRG_CTRL_DTSTAT) {
- printk(KERN_INFO "Error(s) in PCI interrupt and bridge control"
- "register on device %s\n", pci_info->ctl_name);
- printk(KERN_INFO "DTSTAT: %d\n",
- (val32 & PCI_INTBRG_CTRL_DTSTAT) != 0);
-
- val32 |= PCI_INTBRG_CTRL_DTSTAT;
- edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-
- /* Check out PCI Bridge Memory Base-Limit Register */
- edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
- if (val32 & MEM_LIMIT_CLEAR_MASK) {
- printk(KERN_INFO
- "Error(s) in mem limit register on %s device\n",
- pci_info->ctl_name);
- printk(KERN_INFO "DPE: %d, RSE: %d, RMA: %d\n"
- "RTA: %d, STA: %d, MDPE: %d\n",
- (val32 & MEM_LIMIT_DPE) != 0,
- (val32 & MEM_LIMIT_RSE) != 0,
- (val32 & MEM_LIMIT_RMA) != 0,
- (val32 & MEM_LIMIT_RTA) != 0,
- (val32 & MEM_LIMIT_STA) != 0,
- (val32 & MEM_LIMIT_MDPE) != 0);
-
- val32 |= MEM_LIMIT_CLEAR_MASK;
- edac_pci_write_dword(dev, REG_MEM_LIM, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-}
-
-static struct resource *legacy_io_res;
-static int at_compat_reg_broken;
-#define LEGACY_NR_PORTS 1
-
-/* device-specific methods for amd8111 LPC Bridge device */
-static void amd8111_lpc_bridge_init(struct amd8111_dev_info *dev_info)
-{
- u8 val8;
- struct pci_dev *dev = dev_info->dev;
-
- /* First clear REG_AT_COMPAT[SERR, IOCHK] if necessary */
- legacy_io_res = request_region(REG_AT_COMPAT, LEGACY_NR_PORTS,
- AMD8111_EDAC_MOD_STR);
- if (!legacy_io_res)
- printk(KERN_INFO "%s: failed to request legacy I/O region "
- "start %d, len %d\n", __func__,
- REG_AT_COMPAT, LEGACY_NR_PORTS);
- else {
- val8 = __do_inb(REG_AT_COMPAT);
- if (val8 == 0xff) { /* buggy port */
- printk(KERN_INFO "%s: port %d is buggy, not supported"
- " by hardware?\n", __func__, REG_AT_COMPAT);
- at_compat_reg_broken = 1;
- release_region(REG_AT_COMPAT, LEGACY_NR_PORTS);
- legacy_io_res = NULL;
- } else {
- u8 out8 = 0;
- if (val8 & AT_COMPAT_SERR)
- out8 = AT_COMPAT_CLRSERR;
- if (val8 & AT_COMPAT_IOCHK)
- out8 |= AT_COMPAT_CLRIOCHK;
- if (out8 > 0)
- __do_outb(out8, REG_AT_COMPAT);
- }
- }
-
- /* Second clear error flags on LPC bridge */
- edac_pci_read_byte(dev, REG_IO_CTRL_1, &val8);
- if (val8 & IO_CTRL_1_CLEAR_MASK)
- edac_pci_write_byte(dev, REG_IO_CTRL_1, val8);
-}
-
-static void amd8111_lpc_bridge_exit(struct amd8111_dev_info *dev_info)
-{
- if (legacy_io_res)
- release_region(REG_AT_COMPAT, LEGACY_NR_PORTS);
-}
-
-static void amd8111_lpc_bridge_check(struct edac_device_ctl_info *edac_dev)
-{
- struct amd8111_dev_info *dev_info = edac_dev->pvt_info;
- struct pci_dev *dev = dev_info->dev;
- u8 val8;
-
- edac_pci_read_byte(dev, REG_IO_CTRL_1, &val8);
- if (val8 & IO_CTRL_1_CLEAR_MASK) {
- printk(KERN_INFO
- "Error(s) in IO control register on %s device\n",
- dev_info->ctl_name);
- printk(KERN_INFO "LPC ERR: %d, PW2LPC: %d\n",
- (val8 & IO_CTRL_1_LPC_ERR) != 0,
- (val8 & IO_CTRL_1_PW2LPC) != 0);
-
- val8 |= IO_CTRL_1_CLEAR_MASK;
- edac_pci_write_byte(dev, REG_IO_CTRL_1, val8);
-
- edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
- }
-
- if (at_compat_reg_broken == 0) {
- u8 out8 = 0;
- val8 = __do_inb(REG_AT_COMPAT);
- if (val8 & AT_COMPAT_SERR)
- out8 = AT_COMPAT_CLRSERR;
- if (val8 & AT_COMPAT_IOCHK)
- out8 |= AT_COMPAT_CLRIOCHK;
- if (out8 > 0) {
- __do_outb(out8, REG_AT_COMPAT);
- edac_device_handle_ue(edac_dev, 0, 0,
- edac_dev->ctl_name);
- }
- }
-}
-
-/* General devices represented by edac_device_ctl_info */
-static struct amd8111_dev_info amd8111_devices[] = {
- [LPC_BRIDGE] = {
- .err_dev = PCI_DEVICE_ID_AMD_8111_LPC,
- .ctl_name = "lpc",
- .init = amd8111_lpc_bridge_init,
- .exit = amd8111_lpc_bridge_exit,
- .check = amd8111_lpc_bridge_check,
- },
- {0},
-};
-
-/* PCI controllers represented by edac_pci_ctl_info */
-static struct amd8111_pci_info amd8111_pcis[] = {
- [PCI_BRIDGE] = {
- .err_dev = PCI_DEVICE_ID_AMD_8111_PCI,
- .ctl_name = "AMD8111_PCI_Controller",
- .init = amd8111_pci_bridge_init,
- .exit = amd8111_pci_bridge_exit,
- .check = amd8111_pci_bridge_check,
- },
- {0},
-};
-
-static int amd8111_dev_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
-{
- struct amd8111_dev_info *dev_info = &amd8111_devices[id->driver_data];
- int ret = -ENODEV;
-
- dev_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
- dev_info->err_dev, NULL);
-
- if (!dev_info->dev) {
- printk(KERN_ERR "EDAC device not found:"
- "vendor %x, device %x, name %s\n",
- PCI_VENDOR_ID_AMD, dev_info->err_dev,
- dev_info->ctl_name);
- goto err;
- }
-
- if (pci_enable_device(dev_info->dev)) {
- printk(KERN_ERR "failed to enable:"
- "vendor %x, device %x, name %s\n",
- PCI_VENDOR_ID_AMD, dev_info->err_dev,
- dev_info->ctl_name);
- goto err_dev_put;
- }
-
- /*
- * we do not allocate extra private structure for
- * edac_device_ctl_info, but make use of existing
- * one instead.
- */
- dev_info->edac_idx = edac_device_alloc_index();
- dev_info->edac_dev =
- edac_device_alloc_ctl_info(0, dev_info->ctl_name, 1,
- NULL, 0, 0, dev_info->edac_idx);
- if (!dev_info->edac_dev) {
- ret = -ENOMEM;
- goto err_dev_put;
- }
-
- dev_info->edac_dev->pvt_info = dev_info;
- dev_info->edac_dev->dev = &dev_info->dev->dev;
- dev_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR;
- dev_info->edac_dev->ctl_name = dev_info->ctl_name;
- dev_info->edac_dev->dev_name = dev_name(&dev_info->dev->dev);
-
- if (edac_op_state == EDAC_OPSTATE_POLL)
- dev_info->edac_dev->edac_check = dev_info->check;
-
- if (dev_info->init)
- dev_info->init(dev_info);
-
- if (edac_device_add_device(dev_info->edac_dev) > 0) {
- printk(KERN_ERR "failed to add edac_dev for %s\n",
- dev_info->ctl_name);
- goto err_edac_free_ctl;
- }
-
- printk(KERN_INFO "added one edac_dev on AMD8111 "
- "vendor %x, device %x, name %s\n",
- PCI_VENDOR_ID_AMD, dev_info->err_dev,
- dev_info->ctl_name);
-
- return 0;
-
-err_edac_free_ctl:
- edac_device_free_ctl_info(dev_info->edac_dev);
-err_dev_put:
- pci_dev_put(dev_info->dev);
-err:
- return ret;
-}
-
-static void amd8111_dev_remove(struct pci_dev *dev)
-{
- struct amd8111_dev_info *dev_info;
-
- for (dev_info = amd8111_devices; dev_info->err_dev; dev_info++)
- if (dev_info->dev->device == dev->device)
- break;
-
- if (!dev_info->err_dev) /* should never happen */
- return;
-
- if (dev_info->edac_dev) {
- edac_device_del_device(dev_info->edac_dev->dev);
- edac_device_free_ctl_info(dev_info->edac_dev);
- }
-
- if (dev_info->exit)
- dev_info->exit(dev_info);
-
- pci_dev_put(dev_info->dev);
-}
-
-static int amd8111_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
-{
- struct amd8111_pci_info *pci_info = &amd8111_pcis[id->driver_data];
- int ret = -ENODEV;
-
- pci_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
- pci_info->err_dev, NULL);
-
- if (!pci_info->dev) {
- printk(KERN_ERR "EDAC device not found:"
- "vendor %x, device %x, name %s\n",
- PCI_VENDOR_ID_AMD, pci_info->err_dev,
- pci_info->ctl_name);
- goto err;
- }
-
- if (pci_enable_device(pci_info->dev)) {
- printk(KERN_ERR "failed to enable:"
- "vendor %x, device %x, name %s\n",
- PCI_VENDOR_ID_AMD, pci_info->err_dev,
- pci_info->ctl_name);
- goto err_dev_put;
- }
-
- /*
- * we do not allocate extra private structure for
- * edac_pci_ctl_info, but make use of existing
- * one instead.
- */
- pci_info->edac_idx = edac_pci_alloc_index();
- pci_info->edac_dev = edac_pci_alloc_ctl_info(0, pci_info->ctl_name);
- if (!pci_info->edac_dev) {
- ret = -ENOMEM;
- goto err_dev_put;
- }
-
- pci_info->edac_dev->pvt_info = pci_info;
- pci_info->edac_dev->dev = &pci_info->dev->dev;
- pci_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR;
- pci_info->edac_dev->ctl_name = pci_info->ctl_name;
- pci_info->edac_dev->dev_name = dev_name(&pci_info->dev->dev);
-
- if (edac_op_state == EDAC_OPSTATE_POLL)
- pci_info->edac_dev->edac_check = pci_info->check;
-
- if (pci_info->init)
- pci_info->init(pci_info);
-
- if (edac_pci_add_device(pci_info->edac_dev, pci_info->edac_idx) > 0) {
- printk(KERN_ERR "failed to add edac_pci for %s\n",
- pci_info->ctl_name);
- goto err_edac_free_ctl;
- }
-
- printk(KERN_INFO "added one edac_pci on AMD8111 "
- "vendor %x, device %x, name %s\n",
- PCI_VENDOR_ID_AMD, pci_info->err_dev,
- pci_info->ctl_name);
-
- return 0;
-
-err_edac_free_ctl:
- edac_pci_free_ctl_info(pci_info->edac_dev);
-err_dev_put:
- pci_dev_put(pci_info->dev);
-err:
- return ret;
-}
-
-static void amd8111_pci_remove(struct pci_dev *dev)
-{
- struct amd8111_pci_info *pci_info;
-
- for (pci_info = amd8111_pcis; pci_info->err_dev; pci_info++)
- if (pci_info->dev->device == dev->device)
- break;
-
- if (!pci_info->err_dev) /* should never happen */
- return;
-
- if (pci_info->edac_dev) {
- edac_pci_del_device(pci_info->edac_dev->dev);
- edac_pci_free_ctl_info(pci_info->edac_dev);
- }
-
- if (pci_info->exit)
- pci_info->exit(pci_info);
-
- pci_dev_put(pci_info->dev);
-}
-
-/* PCI Device ID talbe for general EDAC device */
-static const struct pci_device_id amd8111_edac_dev_tbl[] = {
- {
- PCI_VEND_DEV(AMD, 8111_LPC),
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = 0,
- .class_mask = 0,
- .driver_data = LPC_BRIDGE,
- },
- {
- 0,
- } /* table is NULL-terminated */
-};
-MODULE_DEVICE_TABLE(pci, amd8111_edac_dev_tbl);
-
-static struct pci_driver amd8111_edac_dev_driver = {
- .name = "AMD8111_EDAC_DEV",
- .probe = amd8111_dev_probe,
- .remove = amd8111_dev_remove,
- .id_table = amd8111_edac_dev_tbl,
-};
-
-/* PCI Device ID table for EDAC PCI controller */
-static const struct pci_device_id amd8111_edac_pci_tbl[] = {
- {
- PCI_VEND_DEV(AMD, 8111_PCI),
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = 0,
- .class_mask = 0,
- .driver_data = PCI_BRIDGE,
- },
- {
- 0,
- } /* table is NULL-terminated */
-};
-MODULE_DEVICE_TABLE(pci, amd8111_edac_pci_tbl);
-
-static struct pci_driver amd8111_edac_pci_driver = {
- .name = "AMD8111_EDAC_PCI",
- .probe = amd8111_pci_probe,
- .remove = amd8111_pci_remove,
- .id_table = amd8111_edac_pci_tbl,
-};
-
-static int __init amd8111_edac_init(void)
-{
- int val;
-
- printk(KERN_INFO "AMD8111 EDAC driver " AMD8111_EDAC_REVISION "\n");
- printk(KERN_INFO "\t(c) 2008 Wind River Systems, Inc.\n");
-
- /* Only POLL mode supported so far */
- edac_op_state = EDAC_OPSTATE_POLL;
-
- val = pci_register_driver(&amd8111_edac_dev_driver);
- val |= pci_register_driver(&amd8111_edac_pci_driver);
-
- return val;
-}
-
-static void __exit amd8111_edac_exit(void)
-{
- pci_unregister_driver(&amd8111_edac_pci_driver);
- pci_unregister_driver(&amd8111_edac_dev_driver);
-}
-
-
-module_init(amd8111_edac_init);
-module_exit(amd8111_edac_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
-MODULE_DESCRIPTION("AMD8111 HyperTransport I/O Hub EDAC kernel module");
diff --git a/drivers/edac/amd8111_edac.h b/drivers/edac/amd8111_edac.h
deleted file mode 100644
index 200cab1b3e42..000000000000
--- a/drivers/edac/amd8111_edac.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * amd8111_edac.h, EDAC defs for AMD8111 hypertransport chip
- *
- * Copyright (c) 2008 Wind River Systems, Inc.
- *
- * Authors: Cao Qingtao <qingtao.cao@windriver.com>
- * Benjamin Walsh <benjamin.walsh@windriver.com>
- * Hu Yongqi <yongqi.hu@windriver.com>
- */
-
-#ifndef _AMD8111_EDAC_H_
-#define _AMD8111_EDAC_H_
-
-/************************************************************
- * PCI Bridge Status and Command Register, DevA:0x04
- ************************************************************/
-#define REG_PCI_STSCMD 0x04
-enum pci_stscmd_bits {
- PCI_STSCMD_SSE = BIT(30),
- PCI_STSCMD_RMA = BIT(29),
- PCI_STSCMD_RTA = BIT(28),
- PCI_STSCMD_SERREN = BIT(8),
- PCI_STSCMD_CLEAR_MASK = (PCI_STSCMD_SSE |
- PCI_STSCMD_RMA |
- PCI_STSCMD_RTA)
-};
-
-/************************************************************
- * PCI Bridge Memory Base-Limit Register, DevA:0x1c
- ************************************************************/
-#define REG_MEM_LIM 0x1c
-enum mem_limit_bits {
- MEM_LIMIT_DPE = BIT(31),
- MEM_LIMIT_RSE = BIT(30),
- MEM_LIMIT_RMA = BIT(29),
- MEM_LIMIT_RTA = BIT(28),
- MEM_LIMIT_STA = BIT(27),
- MEM_LIMIT_MDPE = BIT(24),
- MEM_LIMIT_CLEAR_MASK = (MEM_LIMIT_DPE |
- MEM_LIMIT_RSE |
- MEM_LIMIT_RMA |
- MEM_LIMIT_RTA |
- MEM_LIMIT_STA |
- MEM_LIMIT_MDPE)
-};
-
-/************************************************************
- * HyperTransport Link Control Register, DevA:0xc4
- ************************************************************/
-#define REG_HT_LINK 0xc4
-enum ht_link_bits {
- HT_LINK_LKFAIL = BIT(4),
- HT_LINK_CRCFEN = BIT(1),
- HT_LINK_CLEAR_MASK = (HT_LINK_LKFAIL)
-};
-
-/************************************************************
- * PCI Bridge Interrupt and Bridge Control, DevA:0x3c
- ************************************************************/
-#define REG_PCI_INTBRG_CTRL 0x3c
-enum pci_intbrg_ctrl_bits {
- PCI_INTBRG_CTRL_DTSERREN = BIT(27),
- PCI_INTBRG_CTRL_DTSTAT = BIT(26),
- PCI_INTBRG_CTRL_MARSP = BIT(21),
- PCI_INTBRG_CTRL_SERREN = BIT(17),
- PCI_INTBRG_CTRL_PEREN = BIT(16),
- PCI_INTBRG_CTRL_CLEAR_MASK = (PCI_INTBRG_CTRL_DTSTAT),
- PCI_INTBRG_CTRL_POLL_MASK = (PCI_INTBRG_CTRL_DTSERREN |
- PCI_INTBRG_CTRL_MARSP |
- PCI_INTBRG_CTRL_SERREN)
-};
-
-/************************************************************
- * I/O Control 1 Register, DevB:0x40
- ************************************************************/
-#define REG_IO_CTRL_1 0x40
-enum io_ctrl_1_bits {
- IO_CTRL_1_NMIONERR = BIT(7),
- IO_CTRL_1_LPC_ERR = BIT(6),
- IO_CTRL_1_PW2LPC = BIT(1),
- IO_CTRL_1_CLEAR_MASK = (IO_CTRL_1_LPC_ERR | IO_CTRL_1_PW2LPC)
-};
-
-/************************************************************
- * Legacy I/O Space Registers
- ************************************************************/
-#define REG_AT_COMPAT 0x61
-enum at_compat_bits {
- AT_COMPAT_SERR = BIT(7),
- AT_COMPAT_IOCHK = BIT(6),
- AT_COMPAT_CLRIOCHK = BIT(3),
- AT_COMPAT_CLRSERR = BIT(2),
-};
-
-struct amd8111_dev_info {
- u16 err_dev; /* PCI Device ID */
- struct pci_dev *dev;
- int edac_idx; /* device index */
- char *ctl_name;
- struct edac_device_ctl_info *edac_dev;
- void (*init)(struct amd8111_dev_info *dev_info);
- void (*exit)(struct amd8111_dev_info *dev_info);
- void (*check)(struct edac_device_ctl_info *edac_dev);
-};
-
-struct amd8111_pci_info {
- u16 err_dev; /* PCI Device ID */
- struct pci_dev *dev;
- int edac_idx; /* pci index */
- const char *ctl_name;
- struct edac_pci_ctl_info *edac_dev;
- void (*init)(struct amd8111_pci_info *dev_info);
- void (*exit)(struct amd8111_pci_info *dev_info);
- void (*check)(struct edac_pci_ctl_info *edac_dev);
-};
-
-#endif /* _AMD8111_EDAC_H_ */
diff --git a/drivers/edac/amd8131_edac.c b/drivers/edac/amd8131_edac.c
deleted file mode 100644
index 28610ba514f4..000000000000
--- a/drivers/edac/amd8131_edac.c
+++ /dev/null
@@ -1,358 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * amd8131_edac.c, AMD8131 hypertransport chip EDAC kernel module
- *
- * Copyright (c) 2008 Wind River Systems, Inc.
- *
- * Authors: Cao Qingtao <qingtao.cao@windriver.com>
- * Benjamin Walsh <benjamin.walsh@windriver.com>
- * Hu Yongqi <yongqi.hu@windriver.com>
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/edac.h>
-#include <linux/pci_ids.h>
-
-#include "edac_module.h"
-#include "amd8131_edac.h"
-
-#define AMD8131_EDAC_REVISION " Ver: 1.0.0"
-#define AMD8131_EDAC_MOD_STR "amd8131_edac"
-
-/* Wrapper functions for accessing PCI configuration space */
-static void edac_pci_read_dword(struct pci_dev *dev, int reg, u32 *val32)
-{
- int ret;
-
- ret = pci_read_config_dword(dev, reg, val32);
- if (ret != 0)
- printk(KERN_ERR AMD8131_EDAC_MOD_STR
- " PCI Access Read Error at 0x%x\n", reg);
-}
-
-static void edac_pci_write_dword(struct pci_dev *dev, int reg, u32 val32)
-{
- int ret;
-
- ret = pci_write_config_dword(dev, reg, val32);
- if (ret != 0)
- printk(KERN_ERR AMD8131_EDAC_MOD_STR
- " PCI Access Write Error at 0x%x\n", reg);
-}
-
-/* Support up to two AMD8131 chipsets on a platform */
-static struct amd8131_dev_info amd8131_devices[] = {
- {
- .inst = NORTH_A,
- .devfn = DEVFN_PCIX_BRIDGE_NORTH_A,
- .ctl_name = "AMD8131_PCIX_NORTH_A",
- },
- {
- .inst = NORTH_B,
- .devfn = DEVFN_PCIX_BRIDGE_NORTH_B,
- .ctl_name = "AMD8131_PCIX_NORTH_B",
- },
- {
- .inst = SOUTH_A,
- .devfn = DEVFN_PCIX_BRIDGE_SOUTH_A,
- .ctl_name = "AMD8131_PCIX_SOUTH_A",
- },
- {
- .inst = SOUTH_B,
- .devfn = DEVFN_PCIX_BRIDGE_SOUTH_B,
- .ctl_name = "AMD8131_PCIX_SOUTH_B",
- },
- {.inst = NO_BRIDGE,},
-};
-
-static void amd8131_pcix_init(struct amd8131_dev_info *dev_info)
-{
- u32 val32;
- struct pci_dev *dev = dev_info->dev;
-
- /* First clear error detection flags */
- edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
- if (val32 & MEM_LIMIT_MASK)
- edac_pci_write_dword(dev, REG_MEM_LIM, val32);
-
- /* Clear Discard Timer Timedout flag */
- edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
- if (val32 & INT_CTLR_DTS)
- edac_pci_write_dword(dev, REG_INT_CTLR, val32);
-
- /* Clear CRC Error flag on link side A */
- edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
- if (val32 & LNK_CTRL_CRCERR_A)
- edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
-
- /* Clear CRC Error flag on link side B */
- edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
- if (val32 & LNK_CTRL_CRCERR_B)
- edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
-
- /*
- * Then enable all error detections.
- *
- * Setup Discard Timer Sync Flood Enable,
- * System Error Enable and Parity Error Enable.
- */
- edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
- val32 |= INT_CTLR_PERR | INT_CTLR_SERR | INT_CTLR_DTSE;
- edac_pci_write_dword(dev, REG_INT_CTLR, val32);
-
- /* Enable overall SERR Error detection */
- edac_pci_read_dword(dev, REG_STS_CMD, &val32);
- val32 |= STS_CMD_SERREN;
- edac_pci_write_dword(dev, REG_STS_CMD, val32);
-
- /* Setup CRC Flood Enable for link side A */
- edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
- val32 |= LNK_CTRL_CRCFEN;
- edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
-
- /* Setup CRC Flood Enable for link side B */
- edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
- val32 |= LNK_CTRL_CRCFEN;
- edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
-}
-
-static void amd8131_pcix_exit(struct amd8131_dev_info *dev_info)
-{
- u32 val32;
- struct pci_dev *dev = dev_info->dev;
-
- /* Disable SERR, PERR and DTSE Error detection */
- edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
- val32 &= ~(INT_CTLR_PERR | INT_CTLR_SERR | INT_CTLR_DTSE);
- edac_pci_write_dword(dev, REG_INT_CTLR, val32);
-
- /* Disable overall System Error detection */
- edac_pci_read_dword(dev, REG_STS_CMD, &val32);
- val32 &= ~STS_CMD_SERREN;
- edac_pci_write_dword(dev, REG_STS_CMD, val32);
-
- /* Disable CRC Sync Flood on link side A */
- edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
- val32 &= ~LNK_CTRL_CRCFEN;
- edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
-
- /* Disable CRC Sync Flood on link side B */
- edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
- val32 &= ~LNK_CTRL_CRCFEN;
- edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
-}
-
-static void amd8131_pcix_check(struct edac_pci_ctl_info *edac_dev)
-{
- struct amd8131_dev_info *dev_info = edac_dev->pvt_info;
- struct pci_dev *dev = dev_info->dev;
- u32 val32;
-
- /* Check PCI-X Bridge Memory Base-Limit Register for errors */
- edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
- if (val32 & MEM_LIMIT_MASK) {
- printk(KERN_INFO "Error(s) in mem limit register "
- "on %s bridge\n", dev_info->ctl_name);
- printk(KERN_INFO "DPE: %d, RSE: %d, RMA: %d\n"
- "RTA: %d, STA: %d, MDPE: %d\n",
- val32 & MEM_LIMIT_DPE,
- val32 & MEM_LIMIT_RSE,
- val32 & MEM_LIMIT_RMA,
- val32 & MEM_LIMIT_RTA,
- val32 & MEM_LIMIT_STA,
- val32 & MEM_LIMIT_MDPE);
-
- val32 |= MEM_LIMIT_MASK;
- edac_pci_write_dword(dev, REG_MEM_LIM, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-
- /* Check if Discard Timer timed out */
- edac_pci_read_dword(dev, REG_INT_CTLR, &val32);
- if (val32 & INT_CTLR_DTS) {
- printk(KERN_INFO "Error(s) in interrupt and control register "
- "on %s bridge\n", dev_info->ctl_name);
- printk(KERN_INFO "DTS: %d\n", val32 & INT_CTLR_DTS);
-
- val32 |= INT_CTLR_DTS;
- edac_pci_write_dword(dev, REG_INT_CTLR, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-
- /* Check if CRC error happens on link side A */
- edac_pci_read_dword(dev, REG_LNK_CTRL_A, &val32);
- if (val32 & LNK_CTRL_CRCERR_A) {
- printk(KERN_INFO "Error(s) in link conf and control register "
- "on %s bridge\n", dev_info->ctl_name);
- printk(KERN_INFO "CRCERR: %d\n", val32 & LNK_CTRL_CRCERR_A);
-
- val32 |= LNK_CTRL_CRCERR_A;
- edac_pci_write_dword(dev, REG_LNK_CTRL_A, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-
- /* Check if CRC error happens on link side B */
- edac_pci_read_dword(dev, REG_LNK_CTRL_B, &val32);
- if (val32 & LNK_CTRL_CRCERR_B) {
- printk(KERN_INFO "Error(s) in link conf and control register "
- "on %s bridge\n", dev_info->ctl_name);
- printk(KERN_INFO "CRCERR: %d\n", val32 & LNK_CTRL_CRCERR_B);
-
- val32 |= LNK_CTRL_CRCERR_B;
- edac_pci_write_dword(dev, REG_LNK_CTRL_B, val32);
-
- edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
- }
-}
-
-static struct amd8131_info amd8131_chipset = {
- .err_dev = PCI_DEVICE_ID_AMD_8131_APIC,
- .devices = amd8131_devices,
- .init = amd8131_pcix_init,
- .exit = amd8131_pcix_exit,
- .check = amd8131_pcix_check,
-};
-
-/*
- * There are 4 PCIX Bridges on ATCA-6101 that share the same PCI Device ID,
- * so amd8131_probe() would be called by kernel 4 times, with different
- * address of pci_dev for each of them each time.
- */
-static int amd8131_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
- struct amd8131_dev_info *dev_info;
-
- for (dev_info = amd8131_chipset.devices; dev_info->inst != NO_BRIDGE;
- dev_info++)
- if (dev_info->devfn == dev->devfn)
- break;
-
- if (dev_info->inst == NO_BRIDGE) /* should never happen */
- return -ENODEV;
-
- /*
- * We can't call pci_get_device() as we are used to do because
- * there are 4 of them but pci_dev_get() instead.
- */
- dev_info->dev = pci_dev_get(dev);
-
- if (pci_enable_device(dev_info->dev)) {
- pci_dev_put(dev_info->dev);
- printk(KERN_ERR "failed to enable:"
- "vendor %x, device %x, devfn %x, name %s\n",
- PCI_VENDOR_ID_AMD, amd8131_chipset.err_dev,
- dev_info->devfn, dev_info->ctl_name);
- return -ENODEV;
- }
-
- /*
- * we do not allocate extra private structure for
- * edac_pci_ctl_info, but make use of existing
- * one instead.
- */
- dev_info->edac_idx = edac_pci_alloc_index();
- dev_info->edac_dev = edac_pci_alloc_ctl_info(0, dev_info->ctl_name);
- if (!dev_info->edac_dev)
- return -ENOMEM;
-
- dev_info->edac_dev->pvt_info = dev_info;
- dev_info->edac_dev->dev = &dev_info->dev->dev;
- dev_info->edac_dev->mod_name = AMD8131_EDAC_MOD_STR;
- dev_info->edac_dev->ctl_name = dev_info->ctl_name;
- dev_info->edac_dev->dev_name = dev_name(&dev_info->dev->dev);
-
- if (edac_op_state == EDAC_OPSTATE_POLL)
- dev_info->edac_dev->edac_check = amd8131_chipset.check;
-
- if (amd8131_chipset.init)
- amd8131_chipset.init(dev_info);
-
- if (edac_pci_add_device(dev_info->edac_dev, dev_info->edac_idx) > 0) {
- printk(KERN_ERR "failed edac_pci_add_device() for %s\n",
- dev_info->ctl_name);
- edac_pci_free_ctl_info(dev_info->edac_dev);
- return -ENODEV;
- }
-
- printk(KERN_INFO "added one device on AMD8131 "
- "vendor %x, device %x, devfn %x, name %s\n",
- PCI_VENDOR_ID_AMD, amd8131_chipset.err_dev,
- dev_info->devfn, dev_info->ctl_name);
-
- return 0;
-}
-
-static void amd8131_remove(struct pci_dev *dev)
-{
- struct amd8131_dev_info *dev_info;
-
- for (dev_info = amd8131_chipset.devices; dev_info->inst != NO_BRIDGE;
- dev_info++)
- if (dev_info->devfn == dev->devfn)
- break;
-
- if (dev_info->inst == NO_BRIDGE) /* should never happen */
- return;
-
- if (dev_info->edac_dev) {
- edac_pci_del_device(dev_info->edac_dev->dev);
- edac_pci_free_ctl_info(dev_info->edac_dev);
- }
-
- if (amd8131_chipset.exit)
- amd8131_chipset.exit(dev_info);
-
- pci_dev_put(dev_info->dev);
-}
-
-static const struct pci_device_id amd8131_edac_pci_tbl[] = {
- {
- PCI_VEND_DEV(AMD, 8131_BRIDGE),
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = 0,
- .class_mask = 0,
- .driver_data = 0,
- },
- {
- 0,
- } /* table is NULL-terminated */
-};
-MODULE_DEVICE_TABLE(pci, amd8131_edac_pci_tbl);
-
-static struct pci_driver amd8131_edac_driver = {
- .name = AMD8131_EDAC_MOD_STR,
- .probe = amd8131_probe,
- .remove = amd8131_remove,
- .id_table = amd8131_edac_pci_tbl,
-};
-
-static int __init amd8131_edac_init(void)
-{
- printk(KERN_INFO "AMD8131 EDAC driver " AMD8131_EDAC_REVISION "\n");
- printk(KERN_INFO "\t(c) 2008 Wind River Systems, Inc.\n");
-
- /* Only POLL mode supported so far */
- edac_op_state = EDAC_OPSTATE_POLL;
-
- return pci_register_driver(&amd8131_edac_driver);
-}
-
-static void __exit amd8131_edac_exit(void)
-{
- pci_unregister_driver(&amd8131_edac_driver);
-}
-
-module_init(amd8131_edac_init);
-module_exit(amd8131_edac_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
-MODULE_DESCRIPTION("AMD8131 HyperTransport PCI-X Tunnel EDAC kernel module");
diff --git a/drivers/edac/amd8131_edac.h b/drivers/edac/amd8131_edac.h
deleted file mode 100644
index 5f362abdaf12..000000000000
--- a/drivers/edac/amd8131_edac.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * amd8131_edac.h, EDAC defs for AMD8131 hypertransport chip
- *
- * Copyright (c) 2008 Wind River Systems, Inc.
- *
- * Authors: Cao Qingtao <qingtao.cao@windriver.com>
- * Benjamin Walsh <benjamin.walsh@windriver.com>
- * Hu Yongqi <yongqi.hu@windriver.com>
- */
-
-#ifndef _AMD8131_EDAC_H_
-#define _AMD8131_EDAC_H_
-
-#define DEVFN_PCIX_BRIDGE_NORTH_A 8
-#define DEVFN_PCIX_BRIDGE_NORTH_B 16
-#define DEVFN_PCIX_BRIDGE_SOUTH_A 24
-#define DEVFN_PCIX_BRIDGE_SOUTH_B 32
-
-/************************************************************
- * PCI-X Bridge Status and Command Register, DevA:0x04
- ************************************************************/
-#define REG_STS_CMD 0x04
-enum sts_cmd_bits {
- STS_CMD_SSE = BIT(30),
- STS_CMD_SERREN = BIT(8)
-};
-
-/************************************************************
- * PCI-X Bridge Interrupt and Bridge Control Register,
- ************************************************************/
-#define REG_INT_CTLR 0x3c
-enum int_ctlr_bits {
- INT_CTLR_DTSE = BIT(27),
- INT_CTLR_DTS = BIT(26),
- INT_CTLR_SERR = BIT(17),
- INT_CTLR_PERR = BIT(16)
-};
-
-/************************************************************
- * PCI-X Bridge Memory Base-Limit Register, DevA:0x1C
- ************************************************************/
-#define REG_MEM_LIM 0x1c
-enum mem_limit_bits {
- MEM_LIMIT_DPE = BIT(31),
- MEM_LIMIT_RSE = BIT(30),
- MEM_LIMIT_RMA = BIT(29),
- MEM_LIMIT_RTA = BIT(28),
- MEM_LIMIT_STA = BIT(27),
- MEM_LIMIT_MDPE = BIT(24),
- MEM_LIMIT_MASK = MEM_LIMIT_DPE|MEM_LIMIT_RSE|MEM_LIMIT_RMA|
- MEM_LIMIT_RTA|MEM_LIMIT_STA|MEM_LIMIT_MDPE
-};
-
-/************************************************************
- * Link Configuration And Control Register, side A
- ************************************************************/
-#define REG_LNK_CTRL_A 0xc4
-
-/************************************************************
- * Link Configuration And Control Register, side B
- ************************************************************/
-#define REG_LNK_CTRL_B 0xc8
-
-enum lnk_ctrl_bits {
- LNK_CTRL_CRCERR_A = BIT(9),
- LNK_CTRL_CRCERR_B = BIT(8),
- LNK_CTRL_CRCFEN = BIT(1)
-};
-
-enum pcix_bridge_inst {
- NORTH_A = 0,
- NORTH_B = 1,
- SOUTH_A = 2,
- SOUTH_B = 3,
- NO_BRIDGE = 4
-};
-
-struct amd8131_dev_info {
- int devfn;
- enum pcix_bridge_inst inst;
- struct pci_dev *dev;
- int edac_idx; /* pci device index */
- char *ctl_name;
- struct edac_pci_ctl_info *edac_dev;
-};
-
-/*
- * AMD8131 chipset has two pairs of PCIX Bridge and related IOAPIC
- * Controller, and ATCA-6101 has two AMD8131 chipsets, so there are
- * four PCIX Bridges on ATCA-6101 altogether.
- *
- * These PCIX Bridges share the same PCI Device ID and are all of
- * Function Zero, they could be discrimated by their pci_dev->devfn.
- * They share the same set of init/check/exit methods, and their
- * private structures are collected in the devices[] array.
- */
-struct amd8131_info {
- u16 err_dev; /* PCI Device ID for AMD8131 APIC*/
- struct amd8131_dev_info *devices;
- void (*init)(struct amd8131_dev_info *dev_info);
- void (*exit)(struct amd8131_dev_info *dev_info);
- void (*check)(struct edac_pci_ctl_info *edac_dev);
-};
-
-#endif /* _AMD8131_EDAC_H_ */
-
diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c
index 5b3164560648..739132e5ed8a 100644
--- a/drivers/edac/bluefield_edac.c
+++ b/drivers/edac/bluefield_edac.c
@@ -47,13 +47,22 @@
#define MLXBF_EDAC_MAX_DIMM_PER_MC 2
#define MLXBF_EDAC_ERROR_GRAIN 8
+#define MLXBF_WRITE_REG_32 (0x82000009)
+#define MLXBF_READ_REG_32 (0x8200000A)
+#define MLXBF_SIP_SVC_VERSION (0x8200ff03)
+
+#define MLXBF_SMCCC_ACCESS_VIOLATION (-4)
+
+#define MLXBF_SVC_REQ_MAJOR 0
+#define MLXBF_SVC_REQ_MINOR 3
+
/*
- * Request MLNX_SIP_GET_DIMM_INFO
+ * Request MLXBF_SIP_GET_DIMM_INFO
*
* Retrieve information about DIMM on a certain slot.
*
* Call register usage:
- * a0: MLNX_SIP_GET_DIMM_INFO
+ * a0: MLXBF_SIP_GET_DIMM_INFO
* a1: (Memory controller index) << 16 | (Dimm index in memory controller)
* a2-7: not used.
*
@@ -61,7 +70,7 @@
* a0: MLXBF_DIMM_INFO defined below describing the DIMM.
* a1-3: not used.
*/
-#define MLNX_SIP_GET_DIMM_INFO 0x82000008
+#define MLXBF_SIP_GET_DIMM_INFO 0x82000008
/* Format for the SMC response about the memory information */
#define MLXBF_DIMM_INFO__SIZE_GB GENMASK_ULL(15, 0)
@@ -72,9 +81,15 @@
#define MLXBF_DIMM_INFO__PACKAGE_X GENMASK_ULL(31, 24)
struct bluefield_edac_priv {
+ /* pointer to device structure */
+ struct device *dev;
int dimm_ranks[MLXBF_EDAC_MAX_DIMM_PER_MC];
void __iomem *emi_base;
int dimm_per_mc;
+ /* access to secure regs supported */
+ bool svc_sreg_support;
+ /* SMC table# for secure regs access */
+ u32 sreg_tbl;
};
static u64 smc_call1(u64 smc_op, u64 smc_arg)
@@ -86,6 +101,71 @@ static u64 smc_call1(u64 smc_op, u64 smc_arg)
return res.a0;
}
+static int secure_readl(void __iomem *addr, u32 *result, u32 sreg_tbl)
+{
+ struct arm_smccc_res res;
+ int status;
+
+ arm_smccc_smc(MLXBF_READ_REG_32, sreg_tbl, (uintptr_t)addr,
+ 0, 0, 0, 0, 0, &res);
+
+ status = res.a0;
+
+ if (status == SMCCC_RET_NOT_SUPPORTED ||
+ status == MLXBF_SMCCC_ACCESS_VIOLATION)
+ return -1;
+
+ *result = (u32)res.a1;
+ return 0;
+}
+
+static int secure_writel(void __iomem *addr, u32 data, u32 sreg_tbl)
+{
+ struct arm_smccc_res res;
+ int status;
+
+ arm_smccc_smc(MLXBF_WRITE_REG_32, sreg_tbl, data, (uintptr_t)addr,
+ 0, 0, 0, 0, &res);
+
+ status = res.a0;
+
+ if (status == SMCCC_RET_NOT_SUPPORTED ||
+ status == MLXBF_SMCCC_ACCESS_VIOLATION)
+ return -1;
+ else
+ return 0;
+}
+
+static int bluefield_edac_readl(struct bluefield_edac_priv *priv, u32 offset, u32 *result)
+{
+ void __iomem *addr;
+ int err = 0;
+
+ addr = priv->emi_base + offset;
+
+ if (priv->svc_sreg_support)
+ err = secure_readl(addr, result, priv->sreg_tbl);
+ else
+ *result = readl(addr);
+
+ return err;
+}
+
+static int bluefield_edac_writel(struct bluefield_edac_priv *priv, u32 offset, u32 data)
+{
+ void __iomem *addr;
+ int err = 0;
+
+ addr = priv->emi_base + offset;
+
+ if (priv->svc_sreg_support)
+ err = secure_writel(addr, data, priv->sreg_tbl);
+ else
+ writel(data, addr);
+
+ return err;
+}
+
/*
* Gather the ECC information from the External Memory Interface registers
* and report it to the edac handler.
@@ -99,7 +179,7 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
u32 ecc_latch_select, dram_syndrom, serr, derr, syndrom;
enum hw_event_mc_err_type ecc_type;
u64 ecc_dimm_addr;
- int ecc_dimm;
+ int ecc_dimm, err;
ecc_type = is_single_ecc ? HW_EVENT_ERR_CORRECTED :
HW_EVENT_ERR_UNCORRECTED;
@@ -109,14 +189,19 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
* registers with information about the last ECC error occurrence.
*/
ecc_latch_select = MLXBF_ECC_LATCH_SEL__START;
- writel(ecc_latch_select, priv->emi_base + MLXBF_ECC_LATCH_SEL);
+ err = bluefield_edac_writel(priv, MLXBF_ECC_LATCH_SEL, ecc_latch_select);
+ if (err)
+ dev_err(priv->dev, "ECC latch select write failed.\n");
/*
* Verify that the ECC reported info in the registers is of the
* same type as the one asked to report. If not, just report the
* error without the detailed information.
*/
- dram_syndrom = readl(priv->emi_base + MLXBF_SYNDROM);
+ err = bluefield_edac_readl(priv, MLXBF_SYNDROM, &dram_syndrom);
+ if (err)
+ dev_err(priv->dev, "DRAM syndrom read failed.\n");
+
serr = FIELD_GET(MLXBF_SYNDROM__SERR, dram_syndrom);
derr = FIELD_GET(MLXBF_SYNDROM__DERR, dram_syndrom);
syndrom = FIELD_GET(MLXBF_SYNDROM__SYN, dram_syndrom);
@@ -127,13 +212,21 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
return;
}
- dram_additional_info = readl(priv->emi_base + MLXBF_ADD_INFO);
+ err = bluefield_edac_readl(priv, MLXBF_ADD_INFO, &dram_additional_info);
+ if (err)
+ dev_err(priv->dev, "DRAM additional info read failed.\n");
+
err_prank = FIELD_GET(MLXBF_ADD_INFO__ERR_PRANK, dram_additional_info);
ecc_dimm = (err_prank >= 2 && priv->dimm_ranks[0] <= 2) ? 1 : 0;
- edea0 = readl(priv->emi_base + MLXBF_ERR_ADDR_0);
- edea1 = readl(priv->emi_base + MLXBF_ERR_ADDR_1);
+ err = bluefield_edac_readl(priv, MLXBF_ERR_ADDR_0, &edea0);
+ if (err)
+ dev_err(priv->dev, "Error addr 0 read failed.\n");
+
+ err = bluefield_edac_readl(priv, MLXBF_ERR_ADDR_1, &edea1);
+ if (err)
+ dev_err(priv->dev, "Error addr 1 read failed.\n");
ecc_dimm_addr = ((u64)edea1 << 32) | edea0;
@@ -147,6 +240,7 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
{
struct bluefield_edac_priv *priv = mci->pvt_info;
u32 ecc_count, single_error_count, double_error_count, ecc_error = 0;
+ int err;
/*
* The memory controller might not be initialized by the firmware
@@ -155,7 +249,10 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
if (mci->edac_cap == EDAC_FLAG_NONE)
return;
- ecc_count = readl(priv->emi_base + MLXBF_ECC_CNT);
+ err = bluefield_edac_readl(priv, MLXBF_ECC_CNT, &ecc_count);
+ if (err)
+ dev_err(priv->dev, "ECC count read failed.\n");
+
single_error_count = FIELD_GET(MLXBF_ECC_CNT__SERR_CNT, ecc_count);
double_error_count = FIELD_GET(MLXBF_ECC_CNT__DERR_CNT, ecc_count);
@@ -172,15 +269,18 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
}
/* Write to clear reported errors. */
- if (ecc_count)
- writel(ecc_error, priv->emi_base + MLXBF_ECC_ERR);
+ if (ecc_count) {
+ err = bluefield_edac_writel(priv, MLXBF_ECC_ERR, ecc_error);
+ if (err)
+ dev_err(priv->dev, "ECC Error write failed.\n");
+ }
}
/* Initialize the DIMMs information for the given memory controller. */
static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
{
struct bluefield_edac_priv *priv = mci->pvt_info;
- int mem_ctrl_idx = mci->mc_idx;
+ u64 mem_ctrl_idx = mci->mc_idx;
struct dimm_info *dimm;
u64 smc_info, smc_arg;
int is_empty = 1, i;
@@ -189,7 +289,7 @@ static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
dimm = mci->dimms[i];
smc_arg = mem_ctrl_idx << 16 | i;
- smc_info = smc_call1(MLNX_SIP_GET_DIMM_INFO, smc_arg);
+ smc_info = smc_call1(MLXBF_SIP_GET_DIMM_INFO, smc_arg);
if (!FIELD_GET(MLXBF_DIMM_INFO__SIZE_GB, smc_info)) {
dimm->mtype = MEM_EMPTY;
@@ -244,6 +344,7 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
struct bluefield_edac_priv *priv;
struct device *dev = &pdev->dev;
struct edac_mc_layer layers[1];
+ struct arm_smccc_res res;
struct mem_ctl_info *mci;
struct resource *emi_res;
unsigned int mc_idx, dimm_count;
@@ -279,13 +380,43 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
return -ENOMEM;
priv = mci->pvt_info;
+ priv->dev = dev;
+
+ /*
+ * The "sec_reg_block" property in the ACPI table determines the method
+ * the driver uses to access the EMI registers:
+ * a) property is not present - directly access registers via readl/writel
+ * b) property is present - indirectly access registers via SMC calls
+ * (assuming required Silicon Provider service version found)
+ */
+ if (device_property_read_u32(dev, "sec_reg_block", &priv->sreg_tbl)) {
+ priv->svc_sreg_support = false;
+ } else {
+ /*
+ * Check for minimum required Arm Silicon Provider (SiP) service
+ * version, ensuring support of required SMC function IDs.
+ */
+ arm_smccc_smc(MLXBF_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
+ if (res.a0 == MLXBF_SVC_REQ_MAJOR &&
+ res.a1 >= MLXBF_SVC_REQ_MINOR) {
+ priv->svc_sreg_support = true;
+ } else {
+ dev_err(dev, "Required SMCs are not supported.\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ }
priv->dimm_per_mc = dimm_count;
- priv->emi_base = devm_ioremap_resource(dev, emi_res);
- if (IS_ERR(priv->emi_base)) {
- dev_err(dev, "failed to map EMI IO resource\n");
- ret = PTR_ERR(priv->emi_base);
- goto err;
+ if (!priv->svc_sreg_support) {
+ priv->emi_base = devm_ioremap_resource(dev, emi_res);
+ if (IS_ERR(priv->emi_base)) {
+ dev_err(dev, "failed to map EMI IO resource\n");
+ ret = PTR_ERR(priv->emi_base);
+ goto err;
+ }
+ } else {
+ priv->emi_base = (void __iomem *)emi_res->start;
}
mci->pdev = dev;
@@ -320,7 +451,6 @@ err:
edac_mc_free(mci);
return ret;
-
}
static void bluefield_edac_mc_remove(struct platform_device *pdev)
diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index d148d262d0d4..e4eaec0aa81d 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -31,18 +31,30 @@
static int edac_mc_idx;
-static u32 orig_ddr_err_disable;
-static u32 orig_ddr_err_sbe;
-static bool little_endian;
+static inline void __iomem *ddr_reg_addr(struct fsl_mc_pdata *pdata, unsigned int off)
+{
+ if (pdata->flag == TYPE_IMX9 && off >= FSL_MC_DATA_ERR_INJECT_HI && off <= FSL_MC_ERR_SBE)
+ return pdata->inject_vbase + off - FSL_MC_DATA_ERR_INJECT_HI
+ + IMX9_MC_DATA_ERR_INJECT_OFF;
+
+ if (pdata->flag == TYPE_IMX9 && off >= IMX9_MC_ERR_EN)
+ return pdata->inject_vbase + off - IMX9_MC_ERR_EN;
-static inline u32 ddr_in32(void __iomem *addr)
+ return pdata->mc_vbase + off;
+}
+
+static inline u32 ddr_in32(struct fsl_mc_pdata *pdata, unsigned int off)
{
- return little_endian ? ioread32(addr) : ioread32be(addr);
+ void __iomem *addr = ddr_reg_addr(pdata, off);
+
+ return pdata->little_endian ? ioread32(addr) : ioread32be(addr);
}
-static inline void ddr_out32(void __iomem *addr, u32 value)
+static inline void ddr_out32(struct fsl_mc_pdata *pdata, unsigned int off, u32 value)
{
- if (little_endian)
+ void __iomem *addr = ddr_reg_addr(pdata, off);
+
+ if (pdata->little_endian)
iowrite32(value, addr);
else
iowrite32be(value, addr);
@@ -60,7 +72,7 @@ static ssize_t fsl_mc_inject_data_hi_show(struct device *dev,
struct mem_ctl_info *mci = to_mci(dev);
struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
- ddr_in32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_HI));
+ ddr_in32(pdata, FSL_MC_DATA_ERR_INJECT_HI));
}
static ssize_t fsl_mc_inject_data_lo_show(struct device *dev,
@@ -70,7 +82,7 @@ static ssize_t fsl_mc_inject_data_lo_show(struct device *dev,
struct mem_ctl_info *mci = to_mci(dev);
struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
- ddr_in32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_LO));
+ ddr_in32(pdata, FSL_MC_DATA_ERR_INJECT_LO));
}
static ssize_t fsl_mc_inject_ctrl_show(struct device *dev,
@@ -80,7 +92,7 @@ static ssize_t fsl_mc_inject_ctrl_show(struct device *dev,
struct mem_ctl_info *mci = to_mci(dev);
struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
- ddr_in32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT));
+ ddr_in32(pdata, FSL_MC_ECC_ERR_INJECT));
}
static ssize_t fsl_mc_inject_data_hi_store(struct device *dev,
@@ -97,7 +109,7 @@ static ssize_t fsl_mc_inject_data_hi_store(struct device *dev,
if (rc)
return rc;
- ddr_out32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_HI, val);
+ ddr_out32(pdata, FSL_MC_DATA_ERR_INJECT_HI, val);
return count;
}
return 0;
@@ -117,7 +129,7 @@ static ssize_t fsl_mc_inject_data_lo_store(struct device *dev,
if (rc)
return rc;
- ddr_out32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_LO, val);
+ ddr_out32(pdata, FSL_MC_DATA_ERR_INJECT_LO, val);
return count;
}
return 0;
@@ -137,7 +149,7 @@ static ssize_t fsl_mc_inject_ctrl_store(struct device *dev,
if (rc)
return rc;
- ddr_out32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT, val);
+ ddr_out32(pdata, FSL_MC_ECC_ERR_INJECT, val);
return count;
}
return 0;
@@ -286,7 +298,7 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
int bad_data_bit;
int bad_ecc_bit;
- err_detect = ddr_in32(pdata->mc_vbase + FSL_MC_ERR_DETECT);
+ err_detect = ddr_in32(pdata, FSL_MC_ERR_DETECT);
if (!err_detect)
return;
@@ -295,14 +307,14 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
/* no more processing if not ECC bit errors */
if (!(err_detect & (DDR_EDE_SBE | DDR_EDE_MBE))) {
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DETECT, err_detect);
+ ddr_out32(pdata, FSL_MC_ERR_DETECT, err_detect);
return;
}
- syndrome = ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_ECC);
+ syndrome = ddr_in32(pdata, FSL_MC_CAPTURE_ECC);
/* Mask off appropriate bits of syndrome based on bus width */
- bus_width = (ddr_in32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG) &
+ bus_width = (ddr_in32(pdata, FSL_MC_DDR_SDRAM_CFG) &
DSC_DBW_MASK) ? 32 : 64;
if (bus_width == 64)
syndrome &= 0xff;
@@ -310,8 +322,8 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
syndrome &= 0xffff;
err_addr = make64(
- ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_EXT_ADDRESS),
- ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_ADDRESS));
+ ddr_in32(pdata, FSL_MC_CAPTURE_EXT_ADDRESS),
+ ddr_in32(pdata, FSL_MC_CAPTURE_ADDRESS));
pfn = err_addr >> PAGE_SHIFT;
for (row_index = 0; row_index < mci->nr_csrows; row_index++) {
@@ -320,29 +332,33 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
break;
}
- cap_high = ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_DATA_HI);
- cap_low = ddr_in32(pdata->mc_vbase + FSL_MC_CAPTURE_DATA_LO);
+ cap_high = ddr_in32(pdata, FSL_MC_CAPTURE_DATA_HI);
+ cap_low = ddr_in32(pdata, FSL_MC_CAPTURE_DATA_LO);
/*
* Analyze single-bit errors on 64-bit wide buses
* TODO: Add support for 32-bit wide buses
*/
if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) {
+ u64 cap = (u64)cap_high << 32 | cap_low;
+ u32 s = syndrome;
+
sbe_ecc_decode(cap_high, cap_low, syndrome,
&bad_data_bit, &bad_ecc_bit);
- if (bad_data_bit != -1)
- fsl_mc_printk(mci, KERN_ERR,
- "Faulty Data bit: %d\n", bad_data_bit);
- if (bad_ecc_bit != -1)
- fsl_mc_printk(mci, KERN_ERR,
- "Faulty ECC bit: %d\n", bad_ecc_bit);
+ if (bad_data_bit >= 0) {
+ fsl_mc_printk(mci, KERN_ERR, "Faulty Data bit: %d\n", bad_data_bit);
+ cap ^= 1ULL << bad_data_bit;
+ }
+
+ if (bad_ecc_bit >= 0) {
+ fsl_mc_printk(mci, KERN_ERR, "Faulty ECC bit: %d\n", bad_ecc_bit);
+ s ^= 1 << bad_ecc_bit;
+ }
fsl_mc_printk(mci, KERN_ERR,
"Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
- cap_high ^ (1 << (bad_data_bit - 32)),
- cap_low ^ (1 << bad_data_bit),
- syndrome ^ (1 << bad_ecc_bit));
+ upper_32_bits(cap), lower_32_bits(cap), s);
}
fsl_mc_printk(mci, KERN_ERR,
@@ -367,7 +383,7 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
row_index, 0, -1,
mci->ctl_name, "");
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DETECT, err_detect);
+ ddr_out32(pdata, FSL_MC_ERR_DETECT, err_detect);
}
static irqreturn_t fsl_mc_isr(int irq, void *dev_id)
@@ -376,7 +392,7 @@ static irqreturn_t fsl_mc_isr(int irq, void *dev_id)
struct fsl_mc_pdata *pdata = mci->pvt_info;
u32 err_detect;
- err_detect = ddr_in32(pdata->mc_vbase + FSL_MC_ERR_DETECT);
+ err_detect = ddr_in32(pdata, FSL_MC_ERR_DETECT);
if (!err_detect)
return IRQ_NONE;
@@ -396,7 +412,7 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
u32 cs_bnds;
int index;
- sdram_ctl = ddr_in32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG);
+ sdram_ctl = ddr_in32(pdata, FSL_MC_DDR_SDRAM_CFG);
sdtype = sdram_ctl & DSC_SDTYPE_MASK;
if (sdram_ctl & DSC_RD_EN) {
@@ -431,6 +447,9 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
case 0x05000000:
mtype = MEM_DDR4;
break;
+ case 0x04000000:
+ mtype = MEM_LPDDR4;
+ break;
default:
mtype = MEM_UNKNOWN;
break;
@@ -444,7 +463,7 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
csrow = mci->csrows[index];
dimm = csrow->channels[0]->dimm;
- cs_bnds = ddr_in32(pdata->mc_vbase + FSL_MC_CS_BNDS_0 +
+ cs_bnds = ddr_in32(pdata, FSL_MC_CS_BNDS_0 +
(index * FSL_MC_CS_BNDS_OFS));
start = (cs_bnds & 0xffff0000) >> 16;
@@ -464,7 +483,9 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
dimm->grain = 8;
dimm->mtype = mtype;
dimm->dtype = DEV_UNKNOWN;
- if (sdram_ctl & DSC_X32_EN)
+ if (pdata->flag == TYPE_IMX9)
+ dimm->dtype = DEV_X16;
+ else if (sdram_ctl & DSC_X32_EN)
dimm->dtype = DEV_X32;
dimm->edac_mode = EDAC_SECDED;
}
@@ -476,6 +497,7 @@ int fsl_mc_err_probe(struct platform_device *op)
struct edac_mc_layer layers[2];
struct fsl_mc_pdata *pdata;
struct resource r;
+ u32 ecc_en_mask;
u32 sdram_ctl;
int res;
@@ -503,11 +525,13 @@ int fsl_mc_err_probe(struct platform_device *op)
mci->ctl_name = pdata->name;
mci->dev_name = pdata->name;
+ pdata->flag = (unsigned long)device_get_match_data(&op->dev);
+
/*
* Get the endianness of DDR controller registers.
* Default is big endian.
*/
- little_endian = of_property_read_bool(op->dev.of_node, "little-endian");
+ pdata->little_endian = of_property_read_bool(op->dev.of_node, "little-endian");
res = of_address_to_resource(op->dev.of_node, 0, &r);
if (res) {
@@ -531,8 +555,23 @@ int fsl_mc_err_probe(struct platform_device *op)
goto err;
}
- sdram_ctl = ddr_in32(pdata->mc_vbase + FSL_MC_DDR_SDRAM_CFG);
- if (!(sdram_ctl & DSC_ECC_EN)) {
+ if (pdata->flag == TYPE_IMX9) {
+ pdata->inject_vbase = devm_platform_ioremap_resource_byname(op, "inject");
+ if (IS_ERR(pdata->inject_vbase)) {
+ res = -ENOMEM;
+ goto err;
+ }
+ }
+
+ if (pdata->flag == TYPE_IMX9) {
+ sdram_ctl = ddr_in32(pdata, IMX9_MC_ERR_EN);
+ ecc_en_mask = ERR_ECC_EN | ERR_INLINE_ECC;
+ } else {
+ sdram_ctl = ddr_in32(pdata, FSL_MC_DDR_SDRAM_CFG);
+ ecc_en_mask = DSC_ECC_EN;
+ }
+
+ if ((sdram_ctl & ecc_en_mask) != ecc_en_mask) {
/* no ECC */
pr_warn("%s: No ECC DIMMs discovered\n", __func__);
res = -ENODEV;
@@ -543,7 +582,8 @@ int fsl_mc_err_probe(struct platform_device *op)
mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR |
MEM_FLAG_DDR2 | MEM_FLAG_RDDR2 |
MEM_FLAG_DDR3 | MEM_FLAG_RDDR3 |
- MEM_FLAG_DDR4 | MEM_FLAG_RDDR4;
+ MEM_FLAG_DDR4 | MEM_FLAG_RDDR4 |
+ MEM_FLAG_LPDDR4;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
mci->mod_name = EDAC_MOD_STR;
@@ -558,11 +598,11 @@ int fsl_mc_err_probe(struct platform_device *op)
fsl_ddr_init_csrows(mci);
/* store the original error disable bits */
- orig_ddr_err_disable = ddr_in32(pdata->mc_vbase + FSL_MC_ERR_DISABLE);
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DISABLE, 0);
+ pdata->orig_ddr_err_disable = ddr_in32(pdata, FSL_MC_ERR_DISABLE);
+ ddr_out32(pdata, FSL_MC_ERR_DISABLE, 0);
/* clear all error bits */
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DETECT, ~0);
+ ddr_out32(pdata, FSL_MC_ERR_DETECT, ~0);
res = edac_mc_add_mc_with_groups(mci, fsl_ddr_dev_groups);
if (res) {
@@ -571,15 +611,15 @@ int fsl_mc_err_probe(struct platform_device *op)
}
if (edac_op_state == EDAC_OPSTATE_INT) {
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_INT_EN,
+ ddr_out32(pdata, FSL_MC_ERR_INT_EN,
DDR_EIE_MBEE | DDR_EIE_SBEE);
/* store the original error management threshold */
- orig_ddr_err_sbe = ddr_in32(pdata->mc_vbase +
- FSL_MC_ERR_SBE) & 0xff0000;
+ pdata->orig_ddr_err_sbe = ddr_in32(pdata,
+ FSL_MC_ERR_SBE) & 0xff0000;
/* set threshold to 1 error per interrupt */
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_SBE, 0x10000);
+ ddr_out32(pdata, FSL_MC_ERR_SBE, 0x10000);
/* register interrupts */
pdata->irq = platform_get_irq(op, 0);
@@ -620,12 +660,13 @@ void fsl_mc_err_remove(struct platform_device *op)
edac_dbg(0, "\n");
if (edac_op_state == EDAC_OPSTATE_INT) {
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_INT_EN, 0);
+ ddr_out32(pdata, FSL_MC_ERR_INT_EN, 0);
}
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_DISABLE,
- orig_ddr_err_disable);
- ddr_out32(pdata->mc_vbase + FSL_MC_ERR_SBE, orig_ddr_err_sbe);
+ ddr_out32(pdata, FSL_MC_ERR_DISABLE,
+ pdata->orig_ddr_err_disable);
+ ddr_out32(pdata, FSL_MC_ERR_SBE, pdata->orig_ddr_err_sbe);
+
edac_mc_del_mc(&op->dev);
edac_mc_free(mci);
diff --git a/drivers/edac/fsl_ddr_edac.h b/drivers/edac/fsl_ddr_edac.h
index c0994a2a003c..73618f79e587 100644
--- a/drivers/edac/fsl_ddr_edac.h
+++ b/drivers/edac/fsl_ddr_edac.h
@@ -39,6 +39,9 @@
#define FSL_MC_CAPTURE_EXT_ADDRESS 0x0e54
#define FSL_MC_ERR_SBE 0x0e58
+#define IMX9_MC_ERR_EN 0x1000
+#define IMX9_MC_DATA_ERR_INJECT_OFF 0x100
+
#define DSC_MEM_EN 0x80000000
#define DSC_ECC_EN 0x20000000
#define DSC_RD_EN 0x10000000
@@ -46,6 +49,9 @@
#define DSC_DBW_32 0x00080000
#define DSC_DBW_64 0x00000000
+#define ERR_ECC_EN 0x80000000
+#define ERR_INLINE_ECC 0x40000000
+
#define DSC_SDTYPE_MASK 0x07000000
#define DSC_X32_EN 0x00000020
@@ -65,11 +71,18 @@
#define DDR_EDI_SBED 0x4 /* single-bit ECC error disable */
#define DDR_EDI_MBED 0x8 /* multi-bit ECC error disable */
+#define TYPE_IMX9 0x1 /* MC used by iMX9 having registers changed */
+
struct fsl_mc_pdata {
char *name;
int edac_idx;
void __iomem *mc_vbase;
+ void __iomem *inject_vbase;
int irq;
+ u32 orig_ddr_err_disable;
+ u32 orig_ddr_err_sbe;
+ bool little_endian;
+ unsigned long flag;
};
int fsl_mc_err_probe(struct platform_device *op);
void fsl_mc_err_remove(struct platform_device *op);
diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
index e2a954de913b..51556c72a967 100644
--- a/drivers/edac/i10nm_base.c
+++ b/drivers/edac/i10nm_base.c
@@ -1036,6 +1036,7 @@ static int __init i10nm_init(void)
return -ENODEV;
cfg = (struct res_config *)id->driver_data;
+ skx_set_res_cfg(cfg);
res_cfg = cfg;
rc = skx_get_hi_lo(0x09a2, off, &tolm, &tohm);
diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
index 9ef13570f2e5..4fc16922dc1a 100644
--- a/drivers/edac/ie31200_edac.c
+++ b/drivers/edac/ie31200_edac.c
@@ -19,7 +19,8 @@
* 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
* 0c08: Xeon E3-1200 v3 Processor DRAM Controller
* 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers
- * 5918: Xeon E3-1200 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
+ * 590f: Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
+ * 5918: Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
* 190f: 6th Gen Core Dual-Core Processor Host Bridge/DRAM Registers
* 191f: 6th Gen Core Quad-Core Processor Host Bridge/DRAM Registers
* 3e..: 8th/9th Gen Core Processor Host Bridge/DRAM Registers
@@ -67,7 +68,8 @@
#define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x190F
#define PCI_DEVICE_ID_INTEL_IE31200_HB_9 0x1918
#define PCI_DEVICE_ID_INTEL_IE31200_HB_10 0x191F
-#define PCI_DEVICE_ID_INTEL_IE31200_HB_11 0x5918
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_11 0x590f
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_12 0x5918
/* Coffee Lake-S */
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK 0x3e00
@@ -88,6 +90,7 @@
((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_9) || \
((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_10) || \
((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_11) || \
+ ((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_12) || \
(((did) & PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK) == \
PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK))
@@ -587,6 +590,7 @@ static const struct pci_device_id ie31200_pci_tbl[] = {
{ PCI_VEND_DEV(INTEL, IE31200_HB_9), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
{ PCI_VEND_DEV(INTEL, IE31200_HB_10), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
{ PCI_VEND_DEV(INTEL, IE31200_HB_11), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
+ { PCI_VEND_DEV(INTEL, IE31200_HB_12), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_1), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_2), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_3), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c
index 189a2fc29e74..fdf3a84fe698 100644
--- a/drivers/edac/igen6_edac.c
+++ b/drivers/edac/igen6_edac.c
@@ -263,6 +263,11 @@ static struct work_struct ecclog_work;
#define DID_ARL_UH_SKU2 0x7d20
#define DID_ARL_UH_SKU3 0x7d30
+/* Compute die IDs for Panther Lake-H with IBECC */
+#define DID_PTL_H_SKU1 0xb000
+#define DID_PTL_H_SKU2 0xb001
+#define DID_PTL_H_SKU3 0xb002
+
static int get_mchbar(struct pci_dev *pdev, u64 *mchbar)
{
union {
@@ -605,6 +610,9 @@ static const struct pci_device_id igen6_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, DID_ARL_UH_SKU1), (kernel_ulong_t)&mtl_p_cfg },
{ PCI_VDEVICE(INTEL, DID_ARL_UH_SKU2), (kernel_ulong_t)&mtl_p_cfg },
{ PCI_VDEVICE(INTEL, DID_ARL_UH_SKU3), (kernel_ulong_t)&mtl_p_cfg },
+ { PCI_VDEVICE(INTEL, DID_PTL_H_SKU1), (kernel_ulong_t)&mtl_p_cfg },
+ { PCI_VDEVICE(INTEL, DID_PTL_H_SKU2), (kernel_ulong_t)&mtl_p_cfg },
+ { PCI_VDEVICE(INTEL, DID_PTL_H_SKU3), (kernel_ulong_t)&mtl_p_cfg },
{ },
};
MODULE_DEVICE_TABLE(pci, igen6_pci_tbl);
@@ -1170,6 +1178,20 @@ fail:
return -ENODEV;
}
+static void igen6_check(struct mem_ctl_info *mci)
+{
+ struct igen6_imc *imc = mci->pvt_info;
+ u64 ecclog;
+
+ /* errsts_clear() isn't NMI-safe. Delay it in the IRQ context */
+ ecclog = ecclog_read_and_clear(imc);
+ if (!ecclog)
+ return;
+
+ if (!ecclog_gen_pool_add(imc->mc, ecclog))
+ irq_work_queue(&ecclog_irq_work);
+}
+
static int igen6_register_mci(int mc, u64 mchbar, struct pci_dev *pdev)
{
struct edac_mc_layer layers[2];
@@ -1211,6 +1233,8 @@ static int igen6_register_mci(int mc, u64 mchbar, struct pci_dev *pdev)
mci->edac_cap = EDAC_FLAG_SECDED;
mci->mod_name = EDAC_MOD_STR;
mci->dev_name = pci_name(pdev);
+ if (edac_op_state == EDAC_OPSTATE_POLL)
+ mci->edac_check = igen6_check;
mci->pvt_info = &igen6_pvt->imc[mc];
imc = mci->pvt_info;
@@ -1245,6 +1269,7 @@ static int igen6_register_mci(int mc, u64 mchbar, struct pci_dev *pdev)
imc->mci = mci;
return 0;
fail3:
+ mci->pvt_info = NULL;
kfree(mci->ctl_name);
fail2:
edac_mc_free(mci);
@@ -1269,6 +1294,7 @@ static void igen6_unregister_mcis(void)
edac_mc_del_mc(mci->pdev);
kfree(mci->ctl_name);
+ mci->pvt_info = NULL;
edac_mc_free(mci);
iounmap(imc->window);
}
@@ -1348,6 +1374,25 @@ static void unregister_err_handler(void)
unregister_nmi_handler(NMI_SERR, IGEN6_NMI_NAME);
}
+static void opstate_set(struct res_config *cfg, const struct pci_device_id *ent)
+{
+ /*
+ * Quirk: Certain SoCs' error reporting interrupts don't work.
+ * Force polling mode for them to ensure that memory error
+ * events can be handled.
+ */
+ if (ent->device == DID_ADL_N_SKU4) {
+ edac_op_state = EDAC_OPSTATE_POLL;
+ return;
+ }
+
+ /* Set the mode according to the configuration data. */
+ if (cfg->machine_check)
+ edac_op_state = EDAC_OPSTATE_INT;
+ else
+ edac_op_state = EDAC_OPSTATE_NMI;
+}
+
static int igen6_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
u64 mchbar;
@@ -1365,6 +1410,8 @@ static int igen6_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto fail;
+ opstate_set(res_cfg, ent);
+
for (i = 0; i < res_cfg->num_imc; i++) {
rc = igen6_register_mci(i, mchbar, pdev);
if (rc)
@@ -1448,8 +1495,6 @@ static int __init igen6_init(void)
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
return -EBUSY;
- edac_op_state = EDAC_OPSTATE_NMI;
-
rc = pci_register_driver(&igen6_driver);
if (rc)
return rc;
diff --git a/drivers/edac/layerscape_edac.c b/drivers/edac/layerscape_edac.c
index 0d42c1238908..9a0c92ebbc3c 100644
--- a/drivers/edac/layerscape_edac.c
+++ b/drivers/edac/layerscape_edac.c
@@ -21,6 +21,7 @@
static const struct of_device_id fsl_ddr_mc_err_of_match[] = {
{ .compatible = "fsl,qoriq-memory-controller", },
+ { .compatible = "nxp,imx9-memory-controller", .data = (void *)TYPE_IMX9, },
{},
};
MODULE_DEVICE_TABLE(of, fsl_ddr_mc_err_of_match);
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 8130c3dc64da..50d74d3bf0f5 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -793,7 +793,9 @@ static int
amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
{
struct mce *m = (struct mce *)data;
+ struct mce_hw_err *err = to_mce_hw_err(m);
unsigned int fam = x86_family(m->cpuid);
+ u32 mca_config_lo = 0, dummy;
int ecc;
if (m->kflags & MCE_HANDLED_CEC)
@@ -813,11 +815,9 @@ amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
((m->status & MCI_STATUS_PCC) ? "PCC" : "-"));
if (boot_cpu_has(X86_FEATURE_SMCA)) {
- u32 low, high;
- u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
+ rdmsr_safe(MSR_AMD64_SMCA_MCx_CONFIG(m->bank), &mca_config_lo, &dummy);
- if (!rdmsr_safe(addr, &low, &high) &&
- (low & MCI_CONFIG_MCAX))
+ if (mca_config_lo & MCI_CONFIG_MCAX)
pr_cont("|%s", ((m->status & MCI_STATUS_TCC) ? "TCC" : "-"));
pr_cont("|%s", ((m->status & MCI_STATUS_SYNDV) ? "SyndV" : "-"));
@@ -850,8 +850,18 @@ amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
if (boot_cpu_has(X86_FEATURE_SMCA)) {
pr_emerg(HW_ERR "IPID: 0x%016llx", m->ipid);
- if (m->status & MCI_STATUS_SYNDV)
- pr_cont(", Syndrome: 0x%016llx", m->synd);
+ if (m->status & MCI_STATUS_SYNDV) {
+ pr_cont(", Syndrome: 0x%016llx\n", m->synd);
+ if (mca_config_lo & MCI_CONFIG_FRUTEXT) {
+ char frutext[17];
+
+ frutext[16] = '\0';
+ memcpy(&frutext[0], &err->vendor.amd.synd1, 8);
+ memcpy(&frutext[8], &err->vendor.amd.synd2, 8);
+
+ pr_emerg(HW_ERR "FRU Text: %s", frutext);
+ }
+ }
pr_cont("\n");
diff --git a/drivers/edac/qcom_edac.c b/drivers/edac/qcom_edac.c
index d3cd4cc54ace..a9a8ba067007 100644
--- a/drivers/edac/qcom_edac.c
+++ b/drivers/edac/qcom_edac.c
@@ -342,9 +342,11 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev)
int ecc_irq;
int rc;
- rc = qcom_llcc_core_setup(llcc_driv_data, llcc_driv_data->bcast_regmap);
- if (rc)
- return rc;
+ if (!llcc_driv_data->ecc_irq_configured) {
+ rc = qcom_llcc_core_setup(llcc_driv_data, llcc_driv_data->bcast_regmap);
+ if (rc)
+ return rc;
+ }
/* Allocate edac control info */
edev_ctl = edac_device_alloc_ctl_info(0, "qcom-llcc", 1, "bank",
diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c
index 85713646957b..6cf17af7d911 100644
--- a/drivers/edac/skx_common.c
+++ b/drivers/edac/skx_common.c
@@ -47,6 +47,7 @@ static skx_show_retry_log_f skx_show_retry_rd_err_log;
static u64 skx_tolm, skx_tohm;
static LIST_HEAD(dev_edac_list);
static bool skx_mem_cfg_2lm;
+static struct res_config *skx_res_cfg;
int skx_adxl_get(void)
{
@@ -119,7 +120,7 @@ void skx_adxl_put(void)
}
EXPORT_SYMBOL_GPL(skx_adxl_put);
-static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_mem)
+static bool skx_adxl_decode(struct decoded_addr *res, enum error_source err_src)
{
struct skx_dev *d;
int i, len = 0;
@@ -135,8 +136,24 @@ static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_me
return false;
}
+ /*
+ * GNR with a Flat2LM memory configuration may mistakenly classify
+ * a near-memory error(DDR5) as a far-memory error(CXL), resulting
+ * in the incorrect selection of decoded ADXL components.
+ * To address this, prefetch the decoded far-memory controller ID
+ * and adjust the error source to near-memory if the far-memory
+ * controller ID is invalid.
+ */
+ if (skx_res_cfg && skx_res_cfg->type == GNR && err_src == ERR_SRC_2LM_FM) {
+ res->imc = (int)adxl_values[component_indices[INDEX_MEMCTRL]];
+ if (res->imc == -1) {
+ err_src = ERR_SRC_2LM_NM;
+ edac_dbg(0, "Adjust the error source to near-memory.\n");
+ }
+ }
+
res->socket = (int)adxl_values[component_indices[INDEX_SOCKET]];
- if (error_in_1st_level_mem) {
+ if (err_src == ERR_SRC_2LM_NM) {
res->imc = (adxl_nm_bitmap & BIT_NM_MEMCTRL) ?
(int)adxl_values[component_indices[INDEX_NM_MEMCTRL]] : -1;
res->channel = (adxl_nm_bitmap & BIT_NM_CHANNEL) ?
@@ -191,6 +208,12 @@ void skx_set_mem_cfg(bool mem_cfg_2lm)
}
EXPORT_SYMBOL_GPL(skx_set_mem_cfg);
+void skx_set_res_cfg(struct res_config *cfg)
+{
+ skx_res_cfg = cfg;
+}
+EXPORT_SYMBOL_GPL(skx_set_res_cfg);
+
void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log)
{
driver_decode = decode;
@@ -620,31 +643,27 @@ static void skx_mce_output_error(struct mem_ctl_info *mci,
optype, skx_msg);
}
-static bool skx_error_in_1st_level_mem(const struct mce *m)
+static enum error_source skx_error_source(const struct mce *m)
{
- u32 errcode;
+ u32 errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK;
- if (!skx_mem_cfg_2lm)
- return false;
-
- errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK;
-
- return errcode == MCACOD_EXT_MEM_ERR;
-}
+ if (errcode != MCACOD_MEM_CTL_ERR && errcode != MCACOD_EXT_MEM_ERR)
+ return ERR_SRC_NOT_MEMORY;
-static bool skx_error_in_mem(const struct mce *m)
-{
- u32 errcode;
+ if (!skx_mem_cfg_2lm)
+ return ERR_SRC_1LM;
- errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK;
+ if (errcode == MCACOD_EXT_MEM_ERR)
+ return ERR_SRC_2LM_NM;
- return (errcode == MCACOD_MEM_CTL_ERR || errcode == MCACOD_EXT_MEM_ERR);
+ return ERR_SRC_2LM_FM;
}
int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
void *data)
{
struct mce *mce = (struct mce *)data;
+ enum error_source err_src;
struct decoded_addr res;
struct mem_ctl_info *mci;
char *type;
@@ -652,8 +671,10 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
if (mce->kflags & MCE_HANDLED_CEC)
return NOTIFY_DONE;
+ err_src = skx_error_source(mce);
+
/* Ignore unless this is memory related with an address */
- if (!skx_error_in_mem(mce) || !(mce->status & MCI_STATUS_ADDRV))
+ if (err_src == ERR_SRC_NOT_MEMORY || !(mce->status & MCI_STATUS_ADDRV))
return NOTIFY_DONE;
memset(&res, 0, sizeof(res));
@@ -667,7 +688,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
/* Try driver decoder first */
if (!(driver_decode && driver_decode(&res))) {
/* Then try firmware decoder (ACPI DSM methods) */
- if (!(adxl_component_count && skx_adxl_decode(&res, skx_error_in_1st_level_mem(mce))))
+ if (!(adxl_component_count && skx_adxl_decode(&res, err_src)))
return NOTIFY_DONE;
}
diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h
index f945c1bf5ca4..54bba8a62f72 100644
--- a/drivers/edac/skx_common.h
+++ b/drivers/edac/skx_common.h
@@ -146,6 +146,13 @@ enum {
INDEX_MAX
};
+enum error_source {
+ ERR_SRC_1LM,
+ ERR_SRC_2LM_NM,
+ ERR_SRC_2LM_FM,
+ ERR_SRC_NOT_MEMORY,
+};
+
#define BIT_NM_MEMCTRL BIT_ULL(INDEX_NM_MEMCTRL)
#define BIT_NM_CHANNEL BIT_ULL(INDEX_NM_CHANNEL)
#define BIT_NM_DIMM BIT_ULL(INDEX_NM_DIMM)
@@ -234,6 +241,7 @@ int skx_adxl_get(void);
void skx_adxl_put(void);
void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log);
void skx_set_mem_cfg(bool mem_cfg_2lm);
+void skx_set_res_cfg(struct res_config *cfg);
int skx_get_src_id(struct skx_dev *d, int off, u8 *id);
int skx_get_node_id(struct skx_dev *d, u8 *id);
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index 892b94cfd626..74a6aa7d8cc9 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -56,7 +56,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
* two cases: either the path goes through this node, in which case
* the hop count is the sum of the two biggest child depths plus 2.
* Or it could be the case that the max hop path is entirely
- * containted in a child tree, in which case the max hop count is just
+ * contained in a child tree, in which case the max hop count is just
* the max hop count of this child.
*/
static void update_hop_count(struct fw_node *node)
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 0ae2c84ecafe..9b298af1cac0 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -80,7 +80,7 @@ struct fw_card_driver {
/*
* Allow the specified node ID to do direct DMA out and in of
* host memory. The card will disable this for all node when
- * a bus reset happens, so driver need to reenable this after
+ * a bus reset happens, so driver need to re-enable this after
* bus reset. Returns 0 on success, -ENODEV if the card
* doesn't support this, -ESTALE if the generation doesn't
* match.
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 7ee55c2804de..c02aed11b590 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1384,7 +1384,7 @@ struct driver_data {
};
/*
- * This function apppends a packet to the DMA queue for transmission.
+ * This function appends a packet to the DMA queue for transmission.
* Must always be called with the ochi->lock held to ensure proper
* generation handling and locking around packet queue manipulation.
*/
@@ -2213,7 +2213,7 @@ static irqreturn_t irq_handler(int irq, void *data)
if (unlikely(param_debug > 0)) {
dev_notice_ratelimited(ohci->card.device,
- "The debug parameter is superceded by tracepoints events, and deprecated.");
+ "The debug parameter is superseded by tracepoints events, and deprecated.");
}
/*
@@ -2614,7 +2614,7 @@ static int ohci_set_config_rom(struct fw_card *card,
* ConfigRomHeader and BusOptions doesn't honor the
* noByteSwapData bit, so with a be32 config rom, the
* controller will load be32 values in to these registers
- * during the atomic update, even on litte endian
+ * during the atomic update, even on little endian
* architectures. The workaround we use is to put a 0 in the
* header quadlet; 0 is endian agnostic and means that the
* config rom isn't ready yet. In the bus reset tasklet we
@@ -3726,12 +3726,11 @@ static int pci_probe(struct pci_dev *dev,
return -ENXIO;
}
- err = pcim_iomap_regions(dev, 1 << 0, ohci_driver_name);
- if (err) {
+ ohci->registers = pcim_iomap_region(dev, 0, ohci_driver_name);
+ if (IS_ERR(ohci->registers)) {
ohci_err(ohci, "request and map MMIO resource unavailable\n");
return -ENXIO;
}
- ohci->registers = pcim_iomap_table(dev)[0];
for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++)
if ((ohci_quirks[i].vendor == dev->vendor) &&
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index 96b2e5f9a8ef..157172a5f2b5 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -325,7 +325,10 @@ EXPORT_SYMBOL_GPL(scmi_driver_unregister);
static void scmi_device_release(struct device *dev)
{
- kfree(to_scmi_dev(dev));
+ struct scmi_device *scmi_dev = to_scmi_dev(dev);
+
+ kfree_const(scmi_dev->name);
+ kfree(scmi_dev);
}
static void __scmi_device_destroy(struct scmi_device *scmi_dev)
@@ -338,7 +341,6 @@ static void __scmi_device_destroy(struct scmi_device *scmi_dev)
if (scmi_dev->protocol_id == SCMI_PROTOCOL_SYSTEM)
atomic_set(&scmi_syspower_registered, 0);
- kfree_const(scmi_dev->name);
ida_free(&scmi_bus_id, scmi_dev->id);
device_unregister(&scmi_dev->dev);
}
@@ -410,7 +412,6 @@ __scmi_device_create(struct device_node *np, struct device *parent,
return scmi_dev;
put_dev:
- kfree_const(scmi_dev->name);
put_device(&scmi_dev->dev);
ida_free(&scmi_bus_id, id);
return NULL;
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index c4b8e7ff88aa..48b12f81141d 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -31,6 +31,8 @@
#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC)
+#define SCMI_SHMEM_MAX_PAYLOAD_SIZE 104
+
enum scmi_error_codes {
SCMI_SUCCESS = 0, /* Success */
SCMI_ERR_SUPPORT = -1, /* Not supported */
@@ -163,7 +165,9 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
* used to initialize this channel
* @dev: Reference to device in the SCMI hierarchy corresponding to this
* channel
+ * @is_p2a: A flag to identify a channel as P2A (RX)
* @rx_timeout_ms: The configured RX timeout in milliseconds.
+ * @max_msg_size: Maximum size of message payload.
* @handle: Pointer to SCMI entity handle
* @no_completion_irq: Flag to indicate that this channel has no completion
* interrupt mechanism for synchronous commands.
@@ -174,7 +178,9 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
struct scmi_chan_info {
int id;
struct device *dev;
+ bool is_p2a;
unsigned int rx_timeout_ms;
+ unsigned int max_msg_size;
struct scmi_handle *handle;
bool no_completion_irq;
void *transport_info;
@@ -222,7 +228,13 @@ struct scmi_transport_ops {
* @max_msg: Maximum number of messages for a channel type (tx or rx) that can
* be pending simultaneously in the system. May be overridden by the
* get_max_msg op.
- * @max_msg_size: Maximum size of data per message that can be handled.
+ * @max_msg_size: Maximum size of data payload per message that can be handled.
+ * @atomic_threshold: Optional system wide DT-configured threshold, expressed
+ * in microseconds, for atomic operations.
+ * Only SCMI synchronous commands reported by the platform
+ * to have an execution latency lesser-equal to the threshold
+ * should be considered for atomic mode operation: such
+ * decision is finally left up to the SCMI drivers.
* @force_polling: Flag to force this whole transport to use SCMI core polling
* mechanism instead of completion interrupts even if available.
* @sync_cmds_completed_on_ret: Flag to indicate that the transport assures
@@ -241,6 +253,7 @@ struct scmi_desc {
int max_rx_timeout_ms;
int max_msg;
int max_msg_size;
+ unsigned int atomic_threshold;
const bool force_polling;
const bool sync_cmds_completed_on_ret;
const bool atomic_enabled;
@@ -309,6 +322,26 @@ enum scmi_bad_msg {
MSG_MBOX_SPURIOUS = -5,
};
+/* Used for compactness and signature validation of the function pointers being
+ * passed.
+ */
+typedef void (*shmem_copy_toio_t)(void __iomem *to, const void *from,
+ size_t count);
+typedef void (*shmem_copy_fromio_t)(void *to, const void __iomem *from,
+ size_t count);
+
+/**
+ * struct scmi_shmem_io_ops - I/O operations to read from/write to
+ * Shared Memory
+ *
+ * @toio: Copy data to the shared memory area
+ * @fromio: Copy data from the shared memory area
+ */
+struct scmi_shmem_io_ops {
+ shmem_copy_fromio_t fromio;
+ shmem_copy_toio_t toio;
+};
+
/* shmem related declarations */
struct scmi_shared_mem;
@@ -329,13 +362,16 @@ struct scmi_shared_mem;
struct scmi_shared_mem_operations {
void (*tx_prepare)(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer,
- struct scmi_chan_info *cinfo);
+ struct scmi_chan_info *cinfo,
+ shmem_copy_toio_t toio);
u32 (*read_header)(struct scmi_shared_mem __iomem *shmem);
void (*fetch_response)(struct scmi_shared_mem __iomem *shmem,
- struct scmi_xfer *xfer);
+ struct scmi_xfer *xfer,
+ shmem_copy_fromio_t fromio);
void (*fetch_notification)(struct scmi_shared_mem __iomem *shmem,
- size_t max_len, struct scmi_xfer *xfer);
+ size_t max_len, struct scmi_xfer *xfer,
+ shmem_copy_fromio_t fromio);
void (*clear_channel)(struct scmi_shared_mem __iomem *shmem);
bool (*poll_done)(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);
@@ -343,7 +379,8 @@ struct scmi_shared_mem_operations {
bool (*channel_intr_enabled)(struct scmi_shared_mem __iomem *shmem);
void __iomem *(*setup_iomap)(struct scmi_chan_info *cinfo,
struct device *dev,
- bool tx, struct resource *res);
+ bool tx, struct resource *res,
+ struct scmi_shmem_io_ops **ops);
};
const struct scmi_shared_mem_operations *scmi_shared_mem_operations_get(void);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index a477b5ade38d..1b5fb2c4ce86 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -149,12 +149,6 @@ struct scmi_debug_info {
* base protocol
* @active_protocols: IDR storing device_nodes for protocols actually defined
* in the DT and confirmed as implemented by fw.
- * @atomic_threshold: Optional system wide DT-configured threshold, expressed
- * in microseconds, for atomic operations.
- * Only SCMI synchronous commands reported by the platform
- * to have an execution latency lesser-equal to the threshold
- * should be considered for atomic mode operation: such
- * decision is finally left up to the SCMI drivers.
* @notify_priv: Pointer to private data structure specific to notifications.
* @node: List head
* @users: Number of users of this instance
@@ -180,7 +174,6 @@ struct scmi_info {
struct mutex protocols_mtx;
u8 *protocols_imp;
struct idr active_protocols;
- unsigned int atomic_threshold;
void *notify_priv;
struct list_head node;
int users;
@@ -1048,6 +1041,11 @@ static inline void scmi_xfer_command_release(struct scmi_info *info,
static inline void scmi_clear_channel(struct scmi_info *info,
struct scmi_chan_info *cinfo)
{
+ if (!cinfo->is_p2a) {
+ dev_warn(cinfo->dev, "Invalid clear on A2P channel !\n");
+ return;
+ }
+
if (info->desc->ops->clear_channel)
info->desc->ops->clear_channel(cinfo);
}
@@ -2440,7 +2438,7 @@ static bool scmi_is_transport_atomic(const struct scmi_handle *handle,
ret = info->desc->atomic_enabled &&
is_transport_polling_capable(info->desc);
if (ret && atomic_threshold)
- *atomic_threshold = info->atomic_threshold;
+ *atomic_threshold = info->desc->atomic_threshold;
return ret;
}
@@ -2638,7 +2636,9 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
if (!cinfo)
return -ENOMEM;
+ cinfo->is_p2a = !tx;
cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms;
+ cinfo->max_msg_size = info->desc->max_msg_size;
/* Create a unique name for this transport device */
snprintf(name, 32, "__scmi_transport_device_%s_%02X",
@@ -2952,7 +2952,7 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
(char **)&dbg->name);
debugfs_create_u32("atomic_threshold_us", 0400, top_dentry,
- &info->atomic_threshold);
+ (u32 *)&info->desc->atomic_threshold);
debugfs_create_str("type", 0400, trans, (char **)&dbg->type);
@@ -3042,13 +3042,32 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev)
dev_info(dev, "Using %s\n", dev_driver_string(trans->supplier));
- ret = of_property_read_u32(dev->of_node, "max-rx-timeout-ms",
+ ret = of_property_read_u32(dev->of_node, "arm,max-rx-timeout-ms",
&trans->desc->max_rx_timeout_ms);
if (ret && ret != -EINVAL)
- dev_err(dev, "Malformed max-rx-timeout-ms DT property.\n");
+ dev_err(dev, "Malformed arm,max-rx-timeout-ms DT property.\n");
+
+ ret = of_property_read_u32(dev->of_node, "arm,max-msg-size",
+ &trans->desc->max_msg_size);
+ if (ret && ret != -EINVAL)
+ dev_err(dev, "Malformed arm,max-msg-size DT property.\n");
+
+ ret = of_property_read_u32(dev->of_node, "arm,max-msg",
+ &trans->desc->max_msg);
+ if (ret && ret != -EINVAL)
+ dev_err(dev, "Malformed arm,max-msg DT property.\n");
- dev_info(dev, "SCMI max-rx-timeout: %dms\n",
- trans->desc->max_rx_timeout_ms);
+ dev_info(dev,
+ "SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n",
+ trans->desc->max_rx_timeout_ms, trans->desc->max_msg_size,
+ trans->desc->max_msg);
+
+ /* System wide atomic threshold for atomic ops .. if any */
+ if (!of_property_read_u32(dev->of_node, "atomic-threshold-us",
+ &trans->desc->atomic_threshold))
+ dev_info(dev,
+ "SCMI System wide atomic threshold set to %u us\n",
+ trans->desc->atomic_threshold);
return trans->desc;
}
@@ -3099,13 +3118,6 @@ static int scmi_probe(struct platform_device *pdev)
handle->devm_protocol_acquire = scmi_devm_protocol_acquire;
handle->devm_protocol_get = scmi_devm_protocol_get;
handle->devm_protocol_put = scmi_devm_protocol_put;
-
- /* System wide atomic threshold for atomic ops .. if any */
- if (!of_property_read_u32(np, "atomic-threshold-us",
- &info->atomic_threshold))
- dev_info(dev,
- "SCMI System wide atomic threshold set to %d us\n",
- info->atomic_threshold);
handle->is_transport_atomic = scmi_is_transport_atomic;
/* Setup all channels described in the DT at first */
@@ -3321,7 +3333,7 @@ static struct platform_driver scmi_driver = {
.dev_groups = versions_groups,
},
.probe = scmi_probe,
- .remove_new = scmi_remove,
+ .remove = scmi_remove,
};
static struct dentry *scmi_debugfs_init(void)
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 2d77b5f40ca7..c7e5a34b254b 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -373,7 +373,7 @@ static int iter_perf_levels_update_state(struct scmi_iterator_state *st,
return 0;
}
-static inline void
+static inline int
process_response_opp(struct device *dev, struct perf_dom_info *dom,
struct scmi_opp *opp, unsigned int loop_idx,
const struct scmi_msg_resp_perf_describe_levels *r)
@@ -386,12 +386,16 @@ process_response_opp(struct device *dev, struct perf_dom_info *dom,
le16_to_cpu(r->opp[loop_idx].transition_latency_us);
ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL);
- if (ret)
- dev_warn(dev, "Failed to add opps_by_lvl at %d for %s - ret:%d\n",
+ if (ret) {
+ dev_info(dev, FW_BUG "Failed to add opps_by_lvl at %d for %s - ret:%d\n",
opp->perf, dom->info.name, ret);
+ return ret;
+ }
+
+ return 0;
}
-static inline void
+static inline int
process_response_opp_v4(struct device *dev, struct perf_dom_info *dom,
struct scmi_opp *opp, unsigned int loop_idx,
const struct scmi_msg_resp_perf_describe_levels_v4 *r)
@@ -404,9 +408,11 @@ process_response_opp_v4(struct device *dev, struct perf_dom_info *dom,
le16_to_cpu(r->opp[loop_idx].transition_latency_us);
ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL);
- if (ret)
- dev_warn(dev, "Failed to add opps_by_lvl at %d for %s - ret:%d\n",
+ if (ret) {
+ dev_info(dev, FW_BUG "Failed to add opps_by_lvl at %d for %s - ret:%d\n",
opp->perf, dom->info.name, ret);
+ return ret;
+ }
/* Note that PERF v4 reports always five 32-bit words */
opp->indicative_freq = le32_to_cpu(r->opp[loop_idx].indicative_freq);
@@ -415,13 +421,21 @@ process_response_opp_v4(struct device *dev, struct perf_dom_info *dom,
ret = xa_insert(&dom->opps_by_idx, opp->level_index, opp,
GFP_KERNEL);
- if (ret)
+ if (ret) {
dev_warn(dev,
"Failed to add opps_by_idx at %d for %s - ret:%d\n",
opp->level_index, dom->info.name, ret);
+ /* Cleanup by_lvl too */
+ xa_erase(&dom->opps_by_lvl, opp->perf);
+
+ return ret;
+ }
+
hash_add(dom->opps_by_freq, &opp->hash, opp->indicative_freq);
}
+
+ return 0;
}
static int
@@ -429,16 +443,22 @@ iter_perf_levels_process_response(const struct scmi_protocol_handle *ph,
const void *response,
struct scmi_iterator_state *st, void *priv)
{
+ int ret;
struct scmi_opp *opp;
struct scmi_perf_ipriv *p = priv;
- opp = &p->perf_dom->opp[st->desc_index + st->loop_idx];
+ opp = &p->perf_dom->opp[p->perf_dom->opp_count];
if (PROTOCOL_REV_MAJOR(p->version) <= 0x3)
- process_response_opp(ph->dev, p->perf_dom, opp, st->loop_idx,
- response);
+ ret = process_response_opp(ph->dev, p->perf_dom, opp,
+ st->loop_idx, response);
else
- process_response_opp_v4(ph->dev, p->perf_dom, opp, st->loop_idx,
- response);
+ ret = process_response_opp_v4(ph->dev, p->perf_dom, opp,
+ st->loop_idx, response);
+
+ /* Skip BAD duplicates received from firmware */
+ if (ret)
+ return ret == -EBUSY ? 0 : ret;
+
p->perf_dom->opp_count++;
dev_dbg(ph->dev, "Level %d Power %d Latency %dus Ifreq %d Index %d\n",
diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c
index 01d8a9398fe8..11c347bff766 100644
--- a/drivers/firmware/arm_scmi/shmem.c
+++ b/drivers/firmware/arm_scmi/shmem.c
@@ -16,6 +16,8 @@
#include "common.h"
+#define SCMI_SHMEM_LAYOUT_OVERHEAD 24
+
/*
* SCMI specification requires all parameters, message headers, return
* arguments or any protocol data to be expressed in little endian
@@ -34,9 +36,59 @@ struct scmi_shared_mem {
u8 msg_payload[];
};
+static inline void shmem_memcpy_fromio32(void *to,
+ const void __iomem *from,
+ size_t count)
+{
+ WARN_ON(!IS_ALIGNED((unsigned long)from, 4) ||
+ !IS_ALIGNED((unsigned long)to, 4) ||
+ count % 4);
+
+ __ioread32_copy(to, from, count / 4);
+}
+
+static inline void shmem_memcpy_toio32(void __iomem *to,
+ const void *from,
+ size_t count)
+{
+ WARN_ON(!IS_ALIGNED((unsigned long)to, 4) ||
+ !IS_ALIGNED((unsigned long)from, 4) ||
+ count % 4);
+
+ __iowrite32_copy(to, from, count / 4);
+}
+
+static struct scmi_shmem_io_ops shmem_io_ops32 = {
+ .fromio = shmem_memcpy_fromio32,
+ .toio = shmem_memcpy_toio32,
+};
+
+/* Wrappers are needed for proper memcpy_{from,to}_io expansion by the
+ * pre-processor.
+ */
+static inline void shmem_memcpy_fromio(void *to,
+ const void __iomem *from,
+ size_t count)
+{
+ memcpy_fromio(to, from, count);
+}
+
+static inline void shmem_memcpy_toio(void __iomem *to,
+ const void *from,
+ size_t count)
+{
+ memcpy_toio(to, from, count);
+}
+
+static struct scmi_shmem_io_ops shmem_io_ops_default = {
+ .fromio = shmem_memcpy_fromio,
+ .toio = shmem_memcpy_toio,
+};
+
static void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer,
- struct scmi_chan_info *cinfo)
+ struct scmi_chan_info *cinfo,
+ shmem_copy_toio_t copy_toio)
{
ktime_t stop;
@@ -73,7 +125,7 @@ static void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
iowrite32(sizeof(shmem->msg_header) + xfer->tx.len, &shmem->length);
iowrite32(pack_scmi_header(&xfer->hdr), &shmem->msg_header);
if (xfer->tx.buf)
- memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len);
+ copy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len);
}
static u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem)
@@ -82,7 +134,8 @@ static u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem)
}
static void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
- struct scmi_xfer *xfer)
+ struct scmi_xfer *xfer,
+ shmem_copy_fromio_t copy_fromio)
{
size_t len = ioread32(&shmem->length);
@@ -91,11 +144,12 @@ static void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
xfer->rx.len = min_t(size_t, xfer->rx.len, len > 8 ? len - 8 : 0);
/* Take a copy to the rx buffer.. */
- memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len);
+ copy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len);
}
static void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem,
- size_t max_len, struct scmi_xfer *xfer)
+ size_t max_len, struct scmi_xfer *xfer,
+ shmem_copy_fromio_t copy_fromio)
{
size_t len = ioread32(&shmem->length);
@@ -103,7 +157,7 @@ static void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem,
xfer->rx.len = min_t(size_t, max_len, len > 4 ? len - 4 : 0);
/* Take a copy to the rx buffer.. */
- memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len);
+ copy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len);
}
static void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem)
@@ -139,7 +193,8 @@ static bool shmem_channel_intr_enabled(struct scmi_shared_mem __iomem *shmem)
static void __iomem *shmem_setup_iomap(struct scmi_chan_info *cinfo,
struct device *dev, bool tx,
- struct resource *res)
+ struct resource *res,
+ struct scmi_shmem_io_ops **ops)
{
struct device_node *shmem __free(device_node);
const char *desc = tx ? "Tx" : "Rx";
@@ -148,6 +203,7 @@ static void __iomem *shmem_setup_iomap(struct scmi_chan_info *cinfo,
struct resource lres = {};
resource_size_t size;
void __iomem *addr;
+ u32 reg_io_width;
shmem = of_parse_phandle(cdev->of_node, "shmem", idx);
if (!shmem)
@@ -167,12 +223,27 @@ static void __iomem *shmem_setup_iomap(struct scmi_chan_info *cinfo,
}
size = resource_size(res);
+ if (cinfo->max_msg_size + SCMI_SHMEM_LAYOUT_OVERHEAD > size) {
+ dev_err(dev, "misconfigured SCMI shared memory\n");
+ return IOMEM_ERR_PTR(-ENOSPC);
+ }
+
addr = devm_ioremap(dev, res->start, size);
if (!addr) {
dev_err(dev, "failed to ioremap SCMI %s shared memory\n", desc);
return IOMEM_ERR_PTR(-EADDRNOTAVAIL);
}
+ of_property_read_u32(shmem, "reg-io-width", &reg_io_width);
+ switch (reg_io_width) {
+ case 4:
+ *ops = &shmem_io_ops32;
+ break;
+ default:
+ *ops = &shmem_io_ops_default;
+ break;
+ }
+
return addr;
}
diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c
index e3d5f7560990..b66df2981456 100644
--- a/drivers/firmware/arm_scmi/transports/mailbox.c
+++ b/drivers/firmware/arm_scmi/transports/mailbox.c
@@ -26,6 +26,7 @@
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
* @chan_lock: Lock that prevents multiple xfers from being queued
+ * @io_ops: Transport specific I/O operations
*/
struct scmi_mailbox {
struct mbox_client cl;
@@ -35,6 +36,7 @@ struct scmi_mailbox {
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
struct mutex chan_lock;
+ struct scmi_shmem_io_ops *io_ops;
};
#define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl)
@@ -45,7 +47,8 @@ static void tx_prepare(struct mbox_client *cl, void *m)
{
struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
- core->shmem->tx_prepare(smbox->shmem, m, smbox->cinfo);
+ core->shmem->tx_prepare(smbox->shmem, m, smbox->cinfo,
+ smbox->io_ops->toio);
}
static void rx_callback(struct mbox_client *cl, void *m)
@@ -197,7 +200,8 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
if (!smbox)
return -ENOMEM;
- smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL);
+ smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL,
+ &smbox->io_ops);
if (IS_ERR(smbox->shmem))
return PTR_ERR(smbox->shmem);
@@ -305,7 +309,7 @@ static void mailbox_fetch_response(struct scmi_chan_info *cinfo,
{
struct scmi_mailbox *smbox = cinfo->transport_info;
- core->shmem->fetch_response(smbox->shmem, xfer);
+ core->shmem->fetch_response(smbox->shmem, xfer, smbox->io_ops->fromio);
}
static void mailbox_fetch_notification(struct scmi_chan_info *cinfo,
@@ -313,7 +317,8 @@ static void mailbox_fetch_notification(struct scmi_chan_info *cinfo,
{
struct scmi_mailbox *smbox = cinfo->transport_info;
- core->shmem->fetch_notification(smbox->shmem, max_len, xfer);
+ core->shmem->fetch_notification(smbox->shmem, max_len, xfer,
+ smbox->io_ops->fromio);
}
static void mailbox_clear_channel(struct scmi_chan_info *cinfo)
@@ -366,7 +371,7 @@ static struct scmi_desc scmi_mailbox_desc = {
.ops = &scmi_mailbox_ops,
.max_rx_timeout_ms = 30, /* We may increase this if required */
.max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
- .max_msg_size = 128,
+ .max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE,
};
static const struct of_device_id scmi_of_match[] = {
diff --git a/drivers/firmware/arm_scmi/transports/optee.c b/drivers/firmware/arm_scmi/transports/optee.c
index 56fc63edf51e..3949a877e17d 100644
--- a/drivers/firmware/arm_scmi/transports/optee.c
+++ b/drivers/firmware/arm_scmi/transports/optee.c
@@ -17,8 +17,6 @@
#include "../common.h"
-#define SCMI_OPTEE_MAX_MSG_SIZE 128
-
enum scmi_optee_pta_cmd {
/*
* PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities
@@ -114,6 +112,7 @@ enum scmi_optee_pta_cmd {
* @req.shmem: Virtual base address of the shared memory
* @req.msg: Shared memory protocol handle for SCMI request and
* synchronous response
+ * @io_ops: Transport specific I/O operations
* @tee_shm: TEE shared memory handle @req or NULL if using IOMEM shmem
* @link: Reference in agent's channel list
*/
@@ -128,6 +127,7 @@ struct scmi_optee_channel {
struct scmi_shared_mem __iomem *shmem;
struct scmi_msg_payld *msg;
} req;
+ struct scmi_shmem_io_ops *io_ops;
struct tee_shm *tee_shm;
struct list_head link;
};
@@ -297,7 +297,7 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t
param[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
param[2].u.memref.shm = channel->tee_shm;
- param[2].u.memref.size = SCMI_OPTEE_MAX_MSG_SIZE;
+ param[2].u.memref.size = SCMI_SHMEM_MAX_PAYLOAD_SIZE;
ret = tee_client_invoke_func(scmi_optee_private->tee_ctx, &arg, param);
if (ret < 0 || arg.ret) {
@@ -330,7 +330,7 @@ static void scmi_optee_clear_channel(struct scmi_chan_info *cinfo)
static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *channel)
{
- const size_t msg_size = SCMI_OPTEE_MAX_MSG_SIZE;
+ const size_t msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE;
void *shbuf;
channel->tee_shm = tee_shm_alloc_kernel_buf(scmi_optee_private->tee_ctx, msg_size);
@@ -350,7 +350,8 @@ static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *ch
static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo,
struct scmi_optee_channel *channel)
{
- channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL);
+ channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL,
+ &channel->io_ops);
if (IS_ERR(channel->req.shmem))
return PTR_ERR(channel->req.shmem);
@@ -465,7 +466,8 @@ static int scmi_optee_send_message(struct scmi_chan_info *cinfo,
ret = invoke_process_msg_channel(channel,
core->msg->command_size(xfer));
} else {
- core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo);
+ core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo,
+ channel->io_ops->toio);
ret = invoke_process_smt_channel(channel);
}
@@ -484,7 +486,8 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
core->msg->fetch_response(channel->req.msg,
channel->rx_len, xfer);
else
- core->shmem->fetch_response(channel->req.shmem, xfer);
+ core->shmem->fetch_response(channel->req.shmem, xfer,
+ channel->io_ops->fromio);
}
static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret,
@@ -514,7 +517,7 @@ static struct scmi_desc scmi_optee_desc = {
.ops = &scmi_optee_ops,
.max_rx_timeout_ms = 30,
.max_msg = 20,
- .max_msg_size = SCMI_OPTEE_MAX_MSG_SIZE,
+ .max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE,
.sync_cmds_completed_on_ret = true,
};
diff --git a/drivers/firmware/arm_scmi/transports/smc.c b/drivers/firmware/arm_scmi/transports/smc.c
index f8dd108777f9..f632a62cfb3e 100644
--- a/drivers/firmware/arm_scmi/transports/smc.c
+++ b/drivers/firmware/arm_scmi/transports/smc.c
@@ -45,6 +45,7 @@
* @irq: An optional IRQ for completion
* @cinfo: SCMI channel info
* @shmem: Transmit/Receive shared memory area
+ * @io_ops: Transport specific I/O operations
* @shmem_lock: Lock to protect access to Tx/Rx shared memory area.
* Used when NOT operating in atomic mode.
* @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
@@ -60,6 +61,7 @@ struct scmi_smc {
int irq;
struct scmi_chan_info *cinfo;
struct scmi_shared_mem __iomem *shmem;
+ struct scmi_shmem_io_ops *io_ops;
/* Protect access to shmem area */
struct mutex shmem_lock;
#define INFLIGHT_NONE MSG_TOKEN_MAX
@@ -144,7 +146,8 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
if (!scmi_info)
return -ENOMEM;
- scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res);
+ scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res,
+ &scmi_info->io_ops);
if (IS_ERR(scmi_info->shmem))
return PTR_ERR(scmi_info->shmem);
@@ -229,7 +232,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
*/
smc_channel_lock_acquire(scmi_info, xfer);
- core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo);
+ core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo,
+ scmi_info->io_ops->toio);
if (scmi_info->cap_id != ULONG_MAX)
arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->cap_id, 0,
@@ -253,7 +257,8 @@ static void smc_fetch_response(struct scmi_chan_info *cinfo,
{
struct scmi_smc *scmi_info = cinfo->transport_info;
- core->shmem->fetch_response(scmi_info->shmem, xfer);
+ core->shmem->fetch_response(scmi_info->shmem, xfer,
+ scmi_info->io_ops->fromio);
}
static void smc_mark_txdone(struct scmi_chan_info *cinfo, int ret,
@@ -277,7 +282,7 @@ static struct scmi_desc scmi_smc_desc = {
.ops = &scmi_smc_ops,
.max_rx_timeout_ms = 30,
.max_msg = 20,
- .max_msg_size = 128,
+ .max_msg_size = SCMI_SHMEM_MAX_PAYLOAD_SIZE,
/*
* Setting .sync_cmds_atomic_replies to true for SMC assumes that,
* once the SMC instruction has completed successfully, the issued
diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmware/arm_scmi/transports/virtio.c
index d349766bc0b2..41aea33776a9 100644
--- a/drivers/firmware/arm_scmi/transports/virtio.c
+++ b/drivers/firmware/arm_scmi/transports/virtio.c
@@ -32,8 +32,8 @@
#define VIRTIO_MAX_RX_TIMEOUT_MS 60000
#define VIRTIO_SCMI_MAX_MSG_SIZE 128 /* Value may be increased. */
-#define VIRTIO_SCMI_MAX_PDU_SIZE \
- (VIRTIO_SCMI_MAX_MSG_SIZE + SCMI_MSG_MAX_PROT_OVERHEAD)
+#define VIRTIO_SCMI_MAX_PDU_SIZE(ci) \
+ ((ci)->max_msg_size + SCMI_MSG_MAX_PROT_OVERHEAD)
#define DESCRIPTORS_PER_TX_MSG 2
/**
@@ -90,6 +90,7 @@ enum poll_states {
* @input: SDU used for (delayed) responses and notifications
* @list: List which scmi_vio_msg may be part of
* @rx_len: Input SDU size in bytes, once input has been received
+ * @max_len: Maximumm allowed SDU size in bytes
* @poll_idx: Last used index registered for polling purposes if this message
* transaction reply was configured for polling.
* @poll_status: Polling state for this message.
@@ -102,6 +103,7 @@ struct scmi_vio_msg {
struct scmi_msg_payld *input;
struct list_head list;
unsigned int rx_len;
+ unsigned int max_len;
unsigned int poll_idx;
enum poll_states poll_status;
/* Lock to protect access to poll_status */
@@ -234,7 +236,7 @@ static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch,
unsigned long flags;
struct device *dev = &vioch->vqueue->vdev->dev;
- sg_init_one(&sg_in, msg->input, VIRTIO_SCMI_MAX_PDU_SIZE);
+ sg_init_one(&sg_in, msg->input, msg->max_len);
spin_lock_irqsave(&vioch->lock, flags);
@@ -439,9 +441,9 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
if (!msg)
return -ENOMEM;
+ msg->max_len = VIRTIO_SCMI_MAX_PDU_SIZE(cinfo);
if (tx) {
- msg->request = devm_kzalloc(dev,
- VIRTIO_SCMI_MAX_PDU_SIZE,
+ msg->request = devm_kzalloc(dev, msg->max_len,
GFP_KERNEL);
if (!msg->request)
return -ENOMEM;
@@ -449,8 +451,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
refcount_set(&msg->users, 1);
}
- msg->input = devm_kzalloc(dev, VIRTIO_SCMI_MAX_PDU_SIZE,
- GFP_KERNEL);
+ msg->input = devm_kzalloc(dev, msg->max_len, GFP_KERNEL);
if (!msg->input)
return -ENOMEM;
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 94a6b4e667de..87c323de17b9 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -630,6 +630,9 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
if (ret)
return ERR_PTR(ret);
+ if (!buf.opp_count)
+ return ERR_PTR(-ENOENT);
+
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return ERR_PTR(-ENOMEM);
@@ -1046,7 +1049,7 @@ static struct platform_driver scpi_driver = {
.dev_groups = versions_groups,
},
.probe = scpi_probe,
- .remove_new = scpi_remove,
+ .remove = scpi_remove,
};
module_platform_driver(scpi_driver);
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 72f2537d90ca..e312d731f4a3 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -84,12 +84,10 @@ config EFI_ZBOOT
help
Create the bootable image as an EFI application that carries the
actual kernel image in compressed form, and decompresses it into
- memory before executing it via LoadImage/StartImage EFI boot service
- calls. For compatibility with non-EFI loaders, the payload can be
- decompressed and executed by the loader as well, provided that the
- loader implements the decompression algorithm and that non-EFI boot
- is supported by the encapsulated image. (The compression algorithm
- used is described in the zboot image header)
+ memory before executing it. For compatibility with non-EFI loaders,
+ the payload can be decompressed and executed by the loader as well,
+ provided that the loader implements the decompression algorithm.
+ (The compression algorithm used is described in the zboot header)
config EFI_ARMSTUB_DTB_LOADER
bool "Enable the DTB loader"
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 70490bf2697b..60c64b81d2c3 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -273,6 +273,7 @@ static __init int efivar_ssdt_load(void)
efi_char16_t *name = NULL;
efi_status_t status;
efi_guid_t guid;
+ int ret = 0;
if (!efivar_ssdt[0])
return 0;
@@ -294,8 +295,8 @@ static __init int efivar_ssdt_load(void)
efi_char16_t *name_tmp =
krealloc(name, name_size, GFP_KERNEL);
if (!name_tmp) {
- kfree(name);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
name = name_tmp;
continue;
@@ -309,26 +310,38 @@ static __init int efivar_ssdt_load(void)
pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt, &guid);
status = efi.get_variable(name, &guid, NULL, &data_size, NULL);
- if (status != EFI_BUFFER_TOO_SMALL || !data_size)
- return -EIO;
+ if (status != EFI_BUFFER_TOO_SMALL || !data_size) {
+ ret = -EIO;
+ goto out;
+ }
data = kmalloc(data_size, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
+ if (!data) {
+ ret = -ENOMEM;
+ goto out;
+ }
status = efi.get_variable(name, &guid, NULL, &data_size, data);
if (status == EFI_SUCCESS) {
- acpi_status ret = acpi_load_table(data, NULL);
- if (ret)
- pr_err("failed to load table: %u\n", ret);
- else
+ acpi_status acpi_ret = acpi_load_table(data, NULL);
+ if (ACPI_FAILURE(acpi_ret)) {
+ pr_err("efivar_ssdt: failed to load table: %u\n",
+ acpi_ret);
+ } else {
+ /*
+ * The @data will be in use by ACPI engine,
+ * do not free it!
+ */
continue;
+ }
} else {
- pr_err("failed to get var data: 0x%lx\n", status);
+ pr_err("efivar_ssdt: failed to get var data: 0x%lx\n", status);
}
kfree(data);
}
- return 0;
+out:
+ kfree(name);
+ return ret;
}
#else
static inline int efivar_ssdt_load(void) { return 0; }
@@ -433,7 +446,9 @@ static int __init efisubsys_init(void)
error = generic_ops_register();
if (error)
goto err_put;
- efivar_ssdt_load();
+ error = efivar_ssdt_load();
+ if (error)
+ pr_err("efi: failed to load SSDT, error %d.\n", error);
platform_device_register_simple("efivars", 0, NULL, 0);
}
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index de659f6a815f..c0c81ca4237e 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -327,7 +327,7 @@ fail:
* Size of memory allocated return in *cmd_line_len.
* Returns NULL on error.
*/
-char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
+char *efi_convert_cmdline(efi_loaded_image_t *image)
{
const efi_char16_t *options = efi_table_attr(image, load_options);
u32 options_size = efi_table_attr(image, load_options_size);
@@ -405,7 +405,6 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
snprintf((char *)cmdline_addr, options_bytes, "%.*ls",
options_bytes - 1, options);
- *cmd_line_len = options_bytes;
return (char *)cmdline_addr;
}
@@ -621,10 +620,6 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
status = efi_load_initrd_dev_path(&initrd, hard_limit);
if (status == EFI_SUCCESS) {
efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
- if (initrd.size > 0 &&
- efi_measure_tagged_event(initrd.base, initrd.size,
- EFISTUB_EVT_INITRD) == EFI_SUCCESS)
- efi_info("Measured initrd data into PCR 9\n");
} else if (status == EFI_NOT_FOUND) {
status = efi_load_initrd_cmdline(image, &initrd, soft_limit,
hard_limit);
@@ -637,6 +632,11 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
if (status != EFI_SUCCESS)
goto failed;
+ if (initrd.size > 0 &&
+ efi_measure_tagged_event(initrd.base, initrd.size,
+ EFISTUB_EVT_INITRD) == EFI_SUCCESS)
+ efi_info("Measured initrd data into PCR 9\n");
+
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(initrd),
(void **)&tbl);
if (status != EFI_SUCCESS)
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 958a680e0660..382b54f40603 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -112,7 +112,6 @@ static u32 get_supported_rt_services(void)
efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
{
- int cmdline_size = 0;
efi_status_t status;
char *cmdline;
@@ -121,35 +120,32 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
* protocol. We are going to copy the command line into the
* device tree, so this can be allocated anywhere.
*/
- cmdline = efi_convert_cmdline(image, &cmdline_size);
+ cmdline = efi_convert_cmdline(image);
if (!cmdline) {
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
return EFI_OUT_OF_RESOURCES;
}
- if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
- IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
- cmdline_size == 0) {
- status = efi_parse_options(CONFIG_CMDLINE);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to parse options\n");
+ if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
+ status = efi_parse_options(cmdline);
+ if (status != EFI_SUCCESS)
goto fail_free_cmdline;
- }
}
- if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
- status = efi_parse_options(cmdline);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to parse options\n");
+ if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+ IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+ cmdline[0] == 0) {
+ status = efi_parse_options(CONFIG_CMDLINE);
+ if (status != EFI_SUCCESS)
goto fail_free_cmdline;
- }
}
*cmdline_ptr = cmdline;
return EFI_SUCCESS;
fail_free_cmdline:
- efi_bs_call(free_pool, cmdline_ptr);
+ efi_err("Failed to parse options\n");
+ efi_bs_call(free_pool, cmdline);
return status;
}
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 685098f9626f..76e44c185f29 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1056,7 +1056,7 @@ void efi_free(unsigned long size, unsigned long addr);
void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size);
-char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
+char *efi_convert_cmdline(efi_loaded_image_t *image);
efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
bool install_cfg_tbl);
diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c
index d6a025df07dc..bd626d55dcbc 100644
--- a/drivers/firmware/efi/libstub/file.c
+++ b/drivers/firmware/efi/libstub/file.c
@@ -175,6 +175,12 @@ static efi_status_t efi_open_device_path(efi_file_protocol_t **volume,
return status;
}
+#ifndef CONFIG_CMDLINE
+#define CONFIG_CMDLINE
+#endif
+
+static const efi_char16_t builtin_cmdline[] = L"" CONFIG_CMDLINE;
+
/*
* Check the cmdline for a LILO-style file= arguments.
*
@@ -189,6 +195,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
unsigned long *load_addr,
unsigned long *load_size)
{
+ const bool ignore_load_options = IS_ENABLED(CONFIG_CMDLINE_OVERRIDE) ||
+ IS_ENABLED(CONFIG_CMDLINE_FORCE);
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;
@@ -197,6 +205,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
unsigned long alloc_addr;
unsigned long alloc_size;
efi_status_t status;
+ bool twopass;
int offset;
if (!load_addr || !load_size)
@@ -209,6 +218,16 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
efi_chunk_size = EFI_READ_CHUNK_SIZE;
alloc_addr = alloc_size = 0;
+
+ if (!ignore_load_options && cmdline_len > 0) {
+ twopass = IS_ENABLED(CONFIG_CMDLINE_BOOL) ||
+ IS_ENABLED(CONFIG_CMDLINE_EXTEND);
+ } else {
+do_builtin: cmdline = builtin_cmdline;
+ cmdline_len = ARRAY_SIZE(builtin_cmdline) - 1;
+ twopass = false;
+ }
+
do {
struct finfo fi;
unsigned long size;
@@ -290,6 +309,9 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
efi_call_proto(volume, close);
} while (offset > 0);
+ if (twopass)
+ goto do_builtin;
+
*load_addr = alloc_addr;
*load_size = alloc_size;
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index 1fd6823248ab..a5c6c4f163fc 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -57,7 +57,7 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca
struct linux_efi_tpm_eventlog *log_tbl = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
- int final_events_size = 0;
+ u32 final_events_size = 0;
first_entry_addr = (unsigned long) log_location;
@@ -110,9 +110,9 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca
*/
if (final_events_table && final_events_table->nr_events) {
struct tcg_pcr_event2_head *header;
- int offset;
+ u32 offset;
void *data;
- int event_size;
+ u32 event_size;
int i = final_events_table->nr_events;
data = (void *)final_events_table;
@@ -124,6 +124,9 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca
event_size = __calc_tpm2_event_size(header,
(void *)(long)log_location,
false);
+ /* If calc fails this is a malformed log */
+ if (!event_size)
+ break;
final_events_size += event_size;
i--;
}
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index f8e465da344d..188c8000d245 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -537,7 +537,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
struct boot_params *boot_params;
struct setup_header *hdr;
- int options_size = 0;
efi_status_t status;
unsigned long alloc;
char *cmdline_ptr;
@@ -569,7 +568,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
hdr->initrd_addr_max = INT_MAX;
/* Convert unicode cmdline to ascii */
- cmdline_ptr = efi_convert_cmdline(image, &options_size);
+ cmdline_ptr = efi_convert_cmdline(image);
if (!cmdline_ptr) {
efi_free(PARAM_SIZE, alloc);
efi_exit(handle, EFI_OUT_OF_RESOURCES);
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 164203429fa7..c38b1a335590 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -22,6 +22,7 @@ unsigned long __ro_after_init efi_mem_attr_table = EFI_INVALID_TABLE_ADDR;
int __init efi_memattr_init(void)
{
efi_memory_attributes_table_t *tbl;
+ unsigned long size;
if (efi_mem_attr_table == EFI_INVALID_TABLE_ADDR)
return 0;
@@ -39,7 +40,22 @@ int __init efi_memattr_init(void)
goto unmap;
}
- tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
+
+ /*
+ * Sanity check: the Memory Attributes Table contains up to 3 entries
+ * for each entry of type EfiRuntimeServicesCode in the EFI memory map.
+ * So if the size of the table exceeds 3x the size of the entire EFI
+ * memory map, there is clearly something wrong, and the table should
+ * just be ignored altogether.
+ */
+ size = tbl->num_entries * tbl->desc_size;
+ if (size > 3 * efi.memmap.nr_map * efi.memmap.desc_size) {
+ pr_warn(FW_BUG "Corrupted EFI Memory Attributes Table detected! (version == %u, desc_size == %u, num_entries == %u)\n",
+ tbl->version, tbl->desc_size, tbl->num_entries);
+ goto unmap;
+ }
+
+ tbl_size = sizeof(*tbl) + size;
memblock_reserve(efi_mem_attr_table, tbl_size);
set_bit(EFI_MEM_ATTR, &efi.flags);
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
index e8d69bd548f3..cdd431027065 100644
--- a/drivers/firmware/efi/tpm.c
+++ b/drivers/firmware/efi/tpm.c
@@ -19,7 +19,7 @@ EXPORT_SYMBOL(efi_tpm_final_log_size);
static int __init tpm2_calc_event_log_size(void *data, int count, void *size_info)
{
struct tcg_pcr_event2_head *header;
- int event_size, size = 0;
+ u32 event_size, size = 0;
while (count > 0) {
header = data + size;
@@ -40,7 +40,8 @@ int __init efi_tpm_eventlog_init(void)
{
struct linux_efi_tpm_eventlog *log_tbl;
struct efi_tcg2_final_events_table *final_tbl;
- int tbl_size;
+ unsigned int tbl_size;
+ int final_tbl_size;
int ret = 0;
if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
@@ -60,7 +61,12 @@ int __init efi_tpm_eventlog_init(void)
}
tbl_size = sizeof(*log_tbl) + log_tbl->size;
- memblock_reserve(efi.tpm_log, tbl_size);
+ if (memblock_reserve(efi.tpm_log, tbl_size)) {
+ pr_err("TPM Event Log memblock reserve fails (0x%lx, 0x%x)\n",
+ efi.tpm_log, tbl_size);
+ ret = -ENOMEM;
+ goto out;
+ }
if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR) {
pr_info("TPM Final Events table not present\n");
@@ -80,26 +86,26 @@ int __init efi_tpm_eventlog_init(void)
goto out;
}
- tbl_size = 0;
+ final_tbl_size = 0;
if (final_tbl->nr_events != 0) {
void *events = (void *)efi.tpm_final_log
+ sizeof(final_tbl->version)
+ sizeof(final_tbl->nr_events);
- tbl_size = tpm2_calc_event_log_size(events,
- final_tbl->nr_events,
- log_tbl->log);
+ final_tbl_size = tpm2_calc_event_log_size(events,
+ final_tbl->nr_events,
+ log_tbl->log);
}
- if (tbl_size < 0) {
+ if (final_tbl_size < 0) {
pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n");
ret = -EINVAL;
goto out_calc;
}
memblock_reserve(efi.tpm_final_log,
- tbl_size + sizeof(*final_tbl));
- efi_tpm_final_log_size = tbl_size;
+ final_tbl_size + sizeof(*final_tbl));
+ efi_tpm_final_log_size = final_tbl_size;
out_calc:
early_memunmap(final_tbl, sizeof(*final_tbl));
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c
index 208652a8087c..882db32e51be 100644
--- a/drivers/firmware/google/coreboot_table.c
+++ b/drivers/firmware/google/coreboot_table.c
@@ -220,7 +220,7 @@ MODULE_DEVICE_TABLE(of, coreboot_of_match);
static struct platform_driver coreboot_table_driver = {
.probe = coreboot_table_probe,
- .remove_new = coreboot_table_remove,
+ .remove = coreboot_table_remove,
.driver = {
.name = "coreboot_table",
.acpi_match_table = ACPI_PTR(cros_coreboot_acpi_match),
diff --git a/drivers/firmware/google/framebuffer-coreboot.c b/drivers/firmware/google/framebuffer-coreboot.c
index daadd71d8ddd..c68c9f56370f 100644
--- a/drivers/firmware/google/framebuffer-coreboot.c
+++ b/drivers/firmware/google/framebuffer-coreboot.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/platform_data/simplefb.h>
#include <linux/platform_device.h>
+#include <linux/sysfb.h>
#include "coreboot_table.h"
@@ -36,6 +37,19 @@ static int framebuffer_probe(struct coreboot_device *dev)
.format = NULL,
};
+ /*
+ * On coreboot systems, the advertised LB_TAG_FRAMEBUFFER entry
+ * in the coreboot table should only be used if the payload did
+ * not pass a framebuffer information to the Linux kernel.
+ *
+ * If the global screen_info data has been filled, the Generic
+ * System Framebuffers (sysfb) will already register a platform
+ * device and pass that screen_info as platform_data to a driver
+ * that can scan-out using the system provided framebuffer.
+ */
+ if (sysfb_handles_screen_info())
+ return -ENODEV;
+
if (!fb->physical_address)
return -ENODEV;
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index d304913314e4..24e666d5c3d1 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -918,7 +918,8 @@ static __init int gsmi_init(void)
gsmi_dev.pdev = platform_device_register_full(&gsmi_dev_info);
if (IS_ERR(gsmi_dev.pdev)) {
printk(KERN_ERR "gsmi: unable to register platform device\n");
- return PTR_ERR(gsmi_dev.pdev);
+ ret = PTR_ERR(gsmi_dev.pdev);
+ goto out_unregister;
}
/* SMI access needs to be serialized */
@@ -1056,10 +1057,11 @@ out_err:
gsmi_buf_free(gsmi_dev.name_buf);
kmem_cache_destroy(gsmi_dev.mem_pool);
platform_device_unregister(gsmi_dev.pdev);
- pr_info("gsmi: failed to load: %d\n", ret);
+out_unregister:
#ifdef CONFIG_PM
platform_driver_unregister(&gsmi_driver_info);
#endif
+ pr_info("gsmi: failed to load: %d\n", ret);
return ret;
}
diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
index 01c8ef14eaec..ed79e823157a 100644
--- a/drivers/firmware/imx/imx-dsp.c
+++ b/drivers/firmware/imx/imx-dsp.c
@@ -180,7 +180,7 @@ static struct platform_driver imx_dsp_driver = {
.name = "imx-dsp",
},
.probe = imx_dsp_probe,
- .remove_new = imx_dsp_remove,
+ .remove = imx_dsp_remove,
};
builtin_platform_driver(imx_dsp_driver);
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 8e59be3782cb..55b9cfad8a04 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -116,7 +116,7 @@ static void __meminit release_firmware_map_entry(struct kobject *kobj)
kfree(entry);
}
-static struct kobj_type __refdata memmap_ktype = {
+static const struct kobj_type memmap_ktype = {
.release = release_firmware_map_entry,
.sysfs_ops = &memmap_attr_ops,
.default_groups = def_groups,
diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c
index 9ca5ee58edbd..38a03698cec9 100644
--- a/drivers/firmware/microchip/mpfs-auto-update.c
+++ b/drivers/firmware/microchip/mpfs-auto-update.c
@@ -76,14 +76,11 @@
#define AUTO_UPDATE_INFO_SIZE SZ_1M
#define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)
-#define AUTO_UPDATE_TIMEOUT_MS 60000
-
struct mpfs_auto_update_priv {
struct mpfs_sys_controller *sys_controller;
struct device *dev;
struct mtd_info *flash;
struct fw_upload *fw_uploader;
- struct completion programming_complete;
size_t size_per_bitstream;
bool cancel_request;
};
@@ -156,19 +153,6 @@ static void mpfs_auto_update_cancel(struct fw_upload *fw_uploader)
static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_uploader)
{
- struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
- int ret;
-
- /*
- * There is no meaningful way to get the status of the programming while
- * it is in progress, so attempting anything other than waiting for it
- * to complete would be misplaced.
- */
- ret = wait_for_completion_timeout(&priv->programming_complete,
- msecs_to_jiffies(AUTO_UPDATE_TIMEOUT_MS));
- if (!ret)
- return FW_UPLOAD_ERR_TIMEOUT;
-
return FW_UPLOAD_ERR_NONE;
}
@@ -349,33 +333,23 @@ static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader,
u32 offset, u32 size, u32 *written)
{
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
- enum fw_upload_err err = FW_UPLOAD_ERR_NONE;
int ret;
- reinit_completion(&priv->programming_complete);
-
ret = mpfs_auto_update_write_bitstream(fw_uploader, data, offset, size, written);
- if (ret) {
- err = FW_UPLOAD_ERR_RW_ERROR;
- goto out;
- }
+ if (ret)
+ return FW_UPLOAD_ERR_RW_ERROR;
- if (priv->cancel_request) {
- err = FW_UPLOAD_ERR_CANCELED;
- goto out;
- }
+ if (priv->cancel_request)
+ return FW_UPLOAD_ERR_CANCELED;
if (mpfs_auto_update_is_bitstream_info(data, size))
- goto out;
+ return FW_UPLOAD_ERR_NONE;
ret = mpfs_auto_update_verify_image(fw_uploader);
if (ret)
- err = FW_UPLOAD_ERR_FW_INVALID;
+ return FW_UPLOAD_ERR_FW_INVALID;
-out:
- complete(&priv->programming_complete);
-
- return err;
+ return FW_UPLOAD_ERR_NONE;
}
static const struct fw_upload_ops mpfs_auto_update_ops = {
@@ -461,8 +435,6 @@ static int mpfs_auto_update_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret,
"The current bitstream does not support auto-update\n");
- init_completion(&priv->programming_complete);
-
fw_uploader = firmware_upload_register(THIS_MODULE, dev, "mpfs-auto-update",
&mpfs_auto_update_ops, priv);
if (IS_ERR(fw_uploader))
@@ -486,7 +458,7 @@ static struct platform_driver mpfs_auto_update_driver = {
.name = "mpfs-auto-update",
},
.probe = mpfs_auto_update_probe,
- .remove_new = mpfs_auto_update_remove,
+ .remove = mpfs_auto_update_remove,
};
module_platform_driver(mpfs_auto_update_driver);
diff --git a/drivers/firmware/mtk-adsp-ipc.c b/drivers/firmware/mtk-adsp-ipc.c
index a762302978de..2b79371c61c9 100644
--- a/drivers/firmware/mtk-adsp-ipc.c
+++ b/drivers/firmware/mtk-adsp-ipc.c
@@ -95,10 +95,9 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev)
adsp_chan->idx = i;
adsp_chan->ch = mbox_request_channel_byname(cl, adsp_mbox_ch_names[i]);
if (IS_ERR(adsp_chan->ch)) {
- ret = PTR_ERR(adsp_chan->ch);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to request mbox chan %s ret %d\n",
- adsp_mbox_ch_names[i], ret);
+ ret = dev_err_probe(dev, PTR_ERR(adsp_chan->ch),
+ "Failed to request mbox channel %s\n",
+ adsp_mbox_ch_names[i]);
for (j = 0; j < i; j++) {
adsp_chan = &adsp_ipc->chans[j];
@@ -133,7 +132,7 @@ static struct platform_driver mtk_adsp_ipc_driver = {
.name = "mtk-adsp-ipc",
},
.probe = mtk_adsp_ipc_probe,
- .remove_new = mtk_adsp_ipc_remove,
+ .remove = mtk_adsp_ipc_remove,
};
builtin_platform_driver(mtk_adsp_ipc_driver);
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index 2328ca58bba6..a1ebbe9b73b1 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -78,6 +78,7 @@ struct psci_0_1_function_ids get_psci_0_1_function_ids(void)
static u32 psci_cpu_suspend_feature;
static bool psci_system_reset2_supported;
+static bool psci_system_off2_hibernate_supported;
static inline bool psci_has_ext_power_state(void)
{
@@ -333,6 +334,36 @@ static void psci_sys_poweroff(void)
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
}
+#ifdef CONFIG_HIBERNATION
+static int psci_sys_hibernate(struct sys_off_data *data)
+{
+ /*
+ * If no hibernate type is specified SYSTEM_OFF2 defaults to selecting
+ * HIBERNATE_OFF.
+ *
+ * There are hypervisors in the wild that do not align with the spec and
+ * reject calls that explicitly provide a hibernate type. For
+ * compatibility with these nonstandard implementations, pass 0 as the
+ * type.
+ */
+ if (system_entering_hibernation())
+ invoke_psci_fn(PSCI_FN_NATIVE(1_3, SYSTEM_OFF2), 0, 0, 0);
+ return NOTIFY_DONE;
+}
+
+static int __init psci_hibernate_init(void)
+{
+ if (psci_system_off2_hibernate_supported) {
+ /* Higher priority than EFI shutdown, but only for hibernate */
+ register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_FIRMWARE + 2,
+ psci_sys_hibernate, NULL);
+ }
+ return 0;
+}
+subsys_initcall(psci_hibernate_init);
+#endif
+
static int psci_features(u32 psci_func_id)
{
return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
@@ -364,6 +395,7 @@ static const struct {
PSCI_ID_NATIVE(1_1, SYSTEM_RESET2),
PSCI_ID(1_1, MEM_PROTECT),
PSCI_ID_NATIVE(1_1, MEM_PROTECT_CHECK_RANGE),
+ PSCI_ID_NATIVE(1_3, SYSTEM_OFF2),
};
static int psci_debugfs_read(struct seq_file *s, void *data)
@@ -525,6 +557,18 @@ static void __init psci_init_system_reset2(void)
psci_system_reset2_supported = true;
}
+static void __init psci_init_system_off2(void)
+{
+ int ret;
+
+ ret = psci_features(PSCI_FN_NATIVE(1_3, SYSTEM_OFF2));
+ if (ret < 0)
+ return;
+
+ if (ret & PSCI_1_3_OFF_TYPE_HIBERNATE_OFF)
+ psci_system_off2_hibernate_supported = true;
+}
+
static void __init psci_init_system_suspend(void)
{
int ret;
@@ -655,6 +699,7 @@ static int __init psci_probe(void)
psci_init_cpu_suspend();
psci_init_system_suspend();
psci_init_system_reset2();
+ psci_init_system_off2();
kvm_init_hyp_services();
}
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 10986cb11ec0..72bf87ddcd96 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -112,6 +112,7 @@ enum qcom_scm_qseecom_tz_cmd_info {
};
#define QSEECOM_MAX_APP_NAME_SIZE 64
+#define SHMBRIDGE_RESULT_NOTSUPP 4
/* Each bit configures cold/warm boot address for one of the 4 CPUs */
static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
@@ -216,7 +217,7 @@ static DEFINE_SPINLOCK(scm_query_lock);
struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void)
{
- return __scm->mempool;
+ return __scm ? __scm->mempool : NULL;
}
static enum qcom_scm_convention __get_convention(void)
@@ -545,7 +546,7 @@ static void qcom_scm_set_download_mode(u32 dload_mode)
} else if (__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT,
QCOM_SCM_BOOT_SET_DLOAD_MODE)) {
ret = __qcom_scm_set_dload_mode(__scm->dev, !!dload_mode);
- } else {
+ } else if (dload_mode) {
dev_err(__scm->dev,
"No available mechanism for setting download mode\n");
}
@@ -903,6 +904,32 @@ int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
}
EXPORT_SYMBOL_GPL(qcom_scm_restore_sec_cfg);
+#define QCOM_SCM_CP_APERTURE_CONTEXT_MASK GENMASK(7, 0)
+
+bool qcom_scm_set_gpu_smmu_aperture_is_available(void)
+{
+ return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP,
+ QCOM_SCM_MP_CP_SMMU_APERTURE_ID);
+}
+EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_aperture_is_available);
+
+int qcom_scm_set_gpu_smmu_aperture(unsigned int context_bank)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_MP,
+ .cmd = QCOM_SCM_MP_CP_SMMU_APERTURE_ID,
+ .arginfo = QCOM_SCM_ARGS(4),
+ .args[0] = 0xffff0000 | FIELD_PREP(QCOM_SCM_CP_APERTURE_CONTEXT_MASK, context_bank),
+ .args[1] = 0xffffffff,
+ .args[2] = 0xffffffff,
+ .args[3] = 0xffffffff,
+ .owner = ARM_SMCCC_OWNER_SIP
+ };
+
+ return qcom_scm_call(__scm->dev, &desc, NULL);
+}
+EXPORT_SYMBOL_GPL(qcom_scm_set_gpu_smmu_aperture);
+
int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
{
struct qcom_scm_desc desc = {
@@ -1361,6 +1388,8 @@ EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh_available);
int qcom_scm_shm_bridge_enable(void)
{
+ int ret;
+
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_MP,
.cmd = QCOM_SCM_MP_SHM_BRIDGE_ENABLE,
@@ -1373,7 +1402,15 @@ int qcom_scm_shm_bridge_enable(void)
QCOM_SCM_MP_SHM_BRIDGE_ENABLE))
return -EOPNOTSUPP;
- return qcom_scm_call(__scm->dev, &desc, &res) ?: res.result[0];
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ if (ret)
+ return ret;
+
+ if (res.result[0] == SHMBRIDGE_RESULT_NOTSUPP)
+ return -EOPNOTSUPP;
+
+ return res.result[0];
}
EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_enable);
@@ -1731,12 +1768,16 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send);
+ any potential issues with this, only allow validated machines for now.
*/
static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
+ { .compatible = "dell,xps13-9345" },
{ .compatible = "lenovo,flex-5g" },
{ .compatible = "lenovo,thinkpad-t14s" },
{ .compatible = "lenovo,thinkpad-x13s", },
+ { .compatible = "lenovo,yoga-slim7x" },
+ { .compatible = "microsoft,arcata", },
{ .compatible = "microsoft,romulus13", },
{ .compatible = "microsoft,romulus15", },
{ .compatible = "qcom,sc8180x-primus" },
+ { .compatible = "qcom,x1e001de-devkit" },
{ .compatible = "qcom,x1e80100-crd" },
{ .compatible = "qcom,x1e80100-qcp" },
{ }
diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
index 685b8f59e7a6..e36b2f67607f 100644
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -116,6 +116,7 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
#define QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE 0x05
#define QCOM_SCM_MP_VIDEO_VAR 0x08
#define QCOM_SCM_MP_ASSIGN 0x16
+#define QCOM_SCM_MP_CP_SMMU_APERTURE_ID 0x1b
#define QCOM_SCM_MP_SHM_BRIDGE_ENABLE 0x1c
#define QCOM_SCM_MP_SHM_BRIDGE_DELETE 0x1d
#define QCOM_SCM_MP_SHM_BRIDGE_CREATE 0x1e
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 85c525745b31..d58da3e4500a 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -757,7 +757,7 @@ MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match);
static struct platform_driver fw_cfg_sysfs_driver = {
.probe = fw_cfg_sysfs_probe,
- .remove_new = fw_cfg_sysfs_remove,
+ .remove = fw_cfg_sysfs_remove,
.driver = {
.name = "fw_cfg",
.of_match_table = fw_cfg_sysfs_mmio_match,
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 18cc34987108..7ecde6921a0a 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -406,7 +406,7 @@ static struct platform_driver rpi_firmware_driver = {
},
.probe = rpi_firmware_probe,
.shutdown = rpi_firmware_shutdown,
- .remove_new = rpi_firmware_remove,
+ .remove = rpi_firmware_remove,
};
module_platform_driver(rpi_firmware_driver);
diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
index d670635914ec..a74600d9f2d7 100644
--- a/drivers/firmware/smccc/smccc.c
+++ b/drivers/firmware/smccc/smccc.c
@@ -16,7 +16,6 @@ static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
bool __ro_after_init smccc_trng_available = false;
-u64 __ro_after_init smccc_has_sve_hint = false;
s32 __ro_after_init smccc_soc_id_version = SMCCC_RET_NOT_SUPPORTED;
s32 __ro_after_init smccc_soc_id_revision = SMCCC_RET_NOT_SUPPORTED;
@@ -28,9 +27,6 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
smccc_conduit = conduit;
smccc_trng_available = smccc_probe_trng();
- if (IS_ENABLED(CONFIG_ARM64_SVE) &&
- smccc_version >= ARM_SMCCC_VERSION_1_3)
- smccc_has_sve_hint = true;
if ((smccc_version >= ARM_SMCCC_VERSION_1_2) &&
(smccc_conduit != SMCCC_CONDUIT_NONE)) {
diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-rsu.c
index e20cee9c2d32..1ea39a0a76c7 100644
--- a/drivers/firmware/stratix10-rsu.c
+++ b/drivers/firmware/stratix10-rsu.c
@@ -802,7 +802,7 @@ static void stratix10_rsu_remove(struct platform_device *pdev)
static struct platform_driver stratix10_rsu_driver = {
.probe = stratix10_rsu_probe,
- .remove_new = stratix10_rsu_remove,
+ .remove = stratix10_rsu_remove,
.driver = {
.name = "stratix10-rsu",
.dev_groups = rsu_groups,
diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
index 528f37417aea..c5c78b869561 100644
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -1271,7 +1271,7 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
static struct platform_driver stratix10_svc_driver = {
.probe = stratix10_svc_drv_probe,
- .remove_new = stratix10_svc_drv_remove,
+ .remove = stratix10_svc_drv_remove,
.driver = {
.name = "stratix10-svc",
.of_match_table = stratix10_svc_drv_match,
diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
index a3df782fa687..7c5c03f274b9 100644
--- a/drivers/firmware/sysfb.c
+++ b/drivers/firmware/sysfb.c
@@ -79,6 +79,25 @@ void sysfb_disable(struct device *dev)
}
EXPORT_SYMBOL_GPL(sysfb_disable);
+/**
+ * sysfb_handles_screen_info() - reports if sysfb handles the global screen_info
+ *
+ * Callers can use sysfb_handles_screen_info() to determine whether the Generic
+ * System Framebuffers (sysfb) can handle the global screen_info data structure
+ * or not. Drivers might need this information to know if they have to setup the
+ * system framebuffer, or if they have to delegate this action to sysfb instead.
+ *
+ * Returns:
+ * True if sysfb handles the global screen_info data structure.
+ */
+bool sysfb_handles_screen_info(void)
+{
+ const struct screen_info *si = &screen_info;
+
+ return !!screen_info_video_type(si);
+}
+EXPORT_SYMBOL_GPL(sysfb_handles_screen_info);
+
#if defined(CONFIG_PCI)
static bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
{
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index 2bee6e918f81..c3a1dc344961 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -3,7 +3,6 @@
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
*/
-#include <linux/cleanup.h>
#include <linux/clk/tegra.h>
#include <linux/genalloc.h>
#include <linux/mailbox_client.h>
@@ -35,24 +34,29 @@ channel_to_ops(struct tegra_bpmp_channel *channel)
struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
{
- struct device_node *np __free(device_node);
struct platform_device *pdev;
struct tegra_bpmp *bpmp;
+ struct device_node *np;
np = of_parse_phandle(dev->of_node, "nvidia,bpmp", 0);
if (!np)
return ERR_PTR(-ENOENT);
pdev = of_find_device_by_node(np);
- if (!pdev)
- return ERR_PTR(-ENODEV);
+ if (!pdev) {
+ bpmp = ERR_PTR(-ENODEV);
+ goto put;
+ }
bpmp = platform_get_drvdata(pdev);
if (!bpmp) {
+ bpmp = ERR_PTR(-EPROBE_DEFER);
put_device(&pdev->dev);
- return ERR_PTR(-EPROBE_DEFER);
+ goto put;
}
+put:
+ of_node_put(np);
return bpmp;
}
EXPORT_SYMBOL_GPL(tegra_bpmp_get);
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 160968301b1f..806a975fff22 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -2,13 +2,14 @@
/*
* Texas Instruments System Control Interface Protocol Driver
*
- * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com/
* Nishanth Menon
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/bitmap.h>
+#include <linux/cpu.h>
#include <linux/debugfs.h>
#include <linux/export.h>
#include <linux/io.h>
@@ -19,11 +20,14 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
#include <linux/property.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/soc/ti/ti-msgmgr.h>
#include <linux/soc/ti/ti_sci_protocol.h>
+#include <linux/suspend.h>
+#include <linux/sys_soc.h>
#include <linux/reboot.h>
#include "ti_sci.h"
@@ -98,6 +102,7 @@ struct ti_sci_desc {
* @minfo: Message info
* @node: list head
* @host_id: Host ID
+ * @fw_caps: FW/SoC low power capabilities
* @users: Number of users of this instance
*/
struct ti_sci_info {
@@ -114,6 +119,7 @@ struct ti_sci_info {
struct ti_sci_xfers_info minfo;
struct list_head node;
u8 host_id;
+ u64 fw_caps;
/* protected by ti_sci_list_mutex */
int users;
};
@@ -1651,6 +1657,364 @@ fail:
return ret;
}
+/**
+ * ti_sci_cmd_prepare_sleep() - Prepare system for system suspend
+ * @handle: pointer to TI SCI handle
+ * @mode: Device identifier
+ * @ctx_lo: Low part of address for context save
+ * @ctx_hi: High part of address for context save
+ * @debug_flags: Debug flags to pass to firmware
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
+ u32 ctx_lo, u32 ctx_hi, u32 debug_flags)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_msg_req_prepare_sleep *req;
+ struct ti_sci_msg_hdr *resp;
+ struct ti_sci_xfer *xfer;
+ struct device *dev;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+ dev = info->dev;
+
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PREPARE_SLEEP,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ sizeof(*req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ dev_err(dev, "Message alloc failed(%d)\n", ret);
+ return ret;
+ }
+
+ req = (struct ti_sci_msg_req_prepare_sleep *)xfer->xfer_buf;
+ req->mode = mode;
+ req->ctx_lo = ctx_lo;
+ req->ctx_hi = ctx_hi;
+ req->debug_flags = debug_flags;
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ dev_err(dev, "Mbox send fail %d\n", ret);
+ goto fail;
+ }
+
+ resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+ if (!ti_sci_is_response_ack(resp)) {
+ dev_err(dev, "Failed to prepare sleep\n");
+ ret = -ENODEV;
+ }
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_msg_cmd_query_fw_caps() - Get the FW/SoC capabilities
+ * @handle: Pointer to TI SCI handle
+ * @fw_caps: Each bit in fw_caps indicating one FW/SOC capability
+ *
+ * Check if the firmware supports any optional low power modes.
+ * Old revisions of TIFS (< 08.04) will NACK the request which results in
+ * -ENODEV being returned.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_msg_cmd_query_fw_caps(const struct ti_sci_handle *handle,
+ u64 *fw_caps)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ struct ti_sci_msg_resp_query_fw_caps *resp;
+ struct device *dev;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+ dev = info->dev;
+
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_FW_CAPS,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ sizeof(struct ti_sci_msg_hdr),
+ sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ dev_err(dev, "Message alloc failed(%d)\n", ret);
+ return ret;
+ }
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ dev_err(dev, "Mbox send fail %d\n", ret);
+ goto fail;
+ }
+
+ resp = (struct ti_sci_msg_resp_query_fw_caps *)xfer->xfer_buf;
+
+ if (!ti_sci_is_response_ack(resp)) {
+ dev_err(dev, "Failed to get capabilities\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ if (fw_caps)
+ *fw_caps = resp->fw_caps;
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_cmd_set_io_isolation() - Enable IO isolation in LPM
+ * @handle: Pointer to TI SCI handle
+ * @state: The desired state of the IO isolation
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_set_io_isolation(const struct ti_sci_handle *handle,
+ u8 state)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_msg_req_set_io_isolation *req;
+ struct ti_sci_msg_hdr *resp;
+ struct ti_sci_xfer *xfer;
+ struct device *dev;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+ dev = info->dev;
+
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_IO_ISOLATION,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ sizeof(*req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ dev_err(dev, "Message alloc failed(%d)\n", ret);
+ return ret;
+ }
+ req = (struct ti_sci_msg_req_set_io_isolation *)xfer->xfer_buf;
+ req->state = state;
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ dev_err(dev, "Mbox send fail %d\n", ret);
+ goto fail;
+ }
+
+ resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+ if (!ti_sci_is_response_ack(resp)) {
+ dev_err(dev, "Failed to set IO isolation\n");
+ ret = -ENODEV;
+ }
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_msg_cmd_lpm_wake_reason() - Get the wakeup source from LPM
+ * @handle: Pointer to TI SCI handle
+ * @source: The wakeup source that woke the SoC from LPM
+ * @timestamp: Timestamp of the wakeup event
+ * @pin: The pin that has triggered wake up
+ * @mode: The last entered low power mode
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_msg_cmd_lpm_wake_reason(const struct ti_sci_handle *handle,
+ u32 *source, u64 *timestamp, u8 *pin, u8 *mode)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ struct ti_sci_msg_resp_lpm_wake_reason *resp;
+ struct device *dev;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+ dev = info->dev;
+
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_WAKE_REASON,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ sizeof(struct ti_sci_msg_hdr),
+ sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ dev_err(dev, "Message alloc failed(%d)\n", ret);
+ return ret;
+ }
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ dev_err(dev, "Mbox send fail %d\n", ret);
+ goto fail;
+ }
+
+ resp = (struct ti_sci_msg_resp_lpm_wake_reason *)xfer->xfer_buf;
+
+ if (!ti_sci_is_response_ack(resp)) {
+ dev_err(dev, "Failed to get wake reason\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ if (source)
+ *source = resp->wake_source;
+ if (timestamp)
+ *timestamp = resp->wake_timestamp;
+ if (pin)
+ *pin = resp->wake_pin;
+ if (mode)
+ *mode = resp->mode;
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_cmd_set_device_constraint() - Set LPM constraint on behalf of a device
+ * @handle: pointer to TI SCI handle
+ * @id: Device identifier
+ * @state: The desired state of device constraint: set or clear
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_set_device_constraint(const struct ti_sci_handle *handle,
+ u32 id, u8 state)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_msg_req_lpm_set_device_constraint *req;
+ struct ti_sci_msg_hdr *resp;
+ struct ti_sci_xfer *xfer;
+ struct device *dev;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+ dev = info->dev;
+
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ sizeof(*req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ dev_err(dev, "Message alloc failed(%d)\n", ret);
+ return ret;
+ }
+ req = (struct ti_sci_msg_req_lpm_set_device_constraint *)xfer->xfer_buf;
+ req->id = id;
+ req->state = state;
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ dev_err(dev, "Mbox send fail %d\n", ret);
+ goto fail;
+ }
+
+ resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+ if (!ti_sci_is_response_ack(resp)) {
+ dev_err(dev, "Failed to set device constraint\n");
+ ret = -ENODEV;
+ }
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_cmd_set_latency_constraint() - Set LPM resume latency constraint
+ * @handle: pointer to TI SCI handle
+ * @latency: maximum acceptable latency (in ms) to wake up from LPM
+ * @state: The desired state of latency constraint: set or clear
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_set_latency_constraint(const struct ti_sci_handle *handle,
+ u16 latency, u8 state)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_msg_req_lpm_set_latency_constraint *req;
+ struct ti_sci_msg_hdr *resp;
+ struct ti_sci_xfer *xfer;
+ struct device *dev;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+ dev = info->dev;
+
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ sizeof(*req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ dev_err(dev, "Message alloc failed(%d)\n", ret);
+ return ret;
+ }
+ req = (struct ti_sci_msg_req_lpm_set_latency_constraint *)xfer->xfer_buf;
+ req->latency = latency;
+ req->state = state;
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ dev_err(dev, "Mbox send fail %d\n", ret);
+ goto fail;
+ }
+
+ resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+ if (!ti_sci_is_response_ack(resp)) {
+ dev_err(dev, "Failed to set device constraint\n");
+ ret = -ENODEV;
+ }
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
{
struct ti_sci_info *info;
@@ -2793,6 +3157,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
struct ti_sci_core_ops *core_ops = &ops->core_ops;
struct ti_sci_dev_ops *dops = &ops->dev_ops;
struct ti_sci_clk_ops *cops = &ops->clk_ops;
+ struct ti_sci_pm_ops *pmops = &ops->pm_ops;
struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops;
struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
@@ -2832,6 +3197,13 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
cops->set_freq = ti_sci_cmd_clk_set_freq;
cops->get_freq = ti_sci_cmd_clk_get_freq;
+ if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) {
+ pr_debug("detected DM managed LPM in fw_caps\n");
+ pmops->lpm_wake_reason = ti_sci_msg_cmd_lpm_wake_reason;
+ pmops->set_device_constraint = ti_sci_cmd_set_device_constraint;
+ pmops->set_latency_constraint = ti_sci_cmd_set_latency_constraint;
+ }
+
rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
rm_core_ops->get_range_from_shost =
ti_sci_cmd_get_resource_range_from_shost;
@@ -3262,6 +3634,111 @@ static int tisci_reboot_handler(struct sys_off_data *data)
return NOTIFY_BAD;
}
+static int ti_sci_prepare_system_suspend(struct ti_sci_info *info)
+{
+ /*
+ * Map and validate the target Linux suspend state to TISCI LPM.
+ * Default is to let Device Manager select the low power mode.
+ */
+ switch (pm_suspend_target_state) {
+ case PM_SUSPEND_MEM:
+ if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) {
+ /*
+ * For the DM_MANAGED mode the context is reserved for
+ * internal use and can be 0
+ */
+ return ti_sci_cmd_prepare_sleep(&info->handle,
+ TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED,
+ 0, 0, 0);
+ } else {
+ /* DM Managed is not supported by the firmware. */
+ dev_err(info->dev, "Suspend to memory is not supported by the firmware\n");
+ return -EOPNOTSUPP;
+ }
+ break;
+ default:
+ /*
+ * Do not fail if we don't have action to take for a
+ * specific suspend mode.
+ */
+ return 0;
+ }
+}
+
+static int __maybe_unused ti_sci_suspend(struct device *dev)
+{
+ struct ti_sci_info *info = dev_get_drvdata(dev);
+ struct device *cpu_dev, *cpu_dev_max = NULL;
+ s32 val, cpu_lat = 0;
+ int i, ret;
+
+ if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) {
+ for_each_possible_cpu(i) {
+ cpu_dev = get_cpu_device(i);
+ val = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_RESUME_LATENCY);
+ if (val != PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) {
+ cpu_lat = max(cpu_lat, val);
+ cpu_dev_max = cpu_dev;
+ }
+ }
+ if (cpu_dev_max) {
+ dev_dbg(cpu_dev_max, "%s: sending max CPU latency=%u\n", __func__, cpu_lat);
+ ret = ti_sci_cmd_set_latency_constraint(&info->handle,
+ cpu_lat, TISCI_MSG_CONSTRAINT_SET);
+ if (ret)
+ return ret;
+ }
+ }
+
+ ret = ti_sci_prepare_system_suspend(info);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int __maybe_unused ti_sci_suspend_noirq(struct device *dev)
+{
+ struct ti_sci_info *info = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_ENABLE);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int __maybe_unused ti_sci_resume_noirq(struct device *dev)
+{
+ struct ti_sci_info *info = dev_get_drvdata(dev);
+ int ret = 0;
+ u32 source;
+ u64 time;
+ u8 pin;
+ u8 mode;
+
+ ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode);
+ /* Do not fail to resume on error as the wake reason is not critical */
+ if (!ret)
+ dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n",
+ source, pin, mode);
+
+ return 0;
+}
+
+static const struct dev_pm_ops ti_sci_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+ .suspend = ti_sci_suspend,
+ .suspend_noirq = ti_sci_suspend_noirq,
+ .resume_noirq = ti_sci_resume_noirq,
+#endif
+};
+
/* Description for K2G */
static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
.default_host_id = 2,
@@ -3390,6 +3867,13 @@ static int ti_sci_probe(struct platform_device *pdev)
goto out;
}
+ ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps);
+ dev_dbg(dev, "Detected firmware capabilities: %s%s%s\n",
+ info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "",
+ info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "",
+ info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : ""
+ );
+
ti_sci_setup_ops(info);
ret = devm_register_restart_handler(dev, tisci_reboot_handler, info);
@@ -3421,8 +3905,9 @@ static struct platform_driver ti_sci_driver = {
.probe = ti_sci_probe,
.driver = {
.name = "ti-sci",
- .of_match_table = of_match_ptr(ti_sci_of_match),
+ .of_match_table = ti_sci_of_match,
.suppress_bind_attrs = true,
+ .pm = &ti_sci_pm_ops,
},
};
module_platform_driver(ti_sci_driver);
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 5846c60220f5..053387d7baa0 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -6,7 +6,7 @@
* The system works in a message response protocol
* See: https://software-dl.ti.com/tisci/esd/latest/index.html for details
*
- * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com/
*/
#ifndef __TI_SCI_H
@@ -19,6 +19,7 @@
#define TI_SCI_MSG_WAKE_REASON 0x0003
#define TI_SCI_MSG_GOODBYE 0x0004
#define TI_SCI_MSG_SYS_RESET 0x0005
+#define TI_SCI_MSG_QUERY_FW_CAPS 0x0022
/* Device requests */
#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200
@@ -35,6 +36,13 @@
#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
+/* Low Power Mode Requests */
+#define TI_SCI_MSG_PREPARE_SLEEP 0x0300
+#define TI_SCI_MSG_LPM_WAKE_REASON 0x0306
+#define TI_SCI_MSG_SET_IO_ISOLATION 0x0307
+#define TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT 0x0309
+#define TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT 0x030A
+
/* Resource Management Requests */
#define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
@@ -133,6 +141,27 @@ struct ti_sci_msg_req_reboot {
} __packed;
/**
+ * struct ti_sci_msg_resp_query_fw_caps - Response for query firmware caps
+ * @hdr: Generic header
+ * @fw_caps: Each bit in fw_caps indicating one FW/SOC capability
+ * MSG_FLAG_CAPS_GENERIC: Generic capability (LPM not supported)
+ * MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM
+ * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM
+ *
+ * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS
+ * providing currently available SOC/firmware capabilities. SoC that don't
+ * support low power modes return only MSG_FLAG_CAPS_GENERIC capability.
+ */
+struct ti_sci_msg_resp_query_fw_caps {
+ struct ti_sci_msg_hdr hdr;
+#define MSG_FLAG_CAPS_GENERIC TI_SCI_MSG_FLAG(0)
+#define MSG_FLAG_CAPS_LPM_PARTIAL_IO TI_SCI_MSG_FLAG(4)
+#define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5)
+#define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1)
+ u64 fw_caps;
+} __packed;
+
+/**
* struct ti_sci_msg_req_set_device_state - Set the desired state of the device
* @hdr: Generic header
* @id: Indicates which device to modify
@@ -545,6 +574,118 @@ struct ti_sci_msg_resp_get_clock_freq {
u64 freq_hz;
} __packed;
+/**
+ * struct tisci_msg_req_prepare_sleep - Request for TISCI_MSG_PREPARE_SLEEP.
+ *
+ * @hdr TISCI header to provide ACK/NAK flags to the host.
+ * @mode Low power mode to enter.
+ * @ctx_lo Low 32-bits of physical pointer to address to use for context save.
+ * @ctx_hi High 32-bits of physical pointer to address to use for context save.
+ * @debug_flags Flags that can be set to halt the sequence during suspend or
+ * resume to allow JTAG connection and debug.
+ *
+ * This message is used as the first step of entering a low power mode. It
+ * allows configurable information, including which state to enter to be
+ * easily shared from the application, as this is a non-secure message and
+ * therefore can be sent by anyone.
+ */
+struct ti_sci_msg_req_prepare_sleep {
+ struct ti_sci_msg_hdr hdr;
+
+#define TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED 0xfd
+ u8 mode;
+ u32 ctx_lo;
+ u32 ctx_hi;
+ u32 debug_flags;
+} __packed;
+
+/**
+ * struct tisci_msg_set_io_isolation_req - Request for TI_SCI_MSG_SET_IO_ISOLATION.
+ *
+ * @hdr: Generic header
+ * @state: The deseared state of the IO isolation.
+ *
+ * This message is used to enable/disable IO isolation for low power modes.
+ * Response is generic ACK / NACK message.
+ */
+struct ti_sci_msg_req_set_io_isolation {
+ struct ti_sci_msg_hdr hdr;
+ u8 state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_lpm_wake_reason - Response for TI_SCI_MSG_LPM_WAKE_REASON.
+ *
+ * @hdr: Generic header.
+ * @wake_source: The wake up source that woke soc from LPM.
+ * @wake_timestamp: Timestamp at which soc woke.
+ * @wake_pin: The pin that has triggered wake up.
+ * @mode: The last entered low power mode.
+ * @rsvd: Reserved for future use.
+ *
+ * Response to a generic message with message type TI_SCI_MSG_LPM_WAKE_REASON,
+ * used to query the wake up source, pin and entered low power mode.
+ */
+struct ti_sci_msg_resp_lpm_wake_reason {
+ struct ti_sci_msg_hdr hdr;
+ u32 wake_source;
+ u64 wake_timestamp;
+ u8 wake_pin;
+ u8 mode;
+ u32 rsvd[2];
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_lpm_set_device_constraint - Request for
+ * TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT.
+ *
+ * @hdr: TISCI header to provide ACK/NAK flags to the host.
+ * @id: Device ID of device whose constraint has to be modified.
+ * @state: The desired state of device constraint: set or clear.
+ * @rsvd: Reserved for future use.
+ *
+ * This message is used by host to set constraint on the device. This can be
+ * sent anytime after boot before prepare sleep message. Any device can set a
+ * constraint on the low power mode that the SoC can enter. It allows
+ * configurable information to be easily shared from the application, as this
+ * is a non-secure message and therefore can be sent by anyone. By setting a
+ * constraint, the device ensures that it will not be powered off or reset in
+ * the selected mode. Note: Access Restriction: Exclusivity flag of Device will
+ * be honored. If some other host already has constraint on this device ID,
+ * NACK will be returned.
+ */
+struct ti_sci_msg_req_lpm_set_device_constraint {
+ struct ti_sci_msg_hdr hdr;
+ u32 id;
+ u8 state;
+ u32 rsvd[2];
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_lpm_set_latency_constraint - Request for
+ * TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT.
+ *
+ * @hdr: TISCI header to provide ACK/NAK flags to the host.
+ * @wkup_latency: The maximum acceptable latency to wake up from low power mode
+ * in milliseconds. The deeper the state, the higher the latency.
+ * @state: The desired state of wakeup latency constraint: set or clear.
+ * @rsvd: Reserved for future use.
+ *
+ * This message is used by host to set wakeup latency from low power mode. This can
+ * be sent anytime after boot before prepare sleep message, and can be sent after
+ * current low power mode is exited. Any device can set a constraint on the low power
+ * mode that the SoC can enter. It allows configurable information to be easily shared
+ * from the application, as this is a non-secure message and therefore can be sent by
+ * anyone. By setting a wakeup latency constraint, the host ensures that the resume time
+ * from selected low power mode will be less than the constraint value.
+ */
+struct ti_sci_msg_req_lpm_set_latency_constraint {
+ struct ti_sci_msg_hdr hdr;
+ u16 latency;
+ u8 state;
+ u32 rsvd;
+} __packed;
+
#define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
/**
diff --git a/drivers/firmware/turris-mox-rwtm.c b/drivers/firmware/turris-mox-rwtm.c
index f3bc0d427825..47fe6261f5a3 100644
--- a/drivers/firmware/turris-mox-rwtm.c
+++ b/drivers/firmware/turris-mox-rwtm.c
@@ -61,6 +61,27 @@ enum mbox_cmd {
MBOX_CMD_OTP_WRITE = 8,
};
+/**
+ * struct mox_rwtm - driver private data structure
+ * @mbox_client: rWTM mailbox client
+ * @mbox: rWTM mailbox channel
+ * @hwrng: RNG driver structure
+ * @reply: last mailbox reply, filled in receive callback
+ * @buf: DMA buffer
+ * @buf_phys: physical address of the DMA buffer
+ * @busy: mutex to protect mailbox command execution
+ * @cmd_done: command done completion
+ * @has_board_info: whether board information is present
+ * @serial_number: serial number of the device
+ * @board_version: board version / revision of the device
+ * @ram_size: RAM size of the device
+ * @mac_address1: first MAC address of the device
+ * @mac_address2: second MAC address of the device
+ * @has_pubkey: whether board ECDSA public key is present
+ * @pubkey: board ECDSA public key
+ * @last_sig: last ECDSA signature generated with board ECDSA private key
+ * @last_sig_done: whether the last ECDSA signing is complete
+ */
struct mox_rwtm {
struct mbox_client mbox_client;
struct mbox_chan *mbox;
@@ -74,13 +95,11 @@ struct mox_rwtm {
struct mutex busy;
struct completion cmd_done;
- /* board information */
bool has_board_info;
u64 serial_number;
int board_version, ram_size;
u8 mac_address1[ETH_ALEN], mac_address2[ETH_ALEN];
- /* public key burned in eFuse */
bool has_pubkey;
u8 pubkey[135];
diff --git a/drivers/firmware/xilinx/zynqmp-debug.c b/drivers/firmware/xilinx/zynqmp-debug.c
index 8528850af889..22853ae0efdf 100644
--- a/drivers/firmware/xilinx/zynqmp-debug.c
+++ b/drivers/firmware/xilinx/zynqmp-debug.c
@@ -31,13 +31,51 @@ static char debugfs_buf[PAGE_SIZE];
#define PM_API(id) {id, #id, strlen(#id)}
static struct pm_api_info pm_api_list[] = {
+ PM_API(PM_FORCE_POWERDOWN),
+ PM_API(PM_REQUEST_WAKEUP),
+ PM_API(PM_SYSTEM_SHUTDOWN),
+ PM_API(PM_REQUEST_NODE),
+ PM_API(PM_RELEASE_NODE),
+ PM_API(PM_SET_REQUIREMENT),
PM_API(PM_GET_API_VERSION),
+ PM_API(PM_REGISTER_NOTIFIER),
+ PM_API(PM_RESET_ASSERT),
+ PM_API(PM_RESET_GET_STATUS),
+ PM_API(PM_GET_CHIPID),
+ PM_API(PM_PINCTRL_SET_FUNCTION),
+ PM_API(PM_PINCTRL_CONFIG_PARAM_GET),
+ PM_API(PM_PINCTRL_CONFIG_PARAM_SET),
+ PM_API(PM_IOCTL),
+ PM_API(PM_CLOCK_ENABLE),
+ PM_API(PM_CLOCK_DISABLE),
+ PM_API(PM_CLOCK_GETSTATE),
+ PM_API(PM_CLOCK_SETDIVIDER),
+ PM_API(PM_CLOCK_GETDIVIDER),
+ PM_API(PM_CLOCK_SETPARENT),
+ PM_API(PM_CLOCK_GETPARENT),
PM_API(PM_QUERY_DATA),
};
static struct dentry *firmware_debugfs_root;
/**
+ * zynqmp_pm_ioctl - PM IOCTL for device control and configs
+ * @node: Node ID of the device
+ * @ioctl: ID of the requested IOCTL
+ * @arg1: Argument 1 of requested IOCTL call
+ * @arg2: Argument 2 of requested IOCTL call
+ * @arg3: Argument 3 of requested IOCTL call
+ * @out: Returned output value
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_ioctl(const u32 node, const u32 ioctl, const u32 arg1,
+ const u32 arg2, const u32 arg3, u32 *out)
+{
+ return zynqmp_pm_invoke_fn(PM_IOCTL, out, 5, node, ioctl, arg1, arg2, arg3);
+}
+
+/**
* zynqmp_pm_argument_value() - Extract argument value from a PM-API request
* @arg: Entered PM-API argument in string format
*
@@ -95,6 +133,128 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
sprintf(debugfs_buf, "PM-API Version = %d.%d\n",
pm_api_version >> 16, pm_api_version & 0xffff);
break;
+ case PM_FORCE_POWERDOWN:
+ ret = zynqmp_pm_force_pwrdwn(pm_api_arg[0],
+ pm_api_arg[1] ? pm_api_arg[1] :
+ ZYNQMP_PM_REQUEST_ACK_NO);
+ break;
+ case PM_REQUEST_WAKEUP:
+ ret = zynqmp_pm_request_wake(pm_api_arg[0],
+ pm_api_arg[1], pm_api_arg[2],
+ pm_api_arg[3] ? pm_api_arg[3] :
+ ZYNQMP_PM_REQUEST_ACK_NO);
+ break;
+ case PM_SYSTEM_SHUTDOWN:
+ ret = zynqmp_pm_system_shutdown(pm_api_arg[0], pm_api_arg[1]);
+ break;
+ case PM_REQUEST_NODE:
+ ret = zynqmp_pm_request_node(pm_api_arg[0],
+ pm_api_arg[1] ? pm_api_arg[1] :
+ ZYNQMP_PM_CAPABILITY_ACCESS,
+ pm_api_arg[2] ? pm_api_arg[2] : 0,
+ pm_api_arg[3] ? pm_api_arg[3] :
+ ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+ break;
+ case PM_RELEASE_NODE:
+ ret = zynqmp_pm_release_node(pm_api_arg[0]);
+ break;
+ case PM_SET_REQUIREMENT:
+ ret = zynqmp_pm_set_requirement(pm_api_arg[0],
+ pm_api_arg[1] ? pm_api_arg[1] :
+ ZYNQMP_PM_CAPABILITY_CONTEXT,
+ pm_api_arg[2] ?
+ pm_api_arg[2] : 0,
+ pm_api_arg[3] ? pm_api_arg[3] :
+ ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+ break;
+ case PM_REGISTER_NOTIFIER:
+ ret = zynqmp_pm_register_notifier(pm_api_arg[0],
+ pm_api_arg[1] ?
+ pm_api_arg[1] : 0,
+ pm_api_arg[2] ?
+ pm_api_arg[2] : 0,
+ pm_api_arg[3] ?
+ pm_api_arg[3] : 0);
+ break;
+ case PM_RESET_ASSERT:
+ ret = zynqmp_pm_reset_assert(pm_api_arg[0], pm_api_arg[1]);
+ break;
+ case PM_RESET_GET_STATUS:
+ ret = zynqmp_pm_reset_get_status(pm_api_arg[0], &pm_api_ret[0]);
+ if (!ret)
+ sprintf(debugfs_buf, "Reset status: %u\n",
+ pm_api_ret[0]);
+ break;
+ case PM_GET_CHIPID:
+ ret = zynqmp_pm_get_chipid(&pm_api_ret[0], &pm_api_ret[1]);
+ if (!ret)
+ sprintf(debugfs_buf, "Idcode: %#x, Version:%#x\n",
+ pm_api_ret[0], pm_api_ret[1]);
+ break;
+ case PM_PINCTRL_SET_FUNCTION:
+ ret = zynqmp_pm_pinctrl_set_function(pm_api_arg[0],
+ pm_api_arg[1]);
+ break;
+ case PM_PINCTRL_CONFIG_PARAM_GET:
+ ret = zynqmp_pm_pinctrl_get_config(pm_api_arg[0], pm_api_arg[1],
+ &pm_api_ret[0]);
+ if (!ret)
+ sprintf(debugfs_buf,
+ "Pin: %llu, Param: %llu, Value: %u\n",
+ pm_api_arg[0], pm_api_arg[1],
+ pm_api_ret[0]);
+ break;
+ case PM_PINCTRL_CONFIG_PARAM_SET:
+ ret = zynqmp_pm_pinctrl_set_config(pm_api_arg[0],
+ pm_api_arg[1],
+ pm_api_arg[2]);
+ break;
+ case PM_IOCTL:
+ ret = zynqmp_pm_ioctl(pm_api_arg[0], pm_api_arg[1],
+ pm_api_arg[2], pm_api_arg[3],
+ pm_api_arg[4], &pm_api_ret[0]);
+ if (!ret && (pm_api_arg[1] == IOCTL_GET_RPU_OPER_MODE ||
+ pm_api_arg[1] == IOCTL_GET_PLL_FRAC_MODE ||
+ pm_api_arg[1] == IOCTL_GET_PLL_FRAC_DATA ||
+ pm_api_arg[1] == IOCTL_READ_GGS ||
+ pm_api_arg[1] == IOCTL_READ_PGGS ||
+ pm_api_arg[1] == IOCTL_READ_REG))
+ sprintf(debugfs_buf, "IOCTL return value: %u\n",
+ pm_api_ret[1]);
+ if (!ret && pm_api_arg[1] == IOCTL_GET_QOS)
+ sprintf(debugfs_buf, "Default QoS: %u\nCurrent QoS: %u\n",
+ pm_api_ret[1], pm_api_ret[2]);
+ break;
+ case PM_CLOCK_ENABLE:
+ ret = zynqmp_pm_clock_enable(pm_api_arg[0]);
+ break;
+ case PM_CLOCK_DISABLE:
+ ret = zynqmp_pm_clock_disable(pm_api_arg[0]);
+ break;
+ case PM_CLOCK_GETSTATE:
+ ret = zynqmp_pm_clock_getstate(pm_api_arg[0], &pm_api_ret[0]);
+ if (!ret)
+ sprintf(debugfs_buf, "Clock state: %u\n",
+ pm_api_ret[0]);
+ break;
+ case PM_CLOCK_SETDIVIDER:
+ ret = zynqmp_pm_clock_setdivider(pm_api_arg[0], pm_api_arg[1]);
+ break;
+ case PM_CLOCK_GETDIVIDER:
+ ret = zynqmp_pm_clock_getdivider(pm_api_arg[0], &pm_api_ret[0]);
+ if (!ret)
+ sprintf(debugfs_buf, "Divider Value: %d\n",
+ pm_api_ret[0]);
+ break;
+ case PM_CLOCK_SETPARENT:
+ ret = zynqmp_pm_clock_setparent(pm_api_arg[0], pm_api_arg[1]);
+ break;
+ case PM_CLOCK_GETPARENT:
+ ret = zynqmp_pm_clock_getparent(pm_api_arg[0], &pm_api_ret[0]);
+ if (!ret)
+ sprintf(debugfs_buf,
+ "Clock parent Index: %u\n", pm_api_ret[0]);
+ break;
case PM_QUERY_DATA:
qdata.qid = pm_api_arg[0];
qdata.arg1 = pm_api_arg[1];
@@ -150,7 +310,7 @@ static ssize_t zynqmp_pm_debugfs_api_write(struct file *file,
char *kern_buff, *tmp_buff;
char *pm_api_req;
u32 pm_id = 0;
- u64 pm_api_arg[4] = {0, 0, 0, 0};
+ u64 pm_api_arg[5] = {0, 0, 0, 0, 0};
/* Return values from PM APIs calls */
u32 pm_api_ret[4] = {0, 0, 0, 0};
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index add8acf66a9c..720fa8b5d8e9 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -3,7 +3,7 @@
* Xilinx Zynq MPSoC Firmware layer
*
* Copyright (C) 2014-2022 Xilinx, Inc.
- * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
*
* Michal Simek <michal.simek@amd.com>
* Davorin Mista <davorin.mista@aggios.com>
@@ -46,6 +46,7 @@ static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
static u32 query_features[FEATURE_PAYLOAD_SIZE];
+static u32 sip_svc_version;
static struct platform_device *em_dev;
/**
@@ -151,6 +152,9 @@ static noinline int do_fw_call_smc(u32 *ret_payload, u32 num_args, ...)
ret_payload[1] = upper_32_bits(res.a0);
ret_payload[2] = lower_32_bits(res.a1);
ret_payload[3] = upper_32_bits(res.a1);
+ ret_payload[4] = lower_32_bits(res.a2);
+ ret_payload[5] = upper_32_bits(res.a2);
+ ret_payload[6] = lower_32_bits(res.a3);
}
return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
@@ -191,6 +195,9 @@ static noinline int do_fw_call_hvc(u32 *ret_payload, u32 num_args, ...)
ret_payload[1] = upper_32_bits(res.a0);
ret_payload[2] = lower_32_bits(res.a1);
ret_payload[3] = upper_32_bits(res.a1);
+ ret_payload[4] = lower_32_bits(res.a2);
+ ret_payload[5] = upper_32_bits(res.a2);
+ ret_payload[6] = lower_32_bits(res.a3);
}
return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
@@ -218,11 +225,14 @@ static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
* Feature check of TF-A APIs is done in the TF-A layer and it expects for
* MODULE_ID_MASK bits of SMC's arg[0] to be the same as PM_MODULE_ID.
*/
- if (module_id == TF_A_MODULE_ID)
+ if (module_id == TF_A_MODULE_ID) {
module_id = PM_MODULE_ID;
+ smc_arg[1] = api_id;
+ } else {
+ smc_arg[1] = (api_id & API_ID_MASK);
+ }
smc_arg[0] = PM_SIP_SVC | FIELD_PREP(MODULE_ID_MASK, module_id) | feature_check_api_id;
- smc_arg[1] = (api_id & API_ID_MASK);
ret = do_fw_call(ret_payload, 2, smc_arg[0], smc_arg[1]);
if (ret)
@@ -332,6 +342,70 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
/**
+ * zynqmp_pm_invoke_fw_fn() - Invoke the system-level platform management layer
+ * caller function depending on the configuration
+ * @pm_api_id: Requested PM-API call
+ * @ret_payload: Returned value array
+ * @num_args: Number of arguments to requested PM-API call
+ *
+ * Invoke platform management function for SMC or HVC call, depending on
+ * configuration.
+ * Following SMC Calling Convention (SMCCC) for SMC64:
+ * Pm Function Identifier,
+ * PM_SIP_SVC + PASS_THROUGH_FW_CMD_ID =
+ * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
+ * ((SMC_64) << FUNCID_CC_SHIFT)
+ * ((SIP_START) << FUNCID_OEN_SHIFT)
+ * (PASS_THROUGH_FW_CMD_ID))
+ *
+ * PM_SIP_SVC - Registered ZynqMP SIP Service Call.
+ * PASS_THROUGH_FW_CMD_ID - Fixed SiP SVC call ID for FW specific calls.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
+{
+ /*
+ * Added SIP service call Function Identifier
+ * Make sure to stay in x0 register
+ */
+ u64 smc_arg[SMC_ARG_CNT_64];
+ int ret, i;
+ va_list arg_list;
+ u32 args[SMC_ARG_CNT_32] = {0};
+ u32 module_id;
+
+ if (num_args > SMC_ARG_CNT_32)
+ return -EINVAL;
+
+ va_start(arg_list, num_args);
+
+ /* Check if feature is supported or not */
+ ret = zynqmp_pm_feature(pm_api_id);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < num_args; i++)
+ args[i] = va_arg(arg_list, u32);
+
+ va_end(arg_list);
+
+ module_id = FIELD_GET(PLM_MODULE_ID_MASK, pm_api_id);
+
+ if (module_id == 0)
+ module_id = XPM_MODULE_ID;
+
+ smc_arg[0] = PM_SIP_SVC | PASS_THROUGH_FW_CMD_ID;
+ smc_arg[1] = ((u64)args[0] << 32U) | FIELD_PREP(PLM_MODULE_ID_MASK, module_id) |
+ (pm_api_id & API_ID_MASK);
+ for (i = 1; i < (SMC_ARG_CNT_64 - 1); i++)
+ smc_arg[i + 1] = ((u64)args[(i * 2)] << 32U) | args[(i * 2) - 1];
+
+ return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
+ smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
+}
+
+/**
* zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
* caller function depending on the configuration
* @pm_api_id: Requested PM-API call
@@ -489,6 +563,35 @@ int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
EXPORT_SYMBOL_GPL(zynqmp_pm_get_family_info);
/**
+ * zynqmp_pm_get_sip_svc_version() - Get SiP service call version
+ * @version: Returned version value
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_get_sip_svc_version(u32 *version)
+{
+ struct arm_smccc_res res;
+ u64 args[SMC_ARG_CNT_64] = {0};
+
+ if (!version)
+ return -EINVAL;
+
+ /* Check if SiP SVC version already verified */
+ if (sip_svc_version > 0) {
+ *version = sip_svc_version;
+ return 0;
+ }
+
+ args[0] = GET_SIP_SVC_VERSION;
+
+ arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
+
+ *version = ((lower_32_bits(res.a0) << 16U) | lower_32_bits(res.a1));
+
+ return zynqmp_pm_ret_code(XST_PM_SUCCESS);
+}
+
+/**
* zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
* @version: Returned version value
*
@@ -552,10 +655,34 @@ static int get_set_conduit_method(struct device_node *np)
*/
int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
{
- int ret;
+ int ret, i = 0;
+ u32 ret_payload[PAYLOAD_ARG_CNT] = {0};
+
+ if (sip_svc_version >= SIP_SVC_PASSTHROUGH_VERSION) {
+ ret = zynqmp_pm_invoke_fw_fn(PM_QUERY_DATA, ret_payload, 4,
+ qdata.qid, qdata.arg1,
+ qdata.arg2, qdata.arg3);
+ /* To support backward compatibility */
+ if (!ret && !ret_payload[0]) {
+ /*
+ * TF-A passes return status on 0th index but
+ * api to get clock name reads data from 0th
+ * index so pass data at 0th index instead of
+ * return status
+ */
+ if (qdata.qid == PM_QID_CLOCK_GET_NAME ||
+ qdata.qid == PM_QID_PINCTRL_GET_FUNCTION_NAME)
+ i = 1;
+
+ for (; i < PAYLOAD_ARG_CNT; i++, out++)
+ *out = ret_payload[i];
+
+ return ret;
+ }
+ }
- ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid, qdata.arg1, qdata.arg2,
- qdata.arg3);
+ ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid,
+ qdata.arg1, qdata.arg2, qdata.arg3);
/*
* For clock name query, all bytes in SMC response are clock name
@@ -920,7 +1047,7 @@ int zynqmp_pm_set_boot_health_status(u32 value)
*
* Return: Returns status, either success or error+reason
*/
-int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
+int zynqmp_pm_reset_assert(const u32 reset,
const enum zynqmp_pm_reset_action assert_flag)
{
return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, NULL, 2, reset, assert_flag);
@@ -934,7 +1061,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
*
* Return: Returns status, either success or error+reason
*/
-int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
+int zynqmp_pm_reset_get_status(const u32 reset, u32 *status)
{
u32 ret_payload[PAYLOAD_ARG_CNT];
int ret;
@@ -1118,8 +1245,11 @@ int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
if (pm_family_code == ZYNQMP_FAMILY_CODE &&
param == PM_PINCTRL_CONFIG_TRI_STATE) {
ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
- if (ret < PM_PINCTRL_PARAM_SET_VERSION)
+ if (ret < PM_PINCTRL_PARAM_SET_VERSION) {
+ pr_warn("The requested pinctrl feature is not supported in the current firmware.\n"
+ "Expected firmware version is 2023.1 and above for this feature to work.\r\n");
return -EOPNOTSUPP;
+ }
}
return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, NULL, 3, pin, param, value);
@@ -1887,6 +2017,11 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
if (ret)
return ret;
+ /* Get SiP SVC version number */
+ ret = zynqmp_pm_get_sip_svc_version(&sip_svc_version);
+ if (ret)
+ return ret;
+
ret = do_feature_check_call(PM_FEATURE_CHECK);
if (ret >= 0 && ((ret & FIRMWARE_VERSION_MASK) >= PM_API_VERSION_1))
feature_check_enabled = true;
@@ -1983,6 +2118,6 @@ static struct platform_driver zynqmp_firmware_driver = {
.dev_groups = zynqmp_firmware_groups,
},
.probe = zynqmp_firmware_probe,
- .remove_new = zynqmp_firmware_remove,
+ .remove = zynqmp_firmware_remove,
};
module_platform_driver(zynqmp_firmware_driver);
diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c
index f4de3fea0b2d..e41492988dd6 100644
--- a/drivers/fpga/altera-fpga2sdram.c
+++ b/drivers/fpga/altera-fpga2sdram.c
@@ -152,7 +152,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
static struct platform_driver altera_fpga_driver = {
.probe = alt_fpga_bridge_probe,
- .remove_new = alt_fpga_bridge_remove,
+ .remove = alt_fpga_bridge_remove,
.driver = {
.name = "altera_fpga2sdram_bridge",
.of_match_table = of_match_ptr(altera_fpga_of_match),
diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c
index 44061cb16f87..594693ff786e 100644
--- a/drivers/fpga/altera-freeze-bridge.c
+++ b/drivers/fpga/altera-freeze-bridge.c
@@ -262,7 +262,7 @@ static void altera_freeze_br_remove(struct platform_device *pdev)
static struct platform_driver altera_freeze_br_driver = {
.probe = altera_freeze_br_probe,
- .remove_new = altera_freeze_br_remove,
+ .remove = altera_freeze_br_remove,
.driver = {
.name = "altera_freeze_br",
.of_match_table = altera_freeze_br_of_match,
diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
index 6f8e24be19c6..f2f1250689cb 100644
--- a/drivers/fpga/altera-hps2fpga.c
+++ b/drivers/fpga/altera-hps2fpga.c
@@ -205,7 +205,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
static struct platform_driver alt_fpga_bridge_driver = {
.probe = alt_fpga_bridge_probe,
- .remove_new = alt_fpga_bridge_remove,
+ .remove = alt_fpga_bridge_remove,
.driver = {
.name = "altera_hps2fpga_bridge",
.of_match_table = of_match_ptr(altera_fpga_of_match),
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 6b97c073849e..2fd4f07ed081 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -947,12 +947,12 @@ static const struct attribute_group *afu_dev_groups[] = {
};
static struct platform_driver afu_driver = {
- .driver = {
- .name = DFL_FPGA_FEATURE_DEV_PORT,
+ .driver = {
+ .name = DFL_FPGA_FEATURE_DEV_PORT,
.dev_groups = afu_dev_groups,
},
- .probe = afu_probe,
- .remove_new = afu_remove,
+ .probe = afu_probe,
+ .remove = afu_remove,
};
static int __init afu_init(void)
diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c
index 0b01b3895277..950c606c59d4 100644
--- a/drivers/fpga/dfl-fme-br.c
+++ b/drivers/fpga/dfl-fme-br.c
@@ -92,11 +92,11 @@ static void fme_br_remove(struct platform_device *pdev)
}
static struct platform_driver fme_br_driver = {
- .driver = {
- .name = DFL_FPGA_FME_BRIDGE,
+ .driver = {
+ .name = DFL_FPGA_FME_BRIDGE,
},
- .probe = fme_br_probe,
- .remove_new = fme_br_remove,
+ .probe = fme_br_probe,
+ .remove = fme_br_remove,
};
module_platform_driver(fme_br_driver);
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index 864924f68f5e..f8d89a4a6ccb 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -742,12 +742,12 @@ static const struct attribute_group *fme_dev_groups[] = {
};
static struct platform_driver fme_driver = {
- .driver = {
- .name = DFL_FPGA_FEATURE_DEV_FME,
+ .driver = {
+ .name = DFL_FPGA_FEATURE_DEV_FME,
.dev_groups = fme_dev_groups,
},
- .probe = fme_probe,
- .remove_new = fme_remove,
+ .probe = fme_probe,
+ .remove = fme_remove,
};
module_platform_driver(fme_driver);
diff --git a/drivers/fpga/dfl-fme-region.c b/drivers/fpga/dfl-fme-region.c
index 71616f8b4982..c6cd63063c82 100644
--- a/drivers/fpga/dfl-fme-region.c
+++ b/drivers/fpga/dfl-fme-region.c
@@ -71,11 +71,11 @@ static void fme_region_remove(struct platform_device *pdev)
}
static struct platform_driver fme_region_driver = {
- .driver = {
- .name = DFL_FPGA_FME_REGION,
+ .driver = {
+ .name = DFL_FPGA_FME_REGION,
},
- .probe = fme_region_probe,
- .remove_new = fme_region_remove,
+ .probe = fme_region_probe,
+ .remove = fme_region_remove,
};
module_platform_driver(fme_region_driver);
diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c
index 80cac3a5f976..602807d6afcc 100644
--- a/drivers/fpga/dfl-pci.c
+++ b/drivers/fpga/dfl-pci.c
@@ -39,14 +39,6 @@ struct cci_drvdata {
struct dfl_fpga_cdev *cdev; /* container device */
};
-static void __iomem *cci_pci_ioremap_bar0(struct pci_dev *pcidev)
-{
- if (pcim_iomap_regions(pcidev, BIT(0), DRV_NAME))
- return NULL;
-
- return pcim_iomap_table(pcidev)[0];
-}
-
static int cci_pci_alloc_irq(struct pci_dev *pcidev)
{
int ret, nvec = pci_msix_vec_count(pcidev);
@@ -235,9 +227,9 @@ static int find_dfls_by_default(struct pci_dev *pcidev,
u64 v;
/* start to find Device Feature List from Bar 0 */
- base = cci_pci_ioremap_bar0(pcidev);
- if (!base)
- return -ENOMEM;
+ base = pcim_iomap_region(pcidev, 0, DRV_NAME);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
/*
* PF device has FME and Ports/AFUs, and VF device only has one
@@ -296,7 +288,7 @@ static int find_dfls_by_default(struct pci_dev *pcidev,
}
/* release I/O mappings for next step enumeration */
- pcim_iounmap_regions(pcidev, BIT(0));
+ pcim_iounmap_region(pcidev, 0);
return ret;
}
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 7ac9f9f5af12..dd515083bbdd 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -759,7 +759,7 @@ MODULE_DEVICE_TABLE(platform, intel_m10bmc_sec_ids);
static struct platform_driver intel_m10bmc_sec_driver = {
.probe = m10bmc_sec_probe,
- .remove_new = m10bmc_sec_remove,
+ .remove = m10bmc_sec_remove,
.driver = {
.name = "intel-m10bmc-sec-update",
.dev_groups = m10bmc_sec_attr_groups,
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index 8526a5a86f0c..43db4bb77138 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -436,7 +436,7 @@ static void of_fpga_region_remove(struct platform_device *pdev)
static struct platform_driver of_fpga_region_driver = {
.probe = of_fpga_region_probe,
- .remove_new = of_fpga_region_remove,
+ .remove = of_fpga_region_remove,
.driver = {
.name = "of-fpga-region",
.of_match_table = of_match_ptr(fpga_region_of_match),
diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c
index 4c03513b8f03..0165a3c86932 100644
--- a/drivers/fpga/socfpga-a10.c
+++ b/drivers/fpga/socfpga-a10.c
@@ -535,7 +535,7 @@ MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match);
static struct platform_driver socfpga_a10_fpga_driver = {
.probe = socfpga_a10_fpga_probe,
- .remove_new = socfpga_a10_fpga_remove,
+ .remove = socfpga_a10_fpga_remove,
.driver = {
.name = "socfpga_a10_fpga_manager",
.of_match_table = socfpga_a10_fpga_of_match,
diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c
index 2c0def7d7cbb..0a295ccf1644 100644
--- a/drivers/fpga/stratix10-soc.c
+++ b/drivers/fpga/stratix10-soc.c
@@ -455,7 +455,7 @@ MODULE_DEVICE_TABLE(of, s10_of_match);
static struct platform_driver s10_driver = {
.probe = s10_probe,
- .remove_new = s10_remove,
+ .remove = s10_remove,
.driver = {
.name = "Stratix10 SoC FPGA manager",
.of_match_table = of_match_ptr(s10_of_match),
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
index 788dd2f63a65..822751fad18a 100644
--- a/drivers/fpga/xilinx-pr-decoupler.c
+++ b/drivers/fpga/xilinx-pr-decoupler.c
@@ -162,7 +162,7 @@ static void xlnx_pr_decoupler_remove(struct platform_device *pdev)
static struct platform_driver xlnx_pr_decoupler_driver = {
.probe = xlnx_pr_decoupler_probe,
- .remove_new = xlnx_pr_decoupler_remove,
+ .remove = xlnx_pr_decoupler_remove,
.driver = {
.name = "xlnx_pr_decoupler",
.of_match_table = xlnx_pr_decoupler_of_match,
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 4db3d80e10b0..f7e08f7ea9ef 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -642,7 +642,7 @@ MODULE_DEVICE_TABLE(of, zynq_fpga_of_match);
static struct platform_driver zynq_fpga_driver = {
.probe = zynq_fpga_probe,
- .remove_new = zynq_fpga_remove,
+ .remove = zynq_fpga_remove,
.driver = {
.name = "zynq_fpga_manager",
.of_match_table = of_match_ptr(zynq_fpga_of_match),
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d93cd4f722b4..56fee58e281e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -70,8 +70,7 @@ config GPIO_SYSFS
ioctl() operations instead.
config GPIO_CDEV
- bool
- prompt "Character device (/dev/gpiochipN) support" if EXPERT
+ bool "Character device (/dev/gpiochipN) support" if EXPERT
default y
help
Say Y here to add the character device /dev/gpiochipN interface
@@ -149,9 +148,7 @@ config GPIO_74XX_MMIO
config GPIO_ALTERA
tristate "Altera GPIO"
- depends on OF_GPIO
select GPIOLIB_IRQCHIP
- select OF_GPIO_MM_GPIOCHIP
help
Say Y or M here to build support for the Altera PIO device.
@@ -243,7 +240,7 @@ config GPIO_CLPS711X
config GPIO_DAVINCI
tristate "TI Davinci/Keystone GPIO support"
default y if ARCH_DAVINCI
- depends on (ARM || ARM64) && (ARCH_DAVINCI || ARCH_KEYSTONE || ARCH_K3)
+ depends on ((ARM || ARM64) && (ARCH_DAVINCI || ARCH_KEYSTONE || ARCH_K3)) || COMPILE_TEST
help
Say yes here to enable GPIO support for TI Davinci/Keystone SoCs.
@@ -341,7 +338,6 @@ config GPIO_GRANITERAPIDS
config GPIO_GRGPIO
tristate "Aeroflex Gaisler GRGPIO support"
- depends on OF_GPIO
select GPIO_GENERIC
select IRQ_DOMAIN
help
@@ -487,8 +483,7 @@ config GPIO_MT7621
config GPIO_MVEBU
def_bool y
- depends on PLAT_ORION || ARCH_MVEBU
- depends on OF_GPIO
+ depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
select GENERIC_IRQ_CHIP
select REGMAP_MMIO
@@ -549,6 +544,12 @@ config GPIO_PL061
help
Say yes here to support the PrimeCell PL061 GPIO device.
+config GPIO_POLARFIRE_SOC
+ bool "Microchip FPGA GPIO support"
+ select REGMAP_MMIO
+ help
+ Say yes here to support the GPIO controllers on Microchip FPGAs.
+
config GPIO_PXA
bool "PXA GPIO support"
depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
@@ -714,13 +715,13 @@ config GPIO_TEGRA
config GPIO_TEGRA186
tristate "NVIDIA Tegra186 GPIO support"
- default ARCH_TEGRA_186_SOC || ARCH_TEGRA_194_SOC
- depends on ARCH_TEGRA_186_SOC || ARCH_TEGRA_194_SOC || COMPILE_TEST
+ default ARCH_TEGRA_186_SOC || ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC
+ depends on ARCH_TEGRA_186_SOC || ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC || COMPILE_TEST
depends on OF_GPIO
select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY
help
- Say yes here to support GPIO pins on NVIDIA Tegra186 SoCs.
+ Say yes here to support GPIO pins on NVIDIA Tegra186, 194 and 234 SoCs.
config GPIO_TS4800
tristate "TS-4800 DIO blocks and compatibles"
@@ -796,7 +797,6 @@ config GPIO_XGENE_SB
config GPIO_XILINX
tristate "Xilinx GPIO support"
select GPIOLIB_IRQCHIP
- depends on OF_GPIO
help
Say yes here to support the Xilinx FPGA GPIO device.
@@ -1287,6 +1287,16 @@ config GPIO_BD9571MWV
This driver can also be built as a module. If so, the module
will be called gpio-bd9571mwv.
+config GPIO_CGBC
+ tristate "Congatec Board Controller GPIO support"
+ depends on MFD_CGBC
+ help
+ Select this option to enable GPIO support for the Congatec Board
+ Controller.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-cgbc.
+
config GPIO_CROS_EC
tristate "ChromeOS EC GPIO support"
depends on CROS_EC
@@ -1844,6 +1854,13 @@ config GPIO_VIPERBOARD
River Tech's viperboard.h for detailed meaning
of the module parameters.
+config GPIO_MPSSE
+ tristate "FTDI MPSSE GPIO support"
+ select GPIOLIB_IRQCHIP
+ help
+ GPIO driver for FTDI's MPSSE interface. These can do input and
+ output. Each MPSSE provides 16 IO pins.
+
endmenu
menu "Virtual GPIO drivers"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 1429e8c0229b..af3ba4d81b58 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o
+obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o
obj-$(CONFIG_GPIO_CROS_EC) += gpio-cros-ec.o
@@ -114,6 +115,7 @@ obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
+obj-$(CONFIG_GPIO_MPSSE) += gpio-mpsse.o
obj-$(CONFIG_GPIO_MSC313) += gpio-msc313.o
obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o
obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
@@ -133,6 +135,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o
obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o
+obj-$(CONFIG_GPIO_POLARFIRE_SOC) += gpio-mpfs.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO
index 189c3abe7e79..942d1cd2bd3c 100644
--- a/drivers/gpio/TODO
+++ b/drivers/gpio/TODO
@@ -61,8 +61,8 @@ Work items:
- Change all consumer drivers that #include <linux/of_gpio.h> to
#include <linux/gpio/consumer.h> and stop doing custom parsing of the
- GPIO lines from the device tree. This can be tricky and often ivolves
- changing boardfiles, etc.
+ GPIO lines from the device tree. This can be tricky and often involves
+ changing board files, etc.
- Pull semantics for legacy device tree (OF) GPIO lookups into
gpiolib-of.c: in some cases subsystems are doing custom flags and
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 753e7be039e4..fca6cd2eb1dd 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -143,24 +143,17 @@ static int gen_74x164_probe(struct spi_device *spi)
chip->gpio_chip.parent = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE;
- mutex_init(&chip->lock);
+ ret = devm_mutex_init(&spi->dev, &chip->lock);
+ if (ret)
+ return ret;
ret = __gen_74x164_write_config(chip);
- if (ret) {
- dev_err(&spi->dev, "Failed writing: %d\n", ret);
- goto exit_destroy;
- }
+ if (ret)
+ return dev_err_probe(&spi->dev, ret, "Config write failed\n");
gpiod_set_value_cansleep(chip->gpiod_oe, 1);
- ret = gpiochip_add_data(&chip->gpio_chip, chip);
- if (!ret)
- return 0;
-
-exit_destroy:
- mutex_destroy(&chip->lock);
-
- return ret;
+ return devm_gpiochip_add_data(&spi->dev, &chip->gpio_chip, chip);
}
static void gen_74x164_remove(struct spi_device *spi)
@@ -168,8 +161,6 @@ static void gen_74x164_remove(struct spi_device *spi)
struct gen_74x164_chip *chip = spi_get_drvdata(spi);
gpiod_set_value_cansleep(chip->gpiod_oe, 0);
- gpiochip_remove(&chip->gpio_chip);
- mutex_destroy(&chip->lock);
}
static const struct spi_device_id gen_74x164_spi_ids[] = {
diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c
index 38e0fff9afe7..65f41cc3eafc 100644
--- a/drivers/gpio/gpio-aggregator.c
+++ b/drivers/gpio/gpio-aggregator.c
@@ -65,11 +65,11 @@ static int aggr_parse(struct gpio_aggregator *aggr)
{
char *args = skip_spaces(aggr->args);
char *name, *offsets, *p;
- unsigned long *bitmap;
unsigned int i, n = 0;
int error = 0;
- bitmap = bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL);
+ unsigned long *bitmap __free(bitmap) =
+ bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
@@ -82,7 +82,7 @@ static int aggr_parse(struct gpio_aggregator *aggr)
/* Named GPIO line */
error = aggr_add_gpio(aggr, name, U16_MAX, &n);
if (error)
- goto free_bitmap;
+ return error;
name = offsets;
continue;
@@ -92,13 +92,13 @@ static int aggr_parse(struct gpio_aggregator *aggr)
error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS);
if (error) {
pr_err("Cannot parse %s: %d\n", offsets, error);
- goto free_bitmap;
+ return error;
}
for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) {
error = aggr_add_gpio(aggr, name, i, &n);
if (error)
- goto free_bitmap;
+ return error;
}
args = next_arg(args, &name, &p);
@@ -106,12 +106,10 @@ static int aggr_parse(struct gpio_aggregator *aggr)
if (!n) {
pr_err("No GPIOs specified\n");
- error = -EINVAL;
+ return -EINVAL;
}
-free_bitmap:
- bitmap_free(bitmap);
- return error;
+ return 0;
}
static ssize_t new_device_store(struct device_driver *driver, const char *buf,
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index c2edfbb231fc..73e660c5e38a 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -4,11 +4,19 @@
* Based on gpio-mpc8xxx.c
*/
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/err.h>
#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/gpio/driver.h>
-#include <linux/gpio/legacy-of-mm-gpiochip.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <linux/gpio/driver.h>
#define ALTERA_GPIO_MAX_NGPIO 32
#define ALTERA_GPIO_DATA 0x0
@@ -18,7 +26,8 @@
/**
* struct altera_gpio_chip
-* @mmchip : memory mapped chip structure.
+* @gc : GPIO chip structure.
+* @regs : memory mapped IO address for the controller registers.
* @gpio_lock : synchronization lock so that new irq/set/get requests
* will be blocked until the current one completes.
* @interrupt_trigger : specifies the hardware configured IRQ trigger type
@@ -26,7 +35,8 @@
* @mapped_irq : kernel mapped irq number.
*/
struct altera_gpio_chip {
- struct of_mm_gpio_chip mmchip;
+ struct gpio_chip gc;
+ void __iomem *regs;
raw_spinlock_t gpio_lock;
int interrupt_trigger;
int mapped_irq;
@@ -34,40 +44,36 @@ struct altera_gpio_chip {
static void altera_gpio_irq_unmask(struct irq_data *d)
{
- struct altera_gpio_chip *altera_gc;
- struct of_mm_gpio_chip *mm_gc;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
unsigned long flags;
u32 intmask;
- altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- mm_gc = &altera_gc->mmchip;
- gpiochip_enable_irq(&mm_gc->gc, irqd_to_hwirq(d));
+ gpiochip_enable_irq(gc, irqd_to_hwirq(d));
raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
- intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
+ intmask = readl(altera_gc->regs + ALTERA_GPIO_IRQ_MASK);
/* Set ALTERA_GPIO_IRQ_MASK bit to unmask */
intmask |= BIT(irqd_to_hwirq(d));
- writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
+ writel(intmask, altera_gc->regs + ALTERA_GPIO_IRQ_MASK);
raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
}
static void altera_gpio_irq_mask(struct irq_data *d)
{
- struct altera_gpio_chip *altera_gc;
- struct of_mm_gpio_chip *mm_gc;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
unsigned long flags;
u32 intmask;
- altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- mm_gc = &altera_gc->mmchip;
-
raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
- intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
+ intmask = readl(altera_gc->regs + ALTERA_GPIO_IRQ_MASK);
/* Clear ALTERA_GPIO_IRQ_MASK bit to mask */
intmask &= ~BIT(irqd_to_hwirq(d));
- writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
+ writel(intmask, altera_gc->regs + ALTERA_GPIO_IRQ_MASK);
raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
- gpiochip_disable_irq(&mm_gc->gc, irqd_to_hwirq(d));
+
+ gpiochip_disable_irq(gc, irqd_to_hwirq(d));
}
/*
@@ -77,9 +83,8 @@ static void altera_gpio_irq_mask(struct irq_data *d)
static int altera_gpio_irq_set_type(struct irq_data *d,
unsigned int type)
{
- struct altera_gpio_chip *altera_gc;
-
- altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
if (type == IRQ_TYPE_NONE) {
irq_set_handler_locked(d, handle_bad_irq);
@@ -105,49 +110,39 @@ static unsigned int altera_gpio_irq_startup(struct irq_data *d)
static int altera_gpio_get(struct gpio_chip *gc, unsigned offset)
{
- struct of_mm_gpio_chip *mm_gc;
-
- mm_gc = to_of_mm_gpio_chip(gc);
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
- return !!(readl(mm_gc->regs + ALTERA_GPIO_DATA) & BIT(offset));
+ return !!(readl(altera_gc->regs + ALTERA_GPIO_DATA) & BIT(offset));
}
static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
{
- struct of_mm_gpio_chip *mm_gc;
- struct altera_gpio_chip *chip;
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
unsigned long flags;
unsigned int data_reg;
- mm_gc = to_of_mm_gpio_chip(gc);
- chip = gpiochip_get_data(gc);
-
- raw_spin_lock_irqsave(&chip->gpio_lock, flags);
- data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
+ raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
+ data_reg = readl(altera_gc->regs + ALTERA_GPIO_DATA);
if (value)
data_reg |= BIT(offset);
else
data_reg &= ~BIT(offset);
- writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA);
- raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
+ writel(data_reg, altera_gc->regs + ALTERA_GPIO_DATA);
+ raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
}
static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
- struct of_mm_gpio_chip *mm_gc;
- struct altera_gpio_chip *chip;
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
unsigned long flags;
unsigned int gpio_ddr;
- mm_gc = to_of_mm_gpio_chip(gc);
- chip = gpiochip_get_data(gc);
-
- raw_spin_lock_irqsave(&chip->gpio_lock, flags);
+ raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
/* Set pin as input, assumes software controlled IP */
- gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
+ gpio_ddr = readl(altera_gc->regs + ALTERA_GPIO_DIR);
gpio_ddr &= ~BIT(offset);
- writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
- raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
+ writel(gpio_ddr, altera_gc->regs + ALTERA_GPIO_DIR);
+ raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
return 0;
}
@@ -155,53 +150,46 @@ static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
static int altera_gpio_direction_output(struct gpio_chip *gc,
unsigned offset, int value)
{
- struct of_mm_gpio_chip *mm_gc;
- struct altera_gpio_chip *chip;
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
unsigned long flags;
unsigned int data_reg, gpio_ddr;
- mm_gc = to_of_mm_gpio_chip(gc);
- chip = gpiochip_get_data(gc);
-
- raw_spin_lock_irqsave(&chip->gpio_lock, flags);
+ raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
/* Sets the GPIO value */
- data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
+ data_reg = readl(altera_gc->regs + ALTERA_GPIO_DATA);
if (value)
data_reg |= BIT(offset);
else
data_reg &= ~BIT(offset);
- writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA);
+ writel(data_reg, altera_gc->regs + ALTERA_GPIO_DATA);
/* Set pin as output, assumes software controlled IP */
- gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
+ gpio_ddr = readl(altera_gc->regs + ALTERA_GPIO_DIR);
gpio_ddr |= BIT(offset);
- writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
- raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
+ writel(gpio_ddr, altera_gc->regs + ALTERA_GPIO_DIR);
+ raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
return 0;
}
static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
{
- struct altera_gpio_chip *altera_gc;
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
+ struct irq_domain *irqdomain = gc->irq.domain;
struct irq_chip *chip;
- struct of_mm_gpio_chip *mm_gc;
- struct irq_domain *irqdomain;
unsigned long status;
int i;
- altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc));
chip = irq_desc_get_chip(desc);
- mm_gc = &altera_gc->mmchip;
- irqdomain = altera_gc->mmchip.gc.irq.domain;
chained_irq_enter(chip, desc);
while ((status =
- (readl(mm_gc->regs + ALTERA_GPIO_EDGE_CAP) &
- readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK)))) {
- writel(status, mm_gc->regs + ALTERA_GPIO_EDGE_CAP);
- for_each_set_bit(i, &status, mm_gc->gc.ngpio)
+ (readl(altera_gc->regs + ALTERA_GPIO_EDGE_CAP) &
+ readl(altera_gc->regs + ALTERA_GPIO_IRQ_MASK)))) {
+ writel(status, altera_gc->regs + ALTERA_GPIO_EDGE_CAP);
+ for_each_set_bit(i, &status, gc->ngpio)
generic_handle_domain_irq(irqdomain, i);
}
@@ -210,24 +198,21 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
{
- struct altera_gpio_chip *altera_gc;
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct altera_gpio_chip *altera_gc = gpiochip_get_data(gc);
+ struct irq_domain *irqdomain = gc->irq.domain;
struct irq_chip *chip;
- struct of_mm_gpio_chip *mm_gc;
- struct irq_domain *irqdomain;
unsigned long status;
int i;
- altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc));
chip = irq_desc_get_chip(desc);
- mm_gc = &altera_gc->mmchip;
- irqdomain = altera_gc->mmchip.gc.irq.domain;
chained_irq_enter(chip, desc);
- status = readl(mm_gc->regs + ALTERA_GPIO_DATA);
- status &= readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
+ status = readl(altera_gc->regs + ALTERA_GPIO_DATA);
+ status &= readl(altera_gc->regs + ALTERA_GPIO_IRQ_MASK);
- for_each_set_bit(i, &status, mm_gc->gc.ngpio)
+ for_each_set_bit(i, &status, gc->ngpio)
generic_handle_domain_irq(irqdomain, i);
chained_irq_exit(chip, desc);
@@ -246,7 +231,7 @@ static const struct irq_chip altera_gpio_irq_chip = {
static int altera_gpio_probe(struct platform_device *pdev)
{
- struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
int reg, ret;
struct altera_gpio_chip *altera_gc;
struct gpio_irq_chip *girq;
@@ -257,39 +242,47 @@ static int altera_gpio_probe(struct platform_device *pdev)
raw_spin_lock_init(&altera_gc->gpio_lock);
- if (of_property_read_u32(node, "altr,ngpio", &reg))
+ if (device_property_read_u32(dev, "altr,ngpio", &reg))
/* By default assume maximum ngpio */
- altera_gc->mmchip.gc.ngpio = ALTERA_GPIO_MAX_NGPIO;
+ altera_gc->gc.ngpio = ALTERA_GPIO_MAX_NGPIO;
else
- altera_gc->mmchip.gc.ngpio = reg;
+ altera_gc->gc.ngpio = reg;
- if (altera_gc->mmchip.gc.ngpio > ALTERA_GPIO_MAX_NGPIO) {
+ if (altera_gc->gc.ngpio > ALTERA_GPIO_MAX_NGPIO) {
dev_warn(&pdev->dev,
"ngpio is greater than %d, defaulting to %d\n",
ALTERA_GPIO_MAX_NGPIO, ALTERA_GPIO_MAX_NGPIO);
- altera_gc->mmchip.gc.ngpio = ALTERA_GPIO_MAX_NGPIO;
+ altera_gc->gc.ngpio = ALTERA_GPIO_MAX_NGPIO;
}
- altera_gc->mmchip.gc.direction_input = altera_gpio_direction_input;
- altera_gc->mmchip.gc.direction_output = altera_gpio_direction_output;
- altera_gc->mmchip.gc.get = altera_gpio_get;
- altera_gc->mmchip.gc.set = altera_gpio_set;
- altera_gc->mmchip.gc.owner = THIS_MODULE;
- altera_gc->mmchip.gc.parent = &pdev->dev;
+ altera_gc->gc.direction_input = altera_gpio_direction_input;
+ altera_gc->gc.direction_output = altera_gpio_direction_output;
+ altera_gc->gc.get = altera_gpio_get;
+ altera_gc->gc.set = altera_gpio_set;
+ altera_gc->gc.owner = THIS_MODULE;
+ altera_gc->gc.parent = &pdev->dev;
+ altera_gc->gc.base = -1;
- altera_gc->mapped_irq = platform_get_irq_optional(pdev, 0);
+ altera_gc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", dev_fwnode(dev));
+ if (!altera_gc->gc.label)
+ return -ENOMEM;
+ altera_gc->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(altera_gc->regs))
+ return dev_err_probe(dev, PTR_ERR(altera_gc->regs), "failed to ioremap memory resource\n");
+
+ altera_gc->mapped_irq = platform_get_irq_optional(pdev, 0);
if (altera_gc->mapped_irq < 0)
goto skip_irq;
- if (of_property_read_u32(node, "altr,interrupt-type", &reg)) {
+ if (device_property_read_u32(dev, "altr,interrupt-type", &reg)) {
dev_err(&pdev->dev,
"altr,interrupt-type value not set in device tree\n");
return -EINVAL;
}
altera_gc->interrupt_trigger = reg;
- girq = &altera_gc->mmchip.gc.irq;
+ girq = &altera_gc->gc.irq;
gpio_irq_chip_set_chip(girq, &altera_gpio_irq_chip);
if (altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH)
@@ -306,24 +299,15 @@ static int altera_gpio_probe(struct platform_device *pdev)
girq->parents[0] = altera_gc->mapped_irq;
skip_irq:
- ret = of_mm_gpiochip_add_data(node, &altera_gc->mmchip, altera_gc);
+ ret = devm_gpiochip_add_data(dev, &altera_gc->gc, altera_gc);
if (ret) {
dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n");
return ret;
}
- platform_set_drvdata(pdev, altera_gc);
-
return 0;
}
-static void altera_gpio_remove(struct platform_device *pdev)
-{
- struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev);
-
- of_mm_gpiochip_remove(&altera_gc->mmchip);
-}
-
static const struct of_device_id altera_gpio_of_match[] = {
{ .compatible = "altr,pio-1.0", },
{},
@@ -336,7 +320,6 @@ static struct platform_driver altera_gpio_driver = {
.of_match_table = altera_gpio_of_match,
},
.probe = altera_gpio_probe,
- .remove_new = altera_gpio_remove,
};
static int __init altera_gpio_init(void)
diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c
index 0a2ea9db4682..b70036587d9c 100644
--- a/drivers/gpio/gpio-amdpt.c
+++ b/drivers/gpio/gpio-amdpt.c
@@ -106,7 +106,7 @@ static int pt_gpio_probe(struct platform_device *pdev)
pt_gpio->gc.free = pt_gpio_free;
pt_gpio->gc.ngpio = (uintptr_t)device_get_match_data(dev);
- ret = gpiochip_add_data(&pt_gpio->gc, pt_gpio);
+ ret = devm_gpiochip_add_data(dev, &pt_gpio->gc, pt_gpio);
if (ret) {
dev_err(dev, "Failed to register GPIO lib\n");
return ret;
@@ -122,13 +122,6 @@ static int pt_gpio_probe(struct platform_device *pdev)
return ret;
}
-static void pt_gpio_remove(struct platform_device *pdev)
-{
- struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev);
-
- gpiochip_remove(&pt_gpio->gc);
-}
-
static const struct acpi_device_id pt_gpio_acpi_match[] = {
{ "AMDF030", PT_TOTAL_GPIO },
{ "AMDIF030", PT_TOTAL_GPIO },
@@ -143,7 +136,6 @@ static struct platform_driver pt_gpio_driver = {
.acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),
},
.probe = pt_gpio_probe,
- .remove_new = pt_gpio_remove,
};
module_platform_driver(pt_gpio_driver);
diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index 72755fee6478..34eb26298e32 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -420,7 +420,7 @@ static void aspeed_sgpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
int offset;
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
- seq_printf(p, dev_name(gpio->dev));
+ seq_puts(p, dev_name(gpio->dev));
}
static const struct irq_chip aspeed_sgpio_irq_chip = {
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index ea40ad43a79b..40c1bd80f8b0 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -30,6 +30,27 @@
#include <linux/gpio/consumer.h>
#include "gpiolib.h"
+/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
+
+#define GPIO_G7_IRQ_STS_BASE 0x100
+#define GPIO_G7_IRQ_STS_OFFSET(x) (GPIO_G7_IRQ_STS_BASE + (x) * 0x4)
+#define GPIO_G7_CTRL_REG_BASE 0x180
+#define GPIO_G7_CTRL_REG_OFFSET(x) (GPIO_G7_CTRL_REG_BASE + (x) * 0x4)
+#define GPIO_G7_CTRL_OUT_DATA BIT(0)
+#define GPIO_G7_CTRL_DIR BIT(1)
+#define GPIO_G7_CTRL_IRQ_EN BIT(2)
+#define GPIO_G7_CTRL_IRQ_TYPE0 BIT(3)
+#define GPIO_G7_CTRL_IRQ_TYPE1 BIT(4)
+#define GPIO_G7_CTRL_IRQ_TYPE2 BIT(5)
+#define GPIO_G7_CTRL_RST_TOLERANCE BIT(6)
+#define GPIO_G7_CTRL_DEBOUNCE_SEL1 BIT(7)
+#define GPIO_G7_CTRL_DEBOUNCE_SEL2 BIT(8)
+#define GPIO_G7_CTRL_INPUT_MASK BIT(9)
+#define GPIO_G7_CTRL_IRQ_STS BIT(12)
+#define GPIO_G7_CTRL_IN_DATA BIT(13)
+
struct aspeed_bank_props {
unsigned int bank;
u32 input;
@@ -39,6 +60,10 @@ struct aspeed_bank_props {
struct aspeed_gpio_config {
unsigned int nr_gpios;
const struct aspeed_bank_props *props;
+ const struct aspeed_gpio_llops *llops;
+ const int *debounce_timers_array;
+ int debounce_timers_num;
+ bool require_dcache;
};
/*
@@ -77,7 +102,6 @@ struct aspeed_gpio_bank {
uint16_t debounce_regs;
uint16_t tolerance_regs;
uint16_t cmdsrc_regs;
- const char names[4][3];
};
/*
@@ -92,6 +116,22 @@ struct aspeed_gpio_bank {
*/
static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 };
+static const int g7_debounce_timers[4] = { 0x00, 0x00, 0x04, 0x08 };
+
+/*
+ * The debounce timers array is used to configure the debounce timer settings.Here’s how it works:
+ * Array Value: Indicates the offset for configuring the debounce timer.
+ * Array Index: Corresponds to the debounce setting register.
+ * The debounce timers array follows this pattern for configuring the debounce setting registers:
+ * Array Index 0: No debounce timer is set;
+ * Array Value is irrelevant (don’t care).
+ * Array Index 1: Debounce setting #2 is set to 1, and debounce setting #1 is set to 0.
+ * Array Value: offset for configuring debounce timer 0 (g4: 0x50, g7: 0x00)
+ * Array Index 2: Debounce setting #2 is set to 0, and debounce setting #1 is set to 1.
+ * Array Value: offset for configuring debounce timer 1 (g4: 0x54, g7: 0x04)
+ * Array Index 3: Debounce setting #2 is set to 1, and debounce setting #1 is set to 1.
+ * Array Value: offset for configuring debounce timer 2 (g4: 0x58, g7: 0x8)
+ */
static const struct aspeed_gpio_copro_ops *copro_ops;
static void *copro_data;
@@ -104,7 +144,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x0040,
.tolerance_regs = 0x001c,
.cmdsrc_regs = 0x0060,
- .names = { "A", "B", "C", "D" },
},
{
.val_regs = 0x0020,
@@ -113,7 +152,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x0048,
.tolerance_regs = 0x003c,
.cmdsrc_regs = 0x0068,
- .names = { "E", "F", "G", "H" },
},
{
.val_regs = 0x0070,
@@ -122,7 +160,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x00b0,
.tolerance_regs = 0x00ac,
.cmdsrc_regs = 0x0090,
- .names = { "I", "J", "K", "L" },
},
{
.val_regs = 0x0078,
@@ -131,7 +168,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x0100,
.tolerance_regs = 0x00fc,
.cmdsrc_regs = 0x00e0,
- .names = { "M", "N", "O", "P" },
},
{
.val_regs = 0x0080,
@@ -140,7 +176,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x0130,
.tolerance_regs = 0x012c,
.cmdsrc_regs = 0x0110,
- .names = { "Q", "R", "S", "T" },
},
{
.val_regs = 0x0088,
@@ -149,7 +184,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x0160,
.tolerance_regs = 0x015c,
.cmdsrc_regs = 0x0140,
- .names = { "U", "V", "W", "X" },
},
{
.val_regs = 0x01E0,
@@ -158,7 +192,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x0190,
.tolerance_regs = 0x018c,
.cmdsrc_regs = 0x0170,
- .names = { "Y", "Z", "AA", "AB" },
},
{
.val_regs = 0x01e8,
@@ -167,7 +200,6 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.debounce_regs = 0x01c0,
.tolerance_regs = 0x01bc,
.cmdsrc_regs = 0x01a0,
- .names = { "AC", "", "", "" },
},
};
@@ -187,6 +219,19 @@ enum aspeed_gpio_reg {
reg_cmdsrc1,
};
+struct aspeed_gpio_llops {
+ void (*reg_bit_set)(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg, bool val);
+ bool (*reg_bit_get)(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg);
+ int (*reg_bank_get)(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg);
+ void (*privilege_ctrl)(struct aspeed_gpio *gpio, unsigned int offset, int owner);
+ void (*privilege_init)(struct aspeed_gpio *gpio);
+ bool (*copro_request)(struct aspeed_gpio *gpio, unsigned int offset);
+ void (*copro_release)(struct aspeed_gpio *gpio, unsigned int offset);
+};
+
#define GPIO_VAL_VALUE 0x00
#define GPIO_VAL_DIR 0x04
@@ -207,9 +252,9 @@ enum aspeed_gpio_reg {
#define GPIO_CMDSRC_RESERVED 3
/* This will be resolved at compile time */
-static inline void __iomem *bank_reg(struct aspeed_gpio *gpio,
- const struct aspeed_gpio_bank *bank,
- const enum aspeed_gpio_reg reg)
+static void __iomem *aspeed_gpio_g4_bank_reg(struct aspeed_gpio *gpio,
+ const struct aspeed_gpio_bank *bank,
+ const enum aspeed_gpio_reg reg)
{
switch (reg) {
case reg_val:
@@ -242,14 +287,43 @@ static inline void __iomem *bank_reg(struct aspeed_gpio *gpio,
BUG();
}
+static u32 aspeed_gpio_g7_reg_mask(const enum aspeed_gpio_reg reg)
+{
+ switch (reg) {
+ case reg_val:
+ return GPIO_G7_CTRL_OUT_DATA;
+ case reg_dir:
+ return GPIO_G7_CTRL_DIR;
+ case reg_irq_enable:
+ return GPIO_G7_CTRL_IRQ_EN;
+ case reg_irq_type0:
+ return GPIO_G7_CTRL_IRQ_TYPE0;
+ case reg_irq_type1:
+ return GPIO_G7_CTRL_IRQ_TYPE1;
+ case reg_irq_type2:
+ return GPIO_G7_CTRL_IRQ_TYPE2;
+ case reg_tolerance:
+ return GPIO_G7_CTRL_RST_TOLERANCE;
+ case reg_debounce_sel1:
+ return GPIO_G7_CTRL_DEBOUNCE_SEL1;
+ case reg_debounce_sel2:
+ return GPIO_G7_CTRL_DEBOUNCE_SEL2;
+ case reg_rdata:
+ return GPIO_G7_CTRL_OUT_DATA;
+ case reg_irq_status:
+ return GPIO_G7_CTRL_IRQ_STS;
+ case reg_cmdsrc0:
+ case reg_cmdsrc1:
+ default:
+ WARN_ON_ONCE(1);
+ return 0;
+ }
+}
+
#define GPIO_BANK(x) ((x) >> 5)
#define GPIO_OFFSET(x) ((x) & 0x1f)
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
-#define _GPIO_SET_DEBOUNCE(t, o, i) ((!!((t) & BIT(i))) << GPIO_OFFSET(o))
-#define GPIO_SET_DEBOUNCE1(t, o) _GPIO_SET_DEBOUNCE(t, o, 1)
-#define GPIO_SET_DEBOUNCE2(t, o) _GPIO_SET_DEBOUNCE(t, o, 0)
-
static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
{
unsigned int bank = GPIO_BANK(offset);
@@ -280,11 +354,11 @@ static inline const struct aspeed_bank_props *find_bank_props(
static inline bool have_gpio(struct aspeed_gpio *gpio, unsigned int offset)
{
const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
- const struct aspeed_gpio_bank *bank = to_bank(offset);
- unsigned int group = GPIO_OFFSET(offset) / 8;
- return bank->names[group][0] != '\0' &&
- (!props || ((props->input | props->output) & GPIO_BIT(offset)));
+ if (offset >= gpio->chip.ngpio)
+ return false;
+
+ return (!props || ((props->input | props->output) & GPIO_BIT(offset)));
}
static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
@@ -304,110 +378,49 @@ static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
return !props || (props->output & GPIO_BIT(offset));
}
-static void aspeed_gpio_change_cmd_source(struct aspeed_gpio *gpio,
- const struct aspeed_gpio_bank *bank,
- int bindex, int cmdsrc)
+static void aspeed_gpio_change_cmd_source(struct aspeed_gpio *gpio, unsigned int offset, int cmdsrc)
{
- void __iomem *c0 = bank_reg(gpio, bank, reg_cmdsrc0);
- void __iomem *c1 = bank_reg(gpio, bank, reg_cmdsrc1);
- u32 bit, reg;
-
- /*
- * Each register controls 4 banks, so take the bottom 2
- * bits of the bank index, and use them to select the
- * right control bit (0, 8, 16 or 24).
- */
- bit = BIT((bindex & 3) << 3);
-
- /* Source 1 first to avoid illegal 11 combination */
- reg = ioread32(c1);
- if (cmdsrc & 2)
- reg |= bit;
- else
- reg &= ~bit;
- iowrite32(reg, c1);
-
- /* Then Source 0 */
- reg = ioread32(c0);
- if (cmdsrc & 1)
- reg |= bit;
- else
- reg &= ~bit;
- iowrite32(reg, c0);
+ if (gpio->config->llops->privilege_ctrl)
+ gpio->config->llops->privilege_ctrl(gpio, offset, cmdsrc);
}
static bool aspeed_gpio_copro_request(struct aspeed_gpio *gpio,
unsigned int offset)
{
- const struct aspeed_gpio_bank *bank = to_bank(offset);
-
- if (!copro_ops || !gpio->cf_copro_bankmap)
- return false;
- if (!gpio->cf_copro_bankmap[offset >> 3])
- return false;
- if (!copro_ops->request_access)
- return false;
-
- /* Pause the coprocessor */
- copro_ops->request_access(copro_data);
-
- /* Change command source back to ARM */
- aspeed_gpio_change_cmd_source(gpio, bank, offset >> 3, GPIO_CMDSRC_ARM);
-
- /* Update cache */
- gpio->dcache[GPIO_BANK(offset)] = ioread32(bank_reg(gpio, bank, reg_rdata));
+ if (gpio->config->llops->copro_request)
+ return gpio->config->llops->copro_request(gpio, offset);
- return true;
+ return false;
}
static void aspeed_gpio_copro_release(struct aspeed_gpio *gpio,
unsigned int offset)
{
- const struct aspeed_gpio_bank *bank = to_bank(offset);
-
- if (!copro_ops || !gpio->cf_copro_bankmap)
- return;
- if (!gpio->cf_copro_bankmap[offset >> 3])
- return;
- if (!copro_ops->release_access)
- return;
-
- /* Change command source back to ColdFire */
- aspeed_gpio_change_cmd_source(gpio, bank, offset >> 3,
- GPIO_CMDSRC_COLDFIRE);
+ if (gpio->config->llops->copro_release)
+ gpio->config->llops->copro_release(gpio, offset);
+}
- /* Restart the coprocessor */
- copro_ops->release_access(copro_data);
+static bool aspeed_gpio_support_copro(struct aspeed_gpio *gpio)
+{
+ return gpio->config->llops->copro_request && gpio->config->llops->copro_release &&
+ gpio->config->llops->privilege_ctrl && gpio->config->llops->privilege_init;
}
static int aspeed_gpio_get(struct gpio_chip *gc, unsigned int offset)
{
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
- const struct aspeed_gpio_bank *bank = to_bank(offset);
- return !!(ioread32(bank_reg(gpio, bank, reg_val)) & GPIO_BIT(offset));
+ return gpio->config->llops->reg_bit_get(gpio, offset, reg_val);
}
static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
int val)
{
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
- const struct aspeed_gpio_bank *bank = to_bank(offset);
- void __iomem *addr;
- u32 reg;
-
- addr = bank_reg(gpio, bank, reg_val);
- reg = gpio->dcache[GPIO_BANK(offset)];
- if (val)
- reg |= GPIO_BIT(offset);
- else
- reg &= ~GPIO_BIT(offset);
- gpio->dcache[GPIO_BANK(offset)] = reg;
-
- iowrite32(reg, addr);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_val, val);
/* Flush write */
- ioread32(addr);
+ gpio->config->llops->reg_bit_get(gpio, offset, reg_val);
}
static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
@@ -415,7 +428,7 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
{
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
unsigned long flags;
- bool copro;
+ bool copro = false;
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
@@ -430,22 +443,16 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
{
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
- const struct aspeed_gpio_bank *bank = to_bank(offset);
- void __iomem *addr = bank_reg(gpio, bank, reg_dir);
unsigned long flags;
- bool copro;
- u32 reg;
+ bool copro = false;
if (!have_input(gpio, offset))
return -ENOTSUPP;
raw_spin_lock_irqsave(&gpio->lock, flags);
- reg = ioread32(addr);
- reg &= ~GPIO_BIT(offset);
-
copro = aspeed_gpio_copro_request(gpio, offset);
- iowrite32(reg, addr);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_dir, 0);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
@@ -458,23 +465,17 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
unsigned int offset, int val)
{
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
- const struct aspeed_gpio_bank *bank = to_bank(offset);
- void __iomem *addr = bank_reg(gpio, bank, reg_dir);
unsigned long flags;
- bool copro;
- u32 reg;
+ bool copro = false;
if (!have_output(gpio, offset))
return -ENOTSUPP;
raw_spin_lock_irqsave(&gpio->lock, flags);
- reg = ioread32(addr);
- reg |= GPIO_BIT(offset);
-
copro = aspeed_gpio_copro_request(gpio, offset);
__aspeed_gpio_set(gc, offset, val);
- iowrite32(reg, addr);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_dir, 1);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
@@ -486,7 +487,6 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
- const struct aspeed_gpio_bank *bank = to_bank(offset);
unsigned long flags;
u32 val;
@@ -498,7 +498,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
raw_spin_lock_irqsave(&gpio->lock, flags);
- val = ioread32(bank_reg(gpio, bank, reg_dir)) & GPIO_BIT(offset);
+ val = gpio->config->llops->reg_bit_get(gpio, offset, reg_dir);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
@@ -507,8 +507,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
struct aspeed_gpio **gpio,
- const struct aspeed_gpio_bank **bank,
- u32 *bit, int *offset)
+ int *offset)
{
struct aspeed_gpio *internal;
@@ -521,32 +520,25 @@ static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
return -ENOTSUPP;
*gpio = internal;
- *bank = to_bank(*offset);
- *bit = GPIO_BIT(*offset);
return 0;
}
static void aspeed_gpio_irq_ack(struct irq_data *d)
{
- const struct aspeed_gpio_bank *bank;
struct aspeed_gpio *gpio;
unsigned long flags;
- void __iomem *status_addr;
int rc, offset;
- bool copro;
- u32 bit;
+ bool copro = false;
- rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);
+ rc = irqd_to_aspeed_gpio_data(d, &gpio, &offset);
if (rc)
return;
- status_addr = bank_reg(gpio, bank, reg_irq_status);
-
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
- iowrite32(bit, status_addr);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_status, 1);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
@@ -555,20 +547,15 @@ static void aspeed_gpio_irq_ack(struct irq_data *d)
static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
{
- const struct aspeed_gpio_bank *bank;
struct aspeed_gpio *gpio;
unsigned long flags;
- u32 reg, bit;
- void __iomem *addr;
int rc, offset;
- bool copro;
+ bool copro = false;
- rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);
+ rc = irqd_to_aspeed_gpio_data(d, &gpio, &offset);
if (rc)
return;
- addr = bank_reg(gpio, bank, reg_irq_enable);
-
/* Unmasking the IRQ */
if (set)
gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d));
@@ -576,12 +563,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
- reg = ioread32(addr);
- if (set)
- reg |= bit;
- else
- reg &= ~bit;
- iowrite32(reg, addr);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_enable, set);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
@@ -607,34 +589,31 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
u32 type0 = 0;
u32 type1 = 0;
u32 type2 = 0;
- u32 bit, reg;
- const struct aspeed_gpio_bank *bank;
irq_flow_handler_t handler;
struct aspeed_gpio *gpio;
unsigned long flags;
- void __iomem *addr;
int rc, offset;
- bool copro;
+ bool copro = false;
- rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);
+ rc = irqd_to_aspeed_gpio_data(d, &gpio, &offset);
if (rc)
return -EINVAL;
switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_BOTH:
- type2 |= bit;
+ type2 = 1;
fallthrough;
case IRQ_TYPE_EDGE_RISING:
- type0 |= bit;
+ type0 = 1;
fallthrough;
case IRQ_TYPE_EDGE_FALLING:
handler = handle_edge_irq;
break;
case IRQ_TYPE_LEVEL_HIGH:
- type0 |= bit;
+ type0 = 1;
fallthrough;
case IRQ_TYPE_LEVEL_LOW:
- type1 |= bit;
+ type1 = 1;
handler = handle_level_irq;
break;
default:
@@ -644,20 +623,9 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
- addr = bank_reg(gpio, bank, reg_irq_type0);
- reg = ioread32(addr);
- reg = (reg & ~bit) | type0;
- iowrite32(reg, addr);
-
- addr = bank_reg(gpio, bank, reg_irq_type1);
- reg = ioread32(addr);
- reg = (reg & ~bit) | type1;
- iowrite32(reg, addr);
-
- addr = bank_reg(gpio, bank, reg_irq_type2);
- reg = ioread32(addr);
- reg = (reg & ~bit) | type2;
- iowrite32(reg, addr);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type0, type0);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type1, type1);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_irq_type2, type2);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
@@ -672,7 +640,6 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct irq_chip *ic = irq_desc_get_chip(desc);
- struct aspeed_gpio *data = gpiochip_get_data(gc);
unsigned int i, p, banks;
unsigned long reg;
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
@@ -681,9 +648,7 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
for (i = 0; i < banks; i++) {
- const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
-
- reg = ioread32(bank_reg(data, bank, reg_irq_status));
+ reg = gpio->config->llops->reg_bank_get(gpio, i * 32, reg_irq_status);
for_each_set_bit(p, &reg, 32)
generic_handle_domain_irq(gc->irq.domain, i * 32 + p);
@@ -722,23 +687,12 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
{
struct aspeed_gpio *gpio = gpiochip_get_data(chip);
unsigned long flags;
- void __iomem *treg;
- bool copro;
- u32 val;
-
- treg = bank_reg(gpio, to_bank(offset), reg_tolerance);
+ bool copro = false;
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
- val = readl(treg);
-
- if (enable)
- val |= GPIO_BIT(offset);
- else
- val &= ~GPIO_BIT(offset);
-
- writel(val, treg);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_tolerance, enable);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
@@ -832,21 +786,11 @@ static inline bool timer_allocation_registered(struct aspeed_gpio *gpio,
static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset,
unsigned int timer)
{
- const struct aspeed_gpio_bank *bank = to_bank(offset);
- const u32 mask = GPIO_BIT(offset);
- void __iomem *addr;
- u32 val;
-
/* Note: Debounce timer isn't under control of the command
* source registers, so no need to sync with the coprocessor
*/
- addr = bank_reg(gpio, bank, reg_debounce_sel1);
- val = ioread32(addr);
- iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE1(timer, offset), addr);
-
- addr = bank_reg(gpio, bank, reg_debounce_sel2);
- val = ioread32(addr);
- iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE2(timer, offset), addr);
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_debounce_sel1, !!(timer & BIT(1)));
+ gpio->config->llops->reg_bit_set(gpio, offset, reg_debounce_sel2, !!(timer & BIT(0)));
}
static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
@@ -877,15 +821,15 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
}
/* Try to find a timer already configured for the debounce period */
- for (i = 1; i < ARRAY_SIZE(debounce_timers); i++) {
+ for (i = 1; i < gpio->config->debounce_timers_num; i++) {
u32 cycles;
- cycles = ioread32(gpio->base + debounce_timers[i]);
+ cycles = ioread32(gpio->base + gpio->config->debounce_timers_array[i]);
if (requested_cycles == cycles)
break;
}
- if (i == ARRAY_SIZE(debounce_timers)) {
+ if (i == gpio->config->debounce_timers_num) {
int j;
/*
@@ -899,8 +843,8 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
if (j == ARRAY_SIZE(gpio->timer_users)) {
dev_warn(chip->parent,
- "Debounce timers exhausted, cannot debounce for period %luus\n",
- usecs);
+ "Debounce timers exhausted, cannot debounce for period %luus\n",
+ usecs);
rc = -EPERM;
@@ -916,7 +860,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
i = j;
- iowrite32(requested_cycles, gpio->base + debounce_timers[i]);
+ iowrite32(requested_cycles, gpio->base + gpio->config->debounce_timers_array[i]);
}
if (WARN(i == 0, "Cannot register index of disabled timer\n")) {
@@ -1019,6 +963,9 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
const struct aspeed_gpio_bank *bank = to_bank(offset);
unsigned long flags;
+ if (!aspeed_gpio_support_copro(gpio))
+ return -EOPNOTSUPP;
+
if (!gpio->cf_copro_bankmap)
gpio->cf_copro_bankmap = kzalloc(gpio->chip.ngpio >> 3, GFP_KERNEL);
if (!gpio->cf_copro_bankmap)
@@ -1038,7 +985,7 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
/* Switch command source */
if (gpio->cf_copro_bankmap[bindex] == 1)
- aspeed_gpio_change_cmd_source(gpio, bank, bindex,
+ aspeed_gpio_change_cmd_source(gpio, offset,
GPIO_CMDSRC_COLDFIRE);
if (vreg_offset)
@@ -1062,9 +1009,11 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
struct gpio_chip *chip = gpiod_to_chip(desc);
struct aspeed_gpio *gpio = gpiochip_get_data(chip);
int rc = 0, bindex, offset = gpio_chip_hwgpio(desc);
- const struct aspeed_gpio_bank *bank = to_bank(offset);
unsigned long flags;
+ if (!aspeed_gpio_support_copro(gpio))
+ return -EOPNOTSUPP;
+
if (!gpio->cf_copro_bankmap)
return -ENXIO;
@@ -1083,7 +1032,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
/* Switch command source */
if (gpio->cf_copro_bankmap[bindex] == 0)
- aspeed_gpio_change_cmd_source(gpio, bank, bindex,
+ aspeed_gpio_change_cmd_source(gpio, offset,
GPIO_CMDSRC_ARM);
bail:
raw_spin_unlock_irqrestore(&gpio->lock, flags);
@@ -1093,16 +1042,14 @@ EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio);
static void aspeed_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
- const struct aspeed_gpio_bank *bank;
struct aspeed_gpio *gpio;
- u32 bit;
int rc, offset;
- rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);
+ rc = irqd_to_aspeed_gpio_data(d, &gpio, &offset);
if (rc)
return;
- seq_printf(p, dev_name(gpio->dev));
+ seq_puts(p, dev_name(gpio->dev));
}
static const struct irq_chip aspeed_gpio_irq_chip = {
@@ -1115,6 +1062,173 @@ static const struct irq_chip aspeed_gpio_irq_chip = {
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
+static void aspeed_g4_reg_bit_set(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg, bool val)
+{
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ void __iomem *addr = aspeed_gpio_g4_bank_reg(gpio, bank, reg);
+ u32 temp;
+
+ if (reg == reg_val)
+ temp = gpio->dcache[GPIO_BANK(offset)];
+ else
+ temp = ioread32(addr);
+
+ if (val)
+ temp |= GPIO_BIT(offset);
+ else
+ temp &= ~GPIO_BIT(offset);
+
+ if (reg == reg_val)
+ gpio->dcache[GPIO_BANK(offset)] = temp;
+ iowrite32(temp, addr);
+}
+
+static bool aspeed_g4_reg_bit_get(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg)
+{
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ void __iomem *addr = aspeed_gpio_g4_bank_reg(gpio, bank, reg);
+
+ return !!(ioread32(addr) & GPIO_BIT(offset));
+}
+
+static int aspeed_g4_reg_bank_get(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg)
+{
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ void __iomem *addr = aspeed_gpio_g4_bank_reg(gpio, bank, reg);
+
+ if (reg == reg_rdata || reg == reg_irq_status)
+ return ioread32(addr);
+ else
+ return -EOPNOTSUPP;
+}
+
+static void aspeed_g4_privilege_ctrl(struct aspeed_gpio *gpio, unsigned int offset, int cmdsrc)
+{
+ /*
+ * The command source register is only valid in bits 0, 8, 16, and 24, so we use
+ * (offset & ~(0x7)) to ensure that reg_bits_set always targets a valid bit.
+ */
+ /* Source 1 first to avoid illegal 11 combination */
+ aspeed_g4_reg_bit_set(gpio, offset & ~(0x7), reg_cmdsrc1, !!(cmdsrc & BIT(1)));
+ /* Then Source 0 */
+ aspeed_g4_reg_bit_set(gpio, offset & ~(0x7), reg_cmdsrc0, !!(cmdsrc & BIT(0)));
+}
+
+static void aspeed_g4_privilege_init(struct aspeed_gpio *gpio)
+{
+ u32 i;
+
+ /* Switch all command sources to the ARM by default */
+ for (i = 0; i < DIV_ROUND_UP(gpio->chip.ngpio, 32); i++) {
+ aspeed_g4_privilege_ctrl(gpio, (i << 5) + 0, GPIO_CMDSRC_ARM);
+ aspeed_g4_privilege_ctrl(gpio, (i << 5) + 8, GPIO_CMDSRC_ARM);
+ aspeed_g4_privilege_ctrl(gpio, (i << 5) + 16, GPIO_CMDSRC_ARM);
+ aspeed_g4_privilege_ctrl(gpio, (i << 5) + 24, GPIO_CMDSRC_ARM);
+ }
+}
+
+static bool aspeed_g4_copro_request(struct aspeed_gpio *gpio, unsigned int offset)
+{
+ if (!copro_ops || !gpio->cf_copro_bankmap)
+ return false;
+ if (!gpio->cf_copro_bankmap[offset >> 3])
+ return false;
+ if (!copro_ops->request_access)
+ return false;
+
+ /* Pause the coprocessor */
+ copro_ops->request_access(copro_data);
+
+ /* Change command source back to ARM */
+ aspeed_g4_privilege_ctrl(gpio, offset, GPIO_CMDSRC_ARM);
+
+ /* Update cache */
+ gpio->dcache[GPIO_BANK(offset)] = aspeed_g4_reg_bank_get(gpio, offset, reg_rdata);
+
+ return true;
+}
+
+static void aspeed_g4_copro_release(struct aspeed_gpio *gpio, unsigned int offset)
+{
+ if (!copro_ops || !gpio->cf_copro_bankmap)
+ return;
+ if (!gpio->cf_copro_bankmap[offset >> 3])
+ return;
+ if (!copro_ops->release_access)
+ return;
+
+ /* Change command source back to ColdFire */
+ aspeed_g4_privilege_ctrl(gpio, offset, GPIO_CMDSRC_COLDFIRE);
+
+ /* Restart the coprocessor */
+ copro_ops->release_access(copro_data);
+}
+
+static const struct aspeed_gpio_llops aspeed_g4_llops = {
+ .reg_bit_set = aspeed_g4_reg_bit_set,
+ .reg_bit_get = aspeed_g4_reg_bit_get,
+ .reg_bank_get = aspeed_g4_reg_bank_get,
+ .privilege_ctrl = aspeed_g4_privilege_ctrl,
+ .privilege_init = aspeed_g4_privilege_init,
+ .copro_request = aspeed_g4_copro_request,
+ .copro_release = aspeed_g4_copro_release,
+};
+
+static void aspeed_g7_reg_bit_set(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg, bool val)
+{
+ u32 mask = aspeed_gpio_g7_reg_mask(reg);
+ void __iomem *addr = gpio->base + GPIO_G7_CTRL_REG_OFFSET(offset);
+ u32 write_val;
+
+ if (mask) {
+ write_val = (ioread32(addr) & ~(mask)) | field_prep(mask, val);
+ iowrite32(write_val, addr);
+ }
+}
+
+static bool aspeed_g7_reg_bit_get(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg)
+{
+ u32 mask = aspeed_gpio_g7_reg_mask(reg);
+ void __iomem *addr;
+
+ addr = gpio->base + GPIO_G7_CTRL_REG_OFFSET(offset);
+ if (reg == reg_val)
+ mask = GPIO_G7_CTRL_IN_DATA;
+
+ if (mask)
+ return field_get(mask, ioread32(addr));
+ else
+ return 0;
+}
+
+static int aspeed_g7_reg_bank_get(struct aspeed_gpio *gpio, unsigned int offset,
+ const enum aspeed_gpio_reg reg)
+{
+ void __iomem *addr;
+
+ if (reg == reg_irq_status) {
+ addr = gpio->base + GPIO_G7_IRQ_STS_OFFSET(offset >> 5);
+ return ioread32(addr);
+ } else {
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct aspeed_gpio_llops aspeed_g7_llops = {
+ .reg_bit_set = aspeed_g7_reg_bit_set,
+ .reg_bit_get = aspeed_g7_reg_bit_get,
+ .reg_bank_get = aspeed_g7_reg_bank_get,
+ .privilege_ctrl = NULL,
+ .privilege_init = NULL,
+ .copro_request = NULL,
+ .copro_release = NULL,
+};
+
/*
* Any banks not specified in a struct aspeed_bank_props array are assumed to
* have the properties:
@@ -1131,7 +1245,14 @@ static const struct aspeed_bank_props ast2400_bank_props[] = {
static const struct aspeed_gpio_config ast2400_config =
/* 220 for simplicity, really 216 with two 4-GPIO holes, four at end */
- { .nr_gpios = 220, .props = ast2400_bank_props, };
+ {
+ .nr_gpios = 220,
+ .props = ast2400_bank_props,
+ .llops = &aspeed_g4_llops,
+ .debounce_timers_array = debounce_timers,
+ .debounce_timers_num = ARRAY_SIZE(debounce_timers),
+ .require_dcache = true,
+ };
static const struct aspeed_bank_props ast2500_bank_props[] = {
/* input output */
@@ -1143,7 +1264,14 @@ static const struct aspeed_bank_props ast2500_bank_props[] = {
static const struct aspeed_gpio_config ast2500_config =
/* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
- { .nr_gpios = 232, .props = ast2500_bank_props, };
+ {
+ .nr_gpios = 232,
+ .props = ast2500_bank_props,
+ .llops = &aspeed_g4_llops,
+ .debounce_timers_array = debounce_timers,
+ .debounce_timers_num = ARRAY_SIZE(debounce_timers),
+ .require_dcache = true,
+ };
static const struct aspeed_bank_props ast2600_bank_props[] = {
/* input output */
@@ -1159,17 +1287,48 @@ static const struct aspeed_gpio_config ast2600_config =
* We expect ngpio being set in the device tree and this is a fallback
* option.
*/
- { .nr_gpios = 208, .props = ast2600_bank_props, };
+ {
+ .nr_gpios = 208,
+ .props = ast2600_bank_props,
+ .llops = &aspeed_g4_llops,
+ .debounce_timers_array = debounce_timers,
+ .debounce_timers_num = ARRAY_SIZE(debounce_timers),
+ .require_dcache = true,
+ };
+
+static const struct aspeed_bank_props ast2700_bank_props[] = {
+ /* input output */
+ { 1, 0x0fffffff, 0x0fffffff }, /* E/F/G/H, 4-GPIO hole */
+ { 6, 0x00ffffff, 0x00ff0000 }, /* Y/Z/AA */
+ {},
+};
+
+static const struct aspeed_gpio_config ast2700_config =
+ /*
+ * ast2700 has two controllers one with 212 GPIOs and one with 16 GPIOs.
+ * 216 for simplicity, actual number is 212 (4-GPIO hole in GPIOH)
+ * We expect ngpio being set in the device tree and this is a fallback
+ * option.
+ */
+ {
+ .nr_gpios = 216,
+ .props = ast2700_bank_props,
+ .llops = &aspeed_g7_llops,
+ .debounce_timers_array = g7_debounce_timers,
+ .debounce_timers_num = ARRAY_SIZE(g7_debounce_timers),
+ .require_dcache = false,
+ };
static const struct of_device_id aspeed_gpio_of_table[] = {
{ .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, },
{ .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, },
{ .compatible = "aspeed,ast2600-gpio", .data = &ast2600_config, },
+ { .compatible = "aspeed,ast2700-gpio", .data = &ast2700_config, },
{}
};
MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
-static int __init aspeed_gpio_probe(struct platform_device *pdev)
+static int aspeed_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *gpio_id;
struct gpio_irq_chip *girq;
@@ -1202,6 +1361,10 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->config = gpio_id->data;
+ if (!gpio->config->llops->reg_bit_set || !gpio->config->llops->reg_bit_get ||
+ !gpio->config->llops->reg_bank_get)
+ return -EINVAL;
+
gpio->chip.parent = &pdev->dev;
err = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpio);
gpio->chip.ngpio = (u16) ngpio;
@@ -1218,27 +1381,23 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1;
- /* Allocate a cache of the output registers */
- banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
- gpio->dcache = devm_kcalloc(&pdev->dev,
- banks, sizeof(u32), GFP_KERNEL);
- if (!gpio->dcache)
- return -ENOMEM;
-
- /*
- * Populate it with initial values read from the HW and switch
- * all command sources to the ARM by default
- */
- for (i = 0; i < banks; i++) {
- const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
- void __iomem *addr = bank_reg(gpio, bank, reg_rdata);
- gpio->dcache[i] = ioread32(addr);
- aspeed_gpio_change_cmd_source(gpio, bank, 0, GPIO_CMDSRC_ARM);
- aspeed_gpio_change_cmd_source(gpio, bank, 1, GPIO_CMDSRC_ARM);
- aspeed_gpio_change_cmd_source(gpio, bank, 2, GPIO_CMDSRC_ARM);
- aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM);
+ if (gpio->config->require_dcache) {
+ /* Allocate a cache of the output registers */
+ banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
+ gpio->dcache = devm_kcalloc(&pdev->dev, banks, sizeof(u32), GFP_KERNEL);
+ if (!gpio->dcache)
+ return -ENOMEM;
+ /*
+ * Populate it with initial values read from the HW
+ */
+ for (i = 0; i < banks; i++)
+ gpio->dcache[i] =
+ gpio->config->llops->reg_bank_get(gpio, (i << 5), reg_rdata);
}
+ if (gpio->config->llops->privilege_init)
+ gpio->config->llops->privilege_init(gpio);
+
/* Set up an irqchip */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -1270,13 +1429,14 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
}
static struct platform_driver aspeed_gpio_driver = {
+ .probe = aspeed_gpio_probe,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = aspeed_gpio_of_table,
},
};
-module_platform_driver_probe(aspeed_gpio_driver, aspeed_gpio_probe);
+module_platform_driver(aspeed_gpio_driver);
MODULE_DESCRIPTION("Aspeed GPIO Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index 5762e517338e..491b529d25f8 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -751,7 +751,7 @@ static struct platform_driver brcmstb_gpio_driver = {
.pm = &brcmstb_gpio_pm_ops,
},
.probe = brcmstb_gpio_probe,
- .remove_new = brcmstb_gpio_remove,
+ .remove = brcmstb_gpio_remove,
.shutdown = brcmstb_gpio_shutdown,
};
module_platform_driver(brcmstb_gpio_driver);
diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c
index 1b8ffd0ddab6..e9dd2564c54f 100644
--- a/drivers/gpio/gpio-cadence.c
+++ b/drivers/gpio/gpio-cadence.c
@@ -277,7 +277,7 @@ static struct platform_driver cdns_gpio_driver = {
.of_match_table = cdns_of_ids,
},
.probe = cdns_gpio_probe,
- .remove_new = cdns_gpio_remove,
+ .remove = cdns_gpio_remove,
};
module_platform_driver(cdns_gpio_driver);
diff --git a/drivers/gpio/gpio-cgbc.c b/drivers/gpio/gpio-cgbc.c
new file mode 100644
index 000000000000..9213faa11522
--- /dev/null
+++ b/drivers/gpio/gpio-cgbc.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Congatec Board Controller GPIO driver
+ *
+ * Copyright (C) 2024 Bootlin
+ * Author: Thomas Richard <thomas.richard@bootlin.com>
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/mfd/cgbc.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#define CGBC_GPIO_NGPIO 14
+
+#define CGBC_GPIO_CMD_GET 0x64
+#define CGBC_GPIO_CMD_SET 0x65
+#define CGBC_GPIO_CMD_DIR_GET 0x66
+#define CGBC_GPIO_CMD_DIR_SET 0x67
+
+struct cgbc_gpio_data {
+ struct gpio_chip chip;
+ struct cgbc_device_data *cgbc;
+ struct mutex lock;
+};
+
+static int cgbc_gpio_cmd(struct cgbc_device_data *cgbc,
+ u8 cmd0, u8 cmd1, u8 cmd2, u8 *value)
+{
+ u8 cmd[3] = {cmd0, cmd1, cmd2};
+
+ return cgbc_command(cgbc, cmd, sizeof(cmd), value, 1, NULL);
+}
+
+static int cgbc_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
+ struct cgbc_device_data *cgbc = gpio->cgbc;
+ int ret;
+ u8 val;
+
+ scoped_guard(mutex, &gpio->lock)
+ ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_GET, (offset > 7) ? 1 : 0, 0, &val);
+
+ offset %= 8;
+
+ if (ret)
+ return ret;
+ else
+ return (int)(val & (u8)BIT(offset));
+}
+
+static void __cgbc_gpio_set(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
+ struct cgbc_device_data *cgbc = gpio->cgbc;
+ u8 val;
+ int ret;
+
+ ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_GET, (offset > 7) ? 1 : 0, 0, &val);
+ if (ret)
+ return;
+
+ if (value)
+ val |= BIT(offset % 8);
+ else
+ val &= ~(BIT(offset % 8));
+
+ cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_SET, (offset > 7) ? 1 : 0, val, &val);
+}
+
+static void cgbc_gpio_set(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
+
+ scoped_guard(mutex, &gpio->lock)
+ __cgbc_gpio_set(chip, offset, value);
+}
+
+static int cgbc_gpio_direction_set(struct gpio_chip *chip,
+ unsigned int offset, int direction)
+{
+ struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
+ struct cgbc_device_data *cgbc = gpio->cgbc;
+ int ret;
+ u8 val;
+
+ ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_GET, (offset > 7) ? 1 : 0, 0, &val);
+ if (ret)
+ goto end;
+
+ if (direction == GPIO_LINE_DIRECTION_IN)
+ val &= ~(BIT(offset % 8));
+ else
+ val |= BIT(offset % 8);
+
+ ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_SET, (offset > 7) ? 1 : 0, val, &val);
+
+end:
+ return ret;
+}
+
+static int cgbc_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
+
+ guard(mutex)(&gpio->lock);
+ return cgbc_gpio_direction_set(chip, offset, GPIO_LINE_DIRECTION_IN);
+}
+
+static int cgbc_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
+
+ guard(mutex)(&gpio->lock);
+
+ __cgbc_gpio_set(chip, offset, value);
+ return cgbc_gpio_direction_set(chip, offset, GPIO_LINE_DIRECTION_OUT);
+}
+
+static int cgbc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
+ struct cgbc_device_data *cgbc = gpio->cgbc;
+ int ret;
+ u8 val;
+
+ scoped_guard(mutex, &gpio->lock)
+ ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_GET, (offset > 7) ? 1 : 0, 0, &val);
+
+ if (ret)
+ return ret;
+
+ if (val & BIT(offset % 8))
+ return GPIO_LINE_DIRECTION_OUT;
+ else
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int cgbc_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct cgbc_device_data *cgbc = dev_get_drvdata(dev->parent);
+ struct cgbc_gpio_data *gpio;
+ struct gpio_chip *chip;
+ int ret;
+
+ gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
+ if (!gpio)
+ return -ENOMEM;
+
+ gpio->cgbc = cgbc;
+
+ platform_set_drvdata(pdev, gpio);
+
+ chip = &gpio->chip;
+ chip->label = dev_name(&pdev->dev);
+ chip->owner = THIS_MODULE;
+ chip->parent = dev;
+ chip->base = -1;
+ chip->direction_input = cgbc_gpio_direction_input;
+ chip->direction_output = cgbc_gpio_direction_output;
+ chip->get_direction = cgbc_gpio_get_direction;
+ chip->get = cgbc_gpio_get;
+ chip->set = cgbc_gpio_set;
+ chip->ngpio = CGBC_GPIO_NGPIO;
+
+ ret = devm_mutex_init(dev, &gpio->lock);
+ if (ret)
+ return ret;
+
+ ret = devm_gpiochip_add_data(dev, chip, gpio);
+ if (ret)
+ return dev_err_probe(dev, ret, "Could not register GPIO chip\n");
+
+ return 0;
+}
+
+static struct platform_driver cgbc_gpio_driver = {
+ .driver = {
+ .name = "cgbc-gpio",
+ },
+ .probe = cgbc_gpio_probe,
+};
+
+module_platform_driver(cgbc_gpio_driver);
+
+MODULE_DESCRIPTION("Congatec Board Controller GPIO Driver");
+MODULE_AUTHOR("Thomas Richard <thomas.richard@bootlin.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cgbc-gpio");
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 76b58c70b257..8c033e8cf3c9 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -15,7 +15,6 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
-#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/property.h>
@@ -159,14 +158,13 @@ static int davinci_gpio_probe(struct platform_device *pdev)
unsigned int ngpio, nbank, nirq, gpio_unbanked;
struct davinci_gpio_controller *chips;
struct device *dev = &pdev->dev;
- struct device_node *dn = dev_of_node(dev);
/*
* The gpio banks conceptually expose a segmented bitmap,
* and "ngpio" is one more than the largest zero-based
* bit index that's valid.
*/
- ret = of_property_read_u32(dn, "ti,ngpio", &ngpio);
+ ret = device_property_read_u32(dev, "ti,ngpio", &ngpio);
if (ret)
return dev_err_probe(dev, ret, "Failed to get the number of GPIOs\n");
if (ngpio == 0)
@@ -177,8 +175,8 @@ static int davinci_gpio_probe(struct platform_device *pdev)
* interrupts is equal to number of gpios else all are banked so
* number of interrupts is equal to number of banks(each with 16 gpios)
*/
- ret = of_property_read_u32(dn, "ti,davinci-gpio-unbanked",
- &gpio_unbanked);
+ ret = device_property_read_u32(dev, "ti,davinci-gpio-unbanked",
+ &gpio_unbanked);
if (ret)
return dev_err_probe(dev, ret, "Failed to get the unbanked GPIOs property\n");
@@ -662,7 +660,7 @@ static struct platform_driver davinci_gpio_driver = {
.driver = {
.name = "davinci_gpio",
.pm = pm_sleep_ptr(&davinci_gpio_dev_pm_ops),
- .of_match_table = of_match_ptr(davinci_gpio_ids),
+ .of_match_table = davinci_gpio_ids,
},
};
diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c
index 7ead1f51128a..596da59d4b13 100644
--- a/drivers/gpio/gpio-dln2.c
+++ b/drivers/gpio/gpio-dln2.c
@@ -512,7 +512,7 @@ static void dln2_gpio_remove(struct platform_device *pdev)
static struct platform_driver dln2_gpio_driver = {
.driver.name = "dln2-gpio",
.probe = dln2_gpio_probe,
- .remove_new = dln2_gpio_remove,
+ .remove = dln2_gpio_remove,
};
module_platform_driver(dln2_gpio_driver);
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 798235791f70..43b667b41f5d 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -571,7 +571,6 @@ static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode,
static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
{
- struct fwnode_handle *fwnode;
struct dwapb_platform_data *pdata;
struct dwapb_port_property *pp;
int nports;
@@ -592,7 +591,7 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
pdata->nports = nports;
i = 0;
- device_for_each_child_node(dev, fwnode) {
+ device_for_each_child_node_scoped(dev, fwnode) {
pp = &pdata->properties[i++];
pp->fwnode = fwnode;
@@ -600,7 +599,6 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
pp->idx >= DWAPB_MAX_PORTS) {
dev_err(dev,
"missing/invalid port index for port%d\n", i);
- fwnode_handle_put(fwnode);
return ERR_PTR(-EINVAL);
}
@@ -694,6 +692,7 @@ static const struct acpi_device_id dwapb_acpi_match[] = {
{"HISI0181", GPIO_REG_OFFSET_V1},
{"APMC0D07", GPIO_REG_OFFSET_V1},
{"APMC0D81", GPIO_REG_OFFSET_V2},
+ {"FUJI200A", GPIO_REG_OFFSET_V1},
{ }
};
MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match);
diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
index 2dd0e46c42ad..d4bf8d187e16 100644
--- a/drivers/gpio/gpio-eic-sprd.c
+++ b/drivers/gpio/gpio-eic-sprd.c
@@ -10,8 +10,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/notifier.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/spinlock.h>
/* EIC registers definition */
@@ -617,7 +617,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
u16 num_banks = 0;
int ret, i;
- pdata = of_device_get_match_data(dev);
+ pdata = device_get_match_data(dev);
if (!pdata) {
dev_err(dev, "No matching driver data found.\n");
return -EINVAL;
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index ab798c848215..58d2464c07bc 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -249,7 +249,7 @@ static void ep93xx_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip gpio_eic_irq_chip = {
diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 5170fe7599cd..d5909a4f0433 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -99,11 +99,13 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
+ unsigned int bit_value = value ? BIT(bit) : 0;
- if (value)
- regmap_set_bits(exar_gpio->regmap, addr, BIT(bit));
- else
- regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
+ /*
+ * regmap_write_bits() forces value to be written when an external
+ * pull up/down might otherwise indicate value was already set.
+ */
+ regmap_write_bits(exar_gpio->regmap, addr, BIT(bit), bit_value);
}
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c
index 97d345b59352..c35eaa2851d8 100644
--- a/drivers/gpio/gpio-ftgpio010.c
+++ b/drivers/gpio/gpio-ftgpio010.c
@@ -253,18 +253,13 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- g->clk = devm_clk_get(dev, NULL);
- if (!IS_ERR(g->clk)) {
- ret = clk_prepare_enable(g->clk);
- if (ret)
- return ret;
- } else if (PTR_ERR(g->clk) == -EPROBE_DEFER) {
+ g->clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(g->clk) && PTR_ERR(g->clk) == -EPROBE_DEFER)
/*
* Percolate deferrals, for anything else,
* just live without the clocking.
*/
return PTR_ERR(g->clk);
- }
ret = bgpio_init(&g->gc, dev, 4,
g->base + GPIO_DATA_IN,
@@ -273,10 +268,9 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
g->base + GPIO_DIR,
NULL,
0);
- if (ret) {
- dev_err(dev, "unable to init generic GPIO\n");
- goto dis_clk;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "unable to init generic GPIO\n");
+
g->gc.label = dev_name(dev);
g->gc.base = -1;
g->gc.parent = dev;
@@ -293,10 +287,9 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
GFP_KERNEL);
- if (!girq->parents) {
- ret = -ENOMEM;
- goto dis_clk;
- }
+ if (!girq->parents)
+ return -ENOMEM;
+
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
girq->parents[0] = irq;
@@ -309,26 +302,7 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
/* Clear any use of debounce */
writel(0x0, g->base + GPIO_DEBOUNCE_EN);
- ret = devm_gpiochip_add_data(dev, &g->gc, g);
- if (ret)
- goto dis_clk;
-
- platform_set_drvdata(pdev, g);
- dev_info(dev, "FTGPIO010 @%p registered\n", g->base);
-
- return 0;
-
-dis_clk:
- clk_disable_unprepare(g->clk);
-
- return ret;
-}
-
-static void ftgpio_gpio_remove(struct platform_device *pdev)
-{
- struct ftgpio_gpio *g = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(g->clk);
+ return devm_gpiochip_add_data(dev, &g->gc, g);
}
static const struct of_device_id ftgpio_gpio_of_match[] = {
@@ -350,6 +324,5 @@ static struct platform_driver ftgpio_gpio_driver = {
.of_match_table = ftgpio_gpio_of_match,
},
.probe = ftgpio_gpio_probe,
- .remove_new = ftgpio_gpio_remove,
};
builtin_platform_driver(ftgpio_gpio_driver);
diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
index 017c7170eb57..169f33c41c59 100644
--- a/drivers/gpio/gpio-grgpio.c
+++ b/drivers/gpio/gpio-grgpio.c
@@ -16,20 +16,20 @@
* Contributors: Andreas Larsson <andreas@gaisler.com>
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/gpio/driver.h>
-#include <linux/slab.h>
+#include <linux/bitops.h>
#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
-#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
#define GRGPIO_MAX_NGPIO 32
@@ -318,6 +318,13 @@ static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq)
raw_spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags);
}
+static void grgpio_irq_domain_remove(void *data)
+{
+ struct irq_domain *domain = data;
+
+ irq_domain_remove(domain);
+}
+
static const struct irq_domain_ops grgpio_irq_domain_ops = {
.map = grgpio_irq_map,
.unmap = grgpio_irq_unmap,
@@ -328,6 +335,7 @@ static const struct irq_domain_ops grgpio_irq_domain_ops = {
static int grgpio_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
+ struct device *dev = &ofdev->dev;
void __iomem *regs;
struct gpio_chip *gc;
struct grgpio_priv *priv;
@@ -337,7 +345,7 @@ static int grgpio_probe(struct platform_device *ofdev)
int size;
int i;
- priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -346,28 +354,31 @@ static int grgpio_probe(struct platform_device *ofdev)
return PTR_ERR(regs);
gc = &priv->gc;
- err = bgpio_init(gc, &ofdev->dev, 4, regs + GRGPIO_DATA,
+ err = bgpio_init(gc, dev, 4, regs + GRGPIO_DATA,
regs + GRGPIO_OUTPUT, NULL, regs + GRGPIO_DIR, NULL,
BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (err) {
- dev_err(&ofdev->dev, "bgpio_init() failed\n");
+ dev_err(dev, "bgpio_init() failed\n");
return err;
}
priv->regs = regs;
priv->imask = gc->read_reg(regs + GRGPIO_IMASK);
- priv->dev = &ofdev->dev;
+ priv->dev = dev;
gc->owner = THIS_MODULE;
gc->to_irq = grgpio_to_irq;
- gc->label = devm_kasprintf(&ofdev->dev, GFP_KERNEL, "%pOF", np);
+ gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
+ if (!gc->label)
+ return -ENOMEM;
+
gc->base = -1;
err = of_property_read_u32(np, "nbits", &prop);
if (err || prop <= 0 || prop > GRGPIO_MAX_NGPIO) {
gc->ngpio = GRGPIO_MAX_NGPIO;
- dev_dbg(&ofdev->dev,
- "No or invalid nbits property: assume %d\n", gc->ngpio);
+ dev_dbg(dev, "No or invalid nbits property: assume %d\n",
+ gc->ngpio);
} else {
gc->ngpio = prop;
}
@@ -379,7 +390,7 @@ static int grgpio_probe(struct platform_device *ofdev)
irqmap = (s32 *)of_get_property(np, "irqmap", &size);
if (irqmap) {
if (size < gc->ngpio) {
- dev_err(&ofdev->dev,
+ dev_err(dev,
"irqmap shorter than ngpio (%d < %d)\n",
size, gc->ngpio);
return -EINVAL;
@@ -389,10 +400,15 @@ static int grgpio_probe(struct platform_device *ofdev)
&grgpio_irq_domain_ops,
priv);
if (!priv->domain) {
- dev_err(&ofdev->dev, "Could not add irq domain\n");
+ dev_err(dev, "Could not add irq domain\n");
return -EINVAL;
}
+ err = devm_add_action_or_reset(dev, grgpio_irq_domain_remove,
+ priv->domain);
+ if (err)
+ return err;
+
for (i = 0; i < gc->ngpio; i++) {
struct grgpio_lirq *lirq;
int ret;
@@ -415,32 +431,18 @@ static int grgpio_probe(struct platform_device *ofdev)
}
}
- platform_set_drvdata(ofdev, priv);
-
- err = gpiochip_add_data(gc, priv);
+ err = devm_gpiochip_add_data(dev, gc, priv);
if (err) {
- dev_err(&ofdev->dev, "Could not add gpiochip\n");
- if (priv->domain)
- irq_domain_remove(priv->domain);
+ dev_err(dev, "Could not add gpiochip\n");
return err;
}
- dev_info(&ofdev->dev, "regs=0x%p, base=%d, ngpio=%d, irqs=%s\n",
+ dev_info(dev, "regs=0x%p, base=%d, ngpio=%d, irqs=%s\n",
priv->regs, gc->base, gc->ngpio, priv->domain ? "on" : "off");
return 0;
}
-static void grgpio_remove(struct platform_device *ofdev)
-{
- struct grgpio_priv *priv = platform_get_drvdata(ofdev);
-
- gpiochip_remove(&priv->gc);
-
- if (priv->domain)
- irq_domain_remove(priv->domain);
-}
-
static const struct of_device_id grgpio_match[] = {
{.name = "GAISLER_GPIO"},
{.name = "01_01a"},
@@ -455,7 +457,6 @@ static struct platform_driver grgpio_driver = {
.of_match_table = grgpio_match,
},
.probe = grgpio_probe,
- .remove_new = grgpio_remove,
};
module_platform_driver(grgpio_driver);
diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c
index 1bcfc1835dae..0580f6712bea 100644
--- a/drivers/gpio/gpio-hlwd.c
+++ b/drivers/gpio/gpio-hlwd.c
@@ -210,7 +210,7 @@ static void hlwd_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
struct hlwd_gpio *hlwd =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
- seq_printf(p, dev_name(hlwd->dev));
+ seq_puts(p, dev_name(hlwd->dev));
}
static const struct irq_chip hlwd_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c
index dfec9fbfc7a9..d67b912d884d 100644
--- a/drivers/gpio/gpio-ljca.c
+++ b/drivers/gpio/gpio-ljca.c
@@ -420,8 +420,14 @@ static int ljca_gpio_probe(struct auxiliary_device *auxdev,
if (!ljca_gpio->connect_mode)
return -ENOMEM;
- mutex_init(&ljca_gpio->irq_lock);
- mutex_init(&ljca_gpio->trans_lock);
+ ret = devm_mutex_init(&auxdev->dev, &ljca_gpio->irq_lock);
+ if (ret)
+ return ret;
+
+ ret = devm_mutex_init(&auxdev->dev, &ljca_gpio->trans_lock);
+ if (ret)
+ return ret;
+
ljca_gpio->gc.direction_input = ljca_gpio_direction_input;
ljca_gpio->gc.direction_output = ljca_gpio_direction_output;
ljca_gpio->gc.get_direction = ljca_gpio_get_direction;
@@ -453,11 +459,8 @@ static int ljca_gpio_probe(struct auxiliary_device *auxdev,
INIT_WORK(&ljca_gpio->work, ljca_gpio_async);
ret = gpiochip_add_data(&ljca_gpio->gc, ljca_gpio);
- if (ret) {
+ if (ret)
ljca_unregister_event_cb(ljca);
- mutex_destroy(&ljca_gpio->irq_lock);
- mutex_destroy(&ljca_gpio->trans_lock);
- }
return ret;
}
@@ -469,8 +472,6 @@ static void ljca_gpio_remove(struct auxiliary_device *auxdev)
gpiochip_remove(&ljca_gpio->gc);
ljca_unregister_event_cb(ljca_gpio->ljca);
cancel_work_sync(&ljca_gpio->work);
- mutex_destroy(&ljca_gpio->irq_lock);
- mutex_destroy(&ljca_gpio->trans_lock);
}
static const struct auxiliary_device_id ljca_gpio_id_table[] = {
diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c
index e7c0ef6e54fa..2cf9fb4637a2 100644
--- a/drivers/gpio/gpio-lpc18xx.c
+++ b/drivers/gpio/gpio-lpc18xx.c
@@ -388,7 +388,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_gpio_match);
static struct platform_driver lpc18xx_gpio_driver = {
.probe = lpc18xx_gpio_probe,
- .remove_new = lpc18xx_gpio_remove,
+ .remove = lpc18xx_gpio_remove,
.driver = {
.name = "lpc18xx-gpio",
.of_match_table = lpc18xx_gpio_match,
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
index 701795b9d329..e688c13c8cc3 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -165,7 +165,10 @@ int __max730x_probe(struct max7301 *ts)
pdata = dev_get_platdata(dev);
- mutex_init(&ts->lock);
+ ret = devm_mutex_init(ts->dev, &ts->lock);
+ if (ret)
+ return ret;
+
dev_set_drvdata(dev, ts);
/* Power up the chip and disable IRQ output */
@@ -206,17 +209,11 @@ int __max730x_probe(struct max7301 *ts)
int offset = (i - 1) * 4 + j;
ret = max7301_direction_input(&ts->chip, offset);
if (ret)
- goto exit_destroy;
+ return ret;
}
}
- ret = gpiochip_add_data(&ts->chip, ts);
- if (!ret)
- return ret;
-
-exit_destroy:
- mutex_destroy(&ts->lock);
- return ret;
+ return devm_gpiochip_add_data(ts->dev, &ts->chip, ts);
}
EXPORT_SYMBOL_GPL(__max730x_probe);
@@ -226,8 +223,6 @@ void __max730x_remove(struct device *dev)
/* Power down the chip and disable IRQ output */
ts->write(dev, 0x04, 0x00);
- gpiochip_remove(&ts->chip);
- mutex_destroy(&ts->lock);
}
EXPORT_SYMBOL_GPL(__max730x_remove);
diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
index ccbb63c21d6f..7ee891ef6905 100644
--- a/drivers/gpio/gpio-mb86s7x.c
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -145,8 +145,6 @@ static int mb86s70_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
irq = platform_get_irq(to_platform_device(gc->parent), index);
if (irq < 0)
return irq;
- if (irq == 0)
- break;
if (irq_get_irq_data(irq)->hwirq == offset)
return irq;
}
@@ -227,7 +225,7 @@ static struct platform_driver mb86s70_gpio_driver = {
.acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids),
},
.probe = mb86s70_gpio_probe,
- .remove_new = mb86s70_gpio_remove,
+ .remove = mb86s70_gpio_remove,
};
module_platform_driver(mb86s70_gpio_driver);
diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c
index a035a9bcb57c..3ccd2cb35b9c 100644
--- a/drivers/gpio/gpio-menz127.c
+++ b/drivers/gpio/gpio-menz127.c
@@ -127,6 +127,13 @@ static int men_z127_set_config(struct gpio_chip *gc, unsigned offset,
return -ENOTSUPP;
}
+static void men_z127_release_mem(void *data)
+{
+ struct resource *res = data;
+
+ mcb_release_mem(res);
+}
+
static int men_z127_probe(struct mcb_device *mdev,
const struct mcb_device_id *id)
{
@@ -140,17 +147,19 @@ static int men_z127_probe(struct mcb_device *mdev,
return -ENOMEM;
men_z127_gpio->mem = mcb_request_mem(mdev, dev_name(dev));
- if (IS_ERR(men_z127_gpio->mem)) {
- dev_err(dev, "failed to request device memory");
- return PTR_ERR(men_z127_gpio->mem);
- }
+ if (IS_ERR(men_z127_gpio->mem))
+ return dev_err_probe(dev, PTR_ERR(men_z127_gpio->mem),
+ "failed to request device memory");
- men_z127_gpio->reg_base = ioremap(men_z127_gpio->mem->start,
- resource_size(men_z127_gpio->mem));
- if (men_z127_gpio->reg_base == NULL) {
- ret = -ENXIO;
- goto err_release;
- }
+ ret = devm_add_action_or_reset(dev, men_z127_release_mem,
+ men_z127_gpio->mem);
+ if (ret)
+ return ret;
+
+ men_z127_gpio->reg_base = devm_ioremap(dev, men_z127_gpio->mem->start,
+ resource_size(men_z127_gpio->mem));
+ if (men_z127_gpio->reg_base == NULL)
+ return -ENXIO;
mcb_set_drvdata(mdev, men_z127_gpio);
@@ -161,34 +170,16 @@ static int men_z127_probe(struct mcb_device *mdev,
men_z127_gpio->reg_base + MEN_Z127_GPIODR,
NULL, 0);
if (ret)
- goto err_unmap;
+ return ret;
men_z127_gpio->gc.set_config = men_z127_set_config;
- ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
- if (ret) {
- dev_err(dev, "failed to register MEN 16Z127 GPIO controller");
- goto err_unmap;
- }
-
- dev_info(dev, "MEN 16Z127 GPIO driver registered");
+ ret = devm_gpiochip_add_data(dev, &men_z127_gpio->gc, men_z127_gpio);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to register MEN 16Z127 GPIO controller");
return 0;
-
-err_unmap:
- iounmap(men_z127_gpio->reg_base);
-err_release:
- mcb_release_mem(men_z127_gpio->mem);
- return ret;
-}
-
-static void men_z127_remove(struct mcb_device *mdev)
-{
- struct men_z127_gpio *men_z127_gpio = mcb_get_drvdata(mdev);
-
- gpiochip_remove(&men_z127_gpio->gc);
- iounmap(men_z127_gpio->reg_base);
- mcb_release_mem(men_z127_gpio->mem);
}
static const struct mcb_device_id men_z127_ids[] = {
@@ -202,7 +193,6 @@ static struct mcb_driver men_z127_driver = {
.name = "z127-gpio",
},
.probe = men_z127_probe,
- .remove = men_z127_remove,
.id_table = men_z127_ids,
};
module_mcb_driver(men_z127_driver);
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index 421d7e3a6c66..cd20604f26de 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -78,24 +78,25 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
if (retval)
return retval;
- retval = pcim_iomap_regions(pdev, BIT(1) | BIT(0), pci_name(pdev));
- if (retval)
- return dev_err_probe(dev, retval, "I/O memory mapping error\n");
-
- base = pcim_iomap_table(pdev)[1];
+ base = pcim_iomap_region(pdev, 1, pci_name(pdev));
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base), "I/O memory mapping error\n");
irq_base = readl(base + 0 * sizeof(u32));
gpio_base = readl(base + 1 * sizeof(u32));
/* Release the IO mapping, since we already get the info from BAR1 */
- pcim_iounmap_regions(pdev, BIT(1));
+ pcim_iounmap_region(pdev, 1);
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = dev;
- priv->reg_base = pcim_iomap_table(pdev)[0];
+ priv->reg_base = pcim_iomap_region(pdev, 0, pci_name(pdev));
+ if (IS_ERR(priv->reg_base))
+ return dev_err_probe(dev, PTR_ERR(priv->reg_base),
+ "I/O memory mapping error\n");
priv->pin_info.pin_ranges = mrfld_gpio_ranges;
priv->pin_info.nranges = ARRAY_SIZE(mrfld_gpio_ranges);
diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c
index 6abe01bc39c3..6f3dda6b635f 100644
--- a/drivers/gpio/gpio-mlxbf2.c
+++ b/drivers/gpio/gpio-mlxbf2.c
@@ -331,7 +331,7 @@ static void mlxbf2_gpio_irq_print_chip(struct irq_data *irqd,
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);
- seq_printf(p, dev_name(gs->dev));
+ seq_puts(p, dev_name(gs->dev));
}
static const struct irq_chip mlxbf2_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c
index e855c68c981b..14ae25783438 100644
--- a/drivers/gpio/gpio-mm-lantiq.c
+++ b/drivers/gpio/gpio-mm-lantiq.c
@@ -136,7 +136,7 @@ MODULE_DEVICE_TABLE(of, ltq_mm_match);
static struct platform_driver ltq_mm_driver = {
.probe = ltq_mm_probe,
- .remove_new = ltq_mm_remove,
+ .remove = ltq_mm_remove,
.driver = {
.name = "gpio-mm-ltq",
.of_match_table = ltq_mm_match,
diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
index a199dce3394a..091d96f2d682 100644
--- a/drivers/gpio/gpio-mpc5200.c
+++ b/drivers/gpio/gpio-mpc5200.c
@@ -183,7 +183,7 @@ static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
.of_match_table = mpc52xx_wkup_gpiochip_match,
},
.probe = mpc52xx_wkup_gpiochip_probe,
- .remove_new = mpc52xx_gpiochip_remove,
+ .remove = mpc52xx_gpiochip_remove,
};
/*
@@ -336,7 +336,7 @@ static struct platform_driver mpc52xx_simple_gpiochip_driver = {
.of_match_table = mpc52xx_simple_gpiochip_match,
},
.probe = mpc52xx_simple_gpiochip_probe,
- .remove_new = mpc52xx_gpiochip_remove,
+ .remove = mpc52xx_gpiochip_remove,
};
static struct platform_driver * const drivers[] = {
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index 685ec31db409..24417c3247b0 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -15,7 +15,6 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@@ -300,14 +299,14 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = {
static int mpc8xxx_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
- struct mpc8xxx_gpio_chip *mpc8xxx_gc;
- struct gpio_chip *gc;
const struct mpc8xxx_gpio_devtype *devtype = NULL;
+ struct mpc8xxx_gpio_chip *mpc8xxx_gc;
+ struct device *dev = &pdev->dev;
struct fwnode_handle *fwnode;
+ struct gpio_chip *gc;
int ret;
- mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
+ mpc8xxx_gc = devm_kzalloc(dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
if (!mpc8xxx_gc)
return -ENOMEM;
@@ -320,32 +319,28 @@ static int mpc8xxx_probe(struct platform_device *pdev)
return PTR_ERR(mpc8xxx_gc->regs);
gc = &mpc8xxx_gc->gc;
- gc->parent = &pdev->dev;
-
- if (device_property_read_bool(&pdev->dev, "little-endian")) {
- ret = bgpio_init(gc, &pdev->dev, 4,
- mpc8xxx_gc->regs + GPIO_DAT,
- NULL, NULL,
- mpc8xxx_gc->regs + GPIO_DIR, NULL,
- BGPIOF_BIG_ENDIAN);
+ gc->parent = dev;
+
+ if (device_property_read_bool(dev, "little-endian")) {
+ ret = bgpio_init(gc, dev, 4, mpc8xxx_gc->regs + GPIO_DAT,
+ NULL, NULL, mpc8xxx_gc->regs + GPIO_DIR,
+ NULL, BGPIOF_BIG_ENDIAN);
if (ret)
return ret;
- dev_dbg(&pdev->dev, "GPIO registers are LITTLE endian\n");
+ dev_dbg(dev, "GPIO registers are LITTLE endian\n");
} else {
- ret = bgpio_init(gc, &pdev->dev, 4,
- mpc8xxx_gc->regs + GPIO_DAT,
- NULL, NULL,
- mpc8xxx_gc->regs + GPIO_DIR, NULL,
- BGPIOF_BIG_ENDIAN
+ ret = bgpio_init(gc, dev, 4, mpc8xxx_gc->regs + GPIO_DAT,
+ NULL, NULL, mpc8xxx_gc->regs + GPIO_DIR,
+ NULL, BGPIOF_BIG_ENDIAN
| BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (ret)
return ret;
- dev_dbg(&pdev->dev, "GPIO registers are BIG endian\n");
+ dev_dbg(dev, "GPIO registers are BIG endian\n");
}
mpc8xxx_gc->direction_output = gc->direction_output;
- devtype = device_get_match_data(&pdev->dev);
+ devtype = device_get_match_data(dev);
if (!devtype)
devtype = &mpc8xxx_gpio_devtype_default;
@@ -370,10 +365,10 @@ static int mpc8xxx_probe(struct platform_device *pdev)
* associated input enable must be set (GPIOxGPIE[IEn]=1) to propagate
* the port value to the GPIO Data Register.
*/
- fwnode = dev_fwnode(&pdev->dev);
- if (of_device_is_compatible(np, "fsl,qoriq-gpio") ||
- of_device_is_compatible(np, "fsl,ls1028a-gpio") ||
- of_device_is_compatible(np, "fsl,ls1088a-gpio") ||
+ fwnode = dev_fwnode(dev);
+ if (device_is_compatible(dev, "fsl,qoriq-gpio") ||
+ device_is_compatible(dev, "fsl,ls1028a-gpio") ||
+ device_is_compatible(dev, "fsl,ls1088a-gpio") ||
is_acpi_node(fwnode)) {
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
/* Also, latch state of GPIOs configured as output by bootloader. */
@@ -381,9 +376,9 @@ static int mpc8xxx_probe(struct platform_device *pdev)
gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR);
}
- ret = devm_gpiochip_add_data(&pdev->dev, gc, mpc8xxx_gc);
+ ret = devm_gpiochip_add_data(dev, gc, mpc8xxx_gc);
if (ret) {
- dev_err(&pdev->dev,
+ dev_err(dev,
"GPIO chip registration failed with status %d\n", ret);
return ret;
}
@@ -404,18 +399,17 @@ static int mpc8xxx_probe(struct platform_device *pdev)
gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff);
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0);
- ret = devm_request_irq(&pdev->dev, mpc8xxx_gc->irqn,
+ ret = devm_request_irq(dev, mpc8xxx_gc->irqn,
mpc8xxx_gpio_irq_cascade,
IRQF_NO_THREAD | IRQF_SHARED, "gpio-cascade",
mpc8xxx_gc);
if (ret) {
- dev_err(&pdev->dev,
- "failed to devm_request_irq(%d), ret = %d\n",
+ dev_err(dev, "failed to devm_request_irq(%d), ret = %d\n",
mpc8xxx_gc->irqn, ret);
goto err;
}
- device_init_wakeup(&pdev->dev, true);
+ device_init_wakeup(dev, true);
return 0;
err:
@@ -466,7 +460,7 @@ MODULE_DEVICE_TABLE(acpi, gpio_acpi_ids);
static struct platform_driver mpc8xxx_plat_driver = {
.probe = mpc8xxx_probe,
- .remove_new = mpc8xxx_remove,
+ .remove = mpc8xxx_remove,
.driver = {
.name = "gpio-mpc8xxx",
.of_match_table = mpc8xxx_gpio_ids,
diff --git a/drivers/gpio/gpio-mpfs.c b/drivers/gpio/gpio-mpfs.c
new file mode 100644
index 000000000000..561a961c97a6
--- /dev/null
+++ b/drivers/gpio/gpio-mpfs.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: (GPL-2.0)
+/*
+ * Microchip PolarFire SoC (MPFS) GPIO controller driver
+ *
+ * Copyright (c) 2018-2024 Microchip Technology Inc. and its subsidiaries
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+
+#define MPFS_GPIO_CTRL(i) (0x4 * (i))
+#define MPFS_MAX_NUM_GPIO 32
+#define MPFS_GPIO_EN_INT 3
+#define MPFS_GPIO_EN_OUT_BUF BIT(2)
+#define MPFS_GPIO_EN_IN BIT(1)
+#define MPFS_GPIO_EN_OUT BIT(0)
+#define MPFS_GPIO_DIR_MASK GENMASK(2, 0)
+
+#define MPFS_GPIO_TYPE_INT_EDGE_BOTH 0x80
+#define MPFS_GPIO_TYPE_INT_EDGE_NEG 0x60
+#define MPFS_GPIO_TYPE_INT_EDGE_POS 0x40
+#define MPFS_GPIO_TYPE_INT_LEVEL_LOW 0x20
+#define MPFS_GPIO_TYPE_INT_LEVEL_HIGH 0x00
+#define MPFS_GPIO_TYPE_INT_MASK GENMASK(7, 5)
+#define MPFS_IRQ_REG 0x80
+
+#define MPFS_INP_REG 0x84
+#define COREGPIO_INP_REG 0x90
+#define MPFS_OUTP_REG 0x88
+#define COREGPIO_OUTP_REG 0xA0
+
+struct mpfs_gpio_reg_offsets {
+ u8 inp;
+ u8 outp;
+};
+
+struct mpfs_gpio_chip {
+ struct regmap *regs;
+ const struct mpfs_gpio_reg_offsets *offsets;
+ struct gpio_chip gc;
+};
+
+static const struct regmap_config mpfs_gpio_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+};
+
+static int mpfs_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio_index)
+{
+ struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
+
+ regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index),
+ MPFS_GPIO_DIR_MASK, MPFS_GPIO_EN_IN);
+
+ return 0;
+}
+
+static int mpfs_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio_index, int value)
+{
+ struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
+
+ regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index),
+ MPFS_GPIO_DIR_MASK, MPFS_GPIO_EN_IN);
+ regmap_update_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, BIT(gpio_index),
+ value << gpio_index);
+
+ return 0;
+}
+
+static int mpfs_gpio_get_direction(struct gpio_chip *gc,
+ unsigned int gpio_index)
+{
+ struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
+ unsigned int gpio_cfg;
+
+ regmap_read(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index), &gpio_cfg);
+ if (gpio_cfg & MPFS_GPIO_EN_IN)
+ return GPIO_LINE_DIRECTION_IN;
+
+ return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int mpfs_gpio_get(struct gpio_chip *gc, unsigned int gpio_index)
+{
+ struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
+
+ if (mpfs_gpio_get_direction(gc, gpio_index) == GPIO_LINE_DIRECTION_OUT)
+ return regmap_test_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, BIT(gpio_index));
+ else
+ return regmap_test_bits(mpfs_gpio->regs, mpfs_gpio->offsets->inp, BIT(gpio_index));
+}
+
+static void mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int value)
+{
+ struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
+
+ mpfs_gpio_get(gc, gpio_index);
+
+ regmap_update_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, BIT(gpio_index),
+ value << gpio_index);
+
+ mpfs_gpio_get(gc, gpio_index);
+}
+
+static int mpfs_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mpfs_gpio_chip *mpfs_gpio;
+ struct clk *clk;
+ void __iomem *base;
+ int ngpios;
+
+ mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL);
+ if (!mpfs_gpio)
+ return -ENOMEM;
+
+ mpfs_gpio->offsets = device_get_match_data(&pdev->dev);
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base), "failed to ioremap memory resource\n");
+
+ mpfs_gpio->regs = devm_regmap_init_mmio(dev, base, &mpfs_gpio_regmap_config);
+ if (IS_ERR(mpfs_gpio->regs))
+ return dev_err_probe(dev, PTR_ERR(mpfs_gpio->regs),
+ "failed to initialise regmap\n");
+
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk), "failed to get and enable clock\n");
+
+ ngpios = MPFS_MAX_NUM_GPIO;
+ device_property_read_u32(dev, "ngpios", &ngpios);
+ if (ngpios > MPFS_MAX_NUM_GPIO)
+ ngpios = MPFS_MAX_NUM_GPIO;
+
+ mpfs_gpio->gc.direction_input = mpfs_gpio_direction_input;
+ mpfs_gpio->gc.direction_output = mpfs_gpio_direction_output;
+ mpfs_gpio->gc.get_direction = mpfs_gpio_get_direction;
+ mpfs_gpio->gc.get = mpfs_gpio_get;
+ mpfs_gpio->gc.set = mpfs_gpio_set;
+ mpfs_gpio->gc.base = -1;
+ mpfs_gpio->gc.ngpio = ngpios;
+ mpfs_gpio->gc.label = dev_name(dev);
+ mpfs_gpio->gc.parent = dev;
+ mpfs_gpio->gc.owner = THIS_MODULE;
+
+ return devm_gpiochip_add_data(dev, &mpfs_gpio->gc, mpfs_gpio);
+}
+
+static const struct mpfs_gpio_reg_offsets mpfs_reg_offsets = {
+ .inp = MPFS_INP_REG,
+ .outp = MPFS_OUTP_REG,
+};
+
+static const struct mpfs_gpio_reg_offsets coregpio_reg_offsets = {
+ .inp = COREGPIO_INP_REG,
+ .outp = COREGPIO_OUTP_REG,
+};
+
+static const struct of_device_id mpfs_gpio_of_ids[] = {
+ {
+ .compatible = "microchip,mpfs-gpio",
+ .data = &mpfs_reg_offsets,
+ }, {
+ .compatible = "microchip,coregpio-rtl-v3",
+ .data = &coregpio_reg_offsets,
+ },
+ { /* end of list */ }
+};
+
+static struct platform_driver mpfs_gpio_driver = {
+ .probe = mpfs_gpio_probe,
+ .driver = {
+ .name = "microchip,mpfs-gpio",
+ .of_match_table = mpfs_gpio_of_ids,
+ },
+};
+builtin_platform_driver(mpfs_gpio_driver);
diff --git a/drivers/gpio/gpio-mpsse.c b/drivers/gpio/gpio-mpsse.c
new file mode 100644
index 000000000000..3ea32c5e33d1
--- /dev/null
+++ b/drivers/gpio/gpio-mpsse.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * FTDI MPSSE GPIO support
+ *
+ * Based on code by Anatolij Gustschin
+ *
+ * Copyright (C) 2024 Mary Strodl <mstrodl@csh.rit.edu>
+ */
+
+#include <linux/cleanup.h>
+#include <linux/gpio/driver.h>
+#include <linux/mutex.h>
+#include <linux/usb.h>
+
+struct mpsse_priv {
+ struct gpio_chip gpio;
+ struct usb_device *udev; /* USB device encompassing all MPSSEs */
+ struct usb_interface *intf; /* USB interface for this MPSSE */
+ u8 intf_id; /* USB interface number for this MPSSE */
+ struct work_struct irq_work; /* polling work thread */
+ struct mutex irq_mutex; /* lock over irq_data */
+ atomic_t irq_type[16]; /* pin -> edge detection type */
+ atomic_t irq_enabled;
+ int id;
+
+ u8 gpio_outputs[2]; /* Output states for GPIOs [L, H] */
+ u8 gpio_dir[2]; /* Directions for GPIOs [L, H] */
+
+ u8 *bulk_in_buf; /* Extra recv buffer to grab status bytes */
+
+ struct usb_endpoint_descriptor *bulk_in;
+ struct usb_endpoint_descriptor *bulk_out;
+
+ struct mutex io_mutex; /* sync I/O with disconnect */
+};
+
+struct bulk_desc {
+ bool tx; /* direction of bulk transfer */
+ u8 *data; /* input (tx) or output (rx) */
+ int len; /* Length of `data` if tx, or length of */
+ /* Data to read if rx */
+ int len_actual; /* Length successfully transferred */
+ int timeout;
+};
+
+static const struct usb_device_id gpio_mpsse_table[] = {
+ { USB_DEVICE(0x0c52, 0xa064) }, /* SeaLevel Systems, Inc. */
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, gpio_mpsse_table);
+
+static DEFINE_IDA(gpio_mpsse_ida);
+
+/* MPSSE commands */
+#define SET_BITS_CMD 0x80
+#define GET_BITS_CMD 0x81
+
+#define SET_BITMODE_REQUEST 0x0B
+#define MODE_MPSSE (2 << 8)
+#define MODE_RESET 0
+
+/* Arbitrarily decided. This could probably be much less */
+#define MPSSE_WRITE_TIMEOUT 5000
+#define MPSSE_READ_TIMEOUT 5000
+
+/* 1 millisecond, also pretty arbitrary */
+#define MPSSE_POLL_INTERVAL 1000
+
+static int mpsse_bulk_xfer(struct usb_interface *intf, struct bulk_desc *desc)
+{
+ struct mpsse_priv *priv = usb_get_intfdata(intf);
+ struct usb_device *udev = priv->udev;
+ unsigned int pipe;
+ int ret;
+
+ if (desc->tx)
+ pipe = usb_sndbulkpipe(udev, priv->bulk_out->bEndpointAddress);
+ else
+ pipe = usb_rcvbulkpipe(udev, priv->bulk_in->bEndpointAddress);
+
+ ret = usb_bulk_msg(udev, pipe, desc->data, desc->len,
+ &desc->len_actual, desc->timeout);
+ if (ret)
+ dev_dbg(&udev->dev, "mpsse: bulk transfer failed: %d\n", ret);
+
+ return ret;
+}
+
+static int mpsse_write(struct usb_interface *intf,
+ u8 *buf, size_t len)
+{
+ int ret;
+ struct bulk_desc desc;
+
+ desc.len_actual = 0;
+ desc.tx = true;
+ desc.data = buf;
+ desc.len = len;
+ desc.timeout = MPSSE_WRITE_TIMEOUT;
+
+ ret = mpsse_bulk_xfer(intf, &desc);
+
+ return ret;
+}
+
+static int mpsse_read(struct usb_interface *intf, u8 *buf, size_t len)
+{
+ int ret;
+ struct bulk_desc desc;
+ struct mpsse_priv *priv = usb_get_intfdata(intf);
+
+ desc.len_actual = 0;
+ desc.tx = false;
+ desc.data = priv->bulk_in_buf;
+ /* Device sends 2 additional status bytes, read len + 2 */
+ desc.len = min_t(size_t, len + 2, usb_endpoint_maxp(priv->bulk_in));
+ desc.timeout = MPSSE_READ_TIMEOUT;
+
+ ret = mpsse_bulk_xfer(intf, &desc);
+ if (ret)
+ return ret;
+
+ /* Did we get enough data? */
+ if (desc.len_actual < desc.len)
+ return -EIO;
+
+ memcpy(buf, desc.data + 2, desc.len_actual - 2);
+
+ return ret;
+}
+
+static int gpio_mpsse_set_bank(struct mpsse_priv *priv, u8 bank)
+{
+ int ret;
+ u8 tx_buf[3] = {
+ SET_BITS_CMD | (bank << 1),
+ priv->gpio_outputs[bank],
+ priv->gpio_dir[bank],
+ };
+
+ ret = mpsse_write(priv->intf, tx_buf, 3);
+
+ return ret;
+}
+
+static int gpio_mpsse_get_bank(struct mpsse_priv *priv, u8 bank)
+{
+ int ret;
+ u8 buf = GET_BITS_CMD | (bank << 1);
+
+ ret = mpsse_write(priv->intf, &buf, 1);
+ if (ret)
+ return ret;
+
+ ret = mpsse_read(priv->intf, &buf, 1);
+ if (ret)
+ return ret;
+
+ return buf;
+}
+
+static void gpio_mpsse_set_multiple(struct gpio_chip *chip, unsigned long *mask,
+ unsigned long *bits)
+{
+ unsigned long i, bank, bank_mask, bank_bits;
+ int ret;
+ struct mpsse_priv *priv = gpiochip_get_data(chip);
+
+ guard(mutex)(&priv->io_mutex);
+ for_each_set_clump8(i, bank_mask, mask, chip->ngpio) {
+ bank = i / 8;
+
+ if (bank_mask) {
+ bank_bits = bitmap_get_value8(bits, i);
+ /* Zero out pins we want to change */
+ priv->gpio_outputs[bank] &= ~bank_mask;
+ /* Set pins we care about */
+ priv->gpio_outputs[bank] |= bank_bits & bank_mask;
+
+ ret = gpio_mpsse_set_bank(priv, bank);
+ if (ret)
+ dev_err(&priv->intf->dev,
+ "Couldn't set values for bank %ld!",
+ bank);
+ }
+ }
+}
+
+static int gpio_mpsse_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+ unsigned long *bits)
+{
+ unsigned long i, bank, bank_mask;
+ int ret;
+ struct mpsse_priv *priv = gpiochip_get_data(chip);
+
+ guard(mutex)(&priv->io_mutex);
+ for_each_set_clump8(i, bank_mask, mask, chip->ngpio) {
+ bank = i / 8;
+
+ if (bank_mask) {
+ ret = gpio_mpsse_get_bank(priv, bank);
+ if (ret < 0)
+ return ret;
+
+ bitmap_set_value8(bits, ret & bank_mask, i);
+ }
+ }
+
+ return 0;
+}
+
+static int gpio_mpsse_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ int err;
+ unsigned long mask = 0, bits = 0;
+
+ __set_bit(offset, &mask);
+ err = gpio_mpsse_get_multiple(chip, &mask, &bits);
+ if (err)
+ return err;
+
+ /* == is not guaranteed to give 1 if true */
+ if (bits)
+ return 1;
+ else
+ return 0;
+}
+
+static void gpio_mpsse_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ unsigned long mask = 0, bits = 0;
+
+ __set_bit(offset, &mask);
+ if (value)
+ __set_bit(offset, &bits);
+
+ gpio_mpsse_set_multiple(chip, &mask, &bits);
+}
+
+static int gpio_mpsse_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct mpsse_priv *priv = gpiochip_get_data(chip);
+ int bank = (offset & 8) >> 3;
+ int bank_offset = offset & 7;
+
+ scoped_guard(mutex, &priv->io_mutex)
+ priv->gpio_dir[bank] |= BIT(bank_offset);
+
+ gpio_mpsse_gpio_set(chip, offset, value);
+
+ return 0;
+}
+
+static int gpio_mpsse_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mpsse_priv *priv = gpiochip_get_data(chip);
+ int bank = (offset & 8) >> 3;
+ int bank_offset = offset & 7;
+
+ guard(mutex)(&priv->io_mutex);
+ priv->gpio_dir[bank] &= ~BIT(bank_offset);
+ gpio_mpsse_set_bank(priv, bank);
+
+ return 0;
+}
+
+static int gpio_mpsse_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ int ret;
+ int bank = (offset & 8) >> 3;
+ int bank_offset = offset & 7;
+ struct mpsse_priv *priv = gpiochip_get_data(chip);
+
+ guard(mutex)(&priv->io_mutex);
+ /* MPSSE directions are inverted */
+ if (priv->gpio_dir[bank] & BIT(bank_offset))
+ ret = GPIO_LINE_DIRECTION_OUT;
+ else
+ ret = GPIO_LINE_DIRECTION_IN;
+
+ return ret;
+}
+
+static void gpio_mpsse_poll(struct work_struct *work)
+{
+ unsigned long pin_mask, pin_states, flags;
+ int irq_enabled, offset, err, value, fire_irq,
+ irq, old_value[16], irq_type[16];
+ struct mpsse_priv *priv = container_of(work, struct mpsse_priv,
+ irq_work);
+
+ for (offset = 0; offset < priv->gpio.ngpio; ++offset)
+ old_value[offset] = -1;
+
+ while ((irq_enabled = atomic_read(&priv->irq_enabled))) {
+ usleep_range(MPSSE_POLL_INTERVAL, MPSSE_POLL_INTERVAL + 1000);
+ /* Cleanup will trigger at the end of the loop */
+ guard(mutex)(&priv->irq_mutex);
+
+ pin_mask = 0;
+ pin_states = 0;
+ for (offset = 0; offset < priv->gpio.ngpio; ++offset) {
+ irq_type[offset] = atomic_read(&priv->irq_type[offset]);
+ if (irq_type[offset] != IRQ_TYPE_NONE &&
+ irq_enabled & BIT(offset))
+ pin_mask |= BIT(offset);
+ else
+ old_value[offset] = -1;
+ }
+
+ err = gpio_mpsse_get_multiple(&priv->gpio, &pin_mask,
+ &pin_states);
+ if (err) {
+ dev_err_ratelimited(&priv->intf->dev,
+ "Error polling!\n");
+ continue;
+ }
+
+ /* Check each value */
+ for (offset = 0; offset < priv->gpio.ngpio; ++offset) {
+ if (old_value[offset] == -1)
+ continue;
+
+ fire_irq = 0;
+ value = pin_states & BIT(offset);
+
+ switch (irq_type[offset]) {
+ case IRQ_TYPE_EDGE_RISING:
+ fire_irq = value > old_value[offset];
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ fire_irq = value < old_value[offset];
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ fire_irq = value != old_value[offset];
+ break;
+ }
+ if (!fire_irq)
+ continue;
+
+ irq = irq_find_mapping(priv->gpio.irq.domain,
+ offset);
+ local_irq_save(flags);
+ generic_handle_irq(irq);
+ local_irq_disable();
+ local_irq_restore(flags);
+ }
+
+ /* Sync back values so we can refer to them next tick */
+ for (offset = 0; offset < priv->gpio.ngpio; ++offset)
+ if (irq_type[offset] != IRQ_TYPE_NONE &&
+ irq_enabled & BIT(offset))
+ old_value[offset] = pin_states & BIT(offset);
+ }
+}
+
+static int gpio_mpsse_set_irq_type(struct irq_data *irqd, unsigned int type)
+{
+ int offset;
+ struct mpsse_priv *priv = irq_data_get_irq_chip_data(irqd);
+
+ offset = irqd->hwirq;
+ atomic_set(&priv->irq_type[offset], type & IRQ_TYPE_EDGE_BOTH);
+
+ return 0;
+}
+
+static void gpio_mpsse_irq_disable(struct irq_data *irqd)
+{
+ struct mpsse_priv *priv = irq_data_get_irq_chip_data(irqd);
+
+ atomic_and(~BIT(irqd->hwirq), &priv->irq_enabled);
+ gpiochip_disable_irq(&priv->gpio, irqd->hwirq);
+}
+
+static void gpio_mpsse_irq_enable(struct irq_data *irqd)
+{
+ struct mpsse_priv *priv = irq_data_get_irq_chip_data(irqd);
+
+ gpiochip_enable_irq(&priv->gpio, irqd->hwirq);
+ /* If no-one else was using the IRQ, enable it */
+ if (!atomic_fetch_or(BIT(irqd->hwirq), &priv->irq_enabled)) {
+ INIT_WORK(&priv->irq_work, gpio_mpsse_poll);
+ schedule_work(&priv->irq_work);
+ }
+}
+
+static const struct irq_chip gpio_mpsse_irq_chip = {
+ .name = "gpio-mpsse-irq",
+ .irq_enable = gpio_mpsse_irq_enable,
+ .irq_disable = gpio_mpsse_irq_disable,
+ .irq_set_type = gpio_mpsse_set_irq_type,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static void gpio_mpsse_ida_remove(void *data)
+{
+ struct mpsse_priv *priv = data;
+
+ ida_free(&gpio_mpsse_ida, priv->id);
+}
+
+static int gpio_mpsse_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct mpsse_priv *priv;
+ struct device *dev;
+ int err;
+
+ dev = &interface->dev;
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->udev = usb_get_dev(interface_to_usbdev(interface));
+ priv->intf = interface;
+ priv->intf_id = interface->cur_altsetting->desc.bInterfaceNumber;
+
+ priv->id = ida_alloc(&gpio_mpsse_ida, GFP_KERNEL);
+ if (priv->id < 0)
+ return priv->id;
+
+ err = devm_add_action_or_reset(dev, gpio_mpsse_ida_remove, priv);
+ if (err)
+ return err;
+
+ err = devm_mutex_init(dev, &priv->io_mutex);
+ if (err)
+ return err;
+
+ err = devm_mutex_init(dev, &priv->irq_mutex);
+ if (err)
+ return err;
+
+ priv->gpio.label = devm_kasprintf(dev, GFP_KERNEL,
+ "gpio-mpsse.%d.%d",
+ priv->id, priv->intf_id);
+ if (!priv->gpio.label)
+ return -ENOMEM;
+
+ priv->gpio.owner = THIS_MODULE;
+ priv->gpio.parent = interface->usb_dev;
+ priv->gpio.get_direction = gpio_mpsse_get_direction;
+ priv->gpio.direction_input = gpio_mpsse_direction_input;
+ priv->gpio.direction_output = gpio_mpsse_direction_output;
+ priv->gpio.get = gpio_mpsse_gpio_get;
+ priv->gpio.set = gpio_mpsse_gpio_set;
+ priv->gpio.get_multiple = gpio_mpsse_get_multiple;
+ priv->gpio.set_multiple = gpio_mpsse_set_multiple;
+ priv->gpio.base = -1;
+ priv->gpio.ngpio = 16;
+ priv->gpio.offset = priv->intf_id * priv->gpio.ngpio;
+ priv->gpio.can_sleep = 1;
+
+ err = usb_find_common_endpoints(interface->cur_altsetting,
+ &priv->bulk_in, &priv->bulk_out,
+ NULL, NULL);
+ if (err)
+ return err;
+
+ priv->bulk_in_buf = devm_kmalloc(dev, usb_endpoint_maxp(priv->bulk_in),
+ GFP_KERNEL);
+ if (!priv->bulk_in_buf)
+ return -ENOMEM;
+
+ usb_set_intfdata(interface, priv);
+
+ /* Reset mode, needed to correctly enter MPSSE mode */
+ err = usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ SET_BITMODE_REQUEST,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ MODE_RESET, priv->intf_id + 1, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (err)
+ return err;
+
+ /* Enter MPSSE mode */
+ err = usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ SET_BITMODE_REQUEST,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ MODE_MPSSE, priv->intf_id + 1, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (err)
+ return err;
+
+ gpio_irq_chip_set_chip(&priv->gpio.irq, &gpio_mpsse_irq_chip);
+
+ priv->gpio.irq.parent_handler = NULL;
+ priv->gpio.irq.num_parents = 0;
+ priv->gpio.irq.parents = NULL;
+ priv->gpio.irq.default_type = IRQ_TYPE_NONE;
+ priv->gpio.irq.handler = handle_simple_irq;
+
+ err = devm_gpiochip_add_data(dev, &priv->gpio, priv);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static void gpio_mpsse_disconnect(struct usb_interface *intf)
+{
+ struct mpsse_priv *priv = usb_get_intfdata(intf);
+
+ priv->intf = NULL;
+ usb_set_intfdata(intf, NULL);
+ usb_put_dev(priv->udev);
+}
+
+static struct usb_driver gpio_mpsse_driver = {
+ .name = "gpio-mpsse",
+ .probe = gpio_mpsse_probe,
+ .disconnect = gpio_mpsse_disconnect,
+ .id_table = gpio_mpsse_table,
+};
+
+module_usb_driver(gpio_mpsse_driver);
+
+MODULE_AUTHOR("Mary Strodl <mstrodl@csh.rit.edu>");
+MODULE_DESCRIPTION("MPSSE GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 8cfd3a89c018..5ffb332e9849 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -794,8 +794,8 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
u32 set;
if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
- int ret = of_property_read_u32(dev->of_node,
- "marvell,pwm-offset", &offset);
+ int ret = device_property_read_u32(dev, "marvell,pwm-offset",
+ &offset);
if (ret < 0)
return 0;
} else {
@@ -1106,7 +1106,7 @@ static int mvebu_gpio_probe_syscon(struct platform_device *pdev,
if (IS_ERR(mvchip->regs))
return PTR_ERR(mvchip->regs);
- if (of_property_read_u32(pdev->dev.of_node, "offset", &mvchip->offset))
+ if (device_property_read_u32(&pdev->dev, "offset", &mvchip->offset))
return -EINVAL;
return 0;
@@ -1147,7 +1147,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mvchip);
- if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
+ if (device_property_read_u32(&pdev->dev, "ngpios", &ngpios)) {
dev_err(&pdev->dev, "Missing ngpios OF property\n");
return -ENODEV;
}
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 76d5d87e9681..54c4bfdccf56 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -715,7 +715,7 @@ static void omap_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
- seq_printf(p, dev_name(bank->dev));
+ seq_puts(p, dev_name(bank->dev));
}
static const struct irq_chip omap_gpio_irq_chip = {
@@ -1557,7 +1557,7 @@ static const struct dev_pm_ops gpio_pm_ops = {
static struct platform_driver omap_gpio_driver = {
.probe = omap_gpio_probe,
- .remove_new = omap_gpio_remove,
+ .remove = omap_gpio_remove,
.driver = {
.name = "omap_gpio",
.pm = &gpio_pm_ops,
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 3f2d33ee20cc..272febc3230e 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -815,7 +815,7 @@ static void pca953x_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip pca953x_irq_chip = {
diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c
index 44c0a21b1d1d..64f332c80550 100644
--- a/drivers/gpio/gpio-pci-idio-16.c
+++ b/drivers/gpio/gpio-pci-idio-16.c
@@ -70,24 +70,17 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct device *const dev = &pdev->dev;
int err;
const size_t pci_bar_index = 2;
- const char *const name = pci_name(pdev);
struct idio_16_regmap_config config = {};
void __iomem *regs;
struct regmap *map;
err = pcim_enable_device(pdev);
- if (err) {
- dev_err(dev, "Failed to enable PCI device (%d)\n", err);
- return err;
- }
-
- err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
- if (err) {
- dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
- return err;
- }
+ if (err)
+ return dev_err_probe(dev, err, "Failed to enable PCI device\n");
- regs = pcim_iomap_table(pdev)[pci_bar_index];
+ regs = pcim_iomap_region(pdev, pci_bar_index, pci_name(pdev));
+ if (IS_ERR(regs))
+ return dev_err_probe(dev, PTR_ERR(regs), "Unable to map PCI I/O addresses\n");
map = devm_regmap_init_mmio(dev, regs, &idio_16_regmap_config);
if (IS_ERR(map))
diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c
index 7f7f95ad4343..80c0ba0afa67 100644
--- a/drivers/gpio/gpio-pcie-idio-24.c
+++ b/drivers/gpio/gpio-pcie-idio-24.c
@@ -305,19 +305,16 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct regmap_irq_chip_data *chip_data;
err = pcim_enable_device(pdev);
- if (err) {
- dev_err(dev, "Failed to enable PCI device (%d)\n", err);
- return err;
- }
+ if (err)
+ return dev_err_probe(dev, err, "Failed to enable PCI device\n");
- err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name);
- if (err) {
- dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
- return err;
- }
+ pex8311_regs = pcim_iomap_region(pdev, pci_plx_bar_index, "pex8311");
+ if (IS_ERR(pex8311_regs))
+ return dev_err_probe(dev, PTR_ERR(pex8311_regs), "Unable to map PEX 8311 I/O addresses\n");
- pex8311_regs = pcim_iomap_table(pdev)[pci_plx_bar_index];
- idio_24_regs = pcim_iomap_table(pdev)[pci_bar_index];
+ idio_24_regs = pcim_iomap_region(pdev, pci_bar_index, name);
+ if (IS_ERR(idio_24_regs))
+ return dev_err_probe(dev, PTR_ERR(idio_24_regs), "Unable to map PCIe-IDIO-24 I/O addresses\n");
intcsr_map = devm_regmap_init_mmio(dev, pex8311_regs, &pex8311_intcsr_regmap_config);
if (IS_ERR(intcsr_map))
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index a211a02d4b4a..1c273727ffa3 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -291,7 +291,7 @@ static void pl061_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip pl061_irq_chip = {
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 6159fda38d5d..2ecee3269a0c 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -657,7 +657,7 @@ static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, gpio_rcar_resume);
static struct platform_driver gpio_rcar_device_driver = {
.probe = gpio_rcar_probe,
- .remove_new = gpio_rcar_remove,
+ .remove = gpio_rcar_remove,
.driver = {
.name = "gpio_rcar",
.pm = &gpio_rcar_pm_ops,
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index 365ab947983c..01a3b3dac58b 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -26,9 +26,16 @@
#include "../pinctrl/core.h"
#include "../pinctrl/pinctrl-rockchip.h"
+/*
+ * Version ID Register
+ * Bits [31:24] - Major Version
+ * Bits [23:16] - Minor Version
+ * Bits [15:0] - Revision Number
+ */
#define GPIO_TYPE_V1 (0) /* GPIO Version ID reserved */
-#define GPIO_TYPE_V2 (0x01000C2B) /* GPIO Version ID 0x01000C2B */
-#define GPIO_TYPE_V2_1 (0x0101157C) /* GPIO Version ID 0x0101157C */
+#define GPIO_TYPE_V2 (0x01000C2B)
+#define GPIO_TYPE_V2_1 (0x0101157C)
+#define GPIO_TYPE_V2_2 (0x010219C8)
static const struct rockchip_gpio_regs gpio_regs_v1 = {
.port_dr = 0x00,
@@ -602,7 +609,7 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
* files which don't set the "gpio-ranges" property or systems that
* utilize ACPI the driver has to call gpiochip_add_pin_range().
*/
- if (!of_property_read_bool(bank->of_node, "gpio-ranges")) {
+ if (!of_property_present(bank->of_node, "gpio-ranges")) {
struct device_node *pctlnp = of_get_parent(bank->of_node);
struct pinctrl_dev *pctldev = NULL;
@@ -661,8 +668,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
clk_prepare_enable(bank->clk);
id = readl(bank->reg_base + gpio_regs_v2.version_id);
- /* If not gpio v2, that is default to v1. */
- if (id == GPIO_TYPE_V2 || id == GPIO_TYPE_V2_1) {
+ switch (id) {
+ case GPIO_TYPE_V2:
+ case GPIO_TYPE_V2_1:
+ case GPIO_TYPE_V2_2:
bank->gpio_regs = &gpio_regs_v2;
bank->gpio_type = GPIO_TYPE_V2;
bank->db_clk = of_clk_get(bank->of_node, 1);
@@ -671,9 +680,14 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
clk_disable_unprepare(bank->clk);
return -EINVAL;
}
- } else {
+ break;
+ case GPIO_TYPE_V1:
bank->gpio_regs = &gpio_regs_v1;
bank->gpio_type = GPIO_TYPE_V1;
+ break;
+ default:
+ dev_err(bank->dev, "unsupported version ID: 0x%08x\n", id);
+ return -ENODEV;
}
return 0;
@@ -795,7 +809,7 @@ static const struct of_device_id rockchip_gpio_match[] = {
static struct platform_driver rockchip_gpio_driver = {
.probe = rockchip_gpio_probe,
- .remove_new = rockchip_gpio_remove,
+ .remove = rockchip_gpio_remove,
.driver = {
.name = "rockchip-gpio",
.of_match_table = rockchip_gpio_match,
diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c
index dcca1d7f173e..f387dad81f29 100644
--- a/drivers/gpio/gpio-sim.c
+++ b/drivers/gpio/gpio-sim.c
@@ -520,15 +520,12 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
static int gpio_sim_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct fwnode_handle *swnode;
int ret;
- device_for_each_child_node(dev, swnode) {
+ device_for_each_child_node_scoped(dev, swnode) {
ret = gpio_sim_add_bank(swnode, dev);
- if (ret) {
- fwnode_handle_put(swnode);
+ if (ret)
return ret;
- }
}
return 0;
diff --git a/drivers/gpio/gpio-sloppy-logic-analyzer.c b/drivers/gpio/gpio-sloppy-logic-analyzer.c
index 59a8f3a5c4e4..8cf3b171c599 100644
--- a/drivers/gpio/gpio-sloppy-logic-analyzer.c
+++ b/drivers/gpio/gpio-sloppy-logic-analyzer.c
@@ -313,7 +313,7 @@ MODULE_DEVICE_TABLE(of, gpio_la_poll_of_match);
static struct platform_driver gpio_la_poll_device_driver = {
.probe = gpio_la_poll_probe,
- .remove_new = gpio_la_poll_remove,
+ .remove = gpio_la_poll_remove,
.driver = {
.name = GPIO_LA_NAME,
.of_match_table = gpio_la_poll_of_match,
diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c
index e8c1485b9c73..b6335cde455f 100644
--- a/drivers/gpio/gpio-tb10x.c
+++ b/drivers/gpio/gpio-tb10x.c
@@ -235,7 +235,7 @@ MODULE_DEVICE_TABLE(of, tb10x_gpio_dt_ids);
static struct platform_driver tb10x_gpio_driver = {
.probe = tb10x_gpio_probe,
- .remove_new = tb10x_gpio_remove,
+ .remove = tb10x_gpio_remove,
.driver = {
.name = "tb10x-gpio",
.of_match_table = tb10x_gpio_dt_ids,
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 6d3a39a03f58..9ad286adf263 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -600,7 +600,7 @@ static void tegra_gpio_irq_print_chip(struct irq_data *d, struct seq_file *s)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
- seq_printf(s, dev_name(chip->parent));
+ seq_puts(s, dev_name(chip->parent));
}
static const struct irq_chip tegra_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 1ecb733a5e88..6895b65c86af 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -610,7 +610,7 @@ static void tegra186_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip tegra186_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c
index f2e7e8754d95..5e26eb3adabb 100644
--- a/drivers/gpio/gpio-tqmx86.c
+++ b/drivers/gpio/gpio-tqmx86.c
@@ -275,7 +275,7 @@ static void tqmx86_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- seq_printf(p, gc->label);
+ seq_puts(p, gc->label);
}
static const struct irq_chip tqmx86_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c
index 0f6397b77c9d..5c806140fdf0 100644
--- a/drivers/gpio/gpio-ts4900.c
+++ b/drivers/gpio/gpio-ts4900.c
@@ -8,8 +8,8 @@
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
-#include <linux/of.h>
#include <linux/module.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#define DEFAULT_PIN_NUMBER 32
@@ -142,7 +142,7 @@ static int ts4900_gpio_probe(struct i2c_client *client)
u32 ngpio;
int ret;
- if (of_property_read_u32(client->dev.of_node, "ngpios", &ngpio))
+ if (device_property_read_u32(&client->dev, "ngpios", &ngpio))
ngpio = DEFAULT_PIN_NUMBER;
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
@@ -153,7 +153,7 @@ static int ts4900_gpio_probe(struct i2c_client *client)
priv->gpio_chip.label = "ts4900-gpio";
priv->gpio_chip.ngpio = ngpio;
priv->gpio_chip.parent = &client->dev;
- priv->input_bit = (uintptr_t)of_device_get_match_data(&client->dev);
+ priv->input_bit = (uintptr_t)device_get_match_data(&client->dev);
priv->regmap = devm_regmap_init_i2c(client, &ts4900_regmap_config);
if (IS_ERR(priv->regmap)) {
diff --git a/drivers/gpio/gpio-ts5500.c b/drivers/gpio/gpio-ts5500.c
index 90f8e9e9915e..61cbec5c06a7 100644
--- a/drivers/gpio/gpio-ts5500.c
+++ b/drivers/gpio/gpio-ts5500.c
@@ -433,7 +433,7 @@ static struct platform_driver ts5500_dio_driver = {
.name = "ts5500-dio",
},
.probe = ts5500_dio_probe,
- .remove_new = ts5500_dio_remove,
+ .remove = ts5500_dio_remove,
.id_table = ts5500_dio_ids,
};
diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index da99ba13e82d..d738da8718f9 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -481,7 +481,7 @@ MODULE_DEVICE_TABLE(of, uniphier_gpio_match);
static struct platform_driver uniphier_gpio_driver = {
.probe = uniphier_gpio_probe,
- .remove_new = uniphier_gpio_remove,
+ .remove = uniphier_gpio_remove,
.driver = {
.name = "uniphier-gpio",
.of_match_table = uniphier_gpio_match,
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 27eff741fe9a..c4f34a347cb6 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -15,10 +15,9 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
#define VF610_GPIO_PER_PORT 32
@@ -297,7 +296,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
if (!port)
return -ENOMEM;
- port->sdata = of_device_get_match_data(dev);
+ port->sdata = device_get_match_data(dev);
dual_base = port->sdata->have_dual_base;
diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c
index ebc71ecdb6cf..5bd965c18a46 100644
--- a/drivers/gpio/gpio-visconti.c
+++ b/drivers/gpio/gpio-visconti.c
@@ -142,7 +142,7 @@ static void visconti_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct visconti_gpio *priv = gpiochip_get_data(gc);
- seq_printf(p, dev_name(priv->dev));
+ seq_puts(p, dev_name(priv->dev));
}
static const struct irq_chip visconti_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c
index bd5befa807c3..48b829733b15 100644
--- a/drivers/gpio/gpio-xgene-sb.c
+++ b/drivers/gpio/gpio-xgene-sb.c
@@ -8,20 +8,22 @@
* Quan Nguyen <qnguyen@apm.com>.
*/
-#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
#include <linux/gpio/driver.h>
-#include <linux/acpi.h>
#include "gpiolib-acpi.h"
-/* Common property names */
-#define XGENE_NIRQ_PROPERTY "apm,nr-irqs"
-#define XGENE_NGPIO_PROPERTY "apm,nr-gpios"
-#define XGENE_IRQ_START_PROPERTY "apm,irq-start"
-
#define XGENE_DFLT_MAX_NGPIO 22
#define XGENE_DFLT_MAX_NIRQ 6
#define XGENE_DFLT_IRQ_START_PIN 8
@@ -252,18 +254,17 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev)
/* Retrieve start irq pin, use default if property not found */
priv->irq_start = XGENE_DFLT_IRQ_START_PIN;
- if (!device_property_read_u32(&pdev->dev,
- XGENE_IRQ_START_PROPERTY, &val32))
+ if (!device_property_read_u32(&pdev->dev, "apm,irq-start", &val32))
priv->irq_start = val32;
/* Retrieve number irqs, use default if property not found */
priv->nirq = XGENE_DFLT_MAX_NIRQ;
- if (!device_property_read_u32(&pdev->dev, XGENE_NIRQ_PROPERTY, &val32))
+ if (!device_property_read_u32(&pdev->dev, "apm,nr-irqs", &val32))
priv->nirq = val32;
/* Retrieve number gpio, use default if property not found */
priv->gc.ngpio = XGENE_DFLT_MAX_NGPIO;
- if (!device_property_read_u32(&pdev->dev, XGENE_NGPIO_PROPERTY, &val32))
+ if (!device_property_read_u32(&pdev->dev, "apm,nr-gpios", &val32))
priv->gc.ngpio = val32;
dev_info(&pdev->dev, "Support %d gpios, %d irqs start from pin %d\n",
@@ -305,27 +306,25 @@ static void xgene_gpio_sb_remove(struct platform_device *pdev)
}
static const struct of_device_id xgene_gpio_sb_of_match[] = {
- {.compatible = "apm,xgene-gpio-sb", },
- {},
+ { .compatible = "apm,xgene-gpio-sb" },
+ {}
};
MODULE_DEVICE_TABLE(of, xgene_gpio_sb_of_match);
-#ifdef CONFIG_ACPI
static const struct acpi_device_id xgene_gpio_sb_acpi_match[] = {
- {"APMC0D15", 0},
- {},
+ { "APMC0D15" },
+ {}
};
MODULE_DEVICE_TABLE(acpi, xgene_gpio_sb_acpi_match);
-#endif
static struct platform_driver xgene_gpio_sb_driver = {
.driver = {
.name = "xgene-gpio-sb",
.of_match_table = xgene_gpio_sb_of_match,
- .acpi_match_table = ACPI_PTR(xgene_gpio_sb_acpi_match),
- },
+ .acpi_match_table = xgene_gpio_sb_acpi_match,
+ },
.probe = xgene_gpio_sb_probe,
- .remove_new = xgene_gpio_sb_remove,
+ .remove = xgene_gpio_sb_remove,
};
module_platform_driver(xgene_gpio_sb_driver);
diff --git a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c
index d445eea03687..93544e98ccbd 100644
--- a/drivers/gpio/gpio-xgs-iproc.c
+++ b/drivers/gpio/gpio-xgs-iproc.c
@@ -198,7 +198,7 @@ static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
- seq_printf(p, dev_name(chip->dev));
+ seq_puts(p, dev_name(chip->dev));
}
static const struct irq_chip iproc_gpio_irq_chip = {
@@ -316,7 +316,7 @@ static struct platform_driver bcm_iproc_gpio_driver = {
.of_match_table = bcm_iproc_gpio_of_match,
},
.probe = iproc_gpio_probe,
- .remove_new = iproc_gpio_remove,
+ .remove = iproc_gpio_remove,
};
module_platform_driver(bcm_iproc_gpio_driver);
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index afcf432a1573..c6a8f2c82680 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -15,9 +15,9 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/slab.h>
/* Register Offset Definitions */
@@ -561,9 +561,9 @@ static const struct irq_chip xgpio_irq_chip = {
*/
static int xgpio_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct xgpio_instance *chip;
int status = 0;
- struct device_node *np = pdev->dev.of_node;
u32 is_dual = 0;
u32 width[2];
u32 state[2];
@@ -571,14 +571,14 @@ static int xgpio_probe(struct platform_device *pdev)
struct gpio_irq_chip *girq;
u32 temp;
- chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(pdev, chip);
/* First, check if the device is dual-channel */
- of_property_read_u32(np, "xlnx,is-dual", &is_dual);
+ device_property_read_u32(dev, "xlnx,is-dual", &is_dual);
/* Setup defaults */
memset32(width, 0, ARRAY_SIZE(width));
@@ -586,14 +586,14 @@ static int xgpio_probe(struct platform_device *pdev)
memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir));
/* Update GPIO state shadow register with default value */
- of_property_read_u32(np, "xlnx,dout-default", &state[0]);
- of_property_read_u32(np, "xlnx,dout-default-2", &state[1]);
+ device_property_read_u32(dev, "xlnx,dout-default", &state[0]);
+ device_property_read_u32(dev, "xlnx,dout-default-2", &state[1]);
bitmap_from_arr32(chip->state, state, 64);
/* Update GPIO direction shadow register with default value */
- of_property_read_u32(np, "xlnx,tri-default", &dir[0]);
- of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]);
+ device_property_read_u32(dev, "xlnx,tri-default", &dir[0]);
+ device_property_read_u32(dev, "xlnx,tri-default-2", &dir[1]);
bitmap_from_arr32(chip->dir, dir, 64);
@@ -601,13 +601,13 @@ static int xgpio_probe(struct platform_device *pdev)
* Check device node and parent device node for device width
* and assume default width of 32
*/
- if (of_property_read_u32(np, "xlnx,gpio-width", &width[0]))
+ if (device_property_read_u32(dev, "xlnx,gpio-width", &width[0]))
width[0] = 32;
if (width[0] > 32)
return -EINVAL;
- if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1]))
+ if (is_dual && device_property_read_u32(dev, "xlnx,gpio2-width", &width[1]))
width[1] = 32;
if (width[1] > 32)
@@ -624,7 +624,7 @@ static int xgpio_probe(struct platform_device *pdev)
chip->gc.base = -1;
chip->gc.ngpio = bitmap_weight(chip->hw_map, 64);
- chip->gc.parent = &pdev->dev;
+ chip->gc.parent = dev;
chip->gc.direction_input = xgpio_dir_in;
chip->gc.direction_output = xgpio_dir_out;
chip->gc.get = xgpio_get;
@@ -633,21 +633,21 @@ static int xgpio_probe(struct platform_device *pdev)
chip->gc.free = xgpio_free;
chip->gc.set_multiple = xgpio_set_multiple;
- chip->gc.label = dev_name(&pdev->dev);
+ chip->gc.label = dev_name(dev);
chip->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(chip->regs)) {
- dev_err(&pdev->dev, "failed to ioremap memory resource\n");
+ dev_err(dev, "failed to ioremap memory resource\n");
return PTR_ERR(chip->regs);
}
- chip->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+ chip->clk = devm_clk_get_optional_enabled(dev, NULL);
if (IS_ERR(chip->clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(chip->clk), "input clock not found.\n");
+ return dev_err_probe(dev, PTR_ERR(chip->clk), "input clock not found.\n");
- pm_runtime_get_noresume(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
xgpio_save_regs(chip);
@@ -667,8 +667,7 @@ static int xgpio_probe(struct platform_device *pdev)
gpio_irq_chip_set_chip(girq, &xgpio_irq_chip);
girq->parent_handler = xgpio_irqhandler;
girq->num_parents = 1;
- girq->parents = devm_kcalloc(&pdev->dev, 1,
- sizeof(*girq->parents),
+ girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents) {
status = -ENOMEM;
@@ -679,18 +678,18 @@ static int xgpio_probe(struct platform_device *pdev)
girq->handler = handle_bad_irq;
skip_irq:
- status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
+ status = devm_gpiochip_add_data(dev, &chip->gc, chip);
if (status) {
- dev_err(&pdev->dev, "failed to add GPIO chip\n");
+ dev_err(dev, "failed to add GPIO chip\n");
goto err_pm_put;
}
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
return 0;
err_pm_put:
- pm_runtime_disable(&pdev->dev);
- pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
return status;
}
@@ -703,7 +702,7 @@ MODULE_DEVICE_TABLE(of, xgpio_of_match);
static struct platform_driver xgpio_plat_driver = {
.probe = xgpio_probe,
- .remove_new = xgpio_remove,
+ .remove = xgpio_remove,
.driver = {
.name = "gpio-xilinx",
.of_match_table = xgpio_of_match,
diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c
index 2de61337ad3b..d7230fd83f5d 100644
--- a/drivers/gpio/gpio-zevio.c
+++ b/drivers/gpio/gpio-zevio.c
@@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -169,6 +170,7 @@ static const struct gpio_chip zevio_gpio_chip = {
/* Initialization */
static int zevio_gpio_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct zevio_gpio *controller;
int status, i;
@@ -180,6 +182,10 @@ static int zevio_gpio_probe(struct platform_device *pdev)
controller->chip = zevio_gpio_chip;
controller->chip.parent = &pdev->dev;
+ controller->chip.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", dev_fwnode(dev));
+ if (!controller->chip.label)
+ return -ENOMEM;
+
controller->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(controller->regs))
return dev_err_probe(&pdev->dev, PTR_ERR(controller->regs),
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 1a42336dfc1d..be81fa2b17ab 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -1023,7 +1023,7 @@ static struct platform_driver zynq_gpio_driver = {
.of_match_table = zynq_gpio_of_match,
},
.probe = zynq_gpio_probe,
- .remove_new = zynq_gpio_remove,
+ .remove = zynq_gpio_remove,
};
module_platform_driver(zynq_gpio_driver);
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 78ecd56123a3..1f9fe50bba00 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -1315,9 +1315,8 @@ acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip,
static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
{
struct gpio_chip *chip = achip->chip;
- struct fwnode_handle *fwnode;
- device_for_each_child_node(chip->parent, fwnode) {
+ device_for_each_child_node_scoped(chip->parent, fwnode) {
unsigned long lflags;
enum gpiod_flags dflags;
struct gpio_desc *desc;
@@ -1335,7 +1334,6 @@ static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
ret = gpiod_hog(desc, name, lflags, dflags);
if (ret) {
dev_err(chip->parent, "Failed to hog GPIO\n");
- fwnode_handle_put(fwnode);
return;
}
}
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 78c9d9ed3d68..40f76a90fd7d 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -16,16 +16,15 @@
#include <linux/hte.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
-#include <linux/kernel.h>
#include <linux/kfifo.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/overflow.h>
#include <linux/pinctrl/consumer.h>
#include <linux/poll.h>
-#include <linux/rbtree.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <linux/timekeeping.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
@@ -143,18 +142,22 @@ static int linehandle_validate_flags(u32 flags)
static void linehandle_flags_to_desc_flags(u32 lflags, unsigned long *flagsp)
{
- assign_bit(FLAG_ACTIVE_LOW, flagsp,
+ unsigned long flags = READ_ONCE(*flagsp);
+
+ assign_bit(FLAG_ACTIVE_LOW, &flags,
lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW);
- assign_bit(FLAG_OPEN_DRAIN, flagsp,
+ assign_bit(FLAG_OPEN_DRAIN, &flags,
lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN);
- assign_bit(FLAG_OPEN_SOURCE, flagsp,
+ assign_bit(FLAG_OPEN_SOURCE, &flags,
lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
- assign_bit(FLAG_PULL_UP, flagsp,
+ assign_bit(FLAG_PULL_UP, &flags,
lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP);
- assign_bit(FLAG_PULL_DOWN, flagsp,
+ assign_bit(FLAG_PULL_DOWN, &flags,
lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN);
- assign_bit(FLAG_BIAS_DISABLE, flagsp,
+ assign_bit(FLAG_BIAS_DISABLE, &flags,
lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE);
+
+ WRITE_ONCE(*flagsp, flags);
}
static long linehandle_set_config(struct linehandle_state *lh,
@@ -184,11 +187,11 @@ static long linehandle_set_config(struct linehandle_state *lh,
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
int val = !!gcnf.default_values[i];
- ret = gpiod_direction_output(desc, val);
+ ret = gpiod_direction_output_nonotify(desc, val);
if (ret)
return ret;
} else {
- ret = gpiod_direction_input(desc);
+ ret = gpiod_direction_input_nonotify(desc);
if (ret)
return ret;
}
@@ -359,11 +362,11 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
int val = !!handlereq.default_values[i];
- ret = gpiod_direction_output(desc, val);
+ ret = gpiod_direction_output_nonotify(desc, val);
if (ret)
goto out_free_lh;
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
- ret = gpiod_direction_input(desc);
+ ret = gpiod_direction_input_nonotify(desc);
if (ret)
goto out_free_lh;
}
@@ -417,7 +420,6 @@ out_free_lh:
/**
* struct line - contains the state of a requested line
- * @node: to store the object in supinfo_tree if supplemental
* @desc: the GPIO descriptor for this line.
* @req: the corresponding line request
* @irq: the interrupt triggered in response to events on this GPIO
@@ -430,7 +432,6 @@ out_free_lh:
* @line_seqno: the seqno for the current edge event in the sequence of
* events for this line.
* @work: the worker that implements software debouncing
- * @debounce_period_us: the debounce period in microseconds
* @sw_debounced: flag indicating if the software debouncer is active
* @level: the current debounced physical level of the line
* @hdesc: the Hardware Timestamp Engine (HTE) descriptor
@@ -439,7 +440,6 @@ out_free_lh:
* @last_seqno: the last sequence number before debounce period expires
*/
struct line {
- struct rb_node node;
struct gpio_desc *desc;
/*
* -- edge detector specific fields --
@@ -450,7 +450,7 @@ struct line {
* The flags for the active edge detector configuration.
*
* edflags is set by linereq_create(), linereq_free(), and
- * linereq_set_config_unlocked(), which are themselves mutually
+ * linereq_set_config(), which are themselves mutually
* exclusive, and is accessed by edge_irq_thread(),
* process_hw_ts_thread() and debounce_work_func(),
* which can all live with a slightly stale value.
@@ -474,15 +474,6 @@ struct line {
*/
struct delayed_work work;
/*
- * debounce_period_us is accessed by debounce_irq_handler() and
- * process_hw_ts() which are disabled when modified by
- * debounce_setup(), edge_detector_setup() or edge_detector_stop()
- * or can live with a stale version when updated by
- * edge_detector_update().
- * The modifying functions are themselves mutually exclusive.
- */
- unsigned int debounce_period_us;
- /*
* sw_debounce is accessed by linereq_set_config(), which is the
* only setter, and linereq_get_values(), which can live with a
* slightly stale value.
@@ -514,17 +505,6 @@ struct line {
#endif /* CONFIG_HTE */
};
-/*
- * a rbtree of the struct lines containing supplemental info.
- * Used to populate gpio_v2_line_info with cdev specific fields not contained
- * in the struct gpio_desc.
- * A line is determined to contain supplemental information by
- * line_has_supinfo().
- */
-static struct rb_root supinfo_tree = RB_ROOT;
-/* covers supinfo_tree */
-static DEFINE_SPINLOCK(supinfo_lock);
-
/**
* struct linereq - contains the state of a userspace line request
* @gdev: the GPIO device the line request pertains to
@@ -538,8 +518,7 @@ static DEFINE_SPINLOCK(supinfo_lock);
* this line request. Note that this is not used when @num_lines is 1, as
* the line_seqno is then the same and is cheaper to calculate.
* @config_mutex: mutex for serializing ioctl() calls to ensure consistency
- * of configuration, particularly multi-step accesses to desc flags and
- * changes to supinfo status.
+ * of configuration, particularly multi-step accesses to desc flags.
* @lines: the lines held by this line request, with @num_lines elements.
*/
struct linereq {
@@ -555,103 +534,6 @@ struct linereq {
struct line lines[] __counted_by(num_lines);
};
-static void supinfo_insert(struct line *line)
-{
- struct rb_node **new = &(supinfo_tree.rb_node), *parent = NULL;
- struct line *entry;
-
- guard(spinlock)(&supinfo_lock);
-
- while (*new) {
- entry = container_of(*new, struct line, node);
-
- parent = *new;
- if (line->desc < entry->desc) {
- new = &((*new)->rb_left);
- } else if (line->desc > entry->desc) {
- new = &((*new)->rb_right);
- } else {
- /* this should never happen */
- WARN(1, "duplicate line inserted");
- return;
- }
- }
-
- rb_link_node(&line->node, parent, new);
- rb_insert_color(&line->node, &supinfo_tree);
-}
-
-static void supinfo_erase(struct line *line)
-{
- guard(spinlock)(&supinfo_lock);
-
- rb_erase(&line->node, &supinfo_tree);
-}
-
-static struct line *supinfo_find(struct gpio_desc *desc)
-{
- struct rb_node *node = supinfo_tree.rb_node;
- struct line *line;
-
- while (node) {
- line = container_of(node, struct line, node);
- if (desc < line->desc)
- node = node->rb_left;
- else if (desc > line->desc)
- node = node->rb_right;
- else
- return line;
- }
- return NULL;
-}
-
-static void supinfo_to_lineinfo(struct gpio_desc *desc,
- struct gpio_v2_line_info *info)
-{
- struct gpio_v2_line_attribute *attr;
- struct line *line;
-
- guard(spinlock)(&supinfo_lock);
-
- line = supinfo_find(desc);
- if (!line)
- return;
-
- attr = &info->attrs[info->num_attrs];
- attr->id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE;
- attr->debounce_period_us = READ_ONCE(line->debounce_period_us);
- info->num_attrs++;
-}
-
-static inline bool line_has_supinfo(struct line *line)
-{
- return READ_ONCE(line->debounce_period_us);
-}
-
-/*
- * Checks line_has_supinfo() before and after the change to avoid unnecessary
- * supinfo_tree access.
- * Called indirectly by linereq_create() or linereq_set_config() so line
- * is already protected from concurrent changes.
- */
-static void line_set_debounce_period(struct line *line,
- unsigned int debounce_period_us)
-{
- bool was_suppl = line_has_supinfo(line);
-
- WRITE_ONCE(line->debounce_period_us, debounce_period_us);
-
- /* if supinfo status is unchanged then we're done */
- if (line_has_supinfo(line) == was_suppl)
- return;
-
- /* supinfo status has changed, so update the tree */
- if (was_suppl)
- supinfo_erase(line);
- else
- supinfo_insert(line);
-}
-
#define GPIO_V2_LINE_BIAS_FLAGS \
(GPIO_V2_LINE_FLAG_BIAS_PULL_UP | \
GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN | \
@@ -819,7 +701,7 @@ static enum hte_return process_hw_ts(struct hte_ts_data *ts, void *p)
line->total_discard_seq++;
line->last_seqno = ts->seq;
mod_delayed_work(system_wq, &line->work,
- usecs_to_jiffies(READ_ONCE(line->debounce_period_us)));
+ usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us)));
} else {
if (unlikely(ts->seq < line->line_seqno))
return HTE_CB_HANDLED;
@@ -960,7 +842,7 @@ static irqreturn_t debounce_irq_handler(int irq, void *p)
struct line *line = p;
mod_delayed_work(system_wq, &line->work,
- usecs_to_jiffies(READ_ONCE(line->debounce_period_us)));
+ usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us)));
return IRQ_HANDLED;
}
@@ -1040,12 +922,13 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us)
int ret, level, irq;
char *label;
- /* try hardware */
- ret = gpiod_set_debounce(line->desc, debounce_period_us);
- if (!ret) {
- line_set_debounce_period(line, debounce_period_us);
- return ret;
- }
+ /*
+ * Try hardware. Skip gpiod_set_config() to avoid emitting two
+ * CHANGED_CONFIG line state events.
+ */
+ ret = gpio_do_set_config(line->desc,
+ pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE,
+ debounce_period_us));
if (ret != -ENOTSUPP)
return ret;
@@ -1128,7 +1011,8 @@ static void edge_detector_stop(struct line *line)
cancel_delayed_work_sync(&line->work);
WRITE_ONCE(line->sw_debounced, 0);
WRITE_ONCE(line->edflags, 0);
- line_set_debounce_period(line, 0);
+ if (line->desc)
+ WRITE_ONCE(line->desc->debounce_period_us, 0);
/* do not change line->level - see comment in debounced_value() */
}
@@ -1161,7 +1045,7 @@ static int edge_detector_setup(struct line *line,
ret = debounce_setup(line, debounce_period_us);
if (ret)
return ret;
- line_set_debounce_period(line, debounce_period_us);
+ WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us);
}
/* detection disabled or sw debouncer will provide edge detection */
@@ -1209,12 +1093,12 @@ static int edge_detector_update(struct line *line,
gpio_v2_line_config_debounce_period(lc, line_idx);
if ((active_edflags == edflags) &&
- (READ_ONCE(line->debounce_period_us) == debounce_period_us))
+ (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us))
return 0;
/* sw debounced and still will be...*/
if (debounce_period_us && READ_ONCE(line->sw_debounced)) {
- line_set_debounce_period(line, debounce_period_us);
+ WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us);
/*
* ensure event fifo is initialised if edge detection
* is now enabled.
@@ -1331,7 +1215,7 @@ static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc,
if (lc->num_attrs > GPIO_V2_LINE_NUM_ATTRS_MAX)
return -EINVAL;
- if (memchr_inv(lc->padding, 0, sizeof(lc->padding)))
+ if (!mem_is_zero(lc->padding, sizeof(lc->padding)))
return -EINVAL;
for (i = 0; i < num_lines; i++) {
@@ -1348,38 +1232,42 @@ static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc,
return 0;
}
-static void gpio_v2_line_config_flags_to_desc_flags(u64 flags,
+static void gpio_v2_line_config_flags_to_desc_flags(u64 lflags,
unsigned long *flagsp)
{
- assign_bit(FLAG_ACTIVE_LOW, flagsp,
- flags & GPIO_V2_LINE_FLAG_ACTIVE_LOW);
+ unsigned long flags = READ_ONCE(*flagsp);
+
+ assign_bit(FLAG_ACTIVE_LOW, &flags,
+ lflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW);
- if (flags & GPIO_V2_LINE_FLAG_OUTPUT)
- set_bit(FLAG_IS_OUT, flagsp);
- else if (flags & GPIO_V2_LINE_FLAG_INPUT)
- clear_bit(FLAG_IS_OUT, flagsp);
+ if (lflags & GPIO_V2_LINE_FLAG_OUTPUT)
+ set_bit(FLAG_IS_OUT, &flags);
+ else if (lflags & GPIO_V2_LINE_FLAG_INPUT)
+ clear_bit(FLAG_IS_OUT, &flags);
- assign_bit(FLAG_EDGE_RISING, flagsp,
- flags & GPIO_V2_LINE_FLAG_EDGE_RISING);
- assign_bit(FLAG_EDGE_FALLING, flagsp,
- flags & GPIO_V2_LINE_FLAG_EDGE_FALLING);
+ assign_bit(FLAG_EDGE_RISING, &flags,
+ lflags & GPIO_V2_LINE_FLAG_EDGE_RISING);
+ assign_bit(FLAG_EDGE_FALLING, &flags,
+ lflags & GPIO_V2_LINE_FLAG_EDGE_FALLING);
- assign_bit(FLAG_OPEN_DRAIN, flagsp,
- flags & GPIO_V2_LINE_FLAG_OPEN_DRAIN);
- assign_bit(FLAG_OPEN_SOURCE, flagsp,
- flags & GPIO_V2_LINE_FLAG_OPEN_SOURCE);
+ assign_bit(FLAG_OPEN_DRAIN, &flags,
+ lflags & GPIO_V2_LINE_FLAG_OPEN_DRAIN);
+ assign_bit(FLAG_OPEN_SOURCE, &flags,
+ lflags & GPIO_V2_LINE_FLAG_OPEN_SOURCE);
- assign_bit(FLAG_PULL_UP, flagsp,
- flags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP);
- assign_bit(FLAG_PULL_DOWN, flagsp,
- flags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN);
- assign_bit(FLAG_BIAS_DISABLE, flagsp,
- flags & GPIO_V2_LINE_FLAG_BIAS_DISABLED);
+ assign_bit(FLAG_PULL_UP, &flags,
+ lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP);
+ assign_bit(FLAG_PULL_DOWN, &flags,
+ lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN);
+ assign_bit(FLAG_BIAS_DISABLE, &flags,
+ lflags & GPIO_V2_LINE_FLAG_BIAS_DISABLED);
- assign_bit(FLAG_EVENT_CLOCK_REALTIME, flagsp,
- flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME);
- assign_bit(FLAG_EVENT_CLOCK_HTE, flagsp,
- flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE);
+ assign_bit(FLAG_EVENT_CLOCK_REALTIME, &flags,
+ lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME);
+ assign_bit(FLAG_EVENT_CLOCK_HTE, &flags,
+ lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE);
+
+ WRITE_ONCE(*flagsp, flags);
}
static long linereq_get_values(struct linereq *lr, void __user *ip)
@@ -1546,11 +1434,11 @@ static long linereq_set_config(struct linereq *lr, void __user *ip)
int val = gpio_v2_line_config_output_value(&lc, i);
edge_detector_stop(line);
- ret = gpiod_direction_output(desc, val);
+ ret = gpiod_direction_output_nonotify(desc, val);
if (ret)
return ret;
} else {
- ret = gpiod_direction_input(desc);
+ ret = gpiod_direction_input_nonotify(desc);
if (ret)
return ret;
@@ -1669,7 +1557,6 @@ static ssize_t linereq_read(struct file *file, char __user *buf,
static void linereq_free(struct linereq *lr)
{
- struct line *line;
unsigned int i;
if (lr->device_unregistered_nb.notifier_call)
@@ -1677,14 +1564,10 @@ static void linereq_free(struct linereq *lr)
&lr->device_unregistered_nb);
for (i = 0; i < lr->num_lines; i++) {
- line = &lr->lines[i];
- if (!line->desc)
- continue;
-
- edge_detector_stop(line);
- if (line_has_supinfo(line))
- supinfo_erase(line);
- gpiod_free(line->desc);
+ if (lr->lines[i].desc) {
+ edge_detector_stop(&lr->lines[i]);
+ gpiod_free(lr->lines[i].desc);
+ }
}
kfifo_free(&lr->events);
kfree(lr->label);
@@ -1746,7 +1629,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
if ((ulr.num_lines == 0) || (ulr.num_lines > GPIO_V2_LINES_MAX))
return -EINVAL;
- if (memchr_inv(ulr.padding, 0, sizeof(ulr.padding)))
+ if (!mem_is_zero(ulr.padding, sizeof(ulr.padding)))
return -EINVAL;
lc = &ulr.config;
@@ -1818,11 +1701,11 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
int val = gpio_v2_line_config_output_value(lc, i);
- ret = gpiod_direction_output(desc, val);
+ ret = gpiod_direction_output_nonotify(desc, val);
if (ret)
goto out_free_linereq;
} else if (flags & GPIO_V2_LINE_FLAG_INPUT) {
- ret = gpiod_direction_input(desc);
+ ret = gpiod_direction_input_nonotify(desc);
if (ret)
goto out_free_linereq;
@@ -2353,8 +2236,9 @@ static void gpio_v2_line_info_changed_to_v1(
#endif /* CONFIG_GPIO_CDEV_V1 */
static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
- struct gpio_v2_line_info *info)
+ struct gpio_v2_line_info *info, bool atomic)
{
+ u32 debounce_period_us;
unsigned long dflags;
const char *label;
@@ -2391,12 +2275,14 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
*/
if (test_bit(FLAG_REQUESTED, &dflags) ||
test_bit(FLAG_IS_HOGGED, &dflags) ||
- test_bit(FLAG_USED_AS_IRQ, &dflags) ||
test_bit(FLAG_EXPORT, &dflags) ||
test_bit(FLAG_SYSFS, &dflags) ||
- !gpiochip_line_is_valid(guard.gc, info->offset) ||
- !pinctrl_gpio_can_use_line(guard.gc, info->offset))
+ !gpiochip_line_is_valid(guard.gc, info->offset)) {
info->flags |= GPIO_V2_LINE_FLAG_USED;
+ } else if (!atomic) {
+ if (!pinctrl_gpio_can_use_line(guard.gc, info->offset))
+ info->flags |= GPIO_V2_LINE_FLAG_USED;
+ }
if (test_bit(FLAG_IS_OUT, &dflags))
info->flags |= GPIO_V2_LINE_FLAG_OUTPUT;
@@ -2427,6 +2313,14 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME;
else if (test_bit(FLAG_EVENT_CLOCK_HTE, &dflags))
info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE;
+
+ debounce_period_us = READ_ONCE(desc->debounce_period_us);
+ if (debounce_period_us) {
+ info->attrs[info->num_attrs].id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE;
+ info->attrs[info->num_attrs].debounce_period_us =
+ debounce_period_us;
+ info->num_attrs++;
+ }
}
struct gpio_chardev_data {
@@ -2439,6 +2333,7 @@ struct gpio_chardev_data {
#ifdef CONFIG_GPIO_CDEV_V1
atomic_t watch_abi_version;
#endif
+ struct file *fp;
};
static int chipinfo_get(struct gpio_chardev_data *cdev, void __user *ip)
@@ -2494,7 +2389,7 @@ static int lineinfo_get_v1(struct gpio_chardev_data *cdev, void __user *ip,
return -EBUSY;
}
- gpio_desc_to_lineinfo(desc, &lineinfo_v2);
+ gpio_desc_to_lineinfo(desc, &lineinfo_v2, false);
gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
@@ -2516,7 +2411,7 @@ static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
return -EFAULT;
- if (memchr_inv(lineinfo.padding, 0, sizeof(lineinfo.padding)))
+ if (!mem_is_zero(lineinfo.padding, sizeof(lineinfo.padding)))
return -EINVAL;
desc = gpio_device_get_desc(cdev->gdev, lineinfo.offset);
@@ -2531,8 +2426,7 @@ static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
if (test_and_set_bit(lineinfo.offset, cdev->watched_lines))
return -EBUSY;
}
- gpio_desc_to_lineinfo(desc, &lineinfo);
- supinfo_to_lineinfo(desc, &lineinfo);
+ gpio_desc_to_lineinfo(desc, &lineinfo, false);
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
if (watch)
@@ -2609,29 +2503,86 @@ static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
}
#endif
+struct lineinfo_changed_ctx {
+ struct work_struct work;
+ struct gpio_v2_line_info_changed chg;
+ struct gpio_device *gdev;
+ struct gpio_chardev_data *cdev;
+};
+
+static void lineinfo_changed_func(struct work_struct *work)
+{
+ struct lineinfo_changed_ctx *ctx =
+ container_of(work, struct lineinfo_changed_ctx, work);
+ struct gpio_chip *gc;
+ int ret;
+
+ if (!(ctx->chg.info.flags & GPIO_V2_LINE_FLAG_USED)) {
+ /*
+ * If nobody set the USED flag earlier, let's see with pinctrl
+ * now. We're doing this late because it's a sleeping function.
+ * Pin functions are in general much more static and while it's
+ * not 100% bullet-proof, it's good enough for most cases.
+ */
+ scoped_guard(srcu, &ctx->gdev->srcu) {
+ gc = srcu_dereference(ctx->gdev->chip, &ctx->gdev->srcu);
+ if (gc &&
+ !pinctrl_gpio_can_use_line(gc, ctx->chg.info.offset))
+ ctx->chg.info.flags |= GPIO_V2_LINE_FLAG_USED;
+ }
+ }
+
+ ret = kfifo_in_spinlocked(&ctx->cdev->events, &ctx->chg, 1,
+ &ctx->cdev->wait.lock);
+ if (ret)
+ wake_up_poll(&ctx->cdev->wait, EPOLLIN);
+ else
+ pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
+
+ gpio_device_put(ctx->gdev);
+ fput(ctx->cdev->fp);
+ kfree(ctx);
+}
+
static int lineinfo_changed_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
struct gpio_chardev_data *cdev =
container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb);
- struct gpio_v2_line_info_changed chg;
+ struct lineinfo_changed_ctx *ctx;
struct gpio_desc *desc = data;
- int ret;
if (!test_bit(gpio_chip_hwgpio(desc), cdev->watched_lines))
return NOTIFY_DONE;
- memset(&chg, 0, sizeof(chg));
- chg.event_type = action;
- chg.timestamp_ns = ktime_get_ns();
- gpio_desc_to_lineinfo(desc, &chg.info);
- supinfo_to_lineinfo(desc, &chg.info);
+ /*
+ * If this is called from atomic context (for instance: with a spinlock
+ * taken by the atomic notifier chain), any sleeping calls must be done
+ * outside of this function in process context of the dedicated
+ * workqueue.
+ *
+ * Let's gather as much info as possible from the descriptor and
+ * postpone just the call to pinctrl_gpio_can_use_line() until the work
+ * is executed.
+ */
- ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock);
- if (ret)
- wake_up_poll(&cdev->wait, EPOLLIN);
- else
- pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
+ ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
+ if (!ctx) {
+ pr_err("Failed to allocate memory for line info notification\n");
+ return NOTIFY_DONE;
+ }
+
+ ctx->chg.event_type = action;
+ ctx->chg.timestamp_ns = ktime_get_ns();
+ gpio_desc_to_lineinfo(desc, &ctx->chg.info, true);
+ /* Keep the GPIO device alive until we emit the event. */
+ ctx->gdev = gpio_device_get(desc->gdev);
+ ctx->cdev = cdev;
+ /* Keep the file descriptor alive too. */
+ get_file(ctx->cdev->fp);
+
+ INIT_WORK(&ctx->work, lineinfo_changed_func);
+ queue_work(ctx->gdev->line_state_wq, &ctx->work);
return NOTIFY_OK;
}
@@ -2778,8 +2729,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
cdev->gdev = gpio_device_get(gdev);
cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
- ret = blocking_notifier_chain_register(&gdev->line_state_notifier,
- &cdev->lineinfo_changed_nb);
+ ret = atomic_notifier_chain_register(&gdev->line_state_notifier,
+ &cdev->lineinfo_changed_nb);
if (ret)
goto out_free_bitmap;
@@ -2791,6 +2742,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
goto out_unregister_line_notifier;
file->private_data = cdev;
+ cdev->fp = file;
ret = nonseekable_open(inode, file);
if (ret)
@@ -2802,8 +2754,8 @@ out_unregister_device_notifier:
blocking_notifier_chain_unregister(&gdev->device_notifier,
&cdev->device_unregistered_nb);
out_unregister_line_notifier:
- blocking_notifier_chain_unregister(&gdev->line_state_notifier,
- &cdev->lineinfo_changed_nb);
+ atomic_notifier_chain_unregister(&gdev->line_state_notifier,
+ &cdev->lineinfo_changed_nb);
out_free_bitmap:
gpio_device_put(gdev);
bitmap_free(cdev->watched_lines);
@@ -2827,8 +2779,8 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file)
blocking_notifier_chain_unregister(&gdev->device_notifier,
&cdev->device_unregistered_nb);
- blocking_notifier_chain_unregister(&gdev->line_state_notifier,
- &cdev->lineinfo_changed_nb);
+ atomic_notifier_chain_unregister(&gdev->line_state_notifier,
+ &cdev->lineinfo_changed_nb);
bitmap_free(cdev->watched_lines);
gpio_device_put(gdev);
kfree(cdev);
@@ -2857,6 +2809,11 @@ int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
gdev->chrdev.owner = THIS_MODULE;
gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id);
+ gdev->line_state_wq = alloc_ordered_workqueue("%s", WQ_HIGHPRI,
+ dev_name(&gdev->dev));
+ if (!gdev->line_state_wq)
+ return -ENOMEM;
+
ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
if (ret)
return ret;
@@ -2873,6 +2830,7 @@ int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
void gpiolib_cdev_unregister(struct gpio_device *gdev)
{
+ destroy_workqueue(gdev->line_state_wq);
cdev_device_del(&gdev->chrdev, &gdev->dev);
blocking_notifier_call_chain(&gdev->device_notifier, 0, NULL);
}
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c
index 28f1046fb670..aeae6df8bec9 100644
--- a/drivers/gpio/gpiolib-legacy.c
+++ b/drivers/gpio/gpiolib-legacy.c
@@ -46,9 +46,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (err)
return err;
- if (flags & GPIOF_ACTIVE_LOW)
- set_bit(FLAG_ACTIVE_LOW, &desc->flags);
-
if (flags & GPIOF_IN)
err = gpiod_direction_input(desc);
else
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 880f1efcaca5..2e537ee979f3 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -337,7 +337,7 @@ static void of_gpio_flags_quirks(const struct device_node *np,
* to determine if the flags should have inverted semantics.
*/
if (IS_ENABLED(CONFIG_SPI_MASTER) && !strcmp(propname, "cs-gpios") &&
- of_property_read_bool(np, "cs-gpios")) {
+ of_property_present(np, "cs-gpios")) {
u32 cs;
int ret;
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 17ed229412af..1acfa43bf1ab 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -21,6 +21,8 @@
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
+#include <uapi/linux/gpio.h>
+
#include "gpiolib.h"
#include "gpiolib-sysfs.h"
@@ -77,12 +79,10 @@ static ssize_t direction_show(struct device *dev,
struct gpio_desc *desc = data->desc;
int value;
- mutex_lock(&data->mutex);
-
- gpiod_get_direction(desc);
- value = !!test_bit(FLAG_IS_OUT, &desc->flags);
-
- mutex_unlock(&data->mutex);
+ scoped_guard(mutex, &data->mutex) {
+ gpiod_get_direction(desc);
+ value = !!test_bit(FLAG_IS_OUT, &desc->flags);
+ }
return sysfs_emit(buf, "%s\n", value ? "out" : "in");
}
@@ -94,7 +94,7 @@ static ssize_t direction_store(struct device *dev,
struct gpio_desc *desc = data->desc;
ssize_t status;
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
if (sysfs_streq(buf, "high"))
status = gpiod_direction_output_raw(desc, 1);
@@ -105,8 +105,6 @@ static ssize_t direction_store(struct device *dev,
else
status = -EINVAL;
- mutex_unlock(&data->mutex);
-
return status ? : size;
}
static DEVICE_ATTR_RW(direction);
@@ -118,11 +116,8 @@ static ssize_t value_show(struct device *dev,
struct gpio_desc *desc = data->desc;
ssize_t status;
- mutex_lock(&data->mutex);
-
- status = gpiod_get_value_cansleep(desc);
-
- mutex_unlock(&data->mutex);
+ scoped_guard(mutex, &data->mutex)
+ status = gpiod_get_value_cansleep(desc);
if (status < 0)
return status;
@@ -140,18 +135,17 @@ static ssize_t value_store(struct device *dev,
status = kstrtol(buf, 0, &value);
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
- if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
- status = -EPERM;
- } else if (status == 0) {
- gpiod_set_value_cansleep(desc, value);
- status = size;
- }
+ if (!test_bit(FLAG_IS_OUT, &desc->flags))
+ return -EPERM;
+
+ if (status)
+ return status;
- mutex_unlock(&data->mutex);
+ gpiod_set_value_cansleep(desc, value);
- return status;
+ return size;
}
static DEVICE_ATTR_PREALLOC(value, S_IWUSR | S_IRUGO, value_show, value_store);
@@ -185,12 +179,16 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
return -ENODEV;
irq_flags = IRQF_SHARED;
- if (flags & GPIO_IRQF_TRIGGER_FALLING)
+ if (flags & GPIO_IRQF_TRIGGER_FALLING) {
irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
- if (flags & GPIO_IRQF_TRIGGER_RISING)
+ set_bit(FLAG_EDGE_FALLING, &desc->flags);
+ }
+ if (flags & GPIO_IRQF_TRIGGER_RISING) {
irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+ set_bit(FLAG_EDGE_RISING, &desc->flags);
+ }
/*
* FIXME: This should be done in the irq_request_resources callback
@@ -216,6 +214,8 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
err_unlock:
gpiochip_unlock_as_irq(guard.gc, gpio_chip_hwgpio(desc));
err_put_kn:
+ clear_bit(FLAG_EDGE_RISING, &desc->flags);
+ clear_bit(FLAG_EDGE_FALLING, &desc->flags);
sysfs_put(data->value_kn);
return ret;
@@ -237,6 +237,8 @@ static void gpio_sysfs_free_irq(struct device *dev)
data->irq_flags = 0;
free_irq(data->irq, data);
gpiochip_unlock_as_irq(guard.gc, gpio_chip_hwgpio(desc));
+ clear_bit(FLAG_EDGE_RISING, &desc->flags);
+ clear_bit(FLAG_EDGE_FALLING, &desc->flags);
sysfs_put(data->value_kn);
}
@@ -253,11 +255,8 @@ static ssize_t edge_show(struct device *dev,
struct gpiod_data *data = dev_get_drvdata(dev);
int flags;
- mutex_lock(&data->mutex);
-
- flags = data->irq_flags;
-
- mutex_unlock(&data->mutex);
+ scoped_guard(mutex, &data->mutex)
+ flags = data->irq_flags;
if (flags >= ARRAY_SIZE(trigger_names))
return 0;
@@ -276,26 +275,24 @@ static ssize_t edge_store(struct device *dev,
if (flags < 0)
return flags;
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
- if (flags == data->irq_flags) {
- status = size;
- goto out_unlock;
- }
+ if (flags == data->irq_flags)
+ return size;
if (data->irq_flags)
gpio_sysfs_free_irq(dev);
- if (flags) {
- status = gpio_sysfs_request_irq(dev, flags);
- if (!status)
- status = size;
- }
+ if (!flags)
+ return size;
-out_unlock:
- mutex_unlock(&data->mutex);
+ status = gpio_sysfs_request_irq(dev, flags);
+ if (status)
+ return status;
- return status;
+ gpiod_line_state_notify(data->desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
+ return size;
}
static DEVICE_ATTR_RW(edge);
@@ -320,6 +317,8 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value)
status = gpio_sysfs_request_irq(dev, flags);
}
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
return status;
}
@@ -330,11 +329,8 @@ static ssize_t active_low_show(struct device *dev,
struct gpio_desc *desc = data->desc;
int value;
- mutex_lock(&data->mutex);
-
- value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags);
-
- mutex_unlock(&data->mutex);
+ scoped_guard(mutex, &data->mutex)
+ value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags);
return sysfs_emit(buf, "%d\n", value);
}
@@ -350,13 +346,9 @@ static ssize_t active_low_store(struct device *dev,
if (status)
return status;
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
- status = gpio_sysfs_set_active_low(dev, value);
-
- mutex_unlock(&data->mutex);
-
- return status ? : size;
+ return gpio_sysfs_set_active_low(dev, value) ?: size;
}
static DEVICE_ATTR_RW(active_low);
@@ -463,7 +455,7 @@ static ssize_t export_store(const struct class *class,
desc = gpio_to_desc(gpio);
/* reject invalid GPIOs */
if (!desc) {
- pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+ pr_debug_ratelimited("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
@@ -473,7 +465,7 @@ static ssize_t export_store(const struct class *class,
offset = gpio_chip_hwgpio(desc);
if (!gpiochip_line_is_valid(guard.gc, offset)) {
- pr_warn("%s: GPIO %ld masked\n", __func__, gpio);
+ pr_debug_ratelimited("%s: GPIO %ld masked\n", __func__, gpio);
return -EINVAL;
}
@@ -493,10 +485,12 @@ static ssize_t export_store(const struct class *class,
}
status = gpiod_export(desc, true);
- if (status < 0)
+ if (status < 0) {
gpiod_free(desc);
- else
+ } else {
set_bit(FLAG_SYSFS, &desc->flags);
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
+ }
done:
if (status)
@@ -520,7 +514,7 @@ static ssize_t unexport_store(const struct class *class,
desc = gpio_to_desc(gpio);
/* reject bogus commands (gpiod_unexport() ignores them) */
if (!desc) {
- pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+ pr_debug_ratelimited("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
@@ -549,12 +543,11 @@ static struct attribute *gpio_class_attrs[] = {
};
ATTRIBUTE_GROUPS(gpio_class);
-static struct class gpio_class = {
+static const struct class gpio_class = {
.name = "gpio",
- .class_groups = gpio_class_groups,
+ .class_groups = gpio_class_groups,
};
-
/**
* gpiod_export - export a GPIO through sysfs
* @desc: GPIO to make available, already requested
@@ -573,11 +566,10 @@ static struct class gpio_class = {
*/
int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
{
- const char *ioname = NULL;
struct gpio_device *gdev;
struct gpiod_data *data;
struct device *dev;
- int status, offset;
+ int status;
/* can't export until sysfs is available ... */
if (!class_is_registered(&gpio_class)) {
@@ -599,24 +591,24 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
gdev = desc->gdev;
- mutex_lock(&sysfs_lock);
+ guard(mutex)(&sysfs_lock);
/* check if chip is being removed */
if (!gdev->mockdev) {
status = -ENODEV;
- goto err_unlock;
+ goto err_clear_bit;
}
if (!test_bit(FLAG_REQUESTED, &desc->flags)) {
gpiod_dbg(desc, "%s: unavailable (not requested)\n", __func__);
status = -EPERM;
- goto err_unlock;
+ goto err_clear_bit;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
- goto err_unlock;
+ goto err_clear_bit;
}
data->desc = desc;
@@ -626,26 +618,19 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
else
data->direction_can_change = false;
- offset = gpio_chip_hwgpio(desc);
- if (guard.gc->names && guard.gc->names[offset])
- ioname = guard.gc->names[offset];
-
dev = device_create_with_groups(&gpio_class, &gdev->dev,
MKDEV(0, 0), data, gpio_groups,
- ioname ? ioname : "gpio%u",
- desc_to_gpio(desc));
+ "gpio%u", desc_to_gpio(desc));
if (IS_ERR(dev)) {
status = PTR_ERR(dev);
goto err_free_data;
}
- mutex_unlock(&sysfs_lock);
return 0;
err_free_data:
kfree(data);
-err_unlock:
- mutex_unlock(&sysfs_lock);
+err_clear_bit:
clear_bit(FLAG_EXPORT, &desc->flags);
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
@@ -709,36 +694,28 @@ void gpiod_unexport(struct gpio_desc *desc)
return;
}
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags))
- goto err_unlock;
-
- dev = class_find_device(&gpio_class, NULL, desc, match_export);
- if (!dev)
- goto err_unlock;
-
- data = dev_get_drvdata(dev);
+ scoped_guard(mutex, &sysfs_lock) {
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ return;
- clear_bit(FLAG_EXPORT, &desc->flags);
+ dev = class_find_device(&gpio_class, NULL, desc, match_export);
+ if (!dev)
+ return;
- device_unregister(dev);
+ data = dev_get_drvdata(dev);
+ clear_bit(FLAG_EXPORT, &desc->flags);
+ device_unregister(dev);
- /*
- * Release irq after deregistration to prevent race with edge_store.
- */
- if (data->irq_flags)
- gpio_sysfs_free_irq(dev);
-
- mutex_unlock(&sysfs_lock);
+ /*
+ * Release irq after deregistration to prevent race with
+ * edge_store.
+ */
+ if (data->irq_flags)
+ gpio_sysfs_free_irq(dev);
+ }
put_device(dev);
kfree(data);
-
- return;
-
-err_unlock:
- mutex_unlock(&sysfs_lock);
}
EXPORT_SYMBOL_GPL(gpiod_unexport);
@@ -779,9 +756,8 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
if (IS_ERR(dev))
return PTR_ERR(dev);
- mutex_lock(&sysfs_lock);
+ guard(mutex)(&sysfs_lock);
gdev->mockdev = dev;
- mutex_unlock(&sysfs_lock);
return 0;
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 2b02655abb56..679ed764cb14 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -14,6 +14,7 @@
#include <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/irqdesc.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/lockdep.h>
@@ -23,7 +24,6 @@
#include <linux/pinctrl/consumer.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
-#include <linux/spinlock.h>
#include <linux/srcu.h>
#include <linux/string.h>
@@ -713,6 +713,45 @@ bool gpiochip_line_is_valid(const struct gpio_chip *gc,
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
+static void gpiod_free_irqs(struct gpio_desc *desc)
+{
+ int irq = gpiod_to_irq(desc);
+ struct irq_desc *irqd = irq_to_desc(irq);
+ void *cookie;
+
+ for (;;) {
+ /*
+ * Make sure the action doesn't go away while we're
+ * dereferencing it. Retrieve and store the cookie value.
+ * If the irq is freed after we release the lock, that's
+ * alright - the underlying maple tree lookup will return NULL
+ * and nothing will happen in free_irq().
+ */
+ scoped_guard(mutex, &irqd->request_mutex) {
+ if (!irq_desc_has_action(irqd))
+ return;
+
+ cookie = irqd->action->dev_id;
+ }
+
+ free_irq(irq, cookie);
+ }
+}
+
+/*
+ * The chip is going away but there may be users who had requested interrupts
+ * on its GPIO lines who have no idea about its removal and have no way of
+ * being notified about it. We need to free any interrupts still in use here or
+ * we'll leak memory and resources (like procfs files).
+ */
+static void gpiochip_free_remaining_irqs(struct gpio_chip *gc)
+{
+ struct gpio_desc *desc;
+
+ for_each_gpio_desc_with_flag(gc, desc, FLAG_USED_AS_IRQ)
+ gpiod_free_irqs(desc);
+}
+
static void gpiodev_release(struct device *dev)
{
struct gpio_device *gdev = to_gpio_device(dev);
@@ -986,10 +1025,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
}
}
- for (desc_index = 0; desc_index < gc->ngpio; desc_index++)
- gdev->descs[desc_index].gdev = gdev;
-
- BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
+ ATOMIC_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
ret = init_srcu_struct(&gdev->srcu);
@@ -1018,6 +1054,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
for (desc_index = 0; desc_index < gc->ngpio; desc_index++) {
struct gpio_desc *desc = &gdev->descs[desc_index];
+ desc->gdev = gdev;
+
if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) {
assign_bit(FLAG_IS_OUT,
&desc->flags, !gc->get_direction(gc, desc_index));
@@ -1125,6 +1163,7 @@ void gpiochip_remove(struct gpio_chip *gc)
/* FIXME: should the legacy sysfs handling be moved to gpio_device? */
gpiochip_sysfs_unregister(gdev);
gpiochip_free_hogs(gc);
+ gpiochip_free_remaining_irqs(gc);
scoped_guard(mutex, &gpio_devices_lock)
list_del_rcu(&gdev->list);
@@ -1183,11 +1222,6 @@ struct gpio_device *gpio_device_find(const void *data,
struct gpio_device *gdev;
struct gpio_chip *gc;
- /*
- * Not yet but in the future the spinlock below will become a mutex.
- * Annotate this function before anyone tries to use it in interrupt
- * context like it happened with gpiochip_find().
- */
might_sleep();
guard(srcu)(&gpio_devices_srcu);
@@ -2392,8 +2426,10 @@ static void gpiod_free_commit(struct gpio_desc *desc)
#endif
desc_set_label(desc, NULL);
WRITE_ONCE(desc->flags, flags);
-
- gpiod_line_state_notify(desc, GPIOLINE_CHANGED_RELEASED);
+#ifdef CONFIG_GPIO_CDEV
+ WRITE_ONCE(desc->debounce_period_us, 0);
+#endif
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_RELEASED);
}
}
@@ -2492,6 +2528,8 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
return ERR_PTR(ret);
}
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
+
return desc;
}
EXPORT_SYMBOL_GPL(gpiochip_request_own_desc);
@@ -2520,13 +2558,28 @@ EXPORT_SYMBOL_GPL(gpiochip_free_own_desc);
* rely on gpio_request() having been called beforehand.
*/
-static int gpio_do_set_config(struct gpio_chip *gc, unsigned int offset,
- unsigned long config)
+int gpio_do_set_config(struct gpio_desc *desc, unsigned long config)
{
- if (!gc->set_config)
+ int ret;
+
+ CLASS(gpio_chip_guard, guard)(desc);
+ if (!guard.gc)
+ return -ENODEV;
+
+ if (!guard.gc->set_config)
return -ENOTSUPP;
- return gc->set_config(gc, offset, config);
+ ret = guard.gc->set_config(guard.gc, gpio_chip_hwgpio(desc), config);
+#ifdef CONFIG_GPIO_CDEV
+ /*
+ * Special case - if we're setting debounce period, we need to store
+ * it in the descriptor in case user-space wants to know it.
+ */
+ if (!ret && pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE)
+ WRITE_ONCE(desc->debounce_period_us,
+ pinconf_to_config_argument(config));
+#endif
+ return ret;
}
static int gpio_set_config_with_argument(struct gpio_desc *desc,
@@ -2535,12 +2588,8 @@ static int gpio_set_config_with_argument(struct gpio_desc *desc,
{
unsigned long config;
- CLASS(gpio_chip_guard, guard)(desc);
- if (!guard.gc)
- return -ENODEV;
-
config = pinconf_to_config_packed(mode, argument);
- return gpio_do_set_config(guard.gc, gpio_chip_hwgpio(desc), config);
+ return gpio_do_set_config(desc, config);
}
static int gpio_set_config_with_argument_optional(struct gpio_desc *desc,
@@ -2615,9 +2664,15 @@ static int gpio_set_bias(struct gpio_desc *desc)
*/
int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce)
{
- return gpio_set_config_with_argument_optional(desc,
- PIN_CONFIG_INPUT_DEBOUNCE,
- debounce);
+ int ret;
+
+ ret = gpio_set_config_with_argument_optional(desc,
+ PIN_CONFIG_INPUT_DEBOUNCE,
+ debounce);
+ if (!ret)
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
+ return ret;
}
/**
@@ -2632,10 +2687,22 @@ int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce)
*/
int gpiod_direction_input(struct gpio_desc *desc)
{
- int ret = 0;
+ int ret;
VALIDATE_DESC(desc);
+ ret = gpiod_direction_input_nonotify(desc);
+ if (ret == 0)
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(gpiod_direction_input);
+
+int gpiod_direction_input_nonotify(struct gpio_desc *desc)
+{
+ int ret = 0;
+
CLASS(gpio_chip_guard, guard)(desc);
if (!guard.gc)
return -ENODEV;
@@ -2678,7 +2745,6 @@ int gpiod_direction_input(struct gpio_desc *desc)
return ret;
}
-EXPORT_SYMBOL_GPL(gpiod_direction_input);
static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value)
{
@@ -2740,8 +2806,15 @@ static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value)
*/
int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
+ int ret;
+
VALIDATE_DESC(desc);
- return gpiod_direction_output_raw_commit(desc, value);
+
+ ret = gpiod_direction_output_raw_commit(desc, value);
+ if (ret == 0)
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(gpiod_direction_output_raw);
@@ -2760,11 +2833,23 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output_raw);
*/
int gpiod_direction_output(struct gpio_desc *desc, int value)
{
- unsigned long flags;
int ret;
VALIDATE_DESC(desc);
+ ret = gpiod_direction_output_nonotify(desc, value);
+ if (ret == 0)
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(gpiod_direction_output);
+
+int gpiod_direction_output_nonotify(struct gpio_desc *desc, int value)
+{
+ unsigned long flags;
+ int ret;
+
flags = READ_ONCE(desc->flags);
if (test_bit(FLAG_ACTIVE_LOW, &flags))
@@ -2788,7 +2873,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
goto set_output_value;
/* Emulate open drain by not actively driving the line high */
if (value) {
- ret = gpiod_direction_input(desc);
+ ret = gpiod_direction_input_nonotify(desc);
goto set_output_flag;
}
} else if (test_bit(FLAG_OPEN_SOURCE, &flags)) {
@@ -2797,7 +2882,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
goto set_output_value;
/* Emulate open source by not actively driving the line low */
if (!value) {
- ret = gpiod_direction_input(desc);
+ ret = gpiod_direction_input_nonotify(desc);
goto set_output_flag;
}
} else {
@@ -2821,7 +2906,6 @@ set_output_flag:
set_bit(FLAG_IS_OUT, &desc->flags);
return ret;
}
-EXPORT_SYMBOL_GPL(gpiod_direction_output);
/**
* gpiod_enable_hw_timestamp_ns - Enable hardware timestamp in nanoseconds.
@@ -2900,13 +2984,30 @@ EXPORT_SYMBOL_GPL(gpiod_disable_hw_timestamp_ns);
*/
int gpiod_set_config(struct gpio_desc *desc, unsigned long config)
{
+ int ret;
+
VALIDATE_DESC(desc);
- CLASS(gpio_chip_guard, guard)(desc);
- if (!guard.gc)
- return -ENODEV;
+ ret = gpio_do_set_config(desc, config);
+ if (!ret) {
+ /* These are the only options we notify the userspace about. */
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case PIN_CONFIG_DRIVE_OPEN_SOURCE:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ gpiod_line_state_notify(desc,
+ GPIO_V2_LINE_CHANGED_CONFIG);
+ break;
+ default:
+ break;
+ }
+ }
- return gpio_do_set_config(guard.gc, gpio_chip_hwgpio(desc), config);
+ return ret;
}
EXPORT_SYMBOL_GPL(gpiod_set_config);
@@ -2973,6 +3074,7 @@ void gpiod_toggle_active_low(struct gpio_desc *desc)
{
VALIDATE_DESC_VOID(desc);
change_bit(FLAG_ACTIVE_LOW, &desc->flags);
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
}
EXPORT_SYMBOL_GPL(gpiod_toggle_active_low);
@@ -3617,9 +3719,15 @@ EXPORT_SYMBOL_GPL(gpiod_cansleep);
*/
int gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
{
+ int ret;
+
VALIDATE_DESC(desc);
- return desc_set_label(desc, name);
+ ret = desc_set_label(desc, name);
+ if (ret == 0)
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(gpiod_set_consumer_name);
@@ -4047,8 +4155,8 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);
void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action)
{
- blocking_notifier_call_chain(&desc->gdev->line_state_notifier,
- action, desc);
+ atomic_notifier_call_chain(&desc->gdev->line_state_notifier,
+ action, desc);
}
/**
@@ -4325,7 +4433,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
return ERR_PTR(ret);
}
- gpiod_line_state_notify(desc, GPIOLINE_CHANGED_REQUESTED);
+ gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
return desc;
}
@@ -4497,10 +4605,10 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
/* Process flags */
if (dflags & GPIOD_FLAGS_BIT_DIR_OUT)
- ret = gpiod_direction_output(desc,
+ ret = gpiod_direction_output_nonotify(desc,
!!(dflags & GPIOD_FLAGS_BIT_DIR_VAL));
else
- ret = gpiod_direction_input(desc);
+ ret = gpiod_direction_input_nonotify(desc);
return ret;
}
@@ -4967,19 +5075,19 @@ static int gpiolib_seq_show(struct seq_file *s, void *v)
struct gpio_chip *gc;
struct device *parent;
+ if (priv->newline)
+ seq_putc(s, '\n');
+
guard(srcu)(&gdev->srcu);
gc = srcu_dereference(gdev->chip, &gdev->srcu);
if (!gc) {
- seq_printf(s, "%s%s: (dangling chip)\n",
- priv->newline ? "\n" : "",
- dev_name(&gdev->dev));
+ seq_printf(s, "%s: (dangling chip)\n", dev_name(&gdev->dev));
return 0;
}
- seq_printf(s, "%s%s: GPIOs %u-%u", priv->newline ? "\n" : "",
- dev_name(&gdev->dev),
- gdev->base, gdev->base + gdev->ngpio - 1);
+ seq_printf(s, "%s: GPIOs %u-%u", dev_name(&gdev->dev), gdev->base,
+ gdev->base + gdev->ngpio - 1);
parent = gc->parent;
if (parent)
seq_printf(s, ", parent: %s/%s",
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 067197d61d57..83690f72f7e5 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/srcu.h>
+#include <linux/workqueue.h>
#define GPIOCHIP_NAME "gpiochip"
@@ -44,6 +45,8 @@
* @list: links gpio_device:s together for traversal
* @line_state_notifier: used to notify subscribers about lines being
* requested, released or reconfigured
+ * @line_state_wq: used to emit line state events from a separate thread in
+ * process context
* @device_notifier: used to notify character device wait queues about the GPIO
* device being unregistered
* @srcu: protects the pointer to the underlying GPIO chip
@@ -69,7 +72,8 @@ struct gpio_device {
const char *label;
void *data;
struct list_head list;
- struct blocking_notifier_head line_state_notifier;
+ struct atomic_notifier_head line_state_notifier;
+ struct workqueue_struct *line_state_wq;
struct blocking_notifier_head device_notifier;
struct srcu_struct srcu;
@@ -151,6 +155,8 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
int gpiod_set_transitory(struct gpio_desc *desc, bool transitory);
void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
+int gpiod_direction_output_nonotify(struct gpio_desc *desc, int value);
+int gpiod_direction_input_nonotify(struct gpio_desc *desc);
struct gpio_desc_label {
struct rcu_head rh;
@@ -165,6 +171,7 @@ struct gpio_desc_label {
* @label: Name of the consumer
* @name: Line name
* @hog: Pointer to the device node that hogs this line (if any)
+ * @debounce_period_us: Debounce period in microseconds
*
* These are obtained using gpiod_get() and are preferable to the old
* integer-based handles.
@@ -202,6 +209,10 @@ struct gpio_desc {
#ifdef CONFIG_OF_DYNAMIC
struct device_node *hog;
#endif
+#ifdef CONFIG_GPIO_CDEV
+ /* debounce period in microseconds */
+ unsigned int debounce_period_us;
+#endif
};
#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
@@ -249,6 +260,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
const char *label,
bool platform_lookup_allowed);
+int gpio_do_set_config(struct gpio_desc *desc, unsigned long config);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags);
int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);
diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
index 3a588fecb0c5..f44de9d4b6a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
@@ -330,6 +330,8 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
}
list_for_each_entry(tmp_adev, reset_device_list, reset_list) {
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = aldebaran_mode2_restore_ip(tmp_adev);
@@ -375,6 +377,8 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
tmp_adev);
if (!r) {
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_DEFAULT);
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
r = amdgpu_ib_ring_tests(tmp_adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 3af5acff8518..4653a8d2823a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -118,7 +118,7 @@
#define MAX_GPU_INSTANCE 64
-#define GFX_SLICE_PERIOD msecs_to_jiffies(250)
+#define GFX_SLICE_PERIOD_MS 250
struct amdgpu_gpu_instance {
struct amdgpu_device *adev;
@@ -299,6 +299,12 @@ extern int amdgpu_wbrf;
#define AMDGPU_RESET_VCE (1 << 13)
#define AMDGPU_RESET_VCE1 (1 << 14)
+/* reset mask */
+#define AMDGPU_RESET_TYPE_FULL (1 << 0) /* full adapter reset, mode1/mode2/BACO/etc. */
+#define AMDGPU_RESET_TYPE_SOFT_RESET (1 << 1) /* IP level soft reset */
+#define AMDGPU_RESET_TYPE_PER_QUEUE (1 << 2) /* per queue */
+#define AMDGPU_RESET_TYPE_PER_PIPE (1 << 3) /* per pipe */
+
/* max cursor sizes (in pixels) */
#define CIK_CURSOR_WIDTH 128
#define CIK_CURSOR_HEIGHT 128
@@ -833,6 +839,7 @@ struct amdgpu_mqd {
enum amdgpu_init_lvl_id {
AMDGPU_INIT_LEVEL_DEFAULT,
AMDGPU_INIT_LEVEL_MINIMAL_XGMI,
+ AMDGPU_INIT_LEVEL_RESET_RECOVERY,
};
struct amdgpu_init_level {
@@ -1111,8 +1118,6 @@ struct amdgpu_device {
bool in_s3;
bool in_s4;
bool in_s0ix;
- /* indicate amdgpu suspension status */
- bool suspend_complete;
enum pp_mp1_state mp1_state;
struct amdgpu_doorbell_index doorbell_index;
@@ -1466,6 +1471,8 @@ struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev);
struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev,
struct dma_fence *gang);
bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev);
+ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring);
+ssize_t amdgpu_show_reset_mask(char *buf, uint32_t supported_reset);
/* atpx handler */
#if defined(CONFIG_VGA_SWITCHEROO)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
index 2ca127173135..9d6345146495 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
@@ -158,7 +158,7 @@ static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_smu_
return -EINVAL;
}
- if (start + count >= max_count)
+ if (start + count > max_count)
return -EINVAL;
count = min_t(int, count, max_count);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index cce85389427f..b8d4e07d2043 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -172,8 +172,8 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
&buffer);
obj = (union acpi_object *)buffer.pointer;
- /* Fail if calling the method fails and ATIF is supported */
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ /* Fail if calling the method fails */
+ if (ACPI_FAILURE(status)) {
DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
acpi_format_exception(status));
kfree(obj);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index b545940e512b..3afcd1e8aa54 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -834,6 +834,9 @@ int amdgpu_amdkfd_unmap_hiq(struct amdgpu_device *adev, u32 doorbell_off,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
+ if (!kiq_ring->sched.ready || adev->job_hang)
+ return 0;
+
ring_funcs = kzalloc(sizeof(*ring_funcs), GFP_KERNEL);
if (!ring_funcs)
return -ENOMEM;
@@ -858,8 +861,14 @@ int amdgpu_amdkfd_unmap_hiq(struct amdgpu_device *adev, u32 doorbell_off,
kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES, 0, 0);
- if (kiq_ring->sched.ready && !adev->job_hang)
- r = amdgpu_ring_test_helper(kiq_ring);
+ /* Submit unmap queue packet */
+ amdgpu_ring_commit(kiq_ring);
+ /*
+ * Ring test will do a basic scratch register change check. Just run
+ * this to ensure that unmap queues that is submitted before got
+ * processed successfully before returning.
+ */
+ r = amdgpu_ring_test_helper(kiq_ring);
spin_unlock(&kiq->ring_lock);
@@ -890,6 +899,15 @@ int amdgpu_amdkfd_start_sched(struct amdgpu_device *adev, uint32_t node_id)
return kgd2kfd_start_sched(adev->kfd.dev, node_id);
}
+/* check if there are KFD queues active */
+bool amdgpu_amdkfd_compute_active(struct amdgpu_device *adev, uint32_t node_id)
+{
+ if (!adev->kfd.init_complete)
+ return false;
+
+ return kgd2kfd_compute_active(adev->kfd.dev, node_id);
+}
+
/* Config CGTT_SQ_CLK_CTRL */
int amdgpu_amdkfd_config_sq_perfmon(struct amdgpu_device *adev, uint32_t xcp_id,
bool core_override_enable, bool reg_override_enable, bool perfmon_override_enable)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 7e0a22072536..4b80ad860639 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -268,6 +268,7 @@ int amdgpu_amdkfd_start_sched(struct amdgpu_device *adev, uint32_t node_id);
int amdgpu_amdkfd_stop_sched(struct amdgpu_device *adev, uint32_t node_id);
int amdgpu_amdkfd_config_sq_perfmon(struct amdgpu_device *adev, uint32_t xcp_id,
bool core_override_enable, bool reg_override_enable, bool perfmon_override_enable);
+bool amdgpu_amdkfd_compute_active(struct amdgpu_device *adev, uint32_t node_id);
/* Read user wptr from a specified user address space with page fault
@@ -431,6 +432,7 @@ int kgd2kfd_check_and_lock_kfd(void);
void kgd2kfd_unlock_kfd(void);
int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id);
int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id);
+bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id);
#else
static inline int kgd2kfd_init(void)
{
@@ -511,5 +513,10 @@ static inline int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
{
return 0;
}
+
+static inline bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id)
+{
+ return false;
+}
#endif
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 37d8657f0776..a68338cb7b4a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -402,7 +402,7 @@ static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, char __user *buf, siz
int r;
uint32_t *data, x;
- if (size & 0x3 || *pos & 0x3)
+ if (size > 4096 || size & 0x3 || *pos & 0x3)
return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
@@ -1648,7 +1648,7 @@ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
ent = debugfs_create_file(debugfs_regs_names[i],
- S_IFREG | 0444, root,
+ S_IFREG | 0400, root,
adev, debugfs_regs[i]);
if (!i && !IS_ERR_OR_NULL(ent))
i_size_write(ent->d_inode, adev->rmmio_size);
@@ -2096,17 +2096,20 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
amdgpu_debugfs_umsch_fwlog_init(adev, &adev->umsch_mm);
amdgpu_debugfs_jpeg_sched_mask_init(adev);
+ amdgpu_debugfs_gfx_sched_mask_init(adev);
+ amdgpu_debugfs_compute_sched_mask_init(adev);
+ amdgpu_debugfs_sdma_sched_mask_init(adev);
amdgpu_ras_debugfs_create_all(adev);
amdgpu_rap_debugfs_init(adev);
amdgpu_securedisplay_debugfs_init(adev);
amdgpu_fw_attestation_debugfs_init(adev);
- debugfs_create_file("amdgpu_evict_vram", 0444, root, adev,
+ debugfs_create_file("amdgpu_evict_vram", 0400, root, adev,
&amdgpu_evict_vram_fops);
- debugfs_create_file("amdgpu_evict_gtt", 0444, root, adev,
+ debugfs_create_file("amdgpu_evict_gtt", 0400, root, adev,
&amdgpu_evict_gtt_fops);
- debugfs_create_file("amdgpu_test_ib", 0444, root, adev,
+ debugfs_create_file("amdgpu_test_ib", 0400, root, adev,
&amdgpu_debugfs_test_ib_fops);
debugfs_create_file("amdgpu_vm_info", 0444, root, adev,
&amdgpu_debugfs_vm_info_fops);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index f12fab13386a..9095c05e0269 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -156,6 +156,11 @@ struct amdgpu_init_level amdgpu_init_default = {
.hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
};
+struct amdgpu_init_level amdgpu_init_recovery = {
+ .level = AMDGPU_INIT_LEVEL_RESET_RECOVERY,
+ .hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
+};
+
/*
* Minimal blocks needed to be initialized before a XGMI hive can be reset. This
* is used for cases like reset on initialization where the entire hive needs to
@@ -182,6 +187,9 @@ void amdgpu_set_init_level(struct amdgpu_device *adev,
case AMDGPU_INIT_LEVEL_MINIMAL_XGMI:
adev->init_lvl = &amdgpu_init_minimal_xgmi;
break;
+ case AMDGPU_INIT_LEVEL_RESET_RECOVERY:
+ adev->init_lvl = &amdgpu_init_recovery;
+ break;
case AMDGPU_INIT_LEVEL_DEFAULT:
fallthrough;
default:
@@ -3250,7 +3258,7 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
return r;
}
- if (!amdgpu_in_reset(adev))
+ if (!amdgpu_reset_in_recovery(adev))
amdgpu_ras_set_error_query_ready(adev, true);
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
@@ -4236,7 +4244,10 @@ int amdgpu_device_init(struct amdgpu_device *adev,
* for throttling interrupt) = 60 seconds.
*/
ratelimit_state_init(&adev->throttling_logging_rs, (60 - 1) * HZ, 1);
+ ratelimit_state_init(&adev->virt.ras_telemetry_rs, 5 * HZ, 1);
+
ratelimit_set_flags(&adev->throttling_logging_rs, RATELIMIT_MSG_ON_RELEASE);
+ ratelimit_set_flags(&adev->virt.ras_telemetry_rs, RATELIMIT_MSG_ON_RELEASE);
/* Registers mapping */
/* TODO: block userspace mapping of io register */
@@ -4666,8 +4677,8 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
int idx;
bool px;
- amdgpu_fence_driver_sw_fini(adev);
amdgpu_device_ip_fini(adev);
+ amdgpu_fence_driver_sw_fini(adev);
amdgpu_ucode_release(&adev->firmware.gpu_info_fw);
adev->accel_working = false;
dma_fence_put(rcu_dereference_protected(adev->gang_submit, true));
@@ -5186,6 +5197,9 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 3))
amdgpu_ras_resume(adev);
+
+ amdgpu_virt_ras_telemetry_post_reset(adev);
+
return 0;
}
@@ -5413,7 +5427,7 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
struct list_head *device_list_handle;
bool full_reset, vram_lost = false;
struct amdgpu_device *tmp_adev;
- int r;
+ int r, init_level;
device_list_handle = reset_context->reset_device_list;
@@ -5422,10 +5436,18 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
full_reset = test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
+ /**
+ * If it's reset on init, it's default init level, otherwise keep level
+ * as recovery level.
+ */
+ if (reset_context->method == AMD_RESET_METHOD_ON_INIT)
+ init_level = AMDGPU_INIT_LEVEL_DEFAULT;
+ else
+ init_level = AMDGPU_INIT_LEVEL_RESET_RECOVERY;
+
r = 0;
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
- /* After reset, it's default init level */
- amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
+ amdgpu_set_init_level(tmp_adev, init_level);
if (full_reset) {
/* post card */
amdgpu_ras_set_fed(tmp_adev, false);
@@ -5512,6 +5534,9 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
out:
if (!r) {
+ /* IP init is complete now, set level as default */
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_DEFAULT);
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
@@ -6200,6 +6225,9 @@ bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
bool p2p_access =
!adev->gmc.xgmi.connected_to_cpu &&
!(pci_p2pdma_distance(adev->pdev, peer_adev->dev, false) < 0);
+ if (!p2p_access)
+ dev_info(adev->dev, "PCIe P2P access from peer device %s is not supported by the chipset\n",
+ pci_name(peer_adev->pdev));
bool is_large_bar = adev->gmc.visible_vram_size &&
adev->gmc.real_vram_size == adev->gmc.visible_vram_size;
@@ -6452,6 +6480,9 @@ bool amdgpu_device_cache_pci_state(struct pci_dev *pdev)
struct amdgpu_device *adev = drm_to_adev(dev);
int r;
+ if (amdgpu_sriov_vf(adev))
+ return false;
+
r = pci_save_state(pdev);
if (!r) {
kfree(adev->pci_state);
@@ -6712,3 +6743,47 @@ uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev,
}
return ret;
}
+
+ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring)
+{
+ ssize_t size = 0;
+
+ if (!ring || !ring->adev)
+ return size;
+
+ if (amdgpu_device_should_recover_gpu(ring->adev))
+ size |= AMDGPU_RESET_TYPE_FULL;
+
+ if (unlikely(!ring->adev->debug_disable_soft_recovery) &&
+ !amdgpu_sriov_vf(ring->adev) && ring->funcs->soft_recovery)
+ size |= AMDGPU_RESET_TYPE_SOFT_RESET;
+
+ return size;
+}
+
+ssize_t amdgpu_show_reset_mask(char *buf, uint32_t supported_reset)
+{
+ ssize_t size = 0;
+
+ if (supported_reset == 0) {
+ size += sysfs_emit_at(buf, size, "unsupported");
+ size += sysfs_emit_at(buf, size, "\n");
+ return size;
+
+ }
+
+ if (supported_reset & AMDGPU_RESET_TYPE_SOFT_RESET)
+ size += sysfs_emit_at(buf, size, "soft ");
+
+ if (supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)
+ size += sysfs_emit_at(buf, size, "queue ");
+
+ if (supported_reset & AMDGPU_RESET_TYPE_PER_PIPE)
+ size += sysfs_emit_at(buf, size, "pipe ");
+
+ if (supported_reset & AMDGPU_RESET_TYPE_FULL)
+ size += sysfs_emit_at(buf, size, "full ");
+
+ size += sysfs_emit_at(buf, size, "\n");
+ return size;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 73f4d56c5de4..1040204ac8b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -1795,11 +1795,13 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
switch (le16_to_cpu(nps_info->v1.header.version_major)) {
case 1:
+ mem_ranges = kvcalloc(nps_info->v1.count,
+ sizeof(*mem_ranges),
+ GFP_KERNEL);
+ if (!mem_ranges)
+ return -ENOMEM;
*nps_type = nps_info->v1.nps_type;
*range_cnt = nps_info->v1.count;
- mem_ranges = kvzalloc(
- *range_cnt * sizeof(struct amdgpu_gmc_memrange),
- GFP_KERNEL);
for (i = 0; i < *range_cnt; i++) {
mem_ranges[i].base_address =
nps_info->v1.instance_info[i].base_address;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 6ac7d335e28e..38686203bea6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -888,7 +888,7 @@ module_param_named(visualconfirm, amdgpu_dc_visual_confirm, uint, 0444);
* the ABM algorithm, with 1 being the least reduction and 4 being the most
* reduction.
*
- * Defaults to -1, or disabled. Userspace can only override this level after
+ * Defaults to -1, or auto. Userspace can only override this level after
* boot if it's set to auto.
*/
int amdgpu_dm_abm_level = -1;
@@ -2505,7 +2505,6 @@ static int amdgpu_pmops_suspend(struct device *dev)
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
- adev->suspend_complete = false;
if (amdgpu_acpi_is_s0ix_active(adev))
adev->in_s0ix = true;
else if (amdgpu_acpi_is_s3_active(adev))
@@ -2520,7 +2519,6 @@ static int amdgpu_pmops_suspend_noirq(struct device *dev)
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
- adev->suspend_complete = true;
if (amdgpu_acpi_should_gpu_reset(adev))
return amdgpu_asic_reset(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index 35fee3e8cde2..8cd69836dd99 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -200,7 +200,7 @@ static int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
dev_err_ratelimited(&i2c_adap->dev,
"maddr:0x%04X size:0x%02X:quirk max_%s_len must be > %d",
eeprom_addr, buf_size,
- read ? "read" : "write", EEPROM_OFFSET_SIZE);
+ str_read_write(read), EEPROM_OFFSET_SIZE);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
index 00a4ab082459..df2cf5c33925 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
@@ -33,6 +33,7 @@
#include <drm/amdgpu_drm.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
#include "amdgpu.h"
#include "amdgpu_vm.h"
@@ -65,6 +66,10 @@ void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file)
[TTM_PL_VRAM] = "vram",
[TTM_PL_TT] = "gtt",
[TTM_PL_SYSTEM] = "cpu",
+ [AMDGPU_PL_GDS] = "gds",
+ [AMDGPU_PL_GWS] = "gws",
+ [AMDGPU_PL_OA] = "oa",
+ [AMDGPU_PL_DOORBELL] = "doorbell",
};
unsigned int hw_ip, i;
int ret;
@@ -86,32 +91,30 @@ void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file)
drm_printf(p, "pasid:\t%u\n", fpriv->vm.pasid);
- for (i = 0; i < TTM_PL_PRIV; i++)
+ for (i = 0; i < ARRAY_SIZE(pl_name); i++) {
+ if (!pl_name[i])
+ continue;
+
drm_print_memory_stats(p,
&stats[i].drm,
DRM_GEM_OBJECT_RESIDENT |
DRM_GEM_OBJECT_PURGEABLE,
pl_name[i]);
+ }
/* Legacy amdgpu keys, alias to drm-resident-memory-: */
drm_printf(p, "drm-memory-vram:\t%llu KiB\n",
- stats[TTM_PL_VRAM].total/1024UL);
+ stats[TTM_PL_VRAM].drm.resident/1024UL);
drm_printf(p, "drm-memory-gtt: \t%llu KiB\n",
- stats[TTM_PL_TT].total/1024UL);
+ stats[TTM_PL_TT].drm.resident/1024UL);
drm_printf(p, "drm-memory-cpu: \t%llu KiB\n",
- stats[TTM_PL_SYSTEM].total/1024UL);
+ stats[TTM_PL_SYSTEM].drm.resident/1024UL);
/* Amdgpu specific memory accounting keys: */
- drm_printf(p, "amd-memory-visible-vram:\t%llu KiB\n",
- stats[TTM_PL_VRAM].visible/1024UL);
drm_printf(p, "amd-evicted-vram:\t%llu KiB\n",
stats[TTM_PL_VRAM].evicted/1024UL);
- drm_printf(p, "amd-evicted-visible-vram:\t%llu KiB\n",
- stats[TTM_PL_VRAM].evicted_visible/1024UL);
drm_printf(p, "amd-requested-vram:\t%llu KiB\n",
stats[TTM_PL_VRAM].requested/1024UL);
- drm_printf(p, "amd-requested-visible-vram:\t%llu KiB\n",
- stats[TTM_PL_VRAM].requested_visible/1024UL);
drm_printf(p, "amd-requested-gtt:\t%llu KiB\n",
stats[TTM_PL_TT].requested/1024UL);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index 256b95232de5..b2033f8352f5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -78,8 +78,9 @@ static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev)
if (adev->dummy_page_addr)
return 0;
- adev->dummy_page_addr = dma_map_page(&adev->pdev->dev, dummy_page, 0,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
+ adev->dummy_page_addr = dma_map_page_attrs(&adev->pdev->dev, dummy_page, 0,
+ PAGE_SIZE, DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) {
dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n");
adev->dummy_page_addr = 0;
@@ -99,8 +100,9 @@ void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
{
if (!adev->dummy_page_addr)
return;
- dma_unmap_page(&adev->pdev->dev, adev->dummy_page_addr, PAGE_SIZE,
- DMA_BIDIRECTIONAL);
+ dma_unmap_page_attrs(&adev->pdev->dev, adev->dummy_page_addr, PAGE_SIZE,
+ DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
adev->dummy_page_addr = 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index e96984c53e72..69a6b6dba0a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -515,6 +515,9 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
+ if (!kiq_ring->sched.ready || adev->job_hang || amdgpu_in_reset(adev))
+ return 0;
+
spin_lock(&kiq->ring_lock);
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
adev->gfx.num_compute_rings)) {
@@ -528,20 +531,15 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
&adev->gfx.compute_ring[j],
RESET_QUEUES, 0, 0);
}
-
- /**
- * This is workaround: only skip kiq_ring test
- * during ras recovery in suspend stage for gfx9.4.3
+ /* Submit unmap queue packet */
+ amdgpu_ring_commit(kiq_ring);
+ /*
+ * Ring test will do a basic scratch register change check. Just run
+ * this to ensure that unmap queues that is submitted before got
+ * processed successfully before returning.
*/
- if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
- amdgpu_ras_in_recovery(adev)) {
- spin_unlock(&kiq->ring_lock);
- return 0;
- }
+ r = amdgpu_ring_test_helper(kiq_ring);
- if (kiq_ring->sched.ready && !adev->job_hang)
- r = amdgpu_ring_test_helper(kiq_ring);
spin_unlock(&kiq->ring_lock);
return r;
@@ -569,8 +567,11 @@ int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id)
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
- spin_lock(&kiq->ring_lock);
+ if (!adev->gfx.kiq[0].ring.sched.ready || adev->job_hang)
+ return 0;
+
if (amdgpu_gfx_is_master_xcc(adev, xcc_id)) {
+ spin_lock(&kiq->ring_lock);
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
adev->gfx.num_gfx_rings)) {
spin_unlock(&kiq->ring_lock);
@@ -583,11 +584,17 @@ int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id)
&adev->gfx.gfx_ring[j],
PREEMPT_QUEUES, 0, 0);
}
- }
+ /* Submit unmap queue packet */
+ amdgpu_ring_commit(kiq_ring);
- if (adev->gfx.kiq[0].ring.sched.ready && !adev->job_hang)
+ /*
+ * Ring test will do a basic scratch register change check.
+ * Just run this to ensure that unmap queues that is submitted
+ * before got processed successfully before returning.
+ */
r = amdgpu_ring_test_helper(kiq_ring);
- spin_unlock(&kiq->ring_lock);
+ spin_unlock(&kiq->ring_lock);
+ }
return r;
}
@@ -692,7 +699,13 @@ int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev, int xcc_id)
kiq->pmf->kiq_map_queues(kiq_ring,
&adev->gfx.compute_ring[j]);
}
-
+ /* Submit map queue packet */
+ amdgpu_ring_commit(kiq_ring);
+ /*
+ * Ring test will do a basic scratch register change check. Just run
+ * this to ensure that map queues that is submitted before got
+ * processed successfully before returning.
+ */
r = amdgpu_ring_test_helper(kiq_ring);
spin_unlock(&kiq->ring_lock);
if (r)
@@ -743,7 +756,13 @@ int amdgpu_gfx_enable_kgq(struct amdgpu_device *adev, int xcc_id)
&adev->gfx.gfx_ring[j]);
}
}
-
+ /* Submit map queue packet */
+ amdgpu_ring_commit(kiq_ring);
+ /*
+ * Ring test will do a basic scratch register change check. Just run
+ * this to ensure that map queues that is submitted before got
+ * processed successfully before returning.
+ */
r = amdgpu_ring_test_helper(kiq_ring);
spin_unlock(&kiq->ring_lock);
if (r)
@@ -885,6 +904,9 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
if (r)
return r;
+ if (amdgpu_sriov_vf(adev))
+ return r;
+
if (adev->gfx.cp_ecc_error_irq.funcs) {
r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
if (r)
@@ -1576,9 +1598,11 @@ static ssize_t amdgpu_gfx_set_enforce_isolation(struct device *dev,
if (adev->enforce_isolation[i] && !partition_values[i]) {
/* Going from enabled to disabled */
amdgpu_vmid_free_reserved(adev, AMDGPU_GFXHUB(i));
+ amdgpu_mes_set_enforce_isolation(adev, i, false);
} else if (!adev->enforce_isolation[i] && partition_values[i]) {
/* Going from disabled to enabled */
amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(i));
+ amdgpu_mes_set_enforce_isolation(adev, i, true);
}
adev->enforce_isolation[i] = partition_values[i];
}
@@ -1588,6 +1612,32 @@ static ssize_t amdgpu_gfx_set_enforce_isolation(struct device *dev,
return count;
}
+static ssize_t amdgpu_gfx_get_gfx_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->gfx.gfx_supported_reset);
+}
+
+static ssize_t amdgpu_gfx_get_compute_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->gfx.compute_supported_reset);
+}
+
static DEVICE_ATTR(run_cleaner_shader, 0200,
NULL, amdgpu_gfx_set_run_cleaner_shader);
@@ -1601,8 +1651,13 @@ static DEVICE_ATTR(current_compute_partition, 0644,
static DEVICE_ATTR(available_compute_partition, 0444,
amdgpu_gfx_get_available_compute_partition, NULL);
+static DEVICE_ATTR(gfx_reset_mask, 0444,
+ amdgpu_gfx_get_gfx_reset_mask, NULL);
-int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev)
+static DEVICE_ATTR(compute_reset_mask, 0444,
+ amdgpu_gfx_get_compute_reset_mask, NULL);
+
+static int amdgpu_gfx_sysfs_xcp_init(struct amdgpu_device *adev)
{
struct amdgpu_xcp_mgr *xcp_mgr = adev->xcp_mgr;
bool xcp_switch_supported;
@@ -1629,7 +1684,7 @@ int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev)
return r;
}
-void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev)
+static void amdgpu_gfx_sysfs_xcp_fini(struct amdgpu_device *adev)
{
struct amdgpu_xcp_mgr *xcp_mgr = adev->xcp_mgr;
bool xcp_switch_supported;
@@ -1646,25 +1701,88 @@ void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev)
&dev_attr_available_compute_partition);
}
-int amdgpu_gfx_sysfs_isolation_shader_init(struct amdgpu_device *adev)
+static int amdgpu_gfx_sysfs_isolation_shader_init(struct amdgpu_device *adev)
{
int r;
r = device_create_file(adev->dev, &dev_attr_enforce_isolation);
if (r)
return r;
+ if (adev->gfx.enable_cleaner_shader)
+ r = device_create_file(adev->dev, &dev_attr_run_cleaner_shader);
- r = device_create_file(adev->dev, &dev_attr_run_cleaner_shader);
- if (r)
+ return r;
+}
+
+static void amdgpu_gfx_sysfs_isolation_shader_fini(struct amdgpu_device *adev)
+{
+ device_remove_file(adev->dev, &dev_attr_enforce_isolation);
+ if (adev->gfx.enable_cleaner_shader)
+ device_remove_file(adev->dev, &dev_attr_run_cleaner_shader);
+}
+
+static int amdgpu_gfx_sysfs_reset_mask_init(struct amdgpu_device *adev)
+{
+ int r = 0;
+
+ if (!amdgpu_gpu_recovery)
return r;
- return 0;
+ if (adev->gfx.num_gfx_rings) {
+ r = device_create_file(adev->dev, &dev_attr_gfx_reset_mask);
+ if (r)
+ return r;
+ }
+
+ if (adev->gfx.num_compute_rings) {
+ r = device_create_file(adev->dev, &dev_attr_compute_reset_mask);
+ if (r)
+ return r;
+ }
+
+ return r;
}
-void amdgpu_gfx_sysfs_isolation_shader_fini(struct amdgpu_device *adev)
+static void amdgpu_gfx_sysfs_reset_mask_fini(struct amdgpu_device *adev)
{
- device_remove_file(adev->dev, &dev_attr_enforce_isolation);
- device_remove_file(adev->dev, &dev_attr_run_cleaner_shader);
+ if (!amdgpu_gpu_recovery)
+ return;
+
+ if (adev->gfx.num_gfx_rings)
+ device_remove_file(adev->dev, &dev_attr_gfx_reset_mask);
+
+ if (adev->gfx.num_compute_rings)
+ device_remove_file(adev->dev, &dev_attr_compute_reset_mask);
+}
+
+int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev)
+{
+ int r;
+
+ r = amdgpu_gfx_sysfs_xcp_init(adev);
+ if (r) {
+ dev_err(adev->dev, "failed to create xcp sysfs files");
+ return r;
+ }
+
+ r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
+ if (r)
+ dev_err(adev->dev, "failed to create isolation sysfs files");
+
+ r = amdgpu_gfx_sysfs_reset_mask_init(adev);
+ if (r)
+ dev_err(adev->dev, "failed to create reset mask sysfs files");
+
+ return r;
+}
+
+void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev)
+{
+ if (adev->dev->kobj.sd) {
+ amdgpu_gfx_sysfs_xcp_fini(adev);
+ amdgpu_gfx_sysfs_isolation_shader_fini(adev);
+ amdgpu_gfx_sysfs_reset_mask_fini(adev);
+ }
}
int amdgpu_gfx_cleaner_shader_sw_init(struct amdgpu_device *adev,
@@ -1752,7 +1870,7 @@ static void amdgpu_gfx_kfd_sch_ctrl(struct amdgpu_device *adev, u32 idx,
if (adev->gfx.kfd_sch_req_count[idx] == 0 &&
adev->gfx.kfd_sch_inactive[idx]) {
schedule_delayed_work(&adev->gfx.enforce_isolation[idx].work,
- GFX_SLICE_PERIOD);
+ msecs_to_jiffies(adev->gfx.enforce_isolation_time[idx]));
}
} else {
if (adev->gfx.kfd_sch_req_count[idx] == 0) {
@@ -1807,8 +1925,9 @@ void amdgpu_gfx_enforce_isolation_handler(struct work_struct *work)
fences += amdgpu_fence_count_emitted(&adev->gfx.compute_ring[i]);
}
if (fences) {
+ /* we've already had our timeslice, so let's wrap this up */
schedule_delayed_work(&adev->gfx.enforce_isolation[idx].work,
- GFX_SLICE_PERIOD);
+ msecs_to_jiffies(1));
} else {
/* Tell KFD to resume the runqueue */
if (adev->kfd.init_complete) {
@@ -1821,6 +1940,51 @@ void amdgpu_gfx_enforce_isolation_handler(struct work_struct *work)
mutex_unlock(&adev->enforce_isolation_mutex);
}
+static void
+amdgpu_gfx_enforce_isolation_wait_for_kfd(struct amdgpu_device *adev,
+ u32 idx)
+{
+ unsigned long cjiffies;
+ bool wait = false;
+
+ mutex_lock(&adev->enforce_isolation_mutex);
+ if (adev->enforce_isolation[idx]) {
+ /* set the initial values if nothing is set */
+ if (!adev->gfx.enforce_isolation_jiffies[idx]) {
+ adev->gfx.enforce_isolation_jiffies[idx] = jiffies;
+ adev->gfx.enforce_isolation_time[idx] = GFX_SLICE_PERIOD_MS;
+ }
+ /* Make sure KFD gets a chance to run */
+ if (amdgpu_amdkfd_compute_active(adev, idx)) {
+ cjiffies = jiffies;
+ if (time_after(cjiffies, adev->gfx.enforce_isolation_jiffies[idx])) {
+ cjiffies -= adev->gfx.enforce_isolation_jiffies[idx];
+ if ((jiffies_to_msecs(cjiffies) >= GFX_SLICE_PERIOD_MS)) {
+ /* if our time is up, let KGD work drain before scheduling more */
+ wait = true;
+ /* reset the timer period */
+ adev->gfx.enforce_isolation_time[idx] = GFX_SLICE_PERIOD_MS;
+ } else {
+ /* set the timer period to what's left in our time slice */
+ adev->gfx.enforce_isolation_time[idx] =
+ GFX_SLICE_PERIOD_MS - jiffies_to_msecs(cjiffies);
+ }
+ } else {
+ /* if jiffies wrap around we will just wait a little longer */
+ adev->gfx.enforce_isolation_jiffies[idx] = jiffies;
+ }
+ } else {
+ /* if there is no KFD work, then set the full slice period */
+ adev->gfx.enforce_isolation_jiffies[idx] = jiffies;
+ adev->gfx.enforce_isolation_time[idx] = GFX_SLICE_PERIOD_MS;
+ }
+ }
+ mutex_unlock(&adev->enforce_isolation_mutex);
+
+ if (wait)
+ msleep(GFX_SLICE_PERIOD_MS);
+}
+
void amdgpu_gfx_enforce_isolation_ring_begin_use(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
@@ -1837,6 +2001,9 @@ void amdgpu_gfx_enforce_isolation_ring_begin_use(struct amdgpu_ring *ring)
if (idx >= MAX_XCP)
return;
+ /* Don't submit more work until KFD has had some time */
+ amdgpu_gfx_enforce_isolation_wait_for_kfd(adev, idx);
+
mutex_lock(&adev->enforce_isolation_mutex);
if (adev->enforce_isolation[idx]) {
if (adev->kfd.init_complete)
@@ -1868,3 +2035,144 @@ void amdgpu_gfx_enforce_isolation_ring_end_use(struct amdgpu_ring *ring)
}
mutex_unlock(&adev->enforce_isolation_mutex);
}
+
+/*
+ * debugfs for to enable/disable gfx job submission to specific core.
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int amdgpu_debugfs_gfx_sched_mask_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ u32 i;
+ u64 mask = 0;
+ struct amdgpu_ring *ring;
+
+ if (!adev)
+ return -ENODEV;
+
+ mask = (1 << adev->gfx.num_gfx_rings) - 1;
+ if ((val & mask) == 0)
+ return -EINVAL;
+
+ for (i = 0; i < adev->gfx.num_gfx_rings; ++i) {
+ ring = &adev->gfx.gfx_ring[i];
+ if (val & (1 << i))
+ ring->sched.ready = true;
+ else
+ ring->sched.ready = false;
+ }
+ /* publish sched.ready flag update effective immediately across smp */
+ smp_rmb();
+ return 0;
+}
+
+static int amdgpu_debugfs_gfx_sched_mask_get(void *data, u64 *val)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ u32 i;
+ u64 mask = 0;
+ struct amdgpu_ring *ring;
+
+ if (!adev)
+ return -ENODEV;
+ for (i = 0; i < adev->gfx.num_gfx_rings; ++i) {
+ ring = &adev->gfx.gfx_ring[i];
+ if (ring->sched.ready)
+ mask |= 1 << i;
+ }
+
+ *val = mask;
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_debugfs_gfx_sched_mask_fops,
+ amdgpu_debugfs_gfx_sched_mask_get,
+ amdgpu_debugfs_gfx_sched_mask_set, "%llx\n");
+
+#endif
+
+void amdgpu_debugfs_gfx_sched_mask_init(struct amdgpu_device *adev)
+{
+#if defined(CONFIG_DEBUG_FS)
+ struct drm_minor *minor = adev_to_drm(adev)->primary;
+ struct dentry *root = minor->debugfs_root;
+ char name[32];
+
+ if (!(adev->gfx.num_gfx_rings > 1))
+ return;
+ sprintf(name, "amdgpu_gfx_sched_mask");
+ debugfs_create_file(name, 0600, root, adev,
+ &amdgpu_debugfs_gfx_sched_mask_fops);
+#endif
+}
+
+/*
+ * debugfs for to enable/disable compute job submission to specific core.
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int amdgpu_debugfs_compute_sched_mask_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ u32 i;
+ u64 mask = 0;
+ struct amdgpu_ring *ring;
+
+ if (!adev)
+ return -ENODEV;
+
+ mask = (1 << adev->gfx.num_compute_rings) - 1;
+ if ((val & mask) == 0)
+ return -EINVAL;
+
+ for (i = 0; i < adev->gfx.num_compute_rings; ++i) {
+ ring = &adev->gfx.compute_ring[i];
+ if (val & (1 << i))
+ ring->sched.ready = true;
+ else
+ ring->sched.ready = false;
+ }
+
+ /* publish sched.ready flag update effective immediately across smp */
+ smp_rmb();
+ return 0;
+}
+
+static int amdgpu_debugfs_compute_sched_mask_get(void *data, u64 *val)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ u32 i;
+ u64 mask = 0;
+ struct amdgpu_ring *ring;
+
+ if (!adev)
+ return -ENODEV;
+ for (i = 0; i < adev->gfx.num_compute_rings; ++i) {
+ ring = &adev->gfx.compute_ring[i];
+ if (ring->sched.ready)
+ mask |= 1 << i;
+ }
+
+ *val = mask;
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_debugfs_compute_sched_mask_fops,
+ amdgpu_debugfs_compute_sched_mask_get,
+ amdgpu_debugfs_compute_sched_mask_set, "%llx\n");
+
+#endif
+
+void amdgpu_debugfs_compute_sched_mask_init(struct amdgpu_device *adev)
+{
+#if defined(CONFIG_DEBUG_FS)
+ struct drm_minor *minor = adev_to_drm(adev)->primary;
+ struct dentry *root = minor->debugfs_root;
+ char name[32];
+
+ if (!(adev->gfx.num_compute_rings > 1))
+ return;
+ sprintf(name, "amdgpu_compute_sched_mask");
+ debugfs_create_file(name, 0600, root, adev,
+ &amdgpu_debugfs_compute_sched_mask_fops);
+#endif
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index f710178a21bc..8b5bd63b5773 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -424,6 +424,8 @@ struct amdgpu_gfx {
/* reset mask */
uint32_t grbm_soft_reset;
uint32_t srbm_soft_reset;
+ uint32_t gfx_supported_reset;
+ uint32_t compute_supported_reset;
/* gfx off */
bool gfx_off_state; /* true: enabled, false: disabled */
@@ -472,6 +474,8 @@ struct amdgpu_gfx {
struct mutex kfd_sch_mutex;
u64 kfd_sch_req_count[MAX_XCP];
bool kfd_sch_inactive[MAX_XCP];
+ unsigned long enforce_isolation_jiffies[MAX_XCP];
+ unsigned long enforce_isolation_time[MAX_XCP];
};
struct amdgpu_gfx_ras_reg_entry {
@@ -577,11 +581,11 @@ void amdgpu_gfx_cleaner_shader_sw_fini(struct amdgpu_device *adev);
void amdgpu_gfx_cleaner_shader_init(struct amdgpu_device *adev,
unsigned int cleaner_shader_size,
const void *cleaner_shader_ptr);
-int amdgpu_gfx_sysfs_isolation_shader_init(struct amdgpu_device *adev);
-void amdgpu_gfx_sysfs_isolation_shader_fini(struct amdgpu_device *adev);
void amdgpu_gfx_enforce_isolation_handler(struct work_struct *work);
void amdgpu_gfx_enforce_isolation_ring_begin_use(struct amdgpu_ring *ring);
void amdgpu_gfx_enforce_isolation_ring_end_use(struct amdgpu_ring *ring);
+void amdgpu_debugfs_gfx_sched_mask_init(struct amdgpu_device *adev);
+void amdgpu_debugfs_compute_sched_mask_init(struct amdgpu_device *adev);
static inline const char *amdgpu_gfx_compute_mode_desc(int mode)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index ea2663169bf3..b9d08bc96581 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -137,6 +137,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
/* attempt a per ring reset */
if (amdgpu_gpu_recovery &&
ring->funcs->reset) {
+ dev_err(adev->dev, "Starting %s ring reset\n", s_job->sched->name);
/* stop the scheduler, but don't mess with the
* bad job yet because if ring reset fails
* we'll fall back to full GPU reset.
@@ -152,6 +153,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
drm_sched_start(&ring->sched, 0);
goto exit;
}
+ dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name);
}
if (amdgpu_device_should_recover_gpu(ring->adev)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
index 95e2796919fc..b6d2eb049f54 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
@@ -47,7 +47,7 @@ int amdgpu_jpeg_sw_init(struct amdgpu_device *adev)
adev->jpeg.indirect_sram = true;
for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {
- if (adev->jpeg.harvest_config & (1 << i))
+ if (adev->jpeg.harvest_config & (1U << i))
continue;
if (adev->jpeg.indirect_sram) {
@@ -73,7 +73,7 @@ int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev)
int i, j;
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
- if (adev->jpeg.harvest_config & (1 << i))
+ if (adev->jpeg.harvest_config & (1U << i))
continue;
amdgpu_bo_free_kernel(
@@ -110,7 +110,7 @@ static void amdgpu_jpeg_idle_work_handler(struct work_struct *work)
unsigned int i, j;
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
- if (adev->jpeg.harvest_config & (1 << i))
+ if (adev->jpeg.harvest_config & (1U << i))
continue;
for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j)
@@ -357,7 +357,7 @@ static int amdgpu_debugfs_jpeg_sched_mask_set(void *data, u64 val)
if (!adev)
return -ENODEV;
- mask = (1 << (adev->jpeg.num_jpeg_inst * adev->jpeg.num_jpeg_rings)) - 1;
+ mask = (1ULL << (adev->jpeg.num_jpeg_inst * adev->jpeg.num_jpeg_rings)) - 1;
if ((val & mask) == 0)
return -EINVAL;
@@ -388,7 +388,7 @@ static int amdgpu_debugfs_jpeg_sched_mask_get(void *data, u64 *val)
for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {
ring = &adev->jpeg.inst[i].ring_dec[j];
if (ring->sched.ready)
- mask |= 1 << ((i * adev->jpeg.num_jpeg_rings) + j);
+ mask |= 1ULL << ((i * adev->jpeg.num_jpeg_rings) + j);
}
}
*val = mask;
@@ -415,3 +415,40 @@ void amdgpu_debugfs_jpeg_sched_mask_init(struct amdgpu_device *adev)
&amdgpu_debugfs_jpeg_sched_mask_fops);
#endif
}
+
+static ssize_t amdgpu_get_jpeg_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->jpeg.supported_reset);
+}
+
+static DEVICE_ATTR(jpeg_reset_mask, 0444,
+ amdgpu_get_jpeg_reset_mask, NULL);
+
+int amdgpu_jpeg_sysfs_reset_mask_init(struct amdgpu_device *adev)
+{
+ int r = 0;
+
+ if (adev->jpeg.num_jpeg_inst) {
+ r = device_create_file(adev->dev, &dev_attr_jpeg_reset_mask);
+ if (r)
+ return r;
+ }
+
+ return r;
+}
+
+void amdgpu_jpeg_sysfs_reset_mask_fini(struct amdgpu_device *adev)
+{
+ if (adev->dev->kobj.sd) {
+ if (adev->jpeg.num_jpeg_inst)
+ device_remove_file(adev->dev, &dev_attr_jpeg_reset_mask);
+ }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
index 819dc7a0af99..3eb4a4653fce 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
@@ -128,6 +128,7 @@ struct amdgpu_jpeg {
uint16_t inst_mask;
uint8_t num_inst_per_aid;
bool indirect_sram;
+ uint32_t supported_reset;
};
int amdgpu_jpeg_sw_init(struct amdgpu_device *adev);
@@ -150,5 +151,7 @@ int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_jpeg_psp_update_sram(struct amdgpu_device *adev, int inst_idx,
enum AMDGPU_UCODE_ID ucode_id);
void amdgpu_debugfs_jpeg_sched_mask_init(struct amdgpu_device *adev);
+int amdgpu_jpeg_sysfs_reset_mask_init(struct amdgpu_device *adev);
+void amdgpu_jpeg_sysfs_reset_mask_fini(struct amdgpu_device *adev);
#endif /*__AMDGPU_JPEG_H__*/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
index 18ee60378727..3ca03b5e0f91 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
@@ -348,6 +348,24 @@ static bool amdgpu_mca_bank_should_update(struct amdgpu_device *adev, enum amdgp
return ret;
}
+static bool amdgpu_mca_bank_should_dump(struct amdgpu_device *adev, enum amdgpu_mca_error_type type,
+ struct mca_bank_entry *entry)
+{
+ bool ret;
+
+ switch (type) {
+ case AMDGPU_MCA_ERROR_TYPE_CE:
+ ret = amdgpu_mca_is_deferred_error(adev, entry->regs[MCA_REG_IDX_STATUS]);
+ break;
+ case AMDGPU_MCA_ERROR_TYPE_UE:
+ default:
+ ret = true;
+ break;
+ }
+
+ return ret;
+}
+
static int amdgpu_mca_smu_get_mca_set(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, struct mca_bank_set *mca_set,
struct ras_query_context *qctx)
{
@@ -373,7 +391,8 @@ static int amdgpu_mca_smu_get_mca_set(struct amdgpu_device *adev, enum amdgpu_mc
amdgpu_mca_bank_set_add_entry(mca_set, &entry);
- amdgpu_mca_smu_mca_bank_dump(adev, i, &entry, qctx);
+ if (amdgpu_mca_bank_should_dump(adev, type, &entry))
+ amdgpu_mca_smu_mca_bank_dump(adev, i, &entry, qctx);
}
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
index 6909af56fcad..59ec20b07a6a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
@@ -104,7 +104,7 @@ static int amdgpu_mes_event_log_init(struct amdgpu_device *adev)
return 0;
r = amdgpu_bo_create_kernel(adev, adev->mes.event_log_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_GTT,
+ AMDGPU_GEM_DOMAIN_VRAM,
&adev->mes.event_log_gpu_obj,
&adev->mes.event_log_gpu_addr,
&adev->mes.event_log_cpu_addr);
@@ -192,17 +192,6 @@ int amdgpu_mes_init(struct amdgpu_device *adev)
(uint64_t *)&adev->wb.wb[adev->mes.query_status_fence_offs[i]];
}
- r = amdgpu_device_wb_get(adev, &adev->mes.read_val_offs);
- if (r) {
- dev_err(adev->dev,
- "(%d) read_val_offs alloc failed\n", r);
- goto error;
- }
- adev->mes.read_val_gpu_addr =
- adev->wb.gpu_addr + (adev->mes.read_val_offs * 4);
- adev->mes.read_val_ptr =
- (uint32_t *)&adev->wb.wb[adev->mes.read_val_offs];
-
r = amdgpu_mes_doorbell_init(adev);
if (r)
goto error;
@@ -223,8 +212,6 @@ error:
amdgpu_device_wb_free(adev,
adev->mes.query_status_fence_offs[i]);
}
- if (adev->mes.read_val_ptr)
- amdgpu_device_wb_free(adev, adev->mes.read_val_offs);
idr_destroy(&adev->mes.pasid_idr);
idr_destroy(&adev->mes.gang_id_idr);
@@ -249,8 +236,6 @@ void amdgpu_mes_fini(struct amdgpu_device *adev)
amdgpu_device_wb_free(adev,
adev->mes.query_status_fence_offs[i]);
}
- if (adev->mes.read_val_ptr)
- amdgpu_device_wb_free(adev, adev->mes.read_val_offs);
amdgpu_mes_doorbell_free(adev);
@@ -921,10 +906,19 @@ uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg)
{
struct mes_misc_op_input op_input;
int r, val = 0;
+ uint32_t addr_offset = 0;
+ uint64_t read_val_gpu_addr;
+ uint32_t *read_val_ptr;
+ if (amdgpu_device_wb_get(adev, &addr_offset)) {
+ DRM_ERROR("critical bug! too many mes readers\n");
+ goto error;
+ }
+ read_val_gpu_addr = adev->wb.gpu_addr + (addr_offset * 4);
+ read_val_ptr = (uint32_t *)&adev->wb.wb[addr_offset];
op_input.op = MES_MISC_OP_READ_REG;
op_input.read_reg.reg_offset = reg;
- op_input.read_reg.buffer_addr = adev->mes.read_val_gpu_addr;
+ op_input.read_reg.buffer_addr = read_val_gpu_addr;
if (!adev->mes.funcs->misc_op) {
DRM_ERROR("mes rreg is not supported!\n");
@@ -935,9 +929,11 @@ uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg)
if (r)
DRM_ERROR("failed to read reg (0x%x)\n", reg);
else
- val = *(adev->mes.read_val_ptr);
+ val = *(read_val_ptr);
error:
+ if (addr_offset)
+ amdgpu_device_wb_free(adev, addr_offset);
return val;
}
@@ -1594,6 +1590,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
char ucode_prefix[30];
char fw_name[50];
bool need_retry = false;
+ u32 *ucode_ptr;
int r;
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix,
@@ -1631,6 +1628,10 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
adev->mes.data_start_addr[pipe] =
le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
+ ucode_ptr = (u32 *)(adev->mes.fw[pipe]->data +
+ sizeof(union amdgpu_firmware_header));
+ adev->mes.fw_version[pipe] =
+ le32_to_cpu(ucode_ptr[24]) & AMDGPU_MES_VERSION_MASK;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
int ucode, ucode_data;
@@ -1677,6 +1678,29 @@ bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev)
return is_supported;
}
+/* Fix me -- node_id is used to identify the correct MES instances in the future */
+int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable)
+{
+ struct mes_misc_op_input op_input = {0};
+ int r;
+
+ op_input.op = MES_MISC_OP_CHANGE_CONFIG;
+ op_input.change_config.option.limit_single_process = enable ? 1 : 0;
+
+ if (!adev->mes.funcs->misc_op) {
+ dev_err(adev->dev, "mes change config is not supported!\n");
+ r = -EINVAL;
+ goto error;
+ }
+
+ r = adev->mes.funcs->misc_op(&adev->mes, &op_input);
+ if (r)
+ dev_err(adev->dev, "failed to change_config.\n");
+
+error:
+ return r;
+}
+
#if defined(CONFIG_DEBUG_FS)
static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
index 96788c0f42f1..c6f93cbd6739 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
@@ -40,6 +40,7 @@
#define AMDGPU_MES_VERSION_MASK 0x00000fff
#define AMDGPU_MES_API_VERSION_MASK 0x00fff000
#define AMDGPU_MES_FEAT_VERSION_MASK 0xff000000
+#define AMDGPU_MES_MSCRATCH_SIZE 0x8000
enum amdgpu_mes_priority_level {
AMDGPU_MES_PRIORITY_LEVEL_LOW = 0,
@@ -75,6 +76,7 @@ struct amdgpu_mes {
uint32_t sched_version;
uint32_t kiq_version;
+ uint32_t fw_version[AMDGPU_MAX_MES_PIPES];
bool enable_legacy_queue_map;
uint32_t total_max_queue;
@@ -119,9 +121,6 @@ struct amdgpu_mes {
uint32_t query_status_fence_offs[AMDGPU_MAX_MES_PIPES];
uint64_t query_status_fence_gpu_addr[AMDGPU_MAX_MES_PIPES];
uint64_t *query_status_fence_ptr[AMDGPU_MAX_MES_PIPES];
- uint32_t read_val_offs;
- uint64_t read_val_gpu_addr;
- uint32_t *read_val_ptr;
uint32_t saved_flags;
@@ -310,6 +309,7 @@ enum mes_misc_opcode {
MES_MISC_OP_WRM_REG_WAIT,
MES_MISC_OP_WRM_REG_WR_WAIT,
MES_MISC_OP_SET_SHADER_DEBUGGER,
+ MES_MISC_OP_CHANGE_CONFIG,
};
struct mes_misc_op_input {
@@ -348,6 +348,21 @@ struct mes_misc_op_input {
uint32_t tcp_watch_cntl[4];
uint32_t trap_en;
} set_shader_debugger;
+
+ struct {
+ union {
+ struct {
+ uint32_t limit_single_process : 1;
+ uint32_t enable_hws_logging_buffer : 1;
+ uint32_t reserved : 30;
+ };
+ uint32_t all;
+ } option;
+ struct {
+ uint32_t tdr_level;
+ uint32_t tdr_delay;
+ } tdr_config;
+ } change_config;
};
};
@@ -518,4 +533,7 @@ static inline void amdgpu_mes_unlock(struct amdgpu_mes *mes)
}
bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev);
+
+int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable);
+
#endif /* __AMDGPU_MES_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 1e6a044e3143..6852d50caa89 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -40,6 +40,7 @@
#include "amdgpu_trace.h"
#include "amdgpu_amdkfd.h"
#include "amdgpu_vram_mgr.h"
+#include "amdgpu_vm.h"
/**
* DOC: amdgpu_object
@@ -161,7 +162,8 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
* When GTT is just an alternative to VRAM make sure that we
* only use it as fallback and still try to fill up VRAM first.
*/
- if (domain & abo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM)
+ if (domain & abo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM &&
+ !(adev->flags & AMD_IS_APU))
places[c].flags |= TTM_PL_FLAG_FALLBACK;
c++;
}
@@ -1208,23 +1210,11 @@ void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
type = res->mem_type;
}
- /* Squash some into 'cpu' to keep the legacy userspace view. */
- switch (type) {
- case TTM_PL_VRAM:
- case TTM_PL_TT:
- case TTM_PL_SYSTEM:
- break;
- default:
- type = TTM_PL_SYSTEM;
- break;
- }
-
if (drm_WARN_ON_ONCE(&adev->ddev, type >= sz))
return;
/* DRM stats common fields: */
- stats[type].total += size;
if (drm_gem_object_is_shared_for_memory_stats(obj))
stats[type].drm.shared += size;
else
@@ -1237,23 +1227,14 @@ void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
stats[type].drm.active += size;
else if (bo->flags & AMDGPU_GEM_CREATE_DISCARDABLE)
stats[type].drm.purgeable += size;
-
- if (type == TTM_PL_VRAM && amdgpu_res_cpu_visible(adev, res))
- stats[type].visible += size;
}
/* amdgpu specific stats: */
if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) {
stats[TTM_PL_VRAM].requested += size;
- if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
- stats[TTM_PL_VRAM].requested_visible += size;
-
- if (type != TTM_PL_VRAM) {
+ if (type != TTM_PL_VRAM)
stats[TTM_PL_VRAM].evicted += size;
- if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
- stats[TTM_PL_VRAM].evicted_visible += size;
- }
} else if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_GTT) {
stats[TTM_PL_TT].requested += size;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 7260349917ef..be6769852ece 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -139,17 +139,6 @@ struct amdgpu_bo_vm {
struct amdgpu_vm_bo_base entries[];
};
-struct amdgpu_mem_stats {
- struct drm_memory_stats drm;
-
- uint64_t total;
- uint64_t visible;
- uint64_t evicted;
- uint64_t evicted_visible;
- uint64_t requested;
- uint64_t requested_visible;
-};
-
static inline struct amdgpu_bo *ttm_to_amdgpu_bo(struct ttm_buffer_object *tbo)
{
return container_of(tbo, struct amdgpu_bo, tbo);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
index e8adfd0a570a..34b5e22b44e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
@@ -137,7 +137,8 @@ void amdgpu_preempt_mgr_fini(struct amdgpu_device *adev)
if (ret)
return;
- device_remove_file(adev->dev, &dev_attr_mem_info_preempt_used);
+ if (adev->dev->kobj.sd)
+ device_remove_file(adev->dev, &dev_attr_mem_info_preempt_used);
ttm_resource_manager_cleanup(man);
ttm_set_driver_manager(&adev->mman.bdev, AMDGPU_PL_PREEMPT, NULL);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index abd5e980c9c7..448f9e742983 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -1834,6 +1834,9 @@ int psp_ras_initialize(struct psp_context *psp)
ras_cmd->ras_in_message.init_flags.xcc_mask =
adev->gfx.xcc_mask;
ras_cmd->ras_in_message.init_flags.channel_dis_num = hweight32(adev->gmc.m_half_use) * 2;
+ if (adev->gmc.gmc_funcs->query_mem_partition_mode)
+ ras_cmd->ras_in_message.init_flags.nps_mode =
+ adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
ret = psp_ta_load(psp, &psp->ras_context.context);
@@ -3563,6 +3566,36 @@ out:
return err;
}
+static bool is_ta_fw_applicable(struct psp_context *psp,
+ const struct psp_fw_bin_desc *desc)
+{
+ struct amdgpu_device *adev = psp->adev;
+ uint32_t fw_version;
+
+ switch (desc->fw_type) {
+ case TA_FW_TYPE_PSP_XGMI:
+ case TA_FW_TYPE_PSP_XGMI_AUX:
+ /* for now, AUX TA only exists on 13.0.6 ta bin,
+ * from v20.00.0x.14
+ */
+ if (amdgpu_ip_version(adev, MP0_HWIP, 0) ==
+ IP_VERSION(13, 0, 6)) {
+ fw_version = le32_to_cpu(desc->fw_version);
+
+ if (adev->flags & AMD_IS_APU &&
+ (fw_version & 0xff) >= 0x14)
+ return desc->fw_type == TA_FW_TYPE_PSP_XGMI_AUX;
+ else
+ return desc->fw_type == TA_FW_TYPE_PSP_XGMI;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
static int parse_ta_bin_descriptor(struct psp_context *psp,
const struct psp_fw_bin_desc *desc,
const struct ta_firmware_header_v2_0 *ta_hdr)
@@ -3572,6 +3605,9 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
if (!psp || !desc || !ta_hdr)
return -EINVAL;
+ if (!is_ta_fw_applicable(psp, desc))
+ return 0;
+
ucode_start_addr = (uint8_t *)ta_hdr +
le32_to_cpu(desc->offset_bytes) +
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
@@ -3584,6 +3620,7 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
psp->asd_context.bin_desc.start_addr = ucode_start_addr;
break;
case TA_FW_TYPE_PSP_XGMI:
+ case TA_FW_TYPE_PSP_XGMI_AUX:
psp->xgmi_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
psp->xgmi_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
psp->xgmi_context.context.bin_desc.start_addr = ucode_start_addr;
@@ -4075,7 +4112,7 @@ static umode_t amdgpu_flash_attr_is_visible(struct kobject *kobj, struct attribu
}
static umode_t amdgpu_bin_flash_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
int idx)
{
struct device *dev = kobj_to_dev(kobj);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 1d9eda883bb8..4c9fa24dd972 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1214,6 +1214,42 @@ static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev,
}
}
+static void amdgpu_ras_virt_error_generate_report(struct amdgpu_device *adev,
+ struct ras_query_if *query_if,
+ struct ras_err_data *err_data,
+ struct ras_query_context *qctx)
+{
+ unsigned long new_ue, new_ce, new_de;
+ struct ras_manager *obj = amdgpu_ras_find_obj(adev, &query_if->head);
+ const char *blk_name = get_ras_block_str(&query_if->head);
+ u64 event_id = qctx->evid.event_id;
+
+ new_ce = err_data->ce_count - obj->err_data.ce_count;
+ new_ue = err_data->ue_count - obj->err_data.ue_count;
+ new_de = err_data->de_count - obj->err_data.de_count;
+
+ if (new_ce) {
+ RAS_EVENT_LOG(adev, event_id, "%lu correctable hardware errors "
+ "detected in %s block\n",
+ new_ce,
+ blk_name);
+ }
+
+ if (new_ue) {
+ RAS_EVENT_LOG(adev, event_id, "%lu uncorrectable hardware errors "
+ "detected in %s block\n",
+ new_ue,
+ blk_name);
+ }
+
+ if (new_de) {
+ RAS_EVENT_LOG(adev, event_id, "%lu deferred hardware errors "
+ "detected in %s block\n",
+ new_de,
+ blk_name);
+ }
+}
+
static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, struct ras_err_data *err_data)
{
struct ras_err_node *err_node;
@@ -1237,6 +1273,15 @@ static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, s
}
}
+static void amdgpu_ras_mgr_virt_error_data_statistics_update(struct ras_manager *obj,
+ struct ras_err_data *err_data)
+{
+ /* Host reports absolute counts */
+ obj->err_data.ue_count = err_data->ue_count;
+ obj->err_data.ce_count = err_data->ce_count;
+ obj->err_data.de_count = err_data->de_count;
+}
+
static struct ras_manager *get_ras_manager(struct amdgpu_device *adev, enum amdgpu_ras_block blk)
{
struct ras_common_if head;
@@ -1253,7 +1298,7 @@ int amdgpu_ras_bind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
struct ras_manager *obj;
/* in resume phase, no need to create aca fs node */
- if (adev->in_suspend || amdgpu_in_reset(adev))
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev))
return 0;
obj = get_ras_manager(adev, blk);
@@ -1323,7 +1368,9 @@ static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev,
if (error_query_mode == AMDGPU_RAS_INVALID_ERROR_QUERY)
return -EINVAL;
- if (error_query_mode == AMDGPU_RAS_DIRECT_ERROR_QUERY) {
+ if (error_query_mode == AMDGPU_RAS_VIRT_ERROR_COUNT_QUERY) {
+ return amdgpu_virt_req_ras_err_count(adev, blk, err_data);
+ } else if (error_query_mode == AMDGPU_RAS_DIRECT_ERROR_QUERY) {
if (info->head.block == AMDGPU_RAS_BLOCK__UMC) {
amdgpu_ras_get_ecc_info(adev, err_data);
} else {
@@ -1405,14 +1452,22 @@ static int amdgpu_ras_query_error_status_with_event(struct amdgpu_device *adev,
if (ret)
goto out_fini_err_data;
- amdgpu_rasmgr_error_data_statistic_update(obj, &err_data);
+ if (error_query_mode != AMDGPU_RAS_VIRT_ERROR_COUNT_QUERY) {
+ amdgpu_rasmgr_error_data_statistic_update(obj, &err_data);
+ amdgpu_ras_error_generate_report(adev, info, &err_data, &qctx);
+ } else {
+ /* Host provides absolute error counts. First generate the report
+ * using the previous VF internal count against new host count.
+ * Then Update VF internal count.
+ */
+ amdgpu_ras_virt_error_generate_report(adev, info, &err_data, &qctx);
+ amdgpu_ras_mgr_virt_error_data_statistics_update(obj, &err_data);
+ }
info->ue_count = obj->err_data.ue_count;
info->ce_count = obj->err_data.ce_count;
info->de_count = obj->err_data.de_count;
- amdgpu_ras_error_generate_report(adev, info, &err_data, &qctx);
-
out_fini_err_data:
amdgpu_ras_error_data_fini(&err_data);
@@ -2605,6 +2660,7 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
reset_context.method = AMD_RESET_METHOD_NONE;
reset_context.reset_req_dev = adev;
reset_context.src = AMDGPU_RESET_SRC_RAS;
+ set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
/* Perform full reset in fatal error mode */
if (!amdgpu_ras_is_poison_mode_supported(ras->adev))
@@ -3452,6 +3508,11 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev)
if (!amdgpu_ras_asic_supported(adev))
return;
+ if (amdgpu_sriov_vf(adev)) {
+ if (amdgpu_virt_get_ras_capability(adev))
+ goto init_ras_enabled_flag;
+ }
+
/* query ras capability from psp */
if (amdgpu_psp_get_ras_capability(&adev->psp))
goto init_ras_enabled_flag;
@@ -3549,7 +3610,7 @@ static void amdgpu_ras_event_mgr_init(struct amdgpu_device *adev)
ras->event_mgr = hive ? &hive->event_mgr : &ras->__event_mgr;
/* init event manager with node 0 on xgmi system */
- if (!amdgpu_in_reset(adev)) {
+ if (!amdgpu_reset_in_recovery(adev)) {
if (!hive || adev->gmc.xgmi.node_id == 0)
ras_event_mgr_init(ras->event_mgr);
}
@@ -3764,7 +3825,7 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
r = amdgpu_ras_feature_enable_on_boot(adev, ras_block, 1);
if (r) {
- if (adev->in_suspend || amdgpu_in_reset(adev)) {
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev)) {
/* in resume phase, if fail to enable ras,
* clean up all ras fs nodes, and disable ras */
goto cleanup;
@@ -3776,7 +3837,7 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
amdgpu_persistent_edc_harvesting(adev, ras_block);
/* in resume phase, no need to create ras fs node */
- if (adev->in_suspend || amdgpu_in_reset(adev))
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev))
return 0;
ras_obj = container_of(ras_block, struct amdgpu_ras_block_object, ras_comm);
@@ -3906,7 +3967,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
amdgpu_ras_event_mgr_init(adev);
if (amdgpu_ras_aca_is_supported(adev)) {
- if (amdgpu_in_reset(adev)) {
+ if (amdgpu_reset_in_recovery(adev)) {
if (amdgpu_aca_is_enabled(adev))
r = amdgpu_aca_reset(adev);
else
@@ -3924,7 +3985,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
}
/* Guest side doesn't need init ras feature */
- if (amdgpu_sriov_vf(adev))
+ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_ras_telemetry_en(adev))
return 0;
list_for_each_entry_safe(node, tmp, &adev->ras_list, node) {
@@ -4391,11 +4452,14 @@ bool amdgpu_ras_get_error_query_mode(struct amdgpu_device *adev,
return false;
}
- if ((smu_funcs && smu_funcs->set_debug_mode) || (mca_funcs && mca_funcs->mca_set_debug_mode))
+ if (amdgpu_sriov_vf(adev)) {
+ *error_query_mode = AMDGPU_RAS_VIRT_ERROR_COUNT_QUERY;
+ } else if ((smu_funcs && smu_funcs->set_debug_mode) || (mca_funcs && mca_funcs->mca_set_debug_mode)) {
*error_query_mode =
(con->is_aca_debug_mode) ? AMDGPU_RAS_DIRECT_ERROR_QUERY : AMDGPU_RAS_FIRMWARE_ERROR_QUERY;
- else
+ } else {
*error_query_mode = AMDGPU_RAS_DIRECT_ERROR_QUERY;
+ }
return true;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
index 871b2d6278e0..6db772ecfee4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -365,6 +365,7 @@ enum amdgpu_ras_error_query_mode {
AMDGPU_RAS_INVALID_ERROR_QUERY = 0,
AMDGPU_RAS_DIRECT_ERROR_QUERY = 1,
AMDGPU_RAS_FIRMWARE_ERROR_QUERY = 2,
+ AMDGPU_RAS_VIRT_ERROR_COUNT_QUERY = 3,
};
/* ras error status reisger fields */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
index 24dae7cdbe95..a0acb65f4b40 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
@@ -342,3 +342,8 @@ void amdgpu_reset_get_desc(struct amdgpu_reset_context *rst_ctxt, char *buf,
strscpy(buf, "unknown", len);
}
}
+
+bool amdgpu_reset_in_recovery(struct amdgpu_device *adev)
+{
+ return (adev->init_lvl->level == AMDGPU_INIT_LEVEL_RESET_RECOVERY);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
index f8628bc898df..4d9b9701139b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
@@ -158,4 +158,6 @@ extern struct amdgpu_reset_handler xgmi_reset_on_init_handler;
int amdgpu_reset_do_xgmi_reset_on_init(
struct amdgpu_reset_context *reset_context);
+bool amdgpu_reset_in_recovery(struct amdgpu_device *adev);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 42f616c05f50..a6e28fe3f8d6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -109,21 +109,17 @@ int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned int ndw)
void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
{
uint32_t occupied, chunk1, chunk2;
- uint32_t *dst;
occupied = ring->wptr & ring->buf_mask;
- dst = (void *)&ring->ring[occupied];
chunk1 = ring->buf_mask + 1 - occupied;
chunk1 = (chunk1 >= count) ? count : chunk1;
chunk2 = count - chunk1;
if (chunk1)
- memset32(dst, ring->funcs->nop, chunk1);
+ memset32(&ring->ring[occupied], ring->funcs->nop, chunk1);
- if (chunk2) {
- dst = (void *)ring->ring;
- memset32(dst, ring->funcs->nop, chunk2);
- }
+ if (chunk2)
+ memset32(ring->ring, ring->funcs->nop, chunk2);
ring->wptr += count;
ring->wptr &= ring->ptr_mask;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 574336d6714a..36fc9578c53c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -246,7 +246,7 @@ struct amdgpu_ring {
struct drm_gpu_scheduler sched;
struct amdgpu_bo *ring_obj;
- volatile uint32_t *ring;
+ uint32_t *ring;
unsigned rptr_offs;
u64 rptr_gpu_addr;
volatile u32 *rptr_cpu_addr;
@@ -288,7 +288,7 @@ struct amdgpu_ring {
u64 cond_exe_gpu_addr;
volatile u32 *cond_exe_cpu_addr;
unsigned int set_q_mode_offs;
- volatile u32 *set_q_mode_ptr;
+ u32 *set_q_mode_ptr;
u64 set_q_mode_token;
unsigned vm_hub;
unsigned vm_inv_eng;
@@ -386,10 +386,8 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring,
void *src, int count_dw)
{
unsigned occupied, chunk1, chunk2;
- void *dst;
occupied = ring->wptr & ring->buf_mask;
- dst = (void *)&ring->ring[occupied];
chunk1 = ring->buf_mask + 1 - occupied;
chunk1 = (chunk1 >= count_dw) ? count_dw : chunk1;
chunk2 = count_dw - chunk1;
@@ -397,12 +395,11 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring,
chunk2 <<= 2;
if (chunk1)
- memcpy(dst, src, chunk1);
+ memcpy(&ring->ring[occupied], src, chunk1);
if (chunk2) {
src += chunk1;
- dst = (void *)ring->ring;
- memcpy(dst, src, chunk2);
+ memcpy(ring->ring, src, chunk2);
}
ring->wptr += count_dw;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
index b0a8abc7a8ec..341beec59537 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
@@ -35,21 +35,19 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
int fd,
int32_t priority)
{
- struct fd f = fdget(fd);
+ CLASS(fd, f)(fd);
struct amdgpu_fpriv *fpriv;
struct amdgpu_ctx_mgr *mgr;
struct amdgpu_ctx *ctx;
uint32_t id;
int r;
- if (!fd_file(f))
+ if (fd_empty(f))
return -EINVAL;
r = amdgpu_file_to_fpriv(fd_file(f), &fpriv);
- if (r) {
- fdput(f);
+ if (r)
return r;
- }
mgr = &fpriv->ctx_mgr;
mutex_lock(&mgr->lock);
@@ -57,7 +55,6 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
amdgpu_ctx_priority_override(ctx, priority);
mutex_unlock(&mgr->lock);
- fdput(f);
return 0;
}
@@ -66,31 +63,25 @@ static int amdgpu_sched_context_priority_override(struct amdgpu_device *adev,
unsigned ctx_id,
int32_t priority)
{
- struct fd f = fdget(fd);
+ CLASS(fd, f)(fd);
struct amdgpu_fpriv *fpriv;
struct amdgpu_ctx *ctx;
int r;
- if (!fd_file(f))
+ if (fd_empty(f))
return -EINVAL;
r = amdgpu_file_to_fpriv(fd_file(f), &fpriv);
- if (r) {
- fdput(f);
+ if (r)
return r;
- }
ctx = amdgpu_ctx_get(fpriv, ctx_id);
- if (!ctx) {
- fdput(f);
+ if (!ctx)
return -EINVAL;
- }
amdgpu_ctx_priority_override(ctx, priority);
amdgpu_ctx_put(ctx);
- fdput(f);
-
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 183a976ba29d..113f0d242618 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -343,3 +343,116 @@ int amdgpu_sdma_ras_sw_init(struct amdgpu_device *adev)
return 0;
}
+
+/*
+ * debugfs for to enable/disable sdma job submission to specific core.
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int amdgpu_debugfs_sdma_sched_mask_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ u32 i;
+ u64 mask = 0;
+ struct amdgpu_ring *ring;
+
+ if (!adev)
+ return -ENODEV;
+
+ mask = (1 << adev->sdma.num_instances) - 1;
+ if ((val & mask) == 0)
+ return -EINVAL;
+
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ ring = &adev->sdma.instance[i].ring;
+ if (val & (1 << i))
+ ring->sched.ready = true;
+ else
+ ring->sched.ready = false;
+ }
+ /* publish sched.ready flag update effective immediately across smp */
+ smp_rmb();
+ return 0;
+}
+
+static int amdgpu_debugfs_sdma_sched_mask_get(void *data, u64 *val)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)data;
+ u32 i;
+ u64 mask = 0;
+ struct amdgpu_ring *ring;
+
+ if (!adev)
+ return -ENODEV;
+ for (i = 0; i < adev->sdma.num_instances; ++i) {
+ ring = &adev->sdma.instance[i].ring;
+ if (ring->sched.ready)
+ mask |= 1 << i;
+ }
+
+ *val = mask;
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_debugfs_sdma_sched_mask_fops,
+ amdgpu_debugfs_sdma_sched_mask_get,
+ amdgpu_debugfs_sdma_sched_mask_set, "%llx\n");
+
+#endif
+
+void amdgpu_debugfs_sdma_sched_mask_init(struct amdgpu_device *adev)
+{
+#if defined(CONFIG_DEBUG_FS)
+ struct drm_minor *minor = adev_to_drm(adev)->primary;
+ struct dentry *root = minor->debugfs_root;
+ char name[32];
+
+ if (!(adev->sdma.num_instances > 1))
+ return;
+ sprintf(name, "amdgpu_sdma_sched_mask");
+ debugfs_create_file(name, 0600, root, adev,
+ &amdgpu_debugfs_sdma_sched_mask_fops);
+#endif
+}
+
+static ssize_t amdgpu_get_sdma_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->sdma.supported_reset);
+}
+
+static DEVICE_ATTR(sdma_reset_mask, 0444,
+ amdgpu_get_sdma_reset_mask, NULL);
+
+int amdgpu_sdma_sysfs_reset_mask_init(struct amdgpu_device *adev)
+{
+ int r = 0;
+
+ if (!amdgpu_gpu_recovery)
+ return r;
+
+ if (adev->sdma.num_instances) {
+ r = device_create_file(adev->dev, &dev_attr_sdma_reset_mask);
+ if (r)
+ return r;
+ }
+
+ return r;
+}
+
+void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev)
+{
+ if (!amdgpu_gpu_recovery)
+ return;
+
+ if (adev->dev->kobj.sd) {
+ if (adev->sdma.num_instances)
+ device_remove_file(adev->dev, &dev_attr_sdma_reset_mask);
+ }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
index 087ce0f6fa07..2db58b5812a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
@@ -116,6 +116,7 @@ struct amdgpu_sdma {
struct ras_common_if *ras_if;
struct amdgpu_sdma_ras *ras;
uint32_t *ip_dump;
+ uint32_t supported_reset;
};
/*
@@ -175,5 +176,7 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev, u32 instance,
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
bool duplicate);
int amdgpu_sdma_ras_sw_init(struct amdgpu_device *adev);
-
+void amdgpu_debugfs_sdma_sched_mask_init(struct amdgpu_device *adev);
+int amdgpu_sdma_sysfs_reset_mask_init(struct amdgpu_device *adev);
+void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 0637414fc70e..9f922ec50ea2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1851,6 +1851,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
mutex_init(&adev->mman.gtt_window_lock);
+ dma_set_max_seg_size(adev->dev, UINT_MAX);
/* No others user of address space so set it to 0 */
r = ttm_device_init(&adev->mman.bdev, &amdgpu_bo_driver, adev->dev,
adev_to_drm(adev)->anon_inode->i_mapping,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 4e23419b92d4..4150ec0aa10d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -163,6 +163,7 @@ enum ta_fw_type {
TA_FW_TYPE_PSP_DTM,
TA_FW_TYPE_PSP_RAP,
TA_FW_TYPE_PSP_SECUREDISPLAY,
+ TA_FW_TYPE_PSP_XGMI_AUX,
TA_FW_TYPE_MAX_INDEX,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
index bb7b9b2eaac1..896f3609b0ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
@@ -318,6 +318,9 @@ int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
if (r)
return r;
+ if (amdgpu_sriov_vf(adev))
+ return r;
+
if (amdgpu_ras_is_supported(adev, ras_block->block)) {
r = amdgpu_irq_get(adev, &adev->gmc.ecc_irq, 0);
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 74fdbf71d95b..599d3ca4e0ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -214,15 +214,15 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
drm_sched_entity_destroy(&adev->vce.entity);
- amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
- (void **)&adev->vce.cpu_addr);
-
for (i = 0; i < adev->vce.num_rings; i++)
amdgpu_ring_fini(&adev->vce.ring[i]);
amdgpu_ucode_release(&adev->vce.fw);
mutex_destroy(&adev->vce.idle_mutex);
+ amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
+ (void **)&adev->vce.cpu_addr);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index aecb78e0519f..3e94c3ba1ba2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -1283,3 +1283,40 @@ int amdgpu_vcn_psp_update_sram(struct amdgpu_device *adev, int inst_idx,
return psp_execute_ip_fw_load(&adev->psp, &ucode);
}
+
+static ssize_t amdgpu_get_vcn_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->vcn.supported_reset);
+}
+
+static DEVICE_ATTR(vcn_reset_mask, 0444,
+ amdgpu_get_vcn_reset_mask, NULL);
+
+int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev)
+{
+ int r = 0;
+
+ if (adev->vcn.num_vcn_inst) {
+ r = device_create_file(adev->dev, &dev_attr_vcn_reset_mask);
+ if (r)
+ return r;
+ }
+
+ return r;
+}
+
+void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev)
+{
+ if (adev->dev->kobj.sd) {
+ if (adev->vcn.num_vcn_inst)
+ device_remove_file(adev->dev, &dev_attr_vcn_reset_mask);
+ }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 765b809d48a2..1e32311c1dff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -333,6 +333,8 @@ struct amdgpu_vcn {
/* IP reg dump */
uint32_t *ip_dump;
+
+ uint32_t supported_reset;
};
struct amdgpu_fw_shared_rb_ptrs_struct {
@@ -519,5 +521,7 @@ int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_vcn_psp_update_sram(struct amdgpu_device *adev, int inst_idx,
enum AMDGPU_UCODE_ID ucode_id);
int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev);
+int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev);
+void amdgpu_vcn_sysfs_reset_mask_fini(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 b6397d3229e1..c704e9803e11 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -523,6 +523,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
adev->unique_id =
((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->uuid;
+ adev->virt.ras_en_caps.all = ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->ras_en_caps.all;
+ adev->virt.ras_telemetry_en_caps.all =
+ ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->ras_telemetry_en_caps.all;
break;
default:
dev_err(adev->dev, "invalid pf2vf version: 0x%x\n", pf2vf_info->version);
@@ -703,6 +706,8 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev)
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));
+ adev->virt.fw_reserve.ras_telemetry =
+ (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB << 10));
} else if (adev->mman.drv_vram_usage_va) {
adev->virt.fw_reserve.p_pf2vf =
(struct amd_sriov_msg_pf2vf_info_header *)
@@ -710,6 +715,8 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev)
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));
+ adev->virt.fw_reserve.ras_telemetry =
+ (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB << 10));
}
amdgpu_virt_read_pf2vf_data(adev);
@@ -1144,3 +1151,185 @@ bool amdgpu_sriov_xnack_support(struct amdgpu_device *adev)
return xnack_mode;
}
+
+bool amdgpu_virt_get_ras_capability(struct amdgpu_device *adev)
+{
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+
+ if (!amdgpu_sriov_ras_caps_en(adev))
+ return false;
+
+ if (adev->virt.ras_en_caps.bits.block_umc)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__UMC);
+ if (adev->virt.ras_en_caps.bits.block_sdma)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__SDMA);
+ if (adev->virt.ras_en_caps.bits.block_gfx)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__GFX);
+ if (adev->virt.ras_en_caps.bits.block_mmhub)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__MMHUB);
+ if (adev->virt.ras_en_caps.bits.block_athub)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__ATHUB);
+ if (adev->virt.ras_en_caps.bits.block_pcie_bif)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__PCIE_BIF);
+ if (adev->virt.ras_en_caps.bits.block_hdp)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__HDP);
+ if (adev->virt.ras_en_caps.bits.block_xgmi_wafl)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__XGMI_WAFL);
+ if (adev->virt.ras_en_caps.bits.block_df)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__DF);
+ if (adev->virt.ras_en_caps.bits.block_smn)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__SMN);
+ if (adev->virt.ras_en_caps.bits.block_sem)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__SEM);
+ if (adev->virt.ras_en_caps.bits.block_mp0)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__MP0);
+ if (adev->virt.ras_en_caps.bits.block_mp1)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__MP1);
+ if (adev->virt.ras_en_caps.bits.block_fuse)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__FUSE);
+ if (adev->virt.ras_en_caps.bits.block_mca)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__MCA);
+ if (adev->virt.ras_en_caps.bits.block_vcn)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__VCN);
+ if (adev->virt.ras_en_caps.bits.block_jpeg)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__JPEG);
+ if (adev->virt.ras_en_caps.bits.block_ih)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__IH);
+ if (adev->virt.ras_en_caps.bits.block_mpio)
+ adev->ras_hw_enabled |= BIT(AMDGPU_RAS_BLOCK__MPIO);
+
+ if (adev->virt.ras_en_caps.bits.poison_propogation_mode)
+ con->poison_supported = true; /* Poison is handled by host */
+
+ return true;
+}
+
+static inline enum amd_sriov_ras_telemetry_gpu_block
+amdgpu_ras_block_to_sriov(struct amdgpu_device *adev, enum amdgpu_ras_block block) {
+ switch (block) {
+ case AMDGPU_RAS_BLOCK__UMC:
+ return RAS_TELEMETRY_GPU_BLOCK_UMC;
+ case AMDGPU_RAS_BLOCK__SDMA:
+ return RAS_TELEMETRY_GPU_BLOCK_SDMA;
+ case AMDGPU_RAS_BLOCK__GFX:
+ return RAS_TELEMETRY_GPU_BLOCK_GFX;
+ case AMDGPU_RAS_BLOCK__MMHUB:
+ return RAS_TELEMETRY_GPU_BLOCK_MMHUB;
+ case AMDGPU_RAS_BLOCK__ATHUB:
+ return RAS_TELEMETRY_GPU_BLOCK_ATHUB;
+ case AMDGPU_RAS_BLOCK__PCIE_BIF:
+ return RAS_TELEMETRY_GPU_BLOCK_PCIE_BIF;
+ case AMDGPU_RAS_BLOCK__HDP:
+ return RAS_TELEMETRY_GPU_BLOCK_HDP;
+ case AMDGPU_RAS_BLOCK__XGMI_WAFL:
+ return RAS_TELEMETRY_GPU_BLOCK_XGMI_WAFL;
+ case AMDGPU_RAS_BLOCK__DF:
+ return RAS_TELEMETRY_GPU_BLOCK_DF;
+ case AMDGPU_RAS_BLOCK__SMN:
+ return RAS_TELEMETRY_GPU_BLOCK_SMN;
+ case AMDGPU_RAS_BLOCK__SEM:
+ return RAS_TELEMETRY_GPU_BLOCK_SEM;
+ case AMDGPU_RAS_BLOCK__MP0:
+ return RAS_TELEMETRY_GPU_BLOCK_MP0;
+ case AMDGPU_RAS_BLOCK__MP1:
+ return RAS_TELEMETRY_GPU_BLOCK_MP1;
+ case AMDGPU_RAS_BLOCK__FUSE:
+ return RAS_TELEMETRY_GPU_BLOCK_FUSE;
+ case AMDGPU_RAS_BLOCK__MCA:
+ return RAS_TELEMETRY_GPU_BLOCK_MCA;
+ case AMDGPU_RAS_BLOCK__VCN:
+ return RAS_TELEMETRY_GPU_BLOCK_VCN;
+ case AMDGPU_RAS_BLOCK__JPEG:
+ return RAS_TELEMETRY_GPU_BLOCK_JPEG;
+ case AMDGPU_RAS_BLOCK__IH:
+ return RAS_TELEMETRY_GPU_BLOCK_IH;
+ case AMDGPU_RAS_BLOCK__MPIO:
+ return RAS_TELEMETRY_GPU_BLOCK_MPIO;
+ default:
+ dev_err(adev->dev, "Unsupported SRIOV RAS telemetry block 0x%x\n", block);
+ return RAS_TELEMETRY_GPU_BLOCK_COUNT;
+ }
+}
+
+static int amdgpu_virt_cache_host_error_counts(struct amdgpu_device *adev,
+ struct amdsriov_ras_telemetry *host_telemetry)
+{
+ struct amd_sriov_ras_telemetry_error_count *tmp = NULL;
+ uint32_t checksum, used_size;
+
+ checksum = host_telemetry->header.checksum;
+ used_size = host_telemetry->header.used_size;
+
+ if (used_size > (AMD_SRIOV_RAS_TELEMETRY_SIZE_KB << 10))
+ return 0;
+
+ tmp = kmalloc(used_size, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ memcpy(tmp, &host_telemetry->body.error_count, used_size);
+
+ if (checksum != amd_sriov_msg_checksum(tmp, used_size, 0, 0))
+ goto out;
+
+ memcpy(&adev->virt.count_cache, tmp,
+ min(used_size, sizeof(adev->virt.count_cache)));
+out:
+ kfree(tmp);
+
+ return 0;
+}
+
+static int amdgpu_virt_req_ras_err_count_internal(struct amdgpu_device *adev, bool force_update)
+{
+ struct amdgpu_virt *virt = &adev->virt;
+
+ /* Host allows 15 ras telemetry requests per 60 seconds. Afterwhich, the Host
+ * will ignore incoming guest messages. Ratelimit the guest messages to
+ * prevent guest self DOS.
+ */
+ if (__ratelimit(&adev->virt.ras_telemetry_rs) || force_update) {
+ if (!virt->ops->req_ras_err_count(adev))
+ amdgpu_virt_cache_host_error_counts(adev,
+ adev->virt.fw_reserve.ras_telemetry);
+ }
+
+ return 0;
+}
+
+/* Bypass ACA interface and query ECC counts directly from host */
+int amdgpu_virt_req_ras_err_count(struct amdgpu_device *adev, enum amdgpu_ras_block block,
+ struct ras_err_data *err_data)
+{
+ enum amd_sriov_ras_telemetry_gpu_block sriov_block;
+
+ sriov_block = amdgpu_ras_block_to_sriov(adev, block);
+
+ if (sriov_block >= RAS_TELEMETRY_GPU_BLOCK_COUNT ||
+ !amdgpu_sriov_ras_telemetry_block_en(adev, sriov_block))
+ return -EOPNOTSUPP;
+
+ /* Host Access may be lost during reset, just return last cached data. */
+ if (down_read_trylock(&adev->reset_domain->sem)) {
+ amdgpu_virt_req_ras_err_count_internal(adev, false);
+ up_read(&adev->reset_domain->sem);
+ }
+
+ err_data->ue_count = adev->virt.count_cache.block[sriov_block].ue_count;
+ err_data->ce_count = adev->virt.count_cache.block[sriov_block].ce_count;
+ err_data->de_count = adev->virt.count_cache.block[sriov_block].de_count;
+
+ return 0;
+}
+
+int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev)
+{
+ unsigned long ue_count, ce_count;
+
+ if (amdgpu_sriov_ras_telemetry_en(adev)) {
+ amdgpu_virt_req_ras_err_count_internal(adev, true);
+ amdgpu_ras_query_error_count(adev, &ce_count, &ue_count, NULL);
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
index b650a2032c42..5381b8d596e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
@@ -95,6 +95,7 @@ struct amdgpu_virt_ops {
void (*ras_poison_handler)(struct amdgpu_device *adev,
enum amdgpu_ras_block block);
bool (*rcvd_ras_intr)(struct amdgpu_device *adev);
+ int (*req_ras_err_count)(struct amdgpu_device *adev);
};
/*
@@ -103,6 +104,7 @@ struct amdgpu_virt_ops {
struct amdgpu_virt_fw_reserve {
struct amd_sriov_msg_pf2vf_info_header *p_pf2vf;
struct amd_sriov_msg_vf2pf_info_header *p_vf2pf;
+ void *ras_telemetry;
unsigned int checksum_key;
};
@@ -136,6 +138,8 @@ enum AMDGIM_FEATURE_FLAG {
AMDGIM_FEATURE_VCN_RB_DECOUPLE = (1 << 7),
/* MES info */
AMDGIM_FEATURE_MES_INFO_ENABLE = (1 << 8),
+ AMDGIM_FEATURE_RAS_CAPS = (1 << 9),
+ AMDGIM_FEATURE_RAS_TELEMETRY = (1 << 10),
};
enum AMDGIM_REG_ACCESS_FLAG {
@@ -276,6 +280,12 @@ struct amdgpu_virt {
uint32_t autoload_ucode_id;
struct mutex rlcg_reg_lock;
+
+ union amd_sriov_ras_caps ras_en_caps;
+ union amd_sriov_ras_caps ras_telemetry_en_caps;
+
+ struct ratelimit_state ras_telemetry_rs;
+ struct amd_sriov_ras_telemetry_error_count count_cache;
};
struct amdgpu_video_codec_info;
@@ -320,6 +330,15 @@ struct amdgpu_video_codec_info;
#define amdgpu_sriov_vf_mmio_access_protection(adev) \
((adev)->virt.caps & AMDGPU_VF_MMIO_ACCESS_PROTECT)
+#define amdgpu_sriov_ras_caps_en(adev) \
+((adev)->virt.gim_feature & AMDGIM_FEATURE_RAS_CAPS)
+
+#define amdgpu_sriov_ras_telemetry_en(adev) \
+(((adev)->virt.gim_feature & AMDGIM_FEATURE_RAS_TELEMETRY) && (adev)->virt.fw_reserve.ras_telemetry)
+
+#define amdgpu_sriov_ras_telemetry_block_en(adev, sriov_blk) \
+(amdgpu_sriov_ras_telemetry_en((adev)) && (adev)->virt.ras_telemetry_en_caps.all & BIT(sriov_blk))
+
static inline bool is_virtual_machine(void)
{
#if defined(CONFIG_X86)
@@ -383,4 +402,8 @@ bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev,
u32 acc_flags, u32 hwip,
bool write, u32 *rlcg_flag);
u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag, u32 xcc_id);
+bool amdgpu_virt_get_ras_capability(struct amdgpu_device *adev);
+int amdgpu_virt_req_ras_err_count(struct amdgpu_device *adev, enum amdgpu_ras_block block,
+ struct ras_err_data *err_data);
+int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 6b855810ee86..8d9bf7a0857f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -1161,7 +1161,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
int r;
amdgpu_sync_create(&sync);
- if (clear || !bo) {
+ if (clear) {
mem = NULL;
/* Implicitly sync to command submissions in the same VM before
@@ -1176,6 +1176,10 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
if (r)
goto error_free;
}
+ } else if (!bo) {
+ mem = NULL;
+
+ /* PRT map operations don't need to sync to anything. */
} else {
struct drm_gem_object *obj = &bo->tbo.base;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index c5b41e3ed14f..5d119ac26c4f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -42,7 +42,6 @@ struct amdgpu_bo_va;
struct amdgpu_job;
struct amdgpu_bo_list_entry;
struct amdgpu_bo_vm;
-struct amdgpu_mem_stats;
/*
* GPUVM handling
@@ -322,6 +321,16 @@ struct amdgpu_vm_fault_info {
unsigned int vmhub;
};
+struct amdgpu_mem_stats {
+ struct drm_memory_stats drm;
+
+ /* buffers that requested this placement */
+ uint64_t requested;
+ /* buffers that requested this placement
+ * but are currently evicted */
+ uint64_t evicted;
+};
+
struct amdgpu_vm {
/* tree of virtual addresses mapped */
struct rb_root_cached va;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
index 46713a158d90..110b120d7375 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
@@ -377,6 +377,13 @@ static int vpe_sw_init(struct amdgpu_ip_block *ip_block)
ret = vpe_init_microcode(vpe);
if (ret)
goto out;
+
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vpe.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vpe.ring);
+ ret = amdgpu_vpe_sysfs_reset_mask_init(adev);
+ if (ret)
+ goto out;
out:
return ret;
}
@@ -389,6 +396,7 @@ static int vpe_sw_fini(struct amdgpu_ip_block *ip_block)
release_firmware(vpe->fw);
vpe->fw = NULL;
+ amdgpu_vpe_sysfs_reset_mask_fini(adev);
vpe_ring_fini(vpe);
amdgpu_bo_free_kernel(&adev->vpe.cmdbuf_obj,
@@ -865,6 +873,43 @@ static void vpe_ring_end_use(struct amdgpu_ring *ring)
schedule_delayed_work(&adev->vpe.idle_work, VPE_IDLE_TIMEOUT);
}
+static ssize_t amdgpu_get_vpe_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->vpe.supported_reset);
+}
+
+static DEVICE_ATTR(vpe_reset_mask, 0444,
+ amdgpu_get_vpe_reset_mask, NULL);
+
+int amdgpu_vpe_sysfs_reset_mask_init(struct amdgpu_device *adev)
+{
+ int r = 0;
+
+ if (adev->vpe.num_instances) {
+ r = device_create_file(adev->dev, &dev_attr_vpe_reset_mask);
+ if (r)
+ return r;
+ }
+
+ return r;
+}
+
+void amdgpu_vpe_sysfs_reset_mask_fini(struct amdgpu_device *adev)
+{
+ if (adev->dev->kobj.sd) {
+ if (adev->vpe.num_instances)
+ device_remove_file(adev->dev, &dev_attr_vpe_reset_mask);
+ }
+}
+
static const struct amdgpu_ring_funcs vpe_ring_funcs = {
.type = AMDGPU_RING_TYPE_VPE,
.align_mask = 0xf,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h
index 231d86d0953e..695da740a97e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h
@@ -79,6 +79,7 @@ struct amdgpu_vpe {
uint32_t num_instances;
bool collaborate_mode;
+ uint32_t supported_reset;
};
int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev);
@@ -86,6 +87,8 @@ int amdgpu_vpe_init_microcode(struct amdgpu_vpe *vpe);
int amdgpu_vpe_ring_init(struct amdgpu_vpe *vpe);
int amdgpu_vpe_ring_fini(struct amdgpu_vpe *vpe);
int amdgpu_vpe_configure_dpm(struct amdgpu_vpe *vpe);
+void amdgpu_vpe_sysfs_reset_mask_fini(struct amdgpu_device *adev);
+int amdgpu_vpe_sysfs_reset_mask_init(struct amdgpu_device *adev);
#define vpe_ring_init(vpe) ((vpe)->funcs->ring_init ? (vpe)->funcs->ring_init((vpe)) : 0)
#define vpe_ring_start(vpe) ((vpe)->funcs->ring_start ? (vpe)->funcs->ring_start((vpe)) : 0)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index 83a16918ea76..e209b5e101df 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -471,6 +471,16 @@ static const char *xcp_desc[] = {
[AMDGPU_CPX_PARTITION_MODE] = "CPX",
};
+static const char *nps_desc[] = {
+ [UNKNOWN_MEMORY_PARTITION_MODE] = "UNKNOWN",
+ [AMDGPU_NPS1_PARTITION_MODE] = "NPS1",
+ [AMDGPU_NPS2_PARTITION_MODE] = "NPS2",
+ [AMDGPU_NPS3_PARTITION_MODE] = "NPS3",
+ [AMDGPU_NPS4_PARTITION_MODE] = "NPS4",
+ [AMDGPU_NPS6_PARTITION_MODE] = "NPS6",
+ [AMDGPU_NPS8_PARTITION_MODE] = "NPS8",
+};
+
ATTRIBUTE_GROUPS(xcp_cfg_res_sysfs);
#define to_xcp_attr(x) \
@@ -540,6 +550,26 @@ static ssize_t supported_xcp_configs_show(struct kobject *kobj,
return size;
}
+static ssize_t supported_nps_configs_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct amdgpu_xcp_cfg *xcp_cfg = to_xcp_cfg(kobj);
+ int size = 0, mode;
+ char *sep = "";
+
+ if (!xcp_cfg || !xcp_cfg->compatible_nps_modes)
+ return sysfs_emit(buf, "Not supported\n");
+
+ for_each_inst(mode, xcp_cfg->compatible_nps_modes) {
+ size += sysfs_emit_at(buf, size, "%s%s", sep, nps_desc[mode]);
+ sep = ", ";
+ }
+
+ size += sysfs_emit_at(buf, size, "\n");
+
+ return size;
+}
+
static ssize_t xcp_config_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -596,6 +626,9 @@ static const struct kobj_type xcp_cfg_sysfs_ktype = {
static struct kobj_attribute supp_part_sysfs_mode =
__ATTR_RO(supported_xcp_configs);
+static struct kobj_attribute supp_nps_sysfs_mode =
+ __ATTR_RO(supported_nps_configs);
+
static const struct attribute *xcp_attrs[] = {
&supp_part_sysfs_mode.attr,
&xcp_cfg_sysfs_mode.attr,
@@ -625,13 +658,24 @@ void amdgpu_xcp_cfg_sysfs_init(struct amdgpu_device *adev)
if (r)
goto err1;
+ if (adev->gmc.supported_nps_modes != 0) {
+ r = sysfs_create_file(&xcp_cfg->kobj, &supp_nps_sysfs_mode.attr);
+ if (r) {
+ sysfs_remove_files(&xcp_cfg->kobj, xcp_attrs);
+ goto err1;
+ }
+ }
+
mode = (xcp_cfg->xcp_mgr->mode ==
AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE) ?
AMDGPU_SPX_PARTITION_MODE :
xcp_cfg->xcp_mgr->mode;
r = amdgpu_xcp_get_res_info(xcp_cfg->xcp_mgr, mode, xcp_cfg);
- if (r)
+ if (r) {
+ sysfs_remove_file(&xcp_cfg->kobj, &supp_nps_sysfs_mode.attr);
+ sysfs_remove_files(&xcp_cfg->kobj, xcp_attrs);
goto err1;
+ }
xcp_cfg->mode = mode;
for (i = 0; i < xcp_cfg->num_res; i++) {
@@ -653,6 +697,7 @@ err:
kobject_put(&xcp_res->kobj);
}
+ sysfs_remove_file(&xcp_cfg->kobj, &supp_nps_sysfs_mode.attr);
sysfs_remove_files(&xcp_cfg->kobj, xcp_attrs);
err1:
kobject_put(&xcp_cfg->kobj);
@@ -673,6 +718,7 @@ void amdgpu_xcp_cfg_sysfs_fini(struct amdgpu_device *adev)
kobject_put(&xcp_res->kobj);
}
+ sysfs_remove_file(&xcp_cfg->kobj, &supp_nps_sysfs_mode.attr);
sysfs_remove_files(&xcp_cfg->kobj, xcp_attrs);
kobject_put(&xcp_cfg->kobj);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
index 7ac89d78a5bf..b63f53242c57 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
@@ -77,6 +77,7 @@ struct amdgpu_xcp_cfg {
u8 num_res;
struct amdgpu_xcp_mgr *xcp_mgr;
struct kobject kobj;
+ u16 compatible_nps_modes;
};
struct amdgpu_xcp_ip_funcs {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index b47422b0b5b1..74b4349e345a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -40,6 +40,11 @@
#define smnPCS_GOPX1_PCS_ERROR_STATUS 0x12200210
#define smnPCS_GOPX1_PCS_ERROR_NONCORRECTABLE_MASK 0x12200218
+#define XGMI_STATE_DISABLE 0xD1
+#define XGMI_STATE_LS0 0x81
+#define XGMI_LINK_ACTIVE 1
+#define XGMI_LINK_INACTIVE 0
+
static DEFINE_MUTEX(xgmi_mutex);
#define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4
@@ -289,6 +294,42 @@ static const struct amdgpu_pcs_ras_field xgmi3x16_pcs_ras_fields[] = {
SOC15_REG_FIELD(PCS_XGMI3X16_PCS_ERROR_STATUS, RxCMDPktErr)},
};
+static u32 xgmi_v6_4_get_link_status(struct amdgpu_device *adev, int global_link_num)
+{
+ const u32 smnpcs_xgmi3x16_pcs_state_hist1 = 0x11a00070;
+ const int xgmi_inst = 2;
+ u32 link_inst;
+ u64 addr;
+
+ link_inst = global_link_num % xgmi_inst;
+
+ addr = (smnpcs_xgmi3x16_pcs_state_hist1 | (link_inst << 20)) +
+ adev->asic_funcs->encode_ext_smn_addressing(global_link_num / xgmi_inst);
+
+ return RREG32_PCIE_EXT(addr);
+}
+
+int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev, int global_link_num)
+{
+ u32 xgmi_state_reg_val;
+
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
+ case IP_VERSION(6, 4, 0):
+ xgmi_state_reg_val = xgmi_v6_4_get_link_status(adev, global_link_num);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if ((xgmi_state_reg_val & 0xFF) == XGMI_STATE_DISABLE)
+ return -ENOLINK;
+
+ if ((xgmi_state_reg_val & 0xFF) == XGMI_STATE_LS0)
+ return XGMI_LINK_ACTIVE;
+
+ return XGMI_LINK_INACTIVE;
+}
+
/**
* DOC: AMDGPU XGMI Support
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
index 8cc7ab38db7c..d1282b4c6348 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
@@ -84,5 +84,7 @@ int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev);
int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev,
struct amdgpu_hive_info *hive,
int req_nps_mode);
+int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev,
+ int global_link_num);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
index 6e9eeaeb3de1..b4f9c2f4e92c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
@@ -28,17 +28,21 @@
#define AMD_SRIOV_MSG_VBIOS_SIZE_KB 64
#define AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB AMD_SRIOV_MSG_VBIOS_SIZE_KB
#define AMD_SRIOV_MSG_DATAEXCHANGE_SIZE_KB 4
-
+#define AMD_SRIOV_MSG_TMR_OFFSET_KB 2048
+#define AMD_SRIOV_MSG_BAD_PAGE_SIZE_KB 2
+#define AMD_SRIOV_RAS_TELEMETRY_SIZE_KB 64
/*
* layout
- * 0 64KB 65KB 66KB
- * | VBIOS | PF2VF | VF2PF | Bad Page | ...
- * | 64KB | 1KB | 1KB |
+ * 0 64KB 65KB 66KB 68KB 132KB
+ * | VBIOS | PF2VF | VF2PF | Bad Page | RAS Telemetry Region | ...
+ * | 64KB | 1KB | 1KB | 2KB | 64KB | ...
*/
+
#define AMD_SRIOV_MSG_SIZE_KB 1
#define AMD_SRIOV_MSG_PF2VF_OFFSET_KB AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB
#define AMD_SRIOV_MSG_VF2PF_OFFSET_KB (AMD_SRIOV_MSG_PF2VF_OFFSET_KB + AMD_SRIOV_MSG_SIZE_KB)
#define AMD_SRIOV_MSG_BAD_PAGE_OFFSET_KB (AMD_SRIOV_MSG_VF2PF_OFFSET_KB + AMD_SRIOV_MSG_SIZE_KB)
+#define AMD_SRIOV_MSG_RAS_TELEMETRY_OFFSET_KB (AMD_SRIOV_MSG_BAD_PAGE_OFFSET_KB + AMD_SRIOV_MSG_BAD_PAGE_SIZE_KB)
/*
* PF2VF history log:
@@ -86,30 +90,59 @@ enum amd_sriov_ucode_engine_id {
union amd_sriov_msg_feature_flags {
struct {
- uint32_t error_log_collect : 1;
- uint32_t host_load_ucodes : 1;
- uint32_t host_flr_vramlost : 1;
- uint32_t mm_bw_management : 1;
- uint32_t pp_one_vf_mode : 1;
- uint32_t reg_indirect_acc : 1;
- uint32_t av1_support : 1;
- uint32_t vcn_rb_decouple : 1;
- uint32_t mes_info_enable : 1;
- uint32_t reserved : 23;
+ uint32_t error_log_collect : 1;
+ uint32_t host_load_ucodes : 1;
+ uint32_t host_flr_vramlost : 1;
+ uint32_t mm_bw_management : 1;
+ uint32_t pp_one_vf_mode : 1;
+ uint32_t reg_indirect_acc : 1;
+ uint32_t av1_support : 1;
+ uint32_t vcn_rb_decouple : 1;
+ uint32_t mes_info_dump_enable : 1;
+ uint32_t ras_caps : 1;
+ uint32_t ras_telemetry : 1;
+ uint32_t reserved : 21;
} flags;
uint32_t all;
};
union amd_sriov_reg_access_flags {
struct {
- uint32_t vf_reg_access_ih : 1;
- uint32_t vf_reg_access_mmhub : 1;
- uint32_t vf_reg_access_gc : 1;
- uint32_t reserved : 29;
+ uint32_t vf_reg_access_ih : 1;
+ uint32_t vf_reg_access_mmhub : 1;
+ uint32_t vf_reg_access_gc : 1;
+ uint32_t reserved : 29;
} flags;
uint32_t all;
};
+union amd_sriov_ras_caps {
+ struct {
+ uint64_t block_umc : 1;
+ uint64_t block_sdma : 1;
+ uint64_t block_gfx : 1;
+ uint64_t block_mmhub : 1;
+ uint64_t block_athub : 1;
+ uint64_t block_pcie_bif : 1;
+ uint64_t block_hdp : 1;
+ uint64_t block_xgmi_wafl : 1;
+ uint64_t block_df : 1;
+ uint64_t block_smn : 1;
+ uint64_t block_sem : 1;
+ uint64_t block_mp0 : 1;
+ uint64_t block_mp1 : 1;
+ uint64_t block_fuse : 1;
+ uint64_t block_mca : 1;
+ uint64_t block_vcn : 1;
+ uint64_t block_jpeg : 1;
+ uint64_t block_ih : 1;
+ uint64_t block_mpio : 1;
+ uint64_t poison_propogation_mode : 1;
+ uint64_t reserved : 44;
+ } bits;
+ uint64_t all;
+};
+
union amd_sriov_msg_os_info {
struct {
uint32_t windows : 1;
@@ -158,7 +191,7 @@ struct amd_sriov_msg_pf2vf_info_header {
uint32_t reserved[2];
};
-#define AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE (49)
+#define AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE (55)
struct amd_sriov_msg_pf2vf_info {
/* header contains size and version */
struct amd_sriov_msg_pf2vf_info_header header;
@@ -211,6 +244,12 @@ struct amd_sriov_msg_pf2vf_info {
uint32_t pcie_atomic_ops_support_flags;
/* Portion of GPU memory occupied by VF. MAX value is 65535, but set to uint32_t to maintain alignment with reserved size */
uint32_t gpu_capacity;
+ /* vf bdf on host pci tree for debug only */
+ uint32_t bdf_on_host;
+ uint32_t more_bp; //Reserved for future use.
+ union amd_sriov_ras_caps ras_en_caps;
+ union amd_sriov_ras_caps ras_telemetry_en_caps;
+
/* reserved */
uint32_t reserved[256 - AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE];
} __packed;
@@ -283,8 +322,12 @@ enum amd_sriov_mailbox_request_message {
MB_REQ_MSG_REL_GPU_FINI_ACCESS,
MB_REQ_MSG_REQ_GPU_RESET_ACCESS,
MB_REQ_MSG_REQ_GPU_INIT_DATA,
+ MB_REQ_MSG_PSP_VF_CMD_RELAY,
MB_REQ_MSG_LOG_VF_ERROR = 200,
+ MB_REQ_MSG_READY_TO_RESET = 201,
+ MB_REQ_MSG_RAS_POISON = 202,
+ MB_REQ_RAS_ERROR_COUNT = 203,
};
/* mailbox message send from host to guest */
@@ -297,10 +340,60 @@ enum amd_sriov_mailbox_response_message {
MB_RES_MSG_FAIL,
MB_RES_MSG_QUERY_ALIVE,
MB_RES_MSG_GPU_INIT_DATA_READY,
+ MB_RES_MSG_RAS_ERROR_COUNT_READY = 11,
MB_RES_MSG_TEXT_MESSAGE = 255
};
+enum amd_sriov_ras_telemetry_gpu_block {
+ RAS_TELEMETRY_GPU_BLOCK_UMC = 0,
+ RAS_TELEMETRY_GPU_BLOCK_SDMA = 1,
+ RAS_TELEMETRY_GPU_BLOCK_GFX = 2,
+ RAS_TELEMETRY_GPU_BLOCK_MMHUB = 3,
+ RAS_TELEMETRY_GPU_BLOCK_ATHUB = 4,
+ RAS_TELEMETRY_GPU_BLOCK_PCIE_BIF = 5,
+ RAS_TELEMETRY_GPU_BLOCK_HDP = 6,
+ RAS_TELEMETRY_GPU_BLOCK_XGMI_WAFL = 7,
+ RAS_TELEMETRY_GPU_BLOCK_DF = 8,
+ RAS_TELEMETRY_GPU_BLOCK_SMN = 9,
+ RAS_TELEMETRY_GPU_BLOCK_SEM = 10,
+ RAS_TELEMETRY_GPU_BLOCK_MP0 = 11,
+ RAS_TELEMETRY_GPU_BLOCK_MP1 = 12,
+ RAS_TELEMETRY_GPU_BLOCK_FUSE = 13,
+ RAS_TELEMETRY_GPU_BLOCK_MCA = 14,
+ RAS_TELEMETRY_GPU_BLOCK_VCN = 15,
+ RAS_TELEMETRY_GPU_BLOCK_JPEG = 16,
+ RAS_TELEMETRY_GPU_BLOCK_IH = 17,
+ RAS_TELEMETRY_GPU_BLOCK_MPIO = 18,
+ RAS_TELEMETRY_GPU_BLOCK_COUNT = 19,
+};
+
+struct amd_sriov_ras_telemetry_header {
+ uint32_t checksum;
+ uint32_t used_size;
+ uint32_t reserved[2];
+};
+
+struct amd_sriov_ras_telemetry_error_count {
+ struct {
+ uint32_t ce_count;
+ uint32_t ue_count;
+ uint32_t de_count;
+ uint32_t ce_overflow_count;
+ uint32_t ue_overflow_count;
+ uint32_t de_overflow_count;
+ uint32_t reserved[6];
+ } block[RAS_TELEMETRY_GPU_BLOCK_COUNT];
+};
+
+struct amdsriov_ras_telemetry {
+ struct amd_sriov_ras_telemetry_header header;
+
+ union {
+ struct amd_sriov_ras_telemetry_error_count error_count;
+ } body;
+};
+
/* version data stored in MAILBOX_MSGBUF_RCV_DW1 for future expansion */
enum amd_sriov_gpu_init_data_version {
GPU_INIT_DATA_READY_V1 = 1,
diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
index 890976b7ce77..e157d6d857b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
+++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
@@ -455,6 +455,7 @@ static int aqua_vanjaram_get_xcp_res_info(struct amdgpu_xcp_mgr *xcp_mgr,
int max_res[AMDGPU_XCP_RES_MAX] = {};
bool res_lt_xcp;
int num_xcp, i;
+ u16 nps_modes;
if (!(xcp_mgr->supp_xcp_modes & BIT(mode)))
return -EINVAL;
@@ -467,23 +468,33 @@ static int aqua_vanjaram_get_xcp_res_info(struct amdgpu_xcp_mgr *xcp_mgr,
switch (mode) {
case AMDGPU_SPX_PARTITION_MODE:
num_xcp = 1;
+ nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE);
break;
case AMDGPU_DPX_PARTITION_MODE:
num_xcp = 2;
+ nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE);
break;
case AMDGPU_TPX_PARTITION_MODE:
num_xcp = 3;
+ nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) |
+ BIT(AMDGPU_NPS4_PARTITION_MODE);
break;
case AMDGPU_QPX_PARTITION_MODE:
num_xcp = 4;
+ nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) |
+ BIT(AMDGPU_NPS4_PARTITION_MODE);
break;
case AMDGPU_CPX_PARTITION_MODE:
num_xcp = NUM_XCC(adev->gfx.xcc_mask);
+ nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) |
+ BIT(AMDGPU_NPS4_PARTITION_MODE);
break;
default:
return -EINVAL;
}
+ xcp_cfg->compatible_nps_modes =
+ (adev->gmc.supported_nps_modes & nps_modes);
xcp_cfg->num_res = ARRAY_SIZE(max_res);
for (i = 0; i < xcp_cfg->num_res; i++) {
@@ -537,7 +548,7 @@ static bool __aqua_vanjaram_is_valid_mode(struct amdgpu_xcp_mgr *xcp_mgr,
case AMDGPU_SPX_PARTITION_MODE:
return adev->gmc.num_mem_partitions == 1 && num_xcc > 0;
case AMDGPU_DPX_PARTITION_MODE:
- return adev->gmc.num_mem_partitions != 8 && (num_xcc % 4) == 0;
+ return adev->gmc.num_mem_partitions <= 2 && (num_xcc % 4) == 0;
case AMDGPU_TPX_PARTITION_MODE:
return (adev->gmc.num_mem_partitions == 1 ||
adev->gmc.num_mem_partitions == 3) &&
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
index 483a441b46aa..621aeca53880 100644
--- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
+++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
@@ -254,8 +254,8 @@ static void df_v3_6_sw_init(struct amdgpu_device *adev)
static void df_v3_6_sw_fini(struct amdgpu_device *adev)
{
-
- device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
+ if (adev->dev->kobj.sd)
+ device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 9da95b25e158..24dce803a829 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -4825,6 +4825,11 @@ static int gfx_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
}
}
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->gfx.gfx_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
+ adev->gfx.compute_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
r = amdgpu_gfx_kiq_init(adev, GFX10_MEC_HPD_SIZE, 0);
if (r) {
@@ -4853,9 +4858,10 @@ static int gfx_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
gfx_v10_0_alloc_ip_dump(adev);
- r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
+ r = amdgpu_gfx_sysfs_init(adev);
if (r)
return r;
+
return 0;
}
@@ -4907,7 +4913,7 @@ static int gfx_v10_0_sw_fini(struct amdgpu_ip_block *ip_block)
gfx_v10_0_rlc_backdoor_autoload_buffer_fini(adev);
gfx_v10_0_free_microcode(adev);
- amdgpu_gfx_sysfs_isolation_shader_fini(adev);
+ amdgpu_gfx_sysfs_fini(adev);
kfree(adev->gfx.ip_dump_core);
kfree(adev->gfx.ip_dump_compute_queues);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 894fc04201c3..2ae058a224f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -46,6 +46,7 @@
#include "clearstate_gfx11.h"
#include "v11_structs.h"
#include "gfx_v11_0.h"
+#include "gfx_v11_0_cleaner_shader.h"
#include "gfx_v11_0_3.h"
#include "nbio_v4_3.h"
#include "mes_v11_0.h"
@@ -1579,8 +1580,26 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
}
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
+ case IP_VERSION(11, 0, 0):
+ case IP_VERSION(11, 0, 2):
+ case IP_VERSION(11, 0, 3):
+ adev->gfx.cleaner_shader_ptr = gfx_11_0_3_cleaner_shader_hex;
+ adev->gfx.cleaner_shader_size = sizeof(gfx_11_0_3_cleaner_shader_hex);
+ if (adev->gfx.me_fw_version >= 2280 &&
+ adev->gfx.pfp_fw_version >= 2370 &&
+ adev->gfx.mec_fw_version >= 2450 &&
+ adev->mes.fw_version[0] >= 99) {
+ adev->gfx.enable_cleaner_shader = true;
+ r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size);
+ if (r) {
+ adev->gfx.enable_cleaner_shader = false;
+ dev_err(adev->dev, "Failed to initialize cleaner shader\n");
+ }
+ }
+ break;
default:
adev->gfx.enable_cleaner_shader = false;
+ break;
}
/* Enable CG flag in one VF mode for enabling RLC safe mode enter/exit */
@@ -1674,6 +1693,24 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
}
}
+ adev->gfx.gfx_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
+ adev->gfx.compute_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
+ case IP_VERSION(11, 0, 0):
+ case IP_VERSION(11, 0, 2):
+ case IP_VERSION(11, 0, 3):
+ if ((adev->gfx.me_fw_version >= 2280) &&
+ (adev->gfx.mec_fw_version >= 2410)) {
+ adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ }
+ break;
+ default:
+ break;
+ }
+
if (!adev->enable_mes_kiq) {
r = amdgpu_gfx_kiq_init(adev, GFX11_MEC_HPD_SIZE, 0);
if (r) {
@@ -1708,7 +1745,7 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
gfx_v11_0_alloc_ip_dump(adev);
- r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
+ r = amdgpu_gfx_sysfs_init(adev);
if (r)
return r;
@@ -1773,7 +1810,7 @@ static int gfx_v11_0_sw_fini(struct amdgpu_ip_block *ip_block)
gfx_v11_0_free_microcode(adev);
- amdgpu_gfx_sysfs_isolation_shader_fini(adev);
+ amdgpu_gfx_sysfs_fini(adev);
kfree(adev->gfx.ip_dump_core);
kfree(adev->gfx.ip_dump_compute_queues);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3_cleaner_shader.asm b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3_cleaner_shader.asm
new file mode 100644
index 000000000000..9b90b66368c7
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_3_cleaner_shader.asm
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2024 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.
+ */
+
+// This shader is to clean LDS, SGPRs and VGPRs. It is first 64 Dwords or 256 bytes of 192 Dwords cleaner shader.
+//To turn this shader program on for complitaion change this to main and lower shader main to main_1
+
+// Navi3 : Clear SGPRs, VGPRs and LDS
+// Launch 32 waves per CU (16 per SIMD) as a workgroup (threadgroup) to fill every wave slot
+// Waves are "wave32" and have 64 VGPRs each, which uses all 1024 VGPRs per SIMD
+// Waves are launched in "CU" mode, and the workgroup shares 64KB of LDS (half of the WGP's LDS)
+// It takes 2 workgroups to use all of LDS: one on each CU of the WGP
+// Each wave clears SGPRs 0 - 107
+// Each wave clears VGPRs 0 - 63
+// The first wave of the workgroup clears its 64KB of LDS
+// The shader starts with "S_BARRIER" to ensure SPI has launched all waves of the workgroup
+// before any wave in the workgroup could end. Without this, it is possible not all SGPRs get cleared.
+
+shader main
+ asic(GFX11)
+ type(CS)
+ wave_size(32)
+// Note: original source code from SQ team
+
+// Takes about 2500 clocks to run.
+// (theorhetical fastest = 1024clks vgpr + 640lds = 1660 clks)
+//
+ S_BARRIER
+
+ //
+ // CLEAR VGPRs
+ //
+ s_mov_b32 m0, 0x00000058 // Loop 96/8=12 times (loop unrolled for performance)
+
+label_0005:
+ v_movreld_b32 v0, 0
+ v_movreld_b32 v1, 0
+ v_movreld_b32 v2, 0
+ v_movreld_b32 v3, 0
+ v_movreld_b32 v4, 0
+ v_movreld_b32 v5, 0
+ v_movreld_b32 v6, 0
+ v_movreld_b32 v7, 0
+ s_sub_u32 m0, m0, 8
+ s_cbranch_scc0 label_0005
+ //
+ //
+
+ s_mov_b32 s2, 0x80000000 // Bit31 is first_wave
+ s_and_b32 s2, s2, s0 // sgpr0 has tg_size (first_wave) term as in ucode only COMPUTE_PGM_RSRC2.tg_size_en is set
+ s_cbranch_scc0 label_0023 // Clean LDS if its first wave of ThreadGroup/WorkGroup
+ // CLEAR LDS
+ //
+ s_mov_b32 exec_lo, 0xffffffff
+ s_mov_b32 exec_hi, 0xffffffff
+ v_mbcnt_lo_u32_b32 v1, exec_hi, 0 // Set V1 to thread-ID (0..63)
+ v_mbcnt_hi_u32_b32 v1, exec_lo, v1 // Set V1 to thread-ID (0..63)
+ v_mul_u32_u24 v1, 0x00000008, v1 // * 8, so each thread is a double-dword address (8byte)
+ s_mov_b32 s2, 0x00000003f // 64 loop iterations
+ s_mov_b32 m0, 0xffffffff
+ // Clear all of LDS space
+ // Each FirstWave of WorkGroup clears 64kbyte block
+
+label_001F:
+ ds_write2_b64 v1, v[2:3], v[2:3] offset1:32
+ ds_write2_b64 v1, v[4:5], v[4:5] offset0:64 offset1:96
+ v_add_co_u32 v1, vcc, 0x00000400, v1
+ s_sub_u32 s2, s2, 1
+ s_cbranch_scc0 label_001F
+ //
+ // CLEAR SGPRs
+ //
+label_0023:
+ s_mov_b32 m0, 0x00000068 // Loop 108/4=27 times (loop unrolled for performance)
+label_sgpr_loop:
+ s_movreld_b32 s0, 0
+ s_movreld_b32 s1, 0
+ s_movreld_b32 s2, 0
+ s_movreld_b32 s3, 0
+ s_sub_u32 m0, m0, 4
+ s_cbranch_scc0 label_sgpr_loop
+
+ //clear vcc
+ s_mov_b64 vcc, 0 //clear vcc
+ s_mov_b32 flat_scratch_lo, 0 //clear flat scratch lo SGPR
+ s_mov_b32 flat_scratch_hi, 0 //clear flat scratch hi SGPR
+ s_mov_b64 ttmp0, 0 //Clear ttmp0 and ttmp1
+ s_mov_b64 ttmp2, 0 //Clear ttmp2 and ttmp3
+ s_mov_b64 ttmp4, 0 //Clear ttmp4 and ttmp5
+ s_mov_b64 ttmp6, 0 //Clear ttmp6 and ttmp7
+ s_mov_b64 ttmp8, 0 //Clear ttmp8 and ttmp9
+ s_mov_b64 ttmp10, 0 //Clear ttmp10 and ttmp11
+ s_mov_b64 ttmp12, 0 //Clear ttmp12 and ttmp13
+ s_mov_b64 ttmp14, 0 //Clear ttmp14 and ttmp15
+
+ s_endpgm
+
+end
+
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_cleaner_shader.h b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_cleaner_shader.h
new file mode 100644
index 000000000000..3218cc04f543
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0_cleaner_shader.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2024 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.
+ */
+
+/* Define the cleaner shader gfx_11_0_3 */
+static const u32 gfx_11_0_3_cleaner_shader_hex[] = {
+ 0xb0804006, 0xbe8200ff,
+ 0x00000058, 0xbefd0080,
+ 0x7e008480, 0x7e028480,
+ 0x7e048480, 0x7e068480,
+ 0x7e088480, 0x7e0a8480,
+ 0x7e0c8480, 0x7e0e8480,
+ 0xbefd0002, 0x80828802,
+ 0xbfa1fff5, 0xbe8200ff,
+ 0x80000000, 0x8b020002,
+ 0xbfa10012, 0xbefe00c1,
+ 0xbeff00c1, 0xd71f0001,
+ 0x0001007f, 0xd7200001,
+ 0x0002027e, 0x16020288,
+ 0xbe8200bf, 0xbefd00c1,
+ 0xd9382000, 0x00020201,
+ 0xd9386040, 0x00040401,
+ 0xd7006a01, 0x000202ff,
+ 0x00000400, 0x80828102,
+ 0xbfa1fff7, 0xbefd00ff,
+ 0x00000068, 0xbe804280,
+ 0xbe814280, 0xbe824280,
+ 0xbe834280, 0x80fd847d,
+ 0xbfa1fffa, 0xbeea0180,
+ 0xbeec0180, 0xbeee0180,
+ 0xbef00180, 0xbef20180,
+ 0xbef40180, 0xbef60180,
+ 0xbef80180, 0xbefa0180,
+ 0xbfb00000, 0xbf9f0000,
+ 0xbf9f0000, 0xbf9f0000,
+ 0xbf9f0000, 0xbf9f0000,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index 9fec28d8a5fc..fe7c48f2fb2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -1437,6 +1437,12 @@ static int gfx_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
}
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->gfx.gfx_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
+ adev->gfx.compute_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
+
if (!adev->enable_mes_kiq) {
r = amdgpu_gfx_kiq_init(adev, GFX12_MEC_HPD_SIZE, 0);
if (r) {
@@ -1466,7 +1472,7 @@ static int gfx_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
gfx_v12_0_alloc_ip_dump(adev);
- r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
+ r = amdgpu_gfx_sysfs_init(adev);
if (r)
return r;
@@ -1529,7 +1535,7 @@ static int gfx_v12_0_sw_fini(struct amdgpu_ip_block *ip_block)
gfx_v12_0_free_microcode(adev);
- amdgpu_gfx_sysfs_isolation_shader_fini(adev);
+ amdgpu_gfx_sysfs_fini(adev);
kfree(adev->gfx.ip_dump_core);
kfree(adev->gfx.ip_dump_compute_queues);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 480c41ee947e..b7006c41e270 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -4823,6 +4823,13 @@ static int gfx_v8_0_kcq_disable(struct amdgpu_device *adev)
amdgpu_ring_write(kiq_ring, 0);
amdgpu_ring_write(kiq_ring, 0);
}
+ /* Submit unmap queue packet */
+ amdgpu_ring_commit(kiq_ring);
+ /*
+ * Ring test will do a basic scratch register change check. Just run
+ * this to ensure that unmap queues that is submitted before got
+ * processed successfully before returning.
+ */
r = amdgpu_ring_test_helper(kiq_ring);
if (r)
DRM_ERROR("KCQ disable failed\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 66947850d7e4..0b6f09f2cc9b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -2374,6 +2374,12 @@ static int gfx_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
}
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->gfx.gfx_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
+ adev->gfx.compute_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
+
r = amdgpu_gfx_kiq_init(adev, GFX9_MEC_HPD_SIZE, 0);
if (r) {
DRM_ERROR("Failed to init KIQ BOs!\n");
@@ -2402,7 +2408,7 @@ static int gfx_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
gfx_v9_0_alloc_ip_dump(adev);
- r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
+ r = amdgpu_gfx_sysfs_init(adev);
if (r)
return r;
@@ -2443,7 +2449,7 @@ static int gfx_v9_0_sw_fini(struct amdgpu_ip_block *ip_block)
}
gfx_v9_0_free_microcode(adev);
- amdgpu_gfx_sysfs_isolation_shader_fini(adev);
+ amdgpu_gfx_sysfs_fini(adev);
kfree(adev->gfx.ip_dump_core);
kfree(adev->gfx.ip_dump_compute_queues);
@@ -3288,8 +3294,8 @@ static int gfx_v9_0_cp_gfx_start(struct amdgpu_device *adev)
* confirmed that the APU gfx10/gfx11 needn't such update.
*/
if (adev->flags & AMD_IS_APU &&
- adev->in_s3 && !adev->suspend_complete) {
- DRM_INFO(" Will skip the CSB packet resubmit\n");
+ adev->in_s3 && !pm_resume_via_firmware()) {
+ DRM_INFO("Will skip the CSB packet resubmit\n");
return 0;
}
r = amdgpu_ring_alloc(ring, gfx_v9_0_get_csb_size(adev) + 4 + 3);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index 016290f00592..e2b3dda57030 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -1157,6 +1157,19 @@ static int gfx_v9_4_3_sw_init(struct amdgpu_ip_block *ip_block)
return r;
}
+ adev->gfx.compute_supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
+ case IP_VERSION(9, 4, 3):
+ case IP_VERSION(9, 4, 4):
+ if (adev->gfx.mec_fw_version >= 155) {
+ adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_PIPE;
+ }
+ break;
+ default:
+ break;
+ }
r = gfx_v9_4_3_gpu_early_init(adev);
if (r)
return r;
@@ -1171,10 +1184,6 @@ static int gfx_v9_4_3_sw_init(struct amdgpu_ip_block *ip_block)
gfx_v9_4_3_alloc_ip_dump(adev);
- r = amdgpu_gfx_sysfs_isolation_shader_init(adev);
- if (r)
- return r;
-
return 0;
}
@@ -1199,7 +1208,6 @@ static int gfx_v9_4_3_sw_fini(struct amdgpu_ip_block *ip_block)
amdgpu_bo_unref(&adev->gfx.rlc.clear_state_obj);
gfx_v9_4_3_free_microcode(adev);
amdgpu_gfx_sysfs_fini(adev);
- amdgpu_gfx_sysfs_isolation_shader_fini(adev);
kfree(adev->gfx.ip_dump_core);
kfree(adev->gfx.ip_dump_compute_queues);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 07f45f1a503a..b6016f11956e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -87,9 +87,14 @@ static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev)
static void gmc_v7_0_mc_stop(struct amdgpu_device *adev)
{
+ struct amdgpu_ip_block *ip_block;
u32 blackout;
- gmc_v7_0_wait_for_idle((void *)adev);
+ ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GMC);
+ if (!ip_block)
+ return;
+
+ gmc_v7_0_wait_for_idle(ip_block);
blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
if (REG_GET_FIELD(blackout, MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE) != 1) {
@@ -251,9 +256,14 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev,
*/
static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
{
+ struct amdgpu_ip_block *ip_block;
u32 tmp;
int i, j;
+ ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GMC);
+ if (!ip_block)
+ return;
+
/* Initialize HDP */
for (i = 0, j = 0; i < 32; i++, j += 0x6) {
WREG32((0xb05 + j), 0x00000000);
@@ -264,7 +274,7 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
}
WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
if (adev->mode_info.num_crtc) {
@@ -288,7 +298,7 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
WREG32(mmMC_VM_AGP_BASE, 0);
WREG32(mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 22);
WREG32(mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 22);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK);
@@ -1183,7 +1193,7 @@ static int gmc_v7_0_soft_reset(struct amdgpu_ip_block *ip_block)
if (srbm_soft_reset) {
gmc_v7_0_mc_stop(adev);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for GMC idle timed out !\n");
tmp = RREG32(mmSRBM_SOFT_RESET);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index f43ded8a0aab..50c5da3020cb 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1130,8 +1130,10 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
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 | AMDGPU_GEM_CREATE_EXT_COHERENT);
+ bool is_vram = bo->tbo.resource &&
+ bo->tbo.resource->mem_type == TTM_PL_VRAM;
+ bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+ AMDGPU_GEM_CREATE_EXT_COHERENT);
bool ext_coherent = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENT;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
@@ -1139,6 +1141,8 @@ static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
bool snoop = false;
bool is_local;
+ dma_resv_assert_held(bo->tbo.base.resv);
+
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
@@ -1257,9 +1261,8 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
*flags &= ~AMDGPU_PTE_VALID;
}
- if (bo && bo->tbo.resource)
- gmc_v9_0_get_coherence_flags(adev, mapping->bo_va->base.bo,
- mapping, flags);
+ if ((*flags & AMDGPU_PTE_VALID) && bo)
+ gmc_v9_0_get_coherence_flags(adev, bo, mapping, flags);
}
static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
index 03b8b7cd5229..7319299f25ae 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
@@ -604,7 +604,7 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
+ bool set_clocks = !cancel_delayed_work_sync(&adev->jpeg.idle_work);
int cnt = 0;
mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index d6823fb45d32..6e29b69894a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -150,7 +150,7 @@ static int jpeg_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 5063a38801d6..9ac421486f05 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -211,7 +211,7 @@ static int jpeg_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index 10adbb7cbf53..e0df6800502c 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -164,7 +164,7 @@ static int jpeg_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 89953c0f5f1f..eca1963c33b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -123,6 +123,12 @@ static int jpeg_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
r = amdgpu_jpeg_ras_sw_init(adev);
if (r)
return r;
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->jpeg.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
+ r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
return 0;
}
@@ -143,6 +149,7 @@ static int jpeg_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_jpeg_sysfs_reset_mask_fini(adev);
r = amdgpu_jpeg_sw_fini(adev);
return r;
@@ -195,7 +202,7 @@ static int jpeg_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (!amdgpu_sriov_vf(adev)) {
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index 6917e4a8e96a..67b51bcbacd1 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -159,6 +159,13 @@ static int jpeg_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
}
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->jpeg.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
+ r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -178,6 +185,7 @@ static int jpeg_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_jpeg_sysfs_reset_mask_fini(adev);
r = amdgpu_jpeg_sw_fini(adev);
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
index f3cce523f3cb..1d9e3b101c3a 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
@@ -153,6 +153,13 @@ static int jpeg_v4_0_5_sw_init(struct amdgpu_ip_block *ip_block)
adev->jpeg.inst[i].external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, i, regUVD_JPEG_PITCH);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->jpeg.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
+ r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -172,6 +179,7 @@ static int jpeg_v4_0_5_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_jpeg_sysfs_reset_mask_fini(adev);
r = amdgpu_jpeg_sw_fini(adev);
return r;
@@ -219,7 +227,7 @@ static int jpeg_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
index 06840d1dae79..58fb1e5fa89c 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
@@ -100,6 +100,12 @@ static int jpeg_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;
adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->jpeg.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->jpeg.inst[0].ring_dec[0]);
+ r = amdgpu_jpeg_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
return 0;
}
@@ -119,6 +125,7 @@ static int jpeg_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_jpeg_sysfs_reset_mask_fini(adev);
r = amdgpu_jpeg_sw_fini(adev);
return r;
@@ -161,7 +168,7 @@ static int jpeg_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 0e758ebf2372..9c905b9e9376 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -644,6 +644,18 @@ static int mes_v11_0_misc_op(struct amdgpu_mes *mes,
sizeof(misc_pkt.set_shader_debugger.tcp_watch_cntl));
misc_pkt.set_shader_debugger.trap_en = input->set_shader_debugger.trap_en;
break;
+ case MES_MISC_OP_CHANGE_CONFIG:
+ if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) < 0x63) {
+ dev_err(mes->adev->dev, "MES FW versoin must be larger than 0x63 to support limit single process feature.\n");
+ return -EINVAL;
+ }
+ misc_pkt.opcode = MESAPI_MISC__CHANGE_CONFIG;
+ misc_pkt.change_config.opcode =
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_LIMIT_SINGLE_PROCESS;
+ misc_pkt.change_config.option.bits.limit_single_process =
+ input->change_config.option.limit_single_process;
+ break;
+
default:
DRM_ERROR("unsupported misc op (%d) \n", input->op);
return -EINVAL;
@@ -708,6 +720,9 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
mes->event_log_gpu_addr;
}
+ if (enforce_isolation)
+ mes_set_hw_res_pkt.limit_single_process = 1;
+
return mes_v11_0_submit_pkt_and_poll_completion(mes,
&mes_set_hw_res_pkt, sizeof(mes_set_hw_res_pkt),
offsetof(union MESAPI_SET_HW_RESOURCES, api_status));
@@ -908,6 +923,16 @@ static void mes_v11_0_enable(struct amdgpu_device *adev, bool enable)
uint32_t pipe, data = 0;
if (enable) {
+ if (amdgpu_mes_log_enable) {
+ WREG32_SOC15(GC, 0, regCP_MES_MSCRATCH_LO,
+ lower_32_bits(adev->mes.event_log_gpu_addr + AMDGPU_MES_LOG_BUFFER_SIZE));
+ WREG32_SOC15(GC, 0, regCP_MES_MSCRATCH_HI,
+ upper_32_bits(adev->mes.event_log_gpu_addr + AMDGPU_MES_LOG_BUFFER_SIZE));
+ dev_info(adev->dev, "Setup CP MES MSCRATCH address : 0x%x. 0x%x\n",
+ RREG32_SOC15(GC, 0, regCP_MES_MSCRATCH_HI),
+ RREG32_SOC15(GC, 0, regCP_MES_MSCRATCH_LO));
+ }
+
data = RREG32_SOC15(GC, 0, regCP_MES_CNTL);
data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1);
data = REG_SET_FIELD(data, CP_MES_CNTL,
@@ -1370,7 +1395,7 @@ static int mes_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->mes.kiq_hw_init = &mes_v11_0_kiq_hw_init;
adev->mes.kiq_hw_fini = &mes_v11_0_kiq_hw_fini;
- adev->mes.event_log_size = AMDGPU_MES_LOG_BUFFER_SIZE;
+ adev->mes.event_log_size = AMDGPU_MES_LOG_BUFFER_SIZE + AMDGPU_MES_MSCRATCH_SIZE;
r = amdgpu_mes_init(adev);
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
index 3daa8862e622..9ecc5d61e49b 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
@@ -531,6 +531,14 @@ static int mes_v12_0_misc_op(struct amdgpu_mes *mes,
sizeof(misc_pkt.set_shader_debugger.tcp_watch_cntl));
misc_pkt.set_shader_debugger.trap_en = input->set_shader_debugger.trap_en;
break;
+ case MES_MISC_OP_CHANGE_CONFIG:
+ misc_pkt.opcode = MESAPI_MISC__CHANGE_CONFIG;
+ misc_pkt.change_config.opcode =
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_LIMIT_SINGLE_PROCESS;
+ misc_pkt.change_config.option.bits.limit_single_process =
+ input->change_config.option.limit_single_process;
+ break;
+
default:
DRM_ERROR("unsupported misc op (%d) \n", input->op);
return -EINVAL;
@@ -550,7 +558,7 @@ static int mes_v12_0_set_hw_resources_1(struct amdgpu_mes *mes, int pipe)
mes_set_hw_res_1_pkt.header.type = MES_API_TYPE_SCHEDULER;
mes_set_hw_res_1_pkt.header.opcode = MES_SCH_API_SET_HW_RSRC_1;
mes_set_hw_res_1_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
- mes_set_hw_res_1_pkt.mes_kiq_unmap_timeout = 100;
+ mes_set_hw_res_1_pkt.mes_kiq_unmap_timeout = 0xa;
return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe,
&mes_set_hw_res_1_pkt, sizeof(mes_set_hw_res_1_pkt),
@@ -624,6 +632,9 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe)
mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = mes->event_log_gpu_addr + pipe * AMDGPU_MES_LOG_BUFFER_SIZE;
}
+ if (enforce_isolation)
+ mes_set_hw_res_pkt.limit_single_process = 1;
+
return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe,
&mes_set_hw_res_pkt, sizeof(mes_set_hw_res_pkt),
offsetof(union MESAPI_SET_HW_RESOURCES, api_status));
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
index f47bd7ada4d7..4dcb72d1bdda 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
@@ -61,15 +61,18 @@ static enum idh_event xgpu_nv_mailbox_peek_msg(struct amdgpu_device *adev)
static int xgpu_nv_mailbox_rcv_msg(struct amdgpu_device *adev,
enum idh_event event)
{
+ int r = 0;
u32 reg;
reg = RREG32_NO_KIQ(mmMAILBOX_MSGBUF_RCV_DW0);
- if (reg != event)
+ if (reg == IDH_FAIL)
+ r = -EINVAL;
+ else if (reg != event)
return -ENOENT;
xgpu_nv_mailbox_send_ack(adev);
- return 0;
+ return r;
}
static uint8_t xgpu_nv_peek_ack(struct amdgpu_device *adev)
@@ -178,6 +181,9 @@ send_request:
if (data1 != 0)
event = IDH_RAS_POISON_READY;
break;
+ case IDH_REQ_RAS_ERROR_COUNT:
+ event = IDH_RAS_ERROR_COUNT_READY;
+ break;
default:
break;
}
@@ -456,6 +462,11 @@ static bool xgpu_nv_rcvd_ras_intr(struct amdgpu_device *adev)
return (msg == IDH_RAS_ERROR_DETECTED || msg == 0xFFFFFFFF);
}
+static int xgpu_nv_req_ras_err_count(struct amdgpu_device *adev)
+{
+ return xgpu_nv_send_access_requests(adev, IDH_REQ_RAS_ERROR_COUNT);
+}
+
const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
.req_full_gpu = xgpu_nv_request_full_gpu_access,
.rel_full_gpu = xgpu_nv_release_full_gpu_access,
@@ -466,4 +477,5 @@ const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
.trans_msg = xgpu_nv_mailbox_trans_msg,
.ras_poison_handler = xgpu_nv_ras_poison_handler,
.rcvd_ras_intr = xgpu_nv_rcvd_ras_intr,
+ .req_ras_err_count = xgpu_nv_req_ras_err_count,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
index 1d099ffb3a5a..9d61d76e1bf9 100644
--- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
+++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
@@ -40,6 +40,7 @@ enum idh_request {
IDH_LOG_VF_ERROR = 200,
IDH_READY_TO_RESET = 201,
IDH_RAS_POISON = 202,
+ IDH_REQ_RAS_ERROR_COUNT = 203,
};
enum idh_event {
@@ -54,6 +55,8 @@ enum idh_event {
IDH_RAS_POISON_READY,
IDH_PF_SOFT_FLR_NOTIFICATION,
IDH_RAS_ERROR_DETECTED,
+ IDH_RAS_ERROR_COUNT_READY = 11,
+
IDH_TEXT_MESSAGE = 255,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
index 7a9adfda5814..814ab59fdd4a 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
@@ -275,6 +275,15 @@ static void nbio_v7_11_init_registers(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, data);
+ switch (adev->ip_versions[NBIO_HWIP][0]) {
+ case IP_VERSION(7, 11, 0):
+ case IP_VERSION(7, 11, 1):
+ case IP_VERSION(7, 11, 2):
+ case IP_VERSION(7, 11, 3):
+ data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4) & ~BIT(23);
+ WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4, data);
+ break;
+ }
}
static void nbio_v7_11_update_medium_grain_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
index fb37e354a9d5..1ac730328516 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
@@ -247,6 +247,12 @@ static void nbio_v7_7_init_registers(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regBIF0_PCIE_MST_CTRL_3, data);
+ switch (adev->ip_versions[NBIO_HWIP][0]) {
+ case IP_VERSION(7, 7, 0):
+ data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4) & ~BIT(23);
+ WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4, data);
+ break;
+ }
}
static void nbio_v7_7_update_medium_grain_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 6b72169be8f8..3bad565ded73 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -67,8 +67,8 @@ static const struct amd_ip_funcs nv_common_ip_funcs;
/* Navi */
static const struct amdgpu_video_codec_info nv_video_codecs_encode_array[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 4096, 0)},
};
static const struct amdgpu_video_codecs nv_video_codecs_encode = {
@@ -94,8 +94,8 @@ static const struct amdgpu_video_codecs nv_video_codecs_decode = {
/* Sienna Cichlid */
static const struct amdgpu_video_codec_info sc_video_codecs_encode_array[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2160, 0)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 7680, 4352, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
};
static const struct amdgpu_video_codecs sc_video_codecs_encode = {
@@ -136,8 +136,8 @@ static const struct amdgpu_video_codecs sc_video_codecs_decode_vcn1 = {
/* SRIOV Sienna Cichlid, not const since data is controlled by host */
static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2160, 0)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 7680, 4352, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
};
static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn0[] = {
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index 9c7cea0890c9..a38553f38fdc 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -1430,6 +1430,10 @@ static int sdma_v4_4_2_sw_init(struct amdgpu_ip_block *ip_block)
}
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->sdma.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->sdma.instance[0].ring);
+
if (amdgpu_sdma_ras_sw_init(adev)) {
dev_err(adev->dev, "fail to initialize sdma ras block\n");
return -EINVAL;
@@ -1442,6 +1446,10 @@ static int sdma_v4_4_2_sw_init(struct amdgpu_ip_block *ip_block)
else
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
+ r = amdgpu_sdma_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return r;
}
@@ -1456,6 +1464,7 @@ static int sdma_v4_4_2_sw_fini(struct amdgpu_ip_block *ip_block)
amdgpu_ring_fini(&adev->sdma.instance[i].page);
}
+ amdgpu_sdma_sysfs_reset_mask_fini(adev);
if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 4, 2) ||
amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(4, 4, 5))
amdgpu_sdma_destroy_inst_ctx(adev, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index d31c4860933f..fa9b40934957 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -1452,6 +1452,19 @@ static int sdma_v5_0_sw_init(struct amdgpu_ip_block *ip_block)
return r;
}
+ adev->sdma.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->sdma.instance[0].ring);
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
+ case IP_VERSION(5, 0, 0):
+ case IP_VERSION(5, 0, 2):
+ case IP_VERSION(5, 0, 5):
+ if (adev->sdma.instance[0].fw_version >= 35)
+ adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ break;
+ default:
+ break;
+ }
+
/* Allocate memory for SDMA IP Dump buffer */
ptr = kcalloc(adev->sdma.num_instances * reg_count, sizeof(uint32_t), GFP_KERNEL);
if (ptr)
@@ -1459,6 +1472,10 @@ static int sdma_v5_0_sw_init(struct amdgpu_ip_block *ip_block)
else
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
+ r = amdgpu_sdma_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return r;
}
@@ -1470,6 +1487,7 @@ static int sdma_v5_0_sw_fini(struct amdgpu_ip_block *ip_block)
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ring_fini(&adev->sdma.instance[i].ring);
+ amdgpu_sdma_sysfs_reset_mask_fini(adev);
amdgpu_sdma_destroy_inst_ctx(adev, false);
kfree(adev->sdma.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index ffa8c62ac101..ba5160399ab2 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -1357,6 +1357,24 @@ static int sdma_v5_2_sw_init(struct amdgpu_ip_block *ip_block)
return r;
}
+ adev->sdma.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->sdma.instance[0].ring);
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
+ case IP_VERSION(5, 2, 0):
+ case IP_VERSION(5, 2, 2):
+ case IP_VERSION(5, 2, 3):
+ case IP_VERSION(5, 2, 4):
+ if (adev->sdma.instance[0].fw_version >= 76)
+ adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ break;
+ case IP_VERSION(5, 2, 5):
+ if (adev->sdma.instance[0].fw_version >= 34)
+ adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ break;
+ default:
+ break;
+ }
+
/* Allocate memory for SDMA IP Dump buffer */
ptr = kcalloc(adev->sdma.num_instances * reg_count, sizeof(uint32_t), GFP_KERNEL);
if (ptr)
@@ -1364,6 +1382,10 @@ static int sdma_v5_2_sw_init(struct amdgpu_ip_block *ip_block)
else
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
+ r = amdgpu_sdma_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return r;
}
@@ -1375,6 +1397,7 @@ static int sdma_v5_2_sw_fini(struct amdgpu_ip_block *ip_block)
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ring_fini(&adev->sdma.instance[i].ring);
+ amdgpu_sdma_sysfs_reset_mask_fini(adev);
amdgpu_sdma_destroy_inst_ctx(adev, true);
kfree(adev->sdma.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 5635f2d84090..d46128b0ec92 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -1350,6 +1350,19 @@ static int sdma_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
return r;
}
+ adev->sdma.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->sdma.instance[0].ring);
+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) {
+ case IP_VERSION(6, 0, 0):
+ case IP_VERSION(6, 0, 2):
+ case IP_VERSION(6, 0, 3):
+ if (adev->sdma.instance[0].fw_version >= 21)
+ adev->sdma.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
+ break;
+ default:
+ break;
+ }
+
if (amdgpu_sdma_ras_sw_init(adev)) {
dev_err(adev->dev, "Failed to initialize sdma ras block!\n");
return -EINVAL;
@@ -1362,6 +1375,10 @@ static int sdma_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
else
DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n");
+ r = amdgpu_sdma_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return r;
}
@@ -1373,6 +1390,7 @@ static int sdma_v6_0_sw_fini(struct amdgpu_ip_block *ip_block)
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ring_fini(&adev->sdma.instance[i].ring);
+ amdgpu_sdma_sysfs_reset_mask_fini(adev);
amdgpu_sdma_destroy_inst_ctx(adev, true);
kfree(adev->sdma.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
index 9b01e074af47..2594467bdd87 100644
--- a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
+++ b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
@@ -220,6 +220,7 @@ sienna_cichlid_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
int r;
struct amdgpu_device *tmp_adev = (struct amdgpu_device *)reset_ctl->handle;
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = sienna_cichlid_mode2_restore_ip(tmp_adev);
@@ -237,6 +238,7 @@ sienna_cichlid_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
dev_err(tmp_adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
index e70ebad3f9fa..70569ea906bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
@@ -221,6 +221,7 @@ smu_v13_0_10_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
int r;
struct amdgpu_device *tmp_adev = (struct amdgpu_device *)reset_ctl->handle;
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = smu_v13_0_10_mode2_restore_ip(tmp_adev);
@@ -234,6 +235,7 @@ smu_v13_0_10_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
dev_err(tmp_adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index 93e44e7ee3fa..ede072758dab 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -90,8 +90,8 @@ static const struct amd_ip_funcs soc15_common_ip_funcs;
/* Vega, Raven, Arcturus */
static const struct amdgpu_video_codec_info vega_video_codecs_encode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 4096, 0)},
};
static const struct amdgpu_video_codecs vega_video_codecs_encode =
@@ -578,22 +578,16 @@ soc15_asic_reset_method(struct amdgpu_device *adev)
static bool soc15_need_reset_on_resume(struct amdgpu_device *adev)
{
- u32 sol_reg;
-
- sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
-
/* Will reset for the following suspend abort cases.
- * 1) Only reset limit on APU side, dGPU hasn't checked yet.
- * 2) S3 suspend abort and TOS already launched.
+ * 1) Only reset on APU side, dGPU hasn't checked yet.
+ * 2) S3 suspend aborted in the normal S3 suspend or
+ * performing pm core test.
*/
if (adev->flags & AMD_IS_APU && adev->in_s3 &&
- sol_reg) {
- adev->suspend_complete = false;
+ !pm_resume_via_firmware())
return true;
- } else {
- adev->suspend_complete = true;
+ else
return false;
- }
}
static int soc15_asic_reset(struct amdgpu_device *adev)
@@ -603,11 +597,17 @@ static int soc15_asic_reset(struct amdgpu_device *adev)
* successfully. So now, temporarily enable it for the
* S3 suspend abort case.
*/
- if (((adev->apu_flags & AMD_APU_IS_RAVEN) ||
- (adev->apu_flags & AMD_APU_IS_RAVEN2)) &&
- !soc15_need_reset_on_resume(adev))
+
+ if ((adev->apu_flags & AMD_APU_IS_PICASSO ||
+ !(adev->apu_flags & AMD_APU_IS_RAVEN)) &&
+ soc15_need_reset_on_resume(adev))
+ goto asic_reset;
+
+ if ((adev->apu_flags & AMD_APU_IS_RAVEN) ||
+ (adev->apu_flags & AMD_APU_IS_RAVEN2))
return 0;
+asic_reset:
switch (soc15_asic_reset_method(adev)) {
case AMD_RESET_METHOD_PCI:
dev_info(adev->dev, "PCI reset\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
index 1c07ebdc0d1f..d6999835918f 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
@@ -49,13 +49,13 @@ static const struct amd_ip_funcs soc21_common_ip_funcs;
/* SOC21 */
static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_vcn0[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
};
static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_vcn1[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
};
@@ -96,14 +96,14 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_decode_vcn1 = {
/* SRIOV SOC21, not const since data is controlled by host */
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn0[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
};
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn1[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn0 = {
@@ -897,9 +897,10 @@ static bool soc21_need_reset_on_resume(struct amdgpu_device *adev)
/* Will reset for the following suspend abort cases.
* 1) Only reset dGPU side.
* 2) S3 suspend got aborted and TOS is active.
+ * As for dGPU suspend abort cases the SOL value
+ * will be kept as zero at this resume point.
*/
- if (!(adev->flags & AMD_IS_APU) && adev->in_s3 &&
- !adev->suspend_complete) {
+ if (!(adev->flags & AMD_IS_APU) && adev->in_s3) {
sol_reg1 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
msleep(100);
sol_reg2 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
diff --git a/drivers/gpu/drm/amd/amdgpu/soc24.c b/drivers/gpu/drm/amd/amdgpu/soc24.c
index 3af10ef4b793..be96de92b2f5 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc24.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc24.c
@@ -48,7 +48,7 @@
static const struct amd_ip_funcs soc24_common_ip_funcs;
static const struct amdgpu_video_codec_info vcn_5_0_0_video_codecs_encode_array_vcn0[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
};
diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h
index 3ac56a9645eb..21b71a427b1f 100644
--- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h
+++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h
@@ -113,6 +113,14 @@ enum ta_ras_address_type {
TA_RAS_PA_TO_MCA,
};
+enum ta_ras_nps_mode {
+ TA_RAS_UNKNOWN_MODE = 0,
+ TA_RAS_NPS1_MODE = 1,
+ TA_RAS_NPS2_MODE = 2,
+ TA_RAS_NPS4_MODE = 4,
+ TA_RAS_NPS8_MODE = 8,
+};
+
/* Input/output structures for RAS commands */
/**********************************************************/
@@ -139,6 +147,7 @@ struct ta_ras_init_flags {
uint8_t dgpu_mode;
uint16_t xcc_mask;
uint8_t channel_dis_num;
+ uint8_t nps_mode;
};
struct ta_ras_mca_addr {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 5512259cac79..fcc8511e91ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -225,6 +225,10 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
vcn_v4_0_fw_shared_init(adev, i);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@@ -247,6 +251,10 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -284,6 +292,7 @@ static int vcn_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 0d5c94bfc0ef..3f69b9b2bcd0 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -95,6 +95,13 @@ static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring);
static void vcn_v4_0_3_set_ras_funcs(struct amdgpu_device *adev);
static void vcn_v4_0_3_enable_ras(struct amdgpu_device *adev,
int inst_idx, bool indirect);
+
+static inline bool vcn_v4_0_3_normalizn_reqd(struct amdgpu_device *adev)
+{
+ return (amdgpu_sriov_vf(adev) ||
+ (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)));
+}
+
/**
* vcn_v4_0_3_early_init - set function pointers
*
@@ -116,6 +123,20 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
return amdgpu_vcn_early_init(adev);
}
+static int vcn_v4_0_3_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
+{
+ struct amdgpu_vcn4_fw_shared *fw_shared;
+
+ fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
+ fw_shared->sq.is_enabled = 1;
+
+ if (amdgpu_vcnfw_log)
+ amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]);
+
+ return 0;
+}
+
/**
* vcn_v4_0_3_sw_init - sw init for VCN block
*
@@ -148,8 +169,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
return r;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- volatile struct amdgpu_vcn4_fw_shared *fw_shared;
-
vcn_inst = GET_INST(VCN, i);
ring = &adev->vcn.inst[i].ring_enc[0];
@@ -172,14 +191,13 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
- fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
- fw_shared->sq.is_enabled = true;
-
- if (amdgpu_vcnfw_log)
- amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+ vcn_v4_0_3_fw_shared_init(adev, i);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@@ -206,6 +224,10 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -239,6 +261,7 @@ static int vcn_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
@@ -273,6 +296,8 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
}
} else {
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ struct amdgpu_vcn4_fw_shared *fw_shared;
+
vcn_inst = GET_INST(VCN, i);
ring = &adev->vcn.inst[i].ring_enc[0];
@@ -296,6 +321,11 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
regVCN_RB1_DB_CTRL);
}
+ /* Re-init fw_shared when RAS fatal error occurred */
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ if (!fw_shared->sq.is_enabled)
+ vcn_v4_0_3_fw_shared_init(adev, i);
+
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
@@ -1428,8 +1458,8 @@ static uint64_t vcn_v4_0_3_unified_ring_get_wptr(struct amdgpu_ring *ring)
static void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
uint32_t val, uint32_t mask)
{
- /* For VF, only local offsets should be used */
- if (amdgpu_sriov_vf(ring->adev))
+ /* Use normalized offsets when required */
+ if (vcn_v4_0_3_normalizn_reqd(ring->adev))
reg = NORMALIZE_VCN_REG_OFFSET(reg);
amdgpu_ring_write(ring, VCN_ENC_CMD_REG_WAIT);
@@ -1440,8 +1470,8 @@ static void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t
static void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val)
{
- /* For VF, only local offsets should be used */
- if (amdgpu_sriov_vf(ring->adev))
+ /* Use normalized offsets when required */
+ if (vcn_v4_0_3_normalizn_reqd(ring->adev))
reg = NORMALIZE_VCN_REG_OFFSET(reg);
amdgpu_ring_write(ring, VCN_ENC_CMD_REG_WRITE);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index fe2cc1a80c13..bd3d2bbdc16b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -170,6 +170,10 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
@@ -181,6 +185,11 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
} else {
adev->vcn.ip_dump = ptr;
}
+
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -215,6 +224,7 @@ static int vcn_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index b3fa54c0514e..a83505815d39 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -136,15 +136,15 @@ static const struct amdgpu_video_codec_info polaris_video_codecs_encode_array[]
{
.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC,
.max_width = 4096,
- .max_height = 2304,
- .max_pixels_per_frame = 4096 * 2304,
+ .max_height = 4096,
+ .max_pixels_per_frame = 4096 * 4096,
.max_level = 0,
},
{
.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC,
.max_width = 4096,
- .max_height = 2304,
- .max_pixels_per_frame = 4096 * 2304,
+ .max_height = 4096,
+ .max_pixels_per_frame = 4096 * 4096,
.max_level = 0,
},
};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index fad1c8f2bc83..956198da7859 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -534,7 +534,8 @@ static void kfd_cwsr_init(struct kfd_dev *kfd)
kfd->cwsr_isa = cwsr_trap_gfx11_hex;
kfd->cwsr_isa_size = sizeof(cwsr_trap_gfx11_hex);
} else {
- BUILD_BUG_ON(sizeof(cwsr_trap_gfx12_hex) > PAGE_SIZE);
+ BUILD_BUG_ON(sizeof(cwsr_trap_gfx12_hex)
+ > KFD_CWSR_TMA_OFFSET);
kfd->cwsr_isa = cwsr_trap_gfx12_hex;
kfd->cwsr_isa_size = sizeof(cwsr_trap_gfx12_hex);
}
@@ -1392,6 +1393,13 @@ void kfd_dec_compute_active(struct kfd_node *node)
WARN_ONCE(count < 0, "Compute profile ref. count error");
}
+static bool kfd_compute_active(struct kfd_node *node)
+{
+ if (atomic_read(&node->kfd->compute_profile))
+ return true;
+ return false;
+}
+
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask)
{
/*
@@ -1485,6 +1493,24 @@ int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
return node->dqm->ops.halt(node->dqm);
}
+bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id)
+{
+ struct kfd_node *node;
+
+ if (!kfd->init_complete)
+ return false;
+
+ if (node_id >= kfd->num_nodes) {
+ dev_warn(kfd->adev->dev, "Invalid node ID: %u exceeds %u\n",
+ node_id, kfd->num_nodes - 1);
+ return false;
+ }
+
+ node = kfd->nodes[node_id];
+
+ return kfd_compute_active(node);
+}
+
#if defined(CONFIG_DEBUG_FS)
/* This function will send a package to HIQ to hang the HWS
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 38c19dc8311d..c79fe9069e22 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -202,6 +202,8 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
int r, queue_type;
uint64_t wptr_addr_off;
+ if (!dqm->sched_running || dqm->sched_halt)
+ return 0;
if (!down_read_trylock(&adev->reset_domain->sem))
return -EIO;
@@ -270,6 +272,8 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
int r;
struct mes_remove_queue_input queue_input;
+ if (!dqm->sched_running || dqm->sched_halt)
+ return 0;
if (!down_read_trylock(&adev->reset_domain->sem))
return -EIO;
@@ -292,7 +296,7 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
return r;
}
-static int remove_all_queues_mes(struct device_queue_manager *dqm)
+static int remove_all_kfd_queues_mes(struct device_queue_manager *dqm)
{
struct device_process_node *cur;
struct device *dev = dqm->dev->adev->dev;
@@ -319,6 +323,33 @@ static int remove_all_queues_mes(struct device_queue_manager *dqm)
return retval;
}
+static int add_all_kfd_queues_mes(struct device_queue_manager *dqm)
+{
+ struct device_process_node *cur;
+ struct device *dev = dqm->dev->adev->dev;
+ struct qcm_process_device *qpd;
+ struct queue *q;
+ int retval = 0;
+
+ list_for_each_entry(cur, &dqm->queues, list) {
+ qpd = cur->qpd;
+ list_for_each_entry(q, &qpd->queues_list, list) {
+ if (!q->properties.is_active)
+ continue;
+ retval = add_queue_mes(dqm, q, qpd);
+ if (retval) {
+ dev_err(dev, "%s: Failed to add queue %d for dev %d",
+ __func__,
+ q->properties.queue_id,
+ dqm->dev->id);
+ return retval;
+ }
+ }
+ }
+
+ return retval;
+}
+
static int suspend_all_queues_mes(struct device_queue_manager *dqm)
{
struct amdgpu_device *adev = (struct amdgpu_device *)dqm->dev->adev;
@@ -1742,7 +1773,7 @@ static int halt_cpsch(struct device_queue_manager *dqm)
KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0,
USE_DEFAULT_GRACE_PERIOD, false);
else
- ret = remove_all_queues_mes(dqm);
+ ret = remove_all_kfd_queues_mes(dqm);
}
dqm->sched_halt = true;
dqm_unlock(dqm);
@@ -1768,6 +1799,9 @@ static int unhalt_cpsch(struct device_queue_manager *dqm)
ret = execute_queues_cpsch(dqm,
KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES,
0, USE_DEFAULT_GRACE_PERIOD);
+ else
+ ret = add_all_kfd_queues_mes(dqm);
+
dqm_unlock(dqm);
return ret;
@@ -1867,7 +1901,7 @@ static int stop_cpsch(struct device_queue_manager *dqm)
if (!dqm->dev->kfd->shared_resources.enable_mes)
unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD, false);
else
- remove_all_queues_mes(dqm);
+ remove_all_kfd_queues_mes(dqm);
dqm->sched_running = false;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
index 4843dcb9a5f7..2b0a830f5b29 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
@@ -125,7 +125,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
memset(kq->pq_kernel_addr, 0, queue_size);
memset(kq->rptr_kernel, 0, sizeof(*kq->rptr_kernel));
- memset(kq->wptr_kernel, 0, sizeof(*kq->wptr_kernel));
+ memset(kq->wptr_kernel, 0, dev->kfd->device_info.doorbell_size);
prop.queue_size = queue_size;
prop.is_interop = false;
@@ -306,12 +306,17 @@ int kq_submit_packet(struct kernel_queue *kq)
if (amdgpu_amdkfd_is_fed(kq->dev->adev))
return -EIO;
+ /* Make sure ring buffer is updated before wptr updated */
+ mb();
+
if (kq->dev->kfd->device_info.doorbell_size == 8) {
*kq->wptr64_kernel = kq->pending_wptr64;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
kq->pending_wptr64);
} else {
*kq->wptr_kernel = kq->pending_wptr;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
kq->pending_wptr);
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index d4aa843aacfd..87cd52cf4ee9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -271,11 +271,9 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer)
struct kfd_process *proc = NULL;
struct kfd_process_device *pdd = NULL;
int i;
- struct kfd_cu_occupancy cu_occupancy[AMDGPU_MAX_QUEUES];
+ struct kfd_cu_occupancy *cu_occupancy;
u32 queue_format;
- memset(cu_occupancy, 0x0, sizeof(cu_occupancy));
-
pdd = container_of(attr, struct kfd_process_device, attr_cu_occupancy);
dev = pdd->dev;
if (dev->kfd2kgd->get_cu_occupancy == NULL)
@@ -293,6 +291,10 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer)
wave_cnt = 0;
max_waves_per_cu = 0;
+ cu_occupancy = kcalloc(AMDGPU_MAX_QUEUES, sizeof(*cu_occupancy), GFP_KERNEL);
+ if (!cu_occupancy)
+ return -ENOMEM;
+
/*
* For GFX 9.4.3, fetch the CU occupancy from the first XCC in the partition.
* For AQL queues, because of cooperative dispatch we multiply the wave count
@@ -318,6 +320,7 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer)
/* Translate wave count to number of compute units */
cu_cnt = (wave_cnt + (max_waves_per_cu - 1)) / max_waves_per_cu;
+ kfree(cu_occupancy);
return snprintf(buffer, PAGE_SIZE, "%d\n", cu_cnt);
}
@@ -338,8 +341,8 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr,
attr_sdma);
struct kfd_sdma_activity_handler_workarea sdma_activity_work_handler;
- INIT_WORK(&sdma_activity_work_handler.sdma_activity_work,
- kfd_sdma_activity_worker);
+ INIT_WORK_ONSTACK(&sdma_activity_work_handler.sdma_activity_work,
+ kfd_sdma_activity_worker);
sdma_activity_work_handler.pdd = pdd;
sdma_activity_work_handler.sdma_activity_counter = 0;
@@ -347,6 +350,7 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr,
schedule_work(&sdma_activity_work_handler.sdma_activity_work);
flush_work(&sdma_activity_work_handler.sdma_activity_work);
+ destroy_work_on_stack(&sdma_activity_work_handler.sdma_activity_work);
return snprintf(buffer, PAGE_SIZE, "%llu\n",
(sdma_activity_work_handler.sdma_activity_counter)/
@@ -850,8 +854,10 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
goto out;
}
- /* A prior open of /dev/kfd could have already created the process. */
- process = find_process(thread, false);
+ /* A prior open of /dev/kfd could have already created the process.
+ * find_process will increase process kref in this case
+ */
+ process = find_process(thread, true);
if (process) {
pr_debug("Process already found\n");
} else {
@@ -899,8 +905,6 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
init_waitqueue_head(&process->wait_irq_drain);
}
out:
- if (!IS_ERR(process))
- kref_get(&process->ref);
mutex_unlock(&kfd_processes_mutex);
mmput(thread->mm);
@@ -1186,10 +1190,8 @@ static void kfd_process_ref_release(struct kref *ref)
static struct mmu_notifier *kfd_process_alloc_notifier(struct mm_struct *mm)
{
- int idx = srcu_read_lock(&kfd_processes_srcu);
- struct kfd_process *p = find_process_by_mm(mm);
-
- srcu_read_unlock(&kfd_processes_srcu, idx);
+ /* This increments p->ref counter if kfd process p exists */
+ struct kfd_process *p = kfd_lookup_process_by_mm(mm);
return p ? &p->mmu_notifier : ERR_PTR(-ESRCH);
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 3871591c9aec..9476e30d6baa 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1998,6 +1998,8 @@ static void kfd_topology_set_capabilities(struct kfd_topology_device *dev)
if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(9, 4, 2))
dev->node_props.capability |=
HSA_CAP_TRAP_DEBUG_PRECISE_MEMORY_OPERATIONS_SUPPORTED;
+
+ dev->node_props.capability |= HSA_CAP_PER_QUEUE_RESET_SUPPORTED;
} else {
dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 |
HSA_DBG_WATCH_ADDR_MASK_HI_BIT;
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index df17e79c45c7..11e3f2f3b174 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -7,20 +7,21 @@ menu "Display Engine Configuration"
config DRM_AMD_DC
bool "AMD DC - Enable new display engine"
default y
- depends on BROKEN || !CC_IS_CLANG || ARM64 || RISCV || SPARC64 || X86_64
+ depends on BROKEN || !CC_IS_CLANG || ARM64 || LOONGARCH || RISCV || SPARC64 || X86_64
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
- select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || RISCV))
+ select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || LOONGARCH || RISCV))
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
Raven ASICs.
- calculate_bandwidth() is presently broken on all !(X86_64 || SPARC64 || ARM64)
- architectures built with Clang (all released versions), whereby the stack
- frame gets blown up to well over 5k. This would cause an immediate kernel
- panic on most architectures. We'll revert this when the following bug report
- has been resolved: https://github.com/llvm/llvm-project/issues/41896.
+ calculate_bandwidth() is presently broken on all !(X86_64 || SPARC64 ||
+ ARM64 || LOONGARCH || RISCV) architectures built with Clang (all released
+ versions), whereby the stack frame gets blown up to well over 5k. This
+ would cause an immediate kernel panic on most architectures. We'll revert
+ this when the following bug report has been resolved:
+ https://github.com/llvm/llvm-project/issues/41896.
config DRM_AMD_DC_FP
def_bool n
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 75d6b90104f8..f0a6816709ca 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1307,6 +1307,29 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
DRM_INFO("DMUB hardware initialized: version=0x%08X\n",
adev->dm.dmcub_fw_version);
+ /* Keeping sanity checks off if
+ * DCN31 >= 4.0.59.0
+ * DCN314 >= 8.0.16.0
+ * Otherwise, turn on sanity checks
+ */
+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
+ case IP_VERSION(3, 1, 2):
+ case IP_VERSION(3, 1, 3):
+ if (adev->dm.dmcub_fw_version &&
+ adev->dm.dmcub_fw_version >= DMUB_FW_VERSION(4, 0, 0) &&
+ adev->dm.dmcub_fw_version < DMUB_FW_VERSION(4, 0, 59))
+ adev->dm.dc->debug.sanity_checks = true;
+ break;
+ case IP_VERSION(3, 1, 4):
+ if (adev->dm.dmcub_fw_version &&
+ adev->dm.dmcub_fw_version >= DMUB_FW_VERSION(4, 0, 0) &&
+ adev->dm.dmcub_fw_version < DMUB_FW_VERSION(8, 0, 16))
+ adev->dm.dc->debug.sanity_checks = true;
+ break;
+ default:
+ break;
+ }
+
return 0;
}
@@ -3170,8 +3193,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
struct dm_atomic_state *dm_state = to_dm_atomic_state(dm->atomic_obj.state);
enum dc_connection_type new_connection_type = dc_connection_none;
struct dc_state *dc_state;
- int i, r, j, ret;
- bool need_hotplug = false;
+ int i, r, j;
struct dc_commit_streams_params commit_params = {};
if (dm->dc->caps.ips_support) {
@@ -3360,23 +3382,16 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
aconnector->mst_root)
continue;
- ret = drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr, true);
-
- if (ret < 0) {
- dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
- aconnector->dc_link);
- need_hotplug = true;
- }
+ drm_dp_mst_topology_queue_probe(&aconnector->mst_mgr);
}
drm_connector_list_iter_end(&iter);
- if (need_hotplug)
- drm_kms_helper_hotplug_event(ddev);
-
amdgpu_dm_irq_resume_late(adev);
amdgpu_dm_smu_write_watermarks_table(adev);
+ drm_kms_helper_hotplug_event(ddev);
+
return 0;
}
@@ -4648,7 +4663,12 @@ static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
if (!rc)
DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx);
} else {
- rc = dc_link_set_backlight_level(link, brightness, 0);
+ struct set_backlight_level_params backlight_level_params = { 0 };
+
+ backlight_level_params.backlight_pwm_u16_16 = brightness;
+ backlight_level_params.transition_time_in_ms = 0;
+
+ rc = dc_link_set_backlight_level(link, &backlight_level_params);
if (!rc)
DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx);
}
@@ -6793,7 +6813,7 @@ create_stream_for_sink(struct drm_connector *connector,
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;
+ aconnector->sr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
}
finish:
@@ -7326,10 +7346,15 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL;
int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8;
enum dc_status dc_result = DC_OK;
+ uint8_t bpc_limit = 6;
if (!dm_state)
return NULL;
+ if (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+ aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
+ bpc_limit = 8;
+
do {
stream = create_stream_for_sink(connector, drm_mode,
dm_state, old_stream,
@@ -7350,11 +7375,12 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
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_DEBUG_KMS("Mode %dx%d (clk %d) pixel_encoding:%s color_depth:%s failed validation -- %s\n",
drm_mode->hdisplay,
drm_mode->vdisplay,
drm_mode->clock,
- dc_result,
+ dc_pixel_encoding_to_str(stream->timing.pixel_encoding),
+ dc_color_depth_to_str(stream->timing.display_color_depth),
dc_status_to_str(dc_result));
dc_stream_release(stream);
@@ -7362,10 +7388,13 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
requested_bpc -= 2; /* lower bpc to retry validation */
}
- } while (stream == NULL && requested_bpc >= 6);
+ } while (stream == NULL && requested_bpc >= bpc_limit);
- if (dc_result == DC_FAIL_ENC_VALIDATE && !aconnector->force_yuv420_output) {
- DRM_DEBUG_KMS("Retry forcing YCbCr420 encoding\n");
+ if ((dc_result == DC_FAIL_ENC_VALIDATE ||
+ dc_result == DC_EXCEED_DONGLE_CAP) &&
+ !aconnector->force_yuv420_output) {
+ DRM_DEBUG_KMS("%s:%d Retry forcing yuv420 encoding\n",
+ __func__, __LINE__);
aconnector->force_yuv420_output = true;
stream = create_validate_stream_for_sink(aconnector, drm_mode,
@@ -8888,6 +8917,56 @@ static void amdgpu_dm_update_cursor(struct drm_plane *plane,
}
}
+static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach,
+ const struct dm_crtc_state *acrtc_state,
+ const u64 current_ts)
+{
+ struct psr_settings *psr = &acrtc_state->stream->link->psr_settings;
+ struct replay_settings *pr = &acrtc_state->stream->link->replay_settings;
+ struct amdgpu_dm_connector *aconn =
+ (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context;
+
+ if (acrtc_state->update_type > UPDATE_TYPE_FAST) {
+ if (pr->config.replay_supported && !pr->replay_feature_enabled)
+ amdgpu_dm_link_setup_replay(acrtc_state->stream->link, aconn);
+ else if (psr->psr_version != DC_PSR_VERSION_UNSUPPORTED &&
+ !psr->psr_feature_enabled)
+ if (!aconn->disallow_edp_enter_psr)
+ amdgpu_dm_link_setup_psr(acrtc_state->stream);
+ }
+
+ /* Decrement skip count when SR is enabled and we're doing fast updates. */
+ if (acrtc_state->update_type == UPDATE_TYPE_FAST &&
+ (psr->psr_feature_enabled || pr->config.replay_supported)) {
+ if (aconn->sr_skip_count > 0)
+ aconn->sr_skip_count--;
+
+ /* Allow SR when skip count is 0. */
+ acrtc_attach->dm_irq_params.allow_sr_entry = !aconn->sr_skip_count;
+
+ /*
+ * If sink supports PSR SU/Panel Replay, there is no need to rely on
+ * a vblank event disable request to enable PSR/RP. PSR SU/RP
+ * can be enabled immediately once OS demonstrates an
+ * adequate number of fast atomic commits to notify KMD
+ * of update events. See `vblank_control_worker()`.
+ */
+ if (acrtc_attach->dm_irq_params.allow_sr_entry &&
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+ !amdgpu_dm_crc_window_is_activated(acrtc_state->base.crtc) &&
+#endif
+ (current_ts - psr->psr_dirty_rects_change_timestamp_ns) > 500000000) {
+ if (pr->replay_feature_enabled && !pr->replay_allow_active)
+ amdgpu_dm_replay_enable(acrtc_state->stream, true);
+ if (psr->psr_version >= DC_PSR_VERSION_SU_1 &&
+ !psr->psr_allow_active && !aconn->disallow_edp_enter_psr)
+ amdgpu_dm_psr_enable(acrtc_state->stream);
+ }
+ } else {
+ acrtc_attach->dm_irq_params.allow_sr_entry = false;
+ }
+}
+
static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
struct drm_device *dev,
struct amdgpu_display_manager *dm,
@@ -9041,7 +9120,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
* during the PSR-SU was disabled.
*/
if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
- acrtc_attach->dm_irq_params.allow_psr_entry &&
+ acrtc_attach->dm_irq_params.allow_sr_entry &&
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
!amdgpu_dm_crc_window_is_activated(acrtc_state->base.crtc) &&
#endif
@@ -9216,9 +9295,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
bundle->stream_update.abm_level = &acrtc_state->abm_level;
mutex_lock(&dm->dc_lock);
- if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
- acrtc_state->stream->link->psr_settings.psr_allow_active)
- amdgpu_dm_psr_disable(acrtc_state->stream);
+ if (acrtc_state->update_type > UPDATE_TYPE_FAST) {
+ if (acrtc_state->stream->link->replay_settings.replay_allow_active)
+ amdgpu_dm_replay_disable(acrtc_state->stream);
+ if (acrtc_state->stream->link->psr_settings.psr_allow_active)
+ amdgpu_dm_psr_disable(acrtc_state->stream);
+ }
mutex_unlock(&dm->dc_lock);
/*
@@ -9259,57 +9341,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
dm_update_pflip_irq_state(drm_to_adev(dev),
acrtc_attach);
- if (acrtc_state->update_type > UPDATE_TYPE_FAST) {
- if (acrtc_state->stream->link->replay_settings.config.replay_supported &&
- !acrtc_state->stream->link->replay_settings.replay_feature_enabled) {
- struct amdgpu_dm_connector *aconn =
- (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context;
- amdgpu_dm_link_setup_replay(acrtc_state->stream->link, aconn);
- } else if (acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED &&
- !acrtc_state->stream->link->psr_settings.psr_feature_enabled) {
-
- struct amdgpu_dm_connector *aconn = (struct amdgpu_dm_connector *)
- acrtc_state->stream->dm_stream_context;
-
- if (!aconn->disallow_edp_enter_psr)
- amdgpu_dm_link_setup_psr(acrtc_state->stream);
- }
- }
-
- /* Decrement skip count when PSR is enabled and we're doing fast updates. */
- if (acrtc_state->update_type == UPDATE_TYPE_FAST &&
- acrtc_state->stream->link->psr_settings.psr_feature_enabled) {
- struct amdgpu_dm_connector *aconn =
- (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context;
-
- if (aconn->psr_skip_count > 0)
- aconn->psr_skip_count--;
-
- /* Allow PSR when skip count is 0. */
- acrtc_attach->dm_irq_params.allow_psr_entry = !aconn->psr_skip_count;
-
- /*
- * If sink supports PSR SU, there is no need to rely on
- * a vblank event disable request to enable PSR. PSR SU
- * can be enabled immediately once OS demonstrates an
- * adequate number of fast atomic commits to notify KMD
- * of update events. See `vblank_control_worker()`.
- */
- 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 &&
- !aconn->disallow_edp_enter_psr &&
- (timestamp_ns -
- acrtc_state->stream->link->psr_settings.psr_dirty_rects_change_timestamp_ns) >
- 500000000)
- amdgpu_dm_psr_enable(acrtc_state->stream);
- } else {
- acrtc_attach->dm_irq_params.allow_psr_entry = false;
- }
-
+ amdgpu_dm_enable_self_refresh(acrtc_attach, acrtc_state, timestamp_ns);
mutex_unlock(&dm->dc_lock);
}
@@ -9442,6 +9474,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
bool mode_set_reset_required = false;
u32 i;
struct dc_commit_streams_params params = {dc_state->streams, dc_state->stream_count};
+ bool set_backlight_level = false;
/* Disable writeback */
for_each_old_connector_in_state(state, connector, old_con_state, i) {
@@ -9561,6 +9594,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
acrtc->hw_mode = new_crtc_state->mode;
crtc->hwmode = new_crtc_state->mode;
mode_set_reset_required = true;
+ set_backlight_level = true;
} else if (modereset_required(new_crtc_state)) {
drm_dbg_atomic(dev,
"Atomic commit: RESET. crtc id %d:[%p]\n",
@@ -9612,6 +9646,19 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
acrtc->otg_inst = status->primary_otg_inst;
}
}
+
+ /* During boot up and resume the DC layer will reset the panel brightness
+ * to fix a flicker issue.
+ * It will cause the dm->actual_brightness is not the current panel brightness
+ * level. (the dm->brightness is the correct panel level)
+ * So we set the backlight level with dm->brightness value after set mode
+ */
+ if (set_backlight_level) {
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if (dm->backlight_dev[i])
+ amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
+ }
+ }
}
static void dm_set_writeback(struct amdgpu_display_manager *dm,
@@ -12080,7 +12127,7 @@ static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
break;
}
- while (j < EDID_LENGTH) {
+ while (j < EDID_LENGTH - sizeof(struct amd_vsdb_block)) {
struct amd_vsdb_block *amd_vsdb = (struct amd_vsdb_block *)&edid_ext[j];
unsigned int ieeeId = (amd_vsdb->ieee_id[2] << 16) | (amd_vsdb->ieee_id[1] << 8) | (amd_vsdb->ieee_id[0]);
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 25e95775c45c..6464a8378387 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -727,7 +727,7 @@ struct amdgpu_dm_connector {
/* Cached display modes */
struct drm_display_mode freesync_vid_base;
- int psr_skip_count;
+ int sr_skip_count;
bool disallow_edp_enter_psr;
/* Record progress status of mst*/
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 ffa4d3965b4b..64a041c2af05 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
@@ -35,7 +35,7 @@
#include "amdgpu_dm_trace.h"
#include "amdgpu_dm_debugfs.h"
-#define HPD_DETECTION_PERIOD_uS 5000000
+#define HPD_DETECTION_PERIOD_uS 2000000
#define HPD_DETECTION_TIME_uS 100000
void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc)
@@ -252,10 +252,8 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
else if (dm->active_vblank_irq_count)
dm->active_vblank_irq_count--;
- if (dm->active_vblank_irq_count > 0) {
- DRM_DEBUG_KMS("Allow idle optimizations (MALL): false\n");
+ if (dm->active_vblank_irq_count > 0)
dc_allow_idle_optimizations(dm->dc, false);
- }
/*
* Control PSR based on vblank requirements from OS
@@ -267,17 +265,14 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
* where the SU region is the full hactive*vactive region. See
* fill_dc_dirty_rects().
*/
- if (vblank_work->stream && vblank_work->stream->link) {
+ if (vblank_work->stream && vblank_work->stream->link && vblank_work->acrtc) {
amdgpu_dm_crtc_set_panel_sr_feature(
vblank_work, vblank_work->enable,
- vblank_work->acrtc->dm_irq_params.allow_psr_entry ||
- vblank_work->stream->link->replay_settings.replay_feature_enabled);
+ vblank_work->acrtc->dm_irq_params.allow_sr_entry);
}
- if (dm->active_vblank_irq_count == 0) {
- DRM_DEBUG_KMS("Allow idle optimizations (MALL): true\n");
+ if (dm->active_vblank_irq_count == 0)
dc_allow_idle_optimizations(dm->dc, true);
- }
mutex_unlock(&dm->dc_lock);
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 5c9303241aeb..6a7ecc1e4602 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
@@ -33,7 +33,7 @@ struct dm_irq_params {
struct mod_vrr_params vrr_params;
struct dc_stream_state *stream;
int active_planes;
- bool allow_psr_entry;
+ bool allow_sr_entry;
struct mod_freesync_config freesync_config;
#ifdef CONFIG_DEBUG_FS
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 0d8498ab9b23..c9a6de110b74 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -3122,7 +3122,7 @@ static enum bp_result bios_parser_get_vram_info(
struct dc_vram_info *info)
{
struct bios_parser *bp = BP_FROM_DCB(dcb);
- static enum bp_result result = BP_RESULT_BADBIOSTABLE;
+ enum bp_result result = BP_RESULT_BADBIOSTABLE;
struct atom_common_table_header *header;
struct atom_data_revision revision;
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 e93df3d6222e..bc123f1884da 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
@@ -50,12 +50,13 @@
#include "link.h"
#include "logger_types.h"
+
+
+#include "yellow_carp_offset.h"
#undef DC_LOGGER
#define DC_LOGGER \
clk_mgr->base.base.ctx->logger
-#include "yellow_carp_offset.h"
-
#define regCLK1_CLK_PLL_REQ 0x0237
#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
index 29eff386505a..91d872d6d392 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
@@ -53,9 +53,6 @@
#include "logger_types.h"
-#undef DC_LOGGER
-#define DC_LOGGER \
- clk_mgr->base.base.ctx->logger
#define MAX_INSTANCE 7
@@ -77,6 +74,9 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0,
{ { 0x0001B200, 0x0242DC00, 0, 0, 0, 0, 0, 0 } },
{ { 0x0001B400, 0x0242E000, 0, 0, 0, 0, 0, 0 } } } };
+#undef DC_LOGGER
+#define DC_LOGGER \
+ clk_mgr->base.base.ctx->logger
#define regCLK1_CLK_PLL_REQ 0x0237
#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index 7d68006137a9..b77333817f18 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -55,6 +55,7 @@
#define DC_LOGGER \
clk_mgr->base.base.ctx->logger
+
#define regCLK1_CLK_PLL_REQ 0x0237
#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
@@ -132,6 +133,8 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *
for (i = 0; i < dc->res_pool->pipe_count; ++i) {
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
+ struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dccg *dccg = clk_mgr_internal->dccg;
struct pipe_ctx *pipe = safe_to_lower
? &context->res_ctx.pipe_ctx[i]
: &dc->current_state->res_ctx.pipe_ctx[i];
@@ -148,8 +151,21 @@ static void dcn35_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *
new_pipe->stream_res.stream_enc &&
new_pipe->stream_res.stream_enc->funcs->is_fifo_enabled &&
new_pipe->stream_res.stream_enc->funcs->is_fifo_enabled(new_pipe->stream_res.stream_enc);
- if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) ||
- !pipe->stream->link_enc) && !stream_changed_otg_dig_on) {
+
+ bool has_active_hpo = false;
+
+ if (old_pipe->stream && new_pipe->stream && old_pipe->stream == new_pipe->stream) {
+ has_active_hpo = dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(old_pipe) &&
+ dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(new_pipe);
+
+ }
+
+
+ if (!has_active_hpo && !dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe) &&
+ (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) ||
+ !pipe->stream->link_enc) && !stream_changed_otg_dig_on)) {
+
+
/* This w/a should not trigger when we have a dig active */
if (disable) {
if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc)
@@ -977,11 +993,8 @@ static void dcn35_exit_low_power_state(struct clk_mgr *clk_mgr_base)
static bool dcn35_is_ips_supported(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
- bool ips_supported = true;
-
- ips_supported = dcn35_smu_get_ips_supported(clk_mgr) ? true : false;
- return ips_supported;
+ return dcn35_smu_get_ips_supported(clk_mgr) ? true : false;
}
static void dcn35_init_clocks_fpga(struct clk_mgr *clk_mgr)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 5a12fc75f97f..1dd26d5df6b9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3141,7 +3141,10 @@ static void restore_planes_and_stream_state(
return;
for (i = 0; i < status->plane_count; i++) {
+ /* refcount will always be valid, restore everything else */
+ struct kref refcount = status->plane_states[i]->refcount;
*status->plane_states[i] = scratch->plane_states[i];
+ status->plane_states[i]->refcount = refcount;
}
*stream = scratch->stream_state;
}
@@ -3835,7 +3838,7 @@ static void commit_planes_for_stream(struct dc *dc,
dc_exit_ips_for_hw_access(dc);
dc_z10_restore(dc);
- if (update_type == UPDATE_TYPE_FULL)
+ if (update_type == UPDATE_TYPE_FULL && dc->optimized_required)
hwss_process_outstanding_hw_updates(dc, dc->current_state);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -3862,6 +3865,9 @@ static void commit_planes_for_stream(struct dc *dc,
context_clock_trace(dc, context);
}
+ if (update_type == UPDATE_TYPE_FULL)
+ hwss_wait_for_outstanding_hw_updates(dc, dc->current_state);
+
top_pipe_to_program = resource_get_otg_master_for_stream(
&context->res_ctx,
stream);
@@ -5429,8 +5435,10 @@ bool dc_set_ips_disable(struct dc *dc, unsigned int disable_ips)
void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const *caller_name)
{
- if (dc->debug.disable_idle_power_optimizations)
+ if (dc->debug.disable_idle_power_optimizations) {
+ DC_LOG_DEBUG("%s: disabled\n", __func__);
return;
+ }
if (allow != dc->idle_optimizations_allowed)
DC_LOG_IPS("%s: allow_idle old=%d new=%d (caller=%s)\n", __func__,
@@ -5447,8 +5455,10 @@ void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const
return;
if (dc->hwss.apply_idle_power_optimizations && dc->clk_mgr != NULL &&
- dc->hwss.apply_idle_power_optimizations(dc, allow))
+ dc->hwss.apply_idle_power_optimizations(dc, allow)) {
dc->idle_optimizations_allowed = allow;
+ DC_LOG_DEBUG("%s: %s\n", __func__, allow ? "enabled" : "disabled");
+ }
}
void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name)
@@ -6090,11 +6100,11 @@ struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state
{
struct dc_power_profile profile = { 0 };
- if (!context || !context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc)
+ profile.power_level = !context->bw_ctx.bw.dcn.clk.p_state_change_support;
+ if (!context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc)
return profile;
struct dc *dc = context->clk_mgr->ctx->dc;
-
if (dc->res_pool->funcs->get_power_profile)
profile.power_level = dc->res_pool->funcs->get_power_profile(context);
return profile;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
index 801cdbc8117d..af1ea5792560 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
@@ -46,11 +46,6 @@
DC_LOG_IF_TRACE(__VA_ARGS__); \
} while (0)
-#define TIMING_TRACE(...) do {\
- if (dc->debug.timing_trace) \
- DC_LOG_SYNC(__VA_ARGS__); \
-} while (0)
-
#define CLOCK_TRACE(...) do {\
if (dc->debug.clock_trace) \
DC_LOG_BANDWIDTH_CALCS(__VA_ARGS__); \
@@ -306,43 +301,6 @@ void post_surface_trace(struct dc *dc)
}
-void context_timing_trace(
- struct dc *dc,
- struct resource_context *res_ctx)
-{
- int i;
- int h_pos[MAX_PIPES] = {0}, v_pos[MAX_PIPES] = {0};
- struct crtc_position position;
- unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
- DC_LOGGER_INIT(dc->ctx->logger);
-
-
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
- /* get_position() returns CRTC vertical/horizontal counter
- * hence not applicable for underlay pipe
- */
- if (pipe_ctx->stream == NULL || pipe_ctx->pipe_idx == underlay_idx)
- continue;
-
- pipe_ctx->stream_res.tg->funcs->get_position(pipe_ctx->stream_res.tg, &position);
- h_pos[i] = position.horizontal_count;
- v_pos[i] = position.vertical_count;
- }
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
-
- if (pipe_ctx->stream == NULL || pipe_ctx->pipe_idx == underlay_idx)
- continue;
-
- TIMING_TRACE("OTG_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n",
- pipe_ctx->stream_res.tg->inst,
- pipe_ctx->stream->timing.h_total,
- pipe_ctx->stream->timing.v_total,
- h_pos[i], v_pos[i]);
- }
-}
-
void context_clock_trace(
struct dc *dc,
struct dc_state *context)
@@ -434,3 +392,43 @@ char *dc_status_to_str(enum dc_status status)
return "Unexpected status error";
}
+
+char *dc_pixel_encoding_to_str(enum dc_pixel_encoding pixel_encoding)
+{
+ switch (pixel_encoding) {
+ case PIXEL_ENCODING_RGB:
+ return "RGB";
+ case PIXEL_ENCODING_YCBCR422:
+ return "YUV422";
+ case PIXEL_ENCODING_YCBCR444:
+ return "YUV444";
+ case PIXEL_ENCODING_YCBCR420:
+ return "YUV420";
+ default:
+ return "Unknown";
+ }
+}
+
+char *dc_color_depth_to_str(enum dc_color_depth color_depth)
+{
+ switch (color_depth) {
+ case COLOR_DEPTH_666:
+ return "6-bpc";
+ case COLOR_DEPTH_888:
+ return "8-bpc";
+ case COLOR_DEPTH_101010:
+ return "10-bpc";
+ case COLOR_DEPTH_121212:
+ return "12-bpc";
+ case COLOR_DEPTH_141414:
+ return "14-bpc";
+ case COLOR_DEPTH_161616:
+ return "16-bpc";
+ case COLOR_DEPTH_999:
+ return "9-bpc";
+ case COLOR_DEPTH_111111:
+ return "11-bpc";
+ default:
+ return "Unknown";
+ }
+}
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 2fdcf8d59b9f..252af83e34a5 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
@@ -312,11 +312,11 @@ void get_mpctree_visual_confirm_color(
{
const struct tg_color pipe_colors[6] = {
{MAX_TG_COLOR_VALUE, 0, 0}, /* red */
- {MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE / 4, 0}, /* orange */
{MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE, 0}, /* yellow */
{0, MAX_TG_COLOR_VALUE, 0}, /* green */
+ {0, MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE}, /* cyan */
{0, 0, MAX_TG_COLOR_VALUE}, /* blue */
- {MAX_TG_COLOR_VALUE / 2, 0, MAX_TG_COLOR_VALUE / 2}, /* purple */
+ {MAX_TG_COLOR_VALUE, 0, MAX_TG_COLOR_VALUE}, /* magenta */
};
struct pipe_ctx *top_pipe = pipe_ctx;
@@ -898,6 +898,9 @@ void hwss_setup_dpp(union block_sequence_params *params)
struct dpp *dpp = pipe_ctx->plane_res.dpp;
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ if (!plane_state)
+ return;
+
if (dpp && dpp->funcs->dpp_setup) {
// program the input csc
dpp->funcs->dpp_setup(dpp,
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
index dfdfe22d9e85..457d60eeb486 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
@@ -430,11 +430,10 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link,
}
bool dc_link_set_backlight_level(const struct dc_link *link,
- uint32_t backlight_pwm_u16_16,
- uint32_t frame_ramp)
+ struct set_backlight_level_params *backlight_level_params)
{
return link->dc->link_srv->edp_set_backlight_level(link,
- backlight_pwm_u16_16, frame_ramp);
+ backlight_level_params);
}
bool dc_link_set_backlight_level_nits(struct dc_link *link,
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 33125b95c3a1..619fad17de55 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1501,6 +1501,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
res = spl_calculate_scaler_params(spl_in, spl_out);
// Convert respective out params from SPL to scaler data
translate_SPL_out_params_to_pipe_ctx(pipe_ctx, spl_out);
+
+ /* Ignore scaler failure if pipe context plane is phantom plane */
+ if (!res && plane_state->is_phantom)
+ res = true;
} else {
#endif
/* depends on h_active */
@@ -1571,6 +1575,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
&plane_state->scaling_quality);
}
+ /* Ignore scaler failure if pipe context plane is phantom plane */
+ if (!res && plane_state->is_phantom)
+ res = true;
+
if (res && (pipe_ctx->plane_res.scl_data.taps.v_taps != temp.v_taps ||
pipe_ctx->plane_res.scl_data.taps.h_taps != temp.h_taps ||
pipe_ctx->plane_res.scl_data.taps.v_taps_c != temp.v_taps_c ||
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
index 2597e3fd562b..e006f816ff2f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
@@ -265,6 +265,9 @@ struct dc_state *dc_state_create_copy(struct dc_state *src_state)
dc_state_copy_internal(new_state, src_state);
#ifdef CONFIG_DRM_AMD_DC_FP
+ new_state->bw_ctx.dml2 = NULL;
+ new_state->bw_ctx.dml2_dc_power_source = NULL;
+
if (src_state->bw_ctx.dml2 &&
!dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) {
dc_state_release(new_state);
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 5d233c09d239..55dc482d9b36 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -292,7 +292,9 @@ bool dc_stream_set_cursor_attributes(
* 2. If not subvp high refresh, for single display cases, if resolution is >= 5K and refresh rate < 120hz
* 3. If not subvp high refresh, for multi display cases, if resolution is >= 4K and refresh rate < 120hz
*/
- if (dc->debug.allow_sw_cursor_fallback && attributes->height * attributes->width * 4 > 16384) {
+ if (dc->debug.allow_sw_cursor_fallback &&
+ attributes->height * attributes->width * 4 > 16384 &&
+ !stream->hw_cursor_req) {
if (check_subvp_sw_cursor_fallback_req(dc, stream))
return false;
}
@@ -810,12 +812,12 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
stream->dst.height,
stream->output_color_space);
DC_LOG_DC(
- "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n",
+ "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixel_encoding:%s, color_depth:%s\n",
stream->timing.pix_clk_100hz / 10,
stream->timing.h_total,
stream->timing.v_total,
- stream->timing.pixel_encoding,
- stream->timing.display_color_depth);
+ dc_pixel_encoding_to_str(stream->timing.pixel_encoding),
+ dc_color_depth_to_str(stream->timing.display_color_depth));
DC_LOG_DC(
"\tlink: %d\n",
stream->link->link_index);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 6d76dc110d38..104051935884 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -55,7 +55,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
-#define DC_VER "3.2.306"
+#define DC_VER "3.2.310"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@@ -225,6 +225,7 @@ struct dc_dmub_caps {
bool subvp_psr;
bool gecc_enable;
uint8_t fams_ver;
+ bool aux_backlight_support;
};
struct dc_scl_caps {
@@ -868,7 +869,6 @@ struct dc_debug_options {
bool sanity_checks;
bool max_disp_clk;
bool surface_trace;
- bool timing_trace;
bool clock_trace;
bool validation_trace;
bool bandwidth_calcs_trace;
@@ -1067,6 +1067,7 @@ struct dc_debug_options {
unsigned int sharpen_policy;
unsigned int scale_to_sharpness_policy;
bool skip_full_updated_if_possible;
+ unsigned int enable_oled_edp_power_up_opt;
};
@@ -2210,8 +2211,7 @@ void dc_link_edp_panel_backlight_power_on(struct dc_link *link,
* and 16 bit fractional, where 1.0 is max backlight value.
*/
bool dc_link_set_backlight_level(const struct dc_link *dc_link,
- uint32_t backlight_pwm_u16_16,
- uint32_t frame_ramp);
+ struct set_backlight_level_params *backlight_level_params);
/* Set/get nits-based backlight level of an embedded panel (eDP, LVDS). */
bool dc_link_set_backlight_level_nits(struct dc_link *link,
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 f0417ee6fcf8..f90fc154549a 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -1013,7 +1013,6 @@ static bool dc_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
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
diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
index 24aa9df892f3..c8d8e335fa37 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -8,13 +8,13 @@
#include "dcn32/dcn32_dpp.h"
#include "dcn401/dcn401_dpp.h"
-static struct spl_funcs dcn2_spl_funcs = {
+static struct spl_callbacks dcn2_spl_callbacks = {
.spl_calc_lb_num_partitions = dscl2_spl_calc_lb_num_partitions,
};
-static struct spl_funcs dcn32_spl_funcs = {
+static struct spl_callbacks dcn32_spl_callbacks = {
.spl_calc_lb_num_partitions = dscl32_spl_calc_lb_num_partitions,
};
-static struct spl_funcs dcn401_spl_funcs = {
+static struct spl_callbacks dcn401_spl_callbacks = {
.spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions,
};
static void populate_splrect_from_rect(struct spl_rect *spl_rect, const struct rect *rect)
@@ -77,16 +77,16 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
// This is used to determine the vtap support
switch (plane_state->ctx->dce_version) {
case DCN_VERSION_2_0:
- spl_in->funcs = &dcn2_spl_funcs;
+ spl_in->callbacks = dcn2_spl_callbacks;
break;
case DCN_VERSION_3_2:
- spl_in->funcs = &dcn32_spl_funcs;
+ spl_in->callbacks = dcn32_spl_callbacks;
break;
case DCN_VERSION_4_01:
- spl_in->funcs = &dcn401_spl_funcs;
+ spl_in->callbacks = dcn401_spl_callbacks;
break;
default:
- spl_in->funcs = &dcn2_spl_funcs;
+ spl_in->callbacks = dcn2_spl_callbacks;
}
// Make format field from spl_in point to plane_res scl_data format
spl_in->basic_in.format = (enum spl_pixel_format)pipe_ctx->plane_res.scl_data.format;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 3401f4c9fb10..edf4df1d03b5 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -180,6 +180,8 @@ struct dc_panel_patch {
unsigned int remove_sink_ext_caps;
unsigned int disable_colorimetry;
uint8_t blankstream_before_otg_off;
+ bool oled_optimize_display_on;
+ unsigned int force_mst_blocked_discovery;
};
struct dc_edid_caps {
@@ -1302,4 +1304,31 @@ struct dc_commit_streams_params {
enum dc_power_source_type power_source;
};
+struct set_backlight_level_params {
+ /* backlight in pwm */
+ uint32_t backlight_pwm_u16_16;
+ /* brightness ramping */
+ uint32_t frame_ramp;
+ /* backlight control type
+ * 0: PWM backlight control
+ * 1: VESA AUX backlight control
+ * 2: AMD AUX backlight control
+ */
+ enum backlight_control_type control_type;
+ /* backlight in millinits */
+ uint32_t backlight_millinits;
+ /* transition time in ms */
+ uint32_t transition_time_in_ms;
+ /* minimum luminance in nits */
+ uint32_t min_luminance;
+ /* maximum luminance in nits */
+ uint32_t max_luminance;
+ /* minimum backlight in pwm */
+ uint32_t min_backlight_pwm;
+ /* maximum backlight in pwm */
+ uint32_t max_backlight_pwm;
+ /* AUX HW instance */
+ uint8_t aux_inst;
+};
+
#endif /* DC_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
index 838d72eaa87f..b363f5360818 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
@@ -1392,10 +1392,10 @@ static void dccg35_set_dtbclk_dto(
/* The recommended programming sequence to enable DTBCLK DTO to generate
* valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
- * be set only after DTO is enabled
+ * be set only after DTO is enabled.
+ * PIPEx_DTO_SRC_SEL should not be programmed during DTBCLK update since OTG may still be on, and the
+ * programming is handled in program_pix_clk() regardless, so it can be removed from here.
*/
- REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
- PIPE_DTO_SRC_SEL[params->otg_inst], 2);
} else {
switch (params->otg_inst) {
case 0:
@@ -1412,9 +1412,12 @@ static void dccg35_set_dtbclk_dto(
break;
}
- REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
- DTBCLK_DTO_ENABLE[params->otg_inst], 0,
- PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);
+ /**
+ * PIPEx_DTO_SRC_SEL should not be programmed during DTBCLK update since OTG may still be on, and the
+ * programming is handled in program_pix_clk() regardless, so it can be removed from here.
+ */
+ REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
+ DTBCLK_DTO_ENABLE[params->otg_inst], 0);
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/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
index 5c2825bc9a87..d199e4ed2e59 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -277,7 +277,6 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
uint32_t misc1 = 0;
uint32_t h_blank;
uint32_t h_back_porch;
- uint8_t synchronous_clock = 0; /* asynchronous mode */
uint8_t colorimetry_bpc;
uint8_t dynamic_range_rgb = 0; /*full range*/
uint8_t dynamic_range_ycbcr = 1; /*bt709*/
@@ -380,7 +379,6 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
break;
}
- misc0 = misc0 | synchronous_clock;
misc0 = colorimetry_bpc << 5;
if (REG(DP_MSA_TIMING_PARAM1)) {
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
index db7557a1c613..8a3fbf95c48f 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
@@ -76,7 +76,6 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MAS
mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C,
value);
- temp = 0;
value = 0;
temp = address.low_part >>
UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT;
@@ -112,7 +111,6 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MAS
mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L,
value);
- temp = 0;
value = 0;
temp = address.low_part >>
UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
index 05df502a54f2..88cf47a5ea75 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
@@ -46,7 +46,7 @@
#include "clk_mgr.h"
__printf(3, 4)
-unsigned int snprintf_count(char *pbuf, unsigned int bufsize, char *fmt, ...)
+unsigned int snprintf_count(char *pbuf, unsigned int bufsize, const char *fmt, ...)
{
int ret_vsnprintf;
unsigned int chars_printed;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
index 1e1038fb04e8..0690c346f2c5 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
@@ -280,157 +280,6 @@ bool cm3_helper_translate_curve_to_hw_format(
return true;
}
-#define NUM_DEGAMMA_REGIONS 12
-
-
-bool cm3_helper_translate_curve_to_degamma_hw_format(
- const struct dc_transfer_func *output_tf,
- struct pwl_params *lut_params)
-{
- struct curve_points3 *corner_points;
- struct pwl_result_data *rgb_resulted;
- struct pwl_result_data *rgb;
- struct pwl_result_data *rgb_plus_1;
-
- int32_t region_start, region_end;
- int32_t i;
- uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
-
- if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
- return false;
-
- corner_points = lut_params->corner_points;
- rgb_resulted = lut_params->rgb_resulted;
- hw_points = 0;
-
- memset(lut_params, 0, sizeof(struct pwl_params));
- memset(seg_distr, 0, sizeof(seg_distr));
-
- region_start = -NUM_DEGAMMA_REGIONS;
- region_end = 0;
-
-
- for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
- /* 12 segments
- * segments are from 2^-12 to 0
- */
- for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)
- seg_distr[i] = 4;
-
- for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
- hw_points += (1 << seg_distr[k]);
- }
-
- j = 0;
- for (k = 0; k < (region_end - region_start); k++) {
- increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
- start_index = (region_start + k + MAX_LOW_POINT) *
- NUMBER_SW_SEGMENTS;
- for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
- i += increment) {
- if (j == hw_points - 1)
- break;
- if (i >= TRANSFER_FUNC_POINTS)
- return false;
- rgb_resulted[j].red = output_tf->tf_pts.red[i];
- rgb_resulted[j].green = output_tf->tf_pts.green[i];
- rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
- j++;
- }
- }
-
- /* last point */
- start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
- rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
- rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
- rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
-
- corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
- dc_fixpt_from_int(region_start));
- corner_points[0].green.x = corner_points[0].red.x;
- corner_points[0].blue.x = corner_points[0].red.x;
- corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
- dc_fixpt_from_int(region_end));
- corner_points[1].green.x = corner_points[1].red.x;
- corner_points[1].blue.x = corner_points[1].red.x;
-
- corner_points[0].red.y = rgb_resulted[0].red;
- corner_points[0].green.y = rgb_resulted[0].green;
- corner_points[0].blue.y = rgb_resulted[0].blue;
-
- /* see comment above, m_arrPoints[1].y should be the Y value for the
- * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
- */
- corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
- corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
- corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
- corner_points[1].red.slope = dc_fixpt_zero;
- corner_points[1].green.slope = dc_fixpt_zero;
- corner_points[1].blue.slope = dc_fixpt_zero;
-
- if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
- /* for PQ, we want to have a straight line from last HW X point,
- * and the slope to be such that we hit 1.0 at 10000 nits.
- */
- const struct fixed31_32 end_value =
- dc_fixpt_from_int(125);
-
- corner_points[1].red.slope = dc_fixpt_div(
- dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
- dc_fixpt_sub(end_value, corner_points[1].red.x));
- corner_points[1].green.slope = dc_fixpt_div(
- dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
- dc_fixpt_sub(end_value, corner_points[1].green.x));
- corner_points[1].blue.slope = dc_fixpt_div(
- dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
- dc_fixpt_sub(end_value, corner_points[1].blue.x));
- }
-
- lut_params->hw_points_num = hw_points;
-
- k = 0;
- for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
- if (seg_distr[k] != -1) {
- lut_params->arr_curve_points[k].segments_num =
- seg_distr[k];
- lut_params->arr_curve_points[i].offset =
- lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
- }
- k++;
- }
-
- if (seg_distr[k] != -1)
- lut_params->arr_curve_points[k].segments_num = seg_distr[k];
-
- rgb = rgb_resulted;
- rgb_plus_1 = rgb_resulted + 1;
-
- i = 1;
- while (i != hw_points + 1) {
- if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
- rgb_plus_1->red = rgb->red;
- if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
- rgb_plus_1->green = rgb->green;
- if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
- rgb_plus_1->blue = rgb->blue;
-
- rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
- rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
- rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
-
- ++rgb_plus_1;
- ++rgb;
- ++i;
- }
- cm3_helper_convert_to_custom_float(rgb_resulted,
- lut_params->corner_points,
- hw_points, false);
-
- return true;
-}
-
bool cm3_helper_convert_to_custom_float(
struct pwl_result_data *rgb_resulted,
struct curve_points3 *corner_points,
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
index f496e952ceec..d01a8b8f9595 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
@@ -255,7 +255,6 @@ void enc1_stream_encoder_dp_set_stream_attribute(
uint32_t misc1 = 0;
uint32_t h_blank;
uint32_t h_back_porch;
- uint8_t synchronous_clock = 0; /* asynchronous mode */
uint8_t colorimetry_bpc;
uint8_t dp_pixel_encoding = 0;
uint8_t dp_component_depth = 0;
@@ -362,7 +361,6 @@ void enc1_stream_encoder_dp_set_stream_attribute(
break;
}
- misc0 = misc0 | synchronous_clock;
misc0 = colorimetry_bpc << 5;
switch (output_color_space) {
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
index 0a27e0942a12..098c2a01a850 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
@@ -447,7 +447,6 @@ void enc401_stream_encoder_dp_set_stream_attribute(
uint32_t misc1 = 0;
uint32_t h_blank;
uint32_t h_back_porch;
- uint8_t synchronous_clock = 0; /* asynchronous mode */
uint8_t colorimetry_bpc;
uint8_t dp_pixel_encoding = 0;
uint8_t dp_component_depth = 0;
@@ -603,7 +602,6 @@ void enc401_stream_encoder_dp_set_stream_attribute(
break;
}
- misc0 = misc0 | synchronous_clock;
misc0 = colorimetry_bpc << 5;
switch (output_color_space) {
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h
index 9405c47ee2a9..f81e5a4e1d6d 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services.h
@@ -143,7 +143,7 @@ void generic_reg_wait(const struct dc_context *ctx,
unsigned int delay_between_poll_us, unsigned int time_out_num_tries,
const char *func_name, int line);
-unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...);
+unsigned int snprintf_count(char *pBuf, unsigned int bufSize, const char *fmt, ...);
/* These macros need to be used with soc15 registers in order to retrieve
* the actual offset.
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
index 7a01a956e4bb..138b4b1e42ed 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
@@ -859,7 +859,7 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
plane->immediate_flip = plane_state->flip_immediate;
plane->composition.rect_out_height_spans_vactive =
- plane_state->dst_rect.height >= stream->timing.v_addressable &&
+ plane_state->dst_rect.height >= stream->src.height &&
stream->dst.height >= stream->timing.v_addressable;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_dchub_registers.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_dchub_registers.h
index 83fc15bf13cf..25b607e7b726 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_dchub_registers.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_dchub_registers.h
@@ -88,6 +88,7 @@ struct dml2_display_arb_regs {
uint32_t sdpif_request_rate_limit;
uint32_t allow_sdpif_rate_limit_when_cstate_req;
uint32_t dcfclk_deep_sleep_hysteresis;
+ uint32_t pstate_stall_threshold;
};
struct dml2_cursor_dlg_regs{
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index 3ea54fd52e46..601320b1be81 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -11,6 +11,7 @@
#define DML2_MAX_FMT_420_BUFFER_WIDTH 4096
#define DML_MAX_NUM_OF_SLICES_PER_DSC 4
+#define ALLOW_SDPIF_RATE_LIMIT_PRE_CSTATE
const char *dml2_core_internal_bw_type_str(enum dml2_core_internal_bw_type bw_type)
{
@@ -3886,6 +3887,10 @@ static void CalculateSwathAndDETConfiguration(struct dml2_core_internal_scratch
#endif
*p->hw_debug5 = false;
+#ifdef ALLOW_SDPIF_RATE_LIMIT_PRE_CSTATE
+ if (p->NumberOfActiveSurfaces > 1)
+ *p->hw_debug5 = true;
+#else
for (unsigned int k = 0; k < p->NumberOfActiveSurfaces; ++k) {
if (!(p->mrq_present) && (!(*p->UnboundedRequestEnabled)) && (TotalActiveDPP == 1)
&& p->display_cfg->plane_descriptors[k].surface.dcc.enable
@@ -3901,6 +3906,7 @@ static void CalculateSwathAndDETConfiguration(struct dml2_core_internal_scratch
dml2_printf("DML::%s: k=%u hw_debug5 = %u\n", __func__, k, *p->hw_debug5);
#endif
}
+#endif
}
static enum dml2_odm_mode DecideODMMode(unsigned int HActive,
@@ -12236,6 +12242,8 @@ static void rq_dlg_get_dlg_reg(
static void rq_dlg_get_arb_params(const struct dml2_display_cfg *display_cfg, const struct dml2_core_internal_display_mode_lib *mode_lib, struct dml2_display_arb_regs *arb_param)
{
+ double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
+
arb_param->max_req_outstanding = mode_lib->soc.max_outstanding_reqs;
arb_param->min_req_outstanding = mode_lib->soc.max_outstanding_reqs; // turn off the sat level feature if this set to max
arb_param->sdpif_request_rate_limit = (3 * mode_lib->ip.words_per_channel * mode_lib->soc.clk_table.dram_config.channel_count) / 4;
@@ -12247,6 +12255,7 @@ static void rq_dlg_get_arb_params(const struct dml2_display_cfg *display_cfg, co
arb_param->compbuf_size = mode_lib->mp.CompressedBufferSizeInkByte / mode_lib->ip.compressed_buffer_segment_size_in_kbytes;
arb_param->allow_sdpif_rate_limit_when_cstate_req = dml_get_hw_debug5(mode_lib);
arb_param->dcfclk_deep_sleep_hysteresis = dml_get_dcfclk_deep_sleep_hysteresis(mode_lib);
+ arb_param->pstate_stall_threshold = (unsigned int)(mode_lib->ip_caps.fams2.max_allow_delay_us * refclk_freq_in_mhz);
#ifdef __DML_VBA_DEBUG__
dml2_printf("DML::%s: max_req_outstanding = %d\n", __func__, arb_param->max_req_outstanding);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
index 5a09dd298e6f..92269f0e50ed 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
@@ -8,6 +8,7 @@
#include "dml2_pmo_dcn4_fams2.h"
static const double MIN_VACTIVE_MARGIN_PCT = 0.25; // We need more than non-zero margin because DET buffer granularity can alter vactive latency hiding
+static const double MIN_BLANK_STUTTER_FACTOR = 3.0;
static const struct dml2_pmo_pstate_strategy base_strategy_list_1_display[] = {
// VActive Preferred
@@ -2140,6 +2141,7 @@ bool pmo_dcn4_fams2_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in
struct dml2_pmo_instance *pmo = in_out->instance;
bool stutter_period_meets_z8_eco = true;
bool z8_stutter_optimization_too_expensive = false;
+ bool stutter_optimization_too_expensive = false;
double line_time_us, vblank_nom_time_us;
unsigned int i;
@@ -2161,10 +2163,15 @@ bool pmo_dcn4_fams2_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in
line_time_us = (double)in_out->base_display_config->display_config.stream_descriptors[i].timing.h_total / (in_out->base_display_config->display_config.stream_descriptors[i].timing.pixel_clock_khz * 1000) * 1000000;
vblank_nom_time_us = line_time_us * in_out->base_display_config->display_config.stream_descriptors[i].timing.vblank_nom;
- if (vblank_nom_time_us < pmo->soc_bb->power_management_parameters.z8_stutter_exit_latency_us) {
+ if (vblank_nom_time_us < pmo->soc_bb->power_management_parameters.z8_stutter_exit_latency_us * MIN_BLANK_STUTTER_FACTOR) {
z8_stutter_optimization_too_expensive = true;
break;
}
+
+ if (vblank_nom_time_us < pmo->soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us * MIN_BLANK_STUTTER_FACTOR) {
+ stutter_optimization_too_expensive = true;
+ break;
+ }
}
pmo->scratch.pmo_dcn4.num_stutter_candidates = 0;
@@ -2180,7 +2187,7 @@ bool pmo_dcn4_fams2_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in
pmo->scratch.pmo_dcn4.z8_vblank_optimizable = false;
}
- if (pmo->soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us > 0) {
+ if (!stutter_optimization_too_expensive && pmo->soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us > 0) {
pmo->scratch.pmo_dcn4.optimal_vblank_reserved_time_for_stutter_us[pmo->scratch.pmo_dcn4.num_stutter_candidates] = (unsigned int)pmo->soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us;
pmo->scratch.pmo_dcn4.num_stutter_candidates++;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
index 6eccf0241d85..1ed21c1b86a5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
@@ -258,12 +258,25 @@ static unsigned int find_preferred_pipe_candidates(const struct dc_state *existi
* However this condition comes with a caveat. We need to ignore pipes that will
* require a change in OPP but still have the same stream id. For example during
* an MPC to ODM transiton.
+ *
+ * Adding check to avoid pipe select on the head pipe by utilizing dc resource
+ * helper function resource_get_primary_dpp_pipe and comparing the pipe index.
*/
if (existing_state) {
for (i = 0; i < pipe_count; i++) {
if (existing_state->res_ctx.pipe_ctx[i].stream && existing_state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id) {
+ struct pipe_ctx *head_pipe =
+ resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ?
+ resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) :
+ NULL;
+
+ // we should always respect the head pipe from selection
+ if (head_pipe && head_pipe->pipe_idx == i)
+ continue;
if (existing_state->res_ctx.pipe_ctx[i].plane_res.hubp &&
- existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i)
+ existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i &&
+ (existing_state->res_ctx.pipe_ctx[i].prev_odm_pipe ||
+ existing_state->res_ctx.pipe_ctx[i].next_odm_pipe))
continue;
preferred_pipe_candidates[num_preferred_candidates++] = i;
@@ -292,6 +305,14 @@ static unsigned int find_last_resort_pipe_candidates(const struct dc_state *exis
*/
if (existing_state) {
for (i = 0; i < pipe_count; i++) {
+ struct pipe_ctx *head_pipe =
+ resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ?
+ resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) :
+ NULL;
+
+ // we should always respect the head pipe from selection
+ if (head_pipe && head_pipe->pipe_idx == i)
+ continue;
if ((existing_state->res_ctx.pipe_ctx[i].plane_res.hubp &&
existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i) ||
existing_state->res_ctx.pipe_ctx[i].stream_res.tg)
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
index 5105fd580017..2f92e7d4981b 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
@@ -1091,7 +1091,8 @@ void dpp401_dscl_set_scaler_manual_scale(struct dpp *dpp_base,
/* ISHARP_DELTA_LUT */
dpp401_dscl_set_isharp_filter(dpp, scl_data->dscl_prog_data.isharp_delta);
dpp->scl_data.dscl_prog_data.sharpness_level = scl_data->dscl_prog_data.sharpness_level;
- dpp->scl_data.dscl_prog_data.isharp_delta = scl_data->dscl_prog_data.isharp_delta;
+ memcpy(dpp->scl_data.dscl_prog_data.isharp_delta, scl_data->dscl_prog_data.isharp_delta,
+ sizeof(uint32_t) * ISHARP_LUT_TABLE_SIZE);
if (memcmp(&dpp->scl_data, scl_data, sizeof(*scl_data)) == 0)
return;
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index ebd5df1a36e8..d9aaebfa3a0a 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -1093,14 +1093,11 @@ static bool setup_dsc_config(
if (!is_dsc_possible)
goto done;
- // Final decission: can we do DSC or not?
- if (is_dsc_possible) {
- // Fill out the rest of DSC settings
- dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
- dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
- dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
- dsc_cfg->is_dp = dsc_sink_caps->is_dp;
- }
+ /* Fill out the rest of DSC settings */
+ dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
+ dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
+ dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
+ dsc_cfg->is_dp = dsc_sink_caps->is_dp;
done:
if (!is_dsc_possible)
diff --git a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h
index bd98b327a6c7..b86347c9b038 100644
--- a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h
+++ b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_cm_common.h
@@ -63,10 +63,6 @@ bool cm3_helper_translate_curve_to_hw_format(
const struct dc_transfer_func *output_tf,
struct pwl_params *lut_params, bool fixpoint);
-bool cm3_helper_translate_curve_to_degamma_hw_format(
- const struct dc_transfer_func *output_tf,
- struct pwl_params *lut_params);
-
bool cm3_helper_convert_to_custom_float(
struct pwl_result_data *rgb_resulted,
struct curve_points3 *corner_points,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
index a1e2cde9c4cc..9fbd45c7dfef 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
@@ -198,6 +198,9 @@ struct dcn_hubbub_registers {
uint32_t DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B;
uint32_t DCHUBBUB_ARB_FRAC_URG_BW_MALL_A;
uint32_t DCHUBBUB_ARB_FRAC_URG_BW_MALL_B;
+ uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL1;
+ uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL2;
+ uint32_t DCHUBBUB_CTRL_STATUS;
};
#define HUBBUB_REG_FIELD_LIST_DCN32(type) \
@@ -313,7 +316,17 @@ struct dcn_hubbub_registers {
type DCN_VM_ERROR_VMID;\
type DCN_VM_ERROR_TABLE_LEVEL;\
type DCN_VM_ERROR_PIPE;\
- type DCN_VM_ERROR_INTERRUPT_STATUS
+ type DCN_VM_ERROR_INTERRUPT_STATUS;\
+ type DCHUBBUB_TIMEOUT_ERROR_STATUS;\
+ type DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD;\
+ type DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD;\
+ type DCHUBBUB_TIMEOUT_DETECTION_EN;\
+ type DCHUBBUB_TIMEOUT_TIMER_RESET;\
+ type ROB_UNDERFLOW_STATUS;\
+ type ROB_OVERFLOW_STATUS;\
+ type ROB_OVERFLOW_CLEAR;\
+ type DCHUBBUB_HW_DEBUG;\
+ type CSTATE_SWATH_CHK_GOOD_MODE
#define HUBBUB_STUTTER_REG_FIELD_LIST(type) \
type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A;\
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
index 036bb3e6c957..46d8f5c70750 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
@@ -96,6 +96,7 @@ struct dcn20_hubbub {
unsigned int det1_size;
unsigned int det2_size;
unsigned int det3_size;
+ bool allow_sdpif_rate_limit_when_cstate_req;
};
void hubbub2_construct(struct dcn20_hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
index 37d26fa0b6fb..92fab471b183 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
@@ -1192,6 +1192,37 @@ static void dcn401_wait_for_det_update(struct hubbub *hubbub, int hubp_inst)
}
}
+static bool dcn401_program_arbiter(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ bool wm_pending = false;
+ uint32_t temp;
+
+ /* request backpressure and outstanding return threshold (unused)*/
+ //REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, arb_regs->req_stall_threshold);
+
+ /* P-State stall threshold */
+ REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, arb_regs->pstate_stall_threshold);
+
+ if (safe_to_lower || arb_regs->allow_sdpif_rate_limit_when_cstate_req > hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ hubbub2->allow_sdpif_rate_limit_when_cstate_req = arb_regs->allow_sdpif_rate_limit_when_cstate_req;
+
+ /* only update the required bits */
+ REG_GET(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, &temp);
+ if (hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ temp |= (1 << 5);
+ } else {
+ temp &= ~(1 << 5);
+ }
+ REG_UPDATE(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, temp);
+ } else {
+ wm_pending = true;
+ }
+
+ return wm_pending;
+}
+
static const struct hubbub_funcs hubbub4_01_funcs = {
.update_dchub = hubbub2_update_dchub,
.init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,
@@ -1215,6 +1246,7 @@ static const struct hubbub_funcs hubbub4_01_funcs = {
.program_det_segments = dcn401_program_det_segments,
.program_compbuf_segments = dcn401_program_compbuf_segments,
.wait_for_det_update = dcn401_wait_for_det_update,
+ .program_arbiter = dcn401_program_arbiter,
};
void hubbub401_construct(struct dcn20_hubbub *hubbub2,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
index f35f19ba3e18..b1d9ea9d1c3d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
@@ -123,8 +123,17 @@
HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCFCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\
HUBBUB_SF(DCHUBBUB_SDPIF_CFG0, SDPIF_PORT_CONTROL, mask_sh),\
HUBBUB_SF(DCHUBBUB_SDPIF_CFG1, SDPIF_MAX_NUM_OUTSTANDING, mask_sh),\
- HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh)
-
+ HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_ERROR_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_DETECTION_EN, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_UNDERFLOW_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_CLEAR, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, CSTATE_SWATH_CHK_GOOD_MODE, mask_sh)
bool hubbub401_program_urgent_watermarks(
struct hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index c31ec44ccd8c..81f4c386c287 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -1039,7 +1039,8 @@ void dce110_edp_backlight_control(
link_transmitter_control(ctx->dc_bios, &cntl);
if (enable && link->dpcd_sink_ext_caps.bits.oled &&
- !link->dc->config.edp_no_power_sequencing) {
+ !link->dc->config.edp_no_power_sequencing &&
+ !link->local_sink->edid_caps.panel_patch.oled_optimize_display_on) {
post_T7_delay += link->panel_config.pps.extra_post_t7_ms;
msleep(post_T7_delay);
}
@@ -3142,10 +3143,10 @@ static void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
}
bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx,
- struct set_backlight_level_params *params)
+ struct set_backlight_level_params *backlight_level_params)
{
- uint32_t backlight_pwm_u16_16 = params->backlight_pwm_u16_16;
- uint32_t frame_ramp = params->frame_ramp;
+ uint32_t backlight_pwm_u16_16 = backlight_level_params->backlight_pwm_u16_16;
+ uint32_t frame_ramp = backlight_level_params->frame_ramp;
struct dc_link *link = pipe_ctx->stream->link;
struct dc *dc = link->ctx->dc;
struct abm *abm = pipe_ctx->stream_res.abm;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 05424a9af58b..b029ec1b26d3 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -1925,9 +1925,9 @@ static void dcn20_program_pipe(
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);
}
- if (pipe_ctx->update_flags.raw ||
- (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) ||
- pipe_ctx->stream->update_flags.raw)
+ if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw ||
+ pipe_ctx->plane_state->update_flags.raw ||
+ pipe_ctx->stream->update_flags.raw))
dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable ||
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
index 630e05f32c80..61efb15572ff 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
@@ -137,7 +137,7 @@ void dcn21_PLAT_58856_wa(struct dc_state *context, struct pipe_ctx *pipe_ctx)
pipe_ctx->stream->dpms_off = true;
}
-static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst,
+bool dcn21_dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst,
uint32_t option, uint32_t panel_inst, uint32_t pwrseq_inst)
{
union dmub_rb_cmd cmd;
@@ -199,7 +199,7 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
abm->funcs->set_pipe_ex(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE,
panel_cntl->inst, panel_cntl->pwrseq_inst);
} else {
- dmub_abm_set_pipe(abm,
+ dcn21_dmub_abm_set_pipe(abm,
otg_inst,
SET_ABM_PIPE_IMMEDIATELY_DISABLE,
panel_cntl->inst,
@@ -234,7 +234,7 @@ void dcn21_set_pipe(struct pipe_ctx *pipe_ctx)
panel_cntl->inst,
panel_cntl->pwrseq_inst);
} else {
- dmub_abm_set_pipe(abm, otg_inst,
+ dcn21_dmub_abm_set_pipe(abm, otg_inst,
SET_ABM_PIPE_NORMAL,
panel_cntl->inst,
panel_cntl->pwrseq_inst);
@@ -242,15 +242,15 @@ void dcn21_set_pipe(struct pipe_ctx *pipe_ctx)
}
bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
- struct set_backlight_level_params *params)
+ struct set_backlight_level_params *backlight_level_params)
{
struct dc_context *dc = pipe_ctx->stream->ctx;
struct abm *abm = pipe_ctx->stream_res.abm;
struct timing_generator *tg = pipe_ctx->stream_res.tg;
struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
uint32_t otg_inst;
- uint32_t backlight_pwm_u16_16 = params->backlight_pwm_u16_16;
- uint32_t frame_ramp = params->frame_ramp;
+ uint32_t backlight_pwm_u16_16 = backlight_level_params->backlight_pwm_u16_16;
+ uint32_t frame_ramp = backlight_level_params->frame_ramp;
if (!abm || !tg || !panel_cntl)
return false;
@@ -258,7 +258,7 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
otg_inst = tg->inst;
if (dc->dc->res_pool->dmcu) {
- dce110_set_backlight_level(pipe_ctx, params);
+ dce110_set_backlight_level(pipe_ctx, backlight_level_params);
return true;
}
@@ -269,7 +269,7 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
panel_cntl->inst,
panel_cntl->pwrseq_inst);
} else {
- dmub_abm_set_pipe(abm,
+ dcn21_dmub_abm_set_pipe(abm,
otg_inst,
SET_ABM_PIPE_NORMAL,
panel_cntl->inst,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.h
index a7eaaa4596be..f72a27ac1bf1 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.h
@@ -47,6 +47,8 @@ void dcn21_optimize_pwr_state(
void dcn21_PLAT_58856_wa(struct dc_state *context,
struct pipe_ctx *pipe_ctx);
+bool dcn21_dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst,
+ uint32_t option, uint32_t panel_inst, uint32_t pwrseq_inst);
void dcn21_set_pipe(struct pipe_ctx *pipe_ctx);
void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx);
bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
index bfc78a42bc2a..03ba01f4ace1 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
@@ -47,9 +47,11 @@
#include "dce/dmub_outbox.h"
#include "link.h"
#include "dcn10/dcn10_hwseq.h"
+#include "dcn21/dcn21_hwseq.h"
#include "inc/link_enc_cfg.h"
#include "dcn30/dcn30_vpg.h"
#include "dce/dce_i2c_hw.h"
+#include "dce/dmub_abm_lcd.h"
#define DC_LOGGER_INIT(logger)
@@ -517,15 +519,18 @@ static void dcn31_reset_back_end_for_pipe(
dc->hwss.set_abm_immediate_disable(pipe_ctx);
- if ((!pipe_ctx->stream->dpms_off || pipe_ctx->stream->link->link_status.link_active)
- && pipe_ctx->stream->sink && pipe_ctx->stream->sink->edid_caps.panel_patch.blankstream_before_otg_off) {
+ link = pipe_ctx->stream->link;
+
+ if ((!pipe_ctx->stream->dpms_off || link->link_status.link_active) &&
+ (link->connector_signal == SIGNAL_TYPE_EDP))
dc->hwss.blank_stream(pipe_ctx);
- }
pipe_ctx->stream_res.tg->funcs->set_dsc_config(
pipe_ctx->stream_res.tg,
OPTC_DSC_DISABLED, 0, 0);
+
pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
+
pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
@@ -537,7 +542,6 @@ static void dcn31_reset_back_end_for_pipe(
pipe_ctx->stream_res.tg->funcs->set_drr(
pipe_ctx->stream_res.tg, NULL);
- link = pipe_ctx->stream->link;
/* DPMS may already disable or */
/* dpms_off status is incorrect due to fastboot
* feature. When system resume from S4 with second
@@ -638,3 +642,51 @@ void dcn31_set_static_screen_control(struct pipe_ctx **pipe_ctx,
pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(pipe_ctx[i]->stream_res.tg,
triggers, params->num_frames);
}
+
+static void dmub_abm_set_backlight(struct dc_context *dc,
+ struct set_backlight_level_params *backlight_level_params, uint32_t panel_inst)
+{
+ union dmub_rb_cmd cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.abm_set_backlight.header.type = DMUB_CMD__ABM;
+ cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT;
+ cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = backlight_level_params->frame_ramp;
+ cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_level_params->backlight_pwm_u16_16;
+ cmd.abm_set_backlight.abm_set_backlight_data.backlight_control_type =
+ (enum dmub_backlight_control_type) backlight_level_params->control_type;
+ cmd.abm_set_backlight.abm_set_backlight_data.min_luminance = backlight_level_params->min_luminance;
+ cmd.abm_set_backlight.abm_set_backlight_data.max_luminance = backlight_level_params->max_luminance;
+ cmd.abm_set_backlight.abm_set_backlight_data.min_backlight_pwm = backlight_level_params->min_backlight_pwm;
+ cmd.abm_set_backlight.abm_set_backlight_data.max_backlight_pwm = backlight_level_params->max_backlight_pwm;
+ cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
+ cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst);
+ cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
+
+ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
+
+bool dcn31_set_backlight_level(struct pipe_ctx *pipe_ctx,
+ struct set_backlight_level_params *backlight_level_params)
+{
+ struct dc_context *dc = pipe_ctx->stream->ctx;
+ struct abm *abm = pipe_ctx->stream_res.abm;
+ struct timing_generator *tg = pipe_ctx->stream_res.tg;
+ struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
+ uint32_t otg_inst;
+
+ if (!abm || !tg || !panel_cntl)
+ return false;
+
+ otg_inst = tg->inst;
+
+ dcn21_dmub_abm_set_pipe(abm,
+ otg_inst,
+ SET_ABM_PIPE_NORMAL,
+ panel_cntl->inst,
+ panel_cntl->pwrseq_inst);
+
+ dmub_abm_set_backlight(dc, backlight_level_params, panel_cntl->inst);
+
+ return true;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h
index b8bc939da155..0d09aa8cfb65 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.h
@@ -51,6 +51,8 @@ int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_
void dcn31_reset_hw_ctx_wrap(
struct dc *dc,
struct dc_state *context);
+bool dcn31_set_backlight_level(struct pipe_ctx *pipe_ctx,
+ struct set_backlight_level_params *params);
bool dcn31_is_abm_supported(struct dc *dc,
struct dc_state *context, struct dc_stream_state *stream);
void dcn31_init_pipes(struct dc *dc, struct dc_state *context);
@@ -59,5 +61,4 @@ 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);
-
#endif /* __DC_HWSS_DCN31_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
index 56f3c70d4b55..5f8f45b48720 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
@@ -98,7 +98,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
.set_flip_control_gsl = dcn20_set_flip_control_gsl,
.get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,
.calc_vupdate_position = dcn10_calc_vupdate_position,
- .set_backlight_level = dcn21_set_backlight_level,
+ .set_backlight_level = dcn31_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.set_pipe = dcn21_set_pipe,
.enable_lvds_link_output = dce110_enable_lvds_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
index 68e6de6b5758..6bdfbf22ce87 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
@@ -100,7 +100,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
.set_flip_control_gsl = dcn20_set_flip_control_gsl,
.get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,
.calc_vupdate_position = dcn10_calc_vupdate_position,
- .set_backlight_level = dcn21_set_backlight_level,
+ .set_backlight_level = dcn31_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.set_pipe = dcn21_set_pipe,
.enable_lvds_link_output = dce110_enable_lvds_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
index dbcd2dfb19c1..5ecee7e320da 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
@@ -98,7 +98,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.calc_vupdate_position = dcn10_calc_vupdate_position,
.apply_idle_power_optimizations = dcn32_apply_idle_power_optimizations,
.does_plane_fit_in_mall = NULL,
- .set_backlight_level = dcn21_set_backlight_level,
+ .set_backlight_level = dcn31_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.hardware_release = dcn30_hardware_release,
.set_pipe = dcn21_set_pipe,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index bd309dbdf7b2..e599cdc465bf 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -309,6 +309,7 @@ void dcn35_init_hw(struct dc *dc)
dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+ dc->caps.dmub_caps.aux_backlight_support = dc->ctx->dmub_srv->dmub->feature_caps.abm_aux_backlight_support;
}
if (dc->res_pool->pg_cntl) {
@@ -841,6 +842,7 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context)
uint32_t num_opps = 0;
uint32_t opp_id_src0 = OPP_ID_INVALID;
uint32_t opp_id_src1 = OPP_ID_INVALID;
+ uint32_t optc_dsc_state = 0;
// Step 1: To find out which OPTC is running & OPTC DSC is ON
// We can't use res_pool->res_cap->num_timing_generator to check
@@ -849,7 +851,6 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context)
// Some ASICs would be fused display pipes less than the default setting.
// In dcnxx_resource_construct function, driver would obatin real information.
for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
- uint32_t optc_dsc_state = 0;
struct timing_generator *tg = dc->res_pool->timing_generators[i];
if (tg->funcs->is_tg_enabled(tg)) {
@@ -864,15 +865,18 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context)
}
}
- // Step 2: To power down DSC but skip DSC of running OPTC
+ // Step 2: To power down DSC but skip DSC of running OPTC
for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
struct dcn_dsc_state s = {0};
- dc->res_pool->dscs[i]->funcs->dsc_read_state(dc->res_pool->dscs[i], &s);
+ /* avoid reading DSC state when it is not in use as it may be power gated */
+ if (optc_dsc_state) {
+ dc->res_pool->dscs[i]->funcs->dsc_read_state(dc->res_pool->dscs[i], &s);
- if ((s.dsc_opp_source == opp_id_src0 || s.dsc_opp_source == opp_id_src1) &&
- s.dsc_clock_en && s.dsc_fw_en)
- continue;
+ if ((s.dsc_opp_source == opp_id_src0 || s.dsc_opp_source == opp_id_src1) &&
+ s.dsc_clock_en && s.dsc_fw_en)
+ continue;
+ }
pg_cntl->funcs->dsc_pg_control(pg_cntl, dc->res_pool->dscs[i]->inst, false);
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
index 55dc5799e725..fd67779c27a9 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
@@ -101,7 +101,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
.set_flip_control_gsl = dcn20_set_flip_control_gsl,
.get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,
.calc_vupdate_position = dcn10_calc_vupdate_position,
- .set_backlight_level = dcn21_set_backlight_level,
+ .set_backlight_level = dcn31_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.set_pipe = dcn21_set_pipe,
.enable_lvds_link_output = dce110_enable_lvds_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
index a93864b63d48..3c275a1eff58 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
@@ -100,7 +100,7 @@ static const struct hw_sequencer_funcs dcn351_funcs = {
.set_flip_control_gsl = dcn20_set_flip_control_gsl,
.get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,
.calc_vupdate_position = dcn10_calc_vupdate_position,
- .set_backlight_level = dcn21_set_backlight_level,
+ .set_backlight_level = dcn31_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.set_pipe = dcn21_set_pipe,
.enable_lvds_link_output = dce110_enable_lvds_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 3c70f40bf047..5de11e2837c0 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -1488,6 +1488,10 @@ void dcn401_prepare_bandwidth(struct dc *dc,
&context->bw_ctx.bw.dcn.watermarks,
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
false);
+ /* update timeout thresholds */
+ if (hubbub->funcs->program_arbiter) {
+ dc->wm_optimized_required |= hubbub->funcs->program_arbiter(hubbub, &context->bw_ctx.bw.dcn.arb_regs, false);
+ }
/* decrease compbuf size */
if (hubbub->funcs->program_compbuf_segments) {
@@ -1529,6 +1533,10 @@ void dcn401_optimize_bandwidth(
&context->bw_ctx.bw.dcn.watermarks,
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
true);
+ /* update timeout thresholds */
+ if (hubbub->funcs->program_arbiter) {
+ hubbub->funcs->program_arbiter(hubbub, &context->bw_ctx.bw.dcn.arb_regs, true);
+ }
if (dc->clk_mgr->dc_mode_softmax_enabled)
if (dc->clk_mgr->clks.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
index c73305e57d39..23e4f208152e 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
@@ -77,7 +77,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
.calc_vupdate_position = dcn10_calc_vupdate_position,
.apply_idle_power_optimizations = dcn401_apply_idle_power_optimizations,
.does_plane_fit_in_mall = NULL,
- .set_backlight_level = dcn21_set_backlight_level,
+ .set_backlight_level = dcn31_set_backlight_level,
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.hardware_release = dcn401_hardware_release,
.set_pipe = dcn21_set_pipe,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index 1df17c54f3a9..66fdc5805d0a 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -174,11 +174,6 @@ union block_sequence_params {
struct fams2_global_control_lock_fast_params fams2_global_control_lock_fast_params;
};
-struct set_backlight_level_params {
- uint32_t backlight_pwm_u16_16;
- uint32_t frame_ramp;
-};
-
enum block_sequence_func {
DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST = 0,
OPTC_PIPE_CONTROL_LOCK,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h
index fa5edd03d004..b5afd8c3103d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h
@@ -60,5 +60,7 @@ enum dc_status {
};
char *dc_status_to_str(enum dc_status status);
+char *dc_pixel_encoding_to_str(enum dc_pixel_encoding pixel_encoding);
+char *dc_color_depth_to_str(enum dc_color_depth color_depth);
#endif /* _CORE_STATUS_H_ */
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 67c32401893e..52b745667ef7 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -228,6 +228,7 @@ struct hubbub_funcs {
void (*program_det_segments)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg);
void (*program_compbuf_segments)(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase);
void (*wait_for_det_update)(struct hubbub *hubbub, int hubp_inst);
+ bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
};
struct hubbub {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h
index 72a8479e1f2d..f04292086c08 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link.h
@@ -248,8 +248,7 @@ struct link_service {
uint32_t *backlight_millinits_avg,
uint32_t *backlight_millinits_peak);
bool (*edp_set_backlight_level)(const struct dc_link *link,
- uint32_t backlight_pwm_u16_16,
- uint32_t frame_ramp);
+ struct set_backlight_level_params *backlight_level_params);
bool (*edp_set_backlight_level_nits)(struct dc_link *link,
bool isHDR,
uint32_t backlight_millinits,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index c4e03482ba9a..41cab9ad6885 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -2082,6 +2082,9 @@ static enum dc_status enable_link_dp(struct dc_state *state,
if (link_settings->link_rate == LINK_RATE_LOW)
skip_video_pattern = false;
+ if (stream->sink_patches.oled_optimize_display_on)
+ set_default_brightness_aux(link);
+
if (perform_link_training_with_retries(link_settings,
skip_video_pattern,
lt_attempts,
@@ -2105,10 +2108,14 @@ static enum dc_status enable_link_dp(struct dc_state *state,
if (link->dpcd_sink_ext_caps.bits.oled == 1 ||
link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 ||
link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) {
- set_default_brightness_aux(link);
- if (link->dpcd_sink_ext_caps.bits.oled == 1)
- msleep(bl_oled_enable_delay);
- edp_backlight_enable_aux(link, true);
+ if (!stream->sink_patches.oled_optimize_display_on) {
+ set_default_brightness_aux(link);
+ if (link->dpcd_sink_ext_caps.bits.oled == 1)
+ msleep(bl_oled_enable_delay);
+ edp_backlight_enable_aux(link, true);
+ } else {
+ edp_backlight_enable_aux(link, true);
+ }
}
return status;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index e05b8fddf2af..9dabaf682171 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -51,9 +51,10 @@
#include "dc_dmub_srv.h"
#include "gpio_service_interface.h"
+#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
+
#define DC_LOGGER \
link->ctx->logger
-#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
#ifndef MAX
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
@@ -1416,8 +1417,7 @@ static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
if (!link->ctx->dmub_srv ||
link->ep_type != DISPLAY_ENDPOINT_PHY ||
- link->link_enc->features.flags.bits.DP_IS_USB_C == 0 ||
- link->link_enc->features.flags.bits.IS_DP2_CAPABLE == 0)
+ link->link_enc->features.flags.bits.DP_IS_USB_C == 0)
return false;
memset(&cmd, 0, sizeof(cmd));
@@ -1430,9 +1430,7 @@ static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
cable_id->raw = cmd.cable_id.data.output_raw;
DC_LOG_DC("usbc_cable_id = %d.\n", cable_id->raw);
}
-
- ASSERT(cmd.cable_id.header.ret_status);
- return true;
+ return cmd.cable_id.header.ret_status == 1;
}
static void retrieve_cable_id(struct dc_link *link)
@@ -1635,9 +1633,11 @@ static bool retrieve_link_cap(struct dc_link *link)
}
/* Read DP tunneling information. */
- status = dpcd_get_tunneling_device_data(link);
- if (status != DC_OK)
- dm_error("%s: Read tunneling device data failed.\n", __func__);
+ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
+ status = dpcd_get_tunneling_device_data(link);
+ if (status != DC_OK)
+ dm_error("%s: Read tunneling device data failed.\n", __func__);
+ }
dpcd_set_source_specific_data(link);
/* Sink may need to configure internals based on vendor, so allow some
@@ -2129,8 +2129,6 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
/* get max link encoder capability */
if (link_enc)
link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap);
- else
- return max_link_cap;
/* Lower link settings based on sink's link cap */
if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
@@ -2164,15 +2162,10 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
*/
cable_max_link_rate = get_cable_max_link_rate(link);
- if (!link->dc->debug.ignore_cable_id) {
- if (cable_max_link_rate != LINK_RATE_UNKNOWN)
- // cable max link rate known
- max_link_cap.link_rate = MIN(max_link_cap.link_rate, cable_max_link_rate);
- else if (link_enc->funcs->is_in_alt_mode && link_enc->funcs->is_in_alt_mode(link_enc))
- // cable max link rate ambiguous, DP alt mode, limit to HBR3
- max_link_cap.link_rate = MIN(max_link_cap.link_rate, LINK_RATE_HIGH3);
- //else {}
- // cable max link rate ambiguous, DP, do nothing
+ if (!link->dc->debug.ignore_cable_id &&
+ cable_max_link_rate != LINK_RATE_UNKNOWN) {
+ if (cable_max_link_rate < max_link_cap.link_rate)
+ max_link_cap.link_rate = cable_max_link_rate;
if (!link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY &&
link->dpcd_caps.cable_id.bits.CABLE_TYPE >= 2)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index 96bf135b6f05..48abeaa88678 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -221,21 +221,11 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
&replay_error_status.raw,
sizeof(replay_error_status.raw));
- link->replay_settings.config.replay_error_status.bits.LINK_CRC_ERROR =
- replay_error_status.bits.LINK_CRC_ERROR;
- link->replay_settings.config.replay_error_status.bits.DESYNC_ERROR =
- replay_configuration.bits.DESYNC_ERROR_STATUS;
- link->replay_settings.config.replay_error_status.bits.STATE_TRANSITION_ERROR =
- replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS;
-
- if (link->replay_settings.config.replay_error_status.bits.LINK_CRC_ERROR ||
- link->replay_settings.config.replay_error_status.bits.DESYNC_ERROR ||
- link->replay_settings.config.replay_error_status.bits.STATE_TRANSITION_ERROR) {
+ if (replay_error_status.bits.LINK_CRC_ERROR ||
+ replay_configuration.bits.DESYNC_ERROR_STATUS ||
+ replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS) {
bool allow_active;
- if (link->replay_settings.config.replay_error_status.bits.DESYNC_ERROR)
- link->replay_settings.config.received_desync_error_hpd = 1;
-
if (link->replay_settings.config.force_disable_desync_error_check)
return;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index 43a467f6ce7b..e0e3bb865359 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -161,7 +161,9 @@ bool edp_set_backlight_level_nits(struct dc_link *link,
link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
return false;
- if (link->backlight_control_type == BACKLIGHT_CONTROL_VESA_AUX) {
+ // use internal backlight control if dmub capabilities are not present
+ if (link->backlight_control_type == BACKLIGHT_CONTROL_VESA_AUX &&
+ !link->dc->caps.dmub_caps.aux_backlight_support) {
uint8_t backlight_enable = 0;
struct target_luminance_value *target_luminance = NULL;
@@ -185,7 +187,7 @@ bool edp_set_backlight_level_nits(struct dc_link *link,
(uint8_t *)(target_luminance),
sizeof(struct target_luminance_value)) != DC_OK)
return false;
- } else {
+ } else if (link->backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX) {
struct dpcd_source_backlight_set dpcd_backlight_set;
*(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
*(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
@@ -517,17 +519,17 @@ static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link)
}
bool edp_set_backlight_level(const struct dc_link *link,
- uint32_t backlight_pwm_u16_16,
- uint32_t frame_ramp)
+ struct set_backlight_level_params *backlight_level_params)
{
struct dc *dc = link->ctx->dc;
+ uint32_t backlight_pwm_u16_16 = backlight_level_params->backlight_pwm_u16_16;
+ uint32_t frame_ramp = backlight_level_params->frame_ramp;
DC_LOGGER_INIT(link->ctx->logger);
DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
backlight_pwm_u16_16, backlight_pwm_u16_16);
if (dc_is_embedded_signal(link->connector_signal)) {
struct pipe_ctx *pipe_ctx = get_pipe_from_link(link);
- struct set_backlight_level_params backlight_level_param = { 0 };
if (link->panel_cntl)
link->panel_cntl->stored_backlight_registers.USER_LEVEL = backlight_pwm_u16_16;
@@ -542,12 +544,11 @@ bool edp_set_backlight_level(const struct dc_link *link,
return false;
}
- backlight_level_param.backlight_pwm_u16_16 = backlight_pwm_u16_16;
- backlight_level_param.frame_ramp = frame_ramp;
+ backlight_level_params->frame_ramp = frame_ramp;
dc->hwss.set_backlight_level(
pipe_ctx,
- &backlight_level_param);
+ backlight_level_params);
}
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
index 30dc8c24c008..bcfa6ac5d4e7 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
@@ -36,8 +36,7 @@ bool edp_get_backlight_level_nits(struct dc_link *link,
uint32_t *backlight_millinits_avg,
uint32_t *backlight_millinits_peak);
bool edp_set_backlight_level(const struct dc_link *link,
- uint32_t backlight_pwm_u16_16,
- uint32_t frame_ramp);
+ struct set_backlight_level_params *backlight_level_params);
bool edp_set_backlight_level_nits(struct dc_link *link,
bool isHDR,
uint32_t backlight_millinits,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
index 05d6d41ef9d3..770a380cc03d 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
@@ -533,7 +533,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.sanity_checks = true,
.disable_dmcu = false,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
/* raven smu dones't allow 0 disp clk,
@@ -560,18 +559,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.using_dml2 = false,
};
-static const struct dc_debug_options debug_defaults_diags = {
- .disable_dmcu = false,
- .force_abm_enable = false,
- .timing_trace = true,
- .clock_trace = true,
- .disable_stutter = true,
- .disable_pplib_clock_request = true,
- .disable_pplib_wm_range = true,
- .underflow_assert_delay_us = 0xFFFFFFFF,
- .enable_legacy_fast_update = true,
-};
-
static void dcn10_dpp_destroy(struct dpp **dpp)
{
kfree(TO_DCN10_DPP(*dpp));
@@ -1400,8 +1387,6 @@ static bool dcn10_resource_construct(
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
- else
- dc->debug = debug_defaults_diags;
/*************************************************
* Create resources *
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
index 288189913e1e..189d0c85872e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
@@ -706,7 +706,6 @@ static const struct resource_caps res_cap_nv14 = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = false,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
.pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
index 15180ad71513..d3d67d366523 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
@@ -600,7 +600,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
index 14b28841657d..021ba8ac5c8c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
@@ -610,7 +610,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = false,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
.min_disp_clk_khz = 100000,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
index baa4e2647dad..cd31e4f16c14 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
@@ -711,7 +711,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true, //No DMCU on DCN30
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
index d8a7c2cf05de..a9816affd312 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
@@ -682,7 +682,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_dpp_power_gate = false,
.disable_hubp_power_gate = false,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
index 40c20b04635a..02af8b8f4d27 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
@@ -81,7 +81,6 @@
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
index daf1b65fd088..7002a8dd358a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
@@ -82,7 +82,6 @@
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = true,
.pipe_split_policy = MPC_SPLIT_AVOID,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
index 36bb26182e11..c16cf1c8f7f9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
@@ -858,7 +858,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
@@ -869,7 +868,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.max_downscale_src_width = 4096,/*upto true 4K*/
.disable_pplib_wm_range = false,
.scl_reset_length10 = true,
- .sanity_checks = true,
+ .sanity_checks = false,
.underflow_assert_delay_us = 0xFFFFFFFF,
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
index 58a5fbcf22bf..c0f48c78e968 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
@@ -876,7 +876,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.replay_skip_crtc_disabled = true,
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_dpp_power_gate = false,
.disable_hubp_power_gate = false,
@@ -889,7 +888,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.max_downscale_src_width = 4096,/*upto true 4k*/
.disable_pplib_wm_range = false,
.scl_reset_length10 = true,
- .sanity_checks = true,
+ .sanity_checks = false,
.underflow_assert_delay_us = 0xFFFFFFFF,
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index 3acad708c31b..6c3295259a81 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -858,7 +858,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.disable_z10 = true, /*hw not support it*/
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
index ce56f5d162c0..6edaaadcb173 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
@@ -853,7 +853,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.disable_z10 = true, /*hw not support it*/
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index aaaa888d112d..01d1a11d5545 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -689,7 +689,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_AVOID, // Due to CRB, no need to MPC split anymore
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
index 35acc13cb5a9..5cb74fd9cb7d 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
@@ -686,7 +686,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_AVOID,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index 795f2c71c70f..6cc2960b6104 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -712,7 +712,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_AVOID,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index 0b8dc2eff596..d87e2641cda1 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -692,7 +692,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_AVOID,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index 306b4117e219..db93bac247c0 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -685,7 +685,6 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_dmcu = true,
.force_abm_enable = false,
- .timing_trace = false,
.clock_trace = true,
.disable_pplib_clock_request = false,
.pipe_split_policy = MPC_SPLIT_AVOID,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index bdafa7496cea..19568c359669 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -610,7 +610,10 @@ void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
SR(DCHUBBUB_CLOCK_CNTL), \
SR(DCHUBBUB_SDPIF_CFG0), \
SR(DCHUBBUB_SDPIF_CFG1), \
- SR(DCHUBBUB_MEM_PWR_MODE_CTRL)
+ SR(DCHUBBUB_MEM_PWR_MODE_CTRL), \
+ SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL1), \
+ SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL2), \
+ SR(DCHUBBUB_CTRL_STATUS)
/* DCCG */
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
index f043c7e32e16..73a65913cb12 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
@@ -99,7 +99,7 @@ static struct spl_rect calculate_plane_rec_in_timing_active(
*
* recout_x = 128 + round(plane_x * 2304 / 1920)
* recout_w = 128 + round((plane_x + plane_w) * 2304 / 1920) - recout_x
- * recout_y = 0 + round(plane_y * 1440 / 1280)
+ * recout_y = 0 + round(plane_y * 1440 / 1200)
* recout_h = 0 + round((plane_y + plane_h) * 1440 / 1200) - recout_y
*
* NOTE: fixed point division is not error free. To reduce errors
@@ -739,14 +739,13 @@ static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in,
return SCL_MODE_SCALING_444_RGB_ENABLE;
}
- /* Bypass YUV if at 1:1 with no ISHARP or if doing 2:1 YUV
- * downscale without EASF
+ /*
+ * Bypass YUV if Y is 1:1 with no ISHARP
+ * Do not bypass UV at 1:1 for cositing to be applied
*/
- if ((!enable_isharp) && (!enable_easf)) {
+ if (!enable_isharp) {
if (data->ratios.horz.value == one && data->ratios.vert.value == one)
return SCL_MODE_SCALING_420_LUMA_BYPASS;
- if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
- return SCL_MODE_SCALING_420_CHROMA_BYPASS;
}
return SCL_MODE_SCALING_420_YCBCR_ENABLE;
@@ -868,6 +867,60 @@ static bool spl_get_isharp_en(struct spl_in *spl_in,
return enable_isharp;
}
+/* Calculate number of tap with adaptive scaling off */
+static void spl_get_taps_non_adaptive_scaler(
+ struct spl_scratch *spl_scratch, const struct spl_taps *in_taps)
+{
+ if (in_taps->h_taps == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz) > 1)
+ spl_scratch->scl_data.taps.h_taps = spl_min(2 * spl_fixpt_ceil(
+ spl_scratch->scl_data.ratios.horz), 8);
+ else
+ spl_scratch->scl_data.taps.h_taps = 4;
+ } else
+ spl_scratch->scl_data.taps.h_taps = in_taps->h_taps;
+
+ if (in_taps->v_taps == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) > 1)
+ spl_scratch->scl_data.taps.v_taps = spl_min(spl_fixpt_ceil(spl_fixpt_mul_int(
+ spl_scratch->scl_data.ratios.vert, 2)), 8);
+ else
+ spl_scratch->scl_data.taps.v_taps = 4;
+ } else
+ spl_scratch->scl_data.taps.v_taps = in_taps->v_taps;
+
+ if (in_taps->v_taps_c == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) > 1)
+ spl_scratch->scl_data.taps.v_taps_c = spl_min(spl_fixpt_ceil(spl_fixpt_mul_int(
+ spl_scratch->scl_data.ratios.vert_c, 2)), 8);
+ else
+ spl_scratch->scl_data.taps.v_taps_c = 4;
+ } else
+ spl_scratch->scl_data.taps.v_taps_c = in_taps->v_taps_c;
+
+ if (in_taps->h_taps_c == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz_c) > 1)
+ spl_scratch->scl_data.taps.h_taps_c = spl_min(2 * spl_fixpt_ceil(
+ spl_scratch->scl_data.ratios.horz_c), 8);
+ else
+ spl_scratch->scl_data.taps.h_taps_c = 4;
+ } else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1)
+ /* Only 1 and even h_taps_c are supported by hw */
+ spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c - 1;
+ else
+ spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c;
+
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz))
+ spl_scratch->scl_data.taps.h_taps = 1;
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert))
+ spl_scratch->scl_data.taps.v_taps = 1;
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c))
+ spl_scratch->scl_data.taps.h_taps_c = 1;
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c))
+ spl_scratch->scl_data.taps.v_taps_c = 1;
+
+}
+
/* Calculate optimal number of taps */
static bool spl_get_optimal_number_of_taps(
int max_downscale_src_width, struct spl_in *spl_in, struct spl_scratch *spl_scratch,
@@ -879,18 +932,21 @@ static bool spl_get_optimal_number_of_taps(
int min_taps_y, min_taps_c;
enum lb_memory_config lb_config;
bool skip_easf = false;
+ bool is_ycbcr = spl_dscl_is_video_format(spl_in->basic_in.format);
if (spl_scratch->scl_data.viewport.width > spl_scratch->scl_data.h_active &&
max_downscale_src_width != 0 &&
- spl_scratch->scl_data.viewport.width > max_downscale_src_width)
+ spl_scratch->scl_data.viewport.width > max_downscale_src_width) {
+ spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps);
+ *enable_easf_v = false;
+ *enable_easf_h = false;
+ *enable_isharp = false;
return false;
+ }
/* Disable adaptive scaler and sharpener when integer scaling is enabled */
if (spl_in->scaling_quality.integer_scaling) {
- spl_scratch->scl_data.taps.h_taps = 1;
- spl_scratch->scl_data.taps.v_taps = 1;
- spl_scratch->scl_data.taps.v_taps_c = 1;
- spl_scratch->scl_data.taps.h_taps_c = 1;
+ spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps);
*enable_easf_v = false;
*enable_easf_h = false;
*enable_isharp = false;
@@ -905,43 +961,9 @@ static bool spl_get_optimal_number_of_taps(
* From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling
* taps = 4 for upscaling
*/
- if (skip_easf) {
- if (in_taps->h_taps == 0) {
- if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz) > 1)
- spl_scratch->scl_data.taps.h_taps = spl_min(2 * spl_fixpt_ceil(
- spl_scratch->scl_data.ratios.horz), 8);
- else
- spl_scratch->scl_data.taps.h_taps = 4;
- } else
- spl_scratch->scl_data.taps.h_taps = in_taps->h_taps;
- if (in_taps->v_taps == 0) {
- if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) > 1)
- spl_scratch->scl_data.taps.v_taps = spl_min(spl_fixpt_ceil(spl_fixpt_mul_int(
- spl_scratch->scl_data.ratios.vert, 2)), 8);
- else
- spl_scratch->scl_data.taps.v_taps = 4;
- } else
- spl_scratch->scl_data.taps.v_taps = in_taps->v_taps;
- if (in_taps->v_taps_c == 0) {
- if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) > 1)
- spl_scratch->scl_data.taps.v_taps_c = spl_min(spl_fixpt_ceil(spl_fixpt_mul_int(
- spl_scratch->scl_data.ratios.vert_c, 2)), 8);
- else
- spl_scratch->scl_data.taps.v_taps_c = 4;
- } else
- spl_scratch->scl_data.taps.v_taps_c = in_taps->v_taps_c;
- if (in_taps->h_taps_c == 0) {
- if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz_c) > 1)
- spl_scratch->scl_data.taps.h_taps_c = spl_min(2 * spl_fixpt_ceil(
- spl_scratch->scl_data.ratios.horz_c), 8);
- else
- spl_scratch->scl_data.taps.h_taps_c = 4;
- } else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1)
- /* Only 1 and even h_taps_c are supported by hw */
- spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c - 1;
- else
- spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c;
- } else {
+ if (skip_easf)
+ spl_get_taps_non_adaptive_scaler(spl_scratch, in_taps);
+ else {
if (spl_is_yuv420(spl_in->basic_in.format)) {
spl_scratch->scl_data.taps.h_taps = 6;
spl_scratch->scl_data.taps.v_taps = 6;
@@ -966,7 +988,7 @@ static bool spl_get_optimal_number_of_taps(
else
lb_config = LB_MEMORY_CONFIG_0;
// Determine max vtap support by calculating how much line buffer can fit
- spl_in->funcs->spl_calc_lb_num_partitions(spl_in->basic_out.alpha_en, &spl_scratch->scl_data,
+ spl_in->callbacks.spl_calc_lb_num_partitions(spl_in->basic_out.alpha_en, &spl_scratch->scl_data,
lb_config, &num_part_y, &num_part_c);
/* MAX_V_TAPS = MIN (NUM_LINES - MAX(CEILING(V_RATIO,1)-2, 0), 8) */
if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) > 2)
@@ -1052,10 +1074,9 @@ static bool spl_get_optimal_number_of_taps(
/* Sharpener requires scaler to be enabled, including for 1:1
* Check if ISHARP can be enabled
- * If ISHARP is not enabled, for 1:1, set taps to 1 and disable
- * EASF
- * For case of 2:1 YUV where chroma is 1:1, set taps to 1 if
- * EASF is not enabled
+ * If ISHARP is not enabled, set taps to 1 if ratio is 1:1
+ * except for chroma taps. Keep previous taps so it can
+ * handle cositing
*/
*enable_isharp = spl_get_isharp_en(spl_in, spl_scratch);
@@ -1065,20 +1086,28 @@ static bool spl_get_optimal_number_of_taps(
spl_scratch->scl_data.taps.h_taps = 1;
spl_scratch->scl_data.taps.v_taps = 1;
- if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c))
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c) && !is_ycbcr)
spl_scratch->scl_data.taps.h_taps_c = 1;
- if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c))
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c) && !is_ycbcr)
spl_scratch->scl_data.taps.v_taps_c = 1;
*enable_easf_v = false;
*enable_easf_h = false;
} else {
if ((!*enable_easf_h) &&
+ (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz)))
+ spl_scratch->scl_data.taps.h_taps = 1;
+
+ if ((!*enable_easf_v) &&
+ (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert)))
+ spl_scratch->scl_data.taps.v_taps = 1;
+
+ if ((!*enable_easf_h) && !is_ycbcr &&
(IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c)))
spl_scratch->scl_data.taps.h_taps_c = 1;
- if ((!*enable_easf_v) &&
+ if ((!*enable_easf_v) && !is_ycbcr &&
(IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c)))
spl_scratch->scl_data.taps.v_taps_c = 1;
}
@@ -1089,8 +1118,7 @@ static bool spl_get_optimal_number_of_taps(
static void spl_set_black_color_data(enum spl_pixel_format format,
struct scl_black_color *scl_black_color)
{
- bool ycbcr = format >= SPL_PIXEL_FORMAT_VIDEO_BEGIN
- && format <= SPL_PIXEL_FORMAT_VIDEO_END;
+ bool ycbcr = spl_dscl_is_video_format(format);
if (ycbcr) {
scl_black_color->offset_rgb_y = BLACK_OFFSET_RGB_Y;
scl_black_color->offset_rgb_cbcr = BLACK_OFFSET_CBCR;
@@ -1602,7 +1630,8 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data,
spl_build_isharp_1dlut_from_reference_curve(ratio, setup, adp_sharpness,
scale_to_sharpness_policy);
- dscl_prog_data->isharp_delta = spl_get_pregen_filter_isharp_1D_lut(setup);
+ memcpy(dscl_prog_data->isharp_delta, spl_get_pregen_filter_isharp_1D_lut(setup),
+ sizeof(uint32_t) * ISHARP_LUT_TABLE_SIZE);
dscl_prog_data->sharpness_level = adp_sharpness.sharpness_level;
dscl_prog_data->isharp_en = 1; // ISHARP_EN
@@ -1723,6 +1752,32 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data,
spl_set_blur_scale_data(dscl_prog_data, data);
}
+/* Calculate recout, scaling ratio, and viewport, then get optimal number of taps */
+static bool spl_calculate_number_of_taps(struct spl_in *spl_in, struct spl_scratch *spl_scratch, struct spl_out *spl_out,
+ bool *enable_easf_v, bool *enable_easf_h, bool *enable_isharp)
+{
+ bool res = false;
+
+ memset(spl_scratch, 0, sizeof(struct spl_scratch));
+ spl_scratch->scl_data.h_active = spl_in->h_active;
+ spl_scratch->scl_data.v_active = spl_in->v_active;
+
+ // All SPL calls
+ /* recout calculation */
+ /* depends on h_active */
+ spl_calculate_recout(spl_in, spl_scratch, spl_out);
+ /* depends on pixel format */
+ spl_calculate_scaling_ratios(spl_in, spl_scratch, spl_out);
+ /* depends on scaling ratios and recout, does not calculate offset yet */
+ spl_calculate_viewport_size(spl_in, spl_scratch);
+
+ res = spl_get_optimal_number_of_taps(
+ spl_in->basic_out.max_downscale_src_width, spl_in,
+ spl_scratch, &spl_in->scaling_quality, enable_easf_v,
+ enable_easf_h, enable_isharp);
+ return res;
+}
+
/* Calculate scaler parameters */
bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
{
@@ -1737,23 +1792,9 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
bool enable_isharp = false;
const struct spl_scaler_data *data = &spl_scratch.scl_data;
- memset(&spl_scratch, 0, sizeof(struct spl_scratch));
- spl_scratch.scl_data.h_active = spl_in->h_active;
- spl_scratch.scl_data.v_active = spl_in->v_active;
-
- // All SPL calls
- /* recout calculation */
- /* depends on h_active */
- spl_calculate_recout(spl_in, &spl_scratch, spl_out);
- /* depends on pixel format */
- spl_calculate_scaling_ratios(spl_in, &spl_scratch, spl_out);
- /* depends on scaling ratios and recout, does not calculate offset yet */
- spl_calculate_viewport_size(spl_in, &spl_scratch);
+ res = spl_calculate_number_of_taps(spl_in, &spl_scratch, spl_out,
+ &enable_easf_v, &enable_easf_h, &enable_isharp);
- res = spl_get_optimal_number_of_taps(
- spl_in->basic_out.max_downscale_src_width, spl_in,
- &spl_scratch, &spl_in->scaling_quality, &enable_easf_v,
- &enable_easf_h, &enable_isharp);
/*
* Depends on recout, scaling ratios, h_active and taps
* May need to re-check lb size after this in some obscure scenario
@@ -1765,12 +1806,12 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
// Clamp
spl_clamp_viewport(&spl_scratch.scl_data.viewport);
- if (!res)
- return res;
-
// Save all calculated parameters in dscl_prog_data structure to program hw registers
spl_set_dscl_prog_data(spl_in, &spl_scratch, spl_out, enable_easf_v, enable_easf_h, enable_isharp);
+ if (!res)
+ return res;
+
if (spl_in->lls_pref == LLS_PREF_YES) {
if (spl_in->is_hdr_on)
setup = HDR_L;
@@ -1801,3 +1842,20 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
return res;
}
+
+/* External interface to get number of taps only */
+bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out)
+{
+ bool res = false;
+ bool enable_easf_v = false;
+ bool enable_easf_h = false;
+ bool enable_isharp = false;
+ struct spl_scratch spl_scratch;
+ struct dscl_prog_data *dscl_prog_data = spl_out->dscl_prog_data;
+ const struct spl_scaler_data *data = &spl_scratch.scl_data;
+
+ res = spl_calculate_number_of_taps(spl_in, &spl_scratch, spl_out,
+ &enable_easf_v, &enable_easf_h, &enable_isharp);
+ spl_set_taps_data(dscl_prog_data, data);
+ return res;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
index 205e59a2a8ee..02a2d6725ed5 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
@@ -13,4 +13,6 @@
bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out);
+bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out);
+
#endif /* __DC_SPL_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h
index afcc66206ca2..89af91e19b6c 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h
@@ -7,7 +7,6 @@
#include "dc_spl_types.h"
-#define ISHARP_LUT_TABLE_SIZE 32
const uint32_t *spl_get_filter_isharp_1D_lut_0(void);
const uint32_t *spl_get_filter_isharp_1D_lut_0p5x(void);
const uint32_t *spl_get_filter_isharp_1D_lut_1p0x(void);
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
index fcb5d389592b..55d557df4aa5 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h
@@ -250,6 +250,7 @@ enum isharp_en {
ISHARP_DISABLE,
ISHARP_ENABLE
};
+#define ISHARP_LUT_TABLE_SIZE 32
// Below struct holds values that can be directly used to program
// hardware registers. No conversion/clamping is required
struct dscl_prog_data {
@@ -400,7 +401,7 @@ struct dscl_prog_data {
uint32_t isharp_nl_en; // ISHARP_NL_EN ? TODO:check this
struct isharp_lba isharp_lba; // ISHARP_LBA
struct isharp_fmt isharp_fmt; // ISHARP_FMT
- const uint32_t *isharp_delta;
+ uint32_t isharp_delta[ISHARP_LUT_TABLE_SIZE];
struct isharp_nldelta_sclip isharp_nldelta_sclip; // ISHARP_NLDELTA_SCLIP
/* blur and scale filter */
const uint16_t *filter_blur_scale_v;
@@ -496,7 +497,7 @@ enum scale_to_sharpness_policy {
SCALE_TO_SHARPNESS_ADJ_YUV = 1,
SCALE_TO_SHARPNESS_ADJ_ALL = 2
};
-struct spl_funcs {
+struct spl_callbacks {
void (*spl_calc_lb_num_partitions)
(bool alpha_en,
const struct spl_scaler_data *scl_data,
@@ -517,7 +518,7 @@ struct spl_in {
// Basic slice information
int odm_slice_index; // ODM Slice Index using get_odm_split_index
struct spl_taps scaling_quality; // Explicit Scaling Quality
- struct spl_funcs *funcs;
+ struct spl_callbacks callbacks;
// Inputs for isharp and EASF
struct adaptive_sharpness adaptive_sharpness; // Adaptive Sharpness
enum linear_light_scaling lls_pref; // Linear Light Scaling
diff --git a/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c
index 5fd79d9c67e2..131f1e3949d3 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c
@@ -22,7 +22,7 @@ static inline unsigned long long abs_i64(
* result = dividend / divisor
* *remainder = dividend % divisor
*/
-static inline unsigned long long complete_integer_division_u64(
+static inline unsigned long long spl_complete_integer_division_u64(
unsigned long long dividend,
unsigned long long divisor,
unsigned long long *remainder)
@@ -60,7 +60,7 @@ struct spl_fixed31_32 spl_fixpt_from_fraction(long long numerator, long long den
/* determine integer part */
- unsigned long long res_value = complete_integer_division_u64(
+ unsigned long long res_value = spl_complete_integer_division_u64(
arg1_value, arg2_value, &remainder);
SPL_ASSERT(res_value <= (unsigned long long)LONG_MAX);
@@ -286,7 +286,7 @@ struct spl_fixed31_32 spl_fixpt_cos(struct spl_fixed31_32 arg)
*
* Calculated as Taylor series.
*/
-static struct spl_fixed31_32 fixed31_32_exp_from_taylor_series(struct spl_fixed31_32 arg)
+static struct spl_fixed31_32 spl_fixed31_32_exp_from_taylor_series(struct spl_fixed31_32 arg)
{
unsigned int n = 9;
@@ -345,14 +345,14 @@ struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg)
if (m > 0)
return spl_fixpt_shl(
- fixed31_32_exp_from_taylor_series(r),
+ spl_fixed31_32_exp_from_taylor_series(r),
(unsigned char)m);
else
return spl_fixpt_div_int(
- fixed31_32_exp_from_taylor_series(r),
+ spl_fixed31_32_exp_from_taylor_series(r),
1LL << -m);
} else if (arg.value != 0)
- return fixed31_32_exp_from_taylor_series(arg);
+ return spl_fixed31_32_exp_from_taylor_series(arg);
else
return spl_fixpt_one;
}
@@ -396,7 +396,7 @@ struct spl_fixed31_32 spl_fixpt_log(struct spl_fixed31_32 arg)
* part in 32 bits. It is used in hw programming (scaler)
*/
-static inline unsigned int ux_dy(
+static inline unsigned int spl_ux_dy(
long long value,
unsigned int integer_bits,
unsigned int fractional_bits)
@@ -415,13 +415,13 @@ static inline unsigned int ux_dy(
return result | fractional_part;
}
-static inline unsigned int clamp_ux_dy(
+static inline unsigned int spl_clamp_ux_dy(
long long value,
unsigned int integer_bits,
unsigned int fractional_bits,
unsigned int min_clamp)
{
- unsigned int truncated_val = ux_dy(value, integer_bits, fractional_bits);
+ unsigned int truncated_val = spl_ux_dy(value, integer_bits, fractional_bits);
if (value >= (1LL << (integer_bits + FIXED31_32_BITS_PER_FRACTIONAL_PART)))
return (1 << (integer_bits + fractional_bits)) - 1;
@@ -433,40 +433,40 @@ static inline unsigned int clamp_ux_dy(
unsigned int spl_fixpt_u4d19(struct spl_fixed31_32 arg)
{
- return ux_dy(arg.value, 4, 19);
+ return spl_ux_dy(arg.value, 4, 19);
}
unsigned int spl_fixpt_u3d19(struct spl_fixed31_32 arg)
{
- return ux_dy(arg.value, 3, 19);
+ return spl_ux_dy(arg.value, 3, 19);
}
unsigned int spl_fixpt_u2d19(struct spl_fixed31_32 arg)
{
- return ux_dy(arg.value, 2, 19);
+ return spl_ux_dy(arg.value, 2, 19);
}
unsigned int spl_fixpt_u0d19(struct spl_fixed31_32 arg)
{
- return ux_dy(arg.value, 0, 19);
+ return spl_ux_dy(arg.value, 0, 19);
}
unsigned int spl_fixpt_clamp_u0d14(struct spl_fixed31_32 arg)
{
- return clamp_ux_dy(arg.value, 0, 14, 1);
+ return spl_clamp_ux_dy(arg.value, 0, 14, 1);
}
unsigned int spl_fixpt_clamp_u0d10(struct spl_fixed31_32 arg)
{
- return clamp_ux_dy(arg.value, 0, 10, 1);
+ return spl_clamp_ux_dy(arg.value, 0, 10, 1);
}
int spl_fixpt_s4d19(struct spl_fixed31_32 arg)
{
if (arg.value < 0)
- return -(int)ux_dy(spl_fixpt_abs(arg).value, 4, 19);
+ return -(int)spl_ux_dy(spl_fixpt_abs(arg).value, 4, 19);
else
- return ux_dy(arg.value, 4, 19);
+ return spl_ux_dy(arg.value, 4, 19);
}
struct spl_fixed31_32 spl_fixpt_from_ux_dy(unsigned int value,
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index ff27229cc3a4..b353c4ceb60d 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -301,6 +301,7 @@ struct dmub_srv_hw_params {
bool disallow_phy_access;
bool disable_sldo_opt;
bool enable_non_transparent_setconfig;
+ bool lower_hbr3_phy_ssc;
};
/**
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 6edd3d34c7b5..b800a507d1e0 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -495,6 +495,7 @@ struct dmub_feature_caps {
uint8_t gecc_enable;
uint8_t replay_supported;
uint8_t replay_reserved[3];
+ uint8_t abm_aux_backlight_support;
};
struct dmub_visual_confirm_color {
@@ -694,7 +695,8 @@ union dmub_fw_boot_options {
uint32_t ips_disable: 3; /* options to disable ips support*/
uint32_t ips_sequential_ono: 1; /**< 1 to enable sequential ONO IPS sequence */
uint32_t disable_sldo_opt: 1; /**< 1 to disable SLDO optimizations */
- uint32_t reserved : 7; /**< reserved */
+ uint32_t lower_hbr3_phy_ssc: 1; /**< 1 to lower hbr3 phy ssc to 0.125 percent */
+ uint32_t reserved : 6; /**< reserved */
} bits; /**< boot bits */
uint32_t all; /**< 32-bit access to bits */
};
@@ -726,6 +728,7 @@ enum dmub_shared_state_feature_id {
DMUB_SHARED_SHARE_FEATURE__INVALID = 0,
DMUB_SHARED_SHARE_FEATURE__IPS_FW = 1,
DMUB_SHARED_SHARE_FEATURE__IPS_DRIVER = 2,
+ DMUB_SHARED_SHARE_FEATURE__DEBUG_SETUP = 3,
DMUB_SHARED_STATE_FEATURE__LAST, /* Total number of features. */
};
@@ -752,7 +755,7 @@ union dmub_shared_state_ips_driver_signals {
uint32_t allow_ips1 : 1; /**< 1 is IPS1 is allowed */
uint32_t allow_ips2 : 1; /**< 1 is IPS1 is allowed */
uint32_t allow_z10 : 1; /**< 1 if Z10 is allowed */
- uint32_t allow_idle : 1; /**< 1 if driver is allowing idle */
+ uint32_t allow_idle: 1; /**< 1 if driver is allowing idle */
uint32_t reserved_bits : 27; /**< Reversed bits */
} bits;
uint32_t all;
@@ -763,6 +766,14 @@ union dmub_shared_state_ips_driver_signals {
*/
#define DMUB_SHARED_STATE__IPS_FW_VERSION 1
+struct dmub_shared_state_debug_setup {
+ union {
+ struct {
+ uint32_t exclude_points[62];
+ } profile_mode;
+ };
+};
+
/**
* struct dmub_shared_state_ips_fw - Firmware state for IPS.
*/
@@ -815,6 +826,7 @@ struct dmub_shared_state_feature_block {
struct dmub_shared_state_feature_common common; /**< Generic data */
struct dmub_shared_state_ips_fw ips_fw; /**< IPS firmware state */
struct dmub_shared_state_ips_driver ips_driver; /**< IPS driver state */
+ struct dmub_shared_state_debug_setup debug_setup; /**< Debug setup */
} data; /**< Shared state data. */
}; /* 256-bytes, fixed */
@@ -1157,6 +1169,10 @@ enum dmub_gpint_command {
* RETURN: Total residency in microseconds - upper 32 bits
*/
DMUB_GPINT__GET_IPS_RESIDENCY_DURATION_US_HI = 133,
+ /**
+ * DESC: Setup debug configs.
+ */
+ DMUB_GPINT__SETUP_DEBUG_MODE = 136,
};
/**
@@ -4411,6 +4427,24 @@ struct dmub_rb_cmd_abm_set_pipe {
};
/**
+ * Type of backlight control method to be used by ABM module
+ */
+enum dmub_backlight_control_type {
+ /**
+ * PWM Backlight control
+ */
+ DMU_BACKLIGHT_CONTROL_PWM = 0,
+ /**
+ * VESA Aux-based backlight control
+ */
+ DMU_BACKLIGHT_CONTROL_VESA_AUX = 1,
+ /**
+ * AMD DPCD Aux-based backlight control
+ */
+ DMU_BACKLIGHT_CONTROL_AMD_AUX = 2,
+};
+
+/**
* Data passed from driver to FW in a DMUB_CMD__ABM_SET_BACKLIGHT command.
*/
struct dmub_cmd_abm_set_backlight_data {
@@ -4437,12 +4471,9 @@ struct dmub_cmd_abm_set_backlight_data {
uint8_t panel_mask;
/**
- * Backlight control type.
- * Value 0 is PWM backlight control.
- * Value 1 is VAUX backlight control.
- * Value 2 is AMD DPCD AUX backlight control.
+ * AUX HW Instance.
*/
- uint8_t backlight_control_type;
+ uint8_t aux_inst;
/**
* Explicit padding to 4 byte boundary.
@@ -4450,6 +4481,14 @@ struct dmub_cmd_abm_set_backlight_data {
uint8_t pad[1];
/**
+ * Backlight control type.
+ * Value 0 is PWM backlight control.
+ * Value 1 is VAUX backlight control.
+ * Value 2 is AMD DPCD AUX backlight control.
+ */
+ enum dmub_backlight_control_type backlight_control_type;
+
+ /**
* Minimum luminance in nits.
*/
uint32_t min_luminance;
@@ -5171,7 +5210,34 @@ struct dmub_rb_cmd_get_usbc_cable_id {
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
+ DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY,
+ DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_STOP_UPDATE,
+ DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_WIN_NOTIFY
+};
+
+#define MAX_ROI_NUM 2
+
+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;
+};
+
+struct dmub_cmd_roi_window_ctl {
+ uint16_t x_start;
+ uint16_t x_end;
+ uint16_t y_start;
+ uint16_t y_end;
+ bool enable;
+};
+
+struct dmub_cmd_roi_ctl_info {
+ uint8_t otg_id;
+ uint8_t phy_id;
+ struct dmub_cmd_roi_window_ctl roi_ctl[MAX_ROI_NUM];
};
/**
@@ -5182,14 +5248,8 @@ struct dmub_rb_cmd_secure_display {
/**
* 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;
+ struct dmub_cmd_roi_info roi_info;
+ struct dmub_cmd_roi_ctl_info mul_roi_ctl;
};
/**
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
index 2ccad79053c5..e5e77bd3c31e 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
@@ -426,6 +426,7 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu
boot_options.bits.ips_sequential_ono = params->ips_sequential_ono;
boot_options.bits.disable_sldo_opt = params->disable_sldo_opt;
boot_options.bits.enable_non_transparent_setconfig = params->enable_non_transparent_setconfig;
+ boot_options.bits.lower_hbr3_phy_ssc = params->lower_hbr3_phy_ssc;
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
}
@@ -463,7 +464,7 @@ uint32_t dmub_dcn35_get_current_time(struct dmub_srv *dmub)
void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data)
{
- uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
+ uint32_t is_dmub_enabled, is_soft_reset;
uint32_t is_traceport_enabled, is_cw6_enabled;
if (!dmub || !diag_data)
@@ -513,9 +514,6 @@ void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
diag_data->is_dmcub_soft_reset = is_soft_reset;
- REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- diag_data->is_dmcub_secure_reset = is_sec_reset;
-
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
diag_data->is_traceport_en = is_traceport_enabled;
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index db16066bc893..a3f3ff5d49ac 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -497,6 +497,7 @@ enum dmub_status
const struct dmub_fw_meta_info *fw_info;
uint32_t fw_state_size = DMUB_FW_STATE_SIZE;
uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE;
+ uint32_t shared_state_size = DMUB_FW_HEADER_SHARED_STATE_SIZE;
uint32_t window_sizes[DMUB_WINDOW_TOTAL] = { 0 };
if (!dmub->sw_init)
@@ -514,6 +515,7 @@ enum dmub_status
fw_state_size = fw_info->fw_region_size;
trace_buffer_size = fw_info->trace_buffer_size;
+ shared_state_size = fw_info->shared_state_size;
/**
* If DM didn't fill in a version, then fill it in based on
@@ -534,7 +536,7 @@ enum dmub_status
window_sizes[DMUB_WINDOW_5_TRACEBUFF] = trace_buffer_size;
window_sizes[DMUB_WINDOW_6_FW_STATE] = fw_state_size;
window_sizes[DMUB_WINDOW_7_SCRATCH_MEM] = DMUB_SCRATCH_MEM_SIZE;
- window_sizes[DMUB_WINDOW_SHARED_STATE] = DMUB_FW_HEADER_SHARED_STATE_SIZE;
+ window_sizes[DMUB_WINDOW_SHARED_STATE] = max(DMUB_FW_HEADER_SHARED_STATE_SIZE, shared_state_size);
out->fb_size =
dmub_srv_calc_regions_for_memory_type(params, out, window_sizes, DMUB_WINDOW_MEMORY_TYPE_FB);
diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h
index 02c23b04d34b..058f882d5bdd 100644
--- a/drivers/gpu/drm/amd/display/include/logger_interface.h
+++ b/drivers/gpu/drm/amd/display/include/logger_interface.h
@@ -52,10 +52,6 @@ void update_surface_trace(
void post_surface_trace(struct dc *dc);
-void context_timing_trace(
- struct dc *dc,
- struct resource_context *res_ctx);
-
void context_clock_trace(
struct dc *dc,
struct dc_state *context);
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 3699e633801d..a71df052cf25 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -1399,71 +1399,6 @@ static void scale_gamma_dx(struct pwl_float_data *pwl_rgb,
pwl_rgb[i-1].b, 2), pwl_rgb[i-2].b);
}
-/* todo: all these scale_gamma functions are inherently the same but
- * take different structures as params or different format for ramp
- * values. We could probably implement it in a more generic fashion
- */
-static void scale_user_regamma_ramp(struct pwl_float_data *pwl_rgb,
- const struct regamma_ramp *ramp,
- struct dividers dividers)
-{
- unsigned short max_driver = 0xFFFF;
- unsigned short max_os = 0xFF00;
- unsigned short scaler = max_os;
- uint32_t i;
- struct pwl_float_data *rgb = pwl_rgb;
- struct pwl_float_data *rgb_last = rgb + GAMMA_RGB_256_ENTRIES - 1;
-
- i = 0;
- do {
- if (ramp->gamma[i] > max_os ||
- ramp->gamma[i + 256] > max_os ||
- ramp->gamma[i + 512] > max_os) {
- scaler = max_driver;
- break;
- }
- i++;
- } while (i != GAMMA_RGB_256_ENTRIES);
-
- i = 0;
- do {
- rgb->r = dc_fixpt_from_fraction(
- ramp->gamma[i], scaler);
- rgb->g = dc_fixpt_from_fraction(
- ramp->gamma[i + 256], scaler);
- rgb->b = dc_fixpt_from_fraction(
- ramp->gamma[i + 512], scaler);
-
- ++rgb;
- ++i;
- } while (i != GAMMA_RGB_256_ENTRIES);
-
- rgb->r = dc_fixpt_mul(rgb_last->r,
- dividers.divider1);
- rgb->g = dc_fixpt_mul(rgb_last->g,
- dividers.divider1);
- rgb->b = dc_fixpt_mul(rgb_last->b,
- dividers.divider1);
-
- ++rgb;
-
- rgb->r = dc_fixpt_mul(rgb_last->r,
- dividers.divider2);
- rgb->g = dc_fixpt_mul(rgb_last->g,
- dividers.divider2);
- rgb->b = dc_fixpt_mul(rgb_last->b,
- dividers.divider2);
-
- ++rgb;
-
- rgb->r = dc_fixpt_mul(rgb_last->r,
- dividers.divider3);
- rgb->g = dc_fixpt_mul(rgb_last->g,
- dividers.divider3);
- rgb->b = dc_fixpt_mul(rgb_last->b,
- dividers.divider3);
-}
-
/*
* RS3+ color transform DDI - 1D LUT adjustment is composed with regamma here
* Input is evenly distributed in the output color space as specified in
@@ -1663,106 +1598,6 @@ static bool calculate_interpolated_hardware_curve(
return true;
}
-/* The "old" interpolation uses a complicated scheme to build an array of
- * coefficients while also using an array of 0-255 normalized to 0-1
- * Then there's another loop using both of the above + new scaled user ramp
- * and we concatenate them. It also searches for points of interpolation and
- * uses enums for positions.
- *
- * This function uses a different approach:
- * user ramp is always applied on X with 0/255, 1/255, 2/255, ..., 255/255
- * To find index for hwX , we notice the following:
- * i/255 <= hwX < (i+1)/255 <=> i <= 255*hwX < i+1
- * See apply_lut_1d which is the same principle, but on 4K entry 1D LUT
- *
- * Once the index is known, combined Y is simply:
- * user_ramp(index) + (hwX-index/255)*(user_ramp(index+1) - user_ramp(index)
- *
- * We should switch to this method in all cases, it's simpler and faster
- * ToDo one day - for now this only applies to ADL regamma to avoid regression
- * for regular use cases (sRGB and PQ)
- */
-static void interpolate_user_regamma(uint32_t hw_points_num,
- struct pwl_float_data *rgb_user,
- bool apply_degamma,
- struct dc_transfer_func_distributed_points *tf_pts)
-{
- uint32_t i;
- uint32_t color = 0;
- int32_t index;
- int32_t index_next;
- struct fixed31_32 *tf_point;
- struct fixed31_32 hw_x;
- struct fixed31_32 norm_factor =
- dc_fixpt_from_int(255);
- struct fixed31_32 norm_x;
- struct fixed31_32 index_f;
- struct fixed31_32 lut1;
- struct fixed31_32 lut2;
- struct fixed31_32 delta_lut;
- struct fixed31_32 delta_index;
- const struct fixed31_32 one = dc_fixpt_from_int(1);
-
- i = 0;
- /* fixed_pt library has problems handling too small values */
- while (i != 32) {
- tf_pts->red[i] = dc_fixpt_zero;
- tf_pts->green[i] = dc_fixpt_zero;
- tf_pts->blue[i] = dc_fixpt_zero;
- ++i;
- }
- while (i <= hw_points_num + 1) {
- for (color = 0; color < 3; color++) {
- if (color == 0)
- tf_point = &tf_pts->red[i];
- else if (color == 1)
- tf_point = &tf_pts->green[i];
- else
- tf_point = &tf_pts->blue[i];
-
- if (apply_degamma) {
- if (color == 0)
- hw_x = coordinates_x[i].regamma_y_red;
- else if (color == 1)
- hw_x = coordinates_x[i].regamma_y_green;
- else
- hw_x = coordinates_x[i].regamma_y_blue;
- } else
- hw_x = coordinates_x[i].x;
-
- if (dc_fixpt_le(one, hw_x))
- hw_x = one;
-
- norm_x = dc_fixpt_mul(norm_factor, hw_x);
- index = dc_fixpt_floor(norm_x);
- if (index < 0 || index > 255)
- continue;
-
- index_f = dc_fixpt_from_int(index);
- index_next = (index == 255) ? index : index + 1;
-
- if (color == 0) {
- lut1 = rgb_user[index].r;
- lut2 = rgb_user[index_next].r;
- } else if (color == 1) {
- lut1 = rgb_user[index].g;
- lut2 = rgb_user[index_next].g;
- } else {
- lut1 = rgb_user[index].b;
- lut2 = rgb_user[index_next].b;
- }
-
- // we have everything now, so interpolate
- delta_lut = dc_fixpt_sub(lut2, lut1);
- delta_index = dc_fixpt_sub(norm_x, index_f);
-
- *tf_point = dc_fixpt_add(lut1,
- dc_fixpt_mul(delta_index, delta_lut));
- }
- ++i;
- }
-}
-
static void build_new_custom_resulted_curve(
uint32_t hw_points_num,
struct dc_transfer_func_distributed_points *tf_pts)
@@ -1784,29 +1619,6 @@ static void build_new_custom_resulted_curve(
}
}
-static void apply_degamma_for_user_regamma(struct pwl_float_data_ex *rgb_regamma,
- uint32_t hw_points_num, struct calculate_buffer *cal_buffer)
-{
- uint32_t i;
-
- struct gamma_coefficients coeff;
- struct pwl_float_data_ex *rgb = rgb_regamma;
- const struct hw_x_point *coord_x = coordinates_x;
-
- build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB);
-
- i = 0;
- while (i != hw_points_num + 1) {
- rgb->r = translate_from_linear_space_ex(
- coord_x->x, &coeff, 0, cal_buffer);
- rgb->g = rgb->r;
- rgb->b = rgb->r;
- ++coord_x;
- ++rgb;
- ++i;
- }
-}
-
static bool map_regamma_hw_to_x_user(
const struct dc_gamma *ramp,
struct pixel_gamma_point *coeff128,
@@ -1855,125 +1667,6 @@ static bool map_regamma_hw_to_x_user(
#define _EXTRA_POINTS 3
-bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf,
- const struct regamma_lut *regamma,
- struct calculate_buffer *cal_buffer,
- const struct dc_gamma *ramp)
-{
- struct gamma_coefficients coeff;
- const struct hw_x_point *coord_x = coordinates_x;
- uint32_t i = 0;
-
- do {
- coeff.a0[i] = dc_fixpt_from_fraction(
- regamma->coeff.A0[i], 10000000);
- coeff.a1[i] = dc_fixpt_from_fraction(
- regamma->coeff.A1[i], 1000);
- coeff.a2[i] = dc_fixpt_from_fraction(
- regamma->coeff.A2[i], 1000);
- coeff.a3[i] = dc_fixpt_from_fraction(
- regamma->coeff.A3[i], 1000);
- coeff.user_gamma[i] = dc_fixpt_from_fraction(
- regamma->coeff.gamma[i], 1000);
-
- ++i;
- } while (i != 3);
-
- i = 0;
- /* fixed_pt library has problems handling too small values */
- while (i != 32) {
- output_tf->tf_pts.red[i] = dc_fixpt_zero;
- output_tf->tf_pts.green[i] = dc_fixpt_zero;
- output_tf->tf_pts.blue[i] = dc_fixpt_zero;
- ++coord_x;
- ++i;
- }
- while (i != MAX_HW_POINTS + 1) {
- output_tf->tf_pts.red[i] = translate_from_linear_space_ex(
- coord_x->x, &coeff, 0, cal_buffer);
- output_tf->tf_pts.green[i] = translate_from_linear_space_ex(
- coord_x->x, &coeff, 1, cal_buffer);
- output_tf->tf_pts.blue[i] = translate_from_linear_space_ex(
- coord_x->x, &coeff, 2, cal_buffer);
- ++coord_x;
- ++i;
- }
-
- if (ramp && ramp->type == GAMMA_CS_TFM_1D)
- apply_lut_1d(ramp, MAX_HW_POINTS, &output_tf->tf_pts);
-
- // this function just clamps output to 0-1
- build_new_custom_resulted_curve(MAX_HW_POINTS, &output_tf->tf_pts);
- output_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
-
- return true;
-}
-
-bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf,
- const struct regamma_lut *regamma,
- struct calculate_buffer *cal_buffer,
- const struct dc_gamma *ramp)
-{
- struct dc_transfer_func_distributed_points *tf_pts = &output_tf->tf_pts;
- struct dividers dividers;
-
- struct pwl_float_data *rgb_user = NULL;
- struct pwl_float_data_ex *rgb_regamma = NULL;
- bool ret = false;
-
- if (regamma == NULL)
- return false;
-
- output_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
-
- rgb_user = kcalloc(GAMMA_RGB_256_ENTRIES + _EXTRA_POINTS,
- sizeof(*rgb_user),
- GFP_KERNEL);
- if (!rgb_user)
- goto rgb_user_alloc_fail;
-
- rgb_regamma = kcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
- sizeof(*rgb_regamma),
- GFP_KERNEL);
- if (!rgb_regamma)
- goto rgb_regamma_alloc_fail;
-
- dividers.divider1 = dc_fixpt_from_fraction(3, 2);
- dividers.divider2 = dc_fixpt_from_int(2);
- dividers.divider3 = dc_fixpt_from_fraction(5, 2);
-
- scale_user_regamma_ramp(rgb_user, &regamma->ramp, dividers);
-
- if (regamma->flags.bits.applyDegamma == 1) {
- apply_degamma_for_user_regamma(rgb_regamma, MAX_HW_POINTS, cal_buffer);
- copy_rgb_regamma_to_coordinates_x(coordinates_x,
- MAX_HW_POINTS, rgb_regamma);
- }
-
- interpolate_user_regamma(MAX_HW_POINTS, rgb_user,
- regamma->flags.bits.applyDegamma, tf_pts);
-
- // no custom HDR curves!
- tf_pts->end_exponent = 0;
- tf_pts->x_point_at_y1_red = 1;
- tf_pts->x_point_at_y1_green = 1;
- tf_pts->x_point_at_y1_blue = 1;
-
- if (ramp && ramp->type == GAMMA_CS_TFM_1D)
- apply_lut_1d(ramp, MAX_HW_POINTS, &output_tf->tf_pts);
-
- // this function just clamps output to 0-1
- build_new_custom_resulted_curve(MAX_HW_POINTS, tf_pts);
-
- ret = true;
-
- kfree(rgb_regamma);
-rgb_regamma_alloc_fail:
- kfree(rgb_user);
-rgb_user_alloc_fail:
- return ret;
-}
-
bool mod_color_calculate_degamma_params(struct dc_color_caps *dc_caps,
struct dc_transfer_func *input_tf,
const struct dc_gamma *ramp, bool map_user_ramp)
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
index ee5c466613de..97e55278940e 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
@@ -115,15 +115,4 @@ bool mod_color_calculate_degamma_params(struct dc_color_caps *dc_caps,
struct dc_transfer_func *output_tf,
const struct dc_gamma *ramp, bool mapUserRamp);
-bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf,
- const struct regamma_lut *regamma,
- struct calculate_buffer *cal_buffer,
- const struct dc_gamma *ramp);
-
-bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf,
- const struct regamma_lut *regamma,
- struct calculate_buffer *cal_buffer,
- const struct dc_gamma *ramp);
-
-
#endif /* COLOR_MOD_COLOR_GAMMA_H_ */
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index fc4268729017..f980a84dceef 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -129,6 +129,9 @@ unsigned int mod_freesync_calc_v_total_from_refresh(
unsigned int v_total;
unsigned int frame_duration_in_ns;
+ if (refresh_in_uhz == 0)
+ return stream->timing.v_total;
+
frame_duration_in_ns =
((unsigned int)(div64_u64((1000000000ULL * 1000000),
refresh_in_uhz)));
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
index c996365e84b0..1d41dd58f6bc 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
@@ -27,6 +27,11 @@
#include "hdcp.h"
+static inline uint16_t get_hdmi_rxstatus_msg_size(const uint8_t rxstatus[2])
+{
+ return HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(rxstatus[1]) << 8 | rxstatus[0];
+}
+
static inline enum mod_hdcp_status check_receiver_id_list_ready(struct mod_hdcp *hdcp)
{
uint8_t is_ready = 0;
@@ -35,8 +40,7 @@ static inline enum mod_hdcp_status check_receiver_id_list_ready(struct mod_hdcp
is_ready = HDCP_2_2_DP_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus_dp) ? 1 : 0;
else
is_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus[1]) &&
- (HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
- hdcp->auth.msg.hdcp2.rxstatus[0])) ? 1 : 0;
+ get_hdmi_rxstatus_msg_size(hdcp->auth.msg.hdcp2.rxstatus) != 0) ? 1 : 0;
return is_ready ? MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_NOT_READY;
}
@@ -84,15 +88,13 @@ static inline enum mod_hdcp_status check_link_integrity_failure_dp(
static enum mod_hdcp_status check_ake_cert_available(struct mod_hdcp *hdcp)
{
enum mod_hdcp_status status;
- uint16_t size;
if (is_dp_hdcp(hdcp)) {
status = MOD_HDCP_STATUS_SUCCESS;
} else {
status = mod_hdcp_read_rxstatus(hdcp);
if (status == MOD_HDCP_STATUS_SUCCESS) {
- size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
- hdcp->auth.msg.hdcp2.rxstatus[0];
+ const uint16_t size = get_hdmi_rxstatus_msg_size(hdcp->auth.msg.hdcp2.rxstatus);
status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_cert)) ?
MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_AKE_CERT_PENDING;
@@ -104,7 +106,6 @@ static enum mod_hdcp_status check_ake_cert_available(struct mod_hdcp *hdcp)
static enum mod_hdcp_status check_h_prime_available(struct mod_hdcp *hdcp)
{
enum mod_hdcp_status status;
- uint8_t size;
status = mod_hdcp_read_rxstatus(hdcp);
if (status != MOD_HDCP_STATUS_SUCCESS)
@@ -115,8 +116,7 @@ static enum mod_hdcp_status check_h_prime_available(struct mod_hdcp *hdcp)
MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING;
} else {
- size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
- hdcp->auth.msg.hdcp2.rxstatus[0];
+ const uint16_t size = get_hdmi_rxstatus_msg_size(hdcp->auth.msg.hdcp2.rxstatus);
status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)) ?
MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING;
@@ -128,7 +128,6 @@ out:
static enum mod_hdcp_status check_pairing_info_available(struct mod_hdcp *hdcp)
{
enum mod_hdcp_status status;
- uint8_t size;
status = mod_hdcp_read_rxstatus(hdcp);
if (status != MOD_HDCP_STATUS_SUCCESS)
@@ -139,8 +138,7 @@ static enum mod_hdcp_status check_pairing_info_available(struct mod_hdcp *hdcp)
MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING;
} else {
- size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
- hdcp->auth.msg.hdcp2.rxstatus[0];
+ const uint16_t size = get_hdmi_rxstatus_msg_size(hdcp->auth.msg.hdcp2.rxstatus);
status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)) ?
MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING;
@@ -152,7 +150,6 @@ out:
static enum mod_hdcp_status poll_l_prime_available(struct mod_hdcp *hdcp)
{
enum mod_hdcp_status status = MOD_HDCP_STATUS_FAILURE;
- uint8_t size;
uint16_t max_wait = 20; // units of ms
uint16_t num_polls = 5;
uint16_t wait_time = max_wait / num_polls;
@@ -167,8 +164,7 @@ static enum mod_hdcp_status poll_l_prime_available(struct mod_hdcp *hdcp)
if (status != MOD_HDCP_STATUS_SUCCESS)
break;
- size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
- hdcp->auth.msg.hdcp2.rxstatus[0];
+ const uint16_t size = get_hdmi_rxstatus_msg_size(hdcp->auth.msg.hdcp2.rxstatus);
status = (size == sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)) ?
MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_L_PRIME_PENDING;
@@ -181,7 +177,6 @@ static enum mod_hdcp_status poll_l_prime_available(struct mod_hdcp *hdcp)
static enum mod_hdcp_status check_stream_ready_available(struct mod_hdcp *hdcp)
{
enum mod_hdcp_status status;
- uint8_t size;
if (is_dp_hdcp(hdcp)) {
status = MOD_HDCP_STATUS_INVALID_OPERATION;
@@ -189,8 +184,7 @@ static enum mod_hdcp_status check_stream_ready_available(struct mod_hdcp *hdcp)
status = mod_hdcp_read_rxstatus(hdcp);
if (status != MOD_HDCP_STATUS_SUCCESS)
goto out;
- size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
- hdcp->auth.msg.hdcp2.rxstatus[0];
+ const uint16_t size = get_hdmi_rxstatus_msg_size(hdcp->auth.msg.hdcp2.rxstatus);
status = (size == sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)) ?
MOD_HDCP_STATUS_SUCCESS :
MOD_HDCP_STATUS_HDCP2_STREAM_READY_PENDING;
@@ -249,8 +243,7 @@ static uint8_t process_rxstatus(struct mod_hdcp *hdcp,
sizeof(hdcp->auth.msg.hdcp2.rx_id_list);
else
hdcp->auth.msg.hdcp2.rx_id_list_size =
- HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
- hdcp->auth.msg.hdcp2.rxstatus[0];
+ get_hdmi_rxstatus_msg_size(hdcp->auth.msg.hdcp2.rxstatus);
}
out:
return (*status == MOD_HDCP_STATUS_SUCCESS);
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h
index f42a276499cd..5d9d5fea6e06 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_4_1_0_sh_mask.h
@@ -6199,10 +6199,12 @@
#define DCHUBBUB_CTRL_STATUS__ROB_UNDERFLOW_STATUS__SHIFT 0x1
#define DCHUBBUB_CTRL_STATUS__ROB_OVERFLOW_STATUS__SHIFT 0x2
#define DCHUBBUB_CTRL_STATUS__ROB_OVERFLOW_CLEAR__SHIFT 0x3
+#define DCHUBBUB_CTRL_STATUS__DCHUBBUB_HW_DEBUG__SHIFT 0x4
#define DCHUBBUB_CTRL_STATUS__CSTATE_SWATH_CHK_GOOD_MODE__SHIFT 0x1f
#define DCHUBBUB_CTRL_STATUS__ROB_UNDERFLOW_STATUS_MASK 0x00000002L
#define DCHUBBUB_CTRL_STATUS__ROB_OVERFLOW_STATUS_MASK 0x00000004L
#define DCHUBBUB_CTRL_STATUS__ROB_OVERFLOW_CLEAR_MASK 0x00000008L
+#define DCHUBBUB_CTRL_STATUS__DCHUBBUB_HW_DEBUG_MASK 0x3FFFFFF0L
#define DCHUBBUB_CTRL_STATUS__CSTATE_SWATH_CHK_GOOD_MODE_MASK 0x80000000L
//DCHUBBUB_TIMEOUT_DETECTION_CTRL1
#define DCHUBBUB_TIMEOUT_DETECTION_CTRL1__DCHUBBUB_TIMEOUT_ERROR_STATUS__SHIFT 0x0
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
index 5ebe4cb40f9d..c38a01742d6f 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
@@ -7571,6 +7571,8 @@
// base address: 0x10100000
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0 0xd000
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_BASE_IDX 5
+#define regRCC_DEV0_EPF5_STRAP4 0xd284
+#define regRCC_DEV0_EPF5_STRAP4_BASE_IDX 5
// addressBlock: nbio_nbif0_bif_rst_bif_rst_regblk
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
index eb8c556d9c93..3b96f1e5a180 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
@@ -50665,6 +50665,19 @@
#define RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_D1_SUPPORT_DEV0_F0_MASK 0x40000000L
#define RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_D2_SUPPORT_DEV0_F0_MASK 0x80000000L
+//RCC_DEV0_EPF5_STRAP4
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_64BIT_EN_DEV0_F5__SHIFT 0x14
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_EN_DEV0_F5__SHIFT 0x15
+#define RCC_DEV0_EPF5_STRAP4__STRAP_FLR_EN_DEV0_F5__SHIFT 0x16
+#define RCC_DEV0_EPF5_STRAP4__STRAP_PME_SUPPORT_DEV0_F5__SHIFT 0x17
+#define RCC_DEV0_EPF5_STRAP4__STRAP_INTERRUPT_PIN_DEV0_F5__SHIFT 0x1c
+#define RCC_DEV0_EPF5_STRAP4__STRAP_AUXPWR_SUPPORT_DEV0_F5__SHIFT 0x1f
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_64BIT_EN_DEV0_F5_MASK 0x00100000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_EN_DEV0_F5_MASK 0x00200000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_FLR_EN_DEV0_F5_MASK 0x00400000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_PME_SUPPORT_DEV0_F5_MASK 0x0F800000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_INTERRUPT_PIN_DEV0_F5_MASK 0x70000000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_AUXPWR_SUPPORT_DEV0_F5_MASK 0x80000000L
// addressBlock: nbio_nbif0_bif_rst_bif_rst_regblk
//HARD_RST_CTRL
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 2fa71f68205e..67a5de573943 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -119,6 +119,8 @@ enum pp_clock_type {
OD_ACOUSTIC_TARGET,
OD_FAN_TARGET_TEMPERATURE,
OD_FAN_MINIMUM_PWM,
+ OD_FAN_ZERO_RPM_ENABLE,
+ OD_FAN_ZERO_RPM_STOP_TEMP,
};
enum amd_pp_sensors {
@@ -199,6 +201,8 @@ enum PP_OD_DPM_TABLE_COMMAND {
PP_OD_EDIT_ACOUSTIC_TARGET,
PP_OD_EDIT_FAN_TARGET_TEMPERATURE,
PP_OD_EDIT_FAN_MINIMUM_PWM,
+ PP_OD_EDIT_FAN_ZERO_RPM_ENABLE,
+ PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP,
};
struct pp_states_info {
@@ -353,11 +357,22 @@ struct dpm_clocks;
struct amdgpu_xcp_metrics {
/* Utilization Instantaneous (%) */
- u32 gfx_busy_inst[MAX_XCC];
- u16 jpeg_busy[NUM_JPEG_ENG];
- u16 vcn_busy[NUM_VCN];
+ uint32_t gfx_busy_inst[MAX_XCC];
+ uint16_t jpeg_busy[NUM_JPEG_ENG];
+ uint16_t vcn_busy[NUM_VCN];
/* Utilization Accumulated (%) */
- u64 gfx_busy_acc[MAX_XCC];
+ uint64_t gfx_busy_acc[MAX_XCC];
+};
+
+struct amdgpu_xcp_metrics_v1_1 {
+ /* Utilization Instantaneous (%) */
+ uint32_t gfx_busy_inst[MAX_XCC];
+ uint16_t jpeg_busy[NUM_JPEG_ENG];
+ uint16_t vcn_busy[NUM_VCN];
+ /* Utilization Accumulated (%) */
+ uint64_t gfx_busy_acc[MAX_XCC];
+ /* Total App Clock Counter Accumulated */
+ uint64_t gfx_below_host_limit_acc[MAX_XCC];
};
struct amd_pm_funcs {
@@ -973,6 +988,105 @@ struct gpu_metrics_v1_6 {
uint32_t pcie_lc_perf_other_end_recovery;
};
+struct gpu_metrics_v1_7 {
+ struct metrics_table_header common_header;
+
+ /* Temperature (Celsius) */
+ uint16_t temperature_hotspot;
+ uint16_t temperature_mem;
+ uint16_t temperature_vrsoc;
+
+ /* Power (Watts) */
+ uint16_t curr_socket_power;
+
+ /* Utilization (%) */
+ uint16_t average_gfx_activity;
+ uint16_t average_umc_activity; // memory controller
+
+ /* VRAM max bandwidthi (in GB/sec) at max memory clock */
+ uint64_t mem_max_bandwidth;
+
+ /* Energy (15.259uJ (2^-16) units) */
+ uint64_t energy_accumulator;
+
+ /* Driver attached timestamp (in ns) */
+ uint64_t system_clock_counter;
+
+ /* Accumulation cycle counter */
+ uint32_t accumulation_counter;
+
+ /* Accumulated throttler residencies */
+ uint32_t prochot_residency_acc;
+ uint32_t ppt_residency_acc;
+ uint32_t socket_thm_residency_acc;
+ uint32_t vr_thm_residency_acc;
+ uint32_t hbm_thm_residency_acc;
+
+ /* Clock Lock Status. Each bit corresponds to clock instance */
+ uint32_t gfxclk_lock_status;
+
+ /* Link width (number of lanes) and speed (in 0.1 GT/s) */
+ uint16_t pcie_link_width;
+ uint16_t pcie_link_speed;
+
+ /* XGMI bus width and bitrate (in Gbps) */
+ uint16_t xgmi_link_width;
+ uint16_t xgmi_link_speed;
+
+ /* Utilization Accumulated (%) */
+ uint32_t gfx_activity_acc;
+ uint32_t mem_activity_acc;
+
+ /*PCIE accumulated bandwidth (GB/sec) */
+ uint64_t pcie_bandwidth_acc;
+
+ /*PCIE instantaneous bandwidth (GB/sec) */
+ uint64_t pcie_bandwidth_inst;
+
+ /* PCIE L0 to recovery state transition accumulated count */
+ uint64_t pcie_l0_to_recov_count_acc;
+
+ /* PCIE replay accumulated count */
+ uint64_t pcie_replay_count_acc;
+
+ /* PCIE replay rollover accumulated count */
+ uint64_t pcie_replay_rover_count_acc;
+
+ /* PCIE NAK sent accumulated count */
+ uint32_t pcie_nak_sent_count_acc;
+
+ /* PCIE NAK received accumulated count */
+ uint32_t pcie_nak_rcvd_count_acc;
+
+ /* XGMI accumulated data transfer size(KiloBytes) */
+ uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS];
+ uint64_t xgmi_write_data_acc[NUM_XGMI_LINKS];
+
+ /* XGMI link status(active/inactive) */
+ uint16_t xgmi_link_status[NUM_XGMI_LINKS];
+
+ uint16_t padding;
+
+ /* PMFW attached timestamp (10ns resolution) */
+ uint64_t firmware_timestamp;
+
+ /* Current clocks (Mhz) */
+ uint16_t current_gfxclk[MAX_GFX_CLKS];
+ uint16_t current_socclk[MAX_CLKS];
+ uint16_t current_vclk0[MAX_CLKS];
+ uint16_t current_dclk0[MAX_CLKS];
+ uint16_t current_uclk;
+
+ /* Number of current partition */
+ uint16_t num_partition;
+
+ /* XCP metrics stats */
+ struct amdgpu_xcp_metrics_v1_1 xcp_stats[NUM_XCP];
+
+ /* PCIE other end recovery counter */
+ uint32_t pcie_lc_perf_other_end_recovery;
+};
+
/*
* gpu_metrics_v2_0 is not recommended as it's not naturally aligned.
* Use gpu_metrics_v2_1 or later instead.
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 21ceafce1f9b..eb46cb10c24d 100644
--- a/drivers/gpu/drm/amd/include/mes_v11_api_def.h
+++ b/drivers/gpu/drm/amd/include/mes_v11_api_def.h
@@ -230,13 +230,23 @@ union MESAPI_SET_HW_RESOURCES {
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 use_disable_queue_in_legacy_uq_preemption : 1;
+ uint32_t send_write_data : 1;
+ uint32_t os_tdr_timeout_override : 1;
+ uint32_t use_rs64mem_for_proc_gang_ctx : 1;
+ uint32_t use_add_queue_unmap_flag_addr : 1;
+ uint32_t enable_mes_sch_stb_log : 1;
+ uint32_t limit_single_process : 1;
+ uint32_t is_strix_tmz_wa_enabled :1;
+ uint32_t reserved : 13;
};
uint32_t uint32_t_all;
};
uint32_t oversubscription_timer;
uint64_t doorbell_info;
uint64_t event_intr_history_gpu_mc_ptr;
+ uint64_t timestamp;
+ uint32_t os_tdr_timeout_in_sec;
};
uint32_t max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS];
@@ -563,6 +573,11 @@ enum MESAPI_MISC_OPCODE {
MESAPI_MISC__READ_REG,
MESAPI_MISC__WAIT_REG_MEM,
MESAPI_MISC__SET_SHADER_DEBUGGER,
+ MESAPI_MISC__NOTIFY_WORK_ON_UNMAPPED_QUEUE,
+ MESAPI_MISC__NOTIFY_TO_UNMAP_PROCESSES,
+ MESAPI_MISC__CHANGE_CONFIG,
+ MESAPI_MISC__LAUNCH_CLEANER_SHADER,
+
MESAPI_MISC__MAX,
};
@@ -617,6 +632,31 @@ struct SET_SHADER_DEBUGGER {
uint32_t trap_en;
};
+enum MESAPI_MISC__CHANGE_CONFIG_OPTION {
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_LIMIT_SINGLE_PROCESS = 0,
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_ENABLE_HWS_LOGGING_BUFFER = 1,
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_CHANGE_TDR_CONFIG = 2,
+
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_MAX = 0x1F
+};
+
+struct CHANGE_CONFIG {
+ enum MESAPI_MISC__CHANGE_CONFIG_OPTION opcode;
+ union {
+ struct {
+ uint32_t limit_single_process : 1;
+ uint32_t enable_hws_logging_buffer : 1;
+ uint32_t reserved : 31;
+ } bits;
+ uint32_t all;
+ } option;
+
+ struct {
+ uint32_t tdr_level;
+ uint32_t tdr_delay;
+ } tdr_config;
+};
+
union MESAPI__MISC {
struct {
union MES_API_HEADER header;
@@ -631,6 +671,7 @@ union MESAPI__MISC {
struct WAIT_REG_MEM wait_reg_mem;
struct SET_SHADER_DEBUGGER set_shader_debugger;
enum MES_AMD_PRIORITY_LEVEL queue_sch_level;
+ struct CHANGE_CONFIG change_config;
uint32_t data[MISC_DATA_MAX_SIZE_IN_DWORDS];
};
diff --git a/drivers/gpu/drm/amd/include/mes_v12_api_def.h b/drivers/gpu/drm/amd/include/mes_v12_api_def.h
index 101e2fe962c6..c9b2ca5cf75f 100644
--- a/drivers/gpu/drm/amd/include/mes_v12_api_def.h
+++ b/drivers/gpu/drm/amd/include/mes_v12_api_def.h
@@ -643,6 +643,10 @@ enum MESAPI_MISC_OPCODE {
MESAPI_MISC__SET_SHADER_DEBUGGER,
MESAPI_MISC__NOTIFY_WORK_ON_UNMAPPED_QUEUE,
MESAPI_MISC__NOTIFY_TO_UNMAP_PROCESSES,
+ MESAPI_MISC__QUERY_HUNG_ENGINE_ID,
+ MESAPI_MISC__CHANGE_CONFIG,
+ MESAPI_MISC__LAUNCH_CLEANER_SHADER,
+ MESAPI_MISC__SETUP_MES_DBGEXT,
MESAPI_MISC__MAX,
};
@@ -713,6 +717,31 @@ struct SET_GANG_SUBMIT {
uint32_t slave_gang_context_array_index;
};
+enum MESAPI_MISC__CHANGE_CONFIG_OPTION {
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_LIMIT_SINGLE_PROCESS = 0,
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_ENABLE_HWS_LOGGING_BUFFER = 1,
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_CHANGE_TDR_CONFIG = 2,
+
+ MESAPI_MISC__CHANGE_CONFIG_OPTION_MAX = 0x1F
+};
+
+struct CHANGE_CONFIG {
+ enum MESAPI_MISC__CHANGE_CONFIG_OPTION opcode;
+ union {
+ struct {
+ uint32_t limit_single_process : 1;
+ uint32_t enable_hws_logging_buffer : 1;
+ uint32_t reserved : 30;
+ } bits;
+ uint32_t all;
+ } option;
+
+ struct {
+ uint32_t tdr_level;
+ uint32_t tdr_delay;
+ } tdr_config;
+};
+
union MESAPI__MISC {
struct {
union MES_API_HEADER header;
@@ -726,7 +755,7 @@ union MESAPI__MISC {
struct WAIT_REG_MEM wait_reg_mem;
struct SET_SHADER_DEBUGGER set_shader_debugger;
enum MES_AMD_PRIORITY_LEVEL queue_sch_level;
-
+ struct CHANGE_CONFIG change_config;
uint32_t data[MISC_DATA_MAX_SIZE_IN_DWORDS];
};
uint64_t timestamp;
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index ea940773353c..136e8193867c 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -4109,6 +4109,117 @@ static umode_t fan_minimum_pwm_visible(struct amdgpu_device *adev)
return umode;
}
+/**
+ * DOC: fan_zero_rpm_enable
+ *
+ * The amdgpu driver provides a sysfs API for checking and adjusting the
+ * zero RPM feature.
+ *
+ * Reading back the file shows you the current setting and the permitted
+ * ranges if changable.
+ *
+ * Writing an integer to the file, change the setting accordingly.
+ *
+ * When you have finished the editing, write "c" (commit) to the file to commit
+ * your changes.
+ *
+ * If you want to reset to the default value, write "r" (reset) to the file to
+ * reset them.
+ */
+static ssize_t fan_zero_rpm_enable_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ struct od_kobj *container = container_of(kobj, struct od_kobj, kobj);
+ struct amdgpu_device *adev = (struct amdgpu_device *)container->priv;
+
+ return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_FAN_ZERO_RPM_ENABLE, buf);
+}
+
+static ssize_t fan_zero_rpm_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct od_kobj *container = container_of(kobj, struct od_kobj, kobj);
+ struct amdgpu_device *adev = (struct amdgpu_device *)container->priv;
+
+ return (ssize_t)amdgpu_distribute_custom_od_settings(adev,
+ PP_OD_EDIT_FAN_ZERO_RPM_ENABLE,
+ buf,
+ count);
+}
+
+static umode_t fan_zero_rpm_enable_visible(struct amdgpu_device *adev)
+{
+ umode_t umode = 0000;
+
+ if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE)
+ umode |= S_IRUSR | S_IRGRP | S_IROTH;
+
+ if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET)
+ umode |= S_IWUSR;
+
+ return umode;
+}
+
+/**
+ * DOC: fan_zero_rpm_stop_temperature
+ *
+ * The amdgpu driver provides a sysfs API for checking and adjusting the
+ * zero RPM stop temperature feature.
+ *
+ * Reading back the file shows you the current setting and the permitted
+ * ranges if changable.
+ *
+ * Writing an integer to the file, change the setting accordingly.
+ *
+ * When you have finished the editing, write "c" (commit) to the file to commit
+ * your changes.
+ *
+ * If you want to reset to the default value, write "r" (reset) to the file to
+ * reset them.
+ *
+ * This setting works only if the Zero RPM setting is enabled. It adjusts the
+ * temperature below which the fan can stop.
+ */
+static ssize_t fan_zero_rpm_stop_temp_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ struct od_kobj *container = container_of(kobj, struct od_kobj, kobj);
+ struct amdgpu_device *adev = (struct amdgpu_device *)container->priv;
+
+ return (ssize_t)amdgpu_retrieve_od_settings(adev, OD_FAN_ZERO_RPM_STOP_TEMP, buf);
+}
+
+static ssize_t fan_zero_rpm_stop_temp_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct od_kobj *container = container_of(kobj, struct od_kobj, kobj);
+ struct amdgpu_device *adev = (struct amdgpu_device *)container->priv;
+
+ return (ssize_t)amdgpu_distribute_custom_od_settings(adev,
+ PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP,
+ buf,
+ count);
+}
+
+static umode_t fan_zero_rpm_stop_temp_visible(struct amdgpu_device *adev)
+{
+ umode_t umode = 0000;
+
+ if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_RETRIEVE)
+ umode |= S_IRUSR | S_IRGRP | S_IROTH;
+
+ if (adev->pm.od_feature_mask & OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_SET)
+ umode |= S_IWUSR;
+
+ return umode;
+}
+
static struct od_feature_set amdgpu_od_set = {
.containers = {
[0] = {
@@ -4154,6 +4265,22 @@ static struct od_feature_set amdgpu_od_set = {
.store = fan_minimum_pwm_store,
},
},
+ [5] = {
+ .name = "fan_zero_rpm_enable",
+ .ops = {
+ .is_visible = fan_zero_rpm_enable_visible,
+ .show = fan_zero_rpm_enable_show,
+ .store = fan_zero_rpm_enable_store,
+ },
+ },
+ [6] = {
+ .name = "fan_zero_rpm_stop_temperature",
+ .ops = {
+ .is_visible = fan_zero_rpm_stop_temp_visible,
+ .show = fan_zero_rpm_stop_temp_show,
+ .store = fan_zero_rpm_stop_temp_store,
+ },
+ },
},
},
},
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
index f5bf41f21c41..363af8990aa2 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
@@ -328,6 +328,10 @@ struct config_table_setting
#define OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET BIT(7)
#define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE BIT(8)
#define OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET BIT(9)
+#define OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE BIT(10)
+#define OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET BIT(11)
+#define OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_RETRIEVE BIT(12)
+#define OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_SET BIT(13)
struct amdgpu_pm {
struct mutex mutex;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
index b52ce135d84d..d3ff6a831ed5 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
@@ -257,20 +257,18 @@ static int vega12_smu_init(struct pp_hwmgr *hwmgr)
priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
tools_size = 0x19000;
- if (tools_size) {
- ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
- tools_size,
- PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
- if (ret)
- goto err1;
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ tools_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
+ if (ret)
+ goto err1;
- priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
- priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
- }
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
/* allocate space for AVFS Fuse table */
ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 67d5a8123416..b8355293518f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -252,7 +252,7 @@ static int smu_dpm_set_vcn_enable(struct smu_context *smu,
if (atomic_read(&power_gate->vcn_gated) ^ enable)
return 0;
- ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable);
+ ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable, 0xff);
if (!ret)
atomic_set(&power_gate->vcn_gated, !enable);
@@ -1261,26 +1261,33 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)
smu->watermarks_bitmap = 0;
smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ smu->user_dpm_profile.user_workload_mask = 0;
atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);
- smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
- smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
- smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
- smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
- smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
- smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
- smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
+ smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
+ smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
+ smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
+ smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
+ smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
+ smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
+ smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
if (smu->is_apu ||
- !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
- smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
- else
- smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
+ !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
+ smu->driver_workload_mask =
+ 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+ } else {
+ smu->driver_workload_mask =
+ 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
+ smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+ }
+ smu->workload_mask = smu->driver_workload_mask |
+ smu->user_dpm_profile.user_workload_mask;
smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
@@ -1697,7 +1704,9 @@ static int smu_smc_hw_setup(struct smu_context *smu)
return ret;
}
- if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
+ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5)
+ pcie_gen = 4;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
pcie_gen = 3;
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
pcie_gen = 2;
@@ -1710,7 +1719,9 @@ static int smu_smc_hw_setup(struct smu_context *smu)
* Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
* Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
*/
- if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
+ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X32)
+ pcie_width = 7;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
pcie_width = 6;
else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
pcie_width = 5;
@@ -2355,17 +2366,20 @@ static int smu_switch_power_profile(void *handle,
return -EINVAL;
if (!en) {
- smu->workload_mask &= ~(1 << smu->workload_prority[type]);
+ smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
index = fls(smu->workload_mask);
index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
workload[0] = smu->workload_setting[index];
} else {
- smu->workload_mask |= (1 << smu->workload_prority[type]);
+ smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
index = fls(smu->workload_mask);
index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
workload[0] = smu->workload_setting[index];
}
+ smu->workload_mask = smu->driver_workload_mask |
+ smu->user_dpm_profile.user_workload_mask;
+
if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
smu_bump_power_profile_mode(smu, workload, 0);
@@ -2885,6 +2899,10 @@ static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
clk_type = SMU_OD_FAN_TARGET_TEMPERATURE; break;
case OD_FAN_MINIMUM_PWM:
clk_type = SMU_OD_FAN_MINIMUM_PWM; break;
+ case OD_FAN_ZERO_RPM_ENABLE:
+ clk_type = SMU_OD_FAN_ZERO_RPM_ENABLE; break;
+ case OD_FAN_ZERO_RPM_STOP_TEMP:
+ clk_type = SMU_OD_FAN_ZERO_RPM_STOP_TEMP; break;
default:
clk_type = SMU_CLK_COUNT; break;
}
@@ -3056,12 +3074,23 @@ static int smu_set_power_profile_mode(void *handle,
uint32_t param_size)
{
struct smu_context *smu = handle;
+ int ret;
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
!smu->ppt_funcs->set_power_profile_mode)
return -EOPNOTSUPP;
- return smu_bump_power_profile_mode(smu, param, param_size);
+ if (smu->user_dpm_profile.user_workload_mask &
+ (1 << smu->workload_priority[param[param_size]]))
+ return 0;
+
+ smu->user_dpm_profile.user_workload_mask =
+ (1 << smu->workload_priority[param[param_size]]);
+ smu->workload_mask = smu->user_dpm_profile.user_workload_mask |
+ smu->driver_workload_mask;
+ ret = smu_bump_power_profile_mode(smu, param, param_size);
+
+ return ret;
}
static int smu_get_fan_control_mode(void *handle, u32 *fan_mode)
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 8bb32b3f0d9c..d665c47f19b7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -240,6 +240,7 @@ struct smu_user_dpm_profile {
/* user clock state information */
uint32_t clk_mask[SMU_CLK_COUNT];
uint32_t clk_dependency;
+ uint32_t user_workload_mask;
};
#define SMU_TABLE_INIT(tables, table_id, s, a, d) \
@@ -557,7 +558,8 @@ struct smu_context {
bool disable_uclk_switch;
uint32_t workload_mask;
- uint32_t workload_prority[WORKLOAD_POLICY_MAX];
+ uint32_t driver_workload_mask;
+ uint32_t workload_priority[WORKLOAD_POLICY_MAX];
uint32_t workload_setting[WORKLOAD_POLICY_MAX];
uint32_t power_profile_mode;
uint32_t default_power_profile_mode;
@@ -739,7 +741,7 @@ struct pptable_funcs {
* @dpm_set_vcn_enable: Enable/disable VCN engine dynamic power
* management.
*/
- int (*dpm_set_vcn_enable)(struct smu_context *smu, bool enable);
+ int (*dpm_set_vcn_enable)(struct smu_context *smu, bool enable, int inst);
/**
* @dpm_set_jpeg_enable: Enable/disable JPEG engine dynamic power
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 e71a721c12b9..a299dc4a8071 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -313,6 +313,8 @@ enum smu_clk_type {
SMU_OD_ACOUSTIC_TARGET,
SMU_OD_FAN_TARGET_TEMPERATURE,
SMU_OD_FAN_MINIMUM_PWM,
+ SMU_OD_FAN_ZERO_RPM_ENABLE,
+ SMU_OD_FAN_ZERO_RPM_STOP_TEMP,
SMU_CLK_COUNT,
};
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
index 044d6893b43e..ae3563d71fa0 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
@@ -255,7 +255,8 @@ int smu_v13_0_wait_for_event(struct smu_context *smu, enum smu_event_type event,
uint64_t event_arg);
int smu_v13_0_set_vcn_enable(struct smu_context *smu,
- bool enable);
+ bool enable,
+ int inst);
int smu_v13_0_set_jpeg_enable(struct smu_context *smu,
bool enable);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
index 07c220102c1d..29a4583db873 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
@@ -53,7 +53,7 @@
#define CTF_OFFSET_MEM 5
extern const int decoded_link_speed[5];
-extern const int decoded_link_width[7];
+extern const int decoded_link_width[8];
#define DECODE_GEN_SPEED(gen_speed_idx) (decoded_link_speed[gen_speed_idx])
#define DECODE_LANE_WIDTH(lane_width_idx) (decoded_link_width[lane_width_idx])
@@ -210,7 +210,8 @@ int smu_v14_0_wait_for_event(struct smu_context *smu, enum smu_event_type event,
uint64_t event_arg);
int smu_v14_0_set_vcn_enable(struct smu_context *smu,
- bool enable);
+ bool enable,
+ int inst);
int smu_v14_0_set_jpeg_enable(struct smu_context *smu,
bool enable);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 5ad09323a29d..12125303bb79 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1344,8 +1344,12 @@ static int arcturus_get_power_limit(struct smu_context *smu,
*default_power_limit = power_limit;
if (max_power_limit)
*max_power_limit = power_limit;
+ /**
+ * No lower bound is imposed on the limit. Any unreasonable limit set
+ * will result in frequent throttling.
+ */
if (min_power_limit)
- *min_power_limit = power_limit;
+ *min_power_limit = 0;
return 0;
}
@@ -1455,7 +1459,6 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
return -EINVAL;
}
-
if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
(smu->smc_fw_version >= 0x360d00)) {
if (size != 10)
@@ -1523,14 +1526,14 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_SetWorkloadMask,
- 1 << workload_type,
+ smu->workload_mask,
NULL);
if (ret) {
dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
return ret;
}
- smu->power_profile_mode = profile_mode;
+ smu_cmn_assign_power_profile(smu);
return 0;
}
@@ -1571,7 +1574,9 @@ static bool arcturus_is_dpm_running(struct smu_context *smu)
return !!(feature_enabled & SMC_DPM_FEATURE);
}
-static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+static int arcturus_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable,
+ int inst)
{
int ret = 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 9fa305ba6422..211635dabed8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1135,7 +1135,9 @@ static int navi10_set_default_dpm_table(struct smu_context *smu)
return 0;
}
-static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+static int navi10_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable,
+ int inst)
{
int ret = 0;
@@ -2081,10 +2083,13 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u
smu->power_profile_mode);
if (workload_type < 0)
return -EINVAL;
+
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
- 1 << workload_type, NULL);
+ smu->workload_mask, NULL);
if (ret)
dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
+ else
+ smu_cmn_assign_power_profile(smu);
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 77e58eb46328..d0ed0d060a8a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -1152,7 +1152,9 @@ static int sienna_cichlid_set_default_dpm_table(struct smu_context *smu)
return 0;
}
-static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable,
+ int inst)
{
struct amdgpu_device *adev = smu->adev;
int i, ret = 0;
@@ -1786,10 +1788,13 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *
smu->power_profile_mode);
if (workload_type < 0)
return -EINVAL;
+
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
- 1 << workload_type, NULL);
+ smu->workload_mask, NULL);
if (ret)
dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
+ else
+ smu_cmn_assign_power_profile(smu);
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index 6c43724c01dd..f89c487dce72 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -461,7 +461,9 @@ static int vangogh_init_smc_tables(struct smu_context *smu)
return smu_v11_0_init_smc_tables(smu);
}
-static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+static int vangogh_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable,
+ int inst)
{
int ret = 0;
@@ -1079,7 +1081,7 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,
}
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
- 1 << workload_type,
+ smu->workload_mask,
NULL);
if (ret) {
dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
@@ -1087,7 +1089,7 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,
return ret;
}
- smu->power_profile_mode = profile_mode;
+ smu_cmn_assign_power_profile(smu);
return 0;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index 0b210b1f2628..75a9ea87f419 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -645,7 +645,9 @@ static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context
return pm_type;
}
-static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+static int renoir_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable,
+ int inst)
{
int ret = 0;
@@ -890,14 +892,14 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u
}
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
- 1 << workload_type,
+ smu->workload_mask,
NULL);
if (ret) {
dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
return ret;
}
- smu->power_profile_mode = profile_mode;
+ smu_cmn_assign_power_profile(smu);
return 0;
}
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 6cfd66363915..2bfea740dace 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
@@ -2104,7 +2104,8 @@ int smu_v13_0_get_current_pcie_link_speed(struct smu_context *smu)
}
int smu_v13_0_set_vcn_enable(struct smu_context *smu,
- bool enable)
+ bool enable,
+ int inst)
{
struct amdgpu_device *adev = smu->adev;
int i, ret = 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 8d25cc1f218f..80c6b1e523aa 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
@@ -107,6 +107,8 @@
#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8
#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9
#define PP_OD_FEATURE_FAN_MINIMUM_PWM 10
+#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE 11
+#define PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP 12
#define LINK_SPEED_MAX 3
@@ -1130,6 +1132,14 @@ static void smu_v13_0_0_get_od_setting_limits(struct smu_context *smu,
od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
od_max_setting = overdrive_upperlimits->FanMinimumPwm;
break;
+ case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE:
+ od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable;
+ od_max_setting = overdrive_upperlimits->FanZeroRpmEnable;
+ break;
+ case PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP:
+ od_min_setting = overdrive_lowerlimits->FanZeroRpmStopTemp;
+ od_max_setting = overdrive_upperlimits->FanZeroRpmStopTemp;
+ break;
default:
od_min_setting = od_max_setting = INT_MAX;
break;
@@ -1450,6 +1460,42 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
min_value, max_value);
break;
+ case SMU_OD_FAN_ZERO_RPM_ENABLE:
+ if (!smu_v13_0_0_is_od_feature_supported(smu,
+ PP_OD_FEATURE_ZERO_FAN_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n");
+ size += sysfs_emit_at(buf, size, "%d\n",
+ (int)od_table->OverDriveTable.FanZeroRpmEnable);
+
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+ &min_value,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n",
+ min_value, max_value);
+ break;
+
+ case SMU_OD_FAN_ZERO_RPM_STOP_TEMP:
+ if (!smu_v13_0_0_is_od_feature_supported(smu,
+ PP_OD_FEATURE_ZERO_FAN_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_STOP_TEMPERATURE:\n");
+ size += sysfs_emit_at(buf, size, "%d\n",
+ (int)od_table->OverDriveTable.FanZeroRpmStopTemp);
+
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP,
+ &min_value,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "ZERO_RPM_STOP_TEMPERATURE: %u %u\n",
+ min_value, max_value);
+ break;
+
case SMU_OD_RANGE:
if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
@@ -1547,6 +1593,16 @@ static int smu_v13_0_0_od_restore_table_single(struct smu_context *smu, long inp
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
+ case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+ od_table->OverDriveTable.FanZeroRpmEnable =
+ boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
+ case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
+ od_table->OverDriveTable.FanZeroRpmStopTemp =
+ boot_overdrive_table->OverDriveTable.FanZeroRpmStopTemp;
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
default:
dev_info(adev->dev, "Invalid table index: %ld\n", input);
return -EINVAL;
@@ -1840,6 +1896,48 @@ static int smu_v13_0_0_od_edit_dpm_table(struct smu_context *smu,
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
+ case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+ if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
+ dev_warn(adev->dev, "Zero RPM setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+ &minimum,
+ &maximum);
+ if (input[0] < minimum ||
+ input[0] > maximum) {
+ dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n",
+ input[0], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.FanZeroRpmEnable = input[0];
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
+
+ case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
+ if (!smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
+ dev_warn(adev->dev, "Zero RPM setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ smu_v13_0_0_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP,
+ &minimum,
+ &maximum);
+ if (input[0] < minimum ||
+ input[0] > maximum) {
+ dev_info(adev->dev, "zero RPM stop temperature setting(%ld) must be within [%d, %d]!\n",
+ input[0], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.FanZeroRpmStopTemp = input[0];
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
+
case PP_OD_RESTORE_DEFAULT_TABLE:
if (size == 1) {
ret = smu_v13_0_0_od_restore_table_single(smu, input[0]);
@@ -2110,7 +2208,11 @@ static void smu_v13_0_0_set_supported_od_feature_mask(struct smu_context *smu)
OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
- OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET;
+ OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_RETRIEVE |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_SET;
}
static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
@@ -2176,6 +2278,10 @@ static int smu_v13_0_0_set_default_od_settings(struct smu_context *smu)
user_od_table_bak.OverDriveTable.FanTargetTemperature;
user_od_table->OverDriveTable.FanMinimumPwm =
user_od_table_bak.OverDriveTable.FanMinimumPwm;
+ user_od_table->OverDriveTable.FanZeroRpmEnable =
+ user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
+ user_od_table->OverDriveTable.FanZeroRpmStopTemp =
+ user_od_table_bak.OverDriveTable.FanZeroRpmStopTemp;
}
smu_v13_0_0_set_supported_od_feature_mask(smu);
@@ -2473,7 +2579,7 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
DpmActivityMonitorCoeffInt_t *activity_monitor =
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
int workload_type, ret = 0;
- u32 workload_mask, selected_workload_mask;
+ u32 workload_mask;
smu->power_profile_mode = input[size];
@@ -2540,7 +2646,7 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
if (workload_type < 0)
return -EINVAL;
- selected_workload_mask = workload_mask = 1 << workload_type;
+ workload_mask = 1 << workload_type;
/* Add optimizations for SMU13.0.0/10. Reuse the power saving profile */
if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) &&
@@ -2555,12 +2661,22 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
workload_mask |= 1 << workload_type;
}
+ smu->workload_mask |= workload_mask;
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_SetWorkloadMask,
- workload_mask,
+ smu->workload_mask,
NULL);
- if (!ret)
- smu->workload_mask = selected_workload_mask;
+ if (!ret) {
+ smu_cmn_assign_power_profile(smu);
+ if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {
+ workload_type = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_WORKLOAD,
+ PP_SMC_POWER_PROFILE_FULLSCREEN3D);
+ smu->power_profile_mode = smu->workload_mask & (1 << workload_type)
+ ? PP_SMC_POWER_PROFILE_FULLSCREEN3D
+ : PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ }
+ }
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
index a71b7c0803f1..f5db181ef489 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
@@ -193,7 +193,9 @@ static int smu_v13_0_5_system_features_control(struct smu_context *smu, bool en)
return ret;
}
-static int smu_v13_0_5_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+static int smu_v13_0_5_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable,
+ int inst)
{
int ret = 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index 7ebb675c5786..ab3c93ddce46 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -96,7 +96,6 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_14.bin");
#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xE0
#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0x5
#define LINK_SPEED_MAX 4
-
#define SMU_13_0_6_DSCLK_THRESHOLD 140
#define MCA_BANK_IPID(_ip, _hwid, _type) \
@@ -370,7 +369,7 @@ static int smu_v13_0_6_tables_init(struct smu_context *smu)
return -ENOMEM;
smu_table->metrics_time = 0;
- smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_6);
+ smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_7);
smu_table->gpu_metrics_table =
kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
if (!smu_table->gpu_metrics_table) {
@@ -2321,8 +2320,8 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
{
bool per_inst, smu_13_0_6_per_inst, smu_13_0_14_per_inst, apu_per_inst;
struct smu_table_context *smu_table = &smu->smu_table;
- struct gpu_metrics_v1_6 *gpu_metrics =
- (struct gpu_metrics_v1_6 *)smu_table->gpu_metrics_table;
+ struct gpu_metrics_v1_7 *gpu_metrics =
+ (struct gpu_metrics_v1_7 *)smu_table->gpu_metrics_table;
bool flag = smu_v13_0_6_is_unified_metrics(smu);
int ret = 0, xcc_id, inst, i, j, k, idx;
struct amdgpu_device *adev = smu->adev;
@@ -2341,7 +2340,7 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
metrics_a = (MetricsTableA_t *)metrics_x;
- smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 6);
+ smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 7);
gpu_metrics->temperature_hotspot =
SMUQ10_ROUND(GET_METRIC_FIELD(MaxSocketTemperature, flag));
@@ -2448,6 +2447,9 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
SMUQ10_ROUND(GET_METRIC_FIELD(XgmiReadDataSizeAcc, flag)[i]);
gpu_metrics->xgmi_write_data_acc[i] =
SMUQ10_ROUND(GET_METRIC_FIELD(XgmiWriteDataSizeAcc, flag)[i]);
+ ret = amdgpu_get_xgmi_link_status(adev, i);
+ if (ret >= 0)
+ gpu_metrics->xgmi_link_status[i] = ret;
}
gpu_metrics->num_partition = adev->xcp_mgr->num_xcps;
@@ -3041,6 +3043,16 @@ static int mmhub_err_codes[] = {
CODE_VML2, CODE_VML2_WALKER, CODE_MMCANE,
};
+static int vcn_err_codes[] = {
+ CODE_VIDD, CODE_VIDV,
+};
+static int jpeg_err_codes[] = {
+ CODE_JPEG0S, CODE_JPEG0D, CODE_JPEG1S, CODE_JPEG1D,
+ CODE_JPEG2S, CODE_JPEG2D, CODE_JPEG3S, CODE_JPEG3D,
+ CODE_JPEG4S, CODE_JPEG4D, CODE_JPEG5S, CODE_JPEG5D,
+ CODE_JPEG6S, CODE_JPEG6D, CODE_JPEG7S, CODE_JPEG7D,
+};
+
static const struct mca_ras_info mca_ras_table[] = {
{
.blkid = AMDGPU_RAS_BLOCK__UMC,
@@ -3069,6 +3081,20 @@ static const struct mca_ras_info mca_ras_table[] = {
.blkid = AMDGPU_RAS_BLOCK__XGMI_WAFL,
.ip = AMDGPU_MCA_IP_PCS_XGMI,
.get_err_count = mca_pcs_xgmi_mca_get_err_count,
+ }, {
+ .blkid = AMDGPU_RAS_BLOCK__VCN,
+ .ip = AMDGPU_MCA_IP_SMU,
+ .err_code_array = vcn_err_codes,
+ .err_code_count = ARRAY_SIZE(vcn_err_codes),
+ .get_err_count = mca_smu_mca_get_err_count,
+ .bank_is_valid = mca_smu_bank_is_valid,
+ }, {
+ .blkid = AMDGPU_RAS_BLOCK__JPEG,
+ .ip = AMDGPU_MCA_IP_SMU,
+ .err_code_array = jpeg_err_codes,
+ .err_code_count = ARRAY_SIZE(jpeg_err_codes),
+ .get_err_count = mca_smu_mca_get_err_count,
+ .bank_is_valid = mca_smu_bank_is_valid,
},
};
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 23f13388455f..4fd0354bd312 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
@@ -83,6 +83,8 @@
#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8
#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9
#define PP_OD_FEATURE_FAN_MINIMUM_PWM 10
+#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE 11
+#define PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP 12
#define LINK_SPEED_MAX 3
@@ -1119,6 +1121,14 @@ static void smu_v13_0_7_get_od_setting_limits(struct smu_context *smu,
od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
od_max_setting = overdrive_upperlimits->FanMinimumPwm;
break;
+ case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE:
+ od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable;
+ od_max_setting = overdrive_upperlimits->FanZeroRpmEnable;
+ break;
+ case PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP:
+ od_min_setting = overdrive_lowerlimits->FanZeroRpmStopTemp;
+ od_max_setting = overdrive_upperlimits->FanZeroRpmStopTemp;
+ break;
default:
od_min_setting = od_max_setting = INT_MAX;
break;
@@ -1439,6 +1449,42 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
min_value, max_value);
break;
+ case SMU_OD_FAN_ZERO_RPM_ENABLE:
+ if (!smu_v13_0_7_is_od_feature_supported(smu,
+ PP_OD_FEATURE_ZERO_FAN_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n");
+ size += sysfs_emit_at(buf, size, "%d\n",
+ (int)od_table->OverDriveTable.FanZeroRpmEnable);
+
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+ &min_value,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n",
+ min_value, max_value);
+ break;
+
+ case SMU_OD_FAN_ZERO_RPM_STOP_TEMP:
+ if (!smu_v13_0_7_is_od_feature_supported(smu,
+ PP_OD_FEATURE_ZERO_FAN_BIT))
+ break;
+
+ size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_STOP_TEMPERATURE:\n");
+ size += sysfs_emit_at(buf, size, "%d\n",
+ (int)od_table->OverDriveTable.FanZeroRpmStopTemp);
+
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP,
+ &min_value,
+ &max_value);
+ size += sysfs_emit_at(buf, size, "ZERO_RPM_STOP_TEMPERATURE: %u %u\n",
+ min_value, max_value);
+ break;
+
case SMU_OD_RANGE:
if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
@@ -1535,6 +1581,16 @@ static int smu_v13_0_7_od_restore_table_single(struct smu_context *smu, long inp
od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
+ case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+ od_table->OverDriveTable.FanZeroRpmEnable =
+ boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
+ case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
+ od_table->OverDriveTable.FanZeroRpmStopTemp =
+ boot_overdrive_table->OverDriveTable.FanZeroRpmStopTemp;
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
default:
dev_info(adev->dev, "Invalid table index: %ld\n", input);
return -EINVAL;
@@ -1828,6 +1884,48 @@ static int smu_v13_0_7_od_edit_dpm_table(struct smu_context *smu,
od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
break;
+ case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
+ if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
+ dev_warn(adev->dev, "Zero RPM setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
+ &minimum,
+ &maximum);
+ if (input[0] < minimum ||
+ input[0] > maximum) {
+ dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n",
+ input[0], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.FanZeroRpmEnable = input[0];
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
+
+ case PP_OD_EDIT_FAN_ZERO_RPM_STOP_TEMP:
+ if (!smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
+ dev_warn(adev->dev, "Zero RPM setting not supported!\n");
+ return -ENOTSUPP;
+ }
+
+ smu_v13_0_7_get_od_setting_limits(smu,
+ PP_OD_FEATURE_FAN_ZERO_RPM_STOP_TEMP,
+ &minimum,
+ &maximum);
+ if (input[0] < minimum ||
+ input[0] > maximum) {
+ dev_info(adev->dev, "zero RPM stop temperature setting(%ld) must be within [%d, %d]!\n",
+ input[0], minimum, maximum);
+ return -EINVAL;
+ }
+
+ od_table->OverDriveTable.FanZeroRpmStopTemp = input[0];
+ od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
+ break;
+
case PP_OD_RESTORE_DEFAULT_TABLE:
if (size == 1) {
ret = smu_v13_0_7_od_restore_table_single(smu, input[0]);
@@ -2049,6 +2147,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
+ gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
@@ -2094,7 +2194,11 @@ static void smu_v13_0_7_set_supported_od_feature_mask(struct smu_context *smu)
OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
- OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET;
+ OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_RETRIEVE |
+ OD_OPS_SUPPORT_FAN_ZERO_RPM_STOP_TEMP_SET;
}
static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
@@ -2160,6 +2264,10 @@ static int smu_v13_0_7_set_default_od_settings(struct smu_context *smu)
user_od_table_bak.OverDriveTable.FanTargetTemperature;
user_od_table->OverDriveTable.FanMinimumPwm =
user_od_table_bak.OverDriveTable.FanMinimumPwm;
+ user_od_table->OverDriveTable.FanZeroRpmEnable =
+ user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
+ user_od_table->OverDriveTable.FanZeroRpmStopTemp =
+ user_od_table_bak.OverDriveTable.FanZeroRpmStopTemp;
}
smu_v13_0_7_set_supported_od_feature_mask(smu);
@@ -2487,13 +2595,14 @@ static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *inp
smu->power_profile_mode);
if (workload_type < 0)
return -EINVAL;
+
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
- 1 << workload_type, NULL);
+ smu->workload_mask, NULL);
if (ret)
dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
else
- smu->workload_mask = (1 << workload_type);
+ smu_cmn_assign_power_profile(smu);
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
index 71d58c8c8cc0..73b4506ef5a8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
@@ -220,7 +220,9 @@ static int yellow_carp_system_features_control(struct smu_context *smu, bool en)
return ret;
}
-static int yellow_carp_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+static int yellow_carp_dpm_set_vcn_enable(struct smu_context *smu,
+ bool enable,
+ int inst)
{
int ret = 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
index f7745eaf118e..a87040cb2f2e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
@@ -49,7 +49,7 @@
#define regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0_BASE_IDX 0
const int decoded_link_speed[5] = {1, 2, 3, 4, 5};
-const int decoded_link_width[7] = {0, 1, 2, 4, 8, 12, 16};
+const int decoded_link_width[8] = {0, 1, 2, 4, 8, 12, 16, 32};
/*
* DO NOT use these for err/warn/info/debug messages.
* Use dev_err, dev_warn, dev_info and dev_dbg instead.
@@ -1507,7 +1507,8 @@ int smu_v14_0_set_single_dpm_table(struct smu_context *smu,
}
int smu_v14_0_set_vcn_enable(struct smu_context *smu,
- bool enable)
+ bool enable,
+ int inst)
{
struct amdgpu_device *adev = smu->adev;
int i, ret = 0;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
index 8798ebfcea83..84f9b007b59f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
@@ -1132,7 +1132,7 @@ static int smu_v14_0_common_get_dpm_level_count(struct smu_context *smu,
static int smu_v14_0_0_print_clk_levels(struct smu_context *smu,
enum smu_clk_type clk_type, char *buf)
{
- int i, size = 0, ret = 0;
+ int i, idx, ret = 0, size = 0;
uint32_t cur_value = 0, value = 0, count = 0;
uint32_t min, max;
@@ -1168,7 +1168,8 @@ static int smu_v14_0_0_print_clk_levels(struct smu_context *smu,
break;
for (i = 0; i < count; i++) {
- ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, i, &value);
+ idx = (clk_type == SMU_MCLK) ? (count - i - 1) : i;
+ ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, idx, &value);
if (ret)
break;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index cefe10b95d8e..687a0f5ac94f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -367,54 +367,6 @@ static int smu_v14_0_2_store_powerplay_table(struct smu_context *smu)
return 0;
}
-#ifndef atom_smc_dpm_info_table_14_0_0
-struct atom_smc_dpm_info_table_14_0_0 {
- struct atom_common_table_header table_header;
- BoardTable_t BoardTable;
-};
-#endif
-
-static int smu_v14_0_2_append_powerplay_table(struct smu_context *smu)
-{
- struct smu_table_context *table_context = &smu->smu_table;
- PPTable_t *smc_pptable = table_context->driver_pptable;
- struct atom_smc_dpm_info_table_14_0_0 *smc_dpm_table;
- BoardTable_t *BoardTable = &smc_pptable->BoardTable;
- int index, ret;
-
- index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
- smc_dpm_info);
-
- ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
- (uint8_t **)&smc_dpm_table);
- if (ret)
- return ret;
-
- memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t));
-
- return 0;
-}
-
-#if 0
-static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
- void **table,
- uint32_t *size)
-{
- struct smu_table_context *smu_table = &smu->smu_table;
- void *combo_pptable = smu_table->combo_pptable;
- int ret = 0;
-
- ret = smu_cmn_get_combo_pptable(smu);
- if (ret)
- return ret;
-
- *table = combo_pptable;
- *size = sizeof(struct smu_14_0_powerplay_table);
-
- return 0;
-}
-#endif
-
static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
void **table,
uint32_t *size)
@@ -436,16 +388,12 @@ static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
static int smu_v14_0_2_setup_pptable(struct smu_context *smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
- struct amdgpu_device *adev = smu->adev;
int ret = 0;
if (amdgpu_sriov_vf(smu->adev))
return 0;
- if (!adev->scpm_enabled)
- ret = smu_v14_0_setup_pptable(smu);
- else
- ret = smu_v14_0_2_get_pptable_from_pmfw(smu,
+ ret = smu_v14_0_2_get_pptable_from_pmfw(smu,
&smu_table->power_play_table,
&smu_table->power_play_table_size);
if (ret)
@@ -455,16 +403,6 @@ static int smu_v14_0_2_setup_pptable(struct smu_context *smu)
if (ret)
return ret;
- /*
- * With SCPM enabled, the operation below will be handled
- * by PSP. Driver involvment is unnecessary and useless.
- */
- if (!adev->scpm_enabled) {
- ret = smu_v14_0_2_append_powerplay_table(smu);
- if (ret)
- return ret;
- }
-
ret = smu_v14_0_2_check_powerplay_table(smu);
if (ret)
return ret;
@@ -1235,13 +1173,15 @@ static int smu_v14_0_2_print_clk_levels(struct smu_context *smu,
(pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
(pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
(pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
- (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "",
+ (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," :
+ (pcie_table->pcie_gen[i] == 4) ? "32.0GT/s," : "",
(pcie_table->pcie_lane[i] == 1) ? "x1" :
(pcie_table->pcie_lane[i] == 2) ? "x2" :
(pcie_table->pcie_lane[i] == 3) ? "x4" :
(pcie_table->pcie_lane[i] == 4) ? "x8" :
(pcie_table->pcie_lane[i] == 5) ? "x12" :
- (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
+ (pcie_table->pcie_lane[i] == 6) ? "x16" :
+ (pcie_table->pcie_lane[i] == 7) ? "x32" : "",
pcie_table->clk_freq[i],
(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
@@ -1525,15 +1465,35 @@ static int smu_v14_0_2_update_pcie_parameters(struct smu_context *smu,
struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
struct smu_14_0_pcie_table *pcie_table =
&dpm_context->dpm_tables.pcie_table;
+ int num_of_levels = pcie_table->num_of_link_levels;
uint32_t smu_pcie_arg;
int ret, i;
- for (i = 0; i < pcie_table->num_of_link_levels; i++) {
- if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ if (!num_of_levels)
+ return 0;
+
+ if (!(smu->adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
+ if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap)
+ pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1];
+
+ if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap)
+ pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1];
+
+ /* Force all levels to use the same settings */
+ for (i = 0; i < num_of_levels; i++) {
pcie_table->pcie_gen[i] = pcie_gen_cap;
- if (pcie_table->pcie_lane[i] > pcie_width_cap)
pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ } else {
+ for (i = 0; i < num_of_levels; i++) {
+ if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ if (pcie_table->pcie_lane[i] > pcie_width_cap)
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ }
+ for (i = 0; i < num_of_levels; i++) {
smu_pcie_arg = i << 16;
smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
smu_pcie_arg |= pcie_table->pcie_lane[i];
@@ -1857,12 +1817,11 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
if (workload_type < 0)
return -EINVAL;
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetWorkloadMask,
- 1 << workload_type,
- NULL);
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+ smu->workload_mask, NULL);
+
if (!ret)
- smu->workload_mask = 1 << workload_type;
+ smu_cmn_assign_power_profile(smu);
return ret;
}
@@ -2786,7 +2745,6 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
.check_fw_status = smu_v14_0_check_fw_status,
.setup_pptable = smu_v14_0_2_setup_pptable,
.check_fw_version = smu_v14_0_check_fw_version,
- .write_pptable = smu_cmn_write_pptable,
.set_driver_table_location = smu_v14_0_set_driver_table_location,
.system_features_control = smu_v14_0_system_features_control,
.set_allowed_mask = smu_v14_0_set_allowed_mask,
@@ -2817,7 +2775,6 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
.get_unique_id = smu_v14_0_2_get_unique_id,
.get_power_limit = smu_v14_0_2_get_power_limit,
.set_power_limit = smu_v14_0_2_set_power_limit,
- .set_power_source = smu_v14_0_set_power_source,
.get_power_profile_mode = smu_v14_0_2_get_power_profile_mode,
.set_power_profile_mode = smu_v14_0_2_set_power_profile_mode,
.run_btc = smu_v14_0_run_btc,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 843f00c9e407..dbbd3759bff3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1081,6 +1081,9 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev)
case METRICS_VERSION(1, 6):
structure_size = sizeof(struct gpu_metrics_v1_6);
break;
+ case METRICS_VERSION(1, 7):
+ structure_size = sizeof(struct gpu_metrics_v1_7);
+ break;
case METRICS_VERSION(2, 0):
structure_size = sizeof(struct gpu_metrics_v2_0);
break;
@@ -1141,6 +1144,14 @@ int smu_cmn_set_mp1_state(struct smu_context *smu,
return ret;
}
+void smu_cmn_assign_power_profile(struct smu_context *smu)
+{
+ uint32_t index;
+ index = fls(smu->workload_mask);
+ index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+ smu->power_profile_mode = smu->workload_setting[index];
+}
+
bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)
{
struct pci_dev *p = NULL;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index 1de685defe85..8a801e389659 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -130,6 +130,8 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev);
int smu_cmn_set_mp1_state(struct smu_context *smu,
enum pp_mp1_state mp1_state);
+void smu_cmn_assign_power_profile(struct smu_context *smu);
+
/*
* Helper function to make sysfs_emit_at() happy. Align buf to
* the current page boundary and record the offset.
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 609f4d0ac93d..6b4664d91faa 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -90,6 +90,17 @@ config DRM_FSL_LDB
help
Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
+config DRM_ITE_IT6263
+ tristate "ITE IT6263 LVDS/HDMI bridge"
+ depends on OF
+ select DRM_DISPLAY_HDMI_STATE_HELPER
+ select DRM_DISPLAY_HELPER
+ select DRM_BRIDGE_CONNECTOR
+ select DRM_KMS_HELPER
+ select REGMAP_I2C
+ help
+ ITE IT6263 LVDS to HDMI bridge chip driver.
+
config DRM_ITE_IT6505
tristate "ITE IT6505 DisplayPort bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 3daf803ce80b..97304b429a53 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
obj-$(CONFIG_DRM_FSL_LDB) += fsl-ldb.o
+obj-$(CONFIG_DRM_ITE_IT6263) += ite-it6263.o
obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o
obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o
diff --git a/drivers/gpu/drm/bridge/ite-it6263.c b/drivers/gpu/drm/bridge/ite-it6263.c
new file mode 100644
index 000000000000..cbabd4e20d3e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ite-it6263.c
@@ -0,0 +1,898 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/hdmi.h>
+#include <linux/i2c.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/display/drm_hdmi_state_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_state_helper.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_edid.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+
+/* -----------------------------------------------------------------------------
+ * LVDS registers
+ */
+
+/* LVDS software reset registers */
+#define LVDS_REG_05 0x05
+#define REG_SOFT_P_RST BIT(1)
+
+/* LVDS system configuration registers */
+/* 0x0b */
+#define LVDS_REG_0B 0x0b
+#define REG_SSC_PCLK_RF BIT(0)
+#define REG_LVDS_IN_SWAP BIT(1)
+
+/* LVDS test pattern gen control registers */
+/* 0x2c */
+#define LVDS_REG_2C 0x2c
+#define REG_COL_DEP GENMASK(1, 0)
+#define BIT8 FIELD_PREP(REG_COL_DEP, 1)
+#define OUT_MAP BIT(4)
+#define JEIDA 0
+#define REG_DESSC_ENB BIT(6)
+#define DMODE BIT(7)
+#define DISO BIT(7)
+#define SISO 0
+
+#define LVDS_REG_3C 0x3c
+#define LVDS_REG_3F 0x3f
+#define LVDS_REG_47 0x47
+#define LVDS_REG_48 0x48
+#define LVDS_REG_4F 0x4f
+#define LVDS_REG_52 0x52
+
+/* -----------------------------------------------------------------------------
+ * HDMI registers are separated into three banks:
+ * 1) HDMI register common bank: 0x00 ~ 0x2f
+ */
+
+/* HDMI genernal registers */
+#define HDMI_REG_SW_RST 0x04
+#define SOFTREF_RST BIT(5)
+#define SOFTA_RST BIT(4)
+#define SOFTV_RST BIT(3)
+#define AUD_RST BIT(2)
+#define HDCP_RST BIT(0)
+#define HDMI_RST_ALL (SOFTREF_RST | SOFTA_RST | SOFTV_RST | \
+ AUD_RST | HDCP_RST)
+
+#define HDMI_REG_SYS_STATUS 0x0e
+#define HPDETECT BIT(6)
+#define TXVIDSTABLE BIT(4)
+
+#define HDMI_REG_BANK_CTRL 0x0f
+#define REG_BANK_SEL BIT(0)
+
+/* HDMI System DDC control registers */
+#define HDMI_REG_DDC_MASTER_CTRL 0x10
+#define MASTER_SEL_HOST BIT(0)
+
+#define HDMI_REG_DDC_HEADER 0x11
+
+#define HDMI_REG_DDC_REQOFF 0x12
+#define HDMI_REG_DDC_REQCOUNT 0x13
+#define HDMI_REG_DDC_EDIDSEG 0x14
+
+#define HDMI_REG_DDC_CMD 0x15
+#define DDC_CMD_EDID_READ 0x3
+#define DDC_CMD_FIFO_CLR 0x9
+
+#define HDMI_REG_DDC_STATUS 0x16
+#define DDC_DONE BIT(7)
+#define DDC_NOACK BIT(5)
+#define DDC_WAITBUS BIT(4)
+#define DDC_ARBILOSE BIT(3)
+#define DDC_ERROR (DDC_NOACK | DDC_WAITBUS | DDC_ARBILOSE)
+
+#define HDMI_DDC_FIFO_BYTES 32
+#define HDMI_REG_DDC_READFIFO 0x17
+#define HDMI_REG_LVDS_PORT 0x1d /* LVDS input control I2C addr */
+#define HDMI_REG_LVDS_PORT_EN 0x1e
+#define LVDS_INPUT_CTRL_I2C_ADDR 0x33
+
+/* -----------------------------------------------------------------------------
+ * 2) HDMI register bank0: 0x30 ~ 0xff
+ */
+
+/* HDMI AFE registers */
+#define HDMI_REG_AFE_DRV_CTRL 0x61
+#define AFE_DRV_PWD BIT(5)
+#define AFE_DRV_RST BIT(4)
+
+#define HDMI_REG_AFE_XP_CTRL 0x62
+#define AFE_XP_GAINBIT BIT(7)
+#define AFE_XP_ER0 BIT(4)
+#define AFE_XP_RESETB BIT(3)
+
+#define HDMI_REG_AFE_ISW_CTRL 0x63
+
+#define HDMI_REG_AFE_IP_CTRL 0x64
+#define AFE_IP_GAINBIT BIT(7)
+#define AFE_IP_ER0 BIT(3)
+#define AFE_IP_RESETB BIT(2)
+
+/* HDMI input data format registers */
+#define HDMI_REG_INPUT_MODE 0x70
+#define IN_RGB 0x00
+
+/* HDMI general control registers */
+#define HDMI_REG_HDMI_MODE 0xc0
+#define TX_HDMI_MODE BIT(0)
+
+#define HDMI_REG_GCP 0xc1
+#define AVMUTE BIT(0)
+#define HDMI_COLOR_DEPTH GENMASK(6, 4)
+#define HDMI_COLOR_DEPTH_24 FIELD_PREP(HDMI_COLOR_DEPTH, 4)
+
+#define HDMI_REG_PKT_GENERAL_CTRL 0xc6
+#define HDMI_REG_AVI_INFOFRM_CTRL 0xcd
+#define ENABLE_PKT BIT(0)
+#define REPEAT_PKT BIT(1)
+
+/* -----------------------------------------------------------------------------
+ * 3) HDMI register bank1: 0x130 ~ 0x1ff (HDMI packet registers)
+ */
+
+/* AVI packet registers */
+#define HDMI_REG_AVI_DB1 0x158
+#define HDMI_REG_AVI_DB2 0x159
+#define HDMI_REG_AVI_DB3 0x15a
+#define HDMI_REG_AVI_DB4 0x15b
+#define HDMI_REG_AVI_DB5 0x15c
+#define HDMI_REG_AVI_CSUM 0x15d
+#define HDMI_REG_AVI_DB6 0x15e
+#define HDMI_REG_AVI_DB7 0x15f
+#define HDMI_REG_AVI_DB8 0x160
+#define HDMI_REG_AVI_DB9 0x161
+#define HDMI_REG_AVI_DB10 0x162
+#define HDMI_REG_AVI_DB11 0x163
+#define HDMI_REG_AVI_DB12 0x164
+#define HDMI_REG_AVI_DB13 0x165
+
+#define HDMI_AVI_DB_CHUNK1_SIZE (HDMI_REG_AVI_DB5 - HDMI_REG_AVI_DB1 + 1)
+#define HDMI_AVI_DB_CHUNK2_SIZE (HDMI_REG_AVI_DB13 - HDMI_REG_AVI_DB6 + 1)
+
+/* IT6263 data sheet Rev0.8: LVDS RX supports input clock rate up to 150MHz. */
+#define MAX_PIXEL_CLOCK_KHZ 150000
+
+/* IT6263 programming guide Ver0.90: PCLK_HIGH for TMDS clock over 80MHz. */
+#define HIGH_PIXEL_CLOCK_KHZ 80000
+
+/*
+ * IT6263 data sheet Rev0.8: HDMI TX supports link speeds of up to 2.25Gbps
+ * (link clock rate of 225MHz).
+ */
+#define MAX_HDMI_TMDS_CHAR_RATE_HZ 225000000
+
+struct it6263 {
+ struct device *dev;
+ struct i2c_client *hdmi_i2c;
+ struct i2c_client *lvds_i2c;
+ struct regmap *hdmi_regmap;
+ struct regmap *lvds_regmap;
+ struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
+ int lvds_data_mapping;
+ bool lvds_dual_link;
+ bool lvds_link12_swap;
+};
+
+static inline struct it6263 *bridge_to_it6263(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct it6263, bridge);
+}
+
+static bool it6263_hdmi_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case HDMI_REG_SW_RST:
+ case HDMI_REG_BANK_CTRL:
+ case HDMI_REG_DDC_MASTER_CTRL:
+ case HDMI_REG_DDC_HEADER:
+ case HDMI_REG_DDC_REQOFF:
+ case HDMI_REG_DDC_REQCOUNT:
+ case HDMI_REG_DDC_EDIDSEG:
+ case HDMI_REG_DDC_CMD:
+ case HDMI_REG_LVDS_PORT:
+ case HDMI_REG_LVDS_PORT_EN:
+ case HDMI_REG_AFE_DRV_CTRL:
+ case HDMI_REG_AFE_XP_CTRL:
+ case HDMI_REG_AFE_ISW_CTRL:
+ case HDMI_REG_AFE_IP_CTRL:
+ case HDMI_REG_INPUT_MODE:
+ case HDMI_REG_HDMI_MODE:
+ case HDMI_REG_GCP:
+ case HDMI_REG_PKT_GENERAL_CTRL:
+ case HDMI_REG_AVI_INFOFRM_CTRL:
+ case HDMI_REG_AVI_DB1:
+ case HDMI_REG_AVI_DB2:
+ case HDMI_REG_AVI_DB3:
+ case HDMI_REG_AVI_DB4:
+ case HDMI_REG_AVI_DB5:
+ case HDMI_REG_AVI_CSUM:
+ case HDMI_REG_AVI_DB6:
+ case HDMI_REG_AVI_DB7:
+ case HDMI_REG_AVI_DB8:
+ case HDMI_REG_AVI_DB9:
+ case HDMI_REG_AVI_DB10:
+ case HDMI_REG_AVI_DB11:
+ case HDMI_REG_AVI_DB12:
+ case HDMI_REG_AVI_DB13:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool it6263_hdmi_readable_reg(struct device *dev, unsigned int reg)
+{
+ if (it6263_hdmi_writeable_reg(dev, reg))
+ return true;
+
+ switch (reg) {
+ case HDMI_REG_SYS_STATUS:
+ case HDMI_REG_DDC_STATUS:
+ case HDMI_REG_DDC_READFIFO:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool it6263_hdmi_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case HDMI_REG_SW_RST:
+ case HDMI_REG_SYS_STATUS:
+ case HDMI_REG_DDC_STATUS:
+ case HDMI_REG_DDC_READFIFO:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_range_cfg it6263_hdmi_range_cfg = {
+ .range_min = 0x00,
+ .range_max = HDMI_REG_AVI_DB13,
+ .selector_reg = HDMI_REG_BANK_CTRL,
+ .selector_mask = REG_BANK_SEL,
+ .selector_shift = 0,
+ .window_start = 0x00,
+ .window_len = 0x100,
+};
+
+static const struct regmap_config it6263_hdmi_regmap_config = {
+ .name = "it6263-hdmi",
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = it6263_hdmi_writeable_reg,
+ .readable_reg = it6263_hdmi_readable_reg,
+ .volatile_reg = it6263_hdmi_volatile_reg,
+ .max_register = HDMI_REG_AVI_DB13,
+ .ranges = &it6263_hdmi_range_cfg,
+ .num_ranges = 1,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static bool it6263_lvds_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case LVDS_REG_05:
+ case LVDS_REG_0B:
+ case LVDS_REG_2C:
+ case LVDS_REG_3C:
+ case LVDS_REG_3F:
+ case LVDS_REG_47:
+ case LVDS_REG_48:
+ case LVDS_REG_4F:
+ case LVDS_REG_52:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool it6263_lvds_readable_reg(struct device *dev, unsigned int reg)
+{
+ return it6263_lvds_writeable_reg(dev, reg);
+}
+
+static bool it6263_lvds_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return reg == LVDS_REG_05;
+}
+
+static const struct regmap_config it6263_lvds_regmap_config = {
+ .name = "it6263-lvds",
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = it6263_lvds_writeable_reg,
+ .readable_reg = it6263_lvds_readable_reg,
+ .volatile_reg = it6263_lvds_volatile_reg,
+ .max_register = LVDS_REG_52,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static const char * const it6263_supplies[] = {
+ "ivdd", "ovdd", "txavcc18", "txavcc33", "pvcc1", "pvcc2",
+ "avcc", "anvdd", "apvdd"
+};
+
+static int it6263_parse_dt(struct it6263 *it)
+{
+ struct device *dev = it->dev;
+ struct device_node *port0, *port1;
+ int ret = 0;
+
+ it->lvds_data_mapping = drm_of_lvds_get_data_mapping(dev->of_node);
+ if (it->lvds_data_mapping < 0) {
+ dev_err(dev, "%pOF: invalid or missing %s DT property: %d\n",
+ dev->of_node, "data-mapping", it->lvds_data_mapping);
+ return it->lvds_data_mapping;
+ }
+
+ it->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0);
+ if (IS_ERR(it->next_bridge))
+ return dev_err_probe(dev, PTR_ERR(it->next_bridge),
+ "failed to get next bridge\n");
+
+ port0 = of_graph_get_port_by_id(dev->of_node, 0);
+ port1 = of_graph_get_port_by_id(dev->of_node, 1);
+ if (port0 && port1) {
+ int order;
+
+ it->lvds_dual_link = true;
+ order = drm_of_lvds_get_dual_link_pixel_order_sink(port0, port1);
+ if (order < 0) {
+ dev_err(dev,
+ "failed to get dual link pixel order: %d\n",
+ order);
+ ret = order;
+ } else if (order == DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
+ it->lvds_link12_swap = true;
+ }
+ } else if (port1) {
+ ret = -EINVAL;
+ dev_err(dev, "single input LVDS port1 is not supported\n");
+ } else if (!port0) {
+ ret = -EINVAL;
+ dev_err(dev, "no input LVDS port\n");
+ }
+
+ of_node_put(port0);
+ of_node_put(port1);
+
+ return ret;
+}
+
+static inline void it6263_hw_reset(struct gpio_desc *reset_gpio)
+{
+ if (!reset_gpio)
+ return;
+
+ gpiod_set_value_cansleep(reset_gpio, 0);
+ fsleep(1000);
+ gpiod_set_value_cansleep(reset_gpio, 1);
+ /* The chip maker says the low pulse should be at least 40ms. */
+ fsleep(40000);
+ gpiod_set_value_cansleep(reset_gpio, 0);
+ /* addtional time to wait the high voltage to be stable */
+ fsleep(5000);
+}
+
+static inline int it6263_lvds_set_i2c_addr(struct it6263 *it)
+{
+ int ret;
+
+ ret = regmap_write(it->hdmi_regmap, HDMI_REG_LVDS_PORT,
+ LVDS_INPUT_CTRL_I2C_ADDR << 1);
+ if (ret)
+ return ret;
+
+ return regmap_write(it->hdmi_regmap, HDMI_REG_LVDS_PORT_EN, BIT(0));
+}
+
+static inline void it6263_lvds_reset(struct it6263 *it)
+{
+ /* AFE PLL reset */
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_3C, BIT(0), 0x0);
+ fsleep(1000);
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_3C, BIT(0), BIT(0));
+
+ /* software pixel clock domain reset */
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_05, REG_SOFT_P_RST,
+ REG_SOFT_P_RST);
+ fsleep(1000);
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_05, REG_SOFT_P_RST, 0x0);
+ fsleep(10000);
+}
+
+static inline void it6263_lvds_set_interface(struct it6263 *it)
+{
+ /* color depth */
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, REG_COL_DEP, BIT8);
+ /* output mapping */
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, OUT_MAP, JEIDA);
+
+ if (it->lvds_dual_link) {
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, DMODE, DISO);
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_52, BIT(1), BIT(1));
+ } else {
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, DMODE, SISO);
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_52, BIT(1), 0);
+ }
+}
+
+static inline void it6263_lvds_set_afe(struct it6263 *it)
+{
+ regmap_write(it->lvds_regmap, LVDS_REG_3C, 0xaa);
+ regmap_write(it->lvds_regmap, LVDS_REG_3F, 0x02);
+ regmap_write(it->lvds_regmap, LVDS_REG_47, 0xaa);
+ regmap_write(it->lvds_regmap, LVDS_REG_48, 0x02);
+ regmap_write(it->lvds_regmap, LVDS_REG_4F, 0x11);
+
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_0B, REG_SSC_PCLK_RF,
+ REG_SSC_PCLK_RF);
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_3C, 0x07, 0);
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_2C, REG_DESSC_ENB,
+ REG_DESSC_ENB);
+}
+
+static inline void it6263_lvds_sys_cfg(struct it6263 *it)
+{
+ regmap_write_bits(it->lvds_regmap, LVDS_REG_0B, REG_LVDS_IN_SWAP,
+ it->lvds_link12_swap ? REG_LVDS_IN_SWAP : 0);
+}
+
+static inline void it6263_lvds_config(struct it6263 *it)
+{
+ it6263_lvds_reset(it);
+ it6263_lvds_set_interface(it);
+ it6263_lvds_set_afe(it);
+ it6263_lvds_sys_cfg(it);
+}
+
+static inline void it6263_hdmi_config(struct it6263 *it)
+{
+ regmap_write(it->hdmi_regmap, HDMI_REG_SW_RST, HDMI_RST_ALL);
+ regmap_write(it->hdmi_regmap, HDMI_REG_INPUT_MODE, IN_RGB);
+ regmap_write_bits(it->hdmi_regmap, HDMI_REG_GCP, HDMI_COLOR_DEPTH,
+ HDMI_COLOR_DEPTH_24);
+}
+
+static enum drm_connector_status it6263_detect(struct it6263 *it)
+{
+ unsigned int val;
+
+ regmap_read(it->hdmi_regmap, HDMI_REG_SYS_STATUS, &val);
+ if (val & HPDETECT)
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+}
+
+static int it6263_read_edid(void *data, u8 *buf, unsigned int block, size_t len)
+{
+ struct it6263 *it = data;
+ struct regmap *regmap = it->hdmi_regmap;
+ unsigned int start = (block % 2) * EDID_LENGTH;
+ unsigned int segment = block >> 1;
+ unsigned int count, val;
+ int ret;
+
+ regmap_write(regmap, HDMI_REG_DDC_MASTER_CTRL, MASTER_SEL_HOST);
+ regmap_write(regmap, HDMI_REG_DDC_HEADER, DDC_ADDR << 1);
+ regmap_write(regmap, HDMI_REG_DDC_EDIDSEG, segment);
+
+ while (len) {
+ /* clear DDC FIFO */
+ regmap_write(regmap, HDMI_REG_DDC_CMD, DDC_CMD_FIFO_CLR);
+
+ ret = regmap_read_poll_timeout(regmap, HDMI_REG_DDC_STATUS,
+ val, val & DDC_DONE,
+ 2000, 10000);
+ if (ret) {
+ dev_err(it->dev, "failed to clear DDC FIFO:%d\n", ret);
+ return ret;
+ }
+
+ count = len > HDMI_DDC_FIFO_BYTES ? HDMI_DDC_FIFO_BYTES : len;
+
+ /* fire the read command */
+ regmap_write(regmap, HDMI_REG_DDC_REQOFF, start);
+ regmap_write(regmap, HDMI_REG_DDC_REQCOUNT, count);
+ regmap_write(regmap, HDMI_REG_DDC_CMD, DDC_CMD_EDID_READ);
+
+ start += count;
+ len -= count;
+
+ ret = regmap_read_poll_timeout(regmap, HDMI_REG_DDC_STATUS, val,
+ val & (DDC_DONE | DDC_ERROR),
+ 20000, 250000);
+ if (ret && !(val & DDC_ERROR)) {
+ dev_err(it->dev, "failed to read EDID:%d\n", ret);
+ return ret;
+ }
+
+ if (val & DDC_ERROR) {
+ dev_err(it->dev, "DDC error\n");
+ return -EIO;
+ }
+
+ /* cache to buffer */
+ for (; count > 0; count--) {
+ regmap_read(regmap, HDMI_REG_DDC_READFIFO, &val);
+ *(buf++) = val;
+ }
+ }
+
+ return 0;
+}
+
+static int it6263_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)
+{
+ return drm_atomic_helper_connector_hdmi_check(conn_state->connector,
+ conn_state->state);
+}
+
+static void
+it6263_bridge_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct it6263 *it = bridge_to_it6263(bridge);
+
+ regmap_write_bits(it->hdmi_regmap, HDMI_REG_GCP, AVMUTE, AVMUTE);
+ regmap_write(it->hdmi_regmap, HDMI_REG_PKT_GENERAL_CTRL, 0);
+ regmap_write(it->hdmi_regmap, HDMI_REG_AFE_DRV_CTRL,
+ AFE_DRV_RST | AFE_DRV_PWD);
+}
+
+static void
+it6263_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct drm_atomic_state *state = old_bridge_state->base.state;
+ struct it6263 *it = bridge_to_it6263(bridge);
+ const struct drm_crtc_state *crtc_state;
+ struct regmap *regmap = it->hdmi_regmap;
+ const struct drm_display_mode *mode;
+ struct drm_connector *connector;
+ bool is_stable = false;
+ struct drm_crtc *crtc;
+ unsigned int val;
+ bool pclk_high;
+ int i, ret;
+
+ 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);
+ mode = &crtc_state->adjusted_mode;
+
+ regmap_write(regmap, HDMI_REG_HDMI_MODE, TX_HDMI_MODE);
+
+ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
+
+ /* HDMI AFE setup */
+ pclk_high = mode->clock > HIGH_PIXEL_CLOCK_KHZ;
+ regmap_write(regmap, HDMI_REG_AFE_DRV_CTRL, AFE_DRV_RST);
+ if (pclk_high)
+ regmap_write(regmap, HDMI_REG_AFE_XP_CTRL,
+ AFE_XP_GAINBIT | AFE_XP_RESETB);
+ else
+ regmap_write(regmap, HDMI_REG_AFE_XP_CTRL,
+ AFE_XP_ER0 | AFE_XP_RESETB);
+ regmap_write(regmap, HDMI_REG_AFE_ISW_CTRL, 0x10);
+ if (pclk_high)
+ regmap_write(regmap, HDMI_REG_AFE_IP_CTRL,
+ AFE_IP_GAINBIT | AFE_IP_RESETB);
+ else
+ regmap_write(regmap, HDMI_REG_AFE_IP_CTRL,
+ AFE_IP_ER0 | AFE_IP_RESETB);
+
+ /* HDMI software video reset */
+ regmap_write_bits(regmap, HDMI_REG_SW_RST, SOFTV_RST, SOFTV_RST);
+ fsleep(1000);
+ regmap_write_bits(regmap, HDMI_REG_SW_RST, SOFTV_RST, 0);
+
+ /* reconfigure LVDS and retry several times in case video is instable */
+ for (i = 0; i < 3; i++) {
+ ret = regmap_read_poll_timeout(regmap, HDMI_REG_SYS_STATUS, val,
+ val & TXVIDSTABLE,
+ 20000, 500000);
+ if (!ret) {
+ is_stable = true;
+ break;
+ }
+
+ it6263_lvds_config(it);
+ }
+
+ if (!is_stable)
+ dev_warn(it->dev, "failed to wait for video stable\n");
+
+ /* HDMI AFE reset release and power up */
+ regmap_write(regmap, HDMI_REG_AFE_DRV_CTRL, 0);
+
+ regmap_write_bits(regmap, HDMI_REG_GCP, AVMUTE, 0);
+
+ regmap_write(regmap, HDMI_REG_PKT_GENERAL_CTRL, ENABLE_PKT | REPEAT_PKT);
+}
+
+static enum drm_mode_status
+it6263_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+ unsigned long long rate;
+
+ rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+ if (rate == 0)
+ return MODE_NOCLOCK;
+
+ return bridge->funcs->hdmi_tmds_char_rate_valid(bridge, mode, rate);
+}
+
+static int it6263_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct it6263 *it = bridge_to_it6263(bridge);
+ struct drm_connector *connector;
+ int ret;
+
+ ret = drm_bridge_attach(bridge->encoder, it->next_bridge, bridge,
+ flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret < 0)
+ return ret;
+
+ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+ return 0;
+
+ connector = drm_bridge_connector_init(bridge->dev, bridge->encoder);
+ if (IS_ERR(connector)) {
+ ret = PTR_ERR(connector);
+ dev_err(it->dev, "failed to initialize bridge connector: %d\n",
+ ret);
+ return ret;
+ }
+
+ drm_connector_attach_encoder(connector, bridge->encoder);
+
+ return 0;
+}
+
+static enum drm_connector_status it6263_bridge_detect(struct drm_bridge *bridge)
+{
+ struct it6263 *it = bridge_to_it6263(bridge);
+
+ return it6263_detect(it);
+}
+
+static const struct drm_edid *
+it6263_bridge_edid_read(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ struct it6263 *it = bridge_to_it6263(bridge);
+
+ return drm_edid_read_custom(connector, it6263_read_edid, it);
+}
+
+static u32 *
+it6263_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts)
+{
+ struct it6263 *it = bridge_to_it6263(bridge);
+ u32 *input_fmts;
+
+ *num_input_fmts = 0;
+
+ if (it->lvds_data_mapping != MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA)
+ return NULL;
+
+ input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
+ if (!input_fmts)
+ return NULL;
+
+ input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
+ *num_input_fmts = 1;
+
+ return input_fmts;
+}
+
+static enum drm_mode_status
+it6263_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate)
+{
+ if (mode->clock > MAX_PIXEL_CLOCK_KHZ)
+ return MODE_CLOCK_HIGH;
+
+ if (tmds_rate > MAX_HDMI_TMDS_CHAR_RATE_HZ)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+static int it6263_hdmi_clear_infoframe(struct drm_bridge *bridge,
+ enum hdmi_infoframe_type type)
+{
+ struct it6263 *it = bridge_to_it6263(bridge);
+
+ if (type == HDMI_INFOFRAME_TYPE_AVI)
+ regmap_write(it->hdmi_regmap, HDMI_REG_AVI_INFOFRM_CTRL, 0);
+ else
+ dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
+
+ return 0;
+}
+
+static int it6263_hdmi_write_infoframe(struct drm_bridge *bridge,
+ enum hdmi_infoframe_type type,
+ const u8 *buffer, size_t len)
+{
+ struct it6263 *it = bridge_to_it6263(bridge);
+ struct regmap *regmap = it->hdmi_regmap;
+
+ if (type != HDMI_INFOFRAME_TYPE_AVI) {
+ dev_dbg(it->dev, "unsupported HDMI infoframe 0x%x\n", type);
+ return 0;
+ }
+
+ /* write the first AVI infoframe data byte chunk(DB1-DB5) */
+ regmap_bulk_write(regmap, HDMI_REG_AVI_DB1,
+ &buffer[HDMI_INFOFRAME_HEADER_SIZE],
+ HDMI_AVI_DB_CHUNK1_SIZE);
+
+ /* write the second AVI infoframe data byte chunk(DB6-DB13) */
+ regmap_bulk_write(regmap, HDMI_REG_AVI_DB6,
+ &buffer[HDMI_INFOFRAME_HEADER_SIZE +
+ HDMI_AVI_DB_CHUNK1_SIZE],
+ HDMI_AVI_DB_CHUNK2_SIZE);
+
+ /* write checksum */
+ regmap_write(regmap, HDMI_REG_AVI_CSUM, buffer[3]);
+
+ regmap_write(regmap, HDMI_REG_AVI_INFOFRM_CTRL, ENABLE_PKT | REPEAT_PKT);
+
+ return 0;
+}
+
+static const struct drm_bridge_funcs it6263_bridge_funcs = {
+ .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,
+ .attach = it6263_bridge_attach,
+ .mode_valid = it6263_bridge_mode_valid,
+ .atomic_disable = it6263_bridge_atomic_disable,
+ .atomic_enable = it6263_bridge_atomic_enable,
+ .atomic_check = it6263_bridge_atomic_check,
+ .detect = it6263_bridge_detect,
+ .edid_read = it6263_bridge_edid_read,
+ .atomic_get_input_bus_fmts = it6263_bridge_atomic_get_input_bus_fmts,
+ .hdmi_tmds_char_rate_valid = it6263_hdmi_tmds_char_rate_valid,
+ .hdmi_clear_infoframe = it6263_hdmi_clear_infoframe,
+ .hdmi_write_infoframe = it6263_hdmi_write_infoframe,
+};
+
+static int it6263_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct gpio_desc *reset_gpio;
+ struct it6263 *it;
+ int ret;
+
+ it = devm_kzalloc(dev, sizeof(*it), GFP_KERNEL);
+ if (!it)
+ return -ENOMEM;
+
+ it->dev = dev;
+ it->hdmi_i2c = client;
+
+ it->hdmi_regmap = devm_regmap_init_i2c(client,
+ &it6263_hdmi_regmap_config);
+ if (IS_ERR(it->hdmi_regmap))
+ return dev_err_probe(dev, PTR_ERR(it->hdmi_regmap),
+ "failed to init I2C regmap for HDMI\n");
+
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(reset_gpio),
+ "failed to get reset gpio\n");
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(it6263_supplies),
+ it6263_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get power supplies\n");
+
+ ret = it6263_parse_dt(it);
+ if (ret)
+ return ret;
+
+ it6263_hw_reset(reset_gpio);
+
+ ret = it6263_lvds_set_i2c_addr(it);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set I2C addr\n");
+
+ it->lvds_i2c = devm_i2c_new_dummy_device(dev, client->adapter,
+ LVDS_INPUT_CTRL_I2C_ADDR);
+ if (IS_ERR(it->lvds_i2c))
+ dev_err_probe(it->dev, PTR_ERR(it->lvds_i2c),
+ "failed to allocate I2C device for LVDS\n");
+
+ it->lvds_regmap = devm_regmap_init_i2c(it->lvds_i2c,
+ &it6263_lvds_regmap_config);
+ if (IS_ERR(it->lvds_regmap))
+ return dev_err_probe(dev, PTR_ERR(it->lvds_regmap),
+ "failed to init I2C regmap for LVDS\n");
+
+ it6263_lvds_config(it);
+ it6263_hdmi_config(it);
+
+ i2c_set_clientdata(client, it);
+
+ it->bridge.funcs = &it6263_bridge_funcs;
+ it->bridge.of_node = dev->of_node;
+ /* IT6263 chip doesn't support HPD interrupt. */
+ it->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
+ DRM_BRIDGE_OP_HDMI;
+ it->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+ it->bridge.vendor = "ITE";
+ it->bridge.product = "IT6263";
+
+ return devm_drm_bridge_add(dev, &it->bridge);
+}
+
+static const struct of_device_id it6263_of_match[] = {
+ { .compatible = "ite,it6263", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, it6263_of_match);
+
+static const struct i2c_device_id it6263_i2c_ids[] = {
+ { "it6263", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, it6263_i2c_ids);
+
+static struct i2c_driver it6263_driver = {
+ .probe = it6263_probe,
+ .driver = {
+ .name = "it6263",
+ .of_match_table = it6263_of_match,
+ },
+ .id_table = it6263_i2c_ids,
+};
+module_i2c_driver(it6263_driver);
+
+MODULE_DESCRIPTION("ITE Tech. Inc. IT6263 LVDS/HDMI bridge");
+MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index 7ff17aa14b01..008d86cc562a 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -2614,9 +2614,9 @@ static int it6505_poweron(struct it6505 *it6505)
/* time interval between OVDD and SYSRSTN at least be 10ms */
if (pdata->gpiod_reset) {
usleep_range(10000, 20000);
- gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
- usleep_range(1000, 2000);
gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
usleep_range(25000, 35000);
}
@@ -2647,7 +2647,7 @@ static int it6505_poweroff(struct it6505 *it6505)
disable_irq_nosync(it6505->irq);
if (pdata->gpiod_reset)
- gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
if (pdata->pwr18) {
err = regulator_disable(pdata->pwr18);
@@ -3135,7 +3135,7 @@ static int it6505_init_pdata(struct it6505 *it6505)
return PTR_ERR(pdata->ovdd);
}
- pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(pdata->gpiod_reset)) {
dev_err(dev, "gpiod_reset gpio not found");
return PTR_ERR(pdata->gpiod_reset);
diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
index fc96fa5aab54..2cb748bbefcd 100644
--- a/drivers/gpu/drm/bridge/tc358768.c
+++ b/drivers/gpu/drm/bridge/tc358768.c
@@ -125,6 +125,9 @@
#define TC358768_DSI_CONFW_MODE_CLR (6 << 29)
#define TC358768_DSI_CONFW_ADDR_DSI_CONTROL (0x3 << 24)
+/* TC358768_DSICMD_TX (0x0600) register */
+#define TC358768_DSI_CMDTX_DC_START BIT(0)
+
static const char * const tc358768_supplies[] = {
"vddc", "vddmipi", "vddio"
};
@@ -229,6 +232,21 @@ static void tc358768_update_bits(struct tc358768_priv *priv, u32 reg, u32 mask,
tc358768_write(priv, reg, tmp);
}
+static void tc358768_dsicmd_tx(struct tc358768_priv *priv)
+{
+ u32 val;
+
+ /* start transfer */
+ tc358768_write(priv, TC358768_DSICMD_TX, TC358768_DSI_CMDTX_DC_START);
+ if (priv->error)
+ return;
+
+ /* wait transfer completion */
+ priv->error = regmap_read_poll_timeout(priv->regmap, TC358768_DSICMD_TX, val,
+ (val & TC358768_DSI_CMDTX_DC_START) == 0,
+ 100, 100000);
+}
+
static int tc358768_sw_reset(struct tc358768_priv *priv)
{
/* Assert Reset */
@@ -518,8 +536,7 @@ static ssize_t tc358768_dsi_host_transfer(struct mipi_dsi_host *host,
}
}
- /* start transfer */
- tc358768_write(priv, TC358768_DSICMD_TX, 1);
+ tc358768_dsicmd_tx(priv);
ret = tc358768_clear_error(priv);
if (ret)
diff --git a/drivers/gpu/drm/ci/xfails/requirements.txt b/drivers/gpu/drm/ci/xfails/requirements.txt
deleted file mode 100644
index 5e6d48d98e4e..000000000000
--- a/drivers/gpu/drm/ci/xfails/requirements.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-git+https://gitlab.freedesktop.org/gfx-ci/ci-collate@09e7142715c16f54344ddf97013331ba063b162b
-termcolor==2.3.0
-
-# ci-collate dependencies
-certifi==2023.7.22
-charset-normalizer==3.2.0
-idna==3.4
-pip==23.3
-python-gitlab==3.15.0
-requests==2.31.0
-requests-toolbelt==1.0.0
-ruamel.yaml==0.17.32
-ruamel.yaml.clib==0.2.7
-setuptools==70.0.0
-tenacity==8.2.3
-urllib3==2.0.7
-wheel==0.41.1
diff --git a/drivers/gpu/drm/ci/xfails/update-xfails.py b/drivers/gpu/drm/ci/xfails/update-xfails.py
deleted file mode 100755
index a446e98d72a1..000000000000
--- a/drivers/gpu/drm/ci/xfails/update-xfails.py
+++ /dev/null
@@ -1,204 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-from collections import defaultdict
-import difflib
-import os
-import re
-from glcollate import Collate
-from termcolor import colored
-from urllib.parse import urlparse
-
-
-def get_canonical_name(job_name):
- return re.split(r" \d+/\d+", job_name)[0]
-
-
-def get_xfails_file_path(job_name, suffix):
- canonical_name = get_canonical_name(job_name)
- name = canonical_name.replace(":", "-")
- script_dir = os.path.dirname(os.path.abspath(__file__))
- return os.path.join(script_dir, f"{name}-{suffix}.txt")
-
-
-def get_unit_test_name_and_results(unit_test):
- if "Artifact results/failures.csv not found" in unit_test or '' == unit_test:
- return None, None
- unit_test_name, unit_test_result = unit_test.strip().split(",")
- return unit_test_name, unit_test_result
-
-
-def read_file(file_path):
- try:
- with open(file_path, "r") as file:
- f = file.readlines()
- if len(f):
- f[-1] = f[-1].strip() + "\n"
- return f
- except FileNotFoundError:
- return []
-
-
-def save_file(content, file_path):
- # delete file is content is empty
- if not content or not any(content):
- if os.path.exists(file_path):
- os.remove(file_path)
- return
-
- with open(file_path, "w") as file:
- file.writelines(content)
-
-
-def is_test_present_on_file(file_content, unit_test_name):
- return any(unit_test_name in line for line in file_content)
-
-
-def is_unit_test_present_in_other_jobs(unit_test, job_ids):
- return all(unit_test in job_ids[job_id] for job_id in job_ids)
-
-
-def remove_unit_test_if_present(lines, unit_test_name):
- if not is_test_present_on_file(lines, unit_test_name):
- return
- lines[:] = [line for line in lines if unit_test_name not in line]
-
-
-def add_unit_test_if_not_present(lines, unit_test_name, file_name):
- # core_getversion is mandatory
- if "core_getversion" in unit_test_name:
- print("WARNING: core_getversion should pass, not adding it to", os.path.basename(file_name))
- elif all(unit_test_name not in line for line in lines):
- lines.append(unit_test_name + "\n")
-
-
-def update_unit_test_result_in_fails_txt(fails_txt, unit_test):
- unit_test_name, unit_test_result = get_unit_test_name_and_results(unit_test)
- for i, line in enumerate(fails_txt):
- if unit_test_name in line:
- _, current_result = get_unit_test_name_and_results(line)
- fails_txt[i] = unit_test + "\n"
- return
-
-
-def add_unit_test_or_update_result_to_fails_if_present(fails_txt, unit_test, fails_txt_path):
- unit_test_name, _ = get_unit_test_name_and_results(unit_test)
- if not is_test_present_on_file(fails_txt, unit_test_name):
- add_unit_test_if_not_present(fails_txt, unit_test, fails_txt_path)
- # if it is present but not with the same result
- elif not is_test_present_on_file(fails_txt, unit_test):
- update_unit_test_result_in_fails_txt(fails_txt, unit_test)
-
-
-def split_unit_test_from_collate(xfails):
- for job_name in xfails.keys():
- for job_id in xfails[job_name].copy().keys():
- if "not found" in xfails[job_name][job_id].content_as_str:
- del xfails[job_name][job_id]
- continue
- xfails[job_name][job_id] = xfails[job_name][job_id].content_as_str.splitlines()
-
-
-def get_xfails_from_pipeline_url(pipeline_url):
- parsed_url = urlparse(pipeline_url)
- path_components = parsed_url.path.strip("/").split("/")
-
- namespace = path_components[0]
- project = path_components[1]
- pipeline_id = path_components[-1]
-
- print("Collating from:", namespace, project, pipeline_id)
- xfails = (
- Collate(namespace=namespace, project=project)
- .from_pipeline(pipeline_id)
- .get_artifact("results/failures.csv")
- )
-
- split_unit_test_from_collate(xfails)
- return xfails
-
-
-def get_xfails_from_pipeline_urls(pipelines_urls):
- xfails = defaultdict(dict)
-
- for url in pipelines_urls:
- new_xfails = get_xfails_from_pipeline_url(url)
- for key in new_xfails:
- xfails[key].update(new_xfails[key])
-
- return xfails
-
-
-def print_diff(old_content, new_content, file_name):
- diff = difflib.unified_diff(old_content, new_content, lineterm="", fromfile=file_name, tofile=file_name)
- diff = [colored(line, "green") if line.startswith("+") else
- colored(line, "red") if line.startswith("-") else line for line in diff]
- print("\n".join(diff[:3]))
- print("".join(diff[3:]))
-
-
-def main(pipelines_urls, only_flakes):
- xfails = get_xfails_from_pipeline_urls(pipelines_urls)
-
- for job_name in xfails.keys():
- fails_txt_path = get_xfails_file_path(job_name, "fails")
- flakes_txt_path = get_xfails_file_path(job_name, "flakes")
-
- fails_txt = read_file(fails_txt_path)
- flakes_txt = read_file(flakes_txt_path)
-
- fails_txt_original = fails_txt.copy()
- flakes_txt_original = flakes_txt.copy()
-
- for job_id in xfails[job_name].keys():
- for unit_test in xfails[job_name][job_id]:
- unit_test_name, unit_test_result = get_unit_test_name_and_results(unit_test)
-
- if not unit_test_name:
- continue
-
- if only_flakes:
- remove_unit_test_if_present(fails_txt, unit_test_name)
- add_unit_test_if_not_present(flakes_txt, unit_test_name, flakes_txt_path)
- continue
-
- # drop it from flakes if it is present to analyze it again
- remove_unit_test_if_present(flakes_txt, unit_test_name)
-
- if unit_test_result == "UnexpectedPass":
- remove_unit_test_if_present(fails_txt, unit_test_name)
- # flake result
- if not is_unit_test_present_in_other_jobs(unit_test, xfails[job_name]):
- add_unit_test_if_not_present(flakes_txt, unit_test_name, flakes_txt_path)
- continue
-
- # flake result
- if not is_unit_test_present_in_other_jobs(unit_test, xfails[job_name]):
- remove_unit_test_if_present(fails_txt, unit_test_name)
- add_unit_test_if_not_present(flakes_txt, unit_test_name, flakes_txt_path)
- continue
-
- # consistent result
- add_unit_test_or_update_result_to_fails_if_present(fails_txt, unit_test,
- fails_txt_path)
-
- fails_txt.sort()
- flakes_txt.sort()
-
- if fails_txt != fails_txt_original:
- save_file(fails_txt, fails_txt_path)
- print_diff(fails_txt_original, fails_txt, os.path.basename(fails_txt_path))
- if flakes_txt != flakes_txt_original:
- save_file(flakes_txt, flakes_txt_path)
- print_diff(flakes_txt_original, flakes_txt, os.path.basename(flakes_txt_path))
-
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser(description="Update xfails from a given pipeline.")
- parser.add_argument("pipeline_urls", nargs="+", type=str, help="URLs to the pipelines to analyze the failures.")
- parser.add_argument("--only-flakes", action="store_true", help="Treat every detected failure as a flake, edit *-flakes.txt only.")
-
- args = parser.parse_args()
-
- main(args.pipeline_urls, args.only_flakes)
- print("Done.")
diff --git a/drivers/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c
index d810529ebfb6..ec7eac6b595f 100644
--- a/drivers/gpu/drm/display/drm_dp_aux_bus.c
+++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c
@@ -292,7 +292,7 @@ int of_dp_aux_populate_bus(struct drm_dp_aux *aux,
aux_ep->dev.parent = aux->dev;
aux_ep->dev.bus = &dp_aux_bus_type;
aux_ep->dev.type = &dp_aux_device_type_type;
- aux_ep->dev.of_node = of_node_get(np);
+ device_set_node(&aux_ep->dev, of_fwnode_handle(of_node_get(np)));
dev_set_name(&aux_ep->dev, "aux-%s", dev_name(aux->dev));
ret = device_register(&aux_ep->dev);
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 9011f8e16099..cb5f22f5bbb6 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -129,7 +129,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
*/
struct drm_file *drm_file_alloc(struct drm_minor *minor)
{
- static atomic64_t ident = ATOMIC_INIT(0);
+ static atomic64_t ident = ATOMIC64_INIT(0);
struct drm_device *dev = minor->dev;
struct drm_file *file;
int ret;
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 47e6e8577b62..b781601946db 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -870,7 +870,7 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
INIT_LIST_HEAD(&fb->filp_head);
fb->funcs = funcs;
- strcpy(fb->comm, current->comm);
+ strscpy(fb->comm, current->comm);
ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB,
false, drm_framebuffer_free);
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 177b600895d3..5c2abc9eca9c 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -341,8 +341,23 @@ static int drm_of_lvds_get_remote_pixels_type(
return pixels_type;
}
+static int __drm_of_lvds_get_dual_link_pixel_order(int p1_pt, int p2_pt)
+{
+ /*
+ * A valid dual-lVDS bus is found when one port is marked with
+ * "dual-lvds-even-pixels", and the other port is marked with
+ * "dual-lvds-odd-pixels", bail out if the markers are not right.
+ */
+ if (p1_pt + p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
+ return -EINVAL;
+
+ return p1_pt == DRM_OF_LVDS_EVEN ?
+ DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS :
+ DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
+}
+
/**
- * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order
+ * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link source pixel order
* @port1: First DT port node of the Dual-link LVDS source
* @port2: Second DT port node of the Dual-link LVDS source
*
@@ -387,19 +402,58 @@ int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
if (remote_p2_pt < 0)
return remote_p2_pt;
- /*
- * A valid dual-lVDS bus is found when one remote port is marked with
- * "dual-lvds-even-pixels", and the other remote port is marked with
- * "dual-lvds-odd-pixels", bail out if the markers are not right.
- */
- if (remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
+ return __drm_of_lvds_get_dual_link_pixel_order(remote_p1_pt, remote_p2_pt);
+}
+EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order);
+
+/**
+ * drm_of_lvds_get_dual_link_pixel_order_sink - Get LVDS dual-link sink pixel order
+ * @port1: First DT port node of the Dual-link LVDS sink
+ * @port2: Second DT port node of the Dual-link LVDS sink
+ *
+ * An LVDS dual-link connection is made of two links, with even pixels
+ * transitting on one link, and odd pixels on the other link. This function
+ * returns, for two ports of an LVDS dual-link sink, which port shall transmit
+ * the even and odd pixels, based on the requirements of the sink.
+ *
+ * The pixel order is determined from the dual-lvds-even-pixels and
+ * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
+ * properties are not present, or if their usage is not valid, this function
+ * returns -EINVAL.
+ *
+ * If either port is not connected, this function returns -EPIPE.
+ *
+ * @port1 and @port2 are typically DT sibling nodes, but may have different
+ * parents when, for instance, two separate LVDS decoders receive the even and
+ * odd pixels.
+ *
+ * Return:
+ * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 receives even pixels and @port2
+ * receives odd pixels
+ * * DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS - @port1 receives odd pixels and @port2
+ * receives even pixels
+ * * -EINVAL - @port1 or @port2 are NULL
+ * * -EPIPE - when @port1 or @port2 are not connected
+ */
+int drm_of_lvds_get_dual_link_pixel_order_sink(struct device_node *port1,
+ struct device_node *port2)
+{
+ int sink_p1_pt, sink_p2_pt;
+
+ if (!port1 || !port2)
return -EINVAL;
- return remote_p1_pt == DRM_OF_LVDS_EVEN ?
- DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS :
- DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
+ sink_p1_pt = drm_of_lvds_get_port_pixels_type(port1);
+ if (!sink_p1_pt)
+ return -EPIPE;
+
+ sink_p2_pt = drm_of_lvds_get_port_pixels_type(port2);
+ if (!sink_p2_pt)
+ return -EPIPE;
+
+ return __drm_of_lvds_get_dual_link_pixel_order(sink_p1_pt, sink_p2_pt);
}
-EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order);
+EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order_sink);
/**
* drm_of_lvds_get_data_mapping - Get LVDS data mapping
@@ -410,7 +464,9 @@ EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order);
* Return:
* * MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - data-mapping is "jeida-18"
* * MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA - data-mapping is "jeida-24"
+ * * MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA - data-mapping is "jeida-30"
* * MEDIA_BUS_FMT_RGB888_1X7X4_SPWG - data-mapping is "vesa-24"
+ * * MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG - data-mapping is "vesa-30"
* * -EINVAL - the "data-mapping" property is unsupported
* * -ENODEV - the "data-mapping" property is missing
*/
@@ -427,8 +483,12 @@ int drm_of_lvds_get_data_mapping(const struct device_node *port)
return MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
if (!strcmp(mapping, "jeida-24"))
return MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
+ if (!strcmp(mapping, "jeida-30"))
+ return MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA;
if (!strcmp(mapping, "vesa-24"))
return MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
+ if (!strcmp(mapping, "vesa-30"))
+ return MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG;
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index 3f2e2b851cbc..4a73821b81f6 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -421,7 +421,6 @@ static const struct dmi_system_id orientation_data[] = {
}, { /* Lenovo Yoga Tab 3 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 *)&lcd1600x2560_rightside_up,
diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
index 74412b7bf936..0a9ecc1380d2 100644
--- a/drivers/gpu/drm/drm_panic.c
+++ b/drivers/gpu/drm/drm_panic.c
@@ -209,6 +209,14 @@ static u32 convert_xrgb8888_to_argb2101010(u32 pix)
return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03);
}
+static u32 convert_xrgb8888_to_abgr2101010(u32 pix)
+{
+ pix = ((pix & 0x00FF0000) >> 14) |
+ ((pix & 0x0000FF00) << 4) |
+ ((pix & 0x000000FF) << 22);
+ return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03);
+}
+
/*
* convert_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format
* @color: input color, in xrgb8888 format
@@ -242,6 +250,8 @@ static u32 convert_from_xrgb8888(u32 color, u32 format)
return convert_xrgb8888_to_xrgb2101010(color);
case DRM_FORMAT_ARGB2101010:
return convert_xrgb8888_to_argb2101010(color);
+ case DRM_FORMAT_ABGR2101010:
+ return convert_xrgb8888_to_abgr2101010(color);
default:
WARN_ONCE(1, "Can't convert to %p4cc\n", &format);
return 0;
diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs
index 1ef56cb07dfb..09500cddc009 100644
--- a/drivers/gpu/drm/drm_panic_qr.rs
+++ b/drivers/gpu/drm/drm_panic_qr.rs
@@ -209,12 +209,9 @@ const FORMAT_INFOS_QR_L: [u16; 8] = [
impl Version {
/// Returns the smallest QR version than can hold these segments.
fn from_segments(segments: &[&Segment<'_>]) -> Option<Version> {
- for v in (1..=40).map(|k| Version(k)) {
- if v.max_data() * 8 >= segments.iter().map(|s| s.total_size_bits(v)).sum() {
- return Some(v);
- }
- }
- None
+ (1..=40)
+ .map(Version)
+ .find(|&v| v.max_data() * 8 >= segments.iter().map(|s| s.total_size_bits(v)).sum())
}
fn width(&self) -> u8 {
@@ -242,7 +239,7 @@ impl Version {
}
fn alignment_pattern(&self) -> &'static [u8] {
- &ALIGNMENT_PATTERNS[self.0 - 1]
+ ALIGNMENT_PATTERNS[self.0 - 1]
}
fn poly(&self) -> &'static [u8] {
@@ -479,7 +476,7 @@ struct EncodedMsg<'a> {
/// Data to be put in the QR code, with correct segment encoding, padding, and
/// Error Code Correction.
impl EncodedMsg<'_> {
- fn new<'a, 'b>(segments: &[&Segment<'b>], data: &'a mut [u8]) -> Option<EncodedMsg<'a>> {
+ fn new<'a>(segments: &[&Segment<'_>], data: &'a mut [u8]) -> Option<EncodedMsg<'a>> {
let version = Version::from_segments(segments)?;
let ec_size = version.ec_size();
let g1_blocks = version.g1_blocks();
@@ -492,7 +489,7 @@ impl EncodedMsg<'_> {
data.fill(0);
let mut em = EncodedMsg {
- data: data,
+ data,
ec_size,
g1_blocks,
g2_blocks,
@@ -722,7 +719,10 @@ impl QrImage<'_> {
fn is_finder(&self, x: u8, y: u8) -> bool {
let end = self.width - 8;
- (x < 8 && y < 8) || (x < 8 && y >= end) || (x >= end && y < 8)
+ #[expect(clippy::nonminimal_bool)]
+ {
+ (x < 8 && y < 8) || (x < 8 && y >= end) || (x >= end && y < 8)
+ }
}
// Alignment pattern: 5x5 squares in a grid.
@@ -979,10 +979,11 @@ pub unsafe extern "C" fn drm_panic_qr_generate(
/// * `url_len`: Length of the URL.
///
/// * If `url_len` > 0, remove the 2 segments header/length and also count the
-/// conversion to numeric segments.
+/// conversion to numeric segments.
/// * If `url_len` = 0, only removes 3 bytes for 1 binary segment.
#[no_mangle]
pub extern "C" fn drm_panic_qr_max_data_size(version: u8, url_len: usize) -> usize {
+ #[expect(clippy::manual_range_contains)]
if version < 1 || version > 40 {
return 0;
}
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 8e3d2d7060f8..4f2ab8a7b50f 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -712,16 +712,14 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
int fd, u32 *handle)
{
struct drm_syncobj *syncobj;
- struct fd f = fdget(fd);
+ CLASS(fd, f)(fd);
int ret;
- if (!fd_file(f))
+ if (fd_empty(f))
return -EINVAL;
- if (fd_file(f)->f_op != &drm_syncobj_file_fops) {
- fdput(f);
+ if (fd_file(f)->f_op != &drm_syncobj_file_fops)
return -EINVAL;
- }
/* take a reference to put in the idr */
syncobj = fd_file(f)->private_data;
@@ -739,7 +737,6 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
} else
drm_syncobj_put(syncobj);
- fdput(f);
return ret;
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
index 384df1659be6..b13a17276d07 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -482,7 +482,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
} else {
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
VIVS_GL_FLUSH_CACHE_DEPTH |
- VIVS_GL_FLUSH_CACHE_COLOR);
+ VIVS_GL_FLUSH_CACHE_COLOR |
+ VIVS_GL_FLUSH_CACHE_SHADER_L1);
if (has_blt) {
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
index 721d633aece9..7aa5f14d0c87 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
@@ -5,8 +5,6 @@
#include <linux/dma-mapping.h>
-#include <drm/drm_mm.h>
-
#include "etnaviv_cmdbuf.h"
#include "etnaviv_gem.h"
#include "etnaviv_gpu.h"
@@ -55,6 +53,7 @@ etnaviv_cmdbuf_suballoc_new(struct device *dev)
return suballoc;
free_suballoc:
+ mutex_destroy(&suballoc->lock);
kfree(suballoc);
return ERR_PTR(ret);
@@ -79,6 +78,7 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)
{
dma_free_wc(suballoc->dev, SUBALLOC_SIZE, suballoc->vaddr,
suballoc->paddr);
+ mutex_destroy(&suballoc->lock);
kfree(suballoc);
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 6500f3999c5f..9b4e2f4b1bc7 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -538,6 +538,16 @@ static int etnaviv_bind(struct device *dev)
priv->num_gpus = 0;
priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
+ /*
+ * If the GPU is part of a system with DMA addressing limitations,
+ * request pages for our SHM backend buffers from the DMA32 zone to
+ * hopefully avoid performance killing SWIOTLB bounce buffering.
+ */
+ if (dma_addressing_limited(dev)) {
+ priv->shm_gfp_mask |= GFP_DMA32;
+ priv->shm_gfp_mask &= ~__GFP_HIGHMEM;
+ }
+
priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev);
if (IS_ERR(priv->cmdbuf_suballoc)) {
dev_err(drm->dev, "Failed to create cmdbuf suballocator\n");
@@ -564,6 +574,7 @@ out_unbind:
out_destroy_suballoc:
etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
out_free_priv:
+ mutex_destroy(&priv->gem_lock);
kfree(priv);
out_put:
drm_dev_put(drm);
@@ -608,7 +619,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
if (!of_device_is_available(core_node))
continue;
- drm_of_component_match_add(&pdev->dev, &match,
+ drm_of_component_match_add(dev, &match,
component_compare_of, core_node);
}
} else {
@@ -631,9 +642,9 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
* bit to make sure we are allocating the command buffers and
* TLBs in the lower 4 GiB address space.
*/
- if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
- dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
- dev_dbg(&pdev->dev, "No suitable DMA available\n");
+ if (dma_set_mask(dev, DMA_BIT_MASK(40)) ||
+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) {
+ dev_dbg(dev, "No suitable DMA available\n");
return -ENODEV;
}
@@ -644,7 +655,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
*/
first_node = etnaviv_of_first_available_node();
if (first_node) {
- of_dma_configure(&pdev->dev, first_node, true);
+ of_dma_configure(dev, first_node, true);
of_node_put(first_node);
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 5c0c9d4e3be1..16473c371444 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -514,6 +514,7 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
etnaviv_obj->ops->release(etnaviv_obj);
drm_gem_object_release(obj);
+ mutex_destroy(&etnaviv_obj->lock);
kfree(etnaviv_obj);
}
@@ -543,7 +544,7 @@ static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
.vm_ops = &vm_ops,
};
-static int etnaviv_gem_new_impl(struct drm_device *dev, u32 flags,
+static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
{
struct etnaviv_gem_object *etnaviv_obj;
@@ -570,6 +571,7 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 flags,
if (!etnaviv_obj)
return -ENOMEM;
+ etnaviv_obj->size = ALIGN(size, SZ_4K);
etnaviv_obj->flags = flags;
etnaviv_obj->ops = ops;
@@ -590,15 +592,13 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
struct drm_gem_object *obj = NULL;
int ret;
- size = PAGE_ALIGN(size);
-
- ret = etnaviv_gem_new_impl(dev, flags, &etnaviv_gem_shmem_ops, &obj);
+ ret = etnaviv_gem_new_impl(dev, size, flags, &etnaviv_gem_shmem_ops, &obj);
if (ret)
goto fail;
lockdep_set_class(&to_etnaviv_bo(obj)->lock, &etnaviv_shm_lock_class);
- ret = drm_gem_object_init(dev, obj, size);
+ ret = drm_gem_object_init(dev, obj, PAGE_ALIGN(size));
if (ret)
goto fail;
@@ -627,7 +627,7 @@ int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
struct drm_gem_object *obj;
int ret;
- ret = etnaviv_gem_new_impl(dev, flags, ops, &obj);
+ ret = etnaviv_gem_new_impl(dev, size, flags, ops, &obj);
if (ret)
return ret;
@@ -686,7 +686,7 @@ static void etnaviv_gem_userptr_release(struct etnaviv_gem_object *etnaviv_obj)
kfree(etnaviv_obj->sgt);
}
if (etnaviv_obj->pages) {
- int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
+ unsigned int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
unpin_user_pages(etnaviv_obj->pages, npages);
kvfree(etnaviv_obj->pages);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
index a42d260cac2c..687555aae807 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
@@ -36,6 +36,11 @@ struct etnaviv_gem_object {
const struct etnaviv_gem_ops *ops;
struct mutex lock;
+ /*
+ * The actual size that is visible to the GPU, not necessarily
+ * PAGE_SIZE aligned, but should be aligned to GPU page size.
+ */
+ u32 size;
u32 flags;
struct list_head gem_node;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
index 3524b5811682..6b98200068e4 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -17,7 +17,7 @@ static struct lock_class_key etnaviv_prime_lock_class;
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
- int npages = obj->size >> PAGE_SHIFT;
+ unsigned int npages = obj->size >> PAGE_SHIFT;
if (WARN_ON(!etnaviv_obj->pages)) /* should have already pinned! */
return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index 3d0f8d182506..3c0a5c3e0e3d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -6,7 +6,6 @@
#include <drm/drm_file.h>
#include <linux/dma-fence-array.h>
#include <linux/file.h>
-#include <linux/pm_runtime.h>
#include <linux/dma-resv.h>
#include <linux/sync_file.h>
#include <linux/uaccess.h>
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 7c7f97793ddd..c7d59c06ccd1 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -574,8 +574,8 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
continue;
}
- /* disable debug registers, as they are not normally needed */
- control |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
+ /* enable debug register access */
+ control &= ~VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
failed = false;
@@ -839,17 +839,8 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
if (ret)
goto fail;
- /*
- * If the GPU is part of a system with DMA addressing limitations,
- * request pages for our SHM backend buffers from the DMA32 zone to
- * hopefully avoid performance killing SWIOTLB bounce buffering.
- */
- if (dma_addressing_limited(gpu->dev))
- priv->shm_gfp_mask |= GFP_DMA32;
-
/* Create buffer: */
- ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer,
- PAGE_SIZE);
+ ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer, SZ_4K);
if (ret) {
dev_err(gpu->dev, "could not create command buffer\n");
goto fail;
@@ -1330,17 +1321,16 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
{
u32 val;
+ mutex_lock(&gpu->lock);
+
/* disable clock gating */
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
- /* enable debug register */
- val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
- val &= ~VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
- gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
-
sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE);
+
+ mutex_unlock(&gpu->lock);
}
static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
@@ -1350,23 +1340,22 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
unsigned int i;
u32 val;
+ mutex_lock(&gpu->lock);
+
sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);
+ /* enable clock gating */
+ val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
+ val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
+ gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
+
+ mutex_unlock(&gpu->lock);
+
for (i = 0; i < submit->nr_pmrs; i++) {
const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;
*pmr->bo_vma = pmr->sequence;
}
-
- /* disable debug register */
- val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
- val |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
- gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
-
- /* enable clock gating */
- val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
- val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
- gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
}
@@ -1862,7 +1851,7 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
if (!gpu)
return -ENOMEM;
- gpu->dev = &pdev->dev;
+ gpu->dev = dev;
mutex_init(&gpu->lock);
mutex_init(&gpu->sched_lock);
@@ -1876,8 +1865,8 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
if (gpu->irq < 0)
return gpu->irq;
- err = devm_request_irq(&pdev->dev, gpu->irq, irq_handler, 0,
- dev_name(gpu->dev), gpu);
+ err = devm_request_irq(dev, gpu->irq, irq_handler, 0,
+ dev_name(dev), gpu);
if (err) {
dev_err(dev, "failed to request IRQ%u: %d\n", gpu->irq, err);
return err;
@@ -1914,13 +1903,13 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
* autosuspend delay is rather arbitary: no measurements have
* yet been performed to determine an appropriate value.
*/
- pm_runtime_use_autosuspend(gpu->dev);
- pm_runtime_set_autosuspend_delay(gpu->dev, 200);
- pm_runtime_enable(gpu->dev);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, 200);
+ pm_runtime_enable(dev);
- err = component_add(&pdev->dev, &gpu_ops);
+ err = component_add(dev, &gpu_ops);
if (err < 0) {
- dev_err(&pdev->dev, "failed to register component: %d\n", err);
+ dev_err(dev, "failed to register component: %d\n", err);
return err;
}
@@ -1929,8 +1918,13 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
static void etnaviv_gpu_platform_remove(struct platform_device *pdev)
{
+ struct etnaviv_gpu *gpu = dev_get_drvdata(&pdev->dev);
+
component_del(&pdev->dev, &gpu_ops);
pm_runtime_disable(&pdev->dev);
+
+ mutex_destroy(&gpu->lock);
+ mutex_destroy(&gpu->sched_lock);
}
static int etnaviv_gpu_rpm_suspend(struct device *dev)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 31322195b9e4..4d8a7d48ade3 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -144,6 +144,7 @@ struct etnaviv_gpu {
/* hang detection */
u32 hangcheck_dma_addr;
+ u32 hangcheck_primid;
u32 hangcheck_fence;
void __iomem *mmio;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index 1661d589bf3e..7e065b3723cf 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -69,9 +69,11 @@ static int etnaviv_context_map(struct etnaviv_iommu_context *context,
return ret;
}
-static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
+static int etnaviv_iommu_map(struct etnaviv_iommu_context *context,
+ u32 iova, unsigned int va_len,
struct sg_table *sgt, int prot)
-{ struct scatterlist *sg;
+{
+ struct scatterlist *sg;
unsigned int da = iova;
unsigned int i;
int ret;
@@ -81,14 +83,16 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
for_each_sgtable_dma_sg(sgt, sg, i) {
phys_addr_t pa = sg_dma_address(sg) - sg->offset;
- size_t bytes = sg_dma_len(sg) + sg->offset;
+ unsigned int da_len = sg_dma_len(sg) + sg->offset;
+ unsigned int bytes = min_t(unsigned int, da_len, va_len);
- VERB("map[%d]: %08x %pap(%zx)", i, iova, &pa, bytes);
+ VERB("map[%d]: %08x %pap(%x)", i, iova, &pa, bytes);
ret = etnaviv_context_map(context, da, pa, bytes, prot);
if (ret)
goto fail;
+ va_len -= bytes;
da += bytes;
}
@@ -104,21 +108,7 @@ fail:
static void etnaviv_iommu_unmap(struct etnaviv_iommu_context *context, u32 iova,
struct sg_table *sgt, unsigned len)
{
- struct scatterlist *sg;
- unsigned int da = iova;
- int i;
-
- for_each_sgtable_dma_sg(sgt, sg, i) {
- size_t bytes = sg_dma_len(sg) + sg->offset;
-
- etnaviv_context_unmap(context, da, bytes);
-
- VERB("unmap[%d]: %08x(%zx)", i, iova, bytes);
-
- BUG_ON(!PAGE_ALIGNED(bytes));
-
- da += bytes;
- }
+ etnaviv_context_unmap(context, iova, len);
context->flush_seq++;
}
@@ -131,7 +121,7 @@ static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
lockdep_assert_held(&context->lock);
etnaviv_iommu_unmap(context, mapping->vram_node.start,
- etnaviv_obj->sgt, etnaviv_obj->base.size);
+ etnaviv_obj->sgt, etnaviv_obj->size);
drm_mm_remove_node(&mapping->vram_node);
}
@@ -305,16 +295,14 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
node = &mapping->vram_node;
if (va)
- ret = etnaviv_iommu_insert_exact(context, node,
- etnaviv_obj->base.size, va);
+ ret = etnaviv_iommu_insert_exact(context, node, etnaviv_obj->size, va);
else
- ret = etnaviv_iommu_find_iova(context, node,
- etnaviv_obj->base.size);
+ ret = etnaviv_iommu_find_iova(context, node, etnaviv_obj->size);
if (ret < 0)
goto unlock;
mapping->iova = node->start;
- ret = etnaviv_iommu_map(context, node->start, sgt,
+ ret = etnaviv_iommu_map(context, node->start, etnaviv_obj->size, sgt,
ETNAVIV_PROT_READ | ETNAVIV_PROT_WRITE);
if (ret < 0) {
@@ -358,7 +346,7 @@ static void etnaviv_iommu_context_free(struct kref *kref)
container_of(kref, struct etnaviv_iommu_context, refcount);
etnaviv_cmdbuf_suballoc_unmap(context, &context->cmdbuf_mapping);
-
+ mutex_destroy(&context->lock);
context->global->ops->free(context);
}
void etnaviv_iommu_context_put(struct etnaviv_iommu_context *context)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
index c01a147f0dfd..7f8ac0178547 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
@@ -61,7 +61,6 @@ struct etnaviv_iommu_global {
/* P(age) T(able) A(rray) */
u64 *pta_cpu;
dma_addr_t pta_dma;
- struct spinlock pta_lock;
DECLARE_BITMAP(pta_alloc, ETNAVIV_PTA_ENTRIES);
} v2;
};
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
index dc9dea664a28..d53a5c293373 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
@@ -62,6 +62,8 @@ static u32 pipe_perf_reg_read(struct etnaviv_gpu *gpu,
u32 value = 0;
unsigned i;
+ lockdep_assert_held(&gpu->lock);
+
for (i = 0; i < gpu->identity.pixel_pipes; i++) {
pipe_select(gpu, clock, i);
value += perf_reg_read(gpu, domain, signal);
@@ -81,6 +83,8 @@ static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
u32 value = 0;
unsigned i;
+ lockdep_assert_held(&gpu->lock);
+
for (i = 0; i < gpu->identity.pixel_pipes; i++) {
pipe_select(gpu, clock, i);
value += gpu_read(gpu, signal->data);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index 23ced5896c7c..5b67eda122db 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -11,6 +11,7 @@
#include "etnaviv_gpu.h"
#include "etnaviv_sched.h"
#include "state.xml.h"
+#include "state_hi.xml.h"
static int etnaviv_job_hang_limit = 0;
module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444);
@@ -35,7 +36,7 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
{
struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job);
struct etnaviv_gpu *gpu = submit->gpu;
- u32 dma_addr;
+ u32 dma_addr, primid = 0;
int change;
/*
@@ -52,10 +53,22 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
*/
dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
change = dma_addr - gpu->hangcheck_dma_addr;
+ if (submit->exec_state == ETNA_PIPE_3D) {
+ /* guard against concurrent usage from perfmon_sample */
+ mutex_lock(&gpu->lock);
+ gpu_write(gpu, VIVS_MC_PROFILE_CONFIG0,
+ VIVS_MC_PROFILE_CONFIG0_FE_CURRENT_PRIM <<
+ VIVS_MC_PROFILE_CONFIG0_FE__SHIFT);
+ primid = gpu_read(gpu, VIVS_MC_PROFILE_FE_READ);
+ mutex_unlock(&gpu->lock);
+ }
if (gpu->state == ETNA_GPU_STATE_RUNNING &&
(gpu->completed_fence != gpu->hangcheck_fence ||
- change < 0 || change > 16)) {
+ change < 0 || change > 16 ||
+ (submit->exec_state == ETNA_PIPE_3D &&
+ gpu->hangcheck_primid != primid))) {
gpu->hangcheck_dma_addr = dma_addr;
+ gpu->hangcheck_primid = primid;
gpu->hangcheck_fence = gpu->completed_fence;
goto out_no_timeout;
}
diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h
index 829bc528e618..f7bc5f6e20ff 100644
--- a/drivers/gpu/drm/etnaviv/state_hi.xml.h
+++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h
@@ -8,17 +8,17 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
git clone git://0x04.net/rules-ng-ng
The rules-ng-ng source files this header was generated from are:
-- state.xml ( 29355 bytes, from 2024-01-19 10:18:54)
-- common.xml ( 35664 bytes, from 2023-12-06 10:55:32)
-- common_3d.xml ( 15069 bytes, from 2023-11-22 10:05:24)
-- state_hi.xml ( 35854 bytes, from 2023-12-11 15:50:17)
-- copyright.xml ( 1597 bytes, from 2016-11-10 13:58:32)
-- state_2d.xml ( 52271 bytes, from 2023-06-02 12:35:03)
-- state_3d.xml ( 89522 bytes, from 2024-01-19 10:18:54)
-- state_blt.xml ( 14592 bytes, from 2023-11-22 10:05:09)
-- state_vg.xml ( 5975 bytes, from 2016-11-10 13:58:32)
-
-Copyright (C) 2012-2023 by the following authors:
+- state.xml ( 30729 bytes, from 2024-06-21 11:31:54)
+- common.xml ( 35664 bytes, from 2023-12-13 09:33:18)
+- common_3d.xml ( 15069 bytes, from 2023-12-13 09:33:18)
+- state_hi.xml ( 35909 bytes, from 2024-06-21 11:31:54)
+- copyright.xml ( 1597 bytes, from 2020-10-28 12:56:03)
+- state_2d.xml ( 52271 bytes, from 2023-05-30 20:50:02)
+- state_3d.xml ( 89626 bytes, from 2024-06-21 11:32:57)
+- state_blt.xml ( 14592 bytes, from 2023-12-13 09:33:18)
+- state_vg.xml ( 5975 bytes, from 2020-10-28 12:56:03)
+
+Copyright (C) 2012-2024 by the following authors:
- Wladimir J. van der Laan <laanwj@gmail.com>
- Christian Gmeiner <christian.gmeiner@gmail.com>
- Lucas Stach <l.stach@pengutronix.de>
@@ -467,6 +467,7 @@ DEALINGS IN THE SOFTWARE.
#define VIVS_MC_PROFILE_CONFIG0 0x00000470
#define VIVS_MC_PROFILE_CONFIG0_FE__MASK 0x000000ff
#define VIVS_MC_PROFILE_CONFIG0_FE__SHIFT 0
+#define VIVS_MC_PROFILE_CONFIG0_FE_CURRENT_PRIM 0x00000009
#define VIVS_MC_PROFILE_CONFIG0_FE_DRAW_COUNT 0x0000000a
#define VIVS_MC_PROFILE_CONFIG0_FE_OUT_VERTEX_COUNT 0x0000000b
#define VIVS_MC_PROFILE_CONFIG0_FE_CACHE_MISS_COUNT 0x0000000c
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 0d185c0564b9..c65364087fac 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -37,6 +37,24 @@
#define WINDOWS_NR 2
+struct decon_data {
+ unsigned int vidw_buf_start_base;
+ unsigned int shadowcon_win_protect_shift;
+ unsigned int wincon_burstlen_shift;
+};
+
+static struct decon_data exynos7_decon_data = {
+ .vidw_buf_start_base = 0x80,
+ .shadowcon_win_protect_shift = 10,
+ .wincon_burstlen_shift = 11,
+};
+
+static struct decon_data exynos7870_decon_data = {
+ .vidw_buf_start_base = 0x880,
+ .shadowcon_win_protect_shift = 8,
+ .wincon_burstlen_shift = 10,
+};
+
struct decon_context {
struct device *dev;
struct drm_device *drm_dev;
@@ -55,11 +73,19 @@ struct decon_context {
wait_queue_head_t wait_vsync_queue;
atomic_t wait_vsync_event;
+ const struct decon_data *data;
struct drm_encoder *encoder;
};
static const struct of_device_id decon_driver_dt_match[] = {
- {.compatible = "samsung,exynos7-decon"},
+ {
+ .compatible = "samsung,exynos7-decon",
+ .data = &exynos7_decon_data,
+ },
+ {
+ .compatible = "samsung,exynos7870-decon",
+ .data = &exynos7870_decon_data,
+ },
{},
};
MODULE_DEVICE_TABLE(of, decon_driver_dt_match);
@@ -81,10 +107,31 @@ static const enum drm_plane_type decon_win_types[WINDOWS_NR] = {
DRM_PLANE_TYPE_CURSOR,
};
-static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
+/**
+ * decon_shadow_protect_win() - disable updating values from shadow registers at vsync
+ *
+ * @ctx: display and enhancement controller context
+ * @win: window to protect registers for
+ * @protect: 1 to protect (disable updates)
+ */
+static void decon_shadow_protect_win(struct decon_context *ctx,
+ unsigned int win, bool protect)
{
- struct decon_context *ctx = crtc->ctx;
+ u32 bits, val;
+ unsigned int shift = ctx->data->shadowcon_win_protect_shift;
+
+ bits = SHADOWCON_WINx_PROTECT(shift, win);
+
+ val = readl(ctx->regs + SHADOWCON);
+ if (protect)
+ val |= bits;
+ else
+ val &= ~bits;
+ writel(val, ctx->regs + SHADOWCON);
+}
+static void decon_wait_for_vblank(struct decon_context *ctx)
+{
if (ctx->suspended)
return;
@@ -100,25 +147,33 @@ static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
DRM_DEV_DEBUG_KMS(ctx->dev, "vblank wait timed out.\n");
}
-static void decon_clear_channels(struct exynos_drm_crtc *crtc)
+static void decon_clear_channels(struct decon_context *ctx)
{
- struct decon_context *ctx = crtc->ctx;
unsigned int win, ch_enabled = 0;
+ u32 val;
/* Check if any channel is enabled. */
for (win = 0; win < WINDOWS_NR; win++) {
- u32 val = readl(ctx->regs + WINCON(win));
+ val = readl(ctx->regs + WINCON(win));
if (val & WINCONx_ENWIN) {
+ decon_shadow_protect_win(ctx, win, true);
+
val &= ~WINCONx_ENWIN;
writel(val, ctx->regs + WINCON(win));
ch_enabled = 1;
+
+ decon_shadow_protect_win(ctx, win, false);
}
}
+ val = readl(ctx->regs + DECON_UPDATE);
+ val |= DECON_UPDATE_STANDALONE_F;
+ writel(val, ctx->regs + DECON_UPDATE);
+
/* Wait for vsync, as disable channel takes effect at next vsync */
if (ch_enabled)
- decon_wait_for_vblank(ctx->crtc);
+ decon_wait_for_vblank(ctx);
}
static int decon_ctx_initialize(struct decon_context *ctx,
@@ -126,7 +181,7 @@ static int decon_ctx_initialize(struct decon_context *ctx,
{
ctx->drm_dev = drm_dev;
- decon_clear_channels(ctx->crtc);
+ decon_clear_channels(ctx);
return exynos_drm_register_dma(drm_dev, ctx->dev, &ctx->dma_priv);
}
@@ -140,7 +195,7 @@ static void decon_ctx_remove(struct decon_context *ctx)
static u32 decon_calc_clkdiv(struct decon_context *ctx,
const struct drm_display_mode *mode)
{
- unsigned long ideal_clk = mode->clock;
+ unsigned long ideal_clk = mode->clock * 1000;
u32 clkdiv;
/* Find the clock divider value that gets us closest to ideal_clk */
@@ -263,6 +318,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
{
unsigned long val;
int padding;
+ unsigned int shift = ctx->data->wincon_burstlen_shift;
val = readl(ctx->regs + WINCON(win));
val &= ~WINCONx_BPPMODE_MASK;
@@ -270,44 +326,44 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
switch (fb->format->format) {
case DRM_FORMAT_RGB565:
val |= WINCONx_BPPMODE_16BPP_565;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_XRGB8888:
val |= WINCONx_BPPMODE_24BPP_xRGB;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_XBGR8888:
val |= WINCONx_BPPMODE_24BPP_xBGR;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_RGBX8888:
val |= WINCONx_BPPMODE_24BPP_RGBx;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_BGRX8888:
val |= WINCONx_BPPMODE_24BPP_BGRx;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_ARGB8888:
val |= WINCONx_BPPMODE_32BPP_ARGB | WINCONx_BLD_PIX |
WINCONx_ALPHA_SEL;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_ABGR8888:
val |= WINCONx_BPPMODE_32BPP_ABGR | WINCONx_BLD_PIX |
WINCONx_ALPHA_SEL;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_RGBA8888:
val |= WINCONx_BPPMODE_32BPP_RGBA | WINCONx_BLD_PIX |
WINCONx_ALPHA_SEL;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
case DRM_FORMAT_BGRA8888:
default:
val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX |
WINCONx_ALPHA_SEL;
- val |= WINCONx_BURSTLEN_16WORD;
+ val |= WINCONx_BURSTLEN_16WORD(shift);
break;
}
@@ -323,8 +379,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
padding = (fb->pitches[0] / fb->format->cpp[0]) - fb->width;
if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
- val &= ~WINCONx_BURSTLEN_MASK;
- val |= WINCONx_BURSTLEN_8WORD;
+ val &= ~WINCONx_BURSTLEN_MASK(shift);
+ val |= WINCONx_BURSTLEN_8WORD(shift);
}
writel(val, ctx->regs + WINCON(win));
@@ -343,28 +399,6 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
}
-/**
- * decon_shadow_protect_win() - disable updating values from shadow registers at vsync
- *
- * @ctx: display and enhancement controller context
- * @win: window to protect registers for
- * @protect: 1 to protect (disable updates)
- */
-static void decon_shadow_protect_win(struct decon_context *ctx,
- unsigned int win, bool protect)
-{
- u32 bits, val;
-
- bits = SHADOWCON_WINx_PROTECT(win);
-
- val = readl(ctx->regs + SHADOWCON);
- if (protect)
- val |= bits;
- else
- val &= ~bits;
- writel(val, ctx->regs + SHADOWCON);
-}
-
static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
@@ -391,6 +425,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
unsigned int win = plane->index;
unsigned int cpp = fb->format->cpp[0];
unsigned int pitch = fb->pitches[0];
+ unsigned int vidw_addr0_base = ctx->data->vidw_buf_start_base;
if (ctx->suspended)
return;
@@ -407,7 +442,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
/* buffer start address */
val = (unsigned long)exynos_drm_fb_dma_addr(fb, 0);
- writel(val, ctx->regs + VIDW_BUF_START(win));
+ writel(val, ctx->regs + VIDW_BUF_START(vidw_addr0_base, win));
padding = (pitch / cpp) - fb->width;
@@ -689,6 +724,7 @@ static int decon_probe(struct platform_device *pdev)
ctx->dev = dev;
ctx->suspended = true;
+ ctx->data = of_device_get_match_data(dev);
i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
if (i80_if_timings)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 0ed4f2b8595a..1815374c38df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -19,9 +19,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
enum exynos_drm_output_type out_type,
const struct exynos_drm_crtc_ops *ops,
void *context);
-void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
-void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
- struct exynos_drm_plane *exynos_plane);
/* This function gets crtc device matched with out_type. */
struct exynos_drm_crtc *exynos_drm_crtc_get_by_type(struct drm_device *drm_dev,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 59fa22050717..1ae90ef1fc23 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1286,7 +1286,7 @@ static int gsc_probe(struct platform_device *pdev)
return ret;
}
- /* context initailization */
+ /* context initialization */
ctx->id = pdev->id;
platform_set_drvdata(pdev, ctx);
diff --git a/drivers/gpu/drm/exynos/regs-decon7.h b/drivers/gpu/drm/exynos/regs-decon7.h
index 5bc5f1db5196..216c106dac8f 100644
--- a/drivers/gpu/drm/exynos/regs-decon7.h
+++ b/drivers/gpu/drm/exynos/regs-decon7.h
@@ -48,7 +48,7 @@
/* SHADOWCON */
#define SHADOWCON 0x30
-#define SHADOWCON_WINx_PROTECT(_win) (1 << (10 + (_win)))
+#define SHADOWCON_WINx_PROTECT(_shf, _win) (1 << ((_shf) + (_win)))
/* WINCONx */
#define WINCON(_win) (0x50 + ((_win) * 4))
@@ -58,10 +58,9 @@
#define WINCONx_BUFSEL_SHIFT 28
#define WINCONx_TRIPLE_BUF_MODE (0x1 << 18)
#define WINCONx_DOUBLE_BUF_MODE (0x0 << 18)
-#define WINCONx_BURSTLEN_16WORD (0x0 << 11)
-#define WINCONx_BURSTLEN_8WORD (0x1 << 11)
-#define WINCONx_BURSTLEN_MASK (0x1 << 11)
-#define WINCONx_BURSTLEN_SHIFT 11
+#define WINCONx_BURSTLEN_16WORD(_shf) (0x0 << (_shf))
+#define WINCONx_BURSTLEN_8WORD(_shf) (0x1 << (_shf))
+#define WINCONx_BURSTLEN_MASK(_shf) (0x1 << (_shf))
#define WINCONx_BLD_PLANE (0 << 8)
#define WINCONx_BLD_PIX (1 << 8)
#define WINCONx_ALPHA_MUL (1 << 7)
@@ -89,9 +88,9 @@
#define VIDOSD_H(_x) (0x80 + ((_x) * 4))
/* Frame buffer start addresses: VIDWxxADD0n */
-#define VIDW_BUF_START(_win) (0x80 + ((_win) * 0x10))
-#define VIDW_BUF_START1(_win) (0x84 + ((_win) * 0x10))
-#define VIDW_BUF_START2(_win) (0x88 + ((_win) * 0x10))
+#define VIDW_BUF_START(_base, _win) ((_base) + ((_win) * 0x10))
+#define VIDW_BUF_START1(_base, _win) ((_base) + ((_win) * 0x10))
+#define VIDW_BUF_START2(_base, _win) ((_base) + ((_win) * 0x10))
#define VIDW_WHOLE_X(_win) (0x0130 + ((_win) * 8))
#define VIDW_WHOLE_Y(_win) (0x0134 + ((_win) * 8))
diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig
index c2927c37c40b..aa2ea128aa2f 100644
--- a/drivers/gpu/drm/gma500/Kconfig
+++ b/drivers/gpu/drm/gma500/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_GMA500
tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
- depends on DRM && PCI && X86 && MMU
+ depends on DRM && PCI && X86 && MMU && HAS_IOPORT
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index e033bcaef4f3..31710d98cad5 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -339,6 +339,7 @@ i915-y += \
display/intel_lspcon.o \
display/intel_lvds.o \
display/intel_panel.o \
+ display/intel_pfit.o \
display/intel_pps.o \
display/intel_qp_tables.o \
display/intel_sdvo.o \
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c
index 440fb3002f28..4fbec065d53e 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -170,13 +170,12 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
bool cur_state = intel_de_read(display, intel_dp->output_reg) & DP_PORT_EN;
- I915_STATE_WARN(dev_priv, cur_state != state,
- "[ENCODER:%d:%s] state assertion failure (expected %s, current %s)\n",
- dig_port->base.base.base.id, dig_port->base.base.name,
- str_on_off(state), str_on_off(cur_state));
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "[ENCODER:%d:%s] state assertion failure (expected %s, current %s)\n",
+ dig_port->base.base.base.id, dig_port->base.base.name,
+ str_on_off(state), str_on_off(cur_state));
}
#define assert_dp_port_disabled(d) assert_dp_port((d), false)
@@ -185,9 +184,9 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state)
struct intel_display *display = &dev_priv->display;
bool cur_state = intel_de_read(display, DP_A) & DP_PLL_ENABLE;
- I915_STATE_WARN(dev_priv, cur_state != state,
- "eDP PLL state assertion failure (expected %s, current %s)\n",
- str_on_off(state), str_on_off(cur_state));
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "eDP PLL state assertion failure (expected %s, current %s)\n",
+ str_on_off(state), str_on_off(cur_state));
}
#define assert_edp_pll_enabled(d) assert_edp_pll((d), true)
#define assert_edp_pll_disabled(d) assert_edp_pll((d), false)
@@ -706,8 +705,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
if (IS_CHERRYVIEW(dev_priv))
lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count);
- vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp),
- lane_mask);
+ vlv_wait_port_ready(display, dp_to_dig_port(intel_dp), lane_mask);
}
intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
@@ -1251,6 +1249,7 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder)
intel_dp->DP = intel_de_read(display, intel_dp->output_reg);
intel_dp->reset_link_params = true;
+ intel_dp_invalidate_source_oui(intel_dp);
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_pps_pipe_reset(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index 46f23bdb4c17..d1a7d0d57c6b 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -480,8 +480,8 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
+ struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
vlv_phy_pre_encoder_enable(encoder, pipe_config);
@@ -496,7 +496,7 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state,
g4x_hdmi_enable_port(encoder, pipe_config);
- vlv_wait_port_ready(dev_priv, dig_port, 0x0);
+ vlv_wait_port_ready(display, dig_port, 0x0);
}
static void vlv_hdmi_pre_pll_enable(struct intel_atomic_state *state,
@@ -557,9 +557,8 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
+ struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
- struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
chv_phy_pre_encoder_enable(encoder, pipe_config);
@@ -573,7 +572,7 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state,
g4x_hdmi_enable_port(encoder, pipe_config);
- vlv_wait_port_ready(dev_priv, dig_port, 0x0);
+ vlv_wait_port_ready(display, dig_port, 0x0);
/* Second common lane will stay alive on its own now */
chv_phy_release_cl2_override(encoder);
diff --git a/drivers/gpu/drm/i915/display/hsw_ips.c b/drivers/gpu/drm/i915/display/hsw_ips.c
index c571c6e76d4a..34c5d28fc866 100644
--- a/drivers/gpu/drm/i915/display/hsw_ips.c
+++ b/drivers/gpu/drm/i915/display/hsw_ips.c
@@ -15,6 +15,7 @@
static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
u32 val;
@@ -27,16 +28,16 @@ static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
* This function is called from post_plane_update, which is run after
* a vblank wait.
*/
- drm_WARN_ON(&i915->drm,
+ drm_WARN_ON(display->drm,
!(crtc_state->active_planes & ~BIT(PLANE_CURSOR)));
val = IPS_ENABLE;
- if (i915->display.ips.false_color)
+ if (display->ips.false_color)
val |= IPS_FALSE_COLOR;
if (IS_BROADWELL(i915)) {
- drm_WARN_ON(&i915->drm,
+ drm_WARN_ON(display->drm,
snb_pcode_write(&i915->uncore, DISPLAY_IPS_CONTROL,
val | IPS_PCODE_CONTROL));
/*
@@ -46,7 +47,7 @@ static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
* so we need to just enable it and continue on.
*/
} else {
- intel_de_write(i915, IPS_CTL, val);
+ intel_de_write(display, IPS_CTL, val);
/*
* The bit only becomes 1 in the next vblank, so this wait here
* is essentially intel_wait_for_vblank. If we don't have this
@@ -54,14 +55,15 @@ static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
* the HW state readout code will complain that the expected
* IPS_CTL value is not the one we read.
*/
- if (intel_de_wait_for_set(i915, IPS_CTL, IPS_ENABLE, 50))
- drm_err(&i915->drm,
+ if (intel_de_wait_for_set(display, IPS_CTL, IPS_ENABLE, 50))
+ drm_err(display->drm,
"Timed out waiting for IPS enable\n");
}
}
bool hsw_ips_disable(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
bool need_vblank_wait = false;
@@ -70,19 +72,19 @@ bool hsw_ips_disable(const struct intel_crtc_state *crtc_state)
return need_vblank_wait;
if (IS_BROADWELL(i915)) {
- drm_WARN_ON(&i915->drm,
+ drm_WARN_ON(display->drm,
snb_pcode_write(&i915->uncore, DISPLAY_IPS_CONTROL, 0));
/*
* Wait for PCODE to finish disabling IPS. The BSpec specified
* 42ms timeout value leads to occasional timeouts so use 100ms
* instead.
*/
- if (intel_de_wait_for_clear(i915, IPS_CTL, IPS_ENABLE, 100))
- drm_err(&i915->drm,
+ if (intel_de_wait_for_clear(display, IPS_CTL, IPS_ENABLE, 100))
+ drm_err(display->drm,
"Timed out waiting for IPS disable\n");
} else {
- intel_de_write(i915, IPS_CTL, 0);
- intel_de_posting_read(i915, IPS_CTL);
+ intel_de_write(display, IPS_CTL, 0);
+ intel_de_posting_read(display, IPS_CTL);
}
/* We need to wait for a vblank before we can disable the plane. */
@@ -188,6 +190,7 @@ bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
@@ -195,7 +198,7 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
if (!hsw_crtc_supports_ips(crtc))
return false;
- if (!i915->display.params.enable_ips)
+ if (!display->params.enable_ips)
return false;
if (crtc_state->pipe_bpp > 24)
@@ -209,7 +212,7 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
* Should measure whether using a lower cdclk w/o IPS
*/
if (IS_BROADWELL(i915) &&
- crtc_state->pixel_rate > i915->display.cdclk.max_cdclk_freq * 95 / 100)
+ crtc_state->pixel_rate > display->cdclk.max_cdclk_freq * 95 / 100)
return false;
return true;
@@ -259,6 +262,7 @@ int hsw_ips_compute_config(struct intel_atomic_state *state,
void hsw_ips_get_config(struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
@@ -266,7 +270,7 @@ void hsw_ips_get_config(struct intel_crtc_state *crtc_state)
return;
if (IS_HASWELL(i915)) {
- crtc_state->ips_enabled = intel_de_read(i915, IPS_CTL) & IPS_ENABLE;
+ crtc_state->ips_enabled = intel_de_read(display, IPS_CTL) & IPS_ENABLE;
} else {
/*
* We cannot readout IPS state on broadwell, set to
@@ -280,9 +284,9 @@ void hsw_ips_get_config(struct intel_crtc_state *crtc_state)
static int hsw_ips_debugfs_false_color_get(void *data, u64 *val)
{
struct intel_crtc *crtc = data;
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
- *val = i915->display.ips.false_color;
+ *val = display->ips.false_color;
return 0;
}
@@ -290,7 +294,7 @@ static int hsw_ips_debugfs_false_color_get(void *data, u64 *val)
static int hsw_ips_debugfs_false_color_set(void *data, u64 val)
{
struct intel_crtc *crtc = data;
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
struct intel_crtc_state *crtc_state;
int ret;
@@ -298,7 +302,7 @@ static int hsw_ips_debugfs_false_color_set(void *data, u64 val)
if (ret)
return ret;
- i915->display.ips.false_color = val;
+ display->ips.false_color = val;
crtc_state = to_intel_crtc_state(crtc->base.state);
@@ -325,18 +329,19 @@ DEFINE_DEBUGFS_ATTRIBUTE(hsw_ips_debugfs_false_color_fops,
static int hsw_ips_debugfs_status_show(struct seq_file *m, void *unused)
{
struct intel_crtc *crtc = m->private;
+ struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
intel_wakeref_t wakeref;
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
seq_printf(m, "Enabled by kernel parameter: %s\n",
- str_yes_no(i915->display.params.enable_ips));
+ str_yes_no(display->params.enable_ips));
- if (DISPLAY_VER(i915) >= 8) {
+ if (DISPLAY_VER(display) >= 8) {
seq_puts(m, "Currently: unknown\n");
} else {
- if (intel_de_read(i915, IPS_CTL) & IPS_ENABLE)
+ if (intel_de_read(display, IPS_CTL) & IPS_ENABLE)
seq_puts(m, "Currently: enabled\n");
else
seq_puts(m, "Currently: disabled\n");
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 87a27d91d15d..8a49f499e3fb 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -46,43 +46,44 @@
#include "intel_dsi.h"
#include "intel_dsi_vbt.h"
#include "intel_panel.h"
+#include "intel_pfit.h"
#include "intel_vdsc.h"
#include "intel_vdsc_regs.h"
#include "skl_scaler.h"
#include "skl_universal_plane.h"
-static int header_credits_available(struct drm_i915_private *dev_priv,
+static int header_credits_available(struct intel_display *display,
enum transcoder dsi_trans)
{
- return (intel_de_read(dev_priv, DSI_CMD_TXCTL(dsi_trans)) & FREE_HEADER_CREDIT_MASK)
+ return (intel_de_read(display, DSI_CMD_TXCTL(dsi_trans)) & FREE_HEADER_CREDIT_MASK)
>> FREE_HEADER_CREDIT_SHIFT;
}
-static int payload_credits_available(struct drm_i915_private *dev_priv,
+static int payload_credits_available(struct intel_display *display,
enum transcoder dsi_trans)
{
- return (intel_de_read(dev_priv, DSI_CMD_TXCTL(dsi_trans)) & FREE_PLOAD_CREDIT_MASK)
+ return (intel_de_read(display, DSI_CMD_TXCTL(dsi_trans)) & FREE_PLOAD_CREDIT_MASK)
>> FREE_PLOAD_CREDIT_SHIFT;
}
-static bool wait_for_header_credits(struct drm_i915_private *dev_priv,
+static bool wait_for_header_credits(struct intel_display *display,
enum transcoder dsi_trans, int hdr_credit)
{
- if (wait_for_us(header_credits_available(dev_priv, dsi_trans) >=
+ if (wait_for_us(header_credits_available(display, dsi_trans) >=
hdr_credit, 100)) {
- drm_err(&dev_priv->drm, "DSI header credits not released\n");
+ drm_err(display->drm, "DSI header credits not released\n");
return false;
}
return true;
}
-static bool wait_for_payload_credits(struct drm_i915_private *dev_priv,
+static bool wait_for_payload_credits(struct intel_display *display,
enum transcoder dsi_trans, int payld_credit)
{
- if (wait_for_us(payload_credits_available(dev_priv, dsi_trans) >=
+ if (wait_for_us(payload_credits_available(display, dsi_trans) >=
payld_credit, 100)) {
- drm_err(&dev_priv->drm, "DSI payload credits not released\n");
+ drm_err(display->drm, "DSI payload credits not released\n");
return false;
}
@@ -99,7 +100,7 @@ static enum transcoder dsi_port_to_transcoder(enum port port)
static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
struct mipi_dsi_device *dsi;
enum port port;
@@ -109,8 +110,8 @@ static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder)
/* wait for header/payload credits to be released */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- wait_for_header_credits(dev_priv, dsi_trans, MAX_HEADER_CREDIT);
- wait_for_payload_credits(dev_priv, dsi_trans, MAX_PLOAD_CREDIT);
+ wait_for_header_credits(display, dsi_trans, MAX_HEADER_CREDIT);
+ wait_for_payload_credits(display, dsi_trans, MAX_PLOAD_CREDIT);
}
/* send nop DCS command */
@@ -120,22 +121,22 @@ static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder)
dsi->channel = 0;
ret = mipi_dsi_dcs_nop(dsi);
if (ret < 0)
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"error sending DCS NOP command\n");
}
/* wait for header credits to be released */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- wait_for_header_credits(dev_priv, dsi_trans, MAX_HEADER_CREDIT);
+ wait_for_header_credits(display, dsi_trans, MAX_HEADER_CREDIT);
}
/* wait for LP TX in progress bit to be cleared */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- if (wait_for_us(!(intel_de_read(dev_priv, DSI_LP_MSG(dsi_trans)) &
+ if (wait_for_us(!(intel_de_read(display, DSI_LP_MSG(dsi_trans)) &
LPTX_IN_PROGRESS), 20))
- drm_err(&dev_priv->drm, "LPTX bit not cleared\n");
+ drm_err(display->drm, "LPTX bit not cleared\n");
}
}
@@ -143,7 +144,7 @@ static int dsi_send_pkt_payld(struct intel_dsi_host *host,
const struct mipi_dsi_packet *packet)
{
struct intel_dsi *intel_dsi = host->intel_dsi;
- struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev);
+ struct intel_display *display = to_intel_display(&intel_dsi->base);
enum transcoder dsi_trans = dsi_port_to_transcoder(host->port);
const u8 *data = packet->payload;
u32 len = packet->payload_length;
@@ -151,20 +152,20 @@ static int dsi_send_pkt_payld(struct intel_dsi_host *host,
/* payload queue can accept *256 bytes*, check limit */
if (len > MAX_PLOAD_CREDIT * 4) {
- drm_err(&i915->drm, "payload size exceeds max queue limit\n");
+ drm_err(display->drm, "payload size exceeds max queue limit\n");
return -EINVAL;
}
for (i = 0; i < len; i += 4) {
u32 tmp = 0;
- if (!wait_for_payload_credits(i915, dsi_trans, 1))
+ if (!wait_for_payload_credits(display, dsi_trans, 1))
return -EBUSY;
for (j = 0; j < min_t(u32, len - i, 4); j++)
tmp |= *data++ << 8 * j;
- intel_de_write(i915, DSI_CMD_TXPYLD(dsi_trans), tmp);
+ intel_de_write(display, DSI_CMD_TXPYLD(dsi_trans), tmp);
}
return 0;
@@ -175,14 +176,14 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host,
bool enable_lpdt)
{
struct intel_dsi *intel_dsi = host->intel_dsi;
- struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
+ struct intel_display *display = to_intel_display(&intel_dsi->base);
enum transcoder dsi_trans = dsi_port_to_transcoder(host->port);
u32 tmp;
- if (!wait_for_header_credits(dev_priv, dsi_trans, 1))
+ if (!wait_for_header_credits(display, dsi_trans, 1))
return -EBUSY;
- tmp = intel_de_read(dev_priv, DSI_CMD_TXHDR(dsi_trans));
+ tmp = intel_de_read(display, DSI_CMD_TXHDR(dsi_trans));
if (packet->payload)
tmp |= PAYLOAD_PRESENT;
@@ -201,15 +202,14 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host,
tmp |= ((packet->header[0] & DT_MASK) << DT_SHIFT);
tmp |= (packet->header[1] << PARAM_WC_LOWER_SHIFT);
tmp |= (packet->header[2] << PARAM_WC_UPPER_SHIFT);
- intel_de_write(dev_priv, DSI_CMD_TXHDR(dsi_trans), tmp);
+ intel_de_write(display, DSI_CMD_TXHDR(dsi_trans), tmp);
return 0;
}
void icl_dsi_frame_update(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_display *display = to_intel_display(crtc_state);
u32 mode_flags;
enum port port;
@@ -227,12 +227,13 @@ void icl_dsi_frame_update(struct intel_crtc_state *crtc_state)
else
return;
- intel_de_rmw(dev_priv, DSI_CMD_FRMCTL(port), 0, DSI_FRAME_UPDATE_REQUEST);
+ intel_de_rmw(display, DSI_CMD_FRMCTL(port), 0,
+ DSI_FRAME_UPDATE_REQUEST);
}
static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum phy phy;
u32 tmp, mask, val;
@@ -246,31 +247,31 @@ static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
mask = SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK;
val = SCALING_MODE_SEL(0x2) | TAP2_DISABLE | TAP3_DISABLE |
RTERM_SELECT(0x6);
- tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
+ tmp = intel_de_read(display, ICL_PORT_TX_DW5_LN(0, phy));
tmp &= ~mask;
tmp |= val;
- intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), tmp);
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW5_AUX(phy), mask, val);
+ intel_de_write(display, ICL_PORT_TX_DW5_GRP(phy), tmp);
+ intel_de_rmw(display, ICL_PORT_TX_DW5_AUX(phy), mask, val);
mask = SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
RCOMP_SCALAR_MASK;
val = SWING_SEL_UPPER(0x2) | SWING_SEL_LOWER(0x2) |
RCOMP_SCALAR(0x98);
- tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(0, phy));
+ tmp = intel_de_read(display, ICL_PORT_TX_DW2_LN(0, phy));
tmp &= ~mask;
tmp |= val;
- intel_de_write(dev_priv, ICL_PORT_TX_DW2_GRP(phy), tmp);
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_AUX(phy), mask, val);
+ intel_de_write(display, ICL_PORT_TX_DW2_GRP(phy), tmp);
+ intel_de_rmw(display, ICL_PORT_TX_DW2_AUX(phy), mask, val);
mask = POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
CURSOR_COEFF_MASK;
val = POST_CURSOR_1(0x0) | POST_CURSOR_2(0x0) |
CURSOR_COEFF(0x3f);
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_AUX(phy), mask, val);
+ intel_de_rmw(display, ICL_PORT_TX_DW4_AUX(phy), mask, val);
/* Bspec: must not use GRP register for write */
for (lane = 0; lane <= 3; lane++)
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(lane, phy),
+ intel_de_rmw(display, ICL_PORT_TX_DW4_LN(lane, phy),
mask, val);
}
}
@@ -278,13 +279,13 @@ static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
static void configure_dual_link_mode(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
i915_reg_t dss_ctl1_reg, dss_ctl2_reg;
u32 dss_ctl1;
/* FIXME: Move all DSS handling to intel_vdsc.c */
- if (DISPLAY_VER(dev_priv) >= 12) {
+ if (DISPLAY_VER(display) >= 12) {
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
dss_ctl1_reg = ICL_PIPE_DSS_CTL1(crtc->pipe);
@@ -294,7 +295,7 @@ static void configure_dual_link_mode(struct intel_encoder *encoder,
dss_ctl2_reg = DSS_CTL2;
}
- dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg);
+ dss_ctl1 = intel_de_read(display, dss_ctl1_reg);
dss_ctl1 |= SPLITTER_ENABLE;
dss_ctl1 &= ~OVERLAP_PIXELS_MASK;
dss_ctl1 |= OVERLAP_PIXELS(intel_dsi->pixel_overlap);
@@ -309,19 +310,19 @@ static void configure_dual_link_mode(struct intel_encoder *encoder,
dl_buffer_depth = hactive / 2 + intel_dsi->pixel_overlap;
if (dl_buffer_depth > MAX_DL_BUFFER_TARGET_DEPTH)
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"DL buffer depth exceed max value\n");
dss_ctl1 &= ~LEFT_DL_BUF_TARGET_DEPTH_MASK;
dss_ctl1 |= LEFT_DL_BUF_TARGET_DEPTH(dl_buffer_depth);
- intel_de_rmw(dev_priv, dss_ctl2_reg, RIGHT_DL_BUF_TARGET_DEPTH_MASK,
+ intel_de_rmw(display, dss_ctl2_reg, RIGHT_DL_BUF_TARGET_DEPTH_MASK,
RIGHT_DL_BUF_TARGET_DEPTH(dl_buffer_depth));
} else {
/* Interleave */
dss_ctl1 |= DUAL_LINK_MODE_INTERLEAVE;
}
- intel_de_write(dev_priv, dss_ctl1_reg, dss_ctl1);
+ intel_de_write(display, dss_ctl1_reg, dss_ctl1);
}
/* aka DSI 8X clock */
@@ -342,6 +343,7 @@ static int afe_clk(struct intel_encoder *encoder,
static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
@@ -361,33 +363,34 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
}
for_each_dsi_port(port, intel_dsi->ports) {
- intel_de_write(dev_priv, ICL_DSI_ESC_CLK_DIV(port),
+ intel_de_write(display, ICL_DSI_ESC_CLK_DIV(port),
esc_clk_div_m & ICL_ESC_CLK_DIV_MASK);
- intel_de_posting_read(dev_priv, ICL_DSI_ESC_CLK_DIV(port));
+ intel_de_posting_read(display, ICL_DSI_ESC_CLK_DIV(port));
}
for_each_dsi_port(port, intel_dsi->ports) {
- intel_de_write(dev_priv, ICL_DPHY_ESC_CLK_DIV(port),
+ intel_de_write(display, ICL_DPHY_ESC_CLK_DIV(port),
esc_clk_div_m & ICL_ESC_CLK_DIV_MASK);
- intel_de_posting_read(dev_priv, ICL_DPHY_ESC_CLK_DIV(port));
+ intel_de_posting_read(display, ICL_DPHY_ESC_CLK_DIV(port));
}
if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
for_each_dsi_port(port, intel_dsi->ports) {
- intel_de_write(dev_priv, ADL_MIPIO_DW(port, 8),
+ intel_de_write(display, ADL_MIPIO_DW(port, 8),
esc_clk_div_m_phy & TX_ESC_CLK_DIV_PHY);
- intel_de_posting_read(dev_priv, ADL_MIPIO_DW(port, 8));
+ intel_de_posting_read(display, ADL_MIPIO_DW(port, 8));
}
}
}
-static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv,
- struct intel_dsi *intel_dsi)
+static void get_dsi_io_power_domains(struct intel_dsi *intel_dsi)
{
+ struct intel_display *display = to_intel_display(&intel_dsi->base);
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
enum port port;
for_each_dsi_port(port, intel_dsi->ports) {
- drm_WARN_ON(&dev_priv->drm, intel_dsi->io_wakeref[port]);
+ drm_WARN_ON(display->drm, intel_dsi->io_wakeref[port]);
intel_dsi->io_wakeref[port] =
intel_display_power_get(dev_priv,
port == PORT_A ?
@@ -398,15 +401,15 @@ static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv,
static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_rmw(dev_priv, ICL_DSI_IO_MODECTL(port),
+ intel_de_rmw(display, ICL_DSI_IO_MODECTL(port),
0, COMBO_PHY_MODE_DSI);
- get_dsi_io_power_domains(dev_priv, intel_dsi);
+ get_dsi_io_power_domains(intel_dsi);
}
static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
@@ -422,6 +425,7 @@ static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum phy phy;
@@ -430,32 +434,33 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
/* Step 4b(i) set loadgen select for transmit and aux lanes */
for_each_dsi_phy(phy, intel_dsi->phys) {
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_AUX(phy), LOADGEN_SELECT, 0);
+ intel_de_rmw(display, ICL_PORT_TX_DW4_AUX(phy),
+ LOADGEN_SELECT, 0);
for (lane = 0; lane <= 3; lane++)
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(lane, phy),
+ intel_de_rmw(display, ICL_PORT_TX_DW4_LN(lane, phy),
LOADGEN_SELECT, lane != 2 ? LOADGEN_SELECT : 0);
}
/* Step 4b(ii) set latency optimization for transmit and aux lanes */
for_each_dsi_phy(phy, intel_dsi->phys) {
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_AUX(phy),
+ intel_de_rmw(display, ICL_PORT_TX_DW2_AUX(phy),
FRC_LATENCY_OPTIM_MASK, FRC_LATENCY_OPTIM_VAL(0x5));
- tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(0, phy));
+ tmp = intel_de_read(display, ICL_PORT_TX_DW2_LN(0, phy));
tmp &= ~FRC_LATENCY_OPTIM_MASK;
tmp |= FRC_LATENCY_OPTIM_VAL(0x5);
- intel_de_write(dev_priv, ICL_PORT_TX_DW2_GRP(phy), tmp);
+ intel_de_write(display, ICL_PORT_TX_DW2_GRP(phy), tmp);
/* For EHL, TGL, set latency optimization for PCS_DW1 lanes */
if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv) ||
- (DISPLAY_VER(dev_priv) >= 12)) {
- intel_de_rmw(dev_priv, ICL_PORT_PCS_DW1_AUX(phy),
+ (DISPLAY_VER(display) >= 12)) {
+ intel_de_rmw(display, ICL_PORT_PCS_DW1_AUX(phy),
LATENCY_OPTIM_MASK, LATENCY_OPTIM_VAL(0));
- tmp = intel_de_read(dev_priv,
+ tmp = intel_de_read(display,
ICL_PORT_PCS_DW1_LN(0, phy));
tmp &= ~LATENCY_OPTIM_MASK;
tmp |= LATENCY_OPTIM_VAL(0x1);
- intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy),
+ intel_de_write(display, ICL_PORT_PCS_DW1_GRP(phy),
tmp);
}
}
@@ -464,17 +469,17 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
u32 tmp;
enum phy phy;
/* clear common keeper enable bit */
for_each_dsi_phy(phy, intel_dsi->phys) {
- tmp = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy));
+ tmp = intel_de_read(display, ICL_PORT_PCS_DW1_LN(0, phy));
tmp &= ~COMMON_KEEPER_EN;
- intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), tmp);
- intel_de_rmw(dev_priv, ICL_PORT_PCS_DW1_AUX(phy), COMMON_KEEPER_EN, 0);
+ intel_de_write(display, ICL_PORT_PCS_DW1_GRP(phy), tmp);
+ intel_de_rmw(display, ICL_PORT_PCS_DW1_AUX(phy), COMMON_KEEPER_EN, 0);
}
/*
@@ -483,14 +488,15 @@ static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
* as part of lane phy sequence configuration
*/
for_each_dsi_phy(phy, intel_dsi->phys)
- intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy), 0, SUS_CLOCK_CONFIG);
+ intel_de_rmw(display, ICL_PORT_CL_DW5(phy), 0,
+ SUS_CLOCK_CONFIG);
/* Clear training enable to change swing values */
for_each_dsi_phy(phy, intel_dsi->phys) {
- tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
+ tmp = intel_de_read(display, ICL_PORT_TX_DW5_LN(0, phy));
tmp &= ~TX_TRAINING_EN;
- intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), tmp);
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW5_AUX(phy), TX_TRAINING_EN, 0);
+ intel_de_write(display, ICL_PORT_TX_DW5_GRP(phy), tmp);
+ intel_de_rmw(display, ICL_PORT_TX_DW5_AUX(phy), TX_TRAINING_EN, 0);
}
/* Program swing and de-emphasis */
@@ -498,26 +504,26 @@ static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
/* Set training enable to trigger update */
for_each_dsi_phy(phy, intel_dsi->phys) {
- tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
+ tmp = intel_de_read(display, ICL_PORT_TX_DW5_LN(0, phy));
tmp |= TX_TRAINING_EN;
- intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), tmp);
- intel_de_rmw(dev_priv, ICL_PORT_TX_DW5_AUX(phy), 0, TX_TRAINING_EN);
+ intel_de_write(display, ICL_PORT_TX_DW5_GRP(phy), tmp);
+ intel_de_rmw(display, ICL_PORT_TX_DW5_AUX(phy), 0, TX_TRAINING_EN);
}
}
static void gen11_dsi_enable_ddi_buffer(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
for_each_dsi_port(port, intel_dsi->ports) {
- intel_de_rmw(dev_priv, DDI_BUF_CTL(port), 0, DDI_BUF_CTL_ENABLE);
+ intel_de_rmw(display, DDI_BUF_CTL(port), 0, DDI_BUF_CTL_ENABLE);
- if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
+ if (wait_for_us(!(intel_de_read(display, DDI_BUF_CTL(port)) &
DDI_BUF_IS_IDLE),
500))
- drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
+ drm_err(display->drm, "DDI port:%c buffer idle\n",
port_name(port));
}
}
@@ -526,6 +532,7 @@ static void
gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
@@ -533,12 +540,12 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
/* Program DPHY clock lanes timings */
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_write(dev_priv, DPHY_CLK_TIMING_PARAM(port),
+ intel_de_write(display, DPHY_CLK_TIMING_PARAM(port),
intel_dsi->dphy_reg);
/* Program DPHY data lanes timings */
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_write(dev_priv, DPHY_DATA_TIMING_PARAM(port),
+ intel_de_write(display, DPHY_DATA_TIMING_PARAM(port),
intel_dsi->dphy_data_lane_reg);
/*
@@ -547,10 +554,10 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
* a value '0' inside TA_PARAM_REGISTERS otherwise
* leave all fields at HW default values.
*/
- if (DISPLAY_VER(dev_priv) == 11) {
+ if (DISPLAY_VER(display) == 11) {
if (afe_clk(encoder, crtc_state) <= 800000) {
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_rmw(dev_priv, DPHY_TA_TIMING_PARAM(port),
+ intel_de_rmw(display, DPHY_TA_TIMING_PARAM(port),
TA_SURE_MASK,
TA_SURE_OVERRIDE | TA_SURE(0));
}
@@ -558,7 +565,7 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
for_each_dsi_phy(phy, intel_dsi->phys)
- intel_de_rmw(dev_priv, ICL_DPHY_CHKN(phy),
+ intel_de_rmw(display, ICL_DPHY_CHKN(phy),
0, ICL_DPHY_CHKN_AFE_OVER_PPI_STRAP);
}
}
@@ -567,30 +574,30 @@ static void
gen11_dsi_setup_timings(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
/* Program T-INIT master registers */
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_rmw(dev_priv, ICL_DSI_T_INIT_MASTER(port),
+ intel_de_rmw(display, ICL_DSI_T_INIT_MASTER(port),
DSI_T_INIT_MASTER_MASK, intel_dsi->init_count);
/* shadow register inside display core */
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_write(dev_priv, DSI_CLK_TIMING_PARAM(port),
+ intel_de_write(display, DSI_CLK_TIMING_PARAM(port),
intel_dsi->dphy_reg);
/* shadow register inside display core */
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_write(dev_priv, DSI_DATA_TIMING_PARAM(port),
+ intel_de_write(display, DSI_DATA_TIMING_PARAM(port),
intel_dsi->dphy_data_lane_reg);
/* shadow register inside display core */
- if (DISPLAY_VER(dev_priv) == 11) {
+ if (DISPLAY_VER(display) == 11) {
if (afe_clk(encoder, crtc_state) <= 800000) {
for_each_dsi_port(port, intel_dsi->ports) {
- intel_de_rmw(dev_priv, DSI_TA_TIMING_PARAM(port),
+ intel_de_rmw(display, DSI_TA_TIMING_PARAM(port),
TA_SURE_MASK,
TA_SURE_OVERRIDE | TA_SURE(0));
}
@@ -600,45 +607,45 @@ gen11_dsi_setup_timings(struct intel_encoder *encoder,
static void gen11_dsi_gate_clocks(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
u32 tmp;
enum phy phy;
- mutex_lock(&dev_priv->display.dpll.lock);
- tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
+ mutex_lock(&display->dpll.lock);
+ tmp = intel_de_read(display, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys)
tmp |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
- intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
- mutex_unlock(&dev_priv->display.dpll.lock);
+ intel_de_write(display, ICL_DPCLKA_CFGCR0, tmp);
+ mutex_unlock(&display->dpll.lock);
}
static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
u32 tmp;
enum phy phy;
- mutex_lock(&dev_priv->display.dpll.lock);
- tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
+ mutex_lock(&display->dpll.lock);
+ tmp = intel_de_read(display, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys)
tmp &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
- intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
- mutex_unlock(&dev_priv->display.dpll.lock);
+ intel_de_write(display, ICL_DPCLKA_CFGCR0, tmp);
+ mutex_unlock(&display->dpll.lock);
}
static bool gen11_dsi_is_clock_enabled(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
bool clock_enabled = false;
enum phy phy;
u32 tmp;
- tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
+ tmp = intel_de_read(display, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys) {
if (!(tmp & ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)))
@@ -651,36 +658,36 @@ static bool gen11_dsi_is_clock_enabled(struct intel_encoder *encoder)
static void gen11_dsi_map_pll(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
enum phy phy;
u32 val;
- mutex_lock(&dev_priv->display.dpll.lock);
+ mutex_lock(&display->dpll.lock);
- val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
+ val = intel_de_read(display, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys) {
val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
val |= ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy);
}
- intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
+ intel_de_write(display, ICL_DPCLKA_CFGCR0, val);
for_each_dsi_phy(phy, intel_dsi->phys) {
val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
}
- intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
+ intel_de_write(display, ICL_DPCLKA_CFGCR0, val);
- intel_de_posting_read(dev_priv, ICL_DPCLKA_CFGCR0);
+ intel_de_posting_read(display, ICL_DPCLKA_CFGCR0);
- mutex_unlock(&dev_priv->display.dpll.lock);
+ mutex_unlock(&display->dpll.lock);
}
static void
gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
enum pipe pipe = crtc->pipe;
@@ -690,7 +697,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- tmp = intel_de_read(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans));
+ tmp = intel_de_read(display, DSI_TRANS_FUNC_CONF(dsi_trans));
if (intel_dsi->eotp_pkt)
tmp &= ~EOTP_DISABLED;
@@ -746,7 +753,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
}
}
- if (DISPLAY_VER(dev_priv) >= 12) {
+ if (DISPLAY_VER(display) >= 12) {
if (is_vid_mode(intel_dsi))
tmp |= BLANKING_PACKET_ENABLE;
}
@@ -779,15 +786,15 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
tmp |= TE_SOURCE_GPIO;
}
- intel_de_write(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans), tmp);
+ intel_de_write(display, DSI_TRANS_FUNC_CONF(dsi_trans), tmp);
}
/* enable port sync mode if dual link */
if (intel_dsi->dual_link) {
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_rmw(dev_priv,
- TRANS_DDI_FUNC_CTL2(dev_priv, dsi_trans),
+ intel_de_rmw(display,
+ TRANS_DDI_FUNC_CTL2(display, dsi_trans),
0, PORT_SYNC_MODE_ENABLE);
}
@@ -799,8 +806,8 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
dsi_trans = dsi_port_to_transcoder(port);
/* select data lane width */
- tmp = intel_de_read(dev_priv,
- TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans));
+ tmp = intel_de_read(display,
+ TRANS_DDI_FUNC_CTL(display, dsi_trans));
tmp &= ~DDI_PORT_WIDTH_MASK;
tmp |= DDI_PORT_WIDTH(intel_dsi->lane_count);
@@ -826,16 +833,16 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
/* enable DDI buffer */
tmp |= TRANS_DDI_FUNC_ENABLE;
- intel_de_write(dev_priv,
- TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans), tmp);
+ intel_de_write(display,
+ TRANS_DDI_FUNC_CTL(display, dsi_trans), tmp);
}
/* wait for link ready */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- if (wait_for_us((intel_de_read(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans)) &
+ if (wait_for_us((intel_de_read(display, DSI_TRANS_FUNC_CONF(dsi_trans)) &
LINK_READY), 2500))
- drm_err(&dev_priv->drm, "DSI link not ready\n");
+ drm_err(display->drm, "DSI link not ready\n");
}
}
@@ -843,7 +850,7 @@ static void
gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
@@ -910,17 +917,17 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
/* minimum hactive as per bspec: 256 pixels */
if (adjusted_mode->crtc_hdisplay < 256)
- drm_err(&dev_priv->drm, "hactive is less then 256 pixels\n");
+ drm_err(display->drm, "hactive is less then 256 pixels\n");
/* if RGB666 format, then hactive must be multiple of 4 pixels */
if (intel_dsi->pixel_format == MIPI_DSI_FMT_RGB666 && hactive % 4 != 0)
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"hactive pixels are not multiple of 4\n");
/* program TRANS_HTOTAL register */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_write(dev_priv, TRANS_HTOTAL(dev_priv, dsi_trans),
+ intel_de_write(display, TRANS_HTOTAL(display, dsi_trans),
HACTIVE(hactive - 1) | HTOTAL(htotal - 1));
}
@@ -929,12 +936,12 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
if (intel_dsi->video_mode == NON_BURST_SYNC_PULSE) {
/* BSPEC: hsync size should be atleast 16 pixels */
if (hsync_size < 16)
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"hsync size < 16 pixels\n");
}
if (hback_porch < 16)
- drm_err(&dev_priv->drm, "hback porch < 16 pixels\n");
+ drm_err(display->drm, "hback porch < 16 pixels\n");
if (intel_dsi->dual_link) {
hsync_start /= 2;
@@ -943,8 +950,8 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_write(dev_priv,
- TRANS_HSYNC(dev_priv, dsi_trans),
+ intel_de_write(display,
+ TRANS_HSYNC(display, dsi_trans),
HSYNC_START(hsync_start - 1) | HSYNC_END(hsync_end - 1));
}
}
@@ -958,22 +965,22 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
* struct drm_display_mode.
* For interlace mode: program required pixel minus 2
*/
- intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, dsi_trans),
+ intel_de_write(display, TRANS_VTOTAL(display, dsi_trans),
VACTIVE(vactive - 1) | VTOTAL(vtotal - 1));
}
if (vsync_end < vsync_start || vsync_end > vtotal)
- drm_err(&dev_priv->drm, "Invalid vsync_end value\n");
+ drm_err(display->drm, "Invalid vsync_end value\n");
if (vsync_start < vactive)
- drm_err(&dev_priv->drm, "vsync_start less than vactive\n");
+ drm_err(display->drm, "vsync_start less than vactive\n");
/* program TRANS_VSYNC register for video mode only */
if (is_vid_mode(intel_dsi)) {
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_write(dev_priv,
- TRANS_VSYNC(dev_priv, dsi_trans),
+ intel_de_write(display,
+ TRANS_VSYNC(display, dsi_trans),
VSYNC_START(vsync_start - 1) | VSYNC_END(vsync_end - 1));
}
}
@@ -987,8 +994,8 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
if (is_vid_mode(intel_dsi)) {
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_write(dev_priv,
- TRANS_VSYNCSHIFT(dev_priv, dsi_trans),
+ intel_de_write(display,
+ TRANS_VSYNCSHIFT(display, dsi_trans),
vsync_shift);
}
}
@@ -999,11 +1006,11 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
* FIXME get rid of these local hacks and do it right,
* this will not handle eg. delayed vblank correctly.
*/
- if (DISPLAY_VER(dev_priv) >= 12) {
+ if (DISPLAY_VER(display) >= 12) {
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_write(dev_priv,
- TRANS_VBLANK(dev_priv, dsi_trans),
+ intel_de_write(display,
+ TRANS_VBLANK(display, dsi_trans),
VBLANK_START(vactive - 1) | VBLANK_END(vtotal - 1));
}
}
@@ -1011,20 +1018,20 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
static void gen11_dsi_enable_transcoder(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
enum transcoder dsi_trans;
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_rmw(dev_priv, TRANSCONF(dev_priv, dsi_trans), 0,
+ intel_de_rmw(display, TRANSCONF(display, dsi_trans), 0,
TRANSCONF_ENABLE);
/* wait for transcoder to be enabled */
- if (intel_de_wait_for_set(dev_priv, TRANSCONF(dev_priv, dsi_trans),
+ if (intel_de_wait_for_set(display, TRANSCONF(display, dsi_trans),
TRANSCONF_STATE_ENABLE, 10))
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"DSI transcoder not enabled\n");
}
}
@@ -1032,7 +1039,7 @@ static void gen11_dsi_enable_transcoder(struct intel_encoder *encoder)
static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
enum transcoder dsi_trans;
@@ -1056,21 +1063,21 @@ static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder,
dsi_trans = dsi_port_to_transcoder(port);
/* program hst_tx_timeout */
- intel_de_rmw(dev_priv, DSI_HSTX_TO(dsi_trans),
+ intel_de_rmw(display, DSI_HSTX_TO(dsi_trans),
HSTX_TIMEOUT_VALUE_MASK,
HSTX_TIMEOUT_VALUE(hs_tx_timeout));
/* FIXME: DSI_CALIB_TO */
/* program lp_rx_host timeout */
- intel_de_rmw(dev_priv, DSI_LPRX_HOST_TO(dsi_trans),
+ intel_de_rmw(display, DSI_LPRX_HOST_TO(dsi_trans),
LPRX_TIMEOUT_VALUE_MASK,
LPRX_TIMEOUT_VALUE(lp_rx_timeout));
/* FIXME: DSI_PWAIT_TO */
/* program turn around timeout */
- intel_de_rmw(dev_priv, DSI_TA_TO(dsi_trans),
+ intel_de_rmw(display, DSI_TA_TO(dsi_trans),
TA_TIMEOUT_VALUE_MASK,
TA_TIMEOUT_VALUE(ta_timeout));
}
@@ -1079,7 +1086,7 @@ static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder,
static void gen11_dsi_config_util_pin(struct intel_encoder *encoder,
bool enable)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
u32 tmp;
@@ -1091,7 +1098,7 @@ static void gen11_dsi_config_util_pin(struct intel_encoder *encoder,
if (is_vid_mode(intel_dsi) || (intel_dsi->ports & BIT(PORT_B)))
return;
- tmp = intel_de_read(dev_priv, UTIL_PIN_CTL);
+ tmp = intel_de_read(display, UTIL_PIN_CTL);
if (enable) {
tmp |= UTIL_PIN_DIRECTION_INPUT;
@@ -1099,7 +1106,7 @@ static void gen11_dsi_config_util_pin(struct intel_encoder *encoder,
} else {
tmp &= ~UTIL_PIN_ENABLE;
}
- intel_de_write(dev_priv, UTIL_PIN_CTL, tmp);
+ intel_de_write(display, UTIL_PIN_CTL, tmp);
}
static void
@@ -1137,7 +1144,7 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder,
static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
struct mipi_dsi_device *dsi;
enum port port;
@@ -1153,14 +1160,14 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
* FIXME: This uses the number of DW's currently in the payload
* receive queue. This is probably not what we want here.
*/
- tmp = intel_de_read(dev_priv, DSI_CMD_RXCTL(dsi_trans));
+ tmp = intel_de_read(display, DSI_CMD_RXCTL(dsi_trans));
tmp &= NUMBER_RX_PLOAD_DW_MASK;
/* multiply "Number Rx Payload DW" by 4 to get max value */
tmp = tmp * 4;
dsi = intel_dsi->dsi_hosts[port]->device;
ret = mipi_dsi_set_maximum_return_packet_size(dsi, tmp);
if (ret < 0)
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"error setting max return pkt size%d\n", tmp);
}
@@ -1220,10 +1227,10 @@ static void gen11_dsi_pre_enable(struct intel_atomic_state *state,
static void icl_apply_kvmr_pipe_a_wa(struct intel_encoder *encoder,
enum pipe pipe, bool enable)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
- if (DISPLAY_VER(dev_priv) == 11 && pipe == PIPE_B)
- intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
+ if (DISPLAY_VER(display) == 11 && pipe == PIPE_B)
+ intel_de_rmw(display, CHICKEN_PAR1_1,
IGNORE_KVMR_PIPE_A,
enable ? IGNORE_KVMR_PIPE_A : 0);
}
@@ -1236,13 +1243,13 @@ static void icl_apply_kvmr_pipe_a_wa(struct intel_encoder *encoder,
*/
static void adlp_set_lp_hs_wakeup_gb(struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
- if (DISPLAY_VER(i915) == 13) {
+ if (DISPLAY_VER(display) == 13) {
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_rmw(i915, TGL_DSI_CHKN_REG(port),
+ intel_de_rmw(display, TGL_DSI_CHKN_REG(port),
TGL_DSI_CHKN_LSHS_GB_MASK,
TGL_DSI_CHKN_LSHS_GB(4));
}
@@ -1276,7 +1283,7 @@ static void gen11_dsi_enable(struct intel_atomic_state *state,
static void gen11_dsi_disable_transcoder(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
enum transcoder dsi_trans;
@@ -1285,13 +1292,13 @@ static void gen11_dsi_disable_transcoder(struct intel_encoder *encoder)
dsi_trans = dsi_port_to_transcoder(port);
/* disable transcoder */
- intel_de_rmw(dev_priv, TRANSCONF(dev_priv, dsi_trans),
+ intel_de_rmw(display, TRANSCONF(display, dsi_trans),
TRANSCONF_ENABLE, 0);
/* wait for transcoder to be disabled */
- if (intel_de_wait_for_clear(dev_priv, TRANSCONF(dev_priv, dsi_trans),
+ if (intel_de_wait_for_clear(display, TRANSCONF(display, dsi_trans),
TRANSCONF_STATE_ENABLE, 50))
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"DSI trancoder not disabled\n");
}
}
@@ -1308,7 +1315,7 @@ static void gen11_dsi_powerdown_panel(struct intel_encoder *encoder)
static void gen11_dsi_deconfigure_trancoder(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
enum transcoder dsi_trans;
@@ -1317,29 +1324,29 @@ static void gen11_dsi_deconfigure_trancoder(struct intel_encoder *encoder)
/* disable periodic update mode */
if (is_cmd_mode(intel_dsi)) {
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_rmw(dev_priv, DSI_CMD_FRMCTL(port),
+ intel_de_rmw(display, DSI_CMD_FRMCTL(port),
DSI_PERIODIC_FRAME_UPDATE_ENABLE, 0);
}
/* put dsi link in ULPS */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- tmp = intel_de_read(dev_priv, DSI_LP_MSG(dsi_trans));
+ tmp = intel_de_read(display, DSI_LP_MSG(dsi_trans));
tmp |= LINK_ENTER_ULPS;
tmp &= ~LINK_ULPS_TYPE_LP11;
- intel_de_write(dev_priv, DSI_LP_MSG(dsi_trans), tmp);
+ intel_de_write(display, DSI_LP_MSG(dsi_trans), tmp);
- if (wait_for_us((intel_de_read(dev_priv, DSI_LP_MSG(dsi_trans)) &
+ if (wait_for_us((intel_de_read(display, DSI_LP_MSG(dsi_trans)) &
LINK_IN_ULPS),
10))
- drm_err(&dev_priv->drm, "DSI link not in ULPS\n");
+ drm_err(display->drm, "DSI link not in ULPS\n");
}
/* disable ddi function */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_rmw(dev_priv,
- TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans),
+ intel_de_rmw(display,
+ TRANS_DDI_FUNC_CTL(display, dsi_trans),
TRANS_DDI_FUNC_ENABLE, 0);
}
@@ -1347,8 +1354,8 @@ static void gen11_dsi_deconfigure_trancoder(struct intel_encoder *encoder)
if (intel_dsi->dual_link) {
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- intel_de_rmw(dev_priv,
- TRANS_DDI_FUNC_CTL2(dev_priv, dsi_trans),
+ intel_de_rmw(display,
+ TRANS_DDI_FUNC_CTL2(display, dsi_trans),
PORT_SYNC_MODE_ENABLE, 0);
}
}
@@ -1356,18 +1363,18 @@ static void gen11_dsi_deconfigure_trancoder(struct intel_encoder *encoder)
static void gen11_dsi_disable_port(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
gen11_dsi_ungate_clocks(encoder);
for_each_dsi_port(port, intel_dsi->ports) {
- intel_de_rmw(dev_priv, DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE, 0);
+ intel_de_rmw(display, DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE, 0);
- if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
+ if (wait_for_us((intel_de_read(display, DDI_BUF_CTL(port)) &
DDI_BUF_IS_IDLE),
8))
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"DDI port:%c buffer not idle\n",
port_name(port));
}
@@ -1376,6 +1383,7 @@ static void gen11_dsi_disable_port(struct intel_encoder *encoder)
static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
@@ -1393,7 +1401,7 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
/* set mode to DDI */
for_each_dsi_port(port, intel_dsi->ports)
- intel_de_rmw(dev_priv, ICL_DSI_IO_MODECTL(port),
+ intel_de_rmw(display, ICL_DSI_IO_MODECTL(port),
COMBO_PHY_MODE_DSI, 0);
}
@@ -1505,8 +1513,7 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder,
static bool gen11_dsi_is_periodic_cmd_mode(struct intel_dsi *intel_dsi)
{
- struct drm_device *dev = intel_dsi->base.base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_display *display = to_intel_display(&intel_dsi->base);
enum transcoder dsi_trans;
u32 val;
@@ -1515,7 +1522,7 @@ static bool gen11_dsi_is_periodic_cmd_mode(struct intel_dsi *intel_dsi)
else
dsi_trans = TRANSCODER_DSI_0;
- val = intel_de_read(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans));
+ val = intel_de_read(display, DSI_TRANS_FUNC_CONF(dsi_trans));
return (val & DSI_PERIODIC_FRAME_UPDATE_ENABLE);
}
@@ -1558,7 +1565,7 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder,
static void gen11_dsi_sync_state(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *intel_crtc;
enum pipe pipe;
@@ -1569,9 +1576,9 @@ static void gen11_dsi_sync_state(struct intel_encoder *encoder,
pipe = intel_crtc->pipe;
/* wa verify 1409054076:icl,jsl,ehl */
- if (DISPLAY_VER(dev_priv) == 11 && pipe == PIPE_B &&
- !(intel_de_read(dev_priv, CHICKEN_PAR1_1) & IGNORE_KVMR_PIPE_A))
- drm_dbg_kms(&dev_priv->drm,
+ if (DISPLAY_VER(display) == 11 && pipe == PIPE_B &&
+ !(intel_de_read(display, CHICKEN_PAR1_1) & IGNORE_KVMR_PIPE_A))
+ drm_dbg_kms(display->drm,
"[ENCODER:%d:%s] BIOS left IGNORE_KVMR_PIPE_A cleared with pipe B enabled\n",
encoder->base.base.id,
encoder->base.name);
@@ -1580,9 +1587,9 @@ static void gen11_dsi_sync_state(struct intel_encoder *encoder,
static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
- int dsc_max_bpc = DISPLAY_VER(dev_priv) >= 12 ? 12 : 10;
+ int dsc_max_bpc = DISPLAY_VER(display) >= 12 ? 12 : 10;
bool use_dsc;
int ret;
@@ -1607,12 +1614,12 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
return ret;
/* DSI specific sanity checks on the common code */
- drm_WARN_ON(&dev_priv->drm, vdsc_cfg->vbr_enable);
- drm_WARN_ON(&dev_priv->drm, vdsc_cfg->simple_422);
- drm_WARN_ON(&dev_priv->drm,
+ drm_WARN_ON(display->drm, vdsc_cfg->vbr_enable);
+ drm_WARN_ON(display->drm, vdsc_cfg->simple_422);
+ drm_WARN_ON(display->drm,
vdsc_cfg->pic_width % vdsc_cfg->slice_width);
- drm_WARN_ON(&dev_priv->drm, vdsc_cfg->slice_height < 8);
- drm_WARN_ON(&dev_priv->drm,
+ drm_WARN_ON(display->drm, vdsc_cfg->slice_height < 8);
+ drm_WARN_ON(display->drm,
vdsc_cfg->pic_height % vdsc_cfg->slice_height);
ret = drm_dsc_compute_rc_parameters(vdsc_cfg);
@@ -1628,7 +1635,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
struct intel_connector *intel_connector = intel_dsi->attached_connector;
struct drm_display_mode *adjusted_mode =
@@ -1662,7 +1669,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder,
pipe_config->clock_set = true;
if (gen11_dsi_dsc_compute_config(encoder, pipe_config))
- drm_dbg_kms(&i915->drm, "Attempting to use DSC failed\n");
+ drm_dbg_kms(display->drm, "Attempting to use DSC failed\n");
pipe_config->port_clock = afe_clk(encoder, pipe_config) / 5;
@@ -1680,15 +1687,13 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder,
static void gen11_dsi_get_power_domains(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
-
- get_dsi_io_power_domains(i915,
- enc_to_intel_dsi(encoder));
+ get_dsi_io_power_domains(enc_to_intel_dsi(encoder));
}
static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum transcoder dsi_trans;
@@ -1704,8 +1709,8 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
- tmp = intel_de_read(dev_priv,
- TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans));
+ tmp = intel_de_read(display,
+ TRANS_DDI_FUNC_CTL(display, dsi_trans));
switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
case TRANS_DDI_EDP_INPUT_A_ON:
*pipe = PIPE_A;
@@ -1720,11 +1725,11 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
*pipe = PIPE_D;
break;
default:
- drm_err(&dev_priv->drm, "Invalid PIPE input\n");
+ drm_err(display->drm, "Invalid PIPE input\n");
goto out;
}
- tmp = intel_de_read(dev_priv, TRANSCONF(dev_priv, dsi_trans));
+ tmp = intel_de_read(display, TRANSCONF(display, dsi_trans));
ret = tmp & TRANSCONF_ENABLE;
}
out:
@@ -1834,8 +1839,7 @@ static const struct mipi_dsi_host_ops gen11_dsi_host_ops = {
static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
{
- struct drm_device *dev = intel_dsi->base.base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_display *display = to_intel_display(&intel_dsi->base);
struct intel_connector *connector = intel_dsi->attached_connector;
struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
u32 tlpx_ns;
@@ -1859,7 +1863,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
*/
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
if (prepare_cnt > ICL_PREPARE_CNT_MAX) {
- drm_dbg_kms(&dev_priv->drm, "prepare_cnt out of range (%d)\n",
+ drm_dbg_kms(display->drm, "prepare_cnt out of range (%d)\n",
prepare_cnt);
prepare_cnt = ICL_PREPARE_CNT_MAX;
}
@@ -1868,7 +1872,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
clk_zero_cnt = DIV_ROUND_UP(mipi_config->tclk_prepare_clkzero -
ths_prepare_ns, tlpx_ns);
if (clk_zero_cnt > ICL_CLK_ZERO_CNT_MAX) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"clk_zero_cnt out of range (%d)\n", clk_zero_cnt);
clk_zero_cnt = ICL_CLK_ZERO_CNT_MAX;
}
@@ -1876,7 +1880,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
/* trail cnt in escape clocks*/
trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
if (trail_cnt > ICL_TRAIL_CNT_MAX) {
- drm_dbg_kms(&dev_priv->drm, "trail_cnt out of range (%d)\n",
+ drm_dbg_kms(display->drm, "trail_cnt out of range (%d)\n",
trail_cnt);
trail_cnt = ICL_TRAIL_CNT_MAX;
}
@@ -1884,7 +1888,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
/* tclk pre count in escape clocks */
tclk_pre_cnt = DIV_ROUND_UP(mipi_config->tclk_pre, tlpx_ns);
if (tclk_pre_cnt > ICL_TCLK_PRE_CNT_MAX) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"tclk_pre_cnt out of range (%d)\n", tclk_pre_cnt);
tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
}
@@ -1893,7 +1897,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
ths_prepare_ns, tlpx_ns);
if (hs_zero_cnt > ICL_HS_ZERO_CNT_MAX) {
- drm_dbg_kms(&dev_priv->drm, "hs_zero_cnt out of range (%d)\n",
+ drm_dbg_kms(display->drm, "hs_zero_cnt out of range (%d)\n",
hs_zero_cnt);
hs_zero_cnt = ICL_HS_ZERO_CNT_MAX;
}
@@ -1901,7 +1905,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
/* hs exit zero cnt in escape clocks */
exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
if (exit_zero_cnt > ICL_EXIT_ZERO_CNT_MAX) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"exit_zero_cnt out of range (%d)\n",
exit_zero_cnt);
exit_zero_cnt = ICL_EXIT_ZERO_CNT_MAX;
@@ -1943,10 +1947,9 @@ static void icl_dsi_add_properties(struct intel_connector *connector)
fixed_mode->vdisplay);
}
-void icl_dsi_init(struct drm_i915_private *dev_priv,
+void icl_dsi_init(struct intel_display *display,
const struct intel_bios_encoder_data *devdata)
{
- struct intel_display *display = &dev_priv->display;
struct intel_dsi *intel_dsi;
struct intel_encoder *encoder;
struct intel_connector *intel_connector;
@@ -1974,7 +1977,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv,
encoder->devdata = devdata;
/* register DSI encoder with DRM subsystem */
- drm_encoder_init(&dev_priv->drm, &encoder->base, &gen11_dsi_encoder_funcs,
+ drm_encoder_init(display->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;
@@ -1999,7 +2003,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv,
encoder->shutdown = intel_dsi_shutdown;
/* register DSI connector with DRM subsystem */
- drm_connector_init(&dev_priv->drm, connector, &gen11_dsi_connector_funcs,
+ drm_connector_init(display->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;
@@ -2012,12 +2017,12 @@ void icl_dsi_init(struct drm_i915_private *dev_priv,
intel_bios_init_panel_late(display, &intel_connector->panel, encoder->devdata, NULL);
- mutex_lock(&dev_priv->drm.mode_config.mutex);
+ mutex_lock(&display->drm->mode_config.mutex);
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
- mutex_unlock(&dev_priv->drm.mode_config.mutex);
+ mutex_unlock(&display->drm->mode_config.mutex);
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
- drm_err(&dev_priv->drm, "DSI fixed mode info missing\n");
+ drm_err(display->drm, "DSI fixed mode info missing\n");
goto err;
}
@@ -2030,10 +2035,10 @@ void icl_dsi_init(struct drm_i915_private *dev_priv,
else
intel_dsi->ports = BIT(port);
- if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports))
+ if (drm_WARN_ON(display->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports))
intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports;
- if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports))
+ if (drm_WARN_ON(display->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports))
intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports;
for_each_dsi_port(port, intel_dsi->ports) {
@@ -2047,7 +2052,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv,
}
if (!intel_dsi_vbt_init(intel_dsi, MIPI_DSI_GENERIC_PANEL_ID)) {
- drm_dbg_kms(&dev_priv->drm, "no device found\n");
+ drm_dbg_kms(display->drm, "no device found\n");
goto err;
}
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.h b/drivers/gpu/drm/i915/display/icl_dsi.h
index 43fa7d72eeb1..099fc50e35b4 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.h
+++ b/drivers/gpu/drm/i915/display/icl_dsi.h
@@ -6,11 +6,11 @@
#ifndef __ICL_DSI_H__
#define __ICL_DSI_H__
-struct drm_i915_private;
struct intel_bios_encoder_data;
struct intel_crtc_state;
+struct intel_display;
-void icl_dsi_init(struct drm_i915_private *dev_priv,
+void icl_dsi_init(struct intel_display *display,
const struct intel_bios_encoder_data *devdata);
void icl_dsi_frame_update(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 b7e462075ded..d89630b2d5c1 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -1024,6 +1024,12 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
*/
hsub = 1;
vsub = 1;
+
+ /* Wa_16023981245 */
+ if ((DISPLAY_VERx100(i915) == 2000 ||
+ DISPLAY_VERx100(i915) == 3000) &&
+ src_x % 2 != 0)
+ hsub = 2;
} else {
hsub = fb->format->hsub;
vsub = fb->format->vsub;
diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c
index 9e05745d797d..3f81a726cc7d 100644
--- a/drivers/gpu/drm/i915/display/intel_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_backlight.c
@@ -949,7 +949,7 @@ int intel_backlight_device_register(struct intel_connector *connector)
else
props.power = BACKLIGHT_POWER_OFF;
- name = kstrdup_const("intel_backlight", GFP_KERNEL);
+ name = kstrdup("intel_backlight", GFP_KERNEL);
if (!name)
return -ENOMEM;
@@ -963,7 +963,7 @@ int intel_backlight_device_register(struct intel_connector *connector)
* compatibility. Use unique names for subsequent backlight devices as a
* fallback when the default name already exists.
*/
- kfree_const(name);
+ kfree(name);
name = kasprintf(GFP_KERNEL, "card%d-%s-backlight",
i915->drm.primary->index, connector->base.name);
if (!name)
@@ -987,7 +987,7 @@ int intel_backlight_device_register(struct intel_connector *connector)
connector->base.base.id, connector->base.name, name);
out:
- kfree_const(name);
+ kfree(name);
return ret;
}
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 9967b65e3cf6..a4cdd82c4a75 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -1169,7 +1169,6 @@ static int intel_bios_ssc_frequency(struct intel_display *display,
static void
parse_general_features(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
const struct bdb_general_features *general;
general = bdb_find_section(display, BDB_GENERAL_FEATURES);
@@ -1179,7 +1178,7 @@ parse_general_features(struct intel_display *display)
display->vbt.int_tv_support = general->int_tv_support;
/* int_crt_support can't be trusted on earlier platforms */
if (display->vbt.version >= 155 &&
- (HAS_DDI(display) || IS_VALLEYVIEW(i915)))
+ (HAS_DDI(display) || display->platform.valleyview))
display->vbt.int_crt_support = general->int_crt_support;
display->vbt.lvds_use_ssc = general->enable_ssc;
display->vbt.lvds_ssc_freq =
@@ -1542,7 +1541,6 @@ static void
parse_psr(struct intel_display *display,
struct intel_panel *panel)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
const struct bdb_psr *psr;
const struct psr_table *psr_table;
int panel_type = panel->vbt.panel_type;
@@ -1567,7 +1565,7 @@ parse_psr(struct intel_display *display,
* Old decimal value is wake up time in multiples of 100 us.
*/
if (display->vbt.version >= 205 &&
- (DISPLAY_VER(display) >= 9 && !IS_BROXTON(i915))) {
+ (DISPLAY_VER(display) >= 9 && !display->platform.broxton)) {
switch (psr_table->tp1_wakeup_time) {
case 0:
panel->vbt.psr.tp1_wakeup_time_us = 500;
@@ -2029,11 +2027,9 @@ static void icl_fixup_mipi_sequences(struct intel_display *display,
static void fixup_mipi_sequences(struct intel_display *display,
struct intel_panel *panel)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
-
if (DISPLAY_VER(display) >= 11)
icl_fixup_mipi_sequences(display, panel);
- else if (IS_VALLEYVIEW(i915))
+ else if (display->platform.valleyview)
vlv_fixup_mipi_sequences(display, panel);
}
@@ -2243,15 +2239,15 @@ static u8 map_ddc_pin(struct intel_display *display, u8 vbt_pin)
const u8 *ddc_pin_map;
int i, n_entries;
- if (INTEL_PCH_TYPE(i915) >= PCH_MTL || IS_ALDERLAKE_P(i915)) {
+ if (INTEL_PCH_TYPE(i915) >= PCH_MTL || display->platform.alderlake_p) {
ddc_pin_map = adlp_ddc_pin_map;
n_entries = ARRAY_SIZE(adlp_ddc_pin_map);
- } else if (IS_ALDERLAKE_S(i915)) {
+ } else if (display->platform.alderlake_s) {
ddc_pin_map = adls_ddc_pin_map;
n_entries = ARRAY_SIZE(adls_ddc_pin_map);
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
return vbt_pin;
- } else if (IS_ROCKETLAKE(i915) && INTEL_PCH_TYPE(i915) == PCH_TGP) {
+ } else if (display->platform.rocketlake && INTEL_PCH_TYPE(i915) == PCH_TGP) {
ddc_pin_map = rkl_pch_tgp_ddc_pin_map;
n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map);
} else if (HAS_PCH_TGP(i915) && DISPLAY_VER(display) == 9) {
@@ -2334,7 +2330,6 @@ static enum port __dvo_port_to_port(int n_ports, int n_dvo,
static enum port dvo_port_to_port(struct intel_display *display,
u8 dvo_port)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
/*
* Each DDI port can have more than one value on the "DVO Port" field,
* so look for all the possible values for each port.
@@ -2391,12 +2386,12 @@ static enum port dvo_port_to_port(struct intel_display *display,
ARRAY_SIZE(xelpd_port_mapping[0]),
xelpd_port_mapping,
dvo_port);
- else if (IS_ALDERLAKE_S(i915))
+ else if (display->platform.alderlake_s)
return __dvo_port_to_port(ARRAY_SIZE(adls_port_mapping),
ARRAY_SIZE(adls_port_mapping[0]),
adls_port_mapping,
dvo_port);
- else if (IS_DG1(i915) || IS_ROCKETLAKE(i915))
+ else if (display->platform.dg1 || display->platform.rocketlake)
return __dvo_port_to_port(ARRAY_SIZE(rkl_port_mapping),
ARRAY_SIZE(rkl_port_mapping[0]),
rkl_port_mapping,
@@ -2519,7 +2514,6 @@ static void sanitize_hdmi_level_shift(struct intel_bios_encoder_data *devdata,
enum port port)
{
struct intel_display *display = devdata->display;
- struct drm_i915_private *i915 = to_i915(display->drm);
if (!intel_bios_encoder_supports_dvi(devdata))
return;
@@ -2529,7 +2523,7 @@ static void sanitize_hdmi_level_shift(struct intel_bios_encoder_data *devdata,
* with a HSW VBT where the level shifter value goes
* up to 11, whereas the BDW max is 9.
*/
- if (IS_BROADWELL(i915) && devdata->child.hdmi_level_shifter_value > 9) {
+ if (display->platform.broadwell && devdata->child.hdmi_level_shifter_value > 9) {
drm_dbg_kms(display->drm,
"Bogus port %c VBT HDMI level shift %d, adjusting to %d\n",
port_name(port), devdata->child.hdmi_level_shifter_value, 9);
@@ -2618,14 +2612,13 @@ int intel_bios_hdmi_max_tmds_clock(const struct intel_bios_encoder_data *devdata
static bool is_port_valid(struct intel_display *display, enum port port)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
/*
* On some ICL SKUs port F is not present, but broken VBTs mark
* the port as present. Only try to initialize port F for the
* SKUs that may actually have it.
*/
- if (port == PORT_F && IS_ICELAKE(i915))
- return IS_ICL_WITH_PORT_F(i915);
+ if (port == PORT_F && display->platform.icelake)
+ return display->platform.icelake_port_f;
return true;
}
@@ -2723,9 +2716,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
static bool has_ddi_port_info(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
-
- return DISPLAY_VER(display) >= 5 || IS_G4X(i915);
+ return DISPLAY_VER(display) >= 5 || display->platform.g4x;
}
static void parse_ddi_ports(struct intel_display *display)
@@ -2796,7 +2787,6 @@ static bool child_device_size_valid(struct intel_display *display, int size)
static void
parse_general_definitions(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
const struct bdb_general_definitions *defs;
struct intel_bios_encoder_data *devdata;
const struct child_device_config *child;
@@ -2821,7 +2811,7 @@ parse_general_definitions(struct intel_display *display)
bus_pin = defs->crt_ddc_gmbus_pin;
drm_dbg_kms(display->drm, "crt_ddc_bus_pin: %d\n", bus_pin);
- if (intel_gmbus_is_valid_pin(i915, bus_pin))
+ if (intel_gmbus_is_valid_pin(display, bus_pin))
display->vbt.crt_ddc_pin = bus_pin;
if (!child_device_size_valid(display, defs->child_dev_size))
@@ -2907,7 +2897,7 @@ init_vbt_missing_defaults(struct intel_display *display)
unsigned int ports = DISPLAY_RUNTIME_INFO(display)->port_mask;
enum port port;
- if (!HAS_DDI(display) && !IS_CHERRYVIEW(i915))
+ if (!HAS_DDI(display) && !display->platform.cherryview)
return;
for_each_port_masked(port, ports) {
@@ -3338,7 +3328,6 @@ bool intel_bios_is_tv_present(struct intel_display *display)
*/
bool intel_bios_is_lvds_present(struct intel_display *display, u8 *i2c_pin)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
const struct intel_bios_encoder_data *devdata;
if (list_empty(&display->vbt.display_devices))
@@ -3355,7 +3344,7 @@ bool intel_bios_is_lvds_present(struct intel_display *display, u8 *i2c_pin)
child->device_type != DEVICE_TYPE_LFP)
continue;
- if (intel_gmbus_is_valid_pin(i915, child->i2c_pin))
+ if (intel_gmbus_is_valid_pin(display, child->i2c_pin))
*i2c_pin = child->i2c_pin;
/* However, we cannot trust the BIOS writers to populate
@@ -3603,17 +3592,16 @@ static const u8 direct_aux_ch_map[] = {
static enum aux_ch map_aux_ch(struct intel_display *display, u8 aux_channel)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
const u8 *aux_ch_map;
int i, n_entries;
if (DISPLAY_VER(display) >= 13) {
aux_ch_map = adlp_aux_ch_map;
n_entries = ARRAY_SIZE(adlp_aux_ch_map);
- } else if (IS_ALDERLAKE_S(i915)) {
+ } else if (display->platform.alderlake_s) {
aux_ch_map = adls_aux_ch_map;
n_entries = ARRAY_SIZE(adls_aux_ch_map);
- } else if (IS_DG1(i915) || IS_ROCKETLAKE(i915)) {
+ } else if (display->platform.dg1 || display->platform.rocketlake) {
aux_ch_map = rkl_aux_ch_map;
n_entries = ARRAY_SIZE(rkl_aux_ch_map);
} else {
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index 47036d4abb33..a52b0ae68b96 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -743,7 +743,7 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
- if (DISPLAY_VER_FULL(dev_priv) >= IP_VER(14, 1) && IS_DGFX(dev_priv))
+ if (DISPLAY_VERx100(dev_priv) >= 1401 && IS_DGFX(dev_priv))
xe2_hpd_get_bw_info(dev_priv, &xe2_hpd_sa_info);
else if (DISPLAY_VER(dev_priv) >= 14)
tgl_get_bw_info(dev_priv, &mtl_sa_info);
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index fa1c2012b10c..03c4eef3f92a 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1468,6 +1468,39 @@ static const struct intel_cdclk_vals xe2hpd_cdclk_table[] = {
{}
};
+static const struct intel_cdclk_vals xe3lpd_cdclk_table[] = {
+ { .refclk = 38400, .cdclk = 153600, .ratio = 16, .waveform = 0xaaaa },
+ { .refclk = 38400, .cdclk = 172800, .ratio = 16, .waveform = 0xad5a },
+ { .refclk = 38400, .cdclk = 192000, .ratio = 16, .waveform = 0xb6b6 },
+ { .refclk = 38400, .cdclk = 211200, .ratio = 16, .waveform = 0xdbb6 },
+ { .refclk = 38400, .cdclk = 230400, .ratio = 16, .waveform = 0xeeee },
+ { .refclk = 38400, .cdclk = 249600, .ratio = 16, .waveform = 0xf7de },
+ { .refclk = 38400, .cdclk = 268800, .ratio = 16, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 288000, .ratio = 16, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 307200, .ratio = 16, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 326400, .ratio = 17, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 345600, .ratio = 18, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 364800, .ratio = 19, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 384000, .ratio = 20, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 403200, .ratio = 21, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 422400, .ratio = 22, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 441600, .ratio = 23, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 460800, .ratio = 24, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 480000, .ratio = 25, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 499200, .ratio = 26, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 518400, .ratio = 27, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 537600, .ratio = 28, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 556800, .ratio = 29, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 576000, .ratio = 30, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 595200, .ratio = 31, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 614400, .ratio = 32, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 633600, .ratio = 33, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 672000, .ratio = 35, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 691200, .ratio = 36, .waveform = 0xffff },
+ {}
+};
+
static const int cdclk_squash_len = 16;
static int cdclk_squash_divider(u16 waveform)
@@ -1594,6 +1627,16 @@ static u8 rplu_calc_voltage_level(int cdclk)
rplu_voltage_level_max_cdclk);
}
+static u8 xe3lpd_calc_voltage_level(int cdclk)
+{
+ /*
+ * Starting with xe3lpd power controller does not need the voltage
+ * index when doing the modeset update. This function is best left
+ * defined but returning 0 to the mask.
+ */
+ return 0;
+}
+
static void icl_readout_refclk(struct intel_display *display,
struct intel_cdclk_config *cdclk_config)
{
@@ -2015,8 +2058,8 @@ static bool pll_enable_wa_needed(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
- return (DISPLAY_VER_FULL(display) == IP_VER(20, 0) ||
- DISPLAY_VER_FULL(display) == IP_VER(14, 0) ||
+ return (DISPLAY_VERx100(display) == 2000 ||
+ DISPLAY_VERx100(display) == 1400 ||
IS_DG2(dev_priv)) &&
display->cdclk.hw.vco > 0;
}
@@ -3437,7 +3480,9 @@ void intel_update_max_cdclk(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
- if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
+ if (DISPLAY_VER(display) >= 30) {
+ display->cdclk.max_cdclk_freq = 691200;
+ } else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
if (display->cdclk.hw.ref == 24000)
display->cdclk.max_cdclk_freq = 552000;
else
@@ -3650,6 +3695,13 @@ void intel_cdclk_debugfs_register(struct intel_display *display)
display, &i915_cdclk_info_fops);
}
+static const struct intel_cdclk_funcs xe3lpd_cdclk_funcs = {
+ .get_cdclk = bxt_get_cdclk,
+ .set_cdclk = bxt_set_cdclk,
+ .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
+ .calc_voltage_level = xe3lpd_calc_voltage_level,
+};
+
static const struct intel_cdclk_funcs rplu_cdclk_funcs = {
.get_cdclk = bxt_get_cdclk,
.set_cdclk = bxt_set_cdclk,
@@ -3794,10 +3846,13 @@ void intel_init_cdclk_hooks(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
- if (DISPLAY_VER(display) >= 20) {
+ if (DISPLAY_VER(display) >= 30) {
+ display->funcs.cdclk = &xe3lpd_cdclk_funcs;
+ display->cdclk.table = xe3lpd_cdclk_table;
+ } else if (DISPLAY_VER(display) >= 20) {
display->funcs.cdclk = &rplu_cdclk_funcs;
display->cdclk.table = xe2lpd_cdclk_table;
- } else if (DISPLAY_VER_FULL(display) >= IP_VER(14, 1)) {
+ } else if (DISPLAY_VERx100(display) >= 1401) {
display->funcs.cdclk = &rplu_cdclk_funcs;
display->cdclk.table = xe2hpd_cdclk_table;
} else if (DISPLAY_VER(display) >= 14) {
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index caf1af039960..174753625bca 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -250,38 +250,38 @@ static void ilk_update_pipe_csc(struct intel_dsb *dsb,
static void ilk_read_pipe_csc(struct intel_crtc *crtc,
struct intel_csc_matrix *csc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
u32 tmp;
- csc->preoff[0] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(pipe));
- csc->preoff[1] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_ME(pipe));
- csc->preoff[2] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_LO(pipe));
+ csc->preoff[0] = intel_de_read_fw(display, PIPE_CSC_PREOFF_HI(pipe));
+ csc->preoff[1] = intel_de_read_fw(display, PIPE_CSC_PREOFF_ME(pipe));
+ csc->preoff[2] = intel_de_read_fw(display, PIPE_CSC_PREOFF_LO(pipe));
- tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_COEFF_RY_GY(pipe));
csc->coeff[0] = tmp >> 16;
csc->coeff[1] = tmp & 0xffff;
- tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BY(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_COEFF_BY(pipe));
csc->coeff[2] = tmp >> 16;
- tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_COEFF_RU_GU(pipe));
csc->coeff[3] = tmp >> 16;
csc->coeff[4] = tmp & 0xffff;
- tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BU(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_COEFF_BU(pipe));
csc->coeff[5] = tmp >> 16;
- tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_COEFF_RV_GV(pipe));
csc->coeff[6] = tmp >> 16;
csc->coeff[7] = tmp & 0xffff;
- tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BV(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_COEFF_BV(pipe));
csc->coeff[8] = tmp >> 16;
- if (DISPLAY_VER(i915) < 7)
+ if (DISPLAY_VER(display) < 7)
return;
- csc->postoff[0] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_HI(pipe));
- csc->postoff[1] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_ME(pipe));
- csc->postoff[2] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_LO(pipe));
+ csc->postoff[0] = intel_de_read_fw(display, PIPE_CSC_POSTOFF_HI(pipe));
+ csc->postoff[1] = intel_de_read_fw(display, PIPE_CSC_POSTOFF_ME(pipe));
+ csc->postoff[2] = intel_de_read_fw(display, PIPE_CSC_POSTOFF_LO(pipe));
}
static void ilk_read_csc(struct intel_crtc_state *crtc_state)
@@ -353,35 +353,35 @@ static void icl_update_output_csc(struct intel_dsb *dsb,
static void icl_read_output_csc(struct intel_crtc *crtc,
struct intel_csc_matrix *csc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
u32 tmp;
- csc->preoff[0] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe));
- csc->preoff[1] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe));
- csc->preoff[2] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe));
+ csc->preoff[0] = intel_de_read_fw(display, PIPE_CSC_OUTPUT_PREOFF_HI(pipe));
+ csc->preoff[1] = intel_de_read_fw(display, PIPE_CSC_OUTPUT_PREOFF_ME(pipe));
+ csc->preoff[2] = intel_de_read_fw(display, PIPE_CSC_OUTPUT_PREOFF_LO(pipe));
- tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe));
csc->coeff[0] = tmp >> 16;
csc->coeff[1] = tmp & 0xffff;
- tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_OUTPUT_COEFF_BY(pipe));
csc->coeff[2] = tmp >> 16;
- tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe));
csc->coeff[3] = tmp >> 16;
csc->coeff[4] = tmp & 0xffff;
- tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_OUTPUT_COEFF_BU(pipe));
csc->coeff[5] = tmp >> 16;
- tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe));
csc->coeff[6] = tmp >> 16;
csc->coeff[7] = tmp & 0xffff;
- tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe));
+ tmp = intel_de_read_fw(display, PIPE_CSC_OUTPUT_COEFF_BV(pipe));
csc->coeff[8] = tmp >> 16;
- csc->postoff[0] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe));
- csc->postoff[1] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe));
- csc->postoff[2] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe));
+ csc->postoff[0] = intel_de_read_fw(display, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe));
+ csc->postoff[1] = intel_de_read_fw(display, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe));
+ csc->postoff[2] = intel_de_read_fw(display, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe));
}
static void icl_read_csc(struct intel_crtc_state *crtc_state)
@@ -402,14 +402,15 @@ static void icl_read_csc(struct intel_crtc_state *crtc_state)
static bool ilk_limited_range(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct drm_i915_private *i915 = to_i915(display->drm);
/* icl+ have dedicated output CSC */
- if (DISPLAY_VER(i915) >= 11)
+ if (DISPLAY_VER(display) >= 11)
return false;
/* pre-hsw have TRANSCONF_COLOR_RANGE_SELECT */
- if (DISPLAY_VER(i915) < 7 || IS_IVYBRIDGE(i915))
+ if (DISPLAY_VER(display) < 7 || IS_IVYBRIDGE(i915))
return false;
return crtc_state->limited_color_range;
@@ -417,7 +418,7 @@ static bool ilk_limited_range(const struct intel_crtc_state *crtc_state)
static bool ilk_lut_limited_range(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (!ilk_limited_range(crtc_state))
return false;
@@ -425,7 +426,7 @@ static bool ilk_lut_limited_range(const struct intel_crtc_state *crtc_state)
if (crtc_state->c8_planes)
return false;
- if (DISPLAY_VER(i915) == 10)
+ if (DISPLAY_VER(display) == 10)
return crtc_state->hw.gamma_lut;
else
return crtc_state->hw.gamma_lut &&
@@ -440,13 +441,13 @@ static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state)
return !ilk_lut_limited_range(crtc_state);
}
-static void ilk_csc_copy(struct drm_i915_private *i915,
+static void ilk_csc_copy(struct intel_display *display,
struct intel_csc_matrix *dst,
const struct intel_csc_matrix *src)
{
*dst = *src;
- if (DISPLAY_VER(i915) < 7)
+ if (DISPLAY_VER(display) < 7)
memset(dst->postoff, 0, sizeof(dst->postoff));
}
@@ -454,7 +455,7 @@ static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
struct intel_csc_matrix *csc,
bool limited_color_range)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
const u64 *input;
u64 temp[9];
@@ -462,9 +463,9 @@ static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
/* for preoff/postoff */
if (limited_color_range)
- ilk_csc_copy(i915, csc, &ilk_csc_matrix_limited_range);
+ ilk_csc_copy(display, csc, &ilk_csc_matrix_limited_range);
else
- ilk_csc_copy(i915, csc, &ilk_csc_matrix_identity);
+ ilk_csc_copy(display, csc, &ilk_csc_matrix_identity);
if (limited_color_range)
input = ctm_mult_by_limited(temp, ctm->matrix);
@@ -512,21 +513,22 @@ static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
static void ilk_assign_csc(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct drm_i915_private *i915 = to_i915(display->drm);
bool limited_color_range = ilk_csc_limited_range(crtc_state);
if (crtc_state->hw.ctm) {
- drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
+ drm_WARN_ON(display->drm, !crtc_state->csc_enable);
ilk_csc_convert_ctm(crtc_state, &crtc_state->csc, limited_color_range);
} else if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
- drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
+ drm_WARN_ON(display->drm, !crtc_state->csc_enable);
- ilk_csc_copy(i915, &crtc_state->csc, &ilk_csc_matrix_rgb_to_ycbcr);
+ ilk_csc_copy(display, &crtc_state->csc, &ilk_csc_matrix_rgb_to_ycbcr);
} else if (limited_color_range) {
- drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
+ drm_WARN_ON(display->drm, !crtc_state->csc_enable);
- ilk_csc_copy(i915, &crtc_state->csc, &ilk_csc_matrix_limited_range);
+ ilk_csc_copy(display, &crtc_state->csc, &ilk_csc_matrix_limited_range);
} else if (crtc_state->csc_enable) {
/*
* On GLK both pipe CSC and degamma LUT are controlled
@@ -534,9 +536,9 @@ static void ilk_assign_csc(struct intel_crtc_state *crtc_state)
* LUT is needed but CSC is not we need to load an
* identity matrix.
*/
- drm_WARN_ON(&i915->drm, !IS_GEMINILAKE(i915));
+ drm_WARN_ON(display->drm, !IS_GEMINILAKE(i915));
- ilk_csc_copy(i915, &crtc_state->csc, &ilk_csc_matrix_identity);
+ ilk_csc_copy(display, &crtc_state->csc, &ilk_csc_matrix_identity);
} else {
intel_csc_clear(&crtc_state->csc);
}
@@ -553,28 +555,28 @@ static void ilk_load_csc_matrix(struct intel_dsb *dsb,
static void icl_assign_csc(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->hw.ctm) {
- drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) == 0);
+ drm_WARN_ON(display->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) == 0);
ilk_csc_convert_ctm(crtc_state, &crtc_state->csc, false);
} else {
- drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) != 0);
+ drm_WARN_ON(display->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) != 0);
intel_csc_clear(&crtc_state->csc);
}
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
- drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
+ drm_WARN_ON(display->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
- ilk_csc_copy(i915, &crtc_state->output_csc, &ilk_csc_matrix_rgb_to_ycbcr);
+ ilk_csc_copy(display, &crtc_state->output_csc, &ilk_csc_matrix_rgb_to_ycbcr);
} else if (crtc_state->limited_color_range) {
- drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
+ drm_WARN_ON(display->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
- ilk_csc_copy(i915, &crtc_state->output_csc, &ilk_csc_matrix_limited_range);
+ ilk_csc_copy(display, &crtc_state->output_csc, &ilk_csc_matrix_limited_range);
} else {
- drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) != 0);
+ drm_WARN_ON(display->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) != 0);
intel_csc_clear(&crtc_state->output_csc);
}
@@ -632,51 +634,51 @@ static void vlv_wgc_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
static void vlv_load_wgc_csc(struct intel_crtc *crtc,
const struct intel_csc_matrix *csc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
- intel_de_write_fw(dev_priv, PIPE_WGC_C01_C00(dev_priv, pipe),
+ intel_de_write_fw(display, PIPE_WGC_C01_C00(display, pipe),
csc->coeff[1] << 16 | csc->coeff[0]);
- intel_de_write_fw(dev_priv, PIPE_WGC_C02(dev_priv, pipe),
+ intel_de_write_fw(display, PIPE_WGC_C02(display, pipe),
csc->coeff[2]);
- intel_de_write_fw(dev_priv, PIPE_WGC_C11_C10(dev_priv, pipe),
+ intel_de_write_fw(display, PIPE_WGC_C11_C10(display, pipe),
csc->coeff[4] << 16 | csc->coeff[3]);
- intel_de_write_fw(dev_priv, PIPE_WGC_C12(dev_priv, pipe),
+ intel_de_write_fw(display, PIPE_WGC_C12(display, pipe),
csc->coeff[5]);
- intel_de_write_fw(dev_priv, PIPE_WGC_C21_C20(dev_priv, pipe),
+ intel_de_write_fw(display, PIPE_WGC_C21_C20(display, pipe),
csc->coeff[7] << 16 | csc->coeff[6]);
- intel_de_write_fw(dev_priv, PIPE_WGC_C22(dev_priv, pipe),
+ intel_de_write_fw(display, PIPE_WGC_C22(display, pipe),
csc->coeff[8]);
}
static void vlv_read_wgc_csc(struct intel_crtc *crtc,
struct intel_csc_matrix *csc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
u32 tmp;
- tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C01_C00(dev_priv, pipe));
+ tmp = intel_de_read_fw(display, PIPE_WGC_C01_C00(display, pipe));
csc->coeff[0] = tmp & 0xffff;
csc->coeff[1] = tmp >> 16;
- tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C02(dev_priv, pipe));
+ tmp = intel_de_read_fw(display, PIPE_WGC_C02(display, pipe));
csc->coeff[2] = tmp & 0xffff;
- tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C11_C10(dev_priv, pipe));
+ tmp = intel_de_read_fw(display, PIPE_WGC_C11_C10(display, pipe));
csc->coeff[3] = tmp & 0xffff;
csc->coeff[4] = tmp >> 16;
- tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C12(dev_priv, pipe));
+ tmp = intel_de_read_fw(display, PIPE_WGC_C12(display, pipe));
csc->coeff[5] = tmp & 0xffff;
- tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C21_C20(dev_priv, pipe));
+ tmp = intel_de_read_fw(display, PIPE_WGC_C21_C20(display, pipe));
csc->coeff[6] = tmp & 0xffff;
csc->coeff[7] = tmp >> 16;
- tmp = intel_de_read_fw(dev_priv, PIPE_WGC_C22(dev_priv, pipe));
+ tmp = intel_de_read_fw(display, PIPE_WGC_C22(display, pipe));
csc->coeff[8] = tmp & 0xffff;
}
@@ -690,14 +692,14 @@ static void vlv_read_csc(struct intel_crtc_state *crtc_state)
static void vlv_assign_csc(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->hw.ctm) {
- drm_WARN_ON(&i915->drm, !crtc_state->wgc_enable);
+ drm_WARN_ON(display->drm, !crtc_state->wgc_enable);
vlv_wgc_csc_convert_ctm(crtc_state, &crtc_state->csc);
} else {
- drm_WARN_ON(&i915->drm, crtc_state->wgc_enable);
+ drm_WARN_ON(display->drm, crtc_state->wgc_enable);
intel_csc_clear(&crtc_state->csc);
}
@@ -734,45 +736,45 @@ static const struct intel_csc_matrix chv_cgm_csc_matrix_identity = {
static void chv_load_cgm_csc(struct intel_crtc *crtc,
const struct intel_csc_matrix *csc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
- intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF01(pipe),
+ intel_de_write_fw(display, CGM_PIPE_CSC_COEFF01(pipe),
csc->coeff[1] << 16 | csc->coeff[0]);
- intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF23(pipe),
+ intel_de_write_fw(display, CGM_PIPE_CSC_COEFF23(pipe),
csc->coeff[3] << 16 | csc->coeff[2]);
- intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF45(pipe),
+ intel_de_write_fw(display, CGM_PIPE_CSC_COEFF45(pipe),
csc->coeff[5] << 16 | csc->coeff[4]);
- intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF67(pipe),
+ intel_de_write_fw(display, CGM_PIPE_CSC_COEFF67(pipe),
csc->coeff[7] << 16 | csc->coeff[6]);
- intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF8(pipe),
+ intel_de_write_fw(display, CGM_PIPE_CSC_COEFF8(pipe),
csc->coeff[8]);
}
static void chv_read_cgm_csc(struct intel_crtc *crtc,
struct intel_csc_matrix *csc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
u32 tmp;
- tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF01(pipe));
+ tmp = intel_de_read_fw(display, CGM_PIPE_CSC_COEFF01(pipe));
csc->coeff[0] = tmp & 0xffff;
csc->coeff[1] = tmp >> 16;
- tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF23(pipe));
+ tmp = intel_de_read_fw(display, CGM_PIPE_CSC_COEFF23(pipe));
csc->coeff[2] = tmp & 0xffff;
csc->coeff[3] = tmp >> 16;
- tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF45(pipe));
+ tmp = intel_de_read_fw(display, CGM_PIPE_CSC_COEFF45(pipe));
csc->coeff[4] = tmp & 0xffff;
csc->coeff[5] = tmp >> 16;
- tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF67(pipe));
+ tmp = intel_de_read_fw(display, CGM_PIPE_CSC_COEFF67(pipe));
csc->coeff[6] = tmp & 0xffff;
csc->coeff[7] = tmp >> 16;
- tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF8(pipe));
+ tmp = intel_de_read_fw(display, CGM_PIPE_CSC_COEFF8(pipe));
csc->coeff[8] = tmp & 0xffff;
}
@@ -786,16 +788,16 @@ static void chv_read_csc(struct intel_crtc_state *crtc_state)
static void chv_assign_csc(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
- drm_WARN_ON(&i915->drm, crtc_state->wgc_enable);
+ drm_WARN_ON(display->drm, crtc_state->wgc_enable);
if (crtc_state->hw.ctm) {
- drm_WARN_ON(&i915->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
+ drm_WARN_ON(display->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
chv_cgm_csc_convert_ctm(crtc_state, &crtc_state->csc);
} else {
- drm_WARN_ON(&i915->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
+ drm_WARN_ON(display->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
crtc_state->csc = chv_cgm_csc_matrix_identity;
}
@@ -1019,12 +1021,12 @@ static void ilk_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
/* update TRANSCONF GAMMA_MODE */
ilk_set_pipeconf(crtc_state);
- intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
+ intel_de_write_fw(display, PIPE_CSC_MODE(crtc->pipe),
crtc_state->csc_mode);
}
@@ -1032,43 +1034,43 @@ static void hsw_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
- intel_de_write(i915, GAMMA_MODE(crtc->pipe),
+ intel_de_write(display, GAMMA_MODE(crtc->pipe),
crtc_state->gamma_mode);
- intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
+ intel_de_write_fw(display, PIPE_CSC_MODE(crtc->pipe),
crtc_state->csc_mode);
}
static u32 hsw_read_gamma_mode(struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
- return intel_de_read(i915, GAMMA_MODE(crtc->pipe));
+ return intel_de_read(display, GAMMA_MODE(crtc->pipe));
}
static u32 ilk_read_csc_mode(struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
- return intel_de_read(i915, PIPE_CSC_MODE(crtc->pipe));
+ return intel_de_read(display, PIPE_CSC_MODE(crtc->pipe));
}
static void i9xx_get_config(struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
u32 tmp;
- tmp = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane));
+ tmp = intel_de_read(display, DSPCNTR(display, i9xx_plane));
if (tmp & DISP_PIPE_GAMMA_ENABLE)
crtc_state->gamma_enable = true;
- if (!HAS_GMCH(dev_priv) && tmp & DISP_PIPE_CSC_ENABLE)
+ if (!HAS_GMCH(display) && tmp & DISP_PIPE_CSC_ENABLE)
crtc_state->csc_enable = true;
}
@@ -1084,14 +1086,14 @@ static void hsw_get_config(struct intel_crtc_state *crtc_state)
static void skl_get_config(struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
u32 tmp;
crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
crtc_state->csc_mode = ilk_read_csc_mode(crtc);
- tmp = intel_de_read(i915, SKL_BOTTOM_COLOR(crtc->pipe));
+ tmp = intel_de_read(display, SKL_BOTTOM_COLOR(crtc->pipe));
if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
crtc_state->gamma_enable = true;
@@ -1103,8 +1105,8 @@ static void skl_get_config(struct intel_crtc_state *crtc_state)
static void skl_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 val = 0;
@@ -1130,8 +1132,8 @@ static void skl_color_commit_arm(struct intel_dsb *dsb,
static void icl_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
/*
@@ -1147,8 +1149,8 @@ static void icl_color_commit_arm(struct intel_dsb *dsb,
static void icl_color_post_update(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
/*
* Despite Wa_1406463849, ICL CSC is no longer disarmed by
@@ -1164,17 +1166,17 @@ static void icl_color_post_update(const struct intel_crtc_state *crtc_state)
*
* TGL+ no longer need this workaround.
*/
- intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(crtc->pipe));
+ intel_de_read_fw(display, PIPE_CSC_PREOFF_HI(crtc->pipe));
}
static struct drm_property_blob *
-create_linear_lut(struct drm_i915_private *i915, int lut_size)
+create_linear_lut(struct intel_display *display, int lut_size)
{
struct drm_property_blob *blob;
struct drm_color_lut *lut;
int i;
- blob = drm_property_create_blob(&i915->drm,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -1202,7 +1204,7 @@ static u16 lut_limited_range(unsigned int value)
}
static struct drm_property_blob *
-create_resized_lut(struct drm_i915_private *i915,
+create_resized_lut(struct intel_display *display,
const struct drm_property_blob *blob_in, int lut_out_size,
bool limited_color_range)
{
@@ -1211,7 +1213,7 @@ create_resized_lut(struct drm_i915_private *i915,
const struct drm_color_lut *lut_in;
struct drm_color_lut *lut_out;
- blob_out = drm_property_create_blob(&i915->drm,
+ blob_out = drm_property_create_blob(display->drm,
sizeof(lut_out[0]) * lut_out_size,
NULL);
if (IS_ERR(blob_out))
@@ -1239,7 +1241,7 @@ create_resized_lut(struct drm_i915_private *i915,
static void i9xx_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 intel_display *display = to_intel_display(crtc);
const struct drm_color_lut *lut;
enum pipe pipe = crtc->pipe;
int i;
@@ -1250,24 +1252,24 @@ static void i9xx_load_lut_8(struct intel_crtc *crtc,
lut = blob->data;
for (i = 0; i < 256; i++)
- intel_de_write_fw(dev_priv, PALETTE(dev_priv, pipe, i),
+ intel_de_write_fw(display, PALETTE(display, pipe, i),
i9xx_lut_8(&lut[i]));
}
static void i9xx_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 intel_display *display = to_intel_display(crtc);
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 - 1; i++) {
- intel_de_write_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 0),
+ intel_de_write_fw(display,
+ PALETTE(display, pipe, 2 * i + 0),
i9xx_lut_10_ldw(&lut[i]));
- intel_de_write_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 1),
+ intel_de_write_fw(display,
+ PALETTE(display, pipe, 2 * i + 1),
i9xx_lut_10_udw(&lut[i]));
}
}
@@ -1293,23 +1295,23 @@ static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
static void i965_load_lut_10p6(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
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 - 1; i++) {
- intel_de_write_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 0),
+ intel_de_write_fw(display,
+ PALETTE(display, pipe, 2 * i + 0),
i965_lut_10p6_ldw(&lut[i]));
- intel_de_write_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 1),
+ intel_de_write_fw(display,
+ PALETTE(display, pipe, 2 * i + 1),
i965_lut_10p6_udw(&lut[i]));
}
- intel_de_write_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 0), lut[i].red);
- intel_de_write_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 1), lut[i].green);
- intel_de_write_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 2), lut[i].blue);
+ intel_de_write_fw(display, PIPEGCMAX(display, pipe, 0), lut[i].red);
+ intel_de_write_fw(display, PIPEGCMAX(display, pipe, 1), lut[i].green);
+ intel_de_write_fw(display, PIPEGCMAX(display, pipe, 2), lut[i].blue);
}
static void i965_load_luts(const struct intel_crtc_state *crtc_state)
@@ -1333,12 +1335,12 @@ static void i965_load_luts(const struct intel_crtc_state *crtc_state)
static void ilk_lut_write(const struct intel_crtc_state *crtc_state,
i915_reg_t reg, u32 val)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->dsb_color_vblank)
intel_dsb_reg_write(crtc_state->dsb_color_vblank, reg, val);
else
- intel_de_write_fw(i915, reg, val);
+ intel_de_write_fw(display, reg, val);
}
static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
@@ -1545,9 +1547,9 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
}
}
-static int glk_degamma_lut_size(struct drm_i915_private *i915)
+static int glk_degamma_lut_size(struct intel_display *display)
{
- if (DISPLAY_VER(i915) >= 13)
+ if (DISPLAY_VER(display) >= 13)
return 131;
else
return 35;
@@ -1579,8 +1581,8 @@ static void mtl_degamma_lut_pack(struct drm_color_lut *entry, u32 val)
static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- 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;
@@ -1611,14 +1613,14 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
* as compared to just 16 to achieve this.
*/
ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
- DISPLAY_VER(i915) >= 14 ?
+ DISPLAY_VER(display) >= 14 ?
mtl_degamma_lut(&lut[i]) : glk_degamma_lut(&lut[i]));
}
/* Clamp values > 1.0. */
- while (i++ < glk_degamma_lut_size(i915))
+ while (i++ < glk_degamma_lut_size(display))
ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
- DISPLAY_VER(i915) >= 14 ?
+ DISPLAY_VER(display) >= 14 ?
1 << 24 : 1 << 16);
ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0);
@@ -1819,15 +1821,15 @@ static void chv_cgm_degamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
static void chv_load_cgm_degamma(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
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(i915, CGM_PIPE_DEGAMMA(pipe, i, 0),
+ intel_de_write_fw(display, CGM_PIPE_DEGAMMA(pipe, i, 0),
chv_cgm_degamma_ldw(&lut[i]));
- intel_de_write_fw(i915, CGM_PIPE_DEGAMMA(pipe, i, 1),
+ intel_de_write_fw(display, CGM_PIPE_DEGAMMA(pipe, i, 1),
chv_cgm_degamma_udw(&lut[i]));
}
}
@@ -1853,23 +1855,23 @@ static void chv_cgm_gamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
static void chv_load_cgm_gamma(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
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(i915, CGM_PIPE_GAMMA(pipe, i, 0),
+ intel_de_write_fw(display, CGM_PIPE_GAMMA(pipe, i, 0),
chv_cgm_gamma_ldw(&lut[i]));
- intel_de_write_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1),
+ intel_de_write_fw(display, CGM_PIPE_GAMMA(pipe, i, 1),
chv_cgm_gamma_udw(&lut[i]));
}
}
static void chv_load_luts(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- 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;
@@ -1884,43 +1886,43 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state)
else
i965_load_luts(crtc_state);
- intel_de_write_fw(i915, CGM_PIPE_MODE(crtc->pipe),
+ intel_de_write_fw(display, 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 *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->dsb_color_vblank)
return;
- i915->display.funcs.color->load_luts(crtc_state);
+ display->funcs.color->load_luts(crtc_state);
}
void intel_color_commit_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
- if (i915->display.funcs.color->color_commit_noarm)
- i915->display.funcs.color->color_commit_noarm(dsb, crtc_state);
+ if (display->funcs.color->color_commit_noarm)
+ display->funcs.color->color_commit_noarm(dsb, crtc_state);
}
void intel_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
- i915->display.funcs.color->color_commit_arm(dsb, crtc_state);
+ display->funcs.color->color_commit_arm(dsb, crtc_state);
}
void intel_color_post_update(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
- if (i915->display.funcs.color->color_post_update)
- i915->display.funcs.color->color_post_update(crtc_state);
+ if (display->funcs.color->color_post_update)
+ display->funcs.color->color_post_update(crtc_state);
}
void intel_color_modeset(const struct intel_crtc_state *crtc_state)
@@ -1943,7 +1945,7 @@ void intel_color_modeset(const struct intel_crtc_state *crtc_state)
void intel_color_prepare_commit(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -1961,7 +1963,7 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
if (!crtc_state->dsb_color_vblank)
return;
- i915->display.funcs.color->load_luts(crtc_state);
+ display->funcs.color->load_luts(crtc_state);
intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank);
intel_dsb_interrupt(crtc_state->dsb_color_vblank);
@@ -2030,7 +2032,7 @@ static bool chv_can_preload_luts(struct intel_atomic_state *state,
int intel_color_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_state *new_crtc_state =
@@ -2046,20 +2048,19 @@ int intel_color_check(struct intel_atomic_state *state,
if (!intel_crtc_needs_color_update(new_crtc_state))
return 0;
- return i915->display.funcs.color->color_check(state, crtc);
+ return display->funcs.color->color_check(state, crtc);
}
void intel_color_get_config(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
- if (i915->display.funcs.color->get_config)
- i915->display.funcs.color->get_config(crtc_state);
+ display->funcs.color->get_config(crtc_state);
- i915->display.funcs.color->read_luts(crtc_state);
+ display->funcs.color->read_luts(crtc_state);
- if (i915->display.funcs.color->read_csc)
- i915->display.funcs.color->read_csc(crtc_state);
+ if (display->funcs.color->read_csc)
+ display->funcs.color->read_csc(crtc_state);
}
bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
@@ -2067,7 +2068,7 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob2,
bool is_pre_csc_lut)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
/*
* FIXME c8_planes readout missing thus
@@ -2076,14 +2077,14 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
if (!is_pre_csc_lut && crtc_state->c8_planes)
return true;
- return i915->display.funcs.color->lut_equal(crtc_state, blob1, blob2,
- is_pre_csc_lut);
+ return display->funcs.color->lut_equal(crtc_state, blob1, blob2,
+ is_pre_csc_lut);
}
static bool need_plane_update(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(plane->base.dev);
+ struct intel_display *display = to_intel_display(plane);
/*
* On pre-SKL the pipe gamma enable and pipe csc enable for
@@ -2091,15 +2092,14 @@ 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(i915) < 9 &&
- plane->id == PLANE_PRIMARY);
+ (DISPLAY_VER(display) < 9 && plane->id == PLANE_PRIMARY);
}
static int
intel_color_add_affected_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_state *new_crtc_state =
@@ -2114,7 +2114,7 @@ intel_color_add_affected_planes(struct intel_atomic_state *state,
new_crtc_state->csc_enable == old_crtc_state->csc_enable)
return 0;
- for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) {
+ for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
struct intel_plane_state *plane_state;
if (!need_plane_update(plane, new_crtc_state))
@@ -2129,7 +2129,7 @@ intel_color_add_affected_planes(struct intel_atomic_state *state,
new_crtc_state->do_async_flip = false;
/* plane control register changes blocked by CxSR */
- if (HAS_GMCH(i915))
+ if (HAS_GMCH(display))
new_crtc_state->disable_cxsr = true;
}
@@ -2138,43 +2138,44 @@ intel_color_add_affected_planes(struct intel_atomic_state *state,
static u32 intel_gamma_lut_tests(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
if (lut_is_legacy(gamma_lut))
return 0;
- return DISPLAY_INFO(i915)->color.gamma_lut_tests;
+ return DISPLAY_INFO(display)->color.gamma_lut_tests;
}
static u32 intel_degamma_lut_tests(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
- return DISPLAY_INFO(i915)->color.degamma_lut_tests;
+ return DISPLAY_INFO(display)->color.degamma_lut_tests;
}
static int intel_gamma_lut_size(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
if (lut_is_legacy(gamma_lut))
return LEGACY_LUT_LENGTH;
- return DISPLAY_INFO(i915)->color.gamma_lut_size;
+ return DISPLAY_INFO(display)->color.gamma_lut_size;
}
static u32 intel_degamma_lut_size(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
- return DISPLAY_INFO(i915)->color.degamma_lut_size;
+ return DISPLAY_INFO(display)->color.degamma_lut_size;
}
-static int check_lut_size(struct drm_i915_private *i915,
+static int check_lut_size(struct intel_crtc *crtc, const char *lut_name,
const struct drm_property_blob *lut, int expected)
{
+ struct intel_display *display = to_intel_display(crtc);
int len;
if (!lut)
@@ -2182,8 +2183,9 @@ static int check_lut_size(struct drm_i915_private *i915,
len = drm_color_lut_size(lut);
if (len != expected) {
- drm_dbg_kms(&i915->drm, "Invalid LUT size; got %d, expected %d\n",
- len, expected);
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] Invalid %s LUT size; got %d, expected %d\n",
+ crtc->base.base.id, crtc->base.name, lut_name, len, expected);
return -EINVAL;
}
@@ -2193,23 +2195,25 @@ static int check_lut_size(struct drm_i915_private *i915,
static int _check_luts(const struct intel_crtc_state *crtc_state,
u32 degamma_tests, u32 gamma_tests)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(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;
int gamma_length, degamma_length;
/* C8 relies on its palette being stored in the legacy LUT */
if (crtc_state->c8_planes && !lut_is_legacy(crtc_state->hw.gamma_lut)) {
- drm_dbg_kms(&i915->drm,
- "C8 pixelformat requires the legacy LUT\n");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] C8 pixelformat requires the legacy LUT\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
degamma_length = intel_degamma_lut_size(crtc_state);
gamma_length = intel_gamma_lut_size(crtc_state);
- if (check_lut_size(i915, degamma_lut, degamma_length) ||
- check_lut_size(i915, gamma_lut, gamma_length))
+ if (check_lut_size(crtc, "degamma", degamma_lut, degamma_length) ||
+ check_lut_size(crtc, "gamma", gamma_lut, gamma_length))
return -EINVAL;
if (drm_color_lut_check(degamma_lut, degamma_tests) ||
@@ -2241,9 +2245,10 @@ static int i9xx_lut_10_diff(u16 a, u16 b)
drm_color_lut_extract(b, 10);
}
-static int i9xx_check_lut_10(struct drm_i915_private *dev_priv,
+static int i9xx_check_lut_10(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
+ struct intel_display *display = to_intel_display(crtc);
const struct drm_color_lut *lut = blob->data;
int lut_size = drm_color_lut_size(blob);
const struct drm_color_lut *a = &lut[lut_size - 2];
@@ -2252,7 +2257,9 @@ static int i9xx_check_lut_10(struct drm_i915_private *dev_priv,
if (i9xx_lut_10_diff(b->red, a->red) > 0x7f ||
i9xx_lut_10_diff(b->green, a->green) > 0x7f ||
i9xx_lut_10_diff(b->blue, a->blue) > 0x7f) {
- drm_dbg_kms(&dev_priv->drm, "Last gamma LUT entry exceeds max slope\n");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] Last gamma LUT entry exceeds max slope\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
@@ -2261,28 +2268,28 @@ static int i9xx_check_lut_10(struct drm_i915_private *dev_priv,
void intel_color_assert_luts(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
/* make sure {pre,post}_csc_lut were correctly assigned */
- if (DISPLAY_VER(i915) >= 11 || HAS_GMCH(i915)) {
- drm_WARN_ON(&i915->drm,
+ if (DISPLAY_VER(display) >= 11 || HAS_GMCH(display)) {
+ drm_WARN_ON(display->drm,
crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut);
- drm_WARN_ON(&i915->drm,
+ drm_WARN_ON(display->drm,
crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
- } else if (DISPLAY_VER(i915) == 10) {
- drm_WARN_ON(&i915->drm,
+ } else if (DISPLAY_VER(display) == 10) {
+ drm_WARN_ON(display->drm,
crtc_state->post_csc_lut == crtc_state->hw.gamma_lut &&
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->pre_csc_lut != display->color.glk_linear_degamma_lut);
+ drm_WARN_ON(display->drm,
!ilk_lut_limited_range(crtc_state) &&
crtc_state->post_csc_lut != NULL &&
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,
+ drm_WARN_ON(display->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,
+ drm_WARN_ON(display->drm,
!ilk_lut_limited_range(crtc_state) &&
crtc_state->post_csc_lut != crtc_state->hw.degamma_lut &&
crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
@@ -2300,7 +2307,7 @@ static void intel_assign_luts(struct intel_crtc_state *crtc_state)
static int i9xx_color_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
int ret;
@@ -2315,9 +2322,9 @@ static int i9xx_color_check(struct intel_atomic_state *state,
crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state);
- if (DISPLAY_VER(i915) < 4 &&
+ if (DISPLAY_VER(display) < 4 &&
crtc_state->gamma_mode == GAMMA_MODE_MODE_10BIT) {
- ret = i9xx_check_lut_10(i915, crtc_state->hw.gamma_lut);
+ ret = i9xx_check_lut_10(crtc, crtc_state->hw.gamma_lut);
if (ret)
return ret;
}
@@ -2484,12 +2491,12 @@ static u32 ilk_csc_mode(const struct intel_crtc_state *crtc_state)
static int ilk_assign_luts(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (ilk_lut_limited_range(crtc_state)) {
struct drm_property_blob *gamma_lut;
- gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut,
+ gamma_lut = create_resized_lut(display, crtc_state->hw.gamma_lut,
drm_color_lut_size(crtc_state->hw.gamma_lut),
true);
if (IS_ERR(gamma_lut))
@@ -2523,7 +2530,7 @@ static int ilk_assign_luts(struct intel_crtc_state *crtc_state)
static int ilk_color_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
int ret;
@@ -2533,15 +2540,17 @@ static int ilk_color_check(struct intel_atomic_state *state,
return ret;
if (crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) {
- drm_dbg_kms(&i915->drm,
- "Degamma and gamma together are not possible\n");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] Degamma and gamma together are not possible\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
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");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] YCbCr and CTM together are not possible\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
@@ -2594,21 +2603,21 @@ static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state)
static int ivb_assign_luts(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
struct drm_property_blob *degamma_lut, *gamma_lut;
if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT)
return ilk_assign_luts(crtc_state);
- 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);
+ drm_WARN_ON(display->drm, drm_color_lut_size(crtc_state->hw.degamma_lut) != 1024);
+ drm_WARN_ON(display->drm, drm_color_lut_size(crtc_state->hw.gamma_lut) != 1024);
- degamma_lut = create_resized_lut(i915, crtc_state->hw.degamma_lut, 512,
+ degamma_lut = create_resized_lut(display, crtc_state->hw.degamma_lut, 512,
false);
if (IS_ERR(degamma_lut))
return PTR_ERR(degamma_lut);
- gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, 512,
+ gamma_lut = create_resized_lut(display, crtc_state->hw.gamma_lut, 512,
ilk_lut_limited_range(crtc_state));
if (IS_ERR(gamma_lut)) {
drm_property_blob_put(degamma_lut);
@@ -2627,7 +2636,7 @@ static int ivb_assign_luts(struct intel_crtc_state *crtc_state)
static int ivb_color_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
int ret;
@@ -2637,22 +2646,25 @@ static int ivb_color_check(struct intel_atomic_state *state,
return ret;
if (crtc_state->c8_planes && crtc_state->hw.degamma_lut) {
- drm_dbg_kms(&i915->drm,
- "C8 pixelformat and degamma together are not possible\n");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] C8 pixelformat and degamma together are not possible\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
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");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] YCbCr and CTM together are not possible\n",
+ crtc->base.base.id, crtc->base.name);
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");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] YCbCr and degamma+gamma together are not possible\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
@@ -2697,13 +2709,13 @@ static bool glk_use_pre_csc_lut_for_gamma(const struct intel_crtc_state *crtc_st
static int glk_assign_luts(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (glk_use_pre_csc_lut_for_gamma(crtc_state)) {
struct drm_property_blob *gamma_lut;
- gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut,
- DISPLAY_INFO(i915)->color.degamma_lut_size,
+ gamma_lut = create_resized_lut(display, crtc_state->hw.gamma_lut,
+ DISPLAY_INFO(display)->color.degamma_lut_size,
false);
if (IS_ERR(gamma_lut))
return PTR_ERR(gamma_lut);
@@ -2719,7 +2731,7 @@ static int glk_assign_luts(struct intel_crtc_state *crtc_state)
if (ilk_lut_limited_range(crtc_state)) {
struct drm_property_blob *gamma_lut;
- gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut,
+ gamma_lut = create_resized_lut(display, crtc_state->hw.gamma_lut,
drm_color_lut_size(crtc_state->hw.gamma_lut),
true);
if (IS_ERR(gamma_lut))
@@ -2742,7 +2754,7 @@ static int glk_assign_luts(struct intel_crtc_state *crtc_state)
*/
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);
+ display->color.glk_linear_degamma_lut);
return 0;
}
@@ -2761,7 +2773,7 @@ static int glk_check_luts(const struct intel_crtc_state *crtc_state)
static int glk_color_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
int ret;
@@ -2772,15 +2784,17 @@ static int glk_color_check(struct intel_atomic_state *state,
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");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] YCbCr and CTM together are not possible\n",
+ crtc->base.base.id, crtc->base.name);
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");
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] YCbCr and degamma+gamma together are not possible\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
@@ -2817,8 +2831,7 @@ static int glk_color_check(struct intel_atomic_state *state,
static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc_state);
u32 gamma_mode = 0;
if (crtc_state->hw.degamma_lut)
@@ -2836,7 +2849,7 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state)
* ToDo: Extend to Logarithmic Gamma once the new UAPI
* is accepted and implemented by a userspace consumer
*/
- else if (DISPLAY_VER(i915) >= 13)
+ else if (DISPLAY_VER(display) >= 13)
gamma_mode |= GAMMA_MODE_MODE_10BIT;
else
gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEG;
@@ -3217,13 +3230,13 @@ static bool icl_lut_equal(const struct intel_crtc_state *crtc_state,
static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
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,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * LEGACY_LUT_LENGTH,
NULL);
if (IS_ERR(blob))
@@ -3232,8 +3245,8 @@ static struct drm_property_blob *i9xx_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,
- PALETTE(dev_priv, pipe, i));
+ u32 val = intel_de_read_fw(display,
+ PALETTE(display, pipe, i));
i9xx_lut_8_pack(&lut[i], val);
}
@@ -3243,15 +3256,15 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
static struct drm_property_blob *i9xx_read_lut_10(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- u32 lut_size = DISPLAY_INFO(dev_priv)->color.gamma_lut_size;
+ struct intel_display *display = to_intel_display(crtc);
+ u32 lut_size = DISPLAY_INFO(display)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
u32 ldw, udw;
int i;
- blob = drm_property_create_blob(&dev_priv->drm,
+ blob = drm_property_create_blob(display->drm,
lut_size * sizeof(lut[0]), NULL);
if (IS_ERR(blob))
return NULL;
@@ -3259,10 +3272,10 @@ static struct drm_property_blob *i9xx_read_lut_10(struct intel_crtc *crtc)
lut = blob->data;
for (i = 0; i < lut_size - 1; i++) {
- ldw = intel_de_read_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 0));
- udw = intel_de_read_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 1));
+ ldw = intel_de_read_fw(display,
+ PALETTE(display, pipe, 2 * i + 0));
+ udw = intel_de_read_fw(display,
+ PALETTE(display, pipe, 2 * i + 1));
i9xx_lut_10_pack(&lut[i], ldw, udw);
}
@@ -3294,13 +3307,13 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int i, lut_size = DISPLAY_INFO(dev_priv)->color.gamma_lut_size;
+ struct intel_display *display = to_intel_display(crtc);
+ int i, lut_size = DISPLAY_INFO(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,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3309,17 +3322,17 @@ static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
lut = blob->data;
for (i = 0; i < lut_size - 1; i++) {
- u32 ldw = intel_de_read_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 0));
- u32 udw = intel_de_read_fw(dev_priv,
- PALETTE(dev_priv, pipe, 2 * i + 1));
+ u32 ldw = intel_de_read_fw(display,
+ PALETTE(display, pipe, 2 * i + 0));
+ u32 udw = intel_de_read_fw(display,
+ PALETTE(display, pipe, 2 * i + 1));
i965_lut_10p6_pack(&lut[i], ldw, udw);
}
- lut[i].red = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 0)));
- lut[i].green = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 1)));
- lut[i].blue = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(dev_priv, pipe, 2)));
+ lut[i].red = i965_lut_11p6_max_pack(intel_de_read_fw(display, PIPEGCMAX(display, pipe, 0)));
+ lut[i].green = i965_lut_11p6_max_pack(intel_de_read_fw(display, PIPEGCMAX(display, pipe, 1)));
+ lut[i].blue = i965_lut_11p6_max_pack(intel_de_read_fw(display, PIPEGCMAX(display, pipe, 2)));
return blob;
}
@@ -3346,13 +3359,13 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int i, lut_size = DISPLAY_INFO(dev_priv)->color.degamma_lut_size;
+ struct intel_display *display = to_intel_display(crtc);
+ int i, lut_size = DISPLAY_INFO(display)->color.degamma_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,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3361,8 +3374,8 @@ static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc)
lut = blob->data;
for (i = 0; i < lut_size; i++) {
- u32 ldw = intel_de_read_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0));
- u32 udw = intel_de_read_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1));
+ u32 ldw = intel_de_read_fw(display, CGM_PIPE_DEGAMMA(pipe, i, 0));
+ u32 udw = intel_de_read_fw(display, CGM_PIPE_DEGAMMA(pipe, i, 1));
chv_cgm_degamma_pack(&lut[i], ldw, udw);
}
@@ -3372,13 +3385,13 @@ static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc)
static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
+ struct intel_display *display = to_intel_display(crtc);
+ int i, lut_size = DISPLAY_INFO(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(&i915->drm,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3387,8 +3400,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(i915, CGM_PIPE_GAMMA(pipe, i, 0));
- u32 udw = intel_de_read_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1));
+ u32 ldw = intel_de_read_fw(display, CGM_PIPE_GAMMA(pipe, i, 0));
+ u32 udw = intel_de_read_fw(display, CGM_PIPE_GAMMA(pipe, i, 1));
chv_cgm_gamma_pack(&lut[i], ldw, udw);
}
@@ -3398,10 +3411,10 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
static void chv_get_config(struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- crtc_state->cgm_mode = intel_de_read(i915, CGM_PIPE_MODE(crtc->pipe));
+ crtc_state->cgm_mode = intel_de_read(display, CGM_PIPE_MODE(crtc->pipe));
i9xx_get_config(crtc_state);
}
@@ -3421,13 +3434,13 @@ static void chv_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
int i;
- blob = drm_property_create_blob(&i915->drm,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * LEGACY_LUT_LENGTH,
NULL);
if (IS_ERR(blob))
@@ -3436,7 +3449,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(i915, LGC_PALETTE(pipe, i));
+ u32 val = intel_de_read_fw(display, LGC_PALETTE(pipe, i));
i9xx_lut_8_pack(&lut[i], val);
}
@@ -3446,13 +3459,13 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
+ struct intel_display *display = to_intel_display(crtc);
+ int i, lut_size = DISPLAY_INFO(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(&i915->drm,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3461,7 +3474,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(i915, PREC_PALETTE(pipe, i));
+ u32 val = intel_de_read_fw(display, PREC_PALETTE(pipe, i));
ilk_lut_10_pack(&lut[i], val);
}
@@ -3509,13 +3522,13 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *ivb_read_lut_10(struct intel_crtc *crtc,
u32 prec_index)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
int i, lut_size = ivb_lut_10_size(prec_index);
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
- blob = drm_property_create_blob(&dev_priv->drm,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3526,14 +3539,14 @@ static struct drm_property_blob *ivb_read_lut_10(struct intel_crtc *crtc,
for (i = 0; i < lut_size; i++) {
u32 val;
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_INDEX(pipe),
prec_index + i);
- val = intel_de_read_fw(dev_priv, PREC_PAL_DATA(pipe));
+ val = intel_de_read_fw(display, PREC_PAL_DATA(pipe));
ilk_lut_10_pack(&lut[i], val);
}
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_INDEX(pipe),
PAL_PREC_INDEX_VALUE(0));
return blob;
@@ -3574,13 +3587,13 @@ static void ivb_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 *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
int i, lut_size = ivb_lut_10_size(prec_index);
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
- blob = drm_property_create_blob(&i915->drm,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3588,19 +3601,19 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc,
lut = blob->data;
- intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_INDEX(pipe),
prec_index);
- intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_INDEX(pipe),
PAL_PREC_AUTO_INCREMENT |
prec_index);
for (i = 0; i < lut_size; i++) {
- u32 val = intel_de_read_fw(i915, PREC_PAL_DATA(pipe));
+ u32 val = intel_de_read_fw(display, PREC_PAL_DATA(pipe));
ilk_lut_10_pack(&lut[i], val);
}
- intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_INDEX(pipe),
PAL_PREC_INDEX_VALUE(0));
return blob;
@@ -3639,13 +3652,13 @@ static void bdw_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int i, lut_size = DISPLAY_INFO(dev_priv)->color.degamma_lut_size;
+ struct intel_display *display = to_intel_display(crtc);
+ int i, lut_size = DISPLAY_INFO(display)->color.degamma_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,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3658,22 +3671,22 @@ static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc)
* 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),
+ intel_de_write_fw(display, PRE_CSC_GAMC_INDEX(pipe),
PRE_CSC_GAMC_INDEX_VALUE(0));
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
+ intel_de_write_fw(display, PRE_CSC_GAMC_INDEX(pipe),
PRE_CSC_GAMC_AUTO_INCREMENT |
PRE_CSC_GAMC_INDEX_VALUE(0));
for (i = 0; i < lut_size; i++) {
- u32 val = intel_de_read_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe));
+ u32 val = intel_de_read_fw(display, PRE_CSC_GAMC_DATA(pipe));
- if (DISPLAY_VER(dev_priv) >= 14)
+ if (DISPLAY_VER(display) >= 14)
mtl_degamma_lut_pack(&lut[i], val);
else
glk_degamma_lut_pack(&lut[i], val);
}
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
+ intel_de_write_fw(display, PRE_CSC_GAMC_INDEX(pipe),
PRE_CSC_GAMC_INDEX_VALUE(0));
return blob;
@@ -3705,13 +3718,13 @@ 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 *i915 = to_i915(crtc->base.dev);
- int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
+ struct intel_display *display = to_intel_display(crtc);
+ int i, lut_size = DISPLAY_INFO(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(&i915->drm,
+ blob = drm_property_create_blob(display->drm,
sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
@@ -3719,20 +3732,20 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc)
lut = blob->data;
- intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_MULTI_SEG_INDEX(pipe),
PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
- intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_MULTI_SEG_INDEX(pipe),
PAL_PREC_MULTI_SEG_AUTO_INCREMENT |
PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
for (i = 0; i < 9; i++) {
- 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));
+ u32 ldw = intel_de_read_fw(display, PREC_PAL_MULTI_SEG_DATA(pipe));
+ u32 udw = intel_de_read_fw(display, PREC_PAL_MULTI_SEG_DATA(pipe));
ilk_lut_12p4_pack(&lut[i], ldw, udw);
}
- intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe),
+ intel_de_write_fw(display, PREC_PAL_MULTI_SEG_INDEX(pipe),
PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
/*
@@ -3899,15 +3912,15 @@ static const struct intel_color_funcs ilk_color_funcs = {
void intel_color_crtc_init(struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
int degamma_lut_size, gamma_lut_size;
bool has_ctm;
drm_mode_crtc_set_gamma_size(&crtc->base, 256);
- gamma_lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
- degamma_lut_size = DISPLAY_INFO(i915)->color.degamma_lut_size;
- has_ctm = DISPLAY_VER(i915) >= 5;
+ gamma_lut_size = DISPLAY_INFO(display)->color.gamma_lut_size;
+ degamma_lut_size = DISPLAY_INFO(display)->color.degamma_lut_size;
+ has_ctm = DISPLAY_VER(display) >= 5;
/*
* "DPALETTE_A: NOTE: The 8-bit (non-10-bit) mode is the
@@ -3917,57 +3930,59 @@ void intel_color_crtc_init(struct intel_crtc *crtc)
* Confirmed on alv,cst,pnv. Mobile gen2 parts (alm,mgm)
* are confirmed not to suffer from this restriction.
*/
- if (DISPLAY_VER(i915) == 3 && crtc->pipe == PIPE_A)
+ if (DISPLAY_VER(display) == 3 && crtc->pipe == PIPE_A)
gamma_lut_size = 256;
drm_crtc_enable_color_mgmt(&crtc->base, degamma_lut_size,
has_ctm, gamma_lut_size);
}
-int intel_color_init(struct drm_i915_private *i915)
+int intel_color_init(struct intel_display *display)
{
struct drm_property_blob *blob;
- if (DISPLAY_VER(i915) != 10)
+ if (DISPLAY_VER(display) != 10)
return 0;
- blob = create_linear_lut(i915,
- DISPLAY_INFO(i915)->color.degamma_lut_size);
+ blob = create_linear_lut(display,
+ DISPLAY_INFO(display)->color.degamma_lut_size);
if (IS_ERR(blob))
return PTR_ERR(blob);
- i915->display.color.glk_linear_degamma_lut = blob;
+ display->color.glk_linear_degamma_lut = blob;
return 0;
}
-void intel_color_init_hooks(struct drm_i915_private *i915)
+void intel_color_init_hooks(struct intel_display *display)
{
- if (HAS_GMCH(i915)) {
+ struct drm_i915_private *i915 = to_i915(display->drm);
+
+ if (HAS_GMCH(display)) {
if (IS_CHERRYVIEW(i915))
- i915->display.funcs.color = &chv_color_funcs;
+ display->funcs.color = &chv_color_funcs;
else if (IS_VALLEYVIEW(i915))
- i915->display.funcs.color = &vlv_color_funcs;
- else if (DISPLAY_VER(i915) >= 4)
- i915->display.funcs.color = &i965_color_funcs;
+ display->funcs.color = &vlv_color_funcs;
+ else if (DISPLAY_VER(display) >= 4)
+ display->funcs.color = &i965_color_funcs;
else
- i915->display.funcs.color = &i9xx_color_funcs;
+ display->funcs.color = &i9xx_color_funcs;
} else {
- if (DISPLAY_VER(i915) >= 12)
- i915->display.funcs.color = &tgl_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;
+ if (DISPLAY_VER(display) >= 12)
+ display->funcs.color = &tgl_color_funcs;
+ else if (DISPLAY_VER(display) == 11)
+ display->funcs.color = &icl_color_funcs;
+ else if (DISPLAY_VER(display) == 10)
+ display->funcs.color = &glk_color_funcs;
+ else if (DISPLAY_VER(display) == 9)
+ display->funcs.color = &skl_color_funcs;
+ else if (DISPLAY_VER(display) == 8)
+ 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;
+ display->funcs.color = &hsw_color_funcs;
+ else if (DISPLAY_VER(display) == 7)
+ display->funcs.color = &ivb_color_funcs;
else
- i915->display.funcs.color = &ilk_color_funcs;
+ 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 ba493f381031..9d66457c1e89 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -11,12 +11,12 @@
struct intel_atomic_state;
struct intel_crtc_state;
struct intel_crtc;
+struct intel_display;
struct intel_dsb;
-struct drm_i915_private;
struct drm_property_blob;
-void intel_color_init_hooks(struct drm_i915_private *i915);
-int intel_color_init(struct drm_i915_private *i915);
+void intel_color_init_hooks(struct intel_display *display);
+int intel_color_init(struct intel_display *display);
void intel_color_crtc_init(struct intel_crtc *crtc);
int intel_color_check(struct intel_atomic_state *state,
struct intel_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index fd78adbaadbe..74c1983fe07e 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -81,12 +81,13 @@ static struct intel_crt *intel_attached_crt(struct intel_connector *connector)
return intel_encoder_to_crt(intel_attached_encoder(connector));
}
-bool intel_crt_port_enabled(struct drm_i915_private *dev_priv,
+bool intel_crt_port_enabled(struct intel_display *display,
i915_reg_t adpa_reg, enum pipe *pipe)
{
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 val;
- val = intel_de_read(dev_priv, adpa_reg);
+ val = intel_de_read(display, adpa_reg);
/* asserts want to know the pipe even if the port is disabled */
if (HAS_PCH_CPT(dev_priv))
@@ -100,6 +101,7 @@ bool intel_crt_port_enabled(struct drm_i915_private *dev_priv,
static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crt *crt = intel_encoder_to_crt(encoder);
intel_wakeref_t wakeref;
@@ -110,7 +112,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
if (!wakeref)
return false;
- ret = intel_crt_port_enabled(dev_priv, crt->adpa_reg, pipe);
+ ret = intel_crt_port_enabled(display, crt->adpa_reg, pipe);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
@@ -119,11 +121,11 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_crt *crt = intel_encoder_to_crt(encoder);
u32 tmp, flags = 0;
- tmp = intel_de_read(dev_priv, crt->adpa_reg);
+ tmp = intel_de_read(display, crt->adpa_reg);
if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
@@ -168,13 +170,14 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int mode)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crt *crt = intel_encoder_to_crt(encoder);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
u32 adpa;
- if (DISPLAY_VER(dev_priv) >= 5)
+ if (DISPLAY_VER(display) >= 5)
adpa = ADPA_HOTPLUG_BITS;
else
adpa = 0;
@@ -193,7 +196,7 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder,
adpa |= ADPA_PIPE_SEL(crtc->pipe);
if (!HAS_PCH_SPLIT(dev_priv))
- intel_de_write(dev_priv, BCLRPAT(dev_priv, crtc->pipe), 0);
+ intel_de_write(display, BCLRPAT(display, crtc->pipe), 0);
switch (mode) {
case DRM_MODE_DPMS_ON:
@@ -210,7 +213,7 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder,
break;
}
- intel_de_write(dev_priv, crt->adpa_reg, adpa);
+ intel_de_write(display, crt->adpa_reg, adpa);
}
static void intel_disable_crt(struct intel_atomic_state *state,
@@ -241,9 +244,10 @@ static void hsw_disable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- drm_WARN_ON(&dev_priv->drm, !old_crtc_state->has_pch_encoder);
+ drm_WARN_ON(display->drm, !old_crtc_state->has_pch_encoder);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
}
@@ -253,6 +257,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
+ struct intel_display *display = to_intel_display(state);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -272,7 +277,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state,
hsw_fdi_disable(encoder);
- drm_WARN_ON(&dev_priv->drm, !old_crtc_state->has_pch_encoder);
+ drm_WARN_ON(display->drm, !old_crtc_state->has_pch_encoder);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
}
@@ -282,9 +287,10 @@ static void hsw_pre_pll_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- drm_WARN_ON(&dev_priv->drm, !crtc_state->has_pch_encoder);
+ drm_WARN_ON(display->drm, !crtc_state->has_pch_encoder);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
}
@@ -294,11 +300,12 @@ static void hsw_pre_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
- drm_WARN_ON(&dev_priv->drm, !crtc_state->has_pch_encoder);
+ drm_WARN_ON(display->drm, !crtc_state->has_pch_encoder);
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
@@ -312,11 +319,12 @@ static void hsw_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
- drm_WARN_ON(&dev_priv->drm, !crtc_state->has_pch_encoder);
+ drm_WARN_ON(display->drm, !crtc_state->has_pch_encoder);
intel_ddi_enable_transcoder_func(encoder, crtc_state);
@@ -346,9 +354,10 @@ static enum drm_mode_status
intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- int max_dotclk = dev_priv->display.cdclk.max_dotclk_freq;
+ int max_dotclk = display->cdclk.max_dotclk_freq;
enum drm_mode_status status;
int max_clock;
@@ -367,7 +376,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
* DAC limit supposedly 355 MHz.
*/
max_clock = 270000;
- else if (IS_DISPLAY_VER(dev_priv, 3, 4))
+ else if (IS_DISPLAY_VER(display, 3, 4))
max_clock = 400000;
else
max_clock = 350000;
@@ -428,6 +437,7 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
@@ -450,7 +460,7 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
if (HAS_PCH_LPT(dev_priv)) {
/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"LPT only supports 24bpp\n");
return -EINVAL;
}
@@ -470,6 +480,7 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -483,36 +494,36 @@ static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
crt->force_hotplug_required = false;
- save_adpa = adpa = intel_de_read(dev_priv, crt->adpa_reg);
- drm_dbg_kms(&dev_priv->drm,
+ save_adpa = adpa = intel_de_read(display, crt->adpa_reg);
+ drm_dbg_kms(display->drm,
"trigger hotplug detect cycle: adpa=0x%x\n", adpa);
adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
if (turn_off_dac)
adpa &= ~ADPA_DAC_ENABLE;
- intel_de_write(dev_priv, crt->adpa_reg, adpa);
+ intel_de_write(display, crt->adpa_reg, adpa);
- if (intel_de_wait_for_clear(dev_priv,
+ if (intel_de_wait_for_clear(display,
crt->adpa_reg,
ADPA_CRT_HOTPLUG_FORCE_TRIGGER,
1000))
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"timed out waiting for FORCE_TRIGGER");
if (turn_off_dac) {
- intel_de_write(dev_priv, crt->adpa_reg, save_adpa);
- intel_de_posting_read(dev_priv, crt->adpa_reg);
+ intel_de_write(display, crt->adpa_reg, save_adpa);
+ intel_de_posting_read(display, crt->adpa_reg);
}
}
/* Check the status to see if both blue and green are on now */
- adpa = intel_de_read(dev_priv, crt->adpa_reg);
+ adpa = intel_de_read(display, crt->adpa_reg);
if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
ret = true;
else
ret = false;
- drm_dbg_kms(&dev_priv->drm, "ironlake hotplug adpa=0x%x, result %d\n",
+ drm_dbg_kms(display->drm, "ironlake hotplug adpa=0x%x, result %d\n",
adpa, ret);
return ret;
@@ -520,6 +531,7 @@ static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -542,29 +554,29 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
*/
reenable_hpd = intel_hpd_disable(dev_priv, crt->base.hpd_pin);
- save_adpa = adpa = intel_de_read(dev_priv, crt->adpa_reg);
- drm_dbg_kms(&dev_priv->drm,
+ save_adpa = adpa = intel_de_read(display, crt->adpa_reg);
+ drm_dbg_kms(display->drm,
"trigger hotplug detect cycle: adpa=0x%x\n", adpa);
adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
- intel_de_write(dev_priv, crt->adpa_reg, adpa);
+ intel_de_write(display, crt->adpa_reg, adpa);
- if (intel_de_wait_for_clear(dev_priv, crt->adpa_reg,
+ if (intel_de_wait_for_clear(display, crt->adpa_reg,
ADPA_CRT_HOTPLUG_FORCE_TRIGGER, 1000)) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"timed out waiting for FORCE_TRIGGER");
- intel_de_write(dev_priv, crt->adpa_reg, save_adpa);
+ intel_de_write(display, crt->adpa_reg, save_adpa);
}
/* Check the status to see if both blue and green are on now */
- adpa = intel_de_read(dev_priv, crt->adpa_reg);
+ adpa = intel_de_read(display, crt->adpa_reg);
if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
ret = true;
else
ret = false;
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"valleyview hotplug adpa=0x%x, result %d\n", adpa, ret);
if (reenable_hpd)
@@ -575,6 +587,7 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
static bool intel_crt_detect_hotplug(struct drm_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
u32 stat;
@@ -603,18 +616,18 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
CRT_HOTPLUG_FORCE_DETECT,
CRT_HOTPLUG_FORCE_DETECT);
/* wait for FORCE_DETECT to go off */
- if (intel_de_wait_for_clear(dev_priv, PORT_HOTPLUG_EN(dev_priv),
+ if (intel_de_wait_for_clear(display, PORT_HOTPLUG_EN(display),
CRT_HOTPLUG_FORCE_DETECT, 1000))
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"timed out waiting for FORCE_DETECT to go off");
}
- stat = intel_de_read(dev_priv, PORT_HOTPLUG_STAT(dev_priv));
+ stat = intel_de_read(display, PORT_HOTPLUG_STAT(display));
if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
ret = true;
/* clear the interrupt we just generated, if any */
- intel_de_write(dev_priv, PORT_HOTPLUG_STAT(dev_priv),
+ intel_de_write(display, PORT_HOTPLUG_STAT(display),
CRT_HOTPLUG_INT_STATUS);
i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0);
@@ -660,8 +673,7 @@ static int intel_crt_ddc_get_modes(struct drm_connector *connector,
static bool intel_crt_detect_ddc(struct drm_connector *connector)
{
- struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
- struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
+ struct intel_display *display = to_intel_display(connector->dev);
const struct drm_edid *drm_edid;
bool ret = false;
@@ -674,15 +686,15 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
* have to check the EDID input spec of the attached device.
*/
if (drm_edid_is_digital(drm_edid)) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
} else {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"CRT detected via DDC:0x50 [EDID]\n");
ret = true;
}
} else {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"CRT not detected via DDC:0x50 [no valid EDID found]\n");
}
@@ -695,8 +707,6 @@ static enum drm_connector_status
intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
{
struct intel_display *display = to_intel_display(&crt->base);
- struct drm_device *dev = crt->base.base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
enum transcoder cpu_transcoder = (enum transcoder)pipe;
u32 save_bclrpat;
u32 save_vtotal;
@@ -707,14 +717,14 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
u8 st00;
enum drm_connector_status status;
- drm_dbg_kms(&dev_priv->drm, "starting load-detect on CRT\n");
+ drm_dbg_kms(display->drm, "starting load-detect on CRT\n");
- save_bclrpat = intel_de_read(dev_priv,
- BCLRPAT(dev_priv, cpu_transcoder));
- save_vtotal = intel_de_read(dev_priv,
- TRANS_VTOTAL(dev_priv, cpu_transcoder));
- vblank = intel_de_read(dev_priv,
- TRANS_VBLANK(dev_priv, cpu_transcoder));
+ save_bclrpat = intel_de_read(display,
+ BCLRPAT(display, cpu_transcoder));
+ save_vtotal = intel_de_read(display,
+ TRANS_VTOTAL(display, cpu_transcoder));
+ vblank = intel_de_read(display,
+ TRANS_VBLANK(display, cpu_transcoder));
vtotal = REG_FIELD_GET(VTOTAL_MASK, save_vtotal) + 1;
vactive = REG_FIELD_GET(VACTIVE_MASK, save_vtotal) + 1;
@@ -723,25 +733,25 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
vblank_end = REG_FIELD_GET(VBLANK_END_MASK, vblank) + 1;
/* Set the border color to purple. */
- intel_de_write(dev_priv, BCLRPAT(dev_priv, cpu_transcoder), 0x500050);
+ intel_de_write(display, BCLRPAT(display, cpu_transcoder), 0x500050);
- if (DISPLAY_VER(dev_priv) != 2) {
- u32 transconf = intel_de_read(dev_priv,
- TRANSCONF(dev_priv, cpu_transcoder));
+ if (DISPLAY_VER(display) != 2) {
+ u32 transconf = intel_de_read(display,
+ TRANSCONF(display, cpu_transcoder));
- intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder),
+ intel_de_write(display, TRANSCONF(display, cpu_transcoder),
transconf | TRANSCONF_FORCE_BORDER);
- intel_de_posting_read(dev_priv,
- TRANSCONF(dev_priv, cpu_transcoder));
+ intel_de_posting_read(display,
+ TRANSCONF(display, cpu_transcoder));
/* Wait for next Vblank to substitue
* border color for Color info */
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(display, pipe));
- st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE);
+ st00 = intel_de_read8(display, _VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
connector_status_connected :
connector_status_disconnected;
- intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder),
+ intel_de_write(display, TRANSCONF(display, cpu_transcoder),
transconf);
} else {
bool restore_vblank = false;
@@ -752,13 +762,13 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
* Yes, this will flicker
*/
if (vblank_start <= vactive && vblank_end >= vtotal) {
- u32 vsync = intel_de_read(dev_priv,
- TRANS_VSYNC(dev_priv, cpu_transcoder));
+ u32 vsync = intel_de_read(display,
+ TRANS_VSYNC(display, cpu_transcoder));
u32 vsync_start = REG_FIELD_GET(VSYNC_START_MASK, vsync) + 1;
vblank_start = vsync_start;
- intel_de_write(dev_priv,
- TRANS_VBLANK(dev_priv, cpu_transcoder),
+ intel_de_write(display,
+ TRANS_VBLANK(display, cpu_transcoder),
VBLANK_START(vblank_start - 1) |
VBLANK_END(vblank_end - 1));
restore_vblank = true;
@@ -772,9 +782,9 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
/*
* Wait for the border to be displayed
*/
- while (intel_de_read(dev_priv, PIPEDSL(dev_priv, pipe)) >= vactive)
+ while (intel_de_read(display, PIPEDSL(display, pipe)) >= vactive)
;
- while ((dsl = intel_de_read(dev_priv, PIPEDSL(dev_priv, pipe))) <= vsample)
+ while ((dsl = intel_de_read(display, PIPEDSL(display, pipe))) <= vsample)
;
/*
* Watch ST00 for an entire scanline
@@ -784,15 +794,15 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
do {
count++;
/* Read the ST00 VGA status register */
- st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE);
+ st00 = intel_de_read8(display, _VGA_MSR_WRITE);
if (st00 & (1 << 4))
detect++;
- } while ((intel_de_read(dev_priv, PIPEDSL(dev_priv, pipe)) == dsl));
+ } while ((intel_de_read(display, PIPEDSL(display, pipe)) == dsl));
/* restore vblank if necessary */
if (restore_vblank)
- intel_de_write(dev_priv,
- TRANS_VBLANK(dev_priv, cpu_transcoder),
+ intel_de_write(display,
+ TRANS_VBLANK(display, cpu_transcoder),
vblank);
/*
* If more than 3/4 of the scanline detected a monitor,
@@ -806,7 +816,7 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
}
/* Restore previous settings */
- intel_de_write(dev_priv, BCLRPAT(dev_priv, cpu_transcoder),
+ intel_de_write(display, BCLRPAT(display, cpu_transcoder),
save_bclrpat);
return status;
@@ -843,6 +853,7 @@ intel_crt_detect(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force)
{
+ struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *intel_encoder = &crt->base;
@@ -850,7 +861,7 @@ intel_crt_detect(struct drm_connector *connector,
intel_wakeref_t wakeref;
int status;
- drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] force=%d\n",
+ drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] force=%d\n",
connector->base.id, connector->name,
force);
@@ -860,7 +871,7 @@ intel_crt_detect(struct drm_connector *connector,
if (!intel_display_driver_check_access(dev_priv))
return connector->status;
- if (dev_priv->display.params.load_detect_test) {
+ if (display->params.load_detect_test) {
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
goto load_detect;
@@ -873,18 +884,18 @@ intel_crt_detect(struct drm_connector *connector,
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
- if (I915_HAS_HOTPLUG(dev_priv)) {
+ if (I915_HAS_HOTPLUG(display)) {
/* We can not rely on the HPD pin always being correctly wired
* up, for example many KVM do not pass it through, and so
* only trust an assertion that the monitor is connected.
*/
if (intel_crt_detect_hotplug(connector)) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"CRT detected via hotplug\n");
status = connector_status_connected;
goto out;
} else
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"CRT not detected via hotplug\n");
}
@@ -897,7 +908,7 @@ intel_crt_detect(struct drm_connector *connector,
* broken monitor (without edid) to work behind a broken kvm (that fails
* to have the right resistors for HP detection) needs to fix this up.
* For now just bail out. */
- if (I915_HAS_HOTPLUG(dev_priv)) {
+ if (I915_HAS_HOTPLUG(display)) {
status = connector_status_disconnected;
goto out;
}
@@ -917,10 +928,10 @@ load_detect:
} else {
if (intel_crt_detect_ddc(connector))
status = connector_status_connected;
- else if (DISPLAY_VER(dev_priv) < 4)
+ else if (DISPLAY_VER(display) < 4)
status = intel_crt_load_detect(crt,
to_intel_crtc(connector->state->crtc)->pipe);
- else if (dev_priv->display.params.load_detect_test)
+ else if (display->params.load_detect_test)
status = connector_status_disconnected;
else
status = connector_status_unknown;
@@ -935,6 +946,7 @@ out:
static int intel_crt_get_modes(struct drm_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
@@ -954,7 +966,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
goto out;
/* Try to probe digital port for output in DVI-I -> VGA mode. */
- ddc = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB);
+ ddc = intel_gmbus_get_adapter(display, GMBUS_PIN_DPB);
ret = intel_crt_ddc_get_modes(connector, ddc);
out:
@@ -965,19 +977,19 @@ out:
void intel_crt_reset(struct drm_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->dev);
+ struct intel_display *display = to_intel_display(encoder->dev);
struct intel_crt *crt = intel_encoder_to_crt(to_intel_encoder(encoder));
- if (DISPLAY_VER(dev_priv) >= 5) {
+ if (DISPLAY_VER(display) >= 5) {
u32 adpa;
- adpa = intel_de_read(dev_priv, crt->adpa_reg);
+ adpa = intel_de_read(display, crt->adpa_reg);
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
adpa |= ADPA_HOTPLUG_BITS;
- intel_de_write(dev_priv, crt->adpa_reg, adpa);
- intel_de_posting_read(dev_priv, crt->adpa_reg);
+ intel_de_write(display, crt->adpa_reg, adpa);
+ intel_de_posting_read(display, crt->adpa_reg);
- drm_dbg_kms(&dev_priv->drm, "crt adpa set to 0x%x\n", adpa);
+ drm_dbg_kms(display->drm, "crt adpa set to 0x%x\n", adpa);
crt->force_hotplug_required = true;
}
@@ -1007,8 +1019,9 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
.destroy = intel_encoder_destroy,
};
-void intel_crt_init(struct drm_i915_private *dev_priv)
+void intel_crt_init(struct intel_display *display)
{
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
struct drm_connector *connector;
struct intel_crt *crt;
struct intel_connector *intel_connector;
@@ -1023,7 +1036,7 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
else
adpa_reg = ADPA;
- adpa = intel_de_read(dev_priv, adpa_reg);
+ adpa = intel_de_read(display, adpa_reg);
if ((adpa & ADPA_DAC_ENABLE) == 0) {
/*
* On some machines (some IVB at least) CRT can be
@@ -1033,11 +1046,11 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
* take. So the only way to tell is attempt to enable
* it and see what happens.
*/
- intel_de_write(dev_priv, adpa_reg,
+ intel_de_write(display, adpa_reg,
adpa | ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
- if ((intel_de_read(dev_priv, adpa_reg) & ADPA_DAC_ENABLE) == 0)
+ if ((intel_de_read(display, adpa_reg) & ADPA_DAC_ENABLE) == 0)
return;
- intel_de_write(dev_priv, adpa_reg, adpa);
+ intel_de_write(display, adpa_reg, adpa);
}
crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
@@ -1050,16 +1063,16 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
return;
}
- ddc_pin = dev_priv->display.vbt.crt_ddc_pin;
+ ddc_pin = display->vbt.crt_ddc_pin;
connector = &intel_connector->base;
crt->connector = intel_connector;
- drm_connector_init_with_ddc(&dev_priv->drm, connector,
+ drm_connector_init_with_ddc(display->drm, connector,
&intel_crt_connector_funcs,
DRM_MODE_CONNECTOR_VGA,
- intel_gmbus_get_adapter(dev_priv, ddc_pin));
+ intel_gmbus_get_adapter(display, ddc_pin));
- drm_encoder_init(&dev_priv->drm, &crt->base.base, &intel_crt_enc_funcs,
+ drm_encoder_init(display->drm, &crt->base.base, &intel_crt_enc_funcs,
DRM_MODE_ENCODER_DAC, "CRT");
intel_connector_attach_encoder(intel_connector, &crt->base);
@@ -1071,14 +1084,14 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
else
crt->base.pipe_mask = ~0;
- if (DISPLAY_VER(dev_priv) != 2)
+ if (DISPLAY_VER(display) != 2)
connector->interlace_allowed = true;
crt->adpa_reg = adpa_reg;
crt->base.power_domain = POWER_DOMAIN_PORT_CRT;
- if (I915_HAS_HOTPLUG(dev_priv) &&
+ if (I915_HAS_HOTPLUG(display) &&
!dmi_check_system(intel_spurious_crt_detect)) {
crt->base.hpd_pin = HPD_CRT;
crt->base.hotplug = intel_encoder_hotplug;
@@ -1088,7 +1101,7 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
}
intel_connector->base.polled = intel_connector->polled;
- if (HAS_DDI(dev_priv)) {
+ if (HAS_DDI(display)) {
assert_port_valid(dev_priv, PORT_E);
crt->base.port = PORT_E;
@@ -1132,8 +1145,8 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
FDI_RX_LINK_REVERSAL_OVERRIDE;
- dev_priv->display.fdi.rx_config = intel_de_read(dev_priv,
- FDI_RX_CTL(PIPE_A)) & fdi_config;
+ display->fdi.rx_config = intel_de_read(display,
+ FDI_RX_CTL(PIPE_A)) & fdi_config;
}
intel_crt_reset(&crt->base.base);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.h b/drivers/gpu/drm/i915/display/intel_crt.h
index fe7690c2b948..e0abfe96a3d2 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.h
+++ b/drivers/gpu/drm/i915/display/intel_crt.h
@@ -10,20 +10,20 @@
enum pipe;
struct drm_encoder;
-struct drm_i915_private;
+struct intel_display;
#ifdef I915
-bool intel_crt_port_enabled(struct drm_i915_private *dev_priv,
+bool intel_crt_port_enabled(struct intel_display *display,
i915_reg_t adpa_reg, enum pipe *pipe);
-void intel_crt_init(struct drm_i915_private *dev_priv);
+void intel_crt_init(struct intel_display *display);
void intel_crt_reset(struct drm_encoder *encoder);
#else
-static inline bool intel_crt_port_enabled(struct drm_i915_private *dev_priv,
+static inline bool intel_crt_port_enabled(struct intel_display *display,
i915_reg_t adpa_reg, enum pipe *pipe)
{
return false;
}
-static inline void intel_crt_init(struct drm_i915_private *dev_priv)
+static inline void intel_crt_init(struct intel_display *display)
{
}
static inline void intel_crt_reset(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 3c9168a57f38..a2c528d707f4 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -36,11 +36,11 @@
static void assert_vblank_disabled(struct drm_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->dev);
+ struct intel_display *display = to_intel_display(crtc->dev);
- if (I915_STATE_WARN(i915, drm_crtc_vblank_get(crtc) == 0,
- "[CRTC:%d:%s] vblank assertion failure (expected off, current on)\n",
- crtc->base.id, crtc->name))
+ if (INTEL_DISPLAY_STATE_WARN(display, drm_crtc_vblank_get(crtc) == 0,
+ "[CRTC:%d:%s] vblank assertion failure (expected off, current on)\n",
+ crtc->base.id, crtc->name))
drm_crtc_vblank_put(crtc);
}
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index f73d576fd99e..71dc659228ab 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -34,6 +34,9 @@ bool intel_encoder_is_c10phy(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_encoder_to_phy(encoder);
+ if (IS_PANTHERLAKE(i915) && phy == PHY_A)
+ return true;
+
if ((IS_LUNARLAKE(i915) || IS_METEORLAKE(i915)) && phy < PHY_C)
return true;
@@ -65,22 +68,23 @@ static u8 intel_cx0_get_owned_lane_mask(struct intel_encoder *encoder)
}
static void
-assert_dc_off(struct drm_i915_private *i915)
+assert_dc_off(struct intel_display *display)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
bool enabled;
enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
- drm_WARN_ON(&i915->drm, !enabled);
+ drm_WARN_ON(display->drm, !enabled);
}
static void intel_cx0_program_msgbus_timer(struct intel_encoder *encoder)
{
+ struct intel_display *display = to_intel_display(encoder);
int lane;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
for_each_cx0_lane_in_mask(INTEL_CX0_BOTH_LANES, lane)
- intel_de_rmw(i915,
- XELPDP_PORT_MSGBUS_TIMER(i915, encoder->port, lane),
+ intel_de_rmw(display,
+ XELPDP_PORT_MSGBUS_TIMER(display, encoder->port, lane),
XELPDP_PORT_MSGBUS_TIMER_VAL_MASK,
XELPDP_PORT_MSGBUS_TIMER_VAL);
}
@@ -119,25 +123,28 @@ static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_w
static void intel_clear_response_ready_flag(struct intel_encoder *encoder,
int lane)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
- intel_de_rmw(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(i915, encoder->port, lane),
+ intel_de_rmw(display,
+ XELPDP_PORT_P2M_MSGBUS_STATUS(display, encoder->port, lane),
0, XELPDP_PORT_P2M_RESPONSE_READY | XELPDP_PORT_P2M_ERROR_SET);
}
static void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum phy phy = intel_encoder_to_phy(encoder);
- intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_RESET);
- if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_RESET,
XELPDP_MSGBUS_TIMEOUT_SLOW)) {
- drm_err_once(&i915->drm, "Failed to bring PHY %c to idle.\n", phy_name(phy));
+ drm_err_once(display->drm,
+ "Failed to bring PHY %c to idle.\n",
+ phy_name(phy));
return;
}
@@ -147,22 +154,23 @@ static void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane)
static int intel_cx0_wait_for_ack(struct intel_encoder *encoder,
int command, int lane, u32 *val)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum phy phy = intel_encoder_to_phy(encoder);
- if (intel_de_wait_custom(i915,
- XELPDP_PORT_P2M_MSGBUS_STATUS(i915, port, lane),
+ if (intel_de_wait_custom(display,
+ XELPDP_PORT_P2M_MSGBUS_STATUS(display, port, lane),
XELPDP_PORT_P2M_RESPONSE_READY,
XELPDP_PORT_P2M_RESPONSE_READY,
XELPDP_MSGBUS_TIMEOUT_FAST_US,
XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
- drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
+ drm_dbg_kms(display->drm,
+ "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
phy_name(phy), *val);
- if (!(intel_de_read(i915, XELPDP_PORT_MSGBUS_TIMER(i915, port, lane)) &
+ if (!(intel_de_read(display, XELPDP_PORT_MSGBUS_TIMER(display, port, lane)) &
XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT))
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"PHY %c Hardware did not detect a timeout\n",
phy_name(phy));
@@ -171,14 +179,18 @@ static int intel_cx0_wait_for_ack(struct intel_encoder *encoder,
}
if (*val & XELPDP_PORT_P2M_ERROR_SET) {
- drm_dbg_kms(&i915->drm, "PHY %c Error occurred during %s command. Status: 0x%x\n", phy_name(phy),
+ drm_dbg_kms(display->drm,
+ "PHY %c Error occurred during %s command. Status: 0x%x\n",
+ phy_name(phy),
command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val);
intel_cx0_bus_reset(encoder, lane);
return -EINVAL;
}
if (REG_FIELD_GET(XELPDP_PORT_P2M_COMMAND_TYPE_MASK, *val) != command) {
- drm_dbg_kms(&i915->drm, "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n", phy_name(phy),
+ drm_dbg_kms(display->drm,
+ "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n",
+ phy_name(phy),
command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val);
intel_cx0_bus_reset(encoder, lane);
return -EINVAL;
@@ -190,22 +202,22 @@ static int intel_cx0_wait_for_ack(struct intel_encoder *encoder,
static int __intel_cx0_read_once(struct intel_encoder *encoder,
int lane, u16 addr)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum phy phy = intel_encoder_to_phy(encoder);
int ack;
u32 val;
- if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_PENDING,
XELPDP_MSGBUS_TIMEOUT_SLOW)) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"PHY %c Timeout waiting for previous transaction to complete. Reset the bus and retry.\n", phy_name(phy));
intel_cx0_bus_reset(encoder, lane);
return -ETIMEDOUT;
}
- intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_PENDING |
XELPDP_PORT_M2P_COMMAND_READ |
XELPDP_PORT_M2P_ADDRESS(addr));
@@ -221,7 +233,8 @@ static int __intel_cx0_read_once(struct intel_encoder *encoder,
* down and let the message bus to end up
* in a known state
*/
- intel_cx0_bus_reset(encoder, lane);
+ if (DISPLAY_VER(display) < 30)
+ intel_cx0_bus_reset(encoder, lane);
return REG_FIELD_GET(XELPDP_PORT_P2M_DATA_MASK, val);
}
@@ -229,11 +242,11 @@ static int __intel_cx0_read_once(struct intel_encoder *encoder,
static u8 __intel_cx0_read(struct intel_encoder *encoder,
int lane, u16 addr)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
int i, status;
- assert_dc_off(i915);
+ assert_dc_off(display);
/* 3 tries is assumed to be enough to read successfully */
for (i = 0; i < 3; i++) {
@@ -243,7 +256,8 @@ static u8 __intel_cx0_read(struct intel_encoder *encoder,
return status;
}
- drm_err_once(&i915->drm, "PHY %c Read %04x failed after %d retries.\n",
+ drm_err_once(display->drm,
+ "PHY %c Read %04x failed after %d retries.\n",
phy_name(phy), addr, i);
return 0;
@@ -260,32 +274,32 @@ static u8 intel_cx0_read(struct intel_encoder *encoder,
static int __intel_cx0_write_once(struct intel_encoder *encoder,
int lane, u16 addr, u8 data, bool committed)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum phy phy = intel_encoder_to_phy(encoder);
int ack;
u32 val;
- if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_PENDING,
XELPDP_MSGBUS_TIMEOUT_SLOW)) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"PHY %c Timeout waiting for previous transaction to complete. Resetting the bus.\n", phy_name(phy));
intel_cx0_bus_reset(encoder, lane);
return -ETIMEDOUT;
}
- intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_PENDING |
(committed ? XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED :
XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED) |
XELPDP_PORT_M2P_DATA(data) |
XELPDP_PORT_M2P_ADDRESS(addr));
- if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_PENDING,
XELPDP_MSGBUS_TIMEOUT_SLOW)) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"PHY %c Timeout waiting for write to complete. Resetting the bus.\n", phy_name(phy));
intel_cx0_bus_reset(encoder, lane);
return -ETIMEDOUT;
@@ -295,9 +309,9 @@ static int __intel_cx0_write_once(struct intel_encoder *encoder,
ack = intel_cx0_wait_for_ack(encoder, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val);
if (ack < 0)
return ack;
- } else if ((intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(i915, port, lane)) &
+ } else if ((intel_de_read(display, XELPDP_PORT_P2M_MSGBUS_STATUS(display, port, lane)) &
XELPDP_PORT_P2M_ERROR_SET)) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"PHY %c Error occurred during write command.\n", phy_name(phy));
intel_cx0_bus_reset(encoder, lane);
return -EINVAL;
@@ -310,7 +324,8 @@ static int __intel_cx0_write_once(struct intel_encoder *encoder,
* down and let the message bus to end up
* in a known state
*/
- intel_cx0_bus_reset(encoder, lane);
+ if (DISPLAY_VER(display) < 30)
+ intel_cx0_bus_reset(encoder, lane);
return 0;
}
@@ -318,11 +333,11 @@ static int __intel_cx0_write_once(struct intel_encoder *encoder,
static void __intel_cx0_write(struct intel_encoder *encoder,
int lane, u16 addr, u8 data, bool committed)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
int i, status;
- assert_dc_off(i915);
+ assert_dc_off(display);
/* 3 tries is assumed to be enough to write successfully */
for (i = 0; i < 3; i++) {
@@ -332,7 +347,7 @@ static void __intel_cx0_write(struct intel_encoder *encoder,
return;
}
- drm_err_once(&i915->drm,
+ drm_err_once(display->drm,
"PHY %c Write %04x failed after %d retries.\n", phy_name(phy), addr, i);
}
@@ -348,9 +363,9 @@ static void intel_cx0_write(struct intel_encoder *encoder,
static void intel_c20_sram_write(struct intel_encoder *encoder,
int lane, u16 addr, u16 data)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
- assert_dc_off(i915);
+ assert_dc_off(display);
intel_cx0_write(encoder, lane, PHY_C20_WR_ADDRESS_H, addr >> 8, 0);
intel_cx0_write(encoder, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0);
@@ -362,10 +377,10 @@ static void intel_c20_sram_write(struct intel_encoder *encoder,
static u16 intel_c20_sram_read(struct intel_encoder *encoder,
int lane, u16 addr)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
u16 val;
- assert_dc_off(i915);
+ assert_dc_off(display);
intel_cx0_write(encoder, lane, PHY_C20_RD_ADDRESS_H, addr >> 8, 0);
intel_cx0_write(encoder, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 1);
@@ -429,7 +444,7 @@ static u8 intel_c10_get_tx_term_ctl(const struct intel_crtc_state *crtc_state)
void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
const struct intel_ddi_buf_trans *trans;
u8 owned_lane_mask;
intel_wakeref_t wakeref;
@@ -444,7 +459,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
wakeref = intel_cx0_phy_transaction_begin(encoder);
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
- if (drm_WARN_ON_ONCE(&i915->drm, !trans)) {
+ if (drm_WARN_ON_ONCE(display->drm, !trans)) {
intel_cx0_phy_transaction_end(encoder, wakeref);
return;
}
@@ -1122,6 +1137,22 @@ static const struct intel_c20pll_state * const xe2hpd_c20_dp_tables[] = {
NULL,
};
+static const struct intel_c20pll_state * const xe3lpd_c20_dp_edp_tables[] = {
+ &mtl_c20_dp_rbr,
+ &xe2hpd_c20_edp_r216,
+ &xe2hpd_c20_edp_r243,
+ &mtl_c20_dp_hbr1,
+ &xe2hpd_c20_edp_r324,
+ &xe2hpd_c20_edp_r432,
+ &mtl_c20_dp_hbr2,
+ &xe2hpd_c20_edp_r675,
+ &mtl_c20_dp_hbr3,
+ &mtl_c20_dp_uhbr10,
+ &xe2hpd_c20_dp_uhbr13_5,
+ &mtl_c20_dp_uhbr20,
+ NULL,
+};
+
/*
* HDMI link rates with 38.4 MHz reference clock.
*/
@@ -2003,12 +2034,12 @@ intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
int i;
if (intel_crtc_has_dp_encoder(crtc_state)) {
- if (intel_panel_use_ssc(i915)) {
+ if (intel_panel_use_ssc(display)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
pll_state->ssc_enabled =
@@ -2019,7 +2050,7 @@ static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
if (pll_state->ssc_enabled)
return;
- drm_WARN_ON(&i915->drm, ARRAY_SIZE(pll_state->c10.pll) < 9);
+ drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) < 9);
for (i = 4; i < 9; i++)
pll_state->c10.pll[i] = 0;
}
@@ -2073,7 +2104,7 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
}
-static void intel_c10_pll_program(struct drm_i915_private *i915,
+static void intel_c10_pll_program(struct intel_display *display,
const struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
@@ -2106,7 +2137,7 @@ static void intel_c10_pll_program(struct drm_i915_private *i915,
MB_WRITE_COMMITTED);
}
-static void intel_c10pll_dump_hw_state(struct drm_i915_private *i915,
+static void intel_c10pll_dump_hw_state(struct intel_display *display,
const struct intel_c10pll_state *hw_state)
{
bool fracen;
@@ -2115,35 +2146,39 @@ static void intel_c10pll_dump_hw_state(struct drm_i915_private *i915,
unsigned int multiplier, tx_clk_div;
fracen = hw_state->pll[0] & C10_PLL0_FRACEN;
- drm_dbg_kms(&i915->drm, "c10pll_hw_state: fracen: %s, ",
+ drm_dbg_kms(display->drm, "c10pll_hw_state: fracen: %s, ",
str_yes_no(fracen));
if (fracen) {
frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11];
frac_rem = hw_state->pll[14] << 8 | hw_state->pll[13];
frac_den = hw_state->pll[10] << 8 | hw_state->pll[9];
- drm_dbg_kms(&i915->drm, "quot: %u, rem: %u, den: %u,\n",
+ drm_dbg_kms(display->drm, "quot: %u, rem: %u, den: %u,\n",
frac_quot, frac_rem, frac_den);
}
multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, hw_state->pll[3]) << 8 |
hw_state->pll[2]) / 2 + 16;
tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, hw_state->pll[15]);
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div);
- drm_dbg_kms(&i915->drm, "c10pll_rawhw_state:");
- drm_dbg_kms(&i915->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, hw_state->cmn);
+ drm_dbg_kms(display->drm, "c10pll_rawhw_state:");
+ drm_dbg_kms(display->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx,
+ hw_state->cmn);
BUILD_BUG_ON(ARRAY_SIZE(hw_state->pll) % 4);
for (i = 0; i < ARRAY_SIZE(hw_state->pll); i = i + 4)
- drm_dbg_kms(&i915->drm, "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n",
+ drm_dbg_kms(display->drm,
+ "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n",
i, hw_state->pll[i], i + 1, hw_state->pll[i + 1],
i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]);
}
-static int intel_c20_compute_hdmi_tmds_pll(u64 pixel_clock, struct intel_c20pll_state *pll_state)
+static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
u64 datarate;
u64 mpll_tx_clk_div;
u64 vco_freq_shift;
@@ -2152,13 +2187,14 @@ static int intel_c20_compute_hdmi_tmds_pll(u64 pixel_clock, struct intel_c20pll_
u64 mpll_multiplier;
u64 mpll_fracn_quot;
u64 mpll_fracn_rem;
+ u16 tx_misc;
u8 mpllb_ana_freq_vco;
u8 mpll_div_multiplier;
- if (pixel_clock < 25175 || pixel_clock > 600000)
+ if (crtc_state->port_clock < 25175 || crtc_state->port_clock > 600000)
return -EINVAL;
- datarate = ((u64)pixel_clock * 1000) * 10;
+ datarate = ((u64)crtc_state->port_clock * 1000) * 10;
mpll_tx_clk_div = ilog2(div64_u64((u64)CLOCK_9999MHZ, (u64)datarate));
vco_freq_shift = ilog2(div64_u64((u64)CLOCK_4999MHZ * (u64)256, (u64)datarate));
vco_freq = (datarate << vco_freq_shift) >> 8;
@@ -2171,6 +2207,11 @@ static int intel_c20_compute_hdmi_tmds_pll(u64 pixel_clock, struct intel_c20pll_
mpll_div_multiplier = min_t(u8, div64_u64((vco_freq * 16 + (datarate >> 1)),
datarate), 255);
+ if (DISPLAY_VER(display) >= 20)
+ tx_misc = 0x5;
+ else
+ tx_misc = 0x0;
+
if (vco_freq <= DATARATE_3000000000)
mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_3;
else if (vco_freq <= DATARATE_3500000000)
@@ -2180,9 +2221,9 @@ static int intel_c20_compute_hdmi_tmds_pll(u64 pixel_clock, struct intel_c20pll_
else
mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_0;
- pll_state->clock = pixel_clock;
+ pll_state->clock = crtc_state->port_clock;
pll_state->tx[0] = 0xbe88;
- pll_state->tx[1] = 0x9800;
+ pll_state->tx[1] = 0x9800 | C20_PHY_TX_MISC(tx_misc);
pll_state->tx[2] = 0x0000;
pll_state->cmn[0] = 0x0500;
pll_state->cmn[1] = 0x0005;
@@ -2239,13 +2280,19 @@ static const struct intel_c20pll_state * const *
intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(crtc_state);
if (intel_crtc_has_dp_encoder(crtc_state)) {
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
- return xe2hpd_c20_edp_tables;
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
+ if (DISPLAY_RUNTIME_INFO(display)->edp_typec_support)
+ return xe3lpd_c20_dp_edp_tables;
+ if (DISPLAY_VERx100(display) == 1401)
+ return xe2hpd_c20_edp_tables;
+ }
- if (DISPLAY_VER_FULL(i915) == IP_VER(14, 1))
+ if (DISPLAY_VER(display) >= 30)
+ return xe3lpd_c20_dp_edp_tables;
+ else if (DISPLAY_VERx100(display) == 1401)
return xe2hpd_c20_dp_tables;
else
return mtl_c20_dp_tables;
@@ -2266,8 +2313,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
/* try computed C20 HDMI tables before using consolidated tables */
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
- if (intel_c20_compute_hdmi_tmds_pll(crtc_state->port_clock,
- &crtc_state->dpll_hw_state.cx0pll.c20) == 0)
+ if (intel_c20_compute_hdmi_tmds_pll(crtc_state) == 0)
return 0;
}
@@ -2347,10 +2393,10 @@ static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
struct intel_c20pll_state *pll_state)
{
+ struct intel_display *display = to_intel_display(encoder);
bool cntx;
intel_wakeref_t wakeref;
int i;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
wakeref = intel_cx0_phy_transaction_begin(encoder);
@@ -2362,11 +2408,11 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
if (cntx)
pll_state->tx[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_B_TX_CNTX_CFG(i915, i));
+ PHY_C20_B_TX_CNTX_CFG(display, i));
else
pll_state->tx[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_A_TX_CNTX_CFG(i915, i));
+ PHY_C20_A_TX_CNTX_CFG(display, i));
}
/* Read common configuration */
@@ -2374,11 +2420,11 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
if (cntx)
pll_state->cmn[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_B_CMN_CNTX_CFG(i915, i));
+ PHY_C20_B_CMN_CNTX_CFG(display, i));
else
pll_state->cmn[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_A_CMN_CNTX_CFG(i915, i));
+ PHY_C20_A_CMN_CNTX_CFG(display, i));
}
if (intel_c20phy_use_mpllb(pll_state)) {
@@ -2387,11 +2433,11 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
if (cntx)
pll_state->mpllb[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_B_MPLLB_CNTX_CFG(i915, i));
+ PHY_C20_B_MPLLB_CNTX_CFG(display, i));
else
pll_state->mpllb[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_A_MPLLB_CNTX_CFG(i915, i));
+ PHY_C20_A_MPLLB_CNTX_CFG(display, i));
}
} else {
/* MPLLA configuration */
@@ -2399,11 +2445,11 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
if (cntx)
pll_state->mplla[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_B_MPLLA_CNTX_CFG(i915, i));
+ PHY_C20_B_MPLLA_CNTX_CFG(display, i));
else
pll_state->mplla[i] = intel_c20_sram_read(encoder,
INTEL_CX0_LANE0,
- PHY_C20_A_MPLLA_CNTX_CFG(i915, i));
+ PHY_C20_A_MPLLA_CNTX_CFG(display, i));
}
}
@@ -2412,33 +2458,37 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
}
-static void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+static void intel_c20pll_dump_hw_state(struct intel_display *display,
const struct intel_c20pll_state *hw_state)
{
int i;
- drm_dbg_kms(&i915->drm, "c20pll_hw_state:\n");
- drm_dbg_kms(&i915->drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n",
+ drm_dbg_kms(display->drm, "c20pll_hw_state:\n");
+ drm_dbg_kms(display->drm,
+ "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n",
hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
- drm_dbg_kms(&i915->drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n",
+ drm_dbg_kms(display->drm,
+ "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n",
hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]);
if (intel_c20phy_use_mpllb(hw_state)) {
for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
- drm_dbg_kms(&i915->drm, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]);
+ drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i,
+ hw_state->mpllb[i]);
} else {
for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
- drm_dbg_kms(&i915->drm, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]);
+ drm_dbg_kms(display->drm, "mplla[%d] = 0x%.4x\n", i,
+ hw_state->mplla[i]);
}
}
-void intel_cx0pll_dump_hw_state(struct drm_i915_private *i915,
+void intel_cx0pll_dump_hw_state(struct intel_display *display,
const struct intel_cx0pll_state *hw_state)
{
if (hw_state->use_c10)
- intel_c10pll_dump_hw_state(i915, &hw_state->c10);
+ intel_c10pll_dump_hw_state(display, &hw_state->c10);
else
- intel_c20pll_dump_hw_state(i915, &hw_state->c20);
+ intel_c20pll_dump_hw_state(display, &hw_state->c20);
}
static u8 intel_c20_get_dp_rate(u32 clock)
@@ -2538,7 +2588,7 @@ static int intel_get_c20_custom_width(u32 clock, bool dp)
return 0;
}
-static void intel_c20_pll_program(struct drm_i915_private *i915,
+static void intel_c20_pll_program(struct intel_display *display,
const struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
@@ -2571,11 +2621,11 @@ static void intel_c20_pll_program(struct drm_i915_private *i915,
for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) {
if (cntx)
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_A_TX_CNTX_CFG(i915, i),
+ PHY_C20_A_TX_CNTX_CFG(display, i),
pll_state->tx[i]);
else
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_B_TX_CNTX_CFG(i915, i),
+ PHY_C20_B_TX_CNTX_CFG(display, i),
pll_state->tx[i]);
}
@@ -2583,11 +2633,11 @@ static void intel_c20_pll_program(struct drm_i915_private *i915,
for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) {
if (cntx)
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_A_CMN_CNTX_CFG(i915, i),
+ PHY_C20_A_CMN_CNTX_CFG(display, i),
pll_state->cmn[i]);
else
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_B_CMN_CNTX_CFG(i915, i),
+ PHY_C20_B_CMN_CNTX_CFG(display, i),
pll_state->cmn[i]);
}
@@ -2596,22 +2646,22 @@ static void intel_c20_pll_program(struct drm_i915_private *i915,
for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
if (cntx)
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_A_MPLLB_CNTX_CFG(i915, i),
+ PHY_C20_A_MPLLB_CNTX_CFG(display, i),
pll_state->mpllb[i]);
else
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_B_MPLLB_CNTX_CFG(i915, i),
+ PHY_C20_B_MPLLB_CNTX_CFG(display, i),
pll_state->mpllb[i]);
}
} else {
for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
if (cntx)
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_A_MPLLA_CNTX_CFG(i915, i),
+ PHY_C20_A_MPLLA_CNTX_CFG(display, i),
pll_state->mplla[i]);
else
intel_c20_sram_write(encoder, INTEL_CX0_LANE0,
- PHY_C20_B_MPLLA_CNTX_CFG(i915, i),
+ PHY_C20_B_MPLLA_CNTX_CFG(display, i),
pll_state->mplla[i]);
}
}
@@ -2678,10 +2728,10 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
bool lane_reversal)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
u32 val = 0;
- intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, encoder->port),
XELPDP_PORT_REVERSAL,
lane_reversal ? XELPDP_PORT_REVERSAL : 0);
@@ -2703,7 +2753,7 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
else
val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLA |
XELPDP_SSC_ENABLE_PLLB, val);
@@ -2734,48 +2784,49 @@ static u32 intel_cx0_get_powerdown_state(u8 lane_mask, u8 state)
static void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder,
u8 lane_mask, u8 state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum phy phy = intel_encoder_to_phy(encoder);
- i915_reg_t buf_ctl2_reg = XELPDP_PORT_BUF_CTL2(i915, port);
+ i915_reg_t buf_ctl2_reg = XELPDP_PORT_BUF_CTL2(display, port);
int lane;
- intel_de_rmw(i915, buf_ctl2_reg,
+ intel_de_rmw(display, buf_ctl2_reg,
intel_cx0_get_powerdown_state(INTEL_CX0_BOTH_LANES, XELPDP_LANE_POWERDOWN_NEW_STATE_MASK),
intel_cx0_get_powerdown_state(lane_mask, state));
/* Wait for pending transactions.*/
for_each_cx0_lane_in_mask(lane_mask, lane)
- if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane),
+ if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane),
XELPDP_PORT_M2P_TRANSACTION_PENDING,
XELPDP_MSGBUS_TIMEOUT_SLOW)) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"PHY %c Timeout waiting for previous transaction to complete. Reset the bus.\n",
phy_name(phy));
intel_cx0_bus_reset(encoder, lane);
}
- intel_de_rmw(i915, buf_ctl2_reg,
+ intel_de_rmw(display, buf_ctl2_reg,
intel_cx0_get_powerdown_update(INTEL_CX0_BOTH_LANES),
intel_cx0_get_powerdown_update(lane_mask));
/* Update Timeout Value */
- if (intel_de_wait_custom(i915, buf_ctl2_reg,
+ if (intel_de_wait_custom(display, buf_ctl2_reg,
intel_cx0_get_powerdown_update(lane_mask), 0,
XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 0, NULL))
- drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n",
+ drm_warn(display->drm,
+ "PHY %c failed to bring out of Lane reset after %dus.\n",
phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
}
static void intel_cx0_setup_powerdown(struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
- intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(i915, port),
+ intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port),
XELPDP_POWER_STATE_READY_MASK,
XELPDP_POWER_STATE_READY(CX0_P2_STATE_READY));
- intel_de_rmw(i915, XELPDP_PORT_BUF_CTL3(i915, port),
+ intel_de_rmw(display, XELPDP_PORT_BUF_CTL3(display, port),
XELPDP_POWER_STATE_ACTIVE_MASK |
XELPDP_PLL_LANE_STAGGERING_DELAY_MASK,
XELPDP_POWER_STATE_ACTIVE(CX0_P0_STATE_ACTIVE) |
@@ -2807,7 +2858,7 @@ static u32 intel_cx0_get_pclk_refclk_ack(u8 lane_mask)
static void intel_cx0_phy_lane_reset(struct intel_encoder *encoder,
bool lane_reversal)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum phy phy = intel_encoder_to_phy(encoder);
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
@@ -2820,48 +2871,51 @@ static void intel_cx0_phy_lane_reset(struct intel_encoder *encoder,
XELPDP_LANE_PHY_CURRENT_STATUS(1))
: XELPDP_LANE_PHY_CURRENT_STATUS(0);
- if (intel_de_wait_custom(i915, XELPDP_PORT_BUF_CTL1(i915, port),
+ if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL1(display, port),
XELPDP_PORT_BUF_SOC_PHY_READY,
XELPDP_PORT_BUF_SOC_PHY_READY,
XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US, 0, NULL))
- drm_warn(&i915->drm, "PHY %c failed to bring out of SOC reset after %dus.\n",
+ drm_warn(display->drm,
+ "PHY %c failed to bring out of SOC reset after %dus.\n",
phy_name(phy), XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US);
- intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(i915, port), lane_pipe_reset,
+ intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_pipe_reset,
lane_pipe_reset);
- if (intel_de_wait_custom(i915, XELPDP_PORT_BUF_CTL2(i915, port),
+ if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port),
lane_phy_current_status, lane_phy_current_status,
XELPDP_PORT_RESET_START_TIMEOUT_US, 0, NULL))
- drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n",
+ drm_warn(display->drm,
+ "PHY %c failed to bring out of Lane reset after %dus.\n",
phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port),
intel_cx0_get_pclk_refclk_request(owned_lane_mask),
intel_cx0_get_pclk_refclk_request(lane_mask));
- if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, port),
+ if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, port),
intel_cx0_get_pclk_refclk_ack(owned_lane_mask),
intel_cx0_get_pclk_refclk_ack(lane_mask),
XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL))
- drm_warn(&i915->drm, "PHY %c failed to request refclk after %dus.\n",
+ drm_warn(display->drm,
+ "PHY %c failed to request refclk after %dus.\n",
phy_name(phy), XELPDP_REFCLK_ENABLE_TIMEOUT_US);
intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES,
CX0_P2_STATE_RESET);
intel_cx0_setup_powerdown(encoder);
- intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(i915, port), lane_pipe_reset, 0);
+ intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_pipe_reset, 0);
- if (intel_de_wait_for_clear(i915, XELPDP_PORT_BUF_CTL2(i915, port),
+ if (intel_de_wait_for_clear(display, XELPDP_PORT_BUF_CTL2(display, port),
lane_phy_current_status,
XELPDP_PORT_RESET_END_TIMEOUT))
- drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dms.\n",
+ drm_warn(display->drm,
+ "PHY %c failed to bring out of Lane reset after %dms.\n",
phy_name(phy), XELPDP_PORT_RESET_END_TIMEOUT);
}
-static void intel_cx0_program_phy_lane(struct drm_i915_private *i915,
- struct intel_encoder *encoder, int lane_count,
+static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_count,
bool lane_reversal)
{
int i;
@@ -2930,7 +2984,7 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
static void intel_cx0pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
@@ -2962,15 +3016,15 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
/* 5. Program PHY internal PLL internal registers. */
if (intel_encoder_is_c10phy(encoder))
- intel_c10_pll_program(i915, crtc_state, encoder);
+ intel_c10_pll_program(display, crtc_state, encoder);
else
- intel_c20_pll_program(i915, crtc_state, encoder);
+ intel_c20_pll_program(display, crtc_state, encoder);
/*
* 6. Program the enabled and disabled owned PHY lane
* transmitters over message bus
*/
- intel_cx0_program_phy_lane(i915, encoder, crtc_state->lane_count, lane_reversal);
+ intel_cx0_program_phy_lane(encoder, crtc_state->lane_count, lane_reversal);
/*
* 7. Follow the Display Voltage Frequency Switching - Sequence
@@ -2981,23 +3035,23 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
* 8. Program DDI_CLK_VALFREQ to match intended DDI
* clock frequency.
*/
- intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
crtc_state->port_clock);
/*
* 9. Set PORT_CLOCK_CTL register PCLK PLL Request
* LN<Lane for maxPCLK> to "1" to enable PLL.
*/
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES),
intel_cx0_get_pclk_pll_request(maxpclk_lane));
/* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
- if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES),
intel_cx0_get_pclk_pll_ack(maxpclk_lane),
XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, 0, NULL))
- drm_warn(&i915->drm, "Port %c PLL not locked after %dus.\n",
+ drm_warn(display->drm, "Port %c PLL not locked after %dus.\n",
phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US);
/*
@@ -3011,15 +3065,16 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- u32 clock;
- u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port));
+ struct intel_display *display = to_intel_display(encoder);
+ u32 clock, val;
+
+ val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port));
clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
- drm_WARN_ON(&i915->drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
- drm_WARN_ON(&i915->drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
- drm_WARN_ON(&i915->drm, !(val & XELPDP_TBT_CLOCK_ACK));
+ drm_WARN_ON(display->drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
+ drm_WARN_ON(display->drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
+ drm_WARN_ON(display->drm, !(val & XELPDP_TBT_CLOCK_ACK));
switch (clock) {
case XELPDP_DDI_CLOCK_SELECT_TBT_162:
@@ -3036,7 +3091,7 @@ int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
}
}
-static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
+static int intel_mtl_tbt_clock_select(int clock)
{
switch (clock) {
case 162000:
@@ -3056,7 +3111,7 @@ static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
u32 val = 0;
@@ -3064,13 +3119,13 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
* 1. Program PORT_CLOCK_CTL REGISTER to configure
* clock muxes, gating and SSC
*/
- val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(i915, crtc_state->port_clock));
+ val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(crtc_state->port_clock));
val |= XELPDP_FORWARD_CLOCK_UNGATE;
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_FORWARD_CLOCK_UNGATE, val);
/* 2. Read back PORT_CLOCK_CTL REGISTER */
- val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port));
+ val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port));
/*
* 3. Follow the Display Voltage Frequency Switching - Sequence
@@ -3081,14 +3136,15 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
* 4. Set PORT_CLOCK_CTL register TBT CLOCK Request to "1" to enable PLL.
*/
val |= XELPDP_TBT_CLOCK_REQUEST;
- intel_de_write(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), val);
+ intel_de_write(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), val);
/* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */
- if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_TBT_CLOCK_ACK,
XELPDP_TBT_CLOCK_ACK,
100, 0, NULL))
- drm_warn(&i915->drm, "[ENCODER:%d:%s][%c] PHY PLL not locked after 100us.\n",
+ drm_warn(display->drm,
+ "[ENCODER:%d:%s][%c] PHY PLL not locked after 100us.\n",
encoder->base.base.id, encoder->base.name, phy_name(phy));
/*
@@ -3100,7 +3156,7 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
* 7. Program DDI_CLK_VALFREQ to match intended DDI
* clock frequency.
*/
- intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
crtc_state->port_clock);
}
@@ -3117,12 +3173,14 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder,
static u8 cx0_power_control_disable_val(struct intel_encoder *encoder)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
if (intel_encoder_is_c10phy(encoder))
return CX0_P2PG_STATE_DISABLE;
- if (IS_BATTLEMAGE(i915) && encoder->port == PORT_A)
+ if ((IS_BATTLEMAGE(i915) && encoder->port == PORT_A) ||
+ (DISPLAY_VER(display) >= 30 && encoder->type == INTEL_OUTPUT_EDP))
return CX0_P2PG_STATE_DISABLE;
return CX0_P4PG_STATE_DISABLE;
@@ -3130,7 +3188,7 @@ static u8 cx0_power_control_disable_val(struct intel_encoder *encoder)
static void intel_cx0pll_disable(struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder);
@@ -3147,21 +3205,22 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder)
* 3. Set PORT_CLOCK_CTL register PCLK PLL Request LN<Lane for maxPCLK>
* to "0" to disable PLL.
*/
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES) |
intel_cx0_get_pclk_refclk_request(INTEL_CX0_BOTH_LANES), 0);
/* 4. Program DDI_CLK_VALFREQ to 0. */
- intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port), 0);
+ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), 0);
/*
* 5. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK**> == "0".
*/
- if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES) |
intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES), 0,
XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US, 0, NULL))
- drm_warn(&i915->drm, "Port %c PLL not unlocked after %dus.\n",
+ drm_warn(display->drm,
+ "Port %c PLL not unlocked after %dus.\n",
phy_name(phy), XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US);
/*
@@ -3170,9 +3229,9 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder)
*/
/* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_DDI_CLOCK_SELECT_MASK, 0);
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_FORWARD_CLOCK_UNGATE, 0);
intel_cx0_phy_transaction_end(encoder, wakeref);
@@ -3180,7 +3239,7 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder)
static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
/*
@@ -3191,13 +3250,14 @@ static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
/*
* 2. Set PORT_CLOCK_CTL register TBT CLOCK Request to "0" to disable PLL.
*/
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_TBT_CLOCK_REQUEST, 0);
/* 3. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "0". */
- if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_TBT_CLOCK_ACK, 0, 10, 0, NULL))
- drm_warn(&i915->drm, "[ENCODER:%d:%s][%c] PHY PLL not unlocked after 10us.\n",
+ drm_warn(display->drm,
+ "[ENCODER:%d:%s][%c] PHY PLL not unlocked after 10us.\n",
encoder->base.base.id, encoder->base.name, phy_name(phy));
/*
@@ -3208,12 +3268,12 @@ static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
/*
* 5. Program PORT CLOCK CTRL register to disable and gate clocks
*/
- intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port),
+ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_DDI_CLOCK_SELECT_MASK |
XELPDP_FORWARD_CLOCK_UNGATE, 0);
/* 6. Program DDI_CLK_VALFREQ to 0. */
- intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port), 0);
+ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), 0);
}
void intel_mtl_pll_disable(struct intel_encoder *encoder)
@@ -3230,13 +3290,15 @@ enum icl_port_dpll_id
intel_mtl_port_pll_type(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
+ u32 val, clock;
+
/*
* TODO: Determine the PLL type from the SW state, once MTL PLL
* handling is done via the standard shared DPLL framework.
*/
- u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port));
- u32 clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+ val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port));
+ clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK ||
clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK)
@@ -3250,28 +3312,28 @@ static void intel_c10pll_state_verify(const struct intel_crtc_state *state,
struct intel_encoder *encoder,
struct intel_c10pll_state *mpllb_hw_state)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_c10pll_state *mpllb_sw_state = &state->dpll_hw_state.cx0pll.c10;
int i;
for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
u8 expected = mpllb_sw_state->pll[i];
- I915_STATE_WARN(i915, mpllb_hw_state->pll[i] != expected,
- "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)",
- crtc->base.base.id, crtc->base.name, i,
- expected, mpllb_hw_state->pll[i]);
+ INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->pll[i] != expected,
+ "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)",
+ crtc->base.base.id, crtc->base.name, i,
+ expected, mpllb_hw_state->pll[i]);
}
- I915_STATE_WARN(i915, mpllb_hw_state->tx != mpllb_sw_state->tx,
- "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)",
- crtc->base.base.id, crtc->base.name,
- mpllb_sw_state->tx, mpllb_hw_state->tx);
+ INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->tx != mpllb_sw_state->tx,
+ "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)",
+ crtc->base.base.id, crtc->base.name,
+ mpllb_sw_state->tx, mpllb_hw_state->tx);
- I915_STATE_WARN(i915, mpllb_hw_state->cmn != mpllb_sw_state->cmn,
- "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)",
- crtc->base.base.id, crtc->base.name,
- mpllb_sw_state->cmn, mpllb_hw_state->cmn);
+ INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->cmn != mpllb_sw_state->cmn,
+ "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)",
+ crtc->base.base.id, crtc->base.name,
+ mpllb_sw_state->cmn, mpllb_hw_state->cmn);
}
void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
@@ -3357,64 +3419,64 @@ static void intel_c20pll_state_verify(const struct intel_crtc_state *state,
struct intel_encoder *encoder,
struct intel_c20pll_state *mpll_hw_state)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_c20pll_state *mpll_sw_state = &state->dpll_hw_state.cx0pll.c20;
bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state);
bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state);
int clock = intel_c20pll_calc_port_clock(encoder, mpll_sw_state);
int i;
- I915_STATE_WARN(i915, mpll_hw_state->clock != clock,
- "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)",
- crtc->base.base.id, crtc->base.name,
- mpll_sw_state->clock, mpll_hw_state->clock);
+ INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->clock != clock,
+ "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)",
+ crtc->base.base.id, crtc->base.name,
+ mpll_sw_state->clock, mpll_hw_state->clock);
- I915_STATE_WARN(i915, sw_use_mpllb != hw_use_mpllb,
- "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection (expected %d, found %d)",
- crtc->base.base.id, crtc->base.name,
- sw_use_mpllb, hw_use_mpllb);
+ INTEL_DISPLAY_STATE_WARN(display, sw_use_mpllb != hw_use_mpllb,
+ "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection (expected %d, found %d)",
+ crtc->base.base.id, crtc->base.name,
+ sw_use_mpllb, hw_use_mpllb);
if (hw_use_mpllb) {
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) {
- I915_STATE_WARN(i915, mpll_hw_state->mpllb[i] != mpll_sw_state->mpllb[i],
- "[CRTC:%d:%s] mismatch in C20MPLLB: Register[%d] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->mpllb[i], mpll_hw_state->mpllb[i]);
+ INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mpllb[i] != mpll_sw_state->mpllb[i],
+ "[CRTC:%d:%s] mismatch in C20MPLLB: Register[%d] (expected 0x%04x, found 0x%04x)",
+ crtc->base.base.id, crtc->base.name, i,
+ mpll_sw_state->mpllb[i], mpll_hw_state->mpllb[i]);
}
} else {
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
- I915_STATE_WARN(i915, mpll_hw_state->mplla[i] != mpll_sw_state->mplla[i],
- "[CRTC:%d:%s] mismatch in C20MPLLA: Register[%d] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->mplla[i], mpll_hw_state->mplla[i]);
+ INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mplla[i] != mpll_sw_state->mplla[i],
+ "[CRTC:%d:%s] mismatch in C20MPLLA: Register[%d] (expected 0x%04x, found 0x%04x)",
+ crtc->base.base.id, crtc->base.name, i,
+ mpll_sw_state->mplla[i], mpll_hw_state->mplla[i]);
}
}
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) {
- I915_STATE_WARN(i915, mpll_hw_state->tx[i] != mpll_sw_state->tx[i],
- "[CRTC:%d:%s] mismatch in C20: Register TX[%i] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->tx[i], mpll_hw_state->tx[i]);
+ INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->tx[i] != mpll_sw_state->tx[i],
+ "[CRTC:%d:%s] mismatch in C20: Register TX[%i] (expected 0x%04x, found 0x%04x)",
+ crtc->base.base.id, crtc->base.name, i,
+ mpll_sw_state->tx[i], mpll_hw_state->tx[i]);
}
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->cmn); i++) {
- I915_STATE_WARN(i915, mpll_hw_state->cmn[i] != mpll_sw_state->cmn[i],
- "[CRTC:%d:%s] mismatch in C20: Register CMN[%i] (expected 0x%04x, found 0x%04x)",
- crtc->base.base.id, crtc->base.name, i,
- mpll_sw_state->cmn[i], mpll_hw_state->cmn[i]);
+ INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->cmn[i] != mpll_sw_state->cmn[i],
+ "[CRTC:%d:%s] mismatch in C20: Register CMN[%i] (expected 0x%04x, found 0x%04x)",
+ crtc->base.base.id, crtc->base.name, i,
+ mpll_sw_state->cmn[i], mpll_hw_state->cmn[i]);
}
}
void intel_cx0pll_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_encoder *encoder;
struct intel_cx0pll_state mpll_hw_state = {};
- if (DISPLAY_VER(i915) < 14)
+ if (DISPLAY_VER(display) < 14)
return;
if (!new_crtc_state->hw.active)
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 9004b99bb51f..711168882684 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -7,17 +7,15 @@
#define __INTEL_CX0_PHY_H__
#include <linux/types.h>
-#include <linux/bitfield.h>
-#include <linux/bits.h>
enum icl_port_dpll_id;
-struct drm_i915_private;
struct intel_atomic_state;
struct intel_c10pll_state;
struct intel_c20pll_state;
-struct intel_cx0pll_state;
struct intel_crtc;
struct intel_crtc_state;
+struct intel_cx0pll_state;
+struct intel_display;
struct intel_encoder;
struct intel_hdmi;
@@ -35,7 +33,7 @@ void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder,
const struct intel_cx0pll_state *pll_state);
-void intel_cx0pll_dump_hw_state(struct drm_i915_private *dev_priv,
+void intel_cx0pll_dump_hw_state(struct intel_display *display,
const struct intel_cx0pll_state *hw_state);
void intel_cx0pll_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index ab3ae110b68f..f0e5c196eae4 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -273,13 +273,15 @@
#define _XE2HPD_C20_A_MPLLB_CFG 0xCCC2
#define _XE2HPD_C20_B_MPLLB_CFG 0xCCB6
-#define _IS_XE2HPD_C20(i915) (DISPLAY_VER_FULL(i915) == IP_VER(14, 1))
+#define _IS_XE2HPD_C20(i915) (DISPLAY_VERx100(i915) == 1401)
#define PHY_C20_A_TX_CNTX_CFG(i915, idx) \
((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_TX_CNTX_CFG : _MTL_C20_A_TX_CNTX_CFG) - (idx))
#define PHY_C20_B_TX_CNTX_CFG(i915, idx) \
((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_B_TX_CNTX_CFG : _MTL_C20_B_TX_CNTX_CFG) - (idx))
#define C20_PHY_TX_RATE REG_GENMASK(2, 0)
+#define C20_PHY_TX_MISC_MASK REG_GENMASK16(7, 0)
+#define C20_PHY_TX_MISC(val) REG_FIELD_PREP16(C20_PHY_TX_MISC_MASK, (val))
#define PHY_C20_A_CMN_CNTX_CFG(i915, idx) \
((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_CMN_CNTX_CFG : _MTL_C20_A_CMN_CNTX_CFG) - (idx))
@@ -363,4 +365,7 @@
#define HDMI_DIV_MASK REG_GENMASK16(2, 0)
#define HDMI_DIV(val) REG_FIELD_PREP16(HDMI_DIV_MASK, val)
+#define PICA_PHY_CONFIG_CONTROL _MMIO(0x16FE68)
+#define EDP_ON_TYPEC REG_BIT(31)
+
#endif /* __INTEL_CX0_REG_DEFS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index fe1ded6707f9..49b5cc01ce40 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2236,7 +2236,7 @@ static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION,
enable ? DP_FEC_READY : 0) <= 0)
drm_dbg_kms(display->drm, "Failed to set FEC_READY to %s in the sink\n",
- enable ? "enabled" : "disabled");
+ str_enabled_disabled(enable));
if (enable &&
drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_STATUS,
@@ -2256,9 +2256,9 @@ static int read_fec_detected_status(struct drm_dp_aux *aux)
return status;
}
-static void wait_for_fec_detected(struct drm_dp_aux *aux, bool enabled)
+static int wait_for_fec_detected(struct drm_dp_aux *aux, bool enabled)
{
- struct drm_i915_private *i915 = to_i915(aux->drm_dev);
+ struct intel_display *display = to_intel_display(aux->drm_dev);
int mask = enabled ? DP_FEC_DECODE_EN_DETECTED : DP_FEC_DECODE_DIS_DETECTED;
int status;
int err;
@@ -2267,57 +2267,92 @@ static void wait_for_fec_detected(struct drm_dp_aux *aux, bool enabled)
status & mask || status < 0,
10000, 200000);
- if (!err && status >= 0)
- return;
+ if (err || status < 0) {
+ drm_dbg_kms(display->drm,
+ "Failed waiting for FEC %s to get detected: %d (status %d)\n",
+ str_enabled_disabled(enabled), err, status);
+ return err ? err : status;
+ }
- if (err == -ETIMEDOUT)
- drm_dbg_kms(&i915->drm, "Timeout waiting for FEC %s to get detected\n",
- str_enabled_disabled(enabled));
- else
- drm_dbg_kms(&i915->drm, "FEC detected status read error: %d\n", status);
+ return 0;
}
-void intel_ddi_wait_for_fec_status(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- bool enabled)
+int intel_ddi_wait_for_fec_status(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ bool enabled)
{
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
int ret;
if (!crtc_state->fec_enable)
- return;
+ return 0;
if (enabled)
- ret = intel_de_wait_for_set(i915, dp_tp_status_reg(encoder, crtc_state),
+ ret = intel_de_wait_for_set(display, dp_tp_status_reg(encoder, crtc_state),
DP_TP_STATUS_FEC_ENABLE_LIVE, 1);
else
- ret = intel_de_wait_for_clear(i915, dp_tp_status_reg(encoder, crtc_state),
+ ret = intel_de_wait_for_clear(display, dp_tp_status_reg(encoder, crtc_state),
DP_TP_STATUS_FEC_ENABLE_LIVE, 1);
- if (ret)
- drm_err(&i915->drm,
+ if (ret) {
+ drm_err(display->drm,
"Timeout waiting for FEC live state to get %s\n",
str_enabled_disabled(enabled));
-
+ return ret;
+ }
/*
* At least the Synoptics MST hub doesn't set the detected flag for
* FEC decoding disabling so skip waiting for that.
*/
- if (enabled)
- wait_for_fec_detected(&intel_dp->aux, enabled);
+ if (enabled) {
+ ret = wait_for_fec_detected(&intel_dp->aux, enabled);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static void intel_ddi_enable_fec(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
+ int i;
+ int ret;
if (!crtc_state->fec_enable)
return;
- intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
+ intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
0, DP_TP_CTL_FEC_ENABLE);
+
+ if (DISPLAY_VER(display) < 30)
+ return;
+
+ ret = intel_ddi_wait_for_fec_status(encoder, crtc_state, true);
+ if (!ret)
+ return;
+
+ for (i = 0; i < 3; i++) {
+ drm_dbg_kms(display->drm, "Retry FEC enabling\n");
+
+ intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
+ DP_TP_CTL_FEC_ENABLE, 0);
+
+ ret = intel_ddi_wait_for_fec_status(encoder, crtc_state, false);
+ if (ret)
+ continue;
+
+ intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
+ 0, DP_TP_CTL_FEC_ENABLE);
+
+ ret = intel_ddi_wait_for_fec_status(encoder, crtc_state, true);
+ if (!ret)
+ return;
+ }
+
+ drm_err(display->drm, "Failed to enable FEC after retries\n");
}
static void intel_ddi_disable_fec(struct intel_encoder *encoder,
@@ -3478,6 +3513,13 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
drm_connector_update_privacy_screen(conn_state);
}
+static void intel_ddi_update_pipe_hdmi(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ intel_hdmi_fastset_infoframes(encoder, crtc_state, conn_state);
+}
+
void intel_ddi_update_pipe(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
@@ -3489,6 +3531,10 @@ void intel_ddi_update_pipe(struct intel_atomic_state *state,
intel_ddi_update_pipe_dp(state, encoder, crtc_state,
conn_state);
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ intel_ddi_update_pipe_hdmi(encoder, crtc_state,
+ conn_state);
+
intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state);
}
@@ -4392,6 +4438,7 @@ static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
intel_dp->reset_link_params = true;
+ intel_dp_invalidate_source_oui(intel_dp);
intel_pps_encoder_reset(intel_dp);
@@ -4885,7 +4932,7 @@ void intel_ddi_init(struct intel_display *display,
if (!assert_has_icl_dsi(dev_priv))
return;
- icl_dsi_init(dev_priv, devdata);
+ icl_dsi_init(display, devdata);
return;
}
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h
index 6d85422bdefe..640851d46b1b 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.h
+++ b/drivers/gpu/drm/i915/display/intel_ddi.h
@@ -63,9 +63,9 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
void intel_ddi_enable_transcoder_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_disable_transcoder_clock(const struct intel_crtc_state *crtc_state);
-void intel_ddi_wait_for_fec_status(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
- bool enabled);
+int intel_ddi_wait_for_fec_status(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ bool enabled);
void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h
index e017cd4a8168..bb51f974e9e2 100644
--- a/drivers/gpu/drm/i915/display/intel_de.h
+++ b/drivers/gpu/drm/i915/display/intel_de.h
@@ -32,7 +32,7 @@ __intel_de_read(struct intel_display *display, i915_reg_t reg)
#define intel_de_read(p,...) __intel_de_read(__to_intel_display(p), __VA_ARGS__)
static inline u8
-__intel_de_read8(struct intel_display *display, i915_reg_t reg)
+intel_de_read8(struct intel_display *display, i915_reg_t reg)
{
u8 val;
@@ -44,11 +44,10 @@ __intel_de_read8(struct intel_display *display, i915_reg_t reg)
return val;
}
-#define intel_de_read8(p,...) __intel_de_read8(__to_intel_display(p), __VA_ARGS__)
static inline u64
-__intel_de_read64_2x32(struct intel_display *display,
- i915_reg_t lower_reg, i915_reg_t upper_reg)
+intel_de_read64_2x32(struct intel_display *display,
+ i915_reg_t lower_reg, i915_reg_t upper_reg)
{
u64 val;
@@ -63,7 +62,6 @@ __intel_de_read64_2x32(struct intel_display *display,
return val;
}
-#define intel_de_read64_2x32(p,...) __intel_de_read64_2x32(__to_intel_display(p), __VA_ARGS__)
static inline void
__intel_de_posting_read(struct intel_display *display, i915_reg_t reg)
@@ -88,12 +86,11 @@ __intel_de_write(struct intel_display *display, i915_reg_t reg, u32 val)
#define intel_de_write(p,...) __intel_de_write(__to_intel_display(p), __VA_ARGS__)
static inline u32
-____intel_de_rmw_nowl(struct intel_display *display, i915_reg_t reg,
- u32 clear, u32 set)
+__intel_de_rmw_nowl(struct intel_display *display, i915_reg_t reg,
+ u32 clear, u32 set)
{
return intel_uncore_rmw(__to_uncore(display), reg, clear, set);
}
-#define __intel_de_rmw_nowl(p,...) ____intel_de_rmw_nowl(__to_intel_display(p), __VA_ARGS__)
static inline u32
__intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear,
@@ -112,18 +109,17 @@ __intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear,
#define intel_de_rmw(p,...) __intel_de_rmw(__to_intel_display(p), __VA_ARGS__)
static inline int
-____intel_de_wait_for_register_nowl(struct intel_display *display,
- i915_reg_t reg,
- u32 mask, u32 value, unsigned int timeout)
+__intel_de_wait_for_register_nowl(struct intel_display *display,
+ i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout)
{
return intel_wait_for_register(__to_uncore(display), reg, mask,
value, timeout);
}
-#define __intel_de_wait_for_register_nowl(p,...) ____intel_de_wait_for_register_nowl(__to_intel_display(p), __VA_ARGS__)
static inline int
-__intel_de_wait(struct intel_display *display, i915_reg_t reg,
- u32 mask, u32 value, unsigned int timeout)
+intel_de_wait(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout)
{
int ret;
@@ -136,11 +132,10 @@ __intel_de_wait(struct intel_display *display, i915_reg_t reg,
return ret;
}
-#define intel_de_wait(p,...) __intel_de_wait(__to_intel_display(p), __VA_ARGS__)
static inline int
-__intel_de_wait_fw(struct intel_display *display, i915_reg_t reg,
- u32 mask, u32 value, unsigned int timeout)
+intel_de_wait_fw(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value, unsigned int timeout)
{
int ret;
@@ -153,13 +148,12 @@ __intel_de_wait_fw(struct intel_display *display, i915_reg_t reg,
return ret;
}
-#define intel_de_wait_fw(p,...) __intel_de_wait_fw(__to_intel_display(p), __VA_ARGS__)
static inline int
-__intel_de_wait_custom(struct intel_display *display, i915_reg_t reg,
- u32 mask, u32 value,
- unsigned int fast_timeout_us,
- unsigned int slow_timeout_ms, u32 *out_value)
+intel_de_wait_custom(struct intel_display *display, i915_reg_t reg,
+ u32 mask, u32 value,
+ unsigned int fast_timeout_us,
+ unsigned int slow_timeout_ms, u32 *out_value)
{
int ret;
@@ -173,7 +167,6 @@ __intel_de_wait_custom(struct intel_display *display, i915_reg_t reg,
return ret;
}
-#define intel_de_wait_custom(p,...) __intel_de_wait_custom(__to_intel_display(p), __VA_ARGS__)
static inline int
__intel_de_wait_for_set(struct intel_display *display, i915_reg_t reg,
@@ -220,19 +213,16 @@ __intel_de_write_fw(struct intel_display *display, i915_reg_t reg, u32 val)
#define intel_de_write_fw(p,...) __intel_de_write_fw(__to_intel_display(p), __VA_ARGS__)
static inline u32
-__intel_de_read_notrace(struct intel_display *display, i915_reg_t reg)
+intel_de_read_notrace(struct intel_display *display, i915_reg_t reg)
{
return intel_uncore_read_notrace(__to_uncore(display), reg);
}
-#define intel_de_read_notrace(p,...) __intel_de_read_notrace(__to_intel_display(p), __VA_ARGS__)
static inline void
-__intel_de_write_notrace(struct intel_display *display, i915_reg_t reg,
- u32 val)
+intel_de_write_notrace(struct intel_display *display, i915_reg_t reg, u32 val)
{
intel_uncore_write_notrace(__to_uncore(display), reg, val);
}
-#define intel_de_write_notrace(p,...) __intel_de_write_notrace(__to_intel_display(p), __VA_ARGS__)
static __always_inline void
intel_de_write_dsb(struct intel_display *display, struct intel_dsb *dsb,
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index e1f6255e918b..863927f429aa 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -422,6 +422,7 @@ intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state)
void assert_transcoder(struct drm_i915_private *dev_priv,
enum transcoder cpu_transcoder, bool state)
{
+ struct intel_display *display = &dev_priv->display;
bool cur_state;
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
@@ -442,24 +443,24 @@ void assert_transcoder(struct drm_i915_private *dev_priv,
cur_state = false;
}
- I915_STATE_WARN(dev_priv, cur_state != state,
- "transcoder %s assertion failure (expected %s, current %s)\n",
- transcoder_name(cpu_transcoder), str_on_off(state),
- str_on_off(cur_state));
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "transcoder %s assertion failure (expected %s, current %s)\n",
+ transcoder_name(cpu_transcoder), str_on_off(state),
+ str_on_off(cur_state));
}
static void assert_plane(struct intel_plane *plane, bool state)
{
- struct drm_i915_private *i915 = to_i915(plane->base.dev);
+ struct intel_display *display = to_intel_display(plane->base.dev);
enum pipe pipe;
bool cur_state;
cur_state = plane->get_hw_state(plane, &pipe);
- I915_STATE_WARN(i915, cur_state != state,
- "%s assertion failure (expected %s, current %s)\n",
- plane->base.name, str_on_off(state),
- str_on_off(cur_state));
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "%s assertion failure (expected %s, current %s)\n",
+ plane->base.name, str_on_off(state),
+ str_on_off(cur_state));
}
#define assert_plane_enabled(p) assert_plane(p, true)
@@ -474,7 +475,7 @@ static void assert_planes_disabled(struct intel_crtc *crtc)
assert_plane_disabled(plane);
}
-void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+void vlv_wait_port_ready(struct intel_display *display,
struct intel_digital_port *dig_port,
unsigned int expected_mask)
{
@@ -487,11 +488,11 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
fallthrough;
case PORT_B:
port_mask = DPLL_PORTB_READY_MASK;
- dpll_reg = DPLL(dev_priv, 0);
+ dpll_reg = DPLL(display, 0);
break;
case PORT_C:
port_mask = DPLL_PORTC_READY_MASK;
- dpll_reg = DPLL(dev_priv, 0);
+ dpll_reg = DPLL(display, 0);
expected_mask <<= 4;
break;
case PORT_D:
@@ -500,11 +501,11 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
break;
}
- if (intel_de_wait(dev_priv, dpll_reg, port_mask, expected_mask, 1000))
- drm_WARN(&dev_priv->drm, 1,
+ if (intel_de_wait(display, dpll_reg, port_mask, expected_mask, 1000))
+ drm_WARN(display->drm, 1,
"timed out waiting for [ENCODER:%d:%s] port ready: got 0x%x, expected 0x%x\n",
dig_port->base.base.base.id, dig_port->base.base.name,
- intel_de_read(dev_priv, dpll_reg) & port_mask,
+ intel_de_read(display, dpll_reg) & port_mask,
expected_mask);
}
@@ -861,7 +862,7 @@ static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
*/
if (IS_DG2(dev_priv))
tmp &= ~UNDERRUN_RECOVERY_ENABLE_DG2;
- else if (DISPLAY_VER(dev_priv) >= 13)
+ else if ((DISPLAY_VER(dev_priv) >= 13) && (DISPLAY_VER(dev_priv) < 30))
tmp |= UNDERRUN_RECOVERY_DISABLE_ADLP;
/* Wa_14010547955:dg2 */
@@ -2609,13 +2610,29 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state)
return 0;
}
+static bool intel_crtc_needs_wa_14015401596(struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+
+ return intel_vrr_possible(crtc_state) && crtc_state->has_psr &&
+ adjusted_mode->crtc_vblank_start == adjusted_mode->crtc_vdisplay &&
+ IS_DISPLAY_VER(display, 13, 14);
+}
+
static int intel_crtc_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
+ struct drm_display_mode *adjusted_mode =
+ &crtc_state->hw.adjusted_mode;
int ret;
+ /* Wa_14015401596 */
+ if (intel_crtc_needs_wa_14015401596(crtc_state))
+ adjusted_mode->crtc_vblank_start += 1;
+
ret = intel_dpll_crtc_compute_clock(state, crtc);
if (ret)
return ret;
@@ -5050,6 +5067,8 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
struct drm_connector *connector;
int i;
+ intel_vrr_compute_config_late(crtc_state);
+
for_each_new_connector_in_state(&state->base, connector,
conn_state, i) {
struct intel_encoder *encoder =
@@ -5287,15 +5306,15 @@ pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset,
const struct intel_cx0pll_state *a,
const struct intel_cx0pll_state *b)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_display *display = to_intel_display(crtc);
char *chipname = a->use_c10 ? "C10" : "C20";
pipe_config_mismatch(p, fastset, crtc, name, chipname);
drm_printf(p, "expected:\n");
- intel_cx0pll_dump_hw_state(i915, a);
+ intel_cx0pll_dump_hw_state(display, a);
drm_printf(p, "found:\n");
- intel_cx0pll_dump_hw_state(i915, b);
+ intel_cx0pll_dump_hw_state(display, b);
}
bool
@@ -5683,7 +5702,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_INFOFRAME(avi);
PIPE_CONF_CHECK_INFOFRAME(spd);
PIPE_CONF_CHECK_INFOFRAME(hdmi);
- PIPE_CONF_CHECK_INFOFRAME(drm);
+ if (!fastset)
+ PIPE_CONF_CHECK_INFOFRAME(drm);
PIPE_CONF_CHECK_DP_VSC_SDP(vsc);
PIPE_CONF_CHECK_DP_AS_SDP(as_sdp);
@@ -8129,7 +8149,7 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
if (HAS_DDI(dev_priv)) {
if (intel_ddi_crt_present(dev_priv))
- intel_crt_init(dev_priv);
+ intel_crt_init(display);
intel_bios_for_each_encoder(display, intel_ddi_init);
@@ -8144,7 +8164,7 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
* incorrect sharing of the PPS.
*/
intel_lvds_init(dev_priv);
- intel_crt_init(dev_priv);
+ intel_crt_init(display);
dpd_is_edp = intel_dp_is_port_edp(dev_priv, PORT_D);
@@ -8175,7 +8195,7 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
bool has_edp, has_port;
if (IS_VALLEYVIEW(dev_priv) && dev_priv->display.vbt.int_crt_support)
- intel_crt_init(dev_priv);
+ intel_crt_init(display);
/*
* The DP_DETECTED bit is the latched state of the DDC
@@ -8221,14 +8241,14 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
vlv_dsi_init(dev_priv);
} else if (IS_PINEVIEW(dev_priv)) {
intel_lvds_init(dev_priv);
- intel_crt_init(dev_priv);
+ intel_crt_init(display);
} else if (IS_DISPLAY_VER(dev_priv, 3, 4)) {
bool found = false;
if (IS_MOBILE(dev_priv))
intel_lvds_init(dev_priv);
- intel_crt_init(dev_priv);
+ intel_crt_init(display);
if (intel_de_read(dev_priv, GEN3_SDVOB) & SDVO_DETECTED) {
drm_dbg_kms(&dev_priv->drm, "probing SDVOB\n");
@@ -8270,7 +8290,7 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
if (IS_I85X(dev_priv))
intel_lvds_init(dev_priv);
- intel_crt_init(dev_priv);
+ intel_crt_init(display);
intel_dvo_init(dev_priv);
}
@@ -8432,7 +8452,10 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
* plane so let's not advertize modes that are
* too big for that.
*/
- if (DISPLAY_VER(dev_priv) >= 11) {
+ if (DISPLAY_VER(dev_priv) >= 30) {
+ plane_width_max = 6144 * num_joined_pipes;
+ plane_height_max = 4800;
+ } else if (DISPLAY_VER(dev_priv) >= 11) {
plane_width_max = 5120 * num_joined_pipes;
plane_height_max = 4320;
} else {
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 61e1df878de9..caef04f655c5 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -492,7 +492,7 @@ bool intel_encoder_is_tc(struct intel_encoder *encoder);
enum tc_port intel_encoder_to_tc(struct intel_encoder *encoder);
int ilk_get_lanes_required(int target_clock, int link_bw, int bpp);
-void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+void vlv_wait_port_ready(struct intel_display *display,
struct intel_digital_port *dig_port,
unsigned int expected_mask);
@@ -585,18 +585,17 @@ void assert_transcoder(struct drm_i915_private *dev_priv,
bool assert_port_valid(struct drm_i915_private *i915, enum port port);
/*
- * Use I915_STATE_WARN(x) (rather than WARN() and WARN_ON()) for hw state sanity
- * checks to check for unexpected conditions which may not necessarily be a user
- * visible problem. This will either WARN() or DRM_ERROR() depending on the
- * verbose_state_checks module param, to enable distros and users to tailor
- * their preferred amount of i915 abrt spam.
+ * Use INTEL_DISPLAY_STATE_WARN(x) (rather than WARN() and WARN_ON()) for hw
+ * state sanity checks to check for unexpected conditions which may not
+ * necessarily be a user visible problem. This will either drm_WARN() or
+ * drm_err() depending on the verbose_state_checks module param, to enable
+ * distros and users to tailor their preferred amount of i915 abrt spam.
*/
-#define I915_STATE_WARN(__i915, condition, format...) ({ \
- struct drm_device *drm = &(__i915)->drm; \
+#define INTEL_DISPLAY_STATE_WARN(__display, condition, format...) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
- if (!drm_WARN(drm, __i915->display.params.verbose_state_checks, format)) \
- drm_err(drm, format); \
+ if (!drm_WARN((__display)->drm, (__display)->params.verbose_state_checks, format)) \
+ drm_err((__display)->drm, format); \
unlikely(__ret_warn_on); \
})
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index 982dd9469195..45b7c6900adc 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -284,6 +284,9 @@ struct intel_display {
/* drm device backpointer */
struct drm_device *drm;
+ /* Platform (and subplatform, if any) identification */
+ struct intel_display_platforms platform;
+
/* Display functions */
struct {
/* Top level crtc-ish functions */
@@ -455,6 +458,8 @@ struct intel_display {
/* For i915gm/i945gm vblank irq workaround */
u8 vblank_enabled;
+ int vblank_wa_num_pipes;
+
struct work_struct vblank_dc_work;
u32 de_irq_mask[I915_MAX_PIPES];
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c
index f33062322c66..5f98e1b2a401 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.c
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -3,12 +3,13 @@
* Copyright © 2023 Intel Corporation
*/
-#include <drm/intel/i915_pciids.h>
+#include <drm/intel/pciids.h>
#include <drm/drm_color_mgmt.h>
#include <linux/pci.h>
#include "i915_drv.h"
#include "i915_reg.h"
+#include "intel_cx0_phy_regs.h"
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_device.h"
@@ -31,14 +32,25 @@ struct stepping_desc {
.step_info.size = ARRAY_SIZE(_map)
struct subplatform_desc {
- enum intel_display_subplatform subplatform;
+ struct intel_display_platforms platforms;
const char *name;
const u16 *pciidlist;
struct stepping_desc step_info;
};
+#define SUBPLATFORM(_platform, _subplatform) \
+ .platforms._platform##_##_subplatform = 1, \
+ .name = #_subplatform
+
+/*
+ * Group subplatform alias that matches multiple subplatforms. For making ult
+ * cover both ult and ulx on HSW/BDW.
+ */
+#define SUBPLATFORM_GROUP(_platform, _subplatform) \
+ .platforms._platform##_##_subplatform = 1
+
struct platform_desc {
- enum intel_display_platform platform;
+ struct intel_display_platforms platforms;
const char *name;
const struct subplatform_desc *subplatforms;
const struct intel_display_device_info *info; /* NULL for GMD ID */
@@ -46,9 +58,16 @@ struct platform_desc {
};
#define PLATFORM(_platform) \
- .platform = (INTEL_DISPLAY_##_platform), \
+ .platforms._platform = 1, \
.name = #_platform
+/*
+ * Group platform alias that matches multiple platforms. For aliases such as g4x
+ * that covers both g45 and gm45.
+ */
+#define PLATFORM_GROUP(_platform) \
+ .platforms._platform = 1
+
#define ID(id) (id)
static const struct intel_display_device_info no_display = {};
@@ -232,7 +251,7 @@ static const struct intel_display_device_info no_display = {};
.__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A)
static const struct platform_desc i830_desc = {
- PLATFORM(I830),
+ PLATFORM(i830),
.info = &(const struct intel_display_device_info) {
I830_DISPLAY,
@@ -241,7 +260,7 @@ static const struct platform_desc i830_desc = {
};
static const struct platform_desc i845_desc = {
- PLATFORM(I845G),
+ PLATFORM(i845g),
.info = &(const struct intel_display_device_info) {
I845_DISPLAY,
@@ -250,7 +269,7 @@ static const struct platform_desc i845_desc = {
};
static const struct platform_desc i85x_desc = {
- PLATFORM(I85X),
+ PLATFORM(i85x),
.info = &(const struct intel_display_device_info) {
I830_DISPLAY,
@@ -260,7 +279,7 @@ static const struct platform_desc i85x_desc = {
};
static const struct platform_desc i865g_desc = {
- PLATFORM(I865G),
+ PLATFORM(i865g),
.info = &(const struct intel_display_device_info) {
I845_DISPLAY,
@@ -282,7 +301,7 @@ static const struct platform_desc i865g_desc = {
.__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) /* SDVO B/C */
static const struct platform_desc i915g_desc = {
- PLATFORM(I915G),
+ PLATFORM(i915g),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I845_COLORS,
@@ -292,7 +311,7 @@ static const struct platform_desc i915g_desc = {
};
static const struct platform_desc i915gm_desc = {
- PLATFORM(I915GM),
+ PLATFORM(i915gm),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
@@ -305,7 +324,7 @@ static const struct platform_desc i915gm_desc = {
};
static const struct platform_desc i945g_desc = {
- PLATFORM(I945G),
+ PLATFORM(i945g),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I845_COLORS,
@@ -316,7 +335,7 @@ static const struct platform_desc i945g_desc = {
};
static const struct platform_desc i945gm_desc = {
- PLATFORM(I915GM),
+ PLATFORM(i915gm),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
@@ -330,7 +349,7 @@ static const struct platform_desc i945gm_desc = {
};
static const struct platform_desc g33_desc = {
- PLATFORM(G33),
+ PLATFORM(g33),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I845_COLORS,
@@ -339,7 +358,7 @@ static const struct platform_desc g33_desc = {
};
static const struct platform_desc pnv_desc = {
- PLATFORM(PINEVIEW),
+ PLATFORM(pineview),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
@@ -360,7 +379,7 @@ static const struct platform_desc pnv_desc = {
BIT(TRANSCODER_A) | BIT(TRANSCODER_B)
static const struct platform_desc i965g_desc = {
- PLATFORM(I965G),
+ PLATFORM(i965g),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
.has_overlay = 1,
@@ -370,7 +389,7 @@ static const struct platform_desc i965g_desc = {
};
static const struct platform_desc i965gm_desc = {
- PLATFORM(I965GM),
+ PLATFORM(i965gm),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
.has_overlay = 1,
@@ -382,7 +401,8 @@ static const struct platform_desc i965gm_desc = {
};
static const struct platform_desc g45_desc = {
- PLATFORM(G45),
+ PLATFORM(g45),
+ PLATFORM_GROUP(g4x),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
@@ -391,7 +411,8 @@ static const struct platform_desc g45_desc = {
};
static const struct platform_desc gm45_desc = {
- PLATFORM(GM45),
+ PLATFORM(gm45),
+ PLATFORM_GROUP(g4x),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
.supports_tv = 1,
@@ -414,14 +435,14 @@ static const struct platform_desc gm45_desc = {
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
static const struct platform_desc ilk_d_desc = {
- PLATFORM(IRONLAKE),
+ PLATFORM(ironlake),
.info = &(const struct intel_display_device_info) {
ILK_DISPLAY,
},
};
static const struct platform_desc ilk_m_desc = {
- PLATFORM(IRONLAKE),
+ PLATFORM(ironlake),
.info = &(const struct intel_display_device_info) {
ILK_DISPLAY,
@@ -430,7 +451,7 @@ static const struct platform_desc ilk_m_desc = {
};
static const struct platform_desc snb_desc = {
- PLATFORM(SANDYBRIDGE),
+ PLATFORM(sandybridge),
.info = &(const struct intel_display_device_info) {
.has_hotplug = 1,
I9XX_PIPE_OFFSETS,
@@ -447,7 +468,7 @@ static const struct platform_desc snb_desc = {
};
static const struct platform_desc ivb_desc = {
- PLATFORM(IVYBRIDGE),
+ PLATFORM(ivybridge),
.info = &(const struct intel_display_device_info) {
.has_hotplug = 1,
IVB_PIPE_OFFSETS,
@@ -464,7 +485,7 @@ static const struct platform_desc ivb_desc = {
};
static const struct platform_desc vlv_desc = {
- PLATFORM(VALLEYVIEW),
+ PLATFORM(valleyview),
.info = &(const struct intel_display_device_info) {
.has_gmch = 1,
.has_hotplug = 1,
@@ -495,10 +516,19 @@ static const u16 hsw_ulx_ids[] = {
};
static const struct platform_desc hsw_desc = {
- PLATFORM(HASWELL),
+ PLATFORM(haswell),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_HASWELL_ULT, "ULT", hsw_ult_ids },
- { INTEL_DISPLAY_HASWELL_ULX, "ULX", hsw_ulx_ids },
+ /* Special case: Use ult both as group and subplatform. */
+ {
+ SUBPLATFORM(haswell, ult),
+ SUBPLATFORM_GROUP(haswell, ult),
+ .pciidlist = hsw_ult_ids,
+ },
+ {
+ SUBPLATFORM(haswell, ulx),
+ SUBPLATFORM_GROUP(haswell, ult),
+ .pciidlist = hsw_ulx_ids,
+ },
{},
},
.info = &(const struct intel_display_device_info) {
@@ -539,10 +569,19 @@ static const u16 bdw_ulx_ids[] = {
};
static const struct platform_desc bdw_desc = {
- PLATFORM(BROADWELL),
+ PLATFORM(broadwell),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_BROADWELL_ULT, "ULT", bdw_ult_ids },
- { INTEL_DISPLAY_BROADWELL_ULX, "ULX", bdw_ulx_ids },
+ /* Special case: Use ult both as group and subplatform. */
+ {
+ SUBPLATFORM(broadwell, ult),
+ SUBPLATFORM_GROUP(broadwell, ult),
+ .pciidlist = bdw_ult_ids,
+ },
+ {
+ SUBPLATFORM(broadwell, ulx),
+ SUBPLATFORM_GROUP(broadwell, ult),
+ .pciidlist = bdw_ulx_ids,
+ },
{},
},
.info = &(const struct intel_display_device_info) {
@@ -567,7 +606,7 @@ static const struct platform_desc bdw_desc = {
};
static const struct platform_desc chv_desc = {
- PLATFORM(CHERRYVIEW),
+ PLATFORM(cherryview),
.info = &(const struct intel_display_device_info) {
.has_hotplug = 1,
.has_gmch = 1,
@@ -630,10 +669,16 @@ static const enum intel_step skl_steppings[] = {
};
static const struct platform_desc skl_desc = {
- PLATFORM(SKYLAKE),
+ PLATFORM(skylake),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_SKYLAKE_ULT, "ULT", skl_ult_ids },
- { INTEL_DISPLAY_SKYLAKE_ULX, "ULX", skl_ulx_ids },
+ {
+ SUBPLATFORM(skylake, ult),
+ .pciidlist = skl_ult_ids,
+ },
+ {
+ SUBPLATFORM(skylake, ulx),
+ .pciidlist = skl_ulx_ids,
+ },
{},
},
.info = &skl_display,
@@ -665,10 +710,16 @@ static const enum intel_step kbl_steppings[] = {
};
static const struct platform_desc kbl_desc = {
- PLATFORM(KABYLAKE),
+ PLATFORM(kabylake),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_KABYLAKE_ULT, "ULT", kbl_ult_ids },
- { INTEL_DISPLAY_KABYLAKE_ULX, "ULX", kbl_ulx_ids },
+ {
+ SUBPLATFORM(kabylake, ult),
+ .pciidlist = kbl_ult_ids,
+ },
+ {
+ SUBPLATFORM(kabylake, ulx),
+ .pciidlist = kbl_ulx_ids,
+ },
{},
},
.info = &skl_display,
@@ -690,10 +741,16 @@ static const u16 cfl_ulx_ids[] = {
};
static const struct platform_desc cfl_desc = {
- PLATFORM(COFFEELAKE),
+ PLATFORM(coffeelake),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_COFFEELAKE_ULT, "ULT", cfl_ult_ids },
- { INTEL_DISPLAY_COFFEELAKE_ULX, "ULX", cfl_ulx_ids },
+ {
+ SUBPLATFORM(coffeelake, ult),
+ .pciidlist = cfl_ult_ids,
+ },
+ {
+ SUBPLATFORM(coffeelake, ulx),
+ .pciidlist = cfl_ulx_ids,
+ },
{},
},
.info = &skl_display,
@@ -706,9 +763,12 @@ static const u16 cml_ult_ids[] = {
};
static const struct platform_desc cml_desc = {
- PLATFORM(COMETLAKE),
+ PLATFORM(cometlake),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_COMETLAKE_ULT, "ULT", cml_ult_ids },
+ {
+ SUBPLATFORM(cometlake, ult),
+ .pciidlist = cml_ult_ids,
+ },
{},
},
.info = &skl_display,
@@ -745,7 +805,7 @@ static const enum intel_step bxt_steppings[] = {
};
static const struct platform_desc bxt_desc = {
- PLATFORM(BROXTON),
+ PLATFORM(broxton),
.info = &(const struct intel_display_device_info) {
GEN9_LP_DISPLAY,
.dbuf.size = 512 - 4, /* 4 blocks for bypass path allocation */
@@ -760,7 +820,7 @@ static const enum intel_step glk_steppings[] = {
};
static const struct platform_desc glk_desc = {
- PLATFORM(GEMINILAKE),
+ PLATFORM(geminilake),
.info = &(const struct intel_display_device_info) {
GEN9_LP_DISPLAY,
.dbuf.size = 1024 - 4, /* 4 blocks for bypass path allocation */
@@ -822,9 +882,12 @@ static const enum intel_step icl_steppings[] = {
};
static const struct platform_desc icl_desc = {
- PLATFORM(ICELAKE),
+ PLATFORM(icelake),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_ICELAKE_PORT_F, "Port F", icl_port_f_ids },
+ {
+ SUBPLATFORM(icelake, port_f),
+ .pciidlist = icl_port_f_ids,
+ },
{},
},
.info = &(const struct intel_display_device_info) {
@@ -847,13 +910,13 @@ static const enum intel_step jsl_ehl_steppings[] = {
};
static const struct platform_desc jsl_desc = {
- PLATFORM(JASPERLAKE),
+ PLATFORM(jasperlake),
.info = &jsl_ehl_display,
STEP_INFO(jsl_ehl_steppings),
};
static const struct platform_desc ehl_desc = {
- PLATFORM(ELKHARTLAKE),
+ PLATFORM(elkhartlake),
.info = &jsl_ehl_display,
STEP_INFO(jsl_ehl_steppings),
};
@@ -919,10 +982,13 @@ static const enum intel_step tgl_uy_steppings[] = {
};
static const struct platform_desc tgl_desc = {
- PLATFORM(TIGERLAKE),
+ PLATFORM(tigerlake),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_TIGERLAKE_UY, "UY", tgl_uy_ids,
- STEP_INFO(tgl_uy_steppings) },
+ {
+ SUBPLATFORM(tigerlake, uy),
+ .pciidlist = tgl_uy_ids,
+ STEP_INFO(tgl_uy_steppings),
+ },
{},
},
.info = &(const struct intel_display_device_info) {
@@ -944,7 +1010,7 @@ static const enum intel_step dg1_steppings[] = {
};
static const struct platform_desc dg1_desc = {
- PLATFORM(DG1),
+ PLATFORM(dg1),
.info = &(const struct intel_display_device_info) {
XE_D_DISPLAY,
@@ -961,7 +1027,7 @@ static const enum intel_step rkl_steppings[] = {
};
static const struct platform_desc rkl_desc = {
- PLATFORM(ROCKETLAKE),
+ PLATFORM(rocketlake),
.info = &(const struct intel_display_device_info) {
XE_D_DISPLAY,
.abox_mask = BIT(0),
@@ -996,10 +1062,13 @@ static const enum intel_step adl_s_rpl_s_steppings[] = {
};
static const struct platform_desc adl_s_desc = {
- PLATFORM(ALDERLAKE_S),
+ PLATFORM(alderlake_s),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_ALDERLAKE_S_RAPTORLAKE_S, "RPL-S", adls_rpls_ids,
- STEP_INFO(adl_s_rpl_s_steppings) },
+ {
+ SUBPLATFORM(alderlake_s, raptorlake_s),
+ .pciidlist = adls_rpls_ids,
+ STEP_INFO(adl_s_rpl_s_steppings),
+ },
{},
},
.info = &(const struct intel_display_device_info) {
@@ -1100,14 +1169,23 @@ static const enum intel_step adl_p_rpl_pu_steppings[] = {
};
static const struct platform_desc adl_p_desc = {
- PLATFORM(ALDERLAKE_P),
+ PLATFORM(alderlake_p),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_ALDERLAKE_P_ALDERLAKE_N, "ADL-N", adlp_adln_ids,
- STEP_INFO(adl_p_adl_n_steppings) },
- { INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_P, "RPL-P", adlp_rplp_ids,
- STEP_INFO(adl_p_rpl_pu_steppings) },
- { INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_U, "RPL-U", adlp_rplu_ids,
- STEP_INFO(adl_p_rpl_pu_steppings) },
+ {
+ SUBPLATFORM(alderlake_p, alderlake_n),
+ .pciidlist = adlp_adln_ids,
+ STEP_INFO(adl_p_adl_n_steppings),
+ },
+ {
+ SUBPLATFORM(alderlake_p, raptorlake_p),
+ .pciidlist = adlp_rplp_ids,
+ STEP_INFO(adl_p_rpl_pu_steppings),
+ },
+ {
+ SUBPLATFORM(alderlake_p, raptorlake_u),
+ .pciidlist = adlp_rplu_ids,
+ STEP_INFO(adl_p_rpl_pu_steppings),
+ },
{},
},
.info = &xe_lpd_display,
@@ -1159,14 +1237,23 @@ static const enum intel_step dg2_g12_steppings[] = {
};
static const struct platform_desc dg2_desc = {
- PLATFORM(DG2),
+ PLATFORM(dg2),
.subplatforms = (const struct subplatform_desc[]) {
- { INTEL_DISPLAY_DG2_G10, "G10", dg2_g10_ids,
- STEP_INFO(dg2_g10_steppings) },
- { INTEL_DISPLAY_DG2_G11, "G11", dg2_g11_ids,
- STEP_INFO(dg2_g11_steppings) },
- { INTEL_DISPLAY_DG2_G12, "G12", dg2_g12_ids,
- STEP_INFO(dg2_g12_steppings) },
+ {
+ SUBPLATFORM(dg2, g10),
+ .pciidlist = dg2_g10_ids,
+ STEP_INFO(dg2_g10_steppings),
+ },
+ {
+ SUBPLATFORM(dg2, g11),
+ .pciidlist = dg2_g11_ids,
+ STEP_INFO(dg2_g11_steppings),
+ },
+ {
+ SUBPLATFORM(dg2, g12),
+ .pciidlist = dg2_g12_ids,
+ STEP_INFO(dg2_g12_steppings),
+ },
{},
},
.info = &xe_hpd_display,
@@ -1227,6 +1314,7 @@ static const struct intel_display_device_info xe2_lpd_display = {
.__runtime_defaults.fbc_mask =
BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B) |
BIT(INTEL_FBC_C) | BIT(INTEL_FBC_D),
+ .__runtime_defaults.has_dbuf_overlap_detection = true,
};
static const struct intel_display_device_info xe2_hpd_display = {
@@ -1241,15 +1329,19 @@ static const struct intel_display_device_info xe2_hpd_display = {
* reported by the hardware.
*/
static const struct platform_desc mtl_desc = {
- PLATFORM(METEORLAKE),
+ PLATFORM(meteorlake),
};
static const struct platform_desc lnl_desc = {
- PLATFORM(LUNARLAKE),
+ PLATFORM(lunarlake),
};
static const struct platform_desc bmg_desc = {
- PLATFORM(BATTLEMAGE),
+ PLATFORM(battlemage),
+};
+
+static const struct platform_desc ptl_desc = {
+ PLATFORM(pantherlake),
};
__diag_pop();
@@ -1322,6 +1414,7 @@ static const struct {
INTEL_MTL_IDS(INTEL_DISPLAY_DEVICE, &mtl_desc),
INTEL_LNL_IDS(INTEL_DISPLAY_DEVICE, &lnl_desc),
INTEL_BMG_IDS(INTEL_DISPLAY_DEVICE, &bmg_desc),
+ INTEL_PTL_IDS(INTEL_DISPLAY_DEVICE, &ptl_desc),
};
static const struct {
@@ -1332,6 +1425,7 @@ static const struct {
{ 14, 0, &xe_lpdp_display },
{ 14, 1, &xe2_hpd_display },
{ 20, 0, &xe2_lpd_display },
+ { 30, 0, &xe2_lpd_display },
};
static const struct intel_display_device_info *
@@ -1392,7 +1486,7 @@ find_subplatform_desc(struct pci_dev *pdev, const struct platform_desc *desc)
const struct subplatform_desc *sp;
const u16 *id;
- for (sp = desc->subplatforms; sp && sp->subplatform; sp++)
+ for (sp = desc->subplatforms; sp && sp->pciidlist; sp++)
for (id = sp->pciidlist; *id; id++)
if (*id == pdev->device)
return sp;
@@ -1451,6 +1545,25 @@ static enum intel_step get_pre_gmdid_step(struct intel_display *display,
return step;
}
+/* Size of the entire bitmap, not the number of platforms */
+static unsigned int display_platforms_num_bits(void)
+{
+ return sizeof(((struct intel_display_platforms *)0)->bitmap) * BITS_PER_BYTE;
+}
+
+/* Number of platform bits set */
+static unsigned int display_platforms_weight(const struct intel_display_platforms *p)
+{
+ return bitmap_weight(p->bitmap, display_platforms_num_bits());
+}
+
+/* Merge the subplatform information from src to dst */
+static void display_platforms_or(struct intel_display_platforms *dst,
+ const struct intel_display_platforms *src)
+{
+ bitmap_or(dst->bitmap, dst->bitmap, src->bitmap, display_platforms_num_bits());
+}
+
void intel_display_device_probe(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
@@ -1490,13 +1603,23 @@ void intel_display_device_probe(struct drm_i915_private *i915)
&DISPLAY_INFO(i915)->__runtime_defaults,
sizeof(*DISPLAY_RUNTIME_INFO(i915)));
- drm_WARN_ON(&i915->drm, !desc->platform || !desc->name);
- DISPLAY_RUNTIME_INFO(i915)->platform = desc->platform;
+ drm_WARN_ON(&i915->drm, !desc->name ||
+ !display_platforms_weight(&desc->platforms));
+
+ display->platform = desc->platforms;
subdesc = find_subplatform_desc(pdev, desc);
if (subdesc) {
- drm_WARN_ON(&i915->drm, !subdesc->subplatform || !subdesc->name);
- DISPLAY_RUNTIME_INFO(i915)->subplatform = subdesc->subplatform;
+ drm_WARN_ON(&i915->drm, !subdesc->name ||
+ !display_platforms_weight(&subdesc->platforms));
+
+ display_platforms_or(&display->platform, &subdesc->platforms);
+
+ /* Ensure platform and subplatform are distinct */
+ drm_WARN_ON(&i915->drm,
+ display_platforms_weight(&display->platform) !=
+ display_platforms_weight(&desc->platforms) +
+ display_platforms_weight(&subdesc->platforms));
}
if (ip_ver.ver || ip_ver.rel || ip_ver.step) {
@@ -1653,8 +1776,10 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE)
display_runtime->has_hdcp = 0;
- if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE)
- display_runtime->fbc_mask = 0;
+ if (IS_DG2(i915) || DISPLAY_VER(i915) < 13) {
+ if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE)
+ display_runtime->fbc_mask = 0;
+ }
if (DISPLAY_VER(i915) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
display_runtime->has_dmc = 0;
@@ -1662,6 +1787,10 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
if (IS_DISPLAY_VER(i915, 10, 12) &&
(dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE))
display_runtime->has_dsc = 0;
+
+ if (DISPLAY_VER(display) >= 20 &&
+ (dfsm & XE2LPD_DFSM_DBUF_OVERLAP_DISABLE))
+ display_runtime->has_dbuf_overlap_detection = false;
}
if (DISPLAY_VER(i915) >= 20) {
@@ -1679,6 +1808,10 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
}
}
+ if (DISPLAY_VER(i915) >= 30)
+ display_runtime->edp_typec_support =
+ intel_de_read(display, PICA_PHY_CONFIG_CONTROL) & EDP_ON_TYPEC;
+
display_runtime->rawclk_freq = intel_read_rawclk(display);
drm_dbg_kms(&i915->drm, "rawclk rate: %d kHz\n", display_runtime->rawclk_freq);
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index 3ef537fa551a..43144a037f9f 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -6,6 +6,7 @@
#ifndef __INTEL_DISPLAY_DEVICE_H__
#define __INTEL_DISPLAY_DEVICE_H__
+#include <linux/bitops.h>
#include <linux/types.h>
#include "intel_display_conversion.h"
@@ -14,89 +15,108 @@
struct drm_i915_private;
struct drm_printer;
-/* Keep in gen based order, and chronological order within a gen */
-enum intel_display_platform {
- INTEL_DISPLAY_PLATFORM_UNINITIALIZED = 0,
- /* Display ver 2 */
- INTEL_DISPLAY_I830,
- INTEL_DISPLAY_I845G,
- INTEL_DISPLAY_I85X,
- INTEL_DISPLAY_I865G,
- /* Display ver 3 */
- INTEL_DISPLAY_I915G,
- INTEL_DISPLAY_I915GM,
- INTEL_DISPLAY_I945G,
- INTEL_DISPLAY_I945GM,
- INTEL_DISPLAY_G33,
- INTEL_DISPLAY_PINEVIEW,
- /* Display ver 4 */
- INTEL_DISPLAY_I965G,
- INTEL_DISPLAY_I965GM,
- INTEL_DISPLAY_G45,
- INTEL_DISPLAY_GM45,
- /* Display ver 5 */
- INTEL_DISPLAY_IRONLAKE,
- /* Display ver 6 */
- INTEL_DISPLAY_SANDYBRIDGE,
- /* Display ver 7 */
- INTEL_DISPLAY_IVYBRIDGE,
- INTEL_DISPLAY_VALLEYVIEW,
- INTEL_DISPLAY_HASWELL,
- /* Display ver 8 */
- INTEL_DISPLAY_BROADWELL,
- INTEL_DISPLAY_CHERRYVIEW,
- /* Display ver 9 */
- INTEL_DISPLAY_SKYLAKE,
- INTEL_DISPLAY_BROXTON,
- INTEL_DISPLAY_KABYLAKE,
- INTEL_DISPLAY_GEMINILAKE,
- INTEL_DISPLAY_COFFEELAKE,
- INTEL_DISPLAY_COMETLAKE,
- /* Display ver 11 */
- INTEL_DISPLAY_ICELAKE,
- INTEL_DISPLAY_JASPERLAKE,
- INTEL_DISPLAY_ELKHARTLAKE,
- /* Display ver 12 */
- INTEL_DISPLAY_TIGERLAKE,
- INTEL_DISPLAY_ROCKETLAKE,
- INTEL_DISPLAY_DG1,
- INTEL_DISPLAY_ALDERLAKE_S,
- /* Display ver 13 */
- INTEL_DISPLAY_ALDERLAKE_P,
- INTEL_DISPLAY_DG2,
- /* Display ver 14 (based on GMD ID) */
- INTEL_DISPLAY_METEORLAKE,
- /* Display ver 20 (based on GMD ID) */
- INTEL_DISPLAY_LUNARLAKE,
- /* Display ver 14.1 (based on GMD ID) */
- INTEL_DISPLAY_BATTLEMAGE,
-};
+/*
+ * Display platforms and subplatforms. Keep platforms in display version based
+ * order, chronological order within a version, and subplatforms next to the
+ * platform.
+ */
+#define INTEL_DISPLAY_PLATFORMS(func) \
+ /* Display ver 2 */ \
+ func(i830) \
+ func(i845g) \
+ func(i85x) \
+ func(i865g) \
+ /* Display ver 3 */ \
+ func(i915g) \
+ func(i915gm) \
+ func(i945g) \
+ func(i945gm) \
+ func(g33) \
+ func(pineview) \
+ /* Display ver 4 */ \
+ func(i965g) \
+ func(i965gm) \
+ func(g45) \
+ func(gm45) \
+ func(g4x) /* group alias for g45 and gm45 */ \
+ /* Display ver 5 */ \
+ func(ironlake) \
+ /* Display ver 6 */ \
+ func(sandybridge) \
+ /* Display ver 7 */ \
+ func(ivybridge) \
+ func(valleyview) \
+ func(haswell) \
+ func(haswell_ult) \
+ func(haswell_ulx) \
+ /* Display ver 8 */ \
+ func(broadwell) \
+ func(broadwell_ult) \
+ func(broadwell_ulx) \
+ func(cherryview) \
+ /* Display ver 9 */ \
+ func(skylake) \
+ func(skylake_ult) \
+ func(skylake_ulx) \
+ func(broxton) \
+ func(kabylake) \
+ func(kabylake_ult) \
+ func(kabylake_ulx) \
+ func(geminilake) \
+ func(coffeelake) \
+ func(coffeelake_ult) \
+ func(coffeelake_ulx) \
+ func(cometlake) \
+ func(cometlake_ult) \
+ func(cometlake_ulx) \
+ /* Display ver 11 */ \
+ func(icelake) \
+ func(icelake_port_f) \
+ func(jasperlake) \
+ func(elkhartlake) \
+ /* Display ver 12 */ \
+ func(tigerlake) \
+ func(tigerlake_uy) \
+ func(rocketlake) \
+ func(dg1) \
+ func(alderlake_s) \
+ func(alderlake_s_raptorlake_s) \
+ /* Display ver 13 */ \
+ func(alderlake_p) \
+ func(alderlake_p_alderlake_n) \
+ func(alderlake_p_raptorlake_p) \
+ func(alderlake_p_raptorlake_u) \
+ func(dg2) \
+ func(dg2_g10) \
+ func(dg2_g11) \
+ func(dg2_g12) \
+ /* Display ver 14 (based on GMD ID) */ \
+ func(meteorlake) \
+ /* Display ver 20 (based on GMD ID) */ \
+ func(lunarlake) \
+ /* Display ver 14.1 (based on GMD ID) */ \
+ func(battlemage) \
+ /* Display ver 30 (based on GMD ID) */ \
+ func(pantherlake)
+
+#define __MEMBER(name) unsigned long name:1;
+#define __COUNT(x) 1 +
-enum intel_display_subplatform {
- INTEL_DISPLAY_SUBPLATFORM_UNINITIALIZED = 0,
- INTEL_DISPLAY_HASWELL_ULT,
- INTEL_DISPLAY_HASWELL_ULX,
- INTEL_DISPLAY_BROADWELL_ULT,
- INTEL_DISPLAY_BROADWELL_ULX,
- INTEL_DISPLAY_SKYLAKE_ULT,
- INTEL_DISPLAY_SKYLAKE_ULX,
- INTEL_DISPLAY_KABYLAKE_ULT,
- INTEL_DISPLAY_KABYLAKE_ULX,
- INTEL_DISPLAY_COFFEELAKE_ULT,
- INTEL_DISPLAY_COFFEELAKE_ULX,
- INTEL_DISPLAY_COMETLAKE_ULT,
- INTEL_DISPLAY_COMETLAKE_ULX,
- INTEL_DISPLAY_ICELAKE_PORT_F,
- INTEL_DISPLAY_TIGERLAKE_UY,
- INTEL_DISPLAY_ALDERLAKE_S_RAPTORLAKE_S,
- INTEL_DISPLAY_ALDERLAKE_P_ALDERLAKE_N,
- INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_P,
- INTEL_DISPLAY_ALDERLAKE_P_RAPTORLAKE_U,
- INTEL_DISPLAY_DG2_G10,
- INTEL_DISPLAY_DG2_G11,
- INTEL_DISPLAY_DG2_G12,
+#define __NUM_PLATFORMS (INTEL_DISPLAY_PLATFORMS(__COUNT) 0)
+
+struct intel_display_platforms {
+ union {
+ struct {
+ INTEL_DISPLAY_PLATFORMS(__MEMBER);
+ };
+ DECLARE_BITMAP(bitmap, __NUM_PLATFORMS);
+ };
};
+#undef __MEMBER
+#undef __COUNT
+#undef __NUM_PLATFORMS
+
#define DEV_INFO_DISPLAY_FOR_EACH_FLAG(func) \
/* Keep in alphabetical order */ \
func(cursor_needs_physical); \
@@ -123,6 +143,7 @@ enum intel_display_subplatform {
#define HAS_CDCLK_SQUASH(i915) (DISPLAY_INFO(i915)->has_cdclk_squash)
#define HAS_CUR_FBC(i915) (!HAS_GMCH(i915) && IS_DISPLAY_VER(i915, 7, 13))
#define HAS_D12_PLANE_MINIMIZATION(i915) (IS_ROCKETLAKE(i915) || IS_ALDERLAKE_S(i915))
+#define HAS_DBUF_OVERLAP_DETECTION(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dbuf_overlap_detection)
#define HAS_DDI(i915) (DISPLAY_INFO(i915)->has_ddi)
#define HAS_DISPLAY(i915) (DISPLAY_RUNTIME_INFO(i915)->pipe_mask != 0)
#define HAS_DMC(i915) (DISPLAY_RUNTIME_INFO(i915)->has_dmc)
@@ -166,10 +187,10 @@ enum intel_display_subplatform {
#define SUPPORTS_TV(i915) (DISPLAY_INFO(i915)->supports_tv)
/* Check that device has a display IP version within the specific range. */
-#define IS_DISPLAY_VER_FULL(__i915, from, until) ( \
- BUILD_BUG_ON_ZERO((from) < IP_VER(2, 0)) + \
- (DISPLAY_VER_FULL(__i915) >= (from) && \
- DISPLAY_VER_FULL(__i915) <= (until)))
+#define IS_DISPLAY_VERx100(__i915, from, until) ( \
+ BUILD_BUG_ON_ZERO((from) < 200) + \
+ (DISPLAY_VERx100(__i915) >= (from) && \
+ DISPLAY_VERx100(__i915) <= (until)))
/*
* Check if a device has a specific IP version as well as a stepping within the
@@ -180,22 +201,22 @@ enum intel_display_subplatform {
* hardware fix is present and the software workaround is no longer necessary.
* E.g.,
*
- * IS_DISPLAY_VER_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_B2)
- * IS_DISPLAY_VER_STEP(i915, IP_VER(14, 0), STEP_C0, STEP_FOREVER)
+ * IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_A0, STEP_B2)
+ * IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_C0, STEP_FOREVER)
*
* "STEP_FOREVER" can be passed as "until" for workarounds that have no upper
* stepping bound for the specified IP version.
*/
-#define IS_DISPLAY_VER_STEP(__i915, ipver, from, until) \
- (IS_DISPLAY_VER_FULL((__i915), (ipver), (ipver)) && \
+#define IS_DISPLAY_VERx100_STEP(__i915, ipver, from, until) \
+ (IS_DISPLAY_VERx100((__i915), (ipver), (ipver)) && \
IS_DISPLAY_STEP((__i915), (from), (until)))
#define DISPLAY_INFO(i915) (__to_intel_display(i915)->info.__device_info)
#define DISPLAY_RUNTIME_INFO(i915) (&__to_intel_display(i915)->info.__runtime_info)
#define DISPLAY_VER(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver)
-#define DISPLAY_VER_FULL(i915) IP_VER(DISPLAY_RUNTIME_INFO(i915)->ip.ver, \
- DISPLAY_RUNTIME_INFO(i915)->ip.rel)
+#define DISPLAY_VERx100(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver * 100 + \
+ DISPLAY_RUNTIME_INFO(i915)->ip.rel)
#define IS_DISPLAY_VER(i915, from, until) \
(DISPLAY_VER(i915) >= (from) && DISPLAY_VER(i915) <= (until))
@@ -206,9 +227,6 @@ enum intel_display_subplatform {
INTEL_DISPLAY_STEP(__i915) >= (since) && INTEL_DISPLAY_STEP(__i915) < (until))
struct intel_display_runtime_info {
- enum intel_display_platform platform;
- enum intel_display_subplatform subplatform;
-
struct intel_display_ip_ver {
u16 ver;
u16 rel;
@@ -230,6 +248,8 @@ struct intel_display_runtime_info {
bool has_hdcp;
bool has_dmc;
bool has_dsc;
+ bool edp_typec_support;
+ bool has_dbuf_overlap_detection;
};
struct intel_display_device_info {
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 673f9b965494..56b78cf6b854 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -194,7 +194,7 @@ void intel_display_driver_early_probe(struct drm_i915_private *i915)
intel_display_irq_init(i915);
intel_dkl_phy_init(i915);
- intel_color_init_hooks(i915);
+ intel_color_init_hooks(&i915->display);
intel_init_cdclk_hooks(&i915->display);
intel_audio_hooks_init(i915);
intel_dpll_init_clock_hook(i915);
@@ -249,7 +249,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
if (ret)
goto cleanup_vga_client_pw_domain_dmc;
- ret = intel_color_init(i915);
+ ret = intel_color_init(display);
if (ret)
goto cleanup_vga_client_pw_domain_dmc;
@@ -432,7 +432,7 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
intel_pps_setup(display);
- intel_gmbus_setup(i915);
+ intel_gmbus_setup(display);
drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
INTEL_NUM_PIPES(i915),
@@ -485,7 +485,7 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
return 0;
err_hdcp:
- intel_hdcp_component_fini(i915);
+ intel_hdcp_component_fini(display);
err_mode_config:
intel_mode_config_cleanup(i915);
@@ -495,6 +495,7 @@ err_mode_config:
/* part #3: call after gem init */
int intel_display_driver_probe(struct drm_i915_private *i915)
{
+ struct intel_display *display = &i915->display;
int ret;
if (!HAS_DISPLAY(i915))
@@ -505,7 +506,7 @@ int intel_display_driver_probe(struct drm_i915_private *i915)
* the BIOS fb takeover and whatever else magic ggtt reservations
* happen during gem/ggtt init.
*/
- intel_hdcp_component_init(i915);
+ intel_hdcp_component_init(display);
/*
* Force all active planes to recompute their states. So that on
@@ -600,7 +601,7 @@ void intel_display_driver_remove_noirq(struct drm_i915_private *i915)
/* flush any delayed tasks or pending work */
flush_workqueue(i915->unordered_wq);
- intel_hdcp_component_fini(i915);
+ intel_hdcp_component_fini(display);
intel_mode_config_cleanup(i915);
@@ -608,7 +609,7 @@ void intel_display_driver_remove_noirq(struct drm_i915_private *i915)
intel_overlay_cleanup(i915);
- intel_gmbus_teardown(i915);
+ intel_gmbus_teardown(display);
destroy_workqueue(i915->display.wq.flip);
destroy_workqueue(i915->display.wq.modeset);
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
index a4367ddc7a44..e1547ebce60e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -543,12 +543,13 @@ void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv,
intel_opregion_asle_intr(display);
if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
- intel_gmbus_irq_handler(dev_priv);
+ intel_gmbus_irq_handler(display);
}
void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
u32 pipe_stats[I915_MAX_PIPES])
{
+ struct intel_display *display = &dev_priv->display;
enum pipe pipe;
for_each_pipe(dev_priv, pipe) {
@@ -566,7 +567,7 @@ void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
}
if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
- intel_gmbus_irq_handler(dev_priv);
+ intel_gmbus_irq_handler(display);
}
static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
@@ -588,7 +589,7 @@ static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
intel_dp_aux_irq_handler(display);
if (pch_iir & SDE_GMBUS)
- intel_gmbus_irq_handler(dev_priv);
+ intel_gmbus_irq_handler(display);
if (pch_iir & SDE_AUDIO_HDCP_MASK)
drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n");
@@ -677,7 +678,7 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
intel_dp_aux_irq_handler(display);
if (pch_iir & SDE_GMBUS_CPT)
- intel_gmbus_irq_handler(dev_priv);
+ intel_gmbus_irq_handler(display);
if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n");
@@ -902,6 +903,13 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
struct intel_display *display = &dev_priv->display;
bool found = false;
+ if (HAS_DBUF_OVERLAP_DETECTION(display)) {
+ if (iir & XE2LPD_DBUF_OVERLAP_DETECTED) {
+ drm_warn(display->drm, "DBuf overlap detected\n");
+ found = true;
+ }
+ }
+
if (DISPLAY_VER(dev_priv) >= 14) {
if (iir & (XELPDP_PMDEMAND_RSP |
XELPDP_PMDEMAND_RSPTOUT_ERR)) {
@@ -1021,17 +1029,6 @@ static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915)
return GEN8_PIPE_PRIMARY_FLIP_DONE;
}
-u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv)
-{
- u32 mask = GEN8_PIPE_FIFO_UNDERRUN;
-
- if (DISPLAY_VER(dev_priv) >= 13)
- mask |= XELPD_PIPE_SOFT_UNDERRUN |
- XELPD_PIPE_HARD_UNDERRUN;
-
- return mask;
-}
-
static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir)
{
u32 pica_ier = 0;
@@ -1120,7 +1117,7 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
(iir & BXT_DE_PORT_GMBUS)) {
- intel_gmbus_irq_handler(dev_priv);
+ intel_gmbus_irq_handler(display);
found = true;
}
@@ -1177,7 +1174,7 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
hsw_pipe_crc_irq_handler(dev_priv, pipe);
- if (iir & gen8_de_pipe_underrun_mask(dev_priv))
+ if (iir & GEN8_PIPE_FIFO_UNDERRUN)
intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
@@ -1424,7 +1421,7 @@ static void intel_display_vblank_dc_work(struct work_struct *work)
struct intel_display *display =
container_of(work, typeof(*display), irq.vblank_dc_work);
struct drm_i915_private *i915 = to_i915(display->drm);
- u8 vblank_enabled = READ_ONCE(display->irq.vblank_enabled);
+ int vblank_wa_num_pipes = READ_ONCE(display->irq.vblank_wa_num_pipes);
/*
* NOTE: intel_display_power_set_target_dc_state is used only by PSR
@@ -1432,7 +1429,7 @@ static void intel_display_vblank_dc_work(struct work_struct *work)
* PSR code. If DC3CO is taken into use we need take that into account
* here as well.
*/
- intel_display_power_set_target_dc_state(i915, vblank_enabled ? DC_STATE_DISABLE :
+ intel_display_power_set_target_dc_state(i915, vblank_wa_num_pipes ? DC_STATE_DISABLE :
DC_STATE_EN_UPTO_DC6);
}
@@ -1447,7 +1444,7 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
if (gen11_dsi_configure_te(crtc, true))
return 0;
- if (display->irq.vblank_enabled++ == 0 && crtc->block_dc_for_vblank)
+ if (crtc->block_dc_for_vblank && display->irq.vblank_wa_num_pipes++ == 0)
schedule_work(&display->irq.vblank_dc_work);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
@@ -1478,7 +1475,7 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
- if (--display->irq.vblank_enabled == 0 && crtc->block_dc_for_vblank)
+ if (crtc->block_dc_for_vblank && --display->irq.vblank_wa_num_pipes == 0)
schedule_work(&display->irq.vblank_dc_work);
}
@@ -1496,7 +1493,7 @@ void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
i9xx_pipestat_irq_reset(dev_priv);
- gen3_irq_reset(uncore, VLV_IRQ_REGS);
+ gen2_irq_reset(uncore, VLV_IRQ_REGS);
dev_priv->irq_mask = ~0u;
}
@@ -1539,7 +1536,7 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
dev_priv->irq_mask = ~enable_mask;
- gen3_irq_init(uncore, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask);
+ gen2_irq_init(uncore, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask);
}
void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
@@ -1556,10 +1553,10 @@ void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
for_each_pipe(dev_priv, pipe)
if (intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe)))
- gen3_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
+ gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
- gen3_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS);
- gen3_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS);
}
void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
@@ -1599,26 +1596,25 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
for_each_pipe(dev_priv, pipe)
if (intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe)))
- gen3_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
+ gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
- gen3_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS);
- gen3_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS);
if (DISPLAY_VER(dev_priv) >= 14)
- gen3_irq_reset(uncore, PICAINTERRUPT_IRQ_REGS);
+ gen2_irq_reset(uncore, PICAINTERRUPT_IRQ_REGS);
else
- gen3_irq_reset(uncore, GEN11_DE_HPD_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN11_DE_HPD_IRQ_REGS);
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
- gen3_irq_reset(uncore, SDE_IRQ_REGS);
+ gen2_irq_reset(uncore, SDE_IRQ_REGS);
}
void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
u8 pipe_mask)
{
struct intel_uncore *uncore = &dev_priv->uncore;
- u32 extra_ier = GEN8_PIPE_VBLANK |
- gen8_de_pipe_underrun_mask(dev_priv) |
+ u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN |
gen8_de_pipe_flip_done_mask(dev_priv);
enum pipe pipe;
@@ -1630,7 +1626,7 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
}
for_each_pipe_masked(dev_priv, pipe, pipe_mask)
- gen3_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe),
+ gen2_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe),
dev_priv->display.irq.de_irq_mask[pipe],
~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier);
@@ -1651,7 +1647,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
}
for_each_pipe_masked(dev_priv, pipe, pipe_mask)
- gen3_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
+ gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
spin_unlock_irq(&dev_priv->irq_lock);
@@ -1685,7 +1681,7 @@ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
else
mask = SDE_GMBUS_CPT;
- gen3_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff);
+ gen2_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff);
}
void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
@@ -1742,7 +1738,7 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915)
}
if (IS_HASWELL(i915)) {
- gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
+ gen2_assert_iir_is_zero(uncore, EDP_PSR_IIR);
display_mask |= DE_EDP_PSR_INT_HSW;
}
@@ -1753,7 +1749,7 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915)
ibx_irq_postinstall(i915);
- gen3_irq_init(uncore, DE_IRQ_REGS, i915->irq_mask,
+ gen2_irq_init(uncore, DE_IRQ_REGS, i915->irq_mask,
display_mask | extra_mask);
}
@@ -1801,14 +1797,16 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
de_port_masked |= DSI0_TE | DSI1_TE;
}
+ if (HAS_DBUF_OVERLAP_DETECTION(display))
+ de_misc_masked |= XE2LPD_DBUF_OVERLAP_DETECTED;
+
if (HAS_DSB(dev_priv))
de_pipe_masked |= GEN12_DSB_INT(INTEL_DSB_0) |
GEN12_DSB_INT(INTEL_DSB_1) |
GEN12_DSB_INT(INTEL_DSB_2);
de_pipe_enables = de_pipe_masked |
- GEN8_PIPE_VBLANK |
- gen8_de_pipe_underrun_mask(dev_priv) |
+ GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN |
gen8_de_pipe_flip_done_mask(dev_priv);
de_port_enables = de_port_masked;
@@ -1827,11 +1825,11 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
if (!intel_display_power_is_enabled(dev_priv, domain))
continue;
- gen3_assert_iir_is_zero(uncore,
+ gen2_assert_iir_is_zero(uncore,
TRANS_PSR_IIR(dev_priv, trans));
}
} else {
- gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
+ gen2_assert_iir_is_zero(uncore, EDP_PSR_IIR);
}
for_each_pipe(dev_priv, pipe) {
@@ -1839,20 +1837,20 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
if (intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe)))
- gen3_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe),
+ gen2_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe),
dev_priv->display.irq.de_irq_mask[pipe],
de_pipe_enables);
}
- gen3_irq_init(uncore, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables);
- gen3_irq_init(uncore, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked);
+ gen2_irq_init(uncore, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables);
+ gen2_irq_init(uncore, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked);
if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
u32 de_hpd_masked = 0;
u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
GEN11_DE_TBT_HOTPLUG_MASK;
- gen3_irq_init(uncore, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked,
+ gen2_irq_init(uncore, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked,
de_hpd_enables);
}
}
@@ -1865,10 +1863,10 @@ static void mtp_irq_postinstall(struct drm_i915_private *i915)
u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
XELPDP_TBT_HOTPLUG_MASK;
- gen3_irq_init(uncore, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask,
+ gen2_irq_init(uncore, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask,
de_hpd_enables);
- gen3_irq_init(uncore, SDE_IRQ_REGS, ~sde_mask, 0xffffffff);
+ gen2_irq_init(uncore, SDE_IRQ_REGS, ~sde_mask, 0xffffffff);
}
static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
@@ -1876,7 +1874,7 @@ static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
struct intel_uncore *uncore = &dev_priv->uncore;
u32 mask = SDE_GMBUS_ICP;
- gen3_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff);
+ gen2_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff);
}
void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.h b/drivers/gpu/drm/i915/display/intel_display_irq.h
index 4b493cff7b8e..b077712b7be1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.h
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.h
@@ -33,7 +33,6 @@ void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits);
void gen8_irq_power_well_post_enable(struct drm_i915_private *i915, u8 pipe_mask);
void gen8_irq_power_well_pre_disable(struct drm_i915_private *i915, u8 pipe_mask);
-u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *i915);
int i8xx_enable_vblank(struct drm_crtc *crtc);
int i915gm_enable_vblank(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index c2bc80f5bf6b..2766fd9208b0 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -1176,43 +1176,44 @@ static void hsw_assert_cdclk(struct drm_i915_private *dev_priv)
static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
{
+ struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc;
- for_each_intel_crtc(&dev_priv->drm, crtc)
- I915_STATE_WARN(dev_priv, crtc->active,
- "CRTC for pipe %c enabled\n",
- pipe_name(crtc->pipe));
-
- I915_STATE_WARN(dev_priv, intel_de_read(dev_priv, HSW_PWR_WELL_CTL2),
- "Display power well on\n");
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, SPLL_CTL) & SPLL_PLL_ENABLE,
- "SPLL enabled\n");
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, WRPLL_CTL(0)) & WRPLL_PLL_ENABLE,
- "WRPLL1 enabled\n");
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, WRPLL_CTL(1)) & WRPLL_PLL_ENABLE,
- "WRPLL2 enabled\n");
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, PP_STATUS(dev_priv, 0)) & PP_ON,
- "Panel power on\n");
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
- "CPU PWM1 enabled\n");
+ for_each_intel_crtc(display->drm, crtc)
+ INTEL_DISPLAY_STATE_WARN(display, crtc->active,
+ "CRTC for pipe %c enabled\n",
+ pipe_name(crtc->pipe));
+
+ INTEL_DISPLAY_STATE_WARN(display, intel_de_read(display, HSW_PWR_WELL_CTL2),
+ "Display power well on\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, SPLL_CTL) & SPLL_PLL_ENABLE,
+ "SPLL enabled\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, WRPLL_CTL(0)) & WRPLL_PLL_ENABLE,
+ "WRPLL1 enabled\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, WRPLL_CTL(1)) & WRPLL_PLL_ENABLE,
+ "WRPLL2 enabled\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, PP_STATUS(display, 0)) & PP_ON,
+ "Panel power on\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
+ "CPU PWM1 enabled\n");
if (IS_HASWELL(dev_priv))
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
- "CPU PWM2 enabled\n");
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
- "PCH PWM1 enabled\n");
- I915_STATE_WARN(dev_priv,
- (intel_de_read(dev_priv, UTIL_PIN_CTL) & (UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) == (UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM),
- "Utility pin enabled in PWM mode\n");
- I915_STATE_WARN(dev_priv,
- intel_de_read(dev_priv, PCH_GTC_CTL) & PCH_GTC_ENABLE,
- "PCH GTC enabled\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
+ "CPU PWM2 enabled\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
+ "PCH PWM1 enabled\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ (intel_de_read(display, UTIL_PIN_CTL) & (UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) == (UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM),
+ "Utility pin enabled in PWM mode\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_de_read(display, PCH_GTC_CTL) & PCH_GTC_ENABLE,
+ "PCH GTC enabled\n");
/*
* In theory we can still leave IRQs enabled, as long as only the HPD
@@ -1220,8 +1221,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
* gen-specific and since we only disable LCPLL after we fully disable
* the interrupts, the check below should be enough.
*/
- I915_STATE_WARN(dev_priv, intel_irqs_enabled(dev_priv),
- "IRQs enabled\n");
+ INTEL_DISPLAY_STATE_WARN(display, intel_irqs_enabled(dev_priv),
+ "IRQs enabled\n");
}
static u32 hsw_read_dcomp(struct drm_i915_private *dev_priv)
@@ -1683,14 +1684,14 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
intel_snps_phy_wait_for_calibration(dev_priv);
/* 9. XE2_HPD: Program CHICKEN_MISC_2 before any cursor or planes are enabled */
- if (DISPLAY_VER_FULL(dev_priv) == IP_VER(14, 1))
+ if (DISPLAY_VERx100(dev_priv) == 1401)
intel_de_rmw(dev_priv, CHICKEN_MISC_2, BMG_DARB_HALF_BLK_END_BURST, 1);
if (resume)
intel_dmc_load_program(display);
/* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p,dg2 */
- if (IS_DISPLAY_VER_FULL(dev_priv, IP_VER(12, 0), IP_VER(13, 0)))
+ if (IS_DISPLAY_VERx100(dev_priv, 1200, 1300))
intel_de_rmw(dev_priv, GEN11_CHICKEN_DCPR_2, 0,
DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM |
DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR);
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 10948b3964ee..5575aa0d6689 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_map.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c
@@ -1586,6 +1586,136 @@ static const struct i915_power_well_desc_list xe2lpd_power_wells[] = {
I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica),
};
+/*
+ * Xe3 changes the power well hierarchy slightly from Xe_LPD+; PGB now
+ * depends on PG1 instead of PG2:
+ *
+ * PG0
+ * |
+ * --PG1--
+ * / | \
+ * PGA PGB PG2
+ * / \
+ * PGC PGD
+ */
+
+#define XE3LPD_PW_C_POWER_DOMAINS \
+ POWER_DOMAIN_PIPE_C, \
+ POWER_DOMAIN_PIPE_PANEL_FITTER_C
+
+#define XE3LPD_PW_D_POWER_DOMAINS \
+ POWER_DOMAIN_PIPE_D, \
+ POWER_DOMAIN_PIPE_PANEL_FITTER_D
+
+#define XE3LPD_PW_2_POWER_DOMAINS \
+ XE3LPD_PW_C_POWER_DOMAINS, \
+ XE3LPD_PW_D_POWER_DOMAINS, \
+ POWER_DOMAIN_TRANSCODER_C, \
+ POWER_DOMAIN_TRANSCODER_D, \
+ POWER_DOMAIN_VGA, \
+ POWER_DOMAIN_PORT_DDI_LANES_TC1, \
+ POWER_DOMAIN_PORT_DDI_LANES_TC2, \
+ POWER_DOMAIN_PORT_DDI_LANES_TC3, \
+ POWER_DOMAIN_PORT_DDI_LANES_TC4
+
+I915_DECL_PW_DOMAINS(xe3lpd_pwdoms_pw_2,
+ XE3LPD_PW_2_POWER_DOMAINS,
+ POWER_DOMAIN_INIT);
+
+I915_DECL_PW_DOMAINS(xe3lpd_pwdoms_pw_b,
+ POWER_DOMAIN_PIPE_B,
+ POWER_DOMAIN_PIPE_PANEL_FITTER_B,
+ POWER_DOMAIN_INIT);
+
+I915_DECL_PW_DOMAINS(xe3lpd_pwdoms_pw_c,
+ XE3LPD_PW_C_POWER_DOMAINS,
+ POWER_DOMAIN_INIT);
+
+I915_DECL_PW_DOMAINS(xe3lpd_pwdoms_pw_d,
+ XE3LPD_PW_D_POWER_DOMAINS,
+ POWER_DOMAIN_INIT);
+
+static const struct i915_power_well_desc xe3lpd_power_wells_main[] = {
+ {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("PW_2", &xe3lpd_pwdoms_pw_2,
+ .hsw.idx = ICL_PW_CTL_IDX_PW_2,
+ .id = SKL_DISP_PW_2),
+ ),
+ .ops = &hsw_power_well_ops,
+ .has_vga = true,
+ .has_fuses = true,
+ }, {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("PW_A", &xelpd_pwdoms_pw_a,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_A),
+ ),
+ .ops = &hsw_power_well_ops,
+ .irq_pipe_mask = BIT(PIPE_A),
+ .has_fuses = true,
+ }, {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("PW_B", &xe3lpd_pwdoms_pw_b,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_B),
+ ),
+ .ops = &hsw_power_well_ops,
+ .irq_pipe_mask = BIT(PIPE_B),
+ .has_fuses = true,
+ }, {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("PW_C", &xe3lpd_pwdoms_pw_c,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_C),
+ ),
+ .ops = &hsw_power_well_ops,
+ .irq_pipe_mask = BIT(PIPE_C),
+ .has_fuses = true,
+ }, {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("PW_D", &xe3lpd_pwdoms_pw_d,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_D),
+ ),
+ .ops = &hsw_power_well_ops,
+ .irq_pipe_mask = BIT(PIPE_D),
+ .has_fuses = true,
+ }, {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("AUX_A", &icl_pwdoms_aux_a, .xelpdp.aux_ch = AUX_CH_A),
+ I915_PW("AUX_B", &icl_pwdoms_aux_b, .xelpdp.aux_ch = AUX_CH_B),
+ I915_PW("AUX_TC1", &xelpdp_pwdoms_aux_tc1, .xelpdp.aux_ch = AUX_CH_USBC1),
+ I915_PW("AUX_TC2", &xelpdp_pwdoms_aux_tc2, .xelpdp.aux_ch = AUX_CH_USBC2),
+ I915_PW("AUX_TC3", &xelpdp_pwdoms_aux_tc3, .xelpdp.aux_ch = AUX_CH_USBC3),
+ I915_PW("AUX_TC4", &xelpdp_pwdoms_aux_tc4, .xelpdp.aux_ch = AUX_CH_USBC4),
+ ),
+ .ops = &xelpdp_aux_power_well_ops,
+ },
+};
+
+I915_DECL_PW_DOMAINS(xe3lpd_pwdoms_dc_off,
+ POWER_DOMAIN_DC_OFF,
+ XE3LPD_PW_2_POWER_DOMAINS,
+ XE3LPD_PW_C_POWER_DOMAINS,
+ XE3LPD_PW_D_POWER_DOMAINS,
+ POWER_DOMAIN_AUDIO_MMIO,
+ POWER_DOMAIN_INIT);
+
+static const struct i915_power_well_desc xe3lpd_power_wells_dcoff[] = {
+ {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("DC_off", &xe3lpd_pwdoms_dc_off,
+ .id = SKL_DISP_DC_OFF),
+ ),
+ .ops = &gen9_dc_off_power_well_ops,
+ },
+};
+
+static const struct i915_power_well_desc_list xe3lpd_power_wells[] = {
+ I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
+ I915_PW_DESCRIPTORS(icl_power_wells_pw_1),
+ I915_PW_DESCRIPTORS(xe3lpd_power_wells_dcoff),
+ I915_PW_DESCRIPTORS(xe3lpd_power_wells_main),
+ I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica),
+};
+
static void init_power_well_domains(const struct i915_power_well_instance *inst,
struct i915_power_well *power_well)
{
@@ -1693,7 +1823,9 @@ int intel_display_power_map_init(struct i915_power_domains *power_domains)
return 0;
}
- if (DISPLAY_VER(i915) >= 20)
+ if (DISPLAY_VER(i915) >= 30)
+ return set_power_wells(power_domains, xe3lpd_power_wells);
+ else if (DISPLAY_VER(i915) >= 20)
return set_power_wells(power_domains, xe2lpd_power_wells);
else if (DISPLAY_VER(i915) >= 14)
return set_power_wells(power_domains, xelpdp_power_wells);
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 adaf7cf3a33b..f0131dd853de 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -919,38 +919,45 @@ static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- bxt_dpio_phy_init(dev_priv, i915_power_well_instance(power_well)->bxt.phy);
+ struct intel_display *display = &dev_priv->display;
+
+ bxt_dpio_phy_init(display, i915_power_well_instance(power_well)->bxt.phy);
}
static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- bxt_dpio_phy_uninit(dev_priv, i915_power_well_instance(power_well)->bxt.phy);
+ struct intel_display *display = &dev_priv->display;
+
+ bxt_dpio_phy_uninit(display, i915_power_well_instance(power_well)->bxt.phy);
}
static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- return bxt_dpio_phy_is_enabled(dev_priv, i915_power_well_instance(power_well)->bxt.phy);
+ struct intel_display *display = &dev_priv->display;
+
+ return bxt_dpio_phy_is_enabled(display, i915_power_well_instance(power_well)->bxt.phy);
}
static void bxt_verify_dpio_phy_power_wells(struct drm_i915_private *dev_priv)
{
+ struct intel_display *display = &dev_priv->display;
struct i915_power_well *power_well;
power_well = lookup_power_well(dev_priv, BXT_DISP_PW_DPIO_CMN_A);
if (intel_power_well_refcount(power_well) > 0)
- bxt_dpio_phy_verify_state(dev_priv, i915_power_well_instance(power_well)->bxt.phy);
+ bxt_dpio_phy_verify_state(display, i915_power_well_instance(power_well)->bxt.phy);
power_well = lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);
if (intel_power_well_refcount(power_well) > 0)
- bxt_dpio_phy_verify_state(dev_priv, i915_power_well_instance(power_well)->bxt.phy);
+ bxt_dpio_phy_verify_state(display, i915_power_well_instance(power_well)->bxt.phy);
if (IS_GEMINILAKE(dev_priv)) {
power_well = lookup_power_well(dev_priv,
GLK_DISP_PW_DPIO_CMN_C);
if (intel_power_well_refcount(power_well) > 0)
- bxt_dpio_phy_verify_state(dev_priv,
+ bxt_dpio_phy_verify_state(display,
i915_power_well_instance(power_well)->bxt.phy);
}
}
@@ -1330,13 +1337,14 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
#define BITS_SET(val, bits) (((val) & (bits)) == (bits))
-static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
+static void assert_chv_phy_status(struct intel_display *display)
{
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
struct i915_power_well *cmn_bc =
lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);
struct i915_power_well *cmn_d =
lookup_power_well(dev_priv, CHV_DISP_PW_DPIO_CMN_D);
- u32 phy_control = dev_priv->display.power.chv_phy_control;
+ u32 phy_control = display->power.chv_phy_control;
u32 phy_status = 0;
u32 phy_status_mask = 0xffffffff;
@@ -1347,7 +1355,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
* reset (ie. the power well has been disabled at
* least once).
*/
- if (!dev_priv->display.power.chv_phy_assert[DPIO_PHY0])
+ if (!display->power.chv_phy_assert[DPIO_PHY0])
phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1) |
@@ -1355,7 +1363,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1));
- if (!dev_priv->display.power.chv_phy_assert[DPIO_PHY1])
+ if (!display->power.chv_phy_assert[DPIO_PHY1])
phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1));
@@ -1383,7 +1391,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
*/
if (BITS_SET(phy_control,
PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) &&
- (intel_de_read(dev_priv, DPLL(dev_priv, PIPE_B)) & DPLL_VCO_ENABLE) == 0)
+ (intel_de_read(display, DPLL(display, PIPE_B)) & DPLL_VCO_ENABLE) == 0)
phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1);
if (BITS_SET(phy_control,
@@ -1426,12 +1434,12 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
* The PHY may be busy with some initial calibration and whatnot,
* so the power state can take a while to actually change.
*/
- if (intel_de_wait(dev_priv, DISPLAY_PHY_STATUS,
+ if (intel_de_wait(display, DISPLAY_PHY_STATUS,
phy_status_mask, phy_status, 10))
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n",
- intel_de_read(dev_priv, DISPLAY_PHY_STATUS) & phy_status_mask,
- phy_status, dev_priv->display.power.chv_phy_control);
+ intel_de_read(display, DISPLAY_PHY_STATUS) & phy_status_mask,
+ phy_status, display->power.chv_phy_control);
}
#undef BITS_SET
@@ -1439,11 +1447,12 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
+ struct intel_display *display = &dev_priv->display;
enum i915_power_well_id id = i915_power_well_instance(power_well)->id;
enum dpio_phy phy;
u32 tmp;
- drm_WARN_ON_ONCE(&dev_priv->drm,
+ drm_WARN_ON_ONCE(display->drm,
id != VLV_DISP_PW_DPIO_CMN_BC &&
id != CHV_DISP_PW_DPIO_CMN_D);
@@ -1457,9 +1466,9 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
vlv_set_power_well(dev_priv, power_well, true);
/* Poll for phypwrgood signal */
- if (intel_de_wait_for_set(dev_priv, DISPLAY_PHY_STATUS,
+ if (intel_de_wait_for_set(display, DISPLAY_PHY_STATUS,
PHY_POWERGOOD(phy), 1))
- drm_err(&dev_priv->drm, "Display PHY %d is not power up\n",
+ drm_err(display->drm, "Display PHY %d is not power up\n",
phy);
vlv_dpio_get(dev_priv);
@@ -1487,24 +1496,25 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
vlv_dpio_put(dev_priv);
- dev_priv->display.power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
- intel_de_write(dev_priv, DISPLAY_PHY_CONTROL,
- dev_priv->display.power.chv_phy_control);
+ display->power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
+ intel_de_write(display, DISPLAY_PHY_CONTROL,
+ display->power.chv_phy_control);
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
- phy, dev_priv->display.power.chv_phy_control);
+ phy, display->power.chv_phy_control);
- assert_chv_phy_status(dev_priv);
+ assert_chv_phy_status(display);
}
static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
+ struct intel_display *display = &dev_priv->display;
enum i915_power_well_id id = i915_power_well_instance(power_well)->id;
enum dpio_phy phy;
- drm_WARN_ON_ONCE(&dev_priv->drm,
+ drm_WARN_ON_ONCE(display->drm,
id != VLV_DISP_PW_DPIO_CMN_BC &&
id != CHV_DISP_PW_DPIO_CMN_D);
@@ -1517,20 +1527,20 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
assert_pll_disabled(dev_priv, PIPE_C);
}
- dev_priv->display.power.chv_phy_control &= ~PHY_COM_LANE_RESET_DEASSERT(phy);
- intel_de_write(dev_priv, DISPLAY_PHY_CONTROL,
- dev_priv->display.power.chv_phy_control);
+ display->power.chv_phy_control &= ~PHY_COM_LANE_RESET_DEASSERT(phy);
+ intel_de_write(display, DISPLAY_PHY_CONTROL,
+ display->power.chv_phy_control);
vlv_set_power_well(dev_priv, power_well, false);
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
- phy, dev_priv->display.power.chv_phy_control);
+ phy, display->power.chv_phy_control);
/* PHY is fully reset now, so we can enable the PHY state asserts */
- dev_priv->display.power.chv_phy_assert[phy] = true;
+ display->power.chv_phy_assert[phy] = true;
- assert_chv_phy_status(dev_priv);
+ assert_chv_phy_status(display);
}
static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
@@ -1600,29 +1610,30 @@ static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpi
bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
enum dpio_channel ch, bool override)
{
- struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
+ struct intel_display *display = &dev_priv->display;
+ struct i915_power_domains *power_domains = &display->power.domains;
bool was_override;
mutex_lock(&power_domains->lock);
- was_override = dev_priv->display.power.chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+ was_override = display->power.chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
if (override == was_override)
goto out;
if (override)
- dev_priv->display.power.chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+ display->power.chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
else
- dev_priv->display.power.chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+ display->power.chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
- intel_de_write(dev_priv, DISPLAY_PHY_CONTROL,
- dev_priv->display.power.chv_phy_control);
+ intel_de_write(display, DISPLAY_PHY_CONTROL,
+ display->power.chv_phy_control);
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
- phy, ch, dev_priv->display.power.chv_phy_control);
+ phy, ch, display->power.chv_phy_control);
- assert_chv_phy_status(dev_priv);
+ assert_chv_phy_status(display);
out:
mutex_unlock(&power_domains->lock);
@@ -1633,29 +1644,30 @@ out:
void chv_phy_powergate_lanes(struct intel_encoder *encoder,
bool override, unsigned int mask)
{
+ struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
+ struct i915_power_domains *power_domains = &display->power.domains;
enum dpio_phy phy = vlv_dig_port_to_phy(enc_to_dig_port(encoder));
enum dpio_channel ch = vlv_dig_port_to_channel(enc_to_dig_port(encoder));
mutex_lock(&power_domains->lock);
- dev_priv->display.power.chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch);
- dev_priv->display.power.chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch);
+ display->power.chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch);
+ display->power.chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch);
if (override)
- dev_priv->display.power.chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+ display->power.chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
else
- dev_priv->display.power.chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+ display->power.chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
- intel_de_write(dev_priv, DISPLAY_PHY_CONTROL,
- dev_priv->display.power.chv_phy_control);
+ intel_de_write(display, DISPLAY_PHY_CONTROL,
+ display->power.chv_phy_control);
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
- phy, ch, mask, dev_priv->display.power.chv_phy_control);
+ phy, ch, mask, display->power.chv_phy_control);
- assert_chv_phy_status(dev_priv);
+ assert_chv_phy_status(display);
assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h
index fc28d34b5eef..9bd8f1e505b0 100644
--- a/drivers/gpu/drm/i915/display/intel_display_trace.h
+++ b/drivers/gpu/drm/i915/display/intel_display_trace.h
@@ -9,44 +9,85 @@
#if !defined(__INTEL_DISPLAY_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
#define __INTEL_DISPLAY_TRACE_H__
+#include <linux/string.h>
#include <linux/string_helpers.h>
#include <linux/types.h>
#include <linux/tracepoint.h>
#include "i915_drv.h"
#include "intel_crtc.h"
+#include "intel_display_limits.h"
#include "intel_display_types.h"
#include "intel_vblank.h"
#define __dev_name_display(display) dev_name((display)->drm->dev)
#define __dev_name_kms(obj) dev_name((obj)->base.dev->dev)
+/*
+ * Using identifiers from enum pipe in TP_printk() will confuse tools that
+ * parse /sys/kernel/debug/tracing/{xe,i915}/<event>/format. So we use CPP
+ * macros instead.
+ */
+#define _TRACE_PIPE_A 0
+#define _TRACE_PIPE_B 1
+#define _TRACE_PIPE_C 2
+#define _TRACE_PIPE_D 3
+
+/*
+ * FIXME: Several TP_printk() calls below display frame and scanline numbers for
+ * all possible pipes (regardless of whether they are available) and that is
+ * done with a constant format string. A better approach would be to generate
+ * that info dynamically based on available pipes, but, while we do not have
+ * that implemented yet, let's assert that the constant format string indeed
+ * covers all possible pipes.
+ */
+static_assert(I915_MAX_PIPES - 1 == _TRACE_PIPE_D);
+
+#define _PIPES_FRAME_AND_SCANLINE_FMT \
+ "pipe A: frame=%u, scanline=%u" \
+ ", pipe B: frame=%u, scanline=%u" \
+ ", pipe C: frame=%u, scanline=%u" \
+ ", pipe D: frame=%u, scanline=%u"
+
+#define _PIPES_FRAME_AND_SCANLINE_VALUES \
+ __entry->frame[_TRACE_PIPE_A], __entry->scanline[_TRACE_PIPE_A] \
+ , __entry->frame[_TRACE_PIPE_B], __entry->scanline[_TRACE_PIPE_B] \
+ , __entry->frame[_TRACE_PIPE_C], __entry->scanline[_TRACE_PIPE_C] \
+ , __entry->frame[_TRACE_PIPE_D], __entry->scanline[_TRACE_PIPE_D]
+
+/*
+ * Paranoid sanity check that at least the enumeration starts at the
+ * same value as _TRACE_PIPE_A.
+ */
+static_assert(PIPE_A == _TRACE_PIPE_A);
+
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)
+ __array(u32, frame, I915_MAX_PIPES)
+ __array(u32, scanline, I915_MAX_PIPES)
+ __field(char, pipe_name)
),
TP_fast_assign(
struct intel_display *display = to_intel_display(crtc);
struct intel_crtc *it__;
__assign_str(dev);
+ memset(__entry->frame, 0,
+ sizeof(__entry->frame[0]) * I915_MAX_PIPES);
+ memset(__entry->scanline, 0,
+ sizeof(__entry->scanline[0]) * I915_MAX_PIPES);
for_each_intel_crtc(display->drm, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->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])
+ TP_printk("dev %s, pipe %c enable, " _PIPES_FRAME_AND_SCANLINE_FMT,
+ __get_str(dev), __entry->pipe_name, _PIPES_FRAME_AND_SCANLINE_VALUES)
);
TRACE_EVENT(intel_pipe_disable,
@@ -55,27 +96,28 @@ TRACE_EVENT(intel_pipe_disable,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __array(u32, frame, 3)
- __array(u32, scanline, 3)
- __field(enum pipe, pipe)
+ __array(u32, frame, I915_MAX_PIPES)
+ __array(u32, scanline, I915_MAX_PIPES)
+ __field(char, pipe_name)
),
TP_fast_assign(
struct intel_display *display = to_intel_display(crtc);
struct intel_crtc *it__;
__assign_str(dev);
+ memset(__entry->frame, 0,
+ sizeof(__entry->frame[0]) * I915_MAX_PIPES);
+ memset(__entry->scanline, 0,
+ sizeof(__entry->scanline[0]) * I915_MAX_PIPES);
for_each_intel_crtc(display->drm, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->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])
+ TP_printk("dev %s, pipe %c disable, " _PIPES_FRAME_AND_SCANLINE_FMT,
+ __get_str(dev), __entry->pipe_name, _PIPES_FRAME_AND_SCANLINE_VALUES)
);
TRACE_EVENT(intel_crtc_flip_done,
@@ -84,20 +126,20 @@ TRACE_EVENT(intel_crtc_flip_done,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline)
);
@@ -107,7 +149,7 @@ TRACE_EVENT(intel_pipe_crc,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__array(u32, crcs, 5)
@@ -115,14 +157,14 @@ TRACE_EVENT(intel_pipe_crc,
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(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("dev %s, pipe %c, frame=%u, scanline=%u crc=%08x %08x %08x %08x %08x",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline,
__entry->crcs[0], __entry->crcs[1],
__entry->crcs[2], __entry->crcs[3],
@@ -135,7 +177,7 @@ TRACE_EVENT(intel_cpu_fifo_underrun,
TP_STRUCT__entry(
__string(dev, __dev_name_display(display))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
@@ -143,13 +185,13 @@ TRACE_EVENT(intel_cpu_fifo_underrun,
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
__assign_str(dev);
- __entry->pipe = pipe;
+ __entry->pipe_name = pipe_name(pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline)
);
@@ -159,7 +201,7 @@ TRACE_EVENT(intel_pch_fifo_underrun,
TP_STRUCT__entry(
__string(dev, __dev_name_display(display))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
@@ -168,13 +210,13 @@ TRACE_EVENT(intel_pch_fifo_underrun,
enum pipe pipe = pch_transcoder;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
__assign_str(dev);
- __entry->pipe = pipe;
+ __entry->pipe_name = pipe_name(pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pch transcoder %c, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline)
);
@@ -184,8 +226,8 @@ TRACE_EVENT(intel_memory_cxsr,
TP_STRUCT__entry(
__string(dev, __dev_name_display(display))
- __array(u32, frame, 3)
- __array(u32, scanline, 3)
+ __array(u32, frame, I915_MAX_PIPES)
+ __array(u32, scanline, I915_MAX_PIPES)
__field(bool, old)
__field(bool, new)
),
@@ -193,6 +235,10 @@ TRACE_EVENT(intel_memory_cxsr,
TP_fast_assign(
struct intel_crtc *crtc;
__assign_str(dev);
+ memset(__entry->frame, 0,
+ sizeof(__entry->frame[0]) * I915_MAX_PIPES);
+ memset(__entry->scanline, 0,
+ sizeof(__entry->scanline[0]) * I915_MAX_PIPES);
for_each_intel_crtc(display->drm, crtc) {
__entry->frame[crtc->pipe] = intel_crtc_get_vblank_counter(crtc);
__entry->scanline[crtc->pipe] = intel_get_crtc_scanline(crtc);
@@ -201,11 +247,9 @@ TRACE_EVENT(intel_memory_cxsr,
__entry->new = 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",
+ TP_printk("dev %s, cxsr %s->%s, " _PIPES_FRAME_AND_SCANLINE_FMT,
__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])
+ _PIPES_FRAME_AND_SCANLINE_VALUES)
);
TRACE_EVENT(g4x_wm,
@@ -214,7 +258,7 @@ TRACE_EVENT(g4x_wm,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(u16, primary)
@@ -233,7 +277,7 @@ TRACE_EVENT(g4x_wm,
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->primary = wm->pipe[crtc->pipe].plane[PLANE_PRIMARY];
@@ -251,7 +295,7 @@ TRACE_EVENT(g4x_wm,
),
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),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline,
__entry->primary, __entry->sprite, __entry->cursor,
str_yes_no(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc,
@@ -265,7 +309,7 @@ TRACE_EVENT(vlv_wm,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(u32, level)
@@ -280,7 +324,7 @@ TRACE_EVENT(vlv_wm,
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->level = wm->level;
@@ -294,7 +338,7 @@ TRACE_EVENT(vlv_wm,
),
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),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline,
__entry->level, __entry->cxsr,
__entry->primary, __entry->sprite0, __entry->sprite1, __entry->cursor,
@@ -307,7 +351,7 @@ TRACE_EVENT(vlv_fifo_size,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(u32, sprite0_start)
@@ -317,7 +361,7 @@ TRACE_EVENT(vlv_fifo_size,
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->sprite0_start = sprite0_start;
@@ -326,7 +370,7 @@ TRACE_EVENT(vlv_fifo_size,
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, %d/%d/%d",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline,
__entry->sprite0_start, __entry->sprite1_start, __entry->fifo_size)
);
@@ -337,7 +381,7 @@ TRACE_EVENT(intel_plane_async_flip,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(bool, async_flip)
@@ -347,14 +391,14 @@ TRACE_EVENT(intel_plane_async_flip,
TP_fast_assign(
__assign_str(dev);
__assign_str(name);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->async_flip = async_flip;
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, async_flip=%s",
- __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline, str_yes_no(__entry->async_flip))
);
@@ -364,7 +408,7 @@ TRACE_EVENT(intel_plane_update_noarm,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__array(int, src, 4)
@@ -375,7 +419,7 @@ TRACE_EVENT(intel_plane_update_noarm,
TP_fast_assign(
__assign_str(dev);
__assign_str(name);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src));
@@ -383,7 +427,7 @@ TRACE_EVENT(intel_plane_update_noarm,
),
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),
+ __get_str(dev), __entry->pipe_name, __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))
@@ -395,7 +439,7 @@ TRACE_EVENT(intel_plane_update_arm,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__array(int, src, 4)
@@ -406,7 +450,7 @@ TRACE_EVENT(intel_plane_update_arm,
TP_fast_assign(
__assign_str(dev);
__assign_str(name);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src));
@@ -414,7 +458,7 @@ TRACE_EVENT(intel_plane_update_arm,
),
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),
+ __get_str(dev), __entry->pipe_name, __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))
@@ -426,7 +470,7 @@ TRACE_EVENT(intel_plane_disable_arm,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__string(name, plane->base.name)
@@ -435,13 +479,13 @@ TRACE_EVENT(intel_plane_disable_arm,
TP_fast_assign(
__assign_str(dev);
__assign_str(name);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);
@@ -452,7 +496,7 @@ TRACE_EVENT(intel_fbc_activate,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
__string(name, plane->base.name)
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
@@ -463,13 +507,13 @@ TRACE_EVENT(intel_fbc_activate,
plane->pipe);
__assign_str(dev);
__assign_str(name);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);
@@ -480,7 +524,7 @@ TRACE_EVENT(intel_fbc_deactivate,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
__string(name, plane->base.name)
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
@@ -491,13 +535,13 @@ TRACE_EVENT(intel_fbc_deactivate,
plane->pipe);
__assign_str(dev);
__assign_str(name);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);
@@ -508,7 +552,7 @@ TRACE_EVENT(intel_fbc_nuke,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
__string(name, plane->base.name)
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
@@ -519,13 +563,13 @@ TRACE_EVENT(intel_fbc_nuke,
plane->pipe);
__assign_str(dev);
__assign_str(name);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);
@@ -535,20 +579,20 @@ TRACE_EVENT(intel_crtc_vblank_work_start,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline)
);
@@ -558,20 +602,20 @@ TRACE_EVENT(intel_crtc_vblank_work_end,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline)
);
@@ -581,7 +625,7 @@ TRACE_EVENT(intel_pipe_update_start,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(u32, min)
@@ -590,7 +634,7 @@ TRACE_EVENT(intel_pipe_update_start,
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->min = crtc->debug.min_vbl;
@@ -598,7 +642,7 @@ TRACE_EVENT(intel_pipe_update_start,
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline,
__entry->min, __entry->max)
);
@@ -609,7 +653,7 @@ TRACE_EVENT(intel_pipe_update_vblank_evaded,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(u32, min)
@@ -618,7 +662,7 @@ TRACE_EVENT(intel_pipe_update_vblank_evaded,
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = crtc->debug.start_vbl_count;
__entry->scanline = crtc->debug.scanline_start;
__entry->min = crtc->debug.min_vbl;
@@ -626,7 +670,7 @@ TRACE_EVENT(intel_pipe_update_vblank_evaded,
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline,
__entry->min, __entry->max)
);
@@ -637,20 +681,20 @@ TRACE_EVENT(intel_pipe_update_end,
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
- __field(enum pipe, pipe)
+ __field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
__assign_str(dev);
- __entry->pipe = crtc->pipe;
+ __entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = frame;
__entry->scanline = scanline_end;
),
TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
- __get_str(dev), pipe_name(__entry->pipe),
+ __get_str(dev), __entry->pipe_name,
__entry->frame, __entry->scanline)
);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 2bb1fa64da2f..ff6eb93337e0 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1618,6 +1618,8 @@ struct intel_psr {
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
u8 entry_setup_frames;
+
+ bool link_ok;
};
struct intel_dp {
@@ -1765,6 +1767,7 @@ struct intel_dp {
/* When we last wrote the OUI for eDP */
unsigned long last_oui_write;
+ bool oui_valid;
bool colorimetry_support;
@@ -2104,6 +2107,10 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
__drm_device_to_intel_display((p)->base.dev)
#define __intel_hdmi_to_intel_display(p) \
__drm_device_to_intel_display(hdmi_to_dig_port(p)->base.base.dev)
+#define __intel_plane_to_intel_display(p) \
+ __drm_device_to_intel_display((p)->base.dev)
+#define __intel_plane_state_to_intel_display(p) \
+ __drm_device_to_intel_display((p)->uapi.plane->dev)
/* Helper for generic association. Map types to conversion functions/macros. */
#define __assoc(type, p) \
@@ -2122,6 +2129,8 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
__assoc(intel_digital_port, p), \
__assoc(intel_dp, p), \
__assoc(intel_encoder, p), \
- __assoc(intel_hdmi, p))
+ __assoc(intel_hdmi, p), \
+ __assoc(intel_plane, p), \
+ __assoc(intel_plane_state, p))
#endif /* __INTEL_DISPLAY_TYPES_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 48bbbf8f312c..87bdacfd9edf 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -113,6 +113,9 @@ static bool dmc_firmware_param_disabled(struct intel_display *display)
#define DISPLAY_VER13_DMC_MAX_FW_SIZE 0x20000
#define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE
+#define XE3LPD_DMC_PATH DMC_PATH(xe3lpd)
+MODULE_FIRMWARE(XE3LPD_DMC_PATH);
+
#define XE2LPD_DMC_PATH DMC_PATH(xe2lpd)
MODULE_FIRMWARE(XE2LPD_DMC_PATH);
@@ -168,13 +171,16 @@ static const char *dmc_firmware_default(struct intel_display *display, u32 *size
const char *fw_path = NULL;
u32 max_fw_size = 0;
- if (DISPLAY_VER_FULL(display) == IP_VER(20, 0)) {
+ if (DISPLAY_VERx100(display) == 3000) {
+ fw_path = XE3LPD_DMC_PATH;
+ max_fw_size = XE2LPD_DMC_MAX_FW_SIZE;
+ } else if (DISPLAY_VERx100(display) == 2000) {
fw_path = XE2LPD_DMC_PATH;
max_fw_size = XE2LPD_DMC_MAX_FW_SIZE;
- } else if (DISPLAY_VER_FULL(display) == IP_VER(14, 1)) {
+ } else if (DISPLAY_VERx100(display) == 1401) {
fw_path = BMG_DMC_PATH;
max_fw_size = XELPDP_DMC_MAX_FW_SIZE;
- } else if (DISPLAY_VER_FULL(display) == IP_VER(14, 0)) {
+ } else if (DISPLAY_VERx100(display) == 1400) {
fw_path = MTL_DMC_PATH;
max_fw_size = XELPDP_DMC_MAX_FW_SIZE;
} else if (IS_DG2(i915)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index fbb096be02ad..ff5ba7b3035f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -83,8 +83,10 @@
#include "intel_modeset_lock.h"
#include "intel_panel.h"
#include "intel_pch_display.h"
+#include "intel_pfit.h"
#include "intel_pps.h"
#include "intel_psr.h"
+#include "intel_runtime_pm.h"
#include "intel_quirks.h"
#include "intel_tc.h"
#include "intel_vdsc.h"
@@ -495,7 +497,7 @@ static int mtl_max_source_rate(struct intel_dp *intel_dp)
if (intel_encoder_is_c10phy(encoder))
return 810000;
- if (DISPLAY_VER_FULL(to_i915(encoder->base.dev)) == IP_VER(14, 1))
+ if (DISPLAY_VERx100(to_i915(encoder->base.dev)) == 1401)
return 1350000;
return 2000000;
@@ -1313,14 +1315,17 @@ bool intel_dp_needs_joiner(struct intel_dp *intel_dp,
int num_joined_pipes)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ int hdisplay_limit;
if (!intel_dp_has_joiner(intel_dp))
return false;
num_joined_pipes /= 2;
+ hdisplay_limit = DISPLAY_VER(i915) >= 30 ? 6144 : 5120;
+
return clock > num_joined_pipes * i915->display.cdclk.max_dotclk_freq ||
- hdisplay > num_joined_pipes * 5120;
+ hdisplay > num_joined_pipes * hdisplay_limit;
}
int intel_dp_num_joined_pipes(struct intel_dp *intel_dp,
@@ -2475,7 +2480,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
encoder->base.base.id, encoder->base.name,
crtc->base.base.id, crtc->base.name,
adjusted_mode->crtc_clock,
- dsc ? "on" : "off",
+ str_on_off(dsc),
limits->max_lane_count,
limits->max_rate,
limits->pipe.max_bpp,
@@ -3399,30 +3404,43 @@ void intel_dp_sink_disable_decompression(struct intel_atomic_state *state,
}
static void
-intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful)
+intel_dp_init_source_oui(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 oui[] = { 0x00, 0xaa, 0x01 };
u8 buf[3] = {};
+ if (READ_ONCE(intel_dp->oui_valid))
+ return;
+
+ WRITE_ONCE(intel_dp->oui_valid, true);
+
/*
* During driver init, we want to be careful and avoid changing the source OUI if it's
* already set to what we want, so as to avoid clearing any state by accident
*/
- if (careful) {
- if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0)
- drm_err(&i915->drm, "Failed to read source OUI\n");
+ if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0)
+ drm_err(&i915->drm, "Failed to read source OUI\n");
- if (memcmp(oui, buf, sizeof(oui)) == 0)
- return;
+ if (memcmp(oui, buf, sizeof(oui)) == 0) {
+ /* Assume the OUI was written now. */
+ intel_dp->last_oui_write = jiffies;
+ return;
}
- if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0)
- drm_err(&i915->drm, "Failed to write source OUI\n");
+ if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) {
+ drm_info(&i915->drm, "Failed to write source OUI\n");
+ WRITE_ONCE(intel_dp->oui_valid, false);
+ }
intel_dp->last_oui_write = jiffies;
}
+void intel_dp_invalidate_source_oui(struct intel_dp *intel_dp)
+{
+ WRITE_ONCE(intel_dp->oui_valid, false);
+}
+
void intel_dp_wait_source_oui(struct intel_dp *intel_dp)
{
struct intel_connector *connector = intel_dp->attached_connector;
@@ -3458,8 +3476,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
lspcon_resume(dp_to_dig_port(intel_dp));
/* Write the source OUI as early as possible */
- if (intel_dp_is_edp(intel_dp))
- intel_edp_init_source_oui(intel_dp, false);
+ intel_dp_init_source_oui(intel_dp);
/*
* When turning on, we need to retry for 1ms to give the sink
@@ -3997,6 +4014,23 @@ static void intel_edp_get_dsc_sink_cap(u8 edp_dpcd_rev, struct intel_connector *
intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, connector->dp.dsc_dpcd);
}
+static void
+intel_dp_detect_dsc_caps(struct intel_dp *intel_dp, struct intel_connector *connector)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+ /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */
+ if (!HAS_DSC(i915))
+ return;
+
+ if (intel_dp_is_edp(intel_dp))
+ intel_edp_get_dsc_sink_cap(intel_dp->edp_dpcd[0],
+ connector);
+ else
+ intel_dp_get_dsc_sink_cap(intel_dp->dpcd[DP_DPCD_REV],
+ connector);
+}
+
static void intel_edp_mso_mode_fixup(struct intel_connector *connector,
struct drm_display_mode *mode)
{
@@ -4163,6 +4197,12 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
}
/*
+ * If needed, program our source OUI so we can make various Intel-specific AUX services
+ * available (such as HDR backlight controls)
+ */
+ intel_dp_init_source_oui(intel_dp);
+
+ /*
* This has to be called after intel_dp->edp_dpcd is filled, PSR checks
* for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1]
*/
@@ -4172,15 +4212,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
intel_dp_set_max_sink_lane_count(intel_dp);
/* Read the eDP DSC DPCD registers */
- if (HAS_DSC(dev_priv))
- intel_edp_get_dsc_sink_cap(intel_dp->edp_dpcd[0],
- connector);
-
- /*
- * If needed, program our source OUI so we can make various Intel-specific AUX services
- * available (such as HDR backlight controls)
- */
- intel_edp_init_source_oui(intel_dp, true);
+ intel_dp_detect_dsc_caps(intel_dp, connector);
return true;
}
@@ -5006,7 +5038,8 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp)
return true;
/* Retrain if link not ok */
- return !intel_dp_link_ok(intel_dp, link_status);
+ return !intel_dp_link_ok(intel_dp, link_status) &&
+ !intel_psr_link_ok(intel_dp);
}
bool intel_dp_has_connector(struct intel_dp *intel_dp,
@@ -5034,6 +5067,21 @@ bool intel_dp_has_connector(struct intel_dp *intel_dp,
return false;
}
+static void wait_for_connector_hw_done(const struct drm_connector_state *conn_state)
+{
+ struct intel_connector *connector = to_intel_connector(conn_state->connector);
+ struct intel_display *display = to_intel_display(connector);
+
+ drm_modeset_lock_assert_held(&display->drm->mode_config.connection_mutex);
+
+ if (!conn_state->commit)
+ return;
+
+ drm_WARN_ON(display->drm,
+ !wait_for_completion_timeout(&conn_state->commit->hw_done,
+ msecs_to_jiffies(5000)));
+}
+
int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
struct drm_modeset_acquire_ctx *ctx,
u8 *pipe_mask)
@@ -5070,10 +5118,7 @@ int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
if (!crtc_state->hw.active)
continue;
- if (conn_state->commit)
- drm_WARN_ON(&i915->drm,
- !wait_for_completion_timeout(&conn_state->commit->hw_done,
- msecs_to_jiffies(5000)));
+ wait_for_connector_hw_done(conn_state);
*pipe_mask |= BIT(crtc->pipe);
}
@@ -5082,6 +5127,11 @@ int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
return ret;
}
+void intel_dp_flush_connector_commits(struct intel_connector *connector)
+{
+ wait_for_connector_hw_done(connector->base.state);
+}
+
static bool intel_dp_is_connected(struct intel_dp *intel_dp)
{
struct intel_connector *connector = intel_dp->attached_connector;
@@ -5545,23 +5595,6 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
}
static void
-intel_dp_detect_dsc_caps(struct intel_dp *intel_dp, struct intel_connector *connector)
-{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-
- /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */
- if (!HAS_DSC(i915))
- return;
-
- if (intel_dp_is_edp(intel_dp))
- intel_edp_get_dsc_sink_cap(intel_dp->edp_dpcd[0],
- connector);
- else
- intel_dp_get_dsc_sink_cap(intel_dp->dpcd[DP_DPCD_REV],
- connector);
-}
-
-static void
intel_dp_detect_sdp_caps(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@@ -5595,6 +5628,10 @@ intel_dp_detect(struct drm_connector *connector,
if (!intel_display_driver_check_access(dev_priv))
return connector->status;
+ intel_dp_flush_connector_commits(intel_connector);
+
+ intel_pps_vdd_on(intel_dp);
+
/* Can't disconnect eDP */
if (intel_dp_is_edp(intel_dp))
status = edp_detect(intel_dp);
@@ -5625,12 +5662,17 @@ intel_dp_detect(struct drm_connector *connector,
intel_dp_tunnel_disconnect(intel_dp);
- goto out;
+ goto out_unset_edid;
}
+ intel_dp_init_source_oui(intel_dp);
+
ret = intel_dp_tunnel_detect(intel_dp, ctx);
- if (ret == -EDEADLK)
- return ret;
+ if (ret == -EDEADLK) {
+ status = ret;
+
+ goto out_vdd_off;
+ }
if (ret == 1)
intel_connector->base.epoch_counter++;
@@ -5658,7 +5700,7 @@ intel_dp_detect(struct drm_connector *connector,
* with EDID on it
*/
status = connector_status_disconnected;
- goto out;
+ goto out_unset_edid;
}
/*
@@ -5687,7 +5729,7 @@ intel_dp_detect(struct drm_connector *connector,
intel_dp_check_device_service_irq(intel_dp);
-out:
+out_unset_edid:
if (status != connector_status_connected && !intel_dp->is_mst)
intel_dp_unset_edid(intel_dp);
@@ -5696,6 +5738,9 @@ out:
status,
intel_dp->dpcd,
intel_dp->downstream_ports);
+out_vdd_off:
+ intel_pps_vdd_off(intel_dp);
+
return status;
}
@@ -6054,7 +6099,9 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
u8 dpcd[DP_RECEIVER_CAP_SIZE];
if (dig_port->base.type == INTEL_OUTPUT_EDP &&
- (long_hpd || !intel_pps_have_panel_power_or_vdd(intel_dp))) {
+ (long_hpd ||
+ intel_runtime_pm_suspended(&i915->runtime_pm) ||
+ !intel_pps_have_panel_power_or_vdd(intel_dp))) {
/*
* vdd off can generate a long/short pulse on eDP which
* would require vdd on to handle it, and thus we
@@ -6087,6 +6134,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
if (long_hpd) {
intel_dp->reset_link_params = true;
+ intel_dp_invalidate_source_oui(intel_dp);
+
return IRQ_NONE;
}
@@ -6372,6 +6421,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
out_vdd_off:
intel_pps_vdd_off_sync(intel_dp);
+ intel_bios_fini_panel(&intel_connector->panel);
return false;
}
@@ -6411,6 +6461,7 @@ bool
intel_dp_init_connector(struct intel_digital_port *dig_port,
struct intel_connector *intel_connector)
{
+ struct intel_display *display = to_intel_display(dig_port);
struct drm_connector *connector = &intel_connector->base;
struct intel_dp *intel_dp = &dig_port->dp;
struct intel_encoder *intel_encoder = &dig_port->base;
@@ -6436,10 +6487,11 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
if (_intel_dp_is_port_edp(dev_priv, intel_encoder->devdata, port)) {
/*
- * Currently we don't support eDP on TypeC ports, although in
- * theory it could work on TypeC legacy ports.
+ * Currently we don't support eDP on TypeC ports for DISPLAY_VER < 30,
+ * although in theory it could work on TypeC legacy ports.
*/
- drm_WARN_ON(dev, intel_encoder_is_tc(intel_encoder));
+ drm_WARN_ON(dev, intel_encoder_is_tc(intel_encoder) &&
+ DISPLAY_VER(dev_priv) < 30);
type = DRM_MODE_CONNECTOR_eDP;
intel_encoder->type = INTEL_OUTPUT_EDP;
@@ -6473,7 +6525,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
if (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) < 12)
connector->interlace_allowed = true;
- intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
+ if (type != DRM_MODE_CONNECTOR_eDP)
+ intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
intel_connector->base.polled = intel_connector->polled;
intel_connector_attach_encoder(intel_connector, intel_encoder);
@@ -6499,7 +6552,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
intel_dp_add_properties(intel_dp, connector);
- if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) {
+ if (is_hdcp_supported(display, port) && !intel_dp_is_edp(intel_dp)) {
int ret = intel_dp_hdcp_init(dig_port, intel_connector);
if (ret)
drm_dbg_kms(&dev_priv->drm,
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 60baf4072dc9..48f10876be65 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -54,6 +54,7 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp,
int intel_dp_get_active_pipes(struct intel_dp *intel_dp,
struct drm_modeset_acquire_ctx *ctx,
u8 *pipe_mask);
+void intel_dp_flush_connector_commits(struct intel_connector *connector);
void intel_dp_link_check(struct intel_encoder *encoder);
void intel_dp_check_link_state(struct intel_dp *intel_dp);
void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode);
@@ -188,6 +189,7 @@ void intel_dp_check_frl_training(struct intel_dp *intel_dp);
void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
+void intel_dp_invalidate_source_oui(struct intel_dp *intel_dp);
void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index dce645a07cdb..00c493cc8a4b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -58,7 +58,7 @@ static
int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
u8 *an)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
u8 aksv[DRM_HDCP_KSV_LEN] = {};
ssize_t dpcd_ret;
@@ -66,7 +66,7 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AN,
an, DRM_HDCP_AN_LEN);
if (dpcd_ret != DRM_HDCP_AN_LEN) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Failed to write An over DP/AUX (%zd)\n",
dpcd_ret);
return dpcd_ret >= 0 ? -EIO : dpcd_ret;
@@ -82,7 +82,7 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AKSV,
aksv, DRM_HDCP_KSV_LEN);
if (dpcd_ret != DRM_HDCP_KSV_LEN) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Failed to write Aksv over DP/AUX (%zd)\n",
dpcd_ret);
return dpcd_ret >= 0 ? -EIO : dpcd_ret;
@@ -93,13 +93,13 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
static int intel_dp_hdcp_read_bksv(struct intel_digital_port *dig_port,
u8 *bksv)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv,
DRM_HDCP_KSV_LEN);
if (ret != DRM_HDCP_KSV_LEN) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read Bksv from DP/AUX failed (%zd)\n", ret);
return ret >= 0 ? -EIO : ret;
}
@@ -109,7 +109,7 @@ static int intel_dp_hdcp_read_bksv(struct intel_digital_port *dig_port,
static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port,
u8 *bstatus)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
/*
@@ -120,7 +120,7 @@ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port,
ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BINFO,
bstatus, DRM_HDCP_BSTATUS_LEN);
if (ret != DRM_HDCP_BSTATUS_LEN) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read bstatus from DP/AUX failed (%zd)\n", ret);
return ret >= 0 ? -EIO : ret;
}
@@ -129,7 +129,7 @@ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port,
static
int intel_dp_hdcp_read_bcaps(struct drm_dp_aux *aux,
- struct drm_i915_private *i915,
+ struct intel_display *display,
u8 *bcaps)
{
ssize_t ret;
@@ -137,7 +137,7 @@ int intel_dp_hdcp_read_bcaps(struct drm_dp_aux *aux,
ret = drm_dp_dpcd_read(aux, DP_AUX_HDCP_BCAPS,
bcaps, 1);
if (ret != 1) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read bcaps from DP/AUX failed (%zd)\n", ret);
return ret >= 0 ? -EIO : ret;
}
@@ -149,11 +149,11 @@ static
int intel_dp_hdcp_repeater_present(struct intel_digital_port *dig_port,
bool *repeater_present)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
u8 bcaps;
- ret = intel_dp_hdcp_read_bcaps(&dig_port->dp.aux, i915, &bcaps);
+ ret = intel_dp_hdcp_read_bcaps(&dig_port->dp.aux, display, &bcaps);
if (ret)
return ret;
@@ -165,13 +165,14 @@ static
int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *dig_port,
u8 *ri_prime)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME,
ri_prime, DRM_HDCP_RI_LEN);
if (ret != DRM_HDCP_RI_LEN) {
- drm_dbg_kms(&i915->drm, "Read Ri' from DP/AUX failed (%zd)\n",
+ drm_dbg_kms(display->drm,
+ "Read Ri' from DP/AUX failed (%zd)\n",
ret);
return ret >= 0 ? -EIO : ret;
}
@@ -182,14 +183,14 @@ static
int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *dig_port,
bool *ksv_ready)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
u8 bstatus;
ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS,
&bstatus, 1);
if (ret != 1) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read bstatus from DP/AUX failed (%zd)\n", ret);
return ret >= 0 ? -EIO : ret;
}
@@ -201,7 +202,7 @@ static
int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port,
int num_downstream, u8 *ksv_fifo)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
int i;
@@ -213,7 +214,7 @@ int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port,
ksv_fifo + i * DRM_HDCP_KSV_LEN,
len);
if (ret != len) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read ksv[%d] from DP/AUX failed (%zd)\n",
i, ret);
return ret >= 0 ? -EIO : ret;
@@ -226,7 +227,7 @@ static
int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port,
int i, u32 *part)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
if (i >= DRM_HDCP_V_PRIME_NUM_PARTS)
@@ -236,7 +237,7 @@ int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port,
DP_AUX_HDCP_V_PRIME(i), part,
DRM_HDCP_V_PRIME_PART_LEN);
if (ret != DRM_HDCP_V_PRIME_PART_LEN) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read v'[%d] from DP/AUX failed (%zd)\n", i, ret);
return ret >= 0 ? -EIO : ret;
}
@@ -256,14 +257,14 @@ static
bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port,
struct intel_connector *connector)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
u8 bstatus;
ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS,
&bstatus, 1);
if (ret != 1) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read bstatus from DP/AUX failed (%zd)\n", ret);
return false;
}
@@ -275,11 +276,11 @@ static
int intel_dp_hdcp_get_capability(struct intel_digital_port *dig_port,
bool *hdcp_capable)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
ssize_t ret;
u8 bcaps;
- ret = intel_dp_hdcp_read_bcaps(&dig_port->dp.aux, i915, &bcaps);
+ ret = intel_dp_hdcp_read_bcaps(&dig_port->dp.aux, display, &bcaps);
if (ret)
return ret;
@@ -342,7 +343,7 @@ static int
intel_dp_hdcp2_read_rx_status(struct intel_connector *connector,
u8 *rx_status)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct drm_dp_aux *aux = &dig_port->dp.aux;
ssize_t ret;
@@ -351,7 +352,7 @@ intel_dp_hdcp2_read_rx_status(struct intel_connector *connector,
DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status,
HDCP_2_2_DP_RXSTATUS_LEN);
if (ret != HDCP_2_2_DP_RXSTATUS_LEN) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Read bstatus from DP/AUX failed (%zd)\n", ret);
return ret >= 0 ? -EIO : ret;
}
@@ -397,7 +398,7 @@ static ssize_t
intel_dp_hdcp2_wait_for_msg(struct intel_connector *connector,
const struct hdcp2_dp_msg_data *hdcp2_msg_data)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct intel_dp *dp = &dig_port->dp;
struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
@@ -430,7 +431,7 @@ intel_dp_hdcp2_wait_for_msg(struct intel_connector *connector,
}
if (ret)
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"msg_id %d, ret %d, timeout(mSec): %d\n",
hdcp2_msg_data->msg_id, ret, timeout);
@@ -514,8 +515,8 @@ static
int intel_dp_hdcp2_read_msg(struct intel_connector *connector,
u8 msg_id, void *buf, size_t size)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct drm_dp_aux *aux = &dig_port->dp.aux;
struct intel_dp *dp = &dig_port->dp;
struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
@@ -568,7 +569,7 @@ int intel_dp_hdcp2_read_msg(struct intel_connector *connector,
ret = drm_dp_dpcd_read(aux, offset,
(void *)byte, len);
if (ret < 0) {
- drm_dbg_kms(&i915->drm, "msg_id %d, ret %zd\n",
+ drm_dbg_kms(display->drm, "msg_id %d, ret %zd\n",
msg_id, ret);
return ret;
}
@@ -581,7 +582,8 @@ int intel_dp_hdcp2_read_msg(struct intel_connector *connector,
if (hdcp2_msg_data->msg_read_timeout > 0) {
msg_expired = ktime_after(ktime_get_raw(), msg_end);
if (msg_expired) {
- drm_dbg_kms(&i915->drm, "msg_id %d, entire msg read timeout(mSec): %d\n",
+ drm_dbg_kms(display->drm,
+ "msg_id %d, entire msg read timeout(mSec): %d\n",
msg_id, hdcp2_msg_data->msg_read_timeout);
return -ETIMEDOUT;
}
@@ -696,7 +698,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector,
bool *hdcp_capable,
bool *hdcp2_capable)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct drm_dp_aux *aux;
u8 bcaps;
int ret;
@@ -709,10 +711,10 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector,
aux = &connector->port->aux;
ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable);
if (ret)
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"HDCP2 DPCD capability read failed err: %d\n", ret);
- ret = intel_dp_hdcp_read_bcaps(aux, i915, &bcaps);
+ ret = intel_dp_hdcp_read_bcaps(aux, display, &bcaps);
if (ret)
return ret;
@@ -745,8 +747,8 @@ static int
intel_dp_mst_toggle_hdcp_stream_select(struct intel_connector *connector,
bool enable)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
@@ -754,7 +756,7 @@ intel_dp_mst_toggle_hdcp_stream_select(struct intel_connector *connector,
hdcp->stream_transcoder, enable,
TRANS_DDI_HDCP_SELECT);
if (ret)
- drm_err(&i915->drm, "%s HDCP stream select failed (%d)\n",
+ drm_err(display->drm, "%s HDCP stream select failed (%d)\n",
enable ? "Enable" : "Disable", ret);
return ret;
}
@@ -763,8 +765,8 @@ static int
intel_dp_mst_hdcp_stream_encryption(struct intel_connector *connector,
bool enable)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
enum port port = dig_port->base.port;
enum transcoder cpu_transcoder = hdcp->stream_transcoder;
@@ -780,11 +782,11 @@ intel_dp_mst_hdcp_stream_encryption(struct intel_connector *connector,
return -EINVAL;
/* Wait for encryption confirmation */
- if (intel_de_wait(i915, HDCP_STATUS(i915, cpu_transcoder, port),
+ if (intel_de_wait(display, HDCP_STATUS(display, cpu_transcoder, port),
stream_enc_status, enable ? stream_enc_status : 0,
HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
- drm_err(&i915->drm, "Timed out waiting for transcoder: %s stream encryption %s\n",
- transcoder_name(cpu_transcoder), enable ? "enabled" : "disabled");
+ drm_err(display->drm, "Timed out waiting for transcoder: %s stream encryption %s\n",
+ transcoder_name(cpu_transcoder), str_enabled_disabled(enable));
return -ETIMEDOUT;
}
@@ -795,8 +797,8 @@ static int
intel_dp_mst_hdcp2_stream_encryption(struct intel_connector *connector,
bool enable)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
struct intel_hdcp *hdcp = &connector->hdcp;
enum transcoder cpu_transcoder = hdcp->stream_transcoder;
@@ -804,8 +806,8 @@ intel_dp_mst_hdcp2_stream_encryption(struct intel_connector *connector,
enum port port = dig_port->base.port;
int ret;
- drm_WARN_ON(&i915->drm, enable &&
- !!(intel_de_read(i915, HDCP2_AUTH_STREAM(i915, cpu_transcoder, port))
+ drm_WARN_ON(display->drm, enable &&
+ !!(intel_de_read(display, HDCP2_AUTH_STREAM(display, cpu_transcoder, port))
& AUTH_STREAM_TYPE) != data->streams[0].stream_type);
ret = intel_dp_mst_toggle_hdcp_stream_select(connector, enable);
@@ -813,12 +815,12 @@ intel_dp_mst_hdcp2_stream_encryption(struct intel_connector *connector,
return ret;
/* Wait for encryption confirmation */
- if (intel_de_wait(i915, HDCP2_STREAM_STATUS(i915, cpu_transcoder, pipe),
+ if (intel_de_wait(display, HDCP2_STREAM_STATUS(display, cpu_transcoder, pipe),
STREAM_ENCRYPTION_STATUS,
enable ? STREAM_ENCRYPTION_STATUS : 0,
HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
- drm_err(&i915->drm, "Timed out waiting for transcoder: %s stream encryption %s\n",
- transcoder_name(cpu_transcoder), enable ? "enabled" : "disabled");
+ drm_err(display->drm, "Timed out waiting for transcoder: %s stream encryption %s\n",
+ transcoder_name(cpu_transcoder), str_enabled_disabled(enable));
return -ETIMEDOUT;
}
@@ -873,13 +875,12 @@ static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim = {
int intel_dp_hdcp_init(struct intel_digital_port *dig_port,
struct intel_connector *intel_connector)
{
- struct drm_device *dev = intel_connector->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_display *display = to_intel_display(dig_port);
struct intel_encoder *intel_encoder = &dig_port->base;
enum port port = intel_encoder->port;
struct intel_dp *intel_dp = &dig_port->dp;
- if (!is_hdcp_supported(dev_priv, port))
+ if (!is_hdcp_supported(display, port))
return 0;
if (intel_connector->mst_port)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 7be8fb047b6c..5bba078c00d8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -153,7 +153,7 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec
{
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
- int num_joined_pipes = crtc_state->joiner_pipes;
+ int num_joined_pipes = intel_crtc_num_joined_pipes(crtc_state);
return intel_dp_dsc_get_slice_count(connector,
adjusted_mode->clock,
@@ -1573,6 +1573,8 @@ intel_dp_mst_detect(struct drm_connector *connector,
if (!intel_display_driver_check_access(i915))
return connector->status;
+ intel_dp_flush_connector_commits(intel_connector);
+
return drm_dp_mst_detect_port(connector, ctx, &intel_dp->mst_mgr,
intel_connector->port);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c
index d20e4e9cf7f7..0f12f2c3467c 100644
--- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c
@@ -219,8 +219,10 @@ static const struct bxt_dpio_phy_info glk_dpio_phy_info[] = {
};
static const struct bxt_dpio_phy_info *
-bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count)
+bxt_get_phy_list(struct intel_display *display, int *count)
{
+ struct drm_i915_private *dev_priv = to_i915(display->drm);
+
if (IS_GEMINILAKE(dev_priv)) {
*count = ARRAY_SIZE(glk_dpio_phy_info);
return glk_dpio_phy_info;
@@ -231,22 +233,22 @@ bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count)
}
static const struct bxt_dpio_phy_info *
-bxt_get_phy_info(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+bxt_get_phy_info(struct intel_display *display, enum dpio_phy phy)
{
int count;
const struct bxt_dpio_phy_info *phy_list =
- bxt_get_phy_list(dev_priv, &count);
+ bxt_get_phy_list(display, &count);
return &phy_list[phy];
}
-void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
+void bxt_port_to_phy_channel(struct intel_display *display, enum port port,
enum dpio_phy *phy, enum dpio_channel *ch)
{
const struct bxt_dpio_phy_info *phy_info, *phys;
int i, count;
- phys = bxt_get_phy_list(dev_priv, &count);
+ phys = bxt_get_phy_list(display, &count);
for (i = 0; i < count; i++) {
phy_info = &phys[i];
@@ -265,7 +267,7 @@ void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
}
}
- drm_WARN(&dev_priv->drm, 1, "PHY not found for PORT %c",
+ drm_WARN(display->drm, 1, "PHY not found for PORT %c",
port_name(port));
*phy = DPIO_PHY0;
*ch = DPIO_CH0;
@@ -275,16 +277,16 @@ void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
* Like intel_de_rmw() but reads from a single per-lane register and
* writes to the group register to write the same value to all the lanes.
*/
-static u32 bxt_dpio_phy_rmw_grp(struct drm_i915_private *i915,
+static u32 bxt_dpio_phy_rmw_grp(struct intel_display *display,
i915_reg_t reg_single,
i915_reg_t reg_group,
u32 clear, u32 set)
{
u32 old, val;
- old = intel_de_read(i915, reg_single);
+ old = intel_de_read(display, reg_single);
val = (old & ~clear) | set;
- intel_de_write(i915, reg_group, val);
+ intel_de_write(display, reg_group, val);
return old;
}
@@ -292,30 +294,30 @@ static u32 bxt_dpio_phy_rmw_grp(struct drm_i915_private *i915,
void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
const struct intel_ddi_buf_trans *trans;
enum dpio_channel ch;
enum dpio_phy phy;
int lane, n_entries;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
- if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
+ if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
- bxt_port_to_phy_channel(dev_priv, encoder->port, &phy, &ch);
+ bxt_port_to_phy_channel(display, encoder->port, &phy, &ch);
/*
* While we write to the group register to program all lanes at once we
* can read only lane registers and we pick lanes 0/1 for that.
*/
- bxt_dpio_phy_rmw_grp(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch),
+ bxt_dpio_phy_rmw_grp(display, BXT_PORT_PCS_DW10_LN01(phy, ch),
BXT_PORT_PCS_DW10_GRP(phy, ch),
TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT, 0);
for (lane = 0; lane < crtc_state->lane_count; lane++) {
int level = intel_ddi_level(encoder, crtc_state, lane);
- intel_de_rmw(dev_priv, BXT_PORT_TX_DW2_LN(phy, ch, lane),
+ intel_de_rmw(display, BXT_PORT_TX_DW2_LN(phy, ch, lane),
MARGIN_000_MASK | UNIQ_TRANS_SCALE_MASK,
MARGIN_000(trans->entries[level].bxt.margin) |
UNIQ_TRANS_SCALE(trans->entries[level].bxt.scale));
@@ -325,50 +327,50 @@ void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder,
int level = intel_ddi_level(encoder, crtc_state, lane);
u32 val;
- intel_de_rmw(dev_priv, BXT_PORT_TX_DW3_LN(phy, ch, lane),
+ intel_de_rmw(display, BXT_PORT_TX_DW3_LN(phy, ch, lane),
SCALE_DCOMP_METHOD,
trans->entries[level].bxt.enable ?
SCALE_DCOMP_METHOD : 0);
- val = intel_de_read(dev_priv, BXT_PORT_TX_DW3_LN(phy, ch, lane));
+ val = intel_de_read(display, BXT_PORT_TX_DW3_LN(phy, ch, lane));
if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD))
- drm_err(&dev_priv->drm,
+ drm_err(display->drm,
"Disabled scaling while ouniqetrangenmethod was set");
}
for (lane = 0; lane < crtc_state->lane_count; lane++) {
int level = intel_ddi_level(encoder, crtc_state, lane);
- intel_de_rmw(dev_priv, BXT_PORT_TX_DW4_LN(phy, ch, lane),
+ intel_de_rmw(display, BXT_PORT_TX_DW4_LN(phy, ch, lane),
DE_EMPHASIS_MASK,
DE_EMPHASIS(trans->entries[level].bxt.deemphasis));
}
- bxt_dpio_phy_rmw_grp(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch),
+ bxt_dpio_phy_rmw_grp(display, BXT_PORT_PCS_DW10_LN01(phy, ch),
BXT_PORT_PCS_DW10_GRP(phy, ch),
0, TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT);
}
-bool bxt_dpio_phy_is_enabled(struct drm_i915_private *dev_priv,
+bool bxt_dpio_phy_is_enabled(struct intel_display *display,
enum dpio_phy phy)
{
const struct bxt_dpio_phy_info *phy_info;
- phy_info = bxt_get_phy_info(dev_priv, phy);
+ phy_info = bxt_get_phy_info(display, phy);
- if (!(intel_de_read(dev_priv, BXT_P_CR_GT_DISP_PWRON) & phy_info->pwron_mask))
+ if (!(intel_de_read(display, BXT_P_CR_GT_DISP_PWRON) & phy_info->pwron_mask))
return false;
- if ((intel_de_read(dev_priv, BXT_PORT_CL1CM_DW0(phy)) &
+ if ((intel_de_read(display, BXT_PORT_CL1CM_DW0(phy)) &
(PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) {
- drm_dbg(&dev_priv->drm,
+ drm_dbg(display->drm,
"DDI PHY %d powered, but power hasn't settled\n", phy);
return false;
}
- if (!(intel_de_read(dev_priv, BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) {
- drm_dbg(&dev_priv->drm,
+ if (!(intel_de_read(display, BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) {
+ drm_dbg(display->drm,
"DDI PHY %d powered, but still in reset\n", phy);
return false;
@@ -377,47 +379,44 @@ bool bxt_dpio_phy_is_enabled(struct drm_i915_private *dev_priv,
return true;
}
-static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+static u32 bxt_get_grc(struct intel_display *display, enum dpio_phy phy)
{
- u32 val = intel_de_read(dev_priv, BXT_PORT_REF_DW6(phy));
+ u32 val = intel_de_read(display, BXT_PORT_REF_DW6(phy));
return REG_FIELD_GET(GRC_CODE_MASK, val);
}
-static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv,
+static void bxt_phy_wait_grc_done(struct intel_display *display,
enum dpio_phy phy)
{
- if (intel_de_wait_for_set(dev_priv, BXT_PORT_REF_DW3(phy),
- GRC_DONE, 10))
- drm_err(&dev_priv->drm, "timeout waiting for PHY%d GRC\n",
- phy);
+ if (intel_de_wait_for_set(display, BXT_PORT_REF_DW3(phy), GRC_DONE, 10))
+ drm_err(display->drm, "timeout waiting for PHY%d GRC\n", phy);
}
-static void _bxt_dpio_phy_init(struct drm_i915_private *dev_priv,
- enum dpio_phy phy)
+static void _bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy)
{
const struct bxt_dpio_phy_info *phy_info;
u32 val;
- phy_info = bxt_get_phy_info(dev_priv, phy);
+ phy_info = bxt_get_phy_info(display, phy);
- if (bxt_dpio_phy_is_enabled(dev_priv, phy)) {
+ if (bxt_dpio_phy_is_enabled(display, phy)) {
/* Still read out the GRC value for state verification */
if (phy_info->rcomp_phy != -1)
- dev_priv->display.state.bxt_phy_grc = bxt_get_grc(dev_priv, phy);
+ display->state.bxt_phy_grc = bxt_get_grc(display, phy);
- if (bxt_dpio_phy_verify_state(dev_priv, phy)) {
- drm_dbg(&dev_priv->drm, "DDI PHY %d already enabled, "
+ if (bxt_dpio_phy_verify_state(display, phy)) {
+ drm_dbg(display->drm, "DDI PHY %d already enabled, "
"won't reprogram it\n", phy);
return;
}
- drm_dbg(&dev_priv->drm,
+ drm_dbg(display->drm,
"DDI PHY %d enabled with invalid state, "
"force reprogramming it\n", phy);
}
- intel_de_rmw(dev_priv, BXT_P_CR_GT_DISP_PWRON, 0, phy_info->pwron_mask);
+ intel_de_rmw(display, BXT_P_CR_GT_DISP_PWRON, 0, phy_info->pwron_mask);
/*
* The PHY registers start out inaccessible and respond to reads with
@@ -427,92 +426,91 @@ static void _bxt_dpio_phy_init(struct drm_i915_private *dev_priv,
* The flag should get set in 100us according to the HW team, but
* use 1ms due to occasional timeouts observed with that.
*/
- if (intel_de_wait_fw(dev_priv, BXT_PORT_CL1CM_DW0(phy),
+ if (intel_de_wait_fw(display, BXT_PORT_CL1CM_DW0(phy),
PHY_RESERVED | PHY_POWER_GOOD, PHY_POWER_GOOD, 1))
- drm_err(&dev_priv->drm, "timeout during PHY%d power on\n",
+ drm_err(display->drm, "timeout during PHY%d power on\n",
phy);
/* Program PLL Rcomp code offset */
- intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW9(phy),
+ intel_de_rmw(display, BXT_PORT_CL1CM_DW9(phy),
IREF0RC_OFFSET_MASK, IREF0RC_OFFSET(0xE4));
- intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW10(phy),
+ intel_de_rmw(display, BXT_PORT_CL1CM_DW10(phy),
IREF1RC_OFFSET_MASK, IREF1RC_OFFSET(0xE4));
/* Program power gating */
- intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW28(phy), 0,
+ intel_de_rmw(display, BXT_PORT_CL1CM_DW28(phy), 0,
OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG);
if (phy_info->dual_channel)
- intel_de_rmw(dev_priv, BXT_PORT_CL2CM_DW6(phy), 0,
+ intel_de_rmw(display, BXT_PORT_CL2CM_DW6(phy), 0,
DW6_OLDO_DYN_PWR_DOWN_EN);
if (phy_info->rcomp_phy != -1) {
u32 grc_code;
- bxt_phy_wait_grc_done(dev_priv, phy_info->rcomp_phy);
+ bxt_phy_wait_grc_done(display, phy_info->rcomp_phy);
/*
* PHY0 isn't connected to an RCOMP resistor so copy over
* the corresponding calibrated value from PHY1, and disable
* the automatic calibration on PHY0.
*/
- val = bxt_get_grc(dev_priv, phy_info->rcomp_phy);
- dev_priv->display.state.bxt_phy_grc = val;
+ val = bxt_get_grc(display, phy_info->rcomp_phy);
+ display->state.bxt_phy_grc = val;
grc_code = GRC_CODE_FAST(val) |
GRC_CODE_SLOW(val) |
GRC_CODE_NOM(val);
- intel_de_write(dev_priv, BXT_PORT_REF_DW6(phy), grc_code);
- intel_de_rmw(dev_priv, BXT_PORT_REF_DW8(phy),
+ intel_de_write(display, BXT_PORT_REF_DW6(phy), grc_code);
+ intel_de_rmw(display, BXT_PORT_REF_DW8(phy),
0, GRC_DIS | GRC_RDY_OVRD);
}
if (phy_info->reset_delay)
udelay(phy_info->reset_delay);
- intel_de_rmw(dev_priv, BXT_PHY_CTL_FAMILY(phy), 0, COMMON_RESET_DIS);
+ intel_de_rmw(display, BXT_PHY_CTL_FAMILY(phy), 0, COMMON_RESET_DIS);
}
-void bxt_dpio_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+void bxt_dpio_phy_uninit(struct intel_display *display, enum dpio_phy phy)
{
const struct bxt_dpio_phy_info *phy_info;
- phy_info = bxt_get_phy_info(dev_priv, phy);
+ phy_info = bxt_get_phy_info(display, phy);
- intel_de_rmw(dev_priv, BXT_PHY_CTL_FAMILY(phy), COMMON_RESET_DIS, 0);
+ intel_de_rmw(display, BXT_PHY_CTL_FAMILY(phy), COMMON_RESET_DIS, 0);
- intel_de_rmw(dev_priv, BXT_P_CR_GT_DISP_PWRON, phy_info->pwron_mask, 0);
+ intel_de_rmw(display, BXT_P_CR_GT_DISP_PWRON, phy_info->pwron_mask, 0);
}
-void bxt_dpio_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+void bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy)
{
- const struct bxt_dpio_phy_info *phy_info =
- bxt_get_phy_info(dev_priv, phy);
+ const struct bxt_dpio_phy_info *phy_info = bxt_get_phy_info(display, phy);
enum dpio_phy rcomp_phy = phy_info->rcomp_phy;
bool was_enabled;
- lockdep_assert_held(&dev_priv->display.power.domains.lock);
+ lockdep_assert_held(&display->power.domains.lock);
was_enabled = true;
if (rcomp_phy != -1)
- was_enabled = bxt_dpio_phy_is_enabled(dev_priv, rcomp_phy);
+ was_enabled = bxt_dpio_phy_is_enabled(display, rcomp_phy);
/*
* We need to copy the GRC calibration value from rcomp_phy,
* so make sure it's powered up.
*/
if (!was_enabled)
- _bxt_dpio_phy_init(dev_priv, rcomp_phy);
+ _bxt_dpio_phy_init(display, rcomp_phy);
- _bxt_dpio_phy_init(dev_priv, phy);
+ _bxt_dpio_phy_init(display, phy);
if (!was_enabled)
- bxt_dpio_phy_uninit(dev_priv, rcomp_phy);
+ bxt_dpio_phy_uninit(display, rcomp_phy);
}
static bool __printf(6, 7)
-__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+__phy_reg_verify_state(struct intel_display *display, enum dpio_phy phy,
i915_reg_t reg, u32 mask, u32 expected,
const char *reg_fmt, ...)
{
@@ -520,7 +518,7 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
va_list args;
u32 val;
- val = intel_de_read(dev_priv, reg);
+ val = intel_de_read(display, reg);
if ((val & mask) == expected)
return true;
@@ -528,7 +526,7 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
vaf.fmt = reg_fmt;
vaf.va = &args;
- drm_dbg(&dev_priv->drm, "DDI PHY %d reg %pV [%08x] state mismatch: "
+ drm_dbg(display->drm, "DDI PHY %d reg %pV [%08x] state mismatch: "
"current %08x, expected %08x (mask %08x)\n",
phy, &vaf, reg.reg, val, (val & ~mask) | expected,
mask);
@@ -538,20 +536,20 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
return false;
}
-bool bxt_dpio_phy_verify_state(struct drm_i915_private *dev_priv,
+bool bxt_dpio_phy_verify_state(struct intel_display *display,
enum dpio_phy phy)
{
const struct bxt_dpio_phy_info *phy_info;
u32 mask;
bool ok;
- phy_info = bxt_get_phy_info(dev_priv, phy);
+ phy_info = bxt_get_phy_info(display, phy);
#define _CHK(reg, mask, exp, fmt, ...) \
- __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \
+ __phy_reg_verify_state(display, phy, reg, mask, exp, fmt, \
## __VA_ARGS__)
- if (!bxt_dpio_phy_is_enabled(dev_priv, phy))
+ if (!bxt_dpio_phy_is_enabled(display, phy))
return false;
ok = true;
@@ -575,7 +573,7 @@ bool bxt_dpio_phy_verify_state(struct drm_i915_private *dev_priv,
"BXT_PORT_CL2CM_DW6(%d)", phy);
if (phy_info->rcomp_phy != -1) {
- u32 grc_code = dev_priv->display.state.bxt_phy_grc;
+ u32 grc_code = display->state.bxt_phy_grc;
grc_code = GRC_CODE_FAST(grc_code) |
GRC_CODE_SLOW(grc_code) |
@@ -614,20 +612,20 @@ bxt_dpio_phy_calc_lane_lat_optim_mask(u8 lane_count)
void bxt_dpio_phy_set_lane_optim_mask(struct intel_encoder *encoder,
u8 lane_lat_optim_mask)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum dpio_phy phy;
enum dpio_channel ch;
int lane;
- bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
+ bxt_port_to_phy_channel(display, port, &phy, &ch);
for (lane = 0; lane < 4; lane++) {
/*
* Note that on CHV this flag is called UPAR, but has
* the same function.
*/
- intel_de_rmw(dev_priv, BXT_PORT_TX_DW14_LN(phy, ch, lane),
+ intel_de_rmw(display, BXT_PORT_TX_DW14_LN(phy, ch, lane),
LATENCY_OPTIM,
lane_lat_optim_mask & BIT(lane) ? LATENCY_OPTIM : 0);
}
@@ -636,18 +634,18 @@ void bxt_dpio_phy_set_lane_optim_mask(struct intel_encoder *encoder,
u8
bxt_dpio_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
enum dpio_phy phy;
enum dpio_channel ch;
int lane;
u8 mask;
- bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
+ bxt_port_to_phy_channel(display, port, &phy, &ch);
mask = 0;
for (lane = 0; lane < 4; lane++) {
- u32 val = intel_de_read(dev_priv,
+ u32 val = intel_de_read(display,
BXT_PORT_TX_DW14_LN(phy, ch, lane));
if (val & LATENCY_OPTIM)
diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.h b/drivers/gpu/drm/i915/display/intel_dpio_phy.h
index 226994dcb89b..a82939165546 100644
--- a/drivers/gpu/drm/i915/display/intel_dpio_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.h
@@ -10,9 +10,9 @@
enum pipe;
enum port;
-struct drm_i915_private;
struct intel_crtc_state;
struct intel_digital_port;
+struct intel_display;
struct intel_encoder;
enum dpio_channel {
@@ -27,15 +27,15 @@ enum dpio_phy {
};
#ifdef I915
-void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
+void bxt_port_to_phy_channel(struct intel_display *display, enum port port,
enum dpio_phy *phy, enum dpio_channel *ch);
void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
-void bxt_dpio_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy);
-void bxt_dpio_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy);
-bool bxt_dpio_phy_is_enabled(struct drm_i915_private *dev_priv,
+void bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy);
+void bxt_dpio_phy_uninit(struct intel_display *display, enum dpio_phy phy);
+bool bxt_dpio_phy_is_enabled(struct intel_display *display,
enum dpio_phy phy);
-bool bxt_dpio_phy_verify_state(struct drm_i915_private *dev_priv,
+bool bxt_dpio_phy_verify_state(struct intel_display *display,
enum dpio_phy phy);
u8 bxt_dpio_phy_calc_lane_lat_optim_mask(u8 lane_count);
void bxt_dpio_phy_set_lane_optim_mask(struct intel_encoder *encoder,
@@ -73,7 +73,7 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state);
#else
-static inline void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
+static inline void bxt_port_to_phy_channel(struct intel_display *display, enum port port,
enum dpio_phy *phy, enum dpio_channel *ch)
{
}
@@ -81,18 +81,18 @@ static inline void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
}
-static inline void bxt_dpio_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+static inline void bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy)
{
}
-static inline void bxt_dpio_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+static inline void bxt_dpio_phy_uninit(struct intel_display *display, enum dpio_phy phy)
{
}
-static inline bool bxt_dpio_phy_is_enabled(struct drm_i915_private *dev_priv,
+static inline bool bxt_dpio_phy_is_enabled(struct intel_display *display,
enum dpio_phy phy)
{
return false;
}
-static inline bool bxt_dpio_phy_verify_state(struct drm_i915_private *dev_priv,
+static inline bool bxt_dpio_phy_verify_state(struct intel_display *display,
enum dpio_phy phy)
{
return true;
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index b679c5391fe6..198ceda790d2 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -1003,6 +1003,7 @@ static u32 i9xx_dpll(const struct intel_crtc_state *crtc_state,
const struct dpll *clock,
const struct dpll *reduced_clock)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dpll;
@@ -1061,7 +1062,7 @@ static u32 i9xx_dpll(const struct intel_crtc_state *crtc_state,
if (crtc_state->sdvo_tv_clock)
dpll |= PLL_REF_INPUT_TVCLKINBC;
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
- intel_panel_use_ssc(dev_priv))
+ intel_panel_use_ssc(display))
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
else
dpll |= PLL_REF_INPUT_DREFCLK;
@@ -1095,6 +1096,7 @@ static u32 i8xx_dpll(const struct intel_crtc_state *crtc_state,
const struct dpll *clock,
const struct dpll *reduced_clock)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dpll;
@@ -1131,7 +1133,7 @@ static u32 i8xx_dpll(const struct intel_crtc_state *crtc_state,
dpll |= DPLL_DVO_2X_MODE;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
- intel_panel_use_ssc(dev_priv))
+ intel_panel_use_ssc(display))
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
else
dpll |= PLL_REF_INPUT_DREFCLK;
@@ -1237,11 +1239,12 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state,
static int ilk_fb_cb_factor(const struct intel_crtc_state *crtc_state)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
- ((intel_panel_use_ssc(i915) && i915->display.vbt.lvds_ssc_freq == 100000) ||
+ ((intel_panel_use_ssc(display) && i915->display.vbt.lvds_ssc_freq == 100000) ||
(HAS_PCH_IBX(i915) && intel_is_dual_link_lvds(i915))))
return 25;
@@ -1271,6 +1274,7 @@ static u32 ilk_dpll(const struct intel_crtc_state *crtc_state,
const struct dpll *clock,
const struct dpll *reduced_clock)
{
+ struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dpll;
@@ -1332,7 +1336,7 @@ static u32 ilk_dpll(const struct intel_crtc_state *crtc_state,
WARN_ON(reduced_clock->p2 != clock->p2);
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
- intel_panel_use_ssc(dev_priv))
+ intel_panel_use_ssc(display))
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
else
dpll |= PLL_REF_INPUT_DREFCLK;
@@ -1356,6 +1360,7 @@ static void ilk_compute_dpll(struct intel_crtc_state *crtc_state,
static int ilk_crtc_compute_clock(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -1368,7 +1373,7 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
- if (intel_panel_use_ssc(dev_priv)) {
+ if (intel_panel_use_ssc(display)) {
drm_dbg_kms(&dev_priv->drm,
"using SSC reference clock of %d kHz\n",
dev_priv->display.vbt.lvds_ssc_freq);
@@ -1532,6 +1537,7 @@ static int vlv_crtc_compute_clock(struct intel_atomic_state *state,
static int g4x_crtc_compute_clock(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -1539,7 +1545,7 @@ static int g4x_crtc_compute_clock(struct intel_atomic_state *state,
int refclk = 96000;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
- if (intel_panel_use_ssc(dev_priv)) {
+ if (intel_panel_use_ssc(display)) {
refclk = dev_priv->display.vbt.lvds_ssc_freq;
drm_dbg_kms(&dev_priv->drm,
"using SSC reference clock of %d kHz\n",
@@ -1581,6 +1587,7 @@ static int g4x_crtc_compute_clock(struct intel_atomic_state *state,
static int pnv_crtc_compute_clock(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -1588,7 +1595,7 @@ static int pnv_crtc_compute_clock(struct intel_atomic_state *state,
int refclk = 96000;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
- if (intel_panel_use_ssc(dev_priv)) {
+ if (intel_panel_use_ssc(display)) {
refclk = dev_priv->display.vbt.lvds_ssc_freq;
drm_dbg_kms(&dev_priv->drm,
"using SSC reference clock of %d kHz\n",
@@ -1619,6 +1626,7 @@ static int pnv_crtc_compute_clock(struct intel_atomic_state *state,
static int i9xx_crtc_compute_clock(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -1626,7 +1634,7 @@ static int i9xx_crtc_compute_clock(struct intel_atomic_state *state,
int refclk = 96000;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
- if (intel_panel_use_ssc(dev_priv)) {
+ if (intel_panel_use_ssc(display)) {
refclk = dev_priv->display.vbt.lvds_ssc_freq;
drm_dbg_kms(&dev_priv->drm,
"using SSC reference clock of %d kHz\n",
@@ -1659,6 +1667,7 @@ static int i9xx_crtc_compute_clock(struct intel_atomic_state *state,
static int i8xx_crtc_compute_clock(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -1666,7 +1675,7 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state,
int refclk = 48000;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
- if (intel_panel_use_ssc(dev_priv)) {
+ if (intel_panel_use_ssc(display)) {
refclk = dev_priv->display.vbt.lvds_ssc_freq;
drm_dbg_kms(&dev_priv->drm,
"using SSC reference clock of %d kHz\n",
@@ -2322,12 +2331,13 @@ void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe)
static void assert_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
+ struct intel_display *display = &dev_priv->display;
bool cur_state;
- cur_state = intel_de_read(dev_priv, DPLL(dev_priv, pipe)) & DPLL_VCO_ENABLE;
- I915_STATE_WARN(dev_priv, cur_state != state,
- "PLL state assertion failure (expected %s, current %s)\n",
- str_on_off(state), str_on_off(cur_state));
+ cur_state = intel_de_read(display, DPLL(display, pipe)) & DPLL_VCO_ENABLE;
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "PLL state assertion failure (expected %s, current %s)\n",
+ str_on_off(state), str_on_off(cur_state));
}
void assert_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index f490b2157828..e60497bb8a94 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -173,18 +173,19 @@ void assert_shared_dpll(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
bool state)
{
+ struct intel_display *display = &i915->display;
bool cur_state;
struct intel_dpll_hw_state hw_state;
- if (drm_WARN(&i915->drm, !pll,
+ if (drm_WARN(display->drm, !pll,
"asserting DPLL %s with no DPLL\n", str_on_off(state)))
return;
cur_state = intel_dpll_get_hw_state(i915, pll, &hw_state);
- I915_STATE_WARN(i915, cur_state != state,
- "%s assertion failure (expected %s, current %s)\n",
- pll->info->name, str_on_off(state),
- str_on_off(cur_state));
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "%s assertion failure (expected %s, current %s)\n",
+ pll->info->name, str_on_off(state),
+ str_on_off(cur_state));
}
static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id)
@@ -545,14 +546,15 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *i915,
static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *i915)
{
+ struct intel_display *display = &i915->display;
u32 val;
bool enabled;
- val = intel_de_read(i915, PCH_DREF_CONTROL);
+ val = intel_de_read(display, PCH_DREF_CONTROL);
enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
DREF_SUPERSPREAD_SOURCE_MASK));
- I915_STATE_WARN(i915, !enabled,
- "PCH refclk assertion failure, should be active but is disabled\n");
+ INTEL_DISPLAY_STATE_WARN(display, !enabled,
+ "PCH refclk assertion failure, should be active but is disabled\n");
}
static void ibx_pch_dpll_enable(struct drm_i915_private *i915,
@@ -2035,13 +2037,14 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
const struct intel_dpll_hw_state *dpll_hw_state)
{
+ struct intel_display *display = &i915->display;
const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt;
enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
enum dpio_phy phy;
enum dpio_channel ch;
u32 temp;
- bxt_port_to_phy_channel(i915, port, &phy, &ch);
+ bxt_port_to_phy_channel(display, port, &phy, &ch);
/* Non-SSC reference */
intel_de_rmw(i915, BXT_PORT_PLL_ENABLE(port), 0, PORT_PLL_REF_SEL);
@@ -2157,6 +2160,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *dpll_hw_state)
{
+ struct intel_display *display = &i915->display;
struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt;
enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
intel_wakeref_t wakeref;
@@ -2165,7 +2169,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *i915,
u32 val;
bool ret;
- bxt_port_to_phy_channel(i915, port, &phy, &ch);
+ bxt_port_to_phy_channel(display, port, &phy, &ch);
wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
@@ -4619,6 +4623,7 @@ verify_single_dpll_state(struct drm_i915_private *i915,
struct intel_crtc *crtc,
const struct intel_crtc_state *new_crtc_state)
{
+ struct intel_display *display = &i915->display;
struct intel_dpll_hw_state dpll_hw_state = {};
u8 pipe_mask;
bool active;
@@ -4626,22 +4631,22 @@ verify_single_dpll_state(struct drm_i915_private *i915,
active = intel_dpll_get_hw_state(i915, pll, &dpll_hw_state);
if (!pll->info->always_on) {
- I915_STATE_WARN(i915, !pll->on && pll->active_mask,
- "%s: pll in active use but not on in sw tracking\n",
- pll->info->name);
- I915_STATE_WARN(i915, pll->on && !pll->active_mask,
- "%s: pll is on but not used by any active pipe\n",
- pll->info->name);
- I915_STATE_WARN(i915, pll->on != active,
- "%s: pll on state mismatch (expected %i, found %i)\n",
- pll->info->name, pll->on, active);
+ INTEL_DISPLAY_STATE_WARN(display, !pll->on && pll->active_mask,
+ "%s: pll in active use but not on in sw tracking\n",
+ pll->info->name);
+ INTEL_DISPLAY_STATE_WARN(display, pll->on && !pll->active_mask,
+ "%s: pll is on but not used by any active pipe\n",
+ pll->info->name);
+ INTEL_DISPLAY_STATE_WARN(display, pll->on != active,
+ "%s: pll on state mismatch (expected %i, found %i)\n",
+ pll->info->name, pll->on, active);
}
if (!crtc) {
- I915_STATE_WARN(i915,
- pll->active_mask & ~pll->state.pipe_mask,
- "%s: more active pll users than references: 0x%x vs 0x%x\n",
- pll->info->name, pll->active_mask, pll->state.pipe_mask);
+ INTEL_DISPLAY_STATE_WARN(display,
+ pll->active_mask & ~pll->state.pipe_mask,
+ "%s: more active pll users than references: 0x%x vs 0x%x\n",
+ pll->info->name, pll->active_mask, pll->state.pipe_mask);
return;
}
@@ -4649,23 +4654,23 @@ verify_single_dpll_state(struct drm_i915_private *i915,
pipe_mask = BIT(crtc->pipe);
if (new_crtc_state->hw.active)
- I915_STATE_WARN(i915, !(pll->active_mask & pipe_mask),
- "%s: pll active mismatch (expected pipe %c in active mask 0x%x)\n",
- pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
+ INTEL_DISPLAY_STATE_WARN(display, !(pll->active_mask & pipe_mask),
+ "%s: pll active mismatch (expected pipe %c in active mask 0x%x)\n",
+ pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
else
- I915_STATE_WARN(i915, pll->active_mask & pipe_mask,
- "%s: pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n",
- pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
+ INTEL_DISPLAY_STATE_WARN(display, pll->active_mask & pipe_mask,
+ "%s: pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n",
+ pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
- I915_STATE_WARN(i915, !(pll->state.pipe_mask & pipe_mask),
- "%s: pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
- pll->info->name, pipe_mask, pll->state.pipe_mask);
+ INTEL_DISPLAY_STATE_WARN(display, !(pll->state.pipe_mask & pipe_mask),
+ "%s: pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
+ pll->info->name, pipe_mask, pll->state.pipe_mask);
- I915_STATE_WARN(i915,
- pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
- sizeof(dpll_hw_state)),
- "%s: pll hw state mismatch\n",
- pll->info->name);
+ INTEL_DISPLAY_STATE_WARN(display,
+ pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
+ sizeof(dpll_hw_state)),
+ "%s: pll hw state mismatch\n",
+ pll->info->name);
}
static bool has_alt_port_dpll(const struct intel_shared_dpll *old_pll,
@@ -4678,6 +4683,7 @@ static bool has_alt_port_dpll(const struct intel_shared_dpll *old_pll,
void intel_shared_dpll_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
@@ -4693,16 +4699,16 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state,
u8 pipe_mask = BIT(crtc->pipe);
struct intel_shared_dpll *pll = old_crtc_state->shared_dpll;
- I915_STATE_WARN(i915, pll->active_mask & pipe_mask,
- "%s: pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n",
- pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
+ INTEL_DISPLAY_STATE_WARN(display, pll->active_mask & pipe_mask,
+ "%s: pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n",
+ pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
/* TC ports have both MG/TC and TBT PLL referenced simultaneously */
- I915_STATE_WARN(i915, !has_alt_port_dpll(old_crtc_state->shared_dpll,
- new_crtc_state->shared_dpll) &&
- pll->state.pipe_mask & pipe_mask,
- "%s: pll enabled crtcs mismatch (found pipe %c in enabled mask (0x%x))\n",
- pll->info->name, pipe_name(crtc->pipe), pll->state.pipe_mask);
+ INTEL_DISPLAY_STATE_WARN(display, !has_alt_port_dpll(old_crtc_state->shared_dpll,
+ new_crtc_state->shared_dpll) &&
+ pll->state.pipe_mask & pipe_mask,
+ "%s: pll enabled crtcs mismatch (found pipe %c in enabled mask (0x%x))\n",
+ pll->info->name, pipe_name(crtc->pipe), pll->state.pipe_mask);
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index f0e3be0fe420..e8129a720210 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -323,6 +323,7 @@ enum {
static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv,
int gpio, bool value)
{
+ struct intel_display *display = &dev_priv->display;
int index;
if (drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 11 && gpio >= MIPI_RESET_2))
@@ -367,7 +368,7 @@ static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv,
case MIPI_AVEE_EN_2:
index = gpio == MIPI_AVEE_EN_1 ? 1 : 2;
- intel_de_rmw(dev_priv, GPIO(dev_priv, index),
+ intel_de_rmw(display, GPIO(display, index),
GPIO_CLOCK_VAL_OUT,
GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_DIR_OUT |
GPIO_CLOCK_VAL_MASK | (value ? GPIO_CLOCK_VAL_OUT : 0));
@@ -376,7 +377,7 @@ static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv,
case MIPI_VIO_EN_2:
index = gpio == MIPI_VIO_EN_1 ? 1 : 2;
- intel_de_rmw(dev_priv, GPIO(dev_priv, index),
+ intel_de_rmw(display, GPIO(display, index),
GPIO_DATA_VAL_OUT,
GPIO_DATA_DIR_MASK | GPIO_DATA_DIR_OUT |
GPIO_DATA_VAL_MASK | (value ? GPIO_DATA_VAL_OUT : 0));
diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c
index 9508ceae0d84..2d5ffb37eac9 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo.c
+++ b/drivers/gpu/drm/i915/display/intel_dvo.c
@@ -417,6 +417,7 @@ static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv,
struct intel_dvo *intel_dvo,
const struct intel_dvo_device *dvo)
{
+ struct intel_display *display = &dev_priv->display;
struct i2c_adapter *i2c;
u32 dpll[I915_MAX_PIPES];
enum pipe pipe;
@@ -428,7 +429,7 @@ static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv,
* special cases, but otherwise default to what's defined
* in the spec.
*/
- if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio))
+ if (intel_gmbus_is_valid_pin(display, dvo->gpio))
gpio = dvo->gpio;
else if (dvo->type == INTEL_DVO_CHIP_LVDS)
gpio = GMBUS_PIN_SSC;
@@ -440,7 +441,7 @@ static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv,
* It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA).
*/
- i2c = intel_gmbus_get_adapter(dev_priv, gpio);
+ i2c = intel_gmbus_get_adapter(display, gpio);
intel_dvo->dev = *dvo;
@@ -489,6 +490,7 @@ static bool intel_dvo_probe(struct drm_i915_private *i915,
void intel_dvo_init(struct drm_i915_private *i915)
{
+ struct intel_display *display = &i915->display;
struct intel_connector *connector;
struct intel_encoder *encoder;
struct intel_dvo *intel_dvo;
@@ -549,7 +551,7 @@ void intel_dvo_init(struct drm_i915_private *i915)
drm_connector_init_with_ddc(&i915->drm, &connector->base,
&intel_dvo_connector_funcs,
intel_dvo_connector_type(&intel_dvo->dev),
- intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC));
+ intel_gmbus_get_adapter(display, GMBUS_PIN_DPC));
drm_connector_helper_add(&connector->base,
&intel_dvo_connector_helper_funcs);
diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c
index a7b4cf8b6d50..6a7060889f40 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -349,7 +349,7 @@ static const struct intel_modifier_desc intel_modifiers[] = {
.plane_caps = INTEL_PLANE_CAP_TILING_Y,
}, {
.modifier = I915_FORMAT_MOD_X_TILED,
- .display_ver = DISPLAY_VER_ALL,
+ .display_ver = { 0, 29 },
.plane_caps = INTEL_PLANE_CAP_TILING_X,
}, {
.modifier = DRM_FORMAT_MOD_LINEAR,
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index 2e0863093cff..df05904bac8a 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -1347,7 +1347,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
/* Wa_14016291713 */
if ((IS_DISPLAY_VER(display, 12, 13) ||
- IS_DISPLAY_VER_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0)) &&
+ IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_A0, STEP_C0)) &&
crtc_state->has_psr && !crtc_state->has_panel_replay) {
plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)";
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index 0168894e9cd1..98e1a3606227 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -26,9 +26,10 @@ struct intel_fdi_funcs {
static void assert_fdi_tx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
+ struct intel_display *display = &dev_priv->display;
bool cur_state;
- if (HAS_DDI(dev_priv)) {
+ if (HAS_DDI(display)) {
/*
* DDI does not have a specific FDI_TX register.
*
@@ -36,14 +37,14 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
* so pipe->transcoder cast is fine here.
*/
enum transcoder cpu_transcoder = (enum transcoder)pipe;
- cur_state = intel_de_read(dev_priv,
- TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE;
+ cur_state = intel_de_read(display,
+ TRANS_DDI_FUNC_CTL(display, cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE;
} else {
- cur_state = intel_de_read(dev_priv, FDI_TX_CTL(pipe)) & FDI_TX_ENABLE;
+ cur_state = intel_de_read(display, FDI_TX_CTL(pipe)) & FDI_TX_ENABLE;
}
- I915_STATE_WARN(dev_priv, cur_state != state,
- "FDI TX state assertion failure (expected %s, current %s)\n",
- str_on_off(state), str_on_off(cur_state));
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "FDI TX state assertion failure (expected %s, current %s)\n",
+ str_on_off(state), str_on_off(cur_state));
}
void assert_fdi_tx_enabled(struct drm_i915_private *i915, enum pipe pipe)
@@ -59,12 +60,13 @@ void assert_fdi_tx_disabled(struct drm_i915_private *i915, enum pipe pipe)
static void assert_fdi_rx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
+ struct intel_display *display = &dev_priv->display;
bool cur_state;
- cur_state = intel_de_read(dev_priv, FDI_RX_CTL(pipe)) & FDI_RX_ENABLE;
- I915_STATE_WARN(dev_priv, cur_state != state,
- "FDI RX state assertion failure (expected %s, current %s)\n",
- str_on_off(state), str_on_off(cur_state));
+ cur_state = intel_de_read(display, FDI_RX_CTL(pipe)) & FDI_RX_ENABLE;
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "FDI RX state assertion failure (expected %s, current %s)\n",
+ str_on_off(state), str_on_off(cur_state));
}
void assert_fdi_rx_enabled(struct drm_i915_private *i915, enum pipe pipe)
@@ -80,6 +82,7 @@ void assert_fdi_rx_disabled(struct drm_i915_private *i915, enum pipe pipe)
void assert_fdi_tx_pll_enabled(struct drm_i915_private *i915,
enum pipe pipe)
{
+ struct intel_display *display = &i915->display;
bool cur_state;
/* ILK FDI PLL is always enabled */
@@ -87,23 +90,24 @@ void assert_fdi_tx_pll_enabled(struct drm_i915_private *i915,
return;
/* On Haswell, DDI ports are responsible for the FDI PLL setup */
- if (HAS_DDI(i915))
+ if (HAS_DDI(display))
return;
- cur_state = intel_de_read(i915, FDI_TX_CTL(pipe)) & FDI_TX_PLL_ENABLE;
- I915_STATE_WARN(i915, !cur_state,
- "FDI TX PLL assertion failure, should be active but is disabled\n");
+ cur_state = intel_de_read(display, FDI_TX_CTL(pipe)) & FDI_TX_PLL_ENABLE;
+ INTEL_DISPLAY_STATE_WARN(display, !cur_state,
+ "FDI TX PLL assertion failure, should be active but is disabled\n");
}
static void assert_fdi_rx_pll(struct drm_i915_private *i915,
enum pipe pipe, bool state)
{
+ struct intel_display *display = &i915->display;
bool cur_state;
- cur_state = intel_de_read(i915, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE;
- I915_STATE_WARN(i915, cur_state != state,
- "FDI RX PLL assertion failure (expected %s, current %s)\n",
- str_on_off(state), str_on_off(cur_state));
+ cur_state = intel_de_read(display, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE;
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "FDI RX PLL assertion failure (expected %s, current %s)\n",
+ str_on_off(state), str_on_off(cur_state));
}
void assert_fdi_rx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
index 745ce22afb89..cda1daf4cdea 100644
--- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
@@ -192,35 +192,15 @@ static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
}
}
-static u32
-icl_pipe_status_underrun_mask(struct drm_i915_private *dev_priv)
-{
- u32 mask = PIPE_STATUS_UNDERRUN;
-
- if (DISPLAY_VER(dev_priv) >= 13)
- mask |= PIPE_STATUS_SOFT_UNDERRUN_XELPD |
- PIPE_STATUS_HARD_UNDERRUN_XELPD |
- PIPE_STATUS_PORT_UNDERRUN_XELPD;
-
- return mask;
-}
-
static void bdw_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- u32 mask = gen8_de_pipe_underrun_mask(dev_priv);
-
- if (enable) {
- if (DISPLAY_VER(dev_priv) >= 11)
- intel_de_write(dev_priv,
- ICL_PIPESTATUS(dev_priv, pipe),
- icl_pipe_status_underrun_mask(dev_priv));
- bdw_enable_pipe_irq(dev_priv, pipe, mask);
- } else {
- bdw_disable_pipe_irq(dev_priv, pipe, mask);
- }
+ if (enable)
+ bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
+ else
+ bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
}
static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
@@ -404,7 +384,6 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
{
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
- u32 underruns = 0;
/* We may be called too early in init, thanks BIOS! */
if (crtc == NULL)
@@ -415,37 +394,10 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
crtc->cpu_fifo_underrun_disabled)
return;
- /*
- * Starting with display version 11, the PIPE_STAT register records
- * whether an underrun has happened, and on XELPD+, it will also record
- * whether the underrun was soft/hard and whether it was triggered by
- * the downstream port logic. We should clear these bits (which use
- * write-1-to-clear logic) too.
- *
- * Note that although the IIR gives us the same underrun and soft/hard
- * information, PIPE_STAT is the only place we can find out whether
- * the underrun was caused by the downstream port.
- */
- if (DISPLAY_VER(dev_priv) >= 11) {
- underruns = intel_de_read(dev_priv,
- ICL_PIPESTATUS(dev_priv, pipe)) &
- icl_pipe_status_underrun_mask(dev_priv);
- intel_de_write(dev_priv, ICL_PIPESTATUS(dev_priv, pipe),
- underruns);
- }
-
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
trace_intel_cpu_fifo_underrun(display, pipe);
- if (DISPLAY_VER(dev_priv) >= 11)
- drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun: %s%s%s%s\n",
- pipe_name(pipe),
- underruns & PIPE_STATUS_SOFT_UNDERRUN_XELPD ? "soft," : "",
- underruns & PIPE_STATUS_HARD_UNDERRUN_XELPD ? "hard," : "",
- underruns & PIPE_STATUS_PORT_UNDERRUN_XELPD ? "port," : "",
- underruns & PIPE_STATUS_UNDERRUN ? "transcoder," : "");
- else
- drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
+ drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
}
intel_fbc_handle_fifo_underrun_irq(&dev_priv->display);
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index 6470f75106bd..e3d938c7f83e 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -48,7 +48,7 @@ struct intel_gmbus {
u32 reg0;
i915_reg_t gpio_reg;
struct i2c_algo_bit_data bit_algo;
- struct drm_i915_private *i915;
+ struct intel_display *display;
};
enum gmbus_gpio {
@@ -149,9 +149,10 @@ static const struct gmbus_pin gmbus_pins_mtp[] = {
[GMBUS_PIN_12_TC4_ICP] = { "tc4", GPIOM },
};
-static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915,
+static const struct gmbus_pin *get_gmbus_pin(struct intel_display *display,
unsigned int pin)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
const struct gmbus_pin *pins;
size_t size;
@@ -173,7 +174,7 @@ static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915,
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
pins = gmbus_pins_bxt;
size = ARRAY_SIZE(gmbus_pins_bxt);
- } else if (DISPLAY_VER(i915) == 9) {
+ } else if (DISPLAY_VER(display) == 9) {
pins = gmbus_pins_skl;
size = ARRAY_SIZE(gmbus_pins_skl);
} else if (IS_BROADWELL(i915)) {
@@ -190,9 +191,9 @@ static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915,
return &pins[pin];
}
-bool intel_gmbus_is_valid_pin(struct drm_i915_private *i915, unsigned int pin)
+bool intel_gmbus_is_valid_pin(struct intel_display *display, unsigned int pin)
{
- return get_gmbus_pin(i915, pin);
+ return get_gmbus_pin(display, pin);
}
/* Intel GPIO access functions */
@@ -206,42 +207,45 @@ to_intel_gmbus(struct i2c_adapter *i2c)
}
void
-intel_gmbus_reset(struct drm_i915_private *i915)
+intel_gmbus_reset(struct intel_display *display)
{
- intel_de_write(i915, GMBUS0(i915), 0);
- intel_de_write(i915, GMBUS4(i915), 0);
+ intel_de_write(display, GMBUS0(display), 0);
+ intel_de_write(display, GMBUS4(display), 0);
}
-static void pnv_gmbus_clock_gating(struct drm_i915_private *i915,
+static void pnv_gmbus_clock_gating(struct intel_display *display,
bool enable)
{
/* When using bit bashing for I2C, this bit needs to be set to 1 */
- intel_de_rmw(i915, DSPCLK_GATE_D(i915), PNV_GMBUSUNIT_CLOCK_GATE_DISABLE,
+ intel_de_rmw(display, DSPCLK_GATE_D(display),
+ PNV_GMBUSUNIT_CLOCK_GATE_DISABLE,
!enable ? PNV_GMBUSUNIT_CLOCK_GATE_DISABLE : 0);
}
-static void pch_gmbus_clock_gating(struct drm_i915_private *i915,
+static void pch_gmbus_clock_gating(struct intel_display *display,
bool enable)
{
- intel_de_rmw(i915, SOUTH_DSPCLK_GATE_D, PCH_GMBUSUNIT_CLOCK_GATE_DISABLE,
+ intel_de_rmw(display, SOUTH_DSPCLK_GATE_D,
+ PCH_GMBUSUNIT_CLOCK_GATE_DISABLE,
!enable ? PCH_GMBUSUNIT_CLOCK_GATE_DISABLE : 0);
}
-static void bxt_gmbus_clock_gating(struct drm_i915_private *i915,
+static void bxt_gmbus_clock_gating(struct intel_display *display,
bool enable)
{
- intel_de_rmw(i915, GEN9_CLKGATE_DIS_4, BXT_GMBUS_GATING_DIS,
+ intel_de_rmw(display, GEN9_CLKGATE_DIS_4, BXT_GMBUS_GATING_DIS,
!enable ? BXT_GMBUS_GATING_DIS : 0);
}
static u32 get_reserved(struct intel_gmbus *bus)
{
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
+ struct drm_i915_private *i915 = to_i915(display->drm);
u32 reserved = 0;
/* On most chips, these bits must be preserved in software. */
if (!IS_I830(i915) && !IS_I845G(i915))
- reserved = intel_de_read_notrace(i915, bus->gpio_reg) &
+ reserved = intel_de_read_notrace(display, bus->gpio_reg) &
(GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE);
return reserved;
@@ -250,31 +254,31 @@ static u32 get_reserved(struct intel_gmbus *bus)
static int get_clock(void *data)
{
struct intel_gmbus *bus = data;
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
u32 reserved = get_reserved(bus);
- intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK);
- intel_de_write_notrace(i915, bus->gpio_reg, reserved);
+ intel_de_write_notrace(display, bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK);
+ intel_de_write_notrace(display, bus->gpio_reg, reserved);
- return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0;
+ return (intel_de_read_notrace(display, bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0;
}
static int get_data(void *data)
{
struct intel_gmbus *bus = data;
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
u32 reserved = get_reserved(bus);
- intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK);
- intel_de_write_notrace(i915, bus->gpio_reg, reserved);
+ intel_de_write_notrace(display, bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK);
+ intel_de_write_notrace(display, bus->gpio_reg, reserved);
- return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0;
+ return (intel_de_read_notrace(display, bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0;
}
static void set_clock(void *data, int state_high)
{
struct intel_gmbus *bus = data;
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
u32 reserved = get_reserved(bus);
u32 clock_bits;
@@ -284,14 +288,14 @@ static void set_clock(void *data, int state_high)
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
GPIO_CLOCK_VAL_MASK;
- intel_de_write_notrace(i915, bus->gpio_reg, reserved | clock_bits);
- intel_de_posting_read(i915, bus->gpio_reg);
+ intel_de_write_notrace(display, bus->gpio_reg, reserved | clock_bits);
+ intel_de_posting_read(display, bus->gpio_reg);
}
static void set_data(void *data, int state_high)
{
struct intel_gmbus *bus = data;
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
u32 reserved = get_reserved(bus);
u32 data_bits;
@@ -301,20 +305,21 @@ static void set_data(void *data, int state_high)
data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
GPIO_DATA_VAL_MASK;
- intel_de_write_notrace(i915, bus->gpio_reg, reserved | data_bits);
- intel_de_posting_read(i915, bus->gpio_reg);
+ intel_de_write_notrace(display, bus->gpio_reg, reserved | data_bits);
+ intel_de_posting_read(display, bus->gpio_reg);
}
static int
intel_gpio_pre_xfer(struct i2c_adapter *adapter)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
+ struct drm_i915_private *i915 = to_i915(display->drm);
- intel_gmbus_reset(i915);
+ intel_gmbus_reset(display);
if (IS_PINEVIEW(i915))
- pnv_gmbus_clock_gating(i915, false);
+ pnv_gmbus_clock_gating(display, false);
set_data(bus, 1);
set_clock(bus, 1);
@@ -326,13 +331,14 @@ static void
intel_gpio_post_xfer(struct i2c_adapter *adapter)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
+ struct drm_i915_private *i915 = to_i915(display->drm);
set_data(bus, 1);
set_clock(bus, 1);
if (IS_PINEVIEW(i915))
- pnv_gmbus_clock_gating(i915, true);
+ pnv_gmbus_clock_gating(display, true);
}
static void
@@ -355,16 +361,17 @@ intel_gpio_setup(struct intel_gmbus *bus, i915_reg_t gpio_reg)
algo->data = bus;
}
-static bool has_gmbus_irq(struct drm_i915_private *i915)
+static bool has_gmbus_irq(struct intel_display *display)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
/*
* encoder->shutdown() may want to use GMBUS
* after irqs have already been disabled.
*/
- return HAS_GMBUS_IRQ(i915) && intel_irqs_enabled(i915);
+ return HAS_GMBUS_IRQ(display) && intel_irqs_enabled(i915);
}
-static int gmbus_wait(struct drm_i915_private *i915, u32 status, u32 irq_en)
+static int gmbus_wait(struct intel_display *display, u32 status, u32 irq_en)
{
DEFINE_WAIT(wait);
u32 gmbus2;
@@ -374,21 +381,21 @@ static int gmbus_wait(struct drm_i915_private *i915, u32 status, u32 irq_en)
* we also need to check for NAKs besides the hw ready/idle signal, we
* need to wake up periodically and check that ourselves.
*/
- if (!has_gmbus_irq(i915))
+ if (!has_gmbus_irq(display))
irq_en = 0;
- add_wait_queue(&i915->display.gmbus.wait_queue, &wait);
- intel_de_write_fw(i915, GMBUS4(i915), irq_en);
+ add_wait_queue(&display->gmbus.wait_queue, &wait);
+ intel_de_write_fw(display, GMBUS4(display), irq_en);
status |= GMBUS_SATOER;
- ret = wait_for_us((gmbus2 = intel_de_read_fw(i915, GMBUS2(i915))) & status,
+ ret = wait_for_us((gmbus2 = intel_de_read_fw(display, GMBUS2(display))) & status,
2);
if (ret)
- ret = wait_for((gmbus2 = intel_de_read_fw(i915, GMBUS2(i915))) & status,
+ ret = wait_for((gmbus2 = intel_de_read_fw(display, GMBUS2(display))) & status,
50);
- intel_de_write_fw(i915, GMBUS4(i915), 0);
- remove_wait_queue(&i915->display.gmbus.wait_queue, &wait);
+ intel_de_write_fw(display, GMBUS4(display), 0);
+ remove_wait_queue(&display->gmbus.wait_queue, &wait);
if (gmbus2 & GMBUS_SATOER)
return -ENXIO;
@@ -397,7 +404,7 @@ static int gmbus_wait(struct drm_i915_private *i915, u32 status, u32 irq_en)
}
static int
-gmbus_wait_idle(struct drm_i915_private *i915)
+gmbus_wait_idle(struct intel_display *display)
{
DEFINE_WAIT(wait);
u32 irq_enable;
@@ -405,33 +412,33 @@ gmbus_wait_idle(struct drm_i915_private *i915)
/* Important: The hw handles only the first bit, so set only one! */
irq_enable = 0;
- if (has_gmbus_irq(i915))
+ if (has_gmbus_irq(display))
irq_enable = GMBUS_IDLE_EN;
- add_wait_queue(&i915->display.gmbus.wait_queue, &wait);
- intel_de_write_fw(i915, GMBUS4(i915), irq_enable);
+ add_wait_queue(&display->gmbus.wait_queue, &wait);
+ intel_de_write_fw(display, GMBUS4(display), irq_enable);
- ret = intel_de_wait_fw(i915, GMBUS2(i915), GMBUS_ACTIVE, 0, 10);
+ ret = intel_de_wait_fw(display, GMBUS2(display), GMBUS_ACTIVE, 0, 10);
- intel_de_write_fw(i915, GMBUS4(i915), 0);
- remove_wait_queue(&i915->display.gmbus.wait_queue, &wait);
+ intel_de_write_fw(display, GMBUS4(display), 0);
+ remove_wait_queue(&display->gmbus.wait_queue, &wait);
return ret;
}
-static unsigned int gmbus_max_xfer_size(struct drm_i915_private *i915)
+static unsigned int gmbus_max_xfer_size(struct intel_display *display)
{
- return DISPLAY_VER(i915) >= 9 ? GEN9_GMBUS_BYTE_COUNT_MAX :
+ return DISPLAY_VER(display) >= 9 ? GEN9_GMBUS_BYTE_COUNT_MAX :
GMBUS_BYTE_COUNT_MAX;
}
static int
-gmbus_xfer_read_chunk(struct drm_i915_private *i915,
+gmbus_xfer_read_chunk(struct intel_display *display,
unsigned short addr, u8 *buf, unsigned int len,
u32 gmbus0_reg, u32 gmbus1_index)
{
unsigned int size = len;
- bool burst_read = len > gmbus_max_xfer_size(i915);
+ bool burst_read = len > gmbus_max_xfer_size(display);
bool extra_byte_added = false;
if (burst_read) {
@@ -444,21 +451,21 @@ gmbus_xfer_read_chunk(struct drm_i915_private *i915,
len++;
}
size = len % 256 + 256;
- intel_de_write_fw(i915, GMBUS0(i915),
+ intel_de_write_fw(display, GMBUS0(display),
gmbus0_reg | GMBUS_BYTE_CNT_OVERRIDE);
}
- intel_de_write_fw(i915, GMBUS1(i915),
+ intel_de_write_fw(display, GMBUS1(display),
gmbus1_index | GMBUS_CYCLE_WAIT | (size << GMBUS_BYTE_COUNT_SHIFT) | (addr << GMBUS_SLAVE_ADDR_SHIFT) | GMBUS_SLAVE_READ | GMBUS_SW_RDY);
while (len) {
int ret;
u32 val, loop = 0;
- ret = gmbus_wait(i915, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
+ ret = gmbus_wait(display, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
if (ret)
return ret;
- val = intel_de_read_fw(i915, GMBUS3(i915));
+ val = intel_de_read_fw(display, GMBUS3(display));
do {
if (extra_byte_added && len == 1)
break;
@@ -469,7 +476,7 @@ gmbus_xfer_read_chunk(struct drm_i915_private *i915,
if (burst_read && len == size - 4)
/* Reset the override bit */
- intel_de_write_fw(i915, GMBUS0(i915), gmbus0_reg);
+ intel_de_write_fw(display, GMBUS0(display), gmbus0_reg);
}
return 0;
@@ -486,9 +493,10 @@ gmbus_xfer_read_chunk(struct drm_i915_private *i915,
#define INTEL_GMBUS_BURST_READ_MAX_LEN 767U
static int
-gmbus_xfer_read(struct drm_i915_private *i915, struct i2c_msg *msg,
+gmbus_xfer_read(struct intel_display *display, struct i2c_msg *msg,
u32 gmbus0_reg, u32 gmbus1_index)
{
+ struct drm_i915_private *i915 = to_i915(display->drm);
u8 *buf = msg->buf;
unsigned int rx_size = msg->len;
unsigned int len;
@@ -498,9 +506,9 @@ gmbus_xfer_read(struct drm_i915_private *i915, struct i2c_msg *msg,
if (HAS_GMBUS_BURST_READ(i915))
len = min(rx_size, INTEL_GMBUS_BURST_READ_MAX_LEN);
else
- len = min(rx_size, gmbus_max_xfer_size(i915));
+ len = min(rx_size, gmbus_max_xfer_size(display));
- ret = gmbus_xfer_read_chunk(i915, msg->addr, buf, len,
+ ret = gmbus_xfer_read_chunk(display, msg->addr, buf, len,
gmbus0_reg, gmbus1_index);
if (ret)
return ret;
@@ -513,7 +521,7 @@ gmbus_xfer_read(struct drm_i915_private *i915, struct i2c_msg *msg,
}
static int
-gmbus_xfer_write_chunk(struct drm_i915_private *i915,
+gmbus_xfer_write_chunk(struct intel_display *display,
unsigned short addr, u8 *buf, unsigned int len,
u32 gmbus1_index)
{
@@ -526,8 +534,8 @@ gmbus_xfer_write_chunk(struct drm_i915_private *i915,
len -= 1;
}
- intel_de_write_fw(i915, GMBUS3(i915), val);
- intel_de_write_fw(i915, GMBUS1(i915),
+ intel_de_write_fw(display, GMBUS3(display), val);
+ intel_de_write_fw(display, GMBUS1(display),
gmbus1_index | GMBUS_CYCLE_WAIT | (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | (addr << GMBUS_SLAVE_ADDR_SHIFT) | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
while (len) {
int ret;
@@ -537,9 +545,9 @@ gmbus_xfer_write_chunk(struct drm_i915_private *i915,
val |= *buf++ << (8 * loop);
} while (--len && ++loop < 4);
- intel_de_write_fw(i915, GMBUS3(i915), val);
+ intel_de_write_fw(display, GMBUS3(display), val);
- ret = gmbus_wait(i915, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
+ ret = gmbus_wait(display, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
if (ret)
return ret;
}
@@ -548,7 +556,7 @@ gmbus_xfer_write_chunk(struct drm_i915_private *i915,
}
static int
-gmbus_xfer_write(struct drm_i915_private *i915, struct i2c_msg *msg,
+gmbus_xfer_write(struct intel_display *display, struct i2c_msg *msg,
u32 gmbus1_index)
{
u8 *buf = msg->buf;
@@ -557,9 +565,9 @@ gmbus_xfer_write(struct drm_i915_private *i915, struct i2c_msg *msg,
int ret;
do {
- len = min(tx_size, gmbus_max_xfer_size(i915));
+ len = min(tx_size, gmbus_max_xfer_size(display));
- ret = gmbus_xfer_write_chunk(i915, msg->addr, buf, len,
+ ret = gmbus_xfer_write_chunk(display, msg->addr, buf, len,
gmbus1_index);
if (ret)
return ret;
@@ -586,7 +594,7 @@ gmbus_is_index_xfer(struct i2c_msg *msgs, int i, int num)
}
static int
-gmbus_index_xfer(struct drm_i915_private *i915, struct i2c_msg *msgs,
+gmbus_index_xfer(struct intel_display *display, struct i2c_msg *msgs,
u32 gmbus0_reg)
{
u32 gmbus1_index = 0;
@@ -602,17 +610,17 @@ gmbus_index_xfer(struct drm_i915_private *i915, struct i2c_msg *msgs,
/* GMBUS5 holds 16-bit index */
if (gmbus5)
- intel_de_write_fw(i915, GMBUS5(i915), gmbus5);
+ intel_de_write_fw(display, GMBUS5(display), gmbus5);
if (msgs[1].flags & I2C_M_RD)
- ret = gmbus_xfer_read(i915, &msgs[1], gmbus0_reg,
+ ret = gmbus_xfer_read(display, &msgs[1], gmbus0_reg,
gmbus1_index);
else
- ret = gmbus_xfer_write(i915, &msgs[1], gmbus1_index);
+ ret = gmbus_xfer_write(display, &msgs[1], gmbus1_index);
/* Clear GMBUS5 after each index transfer */
if (gmbus5)
- intel_de_write_fw(i915, GMBUS5(i915), 0);
+ intel_de_write_fw(display, GMBUS5(display), 0);
return ret;
}
@@ -622,34 +630,35 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
u32 gmbus0_source)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
+ struct drm_i915_private *i915 = to_i915(display->drm);
int i = 0, inc, try = 0;
int ret = 0;
/* Display WA #0868: skl,bxt,kbl,cfl,glk */
if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
- bxt_gmbus_clock_gating(i915, false);
+ bxt_gmbus_clock_gating(display, false);
else if (HAS_PCH_SPT(i915) || HAS_PCH_CNP(i915))
- pch_gmbus_clock_gating(i915, false);
+ pch_gmbus_clock_gating(display, false);
retry:
- intel_de_write_fw(i915, GMBUS0(i915), gmbus0_source | bus->reg0);
+ intel_de_write_fw(display, GMBUS0(display), gmbus0_source | bus->reg0);
for (; i < num; i += inc) {
inc = 1;
if (gmbus_is_index_xfer(msgs, i, num)) {
- ret = gmbus_index_xfer(i915, &msgs[i],
+ ret = gmbus_index_xfer(display, &msgs[i],
gmbus0_source | bus->reg0);
inc = 2; /* an index transmission is two msgs */
} else if (msgs[i].flags & I2C_M_RD) {
- ret = gmbus_xfer_read(i915, &msgs[i],
+ ret = gmbus_xfer_read(display, &msgs[i],
gmbus0_source | bus->reg0, 0);
} else {
- ret = gmbus_xfer_write(i915, &msgs[i], 0);
+ ret = gmbus_xfer_write(display, &msgs[i], 0);
}
if (!ret)
- ret = gmbus_wait(i915,
+ ret = gmbus_wait(display,
GMBUS_HW_WAIT_PHASE, GMBUS_HW_WAIT_EN);
if (ret == -ETIMEDOUT)
goto timeout;
@@ -661,19 +670,19 @@ retry:
* a STOP on the very first cycle. To simplify the code we
* unconditionally generate the STOP condition with an additional gmbus
* cycle. */
- intel_de_write_fw(i915, GMBUS1(i915), GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
+ intel_de_write_fw(display, GMBUS1(display), GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
/* Mark the GMBUS interface as disabled after waiting for idle.
* We will re-enable it at the start of the next xfer,
* till then let it sleep.
*/
- if (gmbus_wait_idle(i915)) {
- drm_dbg_kms(&i915->drm,
+ if (gmbus_wait_idle(display)) {
+ drm_dbg_kms(display->drm,
"GMBUS [%s] timed out waiting for idle\n",
adapter->name);
ret = -ETIMEDOUT;
}
- intel_de_write_fw(i915, GMBUS0(i915), 0);
+ intel_de_write_fw(display, GMBUS0(display), 0);
ret = ret ?: i;
goto out;
@@ -692,8 +701,8 @@ clear_err:
* it's slow responding and only answers on the 2nd retry.
*/
ret = -ENXIO;
- if (gmbus_wait_idle(i915)) {
- drm_dbg_kms(&i915->drm,
+ if (gmbus_wait_idle(display)) {
+ drm_dbg_kms(display->drm,
"GMBUS [%s] timed out after NAK\n",
adapter->name);
ret = -ETIMEDOUT;
@@ -703,11 +712,11 @@ clear_err:
* of resetting the GMBUS controller and so clearing the
* BUS_ERROR raised by the target's NAK.
*/
- intel_de_write_fw(i915, GMBUS1(i915), GMBUS_SW_CLR_INT);
- intel_de_write_fw(i915, GMBUS1(i915), 0);
- intel_de_write_fw(i915, GMBUS0(i915), 0);
+ intel_de_write_fw(display, GMBUS1(display), GMBUS_SW_CLR_INT);
+ intel_de_write_fw(display, GMBUS1(display), 0);
+ intel_de_write_fw(display, GMBUS0(display), 0);
- drm_dbg_kms(&i915->drm, "GMBUS [%s] NAK for addr: %04x %c(%d)\n",
+ drm_dbg_kms(display->drm, "GMBUS [%s] NAK for addr: %04x %c(%d)\n",
adapter->name, msgs[i].addr,
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
@@ -718,7 +727,7 @@ clear_err:
* drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
*/
if (ret == -ENXIO && i == 0 && try++ == 0) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"GMBUS [%s] NAK on first message, retry\n",
adapter->name);
goto retry;
@@ -727,10 +736,10 @@ clear_err:
goto out;
timeout:
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
bus->adapter.name, bus->reg0 & 0xff);
- intel_de_write_fw(i915, GMBUS0(i915), 0);
+ intel_de_write_fw(display, GMBUS0(display), 0);
/*
* Hardware may not support GMBUS over these pins? Try GPIO bitbanging
@@ -741,9 +750,9 @@ timeout:
out:
/* Display WA #0868: skl,bxt,kbl,cfl,glk */
if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
- bxt_gmbus_clock_gating(i915, true);
+ bxt_gmbus_clock_gating(display, true);
else if (HAS_PCH_SPT(i915) || HAS_PCH_CNP(i915))
- pch_gmbus_clock_gating(i915, true);
+ pch_gmbus_clock_gating(display, true);
return ret;
}
@@ -752,7 +761,8 @@ static int
gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
+ struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref;
int ret;
@@ -776,7 +786,8 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
+ struct drm_i915_private *i915 = to_i915(display->drm);
u8 cmd = DRM_HDCP_DDC_AKSV;
u8 buf[DRM_HDCP_KSV_LEN] = {};
struct i2c_msg msgs[] = {
@@ -797,7 +808,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
int ret;
wakeref = intel_display_power_get(i915, POWER_DOMAIN_GMBUS);
- mutex_lock(&i915->display.gmbus.mutex);
+ mutex_lock(&display->gmbus.mutex);
/*
* In order to output Aksv to the receiver, use an indexed write to
@@ -806,7 +817,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
*/
ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
- mutex_unlock(&i915->display.gmbus.mutex);
+ mutex_unlock(&display->gmbus.mutex);
intel_display_power_put(i915, POWER_DOMAIN_GMBUS, wakeref);
return ret;
@@ -830,27 +841,27 @@ static void gmbus_lock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
- mutex_lock(&i915->display.gmbus.mutex);
+ mutex_lock(&display->gmbus.mutex);
}
static int gmbus_trylock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
- return mutex_trylock(&i915->display.gmbus.mutex);
+ return mutex_trylock(&display->gmbus.mutex);
}
static void gmbus_unlock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
- mutex_unlock(&i915->display.gmbus.mutex);
+ mutex_unlock(&display->gmbus.mutex);
}
static const struct i2c_lock_operations gmbus_lock_ops = {
@@ -861,31 +872,32 @@ static const struct i2c_lock_operations gmbus_lock_ops = {
/**
* intel_gmbus_setup - instantiate all Intel i2c GMBuses
- * @i915: i915 device private
+ * @display: display device
*/
-int intel_gmbus_setup(struct drm_i915_private *i915)
+int intel_gmbus_setup(struct intel_display *display)
{
- struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+ struct drm_i915_private *i915 = to_i915(display->drm);
+ struct pci_dev *pdev = to_pci_dev(display->drm->dev);
unsigned int pin;
int ret;
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
- i915->display.gmbus.mmio_base = VLV_DISPLAY_BASE;
- else if (!HAS_GMCH(i915))
+ display->gmbus.mmio_base = VLV_DISPLAY_BASE;
+ else if (!HAS_GMCH(display))
/*
* Broxton uses the same PCH offsets for South Display Engine,
* even though it doesn't have a PCH.
*/
- i915->display.gmbus.mmio_base = PCH_DISPLAY_BASE;
+ display->gmbus.mmio_base = PCH_DISPLAY_BASE;
- mutex_init(&i915->display.gmbus.mutex);
- init_waitqueue_head(&i915->display.gmbus.wait_queue);
+ mutex_init(&display->gmbus.mutex);
+ init_waitqueue_head(&display->gmbus.wait_queue);
- for (pin = 0; pin < ARRAY_SIZE(i915->display.gmbus.bus); pin++) {
+ for (pin = 0; pin < ARRAY_SIZE(display->gmbus.bus); pin++) {
const struct gmbus_pin *gmbus_pin;
struct intel_gmbus *bus;
- gmbus_pin = get_gmbus_pin(i915, pin);
+ gmbus_pin = get_gmbus_pin(display, pin);
if (!gmbus_pin)
continue;
@@ -901,7 +913,7 @@ int intel_gmbus_setup(struct drm_i915_private *i915)
"i915 gmbus %s", gmbus_pin->name);
bus->adapter.dev.parent = &pdev->dev;
- bus->i915 = i915;
+ bus->display = display;
bus->adapter.algo = &gmbus_algorithm;
bus->adapter.lock_ops = &gmbus_lock_ops;
@@ -919,7 +931,7 @@ int intel_gmbus_setup(struct drm_i915_private *i915)
if (IS_I830(i915))
bus->force_bit = 1;
- intel_gpio_setup(bus, GPIO(i915, gmbus_pin->gpio));
+ intel_gpio_setup(bus, GPIO(display, gmbus_pin->gpio));
ret = i2c_add_adapter(&bus->adapter);
if (ret) {
@@ -927,43 +939,43 @@ int intel_gmbus_setup(struct drm_i915_private *i915)
goto err;
}
- i915->display.gmbus.bus[pin] = bus;
+ display->gmbus.bus[pin] = bus;
}
- intel_gmbus_reset(i915);
+ intel_gmbus_reset(display);
return 0;
err:
- intel_gmbus_teardown(i915);
+ intel_gmbus_teardown(display);
return ret;
}
-struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *i915,
+struct i2c_adapter *intel_gmbus_get_adapter(struct intel_display *display,
unsigned int pin)
{
- if (drm_WARN_ON(&i915->drm, pin >= ARRAY_SIZE(i915->display.gmbus.bus) ||
- !i915->display.gmbus.bus[pin]))
+ if (drm_WARN_ON(display->drm, pin >= ARRAY_SIZE(display->gmbus.bus) ||
+ !display->gmbus.bus[pin]))
return NULL;
- return &i915->display.gmbus.bus[pin]->adapter;
+ return &display->gmbus.bus[pin]->adapter;
}
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
- struct drm_i915_private *i915 = bus->i915;
+ struct intel_display *display = bus->display;
- mutex_lock(&i915->display.gmbus.mutex);
+ mutex_lock(&display->gmbus.mutex);
bus->force_bit += force_bit ? 1 : -1;
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"%sabling bit-banging on %s. force bit now %d\n",
force_bit ? "en" : "dis", adapter->name,
bus->force_bit);
- mutex_unlock(&i915->display.gmbus.mutex);
+ mutex_unlock(&display->gmbus.mutex);
}
bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
@@ -973,25 +985,25 @@ bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
return bus->force_bit;
}
-void intel_gmbus_teardown(struct drm_i915_private *i915)
+void intel_gmbus_teardown(struct intel_display *display)
{
unsigned int pin;
- for (pin = 0; pin < ARRAY_SIZE(i915->display.gmbus.bus); pin++) {
+ for (pin = 0; pin < ARRAY_SIZE(display->gmbus.bus); pin++) {
struct intel_gmbus *bus;
- bus = i915->display.gmbus.bus[pin];
+ bus = display->gmbus.bus[pin];
if (!bus)
continue;
i2c_del_adapter(&bus->adapter);
kfree(bus);
- i915->display.gmbus.bus[pin] = NULL;
+ display->gmbus.bus[pin] = NULL;
}
}
-void intel_gmbus_irq_handler(struct drm_i915_private *i915)
+void intel_gmbus_irq_handler(struct intel_display *display)
{
- wake_up_all(&i915->display.gmbus.wait_queue);
+ wake_up_all(&display->gmbus.wait_queue);
}
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.h b/drivers/gpu/drm/i915/display/intel_gmbus.h
index 8111eb23e2af..35a200a9efc0 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.h
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.h
@@ -8,8 +8,8 @@
#include <linux/types.h>
-struct drm_i915_private;
struct i2c_adapter;
+struct intel_display;
#define GMBUS_PIN_DISABLED 0
#define GMBUS_PIN_SSC 1
@@ -34,18 +34,17 @@ struct i2c_adapter;
#define GMBUS_NUM_PINS 15 /* including 0 */
-int intel_gmbus_setup(struct drm_i915_private *dev_priv);
-void intel_gmbus_teardown(struct drm_i915_private *dev_priv);
-bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
- unsigned int pin);
+int intel_gmbus_setup(struct intel_display *display);
+void intel_gmbus_teardown(struct intel_display *display);
+bool intel_gmbus_is_valid_pin(struct intel_display *display, unsigned int pin);
int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
struct i2c_adapter *
-intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
+intel_gmbus_get_adapter(struct intel_display *display, unsigned int pin);
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter);
-void intel_gmbus_reset(struct drm_i915_private *dev_priv);
+void intel_gmbus_reset(struct intel_display *display);
-void intel_gmbus_irq_handler(struct drm_i915_private *i915);
+void intel_gmbus_irq_handler(struct intel_display *display);
#endif /* __INTEL_GMBUS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus_regs.h b/drivers/gpu/drm/i915/display/intel_gmbus_regs.h
index 53aacbda983c..59bad1dda6d6 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_gmbus_regs.h
@@ -8,9 +8,9 @@
#include "i915_reg_defs.h"
-#define GMBUS_MMIO_BASE(__i915) ((__i915)->display.gmbus.mmio_base)
+#define __GMBUS_MMIO_BASE(__display) ((__display)->gmbus.mmio_base)
-#define GPIO(__i915, gpio) _MMIO(GMBUS_MMIO_BASE(__i915) + 0x5010 + 4 * (gpio))
+#define GPIO(__display, gpio) _MMIO(__GMBUS_MMIO_BASE(__display) + 0x5010 + 4 * (gpio))
#define GPIO_CLOCK_DIR_MASK (1 << 0)
#define GPIO_CLOCK_DIR_IN (0 << 1)
#define GPIO_CLOCK_DIR_OUT (1 << 1)
@@ -27,7 +27,7 @@
#define GPIO_DATA_PULLUP_DISABLE (1 << 13)
/* clock/port select */
-#define GMBUS0(__i915) _MMIO(GMBUS_MMIO_BASE(__i915) + 0x5100)
+#define GMBUS0(__display) _MMIO(__GMBUS_MMIO_BASE(__display) + 0x5100)
#define GMBUS_AKSV_SELECT (1 << 11)
#define GMBUS_RATE_100KHZ (0 << 8)
#define GMBUS_RATE_50KHZ (1 << 8)
@@ -37,7 +37,7 @@
#define GMBUS_BYTE_CNT_OVERRIDE (1 << 6)
/* command/status */
-#define GMBUS1(__i915) _MMIO(GMBUS_MMIO_BASE(__i915) + 0x5104)
+#define GMBUS1(__display) _MMIO(__GMBUS_MMIO_BASE(__display) + 0x5104)
#define GMBUS_SW_CLR_INT (1 << 31)
#define GMBUS_SW_RDY (1 << 30)
#define GMBUS_ENT (1 << 29) /* enable timeout */
@@ -54,7 +54,7 @@
#define GMBUS_SLAVE_WRITE (0 << 0)
/* status */
-#define GMBUS2(__i915) _MMIO(GMBUS_MMIO_BASE(__i915) + 0x5108)
+#define GMBUS2(__display) _MMIO(__GMBUS_MMIO_BASE(__display) + 0x5108)
#define GMBUS_INUSE (1 << 15)
#define GMBUS_HW_WAIT_PHASE (1 << 14)
#define GMBUS_STALL_TIMEOUT (1 << 13)
@@ -64,10 +64,10 @@
#define GMBUS_ACTIVE (1 << 9)
/* data buffer bytes 3-0 */
-#define GMBUS3(__i915) _MMIO(GMBUS_MMIO_BASE(__i915) + 0x510c)
+#define GMBUS3(__display) _MMIO(__GMBUS_MMIO_BASE(__display) + 0x510c)
/* interrupt mask (Pineview+) */
-#define GMBUS4(__i915) _MMIO(GMBUS_MMIO_BASE(__i915) + 0x5110)
+#define GMBUS4(__display) _MMIO(__GMBUS_MMIO_BASE(__display) + 0x5110)
#define GMBUS_SLAVE_TIMEOUT_EN (1 << 4)
#define GMBUS_NAK_EN (1 << 3)
#define GMBUS_IDLE_EN (1 << 2)
@@ -75,7 +75,7 @@
#define GMBUS_HW_RDY_EN (1 << 0)
/* byte index */
-#define GMBUS5(__i915) _MMIO(GMBUS_MMIO_BASE(__i915) + 0x5120)
+#define GMBUS5(__display) _MMIO(__GMBUS_MMIO_BASE(__display) + 0x5120)
#define GMBUS_2BYTE_INDEX_EN (1 << 31)
#endif /* __INTEL_GMBUS_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index ed6aa87403e2..f57e4dba2873 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -43,11 +43,11 @@ intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder,
return;
if (DISPLAY_VER(display) >= 14) {
- if (IS_DISPLAY_VER_STEP(display, IP_VER(14, 0), STEP_D0, STEP_FOREVER))
+ if (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_D0, STEP_FOREVER))
intel_de_rmw(display, MTL_CHICKEN_TRANS(hdcp->cpu_transcoder),
0, HDCP_LINE_REKEY_DISABLE);
- else if (IS_DISPLAY_VER_STEP(display, IP_VER(14, 1), STEP_B0, STEP_FOREVER) ||
- IS_DISPLAY_VER_STEP(display, IP_VER(20, 0), STEP_B0, STEP_FOREVER))
+ else if (IS_DISPLAY_VERx100_STEP(display, 1401, STEP_B0, STEP_FOREVER) ||
+ IS_DISPLAY_VERx100_STEP(display, 2000, STEP_B0, STEP_FOREVER))
intel_de_rmw(display,
TRANS_DDI_FUNC_CTL(display, hdcp->cpu_transcoder),
0, TRANS_DDI_HDCP_LINE_REKEY_DISABLE);
@@ -1192,10 +1192,10 @@ static void intel_hdcp_prop_work(struct work_struct *work)
drm_connector_put(&connector->base);
}
-bool is_hdcp_supported(struct drm_i915_private *i915, enum port port)
+bool is_hdcp_supported(struct intel_display *display, enum port port)
{
- return DISPLAY_RUNTIME_INFO(i915)->has_hdcp &&
- (DISPLAY_VER(i915) >= 12 || port < PORT_E);
+ return DISPLAY_RUNTIME_INFO(display)->has_hdcp &&
+ (DISPLAY_VER(display) >= 12 || port < PORT_E);
}
static int
@@ -1503,6 +1503,8 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
+ struct intel_digital_port *dig_port =
+ intel_attached_dig_port(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_ake_init ake_init;
@@ -1513,30 +1515,36 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
} msgs;
const struct intel_hdcp_shim *shim = hdcp->shim;
size_t size;
- int ret, i;
+ int ret, i, max_retries;
/* Init for seq_num */
hdcp->seq_num_v = 0;
hdcp->seq_num_m = 0;
+ if (intel_encoder_is_dp(&dig_port->base) ||
+ intel_encoder_is_mst(&dig_port->base))
+ max_retries = 10;
+ else
+ max_retries = 1;
+
ret = hdcp2_prepare_ake_init(connector, &msgs.ake_init);
if (ret < 0)
return ret;
/*
* Retry the first read and write to downstream at least 10 times
- * with a 50ms delay if not hdcp2 capable(dock decides to stop advertising
- * hdcp2 capability for some reason). The reason being that
- * during suspend resume dock usually keeps the HDCP2 registers inaccesible
- * causing AUX error. This wouldn't be a big problem if the userspace
- * just kept retrying with some delay while it continues to play low
- * value content but most userpace applications end up throwing an error
- * when it receives one from KMD. This makes sure we give the dock
- * and the sink devices to complete its power cycle and then try HDCP
- * authentication. The values of 10 and delay of 50ms was decided based
- * on multiple trial and errors.
+ * with a 50ms delay if not hdcp2 capable for DP/DPMST encoders
+ * (dock decides to stop advertising hdcp2 capability for some reason).
+ * The reason being that during suspend resume dock usually keeps the
+ * HDCP2 registers inaccesible causing AUX error. This wouldn't be a
+ * big problem if the userspace just kept retrying with some delay while
+ * it continues to play low value content but most userpace applications
+ * end up throwing an error when it receives one from KMD. This makes
+ * sure we give the dock and the sink devices to complete its power cycle
+ * and then try HDCP authentication. The values of 10 and delay of 50ms
+ * was decided based on multiple trial and errors.
*/
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < max_retries; i++) {
if (!intel_hdcp2_get_capability(connector)) {
msleep(50);
continue;
@@ -2301,9 +2309,9 @@ static int initialize_hdcp_port_data(struct intel_connector *connector,
return 0;
}
-static bool is_hdcp2_supported(struct drm_i915_private *i915)
+static bool is_hdcp2_supported(struct intel_display *display)
{
- struct intel_display *display = to_intel_display(&i915->drm);
+ struct drm_i915_private *i915 = to_i915(display->drm);
if (intel_hdcp_gsc_cs_required(display))
return true;
@@ -2317,12 +2325,11 @@ static bool is_hdcp2_supported(struct drm_i915_private *i915)
IS_COMETLAKE(i915));
}
-void intel_hdcp_component_init(struct drm_i915_private *i915)
+void intel_hdcp_component_init(struct intel_display *display)
{
- struct intel_display *display = to_intel_display(&i915->drm);
int ret;
- if (!is_hdcp2_supported(i915))
+ if (!is_hdcp2_supported(display))
return;
mutex_lock(&display->hdcp.hdcp_mutex);
@@ -2367,19 +2374,18 @@ int intel_hdcp_init(struct intel_connector *connector,
struct intel_digital_port *dig_port,
const struct intel_hdcp_shim *shim)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
if (!shim)
return -EINVAL;
- if (is_hdcp2_supported(i915))
+ if (is_hdcp2_supported(display))
intel_hdcp2_init(connector, dig_port, shim);
- ret =
- drm_connector_attach_content_protection_property(&connector->base,
- hdcp->hdcp2_supported);
+ ret = drm_connector_attach_content_protection_property(&connector->base,
+ hdcp->hdcp2_supported);
if (ret) {
hdcp->hdcp2_supported = false;
kfree(dig_port->hdcp_port_data.streams);
@@ -2432,7 +2438,7 @@ static int _intel_hdcp_enable(struct intel_atomic_state *state,
hdcp->stream_transcoder = INVALID_TRANSCODER;
}
- if (DISPLAY_VER(i915) >= 12)
+ if (DISPLAY_VER(display) >= 12)
dig_port->hdcp_port_data.hdcp_transcoder =
intel_get_hdcp_transcoder(hdcp->cpu_transcoder);
@@ -2583,10 +2589,8 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
_intel_hdcp_enable(state, encoder, crtc_state, conn_state);
}
-void intel_hdcp_component_fini(struct drm_i915_private *i915)
+void intel_hdcp_component_fini(struct intel_display *display)
{
- struct intel_display *display = to_intel_display(&i915->drm);
-
mutex_lock(&display->hdcp.hdcp_mutex);
if (!display->hdcp.comp_added) {
mutex_unlock(&display->hdcp.hdcp_mutex);
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h
index 477f2d2bb120..d99830cfb798 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.h
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.h
@@ -12,13 +12,13 @@
struct drm_connector;
struct drm_connector_state;
-struct drm_i915_private;
struct intel_atomic_state;
struct intel_connector;
struct intel_crtc_state;
+struct intel_digital_port;
+struct intel_display;
struct intel_encoder;
struct intel_hdcp_shim;
-struct intel_digital_port;
enum port;
enum transcoder;
@@ -37,14 +37,14 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
-bool is_hdcp_supported(struct drm_i915_private *i915, enum port port);
+bool is_hdcp_supported(struct intel_display *display, enum port port);
bool intel_hdcp_get_capability(struct intel_connector *connector);
bool intel_hdcp2_get_capability(struct intel_connector *connector);
void intel_hdcp_get_remote_capability(struct intel_connector *connector,
bool *hdcp_capable,
bool *hdcp2_capable);
-void intel_hdcp_component_init(struct drm_i915_private *i915);
-void intel_hdcp_component_fini(struct drm_i915_private *i915);
+void intel_hdcp_component_init(struct intel_display *display);
+void intel_hdcp_component_fini(struct intel_display *display);
void intel_hdcp_cleanup(struct intel_connector *connector);
void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 72ac910bf6ec..c6ce6bb88d7c 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -62,6 +62,7 @@
#include "intel_hdmi.h"
#include "intel_lspcon.h"
#include "intel_panel.h"
+#include "intel_pfit.h"
#include "intel_snps_phy.h"
static void
@@ -1211,6 +1212,30 @@ static void vlv_set_infoframes(struct intel_encoder *encoder,
&crtc_state->infoframes.hdmi);
}
+void intel_hdmi_fastset_infoframes(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ i915_reg_t reg = HSW_TVIDEO_DIP_CTL(display,
+ crtc_state->cpu_transcoder);
+ u32 val = intel_de_read(display, reg);
+
+ if ((crtc_state->infoframes.enable &
+ intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM)) == 0 &&
+ (val & VIDEO_DIP_ENABLE_DRM_GLK) == 0)
+ return;
+
+ val &= ~(VIDEO_DIP_ENABLE_DRM_GLK);
+
+ intel_de_write(display, reg, val);
+ intel_de_posting_read(display, reg);
+
+ intel_write_infoframe(encoder, crtc_state,
+ HDMI_INFOFRAME_TYPE_DRM,
+ &crtc_state->infoframes.drm);
+}
+
static void hsw_set_infoframes(struct intel_encoder *encoder,
bool enable,
const struct intel_crtc_state *crtc_state,
@@ -2917,7 +2942,6 @@ static struct intel_encoder *
get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin)
{
struct intel_display *display = to_intel_display(encoder);
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_encoder *other;
for_each_intel_encoder(display->drm, other) {
@@ -2931,7 +2955,7 @@ get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin)
connector = enc_to_dig_port(other)->hdmi.attached_connector;
- if (connector && connector->base.ddc == intel_gmbus_get_adapter(i915, ddc_pin))
+ if (connector && connector->base.ddc == intel_gmbus_get_adapter(display, ddc_pin))
return other;
}
@@ -2941,7 +2965,6 @@ get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin)
static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_encoder *other;
const char *source;
u8 ddc_pin;
@@ -2954,7 +2977,7 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
source = "platform default";
}
- if (!intel_gmbus_is_valid_pin(i915, ddc_pin)) {
+ if (!intel_gmbus_is_valid_pin(display, ddc_pin)) {
drm_dbg_kms(display->drm,
"[ENCODER:%d:%s] Invalid DDC pin %d\n",
encoder->base.base.id, encoder->base.name, ddc_pin);
@@ -3027,7 +3050,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
struct intel_encoder *intel_encoder = &dig_port->base;
struct drm_device *dev = intel_encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
enum port port = intel_encoder->port;
struct cec_connector_info conn_info;
u8 ddc_pin;
@@ -3052,7 +3074,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
drm_connector_init_with_ddc(dev, connector,
&intel_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
- intel_gmbus_get_adapter(dev_priv, ddc_pin));
+ intel_gmbus_get_adapter(display, ddc_pin));
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
@@ -3077,7 +3099,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
intel_connector_attach_encoder(intel_connector, intel_encoder);
intel_hdmi->attached_connector = intel_connector;
- if (is_hdcp_supported(dev_priv, port)) {
+ if (is_hdcp_supported(display, port)) {
int ret = intel_hdcp_init(intel_connector, dig_port,
&intel_hdmi_hdcp_shim);
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 9b97623665c5..466f48df8a74 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -42,6 +42,9 @@ u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder,
u32 intel_hdmi_infoframe_enable(unsigned int type);
void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
+void intel_hdmi_fastset_infoframes(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state);
void intel_read_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
enum hdmi_infoframe_type type,
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
index 5d055dc9366f..cb64c6f0ad1b 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
@@ -556,6 +556,7 @@ void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
{
+ struct intel_display *display = &dev_priv->display;
u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
u32 pin_mask = 0, long_mask = 0;
@@ -589,11 +590,12 @@ void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
if (pch_iir & SDE_GMBUS_ICP)
- intel_gmbus_irq_handler(dev_priv);
+ intel_gmbus_irq_handler(display);
}
void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
{
+ struct intel_display *display = &dev_priv->display;
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
~SDE_PORTE_HOTPLUG_SPT;
u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
@@ -625,7 +627,7 @@ void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
if (pch_iir & SDE_GMBUS_CPT)
- intel_gmbus_irq_handler(dev_priv);
+ intel_gmbus_irq_handler(display);
}
void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger)
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 5f753ee743c6..6d7637ad980a 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -52,6 +52,7 @@
#include "intel_lvds.h"
#include "intel_lvds_regs.h"
#include "intel_panel.h"
+#include "intel_pfit.h"
#include "intel_pps_regs.h"
/* Private structure for the integrated LVDS support */
@@ -900,7 +901,7 @@ void intel_lvds_init(struct drm_i915_private *i915)
drm_connector_init_with_ddc(&i915->drm, &connector->base,
&intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS,
- intel_gmbus_get_adapter(i915, ddc_pin));
+ intel_gmbus_get_adapter(display, ddc_pin));
drm_encoder_init(&i915->drm, &encoder->base, &intel_lvds_enc_funcs,
DRM_MODE_ENCODER_LVDS, "LVDS");
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 3491db5cad31..bc70e72ccc2e 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -27,6 +27,7 @@ static void intel_connector_verify_state(const struct intel_crtc_state *crtc_sta
const struct drm_connector_state *conn_state)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
+ struct intel_display *display = to_intel_display(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
@@ -35,29 +36,29 @@ static void intel_connector_verify_state(const struct intel_crtc_state *crtc_sta
if (connector->get_hw_state(connector)) {
struct intel_encoder *encoder = intel_attached_encoder(connector);
- I915_STATE_WARN(i915, !crtc_state,
- "connector enabled without attached crtc\n");
+ INTEL_DISPLAY_STATE_WARN(display, !crtc_state,
+ "connector enabled without attached crtc\n");
if (!crtc_state)
return;
- I915_STATE_WARN(i915, !crtc_state->hw.active,
- "connector is active, but attached crtc isn't\n");
+ INTEL_DISPLAY_STATE_WARN(display, !crtc_state->hw.active,
+ "connector is active, but attached crtc isn't\n");
if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)
return;
- I915_STATE_WARN(i915,
- conn_state->best_encoder != &encoder->base,
- "atomic encoder doesn't match attached encoder\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ conn_state->best_encoder != &encoder->base,
+ "atomic encoder doesn't match attached encoder\n");
- I915_STATE_WARN(i915, conn_state->crtc != encoder->base.crtc,
- "attached encoder crtc differs from connector crtc\n");
+ INTEL_DISPLAY_STATE_WARN(display, conn_state->crtc != encoder->base.crtc,
+ "attached encoder crtc differs from connector crtc\n");
} else {
- I915_STATE_WARN(i915, crtc_state && crtc_state->hw.active,
- "attached crtc is active, but connector isn't\n");
- I915_STATE_WARN(i915, !crtc_state && conn_state->best_encoder,
- "best encoder set without crtc!\n");
+ INTEL_DISPLAY_STATE_WARN(display, crtc_state && crtc_state->hw.active,
+ "attached crtc is active, but connector isn't\n");
+ INTEL_DISPLAY_STATE_WARN(display, !crtc_state && conn_state->best_encoder,
+ "best encoder set without crtc!\n");
}
}
@@ -65,6 +66,7 @@ static void
verify_connector_state(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_connector *connector;
const struct drm_connector_state *new_conn_state;
int i;
@@ -81,8 +83,8 @@ verify_connector_state(struct intel_atomic_state *state,
intel_connector_verify_state(crtc_state, new_conn_state);
- I915_STATE_WARN(to_i915(connector->dev), new_conn_state->best_encoder != encoder,
- "connector's atomic encoder doesn't match legacy encoder\n");
+ INTEL_DISPLAY_STATE_WARN(display, new_conn_state->best_encoder != encoder,
+ "connector's atomic encoder doesn't match legacy encoder\n");
}
}
@@ -109,6 +111,7 @@ static void intel_pipe_config_sanity_check(const struct intel_crtc_state *crtc_s
static void
verify_encoder_state(struct intel_atomic_state *state)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_encoder *encoder;
struct drm_connector *connector;
@@ -134,25 +137,25 @@ verify_encoder_state(struct intel_atomic_state *state)
found = true;
enabled = true;
- I915_STATE_WARN(i915,
- new_conn_state->crtc != encoder->base.crtc,
- "connector's crtc doesn't match encoder crtc\n");
+ INTEL_DISPLAY_STATE_WARN(display,
+ new_conn_state->crtc != encoder->base.crtc,
+ "connector's crtc doesn't match encoder crtc\n");
}
if (!found)
continue;
- I915_STATE_WARN(i915, !!encoder->base.crtc != enabled,
- "encoder's enabled state mismatch (expected %i, found %i)\n",
- !!encoder->base.crtc, enabled);
+ INTEL_DISPLAY_STATE_WARN(display, !!encoder->base.crtc != enabled,
+ "encoder's enabled state mismatch (expected %i, found %i)\n",
+ !!encoder->base.crtc, enabled);
if (!encoder->base.crtc) {
bool active;
active = encoder->get_hw_state(encoder, &pipe);
- I915_STATE_WARN(i915, active,
- "encoder detached but still enabled on pipe %c.\n",
- pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display, active,
+ "encoder detached but still enabled on pipe %c.\n",
+ pipe_name(pipe));
}
}
}
@@ -161,8 +164,8 @@ static void
verify_crtc_state(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *i915 = to_i915(dev);
+ struct intel_display *display = to_intel_display(state);
+ struct drm_i915_private *i915 = to_i915(display->drm);
const struct intel_crtc_state *sw_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_crtc_state *hw_crtc_state;
@@ -173,7 +176,7 @@ verify_crtc_state(struct intel_atomic_state *state,
if (!hw_crtc_state)
return;
- drm_dbg_kms(&i915->drm, "[CRTC:%d:%s]\n", crtc->base.base.id,
+ drm_dbg_kms(display->drm, "[CRTC:%d:%s]\n", crtc->base.base.id,
crtc->base.name);
hw_crtc_state->hw.enable = sw_crtc_state->hw.enable;
@@ -184,30 +187,30 @@ verify_crtc_state(struct intel_atomic_state *state,
if (IS_I830(i915) && hw_crtc_state->hw.active)
hw_crtc_state->hw.active = sw_crtc_state->hw.active;
- I915_STATE_WARN(i915,
- sw_crtc_state->hw.active != hw_crtc_state->hw.active,
- "crtc active state doesn't match with hw state (expected %i, found %i)\n",
- sw_crtc_state->hw.active, hw_crtc_state->hw.active);
+ INTEL_DISPLAY_STATE_WARN(display,
+ sw_crtc_state->hw.active != hw_crtc_state->hw.active,
+ "crtc active state doesn't match with hw state (expected %i, found %i)\n",
+ sw_crtc_state->hw.active, hw_crtc_state->hw.active);
- I915_STATE_WARN(i915, crtc->active != sw_crtc_state->hw.active,
- "transitional active state does not match atomic hw state (expected %i, found %i)\n",
- sw_crtc_state->hw.active, crtc->active);
+ INTEL_DISPLAY_STATE_WARN(display, crtc->active != sw_crtc_state->hw.active,
+ "transitional active state does not match atomic hw state (expected %i, found %i)\n",
+ sw_crtc_state->hw.active, crtc->active);
primary_crtc = intel_primary_crtc(sw_crtc_state);
- for_each_encoder_on_crtc(dev, &primary_crtc->base, encoder) {
+ for_each_encoder_on_crtc(display->drm, &primary_crtc->base, encoder) {
enum pipe pipe;
bool active;
active = encoder->get_hw_state(encoder, &pipe);
- I915_STATE_WARN(i915, active != sw_crtc_state->hw.active,
- "[ENCODER:%i] active %i with crtc active %i\n",
- encoder->base.base.id, active,
- sw_crtc_state->hw.active);
+ INTEL_DISPLAY_STATE_WARN(display, active != sw_crtc_state->hw.active,
+ "[ENCODER:%i] active %i with crtc active %i\n",
+ encoder->base.base.id, active,
+ sw_crtc_state->hw.active);
- I915_STATE_WARN(i915, active && primary_crtc->pipe != pipe,
- "Encoder connected to wrong pipe %c\n",
- pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display, active && primary_crtc->pipe != pipe,
+ "Encoder connected to wrong pipe %c\n",
+ pipe_name(pipe));
if (active)
intel_encoder_get_config(encoder, hw_crtc_state);
@@ -220,7 +223,7 @@ verify_crtc_state(struct intel_atomic_state *state,
if (!intel_pipe_config_compare(sw_crtc_state,
hw_crtc_state, false)) {
- I915_STATE_WARN(i915, 1, "pipe state doesn't match!\n");
+ INTEL_DISPLAY_STATE_WARN(display, 1, "pipe state doesn't match!\n");
intel_crtc_state_dump(hw_crtc_state, NULL, "hw state");
intel_crtc_state_dump(sw_crtc_state, NULL, "sw state");
}
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 71454ddef20f..313bd3f35ace 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -33,22 +33,19 @@
#include <drm/drm_edid.h>
-#include "i915_reg.h"
+#include "i915_drv.h"
#include "intel_backlight.h"
#include "intel_connector.h"
-#include "intel_de.h"
+#include "intel_display_core.h"
#include "intel_display_driver.h"
#include "intel_display_types.h"
#include "intel_drrs.h"
-#include "intel_lvds_regs.h"
#include "intel_panel.h"
#include "intel_quirks.h"
#include "intel_vrr.h"
-bool intel_panel_use_ssc(struct drm_i915_private *i915)
+bool intel_panel_use_ssc(struct intel_display *display)
{
- struct intel_display *display = &i915->display;
-
if (display->params.panel_use_ssc >= 0)
return display->params.panel_use_ssc != 0;
return display->vbt.lvds_use_ssc &&
@@ -252,7 +249,7 @@ int intel_panel_compute_config(struct intel_connector *connector,
static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector)
{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
const struct drm_display_mode *preferred_mode =
intel_panel_preferred_fixed_mode(connector);
struct drm_display_mode *mode, *next;
@@ -261,7 +258,7 @@ static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connect
if (!is_alt_fixed_mode(mode, preferred_mode))
continue;
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] using alternate EDID fixed mode: " DRM_MODE_FMT "\n",
connector->base.base.id, connector->base.name,
DRM_MODE_ARG(mode));
@@ -272,7 +269,7 @@ static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connect
static void intel_panel_add_edid_preferred_mode(struct intel_connector *connector)
{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct drm_display_mode *scan, *fixed_mode = NULL;
if (list_empty(&connector->base.probed_modes))
@@ -290,7 +287,7 @@ static void intel_panel_add_edid_preferred_mode(struct intel_connector *connecto
fixed_mode = list_first_entry(&connector->base.probed_modes,
typeof(*fixed_mode), head);
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] using %s EDID fixed mode: " DRM_MODE_FMT "\n",
connector->base.base.id, connector->base.name,
fixed_mode->type & DRM_MODE_TYPE_PREFERRED ? "preferred" : "first",
@@ -303,16 +300,16 @@ static void intel_panel_add_edid_preferred_mode(struct intel_connector *connecto
static void intel_panel_destroy_probed_modes(struct intel_connector *connector)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct drm_display_mode *mode, *next;
list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] not using EDID mode: " DRM_MODE_FMT "\n",
connector->base.base.id, connector->base.name,
DRM_MODE_ARG(mode));
list_del(&mode->head);
- drm_mode_destroy(&i915->drm, mode);
+ drm_mode_destroy(display->drm, mode);
}
}
@@ -329,7 +326,7 @@ static void intel_panel_add_fixed_mode(struct intel_connector *connector,
struct drm_display_mode *fixed_mode,
const char *type)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct drm_display_info *info = &connector->base.display_info;
if (!fixed_mode)
@@ -340,7 +337,7 @@ static void intel_panel_add_fixed_mode(struct intel_connector *connector,
info->width_mm = fixed_mode->width_mm;
info->height_mm = fixed_mode->height_mm;
- drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n",
+ drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n",
connector->base.base.id, connector->base.name, type,
DRM_MODE_ARG(fixed_mode));
@@ -349,7 +346,7 @@ static void intel_panel_add_fixed_mode(struct intel_connector *connector,
void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
const struct drm_display_mode *mode;
mode = connector->panel.vbt.lfp_vbt_mode;
@@ -357,13 +354,13 @@ void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector)
return;
intel_panel_add_fixed_mode(connector,
- drm_mode_duplicate(&i915->drm, mode),
+ drm_mode_duplicate(display->drm, mode),
"VBT LFP");
}
void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
const struct drm_display_mode *mode;
mode = connector->panel.vbt.sdvo_lvds_vbt_mode;
@@ -371,7 +368,7 @@ void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector)
return;
intel_panel_add_fixed_mode(connector,
- drm_mode_duplicate(&i915->drm, mode),
+ drm_mode_duplicate(display->drm, mode),
"VBT SDVO");
}
@@ -383,301 +380,6 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
"current (BIOS)");
}
-/* adjusted_mode has been preset to be the panel's fixed mode */
-static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state)
-{
- const struct drm_display_mode *adjusted_mode =
- &crtc_state->hw.adjusted_mode;
- int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
- int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
- int x, y, width, height;
-
- /* Native modes don't need fitting */
- if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
- adjusted_mode->crtc_vdisplay == pipe_src_h &&
- crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
- return 0;
-
- switch (conn_state->scaling_mode) {
- case DRM_MODE_SCALE_CENTER:
- width = pipe_src_w;
- height = pipe_src_h;
- x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
- y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
- break;
-
- case DRM_MODE_SCALE_ASPECT:
- /* Scale but preserve the aspect ratio */
- {
- u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
- u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
- if (scaled_width > scaled_height) { /* pillar */
- width = scaled_height / pipe_src_h;
- if (width & 1)
- width++;
- x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
- y = 0;
- height = adjusted_mode->crtc_vdisplay;
- } else if (scaled_width < scaled_height) { /* letter */
- height = scaled_width / pipe_src_w;
- if (height & 1)
- height++;
- y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
- x = 0;
- width = adjusted_mode->crtc_hdisplay;
- } else {
- x = y = 0;
- width = adjusted_mode->crtc_hdisplay;
- height = adjusted_mode->crtc_vdisplay;
- }
- }
- break;
-
- case DRM_MODE_SCALE_NONE:
- WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w);
- WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h);
- fallthrough;
- case DRM_MODE_SCALE_FULLSCREEN:
- x = y = 0;
- width = adjusted_mode->crtc_hdisplay;
- height = adjusted_mode->crtc_vdisplay;
- break;
-
- default:
- MISSING_CASE(conn_state->scaling_mode);
- return -EINVAL;
- }
-
- drm_rect_init(&crtc_state->pch_pfit.dst,
- x, y, width, height);
- crtc_state->pch_pfit.enabled = true;
-
- return 0;
-}
-
-static void
-centre_horizontally(struct drm_display_mode *adjusted_mode,
- int width)
-{
- u32 border, sync_pos, blank_width, sync_width;
-
- /* keep the hsync and hblank widths constant */
- sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
- blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
- sync_pos = (blank_width - sync_width + 1) / 2;
-
- border = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
- border += border & 1; /* make the border even */
-
- adjusted_mode->crtc_hdisplay = width;
- adjusted_mode->crtc_hblank_start = width + border;
- adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width;
-
- adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos;
- adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width;
-}
-
-static void
-centre_vertically(struct drm_display_mode *adjusted_mode,
- int height)
-{
- u32 border, sync_pos, blank_width, sync_width;
-
- /* keep the vsync and vblank widths constant */
- sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
- blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start;
- sync_pos = (blank_width - sync_width + 1) / 2;
-
- border = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
-
- adjusted_mode->crtc_vdisplay = height;
- adjusted_mode->crtc_vblank_start = height + border;
- adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width;
-
- adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos;
- adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width;
-}
-
-static u32 panel_fitter_scaling(u32 source, u32 target)
-{
- /*
- * Floating point operation is not supported. So the FACTOR
- * is defined, which can avoid the floating point computation
- * when calculating the panel ratio.
- */
-#define ACCURACY 12
-#define FACTOR (1 << ACCURACY)
- u32 ratio = source * FACTOR / target;
- return (FACTOR * ratio + FACTOR/2) / FACTOR;
-}
-
-static void i965_scale_aspect(struct intel_crtc_state *crtc_state,
- u32 *pfit_control)
-{
- const struct drm_display_mode *adjusted_mode =
- &crtc_state->hw.adjusted_mode;
- int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
- int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
- u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
- u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
-
- /* 965+ is easy, it does everything in hw */
- if (scaled_width > scaled_height)
- *pfit_control |= PFIT_ENABLE |
- PFIT_SCALING_PILLAR;
- else if (scaled_width < scaled_height)
- *pfit_control |= PFIT_ENABLE |
- PFIT_SCALING_LETTER;
- else if (adjusted_mode->crtc_hdisplay != pipe_src_w)
- *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
-}
-
-static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
- u32 *pfit_control, u32 *pfit_pgm_ratios,
- u32 *border)
-{
- struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
- int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
- int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
- u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
- u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
- u32 bits;
-
- /*
- * For earlier chips we have to calculate the scaling
- * ratio by hand and program it into the
- * PFIT_PGM_RATIO register
- */
- if (scaled_width > scaled_height) { /* pillar */
- centre_horizontally(adjusted_mode,
- scaled_height / pipe_src_h);
-
- *border = LVDS_BORDER_ENABLE;
- if (pipe_src_h != adjusted_mode->crtc_vdisplay) {
- bits = panel_fitter_scaling(pipe_src_h,
- adjusted_mode->crtc_vdisplay);
-
- *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) |
- PFIT_VERT_SCALE(bits));
- *pfit_control |= (PFIT_ENABLE |
- PFIT_VERT_INTERP_BILINEAR |
- PFIT_HORIZ_INTERP_BILINEAR);
- }
- } else if (scaled_width < scaled_height) { /* letter */
- centre_vertically(adjusted_mode,
- scaled_width / pipe_src_w);
-
- *border = LVDS_BORDER_ENABLE;
- if (pipe_src_w != adjusted_mode->crtc_hdisplay) {
- bits = panel_fitter_scaling(pipe_src_w,
- adjusted_mode->crtc_hdisplay);
-
- *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) |
- PFIT_VERT_SCALE(bits));
- *pfit_control |= (PFIT_ENABLE |
- PFIT_VERT_INTERP_BILINEAR |
- PFIT_HORIZ_INTERP_BILINEAR);
- }
- } else {
- /* Aspects match, Let hw scale both directions */
- *pfit_control |= (PFIT_ENABLE |
- PFIT_VERT_AUTO_SCALE |
- PFIT_HORIZ_AUTO_SCALE |
- PFIT_VERT_INTERP_BILINEAR |
- PFIT_HORIZ_INTERP_BILINEAR);
- }
-}
-
-static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
- struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
- int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
- int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
-
- /* Native modes don't need fitting */
- if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
- adjusted_mode->crtc_vdisplay == pipe_src_h)
- goto out;
-
- switch (conn_state->scaling_mode) {
- case DRM_MODE_SCALE_CENTER:
- /*
- * For centered modes, we have to calculate border widths &
- * heights and modify the values programmed into the CRTC.
- */
- centre_horizontally(adjusted_mode, pipe_src_w);
- centre_vertically(adjusted_mode, pipe_src_h);
- border = LVDS_BORDER_ENABLE;
- break;
- case DRM_MODE_SCALE_ASPECT:
- /* Scale but preserve the aspect ratio */
- if (DISPLAY_VER(dev_priv) >= 4)
- i965_scale_aspect(crtc_state, &pfit_control);
- else
- i9xx_scale_aspect(crtc_state, &pfit_control,
- &pfit_pgm_ratios, &border);
- break;
- case DRM_MODE_SCALE_FULLSCREEN:
- /*
- * Full scaling, even if it changes the aspect ratio.
- * Fortunately this is all done for us in hw.
- */
- if (pipe_src_h != adjusted_mode->crtc_vdisplay ||
- pipe_src_w != adjusted_mode->crtc_hdisplay) {
- pfit_control |= PFIT_ENABLE;
- if (DISPLAY_VER(dev_priv) >= 4)
- pfit_control |= PFIT_SCALING_AUTO;
- else
- pfit_control |= (PFIT_VERT_AUTO_SCALE |
- PFIT_VERT_INTERP_BILINEAR |
- PFIT_HORIZ_AUTO_SCALE |
- PFIT_HORIZ_INTERP_BILINEAR);
- }
- break;
- default:
- MISSING_CASE(conn_state->scaling_mode);
- return -EINVAL;
- }
-
- /* 965+ wants fuzzy fitting */
- /* FIXME: handle multiple panels by failing gracefully */
- if (DISPLAY_VER(dev_priv) >= 4)
- pfit_control |= PFIT_PIPE(crtc->pipe) | PFIT_FILTER_FUZZY;
-
-out:
- if ((pfit_control & PFIT_ENABLE) == 0) {
- pfit_control = 0;
- pfit_pgm_ratios = 0;
- }
-
- /* Make sure pre-965 set dither correctly for 18bpp panels. */
- if (DISPLAY_VER(dev_priv) < 4 && crtc_state->pipe_bpp == 18)
- pfit_control |= PFIT_PANEL_8TO6_DITHER_ENABLE;
-
- crtc_state->gmch_pfit.control = pfit_control;
- crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
- crtc_state->gmch_pfit.lvds_border_bits = border;
-
- return 0;
-}
-
-int intel_panel_fitting(struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
-
- if (HAS_GMCH(i915))
- return gmch_panel_fitting(crtc_state, conn_state);
- else
- return pch_panel_fitting(crtc_state, conn_state);
-}
-
enum drm_connector_status
intel_panel_detect(struct drm_connector *connector, bool force)
{
diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h
index 15a8c897b33f..b60d12322e5d 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.h
+++ b/drivers/gpu/drm/i915/display/intel_panel.h
@@ -14,9 +14,9 @@ struct drm_connector;
struct drm_connector_state;
struct drm_display_mode;
struct drm_edid;
-struct drm_i915_private;
struct intel_connector;
struct intel_crtc_state;
+struct intel_display;
struct intel_encoder;
void intel_panel_init_alloc(struct intel_connector *connector);
@@ -25,7 +25,7 @@ int intel_panel_init(struct intel_connector *connector,
void intel_panel_fini(struct intel_connector *connector);
enum drm_connector_status
intel_panel_detect(struct drm_connector *connector, bool force);
-bool intel_panel_use_ssc(struct drm_i915_private *i915);
+bool intel_panel_use_ssc(struct intel_display *display);
const struct drm_display_mode *
intel_panel_preferred_fixed_mode(struct intel_connector *connector);
const struct drm_display_mode *
@@ -42,8 +42,6 @@ enum drrs_type intel_panel_drrs_type(struct intel_connector *connector);
enum drm_mode_status
intel_panel_mode_valid(struct intel_connector *connector,
const struct drm_display_mode *mode);
-int intel_panel_fitting(struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state);
int intel_panel_compute_config(struct intel_connector *connector,
struct drm_display_mode *adjusted_mode);
void intel_panel_add_edid_fixed_modes(struct intel_connector *connector,
diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c
index f13ab680c2cf..4210de87a0a2 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_display.c
+++ b/drivers/gpu/drm/i915/display/intel_pch_display.c
@@ -39,58 +39,61 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe, enum port port,
i915_reg_t dp_reg)
{
+ struct intel_display *display = &dev_priv->display;
enum pipe port_pipe;
bool state;
state = g4x_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe);
- I915_STATE_WARN(dev_priv, state && port_pipe == pipe,
- "PCH DP %c enabled on transcoder %c, should be disabled\n",
- port_name(port), pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display, state && port_pipe == pipe,
+ "PCH DP %c enabled on transcoder %c, should be disabled\n",
+ port_name(port), pipe_name(pipe));
- I915_STATE_WARN(dev_priv,
- HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
- "IBX PCH DP %c still using transcoder B\n",
- port_name(port));
+ INTEL_DISPLAY_STATE_WARN(display,
+ HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
+ "IBX PCH DP %c still using transcoder B\n",
+ port_name(port));
}
static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe, enum port port,
i915_reg_t hdmi_reg)
{
+ struct intel_display *display = &dev_priv->display;
enum pipe port_pipe;
bool state;
state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe);
- I915_STATE_WARN(dev_priv, state && port_pipe == pipe,
- "PCH HDMI %c enabled on transcoder %c, should be disabled\n",
- port_name(port), pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display, state && port_pipe == pipe,
+ "PCH HDMI %c enabled on transcoder %c, should be disabled\n",
+ port_name(port), pipe_name(pipe));
- I915_STATE_WARN(dev_priv,
- HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
- "IBX PCH HDMI %c still using transcoder B\n",
- port_name(port));
+ INTEL_DISPLAY_STATE_WARN(display,
+ HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
+ "IBX PCH HDMI %c still using transcoder B\n",
+ port_name(port));
}
static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
+ struct intel_display *display = &dev_priv->display;
enum pipe port_pipe;
assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B);
assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C);
assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D);
- I915_STATE_WARN(dev_priv,
- intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && port_pipe == pipe,
- "PCH VGA enabled on transcoder %c, should be disabled\n",
- pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_crt_port_enabled(display, PCH_ADPA, &port_pipe) && port_pipe == pipe,
+ "PCH VGA enabled on transcoder %c, should be disabled\n",
+ pipe_name(pipe));
- I915_STATE_WARN(dev_priv,
- intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && port_pipe == pipe,
- "PCH LVDS enabled on transcoder %c, should be disabled\n",
- pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display,
+ intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && port_pipe == pipe,
+ "PCH LVDS enabled on transcoder %c, should be disabled\n",
+ pipe_name(pipe));
/* PCH SDVOB multiplex with HDMIB */
assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB);
@@ -101,14 +104,15 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
+ struct intel_display *display = &dev_priv->display;
u32 val;
bool enabled;
- val = intel_de_read(dev_priv, PCH_TRANSCONF(pipe));
+ val = intel_de_read(display, PCH_TRANSCONF(pipe));
enabled = !!(val & TRANS_ENABLE);
- I915_STATE_WARN(dev_priv, enabled,
- "transcoder assertion failed, should be off on pipe %c but is still active\n",
- pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display, enabled,
+ "transcoder assertion failed, should be off on pipe %c but is still active\n",
+ pipe_name(pipe));
}
static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c
index 713cfba71475..84c55971e91a 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c
+++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c
@@ -491,6 +491,7 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv)
static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
{
+ struct intel_display *display = &dev_priv->display;
struct intel_encoder *encoder;
struct intel_shared_dpll *pll;
int i;
@@ -572,11 +573,11 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
if (has_panel) {
final |= DREF_SSC_SOURCE_ENABLE;
- if (intel_panel_use_ssc(dev_priv) && can_ssc)
+ if (intel_panel_use_ssc(display) && can_ssc)
final |= DREF_SSC1_ENABLE;
if (has_cpu_edp) {
- if (intel_panel_use_ssc(dev_priv) && can_ssc)
+ if (intel_panel_use_ssc(display) && can_ssc)
final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
else
final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
@@ -604,7 +605,7 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
val |= DREF_SSC_SOURCE_ENABLE;
/* SSC must be turned on before enabling the CPU output */
- if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+ if (intel_panel_use_ssc(display) && can_ssc) {
drm_dbg_kms(&dev_priv->drm, "Using SSC on panel\n");
val |= DREF_SSC1_ENABLE;
} else {
@@ -620,7 +621,7 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
/* Enable CPU source on CPU attached eDP */
if (has_cpu_edp) {
- if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+ if (intel_panel_use_ssc(display) && can_ssc) {
drm_dbg_kms(&dev_priv->drm,
"Using SSC on eDP\n");
val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
diff --git a/drivers/gpu/drm/i915/display/intel_pfit.c b/drivers/gpu/drm/i915/display/intel_pfit.c
new file mode 100644
index 000000000000..50861aa78a89
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pfit.c
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "i915_reg.h"
+#include "intel_display_core.h"
+#include "intel_display_driver.h"
+#include "intel_display_types.h"
+#include "intel_lvds_regs.h"
+#include "intel_pfit.h"
+
+static int intel_pch_pfit_check_dst_window(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ const struct drm_display_mode *adjusted_mode =
+ &crtc_state->hw.adjusted_mode;
+ const struct drm_rect *dst = &crtc_state->pch_pfit.dst;
+ int width = drm_rect_width(dst);
+ int height = drm_rect_height(dst);
+ int x = dst->x1;
+ int y = dst->y1;
+
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE &&
+ (y & 1 || height & 1)) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") misaligned for interlaced output\n",
+ crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst));
+ return -EINVAL;
+ }
+
+ /*
+ * "Restriction : When pipe scaling is enabled, the scaled
+ * output must equal the pipe active area, so Pipe active
+ * size = (2 * PF window position) + PF window size."
+ *
+ * The vertical direction seems more forgiving than the
+ * horizontal direction, but still has some issues so
+ * let's follow the same hard rule for both.
+ */
+ if (adjusted_mode->crtc_hdisplay != 2 * x + width ||
+ adjusted_mode->crtc_vdisplay != 2 * y + height) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") not centered\n",
+ crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst));
+ return -EINVAL;
+ }
+
+ /*
+ * "Restriction : The X position must not be programmed
+ * to be 1 (28:16=0 0000 0000 0001b)."
+ */
+ if (x == 1) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") badly positioned\n",
+ crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+ int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+ int max_src_w, max_src_h;
+
+ if (DISPLAY_VER(display) >= 8) {
+ max_src_w = 4096;
+ max_src_h = 4096;
+ } else if (DISPLAY_VER(display) >= 7) {
+ /*
+ * PF0 7x5 capable
+ * PF1 3x3 capable (could be switched to 7x5
+ * mode on HSW when PF2 unused)
+ * PF2 3x3 capable
+ *
+ * This assumes we use a 1:1 mapping between pipe and PF.
+ */
+ max_src_w = crtc->pipe == PIPE_A ? 4096 : 2048;
+ max_src_h = 4096;
+ } else {
+ max_src_w = 4096;
+ max_src_h = 4096;
+ }
+
+ if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] source size (%dx%d) exceeds pfit max (%dx%d)\n",
+ crtc->base.base.id, crtc->base.name,
+ pipe_src_w, pipe_src_h, max_src_w, max_src_h);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int intel_pch_pfit_check_scaling(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ const struct drm_rect *dst = &crtc_state->pch_pfit.dst;
+ int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+ int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+ int hscale, vscale, max_scale = 0x12000; /* 1.125 */
+ struct drm_rect src;
+
+ drm_rect_init(&src, 0, 0, pipe_src_w << 16, pipe_src_h << 16);
+
+ hscale = drm_rect_calc_hscale(&src, dst, 0, max_scale);
+ if (hscale < 0) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) exceeds max (0x%x)\n",
+ crtc->base.base.id, crtc->base.name,
+ pipe_src_w, drm_rect_width(dst),
+ max_scale);
+ return hscale;
+ }
+
+ vscale = drm_rect_calc_vscale(&src, dst, 0, max_scale);
+ if (vscale < 0) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) exceeds max (0x%x)\n",
+ crtc->base.base.id, crtc->base.name,
+ pipe_src_h, drm_rect_height(dst),
+ max_scale);
+ return vscale;
+ }
+
+ return 0;
+}
+
+static int intel_pch_pfit_check_timings(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ const struct drm_display_mode *adjusted_mode =
+ &crtc_state->hw.adjusted_mode;
+
+ if (adjusted_mode->crtc_vdisplay < 7) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n",
+ crtc->base.base.id, crtc->base.name,
+ adjusted_mode->crtc_vdisplay, 7);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int intel_pch_pfit_check_cloning(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ /*
+ * The panel fitter is in the pipe and thus would affect every
+ * cloned output. The relevant properties (scaling mode, TV
+ * margins) are per-connector so we'd have to make sure each
+ * output sets them up identically. Seems like a very niche use
+ * case so let's just reject cloning entirely when pfit is used.
+ */
+ if (crtc_state->uapi.encoder_mask &&
+ !is_power_of_2(crtc_state->uapi.encoder_mask)) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] no pfit when cloning\n",
+ crtc->base.base.id, crtc->base.name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* adjusted_mode has been preset to be the panel's fixed mode */
+static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ const struct drm_display_mode *adjusted_mode =
+ &crtc_state->hw.adjusted_mode;
+ int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+ int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+ int ret, x, y, width, height;
+
+ /* Native modes don't need fitting */
+ if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
+ adjusted_mode->crtc_vdisplay == pipe_src_h &&
+ crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
+ return 0;
+
+ switch (conn_state->scaling_mode) {
+ case DRM_MODE_SCALE_CENTER:
+ width = pipe_src_w;
+ height = pipe_src_h;
+ x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
+ y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
+ break;
+
+ case DRM_MODE_SCALE_ASPECT:
+ /* Scale but preserve the aspect ratio */
+ {
+ u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
+ u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
+
+ if (scaled_width > scaled_height) { /* pillar */
+ width = scaled_height / pipe_src_h;
+ if (width & 1)
+ width++;
+ x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
+ y = 0;
+ height = adjusted_mode->crtc_vdisplay;
+ } else if (scaled_width < scaled_height) { /* letter */
+ height = scaled_width / pipe_src_w;
+ if (height & 1)
+ height++;
+ y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
+ x = 0;
+ width = adjusted_mode->crtc_hdisplay;
+ } else {
+ x = y = 0;
+ width = adjusted_mode->crtc_hdisplay;
+ height = adjusted_mode->crtc_vdisplay;
+ }
+ }
+ break;
+
+ case DRM_MODE_SCALE_NONE:
+ WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w);
+ WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h);
+ fallthrough;
+ case DRM_MODE_SCALE_FULLSCREEN:
+ x = y = 0;
+ width = adjusted_mode->crtc_hdisplay;
+ height = adjusted_mode->crtc_vdisplay;
+ break;
+
+ default:
+ MISSING_CASE(conn_state->scaling_mode);
+ return -EINVAL;
+ }
+
+ drm_rect_init(&crtc_state->pch_pfit.dst,
+ x, y, width, height);
+ crtc_state->pch_pfit.enabled = true;
+
+ /*
+ * SKL+ have unified scalers for pipes/planes so the
+ * checks are done in a single place for all scalers.
+ */
+ if (DISPLAY_VER(display) >= 9)
+ return 0;
+
+ ret = intel_pch_pfit_check_dst_window(crtc_state);
+ if (ret)
+ return ret;
+
+ ret = intel_pch_pfit_check_src_size(crtc_state);
+ if (ret)
+ return ret;
+
+ ret = intel_pch_pfit_check_scaling(crtc_state);
+ if (ret)
+ return ret;
+
+ ret = intel_pch_pfit_check_timings(crtc_state);
+ if (ret)
+ return ret;
+
+ ret = intel_pch_pfit_check_cloning(crtc_state);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void
+centre_horizontally(struct drm_display_mode *adjusted_mode,
+ int width)
+{
+ u32 border, sync_pos, blank_width, sync_width;
+
+ /* keep the hsync and hblank widths constant */
+ sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+ blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
+ sync_pos = (blank_width - sync_width + 1) / 2;
+
+ border = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
+ border += border & 1; /* make the border even */
+
+ adjusted_mode->crtc_hdisplay = width;
+ adjusted_mode->crtc_hblank_start = width + border;
+ adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width;
+
+ adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos;
+ adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width;
+}
+
+static void
+centre_vertically(struct drm_display_mode *adjusted_mode,
+ int height)
+{
+ u32 border, sync_pos, blank_width, sync_width;
+
+ /* keep the vsync and vblank widths constant */
+ sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
+ blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start;
+ sync_pos = (blank_width - sync_width + 1) / 2;
+
+ border = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
+
+ adjusted_mode->crtc_vdisplay = height;
+ adjusted_mode->crtc_vblank_start = height + border;
+ adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width;
+
+ adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos;
+ adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width;
+}
+
+static u32 panel_fitter_scaling(u32 source, u32 target)
+{
+ /*
+ * Floating point operation is not supported. So the FACTOR
+ * is defined, which can avoid the floating point computation
+ * when calculating the panel ratio.
+ */
+#define ACCURACY 12
+#define FACTOR (1 << ACCURACY)
+ u32 ratio = source * FACTOR / target;
+ return (FACTOR * ratio + FACTOR/2) / FACTOR;
+}
+
+static void i965_scale_aspect(struct intel_crtc_state *crtc_state,
+ u32 *pfit_control)
+{
+ const struct drm_display_mode *adjusted_mode =
+ &crtc_state->hw.adjusted_mode;
+ int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+ int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+ u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
+ u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
+
+ /* 965+ is easy, it does everything in hw */
+ if (scaled_width > scaled_height)
+ *pfit_control |= PFIT_ENABLE |
+ PFIT_SCALING_PILLAR;
+ else if (scaled_width < scaled_height)
+ *pfit_control |= PFIT_ENABLE |
+ PFIT_SCALING_LETTER;
+ else if (adjusted_mode->crtc_hdisplay != pipe_src_w)
+ *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
+}
+
+static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state,
+ u32 *pfit_control, u32 *pfit_pgm_ratios,
+ u32 *border)
+{
+ struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+ int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+ u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h;
+ u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay;
+ u32 bits;
+
+ /*
+ * For earlier chips we have to calculate the scaling
+ * ratio by hand and program it into the
+ * PFIT_PGM_RATIO register
+ */
+ if (scaled_width > scaled_height) { /* pillar */
+ centre_horizontally(adjusted_mode,
+ scaled_height / pipe_src_h);
+
+ *border = LVDS_BORDER_ENABLE;
+ if (pipe_src_h != adjusted_mode->crtc_vdisplay) {
+ bits = panel_fitter_scaling(pipe_src_h,
+ adjusted_mode->crtc_vdisplay);
+
+ *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) |
+ PFIT_VERT_SCALE(bits));
+ *pfit_control |= (PFIT_ENABLE |
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_INTERP_BILINEAR);
+ }
+ } else if (scaled_width < scaled_height) { /* letter */
+ centre_vertically(adjusted_mode,
+ scaled_width / pipe_src_w);
+
+ *border = LVDS_BORDER_ENABLE;
+ if (pipe_src_w != adjusted_mode->crtc_hdisplay) {
+ bits = panel_fitter_scaling(pipe_src_w,
+ adjusted_mode->crtc_hdisplay);
+
+ *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) |
+ PFIT_VERT_SCALE(bits));
+ *pfit_control |= (PFIT_ENABLE |
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_INTERP_BILINEAR);
+ }
+ } else {
+ /* Aspects match, Let hw scale both directions */
+ *pfit_control |= (PFIT_ENABLE |
+ PFIT_VERT_AUTO_SCALE |
+ PFIT_HORIZ_AUTO_SCALE |
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_INTERP_BILINEAR);
+ }
+}
+
+static int intel_gmch_pfit_check_timings(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ const struct drm_display_mode *adjusted_mode =
+ &crtc_state->hw.adjusted_mode;
+ int min;
+
+ if (DISPLAY_VER(display) >= 4)
+ min = 3;
+ else
+ min = 2;
+
+ if (adjusted_mode->crtc_hdisplay < min) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] horizontal active (%d) below minimum (%d) for pfit\n",
+ crtc->base.base.id, crtc->base.name,
+ adjusted_mode->crtc_hdisplay, min);
+ return -EINVAL;
+ }
+
+ if (adjusted_mode->crtc_vdisplay < min) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n",
+ crtc->base.base.id, crtc->base.name,
+ adjusted_mode->crtc_vdisplay, min);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int gmch_panel_fitting(struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
+ struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
+ int pipe_src_h = drm_rect_height(&crtc_state->pipe_src);
+
+ /* Native modes don't need fitting */
+ if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
+ adjusted_mode->crtc_vdisplay == pipe_src_h)
+ goto out;
+
+ /*
+ * TODO: implement downscaling for i965+. Need to account
+ * for downscaling in intel_crtc_compute_pixel_rate().
+ */
+ if (adjusted_mode->crtc_hdisplay < pipe_src_w) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) not supported\n",
+ crtc->base.base.id, crtc->base.name,
+ pipe_src_w, adjusted_mode->crtc_hdisplay);
+ return -EINVAL;
+ }
+ if (adjusted_mode->crtc_vdisplay < pipe_src_h) {
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) not supported\n",
+ crtc->base.base.id, crtc->base.name,
+ pipe_src_h, adjusted_mode->crtc_vdisplay);
+ return -EINVAL;
+ }
+
+ switch (conn_state->scaling_mode) {
+ case DRM_MODE_SCALE_CENTER:
+ /*
+ * For centered modes, we have to calculate border widths &
+ * heights and modify the values programmed into the CRTC.
+ */
+ centre_horizontally(adjusted_mode, pipe_src_w);
+ centre_vertically(adjusted_mode, pipe_src_h);
+ border = LVDS_BORDER_ENABLE;
+ break;
+ case DRM_MODE_SCALE_ASPECT:
+ /* Scale but preserve the aspect ratio */
+ if (DISPLAY_VER(display) >= 4)
+ i965_scale_aspect(crtc_state, &pfit_control);
+ else
+ i9xx_scale_aspect(crtc_state, &pfit_control,
+ &pfit_pgm_ratios, &border);
+ break;
+ case DRM_MODE_SCALE_FULLSCREEN:
+ /*
+ * Full scaling, even if it changes the aspect ratio.
+ * Fortunately this is all done for us in hw.
+ */
+ if (pipe_src_h != adjusted_mode->crtc_vdisplay ||
+ pipe_src_w != adjusted_mode->crtc_hdisplay) {
+ pfit_control |= PFIT_ENABLE;
+ if (DISPLAY_VER(display) >= 4)
+ pfit_control |= PFIT_SCALING_AUTO;
+ else
+ pfit_control |= (PFIT_VERT_AUTO_SCALE |
+ PFIT_VERT_INTERP_BILINEAR |
+ PFIT_HORIZ_AUTO_SCALE |
+ PFIT_HORIZ_INTERP_BILINEAR);
+ }
+ break;
+ default:
+ MISSING_CASE(conn_state->scaling_mode);
+ return -EINVAL;
+ }
+
+ /* 965+ wants fuzzy fitting */
+ /* FIXME: handle multiple panels by failing gracefully */
+ if (DISPLAY_VER(display) >= 4)
+ pfit_control |= PFIT_PIPE(crtc->pipe) | PFIT_FILTER_FUZZY;
+
+out:
+ if ((pfit_control & PFIT_ENABLE) == 0) {
+ pfit_control = 0;
+ pfit_pgm_ratios = 0;
+ }
+
+ /* Make sure pre-965 set dither correctly for 18bpp panels. */
+ if (DISPLAY_VER(display) < 4 && crtc_state->pipe_bpp == 18)
+ pfit_control |= PFIT_PANEL_8TO6_DITHER_ENABLE;
+
+ crtc_state->gmch_pfit.control = pfit_control;
+ crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
+ crtc_state->gmch_pfit.lvds_border_bits = border;
+
+ if ((pfit_control & PFIT_ENABLE) == 0)
+ return 0;
+
+ return intel_gmch_pfit_check_timings(crtc_state);
+}
+
+int intel_panel_fitting(struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+
+ if (HAS_GMCH(display))
+ return gmch_panel_fitting(crtc_state, conn_state);
+ else
+ return pch_panel_fitting(crtc_state, conn_state);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_pfit.h b/drivers/gpu/drm/i915/display/intel_pfit.h
new file mode 100644
index 000000000000..add8d78de2c9
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pfit.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef __INTEL_PFIT_H__
+#define __INTEL_PFIT_H__
+
+struct drm_connector_state;
+struct intel_crtc_state;
+
+int intel_panel_fitting(struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state);
+
+#endif /* __INTEL_PFIT_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c
index ceaf9e3147da..cdd314956a31 100644
--- a/drivers/gpu/drm/i915/display/intel_pmdemand.c
+++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c
@@ -92,7 +92,7 @@ int intel_pmdemand_init(struct drm_i915_private *i915)
&pmdemand_state->base,
&intel_pmdemand_funcs);
- if (IS_DISPLAY_VER_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0))
+ if (IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_A0, STEP_C0))
/* Wa_14016740474 */
intel_de_rmw(i915, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE);
@@ -258,6 +258,7 @@ intel_pmdemand_connector_needs_update(struct intel_atomic_state *state)
static bool intel_pmdemand_needs_update(struct intel_atomic_state *state)
{
+ struct intel_display *display = to_intel_display(state);
const struct intel_bw_state *new_bw_state, *old_bw_state;
const struct intel_cdclk_state *new_cdclk_state, *old_cdclk_state;
const struct intel_crtc_state *new_crtc_state, *old_crtc_state;
@@ -274,12 +275,16 @@ static bool intel_pmdemand_needs_update(struct intel_atomic_state *state)
new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
if (new_dbuf_state &&
- (new_dbuf_state->active_pipes !=
- old_dbuf_state->active_pipes ||
- new_dbuf_state->enabled_slices !=
- old_dbuf_state->enabled_slices))
+ new_dbuf_state->active_pipes != old_dbuf_state->active_pipes)
return true;
+ if (DISPLAY_VER(display) < 30) {
+ if (new_dbuf_state &&
+ new_dbuf_state->enabled_slices !=
+ old_dbuf_state->enabled_slices)
+ return true;
+ }
+
new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
if (new_cdclk_state &&
@@ -327,10 +332,15 @@ int intel_pmdemand_atomic_check(struct intel_atomic_state *state)
if (IS_ERR(new_dbuf_state))
return PTR_ERR(new_dbuf_state);
- new_pmdemand_state->params.active_pipes =
- min_t(u8, hweight8(new_dbuf_state->active_pipes), 3);
- new_pmdemand_state->params.active_dbufs =
- min_t(u8, hweight8(new_dbuf_state->enabled_slices), 3);
+ if (DISPLAY_VER(i915) < 30) {
+ new_pmdemand_state->params.active_dbufs =
+ min_t(u8, hweight8(new_dbuf_state->enabled_slices), 3);
+ new_pmdemand_state->params.active_pipes =
+ min_t(u8, hweight8(new_dbuf_state->active_pipes), 3);
+ } else {
+ new_pmdemand_state->params.active_pipes =
+ min_t(u8, hweight8(new_dbuf_state->active_pipes), INTEL_NUM_PIPES(i915));
+ }
new_cdclk_state = intel_atomic_get_cdclk_state(state);
if (IS_ERR(new_cdclk_state))
@@ -395,27 +405,32 @@ intel_pmdemand_init_pmdemand_params(struct drm_i915_private *i915,
reg2 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1));
- /* Set 1*/
pmdemand_state->params.qclk_gv_bw =
REG_FIELD_GET(XELPDP_PMDEMAND_QCLK_GV_BW_MASK, reg1);
pmdemand_state->params.voltage_index =
REG_FIELD_GET(XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK, reg1);
pmdemand_state->params.qclk_gv_index =
REG_FIELD_GET(XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK, reg1);
- pmdemand_state->params.active_pipes =
- REG_FIELD_GET(XELPDP_PMDEMAND_PIPES_MASK, reg1);
- pmdemand_state->params.active_dbufs =
- REG_FIELD_GET(XELPDP_PMDEMAND_DBUFS_MASK, reg1);
pmdemand_state->params.active_phys =
REG_FIELD_GET(XELPDP_PMDEMAND_PHYS_MASK, reg1);
- /* Set 2*/
pmdemand_state->params.cdclk_freq_mhz =
REG_FIELD_GET(XELPDP_PMDEMAND_CDCLK_FREQ_MASK, reg2);
pmdemand_state->params.ddiclk_max =
REG_FIELD_GET(XELPDP_PMDEMAND_DDICLK_FREQ_MASK, reg2);
- pmdemand_state->params.scalers =
- REG_FIELD_GET(XELPDP_PMDEMAND_SCALERS_MASK, reg2);
+
+ if (DISPLAY_VER(i915) >= 30) {
+ pmdemand_state->params.active_pipes =
+ REG_FIELD_GET(XE3_PMDEMAND_PIPES_MASK, reg1);
+ } else {
+ pmdemand_state->params.active_pipes =
+ REG_FIELD_GET(XELPDP_PMDEMAND_PIPES_MASK, reg1);
+ pmdemand_state->params.active_dbufs =
+ REG_FIELD_GET(XELPDP_PMDEMAND_DBUFS_MASK, reg1);
+
+ pmdemand_state->params.scalers =
+ REG_FIELD_GET(XELPDP_PMDEMAND_SCALERS_MASK, reg2);
+ }
unlock:
mutex_unlock(&i915->display.pmdemand.lock);
@@ -442,6 +457,10 @@ void intel_pmdemand_program_dbuf(struct drm_i915_private *i915,
{
u32 dbufs = min_t(u32, hweight8(dbuf_slices), 3);
+ /* PM Demand only tracks active dbufs on pre-Xe3 platforms */
+ if (DISPLAY_VER(i915) >= 30)
+ return;
+
mutex_lock(&i915->display.pmdemand.lock);
if (drm_WARN_ON(&i915->drm,
!intel_pmdemand_check_prev_transaction(i915)))
@@ -460,7 +479,8 @@ unlock:
}
static void
-intel_pmdemand_update_params(const struct intel_pmdemand_state *new,
+intel_pmdemand_update_params(struct intel_display *display,
+ const struct intel_pmdemand_state *new,
const struct intel_pmdemand_state *old,
u32 *reg1, u32 *reg2, bool serialized)
{
@@ -495,16 +515,22 @@ intel_pmdemand_update_params(const struct intel_pmdemand_state *new,
update_reg(reg1, qclk_gv_bw, XELPDP_PMDEMAND_QCLK_GV_BW_MASK);
update_reg(reg1, voltage_index, XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK);
update_reg(reg1, qclk_gv_index, XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK);
- update_reg(reg1, active_pipes, XELPDP_PMDEMAND_PIPES_MASK);
- update_reg(reg1, active_dbufs, XELPDP_PMDEMAND_DBUFS_MASK);
update_reg(reg1, active_phys, XELPDP_PMDEMAND_PHYS_MASK);
/* Set 2*/
update_reg(reg2, cdclk_freq_mhz, XELPDP_PMDEMAND_CDCLK_FREQ_MASK);
update_reg(reg2, ddiclk_max, XELPDP_PMDEMAND_DDICLK_FREQ_MASK);
- update_reg(reg2, scalers, XELPDP_PMDEMAND_SCALERS_MASK);
update_reg(reg2, plls, XELPDP_PMDEMAND_PLLS_MASK);
+ if (DISPLAY_VER(display) >= 30) {
+ update_reg(reg1, active_pipes, XE3_PMDEMAND_PIPES_MASK);
+ } else {
+ update_reg(reg1, active_pipes, XELPDP_PMDEMAND_PIPES_MASK);
+ update_reg(reg1, active_dbufs, XELPDP_PMDEMAND_DBUFS_MASK);
+
+ update_reg(reg2, scalers, XELPDP_PMDEMAND_SCALERS_MASK);
+ }
+
#undef update_reg
}
@@ -514,6 +540,7 @@ intel_pmdemand_program_params(struct drm_i915_private *i915,
const struct intel_pmdemand_state *old,
bool serialized)
{
+ struct intel_display *display = &i915->display;
bool changed = false;
u32 reg1, mod_reg1;
u32 reg2, mod_reg2;
@@ -529,7 +556,7 @@ intel_pmdemand_program_params(struct drm_i915_private *i915,
reg2 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1));
mod_reg2 = reg2;
- intel_pmdemand_update_params(new, old, &mod_reg1, &mod_reg2,
+ intel_pmdemand_update_params(display, new, old, &mod_reg1, &mod_reg2,
serialized);
if (reg1 != mod_reg1) {
diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.h b/drivers/gpu/drm/i915/display/intel_pmdemand.h
index 128fd61f8f14..a1c49efdc493 100644
--- a/drivers/gpu/drm/i915/display/intel_pmdemand.h
+++ b/drivers/gpu/drm/i915/display/intel_pmdemand.h
@@ -20,14 +20,14 @@ struct pmdemand_params {
u8 voltage_index;
u8 qclk_gv_index;
u8 active_pipes;
- u8 active_dbufs;
+ u8 active_dbufs; /* pre-Xe3 only */
/* Total number of non type C active phys from active_phys_mask */
u8 active_phys;
u8 plls;
u16 cdclk_freq_mhz;
/* max from ddi_clocks[] */
u16 ddiclk_max;
- u8 scalers;
+ u8 scalers; /* pre-Xe3 only */
};
struct intel_pmdemand_state {
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index ffeee9daa568..093fe37a3983 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -29,10 +29,9 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
static const char *pps_name(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_pps *pps = &intel_dp->pps;
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
+ if (display->platform.valleyview || display->platform.cherryview) {
switch (pps->vlv_pps_pipe) {
case INVALID_PIPE:
/*
@@ -122,7 +121,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
DP |= DP_PORT_WIDTH(1);
DP |= DP_LINK_TRAIN_PAT_1;
- if (IS_CHERRYVIEW(dev_priv))
+ if (display->platform.cherryview)
DP |= DP_PIPE_SEL_CHV(pipe);
else
DP |= DP_PIPE_SEL(pipe);
@@ -134,7 +133,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
* So enable temporarily it if it's not already enabled.
*/
if (!pll_enabled) {
- release_cl_override = IS_CHERRYVIEW(dev_priv) &&
+ release_cl_override = display->platform.cherryview &&
!chv_phy_powergate_ch(dev_priv, phy, ch, true);
if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) {
@@ -356,10 +355,10 @@ static int intel_num_pps(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ if (display->platform.valleyview || display->platform.cherryview)
return 2;
- if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
+ if (display->platform.geminilake || display->platform.broxton)
return 2;
if (INTEL_PCH_TYPE(i915) >= PCH_MTL)
@@ -406,11 +405,10 @@ pps_initial_setup(struct intel_dp *intel_dp)
struct intel_display *display = to_intel_display(intel_dp);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct intel_connector *connector = intel_dp->attached_connector;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
lockdep_assert_held(&display->pps.mutex);
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
+ if (display->platform.valleyview || display->platform.cherryview) {
vlv_initial_power_sequencer_setup(intel_dp);
return true;
}
@@ -509,9 +507,9 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp,
memset(regs, 0, sizeof(*regs));
- if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+ if (display->platform.valleyview || display->platform.cherryview)
pps_idx = vlv_power_sequencer_pipe(intel_dp);
- else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
+ else if (display->platform.geminilake || display->platform.broxton)
pps_idx = bxt_power_sequencer_idx(intel_dp);
else
pps_idx = intel_dp->pps.pps_idx;
@@ -522,7 +520,7 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp,
regs->pp_off = PP_OFF_DELAYS(display, pps_idx);
/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
- if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ||
+ if (display->platform.geminilake || display->platform.broxton ||
INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
regs->pp_div = INVALID_MMIO_REG;
else
@@ -552,11 +550,10 @@ _pp_stat_reg(struct intel_dp *intel_dp)
static bool edp_have_panel_power(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(display->drm);
lockdep_assert_held(&display->pps.mutex);
- if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ if ((display->platform.valleyview || display->platform.cherryview) &&
intel_dp->pps.vlv_pps_pipe == INVALID_PIPE)
return false;
@@ -566,11 +563,10 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(display->drm);
lockdep_assert_held(&display->pps.mutex);
- if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ if ((display->platform.valleyview || display->platform.cherryview) &&
intel_dp->pps.vlv_pps_pipe == INVALID_PIPE)
return false;
@@ -801,7 +797,8 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
}
/*
- * Must be paired with intel_pps_off().
+ * Must be paired with intel_pps_vdd_off() or - to disable
+ * both VDD and panel power - intel_pps_off().
* Nested calls to these functions are not allowed since
* we drop the lock. Caller must use some higher level
* locking to prevent nested calls from other threads.
@@ -809,7 +806,6 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
void intel_pps_vdd_on(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref;
bool vdd;
@@ -819,10 +815,10 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp)
vdd = false;
with_intel_pps_lock(intel_dp, wakeref)
vdd = intel_pps_vdd_on_unlocked(intel_dp);
- I915_STATE_WARN(i915, !vdd, "[ENCODER:%d:%s] %s VDD already requested on\n",
- dp_to_dig_port(intel_dp)->base.base.base.id,
- dp_to_dig_port(intel_dp)->base.base.name,
- pps_name(intel_dp));
+ INTEL_DISPLAY_STATE_WARN(display, !vdd, "[ENCODER:%d:%s] %s VDD already requested on\n",
+ dp_to_dig_port(intel_dp)->base.base.base.id,
+ dp_to_dig_port(intel_dp)->base.base.name,
+ pps_name(intel_dp));
}
static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
@@ -861,8 +857,10 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
intel_de_read(display, pp_stat_reg),
intel_de_read(display, pp_ctrl_reg));
- if ((pp & PANEL_POWER_ON) == 0)
+ if ((pp & PANEL_POWER_ON) == 0) {
intel_dp->pps.panel_power_off_time = ktime_get_boottime();
+ intel_dp_invalidate_source_oui(intel_dp);
+ }
intel_display_power_put(dev_priv,
intel_aux_power_domain(dig_port),
@@ -929,18 +927,17 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(display->drm);
lockdep_assert_held(&display->pps.mutex);
if (!intel_dp_is_edp(intel_dp))
return;
- I915_STATE_WARN(dev_priv, !intel_dp->pps.want_panel_vdd,
- "[ENCODER:%d:%s] %s VDD not forced on",
- dp_to_dig_port(intel_dp)->base.base.base.id,
- dp_to_dig_port(intel_dp)->base.base.name,
- pps_name(intel_dp));
+ INTEL_DISPLAY_STATE_WARN(display, !intel_dp->pps.want_panel_vdd,
+ "[ENCODER:%d:%s] %s VDD not forced on",
+ dp_to_dig_port(intel_dp)->base.base.base.id,
+ dp_to_dig_port(intel_dp)->base.base.name,
+ pps_name(intel_dp));
intel_dp->pps.want_panel_vdd = false;
@@ -950,10 +947,20 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
edp_panel_vdd_schedule_off(intel_dp);
}
+void intel_pps_vdd_off(struct intel_dp *intel_dp)
+{
+ intel_wakeref_t wakeref;
+
+ if (!intel_dp_is_edp(intel_dp))
+ return;
+
+ with_intel_pps_lock(intel_dp, wakeref)
+ intel_pps_vdd_off_unlocked(intel_dp, false);
+}
+
void intel_pps_on_unlocked(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 pp;
i915_reg_t pp_ctrl_reg;
@@ -978,7 +985,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp)
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
pp = ilk_get_pp_control(intel_dp);
- if (IS_IRONLAKE(dev_priv)) {
+ if (display->platform.ironlake) {
/* ILK workaround: disable reset around power sequence */
pp &= ~PANEL_POWER_RESET;
intel_de_write(display, pp_ctrl_reg, pp);
@@ -994,7 +1001,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp)
0, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
pp |= PANEL_POWER_ON;
- if (!IS_IRONLAKE(dev_priv))
+ if (!display->platform.ironlake)
pp |= PANEL_POWER_RESET;
intel_de_write(display, pp_ctrl_reg, pp);
@@ -1007,7 +1014,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp)
intel_de_rmw(display, SOUTH_DSPCLK_GATE_D,
PCH_DPLSUNIT_CLOCK_GATE_DISABLE, 0);
- if (IS_IRONLAKE(dev_priv)) {
+ if (display->platform.ironlake) {
pp |= PANEL_POWER_RESET; /* restore panel reset bit */
intel_de_write(display, pp_ctrl_reg, pp);
intel_de_posting_read(display, pp_ctrl_reg);
@@ -1063,6 +1070,8 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
wait_panel_off(intel_dp);
intel_dp->pps.panel_power_off_time = ktime_get_boottime();
+ intel_dp_invalidate_source_oui(intel_dp);
+
/* We got a reference when we enabled the VDD. */
intel_display_power_put(dev_priv,
intel_aux_power_domain(dig_port),
@@ -1148,7 +1157,7 @@ void intel_pps_backlight_power(struct intel_connector *connector, bool enable)
return;
drm_dbg_kms(display->drm, "panel power control backlight %s\n",
- enable ? "enable" : "disable");
+ str_enable_disable(enable));
if (enable)
intel_pps_backlight_on(intel_dp);
@@ -1627,7 +1636,7 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
/* Haswell doesn't have any port selection bits for the panel
* power sequencer any more. */
- if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+ if (display->platform.valleyview || display->platform.cherryview) {
port_sel = PANEL_PORT_SELECT_VLV(port);
} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
switch (port) {
@@ -1674,7 +1683,6 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
void intel_pps_encoder_reset(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref;
if (!intel_dp_is_edp(intel_dp))
@@ -1685,7 +1693,7 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
* Reinit the power sequencer also on the resume path, in case
* BIOS did something nasty with it.
*/
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ if (display->platform.valleyview || display->platform.cherryview)
vlv_initial_power_sequencer_setup(intel_dp);
pps_init_delays(intel_dp);
@@ -1721,11 +1729,10 @@ bool intel_pps_init(struct intel_dp *intel_dp)
static void pps_init_late(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
- struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct intel_connector *connector = intel_dp->attached_connector;
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ if (display->platform.valleyview || display->platform.cherryview)
return;
if (intel_num_pps(display) < 2)
@@ -1783,9 +1790,9 @@ void intel_pps_setup(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
- if (HAS_PCH_SPLIT(i915) || IS_GEMINILAKE(i915) || IS_BROXTON(i915))
+ if (HAS_PCH_SPLIT(i915) || display->platform.geminilake || display->platform.broxton)
display->pps.mmio_base = PCH_PPS_BASE;
- else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ else if (display->platform.valleyview || display->platform.cherryview)
display->pps.mmio_base = VLV_PPS_BASE;
else
display->pps.mmio_base = PPS_BASE;
@@ -1857,7 +1864,7 @@ void assert_pps_unlocked(struct intel_display *display, enum pipe pipe)
MISSING_CASE(port_sel);
break;
}
- } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+ } else if (display->platform.valleyview || display->platform.cherryview) {
/* presumably write lock depends on pipe, not port select */
pp_reg = PP_CONTROL(display, pipe);
panel_pipe = pipe;
@@ -1878,7 +1885,7 @@ void assert_pps_unlocked(struct intel_display *display, enum pipe pipe)
((val & PANEL_UNLOCK_MASK) == PANEL_UNLOCK_REGS))
locked = false;
- I915_STATE_WARN(dev_priv, panel_pipe == pipe && locked,
- "panel assertion failure, pipe %c regs locked\n",
- pipe_name(pipe));
+ INTEL_DISPLAY_STATE_WARN(display, panel_pipe == pipe && locked,
+ "panel assertion failure, pipe %c regs locked\n",
+ pipe_name(pipe));
}
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index bc5046d53626..c83007152f07 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -34,6 +34,7 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp);
void intel_pps_check_power_unlocked(struct intel_dp *intel_dp);
void intel_pps_vdd_on(struct intel_dp *intel_dp);
+void intel_pps_vdd_off(struct intel_dp *intel_dp);
void intel_pps_on(struct intel_dp *intel_dp);
void intel_pps_off(struct intel_dp *intel_dp);
void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 3b20325b3f6a..a784c0b81556 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -233,7 +233,9 @@ static bool psr_global_enabled(struct intel_dp *intel_dp)
switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
case I915_PSR_DEBUG_DEFAULT:
if (display->params.enable_psr == -1)
- return connector->panel.vbt.psr.enable;
+ return intel_dp_is_edp(intel_dp) ?
+ connector->panel.vbt.psr.enable :
+ true;
return display->params.enable_psr;
case I915_PSR_DEBUG_DISABLE:
return false;
@@ -1451,11 +1453,15 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
return false;
}
- if (DISPLAY_VER(display) >= 12) {
+ if (DISPLAY_VER(display) >= 20) {
+ psr_max_h = crtc_hdisplay;
+ psr_max_v = crtc_vdisplay;
+ max_bpp = crtc_state->pipe_bpp;
+ } else if (IS_DISPLAY_VER(display, 12, 14)) {
psr_max_h = 5120;
psr_max_v = 3200;
max_bpp = 30;
- } else if (DISPLAY_VER(display) >= 10) {
+ } else if (IS_DISPLAY_VER(display, 10, 11)) {
psr_max_h = 4096;
psr_max_v = 2304;
max_bpp = 24;
@@ -1912,14 +1918,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
* cause issues if non-supported panels are used.
*/
if (!intel_dp->psr.panel_replay_enabled &&
- (IS_DISPLAY_VER_STEP(display, IP_VER(14, 0), STEP_A0, STEP_B0) ||
+ (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_B0) ||
IS_ALDERLAKE_P(dev_priv)))
intel_de_rmw(display, hsw_chicken_trans_reg(dev_priv, cpu_transcoder),
0, ADLP_1_BASED_X_GRANULARITY);
/* Wa_16012604467:adlp,mtl[a0,b0] */
if (!intel_dp->psr.panel_replay_enabled &&
- IS_DISPLAY_VER_STEP(display, IP_VER(14, 0), STEP_A0, STEP_B0))
+ IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_B0))
intel_de_rmw(display,
MTL_CLKGATE_DIS_TRANS(display, cpu_transcoder),
0,
@@ -2007,6 +2013,15 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
intel_dp->psr.enabled = true;
intel_dp->psr.paused = false;
+ /*
+ * Link_ok is sticky and set here on PSR enable. We can assume link
+ * training is complete as we never continue to PSR enable with
+ * untrained link. Link_ok is kept as set until first short pulse
+ * interrupt. This is targeted to workaround panels stating bad link
+ * after PSR is enabled.
+ */
+ intel_dp->psr.link_ok = true;
+
intel_psr_activate(intel_dp);
}
@@ -2104,7 +2119,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
if (intel_dp->psr.sel_update_enabled) {
/* Wa_16012604467:adlp,mtl[a0,b0] */
if (!intel_dp->psr.panel_replay_enabled &&
- IS_DISPLAY_VER_STEP(display, IP_VER(14, 0), STEP_A0, STEP_B0))
+ IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_B0))
intel_de_rmw(display,
MTL_CLKGATE_DIS_TRANS(display, cpu_transcoder),
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0);
@@ -2166,6 +2181,8 @@ void intel_psr_disable(struct intel_dp *intel_dp,
intel_psr_disable_locked(intel_dp);
+ intel_dp->psr.link_ok = false;
+
mutex_unlock(&intel_dp->psr.lock);
cancel_work_sync(&intel_dp->psr.work);
cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
@@ -2559,7 +2576,7 @@ intel_psr_apply_su_area_workarounds(struct intel_crtc_state *crtc_state)
/* Wa_14014971492 */
if (!crtc_state->has_panel_replay &&
- ((IS_DISPLAY_VER_STEP(display, IP_VER(14, 0), STEP_A0, STEP_B0) ||
+ ((IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_B0) ||
IS_ALDERLAKE_P(i915) || IS_TIGERLAKE(i915))) &&
crtc_state->splitter.enable)
crtc_state->psr2_su_area.y1 = 0;
@@ -3456,6 +3473,8 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp)
mutex_lock(&psr->lock);
+ psr->link_ok = false;
+
if (!psr->enabled)
goto exit;
@@ -3516,6 +3535,33 @@ bool intel_psr_enabled(struct intel_dp *intel_dp)
}
/**
+ * intel_psr_link_ok - return psr->link_ok
+ * @intel_dp: struct intel_dp
+ *
+ * We are seeing unexpected link re-trainings with some panels. This is caused
+ * by panel stating bad link status after PSR is enabled. Code checking link
+ * status can call this to ensure it can ignore bad link status stated by the
+ * panel I.e. if panel is stating bad link and intel_psr_link_ok is stating link
+ * is ok caller should rely on latter.
+ *
+ * Return value of link_ok
+ */
+bool intel_psr_link_ok(struct intel_dp *intel_dp)
+{
+ bool ret;
+
+ if ((!CAN_PSR(intel_dp) && !CAN_PANEL_REPLAY(intel_dp)) ||
+ !intel_dp_is_edp(intel_dp))
+ return false;
+
+ mutex_lock(&intel_dp->psr.lock);
+ ret = intel_dp->psr.link_ok;
+ mutex_unlock(&intel_dp->psr.lock);
+
+ return ret;
+}
+
+/**
* intel_psr_lock - grab PSR lock
* @crtc_state: the crtc state
*
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
index 5f26f61f82aa..956be263c09e 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -59,6 +59,7 @@ void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_st
void intel_psr_pause(struct intel_dp *intel_dp);
void intel_psr_resume(struct intel_dp *intel_dp);
bool intel_psr_needs_block_dc_vblank(const struct intel_crtc_state *crtc_state);
+bool intel_psr_link_ok(struct intel_dp *intel_dp);
void intel_psr_lock(const struct intel_crtc_state *crtc_state);
void intel_psr_unlock(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h
index 0841242543ca..9ad7611506e8 100644
--- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
@@ -298,7 +298,7 @@
#define _PORT_ALPM_CTL_B 0x16fc2c
#define PORT_ALPM_CTL(port) _MMIO_PORT(port, _PORT_ALPM_CTL_A, _PORT_ALPM_CTL_B)
#define PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE REG_BIT(31)
-#define PORT_ALPM_CTL_MAX_PHY_SWING_SETUP_MASK REG_GENMASK(23, 20)
+#define PORT_ALPM_CTL_MAX_PHY_SWING_SETUP_MASK REG_GENMASK(25, 20)
#define PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(val) REG_FIELD_PREP(PORT_ALPM_CTL_MAX_PHY_SWING_SETUP_MASK, val)
#define PORT_ALPM_CTL_MAX_PHY_SWING_HOLD_MASK REG_GENMASK(19, 16)
#define PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(val) REG_FIELD_PREP(PORT_ALPM_CTL_MAX_PHY_SWING_HOLD_MASK, val)
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index b83bf813677d..7a28104f68ad 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2082,10 +2082,10 @@ intel_sdvo_get_edid(struct drm_connector *connector)
static const struct drm_edid *
intel_sdvo_get_analog_edid(struct drm_connector *connector)
{
- struct drm_i915_private *i915 = to_i915(connector->dev);
+ struct intel_display *display = to_intel_display(connector->dev);
struct i2c_adapter *ddc;
- ddc = intel_gmbus_get_adapter(i915, i915->display.vbt.crt_ddc_pin);
+ ddc = intel_gmbus_get_adapter(display, display->vbt.crt_ddc_pin);
if (!ddc)
return NULL;
@@ -2638,6 +2638,7 @@ intel_sdvo_select_ddc_bus(struct intel_sdvo *sdvo,
static void
intel_sdvo_select_i2c_bus(struct intel_sdvo *sdvo)
{
+ struct intel_display *display = to_intel_display(&sdvo->base);
struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
const struct sdvo_device_mapping *mapping;
u8 pin;
@@ -2648,7 +2649,7 @@ intel_sdvo_select_i2c_bus(struct intel_sdvo *sdvo)
mapping = &dev_priv->display.vbt.sdvo_mappings[1];
if (mapping->initialized &&
- intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin))
+ intel_gmbus_is_valid_pin(display, mapping->i2c_pin))
pin = mapping->i2c_pin;
else
pin = GMBUS_PIN_DPB;
@@ -2657,7 +2658,7 @@ intel_sdvo_select_i2c_bus(struct intel_sdvo *sdvo)
sdvo->base.base.base.id, sdvo->base.base.name,
pin, sdvo->target_addr);
- sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);
+ sdvo->i2c = intel_gmbus_get_adapter(display, pin);
/*
* With gmbus we should be able to drive sdvo i2c at 2MHz, but somehow
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
index e6df1f92def5..4b3a32736fd6 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -1997,6 +1997,7 @@ int intel_snps_phy_check_hdmi_link_rate(int clock)
void intel_mpllb_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
+ struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -2019,11 +2020,11 @@ void intel_mpllb_state_verify(struct intel_atomic_state *state,
intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state);
#define MPLLB_CHECK(__name) \
- I915_STATE_WARN(i915, mpllb_sw_state->__name != mpllb_hw_state.__name, \
- "[CRTC:%d:%s] mismatch in MPLLB: %s (expected 0x%08x, found 0x%08x)", \
- crtc->base.base.id, crtc->base.name, \
- __stringify(__name), \
- mpllb_sw_state->__name, mpllb_hw_state.__name)
+ INTEL_DISPLAY_STATE_WARN(display, mpllb_sw_state->__name != mpllb_hw_state.__name, \
+ "[CRTC:%d:%s] mismatch in MPLLB: %s (expected 0x%08x, found 0x%08x)", \
+ crtc->base.base.id, crtc->base.name, \
+ __stringify(__name), \
+ mpllb_sw_state->__name, mpllb_hw_state.__name)
MPLLB_CHECK(mpllb_cp);
MPLLB_CHECK(mpllb_div);
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index 6f2ee7dbc43b..b16c4d2d4077 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -1005,7 +1005,7 @@ xelpdp_tc_phy_wait_for_tcss_power(struct intel_tc_port *tc, bool enabled)
if (wait_for(xelpdp_tc_phy_tcss_power_is_enabled(tc) == enabled, 5)) {
drm_dbg_kms(&i915->drm,
"Port %s: timeout waiting for TCSS power to get %s\n",
- enabled ? "enabled" : "disabled",
+ str_enabled_disabled(enabled),
tc->port_name);
return false;
}
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index e40aff490486..27c530218ee6 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -929,7 +929,7 @@ intel_enable_tv(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
- struct intel_display *display = to_intel_display(state);
+ struct intel_display *display = to_intel_display(encoder);
/* Prevents vblank waits from timing out in intel_tv_detect_type() */
intel_crtc_wait_for_next_vblank(to_intel_crtc(pipe_config->uapi.crtc));
@@ -943,7 +943,7 @@ intel_disable_tv(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
- struct intel_display *display = to_intel_display(state);
+ struct intel_display *display = to_intel_display(encoder);
intel_de_rmw(display, TV_CTL, TV_ENC_ENABLE, 0);
}
@@ -1093,7 +1093,6 @@ intel_tv_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct intel_display *display = to_intel_display(encoder);
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
struct drm_display_mode mode = {};
@@ -1167,7 +1166,7 @@ intel_tv_get_config(struct intel_encoder *encoder,
adjusted_mode->crtc_clock /= 2;
/* pixel counter doesn't work on i965gm TV output */
- if (IS_I965GM(dev_priv))
+ if (display->platform.i965gm)
pipe_config->mode_flags |=
I915_MODE_FLAG_USE_SCANLINE_COUNTER;
}
@@ -1197,7 +1196,6 @@ intel_tv_compute_config(struct intel_encoder *encoder,
struct intel_atomic_state *state =
to_intel_atomic_state(pipe_config->uapi.state);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_tv_connector_state *tv_conn_state =
to_intel_tv_connector_state(conn_state);
const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);
@@ -1349,7 +1347,7 @@ intel_tv_compute_config(struct intel_encoder *encoder,
adjusted_mode->name[0] = '\0';
/* pixel counter doesn't work on i965gm TV output */
- if (IS_I965GM(dev_priv))
+ if (display->platform.i965gm)
pipe_config->mode_flags |=
I915_MODE_FLAG_USE_SCANLINE_COUNTER;
@@ -1525,7 +1523,7 @@ static void intel_tv_pre_enable(struct intel_atomic_state *state,
tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
/* Enable two fixes for the chips that need them. */
- if (IS_I915GM(dev_priv))
+ if (display->platform.i915gm)
tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
set_tv_mode_timings(display, tv_mode, burst_ena);
@@ -1627,7 +1625,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
* The TV sense state should be cleared to zero on cantiga platform. Otherwise
* the TV is misdetected. This is hardware requirement.
*/
- if (IS_GM45(dev_priv))
+ if (display->platform.gm45)
tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c
index d18b8292be49..a95fb3349eba 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -195,7 +195,6 @@ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc)
int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
/*
* The scanline counter increments at the leading edge of hsync.
@@ -225,7 +224,7 @@ int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state)
*/
if (DISPLAY_VER(display) == 2)
return -1;
- else if (HAS_DDI(i915) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ else if (HAS_DDI(display) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
return 2;
else
return 1;
@@ -327,14 +326,13 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,
const struct drm_display_mode *mode)
{
struct intel_display *display = to_intel_display(_crtc->dev);
- struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc *crtc = to_intel_crtc(_crtc);
enum pipe pipe = crtc->pipe;
int position;
int vbl_start, vbl_end, hsync_start, htotal, vtotal;
unsigned long irqflags;
bool use_scanline_counter = DISPLAY_VER(display) >= 5 ||
- IS_G4X(dev_priv) || DISPLAY_VER(display) == 2 ||
+ display->platform.g4x || DISPLAY_VER(display) == 2 ||
crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER;
if (drm_WARN_ON(display->drm, !mode->crtc_clock)) {
@@ -603,14 +601,15 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state,
struct intel_vblank_evade_ctx *evade)
{
+ struct intel_display *display = to_intel_display(new_crtc_state);
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct intel_crtc_state *crtc_state;
const struct drm_display_mode *adjusted_mode;
evade->crtc = crtc;
- evade->need_vlv_dsi_wa = (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) &&
+ evade->need_vlv_dsi_wa = (display->platform.valleyview ||
+ display->platform.cherryview) &&
intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
/*
diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c
index 2c76a0176a35..fd18dd07ae49 100644
--- a/drivers/gpu/drm/i915/display/intel_vga.c
+++ b/drivers/gpu/drm/i915/display/intel_vga.c
@@ -16,9 +16,7 @@
static i915_reg_t intel_vga_cntrl_reg(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
-
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ if (display->platform.valleyview || display->platform.cherryview)
return VLV_VGACNTRL;
else if (DISPLAY_VER(display) >= 5)
return CPU_VGACNTRL;
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index 9a51f5bac307..19a5d0076bb8 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -56,6 +56,11 @@ bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh)
vrefresh <= info->monitor_range.max_vfreq;
}
+bool intel_vrr_possible(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->vrr.flipline;
+}
+
void
intel_vrr_check_modeset(struct intel_atomic_state *state)
{
@@ -239,11 +244,16 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
(crtc_state->hw.adjusted_mode.crtc_vtotal -
crtc_state->hw.adjusted_mode.vsync_end);
}
+}
+
+void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+
+ if (!intel_vrr_possible(crtc_state))
+ return;
- /*
- * For XE_LPD+, we use guardband and pipeline override
- * is deprecated.
- */
if (DISPLAY_VER(display) >= 13) {
crtc_state->vrr.guardband =
crtc_state->vrr.vmin + 1 - adjusted_mode->crtc_vblank_start;
@@ -281,7 +291,7 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
intel_de_rmw(display, CHICKEN_TRANS(cpu_transcoder),
0, PIPE_VBLANK_WITH_DELAY);
- if (!crtc_state->vrr.flipline) {
+ if (!intel_vrr_possible(crtc_state)) {
intel_de_write(display,
TRANS_VRR_CTL(display, cpu_transcoder), 0);
return;
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
index 89937858200d..b3b45c675020 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
@@ -15,9 +15,11 @@ struct intel_crtc_state;
bool intel_vrr_is_capable(struct intel_connector *connector);
bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh);
+bool intel_vrr_possible(const struct intel_crtc_state *crtc_state);
void intel_vrr_check_modeset(struct intel_atomic_state *state);
void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
+void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state);
void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
void intel_vrr_enable(const struct intel_crtc_state *crtc_state);
void intel_vrr_send_push(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index baa601d27815..7dbc99b02eaa 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -272,7 +272,6 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
to_intel_plane(plane_state->uapi.plane);
struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
struct drm_framebuffer *fb = plane_state->hw.fb;
- int ret;
bool force_detach = !fb || !plane_state->uapi.visible;
bool need_scaler = false;
@@ -281,72 +280,16 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
fb && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
need_scaler = true;
- ret = skl_update_scaler(crtc_state, force_detach,
- drm_plane_index(&intel_plane->base),
- &plane_state->scaler_id,
- drm_rect_width(&plane_state->uapi.src) >> 16,
- drm_rect_height(&plane_state->uapi.src) >> 16,
- drm_rect_width(&plane_state->uapi.dst),
- drm_rect_height(&plane_state->uapi.dst),
- fb ? fb->format : NULL,
- fb ? fb->modifier : 0,
- need_scaler);
-
- if (ret || plane_state->scaler_id < 0)
- return ret;
-
- /* check colorkey */
- if (plane_state->ckey.flags) {
- drm_dbg_kms(&dev_priv->drm,
- "[PLANE:%d:%s] scaling with color key not allowed",
- intel_plane->base.base.id,
- intel_plane->base.name);
- return -EINVAL;
- }
-
- /* Check src format */
- switch (fb->format->format) {
- case DRM_FORMAT_RGB565:
- case DRM_FORMAT_XBGR8888:
- case DRM_FORMAT_XRGB8888:
- case DRM_FORMAT_ABGR8888:
- case DRM_FORMAT_ARGB8888:
- case DRM_FORMAT_XRGB2101010:
- case DRM_FORMAT_XBGR2101010:
- case DRM_FORMAT_ARGB2101010:
- case DRM_FORMAT_ABGR2101010:
- case DRM_FORMAT_YUYV:
- case DRM_FORMAT_YVYU:
- case DRM_FORMAT_UYVY:
- case DRM_FORMAT_VYUY:
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_XYUV8888:
- case DRM_FORMAT_P010:
- case DRM_FORMAT_P012:
- case DRM_FORMAT_P016:
- case DRM_FORMAT_Y210:
- case DRM_FORMAT_Y212:
- case DRM_FORMAT_Y216:
- case DRM_FORMAT_XVYU2101010:
- case DRM_FORMAT_XVYU12_16161616:
- case DRM_FORMAT_XVYU16161616:
- break;
- case DRM_FORMAT_XBGR16161616F:
- case DRM_FORMAT_ABGR16161616F:
- case DRM_FORMAT_XRGB16161616F:
- case DRM_FORMAT_ARGB16161616F:
- if (DISPLAY_VER(dev_priv) >= 11)
- break;
- fallthrough;
- default:
- drm_dbg_kms(&dev_priv->drm,
- "[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n",
- intel_plane->base.base.id, intel_plane->base.name,
- fb->base.id, fb->format->format);
- return -EINVAL;
- }
-
- return 0;
+ return skl_update_scaler(crtc_state, force_detach,
+ drm_plane_index(&intel_plane->base),
+ &plane_state->scaler_id,
+ drm_rect_width(&plane_state->uapi.src) >> 16,
+ drm_rect_height(&plane_state->uapi.src) >> 16,
+ drm_rect_width(&plane_state->uapi.dst),
+ drm_rect_height(&plane_state->uapi.dst),
+ fb ? fb->format : NULL,
+ fb ? fb->modifier : 0,
+ need_scaler);
}
static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index a0a7ed01415a..038ca2ec5d7a 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -431,6 +431,16 @@ static int icl_plane_min_width(const struct drm_framebuffer *fb,
}
}
+static int xe3_plane_max_width(const struct drm_framebuffer *fb,
+ int color_plane,
+ unsigned int rotation)
+{
+ if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
+ return 4096;
+ else
+ return 6144;
+}
+
static int icl_hdr_plane_max_width(const struct drm_framebuffer *fb,
int color_plane,
unsigned int rotation)
@@ -1567,17 +1577,22 @@ skl_plane_async_flip(struct intel_dsb *dsb,
struct intel_display *display = to_intel_display(plane->base.dev);
enum plane_id plane_id = plane->id;
enum pipe pipe = plane->pipe;
- u32 plane_ctl = plane_state->ctl;
+ u32 plane_ctl = plane_state->ctl, plane_surf;
plane_ctl |= skl_plane_ctl_crtc(crtc_state);
+ plane_surf = skl_plane_surf(plane_state, 0);
- if (async_flip)
- plane_ctl |= PLANE_CTL_ASYNC_FLIP;
+ if (async_flip) {
+ if (DISPLAY_VER(display) >= 30)
+ plane_surf |= PLANE_SURF_ASYNC_UPDATE;
+ else
+ plane_ctl |= PLANE_CTL_ASYNC_FLIP;
+ }
intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
plane_ctl);
intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
- skl_plane_surf(plane_state, 0));
+ plane_surf);
}
static bool intel_format_is_p01x(u32 format)
@@ -2584,7 +2599,11 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
intel_fbc_add_plane(skl_plane_fbc(dev_priv, pipe, plane_id), plane);
- if (DISPLAY_VER(dev_priv) >= 11) {
+ if (DISPLAY_VER(dev_priv) >= 30) {
+ plane->max_width = xe3_plane_max_width;
+ plane->max_height = icl_plane_max_height;
+ plane->min_cdclk = icl_plane_min_cdclk;
+ } else if (DISPLAY_VER(dev_priv) >= 11) {
plane->min_width = icl_plane_min_width;
if (icl_is_hdr_plane(dev_priv, plane_id))
plane->max_width = icl_hdr_plane_max_width;
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h b/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h
index 4ddcd7d46bbd..ff31a00d511e 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h
@@ -159,6 +159,7 @@
_PLANE_SURF_2_A, _PLANE_SURF_2_B)
#define PLANE_SURF_ADDR_MASK REG_GENMASK(31, 12)
#define PLANE_SURF_DECRYPT REG_BIT(2)
+#define PLANE_SURF_ASYNC_UPDATE REG_BIT(0)
#define _PLANE_KEYMAX_1_A 0x701a0
#define _PLANE_KEYMAX_2_A 0x702a0
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 6e1f04d5ef47..3b0e87edbacf 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -718,7 +718,7 @@ static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
int width, const struct drm_format_info *format,
u64 modifier, unsigned int rotation,
u32 plane_pixel_rate, struct skl_wm_params *wp,
- int color_plane);
+ int color_plane, unsigned int pan_x);
static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
struct intel_plane *plane,
@@ -765,7 +765,7 @@ skl_cursor_allocation(const struct intel_crtc_state *crtc_state,
drm_format_info(DRM_FORMAT_ARGB8888),
DRM_FORMAT_MOD_LINEAR,
DRM_MODE_ROTATE_0,
- crtc_state->pixel_rate, &wp, 0);
+ crtc_state->pixel_rate, &wp, 0, 0);
drm_WARN_ON(&i915->drm, ret);
for (level = 0; level < i915->display.wm.num_levels; level++) {
@@ -1742,7 +1742,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
int width, const struct drm_format_info *format,
u64 modifier, unsigned int rotation,
u32 plane_pixel_rate, struct skl_wm_params *wp,
- int color_plane)
+ int color_plane, unsigned int pan_x)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
@@ -1803,7 +1803,9 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
wp->y_min_scanlines,
wp->dbuf_block_size);
- if (DISPLAY_VER(i915) >= 10)
+ if (DISPLAY_VER(i915) >= 30)
+ interm_pbpl += (pan_x != 0);
+ else if (DISPLAY_VER(i915) >= 10)
interm_pbpl++;
wp->plane_blocks_per_line = div_fixed16(interm_pbpl,
@@ -1845,7 +1847,8 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state,
fb->format, fb->modifier,
plane_state->hw.rotation,
intel_plane_pixel_rate(crtc_state, plane_state),
- wp, color_plane);
+ wp, color_plane,
+ plane_state->uapi.src.x1);
}
static bool skl_wm_has_lines(struct drm_i915_private *i915, int level)
@@ -1909,7 +1912,10 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
}
}
- blocks = fixed16_to_u32_round_up(selected_result) + 1;
+ blocks = fixed16_to_u32_round_up(selected_result);
+ if (DISPLAY_VER(i915) < 30)
+ blocks++;
+
/*
* Lets have blocks at minimum equivalent to plane_blocks_per_line
* as there will be at minimum one line for lines configuration. This
@@ -3527,7 +3533,7 @@ static void intel_mbus_dbox_update(struct intel_atomic_state *state)
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, new_dbuf_state->active_pipes) {
u32 pipe_val = val;
- if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) {
+ if (DISPLAY_VERx100(i915) == 1400) {
if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe,
new_dbuf_state->active_pipes))
pipe_val |= MBUS_DBOX_BW_8CREDITS_MTL;
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 32d15bd9a358..9383eedee2d4 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -44,6 +44,7 @@
#include "intel_dsi_vbt.h"
#include "intel_fifo_underrun.h"
#include "intel_panel.h"
+#include "intel_pfit.h"
#include "skl_scaler.h"
#include "vlv_dsi.h"
#include "vlv_dsi_pll.h"
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
index 70c5a13a3c75..59a50647f2c3 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
@@ -592,15 +592,16 @@ void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
static void assert_dsi_pll(struct drm_i915_private *i915, bool state)
{
+ struct intel_display *display = &i915->display;
bool cur_state;
vlv_cck_get(i915);
cur_state = vlv_cck_read(i915, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN;
vlv_cck_put(i915);
- I915_STATE_WARN(i915, cur_state != state,
- "DSI PLL state assertion failure (expected %s, current %s)\n",
- str_on_off(state), str_on_off(cur_state));
+ INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
+ "DSI PLL state assertion failure (expected %s, current %s)\n",
+ str_on_off(state), str_on_off(cur_state));
}
void assert_dsi_pll_enabled(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/i915/gt/gen7_renderclear.c b/drivers/gpu/drm/i915/gt/gen7_renderclear.c
index d38b914d1206..6e89112f68ae 100644
--- a/drivers/gpu/drm/i915/gt/gen7_renderclear.c
+++ b/drivers/gpu/drm/i915/gt/gen7_renderclear.c
@@ -399,7 +399,8 @@ static void emit_batch(struct i915_vma * const vma,
batch_add(&cmds, MI_LOAD_REGISTER_IMM(2));
batch_add(&cmds, i915_mmio_reg_offset(CACHE_MODE_0_GEN7));
batch_add(&cmds, 0xffff0000 |
- ((IS_IVB_GT1(i915) || IS_VALLEYVIEW(i915)) ?
+ (((IS_IVYBRIDGE(i915) && INTEL_INFO(i915)->gt == 1) ||
+ IS_VALLEYVIEW(i915)) ?
HIZ_RAW_STALL_OPT_DISABLE :
0));
batch_add(&cmds, i915_mmio_reg_offset(CACHE_MODE_1));
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index a6c69a706fd7..c4a351ebf395 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -185,7 +185,7 @@ int intel_gt_init_hw(struct intel_gt *gt)
if (IS_HASWELL(i915))
intel_uncore_write(uncore,
HSW_MI_PREDICATE_RESULT_2,
- IS_HASWELL_GT3(i915) ?
+ INTEL_INFO(i915)->gt == 3 ?
LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
/* Apply the GT workarounds... */
@@ -302,7 +302,7 @@ static void gen6_check_faults(struct intel_gt *gt)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
- u32 fault;
+ unsigned long fault;
for_each_engine(engine, gt, id) {
fault = GEN6_RING_FAULT_REG_READ(engine);
@@ -310,8 +310,8 @@ static void gen6_check_faults(struct intel_gt *gt)
gt_dbg(gt, "Unexpected fault\n"
"\tAddr: 0x%08lx\n"
"\tAddress space: %s\n"
- "\tSource ID: %d\n"
- "\tType: %d\n",
+ "\tSource ID: %ld\n"
+ "\tType: %ld\n",
fault & PAGE_MASK,
fault & RING_FAULT_GTTSEL_MASK ?
"GGTT" : "PPGTT",
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
index 0c1e405240af..1240d44eeb85 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -452,10 +452,10 @@ void gen8_gt_irq_reset(struct intel_gt *gt)
{
struct intel_uncore *uncore = gt->uncore;
- gen3_irq_reset(uncore, GEN8_GT_IRQ_REGS(0));
- gen3_irq_reset(uncore, GEN8_GT_IRQ_REGS(1));
- gen3_irq_reset(uncore, GEN8_GT_IRQ_REGS(2));
- gen3_irq_reset(uncore, GEN8_GT_IRQ_REGS(3));
+ gen2_irq_reset(uncore, GEN8_GT_IRQ_REGS(0));
+ gen2_irq_reset(uncore, GEN8_GT_IRQ_REGS(1));
+ gen2_irq_reset(uncore, GEN8_GT_IRQ_REGS(2));
+ gen2_irq_reset(uncore, GEN8_GT_IRQ_REGS(3));
}
void gen8_gt_irq_postinstall(struct intel_gt *gt)
@@ -476,14 +476,14 @@ void gen8_gt_irq_postinstall(struct intel_gt *gt)
gt->pm_ier = 0x0;
gt->pm_imr = ~gt->pm_ier;
- gen3_irq_init(uncore, GEN8_GT_IRQ_REGS(0), ~gt_interrupts[0], gt_interrupts[0]);
- gen3_irq_init(uncore, GEN8_GT_IRQ_REGS(1), ~gt_interrupts[1], gt_interrupts[1]);
+ gen2_irq_init(uncore, GEN8_GT_IRQ_REGS(0), ~gt_interrupts[0], gt_interrupts[0]);
+ gen2_irq_init(uncore, GEN8_GT_IRQ_REGS(1), ~gt_interrupts[1], gt_interrupts[1]);
/*
* RPS interrupts will get enabled/disabled on demand when RPS itself
* is enabled/disabled. Same wil be the case for GuC interrupts.
*/
- gen3_irq_init(uncore, GEN8_GT_IRQ_REGS(2), gt->pm_imr, gt->pm_ier);
- gen3_irq_init(uncore, GEN8_GT_IRQ_REGS(3), ~gt_interrupts[3], gt_interrupts[3]);
+ gen2_irq_init(uncore, GEN8_GT_IRQ_REGS(2), gt->pm_imr, gt->pm_ier);
+ gen2_irq_init(uncore, GEN8_GT_IRQ_REGS(3), ~gt_interrupts[3], gt_interrupts[3]);
}
static void gen5_gt_update_irq(struct intel_gt *gt,
@@ -514,9 +514,9 @@ void gen5_gt_irq_reset(struct intel_gt *gt)
{
struct intel_uncore *uncore = gt->uncore;
- gen3_irq_reset(uncore, GT_IRQ_REGS);
+ gen2_irq_reset(uncore, GT_IRQ_REGS);
if (GRAPHICS_VER(gt->i915) >= 6)
- gen3_irq_reset(uncore, GEN6_PM_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN6_PM_IRQ_REGS);
}
void gen5_gt_irq_postinstall(struct intel_gt *gt)
@@ -538,7 +538,7 @@ void gen5_gt_irq_postinstall(struct intel_gt *gt)
else
gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
- gen3_irq_init(uncore, GT_IRQ_REGS, gt->gt_imr, gt_irqs);
+ gen2_irq_init(uncore, GT_IRQ_REGS, gt->gt_imr, gt_irqs);
if (GRAPHICS_VER(gt->i915) >= 6) {
/*
@@ -551,6 +551,6 @@ void gen5_gt_irq_postinstall(struct intel_gt *gt)
}
gt->pm_imr = 0xffffffff;
- gen3_irq_init(uncore, GEN6_PM_IRQ_REGS, gt->pm_imr, pm_irqs);
+ gen2_irq_init(uncore, GEN6_PM_IRQ_REGS, gt->pm_imr, pm_irqs);
}
}
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 7bd5d2c29056..51847a846002 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -820,8 +820,10 @@ static bool ctx_needs_runalone(const struct intel_context *ce)
bool ctx_is_protected = false;
/*
- * On MTL and newer platforms, protected contexts require setting
- * the LRC run-alone bit or else the encryption will not happen.
+ * Wa_14019159160 - Case 2.
+ * On some platforms, protected contexts require setting
+ * the LRC run-alone bit or else the encryption/decryption will not happen.
+ * NOTE: Case 2 only applies to PXP use-case of said workaround.
*/
if (GRAPHICS_VER_FULL(ce->engine->i915) >= IP_VER(12, 70) &&
(ce->engine->class == COMPUTE_CLASS || ce->engine->class == RENDER_CLASS)) {
@@ -850,6 +852,7 @@ static void init_common_regs(u32 * const regs,
if (GRAPHICS_VER(engine->i915) < 11)
ctl |= _MASKED_BIT_DISABLE(CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT |
CTX_CTRL_RS_CTX_ENABLE);
+ /* Wa_14019159160 - Case 2.*/
if (ctx_needs_runalone(ce))
ctl |= _MASKED_BIT_ENABLE(GEN12_CTX_CTRL_RUNALONE_MODE);
regs[CTX_CONTEXT_CONTROL] = ctl;
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 6972525fe6be..570c91878189 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -418,7 +418,7 @@ static void bdw_ctx_workarounds_init(struct intel_engine_cs *engine,
/* WaForceContextSaveRestoreNonCoherent:bdw */
HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
/* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
- (IS_BROADWELL_GT3(i915) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
+ (INTEL_INFO(i915)->gt == 3 ? HDC_FENCE_DEST_SLM_DISABLE : 0));
}
static void chv_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -2546,7 +2546,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN7_FF_DS_SCHED_HW);
/* WaDisablePSDDualDispatchEnable:ivb */
- if (IS_IVB_GT1(i915))
+ if (INTEL_INFO(i915)->gt == 1)
wa_masked_en(wal,
GEN7_HALF_SLICE_CHICKEN1,
GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE);
diff --git a/drivers/gpu/drm/i915/gt/shmem_utils.c b/drivers/gpu/drm/i915/gt/shmem_utils.c
index 1fb6ff77fd89..bb696b29ee2c 100644
--- a/drivers/gpu/drm/i915/gt/shmem_utils.c
+++ b/drivers/gpu/drm/i915/gt/shmem_utils.c
@@ -40,7 +40,7 @@ struct file *shmem_create_from_object(struct drm_i915_gem_object *obj)
if (i915_gem_object_is_shmem(obj)) {
file = obj->base.filp;
- atomic_long_inc(&file->f_count);
+ get_file(file);
return file;
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c
index 551b0d7974ff..5dc0ccd07636 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c
@@ -80,6 +80,7 @@ int intel_gsc_fw_get_binary_info(struct intel_uc_fw *gsc_fw, const void *data, s
const struct intel_gsc_cpd_header_v2 *cpd_header = NULL;
const struct intel_gsc_cpd_entry *cpd_entry = NULL;
const struct intel_gsc_manifest_header *manifest;
+ struct intel_uc_fw_ver min_ver = { 0 };
size_t min_size = sizeof(*layout);
int i;
@@ -212,33 +213,46 @@ int intel_gsc_fw_get_binary_info(struct intel_uc_fw *gsc_fw, const void *data, s
}
}
- if (IS_ARROWLAKE(gt->i915)) {
+ /*
+ * ARL SKUs require newer firmwares, but the blob is actually common
+ * across all MTL and ARL SKUs, so we need to do an explicit version check
+ * here rather than using a separate table entry. If a too old version
+ * is found, then just don't use GSC rather than aborting the driver load.
+ * Note that the major number in the GSC FW version is used to indicate
+ * the platform, so we expect it to always be 102 for MTL/ARL binaries.
+ */
+ if (IS_ARROWLAKE_S(gt->i915))
+ min_ver = (struct intel_uc_fw_ver){ 102, 0, 10, 1878 };
+ else if (IS_ARROWLAKE_H(gt->i915) || IS_ARROWLAKE_U(gt->i915))
+ min_ver = (struct intel_uc_fw_ver){ 102, 1, 15, 1926 };
+
+ if (IS_METEORLAKE(gt->i915) && gsc->release.major != 102) {
+ gt_info(gt, "Invalid GSC firmware for MTL/ARL, got %d.%d.%d.%d but need 102.x.x.x",
+ gsc->release.major, gsc->release.minor,
+ gsc->release.patch, gsc->release.build);
+ return -EINVAL;
+ }
+
+ if (min_ver.major) {
bool too_old = false;
- /*
- * ARL requires a newer firmware than MTL did (102.0.10.1878) but the
- * firmware is actually common. So, need to do an explicit version check
- * here rather than using a separate table entry. And if the older
- * MTL-only version is found, then just don't use GSC rather than aborting
- * the driver load.
- */
- if (gsc->release.major < 102) {
+ if (gsc->release.minor < min_ver.minor) {
too_old = true;
- } else if (gsc->release.major == 102) {
- if (gsc->release.minor == 0) {
- if (gsc->release.patch < 10) {
+ } else if (gsc->release.minor == min_ver.minor) {
+ if (gsc->release.patch < min_ver.patch) {
+ too_old = true;
+ } else if (gsc->release.patch == min_ver.patch) {
+ if (gsc->release.build < min_ver.build)
too_old = true;
- } else if (gsc->release.patch == 10) {
- if (gsc->release.build < 1878)
- too_old = true;
- }
}
}
if (too_old) {
- gt_info(gt, "GSC firmware too old for ARL, got %d.%d.%d.%d but need at least 102.0.10.1878",
+ gt_info(gt, "GSC firmware too old for ARL, got %d.%d.%d.%d but need at least %d.%d.%d.%d",
gsc->release.major, gsc->release.minor,
- gsc->release.patch, gsc->release.build);
+ gsc->release.patch, gsc->release.build,
+ min_ver.major, min_ver.minor,
+ min_ver.patch, min_ver.build);
return -EINVAL;
}
}
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index c66d6d3177c8..17f74cb244bb 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -32,6 +32,8 @@
*
*/
+#include <drm/display/drm_dp.h>
+
#include "i915_drv.h"
#include "i915_reg.h"
#include "gvt.h"
@@ -568,7 +570,7 @@ static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
memcpy(port->dpcd->data, dpcd_fix_data, DPCD_HEADER_SIZE);
port->dpcd->data_valid = true;
- port->dpcd->data[DPCD_SINK_COUNT] = 0x1;
+ port->dpcd->data[DP_SINK_COUNT] = 0x1;
port->type = type;
port->id = resolution;
port->vrefresh_k = GVT_DEFAULT_REFRESH_RATE * MSEC_PER_SEC;
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index f5616f99ef2f..8090bc53c7e1 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -59,52 +59,10 @@ struct intel_vgpu;
#define INTEL_GVT_MAX_UEVENT_VARS 3
-/* DPCD start */
-#define DPCD_SIZE 0x700
-
-/* DPCD */
-#define DP_SET_POWER 0x600
-#define DP_SET_POWER_D0 0x1
-#define AUX_NATIVE_WRITE 0x8
-#define AUX_NATIVE_READ 0x9
-
-#define AUX_NATIVE_REPLY_MASK (0x3 << 4)
-#define AUX_NATIVE_REPLY_ACK (0x0 << 4)
#define AUX_NATIVE_REPLY_NAK (0x1 << 4)
-#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
#define AUX_BURST_SIZE 20
-/* DPCD addresses */
-#define DPCD_REV 0x000
-#define DPCD_MAX_LINK_RATE 0x001
-#define DPCD_MAX_LANE_COUNT 0x002
-
-#define DPCD_TRAINING_PATTERN_SET 0x102
-#define DPCD_SINK_COUNT 0x200
-#define DPCD_LANE0_1_STATUS 0x202
-#define DPCD_LANE2_3_STATUS 0x203
-#define DPCD_LANE_ALIGN_STATUS_UPDATED 0x204
-#define DPCD_SINK_STATUS 0x205
-
-/* link training */
-#define DPCD_TRAINING_PATTERN_SET_MASK 0x03
-#define DPCD_LINK_TRAINING_DISABLED 0x00
-#define DPCD_TRAINING_PATTERN_1 0x01
-#define DPCD_TRAINING_PATTERN_2 0x02
-
-#define DPCD_CP_READY_MASK (1 << 6)
-
-/* lane status */
-#define DPCD_LANES_CR_DONE 0x11
-#define DPCD_LANES_EQ_DONE 0x22
-#define DPCD_SYMBOL_LOCKED 0x44
-
-#define DPCD_INTERLANE_ALIGN_DONE 0x01
-
-#define DPCD_SINK_IN_SYNC 0x03
-/* DPCD end */
-
#define SBI_RESPONSE_MASK 0x3
#define SBI_RESPONSE_SHIFT 0x1
#define SBI_STAT_MASK 0x1
diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c
index c022dc736045..0a357ca42db1 100644
--- a/drivers/gpu/drm/i915/gvt/edid.c
+++ b/drivers/gpu/drm/i915/gvt/edid.c
@@ -32,6 +32,8 @@
*
*/
+#include <drm/display/drm_dp.h>
+
#include "display/intel_dp_aux_regs.h"
#include "display/intel_gmbus_regs.h"
#include "gvt.h"
@@ -504,13 +506,13 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
}
/* Always set the wanted value for vms. */
- ret_msg_size = (((op & 0x1) == GVT_AUX_I2C_READ) ? 2 : 1);
+ ret_msg_size = (((op & 0x1) == DP_AUX_I2C_READ) ? 2 : 1);
vgpu_vreg(vgpu, offset) =
DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_MESSAGE_SIZE(ret_msg_size);
if (msg_length == 3) {
- if (!(op & GVT_AUX_I2C_MOT)) {
+ if (!(op & DP_AUX_I2C_MOT)) {
/* stop */
intel_vgpu_init_i2c_edid(vgpu);
} else {
@@ -530,7 +532,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
i2c_edid->edid_available = true;
}
}
- } else if ((op & 0x1) == GVT_AUX_I2C_WRITE) {
+ } else if ((op & 0x1) == DP_AUX_I2C_WRITE) {
/* TODO
* We only support EDID reading from I2C_over_AUX. And
* we do not expect the index mode to be used. Right now
@@ -538,7 +540,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
* support the gfx driver to do EDID access.
*/
} else {
- if (drm_WARN_ON(&i915->drm, (op & 0x1) != GVT_AUX_I2C_READ))
+ if (drm_WARN_ON(&i915->drm, (op & 0x1) != DP_AUX_I2C_READ))
return;
if (drm_WARN_ON(&i915->drm, msg_length != 4))
return;
@@ -553,7 +555,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
* ACK of I2C_WRITE
* returned byte if it is READ
*/
- aux_data_for_write |= GVT_AUX_I2C_REPLY_ACK << 24;
+ aux_data_for_write |= DP_AUX_I2C_REPLY_ACK << 24;
vgpu_vreg(vgpu, offset + 4) = aux_data_for_write;
}
diff --git a/drivers/gpu/drm/i915/gvt/edid.h b/drivers/gpu/drm/i915/gvt/edid.h
index c3b5a55aecb3..13fd06590929 100644
--- a/drivers/gpu/drm/i915/gvt/edid.h
+++ b/drivers/gpu/drm/i915/gvt/edid.h
@@ -42,14 +42,6 @@ struct intel_vgpu;
#define EDID_SIZE 128
#define EDID_ADDR 0x50 /* Linux hvm EDID addr */
-#define GVT_AUX_NATIVE_WRITE 0x8
-#define GVT_AUX_NATIVE_READ 0x9
-#define GVT_AUX_I2C_WRITE 0x0
-#define GVT_AUX_I2C_READ 0x1
-#define GVT_AUX_I2C_STATUS 0x2
-#define GVT_AUX_I2C_MOT 0x4
-#define GVT_AUX_I2C_REPLY_ACK 0x0
-
struct intel_vgpu_edid_data {
bool data_valid;
unsigned char edid_block[EDID_SIZE];
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index 0f09344d3c20..9494d812c00a 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -36,6 +36,8 @@
*/
+#include <drm/display/drm_dp.h>
+
#include "i915_drv.h"
#include "i915_reg.h"
#include "gvt.h"
@@ -1129,29 +1131,36 @@ static int dp_aux_ch_ctl_trans_done(struct intel_vgpu *vgpu, u32 value,
static void dp_aux_ch_ctl_link_training(struct intel_vgpu_dpcd_data *dpcd,
u8 t)
{
- if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == DPCD_TRAINING_PATTERN_1) {
+ if ((t & DP_TRAINING_PATTERN_MASK) == DP_TRAINING_PATTERN_1) {
/* training pattern 1 for CR */
/* set LANE0_CR_DONE, LANE1_CR_DONE */
- dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_CR_DONE;
+ dpcd->data[DP_LANE0_1_STATUS] |= DP_LANE_CR_DONE |
+ DP_LANE_CR_DONE << 4;
/* set LANE2_CR_DONE, LANE3_CR_DONE */
- dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_CR_DONE;
- } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) ==
- DPCD_TRAINING_PATTERN_2) {
+ dpcd->data[DP_LANE2_3_STATUS] |= DP_LANE_CR_DONE |
+ DP_LANE_CR_DONE << 4;
+ } else if ((t & DP_TRAINING_PATTERN_MASK) ==
+ DP_TRAINING_PATTERN_2) {
/* training pattern 2 for EQ */
/* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane0_1 */
- dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_EQ_DONE;
- dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_SYMBOL_LOCKED;
+ dpcd->data[DP_LANE0_1_STATUS] |= DP_LANE_CHANNEL_EQ_DONE |
+ DP_LANE_CHANNEL_EQ_DONE << 4;
+ dpcd->data[DP_LANE0_1_STATUS] |= DP_LANE_SYMBOL_LOCKED |
+ DP_LANE_SYMBOL_LOCKED << 4;
/* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane2_3 */
- dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_EQ_DONE;
- dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_SYMBOL_LOCKED;
+ dpcd->data[DP_LANE2_3_STATUS] |= DP_LANE_CHANNEL_EQ_DONE |
+ DP_LANE_CHANNEL_EQ_DONE << 4;
+ dpcd->data[DP_LANE2_3_STATUS] |= DP_LANE_SYMBOL_LOCKED |
+ DP_LANE_SYMBOL_LOCKED << 4;
/* set INTERLANE_ALIGN_DONE */
- dpcd->data[DPCD_LANE_ALIGN_STATUS_UPDATED] |=
- DPCD_INTERLANE_ALIGN_DONE;
- } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) ==
- DPCD_LINK_TRAINING_DISABLED) {
+ dpcd->data[DP_LANE_ALIGN_STATUS_UPDATED] |=
+ DP_INTERLANE_ALIGN_DONE;
+ } else if ((t & DP_TRAINING_PATTERN_MASK) ==
+ DP_TRAINING_PATTERN_DISABLE) {
/* finish link training */
/* set sink status as synchronized */
- dpcd->data[DPCD_SINK_STATUS] = DPCD_SINK_IN_SYNC;
+ dpcd->data[DP_SINK_STATUS] = DP_RECEIVE_PORT_0_STATUS |
+ DP_RECEIVE_PORT_1_STATUS;
}
}
@@ -1206,7 +1215,7 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
len = msg & 0xff;
op = ctrl >> 4;
- if (op == GVT_AUX_NATIVE_WRITE) {
+ if (op == DP_AUX_NATIVE_WRITE) {
int t;
u8 buf[16];
@@ -1252,7 +1261,7 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
dpcd->data[p] = buf[t];
/* check for link training */
- if (p == DPCD_TRAINING_PATTERN_SET)
+ if (p == DP_TRAINING_PATTERN_SET)
dp_aux_ch_ctl_link_training(dpcd,
buf[t]);
}
@@ -1265,7 +1274,7 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
return 0;
}
- if (op == GVT_AUX_NATIVE_READ) {
+ if (op == DP_AUX_NATIVE_READ) {
int idx, i, ret = 0;
if ((addr + len + 1) >= DPCD_SIZE) {
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index 5ec293011d99..35319228bc51 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -212,7 +212,7 @@ active_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
struct i915_active_fence *active =
container_of(cb, typeof(*active), cb);
- return cmpxchg(__active_fence_slot(active), fence, NULL) == fence;
+ return try_cmpxchg(__active_fence_slot(active), &fence, NULL);
}
static void
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a66e5bb078cf..7b1a061d92fb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -507,8 +507,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
(IS_PLATFORM(i915, INTEL_IRONLAKE) && IS_MOBILE(i915))
#define IS_SANDYBRIDGE(i915) IS_PLATFORM(i915, INTEL_SANDYBRIDGE)
#define IS_IVYBRIDGE(i915) IS_PLATFORM(i915, INTEL_IVYBRIDGE)
-#define IS_IVB_GT1(i915) (IS_IVYBRIDGE(i915) && \
- INTEL_INFO(i915)->gt == 1)
#define IS_VALLEYVIEW(i915) IS_PLATFORM(i915, INTEL_VALLEYVIEW)
#define IS_CHERRYVIEW(i915) IS_PLATFORM(i915, INTEL_CHERRYVIEW)
#define IS_HASWELL(i915) IS_PLATFORM(i915, INTEL_HASWELL)
@@ -538,9 +536,14 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
*/
#define IS_LUNARLAKE(i915) (0 && i915)
#define IS_BATTLEMAGE(i915) (0 && i915)
-
-#define IS_ARROWLAKE(i915) \
- IS_SUBPLATFORM(i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_ARL)
+#define IS_PANTHERLAKE(i915) (0 && i915)
+
+#define IS_ARROWLAKE_H(i915) \
+ IS_SUBPLATFORM(i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_ARL_H)
+#define IS_ARROWLAKE_U(i915) \
+ IS_SUBPLATFORM(i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_ARL_U)
+#define IS_ARROWLAKE_S(i915) \
+ IS_SUBPLATFORM(i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_ARL_S)
#define IS_DG2_G10(i915) \
IS_SUBPLATFORM(i915, INTEL_DG2, INTEL_SUBPLATFORM_G10)
#define IS_DG2_G11(i915) \
@@ -561,14 +564,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
IS_SUBPLATFORM(i915, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULT)
#define IS_BROADWELL_ULX(i915) \
IS_SUBPLATFORM(i915, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULX)
-#define IS_BROADWELL_GT3(i915) (IS_BROADWELL(i915) && \
- INTEL_INFO(i915)->gt == 3)
#define IS_HASWELL_ULT(i915) \
IS_SUBPLATFORM(i915, INTEL_HASWELL, INTEL_SUBPLATFORM_ULT)
-#define IS_HASWELL_GT3(i915) (IS_HASWELL(i915) && \
- INTEL_INFO(i915)->gt == 3)
-#define IS_HASWELL_GT1(i915) (IS_HASWELL(i915) && \
- INTEL_INFO(i915)->gt == 1)
/* ULX machines are also considered ULT. */
#define IS_HASWELL_ULX(i915) \
IS_SUBPLATFORM(i915, INTEL_HASWELL, INTEL_SUBPLATFORM_ULX)
@@ -580,31 +577,14 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
IS_SUBPLATFORM(i915, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULT)
#define IS_KABYLAKE_ULX(i915) \
IS_SUBPLATFORM(i915, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULX)
-#define IS_SKYLAKE_GT2(i915) (IS_SKYLAKE(i915) && \
- INTEL_INFO(i915)->gt == 2)
-#define IS_SKYLAKE_GT3(i915) (IS_SKYLAKE(i915) && \
- INTEL_INFO(i915)->gt == 3)
-#define IS_SKYLAKE_GT4(i915) (IS_SKYLAKE(i915) && \
- INTEL_INFO(i915)->gt == 4)
-#define IS_KABYLAKE_GT2(i915) (IS_KABYLAKE(i915) && \
- INTEL_INFO(i915)->gt == 2)
-#define IS_KABYLAKE_GT3(i915) (IS_KABYLAKE(i915) && \
- INTEL_INFO(i915)->gt == 3)
#define IS_COFFEELAKE_ULT(i915) \
IS_SUBPLATFORM(i915, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULT)
#define IS_COFFEELAKE_ULX(i915) \
IS_SUBPLATFORM(i915, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULX)
-#define IS_COFFEELAKE_GT2(i915) (IS_COFFEELAKE(i915) && \
- INTEL_INFO(i915)->gt == 2)
-#define IS_COFFEELAKE_GT3(i915) (IS_COFFEELAKE(i915) && \
- INTEL_INFO(i915)->gt == 3)
-
#define IS_COMETLAKE_ULT(i915) \
IS_SUBPLATFORM(i915, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULT)
#define IS_COMETLAKE_ULX(i915) \
IS_SUBPLATFORM(i915, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULX)
-#define IS_COMETLAKE_GT2(i915) (IS_COMETLAKE(i915) && \
- INTEL_INFO(i915)->gt == 2)
#define IS_ICL_WITH_PORT_F(i915) \
IS_SUBPLATFORM(i915, INTEL_ICELAKE, INTEL_SUBPLATFORM_PORTF)
@@ -677,7 +657,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
/* WaRsDisableCoarsePowerGating:skl,cnl */
#define NEEDS_WaRsDisableCoarsePowerGating(i915) \
- (IS_SKYLAKE_GT3(i915) || IS_SKYLAKE_GT4(i915))
+ (IS_SKYLAKE(i915) && (INTEL_INFO(i915)->gt == 3 || INTEL_INFO(i915)->gt == 4))
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
* rows, which changed the alignment requirements and fence programming.
@@ -741,7 +721,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
/* DPF == dynamic parity feature */
#define HAS_L3_DPF(i915) (INTEL_INFO(i915)->has_l3_dpf)
-#define NUM_L3_SLICES(i915) (IS_HASWELL_GT3(i915) ? \
+#define NUM_L3_SLICES(i915) (IS_HASWELL(i915) && INTEL_INFO(i915)->gt == 3 ? \
2 : HAS_L3_DPF(i915))
#define HAS_GUC_DEPRIVILEGE(i915) \
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 135ded17334e..4eb58887819a 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1104,7 +1104,7 @@ i915_vma_coredump_create(const struct intel_gt *gt,
}
INIT_LIST_HEAD(&dst->page_list);
- strcpy(dst->name, name);
+ strscpy(dst->name, name);
dst->next = NULL;
dst->gtt_offset = vma_res->start;
@@ -1404,7 +1404,7 @@ static bool record_context(struct i915_gem_context_coredump *e,
rcu_read_lock();
task = pid_task(ctx->pid, PIDTYPE_PID);
if (task) {
- strcpy(e->comm, task->comm);
+ strscpy(e->comm, task->comm);
e->pid = task->pid;
}
rcu_read_unlock();
@@ -1450,7 +1450,7 @@ capture_vma_snapshot(struct intel_engine_capture_vma *next,
return next;
}
- strcpy(c->name, name);
+ strscpy(c->name, name);
c->vma_res = i915_vma_resource_get(vma_res);
c->next = next;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 333d58343b37..f75cbf5b8a1c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -77,7 +77,7 @@ static inline void pmu_irq_stats(struct drm_i915_private *i915,
WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1);
}
-void gen3_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs)
+void gen2_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs)
{
intel_uncore_write(uncore, regs.imr, 0xffffffff);
intel_uncore_posting_read(uncore, regs.imr);
@@ -94,7 +94,7 @@ void gen3_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs)
/*
* We should clear IMR at preinstall/uninstall, and just check at postinstall.
*/
-void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
+void gen2_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
{
u32 val = intel_uncore_read(uncore, reg);
@@ -110,10 +110,10 @@ void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
intel_uncore_posting_read(uncore, reg);
}
-void gen3_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
+void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
u32 imr_val, u32 ier_val)
{
- gen3_assert_iir_is_zero(uncore, regs.iir);
+ gen2_assert_iir_is_zero(uncore, regs.iir);
intel_uncore_write(uncore, regs.ier, ier_val);
intel_uncore_write(uncore, regs.imr, imr_val);
@@ -622,7 +622,7 @@ static void ibx_irq_reset(struct drm_i915_private *dev_priv)
if (HAS_PCH_NOP(dev_priv))
return;
- gen3_irq_reset(uncore, SDE_IRQ_REGS);
+ gen2_irq_reset(uncore, SDE_IRQ_REGS);
if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff);
@@ -634,7 +634,7 @@ static void ilk_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
- gen3_irq_reset(uncore, DE_IRQ_REGS);
+ gen2_irq_reset(uncore, DE_IRQ_REGS);
dev_priv->irq_mask = ~0u;
if (GRAPHICS_VER(dev_priv) == 7)
@@ -671,7 +671,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv)
gen8_gt_irq_reset(to_gt(dev_priv));
gen8_display_irq_reset(dev_priv);
- gen3_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
if (HAS_PCH_SPLIT(dev_priv))
ibx_irq_reset(dev_priv);
@@ -688,8 +688,8 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv)
gen11_gt_irq_reset(gt);
gen11_display_irq_reset(dev_priv);
- gen3_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS);
- gen3_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
}
static void dg1_irq_reset(struct drm_i915_private *dev_priv)
@@ -705,8 +705,8 @@ static void dg1_irq_reset(struct drm_i915_private *dev_priv)
gen11_display_irq_reset(dev_priv);
- gen3_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS);
- gen3_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
intel_uncore_write(uncore, GEN11_GFX_MSTR_IRQ, ~0);
}
@@ -720,7 +720,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
gen8_gt_irq_reset(to_gt(dev_priv));
- gen3_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
spin_lock_irq(&dev_priv->irq_lock);
if (dev_priv->display.irq.display_irqs_enabled)
@@ -765,7 +765,7 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
gen11_gt_irq_postinstall(gt);
gen11_de_irq_postinstall(dev_priv);
- gen3_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked);
+ gen2_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked);
gen11_master_intr_enable(intel_uncore_regs(uncore));
intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
@@ -781,7 +781,7 @@ static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
for_each_gt(gt, dev_priv, i)
gen11_gt_irq_postinstall(gt);
- gen3_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked);
+ gen2_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked);
dg1_de_irq_postinstall(dev_priv);
@@ -869,7 +869,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv)
i9xx_display_irq_reset(dev_priv);
- gen3_irq_reset(uncore, GEN2_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN2_IRQ_REGS);
dev_priv->irq_mask = ~0u;
}
@@ -901,7 +901,7 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
}
- gen3_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->irq_mask, enable_mask);
+ gen2_irq_init(uncore, GEN2_IRQ_REGS, 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. */
@@ -974,7 +974,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv)
i9xx_display_irq_reset(dev_priv);
- gen3_irq_reset(uncore, GEN2_IRQ_REGS);
+ gen2_irq_reset(uncore, GEN2_IRQ_REGS);
dev_priv->irq_mask = ~0u;
}
@@ -1022,7 +1022,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
if (IS_G4X(dev_priv))
enable_mask |= I915_BSD_USER_INTERRUPT;
- gen3_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->irq_mask, enable_mask);
+ gen2_irq_init(uncore, GEN2_IRQ_REGS, 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. */
diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h
index da3d97143511..0457f6402e05 100644
--- a/drivers/gpu/drm/i915/i915_irq.h
+++ b/drivers/gpu/drm/i915/i915_irq.h
@@ -40,11 +40,11 @@ bool intel_irqs_enabled(struct drm_i915_private *dev_priv);
void intel_synchronize_irq(struct drm_i915_private *i915);
void intel_synchronize_hardirq(struct drm_i915_private *i915);
-void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg);
+void gen2_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg);
-void gen3_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs);
+void gen2_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs);
-void gen3_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
+void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
u32 imr_val, u32 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 eaf8a098e1c5..21006c7f615c 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -24,7 +24,7 @@
#include <drm/drm_color_mgmt.h>
#include <drm/drm_drv.h>
-#include <drm/intel/i915_pciids.h>
+#include <drm/intel/pciids.h>
#include "display/intel_display_driver.h"
#include "gt/intel_gt_regs.h"
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 818142f5a10c..22be4a731d27 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1735,13 +1735,6 @@
#define PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK REG_GENMASK(2, 0) /* tgl+ */
#define PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id) REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
-#define _ICL_PIPE_A_STATUS 0x70058
-#define ICL_PIPESTATUS(dev_priv, pipe) _MMIO_PIPE2(dev_priv, pipe, _ICL_PIPE_A_STATUS)
-#define PIPE_STATUS_UNDERRUN REG_BIT(31)
-#define PIPE_STATUS_SOFT_UNDERRUN_XELPD REG_BIT(28)
-#define PIPE_STATUS_HARD_UNDERRUN_XELPD REG_BIT(27)
-#define PIPE_STATUS_PORT_UNDERRUN_XELPD REG_BIT(26)
-
#define VLV_DPFLIPSTAT _MMIO(VLV_DISPLAY_BASE + 0x70028)
#define PIPEB_LINE_COMPARE_INT_EN REG_BIT(29)
#define PIPEB_HLINE_INT_EN REG_BIT(28)
@@ -2512,9 +2505,7 @@
#define GEN12_PIPEDMC_INTERRUPT REG_BIT(26) /* tgl+ */
#define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl+ */
#define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl+ */
-#define XELPD_PIPE_SOFT_UNDERRUN REG_BIT(22) /* adl/dg2+ */
#define GEN11_PIPE_PLANE7_FAULT REG_BIT(22) /* icl/tgl */
-#define XELPD_PIPE_HARD_UNDERRUN REG_BIT(21) /* adl/dg2+ */
#define GEN11_PIPE_PLANE6_FAULT REG_BIT(21) /* icl/tgl */
#define GEN11_PIPE_PLANE5_FAULT REG_BIT(20) /* icl+ */
#define GEN12_PIPE_VBLANK_UNMOD REG_BIT(19) /* tgl+ */
@@ -2598,6 +2589,7 @@
#define GEN8_DE_MISC_GSE REG_BIT(27)
#define GEN8_DE_EDP_PSR REG_BIT(19)
#define XELPDP_PMDEMAND_RSP REG_BIT(3)
+#define XE2LPD_DBUF_OVERLAP_DETECTED REG_BIT(1)
#define GEN8_DE_MISC_IRQ_REGS I915_IRQ_REGS(GEN8_DE_MISC_IMR, \
GEN8_DE_MISC_IER, \
@@ -2705,6 +2697,7 @@
#define XELPDP_PMDEMAND_QCLK_GV_BW_MASK REG_GENMASK(31, 16)
#define XELPDP_PMDEMAND_VOLTAGE_INDEX_MASK REG_GENMASK(14, 12)
#define XELPDP_PMDEMAND_QCLK_GV_INDEX_MASK REG_GENMASK(11, 8)
+#define XE3_PMDEMAND_PIPES_MASK REG_GENMASK(7, 4)
#define XELPDP_PMDEMAND_PIPES_MASK REG_GENMASK(7, 6)
#define XELPDP_PMDEMAND_DBUFS_MASK REG_GENMASK(5, 4)
#define XELPDP_PMDEMAND_PHYS_MASK REG_GENMASK(2, 0)
@@ -2903,6 +2896,7 @@
#define SKL_DFSM_PIPE_C_DISABLE (1 << 28)
#define TGL_DFSM_PIPE_D_DISABLE (1 << 22)
#define GLK_DFSM_DISPLAY_DSC_DISABLE (1 << 7)
+#define XE2LPD_DFSM_DBUF_OVERLAP_DISABLE (1 << 3)
#define XE2LPD_DE_CAP _MMIO(0x41100)
#define XE2LPD_DE_CAP_3DLUT_MASK REG_GENMASK(31, 30)
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 519e096c607c..8f62cfa23fb7 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -273,11 +273,6 @@ i915_request_active_engine(struct i915_request *rq,
return ret;
}
-static void __rq_init_watchdog(struct i915_request *rq)
-{
- rq->watchdog.timer.function = NULL;
-}
-
static enum hrtimer_restart __rq_watchdog_expired(struct hrtimer *hrtimer)
{
struct i915_request *rq =
@@ -294,6 +289,14 @@ static enum hrtimer_restart __rq_watchdog_expired(struct hrtimer *hrtimer)
return HRTIMER_NORESTART;
}
+static void __rq_init_watchdog(struct i915_request *rq)
+{
+ struct i915_request_watchdog *wdg = &rq->watchdog;
+
+ hrtimer_init(&wdg->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ wdg->timer.function = __rq_watchdog_expired;
+}
+
static void __rq_arm_watchdog(struct i915_request *rq)
{
struct i915_request_watchdog *wdg = &rq->watchdog;
@@ -304,8 +307,6 @@ static void __rq_arm_watchdog(struct i915_request *rq)
i915_request_get(rq);
- hrtimer_init(&wdg->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- wdg->timer.function = __rq_watchdog_expired;
hrtimer_start_range_ns(&wdg->timer,
ns_to_ktime(ce->watchdog.timeout_us *
NSEC_PER_USEC),
@@ -317,7 +318,7 @@ static void __rq_cancel_watchdog(struct i915_request *rq)
{
struct i915_request_watchdog *wdg = &rq->watchdog;
- if (wdg->timer.function && hrtimer_try_to_cancel(&wdg->timer) > 0)
+ if (hrtimer_try_to_cancel(&wdg->timer) > 0)
i915_request_put(rq);
}
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 9d3d9b983032..f18f1acf2158 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -137,5 +137,5 @@ void i915_restore_display(struct drm_i915_private *dev_priv)
intel_vga_redisable(display);
- intel_gmbus_reset(dev_priv);
+ intel_gmbus_reset(display);
}
diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c
index 26c4dbda076e..f76642886569 100644
--- a/drivers/gpu/drm/i915/intel_clock_gating.c
+++ b/drivers/gpu/drm/i915/intel_clock_gating.c
@@ -502,7 +502,7 @@ static void ivb_init_clock_gating(struct drm_i915_private *i915)
CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
CHICKEN3_DGMG_DONE_FIX_DISABLE);
- if (IS_IVB_GT1(i915))
+ if (INTEL_INFO(i915)->gt == 1)
intel_uncore_write(&i915->uncore, GEN7_ROW_CHICKEN2,
_MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
else {
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c
index 3c47c625993e..856b30fa37dc 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -25,7 +25,7 @@
#include <linux/string_helpers.h>
#include <drm/drm_print.h>
-#include <drm/intel/i915_pciids.h>
+#include <drm/intel/pciids.h>
#include "gt/intel_gt_regs.h"
#include "i915_drv.h"
@@ -200,8 +200,16 @@ static const u16 subplatform_g12_ids[] = {
INTEL_DG2_G12_IDS(ID),
};
-static const u16 subplatform_arl_ids[] = {
- INTEL_ARL_IDS(ID),
+static const u16 subplatform_arl_h_ids[] = {
+ INTEL_ARL_H_IDS(ID),
+};
+
+static const u16 subplatform_arl_u_ids[] = {
+ INTEL_ARL_U_IDS(ID),
+};
+
+static const u16 subplatform_arl_s_ids[] = {
+ INTEL_ARL_S_IDS(ID),
};
static bool find_devid(u16 id, const u16 *p, unsigned int num)
@@ -261,9 +269,15 @@ static void intel_device_info_subplatform_init(struct drm_i915_private *i915)
} else if (find_devid(devid, subplatform_g12_ids,
ARRAY_SIZE(subplatform_g12_ids))) {
mask = BIT(INTEL_SUBPLATFORM_G12);
- } else if (find_devid(devid, subplatform_arl_ids,
- ARRAY_SIZE(subplatform_arl_ids))) {
- mask = BIT(INTEL_SUBPLATFORM_ARL);
+ } else if (find_devid(devid, subplatform_arl_h_ids,
+ ARRAY_SIZE(subplatform_arl_h_ids))) {
+ mask = BIT(INTEL_SUBPLATFORM_ARL_H);
+ } else if (find_devid(devid, subplatform_arl_u_ids,
+ ARRAY_SIZE(subplatform_arl_u_ids))) {
+ mask = BIT(INTEL_SUBPLATFORM_ARL_U);
+ } else if (find_devid(devid, subplatform_arl_s_ids,
+ ARRAY_SIZE(subplatform_arl_s_ids))) {
+ mask = BIT(INTEL_SUBPLATFORM_ARL_S);
}
GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_MASK);
diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
index 4f4aa4ff9963..ef84eea9ba0b 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -128,7 +128,9 @@ enum intel_platform {
#define INTEL_SUBPLATFORM_RPLU 2
/* MTL */
-#define INTEL_SUBPLATFORM_ARL 0
+#define INTEL_SUBPLATFORM_ARL_H 0
+#define INTEL_SUBPLATFORM_ARL_U 1
+#define INTEL_SUBPLATFORM_ARL_S 2
enum intel_ppgtt_type {
INTEL_PPGTT_NONE = I915_GEM_PPGTT_NONE,
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h
index 126f8320f86e..e22669d61e95 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.h
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.h
@@ -96,10 +96,16 @@ intel_rpm_wakelock_count(int wakeref_count)
return wakeref_count >> INTEL_RPM_WAKELOCK_SHIFT;
}
+static inline bool
+intel_runtime_pm_suspended(struct intel_runtime_pm *rpm)
+{
+ return pm_runtime_suspended(rpm->kdev);
+}
+
static inline void
assert_rpm_device_not_suspended(struct intel_runtime_pm *rpm)
{
- WARN_ONCE(pm_runtime_suspended(rpm->kdev),
+ WARN_ONCE(intel_runtime_pm_suspended(rpm),
"Device suspended during HW access\n");
}
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c
index 61da4ed9d521..0727492576be 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem.c
@@ -4,7 +4,7 @@
* Copyright © 2018 Intel Corporation
*/
-#include <linux/random.h>
+#include <linux/prandom.h>
#include "gem/i915_gem_internal.h"
#include "gem/i915_gem_pm.h"
diff --git a/drivers/gpu/drm/i915/selftests/i915_random.h b/drivers/gpu/drm/i915/selftests/i915_random.h
index 05364eca20f7..70330a2e80f2 100644
--- a/drivers/gpu/drm/i915/selftests/i915_random.h
+++ b/drivers/gpu/drm/i915/selftests/i915_random.h
@@ -26,7 +26,7 @@
#define __I915_SELFTESTS_RANDOM_H__
#include <linux/math64.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include "../i915_selftest.h"
diff --git a/drivers/gpu/drm/i915/selftests/scatterlist.c b/drivers/gpu/drm/i915/selftests/scatterlist.c
index 805c4bfb85fe..7e59591bbed6 100644
--- a/drivers/gpu/drm/i915/selftests/scatterlist.c
+++ b/drivers/gpu/drm/i915/selftests/scatterlist.c
@@ -22,7 +22,7 @@
*/
#include <linux/prime_numbers.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include "i915_selftest.h"
#include "i915_utils.h"
diff --git a/drivers/gpu/drm/imagination/pvr_context.c b/drivers/gpu/drm/imagination/pvr_context.c
index 98327f9bbd9c..5edc3c01af72 100644
--- a/drivers/gpu/drm/imagination/pvr_context.c
+++ b/drivers/gpu/drm/imagination/pvr_context.c
@@ -17,10 +17,14 @@
#include <drm/drm_auth.h>
#include <drm/drm_managed.h>
+
+#include <linux/bug.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/xarray.h>
@@ -342,6 +346,10 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
return err;
}
+ spin_lock(&pvr_dev->ctx_list_lock);
+ list_add_tail(&ctx->file_link, &pvr_file->contexts);
+ spin_unlock(&pvr_dev->ctx_list_lock);
+
return 0;
err_destroy_fw_obj:
@@ -368,6 +376,11 @@ pvr_context_release(struct kref *ref_count)
container_of(ref_count, struct pvr_context, ref_count);
struct pvr_device *pvr_dev = ctx->pvr_dev;
+ WARN_ON(in_interrupt());
+ spin_lock(&pvr_dev->ctx_list_lock);
+ list_del(&ctx->file_link);
+ spin_unlock(&pvr_dev->ctx_list_lock);
+
xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
pvr_context_destroy_queues(ctx);
pvr_fw_object_destroy(ctx->fw_obj);
@@ -425,11 +438,30 @@ pvr_context_destroy(struct pvr_file *pvr_file, u32 handle)
*/
void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
{
+ struct pvr_device *pvr_dev = pvr_file->pvr_dev;
struct pvr_context *ctx;
unsigned long handle;
xa_for_each(&pvr_file->ctx_handles, handle, ctx)
pvr_context_destroy(pvr_file, handle);
+
+ spin_lock(&pvr_dev->ctx_list_lock);
+ ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
+
+ while (!list_entry_is_head(ctx, &pvr_file->contexts, file_link)) {
+ list_del_init(&ctx->file_link);
+
+ if (pvr_context_get_if_referenced(ctx)) {
+ spin_unlock(&pvr_dev->ctx_list_lock);
+
+ pvr_vm_unmap_all(ctx->vm_ctx);
+
+ pvr_context_put(ctx);
+ spin_lock(&pvr_dev->ctx_list_lock);
+ }
+ ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
+ }
+ spin_unlock(&pvr_dev->ctx_list_lock);
}
/**
@@ -439,6 +471,7 @@ void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
void pvr_context_device_init(struct pvr_device *pvr_dev)
{
xa_init_flags(&pvr_dev->ctx_ids, XA_FLAGS_ALLOC1);
+ spin_lock_init(&pvr_dev->ctx_list_lock);
}
/**
diff --git a/drivers/gpu/drm/imagination/pvr_context.h b/drivers/gpu/drm/imagination/pvr_context.h
index 0c7b97dfa6ba..07afa179cdf4 100644
--- a/drivers/gpu/drm/imagination/pvr_context.h
+++ b/drivers/gpu/drm/imagination/pvr_context.h
@@ -85,6 +85,9 @@ struct pvr_context {
/** @compute: Transfer queue. */
struct pvr_queue *transfer;
} queues;
+
+ /** @file_link: pvr_file PVR context list link. */
+ struct list_head file_link;
};
static __always_inline struct pvr_queue *
@@ -124,6 +127,24 @@ pvr_context_get(struct pvr_context *ctx)
}
/**
+ * pvr_context_get_if_referenced() - Take an additional reference on a still
+ * referenced context.
+ * @ctx: Context pointer.
+ *
+ * Call pvr_context_put() to release.
+ *
+ * Returns:
+ * * True on success, or
+ * * false if no context pointer passed, or the context wasn't still
+ * * referenced.
+ */
+static __always_inline bool
+pvr_context_get_if_referenced(struct pvr_context *ctx)
+{
+ return ctx != NULL && kref_get_unless_zero(&ctx->ref_count) != 0;
+}
+
+/**
* pvr_context_lookup() - Lookup context pointer from handle and file.
* @pvr_file: Pointer to pvr_file structure.
* @handle: Context handle.
diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index b574e23d484b..6d0dfacb677b 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/math.h>
#include <linux/mutex.h>
+#include <linux/spinlock_types.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/wait.h>
@@ -293,6 +294,12 @@ struct pvr_device {
/** @sched_wq: Workqueue for schedulers. */
struct workqueue_struct *sched_wq;
+
+ /**
+ * @ctx_list_lock: Lock to be held when accessing the context list in
+ * struct pvr_file.
+ */
+ spinlock_t ctx_list_lock;
};
/**
@@ -344,6 +351,9 @@ struct pvr_file {
* This array is used to allocate handles returned to userspace.
*/
struct xarray vm_ctx_handles;
+
+ /** @contexts: PVR context list. */
+ struct list_head contexts;
};
/**
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 684a9b9a2247..36c0e768698e 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -28,6 +28,7 @@
#include <linux/export.h>
#include <linux/fs.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -1326,6 +1327,8 @@ pvr_drm_driver_open(struct drm_device *drm_dev, struct drm_file *file)
*/
pvr_file->pvr_dev = pvr_dev;
+ INIT_LIST_HEAD(&pvr_file->contexts);
+
xa_init_flags(&pvr_file->ctx_handles, XA_FLAGS_ALLOC1);
xa_init_flags(&pvr_file->free_list_handles, XA_FLAGS_ALLOC1);
xa_init_flags(&pvr_file->hwrt_handles, XA_FLAGS_ALLOC1);
diff --git a/drivers/gpu/drm/imagination/pvr_vm.c b/drivers/gpu/drm/imagination/pvr_vm.c
index 39773991710a..363f885a7098 100644
--- a/drivers/gpu/drm/imagination/pvr_vm.c
+++ b/drivers/gpu/drm/imagination/pvr_vm.c
@@ -14,6 +14,7 @@
#include <drm/drm_gem.h>
#include <drm/drm_gpuvm.h>
+#include <linux/bug.h>
#include <linux/container_of.h>
#include <linux/err.h>
#include <linux/errno.h>
@@ -597,12 +598,26 @@ err_free:
}
/**
- * pvr_vm_context_release() - Teardown a VM context.
- * @ref_count: Pointer to reference counter of the VM context.
+ * pvr_vm_unmap_all() - Unmap all mappings associated with a VM context.
+ * @vm_ctx: Target VM context.
*
* This function ensures that no mappings are left dangling by unmapping them
* all in order of ascending device-virtual address.
*/
+void
+pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx)
+{
+ WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
+ vm_ctx->gpuvm_mgr.mm_range));
+}
+
+/**
+ * pvr_vm_context_release() - Teardown a VM context.
+ * @ref_count: Pointer to reference counter of the VM context.
+ *
+ * This function also ensures that no mappings are left dangling by calling
+ * pvr_vm_unmap_all.
+ */
static void
pvr_vm_context_release(struct kref *ref_count)
{
@@ -612,8 +627,7 @@ pvr_vm_context_release(struct kref *ref_count)
if (vm_ctx->fw_mem_ctx_obj)
pvr_fw_object_destroy(vm_ctx->fw_mem_ctx_obj);
- WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
- vm_ctx->gpuvm_mgr.mm_range));
+ pvr_vm_unmap_all(vm_ctx);
pvr_mmu_context_destroy(vm_ctx->mmu_ctx);
drm_gem_private_object_fini(&vm_ctx->dummy_gem);
diff --git a/drivers/gpu/drm/imagination/pvr_vm.h b/drivers/gpu/drm/imagination/pvr_vm.h
index f2a6463f2b05..79406243617c 100644
--- a/drivers/gpu/drm/imagination/pvr_vm.h
+++ b/drivers/gpu/drm/imagination/pvr_vm.h
@@ -39,6 +39,7 @@ int pvr_vm_map(struct pvr_vm_context *vm_ctx,
struct pvr_gem_object *pvr_obj, u64 pvr_obj_offset,
u64 device_addr, u64 size);
int pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size);
+void pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx);
dma_addr_t pvr_vm_get_page_table_root_addr(struct pvr_vm_context *vm_ctx);
struct dma_resv *pvr_vm_get_dma_resv(struct pvr_vm_context *vm_ctx);
diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/drm/lib/drm_random.h
index 5543bf0474bc..9f827260a89d 100644
--- a/drivers/gpu/drm/lib/drm_random.h
+++ b/drivers/gpu/drm/lib/drm_random.h
@@ -6,7 +6,7 @@
* be transposed to lib/ at the earliest convenience.
*/
-#include <linux/random.h>
+#include <linux/prandom.h>
#define DRM_RND_STATE_INITIALIZER(seed__) ({ \
struct rnd_state state__; \
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 2e0e7c4079b6..f496e6cfdfe0 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -2,7 +2,7 @@
config DRM_MEDIATEK
tristate "DRM Support for Mediatek SoCs"
depends on DRM
- depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
+ depends on ARCH_MEDIATEK || COMPILE_TEST
depends on COMMON_CLK
depends on HAVE_ARM_SMCCC || COMPILE_TEST
depends on OF
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 04154db9085c..04217a36939c 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -109,6 +109,7 @@ size_t mtk_ovl_get_num_formats(struct device *dev);
void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
+bool mtk_ovl_adaptor_is_comp_present(struct device_node *node);
void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev,
unsigned int next);
void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index bf2546c4681a..187855d83590 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -497,6 +497,41 @@ static int compare_of(struct device *dev, void *data)
return dev->of_node == data;
}
+static int ovl_adaptor_of_get_ddp_comp_type(struct device_node *node,
+ enum mtk_ovl_adaptor_comp_type *ctype)
+{
+ const struct of_device_id *of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node);
+
+ if (!of_id)
+ return -EINVAL;
+
+ *ctype = (enum mtk_ovl_adaptor_comp_type)((uintptr_t)of_id->data);
+
+ return 0;
+}
+
+bool mtk_ovl_adaptor_is_comp_present(struct device_node *node)
+{
+ enum mtk_ovl_adaptor_comp_type type;
+ int ret;
+
+ ret = ovl_adaptor_of_get_ddp_comp_type(node, &type);
+ if (ret)
+ return false;
+
+ if (type >= OVL_ADAPTOR_TYPE_NUM)
+ return false;
+
+ /*
+ * In the context of mediatek-drm, ETHDR, MDP_RDMA and Padding are
+ * used exclusively by OVL Adaptor: if this component is not one of
+ * those, it's likely not an OVL Adaptor path.
+ */
+ return type == OVL_ADAPTOR_TYPE_ETHDR ||
+ type == OVL_ADAPTOR_TYPE_MDP_RDMA ||
+ type == OVL_ADAPTOR_TYPE_PADDING;
+}
+
static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match)
{
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
@@ -506,12 +541,11 @@ static int ovl_adaptor_comp_init(struct device *dev, struct component_match **ma
parent = dev->parent->parent->of_node->parent;
for_each_child_of_node_scoped(parent, node) {
- const struct of_device_id *of_id;
enum mtk_ovl_adaptor_comp_type type;
- int id;
+ int id, ret;
- of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node);
- if (!of_id)
+ ret = ovl_adaptor_of_get_ddp_comp_type(node, &type);
+ if (ret)
continue;
if (!of_device_is_available(node)) {
@@ -520,7 +554,6 @@ static int ovl_adaptor_comp_init(struct device *dev, struct component_match **ma
continue;
}
- type = (enum mtk_ovl_adaptor_comp_type)(uintptr_t)of_id->data;
id = ovl_adaptor_comp_get_id(dev, node, type);
if (id < 0) {
dev_warn(dev, "Skipping unknown component %pOF\n",
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index a08d20654954..20a9d589fd75 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -704,6 +704,20 @@ static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
+ int ret;
+
+ dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 1, -1);
+ if (IS_ERR(dpi->next_bridge)) {
+ ret = PTR_ERR(dpi->next_bridge);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ /* Old devicetree has only one endpoint */
+ dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 0, 0);
+ if (IS_ERR(dpi->next_bridge))
+ return dev_err_probe(dpi->dev, PTR_ERR(dpi->next_bridge),
+ "Failed to get bridge\n");
+ }
return drm_bridge_attach(bridge->encoder, dpi->next_bridge,
&dpi->bridge, flags);
@@ -1058,13 +1072,6 @@ static int mtk_dpi_probe(struct platform_device *pdev)
if (dpi->irq < 0)
return dpi->irq;
- dpi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
- if (IS_ERR(dpi->next_bridge))
- return dev_err_probe(dev, PTR_ERR(dpi->next_bridge),
- "Failed to get bridge\n");
-
- dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node);
-
platform_set_drvdata(pdev, dpi);
dpi->bridge.funcs = &mtk_dpi_bridge_funcs;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index a4594f8873d5..9a8ef8558da9 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -27,6 +27,7 @@
#include "mtk_crtc.h"
#include "mtk_ddp_comp.h"
+#include "mtk_disp_drv.h"
#include "mtk_drm_drv.h"
#include "mtk_gem.h"
@@ -372,12 +373,11 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
struct mtk_drm_private *temp_drm_priv;
struct device_node *phandle = dev->parent->of_node;
const struct of_device_id *of_id;
- struct device_node *node;
struct device *drm_dev;
unsigned int cnt = 0;
int i, j;
- for_each_child_of_node(phandle->parent, node) {
+ for_each_child_of_node_scoped(phandle->parent, node) {
struct platform_device *pdev;
of_id = of_match_node(mtk_drm_of_ids, node);
@@ -820,12 +820,235 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
{ }
};
+static int mtk_drm_of_get_ddp_comp_type(struct device_node *node, enum mtk_ddp_comp_type *ctype)
+{
+ const struct of_device_id *of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
+
+ if (!of_id)
+ return -EINVAL;
+
+ *ctype = (enum mtk_ddp_comp_type)((uintptr_t)of_id->data);
+
+ return 0;
+}
+
+static int mtk_drm_of_get_ddp_ep_cid(struct device_node *node,
+ int output_port, enum mtk_crtc_path crtc_path,
+ struct device_node **next, unsigned int *cid)
+{
+ struct device_node *ep_dev_node, *ep_out;
+ enum mtk_ddp_comp_type comp_type;
+ int ret;
+
+ ep_out = of_graph_get_endpoint_by_regs(node, output_port, crtc_path);
+ if (!ep_out)
+ return -ENOENT;
+
+ ep_dev_node = of_graph_get_remote_port_parent(ep_out);
+ of_node_put(ep_out);
+ if (!ep_dev_node)
+ return -EINVAL;
+
+ /*
+ * Pass the next node pointer regardless of failures in the later code
+ * so that if this function is called in a loop it will walk through all
+ * of the subsequent endpoints anyway.
+ */
+ *next = ep_dev_node;
+
+ if (!of_device_is_available(ep_dev_node))
+ return -ENODEV;
+
+ ret = mtk_drm_of_get_ddp_comp_type(ep_dev_node, &comp_type);
+ if (ret) {
+ if (mtk_ovl_adaptor_is_comp_present(ep_dev_node)) {
+ *cid = (unsigned int)DDP_COMPONENT_DRM_OVL_ADAPTOR;
+ return 0;
+ }
+ return ret;
+ }
+
+ ret = mtk_ddp_comp_get_id(ep_dev_node, comp_type);
+ if (ret < 0)
+ return ret;
+
+ /* All ok! Pass the Component ID to the caller. */
+ *cid = (unsigned int)ret;
+
+ return 0;
+}
+
+/**
+ * mtk_drm_of_ddp_path_build_one - Build a Display HW Pipeline for a CRTC Path
+ * @dev: The mediatek-drm device
+ * @cpath: CRTC Path relative to a VDO or MMSYS
+ * @out_path: Pointer to an array that will contain the new pipeline
+ * @out_path_len: Number of entries in the pipeline array
+ *
+ * MediaTek SoCs can use different DDP hardware pipelines (or paths) depending
+ * on the board-specific desired display configuration; this function walks
+ * through all of the output endpoints starting from a VDO or MMSYS hardware
+ * instance and builds the right pipeline as specified in device trees.
+ *
+ * Return:
+ * * %0 - Display HW Pipeline successfully built and validated
+ * * %-ENOENT - Display pipeline was not specified in device tree
+ * * %-EINVAL - Display pipeline built but validation failed
+ * * %-ENOMEM - Failure to allocate pipeline array to pass to the caller
+ */
+static int mtk_drm_of_ddp_path_build_one(struct device *dev, enum mtk_crtc_path cpath,
+ const unsigned int **out_path,
+ unsigned int *out_path_len)
+{
+ struct device_node *next, *prev, *vdo = dev->parent->of_node;
+ unsigned int temp_path[DDP_COMPONENT_DRM_ID_MAX] = { 0 };
+ unsigned int *final_ddp_path;
+ unsigned short int idx = 0;
+ bool ovl_adaptor_comp_added = false;
+ int ret;
+
+ /* Get the first entry for the temp_path array */
+ ret = mtk_drm_of_get_ddp_ep_cid(vdo, 0, cpath, &next, &temp_path[idx]);
+ if (ret) {
+ if (next && temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) {
+ dev_dbg(dev, "Adding OVL Adaptor for %pOF\n", next);
+ ovl_adaptor_comp_added = true;
+ } else {
+ if (next)
+ dev_err(dev, "Invalid component %pOF\n", next);
+ else
+ dev_err(dev, "Cannot find first endpoint for path %d\n", cpath);
+
+ return ret;
+ }
+ }
+ idx++;
+
+ /*
+ * Walk through port outputs until we reach the last valid mediatek-drm component.
+ * To be valid, this must end with an "invalid" component that is a display node.
+ */
+ do {
+ prev = next;
+ ret = mtk_drm_of_get_ddp_ep_cid(next, 1, cpath, &next, &temp_path[idx]);
+ of_node_put(prev);
+ if (ret) {
+ of_node_put(next);
+ break;
+ }
+
+ /*
+ * If this is an OVL adaptor exclusive component and one of those
+ * was already added, don't add another instance of the generic
+ * DDP_COMPONENT_OVL_ADAPTOR, as this is used only to decide whether
+ * to probe that component master driver of which only one instance
+ * is needed and possible.
+ */
+ if (temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) {
+ if (!ovl_adaptor_comp_added)
+ ovl_adaptor_comp_added = true;
+ else
+ idx--;
+ }
+ } while (++idx < DDP_COMPONENT_DRM_ID_MAX);
+
+ /*
+ * The device component might not be enabled: in that case, don't
+ * check the last entry and just report that the device is missing.
+ */
+ if (ret == -ENODEV)
+ return ret;
+
+ /* If the last entry is not a final display output, the configuration is wrong */
+ switch (temp_path[idx - 1]) {
+ case DDP_COMPONENT_DP_INTF0:
+ case DDP_COMPONENT_DP_INTF1:
+ case DDP_COMPONENT_DPI0:
+ case DDP_COMPONENT_DPI1:
+ case DDP_COMPONENT_DSI0:
+ case DDP_COMPONENT_DSI1:
+ case DDP_COMPONENT_DSI2:
+ case DDP_COMPONENT_DSI3:
+ break;
+ default:
+ dev_err(dev, "Invalid display hw pipeline. Last component: %d (ret=%d)\n",
+ temp_path[idx - 1], ret);
+ return -EINVAL;
+ }
+
+ final_ddp_path = devm_kmemdup(dev, temp_path, idx * sizeof(temp_path[0]), GFP_KERNEL);
+ if (!final_ddp_path)
+ return -ENOMEM;
+
+ dev_dbg(dev, "Display HW Pipeline built with %d components.\n", idx);
+
+ /* Pipeline built! */
+ *out_path = final_ddp_path;
+ *out_path_len = idx;
+
+ return 0;
+}
+
+static int mtk_drm_of_ddp_path_build(struct device *dev, struct device_node *node,
+ struct mtk_mmsys_driver_data *data)
+{
+ struct device_node *ep_node;
+ struct of_endpoint of_ep;
+ bool output_present[MAX_CRTC] = { false };
+ int ret;
+
+ for_each_endpoint_of_node(node, ep_node) {
+ ret = of_graph_parse_endpoint(ep_node, &of_ep);
+ if (ret) {
+ dev_err_probe(dev, ret, "Cannot parse endpoint\n");
+ break;
+ }
+
+ if (of_ep.id >= MAX_CRTC) {
+ ret = dev_err_probe(dev, -EINVAL,
+ "Invalid endpoint%u number\n", of_ep.port);
+ break;
+ }
+
+ output_present[of_ep.id] = true;
+ }
+
+ if (ret) {
+ of_node_put(ep_node);
+ return ret;
+ }
+
+ if (output_present[CRTC_MAIN]) {
+ ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_MAIN,
+ &data->main_path, &data->main_len);
+ if (ret && ret != -ENODEV)
+ return ret;
+ }
+
+ if (output_present[CRTC_EXT]) {
+ ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_EXT,
+ &data->ext_path, &data->ext_len);
+ if (ret && ret != -ENODEV)
+ return ret;
+ }
+
+ if (output_present[CRTC_THIRD]) {
+ ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_THIRD,
+ &data->third_path, &data->third_len);
+ if (ret && ret != -ENODEV)
+ return ret;
+ }
+
+ return 0;
+}
+
static int mtk_drm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *phandle = dev->parent->of_node;
const struct of_device_id *of_id;
struct mtk_drm_private *private;
+ struct mtk_mmsys_driver_data *mtk_drm_data;
struct device_node *node;
struct component_match *match = NULL;
struct platform_device *ovl_adaptor;
@@ -846,7 +1069,27 @@ static int mtk_drm_probe(struct platform_device *pdev)
if (!of_id)
return -ENODEV;
- private->data = of_id->data;
+ mtk_drm_data = (struct mtk_mmsys_driver_data *)of_id->data;
+ if (!mtk_drm_data)
+ return -EINVAL;
+
+ /* Try to build the display pipeline from devicetree graphs */
+ if (of_graph_is_present(phandle)) {
+ dev_dbg(dev, "Building display pipeline for MMSYS %u\n",
+ mtk_drm_data->mmsys_id);
+ private->data = devm_kmemdup(dev, mtk_drm_data,
+ sizeof(*mtk_drm_data), GFP_KERNEL);
+ if (!private->data)
+ return -ENOMEM;
+
+ ret = mtk_drm_of_ddp_path_build(dev, phandle, private->data);
+ if (ret)
+ return ret;
+ } else {
+ /* No devicetree graphs support: go with hardcoded paths if present */
+ dev_dbg(dev, "Using hardcoded paths for MMSYS %u\n", mtk_drm_data->mmsys_id);
+ private->data = mtk_drm_data;
+ };
private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
sizeof(*private->all_drm_private),
@@ -868,12 +1111,11 @@ static int mtk_drm_probe(struct platform_device *pdev)
/* Iterate over sibling DISP function blocks */
for_each_child_of_node(phandle->parent, node) {
- const struct of_device_id *of_id;
enum mtk_ddp_comp_type comp_type;
int comp_id;
- of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
- if (!of_id)
+ ret = mtk_drm_of_get_ddp_comp_type(node, &comp_type);
+ if (ret)
continue;
if (!of_device_is_available(node)) {
@@ -882,8 +1124,6 @@ static int mtk_drm_probe(struct platform_device *pdev)
continue;
}
- comp_type = (enum mtk_ddp_comp_type)(uintptr_t)of_id->data;
-
if (comp_type == MTK_DISP_MUTEX) {
int id;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index ce897984de51..675cdc90a440 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -63,7 +63,7 @@ struct mtk_drm_private {
struct device *mmsys_dev;
struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX];
struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX];
- const struct mtk_mmsys_driver_data *data;
+ struct mtk_mmsys_driver_data *data;
struct drm_atomic_state *suspend_state;
unsigned int mbox_index;
struct mtk_drm_private **all_drm_private;
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index eeec641cab60..33ceeb8d6925 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -988,9 +988,17 @@ static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
dsi->lanes = device->lanes;
dsi->format = device->format;
dsi->mode_flags = device->mode_flags;
- dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
- if (IS_ERR(dsi->next_bridge))
- return PTR_ERR(dsi->next_bridge);
+ dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
+ if (IS_ERR(dsi->next_bridge)) {
+ ret = PTR_ERR(dsi->next_bridge);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ /* Old devicetree has only one endpoint */
+ dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
+ if (IS_ERR(dsi->next_bridge))
+ return PTR_ERR(dsi->next_bridge);
+ }
drm_bridge_add(&dsi->bridge);
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 13110fcc46a8..f274d9430cc3 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -23,6 +23,7 @@ adreno-y := \
adreno/a6xx_gpu.o \
adreno/a6xx_gmu.o \
adreno/a6xx_hfi.o \
+ adreno/a6xx_preempt.o \
adreno-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \
@@ -210,6 +211,7 @@ DISPLAY_HEADERS = \
generated/mdp4.xml.h \
generated/mdp5.xml.h \
generated/mdp_common.xml.h \
+ generated/mdss.xml.h \
generated/sfpb.xml.h
$(addprefix $(obj)/,$(adreno-y)): $(addprefix $(obj)/,$(ADRENO_HEADERS))
diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
index 0dc255ddf5ce..379a3d346c30 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
@@ -22,7 +22,7 @@ static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
break;
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
/* ignore if there has not been a ctx switch: */
- if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
+ if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
break;
fallthrough;
case MSM_SUBMIT_CMD_BUF:
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index b46ff49f47cf..b6df115bb567 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -40,7 +40,7 @@ static void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
break;
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
/* ignore if there has not been a ctx switch: */
- if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
+ if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
break;
fallthrough;
case MSM_SUBMIT_CMD_BUF:
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 8b4cdf95f445..50c490b492f0 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -34,7 +34,7 @@ static void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
break;
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
/* ignore if there has not been a ctx switch: */
- if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
+ if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
break;
fallthrough;
case MSM_SUBMIT_CMD_BUF:
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index e09044930547..ee89db72e36e 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -77,7 +77,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
break;
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
- if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
+ if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
break;
fallthrough;
case MSM_SUBMIT_CMD_BUF:
@@ -132,7 +132,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
unsigned int i, ibs = 0;
if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
- gpu->cur_ctx_seqno = 0;
+ ring->cur_ctx_seqno = 0;
a5xx_submit_in_rb(gpu, submit);
return;
}
@@ -171,7 +171,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
break;
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
- if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
+ if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
break;
fallthrough;
case MSM_SUBMIT_CMD_BUF:
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c
index 7705f8010484..6b91e0bd1514 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_power.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
@@ -307,7 +307,7 @@ int a5xx_power_init(struct msm_gpu *gpu)
else if (adreno_is_a540(adreno_gpu))
a540_lm_setup(gpu);
- /* Set up SP/TP power collpase */
+ /* Set up SP/TP power collapse */
a5xx_pc_init(gpu);
/* Start the GPMU */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 0312b6ee0356..0c560e84ad5a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -973,6 +973,25 @@ static const struct adreno_info a6xx_gpus[] = {
},
.address_space_size = SZ_16G,
}, {
+ .chip_ids = ADRENO_CHIP_IDS(0x06060300),
+ .family = ADRENO_6XX_GEN4,
+ .fw = {
+ [ADRENO_FW_SQE] = "a660_sqe.fw",
+ [ADRENO_FW_GMU] = "a663_gmu.bin",
+ },
+ .gmem = SZ_1M + SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .a6xx = &(const struct a6xx_info) {
+ .hwcg = a690_hwcg,
+ .protect = &a660_protect,
+ .gmu_cgc_mode = 0x00020200,
+ .prim_fifo_threshold = 0x00300200,
+ },
+ .address_space_size = SZ_16G,
+ }, {
.chip_ids = ADRENO_CHIP_IDS(0x06030500),
.family = ADRENO_6XX_GEN4,
.fw = {
@@ -1281,6 +1300,28 @@ static const u32 a730_protect_regs[] = {
};
DECLARE_ADRENO_PROTECT(a730_protect, 48);
+static const uint32_t a7xx_pwrup_reglist_regs[] = {
+ REG_A6XX_UCHE_TRAP_BASE,
+ REG_A6XX_UCHE_TRAP_BASE + 1,
+ REG_A6XX_UCHE_WRITE_THRU_BASE,
+ REG_A6XX_UCHE_WRITE_THRU_BASE + 1,
+ REG_A6XX_UCHE_GMEM_RANGE_MIN,
+ REG_A6XX_UCHE_GMEM_RANGE_MIN + 1,
+ REG_A6XX_UCHE_GMEM_RANGE_MAX,
+ REG_A6XX_UCHE_GMEM_RANGE_MAX + 1,
+ REG_A6XX_UCHE_CACHE_WAYS,
+ REG_A6XX_UCHE_MODE_CNTL,
+ REG_A6XX_RB_NC_MODE_CNTL,
+ REG_A6XX_RB_CMP_DBG_ECO_CNTL,
+ REG_A7XX_GRAS_NC_MODE_CNTL,
+ REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE,
+ REG_A6XX_UCHE_GBIF_GX_CONFIG,
+ REG_A6XX_UCHE_CLIENT_PF,
+ REG_A6XX_TPL1_DBG_ECO_CNTL1,
+};
+
+DECLARE_ADRENO_REGLIST_LIST(a7xx_pwrup_reglist);
+
static const struct adreno_info a7xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x07000200),
@@ -1315,15 +1356,18 @@ static const struct adreno_info a7xx_gpus[] = {
.gmem = SZ_2M,
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION,
.init = a6xx_gpu_init,
.zapfw = "a730_zap.mdt",
.a6xx = &(const struct a6xx_info) {
.hwcg = a730_hwcg,
.protect = &a730_protect,
+ .pwrup_reglist = &a7xx_pwrup_reglist,
.gmu_cgc_mode = 0x00020000,
},
.address_space_size = SZ_16G,
+ .preempt_record_size = 2860 * SZ_1K,
}, {
.chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */
.family = ADRENO_7XX_GEN2,
@@ -1334,16 +1378,19 @@ static const struct adreno_info a7xx_gpus[] = {
.gmem = 3 * SZ_1M,
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION,
.init = a6xx_gpu_init,
.zapfw = "a740_zap.mdt",
.a6xx = &(const struct a6xx_info) {
.hwcg = a740_hwcg,
.protect = &a730_protect,
+ .pwrup_reglist = &a7xx_pwrup_reglist,
.gmu_chipid = 0x7020100,
.gmu_cgc_mode = 0x00020202,
},
.address_space_size = SZ_16G,
+ .preempt_record_size = 4192 * SZ_1K,
}, {
.chip_ids = ADRENO_CHIP_IDS(0x43050c01), /* "C512v2" */
.family = ADRENO_7XX_GEN2,
@@ -1354,15 +1401,18 @@ static const struct adreno_info a7xx_gpus[] = {
.gmem = 3 * SZ_1M,
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION,
.init = a6xx_gpu_init,
.a6xx = &(const struct a6xx_info) {
.hwcg = a740_hwcg,
.protect = &a730_protect,
+ .pwrup_reglist = &a7xx_pwrup_reglist,
.gmu_chipid = 0x7050001,
.gmu_cgc_mode = 0x00020202,
},
.address_space_size = SZ_256G,
+ .preempt_record_size = 4192 * SZ_1K,
}, {
.chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */
.family = ADRENO_7XX_GEN3,
@@ -1373,15 +1423,18 @@ static const struct adreno_info a7xx_gpus[] = {
.gmem = 3 * SZ_1M,
.inactive_period = DRM_MSM_INACTIVE_PERIOD,
.quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
- ADRENO_QUIRK_HAS_HW_APRIV,
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION,
.init = a6xx_gpu_init,
.zapfw = "gen70900_zap.mbn",
.a6xx = &(const struct a6xx_info) {
.protect = &a730_protect,
+ .pwrup_reglist = &a7xx_pwrup_reglist,
.gmu_chipid = 0x7090100,
.gmu_cgc_mode = 0x00020202,
},
.address_space_size = SZ_16G,
+ .preempt_record_size = 3572 * SZ_1K,
}
};
DECLARE_ADRENO_GPULIST(a7xx);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 37927bdd6fbe..14db7376c712 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1522,15 +1522,13 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
irq = platform_get_irq_byname(pdev, name);
- ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH, name, gmu);
+ ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, name, gmu);
if (ret) {
DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s %d\n",
name, ret);
return ret;
}
- disable_irq(irq);
-
return irq;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 94b6c5cab6f4..b4a79f88ccf4 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -99,6 +99,7 @@ struct a6xx_gmu {
struct completion pd_gate;
struct qmp *qmp;
+ struct a6xx_hfi_msg_bw_table *bw_table;
};
static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 702b8d4b3497..019610341df1 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -68,6 +68,8 @@ static void update_shadow_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
uint32_t wptr;
unsigned long flags;
@@ -81,12 +83,17 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
/* Make sure to wrap wptr if we need to */
wptr = get_wptr(ring);
- spin_unlock_irqrestore(&ring->preempt_lock, flags);
-
- /* Make sure everything is posted before making a decision */
- mb();
+ /* Update HW if this is the current ring and we are not in preempt*/
+ if (!a6xx_in_preempt(a6xx_gpu)) {
+ if (a6xx_gpu->cur_ring == ring)
+ gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
+ else
+ ring->restore_wptr = true;
+ } else {
+ ring->restore_wptr = true;
+ }
- gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
}
static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter,
@@ -110,7 +117,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
u32 asid;
u64 memptr = rbmemptr(ring, ttbr0);
- if (ctx->seqno == a6xx_gpu->base.base.cur_ctx_seqno)
+ if (ctx->seqno == ring->cur_ctx_seqno)
return;
if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid))
@@ -148,12 +155,14 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
/*
* Write the new TTBR0 to the memstore. This is good for debugging.
+ * Needed for preemption
*/
- OUT_PKT7(ring, CP_MEM_WRITE, 4);
+ OUT_PKT7(ring, CP_MEM_WRITE, 5);
OUT_RING(ring, CP_MEM_WRITE_0_ADDR_LO(lower_32_bits(memptr)));
OUT_RING(ring, CP_MEM_WRITE_1_ADDR_HI(upper_32_bits(memptr)));
OUT_RING(ring, lower_32_bits(ttbr));
- OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr));
+ OUT_RING(ring, upper_32_bits(ttbr));
+ OUT_RING(ring, ctx->seqno);
/*
* Sync both threads after switching pagetables and enable BR only
@@ -229,7 +238,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
break;
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
- if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
+ if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
break;
fallthrough;
case MSM_SUBMIT_CMD_BUF:
@@ -278,6 +287,46 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
a6xx_flush(gpu, ring);
}
+static void a6xx_emit_set_pseudo_reg(struct msm_ringbuffer *ring,
+ struct a6xx_gpu *a6xx_gpu, struct msm_gpu_submitqueue *queue)
+{
+ u64 preempt_postamble;
+
+ OUT_PKT7(ring, CP_SET_PSEUDO_REG, 12);
+
+ OUT_RING(ring, SMMU_INFO);
+ /* don't save SMMU, we write the record from the kernel instead */
+ OUT_RING(ring, 0);
+ OUT_RING(ring, 0);
+
+ /* privileged and non secure buffer save */
+ OUT_RING(ring, NON_SECURE_SAVE_ADDR);
+ OUT_RING(ring, lower_32_bits(
+ a6xx_gpu->preempt_iova[ring->id]));
+ OUT_RING(ring, upper_32_bits(
+ a6xx_gpu->preempt_iova[ring->id]));
+
+ /* user context buffer save, seems to be unnused by fw */
+ OUT_RING(ring, NON_PRIV_SAVE_ADDR);
+ OUT_RING(ring, 0);
+ OUT_RING(ring, 0);
+
+ OUT_RING(ring, COUNTER);
+ /* seems OK to set to 0 to disable it */
+ OUT_RING(ring, 0);
+ OUT_RING(ring, 0);
+
+ /* Emit postamble to clear perfcounters */
+ preempt_postamble = a6xx_gpu->preempt_postamble_iova;
+
+ OUT_PKT7(ring, CP_SET_AMBLE, 3);
+ OUT_RING(ring, lower_32_bits(preempt_postamble));
+ OUT_RING(ring, upper_32_bits(preempt_postamble));
+ OUT_RING(ring, CP_SET_AMBLE_2_DWORDS(
+ a6xx_gpu->preempt_postamble_len) |
+ CP_SET_AMBLE_2_TYPE(KMD_AMBLE_TYPE));
+}
+
static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
{
unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT;
@@ -295,6 +344,13 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
a6xx_set_pagetable(a6xx_gpu, ring, submit);
+ /*
+ * If preemption is enabled, then set the pseudo register for the save
+ * sequence
+ */
+ if (gpu->nr_rings > 1)
+ a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, submit->queue);
+
get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0),
rbmemptr_stats(ring, index, cpcycles_start));
get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER,
@@ -306,8 +362,10 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_PKT7(ring, CP_SET_MARKER, 1);
OUT_RING(ring, 0x101); /* IFPC disable */
- OUT_PKT7(ring, CP_SET_MARKER, 1);
- OUT_RING(ring, 0x00d); /* IB1LIST start */
+ if (submit->queue->flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT) {
+ OUT_PKT7(ring, CP_SET_MARKER, 1);
+ OUT_RING(ring, 0x00d); /* IB1LIST start */
+ }
/* Submit the commands */
for (i = 0; i < submit->nr_cmds; i++) {
@@ -315,7 +373,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
case MSM_SUBMIT_CMD_IB_TARGET_BUF:
break;
case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
- if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
+ if (ring->cur_ctx_seqno == submit->queue->ctx->seqno)
break;
fallthrough;
case MSM_SUBMIT_CMD_BUF:
@@ -338,8 +396,10 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
update_shadow_rptr(gpu, ring);
}
- OUT_PKT7(ring, CP_SET_MARKER, 1);
- OUT_RING(ring, 0x00e); /* IB1LIST end */
+ if (submit->queue->flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT) {
+ OUT_PKT7(ring, CP_SET_MARKER, 1);
+ OUT_RING(ring, 0x00e); /* IB1LIST end */
+ }
get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0),
rbmemptr_stats(ring, index, cpcycles_end));
@@ -386,6 +446,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, upper_32_bits(rbmemptr(ring, bv_fence)));
OUT_RING(ring, submit->seqno);
+ a6xx_gpu->last_seqno[ring->id] = submit->seqno;
+
/* write the ringbuffer timestamp */
OUT_PKT7(ring, CP_EVENT_WRITE, 4);
OUT_RING(ring, CACHE_CLEAN | CP_EVENT_WRITE_0_IRQ | BIT(27));
@@ -399,10 +461,32 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_PKT7(ring, CP_SET_MARKER, 1);
OUT_RING(ring, 0x100); /* IFPC enable */
+ /* If preemption is enabled */
+ if (gpu->nr_rings > 1) {
+ /* Yield the floor on command completion */
+ OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4);
+
+ /*
+ * If dword[2:1] are non zero, they specify an address for
+ * the CP to write the value of dword[3] to on preemption
+ * complete. Write 0 to skip the write
+ */
+ OUT_RING(ring, 0x00);
+ OUT_RING(ring, 0x00);
+ /* Data value - not used if the address above is 0 */
+ OUT_RING(ring, 0x01);
+ /* generate interrupt on preemption completion */
+ OUT_RING(ring, 0x00);
+ }
+
+
trace_msm_gpu_submit_flush(submit,
gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER));
a6xx_flush(gpu, ring);
+
+ /* Check to see if we need to start preemption */
+ a6xx_preempt_trigger(gpu);
}
static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state)
@@ -551,6 +635,15 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
gpu->ubwc_config.macrotile_mode = 1;
}
+ if (adreno_is_a663(gpu)) {
+ gpu->ubwc_config.highest_bank_bit = 13;
+ gpu->ubwc_config.amsbc = 1;
+ gpu->ubwc_config.rgb565_predicator = 1;
+ gpu->ubwc_config.uavflagprd_inv = 2;
+ gpu->ubwc_config.macrotile_mode = 1;
+ gpu->ubwc_config.ubwc_swizzle = 0x4;
+ }
+
if (adreno_is_7c3(gpu)) {
gpu->ubwc_config.highest_bank_bit = 14;
gpu->ubwc_config.amsbc = 1;
@@ -609,6 +702,77 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
adreno_gpu->ubwc_config.macrotile_mode);
}
+static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ const struct adreno_reglist_list *reglist;
+ void *ptr = a6xx_gpu->pwrup_reglist_ptr;
+ struct cpu_gpu_lock *lock = ptr;
+ u32 *dest = (u32 *)&lock->regs[0];
+ int i;
+
+ reglist = adreno_gpu->info->a6xx->pwrup_reglist;
+
+ lock->gpu_req = lock->cpu_req = lock->turn = 0;
+ lock->ifpc_list_len = 0;
+ lock->preemption_list_len = reglist->count;
+
+ /*
+ * For each entry in each of the lists, write the offset and the current
+ * register value into the GPU buffer
+ */
+ for (i = 0; i < reglist->count; i++) {
+ *dest++ = reglist->regs[i];
+ *dest++ = gpu_read(gpu, reglist->regs[i]);
+ }
+
+ /*
+ * The overall register list is composed of
+ * 1. Static IFPC-only registers
+ * 2. Static IFPC + preemption registers
+ * 3. Dynamic IFPC + preemption registers (ex: perfcounter selects)
+ *
+ * The first two lists are static. Size of these lists are stored as
+ * number of pairs in ifpc_list_len and preemption_list_len
+ * respectively. With concurrent binning, Some of the perfcounter
+ * registers being virtualized, CP needs to know the pipe id to program
+ * the aperture inorder to restore the same. Thus, third list is a
+ * dynamic list with triplets as
+ * (<aperture, shifted 12 bits> <address> <data>), and the length is
+ * stored as number for triplets in dynamic_list_len.
+ */
+ lock->dynamic_list_len = 0;
+}
+
+static int a7xx_preempt_start(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct msm_ringbuffer *ring = gpu->rb[0];
+
+ if (gpu->nr_rings <= 1)
+ return 0;
+
+ /* Turn CP protection off */
+ OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
+ OUT_RING(ring, 0);
+
+ a6xx_emit_set_pseudo_reg(ring, a6xx_gpu, NULL);
+
+ /* Yield the floor on command completion */
+ OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4);
+ OUT_RING(ring, 0x00);
+ OUT_RING(ring, 0x00);
+ OUT_RING(ring, 0x00);
+ /* Generate interrupt on preemption completion */
+ OUT_RING(ring, 0x00);
+
+ a6xx_flush(gpu, ring);
+
+ return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
+}
+
static int a6xx_cp_init(struct msm_gpu *gpu)
{
struct msm_ringbuffer *ring = gpu->rb[0];
@@ -640,6 +804,8 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
static int a7xx_cp_init(struct msm_gpu *gpu)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct msm_ringbuffer *ring = gpu->rb[0];
u32 mask;
@@ -677,11 +843,11 @@ static int a7xx_cp_init(struct msm_gpu *gpu)
/* *Don't* send a power up reg list for concurrent binning (TODO) */
/* Lo address */
- OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, lower_32_bits(a6xx_gpu->pwrup_reglist_iova));
/* Hi address */
- OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, upper_32_bits(a6xx_gpu->pwrup_reglist_iova));
/* BIT(31) set => read the regs from the list */
- OUT_RING(ring, 0x00000000);
+ OUT_RING(ring, BIT(31));
a6xx_flush(gpu, ring);
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
@@ -805,6 +971,16 @@ static int a6xx_ucode_load(struct msm_gpu *gpu)
msm_gem_object_set_name(a6xx_gpu->shadow_bo, "shadow");
}
+ a6xx_gpu->pwrup_reglist_ptr = msm_gem_kernel_new(gpu->dev, PAGE_SIZE,
+ MSM_BO_WC | MSM_BO_MAP_PRIV,
+ gpu->aspace, &a6xx_gpu->pwrup_reglist_bo,
+ &a6xx_gpu->pwrup_reglist_iova);
+
+ if (IS_ERR(a6xx_gpu->pwrup_reglist_ptr))
+ return PTR_ERR(a6xx_gpu->pwrup_reglist_ptr);
+
+ msm_gem_object_set_name(a6xx_gpu->pwrup_reglist_bo, "pwrup_reglist");
+
return 0;
}
@@ -864,6 +1040,7 @@ static int hw_init(struct msm_gpu *gpu)
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
u64 gmem_range_min;
+ unsigned int i;
int ret;
if (!adreno_has_gmu_wrapper(adreno_gpu)) {
@@ -1072,7 +1249,7 @@ static int hw_init(struct msm_gpu *gpu)
if (adreno_is_a690(adreno_gpu))
gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x90);
/* Set dualQ + disable afull for A660 GPU */
- else if (adreno_is_a660(adreno_gpu))
+ else if (adreno_is_a660(adreno_gpu) || adreno_is_a663(adreno_gpu))
gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG, 0x66906);
else if (adreno_is_a7xx(adreno_gpu))
gpu_write(gpu, REG_A6XX_UCHE_CMDQ_CONFIG,
@@ -1134,22 +1311,32 @@ static int hw_init(struct msm_gpu *gpu)
if (a6xx_gpu->shadow_bo) {
gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR,
shadowptr(a6xx_gpu, gpu->rb[0]));
+ for (unsigned int i = 0; i < gpu->nr_rings; i++)
+ a6xx_gpu->shadow[i] = 0;
}
/* ..which means "always" on A7xx, also for BV shadow */
if (adreno_is_a7xx(adreno_gpu)) {
gpu_write64(gpu, REG_A7XX_CP_BV_RB_RPTR_ADDR,
- rbmemptr(gpu->rb[0], bv_fence));
+ rbmemptr(gpu->rb[0], bv_rptr));
}
+ a6xx_preempt_hw_init(gpu);
+
/* Always come up on rb 0 */
a6xx_gpu->cur_ring = gpu->rb[0];
- gpu->cur_ctx_seqno = 0;
+ for (i = 0; i < gpu->nr_rings; i++)
+ gpu->rb[i]->cur_ctx_seqno = 0;
/* Enable the SQE_to start the CP engine */
gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1);
+ if (adreno_is_a7xx(adreno_gpu) && !a6xx_gpu->pwrup_reglist_emitted) {
+ a7xx_patch_pwrup_reglist(gpu);
+ a6xx_gpu->pwrup_reglist_emitted = true;
+ }
+
ret = adreno_is_a7xx(adreno_gpu) ? a7xx_cp_init(gpu) : a6xx_cp_init(gpu);
if (ret)
goto out;
@@ -1187,6 +1374,10 @@ static int hw_init(struct msm_gpu *gpu)
out:
if (adreno_has_gmu_wrapper(adreno_gpu))
return ret;
+
+ /* Last step - yield the ringbuffer */
+ a7xx_preempt_start(gpu);
+
/*
* Tell the GMU that we are done touching the GPU and it can start power
* management
@@ -1564,8 +1755,13 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)
if (status & A6XX_RBBM_INT_0_MASK_SWFUSEVIOLATION)
a7xx_sw_fuse_violation_irq(gpu);
- if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
+ if (status & A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) {
msm_gpu_retire(gpu);
+ a6xx_preempt_trigger(gpu);
+ }
+
+ if (status & A6XX_RBBM_INT_0_MASK_CP_SW)
+ a6xx_preempt_irq(gpu);
return IRQ_HANDLED;
}
@@ -2259,6 +2455,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
struct a6xx_gpu *a6xx_gpu;
struct adreno_gpu *adreno_gpu;
struct msm_gpu *gpu;
+ extern int enable_preemption;
bool is_a7xx;
int ret;
@@ -2297,7 +2494,10 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
return ERR_PTR(ret);
}
- if (is_a7xx)
+ if ((enable_preemption == 1) || (enable_preemption == -1 &&
+ (config->info->quirks & ADRENO_QUIRK_PREEMPTION)))
+ ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 4);
+ else if (is_a7xx)
ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_a7xx, 1);
else if (adreno_has_gmu_wrapper(adreno_gpu))
ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs_gmuwrapper, 1);
@@ -2338,6 +2538,8 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
a6xx_fault_handler);
a6xx_calc_ubwc_config(adreno_gpu);
+ /* Set up the preemption specific bits and pieces for each ringbuffer */
+ a6xx_preempt_init(gpu);
return gpu;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 0fb7febf70e7..4aceffb6aae8 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -12,15 +12,35 @@
extern bool hang_debug;
+struct cpu_gpu_lock {
+ uint32_t gpu_req;
+ uint32_t cpu_req;
+ uint32_t turn;
+ union {
+ struct {
+ uint16_t list_length;
+ uint16_t list_offset;
+ };
+ struct {
+ uint8_t ifpc_list_len;
+ uint8_t preemption_list_len;
+ uint16_t dynamic_list_len;
+ };
+ };
+ uint64_t regs[62];
+};
+
/**
* struct a6xx_info - a6xx specific information from device table
*
* @hwcg: hw clock gating register sequence
* @protect: CP_PROTECT settings
+ * @pwrup_reglist pwrup reglist for preemption
*/
struct a6xx_info {
const struct adreno_reglist *hwcg;
const struct adreno_protect *protect;
+ const struct adreno_reglist_list *pwrup_reglist;
u32 gmu_chipid;
u32 gmu_cgc_mode;
u32 prim_fifo_threshold;
@@ -33,6 +53,29 @@ struct a6xx_gpu {
uint64_t sqe_iova;
struct msm_ringbuffer *cur_ring;
+ struct msm_ringbuffer *next_ring;
+
+ struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS];
+ void *preempt[MSM_GPU_MAX_RINGS];
+ uint64_t preempt_iova[MSM_GPU_MAX_RINGS];
+ struct drm_gem_object *preempt_smmu_bo[MSM_GPU_MAX_RINGS];
+ void *preempt_smmu[MSM_GPU_MAX_RINGS];
+ uint64_t preempt_smmu_iova[MSM_GPU_MAX_RINGS];
+ uint32_t last_seqno[MSM_GPU_MAX_RINGS];
+
+ atomic_t preempt_state;
+ spinlock_t eval_lock;
+ struct timer_list preempt_timer;
+
+ unsigned int preempt_level;
+ bool uses_gmem;
+ bool skip_save_restore;
+
+ struct drm_gem_object *preempt_postamble_bo;
+ void *preempt_postamble_ptr;
+ uint64_t preempt_postamble_iova;
+ uint64_t preempt_postamble_len;
+ bool postamble_enabled;
struct a6xx_gmu gmu;
@@ -40,6 +83,11 @@ struct a6xx_gpu {
uint64_t shadow_iova;
uint32_t *shadow;
+ struct drm_gem_object *pwrup_reglist_bo;
+ void *pwrup_reglist_ptr;
+ uint64_t pwrup_reglist_iova;
+ bool pwrup_reglist_emitted;
+
bool has_whereami;
void __iomem *llc_mmio;
@@ -52,6 +100,100 @@ struct a6xx_gpu {
#define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base)
/*
+ * In order to do lockless preemption we use a simple state machine to progress
+ * through the process.
+ *
+ * PREEMPT_NONE - no preemption in progress. Next state START.
+ * PREEMPT_START - The trigger is evaluating if preemption is possible. Next
+ * states: TRIGGERED, NONE
+ * PREEMPT_FINISH - An intermediate state before moving back to NONE. Next
+ * state: NONE.
+ * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next
+ * states: FAULTED, PENDING
+ * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger
+ * recovery. Next state: N/A
+ * PREEMPT_PENDING: Preemption complete interrupt fired - the callback is
+ * checking the success of the operation. Next state: FAULTED, NONE.
+ */
+
+enum a6xx_preempt_state {
+ PREEMPT_NONE = 0,
+ PREEMPT_START,
+ PREEMPT_FINISH,
+ PREEMPT_TRIGGERED,
+ PREEMPT_FAULTED,
+ PREEMPT_PENDING,
+};
+
+/*
+ * struct a6xx_preempt_record is a shared buffer between the microcode and the
+ * CPU to store the state for preemption. The record itself is much larger
+ * (2112k) but most of that is used by the CP for storage.
+ *
+ * There is a preemption record assigned per ringbuffer. When the CPU triggers a
+ * preemption, it fills out the record with the useful information (wptr, ring
+ * base, etc) and the microcode uses that information to set up the CP following
+ * the preemption. When a ring is switched out, the CP will save the ringbuffer
+ * state back to the record. In this way, once the records are properly set up
+ * the CPU can quickly switch back and forth between ringbuffers by only
+ * updating a few registers (often only the wptr).
+ *
+ * These are the CPU aware registers in the record:
+ * @magic: Must always be 0xAE399D6EUL
+ * @info: Type of the record - written 0 by the CPU, updated by the CP
+ * @errno: preemption error record
+ * @data: Data field in YIELD and SET_MARKER packets, Written and used by CP
+ * @cntl: Value of RB_CNTL written by CPU, save/restored by CP
+ * @rptr: Value of RB_RPTR written by CPU, save/restored by CP
+ * @wptr: Value of RB_WPTR written by CPU, save/restored by CP
+ * @_pad: Reserved/padding
+ * @rptr_addr: Value of RB_RPTR_ADDR_LO|HI written by CPU, save/restored by CP
+ * @rbase: Value of RB_BASE written by CPU, save/restored by CP
+ * @counter: GPU address of the storage area for the preemption counters
+ * @bv_rptr_addr: Value of BV_RB_RPTR_ADDR_LO|HI written by CPU, save/restored by CP
+ */
+struct a6xx_preempt_record {
+ u32 magic;
+ u32 info;
+ u32 errno;
+ u32 data;
+ u32 cntl;
+ u32 rptr;
+ u32 wptr;
+ u32 _pad;
+ u64 rptr_addr;
+ u64 rbase;
+ u64 counter;
+ u64 bv_rptr_addr;
+};
+
+#define A6XX_PREEMPT_RECORD_MAGIC 0xAE399D6EUL
+
+#define PREEMPT_SMMU_INFO_SIZE 4096
+
+#define PREEMPT_RECORD_SIZE(adreno_gpu) \
+ ((adreno_gpu->info->preempt_record_size) == 0 ? \
+ 4192 * SZ_1K : (adreno_gpu->info->preempt_record_size))
+
+/*
+ * The preemption counter block is a storage area for the value of the
+ * preemption counters that are saved immediately before context switch. We
+ * append it on to the end of the allocation for the preemption record.
+ */
+#define A6XX_PREEMPT_COUNTER_SIZE (16 * 4)
+
+struct a7xx_cp_smmu_info {
+ u32 magic;
+ u32 _pad4;
+ u64 ttbr0;
+ u32 asid;
+ u32 context_idr;
+ u32 context_bank;
+};
+
+#define GEN7_CP_SMMU_INFO_MAGIC 0x241350d5UL
+
+/*
* Given a register and a count, return a value to program into
* REG_CP_PROTECT_REG(n) - this will block both reads and writes for
* _len + 1 registers starting at _reg.
@@ -108,6 +250,34 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
+void a6xx_preempt_init(struct msm_gpu *gpu);
+void a6xx_preempt_hw_init(struct msm_gpu *gpu);
+void a6xx_preempt_trigger(struct msm_gpu *gpu);
+void a6xx_preempt_irq(struct msm_gpu *gpu);
+void a6xx_preempt_fini(struct msm_gpu *gpu);
+int a6xx_preempt_submitqueue_setup(struct msm_gpu *gpu,
+ struct msm_gpu_submitqueue *queue);
+void a6xx_preempt_submitqueue_close(struct msm_gpu *gpu,
+ struct msm_gpu_submitqueue *queue);
+
+/* Return true if we are in a preempt state */
+static inline bool a6xx_in_preempt(struct a6xx_gpu *a6xx_gpu)
+{
+ /*
+ * Make sure the read to preempt_state is ordered with respect to reads
+ * of other variables before ...
+ */
+ smp_rmb();
+
+ int preempt_state = atomic_read(&a6xx_gpu->preempt_state);
+
+ /* ... and after. */
+ smp_rmb();
+
+ return !(preempt_state == PREEMPT_NONE ||
+ preempt_state == PREEMPT_FINISH);
+}
+
void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp,
bool suspended);
unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index cdb3f6e74d3e..cb8844ed46b2 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -478,6 +478,37 @@ static void a660_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
msg->cnoc_cmds_data[1][0] = 0x60000001;
}
+static void a663_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
+{
+ /*
+ * Send a single "off" entry just to get things running
+ * TODO: bus scaling
+ */
+ msg->bw_level_num = 1;
+
+ msg->ddr_cmds_num = 3;
+ msg->ddr_wait_bitmask = 0x07;
+
+ msg->ddr_cmds_addrs[0] = 0x50004;
+ msg->ddr_cmds_addrs[1] = 0x50000;
+ msg->ddr_cmds_addrs[2] = 0x500b4;
+
+ msg->ddr_cmds_data[0][0] = 0x40000000;
+ msg->ddr_cmds_data[0][1] = 0x40000000;
+ msg->ddr_cmds_data[0][2] = 0x40000000;
+
+ /*
+ * These are the CX (CNOC) votes - these are used by the GMU but the
+ * votes are known and fixed for the target
+ */
+ msg->cnoc_cmds_num = 1;
+ msg->cnoc_wait_bitmask = 0x01;
+
+ msg->cnoc_cmds_addrs[0] = 0x50058;
+ msg->cnoc_cmds_data[0][0] = 0x40000000;
+ msg->cnoc_cmds_data[1][0] = 0x60000001;
+}
+
static void adreno_7c3_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
{
/*
@@ -630,32 +661,44 @@ static void a6xx_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
{
- struct a6xx_hfi_msg_bw_table msg = { 0 };
+ struct a6xx_hfi_msg_bw_table *msg;
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ if (gmu->bw_table)
+ goto send;
+
+ msg = devm_kzalloc(gmu->dev, sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
if (adreno_is_a618(adreno_gpu))
- a618_build_bw_table(&msg);
+ a618_build_bw_table(msg);
else if (adreno_is_a619(adreno_gpu))
- a619_build_bw_table(&msg);
+ a619_build_bw_table(msg);
else if (adreno_is_a640_family(adreno_gpu))
- a640_build_bw_table(&msg);
+ a640_build_bw_table(msg);
else if (adreno_is_a650(adreno_gpu))
- a650_build_bw_table(&msg);
+ a650_build_bw_table(msg);
else if (adreno_is_7c3(adreno_gpu))
- adreno_7c3_build_bw_table(&msg);
+ adreno_7c3_build_bw_table(msg);
else if (adreno_is_a660(adreno_gpu))
- a660_build_bw_table(&msg);
+ a660_build_bw_table(msg);
+ else if (adreno_is_a663(adreno_gpu))
+ a663_build_bw_table(msg);
else if (adreno_is_a690(adreno_gpu))
- a690_build_bw_table(&msg);
+ a690_build_bw_table(msg);
else if (adreno_is_a730(adreno_gpu))
- a730_build_bw_table(&msg);
+ a730_build_bw_table(msg);
else if (adreno_is_a740_family(adreno_gpu))
- a740_build_bw_table(&msg);
+ a740_build_bw_table(msg);
else
- a6xx_build_bw_table(&msg);
+ a6xx_build_bw_table(msg);
+
+ gmu->bw_table = msg;
- return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, &msg, sizeof(msg),
+send:
+ return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, gmu->bw_table, sizeof(*(gmu->bw_table)),
NULL, 0);
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
new file mode 100644
index 000000000000..2fd4e39f618f
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -0,0 +1,456 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2023 Collabora, Ltd. */
+/* Copyright (c) 2024 Valve Corporation */
+
+#include "msm_gem.h"
+#include "a6xx_gpu.h"
+#include "a6xx_gmu.xml.h"
+#include "msm_mmu.h"
+#include "msm_gpu_trace.h"
+
+/*
+ * Try to transition the preemption state from old to new. Return
+ * true on success or false if the original state wasn't 'old'
+ */
+static inline bool try_preempt_state(struct a6xx_gpu *a6xx_gpu,
+ enum a6xx_preempt_state old, enum a6xx_preempt_state new)
+{
+ enum a6xx_preempt_state cur = atomic_cmpxchg(&a6xx_gpu->preempt_state,
+ old, new);
+
+ return (cur == old);
+}
+
+/*
+ * Force the preemption state to the specified state. This is used in cases
+ * where the current state is known and won't change
+ */
+static inline void set_preempt_state(struct a6xx_gpu *gpu,
+ enum a6xx_preempt_state new)
+{
+ /*
+ * preempt_state may be read by other cores trying to trigger a
+ * preemption or in the interrupt handler so barriers are needed
+ * before...
+ */
+ smp_mb__before_atomic();
+ atomic_set(&gpu->preempt_state, new);
+ /* ... and after*/
+ smp_mb__after_atomic();
+}
+
+/* Write the most recent wptr for the given ring into the hardware */
+static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+{
+ unsigned long flags;
+ uint32_t wptr;
+
+ spin_lock_irqsave(&ring->preempt_lock, flags);
+
+ if (ring->restore_wptr) {
+ wptr = get_wptr(ring);
+
+ gpu_write(gpu, REG_A6XX_CP_RB_WPTR, wptr);
+
+ ring->restore_wptr = false;
+ }
+
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
+}
+
+/* Return the highest priority ringbuffer with something in it */
+static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+
+ unsigned long flags;
+ int i;
+
+ for (i = 0; i < gpu->nr_rings; i++) {
+ bool empty;
+ struct msm_ringbuffer *ring = gpu->rb[i];
+
+ spin_lock_irqsave(&ring->preempt_lock, flags);
+ empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring));
+ if (!empty && ring == a6xx_gpu->cur_ring)
+ empty = ring->memptrs->fence == a6xx_gpu->last_seqno[i];
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
+
+ if (!empty)
+ return ring;
+ }
+
+ return NULL;
+}
+
+static void a6xx_preempt_timer(struct timer_list *t)
+{
+ struct a6xx_gpu *a6xx_gpu = from_timer(a6xx_gpu, t, preempt_timer);
+ struct msm_gpu *gpu = &a6xx_gpu->base.base;
+ struct drm_device *dev = gpu->dev;
+
+ if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_FAULTED))
+ return;
+
+ dev_err(dev->dev, "%s: preemption timed out\n", gpu->name);
+ kthread_queue_work(gpu->worker, &gpu->recover_work);
+}
+
+static void preempt_prepare_postamble(struct a6xx_gpu *a6xx_gpu)
+{
+ u32 *postamble = a6xx_gpu->preempt_postamble_ptr;
+ u32 count = 0;
+
+ postamble[count++] = PKT7(CP_REG_RMW, 3);
+ postamble[count++] = REG_A6XX_RBBM_PERFCTR_SRAM_INIT_CMD;
+ postamble[count++] = 0;
+ postamble[count++] = 1;
+
+ postamble[count++] = PKT7(CP_WAIT_REG_MEM, 6);
+ postamble[count++] = CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ);
+ postamble[count++] = CP_WAIT_REG_MEM_1_POLL_ADDR_LO(
+ REG_A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS);
+ postamble[count++] = CP_WAIT_REG_MEM_2_POLL_ADDR_HI(0);
+ postamble[count++] = CP_WAIT_REG_MEM_3_REF(0x1);
+ postamble[count++] = CP_WAIT_REG_MEM_4_MASK(0x1);
+ postamble[count++] = CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(0);
+
+ a6xx_gpu->preempt_postamble_len = count;
+
+ a6xx_gpu->postamble_enabled = true;
+}
+
+static void preempt_disable_postamble(struct a6xx_gpu *a6xx_gpu)
+{
+ u32 *postamble = a6xx_gpu->preempt_postamble_ptr;
+
+ /*
+ * Disable the postamble by replacing the first packet header with a NOP
+ * that covers the whole buffer.
+ */
+ *postamble = PKT7(CP_NOP, (a6xx_gpu->preempt_postamble_len - 1));
+
+ a6xx_gpu->postamble_enabled = false;
+}
+
+void a6xx_preempt_irq(struct msm_gpu *gpu)
+{
+ uint32_t status;
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct drm_device *dev = gpu->dev;
+
+ if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_PENDING))
+ return;
+
+ /* Delete the preemption watchdog timer */
+ del_timer(&a6xx_gpu->preempt_timer);
+
+ /*
+ * The hardware should be setting the stop bit of CP_CONTEXT_SWITCH_CNTL
+ * to zero before firing the interrupt, but there is a non zero chance
+ * of a hardware condition or a software race that could set it again
+ * before we have a chance to finish. If that happens, log and go for
+ * recovery
+ */
+ status = gpu_read(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL);
+ if (unlikely(status & A6XX_CP_CONTEXT_SWITCH_CNTL_STOP)) {
+ DRM_DEV_ERROR(&gpu->pdev->dev,
+ "!!!!!!!!!!!!!!!! preemption faulted !!!!!!!!!!!!!! irq\n");
+ set_preempt_state(a6xx_gpu, PREEMPT_FAULTED);
+ dev_err(dev->dev, "%s: Preemption failed to complete\n",
+ gpu->name);
+ kthread_queue_work(gpu->worker, &gpu->recover_work);
+ return;
+ }
+
+ a6xx_gpu->cur_ring = a6xx_gpu->next_ring;
+ a6xx_gpu->next_ring = NULL;
+
+ set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
+
+ update_wptr(gpu, a6xx_gpu->cur_ring);
+
+ set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+
+ trace_msm_gpu_preemption_irq(a6xx_gpu->cur_ring->id);
+
+ /*
+ * Retrigger preemption to avoid a deadlock that might occur when preemption
+ * is skipped due to it being already in flight when requested.
+ */
+ a6xx_preempt_trigger(gpu);
+}
+
+void a6xx_preempt_hw_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ int i;
+
+ /* No preemption if we only have one ring */
+ if (gpu->nr_rings == 1)
+ return;
+
+ for (i = 0; i < gpu->nr_rings; i++) {
+ struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[i];
+
+ record_ptr->wptr = 0;
+ record_ptr->rptr = 0;
+ record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]);
+ record_ptr->info = 0;
+ record_ptr->data = 0;
+ record_ptr->rbase = gpu->rb[i]->iova;
+ }
+
+ /* Write a 0 to signal that we aren't switching pagetables */
+ gpu_write64(gpu, REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, 0);
+
+ /* Enable the GMEM save/restore feature for preemption */
+ gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, 0x1);
+
+ /* Reset the preemption state */
+ set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+
+ spin_lock_init(&a6xx_gpu->eval_lock);
+
+ /* Always come up on rb 0 */
+ a6xx_gpu->cur_ring = gpu->rb[0];
+}
+
+void a6xx_preempt_trigger(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ unsigned long flags;
+ struct msm_ringbuffer *ring;
+ unsigned int cntl;
+ bool sysprof;
+
+ if (gpu->nr_rings == 1)
+ return;
+
+ /*
+ * Lock to make sure another thread attempting preemption doesn't skip it
+ * while we are still evaluating the next ring. This makes sure the other
+ * thread does start preemption if we abort it and avoids a soft lock.
+ */
+ spin_lock_irqsave(&a6xx_gpu->eval_lock, flags);
+
+ /*
+ * Try to start preemption by moving from NONE to START. If
+ * unsuccessful, a preemption is already in flight
+ */
+ if (!try_preempt_state(a6xx_gpu, PREEMPT_NONE, PREEMPT_START)) {
+ spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
+ return;
+ }
+
+ cntl = A6XX_CP_CONTEXT_SWITCH_CNTL_LEVEL(a6xx_gpu->preempt_level);
+
+ if (a6xx_gpu->skip_save_restore)
+ cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_SKIP_SAVE_RESTORE;
+
+ if (a6xx_gpu->uses_gmem)
+ cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_USES_GMEM;
+
+ cntl |= A6XX_CP_CONTEXT_SWITCH_CNTL_STOP;
+
+ /* Get the next ring to preempt to */
+ ring = get_next_ring(gpu);
+
+ /*
+ * If no ring is populated or the highest priority ring is the current
+ * one do nothing except to update the wptr to the latest and greatest
+ */
+ if (!ring || (a6xx_gpu->cur_ring == ring)) {
+ set_preempt_state(a6xx_gpu, PREEMPT_FINISH);
+ update_wptr(gpu, a6xx_gpu->cur_ring);
+ set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+ spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
+ return;
+ }
+
+ spin_unlock_irqrestore(&a6xx_gpu->eval_lock, flags);
+
+ spin_lock_irqsave(&ring->preempt_lock, flags);
+
+ struct a7xx_cp_smmu_info *smmu_info_ptr =
+ a6xx_gpu->preempt_smmu[ring->id];
+ struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[ring->id];
+ u64 ttbr0 = ring->memptrs->ttbr0;
+ u32 context_idr = ring->memptrs->context_idr;
+
+ smmu_info_ptr->ttbr0 = ttbr0;
+ smmu_info_ptr->context_idr = context_idr;
+ record_ptr->wptr = get_wptr(ring);
+
+ /*
+ * The GPU will write the wptr we set above when we preempt. Reset
+ * restore_wptr to make sure that we don't write WPTR to the same
+ * thing twice. It's still possible subsequent submissions will update
+ * wptr again, in which case they will set the flag to true. This has
+ * to be protected by the lock for setting the flag and updating wptr
+ * to be atomic.
+ */
+ ring->restore_wptr = false;
+
+ trace_msm_gpu_preemption_trigger(a6xx_gpu->cur_ring->id, ring->id);
+
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
+
+ gpu_write64(gpu,
+ REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO,
+ a6xx_gpu->preempt_smmu_iova[ring->id]);
+
+ gpu_write64(gpu,
+ REG_A6XX_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR,
+ a6xx_gpu->preempt_iova[ring->id]);
+
+ a6xx_gpu->next_ring = ring;
+
+ /* Start a timer to catch a stuck preemption */
+ mod_timer(&a6xx_gpu->preempt_timer, jiffies + msecs_to_jiffies(10000));
+
+ /* Enable or disable postamble as needed */
+ sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1;
+
+ if (!sysprof && !a6xx_gpu->postamble_enabled)
+ preempt_prepare_postamble(a6xx_gpu);
+
+ if (sysprof && a6xx_gpu->postamble_enabled)
+ preempt_disable_postamble(a6xx_gpu);
+
+ /* Set the preemption state to triggered */
+ set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
+
+ /* Trigger the preemption */
+ gpu_write(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL, cntl);
+}
+
+static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
+ struct msm_ringbuffer *ring)
+{
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ struct msm_gpu *gpu = &adreno_gpu->base;
+ struct drm_gem_object *bo = NULL;
+ phys_addr_t ttbr;
+ u64 iova = 0;
+ void *ptr;
+ int asid;
+
+ ptr = msm_gem_kernel_new(gpu->dev,
+ PREEMPT_RECORD_SIZE(adreno_gpu),
+ MSM_BO_WC | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova);
+
+ if (IS_ERR(ptr))
+ return PTR_ERR(ptr);
+
+ memset(ptr, 0, PREEMPT_RECORD_SIZE(adreno_gpu));
+
+ msm_gem_object_set_name(bo, "preempt_record ring%d", ring->id);
+
+ a6xx_gpu->preempt_bo[ring->id] = bo;
+ a6xx_gpu->preempt_iova[ring->id] = iova;
+ a6xx_gpu->preempt[ring->id] = ptr;
+
+ struct a6xx_preempt_record *record_ptr = ptr;
+
+ ptr = msm_gem_kernel_new(gpu->dev,
+ PREEMPT_SMMU_INFO_SIZE,
+ MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY,
+ gpu->aspace, &bo, &iova);
+
+ if (IS_ERR(ptr))
+ return PTR_ERR(ptr);
+
+ memset(ptr, 0, PREEMPT_SMMU_INFO_SIZE);
+
+ msm_gem_object_set_name(bo, "preempt_smmu_info ring%d", ring->id);
+
+ a6xx_gpu->preempt_smmu_bo[ring->id] = bo;
+ a6xx_gpu->preempt_smmu_iova[ring->id] = iova;
+ a6xx_gpu->preempt_smmu[ring->id] = ptr;
+
+ struct a7xx_cp_smmu_info *smmu_info_ptr = ptr;
+
+ msm_iommu_pagetable_params(gpu->aspace->mmu, &ttbr, &asid);
+
+ smmu_info_ptr->magic = GEN7_CP_SMMU_INFO_MAGIC;
+ smmu_info_ptr->ttbr0 = ttbr;
+ smmu_info_ptr->asid = 0xdecafbad;
+ smmu_info_ptr->context_idr = 0;
+
+ /* Set up the defaults on the preemption record */
+ record_ptr->magic = A6XX_PREEMPT_RECORD_MAGIC;
+ record_ptr->info = 0;
+ record_ptr->data = 0;
+ record_ptr->rptr = 0;
+ record_ptr->wptr = 0;
+ record_ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT;
+ record_ptr->rbase = ring->iova;
+ record_ptr->counter = 0;
+ record_ptr->bv_rptr_addr = rbmemptr(ring, bv_rptr);
+
+ return 0;
+}
+
+void a6xx_preempt_fini(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ int i;
+
+ for (i = 0; i < gpu->nr_rings; i++)
+ msm_gem_kernel_put(a6xx_gpu->preempt_bo[i], gpu->aspace);
+}
+
+void a6xx_preempt_init(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ int i;
+
+ /* No preemption if we only have one ring */
+ if (gpu->nr_rings <= 1)
+ return;
+
+ for (i = 0; i < gpu->nr_rings; i++) {
+ if (preempt_init_ring(a6xx_gpu, gpu->rb[i]))
+ goto fail;
+ }
+
+ /* TODO: make this configurable? */
+ a6xx_gpu->preempt_level = 1;
+ a6xx_gpu->uses_gmem = 1;
+ a6xx_gpu->skip_save_restore = 1;
+
+ a6xx_gpu->preempt_postamble_ptr = msm_gem_kernel_new(gpu->dev,
+ PAGE_SIZE,
+ MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY,
+ gpu->aspace, &a6xx_gpu->preempt_postamble_bo,
+ &a6xx_gpu->preempt_postamble_iova);
+
+ preempt_prepare_postamble(a6xx_gpu);
+
+ if (IS_ERR(a6xx_gpu->preempt_postamble_ptr))
+ goto fail;
+
+ timer_setup(&a6xx_gpu->preempt_timer, a6xx_preempt_timer, 0);
+
+ return;
+fail:
+ /*
+ * On any failure our adventure is over. Clean up and
+ * set nr_rings to 1 to force preemption off
+ */
+ a6xx_preempt_fini(gpu);
+ gpu->nr_rings = 1;
+
+ DRM_DEV_ERROR(&gpu->pdev->dev,
+ "preemption init failed, disabling preemption\n");
+
+ return;
+}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index cfc74a9e2646..9ffe91920fbf 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -20,6 +20,10 @@ bool allow_vram_carveout = false;
MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU");
module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600);
+int enable_preemption = -1;
+MODULE_PARM_DESC(enable_preemption, "Enable preemption (A7xx only) (1=on , 0=disable, -1=auto (default))");
+module_param(enable_preemption, int, 0600);
+
extern const struct adreno_gpulist a2xx_gpulist;
extern const struct adreno_gpulist a3xx_gpulist;
extern const struct adreno_gpulist a4xx_gpulist;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 465a4cd14a43..75f5367e73ca 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -533,7 +533,7 @@ int adreno_load_fw(struct adreno_gpu *adreno_gpu)
if (!adreno_gpu->info->fw[i])
continue;
- /* Skip loading GMU firwmare with GMU Wrapper */
+ /* Skip loading GMU firmware with GMU Wrapper */
if (adreno_has_gmu_wrapper(adreno_gpu) && i == ADRENO_FW_GMU)
continue;
@@ -572,8 +572,19 @@ struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu,
int adreno_hw_init(struct msm_gpu *gpu)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ int ret;
+
VERB("%s", gpu->name);
+ if (adreno_gpu->info->family >= ADRENO_6XX_GEN1 &&
+ qcom_scm_set_gpu_smmu_aperture_is_available()) {
+ /* We currently always use context bank 0, so hard code this */
+ ret = qcom_scm_set_gpu_smmu_aperture(0);
+ if (ret)
+ DRM_DEV_ERROR(gpu->dev->dev, "unable to set SMMU aperture: %d\n", ret);
+ }
+
for (int i = 0; i < gpu->nr_rings; i++) {
struct msm_ringbuffer *ring = gpu->rb[i];
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 58d7e7915c57..e71f420f8b3a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -56,6 +56,7 @@ enum adreno_family {
#define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2)
#define ADRENO_QUIRK_HAS_HW_APRIV BIT(3)
#define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4)
+#define ADRENO_QUIRK_PREEMPTION BIT(5)
/* Helper for formating the chip_id in the way that userspace tools like
* crashdec expect.
@@ -111,6 +112,7 @@ struct adreno_info {
* {SHRT_MAX, 0} sentinal.
*/
struct adreno_speedbin *speedbins;
+ u64 preempt_record_size;
};
#define ADRENO_CHIP_IDS(tbl...) (uint32_t[]) { tbl, 0 }
@@ -156,6 +158,19 @@ static const struct adreno_protect name = { \
.count_max = __count_max, \
};
+struct adreno_reglist_list {
+ /** @reg: List of register **/
+ const u32 *regs;
+ /** @count: Number of registers in the list **/
+ u32 count;
+};
+
+#define DECLARE_ADRENO_REGLIST_LIST(name) \
+static const struct adreno_reglist_list name = { \
+ .regs = name ## _regs, \
+ .count = ARRAY_SIZE(name ## _regs), \
+};
+
struct adreno_gpu {
struct msm_gpu base;
const struct adreno_info *info;
@@ -455,6 +470,11 @@ static inline int adreno_is_a680(const struct adreno_gpu *gpu)
return adreno_is_revn(gpu, 680);
}
+static inline int adreno_is_a663(const struct adreno_gpu *gpu)
+{
+ return gpu->info->chip_ids[0] == 0x06060300;
+}
+
static inline int adreno_is_a690(const struct adreno_gpu *gpu)
{
return gpu->info->chip_ids[0] == 0x06090000;
@@ -656,12 +676,15 @@ OUT_PKT4(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
OUT_RING(ring, PKT4(regindx, cnt));
}
+#define PKT7(opcode, cnt) \
+ (CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) | \
+ ((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23))
+
static inline void
OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
{
adreno_wait_ring(ring, cnt + 1);
- OUT_RING(ring, CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) |
- ((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23));
+ OUT_RING(ring, PKT7(opcode, cnt));
}
struct msm_gpu *a2xx_gpu_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
new file mode 100644
index 000000000000..ab3dfb0b374e
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef _DPU_1_14_MSM8937_H
+#define _DPU_1_14_MSM8937_H
+
+static const struct dpu_caps msm8937_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
+ .max_mixer_blendstages = 0x4,
+ .max_linewidth = DEFAULT_DPU_LINE_WIDTH,
+ .pixel_ram_size = 40 * 1024,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
+static const struct dpu_mdp_cfg msm8937_mdp[] = {
+ {
+ .name = "top_0",
+ .base = 0x0, .len = 0x454,
+ .features = BIT(DPU_MDP_VSYNC_SEL),
+ .clk_ctrls = {
+ [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
+ [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
+ [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
+ },
+ },
+};
+
+static const struct dpu_ctl_cfg msm8937_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x64,
+ }, {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x64,
+ }, {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x64,
+ },
+};
+
+static const struct dpu_sspp_cfg msm8937_sspp[] = {
+ {
+ .name = "sspp_0", .id = SSPP_VIG0,
+ .base = 0x4000, .len = 0x150,
+ .features = VIG_MSM8953_MASK,
+ .sblk = &dpu_vig_sblk_qseed2,
+ .xin_id = 0,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG0,
+ }, {
+ .name = "sspp_4", .id = SSPP_RGB0,
+ .base = 0x14000, .len = 0x150,
+ .features = RGB_MSM8953_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 1,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB0,
+ }, {
+ .name = "sspp_5", .id = SSPP_RGB1,
+ .base = 0x16000, .len = 0x150,
+ .features = RGB_MSM8953_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 5,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB1,
+ }, {
+ .name = "sspp_8", .id = SSPP_DMA0,
+ .base = 0x24000, .len = 0x150,
+ .features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR),
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 2,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA0,
+ },
+};
+
+static const struct dpu_lm_cfg msm8937_lm[] = {
+ {
+ .name = "lm_0", .id = LM_0,
+ .base = 0x44000, .len = 0x320,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_1,
+ .pingpong = PINGPONG_0,
+ .dspp = DSPP_0,
+ }, {
+ .name = "lm_1", .id = LM_1,
+ .base = 0x45000, .len = 0x320,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_0,
+ .pingpong = PINGPONG_1,
+ },
+};
+
+static const struct dpu_pingpong_cfg msm8937_pp[] = {
+ {
+ .name = "pingpong_0", .id = PINGPONG_0,
+ .base = 0x70000, .len = 0xd4,
+ .features = PINGPONG_MSM8996_MASK,
+ .sblk = &msm8996_pp_sblk,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
+ }, {
+ .name = "pingpong_1", .id = PINGPONG_1,
+ .base = 0x70800, .len = 0xd4,
+ .features = PINGPONG_MSM8996_MASK,
+ .sblk = &msm8996_pp_sblk,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
+ },
+};
+
+static const struct dpu_dspp_cfg msm8937_dspp[] = {
+ {
+ .name = "dspp_0", .id = DSPP_0,
+ .base = 0x54000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &msm8998_dspp_sblk,
+ },
+};
+
+static const struct dpu_intf_cfg msm8937_intf[] = {
+ {
+ .name = "intf_1", .id = INTF_1,
+ .base = 0x6a800, .len = 0x268,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 14,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ .intr_tear_rd_ptr = -1,
+ }, {
+ .name = "intf_2", .id = INTF_2,
+ .base = 0x6b000, .len = 0x268,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_1,
+ .prog_fetch_lines_worst_case = 14,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ .intr_tear_rd_ptr = -1,
+ },
+};
+
+static const struct dpu_perf_cfg msm8937_perf_data = {
+ .max_bw_low = 3100000,
+ .max_bw_high = 3100000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 0, /* No LLCC on this SoC */
+ .min_dram_ib = 800000,
+ .undersized_prefill_lines = 2,
+ .xtra_prefill_lines = 2,
+ .dest_scale_prefill_lines = 3,
+ .macrotile_prefill_lines = 4,
+ .yuv_nv12_prefill_lines = 8,
+ .linear_prefill_lines = 1,
+ .downscaling_prefill_lines = 1,
+ .amortizable_threshold = 25,
+ .min_prefill_lines = 14,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(msm8998_qos_linear),
+ .entries = msm8998_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
+ .entries = msm8998_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_nrt),
+ .entries = msm8998_qos_nrt
+ },
+ },
+ .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_mdss_version msm8937_mdss_ver = {
+ .core_major_ver = 1,
+ .core_minor_ver = 14,
+};
+
+const struct dpu_mdss_cfg dpu_msm8937_cfg = {
+ .mdss_ver = &msm8937_mdss_ver,
+ .caps = &msm8937_dpu_caps,
+ .mdp = msm8937_mdp,
+ .ctl_count = ARRAY_SIZE(msm8937_ctl),
+ .ctl = msm8937_ctl,
+ .sspp_count = ARRAY_SIZE(msm8937_sspp),
+ .sspp = msm8937_sspp,
+ .mixer_count = ARRAY_SIZE(msm8937_lm),
+ .mixer = msm8937_lm,
+ .dspp_count = ARRAY_SIZE(msm8937_dspp),
+ .dspp = msm8937_dspp,
+ .pingpong_count = ARRAY_SIZE(msm8937_pp),
+ .pingpong = msm8937_pp,
+ .intf_count = ARRAY_SIZE(msm8937_intf),
+ .intf = msm8937_intf,
+ .vbif_count = ARRAY_SIZE(msm8996_vbif),
+ .vbif = msm8996_vbif,
+ .perf = &msm8937_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
new file mode 100644
index 000000000000..6bdaecca6761
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h
@@ -0,0 +1,187 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef _DPU_1_14_MSM8917_H
+#define _DPU_1_14_MSM8917_H
+
+static const struct dpu_caps msm8917_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
+ .max_mixer_blendstages = 0x4,
+ .max_linewidth = DEFAULT_DPU_LINE_WIDTH,
+ .pixel_ram_size = 16 * 1024,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
+static const struct dpu_mdp_cfg msm8917_mdp[] = {
+ {
+ .name = "top_0",
+ .base = 0x0, .len = 0x454,
+ .features = BIT(DPU_MDP_VSYNC_SEL),
+ .clk_ctrls = {
+ [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
+ [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
+ [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
+ },
+ },
+};
+
+static const struct dpu_ctl_cfg msm8917_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x64,
+ }, {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x64,
+ }, {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x64,
+ },
+};
+
+static const struct dpu_sspp_cfg msm8917_sspp[] = {
+ {
+ .name = "sspp_0", .id = SSPP_VIG0,
+ .base = 0x4000, .len = 0x150,
+ .features = VIG_MSM8953_MASK,
+ .sblk = &dpu_vig_sblk_qseed2,
+ .xin_id = 0,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG0,
+ }, {
+ .name = "sspp_4", .id = SSPP_RGB0,
+ .base = 0x14000, .len = 0x150,
+ .features = RGB_MSM8953_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 1,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB0,
+ }, {
+ .name = "sspp_5", .id = SSPP_RGB1,
+ .base = 0x16000, .len = 0x150,
+ .features = RGB_MSM8953_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 5,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB1,
+ }, {
+ .name = "sspp_8", .id = SSPP_DMA0,
+ .base = 0x24000, .len = 0x150,
+ .features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR),
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 2,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA0,
+ },
+};
+
+static const struct dpu_lm_cfg msm8917_lm[] = {
+ {
+ .name = "lm_0", .id = LM_0,
+ .base = 0x44000, .len = 0x320,
+ .sblk = &msm8998_lm_sblk,
+ .pingpong = PINGPONG_0,
+ .dspp = DSPP_0,
+ },
+};
+
+static const struct dpu_pingpong_cfg msm8917_pp[] = {
+ {
+ .name = "pingpong_0", .id = PINGPONG_0,
+ .base = 0x70000, .len = 0xd4,
+ .features = PINGPONG_MSM8996_MASK,
+ .sblk = &msm8996_pp_sblk,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
+ },
+};
+
+static const struct dpu_dspp_cfg msm8917_dspp[] = {
+ {
+ .name = "dspp_0", .id = DSPP_0,
+ .base = 0x54000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &msm8998_dspp_sblk,
+ },
+};
+
+static const struct dpu_intf_cfg msm8917_intf[] = {
+ {
+ .name = "intf_1", .id = INTF_1,
+ .base = 0x6a800, .len = 0x268,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 14,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ .intr_tear_rd_ptr = -1,
+ },
+};
+
+static const struct dpu_perf_cfg msm8917_perf_data = {
+ .max_bw_low = 1800000,
+ .max_bw_high = 1800000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 0, /* No LLCC on this SoC */
+ .min_dram_ib = 800000,
+ .undersized_prefill_lines = 2,
+ .xtra_prefill_lines = 2,
+ .dest_scale_prefill_lines = 3,
+ .macrotile_prefill_lines = 4,
+ .yuv_nv12_prefill_lines = 8,
+ .linear_prefill_lines = 1,
+ .downscaling_prefill_lines = 1,
+ .amortizable_threshold = 25,
+ .min_prefill_lines = 21,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(msm8998_qos_linear),
+ .entries = msm8998_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
+ .entries = msm8998_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_nrt),
+ .entries = msm8998_qos_nrt
+ },
+ },
+ .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_mdss_version msm8917_mdss_ver = {
+ .core_major_ver = 1,
+ .core_minor_ver = 15,
+};
+
+const struct dpu_mdss_cfg dpu_msm8917_cfg = {
+ .mdss_ver = &msm8917_mdss_ver,
+ .caps = &msm8917_dpu_caps,
+ .mdp = msm8917_mdp,
+ .ctl_count = ARRAY_SIZE(msm8917_ctl),
+ .ctl = msm8917_ctl,
+ .sspp_count = ARRAY_SIZE(msm8917_sspp),
+ .sspp = msm8917_sspp,
+ .mixer_count = ARRAY_SIZE(msm8917_lm),
+ .mixer = msm8917_lm,
+ .dspp_count = ARRAY_SIZE(msm8917_dspp),
+ .dspp = msm8917_dspp,
+ .pingpong_count = ARRAY_SIZE(msm8917_pp),
+ .pingpong = msm8917_pp,
+ .intf_count = ARRAY_SIZE(msm8917_intf),
+ .intf = msm8917_intf,
+ .vbif_count = ARRAY_SIZE(msm8996_vbif),
+ .vbif = msm8996_vbif,
+ .perf = &msm8917_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
new file mode 100644
index 000000000000..14f36ea6ad0e
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef _DPU_1_16_MSM8953_H
+#define _DPU_1_16_MSM8953_H
+
+static const struct dpu_caps msm8953_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_LINE_WIDTH,
+ .max_mixer_blendstages = 0x4,
+ .max_linewidth = DEFAULT_DPU_LINE_WIDTH,
+ .pixel_ram_size = 40 * 1024,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
+static const struct dpu_mdp_cfg msm8953_mdp[] = {
+ {
+ .name = "top_0",
+ .base = 0x0, .len = 0x454,
+ .features = BIT(DPU_MDP_VSYNC_SEL),
+ .clk_ctrls = {
+ [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
+ [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
+ [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
+ },
+ },
+};
+
+static const struct dpu_ctl_cfg msm8953_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x64,
+ }, {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x64,
+ }, {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x64,
+ },
+};
+
+static const struct dpu_sspp_cfg msm8953_sspp[] = {
+ {
+ .name = "sspp_0", .id = SSPP_VIG0,
+ .base = 0x4000, .len = 0x150,
+ .features = VIG_MSM8953_MASK,
+ .sblk = &dpu_vig_sblk_qseed2,
+ .xin_id = 0,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG0,
+ }, {
+ .name = "sspp_4", .id = SSPP_RGB0,
+ .base = 0x14000, .len = 0x150,
+ .features = RGB_MSM8953_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 1,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB0,
+ }, {
+ .name = "sspp_5", .id = SSPP_RGB1,
+ .base = 0x16000, .len = 0x150,
+ .features = RGB_MSM8953_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 5,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB1,
+ }, {
+ .name = "sspp_8", .id = SSPP_DMA0,
+ .base = 0x24000, .len = 0x150,
+ .features = DMA_MSM8953_MASK | BIT(DPU_SSPP_CURSOR),
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 2,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA0,
+ },
+};
+
+static const struct dpu_lm_cfg msm8953_lm[] = {
+ {
+ .name = "lm_0", .id = LM_0,
+ .base = 0x44000, .len = 0x320,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_1,
+ .pingpong = PINGPONG_0,
+ .dspp = DSPP_0,
+ }, {
+ .name = "lm_1", .id = LM_1,
+ .base = 0x45000, .len = 0x320,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_0,
+ .pingpong = PINGPONG_1,
+ },
+};
+
+static const struct dpu_pingpong_cfg msm8953_pp[] = {
+ {
+ .name = "pingpong_0", .id = PINGPONG_0,
+ .base = 0x70000, .len = 0xd4,
+ .features = PINGPONG_MSM8996_MASK,
+ .sblk = &msm8996_pp_sblk,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
+ }, {
+ .name = "pingpong_1", .id = PINGPONG_1,
+ .base = 0x70800, .len = 0xd4,
+ .features = PINGPONG_MSM8996_MASK,
+ .sblk = &msm8996_pp_sblk,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
+ },
+};
+
+static const struct dpu_dspp_cfg msm8953_dspp[] = {
+ {
+ .name = "dspp_0", .id = DSPP_0,
+ .base = 0x54000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &msm8998_dspp_sblk,
+ },
+};
+
+static const struct dpu_intf_cfg msm8953_intf[] = {
+ {
+ .name = "intf_0", .id = INTF_0,
+ .base = 0x6a000, .len = 0x268,
+ .type = INTF_NONE,
+ .prog_fetch_lines_worst_case = 14,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
+ .intr_tear_rd_ptr = -1,
+ }, {
+ .name = "intf_1", .id = INTF_1,
+ .base = 0x6a800, .len = 0x268,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 14,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ .intr_tear_rd_ptr = -1,
+ }, {
+ .name = "intf_2", .id = INTF_2,
+ .base = 0x6b000, .len = 0x268,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_1,
+ .prog_fetch_lines_worst_case = 14,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ .intr_tear_rd_ptr = -1,
+ },
+};
+
+static const struct dpu_perf_cfg msm8953_perf_data = {
+ .max_bw_low = 3400000,
+ .max_bw_high = 3400000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 0, /* No LLCC on this SoC */
+ .min_dram_ib = 800000,
+ .undersized_prefill_lines = 2,
+ .xtra_prefill_lines = 2,
+ .dest_scale_prefill_lines = 3,
+ .macrotile_prefill_lines = 4,
+ .yuv_nv12_prefill_lines = 8,
+ .linear_prefill_lines = 1,
+ .downscaling_prefill_lines = 1,
+ .amortizable_threshold = 25,
+ .min_prefill_lines = 14,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(msm8998_qos_linear),
+ .entries = msm8998_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
+ .entries = msm8998_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_nrt),
+ .entries = msm8998_qos_nrt
+ },
+ },
+ .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_mdss_version msm8953_mdss_ver = {
+ .core_major_ver = 1,
+ .core_minor_ver = 16,
+};
+
+const struct dpu_mdss_cfg dpu_msm8953_cfg = {
+ .mdss_ver = &msm8953_mdss_ver,
+ .caps = &msm8953_dpu_caps,
+ .mdp = msm8953_mdp,
+ .ctl_count = ARRAY_SIZE(msm8953_ctl),
+ .ctl = msm8953_ctl,
+ .sspp_count = ARRAY_SIZE(msm8953_sspp),
+ .sspp = msm8953_sspp,
+ .mixer_count = ARRAY_SIZE(msm8953_lm),
+ .mixer = msm8953_lm,
+ .dspp_count = ARRAY_SIZE(msm8953_dspp),
+ .dspp = msm8953_dspp,
+ .pingpong_count = ARRAY_SIZE(msm8953_pp),
+ .pingpong = msm8953_pp,
+ .intf_count = ARRAY_SIZE(msm8953_intf),
+ .intf = msm8953_intf,
+ .vbif_count = ARRAY_SIZE(msm8996_vbif),
+ .vbif = msm8996_vbif,
+ .perf = &msm8953_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
new file mode 100644
index 000000000000..491f6f5827d1
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h
@@ -0,0 +1,338 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DPU_1_7_MSM8996_H
+#define _DPU_1_7_MSM8996_H
+
+static const struct dpu_caps msm8996_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0x7,
+ .has_src_split = true,
+ .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
+static const struct dpu_mdp_cfg msm8996_mdp[] = {
+ {
+ .name = "top_0",
+ .base = 0x0, .len = 0x454,
+ .features = BIT(DPU_MDP_VSYNC_SEL),
+ .clk_ctrls = {
+ [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 },
+ [DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 },
+ [DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0 },
+ [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 },
+ [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 },
+ [DPU_CLK_CTRL_RGB2] = { .reg_off = 0x2bc, .bit_off = 4 },
+ [DPU_CLK_CTRL_RGB3] = { .reg_off = 0x2c4, .bit_off = 4 },
+ [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
+ [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 },
+ [DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 16 },
+ },
+ },
+};
+
+static const struct dpu_ctl_cfg msm8996_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x64,
+ }, {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x64,
+ }, {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x64,
+ }, {
+ .name = "ctl_3", .id = CTL_3,
+ .base = 0x1600, .len = 0x64,
+ }, {
+ .name = "ctl_4", .id = CTL_4,
+ .base = 0x1800, .len = 0x64,
+ },
+};
+
+static const struct dpu_sspp_cfg msm8996_sspp[] = {
+ {
+ .name = "sspp_0", .id = SSPP_VIG0,
+ .base = 0x4000, .len = 0x150,
+ .features = VIG_MSM8996_MASK,
+ .sblk = &dpu_vig_sblk_qseed2,
+ .xin_id = 0,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG0,
+ }, {
+ .name = "sspp_1", .id = SSPP_VIG1,
+ .base = 0x6000, .len = 0x150,
+ .features = VIG_MSM8996_MASK,
+ .sblk = &dpu_vig_sblk_qseed2,
+ .xin_id = 4,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG1,
+ }, {
+ .name = "sspp_2", .id = SSPP_VIG2,
+ .base = 0x8000, .len = 0x150,
+ .features = VIG_MSM8996_MASK,
+ .sblk = &dpu_vig_sblk_qseed2,
+ .xin_id = 8,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG2,
+ }, {
+ .name = "sspp_3", .id = SSPP_VIG3,
+ .base = 0xa000, .len = 0x150,
+ .features = VIG_MSM8996_MASK,
+ .sblk = &dpu_vig_sblk_qseed2,
+ .xin_id = 12,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG3,
+ }, {
+ .name = "sspp_4", .id = SSPP_RGB0,
+ .base = 0x14000, .len = 0x150,
+ .features = RGB_MSM8996_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 1,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB0,
+ }, {
+ .name = "sspp_5", .id = SSPP_RGB1,
+ .base = 0x16000, .len = 0x150,
+ .features = RGB_MSM8996_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 5,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB1,
+ }, {
+ .name = "sspp_6", .id = SSPP_RGB2,
+ .base = 0x18000, .len = 0x150,
+ .features = RGB_MSM8996_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 9,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB2,
+ }, {
+ .name = "sspp_7", .id = SSPP_RGB3,
+ .base = 0x1a000, .len = 0x150,
+ .features = RGB_MSM8996_MASK,
+ .sblk = &dpu_rgb_sblk,
+ .xin_id = 13,
+ .type = SSPP_TYPE_RGB,
+ .clk_ctrl = DPU_CLK_CTRL_RGB3,
+ }, {
+ .name = "sspp_8", .id = SSPP_DMA0,
+ .base = 0x24000, .len = 0x150,
+ .features = DMA_MSM8996_MASK,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 2,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA0,
+ }, {
+ .name = "sspp_9", .id = SSPP_DMA1,
+ .base = 0x26000, .len = 0x150,
+ .features = DMA_MSM8996_MASK,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 10,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA1,
+ },
+};
+
+static const struct dpu_lm_cfg msm8996_lm[] = {
+ {
+ .name = "lm_0", .id = LM_0,
+ .base = 0x44000, .len = 0x320,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_1,
+ .pingpong = PINGPONG_0,
+ .dspp = DSPP_0,
+ }, {
+ .name = "lm_1", .id = LM_1,
+ .base = 0x45000, .len = 0x320,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_0,
+ .pingpong = PINGPONG_1,
+ .dspp = DSPP_1,
+ }, {
+ .name = "lm_2", .id = LM_2,
+ .base = 0x46000, .len = 0x320,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_5,
+ .pingpong = PINGPONG_2,
+ }, {
+ .name = "lm_5", .id = LM_5,
+ .base = 0x49000, .len = 0x320,
+ .features = MIXER_MSM8998_MASK,
+ .sblk = &msm8998_lm_sblk,
+ .lm_pair = LM_2,
+ .pingpong = PINGPONG_3,
+ },
+};
+
+static const struct dpu_pingpong_cfg msm8996_pp[] = {
+ {
+ .name = "pingpong_0", .id = PINGPONG_0,
+ .base = 0x70000, .len = 0xd4,
+ .features = PINGPONG_MSM8996_TE2_MASK,
+ .sblk = &msm8996_pp_sblk_te,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
+ }, {
+ .name = "pingpong_1", .id = PINGPONG_1,
+ .base = 0x70800, .len = 0xd4,
+ .features = PINGPONG_MSM8996_TE2_MASK,
+ .sblk = &msm8996_pp_sblk_te,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
+ }, {
+ .name = "pingpong_2", .id = PINGPONG_2,
+ .base = 0x71000, .len = 0xd4,
+ .features = PINGPONG_MSM8996_MASK,
+ .sblk = &msm8996_pp_sblk,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14),
+ }, {
+ .name = "pingpong_3", .id = PINGPONG_3,
+ .base = 0x71800, .len = 0xd4,
+ .features = PINGPONG_MSM8996_MASK,
+ .sblk = &msm8996_pp_sblk,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
+ .intr_rdptr = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15),
+ },
+};
+
+static const struct dpu_dsc_cfg msm8996_dsc[] = {
+ {
+ .name = "dsc_0", .id = DSC_0,
+ .base = 0x80000, .len = 0x140,
+ }, {
+ .name = "dsc_1", .id = DSC_1,
+ .base = 0x80400, .len = 0x140,
+ },
+};
+
+static const struct dpu_dspp_cfg msm8996_dspp[] = {
+ {
+ .name = "dspp_0", .id = DSPP_0,
+ .base = 0x54000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &msm8998_dspp_sblk,
+ }, {
+ .name = "dspp_1", .id = DSPP_1,
+ .base = 0x56000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &msm8998_dspp_sblk,
+ },
+};
+
+static const struct dpu_intf_cfg msm8996_intf[] = {
+ {
+ .name = "intf_0", .id = INTF_0,
+ .base = 0x6a000, .len = 0x268,
+ .type = INTF_NONE,
+ .prog_fetch_lines_worst_case = 25,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
+ .intr_tear_rd_ptr = -1,
+ }, {
+ .name = "intf_1", .id = INTF_1,
+ .base = 0x6a800, .len = 0x268,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 25,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ .intr_tear_rd_ptr = -1,
+ }, {
+ .name = "intf_2", .id = INTF_2,
+ .base = 0x6b000, .len = 0x268,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_1,
+ .prog_fetch_lines_worst_case = 25,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ .intr_tear_rd_ptr = -1,
+ }, {
+ .name = "intf_3", .id = INTF_3,
+ .base = 0x6b800, .len = 0x268,
+ .type = INTF_HDMI,
+ .prog_fetch_lines_worst_case = 25,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
+ .intr_tear_rd_ptr = -1,
+ },
+};
+
+static const struct dpu_perf_cfg msm8996_perf_data = {
+ .max_bw_low = 9600000,
+ .max_bw_high = 9600000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 0, /* No LLCC on this SoC */
+ .min_dram_ib = 800000,
+ .undersized_prefill_lines = 2,
+ .xtra_prefill_lines = 2,
+ .dest_scale_prefill_lines = 3,
+ .macrotile_prefill_lines = 4,
+ .yuv_nv12_prefill_lines = 8,
+ .linear_prefill_lines = 1,
+ .downscaling_prefill_lines = 1,
+ .amortizable_threshold = 25,
+ .min_prefill_lines = 21,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfffc, 0xff00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(msm8998_qos_linear),
+ .entries = msm8998_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_macrotile),
+ .entries = msm8998_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(msm8998_qos_nrt),
+ .entries = msm8998_qos_nrt
+ },
+ },
+ .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_mdss_version msm8996_mdss_ver = {
+ .core_major_ver = 1,
+ .core_minor_ver = 7,
+};
+
+const struct dpu_mdss_cfg dpu_msm8996_cfg = {
+ .mdss_ver = &msm8996_mdss_ver,
+ .caps = &msm8996_dpu_caps,
+ .mdp = msm8996_mdp,
+ .ctl_count = ARRAY_SIZE(msm8996_ctl),
+ .ctl = msm8996_ctl,
+ .sspp_count = ARRAY_SIZE(msm8996_sspp),
+ .sspp = msm8996_sspp,
+ .mixer_count = ARRAY_SIZE(msm8996_lm),
+ .mixer = msm8996_lm,
+ .dspp_count = ARRAY_SIZE(msm8996_dspp),
+ .dspp = msm8996_dspp,
+ .pingpong_count = ARRAY_SIZE(msm8996_pp),
+ .pingpong = msm8996_pp,
+ .dsc_count = ARRAY_SIZE(msm8996_dsc),
+ .dsc = msm8996_dsc,
+ .intf_count = ARRAY_SIZE(msm8996_intf),
+ .intf = msm8996_intf,
+ .vbif_count = ARRAY_SIZE(msm8996_vbif),
+ .vbif = msm8996_vbif,
+ .perf = &msm8996_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
index 1d3e9666c741..64c94e919a69 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
@@ -157,18 +157,6 @@ static const struct dpu_lm_cfg msm8998_lm[] = {
.lm_pair = LM_5,
.pingpong = PINGPONG_2,
}, {
- .name = "lm_3", .id = LM_3,
- .base = 0x47000, .len = 0x320,
- .features = MIXER_MSM8998_MASK,
- .sblk = &msm8998_lm_sblk,
- .pingpong = PINGPONG_NONE,
- }, {
- .name = "lm_4", .id = LM_4,
- .base = 0x48000, .len = 0x320,
- .features = MIXER_MSM8998_MASK,
- .sblk = &msm8998_lm_sblk,
- .pingpong = PINGPONG_NONE,
- }, {
.name = "lm_5", .id = LM_5,
.base = 0x49000, .len = 0x320,
.features = MIXER_MSM8998_MASK,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
index 7a23389a5732..72bd4f7e9e50 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
@@ -156,25 +156,13 @@ static const struct dpu_lm_cfg sdm845_lm[] = {
.pingpong = PINGPONG_2,
.dspp = DSPP_2,
}, {
- .name = "lm_3", .id = LM_3,
- .base = 0x0, .len = 0x320,
- .features = MIXER_SDM845_MASK,
- .sblk = &sdm845_lm_sblk,
- .pingpong = PINGPONG_NONE,
- .dspp = DSPP_3,
- }, {
- .name = "lm_4", .id = LM_4,
- .base = 0x0, .len = 0x320,
- .features = MIXER_SDM845_MASK,
- .sblk = &sdm845_lm_sblk,
- .pingpong = PINGPONG_NONE,
- }, {
.name = "lm_5", .id = LM_5,
.base = 0x49000, .len = 0x320,
.features = MIXER_SDM845_MASK,
.sblk = &sdm845_lm_sblk,
.lm_pair = LM_2,
.pingpong = PINGPONG_3,
+ .dspp = DSPP_3,
},
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
new file mode 100644
index 000000000000..907b4d7ceb47
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
@@ -0,0 +1,485 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DPU_8_4_SA8775P_H
+#define _DPU_8_4_SA8775P_H
+
+static const struct dpu_caps sa8775p_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0xb,
+ .has_src_split = true,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .has_3d_merge = true,
+ .max_linewidth = 5120,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_mdp_cfg sa8775p_mdp = {
+ .name = "top_0",
+ .base = 0x0, .len = 0x494,
+ .features = BIT(DPU_MDP_PERIPH_0_REMOVED),
+ .clk_ctrls = {
+ [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 },
+ [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 },
+ [DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 },
+ [DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0 },
+ [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 },
+ [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 },
+ [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8 },
+ [DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8 },
+ [DPU_CLK_CTRL_WB2] = { .reg_off = 0x2bc, .bit_off = 16 },
+ [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
+ },
+};
+
+/* FIXME: get rid of DPU_CTL_SPLIT_DISPLAY in favour of proper ACTIVE_CTL support */
+static const struct dpu_ctl_cfg sa8775p_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x15000, .len = 0x204,
+ .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+ }, {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x16000, .len = 0x204,
+ .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+ }, {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x17000, .len = 0x204,
+ .features = CTL_SC7280_MASK,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+ }, {
+ .name = "ctl_3", .id = CTL_3,
+ .base = 0x18000, .len = 0x204,
+ .features = CTL_SC7280_MASK,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+ }, {
+ .name = "ctl_4", .id = CTL_4,
+ .base = 0x19000, .len = 0x204,
+ .features = CTL_SC7280_MASK,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
+ }, {
+ .name = "ctl_5", .id = CTL_5,
+ .base = 0x1a000, .len = 0x204,
+ .features = CTL_SC7280_MASK,
+ .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23),
+ },
+};
+
+static const struct dpu_sspp_cfg sa8775p_sspp[] = {
+ {
+ .name = "sspp_0", .id = SSPP_VIG0,
+ .base = 0x4000, .len = 0x32c,
+ .features = VIG_SDM845_MASK_SDMA,
+ .sblk = &dpu_vig_sblk_qseed3_3_1,
+ .xin_id = 0,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG0,
+ }, {
+ .name = "sspp_1", .id = SSPP_VIG1,
+ .base = 0x6000, .len = 0x32c,
+ .features = VIG_SDM845_MASK_SDMA,
+ .sblk = &dpu_vig_sblk_qseed3_3_1,
+ .xin_id = 4,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG1,
+ }, {
+ .name = "sspp_2", .id = SSPP_VIG2,
+ .base = 0x8000, .len = 0x32c,
+ .features = VIG_SDM845_MASK_SDMA,
+ .sblk = &dpu_vig_sblk_qseed3_3_1,
+ .xin_id = 8,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG2,
+ }, {
+ .name = "sspp_3", .id = SSPP_VIG3,
+ .base = 0xa000, .len = 0x32c,
+ .features = VIG_SDM845_MASK_SDMA,
+ .sblk = &dpu_vig_sblk_qseed3_3_1,
+ .xin_id = 12,
+ .type = SSPP_TYPE_VIG,
+ .clk_ctrl = DPU_CLK_CTRL_VIG3,
+ }, {
+ .name = "sspp_8", .id = SSPP_DMA0,
+ .base = 0x24000, .len = 0x32c,
+ .features = DMA_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 1,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA0,
+ }, {
+ .name = "sspp_9", .id = SSPP_DMA1,
+ .base = 0x26000, .len = 0x32c,
+ .features = DMA_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 5,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA1,
+ }, {
+ .name = "sspp_10", .id = SSPP_DMA2,
+ .base = 0x28000, .len = 0x32c,
+ .features = DMA_CURSOR_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 9,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA2,
+ }, {
+ .name = "sspp_11", .id = SSPP_DMA3,
+ .base = 0x2a000, .len = 0x32c,
+ .features = DMA_CURSOR_SDM845_MASK_SDMA,
+ .sblk = &dpu_dma_sblk,
+ .xin_id = 13,
+ .type = SSPP_TYPE_DMA,
+ .clk_ctrl = DPU_CLK_CTRL_DMA3,
+ },
+};
+
+static const struct dpu_lm_cfg sa8775p_lm[] = {
+ {
+ .name = "lm_0", .id = LM_0,
+ .base = 0x44000, .len = 0x400,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_1,
+ .pingpong = PINGPONG_0,
+ .dspp = DSPP_0,
+ }, {
+ .name = "lm_1", .id = LM_1,
+ .base = 0x45000, .len = 0x400,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_0,
+ .pingpong = PINGPONG_1,
+ .dspp = DSPP_1,
+ }, {
+ .name = "lm_2", .id = LM_2,
+ .base = 0x46000, .len = 0x400,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_3,
+ .pingpong = PINGPONG_2,
+ .dspp = DSPP_2,
+ }, {
+ .name = "lm_3", .id = LM_3,
+ .base = 0x47000, .len = 0x400,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_2,
+ .pingpong = PINGPONG_3,
+ .dspp = DSPP_3,
+ }, {
+ .name = "lm_4", .id = LM_4,
+ .base = 0x48000, .len = 0x400,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_5,
+ .pingpong = PINGPONG_4,
+ }, {
+ .name = "lm_5", .id = LM_5,
+ .base = 0x49000, .len = 0x400,
+ .features = MIXER_SDM845_MASK,
+ .sblk = &sdm845_lm_sblk,
+ .lm_pair = LM_4,
+ .pingpong = PINGPONG_5,
+ },
+};
+
+static const struct dpu_dspp_cfg sa8775p_dspp[] = {
+ {
+ .name = "dspp_0", .id = DSPP_0,
+ .base = 0x54000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &sdm845_dspp_sblk,
+ }, {
+ .name = "dspp_1", .id = DSPP_1,
+ .base = 0x56000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &sdm845_dspp_sblk,
+ }, {
+ .name = "dspp_2", .id = DSPP_2,
+ .base = 0x58000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &sdm845_dspp_sblk,
+ }, {
+ .name = "dspp_3", .id = DSPP_3,
+ .base = 0x5a000, .len = 0x1800,
+ .features = DSPP_SC7180_MASK,
+ .sblk = &sdm845_dspp_sblk,
+ },
+};
+
+static const struct dpu_pingpong_cfg sa8775p_pp[] = {
+ {
+ .name = "pingpong_0", .id = PINGPONG_0,
+ .base = 0x69000, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_0,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
+ }, {
+ .name = "pingpong_1", .id = PINGPONG_1,
+ .base = 0x6a000, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_0,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9),
+ }, {
+ .name = "pingpong_2", .id = PINGPONG_2,
+ .base = 0x6b000, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_1,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10),
+ }, {
+ .name = "pingpong_3", .id = PINGPONG_3,
+ .base = 0x6c000, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_1,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11),
+ }, {
+ .name = "pingpong_4", .id = PINGPONG_4,
+ .base = 0x6d000, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_2,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30),
+ }, {
+ .name = "pingpong_5", .id = PINGPONG_5,
+ .base = 0x6e000, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_2,
+ .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
+ }, {
+ .name = "pingpong_6", .id = PINGPONG_6,
+ .base = 0x65800, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_3,
+ }, {
+ .name = "pingpong_7", .id = PINGPONG_7,
+ .base = 0x65c00, .len = 0,
+ .features = BIT(DPU_PINGPONG_DITHER),
+ .sblk = &sc7280_pp_sblk,
+ .merge_3d = MERGE_3D_3,
+ },
+};
+
+static const struct dpu_merge_3d_cfg sa8775p_merge_3d[] = {
+ {
+ .name = "merge_3d_0", .id = MERGE_3D_0,
+ .base = 0x4e000, .len = 0x8,
+ }, {
+ .name = "merge_3d_1", .id = MERGE_3D_1,
+ .base = 0x4f000, .len = 0x8,
+ }, {
+ .name = "merge_3d_2", .id = MERGE_3D_2,
+ .base = 0x50000, .len = 0x8,
+ }, {
+ .name = "merge_3d_3", .id = MERGE_3D_3,
+ .base = 0x65f00, .len = 0x8,
+ },
+};
+
+/*
+ * NOTE: Each display compression engine (DCE) contains dual hard
+ * slice DSC encoders so both share same base address but with
+ * its own different sub block address.
+ */
+static const struct dpu_dsc_cfg sa8775p_dsc[] = {
+ {
+ .name = "dce_0_0", .id = DSC_0,
+ .base = 0x80000, .len = 0x4,
+ .features = BIT(DPU_DSC_HW_REV_1_2),
+ .sblk = &dsc_sblk_0,
+ }, {
+ .name = "dce_0_1", .id = DSC_1,
+ .base = 0x80000, .len = 0x4,
+ .features = BIT(DPU_DSC_HW_REV_1_2),
+ .sblk = &dsc_sblk_1,
+ }, {
+ .name = "dce_1_0", .id = DSC_2,
+ .base = 0x81000, .len = 0x4,
+ .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
+ .sblk = &dsc_sblk_0,
+ }, {
+ .name = "dce_1_1", .id = DSC_3,
+ .base = 0x81000, .len = 0x4,
+ .features = BIT(DPU_DSC_HW_REV_1_2) | BIT(DPU_DSC_NATIVE_42x_EN),
+ .sblk = &dsc_sblk_1,
+ }, {
+ .name = "dce_2_0", .id = DSC_4,
+ .base = 0x82000, .len = 0x4,
+ .features = BIT(DPU_DSC_HW_REV_1_2),
+ .sblk = &dsc_sblk_0,
+ }, {
+ .name = "dce_2_1", .id = DSC_5,
+ .base = 0x82000, .len = 0x4,
+ .features = BIT(DPU_DSC_HW_REV_1_2),
+ .sblk = &dsc_sblk_1,
+ },
+};
+
+static const struct dpu_wb_cfg sa8775p_wb[] = {
+ {
+ .name = "wb_2", .id = WB_2,
+ .base = 0x65000, .len = 0x2c8,
+ .features = WB_SM8250_MASK,
+ .format_list = wb2_formats_rgb_yuv,
+ .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv),
+ .clk_ctrl = DPU_CLK_CTRL_WB2,
+ .xin_id = 6,
+ .vbif_idx = VBIF_RT,
+ .maxlinewidth = 4096,
+ .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4),
+ },
+};
+
+/* TODO: INTF 3, 6, 7 and 8 are used for MST, marked as INTF_NONE for now */
+static const struct dpu_intf_cfg sa8775p_intf[] = {
+ {
+ .name = "intf_0", .id = INTF_0,
+ .base = 0x34000, .len = 0x280,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25),
+ }, {
+ .name = "intf_1", .id = INTF_1,
+ .base = 0x35000, .len = 0x300,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_0,
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 26),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 27),
+ .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF1_TEAR_INTR, 2),
+ }, {
+ .name = "intf_2", .id = INTF_2,
+ .base = 0x36000, .len = 0x300,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_DSI,
+ .controller_id = MSM_DSI_CONTROLLER_1,
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 28),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 29),
+ .intr_tear_rd_ptr = DPU_IRQ_IDX(MDP_INTF2_TEAR_INTR, 2),
+ }, {
+ .name = "intf_3", .id = INTF_3,
+ .base = 0x37000, .len = 0x280,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_NONE,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31),
+ }, {
+ .name = "intf_4", .id = INTF_4,
+ .base = 0x38000, .len = 0x280,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_DP,
+ .controller_id = MSM_DP_CONTROLLER_1,
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21),
+ }, {
+ .name = "intf_6", .id = INTF_6,
+ .base = 0x3A000, .len = 0x280,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_NONE,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16),
+ }, {
+ .name = "intf_7", .id = INTF_7,
+ .base = 0x3b000, .len = 0x280,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_NONE,
+ .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19),
+ }, {
+ .name = "intf_8", .id = INTF_8,
+ .base = 0x3c000, .len = 0x280,
+ .features = INTF_SC7280_MASK,
+ .type = INTF_NONE,
+ .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */
+ .prog_fetch_lines_worst_case = 24,
+ .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12),
+ .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13),
+ },
+};
+
+static const struct dpu_perf_cfg sa8775p_perf_data = {
+ .max_bw_low = 13600000,
+ .max_bw_high = 18200000,
+ .min_core_ib = 2500000,
+ .min_llcc_ib = 0,
+ .min_dram_ib = 800000,
+ .min_prefill_lines = 35,
+ /* FIXME: lut tables */
+ .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0},
+ .safe_lut_tbl = {0xfff0, 0xfff0, 0x1},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
+ .entries = sm6350_qos_linear_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sm6350_qos_linear_macrotile),
+ .entries = sm6350_qos_linear_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ /* 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_mdss_version sa8775p_mdss_ver = {
+ .core_major_ver = 8,
+ .core_minor_ver = 4,
+};
+
+const struct dpu_mdss_cfg dpu_sa8775p_cfg = {
+ .mdss_ver = &sa8775p_mdss_ver,
+ .caps = &sa8775p_dpu_caps,
+ .mdp = &sa8775p_mdp,
+ .cdm = &sc7280_cdm,
+ .ctl_count = ARRAY_SIZE(sa8775p_ctl),
+ .ctl = sa8775p_ctl,
+ .sspp_count = ARRAY_SIZE(sa8775p_sspp),
+ .sspp = sa8775p_sspp,
+ .mixer_count = ARRAY_SIZE(sa8775p_lm),
+ .mixer = sa8775p_lm,
+ .dspp_count = ARRAY_SIZE(sa8775p_dspp),
+ .dspp = sa8775p_dspp,
+ .pingpong_count = ARRAY_SIZE(sa8775p_pp),
+ .pingpong = sa8775p_pp,
+ .dsc_count = ARRAY_SIZE(sa8775p_dsc),
+ .dsc = sa8775p_dsc,
+ .merge_3d_count = ARRAY_SIZE(sa8775p_merge_3d),
+ .merge_3d = sa8775p_merge_3d,
+ .wb_count = ARRAY_SIZE(sa8775p_wb),
+ .wb = sa8775p_wb,
+ .intf_count = ARRAY_SIZE(sa8775p_intf),
+ .intf = sa8775p_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .perf = &sa8775p_perf_data,
+};
+
+#endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
index 7c286bafb948..e7183cf05776 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
@@ -8,72 +8,26 @@
#include "dpu_kms.h"
#include "dpu_hw_interrupts.h"
-/**
- * dpu_core_irq_preinstall - perform pre-installation of core IRQ handler
- * @kms: MSM KMS handle
- * @return: none
- */
void dpu_core_irq_preinstall(struct msm_kms *kms);
-/**
- * dpu_core_irq_uninstall - uninstall core IRQ handler
- * @kms: MSM KMS handle
- * @return: none
- */
void dpu_core_irq_uninstall(struct msm_kms *kms);
-/**
- * dpu_core_irq - core IRQ handler
- * @kms: MSM KMS handle
- * @return: interrupt handling status
- */
irqreturn_t dpu_core_irq(struct msm_kms *kms);
-/**
- * dpu_core_irq_read - IRQ helper function for reading IRQ status
- * @dpu_kms: DPU handle
- * @irq_idx: irq index
- * @return: non-zero if irq detected; otherwise no irq detected
- */
u32 dpu_core_irq_read(
struct dpu_kms *dpu_kms,
unsigned int irq_idx);
-/**
- * dpu_core_irq_register_callback - For registering callback function on IRQ
- * interrupt
- * @dpu_kms: DPU handle
- * @irq_idx: irq index
- * @irq_cb: IRQ callback funcion.
- * @irq_arg: IRQ callback argument.
- * @return: 0 for success registering callback, otherwise failure
- *
- * This function supports registration of multiple callbacks for each interrupt.
- */
int dpu_core_irq_register_callback(
struct dpu_kms *dpu_kms,
unsigned int irq_idx,
void (*irq_cb)(void *arg),
void *irq_arg);
-/**
- * dpu_core_irq_unregister_callback - For unregistering callback function on IRQ
- * interrupt
- * @dpu_kms: DPU handle
- * @irq_idx: irq index
- * @return: 0 for success registering callback, otherwise failure
- *
- * This function supports registration of multiple callbacks for each interrupt.
- */
int dpu_core_irq_unregister_callback(
struct dpu_kms *dpu_kms,
unsigned int irq_idx);
-/**
- * dpu_debugfs_core_irq_init - register core irq debugfs
- * @dpu_kms: pointer to kms
- * @parent: debugfs directory root
- */
void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
struct dentry *parent);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index 68fae048a9a8..6f0a37f954fe 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -80,7 +80,7 @@ static u64 _dpu_core_perf_calc_clk(const struct dpu_perf_cfg *perf_cfg,
mode = &state->adjusted_mode;
- crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
+ crtc_clk = (u64)mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
drm_atomic_crtc_for_each_plane(plane, crtc) {
pstate = to_dpu_plane_state(plane->state);
@@ -140,6 +140,12 @@ static void _dpu_core_perf_calc_crtc(const struct dpu_core_perf *core_perf,
perf->max_per_pipe_ib, perf->bw_ctl);
}
+/**
+ * dpu_core_perf_crtc_check - validate performance of the given crtc state
+ * @crtc: Pointer to crtc
+ * @state: Pointer to new crtc state
+ * return: zero if success, or error code otherwise
+ */
int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
@@ -301,6 +307,12 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms)
return clk_rate;
}
+/**
+ * dpu_core_perf_crtc_update - update performance of the given crtc
+ * @crtc: Pointer to crtc
+ * @params_changed: true if crtc parameters are modified
+ * return: zero if success, or error code otherwise
+ */
int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
int params_changed)
{
@@ -446,6 +458,11 @@ static const struct file_operations dpu_core_perf_mode_fops = {
.write = _dpu_core_perf_mode_write,
};
+/**
+ * dpu_core_perf_debugfs_init - initialize debugfs for core performance context
+ * @dpu_kms: Pointer to the dpu_kms struct
+ * @parent: Pointer to parent debugfs
+ */
int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent)
{
struct dpu_core_perf *perf = &dpu_kms->perf;
@@ -482,6 +499,12 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent)
}
#endif
+/**
+ * dpu_core_perf_init - initialize the given core performance context
+ * @perf: Pointer to core performance context
+ * @perf_cfg: Pointer to platform performance configuration
+ * @max_core_clk_rate: Maximum core clock rate
+ */
int dpu_core_perf_init(struct dpu_core_perf *perf,
const struct dpu_perf_cfg *perf_cfg,
unsigned long max_core_clk_rate)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index 4186977390bd..451bf8021114 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -54,47 +54,20 @@ struct dpu_core_perf {
u64 fix_core_ab_vote;
};
-/**
- * dpu_core_perf_crtc_check - validate performance of the given crtc state
- * @crtc: Pointer to crtc
- * @state: Pointer to new crtc state
- * return: zero if success, or error code otherwise
- */
int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
struct drm_crtc_state *state);
-/**
- * dpu_core_perf_crtc_update - update performance of the given crtc
- * @crtc: Pointer to crtc
- * @params_changed: true if crtc parameters are modified
- * return: zero if success, or error code otherwise
- */
int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
int params_changed);
-/**
- * dpu_core_perf_crtc_release_bw - release bandwidth of the given crtc
- * @crtc: Pointer to crtc
- */
void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc);
-/**
- * dpu_core_perf_init - initialize the given core performance context
- * @perf: Pointer to core performance context
- * @perf_cfg: Pointer to platform performance configuration
- * @max_core_clk_rate: Maximum core clock rate
- */
int dpu_core_perf_init(struct dpu_core_perf *perf,
const struct dpu_perf_cfg *perf_cfg,
unsigned long max_core_clk_rate);
struct dpu_kms;
-/**
- * dpu_core_perf_debugfs_init - initialize debugfs for core performance context
- * @dpu_kms: Pointer to the dpu_kms struct
- * @debugfs_parent: Pointer to parent debugfs
- */
int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent);
#endif /* _DPU_CORE_PERF_H_ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index db6c57900781..9f6ffd344693 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -572,6 +572,10 @@ static void _dpu_crtc_complete_flip(struct drm_crtc *crtc)
spin_unlock_irqrestore(&dev->event_lock, flags);
}
+/**
+ * dpu_crtc_get_intf_mode - get interface mode of the given crtc
+ * @crtc: Pointert to crtc
+ */
enum dpu_intf_mode dpu_crtc_get_intf_mode(struct drm_crtc *crtc)
{
struct drm_encoder *encoder;
@@ -594,6 +598,10 @@ enum dpu_intf_mode dpu_crtc_get_intf_mode(struct drm_crtc *crtc)
return INTF_MODE_NONE;
}
+/**
+ * dpu_crtc_vblank_callback - called on vblank irq, issues completion events
+ * @crtc: Pointer to drm crtc object
+ */
void dpu_crtc_vblank_callback(struct drm_crtc *crtc)
{
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
@@ -704,6 +712,10 @@ void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event)
kthread_queue_work(priv->event_thread[crtc_id].worker, &fevent->work);
}
+/**
+ * dpu_crtc_complete_commit - callback signalling completion of current commit
+ * @crtc: Pointer to drm crtc object
+ */
void dpu_crtc_complete_commit(struct drm_crtc *crtc)
{
trace_dpu_crtc_complete_commit(DRMID(crtc));
@@ -934,6 +946,10 @@ static int _dpu_crtc_wait_for_frame_done(struct drm_crtc *crtc)
return rc;
}
+/**
+ * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this crtc
+ * @crtc: Pointer to drm crtc object
+ */
void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
{
struct drm_encoder *encoder;
@@ -1230,6 +1246,24 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
return 0;
}
+static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
+{
+ struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
+
+ /*
+ * max crtc width is equal to the max mixer width * 2 and max height is 4K
+ */
+ return drm_mode_validate_size(mode,
+ 2 * dpu_kms->catalog->caps->max_mixer_width,
+ 4096);
+}
+
+/**
+ * dpu_crtc_vblank - enable or disable vblanks for this crtc
+ * @crtc: Pointer to drm crtc object
+ * @en: true to enable vblanks, false to disable
+ */
int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
{
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
@@ -1445,10 +1479,19 @@ static const struct drm_crtc_helper_funcs dpu_crtc_helper_funcs = {
.atomic_check = dpu_crtc_atomic_check,
.atomic_begin = dpu_crtc_atomic_begin,
.atomic_flush = dpu_crtc_atomic_flush,
+ .mode_valid = dpu_crtc_mode_valid,
.get_scanout_position = dpu_crtc_get_scanout_position,
};
-/* initialize crtc */
+/**
+ * dpu_crtc_init - create a new crtc object
+ * @dev: dpu device
+ * @plane: base plane
+ * @cursor: cursor plane
+ * @return: new crtc object or error
+ *
+ * initialize CRTC
+ */
struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
struct drm_plane *cursor)
{
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index febc3e764a63..0b148f3ce0d7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -239,55 +239,17 @@ static inline int dpu_crtc_frame_pending(struct drm_crtc *crtc)
return crtc ? atomic_read(&to_dpu_crtc(crtc)->frame_pending) : -EINVAL;
}
-/**
- * dpu_crtc_vblank - enable or disable vblanks for this crtc
- * @crtc: Pointer to drm crtc object
- * @en: true to enable vblanks, false to disable
- */
int dpu_crtc_vblank(struct drm_crtc *crtc, bool en);
-/**
- * dpu_crtc_vblank_callback - called on vblank irq, issues completion events
- * @crtc: Pointer to drm crtc object
- */
void dpu_crtc_vblank_callback(struct drm_crtc *crtc);
-/**
- * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this crtc
- * @crtc: Pointer to drm crtc object
- */
void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
-/**
- * dpu_crtc_complete_commit - callback signalling completion of current commit
- * @crtc: Pointer to drm crtc object
- */
void dpu_crtc_complete_commit(struct drm_crtc *crtc);
-/**
- * dpu_crtc_init - create a new crtc object
- * @dev: dpu device
- * @plane: base plane
- * @cursor: cursor plane
- * @Return: new crtc object or error
- */
struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
struct drm_plane *cursor);
-/**
- * dpu_crtc_register_custom_event - api for enabling/disabling crtc event
- * @kms: Pointer to dpu_kms
- * @crtc_drm: Pointer to crtc object
- * @event: Event that client is interested
- * @en: Flag to enable/disable the event
- */
-int dpu_crtc_register_custom_event(struct dpu_kms *kms,
- struct drm_crtc *crtc_drm, u32 event, bool en);
-
-/**
- * dpu_crtc_get_intf_mode - get interface mode of the given crtc
- * @crtc: Pointert to crtc
- */
enum dpu_intf_mode dpu_crtc_get_intf_mode(struct drm_crtc *crtc);
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index bd3698bf0cf7..83de7564e2c1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -217,6 +217,10 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
};
+/**
+ * dpu_encoder_get_drm_fmt - return DRM fourcc format
+ * @phys_enc: Pointer to physical encoder structure
+ */
u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc)
{
struct drm_encoder *drm_enc;
@@ -235,6 +239,11 @@ u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc)
return DRM_FORMAT_RGB888;
}
+/**
+ * dpu_encoder_needs_periph_flush - return true if physical encoder requires
+ * peripheral flush
+ * @phys_enc: Pointer to physical encoder structure
+ */
bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
{
struct drm_encoder *drm_enc;
@@ -253,6 +262,10 @@ bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], mode);
}
+/**
+ * dpu_encoder_is_widebus_enabled - return bool value if widebus is enabled
+ * @drm_enc: Pointer to previously created drm encoder structure
+ */
bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
{
const struct dpu_encoder_virt *dpu_enc;
@@ -272,6 +285,11 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
return false;
}
+/**
+ * dpu_encoder_is_dsc_enabled - indicate whether dsc is enabled
+ * for the encoder.
+ * @drm_enc: Pointer to previously created drm encoder structure
+ */
bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc)
{
const struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -279,6 +297,12 @@ bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc)
return dpu_enc->dsc ? true : false;
}
+/**
+ * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained
+ * in virtual encoder that can collect CRC values
+ * @drm_enc: Pointer to previously created drm encoder structure
+ * Returns: Number of physical encoders for given drm encoder
+ */
int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -297,6 +321,10 @@ int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc)
return num_intf;
}
+/**
+ * dpu_encoder_setup_misr - enable misr calculations
+ * @drm_enc: Pointer to previously created drm encoder structure
+ */
void dpu_encoder_setup_misr(const struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -315,6 +343,13 @@ void dpu_encoder_setup_misr(const struct drm_encoder *drm_enc)
}
}
+/**
+ * dpu_encoder_get_crc - get the crc value from interface blocks
+ * @drm_enc: Pointer to previously created drm encoder structure
+ * @crcs: array to fill with CRC data
+ * @pos: offset into the @crcs array
+ * Returns: 0 on success, error otherwise
+ */
int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos)
{
struct dpu_encoder_virt *dpu_enc;
@@ -385,6 +420,12 @@ static char *dpu_encoder_helper_get_intf_type(enum dpu_intf_mode intf_mode)
}
}
+/**
+ * dpu_encoder_helper_report_irq_timeout - utility to report error that irq has
+ * timed out, including reporting frame error event to crtc and debug dump
+ * @phys_enc: Pointer to physical encoder structure
+ * @intr_idx: Failing interrupt index
+ */
void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc,
enum dpu_intr_idx intr_idx)
{
@@ -402,6 +443,15 @@ void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc,
static int dpu_encoder_helper_wait_event_timeout(int32_t drm_id,
u32 irq_idx, struct dpu_encoder_wait_info *info);
+/**
+ * dpu_encoder_helper_wait_for_irq - utility to wait on an irq.
+ * note: will call dpu_encoder_helper_wait_for_irq on timeout
+ * @phys_enc: Pointer to physical encoder structure
+ * @irq_idx: IRQ index
+ * @func: IRQ callback to be called in case of timeout
+ * @wait_info: wait info struct
+ * @return: 0 or -ERROR
+ */
int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
unsigned int irq_idx,
void (*func)(void *arg),
@@ -473,6 +523,10 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
return ret;
}
+/**
+ * dpu_encoder_get_vsync_count - get vsync count for the encoder.
+ * @drm_enc: Pointer to previously created drm encoder structure
+ */
int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -480,6 +534,10 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc)
return phys ? atomic_read(&phys->vsync_cnt) : 0;
}
+/**
+ * dpu_encoder_get_linecount - get interface line count for the encoder.
+ * @drm_enc: Pointer to previously created drm encoder structure
+ */
int dpu_encoder_get_linecount(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -495,6 +553,13 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc)
return linecount;
}
+/**
+ * dpu_encoder_helper_split_config - split display configuration helper function
+ * This helper function may be used by physical encoders to configure
+ * the split display related registers.
+ * @phys_enc: Pointer to physical encoder structure
+ * @interface: enum dpu_intf setting
+ */
void dpu_encoder_helper_split_config(
struct dpu_encoder_phys *phys_enc,
enum dpu_intf interface)
@@ -544,6 +609,10 @@ void dpu_encoder_helper_split_config(
}
}
+/**
+ * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
+ * @drm_enc: Pointer to previously created drm encoder structure
+ */
bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -560,6 +629,12 @@ bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
return (num_dsc > 0) && (num_dsc > intf_count);
}
+/**
+ * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
+ * This helper function is used by physical encoder to get DSC config
+ * used for this encoder.
+ * @drm_enc: Pointer to encoder structure
+ */
struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
{
struct msm_drm_private *priv = drm_enc->dev->dev_private;
@@ -1089,6 +1164,11 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc,
return 0;
}
+/**
+ * dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
+ * @drm_enc: Pointer to previously created drm encoder structure
+ * @job: Pointer to the current drm writeback job
+ */
void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
struct drm_writeback_job *job)
{
@@ -1106,6 +1186,11 @@ void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
}
}
+/**
+ * dpu_encoder_cleanup_wb_job - cleanup writeback job for the encoder.
+ * @drm_enc: Pointer to previously created drm encoder structure
+ * @job: Pointer to the current drm writeback job
+ */
void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc,
struct drm_writeback_job *job)
{
@@ -1248,6 +1333,10 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
}
}
+/**
+ * dpu_encoder_virt_runtime_resume - pm runtime resume the encoder configs
+ * @drm_enc: encoder pointer
+ */
void dpu_encoder_virt_runtime_resume(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -1389,6 +1478,12 @@ static struct dpu_hw_intf *dpu_encoder_get_intf(const struct dpu_mdss_cfg *catal
return NULL;
}
+/**
+ * dpu_encoder_vblank_callback - Notify virtual encoder of vblank IRQ reception
+ * @drm_enc: Pointer to drm encoder structure
+ * @phy_enc: Pointer to physical encoder
+ * Note: This is called from IRQ handler context.
+ */
void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc,
struct dpu_encoder_phys *phy_enc)
{
@@ -1411,6 +1506,12 @@ void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc,
DPU_ATRACE_END("encoder_vblank_callback");
}
+/**
+ * dpu_encoder_underrun_callback - Notify virtual encoder of underrun IRQ reception
+ * @drm_enc: Pointer to drm encoder structure
+ * @phy_enc: Pointer to physical encoder
+ * Note: This is called from IRQ handler context.
+ */
void dpu_encoder_underrun_callback(struct drm_encoder *drm_enc,
struct dpu_encoder_phys *phy_enc)
{
@@ -1429,6 +1530,11 @@ void dpu_encoder_underrun_callback(struct drm_encoder *drm_enc,
DPU_ATRACE_END("encoder_underrun_callback");
}
+/**
+ * dpu_encoder_assign_crtc - Link the encoder to the crtc it's assigned to
+ * @drm_enc: encoder pointer
+ * @crtc: crtc pointer
+ */
void dpu_encoder_assign_crtc(struct drm_encoder *drm_enc, struct drm_crtc *crtc)
{
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
@@ -1441,6 +1547,13 @@ void dpu_encoder_assign_crtc(struct drm_encoder *drm_enc, struct drm_crtc *crtc)
spin_unlock_irqrestore(&dpu_enc->enc_spinlock, lock_flags);
}
+/**
+ * dpu_encoder_toggle_vblank_for_crtc - Toggles vblank interrupts on or off if
+ * the encoder is assigned to the given crtc
+ * @drm_enc: encoder pointer
+ * @crtc: crtc pointer
+ * @enable: true if vblank should be enabled
+ */
void dpu_encoder_toggle_vblank_for_crtc(struct drm_encoder *drm_enc,
struct drm_crtc *crtc, bool enable)
{
@@ -1465,6 +1578,13 @@ void dpu_encoder_toggle_vblank_for_crtc(struct drm_encoder *drm_enc,
}
}
+/**
+ * dpu_encoder_frame_done_callback - Notify virtual encoder that this phys
+ * encoder completes last request frame
+ * @drm_enc: Pointer to drm encoder structure
+ * @ready_phys: Pointer to physical encoder
+ * @event: Event to process
+ */
void dpu_encoder_frame_done_callback(
struct drm_encoder *drm_enc,
struct dpu_encoder_phys *ready_phys, u32 event)
@@ -1587,6 +1707,12 @@ static void _dpu_encoder_trigger_start(struct dpu_encoder_phys *phys)
phys->ops.trigger_start(phys);
}
+/**
+ * dpu_encoder_helper_trigger_start - control start helper function
+ * This helper function may be optionally specified by physical
+ * encoders if they require ctl_start triggering.
+ * @phys_enc: Pointer to physical encoder structure
+ */
void dpu_encoder_helper_trigger_start(struct dpu_encoder_phys *phys_enc)
{
struct dpu_hw_ctl *ctl;
@@ -1708,6 +1834,11 @@ static void _dpu_encoder_kickoff_phys(struct dpu_encoder_virt *dpu_enc)
spin_unlock_irqrestore(&dpu_enc->enc_spinlock, lock_flags);
}
+/**
+ * dpu_encoder_trigger_kickoff_pending - Clear the flush bits from previous
+ * kickoff and trigger the ctl prepare progress for command mode display.
+ * @drm_enc: encoder pointer
+ */
void dpu_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -1784,6 +1915,11 @@ static u32 _dpu_encoder_calculate_linetime(struct dpu_encoder_virt *dpu_enc,
return line_time;
}
+/**
+ * dpu_encoder_vsync_time - get the time of the next vsync
+ * @drm_enc: encoder pointer
+ * @wakeup_time: pointer to ktime_t to write the vsync time to
+ */
int dpu_encoder_vsync_time(struct drm_encoder *drm_enc, ktime_t *wakeup_time)
{
struct drm_display_mode *mode;
@@ -1930,6 +2066,13 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc,
dsc, dsc_common_mode, initial_lines);
}
+/**
+ * dpu_encoder_prepare_for_kickoff - schedule double buffer flip of the ctl
+ * path (i.e. ctl flush and start) at next appropriate time.
+ * Immediately: if no previous commit is outstanding.
+ * Delayed: Block until next trigger can be issued.
+ * @drm_enc: encoder pointer
+ */
void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -1966,6 +2109,10 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
dpu_encoder_prep_dsc(dpu_enc, dpu_enc->dsc);
}
+/**
+ * dpu_encoder_is_valid_for_commit - check if encode has valid parameters for commit.
+ * @drm_enc: Pointer to drm encoder structure
+ */
bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -1987,6 +2134,11 @@ bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc)
return true;
}
+/**
+ * dpu_encoder_kickoff - trigger a double buffer flip of the ctl path
+ * (i.e. ctl flush and start) immediately.
+ * @drm_enc: encoder pointer
+ */
void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -2085,6 +2237,10 @@ static void dpu_encoder_unprep_dsc(struct dpu_encoder_virt *dpu_enc)
}
}
+/**
+ * dpu_encoder_helper_phys_cleanup - helper to cleanup dpu pipeline
+ * @phys_enc: Pointer to physical encoder structure
+ */
void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
{
struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
@@ -2168,6 +2324,12 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
ctl->ops.clear_pending_flush(ctl);
}
+/**
+ * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
+ * @phys_enc: Pointer to physical encoder
+ * @dpu_fmt: Pinter to the format description
+ * @output_type: HDMI/WB
+ */
void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
const struct msm_format *dpu_fmt,
u32 output_type)
@@ -2472,6 +2634,13 @@ static const struct drm_encoder_funcs dpu_encoder_funcs = {
.debugfs_init = dpu_encoder_debugfs_init,
};
+/**
+ * dpu_encoder_init - initialize virtual encoder object
+ * @dev: Pointer to drm device structure
+ * @drm_enc_mode: corresponding DRM_MODE_ENCODER_* constant
+ * @disp_info: Pointer to display information structure
+ * Returns: Pointer to newly created drm encoder
+ */
struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
int drm_enc_mode,
struct msm_display_info *disp_info)
@@ -2593,6 +2762,10 @@ int dpu_encoder_wait_for_tx_complete(struct drm_encoder *drm_enc)
return ret;
}
+/**
+ * dpu_encoder_get_intf_mode - get interface mode of the given encoder
+ * @encoder: Pointer to drm encoder object
+ */
enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder)
{
struct dpu_encoder_virt *dpu_enc = NULL;
@@ -2612,6 +2785,12 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder)
return INTF_MODE_NONE;
}
+/**
+ * dpu_encoder_helper_get_dsc - get DSC blocks mask for the DPU encoder
+ * This helper function is used by physical encoder to get DSC blocks mask
+ * used for this encoder.
+ * @phys_enc: Pointer to physical encoder structure
+ */
unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc)
{
struct drm_encoder *encoder = phys_enc->parent;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index f7465a1774aa..92b5ee390788 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -19,6 +19,8 @@
#define IDLE_TIMEOUT (66 - 16/2)
+#define MAX_H_TILES_PER_DISPLAY 2
+
/**
* struct msm_display_info - defines display properties
* @intf_type: INTF_ type
@@ -36,159 +38,54 @@ struct msm_display_info {
enum dpu_vsync_source vsync_source;
};
-/**
- * dpu_encoder_assign_crtc - Link the encoder to the crtc it's assigned to
- * @encoder: encoder pointer
- * @crtc: crtc pointer
- */
void dpu_encoder_assign_crtc(struct drm_encoder *encoder,
struct drm_crtc *crtc);
-/**
- * dpu_encoder_toggle_vblank_for_crtc - Toggles vblank interrupts on or off if
- * the encoder is assigned to the given crtc
- * @encoder: encoder pointer
- * @crtc: crtc pointer
- * @enable: true if vblank should be enabled
- */
void dpu_encoder_toggle_vblank_for_crtc(struct drm_encoder *encoder,
struct drm_crtc *crtc, bool enable);
-/**
- * dpu_encoder_prepare_for_kickoff - schedule double buffer flip of the ctl
- * path (i.e. ctl flush and start) at next appropriate time.
- * Immediately: if no previous commit is outstanding.
- * Delayed: Block until next trigger can be issued.
- * @encoder: encoder pointer
- */
void dpu_encoder_prepare_for_kickoff(struct drm_encoder *encoder);
-/**
- * dpu_encoder_trigger_kickoff_pending - Clear the flush bits from previous
- * kickoff and trigger the ctl prepare progress for command mode display.
- * @encoder: encoder pointer
- */
void dpu_encoder_trigger_kickoff_pending(struct drm_encoder *encoder);
-/**
- * dpu_encoder_kickoff - trigger a double buffer flip of the ctl path
- * (i.e. ctl flush and start) immediately.
- * @encoder: encoder pointer
- */
void dpu_encoder_kickoff(struct drm_encoder *encoder);
-/**
- * dpu_encoder_wakeup_time - get the time of the next vsync
- */
int dpu_encoder_vsync_time(struct drm_encoder *drm_enc, ktime_t *wakeup_time);
int dpu_encoder_wait_for_commit_done(struct drm_encoder *drm_encoder);
int dpu_encoder_wait_for_tx_complete(struct drm_encoder *drm_encoder);
-/*
- * dpu_encoder_get_intf_mode - get interface mode of the given encoder
- * @encoder: Pointer to drm encoder object
- */
enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder);
-/**
- * dpu_encoder_virt_runtime_resume - pm runtime resume the encoder configs
- * @encoder: encoder pointer
- */
void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder);
-/**
- * dpu_encoder_init - initialize virtual encoder object
- * @dev: Pointer to drm device structure
- * @drm_enc_mode: corresponding DRM_MODE_ENCODER_* constant
- * @disp_info: Pointer to display information structure
- * Returns: Pointer to newly created drm encoder
- */
struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
int drm_enc_mode,
struct msm_display_info *disp_info);
-/**
- * dpu_encoder_set_idle_timeout - set the idle timeout for video
- * and command mode encoders.
- * @drm_enc: Pointer to previously created drm encoder structure
- * @idle_timeout: idle timeout duration in milliseconds
- */
-void dpu_encoder_set_idle_timeout(struct drm_encoder *drm_enc,
- u32 idle_timeout);
-/**
- * dpu_encoder_get_linecount - get interface line count for the encoder.
- * @drm_enc: Pointer to previously created drm encoder structure
- */
int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
-/**
- * dpu_encoder_get_vsync_count - get vsync count for the encoder.
- * @drm_enc: Pointer to previously created drm encoder structure
- */
int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
-/**
- * dpu_encoder_is_widebus_enabled - return bool value if widebus is enabled
- * @drm_enc: Pointer to previously created drm encoder structure
- */
bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
-/**
- * dpu_encoder_is_dsc_enabled - indicate whether dsc is enabled
- * for the encoder.
- * @drm_enc: Pointer to previously created drm encoder structure
- */
bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc);
-/**
- * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained
- * in virtual encoder that can collect CRC values
- * @drm_enc: Pointer to previously created drm encoder structure
- * Returns: Number of physical encoders for given drm encoder
- */
int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc);
-/**
- * dpu_encoder_setup_misr - enable misr calculations
- * @drm_enc: Pointer to previously created drm encoder structure
- */
void dpu_encoder_setup_misr(const struct drm_encoder *drm_encoder);
-/**
- * dpu_encoder_get_crc - get the crc value from interface blocks
- * @drm_enc: Pointer to previously created drm encoder structure
- * Returns: 0 on success, error otherwise
- */
int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos);
-/**
- * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
- * @drm_enc: Pointer to previously created drm encoder structure
- */
bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
-/**
- * dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
- * @drm_enc: Pointer to previously created drm encoder structure
- * @job: Pointer to the current drm writeback job
- */
void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
struct drm_writeback_job *job);
-/**
- * dpu_encoder_cleanup_wb_job - cleanup writeback job for the encoder.
- * @drm_enc: Pointer to previously created drm encoder structure
- * @job: Pointer to the current drm writeback job
- */
void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc,
struct drm_writeback_job *job);
-/**
- * dpu_encoder_is_valid_for_commit - check if encode has valid parameters for commit.
- * @drm_enc: Pointer to drm encoder structure
- */
bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc);
#endif /* __DPU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index e77ebe3a68da..63f09857025c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -279,37 +279,15 @@ struct dpu_encoder_wait_info {
s64 timeout_ms;
};
-/**
- * dpu_encoder_phys_vid_init - Construct a new video mode physical encoder
- * @p: Pointer to init params structure
- * Return: Error code or newly allocated encoder
- */
struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
-/**
- * dpu_encoder_phys_cmd_init - Construct a new command mode physical encoder
- * @dev: Corresponding device for devres management
- * @p: Pointer to init params structure
- * Return: Error code or newly allocated encoder
- */
struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
-/**
- * dpu_encoder_phys_wb_init - initialize writeback encoder
- * @dev: Corresponding device for devres management
- * @init: Pointer to init info structure with initialization params
- */
struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
-/**
- * dpu_encoder_helper_trigger_start - control start helper function
- * This helper function may be optionally specified by physical
- * encoders if they require ctl_start triggering.
- * @phys_enc: Pointer to physical encoder structure
- */
void dpu_encoder_helper_trigger_start(struct dpu_encoder_phys *phys_enc);
static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
@@ -331,106 +309,38 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
return BLEND_3D_NONE;
}
-/**
- * dpu_encoder_helper_get_dsc - get DSC blocks mask for the DPU encoder
- * This helper function is used by physical encoder to get DSC blocks mask
- * used for this encoder.
- * @phys_enc: Pointer to physical encoder structure
- */
unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
-/**
- * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
- * This helper function is used by physical encoder to get DSC config
- * used for this encoder.
- * @drm_enc: Pointer to encoder structure
- */
struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc);
-/**
- * dpu_encoder_get_drm_fmt - return DRM fourcc format
- * @phys_enc: Pointer to physical encoder structure
- */
u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc);
-/**
- * dpu_encoder_needs_periph_flush - return true if physical encoder requires
- * peripheral flush
- * @phys_enc: Pointer to physical encoder structure
- */
bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc);
-/**
- * dpu_encoder_helper_split_config - split display configuration helper function
- * This helper function may be used by physical encoders to configure
- * the split display related registers.
- * @phys_enc: Pointer to physical encoder structure
- * @interface: enum dpu_intf setting
- */
void dpu_encoder_helper_split_config(
struct dpu_encoder_phys *phys_enc,
enum dpu_intf interface);
-/**
- * dpu_encoder_helper_report_irq_timeout - utility to report error that irq has
- * timed out, including reporting frame error event to crtc and debug dump
- * @phys_enc: Pointer to physical encoder structure
- * @intr_idx: Failing interrupt index
- */
void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc,
enum dpu_intr_idx intr_idx);
-/**
- * dpu_encoder_helper_wait_for_irq - utility to wait on an irq.
- * note: will call dpu_encoder_helper_wait_for_irq on timeout
- * @phys_enc: Pointer to physical encoder structure
- * @irq: IRQ index
- * @func: IRQ callback to be called in case of timeout
- * @wait_info: wait info struct
- * @Return: 0 or -ERROR
- */
int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
unsigned int irq,
void (*func)(void *arg),
struct dpu_encoder_wait_info *wait_info);
-/**
- * dpu_encoder_helper_phys_cleanup - helper to cleanup dpu pipeline
- * @phys_enc: Pointer to physical encoder structure
- */
void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc);
-/**
- * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
- * @phys_enc: Pointer to physical encoder
- * @output_type: HDMI/WB
- */
void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
const struct msm_format *dpu_fmt,
u32 output_type);
-/**
- * dpu_encoder_vblank_callback - Notify virtual encoder of vblank IRQ reception
- * @drm_enc: Pointer to drm encoder structure
- * @phys_enc: Pointer to physical encoder
- * Note: This is called from IRQ handler context.
- */
void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc,
struct dpu_encoder_phys *phy_enc);
-/** dpu_encoder_underrun_callback - Notify virtual encoder of underrun IRQ reception
- * @drm_enc: Pointer to drm encoder structure
- * @phys_enc: Pointer to physical encoder
- * Note: This is called from IRQ handler context.
- */
void dpu_encoder_underrun_callback(struct drm_encoder *drm_enc,
struct dpu_encoder_phys *phy_enc);
-/** dpu_encoder_frame_done_callback -- Notify virtual encoder that this phys encoder completes last request frame
- * @drm_enc: Pointer to drm encoder structure
- * @phys_enc: Pointer to physical encoder
- * @event: Event to process
- */
void dpu_encoder_frame_done_callback(
struct drm_encoder *drm_enc,
struct dpu_encoder_phys *ready_phys, u32 event);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index 6fc31d47cd1d..e9bbccc44dad 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -720,6 +720,12 @@ static void dpu_encoder_phys_cmd_init_ops(
ops->get_line_count = dpu_encoder_phys_cmd_get_line_count;
}
+/**
+ * dpu_encoder_phys_cmd_init - Construct a new command mode physical encoder
+ * @dev: Corresponding device for devres management
+ * @p: Pointer to init params structure
+ * Return: Error code or newly allocated encoder
+ */
struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p)
{
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 d8a2edebfe8c..abd6600046cb 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
@@ -746,6 +746,12 @@ static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops)
ops->get_frame_count = dpu_encoder_phys_vid_get_frame_count;
}
+/**
+ * dpu_encoder_phys_vid_init - Construct a new video mode physical encoder
+ * @dev: Corresponding device for devres management
+ * @p: Pointer to init params structure
+ * Return: Error code or newly allocated encoder
+ */
struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p)
{
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 07035ab77b79..4c006ec74575 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -166,10 +166,10 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
/**
* dpu_encoder_phys_wb_setup_fb - setup output framebuffer
* @phys_enc: Pointer to physical encoder
- * @fb: Pointer to output framebuffer
+ * @format: Format of the framebuffer
*/
static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
- struct drm_framebuffer *fb)
+ const struct msm_format *format)
{
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
struct dpu_hw_wb *hw_wb;
@@ -193,12 +193,12 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
hw_wb->ops.setup_roi(hw_wb, wb_cfg);
if (hw_wb->ops.setup_outformat)
- hw_wb->ops.setup_outformat(hw_wb, wb_cfg);
+ hw_wb->ops.setup_outformat(hw_wb, wb_cfg, format);
if (hw_wb->ops.setup_cdp) {
const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf;
- hw_wb->ops.setup_cdp(hw_wb, wb_cfg->dest.format,
+ hw_wb->ops.setup_cdp(hw_wb, format,
perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable);
}
@@ -321,15 +321,10 @@ static void dpu_encoder_phys_wb_setup(
{
struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
struct drm_display_mode mode = phys_enc->cached_mode;
- struct drm_framebuffer *fb = NULL;
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
- struct drm_writeback_job *wb_job;
const struct msm_format *format;
- const struct msm_format *dpu_fmt;
- wb_job = wb_enc->wb_job;
format = msm_framebuffer_format(wb_enc->wb_job->fb);
- dpu_fmt = mdp_get_format(&phys_enc->dpu_kms->base, format->pixel_format, wb_job->fb->modifier);
DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n",
hw_wb->idx - WB_0, mode.name,
@@ -341,9 +336,9 @@ static void dpu_encoder_phys_wb_setup(
dpu_encoder_phys_wb_set_qos(phys_enc);
- dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
+ dpu_encoder_phys_wb_setup_fb(phys_enc, format);
- dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
+ dpu_encoder_helper_phys_setup_cdm(phys_enc, format, CDM_CDWN_OUTPUT_WB);
dpu_encoder_phys_wb_setup_ctl(phys_enc);
}
@@ -587,26 +582,20 @@ static void dpu_encoder_phys_wb_prepare_wb_job(struct dpu_encoder_phys *phys_enc
format = msm_framebuffer_format(job->fb);
- wb_cfg->dest.format = mdp_get_format(&phys_enc->dpu_kms->base,
- format->pixel_format, job->fb->modifier);
- if (!wb_cfg->dest.format) {
- /* this error should be detected during atomic_check */
- DPU_ERROR("failed to get format %p4cc\n", &format->pixel_format);
- return;
- }
-
- ret = dpu_format_populate_layout(aspace, job->fb, &wb_cfg->dest);
+ ret = dpu_format_populate_plane_sizes(job->fb, &wb_cfg->dest);
if (ret) {
- DPU_DEBUG("failed to populate layout %d\n", ret);
+ DPU_DEBUG("failed to populate plane sizes%d\n", ret);
return;
}
+ dpu_format_populate_addrs(aspace, job->fb, &wb_cfg->dest);
+
wb_cfg->dest.width = job->fb->width;
wb_cfg->dest.height = job->fb->height;
- wb_cfg->dest.num_planes = wb_cfg->dest.format->num_planes;
+ wb_cfg->dest.num_planes = format->num_planes;
- if ((wb_cfg->dest.format->fetch_type == MDP_PLANE_PLANAR) &&
- (wb_cfg->dest.format->element[0] == C1_B_Cb))
+ if ((format->fetch_type == MDP_PLANE_PLANAR) &&
+ (format->element[0] == C1_B_Cb))
swap(wb_cfg->dest.plane_addr[1], wb_cfg->dest.plane_addr[2]);
DPU_DEBUG("[fb_offset:%8.8x,%8.8x,%8.8x,%8.8x]\n",
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index 6b1e9a617da3..59c9427da7dd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -13,9 +13,6 @@
#define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096
-#define DPU_MAX_IMG_WIDTH 0x3FFF
-#define DPU_MAX_IMG_HEIGHT 0x3FFF
-
/*
* struct dpu_media_color_map - maps drm format to media format
* @format: DRM base pixel format
@@ -93,10 +90,9 @@ static int _dpu_format_get_media_color_ubwc(const struct msm_format *fmt)
return color_fmt;
}
-static int _dpu_format_get_plane_sizes_ubwc(
+static int _dpu_format_populate_plane_sizes_ubwc(
const struct msm_format *fmt,
- const uint32_t width,
- const uint32_t height,
+ struct drm_framebuffer *fb,
struct dpu_hw_fmt_layout *layout)
{
int i;
@@ -104,9 +100,8 @@ static int _dpu_format_get_plane_sizes_ubwc(
bool meta = MSM_FORMAT_IS_UBWC(fmt);
memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
- layout->format = fmt;
- layout->width = width;
- layout->height = height;
+ layout->width = fb->width;
+ layout->height = fb->height;
layout->num_planes = fmt->num_planes;
color = _dpu_format_get_media_color_ubwc(fmt);
@@ -116,19 +111,19 @@ static int _dpu_format_get_plane_sizes_ubwc(
return -EINVAL;
}
- if (MSM_FORMAT_IS_YUV(layout->format)) {
+ if (MSM_FORMAT_IS_YUV(fmt)) {
uint32_t y_sclines, uv_sclines;
uint32_t y_meta_scanlines = 0;
uint32_t uv_meta_scanlines = 0;
layout->num_planes = 2;
- layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
- y_sclines = VENUS_Y_SCANLINES(color, height);
+ layout->plane_pitch[0] = VENUS_Y_STRIDE(color, fb->width);
+ y_sclines = VENUS_Y_SCANLINES(color, fb->height);
layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
- layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
- uv_sclines = VENUS_UV_SCANLINES(color, height);
+ layout->plane_pitch[1] = VENUS_UV_STRIDE(color, fb->width);
+ uv_sclines = VENUS_UV_SCANLINES(color, fb->height);
layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
@@ -136,13 +131,13 @@ static int _dpu_format_get_plane_sizes_ubwc(
goto done;
layout->num_planes += 2;
- layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
- y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
+ layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, fb->width);
+ y_meta_scanlines = VENUS_Y_META_SCANLINES(color, fb->height);
layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
- layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
- uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
+ layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, fb->width);
+ uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, fb->height);
layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
@@ -151,16 +146,16 @@ static int _dpu_format_get_plane_sizes_ubwc(
layout->num_planes = 1;
- layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
- rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
+ layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, fb->width);
+ rgb_scanlines = VENUS_RGB_SCANLINES(color, fb->height);
layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
if (!meta)
goto done;
layout->num_planes += 2;
- layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
- rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
+ layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, fb->width);
+ rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, fb->height);
layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
}
@@ -172,26 +167,23 @@ done:
return 0;
}
-static int _dpu_format_get_plane_sizes_linear(
+static int _dpu_format_populate_plane_sizes_linear(
const struct msm_format *fmt,
- const uint32_t width,
- const uint32_t height,
- struct dpu_hw_fmt_layout *layout,
- const uint32_t *pitches)
+ struct drm_framebuffer *fb,
+ struct dpu_hw_fmt_layout *layout)
{
int i;
memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
- layout->format = fmt;
- layout->width = width;
- layout->height = height;
+ layout->width = fb->width;
+ layout->height = fb->height;
layout->num_planes = fmt->num_planes;
/* Due to memset above, only need to set planes of interest */
if (fmt->fetch_type == MDP_PLANE_INTERLEAVED) {
layout->num_planes = 1;
- layout->plane_size[0] = width * height * layout->format->bpp;
- layout->plane_pitch[0] = width * layout->format->bpp;
+ layout->plane_size[0] = fb->width * fb->height * fmt->bpp;
+ layout->plane_pitch[0] = fb->width * fmt->bpp;
} else {
uint32_t v_subsample, h_subsample;
uint32_t chroma_samp;
@@ -201,7 +193,7 @@ static int _dpu_format_get_plane_sizes_linear(
_dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
&h_subsample);
- if (width % h_subsample || height % v_subsample) {
+ if (fb->width % h_subsample || fb->height % v_subsample) {
DRM_ERROR("mismatch in subsample vs dimensions\n");
return -EINVAL;
}
@@ -209,11 +201,11 @@ static int _dpu_format_get_plane_sizes_linear(
if ((fmt->pixel_format == DRM_FORMAT_NV12) &&
(MSM_FORMAT_IS_DX(fmt)))
bpp = 2;
- layout->plane_pitch[0] = width * bpp;
+ layout->plane_pitch[0] = fb->width * bpp;
layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
- layout->plane_size[0] = layout->plane_pitch[0] * height;
+ layout->plane_size[0] = layout->plane_pitch[0] * fb->height;
layout->plane_size[1] = layout->plane_pitch[1] *
- (height / v_subsample);
+ (fb->height / v_subsample);
if (fmt->fetch_type == MDP_PLANE_PSEUDO_PLANAR) {
layout->num_planes = 2;
@@ -234,8 +226,13 @@ static int _dpu_format_get_plane_sizes_linear(
* all the components based on ubwc specifications.
*/
for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) {
- if (pitches && layout->plane_pitch[i] < pitches[i])
- layout->plane_pitch[i] = pitches[i];
+ if (layout->plane_pitch[i] <= fb->pitches[i]) {
+ layout->plane_pitch[i] = fb->pitches[i];
+ } else {
+ DRM_DEBUG("plane %u expected pitch %u, fb %u\n",
+ i, layout->plane_pitch[i], fb->pitches[i]);
+ return -EINVAL;
+ }
}
for (i = 0; i < DPU_MAX_PLANES; i++)
@@ -244,53 +241,54 @@ static int _dpu_format_get_plane_sizes_linear(
return 0;
}
-static int dpu_format_get_plane_sizes(
- const struct msm_format *fmt,
- const uint32_t w,
- const uint32_t h,
- struct dpu_hw_fmt_layout *layout,
- const uint32_t *pitches)
+/**
+ * dpu_format_populate_plane_sizes - populate non-address part of the layout based on
+ * fb, and format found in the fb
+ * @fb: framebuffer pointer
+ * @layout: format layout structure to populate
+ *
+ * Return: error code on failure or 0 if new addresses were populated
+ */
+int dpu_format_populate_plane_sizes(
+ struct drm_framebuffer *fb,
+ struct dpu_hw_fmt_layout *layout)
{
- if (!layout || !fmt) {
+ const struct msm_format *fmt;
+
+ if (!layout || !fb) {
DRM_ERROR("invalid pointer\n");
return -EINVAL;
}
- if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
+ if (fb->width > DPU_MAX_IMG_WIDTH ||
+ fb->height > DPU_MAX_IMG_HEIGHT) {
DRM_ERROR("image dimensions outside max range\n");
return -ERANGE;
}
+ fmt = msm_framebuffer_format(fb);
+
if (MSM_FORMAT_IS_UBWC(fmt) || MSM_FORMAT_IS_TILE(fmt))
- return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
+ return _dpu_format_populate_plane_sizes_ubwc(fmt, fb, layout);
- return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
+ return _dpu_format_populate_plane_sizes_linear(fmt, fb, layout);
}
-static int _dpu_format_populate_addrs_ubwc(
- struct msm_gem_address_space *aspace,
- struct drm_framebuffer *fb,
- struct dpu_hw_fmt_layout *layout)
+static void _dpu_format_populate_addrs_ubwc(struct msm_gem_address_space *aspace,
+ struct drm_framebuffer *fb,
+ struct dpu_hw_fmt_layout *layout)
{
+ const struct msm_format *fmt;
uint32_t base_addr = 0;
bool meta;
- if (!fb || !layout) {
- DRM_ERROR("invalid pointers\n");
- return -EINVAL;
- }
-
- if (aspace)
- base_addr = msm_framebuffer_iova(fb, aspace, 0);
- if (!base_addr) {
- DRM_ERROR("failed to retrieve base addr\n");
- return -EFAULT;
- }
+ base_addr = msm_framebuffer_iova(fb, aspace, 0);
- meta = MSM_FORMAT_IS_UBWC(layout->format);
+ fmt = msm_framebuffer_format(fb);
+ meta = MSM_FORMAT_IS_UBWC(fmt);
/* Per-format logic for verifying active planes */
- if (MSM_FORMAT_IS_YUV(layout->format)) {
+ if (MSM_FORMAT_IS_YUV(fmt)) {
/************************************************/
/* UBWC ** */
/* buffer ** DPU PLANE */
@@ -319,7 +317,7 @@ static int _dpu_format_populate_addrs_ubwc(
+ layout->plane_size[2] + layout->plane_size[3];
if (!meta)
- return 0;
+ return;
/* configure Y metadata plane */
layout->plane_addr[2] = base_addr;
@@ -350,119 +348,43 @@ static int _dpu_format_populate_addrs_ubwc(
layout->plane_addr[1] = 0;
if (!meta)
- return 0;
+ return;
layout->plane_addr[2] = base_addr;
layout->plane_addr[3] = 0;
}
- return 0;
}
-static int _dpu_format_populate_addrs_linear(
- struct msm_gem_address_space *aspace,
- struct drm_framebuffer *fb,
- struct dpu_hw_fmt_layout *layout)
+static void _dpu_format_populate_addrs_linear(struct msm_gem_address_space *aspace,
+ struct drm_framebuffer *fb,
+ struct dpu_hw_fmt_layout *layout)
{
unsigned int i;
- /* Can now check the pitches given vs pitches expected */
- for (i = 0; i < layout->num_planes; ++i) {
- if (layout->plane_pitch[i] > fb->pitches[i]) {
- DRM_ERROR("plane %u expected pitch %u, fb %u\n",
- i, layout->plane_pitch[i], fb->pitches[i]);
- return -EINVAL;
- }
- }
-
/* Populate addresses for simple formats here */
- for (i = 0; i < layout->num_planes; ++i) {
- if (aspace)
- layout->plane_addr[i] =
- msm_framebuffer_iova(fb, aspace, i);
- if (!layout->plane_addr[i]) {
- DRM_ERROR("failed to retrieve base addr\n");
- return -EFAULT;
- }
- }
-
- return 0;
+ for (i = 0; i < layout->num_planes; ++i)
+ layout->plane_addr[i] = msm_framebuffer_iova(fb, aspace, i);
}
-int dpu_format_populate_layout(
- struct msm_gem_address_space *aspace,
- struct drm_framebuffer *fb,
- struct dpu_hw_fmt_layout *layout)
+/**
+ * dpu_format_populate_addrs - populate buffer addresses based on
+ * mmu, fb, and format found in the fb
+ * @aspace: address space pointer
+ * @fb: framebuffer pointer
+ * @layout: format layout structure to populate
+ */
+void dpu_format_populate_addrs(struct msm_gem_address_space *aspace,
+ struct drm_framebuffer *fb,
+ struct dpu_hw_fmt_layout *layout)
{
- int ret;
-
- if (!fb || !layout) {
- DRM_ERROR("invalid arguments\n");
- return -EINVAL;
- }
+ const struct msm_format *fmt;
- if ((fb->width > DPU_MAX_IMG_WIDTH) ||
- (fb->height > DPU_MAX_IMG_HEIGHT)) {
- DRM_ERROR("image dimensions outside max range\n");
- return -ERANGE;
- }
-
- layout->format = msm_framebuffer_format(fb);
-
- /* Populate the plane sizes etc via get_format */
- ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
- layout, fb->pitches);
- if (ret)
- return ret;
+ fmt = msm_framebuffer_format(fb);
/* Populate the addresses given the fb */
- if (MSM_FORMAT_IS_UBWC(layout->format) ||
- MSM_FORMAT_IS_TILE(layout->format))
- ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
+ if (MSM_FORMAT_IS_UBWC(fmt) ||
+ MSM_FORMAT_IS_TILE(fmt))
+ _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
else
- ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
-
- return ret;
-}
-
-int dpu_format_check_modified_format(
- const struct msm_kms *kms,
- const struct msm_format *fmt,
- const struct drm_mode_fb_cmd2 *cmd,
- struct drm_gem_object **bos)
-{
- const struct drm_format_info *info;
- struct dpu_hw_fmt_layout layout;
- uint32_t bos_total_size = 0;
- int ret, i;
-
- if (!fmt || !cmd || !bos) {
- DRM_ERROR("invalid arguments\n");
- return -EINVAL;
- }
-
- info = drm_format_info(fmt->pixel_format);
- if (!info)
- return -EINVAL;
-
- ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
- &layout, cmd->pitches);
- if (ret)
- return ret;
-
- for (i = 0; i < info->num_planes; i++) {
- if (!bos[i]) {
- DRM_ERROR("invalid handle for plane %d\n", i);
- return -EINVAL;
- }
- if ((i == 0) || (bos[i] != bos[0]))
- bos_total_size += bos[i]->size;
- }
-
- if (bos_total_size < layout.total_size) {
- DRM_ERROR("buffers total size too small %u expected %u\n",
- bos_total_size, layout.total_size);
- return -EINVAL;
- }
-
- return 0;
+ _dpu_format_populate_addrs_linear(aspace, fb, layout);
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h
index 210d0ed5f0af..c6145d43aa3f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h
@@ -31,35 +31,12 @@ static inline bool dpu_find_format(u32 format, const u32 *supported_formats,
return false;
}
-/**
- * dpu_format_check_modified_format - validate format and buffers for
- * dpu non-standard, i.e. modified format
- * @kms: kms driver
- * @msm_fmt: pointer to the msm_fmt base pointer of an msm_format
- * @cmd: fb_cmd2 structure user request
- * @bos: gem buffer object list
- *
- * Return: error code on failure, 0 on success
- */
-int dpu_format_check_modified_format(
- const struct msm_kms *kms,
- const struct msm_format *msm_fmt,
- const struct drm_mode_fb_cmd2 *cmd,
- struct drm_gem_object **bos);
+void dpu_format_populate_addrs(struct msm_gem_address_space *aspace,
+ struct drm_framebuffer *fb,
+ struct dpu_hw_fmt_layout *layout);
-/**
- * dpu_format_populate_layout - populate the given format layout based on
- * mmu, fb, and format found in the fb
- * @aspace: address space pointer
- * @fb: framebuffer pointer
- * @fmtl: format layout structure to populate
- *
- * Return: error code on failure, -EAGAIN if success but the addresses
- * are the same as before or 0 if new addresses were populated
- */
-int dpu_format_populate_layout(
- struct msm_gem_address_space *aspace,
+int dpu_format_populate_plane_sizes(
struct drm_framebuffer *fb,
- struct dpu_hw_fmt_layout *fmtl);
+ struct dpu_hw_fmt_layout *layout);
#endif /*_DPU_FORMATS_H */
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 dcb4fd85e73b..2cbf41f33cc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -21,6 +21,16 @@
(VIG_BASE_MASK | \
BIT(DPU_SSPP_CSC_10BIT))
+#define VIG_MSM8953_MASK \
+ (BIT(DPU_SSPP_QOS) |\
+ BIT(DPU_SSPP_SCALER_QSEED2) |\
+ BIT(DPU_SSPP_CSC))
+
+#define VIG_MSM8996_MASK \
+ (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_CDP) |\
+ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_SCALER_QSEED2) |\
+ BIT(DPU_SSPP_CSC))
+
#define VIG_MSM8998_MASK \
(VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3_COMPATIBLE))
@@ -32,6 +42,12 @@
#define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL))
+#define DMA_MSM8953_MASK \
+ (BIT(DPU_SSPP_QOS))
+
+#define DMA_MSM8996_MASK \
+ (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_CDP))
+
#define DMA_MSM8998_MASK \
(BIT(DPU_SSPP_QOS) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
@@ -57,9 +73,19 @@
#define DMA_CURSOR_SDM845_MASK_SDMA \
(DMA_CURSOR_SDM845_MASK | BIT(DPU_SSPP_SMART_DMA_V2))
+#define DMA_CURSOR_MSM8996_MASK \
+ (DMA_MSM8996_MASK | BIT(DPU_SSPP_CURSOR))
+
#define DMA_CURSOR_MSM8998_MASK \
(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))
+#define RGB_MSM8953_MASK \
+ (BIT(DPU_SSPP_QOS))
+
+#define RGB_MSM8996_MASK \
+ (BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_CDP) |\
+ BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_SCALER_RGB))
+
#define MIXER_MSM8998_MASK \
(BIT(DPU_MIXER_SOURCESPLIT))
@@ -69,6 +95,12 @@
#define MIXER_QCM2290_MASK \
(BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA))
+#define PINGPONG_MSM8996_MASK \
+ (BIT(DPU_PINGPONG_DSC))
+
+#define PINGPONG_MSM8996_TE2_MASK \
+ (PINGPONG_MSM8996_MASK | BIT(DPU_PINGPONG_TE2))
+
#define PINGPONG_SDM845_MASK \
(BIT(DPU_PINGPONG_DITHER) | BIT(DPU_PINGPONG_DSC))
@@ -115,10 +147,6 @@
#define MAX_HORZ_DECIMATION 4
#define MAX_VERT_DECIMATION 4
-#define MAX_UPSCALE_RATIO 20
-#define MAX_DOWNSCALE_RATIO 4
-#define SSPP_UNITY_SCALE 1
-
#define STRCAT(X, Y) (X Y)
static const uint32_t plane_formats[] = {
@@ -276,8 +304,6 @@ static const u32 wb2_formats_rgb_yuv[] = {
/* SSPP common configuration */
#define _VIG_SBLK(scaler_ver) \
{ \
- .maxdwnscale = MAX_DOWNSCALE_RATIO, \
- .maxupscale = MAX_UPSCALE_RATIO, \
.scaler_blk = {.name = "scaler", \
.version = scaler_ver, \
.base = 0xa00, .len = 0xa0,}, \
@@ -285,15 +311,11 @@ static const u32 wb2_formats_rgb_yuv[] = {
.base = 0x1a00, .len = 0x100,}, \
.format_list = plane_formats_yuv, \
.num_formats = ARRAY_SIZE(plane_formats_yuv), \
- .virt_format_list = plane_formats, \
- .virt_num_formats = ARRAY_SIZE(plane_formats), \
.rotation_cfg = NULL, \
}
#define _VIG_SBLK_ROT(scaler_ver, rot_cfg) \
{ \
- .maxdwnscale = MAX_DOWNSCALE_RATIO, \
- .maxupscale = MAX_UPSCALE_RATIO, \
.scaler_blk = {.name = "scaler", \
.version = scaler_ver, \
.base = 0xa00, .len = 0xa0,}, \
@@ -301,29 +323,40 @@ static const u32 wb2_formats_rgb_yuv[] = {
.base = 0x1a00, .len = 0x100,}, \
.format_list = plane_formats_yuv, \
.num_formats = ARRAY_SIZE(plane_formats_yuv), \
- .virt_format_list = plane_formats, \
- .virt_num_formats = ARRAY_SIZE(plane_formats), \
.rotation_cfg = rot_cfg, \
}
#define _VIG_SBLK_NOSCALE() \
{ \
- .maxdwnscale = SSPP_UNITY_SCALE, \
- .maxupscale = SSPP_UNITY_SCALE, \
.format_list = plane_formats, \
.num_formats = ARRAY_SIZE(plane_formats), \
- .virt_format_list = plane_formats, \
- .virt_num_formats = ARRAY_SIZE(plane_formats), \
+ }
+
+/* qseed2 is not supported, so disabled scaling */
+#define _VIG_SBLK_QSEED2() \
+ { \
+ .scaler_blk = {.name = "scaler", \
+ /* no version for qseed2 */ \
+ .base = 0x200, .len = 0xa0,}, \
+ .csc_blk = {.name = "csc", \
+ .base = 0x320, .len = 0x100,}, \
+ .format_list = plane_formats_yuv, \
+ .num_formats = ARRAY_SIZE(plane_formats_yuv), \
+ .rotation_cfg = NULL, \
+ }
+
+#define _RGB_SBLK() \
+ { \
+ .scaler_blk = {.name = "scaler", \
+ .base = 0x200, .len = 0x28,}, \
+ .format_list = plane_formats, \
+ .num_formats = ARRAY_SIZE(plane_formats), \
}
#define _DMA_SBLK() \
{ \
- .maxdwnscale = SSPP_UNITY_SCALE, \
- .maxupscale = SSPP_UNITY_SCALE, \
.format_list = plane_formats, \
.num_formats = ARRAY_SIZE(plane_formats), \
- .virt_format_list = plane_formats, \
- .virt_num_formats = ARRAY_SIZE(plane_formats), \
}
static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = {
@@ -332,6 +365,9 @@ static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = {
.rot_format_list = rotation_v2_formats,
};
+static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed2 =
+ _VIG_SBLK_QSEED2();
+
static const struct dpu_sspp_sub_blks dpu_vig_sblk_noscale =
_VIG_SBLK_NOSCALE();
@@ -363,6 +399,8 @@ static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_2 =
static const struct dpu_sspp_sub_blks dpu_vig_sblk_qseed3_3_3 =
_VIG_SBLK(SSPP_SCALER_VER(3, 3));
+static const struct dpu_sspp_sub_blks dpu_rgb_sblk = _RGB_SBLK();
+
static const struct dpu_sspp_sub_blks dpu_dma_sblk = _DMA_SBLK();
/*************************************************************
@@ -427,6 +465,15 @@ static const struct dpu_dspp_sub_blks sdm845_dspp_sblk = {
/*************************************************************
* PINGPONG sub blocks config
*************************************************************/
+static const struct dpu_pingpong_sub_blks msm8996_pp_sblk_te = {
+ .te2 = {.name = "te2", .base = 0x2000, .len = 0x0,
+ .version = 0x1},
+};
+
+static const struct dpu_pingpong_sub_blks msm8996_pp_sblk = {
+ /* No dither block */
+};
+
static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = {
.te2 = {.name = "te2", .base = 0x2000, .len = 0x0,
.version = 0x1},
@@ -492,6 +539,34 @@ static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = {
},
};
+static const struct dpu_vbif_cfg msm8996_vbif[] = {
+ {
+ .name = "vbif_rt", .id = VBIF_RT,
+ .base = 0, .len = 0x1040,
+ .default_ot_rd_limit = 32,
+ .default_ot_wr_limit = 16,
+ .features = BIT(DPU_VBIF_QOS_REMAP) | BIT(DPU_VBIF_QOS_OTLIM),
+ .xin_halt_timeout = 0x4000,
+ .qos_rp_remap_size = 0x20,
+ .dynamic_ot_rd_tbl = {
+ .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
+ .cfg = msm8998_ot_rdwr_cfg,
+ },
+ .dynamic_ot_wr_tbl = {
+ .count = ARRAY_SIZE(msm8998_ot_rdwr_cfg),
+ .cfg = msm8998_ot_rdwr_cfg,
+ },
+ .qos_rt_tbl = {
+ .npriority_lvl = ARRAY_SIZE(msm8998_rt_pri_lvl),
+ .priority_lvl = msm8998_rt_pri_lvl,
+ },
+ .qos_nrt_tbl = {
+ .npriority_lvl = ARRAY_SIZE(msm8998_nrt_pri_lvl),
+ .priority_lvl = msm8998_nrt_pri_lvl,
+ },
+ },
+};
+
static const struct dpu_vbif_cfg msm8998_vbif[] = {
{
.name = "vbif_rt", .id = VBIF_RT,
@@ -675,6 +750,11 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
* Hardware catalog
*************************************************************/
+#include "catalog/dpu_1_7_msm8996.h"
+#include "catalog/dpu_1_14_msm8937.h"
+#include "catalog/dpu_1_15_msm8917.h"
+#include "catalog/dpu_1_16_msm8953.h"
+
#include "catalog/dpu_3_0_msm8998.h"
#include "catalog/dpu_3_2_sdm660.h"
#include "catalog/dpu_3_3_sdm630.h"
@@ -699,6 +779,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = {
#include "catalog/dpu_8_0_sc8280xp.h"
#include "catalog/dpu_8_1_sm8450.h"
+#include "catalog/dpu_8_4_sa8775p.h"
#include "catalog/dpu_9_0_sm8550.h"
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 37e18e820a20..c701d18c3522 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -21,8 +21,8 @@
#define DPU_HW_BLK_NAME_LEN 16
-#define MAX_IMG_WIDTH 0x3fff
-#define MAX_IMG_HEIGHT 0x3fff
+#define DPU_MAX_IMG_WIDTH 0x3fff
+#define DPU_MAX_IMG_HEIGHT 0x3fff
#define CRTC_DUAL_MIXERS 2
@@ -364,21 +364,15 @@ struct dpu_caps {
/**
* struct dpu_sspp_sub_blks : SSPP sub-blocks
* common: Pointer to common configurations shared by sub blocks
- * @maxdwnscale: max downscale ratio supported(without DECIMATION)
- * @maxupscale: maxupscale ratio supported
* @max_per_pipe_bw: maximum allowable bandwidth of this pipe in kBps
* @qseed_ver: qseed version
* @scaler_blk:
* @csc_blk:
* @format_list: Pointer to list of supported formats
* @num_formats: Number of supported formats
- * @virt_format_list: Pointer to list of supported formats for virtual planes
- * @virt_num_formats: Number of supported formats for virtual planes
* @dpu_rotation_cfg: inline rotation configuration
*/
struct dpu_sspp_sub_blks {
- u32 maxdwnscale;
- u32 maxupscale;
u32 max_per_pipe_bw;
u32 qseed_ver;
struct dpu_scaler_blk scaler_blk;
@@ -386,8 +380,6 @@ struct dpu_sspp_sub_blks {
const u32 *format_list;
u32 num_formats;
- const u32 *virt_format_list;
- u32 virt_num_formats;
const struct dpu_rotation_cfg *rotation_cfg;
};
@@ -831,6 +823,10 @@ struct dpu_mdss_cfg {
const struct dpu_format_extended *vig_formats;
};
+extern const struct dpu_mdss_cfg dpu_msm8917_cfg;
+extern const struct dpu_mdss_cfg dpu_msm8937_cfg;
+extern const struct dpu_mdss_cfg dpu_msm8953_cfg;
+extern const struct dpu_mdss_cfg dpu_msm8996_cfg;
extern const struct dpu_mdss_cfg dpu_msm8998_cfg;
extern const struct dpu_mdss_cfg dpu_sdm630_cfg;
extern const struct dpu_mdss_cfg dpu_sdm660_cfg;
@@ -850,6 +846,7 @@ extern const struct dpu_mdss_cfg dpu_sm8350_cfg;
extern const struct dpu_mdss_cfg dpu_sc7280_cfg;
extern const struct dpu_mdss_cfg dpu_sc8280xp_cfg;
extern const struct dpu_mdss_cfg dpu_sm8450_cfg;
+extern const struct dpu_mdss_cfg dpu_sa8775p_cfg;
extern const struct dpu_mdss_cfg dpu_sm8550_cfg;
extern const struct dpu_mdss_cfg dpu_sm8650_cfg;
extern const struct dpu_mdss_cfg dpu_x1e80100_cfg;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
index 55d2768a6d4d..ae1534c49ae0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
@@ -222,6 +222,14 @@ static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, const enum dpu_
DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
}
+/**
+ * dpu_hw_cdm_init - initializes the cdm hw driver object.
+ * should be called once before accessing every cdm.
+ * @dev: DRM device handle
+ * @cfg: CDM catalog entry for which driver object is required
+ * @addr : mapped register io address of MDSS
+ * @mdss_rev: mdss hw core revision
+ */
struct dpu_hw_cdm *dpu_hw_cdm_init(struct drm_device *dev,
const struct dpu_cdm_cfg *cfg, void __iomem *addr,
const struct dpu_mdss_version *mdss_rev)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
index ec71c9886d75..6bb3476a05f8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
@@ -122,14 +122,6 @@ struct dpu_hw_cdm {
struct dpu_hw_cdm_ops ops;
};
-/**
- * dpu_hw_cdm_init - initializes the cdm hw driver object.
- * should be called once before accessing every cdm.
- * @dev: DRM device handle
- * @cdm: CDM catalog entry for which driver object is required
- * @addr : mapped register io address of MDSS
- * @mdss_rev: mdss hw core revision
- */
struct dpu_hw_cdm *dpu_hw_cdm_init(struct drm_device *dev,
const struct dpu_cdm_cfg *cdm, void __iomem *addr,
const struct dpu_mdss_version *mdss_rev);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 2e50049f2f85..4893f10d6a58 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -736,6 +736,15 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
};
+/**
+ * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object.
+ * Should be called before accessing any ctl_path register.
+ * @dev: Corresponding device for devres management
+ * @cfg: ctl_path catalog entry for which driver object is required
+ * @addr: mapped register io address of MDP
+ * @mixer_count: Number of mixers in @mixer
+ * @mixer: Pointer to an array of Layer Mixers defined in the catalog
+ */
struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
const struct dpu_ctl_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 4401fdc0f3e4..85c6c835cc87 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -294,15 +294,6 @@ static inline struct dpu_hw_ctl *to_dpu_hw_ctl(struct dpu_hw_blk *hw)
return container_of(hw, struct dpu_hw_ctl, base);
}
-/**
- * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object.
- * Should be called before accessing any ctl_path register.
- * @dev: Corresponding device for devres management
- * @cfg: ctl_path catalog entry for which driver object is required
- * @addr: mapped register io address of MDP
- * @mixer_count: Number of mixers in @mixer
- * @mixer: Pointer to an array of Layer Mixers defined in the catalog
- */
struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
const struct dpu_ctl_cfg *cfg,
void __iomem *addr,
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 5e9aad1b2aa2..657200401f57 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -190,6 +190,13 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk;
};
+/**
+ * dpu_hw_dsc_init() - Initializes the DSC hw driver object.
+ * @dev: Corresponding device for devres management
+ * @cfg: DSC catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * Return: Error code or allocated dpu_hw_dsc context
+ */
struct dpu_hw_dsc *dpu_hw_dsc_init(struct drm_device *dev,
const struct dpu_dsc_cfg *cfg,
void __iomem *addr)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
index 989c88d2449b..fc171bdeca48 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -62,24 +62,10 @@ struct dpu_hw_dsc {
struct dpu_hw_dsc_ops ops;
};
-/**
- * dpu_hw_dsc_init() - Initializes the DSC hw driver object.
- * @dev: Corresponding device for devres management
- * @cfg: DSC catalog entry for which driver object is required
- * @addr: Mapped register io address of MDP
- * Return: Error code or allocated dpu_hw_dsc context
- */
struct dpu_hw_dsc *dpu_hw_dsc_init(struct drm_device *dev,
const struct dpu_dsc_cfg *cfg,
void __iomem *addr);
-/**
- * dpu_hw_dsc_init_1_2() - initializes the v1.2 DSC hw driver object
- * @dev: Corresponding device for devres management
- * @cfg: DSC catalog entry for which driver object is required
- * @addr: Mapped register io address of MDP
- * Returns: Error code or allocated dpu_hw_dsc context
- */
struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(struct drm_device *dev,
const struct dpu_dsc_cfg *cfg,
void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c
index ba193b0376fe..b9c433567262 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c
@@ -369,6 +369,13 @@ static void _setup_dcs_ops_1_2(struct dpu_hw_dsc_ops *ops,
ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk_1_2;
}
+/**
+ * dpu_hw_dsc_init_1_2() - initializes the v1.2 DSC hw driver object
+ * @dev: Corresponding device for devres management
+ * @cfg: DSC catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * Returns: Error code or allocated dpu_hw_dsc context
+ */
struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(struct drm_device *dev,
const struct dpu_dsc_cfg *cfg,
void __iomem *addr)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
index b1da88e2935f..829ca272873e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
@@ -70,6 +70,14 @@ static void _setup_dspp_ops(struct dpu_hw_dspp *c,
c->ops.setup_pcc = dpu_setup_dspp_pcc;
}
+/**
+ * dpu_hw_dspp_init() - Initializes the DSPP hw driver object.
+ * should be called once before accessing every DSPP.
+ * @dev: Corresponding device for devres management
+ * @cfg: DSPP catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * Return: pointer to structure or ERR_PTR
+ */
struct dpu_hw_dspp *dpu_hw_dspp_init(struct drm_device *dev,
const struct dpu_dspp_cfg *cfg,
void __iomem *addr)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
index 3b435690b6cc..45c26cd49fa3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
@@ -78,14 +78,6 @@ static inline struct dpu_hw_dspp *to_dpu_hw_dspp(struct dpu_hw_blk *hw)
return container_of(hw, struct dpu_hw_dspp, base);
}
-/**
- * dpu_hw_dspp_init() - Initializes the DSPP hw driver object.
- * should be called once before accessing every DSPP.
- * @dev: Corresponding device for devres management
- * @cfg: DSPP catalog entry for which driver object is required
- * @addr: Mapped register io address of MDP
- * Return: pointer to structure or ERR_PTR
- */
struct dpu_hw_dspp *dpu_hw_dspp_init(struct drm_device *dev,
const struct dpu_dspp_cfg *cfg,
void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index b85881aab047..49bd77a755aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -237,6 +237,11 @@ static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, unsigned int
irq_entry->cb(irq_entry->arg);
}
+/**
+ * dpu_core_irq - core IRQ handler
+ * @kms: MSM KMS handle
+ * @return: interrupt handling status
+ */
irqreturn_t dpu_core_irq(struct msm_kms *kms)
{
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
@@ -442,6 +447,12 @@ static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms)
wmb();
}
+/**
+ * dpu_core_irq_read - IRQ helper function for reading IRQ status
+ * @dpu_kms: DPU handle
+ * @irq_idx: irq index
+ * @return: non-zero if irq detected; otherwise no irq detected
+ */
u32 dpu_core_irq_read(struct dpu_kms *dpu_kms,
unsigned int irq_idx)
{
@@ -476,6 +487,12 @@ u32 dpu_core_irq_read(struct dpu_kms *dpu_kms,
return intr_status;
}
+/**
+ * dpu_hw_intr_init(): Initializes the interrupts hw object
+ * @dev: Corresponding device for devres management
+ * @addr: mapped register io address of MDP
+ * @m: pointer to MDSS catalog data
+ */
struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev,
void __iomem *addr,
const struct dpu_mdss_cfg *m)
@@ -517,6 +534,17 @@ struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev,
return intr;
}
+/**
+ * dpu_core_irq_register_callback - For registering callback function on IRQ
+ * interrupt
+ * @dpu_kms: DPU handle
+ * @irq_idx: irq index
+ * @irq_cb: IRQ callback function.
+ * @irq_arg: IRQ callback argument.
+ * @return: 0 for success registering callback, otherwise failure
+ *
+ * This function supports registration of multiple callbacks for each interrupt.
+ */
int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms,
unsigned int irq_idx,
void (*irq_cb)(void *arg),
@@ -567,6 +595,15 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms,
return 0;
}
+/**
+ * dpu_core_irq_unregister_callback - For unregistering callback function on IRQ
+ * interrupt
+ * @dpu_kms: DPU handle
+ * @irq_idx: irq index
+ * @return: 0 for success registering callback, otherwise failure
+ *
+ * This function supports registration of multiple callbacks for each interrupt.
+ */
int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms,
unsigned int irq_idx)
{
@@ -628,6 +665,11 @@ static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v)
DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_core_irq);
+/**
+ * dpu_debugfs_core_irq_init - register core irq debugfs
+ * @dpu_kms: pointer to kms
+ * @parent: debugfs directory root
+ */
void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
struct dentry *parent)
{
@@ -636,6 +678,11 @@ void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms,
}
#endif
+/**
+ * dpu_core_irq_preinstall - perform pre-installation of core IRQ handler
+ * @kms: MSM KMS handle
+ * @return: none
+ */
void dpu_core_irq_preinstall(struct msm_kms *kms)
{
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
@@ -653,6 +700,11 @@ void dpu_core_irq_preinstall(struct msm_kms *kms)
}
}
+/**
+ * dpu_core_irq_uninstall - uninstall core IRQ handler
+ * @kms: MSM KMS handle
+ * @return: none
+ */
void dpu_core_irq_uninstall(struct msm_kms *kms)
{
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 564b750a28fe..142358a105c5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -68,12 +68,6 @@ struct dpu_hw_intr {
struct dpu_hw_intr_entry irq_tbl[DPU_NUM_IRQS];
};
-/**
- * dpu_hw_intr_init(): Initializes the interrupts hw object
- * @dev: Corresponding device for devres management
- * @addr: mapped register io address of MDP
- * @m: pointer to MDSS catalog data
- */
struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev,
void __iomem *addr,
const struct dpu_mdss_cfg *m);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 29cb854f831a..fb1d25baa518 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -547,6 +547,14 @@ static void dpu_hw_intf_program_intf_cmd_cfg(struct dpu_hw_intf *intf,
DPU_REG_WRITE(&intf->hw, INTF_CONFIG2, intf_cfg2);
}
+/**
+ * dpu_hw_intf_init() - Initializes the INTF driver for the passed
+ * interface catalog entry.
+ * @dev: Corresponding device for devres management
+ * @cfg: interface catalog entry for which driver object is required
+ * @addr: mapped register io address of MDP
+ * @mdss_rev: dpu core's major and minor versions
+ */
struct dpu_hw_intf *dpu_hw_intf_init(struct drm_device *dev,
const struct dpu_intf_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index fc23650dfbf0..114be272ac0a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -130,14 +130,6 @@ struct dpu_hw_intf {
struct dpu_hw_intf_ops ops;
};
-/**
- * dpu_hw_intf_init() - Initializes the INTF driver for the passed
- * interface catalog entry.
- * @dev: Corresponding device for devres management
- * @cfg: interface catalog entry for which driver object is required
- * @addr: mapped register io address of MDP
- * @mdss_rev: dpu core's major and minor versions
- */
struct dpu_hw_intf *dpu_hw_intf_init(struct drm_device *dev,
const struct dpu_intf_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
index 1d3ccf3228c6..81b56f066519 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
@@ -158,6 +158,13 @@ static void _setup_mixer_ops(struct dpu_hw_lm_ops *ops,
ops->collect_misr = dpu_hw_lm_collect_misr;
}
+/**
+ * dpu_hw_lm_init() - Initializes the mixer hw driver object.
+ * should be called once before accessing every mixer.
+ * @dev: Corresponding device for devres management
+ * @cfg: mixer catalog entry for which driver object is required
+ * @addr: mapped register io address of MDP
+ */
struct dpu_hw_mixer *dpu_hw_lm_init(struct drm_device *dev,
const struct dpu_lm_cfg *cfg,
void __iomem *addr)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
index 0a3381755249..6f60fa9b3cd7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
@@ -93,13 +93,6 @@ static inline struct dpu_hw_mixer *to_dpu_hw_mixer(struct dpu_hw_blk *hw)
return container_of(hw, struct dpu_hw_mixer, base);
}
-/**
- * dpu_hw_lm_init() - Initializes the mixer hw driver object.
- * should be called once before accessing every mixer.
- * @dev: Corresponding device for devres management
- * @cfg: mixer catalog entry for which driver object is required
- * @addr: mapped register io address of MDP
- */
struct dpu_hw_mixer *dpu_hw_lm_init(struct drm_device *dev,
const struct dpu_lm_cfg *cfg,
void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index a2eff36a2224..f8806a4d317b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -293,7 +293,6 @@ enum dpu_3d_blend_mode {
/**
* struct dpu_hw_fmt_layout - format information of the source pixel data
- * @format: pixel format parameters
* @num_planes: number of planes (including meta data planes)
* @width: image width
* @height: image height
@@ -303,7 +302,6 @@ enum dpu_3d_blend_mode {
* @plane_pitch: pitch of each plane
*/
struct dpu_hw_fmt_layout {
- const struct msm_format *format;
uint32_t num_planes;
uint32_t width;
uint32_t height;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
index ddfa40a959cb..0b3325f9c870 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c
@@ -39,6 +39,14 @@ static void _setup_merge_3d_ops(struct dpu_hw_merge_3d *c,
c->ops.setup_3d_mode = dpu_hw_merge_3d_setup_3d_mode;
};
+/**
+ * dpu_hw_merge_3d_init() - Initializes the merge_3d driver for the passed
+ * merge3d catalog entry.
+ * @dev: Corresponding device for devres management
+ * @cfg: Pingpong catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * Return: Error code or allocated dpu_hw_merge_3d context
+ */
struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(struct drm_device *dev,
const struct dpu_merge_3d_cfg *cfg,
void __iomem *addr)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
index c192f02ec1ab..6833c0207523 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
@@ -45,14 +45,6 @@ static inline struct dpu_hw_merge_3d *to_dpu_hw_merge_3d(struct dpu_hw_blk *hw)
return container_of(hw, struct dpu_hw_merge_3d, base);
}
-/**
- * dpu_hw_merge_3d_init() - Initializes the merge_3d driver for the passed
- * merge3d catalog entry.
- * @dev: Corresponding device for devres management
- * @cfg: Pingpong catalog entry for which driver object is required
- * @addr: Mapped register io address of MDP
- * Return: Error code or allocated dpu_hw_merge_3d context
- */
struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(struct drm_device *dev,
const struct dpu_merge_3d_cfg *cfg,
void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 2db4c6fba37a..36c0ec775b92 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -283,6 +283,15 @@ static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
return 0;
}
+/**
+ * dpu_hw_pingpong_init() - initializes the pingpong driver for the passed
+ * pingpong catalog entry.
+ * @dev: Corresponding device for devres management
+ * @cfg: Pingpong catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @mdss_rev: dpu core's major and minor versions
+ * Return: Error code or allocated dpu_hw_pingpong context
+ */
struct dpu_hw_pingpong *dpu_hw_pingpong_init(struct drm_device *dev,
const struct dpu_pingpong_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index a48b69fd79a3..dd99e1c21a1e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -118,15 +118,6 @@ static inline struct dpu_hw_pingpong *to_dpu_hw_pingpong(struct dpu_hw_blk *hw)
return container_of(hw, struct dpu_hw_pingpong, base);
}
-/**
- * dpu_hw_pingpong_init() - initializes the pingpong driver for the passed
- * pingpong catalog entry.
- * @dev: Corresponding device for devres management
- * @cfg: Pingpong catalog entry for which driver object is required
- * @addr: Mapped register io address of MDP
- * @mdss_rev: dpu core's major and minor versions
- * Return: Error code or allocated dpu_hw_pingpong context
- */
struct dpu_hw_pingpong *dpu_hw_pingpong_init(struct drm_device *dev,
const struct dpu_pingpong_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 2c720f1fc1b2..32c7c8084553 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -672,6 +672,15 @@ int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms,
}
#endif
+/**
+ * dpu_hw_sspp_init() - Initializes the sspp hw driver object.
+ * Should be called once before accessing every pipe.
+ * @dev: Corresponding device for devres management
+ * @cfg: Pipe catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @mdss_data: UBWC / MDSS configuration data
+ * @mdss_rev: dpu core's major and minor versions
+ */
struct dpu_hw_sspp *dpu_hw_sspp_init(struct drm_device *dev,
const struct dpu_sspp_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index 4a910b808687..56a0edf2a57c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -12,6 +12,8 @@
struct dpu_hw_sspp;
+#define DPU_SSPP_MAX_PITCH_SIZE 0xffff
+
/**
* Flags
*/
@@ -142,10 +144,12 @@ struct dpu_hw_pixel_ext {
* @src_rect: src ROI, caller takes into account the different operations
* such as decimation, flip etc to program this field
* @dest_rect: destination ROI.
+ * @rotation: simplified drm rotation hint
*/
struct dpu_sw_pipe_cfg {
struct drm_rect src_rect;
struct drm_rect dst_rect;
+ unsigned int rotation;
};
/**
@@ -315,15 +319,7 @@ struct dpu_hw_sspp {
};
struct dpu_kms;
-/**
- * dpu_hw_sspp_init() - Initializes the sspp hw driver object.
- * Should be called once before accessing every pipe.
- * @dev: Corresponding device for devres management
- * @cfg: Pipe catalog entry for which driver object is required
- * @addr: Mapped register io address of MDP
- * @mdss_data: UBWC / MDSS configuration data
- * @mdss_rev: dpu core's major and minor versions
- */
+
struct dpu_hw_sspp *dpu_hw_sspp_init(struct drm_device *dev,
const struct dpu_sspp_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index 0f40eea7f5e2..ad19330de61a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -284,6 +284,13 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
ops->intf_audio_select = dpu_hw_intf_audio_select;
}
+/**
+ * dpu_hw_mdptop_init - initializes the top driver for the passed config
+ * @dev: Corresponding device for devres management
+ * @cfg: MDP TOP configuration from catalog
+ * @addr: Mapped register io address of MDP
+ * @mdss_rev: dpu core's major and minor versions
+ */
struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
const struct dpu_mdp_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index f1ab9fd106e5..04efdcd21ceb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -157,18 +157,9 @@ struct dpu_hw_mdp {
struct dpu_hw_mdp_ops ops;
};
-/**
- * dpu_hw_mdptop_init - initializes the top driver for the passed config
- * @dev: Corresponding device for devres management
- * @cfg: MDP TOP configuration from catalog
- * @addr: Mapped register io address of MDP
- * @mdss_rev: dpu core's major and minor versions
- */
struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
const struct dpu_mdp_cfg *cfg,
void __iomem *addr,
const struct dpu_mdss_version *mdss_rev);
-void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp);
-
#endif /*_DPU_HW_TOP_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
index 98e34afde2d2..af76ad8a8103 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
@@ -213,6 +213,13 @@ static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops,
ops->set_write_gather_en = dpu_hw_set_write_gather_en;
}
+/**
+ * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed
+ * VBIF catalog entry.
+ * @dev: Corresponding device for devres management
+ * @cfg: VBIF catalog entry for which driver object is required
+ * @addr: Mapped register io address of MDSS
+ */
struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
const struct dpu_vbif_cfg *cfg,
void __iomem *addr)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
index e2b4307500e4..285121ec804c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
@@ -105,13 +105,6 @@ struct dpu_hw_vbif {
struct dpu_hw_vbif_ops ops;
};
-/**
- * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed
- * VBIF catalog entry.
- * @dev: Corresponding device for devres management
- * @cfg: VBIF catalog entry for which driver object is required
- * @addr: Mapped register io address of MDSS
- */
struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
const struct dpu_vbif_cfg *cfg,
void __iomem *addr);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
index 93ff01c889b5..fb9f90957762 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -64,10 +64,10 @@ static void dpu_hw_wb_setup_outaddress(struct dpu_hw_wb *ctx,
}
static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
- struct dpu_hw_wb_cfg *data)
+ struct dpu_hw_wb_cfg *data,
+ const struct msm_format *fmt)
{
struct dpu_hw_blk_reg_map *c = &ctx->hw;
- const struct msm_format *fmt = data->dest.format;
u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp;
u32 write_config = 0;
u32 opmode = 0;
@@ -213,6 +213,14 @@ static void _setup_wb_ops(struct dpu_hw_wb_ops *ops,
ops->setup_clk_force_ctrl = dpu_hw_wb_setup_clk_force_ctrl;
}
+/**
+ * dpu_hw_wb_init() - Initializes the writeback hw driver object.
+ * @dev: Corresponding device for devres management
+ * @cfg: wb_path catalog entry for which driver object is required
+ * @addr: mapped register io address of MDP
+ * @mdss_rev: dpu core's major and minor versions
+ * Return: Error code or allocated dpu_hw_wb context
+ */
struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
const struct dpu_wb_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
index 37497473e16c..ee5e5ab786e1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
@@ -37,7 +37,8 @@ struct dpu_hw_wb_ops {
struct dpu_hw_wb_cfg *wb);
void (*setup_outformat)(struct dpu_hw_wb *ctx,
- struct dpu_hw_wb_cfg *wb);
+ struct dpu_hw_wb_cfg *wb,
+ const struct msm_format *fmt);
void (*setup_roi)(struct dpu_hw_wb *ctx,
struct dpu_hw_wb_cfg *wb);
@@ -74,14 +75,6 @@ struct dpu_hw_wb {
struct dpu_hw_wb_ops ops;
};
-/**
- * dpu_hw_wb_init() - Initializes the writeback hw driver object.
- * @dev: Corresponding device for devres management
- * @cfg: wb_path catalog entry for which driver object is required
- * @addr: mapped register io address of MDP
- * @mdss_rev: dpu core's major and minor versions
- * Return: Error code or allocated dpu_hw_wb context
- */
struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
const struct dpu_wb_cfg *cfg,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 9bcae53c4f45..ca4847b2b738 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -230,6 +230,21 @@ static int dpu_regset32_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(dpu_regset32);
+/**
+ * dpu_debugfs_create_regset32 - Create register read back file for debugfs
+ *
+ * This function is almost identical to the standard debugfs_create_regset32()
+ * function, with the main difference being that a list of register
+ * names/offsets do not need to be provided. The 'read' function simply outputs
+ * sequential register values over a specified range.
+ *
+ * @name: File name within debugfs
+ * @mode: File mode within debugfs
+ * @parent: Parent directory entry within debugfs, can be NULL
+ * @offset: sub-block offset
+ * @length: sub-block length, in bytes
+ * @dpu_kms: pointer to dpu kms structure
+ */
void dpu_debugfs_create_regset32(const char *name, umode_t mode,
void *parent,
uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms)
@@ -1025,7 +1040,6 @@ static const struct msm_kms_funcs kms_funcs = {
.complete_commit = dpu_kms_complete_commit,
.enable_vblank = dpu_kms_enable_vblank,
.disable_vblank = dpu_kms_disable_vblank,
- .check_modified_format = dpu_format_check_modified_format,
.destroy = dpu_kms_destroy,
.snapshot = dpu_kms_mdp_snapshot,
#ifdef CONFIG_DEBUG_FS
@@ -1061,6 +1075,13 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
return 0;
}
+/**
+ * dpu_kms_get_clk_rate() - get the clock rate
+ * @dpu_kms: pointer to dpu_kms structure
+ * @clock_name: clock name to get the rate
+ *
+ * Return: current clock rate
+ */
unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name)
{
struct clk *clk;
@@ -1202,13 +1223,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
- /*
- * max crtc width is equal to the max mixer width * 2 and max height is
- * is 4K
- */
- dev->mode_config.max_width =
- dpu_kms->catalog->caps->max_mixer_width * 2;
- dev->mode_config.max_height = 4096;
+ dev->mode_config.max_width = DPU_MAX_IMG_WIDTH;
+ dev->mode_config.max_height = DPU_MAX_IMG_HEIGHT;
dev->max_vblank_count = 0xffffffff;
/* Disable vblank irqs aggressively for power-saving */
@@ -1445,8 +1461,13 @@ static const struct dev_pm_ops dpu_pm_ops = {
};
static const struct of_device_id dpu_dt_match[] = {
+ { .compatible = "qcom,msm8917-mdp5", .data = &dpu_msm8917_cfg, },
+ { .compatible = "qcom,msm8937-mdp5", .data = &dpu_msm8937_cfg, },
+ { .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, },
+ { .compatible = "qcom,msm8996-mdp5", .data = &dpu_msm8996_cfg, },
{ .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, },
{ .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, },
+ { .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, },
{ .compatible = "qcom,sdm630-mdp5", .data = &dpu_sdm630_cfg, },
{ .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, },
{ .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, },
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 935ff6fd172c..88d64d43ea1a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -145,38 +145,11 @@ struct dpu_global_state
* @dpu_debugfs_create_regset32: Create 32-bit register dump file
*/
-/**
- * dpu_debugfs_create_regset32 - Create register read back file for debugfs
- *
- * This function is almost identical to the standard debugfs_create_regset32()
- * function, with the main difference being that a list of register
- * names/offsets do not need to be provided. The 'read' function simply outputs
- * sequential register values over a specified range.
- *
- * @name: File name within debugfs
- * @mode: File mode within debugfs
- * @parent: Parent directory entry within debugfs, can be NULL
- * @offset: sub-block offset
- * @length: sub-block length, in bytes
- * @dpu_kms: pointer to dpu kms structure
- */
void dpu_debugfs_create_regset32(const char *name, umode_t mode,
void *parent,
uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms);
/**
- * dpu_debugfs_get_root - Return root directory entry for KMS's debugfs
- *
- * The return value should be passed as the 'parent' argument to subsequent
- * debugfs create calls.
- *
- * @dpu_kms: Pointer to DPU's KMS structure
- *
- * Return: dentry pointer for DPU's debugfs location
- */
-void *dpu_debugfs_get_root(struct dpu_kms *dpu_kms);
-
-/**
* DPU info management functions
* These functions/definitions allow for building up a 'dpu_info' structure
* containing one or more "key=value\n" entries.
@@ -189,13 +162,6 @@ void *dpu_debugfs_get_root(struct dpu_kms *dpu_kms);
int dpu_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
void dpu_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
-/**
- * dpu_kms_get_clk_rate() - get the clock rate
- * @dpu_kms: pointer to dpu_kms structure
- * @clock_name: clock name to get the rate
- *
- * Return: current clock rate
- */
unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name);
#endif /* __dpu_kms_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 29298e066163..3ffac24333a2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -528,8 +528,7 @@ static const struct dpu_csc_cfg *_dpu_plane_get_csc(struct dpu_sw_pipe *pipe,
static void _dpu_plane_setup_scaler(struct dpu_sw_pipe *pipe,
const struct msm_format *fmt, bool color_fill,
- struct dpu_sw_pipe_cfg *pipe_cfg,
- unsigned int rotation)
+ struct dpu_sw_pipe_cfg *pipe_cfg)
{
struct dpu_hw_sspp *pipe_hw = pipe->sspp;
const struct drm_format_info *info = drm_format_info(fmt->pixel_format);
@@ -552,7 +551,7 @@ static void _dpu_plane_setup_scaler(struct dpu_sw_pipe *pipe,
dst_height,
&scaler3_cfg, fmt,
info->hsub, info->vsub,
- rotation);
+ pipe_cfg->rotation);
/* configure pixel extension based on scalar config */
_dpu_plane_setup_pixel_ext(&scaler3_cfg, &pixel_ext,
@@ -604,7 +603,7 @@ static void _dpu_plane_color_fill_pipe(struct dpu_plane_state *pstate,
if (pipe->sspp->ops.setup_rects)
pipe->sspp->ops.setup_rects(pipe, &pipe_cfg);
- _dpu_plane_setup_scaler(pipe, fmt, true, &pipe_cfg, pstate->rotation);
+ _dpu_plane_setup_scaler(pipe, fmt, true, &pipe_cfg);
}
/**
@@ -648,7 +647,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
struct drm_framebuffer *fb = new_state->fb;
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(new_state);
- struct dpu_hw_fmt_layout layout;
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
int ret;
@@ -676,17 +674,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
}
}
- /* validate framebuffer layout before commit */
- ret = dpu_format_populate_layout(pstate->aspace,
- new_state->fb, &layout);
- if (ret) {
- DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
- if (pstate->aspace)
- msm_framebuffer_cleanup(new_state->fb, pstate->aspace,
- pstate->needs_dirtyfb);
- return ret;
- }
-
return 0;
}
@@ -708,12 +695,17 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane,
}
static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu,
- const struct dpu_sspp_sub_blks *sblk,
- struct drm_rect src, const struct msm_format *fmt)
+ struct dpu_sw_pipe *pipe,
+ struct drm_rect src,
+ const struct msm_format *fmt)
{
+ const struct dpu_sspp_sub_blks *sblk = pipe->sspp->cap->sblk;
size_t num_formats;
const u32 *supported_formats;
+ if (!test_bit(DPU_SSPP_INLINE_ROTATION, &pipe->sspp->cap->features))
+ return -EINVAL;
+
if (!sblk->rotation_cfg) {
DPU_ERROR("invalid rotation cfg\n");
return -EINVAL;
@@ -743,6 +735,7 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
{
uint32_t min_src_size;
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
+ int ret;
min_src_size = MSM_FORMAT_IS_YUV(fmt) ? 2 : 1;
@@ -780,6 +773,12 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
return -EINVAL;
}
+ if (pipe_cfg->rotation & DRM_MODE_ROTATE_90) {
+ ret = dpu_plane_check_inline_rotation(pdpu, pipe, pipe_cfg->src_rect, fmt);
+ if (ret)
+ return ret;
+ }
+
/* max clk check */
if (_dpu_plane_calc_clk(mode, pipe_cfg) > kms->perf.max_core_clk_rate) {
DPU_DEBUG_PLANE(pdpu, "plane exceeds max mdp core clk limits\n");
@@ -789,37 +788,29 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
return 0;
}
-static int dpu_plane_atomic_check(struct drm_plane *plane,
- struct drm_atomic_state *state)
+#define MAX_UPSCALE_RATIO 20
+#define MAX_DOWNSCALE_RATIO 4
+
+static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
+ struct drm_plane_state *new_plane_state,
+ const struct drm_crtc_state *crtc_state)
{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
- plane);
- int ret = 0, min_scale;
+ int i, ret = 0, min_scale, max_scale;
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
- struct dpu_sw_pipe *pipe = &pstate->pipe;
- struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
- const struct drm_crtc_state *crtc_state = NULL;
- const struct msm_format *fmt;
struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
struct drm_rect fb_rect = { 0 };
uint32_t max_linewidth;
- unsigned int rotation;
- uint32_t supported_rotations;
- const struct dpu_sspp_cfg *pipe_hw_caps = pstate->pipe.sspp->cap;
- const struct dpu_sspp_sub_blks *sblk = pstate->pipe.sspp->cap->sblk;
- if (new_plane_state->crtc)
- crtc_state = drm_atomic_get_new_crtc_state(state,
- new_plane_state->crtc);
+ min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
+ max_scale = MAX_DOWNSCALE_RATIO << 16;
- min_scale = FRAC_16_16(1, sblk->maxupscale);
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
min_scale,
- sblk->maxdwnscale << 16,
+ max_scale,
true, true);
if (ret) {
DPU_DEBUG_PLANE(pdpu, "Check plane state failed (%d)\n", ret);
@@ -828,12 +819,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
if (!new_plane_state->visible)
return 0;
- pipe->multirect_index = DPU_SSPP_RECT_SOLO;
- pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
- r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
- r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
- r_pipe->sspp = NULL;
-
pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos;
if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) {
DPU_ERROR("> %d plane stages assigned\n",
@@ -841,13 +826,8 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
- pipe_cfg->src_rect = new_plane_state->src;
-
/* state->src is 16.16, src_rect is not */
- pipe_cfg->src_rect.x1 >>= 16;
- pipe_cfg->src_rect.x2 >>= 16;
- pipe_cfg->src_rect.y1 >>= 16;
- pipe_cfg->src_rect.y2 >>= 16;
+ drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
pipe_cfg->dst_rect = new_plane_state->dst;
@@ -855,14 +835,22 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
fb_rect.y2 = new_plane_state->fb->height;
/* Ensure fb size is supported */
- if (drm_rect_width(&fb_rect) > MAX_IMG_WIDTH ||
- drm_rect_height(&fb_rect) > MAX_IMG_HEIGHT) {
+ if (drm_rect_width(&fb_rect) > DPU_MAX_IMG_WIDTH ||
+ drm_rect_height(&fb_rect) > DPU_MAX_IMG_HEIGHT) {
DPU_DEBUG_PLANE(pdpu, "invalid framebuffer " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&fb_rect));
return -E2BIG;
}
- fmt = msm_framebuffer_format(new_plane_state->fb);
+ ret = dpu_format_populate_plane_sizes(new_plane_state->fb, &pstate->layout);
+ if (ret) {
+ DPU_ERROR_PLANE(pdpu, "failed to get format plane sizes, %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < pstate->layout.num_planes; i++)
+ if (pstate->layout.plane_pitch[i] > DPU_SSPP_MAX_PITCH_SIZE)
+ return -E2BIG;
max_linewidth = pdpu->catalog->caps->max_linewidth;
@@ -872,6 +860,86 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
_dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) {
+ if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
+ DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
+ return -E2BIG;
+ }
+
+ *r_pipe_cfg = *pipe_cfg;
+ pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
+ pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
+ r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
+ r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
+ } else {
+ memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg));
+ }
+
+ drm_rect_rotate_inv(&pipe_cfg->src_rect,
+ new_plane_state->fb->width, new_plane_state->fb->height,
+ new_plane_state->rotation);
+ if (r_pipe_cfg->src_rect.x1 != 0)
+ drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
+ new_plane_state->fb->width, new_plane_state->fb->height,
+ new_plane_state->rotation);
+
+ pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
+
+ return 0;
+}
+
+static int dpu_plane_atomic_check_sspp(struct drm_plane *plane,
+ struct drm_atomic_state *state,
+ const struct drm_crtc_state *crtc_state)
+{
+ struct drm_plane_state *new_plane_state =
+ drm_atomic_get_new_plane_state(state, plane);
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
+ struct dpu_sw_pipe *pipe = &pstate->pipe;
+ struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
+ const struct msm_format *fmt;
+ struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
+ struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
+ uint32_t max_linewidth;
+ uint32_t supported_rotations;
+ const struct dpu_sspp_cfg *pipe_hw_caps;
+ const struct dpu_sspp_sub_blks *sblk;
+ int ret = 0;
+
+ pipe_hw_caps = pipe->sspp->cap;
+ sblk = pipe->sspp->cap->sblk;
+
+ /*
+ * We already have verified scaling against platform limitations.
+ * Now check if the SSPP supports scaling at all.
+ */
+ if (!sblk->scaler_blk.len &&
+ ((drm_rect_width(&new_plane_state->src) >> 16 !=
+ drm_rect_width(&new_plane_state->dst)) ||
+ (drm_rect_height(&new_plane_state->src) >> 16 !=
+ drm_rect_height(&new_plane_state->dst))))
+ return -ERANGE;
+
+ fmt = msm_framebuffer_format(new_plane_state->fb);
+
+ max_linewidth = pdpu->catalog->caps->max_linewidth;
+
+ supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0;
+
+ if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION))
+ supported_rotations |= DRM_MODE_ROTATE_90;
+
+ pipe_cfg->rotation = drm_rotation_simplify(new_plane_state->rotation,
+ supported_rotations);
+ r_pipe_cfg->rotation = pipe_cfg->rotation;
+
+ ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt,
+ &crtc_state->adjusted_mode);
+ if (ret)
+ return ret;
+
+ if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) {
/*
* In parallel multirect case only the half of the usual width
* is supported for tiled formats. If we are here, we know that
@@ -885,16 +953,11 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
return -E2BIG;
}
- if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
- DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
- return -E2BIG;
- }
-
if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) ||
drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect) ||
(!test_bit(DPU_SSPP_SMART_DMA_V1, &pipe->sspp->cap->features) &&
!test_bit(DPU_SSPP_SMART_DMA_V2, &pipe->sspp->cap->features)) ||
+ pipe_cfg->rotation & DRM_MODE_ROTATE_90 ||
MSM_FORMAT_IS_YUV(fmt)) {
DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, can't use split source\n",
DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
@@ -912,51 +975,48 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
r_pipe->multirect_index = DPU_SSPP_RECT_1;
r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
- *r_pipe_cfg = *pipe_cfg;
- pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
- pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
- r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
- r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
- }
-
- drm_rect_rotate_inv(&pipe_cfg->src_rect,
- new_plane_state->fb->width, new_plane_state->fb->height,
- new_plane_state->rotation);
- if (r_pipe->sspp)
- drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
- new_plane_state->fb->width, new_plane_state->fb->height,
- new_plane_state->rotation);
-
- ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt, &crtc_state->adjusted_mode);
- if (ret)
- return ret;
-
- if (r_pipe->sspp) {
ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt,
&crtc_state->adjusted_mode);
if (ret)
return ret;
}
- supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0;
+ return 0;
+}
- if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION))
- supported_rotations |= DRM_MODE_ROTATE_90;
+static int dpu_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);
+ int ret = 0;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+ struct dpu_sw_pipe *pipe = &pstate->pipe;
+ struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
+ const struct drm_crtc_state *crtc_state = NULL;
- rotation = drm_rotation_simplify(new_plane_state->rotation,
- supported_rotations);
+ if (new_plane_state->crtc)
+ crtc_state = drm_atomic_get_new_crtc_state(state,
+ new_plane_state->crtc);
- if ((pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) &&
- (rotation & DRM_MODE_ROTATE_90)) {
- ret = dpu_plane_check_inline_rotation(pdpu, sblk, pipe_cfg->src_rect, fmt);
- if (ret)
- return ret;
- }
+ pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
+ r_pipe->sspp = NULL;
- pstate->rotation = rotation;
- pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
+ ret = dpu_plane_atomic_check_nosspp(plane, new_plane_state, crtc_state);
+ if (ret)
+ return ret;
- return 0;
+ if (!new_plane_state->visible)
+ return 0;
+
+ pipe->multirect_index = DPU_SSPP_RECT_SOLO;
+ pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
+ r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
+ r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
+
+ return dpu_plane_atomic_check_sspp(plane, state, crtc_state);
}
static void dpu_plane_flush_csc(struct dpu_plane *pdpu, struct dpu_sw_pipe *pipe)
@@ -981,6 +1041,10 @@ static void dpu_plane_flush_csc(struct dpu_plane *pdpu, struct dpu_sw_pipe *pipe
}
+/**
+ * dpu_plane_flush - final plane operations before commit flush
+ * @plane: Pointer to drm plane structure
+ */
void dpu_plane_flush(struct drm_plane *plane)
{
struct dpu_plane *pdpu;
@@ -1060,14 +1124,14 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane *plane,
pipe_cfg);
}
- _dpu_plane_setup_scaler(pipe, fmt, false, pipe_cfg, pstate->rotation);
+ _dpu_plane_setup_scaler(pipe, fmt, false, pipe_cfg);
if (pipe->sspp->ops.setup_multirect)
pipe->sspp->ops.setup_multirect(
pipe);
if (pipe->sspp->ops.setup_format) {
- unsigned int rotation = pstate->rotation;
+ unsigned int rotation = pipe_cfg->rotation;
src_flags = 0x0;
@@ -1101,7 +1165,8 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane *plane,
_dpu_plane_set_qos_remap(plane, pipe);
}
-static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
+static void dpu_plane_sspp_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
{
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct drm_plane_state *state = plane->state;
@@ -1115,17 +1180,6 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
msm_framebuffer_format(fb);
struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
- struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
- struct msm_gem_address_space *aspace = kms->base.aspace;
- struct dpu_hw_fmt_layout layout;
- bool layout_valid = false;
- int ret;
-
- ret = dpu_format_populate_layout(aspace, fb, &layout);
- if (ret)
- DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
- else
- layout_valid = true;
pstate->pending = true;
@@ -1133,6 +1187,8 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe);
pdpu->is_rt_pipe = is_rt_pipe;
+ dpu_format_populate_addrs(pstate->aspace, new_state->fb, &pstate->layout);
+
DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT
", %p4cc ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src),
crtc->base.id, DRM_RECT_ARG(&state->dst),
@@ -1140,12 +1196,12 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt,
drm_mode_vrefresh(&crtc->mode),
- layout_valid ? &layout : NULL);
+ &pstate->layout);
if (r_pipe->sspp) {
dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt,
drm_mode_vrefresh(&crtc->mode),
- layout_valid ? &layout : NULL);
+ &pstate->layout);
}
if (pstate->needs_qos_remap)
@@ -1197,7 +1253,7 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
if (!new_state->visible) {
_dpu_plane_atomic_disable(plane);
} else {
- dpu_plane_sspp_atomic_update(plane);
+ dpu_plane_sspp_atomic_update(plane, new_state);
}
}
@@ -1301,7 +1357,6 @@ static void dpu_plane_reset(struct drm_plane *plane)
{
struct dpu_plane *pdpu;
struct dpu_plane_state *pstate;
- struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
if (!plane) {
DPU_ERROR("invalid plane\n");
@@ -1323,16 +1378,6 @@ static void dpu_plane_reset(struct drm_plane *plane)
return;
}
- /*
- * Set the SSPP here until we have proper virtualized DPU planes.
- * This is the place where the state is allocated, so fill it fully.
- */
- pstate->pipe.sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
- pstate->pipe.multirect_index = DPU_SSPP_RECT_SOLO;
- pstate->pipe.multirect_mode = DPU_SSPP_MULTIRECT_NONE;
-
- pstate->r_pipe.sspp = NULL;
-
__drm_atomic_helper_plane_reset(plane, &pstate->base);
}
@@ -1388,7 +1433,15 @@ static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = {
.atomic_update = dpu_plane_atomic_update,
};
-/* initialize plane */
+/**
+ * dpu_plane_init - create new dpu plane for the given pipe
+ * @dev: Pointer to DRM device
+ * @pipe: dpu hardware pipe identifier
+ * @type: Plane type - PRIMARY/OVERLAY/CURSOR
+ * @possible_crtcs: bitmask of crtc that can be attached to the given pipe
+ *
+ * Initialize the plane.
+ */
struct drm_plane *dpu_plane_init(struct drm_device *dev,
uint32_t pipe, enum drm_plane_type type,
unsigned long possible_crtcs)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index abd6b21a049b..97090ca7842b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -30,7 +30,7 @@
* @plane_fetch_bw: calculated BW per plane
* @plane_clk: calculated clk per plane
* @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed
- * @rotation: simplified drm rotation hint
+ * @layout: framebuffer memory layout
*/
struct dpu_plane_state {
struct drm_plane_state base;
@@ -47,46 +47,21 @@ struct dpu_plane_state {
u64 plane_clk;
bool needs_dirtyfb;
- unsigned int rotation;
+
+ struct dpu_hw_fmt_layout layout;
};
#define to_dpu_plane_state(x) \
container_of(x, struct dpu_plane_state, base)
-/**
- * dpu_plane_flush - final plane operations before commit flush
- * @plane: Pointer to drm plane structure
- */
void dpu_plane_flush(struct drm_plane *plane);
-/**
- * dpu_plane_set_error: enable/disable error condition
- * @plane: pointer to drm_plane structure
- */
void dpu_plane_set_error(struct drm_plane *plane, bool error);
-/**
- * dpu_plane_init - create new dpu plane for the given pipe
- * @dev: Pointer to DRM device
- * @pipe: dpu hardware pipe identifier
- * @type: Plane type - PRIMARY/OVERLAY/CURSOR
- * @possible_crtcs: bitmask of crtc that can be attached to the given pipe
- *
- */
struct drm_plane *dpu_plane_init(struct drm_device *dev,
uint32_t pipe, enum drm_plane_type type,
unsigned long possible_crtcs);
-/**
- * dpu_plane_color_fill - enables color fill on plane
- * @plane: Pointer to DRM plane object
- * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
- * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
- * Returns: 0 on success
- */
-int dpu_plane_color_fill(struct drm_plane *plane,
- uint32_t color, uint32_t alpha);
-
#ifdef CONFIG_DEBUG_FS
void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable);
#else
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 44938ba7a2b7..c247af03dc8e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -34,6 +34,16 @@ struct dpu_rm_requirements {
struct msm_display_topology topology;
};
+/**
+ * dpu_rm_init - Read hardware catalog and create reservation tracking objects
+ * for all HW blocks.
+ * @dev: Corresponding device for devres management
+ * @rm: DPU Resource Manager handle
+ * @cat: Pointer to hardware catalog
+ * @mdss_data: Pointer to MDSS / UBWC configuration
+ * @mmio: mapped register io address of MDP
+ * @return: 0 on Success otherwise -ERROR
+ */
int dpu_rm_init(struct drm_device *dev,
struct dpu_rm *rm,
const struct dpu_mdss_cfg *cat,
@@ -641,6 +651,13 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
}
}
+/**
+ * dpu_rm_release - Given the encoder for the display chain, release any
+ * HW blocks previously reserved for that use case.
+ * @global_state: resources shared across multiple kms objects
+ * @enc: DRM Encoder handle
+ * @return: 0 on Success otherwise -ERROR
+ */
void dpu_rm_release(struct dpu_global_state *global_state,
struct drm_encoder *enc)
{
@@ -657,6 +674,20 @@ void dpu_rm_release(struct dpu_global_state *global_state,
_dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
}
+/**
+ * dpu_rm_reserve - Given a CRTC->Encoder->Connector display chain, analyze
+ * the use connections and user requirements, specified through related
+ * topology control properties, and reserve hardware blocks to that
+ * display chain.
+ * HW blocks can then be accessed through dpu_rm_get_* functions.
+ * HW Reservations should be released via dpu_rm_release_hw.
+ * @rm: DPU Resource Manager handle
+ * @global_state: resources shared across multiple kms objects
+ * @enc: DRM Encoder handle
+ * @crtc_state: Proposed Atomic DRM CRTC State handle
+ * @topology: Pointer to topology info for the display
+ * @return: 0 on Success otherwise -ERROR
+ */
int dpu_rm_reserve(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
@@ -694,6 +725,16 @@ int dpu_rm_reserve(
return ret;
}
+/**
+ * dpu_rm_get_assigned_resources - Get hw resources of the given type that are
+ * assigned to this encoder
+ * @rm: DPU Resource Manager handle
+ * @global_state: resources shared across multiple kms objects
+ * @enc_id: encoder id requesting for allocation
+ * @type: resource type to return data for
+ * @blks: pointer to the array to be filled by HW resources
+ * @blks_size: size of the @blks array
+ */
int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
struct dpu_global_state *global_state, uint32_t enc_id,
enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
@@ -772,6 +813,11 @@ static void dpu_rm_print_state_helper(struct drm_printer *p,
}
+/**
+ * dpu_rm_print_state - output the RM private state
+ * @p: DRM printer
+ * @global_state: global state
+ */
void dpu_rm_print_state(struct drm_printer *p,
const struct dpu_global_state *global_state)
{
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index e63db8ace6b9..ea0e49cb7b0d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -38,62 +38,40 @@ struct dpu_rm {
};
/**
- * dpu_rm_init - Read hardware catalog and create reservation tracking objects
- * for all HW blocks.
- * @dev: Corresponding device for devres management
- * @rm: DPU Resource Manager handle
- * @cat: Pointer to hardware catalog
- * @mdss_data: Pointer to MDSS / UBWC configuration
- * @mmio: mapped register io address of MDP
- * @Return: 0 on Success otherwise -ERROR
+ * struct msm_display_topology - defines a display topology pipeline
+ * @num_lm: number of layer mixers used
+ * @num_intf: number of interfaces the panel is mounted on
+ * @num_dspp: number of dspp blocks used
+ * @num_dsc: number of Display Stream Compression (DSC) blocks used
+ * @needs_cdm: indicates whether cdm block is needed for this display topology
*/
+struct msm_display_topology {
+ u32 num_lm;
+ u32 num_intf;
+ u32 num_dspp;
+ u32 num_dsc;
+ bool needs_cdm;
+};
+
int dpu_rm_init(struct drm_device *dev,
struct dpu_rm *rm,
const struct dpu_mdss_cfg *cat,
const struct msm_mdss_data *mdss_data,
void __iomem *mmio);
-/**
- * dpu_rm_reserve - Given a CRTC->Encoder->Connector display chain, analyze
- * the use connections and user requirements, specified through related
- * topology control properties, and reserve hardware blocks to that
- * display chain.
- * HW blocks can then be accessed through dpu_rm_get_* functions.
- * HW Reservations should be released via dpu_rm_release_hw.
- * @rm: DPU Resource Manager handle
- * @drm_enc: DRM Encoder handle
- * @crtc_state: Proposed Atomic DRM CRTC State handle
- * @topology: Pointer to topology info for the display
- * @Return: 0 on Success otherwise -ERROR
- */
int dpu_rm_reserve(struct dpu_rm *rm,
struct dpu_global_state *global_state,
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
struct msm_display_topology topology);
-/**
- * dpu_rm_reserve - Given the encoder for the display chain, release any
- * HW blocks previously reserved for that use case.
- * @rm: DPU Resource Manager handle
- * @enc: DRM Encoder handle
- * @Return: 0 on Success otherwise -ERROR
- */
void dpu_rm_release(struct dpu_global_state *global_state,
struct drm_encoder *enc);
-/**
- * Get hw resources of the given type that are assigned to this encoder.
- */
int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
struct dpu_global_state *global_state, uint32_t enc_id,
enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
-/**
- * dpu_rm_print_state - output the RM private state
- * @p: DRM printer
- * @global_state: global state
- */
void dpu_rm_print_state(struct drm_printer *p,
const struct dpu_global_state *global_state);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
index 47c02b98eac3..2a551e455aa3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
@@ -204,6 +204,11 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms,
vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
}
+/**
+ * dpu_vbif_set_qos_remap - set QoS priority level remap
+ * @dpu_kms: DPU handler
+ * @params: Pointer to QoS configuration parameters
+ */
void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
struct dpu_vbif_set_qos_params *params)
{
@@ -245,6 +250,10 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
}
}
+/**
+ * dpu_vbif_clear_errors - clear any vbif errors
+ * @dpu_kms: DPU handler
+ */
void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms)
{
struct dpu_hw_vbif *vbif;
@@ -262,6 +271,10 @@ void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms)
}
}
+/**
+ * dpu_vbif_init_memtypes - initialize xin memory types for vbif
+ * @dpu_kms: DPU handler
+ */
void dpu_vbif_init_memtypes(struct dpu_kms *dpu_kms)
{
struct dpu_hw_vbif *vbif;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h
index e1b1f7f4e4be..62e47ae1e3ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h
@@ -38,32 +38,14 @@ struct dpu_vbif_set_qos_params {
bool is_rt;
};
-/**
- * dpu_vbif_set_ot_limit - set OT limit for vbif client
- * @dpu_kms: DPU handler
- * @params: Pointer to OT configuration parameters
- */
void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms,
struct dpu_vbif_set_ot_params *params);
-/**
- * dpu_vbif_set_qos_remap - set QoS priority level remap
- * @dpu_kms: DPU handler
- * @params: Pointer to QoS configuration parameters
- */
void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
struct dpu_vbif_set_qos_params *params);
-/**
- * dpu_vbif_clear_errors - clear any vbif errors
- * @dpu_kms: DPU handler
- */
void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms);
-/**
- * dpu_vbif_init_memtypes - initialize xin memory types for vbif
- * @dpu_kms: DPU handler
- */
void dpu_vbif_init_memtypes(struct dpu_kms *dpu_kms);
void dpu_debugfs_vbif_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root);
diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
index 4d55e3cf570f..07a2c1e87219 100644
--- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
+++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
@@ -25,24 +25,21 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
addr = base_addr;
end_addr = base_addr + aligned_len;
- if (!(*reg))
- *reg = kvzalloc(len_padded, GFP_KERNEL);
-
- if (*reg)
- dump_addr = *reg;
+ *reg = kvzalloc(len_padded, GFP_KERNEL);
+ if (!*reg)
+ return;
+ dump_addr = *reg;
for (i = 0; i < num_rows; i++) {
x0 = (addr < end_addr) ? readl_relaxed(addr + 0x0) : 0;
x4 = (addr + 0x4 < end_addr) ? readl_relaxed(addr + 0x4) : 0;
x8 = (addr + 0x8 < end_addr) ? readl_relaxed(addr + 0x8) : 0;
xc = (addr + 0xc < end_addr) ? readl_relaxed(addr + 0xc) : 0;
- if (dump_addr) {
- dump_addr[i * 4] = x0;
- dump_addr[i * 4 + 1] = x4;
- dump_addr[i * 4 + 2] = x8;
- dump_addr[i * 4 + 3] = xc;
- }
+ dump_addr[i * 4] = x0;
+ dump_addr[i * 4 + 1] = x4;
+ dump_addr[i * 4 + 2] = x8;
+ dump_addr[i * 4 + 3] = xc;
addr += REG_DUMP_ALIGN;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
index a599fc5d63c5..74e01a5dd419 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
@@ -17,281 +17,281 @@
#include "dp_display.h"
#include "dp_utils.h"
-struct dp_audio_private {
+struct msm_dp_audio_private {
struct platform_device *audio_pdev;
struct platform_device *pdev;
struct drm_device *drm_dev;
- struct dp_catalog *catalog;
+ struct msm_dp_catalog *catalog;
u32 channels;
- struct dp_audio dp_audio;
+ struct msm_dp_audio msm_dp_audio;
};
-static u32 dp_audio_get_header(struct dp_catalog *catalog,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header)
+static u32 msm_dp_audio_get_header(struct msm_dp_catalog *catalog,
+ enum msm_dp_catalog_audio_sdp_type sdp,
+ enum msm_dp_catalog_audio_header_type header)
{
- return dp_catalog_audio_get_header(catalog, sdp, header);
+ return msm_dp_catalog_audio_get_header(catalog, sdp, header);
}
-static void dp_audio_set_header(struct dp_catalog *catalog,
+static void msm_dp_audio_set_header(struct msm_dp_catalog *catalog,
u32 data,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header)
+ enum msm_dp_catalog_audio_sdp_type sdp,
+ enum msm_dp_catalog_audio_header_type header)
{
- dp_catalog_audio_set_header(catalog, sdp, header, data);
+ msm_dp_catalog_audio_set_header(catalog, sdp, header, data);
}
-static void dp_audio_stream_sdp(struct dp_audio_private *audio)
+static void msm_dp_audio_stream_sdp(struct msm_dp_audio_private *audio)
{
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
u32 value, new_value;
u8 parity_byte;
/* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
new_value = 0x02;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_1_BIT)
| (parity_byte << PARITY_BYTE_1_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
/* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
new_value = value;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
/* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
new_value = audio->channels - 1;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| (parity_byte << PARITY_BYTE_3_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
}
-static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
+static void msm_dp_audio_timestamp_sdp(struct msm_dp_audio_private *audio)
{
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
u32 value, new_value;
u8 parity_byte;
/* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
new_value = 0x1;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_1_BIT)
| (parity_byte << PARITY_BYTE_1_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
/* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
new_value = 0x17;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
/* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
new_value = (0x0 | (0x11 << 2));
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| (parity_byte << PARITY_BYTE_3_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
}
-static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
+static void msm_dp_audio_infoframe_sdp(struct msm_dp_audio_private *audio)
{
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
u32 value, new_value;
u8 parity_byte;
/* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
new_value = 0x84;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_1_BIT)
| (parity_byte << PARITY_BYTE_1_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
/* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
new_value = 0x1b;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
/* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
new_value = (0x0 | (0x11 << 2));
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| (parity_byte << PARITY_BYTE_3_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
new_value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
}
-static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
+static void msm_dp_audio_copy_management_sdp(struct msm_dp_audio_private *audio)
{
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
u32 value, new_value;
u8 parity_byte;
/* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
new_value = 0x05;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_1_BIT)
| (parity_byte << PARITY_BYTE_1_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
/* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
new_value = 0x0F;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
/* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
new_value = 0x0;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_3_BIT)
| (parity_byte << PARITY_BYTE_3_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
}
-static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
+static void msm_dp_audio_isrc_sdp(struct msm_dp_audio_private *audio)
{
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
u32 value, new_value;
u8 parity_byte;
/* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
new_value = 0x06;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_1_BIT)
| (parity_byte << PARITY_BYTE_1_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
/* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
+ value = msm_dp_audio_get_header(catalog,
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
new_value = 0x0F;
- parity_byte = dp_utils_calculate_parity(new_value);
+ parity_byte = msm_dp_utils_calculate_parity(new_value);
value |= ((new_value << HEADER_BYTE_2_BIT)
| (parity_byte << PARITY_BYTE_2_BIT));
drm_dbg_dp(audio->drm_dev,
"Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
value, parity_byte);
- dp_audio_set_header(catalog, value,
+ msm_dp_audio_set_header(catalog, value,
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
}
-static void dp_audio_setup_sdp(struct dp_audio_private *audio)
+static void msm_dp_audio_setup_sdp(struct msm_dp_audio_private *audio)
{
- dp_catalog_audio_config_sdp(audio->catalog);
+ msm_dp_catalog_audio_config_sdp(audio->catalog);
- dp_audio_stream_sdp(audio);
- dp_audio_timestamp_sdp(audio);
- dp_audio_infoframe_sdp(audio);
- dp_audio_copy_management_sdp(audio);
- dp_audio_isrc_sdp(audio);
+ msm_dp_audio_stream_sdp(audio);
+ msm_dp_audio_timestamp_sdp(audio);
+ msm_dp_audio_infoframe_sdp(audio);
+ msm_dp_audio_copy_management_sdp(audio);
+ msm_dp_audio_isrc_sdp(audio);
}
-static void dp_audio_setup_acr(struct dp_audio_private *audio)
+static void msm_dp_audio_setup_acr(struct msm_dp_audio_private *audio)
{
u32 select = 0;
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
- switch (audio->dp_audio.bw_code) {
+ switch (audio->msm_dp_audio.bw_code) {
case DP_LINK_BW_1_62:
select = 0;
break;
@@ -310,15 +310,15 @@ static void dp_audio_setup_acr(struct dp_audio_private *audio)
break;
}
- dp_catalog_audio_config_acr(catalog, select);
+ msm_dp_catalog_audio_config_acr(catalog, select);
}
-static void dp_audio_safe_to_exit_level(struct dp_audio_private *audio)
+static void msm_dp_audio_safe_to_exit_level(struct msm_dp_audio_private *audio)
{
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
u32 safe_to_exit_level = 0;
- switch (audio->dp_audio.lane_count) {
+ switch (audio->msm_dp_audio.lane_count) {
case 1:
safe_to_exit_level = 14;
break;
@@ -336,49 +336,49 @@ static void dp_audio_safe_to_exit_level(struct dp_audio_private *audio)
break;
}
- dp_catalog_audio_sfe_level(catalog, safe_to_exit_level);
+ msm_dp_catalog_audio_sfe_level(catalog, safe_to_exit_level);
}
-static void dp_audio_enable(struct dp_audio_private *audio, bool enable)
+static void msm_dp_audio_enable(struct msm_dp_audio_private *audio, bool enable)
{
- struct dp_catalog *catalog = audio->catalog;
+ struct msm_dp_catalog *catalog = audio->catalog;
- dp_catalog_audio_enable(catalog, enable);
+ msm_dp_catalog_audio_enable(catalog, enable);
}
-static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev)
+static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device *pdev)
{
- struct dp_audio *dp_audio;
- struct msm_dp *dp_display;
+ struct msm_dp_audio *msm_dp_audio;
+ struct msm_dp *msm_dp_display;
if (!pdev) {
DRM_ERROR("invalid input\n");
return ERR_PTR(-ENODEV);
}
- dp_display = platform_get_drvdata(pdev);
- if (!dp_display) {
+ msm_dp_display = platform_get_drvdata(pdev);
+ if (!msm_dp_display) {
DRM_ERROR("invalid input\n");
return ERR_PTR(-ENODEV);
}
- dp_audio = dp_display->dp_audio;
+ msm_dp_audio = msm_dp_display->msm_dp_audio;
- if (!dp_audio) {
- DRM_ERROR("invalid dp_audio data\n");
+ if (!msm_dp_audio) {
+ DRM_ERROR("invalid msm_dp_audio data\n");
return ERR_PTR(-EINVAL);
}
- return container_of(dp_audio, struct dp_audio_private, dp_audio);
+ return container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio);
}
-static int dp_audio_hook_plugged_cb(struct device *dev, void *data,
+static int msm_dp_audio_hook_plugged_cb(struct device *dev, void *data,
hdmi_codec_plugged_cb fn,
struct device *codec_dev)
{
struct platform_device *pdev;
- struct msm_dp *dp_display;
+ struct msm_dp *msm_dp_display;
pdev = to_platform_device(dev);
if (!pdev) {
@@ -386,20 +386,20 @@ static int dp_audio_hook_plugged_cb(struct device *dev, void *data,
return -ENODEV;
}
- dp_display = platform_get_drvdata(pdev);
- if (!dp_display) {
+ msm_dp_display = platform_get_drvdata(pdev);
+ if (!msm_dp_display) {
pr_err("invalid input\n");
return -ENODEV;
}
- return dp_display_set_plugged_cb(dp_display, fn, codec_dev);
+ return msm_dp_display_set_plugged_cb(msm_dp_display, fn, codec_dev);
}
-static int dp_audio_get_eld(struct device *dev,
+static int msm_dp_audio_get_eld(struct device *dev,
void *data, uint8_t *buf, size_t len)
{
struct platform_device *pdev;
- struct msm_dp *dp_display;
+ struct msm_dp *msm_dp_display;
pdev = to_platform_device(dev);
@@ -408,30 +408,30 @@ static int dp_audio_get_eld(struct device *dev,
return -ENODEV;
}
- dp_display = platform_get_drvdata(pdev);
- if (!dp_display) {
+ msm_dp_display = platform_get_drvdata(pdev);
+ if (!msm_dp_display) {
DRM_ERROR("invalid input\n");
return -ENODEV;
}
- memcpy(buf, dp_display->connector->eld,
- min(sizeof(dp_display->connector->eld), len));
+ memcpy(buf, msm_dp_display->connector->eld,
+ min(sizeof(msm_dp_display->connector->eld), len));
return 0;
}
-int dp_audio_hw_params(struct device *dev,
+int msm_dp_audio_hw_params(struct device *dev,
void *data,
struct hdmi_codec_daifmt *daifmt,
struct hdmi_codec_params *params)
{
int rc = 0;
- struct dp_audio_private *audio;
+ struct msm_dp_audio_private *audio;
struct platform_device *pdev;
- struct msm_dp *dp_display;
+ struct msm_dp *msm_dp_display;
pdev = to_platform_device(dev);
- dp_display = platform_get_drvdata(pdev);
+ msm_dp_display = platform_get_drvdata(pdev);
/*
* there could be cases where sound card can be opened even
@@ -441,12 +441,12 @@ int dp_audio_hw_params(struct device *dev,
* such cases check for connection status and bail out if not
* connected.
*/
- if (!dp_display->power_on) {
+ if (!msm_dp_display->power_on) {
rc = -EINVAL;
goto end;
}
- audio = dp_audio_get_data(pdev);
+ audio = msm_dp_audio_get_data(pdev);
if (IS_ERR(audio)) {
rc = PTR_ERR(audio);
goto end;
@@ -454,26 +454,26 @@ int dp_audio_hw_params(struct device *dev,
audio->channels = params->channels;
- dp_audio_setup_sdp(audio);
- dp_audio_setup_acr(audio);
- dp_audio_safe_to_exit_level(audio);
- dp_audio_enable(audio, true);
- dp_display_signal_audio_start(dp_display);
- dp_display->audio_enabled = true;
+ msm_dp_audio_setup_sdp(audio);
+ msm_dp_audio_setup_acr(audio);
+ msm_dp_audio_safe_to_exit_level(audio);
+ msm_dp_audio_enable(audio, true);
+ msm_dp_display_signal_audio_start(msm_dp_display);
+ msm_dp_display->audio_enabled = true;
end:
return rc;
}
-static void dp_audio_shutdown(struct device *dev, void *data)
+static void msm_dp_audio_shutdown(struct device *dev, void *data)
{
- struct dp_audio_private *audio;
+ struct msm_dp_audio_private *audio;
struct platform_device *pdev;
- struct msm_dp *dp_display;
+ struct msm_dp *msm_dp_display;
pdev = to_platform_device(dev);
- dp_display = platform_get_drvdata(pdev);
- audio = dp_audio_get_data(pdev);
+ msm_dp_display = platform_get_drvdata(pdev);
+ audio = msm_dp_audio_get_data(pdev);
if (IS_ERR(audio)) {
DRM_ERROR("failed to get audio data\n");
return;
@@ -487,32 +487,32 @@ static void dp_audio_shutdown(struct device *dev, void *data)
* connected. is_connected cannot be used here as its set
* to false earlier than this call
*/
- if (!dp_display->audio_enabled)
+ if (!msm_dp_display->audio_enabled)
return;
- dp_audio_enable(audio, false);
+ msm_dp_audio_enable(audio, false);
/* signal the dp display to safely shutdown clocks */
- dp_display_signal_audio_complete(dp_display);
+ msm_dp_display_signal_audio_complete(msm_dp_display);
}
-static const struct hdmi_codec_ops dp_audio_codec_ops = {
- .hw_params = dp_audio_hw_params,
- .audio_shutdown = dp_audio_shutdown,
- .get_eld = dp_audio_get_eld,
- .hook_plugged_cb = dp_audio_hook_plugged_cb,
+static const struct hdmi_codec_ops msm_dp_audio_codec_ops = {
+ .hw_params = msm_dp_audio_hw_params,
+ .audio_shutdown = msm_dp_audio_shutdown,
+ .get_eld = msm_dp_audio_get_eld,
+ .hook_plugged_cb = msm_dp_audio_hook_plugged_cb,
};
static struct hdmi_codec_pdata codec_data = {
- .ops = &dp_audio_codec_ops,
+ .ops = &msm_dp_audio_codec_ops,
.max_i2s_channels = 8,
.i2s = 1,
};
-void dp_unregister_audio_driver(struct device *dev, struct dp_audio *dp_audio)
+void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio)
{
- struct dp_audio_private *audio_priv;
+ struct msm_dp_audio_private *audio_priv;
- audio_priv = container_of(dp_audio, struct dp_audio_private, dp_audio);
+ audio_priv = container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio);
if (audio_priv->audio_pdev) {
platform_device_unregister(audio_priv->audio_pdev);
@@ -520,13 +520,13 @@ void dp_unregister_audio_driver(struct device *dev, struct dp_audio *dp_audio)
}
}
-int dp_register_audio_driver(struct device *dev,
- struct dp_audio *dp_audio)
+int msm_dp_register_audio_driver(struct device *dev,
+ struct msm_dp_audio *msm_dp_audio)
{
- struct dp_audio_private *audio_priv;
+ struct msm_dp_audio_private *audio_priv;
- audio_priv = container_of(dp_audio,
- struct dp_audio_private, dp_audio);
+ audio_priv = container_of(msm_dp_audio,
+ struct msm_dp_audio_private, msm_dp_audio);
audio_priv->audio_pdev = platform_device_register_data(dev,
HDMI_CODEC_DRV_NAME,
@@ -536,13 +536,13 @@ int dp_register_audio_driver(struct device *dev,
return PTR_ERR_OR_ZERO(audio_priv->audio_pdev);
}
-struct dp_audio *dp_audio_get(struct platform_device *pdev,
- struct dp_panel *panel,
- struct dp_catalog *catalog)
+struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev,
+ struct msm_dp_panel *panel,
+ struct msm_dp_catalog *catalog)
{
int rc = 0;
- struct dp_audio_private *audio;
- struct dp_audio *dp_audio;
+ struct msm_dp_audio_private *audio;
+ struct msm_dp_audio *msm_dp_audio;
if (!pdev || !panel || !catalog) {
DRM_ERROR("invalid input\n");
@@ -559,23 +559,23 @@ struct dp_audio *dp_audio_get(struct platform_device *pdev,
audio->pdev = pdev;
audio->catalog = catalog;
- dp_audio = &audio->dp_audio;
+ msm_dp_audio = &audio->msm_dp_audio;
- dp_catalog_audio_init(catalog);
+ msm_dp_catalog_audio_init(catalog);
- return dp_audio;
+ return msm_dp_audio;
error:
return ERR_PTR(rc);
}
-void dp_audio_put(struct dp_audio *dp_audio)
+void msm_dp_audio_put(struct msm_dp_audio *msm_dp_audio)
{
- struct dp_audio_private *audio;
+ struct msm_dp_audio_private *audio;
- if (!dp_audio)
+ if (!msm_dp_audio)
return;
- audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
+ audio = container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio);
devm_kfree(&audio->pdev->dev, audio);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.h b/drivers/gpu/drm/msm/dp/dp_audio.h
index 4ab78880af82..1c9efaaa40e5 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.h
+++ b/drivers/gpu/drm/msm/dp/dp_audio.h
@@ -13,58 +13,58 @@
#include <sound/hdmi-codec.h>
/**
- * struct dp_audio
+ * struct msm_dp_audio
* @lane_count: number of lanes configured in current session
* @bw_code: link rate's bandwidth code for current session
*/
-struct dp_audio {
+struct msm_dp_audio {
u32 lane_count;
u32 bw_code;
};
/**
- * dp_audio_get()
+ * msm_dp_audio_get()
*
* Creates and instance of dp audio.
*
* @pdev: caller's platform device instance.
- * @panel: an instance of dp_panel module.
- * @catalog: an instance of dp_catalog module.
+ * @panel: an instance of msm_dp_panel module.
+ * @catalog: an instance of msm_dp_catalog module.
*
* Returns the error code in case of failure, otherwize
- * an instance of newly created dp_module.
+ * an instance of newly created msm_dp_module.
*/
-struct dp_audio *dp_audio_get(struct platform_device *pdev,
- struct dp_panel *panel,
- struct dp_catalog *catalog);
+struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev,
+ struct msm_dp_panel *panel,
+ struct msm_dp_catalog *catalog);
/**
- * dp_register_audio_driver()
+ * msm_dp_register_audio_driver()
*
* Registers DP device with hdmi_codec interface.
*
* @dev: DP device instance.
- * @dp_audio: an instance of dp_audio module.
+ * @msm_dp_audio: an instance of msm_dp_audio module.
*
*
* Returns the error code in case of failure, otherwise
* zero on success.
*/
-int dp_register_audio_driver(struct device *dev,
- struct dp_audio *dp_audio);
+int msm_dp_register_audio_driver(struct device *dev,
+ struct msm_dp_audio *msm_dp_audio);
-void dp_unregister_audio_driver(struct device *dev, struct dp_audio *dp_audio);
+void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio);
/**
- * dp_audio_put()
+ * msm_dp_audio_put()
*
- * Cleans the dp_audio instance.
+ * Cleans the msm_dp_audio instance.
*
- * @dp_audio: an instance of dp_audio.
+ * @msm_dp_audio: an instance of msm_dp_audio.
*/
-void dp_audio_put(struct dp_audio *dp_audio);
+void msm_dp_audio_put(struct msm_dp_audio *msm_dp_audio);
-int dp_audio_hw_params(struct device *dev,
+int msm_dp_audio_hw_params(struct device *dev,
void *data,
struct hdmi_codec_daifmt *daifmt,
struct hdmi_codec_params *params);
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 00dfafbebe0e..bc8d46abfc61 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -20,9 +20,9 @@ enum msm_dp_aux_err {
DP_AUX_ERR_PHY,
};
-struct dp_aux_private {
+struct msm_dp_aux_private {
struct device *dev;
- struct dp_catalog *catalog;
+ struct msm_dp_catalog *catalog;
struct phy *phy;
@@ -42,12 +42,12 @@ struct dp_aux_private {
u32 offset;
u32 segment;
- struct drm_dp_aux dp_aux;
+ struct drm_dp_aux msm_dp_aux;
};
#define MAX_AUX_RETRIES 5
-static ssize_t dp_aux_write(struct dp_aux_private *aux,
+static ssize_t msm_dp_aux_write(struct msm_dp_aux_private *aux,
struct drm_dp_aux_msg *msg)
{
u8 data[4];
@@ -88,11 +88,11 @@ static ssize_t dp_aux_write(struct dp_aux_private *aux,
/* index = 0, write */
if (i == 0)
reg |= DP_AUX_DATA_INDEX_WRITE;
- dp_catalog_aux_write_data(aux->catalog, reg);
+ msm_dp_catalog_aux_write_data(aux->catalog, reg);
}
- dp_catalog_aux_clear_trans(aux->catalog, false);
- dp_catalog_aux_clear_hw_interrupts(aux->catalog);
+ msm_dp_catalog_aux_clear_trans(aux->catalog, false);
+ msm_dp_catalog_aux_clear_hw_interrupts(aux->catalog);
reg = 0; /* Transaction number == 1 */
if (!aux->native) { /* i2c */
@@ -106,12 +106,12 @@ static ssize_t dp_aux_write(struct dp_aux_private *aux,
}
reg |= DP_AUX_TRANS_CTRL_GO;
- dp_catalog_aux_write_trans(aux->catalog, reg);
+ msm_dp_catalog_aux_write_trans(aux->catalog, reg);
return len;
}
-static ssize_t dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
+static ssize_t msm_dp_aux_cmd_fifo_tx(struct msm_dp_aux_private *aux,
struct drm_dp_aux_msg *msg)
{
ssize_t ret;
@@ -119,7 +119,7 @@ static ssize_t dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
reinit_completion(&aux->comp);
- ret = dp_aux_write(aux, msg);
+ ret = msm_dp_aux_write(aux, msg);
if (ret < 0)
return ret;
@@ -131,7 +131,7 @@ static ssize_t dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
return ret;
}
-static ssize_t dp_aux_cmd_fifo_rx(struct dp_aux_private *aux,
+static ssize_t msm_dp_aux_cmd_fifo_rx(struct msm_dp_aux_private *aux,
struct drm_dp_aux_msg *msg)
{
u32 data;
@@ -139,20 +139,20 @@ static ssize_t dp_aux_cmd_fifo_rx(struct dp_aux_private *aux,
u32 i, actual_i;
u32 len = msg->size;
- dp_catalog_aux_clear_trans(aux->catalog, true);
+ msm_dp_catalog_aux_clear_trans(aux->catalog, true);
data = DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */
data |= DP_AUX_DATA_READ; /* read */
- dp_catalog_aux_write_data(aux->catalog, data);
+ msm_dp_catalog_aux_write_data(aux->catalog, data);
dp = msg->buffer;
/* discard first byte */
- data = dp_catalog_aux_read_data(aux->catalog);
+ data = msm_dp_catalog_aux_read_data(aux->catalog);
for (i = 0; i < len; i++) {
- data = dp_catalog_aux_read_data(aux->catalog);
+ data = msm_dp_catalog_aux_read_data(aux->catalog);
*dp++ = (u8)((data >> DP_AUX_DATA_OFFSET) & 0xff);
actual_i = (data >> DP_AUX_DATA_INDEX_OFFSET) & 0xFF;
@@ -163,7 +163,7 @@ static ssize_t dp_aux_cmd_fifo_rx(struct dp_aux_private *aux,
return i;
}
-static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
+static void msm_dp_aux_update_offset_and_segment(struct msm_dp_aux_private *aux,
struct drm_dp_aux_msg *input_msg)
{
u32 edid_address = 0x50;
@@ -185,7 +185,7 @@ static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
}
/**
- * dp_aux_transfer_helper() - helper function for EDID read transactions
+ * msm_dp_aux_transfer_helper() - helper function for EDID read transactions
*
* @aux: DP AUX private structure
* @input_msg: input message from DRM upstream APIs
@@ -196,7 +196,7 @@ static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
* This helper function is used to fix EDID reads for non-compliant
* sinks that do not handle the i2c middle-of-transaction flag correctly.
*/
-static void dp_aux_transfer_helper(struct dp_aux_private *aux,
+static void msm_dp_aux_transfer_helper(struct msm_dp_aux_private *aux,
struct drm_dp_aux_msg *input_msg,
bool send_seg)
{
@@ -238,7 +238,7 @@ static void dp_aux_transfer_helper(struct dp_aux_private *aux,
helper_msg.address = segment_address;
helper_msg.buffer = &aux->segment;
helper_msg.size = 1;
- dp_aux_cmd_fifo_tx(aux, &helper_msg);
+ msm_dp_aux_cmd_fifo_tx(aux, &helper_msg);
}
/*
@@ -252,7 +252,7 @@ static void dp_aux_transfer_helper(struct dp_aux_private *aux,
helper_msg.address = input_msg->address;
helper_msg.buffer = &aux->offset;
helper_msg.size = 1;
- dp_aux_cmd_fifo_tx(aux, &helper_msg);
+ msm_dp_aux_cmd_fifo_tx(aux, &helper_msg);
end:
aux->offset += message_size;
@@ -265,15 +265,15 @@ end:
* It will call aux_reset() function to reset the AUX channel,
* if the waiting is timeout.
*/
-static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
+static ssize_t msm_dp_aux_transfer(struct drm_dp_aux *msm_dp_aux,
struct drm_dp_aux_msg *msg)
{
ssize_t ret;
int const aux_cmd_native_max = 16;
int const aux_cmd_i2c_max = 128;
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
@@ -292,7 +292,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
return -EINVAL;
}
- ret = pm_runtime_resume_and_get(dp_aux->dev);
+ ret = pm_runtime_resume_and_get(msm_dp_aux->dev);
if (ret)
return ret;
@@ -313,8 +313,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
goto exit;
}
- dp_aux_update_offset_and_segment(aux, msg);
- dp_aux_transfer_helper(aux, msg, true);
+ msm_dp_aux_update_offset_and_segment(aux, msg);
+ msm_dp_aux_transfer_helper(aux, msg, true);
aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
aux->cmd_busy = true;
@@ -327,7 +327,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
aux->no_send_stop = true;
}
- ret = dp_aux_cmd_fifo_tx(aux, msg);
+ ret = msm_dp_aux_cmd_fifo_tx(aux, msg);
if (ret < 0) {
if (aux->native) {
aux->retry_cnt++;
@@ -335,14 +335,14 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
phy_calibrate(aux->phy);
}
/* reset aux if link is in connected state */
- if (dp_catalog_link_is_connected(aux->catalog))
- dp_catalog_aux_reset(aux->catalog);
+ if (msm_dp_catalog_link_is_connected(aux->catalog))
+ msm_dp_catalog_aux_reset(aux->catalog);
} else {
aux->retry_cnt = 0;
switch (aux->aux_error_num) {
case DP_AUX_ERR_NONE:
if (aux->read)
- ret = dp_aux_cmd_fifo_rx(aux, msg);
+ ret = msm_dp_aux_cmd_fifo_rx(aux, msg);
msg->reply = aux->native ? DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
break;
case DP_AUX_ERR_DEFER:
@@ -364,24 +364,24 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
exit:
mutex_unlock(&aux->mutex);
- pm_runtime_put_sync(dp_aux->dev);
+ pm_runtime_put_sync(msm_dp_aux->dev);
return ret;
}
-irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux)
+irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux)
{
u32 isr;
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- if (!dp_aux) {
+ if (!msm_dp_aux) {
DRM_ERROR("invalid input\n");
return IRQ_NONE;
}
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
- isr = dp_catalog_aux_get_irq(aux->catalog);
+ isr = msm_dp_catalog_aux_get_irq(aux->catalog);
/* no interrupts pending, return immediately */
if (!isr)
@@ -403,7 +403,7 @@ irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux)
if (isr & DP_INTR_AUX_ERROR) {
aux->aux_error_num = DP_AUX_ERR_PHY;
- dp_catalog_aux_clear_hw_interrupts(aux->catalog);
+ msm_dp_catalog_aux_clear_hw_interrupts(aux->catalog);
} else if (isr & DP_INTR_NACK_DEFER) {
aux->aux_error_num = DP_AUX_ERR_NACK_DEFER;
} else if (isr & DP_INTR_WRONG_ADDR) {
@@ -429,68 +429,68 @@ irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux)
return IRQ_HANDLED;
}
-void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled)
+void msm_dp_aux_enable_xfers(struct drm_dp_aux *msm_dp_aux, bool enabled)
{
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
aux->enable_xfers = enabled;
}
-void dp_aux_reconfig(struct drm_dp_aux *dp_aux)
+void msm_dp_aux_reconfig(struct drm_dp_aux *msm_dp_aux)
{
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
phy_calibrate(aux->phy);
- dp_catalog_aux_reset(aux->catalog);
+ msm_dp_catalog_aux_reset(aux->catalog);
}
-void dp_aux_init(struct drm_dp_aux *dp_aux)
+void msm_dp_aux_init(struct drm_dp_aux *msm_dp_aux)
{
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- if (!dp_aux) {
+ if (!msm_dp_aux) {
DRM_ERROR("invalid input\n");
return;
}
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
mutex_lock(&aux->mutex);
- dp_catalog_aux_enable(aux->catalog, true);
+ msm_dp_catalog_aux_enable(aux->catalog, true);
aux->retry_cnt = 0;
aux->initted = true;
mutex_unlock(&aux->mutex);
}
-void dp_aux_deinit(struct drm_dp_aux *dp_aux)
+void msm_dp_aux_deinit(struct drm_dp_aux *msm_dp_aux)
{
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
mutex_lock(&aux->mutex);
aux->initted = false;
- dp_catalog_aux_enable(aux->catalog, false);
+ msm_dp_catalog_aux_enable(aux->catalog, false);
mutex_unlock(&aux->mutex);
}
-int dp_aux_register(struct drm_dp_aux *dp_aux)
+int msm_dp_aux_register(struct drm_dp_aux *msm_dp_aux)
{
int ret;
- if (!dp_aux) {
+ if (!msm_dp_aux) {
DRM_ERROR("invalid input\n");
return -EINVAL;
}
- ret = drm_dp_aux_register(dp_aux);
+ ret = drm_dp_aux_register(msm_dp_aux);
if (ret) {
DRM_ERROR("%s: failed to register drm aux: %d\n", __func__,
ret);
@@ -500,34 +500,34 @@ int dp_aux_register(struct drm_dp_aux *dp_aux)
return 0;
}
-void dp_aux_unregister(struct drm_dp_aux *dp_aux)
+void msm_dp_aux_unregister(struct drm_dp_aux *msm_dp_aux)
{
- drm_dp_aux_unregister(dp_aux);
+ drm_dp_aux_unregister(msm_dp_aux);
}
-static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux,
+static int msm_dp_wait_hpd_asserted(struct drm_dp_aux *msm_dp_aux,
unsigned long wait_us)
{
int ret;
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
ret = pm_runtime_resume_and_get(aux->dev);
if (ret)
return ret;
- ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog, wait_us);
+ ret = msm_dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog, wait_us);
pm_runtime_put_sync(aux->dev);
return ret;
}
-struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
+struct drm_dp_aux *msm_dp_aux_get(struct device *dev, struct msm_dp_catalog *catalog,
struct phy *phy,
bool is_edp)
{
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
if (!catalog) {
DRM_ERROR("invalid input\n");
@@ -553,23 +553,23 @@ struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
* before registering AUX with the DRM device so that
* msm eDP panel can be detected by generic_dep_panel_probe().
*/
- aux->dp_aux.name = "dpu_dp_aux";
- aux->dp_aux.dev = dev;
- aux->dp_aux.transfer = dp_aux_transfer;
- aux->dp_aux.wait_hpd_asserted = dp_wait_hpd_asserted;
- drm_dp_aux_init(&aux->dp_aux);
+ aux->msm_dp_aux.name = "dpu_dp_aux";
+ aux->msm_dp_aux.dev = dev;
+ aux->msm_dp_aux.transfer = msm_dp_aux_transfer;
+ aux->msm_dp_aux.wait_hpd_asserted = msm_dp_wait_hpd_asserted;
+ drm_dp_aux_init(&aux->msm_dp_aux);
- return &aux->dp_aux;
+ return &aux->msm_dp_aux;
}
-void dp_aux_put(struct drm_dp_aux *dp_aux)
+void msm_dp_aux_put(struct drm_dp_aux *msm_dp_aux)
{
- struct dp_aux_private *aux;
+ struct msm_dp_aux_private *aux;
- if (!dp_aux)
+ if (!msm_dp_aux)
return;
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+ aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);
mutex_destroy(&aux->mutex);
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h
index 4f65e892a807..39c5b4c8596a 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.h
+++ b/drivers/gpu/drm/msm/dp/dp_aux.h
@@ -9,18 +9,18 @@
#include "dp_catalog.h"
#include <drm/display/drm_dp_helper.h>
-int dp_aux_register(struct drm_dp_aux *dp_aux);
-void dp_aux_unregister(struct drm_dp_aux *dp_aux);
-irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux);
-void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled);
-void dp_aux_init(struct drm_dp_aux *dp_aux);
-void dp_aux_deinit(struct drm_dp_aux *dp_aux);
-void dp_aux_reconfig(struct drm_dp_aux *dp_aux);
+int msm_dp_aux_register(struct drm_dp_aux *msm_dp_aux);
+void msm_dp_aux_unregister(struct drm_dp_aux *msm_dp_aux);
+irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux);
+void msm_dp_aux_enable_xfers(struct drm_dp_aux *msm_dp_aux, bool enabled);
+void msm_dp_aux_init(struct drm_dp_aux *msm_dp_aux);
+void msm_dp_aux_deinit(struct drm_dp_aux *msm_dp_aux);
+void msm_dp_aux_reconfig(struct drm_dp_aux *msm_dp_aux);
struct phy;
-struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
+struct drm_dp_aux *msm_dp_aux_get(struct device *dev, struct msm_dp_catalog *catalog,
struct phy *phy,
bool is_edp);
-void dp_aux_put(struct drm_dp_aux *aux);
+void msm_dp_aux_put(struct drm_dp_aux *aux);
#endif /*__DP_AUX_H_*/
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 6e55cbf69674..b4c8856fb25d 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -75,18 +75,18 @@ struct dss_io_data {
struct dss_io_region p0;
};
-struct dp_catalog_private {
+struct msm_dp_catalog_private {
struct device *dev;
struct drm_device *drm_dev;
struct dss_io_data io;
u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX];
- struct dp_catalog dp_catalog;
+ struct msm_dp_catalog msm_dp_catalog;
};
-void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *disp_state)
+void msm_dp_catalog_snapshot(struct msm_dp_catalog *msm_dp_catalog, struct msm_disp_state *disp_state)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
struct dss_io_data *dss = &catalog->io;
msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb");
@@ -95,12 +95,12 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d
msm_disp_snapshot_add_block(disp_state, dss->p0.len, dss->p0.base, "dp_p0");
}
-static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset)
+static inline u32 msm_dp_read_aux(struct msm_dp_catalog_private *catalog, u32 offset)
{
return readl_relaxed(catalog->io.aux.base + offset);
}
-static inline void dp_write_aux(struct dp_catalog_private *catalog,
+static inline void msm_dp_write_aux(struct msm_dp_catalog_private *catalog,
u32 offset, u32 data)
{
/*
@@ -110,12 +110,12 @@ static inline void dp_write_aux(struct dp_catalog_private *catalog,
writel(data, catalog->io.aux.base + offset);
}
-static inline u32 dp_read_ahb(const struct dp_catalog_private *catalog, u32 offset)
+static inline u32 msm_dp_read_ahb(const struct msm_dp_catalog_private *catalog, u32 offset)
{
return readl_relaxed(catalog->io.ahb.base + offset);
}
-static inline void dp_write_ahb(struct dp_catalog_private *catalog,
+static inline void msm_dp_write_ahb(struct msm_dp_catalog_private *catalog,
u32 offset, u32 data)
{
/*
@@ -125,7 +125,7 @@ static inline void dp_write_ahb(struct dp_catalog_private *catalog,
writel(data, catalog->io.ahb.base + offset);
}
-static inline void dp_write_p0(struct dp_catalog_private *catalog,
+static inline void msm_dp_write_p0(struct msm_dp_catalog_private *catalog,
u32 offset, u32 data)
{
/*
@@ -135,7 +135,7 @@ static inline void dp_write_p0(struct dp_catalog_private *catalog,
writel(data, catalog->io.p0.base + offset);
}
-static inline u32 dp_read_p0(struct dp_catalog_private *catalog,
+static inline u32 msm_dp_read_p0(struct msm_dp_catalog_private *catalog,
u32 offset)
{
/*
@@ -145,12 +145,12 @@ static inline u32 dp_read_p0(struct dp_catalog_private *catalog,
return readl_relaxed(catalog->io.p0.base + offset);
}
-static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset)
+static inline u32 msm_dp_read_link(struct msm_dp_catalog_private *catalog, u32 offset)
{
return readl_relaxed(catalog->io.link.base + offset);
}
-static inline void dp_write_link(struct dp_catalog_private *catalog,
+static inline void msm_dp_write_link(struct msm_dp_catalog_private *catalog,
u32 offset, u32 data)
{
/*
@@ -161,64 +161,64 @@ static inline void dp_write_link(struct dp_catalog_private *catalog,
}
/* aux related catalog functions */
-u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog)
+u32 msm_dp_catalog_aux_read_data(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- return dp_read_aux(catalog, REG_DP_AUX_DATA);
+ return msm_dp_read_aux(catalog, REG_DP_AUX_DATA);
}
-int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog, u32 data)
+int msm_dp_catalog_aux_write_data(struct msm_dp_catalog *msm_dp_catalog, u32 data)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- dp_write_aux(catalog, REG_DP_AUX_DATA, data);
+ msm_dp_write_aux(catalog, REG_DP_AUX_DATA, data);
return 0;
}
-int dp_catalog_aux_write_trans(struct dp_catalog *dp_catalog, u32 data)
+int msm_dp_catalog_aux_write_trans(struct msm_dp_catalog *msm_dp_catalog, u32 data)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data);
+ msm_dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data);
return 0;
}
-int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read)
+int msm_dp_catalog_aux_clear_trans(struct msm_dp_catalog *msm_dp_catalog, bool read)
{
u32 data;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
if (read) {
- data = dp_read_aux(catalog, REG_DP_AUX_TRANS_CTRL);
+ data = msm_dp_read_aux(catalog, REG_DP_AUX_TRANS_CTRL);
data &= ~DP_AUX_TRANS_CTRL_GO;
- dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data);
+ msm_dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data);
} else {
- dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, 0);
+ msm_dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, 0);
}
return 0;
}
-int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog)
+int msm_dp_catalog_aux_clear_hw_interrupts(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- dp_read_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_STATUS);
- dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f);
- dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f);
- dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0);
+ msm_dp_read_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_STATUS);
+ msm_dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f);
+ msm_dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f);
+ msm_dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0);
return 0;
}
/**
- * dp_catalog_aux_reset() - reset AUX controller
+ * msm_dp_catalog_aux_reset() - reset AUX controller
*
- * @dp_catalog: DP catalog structure
+ * @msm_dp_catalog: DP catalog structure
*
* return: void
*
@@ -227,47 +227,47 @@ int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog)
* NOTE: reset AUX controller will also clear any pending HPD related interrupts
*
*/
-void dp_catalog_aux_reset(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_aux_reset(struct msm_dp_catalog *msm_dp_catalog)
{
u32 aux_ctrl;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL);
+ aux_ctrl = msm_dp_read_aux(catalog, REG_DP_AUX_CTRL);
aux_ctrl |= DP_AUX_CTRL_RESET;
- dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
+ msm_dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
usleep_range(1000, 1100); /* h/w recommended delay */
aux_ctrl &= ~DP_AUX_CTRL_RESET;
- dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
+ msm_dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
}
-void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable)
+void msm_dp_catalog_aux_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable)
{
u32 aux_ctrl;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL);
+ aux_ctrl = msm_dp_read_aux(catalog, REG_DP_AUX_CTRL);
if (enable) {
- dp_write_aux(catalog, REG_DP_TIMEOUT_COUNT, 0xffff);
- dp_write_aux(catalog, REG_DP_AUX_LIMITS, 0xffff);
+ msm_dp_write_aux(catalog, REG_DP_TIMEOUT_COUNT, 0xffff);
+ msm_dp_write_aux(catalog, REG_DP_AUX_LIMITS, 0xffff);
aux_ctrl |= DP_AUX_CTRL_ENABLE;
} else {
aux_ctrl &= ~DP_AUX_CTRL_ENABLE;
}
- dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
+ msm_dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
}
-int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog,
+int msm_dp_catalog_aux_wait_for_hpd_connect_state(struct msm_dp_catalog *msm_dp_catalog,
unsigned long wait_us)
{
u32 state;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
/* poll for hpd connected status every 2ms and timeout after wait_us */
return readl_poll_timeout(catalog->io.aux.base +
@@ -294,10 +294,10 @@ static void dump_regs(void __iomem *base, int len)
}
}
-void dp_catalog_dump_regs(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_dump_regs(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
struct dss_io_data *io = &catalog->io;
pr_info("AHB regs\n");
@@ -313,17 +313,17 @@ void dp_catalog_dump_regs(struct dp_catalog *dp_catalog)
dump_regs(io->p0.base, io->p0.len);
}
-u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog)
+u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 intr, intr_ack;
- intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS);
+ intr = msm_dp_read_ahb(catalog, REG_DP_INTR_STATUS);
intr &= ~DP_INTERRUPT_STATUS1_MASK;
intr_ack = (intr & DP_INTERRUPT_STATUS1)
<< DP_INTERRUPT_STATUS_ACK_SHIFT;
- dp_write_ahb(catalog, REG_DP_INTR_STATUS, intr_ack |
+ msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS, intr_ack |
DP_INTERRUPT_STATUS1_MASK);
return intr;
@@ -331,40 +331,40 @@ u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog)
}
/* controller related catalog functions */
-void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog,
- u32 dp_tu, u32 valid_boundary,
+void msm_dp_catalog_ctrl_update_transfer_unit(struct msm_dp_catalog *msm_dp_catalog,
+ u32 msm_dp_tu, u32 valid_boundary,
u32 valid_boundary2)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- dp_write_link(catalog, REG_DP_VALID_BOUNDARY, valid_boundary);
- dp_write_link(catalog, REG_DP_TU, dp_tu);
- dp_write_link(catalog, REG_DP_VALID_BOUNDARY_2, valid_boundary2);
+ msm_dp_write_link(catalog, REG_DP_VALID_BOUNDARY, valid_boundary);
+ msm_dp_write_link(catalog, REG_DP_TU, msm_dp_tu);
+ msm_dp_write_link(catalog, REG_DP_VALID_BOUNDARY_2, valid_boundary2);
}
-void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 state)
+void msm_dp_catalog_ctrl_state_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 state)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- dp_write_link(catalog, REG_DP_STATE_CTRL, state);
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL, state);
}
-void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 cfg)
+void msm_dp_catalog_ctrl_config_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 cfg)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
drm_dbg_dp(catalog->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", cfg);
- dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg);
+ msm_dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg);
}
-void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */
u32 ln_mapping;
@@ -373,71 +373,71 @@ void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog)
ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT;
ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT;
- dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING,
+ msm_dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING,
ln_mapping);
}
-void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_ctrl_psr_mainlink_enable(struct msm_dp_catalog *msm_dp_catalog,
bool enable)
{
u32 val;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- val = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+ val = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
if (enable)
val |= DP_MAINLINK_CTRL_ENABLE;
else
val &= ~DP_MAINLINK_CTRL_ENABLE;
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val);
}
-void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_ctrl_mainlink_ctrl(struct msm_dp_catalog *msm_dp_catalog,
bool enable)
{
u32 mainlink_ctrl;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
drm_dbg_dp(catalog->drm_dev, "enable=%d\n", enable);
if (enable) {
/*
* To make sure link reg writes happens before other operation,
- * dp_write_link() function uses writel()
+ * msm_dp_write_link() function uses writel()
*/
- mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+ mainlink_ctrl = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET |
DP_MAINLINK_CTRL_ENABLE);
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
mainlink_ctrl |= DP_MAINLINK_CTRL_RESET;
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET;
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE |
DP_MAINLINK_FB_BOUNDARY_SEL);
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
} else {
- mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+ mainlink_ctrl = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE;
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
}
}
-void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_ctrl_config_misc(struct msm_dp_catalog *msm_dp_catalog,
u32 colorimetry_cfg,
u32 test_bits_depth)
{
u32 misc_val;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- misc_val = dp_read_link(catalog, REG_DP_MISC1_MISC0);
+ misc_val = msm_dp_read_link(catalog, REG_DP_MISC1_MISC0);
/* clear bpp bits */
misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT);
@@ -447,27 +447,27 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog,
misc_val |= DP_MISC0_SYNCHRONOUS_CLK;
drm_dbg_dp(catalog->drm_dev, "misc settings = 0x%x\n", misc_val);
- dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
+ msm_dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
}
-void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_setup_peripheral_flush(struct msm_dp_catalog *msm_dp_catalog)
{
u32 mainlink_ctrl, hw_revision;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+ mainlink_ctrl = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
- hw_revision = dp_catalog_hw_revision(dp_catalog);
+ hw_revision = msm_dp_catalog_hw_revision(msm_dp_catalog);
if (hw_revision >= DP_HW_VERSION_1_2)
mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
else
mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
}
-void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_ctrl_config_msa(struct msm_dp_catalog *msm_dp_catalog,
u32 rate, u32 stream_rate_khz,
bool is_ycbcr_420)
{
@@ -478,8 +478,8 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
u32 const link_rate_hbr3 = 810000;
unsigned long den, num;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
if (rate == link_rate_hbr3)
pixel_div = 6;
@@ -522,22 +522,22 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
nvid *= 3;
drm_dbg_dp(catalog->drm_dev, "mvid=0x%x, nvid=0x%x\n", mvid, nvid);
- dp_write_link(catalog, REG_DP_SOFTWARE_MVID, mvid);
- dp_write_link(catalog, REG_DP_SOFTWARE_NVID, nvid);
- dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0);
+ msm_dp_write_link(catalog, REG_DP_SOFTWARE_MVID, mvid);
+ msm_dp_write_link(catalog, REG_DP_SOFTWARE_NVID, nvid);
+ msm_dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0);
}
-int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
+int msm_dp_catalog_ctrl_set_pattern_state_bit(struct msm_dp_catalog *msm_dp_catalog,
u32 state_bit)
{
int bit, ret;
u32 data;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
bit = BIT(state_bit - 1);
drm_dbg_dp(catalog->drm_dev, "hw: bit=%d train=%d\n", bit, state_bit);
- dp_catalog_ctrl_state_ctrl(dp_catalog, bit);
+ msm_dp_catalog_ctrl_state_ctrl(msm_dp_catalog, bit);
bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;
@@ -554,25 +554,25 @@ int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
}
/**
- * dp_catalog_hw_revision() - retrieve DP hw revision
+ * msm_dp_catalog_hw_revision() - retrieve DP hw revision
*
- * @dp_catalog: DP catalog structure
+ * @msm_dp_catalog: DP catalog structure
*
* Return: DP controller hw revision
*
*/
-u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog)
+u32 msm_dp_catalog_hw_revision(const struct msm_dp_catalog *msm_dp_catalog)
{
- const struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ const struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- return dp_read_ahb(catalog, REG_DP_HW_VERSION);
+ return msm_dp_read_ahb(catalog, REG_DP_HW_VERSION);
}
/**
- * dp_catalog_ctrl_reset() - reset DP controller
+ * msm_dp_catalog_ctrl_reset() - reset DP controller
*
- * @dp_catalog: DP catalog structure
+ * @msm_dp_catalog: DP catalog structure
*
* return: void
*
@@ -581,28 +581,28 @@ u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog)
* NOTE: reset DP controller will also clear any pending HPD related interrupts
*
*/
-void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_ctrl_reset(struct msm_dp_catalog *msm_dp_catalog)
{
u32 sw_reset;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- sw_reset = dp_read_ahb(catalog, REG_DP_SW_RESET);
+ sw_reset = msm_dp_read_ahb(catalog, REG_DP_SW_RESET);
sw_reset |= DP_SW_RESET;
- dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset);
+ msm_dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset);
usleep_range(1000, 1100); /* h/w recommended delay */
sw_reset &= ~DP_SW_RESET;
- dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset);
+ msm_dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset);
}
-bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog)
+bool msm_dp_catalog_ctrl_mainlink_ready(struct msm_dp_catalog *msm_dp_catalog)
{
u32 data;
int ret;
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
/* Poll for mainlink ready status */
ret = readl_poll_timeout(catalog->io.link.base +
@@ -617,96 +617,96 @@ bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog)
return true;
}
-void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_ctrl_enable_irq(struct msm_dp_catalog *msm_dp_catalog,
bool enable)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
if (enable) {
- dp_write_ahb(catalog, REG_DP_INTR_STATUS,
+ msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS,
DP_INTERRUPT_STATUS1_MASK);
- dp_write_ahb(catalog, REG_DP_INTR_STATUS2,
+ msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS2,
DP_INTERRUPT_STATUS2_MASK);
} else {
- dp_write_ahb(catalog, REG_DP_INTR_STATUS, 0x00);
- dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 0x00);
+ msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS, 0x00);
+ msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 0x00);
}
}
-void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_hpd_config_intr(struct msm_dp_catalog *msm_dp_catalog,
u32 intr_mask, bool en)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- u32 config = dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK);
+ u32 config = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK);
config = (en ? config | intr_mask : config & ~intr_mask);
drm_dbg_dp(catalog->drm_dev, "intr_mask=%#x config=%#x\n",
intr_mask, config);
- dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK,
+ msm_dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK,
config & DP_DP_HPD_INT_MASK);
}
-void dp_catalog_ctrl_hpd_enable(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_ctrl_hpd_enable(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER);
+ u32 reftimer = msm_dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER);
/* Configure REFTIMER and enable it */
reftimer |= DP_DP_HPD_REFTIMER_ENABLE;
- dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer);
+ msm_dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer);
/* Enable HPD */
- dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
+ msm_dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
}
-void dp_catalog_ctrl_hpd_disable(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_ctrl_hpd_disable(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER);
+ u32 reftimer = msm_dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER);
reftimer &= ~DP_DP_HPD_REFTIMER_ENABLE;
- dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer);
+ msm_dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer);
- dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, 0);
+ msm_dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, 0);
}
-static void dp_catalog_enable_sdp(struct dp_catalog_private *catalog)
+static void msm_dp_catalog_enable_sdp(struct msm_dp_catalog_private *catalog)
{
/* trigger sdp */
- dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
- dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x0);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x0);
}
-void dp_catalog_ctrl_config_psr(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_ctrl_config_psr(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 config;
/* enable PSR1 function */
- config = dp_read_link(catalog, REG_PSR_CONFIG);
+ config = msm_dp_read_link(catalog, REG_PSR_CONFIG);
config |= PSR1_SUPPORTED;
- dp_write_link(catalog, REG_PSR_CONFIG, config);
+ msm_dp_write_link(catalog, REG_PSR_CONFIG, config);
- dp_write_ahb(catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
- dp_catalog_enable_sdp(catalog);
+ msm_dp_write_ahb(catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
+ msm_dp_catalog_enable_sdp(catalog);
}
-void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter)
+void msm_dp_catalog_ctrl_set_psr(struct msm_dp_catalog *msm_dp_catalog, bool enter)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 cmd;
- cmd = dp_read_link(catalog, REG_PSR_CMD);
+ cmd = msm_dp_read_link(catalog, REG_PSR_CMD);
cmd &= ~(PSR_ENTER | PSR_EXIT);
@@ -715,17 +715,17 @@ void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter)
else
cmd |= PSR_EXIT;
- dp_catalog_enable_sdp(catalog);
- dp_write_link(catalog, REG_PSR_CMD, cmd);
+ msm_dp_catalog_enable_sdp(catalog);
+ msm_dp_write_link(catalog, REG_PSR_CMD, cmd);
}
-u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
+u32 msm_dp_catalog_link_is_connected(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 status;
- status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
+ status = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
drm_dbg_dp(catalog->drm_dev, "aux status: %#x\n", status);
status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT;
status &= DP_DP_HPD_STATE_STATUS_BITS_MASK;
@@ -733,16 +733,16 @@ u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
return status;
}
-u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog)
+u32 msm_dp_catalog_hpd_get_intr_status(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
int isr, mask;
- isr = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
- dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK,
+ isr = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
+ msm_dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK,
(isr & DP_DP_HPD_INT_MASK));
- mask = dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK);
+ mask = msm_dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK);
/*
* We only want to return interrupts that are unmasked to the caller.
@@ -754,115 +754,115 @@ u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog)
return isr & (mask | ~DP_DP_HPD_INT_MASK);
}
-u32 dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog *dp_catalog)
+u32 msm_dp_catalog_ctrl_read_psr_interrupt_status(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 intr, intr_ack;
- intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS4);
+ intr = msm_dp_read_ahb(catalog, REG_DP_INTR_STATUS4);
intr_ack = (intr & DP_INTERRUPT_STATUS4)
<< DP_INTERRUPT_STATUS_ACK_SHIFT;
- dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack);
+ msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack);
return intr;
}
-int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog)
+int msm_dp_catalog_ctrl_get_interrupt(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 intr, intr_ack;
- intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS2);
+ intr = msm_dp_read_ahb(catalog, REG_DP_INTR_STATUS2);
intr &= ~DP_INTERRUPT_STATUS2_MASK;
intr_ack = (intr & DP_INTERRUPT_STATUS2)
<< DP_INTERRUPT_STATUS_ACK_SHIFT;
- dp_write_ahb(catalog, REG_DP_INTR_STATUS2,
+ msm_dp_write_ahb(catalog, REG_DP_INTR_STATUS2,
intr_ack | DP_INTERRUPT_STATUS2_MASK);
return intr;
}
-void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_ctrl_phy_reset(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- dp_write_ahb(catalog, REG_DP_PHY_CTRL,
+ msm_dp_write_ahb(catalog, REG_DP_PHY_CTRL,
DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL);
usleep_range(1000, 1100); /* h/w recommended delay */
- dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0);
+ msm_dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0);
}
-void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_ctrl_send_phy_pattern(struct msm_dp_catalog *msm_dp_catalog,
u32 pattern)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 value = 0x0;
/* Make sure to clear the current pattern before starting a new one */
- dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0);
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0);
drm_dbg_dp(catalog->drm_dev, "pattern: %#x\n", pattern);
switch (pattern) {
case DP_PHY_TEST_PATTERN_D10_2:
- dp_write_link(catalog, REG_DP_STATE_CTRL,
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_TRAINING_PATTERN1);
break;
case DP_PHY_TEST_PATTERN_ERROR_COUNT:
value &= ~(1 << 16);
- dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
+ msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
value |= SCRAMBLER_RESET_COUNT_VALUE;
- dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
+ msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
- dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
- dp_write_link(catalog, REG_DP_STATE_CTRL,
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
break;
case DP_PHY_TEST_PATTERN_PRBS7:
- dp_write_link(catalog, REG_DP_STATE_CTRL,
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_PRBS7);
break;
case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
- dp_write_link(catalog, REG_DP_STATE_CTRL,
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN);
/* 00111110000011111000001111100000 */
- dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0,
+ msm_dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0,
0x3E0F83E0);
/* 00001111100000111110000011111000 */
- dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1,
+ msm_dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1,
0x0F83E0F8);
/* 1111100000111110 */
- dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2,
+ msm_dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2,
0x0000F83E);
break;
case DP_PHY_TEST_PATTERN_CP2520:
- value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+ value = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER;
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);
value = DP_HBR2_ERM_PATTERN;
- dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
+ msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
value |= SCRAMBLER_RESET_COUNT_VALUE;
- dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
+ msm_dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
- dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
- dp_write_link(catalog, REG_DP_STATE_CTRL,
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
- value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+ value = msm_dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
value |= DP_MAINLINK_CTRL_ENABLE;
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);
break;
case DP_PHY_TEST_PATTERN_SEL_MASK:
- dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
DP_MAINLINK_CTRL_ENABLE);
- dp_write_link(catalog, REG_DP_STATE_CTRL,
+ msm_dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_TRAINING_PATTERN4);
break;
default:
@@ -872,94 +872,94 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
}
}
-u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog)
+u32 msm_dp_catalog_ctrl_read_phy_pattern(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- return dp_read_link(catalog, REG_DP_MAINLINK_READY);
+ return msm_dp_read_link(catalog, REG_DP_MAINLINK_READY);
}
/* panel related catalog functions */
-int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog, u32 total,
- u32 sync_start, u32 width_blanking, u32 dp_active)
+int msm_dp_catalog_panel_timing_cfg(struct msm_dp_catalog *msm_dp_catalog, u32 total,
+ u32 sync_start, u32 width_blanking, u32 msm_dp_active)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 reg;
- dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, total);
- dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC, sync_start);
- dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, width_blanking);
- dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_active);
+ msm_dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, total);
+ msm_dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC, sync_start);
+ msm_dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, width_blanking);
+ msm_dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, msm_dp_active);
- reg = dp_read_p0(catalog, MMSS_DP_INTF_CONFIG);
+ reg = msm_dp_read_p0(catalog, MMSS_DP_INTF_CONFIG);
- if (dp_catalog->wide_bus_en)
+ if (msm_dp_catalog->wide_bus_en)
reg |= DP_INTF_CONFIG_DATABUS_WIDEN;
else
reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN;
- DRM_DEBUG_DP("wide_bus_en=%d reg=%#x\n", dp_catalog->wide_bus_en, reg);
+ DRM_DEBUG_DP("wide_bus_en=%d reg=%#x\n", msm_dp_catalog->wide_bus_en, reg);
- dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg);
return 0;
}
-static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog, struct dp_sdp *vsc_sdp)
+static void msm_dp_catalog_panel_send_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog, struct dp_sdp *vsc_sdp)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 header[2];
u32 val;
int i;
- catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog);
- dp_utils_pack_sdp_header(&vsc_sdp->sdp_header, header);
+ msm_dp_utils_pack_sdp_header(&vsc_sdp->sdp_header, header);
- dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]);
- dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]);
+ msm_dp_write_link(catalog, MMSS_DP_GENERIC0_0, header[0]);
+ msm_dp_write_link(catalog, MMSS_DP_GENERIC0_1, header[1]);
for (i = 0; i < sizeof(vsc_sdp->db); i += 4) {
val = ((vsc_sdp->db[i]) | (vsc_sdp->db[i + 1] << 8) | (vsc_sdp->db[i + 2] << 16) |
(vsc_sdp->db[i + 3] << 24));
- dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val);
+ msm_dp_write_link(catalog, MMSS_DP_GENERIC0_2 + i, val);
}
}
-static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
+static void msm_dp_catalog_panel_update_sdp(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 hw_revision;
- catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog);
- hw_revision = dp_catalog_hw_revision(dp_catalog);
+ hw_revision = msm_dp_catalog_hw_revision(msm_dp_catalog);
if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) {
- dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
- dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
}
}
-void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog, struct dp_sdp *vsc_sdp)
+void msm_dp_catalog_panel_enable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog, struct dp_sdp *vsc_sdp)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 cfg, cfg2, misc;
- catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog);
- cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
- cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
- misc = dp_read_link(catalog, REG_DP_MISC1_MISC0);
+ cfg = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG);
+ cfg2 = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG2);
+ misc = msm_dp_read_link(catalog, REG_DP_MISC1_MISC0);
cfg |= GEN0_SDP_EN;
- dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
cfg2 |= GENERIC0_SDPSIZE_VALID;
- dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
- dp_catalog_panel_send_vsc_sdp(dp_catalog, vsc_sdp);
+ msm_dp_catalog_panel_send_vsc_sdp(msm_dp_catalog, vsc_sdp);
/* indicates presence of VSC (BIT(6) of MISC1) */
misc |= DP_MISC1_VSC_SDP;
@@ -967,27 +967,27 @@ void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog, struct dp_sd
drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n");
pr_debug("misc settings = 0x%x\n", misc);
- dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
+ msm_dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
- dp_catalog_panel_update_sdp(dp_catalog);
+ msm_dp_catalog_panel_update_sdp(msm_dp_catalog);
}
-void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_panel_disable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 cfg, cfg2, misc;
- catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog, struct msm_dp_catalog_private, msm_dp_catalog);
- cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
- cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
- misc = dp_read_link(catalog, REG_DP_MISC1_MISC0);
+ cfg = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG);
+ cfg2 = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG2);
+ misc = msm_dp_read_link(catalog, REG_DP_MISC1_MISC0);
cfg &= ~GEN0_SDP_EN;
- dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
cfg2 &= ~GENERIC0_SDPSIZE_VALID;
- dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
/* switch back to MSA */
misc &= ~DP_MISC1_VSC_SDP;
@@ -995,16 +995,16 @@ void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=0\n");
pr_debug("misc settings = 0x%x\n", misc);
- dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
+ msm_dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
- dp_catalog_panel_update_sdp(dp_catalog);
+ msm_dp_catalog_panel_update_sdp(msm_dp_catalog);
}
-void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_panel_tpg_enable(struct msm_dp_catalog *msm_dp_catalog,
struct drm_display_mode *drm_mode)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
u32 hsync_period, vsync_period;
u32 display_v_start, display_v_end;
u32 hsync_start_x, hsync_end_x;
@@ -1036,49 +1036,49 @@ void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
display_hctl = (hsync_end_x << 16) | hsync_start_x;
- dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0);
- dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl);
- dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period *
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period *
hsync_period);
- dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width *
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width *
hsync_period);
- dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl);
- dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0);
- dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start);
- dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end);
- dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0);
- dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0);
-
- dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL,
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0);
+ msm_dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end);
+ msm_dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0);
+ msm_dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0);
+
+ msm_dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL,
DP_TPG_CHECKERED_RECT_PATTERN);
- dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG,
+ msm_dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG,
DP_TPG_VIDEO_CONFIG_BPP_8BIT |
DP_TPG_VIDEO_CONFIG_RGB);
- dp_write_p0(catalog, MMSS_DP_BIST_ENABLE,
+ msm_dp_write_p0(catalog, MMSS_DP_BIST_ENABLE,
DP_BIST_ENABLE_DPBIST_EN);
- dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN,
+ msm_dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN,
DP_TIMING_ENGINE_EN_EN);
drm_dbg_dp(catalog->drm_dev, "%s: enabled tpg\n", __func__);
}
-void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_panel_tpg_disable(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ struct msm_dp_catalog_private *catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0);
- dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0);
- dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0);
+ msm_dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0);
+ msm_dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0);
+ msm_dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0);
}
-static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
+static void __iomem *msm_dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
{
struct resource *res;
void __iomem *base;
@@ -1090,21 +1090,21 @@ static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *l
return base;
}
-static int dp_catalog_get_io(struct dp_catalog_private *catalog)
+static int msm_dp_catalog_get_io(struct msm_dp_catalog_private *catalog)
{
struct platform_device *pdev = to_platform_device(catalog->dev);
struct dss_io_data *dss = &catalog->io;
- dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
+ dss->ahb.base = msm_dp_ioremap(pdev, 0, &dss->ahb.len);
if (IS_ERR(dss->ahb.base))
return PTR_ERR(dss->ahb.base);
- dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
+ dss->aux.base = msm_dp_ioremap(pdev, 1, &dss->aux.len);
if (IS_ERR(dss->aux.base)) {
/*
* The initial binding had a single reg, but in order to
* support variation in the sub-region sizes this was split.
- * dp_ioremap() will fail with -EINVAL here if only a single
+ * msm_dp_ioremap() will fail with -EINVAL here if only a single
* reg is specified, so fill in the sub-region offsets and
* lengths based on this single region.
*/
@@ -1126,13 +1126,13 @@ static int dp_catalog_get_io(struct dp_catalog_private *catalog)
return PTR_ERR(dss->aux.base);
}
} else {
- dss->link.base = dp_ioremap(pdev, 2, &dss->link.len);
+ dss->link.base = msm_dp_ioremap(pdev, 2, &dss->link.len);
if (IS_ERR(dss->link.base)) {
DRM_ERROR("unable to remap link region: %pe\n", dss->link.base);
return PTR_ERR(dss->link.base);
}
- dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len);
+ dss->p0.base = msm_dp_ioremap(pdev, 3, &dss->p0.len);
if (IS_ERR(dss->p0.base)) {
DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base);
return PTR_ERR(dss->p0.base);
@@ -1142,9 +1142,9 @@ static int dp_catalog_get_io(struct dp_catalog_private *catalog)
return 0;
}
-struct dp_catalog *dp_catalog_get(struct device *dev)
+struct msm_dp_catalog *msm_dp_catalog_get(struct device *dev)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
int ret;
catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL);
@@ -1153,78 +1153,78 @@ struct dp_catalog *dp_catalog_get(struct device *dev)
catalog->dev = dev;
- ret = dp_catalog_get_io(catalog);
+ ret = msm_dp_catalog_get_io(catalog);
if (ret)
return ERR_PTR(ret);
- return &catalog->dp_catalog;
+ return &catalog->msm_dp_catalog;
}
-u32 dp_catalog_audio_get_header(struct dp_catalog *dp_catalog,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header)
+u32 msm_dp_catalog_audio_get_header(struct msm_dp_catalog *msm_dp_catalog,
+ enum msm_dp_catalog_audio_sdp_type sdp,
+ enum msm_dp_catalog_audio_header_type header)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX];
- catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
sdp_map = catalog->audio_map;
- return dp_read_link(catalog, sdp_map[sdp][header]);
+ return msm_dp_read_link(catalog, sdp_map[sdp][header]);
}
-void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header,
+void msm_dp_catalog_audio_set_header(struct msm_dp_catalog *msm_dp_catalog,
+ enum msm_dp_catalog_audio_sdp_type sdp,
+ enum msm_dp_catalog_audio_header_type header,
u32 data)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX];
- if (!dp_catalog)
+ if (!msm_dp_catalog)
return;
- catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
sdp_map = catalog->audio_map;
- dp_write_link(catalog, sdp_map[sdp][header], data);
+ msm_dp_write_link(catalog, sdp_map[sdp][header], data);
}
-void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog, u32 select)
+void msm_dp_catalog_audio_config_acr(struct msm_dp_catalog *msm_dp_catalog, u32 select)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 acr_ctrl;
- if (!dp_catalog)
+ if (!msm_dp_catalog)
return;
- catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14);
drm_dbg_dp(catalog->drm_dev, "select: %#x, acr_ctrl: %#x\n",
select, acr_ctrl);
- dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl);
+ msm_dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl);
}
-void dp_catalog_audio_enable(struct dp_catalog *dp_catalog, bool enable)
+void msm_dp_catalog_audio_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 audio_ctrl;
- if (!dp_catalog)
+ if (!msm_dp_catalog)
return;
- catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- audio_ctrl = dp_read_link(catalog, MMSS_DP_AUDIO_CFG);
+ audio_ctrl = msm_dp_read_link(catalog, MMSS_DP_AUDIO_CFG);
if (enable)
audio_ctrl |= BIT(0);
@@ -1233,24 +1233,24 @@ void dp_catalog_audio_enable(struct dp_catalog *dp_catalog, bool enable)
drm_dbg_dp(catalog->drm_dev, "dp_audio_cfg = 0x%x\n", audio_ctrl);
- dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl);
+ msm_dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl);
/* make sure audio engine is disabled */
wmb();
}
-void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_audio_config_sdp(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 sdp_cfg = 0;
u32 sdp_cfg2 = 0;
- if (!dp_catalog)
+ if (!msm_dp_catalog)
return;
- catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- sdp_cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
+ sdp_cfg = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG);
/* AUDIO_TIMESTAMP_SDP_EN */
sdp_cfg |= BIT(1);
/* AUDIO_STREAM_SDP_EN */
@@ -1264,9 +1264,9 @@ void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog)
drm_dbg_dp(catalog->drm_dev, "sdp_cfg = 0x%x\n", sdp_cfg);
- dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg);
- sdp_cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
+ sdp_cfg2 = msm_dp_read_link(catalog, MMSS_DP_SDP_CFG2);
/* IFRM_REGSRC -> Do not use reg values */
sdp_cfg2 &= ~BIT(0);
/* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */
@@ -1274,12 +1274,12 @@ void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog)
drm_dbg_dp(catalog->drm_dev, "sdp_cfg2 = 0x%x\n", sdp_cfg2);
- dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2);
+ msm_dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2);
}
-void dp_catalog_audio_init(struct dp_catalog *dp_catalog)
+void msm_dp_catalog_audio_init(struct msm_dp_catalog *msm_dp_catalog)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = {
{
@@ -1309,27 +1309,27 @@ void dp_catalog_audio_init(struct dp_catalog *dp_catalog)
},
};
- if (!dp_catalog)
+ if (!msm_dp_catalog)
return;
- catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
catalog->audio_map = sdp_map;
}
-void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog, u32 safe_to_exit_level)
+void msm_dp_catalog_audio_sfe_level(struct msm_dp_catalog *msm_dp_catalog, u32 safe_to_exit_level)
{
- struct dp_catalog_private *catalog;
+ struct msm_dp_catalog_private *catalog;
u32 mainlink_levels;
- if (!dp_catalog)
+ if (!msm_dp_catalog)
return;
- catalog = container_of(dp_catalog,
- struct dp_catalog_private, dp_catalog);
+ catalog = container_of(msm_dp_catalog,
+ struct msm_dp_catalog_private, msm_dp_catalog);
- mainlink_levels = dp_read_link(catalog, REG_DP_MAINLINK_LEVELS);
+ mainlink_levels = msm_dp_read_link(catalog, REG_DP_MAINLINK_LEVELS);
mainlink_levels &= 0xFE0;
mainlink_levels |= safe_to_exit_level;
@@ -1337,5 +1337,5 @@ void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog, u32 safe_to_exit_
"mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n",
mainlink_levels, safe_to_exit_level);
- dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels);
+ msm_dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 4679d50b8c73..e932b17eecbf 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -31,7 +31,7 @@
#define DP_HW_VERSION_1_0 0x10000000
#define DP_HW_VERSION_1_2 0x10020000
-enum dp_catalog_audio_sdp_type {
+enum msm_dp_catalog_audio_sdp_type {
DP_AUDIO_SDP_STREAM,
DP_AUDIO_SDP_TIMESTAMP,
DP_AUDIO_SDP_INFOFRAME,
@@ -40,89 +40,89 @@ enum dp_catalog_audio_sdp_type {
DP_AUDIO_SDP_MAX,
};
-enum dp_catalog_audio_header_type {
+enum msm_dp_catalog_audio_header_type {
DP_AUDIO_SDP_HEADER_1,
DP_AUDIO_SDP_HEADER_2,
DP_AUDIO_SDP_HEADER_3,
DP_AUDIO_SDP_HEADER_MAX,
};
-struct dp_catalog {
+struct msm_dp_catalog {
bool wide_bus_en;
};
/* Debug module */
-void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *disp_state);
+void msm_dp_catalog_snapshot(struct msm_dp_catalog *msm_dp_catalog, struct msm_disp_state *disp_state);
/* AUX APIs */
-u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog);
-int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog, u32 data);
-int dp_catalog_aux_write_trans(struct dp_catalog *dp_catalog, u32 data);
-int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read);
-int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog);
-void dp_catalog_aux_reset(struct dp_catalog *dp_catalog);
-void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable);
-int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog,
+u32 msm_dp_catalog_aux_read_data(struct msm_dp_catalog *msm_dp_catalog);
+int msm_dp_catalog_aux_write_data(struct msm_dp_catalog *msm_dp_catalog, u32 data);
+int msm_dp_catalog_aux_write_trans(struct msm_dp_catalog *msm_dp_catalog, u32 data);
+int msm_dp_catalog_aux_clear_trans(struct msm_dp_catalog *msm_dp_catalog, bool read);
+int msm_dp_catalog_aux_clear_hw_interrupts(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_aux_reset(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_aux_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable);
+int msm_dp_catalog_aux_wait_for_hpd_connect_state(struct msm_dp_catalog *msm_dp_catalog,
unsigned long wait_us);
-u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog);
+u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog);
/* DP Controller APIs */
-void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 state);
-void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 config);
-void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
-void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool enable);
-void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
-void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
+void msm_dp_catalog_ctrl_state_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 state);
+void msm_dp_catalog_ctrl_config_ctrl(struct msm_dp_catalog *msm_dp_catalog, u32 config);
+void msm_dp_catalog_ctrl_lane_mapping(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_mainlink_ctrl(struct msm_dp_catalog *msm_dp_catalog, bool enable);
+void msm_dp_catalog_ctrl_psr_mainlink_enable(struct msm_dp_catalog *msm_dp_catalog, bool enable);
+void msm_dp_catalog_setup_peripheral_flush(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_config_misc(struct msm_dp_catalog *msm_dp_catalog, u32 cc, u32 tb);
+void msm_dp_catalog_ctrl_config_msa(struct msm_dp_catalog *msm_dp_catalog, u32 rate,
u32 stream_rate_khz, bool is_ycbcr_420);
-int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 pattern);
-u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
-bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable);
-void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog,
+int msm_dp_catalog_ctrl_set_pattern_state_bit(struct msm_dp_catalog *msm_dp_catalog, u32 pattern);
+u32 msm_dp_catalog_hw_revision(const struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_reset(struct msm_dp_catalog *msm_dp_catalog);
+bool msm_dp_catalog_ctrl_mainlink_ready(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_enable_irq(struct msm_dp_catalog *msm_dp_catalog, bool enable);
+void msm_dp_catalog_hpd_config_intr(struct msm_dp_catalog *msm_dp_catalog,
u32 intr_mask, bool en);
-void dp_catalog_ctrl_hpd_enable(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_hpd_disable(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_config_psr(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter);
-u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog);
-u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog);
-int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog);
-u32 dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog *dp_catalog);
-void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog,
- u32 dp_tu, u32 valid_boundary,
+void msm_dp_catalog_ctrl_hpd_enable(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_hpd_disable(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_config_psr(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_set_psr(struct msm_dp_catalog *msm_dp_catalog, bool enter);
+u32 msm_dp_catalog_link_is_connected(struct msm_dp_catalog *msm_dp_catalog);
+u32 msm_dp_catalog_hpd_get_intr_status(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_phy_reset(struct msm_dp_catalog *msm_dp_catalog);
+int msm_dp_catalog_ctrl_get_interrupt(struct msm_dp_catalog *msm_dp_catalog);
+u32 msm_dp_catalog_ctrl_read_psr_interrupt_status(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_ctrl_update_transfer_unit(struct msm_dp_catalog *msm_dp_catalog,
+ u32 msm_dp_tu, u32 valid_boundary,
u32 valid_boundary2);
-void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
+void msm_dp_catalog_ctrl_send_phy_pattern(struct msm_dp_catalog *msm_dp_catalog,
u32 pattern);
-u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog);
+u32 msm_dp_catalog_ctrl_read_phy_pattern(struct msm_dp_catalog *msm_dp_catalog);
/* DP Panel APIs */
-int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog, u32 total,
- u32 sync_start, u32 width_blanking, u32 dp_active);
-void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog, struct dp_sdp *vsc_sdp);
-void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog);
-void dp_catalog_dump_regs(struct dp_catalog *dp_catalog);
-void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
+int msm_dp_catalog_panel_timing_cfg(struct msm_dp_catalog *msm_dp_catalog, u32 total,
+ u32 sync_start, u32 width_blanking, u32 msm_dp_active);
+void msm_dp_catalog_panel_enable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog, struct dp_sdp *vsc_sdp);
+void msm_dp_catalog_panel_disable_vsc_sdp(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_dump_regs(struct msm_dp_catalog *msm_dp_catalog);
+void msm_dp_catalog_panel_tpg_enable(struct msm_dp_catalog *msm_dp_catalog,
struct drm_display_mode *drm_mode);
-void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog);
+void msm_dp_catalog_panel_tpg_disable(struct msm_dp_catalog *msm_dp_catalog);
-struct dp_catalog *dp_catalog_get(struct device *dev);
+struct msm_dp_catalog *msm_dp_catalog_get(struct device *dev);
/* DP Audio APIs */
-u32 dp_catalog_audio_get_header(struct dp_catalog *dp_catalog,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header);
-void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header,
+u32 msm_dp_catalog_audio_get_header(struct msm_dp_catalog *msm_dp_catalog,
+ enum msm_dp_catalog_audio_sdp_type sdp,
+ enum msm_dp_catalog_audio_header_type header);
+void msm_dp_catalog_audio_set_header(struct msm_dp_catalog *msm_dp_catalog,
+ enum msm_dp_catalog_audio_sdp_type sdp,
+ enum msm_dp_catalog_audio_header_type header,
u32 data);
-void dp_catalog_audio_config_acr(struct dp_catalog *catalog, u32 select);
-void dp_catalog_audio_enable(struct dp_catalog *catalog, bool enable);
-void dp_catalog_audio_config_sdp(struct dp_catalog *catalog);
-void dp_catalog_audio_init(struct dp_catalog *catalog);
-void dp_catalog_audio_sfe_level(struct dp_catalog *catalog, u32 safe_to_exit_level);
+void msm_dp_catalog_audio_config_acr(struct msm_dp_catalog *catalog, u32 select);
+void msm_dp_catalog_audio_enable(struct msm_dp_catalog *catalog, bool enable);
+void msm_dp_catalog_audio_config_sdp(struct msm_dp_catalog *catalog);
+void msm_dp_catalog_audio_init(struct msm_dp_catalog *catalog);
+void msm_dp_catalog_audio_sfe_level(struct msm_dp_catalog *catalog, u32 safe_to_exit_level);
#endif /* _DP_CATALOG_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index f342fc5ae41e..bc2ca8133b79 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -40,7 +40,7 @@ enum {
DP_TRAINING_2,
};
-struct dp_tu_calc_input {
+struct msm_dp_tu_calc_input {
u64 lclk; /* 162, 270, 540 and 810 */
u64 pclk_khz; /* in KHz */
u64 hactive; /* active h-width */
@@ -55,7 +55,7 @@ struct dp_tu_calc_input {
int num_of_dsc_slices; /* number of slices per line */
};
-struct dp_vc_tu_mapping_table {
+struct msm_dp_vc_tu_mapping_table {
u32 vic;
u8 lanes;
u8 lrate; /* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */
@@ -69,14 +69,14 @@ struct dp_vc_tu_mapping_table {
u8 tu_size_minus1;
};
-struct dp_ctrl_private {
- struct dp_ctrl dp_ctrl;
+struct msm_dp_ctrl_private {
+ struct msm_dp_ctrl msm_dp_ctrl;
struct drm_device *drm_dev;
struct device *dev;
struct drm_dp_aux *aux;
- struct dp_panel *panel;
- struct dp_link *link;
- struct dp_catalog *catalog;
+ struct msm_dp_panel *panel;
+ struct msm_dp_link *link;
+ struct msm_dp_catalog *catalog;
struct phy *phy;
@@ -99,8 +99,8 @@ struct dp_ctrl_private {
bool stream_clks_on;
};
-static int dp_aux_link_configure(struct drm_dp_aux *aux,
- struct dp_link_info *link)
+static int msm_dp_aux_link_configure(struct drm_dp_aux *aux,
+ struct msm_dp_link_info *link)
{
u8 values[2];
int err;
@@ -118,14 +118,14 @@ static int dp_aux_link_configure(struct drm_dp_aux *aux,
return 0;
}
-void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
reinit_completion(&ctrl->idle_comp);
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_PUSH_IDLE);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_PUSH_IDLE);
if (!wait_for_completion_timeout(&ctrl->idle_comp,
IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES))
@@ -134,7 +134,7 @@ void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)
drm_dbg_dp(ctrl->drm_dev, "mainlink off\n");
}
-static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
+static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl)
{
u32 config = 0, tbd;
const u8 *dpcd = ctrl->panel->dpcd;
@@ -142,15 +142,15 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
/* Default-> LSCLK DIV: 1/4 LCLK */
config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
- if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+ if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420)
config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */
/* Scrambler reset enable */
if (drm_dp_alternate_scrambler_reset_cap(dpcd))
config |= DP_CONFIGURATION_CTRL_ASSR;
- tbd = dp_link_get_test_bits_depth(ctrl->link,
- ctrl->panel->dp_mode.bpp);
+ tbd = msm_dp_link_get_test_bits_depth(ctrl->link,
+ ctrl->panel->msm_dp_mode.bpp);
config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT;
@@ -170,24 +170,24 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
if (ctrl->panel->psr_cap.version)
config |= DP_CONFIGURATION_CTRL_SEND_VSC;
- dp_catalog_ctrl_config_ctrl(ctrl->catalog, config);
+ msm_dp_catalog_ctrl_config_ctrl(ctrl->catalog, config);
}
-static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl)
+static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl)
{
u32 cc, tb;
- dp_catalog_ctrl_lane_mapping(ctrl->catalog);
- dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
- dp_catalog_setup_peripheral_flush(ctrl->catalog);
+ msm_dp_catalog_ctrl_lane_mapping(ctrl->catalog);
+ msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
+ msm_dp_catalog_setup_peripheral_flush(ctrl->catalog);
- dp_ctrl_config_ctrl(ctrl);
+ msm_dp_ctrl_config_ctrl(ctrl);
- tb = dp_link_get_test_bits_depth(ctrl->link,
- ctrl->panel->dp_mode.bpp);
- cc = dp_link_get_colorimetry_config(ctrl->link);
- dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb);
- dp_panel_timing_cfg(ctrl->panel);
+ tb = msm_dp_link_get_test_bits_depth(ctrl->link,
+ ctrl->panel->msm_dp_mode.bpp);
+ cc = msm_dp_link_get_colorimetry_config(ctrl->link);
+ msm_dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb);
+ msm_dp_panel_timing_cfg(ctrl->panel);
}
/*
@@ -310,7 +310,7 @@ static int _tu_param_compare(s64 a, s64 b)
}
}
-static void dp_panel_update_tu_timings(struct dp_tu_calc_input *in,
+static void msm_dp_panel_update_tu_timings(struct msm_dp_tu_calc_input *in,
struct tu_algo_data *tu)
{
int nlanes = in->nlanes;
@@ -622,9 +622,9 @@ static void _tu_valid_boundary_calc(struct tu_algo_data *tu)
}
}
-static void _dp_ctrl_calc_tu(struct dp_ctrl_private *ctrl,
- struct dp_tu_calc_input *in,
- struct dp_vc_tu_mapping_table *tu_table)
+static void _dp_ctrl_calc_tu(struct msm_dp_ctrl_private *ctrl,
+ struct msm_dp_tu_calc_input *in,
+ struct msm_dp_vc_tu_mapping_table *tu_table)
{
struct tu_algo_data *tu;
int compare_result_1, compare_result_2;
@@ -645,7 +645,7 @@ static void _dp_ctrl_calc_tu(struct dp_ctrl_private *ctrl,
if (!tu)
return;
- dp_panel_update_tu_timings(in, tu);
+ msm_dp_panel_update_tu_timings(in, tu);
tu->err_fp = drm_fixp_from_fraction(1000, 1); /* 1000 */
@@ -956,21 +956,21 @@ tu_size_calc:
kfree(tu);
}
-static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl,
- struct dp_vc_tu_mapping_table *tu_table)
+static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl,
+ struct msm_dp_vc_tu_mapping_table *tu_table)
{
- struct dp_tu_calc_input in;
+ struct msm_dp_tu_calc_input in;
struct drm_display_mode *drm_mode;
- drm_mode = &ctrl->panel->dp_mode.drm_mode;
+ drm_mode = &ctrl->panel->msm_dp_mode.drm_mode;
in.lclk = ctrl->link->link_params.rate / 1000;
in.pclk_khz = drm_mode->clock;
in.hactive = drm_mode->hdisplay;
in.hporch = drm_mode->htotal - drm_mode->hdisplay;
in.nlanes = ctrl->link->link_params.num_lanes;
- in.bpp = ctrl->panel->dp_mode.bpp;
- in.pixel_enc = ctrl->panel->dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
+ in.bpp = ctrl->panel->msm_dp_mode.bpp;
+ in.pixel_enc = ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
in.dsc_en = 0;
in.async_en = 0;
in.fec_en = 0;
@@ -980,16 +980,16 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl,
_dp_ctrl_calc_tu(ctrl, &in, tu_table);
}
-static void dp_ctrl_setup_tr_unit(struct dp_ctrl_private *ctrl)
+static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl)
{
- u32 dp_tu = 0x0;
+ u32 msm_dp_tu = 0x0;
u32 valid_boundary = 0x0;
u32 valid_boundary2 = 0x0;
- struct dp_vc_tu_mapping_table tu_calc_table;
+ struct msm_dp_vc_tu_mapping_table tu_calc_table;
- dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table);
+ msm_dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table);
- dp_tu |= tu_calc_table.tu_size_minus1;
+ msm_dp_tu |= tu_calc_table.tu_size_minus1;
valid_boundary |= tu_calc_table.valid_boundary_link;
valid_boundary |= (tu_calc_table.delay_start_link << 16);
@@ -1001,13 +1001,13 @@ static void dp_ctrl_setup_tr_unit(struct dp_ctrl_private *ctrl)
valid_boundary2 |= BIT(0);
pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n",
- dp_tu, valid_boundary, valid_boundary2);
+ msm_dp_tu, valid_boundary, valid_boundary2);
- dp_catalog_ctrl_update_transfer_unit(ctrl->catalog,
- dp_tu, valid_boundary, valid_boundary2);
+ msm_dp_catalog_ctrl_update_transfer_unit(ctrl->catalog,
+ msm_dp_tu, valid_boundary, valid_boundary2);
}
-static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_wait4video_ready(struct msm_dp_ctrl_private *ctrl)
{
int ret = 0;
@@ -1019,7 +1019,7 @@ static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)
return ret;
}
-static int dp_ctrl_set_vx_px(struct dp_ctrl_private *ctrl,
+static int msm_dp_ctrl_set_vx_px(struct msm_dp_ctrl_private *ctrl,
u8 v_level, u8 p_level)
{
union phy_configure_opts *phy_opts = &ctrl->phy_opts;
@@ -1034,9 +1034,9 @@ static int dp_ctrl_set_vx_px(struct dp_ctrl_private *ctrl,
return 0;
}
-static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl)
{
- struct dp_link *link = ctrl->link;
+ struct msm_dp_link *link = ctrl->link;
int ret = 0, lane, lane_cnt;
u8 buf[4];
u32 max_level_reached = 0;
@@ -1046,7 +1046,7 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
drm_dbg_dp(ctrl->drm_dev,
"voltage level: %d emphasis level: %d\n",
voltage_swing_level, pre_emphasis_level);
- ret = dp_ctrl_set_vx_px(ctrl,
+ ret = msm_dp_ctrl_set_vx_px(ctrl,
voltage_swing_level, pre_emphasis_level);
if (ret)
@@ -1083,7 +1083,7 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
return ret;
}
-static bool dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl,
+static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl,
u8 pattern)
{
u8 buf;
@@ -1100,7 +1100,7 @@ static bool dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl,
return ret == 1;
}
-static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,
+static int msm_dp_ctrl_read_link_status(struct msm_dp_ctrl_private *ctrl,
u8 *link_status)
{
int ret = 0, len;
@@ -1114,24 +1114,24 @@ static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,
return ret;
}
-static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
+static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl,
int *training_step)
{
int tries, old_v_level, ret = 0;
u8 link_status[DP_LINK_STATUS_SIZE];
int const maximum_retries = 4;
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
*training_step = DP_TRAINING_1;
- ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, 1);
+ ret = msm_dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, 1);
if (ret)
return ret;
- dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
+ msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
DP_LINK_SCRAMBLING_DISABLE);
- ret = dp_ctrl_update_vx_px(ctrl);
+ ret = msm_dp_ctrl_update_vx_px(ctrl);
if (ret)
return ret;
@@ -1140,7 +1140,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
for (tries = 0; tries < maximum_retries; tries++) {
drm_dp_link_train_clock_recovery_delay(ctrl->aux, ctrl->panel->dpcd);
- ret = dp_ctrl_read_link_status(ctrl, link_status);
+ ret = msm_dp_ctrl_read_link_status(ctrl, link_status);
if (ret)
return ret;
@@ -1160,8 +1160,8 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
old_v_level = ctrl->link->phy_params.v_level;
}
- dp_link_adjust_levels(ctrl->link, link_status);
- ret = dp_ctrl_update_vx_px(ctrl);
+ msm_dp_link_adjust_levels(ctrl->link, link_status);
+ ret = msm_dp_ctrl_update_vx_px(ctrl);
if (ret)
return ret;
}
@@ -1170,7 +1170,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
return -ETIMEDOUT;
}
-static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_link_rate_down_shift(struct msm_dp_ctrl_private *ctrl)
{
int ret = 0;
@@ -1198,7 +1198,7 @@ static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)
return ret;
}
-static int dp_ctrl_link_lane_down_shift(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl)
{
if (ctrl->link->link_params.num_lanes == 1)
@@ -1213,13 +1213,13 @@ static int dp_ctrl_link_lane_down_shift(struct dp_ctrl_private *ctrl)
return 0;
}
-static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl)
+static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl)
{
- dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE);
+ msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE);
drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd);
}
-static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
+static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl,
int *training_step)
{
int tries = 0, ret = 0;
@@ -1228,7 +1228,7 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
int const maximum_retries = 5;
u8 link_status[DP_LINK_STATUS_SIZE];
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
*training_step = DP_TRAINING_2;
@@ -1243,16 +1243,16 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
state_ctrl_bit = 2;
}
- ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit);
+ ret = msm_dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit);
if (ret)
return ret;
- dp_ctrl_train_pattern_set(ctrl, pattern);
+ msm_dp_ctrl_train_pattern_set(ctrl, pattern);
for (tries = 0; tries <= maximum_retries; tries++) {
drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd);
- ret = dp_ctrl_read_link_status(ctrl, link_status);
+ ret = msm_dp_ctrl_read_link_status(ctrl, link_status);
if (ret)
return ret;
@@ -1261,8 +1261,8 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
return 0;
}
- dp_link_adjust_levels(ctrl->link, link_status);
- ret = dp_ctrl_update_vx_px(ctrl);
+ msm_dp_link_adjust_levels(ctrl->link, link_status);
+ ret = msm_dp_ctrl_update_vx_px(ctrl);
if (ret)
return ret;
@@ -1271,24 +1271,24 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
return -ETIMEDOUT;
}
-static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
+static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl,
int *training_step)
{
int ret = 0;
const u8 *dpcd = ctrl->panel->dpcd;
u8 encoding[] = { 0, DP_SET_ANSI_8B10B };
u8 assr;
- struct dp_link_info link_info = {0};
+ struct msm_dp_link_info link_info = {0};
- dp_ctrl_config_ctrl(ctrl);
+ msm_dp_ctrl_config_ctrl(ctrl);
link_info.num_lanes = ctrl->link->link_params.num_lanes;
link_info.rate = ctrl->link->link_params.rate;
link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING;
- dp_link_reset_phy_params_vx_px(ctrl->link);
+ msm_dp_link_reset_phy_params_vx_px(ctrl->link);
- dp_aux_link_configure(ctrl->aux, &link_info);
+ msm_dp_aux_link_configure(ctrl->aux, &link_info);
if (drm_dp_max_downspread(dpcd))
encoding[0] |= DP_SPREAD_AMP_0_5;
@@ -1302,7 +1302,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
&assr, 1);
}
- ret = dp_ctrl_link_train_1(ctrl, training_step);
+ ret = msm_dp_ctrl_link_train_1(ctrl, training_step);
if (ret) {
DRM_ERROR("link training #1 failed. ret=%d\n", ret);
goto end;
@@ -1311,7 +1311,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
/* print success info as this is a result of user initiated action */
drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n");
- ret = dp_ctrl_link_train_2(ctrl, training_step);
+ ret = msm_dp_ctrl_link_train_2(ctrl, training_step);
if (ret) {
DRM_ERROR("link training #2 failed. ret=%d\n", ret);
goto end;
@@ -1321,17 +1321,17 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
drm_dbg_dp(ctrl->drm_dev, "link training #2 successful\n");
end:
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
return ret;
}
-static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl,
+static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl,
int *training_step)
{
int ret = 0;
- dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
+ msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
return ret;
@@ -1342,17 +1342,17 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl,
* a link training pattern, we have to first do soft reset.
*/
- ret = dp_ctrl_link_train(ctrl, training_step);
+ ret = msm_dp_ctrl_link_train(ctrl, training_step);
return ret;
}
-int dp_ctrl_core_clk_enable(struct dp_ctrl *dp_ctrl)
+int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
int ret = 0;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
if (ctrl->core_clks_on) {
drm_dbg_dp(ctrl->drm_dev, "core clks already enabled\n");
@@ -1374,11 +1374,11 @@ int dp_ctrl_core_clk_enable(struct dp_ctrl *dp_ctrl)
return 0;
}
-void dp_ctrl_core_clk_disable(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
clk_bulk_disable_unprepare(ctrl->num_core_clks, ctrl->core_clks);
@@ -1391,12 +1391,12 @@ void dp_ctrl_core_clk_disable(struct dp_ctrl *dp_ctrl)
ctrl->core_clks_on ? "on" : "off");
}
-static int dp_ctrl_link_clk_enable(struct dp_ctrl *dp_ctrl)
+static int msm_dp_ctrl_link_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
int ret = 0;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
if (ctrl->link_clks_on) {
drm_dbg_dp(ctrl->drm_dev, "links clks already enabled\n");
@@ -1406,7 +1406,7 @@ static int dp_ctrl_link_clk_enable(struct dp_ctrl *dp_ctrl)
if (!ctrl->core_clks_on) {
drm_dbg_dp(ctrl->drm_dev, "Enable core clks before link clks\n");
- dp_ctrl_core_clk_enable(dp_ctrl);
+ msm_dp_ctrl_core_clk_enable(msm_dp_ctrl);
}
ret = clk_bulk_prepare_enable(ctrl->num_link_clks, ctrl->link_clks);
@@ -1424,11 +1424,11 @@ static int dp_ctrl_link_clk_enable(struct dp_ctrl *dp_ctrl)
return 0;
}
-static void dp_ctrl_link_clk_disable(struct dp_ctrl *dp_ctrl)
+static void msm_dp_ctrl_link_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
clk_bulk_disable_unprepare(ctrl->num_link_clks, ctrl->link_clks);
@@ -1441,7 +1441,7 @@ static void dp_ctrl_link_clk_disable(struct dp_ctrl *dp_ctrl)
ctrl->core_clks_on ? "on" : "off");
}
-static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl)
{
int ret = 0;
struct phy *phy = ctrl->phy;
@@ -1455,7 +1455,7 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
phy_power_on(phy);
dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000);
- ret = dp_ctrl_link_clk_enable(&ctrl->dp_ctrl);
+ ret = msm_dp_ctrl_link_clk_enable(&ctrl->msm_dp_ctrl);
if (ret)
DRM_ERROR("Unable to start link clocks. ret=%d\n", ret);
@@ -1464,13 +1464,13 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
return ret;
}
-void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable)
+void msm_dp_ctrl_reset_irq_ctrl(struct msm_dp_ctrl *msm_dp_ctrl, bool enable)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
- dp_catalog_ctrl_reset(ctrl->catalog);
+ msm_dp_catalog_ctrl_reset(ctrl->catalog);
/*
* all dp controller programmable registers will not
@@ -1478,28 +1478,28 @@ void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable)
* therefore interrupt mask bits have to be updated
* to enable/disable interrupts
*/
- dp_catalog_ctrl_enable_irq(ctrl->catalog, enable);
+ msm_dp_catalog_ctrl_enable_irq(ctrl->catalog, enable);
}
-void dp_ctrl_config_psr(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl)
{
u8 cfg;
- struct dp_ctrl_private *ctrl = container_of(dp_ctrl,
- struct dp_ctrl_private, dp_ctrl);
+ struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl,
+ struct msm_dp_ctrl_private, msm_dp_ctrl);
if (!ctrl->panel->psr_cap.version)
return;
- dp_catalog_ctrl_config_psr(ctrl->catalog);
+ msm_dp_catalog_ctrl_config_psr(ctrl->catalog);
cfg = DP_PSR_ENABLE;
drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1);
}
-void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enter)
+void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enter)
{
- struct dp_ctrl_private *ctrl = container_of(dp_ctrl,
- struct dp_ctrl_private, dp_ctrl);
+ struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl,
+ struct msm_dp_ctrl_private, msm_dp_ctrl);
if (!ctrl->panel->psr_cap.version)
return;
@@ -1516,64 +1516,64 @@ void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enter)
*/
if (enter) {
reinit_completion(&ctrl->psr_op_comp);
- dp_catalog_ctrl_set_psr(ctrl->catalog, true);
+ msm_dp_catalog_ctrl_set_psr(ctrl->catalog, true);
if (!wait_for_completion_timeout(&ctrl->psr_op_comp,
PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES)) {
DRM_ERROR("PSR_ENTRY timedout\n");
- dp_catalog_ctrl_set_psr(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_set_psr(ctrl->catalog, false);
return;
}
- dp_ctrl_push_idle(dp_ctrl);
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
+ msm_dp_ctrl_push_idle(msm_dp_ctrl);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
- dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, false);
} else {
- dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, true);
+ msm_dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, true);
- dp_catalog_ctrl_set_psr(ctrl->catalog, false);
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
- dp_ctrl_wait4video_ready(ctrl);
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
+ msm_dp_catalog_ctrl_set_psr(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
+ msm_dp_ctrl_wait4video_ready(ctrl);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
}
}
-void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
struct phy *phy;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
phy = ctrl->phy;
- dp_catalog_ctrl_phy_reset(ctrl->catalog);
+ msm_dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_init(phy);
drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
phy, phy->init_count, phy->power_count);
}
-void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
struct phy *phy;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
phy = ctrl->phy;
- dp_catalog_ctrl_phy_reset(ctrl->catalog);
+ msm_dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_exit(phy);
drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
phy, phy->init_count, phy->power_count);
}
-static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl)
{
struct phy *phy = ctrl->phy;
int ret = 0;
- dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes;
phy_configure(phy, &ctrl->phy_opts);
/*
@@ -1583,13 +1583,13 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl)
*/
dev_pm_opp_set_rate(ctrl->dev, 0);
- dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);
+ msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
phy_power_off(phy);
/* hw recommended delay before re-enabling clocks */
msleep(20);
- ret = dp_ctrl_enable_mainlink_clocks(ctrl);
+ ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl);
if (ret) {
DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret);
return ret;
@@ -1598,18 +1598,18 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl)
return ret;
}
-static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl)
{
struct phy *phy;
phy = ctrl->phy;
- dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
- dp_catalog_ctrl_reset(ctrl->catalog);
+ msm_dp_catalog_ctrl_reset(ctrl->catalog);
dev_pm_opp_set_rate(ctrl->dev, 0);
- dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);
+ msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
phy_power_off(phy);
@@ -1622,30 +1622,30 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl)
return 0;
}
-static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl)
{
int ret = 0;
int training_step = DP_TRAINING_NONE;
- dp_ctrl_push_idle(&ctrl->dp_ctrl);
+ msm_dp_ctrl_push_idle(&ctrl->msm_dp_ctrl);
ctrl->link->phy_params.p_level = 0;
ctrl->link->phy_params.v_level = 0;
- ret = dp_ctrl_setup_main_link(ctrl, &training_step);
+ ret = msm_dp_ctrl_setup_main_link(ctrl, &training_step);
if (ret)
goto end;
- dp_ctrl_clear_training_pattern(ctrl);
+ msm_dp_ctrl_clear_training_pattern(ctrl);
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
- ret = dp_ctrl_wait4video_ready(ctrl);
+ ret = msm_dp_ctrl_wait4video_ready(ctrl);
end:
return ret;
}
-static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
+static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl)
{
bool success = false;
u32 pattern_sent = 0x0;
@@ -1653,17 +1653,17 @@ static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
drm_dbg_dp(ctrl->drm_dev, "request: 0x%x\n", pattern_requested);
- if (dp_ctrl_set_vx_px(ctrl,
+ if (msm_dp_ctrl_set_vx_px(ctrl,
ctrl->link->phy_params.v_level,
ctrl->link->phy_params.p_level)) {
DRM_ERROR("Failed to set v/p levels\n");
return false;
}
- dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested);
- dp_ctrl_update_vx_px(ctrl);
- dp_link_send_test_response(ctrl->link);
+ msm_dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested);
+ msm_dp_ctrl_update_vx_px(ctrl);
+ msm_dp_link_send_test_response(ctrl->link);
- pattern_sent = dp_catalog_ctrl_read_phy_pattern(ctrl->catalog);
+ pattern_sent = msm_dp_catalog_ctrl_read_phy_pattern(ctrl->catalog);
switch (pattern_sent) {
case MR_LINK_TRAINING1:
@@ -1697,7 +1697,7 @@ static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
return success;
}
-static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl)
{
int ret;
unsigned long pixel_rate;
@@ -1713,15 +1713,15 @@ static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl)
* running. Add the global reset just before disabling the
* link clocks and core clocks.
*/
- dp_ctrl_off(&ctrl->dp_ctrl);
+ msm_dp_ctrl_off(&ctrl->msm_dp_ctrl);
- ret = dp_ctrl_on_link(&ctrl->dp_ctrl);
+ ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl);
if (ret) {
DRM_ERROR("failed to enable DP link controller\n");
return ret;
}
- pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
+ pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock;
ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000);
if (ret) {
DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret);
@@ -1739,49 +1739,49 @@ static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl)
ctrl->stream_clks_on = true;
}
- dp_ctrl_send_phy_test_pattern(ctrl);
+ msm_dp_ctrl_send_phy_test_pattern(ctrl);
return 0;
}
-void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
u32 sink_request = 0x0;
- if (!dp_ctrl) {
+ if (!msm_dp_ctrl) {
DRM_ERROR("invalid input\n");
return;
}
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
sink_request = ctrl->link->sink_request;
if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
drm_dbg_dp(ctrl->drm_dev, "PHY_TEST_PATTERN request\n");
- if (dp_ctrl_process_phy_test_request(ctrl)) {
+ if (msm_dp_ctrl_process_phy_test_request(ctrl)) {
DRM_ERROR("process phy_test_req failed\n");
return;
}
}
if (sink_request & DP_LINK_STATUS_UPDATED) {
- if (dp_ctrl_link_maintenance(ctrl)) {
+ if (msm_dp_ctrl_link_maintenance(ctrl)) {
DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");
return;
}
}
if (sink_request & DP_TEST_LINK_TRAINING) {
- dp_link_send_test_response(ctrl->link);
- if (dp_ctrl_link_maintenance(ctrl)) {
+ msm_dp_link_send_test_response(ctrl->link);
+ if (msm_dp_ctrl_link_maintenance(ctrl)) {
DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");
return;
}
}
}
-static bool dp_ctrl_clock_recovery_any_ok(
+static bool msm_dp_ctrl_clock_recovery_any_ok(
const u8 link_status[DP_LINK_STATUS_SIZE],
int lane_count)
{
@@ -1800,20 +1800,20 @@ static bool dp_ctrl_clock_recovery_any_ok(
return drm_dp_clock_recovery_ok(link_status, reduced_cnt);
}
-static bool dp_ctrl_channel_eq_ok(struct dp_ctrl_private *ctrl)
+static bool msm_dp_ctrl_channel_eq_ok(struct msm_dp_ctrl_private *ctrl)
{
u8 link_status[DP_LINK_STATUS_SIZE];
int num_lanes = ctrl->link->link_params.num_lanes;
- dp_ctrl_read_link_status(ctrl, link_status);
+ msm_dp_ctrl_read_link_status(ctrl, link_status);
return drm_dp_channel_eq_ok(link_status, num_lanes);
}
-int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
+int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl)
{
int rc = 0;
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
u32 rate;
int link_train_max_retries = 5;
u32 const phy_cts_pixel_clk_khz = 148500;
@@ -1821,15 +1821,15 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
unsigned int training_step;
unsigned long pixel_rate;
- if (!dp_ctrl)
+ if (!msm_dp_ctrl)
return -EINVAL;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
rate = ctrl->panel->link_info.rate;
- pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
+ pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock;
- dp_ctrl_core_clk_enable(&ctrl->dp_ctrl);
+ msm_dp_ctrl_core_clk_enable(&ctrl->msm_dp_ctrl);
if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
drm_dbg_dp(ctrl->drm_dev,
@@ -1840,7 +1840,7 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
ctrl->link->link_params.rate = rate;
ctrl->link->link_params.num_lanes =
ctrl->panel->link_info.num_lanes;
- if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+ if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420)
pixel_rate >>= 1;
}
@@ -1848,32 +1848,32 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes,
pixel_rate);
- rc = dp_ctrl_enable_mainlink_clocks(ctrl);
+ rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl);
if (rc)
return rc;
while (--link_train_max_retries) {
training_step = DP_TRAINING_NONE;
- rc = dp_ctrl_setup_main_link(ctrl, &training_step);
+ rc = msm_dp_ctrl_setup_main_link(ctrl, &training_step);
if (rc == 0) {
/* training completed successfully */
break;
} else if (training_step == DP_TRAINING_1) {
/* link train_1 failed */
- if (!dp_catalog_link_is_connected(ctrl->catalog))
+ if (!msm_dp_catalog_link_is_connected(ctrl->catalog))
break;
- dp_ctrl_read_link_status(ctrl, link_status);
+ msm_dp_ctrl_read_link_status(ctrl, link_status);
- rc = dp_ctrl_link_rate_down_shift(ctrl);
+ rc = msm_dp_ctrl_link_rate_down_shift(ctrl);
if (rc < 0) { /* already in RBR = 1.6G */
- if (dp_ctrl_clock_recovery_any_ok(link_status,
+ if (msm_dp_ctrl_clock_recovery_any_ok(link_status,
ctrl->link->link_params.num_lanes)) {
/*
* some lanes are ready,
* reduce lane number
*/
- rc = dp_ctrl_link_lane_down_shift(ctrl);
+ rc = msm_dp_ctrl_link_lane_down_shift(ctrl);
if (rc < 0) { /* lane == 1 already */
/* end with failure */
break;
@@ -1885,16 +1885,16 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
}
} else if (training_step == DP_TRAINING_2) {
/* link train_2 failed */
- if (!dp_catalog_link_is_connected(ctrl->catalog))
+ if (!msm_dp_catalog_link_is_connected(ctrl->catalog))
break;
- dp_ctrl_read_link_status(ctrl, link_status);
+ msm_dp_ctrl_read_link_status(ctrl, link_status);
if (!drm_dp_clock_recovery_ok(link_status,
ctrl->link->link_params.num_lanes))
- rc = dp_ctrl_link_rate_down_shift(ctrl);
+ rc = msm_dp_ctrl_link_rate_down_shift(ctrl);
else
- rc = dp_ctrl_link_lane_down_shift(ctrl);
+ rc = msm_dp_ctrl_link_lane_down_shift(ctrl);
if (rc < 0) {
/* end with failure */
@@ -1902,10 +1902,10 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
}
/* stop link training before start re training */
- dp_ctrl_clear_training_pattern(ctrl);
+ msm_dp_ctrl_clear_training_pattern(ctrl);
}
- rc = dp_ctrl_reinitialize_mainlink(ctrl);
+ rc = msm_dp_ctrl_reinitialize_mainlink(ctrl);
if (rc) {
DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc);
break;
@@ -1926,38 +1926,38 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
* link training failed
* end txing train pattern here
*/
- dp_ctrl_clear_training_pattern(ctrl);
+ msm_dp_ctrl_clear_training_pattern(ctrl);
- dp_ctrl_deinitialize_mainlink(ctrl);
+ msm_dp_ctrl_deinitialize_mainlink(ctrl);
rc = -ECONNRESET;
}
return rc;
}
-static int dp_ctrl_link_retrain(struct dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl)
{
int training_step = DP_TRAINING_NONE;
- return dp_ctrl_setup_main_link(ctrl, &training_step);
+ return msm_dp_ctrl_setup_main_link(ctrl, &training_step);
}
-int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
+int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train)
{
int ret = 0;
bool mainlink_ready = false;
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
unsigned long pixel_rate;
unsigned long pixel_rate_orig;
- if (!dp_ctrl)
+ if (!msm_dp_ctrl)
return -EINVAL;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
- pixel_rate = pixel_rate_orig = ctrl->panel->dp_mode.drm_mode.clock;
+ pixel_rate = pixel_rate_orig = ctrl->panel->msm_dp_mode.drm_mode.clock;
- if (dp_ctrl->wide_bus_en || ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+ if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420)
pixel_rate >>= 1;
drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
@@ -1969,7 +1969,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on);
if (!ctrl->link_clks_on) { /* link clk is off */
- ret = dp_ctrl_enable_mainlink_clocks(ctrl);
+ ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl);
if (ret) {
DRM_ERROR("Failed to start link clocks. ret=%d\n", ret);
goto end;
@@ -1993,11 +1993,11 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
ctrl->stream_clks_on = true;
}
- if (force_link_train || !dp_ctrl_channel_eq_ok(ctrl))
- dp_ctrl_link_retrain(ctrl);
+ if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl))
+ msm_dp_ctrl_link_retrain(ctrl);
/* stop txing train pattern to end link training */
- dp_ctrl_clear_training_pattern(ctrl);
+ msm_dp_ctrl_clear_training_pattern(ctrl);
/*
* Set up transfer unit values and set controller state to send
@@ -2005,22 +2005,22 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
*/
reinit_completion(&ctrl->video_comp);
- dp_ctrl_configure_source_params(ctrl);
+ msm_dp_ctrl_configure_source_params(ctrl);
- dp_catalog_ctrl_config_msa(ctrl->catalog,
+ msm_dp_catalog_ctrl_config_msa(ctrl->catalog,
ctrl->link->link_params.rate,
pixel_rate_orig,
- ctrl->panel->dp_mode.out_fmt_is_yuv_420);
+ ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420);
- dp_ctrl_setup_tr_unit(ctrl);
+ msm_dp_ctrl_setup_tr_unit(ctrl);
- dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
+ msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
- ret = dp_ctrl_wait4video_ready(ctrl);
+ ret = msm_dp_ctrl_wait4video_ready(ctrl);
if (ret)
return ret;
- mainlink_ready = dp_catalog_ctrl_mainlink_ready(ctrl->catalog);
+ mainlink_ready = msm_dp_catalog_ctrl_mainlink_ready(ctrl->catalog);
drm_dbg_dp(ctrl->drm_dev,
"mainlink %s\n", mainlink_ready ? "READY" : "NOT READY");
@@ -2028,20 +2028,20 @@ end:
return ret;
}
-void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
struct phy *phy;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
phy = ctrl->phy;
- dp_catalog_panel_disable_vsc_sdp(ctrl->catalog);
+ msm_dp_catalog_panel_disable_vsc_sdp(ctrl->catalog);
/* set dongle to D3 (power off) mode */
- dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true);
+ msm_dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true);
- dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
if (ctrl->stream_clks_on) {
clk_disable_unprepare(ctrl->pixel_clk);
@@ -2049,7 +2049,7 @@ void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
}
dev_pm_opp_set_rate(ctrl->dev, 0);
- dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);
+ msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
phy_power_off(phy);
@@ -2061,17 +2061,17 @@ void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
phy, phy->init_count, phy->power_count);
}
-void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
struct phy *phy;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
phy = ctrl->phy;
- dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
- dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);
+ msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n",
phy, phy->init_count, phy->power_count);
@@ -2082,19 +2082,19 @@ void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl)
phy, phy->init_count, phy->power_count);
}
-void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
+void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
struct phy *phy;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
phy = ctrl->phy;
- dp_catalog_panel_disable_vsc_sdp(ctrl->catalog);
+ msm_dp_catalog_panel_disable_vsc_sdp(ctrl->catalog);
- dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
+ msm_dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
- dp_catalog_ctrl_reset(ctrl->catalog);
+ msm_dp_catalog_ctrl_reset(ctrl->catalog);
if (ctrl->stream_clks_on) {
clk_disable_unprepare(ctrl->pixel_clk);
@@ -2102,26 +2102,26 @@ void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
}
dev_pm_opp_set_rate(ctrl->dev, 0);
- dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);
+ msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
phy_power_off(phy);
drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
phy, phy->init_count, phy->power_count);
}
-irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl)
+irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
u32 isr;
irqreturn_t ret = IRQ_NONE;
- if (!dp_ctrl)
+ if (!msm_dp_ctrl)
return IRQ_NONE;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
if (ctrl->panel->psr_cap.version) {
- isr = dp_catalog_ctrl_read_psr_interrupt_status(ctrl->catalog);
+ isr = msm_dp_catalog_ctrl_read_psr_interrupt_status(ctrl->catalog);
if (isr)
complete(&ctrl->psr_op_comp);
@@ -2136,7 +2136,7 @@ irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl)
drm_dbg_dp(ctrl->drm_dev, "PSR frame capture done\n");
}
- isr = dp_catalog_ctrl_get_interrupt(ctrl->catalog);
+ isr = msm_dp_catalog_ctrl_get_interrupt(ctrl->catalog);
if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) {
@@ -2164,13 +2164,13 @@ static const char *ctrl_clks[] = {
"ctrl_link_iface",
};
-static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl)
+static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
struct device *dev;
int i, rc;
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
dev = ctrl->dev;
ctrl->num_core_clks = ARRAY_SIZE(core_clks);
@@ -2204,12 +2204,12 @@ static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl)
return 0;
}
-struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link,
- struct dp_panel *panel, struct drm_dp_aux *aux,
- struct dp_catalog *catalog,
+struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link,
+ struct msm_dp_panel *panel, struct drm_dp_aux *aux,
+ struct msm_dp_catalog *catalog,
struct phy *phy)
{
- struct dp_ctrl_private *ctrl;
+ struct msm_dp_ctrl_private *ctrl;
int ret;
if (!dev || !panel || !aux ||
@@ -2228,7 +2228,7 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link,
if (ret) {
dev_err(dev, "invalid DP OPP table in device tree\n");
/* caller do PTR_ERR(opp_table) */
- return (struct dp_ctrl *)ERR_PTR(ret);
+ return (struct msm_dp_ctrl *)ERR_PTR(ret);
}
/* OPP table is optional */
@@ -2248,11 +2248,11 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link,
ctrl->dev = dev;
ctrl->phy = phy;
- ret = dp_ctrl_clk_init(&ctrl->dp_ctrl);
+ ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl);
if (ret) {
dev_err(dev, "failed to init clocks\n");
return ERR_PTR(ret);
}
- return &ctrl->dp_ctrl;
+ return &ctrl->msm_dp_ctrl;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index ffcbd9a25748..b7abfedbf574 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -11,34 +11,34 @@
#include "dp_link.h"
#include "dp_catalog.h"
-struct dp_ctrl {
+struct msm_dp_ctrl {
bool wide_bus_en;
};
struct phy;
-int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl);
-int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train);
-void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_off(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl);
-irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl);
-struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link,
- struct dp_panel *panel, struct drm_dp_aux *aux,
- struct dp_catalog *catalog,
+int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl);
+int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train);
+void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl);
+void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl);
+void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl);
+void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl);
+irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl);
+void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl);
+struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link,
+ struct msm_dp_panel *panel, struct drm_dp_aux *aux,
+ struct msm_dp_catalog *catalog,
struct phy *phy);
-void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable);
-void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_irq_phy_exit(struct dp_ctrl *dp_ctrl);
+void msm_dp_ctrl_reset_irq_ctrl(struct msm_dp_ctrl *msm_dp_ctrl, bool enable);
+void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl);
+void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl);
+void msm_dp_ctrl_irq_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl);
-void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enable);
-void dp_ctrl_config_psr(struct dp_ctrl *dp_ctrl);
+void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enable);
+void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl);
-int dp_ctrl_core_clk_enable(struct dp_ctrl *dp_ctrl);
-void dp_ctrl_core_clk_disable(struct dp_ctrl *dp_ctrl);
+int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl);
+void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl);
#endif /* _DP_CTRL_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index b8611f6d2296..22fd946ee201 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -17,15 +17,15 @@
#define DEBUG_NAME "msm_dp"
-struct dp_debug_private {
- struct dp_link *link;
- struct dp_panel *panel;
+struct msm_dp_debug_private {
+ struct msm_dp_link *link;
+ struct msm_dp_panel *panel;
struct drm_connector *connector;
};
-static int dp_debug_show(struct seq_file *seq, void *p)
+static int msm_dp_debug_show(struct seq_file *seq, void *p)
{
- struct dp_debug_private *debug = seq->private;
+ struct msm_dp_debug_private *debug = seq->private;
u64 lclk = 0;
u32 link_params_rate;
const struct drm_display_mode *drm_mode;
@@ -33,7 +33,7 @@ static int dp_debug_show(struct seq_file *seq, void *p)
if (!debug)
return -ENODEV;
- drm_mode = &debug->panel->dp_mode.drm_mode;
+ drm_mode = &debug->panel->msm_dp_mode.drm_mode;
seq_printf(seq, "\tname = %s\n", DEBUG_NAME);
seq_printf(seq, "\tdrm_dp_link\n\t\trate = %u\n",
@@ -55,8 +55,8 @@ static int dp_debug_show(struct seq_file *seq, void *p)
drm_mode->hsync_end - drm_mode->hsync_start,
drm_mode->vsync_end - drm_mode->vsync_start);
seq_printf(seq, "\t\tactive_low = %dx%d\n",
- debug->panel->dp_mode.h_active_low,
- debug->panel->dp_mode.v_active_low);
+ debug->panel->msm_dp_mode.h_active_low,
+ debug->panel->msm_dp_mode.v_active_low);
seq_printf(seq, "\t\th_skew = %d\n",
drm_mode->hskew);
seq_printf(seq, "\t\trefresh rate = %d\n",
@@ -64,7 +64,7 @@ static int dp_debug_show(struct seq_file *seq, void *p)
seq_printf(seq, "\t\tpixel clock khz = %d\n",
drm_mode->clock);
seq_printf(seq, "\t\tbpp = %d\n",
- debug->panel->dp_mode.bpp);
+ debug->panel->msm_dp_mode.bpp);
/* Link Information */
seq_printf(seq, "\tdp_link:\n\t\ttest_requested = %d\n",
@@ -83,11 +83,11 @@ static int dp_debug_show(struct seq_file *seq, void *p)
return 0;
}
-DEFINE_SHOW_ATTRIBUTE(dp_debug);
+DEFINE_SHOW_ATTRIBUTE(msm_dp_debug);
-static int dp_test_data_show(struct seq_file *m, void *data)
+static int msm_dp_test_data_show(struct seq_file *m, void *data)
{
- const struct dp_debug_private *debug = m->private;
+ const struct msm_dp_debug_private *debug = m->private;
const struct drm_connector *connector = debug->connector;
u32 bpc;
@@ -98,18 +98,18 @@ static int dp_test_data_show(struct seq_file *m, void *data)
seq_printf(m, "vdisplay: %d\n",
debug->link->test_video.test_v_height);
seq_printf(m, "bpc: %u\n",
- dp_link_bit_depth_to_bpp(bpc) / 3);
+ msm_dp_link_bit_depth_to_bpp(bpc) / 3);
} else {
seq_puts(m, "0");
}
return 0;
}
-DEFINE_SHOW_ATTRIBUTE(dp_test_data);
+DEFINE_SHOW_ATTRIBUTE(msm_dp_test_data);
-static int dp_test_type_show(struct seq_file *m, void *data)
+static int msm_dp_test_type_show(struct seq_file *m, void *data)
{
- const struct dp_debug_private *debug = m->private;
+ const struct msm_dp_debug_private *debug = m->private;
const struct drm_connector *connector = debug->connector;
if (connector->status == connector_status_connected)
@@ -119,15 +119,15 @@ static int dp_test_type_show(struct seq_file *m, void *data)
return 0;
}
-DEFINE_SHOW_ATTRIBUTE(dp_test_type);
+DEFINE_SHOW_ATTRIBUTE(msm_dp_test_type);
-static ssize_t dp_test_active_write(struct file *file,
+static ssize_t msm_dp_test_active_write(struct file *file,
const char __user *ubuf,
size_t len, loff_t *offp)
{
char *input_buffer;
int status = 0;
- const struct dp_debug_private *debug;
+ const struct msm_dp_debug_private *debug;
const struct drm_connector *connector;
int val = 0;
@@ -164,9 +164,9 @@ static ssize_t dp_test_active_write(struct file *file,
return len;
}
-static int dp_test_active_show(struct seq_file *m, void *data)
+static int msm_dp_test_active_show(struct seq_file *m, void *data)
{
- struct dp_debug_private *debug = m->private;
+ struct msm_dp_debug_private *debug = m->private;
struct drm_connector *connector = debug->connector;
if (connector->status == connector_status_connected) {
@@ -181,28 +181,28 @@ static int dp_test_active_show(struct seq_file *m, void *data)
return 0;
}
-static int dp_test_active_open(struct inode *inode,
+static int msm_dp_test_active_open(struct inode *inode,
struct file *file)
{
- return single_open(file, dp_test_active_show,
+ return single_open(file, msm_dp_test_active_show,
inode->i_private);
}
static const struct file_operations test_active_fops = {
.owner = THIS_MODULE,
- .open = dp_test_active_open,
+ .open = msm_dp_test_active_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
- .write = dp_test_active_write
+ .write = msm_dp_test_active_write
};
-int dp_debug_init(struct device *dev, struct dp_panel *panel,
- struct dp_link *link,
+int msm_dp_debug_init(struct device *dev, struct msm_dp_panel *panel,
+ struct msm_dp_link *link,
struct drm_connector *connector,
struct dentry *root, bool is_edp)
{
- struct dp_debug_private *debug;
+ struct msm_dp_debug_private *debug;
if (!dev || !panel || !link) {
DRM_ERROR("invalid input\n");
@@ -217,20 +217,20 @@ int dp_debug_init(struct device *dev, struct dp_panel *panel,
debug->panel = panel;
debugfs_create_file("dp_debug", 0444, root,
- debug, &dp_debug_fops);
+ debug, &msm_dp_debug_fops);
if (!is_edp) {
- debugfs_create_file("msm_dp_test_active", 0444,
+ debugfs_create_file("dp_test_active", 0444,
root,
debug, &test_active_fops);
- debugfs_create_file("msm_dp_test_data", 0444,
+ debugfs_create_file("dp_test_data", 0444,
root,
- debug, &dp_test_data_fops);
+ debug, &msm_dp_test_data_fops);
- debugfs_create_file("msm_dp_test_type", 0444,
+ debugfs_create_file("dp_test_type", 0444,
root,
- debug, &dp_test_type_fops);
+ debug, &msm_dp_test_type_fops);
}
return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h
index 7e1aa892fc09..6dc0ff4f0f65 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.h
+++ b/drivers/gpu/drm/msm/dp/dp_debug.h
@@ -12,7 +12,7 @@
#if defined(CONFIG_DEBUG_FS)
/**
- * dp_debug_get() - configure and get the DisplayPlot debug module data
+ * msm_dp_debug_get() - configure and get the DisplayPlot debug module data
*
* @dev: device instance of the caller
* @panel: instance of panel module
@@ -25,8 +25,8 @@
* This function sets up the debug module and provides a way
* for debugfs input to be communicated with existing modules
*/
-int dp_debug_init(struct device *dev, struct dp_panel *panel,
- struct dp_link *link,
+int msm_dp_debug_init(struct device *dev, struct msm_dp_panel *panel,
+ struct msm_dp_link *link,
struct drm_connector *connector,
struct dentry *root,
bool is_edp);
@@ -34,8 +34,8 @@ int dp_debug_init(struct device *dev, struct dp_panel *panel,
#else
static inline
-int dp_debug_init(struct device *dev, struct dp_panel *panel,
- struct dp_link *link,
+int msm_dp_debug_init(struct device *dev, struct msm_dp_panel *panel,
+ struct msm_dp_link *link,
struct drm_connector *connector,
struct dentry *root,
bool is_edp)
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 0ddd8abca499..aba925aab7ad 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -67,13 +67,13 @@ enum {
#define WAIT_FOR_RESUME_TIMEOUT_JIFFIES (HZ / 2)
-struct dp_event {
+struct msm_dp_event {
u32 event_id;
u32 data;
u32 delay;
};
-struct dp_display_private {
+struct msm_dp_display_private {
int irq;
unsigned int id;
@@ -85,14 +85,14 @@ struct dp_display_private {
struct drm_device *drm_dev;
- struct dp_catalog *catalog;
+ struct msm_dp_catalog *catalog;
struct drm_dp_aux *aux;
- struct dp_link *link;
- struct dp_panel *panel;
- struct dp_ctrl *ctrl;
+ struct msm_dp_link *link;
+ struct msm_dp_panel *panel;
+ struct msm_dp_ctrl *ctrl;
- struct dp_display_mode dp_mode;
- struct msm_dp dp_display;
+ struct msm_dp_display_mode msm_dp_mode;
+ struct msm_dp msm_dp_display;
/* wait for audio signaling */
struct completion audio_comp;
@@ -104,12 +104,12 @@ struct dp_display_private {
u32 event_pndx;
u32 event_gndx;
struct task_struct *ev_tsk;
- struct dp_event event_list[DP_EVENT_Q_MAX];
+ struct msm_dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
bool wide_bus_supported;
- struct dp_audio *audio;
+ struct msm_dp_audio *audio;
};
struct msm_dp_desc {
@@ -118,25 +118,33 @@ struct msm_dp_desc {
bool wide_bus_supported;
};
-static const struct msm_dp_desc sc7180_dp_descs[] = {
+static const struct msm_dp_desc msm_dp_desc_sa8775p[] = {
+ { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
+ { .io_start = 0x0af5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true },
+ { .io_start = 0x22154000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true },
+ { .io_start = 0x2215c000, .id = MSM_DP_CONTROLLER_3, .wide_bus_supported = true },
+ {}
+};
+
+static const struct msm_dp_desc msm_dp_desc_sc7180[] = {
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
{}
};
-static const struct msm_dp_desc sc7280_dp_descs[] = {
+static const struct msm_dp_desc msm_dp_desc_sc7280[] = {
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
{ .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true },
{}
};
-static const struct msm_dp_desc sc8180x_dp_descs[] = {
+static const struct msm_dp_desc msm_dp_desc_sc8180x[] = {
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
{ .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true },
{ .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true },
{}
};
-static const struct msm_dp_desc sc8280xp_dp_descs[] = {
+static const struct msm_dp_desc msm_dp_desc_sc8280xp[] = {
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
{ .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true },
{ .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true },
@@ -148,12 +156,12 @@ static const struct msm_dp_desc sc8280xp_dp_descs[] = {
{}
};
-static const struct msm_dp_desc sm8650_dp_descs[] = {
+static const struct msm_dp_desc msm_dp_desc_sm8650[] = {
{ .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
{}
};
-static const struct msm_dp_desc x1e80100_dp_descs[] = {
+static const struct msm_dp_desc msm_dp_desc_x1e80100[] = {
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
{ .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true },
{ .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true },
@@ -161,70 +169,71 @@ static const struct msm_dp_desc x1e80100_dp_descs[] = {
{}
};
-static const struct of_device_id dp_dt_match[] = {
- { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_descs },
- { .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_descs },
- { .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_descs },
- { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_descs },
- { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_descs },
- { .compatible = "qcom,sc8280xp-dp", .data = &sc8280xp_dp_descs },
- { .compatible = "qcom,sc8280xp-edp", .data = &sc8280xp_dp_descs },
- { .compatible = "qcom,sdm845-dp", .data = &sc7180_dp_descs },
- { .compatible = "qcom,sm8350-dp", .data = &sc7180_dp_descs },
- { .compatible = "qcom,sm8650-dp", .data = &sm8650_dp_descs },
- { .compatible = "qcom,x1e80100-dp", .data = &x1e80100_dp_descs },
+static const struct of_device_id msm_dp_dt_match[] = {
+ { .compatible = "qcom,sa8775p-dp", .data = &msm_dp_desc_sa8775p },
+ { .compatible = "qcom,sc7180-dp", .data = &msm_dp_desc_sc7180 },
+ { .compatible = "qcom,sc7280-dp", .data = &msm_dp_desc_sc7280 },
+ { .compatible = "qcom,sc7280-edp", .data = &msm_dp_desc_sc7280 },
+ { .compatible = "qcom,sc8180x-dp", .data = &msm_dp_desc_sc8180x },
+ { .compatible = "qcom,sc8180x-edp", .data = &msm_dp_desc_sc8180x },
+ { .compatible = "qcom,sc8280xp-dp", .data = &msm_dp_desc_sc8280xp },
+ { .compatible = "qcom,sc8280xp-edp", .data = &msm_dp_desc_sc8280xp },
+ { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sc7180 },
+ { .compatible = "qcom,sm8350-dp", .data = &msm_dp_desc_sc7180 },
+ { .compatible = "qcom,sm8650-dp", .data = &msm_dp_desc_sm8650 },
+ { .compatible = "qcom,x1e80100-dp", .data = &msm_dp_desc_x1e80100 },
{}
};
-static struct dp_display_private *dev_get_dp_display_private(struct device *dev)
+static struct msm_dp_display_private *dev_get_dp_display_private(struct device *dev)
{
struct msm_dp *dp = dev_get_drvdata(dev);
- return container_of(dp, struct dp_display_private, dp_display);
+ return container_of(dp, struct msm_dp_display_private, msm_dp_display);
}
-static int dp_add_event(struct dp_display_private *dp_priv, u32 event,
+static int msm_dp_add_event(struct msm_dp_display_private *msm_dp_priv, u32 event,
u32 data, u32 delay)
{
unsigned long flag;
- struct dp_event *todo;
+ struct msm_dp_event *todo;
int pndx;
- spin_lock_irqsave(&dp_priv->event_lock, flag);
- pndx = dp_priv->event_pndx + 1;
+ spin_lock_irqsave(&msm_dp_priv->event_lock, flag);
+ pndx = msm_dp_priv->event_pndx + 1;
pndx %= DP_EVENT_Q_MAX;
- if (pndx == dp_priv->event_gndx) {
+ if (pndx == msm_dp_priv->event_gndx) {
pr_err("event_q is full: pndx=%d gndx=%d\n",
- dp_priv->event_pndx, dp_priv->event_gndx);
- spin_unlock_irqrestore(&dp_priv->event_lock, flag);
+ msm_dp_priv->event_pndx, msm_dp_priv->event_gndx);
+ spin_unlock_irqrestore(&msm_dp_priv->event_lock, flag);
return -EPERM;
}
- todo = &dp_priv->event_list[dp_priv->event_pndx++];
- dp_priv->event_pndx %= DP_EVENT_Q_MAX;
+ todo = &msm_dp_priv->event_list[msm_dp_priv->event_pndx++];
+ msm_dp_priv->event_pndx %= DP_EVENT_Q_MAX;
todo->event_id = event;
todo->data = data;
todo->delay = delay;
- wake_up(&dp_priv->event_q);
- spin_unlock_irqrestore(&dp_priv->event_lock, flag);
+ wake_up(&msm_dp_priv->event_q);
+ spin_unlock_irqrestore(&msm_dp_priv->event_lock, flag);
return 0;
}
-static int dp_del_event(struct dp_display_private *dp_priv, u32 event)
+static int msm_dp_del_event(struct msm_dp_display_private *msm_dp_priv, u32 event)
{
unsigned long flag;
- struct dp_event *todo;
+ struct msm_dp_event *todo;
u32 gndx;
- spin_lock_irqsave(&dp_priv->event_lock, flag);
- if (dp_priv->event_pndx == dp_priv->event_gndx) {
- spin_unlock_irqrestore(&dp_priv->event_lock, flag);
+ spin_lock_irqsave(&msm_dp_priv->event_lock, flag);
+ if (msm_dp_priv->event_pndx == msm_dp_priv->event_gndx) {
+ spin_unlock_irqrestore(&msm_dp_priv->event_lock, flag);
return -ENOENT;
}
- gndx = dp_priv->event_gndx;
- while (dp_priv->event_pndx != gndx) {
- todo = &dp_priv->event_list[gndx];
+ gndx = msm_dp_priv->event_gndx;
+ while (msm_dp_priv->event_pndx != gndx) {
+ todo = &msm_dp_priv->event_list[gndx];
if (todo->event_id == event) {
todo->event_id = EV_NO_EVENT; /* deleted */
todo->delay = 0;
@@ -232,60 +241,60 @@ static int dp_del_event(struct dp_display_private *dp_priv, u32 event)
gndx++;
gndx %= DP_EVENT_Q_MAX;
}
- spin_unlock_irqrestore(&dp_priv->event_lock, flag);
+ spin_unlock_irqrestore(&msm_dp_priv->event_lock, flag);
return 0;
}
-void dp_display_signal_audio_start(struct msm_dp *dp_display)
+void msm_dp_display_signal_audio_start(struct msm_dp *msm_dp_display)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
reinit_completion(&dp->audio_comp);
}
-void dp_display_signal_audio_complete(struct msm_dp *dp_display)
+void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
complete_all(&dp->audio_comp);
}
-static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv);
+static int msm_dp_hpd_event_thread_start(struct msm_dp_display_private *msm_dp_priv);
-static int dp_display_bind(struct device *dev, struct device *master,
+static int msm_dp_display_bind(struct device *dev, struct device *master,
void *data)
{
int rc = 0;
- struct dp_display_private *dp = dev_get_dp_display_private(dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
struct msm_drm_private *priv = dev_get_drvdata(master);
struct drm_device *drm = priv->dev;
- dp->dp_display.drm_dev = drm;
- priv->dp[dp->id] = &dp->dp_display;
+ dp->msm_dp_display.drm_dev = drm;
+ priv->dp[dp->id] = &dp->msm_dp_display;
dp->drm_dev = drm;
dp->aux->drm_dev = drm;
- rc = dp_aux_register(dp->aux);
+ rc = msm_dp_aux_register(dp->aux);
if (rc) {
DRM_ERROR("DRM DP AUX register failed\n");
goto end;
}
- rc = dp_register_audio_driver(dev, dp->audio);
+ rc = msm_dp_register_audio_driver(dev, dp->audio);
if (rc) {
DRM_ERROR("Audio registration Dp failed\n");
goto end;
}
- rc = dp_hpd_event_thread_start(dp);
+ rc = msm_dp_hpd_event_thread_start(dp);
if (rc) {
DRM_ERROR("Event thread create failed\n");
goto end;
@@ -296,44 +305,44 @@ end:
return rc;
}
-static void dp_display_unbind(struct device *dev, struct device *master,
+static void msm_dp_display_unbind(struct device *dev, struct device *master,
void *data)
{
- struct dp_display_private *dp = dev_get_dp_display_private(dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
struct msm_drm_private *priv = dev_get_drvdata(master);
kthread_stop(dp->ev_tsk);
of_dp_aux_depopulate_bus(dp->aux);
- dp_unregister_audio_driver(dev, dp->audio);
- dp_aux_unregister(dp->aux);
+ msm_dp_unregister_audio_driver(dev, dp->audio);
+ msm_dp_aux_unregister(dp->aux);
dp->drm_dev = NULL;
dp->aux->drm_dev = NULL;
priv->dp[dp->id] = NULL;
}
-static const struct component_ops dp_display_comp_ops = {
- .bind = dp_display_bind,
- .unbind = dp_display_unbind,
+static const struct component_ops msm_dp_display_comp_ops = {
+ .bind = msm_dp_display_bind,
+ .unbind = msm_dp_display_unbind,
};
-static void dp_display_send_hpd_event(struct msm_dp *dp_display)
+static void msm_dp_display_send_hpd_event(struct msm_dp *msm_dp_display)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
struct drm_connector *connector;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
- connector = dp->dp_display.connector;
+ connector = dp->msm_dp_display.connector;
drm_helper_hpd_irq_event(connector->dev);
}
-static int dp_display_send_hpd_notification(struct dp_display_private *dp,
+static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *dp,
bool hpd)
{
- if ((hpd && dp->dp_display.link_ready) ||
- (!hpd && !dp->dp_display.link_ready)) {
+ if ((hpd && dp->msm_dp_display.link_ready) ||
+ (!hpd && !dp->msm_dp_display.link_ready)) {
drm_dbg_dp(dp->drm_dev, "HPD already %s\n",
(hpd ? "on" : "off"));
return 0;
@@ -342,139 +351,139 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp,
/* reset video pattern flag on disconnect */
if (!hpd) {
dp->panel->video_test = false;
- if (!dp->dp_display.is_edp)
- drm_dp_set_subconnector_property(dp->dp_display.connector,
+ if (!dp->msm_dp_display.is_edp)
+ drm_dp_set_subconnector_property(dp->msm_dp_display.connector,
connector_status_disconnected,
dp->panel->dpcd,
dp->panel->downstream_ports);
}
- dp->dp_display.link_ready = hpd;
+ dp->msm_dp_display.link_ready = hpd;
drm_dbg_dp(dp->drm_dev, "type=%d hpd=%d\n",
- dp->dp_display.connector_type, hpd);
- dp_display_send_hpd_event(&dp->dp_display);
+ dp->msm_dp_display.connector_type, hpd);
+ msm_dp_display_send_hpd_event(&dp->msm_dp_display);
return 0;
}
-static int dp_display_process_hpd_high(struct dp_display_private *dp)
+static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp)
{
- struct drm_connector *connector = dp->dp_display.connector;
+ struct drm_connector *connector = dp->msm_dp_display.connector;
const struct drm_display_info *info = &connector->display_info;
int rc = 0;
- rc = dp_panel_read_sink_caps(dp->panel, connector);
+ rc = msm_dp_panel_read_sink_caps(dp->panel, connector);
if (rc)
goto end;
- dp_link_process_request(dp->link);
+ msm_dp_link_process_request(dp->link);
- if (!dp->dp_display.is_edp)
+ if (!dp->msm_dp_display.is_edp)
drm_dp_set_subconnector_property(connector,
connector_status_connected,
dp->panel->dpcd,
dp->panel->downstream_ports);
- dp->dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled;
+ dp->msm_dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled;
dp->audio_supported = info->has_audio;
- dp_panel_handle_sink_request(dp->panel);
+ msm_dp_panel_handle_sink_request(dp->panel);
/*
* set sink to normal operation mode -- D0
* before dpcd read
*/
- dp_link_psm_config(dp->link, &dp->panel->link_info, false);
+ msm_dp_link_psm_config(dp->link, &dp->panel->link_info, false);
- dp_link_reset_phy_params_vx_px(dp->link);
- rc = dp_ctrl_on_link(dp->ctrl);
+ msm_dp_link_reset_phy_params_vx_px(dp->link);
+ rc = msm_dp_ctrl_on_link(dp->ctrl);
if (rc) {
DRM_ERROR("failed to complete DP link training\n");
goto end;
}
- dp_add_event(dp, EV_USER_NOTIFICATION, true, 0);
+ msm_dp_add_event(dp, EV_USER_NOTIFICATION, true, 0);
end:
return rc;
}
-static void dp_display_host_phy_init(struct dp_display_private *dp)
+static void msm_dp_display_host_phy_init(struct msm_dp_display_private *dp)
{
drm_dbg_dp(dp->drm_dev, "type=%d core_init=%d phy_init=%d\n",
- dp->dp_display.connector_type, dp->core_initialized,
+ dp->msm_dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
if (!dp->phy_initialized) {
- dp_ctrl_phy_init(dp->ctrl);
+ msm_dp_ctrl_phy_init(dp->ctrl);
dp->phy_initialized = true;
}
}
-static void dp_display_host_phy_exit(struct dp_display_private *dp)
+static void msm_dp_display_host_phy_exit(struct msm_dp_display_private *dp)
{
drm_dbg_dp(dp->drm_dev, "type=%d core_init=%d phy_init=%d\n",
- dp->dp_display.connector_type, dp->core_initialized,
+ dp->msm_dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
if (dp->phy_initialized) {
- dp_ctrl_phy_exit(dp->ctrl);
+ msm_dp_ctrl_phy_exit(dp->ctrl);
dp->phy_initialized = false;
}
}
-static void dp_display_host_init(struct dp_display_private *dp)
+static void msm_dp_display_host_init(struct msm_dp_display_private *dp)
{
drm_dbg_dp(dp->drm_dev, "type=%d core_init=%d phy_init=%d\n",
- dp->dp_display.connector_type, dp->core_initialized,
+ dp->msm_dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
- dp_ctrl_core_clk_enable(dp->ctrl);
- dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
- dp_aux_init(dp->aux);
+ msm_dp_ctrl_core_clk_enable(dp->ctrl);
+ msm_dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
+ msm_dp_aux_init(dp->aux);
dp->core_initialized = true;
}
-static void dp_display_host_deinit(struct dp_display_private *dp)
+static void msm_dp_display_host_deinit(struct msm_dp_display_private *dp)
{
drm_dbg_dp(dp->drm_dev, "type=%d core_init=%d phy_init=%d\n",
- dp->dp_display.connector_type, dp->core_initialized,
+ dp->msm_dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
- dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
- dp_aux_deinit(dp->aux);
- dp_ctrl_core_clk_disable(dp->ctrl);
+ msm_dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
+ msm_dp_aux_deinit(dp->aux);
+ msm_dp_ctrl_core_clk_disable(dp->ctrl);
dp->core_initialized = false;
}
-static int dp_display_usbpd_configure_cb(struct device *dev)
+static int msm_dp_display_usbpd_configure_cb(struct device *dev)
{
- struct dp_display_private *dp = dev_get_dp_display_private(dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
- dp_display_host_phy_init(dp);
+ msm_dp_display_host_phy_init(dp);
- return dp_display_process_hpd_high(dp);
+ return msm_dp_display_process_hpd_high(dp);
}
-static int dp_display_notify_disconnect(struct device *dev)
+static int msm_dp_display_notify_disconnect(struct device *dev)
{
- struct dp_display_private *dp = dev_get_dp_display_private(dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
- dp_add_event(dp, EV_USER_NOTIFICATION, false, 0);
+ msm_dp_add_event(dp, EV_USER_NOTIFICATION, false, 0);
return 0;
}
-static void dp_display_handle_video_request(struct dp_display_private *dp)
+static void msm_dp_display_handle_video_request(struct msm_dp_display_private *dp)
{
if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN) {
dp->panel->video_test = true;
- dp_link_send_test_response(dp->link);
+ msm_dp_link_send_test_response(dp->link);
}
}
-static int dp_display_handle_port_status_changed(struct dp_display_private *dp)
+static int msm_dp_display_handle_port_status_changed(struct msm_dp_display_private *dp)
{
int rc = 0;
@@ -482,12 +491,12 @@ static int dp_display_handle_port_status_changed(struct dp_display_private *dp)
drm_dbg_dp(dp->drm_dev, "sink count is zero, nothing to do\n");
if (dp->hpd_state != ST_DISCONNECTED) {
dp->hpd_state = ST_DISCONNECT_PENDING;
- dp_add_event(dp, EV_USER_NOTIFICATION, false, 0);
+ msm_dp_add_event(dp, EV_USER_NOTIFICATION, false, 0);
}
} else {
if (dp->hpd_state == ST_DISCONNECTED) {
dp->hpd_state = ST_MAINLINK_READY;
- rc = dp_display_process_hpd_high(dp);
+ rc = msm_dp_display_process_hpd_high(dp);
if (rc)
dp->hpd_state = ST_DISCONNECTED;
}
@@ -496,7 +505,7 @@ static int dp_display_handle_port_status_changed(struct dp_display_private *dp)
return rc;
}
-static int dp_display_handle_irq_hpd(struct dp_display_private *dp)
+static int msm_dp_display_handle_irq_hpd(struct msm_dp_display_private *dp)
{
u32 sink_request = dp->link->sink_request;
@@ -510,48 +519,48 @@ static int dp_display_handle_irq_hpd(struct dp_display_private *dp)
}
}
- dp_ctrl_handle_sink_request(dp->ctrl);
+ msm_dp_ctrl_handle_sink_request(dp->ctrl);
if (sink_request & DP_TEST_LINK_VIDEO_PATTERN)
- dp_display_handle_video_request(dp);
+ msm_dp_display_handle_video_request(dp);
return 0;
}
-static int dp_display_usbpd_attention_cb(struct device *dev)
+static int msm_dp_display_usbpd_attention_cb(struct device *dev)
{
int rc = 0;
u32 sink_request;
- struct dp_display_private *dp = dev_get_dp_display_private(dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
/* check for any test request issued by sink */
- rc = dp_link_process_request(dp->link);
+ rc = msm_dp_link_process_request(dp->link);
if (!rc) {
sink_request = dp->link->sink_request;
drm_dbg_dp(dp->drm_dev, "hpd_state=%d sink_request=%d\n",
dp->hpd_state, sink_request);
if (sink_request & DS_PORT_STATUS_CHANGED)
- rc = dp_display_handle_port_status_changed(dp);
+ rc = msm_dp_display_handle_port_status_changed(dp);
else
- rc = dp_display_handle_irq_hpd(dp);
+ rc = msm_dp_display_handle_irq_hpd(dp);
}
return rc;
}
-static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
+static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp, u32 data)
{
u32 state;
int ret;
- struct platform_device *pdev = dp->dp_display.pdev;
+ struct platform_device *pdev = dp->msm_dp_display.pdev;
- dp_aux_enable_xfers(dp->aux, true);
+ msm_dp_aux_enable_xfers(dp->aux, true);
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
drm_dbg_dp(dp->drm_dev, "Before, type=%d hpd_state=%d\n",
- dp->dp_display.connector_type, state);
+ dp->msm_dp_display.connector_type, state);
if (state == ST_DISPLAY_OFF) {
mutex_unlock(&dp->event_mutex);
@@ -565,7 +574,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
if (state == ST_DISCONNECT_PENDING) {
/* wait until ST_DISCONNECTED */
- dp_add_event(dp, EV_HPD_PLUG_INT, 0, 1); /* delay = 1 */
+ msm_dp_add_event(dp, EV_HPD_PLUG_INT, 0, 1); /* delay = 1 */
mutex_unlock(&dp->event_mutex);
return 0;
}
@@ -577,7 +586,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
return ret;
}
- ret = dp_display_usbpd_configure_cb(&pdev->dev);
+ ret = msm_dp_display_usbpd_configure_cb(&pdev->dev);
if (ret) { /* link train failed */
dp->hpd_state = ST_DISCONNECTED;
pm_runtime_put_sync(&pdev->dev);
@@ -586,60 +595,60 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
}
drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n",
- dp->dp_display.connector_type, state);
+ dp->msm_dp_display.connector_type, state);
mutex_unlock(&dp->event_mutex);
/* uevent will complete connection part */
return 0;
};
-static void dp_display_handle_plugged_change(struct msm_dp *dp_display,
+static void msm_dp_display_handle_plugged_change(struct msm_dp *msm_dp_display,
bool plugged)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
- dp = container_of(dp_display,
- struct dp_display_private, dp_display);
+ dp = container_of(msm_dp_display,
+ struct msm_dp_display_private, msm_dp_display);
/* notify audio subsystem only if sink supports audio */
- if (dp_display->plugged_cb && dp_display->codec_dev &&
+ if (msm_dp_display->plugged_cb && msm_dp_display->codec_dev &&
dp->audio_supported)
- dp_display->plugged_cb(dp_display->codec_dev, plugged);
+ msm_dp_display->plugged_cb(msm_dp_display->codec_dev, plugged);
}
-static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
+static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp, u32 data)
{
u32 state;
- struct platform_device *pdev = dp->dp_display.pdev;
+ struct platform_device *pdev = dp->msm_dp_display.pdev;
- dp_aux_enable_xfers(dp->aux, false);
+ msm_dp_aux_enable_xfers(dp->aux, false);
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
drm_dbg_dp(dp->drm_dev, "Before, type=%d hpd_state=%d\n",
- dp->dp_display.connector_type, state);
+ dp->msm_dp_display.connector_type, state);
/* unplugged, no more irq_hpd handle */
- dp_del_event(dp, EV_IRQ_HPD_INT);
+ msm_dp_del_event(dp, EV_IRQ_HPD_INT);
if (state == ST_DISCONNECTED) {
/* triggered by irq_hdp with sink_count = 0 */
if (dp->link->sink_count == 0) {
- dp_display_host_phy_exit(dp);
+ msm_dp_display_host_phy_exit(dp);
}
- dp_display_notify_disconnect(&dp->dp_display.pdev->dev);
+ msm_dp_display_notify_disconnect(&dp->msm_dp_display.pdev->dev);
mutex_unlock(&dp->event_mutex);
return 0;
} else if (state == ST_DISCONNECT_PENDING) {
mutex_unlock(&dp->event_mutex);
return 0;
} else if (state == ST_MAINLINK_READY) {
- dp_ctrl_off_link(dp->ctrl);
- dp_display_host_phy_exit(dp);
+ msm_dp_ctrl_off_link(dp->ctrl);
+ msm_dp_display_host_phy_exit(dp);
dp->hpd_state = ST_DISCONNECTED;
- dp_display_notify_disconnect(&dp->dp_display.pdev->dev);
+ msm_dp_display_notify_disconnect(&dp->msm_dp_display.pdev->dev);
pm_runtime_put_sync(&pdev->dev);
mutex_unlock(&dp->event_mutex);
return 0;
@@ -649,7 +658,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
* We don't need separate work for disconnect as
* connect/attention interrupts are disabled
*/
- dp_display_notify_disconnect(&dp->dp_display.pdev->dev);
+ msm_dp_display_notify_disconnect(&dp->msm_dp_display.pdev->dev);
if (state == ST_DISPLAY_OFF) {
dp->hpd_state = ST_DISCONNECTED;
@@ -658,10 +667,10 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
}
/* signal the disconnect event early to ensure proper teardown */
- dp_display_handle_plugged_change(&dp->dp_display, false);
+ msm_dp_display_handle_plugged_change(&dp->msm_dp_display, false);
drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n",
- dp->dp_display.connector_type, state);
+ dp->msm_dp_display.connector_type, state);
/* uevent will complete disconnection part */
pm_runtime_put_sync(&pdev->dev);
@@ -669,7 +678,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
return 0;
}
-static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
+static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp, u32 data)
{
u32 state;
@@ -678,7 +687,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
/* irq_hpd can happen at either connected or disconnected state */
state = dp->hpd_state;
drm_dbg_dp(dp->drm_dev, "Before, type=%d hpd_state=%d\n",
- dp->dp_display.connector_type, state);
+ dp->msm_dp_display.connector_type, state);
if (state == ST_DISPLAY_OFF) {
mutex_unlock(&dp->event_mutex);
@@ -687,33 +696,33 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
if (state == ST_MAINLINK_READY || state == ST_DISCONNECT_PENDING) {
/* wait until ST_CONNECTED */
- dp_add_event(dp, EV_IRQ_HPD_INT, 0, 1); /* delay = 1 */
+ msm_dp_add_event(dp, EV_IRQ_HPD_INT, 0, 1); /* delay = 1 */
mutex_unlock(&dp->event_mutex);
return 0;
}
- dp_display_usbpd_attention_cb(&dp->dp_display.pdev->dev);
+ msm_dp_display_usbpd_attention_cb(&dp->msm_dp_display.pdev->dev);
drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n",
- dp->dp_display.connector_type, state);
+ dp->msm_dp_display.connector_type, state);
mutex_unlock(&dp->event_mutex);
return 0;
}
-static void dp_display_deinit_sub_modules(struct dp_display_private *dp)
+static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp)
{
- dp_audio_put(dp->audio);
- dp_panel_put(dp->panel);
- dp_aux_put(dp->aux);
+ msm_dp_audio_put(dp->audio);
+ msm_dp_panel_put(dp->panel);
+ msm_dp_aux_put(dp->aux);
}
-static int dp_init_sub_modules(struct dp_display_private *dp)
+static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp)
{
int rc = 0;
- struct device *dev = &dp->dp_display.pdev->dev;
- struct dp_panel_in panel_in = {
+ struct device *dev = &dp->msm_dp_display.pdev->dev;
+ struct msm_dp_panel_in panel_in = {
.dev = dev,
};
struct phy *phy;
@@ -723,14 +732,14 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
return PTR_ERR(phy);
rc = phy_set_mode_ext(phy, PHY_MODE_DP,
- dp->dp_display.is_edp ? PHY_SUBMODE_EDP : PHY_SUBMODE_DP);
+ dp->msm_dp_display.is_edp ? PHY_SUBMODE_EDP : PHY_SUBMODE_DP);
if (rc) {
DRM_ERROR("failed to set phy submode, rc = %d\n", rc);
dp->catalog = NULL;
goto error;
}
- dp->catalog = dp_catalog_get(dev);
+ dp->catalog = msm_dp_catalog_get(dev);
if (IS_ERR(dp->catalog)) {
rc = PTR_ERR(dp->catalog);
DRM_ERROR("failed to initialize catalog, rc = %d\n", rc);
@@ -738,9 +747,9 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
goto error;
}
- dp->aux = dp_aux_get(dev, dp->catalog,
+ dp->aux = msm_dp_aux_get(dev, dp->catalog,
phy,
- dp->dp_display.is_edp);
+ dp->msm_dp_display.is_edp);
if (IS_ERR(dp->aux)) {
rc = PTR_ERR(dp->aux);
DRM_ERROR("failed to initialize aux, rc = %d\n", rc);
@@ -748,7 +757,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
goto error;
}
- dp->link = dp_link_get(dev, dp->aux);
+ dp->link = msm_dp_link_get(dev, dp->aux);
if (IS_ERR(dp->link)) {
rc = PTR_ERR(dp->link);
DRM_ERROR("failed to initialize link, rc = %d\n", rc);
@@ -760,7 +769,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
panel_in.catalog = dp->catalog;
panel_in.link = dp->link;
- dp->panel = dp_panel_get(&panel_in);
+ dp->panel = msm_dp_panel_get(&panel_in);
if (IS_ERR(dp->panel)) {
rc = PTR_ERR(dp->panel);
DRM_ERROR("failed to initialize panel, rc = %d\n", rc);
@@ -768,7 +777,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
goto error_link;
}
- dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux,
+ dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux,
dp->catalog,
phy);
if (IS_ERR(dp->ctrl)) {
@@ -778,7 +787,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
goto error_ctrl;
}
- dp->audio = dp_audio_get(dp->dp_display.pdev, dp->panel, dp->catalog);
+ dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->panel, dp->catalog);
if (IS_ERR(dp->audio)) {
rc = PTR_ERR(dp->audio);
pr_err("failed to initialize audio, rc = %d\n", rc);
@@ -789,51 +798,51 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
return rc;
error_ctrl:
- dp_panel_put(dp->panel);
+ msm_dp_panel_put(dp->panel);
error_link:
- dp_aux_put(dp->aux);
+ msm_dp_aux_put(dp->aux);
error:
return rc;
}
-static int dp_display_set_mode(struct msm_dp *dp_display,
- struct dp_display_mode *mode)
+static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display,
+ struct msm_dp_display_mode *mode)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
- drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode);
- dp->panel->dp_mode.bpp = mode->bpp;
- dp->panel->dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;
- dp_panel_init_panel_info(dp->panel);
+ drm_mode_copy(&dp->panel->msm_dp_mode.drm_mode, &mode->drm_mode);
+ dp->panel->msm_dp_mode.bpp = mode->bpp;
+ dp->panel->msm_dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;
+ msm_dp_panel_init_panel_info(dp->panel);
return 0;
}
-static int dp_display_enable(struct dp_display_private *dp, bool force_link_train)
+static int msm_dp_display_enable(struct msm_dp_display_private *dp, bool force_link_train)
{
int rc = 0;
- struct msm_dp *dp_display = &dp->dp_display;
+ struct msm_dp *msm_dp_display = &dp->msm_dp_display;
drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count);
- if (dp_display->power_on) {
+ if (msm_dp_display->power_on) {
drm_dbg_dp(dp->drm_dev, "Link already setup, return\n");
return 0;
}
- rc = dp_ctrl_on_stream(dp->ctrl, force_link_train);
+ rc = msm_dp_ctrl_on_stream(dp->ctrl, force_link_train);
if (!rc)
- dp_display->power_on = true;
+ msm_dp_display->power_on = true;
return rc;
}
-static int dp_display_post_enable(struct msm_dp *dp_display)
+static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
u32 rate;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
rate = dp->link->link_params.rate;
@@ -843,85 +852,85 @@ static int dp_display_post_enable(struct msm_dp *dp_display)
}
/* signal the connect event late to synchronize video and display */
- dp_display_handle_plugged_change(dp_display, true);
+ msm_dp_display_handle_plugged_change(msm_dp_display, true);
- if (dp_display->psr_supported)
- dp_ctrl_config_psr(dp->ctrl);
+ if (msm_dp_display->psr_supported)
+ msm_dp_ctrl_config_psr(dp->ctrl);
return 0;
}
-static int dp_display_disable(struct dp_display_private *dp)
+static int msm_dp_display_disable(struct msm_dp_display_private *dp)
{
- struct msm_dp *dp_display = &dp->dp_display;
+ struct msm_dp *msm_dp_display = &dp->msm_dp_display;
- if (!dp_display->power_on)
+ if (!msm_dp_display->power_on)
return 0;
/* wait only if audio was enabled */
- if (dp_display->audio_enabled) {
+ if (msm_dp_display->audio_enabled) {
/* signal the disconnect event */
- dp_display_handle_plugged_change(dp_display, false);
+ msm_dp_display_handle_plugged_change(msm_dp_display, false);
if (!wait_for_completion_timeout(&dp->audio_comp,
HZ * 5))
DRM_ERROR("audio comp timeout\n");
}
- dp_display->audio_enabled = false;
+ msm_dp_display->audio_enabled = false;
if (dp->link->sink_count == 0) {
/*
* irq_hpd with sink_count = 0
* hdmi unplugged out of dongle
*/
- dp_ctrl_off_link_stream(dp->ctrl);
+ msm_dp_ctrl_off_link_stream(dp->ctrl);
} else {
/*
* unplugged interrupt
* dongle unplugged out of DUT
*/
- dp_ctrl_off(dp->ctrl);
- dp_display_host_phy_exit(dp);
+ msm_dp_ctrl_off(dp->ctrl);
+ msm_dp_display_host_phy_exit(dp);
}
- dp_display->power_on = false;
+ msm_dp_display->power_on = false;
drm_dbg_dp(dp->drm_dev, "sink count: %d\n", dp->link->sink_count);
return 0;
}
-int dp_display_set_plugged_cb(struct msm_dp *dp_display,
+int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display,
hdmi_codec_plugged_cb fn, struct device *codec_dev)
{
bool plugged;
- dp_display->plugged_cb = fn;
- dp_display->codec_dev = codec_dev;
- plugged = dp_display->link_ready;
- dp_display_handle_plugged_change(dp_display, plugged);
+ msm_dp_display->plugged_cb = fn;
+ msm_dp_display->codec_dev = codec_dev;
+ plugged = msm_dp_display->link_ready;
+ msm_dp_display_handle_plugged_change(msm_dp_display, plugged);
return 0;
}
/**
- * dp_bridge_mode_valid - callback to determine if specified mode is valid
+ * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid
* @bridge: Pointer to drm bridge structure
* @info: display info
* @mode: Pointer to drm mode structure
* Returns: Validity status for specified mode
*/
-enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
+enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_info *info,
const struct drm_display_mode *mode)
{
const u32 num_components = 3, default_bpp = 24;
- struct dp_display_private *dp_display;
- struct dp_link_info *link_info;
+ struct msm_dp_display_private *msm_dp_display;
+ struct msm_dp_link_info *link_info;
u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
struct msm_dp *dp;
int mode_pclk_khz = mode->clock;
- dp = to_dp_bridge(bridge)->dp_display;
+ dp = to_dp_bridge(bridge)->msm_dp_display;
if (!dp || !mode_pclk_khz || !dp->connector) {
DRM_ERROR("invalid params\n");
@@ -931,18 +940,18 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
if (mode->clock > DP_MAX_PIXEL_CLK_KHZ)
return MODE_CLOCK_HIGH;
- dp_display = container_of(dp, struct dp_display_private, dp_display);
- link_info = &dp_display->panel->link_info;
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
+ link_info = &msm_dp_display->panel->link_info;
if (drm_mode_is_420_only(&dp->connector->display_info, mode) &&
- dp_display->panel->vsc_sdp_supported)
+ msm_dp_display->panel->vsc_sdp_supported)
mode_pclk_khz /= 2;
mode_bpp = dp->connector->display_info.bpc * num_components;
if (!mode_bpp)
mode_bpp = default_bpp;
- mode_bpp = dp_panel_get_mode_bpp(dp_display->panel,
+ mode_bpp = msm_dp_panel_get_mode_bpp(msm_dp_display->panel,
mode_bpp, mode_pclk_khz);
mode_rate_khz = mode_pclk_khz * mode_bpp;
@@ -954,50 +963,50 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-int dp_display_get_modes(struct msm_dp *dp)
+int msm_dp_display_get_modes(struct msm_dp *dp)
{
- struct dp_display_private *dp_display;
+ struct msm_dp_display_private *msm_dp_display;
if (!dp) {
DRM_ERROR("invalid params\n");
return 0;
}
- dp_display = container_of(dp, struct dp_display_private, dp_display);
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
- return dp_panel_get_modes(dp_display->panel,
+ return msm_dp_panel_get_modes(msm_dp_display->panel,
dp->connector);
}
-bool dp_display_check_video_test(struct msm_dp *dp)
+bool msm_dp_display_check_video_test(struct msm_dp *dp)
{
- struct dp_display_private *dp_display;
+ struct msm_dp_display_private *msm_dp_display;
- dp_display = container_of(dp, struct dp_display_private, dp_display);
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
- return dp_display->panel->video_test;
+ return msm_dp_display->panel->video_test;
}
-int dp_display_get_test_bpp(struct msm_dp *dp)
+int msm_dp_display_get_test_bpp(struct msm_dp *dp)
{
- struct dp_display_private *dp_display;
+ struct msm_dp_display_private *msm_dp_display;
if (!dp) {
DRM_ERROR("invalid params\n");
return 0;
}
- dp_display = container_of(dp, struct dp_display_private, dp_display);
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
- return dp_link_bit_depth_to_bpp(
- dp_display->link->test_video.test_bit_depth);
+ return msm_dp_link_bit_depth_to_bpp(
+ msm_dp_display->link->test_video.test_bit_depth);
}
void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
{
- struct dp_display_private *dp_display;
+ struct msm_dp_display_private *msm_dp_display;
- dp_display = container_of(dp, struct dp_display_private, dp_display);
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
/*
* if we are reading registers we need the link clocks to be on
@@ -1006,65 +1015,65 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
* power_on status before dumping DP registers to avoid crash due
* to unclocked access
*/
- mutex_lock(&dp_display->event_mutex);
+ mutex_lock(&msm_dp_display->event_mutex);
if (!dp->power_on) {
- mutex_unlock(&dp_display->event_mutex);
+ mutex_unlock(&msm_dp_display->event_mutex);
return;
}
- dp_catalog_snapshot(dp_display->catalog, disp_state);
+ msm_dp_catalog_snapshot(msm_dp_display->catalog, disp_state);
- mutex_unlock(&dp_display->event_mutex);
+ mutex_unlock(&msm_dp_display->event_mutex);
}
-void dp_display_set_psr(struct msm_dp *dp_display, bool enter)
+void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
- if (!dp_display) {
+ if (!msm_dp_display) {
DRM_ERROR("invalid params\n");
return;
}
- dp = container_of(dp_display, struct dp_display_private, dp_display);
- dp_ctrl_set_psr(dp->ctrl, enter);
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
+ msm_dp_ctrl_set_psr(dp->ctrl, enter);
}
static int hpd_event_thread(void *data)
{
- struct dp_display_private *dp_priv;
+ struct msm_dp_display_private *msm_dp_priv;
unsigned long flag;
- struct dp_event *todo;
+ struct msm_dp_event *todo;
int timeout_mode = 0;
- dp_priv = (struct dp_display_private *)data;
+ msm_dp_priv = (struct msm_dp_display_private *)data;
while (1) {
if (timeout_mode) {
- wait_event_timeout(dp_priv->event_q,
- (dp_priv->event_pndx == dp_priv->event_gndx) ||
+ wait_event_timeout(msm_dp_priv->event_q,
+ (msm_dp_priv->event_pndx == msm_dp_priv->event_gndx) ||
kthread_should_stop(), EVENT_TIMEOUT);
} else {
- wait_event_interruptible(dp_priv->event_q,
- (dp_priv->event_pndx != dp_priv->event_gndx) ||
+ wait_event_interruptible(msm_dp_priv->event_q,
+ (msm_dp_priv->event_pndx != msm_dp_priv->event_gndx) ||
kthread_should_stop());
}
if (kthread_should_stop())
break;
- spin_lock_irqsave(&dp_priv->event_lock, flag);
- todo = &dp_priv->event_list[dp_priv->event_gndx];
+ spin_lock_irqsave(&msm_dp_priv->event_lock, flag);
+ todo = &msm_dp_priv->event_list[msm_dp_priv->event_gndx];
if (todo->delay) {
- struct dp_event *todo_next;
+ struct msm_dp_event *todo_next;
- dp_priv->event_gndx++;
- dp_priv->event_gndx %= DP_EVENT_Q_MAX;
+ msm_dp_priv->event_gndx++;
+ msm_dp_priv->event_gndx %= DP_EVENT_Q_MAX;
/* re enter delay event into q */
- todo_next = &dp_priv->event_list[dp_priv->event_pndx++];
- dp_priv->event_pndx %= DP_EVENT_Q_MAX;
+ todo_next = &msm_dp_priv->event_list[msm_dp_priv->event_pndx++];
+ msm_dp_priv->event_pndx %= DP_EVENT_Q_MAX;
todo_next->event_id = todo->event_id;
todo_next->data = todo->data;
todo_next->delay = todo->delay - 1;
@@ -1075,33 +1084,33 @@ static int hpd_event_thread(void *data)
/* switch to timeout mode */
timeout_mode = 1;
- spin_unlock_irqrestore(&dp_priv->event_lock, flag);
+ spin_unlock_irqrestore(&msm_dp_priv->event_lock, flag);
continue;
}
/* timeout with no events in q */
- if (dp_priv->event_pndx == dp_priv->event_gndx) {
- spin_unlock_irqrestore(&dp_priv->event_lock, flag);
+ if (msm_dp_priv->event_pndx == msm_dp_priv->event_gndx) {
+ spin_unlock_irqrestore(&msm_dp_priv->event_lock, flag);
continue;
}
- dp_priv->event_gndx++;
- dp_priv->event_gndx %= DP_EVENT_Q_MAX;
+ msm_dp_priv->event_gndx++;
+ msm_dp_priv->event_gndx %= DP_EVENT_Q_MAX;
timeout_mode = 0;
- spin_unlock_irqrestore(&dp_priv->event_lock, flag);
+ spin_unlock_irqrestore(&msm_dp_priv->event_lock, flag);
switch (todo->event_id) {
case EV_HPD_PLUG_INT:
- dp_hpd_plug_handle(dp_priv, todo->data);
+ msm_dp_hpd_plug_handle(msm_dp_priv, todo->data);
break;
case EV_HPD_UNPLUG_INT:
- dp_hpd_unplug_handle(dp_priv, todo->data);
+ msm_dp_hpd_unplug_handle(msm_dp_priv, todo->data);
break;
case EV_IRQ_HPD_INT:
- dp_irq_hpd_handle(dp_priv, todo->data);
+ msm_dp_irq_hpd_handle(msm_dp_priv, todo->data);
break;
case EV_USER_NOTIFICATION:
- dp_display_send_hpd_notification(dp_priv,
+ msm_dp_display_send_hpd_notification(msm_dp_priv,
todo->data);
break;
default:
@@ -1112,22 +1121,22 @@ static int hpd_event_thread(void *data)
return 0;
}
-static int dp_hpd_event_thread_start(struct dp_display_private *dp_priv)
+static int msm_dp_hpd_event_thread_start(struct msm_dp_display_private *msm_dp_priv)
{
/* set event q to empty */
- dp_priv->event_gndx = 0;
- dp_priv->event_pndx = 0;
+ msm_dp_priv->event_gndx = 0;
+ msm_dp_priv->event_pndx = 0;
- dp_priv->ev_tsk = kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler");
- if (IS_ERR(dp_priv->ev_tsk))
- return PTR_ERR(dp_priv->ev_tsk);
+ msm_dp_priv->ev_tsk = kthread_run(hpd_event_thread, msm_dp_priv, "dp_hpd_handler");
+ if (IS_ERR(msm_dp_priv->ev_tsk))
+ return PTR_ERR(msm_dp_priv->ev_tsk);
return 0;
}
-static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
+static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id)
{
- struct dp_display_private *dp = dev_id;
+ struct msm_dp_display_private *dp = dev_id;
irqreturn_t ret = IRQ_NONE;
u32 hpd_isr_status;
@@ -1136,43 +1145,43 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
}
- hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog);
+ hpd_isr_status = msm_dp_catalog_hpd_get_intr_status(dp->catalog);
if (hpd_isr_status & 0x0F) {
drm_dbg_dp(dp->drm_dev, "type=%d isr=0x%x\n",
- dp->dp_display.connector_type, hpd_isr_status);
+ dp->msm_dp_display.connector_type, hpd_isr_status);
/* hpd related interrupts */
if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK)
- dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
+ msm_dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) {
- dp_add_event(dp, EV_IRQ_HPD_INT, 0, 0);
+ msm_dp_add_event(dp, EV_IRQ_HPD_INT, 0, 0);
}
if (hpd_isr_status & DP_DP_HPD_REPLUG_INT_MASK) {
- dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
- dp_add_event(dp, EV_HPD_PLUG_INT, 0, 3);
+ msm_dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
+ msm_dp_add_event(dp, EV_HPD_PLUG_INT, 0, 3);
}
if (hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK)
- dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
+ msm_dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
ret = IRQ_HANDLED;
}
/* DP controller isr */
- ret |= dp_ctrl_isr(dp->ctrl);
+ ret |= msm_dp_ctrl_isr(dp->ctrl);
/* DP aux isr */
- ret |= dp_aux_isr(dp->aux);
+ ret |= msm_dp_aux_isr(dp->aux);
return ret;
}
-static int dp_display_request_irq(struct dp_display_private *dp)
+static int msm_dp_display_request_irq(struct msm_dp_display_private *dp)
{
int rc = 0;
- struct platform_device *pdev = dp->dp_display.pdev;
+ struct platform_device *pdev = dp->msm_dp_display.pdev;
dp->irq = platform_get_irq(pdev, 0);
if (dp->irq < 0) {
@@ -1180,7 +1189,7 @@ static int dp_display_request_irq(struct dp_display_private *dp)
return dp->irq;
}
- rc = devm_request_irq(&pdev->dev, dp->irq, dp_display_irq_handler,
+ rc = devm_request_irq(&pdev->dev, dp->irq, msm_dp_display_irq_handler,
IRQF_TRIGGER_HIGH|IRQF_NO_AUTOEN,
"dp_display_isr", dp);
@@ -1193,7 +1202,7 @@ static int dp_display_request_irq(struct dp_display_private *dp)
return 0;
}
-static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pdev)
+static const struct msm_dp_desc *msm_dp_display_get_desc(struct platform_device *pdev)
{
const struct msm_dp_desc *descs = of_device_get_match_data(&pdev->dev);
struct resource *res;
@@ -1212,7 +1221,7 @@ static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pde
return NULL;
}
-static int dp_display_probe_tail(struct device *dev)
+static int msm_dp_display_probe_tail(struct device *dev)
{
struct msm_dp *dp = dev_get_drvdata(dev);
int ret;
@@ -1232,19 +1241,19 @@ static int dp_display_probe_tail(struct device *dev)
return ret;
}
- ret = component_add(dev, &dp_display_comp_ops);
+ ret = component_add(dev, &msm_dp_display_comp_ops);
if (ret)
DRM_ERROR("component add failed, rc=%d\n", ret);
return ret;
}
-static int dp_auxbus_done_probe(struct drm_dp_aux *aux)
+static int msm_dp_auxbus_done_probe(struct drm_dp_aux *aux)
{
- return dp_display_probe_tail(aux->dev);
+ return msm_dp_display_probe_tail(aux->dev);
}
-static int dp_display_get_connector_type(struct platform_device *pdev,
+static int msm_dp_display_get_connector_type(struct platform_device *pdev,
const struct msm_dp_desc *desc)
{
struct device_node *node = pdev->dev.of_node;
@@ -1263,10 +1272,10 @@ static int dp_display_get_connector_type(struct platform_device *pdev,
return connector_type;
}
-static int dp_display_probe(struct platform_device *pdev)
+static int msm_dp_display_probe(struct platform_device *pdev)
{
int rc = 0;
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
const struct msm_dp_desc *desc;
if (!pdev || !pdev->dev.of_node) {
@@ -1278,18 +1287,18 @@ static int dp_display_probe(struct platform_device *pdev)
if (!dp)
return -ENOMEM;
- desc = dp_display_get_desc(pdev);
+ desc = msm_dp_display_get_desc(pdev);
if (!desc)
return -EINVAL;
- dp->dp_display.pdev = pdev;
+ dp->msm_dp_display.pdev = pdev;
dp->id = desc->id;
- dp->dp_display.connector_type = dp_display_get_connector_type(pdev, desc);
+ dp->msm_dp_display.connector_type = msm_dp_display_get_connector_type(pdev, desc);
dp->wide_bus_supported = desc->wide_bus_supported;
- dp->dp_display.is_edp =
- (dp->dp_display.connector_type == DRM_MODE_CONNECTOR_eDP);
+ dp->msm_dp_display.is_edp =
+ (dp->msm_dp_display.connector_type == DRM_MODE_CONNECTOR_eDP);
- rc = dp_init_sub_modules(dp);
+ rc = msm_dp_init_sub_modules(dp);
if (rc) {
DRM_ERROR("init sub module failed\n");
return -EPROBE_DEFER;
@@ -1301,28 +1310,28 @@ static int dp_display_probe(struct platform_device *pdev)
spin_lock_init(&dp->event_lock);
/* Store DP audio handle inside DP display */
- dp->dp_display.dp_audio = dp->audio;
+ dp->msm_dp_display.msm_dp_audio = dp->audio;
init_completion(&dp->audio_comp);
- platform_set_drvdata(pdev, &dp->dp_display);
+ platform_set_drvdata(pdev, &dp->msm_dp_display);
rc = devm_pm_runtime_enable(&pdev->dev);
if (rc)
goto err;
- rc = dp_display_request_irq(dp);
+ rc = msm_dp_display_request_irq(dp);
if (rc)
goto err;
- if (dp->dp_display.is_edp) {
- rc = devm_of_dp_aux_populate_bus(dp->aux, dp_auxbus_done_probe);
+ if (dp->msm_dp_display.is_edp) {
+ rc = devm_of_dp_aux_populate_bus(dp->aux, msm_dp_auxbus_done_probe);
if (rc) {
DRM_ERROR("eDP auxbus population failed, rc=%d\n", rc);
goto err;
}
} else {
- rc = dp_display_probe_tail(&pdev->dev);
+ rc = msm_dp_display_probe_tail(&pdev->dev);
if (rc)
goto err;
}
@@ -1330,70 +1339,70 @@ static int dp_display_probe(struct platform_device *pdev)
return rc;
err:
- dp_display_deinit_sub_modules(dp);
+ msm_dp_display_deinit_sub_modules(dp);
return rc;
}
-static void dp_display_remove(struct platform_device *pdev)
+static void msm_dp_display_remove(struct platform_device *pdev)
{
- struct dp_display_private *dp = dev_get_dp_display_private(&pdev->dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(&pdev->dev);
- component_del(&pdev->dev, &dp_display_comp_ops);
- dp_display_deinit_sub_modules(dp);
+ component_del(&pdev->dev, &msm_dp_display_comp_ops);
+ msm_dp_display_deinit_sub_modules(dp);
platform_set_drvdata(pdev, NULL);
}
-static int dp_pm_runtime_suspend(struct device *dev)
+static int msm_dp_pm_runtime_suspend(struct device *dev)
{
- struct dp_display_private *dp = dev_get_dp_display_private(dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
disable_irq(dp->irq);
- if (dp->dp_display.is_edp) {
- dp_display_host_phy_exit(dp);
- dp_catalog_ctrl_hpd_disable(dp->catalog);
+ if (dp->msm_dp_display.is_edp) {
+ msm_dp_display_host_phy_exit(dp);
+ msm_dp_catalog_ctrl_hpd_disable(dp->catalog);
}
- dp_display_host_deinit(dp);
+ msm_dp_display_host_deinit(dp);
return 0;
}
-static int dp_pm_runtime_resume(struct device *dev)
+static int msm_dp_pm_runtime_resume(struct device *dev)
{
- struct dp_display_private *dp = dev_get_dp_display_private(dev);
+ struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
/*
* for eDP, host cotroller, HPD block and PHY are enabled here
* but with HPD irq disabled
*
* for DP, only host controller is enabled here.
- * HPD block is enabled at dp_bridge_hpd_enable()
+ * HPD block is enabled at msm_dp_bridge_hpd_enable()
* PHY will be enabled at plugin handler later
*/
- dp_display_host_init(dp);
- if (dp->dp_display.is_edp) {
- dp_catalog_ctrl_hpd_enable(dp->catalog);
- dp_display_host_phy_init(dp);
+ msm_dp_display_host_init(dp);
+ if (dp->msm_dp_display.is_edp) {
+ msm_dp_catalog_ctrl_hpd_enable(dp->catalog);
+ msm_dp_display_host_phy_init(dp);
}
enable_irq(dp->irq);
return 0;
}
-static const struct dev_pm_ops dp_pm_ops = {
- SET_RUNTIME_PM_OPS(dp_pm_runtime_suspend, dp_pm_runtime_resume, NULL)
+static const struct dev_pm_ops msm_dp_pm_ops = {
+ SET_RUNTIME_PM_OPS(msm_dp_pm_runtime_suspend, msm_dp_pm_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
-static struct platform_driver dp_display_driver = {
- .probe = dp_display_probe,
- .remove_new = dp_display_remove,
+static struct platform_driver msm_dp_display_driver = {
+ .probe = msm_dp_display_probe,
+ .remove_new = msm_dp_display_remove,
.driver = {
.name = "msm-dp-display",
- .of_match_table = dp_dt_match,
+ .of_match_table = msm_dp_dt_match,
.suppress_bind_attrs = true,
- .pm = &dp_pm_ops,
+ .pm = &msm_dp_pm_ops,
},
};
@@ -1401,7 +1410,7 @@ int __init msm_dp_register(void)
{
int ret;
- ret = platform_driver_register(&dp_display_driver);
+ ret = platform_driver_register(&msm_dp_display_driver);
if (ret)
DRM_ERROR("Dp display driver register failed");
@@ -1410,294 +1419,294 @@ int __init msm_dp_register(void)
void __exit msm_dp_unregister(void)
{
- platform_driver_unregister(&dp_display_driver);
+ platform_driver_unregister(&msm_dp_display_driver);
}
-bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
+bool msm_dp_is_yuv_420_enabled(const struct msm_dp *msm_dp_display,
const struct drm_display_mode *mode)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
const struct drm_display_info *info;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
- info = &dp_display->connector->display_info;
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
+ info = &msm_dp_display->connector->display_info;
return dp->panel->vsc_sdp_supported && drm_mode_is_420_only(info, mode);
}
-bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
+bool msm_dp_needs_periph_flush(const struct msm_dp *msm_dp_display,
const struct drm_display_mode *mode)
{
- return msm_dp_is_yuv_420_enabled(dp_display, mode);
+ return msm_dp_is_yuv_420_enabled(msm_dp_display, mode);
}
-bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
+bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
- if (dp->dp_mode.out_fmt_is_yuv_420)
+ if (dp->msm_dp_mode.out_fmt_is_yuv_420)
return false;
return dp->wide_bus_supported;
}
-void dp_display_debugfs_init(struct msm_dp *dp_display, struct dentry *root, bool is_edp)
+void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *root, bool is_edp)
{
- struct dp_display_private *dp;
+ struct msm_dp_display_private *dp;
struct device *dev;
int rc;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
- dev = &dp->dp_display.pdev->dev;
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
+ dev = &dp->msm_dp_display.pdev->dev;
- rc = dp_debug_init(dev, dp->panel, dp->link, dp->dp_display.connector, root, is_edp);
+ rc = msm_dp_debug_init(dev, dp->panel, dp->link, dp->msm_dp_display.connector, root, is_edp);
if (rc)
DRM_ERROR("failed to initialize debug, rc = %d\n", rc);
}
-int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
+int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
struct drm_encoder *encoder, bool yuv_supported)
{
- struct dp_display_private *dp_priv;
+ struct msm_dp_display_private *msm_dp_priv;
int ret;
- dp_display->drm_dev = dev;
+ msm_dp_display->drm_dev = dev;
- dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
+ msm_dp_priv = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
- ret = dp_bridge_init(dp_display, dev, encoder, yuv_supported);
+ ret = msm_dp_bridge_init(msm_dp_display, dev, encoder, yuv_supported);
if (ret) {
DRM_DEV_ERROR(dev->dev,
"failed to create dp bridge: %d\n", ret);
return ret;
}
- dp_display->connector = dp_drm_connector_init(dp_display, encoder);
- if (IS_ERR(dp_display->connector)) {
- ret = PTR_ERR(dp_display->connector);
+ msm_dp_display->connector = msm_dp_drm_connector_init(msm_dp_display, encoder);
+ if (IS_ERR(msm_dp_display->connector)) {
+ ret = PTR_ERR(msm_dp_display->connector);
DRM_DEV_ERROR(dev->dev,
"failed to create dp connector: %d\n", ret);
- dp_display->connector = NULL;
+ msm_dp_display->connector = NULL;
return ret;
}
- dp_priv->panel->connector = dp_display->connector;
+ msm_dp_priv->panel->connector = msm_dp_display->connector;
return 0;
}
-void dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state)
{
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
- struct msm_dp *dp = dp_bridge->dp_display;
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
+ struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
int rc = 0;
- struct dp_display_private *dp_display;
+ struct msm_dp_display_private *msm_dp_display;
u32 state;
bool force_link_train = false;
- dp_display = container_of(dp, struct dp_display_private, dp_display);
- if (!dp_display->dp_mode.drm_mode.clock) {
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
+ if (!msm_dp_display->msm_dp_mode.drm_mode.clock) {
DRM_ERROR("invalid params\n");
return;
}
if (dp->is_edp)
- dp_hpd_plug_handle(dp_display, 0);
+ msm_dp_hpd_plug_handle(msm_dp_display, 0);
- mutex_lock(&dp_display->event_mutex);
+ mutex_lock(&msm_dp_display->event_mutex);
if (pm_runtime_resume_and_get(&dp->pdev->dev)) {
DRM_ERROR("failed to pm_runtime_resume\n");
- mutex_unlock(&dp_display->event_mutex);
+ mutex_unlock(&msm_dp_display->event_mutex);
return;
}
- state = dp_display->hpd_state;
+ state = msm_dp_display->hpd_state;
if (state != ST_DISPLAY_OFF && state != ST_MAINLINK_READY) {
- mutex_unlock(&dp_display->event_mutex);
+ mutex_unlock(&msm_dp_display->event_mutex);
return;
}
- rc = dp_display_set_mode(dp, &dp_display->dp_mode);
+ rc = msm_dp_display_set_mode(dp, &msm_dp_display->msm_dp_mode);
if (rc) {
DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc);
- mutex_unlock(&dp_display->event_mutex);
+ mutex_unlock(&msm_dp_display->event_mutex);
return;
}
- state = dp_display->hpd_state;
+ state = msm_dp_display->hpd_state;
if (state == ST_DISPLAY_OFF) {
- dp_display_host_phy_init(dp_display);
+ msm_dp_display_host_phy_init(msm_dp_display);
force_link_train = true;
}
- dp_display_enable(dp_display, force_link_train);
+ msm_dp_display_enable(msm_dp_display, force_link_train);
- rc = dp_display_post_enable(dp);
+ rc = msm_dp_display_post_enable(dp);
if (rc) {
DRM_ERROR("DP display post enable failed, rc=%d\n", rc);
- dp_display_disable(dp_display);
+ msm_dp_display_disable(msm_dp_display);
}
/* completed connection */
- dp_display->hpd_state = ST_CONNECTED;
+ msm_dp_display->hpd_state = ST_CONNECTED;
drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type);
- mutex_unlock(&dp_display->event_mutex);
+ mutex_unlock(&msm_dp_display->event_mutex);
}
-void dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state)
{
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
- struct msm_dp *dp = dp_bridge->dp_display;
- struct dp_display_private *dp_display;
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
+ struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
+ struct msm_dp_display_private *msm_dp_display;
- dp_display = container_of(dp, struct dp_display_private, dp_display);
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
- dp_ctrl_push_idle(dp_display->ctrl);
+ msm_dp_ctrl_push_idle(msm_dp_display->ctrl);
}
-void dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state)
{
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
- struct msm_dp *dp = dp_bridge->dp_display;
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
+ struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
u32 state;
- struct dp_display_private *dp_display;
+ struct msm_dp_display_private *msm_dp_display;
- dp_display = container_of(dp, struct dp_display_private, dp_display);
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
if (dp->is_edp)
- dp_hpd_unplug_handle(dp_display, 0);
+ msm_dp_hpd_unplug_handle(msm_dp_display, 0);
- mutex_lock(&dp_display->event_mutex);
+ mutex_lock(&msm_dp_display->event_mutex);
- state = dp_display->hpd_state;
+ state = msm_dp_display->hpd_state;
if (state != ST_DISCONNECT_PENDING && state != ST_CONNECTED)
drm_dbg_dp(dp->drm_dev, "type=%d wrong hpd_state=%d\n",
dp->connector_type, state);
- dp_display_disable(dp_display);
+ msm_dp_display_disable(msm_dp_display);
- state = dp_display->hpd_state;
+ state = msm_dp_display->hpd_state;
if (state == ST_DISCONNECT_PENDING) {
/* completed disconnection */
- dp_display->hpd_state = ST_DISCONNECTED;
+ msm_dp_display->hpd_state = ST_DISCONNECTED;
} else {
- dp_display->hpd_state = ST_DISPLAY_OFF;
+ msm_dp_display->hpd_state = ST_DISPLAY_OFF;
}
drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type);
pm_runtime_put_sync(&dp->pdev->dev);
- mutex_unlock(&dp_display->event_mutex);
+ mutex_unlock(&msm_dp_display->event_mutex);
}
-void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode)
{
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
- struct msm_dp *dp = dp_bridge->dp_display;
- struct dp_display_private *dp_display;
- struct dp_panel *dp_panel;
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
+ struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
+ struct msm_dp_display_private *msm_dp_display;
+ struct msm_dp_panel *msm_dp_panel;
- dp_display = container_of(dp, struct dp_display_private, dp_display);
- dp_panel = dp_display->panel;
+ msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
+ msm_dp_panel = msm_dp_display->panel;
- memset(&dp_display->dp_mode, 0x0, sizeof(struct dp_display_mode));
+ memset(&msm_dp_display->msm_dp_mode, 0x0, sizeof(struct msm_dp_display_mode));
- if (dp_display_check_video_test(dp))
- dp_display->dp_mode.bpp = dp_display_get_test_bpp(dp);
+ if (msm_dp_display_check_video_test(dp))
+ msm_dp_display->msm_dp_mode.bpp = msm_dp_display_get_test_bpp(dp);
else /* Default num_components per pixel = 3 */
- dp_display->dp_mode.bpp = dp->connector->display_info.bpc * 3;
+ msm_dp_display->msm_dp_mode.bpp = dp->connector->display_info.bpc * 3;
- if (!dp_display->dp_mode.bpp)
- dp_display->dp_mode.bpp = 24; /* Default bpp */
+ if (!msm_dp_display->msm_dp_mode.bpp)
+ msm_dp_display->msm_dp_mode.bpp = 24; /* Default bpp */
- drm_mode_copy(&dp_display->dp_mode.drm_mode, adjusted_mode);
+ drm_mode_copy(&msm_dp_display->msm_dp_mode.drm_mode, adjusted_mode);
- dp_display->dp_mode.v_active_low =
- !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NVSYNC);
+ msm_dp_display->msm_dp_mode.v_active_low =
+ !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NVSYNC);
- dp_display->dp_mode.h_active_low =
- !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
+ msm_dp_display->msm_dp_mode.h_active_low =
+ !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
- dp_display->dp_mode.out_fmt_is_yuv_420 =
+ msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 =
drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
- dp_panel->vsc_sdp_supported;
+ msm_dp_panel->vsc_sdp_supported;
/* populate wide_bus_support to different layers */
- dp_display->ctrl->wide_bus_en =
- dp_display->dp_mode.out_fmt_is_yuv_420 ? false : dp_display->wide_bus_supported;
- dp_display->catalog->wide_bus_en =
- dp_display->dp_mode.out_fmt_is_yuv_420 ? false : dp_display->wide_bus_supported;
+ msm_dp_display->ctrl->wide_bus_en =
+ msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 ? false : msm_dp_display->wide_bus_supported;
+ msm_dp_display->catalog->wide_bus_en =
+ msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 ? false : msm_dp_display->wide_bus_supported;
}
-void dp_bridge_hpd_enable(struct drm_bridge *bridge)
+void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge)
{
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge);
- struct msm_dp *dp_display = dp_bridge->dp_display;
- struct dp_display_private *dp = container_of(dp_display, struct dp_display_private, dp_display);
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge);
+ struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display;
+ struct msm_dp_display_private *dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
/*
* this is for external DP with hpd irq enabled case,
- * step-1: dp_pm_runtime_resume() enable dp host only
+ * step-1: msm_dp_pm_runtime_resume() enable dp host only
* step-2: enable hdp block and have hpd irq enabled here
* step-3: waiting for plugin irq while phy is not initialized
* step-4: DP PHY is initialized at plugin handler before link training
*
*/
mutex_lock(&dp->event_mutex);
- if (pm_runtime_resume_and_get(&dp_display->pdev->dev)) {
+ if (pm_runtime_resume_and_get(&msm_dp_display->pdev->dev)) {
DRM_ERROR("failed to resume power\n");
mutex_unlock(&dp->event_mutex);
return;
}
- dp_catalog_ctrl_hpd_enable(dp->catalog);
+ msm_dp_catalog_ctrl_hpd_enable(dp->catalog);
/* enable HDP interrupts */
- dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, true);
+ msm_dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, true);
- dp_display->internal_hpd = true;
+ msm_dp_display->internal_hpd = true;
mutex_unlock(&dp->event_mutex);
}
-void dp_bridge_hpd_disable(struct drm_bridge *bridge)
+void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge)
{
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge);
- struct msm_dp *dp_display = dp_bridge->dp_display;
- struct dp_display_private *dp = container_of(dp_display, struct dp_display_private, dp_display);
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge);
+ struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display;
+ struct msm_dp_display_private *dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
mutex_lock(&dp->event_mutex);
/* disable HDP interrupts */
- dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false);
- dp_catalog_ctrl_hpd_disable(dp->catalog);
+ msm_dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, false);
+ msm_dp_catalog_ctrl_hpd_disable(dp->catalog);
- dp_display->internal_hpd = false;
+ msm_dp_display->internal_hpd = false;
- pm_runtime_put_sync(&dp_display->pdev->dev);
+ pm_runtime_put_sync(&msm_dp_display->pdev->dev);
mutex_unlock(&dp->event_mutex);
}
-void dp_bridge_hpd_notify(struct drm_bridge *bridge,
+void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge,
enum drm_connector_status status)
{
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge);
- struct msm_dp *dp_display = dp_bridge->dp_display;
- struct dp_display_private *dp = container_of(dp_display, struct dp_display_private, dp_display);
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge);
+ struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display;
+ struct msm_dp_display_private *dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
/* Without next_bridge interrupts are handled by the DP core directly */
- if (dp_display->internal_hpd)
+ if (msm_dp_display->internal_hpd)
return;
- if (!dp_display->link_ready && status == connector_status_connected)
- dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
- else if (dp_display->link_ready && status == connector_status_disconnected)
- dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
+ if (!msm_dp_display->link_ready && status == connector_status_connected)
+ msm_dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
+ else if (msm_dp_display->link_ready && status == connector_status_disconnected)
+ msm_dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index ec7fa67e0569..ecbc2d92f546 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -27,18 +27,18 @@ struct msm_dp {
hdmi_codec_plugged_cb plugged_cb;
- struct dp_audio *dp_audio;
+ struct msm_dp_audio *msm_dp_audio;
bool psr_supported;
};
-int dp_display_set_plugged_cb(struct msm_dp *dp_display,
+int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display,
hdmi_codec_plugged_cb fn, struct device *codec_dev);
-int dp_display_get_modes(struct msm_dp *dp_display);
-bool dp_display_check_video_test(struct msm_dp *dp_display);
-int dp_display_get_test_bpp(struct msm_dp *dp_display);
-void dp_display_signal_audio_start(struct msm_dp *dp_display);
-void dp_display_signal_audio_complete(struct msm_dp *dp_display);
-void dp_display_set_psr(struct msm_dp *dp, bool enter);
-void dp_display_debugfs_init(struct msm_dp *dp_display, struct dentry *dentry, bool is_edp);
+int msm_dp_display_get_modes(struct msm_dp *msm_dp_display);
+bool msm_dp_display_check_video_test(struct msm_dp *msm_dp_display);
+int msm_dp_display_get_test_bpp(struct msm_dp *msm_dp_display);
+void msm_dp_display_signal_audio_start(struct msm_dp *msm_dp_display);
+void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display);
+void msm_dp_display_set_psr(struct msm_dp *dp, bool enter);
+void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *dentry, bool is_edp);
#endif /* _DP_DISPLAY_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 7eb1621f9e7f..d3e241ea6941 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -14,15 +14,15 @@
#include "dp_drm.h"
/**
- * dp_bridge_detect - callback to determine if connector is connected
+ * msm_dp_bridge_detect - callback to determine if connector is connected
* @bridge: Pointer to drm bridge structure
* Returns: Bridge's 'is connected' status
*/
-static enum drm_connector_status dp_bridge_detect(struct drm_bridge *bridge)
+static enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge)
{
struct msm_dp *dp;
- dp = to_dp_bridge(bridge)->dp_display;
+ dp = to_dp_bridge(bridge)->msm_dp_display;
drm_dbg_dp(dp->drm_dev, "link_ready = %s\n",
(dp->link_ready) ? "true" : "false");
@@ -31,14 +31,14 @@ static enum drm_connector_status dp_bridge_detect(struct drm_bridge *bridge)
connector_status_disconnected;
}
-static int dp_bridge_atomic_check(struct drm_bridge *bridge,
+static int msm_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 msm_dp *dp;
- dp = to_dp_bridge(bridge)->dp_display;
+ dp = to_dp_bridge(bridge)->msm_dp_display;
drm_dbg_dp(dp->drm_dev, "link_ready = %s\n",
(dp->link_ready) ? "true" : "false");
@@ -62,12 +62,12 @@ static int dp_bridge_atomic_check(struct drm_bridge *bridge,
/**
- * dp_bridge_get_modes - callback to add drm modes via drm_mode_probed_add()
+ * msm_dp_bridge_get_modes - callback to add drm modes via drm_mode_probed_add()
* @bridge: Poiner to drm bridge
* @connector: Pointer to drm connector structure
* Returns: Number of modes added
*/
-static int dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *connector)
+static int msm_dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *connector)
{
int rc = 0;
struct msm_dp *dp;
@@ -75,11 +75,11 @@ static int dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *
if (!connector)
return 0;
- dp = to_dp_bridge(bridge)->dp_display;
+ dp = to_dp_bridge(bridge)->msm_dp_display;
/* pluggable case assumes EDID is read when HPD */
if (dp->link_ready) {
- rc = dp_display_get_modes(dp);
+ rc = msm_dp_display_get_modes(dp);
if (rc <= 0) {
DRM_ERROR("failed to get DP sink modes, rc=%d\n", rc);
return rc;
@@ -90,37 +90,37 @@ static int dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *
return rc;
}
-static void dp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry *root)
+static void msm_dp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry *root)
{
- struct msm_dp *dp = to_dp_bridge(bridge)->dp_display;
+ struct msm_dp *dp = to_dp_bridge(bridge)->msm_dp_display;
- dp_display_debugfs_init(dp, root, false);
+ msm_dp_display_debugfs_init(dp, root, false);
}
-static const struct drm_bridge_funcs dp_bridge_ops = {
+static const struct drm_bridge_funcs msm_dp_bridge_ops = {
.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 = dp_bridge_atomic_enable,
- .atomic_disable = dp_bridge_atomic_disable,
- .atomic_post_disable = dp_bridge_atomic_post_disable,
- .mode_set = dp_bridge_mode_set,
- .mode_valid = dp_bridge_mode_valid,
- .get_modes = dp_bridge_get_modes,
- .detect = dp_bridge_detect,
- .atomic_check = dp_bridge_atomic_check,
- .hpd_enable = dp_bridge_hpd_enable,
- .hpd_disable = dp_bridge_hpd_disable,
- .hpd_notify = dp_bridge_hpd_notify,
- .debugfs_init = dp_bridge_debugfs_init,
+ .atomic_enable = msm_dp_bridge_atomic_enable,
+ .atomic_disable = msm_dp_bridge_atomic_disable,
+ .atomic_post_disable = msm_dp_bridge_atomic_post_disable,
+ .mode_set = msm_dp_bridge_mode_set,
+ .mode_valid = msm_dp_bridge_mode_valid,
+ .get_modes = msm_dp_bridge_get_modes,
+ .detect = msm_dp_bridge_detect,
+ .atomic_check = msm_dp_bridge_atomic_check,
+ .hpd_enable = msm_dp_bridge_hpd_enable,
+ .hpd_disable = msm_dp_bridge_hpd_disable,
+ .hpd_notify = msm_dp_bridge_hpd_notify,
+ .debugfs_init = msm_dp_bridge_debugfs_init,
};
-static int edp_bridge_atomic_check(struct drm_bridge *drm_bridge,
+static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
- struct msm_dp *dp = to_dp_bridge(drm_bridge)->dp_display;
+ struct msm_dp *dp = to_dp_bridge(drm_bridge)->msm_dp_display;
if (WARN_ON(!conn_state))
return -ENODEV;
@@ -136,18 +136,18 @@ static int edp_bridge_atomic_check(struct drm_bridge *drm_bridge,
return 0;
}
-static void edp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
+static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state)
{
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
- struct msm_dp *dp = dp_bridge->dp_display;
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
+ struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
/*
* Check the old state of the crtc to determine if the panel
- * was put into psr state previously by the edp_bridge_atomic_disable.
+ * was put into psr state previously by the msm_edp_bridge_atomic_disable.
* If the panel is in psr, just exit psr state and skip the full
* bridge enable sequence.
*/
@@ -159,21 +159,21 @@ static void edp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
if (old_crtc_state && old_crtc_state->self_refresh_active) {
- dp_display_set_psr(dp, false);
+ msm_dp_display_set_psr(dp, false);
return;
}
- dp_bridge_atomic_enable(drm_bridge, old_bridge_state);
+ msm_dp_bridge_atomic_enable(drm_bridge, old_bridge_state);
}
-static void edp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
+static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state)
{
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state = NULL, *old_crtc_state = NULL;
- struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
- struct msm_dp *dp = dp_bridge->dp_display;
+ struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
+ struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state,
drm_bridge->encoder);
@@ -194,24 +194,24 @@ static void edp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
* If old crtc state is active, then this is a display disable
* call while the sink is in psr state. So, exit psr here.
* The eDP controller will be disabled in the
- * edp_bridge_atomic_post_disable function.
+ * msm_edp_bridge_atomic_post_disable function.
*
* We observed sink is stuck in self refresh if psr exit is skipped
* when display disable occurs while the sink is in psr state.
*/
if (new_crtc_state->self_refresh_active) {
- dp_display_set_psr(dp, true);
+ msm_dp_display_set_psr(dp, true);
return;
} else if (old_crtc_state->self_refresh_active) {
- dp_display_set_psr(dp, false);
+ msm_dp_display_set_psr(dp, false);
return;
}
out:
- dp_bridge_atomic_disable(drm_bridge, old_bridge_state);
+ msm_dp_bridge_atomic_disable(drm_bridge, old_bridge_state);
}
-static void edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
+static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state)
{
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
@@ -228,29 +228,29 @@ static void edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
return;
/*
- * Self refresh mode is already set in edp_bridge_atomic_disable.
+ * Self refresh mode is already set in msm_edp_bridge_atomic_disable.
*/
if (new_crtc_state->self_refresh_active)
return;
- dp_bridge_atomic_post_disable(drm_bridge, old_bridge_state);
+ msm_dp_bridge_atomic_post_disable(drm_bridge, old_bridge_state);
}
/**
- * edp_bridge_mode_valid - callback to determine if specified mode is valid
+ * msm_edp_bridge_mode_valid - callback to determine if specified mode is valid
* @bridge: Pointer to drm bridge structure
* @info: display info
* @mode: Pointer to drm mode structure
* Returns: Validity status for specified mode
*/
-static enum drm_mode_status edp_bridge_mode_valid(struct drm_bridge *bridge,
+static enum drm_mode_status msm_edp_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_info *info,
const struct drm_display_mode *mode)
{
struct msm_dp *dp;
int mode_pclk_khz = mode->clock;
- dp = to_dp_bridge(bridge)->dp_display;
+ dp = to_dp_bridge(bridge)->msm_dp_display;
if (!dp || !mode_pclk_khz || !dp->connector) {
DRM_ERROR("invalid params\n");
@@ -268,42 +268,42 @@ static enum drm_mode_status edp_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-static void edp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry *root)
+static void msm_edp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry *root)
{
- struct msm_dp *dp = to_dp_bridge(bridge)->dp_display;
+ struct msm_dp *dp = to_dp_bridge(bridge)->msm_dp_display;
- dp_display_debugfs_init(dp, root, true);
+ msm_dp_display_debugfs_init(dp, root, true);
}
-static const struct drm_bridge_funcs edp_bridge_ops = {
- .atomic_enable = edp_bridge_atomic_enable,
- .atomic_disable = edp_bridge_atomic_disable,
- .atomic_post_disable = edp_bridge_atomic_post_disable,
- .mode_set = dp_bridge_mode_set,
- .mode_valid = edp_bridge_mode_valid,
+static const struct drm_bridge_funcs msm_edp_bridge_ops = {
+ .atomic_enable = msm_edp_bridge_atomic_enable,
+ .atomic_disable = msm_edp_bridge_atomic_disable,
+ .atomic_post_disable = msm_edp_bridge_atomic_post_disable,
+ .mode_set = msm_dp_bridge_mode_set,
+ .mode_valid = msm_edp_bridge_mode_valid,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
- .atomic_check = edp_bridge_atomic_check,
- .debugfs_init = edp_bridge_debugfs_init,
+ .atomic_check = msm_edp_bridge_atomic_check,
+ .debugfs_init = msm_edp_bridge_debugfs_init,
};
-int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
+int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
struct drm_encoder *encoder, bool yuv_supported)
{
int rc;
- struct msm_dp_bridge *dp_bridge;
+ struct msm_dp_bridge *msm_dp_bridge;
struct drm_bridge *bridge;
- dp_bridge = devm_kzalloc(dev->dev, sizeof(*dp_bridge), GFP_KERNEL);
- if (!dp_bridge)
+ msm_dp_bridge = devm_kzalloc(dev->dev, sizeof(*msm_dp_bridge), GFP_KERNEL);
+ if (!msm_dp_bridge)
return -ENOMEM;
- dp_bridge->dp_display = dp_display;
+ msm_dp_bridge->msm_dp_display = msm_dp_display;
- bridge = &dp_bridge->bridge;
- bridge->funcs = dp_display->is_edp ? &edp_bridge_ops : &dp_bridge_ops;
- bridge->type = dp_display->connector_type;
+ bridge = &msm_dp_bridge->bridge;
+ bridge->funcs = msm_dp_display->is_edp ? &msm_edp_bridge_ops : &msm_dp_bridge_ops;
+ bridge->type = msm_dp_display->connector_type;
bridge->ycbcr_420_allowed = yuv_supported;
/*
@@ -317,7 +317,7 @@ int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
* allows the panel driver to properly power itself on to read the
* modes.
*/
- if (!dp_display->is_edp) {
+ if (!msm_dp_display->is_edp) {
bridge->ops =
DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_HPD |
@@ -338,9 +338,9 @@ int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
return rc;
}
- if (dp_display->next_bridge) {
+ if (msm_dp_display->next_bridge) {
rc = drm_bridge_attach(encoder,
- dp_display->next_bridge, bridge,
+ msm_dp_display->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (rc < 0) {
DRM_ERROR("failed to attach panel bridge: %d\n", rc);
@@ -352,16 +352,16 @@ int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
}
/* connector initialization */
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display,
+struct drm_connector *msm_dp_drm_connector_init(struct msm_dp *msm_dp_display,
struct drm_encoder *encoder)
{
struct drm_connector *connector = NULL;
- connector = drm_bridge_connector_init(dp_display->drm_dev, encoder);
+ connector = drm_bridge_connector_init(msm_dp_display->drm_dev, encoder);
if (IS_ERR(connector))
return connector;
- if (!dp_display->is_edp)
+ if (!msm_dp_display->is_edp)
drm_connector_attach_dp_subconnector_property(connector);
drm_connector_attach_encoder(connector, encoder);
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
index ae632fcc407c..8eae2f74839f 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.h
+++ b/drivers/gpu/drm/msm/dp/dp_drm.h
@@ -14,32 +14,32 @@
struct msm_dp_bridge {
struct drm_bridge bridge;
- struct msm_dp *dp_display;
+ struct msm_dp *msm_dp_display;
};
#define to_dp_bridge(x) container_of((x), struct msm_dp_bridge, bridge)
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display,
+struct drm_connector *msm_dp_drm_connector_init(struct msm_dp *msm_dp_display,
struct drm_encoder *encoder);
-int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
+int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
struct drm_encoder *encoder,
bool yuv_supported);
-void dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state);
-void dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state);
-void dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
struct drm_bridge_state *old_bridge_state);
-enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
+enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_info *info,
const struct drm_display_mode *mode);
-void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
+void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode);
-void dp_bridge_hpd_enable(struct drm_bridge *bridge);
-void dp_bridge_hpd_disable(struct drm_bridge *bridge);
-void dp_bridge_hpd_notify(struct drm_bridge *bridge,
+void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge);
+void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge);
+void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge,
enum drm_connector_status status);
#endif /* _DP_DRM_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index d8967615d84d..1a1fbb2d7d4f 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -28,25 +28,25 @@ enum audio_pattern_type {
AUDIO_TEST_PATTERN_SAWTOOTH = 0x01,
};
-struct dp_link_request {
+struct msm_dp_link_request {
u32 test_requested;
u32 test_link_rate;
u32 test_lane_count;
};
-struct dp_link_private {
+struct msm_dp_link_private {
u32 prev_sink_count;
struct drm_device *drm_dev;
struct drm_dp_aux *aux;
- struct dp_link dp_link;
+ struct msm_dp_link msm_dp_link;
- struct dp_link_request request;
+ struct msm_dp_link_request request;
struct mutex psm_mutex;
u8 link_status[DP_LINK_STATUS_SIZE];
};
-static int dp_aux_link_power_up(struct drm_dp_aux *aux,
- struct dp_link_info *link)
+static int msm_dp_aux_link_power_up(struct drm_dp_aux *aux,
+ struct msm_dp_link_info *link)
{
u8 value;
ssize_t len;
@@ -73,8 +73,8 @@ static int dp_aux_link_power_up(struct drm_dp_aux *aux,
return 0;
}
-static int dp_aux_link_power_down(struct drm_dp_aux *aux,
- struct dp_link_info *link)
+static int msm_dp_aux_link_power_down(struct drm_dp_aux *aux,
+ struct msm_dp_link_info *link)
{
u8 value;
int err;
@@ -96,7 +96,7 @@ static int dp_aux_link_power_down(struct drm_dp_aux *aux,
return 0;
}
-static int dp_link_get_period(struct dp_link_private *link, int const addr)
+static int msm_dp_link_get_period(struct msm_dp_link_private *link, int const addr)
{
int ret = 0;
u8 data;
@@ -122,19 +122,19 @@ exit:
return ret;
}
-static int dp_link_parse_audio_channel_period(struct dp_link_private *link)
+static int msm_dp_link_parse_audio_channel_period(struct msm_dp_link_private *link)
{
int ret = 0;
- struct dp_link_test_audio *req = &link->dp_link.test_audio;
+ struct msm_dp_link_test_audio *req = &link->msm_dp_link.test_audio;
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
if (ret == -EINVAL)
goto exit;
req->test_audio_period_ch_1 = ret;
drm_dbg_dp(link->drm_dev, "test_audio_period_ch_1 = 0x%x\n", ret);
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
if (ret == -EINVAL)
goto exit;
@@ -142,42 +142,42 @@ static int dp_link_parse_audio_channel_period(struct dp_link_private *link)
drm_dbg_dp(link->drm_dev, "test_audio_period_ch_2 = 0x%x\n", ret);
/* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
if (ret == -EINVAL)
goto exit;
req->test_audio_period_ch_3 = ret;
drm_dbg_dp(link->drm_dev, "test_audio_period_ch_3 = 0x%x\n", ret);
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
if (ret == -EINVAL)
goto exit;
req->test_audio_period_ch_4 = ret;
drm_dbg_dp(link->drm_dev, "test_audio_period_ch_4 = 0x%x\n", ret);
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
if (ret == -EINVAL)
goto exit;
req->test_audio_period_ch_5 = ret;
drm_dbg_dp(link->drm_dev, "test_audio_period_ch_5 = 0x%x\n", ret);
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
if (ret == -EINVAL)
goto exit;
req->test_audio_period_ch_6 = ret;
drm_dbg_dp(link->drm_dev, "test_audio_period_ch_6 = 0x%x\n", ret);
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
if (ret == -EINVAL)
goto exit;
req->test_audio_period_ch_7 = ret;
drm_dbg_dp(link->drm_dev, "test_audio_period_ch_7 = 0x%x\n", ret);
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
+ ret = msm_dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
if (ret == -EINVAL)
goto exit;
@@ -187,7 +187,7 @@ exit:
return ret;
}
-static int dp_link_parse_audio_pattern_type(struct dp_link_private *link)
+static int msm_dp_link_parse_audio_pattern_type(struct msm_dp_link_private *link)
{
int ret = 0;
u8 data;
@@ -208,13 +208,13 @@ static int dp_link_parse_audio_pattern_type(struct dp_link_private *link)
goto exit;
}
- link->dp_link.test_audio.test_audio_pattern_type = data;
+ link->msm_dp_link.test_audio.test_audio_pattern_type = data;
drm_dbg_dp(link->drm_dev, "audio pattern type = 0x%x\n", data);
exit:
return ret;
}
-static int dp_link_parse_audio_mode(struct dp_link_private *link)
+static int msm_dp_link_parse_audio_mode(struct msm_dp_link_private *link)
{
int ret = 0;
u8 data;
@@ -248,8 +248,8 @@ static int dp_link_parse_audio_mode(struct dp_link_private *link)
goto exit;
}
- link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate;
- link->dp_link.test_audio.test_audio_channel_count = channel_count;
+ link->msm_dp_link.test_audio.test_audio_sampling_rate = sampling_rate;
+ link->msm_dp_link.test_audio.test_audio_channel_count = channel_count;
drm_dbg_dp(link->drm_dev,
"sampling_rate = 0x%x, channel_count = 0x%x\n",
sampling_rate, channel_count);
@@ -257,25 +257,25 @@ exit:
return ret;
}
-static int dp_link_parse_audio_pattern_params(struct dp_link_private *link)
+static int msm_dp_link_parse_audio_pattern_params(struct msm_dp_link_private *link)
{
int ret = 0;
- ret = dp_link_parse_audio_mode(link);
+ ret = msm_dp_link_parse_audio_mode(link);
if (ret)
goto exit;
- ret = dp_link_parse_audio_pattern_type(link);
+ ret = msm_dp_link_parse_audio_pattern_type(link);
if (ret)
goto exit;
- ret = dp_link_parse_audio_channel_period(link);
+ ret = msm_dp_link_parse_audio_channel_period(link);
exit:
return ret;
}
-static bool dp_link_is_video_pattern_valid(u32 pattern)
+static bool msm_dp_link_is_video_pattern_valid(u32 pattern)
{
switch (pattern) {
case DP_NO_TEST_PATTERN:
@@ -289,12 +289,12 @@ static bool dp_link_is_video_pattern_valid(u32 pattern)
}
/**
- * dp_link_is_bit_depth_valid() - validates the bit depth requested
+ * msm_dp_link_is_bit_depth_valid() - validates the bit depth requested
* @tbd: bit depth requested by the sink
*
* Returns true if the requested bit depth is supported.
*/
-static bool dp_link_is_bit_depth_valid(u32 tbd)
+static bool msm_dp_link_is_bit_depth_valid(u32 tbd)
{
/* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */
switch (tbd) {
@@ -307,7 +307,7 @@ static bool dp_link_is_bit_depth_valid(u32 tbd)
}
}
-static int dp_link_parse_timing_params1(struct dp_link_private *link,
+static int msm_dp_link_parse_timing_params1(struct msm_dp_link_private *link,
int addr, int len, u32 *val)
{
u8 bp[2];
@@ -328,7 +328,7 @@ static int dp_link_parse_timing_params1(struct dp_link_private *link,
return 0;
}
-static int dp_link_parse_timing_params2(struct dp_link_private *link,
+static int msm_dp_link_parse_timing_params2(struct msm_dp_link_private *link,
int addr, int len,
u32 *val1, u32 *val2)
{
@@ -351,7 +351,7 @@ static int dp_link_parse_timing_params2(struct dp_link_private *link,
return 0;
}
-static int dp_link_parse_timing_params3(struct dp_link_private *link,
+static int msm_dp_link_parse_timing_params3(struct msm_dp_link_private *link,
int addr, u32 *val)
{
u8 bp;
@@ -369,13 +369,13 @@ static int dp_link_parse_timing_params3(struct dp_link_private *link,
}
/**
- * dp_link_parse_video_pattern_params() - parses video pattern parameters from DPCD
+ * msm_dp_link_parse_video_pattern_params() - parses video pattern parameters from DPCD
* @link: Display Port Driver data
*
* Returns 0 if it successfully parses the video link pattern and the link
* bit depth requested by the sink and, and if the values parsed are valid.
*/
-static int dp_link_parse_video_pattern_params(struct dp_link_private *link)
+static int msm_dp_link_parse_video_pattern_params(struct msm_dp_link_private *link)
{
int ret = 0;
ssize_t rlen;
@@ -388,13 +388,13 @@ static int dp_link_parse_video_pattern_params(struct dp_link_private *link)
return rlen;
}
- if (!dp_link_is_video_pattern_valid(bp)) {
+ if (!msm_dp_link_is_video_pattern_valid(bp)) {
DRM_ERROR("invalid link video pattern = 0x%x\n", bp);
ret = -EINVAL;
return ret;
}
- link->dp_link.test_video.test_video_pattern = bp;
+ link->msm_dp_link.test_video.test_video_pattern = bp;
/* Read the requested color bit depth and dynamic range (Byte 0x232) */
rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_MISC0, &bp);
@@ -404,88 +404,88 @@ static int dp_link_parse_video_pattern_params(struct dp_link_private *link)
}
/* Dynamic Range */
- link->dp_link.test_video.test_dyn_range =
+ link->msm_dp_link.test_video.test_dyn_range =
(bp & DP_TEST_DYNAMIC_RANGE_CEA);
/* Color bit depth */
bp &= DP_TEST_BIT_DEPTH_MASK;
- if (!dp_link_is_bit_depth_valid(bp)) {
+ if (!msm_dp_link_is_bit_depth_valid(bp)) {
DRM_ERROR("invalid link bit depth = 0x%x\n", bp);
ret = -EINVAL;
return ret;
}
- link->dp_link.test_video.test_bit_depth = bp;
+ link->msm_dp_link.test_video.test_bit_depth = bp;
/* resolution timing params */
- ret = dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2,
- &link->dp_link.test_video.test_h_total);
+ ret = msm_dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2,
+ &link->msm_dp_link.test_video.test_h_total);
if (ret) {
DRM_ERROR("failed to parse test_htotal(DP_TEST_H_TOTAL_HI)\n");
return ret;
}
- ret = dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2,
- &link->dp_link.test_video.test_v_total);
+ ret = msm_dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2,
+ &link->msm_dp_link.test_video.test_v_total);
if (ret) {
DRM_ERROR("failed to parse test_v_total(DP_TEST_V_TOTAL_HI)\n");
return ret;
}
- ret = dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2,
- &link->dp_link.test_video.test_h_start);
+ ret = msm_dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2,
+ &link->msm_dp_link.test_video.test_h_start);
if (ret) {
DRM_ERROR("failed to parse test_h_start(DP_TEST_H_START_HI)\n");
return ret;
}
- ret = dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2,
- &link->dp_link.test_video.test_v_start);
+ ret = msm_dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2,
+ &link->msm_dp_link.test_video.test_v_start);
if (ret) {
DRM_ERROR("failed to parse test_v_start(DP_TEST_V_START_HI)\n");
return ret;
}
- ret = dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2,
- &link->dp_link.test_video.test_hsync_pol,
- &link->dp_link.test_video.test_hsync_width);
+ ret = msm_dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2,
+ &link->msm_dp_link.test_video.test_hsync_pol,
+ &link->msm_dp_link.test_video.test_hsync_width);
if (ret) {
DRM_ERROR("failed to parse (DP_TEST_HSYNC_HI)\n");
return ret;
}
- ret = dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2,
- &link->dp_link.test_video.test_vsync_pol,
- &link->dp_link.test_video.test_vsync_width);
+ ret = msm_dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2,
+ &link->msm_dp_link.test_video.test_vsync_pol,
+ &link->msm_dp_link.test_video.test_vsync_width);
if (ret) {
DRM_ERROR("failed to parse (DP_TEST_VSYNC_HI)\n");
return ret;
}
- ret = dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2,
- &link->dp_link.test_video.test_h_width);
+ ret = msm_dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2,
+ &link->msm_dp_link.test_video.test_h_width);
if (ret) {
DRM_ERROR("failed to parse test_h_width(DP_TEST_H_WIDTH_HI)\n");
return ret;
}
- ret = dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2,
- &link->dp_link.test_video.test_v_height);
+ ret = msm_dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2,
+ &link->msm_dp_link.test_video.test_v_height);
if (ret) {
DRM_ERROR("failed to parse test_v_height\n");
return ret;
}
- ret = dp_link_parse_timing_params3(link, DP_TEST_MISC1,
- &link->dp_link.test_video.test_rr_d);
- link->dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR;
+ ret = msm_dp_link_parse_timing_params3(link, DP_TEST_MISC1,
+ &link->msm_dp_link.test_video.test_rr_d);
+ link->msm_dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR;
if (ret) {
DRM_ERROR("failed to parse test_rr_d (DP_TEST_MISC1)\n");
return ret;
}
- ret = dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR,
- &link->dp_link.test_video.test_rr_n);
+ ret = msm_dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR,
+ &link->msm_dp_link.test_video.test_rr_n);
if (ret) {
DRM_ERROR("failed to parse test_rr_n\n");
return ret;
@@ -505,34 +505,34 @@ static int dp_link_parse_video_pattern_params(struct dp_link_private *link)
"TEST_V_HEIGHT = %d\n"
"TEST_REFRESH_DENOMINATOR = %d\n"
"TEST_REFRESH_NUMERATOR = %d\n",
- link->dp_link.test_video.test_video_pattern,
- link->dp_link.test_video.test_dyn_range,
- link->dp_link.test_video.test_bit_depth,
- link->dp_link.test_video.test_h_total,
- link->dp_link.test_video.test_v_total,
- link->dp_link.test_video.test_h_start,
- link->dp_link.test_video.test_v_start,
- link->dp_link.test_video.test_hsync_pol,
- link->dp_link.test_video.test_hsync_width,
- link->dp_link.test_video.test_vsync_pol,
- link->dp_link.test_video.test_vsync_width,
- link->dp_link.test_video.test_h_width,
- link->dp_link.test_video.test_v_height,
- link->dp_link.test_video.test_rr_d,
- link->dp_link.test_video.test_rr_n);
+ link->msm_dp_link.test_video.test_video_pattern,
+ link->msm_dp_link.test_video.test_dyn_range,
+ link->msm_dp_link.test_video.test_bit_depth,
+ link->msm_dp_link.test_video.test_h_total,
+ link->msm_dp_link.test_video.test_v_total,
+ link->msm_dp_link.test_video.test_h_start,
+ link->msm_dp_link.test_video.test_v_start,
+ link->msm_dp_link.test_video.test_hsync_pol,
+ link->msm_dp_link.test_video.test_hsync_width,
+ link->msm_dp_link.test_video.test_vsync_pol,
+ link->msm_dp_link.test_video.test_vsync_width,
+ link->msm_dp_link.test_video.test_h_width,
+ link->msm_dp_link.test_video.test_v_height,
+ link->msm_dp_link.test_video.test_rr_d,
+ link->msm_dp_link.test_video.test_rr_n);
return ret;
}
/**
- * dp_link_parse_link_training_params() - parses link training parameters from
+ * msm_dp_link_parse_link_training_params() - parses link training parameters from
* DPCD
* @link: Display Port Driver data
*
* Returns 0 if it successfully parses the link rate (Byte 0x219) and lane
* count (Byte 0x220), and if these values parse are valid.
*/
-static int dp_link_parse_link_training_params(struct dp_link_private *link)
+static int msm_dp_link_parse_link_training_params(struct msm_dp_link_private *link)
{
u8 bp;
ssize_t rlen;
@@ -571,13 +571,13 @@ static int dp_link_parse_link_training_params(struct dp_link_private *link)
}
/**
- * dp_link_parse_phy_test_params() - parses the phy link parameters
+ * msm_dp_link_parse_phy_test_params() - parses the phy link parameters
* @link: Display Port Driver data
*
* Parses the DPCD (Byte 0x248) for the DP PHY link pattern that is being
* requested.
*/
-static int dp_link_parse_phy_test_params(struct dp_link_private *link)
+static int msm_dp_link_parse_phy_test_params(struct msm_dp_link_private *link)
{
u8 data;
ssize_t rlen;
@@ -589,7 +589,7 @@ static int dp_link_parse_phy_test_params(struct dp_link_private *link)
return rlen;
}
- link->dp_link.phy_params.phy_test_pattern_sel = data & 0x07;
+ link->msm_dp_link.phy_params.phy_test_pattern_sel = data & 0x07;
drm_dbg_dp(link->drm_dev, "phy_test_pattern_sel = 0x%x\n", data);
@@ -608,12 +608,12 @@ static int dp_link_parse_phy_test_params(struct dp_link_private *link)
}
/**
- * dp_link_is_video_audio_test_requested() - checks for audio/video link request
+ * msm_dp_link_is_video_audio_test_requested() - checks for audio/video link request
* @link: link requested by the sink
*
* Returns true if the requested link is a permitted audio/video link.
*/
-static bool dp_link_is_video_audio_test_requested(u32 link)
+static bool msm_dp_link_is_video_audio_test_requested(u32 link)
{
u8 video_audio_test = (DP_TEST_LINK_VIDEO_PATTERN |
DP_TEST_LINK_AUDIO_PATTERN |
@@ -624,13 +624,13 @@ static bool dp_link_is_video_audio_test_requested(u32 link)
}
/**
- * dp_link_parse_request() - parses link request parameters from sink
+ * msm_dp_link_parse_request() - parses link request parameters from sink
* @link: Display Port Driver data
*
* Parses the DPCD to check if an automated link is requested (Byte 0x201),
* and what type of link automation is being requested (Byte 0x218).
*/
-static int dp_link_parse_request(struct dp_link_private *link)
+static int msm_dp_link_parse_request(struct msm_dp_link_private *link)
{
int ret = 0;
u8 data;
@@ -672,27 +672,27 @@ static int dp_link_parse_request(struct dp_link_private *link)
drm_dbg_dp(link->drm_dev, "Test:(0x%x) requested\n", data);
link->request.test_requested = data;
if (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) {
- ret = dp_link_parse_phy_test_params(link);
+ ret = msm_dp_link_parse_phy_test_params(link);
if (ret)
goto end;
- ret = dp_link_parse_link_training_params(link);
+ ret = msm_dp_link_parse_link_training_params(link);
if (ret)
goto end;
}
if (link->request.test_requested == DP_TEST_LINK_TRAINING) {
- ret = dp_link_parse_link_training_params(link);
+ ret = msm_dp_link_parse_link_training_params(link);
if (ret)
goto end;
}
- if (dp_link_is_video_audio_test_requested(
+ if (msm_dp_link_is_video_audio_test_requested(
link->request.test_requested)) {
- ret = dp_link_parse_video_pattern_params(link);
+ ret = msm_dp_link_parse_video_pattern_params(link);
if (ret)
goto end;
- ret = dp_link_parse_audio_pattern_params(link);
+ ret = msm_dp_link_parse_audio_pattern_params(link);
}
end:
/*
@@ -700,29 +700,29 @@ end:
* a DP_TEST_NAK.
*/
if (ret) {
- link->dp_link.test_response = DP_TEST_NAK;
+ link->msm_dp_link.test_response = DP_TEST_NAK;
} else {
if (link->request.test_requested != DP_TEST_LINK_EDID_READ)
- link->dp_link.test_response = DP_TEST_ACK;
+ link->msm_dp_link.test_response = DP_TEST_ACK;
else
- link->dp_link.test_response =
+ link->msm_dp_link.test_response =
DP_TEST_EDID_CHECKSUM_WRITE;
}
return ret;
}
-static int dp_link_parse_sink_status_field(struct dp_link_private *link)
+static int msm_dp_link_parse_sink_status_field(struct msm_dp_link_private *link)
{
int len;
- link->prev_sink_count = link->dp_link.sink_count;
+ link->prev_sink_count = link->msm_dp_link.sink_count;
len = drm_dp_read_sink_count(link->aux);
if (len < 0) {
DRM_ERROR("DP parse sink count failed\n");
return len;
}
- link->dp_link.sink_count = len;
+ link->msm_dp_link.sink_count = len;
len = drm_dp_dpcd_read_link_status(link->aux,
link->link_status);
@@ -731,11 +731,11 @@ static int dp_link_parse_sink_status_field(struct dp_link_private *link)
return len;
}
- return dp_link_parse_request(link);
+ return msm_dp_link_parse_request(link);
}
/**
- * dp_link_process_link_training_request() - processes new training requests
+ * msm_dp_link_process_link_training_request() - processes new training requests
* @link: Display Port link data
*
* This function will handle new link training requests that are initiated by
@@ -745,7 +745,7 @@ static int dp_link_parse_sink_status_field(struct dp_link_private *link)
* The function will return 0 if a link training request has been processed,
* otherwise it will return -EINVAL.
*/
-static int dp_link_process_link_training_request(struct dp_link_private *link)
+static int msm_dp_link_process_link_training_request(struct msm_dp_link_private *link)
{
if (link->request.test_requested != DP_TEST_LINK_TRAINING)
return -EINVAL;
@@ -756,49 +756,49 @@ static int dp_link_process_link_training_request(struct dp_link_private *link)
link->request.test_link_rate,
link->request.test_lane_count);
- link->dp_link.link_params.num_lanes = link->request.test_lane_count;
- link->dp_link.link_params.rate =
+ link->msm_dp_link.link_params.num_lanes = link->request.test_lane_count;
+ link->msm_dp_link.link_params.rate =
drm_dp_bw_code_to_link_rate(link->request.test_link_rate);
return 0;
}
-bool dp_link_send_test_response(struct dp_link *dp_link)
+bool msm_dp_link_send_test_response(struct msm_dp_link *msm_dp_link)
{
- struct dp_link_private *link = NULL;
+ struct msm_dp_link_private *link = NULL;
int ret = 0;
- if (!dp_link) {
+ if (!msm_dp_link) {
DRM_ERROR("invalid input\n");
return false;
}
- link = container_of(dp_link, struct dp_link_private, dp_link);
+ link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_RESPONSE,
- dp_link->test_response);
+ msm_dp_link->test_response);
return ret == 1;
}
-int dp_link_psm_config(struct dp_link *dp_link,
- struct dp_link_info *link_info, bool enable)
+int msm_dp_link_psm_config(struct msm_dp_link *msm_dp_link,
+ struct msm_dp_link_info *link_info, bool enable)
{
- struct dp_link_private *link = NULL;
+ struct msm_dp_link_private *link = NULL;
int ret = 0;
- if (!dp_link) {
+ if (!msm_dp_link) {
DRM_ERROR("invalid params\n");
return -EINVAL;
}
- link = container_of(dp_link, struct dp_link_private, dp_link);
+ link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
mutex_lock(&link->psm_mutex);
if (enable)
- ret = dp_aux_link_power_down(link->aux, link_info);
+ ret = msm_dp_aux_link_power_down(link->aux, link_info);
else
- ret = dp_aux_link_power_up(link->aux, link_info);
+ ret = msm_dp_aux_link_power_up(link->aux, link_info);
if (ret)
DRM_ERROR("Failed to %s low power mode\n", enable ?
@@ -808,24 +808,24 @@ int dp_link_psm_config(struct dp_link *dp_link,
return ret;
}
-bool dp_link_send_edid_checksum(struct dp_link *dp_link, u8 checksum)
+bool msm_dp_link_send_edid_checksum(struct msm_dp_link *msm_dp_link, u8 checksum)
{
- struct dp_link_private *link = NULL;
+ struct msm_dp_link_private *link = NULL;
int ret = 0;
- if (!dp_link) {
+ if (!msm_dp_link) {
DRM_ERROR("invalid input\n");
return false;
}
- link = container_of(dp_link, struct dp_link_private, dp_link);
+ link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_EDID_CHECKSUM,
checksum);
return ret == 1;
}
-static void dp_link_parse_vx_px(struct dp_link_private *link)
+static void msm_dp_link_parse_vx_px(struct msm_dp_link_private *link)
{
drm_dbg_dp(link->drm_dev, "vx: 0=%d, 1=%d, 2=%d, 3=%d\n",
drm_dp_get_adjust_request_voltage(link->link_status, 0),
@@ -845,31 +845,31 @@ static void dp_link_parse_vx_px(struct dp_link_private *link)
*/
drm_dbg_dp(link->drm_dev,
"Current: v_level = 0x%x, p_level = 0x%x\n",
- link->dp_link.phy_params.v_level,
- link->dp_link.phy_params.p_level);
- link->dp_link.phy_params.v_level =
+ link->msm_dp_link.phy_params.v_level,
+ link->msm_dp_link.phy_params.p_level);
+ link->msm_dp_link.phy_params.v_level =
drm_dp_get_adjust_request_voltage(link->link_status, 0);
- link->dp_link.phy_params.p_level =
+ link->msm_dp_link.phy_params.p_level =
drm_dp_get_adjust_request_pre_emphasis(link->link_status, 0);
- link->dp_link.phy_params.p_level >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
+ link->msm_dp_link.phy_params.p_level >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
drm_dbg_dp(link->drm_dev,
"Requested: v_level = 0x%x, p_level = 0x%x\n",
- link->dp_link.phy_params.v_level,
- link->dp_link.phy_params.p_level);
+ link->msm_dp_link.phy_params.v_level,
+ link->msm_dp_link.phy_params.p_level);
}
/**
- * dp_link_process_phy_test_pattern_request() - process new phy link requests
+ * msm_dp_link_process_phy_test_pattern_request() - process new phy link requests
* @link: Display Port Driver data
*
* This function will handle new phy link pattern requests that are initiated
* by the sink. The function will return 0 if a phy link pattern has been
* processed, otherwise it will return -EINVAL.
*/
-static int dp_link_process_phy_test_pattern_request(
- struct dp_link_private *link)
+static int msm_dp_link_process_phy_test_pattern_request(
+ struct msm_dp_link_private *link)
{
if (!(link->request.test_requested & DP_TEST_LINK_PHY_TEST_PATTERN)) {
drm_dbg_dp(link->drm_dev, "no phy test\n");
@@ -886,24 +886,24 @@ static int dp_link_process_phy_test_pattern_request(
drm_dbg_dp(link->drm_dev,
"Current: rate = 0x%x, lane count = 0x%x\n",
- link->dp_link.link_params.rate,
- link->dp_link.link_params.num_lanes);
+ link->msm_dp_link.link_params.rate,
+ link->msm_dp_link.link_params.num_lanes);
drm_dbg_dp(link->drm_dev,
"Requested: rate = 0x%x, lane count = 0x%x\n",
link->request.test_link_rate,
link->request.test_lane_count);
- link->dp_link.link_params.num_lanes = link->request.test_lane_count;
- link->dp_link.link_params.rate =
+ link->msm_dp_link.link_params.num_lanes = link->request.test_lane_count;
+ link->msm_dp_link.link_params.rate =
drm_dp_bw_code_to_link_rate(link->request.test_link_rate);
- dp_link_parse_vx_px(link);
+ msm_dp_link_parse_vx_px(link);
return 0;
}
-static bool dp_link_read_psr_error_status(struct dp_link_private *link)
+static bool msm_dp_link_read_psr_error_status(struct msm_dp_link_private *link)
{
u8 status;
@@ -921,7 +921,7 @@ static bool dp_link_read_psr_error_status(struct dp_link_private *link)
return true;
}
-static bool dp_link_psr_capability_changed(struct dp_link_private *link)
+static bool msm_dp_link_psr_capability_changed(struct msm_dp_link_private *link)
{
u8 status;
@@ -941,7 +941,7 @@ static u8 get_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
}
/**
- * dp_link_process_link_status_update() - processes link status updates
+ * msm_dp_link_process_link_status_update() - processes link status updates
* @link: Display Port link module data
*
* This function will check for changes in the link status, e.g. clock
@@ -951,13 +951,13 @@ static u8 get_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
* The function will return 0 if the a link status update has been processed,
* otherwise it will return -EINVAL.
*/
-static int dp_link_process_link_status_update(struct dp_link_private *link)
+static int msm_dp_link_process_link_status_update(struct msm_dp_link_private *link)
{
bool channel_eq_done = drm_dp_channel_eq_ok(link->link_status,
- link->dp_link.link_params.num_lanes);
+ link->msm_dp_link.link_params.num_lanes);
bool clock_recovery_done = drm_dp_clock_recovery_ok(link->link_status,
- link->dp_link.link_params.num_lanes);
+ link->msm_dp_link.link_params.num_lanes);
drm_dbg_dp(link->drm_dev,
"channel_eq_done = %d, clock_recovery_done = %d\n",
@@ -970,7 +970,7 @@ static int dp_link_process_link_status_update(struct dp_link_private *link)
}
/**
- * dp_link_process_ds_port_status_change() - process port status changes
+ * msm_dp_link_process_ds_port_status_change() - process port status changes
* @link: Display Port Driver data
*
* This function will handle downstream port updates that are initiated by
@@ -980,122 +980,122 @@ static int dp_link_process_link_status_update(struct dp_link_private *link)
* The function will return 0 if a downstream port update has been
* processed, otherwise it will return -EINVAL.
*/
-static int dp_link_process_ds_port_status_change(struct dp_link_private *link)
+static int msm_dp_link_process_ds_port_status_change(struct msm_dp_link_private *link)
{
if (get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) &
DP_DOWNSTREAM_PORT_STATUS_CHANGED)
goto reset;
- if (link->prev_sink_count == link->dp_link.sink_count)
+ if (link->prev_sink_count == link->msm_dp_link.sink_count)
return -EINVAL;
reset:
/* reset prev_sink_count */
- link->prev_sink_count = link->dp_link.sink_count;
+ link->prev_sink_count = link->msm_dp_link.sink_count;
return 0;
}
-static bool dp_link_is_video_pattern_requested(struct dp_link_private *link)
+static bool msm_dp_link_is_video_pattern_requested(struct msm_dp_link_private *link)
{
return (link->request.test_requested & DP_TEST_LINK_VIDEO_PATTERN)
&& !(link->request.test_requested &
DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
}
-static bool dp_link_is_audio_pattern_requested(struct dp_link_private *link)
+static bool msm_dp_link_is_audio_pattern_requested(struct msm_dp_link_private *link)
{
return (link->request.test_requested & DP_TEST_LINK_AUDIO_PATTERN);
}
-static void dp_link_reset_data(struct dp_link_private *link)
+static void msm_dp_link_reset_data(struct msm_dp_link_private *link)
{
- link->request = (const struct dp_link_request){ 0 };
- link->dp_link.test_video = (const struct dp_link_test_video){ 0 };
- link->dp_link.test_video.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
- link->dp_link.test_audio = (const struct dp_link_test_audio){ 0 };
- link->dp_link.phy_params.phy_test_pattern_sel = 0;
- link->dp_link.sink_request = 0;
- link->dp_link.test_response = 0;
+ link->request = (const struct msm_dp_link_request){ 0 };
+ link->msm_dp_link.test_video = (const struct msm_dp_link_test_video){ 0 };
+ link->msm_dp_link.test_video.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
+ link->msm_dp_link.test_audio = (const struct msm_dp_link_test_audio){ 0 };
+ link->msm_dp_link.phy_params.phy_test_pattern_sel = 0;
+ link->msm_dp_link.sink_request = 0;
+ link->msm_dp_link.test_response = 0;
}
/**
- * dp_link_process_request() - handle HPD IRQ transition to HIGH
- * @dp_link: pointer to link module data
+ * msm_dp_link_process_request() - handle HPD IRQ transition to HIGH
+ * @msm_dp_link: pointer to link module data
*
* This function will handle the HPD IRQ state transitions from LOW to HIGH
* (including cases when there are back to back HPD IRQ HIGH) indicating
* the start of a new link training request or sink status update.
*/
-int dp_link_process_request(struct dp_link *dp_link)
+int msm_dp_link_process_request(struct msm_dp_link *msm_dp_link)
{
int ret = 0;
- struct dp_link_private *link;
+ struct msm_dp_link_private *link;
- if (!dp_link) {
+ if (!msm_dp_link) {
DRM_ERROR("invalid input\n");
return -EINVAL;
}
- link = container_of(dp_link, struct dp_link_private, dp_link);
+ link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
- dp_link_reset_data(link);
+ msm_dp_link_reset_data(link);
- ret = dp_link_parse_sink_status_field(link);
+ ret = msm_dp_link_parse_sink_status_field(link);
if (ret)
return ret;
if (link->request.test_requested == DP_TEST_LINK_EDID_READ) {
- dp_link->sink_request |= DP_TEST_LINK_EDID_READ;
- } else if (!dp_link_process_ds_port_status_change(link)) {
- dp_link->sink_request |= DS_PORT_STATUS_CHANGED;
- } else if (!dp_link_process_link_training_request(link)) {
- dp_link->sink_request |= DP_TEST_LINK_TRAINING;
- } else if (!dp_link_process_phy_test_pattern_request(link)) {
- dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN;
- } else if (dp_link_read_psr_error_status(link)) {
+ msm_dp_link->sink_request |= DP_TEST_LINK_EDID_READ;
+ } else if (!msm_dp_link_process_ds_port_status_change(link)) {
+ msm_dp_link->sink_request |= DS_PORT_STATUS_CHANGED;
+ } else if (!msm_dp_link_process_link_training_request(link)) {
+ msm_dp_link->sink_request |= DP_TEST_LINK_TRAINING;
+ } else if (!msm_dp_link_process_phy_test_pattern_request(link)) {
+ msm_dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN;
+ } else if (msm_dp_link_read_psr_error_status(link)) {
DRM_ERROR("PSR IRQ_HPD received\n");
- } else if (dp_link_psr_capability_changed(link)) {
+ } else if (msm_dp_link_psr_capability_changed(link)) {
drm_dbg_dp(link->drm_dev, "PSR Capability changed\n");
} else {
- ret = dp_link_process_link_status_update(link);
+ ret = msm_dp_link_process_link_status_update(link);
if (!ret) {
- dp_link->sink_request |= DP_LINK_STATUS_UPDATED;
+ msm_dp_link->sink_request |= DP_LINK_STATUS_UPDATED;
} else {
- if (dp_link_is_video_pattern_requested(link)) {
+ if (msm_dp_link_is_video_pattern_requested(link)) {
ret = 0;
- dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN;
+ msm_dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN;
}
- if (dp_link_is_audio_pattern_requested(link)) {
- dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
+ if (msm_dp_link_is_audio_pattern_requested(link)) {
+ msm_dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
ret = -EINVAL;
}
}
}
drm_dbg_dp(link->drm_dev, "sink request=%#x\n",
- dp_link->sink_request);
+ msm_dp_link->sink_request);
return ret;
}
-int dp_link_get_colorimetry_config(struct dp_link *dp_link)
+int msm_dp_link_get_colorimetry_config(struct msm_dp_link *msm_dp_link)
{
u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB;
- struct dp_link_private *link;
+ struct msm_dp_link_private *link;
- if (!dp_link) {
+ if (!msm_dp_link) {
DRM_ERROR("invalid input\n");
return -EINVAL;
}
- link = container_of(dp_link, struct dp_link_private, dp_link);
+ link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
/*
* Unless a video pattern CTS test is ongoing, use RGB_VESA
* Only RGB_VESA and RGB_CEA supported for now
*/
- if (dp_link_is_video_pattern_requested(link)) {
- if (link->dp_link.test_video.test_dyn_range &
+ if (msm_dp_link_is_video_pattern_requested(link)) {
+ if (link->msm_dp_link.test_video.test_dyn_range &
DP_TEST_DYNAMIC_RANGE_CEA)
cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB;
}
@@ -1103,22 +1103,22 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link)
return cc;
}
-int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status)
+int msm_dp_link_adjust_levels(struct msm_dp_link *msm_dp_link, u8 *link_status)
{
int i;
u8 max_p_level;
int v_max = 0, p_max = 0;
- struct dp_link_private *link;
+ struct msm_dp_link_private *link;
- if (!dp_link) {
+ if (!msm_dp_link) {
DRM_ERROR("invalid input\n");
return -EINVAL;
}
- link = container_of(dp_link, struct dp_link_private, dp_link);
+ link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
/* use the max level across lanes */
- for (i = 0; i < dp_link->link_params.num_lanes; i++) {
+ for (i = 0; i < msm_dp_link->link_params.num_lanes; i++) {
u8 data_v = drm_dp_get_adjust_request_voltage(link_status, i);
u8 data_p = drm_dp_get_adjust_request_pre_emphasis(link_status,
i);
@@ -1131,56 +1131,56 @@ int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status)
p_max = data_p;
}
- dp_link->phy_params.v_level = v_max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
- dp_link->phy_params.p_level = p_max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
+ msm_dp_link->phy_params.v_level = v_max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
+ msm_dp_link->phy_params.p_level = p_max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
/**
* Adjust the voltage swing and pre-emphasis level combination to within
* the allowable range.
*/
- if (dp_link->phy_params.v_level > DP_TRAIN_LEVEL_MAX) {
+ if (msm_dp_link->phy_params.v_level > DP_TRAIN_LEVEL_MAX) {
drm_dbg_dp(link->drm_dev,
"Requested vSwingLevel=%d, change to %d\n",
- dp_link->phy_params.v_level,
+ msm_dp_link->phy_params.v_level,
DP_TRAIN_LEVEL_MAX);
- dp_link->phy_params.v_level = DP_TRAIN_LEVEL_MAX;
+ msm_dp_link->phy_params.v_level = DP_TRAIN_LEVEL_MAX;
}
- if (dp_link->phy_params.p_level > DP_TRAIN_LEVEL_MAX) {
+ if (msm_dp_link->phy_params.p_level > DP_TRAIN_LEVEL_MAX) {
drm_dbg_dp(link->drm_dev,
"Requested preEmphasisLevel=%d, change to %d\n",
- dp_link->phy_params.p_level,
+ msm_dp_link->phy_params.p_level,
DP_TRAIN_LEVEL_MAX);
- dp_link->phy_params.p_level = DP_TRAIN_LEVEL_MAX;
+ msm_dp_link->phy_params.p_level = DP_TRAIN_LEVEL_MAX;
}
- max_p_level = DP_TRAIN_LEVEL_MAX - dp_link->phy_params.v_level;
- if (dp_link->phy_params.p_level > max_p_level) {
+ max_p_level = DP_TRAIN_LEVEL_MAX - msm_dp_link->phy_params.v_level;
+ if (msm_dp_link->phy_params.p_level > max_p_level) {
drm_dbg_dp(link->drm_dev,
"Requested preEmphasisLevel=%d, change to %d\n",
- dp_link->phy_params.p_level,
+ msm_dp_link->phy_params.p_level,
max_p_level);
- dp_link->phy_params.p_level = max_p_level;
+ msm_dp_link->phy_params.p_level = max_p_level;
}
drm_dbg_dp(link->drm_dev, "adjusted: v_level=%d, p_level=%d\n",
- dp_link->phy_params.v_level, dp_link->phy_params.p_level);
+ msm_dp_link->phy_params.v_level, msm_dp_link->phy_params.p_level);
return 0;
}
-void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link)
+void msm_dp_link_reset_phy_params_vx_px(struct msm_dp_link *msm_dp_link)
{
- dp_link->phy_params.v_level = 0;
- dp_link->phy_params.p_level = 0;
+ msm_dp_link->phy_params.v_level = 0;
+ msm_dp_link->phy_params.p_level = 0;
}
-u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
+u32 msm_dp_link_get_test_bits_depth(struct msm_dp_link *msm_dp_link, u32 bpp)
{
u32 tbd;
- struct dp_link_private *link;
+ struct msm_dp_link_private *link;
- link = container_of(dp_link, struct dp_link_private, dp_link);
+ link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
/*
* Few simplistic rules and assumptions made here:
@@ -1209,10 +1209,10 @@ u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
return tbd;
}
-struct dp_link *dp_link_get(struct device *dev, struct drm_dp_aux *aux)
+struct msm_dp_link *msm_dp_link_get(struct device *dev, struct drm_dp_aux *aux)
{
- struct dp_link_private *link;
- struct dp_link *dp_link;
+ struct msm_dp_link_private *link;
+ struct msm_dp_link *msm_dp_link;
if (!dev || !aux) {
DRM_ERROR("invalid input\n");
@@ -1226,7 +1226,7 @@ struct dp_link *dp_link_get(struct device *dev, struct drm_dp_aux *aux)
link->aux = aux;
mutex_init(&link->psm_mutex);
- dp_link = &link->dp_link;
+ msm_dp_link = &link->msm_dp_link;
- return dp_link;
+ return msm_dp_link;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index 5846337bb56f..8db5d5698a97 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -12,7 +12,7 @@
#define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF
#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
-struct dp_link_info {
+struct msm_dp_link_info {
unsigned char revision;
unsigned int rate;
unsigned int num_lanes;
@@ -21,7 +21,7 @@ struct dp_link_info {
#define DP_TRAIN_LEVEL_MAX 3
-struct dp_link_test_video {
+struct msm_dp_link_test_video {
u32 test_video_pattern;
u32 test_bit_depth;
u32 test_dyn_range;
@@ -39,7 +39,7 @@ struct dp_link_test_video {
u32 test_rr_n;
};
-struct dp_link_test_audio {
+struct msm_dp_link_test_audio {
u32 test_audio_sampling_rate;
u32 test_audio_channel_count;
u32 test_audio_pattern_type;
@@ -53,21 +53,21 @@ struct dp_link_test_audio {
u32 test_audio_period_ch_8;
};
-struct dp_link_phy_params {
+struct msm_dp_link_phy_params {
u32 phy_test_pattern_sel;
u8 v_level;
u8 p_level;
};
-struct dp_link {
+struct msm_dp_link {
u32 sink_request;
u32 test_response;
u8 sink_count;
- struct dp_link_test_video test_video;
- struct dp_link_test_audio test_audio;
- struct dp_link_phy_params phy_params;
- struct dp_link_info link_params;
+ struct msm_dp_link_test_video test_video;
+ struct msm_dp_link_test_audio test_audio;
+ struct msm_dp_link_phy_params phy_params;
+ struct msm_dp_link_info link_params;
};
/**
@@ -78,7 +78,7 @@ struct dp_link {
* git bit depth value. This function assumes that bit depth has
* already been validated.
*/
-static inline u32 dp_link_bit_depth_to_bpp(u32 tbd)
+static inline u32 msm_dp_link_bit_depth_to_bpp(u32 tbd)
{
/*
* Few simplistic rules and assumptions made here:
@@ -99,22 +99,22 @@ static inline u32 dp_link_bit_depth_to_bpp(u32 tbd)
}
}
-void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link);
-u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp);
-int dp_link_process_request(struct dp_link *dp_link);
-int dp_link_get_colorimetry_config(struct dp_link *dp_link);
-int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status);
-bool dp_link_send_test_response(struct dp_link *dp_link);
-int dp_link_psm_config(struct dp_link *dp_link,
- struct dp_link_info *link_info, bool enable);
-bool dp_link_send_edid_checksum(struct dp_link *dp_link, u8 checksum);
+void msm_dp_link_reset_phy_params_vx_px(struct msm_dp_link *msm_dp_link);
+u32 msm_dp_link_get_test_bits_depth(struct msm_dp_link *msm_dp_link, u32 bpp);
+int msm_dp_link_process_request(struct msm_dp_link *msm_dp_link);
+int msm_dp_link_get_colorimetry_config(struct msm_dp_link *msm_dp_link);
+int msm_dp_link_adjust_levels(struct msm_dp_link *msm_dp_link, u8 *link_status);
+bool msm_dp_link_send_test_response(struct msm_dp_link *msm_dp_link);
+int msm_dp_link_psm_config(struct msm_dp_link *msm_dp_link,
+ struct msm_dp_link_info *link_info, bool enable);
+bool msm_dp_link_send_edid_checksum(struct msm_dp_link *msm_dp_link, u8 checksum);
/**
- * dp_link_get() - get the functionalities of dp test module
+ * msm_dp_link_get() - get the functionalities of dp test module
*
*
- * return: a pointer to dp_link struct
+ * return: a pointer to msm_dp_link struct
*/
-struct dp_link *dp_link_get(struct device *dev, struct drm_dp_aux *aux);
+struct msm_dp_link *msm_dp_link_get(struct device *dev, struct drm_dp_aux *aux);
#endif /* _DP_LINK_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 6ff6c9ef351f..5d7eaa31bf31 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -14,52 +14,52 @@
#define DP_MAX_NUM_DP_LANES 4
#define DP_LINK_RATE_HBR2 540000 /* kbytes */
-struct dp_panel_private {
+struct msm_dp_panel_private {
struct device *dev;
struct drm_device *drm_dev;
- struct dp_panel dp_panel;
+ struct msm_dp_panel msm_dp_panel;
struct drm_dp_aux *aux;
- struct dp_link *link;
- struct dp_catalog *catalog;
+ struct msm_dp_link *link;
+ struct msm_dp_catalog *catalog;
bool panel_on;
};
-static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
+static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel)
{
ssize_t rlen;
- struct dp_panel *dp_panel;
+ struct msm_dp_panel *msm_dp_panel;
- dp_panel = &panel->dp_panel;
+ msm_dp_panel = &panel->msm_dp_panel;
/* edp sink */
- if (dp_panel->dpcd[DP_EDP_CONFIGURATION_CAP]) {
+ if (msm_dp_panel->dpcd[DP_EDP_CONFIGURATION_CAP]) {
rlen = drm_dp_dpcd_read(panel->aux, DP_PSR_SUPPORT,
- &dp_panel->psr_cap, sizeof(dp_panel->psr_cap));
- if (rlen == sizeof(dp_panel->psr_cap)) {
+ &msm_dp_panel->psr_cap, sizeof(msm_dp_panel->psr_cap));
+ if (rlen == sizeof(msm_dp_panel->psr_cap)) {
drm_dbg_dp(panel->drm_dev,
"psr version: 0x%x, psr_cap: 0x%x\n",
- dp_panel->psr_cap.version,
- dp_panel->psr_cap.capabilities);
+ msm_dp_panel->psr_cap.version,
+ msm_dp_panel->psr_cap.capabilities);
} else
DRM_ERROR("failed to read psr info, rlen=%zd\n", rlen);
}
}
-static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
+static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel)
{
int rc;
- struct dp_panel_private *panel;
- struct dp_link_info *link_info;
+ struct msm_dp_panel_private *panel;
+ struct msm_dp_link_info *link_info;
u8 *dpcd, major, minor;
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
- dpcd = dp_panel->dpcd;
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
+ dpcd = msm_dp_panel->dpcd;
rc = drm_dp_read_dpcd_caps(panel->aux, dpcd);
if (rc)
return rc;
- dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, dpcd);
- link_info = &dp_panel->link_info;
+ msm_dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, dpcd);
+ link_info = &msm_dp_panel->link_info;
link_info->revision = dpcd[DP_DPCD_REV];
major = (link_info->revision >> 4) & 0x0f;
minor = link_info->revision & 0x0f;
@@ -68,12 +68,12 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
link_info->num_lanes = drm_dp_max_lane_count(dpcd);
/* Limit data lanes from data-lanes of endpoint property of dtsi */
- if (link_info->num_lanes > dp_panel->max_dp_lanes)
- link_info->num_lanes = dp_panel->max_dp_lanes;
+ if (link_info->num_lanes > msm_dp_panel->max_dp_lanes)
+ link_info->num_lanes = msm_dp_panel->max_dp_lanes;
/* Limit link rate from link-frequencies of endpoint property of dtsi */
- if (link_info->rate > dp_panel->max_dp_link_rate)
- link_info->rate = dp_panel->max_dp_link_rate;
+ if (link_info->rate > msm_dp_panel->max_dp_link_rate)
+ link_info->rate = msm_dp_panel->max_dp_link_rate;
drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
@@ -82,21 +82,21 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
if (drm_dp_enhanced_frame_cap(dpcd))
link_info->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING;
- dp_panel_read_psr_cap(panel);
+ msm_dp_panel_read_psr_cap(panel);
return rc;
}
-static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
+static u32 msm_dp_panel_get_supported_bpp(struct msm_dp_panel *msm_dp_panel,
u32 mode_edid_bpp, u32 mode_pclk_khz)
{
- const struct dp_link_info *link_info;
+ const struct msm_dp_link_info *link_info;
const u32 max_supported_bpp = 30, min_supported_bpp = 18;
u32 bpp, data_rate_khz;
bpp = min(mode_edid_bpp, max_supported_bpp);
- link_info = &dp_panel->link_info;
+ link_info = &msm_dp_panel->link_info;
data_rate_khz = link_info->num_lanes * link_info->rate * 8;
do {
@@ -108,39 +108,39 @@ static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
return min_supported_bpp;
}
-int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
+int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel,
struct drm_connector *connector)
{
int rc, bw_code;
int count;
- struct dp_panel_private *panel;
+ struct msm_dp_panel_private *panel;
- if (!dp_panel || !connector) {
+ if (!msm_dp_panel || !connector) {
DRM_ERROR("invalid input\n");
return -EINVAL;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
drm_dbg_dp(panel->drm_dev, "max_lanes=%d max_link_rate=%d\n",
- dp_panel->max_dp_lanes, dp_panel->max_dp_link_rate);
+ msm_dp_panel->max_dp_lanes, msm_dp_panel->max_dp_link_rate);
- rc = dp_panel_read_dpcd(dp_panel);
+ rc = msm_dp_panel_read_dpcd(msm_dp_panel);
if (rc) {
DRM_ERROR("read dpcd failed %d\n", rc);
return rc;
}
- bw_code = drm_dp_link_rate_to_bw_code(dp_panel->link_info.rate);
+ bw_code = drm_dp_link_rate_to_bw_code(msm_dp_panel->link_info.rate);
if (!is_link_rate_valid(bw_code) ||
- !is_lane_count_valid(dp_panel->link_info.num_lanes) ||
- (bw_code > dp_panel->max_bw_code)) {
- DRM_ERROR("Illegal link rate=%d lane=%d\n", dp_panel->link_info.rate,
- dp_panel->link_info.num_lanes);
+ !is_lane_count_valid(msm_dp_panel->link_info.num_lanes) ||
+ (bw_code > msm_dp_panel->max_bw_code)) {
+ DRM_ERROR("Illegal link rate=%d lane=%d\n", msm_dp_panel->link_info.rate,
+ msm_dp_panel->link_info.num_lanes);
return -EINVAL;
}
- if (drm_dp_is_branch(dp_panel->dpcd)) {
+ if (drm_dp_is_branch(msm_dp_panel->dpcd)) {
count = drm_dp_read_sink_count(panel->aux);
if (!count) {
panel->link->sink_count = 0;
@@ -148,21 +148,21 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
}
}
- rc = drm_dp_read_downstream_info(panel->aux, dp_panel->dpcd,
- dp_panel->downstream_ports);
+ rc = drm_dp_read_downstream_info(panel->aux, msm_dp_panel->dpcd,
+ msm_dp_panel->downstream_ports);
if (rc)
return rc;
- drm_edid_free(dp_panel->drm_edid);
+ drm_edid_free(msm_dp_panel->drm_edid);
- dp_panel->drm_edid = drm_edid_read_ddc(connector, &panel->aux->ddc);
+ msm_dp_panel->drm_edid = drm_edid_read_ddc(connector, &panel->aux->ddc);
- drm_edid_connector_update(connector, dp_panel->drm_edid);
+ drm_edid_connector_update(connector, msm_dp_panel->drm_edid);
- if (!dp_panel->drm_edid) {
+ if (!msm_dp_panel->drm_edid) {
DRM_ERROR("panel edid read failed\n");
/* check edid read fail is due to unplug */
- if (!dp_catalog_link_is_connected(panel->catalog)) {
+ if (!msm_dp_catalog_link_is_connected(panel->catalog)) {
rc = -ETIMEDOUT;
goto end;
}
@@ -172,87 +172,87 @@ end:
return rc;
}
-u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel,
+u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel,
u32 mode_edid_bpp, u32 mode_pclk_khz)
{
- struct dp_panel_private *panel;
+ struct msm_dp_panel_private *panel;
u32 bpp;
- if (!dp_panel || !mode_edid_bpp || !mode_pclk_khz) {
+ if (!msm_dp_panel || !mode_edid_bpp || !mode_pclk_khz) {
DRM_ERROR("invalid input\n");
return 0;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
- if (dp_panel->video_test)
- bpp = dp_link_bit_depth_to_bpp(
+ if (msm_dp_panel->video_test)
+ bpp = msm_dp_link_bit_depth_to_bpp(
panel->link->test_video.test_bit_depth);
else
- bpp = dp_panel_get_supported_bpp(dp_panel, mode_edid_bpp,
+ bpp = msm_dp_panel_get_supported_bpp(msm_dp_panel, mode_edid_bpp,
mode_pclk_khz);
return bpp;
}
-int dp_panel_get_modes(struct dp_panel *dp_panel,
+int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel,
struct drm_connector *connector)
{
- if (!dp_panel) {
+ if (!msm_dp_panel) {
DRM_ERROR("invalid input\n");
return -EINVAL;
}
- if (dp_panel->drm_edid)
+ if (msm_dp_panel->drm_edid)
return drm_edid_connector_add_modes(connector);
return 0;
}
-static u8 dp_panel_get_edid_checksum(const struct edid *edid)
+static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid)
{
edid += edid->extensions;
return edid->checksum;
}
-void dp_panel_handle_sink_request(struct dp_panel *dp_panel)
+void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel)
{
- struct dp_panel_private *panel;
+ struct msm_dp_panel_private *panel;
- if (!dp_panel) {
+ if (!msm_dp_panel) {
DRM_ERROR("invalid input\n");
return;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) {
/* FIXME: get rid of drm_edid_raw() */
- const struct edid *edid = drm_edid_raw(dp_panel->drm_edid);
+ const struct edid *edid = drm_edid_raw(msm_dp_panel->drm_edid);
u8 checksum;
if (edid)
- checksum = dp_panel_get_edid_checksum(edid);
+ checksum = msm_dp_panel_get_edid_checksum(edid);
else
- checksum = dp_panel->connector->real_edid_checksum;
+ checksum = msm_dp_panel->connector->real_edid_checksum;
- dp_link_send_edid_checksum(panel->link, checksum);
- dp_link_send_test_response(panel->link);
+ msm_dp_link_send_edid_checksum(panel->link, checksum);
+ msm_dp_link_send_test_response(panel->link);
}
}
-void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable)
+void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable)
{
- struct dp_catalog *catalog;
- struct dp_panel_private *panel;
+ struct msm_dp_catalog *catalog;
+ struct msm_dp_panel_private *panel;
- if (!dp_panel) {
+ if (!msm_dp_panel) {
DRM_ERROR("invalid input\n");
return;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
catalog = panel->catalog;
if (!panel->panel_on) {
@@ -262,31 +262,31 @@ void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable)
}
if (!enable) {
- dp_catalog_panel_tpg_disable(catalog);
+ msm_dp_catalog_panel_tpg_disable(catalog);
return;
}
drm_dbg_dp(panel->drm_dev, "calling catalog tpg_enable\n");
- dp_catalog_panel_tpg_enable(catalog, &panel->dp_panel.dp_mode.drm_mode);
+ msm_dp_catalog_panel_tpg_enable(catalog, &panel->msm_dp_panel.msm_dp_mode.drm_mode);
}
-static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
+static int msm_dp_panel_setup_vsc_sdp_yuv_420(struct msm_dp_panel *msm_dp_panel)
{
- struct dp_catalog *catalog;
- struct dp_panel_private *panel;
- struct dp_display_mode *dp_mode;
+ struct msm_dp_catalog *catalog;
+ struct msm_dp_panel_private *panel;
+ struct msm_dp_display_mode *msm_dp_mode;
struct drm_dp_vsc_sdp vsc_sdp_data;
struct dp_sdp vsc_sdp;
ssize_t len;
- if (!dp_panel) {
+ if (!msm_dp_panel) {
DRM_ERROR("invalid input\n");
return -EINVAL;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
catalog = panel->catalog;
- dp_mode = &dp_panel->dp_mode;
+ msm_dp_mode = &msm_dp_panel->msm_dp_mode;
memset(&vsc_sdp_data, 0, sizeof(vsc_sdp_data));
@@ -300,7 +300,7 @@ static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
/* VSC SDP Payload for DB17 */
- vsc_sdp_data.bpc = dp_mode->bpp / 3;
+ vsc_sdp_data.bpc = msm_dp_mode->bpp / 3;
vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
/* VSC SDP Payload for DB18 */
@@ -312,36 +312,36 @@ static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
return len;
}
- dp_catalog_panel_enable_vsc_sdp(catalog, &vsc_sdp);
+ msm_dp_catalog_panel_enable_vsc_sdp(catalog, &vsc_sdp);
return 0;
}
-void dp_panel_dump_regs(struct dp_panel *dp_panel)
+void msm_dp_panel_dump_regs(struct msm_dp_panel *msm_dp_panel)
{
- struct dp_catalog *catalog;
- struct dp_panel_private *panel;
+ struct msm_dp_catalog *catalog;
+ struct msm_dp_panel_private *panel;
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
catalog = panel->catalog;
- dp_catalog_dump_regs(catalog);
+ msm_dp_catalog_dump_regs(catalog);
}
-int dp_panel_timing_cfg(struct dp_panel *dp_panel)
+int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel)
{
u32 data, total_ver, total_hor;
- struct dp_catalog *catalog;
- struct dp_panel_private *panel;
+ struct msm_dp_catalog *catalog;
+ struct msm_dp_panel_private *panel;
struct drm_display_mode *drm_mode;
u32 width_blanking;
u32 sync_start;
- u32 dp_active;
+ u32 msm_dp_active;
u32 total;
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
catalog = panel->catalog;
- drm_mode = &panel->dp_panel.dp_mode.drm_mode;
+ drm_mode = &panel->msm_dp_panel.msm_dp_mode.drm_mode;
drm_dbg_dp(panel->drm_dev, "width=%d hporch= %d %d %d\n",
drm_mode->hdisplay, drm_mode->htotal - drm_mode->hsync_end,
@@ -371,9 +371,9 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel)
data = drm_mode->vsync_end - drm_mode->vsync_start;
data <<= 16;
- data |= (panel->dp_panel.dp_mode.v_active_low << 31);
+ data |= (panel->msm_dp_panel.msm_dp_mode.v_active_low << 31);
data |= drm_mode->hsync_end - drm_mode->hsync_start;
- data |= (panel->dp_panel.dp_mode.h_active_low << 15);
+ data |= (panel->msm_dp_panel.msm_dp_mode.h_active_low << 15);
width_blanking = data;
@@ -381,26 +381,26 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel)
data <<= 16;
data |= drm_mode->hdisplay;
- dp_active = data;
+ msm_dp_active = data;
- dp_catalog_panel_timing_cfg(catalog, total, sync_start, width_blanking, dp_active);
+ msm_dp_catalog_panel_timing_cfg(catalog, total, sync_start, width_blanking, msm_dp_active);
- if (dp_panel->dp_mode.out_fmt_is_yuv_420)
- dp_panel_setup_vsc_sdp_yuv_420(dp_panel);
+ if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420)
+ msm_dp_panel_setup_vsc_sdp_yuv_420(msm_dp_panel);
panel->panel_on = true;
return 0;
}
-int dp_panel_init_panel_info(struct dp_panel *dp_panel)
+int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel)
{
struct drm_display_mode *drm_mode;
- struct dp_panel_private *panel;
+ struct msm_dp_panel_private *panel;
- drm_mode = &dp_panel->dp_mode.drm_mode;
+ drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode;
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
/*
* print resolution info as this is a result
@@ -421,18 +421,18 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel)
drm_mode->vsync_end - drm_mode->vsync_start);
drm_dbg_dp(panel->drm_dev, "pixel clock (KHz)=(%d)\n",
drm_mode->clock);
- drm_dbg_dp(panel->drm_dev, "bpp = %d\n", dp_panel->dp_mode.bpp);
+ drm_dbg_dp(panel->drm_dev, "bpp = %d\n", msm_dp_panel->msm_dp_mode.bpp);
- dp_panel->dp_mode.bpp = dp_panel_get_mode_bpp(dp_panel, dp_panel->dp_mode.bpp,
- dp_panel->dp_mode.drm_mode.clock);
+ msm_dp_panel->msm_dp_mode.bpp = msm_dp_panel_get_mode_bpp(msm_dp_panel, msm_dp_panel->msm_dp_mode.bpp,
+ msm_dp_panel->msm_dp_mode.drm_mode.clock);
drm_dbg_dp(panel->drm_dev, "updated bpp = %d\n",
- dp_panel->dp_mode.bpp);
+ msm_dp_panel->msm_dp_mode.bpp);
return 0;
}
-static u32 dp_panel_link_frequencies(struct device_node *of_node)
+static u32 msm_dp_panel_link_frequencies(struct device_node *of_node)
{
struct device_node *endpoint;
u64 frequency = 0;
@@ -456,17 +456,17 @@ static u32 dp_panel_link_frequencies(struct device_node *of_node)
return frequency;
}
-static int dp_panel_parse_dt(struct dp_panel *dp_panel)
+static int msm_dp_panel_parse_dt(struct msm_dp_panel *msm_dp_panel)
{
- struct dp_panel_private *panel;
+ struct msm_dp_panel_private *panel;
struct device_node *of_node;
int cnt;
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel);
of_node = panel->dev->of_node;
/*
- * data-lanes is the property of dp_out endpoint
+ * data-lanes is the property of msm_dp_out endpoint
*/
cnt = drm_of_get_data_lanes_count_ep(of_node, 1, 0, 1, DP_MAX_NUM_DP_LANES);
if (cnt < 0) {
@@ -475,21 +475,21 @@ static int dp_panel_parse_dt(struct dp_panel *dp_panel)
}
if (cnt > 0)
- dp_panel->max_dp_lanes = cnt;
+ msm_dp_panel->max_dp_lanes = cnt;
else
- dp_panel->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */
+ msm_dp_panel->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */
- dp_panel->max_dp_link_rate = dp_panel_link_frequencies(of_node);
- if (!dp_panel->max_dp_link_rate)
- dp_panel->max_dp_link_rate = DP_LINK_RATE_HBR2;
+ msm_dp_panel->max_dp_link_rate = msm_dp_panel_link_frequencies(of_node);
+ if (!msm_dp_panel->max_dp_link_rate)
+ msm_dp_panel->max_dp_link_rate = DP_LINK_RATE_HBR2;
return 0;
}
-struct dp_panel *dp_panel_get(struct dp_panel_in *in)
+struct msm_dp_panel *msm_dp_panel_get(struct msm_dp_panel_in *in)
{
- struct dp_panel_private *panel;
- struct dp_panel *dp_panel;
+ struct msm_dp_panel_private *panel;
+ struct msm_dp_panel *msm_dp_panel;
int ret;
if (!in->dev || !in->catalog || !in->aux || !in->link) {
@@ -506,20 +506,20 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in)
panel->catalog = in->catalog;
panel->link = in->link;
- dp_panel = &panel->dp_panel;
- dp_panel->max_bw_code = DP_LINK_BW_8_1;
+ msm_dp_panel = &panel->msm_dp_panel;
+ msm_dp_panel->max_bw_code = DP_LINK_BW_8_1;
- ret = dp_panel_parse_dt(dp_panel);
+ ret = msm_dp_panel_parse_dt(msm_dp_panel);
if (ret)
return ERR_PTR(ret);
- return dp_panel;
+ return msm_dp_panel;
}
-void dp_panel_put(struct dp_panel *dp_panel)
+void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel)
{
- if (!dp_panel)
+ if (!msm_dp_panel)
return;
- drm_edid_free(dp_panel->drm_edid);
+ drm_edid_free(msm_dp_panel->drm_edid);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 6722e3923fa5..0e944db3adf2 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -13,7 +13,7 @@
struct edid;
-struct dp_display_mode {
+struct msm_dp_display_mode {
struct drm_display_mode drm_mode;
u32 bpp;
u32 h_active_low;
@@ -21,28 +21,28 @@ struct dp_display_mode {
bool out_fmt_is_yuv_420;
};
-struct dp_panel_in {
+struct msm_dp_panel_in {
struct device *dev;
struct drm_dp_aux *aux;
- struct dp_link *link;
- struct dp_catalog *catalog;
+ struct msm_dp_link *link;
+ struct msm_dp_catalog *catalog;
};
-struct dp_panel_psr {
+struct msm_dp_panel_psr {
u8 version;
u8 capabilities;
};
-struct dp_panel {
+struct msm_dp_panel {
/* dpcd raw data */
u8 dpcd[DP_RECEIVER_CAP_SIZE];
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
- struct dp_link_info link_info;
+ struct msm_dp_link_info link_info;
const struct drm_edid *drm_edid;
struct drm_connector *connector;
- struct dp_display_mode dp_mode;
- struct dp_panel_psr psr_cap;
+ struct msm_dp_display_mode msm_dp_mode;
+ struct msm_dp_panel_psr psr_cap;
bool video_test;
bool vsc_sdp_supported;
@@ -52,18 +52,18 @@ struct dp_panel {
u32 max_bw_code;
};
-int dp_panel_init_panel_info(struct dp_panel *dp_panel);
-int dp_panel_deinit(struct dp_panel *dp_panel);
-int dp_panel_timing_cfg(struct dp_panel *dp_panel);
-void dp_panel_dump_regs(struct dp_panel *dp_panel);
-int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
+int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel);
+int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel);
+int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel);
+void msm_dp_panel_dump_regs(struct msm_dp_panel *msm_dp_panel);
+int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel,
struct drm_connector *connector);
-u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, u32 mode_max_bpp,
+u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp,
u32 mode_pclk_khz);
-int dp_panel_get_modes(struct dp_panel *dp_panel,
+int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel,
struct drm_connector *connector);
-void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
-void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
+void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel);
+void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable);
/**
* is_link_rate_valid() - validates the link rate
@@ -80,7 +80,7 @@ static inline bool is_link_rate_valid(u32 bw_code)
}
/**
- * dp_link_is_lane_count_valid() - validates the lane count
+ * msm_dp_link_is_lane_count_valid() - validates the lane count
* @lane_count: lane count requested by the sink
*
* Returns true if the requested lane count is supported.
@@ -92,6 +92,6 @@ static inline bool is_lane_count_valid(u32 lane_count)
lane_count == 4);
}
-struct dp_panel *dp_panel_get(struct dp_panel_in *in);
-void dp_panel_put(struct dp_panel *dp_panel);
+struct msm_dp_panel *msm_dp_panel_get(struct msm_dp_panel_in *in);
+void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel);
#endif /* _DP_PANEL_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
index da9207caf72d..2a40f07fe2d5 100644
--- a/drivers/gpu/drm/msm/dp/dp_utils.c
+++ b/drivers/gpu/drm/msm/dp/dp_utils.c
@@ -9,7 +9,7 @@
#define DP_SDP_HEADER_SIZE 8
-u8 dp_utils_get_g0_value(u8 data)
+u8 msm_dp_utils_get_g0_value(u8 data)
{
u8 c[4];
u8 g[4];
@@ -30,7 +30,7 @@ u8 dp_utils_get_g0_value(u8 data)
return ret_data;
}
-u8 dp_utils_get_g1_value(u8 data)
+u8 msm_dp_utils_get_g1_value(u8 data)
{
u8 c[4];
u8 g[4];
@@ -51,7 +51,7 @@ u8 dp_utils_get_g1_value(u8 data)
return ret_data;
}
-u8 dp_utils_calculate_parity(u32 data)
+u8 msm_dp_utils_calculate_parity(u32 data)
{
u8 x0 = 0;
u8 x1 = 0;
@@ -65,8 +65,8 @@ u8 dp_utils_calculate_parity(u32 data)
iData = (data >> i * 4) & 0xF;
ci = iData ^ x1;
- x1 = x0 ^ dp_utils_get_g1_value(ci);
- x0 = dp_utils_get_g0_value(ci);
+ x1 = x0 ^ msm_dp_utils_get_g1_value(ci);
+ x0 = msm_dp_utils_get_g0_value(ci);
}
parity_byte = x1 | (x0 << 4);
@@ -74,7 +74,7 @@ u8 dp_utils_calculate_parity(u32 data)
return parity_byte;
}
-ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff)
+ssize_t msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff)
{
size_t length;
@@ -83,14 +83,14 @@ ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_b
return -ENOSPC;
header_buff[0] = FIELD_PREP(HEADER_0_MASK, sdp_header->HB0) |
- FIELD_PREP(PARITY_0_MASK, dp_utils_calculate_parity(sdp_header->HB0)) |
+ FIELD_PREP(PARITY_0_MASK, msm_dp_utils_calculate_parity(sdp_header->HB0)) |
FIELD_PREP(HEADER_1_MASK, sdp_header->HB1) |
- FIELD_PREP(PARITY_1_MASK, dp_utils_calculate_parity(sdp_header->HB1));
+ FIELD_PREP(PARITY_1_MASK, msm_dp_utils_calculate_parity(sdp_header->HB1));
header_buff[1] = FIELD_PREP(HEADER_2_MASK, sdp_header->HB2) |
- FIELD_PREP(PARITY_2_MASK, dp_utils_calculate_parity(sdp_header->HB2)) |
+ FIELD_PREP(PARITY_2_MASK, msm_dp_utils_calculate_parity(sdp_header->HB2)) |
FIELD_PREP(HEADER_3_MASK, sdp_header->HB3) |
- FIELD_PREP(PARITY_3_MASK, dp_utils_calculate_parity(sdp_header->HB3));
+ FIELD_PREP(PARITY_3_MASK, msm_dp_utils_calculate_parity(sdp_header->HB3));
return length;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
index 7c056d9798dc..88d53157f5b5 100644
--- a/drivers/gpu/drm/msm/dp/dp_utils.h
+++ b/drivers/gpu/drm/msm/dp/dp_utils.h
@@ -28,9 +28,9 @@
#define HEADER_3_MASK GENMASK(23, 16)
#define PARITY_3_MASK GENMASK(31, 24)
-u8 dp_utils_get_g0_value(u8 data);
-u8 dp_utils_get_g1_value(u8 data);
-u8 dp_utils_calculate_parity(u32 data);
-ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff);
+u8 msm_dp_utils_get_g0_value(u8 data);
+u8 msm_dp_utils_get_g1_value(u8 data);
+u8 msm_dp_utils_calculate_parity(u32 data);
+ssize_t msm_dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 *header_buff);
#endif /* _DP_UTILS_H_ */
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c
index e6ffaf92d26d..a719fd33d9d8 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c
@@ -157,9 +157,8 @@ static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
#define HDMI_MHZ_TO_HZ ((u64)1000000)
static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk)
{
- u32 const ratio_list[] = {1, 2, 3, 4, 5, 6,
- 9, 10, 12, 15, 25};
- u32 const band_list[] = {0, 1, 2, 3};
+ static const u32 ratio_list[] = {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25};
+ static const u32 band_list[] = {0, 1, 2, 3};
u32 const sz_ratio = ARRAY_SIZE(ratio_list);
u32 const sz_band = ARRAY_SIZE(band_list);
u32 const cmp_cnt = 1024;
@@ -270,7 +269,7 @@ find_optimal_index:
case 25:
found_hsclk_divsel = 14;
break;
- };
+ }
pd->vco_freq = found_vco_freq;
pd->tx_band_sel = found_tx_band_sel;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index edbc1ab0fbc8..c2dd8ef6d6dc 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -985,6 +985,10 @@ module_param(prefer_mdp5, bool, 0444);
/* list all platforms supported by both mdp5 and dpu drivers */
static const char *const msm_mdp5_dpu_migration[] = {
+ "qcom,msm8917-mdp5",
+ "qcom,msm8937-mdp5",
+ "qcom,msm8953-mdp5",
+ "qcom,msm8996-mdp5",
"qcom,sdm630-mdp5",
"qcom,sdm660-mdp5",
NULL,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 133e47bea7d5..d8c9a1b19263 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -52,7 +52,6 @@ struct msm_gem_vma;
struct msm_disp_state;
#define MAX_CRTCS 8
-#define MAX_BRIDGES 8
#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
@@ -71,23 +70,6 @@ enum msm_dsi_controller {
};
#define MSM_GPU_MAX_RINGS 4
-#define MAX_H_TILES_PER_DISPLAY 2
-
-/**
- * struct msm_display_topology - defines a display topology pipeline
- * @num_lm: number of layer mixers used
- * @num_intf: number of interfaces the panel is mounted on
- * @num_dspp: number of dspp blocks used
- * @num_dsc: number of Display Stream Compression (DSC) blocks used
- * @needs_cdm: indicates whether cdm block is needed for this display topology
- */
-struct msm_display_topology {
- u32 num_lm;
- u32 num_intf;
- u32 num_dspp;
- u32 num_dsc;
- bool needs_cdm;
-};
/* Commit/Event thread specific structure */
struct msm_drm_thread {
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index a274b8466423..0d4a3744cfcb 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -783,7 +783,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
mutex_unlock(&gpu->active_lock);
gpu->funcs->submit(gpu, submit);
- gpu->cur_ctx_seqno = submit->queue->ctx->seqno;
+ submit->ring->cur_ctx_seqno = submit->queue->ctx->seqno;
pm_runtime_put(&gpu->pdev->dev);
hangcheck_timer_reset(gpu);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 1f02bb9956be..7cabc8480d7c 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -194,17 +194,6 @@ struct msm_gpu {
refcount_t sysprof_active;
/**
- * cur_ctx_seqno:
- *
- * The ctx->seqno value of the last context to submit rendering,
- * and the one with current pgtables installed (for generations
- * that support per-context pgtables). Tracked by seqno rather
- * than pointer value to avoid dangling pointers, and cases where
- * a ctx can be freed and a new one created with the same address.
- */
- int cur_ctx_seqno;
-
- /**
* lock:
*
* General lock for serializing all the gpu things.
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
index ea70c1c32d94..6970b0f7f457 100644
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -140,6 +140,7 @@ void msm_devfreq_init(struct msm_gpu *gpu)
{
struct msm_gpu_devfreq *df = &gpu->devfreq;
struct msm_drm_private *priv = gpu->dev->dev_private;
+ int ret;
/* We need target support to do devfreq */
if (!gpu->funcs->gpu_busy)
@@ -156,8 +157,12 @@ void msm_devfreq_init(struct msm_gpu *gpu)
mutex_init(&df->lock);
- dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq,
- DEV_PM_QOS_MIN_FREQUENCY, 0);
+ ret = dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq,
+ DEV_PM_QOS_MIN_FREQUENCY, 0);
+ if (ret < 0) {
+ DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize QoS\n");
+ return;
+ }
msm_devfreq_profile.initial_freq = gpu->fast_rate;
diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h
index ac40d857bc45..7f863282db0d 100644
--- a/drivers/gpu/drm/msm/msm_gpu_trace.h
+++ b/drivers/gpu/drm/msm/msm_gpu_trace.h
@@ -177,6 +177,34 @@ TRACE_EVENT(msm_gpu_resume,
TP_printk("%u", __entry->dummy)
);
+TRACE_EVENT(msm_gpu_preemption_trigger,
+ TP_PROTO(int ring_id_from, int ring_id_to),
+ TP_ARGS(ring_id_from, ring_id_to),
+ TP_STRUCT__entry(
+ __field(int, ring_id_from)
+ __field(int, ring_id_to)
+ ),
+ TP_fast_assign(
+ __entry->ring_id_from = ring_id_from;
+ __entry->ring_id_to = ring_id_to;
+ ),
+ TP_printk("preempting %u -> %u",
+ __entry->ring_id_from,
+ __entry->ring_id_to)
+);
+
+TRACE_EVENT(msm_gpu_preemption_irq,
+ TP_PROTO(u32 ring_id),
+ TP_ARGS(ring_id),
+ TP_STRUCT__entry(
+ __field(u32, ring_id)
+ ),
+ TP_fast_assign(
+ __entry->ring_id = ring_id;
+ ),
+ TP_printk("preempted to %u", __entry->ring_id)
+);
+
#endif
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 1e0c54de3716..e60162744c66 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -92,12 +92,6 @@ struct msm_kms_funcs {
* Format handling:
*/
- /* do format checking on format modified through fb_cmd2 modifiers */
- int (*check_modified_format)(const struct msm_kms *kms,
- const struct msm_format *msm_fmt,
- const struct drm_mode_fb_cmd2 *cmd,
- struct drm_gem_object **bos);
-
/* misc: */
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index faa88fd6eb4d..b7bd899ead44 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -19,13 +19,7 @@
#include "msm_mdss.h"
#include "msm_kms.h"
-#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
+#include <generated/mdss.xml.h>
#define MIN_IB_BW 400000000UL /* Min ib vote 400MB */
@@ -83,7 +77,7 @@ static void msm_mdss_irq(struct irq_desc *desc)
chained_irq_enter(chip, desc);
- interrupts = readl_relaxed(msm_mdss->mmio + HW_INTR_STATUS);
+ interrupts = readl_relaxed(msm_mdss->mmio + REG_MDSS_HW_INTR_STATUS);
while (interrupts) {
irq_hw_number_t hwirq = fls(interrupts) - 1;
@@ -173,7 +167,7 @@ static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
{
const struct msm_mdss_data *data = msm_mdss->mdss_data;
- writel_relaxed(data->ubwc_static, msm_mdss->mmio + UBWC_STATIC);
+ writel_relaxed(data->ubwc_static, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
}
static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss)
@@ -189,7 +183,7 @@ static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss)
if (data->ubwc_enc_version == UBWC_1_0)
value |= BIT(8);
- writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
+ writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
}
static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
@@ -200,21 +194,22 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
(data->highest_bank_bit & 0x7) << 4 |
(data->macrotile_mode & 0x1) << 12;
- writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
+ writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
if (data->ubwc_enc_version == UBWC_3_0) {
- writel_relaxed(1, msm_mdss->mmio + UBWC_CTRL_2);
- writel_relaxed(0, msm_mdss->mmio + UBWC_PREDICTION_MODE);
+ writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
+ writel_relaxed(0, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
} else {
if (data->ubwc_dec_version == UBWC_4_3)
- writel_relaxed(3, msm_mdss->mmio + UBWC_CTRL_2);
+ writel_relaxed(3, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
else
- writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
- writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
+ writel_relaxed(2, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
+ writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
}
}
-#define MDSS_HW_MAJ_MIN GENMASK(31, 16)
+#define MDSS_HW_MAJ_MIN \
+ (MDSS_HW_VERSION_MAJOR__MASK | MDSS_HW_VERSION_MINOR__MASK)
#define MDSS_HW_MSM8996 0x1007
#define MDSS_HW_MSM8937 0x100e
@@ -235,7 +230,7 @@ static const struct msm_mdss_data *msm_mdss_generate_mdp5_mdss_data(struct msm_m
if (!data)
return NULL;
- hw_rev = readl_relaxed(mdss->mmio + HW_REV);
+ hw_rev = readl_relaxed(mdss->mmio + REG_MDSS_HW_VERSION);
hw_rev = FIELD_GET(MDSS_HW_MAJ_MIN, hw_rev);
if (hw_rev == MDSS_HW_MSM8996 ||
@@ -334,9 +329,9 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n",
msm_mdss->mdss_data->ubwc_dec_version);
dev_err(msm_mdss->dev, "HW_REV: 0x%x\n",
- readl_relaxed(msm_mdss->mmio + HW_REV));
+ readl_relaxed(msm_mdss->mmio + REG_MDSS_HW_VERSION));
dev_err(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n",
- readl_relaxed(msm_mdss->mmio + UBWC_DEC_HW_VERSION));
+ readl_relaxed(msm_mdss->mmio + REG_MDSS_UBWC_DEC_HW_VERSION));
break;
}
@@ -573,6 +568,16 @@ static const struct msm_mdss_data qcm2290_data = {
.reg_bus_bw = 76800,
};
+static const struct msm_mdss_data sa8775p_data = {
+ .ubwc_enc_version = UBWC_4_0,
+ .ubwc_dec_version = UBWC_4_0,
+ .ubwc_swizzle = 4,
+ .ubwc_static = 1,
+ .highest_bank_bit = 0,
+ .macrotile_mode = 1,
+ .reg_bus_bw = 74000,
+};
+
static const struct msm_mdss_data sc7180_data = {
.ubwc_enc_version = UBWC_2_0,
.ubwc_dec_version = UBWC_2_0,
@@ -710,6 +715,7 @@ static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,mdss" },
{ .compatible = "qcom,msm8998-mdss", .data = &msm8998_data },
{ .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data },
+ { .compatible = "qcom,sa8775p-mdss", .data = &sa8775p_data },
{ .compatible = "qcom,sdm670-mdss", .data = &sdm670_data },
{ .compatible = "qcom,sdm845-mdss", .data = &sdm845_data },
{ .compatible = "qcom,sc7180-mdss", .data = &sc7180_data },
diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c
index 9d6655f96f0c..c803556a8f64 100644
--- a/drivers/gpu/drm/msm/msm_ringbuffer.c
+++ b/drivers/gpu/drm/msm/msm_ringbuffer.c
@@ -64,7 +64,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
char name[32];
int ret;
- /* We assume everwhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */
+ /* We assume everywhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */
BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ));
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h
index 0d6beb8cd39a..d1e49f701c81 100644
--- a/drivers/gpu/drm/msm/msm_ringbuffer.h
+++ b/drivers/gpu/drm/msm/msm_ringbuffer.h
@@ -31,10 +31,12 @@ struct msm_rbmemptrs {
volatile uint32_t rptr;
volatile uint32_t fence;
/* Introduced on A7xx */
+ volatile uint32_t bv_rptr;
volatile uint32_t bv_fence;
volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT];
volatile u64 ttbr0;
+ volatile u32 context_idr;
};
struct msm_cp_state {
@@ -99,6 +101,22 @@ struct msm_ringbuffer {
* preemption. Can be aquired from irq context.
*/
spinlock_t preempt_lock;
+
+ /*
+ * Whether we skipped writing wptr and it needs to be updated in the
+ * future when the ring becomes current.
+ */
+ bool restore_wptr;
+
+ /**
+ * cur_ctx_seqno:
+ *
+ * The ctx->seqno value of the last context to submit to this ring
+ * Tracked by seqno rather than pointer value to avoid dangling
+ * pointers, and cases where a ctx can be freed and a new one created
+ * with the same address.
+ */
+ int cur_ctx_seqno;
};
struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
index 0e803125a325..2fc3eaf81f44 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -161,6 +161,8 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
struct msm_drm_private *priv = drm->dev_private;
struct msm_gpu_submitqueue *queue;
enum drm_sched_priority sched_prio;
+ extern int enable_preemption;
+ bool preemption_supported;
unsigned ring_nr;
int ret;
@@ -170,6 +172,11 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
if (!priv->gpu)
return -ENODEV;
+ preemption_supported = priv->gpu->nr_rings == 1 && enable_preemption != 0;
+
+ if (flags & MSM_SUBMITQUEUE_ALLOW_PREEMPT && preemption_supported)
+ return -EINVAL;
+
ret = msm_gpu_convert_priority(priv->gpu, prio, &ring_nr, &sched_prio);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
index 97608603ea62..2db425abf0f3 100644
--- a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
+++ b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
@@ -2358,7 +2358,12 @@ to upconvert to 32b float internally?
<reg32 offset="0x0" name="REG" type="a6x_cp_protect"/>
</array>
- <reg32 offset="0x08A0" name="CP_CONTEXT_SWITCH_CNTL"/>
+ <reg32 offset="0x08A0" name="CP_CONTEXT_SWITCH_CNTL">
+ <bitfield name="STOP" pos="0" type="boolean"/>
+ <bitfield name="LEVEL" low="6" high="7"/>
+ <bitfield name="USES_GMEM" pos="8" type="boolean"/>
+ <bitfield name="SKIP_SAVE_RESTORE" pos="9" type="boolean"/>
+ </reg32>
<reg64 offset="0x08A1" name="CP_CONTEXT_SWITCH_SMMU_INFO"/>
<reg64 offset="0x08A3" name="CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR"/>
<reg64 offset="0x08A5" name="CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR"/>
diff --git a/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml b/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml
index cab01af55d22..55a35182858c 100644
--- a/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml
+++ b/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml
@@ -581,8 +581,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
and forcibly switch to the indicated context.
</doc>
<value name="CP_CONTEXT_SWITCH" value="0x54" variants="A6XX"/>
- <!-- Note, kgsl calls this CP_SET_AMBLE: -->
- <value name="CP_SET_CTXSWITCH_IB" value="0x55" variants="A6XX-"/>
+ <value name="CP_SET_AMBLE" value="0x55" variants="A6XX-"/>
<!--
Seems to always have the payload:
@@ -2013,42 +2012,38 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
</reg32>
</domain>
-<domain name="CP_SET_CTXSWITCH_IB" width="32">
+<domain name="CP_SET_AMBLE" width="32">
<doc>
- Used by the userspace driver to set various IB's which are
- executed during context save/restore for handling
- state that isn't restored by the
- context switch routine itself.
- </doc>
- <enum name="ctxswitch_ib">
- <value name="RESTORE_IB" value="0">
+ Used by the userspace and kernel drivers to set various IB's
+ which are executed during context save/restore for handling
+ state that isn't restored by the context switch routine itself.
+ </doc>
+ <enum name="amble_type">
+ <value name="PREAMBLE_AMBLE_TYPE" value="0">
<doc>Executed unconditionally when switching back to the context.</doc>
</value>
- <value name="YIELD_RESTORE_IB" value="1">
+ <value name="BIN_PREAMBLE_AMBLE_TYPE" value="1">
<doc>
Executed when switching back after switching
away during execution of
- a CP_SET_MARKER packet with RM6_YIELD as the
- payload *and* the normal save routine was
- bypassed for a shorter one. I think this is
- connected to the "skipsaverestore" bit set by
- the kernel when preempting.
+ a CP_SET_MARKER packet with RM6_BIN_RENDER_END as the
+ payload *and* skipsaverestore is set. This is
+ expected to restore static register values not
+ saved when skipsaverestore is set.
</doc>
</value>
- <value name="SAVE_IB" value="2">
+ <value name="POSTAMBLE_AMBLE_TYPE" value="2">
<doc>
Executed when switching away from the context,
except for context switches initiated via
CP_YIELD.
</doc>
</value>
- <value name="RB_SAVE_IB" value="3">
+ <value name="KMD_AMBLE_TYPE" value="3">
<doc>
This can only be set by the RB (i.e. the kernel)
and executes with protected mode off, but
- is otherwise similar to SAVE_IB.
-
- Note, kgsl calls this CP_KMD_AMBLE_TYPE
+ is otherwise similar to POSTAMBLE_AMBLE_TYPE.
</doc>
</value>
</enum>
@@ -2060,7 +2055,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
</reg32>
<reg32 offset="2" name="2">
<bitfield name="DWORDS" low="0" high="19" type="uint"/>
- <bitfield name="TYPE" low="20" high="21" type="ctxswitch_ib"/>
+ <bitfield name="TYPE" low="20" high="21" type="amble_type"/>
</reg32>
</domain>
diff --git a/drivers/gpu/drm/msm/registers/display/mdp5.xml b/drivers/gpu/drm/msm/registers/display/mdp5.xml
index 92f3263af170..8c9c4af350aa 100644
--- a/drivers/gpu/drm/msm/registers/display/mdp5.xml
+++ b/drivers/gpu/drm/msm/registers/display/mdp5.xml
@@ -9,22 +9,6 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<domain name="VBIF" width="32">
</domain>
-<domain name="MDSS" width="32">
- <reg32 offset="0x00000" name="HW_VERSION">
- <bitfield name="STEP" low="0" high="15" type="uint"/>
- <bitfield name="MINOR" low="16" high="27" type="uint"/>
- <bitfield name="MAJOR" low="28" high="31" type="uint"/>
- </reg32>
-
- <reg32 offset="0x00010" name="HW_INTR_STATUS">
- <bitfield name="INTR_MDP" pos="0" type="boolean"/>
- <bitfield name="INTR_DSI0" pos="4" type="boolean"/>
- <bitfield name="INTR_DSI1" pos="5" type="boolean"/>
- <bitfield name="INTR_HDMI" pos="8" type="boolean"/>
- <bitfield name="INTR_EDP" pos="12" type="boolean"/>
- </reg32>
-</domain>
-
<domain name="MDP5" width="32">
<enum name="mdp5_intf_type">
diff --git a/drivers/gpu/drm/msm/registers/display/mdss.xml b/drivers/gpu/drm/msm/registers/display/mdss.xml
new file mode 100644
index 000000000000..ac85caf1575c
--- /dev/null
+++ b/drivers/gpu/drm/msm/registers/display/mdss.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<database xmlns="http://nouveau.freedesktop.org/"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
+<import file="freedreno_copyright.xml"/>
+
+<domain name="MDSS" width="32">
+ <reg32 offset="0x00000" name="HW_VERSION">
+ <bitfield name="STEP" low="0" high="15" type="uint"/>
+ <bitfield name="MINOR" low="16" high="27" type="uint"/>
+ <bitfield name="MAJOR" low="28" high="31" type="uint"/>
+ </reg32>
+
+ <reg32 offset="0x00010" name="HW_INTR_STATUS">
+ <bitfield name="INTR_MDP" pos="0" type="boolean"/>
+ <bitfield name="INTR_DSI0" pos="4" type="boolean"/>
+ <bitfield name="INTR_DSI1" pos="5" type="boolean"/>
+ <bitfield name="INTR_HDMI" pos="8" type="boolean"/>
+ <bitfield name="INTR_EDP" pos="12" type="boolean"/>
+ </reg32>
+
+ <reg32 offset="0x00058" name="UBWC_DEC_HW_VERSION"/>
+
+ <reg32 offset="0x00144" name="UBWC_STATIC"/>
+ <reg32 offset="0x00150" name="UBWC_CTRL_2"/>
+ <reg32 offset="0x00154" name="UBWC_PREDICTION_MODE"/>
+</domain>
+
+</database>
diff --git a/drivers/gpu/drm/nouveau/dispnv50/tile.h b/drivers/gpu/drm/nouveau/dispnv50/tile.h
new file mode 100644
index 000000000000..e2be82830cf7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/tile.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NV50_TILE_H__
+#define __NV50_TILE_H__
+
+#include <linux/types.h>
+#include <linux/math.h>
+
+/*
+ * Tiling parameters for NV50+.
+ * GOB = Group of bytes, the main unit for tiling blocks.
+ * Tiling blocks are a power of 2 number of GOB.
+ * All GOBs and blocks have the same width: 64 bytes (so 16 pixels in 32bits).
+ * tile_mode is the log2 of the number of GOB per block.
+ */
+
+#define NV_TILE_GOB_HEIGHT_TESLA 4 /* 4 x 64 bytes = 256 bytes for a GOB on Tesla*/
+#define NV_TILE_GOB_HEIGHT 8 /* 8 x 64 bytes = 512 bytes for a GOB on Fermi and later */
+#define NV_TILE_GOB_WIDTH_BYTES 64
+
+/* Number of blocks to cover the width of the framebuffer */
+static inline u32 nouveau_get_width_in_blocks(u32 stride)
+{
+ return DIV_ROUND_UP(stride, NV_TILE_GOB_WIDTH_BYTES);
+}
+
+/* Return the height in pixel of one GOB */
+static inline u32 nouveau_get_gob_height(u16 family)
+{
+ if (family == NV_DEVICE_INFO_V0_TESLA)
+ return NV_TILE_GOB_HEIGHT_TESLA;
+ else
+ return NV_TILE_GOB_HEIGHT;
+}
+
+/* Number of blocks to cover the heigth of the framebuffer */
+static inline u32 nouveau_get_height_in_blocks(u32 height, u32 gobs_in_block, u16 family)
+{
+ return DIV_ROUND_UP(height, nouveau_get_gob_height(family) * gobs_in_block);
+}
+
+/* Return the GOB size in bytes */
+static inline u32 nouveau_get_gob_size(u16 family)
+{
+ return nouveau_get_gob_height(family) * NV_TILE_GOB_WIDTH_BYTES;
+}
+
+/* Return the number of GOB in a block */
+static inline int nouveau_get_gobs_in_block(u32 tile_mode, u16 chipset)
+{
+ if (chipset >= 0xc0)
+ return 1 << (tile_mode >> 4);
+ return 1 << tile_mode;
+}
+
+/* Return true if tile_mode is invalid */
+static inline bool nouveau_check_tile_mode(u32 tile_mode, u16 chipset)
+{
+ if (chipset >= 0xc0)
+ return (tile_mode & 0xfffff0f);
+ return (tile_mode & 0xfffffff0);
+}
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index 7a2cceaee6e9..f6be426dd525 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -30,14 +30,20 @@
#include <nvhw/class/cl507e.h>
#include <nvhw/class/clc37e.h>
+#include <linux/iosys-map.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
-#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_panic.h>
+#include <drm/ttm/ttm_bo.h>
#include "nouveau_bo.h"
#include "nouveau_gem.h"
+#include "tile.h"
static void
nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma)
@@ -577,6 +583,114 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
return 0;
}
+/* Only used by drm_panic get_scanout_buffer() and set_pixel(), so it is
+ * protected by the drm panic spinlock
+ */
+static u32 nv50_panic_blk_h;
+
+/* Return the framebuffer offset of the start of the block where pixel(x,y) is */
+static u32
+nv50_get_block_off(unsigned int x, unsigned int y, unsigned int pitch)
+{
+ u32 blk_x, blk_y, blk_columns;
+
+ blk_columns = nouveau_get_width_in_blocks(pitch);
+ blk_x = (x * 4) / NV_TILE_GOB_WIDTH_BYTES;
+ blk_y = y / nv50_panic_blk_h;
+
+ return ((blk_y * blk_columns) + blk_x) * NV_TILE_GOB_WIDTH_BYTES * nv50_panic_blk_h;
+}
+
+/* Turing and later have 2 level of tiles inside the block */
+static void
+nv50_set_pixel_swizzle(struct drm_scanout_buffer *sb, unsigned int x,
+ unsigned int y, u32 color)
+{
+ u32 blk_off, off, swizzle;
+
+ blk_off = nv50_get_block_off(x, y, sb->pitch[0]);
+
+ y = y % nv50_panic_blk_h;
+
+ /* Inside the block, use the fast address swizzle to compute the offset
+ * For nvidia blocklinear, bit order is yn..y3 x3 y2 x2 y1 y0 x1 x0
+ */
+ swizzle = (x & 3) | (y & 3) << 2 | (x & 4) << 2 | (y & 4) << 3;
+ swizzle |= (x & 8) << 3 | (y >> 3) << 7;
+ off = blk_off + swizzle * 4;
+
+ iosys_map_wr(&sb->map[0], off, u32, color);
+}
+
+static void
+nv50_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, unsigned int y,
+ u32 color)
+{
+ u32 blk_off, off;
+
+ blk_off = nv50_get_block_off(x, y, sb->width);
+
+ x = x % (NV_TILE_GOB_WIDTH_BYTES / 4);
+ y = y % nv50_panic_blk_h;
+ off = blk_off + x * 4 + y * NV_TILE_GOB_WIDTH_BYTES;
+
+ iosys_map_wr(&sb->map[0], off, u32, color);
+}
+
+static int
+nv50_wndw_get_scanout_buffer(struct drm_plane *plane, struct drm_scanout_buffer *sb)
+{
+ struct drm_framebuffer *fb;
+ struct nouveau_bo *nvbo;
+ struct nouveau_drm *drm = nouveau_drm(plane->dev);
+ u16 chipset = drm->client.device.info.chipset;
+ u8 family = drm->client.device.info.family;
+ u32 tile_mode;
+ u8 kind;
+
+ if (!plane->state || !plane->state->fb)
+ return -EINVAL;
+
+ fb = plane->state->fb;
+ nvbo = nouveau_gem_object(fb->obj[0]);
+
+ /* Don't support compressed format, or multiplane yet. */
+ if (nvbo->comp || fb->format->num_planes != 1)
+ return -EOPNOTSUPP;
+
+ if (nouveau_bo_map(nvbo)) {
+ drm_warn(plane->dev, "nouveau bo map failed, panic won't be displayed\n");
+ return -ENOMEM;
+ }
+
+ if (nvbo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK)
+ iosys_map_set_vaddr_iomem(&sb->map[0], (void __iomem *)nvbo->kmap.virtual);
+ else
+ iosys_map_set_vaddr(&sb->map[0], nvbo->kmap.virtual);
+
+ sb->height = fb->height;
+ sb->width = fb->width;
+ sb->pitch[0] = fb->pitches[0];
+ sb->format = fb->format;
+
+ nouveau_framebuffer_get_layout(fb, &tile_mode, &kind);
+ if (kind) {
+ /* If tiling is enabled, use set_pixel() to display correctly.
+ * Only handle 32bits format for now.
+ */
+ if (fb->format->cpp[0] != 4)
+ return -EOPNOTSUPP;
+ nv50_panic_blk_h = nouveau_get_gob_height(family) *
+ nouveau_get_gobs_in_block(tile_mode, chipset);
+
+ if (chipset >= 0x160)
+ sb->set_pixel = nv50_set_pixel_swizzle;
+ else
+ sb->set_pixel = nv50_set_pixel;
+ }
+ return 0;
+}
+
static const struct drm_plane_helper_funcs
nv50_wndw_helper = {
.prepare_fb = nv50_wndw_prepare_fb,
@@ -584,6 +698,14 @@ nv50_wndw_helper = {
.atomic_check = nv50_wndw_atomic_check,
};
+static const struct drm_plane_helper_funcs
+nv50_wndw_primary_helper = {
+ .prepare_fb = nv50_wndw_prepare_fb,
+ .cleanup_fb = nv50_wndw_cleanup_fb,
+ .atomic_check = nv50_wndw_atomic_check,
+ .get_scanout_buffer = nv50_wndw_get_scanout_buffer,
+};
+
static void
nv50_wndw_atomic_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
@@ -732,7 +854,10 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
return ret;
}
- drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
+ if (type == DRM_PLANE_TYPE_PRIMARY)
+ drm_plane_helper_add(&wndw->plane, &nv50_wndw_primary_helper);
+ else
+ drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
if (wndw->func->ilut) {
ret = nv50_lut_init(disp, mmu, &wndw->ilut);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 619a3efbe8c8..add006fc8d81 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -44,6 +44,7 @@
#include <nvif/if0011.h>
#include <nvif/if0013.h>
#include <dispnv50/crc.h>
+#include <dispnv50/tile.h>
int
nouveau_display_vblank_enable(struct drm_crtc *crtc)
@@ -220,69 +221,29 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm,
return 0;
}
-static inline uint32_t
-nouveau_get_width_in_blocks(uint32_t stride)
-{
- /* GOBs per block in the x direction is always one, and GOBs are
- * 64 bytes wide
- */
- static const uint32_t log_block_width = 6;
-
- return (stride + (1 << log_block_width) - 1) >> log_block_width;
-}
-
-static inline uint32_t
-nouveau_get_height_in_blocks(struct nouveau_drm *drm,
- uint32_t height,
- uint32_t log_block_height_in_gobs)
-{
- uint32_t log_gob_height;
- uint32_t log_block_height;
-
- BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
-
- if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
- log_gob_height = 2;
- else
- log_gob_height = 3;
-
- log_block_height = log_block_height_in_gobs + log_gob_height;
-
- return (height + (1 << log_block_height) - 1) >> log_block_height;
-}
-
static int
nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo,
uint32_t offset, uint32_t stride, uint32_t h,
uint32_t tile_mode)
{
- uint32_t gob_size, bw, bh;
+ uint32_t gob_size, bw, bh, gobs_in_block;
uint64_t bl_size;
BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
- if (drm->client.device.info.chipset >= 0xc0) {
- if (tile_mode & 0xF)
- return -EINVAL;
- tile_mode >>= 4;
- }
-
- if (tile_mode & 0xFFFFFFF0)
+ if (nouveau_check_tile_mode(tile_mode, drm->client.device.info.chipset))
return -EINVAL;
- if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
- gob_size = 256;
- else
- gob_size = 512;
-
+ gobs_in_block = nouveau_get_gobs_in_block(tile_mode, drm->client.device.info.chipset);
bw = nouveau_get_width_in_blocks(stride);
- bh = nouveau_get_height_in_blocks(drm, h, tile_mode);
+ bh = nouveau_get_height_in_blocks(h, gobs_in_block, drm->client.device.info.family);
+ gob_size = nouveau_get_gob_size(drm->client.device.info.family);
- bl_size = bw * bh * (1 << tile_mode) * gob_size;
+ bl_size = bw * bh * gobs_in_block * gob_size;
- DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
- offset, stride, h, tile_mode, bw, bh, gob_size, bl_size,
- nvbo->bo.base.size);
+ DRM_DEBUG_KMS("offset=%u stride=%u h=%u gobs_in_block=%u bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
+ offset, stride, h, gobs_in_block, bw, bh, gob_size,
+ bl_size, nvbo->bo.base.size);
if (bl_size + offset > nvbo->bo.base.size)
return -ERANGE;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
index 027867c2a8c5..99110ab2f44d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
@@ -992,7 +992,7 @@ r535_dp_train_target(struct nvkm_outp *outp, u8 target, bool mst, u8 link_nr, u8
ctrl->data = data;
ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
- if (ret == -EAGAIN && ctrl->retryTimeMs) {
+ if ((ret == -EAGAIN || ret == -EBUSY) && ctrl->retryTimeMs) {
/*
* Device (likely an eDP panel) isn't ready yet, wait for the time specified
* by GSP before retrying again
@@ -1060,33 +1060,44 @@ r535_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 addr, u8 *data, u8 *psize)
NV0073_CTRL_DP_AUXCH_CTRL_PARAMS *ctrl;
u8 size = *psize;
int ret;
+ int retries;
- ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_AUXCH_CTRL, sizeof(*ctrl));
- if (IS_ERR(ctrl))
- return PTR_ERR(ctrl);
+ for (retries = 0; retries < 3; ++retries) {
+ ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_AUXCH_CTRL, sizeof(*ctrl));
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
- ctrl->subDeviceInstance = 0;
- ctrl->displayId = BIT(outp->index);
- ctrl->bAddrOnly = !size;
- ctrl->cmd = type;
- if (ctrl->bAddrOnly) {
- ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, REQ_TYPE, WRITE);
- ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, I2C_MOT, FALSE);
- }
- ctrl->addr = addr;
- ctrl->size = !ctrl->bAddrOnly ? (size - 1) : 0;
- memcpy(ctrl->data, data, size);
+ ctrl->subDeviceInstance = 0;
+ ctrl->displayId = BIT(outp->index);
+ ctrl->bAddrOnly = !size;
+ ctrl->cmd = type;
+ if (ctrl->bAddrOnly) {
+ ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, REQ_TYPE, WRITE);
+ ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, I2C_MOT, FALSE);
+ }
+ ctrl->addr = addr;
+ ctrl->size = !ctrl->bAddrOnly ? (size - 1) : 0;
+ memcpy(ctrl->data, data, size);
- ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
- if (ret) {
- nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
- return ret;
+ ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
+ if ((ret == -EAGAIN || ret == -EBUSY) && ctrl->retryTimeMs) {
+ /*
+ * Device (likely an eDP panel) isn't ready yet, wait for the time specified
+ * by GSP before retrying again
+ */
+ nvkm_debug(&disp->engine.subdev,
+ "Waiting %dms for GSP LT panel delay before retrying in AUX\n",
+ ctrl->retryTimeMs);
+ msleep(ctrl->retryTimeMs);
+ nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
+ } else {
+ memcpy(data, ctrl->data, size);
+ *psize = ctrl->size;
+ ret = ctrl->replyType;
+ nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
+ break;
+ }
}
-
- memcpy(data, ctrl->data, size);
- *psize = ctrl->size;
- ret = ctrl->replyType;
- nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c
index a1c8545f1249..cac6d64ab67d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c
@@ -89,11 +89,6 @@ nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user,
nvkm_falcon_fw_dtor_sigs(fw);
}
- /* after last write to the img, sync dma mappings */
- dma_sync_single_for_device(fw->fw.device->dev,
- fw->fw.phys,
- sg_dma_len(&fw->fw.mem.sgl),
- DMA_TO_DEVICE);
FLCNFW_DBG(fw, "resetting");
fw->func->reset(fw);
@@ -105,6 +100,12 @@ nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user,
goto done;
}
+ /* after last write to the img, sync dma mappings */
+ dma_sync_single_for_device(fw->fw.device->dev,
+ fw->fw.phys,
+ sg_dma_len(&fw->fw.mem.sgl),
+ DMA_TO_DEVICE);
+
ret = fw->func->load(fw);
if (ret)
goto done;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
index cf58f9da9139..d586aea30898 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
@@ -78,7 +78,7 @@ r535_rpc_status_to_errno(uint32_t rpc_status)
switch (rpc_status) {
case 0x55: /* NV_ERR_NOT_READY */
case 0x66: /* NV_ERR_TIMEOUT_RETRY */
- return -EAGAIN;
+ return -EBUSY;
case 0x51: /* NV_ERR_NO_MEMORY */
return -ENOMEM;
default:
@@ -601,7 +601,7 @@ r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *argv, u32 repc)
if (rpc->status) {
ret = ERR_PTR(r535_rpc_status_to_errno(rpc->status));
- if (PTR_ERR(ret) != -EAGAIN)
+ if (PTR_ERR(ret) != -EAGAIN && PTR_ERR(ret) != -EBUSY)
nvkm_error(&gsp->subdev, "RM_ALLOC: 0x%x\n", rpc->status);
} else {
ret = repc ? rpc->params : NULL;
@@ -660,7 +660,7 @@ r535_gsp_rpc_rm_ctrl_push(struct nvkm_gsp_object *object, void **argv, u32 repc)
if (rpc->status) {
ret = r535_rpc_status_to_errno(rpc->status);
- if (ret != -EAGAIN)
+ if (ret != -EAGAIN && ret != -EBUSY)
nvkm_error(&gsp->subdev, "cli:0x%08x obj:0x%08x ctrl cmd:0x%08x failed: 0x%08x\n",
object->client->object.handle, object->handle, rpc->cmd, rpc->status);
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 030f997eccd0..b17e77f700dd 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/string.h>
@@ -709,7 +710,7 @@ int dpi_init_port(struct dss_device *dss, struct platform_device *pdev,
if (!dpi)
return -ENOMEM;
- ep = of_get_next_child(port, NULL);
+ ep = of_graph_get_next_port_endpoint(port, NULL);
if (!ep)
return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 91eaae3b9481..f9ae358e8e52 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -11,6 +11,7 @@
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/string.h>
@@ -346,7 +347,7 @@ int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
if (!sdi)
return -ENOMEM;
- ep = of_get_next_child(port, NULL);
+ ep = of_graph_get_next_port_endpoint(port, NULL);
if (!ep) {
r = 0;
goto err_free;
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
index 2d30da38c2c3..3385fd3ef41a 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -38,7 +38,7 @@ static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
return PTR_ERR(opp);
dev_pm_opp_put(opp);
- err = dev_pm_opp_set_rate(dev, *freq);
+ err = dev_pm_opp_set_rate(dev, *freq);
if (!err)
ptdev->pfdevfreq.current_frequency = *freq;
@@ -182,6 +182,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
* if any and will avoid a switch off by regulator_late_cleanup()
*/
ret = dev_pm_opp_set_opp(dev, opp);
+ dev_pm_opp_put(opp);
if (ret) {
DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
return ret;
diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.c b/drivers/gpu/drm/panthor/panthor_devfreq.c
index 9d0f891b9b53..ecc7a52bd688 100644
--- a/drivers/gpu/drm/panthor/panthor_devfreq.c
+++ b/drivers/gpu/drm/panthor/panthor_devfreq.c
@@ -163,13 +163,6 @@ int panthor_devfreq_init(struct panthor_device *ptdev)
cur_freq = clk_get_rate(ptdev->clks.core);
- opp = devfreq_recommended_opp(dev, &cur_freq, 0);
- if (IS_ERR(opp))
- return PTR_ERR(opp);
-
- panthor_devfreq_profile.initial_freq = cur_freq;
- ptdev->current_frequency = cur_freq;
-
/* Regulator coupling only takes care of synchronizing/balancing voltage
* updates, but the coupled regulator needs to be enabled manually.
*
@@ -200,18 +193,24 @@ int panthor_devfreq_init(struct panthor_device *ptdev)
return ret;
}
+ opp = devfreq_recommended_opp(dev, &cur_freq, 0);
+ if (IS_ERR(opp))
+ return PTR_ERR(opp);
+
+ panthor_devfreq_profile.initial_freq = cur_freq;
+ ptdev->current_frequency = cur_freq;
+
/*
* Set the recommend OPP this will enable and configure the regulator
* if any and will avoid a switch off by regulator_late_cleanup()
*/
ret = dev_pm_opp_set_opp(dev, opp);
+ dev_pm_opp_put(opp);
if (ret) {
DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
return ret;
}
- dev_pm_opp_put(opp);
-
/* Find the fastest defined rate */
opp = dev_pm_opp_find_freq_floor(dev, &freq);
if (IS_ERR(opp))
diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index 4082c8f2951d..6fbff516c1c1 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -390,11 +390,15 @@ int panthor_device_mmap_io(struct panthor_device *ptdev, struct vm_area_struct *
{
u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT;
+ if ((vma->vm_flags & VM_SHARED) == 0)
+ return -EINVAL;
+
switch (offset) {
case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET:
if (vma->vm_end - vma->vm_start != PAGE_SIZE ||
(vma->vm_flags & (VM_WRITE | VM_EXEC)))
return -EINVAL;
+ vm_flags_clear(vma, VM_MAYWRITE);
break;
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index 8ca85526491e..a49132f3778b 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -990,6 +990,8 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot,
if (!size)
break;
+
+ offset = 0;
}
return panthor_vm_flush_range(vm, start_iova, iova - start_iova);
@@ -1580,7 +1582,9 @@ panthor_vm_pool_get_vm(struct panthor_vm_pool *pool, u32 handle)
{
struct panthor_vm *vm;
+ xa_lock(&pool->xa);
vm = panthor_vm_get(xa_load(&pool->xa, handle));
+ xa_unlock(&pool->xa);
return vm;
}
diff --git a/drivers/gpu/drm/qxl/Kconfig b/drivers/gpu/drm/qxl/Kconfig
index 1992df4a82d2..98a148bea628 100644
--- a/drivers/gpu/drm/qxl/Kconfig
+++ b/drivers/gpu/drm/qxl/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_QXL
tristate "QXL virtual GPU"
- depends on DRM && PCI && MMU
+ depends on DRM && PCI && MMU && HAS_IOPORT
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select DRM_TTM
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index 47aa06a9a942..5b69cc8011b4 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -760,16 +760,20 @@ static int radeon_audio_component_get_eld(struct device *kdev, int port,
if (!rdev->audio.enabled || !rdev->mode_info.mode_config_initialized)
return 0;
- list_for_each_entry(encoder, &rdev_to_drm(rdev)->mode_config.encoder_list, head) {
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ const struct drm_connector_helper_funcs *connector_funcs =
+ connector->helper_private;
+ encoder = connector_funcs->best_encoder(connector);
+
+ if (!encoder)
+ continue;
+
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));
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index f9c73c55f04f..f9996304d943 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1255,16 +1255,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
goto exit;
}
}
-
- if (dret && radeon_connector->hpd.hpd != RADEON_HPD_NONE &&
- !radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) &&
- connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
- DRM_DEBUG_KMS("EDID is readable when HPD disconnected\n");
- schedule_delayed_work(&rdev->hotplug_work, msecs_to_jiffies(1000));
- ret = connector_status_disconnected;
- goto exit;
- }
-
if (dret) {
radeon_connector->detected_by_load = false;
radeon_connector_free_edid(connector);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 23d6d1a2586d..5e958cc223f4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -248,10 +248,9 @@ int radeon_cik_support = 1;
MODULE_PARM_DESC(cik_support, "CIK support (1 = enabled (default), 0 = disabled)");
module_param_named(cik_support, radeon_cik_support, int, 0444);
-static struct pci_device_id pciidlist[] = {
+static const struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
-
MODULE_DEVICE_TABLE(pci, pciidlist);
static const struct drm_driver kms_driver;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 69d0c12fa419..616d25c8c2de 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -219,8 +219,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict,
if (old_mem->mem_type == TTM_PL_TT &&
new_mem->mem_type == TTM_PL_SYSTEM) {
radeon_ttm_tt_unbind(bo->bdev, bo->ttm);
- ttm_resource_free(bo, &bo->resource);
- ttm_bo_assign_mem(bo, new_mem);
+ ttm_bo_move_null(bo, new_mem);
goto out;
}
if (rdev->ring[radeon_copy_ring_index(rdev)].ready &&
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 9c796ee4c303..c8b362cc2b95 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -82,7 +82,7 @@ static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
* comment in rk_hdptx_phy_power_on() from
* drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
*/
- phy_set_bus_width(hdmi->phy, rate / 100);
+ phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
}
}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index f161f40d8ce4..69900138295b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1093,10 +1093,10 @@ static int vop_plane_atomic_async_check(struct drm_plane *plane,
if (!plane->state->fb)
return -EINVAL;
- if (state)
- crtc_state = drm_atomic_get_existing_crtc_state(state,
- new_plane_state->crtc);
- else /* Special case for asynchronous cursor updates. */
+ crtc_state = drm_atomic_get_existing_crtc_state(state, new_plane_state->crtc);
+
+ /* Special case for asynchronous cursor updates. */
+ if (!crtc_state)
crtc_state = plane->crtc->state;
return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index eeaf71d43191..7ce25281c74c 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -1350,6 +1350,19 @@ EXPORT_SYMBOL(drm_sched_init);
* @sched: scheduler instance
*
* Tears down and cleans up the scheduler.
+ *
+ * This stops submission of new jobs to the hardware through
+ * drm_sched_backend_ops.run_job(). Consequently, drm_sched_backend_ops.free_job()
+ * will not be called for all jobs still in drm_gpu_scheduler.pending_list.
+ * There is no solution for this currently. Thus, it is up to the driver to make
+ * sure that
+ * a) drm_sched_fini() is only called after for all submitted jobs
+ * drm_sched_backend_ops.free_job() has been called or that
+ * b) the jobs for which drm_sched_backend_ops.free_job() has not been called
+ * after drm_sched_fini() ran are freed manually.
+ *
+ * FIXME: Take care of the above problem and prevent this function from leaking
+ * the jobs in drm_gpu_scheduler.pending_list under any circumstances.
*/
void drm_sched_fini(struct drm_gpu_scheduler *sched)
{
@@ -1445,8 +1458,10 @@ EXPORT_SYMBOL(drm_sched_wqueue_ready);
/**
* drm_sched_wqueue_stop - stop scheduler submission
- *
* @sched: scheduler instance
+ *
+ * Stops the scheduler from pulling new jobs from entities. It also stops
+ * freeing jobs automatically through drm_sched_backend_ops.free_job().
*/
void drm_sched_wqueue_stop(struct drm_gpu_scheduler *sched)
{
@@ -1458,8 +1473,12 @@ EXPORT_SYMBOL(drm_sched_wqueue_stop);
/**
* drm_sched_wqueue_start - start scheduler submission
- *
* @sched: scheduler instance
+ *
+ * Restarts the scheduler after drm_sched_wqueue_stop() has stopped it.
+ *
+ * This function is not necessary for 'conventional' startup. The scheduler is
+ * fully operational after drm_sched_init() succeeded.
*/
void drm_sched_wqueue_start(struct drm_gpu_scheduler *sched)
{
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 00c8564520e7..caee824832b3 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -46,6 +46,7 @@ struct gr3d {
unsigned int nclocks;
struct reset_control_bulk_data resets[RST_GR3D_MAX];
unsigned int nresets;
+ struct dev_pm_domain_list *pd_list;
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
};
@@ -369,18 +370,13 @@ static int gr3d_power_up_legacy_domain(struct device *dev, const char *name,
return 0;
}
-static void gr3d_del_link(void *link)
-{
- device_link_del(link);
-}
-
static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
{
- static const char * const opp_genpd_names[] = { "3d0", "3d1", NULL };
- const u32 link_flags = DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
- struct device **opp_virt_devs, *pd_dev;
- struct device_link *link;
- unsigned int i;
+ struct dev_pm_domain_attach_data pd_data = {
+ .pd_names = (const char *[]) { "3d0", "3d1" },
+ .num_pd_names = 2,
+ .pd_flags = PD_FLAG_REQUIRED_OPP,
+ };
int err;
err = of_count_phandle_with_args(dev->of_node, "power-domains",
@@ -414,29 +410,10 @@ static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
if (dev->pm_domain)
return 0;
- err = devm_pm_opp_attach_genpd(dev, opp_genpd_names, &opp_virt_devs);
- if (err)
+ err = devm_pm_domain_attach_list(dev, &pd_data, &gr3d->pd_list);
+ if (err < 0)
return err;
- for (i = 0; opp_genpd_names[i]; i++) {
- pd_dev = opp_virt_devs[i];
- if (!pd_dev) {
- dev_err(dev, "failed to get %s power domain\n",
- opp_genpd_names[i]);
- return -EINVAL;
- }
-
- link = device_link_add(dev, pd_dev, link_flags);
- if (!link) {
- dev_err(dev, "failed to link to %s\n", dev_name(pd_dev));
- return -EINVAL;
- }
-
- err = devm_add_action_or_reset(dev, gr3d_del_link, link);
- if (err)
- return err;
- }
-
return 0;
}
diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
index 447989bb8201..6f91ff1dbf7e 100644
--- a/drivers/gpu/drm/tiny/bochs.c
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/bug.h>
#include <linux/aperture.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -106,12 +107,17 @@ static struct bochs_device *to_bochs_device(const struct drm_device *dev)
/* ---------------------------------------------------------------------- */
+static __always_inline bool bochs_uses_mmio(struct bochs_device *bochs)
+{
+ return !IS_ENABLED(CONFIG_HAS_IOPORT) || bochs->mmio;
+}
+
static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val)
{
if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
return;
- if (bochs->mmio) {
+ if (bochs_uses_mmio(bochs)) {
int offset = ioport - 0x3c0 + 0x400;
writeb(val, bochs->mmio + offset);
@@ -125,7 +131,7 @@ static u8 bochs_vga_readb(struct bochs_device *bochs, u16 ioport)
if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
return 0xff;
- if (bochs->mmio) {
+ if (bochs_uses_mmio(bochs)) {
int offset = ioport - 0x3c0 + 0x400;
return readb(bochs->mmio + offset);
@@ -138,7 +144,7 @@ static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
{
u16 ret = 0;
- if (bochs->mmio) {
+ if (bochs_uses_mmio(bochs)) {
int offset = 0x500 + (reg << 1);
ret = readw(bochs->mmio + offset);
@@ -151,7 +157,7 @@ static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
{
- if (bochs->mmio) {
+ if (bochs_uses_mmio(bochs)) {
int offset = 0x500 + (reg << 1);
writew(val, bochs->mmio + offset);
@@ -236,7 +242,7 @@ static int bochs_hw_init(struct bochs_device *bochs)
DRM_ERROR("Cannot map mmio region\n");
return -ENOMEM;
}
- } else {
+ } else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
ioaddr = VBE_DISPI_IOPORT_INDEX;
iosize = 2;
if (!devm_request_region(&pdev->dev, ioaddr, iosize, "bochs-drm")) {
@@ -244,6 +250,9 @@ static int bochs_hw_init(struct bochs_device *bochs)
return -EBUSY;
}
bochs->ioports = 1;
+ } else {
+ dev_err(dev->dev, "I/O ports are not supported\n");
+ return -EIO;
}
id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c
index f06a2be71f60..4d2adcaeaa60 100644
--- a/drivers/gpu/drm/tiny/cirrus.c
+++ b/drivers/gpu/drm/tiny/cirrus.c
@@ -510,8 +510,10 @@ static void cirrus_crtc_helper_atomic_enable(struct drm_crtc *crtc,
cirrus_mode_set(cirrus, &crtc_state->mode);
+#ifdef CONFIG_HAS_IOPORT
/* Unblank (needed on S3 resume, vgabios doesn't do it then) */
outb(VGA_AR_ENABLE_DISPLAY, VGA_ATT_W);
+#endif
drm_dev_exit(idx);
}
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 57a5769fc994..3f0977d746be 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -187,7 +187,7 @@ static void blend(struct vkms_writeback_job *wb,
const struct pixel_argb_u16 background_color = { .a = 0xffff };
- size_t crtc_y_limit = crtc_state->base.crtc->mode.vdisplay;
+ size_t crtc_y_limit = crtc_state->base.mode.vdisplay;
/*
* The planes are composed line-by-line to avoid heavy memory usage. It is a necessary
@@ -270,7 +270,7 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb,
if (WARN_ON(check_format_funcs(crtc_state, active_wb)))
return -EINVAL;
- line_width = crtc_state->base.crtc->mode.hdisplay;
+ line_width = crtc_state->base.mode.hdisplay;
stage_buffer.n_pixels = line_width;
output_buffer.n_pixels = line_width;
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index a40295c18b48..bbf080d32d2c 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -64,8 +64,6 @@ static int vkms_enable_vblank(struct drm_crtc *crtc)
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
- drm_calc_timestamping_constants(crtc, &crtc->mode);
-
hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
out->vblank_hrtimer.function = &vkms_vblank_simulate;
out->period_ns = ktime_set(0, vblank->framedur_ns);
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
index 0a5a185aa0b0..25a99fde126c 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -92,7 +92,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
DRM_MODE_CONNECTOR_VIRTUAL);
if (ret) {
DRM_ERROR("Failed to init connector\n");
- goto err_connector;
+ return ret;
}
drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
@@ -131,8 +131,5 @@ err_attach:
err_encoder:
drm_connector_cleanup(connector);
-err_connector:
- drm_crtc_cleanup(crtc);
-
return ret;
}
diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c
index bc724cbd5e3a..999d5c01ea81 100644
--- a/drivers/gpu/drm/vkms/vkms_writeback.c
+++ b/drivers/gpu/drm/vkms/vkms_writeback.c
@@ -131,8 +131,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn,
struct drm_connector_state *conn_state = wb_conn->base.state;
struct vkms_crtc_state *crtc_state = output->composer_state;
struct drm_framebuffer *fb = connector_state->writeback_job->fb;
- u16 crtc_height = crtc_state->base.crtc->mode.vdisplay;
- u16 crtc_width = crtc_state->base.crtc->mode.hdisplay;
+ u16 crtc_height = crtc_state->base.mode.vdisplay;
+ u16 crtc_width = crtc_state->base.mode.hdisplay;
struct vkms_writeback_job *active_wb;
struct vkms_frame_info *wb_frame_info;
u32 wb_format = fb->format->format;
diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
index 3353e97687d1..a17e62867f3b 100644
--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
@@ -471,7 +471,7 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)
*/
static bool __must_check get_dma_buf_unless_doomed(struct dma_buf *dmabuf)
{
- return atomic_long_inc_not_zero(&dmabuf->file->f_count) != 0L;
+ return file_ref_get(&dmabuf->file->f_ref);
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index f39bf992364d..8db38927729b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1265,6 +1265,8 @@ static int vmw_framebuffer_surface_create_handle(struct drm_framebuffer *fb,
struct vmw_framebuffer_surface *vfbs = vmw_framebuffer_to_vfbs(fb);
struct vmw_bo *bo = vmw_user_object_buffer(&vfbs->uo);
+ if (WARN_ON(!bo))
+ return -EINVAL;
return drm_gem_handle_create(file_priv, &bo->tbo.base, handle);
}
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index bac96c0dd66e..b51a2bde73e2 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -51,7 +51,7 @@ config DRM_XE
config DRM_XE_DISPLAY
bool "Enable display support"
- depends on DRM_XE && DRM_XE=m
+ depends on DRM_XE && DRM_XE=m && HAS_IOPORT
select FB_IOMEM_HELPERS
select I2C
select I2C_ALGOBIT
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 95aabbb74a28..a93e6fcc0ad9 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -254,6 +254,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_modeset_setup.o \
i915-display/intel_modeset_verify.o \
i915-display/intel_panel.o \
+ i915-display/intel_pfit.o \
i915-display/intel_pmdemand.o \
i915-display/intel_pps.o \
i915-display/intel_psr.o \
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
index b7041b578e5e..84b0991b35b3 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
@@ -67,13 +67,12 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
#define IS_METEORLAKE(dev_priv) IS_PLATFORM(dev_priv, XE_METEORLAKE)
#define IS_LUNARLAKE(dev_priv) IS_PLATFORM(dev_priv, XE_LUNARLAKE)
#define IS_BATTLEMAGE(dev_priv) IS_PLATFORM(dev_priv, XE_BATTLEMAGE)
+#define IS_PANTHERLAKE(dev_priv) IS_PLATFORM(dev_priv, XE_PANTHERLAKE)
#define IS_HASWELL_ULT(dev_priv) (dev_priv && 0)
#define IS_BROADWELL_ULT(dev_priv) (dev_priv && 0)
#define IS_BROADWELL_ULX(dev_priv) (dev_priv && 0)
-#define IP_VER(ver, rel) ((ver) << 8 | (rel))
-
#define IS_MOBILE(xe) (xe && 0)
#define IS_TIGERLAKE_UY(xe) (xe && 0)
diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h
index cba587ceba1b..274042bff1be 100644
--- a/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h
+++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_runtime_pm.h
@@ -20,6 +20,14 @@ static inline void enable_rpm_wakeref_asserts(void *rpm)
{
}
+static inline bool
+intel_runtime_pm_suspended(struct xe_runtime_pm *pm)
+{
+ struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm);
+
+ return pm_runtime_suspended(xe->drm.dev);
+}
+
static inline intel_wakeref_t intel_runtime_pm_get(struct xe_runtime_pm *pm)
{
struct xe_device *xe = container_of(pm, struct xe_device, runtime_pm);
diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c
index 977ef47ea1f9..a7dbc6554d69 100644
--- a/drivers/gpu/drm/xe/display/ext/i915_irq.c
+++ b/drivers/gpu/drm/xe/display/ext/i915_irq.c
@@ -7,7 +7,7 @@
#include "i915_reg.h"
#include "intel_uncore.h"
-void gen3_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs)
+void gen2_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs)
{
intel_uncore_write(uncore, regs.imr, 0xffffffff);
intel_uncore_posting_read(uncore, regs.imr);
@@ -24,7 +24,7 @@ void gen3_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs)
/*
* We should clear IMR at preinstall/uninstall, and just check at postinstall.
*/
-void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
+void gen2_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
{
struct xe_device *xe = container_of(uncore, struct xe_device, uncore);
u32 val = intel_uncore_read(uncore, reg);
@@ -41,10 +41,10 @@ void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
intel_uncore_posting_read(uncore, reg);
}
-void gen3_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
+void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
u32 imr_val, u32 ier_val)
{
- gen3_assert_iir_is_zero(uncore, regs.iir);
+ gen2_assert_iir_is_zero(uncore, regs.iir);
intel_uncore_write(uncore, regs.ier, ier_val);
intel_uncore_write(uncore, regs.imr, imr_val);
diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
index 695c27ac6b0f..b5502f335f53 100644
--- a/drivers/gpu/drm/xe/display/xe_display.c
+++ b/drivers/gpu/drm/xe/display/xe_display.c
@@ -202,12 +202,14 @@ int xe_display_init(struct xe_device *xe)
void xe_display_fini(struct xe_device *xe)
{
+ struct intel_display *display = &xe->display;
+
if (!xe->info.probe_display)
return;
intel_hpd_poll_fini(xe);
- intel_hdcp_component_fini(xe);
+ intel_hdcp_component_fini(display);
intel_audio_deinit(xe);
}
diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
index 6d34b55d72bb..7c02323e9531 100644
--- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
+++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
@@ -44,7 +44,7 @@ bool intel_hdcp_gsc_check_status(struct intel_display *display)
bool ret = true;
unsigned int fw_ref;
- if (!gsc && !xe_uc_fw_is_enabled(&gsc->fw)) {
+ if (!gsc || !xe_uc_fw_is_enabled(&gsc->fw)) {
drm_dbg_kms(&xe->drm,
"GSC Components not ready for HDCP2.x\n");
return false;
diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c
index cd811aa2b227..3e0ae40ebbd2 100644
--- a/drivers/gpu/drm/xe/tests/xe_bo.c
+++ b/drivers/gpu/drm/xe/tests/xe_bo.c
@@ -8,7 +8,7 @@
#include <linux/iosys-map.h>
#include <linux/math64.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include <linux/swap.h>
#include <uapi/linux/sysinfo.h>
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 2cfd1a4df92e..6b7f77425c7f 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -13,7 +13,7 @@
#include <drm/drm_color_mgmt.h>
#include <drm/drm_drv.h>
-#include <drm/intel/xe_pciids.h>
+#include <drm/intel/pciids.h>
#include "display/xe_display.h"
#include "regs/xe_gt_regs.h"
@@ -233,7 +233,7 @@ static const struct xe_device_desc rkl_desc = {
.require_force_probe = true,
};
-static const u16 adls_rpls_ids[] = { XE_RPLS_IDS(NOP), 0 };
+static const u16 adls_rpls_ids[] = { INTEL_RPLS_IDS(NOP), 0 };
static const struct xe_device_desc adl_s_desc = {
.graphics = &graphics_xelp,
@@ -248,7 +248,7 @@ static const struct xe_device_desc adl_s_desc = {
},
};
-static const u16 adlp_rplu_ids[] = { XE_RPLU_IDS(NOP), 0 };
+static const u16 adlp_rplu_ids[] = { INTEL_RPLU_IDS(NOP), 0 };
static const struct xe_device_desc adl_p_desc = {
.graphics = &graphics_xelp,
@@ -285,9 +285,9 @@ static const struct xe_device_desc dg1_desc = {
.require_force_probe = true,
};
-static const u16 dg2_g10_ids[] = { XE_DG2_G10_IDS(NOP), XE_ATS_M150_IDS(NOP), 0 };
-static const u16 dg2_g11_ids[] = { XE_DG2_G11_IDS(NOP), XE_ATS_M75_IDS(NOP), 0 };
-static const u16 dg2_g12_ids[] = { XE_DG2_G12_IDS(NOP), 0 };
+static const u16 dg2_g10_ids[] = { INTEL_DG2_G10_IDS(NOP), INTEL_ATS_M150_IDS(NOP), 0 };
+static const u16 dg2_g11_ids[] = { INTEL_DG2_G11_IDS(NOP), INTEL_ATS_M75_IDS(NOP), 0 };
+static const u16 dg2_g12_ids[] = { INTEL_DG2_G12_IDS(NOP), 0 };
#define DG2_FEATURES \
DGFX_FEATURES, \
@@ -348,7 +348,7 @@ static const struct xe_device_desc bmg_desc = {
static const struct xe_device_desc ptl_desc = {
PLATFORM(PANTHERLAKE),
- .has_display = false,
+ .has_display = true,
.require_force_probe = true,
};
@@ -374,11 +374,6 @@ static const struct gmdid_map media_ip_map[] = {
{ 3000, &media_xe2 },
};
-#define INTEL_VGA_DEVICE(id, info) { \
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, id), \
- PCI_BASE_CLASS_DISPLAY << 16, 0xff << 16, \
- (unsigned long) info }
-
/*
* Make sure any device matches here are from most specific to most
* general. For example, since the Quanta match is based on the subsystem
@@ -386,28 +381,26 @@ static const struct gmdid_map media_ip_map[] = {
* PCI ID matches, otherwise we'll use the wrong info struct above.
*/
static const struct pci_device_id pciidlist[] = {
- XE_TGL_IDS(INTEL_VGA_DEVICE, &tgl_desc),
- XE_RKL_IDS(INTEL_VGA_DEVICE, &rkl_desc),
- XE_ADLS_IDS(INTEL_VGA_DEVICE, &adl_s_desc),
- XE_ADLP_IDS(INTEL_VGA_DEVICE, &adl_p_desc),
- XE_ADLN_IDS(INTEL_VGA_DEVICE, &adl_n_desc),
- XE_RPLU_IDS(INTEL_VGA_DEVICE, &adl_p_desc),
- XE_RPLP_IDS(INTEL_VGA_DEVICE, &adl_p_desc),
- XE_RPLS_IDS(INTEL_VGA_DEVICE, &adl_s_desc),
- XE_DG1_IDS(INTEL_VGA_DEVICE, &dg1_desc),
- XE_ATS_M_IDS(INTEL_VGA_DEVICE, &ats_m_desc),
- XE_ARL_IDS(INTEL_VGA_DEVICE, &mtl_desc),
- XE_DG2_IDS(INTEL_VGA_DEVICE, &dg2_desc),
- XE_MTL_IDS(INTEL_VGA_DEVICE, &mtl_desc),
- XE_LNL_IDS(INTEL_VGA_DEVICE, &lnl_desc),
- XE_BMG_IDS(INTEL_VGA_DEVICE, &bmg_desc),
- XE_PTL_IDS(INTEL_VGA_DEVICE, &ptl_desc),
+ INTEL_TGL_IDS(INTEL_VGA_DEVICE, &tgl_desc),
+ INTEL_RKL_IDS(INTEL_VGA_DEVICE, &rkl_desc),
+ INTEL_ADLS_IDS(INTEL_VGA_DEVICE, &adl_s_desc),
+ INTEL_ADLP_IDS(INTEL_VGA_DEVICE, &adl_p_desc),
+ INTEL_ADLN_IDS(INTEL_VGA_DEVICE, &adl_n_desc),
+ INTEL_RPLU_IDS(INTEL_VGA_DEVICE, &adl_p_desc),
+ INTEL_RPLP_IDS(INTEL_VGA_DEVICE, &adl_p_desc),
+ INTEL_RPLS_IDS(INTEL_VGA_DEVICE, &adl_s_desc),
+ INTEL_DG1_IDS(INTEL_VGA_DEVICE, &dg1_desc),
+ INTEL_ATS_M_IDS(INTEL_VGA_DEVICE, &ats_m_desc),
+ INTEL_ARL_IDS(INTEL_VGA_DEVICE, &mtl_desc),
+ INTEL_DG2_IDS(INTEL_VGA_DEVICE, &dg2_desc),
+ INTEL_MTL_IDS(INTEL_VGA_DEVICE, &mtl_desc),
+ INTEL_LNL_IDS(INTEL_VGA_DEVICE, &lnl_desc),
+ INTEL_BMG_IDS(INTEL_VGA_DEVICE, &bmg_desc),
+ INTEL_PTL_IDS(INTEL_VGA_DEVICE, &ptl_desc),
{ }
};
MODULE_DEVICE_TABLE(pci, pciidlist);
-#undef INTEL_VGA_DEVICE
-
/* is device_id present in comma separated list of ids */
static bool device_id_in_list(u16 device_id, const char *devices, bool negative)
{
diff --git a/drivers/greybus/interface.c b/drivers/greybus/interface.c
index d022bfb5e95d..a0f3e9422721 100644
--- a/drivers/greybus/interface.c
+++ b/drivers/greybus/interface.c
@@ -780,7 +780,7 @@ const struct device_type greybus_interface_type = {
* The position of interface within the Endo is encoded in "interface_id"
* argument.
*
- * Returns a pointer to the new interfce or a null pointer if a
+ * Returns a pointer to the new interface or a null pointer if a
* failure occurs due to memory exhaustion.
*/
struct gb_interface *gb_interface_create(struct gb_module *module,
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index f8a56d631242..4d2a89d65b65 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -213,13 +213,16 @@ config HID_CHICONY
config HID_CORSAIR
tristate "Corsair devices"
depends on USB_HID && LEDS_CLASS
+ select POWER_SUPPLY
help
Support for Corsair devices that are not fully compliant with the
HID standard.
+ Support for Corsair Void headsets.
Supported devices:
- Vengeance K90
- Scimitar PRO RGB
+ - Corsair Void headsets
config HID_COUGAR
tristate "Cougar devices"
@@ -465,6 +468,15 @@ config HID_KYE
- MousePen i608X tablet
- EasyPen M610X tablet
+config HID_KYSONA
+ tristate "Kysona devices"
+ depends on USB_HID
+ help
+ Support for Kysona mice.
+
+ Say Y here if you have a Kysona M600 mouse
+ and want to be able to read its battery capacity.
+
config HID_UCLOGIC
tristate "UC-Logic"
depends on USB_HID
@@ -1096,6 +1108,7 @@ config HID_RMI
select RMI4_F11
select RMI4_F12
select RMI4_F30
+ select RMI4_F3A
help
Support for Synaptics RMI4 touchpads.
Say Y here if you have a Synaptics RMI4 touchpads over i2c-hid or usbhid
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 496dab54c73a..24de45f3677d 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -38,7 +38,7 @@ obj-$(CONFIG_HID_BIGBEN_FF) += hid-bigbenff.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o
-obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o
+obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o hid-corsair-void.o
obj-$(CONFIG_HID_COUGAR) += hid-cougar.o
obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
@@ -70,6 +70,7 @@ obj-$(CONFIG_HID_JABRA) += hid-jabra.o
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o
+obj-$(CONFIG_HID_KYSONA) += hid-kysona.o
obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o
obj-$(CONFIG_HID_LETSKETCH) += hid-letsketch.o
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 8420c227e21b..961b7f35aa67 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -148,7 +148,7 @@ out:
}
EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report);
-u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size)
+const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size)
{
int ret;
struct hid_bpf_ctx_kern ctx_kern = {
@@ -183,7 +183,7 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned
ignore_bpf:
kfree(ctx_kern.data);
- return kmemdup(rdesc, *size, GFP_KERNEL);
+ return rdesc;
}
EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);
@@ -260,8 +260,11 @@ int hid_bpf_allocate_event_data(struct hid_device *hdev)
int hid_bpf_reconnect(struct hid_device *hdev)
{
- if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status))
+ if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) {
+ /* trigger call to call_hid_bpf_rdesc_fixup() during the next probe */
+ hdev->bpf_rsize = 0;
return device_reprobe(&hdev->dev);
+ }
return 0;
}
diff --git a/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c b/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c
index 2411dec6db08..9670e5ef8d54 100644
--- a/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c
+++ b/drivers/hid/bpf/progs/Huion__Dial-2.bpf.c
@@ -214,7 +214,8 @@ static const __u8 fixed_rdesc_pad[] = {
CollectionApplication(
// -- Byte 0 in report
ReportId(PAD_REPORT_ID)
- LogicalRange_i8(0, 1)
+ LogicalMaximum_i8(0)
+ LogicalMaximum_i8(1)
UsagePage_Digitizers
Usage_Dig_TabletFunctionKeys
CollectionPhysical(
@@ -234,14 +235,17 @@ static const __u8 fixed_rdesc_pad[] = {
Input(Var|Abs)
// Byte 4 in report is the dial
Usage_GD_Wheel
- LogicalRange_i8(-1, 1)
+ LogicalMinimum_i8(-1)
+ LogicalMaximum_i8(1)
ReportCount(1)
ReportSize(8)
Input(Var|Rel)
// Byte 5 is the button state
UsagePage_Button
- UsageRange_i8(0x01, 0x8)
- LogicalRange_i8(0x0, 0x1)
+ UsageMinimum_i8(0x01)
+ UsageMaximum_i8(0x08)
+ LogicalMinimum_i8(0x0)
+ LogicalMaximum_i8(0x1)
ReportCount(7)
ReportSize(1)
Input(Var|Abs)
@@ -265,7 +269,8 @@ static const __u8 fixed_rdesc_pen[] = {
Usage_Dig_TipSwitch
Usage_Dig_BarrelSwitch
Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2
- LogicalRange_i8(0, 1)
+ LogicalMinimum_i8(0)
+ LogicalMaximum_i8(1)
ReportSize(1)
ReportCount(3)
Input(Var|Abs)
@@ -280,22 +285,28 @@ static const __u8 fixed_rdesc_pen[] = {
UsagePage_GenericDesktop
Unit(cm)
UnitExponent(-1)
- PhysicalRange_i16(0, 266)
- LogicalRange_i16(0, 32767)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(266)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(32767)
Usage_GD_X
Input(Var|Abs) // Bytes 2+3
- PhysicalRange_i16(0, 166)
- LogicalRange_i16(0, 32767)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(166)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(32767)
Usage_GD_Y
Input(Var|Abs) // Bytes 4+5
)
UsagePage_Digitizers
Usage_Dig_TipPressure
- LogicalRange_i16(0, 8191)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(8191)
Input(Var|Abs) // Byte 6+7
ReportSize(8)
ReportCount(2)
- LogicalRange_i8(-60, 60)
+ LogicalMinimum_i8(-60)
+ LogicalMaximum_i8(60)
Usage_Dig_XTilt
Usage_Dig_YTilt
Input(Var|Abs) // Byte 8+9
@@ -313,7 +324,8 @@ static const __u8 fixed_rdesc_vendor[] = {
Usage_Dig_Pen
CollectionPhysical(
// Byte 1 are the buttons
- LogicalRange_i8(0, 1)
+ LogicalMinimum_i8(0)
+ LogicalMaximum_i8(1)
ReportSize(1)
Usage_Dig_TipSwitch
Usage_Dig_BarrelSwitch
@@ -333,25 +345,31 @@ static const __u8 fixed_rdesc_vendor[] = {
UnitExponent(-1)
// Note: reported logical range differs
// from the pen report ID for x and y
- LogicalRange_i16(0, 53340)
- PhysicalRange_i16(0, 266)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(53340)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(266)
// Bytes 2/3 in report
Usage_GD_X
Input(Var|Abs)
- LogicalRange_i16(0, 33340)
- PhysicalRange_i16(0, 166)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(33340)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(166)
// Bytes 4/5 in report
Usage_GD_Y
Input(Var|Abs)
)
// Bytes 6/7 in report
- LogicalRange_i16(0, 8191)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(8191)
Usage_Dig_TipPressure
Input(Var|Abs)
// Bytes 8/9 in report
ReportCount(1) // Padding
Input(Const)
- LogicalRange_i8(-60, 60)
+ LogicalMinimum_i8(-60)
+ LogicalMaximum_i8(60)
// Byte 10 in report
Usage_Dig_XTilt
// Byte 11 in report
@@ -366,7 +384,8 @@ static const __u8 fixed_rdesc_vendor[] = {
CollectionApplication(
// Byte 0
ReportId(PAD_REPORT_ID)
- LogicalRange_i8(0, 1)
+ LogicalMinimum_i8(0)
+ LogicalMaximum_i8(1)
UsagePage_Digitizers
Usage_Dig_TabletFunctionKeys
CollectionPhysical(
@@ -386,15 +405,18 @@ static const __u8 fixed_rdesc_vendor[] = {
Input(Var|Abs)
// Byte 4 is the button state
UsagePage_Button
- UsageRange_i8(0x01, 0x8)
- LogicalRange_i8(0x0, 0x1)
+ UsageMinimum_i8(0x1)
+ UsageMaximum_i8(0x8)
+ LogicalMinimum_i8(0x0)
+ LogicalMaximum_i8(0x1)
ReportCount(8)
ReportSize(1)
Input(Var|Abs)
// Byte 5 is the top dial
UsagePage_GenericDesktop
Usage_GD_Wheel
- LogicalRange_i8(-1, 1)
+ LogicalMinimum_i8(-1)
+ LogicalMaximum_i8(1)
ReportCount(1)
ReportSize(8)
Input(Var|Rel)
diff --git a/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
index b09b80132368..13f64fb49800 100644
--- a/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
+++ b/drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
@@ -170,7 +170,8 @@ static const __u8 fixed_rdesc_pad[] = {
CollectionApplication(
// -- Byte 0 in report
ReportId(PAD_REPORT_ID)
- LogicalRange_i8(0, 1)
+ LogicalMinimum_i8(0)
+ LogicalMaximum_i8(1)
UsagePage_Digitizers
Usage_Dig_TabletFunctionKeys
CollectionPhysical(
@@ -190,14 +191,17 @@ static const __u8 fixed_rdesc_pad[] = {
Input(Var|Abs)
// Byte 4 in report is the wheel
Usage_GD_Wheel
- LogicalRange_i8(-1, 1)
+ LogicalMinimum_i8(-1)
+ LogicalMaximum_i8(1)
ReportCount(1)
ReportSize(8)
Input(Var|Rel)
// Byte 5 is the button state
UsagePage_Button
- UsageRange_i8(0x01, 0x6)
- LogicalRange_i8(0x01, 0x6)
+ UsageMinimum_i8(0x1)
+ UsageMaximum_i8(0x6)
+ LogicalMinimum_i8(0x1)
+ LogicalMaximum_i8(0x6)
ReportCount(1)
ReportSize(8)
Input(Arr|Abs)
@@ -219,7 +223,8 @@ static const __u8 fixed_rdesc_pen[] = {
Usage_Dig_TipSwitch
Usage_Dig_BarrelSwitch
Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2
- LogicalRange_i8(0, 1)
+ LogicalMinimum_i8(0)
+ LogicalMaximum_i8(1)
ReportSize(1)
ReportCount(3)
Input(Var|Abs)
@@ -234,18 +239,23 @@ static const __u8 fixed_rdesc_pen[] = {
UsagePage_GenericDesktop
Unit(cm)
UnitExponent(-1)
- PhysicalRange_i16(0, 160)
- LogicalRange_i16(0, 32767)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(160)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(32767)
Usage_GD_X
Input(Var|Abs) // Bytes 2+3
- PhysicalRange_i16(0, 100)
- LogicalRange_i16(0, 32767)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(100)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(32767)
Usage_GD_Y
Input(Var|Abs) // Bytes 4+5
)
UsagePage_Digitizers
Usage_Dig_TipPressure
- LogicalRange_i16(0, 8191)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(8191)
Input(Var|Abs) // Byte 6+7
// Two bytes padding so we don't need to change the report at all
ReportSize(8)
@@ -265,7 +275,8 @@ static const __u8 fixed_rdesc_vendor[] = {
Usage_Dig_Pen
CollectionPhysical(
// Byte 1 are the buttons
- LogicalRange_i8(0, 1)
+ LogicalMinimum_i8(0)
+ LogicalMaximum_i8(1)
ReportSize(1)
Usage_Dig_TipSwitch
Usage_Dig_BarrelSwitch
@@ -285,19 +296,24 @@ static const __u8 fixed_rdesc_vendor[] = {
UnitExponent(-1)
// Note: reported logical range differs
// from the pen report ID for x and y
- LogicalRange_i16(0, 32000)
- PhysicalRange_i16(0, 160)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(32000)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(160)
// Bytes 2/3 in report
Usage_GD_X
Input(Var|Abs)
- LogicalRange_i16(0, 20000)
- PhysicalRange_i16(0, 100)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(20000)
+ PhysicalMinimum_i16(0)
+ PhysicalMaximum_i16(100)
// Bytes 4/5 in report
Usage_GD_Y
Input(Var|Abs)
)
// Bytes 6/7 in report
- LogicalRange_i16(0, 8192)
+ LogicalMinimum_i16(0)
+ LogicalMaximum_i16(8192)
Usage_Dig_TipPressure
Input(Var|Abs)
)
@@ -307,7 +323,8 @@ static const __u8 fixed_rdesc_vendor[] = {
CollectionApplication(
// Byte 0
ReportId(PAD_REPORT_ID)
- LogicalRange_i8(0, 1)
+ LogicalMinimum_i8(0)
+ LogicalMaximum_i8(1)
UsagePage_Digitizers
Usage_Dig_TabletFunctionKeys
CollectionPhysical(
@@ -327,8 +344,10 @@ static const __u8 fixed_rdesc_vendor[] = {
Input(Var|Abs)
// Byte 4 is the button state
UsagePage_Button
- UsageRange_i8(0x01, 0x6)
- LogicalRange_i8(0x0, 0x1)
+ UsageMinimum_i8(0x1)
+ UsageMaximum_i8(0x6)
+ LogicalMinimum_i8(0x0)
+ LogicalMaximum_i8(0x1)
ReportCount(6)
ReportSize(1)
Input(Var|Abs)
@@ -337,7 +356,8 @@ static const __u8 fixed_rdesc_vendor[] = {
// Byte 5 is the wheel
UsagePage_GenericDesktop
Usage_GD_Wheel
- LogicalRange_i8(-1, 1)
+ LogicalMinimum_i8(-1)
+ LogicalMaximum_i8(1)
ReportCount(1)
ReportSize(8)
Input(Var|Rel)
diff --git a/drivers/hid/bpf/progs/Mistel__MD770.bpf.c b/drivers/hid/bpf/progs/Mistel__MD770.bpf.c
new file mode 100644
index 000000000000..fb8b5a6968b1
--- /dev/null
+++ b/drivers/hid/bpf/progs/Mistel__MD770.bpf.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Tatsuyuki Ishi
+ */
+
+#include "vmlinux.h"
+#include "hid_bpf.h"
+#include "hid_bpf_helpers.h"
+#include <bpf/bpf_tracing.h>
+
+#define VID_HOLTEK 0x04D9
+#define PID_MD770 0x0339
+#define RDESC_SIZE 203
+
+HID_BPF_CONFIG(
+ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HOLTEK, PID_MD770)
+);
+
+/*
+ * The Mistel MD770 keyboard reports the first 6 simultaneous key presses
+ * through the first interface, and anything beyond that through a second
+ * interface. Unfortunately, the second interface's report descriptor has an
+ * error, causing events to be malformed and ignored. This HID-BPF driver
+ * fixes the descriptor to allow NKRO to work again.
+ *
+ * For reference, this is the original report descriptor:
+ *
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 0
+ * 0x09, 0x80, // Usage (System Control) 2
+ * 0xa1, 0x01, // Collection (Application) 4
+ * 0x85, 0x01, // Report ID (1) 6
+ * 0x19, 0x81, // Usage Minimum (129) 8
+ * 0x29, 0x83, // Usage Maximum (131) 10
+ * 0x15, 0x00, // Logical Minimum (0) 12
+ * 0x25, 0x01, // Logical Maximum (1) 14
+ * 0x95, 0x03, // Report Count (3) 16
+ * 0x75, 0x01, // Report Size (1) 18
+ * 0x81, 0x02, // Input (Data,Var,Abs) 20
+ * 0x95, 0x01, // Report Count (1) 22
+ * 0x75, 0x05, // Report Size (5) 24
+ * 0x81, 0x01, // Input (Cnst,Arr,Abs) 26
+ * 0xc0, // End Collection 28
+ * 0x05, 0x0c, // Usage Page (Consumer Devices) 29
+ * 0x09, 0x01, // Usage (Consumer Control) 31
+ * 0xa1, 0x01, // Collection (Application) 33
+ * 0x85, 0x02, // Report ID (2) 35
+ * 0x15, 0x00, // Logical Minimum (0) 37
+ * 0x25, 0x01, // Logical Maximum (1) 39
+ * 0x95, 0x12, // Report Count (18) 41
+ * 0x75, 0x01, // Report Size (1) 43
+ * 0x0a, 0x83, 0x01, // Usage (AL Consumer Control Config) 45
+ * 0x0a, 0x8a, 0x01, // Usage (AL Email Reader) 48
+ * 0x0a, 0x92, 0x01, // Usage (AL Calculator) 51
+ * 0x0a, 0x94, 0x01, // Usage (AL Local Machine Browser) 54
+ * 0x09, 0xcd, // Usage (Play/Pause) 57
+ * 0x09, 0xb7, // Usage (Stop) 59
+ * 0x09, 0xb6, // Usage (Scan Previous Track) 61
+ * 0x09, 0xb5, // Usage (Scan Next Track) 63
+ * 0x09, 0xe2, // Usage (Mute) 65
+ * 0x09, 0xea, // Usage (Volume Down) 67
+ * 0x09, 0xe9, // Usage (Volume Up) 69
+ * 0x0a, 0x21, 0x02, // Usage (AC Search) 71
+ * 0x0a, 0x23, 0x02, // Usage (AC Home) 74
+ * 0x0a, 0x24, 0x02, // Usage (AC Back) 77
+ * 0x0a, 0x25, 0x02, // Usage (AC Forward) 80
+ * 0x0a, 0x26, 0x02, // Usage (AC Stop) 83
+ * 0x0a, 0x27, 0x02, // Usage (AC Refresh) 86
+ * 0x0a, 0x2a, 0x02, // Usage (AC Bookmarks) 89
+ * 0x81, 0x02, // Input (Data,Var,Abs) 92
+ * 0x95, 0x01, // Report Count (1) 94
+ * 0x75, 0x0e, // Report Size (14) 96
+ * 0x81, 0x01, // Input (Cnst,Arr,Abs) 98
+ * 0xc0, // End Collection 100
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 101
+ * 0x09, 0x02, // Usage (Mouse) 103
+ * 0xa1, 0x01, // Collection (Application) 105
+ * 0x09, 0x01, // Usage (Pointer) 107
+ * 0xa1, 0x00, // Collection (Physical) 109
+ * 0x85, 0x03, // Report ID (3) 111
+ * 0x05, 0x09, // Usage Page (Button) 113
+ * 0x19, 0x01, // Usage Minimum (1) 115
+ * 0x29, 0x08, // Usage Maximum (8) 117
+ * 0x15, 0x00, // Logical Minimum (0) 119
+ * 0x25, 0x01, // Logical Maximum (1) 121
+ * 0x75, 0x01, // Report Size (1) 123
+ * 0x95, 0x08, // Report Count (8) 125
+ * 0x81, 0x02, // Input (Data,Var,Abs) 127
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 129
+ * 0x09, 0x30, // Usage (X) 131
+ * 0x09, 0x31, // Usage (Y) 133
+ * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 135
+ * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 138
+ * 0x75, 0x10, // Report Size (16) 141
+ * 0x95, 0x02, // Report Count (2) 143
+ * 0x81, 0x06, // Input (Data,Var,Rel) 145
+ * 0x09, 0x38, // Usage (Wheel) 147
+ * 0x15, 0x81, // Logical Minimum (-127) 149
+ * 0x25, 0x7f, // Logical Maximum (127) 151
+ * 0x75, 0x08, // Report Size (8) 153
+ * 0x95, 0x01, // Report Count (1) 155
+ * 0x81, 0x06, // Input (Data,Var,Rel) 157
+ * 0x05, 0x0c, // Usage Page (Consumer Devices) 159
+ * 0x0a, 0x38, 0x02, // Usage (AC Pan) 161
+ * 0x95, 0x01, // Report Count (1) 164
+ * 0x81, 0x06, // Input (Data,Var,Rel) 166
+ * 0xc0, // End Collection 168
+ * 0xc0, // End Collection 169
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 170
+ * 0x09, 0x06, // Usage (Keyboard) 172
+ * 0xa1, 0x01, // Collection (Application) 174
+ * 0x85, 0x04, // Report ID (4) 176
+ * 0x05, 0x07, // Usage Page (Keyboard) 178
+ * 0x95, 0x01, // Report Count (1) 180
+ * 0x75, 0x08, // Report Size (8) 182
+ * 0x81, 0x03, // Input (Cnst,Var,Abs) 184
+ * 0x95, 0xe8, // Report Count (232) 186
+ * 0x75, 0x01, // Report Size (1) 188
+ * 0x15, 0x00, // Logical Minimum (0) 190
+ * 0x25, 0x01, // Logical Maximum (1) 192
+ * 0x05, 0x07, // Usage Page (Keyboard) 194
+ * 0x19, 0x00, // Usage Minimum (0) 196
+ * 0x29, 0xe7, // Usage Maximum (231) 198
+ * 0x81, 0x00, // Input (Data,Arr,Abs) 200 <- change to 0x81, 0x02 (Data,Var,Abs)
+ * 0xc0, // End Collection 202
+ */
+
+SEC(HID_BPF_RDESC_FIXUP)
+int BPF_PROG(hid_rdesc_fixup_mistel_md770, struct hid_bpf_ctx *hctx)
+{
+ __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE);
+
+ if (!data)
+ return 0; /* EPERM check */
+
+ if (data[201] == 0x00)
+ data[201] = 0x02;
+
+ return 0;
+}
+
+HID_BPF_OPS(mistel_md770) = {
+ .hid_rdesc_fixup = (void *)hid_rdesc_fixup_mistel_md770,
+};
+
+SEC("syscall")
+int probe(struct hid_bpf_probe_args *ctx)
+{
+ ctx->retval = ctx->rdesc_size != RDESC_SIZE;
+ if (ctx->retval)
+ ctx->retval = -EINVAL;
+
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c b/drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c
new file mode 100644
index 000000000000..6b379e45f531
--- /dev/null
+++ b/drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2024 José Expósito
+ */
+
+#include "vmlinux.h"
+#include "hid_bpf.h"
+#include "hid_bpf_helpers.h"
+#include <bpf/bpf_tracing.h>
+
+#define VID_RAPOO 0x24AE
+#define PID_M50 0x2015
+#define RDESC_SIZE 186
+
+HID_BPF_CONFIG(
+ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_RAPOO, PID_M50)
+);
+
+/*
+ * The Rapoo M50 Plus Silent mouse has 2 side buttons in addition to the left,
+ * right and middle buttons. However, its original HID descriptor has a Usage
+ * Maximum of 3, preventing the side buttons to work. This HID-BPF driver
+ * changes that usage to 5.
+ *
+ * For reference, this is the original report descriptor:
+ *
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 0
+ * 0x09, 0x02, // Usage (Mouse) 2
+ * 0xa1, 0x01, // Collection (Application) 4
+ * 0x85, 0x01, // Report ID (1) 6
+ * 0x09, 0x01, // Usage (Pointer) 8
+ * 0xa1, 0x00, // Collection (Physical) 10
+ * 0x05, 0x09, // Usage Page (Button) 12
+ * 0x19, 0x01, // Usage Minimum (1) 14
+ * 0x29, 0x03, // Usage Maximum (3) 16 <- change to 0x05
+ * 0x15, 0x00, // Logical Minimum (0) 18
+ * 0x25, 0x01, // Logical Maximum (1) 20
+ * 0x75, 0x01, // Report Size (1) 22
+ * 0x95, 0x05, // Report Count (5) 24
+ * 0x81, 0x02, // Input (Data,Var,Abs) 26
+ * 0x75, 0x03, // Report Size (3) 28
+ * 0x95, 0x01, // Report Count (1) 30
+ * 0x81, 0x01, // Input (Cnst,Arr,Abs) 32
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 34
+ * 0x09, 0x30, // Usage (X) 36
+ * 0x09, 0x31, // Usage (Y) 38
+ * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 40
+ * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 43
+ * 0x75, 0x10, // Report Size (16) 46
+ * 0x95, 0x02, // Report Count (2) 48
+ * 0x81, 0x06, // Input (Data,Var,Rel) 50
+ * 0x09, 0x38, // Usage (Wheel) 52
+ * 0x15, 0x81, // Logical Minimum (-127) 54
+ * 0x25, 0x7f, // Logical Maximum (127) 56
+ * 0x75, 0x08, // Report Size (8) 58
+ * 0x95, 0x01, // Report Count (1) 60
+ * 0x81, 0x06, // Input (Data,Var,Rel) 62
+ * 0xc0, // End Collection 64
+ * 0xc0, // End Collection 65
+ * 0x05, 0x0c, // Usage Page (Consumer Devices) 66
+ * 0x09, 0x01, // Usage (Consumer Control) 68
+ * 0xa1, 0x01, // Collection (Application) 70
+ * 0x85, 0x02, // Report ID (2) 72
+ * 0x75, 0x10, // Report Size (16) 74
+ * 0x95, 0x01, // Report Count (1) 76
+ * 0x15, 0x01, // Logical Minimum (1) 78
+ * 0x26, 0x8c, 0x02, // Logical Maximum (652) 80
+ * 0x19, 0x01, // Usage Minimum (1) 83
+ * 0x2a, 0x8c, 0x02, // Usage Maximum (652) 85
+ * 0x81, 0x00, // Input (Data,Arr,Abs) 88
+ * 0xc0, // End Collection 90
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 91
+ * 0x09, 0x80, // Usage (System Control) 93
+ * 0xa1, 0x01, // Collection (Application) 95
+ * 0x85, 0x03, // Report ID (3) 97
+ * 0x09, 0x82, // Usage (System Sleep) 99
+ * 0x09, 0x81, // Usage (System Power Down) 101
+ * 0x09, 0x83, // Usage (System Wake Up) 103
+ * 0x15, 0x00, // Logical Minimum (0) 105
+ * 0x25, 0x01, // Logical Maximum (1) 107
+ * 0x19, 0x01, // Usage Minimum (1) 109
+ * 0x29, 0x03, // Usage Maximum (3) 111
+ * 0x75, 0x01, // Report Size (1) 113
+ * 0x95, 0x03, // Report Count (3) 115
+ * 0x81, 0x02, // Input (Data,Var,Abs) 117
+ * 0x95, 0x05, // Report Count (5) 119
+ * 0x81, 0x01, // Input (Cnst,Arr,Abs) 121
+ * 0xc0, // End Collection 123
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 124
+ * 0x09, 0x00, // Usage (Undefined) 126
+ * 0xa1, 0x01, // Collection (Application) 128
+ * 0x85, 0x05, // Report ID (5) 130
+ * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 132
+ * 0x09, 0x01, // Usage (Vendor Usage 1) 135
+ * 0x15, 0x81, // Logical Minimum (-127) 137
+ * 0x25, 0x7f, // Logical Maximum (127) 139
+ * 0x75, 0x08, // Report Size (8) 141
+ * 0x95, 0x07, // Report Count (7) 143
+ * 0xb1, 0x02, // Feature (Data,Var,Abs) 145
+ * 0xc0, // End Collection 147
+ * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 148
+ * 0x09, 0x0e, // Usage (Vendor Usage 0x0e) 151
+ * 0xa1, 0x01, // Collection (Application) 153
+ * 0x85, 0xba, // Report ID (186) 155
+ * 0x95, 0x1f, // Report Count (31) 157
+ * 0x75, 0x08, // Report Size (8) 159
+ * 0x26, 0xff, 0x00, // Logical Maximum (255) 161
+ * 0x15, 0x00, // Logical Minimum (0) 164
+ * 0x09, 0x01, // Usage (Vendor Usage 1) 166
+ * 0x91, 0x02, // Output (Data,Var,Abs) 168
+ * 0x85, 0xba, // Report ID (186) 170
+ * 0x95, 0x1f, // Report Count (31) 172
+ * 0x75, 0x08, // Report Size (8) 174
+ * 0x26, 0xff, 0x00, // Logical Maximum (255) 176
+ * 0x15, 0x00, // Logical Minimum (0) 179
+ * 0x09, 0x01, // Usage (Vendor Usage 1) 181
+ * 0x81, 0x02, // Input (Data,Var,Abs) 183
+ * 0xc0, // End Collection 185
+ */
+
+SEC(HID_BPF_RDESC_FIXUP)
+int BPF_PROG(hid_rdesc_fixup_rapoo_m50, struct hid_bpf_ctx *hctx)
+{
+ __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE);
+
+ if (!data)
+ return 0; /* EPERM check */
+
+ if (data[17] == 0x03)
+ data[17] = 0x05;
+
+ return 0;
+}
+
+HID_BPF_OPS(rapoo_m50) = {
+ .hid_rdesc_fixup = (void *)hid_rdesc_fixup_rapoo_m50,
+};
+
+SEC("syscall")
+int probe(struct hid_bpf_probe_args *ctx)
+{
+ ctx->retval = ctx->rdesc_size != RDESC_SIZE;
+ if (ctx->retval)
+ ctx->retval = -EINVAL;
+
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/drivers/hid/bpf/progs/hid_report_helpers.h b/drivers/hid/bpf/progs/hid_report_helpers.h
index 0aa1df438eeb..9b2a48e4a311 100644
--- a/drivers/hid/bpf/progs/hid_report_helpers.h
+++ b/drivers/hid/bpf/progs/hid_report_helpers.h
@@ -52,7 +52,8 @@
* Usage_GD_Keyboard
* CollectionApplication( ↠Open the collection
* ReportId(3)
- * LogicalRange_i8(0, 1)
+ * LogicalMinimum_i8(0)
+ * LogicalMaximum_i8(1)
* // other fields
* ) ↠End EndCollection
*
@@ -74,26 +75,43 @@
#define Arr 0x0
#define Abs 0x0
#define Rel 0x4
+#define Null 0x40
+#define Buff 0x0100
/* Use like this: Input(Var|Abs) */
#define Input(i_) 0x081, i8(i_),
#define Output(i_) 0x091, i8(i_),
#define Feature(i_) 0x0b1, i8(i_),
+#define Input_i16(i_) 0x082, LE16(i_),
+#define Output_i16(i_) 0x092, LE16(i_),
+#define Feature_i16(i_) 0x0b2, LE16(i_),
+
#define ReportId(id_) 0x85, i8(id_),
#define ReportSize(sz_) 0x75, i8(sz_),
#define ReportCount(cnt_) 0x95, i8(cnt_),
-#define LogicalRange_i8(min_, max_) 0x15, i8(min_), 0x25, i8(max_),
-#define LogicalRange_i16(min_, max_) 0x16, LE16(min_), 0x26, LE16(max_),
-#define LogicalRange_i32(min_, max_) 0x17, LE32(min_), 0x27, LE32(max_),
+#define LogicalMinimum_i8(min_) 0x15, i8(min_),
+#define LogicalMinimum_i16(min_) 0x16, LE16(min_),
+#define LogicalMinimum_i32(min_) 0x17, LE32(min_),
+
+#define LogicalMaximum_i8(max_) 0x25, i8(max_),
+#define LogicalMaximum_i16(max_) 0x26, LE16(max_),
+#define LogicalMaximum_i32(max_) 0x27, LE32(max_),
+
+#define PhysicalMinimum_i8(min_) 0x35, i8(min_),
+#define PhysicalMinimum_i16(min_) 0x36, LE16(min_),
+#define PhysicalMinimum_i32(min_) 0x37, LE32(min_),
+
+#define PhysicalMaximum_i8(max_) 0x45, i8(max_),
+#define PhysicalMaximum_i16(max_) 0x46, LE16(max_),
+#define PhysicalMaximum_i32(max_) 0x47, LE32(max_),
-#define PhysicalRange_i8(min_, max_) 0x35, i8(min_), 0x45, i8(max_),
-#define PhysicalRange_i16(min_, max_) 0x36, LE16(min_), 0x46, LE16(max_),
-#define PhysicalRange_i32(min_, max_) 0x37, LE32(min_), 0x47, LE32(max_),
+#define UsageMinimum_i8(min_) 0x19, i8(min_),
+#define UsageMinimum_i16(min_) 0x1a, LE16(min_),
-#define UsageRange_i8(min_, max_) 0x19, i8(min_), 0x29, i8(max_),
-#define UsageRange_i16(min_, max_) 0x1a, LE16(min_), 0x2a, LE16(max_),
+#define UsageMaximum_i8(max_) 0x29, i8(max_),
+#define UsageMaximum_i16(max_) 0x2a, LE16(max_),
#define UsagePage_i8(p_) 0x05, i8(p_),
#define UsagePage_i16(p_) 0x06, LE16(p_),
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index a4b47319ad8e..506c6f377e7d 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -1183,7 +1183,7 @@ static const __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
if (drvdata->quirks & QUIRK_G752_KEYBOARD &&
*rsize == 75 && rdesc[61] == 0x15 && rdesc[62] == 0x00) {
- /* report is missing usage mninum and maximum */
+ /* report is missing usage minimum and maximum */
__u8 *new_rdesc;
size_t new_size = *rsize + sizeof(asus_g752_fixed_rdesc);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 612ee6ddfc8d..98bef39642a9 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -46,6 +46,34 @@ module_param_named(ignore_special_drivers, hid_ignore_special_drivers, int, 0600
MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle all devices by generic driver");
/*
+ * Convert a signed n-bit integer to signed 32-bit integer.
+ */
+
+static s32 snto32(__u32 value, unsigned int n)
+{
+ if (!value || !n)
+ return 0;
+
+ if (n > 32)
+ n = 32;
+
+ return sign_extend32(value, n - 1);
+}
+
+/*
+ * Convert a signed 32-bit integer to a signed n-bit integer.
+ */
+
+static u32 s32ton(__s32 value, unsigned int n)
+{
+ s32 a = value >> (n - 1);
+
+ if (a && a != -1)
+ return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
+ return value & ((1 << n) - 1);
+}
+
+/*
* Register a new report for a device.
*/
@@ -425,7 +453,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
* both this and the standard encoding. */
raw_value = item_sdata(item);
if (!(raw_value & 0xfffffff0))
- parser->global.unit_exponent = hid_snto32(raw_value, 4);
+ parser->global.unit_exponent = snto32(raw_value, 4);
else
parser->global.unit_exponent = raw_value;
return 0;
@@ -685,7 +713,14 @@ static void hid_close_report(struct hid_device *device)
INIT_LIST_HEAD(&report_enum->report_list);
}
- kfree(device->rdesc);
+ /*
+ * If the HID driver had a rdesc_fixup() callback, dev->rdesc
+ * will be allocated by hid-core and needs to be freed.
+ * Otherwise, it is either equal to dev_rdesc or bpf_rdesc, in
+ * which cases it'll be freed later on device removal or destroy.
+ */
+ if (device->rdesc != device->dev_rdesc && device->rdesc != device->bpf_rdesc)
+ kfree(device->rdesc);
device->rdesc = NULL;
device->rsize = 0;
@@ -698,6 +733,14 @@ static void hid_close_report(struct hid_device *device)
device->status &= ~HID_STAT_PARSED;
}
+static inline void hid_free_bpf_rdesc(struct hid_device *hdev)
+{
+ /* bpf_rdesc is either equal to dev_rdesc or allocated by call_hid_bpf_rdesc_fixup() */
+ if (hdev->bpf_rdesc != hdev->dev_rdesc)
+ kfree(hdev->bpf_rdesc);
+ hdev->bpf_rdesc = NULL;
+}
+
/*
* Free a device structure, all reports, and all fields.
*/
@@ -707,6 +750,7 @@ void hiddev_free(struct kref *ref)
struct hid_device *hid = container_of(ref, struct hid_device, ref);
hid_close_report(hid);
+ hid_free_bpf_rdesc(hid);
kfree(hid->dev_rdesc);
kfree(hid);
}
@@ -754,35 +798,29 @@ static const u8 *fetch_item(const __u8 *start, const __u8 *end, struct hid_item
}
item->format = HID_ITEM_FORMAT_SHORT;
- item->size = b & 3;
+ item->size = BIT(b & 3) >> 1; /* 0, 1, 2, 3 -> 0, 1, 2, 4 */
+
+ if (end - start < item->size)
+ return NULL;
switch (item->size) {
case 0:
- return start;
+ break;
case 1:
- if ((end - start) < 1)
- return NULL;
- item->data.u8 = *start++;
- return start;
+ item->data.u8 = *start;
+ break;
case 2:
- if ((end - start) < 2)
- return NULL;
item->data.u16 = get_unaligned_le16(start);
- start = (__u8 *)((__le16 *)start + 1);
- return start;
+ break;
- case 3:
- item->size++;
- if ((end - start) < 4)
- return NULL;
+ case 4:
item->data.u32 = get_unaligned_le32(start);
- start = (__u8 *)((__le32 *)start + 1);
- return start;
+ break;
}
- return NULL;
+ return start + item->size;
}
static void hid_scan_input_usage(struct hid_parser *parser, u32 usage)
@@ -1205,7 +1243,6 @@ int hid_open_report(struct hid_device *device)
struct hid_item item;
unsigned int size;
const __u8 *start;
- __u8 *buf;
const __u8 *end;
const __u8 *next;
int ret;
@@ -1221,25 +1258,34 @@ int hid_open_report(struct hid_device *device)
if (WARN_ON(device->status & HID_STAT_PARSED))
return -EBUSY;
- start = device->dev_rdesc;
+ start = device->bpf_rdesc;
if (WARN_ON(!start))
return -ENODEV;
- size = device->dev_rsize;
+ size = device->bpf_rsize;
- /* call_hid_bpf_rdesc_fixup() ensures we work on a copy of rdesc */
- buf = call_hid_bpf_rdesc_fixup(device, start, &size);
- if (buf == NULL)
- return -ENOMEM;
+ if (device->driver->report_fixup) {
+ /*
+ * device->driver->report_fixup() needs to work
+ * on a copy of our report descriptor so it can
+ * change it.
+ */
+ __u8 *buf = kmemdup(start, size, GFP_KERNEL);
+
+ if (buf == NULL)
+ return -ENOMEM;
- if (device->driver->report_fixup)
start = device->driver->report_fixup(device, buf, &size);
- else
- start = buf;
- start = kmemdup(start, size, GFP_KERNEL);
- kfree(buf);
- if (start == NULL)
- return -ENOMEM;
+ /*
+ * The second kmemdup is required in case report_fixup() returns
+ * a static read-only memory, but we have no idea if that memory
+ * needs to be cleaned up or not at the end.
+ */
+ start = kmemdup(start, size, GFP_KERNEL);
+ kfree(buf);
+ if (start == NULL)
+ return -ENOMEM;
+ }
device->rdesc = start;
device->rsize = size;
@@ -1316,46 +1362,6 @@ alloc_err:
EXPORT_SYMBOL_GPL(hid_open_report);
/*
- * Convert a signed n-bit integer to signed 32-bit integer. Common
- * cases are done through the compiler, the screwed things has to be
- * done by hand.
- */
-
-static s32 snto32(__u32 value, unsigned n)
-{
- if (!value || !n)
- return 0;
-
- if (n > 32)
- n = 32;
-
- switch (n) {
- case 8: return ((__s8)value);
- case 16: return ((__s16)value);
- case 32: return ((__s32)value);
- }
- return value & (1 << (n - 1)) ? value | (~0U << n) : value;
-}
-
-s32 hid_snto32(__u32 value, unsigned n)
-{
- return snto32(value, n);
-}
-EXPORT_SYMBOL_GPL(hid_snto32);
-
-/*
- * Convert a signed 32-bit integer to a signed n-bit integer.
- */
-
-static u32 s32ton(__s32 value, unsigned n)
-{
- s32 a = value >> (n - 1);
- if (a && a != -1)
- return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
- return value & ((1 << n) - 1);
-}
-
-/*
* Extract/implement a data field from/to a little endian report (bit array).
*
* Code sort-of follows HID spec:
@@ -1875,7 +1881,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
u32 len = hid_report_len(report) + 7;
- return kmalloc(len, flags);
+ return kzalloc(len, flags);
}
EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
@@ -2674,9 +2680,10 @@ static bool hid_check_device_match(struct hid_device *hdev,
/*
* hid-generic implements .match(), so we must be dealing with a
* different HID driver here, and can simply check if
- * hid_ignore_special_drivers is set or not.
+ * hid_ignore_special_drivers or HID_QUIRK_IGNORE_SPECIAL_DRIVER
+ * are set or not.
*/
- return !hid_ignore_special_drivers;
+ return !hid_ignore_special_drivers && !(hdev->quirks & HID_QUIRK_IGNORE_SPECIAL_DRIVER);
}
static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
@@ -2684,6 +2691,18 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
const struct hid_device_id *id;
int ret;
+ if (!hdev->bpf_rsize) {
+ /* in case a bpf program gets detached, we need to free the old one */
+ hid_free_bpf_rdesc(hdev);
+
+ /* keep this around so we know we called it once */
+ hdev->bpf_rsize = hdev->dev_rsize;
+
+ /* call_hid_bpf_rdesc_fixup will always return a valid pointer */
+ hdev->bpf_rdesc = call_hid_bpf_rdesc_fixup(hdev, hdev->dev_rdesc,
+ &hdev->bpf_rsize);
+ }
+
if (!hid_check_device_match(hdev, hdrv, &id))
return -ENODEV;
@@ -2940,9 +2959,11 @@ static void hid_remove_device(struct hid_device *hdev)
hid_debug_unregister(hdev);
hdev->status &= ~HID_STAT_ADDED;
}
+ hid_free_bpf_rdesc(hdev);
kfree(hdev->dev_rdesc);
hdev->dev_rdesc = NULL;
hdev->dev_rsize = 0;
+ hdev->bpf_rsize = 0;
}
/**
diff --git a/drivers/hid/hid-corsair-void.c b/drivers/hid/hid-corsair-void.c
new file mode 100644
index 000000000000..6ece56b850fc
--- /dev/null
+++ b/drivers/hid/hid-corsair-void.c
@@ -0,0 +1,829 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HID driver for Corsair Void headsets
+ *
+ * Copyright (C) 2023-2024 Stuart Hayhurst
+ */
+
+/* -------------------------------------------------------------------------- */
+/* Receiver report information: (ID 100) */
+/* -------------------------------------------------------------------------- */
+/*
+ * When queried, the receiver reponds with 5 bytes to describe the battery
+ * The power button, mute button and moving the mic also trigger this report
+ * This includes power button + mic + connection + battery status and capacity
+ * The information below may not be perfect, it's been gathered through guesses
+ *
+ * 0: REPORT ID
+ * 100 for the battery packet
+ *
+ * 1: POWER BUTTON + (?)
+ * Largest bit is 1 when power button pressed
+ *
+ * 2: BATTERY CAPACITY + MIC STATUS
+ * Battery capacity:
+ * Seems to report ~54 higher than reality when charging
+ * Capped at 100, charging or not
+ * Microphone status:
+ * Largest bit is set to 1 when the mic is physically up
+ * No bits change when the mic is muted, only when physically moved
+ * This report is sent every time the mic is moved, no polling required
+ *
+ * 3: CONNECTION STATUS
+ * 16: Wired headset
+ * 38: Initialising
+ * 49: Lost connection
+ * 51: Disconnected, searching
+ * 52: Disconnected, not searching
+ * 177: Normal
+ *
+ * 4: BATTERY STATUS
+ * 0: Disconnected
+ * 1: Normal
+ * 2: Low
+ * 3: Critical - sent during shutdown
+ * 4: Fully charged
+ * 5: Charging
+ */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* Receiver report information: (ID 102) */
+/* -------------------------------------------------------------------------- */
+/*
+ * When queried, the recevier responds with 4 bytes to describe the firmware
+ * The first 2 bytes are for the receiver, the second 2 are the headset
+ * The headset firmware version will be 0 if no headset is connected
+ *
+ * 0: Recevier firmware major version
+ * Major version of the receiver's firmware
+ *
+ * 1: Recevier firmware minor version
+ * Minor version of the receiver's firmware
+ *
+ * 2: Headset firmware major version
+ * Major version of the headset's firmware
+ *
+ * 3: Headset firmware minor version
+ * Minor version of the headset's firmware
+ */
+/* -------------------------------------------------------------------------- */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <asm/byteorder.h>
+
+#include "hid-ids.h"
+
+#define CORSAIR_VOID_DEVICE(id, type) { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, (id)), \
+ .driver_data = (type) }
+#define CORSAIR_VOID_WIRELESS_DEVICE(id) CORSAIR_VOID_DEVICE((id), CORSAIR_VOID_WIRELESS)
+#define CORSAIR_VOID_WIRED_DEVICE(id) CORSAIR_VOID_DEVICE((id), CORSAIR_VOID_WIRED)
+
+#define CORSAIR_VOID_STATUS_REQUEST_ID 0xC9
+#define CORSAIR_VOID_NOTIF_REQUEST_ID 0xCA
+#define CORSAIR_VOID_SIDETONE_REQUEST_ID 0xFF
+#define CORSAIR_VOID_STATUS_REPORT_ID 0x64
+#define CORSAIR_VOID_FIRMWARE_REPORT_ID 0x66
+
+#define CORSAIR_VOID_USB_SIDETONE_REQUEST 0x1
+#define CORSAIR_VOID_USB_SIDETONE_REQUEST_TYPE 0x21
+#define CORSAIR_VOID_USB_SIDETONE_VALUE 0x200
+#define CORSAIR_VOID_USB_SIDETONE_INDEX 0xB00
+
+#define CORSAIR_VOID_MIC_MASK GENMASK(7, 7)
+#define CORSAIR_VOID_CAPACITY_MASK GENMASK(6, 0)
+
+#define CORSAIR_VOID_WIRELESS_CONNECTED 177
+
+#define CORSAIR_VOID_SIDETONE_MAX_WIRELESS 55
+#define CORSAIR_VOID_SIDETONE_MAX_WIRED 4096
+
+enum {
+ CORSAIR_VOID_WIRELESS,
+ CORSAIR_VOID_WIRED,
+};
+
+enum {
+ CORSAIR_VOID_BATTERY_NORMAL = 1,
+ CORSAIR_VOID_BATTERY_LOW = 2,
+ CORSAIR_VOID_BATTERY_CRITICAL = 3,
+ CORSAIR_VOID_BATTERY_CHARGED = 4,
+ CORSAIR_VOID_BATTERY_CHARGING = 5,
+};
+
+static enum power_supply_property corsair_void_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_SCOPE,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+struct corsair_void_battery_data {
+ int status;
+ bool present;
+ int capacity;
+ int capacity_level;
+};
+
+struct corsair_void_drvdata {
+ struct hid_device *hid_dev;
+ struct device *dev;
+
+ char *name;
+ bool is_wired;
+ unsigned int sidetone_max;
+
+ struct corsair_void_battery_data battery_data;
+ bool mic_up;
+ bool connected;
+ int fw_receiver_major;
+ int fw_receiver_minor;
+ int fw_headset_major;
+ int fw_headset_minor;
+
+ struct power_supply *battery;
+ struct power_supply_desc battery_desc;
+ struct mutex battery_mutex;
+
+ struct delayed_work delayed_status_work;
+ struct delayed_work delayed_firmware_work;
+ struct work_struct battery_remove_work;
+ struct work_struct battery_add_work;
+};
+
+/*
+ * Functions to process receiver data
+*/
+
+static void corsair_void_set_wireless_status(struct corsair_void_drvdata *drvdata)
+{
+ struct usb_interface *usb_if = to_usb_interface(drvdata->dev->parent);
+
+ if (drvdata->is_wired)
+ return;
+
+ usb_set_wireless_status(usb_if, drvdata->connected ?
+ USB_WIRELESS_STATUS_CONNECTED :
+ USB_WIRELESS_STATUS_DISCONNECTED);
+}
+
+static void corsair_void_set_unknown_batt(struct corsair_void_drvdata *drvdata)
+{
+ struct corsair_void_battery_data *battery_data = &drvdata->battery_data;
+
+ battery_data->status = POWER_SUPPLY_STATUS_UNKNOWN;
+ battery_data->present = false;
+ battery_data->capacity = 0;
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+}
+
+/* Reset data that may change between wireless connections */
+static void corsair_void_set_unknown_wireless_data(struct corsair_void_drvdata *drvdata)
+{
+ /* Only 0 out headset, receiver is always known if relevant */
+ drvdata->fw_headset_major = 0;
+ drvdata->fw_headset_minor = 0;
+
+ drvdata->connected = false;
+ drvdata->mic_up = false;
+
+ corsair_void_set_wireless_status(drvdata);
+}
+
+static void corsair_void_process_receiver(struct corsair_void_drvdata *drvdata,
+ int raw_battery_capacity,
+ int raw_connection_status,
+ int raw_battery_status)
+{
+ struct corsair_void_battery_data *battery_data = &drvdata->battery_data;
+ struct corsair_void_battery_data orig_battery_data;
+
+ /* Save initial battery data, to compare later */
+ orig_battery_data = *battery_data;
+
+ /* Headset not connected, or it's wired */
+ if (raw_connection_status != CORSAIR_VOID_WIRELESS_CONNECTED)
+ goto unknown_battery;
+
+ /* Battery information unavailable */
+ if (raw_battery_status == 0)
+ goto unknown_battery;
+
+ /* Battery must be connected then */
+ battery_data->present = true;
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+
+ /* Set battery status */
+ switch (raw_battery_status) {
+ case CORSAIR_VOID_BATTERY_NORMAL:
+ case CORSAIR_VOID_BATTERY_LOW:
+ case CORSAIR_VOID_BATTERY_CRITICAL:
+ battery_data->status = POWER_SUPPLY_STATUS_DISCHARGING;
+ if (raw_battery_status == CORSAIR_VOID_BATTERY_LOW)
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (raw_battery_status == CORSAIR_VOID_BATTERY_CRITICAL)
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+
+ break;
+ case CORSAIR_VOID_BATTERY_CHARGED:
+ battery_data->status = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case CORSAIR_VOID_BATTERY_CHARGING:
+ battery_data->status = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ default:
+ hid_warn(drvdata->hid_dev, "unknown battery status '%d'",
+ raw_battery_status);
+ goto unknown_battery;
+ break;
+ }
+
+ battery_data->capacity = raw_battery_capacity;
+ corsair_void_set_wireless_status(drvdata);
+
+ goto success;
+unknown_battery:
+ corsair_void_set_unknown_batt(drvdata);
+success:
+
+ /* Inform power supply if battery values changed */
+ if (memcmp(&orig_battery_data, battery_data, sizeof(*battery_data))) {
+ scoped_guard(mutex, &drvdata->battery_mutex) {
+ if (drvdata->battery) {
+ power_supply_changed(drvdata->battery);
+ }
+ }
+ }
+}
+
+/*
+ * Functions to report stored data
+*/
+
+static int corsair_void_battery_get_property(struct power_supply *psy,
+ enum power_supply_property prop,
+ union power_supply_propval *val)
+{
+ struct corsair_void_drvdata *drvdata = power_supply_get_drvdata(psy);
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ if (!strncmp(drvdata->hid_dev->name, "Corsair ", 8))
+ val->strval = drvdata->hid_dev->name + 8;
+ else
+ val->strval = drvdata->hid_dev->name;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = "Corsair";
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = drvdata->battery_data.status;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = drvdata->battery_data.present;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = drvdata->battery_data.capacity;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ val->intval = drvdata->battery_data.capacity_level;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static ssize_t microphone_up_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (!drvdata->connected)
+ return -ENODEV;
+
+ return sysfs_emit(buf, "%d\n", drvdata->mic_up);
+}
+
+static ssize_t fw_version_receiver_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata->fw_receiver_major == 0 && drvdata->fw_receiver_minor == 0)
+ return -ENODATA;
+
+ return sysfs_emit(buf, "%d.%02d\n", drvdata->fw_receiver_major,
+ drvdata->fw_receiver_minor);
+}
+
+
+static ssize_t fw_version_headset_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata->fw_headset_major == 0 && drvdata->fw_headset_minor == 0)
+ return -ENODATA;
+
+ return sysfs_emit(buf, "%d.%02d\n", drvdata->fw_headset_major,
+ drvdata->fw_headset_minor);
+}
+
+static ssize_t sidetone_max_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", drvdata->sidetone_max);
+}
+
+/*
+ * Functions to send data to headset
+*/
+
+static ssize_t send_alert_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+ struct hid_device *hid_dev = drvdata->hid_dev;
+ unsigned char alert_id;
+ unsigned char *send_buf __free(kfree) = NULL;
+ int ret;
+
+ if (!drvdata->connected || drvdata->is_wired)
+ return -ENODEV;
+
+ /* Only accept 0 or 1 for alert ID */
+ if (kstrtou8(buf, 10, &alert_id) || alert_id >= 2)
+ return -EINVAL;
+
+ send_buf = kmalloc(3, GFP_KERNEL);
+ if (!send_buf)
+ return -ENOMEM;
+
+ /* Packet format to send alert with ID alert_id */
+ send_buf[0] = CORSAIR_VOID_NOTIF_REQUEST_ID;
+ send_buf[1] = 0x02;
+ send_buf[2] = alert_id;
+
+ ret = hid_hw_raw_request(hid_dev, CORSAIR_VOID_NOTIF_REQUEST_ID,
+ send_buf, 3, HID_OUTPUT_REPORT,
+ HID_REQ_SET_REPORT);
+ if (ret < 0)
+ hid_warn(hid_dev, "failed to send alert request (reason: %d)",
+ ret);
+ else
+ ret = count;
+
+ return ret;
+}
+
+static int corsair_void_set_sidetone_wired(struct device *dev, const char *buf,
+ unsigned int sidetone)
+{
+ struct usb_interface *usb_if = to_usb_interface(dev->parent);
+ struct usb_device *usb_dev = interface_to_usbdev(usb_if);
+
+ /* Packet format to set sidetone for wired headsets */
+ __le16 sidetone_le = cpu_to_le16(sidetone);
+
+ return usb_control_msg_send(usb_dev, 0,
+ CORSAIR_VOID_USB_SIDETONE_REQUEST,
+ CORSAIR_VOID_USB_SIDETONE_REQUEST_TYPE,
+ CORSAIR_VOID_USB_SIDETONE_VALUE,
+ CORSAIR_VOID_USB_SIDETONE_INDEX,
+ &sidetone_le, 2, USB_CTRL_SET_TIMEOUT,
+ GFP_KERNEL);
+}
+
+static int corsair_void_set_sidetone_wireless(struct device *dev,
+ const char *buf,
+ unsigned char sidetone)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+ struct hid_device *hid_dev = drvdata->hid_dev;
+ unsigned char *send_buf __free(kfree) = NULL;
+
+ send_buf = kmalloc(12, GFP_KERNEL);
+ if (!send_buf)
+ return -ENOMEM;
+
+ /* Packet format to set sidetone for wireless headsets */
+ send_buf[0] = CORSAIR_VOID_SIDETONE_REQUEST_ID;
+ send_buf[1] = 0x0B;
+ send_buf[2] = 0x00;
+ send_buf[3] = 0xFF;
+ send_buf[4] = 0x04;
+ send_buf[5] = 0x0E;
+ send_buf[6] = 0xFF;
+ send_buf[7] = 0x05;
+ send_buf[8] = 0x01;
+ send_buf[9] = 0x04;
+ send_buf[10] = 0x00;
+ send_buf[11] = sidetone + 200;
+
+ return hid_hw_raw_request(hid_dev, CORSAIR_VOID_SIDETONE_REQUEST_ID,
+ send_buf, 12, HID_FEATURE_REPORT,
+ HID_REQ_SET_REPORT);
+}
+
+static ssize_t set_sidetone_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+ struct hid_device *hid_dev = drvdata->hid_dev;
+ unsigned int sidetone;
+ int ret;
+
+ if (!drvdata->connected)
+ return -ENODEV;
+
+ /* sidetone must be between 0 and drvdata->sidetone_max inclusive */
+ if (kstrtouint(buf, 10, &sidetone) || sidetone > drvdata->sidetone_max)
+ return -EINVAL;
+
+ if (drvdata->is_wired)
+ ret = corsair_void_set_sidetone_wired(dev, buf, sidetone);
+ else
+ ret = corsair_void_set_sidetone_wireless(dev, buf, sidetone);
+
+ if (ret < 0)
+ hid_warn(hid_dev, "failed to send sidetone (reason: %d)", ret);
+ else
+ ret = count;
+
+ return ret;
+}
+
+static int corsair_void_request_status(struct hid_device *hid_dev, int id)
+{
+ unsigned char *send_buf __free(kfree) = NULL;
+
+ send_buf = kmalloc(2, GFP_KERNEL);
+ if (!send_buf)
+ return -ENOMEM;
+
+ /* Packet format to request data item (status / firmware) refresh */
+ send_buf[0] = CORSAIR_VOID_STATUS_REQUEST_ID;
+ send_buf[1] = id;
+
+ /* Send request for data refresh */
+ return hid_hw_raw_request(hid_dev, CORSAIR_VOID_STATUS_REQUEST_ID,
+ send_buf, 2, HID_OUTPUT_REPORT,
+ HID_REQ_SET_REPORT);
+}
+
+/*
+ * Headset connect / disconnect handlers and work handlers
+*/
+
+static void corsair_void_status_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+ struct delayed_work *delayed_work;
+ int battery_ret;
+
+ delayed_work = container_of(work, struct delayed_work, work);
+ drvdata = container_of(delayed_work, struct corsair_void_drvdata,
+ delayed_status_work);
+
+ battery_ret = corsair_void_request_status(drvdata->hid_dev,
+ CORSAIR_VOID_STATUS_REPORT_ID);
+ if (battery_ret < 0) {
+ hid_warn(drvdata->hid_dev,
+ "failed to request battery (reason: %d)", battery_ret);
+ }
+}
+
+static void corsair_void_firmware_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+ struct delayed_work *delayed_work;
+ int firmware_ret;
+
+ delayed_work = container_of(work, struct delayed_work, work);
+ drvdata = container_of(delayed_work, struct corsair_void_drvdata,
+ delayed_firmware_work);
+
+ firmware_ret = corsair_void_request_status(drvdata->hid_dev,
+ CORSAIR_VOID_FIRMWARE_REPORT_ID);
+ if (firmware_ret < 0) {
+ hid_warn(drvdata->hid_dev,
+ "failed to request firmware (reason: %d)", firmware_ret);
+ }
+
+}
+
+static void corsair_void_battery_remove_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+
+ drvdata = container_of(work, struct corsair_void_drvdata,
+ battery_remove_work);
+ scoped_guard(mutex, &drvdata->battery_mutex) {
+ if (drvdata->battery) {
+ power_supply_unregister(drvdata->battery);
+ drvdata->battery = NULL;
+ }
+ }
+}
+
+static void corsair_void_battery_add_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+ struct power_supply_config psy_cfg;
+ struct power_supply *new_supply;
+
+ drvdata = container_of(work, struct corsair_void_drvdata,
+ battery_add_work);
+ guard(mutex)(&drvdata->battery_mutex);
+ if (drvdata->battery)
+ return;
+
+ psy_cfg.drv_data = drvdata;
+ new_supply = power_supply_register(drvdata->dev,
+ &drvdata->battery_desc,
+ &psy_cfg);
+
+ if (IS_ERR(new_supply)) {
+ hid_err(drvdata->hid_dev,
+ "failed to register battery '%s' (reason: %ld)\n",
+ drvdata->battery_desc.name,
+ PTR_ERR(new_supply));
+ return;
+ }
+
+ if (power_supply_powers(new_supply, drvdata->dev)) {
+ power_supply_unregister(new_supply);
+ return;
+ }
+
+ drvdata->battery = new_supply;
+}
+
+static void corsair_void_headset_connected(struct corsair_void_drvdata *drvdata)
+{
+ schedule_work(&drvdata->battery_add_work);
+ schedule_delayed_work(&drvdata->delayed_firmware_work,
+ msecs_to_jiffies(100));
+}
+
+static void corsair_void_headset_disconnected(struct corsair_void_drvdata *drvdata)
+{
+ schedule_work(&drvdata->battery_remove_work);
+
+ corsair_void_set_unknown_wireless_data(drvdata);
+ corsair_void_set_unknown_batt(drvdata);
+}
+
+/*
+ * Driver setup, probing and HID event handling
+*/
+
+static DEVICE_ATTR_RO(fw_version_receiver);
+static DEVICE_ATTR_RO(fw_version_headset);
+static DEVICE_ATTR_RO(microphone_up);
+static DEVICE_ATTR_RO(sidetone_max);
+
+static DEVICE_ATTR_WO(send_alert);
+static DEVICE_ATTR_WO(set_sidetone);
+
+static struct attribute *corsair_void_attrs[] = {
+ &dev_attr_fw_version_receiver.attr,
+ &dev_attr_fw_version_headset.attr,
+ &dev_attr_microphone_up.attr,
+ &dev_attr_send_alert.attr,
+ &dev_attr_set_sidetone.attr,
+ &dev_attr_sidetone_max.attr,
+ NULL,
+};
+
+static const struct attribute_group corsair_void_attr_group = {
+ .attrs = corsair_void_attrs,
+};
+
+static int corsair_void_probe(struct hid_device *hid_dev,
+ const struct hid_device_id *hid_id)
+{
+ int ret;
+ struct corsair_void_drvdata *drvdata;
+ char *name;
+
+ if (!hid_is_usb(hid_dev))
+ return -EINVAL;
+
+ drvdata = devm_kzalloc(&hid_dev->dev, sizeof(*drvdata),
+ GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ hid_set_drvdata(hid_dev, drvdata);
+ dev_set_drvdata(&hid_dev->dev, drvdata);
+
+ drvdata->dev = &hid_dev->dev;
+ drvdata->hid_dev = hid_dev;
+ drvdata->is_wired = hid_id->driver_data == CORSAIR_VOID_WIRED;
+
+ drvdata->sidetone_max = CORSAIR_VOID_SIDETONE_MAX_WIRELESS;
+ if (drvdata->is_wired)
+ drvdata->sidetone_max = CORSAIR_VOID_SIDETONE_MAX_WIRED;
+
+ /* Set initial values for no wireless headset attached */
+ /* If a headset is attached, it'll be prompted later */
+ corsair_void_set_unknown_wireless_data(drvdata);
+ corsair_void_set_unknown_batt(drvdata);
+
+ /* Receiver version won't be reset after init */
+ /* Headset version already set via set_unknown_wireless_data */
+ drvdata->fw_receiver_major = 0;
+ drvdata->fw_receiver_minor = 0;
+
+ ret = hid_parse(hid_dev);
+ if (ret) {
+ hid_err(hid_dev, "parse failed (reason: %d)\n", ret);
+ return ret;
+ }
+
+ name = devm_kasprintf(drvdata->dev, GFP_KERNEL,
+ "corsair-void-%d-battery", hid_dev->id);
+ if (!name)
+ return -ENOMEM;
+
+ drvdata->battery_desc.name = name;
+ drvdata->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ drvdata->battery_desc.properties = corsair_void_battery_props;
+ drvdata->battery_desc.num_properties = ARRAY_SIZE(corsair_void_battery_props);
+ drvdata->battery_desc.get_property = corsair_void_battery_get_property;
+
+ drvdata->battery = NULL;
+ INIT_WORK(&drvdata->battery_remove_work,
+ corsair_void_battery_remove_work_handler);
+ INIT_WORK(&drvdata->battery_add_work,
+ corsair_void_battery_add_work_handler);
+ ret = devm_mutex_init(drvdata->dev, &drvdata->battery_mutex);
+ if (ret)
+ return ret;
+
+ ret = sysfs_create_group(&hid_dev->dev.kobj, &corsair_void_attr_group);
+ if (ret)
+ return ret;
+
+ /* Any failures after here will need to call hid_hw_stop */
+ ret = hid_hw_start(hid_dev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ hid_err(hid_dev, "hid_hw_start failed (reason: %d)\n", ret);
+ goto failed_after_sysfs;
+ }
+
+ /* Refresh battery data, in case wireless headset is already connected */
+ INIT_DELAYED_WORK(&drvdata->delayed_status_work,
+ corsair_void_status_work_handler);
+ schedule_delayed_work(&drvdata->delayed_status_work,
+ msecs_to_jiffies(100));
+
+ /* Refresh firmware versions */
+ INIT_DELAYED_WORK(&drvdata->delayed_firmware_work,
+ corsair_void_firmware_work_handler);
+ schedule_delayed_work(&drvdata->delayed_firmware_work,
+ msecs_to_jiffies(100));
+
+ return 0;
+
+failed_after_sysfs:
+ sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group);
+ return ret;
+}
+
+static void corsair_void_remove(struct hid_device *hid_dev)
+{
+ struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev);
+
+ hid_hw_stop(hid_dev);
+ cancel_work_sync(&drvdata->battery_remove_work);
+ cancel_work_sync(&drvdata->battery_add_work);
+ if (drvdata->battery)
+ power_supply_unregister(drvdata->battery);
+
+ cancel_delayed_work_sync(&drvdata->delayed_firmware_work);
+ sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group);
+}
+
+static int corsair_void_raw_event(struct hid_device *hid_dev,
+ struct hid_report *hid_report,
+ u8 *data, int size)
+{
+ struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev);
+ bool was_connected = drvdata->connected;
+
+ /* Description of packets are documented at the top of this file */
+ if (hid_report->id == CORSAIR_VOID_STATUS_REPORT_ID) {
+ drvdata->mic_up = FIELD_GET(CORSAIR_VOID_MIC_MASK, data[2]);
+ drvdata->connected = (data[3] == CORSAIR_VOID_WIRELESS_CONNECTED) ||
+ drvdata->is_wired;
+
+ corsair_void_process_receiver(drvdata,
+ FIELD_GET(CORSAIR_VOID_CAPACITY_MASK, data[2]),
+ data[3], data[4]);
+ } else if (hid_report->id == CORSAIR_VOID_FIRMWARE_REPORT_ID) {
+ drvdata->fw_receiver_major = data[1];
+ drvdata->fw_receiver_minor = data[2];
+ drvdata->fw_headset_major = data[3];
+ drvdata->fw_headset_minor = data[4];
+ }
+
+ /* Handle wireless headset connect / disconnect */
+ if ((was_connected != drvdata->connected) && !drvdata->is_wired) {
+ if (drvdata->connected)
+ corsair_void_headset_connected(drvdata);
+ else
+ corsair_void_headset_disconnected(drvdata);
+ }
+
+ return 0;
+}
+
+static const struct hid_device_id corsair_void_devices[] = {
+ /* Corsair Void Wireless */
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a0c),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a2b),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x1b23),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x1b25),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x1b27),
+
+ /* Corsair Void USB */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a0f),
+ CORSAIR_VOID_WIRED_DEVICE(0x1b1c),
+ CORSAIR_VOID_WIRED_DEVICE(0x1b29),
+ CORSAIR_VOID_WIRED_DEVICE(0x1b2a),
+
+ /* Corsair Void Surround */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a30),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a31),
+
+ /* Corsair Void Pro Wireless */
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a14),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a16),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a1a),
+
+ /* Corsair Void Pro USB */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a17),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a1d),
+
+ /* Corsair Void Pro Surround */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a18),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a1e),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a1f),
+
+ /* Corsair Void Elite Wireless */
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a51),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a55),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a75),
+
+ /* Corsair Void Elite USB */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a52),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a56),
+
+ /* Corsair Void Elite Surround */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a53),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a57),
+
+ {}
+};
+
+MODULE_DEVICE_TABLE(hid, corsair_void_devices);
+
+static struct hid_driver corsair_void_driver = {
+ .name = "hid-corsair-void",
+ .id_table = corsair_void_devices,
+ .probe = corsair_void_probe,
+ .remove = corsair_void_remove,
+ .raw_event = corsair_void_raw_event,
+};
+
+module_hid_driver(corsair_void_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stuart Hayhurst <stuart.a.hayhurst@gmail.com>");
+MODULE_DESCRIPTION("HID driver for Corsair Void headsets");
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index dae2b84a1490..f4c8d981aa0a 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -852,7 +852,8 @@ static int cp2112_set_usb_config(struct hid_device *hdev,
{
int ret;
- BUG_ON(cfg->report != CP2112_USB_CONFIG);
+ if (WARN_ON(cfg->report != CP2112_USB_CONFIG))
+ return -EINVAL;
ret = cp2112_hid_output(hdev, (u8 *)cfg, sizeof(*cfg),
HID_FEATURE_REPORT);
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index d5abfe652fb5..541d682af15a 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -3309,9 +3309,9 @@ static const char *keys[KEY_MAX + 1] = {
[KEY_EPG] = "EPG", [KEY_PVR] = "PVR",
[KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language",
[KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle",
- [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom",
+ [KEY_ANGLE] = "Angle",
[KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard",
- [KEY_SCREEN] = "Screen", [KEY_PC] = "PC",
+ [KEY_PC] = "PC",
[KEY_TV] = "TV", [KEY_TV2] = "TV2",
[KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2",
[KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2",
@@ -3409,8 +3409,7 @@ static const char *keys[KEY_MAX + 1] = {
[BTN_TRIGGER_HAPPY35] = "TriggerHappy35", [BTN_TRIGGER_HAPPY36] = "TriggerHappy36",
[BTN_TRIGGER_HAPPY37] = "TriggerHappy37", [BTN_TRIGGER_HAPPY38] = "TriggerHappy38",
[BTN_TRIGGER_HAPPY39] = "TriggerHappy39", [BTN_TRIGGER_HAPPY40] = "TriggerHappy40",
- [BTN_DIGI] = "Digi", [BTN_STYLUS3] = "Stylus3",
- [BTN_TOOL_QUINTTAP] = "ToolQuintTap", [BTN_WHEEL] = "Wheel",
+ [BTN_STYLUS3] = "Stylus3", [BTN_TOOL_QUINTTAP] = "ToolQuintTap",
[KEY_10CHANNELSDOWN] = "10ChannelsDown",
[KEY_10CHANNELSUP] = "10ChannelsUp",
[KEY_3D_MODE] = "3DMode", [KEY_ADDRESSBOOK] = "Addressbook",
@@ -3440,7 +3439,7 @@ static const char *keys[KEY_MAX + 1] = {
[KEY_FN_RIGHT_SHIFT] = "FnRightShift", [KEY_FRAMEBACK] = "FrameBack",
[KEY_FRAMEFORWARD] = "FrameForward", [KEY_FULL_SCREEN] = "FullScreen",
[KEY_GAMES] = "Games", [KEY_GRAPHICSEDITOR] = "GraphicsEditor",
- [KEY_HANGEUL] = "HanGeul", [KEY_HANGUP_PHONE] = "HangUpPhone",
+ [KEY_HANGUP_PHONE] = "HangUpPhone",
[KEY_IMAGES] = "Images", [KEY_KBD_LCD_MENU1] = "KbdLcdMenu1",
[KEY_KBD_LCD_MENU2] = "KbdLcdMenu2", [KEY_KBD_LCD_MENU3] = "KbdLcdMenu3",
[KEY_KBD_LCD_MENU4] = "KbdLcdMenu4", [KEY_KBD_LCD_MENU5] = "KbdLcdMenu5",
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c
index d2439399fb35..9e04c6d0fcc8 100644
--- a/drivers/hid/hid-generic.c
+++ b/drivers/hid/hid-generic.c
@@ -40,6 +40,9 @@ static bool hid_generic_match(struct hid_device *hdev,
if (ignore_special_driver)
return true;
+ if (hdev->quirks & HID_QUIRK_IGNORE_SPECIAL_DRIVER)
+ return true;
+
if (hdev->quirks & HID_QUIRK_HAVE_SPECIAL_DRIVER)
return false;
diff --git a/drivers/hid/hid-goodix-spi.c b/drivers/hid/hid-goodix-spi.c
index 0f87bf9c67cf..80c0288a3a38 100644
--- a/drivers/hid/hid-goodix-spi.c
+++ b/drivers/hid/hid-goodix-spi.c
@@ -19,6 +19,8 @@
#define GOODIX_HID_DESC_ADDR 0x1058C
#define GOODIX_HID_REPORT_DESC_ADDR 0x105AA
#define GOODIX_HID_SIGN_ADDR 0x10D32
+#define GOODIX_HID_CMD_ADDR 0x10364
+#define GOODIX_HID_REPORT_ADDR 0x22C8C
#define GOODIX_HID_GET_REPORT_CMD 0x02
#define GOODIX_HID_SET_REPORT_CMD 0x03
@@ -348,7 +350,7 @@ static int goodix_hid_check_ack_status(struct goodix_ts_data *ts, u32 *resp_len)
* - byte 0: Ack flag, value of 1 for data ready
* - bytes 1-2: Response data length
*/
- error = goodix_spi_read(ts, ts->hid_report_addr,
+ error = goodix_spi_read(ts, GOODIX_HID_CMD_ADDR,
&hdr, sizeof(hdr));
if (!error && (hdr.flag & GOODIX_HID_ACK_READY_FLAG)) {
len = le16_to_cpu(hdr.size);
@@ -356,7 +358,7 @@ static int goodix_hid_check_ack_status(struct goodix_ts_data *ts, u32 *resp_len)
dev_err(ts->dev, "hrd.size too short: %d", len);
return -EINVAL;
}
- *resp_len = len;
+ *resp_len = len - GOODIX_HID_PKG_LEN_SIZE;
return 0;
}
@@ -431,7 +433,7 @@ static int goodix_hid_get_raw_report(struct hid_device *hid,
tx_len += args_len;
/* Step1: write report request info */
- error = goodix_spi_write(ts, ts->hid_report_addr, tmp_buf, tx_len);
+ error = goodix_spi_write(ts, GOODIX_HID_CMD_ADDR, tmp_buf, tx_len);
if (error) {
dev_err(ts->dev, "failed send read feature cmd, %d", error);
return error;
@@ -446,9 +448,12 @@ static int goodix_hid_get_raw_report(struct hid_device *hid,
if (error)
return error;
- len = min(len, response_data_len - GOODIX_HID_PKG_LEN_SIZE);
+ /* Empty reprot response */
+ if (!response_data_len)
+ return 0;
+ len = min(len, response_data_len);
/* Step3: read response data(skip 2bytes of hid pkg length) */
- error = goodix_spi_read(ts, ts->hid_report_addr +
+ error = goodix_spi_read(ts, GOODIX_HID_CMD_ADDR +
GOODIX_HID_ACK_HEADER_SIZE +
GOODIX_HID_PKG_LEN_SIZE, buf, len);
if (error) {
@@ -518,7 +523,7 @@ static int goodix_hid_set_raw_report(struct hid_device *hid,
memcpy(tmp_buf + tx_len, buf, len);
tx_len += len;
- error = goodix_spi_write(ts, ts->hid_report_addr, tmp_buf, tx_len);
+ error = goodix_spi_write(ts, GOODIX_HID_CMD_ADDR, tmp_buf, tx_len);
if (error) {
dev_err(ts->dev, "failed send report: %*ph", tx_len, tmp_buf);
return error;
@@ -697,12 +702,7 @@ static int goodix_spi_probe(struct spi_device *spi)
return dev_err_probe(dev, PTR_ERR(ts->reset_gpio),
"failed to request reset gpio\n");
- error = device_property_read_u32(dev, "goodix,hid-report-addr",
- &ts->hid_report_addr);
- if (error)
- return dev_err_probe(dev, error,
- "failed get hid report addr\n");
-
+ ts->hid_report_addr = GOODIX_HID_REPORT_ADDR;
error = goodix_dev_confirm(ts);
if (error)
return error;
@@ -749,7 +749,7 @@ static int goodix_spi_set_power(struct goodix_ts_data *ts, int power_state)
power_control_cmd[5] = power_state;
guard(mutex)(&ts->hid_request_lock);
- error = goodix_spi_write(ts, ts->hid_report_addr, power_control_cmd,
+ error = goodix_spi_write(ts, GOODIX_HID_CMD_ADDR, power_control_cmd,
sizeof(power_control_cmd));
if (error) {
dev_err(ts->dev, "failed set power mode: %s",
@@ -786,6 +786,14 @@ static const struct acpi_device_id goodix_spi_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, goodix_spi_acpi_match);
#endif
+#ifdef CONFIG_OF
+static const struct of_device_id goodix_spi_of_match[] = {
+ { .compatible = "goodix,gt7986u-spifw", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, goodix_spi_of_match);
+#endif
+
static const struct spi_device_id goodix_spi_ids[] = {
{ "gt7986u" },
{ },
@@ -796,6 +804,7 @@ static struct spi_driver goodix_spi_driver = {
.driver = {
.name = "goodix-spi-hid",
.acpi_match_table = ACPI_PTR(goodix_spi_acpi_match),
+ .of_match_table = of_match_ptr(goodix_spi_of_match),
.pm = pm_sleep_ptr(&goodix_spi_pm_ops),
},
.probe = goodix_spi_probe,
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index f33485d83d24..0fb210e40a41 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -422,6 +422,25 @@ static int mousevsc_hid_raw_request(struct hid_device *hid,
return 0;
}
+static int mousevsc_hid_probe(struct hid_device *hid_dev, const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hid_dev);
+ if (ret) {
+ hid_err(hid_dev, "parse failed\n");
+ return ret;
+ }
+
+ ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
+ if (ret) {
+ hid_err(hid_dev, "hw start failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct hid_ll_driver mousevsc_ll_driver = {
.parse = mousevsc_hid_parse,
.open = mousevsc_hid_open,
@@ -431,7 +450,16 @@ static const struct hid_ll_driver mousevsc_ll_driver = {
.raw_request = mousevsc_hid_raw_request,
};
-static struct hid_driver mousevsc_hid_driver;
+static const struct hid_device_id mousevsc_devices[] = {
+ { HID_DEVICE(BUS_VIRTUAL, HID_GROUP_ANY, 0x045E, 0x0621) },
+ { }
+};
+
+static struct hid_driver mousevsc_hid_driver = {
+ .name = "hid-hyperv",
+ .id_table = mousevsc_devices,
+ .probe = mousevsc_hid_probe,
+};
static int mousevsc_probe(struct hv_device *device,
const struct hv_vmbus_device_id *dev_id)
@@ -473,7 +501,6 @@ static int mousevsc_probe(struct hv_device *device,
}
hid_dev->ll_driver = &mousevsc_ll_driver;
- hid_dev->driver = &mousevsc_hid_driver;
hid_dev->bus = BUS_VIRTUAL;
hid_dev->vendor = input_dev->hid_dev_info.vendor;
hid_dev->product = input_dev->hid_dev_info.product;
@@ -488,20 +515,6 @@ static int mousevsc_probe(struct hv_device *device,
if (ret)
goto probe_err2;
-
- ret = hid_parse(hid_dev);
- if (ret) {
- hid_err(hid_dev, "parse failed\n");
- goto probe_err2;
- }
-
- ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
-
- if (ret) {
- hid_err(hid_dev, "hw start failed\n");
- goto probe_err2;
- }
-
device_init_wakeup(&device->device, true);
input_dev->connected = true;
@@ -579,12 +592,23 @@ static struct hv_driver mousevsc_drv = {
static int __init mousevsc_init(void)
{
- return vmbus_driver_register(&mousevsc_drv);
+ int ret;
+
+ ret = hid_register_driver(&mousevsc_hid_driver);
+ if (ret)
+ return ret;
+
+ ret = vmbus_driver_register(&mousevsc_drv);
+ if (ret)
+ hid_unregister_driver(&mousevsc_hid_driver);
+
+ return ret;
}
static void __exit mousevsc_exit(void)
{
vmbus_driver_unregister(&mousevsc_drv);
+ hid_unregister_driver(&mousevsc_hid_driver);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 92cff3f2658c..1f47fda809b9 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -94,6 +94,7 @@
#define USB_DEVICE_ID_APPLE_MAGICMOUSE2 0x0269
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265
+#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC 0x0324
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214
@@ -735,6 +736,10 @@
#define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2 0x501A
#define USB_DEVICE_ID_KYE_PENSKETCH_T609A 0x501B
+#define USB_VENDOR_ID_KYSONA 0x3554
+#define USB_DEVICE_ID_KYSONA_M600_DONGLE 0xF57C
+#define USB_DEVICE_ID_KYSONA_M600_WIRED 0xF57D
+
#define USB_VENDOR_ID_LABTEC 0x1020
#define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
#define USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE 0x8888
diff --git a/drivers/hid/hid-kysona.c b/drivers/hid/hid-kysona.c
new file mode 100644
index 000000000000..d4c0406b3323
--- /dev/null
+++ b/drivers/hid/hid-kysona.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * USB HID driver for Kysona
+ * Kysona M600 mice.
+ *
+ * Copyright (c) 2024 Lode Willems <me@lodewillems.com>
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#define BATTERY_TIMEOUT_MS 5000
+
+#define BATTERY_REPORT_ID 4
+
+struct kysona_drvdata {
+ struct hid_device *hdev;
+ bool online;
+
+ struct power_supply_desc battery_desc;
+ struct power_supply *battery;
+ u8 battery_capacity;
+ bool battery_charging;
+ u16 battery_voltage;
+ struct delayed_work battery_work;
+};
+
+static enum power_supply_property kysona_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_SCOPE,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_ONLINE
+};
+
+static int kysona_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct kysona_drvdata *drv_data = power_supply_get_drvdata(psy);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = drv_data->online;
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ if (drv_data->online)
+ val->intval = drv_data->battery_charging ?
+ POWER_SUPPLY_STATUS_CHARGING :
+ POWER_SUPPLY_STATUS_DISCHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ break;
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = drv_data->battery_capacity;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ /* hardware reports voltage in mV. sysfs expects uV */
+ val->intval = drv_data->battery_voltage * 1000;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = drv_data->hdev->name;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static const char kysona_battery_request[] = {
+ 0x08, BATTERY_REPORT_ID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49
+};
+
+static int kysona_m600_fetch_battery(struct hid_device *hdev)
+{
+ u8 *write_buf;
+ int ret;
+
+ /* Request battery information */
+ write_buf = kmemdup(kysona_battery_request, sizeof(kysona_battery_request), GFP_KERNEL);
+ if (!write_buf)
+ return -ENOMEM;
+
+ ret = hid_hw_raw_request(hdev, kysona_battery_request[0],
+ write_buf, sizeof(kysona_battery_request),
+ HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+ if (ret < (int)sizeof(kysona_battery_request)) {
+ hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret);
+ ret = -ENODATA;
+ }
+ kfree(write_buf);
+ return ret;
+}
+
+static void kysona_fetch_battery(struct hid_device *hdev)
+{
+ int ret = kysona_m600_fetch_battery(hdev);
+
+ if (ret < 0)
+ hid_dbg(hdev,
+ "Battery query failed (err: %d)\n", ret);
+}
+
+static void kysona_battery_timer_tick(struct work_struct *work)
+{
+ struct kysona_drvdata *drv_data = container_of(work,
+ struct kysona_drvdata, battery_work.work);
+ struct hid_device *hdev = drv_data->hdev;
+
+ kysona_fetch_battery(hdev);
+ schedule_delayed_work(&drv_data->battery_work,
+ msecs_to_jiffies(BATTERY_TIMEOUT_MS));
+}
+
+static int kysona_battery_probe(struct hid_device *hdev)
+{
+ struct kysona_drvdata *drv_data = hid_get_drvdata(hdev);
+ struct power_supply_config pscfg = { .drv_data = drv_data };
+ int ret = 0;
+
+ drv_data->online = false;
+ drv_data->battery_capacity = 100;
+ drv_data->battery_voltage = 4200;
+
+ drv_data->battery_desc.properties = kysona_battery_props;
+ drv_data->battery_desc.num_properties = ARRAY_SIZE(kysona_battery_props);
+ drv_data->battery_desc.get_property = kysona_battery_get_property;
+ drv_data->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ drv_data->battery_desc.use_for_apm = 0;
+ drv_data->battery_desc.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
+ "kysona-%s-battery",
+ strlen(hdev->uniq) ?
+ hdev->uniq : dev_name(&hdev->dev));
+ if (!drv_data->battery_desc.name)
+ return -ENOMEM;
+
+ drv_data->battery = devm_power_supply_register(&hdev->dev,
+ &drv_data->battery_desc, &pscfg);
+ if (IS_ERR(drv_data->battery)) {
+ ret = PTR_ERR(drv_data->battery);
+ drv_data->battery = NULL;
+ hid_err(hdev, "Unable to register battery device\n");
+ return ret;
+ }
+
+ power_supply_powers(drv_data->battery, &hdev->dev);
+
+ INIT_DELAYED_WORK(&drv_data->battery_work, kysona_battery_timer_tick);
+ kysona_fetch_battery(hdev);
+ schedule_delayed_work(&drv_data->battery_work,
+ msecs_to_jiffies(BATTERY_TIMEOUT_MS));
+
+ return ret;
+}
+
+static int kysona_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+ struct kysona_drvdata *drv_data;
+ struct usb_interface *usbif;
+
+ if (!hid_is_usb(hdev))
+ return -EINVAL;
+
+ usbif = to_usb_interface(hdev->dev.parent);
+
+ drv_data = devm_kzalloc(&hdev->dev, sizeof(*drv_data), GFP_KERNEL);
+ if (!drv_data)
+ return -ENOMEM;
+
+ hid_set_drvdata(hdev, drv_data);
+ drv_data->hdev = hdev;
+
+ ret = hid_parse(hdev);
+ if (ret)
+ return ret;
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret)
+ return ret;
+
+ if (usbif->cur_altsetting->desc.bInterfaceNumber == 1) {
+ if (kysona_battery_probe(hdev) < 0)
+ hid_err(hdev, "Kysona hid battery_probe failed: %d\n", ret);
+ }
+
+ return 0;
+}
+
+static int kysona_raw_event(struct hid_device *hdev,
+ struct hid_report *report, u8 *data, int size)
+{
+ struct kysona_drvdata *drv_data = hid_get_drvdata(hdev);
+
+ if (drv_data->battery && size == sizeof(kysona_battery_request) &&
+ data[0] == 8 && data[1] == BATTERY_REPORT_ID) {
+ drv_data->battery_capacity = data[6];
+ drv_data->battery_charging = data[7];
+ drv_data->battery_voltage = (data[8] << 8) | data[9];
+ drv_data->online = true;
+ }
+
+ return 0;
+}
+
+static void kysona_remove(struct hid_device *hdev)
+{
+ struct kysona_drvdata *drv_data = hid_get_drvdata(hdev);
+
+ if (drv_data->battery)
+ cancel_delayed_work_sync(&drv_data->battery_work);
+
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id kysona_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYSONA, USB_DEVICE_ID_KYSONA_M600_DONGLE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYSONA, USB_DEVICE_ID_KYSONA_M600_WIRED) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, kysona_devices);
+
+static struct hid_driver kysona_driver = {
+ .name = "kysona",
+ .id_table = kysona_devices,
+ .probe = kysona_probe,
+ .raw_event = kysona_raw_event,
+ .remove = kysona_remove
+};
+module_hid_driver(kysona_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HID driver for Kysona devices");
+MODULE_AUTHOR("Lode Willems <me@lodewillems.com>");
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index e3fcf1353fb3..c0a138f21ca4 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -1350,7 +1350,8 @@ int lg4ff_init(struct hid_device *hid)
/* Initialize device properties */
if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
- BUG_ON(mmode_idx == -1);
+ if (WARN_ON(mmode_idx == -1))
+ return -EINVAL;
mmode_wheel = &lg4ff_multimode_wheels[mmode_idx];
}
lg4ff_init_wheel_data(&entry->wdata, &lg4ff_devices[i], mmode_wheel, real_product_id);
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index cf7a6986cf20..10a3bc5f931b 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -928,7 +928,7 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp)
#define CMD_ROOT_GET_PROTOCOL_VERSION 0x10
static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature,
- u8 *feature_index, u8 *feature_type)
+ u8 *feature_index)
{
struct hidpp_report response;
int ret;
@@ -945,7 +945,6 @@ static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature,
return -ENOENT;
*feature_index = response.fap.params[0];
- *feature_type = response.fap.params[1];
return ret;
}
@@ -1012,13 +1011,11 @@ print_version:
static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial)
{
struct hidpp_report response;
- u8 feature_type;
u8 feature_index;
int ret;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_DEVICE_INFORMATION,
- &feature_index,
- &feature_type);
+ &feature_index);
if (ret)
return ret;
@@ -1125,7 +1122,6 @@ static int hidpp_devicenametype_get_device_name(struct hidpp_device *hidpp,
static char *hidpp_get_device_name(struct hidpp_device *hidpp)
{
- u8 feature_type;
u8 feature_index;
u8 __name_length;
char *name;
@@ -1133,7 +1129,7 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp)
int ret;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_GET_DEVICE_NAME_TYPE,
- &feature_index, &feature_type);
+ &feature_index);
if (ret)
return NULL;
@@ -1300,15 +1296,13 @@ static int hidpp20_batterylevel_get_battery_info(struct hidpp_device *hidpp,
static int hidpp20_query_battery_info_1000(struct hidpp_device *hidpp)
{
- u8 feature_type;
int ret;
int status, capacity, next_capacity, level;
if (hidpp->battery.feature_index == 0xff) {
ret = hidpp_root_get_feature(hidpp,
HIDPP_PAGE_BATTERY_LEVEL_STATUS,
- &hidpp->battery.feature_index,
- &feature_type);
+ &hidpp->battery.feature_index);
if (ret)
return ret;
}
@@ -1489,14 +1483,12 @@ static int hidpp20_map_battery_capacity(struct hid_device *hid_dev, int voltage)
static int hidpp20_query_battery_voltage_info(struct hidpp_device *hidpp)
{
- u8 feature_type;
int ret;
int status, voltage, level, charge_type;
if (hidpp->battery.voltage_feature_index == 0xff) {
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_BATTERY_VOLTAGE,
- &hidpp->battery.voltage_feature_index,
- &feature_type);
+ &hidpp->battery.voltage_feature_index);
if (ret)
return ret;
}
@@ -1692,7 +1684,6 @@ static int hidpp20_unifiedbattery_get_status(struct hidpp_device *hidpp,
static int hidpp20_query_battery_info_1004(struct hidpp_device *hidpp)
{
- u8 feature_type;
int ret;
u8 state_of_charge;
int status, level;
@@ -1700,8 +1691,7 @@ static int hidpp20_query_battery_info_1004(struct hidpp_device *hidpp)
if (hidpp->battery.feature_index == 0xff) {
ret = hidpp_root_get_feature(hidpp,
HIDPP_PAGE_UNIFIED_BATTERY,
- &hidpp->battery.feature_index,
- &feature_type);
+ &hidpp->battery.feature_index);
if (ret)
return ret;
}
@@ -1834,14 +1824,9 @@ static int hidpp_battery_get_property(struct power_supply *psy,
static int hidpp_get_wireless_feature_index(struct hidpp_device *hidpp, u8 *feature_index)
{
- u8 feature_type;
- int ret;
-
- ret = hidpp_root_get_feature(hidpp,
- HIDPP_PAGE_WIRELESS_DEVICE_STATUS,
- feature_index, &feature_type);
-
- return ret;
+ return hidpp_root_get_feature(hidpp,
+ HIDPP_PAGE_WIRELESS_DEVICE_STATUS,
+ feature_index);
}
/* -------------------------------------------------------------------------- */
@@ -1952,14 +1937,11 @@ static bool hidpp20_get_adc_measurement_1f20(struct hidpp_device *hidpp,
static int hidpp20_query_adc_measurement_info_1f20(struct hidpp_device *hidpp)
{
- u8 feature_type;
-
if (hidpp->battery.adc_measurement_feature_index == 0xff) {
int ret;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_ADC_MEASUREMENT,
- &hidpp->battery.adc_measurement_feature_index,
- &feature_type);
+ &hidpp->battery.adc_measurement_feature_index);
if (ret)
return ret;
@@ -2014,15 +1996,13 @@ static int hidpp_hrs_set_highres_scrolling_mode(struct hidpp_device *hidpp,
bool enabled, u8 *multiplier)
{
u8 feature_index;
- u8 feature_type;
int ret;
u8 params[1];
struct hidpp_report response;
ret = hidpp_root_get_feature(hidpp,
HIDPP_PAGE_HI_RESOLUTION_SCROLLING,
- &feature_index,
- &feature_type);
+ &feature_index);
if (ret)
return ret;
@@ -2049,12 +2029,11 @@ static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp,
u8 *multiplier)
{
u8 feature_index;
- u8 feature_type;
int ret;
struct hidpp_report response;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
- &feature_index, &feature_type);
+ &feature_index);
if (ret)
goto return_default;
@@ -2076,13 +2055,12 @@ static int hidpp_hrw_set_wheel_mode(struct hidpp_device *hidpp, bool invert,
bool high_resolution, bool use_hidpp)
{
u8 feature_index;
- u8 feature_type;
int ret;
u8 params[1];
struct hidpp_report response;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
- &feature_index, &feature_type);
+ &feature_index);
if (ret)
return ret;
@@ -2111,14 +2089,12 @@ static int hidpp_solar_request_battery_event(struct hidpp_device *hidpp)
{
struct hidpp_report response;
u8 params[2] = { 1, 1 };
- u8 feature_type;
int ret;
if (hidpp->battery.feature_index == 0xff) {
ret = hidpp_root_get_feature(hidpp,
HIDPP_PAGE_SOLAR_KEYBOARD,
- &hidpp->battery.solar_feature_index,
- &feature_type);
+ &hidpp->battery.solar_feature_index);
if (ret)
return ret;
}
@@ -2522,7 +2498,7 @@ static void hidpp_ff_work_handler(struct work_struct *w)
/* regular effect destroyed */
data->effect_ids[wd->params[0]-1] = -1;
else if (wd->effect_id >= HIDPP_FF_EFFECTID_AUTOCENTER)
- /* autocenter spring destoyed */
+ /* autocenter spring destroyed */
data->slot_autocenter = 0;
break;
case HIDPP_FF_SET_GLOBAL_GAINS:
@@ -3098,11 +3074,10 @@ static int wtp_get_config(struct hidpp_device *hidpp)
{
struct wtp_data *wd = hidpp->private_data;
struct hidpp_touchpad_raw_info raw_info = {0};
- u8 feature_type;
int ret;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_TOUCHPAD_RAW_XY,
- &wd->mt_feature_index, &feature_type);
+ &wd->mt_feature_index);
if (ret)
/* means that the device is not powered up */
return ret;
@@ -3296,13 +3271,13 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size)
120);
}
- v = hid_snto32(hid_field_extract(hdev, data+3, 0, 12), 12);
+ v = sign_extend32(hid_field_extract(hdev, data + 3, 0, 12), 11);
input_report_rel(hidpp->input, REL_X, v);
- v = hid_snto32(hid_field_extract(hdev, data+3, 12, 12), 12);
+ v = sign_extend32(hid_field_extract(hdev, data + 3, 12, 12), 11);
input_report_rel(hidpp->input, REL_Y, v);
- v = hid_snto32(data[6], 8);
+ v = sign_extend32(data[6], 7);
if (v != 0)
hidpp_scroll_counter_handle_scroll(hidpp->input,
&hidpp->vertical_wheel_counter, v);
@@ -3362,12 +3337,11 @@ static int k400_disable_tap_to_click(struct hidpp_device *hidpp)
struct k400_private_data *k400 = hidpp->private_data;
struct hidpp_touchpad_fw_items items = {};
int ret;
- u8 feature_type;
if (!k400->feature_index) {
ret = hidpp_root_get_feature(hidpp,
HIDPP_PAGE_TOUCHPAD_FW_ITEMS,
- &k400->feature_index, &feature_type);
+ &k400->feature_index);
if (ret)
/* means that the device is not powered up */
return ret;
@@ -3439,14 +3413,13 @@ static int g920_get_config(struct hidpp_device *hidpp,
struct hidpp_ff_private_data *data)
{
struct hidpp_report response;
- u8 feature_type;
int ret;
memset(data, 0, sizeof(*data));
/* Find feature and store for later use */
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
- &data->feature_index, &feature_type);
+ &data->feature_index);
if (ret)
return ret;
@@ -3735,17 +3708,16 @@ static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp)
if (hidpp->protocol_major >= 2) {
u8 feature_index;
- u8 feature_type;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
- &feature_index, &feature_type);
+ &feature_index);
if (!ret) {
hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL;
hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scroll wheel\n");
return 0;
}
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HI_RESOLUTION_SCROLLING,
- &feature_index, &feature_type);
+ &feature_index);
if (!ret) {
hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL;
hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scrolling\n");
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 8a73b59e0827..ec110dea8772 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -227,7 +227,9 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
touch_minor = tdata[4];
state = tdata[7] & TOUCH_STATE_MASK;
down = state != TOUCH_STATE_NONE;
- } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ input->id.product ==
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
id = tdata[8] & 0xf;
x = (tdata[1] << 27 | tdata[0] << 19) >> 19;
y = -((tdata[3] << 30 | tdata[2] << 22 | tdata[1] << 14) >> 19);
@@ -259,8 +261,9 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
/* If requested, emulate a scroll wheel by detecting small
* vertical touch motions.
*/
- if (emulate_scroll_wheel && (input->id.product !=
- USB_DEVICE_ID_APPLE_MAGICTRACKPAD2)) {
+ if (emulate_scroll_wheel &&
+ input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
+ input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
unsigned long now = jiffies;
int step_x = msc->touches[id].scroll_x - x;
int step_y = msc->touches[id].scroll_y - y;
@@ -359,7 +362,9 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2)
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ input->id.product ==
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC)
input_report_abs(input, ABS_MT_PRESSURE, pressure);
if (report_undeciphered) {
@@ -367,7 +372,9 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2)
input_event(input, EV_MSC, MSC_RAW, tdata[7]);
else if (input->id.product !=
- USB_DEVICE_ID_APPLE_MAGICTRACKPAD2)
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
+ input->id.product !=
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC)
input_event(input, EV_MSC, MSC_RAW, tdata[8]);
}
}
@@ -493,7 +500,9 @@ static int magicmouse_raw_event(struct hid_device *hdev,
magicmouse_emit_buttons(msc, clicks & 3);
input_report_rel(input, REL_X, x);
input_report_rel(input, REL_Y, y);
- } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ input->id.product ==
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
input_mt_sync_frame(input);
input_report_key(input, BTN_MOUSE, clicks & 1);
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
@@ -545,7 +554,9 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
__set_bit(REL_WHEEL_HI_RES, input->relbit);
__set_bit(REL_HWHEEL_HI_RES, input->relbit);
}
- } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ input->id.product ==
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
/* If the trackpad has been connected to a Mac, the name is
* automatically personalized, e.g., "José Expósito's Trackpad".
* When connected through Bluetooth, the personalized name is
@@ -621,7 +632,9 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
MOUSE_RES_X);
input_abs_set_res(input, ABS_MT_POSITION_Y,
MOUSE_RES_Y);
- } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ input->id.product ==
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 253, 0, 0);
input_set_abs_params(input, ABS_PRESSURE, 0, 253, 0, 0);
input_set_abs_params(input, ABS_MT_ORIENTATION, -3, 4, 0, 0);
@@ -660,7 +673,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
input_set_events_per_packet(input, 60);
if (report_undeciphered &&
- input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
+ input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
__set_bit(EV_MSC, input->evbit);
__set_bit(MSC_RAW, input->mscbit);
}
@@ -685,7 +699,9 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
/* Magic Trackpad does not give relative data after switching to MT */
if ((hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD ||
- hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) &&
+ hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ hi->input->id.product ==
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) &&
field->flags & HID_MAIN_ITEM_RELATIVE)
return -1;
@@ -721,7 +737,8 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev)
int ret;
int feature_size;
- if (hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ if (hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
if (hdev->vendor == BT_VENDOR_ID_APPLE) {
feature_size = sizeof(feature_mt_trackpad2_bt);
feature = feature_mt_trackpad2_bt;
@@ -766,7 +783,8 @@ static int magicmouse_fetch_battery(struct hid_device *hdev)
if (!hdev->battery || hdev->vendor != USB_VENDOR_ID_APPLE ||
(hdev->product != USB_DEVICE_ID_APPLE_MAGICMOUSE2 &&
- hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2))
+ hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
+ hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC))
return -1;
report_enum = &hdev->report_enum[hdev->battery_report_type];
@@ -835,7 +853,9 @@ static int magicmouse_probe(struct hid_device *hdev,
if (id->vendor == USB_VENDOR_ID_APPLE &&
(id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
- (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && hdev->type != HID_TYPE_USBMOUSE)))
+ ((id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) &&
+ hdev->type != HID_TYPE_USBMOUSE)))
return 0;
if (!msc->input) {
@@ -850,7 +870,8 @@ static int magicmouse_probe(struct hid_device *hdev,
else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2)
report = hid_register_report(hdev, HID_INPUT_REPORT,
MOUSE2_REPORT_ID, 0);
- else if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ else if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
if (id->vendor == BT_VENDOR_ID_APPLE)
report = hid_register_report(hdev, HID_INPUT_REPORT,
TRACKPAD2_BT_REPORT_ID, 0);
@@ -920,7 +941,8 @@ static const __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*/
if (hdev->vendor == USB_VENDOR_ID_APPLE &&
(hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
- hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) &&
+ hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
+ hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) &&
*rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) {
hid_info(hdev,
"fixing up magicmouse battery report descriptor\n");
@@ -951,6 +973,10 @@ static const struct hid_device_id magic_mice[] = {
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2), .driver_data = 0 },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2), .driver_data = 0 },
+ { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
{ }
};
MODULE_DEVICE_TABLE(hid, magic_mice);
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index e936019d21fe..785743036647 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -31,6 +31,7 @@
* [1] https://gitlab.freedesktop.org/libevdev/hid-tools
*/
+#include <linux/bits.h>
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
@@ -83,6 +84,13 @@ enum latency_mode {
HID_LATENCY_HIGH = 1,
};
+enum report_mode {
+ TOUCHPAD_REPORT_NONE = 0,
+ TOUCHPAD_REPORT_BUTTONS = BIT(0),
+ TOUCHPAD_REPORT_CONTACTS = BIT(1),
+ TOUCHPAD_REPORT_ALL = TOUCHPAD_REPORT_BUTTONS | TOUCHPAD_REPORT_CONTACTS,
+};
+
#define MT_IO_FLAGS_RUNNING 0
#define MT_IO_FLAGS_ACTIVE_SLOTS 1
#define MT_IO_FLAGS_PENDING_SLOTS 2
@@ -1493,8 +1501,7 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
struct hid_field *field,
struct hid_usage *usage,
enum latency_mode latency,
- bool surface_switch,
- bool button_switch,
+ enum report_mode report_mode,
bool *inputmode_found)
{
struct mt_device *td = hid_get_drvdata(hdev);
@@ -1549,11 +1556,11 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
return true;
case HID_DG_SURFACESWITCH:
- field->value[index] = surface_switch;
+ field->value[index] = !!(report_mode & TOUCHPAD_REPORT_CONTACTS);
return true;
case HID_DG_BUTTONSWITCH:
- field->value[index] = button_switch;
+ field->value[index] = !!(report_mode & TOUCHPAD_REPORT_BUTTONS);
return true;
}
@@ -1561,7 +1568,7 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
}
static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
- bool surface_switch, bool button_switch)
+ enum report_mode report_mode)
{
struct hid_report_enum *rep_enum;
struct hid_report *rep;
@@ -1586,8 +1593,7 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
rep->field[i],
usage,
latency,
- surface_switch,
- button_switch,
+ report_mode,
&inputmode_found))
update_report = true;
}
@@ -1830,7 +1836,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n",
hdev->name);
- mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
+ mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_ALL);
return 0;
}
@@ -1842,9 +1848,9 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state)
/* High latency is desirable for power savings during S3/S0ix */
if ((td->mtclass.quirks & MT_QUIRK_DISABLE_WAKEUP) ||
!hid_hw_may_wakeup(hdev))
- mt_set_modes(hdev, HID_LATENCY_HIGH, false, false);
+ mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE);
else
- mt_set_modes(hdev, HID_LATENCY_HIGH, true, true);
+ mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_ALL);
return 0;
}
@@ -1852,7 +1858,7 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state)
static int mt_reset_resume(struct hid_device *hdev)
{
mt_release_contacts(hdev);
- mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
+ mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_ALL);
return 0;
}
@@ -1864,7 +1870,7 @@ static int mt_resume(struct hid_device *hdev)
hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
- mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
+ mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_ALL);
return 0;
}
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index 83e3409d170c..8c28e982e09d 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -296,7 +296,7 @@ static void picolcd_fb_destroy(struct fb_info *info)
/* make sure no work is deferred */
fb_deferred_io_cleanup(info);
- /* No thridparty should ever unregister our framebuffer! */
+ /* No thirdparty should ever unregister our framebuffer! */
WARN_ON(fbdata->picolcd != NULL);
vfree((u8 *)info->fix.smem_start);
@@ -497,6 +497,10 @@ int picolcd_init_framebuffer(struct picolcd_data *data)
#endif
#endif
+#ifdef CONFIG_HID_PICOLCD_LCD
+ info->lcd_dev = data->lcd;
+#endif
+
fbdata = info->par;
spin_lock_init(&fbdata->lock);
fbdata->picolcd = data;
diff --git a/drivers/hid/hid-picolcd_lcd.c b/drivers/hid/hid-picolcd_lcd.c
index 061a33ba7b1d..318f19eac0e7 100644
--- a/drivers/hid/hid-picolcd_lcd.c
+++ b/drivers/hid/hid-picolcd_lcd.c
@@ -41,15 +41,9 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
return 0;
}
-static int picolcd_check_lcd_fb(struct lcd_device *ldev, struct fb_info *fb)
-{
- return fb && fb == picolcd_fbinfo((struct picolcd_data *)lcd_get_data(ldev));
-}
-
static const struct lcd_ops picolcd_lcdops = {
.get_contrast = picolcd_get_contrast,
.set_contrast = picolcd_set_contrast,
- .check_fb = picolcd_check_lcd_fb,
};
int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report)
diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
index 66f0675df24b..617ae240396d 100644
--- a/drivers/hid/hid-sensor-custom.c
+++ b/drivers/hid/hid-sensor-custom.c
@@ -946,7 +946,7 @@ hid_sensor_register_platform_device(struct platform_device *pdev,
memcpy(real_usage, match->luid, 4);
- /* usage id are all lowcase */
+ /* usage id are all lowercase */
for (c = real_usage; *c != '\0'; c++)
*c = tolower(*c);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index d2486f3734f0..5258b45684e8 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1379,7 +1379,8 @@ static int sony_leds_init(struct sony_sc *sc)
u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
u8 use_hw_blink[MAX_LEDS] = { 0 };
- BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
+ if (WARN_ON(!(sc->quirks & SONY_LED_SUPPORT)))
+ return -EINVAL;
if (sc->quirks & BUZZ_CONTROLLER) {
sc->led_count = 4;
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index bf8b633114be..6439913372a8 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -253,7 +253,7 @@ enum
ID_CONTROLLER_DECK_STATE = 9
};
-/* String attribute idenitifiers */
+/* String attribute identifiers */
enum {
ATTRIB_STR_BOARD_SERIAL,
ATTRIB_STR_UNIT_SERIAL,
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 7e83fee1ffa0..f9ff5be94309 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -411,6 +411,15 @@ static void steelseries_headset_fetch_battery(struct hid_device *hdev)
"Battery query failed (err: %d)\n", ret);
}
+static int battery_capacity_to_level(int capacity)
+{
+ if (capacity >= 50)
+ return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ if (capacity >= 20)
+ return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+}
+
static void steelseries_headset_battery_timer_tick(struct work_struct *work)
{
struct steelseries_device *sd = container_of(work,
@@ -442,6 +451,9 @@ static int steelseries_headset_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = sd->battery_capacity;
break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ val->intval = battery_capacity_to_level(sd->battery_capacity);
+ break;
default:
ret = -EINVAL;
break;
@@ -469,6 +481,7 @@ static enum power_supply_property steelseries_headset_battery_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
};
static int steelseries_headset_battery_register(struct steelseries_device *sd)
@@ -603,8 +616,11 @@ static int steelseries_headset_raw_event(struct hid_device *hdev,
hid_dbg(sd->hdev,
"Parsing raw event for Arctis 1 headset (%*ph)\n", size, read_buf);
if (size < ARCTIS_1_BATTERY_RESPONSE_LEN ||
- memcmp (read_buf, arctis_1_battery_request, sizeof(arctis_1_battery_request)))
+ memcmp(read_buf, arctis_1_battery_request, sizeof(arctis_1_battery_request))) {
+ if (!delayed_work_pending(&sd->battery_work))
+ goto request_battery;
return 0;
+ }
if (read_buf[2] == 0x01) {
connected = false;
capacity = 100;
@@ -631,6 +647,7 @@ static int steelseries_headset_raw_event(struct hid_device *hdev,
power_supply_changed(sd->battery);
}
+request_battery:
spin_lock_irqsave(&sd->lock, flags);
if (!sd->removed)
schedule_delayed_work(&sd->battery_work,
diff --git a/drivers/hid/i2c-hid/i2c-hid-of.c b/drivers/hid/i2c-hid/i2c-hid-of.c
index 8be4d576da77..57379b77e977 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of.c
@@ -144,9 +144,9 @@ MODULE_DEVICE_TABLE(of, i2c_hid_of_match);
#endif
static const struct i2c_device_id i2c_hid_of_id_table[] = {
- { "hid", 0 },
- { "hid-over-i2c", 0 },
- { },
+ { "hid" },
+ { "hid-over-i2c" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, i2c_hid_of_id_table);
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index aae0d965b47b..9e2401291a2f 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -381,6 +381,50 @@ static int __maybe_unused ish_resume(struct device *device)
static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume);
+static ssize_t base_version_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ishtp_device *dev = dev_get_drvdata(cdev);
+
+ return sysfs_emit(buf, "%u.%u.%u.%u\n", dev->base_ver.major,
+ dev->base_ver.minor, dev->base_ver.hotfix,
+ dev->base_ver.build);
+}
+static DEVICE_ATTR_RO(base_version);
+
+static ssize_t project_version_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ishtp_device *dev = dev_get_drvdata(cdev);
+
+ return sysfs_emit(buf, "%u.%u.%u.%u\n", dev->prj_ver.major,
+ dev->prj_ver.minor, dev->prj_ver.hotfix,
+ dev->prj_ver.build);
+}
+static DEVICE_ATTR_RO(project_version);
+
+static struct attribute *ish_firmware_attrs[] = {
+ &dev_attr_base_version.attr,
+ &dev_attr_project_version.attr,
+ NULL
+};
+
+static umode_t firmware_is_visible(struct kobject *kobj, struct attribute *attr,
+ int i)
+{
+ struct ishtp_device *dev = dev_get_drvdata(kobj_to_dev(kobj));
+
+ return dev->driver_data->fw_generation ? attr->mode : 0;
+}
+
+static const struct attribute_group ish_firmware_group = {
+ .name = "firmware",
+ .attrs = ish_firmware_attrs,
+ .is_visible = firmware_is_visible,
+};
+
+__ATTRIBUTE_GROUPS(ish_firmware);
+
static struct pci_driver ish_driver = {
.name = KBUILD_MODNAME,
.id_table = ish_pci_tbl,
@@ -388,6 +432,7 @@ static struct pci_driver ish_driver = {
.remove = ish_remove,
.shutdown = ish_shutdown,
.driver.pm = &ish_pm_ops,
+ .dev_groups = ish_firmware_groups,
};
module_pci_driver(ish_driver);
diff --git a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
index b3c3cfcd97fc..f4a671d6386c 100644
--- a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
+++ b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
@@ -793,7 +793,7 @@ static int load_fw_from_host(struct ishtp_cl_data *client_data)
if (rv < 0)
goto end_err_fw_release;
- /* Step 3: Start ISH main firmware exeuction */
+ /* Step 3: Start ISH main firmware execution */
rv = ish_fw_start(client_data);
if (rv < 0)
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
index fbd4f8ea1951..cb04cd1d980b 100644
--- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c
+++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
@@ -70,10 +70,10 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
unsigned char *payload;
struct device_info *dev_info;
int i, j;
- size_t payload_len, total_len, cur_pos, raw_len;
+ size_t payload_len, total_len, cur_pos, raw_len, msg_len;
int report_type;
struct report_list *reports_list;
- char *reports;
+ struct report *report;
size_t report_len;
struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
int curr_hid_dev = client_data->cur_hid_dev;
@@ -280,14 +280,13 @@ do_get_report:
case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
report_type = HID_INPUT_REPORT;
reports_list = (struct report_list *)payload;
- reports = (char *)reports_list->reports;
+ report = reports_list->reports;
for (j = 0; j < reports_list->num_of_reports; j++) {
- recv_msg = (struct hostif_msg *)(reports +
- sizeof(uint16_t));
- report_len = *(uint16_t *)reports;
- payload = reports + sizeof(uint16_t) +
- sizeof(struct hostif_msg_hdr);
+ recv_msg = container_of(&report->msg,
+ struct hostif_msg, hdr);
+ report_len = report->size;
+ payload = recv_msg->payload;
payload_len = report_len -
sizeof(struct hostif_msg_hdr);
@@ -304,7 +303,7 @@ do_get_report:
0);
}
- reports += sizeof(uint16_t) + report_len;
+ report += sizeof(*report) + payload_len;
}
break;
default:
@@ -316,12 +315,12 @@ do_get_report:
}
- if (!cur_pos && cur_pos + payload_len +
- sizeof(struct hostif_msg) < total_len)
+ msg_len = payload_len + sizeof(struct hostif_msg);
+ if (!cur_pos && cur_pos + msg_len < total_len)
++client_data->multi_packet_cnt;
- cur_pos += payload_len + sizeof(struct hostif_msg);
- payload += payload_len + sizeof(struct hostif_msg);
+ cur_pos += msg_len;
+ payload += msg_len;
} while (cur_pos < total_len);
}
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.h b/drivers/hid/intel-ish-hid/ishtp-hid.h
index 35dddc5015b3..2bc19e8ba13e 100644
--- a/drivers/hid/intel-ish-hid/ishtp-hid.h
+++ b/drivers/hid/intel-ish-hid/ishtp-hid.h
@@ -31,6 +31,7 @@ struct hostif_msg_hdr {
struct hostif_msg {
struct hostif_msg_hdr hdr;
+ uint8_t payload[];
} __packed;
struct hostif_msg_to_sensor {
@@ -52,15 +53,17 @@ struct ishtp_version {
uint16_t build;
} __packed;
+struct report {
+ uint16_t size;
+ struct hostif_msg_hdr msg;
+} __packed;
+
/* struct for ISHTP aggregated input data */
struct report_list {
uint16_t total_size;
uint8_t num_of_reports;
uint8_t flags;
- struct {
- uint16_t size_of_report;
- uint8_t report[1];
- } __packed reports[1];
+ struct report reports[];
} __packed;
/* HOSTIF commands */
diff --git a/drivers/hid/intel-ish-hid/ishtp/client.c b/drivers/hid/intel-ish-hid/ishtp/client.c
index 8a7f2f6a4f86..e61b01e9902e 100644
--- a/drivers/hid/intel-ish-hid/ishtp/client.c
+++ b/drivers/hid/intel-ish-hid/ishtp/client.c
@@ -863,7 +863,7 @@ static void ipc_tx_send(void *prm)
/* Send ipc fragment */
ishtp_hdr.length = dev->mtu;
ishtp_hdr.msg_complete = 0;
- /* All fregments submitted to IPC queue with no callback */
+ /* All fragments submitted to IPC queue with no callback */
ishtp_write_message(dev, &ishtp_hdr, pmsg);
cl->tx_offs += dev->mtu;
rem = cl_msg->send_buf.size - cl->tx_offs;
diff --git a/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
index cdacce0a4c9d..effbb442c727 100644
--- a/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
+++ b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
@@ -140,6 +140,13 @@ struct ishtp_driver_data {
char *fw_generation;
};
+struct ish_version {
+ u16 major;
+ u16 minor;
+ u16 hotfix;
+ u16 build;
+};
+
/**
* struct ishtp_device - ISHTP private device struct
*/
@@ -236,6 +243,11 @@ struct ishtp_device {
/* Dump to trace buffers if enabled*/
ishtp_print_log print_log;
+ /* Base version of Intel's released firmware */
+ struct ish_version base_ver;
+ /* Vendor-customized project version */
+ struct ish_version prj_ver;
+
/* Debug stats */
unsigned int ipc_rx_cnt;
unsigned long long ipc_rx_bytes_cnt;
diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.c b/drivers/hid/intel-ish-hid/ishtp/loader.c
index f76c4437a1f5..f34086b29cf0 100644
--- a/drivers/hid/intel-ish-hid/ishtp/loader.c
+++ b/drivers/hid/intel-ish-hid/ishtp/loader.c
@@ -308,6 +308,28 @@ static int request_ish_firmware(const struct firmware **firmware_p,
return _request_ish_firmware(firmware_p, filename, dev);
}
+static int copy_manifest(const struct firmware *fw, struct ish_global_manifest *manifest)
+{
+ u32 offset;
+
+ for (offset = 0; offset + sizeof(*manifest) < fw->size; offset += ISH_MANIFEST_ALIGNMENT) {
+ memcpy(manifest, fw->data + offset, sizeof(*manifest));
+
+ if (le32_to_cpu(manifest->sig_fourcc) == ISH_GLOBAL_SIG)
+ return 0;
+ }
+
+ return -1;
+}
+
+static void copy_ish_version(struct version_in_manifest *src, struct ish_version *dst)
+{
+ dst->major = le16_to_cpu(src->major);
+ dst->minor = le16_to_cpu(src->minor);
+ dst->hotfix = le16_to_cpu(src->hotfix);
+ dst->build = le16_to_cpu(src->build);
+}
+
/**
* ishtp_loader_work() - Load the ISHTP firmware
* @work: The work structure
@@ -336,6 +358,7 @@ void ishtp_loader_work(struct work_struct *work)
struct loader_xfer_query query = { .header = cpu_to_le32(query_hdr.val32), };
struct loader_start start = { .header = cpu_to_le32(start_hdr.val32), };
union loader_recv_message recv_msg;
+ struct ish_global_manifest manifest;
const struct firmware *ish_fw;
void *dma_bufs[FRAGMENT_MAX_NUM] = {};
u32 fragment_size;
@@ -372,7 +395,7 @@ void ishtp_loader_work(struct work_struct *work)
if (rv)
continue; /* try again if failed */
- dev_dbg(dev->devc, "ISH Version %u.%u.%u.%u\n",
+ dev_dbg(dev->devc, "ISH Bootloader Version %u.%u.%u.%u\n",
recv_msg.query_ack.version_major,
recv_msg.query_ack.version_minor,
recv_msg.query_ack.version_hotfix,
@@ -390,6 +413,16 @@ void ishtp_loader_work(struct work_struct *work)
continue; /* try again if failed */
dev_info(dev->devc, "firmware loaded. size:%zu\n", ish_fw->size);
+ if (!copy_manifest(ish_fw, &manifest)) {
+ copy_ish_version(&manifest.base_ver, &dev->base_ver);
+ copy_ish_version(&manifest.prj_ver, &dev->prj_ver);
+ dev_info(dev->devc, "FW base version: %u.%u.%u.%u\n",
+ dev->base_ver.major, dev->base_ver.minor,
+ dev->base_ver.hotfix, dev->base_ver.build);
+ dev_info(dev->devc, "FW project version: %u.%u.%u.%u\n",
+ dev->prj_ver.major, dev->prj_ver.minor,
+ dev->prj_ver.hotfix, dev->prj_ver.build);
+ }
break;
} while (--retry);
diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.h b/drivers/hid/intel-ish-hid/ishtp/loader.h
index 308b96085a4d..4dda038b4947 100644
--- a/drivers/hid/intel-ish-hid/ishtp/loader.h
+++ b/drivers/hid/intel-ish-hid/ishtp/loader.h
@@ -10,6 +10,7 @@
#include <linux/bits.h>
#include <linux/jiffies.h>
+#include <linux/sizes.h>
#include <linux/types.h>
#include "ishtp-dev.h"
@@ -228,4 +229,37 @@ struct ish_firmware_variant {
*/
void ishtp_loader_work(struct work_struct *work);
+/* ISH Manifest alignment in binary is 4KB aligned */
+#define ISH_MANIFEST_ALIGNMENT SZ_4K
+
+/* Signature for ISH global manifest */
+#define ISH_GLOBAL_SIG 0x47485349 /* FourCC 'I', 'S', 'H', 'G' */
+
+struct version_in_manifest {
+ __le16 major;
+ __le16 minor;
+ __le16 hotfix;
+ __le16 build;
+};
+
+/**
+ * struct ish_global_manifest - global manifest for ISH
+ * @sig_fourcc: Signature FourCC, should be 'I', 'S', 'H', 'G'.
+ * @len: Length of the manifest.
+ * @header_version: Version of the manifest header.
+ * @flags: Flags for additional information.
+ * @base_ver: Base version of Intel's released firmware.
+ * @reserved: Reserved space for future use.
+ * @prj_ver: Vendor-customized project version.
+ */
+struct ish_global_manifest {
+ __le32 sig_fourcc;
+ __le32 len;
+ __le32 header_version;
+ __le32 flags;
+ struct version_in_manifest base_ver;
+ __le32 reserved[13];
+ struct version_in_manifest prj_ver;
+};
+
#endif /* _ISHTP_LOADER_H_ */
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index a9e85bdd4cc6..a6eb6fe6130d 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1100,7 +1100,7 @@ static int usbhid_start(struct hid_device *hid)
interval = endpoint->bInterval;
- /* Some vendors give fullspeed interval on highspeed devides */
+ /* Some vendors give fullspeed interval on highspeed devices */
if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
dev->speed == USB_SPEED_HIGH) {
interval = fls(endpoint->bInterval*8);
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 413606bdf476..5501a560fb07 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1353,9 +1353,9 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
rotation -= 1800;
input_report_abs(pen_input, ABS_TILT_X,
- (char)frame[7]);
+ (signed char)frame[7]);
input_report_abs(pen_input, ABS_TILT_Y,
- (char)frame[8]);
+ (signed char)frame[8]);
input_report_abs(pen_input, ABS_Z, rotation);
input_report_abs(pen_input, ABS_WHEEL,
get_unaligned_le16(&frame[11]));
@@ -2422,9 +2422,11 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
wacom_wac->hid_data.sense_state = value;
return;
case HID_DG_INVERT:
- wacom_wac->hid_data.invert_state = value;
+ wacom_wac->hid_data.eraser |= value;
return;
case HID_DG_ERASER:
+ wacom_wac->hid_data.eraser |= value;
+ fallthrough;
case HID_DG_TIPSWITCH:
wacom_wac->hid_data.tipswitch |= value;
return;
@@ -2565,7 +2567,7 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
if (entering_range) { /* first in range */
/* Going into range select tool */
- if (wacom_wac->hid_data.invert_state)
+ if (wacom_wac->hid_data.eraser)
wacom_wac->tool[0] = BTN_TOOL_RUBBER;
else if (wacom_wac->features.quirks & WACOM_QUIRK_AESPEN)
wacom_wac->tool[0] = BTN_TOOL_PEN;
@@ -2619,6 +2621,7 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
}
wacom_wac->hid_data.tipswitch = false;
+ wacom_wac->hid_data.eraser = false;
input_sync(input);
}
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index c8803d5c6a71..0c3c6a6aaae9 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -300,7 +300,7 @@ struct hid_data {
__s16 inputmode_index; /* InputMode HID feature index in the report */
bool sense_state;
bool inrange_state;
- bool invert_state;
+ bool eraser;
bool tipswitch;
bool barrelswitch;
bool barrelswitch2;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 08a3c863f80a..dd376602f3f1 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -855,6 +855,17 @@ config SENSORS_CORETEMP
sensor inside your CPU. Most of the family 6 CPUs
are supported. Check Documentation/hwmon/coretemp.rst for details.
+config SENSORS_ISL28022
+ tristate "Renesas ISL28022"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for ISL28022 power monitor.
+ Check Documentation/hwmon/isl28022.rst for details.
+
+ This driver can also be built as a module. If so, the module
+ will be called isl28022.
+
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
depends on HAS_IOPORT
@@ -1670,6 +1681,17 @@ config SENSORS_NCT6775_I2C
This driver can also be built as a module. If so, the module
will be called nct6775-i2c.
+config SENSORS_NCT7363
+ tristate "Nuvoton NCT7363Y"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for the Nuvoton NCT7363Y
+ hardware monitoring chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called nct7363.
+
config SENSORS_NCT7802
tristate "Nuvoton NCT7802Y"
depends on I2C
@@ -1752,7 +1774,7 @@ source "drivers/hwmon/occ/Kconfig"
config SENSORS_OXP
tristate "OneXPlayer EC fan control"
- depends on ACPI
+ depends on ACPI_EC
depends on X86
help
If you say yes here you get support for fan readings and control over
@@ -2167,11 +2189,12 @@ config SENSORS_INA2XX
select REGMAP_I2C
help
If you say yes here you get support for INA219, INA220, INA226,
- INA230, and INA231 power monitor chips.
+ INA230, INA231, INA260, and SY24655 power monitor chips.
The INA2xx driver is configured for the default configuration of
the part as described in the datasheet.
- Default value for Rshunt is 10 mOhms.
+ Default value for Rshunt is 10 mOhms except for INA260 which has an
+ internal 2 mOhm shunt resistor.
This driver can also be built as a module. If so, the module
will be called ina2xx.
@@ -2274,10 +2297,12 @@ config SENSORS_TMP103
config SENSORS_TMP108
tristate "Texas Instruments TMP108"
depends on I2C
+ depends on I3C || !I3C
select REGMAP_I2C
+ select REGMAP_I3C if I3C
help
If you say yes here you get support for Texas Instruments TMP108
- sensor chips.
+ sensor chips and NXP P3T1085.
This driver can also be built as a module. If so, the module
will be called tmp108.
@@ -2592,6 +2617,7 @@ config SENSORS_ASUS_WMI
config SENSORS_ASUS_EC
tristate "ASUS EC Sensors"
depends on X86
+ depends on ACPI_EC
help
If you say yes here you get support for the ACPI embedded controller
hardware monitoring interface found in ASUS motherboards. The driver
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 9554d2fdcf7b..b827b92f2a78 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -103,6 +103,7 @@ obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
obj-$(CONFIG_SENSORS_INA238) += ina238.o
obj-$(CONFIG_SENSORS_INA3221) += ina3221.o
obj-$(CONFIG_SENSORS_INTEL_M10_BMC_HWMON) += intel-m10-bmc-hwmon.o
+obj-$(CONFIG_SENSORS_ISL28022) += isl28022.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_JC42) += jc42.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
@@ -171,6 +172,7 @@ obj-$(CONFIG_SENSORS_NCT6775_CORE) += nct6775-core.o
nct6775-objs := nct6775-platform.o
obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
obj-$(CONFIG_SENSORS_NCT6775_I2C) += nct6775-i2c.o
+obj-$(CONFIG_SENSORS_NCT7363) += nct7363.o
obj-$(CONFIG_SENSORS_NCT7802) += nct7802.o
obj-$(CONFIG_SENSORS_NCT7904) += nct7904.o
obj-$(CONFIG_SENSORS_NPCM7XX) += npcm750-pwm-fan.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 93653ea05430..ba8c68ae4595 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -1531,7 +1531,7 @@ static struct platform_driver abituguru_driver = {
.pm = pm_sleep_ptr(&abituguru_pm),
},
.probe = abituguru_probe,
- .remove_new = abituguru_remove,
+ .remove = abituguru_remove,
};
static int __init abituguru_detect(void)
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 4501f0e49efb..b70330dc2198 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -1147,12 +1147,12 @@ static int abituguru3_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(abituguru3_pm, abituguru3_suspend, abituguru3_resume);
static struct platform_driver abituguru3_driver = {
- .driver = {
+ .driver = {
.name = ABIT_UGURU3_NAME,
.pm = pm_sleep_ptr(&abituguru3_pm),
},
.probe = abituguru3_probe,
- .remove_new = abituguru3_remove,
+ .remove = abituguru3_remove,
};
static int __init abituguru3_dmi_detect(void)
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 6c8a9c863528..2f1c9d97ad21 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -680,8 +680,9 @@ static int setup_attrs(struct acpi_power_meter_resource *resource)
{
int res = 0;
+ /* _PMD method is optional. */
res = read_domain_devices(resource);
- if (res)
+ if (res != -ENODEV)
return res;
if (resource->caps.flags & POWER_METER_CAN_MEASURE) {
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index ac64b407ed0e..1e3c6acd8974 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -22,6 +22,7 @@
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of_platform.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -893,7 +894,6 @@ static bool amc6821_volatile_reg(struct device *dev, unsigned int reg)
static const struct regmap_config amc6821_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .max_register = AMC6821_REG_CONF3,
.volatile_reg = amc6821_volatile_reg,
.cache_type = REGCACHE_MAPLE,
};
@@ -920,6 +920,13 @@ static int amc6821_probe(struct i2c_client *client)
if (err)
return err;
+ if (of_device_is_compatible(dev->of_node, "tsd,mule")) {
+ err = devm_of_platform_populate(dev);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Failed to create sub-devices\n");
+ }
+
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
data, &amc6821_chip_info,
amc6821_groups);
@@ -927,7 +934,7 @@ static int amc6821_probe(struct i2c_client *client)
}
static const struct i2c_device_id amc6821_id[] = {
- { "amc6821", 0 },
+ { "amc6821" },
{ }
};
@@ -937,6 +944,9 @@ static const struct of_device_id __maybe_unused amc6821_of_match[] = {
{
.compatible = "ti,amc6821",
},
+ {
+ .compatible = "tsd,mule",
+ },
{ }
};
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index 34cac27e4dde..0dcb8a3a691d 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -597,7 +597,7 @@ struct aqc_data {
/* Sensor values */
s32 temp_input[20]; /* Max 4 physical and 16 virtual or 8 physical and 12 virtual */
- s32 speed_input[8];
+ s32 speed_input[9];
u32 speed_input_min[1];
u32 speed_input_target[1];
u32 speed_input_max[1];
diff --git a/drivers/hwmon/aspeed-g6-pwm-tach.c b/drivers/hwmon/aspeed-g6-pwm-tach.c
index 75eadda738ab..4174b129d1fc 100644
--- a/drivers/hwmon/aspeed-g6-pwm-tach.c
+++ b/drivers/hwmon/aspeed-g6-pwm-tach.c
@@ -534,7 +534,7 @@ MODULE_DEVICE_TABLE(of, aspeed_pwm_tach_match);
static struct platform_driver aspeed_pwm_tach_driver = {
.probe = aspeed_pwm_tach_probe,
- .remove_new = aspeed_pwm_tach_remove,
+ .remove = aspeed_pwm_tach_remove,
.driver = {
.name = "aspeed-g6-pwm-tach",
.of_match_table = aspeed_pwm_tach_match,
diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c
index 5514cf780b8b..9991c3fa020a 100644
--- a/drivers/hwmon/cros_ec_hwmon.c
+++ b/drivers/hwmon/cros_ec_hwmon.c
@@ -141,6 +141,7 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type
}
static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(fan,
HWMON_F_INPUT | HWMON_F_FAULT,
HWMON_F_INPUT | HWMON_F_FAULT,
diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
index 7fb0c57dfef5..588e96790850 100644
--- a/drivers/hwmon/da9052-hwmon.c
+++ b/drivers/hwmon/da9052-hwmon.c
@@ -473,7 +473,7 @@ static void da9052_hwmon_remove(struct platform_device *pdev)
static struct platform_driver da9052_hwmon_driver = {
.probe = da9052_hwmon_probe,
- .remove_new = da9052_hwmon_remove,
+ .remove = da9052_hwmon_remove,
.driver = {
.name = "da9052-hwmon",
},
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 1a9b28dc91e6..3d4057309950 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -2721,7 +2721,7 @@ static struct platform_driver dme1737_isa_driver = {
.name = "dme1737",
},
.probe = dme1737_isa_probe,
- .remove_new = dme1737_isa_remove,
+ .remove = dme1737_isa_remove,
};
/* ---------------------------------------------------------------------
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 243c570dee4c..820f894d9ffd 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1497,7 +1497,7 @@ static struct platform_driver f71805f_driver = {
.name = DRVNAME,
},
.probe = f71805f_probe,
- .remove_new = f71805f_remove,
+ .remove = f71805f_remove,
};
static int __init f71805f_device_add(unsigned short address,
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 7c941d320a18..df83f9866fbc 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -2658,7 +2658,7 @@ static struct platform_driver f71882fg_driver = {
.name = DRVNAME,
},
.probe = f71882fg_probe,
- .remove_new = f71882fg_remove,
+ .remove = f71882fg_remove,
};
static int __init f71882fg_init(void)
diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c
index 4514f3ed90cc..14a6385cd7cc 100644
--- a/drivers/hwmon/gsc-hwmon.c
+++ b/drivers/hwmon/gsc-hwmon.c
@@ -231,15 +231,8 @@ gsc_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
return 0;
}
-static umode_t
-gsc_hwmon_is_visible(const void *_data, enum hwmon_sensor_types type, u32 attr,
- int ch)
-{
- return 0444;
-}
-
static const struct hwmon_ops gsc_hwmon_ops = {
- .is_visible = gsc_hwmon_is_visible,
+ .visible = 0444,
.read = gsc_hwmon_read,
.read_string = gsc_hwmon_read_string,
};
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 9c35c4d0369d..49b366254529 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -145,6 +145,17 @@ static const struct class hwmon_class = {
static DEFINE_IDA(hwmon_ida);
+static umode_t hwmon_is_visible(const struct hwmon_ops *ops,
+ const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (ops->visible)
+ return ops->visible;
+
+ return ops->is_visible(drvdata, type, attr, channel);
+}
+
/* Thermal zone handling */
/*
@@ -267,8 +278,8 @@ static int hwmon_thermal_register_sensors(struct device *dev)
int err;
if (!(info[i]->config[j] & HWMON_T_INPUT) ||
- !chip->ops->is_visible(drvdata, hwmon_temp,
- hwmon_temp_input, j))
+ !hwmon_is_visible(chip->ops, drvdata, hwmon_temp,
+ hwmon_temp_input, j))
continue;
err = hwmon_thermal_add_sensor(dev, j);
@@ -506,7 +517,7 @@ static struct attribute *hwmon_genattr(const void *drvdata,
const char *name;
bool is_string = is_string_attr(type, attr);
- mode = ops->is_visible(drvdata, type, attr, index);
+ mode = hwmon_is_visible(ops, drvdata, type, attr, index);
if (!mode)
return ERR_PTR(-ENOENT);
@@ -1033,7 +1044,7 @@ hwmon_device_register_with_info(struct device *dev, const char *name,
if (!dev || !name || !chip)
return ERR_PTR(-EINVAL);
- if (!chip->ops || !chip->ops->is_visible || !chip->info)
+ if (!chip->ops || !(chip->ops->visible || chip->ops->is_visible) || !chip->info)
return ERR_PTR(-EINVAL);
return __hwmon_device_register(dev, name, drvdata, chip, extra_groups);
diff --git a/drivers/hwmon/i5500_temp.c b/drivers/hwmon/i5500_temp.c
index 7b00b38c7f7b..2a530da21949 100644
--- a/drivers/hwmon/i5500_temp.c
+++ b/drivers/hwmon/i5500_temp.c
@@ -29,12 +29,6 @@
#define REG_CTCTRL 0xF7
#define REG_TSTIMER 0xF8
-static umode_t i5500_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
- int channel)
-{
- return 0444;
-}
-
static int i5500_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
long *val)
{
@@ -84,7 +78,7 @@ static int i5500_read(struct device *dev, enum hwmon_sensor_types type, u32 attr
}
static const struct hwmon_ops i5500_ops = {
- .is_visible = i5500_is_visible,
+ .visible = 0444,
.read = i5500_read,
};
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index 02f5d35dd319..b22e0423e324 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -568,7 +568,7 @@ static struct platform_driver i5k_amb_driver = {
.name = DRVNAME,
},
.probe = i5k_amb_probe,
- .remove_new = i5k_amb_remove,
+ .remove = i5k_amb_remove,
};
static int __init i5k_amb_init(void)
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index f0fa6d073627..345fe7db9de9 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -51,17 +51,26 @@
#define INA226_ALERT_LIMIT 0x07
#define INA226_DIE_ID 0xFF
-#define INA2XX_MAX_REGISTERS 8
+/* SY24655 register definitions */
+#define SY24655_EIN 0x0A
+#define SY24655_ACCUM_CONFIG 0x0D
+#define INA2XX_MAX_REGISTERS 0x0D
/* settings - depend on use case */
#define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */
#define INA226_CONFIG_DEFAULT 0x4527 /* averages=16 */
+#define INA260_CONFIG_DEFAULT 0x6527 /* averages=16 */
+#define SY24655_CONFIG_DEFAULT 0x4527 /* averages=16 */
+
+/* (only for sy24655) */
+#define SY24655_ACCUM_CONFIG_DEFAULT 0x044C /* continuous mode, clear after read*/
/* worst case is 68.10 ms (~14.6Hz, ina219) */
#define INA2XX_CONVERSION_RATE 15
#define INA2XX_MAX_DELAY 69 /* worst case delay in ms */
#define INA2XX_RSHUNT_DEFAULT 10000
+#define INA260_RSHUNT 2000
/* bit mask for reading the averaging setting in the configuration register */
#define INA226_AVG_RD_MASK GENMASK(11, 9)
@@ -95,6 +104,7 @@ static bool ina2xx_writeable_reg(struct device *dev, unsigned int reg)
case INA2XX_CALIBRATION:
case INA226_MASK_ENABLE:
case INA226_ALERT_LIMIT:
+ case SY24655_ACCUM_CONFIG:
return true;
default:
return false;
@@ -125,10 +135,13 @@ static const struct regmap_config ina2xx_regmap_config = {
.writeable_reg = ina2xx_writeable_reg,
};
-enum ina2xx_ids { ina219, ina226 };
+enum ina2xx_ids { ina219, ina226, ina260, sy24655 };
struct ina2xx_config {
u16 config_default;
+ bool has_alerts; /* chip supports alerts and limits */
+ bool has_ishunt; /* chip has internal shunt resistor */
+ bool has_power_average; /* chip has internal shunt resistor */
int calibration_value;
int shunt_div;
int bus_voltage_shift;
@@ -145,6 +158,7 @@ struct ina2xx_data {
long power_lsb_uW;
struct mutex config_lock;
struct regmap *regmap;
+ struct i2c_client *client;
};
static const struct ina2xx_config ina2xx_config[] = {
@@ -155,6 +169,9 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 3,
.bus_voltage_lsb = 4000,
.power_lsb_factor = 20,
+ .has_alerts = false,
+ .has_ishunt = false,
+ .has_power_average = false,
},
[ina226] = {
.config_default = INA226_CONFIG_DEFAULT,
@@ -163,6 +180,30 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 0,
.bus_voltage_lsb = 1250,
.power_lsb_factor = 25,
+ .has_alerts = true,
+ .has_ishunt = false,
+ .has_power_average = false,
+ },
+ [ina260] = {
+ .config_default = INA260_CONFIG_DEFAULT,
+ .shunt_div = 400,
+ .bus_voltage_shift = 0,
+ .bus_voltage_lsb = 1250,
+ .power_lsb_factor = 8,
+ .has_alerts = true,
+ .has_ishunt = true,
+ .has_power_average = false,
+ },
+ [sy24655] = {
+ .config_default = SY24655_CONFIG_DEFAULT,
+ .calibration_value = 4096,
+ .shunt_div = 400,
+ .bus_voltage_shift = 0,
+ .bus_voltage_lsb = 1250,
+ .power_lsb_factor = 25,
+ .has_alerts = true,
+ .has_ishunt = false,
+ .has_power_average = true,
},
};
@@ -254,6 +295,15 @@ static int ina2xx_read_init(struct device *dev, int reg, long *val)
unsigned int regval;
int ret, retry;
+ if (data->config->has_ishunt) {
+ /* No calibration needed */
+ ret = regmap_read(regmap, reg, &regval);
+ if (ret < 0)
+ return ret;
+ *val = ina2xx_get_value(data, reg, regval);
+ return 0;
+ }
+
for (retry = 5; retry; retry--) {
ret = regmap_read(regmap, reg, &regval);
if (ret < 0)
@@ -459,6 +509,41 @@ static int ina2xx_in_read(struct device *dev, u32 attr, int channel, long *val)
return 0;
}
+/*
+ * Configuring the READ_EIN (bit 10) of the ACCUM_CONFIG register to 1
+ * can clear accumulator and sample_count after reading the EIN register.
+ * This way, the average power between the last read and the current
+ * read can be obtained. By combining with accurate time data from
+ * outside, the energy consumption during that period can be calculated.
+ */
+static int sy24655_average_power_read(struct ina2xx_data *data, u8 reg, long *val)
+{
+ u8 template[6];
+ int ret;
+ long accumulator_24, sample_count;
+
+ /* 48-bit register read */
+ ret = i2c_smbus_read_i2c_block_data(data->client, reg, 6, template);
+ if (ret < 0)
+ return ret;
+ if (ret != 6)
+ return -EIO;
+ accumulator_24 = ((template[3] << 16) |
+ (template[4] << 8) |
+ template[5]);
+ sample_count = ((template[0] << 16) |
+ (template[1] << 8) |
+ template[2]);
+ if (sample_count <= 0) {
+ *val = 0;
+ return 0;
+ }
+
+ *val = DIV_ROUND_CLOSEST(accumulator_24, sample_count) * data->power_lsb_uW;
+
+ return 0;
+}
+
static int ina2xx_power_read(struct device *dev, u32 attr, long *val)
{
struct ina2xx_data *data = dev_get_drvdata(dev);
@@ -466,6 +551,8 @@ static int ina2xx_power_read(struct device *dev, u32 attr, long *val)
switch (attr) {
case hwmon_power_input:
return ina2xx_read_init(dev, INA2XX_POWER, val);
+ case hwmon_power_average:
+ return sy24655_average_power_read(data, SY24655_EIN, val);
case hwmon_power_crit:
return ina226_alert_limit_read(data, INA226_POWER_OVER_LIMIT_MASK,
INA2XX_POWER, val);
@@ -624,6 +711,8 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
u32 attr, int channel)
{
const struct ina2xx_data *data = _data;
+ bool has_alerts = data->config->has_alerts;
+ bool has_power_average = data->config->has_power_average;
enum ina2xx_ids chip = data->chip;
switch (type) {
@@ -633,12 +722,12 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
return 0444;
case hwmon_in_lcrit:
case hwmon_in_crit:
- if (chip == ina226)
+ if (has_alerts)
return 0644;
break;
case hwmon_in_lcrit_alarm:
case hwmon_in_crit_alarm:
- if (chip == ina226)
+ if (has_alerts)
return 0444;
break;
default:
@@ -651,12 +740,12 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
return 0444;
case hwmon_curr_lcrit:
case hwmon_curr_crit:
- if (chip == ina226)
+ if (has_alerts)
return 0644;
break;
case hwmon_curr_lcrit_alarm:
case hwmon_curr_crit_alarm:
- if (chip == ina226)
+ if (has_alerts)
return 0444;
break;
default:
@@ -668,11 +757,15 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
case hwmon_power_input:
return 0444;
case hwmon_power_crit:
- if (chip == ina226)
+ if (has_alerts)
return 0644;
break;
case hwmon_power_crit_alarm:
- if (chip == ina226)
+ if (has_alerts)
+ return 0444;
+ break;
+ case hwmon_power_average:
+ if (has_power_average)
return 0444;
break;
default:
@@ -682,7 +775,7 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
case hwmon_chip:
switch (attr) {
case hwmon_chip_update_interval:
- if (chip == ina226)
+ if (chip == ina226 || chip == ina260)
return 0644;
break;
default:
@@ -707,7 +800,8 @@ static const struct hwmon_channel_info * const ina2xx_info[] = {
HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM |
HWMON_C_LCRIT | HWMON_C_LCRIT_ALARM),
HWMON_CHANNEL_INFO(power,
- HWMON_P_INPUT | HWMON_P_CRIT | HWMON_P_CRIT_ALARM),
+ HWMON_P_INPUT | HWMON_P_CRIT | HWMON_P_CRIT_ALARM |
+ HWMON_P_AVERAGE),
NULL
};
@@ -791,7 +885,9 @@ static int ina2xx_init(struct device *dev, struct ina2xx_data *data)
u32 shunt;
int ret;
- if (device_property_read_u32(dev, "shunt-resistor", &shunt) < 0)
+ if (data->config->has_ishunt)
+ shunt = INA260_RSHUNT;
+ else if (device_property_read_u32(dev, "shunt-resistor", &shunt) < 0)
shunt = INA2XX_RSHUNT_DEFAULT;
ret = ina2xx_set_shunt(data, shunt);
@@ -802,7 +898,7 @@ static int ina2xx_init(struct device *dev, struct ina2xx_data *data)
if (ret < 0)
return ret;
- if (data->chip == ina226) {
+ if (data->config->has_alerts) {
bool active_high = device_property_read_bool(dev, "ti,alert-polarity-active-high");
regmap_update_bits(regmap, INA226_MASK_ENABLE,
@@ -810,6 +906,22 @@ static int ina2xx_init(struct device *dev, struct ina2xx_data *data)
INA226_ALERT_LATCH_ENABLE |
FIELD_PREP(INA226_ALERT_POLARITY, active_high));
}
+ if (data->config->has_power_average) {
+ if (data->chip == sy24655) {
+ /*
+ * Initialize the power accumulation method to continuous
+ * mode and clear the EIN register after each read of the
+ * EIN register
+ */
+ ret = regmap_write(regmap, SY24655_ACCUM_CONFIG,
+ SY24655_ACCUM_CONFIG_DEFAULT);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ if (data->config->has_ishunt)
+ return 0;
/*
* Calibration register is set to the best value, which eliminates
@@ -836,6 +948,7 @@ static int ina2xx_probe(struct i2c_client *client)
return -ENOMEM;
/* set the device type */
+ data->client = client;
data->config = &ina2xx_config[chip];
data->chip = chip;
mutex_init(&data->config_lock);
@@ -856,7 +969,8 @@ static int ina2xx_probe(struct i2c_client *client)
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
data, &ina2xx_chip_info,
- ina2xx_groups);
+ data->config->has_ishunt ?
+ NULL : ina2xx_groups);
if (IS_ERR(hwmon_dev))
return PTR_ERR(hwmon_dev);
@@ -872,12 +986,18 @@ static const struct i2c_device_id ina2xx_id[] = {
{ "ina226", ina226 },
{ "ina230", ina226 },
{ "ina231", ina226 },
+ { "ina260", ina260 },
+ { "sy24655", sy24655 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ina2xx_id);
static const struct of_device_id __maybe_unused ina2xx_of_match[] = {
{
+ .compatible = "silergy,sy24655",
+ .data = (void *)sy24655
+ },
+ {
.compatible = "ti,ina219",
.data = (void *)ina219
},
@@ -897,7 +1017,11 @@ static const struct of_device_id __maybe_unused ina2xx_of_match[] = {
.compatible = "ti,ina231",
.data = (void *)ina226
},
- { },
+ {
+ .compatible = "ti,ina260",
+ .data = (void *)ina260
+ },
+ { }
};
MODULE_DEVICE_TABLE(of, ina2xx_of_match);
diff --git a/drivers/hwmon/intel-m10-bmc-hwmon.c b/drivers/hwmon/intel-m10-bmc-hwmon.c
index 96397ae6ff18..e221f2c1f332 100644
--- a/drivers/hwmon/intel-m10-bmc-hwmon.c
+++ b/drivers/hwmon/intel-m10-bmc-hwmon.c
@@ -565,13 +565,6 @@ static const struct m10bmc_hwmon_board_data n6000bmc_hwmon_bdata = {
.hinfo = n6000bmc_hinfo,
};
-static umode_t
-m10bmc_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
- u32 attr, int channel)
-{
- return 0444;
-}
-
static const struct m10bmc_sdata *
find_sensor_data(struct m10bmc_hwmon *hw, enum hwmon_sensor_types type,
int channel)
@@ -729,7 +722,7 @@ static int m10bmc_hwmon_read_string(struct device *dev,
}
static const struct hwmon_ops m10bmc_hwmon_ops = {
- .is_visible = m10bmc_hwmon_is_visible,
+ .visible = 0444,
.read = m10bmc_hwmon_read,
.read_string = m10bmc_hwmon_read_string,
};
diff --git a/drivers/hwmon/isl28022.c b/drivers/hwmon/isl28022.c
new file mode 100644
index 000000000000..f9edcfd164c2
--- /dev/null
+++ b/drivers/hwmon/isl28022.c
@@ -0,0 +1,535 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * isl28022.c - driver for Renesas ISL28022 power monitor chip monitoring
+ *
+ * Copyright (c) 2023 Carsten Spieß <mail@carsten-spiess.de>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+/* ISL28022 registers */
+#define ISL28022_REG_CONFIG 0x00
+#define ISL28022_REG_SHUNT 0x01
+#define ISL28022_REG_BUS 0x02
+#define ISL28022_REG_POWER 0x03
+#define ISL28022_REG_CURRENT 0x04
+#define ISL28022_REG_CALIB 0x05
+#define ISL28022_REG_SHUNT_THR 0x06
+#define ISL28022_REG_BUS_THR 0x07
+#define ISL28022_REG_INT 0x08
+#define ISL28022_REG_AUX 0x09
+#define ISL28022_REG_MAX ISL28022_REG_AUX
+
+/* ISL28022 config flags */
+/* mode flags */
+#define ISL28022_MODE_SHIFT 0
+#define ISL28022_MODE_MASK 0x0007
+
+#define ISL28022_MODE_PWR_DOWN 0x0
+#define ISL28022_MODE_TRG_S 0x1
+#define ISL28022_MODE_TRG_B 0x2
+#define ISL28022_MODE_TRG_SB 0x3
+#define ISL28022_MODE_ADC_OFF 0x4
+#define ISL28022_MODE_CONT_S 0x5
+#define ISL28022_MODE_CONT_B 0x6
+#define ISL28022_MODE_CONT_SB 0x7
+
+/* shunt ADC settings */
+#define ISL28022_SADC_SHIFT 3
+#define ISL28022_SADC_MASK 0x0078
+
+#define ISL28022_BADC_SHIFT 7
+#define ISL28022_BADC_MASK 0x0780
+
+#define ISL28022_ADC_12 0x0 /* 12 bit ADC */
+#define ISL28022_ADC_13 0x1 /* 13 bit ADC */
+#define ISL28022_ADC_14 0x2 /* 14 bit ADC */
+#define ISL28022_ADC_15 0x3 /* 15 bit ADC */
+#define ISL28022_ADC_15_1 0x8 /* 15 bit ADC, 1 sample */
+#define ISL28022_ADC_15_2 0x9 /* 15 bit ADC, 2 samples */
+#define ISL28022_ADC_15_4 0xA /* 15 bit ADC, 4 samples */
+#define ISL28022_ADC_15_8 0xB /* 15 bit ADC, 8 samples */
+#define ISL28022_ADC_15_16 0xC /* 15 bit ADC, 16 samples */
+#define ISL28022_ADC_15_32 0xD /* 15 bit ADC, 32 samples */
+#define ISL28022_ADC_15_64 0xE /* 15 bit ADC, 64 samples */
+#define ISL28022_ADC_15_128 0xF /* 15 bit ADC, 128 samples */
+
+/* shunt voltage range */
+#define ISL28022_PG_SHIFT 11
+#define ISL28022_PG_MASK 0x1800
+
+#define ISL28022_PG_40 0x0 /* +/-40 mV */
+#define ISL28022_PG_80 0x1 /* +/-80 mV */
+#define ISL28022_PG_160 0x2 /* +/-160 mV */
+#define ISL28022_PG_320 0x3 /* +/-3200 mV */
+
+/* bus voltage range */
+#define ISL28022_BRNG_SHIFT 13
+#define ISL28022_BRNG_MASK 0x6000
+
+#define ISL28022_BRNG_16 0x0 /* 16 V */
+#define ISL28022_BRNG_32 0x1 /* 32 V */
+#define ISL28022_BRNG_60 0x3 /* 60 V */
+
+/* reset */
+#define ISL28022_RESET 0x8000
+
+struct isl28022_data {
+ struct regmap *regmap;
+ u32 shunt;
+ u32 gain;
+ u32 average;
+};
+
+static int isl28022_read_in(struct device *dev, u32 attr, int channel, long *val)
+{
+ struct isl28022_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int err;
+ u16 sign_bit;
+
+ switch (channel) {
+ case 0:
+ switch (attr) {
+ case hwmon_in_input:
+ err = regmap_read(data->regmap,
+ ISL28022_REG_BUS, &regval);
+ if (err < 0)
+ return err;
+ /* driver supports only 60V mode (BRNG 11) */
+ *val = (long)(((u16)regval) & 0xFFFC);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ case 1:
+ switch (attr) {
+ case hwmon_in_input:
+ err = regmap_read(data->regmap,
+ ISL28022_REG_SHUNT, &regval);
+ if (err < 0)
+ return err;
+ switch (data->gain) {
+ case 8:
+ sign_bit = (regval >> 15) & 0x01;
+ *val = (long)((((u16)regval) & 0x7FFF) -
+ (sign_bit * 32768)) / 100;
+ break;
+ case 4:
+ sign_bit = (regval >> 14) & 0x01;
+ *val = (long)((((u16)regval) & 0x3FFF) -
+ (sign_bit * 16384)) / 100;
+ break;
+ case 2:
+ sign_bit = (regval >> 13) & 0x01;
+ *val = (long)((((u16)regval) & 0x1FFF) -
+ (sign_bit * 8192)) / 100;
+ break;
+ case 1:
+ sign_bit = (regval >> 12) & 0x01;
+ *val = (long)((((u16)regval) & 0x0FFF) -
+ (sign_bit * 4096)) / 100;
+ break;
+ }
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int isl28022_read_current(struct device *dev, u32 attr, long *val)
+{
+ struct isl28022_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int err;
+
+ switch (attr) {
+ case hwmon_curr_input:
+ err = regmap_read(data->regmap,
+ ISL28022_REG_CURRENT, &regval);
+ if (err < 0)
+ return err;
+ *val = ((long)regval * 1250L * (long)data->gain) /
+ (long)data->shunt;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int isl28022_read_power(struct device *dev, u32 attr, long *val)
+{
+ struct isl28022_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int err;
+
+ switch (attr) {
+ case hwmon_power_input:
+ err = regmap_read(data->regmap,
+ ISL28022_REG_POWER, &regval);
+ if (err < 0)
+ return err;
+ *val = ((51200000L * ((long)data->gain)) /
+ (long)data->shunt) * (long)regval;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int isl28022_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_in:
+ return isl28022_read_in(dev, attr, channel, val);
+ case hwmon_curr:
+ return isl28022_read_current(dev, attr, val);
+ case hwmon_power:
+ return isl28022_read_power(dev, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static umode_t isl28022_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_input:
+ return 0444;
+ default:
+ break;
+ }
+ break;
+ case hwmon_curr:
+ switch (attr) {
+ case hwmon_curr_input:
+ return 0444;
+ default:
+ break;
+ }
+ break;
+ case hwmon_power:
+ switch (attr) {
+ case hwmon_power_input:
+ return 0444;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static const struct hwmon_channel_info *isl28022_info[] = {
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT, /* channel 0: bus voltage (mV) */
+ HWMON_I_INPUT), /* channel 1: shunt voltage (mV) */
+ HWMON_CHANNEL_INFO(curr,
+ HWMON_C_INPUT), /* channel 1: current (mA) */
+ HWMON_CHANNEL_INFO(power,
+ HWMON_P_INPUT), /* channel 1: power (µW) */
+ NULL
+};
+
+static const struct hwmon_ops isl28022_hwmon_ops = {
+ .is_visible = isl28022_is_visible,
+ .read = isl28022_read,
+};
+
+static const struct hwmon_chip_info isl28022_chip_info = {
+ .ops = &isl28022_hwmon_ops,
+ .info = isl28022_info,
+};
+
+static bool isl28022_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ISL28022_REG_CONFIG:
+ case ISL28022_REG_CALIB:
+ case ISL28022_REG_SHUNT_THR:
+ case ISL28022_REG_BUS_THR:
+ case ISL28022_REG_INT:
+ case ISL28022_REG_AUX:
+ return true;
+ }
+
+ return false;
+}
+
+static bool isl28022_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ISL28022_REG_CONFIG:
+ case ISL28022_REG_SHUNT:
+ case ISL28022_REG_BUS:
+ case ISL28022_REG_POWER:
+ case ISL28022_REG_CURRENT:
+ case ISL28022_REG_INT:
+ case ISL28022_REG_AUX:
+ return true;
+ }
+ return true;
+}
+
+static const struct regmap_config isl28022_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = ISL28022_REG_MAX,
+ .writeable_reg = isl28022_is_writeable_reg,
+ .volatile_reg = isl28022_is_volatile_reg,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+ .cache_type = REGCACHE_RBTREE,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static int shunt_voltage_show(struct seq_file *seqf, void *unused)
+{
+ struct isl28022_data *data = seqf->private;
+ unsigned int regval;
+ int err;
+
+ err = regmap_read(data->regmap,
+ ISL28022_REG_SHUNT, &regval);
+ if (err)
+ return err;
+
+ /* print shunt voltage in micro volt */
+ seq_printf(seqf, "%d\n", regval * 10);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(shunt_voltage);
+
+static struct dentry *isl28022_debugfs_root;
+
+static void isl28022_debugfs_remove(void *res)
+{
+ debugfs_remove_recursive(res);
+}
+
+static void isl28022_debugfs_init(struct i2c_client *client, struct isl28022_data *data)
+{
+ char name[16];
+ struct dentry *debugfs;
+
+ scnprintf(name, sizeof(name), "%d-%04hx", client->adapter->nr, client->addr);
+
+ debugfs = debugfs_create_dir(name, isl28022_debugfs_root);
+ debugfs_create_file("shunt_voltage", 0444, debugfs, data, &shunt_voltage_fops);
+
+ devm_add_action_or_reset(&client->dev, isl28022_debugfs_remove, debugfs);
+}
+
+/*
+ * read property values and make consistency checks.
+ *
+ * following values for shunt range and resistor are allowed:
+ * 40 mV -> gain 1, shunt min. 800 micro ohms
+ * 80 mV -> gain 2, shunt min. 1600 micro ohms
+ * 160 mV -> gain 4, shunt min. 3200 micro ohms
+ * 320 mV -> gain 8, shunt min. 6400 micro ohms
+ */
+static int isl28022_read_properties(struct device *dev, struct isl28022_data *data)
+{
+ u32 val;
+ int err;
+
+ err = device_property_read_u32(dev, "shunt-resistor-micro-ohms", &val);
+ if (err == -EINVAL)
+ val = 10000;
+ else if (err < 0)
+ return err;
+ data->shunt = val;
+
+ err = device_property_read_u32(dev, "renesas,shunt-range-microvolt", &val);
+ if (err == -EINVAL)
+ val = 320000;
+ else if (err < 0)
+ return err;
+
+ switch (val) {
+ case 40000:
+ data->gain = 1;
+ if (data->shunt < 800)
+ goto shunt_invalid;
+ break;
+ case 80000:
+ data->gain = 2;
+ if (data->shunt < 1600)
+ goto shunt_invalid;
+ break;
+ case 160000:
+ data->gain = 4;
+ if (data->shunt < 3200)
+ goto shunt_invalid;
+ break;
+ case 320000:
+ data->gain = 8;
+ if (data->shunt < 6400)
+ goto shunt_invalid;
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL,
+ "renesas,shunt-range-microvolt invalid value %d\n",
+ val);
+ }
+
+ err = device_property_read_u32(dev, "renesas,average-samples", &val);
+ if (err == -EINVAL)
+ val = 1;
+ else if (err < 0)
+ return err;
+ if (val > 128 || hweight32(val) != 1)
+ return dev_err_probe(dev, -EINVAL,
+ "renesas,average-samples invalid value %d\n",
+ val);
+
+ data->average = val;
+
+ return 0;
+
+shunt_invalid:
+ return dev_err_probe(dev, -EINVAL,
+ "renesas,shunt-resistor-microvolt invalid value %d\n",
+ data->shunt);
+}
+
+/*
+ * write configuration and calibration registers
+ *
+ * The driver supports only shunt and bus continuous ADC mode at 15bit resolution
+ * with averaging from 1 to 128 samples (pow of 2) on both channels.
+ * Shunt voltage gain 1,2,4 or 8 is allowed.
+ * The bus voltage range is 60V fixed.
+ */
+static int isl28022_config(struct isl28022_data *data)
+{
+ int err;
+ u16 config;
+ u16 calib;
+
+ config = (ISL28022_MODE_CONT_SB << ISL28022_MODE_SHIFT) |
+ (ISL28022_BRNG_60 << ISL28022_BRNG_SHIFT) |
+ (__ffs(data->gain) << ISL28022_PG_SHIFT) |
+ ((ISL28022_ADC_15_1 + __ffs(data->average)) << ISL28022_SADC_SHIFT) |
+ ((ISL28022_ADC_15_1 + __ffs(data->average)) << ISL28022_BADC_SHIFT);
+
+ calib = data->shunt ? 0x8000 / data->gain : 0;
+
+ err = regmap_write(data->regmap, ISL28022_REG_CONFIG, config);
+ if (err < 0)
+ return err;
+
+ return regmap_write(data->regmap, ISL28022_REG_CALIB, calib);
+}
+
+static int isl28022_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct isl28022_data *data;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA))
+ return -ENODEV;
+
+ data = devm_kzalloc(dev, sizeof(struct isl28022_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ err = isl28022_read_properties(dev, data);
+ if (err)
+ return err;
+
+ data->regmap = devm_regmap_init_i2c(client, &isl28022_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ err = isl28022_config(data);
+ if (err)
+ return err;
+
+ isl28022_debugfs_init(client, data);
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+ data, &isl28022_chip_info, NULL);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
+
+ return 0;
+}
+
+static const struct i2c_device_id isl28022_ids[] = {
+ { "isl28022", 0},
+ { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, isl28022_ids);
+
+static const struct of_device_id __maybe_unused isl28022_of_match[] = {
+ { .compatible = "renesas,isl28022"},
+ { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(of, isl28022_of_match);
+
+static struct i2c_driver isl28022_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "isl28022",
+ },
+ .probe = isl28022_probe,
+ .id_table = isl28022_ids,
+};
+
+static int __init
+isl28022_init(void)
+{
+ int err;
+
+ isl28022_debugfs_root = debugfs_create_dir("isl28022", NULL);
+ err = i2c_add_driver(&isl28022_driver);
+ if (!err)
+ return 0;
+
+ debugfs_remove_recursive(isl28022_debugfs_root);
+ return err;
+}
+
+static void __exit
+isl28022_exit(void)
+{
+ i2c_del_driver(&isl28022_driver);
+ debugfs_remove_recursive(isl28022_debugfs_root);
+}
+
+module_init(isl28022_init);
+module_exit(isl28022_exit);
+
+MODULE_AUTHOR("Carsten Spieß <mail@carsten-spiess.de>");
+MODULE_DESCRIPTION("ISL28022 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index c459dce496a6..06f0ab2f52fa 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/bitfield.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -19,7 +20,6 @@
#include <linux/hwmon.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/of.h>
#include <linux/regmap.h>
/* Addresses to scan */
@@ -595,20 +595,18 @@ static const struct i2c_device_id jc42_id[] = {
};
MODULE_DEVICE_TABLE(i2c, jc42_id);
-#ifdef CONFIG_OF
static const struct of_device_id jc42_of_ids[] = {
{ .compatible = "jedec,jc-42.4-temp", },
{ }
};
MODULE_DEVICE_TABLE(of, jc42_of_ids);
-#endif
static struct i2c_driver jc42_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "jc42",
.pm = JC42_DEV_PM_OPS,
- .of_match_table = of_match_ptr(jc42_of_ids),
+ .of_match_table = jc42_of_ids,
},
.probe = jc42_probe,
.remove = jc42_remove,
diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
index bb30403f81ca..f0048ff37607 100644
--- a/drivers/hwmon/max197.c
+++ b/drivers/hwmon/max197.c
@@ -332,7 +332,7 @@ static struct platform_driver max197_driver = {
.name = "max197",
},
.probe = max197_probe,
- .remove_new = max197_remove,
+ .remove = max197_remove,
.id_table = max197_device_ids,
};
module_platform_driver(max197_driver);
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index c955b0f3a8d3..32b4d54b2076 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -19,7 +19,6 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/platform_data/max6639.h>
#include <linux/regmap.h>
#include <linux/util_macros.h>
@@ -531,14 +530,49 @@ static int rpm_range_to_reg(int range)
return 1; /* default: 4000 RPM */
}
+static int max6639_probe_child_from_dt(struct i2c_client *client,
+ struct device_node *child,
+ struct max6639_data *data)
+
+{
+ struct device *dev = &client->dev;
+ u32 i;
+ int err, val;
+
+ err = of_property_read_u32(child, "reg", &i);
+ if (err) {
+ dev_err(dev, "missing reg property of %pOFn\n", child);
+ return err;
+ }
+
+ if (i > 1) {
+ dev_err(dev, "Invalid fan index reg %d\n", i);
+ return -EINVAL;
+ }
+
+ err = of_property_read_u32(child, "pulses-per-revolution", &val);
+ if (!err) {
+ if (val < 1 || val > 5) {
+ dev_err(dev, "invalid pulses-per-revolution %d of %pOFn\n", val, child);
+ return -EINVAL;
+ }
+ data->ppr[i] = val;
+ }
+
+ err = of_property_read_u32(child, "max-rpm", &val);
+ if (!err)
+ data->rpm_range[i] = rpm_range_to_reg(val);
+
+ return 0;
+}
+
static int max6639_init_client(struct i2c_client *client,
struct max6639_data *data)
{
- struct max6639_platform_data *max6639_info =
- dev_get_platdata(&client->dev);
- int i;
- int rpm_range = 1; /* default: 4000 RPM */
- int err, ppr;
+ struct device *dev = &client->dev;
+ const struct device_node *np = dev->of_node;
+ struct device_node *child;
+ int i, err;
/* Reset chip to default values, see below for GCONFIG setup */
err = regmap_write(data->regmap, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_POR);
@@ -546,21 +580,29 @@ static int max6639_init_client(struct i2c_client *client,
return err;
/* Fans pulse per revolution is 2 by default */
- if (max6639_info && max6639_info->ppr > 0 &&
- max6639_info->ppr < 5)
- ppr = max6639_info->ppr;
- else
- ppr = 2;
+ data->ppr[0] = 2;
+ data->ppr[1] = 2;
+
+ /* default: 4000 RPM */
+ data->rpm_range[0] = 1;
+ data->rpm_range[1] = 1;
- data->ppr[0] = ppr;
- data->ppr[1] = ppr;
+ for_each_child_of_node(np, child) {
+ if (strcmp(child->name, "fan"))
+ continue;
- if (max6639_info)
- rpm_range = rpm_range_to_reg(max6639_info->rpm_range);
- data->rpm_range[0] = rpm_range;
- data->rpm_range[1] = rpm_range;
+ err = max6639_probe_child_from_dt(client, child, data);
+ if (err) {
+ of_node_put(child);
+ return err;
+ }
+ }
for (i = 0; i < MAX6639_NUM_CHANNELS; i++) {
+ err = regmap_set_bits(data->regmap, MAX6639_REG_OUTPUT_MASK, BIT(1 - i));
+ if (err)
+ return err;
+
/* Set Fan pulse per revolution */
err = max6639_set_ppr(data, i, data->ppr[i]);
if (err)
@@ -573,12 +615,7 @@ static int max6639_init_client(struct i2c_client *client,
return err;
/* Fans PWM polarity high by default */
- if (max6639_info) {
- if (max6639_info->pwm_polarity == 0)
- err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x00);
- else
- err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x02);
- }
+ err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x00);
if (err)
return err;
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index 67471c9cd4d4..66304d48d33a 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -315,7 +315,7 @@ static const struct platform_device_id mc13783_adc_idtable[] = {
MODULE_DEVICE_TABLE(platform, mc13783_adc_idtable);
static struct platform_driver mc13783_adc_driver = {
- .remove_new = mc13783_adc_remove,
+ .remove = mc13783_adc_remove,
.driver = {
.name = DRIVER_NAME,
},
diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c
index 934fed3dd586..ee04795b98aa 100644
--- a/drivers/hwmon/nct6775-core.c
+++ b/drivers/hwmon/nct6775-core.c
@@ -2878,8 +2878,7 @@ store_target_temp(struct device *dev, struct device_attribute *attr,
if (err < 0)
return err;
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
- data->target_temp_mask);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, data->target_temp_mask * 1000), 1000);
mutex_lock(&data->update_lock);
data->target_temp[nr] = val;
@@ -2959,7 +2958,7 @@ store_temp_tolerance(struct device *dev, struct device_attribute *attr,
return err;
/* Limit tolerance as needed */
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, data->tolerance_mask * 1000), 1000);
mutex_lock(&data->update_lock);
data->temp_tolerance[index][nr] = val;
@@ -3085,7 +3084,7 @@ store_weight_temp(struct device *dev, struct device_attribute *attr,
if (err < 0)
return err;
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 255000), 1000);
mutex_lock(&data->update_lock);
data->weight_temp[index][nr] = val;
diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c
index 096f1daa8f2b..1218a3b449a8 100644
--- a/drivers/hwmon/nct6775-platform.c
+++ b/drivers/hwmon/nct6775-platform.c
@@ -1350,6 +1350,8 @@ static const char * const asus_msi_boards[] = {
"Pro H610M-CT D4",
"Pro H610T D4",
"Pro Q670M-C",
+ "Pro WS 600M-CL",
+ "Pro WS 665-ACE",
"Pro WS W680-ACE",
"Pro WS W680-ACE IPMI",
"Pro WS W790-ACE",
diff --git a/drivers/hwmon/nct7363.c b/drivers/hwmon/nct7363.c
new file mode 100644
index 000000000000..be7bf32f6e68
--- /dev/null
+++ b/drivers/hwmon/nct7363.c
@@ -0,0 +1,447 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Nuvoton Technology corporation.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define NCT7363_REG_FUNC_CFG_BASE(x) (0x20 + (x))
+#define NCT7363_REG_LSRS(x) (0x34 + ((x) / 8))
+#define NCT7363_REG_PWMEN_BASE(x) (0x38 + (x))
+#define NCT7363_REG_FANINEN_BASE(x) (0x41 + (x))
+#define NCT7363_REG_FANINX_HVAL(x) (0x48 + ((x) * 2))
+#define NCT7363_REG_FANINX_LVAL(x) (0x49 + ((x) * 2))
+#define NCT7363_REG_FANINX_HL(x) (0x6C + ((x) * 2))
+#define NCT7363_REG_FANINX_LL(x) (0x6D + ((x) * 2))
+#define NCT7363_REG_FSCPXDUTY(x) (0x90 + ((x) * 2))
+#define NCT7363_REG_FSCPXDIV(x) (0x91 + ((x) * 2))
+
+#define PWM_SEL(x) (BIT(0) << ((x) * 2))
+#define FANIN_SEL(_x) ({typeof(_x) (x) = (_x); \
+ BIT(1) << (((x) < 8) ? \
+ (((x) + 8) * 2) : \
+ (((x) % 8) * 2)); })
+#define ALARM_SEL(x, y) ((x) & (BIT((y) % 8)))
+#define VALUE_TO_REG(x, y) (((x) >> ((y) * 8)) & 0xFF)
+
+#define NCT7363_FANINX_LVAL_MASK GENMASK(4, 0)
+#define NCT7363_FANIN_MASK GENMASK(12, 0)
+
+#define NCT7363_PWM_COUNT 16
+
+static inline unsigned int fan_from_reg(u16 val)
+{
+ if (val == NCT7363_FANIN_MASK || val == 0)
+ return 0;
+
+ return (1350000UL / val);
+}
+
+static const struct of_device_id nct7363_of_match[] = {
+ { .compatible = "nuvoton,nct7363", },
+ { .compatible = "nuvoton,nct7362", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, nct7363_of_match);
+
+struct nct7363_data {
+ struct regmap *regmap;
+
+ u16 fanin_mask;
+ u16 pwm_mask;
+};
+
+static int nct7363_read_fan(struct device *dev, u32 attr, int channel,
+ long *val)
+{
+ struct nct7363_data *data = dev_get_drvdata(dev);
+ unsigned int reg;
+ u8 regval[2];
+ int ret;
+ u16 cnt;
+
+ switch (attr) {
+ case hwmon_fan_input:
+ /*
+ * High-byte register should be read first to latch
+ * synchronous low-byte value
+ */
+ ret = regmap_bulk_read(data->regmap,
+ NCT7363_REG_FANINX_HVAL(channel),
+ &regval, 2);
+ if (ret)
+ return ret;
+
+ cnt = (regval[0] << 5) | (regval[1] & NCT7363_FANINX_LVAL_MASK);
+ *val = fan_from_reg(cnt);
+ return 0;
+ case hwmon_fan_min:
+ ret = regmap_bulk_read(data->regmap,
+ NCT7363_REG_FANINX_HL(channel),
+ &regval, 2);
+ if (ret)
+ return ret;
+
+ cnt = (regval[0] << 5) | (regval[1] & NCT7363_FANINX_LVAL_MASK);
+ *val = fan_from_reg(cnt);
+ return 0;
+ case hwmon_fan_alarm:
+ ret = regmap_read(data->regmap,
+ NCT7363_REG_LSRS(channel), &reg);
+ if (ret)
+ return ret;
+
+ *val = (long)ALARM_SEL(reg, channel) > 0 ? 1 : 0;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int nct7363_write_fan(struct device *dev, u32 attr, int channel,
+ long val)
+{
+ struct nct7363_data *data = dev_get_drvdata(dev);
+ u8 regval[2];
+ int ret;
+
+ if (val <= 0)
+ return -EINVAL;
+
+ switch (attr) {
+ case hwmon_fan_min:
+ val = clamp_val(DIV_ROUND_CLOSEST(1350000, val),
+ 1, NCT7363_FANIN_MASK);
+ regval[0] = val >> 5;
+ regval[1] = val & NCT7363_FANINX_LVAL_MASK;
+
+ ret = regmap_bulk_write(data->regmap,
+ NCT7363_REG_FANINX_HL(channel),
+ regval, 2);
+ return ret;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t nct7363_fan_is_visible(const void *_data, u32 attr, int channel)
+{
+ const struct nct7363_data *data = _data;
+
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_alarm:
+ if (data->fanin_mask & BIT(channel))
+ return 0444;
+ break;
+ case hwmon_fan_min:
+ if (data->fanin_mask & BIT(channel))
+ return 0644;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int nct7363_read_pwm(struct device *dev, u32 attr, int channel,
+ long *val)
+{
+ struct nct7363_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int ret;
+
+ switch (attr) {
+ case hwmon_pwm_input:
+ ret = regmap_read(data->regmap,
+ NCT7363_REG_FSCPXDUTY(channel), &regval);
+ if (ret)
+ return ret;
+
+ *val = (long)regval;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int nct7363_write_pwm(struct device *dev, u32 attr, int channel,
+ long val)
+{
+ struct nct7363_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ switch (attr) {
+ case hwmon_pwm_input:
+ if (val < 0 || val > 255)
+ return -EINVAL;
+
+ ret = regmap_write(data->regmap,
+ NCT7363_REG_FSCPXDUTY(channel), val);
+
+ return ret;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t nct7363_pwm_is_visible(const void *_data, u32 attr, int channel)
+{
+ const struct nct7363_data *data = _data;
+
+ switch (attr) {
+ case hwmon_pwm_input:
+ if (data->pwm_mask & BIT(channel))
+ return 0644;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int nct7363_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_fan:
+ return nct7363_read_fan(dev, attr, channel, val);
+ case hwmon_pwm:
+ return nct7363_read_pwm(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int nct7363_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_fan:
+ return nct7363_write_fan(dev, attr, channel, val);
+ case hwmon_pwm:
+ return nct7363_write_pwm(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t nct7363_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_fan:
+ return nct7363_fan_is_visible(data, attr, channel);
+ case hwmon_pwm:
+ return nct7363_pwm_is_visible(data, attr, channel);
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_channel_info *nct7363_info[] = {
+ HWMON_CHANNEL_INFO(fan,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
+ HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT),
+ NULL
+};
+
+static const struct hwmon_ops nct7363_hwmon_ops = {
+ .is_visible = nct7363_is_visible,
+ .read = nct7363_read,
+ .write = nct7363_write,
+};
+
+static const struct hwmon_chip_info nct7363_chip_info = {
+ .ops = &nct7363_hwmon_ops,
+ .info = nct7363_info,
+};
+
+static int nct7363_init_chip(struct nct7363_data *data)
+{
+ u32 func_config = 0;
+ int i, ret;
+
+ /* Pin Function Configuration */
+ for (i = 0; i < NCT7363_PWM_COUNT; i++) {
+ if (data->pwm_mask & BIT(i))
+ func_config |= PWM_SEL(i);
+ if (data->fanin_mask & BIT(i))
+ func_config |= FANIN_SEL(i);
+ }
+
+ for (i = 0; i < 4; i++) {
+ ret = regmap_write(data->regmap, NCT7363_REG_FUNC_CFG_BASE(i),
+ VALUE_TO_REG(func_config, i));
+ if (ret < 0)
+ return ret;
+ }
+
+ /* PWM and FANIN Monitoring Enable */
+ for (i = 0; i < 2; i++) {
+ ret = regmap_write(data->regmap, NCT7363_REG_PWMEN_BASE(i),
+ VALUE_TO_REG(data->pwm_mask, i));
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_write(data->regmap, NCT7363_REG_FANINEN_BASE(i),
+ VALUE_TO_REG(data->fanin_mask, i));
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int nct7363_present_pwm_fanin(struct device *dev,
+ struct device_node *child,
+ struct nct7363_data *data)
+{
+ u8 fanin_ch[NCT7363_PWM_COUNT];
+ struct of_phandle_args args;
+ int ret, fanin_cnt;
+ u8 ch, index;
+
+ ret = of_parse_phandle_with_args(child, "pwms", "#pwm-cells",
+ 0, &args);
+ if (ret)
+ return ret;
+
+ if (args.args[0] >= NCT7363_PWM_COUNT)
+ return -EINVAL;
+ data->pwm_mask |= BIT(args.args[0]);
+
+ fanin_cnt = of_property_count_u8_elems(child, "tach-ch");
+ if (fanin_cnt < 1 || fanin_cnt > NCT7363_PWM_COUNT)
+ return -EINVAL;
+
+ ret = of_property_read_u8_array(child, "tach-ch", fanin_ch, fanin_cnt);
+ if (ret)
+ return ret;
+
+ for (ch = 0; ch < fanin_cnt; ch++) {
+ index = fanin_ch[ch];
+ if (index >= NCT7363_PWM_COUNT)
+ return -EINVAL;
+ data->fanin_mask |= BIT(index);
+ }
+
+ return 0;
+}
+
+static bool nct7363_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case NCT7363_REG_LSRS(0) ... NCT7363_REG_LSRS(15):
+ case NCT7363_REG_FANINX_HVAL(0) ... NCT7363_REG_FANINX_LVAL(15):
+ case NCT7363_REG_FANINX_HL(0) ... NCT7363_REG_FANINX_LL(15):
+ case NCT7363_REG_FSCPXDUTY(0) ... NCT7363_REG_FSCPXDIV(15):
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config nct7363_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .use_single_read = true,
+ .use_single_write = true,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = nct7363_regmap_is_volatile,
+};
+
+static int nct7363_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct device_node *child;
+ struct nct7363_data *data;
+ struct device *hwmon_dev;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->regmap = devm_regmap_init_i2c(client, &nct7363_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ for_each_child_of_node(dev->of_node, child) {
+ ret = nct7363_present_pwm_fanin(dev, child, data);
+ if (ret) {
+ of_node_put(child);
+ return ret;
+ }
+ }
+
+ /* Initialize the chip */
+ ret = nct7363_init_chip(data);
+ if (ret)
+ return ret;
+
+ hwmon_dev =
+ devm_hwmon_device_register_with_info(dev, client->name, data,
+ &nct7363_chip_info, NULL);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static struct i2c_driver nct7363_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "nct7363",
+ .of_match_table = nct7363_of_match,
+ },
+ .probe = nct7363_probe,
+};
+
+module_i2c_driver(nct7363_driver);
+
+MODULE_AUTHOR("CW Ho <cwho@nuvoton.com>");
+MODULE_AUTHOR("Ban Feng <kcfeng0@nuvoton.com>");
+MODULE_DESCRIPTION("NCT7363 Hardware Monitoring Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/nzxt-kraken2.c b/drivers/hwmon/nzxt-kraken2.c
index ed38645a1dc2..034698232758 100644
--- a/drivers/hwmon/nzxt-kraken2.c
+++ b/drivers/hwmon/nzxt-kraken2.c
@@ -35,13 +35,6 @@ struct kraken2_priv_data {
unsigned long updated; /* jiffies */
};
-static umode_t kraken2_is_visible(const void *data,
- enum hwmon_sensor_types type,
- u32 attr, int channel)
-{
- return 0444;
-}
-
static int kraken2_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
@@ -81,7 +74,7 @@ static int kraken2_read_string(struct device *dev, enum hwmon_sensor_types type,
}
static const struct hwmon_ops kraken2_hwmon_ops = {
- .is_visible = kraken2_is_visible,
+ .visible = 0444,
.read = kraken2_read,
.read_string = kraken2_read_string,
};
diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c
index b5993c79c09e..89761a9c8892 100644
--- a/drivers/hwmon/occ/p9_sbe.c
+++ b/drivers/hwmon/occ/p9_sbe.c
@@ -192,8 +192,8 @@ static struct platform_driver p9_sbe_occ_driver = {
.name = "occ-hwmon",
.of_match_table = p9_sbe_occ_of_match,
},
- .probe = p9_sbe_occ_probe,
- .remove_new = p9_sbe_occ_remove,
+ .probe = p9_sbe_occ_probe,
+ .remove = p9_sbe_occ_remove,
};
module_platform_driver(p9_sbe_occ_driver);
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 788b5d58f77e..0f8aa6b42164 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -1606,7 +1606,7 @@ static struct platform_driver pc87360_driver = {
.name = DRIVER_NAME,
},
.probe = pc87360_probe,
- .remove_new = pc87360_remove,
+ .remove = pc87360_remove,
};
/*
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index 7bca04eb4ee4..571402a89368 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -1129,7 +1129,7 @@ static struct platform_driver pc87427_driver = {
.name = DRVNAME,
},
.probe = pc87427_probe,
- .remove_new = pc87427_remove,
+ .remove = pc87427_remove,
};
static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data)
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index a4f02cad92fd..f6d352841953 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -224,9 +224,9 @@ config SENSORS_LTC2978_REGULATOR
depends on SENSORS_LTC2978 && REGULATOR
help
If you say yes here you get regulator support for Linear Technology
- LTC3880, LTC3883, LTC3884, LTC3886, LTC3887, LTC3889, LTC7880,
- LTM4644, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680, LTM4686,
- and LTM4700.
+ LTC3880, LTC3883, LTC3884, LTC3886, LTC3887, LTC3889, LTC7841,
+ LTC7880, LTM4644, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680,
+ LTM4686, and LTM4700.
config SENSORS_LTC3815
tristate "Linear Technologies LTC3815"
diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c
index 7e53fb1d5ea3..97cc951a13a4 100644
--- a/drivers/hwmon/pmbus/isl68137.c
+++ b/drivers/hwmon/pmbus/isl68137.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/string.h>
#include <linux/sysfs.h>
@@ -20,6 +21,7 @@
#define ISL68137_VOUT_AVS 0x30
#define RAA_DMPVR2_READ_VMON 0xc8
+#define MAX_CHANNELS 4
enum chips {
isl68137,
@@ -72,6 +74,17 @@ enum variants {
raa_dmpvr2_hv,
};
+struct isl68137_channel {
+ u32 vout_voltage_divider[2];
+};
+
+struct isl68137_data {
+ struct pmbus_driver_info info;
+ struct isl68137_channel channel[MAX_CHANNELS];
+};
+
+#define to_isl68137_data(x) container_of(x, struct isl68137_data, info)
+
static const struct i2c_device_id raa_dmpvr_id[];
static ssize_t isl68137_avs_enable_show_page(struct i2c_client *client,
@@ -163,13 +176,32 @@ static const struct attribute_group *isl68137_attribute_groups[] = {
static int raa_dmpvr2_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct isl68137_data *data = to_isl68137_data(info);
int ret;
+ u64 temp;
switch (reg) {
case PMBUS_VIRT_READ_VMON:
ret = pmbus_read_word_data(client, page, phase,
RAA_DMPVR2_READ_VMON);
break;
+ case PMBUS_READ_POUT:
+ case PMBUS_READ_VOUT:
+ /*
+ * In cases where a voltage divider is attached to the target
+ * rail between Vout and the Vsense pin, both Vout and Pout
+ * should be scaled by the voltage divider scaling factor.
+ * I.e. Vout = Vsense * Rtotal / Rout
+ */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ if (ret > 0) {
+ temp = DIV_U64_ROUND_CLOSEST((u64)ret *
+ data->channel[page].vout_voltage_divider[1],
+ data->channel[page].vout_voltage_divider[0]);
+ ret = clamp_val(temp, 0, 0xffff);
+ }
+ break;
default:
ret = -ENODATA;
break;
@@ -178,6 +210,40 @@ static int raa_dmpvr2_read_word_data(struct i2c_client *client, int page,
return ret;
}
+static int raa_dmpvr2_write_word_data(struct i2c_client *client, int page,
+ int reg, u16 word)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct isl68137_data *data = to_isl68137_data(info);
+ int ret;
+ u64 temp;
+
+ switch (reg) {
+ case PMBUS_VOUT_MAX:
+ case PMBUS_VOUT_MARGIN_HIGH:
+ case PMBUS_VOUT_MARGIN_LOW:
+ case PMBUS_VOUT_OV_FAULT_LIMIT:
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ case PMBUS_VOUT_COMMAND:
+ /*
+ * In cases where a voltage divider is attached to the target
+ * rail between Vout and the Vsense pin, Vout related PMBus
+ * commands should be scaled based on the expected voltage
+ * at the Vsense pin.
+ * I.e. Vsense = Vout * Rout / Rtotal
+ */
+ temp = DIV_U64_ROUND_CLOSEST((u64)word *
+ data->channel[page].vout_voltage_divider[0],
+ data->channel[page].vout_voltage_divider[1]);
+ ret = clamp_val(temp, 0, 0xffff);
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
static struct pmbus_driver_info raa_dmpvr_info = {
.pages = 3,
.format[PSC_VOLTAGE_IN] = direct,
@@ -220,14 +286,90 @@ static struct pmbus_driver_info raa_dmpvr_info = {
| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
};
+static int isl68137_probe_child_from_dt(struct device *dev,
+ struct device_node *child,
+ struct isl68137_data *data)
+{
+ u32 channel, rout, rtotal;
+ int err;
+
+ err = of_property_read_u32(child, "reg", &channel);
+ if (err) {
+ dev_err(dev, "missing reg property of %pOFn\n", child);
+ return err;
+ }
+ if (channel >= data->info.pages) {
+ dev_err(dev, "invalid reg %d of %pOFn\n", channel, child);
+ return -EINVAL;
+ }
+
+ err = of_property_read_u32_array(child, "vout-voltage-divider",
+ data->channel[channel].vout_voltage_divider,
+ ARRAY_SIZE(data->channel[channel].vout_voltage_divider));
+ if (err && err != -EINVAL) {
+ dev_err(dev,
+ "malformed vout-voltage-divider value for channel %d\n",
+ channel);
+ return err;
+ }
+
+ rout = data->channel[channel].vout_voltage_divider[0];
+ rtotal = data->channel[channel].vout_voltage_divider[1];
+ if (rout == 0) {
+ dev_err(dev,
+ "Voltage divider output resistance must be greater than 0\n");
+ return -EINVAL;
+ }
+ if (rtotal < rout) {
+ dev_err(dev,
+ "Voltage divider total resistance is less than output resistance\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int isl68137_probe_from_dt(struct device *dev,
+ struct isl68137_data *data)
+{
+ const struct device_node *np = dev->of_node;
+ struct device_node *child;
+ int err;
+
+ for_each_child_of_node(np, child) {
+ if (strcmp(child->name, "channel"))
+ continue;
+
+ err = isl68137_probe_child_from_dt(dev, child, data);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int isl68137_probe(struct i2c_client *client)
{
+ struct device *dev = &client->dev;
struct pmbus_driver_info *info;
+ struct isl68137_data *data;
+ int i, err;
- info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
- if (!info)
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
return -ENOMEM;
- memcpy(info, &raa_dmpvr_info, sizeof(*info));
+
+ /*
+ * Initialize all voltage dividers to Rout=1 and Rtotal=1 to simplify
+ * logic in PMBus word read/write functions
+ */
+ for (i = 0; i < MAX_CHANNELS; i++)
+ memset(data->channel[i].vout_voltage_divider,
+ 1,
+ sizeof(data->channel[i].vout_voltage_divider));
+
+ memcpy(&data->info, &raa_dmpvr_info, sizeof(data->info));
+ info = &data->info;
switch (i2c_match_id(raa_dmpvr_id, client)->driver_data) {
case raa_dmpvr1_2rail:
@@ -237,11 +379,14 @@ static int isl68137_probe(struct i2c_client *client)
info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_POUT;
+ info->read_word_data = raa_dmpvr2_read_word_data;
+ info->write_word_data = raa_dmpvr2_write_word_data;
info->groups = isl68137_attribute_groups;
break;
case raa_dmpvr2_1rail:
info->pages = 1;
info->read_word_data = raa_dmpvr2_read_word_data;
+ info->write_word_data = raa_dmpvr2_write_word_data;
break;
case raa_dmpvr2_2rail_nontc:
info->func[0] &= ~PMBUS_HAVE_TEMP3;
@@ -250,9 +395,11 @@ static int isl68137_probe(struct i2c_client *client)
case raa_dmpvr2_2rail:
info->pages = 2;
info->read_word_data = raa_dmpvr2_read_word_data;
+ info->write_word_data = raa_dmpvr2_write_word_data;
break;
case raa_dmpvr2_3rail:
info->read_word_data = raa_dmpvr2_read_word_data;
+ info->write_word_data = raa_dmpvr2_write_word_data;
break;
case raa_dmpvr2_hv:
info->pages = 1;
@@ -263,11 +410,16 @@ static int isl68137_probe(struct i2c_client *client)
info->m[PSC_POWER] = 2;
info->R[PSC_POWER] = -1;
info->read_word_data = raa_dmpvr2_read_word_data;
+ info->write_word_data = raa_dmpvr2_write_word_data;
break;
default:
return -ENODEV;
}
+ err = isl68137_probe_from_dt(dev, data);
+ if (err)
+ return err;
+
return pmbus_do_probe(client, info);
}
@@ -318,11 +470,59 @@ static const struct i2c_device_id raa_dmpvr_id[] = {
MODULE_DEVICE_TABLE(i2c, raa_dmpvr_id);
+static const struct of_device_id isl68137_of_match[] = {
+ { .compatible = "isil,isl68137", .data = (void *)raa_dmpvr1_2rail },
+ { .compatible = "renesas,isl68220", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl68221", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl68222", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl68223", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl68224", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl68225", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl68226", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl68227", .data = (void *)raa_dmpvr2_1rail },
+ { .compatible = "renesas,isl68229", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl68233", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl68239", .data = (void *)raa_dmpvr2_3rail },
+
+ { .compatible = "renesas,isl69222", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69223", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl69224", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69225", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69227", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl69228", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl69234", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69236", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69239", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl69242", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69243", .data = (void *)raa_dmpvr2_1rail },
+ { .compatible = "renesas,isl69247", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69248", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69254", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69255", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69256", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69259", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "isil,isl69260", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,isl69268", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "isil,isl69269", .data = (void *)raa_dmpvr2_3rail },
+ { .compatible = "renesas,isl69298", .data = (void *)raa_dmpvr2_2rail },
+
+ { .compatible = "renesas,raa228000", .data = (void *)raa_dmpvr2_hv },
+ { .compatible = "renesas,raa228004", .data = (void *)raa_dmpvr2_hv },
+ { .compatible = "renesas,raa228006", .data = (void *)raa_dmpvr2_hv },
+ { .compatible = "renesas,raa228228", .data = (void *)raa_dmpvr2_2rail_nontc },
+ { .compatible = "renesas,raa229001", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,raa229004", .data = (void *)raa_dmpvr2_2rail },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, isl68137_of_match);
+
/* This is the driver that will be inserted */
static struct i2c_driver isl68137_driver = {
.driver = {
- .name = "isl68137",
- },
+ .name = "isl68137",
+ .of_match_table = isl68137_of_match,
+ },
.probe = isl68137_probe,
.id_table = raa_dmpvr_id,
};
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 73a86f4d6472..a6eb4d4b5487 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -23,7 +23,8 @@ enum chips {
/* Managers */
ltc2972, ltc2974, ltc2975, ltc2977, ltc2978, ltc2979, ltc2980,
/* Controllers */
- ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7132, ltc7880,
+ ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7132,
+ ltc7841, ltc7880,
/* Modules */
ltm2987, ltm4664, ltm4675, ltm4676, ltm4677, ltm4678, ltm4680, ltm4686,
ltm4700,
@@ -50,7 +51,7 @@ enum chips {
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
-/* LTC3883, LTC3884, LTC3886, LTC3889, LTC7132, LTC7880 */
+/* LTC3883, LTC3884, LTC3886, LTC3889, LTC7132, LTC7841 and LTC7880 only */
#define LTC3883_MFR_IIN_PEAK 0xe1
/* LTC2975 only */
@@ -80,6 +81,7 @@ enum chips {
#define LTC3887_ID 0x4700
#define LTC3889_ID 0x4900
#define LTC7132_ID 0x4CE0
+#define LTC7841_ID 0x40D0
#define LTC7880_ID 0x49E0
#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
#define LTM2987_ID_B 0x8020
@@ -548,6 +550,7 @@ static const struct i2c_device_id ltc2978_id[] = {
{"ltc3887", ltc3887},
{"ltc3889", ltc3889},
{"ltc7132", ltc7132},
+ {"ltc7841", ltc7841},
{"ltc7880", ltc7880},
{"ltm2987", ltm2987},
{"ltm4664", ltm4664},
@@ -654,6 +657,8 @@ static int ltc2978_get_id(struct i2c_client *client)
return ltc3889;
else if (chip_id == LTC7132_ID)
return ltc7132;
+ else if (chip_id == LTC7841_ID)
+ return ltc7841;
else if (chip_id == LTC7880_ID)
return ltc7880;
else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
@@ -854,6 +859,16 @@ static int ltc2978_probe(struct i2c_client *client)
| PMBUS_HAVE_POUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
break;
+ case ltc7841:
+ data->features |= FEAT_CLEAR_PEAKS;
+ info->read_word_data = ltc3883_read_word_data;
+ info->pages = LTC3883_NUM_PAGES;
+ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ break;
default:
return -ENODEV;
}
@@ -907,6 +922,7 @@ static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc3887" },
{ .compatible = "lltc,ltc3889" },
{ .compatible = "lltc,ltc7132" },
+ { .compatible = "lltc,ltc7841" },
{ .compatible = "lltc,ltc7880" },
{ .compatible = "lltc,ltm2987" },
{ .compatible = "lltc,ltm4664" },
diff --git a/drivers/hwmon/pmbus/mp2891.c b/drivers/hwmon/pmbus/mp2891.c
index bb28b15a9103..94ab4ae5fba0 100644
--- a/drivers/hwmon/pmbus/mp2891.c
+++ b/drivers/hwmon/pmbus/mp2891.c
@@ -572,8 +572,8 @@ static int mp2891_probe(struct i2c_client *client)
}
static const struct i2c_device_id mp2891_id[] = {
- {"mp2891", 0},
- {}
+ { "mp2891" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp2891_id);
diff --git a/drivers/hwmon/pmbus/mp2993.c b/drivers/hwmon/pmbus/mp2993.c
index 944593e13231..63691dac2281 100644
--- a/drivers/hwmon/pmbus/mp2993.c
+++ b/drivers/hwmon/pmbus/mp2993.c
@@ -233,8 +233,8 @@ static int mp2993_probe(struct i2c_client *client)
}
static const struct i2c_device_id mp2993_id[] = {
- {"mp2993", 0},
- {}
+ { "mp2993" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp2993_id);
diff --git a/drivers/hwmon/pmbus/mp9941.c b/drivers/hwmon/pmbus/mp9941.c
index 543955cfce67..8ab5fc4d4092 100644
--- a/drivers/hwmon/pmbus/mp9941.c
+++ b/drivers/hwmon/pmbus/mp9941.c
@@ -291,8 +291,8 @@ static int mp9941_probe(struct i2c_client *client)
}
static const struct i2c_device_id mp9941_id[] = {
- {"mp9941", 0},
- {}
+ { "mp9941" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp9941_id);
diff --git a/drivers/hwmon/pmbus/mpq8785.c b/drivers/hwmon/pmbus/mpq8785.c
index 7f87e117b49d..0d16491cd770 100644
--- a/drivers/hwmon/pmbus/mpq8785.c
+++ b/drivers/hwmon/pmbus/mpq8785.c
@@ -22,7 +22,7 @@ static int mpq8785_identify(struct i2c_client *client,
break;
case 1:
case 2:
- info->format[PSC_VOLTAGE_OUT] = direct,
+ info->format[PSC_VOLTAGE_OUT] = direct;
info->m[PSC_VOLTAGE_OUT] = 64;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = 1;
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index ce7fd4ca9d89..a0109296a994 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2719,9 +2719,7 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
* limit registers need to be disabled.
*/
if (!(data->flags & PMBUS_NO_WRITE_PROTECT)) {
- pmbus_wait(client);
- ret = i2c_smbus_read_byte_data(client, PMBUS_WRITE_PROTECT);
- pmbus_update_ts(client, false);
+ ret = _pmbus_read_byte_data(client, -1, PMBUS_WRITE_PROTECT);
if (ret > 0 && (ret & PB_WP_ANY))
data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
@@ -3279,7 +3277,17 @@ static int pmbus_regulator_notify(struct pmbus_data *data, int page, int event)
static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg, u8 val)
{
- return _pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
+ int ret;
+
+ ret = _pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
+
+ /*
+ * Clear fault systematically in case writing PMBUS_SMBALERT_MASK
+ * is not supported by the chip.
+ */
+ pmbus_clear_fault_page(client, page);
+
+ return ret;
}
static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
diff --git a/drivers/hwmon/powerz.c b/drivers/hwmon/powerz.c
index cfb635f94d66..4e663d5b4e33 100644
--- a/drivers/hwmon/powerz.c
+++ b/drivers/hwmon/powerz.c
@@ -54,12 +54,6 @@ static const struct hwmon_channel_info *const powerz_info[] = {
NULL
};
-static umode_t powerz_is_visible(const void *data, enum hwmon_sensor_types type,
- u32 attr, int channel)
-{
- return 0444;
-}
-
static int powerz_read_string(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{
@@ -201,7 +195,7 @@ out:
}
static const struct hwmon_ops powerz_hwmon_ops = {
- .is_visible = powerz_is_visible,
+ .visible = 0444,
.read = powerz_read,
.read_string = powerz_read_string,
};
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index c434db4656e7..53a1a968d00d 100644
--- a/drivers/hwmon/pwm-fan.c
+++ b/drivers/hwmon/pwm-fan.c
@@ -7,6 +7,7 @@
* Author: Kamil Debski <k.debski@samsung.com>
*/
+#include <linux/delay.h>
#include <linux/hwmon.h>
#include <linux/interrupt.h>
#include <linux/mod_devicetable.h>
@@ -60,6 +61,9 @@ struct pwm_fan_ctx {
struct hwmon_chip_info info;
struct hwmon_channel_info fan_channel;
+
+ u64 pwm_duty_cycle_from_stopped;
+ u32 pwm_usec_from_stopped;
};
/* This handler assumes self resetting edge triggered interrupt. */
@@ -199,7 +203,9 @@ static int pwm_fan_power_off(struct pwm_fan_ctx *ctx, bool force_disable)
static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
{
struct pwm_state *state = &ctx->pwm_state;
+ unsigned long final_pwm = pwm;
unsigned long period;
+ bool update = false;
int ret = 0;
if (pwm > 0) {
@@ -208,11 +214,22 @@ static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
return 0;
period = state->period;
- state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
+ update = state->duty_cycle < ctx->pwm_duty_cycle_from_stopped;
+ if (update)
+ state->duty_cycle = ctx->pwm_duty_cycle_from_stopped;
+ else
+ state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
ret = pwm_apply_might_sleep(ctx->pwm, state);
if (ret)
return ret;
ret = pwm_fan_power_on(ctx);
+ if (!ret && update) {
+ pwm = final_pwm;
+ state->duty_cycle = DIV_ROUND_UP(pwm * (period - 1), MAX_PWM);
+ usleep_range(ctx->pwm_usec_from_stopped,
+ ctx->pwm_usec_from_stopped * 2);
+ ret = pwm_apply_might_sleep(ctx->pwm, state);
+ }
} else {
ret = pwm_fan_power_off(ctx, false);
}
@@ -480,6 +497,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
struct device *hwmon;
int ret;
const struct hwmon_channel_info **channels;
+ u32 pwm_min_from_stopped = 0;
u32 *fan_channel_config;
int channel_count = 1; /* We always have a PWM channel. */
int i;
@@ -620,6 +638,19 @@ static int pwm_fan_probe(struct platform_device *pdev)
channels[1] = &ctx->fan_channel;
}
+ ret = of_property_read_u32(dev->of_node, "fan-stop-to-start-percent",
+ &pwm_min_from_stopped);
+ if (!ret && pwm_min_from_stopped) {
+ ctx->pwm_duty_cycle_from_stopped =
+ DIV_ROUND_UP_ULL(pwm_min_from_stopped *
+ (ctx->pwm_state.period - 1),
+ 100);
+ }
+ ret = of_property_read_u32(dev->of_node, "fan-stop-to-start-us",
+ &ctx->pwm_usec_from_stopped);
+ if (ret)
+ ctx->pwm_usec_from_stopped = 250000;
+
ctx->info.ops = &pwm_fan_hwmon_ops;
ctx->info.info = channels;
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
index 65cc52e47db0..10ef1e1f9458 100644
--- a/drivers/hwmon/raspberrypi-hwmon.c
+++ b/drivers/hwmon/raspberrypi-hwmon.c
@@ -81,12 +81,6 @@ static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
return 0;
}
-static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
- u32 attr, int channel)
-{
- return 0444;
-}
-
static const struct hwmon_channel_info * const rpi_info[] = {
HWMON_CHANNEL_INFO(in,
HWMON_I_LCRIT_ALARM),
@@ -94,7 +88,7 @@ static const struct hwmon_channel_info * const rpi_info[] = {
};
static const struct hwmon_ops rpi_hwmon_ops = {
- .is_visible = rpi_is_visible,
+ .visible = 0444,
.read = rpi_read,
};
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
index a4b05ebb0546..d00bd5cc6b15 100644
--- a/drivers/hwmon/sch5636.c
+++ b/drivers/hwmon/sch5636.c
@@ -512,7 +512,7 @@ static struct platform_driver sch5636_driver = {
.name = DRVNAME,
},
.probe = sch5636_probe,
- .remove_new = sch5636_remove,
+ .remove = sch5636_remove,
.id_table = sch5636_device_id,
};
diff --git a/drivers/hwmon/sg2042-mcu.c b/drivers/hwmon/sg2042-mcu.c
index 141045769354..aa3fb773602c 100644
--- a/drivers/hwmon/sg2042-mcu.c
+++ b/drivers/hwmon/sg2042-mcu.c
@@ -346,8 +346,8 @@ static void sg2042_mcu_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id sg2042_mcu_id[] = {
- { "sg2042-hwmon-mcu", 0 },
- {},
+ { "sg2042-hwmon-mcu" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, sg2042_mcu_id);
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 494f9655f44f..3d55047e9baf 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -1051,7 +1051,7 @@ static struct platform_driver sht15_driver = {
.of_match_table = of_match_ptr(sht15_dt_match),
},
.probe = sht15_probe,
- .remove_new = sht15_remove,
+ .remove = sht15_remove,
.id_table = sht15_device_ids,
};
module_platform_driver(sht15_driver);
diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c
index b8916d2735b5..6c9b776237c2 100644
--- a/drivers/hwmon/sht4x.c
+++ b/drivers/hwmon/sht4x.c
@@ -11,6 +11,7 @@
#include <linux/crc8.h>
#include <linux/delay.h>
#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
#include <linux/i2c.h>
#include <linux/jiffies.h>
#include <linux/module.h>
@@ -31,6 +32,12 @@
*/
#define SHT4X_CMD_MEASURE_HPM 0b11111101
#define SHT4X_CMD_RESET 0b10010100
+#define SHT4X_CMD_HEATER_20_1 0b00011110
+#define SHT4X_CMD_HEATER_20_01 0b00010101
+#define SHT4X_CMD_HEATER_110_1 0b00101111
+#define SHT4X_CMD_HEATER_110_01 0b00100100
+#define SHT4X_CMD_HEATER_200_1 0b00111001
+#define SHT4X_CMD_HEATER_200_01 0b00110010
#define SHT4X_CMD_LEN 1
#define SHT4X_CRC8_LEN 1
@@ -49,6 +56,10 @@ DECLARE_CRC8_TABLE(sht4x_crc8_table);
* struct sht4x_data - All the data required to operate an SHT4X chip
* @client: the i2c client associated with the SHT4X
* @lock: a mutex that is used to prevent parallel access to the i2c client
+ * @heating_complete: the time that the last heating finished
+ * @data_pending: true if and only if there are measurements to retrieve after heating
+ * @heater_power: the power at which the heater will be started
+ * @heater_time: the time for which the heater will remain turned on
* @valid: validity of fields below
* @update_interval: the minimum poll interval
* @last_updated: the previous time that the SHT4X was polled
@@ -58,6 +69,10 @@ DECLARE_CRC8_TABLE(sht4x_crc8_table);
struct sht4x_data {
struct i2c_client *client;
struct mutex lock; /* atomic read data updates */
+ unsigned long heating_complete; /* in jiffies */
+ bool data_pending;
+ u32 heater_power; /* in milli-watts */
+ u32 heater_time; /* in milli-seconds */
bool valid; /* validity of fields below */
long update_interval; /* in milli-seconds */
long last_updated; /* in jiffies */
@@ -79,19 +94,30 @@ static int sht4x_read_values(struct sht4x_data *data)
u8 crc;
u8 cmd[SHT4X_CMD_LEN] = {SHT4X_CMD_MEASURE_HPM};
u8 raw_data[SHT4X_RESPONSE_LENGTH];
+ unsigned long curr_jiffies;
mutex_lock(&data->lock);
- next_update = data->last_updated +
- msecs_to_jiffies(data->update_interval);
- if (data->valid && time_before_eq(jiffies, next_update))
- goto unlock;
+ curr_jiffies = jiffies;
+ if (time_before(curr_jiffies, data->heating_complete))
+ msleep(jiffies_to_msecs(data->heating_complete - curr_jiffies));
- ret = i2c_master_send(client, cmd, SHT4X_CMD_LEN);
- if (ret < 0)
- goto unlock;
+ if (data->data_pending &&
+ time_before(jiffies, data->heating_complete + data->update_interval)) {
+ data->data_pending = false;
+ } else {
+ next_update = data->last_updated +
+ msecs_to_jiffies(data->update_interval);
- usleep_range(SHT4X_MEAS_DELAY_HPM, SHT4X_MEAS_DELAY_HPM + SHT4X_DELAY_EXTRA);
+ if (data->valid && time_before_eq(jiffies, next_update))
+ goto unlock;
+
+ ret = i2c_master_send(client, cmd, SHT4X_CMD_LEN);
+ if (ret < 0)
+ goto unlock;
+
+ usleep_range(SHT4X_MEAS_DELAY_HPM, SHT4X_MEAS_DELAY_HPM + SHT4X_DELAY_EXTRA);
+ }
ret = i2c_master_recv(client, raw_data, SHT4X_RESPONSE_LENGTH);
if (ret != SHT4X_RESPONSE_LENGTH) {
@@ -215,6 +241,143 @@ static int sht4x_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
}
}
+static ssize_t heater_enable_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sht4x_data *data = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", time_before(jiffies, data->heating_complete));
+}
+
+static ssize_t heater_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct sht4x_data *data = dev_get_drvdata(dev);
+ bool status;
+ ssize_t ret;
+ u8 cmd;
+ u32 heating_time_bound;
+
+ ret = kstrtobool(buf, &status);
+ if (ret)
+ return ret;
+ if (!status)
+ return -EINVAL;
+
+ if (data->heater_time == 100) {
+ if (data->heater_power == 20)
+ cmd = SHT4X_CMD_HEATER_20_01;
+ else if (data->heater_power == 110)
+ cmd = SHT4X_CMD_HEATER_110_01;
+ else /* data->heater_power == 200 */
+ cmd = SHT4X_CMD_HEATER_200_01;
+
+ heating_time_bound = 110;
+ } else { /* data->heater_time == 1000 */
+ if (data->heater_power == 20)
+ cmd = SHT4X_CMD_HEATER_20_1;
+ else if (data->heater_power == 110)
+ cmd = SHT4X_CMD_HEATER_110_1;
+ else /* data->heater_power == 200 */
+ cmd = SHT4X_CMD_HEATER_200_1;
+
+ heating_time_bound = 1100;
+ }
+
+ mutex_lock(&data->lock);
+
+ if (time_before(jiffies, data->heating_complete)) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ ret = i2c_master_send(data->client, &cmd, SHT4X_CMD_LEN);
+ if (ret < 0)
+ goto unlock;
+
+ data->heating_complete = jiffies + msecs_to_jiffies(heating_time_bound);
+ data->data_pending = true;
+unlock:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+static ssize_t heater_power_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sht4x_data *data = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", data->heater_power);
+}
+
+static ssize_t heater_power_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct sht4x_data *data = dev_get_drvdata(dev);
+ u32 power;
+ ssize_t ret;
+
+ ret = kstrtou32(buf, 10, &power);
+ if (ret)
+ return ret;
+
+ if (power != 20 && power != 110 && power != 200)
+ return -EINVAL;
+
+ data->heater_power = power;
+
+ return count;
+}
+
+static ssize_t heater_time_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sht4x_data *data = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%u\n", data->heater_time);
+}
+
+static ssize_t heater_time_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct sht4x_data *data = dev_get_drvdata(dev);
+ u32 time;
+ ssize_t ret;
+
+ ret = kstrtou32(buf, 10, &time);
+ if (ret)
+ return ret;
+
+ if (time != 100 && time != 1000)
+ return -EINVAL;
+
+ data->heater_time = time;
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(heater_enable);
+static DEVICE_ATTR_RW(heater_power);
+static DEVICE_ATTR_RW(heater_time);
+
+static struct attribute *sht4x_attrs[] = {
+ &dev_attr_heater_enable.attr,
+ &dev_attr_heater_power.attr,
+ &dev_attr_heater_time.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(sht4x);
+
static const struct hwmon_channel_info * const sht4x_info[] = {
HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
@@ -255,6 +418,9 @@ static int sht4x_probe(struct i2c_client *client)
data->update_interval = SHT4X_MIN_POLL_INTERVAL;
data->client = client;
+ data->heater_power = 200;
+ data->heater_time = 1000;
+ data->heating_complete = jiffies;
mutex_init(&data->lock);
@@ -270,7 +436,7 @@ static int sht4x_probe(struct i2c_client *client)
client->name,
data,
&sht4x_chip_info,
- NULL);
+ sht4x_groups);
return PTR_ERR_OR_ZERO(hwmon_dev);
}
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index e73b1522f3ce..b7a7bcd6d3af 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -784,7 +784,7 @@ static struct platform_driver sis5595_driver = {
.name = DRIVER_NAME,
},
.probe = sis5595_probe,
- .remove_new = sis5595_remove,
+ .remove = sis5595_remove,
};
static int sis5595_pci_probe(struct pci_dev *dev,
diff --git a/drivers/hwmon/sl28cpld-hwmon.c b/drivers/hwmon/sl28cpld-hwmon.c
index e020f25c9300..454cc844fb9d 100644
--- a/drivers/hwmon/sl28cpld-hwmon.c
+++ b/drivers/hwmon/sl28cpld-hwmon.c
@@ -23,13 +23,6 @@ struct sl28cpld_hwmon {
u32 offset;
};
-static umode_t sl28cpld_hwmon_is_visible(const void *data,
- enum hwmon_sensor_types type,
- u32 attr, int channel)
-{
- return 0444;
-}
-
static int sl28cpld_hwmon_read(struct device *dev,
enum hwmon_sensor_types type, u32 attr,
int channel, long *input)
@@ -73,7 +66,7 @@ static const struct hwmon_channel_info * const sl28cpld_hwmon_info[] = {
};
static const struct hwmon_ops sl28cpld_hwmon_ops = {
- .is_visible = sl28cpld_hwmon_is_visible,
+ .visible = 0444,
.read = sl28cpld_hwmon_read,
};
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 0d46edbcb144..595bceb78d76 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -858,7 +858,7 @@ static struct platform_driver smsc47m1_driver __refdata = {
.driver = {
.name = DRVNAME,
},
- .remove_new = __exit_p(smsc47m1_remove),
+ .remove = __exit_p(smsc47m1_remove),
};
static int __init smsc47m1_device_add(unsigned short address,
diff --git a/drivers/hwmon/spd5118.c b/drivers/hwmon/spd5118.c
index fcbce5a01e55..6cee48a3e5c3 100644
--- a/drivers/hwmon/spd5118.c
+++ b/drivers/hwmon/spd5118.c
@@ -671,7 +671,7 @@ static int spd5118_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(spd5118_pm_ops, spd5118_suspend, spd5118_resume);
static const struct i2c_device_id spd5118_id[] = {
- { "spd5118", 0 },
+ { "spd5118" },
{ }
};
MODULE_DEVICE_TABLE(i2c, spd5118_id);
diff --git a/drivers/hwmon/surface_fan.c b/drivers/hwmon/surface_fan.c
index de3c5a2409c6..aafb4ac92e6c 100644
--- a/drivers/hwmon/surface_fan.c
+++ b/drivers/hwmon/surface_fan.c
@@ -18,14 +18,6 @@ SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_fan_rpm_get, __le16, {
.command_id = 0x01,
});
-// hwmon
-static umode_t surface_fan_hwmon_is_visible(const void *drvdata,
- enum hwmon_sensor_types type, u32 attr,
- int channel)
-{
- return 0444;
-}
-
static int surface_fan_hwmon_read(struct device *dev,
enum hwmon_sensor_types type, u32 attr,
int channel, long *val)
@@ -49,7 +41,7 @@ static const struct hwmon_channel_info *const surface_fan_info[] = {
};
static const struct hwmon_ops surface_fan_hwmon_ops = {
- .is_visible = surface_fan_hwmon_is_visible,
+ .visible = 0444,
.read = surface_fan_hwmon_read,
};
diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c
index a82bbc959eb1..fbe673009126 100644
--- a/drivers/hwmon/tmp108.c
+++ b/drivers/hwmon/tmp108.c
@@ -13,6 +13,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/i2c.h>
+#include <linux/i3c/device.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/regmap.h>
@@ -323,33 +324,19 @@ static const struct regmap_config tmp108_regmap_config = {
.use_single_write = true,
};
-static int tmp108_probe(struct i2c_client *client)
+static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *name)
{
- struct device *dev = &client->dev;
struct device *hwmon_dev;
struct tmp108 *tmp108;
- int err;
u32 config;
-
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WORD_DATA)) {
- dev_err(dev,
- "adapter doesn't support SMBus word transactions\n");
- return -ENODEV;
- }
+ int err;
tmp108 = devm_kzalloc(dev, sizeof(*tmp108), GFP_KERNEL);
if (!tmp108)
return -ENOMEM;
dev_set_drvdata(dev, tmp108);
-
- tmp108->regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config);
- if (IS_ERR(tmp108->regmap)) {
- err = PTR_ERR(tmp108->regmap);
- dev_err(dev, "regmap init failed: %d", err);
- return err;
- }
+ tmp108->regmap = regmap;
err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config);
if (err < 0) {
@@ -383,13 +370,30 @@ static int tmp108_probe(struct i2c_client *client)
return err;
}
- hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, name,
tmp108,
&tmp108_chip_info,
NULL);
return PTR_ERR_OR_ZERO(hwmon_dev);
}
+static int tmp108_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct regmap *regmap;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WORD_DATA))
+ return dev_err_probe(dev, -ENODEV,
+ "adapter doesn't support SMBus word transactions\n");
+
+ regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap), "regmap init failed");
+
+ return tmp108_common_probe(dev, regmap, client->name);
+}
+
static int tmp108_suspend(struct device *dev)
{
struct tmp108 *tmp108 = dev_get_drvdata(dev);
@@ -420,6 +424,7 @@ MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids);
#ifdef CONFIG_OF
static const struct of_device_id tmp108_of_ids[] = {
+ { .compatible = "nxp,p3t1085", },
{ .compatible = "ti,tmp108", },
{}
};
@@ -436,7 +441,34 @@ static struct i2c_driver tmp108_driver = {
.id_table = tmp108_i2c_ids,
};
-module_i2c_driver(tmp108_driver);
+static const struct i3c_device_id p3t1085_i3c_ids[] = {
+ I3C_DEVICE(0x011b, 0x1529, NULL),
+ {}
+};
+MODULE_DEVICE_TABLE(i3c, p3t1085_i3c_ids);
+
+static int p3t1085_i3c_probe(struct i3c_device *i3cdev)
+{
+ struct device *dev = i3cdev_to_dev(i3cdev);
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_i3c(i3cdev, &tmp108_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to register i3c regmap\n");
+
+ return tmp108_common_probe(dev, regmap, "p3t1085_i3c");
+}
+
+static struct i3c_driver p3t1085_driver = {
+ .driver = {
+ .name = "p3t1085_i3c",
+ },
+ .probe = p3t1085_i3c_probe,
+ .id_table = p3t1085_i3c_ids,
+};
+
+module_i3c_i2c_driver(p3t1085_driver, &tmp108_driver)
MODULE_AUTHOR("John Muir <john@jmuir.com>");
MODULE_DESCRIPTION("Texas Instruments TMP108 temperature sensor driver");
diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c
index dfcfb09d9f3c..80fb03f30c30 100644
--- a/drivers/hwmon/tps23861.c
+++ b/drivers/hwmon/tps23861.c
@@ -132,7 +132,7 @@ static int tps23861_read_temp(struct tps23861_data *data, long *val)
if (err < 0)
return err;
- *val = (regval * TEMPERATURE_LSB) - 20000;
+ *val = ((long)regval * TEMPERATURE_LSB) - 20000;
return 0;
}
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
index 2765d5f1b7f0..e4f1bb538628 100644
--- a/drivers/hwmon/ultra45_env.c
+++ b/drivers/hwmon/ultra45_env.c
@@ -317,7 +317,7 @@ static struct platform_driver env_driver = {
.of_match_table = env_match,
},
.probe = env_probe,
- .remove_new = env_remove,
+ .remove = env_remove,
};
module_platform_driver(env_driver);
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 5abe95b683c0..823bff2871e1 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -197,7 +197,7 @@ static struct platform_driver via_cputemp_driver = {
.name = DRVNAME,
},
.probe = via_cputemp_probe,
- .remove_new = via_cputemp_remove,
+ .remove = via_cputemp_remove,
};
struct pdev_entry {
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 3a002ad3c005..bbaeb808cc15 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -799,7 +799,7 @@ static struct platform_driver via686a_driver = {
.name = DRIVER_NAME,
},
.probe = via686a_probe,
- .remove_new = via686a_remove,
+ .remove = via686a_remove,
};
static const struct pci_device_id via686a_pci_ids[] = {
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index 2f3890463e18..386edea6b69e 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -1221,7 +1221,7 @@ static struct platform_driver vt1211_driver = {
.name = DRVNAME,
},
.probe = vt1211_probe,
- .remove_new = vt1211_remove,
+ .remove = vt1211_remove,
};
static int __init vt1211_device_add(unsigned short address)
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index dcdd14ccd115..3bf27c21845b 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -910,11 +910,11 @@ static void vt8231_remove(struct platform_device *pdev)
static struct platform_driver vt8231_driver = {
- .driver = {
+ .driver = {
.name = DRIVER_NAME,
},
.probe = vt8231_probe,
- .remove_new = vt8231_remove,
+ .remove = vt8231_remove,
};
static const struct pci_device_id vt8231_pci_ids[] = {
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 2fc9b718e2ab..95115d7b863e 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -1844,7 +1844,7 @@ static struct platform_driver w83627hf_driver = {
.pm = W83627HF_DEV_PM_OPS,
},
.probe = w83627hf_probe,
- .remove_new = w83627hf_remove,
+ .remove = w83627hf_remove,
};
static int __init w83627hf_find(int sioaddr, unsigned short *addr,
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index b7957c84d235..076200ed2ec9 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1828,7 +1828,7 @@ static struct platform_driver w83781d_isa_driver = {
.name = "w83781d",
},
.probe = w83781d_isa_probe,
- .remove_new = w83781d_isa_remove,
+ .remove = w83781d_isa_remove,
};
/* return 1 if a supported chip is found, 0 otherwise */
diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
index 5e0759a70f6d..1e3bd129a922 100644
--- a/drivers/hwmon/xgene-hwmon.c
+++ b/drivers/hwmon/xgene-hwmon.c
@@ -772,7 +772,7 @@ MODULE_DEVICE_TABLE(of, xgene_hwmon_of_match);
static struct platform_driver xgene_hwmon_driver = {
.probe = xgene_hwmon_probe,
- .remove_new = xgene_hwmon_remove,
+ .remove = xgene_hwmon_remove,
.driver = {
.name = "xgene-slimpro-hwmon",
.of_match_table = xgene_hwmon_of_match,
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
index 0d7b9839e5b6..e9d8d28e055f 100644
--- a/drivers/hwtracing/intel_th/pci.c
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -23,7 +23,6 @@ enum {
TH_PCI_RTIT_BAR = 4,
};
-#define BAR_MASK (BIT(TH_PCI_CONFIG_BAR) | BIT(TH_PCI_STH_SW_BAR))
#define PCI_REG_NPKDSC 0x80
#define NPKDSC_TSACT BIT(5)
@@ -83,10 +82,16 @@ static int intel_th_pci_probe(struct pci_dev *pdev,
if (err)
return err;
- err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME);
+ err = pcim_request_all_regions(pdev, DRIVER_NAME);
if (err)
return err;
+ if (!pcim_iomap(pdev, TH_PCI_CONFIG_BAR, 0))
+ return -ENOMEM;
+
+ if (!pcim_iomap(pdev, TH_PCI_STH_SW_BAR, 0))
+ return -ENOMEM;
+
if (pdev->resource[TH_PCI_RTIT_BAR].start) {
resource[TH_MMIO_RTIT] = pdev->resource[TH_PCI_RTIT_BAR];
r++;
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 3f71ce4711e3..d27de18de46f 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -5,10 +5,11 @@
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
obj-$(CONFIG_I2C) += i2c-core.o
-i2c-core-objs := i2c-core-base.o i2c-core-smbus.o
+i2c-core-y := i2c-core-base.o i2c-core-smbus.o
i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o
-i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o
-i2c-core-$(CONFIG_OF) += i2c-core-of.o
+i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o
+i2c-core-$(CONFIG_OF) += i2c-core-of.o
+i2c-core-$(CONFIG_OF_DYNAMIC) += i2c-core-of-prober.o
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 6b3ba7e5723a..ceb3ecdf884b 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -62,19 +62,6 @@ config I2C_AMD756
This driver can also be built as a module. If so, the module
will be called i2c-amd756.
-config I2C_AMD756_S4882
- tristate "SMBus multiplexing on the Tyan S4882"
- depends on I2C_AMD756 && X86
- help
- Enabling this option will add specific SMBus support for the Tyan
- S4882 motherboard. On this 4-CPU board, the SMBus is multiplexed
- over 8 different channels, where the various memory module EEPROMs
- and temperature sensors live. Saying yes here will give you access
- to these in addition to the trunk.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-amd756-s4882.
-
config I2C_AMD8111
tristate "AMD 8111"
depends on PCI && HAS_IOPORT
@@ -95,6 +82,23 @@ config I2C_AMD_MP2
This driver can also be built as modules. If so, the modules will
be called i2c-amd-mp2-pci and i2c-amd-mp2-plat.
+config I2C_AMD_ASF
+ tristate "AMD ASF I2C Controller Support"
+ depends on I2C_PIIX4
+ select I2C_SLAVE
+ help
+ This option enables support for the AMD ASF (Alert Standard Format)
+ I2C controller. The AMD ASF controller is an SMBus controller with
+ built-in ASF functionality, allowing it to issue generic SMBus
+ packets and communicate with the DASH controller using MCTP over
+ ASF.
+
+ If you have an AMD system with ASF support and want to enable this
+ functionality, say Y or M here. If unsure, say N.
+
+ To compile this driver as a module, choose M here: the module will
+ be called i2c_amd_asf_plat.
+
config I2C_HIX5HD2
tristate "Hix5hd2 high-speed I2C driver"
depends on ARCH_HISI || ARCH_HIX5HD2 || COMPILE_TEST
@@ -160,6 +164,7 @@ config I2C_I801
Meteor Lake (SOC and PCH)
Birch Stream (SOC)
Arrow Lake (SOC)
+ Panther Lake (SOC)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
@@ -250,19 +255,6 @@ config I2C_NFORCE2
This driver can also be built as a module. If so, the module
will be called i2c-nforce2.
-config I2C_NFORCE2_S4985
- tristate "SMBus multiplexing on the Tyan S4985"
- depends on I2C_NFORCE2 && X86
- help
- Enabling this option will add specific SMBus support for the Tyan
- S4985 motherboard. On this 4-CPU board, the SMBus is multiplexed
- over 4 different channels, where the various memory module EEPROMs
- live. Saying yes here will give you access to these in addition
- to the trunk.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-nforce2-s4985.
-
config I2C_NVIDIA_GPU
tristate "NVIDIA GPU I2C controller"
depends on PCI
@@ -439,7 +431,7 @@ config I2C_AT91
are facing this situation, use the i2c-gpio driver.
config I2C_AT91_SLAVE_EXPERIMENTAL
- tristate "Microchip AT91 I2C experimental slave mode"
+ bool "Microchip AT91 I2C experimental slave mode"
depends on I2C_AT91
select I2C_SLAVE
help
@@ -448,7 +440,7 @@ config I2C_AT91_SLAVE_EXPERIMENTAL
been tested in a heavy way, help wanted.
There are known bugs:
- It can hang, on a SAMA5D4, after several transfers.
- - There are some mismtaches with a SAMA5D4 as slave and a SAMA5D2 as
+ - There are some mismatches with a SAMA5D4 as slave and a SAMA5D2 as
master.
config I2C_AU1550
@@ -535,6 +527,16 @@ config I2C_CBUS_GPIO
This driver can also be built as a module. If so, the module
will be called i2c-cbus-gpio.
+config I2C_CGBC
+ tristate "Congatec I2C Controller"
+ depends on MFD_CGBC
+ help
+ This driver supports the 2 I2C interfaces on the Congatec Board
+ Controller.
+
+ This driver can also be built as a module. If so, the module will
+ be called i2c-cgbc.ko.
+
config I2C_CPM
tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
depends on CPM1 || CPM2
@@ -741,13 +743,14 @@ config I2C_IMG
config I2C_IMX
tristate "IMX I2C interface"
- depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE || COMPILE_TEST
+ depends on ARCH_MXC || ARCH_LAYERSCAPE || ARCH_S32 || COLDFIRE \
+ || COMPILE_TEST
select I2C_SLAVE
help
Say Y here if you want to use the IIC bus controller on
- the Freescale i.MX/MXC, Layerscape or ColdFire processors.
+ the Freescale i.MX/MXC/S32G, Layerscape or ColdFire processors.
- This driver can also be built as a module. If so, the module
+ This driver can also be built as a module. If so, the module
will be called i2c-imx.
config I2C_IMX_LPI2C
@@ -1060,6 +1063,16 @@ config I2C_RK3X
This driver can also be built as a module. If so, the module will
be called i2c-rk3x.
+config I2C_RTL9300
+ tristate "Realtek RTL9300 I2C controller"
+ depends on MACH_REALTEK_RTL || COMPILE_TEST
+ help
+ Say Y here to include support for the I2C controller in Realtek
+ RTL9300 SoCs.
+
+ This driver can also be built as a module. If so, the module will
+ be called i2c-rtl9300.
+
config I2C_RZV2M
tristate "Renesas RZ/V2M adapter"
depends on ARCH_RENESAS || COMPILE_TEST
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index ecc07c50f2a0..1c2a4510abe4 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -14,14 +14,12 @@ obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o
obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o
obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
-obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
-obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o
obj-$(CONFIG_I2C_NVIDIA_GPU) += i2c-nvidia-gpu.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
@@ -38,18 +36,18 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
# Embedded system I2C/SMBus host controller drivers
obj-$(CONFIG_I2C_ALTERA) += i2c-altera.o
obj-$(CONFIG_I2C_AMD_MP2) += i2c-amd-mp2-pci.o i2c-amd-mp2-plat.o
+obj-$(CONFIG_I2C_AMD_ASF) += i2c-amd-asf-plat.o
obj-$(CONFIG_I2C_ASPEED) += i2c-aspeed.o
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
-i2c-at91-objs := i2c-at91-core.o i2c-at91-master.o
-ifeq ($(CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL),y)
- i2c-at91-objs += i2c-at91-slave.o
-endif
+i2c-at91-y := i2c-at91-core.o i2c-at91-master.o
+i2c-at91-$(CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL) += i2c-at91-slave.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_AXXIA) += i2c-axxia.o
obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o
obj-$(CONFIG_I2C_BCM_IPROC) += i2c-bcm-iproc.o
obj-$(CONFIG_I2C_CADENCE) += i2c-cadence.o
obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
+obj-$(CONFIG_I2C_CGBC) += i2c-cgbc.o
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o
@@ -103,6 +101,7 @@ obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-geni.o
obj-$(CONFIG_I2C_QUP) += i2c-qup.o
obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
+obj-$(CONFIG_I2C_RTL9300) += i2c-rtl9300.o
obj-$(CONFIG_I2C_RZV2M) += i2c-rzv2m.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
@@ -111,8 +110,8 @@ obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o
obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
-i2c-stm32f7-drv-objs := i2c-stm32f7.o i2c-stm32.o
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7-drv.o
+i2c-stm32f7-drv-y := i2c-stm32f7.o i2c-stm32.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
@@ -121,10 +120,10 @@ obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_WMT) += i2c-viai2c-wmt.o i2c-viai2c-common.o
-i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
-i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o
+i2c-octeon-y := i2c-octeon-core.o i2c-octeon-platdrv.o
obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o
+i2c-thunderx-y := i2c-octeon-core.o i2c-thunderx-pcidrv.o
obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o
obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
diff --git a/drivers/i2c/busses/i2c-altera.c b/drivers/i2c/busses/i2c-altera.c
index f4dde08a3b92..2da73173ce24 100644
--- a/drivers/i2c/busses/i2c-altera.c
+++ b/drivers/i2c/busses/i2c-altera.c
@@ -482,7 +482,7 @@ MODULE_DEVICE_TABLE(of, altr_i2c_of_match);
static struct platform_driver altr_i2c_driver = {
.probe = altr_i2c_probe,
- .remove_new = altr_i2c_remove,
+ .remove = altr_i2c_remove,
.driver = {
.name = "altera-i2c",
.of_match_table = altr_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-amd-asf-plat.c b/drivers/i2c/busses/i2c-amd-asf-plat.c
new file mode 100644
index 000000000000..ba47df5370c7
--- /dev/null
+++ b/drivers/i2c/busses/i2c-amd-asf-plat.c
@@ -0,0 +1,369 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD Alert Standard Format Platform Driver
+ *
+ * Copyright (c) 2024, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ * Sanket Goswami <Sanket.Goswami@amd.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/devm-helpers.h>
+#include <linux/errno.h>
+#include <linux/gfp_types.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/sprintf.h>
+
+#include "i2c-piix4.h"
+
+/* ASF register bits */
+#define ASF_SLV_LISTN 0
+#define ASF_SLV_INTR 1
+#define ASF_SLV_RST 4
+#define ASF_PEC_SP 5
+#define ASF_DATA_EN 7
+#define ASF_MSTR_EN 16
+#define ASF_CLK_EN 17
+
+/* ASF address offsets */
+#define ASFINDEX (0x07 + piix4_smba)
+#define ASFLISADDR (0x09 + piix4_smba)
+#define ASFSTA (0x0A + piix4_smba)
+#define ASFSLVSTA (0x0D + piix4_smba)
+#define ASFDATARWPTR (0x11 + piix4_smba)
+#define ASFSETDATARDPTR (0x12 + piix4_smba)
+#define ASFDATABNKSEL (0x13 + piix4_smba)
+#define ASFSLVEN (0x15 + piix4_smba)
+
+#define ASF_BLOCK_MAX_BYTES 72
+#define ASF_ERROR_STATUS GENMASK(3, 1)
+
+struct amd_asf_dev {
+ struct i2c_adapter adap;
+ void __iomem *eoi_base;
+ struct i2c_client *target;
+ struct delayed_work work_buf;
+ struct sb800_mmio_cfg mmio_cfg;
+ struct resource *port_addr;
+};
+
+static void amd_asf_process_target(struct work_struct *work)
+{
+ struct amd_asf_dev *dev = container_of(work, struct amd_asf_dev, work_buf.work);
+ unsigned short piix4_smba = dev->port_addr->start;
+ u8 data[ASF_BLOCK_MAX_BYTES];
+ u8 bank, reg, cmd;
+ u8 len = 0, idx, val;
+
+ /* Read target status register */
+ reg = inb_p(ASFSLVSTA);
+
+ /* Check if no error bits are set in target status register */
+ if (reg & ASF_ERROR_STATUS) {
+ /* Set bank as full */
+ cmd = 0;
+ reg |= GENMASK(3, 2);
+ outb_p(reg, ASFDATABNKSEL);
+ } else {
+ /* Read data bank */
+ reg = inb_p(ASFDATABNKSEL);
+ bank = (reg & BIT(3)) ? 1 : 0;
+
+ /* Set read data bank */
+ if (bank) {
+ reg |= BIT(4);
+ reg &= ~BIT(3);
+ } else {
+ reg &= ~BIT(4);
+ reg &= ~BIT(2);
+ }
+
+ /* Read command register */
+ outb_p(reg, ASFDATABNKSEL);
+ cmd = inb_p(ASFINDEX);
+ len = inb_p(ASFDATARWPTR);
+ for (idx = 0; idx < len; idx++)
+ data[idx] = inb_p(ASFINDEX);
+
+ /* Clear data bank status */
+ if (bank) {
+ reg |= BIT(3);
+ outb_p(reg, ASFDATABNKSEL);
+ } else {
+ reg |= BIT(2);
+ outb_p(reg, ASFDATABNKSEL);
+ }
+ }
+
+ outb_p(0, ASFSETDATARDPTR);
+ if (cmd & BIT(0))
+ return;
+
+ /*
+ * Although i2c_slave_event() returns an appropriate error code, we
+ * don't check it here because we're operating in the workqueue context.
+ */
+ i2c_slave_event(dev->target, I2C_SLAVE_WRITE_REQUESTED, &val);
+ for (idx = 0; idx < len; idx++) {
+ val = data[idx];
+ i2c_slave_event(dev->target, I2C_SLAVE_WRITE_RECEIVED, &val);
+ }
+ i2c_slave_event(dev->target, I2C_SLAVE_STOP, &val);
+}
+
+static void amd_asf_update_ioport_target(unsigned short piix4_smba, u8 bit,
+ unsigned long offset, bool set)
+{
+ unsigned long reg;
+
+ reg = inb_p(offset);
+ __assign_bit(bit, &reg, set);
+ outb_p(reg, offset);
+}
+
+static void amd_asf_update_mmio_target(struct amd_asf_dev *dev, u8 bit, bool set)
+{
+ unsigned long reg;
+
+ reg = ioread32(dev->mmio_cfg.addr);
+ __assign_bit(bit, &reg, set);
+ iowrite32(reg, dev->mmio_cfg.addr);
+}
+
+static void amd_asf_setup_target(struct amd_asf_dev *dev)
+{
+ unsigned short piix4_smba = dev->port_addr->start;
+
+ /* Reset both host and target before setting up */
+ outb_p(0, SMBHSTSTS);
+ outb_p(0, ASFSLVSTA);
+ outb_p(0, ASFSTA);
+
+ /* Update target address */
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_LISTN, ASFLISADDR, true);
+ /* Enable target and set the clock */
+ amd_asf_update_mmio_target(dev, ASF_MSTR_EN, false);
+ amd_asf_update_mmio_target(dev, ASF_CLK_EN, true);
+ /* Enable target interrupt */
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_INTR, ASFSLVEN, true);
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_RST, ASFSLVEN, false);
+ /* Enable PEC and PEC append */
+ amd_asf_update_ioport_target(piix4_smba, ASF_DATA_EN, SMBHSTCNT, true);
+ amd_asf_update_ioport_target(piix4_smba, ASF_PEC_SP, SMBHSTCNT, true);
+}
+
+static int amd_asf_access(struct i2c_adapter *adap, u16 addr, u8 command, u8 *data)
+{
+ struct amd_asf_dev *dev = i2c_get_adapdata(adap);
+ unsigned short piix4_smba = dev->port_addr->start;
+ u8 i, len;
+
+ outb_p((addr << 1), SMBHSTADD);
+ outb_p(command, SMBHSTCMD);
+ len = data[0];
+ if (len == 0 || len > ASF_BLOCK_MAX_BYTES)
+ return -EINVAL;
+
+ outb_p(len, SMBHSTDAT0);
+ /* Reset SMBBLKDAT */
+ inb_p(SMBHSTCNT);
+ for (i = 1; i <= len; i++)
+ outb_p(data[i], SMBBLKDAT);
+
+ outb_p(PIIX4_BLOCK_DATA, SMBHSTCNT);
+ /* Enable PEC and PEC append */
+ amd_asf_update_ioport_target(piix4_smba, ASF_DATA_EN, SMBHSTCNT, true);
+ amd_asf_update_ioport_target(piix4_smba, ASF_PEC_SP, SMBHSTCNT, true);
+
+ return piix4_transaction(adap, piix4_smba);
+}
+
+static int amd_asf_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct amd_asf_dev *dev = i2c_get_adapdata(adap);
+ unsigned short piix4_smba = dev->port_addr->start;
+ u8 asf_data[ASF_BLOCK_MAX_BYTES];
+ struct i2c_msg *dev_msgs = msgs;
+ u8 prev_port;
+ int ret;
+
+ if (msgs->flags & I2C_M_RD) {
+ dev_err(&adap->dev, "ASF: Read not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* Exclude the receive header and PEC */
+ if (msgs->len > ASF_BLOCK_MAX_BYTES - 3) {
+ dev_warn(&adap->dev, "ASF: max message length exceeded\n");
+ return -EOPNOTSUPP;
+ }
+
+ asf_data[0] = dev_msgs->len;
+ memcpy(asf_data + 1, dev_msgs[0].buf, dev_msgs->len);
+
+ ret = piix4_sb800_region_request(&adap->dev, &dev->mmio_cfg);
+ if (ret)
+ return ret;
+
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_RST, ASFSLVEN, true);
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_LISTN, ASFLISADDR, false);
+ /* Clear ASF target status */
+ outb_p(0, ASFSLVSTA);
+
+ /* Enable ASF SMBus controller function */
+ amd_asf_update_mmio_target(dev, ASF_MSTR_EN, true);
+ prev_port = piix4_sb800_port_sel(0, &dev->mmio_cfg);
+ ret = amd_asf_access(adap, msgs->addr, msgs[0].buf[0], asf_data);
+ piix4_sb800_port_sel(prev_port, &dev->mmio_cfg);
+ amd_asf_setup_target(dev);
+ piix4_sb800_region_release(&adap->dev, &dev->mmio_cfg);
+ return ret;
+}
+
+static int amd_asf_reg_target(struct i2c_client *target)
+{
+ struct amd_asf_dev *dev = i2c_get_adapdata(target->adapter);
+ unsigned short piix4_smba = dev->port_addr->start;
+ int ret;
+ u8 reg;
+
+ if (dev->target)
+ return -EBUSY;
+
+ ret = piix4_sb800_region_request(&target->dev, &dev->mmio_cfg);
+ if (ret)
+ return ret;
+
+ reg = (target->addr << 1) | I2C_M_RD;
+ outb_p(reg, ASFLISADDR);
+
+ amd_asf_setup_target(dev);
+ dev->target = target;
+ amd_asf_update_ioport_target(piix4_smba, ASF_DATA_EN, ASFDATABNKSEL, false);
+ piix4_sb800_region_release(&target->dev, &dev->mmio_cfg);
+
+ return 0;
+}
+
+static int amd_asf_unreg_target(struct i2c_client *target)
+{
+ struct amd_asf_dev *dev = i2c_get_adapdata(target->adapter);
+ unsigned short piix4_smba = dev->port_addr->start;
+
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_INTR, ASFSLVEN, false);
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_RST, ASFSLVEN, true);
+ dev->target = NULL;
+
+ return 0;
+}
+
+static u32 amd_asf_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_PEC | I2C_FUNC_SLAVE;
+}
+
+static const struct i2c_algorithm amd_asf_smbus_algorithm = {
+ .master_xfer = amd_asf_xfer,
+ .reg_slave = amd_asf_reg_target,
+ .unreg_slave = amd_asf_unreg_target,
+ .functionality = amd_asf_func,
+};
+
+static irqreturn_t amd_asf_irq_handler(int irq, void *ptr)
+{
+ struct amd_asf_dev *dev = ptr;
+ unsigned short piix4_smba = dev->port_addr->start;
+ u8 target_int = inb_p(ASFSTA);
+
+ if (target_int & BIT(6)) {
+ /* Target Interrupt */
+ outb_p(target_int | BIT(6), ASFSTA);
+ schedule_delayed_work(&dev->work_buf, HZ);
+ } else {
+ /* Controller Interrupt */
+ amd_asf_update_ioport_target(piix4_smba, ASF_SLV_INTR, SMBHSTSTS, true);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int amd_asf_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct amd_asf_dev *asf_dev;
+ struct resource *eoi_addr;
+ int ret, irq;
+
+ asf_dev = devm_kzalloc(dev, sizeof(*asf_dev), GFP_KERNEL);
+ if (!asf_dev)
+ return dev_err_probe(dev, -ENOMEM, "Failed to allocate memory\n");
+
+ asf_dev->mmio_cfg.use_mmio = true;
+ asf_dev->port_addr = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!asf_dev->port_addr)
+ return dev_err_probe(dev, -EINVAL, "missing IO resources\n");
+
+ /*
+ * The resource obtained via ACPI might not belong to the ASF device address space. Instead,
+ * it could be within other IP blocks of the ASIC, which are crucial for generating
+ * subsequent interrupts. Therefore, we avoid using devm_platform_ioremap_resource() and
+ * use platform_get_resource() and devm_ioremap() separately to prevent any address space
+ * conflicts.
+ */
+ eoi_addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!eoi_addr)
+ return dev_err_probe(dev, -EINVAL, "missing MEM resources\n");
+
+ asf_dev->eoi_base = devm_ioremap(dev, eoi_addr->start, resource_size(eoi_addr));
+ if (!asf_dev->eoi_base)
+ return dev_err_probe(dev, -EBUSY, "failed mapping IO region\n");
+
+ ret = devm_delayed_work_autocancel(dev, &asf_dev->work_buf, amd_asf_process_target);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to create work queue\n");
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "missing IRQ resources\n");
+
+ ret = devm_request_irq(dev, irq, amd_asf_irq_handler, IRQF_SHARED, "amd_asf", asf_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to request irq: %d for use\n", irq);
+
+ asf_dev->adap.owner = THIS_MODULE;
+ asf_dev->adap.algo = &amd_asf_smbus_algorithm;
+ asf_dev->adap.dev.parent = dev;
+
+ i2c_set_adapdata(&asf_dev->adap, asf_dev);
+ snprintf(asf_dev->adap.name, sizeof(asf_dev->adap.name), "AMD ASF adapter");
+
+ return devm_i2c_add_adapter(dev, &asf_dev->adap);
+}
+
+static const struct acpi_device_id amd_asf_acpi_ids[] = {
+ { "AMDI001A" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, amd_asf_acpi_ids);
+
+static struct platform_driver amd_asf_driver = {
+ .driver = {
+ .name = "i2c-amd-asf",
+ .acpi_match_table = amd_asf_acpi_ids,
+ },
+ .probe = amd_asf_probe,
+};
+module_platform_driver(amd_asf_driver);
+
+MODULE_IMPORT_NS(PIIX4_SMBUS);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AMD Alert Standard Format Driver");
diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c
index 6f0ef587e76d..d9dd0e475d1a 100644
--- a/drivers/i2c/busses/i2c-amd-mp2-plat.c
+++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c
@@ -346,7 +346,7 @@ MODULE_DEVICE_TABLE(acpi, i2c_amd_acpi_match);
static struct platform_driver i2c_amd_plat_driver = {
.probe = i2c_amd_probe,
- .remove_new = i2c_amd_remove,
+ .remove = i2c_amd_remove,
.driver = {
.name = "i2c_amd_mp2",
.acpi_match_table = ACPI_PTR(i2c_amd_acpi_match),
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
deleted file mode 100644
index 063274388a75..000000000000
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ /dev/null
@@ -1,245 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * i2c-amd756-s4882.c - i2c-amd756 extras for the Tyan S4882 motherboard
- *
- * Copyright (C) 2004, 2008 Jean Delvare <jdelvare@suse.de>
- */
-
-/*
- * We select the channels by sending commands to the Philips
- * PCA9556 chip at I2C address 0x18. The main adapter is used for
- * the non-multiplexed part of the bus, and 4 virtual adapters
- * are defined for the multiplexed addresses: 0x50-0x53 (memory
- * module EEPROM) located on channels 1-4, and 0x4c (LM63)
- * located on multiplexed channels 0 and 5-7. We define one
- * virtual adapter per CPU, which corresponds to two multiplexed
- * channels:
- * CPU0: virtual adapter 1, channels 1 and 0
- * CPU1: virtual adapter 2, channels 2 and 5
- * CPU2: virtual adapter 3, channels 3 and 6
- * CPU3: virtual adapter 4, channels 4 and 7
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-extern struct i2c_adapter amd756_smbus;
-
-static struct i2c_adapter *s4882_adapter;
-static struct i2c_algorithm *s4882_algo;
-
-/* Wrapper access functions for multiplexed SMBus */
-static DEFINE_MUTEX(amd756_lock);
-
-static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data * data)
-{
- int error;
-
- /* We exclude the multiplexed addresses */
- if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
- || addr == 0x18)
- return -ENXIO;
-
- mutex_lock(&amd756_lock);
-
- error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write,
- command, size, data);
-
- mutex_unlock(&amd756_lock);
-
- return error;
-}
-
-/* We remember the last used channels combination so as to only switch
- channels when it is really needed. This greatly reduces the SMBus
- overhead, but also assumes that nobody will be writing to the PCA9556
- in our back. */
-static u8 last_channels;
-
-static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data * data,
- u8 channels)
-{
- int error;
-
- /* We exclude the non-multiplexed addresses */
- if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
- return -ENXIO;
-
- mutex_lock(&amd756_lock);
-
- if (last_channels != channels) {
- union i2c_smbus_data mplxdata;
- mplxdata.byte = channels;
-
- error = amd756_smbus.algo->smbus_xfer(adap, 0x18, 0,
- I2C_SMBUS_WRITE, 0x01,
- I2C_SMBUS_BYTE_DATA,
- &mplxdata);
- if (error)
- goto UNLOCK;
- last_channels = channels;
- }
- error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write,
- command, size, data);
-
-UNLOCK:
- mutex_unlock(&amd756_lock);
- return error;
-}
-
-static s32 amd756_access_virt1(struct i2c_adapter * adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data * data)
-{
- /* CPU0: channels 1 and 0 enabled */
- return amd756_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x03);
-}
-
-static s32 amd756_access_virt2(struct i2c_adapter * adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data * data)
-{
- /* CPU1: channels 2 and 5 enabled */
- return amd756_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x24);
-}
-
-static s32 amd756_access_virt3(struct i2c_adapter * adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data * data)
-{
- /* CPU2: channels 3 and 6 enabled */
- return amd756_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x48);
-}
-
-static s32 amd756_access_virt4(struct i2c_adapter * adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data * data)
-{
- /* CPU3: channels 4 and 7 enabled */
- return amd756_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x90);
-}
-
-static int __init amd756_s4882_init(void)
-{
- int i, error;
- union i2c_smbus_data ioconfig;
-
- if (!amd756_smbus.dev.parent)
- return -ENODEV;
-
- /* Configure the PCA9556 multiplexer */
- ioconfig.byte = 0x00; /* All I/O to output mode */
- error = i2c_smbus_xfer(&amd756_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
- I2C_SMBUS_BYTE_DATA, &ioconfig);
- if (error) {
- dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n");
- error = -EIO;
- goto ERROR0;
- }
-
- /* Unregister physical bus */
- i2c_del_adapter(&amd756_smbus);
-
- printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n");
- /* Define the 5 virtual adapters and algorithms structures */
- if (!(s4882_adapter = kcalloc(5, sizeof(struct i2c_adapter),
- GFP_KERNEL))) {
- error = -ENOMEM;
- goto ERROR1;
- }
- if (!(s4882_algo = kcalloc(5, sizeof(struct i2c_algorithm),
- GFP_KERNEL))) {
- error = -ENOMEM;
- goto ERROR2;
- }
-
- /* Fill in the new structures */
- s4882_algo[0] = *(amd756_smbus.algo);
- s4882_algo[0].smbus_xfer = amd756_access_virt0;
- s4882_adapter[0] = amd756_smbus;
- s4882_adapter[0].algo = s4882_algo;
- s4882_adapter[0].dev.parent = amd756_smbus.dev.parent;
- for (i = 1; i < 5; i++) {
- s4882_algo[i] = *(amd756_smbus.algo);
- s4882_adapter[i] = amd756_smbus;
- snprintf(s4882_adapter[i].name, sizeof(s4882_adapter[i].name),
- "SMBus 8111 adapter (CPU%d)", i-1);
- s4882_adapter[i].algo = s4882_algo+i;
- s4882_adapter[i].dev.parent = amd756_smbus.dev.parent;
- }
- s4882_algo[1].smbus_xfer = amd756_access_virt1;
- s4882_algo[2].smbus_xfer = amd756_access_virt2;
- s4882_algo[3].smbus_xfer = amd756_access_virt3;
- s4882_algo[4].smbus_xfer = amd756_access_virt4;
-
- /* Register virtual adapters */
- for (i = 0; i < 5; i++) {
- error = i2c_add_adapter(s4882_adapter+i);
- if (error) {
- printk(KERN_ERR "i2c-amd756-s4882: "
- "Virtual adapter %d registration "
- "failed, module not inserted\n", i);
- for (i--; i >= 0; i--)
- i2c_del_adapter(s4882_adapter+i);
- goto ERROR3;
- }
- }
-
- return 0;
-
-ERROR3:
- kfree(s4882_algo);
- s4882_algo = NULL;
-ERROR2:
- kfree(s4882_adapter);
- s4882_adapter = NULL;
-ERROR1:
- /* Restore physical bus */
- i2c_add_adapter(&amd756_smbus);
-ERROR0:
- return error;
-}
-
-static void __exit amd756_s4882_exit(void)
-{
- if (s4882_adapter) {
- int i;
-
- for (i = 0; i < 5; i++)
- i2c_del_adapter(s4882_adapter+i);
- kfree(s4882_adapter);
- s4882_adapter = NULL;
- }
- kfree(s4882_algo);
- s4882_algo = NULL;
-
- /* Restore physical bus */
- if (i2c_add_adapter(&amd756_smbus))
- printk(KERN_ERR "i2c-amd756-s4882: "
- "Physical bus restoration failed\n");
-}
-
-MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
-MODULE_DESCRIPTION("S4882 SMBus multiplexing");
-MODULE_LICENSE("GPL");
-
-module_init(amd756_s4882_init);
-module_exit(amd756_s4882_exit);
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 208310db906d..fa0d5a2c3732 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -283,7 +283,7 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = amd756_func,
};
-struct i2c_adapter amd756_smbus = {
+static struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
@@ -398,5 +398,3 @@ module_pci_driver(amd756_driver);
MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver");
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(amd756_smbus);
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index cc5a26637fd5..1550d3d552ae 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -1102,7 +1102,7 @@ static void aspeed_i2c_remove_bus(struct platform_device *pdev)
static struct platform_driver aspeed_i2c_bus_driver = {
.probe = aspeed_i2c_probe_bus,
- .remove_new = aspeed_i2c_remove_bus,
+ .remove = aspeed_i2c_remove_bus,
.driver = {
.name = "aspeed-i2c-bus",
.of_match_table = aspeed_i2c_bus_of_table,
diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c
index dc52b3530725..edc047e3e535 100644
--- a/drivers/i2c/busses/i2c-at91-core.c
+++ b/drivers/i2c/busses/i2c-at91-core.c
@@ -330,7 +330,7 @@ static const struct dev_pm_ops __maybe_unused at91_twi_pm = {
static struct platform_driver at91_twi_driver = {
.probe = at91_twi_probe,
- .remove_new = at91_twi_remove,
+ .remove = at91_twi_remove,
.id_table = at91_twi_devtypes,
.driver = {
.name = "at91_i2c",
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 902e420e761e..b78b38ddac46 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -368,7 +368,7 @@ static struct platform_driver au1xpsc_smbus_driver = {
.pm = pm_sleep_ptr(&i2c_au1550_pmops),
},
.probe = i2c_au1550_probe,
- .remove_new = i2c_au1550_remove,
+ .remove = i2c_au1550_remove,
};
module_platform_driver(au1xpsc_smbus_driver);
diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index a66f7f67b3b8..48916cf45ff7 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -824,7 +824,7 @@ MODULE_DEVICE_TABLE(of, axxia_i2c_of_match);
static struct platform_driver axxia_i2c_driver = {
.probe = axxia_i2c_probe,
- .remove_new = axxia_i2c_remove,
+ .remove = axxia_i2c_remove,
.driver = {
.name = "axxia-i2c",
.of_match_table = axxia_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index 133d02899c6b..15b632a146e1 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -1264,7 +1264,7 @@ static struct platform_driver bcm_iproc_i2c_driver = {
.pm = pm_sleep_ptr(&bcm_iproc_i2c_pm_ops),
},
.probe = bcm_iproc_i2c_probe,
- .remove_new = bcm_iproc_i2c_remove,
+ .remove = bcm_iproc_i2c_remove,
};
module_platform_driver(bcm_iproc_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c
index eb5c46a8f824..340fe1305dd9 100644
--- a/drivers/i2c/busses/i2c-bcm-kona.c
+++ b/drivers/i2c/busses/i2c-bcm-kona.c
@@ -877,7 +877,7 @@ static struct platform_driver bcm_kona_i2c_driver = {
.of_match_table = bcm_kona_i2c_of_match,
},
.probe = bcm_kona_i2c_probe,
- .remove_new = bcm_kona_i2c_remove,
+ .remove = bcm_kona_i2c_remove,
};
module_platform_driver(bcm_kona_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
index ae42e37052a8..8554e790f8e3 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match);
static struct platform_driver bcm2835_i2c_driver = {
.probe = bcm2835_i2c_probe,
- .remove_new = bcm2835_i2c_remove,
+ .remove = bcm2835_i2c_remove,
.driver = {
.name = "i2c-bcm2835",
.of_match_table = bcm2835_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 83b85011e377..00f1a046e985 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -744,7 +744,7 @@ static struct platform_driver brcmstb_i2c_driver = {
.pm = pm_sleep_ptr(&brcmstb_i2c_pm),
},
.probe = brcmstb_i2c_probe,
- .remove_new = brcmstb_i2c_remove,
+ .remove = brcmstb_i2c_remove,
};
module_platform_driver(brcmstb_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index 87b9ba95b2e1..b64026fbca66 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -129,6 +129,7 @@
#define CDNS_I2C_BROKEN_HOLD_BIT BIT(0)
#define CDNS_I2C_POLL_US 100000
+#define CDNS_I2C_POLL_US_ATOMIC 10
#define CDNS_I2C_TIMEOUT_US 500000
#define cdns_i2c_readreg(offset) readl_relaxed(id->membase + offset)
@@ -189,6 +190,8 @@ enum cdns_i2c_slave_state {
* @slave_state: I2C Slave state(idle/read/write).
* @fifo_depth: The depth of the transfer FIFO
* @transfer_size: The maximum number of bytes in one transfer
+ * @atomic: Mode of transfer
+ * @err_status_atomic: Error status in atomic mode
*/
struct cdns_i2c {
struct device *dev;
@@ -219,6 +222,8 @@ struct cdns_i2c {
#endif
u32 fifo_depth;
unsigned int transfer_size;
+ bool atomic;
+ int err_status_atomic;
};
struct cdns_platform_data {
@@ -229,6 +234,66 @@ struct cdns_platform_data {
clk_rate_change_nb)
/**
+ * cdns_i2c_init - Controller initialisation
+ * @id: Device private data structure
+ *
+ * Initialise the i2c controller.
+ *
+ */
+static void cdns_i2c_init(struct cdns_i2c *id)
+{
+ cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET);
+ /*
+ * Cadence I2C controller has a bug wherein it generates
+ * invalid read transaction after HW timeout in master receiver mode.
+ * HW timeout is not used by this driver and the interrupt is disabled.
+ * But the feature itself cannot be disabled. Hence maximum value
+ * is written to this register to reduce the chances of error.
+ */
+ cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
+}
+
+/**
+ * cdns_i2c_runtime_suspend - Runtime suspend method for the driver
+ * @dev: Address of the platform_device structure
+ *
+ * Put the driver into low power mode.
+ *
+ * Return: 0 always
+ */
+static int cdns_i2c_runtime_suspend(struct device *dev)
+{
+ struct cdns_i2c *xi2c = dev_get_drvdata(dev);
+
+ clk_disable(xi2c->clk);
+
+ return 0;
+}
+
+/**
+ * cdns_i2c_runtime_resume - Runtime resume
+ * @dev: Address of the platform_device structure
+ *
+ * Runtime resume callback.
+ *
+ * Return: 0 on success and error value on error
+ */
+static int cdns_i2c_runtime_resume(struct device *dev)
+{
+ struct cdns_i2c *xi2c = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_enable(xi2c->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock.\n");
+ return ret;
+ }
+ cdns_i2c_init(xi2c);
+
+ return 0;
+}
+
+/**
* cdns_i2c_clear_bus_hold - Clear bus hold bit
* @id: Pointer to driver data struct
*
@@ -561,6 +626,89 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
return cdns_i2c_master_isr(ptr);
}
+static bool cdns_i2c_error_check(struct cdns_i2c *id)
+{
+ unsigned int isr_status;
+
+ id->err_status = 0;
+
+ isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET);
+ cdns_i2c_writereg(isr_status & CDNS_I2C_IXR_ERR_INTR_MASK, CDNS_I2C_ISR_OFFSET);
+
+ id->err_status = isr_status & CDNS_I2C_IXR_ERR_INTR_MASK;
+
+ return !!id->err_status;
+}
+
+static void cdns_i2c_mrecv_atomic(struct cdns_i2c *id)
+{
+ while (id->recv_count > 0) {
+ bool updatetx;
+
+ /*
+ * Check if transfer size register needs to be updated again for a
+ * large data receive operation.
+ */
+ updatetx = id->recv_count > id->curr_recv_count;
+
+ while (id->curr_recv_count > 0) {
+ if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_RXDV) {
+ *id->p_recv_buf = cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET);
+ id->p_recv_buf++;
+ id->recv_count--;
+ id->curr_recv_count--;
+
+ /*
+ * Clear the hold bit that was set for FIFO control,
+ * if the remaining RX data is less than or equal to
+ * the FIFO depth, unless a repeated start is selected.
+ */
+ if (id->recv_count <= id->fifo_depth && !id->bus_hold_flag)
+ cdns_i2c_clear_bus_hold(id);
+ }
+ if (cdns_i2c_error_check(id))
+ return;
+ if (cdns_is_holdquirk(id, updatetx))
+ break;
+ }
+
+ /*
+ * The controller sends NACK to the slave/target when transfer size
+ * register reaches zero without considering the HOLD bit.
+ * This workaround is implemented for large data transfers to
+ * maintain transfer size non-zero while performing a large
+ * receive operation.
+ */
+ if (cdns_is_holdquirk(id, updatetx)) {
+ /* wait while fifo is full */
+ while (cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET) !=
+ (id->curr_recv_count - id->fifo_depth))
+ ;
+
+ /*
+ * Check number of bytes to be received against maximum
+ * transfer size and update register accordingly.
+ */
+ if ((id->recv_count - id->fifo_depth) >
+ id->transfer_size) {
+ cdns_i2c_writereg(id->transfer_size,
+ CDNS_I2C_XFER_SIZE_OFFSET);
+ id->curr_recv_count = id->transfer_size +
+ id->fifo_depth;
+ } else {
+ cdns_i2c_writereg(id->recv_count -
+ id->fifo_depth,
+ CDNS_I2C_XFER_SIZE_OFFSET);
+ id->curr_recv_count = id->recv_count;
+ }
+ }
+ }
+
+ /* Clear hold (if not repeated start) */
+ if (!id->recv_count && !id->bus_hold_flag)
+ cdns_i2c_clear_bus_hold(id);
+}
+
/**
* cdns_i2c_mrecv - Prepare and start a master receive operation
* @id: pointer to the i2c device structure
@@ -655,7 +803,34 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
cdns_i2c_writereg(addr, CDNS_I2C_ADDR_OFFSET);
}
- cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET);
+ if (!id->atomic)
+ cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET);
+ else
+ cdns_i2c_mrecv_atomic(id);
+}
+
+static void cdns_i2c_msend_rem_atomic(struct cdns_i2c *id)
+{
+ while (id->send_count) {
+ unsigned int avail_bytes;
+ unsigned int bytes_to_send;
+
+ avail_bytes = id->fifo_depth - cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET);
+ if (id->send_count > avail_bytes)
+ bytes_to_send = avail_bytes;
+ else
+ bytes_to_send = id->send_count;
+
+ while (bytes_to_send--) {
+ cdns_i2c_writereg((*id->p_send_buf++), CDNS_I2C_DATA_OFFSET);
+ id->send_count--;
+ }
+ if (cdns_i2c_error_check(id))
+ return;
+ }
+
+ if (!id->send_count && !id->bus_hold_flag)
+ cdns_i2c_clear_bus_hold(id);
}
/**
@@ -718,7 +893,10 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK,
CDNS_I2C_ADDR_OFFSET);
- cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET);
+ if (!id->atomic)
+ cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET);
+ else if (id->send_count > 0)
+ cdns_i2c_msend_rem_atomic(id);
}
/**
@@ -758,7 +936,8 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
id->p_msg = msg;
id->err_status = 0;
- reinit_completion(&id->xfer_done);
+ if (!id->atomic)
+ reinit_completion(&id->xfer_done);
/* Check for the TEN Bit mode on each msg */
reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
@@ -780,14 +959,31 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
/* Minimal time to execute this message */
msg_timeout = msecs_to_jiffies((1000 * msg->len * BITS_PER_BYTE) / id->i2c_clk);
- /* Plus some wiggle room */
- msg_timeout += msecs_to_jiffies(500);
+
+ /*
+ * Plus some wiggle room.
+ * For non-atomic contexts, 500 ms is added to the timeout.
+ * For atomic contexts, 2000 ms is added because transfers happen in polled
+ * mode, requiring more time to account for the polling overhead.
+ */
+ if (!id->atomic)
+ msg_timeout += msecs_to_jiffies(500);
+ else
+ msg_timeout += msecs_to_jiffies(2000);
if (msg_timeout < adap->timeout)
msg_timeout = adap->timeout;
- /* Wait for the signal of completion */
- time_left = wait_for_completion_timeout(&id->xfer_done, msg_timeout);
+ if (!id->atomic) {
+ /* Wait for the signal of completion */
+ time_left = wait_for_completion_timeout(&id->xfer_done, msg_timeout);
+ } else {
+ /* 0 is success, -ETIMEDOUT is error */
+ time_left = !readl_poll_timeout_atomic(id->membase + CDNS_I2C_ISR_OFFSET,
+ reg, (reg & CDNS_I2C_IXR_COMP),
+ CDNS_I2C_POLL_US_ATOMIC, msg_timeout);
+ }
+
if (time_left == 0) {
cdns_i2c_master_reset(adap);
return -ETIMEDOUT;
@@ -806,58 +1002,31 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
return 0;
}
-/**
- * cdns_i2c_master_xfer - The main i2c transfer function
- * @adap: pointer to the i2c adapter driver instance
- * @msgs: pointer to the i2c message structure
- * @num: the number of messages to transfer
- *
- * Initiates the send/recv activity based on the transfer message received.
- *
- * Return: number of msgs processed on success, negative error otherwise
- */
-static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- int num)
+static int cdns_i2c_master_common_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs,
+ int num)
{
int ret, count;
u32 reg;
struct cdns_i2c *id = adap->algo_data;
bool hold_quirk;
-#if IS_ENABLED(CONFIG_I2C_SLAVE)
- bool change_role = false;
-#endif
-
- ret = pm_runtime_resume_and_get(id->dev);
- if (ret < 0)
- return ret;
-
-#if IS_ENABLED(CONFIG_I2C_SLAVE)
- /* Check i2c operating mode and switch if possible */
- if (id->dev_mode == CDNS_I2C_MODE_SLAVE) {
- if (id->slave_state != CDNS_I2C_SLAVE_STATE_IDLE) {
- ret = -EAGAIN;
- goto out;
- }
-
- /* Set mode to master */
- cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id);
-
- /* Mark flag to change role once xfer is completed */
- change_role = true;
- }
-#endif
/* Check if the bus is free */
-
- ret = readl_relaxed_poll_timeout(id->membase + CDNS_I2C_SR_OFFSET,
- reg,
- !(reg & CDNS_I2C_SR_BA),
- CDNS_I2C_POLL_US, CDNS_I2C_TIMEOUT_US);
+ if (!id->atomic)
+ ret = readl_relaxed_poll_timeout(id->membase + CDNS_I2C_SR_OFFSET,
+ reg,
+ !(reg & CDNS_I2C_SR_BA),
+ CDNS_I2C_POLL_US, CDNS_I2C_TIMEOUT_US);
+ else
+ ret = readl_poll_timeout_atomic(id->membase + CDNS_I2C_SR_OFFSET,
+ reg,
+ !(reg & CDNS_I2C_SR_BA),
+ CDNS_I2C_POLL_US_ATOMIC, CDNS_I2C_TIMEOUT_US);
if (ret) {
ret = -EAGAIN;
if (id->adap.bus_recovery_info)
i2c_recover_bus(adap);
- goto out;
+ return ret;
}
hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT);
@@ -877,8 +1046,7 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
if (msgs[count].flags & I2C_M_RD) {
dev_warn(adap->dev.parent,
"Can't do repeated start after a receive message\n");
- ret = -EOPNOTSUPP;
- goto out;
+ return -EOPNOTSUPP;
}
}
id->bus_hold_flag = 1;
@@ -896,26 +1064,65 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
ret = cdns_i2c_process_msg(id, msgs, adap);
if (ret)
- goto out;
+ return ret;
/* Report the other error interrupts to application */
- if (id->err_status) {
+ if (id->err_status || id->err_status_atomic) {
cdns_i2c_master_reset(adap);
- if (id->err_status & CDNS_I2C_IXR_NACK) {
- ret = -ENXIO;
- goto out;
- }
- ret = -EIO;
- goto out;
+ if (id->err_status & CDNS_I2C_IXR_NACK)
+ return -ENXIO;
+
+ return -EIO;
}
}
+ return 0;
+}
+
+/**
+ * cdns_i2c_master_xfer - The main i2c transfer function
+ * @adap: pointer to the i2c adapter driver instance
+ * @msgs: pointer to the i2c message structure
+ * @num: the number of messages to transfer
+ *
+ * Initiates the send/recv activity based on the transfer message received.
+ *
+ * Return: number of msgs processed on success, negative error otherwise
+ */
+static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ int ret;
+ struct cdns_i2c *id = adap->algo_data;
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ bool change_role = false;
+#endif
- ret = num;
+ ret = pm_runtime_resume_and_get(id->dev);
+ if (ret < 0)
+ return ret;
-out:
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+ /* Check i2c operating mode and switch if possible */
+ if (id->dev_mode == CDNS_I2C_MODE_SLAVE) {
+ if (id->slave_state != CDNS_I2C_SLAVE_STATE_IDLE) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ /* Set mode to master */
+ cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id);
+
+ /* Mark flag to change role once xfer is completed */
+ change_role = true;
+ }
+#endif
+ ret = cdns_i2c_master_common_xfer(adap, msgs, num);
+ if (!ret)
+ ret = num;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
+out:
/* Switch i2c mode to slave */
if (change_role)
cdns_i2c_set_mode(CDNS_I2C_MODE_SLAVE, id);
@@ -927,6 +1134,41 @@ out:
}
/**
+ * cdns_i2c_master_xfer_atomic - The i2c transfer function in atomic mode
+ * @adap: pointer to the i2c adapter driver instance
+ * @msgs: pointer to the i2c message structure
+ * @num: the number of messages to transfer
+ *
+ * Return: number of msgs processed on success, negative error otherwise
+ */
+static int cdns_i2c_master_xfer_atomic(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ int ret;
+ struct cdns_i2c *id = adap->algo_data;
+
+ ret = cdns_i2c_runtime_resume(id->dev);
+ if (ret)
+ return ret;
+
+ if (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) {
+ dev_warn(id->adap.dev.parent,
+ "Atomic xfer not supported for version 1.0\n");
+ return 0;
+ }
+
+ id->atomic = true;
+ ret = cdns_i2c_master_common_xfer(adap, msgs, num);
+ if (!ret)
+ ret = num;
+
+ id->atomic = false;
+ cdns_i2c_runtime_suspend(id->dev);
+
+ return ret;
+}
+
+/**
* cdns_i2c_func - Returns the supported features of the I2C driver
* @adap: pointer to the i2c adapter structure
*
@@ -990,6 +1232,7 @@ static int cdns_unreg_slave(struct i2c_client *slave)
static const struct i2c_algorithm cdns_i2c_algo = {
.master_xfer = cdns_i2c_master_xfer,
+ .master_xfer_atomic = cdns_i2c_master_xfer_atomic,
.functionality = cdns_i2c_func,
#if IS_ENABLED(CONFIG_I2C_SLAVE)
.reg_slave = cdns_reg_slave,
@@ -1158,23 +1401,6 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
}
}
-/**
- * cdns_i2c_runtime_suspend - Runtime suspend method for the driver
- * @dev: Address of the platform_device structure
- *
- * Put the driver into low power mode.
- *
- * Return: 0 always
- */
-static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
-{
- struct cdns_i2c *xi2c = dev_get_drvdata(dev);
-
- clk_disable(xi2c->clk);
-
- return 0;
-}
-
static int __maybe_unused cdns_i2c_suspend(struct device *dev)
{
struct cdns_i2c *xi2c = dev_get_drvdata(dev);
@@ -1187,49 +1413,6 @@ static int __maybe_unused cdns_i2c_suspend(struct device *dev)
return 0;
}
-/**
- * cdns_i2c_init - Controller initialisation
- * @id: Device private data structure
- *
- * Initialise the i2c controller.
- *
- */
-static void cdns_i2c_init(struct cdns_i2c *id)
-{
- cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET);
- /*
- * Cadence I2C controller has a bug wherein it generates
- * invalid read transaction after HW timeout in master receiver mode.
- * HW timeout is not used by this driver and the interrupt is disabled.
- * But the feature itself cannot be disabled. Hence maximum value
- * is written to this register to reduce the chances of error.
- */
- cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
-}
-
-/**
- * cdns_i2c_runtime_resume - Runtime resume
- * @dev: Address of the platform_device structure
- *
- * Runtime resume callback.
- *
- * Return: 0 on success and error value on error
- */
-static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
-{
- struct cdns_i2c *xi2c = dev_get_drvdata(dev);
- int ret;
-
- ret = clk_enable(xi2c->clk);
- if (ret) {
- dev_err(dev, "Cannot enable clock.\n");
- return ret;
- }
- cdns_i2c_init(xi2c);
-
- return 0;
-}
-
static int __maybe_unused cdns_i2c_resume(struct device *dev)
{
struct cdns_i2c *xi2c = dev_get_drvdata(dev);
@@ -1469,7 +1652,7 @@ static struct platform_driver cdns_i2c_drv = {
.pm = &cdns_i2c_dev_pm_ops,
},
.probe = cdns_i2c_probe,
- .remove_new = cdns_i2c_remove,
+ .remove = cdns_i2c_remove,
};
module_platform_driver(cdns_i2c_drv);
diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c
index fdc1758a3275..8065c7e4462e 100644
--- a/drivers/i2c/busses/i2c-cbus-gpio.c
+++ b/drivers/i2c/busses/i2c-cbus-gpio.c
@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids);
static struct platform_driver cbus_i2c_driver = {
.probe = cbus_i2c_probe,
- .remove_new = cbus_i2c_remove,
+ .remove = cbus_i2c_remove,
.driver = {
.name = "i2c-cbus-gpio",
.of_match_table = of_match_ptr(i2c_cbus_dt_ids),
diff --git a/drivers/i2c/busses/i2c-cgbc.c b/drivers/i2c/busses/i2c-cgbc.c
new file mode 100644
index 000000000000..eba0b205de11
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cgbc.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Congatec Board Controller I2C busses driver
+ *
+ * Copyright (C) 2024 Bootlin
+ * Author: Thomas Richard <thomas.richard@bootlin.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/cgbc.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define CGBC_I2C_PRIMARY_BUS_ID 0
+#define CGBC_I2C_PM_BUS_ID 4
+
+#define CGBC_I2C_CMD_START 0x40
+#define CGBC_I2C_CMD_STAT 0x48
+#define CGBC_I2C_CMD_DATA 0x50
+#define CGBC_I2C_CMD_SPEED 0x58
+
+#define CGBC_I2C_STAT_IDL 0x00
+#define CGBC_I2C_STAT_DAT 0x01
+#define CGBC_I2C_STAT_BUSY 0x02
+
+#define CGBC_I2C_START 0x80
+#define CGBC_I2C_STOP 0x40
+
+#define CGBC_I2C_LAST_ACK 0x80 /* send ACK on last read byte */
+
+/*
+ * Reference code defines 1kHz as min freq and 6.1MHz as max freq.
+ * But in practice, the board controller limits the frequency to 1MHz, and the
+ * 1kHz is not functional (minimal working freq is 50kHz).
+ * So use these values as limits.
+ */
+#define CGBC_I2C_FREQ_MIN_HZ 50000 /* 50 kHz */
+#define CGBC_I2C_FREQ_MAX_HZ 1000000 /* 1 MHz */
+
+#define CGBC_I2C_FREQ_UNIT_1KHZ 0x40
+#define CGBC_I2C_FREQ_UNIT_10KHZ 0x80
+#define CGBC_I2C_FREQ_UNIT_100KHZ 0xC0
+
+#define CGBC_I2C_FREQ_UNIT_MASK 0xC0
+#define CGBC_I2C_FREQ_VALUE_MASK 0x3F
+
+#define CGBC_I2C_READ_MAX_LEN 31
+#define CGBC_I2C_WRITE_MAX_LEN 32
+
+#define CGBC_I2C_CMD_HEADER_SIZE 4
+#define CGBC_I2C_CMD_SIZE (CGBC_I2C_CMD_HEADER_SIZE + CGBC_I2C_WRITE_MAX_LEN)
+
+enum cgbc_i2c_state {
+ CGBC_I2C_STATE_DONE = 0,
+ CGBC_I2C_STATE_INIT,
+ CGBC_I2C_STATE_START,
+ CGBC_I2C_STATE_READ,
+ CGBC_I2C_STATE_WRITE,
+ CGBC_I2C_STATE_ERROR,
+};
+
+struct i2c_algo_cgbc_data {
+ u8 bus_id;
+ unsigned long read_maxtime_us;
+};
+
+struct cgbc_i2c_data {
+ struct device *dev;
+ struct cgbc_device_data *cgbc;
+ struct i2c_adapter adap;
+ struct i2c_msg *msg;
+ int nmsgs;
+ int pos;
+ enum cgbc_i2c_state state;
+};
+
+struct cgbc_i2c_transfer {
+ u8 bus_id;
+ bool start;
+ bool stop;
+ bool last_ack;
+ u8 read;
+ u8 write;
+ u8 addr;
+ u8 data[CGBC_I2C_WRITE_MAX_LEN];
+};
+
+static u8 cgbc_i2c_freq_to_reg(unsigned int bus_frequency)
+{
+ u8 reg;
+
+ if (bus_frequency <= 10000)
+ reg = CGBC_I2C_FREQ_UNIT_1KHZ | (bus_frequency / 1000);
+ else if (bus_frequency <= 100000)
+ reg = CGBC_I2C_FREQ_UNIT_10KHZ | (bus_frequency / 10000);
+ else
+ reg = CGBC_I2C_FREQ_UNIT_100KHZ | (bus_frequency / 100000);
+
+ return reg;
+}
+
+static unsigned int cgbc_i2c_reg_to_freq(u8 reg)
+{
+ unsigned int freq = reg & CGBC_I2C_FREQ_VALUE_MASK;
+ u8 unit = reg & CGBC_I2C_FREQ_UNIT_MASK;
+
+ if (unit == CGBC_I2C_FREQ_UNIT_100KHZ)
+ return freq * 100000;
+ else if (unit == CGBC_I2C_FREQ_UNIT_10KHZ)
+ return freq * 10000;
+ else
+ return freq * 1000;
+}
+
+static int cgbc_i2c_get_status(struct i2c_adapter *adap)
+{
+ struct i2c_algo_cgbc_data *algo_data = adap->algo_data;
+ struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
+ struct cgbc_device_data *cgbc = i2c->cgbc;
+ u8 cmd = CGBC_I2C_CMD_STAT | algo_data->bus_id;
+ u8 status;
+ int ret;
+
+ ret = cgbc_command(cgbc, &cmd, sizeof(cmd), NULL, 0, &status);
+ if (ret)
+ return ret;
+
+ return status;
+}
+
+static int cgbc_i2c_set_frequency(struct i2c_adapter *adap,
+ unsigned int bus_frequency)
+{
+ struct i2c_algo_cgbc_data *algo_data = adap->algo_data;
+ struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
+ struct cgbc_device_data *cgbc = i2c->cgbc;
+ u8 cmd[2], data;
+ int ret;
+
+ if (bus_frequency > CGBC_I2C_FREQ_MAX_HZ ||
+ bus_frequency < CGBC_I2C_FREQ_MIN_HZ) {
+ dev_info(i2c->dev, "invalid frequency %u, using default\n", bus_frequency);
+ bus_frequency = I2C_MAX_STANDARD_MODE_FREQ;
+ }
+
+ cmd[0] = CGBC_I2C_CMD_SPEED | algo_data->bus_id;
+ cmd[1] = cgbc_i2c_freq_to_reg(bus_frequency);
+
+ ret = cgbc_command(cgbc, &cmd, sizeof(cmd), &data, 1, NULL);
+ if (ret)
+ return dev_err_probe(i2c->dev, ret,
+ "Failed to initialize I2C bus %s",
+ adap->name);
+
+ cmd[1] = 0x00;
+
+ ret = cgbc_command(cgbc, &cmd, sizeof(cmd), &data, 1, NULL);
+ if (ret)
+ return dev_err_probe(i2c->dev, ret,
+ "Failed to get I2C bus frequency");
+
+ bus_frequency = cgbc_i2c_reg_to_freq(data);
+
+ dev_dbg(i2c->dev, "%s is running at %d Hz\n", adap->name, bus_frequency);
+
+ /*
+ * The read_maxtime_us variable represents the maximum time to wait
+ * for data during a read operation. The maximum amount of data that
+ * can be read by a command is CGBC_I2C_READ_MAX_LEN.
+ * Therefore, calculate the max time to properly size the timeout.
+ */
+ algo_data->read_maxtime_us = (BITS_PER_BYTE + 1) * CGBC_I2C_READ_MAX_LEN
+ * USEC_PER_SEC / bus_frequency;
+
+ return 0;
+}
+
+static unsigned int cgbc_i2c_xfer_to_cmd(struct cgbc_i2c_transfer xfer, u8 *cmd)
+{
+ int i = 0;
+
+ cmd[i++] = CGBC_I2C_CMD_START | xfer.bus_id;
+
+ cmd[i] = (xfer.start) ? CGBC_I2C_START : 0x00;
+ if (xfer.stop)
+ cmd[i] |= CGBC_I2C_STOP;
+ cmd[i++] |= (xfer.start) ? xfer.write + 1 : xfer.write;
+
+ cmd[i++] = (xfer.last_ack) ? (xfer.read | CGBC_I2C_LAST_ACK) : xfer.read;
+
+ if (xfer.start)
+ cmd[i++] = xfer.addr;
+
+ if (xfer.write > 0)
+ memcpy(&cmd[i], &xfer.data, xfer.write);
+
+ return i + xfer.write;
+}
+
+static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
+{
+ struct i2c_algo_cgbc_data *algo_data = adap->algo_data;
+ struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
+ struct cgbc_device_data *cgbc = i2c->cgbc;
+ struct i2c_msg *msg = i2c->msg;
+ u8 cmd[CGBC_I2C_CMD_SIZE];
+ int ret, max_len, len, i;
+ unsigned int cmd_len;
+ u8 cmd_data;
+
+ struct cgbc_i2c_transfer xfer = {
+ .bus_id = algo_data->bus_id,
+ .addr = i2c_8bit_addr_from_msg(msg),
+ };
+
+ if (i2c->state == CGBC_I2C_STATE_DONE)
+ return 0;
+
+ ret = cgbc_i2c_get_status(adap);
+
+ if (ret == CGBC_I2C_STAT_BUSY)
+ return -EBUSY;
+ else if (ret < 0)
+ goto err;
+
+ if (i2c->state == CGBC_I2C_STATE_INIT ||
+ (i2c->state == CGBC_I2C_STATE_WRITE && msg->flags & I2C_M_RD))
+ xfer.start = true;
+
+ i2c->state = (msg->flags & I2C_M_RD) ? CGBC_I2C_STATE_READ : CGBC_I2C_STATE_WRITE;
+
+ max_len = (i2c->state == CGBC_I2C_STATE_READ) ?
+ CGBC_I2C_READ_MAX_LEN : CGBC_I2C_WRITE_MAX_LEN;
+
+ if (msg->len - i2c->pos > max_len) {
+ len = max_len;
+ } else {
+ len = msg->len - i2c->pos;
+
+ if (i2c->nmsgs == 1)
+ xfer.stop = true;
+ }
+
+ if (i2c->state == CGBC_I2C_STATE_WRITE) {
+ xfer.write = len;
+ xfer.read = 0;
+
+ for (i = 0; i < len; i++)
+ xfer.data[i] = msg->buf[i2c->pos + i];
+
+ cmd_len = cgbc_i2c_xfer_to_cmd(xfer, &cmd[0]);
+
+ ret = cgbc_command(cgbc, &cmd, cmd_len, NULL, 0, NULL);
+ if (ret)
+ goto err;
+ } else if (i2c->state == CGBC_I2C_STATE_READ) {
+ xfer.write = 0;
+ xfer.read = len;
+
+ if (i2c->nmsgs > 1 || msg->len - i2c->pos > max_len)
+ xfer.read |= CGBC_I2C_LAST_ACK;
+
+ cmd_len = cgbc_i2c_xfer_to_cmd(xfer, &cmd[0]);
+ ret = cgbc_command(cgbc, &cmd, cmd_len, NULL, 0, NULL);
+ if (ret)
+ goto err;
+
+ ret = read_poll_timeout(cgbc_i2c_get_status, ret,
+ ret != CGBC_I2C_STAT_BUSY, 0,
+ 2 * algo_data->read_maxtime_us, false, adap);
+ if (ret < 0)
+ goto err;
+
+ cmd_data = CGBC_I2C_CMD_DATA | algo_data->bus_id;
+ ret = cgbc_command(cgbc, &cmd_data, sizeof(cmd_data),
+ msg->buf + i2c->pos, len, NULL);
+ if (ret)
+ goto err;
+ }
+
+ if (len == (msg->len - i2c->pos)) {
+ i2c->msg++;
+ i2c->nmsgs--;
+ i2c->pos = 0;
+ } else {
+ i2c->pos += len;
+ }
+
+ if (i2c->nmsgs == 0)
+ i2c->state = CGBC_I2C_STATE_DONE;
+
+ return 0;
+
+err:
+ i2c->state = CGBC_I2C_STATE_ERROR;
+ return ret;
+}
+
+static int cgbc_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
+ unsigned long timeout = jiffies + HZ;
+ int ret;
+
+ i2c->state = CGBC_I2C_STATE_INIT;
+ i2c->msg = msgs;
+ i2c->nmsgs = num;
+ i2c->pos = 0;
+
+ while (time_before(jiffies, timeout)) {
+ ret = cgbc_i2c_xfer_msg(adap);
+ if (i2c->state == CGBC_I2C_STATE_DONE)
+ return num;
+
+ if (i2c->state == CGBC_I2C_STATE_ERROR)
+ return ret;
+
+ if (ret == 0)
+ timeout = jiffies + HZ;
+ }
+
+ i2c->state = CGBC_I2C_STATE_ERROR;
+ return -ETIMEDOUT;
+}
+
+static u32 cgbc_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~(I2C_FUNC_SMBUS_QUICK));
+}
+
+static const struct i2c_algorithm cgbc_i2c_algorithm = {
+ .master_xfer = cgbc_i2c_xfer,
+ .functionality = cgbc_i2c_func,
+};
+
+static struct i2c_algo_cgbc_data cgbc_i2c_algo_data[] = {
+ { .bus_id = CGBC_I2C_PRIMARY_BUS_ID },
+ { .bus_id = CGBC_I2C_PM_BUS_ID },
+};
+
+static const struct i2c_adapter cgbc_i2c_adapter[] = {
+ {
+ .owner = THIS_MODULE,
+ .name = "Congatec General Purpose I2C adapter",
+ .class = I2C_CLASS_DEPRECATED,
+ .algo = &cgbc_i2c_algorithm,
+ .algo_data = &cgbc_i2c_algo_data[0],
+ .nr = -1,
+ },
+ {
+ .owner = THIS_MODULE,
+ .name = "Congatec Power Management I2C adapter",
+ .class = I2C_CLASS_DEPRECATED,
+ .algo = &cgbc_i2c_algorithm,
+ .algo_data = &cgbc_i2c_algo_data[1],
+ .nr = -1,
+ },
+};
+
+static int cgbc_i2c_probe(struct platform_device *pdev)
+{
+ struct cgbc_device_data *cgbc = dev_get_drvdata(pdev->dev.parent);
+ struct cgbc_i2c_data *i2c;
+ int ret;
+
+ i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
+ return -ENOMEM;
+
+ i2c->cgbc = cgbc;
+ i2c->dev = &pdev->dev;
+ i2c->adap = cgbc_i2c_adapter[pdev->id];
+ i2c->adap.dev.parent = i2c->dev;
+ i2c_set_adapdata(&i2c->adap, i2c);
+ platform_set_drvdata(pdev, i2c);
+
+ ret = cgbc_i2c_set_frequency(&i2c->adap, I2C_MAX_STANDARD_MODE_FREQ);
+ if (ret)
+ return ret;
+
+ return i2c_add_numbered_adapter(&i2c->adap);
+}
+
+static void cgbc_i2c_remove(struct platform_device *pdev)
+{
+ struct cgbc_i2c_data *i2c = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&i2c->adap);
+}
+
+static struct platform_driver cgbc_i2c_driver = {
+ .driver = {
+ .name = "cgbc-i2c",
+ },
+ .probe = cgbc_i2c_probe,
+ .remove_new = cgbc_i2c_remove,
+};
+
+module_platform_driver(cgbc_i2c_driver);
+
+MODULE_DESCRIPTION("Congatec Board Controller I2C Driver");
+MODULE_AUTHOR("Thomas Richard <thomas.richard@bootlin.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cgbc_i2c");
diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c
index 52e3000626c5..26a36a65521e 100644
--- a/drivers/i2c/busses/i2c-cht-wc.c
+++ b/drivers/i2c/busses/i2c-cht-wc.c
@@ -546,7 +546,7 @@ MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
static struct platform_driver cht_wc_i2c_adap_driver = {
.probe = cht_wc_i2c_adap_i2c_probe,
- .remove_new = cht_wc_i2c_adap_i2c_remove,
+ .remove = cht_wc_i2c_adap_i2c_remove,
.driver = {
.name = "cht_wcove_ext_chgr",
},
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index 4794ec066eb0..260e1643c2cc 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -701,7 +701,7 @@ MODULE_DEVICE_TABLE(of, cpm_i2c_match);
static struct platform_driver cpm_i2c_driver = {
.probe = cpm_i2c_probe,
- .remove_new = cpm_i2c_remove,
+ .remove = cpm_i2c_remove,
.driver = {
.name = "fsl-i2c-cpm",
.of_match_table = cpm_i2c_match,
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index ab2688bd4d33..43bf90d90eeb 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -304,7 +304,7 @@ MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_tunnel_acpi_id);
static struct platform_driver ec_i2c_tunnel_driver = {
.probe = ec_i2c_probe,
- .remove_new = ec_i2c_remove,
+ .remove = ec_i2c_remove,
.driver = {
.name = "cros-ec-i2c-tunnel",
.acpi_match_table = ACPI_PTR(cros_ec_i2c_tunnel_acpi_id),
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index c4fb5e9ab506..71dc0a6688b7 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -935,7 +935,7 @@ MODULE_DEVICE_TABLE(platform, davinci_i2c_driver_ids);
static struct platform_driver davinci_i2c_driver = {
.probe = davinci_i2c_probe,
- .remove_new = davinci_i2c_remove,
+ .remove = davinci_i2c_remove,
.id_table = davinci_i2c_driver_ids,
.driver = {
.name = "i2c_davinci",
diff --git a/drivers/i2c/busses/i2c-designware-amdpsp.c b/drivers/i2c/busses/i2c-designware-amdpsp.c
index 63454b06e5da..8fbd2a10c31a 100644
--- a/drivers/i2c/busses/i2c-designware-amdpsp.c
+++ b/drivers/i2c/busses/i2c-designware-amdpsp.c
@@ -155,7 +155,7 @@ static void psp_release_i2c_bus_deferred(struct work_struct *work)
/*
* If there is any pending transaction, cannot release the bus here.
- * psp_release_i2c_bus will take care of this later.
+ * psp_release_i2c_bus() will take care of this later.
*/
if (psp_i2c_access_count)
goto cleanup;
@@ -210,12 +210,12 @@ static void psp_release_i2c_bus(void)
{
mutex_lock(&psp_i2c_access_mutex);
- /* Return early if mailbox was malfunctional */
+ /* Return early if mailbox was malfunctioned */
if (psp_i2c_mbox_fail)
goto cleanup;
/*
- * If we are last owner of PSP semaphore, need to release aribtration
+ * If we are last owner of PSP semaphore, need to release arbitration
* via mailbox.
*/
psp_i2c_access_count--;
@@ -235,9 +235,9 @@ cleanup:
/*
* Locking methods are based on the default implementation from
- * drivers/i2c/i2c-core-base.c, but with psp acquire and release operations
+ * drivers/i2c/i2c-core-base.c, but with PSP acquire and release operations
* added. With this in place we can ensure that i2c clients on the bus shared
- * with psp are able to lock HW access to the bus for arbitrary number of
+ * with PSP are able to lock HW access to the bus for arbitrary number of
* operations - that is e.g. write-wait-read.
*/
static void i2c_adapter_dw_psp_lock_bus(struct i2c_adapter *adapter,
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index f31d352d98b5..857783d458fb 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -33,7 +33,7 @@
#include "i2c-designware-core.h"
-static char *abort_sources[] = {
+static const char *const abort_sources[] = {
[ABRT_7B_ADDR_NOACK] =
"slave address not acknowledged (7bit mode)",
[ABRT_10ADDR1_NOACK] =
@@ -127,6 +127,8 @@ static int dw_reg_write_word(void *context, unsigned int reg, unsigned int val)
* Autodetects needed register access mode and creates the regmap with
* corresponding read/write callbacks. This must be called before doing any
* other register access.
+ *
+ * Return: 0 on success, or negative errno otherwise.
*/
int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
{
@@ -174,7 +176,7 @@ int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
/*
* Note we'll check the return value of the regmap IO accessors only
* at the probe stage. The rest of the code won't do this because
- * basically we have MMIO-based regmap so non of the read/write methods
+ * basically we have MMIO-based regmap, so none of the read/write methods
* can fail.
*/
dev->map = devm_regmap_init(dev->dev, NULL, dev, &map_cfg);
@@ -336,7 +338,7 @@ static u32 i2c_dw_acpi_round_bus_speed(struct device *device)
acpi_speed = i2c_acpi_find_bus_speed(device);
/*
- * Some DSTDs use a non standard speed, round down to the lowest
+ * Some DSDTs use a non standard speed, round down to the lowest
* standard speed.
*/
for (i = 0; i < ARRAY_SIZE(supported_speeds); i++) {
@@ -380,6 +382,11 @@ int i2c_dw_fw_parse_and_configure(struct dw_i2c_dev *dev)
i2c_parse_fw_timings(device, t, false);
+ if (device_property_read_u32(device, "snps,bus-capacitance-pf", &dev->bus_capacitance_pF))
+ dev->bus_capacitance_pF = 100;
+
+ dev->clk_freq_optimized = device_property_read_bool(device, "snps,clk-freq-optimized");
+
i2c_dw_adjust_bus_speed(dev);
if (is_of_node(fwnode))
@@ -407,47 +414,26 @@ static u32 i2c_dw_read_scl_reg(struct dw_i2c_dev *dev, u32 reg)
}
u32 i2c_dw_scl_hcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
- u32 tSYMBOL, u32 tf, int cond, int offset)
+ u32 tSYMBOL, u32 tf, int offset)
{
if (!ic_clk)
return i2c_dw_read_scl_reg(dev, reg);
/*
- * DesignWare I2C core doesn't seem to have solid strategy to meet
- * the tHD;STA timing spec. Configuring _HCNT based on tHIGH spec
- * will result in violation of the tHD;STA spec.
+ * Conditional expression:
+ *
+ * IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
+ *
+ * This is just experimental rule; the tHD;STA period turned
+ * out to be proportinal to (_HCNT + 3). With this setting,
+ * we could meet both tHIGH and tHD;STA timing specs.
+ *
+ * If unsure, you'd better to take this alternative.
+ *
+ * The reason why we need to take into account "tf" here,
+ * is the same as described in i2c_dw_scl_lcnt().
*/
- if (cond)
- /*
- * Conditional expression:
- *
- * IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
- *
- * This is based on the DW manuals, and represents an ideal
- * configuration. The resulting I2C bus speed will be
- * faster than any of the others.
- *
- * If your hardware is free from tHD;STA issue, try this one.
- */
- return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * tSYMBOL, MICRO) -
- 8 + offset;
- else
- /*
- * Conditional expression:
- *
- * IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
- *
- * This is just experimental rule; the tHD;STA period turned
- * out to be proportinal to (_HCNT + 3). With this setting,
- * we could meet both tHIGH and tHD;STA timing specs.
- *
- * If unsure, you'd better to take this alternative.
- *
- * The reason why we need to take into account "tf" here,
- * is the same as described in i2c_dw_scl_lcnt().
- */
- return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tSYMBOL + tf), MICRO) -
- 3 + offset;
+ return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tSYMBOL + tf), MICRO) - 3 + offset;
}
u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
@@ -467,8 +453,7 @@ u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
* account the fall time of SCL signal (tf). Default tf value
* should be 0.3 us, for safety.
*/
- return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tLOW + tf), MICRO) -
- 1 + offset;
+ return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tLOW + tf), MICRO) - 1 + offset;
}
int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
@@ -524,7 +509,7 @@ err_release_lock:
void __i2c_dw_disable(struct dw_i2c_dev *dev)
{
struct i2c_timings *t = &dev->timings;
- unsigned int raw_intr_stats;
+ unsigned int raw_intr_stats, ic_stats;
unsigned int enable;
int timeout = 100;
bool abort_needed;
@@ -532,9 +517,11 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
int ret;
regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_intr_stats);
+ regmap_read(dev->map, DW_IC_STATUS, &ic_stats);
regmap_read(dev->map, DW_IC_ENABLE, &enable);
- abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD;
+ abort_needed = (raw_intr_stats & DW_IC_INTR_MST_ON_HOLD) ||
+ (ic_stats & DW_IC_STATUS_MASTER_HOLD_TX_FIFO_EMPTY);
if (abort_needed) {
if (!(enable & DW_IC_ENABLE_ENABLE)) {
regmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);
@@ -569,7 +556,7 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
/*
* Wait 10 times the signaling period of the highest I2C
- * transfer supported by the driver (for 400KHz this is
+ * transfer supported by the driver (for 400kHz this is
* 25us) as described in the DesignWare I2C databook.
*/
usleep_range(25, 250);
@@ -676,10 +663,10 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
if (abort_source & DW_IC_TX_ARB_LOST)
return -EAGAIN;
- else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
+ if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
return -EINVAL; /* wrong msgs[] data */
- else
- return -EIO;
+
+ return -EIO;
}
int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 8e8854ec9882..347843b4f5dd 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -116,6 +116,7 @@
#define DW_IC_STATUS_RFNE BIT(3)
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
+#define DW_IC_STATUS_MASTER_HOLD_TX_FIFO_EMPTY BIT(7)
#define DW_IC_SDA_HOLD_RX_SHIFT 16
#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16)
@@ -142,10 +143,10 @@
#define DW_IC_SLAVE 1
/*
- * Hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
+ * Hardware abort codes from the DW_IC_TX_ABRT_SOURCE register.
*
- * Only expected abort codes are listed here
- * refer to the datasheet for the full list
+ * Only expected abort codes are listed here,
+ * refer to the datasheet for the full list.
*/
#define ABRT_7B_ADDR_NOACK 0
#define ABRT_10ADDR1_NOACK 1
@@ -200,7 +201,7 @@ struct reset_control;
* @rst: optional reset for the controller
* @slave: represent an I2C slave device
* @get_clk_rate_khz: callback to retrieve IP specific bus speed
- * @cmd_err: run time hadware error code
+ * @cmd_err: run time hardware error code
* @msgs: points to an array of messages currently being transferred
* @msgs_num: the number of elements in msgs
* @msg_write_idx: the element index of the current tx message in the msgs array
@@ -236,11 +237,15 @@ struct reset_control;
* @release_lock: function to release a hardware lock on the bus
* @semaphore_idx: Index of table with semaphore type attached to the bus. It's
* -1 if there is no semaphore.
- * @shared_with_punit: true if this bus is shared with the SoCs PUNIT
+ * @shared_with_punit: true if this bus is shared with the SoC's PUNIT
* @init: function to initialize the I2C hardware
* @set_sda_hold_time: callback to retrieve IP specific SDA hold timing
* @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE
* @rinfo: I²C GPIO recovery information
+ * @bus_capacitance_pF: bus capacitance in picofarads
+ * @clk_freq_optimized: if this value is true, it means the hardware reduces
+ * its internal clock frequency by reducing the internal latency required
+ * to generate the high period and low period of SCL line.
*
* HCNT and LCNT parameters can be used if the platform knows more accurate
* values than the one computed based only on the input clock frequency.
@@ -298,6 +303,8 @@ struct dw_i2c_dev {
int (*set_sda_hold_time)(struct dw_i2c_dev *dev);
int mode;
struct i2c_bus_recovery_info rinfo;
+ u32 bus_capacitance_pF;
+ bool clk_freq_optimized;
};
#define ACCESS_INTR_MASK BIT(0)
@@ -328,7 +335,7 @@ struct i2c_dw_semaphore_callbacks {
int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
u32 i2c_dw_scl_hcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
- u32 tSYMBOL, u32 tf, int cond, int offset);
+ u32 tSYMBOL, u32 tf, int offset);
u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
u32 tLOW, u32 tf, int offset);
int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index e8ac9a7bf0b3..eca8998d640f 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -71,7 +71,6 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
ic_clk,
4000, /* tHD;STA = tHIGH = 4.0 us */
sda_falling_time,
- 0, /* 0: DW default, 1: Ideal */
0); /* No offset */
dev->ss_lcnt =
i2c_dw_scl_lcnt(dev,
@@ -105,7 +104,6 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
ic_clk,
260, /* tHIGH = 260 ns */
sda_falling_time,
- 0, /* DW default */
0); /* No offset */
dev->fs_lcnt =
i2c_dw_scl_lcnt(dev,
@@ -129,7 +127,6 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
ic_clk,
600, /* tHD;STA = tHIGH = 0.6 us */
sda_falling_time,
- 0, /* 0: DW default, 1: Ideal */
0); /* No offset */
dev->fs_lcnt =
i2c_dw_scl_lcnt(dev,
@@ -154,20 +151,38 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
dev->hs_hcnt = 0;
dev->hs_lcnt = 0;
} else if (!dev->hs_hcnt || !dev->hs_lcnt) {
+ u32 t_high, t_low;
+
+ /*
+ * The legal values stated in the databook for bus
+ * capacitance are only 100pF and 400pF.
+ * If dev->bus_capacitance_pF is greater than or equals
+ * to 400, t_high and t_low are assumed to be
+ * appropriate values for 400pF, otherwise 100pF.
+ */
+ if (dev->bus_capacitance_pF >= 400) {
+ /* assume bus capacitance is 400pF */
+ t_high = dev->clk_freq_optimized ? 160 : 120;
+ t_low = 320;
+ } else {
+ /* assume bus capacitance is 100pF */
+ t_high = 60;
+ t_low = dev->clk_freq_optimized ? 120 : 160;
+ }
+
ic_clk = i2c_dw_clk_rate(dev);
dev->hs_hcnt =
i2c_dw_scl_hcnt(dev,
DW_IC_HS_SCL_HCNT,
ic_clk,
- 160, /* tHIGH = 160 ns */
+ t_high,
sda_falling_time,
- 0, /* DW default */
0); /* No offset */
dev->hs_lcnt =
i2c_dw_scl_lcnt(dev,
DW_IC_HS_SCL_LCNT,
ic_clk,
- 320, /* tLOW = 320 ns */
+ t_low,
scl_falling_time,
0); /* No offset */
}
@@ -184,12 +199,14 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
}
/**
- * i2c_dw_init_master() - Initialize the designware I2C master hardware
+ * i2c_dw_init_master() - Initialize the DesignWare I2C master hardware
* @dev: device private data
*
* This functions configures and enables the I2C master.
* This function is called during I2C init function, and in case of timeout at
* run time.
+ *
+ * Return: 0 on success, or negative errno otherwise.
*/
static int i2c_dw_init_master(struct dw_i2c_dev *dev)
{
@@ -357,7 +374,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
/*
* Initiate the i2c read/write transaction of buffer length,
* and poll for bus busy status. For the last message transfer,
- * update the command with stopbit enable.
+ * update the command with stop bit enable.
*/
for (msg_itr_lmt = buf_len; msg_itr_lmt > 0; msg_itr_lmt--) {
if (msg_wrt_idx == num_msgs - 1 && msg_itr_lmt == 1)
@@ -402,7 +419,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
/*
* Initiate (and continue) low level master read/write transaction.
- * This function is only called from i2c_dw_isr, and pumping i2c_msg
+ * This function is only called from i2c_dw_isr(), and pumping i2c_msg
* messages into the tx buffer. Even if the size of i2c_msg data is
* longer than the size of the tx buffer, it handles everything.
*/
@@ -440,7 +457,8 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
buf = msgs[dev->msg_write_idx].buf;
buf_len = msgs[dev->msg_write_idx].len;
- /* If both IC_EMPTYFIFO_HOLD_MASTER_EN and
+ /*
+ * If both IC_EMPTYFIFO_HOLD_MASTER_EN and
* IC_RESTART_EN are set, we must manually
* set restart bit between messages.
*/
@@ -971,7 +989,7 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
rinfo->unprepare_recovery = i2c_dw_unprepare_recovery;
adap->bus_recovery_info = rinfo;
- dev_info(dev->dev, "running with gpio recovery mode! scl%s",
+ dev_info(dev->dev, "running with GPIO recovery mode! scl%s",
rinfo->sda_gpiod ? ",sda" : "");
return 0;
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 7b2c5d71a7fc..38265c3dc454 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -51,7 +51,7 @@ struct dw_scl_sda_cfg {
u16 fs_hcnt;
u16 ss_lcnt;
u16 fs_lcnt;
- u32 sda_hold;
+ u32 sda_hold_time;
};
struct dw_pci_controller {
@@ -76,7 +76,7 @@ static struct dw_scl_sda_cfg byt_config = {
.fs_hcnt = 0x55,
.ss_lcnt = 0x200,
.fs_lcnt = 0x99,
- .sda_hold = 0x6,
+ .sda_hold_time = 0x6,
};
/* Haswell HCNT/LCNT/SDA hold time */
@@ -85,14 +85,14 @@ static struct dw_scl_sda_cfg hsw_config = {
.fs_hcnt = 0x48,
.ss_lcnt = 0x01fb,
.fs_lcnt = 0xa0,
- .sda_hold = 0x9,
+ .sda_hold_time = 0x9,
};
/* NAVI-AMD HCNT/LCNT/SDA hold time */
static struct dw_scl_sda_cfg navi_amd_config = {
.ss_hcnt = 0x1ae,
.ss_lcnt = 0x23a,
- .sda_hold = 0x9,
+ .sda_hold_time = 0x9,
};
static u32 mfld_get_clk_rate_khz(struct dw_i2c_dev *dev)
@@ -207,6 +207,7 @@ static const struct software_node dgpu_node = {
static int i2c_dw_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
+ struct device *device = &pdev->dev;
struct dw_i2c_dev *dev;
struct i2c_adapter *adap;
int r;
@@ -214,25 +215,22 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
struct dw_scl_sda_cfg *cfg;
if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers))
- return dev_err_probe(&pdev->dev, -EINVAL,
- "Invalid driver data %ld\n",
+ return dev_err_probe(device, -EINVAL, "Invalid driver data %ld\n",
id->driver_data);
controller = &dw_pci_controllers[id->driver_data];
r = pcim_enable_device(pdev);
if (r)
- return dev_err_probe(&pdev->dev, r,
- "Failed to enable I2C PCI device\n");
+ return dev_err_probe(device, r, "Failed to enable I2C PCI device\n");
pci_set_master(pdev);
r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
if (r)
- return dev_err_probe(&pdev->dev, r,
- "I/O memory remapping failed\n");
+ return dev_err_probe(device, r, "I/O memory remapping failed\n");
- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ dev = devm_kzalloc(device, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
@@ -242,7 +240,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
dev->get_clk_rate_khz = controller->get_clk_rate_khz;
dev->base = pcim_iomap_table(pdev)[0];
- dev->dev = &pdev->dev;
+ dev->dev = device;
dev->irq = pci_irq_vector(pdev, 0);
dev->flags |= controller->flags;
@@ -266,7 +264,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
dev->fs_hcnt = cfg->fs_hcnt;
dev->ss_lcnt = cfg->ss_lcnt;
dev->fs_lcnt = cfg->fs_lcnt;
- dev->sda_hold_time = cfg->sda_hold;
+ dev->sda_hold_time = cfg->sda_hold_time;
}
adap = &dev->adapter;
@@ -281,14 +279,14 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) {
dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node);
if (IS_ERR(dev->slave))
- return dev_err_probe(dev->dev, PTR_ERR(dev->slave),
+ return dev_err_probe(device, PTR_ERR(dev->slave),
"register UCSI failed\n");
}
- pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_put_autosuspend(&pdev->dev);
- pm_runtime_allow(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(device, 1000);
+ pm_runtime_use_autosuspend(device);
+ pm_runtime_put_autosuspend(device);
+ pm_runtime_allow(device);
return 0;
}
@@ -296,11 +294,12 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
static void i2c_dw_pci_remove(struct pci_dev *pdev)
{
struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
+ struct device *device = &pdev->dev;
i2c_dw_disable(dev);
- pm_runtime_forbid(&pdev->dev);
- pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_forbid(device);
+ pm_runtime_get_noresume(device);
i2c_del_adapter(&dev->adapter);
}
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 2d0c7348e491..3e12aab6bf2d 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -72,7 +72,7 @@ static int bt1_i2c_write(void *context, unsigned int reg, unsigned int val)
return ret;
return regmap_write(dev->sysmap, BT1_I2C_CTL,
- BT1_I2C_CTL_GO | BT1_I2C_CTL_WR | (reg & BT1_I2C_CTL_ADDR_MASK));
+ BT1_I2C_CTL_GO | BT1_I2C_CTL_WR | (reg & BT1_I2C_CTL_ADDR_MASK));
}
static const struct regmap_config bt1_i2c_cfg = {
@@ -205,6 +205,7 @@ static void i2c_dw_remove_lock_support(struct dw_i2c_dev *dev)
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
+ struct device *device = &pdev->dev;
struct i2c_adapter *adap;
struct dw_i2c_dev *dev;
int irq, ret;
@@ -213,15 +214,15 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
+ dev = devm_kzalloc(device, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
- dev->flags = (uintptr_t)device_get_match_data(&pdev->dev);
- if (device_property_present(&pdev->dev, "wx,i2c-snps-model"))
+ dev->flags = (uintptr_t)device_get_match_data(device);
+ if (device_property_present(device, "wx,i2c-snps-model"))
dev->flags = MODEL_WANGXUN_SP | ACCESS_POLLING;
- dev->dev = &pdev->dev;
+ dev->dev = device;
dev->irq = irq;
platform_set_drvdata(pdev, dev);
@@ -229,7 +230,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
if (ret)
return ret;
- dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+ dev->rst = devm_reset_control_get_optional_exclusive(device, NULL);
if (IS_ERR(dev->rst))
return PTR_ERR(dev->rst);
@@ -246,13 +247,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
i2c_dw_configure(dev);
/* Optional interface clock */
- dev->pclk = devm_clk_get_optional(&pdev->dev, "pclk");
+ dev->pclk = devm_clk_get_optional(device, "pclk");
if (IS_ERR(dev->pclk)) {
ret = PTR_ERR(dev->pclk);
goto exit_reset;
}
- dev->clk = devm_clk_get_optional(&pdev->dev, NULL);
+ dev->clk = devm_clk_get_optional(device, NULL);
if (IS_ERR(dev->clk)) {
ret = PTR_ERR(dev->clk);
goto exit_reset;
@@ -277,31 +278,27 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
adap = &dev->adapter;
adap->owner = THIS_MODULE;
adap->class = dmi_check_system(dw_i2c_hwmon_class_dmi) ?
- I2C_CLASS_HWMON : I2C_CLASS_DEPRECATED;
+ I2C_CLASS_HWMON : I2C_CLASS_DEPRECATED;
adap->nr = -1;
- if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
- dev_pm_set_driver_flags(&pdev->dev,
- DPM_FLAG_SMART_PREPARE);
- } else {
- dev_pm_set_driver_flags(&pdev->dev,
- DPM_FLAG_SMART_PREPARE |
- DPM_FLAG_SMART_SUSPEND);
- }
+ if (dev->flags & ACCESS_NO_IRQ_SUSPEND)
+ dev_pm_set_driver_flags(device, DPM_FLAG_SMART_PREPARE);
+ else
+ dev_pm_set_driver_flags(device, DPM_FLAG_SMART_PREPARE | DPM_FLAG_SMART_SUSPEND);
- device_enable_async_suspend(&pdev->dev);
+ device_enable_async_suspend(device);
/* The code below assumes runtime PM to be disabled. */
- WARN_ON(pm_runtime_enabled(&pdev->dev));
+ WARN_ON(pm_runtime_enabled(device));
- pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(device, 1000);
+ pm_runtime_use_autosuspend(device);
+ pm_runtime_set_active(device);
if (dev->shared_with_punit)
- pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_get_noresume(device);
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_enable(device);
ret = i2c_dw_probe(dev);
if (ret)
@@ -319,15 +316,16 @@ exit_reset:
static void dw_i2c_plat_remove(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+ struct device *device = &pdev->dev;
- pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_get_sync(device);
i2c_del_adapter(&dev->adapter);
i2c_dw_disable(dev);
- pm_runtime_dont_use_autosuspend(&pdev->dev);
- pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(device);
+ pm_runtime_put_sync(device);
dw_i2c_plat_pm_cleanup(dev);
i2c_dw_remove_lock_support(dev);
@@ -351,9 +349,11 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "AMDI0019", ACCESS_INTR_MASK | ARBITRATION_SEMAPHORE },
{ "AMDI0510", 0 },
{ "APMC0D0F", 0 },
+ { "FUJI200B", 0 },
{ "HISI02A1", 0 },
{ "HISI02A2", 0 },
{ "HISI02A3", 0 },
+ { "HJMC3001", 0 },
{ "HYGO0010", ACCESS_INTR_MASK },
{ "INT33C2", 0 },
{ "INT33C3", 0 },
@@ -372,7 +372,7 @@ MODULE_DEVICE_TABLE(platform, dw_i2c_platform_ids);
static struct platform_driver dw_i2c_driver = {
.probe = dw_i2c_plat_probe,
- .remove_new = dw_i2c_plat_remove,
+ .remove = dw_i2c_plat_remove,
.driver = {
.name = "i2c_designware",
.of_match_table = dw_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index 7035296aa24c..fad568e3523b 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -32,12 +32,14 @@ static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev)
}
/**
- * i2c_dw_init_slave() - Initialize the designware i2c slave hardware
+ * i2c_dw_init_slave() - Initialize the DesignWare i2c slave hardware
* @dev: device private data
*
* This function configures and enables the I2C in slave mode.
* This function is called during I2C init function, and in case of timeout at
* run time.
+ *
+ * Return: 0 on success, or negative errno otherwise.
*/
static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
{
@@ -264,7 +266,7 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr_slave,
IRQF_SHARED, dev_name(dev->dev), dev);
if (ret) {
- dev_err(dev->dev, "failure requesting irq %i: %d\n",
+ dev_err(dev->dev, "failure requesting IRQ %i: %d\n",
dev->irq, ret);
return ret;
}
diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c
index 3dc5a46698fc..38d7f31aee79 100644
--- a/drivers/i2c/busses/i2c-digicolor.c
+++ b/drivers/i2c/busses/i2c-digicolor.c
@@ -363,7 +363,7 @@ MODULE_DEVICE_TABLE(of, dc_i2c_match);
static struct platform_driver dc_i2c_driver = {
.probe = dc_i2c_probe,
- .remove_new = dc_i2c_remove,
+ .remove = dc_i2c_remove,
.driver = {
.name = "digicolor-i2c",
.of_match_table = dc_i2c_match,
diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c
index 11ed055143d3..bde2ef098862 100644
--- a/drivers/i2c/busses/i2c-dln2.c
+++ b/drivers/i2c/busses/i2c-dln2.c
@@ -245,7 +245,7 @@ static void dln2_i2c_remove(struct platform_device *pdev)
static struct platform_driver dln2_i2c_driver = {
.driver.name = "dln2-i2c",
.probe = dln2_i2c_probe,
- .remove_new = dln2_i2c_remove,
+ .remove = dln2_i2c_remove,
};
module_platform_driver(dln2_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c
index d08be3f3cede..2512cef8e2a2 100644
--- a/drivers/i2c/busses/i2c-emev2.c
+++ b/drivers/i2c/busses/i2c-emev2.c
@@ -425,7 +425,7 @@ static const struct of_device_id em_i2c_ids[] = {
static struct platform_driver em_i2c_driver = {
.probe = em_i2c_probe,
- .remove_new = em_i2c_remove,
+ .remove = em_i2c_remove,
.driver = {
.name = "em-i2c",
.of_match_table = em_i2c_ids,
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index d8baca9b610c..e330015087ab 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -1009,7 +1009,7 @@ static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
static struct platform_driver exynos5_i2c_driver = {
.probe = exynos5_i2c_probe,
- .remove_new = exynos5_i2c_remove,
+ .remove = exynos5_i2c_remove,
.driver = {
.name = "exynos5-hsi2c",
.pm = pm_sleep_ptr(&exynos5_i2c_dev_pm_ops),
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index e0bd218e2f14..f4355b17bfbf 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -481,7 +481,7 @@ static struct platform_driver i2c_gpio_driver = {
.acpi_match_table = i2c_gpio_acpi_match,
},
.probe = i2c_gpio_probe,
- .remove_new = i2c_gpio_remove,
+ .remove = i2c_gpio_remove,
};
static int __init i2c_gpio_init(void)
diff --git a/drivers/i2c/busses/i2c-gxp.c b/drivers/i2c/busses/i2c-gxp.c
index efafc0528c44..0fc39caa6c87 100644
--- a/drivers/i2c/busses/i2c-gxp.c
+++ b/drivers/i2c/busses/i2c-gxp.c
@@ -595,7 +595,7 @@ MODULE_DEVICE_TABLE(of, gxp_i2c_of_match);
static struct platform_driver gxp_i2c_driver = {
.probe = gxp_i2c_probe,
- .remove_new = gxp_i2c_remove,
+ .remove = gxp_i2c_remove,
.driver = {
.name = "gxp-i2c",
.of_match_table = gxp_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index ec1ebacb9aa8..78c5845e0877 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -454,7 +454,7 @@ static struct platform_driver highlander_i2c_driver = {
},
.probe = highlander_i2c_probe,
- .remove_new = highlander_i2c_remove,
+ .remove = highlander_i2c_remove,
};
module_platform_driver(highlander_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
index 64cade6ba923..370f32974763 100644
--- a/drivers/i2c/busses/i2c-hix5hd2.c
+++ b/drivers/i2c/busses/i2c-hix5hd2.c
@@ -508,7 +508,7 @@ MODULE_DEVICE_TABLE(of, hix5hd2_i2c_match);
static struct platform_driver hix5hd2_i2c_driver = {
.probe = hix5hd2_i2c_probe,
- .remove_new = hix5hd2_i2c_remove,
+ .remove = hix5hd2_i2c_remove,
.driver = {
.name = "hix5hd2-i2c",
.pm = pm_ptr(&hix5hd2_i2c_pm_ops),
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 299fe9d3afab..75dab01d43a7 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -81,6 +81,8 @@
* Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes
* Birch Stream (SOC) 0x5796 32 hard yes yes yes
* Arrow Lake-H (SOC) 0x7722 32 hard yes yes yes
+ * Panther Lake-H (SOC) 0xe322 32 hard yes yes yes
+ * Panther Lake-P (SOC) 0xe422 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@@ -261,6 +263,8 @@
#define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323
#define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3
#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_SOC_S_SMBUS 0xae22
+#define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_H_SMBUS 0xe322
+#define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_P_SMBUS 0xe422
struct i801_mux_config {
char *gpio_chip;
@@ -1055,6 +1059,8 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 82dedb1bb5be..c76c4116ddc7 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -790,7 +790,7 @@ static struct platform_driver ibm_iic_driver = {
.of_match_table = ibm_iic_match,
},
.probe = iic_probe,
- .remove_new = iic_remove,
+ .remove = iic_remove,
};
module_platform_driver(ibm_iic_driver);
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index e0e87185f6bb..02f75cf310aa 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -1497,7 +1497,7 @@ static struct platform_driver img_scb_i2c_driver = {
.pm = pm_ptr(&img_i2c_pm),
},
.probe = img_i2c_probe,
- .remove_new = img_i2c_remove,
+ .remove = img_i2c_remove,
};
module_platform_driver(img_scb_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 976d43f73f38..8adf2963d764 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -703,7 +703,7 @@ static const struct dev_pm_ops lpi2c_pm_ops = {
static struct platform_driver lpi2c_imx_driver = {
.probe = lpi2c_imx_probe,
- .remove_new = lpi2c_imx_remove,
+ .remove = lpi2c_imx_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = lpi2c_imx_of_match,
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 98539313cbc9..f751d231ded8 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -17,7 +17,7 @@
* Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
*
* Copyright 2013 Freescale Semiconductor, Inc.
- * Copyright 2020 NXP
+ * Copyright 2020, 2024 NXP
*
*/
@@ -84,6 +84,7 @@
#define IMX_I2C_REGSHIFT 2
#define VF610_I2C_REGSHIFT 0
+#define S32G_I2C_REGSHIFT 0
/* Bits of IMX I2C registers */
#define I2SR_RXAK 0x01
@@ -165,9 +166,34 @@ static struct imx_i2c_clk_pair vf610_i2c_clk_div[] = {
{ 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E },
};
+/* S32G2/S32G3 clock divider, register value pairs */
+static struct imx_i2c_clk_pair s32g2_i2c_clk_div[] = {
+ { 34, 0x00 }, { 36, 0x01 }, { 38, 0x02 }, { 40, 0x03 },
+ { 42, 0x04 }, { 44, 0x05 }, { 46, 0x06 }, { 48, 0x09 },
+ { 52, 0x0A }, { 54, 0x07 }, { 56, 0x0B }, { 60, 0x0C },
+ { 64, 0x0D }, { 68, 0x40 }, { 72, 0x0E }, { 76, 0x42 },
+ { 80, 0x12 }, { 84, 0x0F }, { 88, 0x13 }, { 96, 0x14 },
+ { 104, 0x15 }, { 108, 0x47 }, { 112, 0x19 }, { 120, 0x16 },
+ { 128, 0x1A }, { 136, 0x80 }, { 144, 0x17 }, { 152, 0x82 },
+ { 160, 0x1C }, { 168, 0x84 }, { 176, 0x1D }, { 192, 0x21 },
+ { 208, 0x1E }, { 216, 0x87 }, { 224, 0x22 }, { 240, 0x56 },
+ { 256, 0x1F }, { 288, 0x24 }, { 320, 0x25 }, { 336, 0x8F },
+ { 352, 0x93 }, { 356, 0x5D }, { 358, 0x98 }, { 384, 0x26 },
+ { 416, 0x56 }, { 448, 0x2A }, { 480, 0x27 }, { 512, 0x2B },
+ { 576, 0x2C }, { 640, 0x2D }, { 704, 0x9D }, { 768, 0x2E },
+ { 832, 0x9D }, { 896, 0x32 }, { 960, 0x2F }, { 1024, 0x33 },
+ { 1152, 0x34 }, { 1280, 0x35 }, { 1536, 0x36 }, { 1792, 0x3A },
+ { 1920, 0x37 }, { 2048, 0x3B }, { 2304, 0x74 }, { 2560, 0x3D },
+ { 3072, 0x3E }, { 3584, 0x7A }, { 3840, 0x3F }, { 4096, 0x7B },
+ { 4608, 0x7C }, { 5120, 0x7D }, { 6144, 0x7E }, { 7168, 0xBA },
+ { 7680, 0x7F }, { 8192, 0xBB }, { 9216, 0xBC }, { 10240, 0xBD },
+ { 12288, 0xBE }, { 15360, 0xBF },
+};
+
enum imx_i2c_type {
IMX1_I2C,
IMX21_I2C,
+ S32G_I2C,
VF610_I2C,
};
@@ -197,6 +223,17 @@ struct imx_i2c_dma {
enum dma_data_direction dma_data_dir;
};
+enum imx_i2c_state {
+ IMX_I2C_STATE_DONE,
+ IMX_I2C_STATE_FAILED,
+ IMX_I2C_STATE_WRITE,
+ IMX_I2C_STATE_DMA,
+ IMX_I2C_STATE_READ,
+ IMX_I2C_STATE_READ_CONTINUE,
+ IMX_I2C_STATE_READ_BLOCK_DATA,
+ IMX_I2C_STATE_READ_BLOCK_DATA_LEN,
+};
+
struct imx_i2c_struct {
struct i2c_adapter adapter;
struct clk *clk;
@@ -216,6 +253,14 @@ struct imx_i2c_struct {
struct i2c_client *slave;
enum i2c_slave_event last_slave_event;
+ struct i2c_msg *msg;
+ unsigned int msg_buf_idx;
+ int isr_result;
+ bool is_lastmsg;
+ enum imx_i2c_state state;
+
+ bool multi_master;
+
/* For checking slave events. */
spinlock_t slave_lock;
struct hrtimer slave_timer;
@@ -258,7 +303,15 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
.ndivs = ARRAY_SIZE(vf610_i2c_clk_div),
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C,
.i2cr_ien_opcode = I2CR_IEN_OPCODE_0,
+};
+static const struct imx_i2c_hwdata s32g2_i2c_hwdata = {
+ .devtype = S32G_I2C,
+ .regshift = S32G_I2C_REGSHIFT,
+ .clk_div = s32g2_i2c_clk_div,
+ .ndivs = ARRAY_SIZE(s32g2_i2c_clk_div),
+ .i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C,
+ .i2cr_ien_opcode = I2CR_IEN_OPCODE_0,
};
static const struct platform_device_id imx_i2c_devtype[] = {
@@ -288,6 +341,7 @@ static const struct of_device_id i2c_imx_dt_ids[] = {
{ .compatible = "fsl,imx8mp-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,imx8mq-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, },
+ { .compatible = "nxp,s32g2-i2c", .data = &s32g2_i2c_hwdata, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, i2c_imx_dt_ids);
@@ -481,6 +535,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a
unsigned long orig_jiffies = jiffies;
unsigned int temp;
+ if (!i2c_imx->multi_master)
+ return 0;
+
while (1) {
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
@@ -540,8 +597,8 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
return -ETIMEDOUT;
}
- /* check for arbitration lost */
- if (i2c_imx->i2csr & I2SR_IAL) {
+ /* In multi-master mode check for arbitration lost */
+ if (i2c_imx->multi_master && (i2c_imx->i2csr & I2SR_IAL)) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__);
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
@@ -903,11 +960,156 @@ static int i2c_imx_unreg_slave(struct i2c_client *client)
return ret;
}
+static inline int i2c_imx_isr_acked(struct imx_i2c_struct *i2c_imx)
+{
+ i2c_imx->isr_result = 0;
+
+ if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) {
+ i2c_imx->state = IMX_I2C_STATE_FAILED;
+ i2c_imx->isr_result = -ENXIO;
+ wake_up(&i2c_imx->queue);
+ }
+
+ return i2c_imx->isr_result;
+}
+
+static inline int i2c_imx_isr_write(struct imx_i2c_struct *i2c_imx)
+{
+ int result;
+
+ result = i2c_imx_isr_acked(i2c_imx);
+ if (result)
+ return result;
+
+ if (i2c_imx->msg->len == i2c_imx->msg_buf_idx)
+ return 0;
+
+ imx_i2c_write_reg(i2c_imx->msg->buf[i2c_imx->msg_buf_idx++], i2c_imx, IMX_I2C_I2DR);
+
+ return 1;
+}
+
+static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx)
+{
+ int result;
+ unsigned int temp;
+
+ result = i2c_imx_isr_acked(i2c_imx);
+ if (result)
+ return result;
+
+ /* setup bus to read data */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp &= ~I2CR_MTX;
+ if (i2c_imx->msg->len - 1)
+ temp &= ~I2CR_TXAK;
+
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
+
+ return 0;
+}
+
+static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)
+{
+ unsigned int temp;
+
+ if ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) {
+ if (i2c_imx->is_lastmsg) {
+ /*
+ * It must generate STOP before read I2DR to prevent
+ * controller from generating another clock cycle
+ */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ if (!(temp & I2CR_MSTA))
+ i2c_imx->stopped = 1;
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ } else {
+ /*
+ * For i2c master receiver repeat restart operation like:
+ * read -> repeat MSTA -> read/write
+ * The controller must set MTX before read the last byte in
+ * the first read operation, otherwise the first read cost
+ * one extra clock cycle.
+ */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp |= I2CR_MTX;
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ }
+ } else if (i2c_imx->msg_buf_idx == (i2c_imx->msg->len - 2)) {
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp |= I2CR_TXAK;
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ }
+
+ i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+}
+
+static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx)
+{
+ u8 len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+
+ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {
+ i2c_imx->isr_result = -EPROTO;
+ i2c_imx->state = IMX_I2C_STATE_FAILED;
+ wake_up(&i2c_imx->queue);
+ }
+ i2c_imx->msg->len += len;
+}
+
static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status)
{
- /* save status register */
- i2c_imx->i2csr = status;
- wake_up(&i2c_imx->queue);
+ /*
+ * This state machine handles I2C reception and transmission in non-DMA
+ * mode. We must process all the data in the ISR to reduce the delay
+ * between two consecutive messages. If the data is not processed in
+ * the ISR, SMBus devices may timeout, leading to a bus error.
+ */
+ switch (i2c_imx->state) {
+ case IMX_I2C_STATE_DMA:
+ i2c_imx->i2csr = status;
+ wake_up(&i2c_imx->queue);
+ break;
+
+ case IMX_I2C_STATE_READ:
+ if (i2c_imx_isr_read(i2c_imx))
+ break;
+ i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE;
+ break;
+
+ case IMX_I2C_STATE_READ_CONTINUE:
+ i2c_imx_isr_read_continue(i2c_imx);
+ if (i2c_imx->msg_buf_idx == i2c_imx->msg->len) {
+ i2c_imx->state = IMX_I2C_STATE_DONE;
+ wake_up(&i2c_imx->queue);
+ }
+ break;
+
+ case IMX_I2C_STATE_READ_BLOCK_DATA:
+ if (i2c_imx_isr_read(i2c_imx))
+ break;
+ i2c_imx->state = IMX_I2C_STATE_READ_BLOCK_DATA_LEN;
+ break;
+
+ case IMX_I2C_STATE_READ_BLOCK_DATA_LEN:
+ i2c_imx_isr_read_block_data_len(i2c_imx);
+ i2c_imx->state = IMX_I2C_STATE_READ_CONTINUE;
+ break;
+
+ case IMX_I2C_STATE_WRITE:
+ if (i2c_imx_isr_write(i2c_imx))
+ break;
+ i2c_imx->state = IMX_I2C_STATE_DONE;
+ wake_up(&i2c_imx->queue);
+ break;
+
+ default:
+ i2c_imx->i2csr = status;
+ i2c_imx->state = IMX_I2C_STATE_FAILED;
+ i2c_imx->isr_result = -EINVAL;
+ wake_up(&i2c_imx->queue);
+ }
return IRQ_HANDLED;
}
@@ -954,6 +1156,8 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
struct imx_i2c_dma *dma = i2c_imx->dma;
struct device *dev = &i2c_imx->adapter.dev;
+ i2c_imx->state = IMX_I2C_STATE_DMA;
+
dma->chan_using = dma->chan_tx;
dma->dma_transfer_dir = DMA_MEM_TO_DEV;
dma->dma_data_dir = DMA_TO_DEVICE;
@@ -1006,6 +1210,42 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
return i2c_imx_acked(i2c_imx);
}
+static int i2c_imx_prepare_read(struct imx_i2c_struct *i2c_imx,
+ struct i2c_msg *msgs, bool use_dma)
+{
+ int result;
+ unsigned int temp = 0;
+
+ /* write slave address */
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
+ result = i2c_imx_trx_complete(i2c_imx, !use_dma);
+ if (result)
+ return result;
+ result = i2c_imx_acked(i2c_imx);
+ if (result)
+ return result;
+
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
+
+ /* setup bus to read data */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp &= ~I2CR_MTX;
+
+ /*
+ * Reset the I2CR_TXAK flag initially for SMBus block read since the
+ * length is unknown
+ */
+ if (msgs->len - 1)
+ temp &= ~I2CR_TXAK;
+ if (use_dma)
+ temp |= I2CR_DMAEN;
+
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
+
+ return 0;
+}
+
static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
struct i2c_msg *msgs, bool is_lastmsg)
{
@@ -1016,6 +1256,13 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
struct imx_i2c_dma *dma = i2c_imx->dma;
struct device *dev = &i2c_imx->adapter.dev;
+ i2c_imx->state = IMX_I2C_STATE_DMA;
+
+ result = i2c_imx_prepare_read(i2c_imx, msgs, true);
+ if (result)
+ return result;
+
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
dma->chan_using = dma->chan_rx;
dma->dma_transfer_dir = DMA_DEV_TO_MEM;
@@ -1092,8 +1339,8 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
return 0;
}
-static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
- bool atomic)
+static int i2c_imx_atomic_write(struct imx_i2c_struct *i2c_imx,
+ struct i2c_msg *msgs)
{
int i, result;
@@ -1102,7 +1349,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
/* write slave address */
imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx, atomic);
+ result = i2c_imx_trx_complete(i2c_imx, true);
if (result)
return result;
result = i2c_imx_acked(i2c_imx);
@@ -1116,7 +1363,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
"<%s> write byte: B%d=0x%X\n",
__func__, i, msgs->buf[i]);
imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx, atomic);
+ result = i2c_imx_trx_complete(i2c_imx, true);
if (result)
return result;
result = i2c_imx_acked(i2c_imx);
@@ -1126,55 +1373,54 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
return 0;
}
-static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
- bool is_lastmsg, bool atomic)
+static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
+{
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n",
+ __func__, i2c_8bit_addr_from_msg(msgs));
+
+ i2c_imx->state = IMX_I2C_STATE_WRITE;
+ i2c_imx->msg = msgs;
+ i2c_imx->msg_buf_idx = 0;
+
+ /*
+ * By writing the device address we start the state machine in the ISR.
+ * The ISR will report when it is done or when it fails.
+ */
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
+ wait_event_timeout(i2c_imx->queue,
+ i2c_imx->state == IMX_I2C_STATE_DONE ||
+ i2c_imx->state == IMX_I2C_STATE_FAILED,
+ (msgs->len + 1) * HZ / 10);
+ if (i2c_imx->state == IMX_I2C_STATE_FAILED) {
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> write failed with %d\n",
+ __func__, i2c_imx->isr_result);
+ return i2c_imx->isr_result;
+ }
+ if (i2c_imx->state != IMX_I2C_STATE_DONE) {
+ dev_err(&i2c_imx->adapter.dev, "<%s> write timedout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx,
+ struct i2c_msg *msgs, bool is_lastmsg)
{
int i, result;
unsigned int temp;
int block_data = msgs->flags & I2C_M_RECV_LEN;
- int use_dma = i2c_imx->dma && msgs->flags & I2C_M_DMA_SAFE &&
- msgs->len >= DMA_THRESHOLD && !block_data;
-
- dev_dbg(&i2c_imx->adapter.dev,
- "<%s> write slave address: addr=0x%x\n",
- __func__, i2c_8bit_addr_from_msg(msgs));
- /* write slave address */
- imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx, atomic);
- if (result)
- return result;
- result = i2c_imx_acked(i2c_imx);
+ result = i2c_imx_prepare_read(i2c_imx, msgs, false);
if (result)
return result;
- dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
-
- /* setup bus to read data */
- temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
- temp &= ~I2CR_MTX;
-
- /*
- * Reset the I2CR_TXAK flag initially for SMBus block read since the
- * length is unknown
- */
- if ((msgs->len - 1) || block_data)
- temp &= ~I2CR_TXAK;
- if (use_dma)
- temp |= I2CR_DMAEN;
- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
-
dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
- if (use_dma)
- return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
-
/* read data */
for (i = 0; i < msgs->len; i++) {
u8 len = 0;
- result = i2c_imx_trx_complete(i2c_imx, atomic);
+ result = i2c_imx_trx_complete(i2c_imx, true);
if (result)
return result;
/*
@@ -1205,7 +1451,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
if (!i2c_imx->stopped)
- i2c_imx_bus_busy(i2c_imx, 0, atomic);
+ i2c_imx_bus_busy(i2c_imx, 0, true);
} else {
/*
* For i2c master receiver repeat restart operation like:
@@ -1236,6 +1482,48 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
return 0;
}
+static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
+ bool is_lastmsg)
+{
+ int block_data = msgs->flags & I2C_M_RECV_LEN;
+
+ dev_dbg(&i2c_imx->adapter.dev,
+ "<%s> write slave address: addr=0x%x\n",
+ __func__, i2c_8bit_addr_from_msg(msgs));
+
+ i2c_imx->is_lastmsg = is_lastmsg;
+
+ if (block_data)
+ i2c_imx->state = IMX_I2C_STATE_READ_BLOCK_DATA;
+ else
+ i2c_imx->state = IMX_I2C_STATE_READ;
+ i2c_imx->msg = msgs;
+ i2c_imx->msg_buf_idx = 0;
+
+ /*
+ * By writing the device address we start the state machine in the ISR.
+ * The ISR will report when it is done or when it fails.
+ */
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
+ wait_event_timeout(i2c_imx->queue,
+ i2c_imx->state == IMX_I2C_STATE_DONE ||
+ i2c_imx->state == IMX_I2C_STATE_FAILED,
+ (msgs->len + 1) * HZ / 10);
+ if (i2c_imx->state == IMX_I2C_STATE_FAILED) {
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> read failed with %d\n",
+ __func__, i2c_imx->isr_result);
+ return i2c_imx->isr_result;
+ }
+ if (i2c_imx->state != IMX_I2C_STATE_DONE) {
+ dev_err(&i2c_imx->adapter.dev, "<%s> read timedout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ if (!i2c_imx->stopped)
+ return i2c_imx_bus_busy(i2c_imx, 0, false);
+
+ return 0;
+}
+
static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
struct i2c_msg *msgs, int num, bool atomic)
{
@@ -1243,6 +1531,7 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
int result;
bool is_lastmsg = false;
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
+ int use_dma = 0;
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx, atomic);
@@ -1295,15 +1584,25 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
(temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0),
(temp & I2SR_RXAK ? 1 : 0));
#endif
+
+ use_dma = i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
+ msgs[i].flags & I2C_M_DMA_SAFE;
if (msgs[i].flags & I2C_M_RD) {
- result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic);
+ int block_data = msgs->flags & I2C_M_RECV_LEN;
+
+ if (atomic)
+ result = i2c_imx_atomic_read(i2c_imx, &msgs[i], is_lastmsg);
+ else if (use_dma && !block_data)
+ result = i2c_imx_dma_read(i2c_imx, &msgs[i], is_lastmsg);
+ else
+ result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg);
} else {
- if (!atomic &&
- i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
- msgs[i].flags & I2C_M_DMA_SAFE)
+ if (atomic)
+ result = i2c_imx_atomic_write(i2c_imx, &msgs[i]);
+ else if (use_dma)
result = i2c_imx_dma_write(i2c_imx, &msgs[i]);
else
- result = i2c_imx_write(i2c_imx, &msgs[i], atomic);
+ result = i2c_imx_write(i2c_imx, &msgs[i]);
}
if (result)
goto fail0;
@@ -1468,6 +1767,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
goto rpm_disable;
}
+ /*
+ * We use the single-master property for backward compatibility.
+ * By default multi master mode is enabled.
+ */
+ i2c_imx->multi_master = !of_property_read_bool(pdev->dev.of_node, "single-master");
+
/* Set up clock divider */
i2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
ret = of_property_read_u32(pdev->dev.of_node,
@@ -1576,7 +1881,7 @@ static const struct dev_pm_ops i2c_imx_pm_ops = {
static struct platform_driver i2c_imx_driver = {
.probe = i2c_imx_probe,
- .remove_new = i2c_imx_remove,
+ .remove = i2c_imx_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_ptr(&i2c_imx_pm_ops),
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 859c14e340e7..ce5ca5b90b39 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -524,7 +524,7 @@ MODULE_DEVICE_TABLE(of, i2c_iop3xx_match);
static struct platform_driver iop3xx_i2c_driver = {
.probe = iop3xx_i2c_probe,
- .remove_new = iop3xx_i2c_remove,
+ .remove = iop3xx_i2c_remove,
.driver = {
.name = "IOP3xx-I2C",
.of_match_table = i2c_iop3xx_match,
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index f59158489ad9..2b3b65ef2900 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -1,41 +1,39 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus
- - Based on i2c-piix4.c
- Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
- Philip Edelbrock <phil@netroedge.com>
- - Intel SCH support
- Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com>
-
-*/
+ * Linux kernel driver for Intel SCH chipset SMBus
+ * - Based on i2c-piix4.c
+ * Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
+ * Philip Edelbrock <phil@netroedge.com>
+ * - Intel SCH support
+ * Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com>
+ */
-/*
- Supports:
- Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L)
- Note: we assume there can only be one device, with one SMBus interface.
-*/
+/* Supports: Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L) */
+#include <linux/container_of.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gfp_types.h>
+#include <linux/i2c.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
+#include <linux/sprintf.h>
#include <linux/stddef.h>
-#include <linux/ioport.h>
-#include <linux/i2c.h>
-#include <linux/io.h>
+#include <linux/string_choices.h>
+#include <linux/types.h>
/* SCH SMBus address offsets */
-#define SMBHSTCNT (0 + sch_smba)
-#define SMBHSTSTS (1 + sch_smba)
-#define SMBHSTCLK (2 + sch_smba)
-#define SMBHSTADD (4 + sch_smba) /* TSA */
-#define SMBHSTCMD (5 + sch_smba)
-#define SMBHSTDAT0 (6 + sch_smba)
-#define SMBHSTDAT1 (7 + sch_smba)
-#define SMBBLKDAT (0x20 + sch_smba)
-
-/* Other settings */
-#define MAX_RETRIES 5000
+#define SMBHSTCNT 0x00
+#define SMBHSTSTS 0x01
+#define SMBHSTCLK 0x02
+#define SMBHSTADD 0x04 /* TSA */
+#define SMBHSTCMD 0x05
+#define SMBHSTDAT0 0x06
+#define SMBHSTDAT1 0x07
+#define SMBBLKDAT 0x20
/* I2C constants */
#define SCH_QUICK 0x00
@@ -44,109 +42,134 @@
#define SCH_WORD_DATA 0x03
#define SCH_BLOCK_DATA 0x05
-static unsigned short sch_smba;
-static struct i2c_adapter sch_adapter;
+struct sch_i2c {
+ struct i2c_adapter adapter;
+ void __iomem *smba;
+};
+
static int backbone_speed = 33000; /* backbone speed in kHz */
-module_param(backbone_speed, int, S_IRUSR | S_IWUSR);
+module_param(backbone_speed, int, 0600);
MODULE_PARM_DESC(backbone_speed, "Backbone speed in kHz, (default = 33000)");
-/*
- * Start the i2c transaction -- the i2c_access will prepare the transaction
- * and this function will execute it.
- * return 0 for success and others for failure.
+static inline u8 sch_io_rd8(struct sch_i2c *priv, unsigned int offset)
+{
+ return ioread8(priv->smba + offset);
+}
+
+static inline void sch_io_wr8(struct sch_i2c *priv, unsigned int offset, u8 value)
+{
+ iowrite8(value, priv->smba + offset);
+}
+
+static inline u16 sch_io_rd16(struct sch_i2c *priv, unsigned int offset)
+{
+ return ioread16(priv->smba + offset);
+}
+
+static inline void sch_io_wr16(struct sch_i2c *priv, unsigned int offset, u16 value)
+{
+ iowrite16(value, priv->smba + offset);
+}
+
+/**
+ * sch_transaction - Start the i2c transaction
+ * @adap: the i2c adapter pointer
+ *
+ * The sch_access() will prepare the transaction and
+ * this function will execute it.
+ *
+ * Return: 0 for success and others for failure.
*/
-static int sch_transaction(void)
+static int sch_transaction(struct i2c_adapter *adap)
{
+ struct sch_i2c *priv = container_of(adap, struct sch_i2c, adapter);
int temp;
- int result = 0;
- int retries = 0;
+ int rc;
- dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
- inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
- inb(SMBHSTDAT1));
+ dev_dbg(&adap->dev,
+ "Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
+ sch_io_rd8(priv, SMBHSTCNT), sch_io_rd8(priv, SMBHSTCMD),
+ sch_io_rd8(priv, SMBHSTADD),
+ sch_io_rd8(priv, SMBHSTDAT0), sch_io_rd8(priv, SMBHSTDAT1));
/* Make sure the SMBus host is ready to start transmitting */
- temp = inb(SMBHSTSTS) & 0x0f;
+ temp = sch_io_rd8(priv, SMBHSTSTS) & 0x0f;
if (temp) {
/* Can not be busy since we checked it in sch_access */
- if (temp & 0x01) {
- dev_dbg(&sch_adapter.dev, "Completion (%02x). "
- "Clear...\n", temp);
- }
- if (temp & 0x06) {
- dev_dbg(&sch_adapter.dev, "SMBus error (%02x). "
- "Resetting...\n", temp);
- }
- outb(temp, SMBHSTSTS);
- temp = inb(SMBHSTSTS) & 0x0f;
+ if (temp & 0x01)
+ dev_dbg(&adap->dev, "Completion (%02x). Clear...\n", temp);
+ if (temp & 0x06)
+ dev_dbg(&adap->dev, "SMBus error (%02x). Resetting...\n", temp);
+ sch_io_wr8(priv, SMBHSTSTS, temp);
+ temp = sch_io_rd8(priv, SMBHSTSTS) & 0x0f;
if (temp) {
- dev_err(&sch_adapter.dev,
- "SMBus is not ready: (%02x)\n", temp);
+ dev_err(&adap->dev, "SMBus is not ready: (%02x)\n", temp);
return -EAGAIN;
}
}
- /* start the transaction by setting bit 4 */
- outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT);
-
- do {
- usleep_range(100, 200);
- temp = inb(SMBHSTSTS) & 0x0f;
- } while ((temp & 0x08) && (retries++ < MAX_RETRIES));
+ /* Start the transaction by setting bit 4 */
+ temp = sch_io_rd8(priv, SMBHSTCNT);
+ temp |= 0x10;
+ sch_io_wr8(priv, SMBHSTCNT, temp);
+ rc = read_poll_timeout(sch_io_rd8, temp, !(temp & 0x08), 200, 500000, true, priv, SMBHSTSTS);
/* If the SMBus is still busy, we give up */
- if (retries > MAX_RETRIES) {
- dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
- result = -ETIMEDOUT;
+ if (rc) {
+ dev_err(&adap->dev, "SMBus Timeout!\n");
} else if (temp & 0x04) {
- result = -EIO;
- dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
- "locked until next hard reset. (sorry!)\n");
+ rc = -EIO;
+ dev_dbg(&adap->dev, "Bus collision! SMBus may be locked until next hard reset. (sorry!)\n");
/* Clock stops and target is stuck in mid-transmission */
} else if (temp & 0x02) {
- result = -EIO;
- dev_err(&sch_adapter.dev, "Error: no response!\n");
+ rc = -EIO;
+ dev_err(&adap->dev, "Error: no response!\n");
} else if (temp & 0x01) {
- dev_dbg(&sch_adapter.dev, "Post complete!\n");
- outb(temp, SMBHSTSTS);
- temp = inb(SMBHSTSTS) & 0x07;
+ dev_dbg(&adap->dev, "Post complete!\n");
+ sch_io_wr8(priv, SMBHSTSTS, temp & 0x0f);
+ temp = sch_io_rd8(priv, SMBHSTSTS) & 0x07;
if (temp & 0x06) {
/* Completion clear failed */
- dev_dbg(&sch_adapter.dev, "Failed reset at end of "
- "transaction (%02x), Bus error!\n", temp);
+ dev_dbg(&adap->dev,
+ "Failed reset at end of transaction (%02x), Bus error!\n", temp);
}
} else {
- result = -ENXIO;
- dev_dbg(&sch_adapter.dev, "No such address.\n");
+ rc = -ENXIO;
+ dev_dbg(&adap->dev, "No such address.\n");
}
- dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
- inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
- inb(SMBHSTDAT1));
- return result;
+ dev_dbg(&adap->dev, "Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
+ sch_io_rd8(priv, SMBHSTCNT), sch_io_rd8(priv, SMBHSTCMD),
+ sch_io_rd8(priv, SMBHSTADD),
+ sch_io_rd8(priv, SMBHSTDAT0), sch_io_rd8(priv, SMBHSTDAT1));
+ return rc;
}
-/*
- * This is the main access entry for i2c-sch access
- * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write
- * (0 for read and 1 for write), size is i2c transaction type and data is the
- * union of transaction for data to be transferred or data read from bus.
- * return 0 for success and others for failure.
+/**
+ * sch_access - the main access entry for i2c-sch access
+ * @adap: the i2c adapter pointer
+ * @addr: the i2c device bus address
+ * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC)
+ * @read_write: 0 for read and 1 for write
+ * @command: Byte interpreted by slave, for protocols which use such bytes
+ * @size: the i2c transaction type
+ * @data: the union of transaction for data to be transferred or data read from bus
+ *
+ * Return: 0 for success and others for failure.
*/
static s32 sch_access(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{
+ struct sch_i2c *priv = container_of(adap, struct sch_i2c, adapter);
int i, len, temp, rc;
/* Make sure the SMBus host is not busy */
- temp = inb(SMBHSTSTS) & 0x0f;
+ temp = sch_io_rd8(priv, SMBHSTSTS) & 0x0f;
if (temp & 0x08) {
- dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp);
+ dev_dbg(&adap->dev, "SMBus busy (%02x)\n", temp);
return -EAGAIN;
}
- temp = inw(SMBHSTCLK);
+ temp = sch_io_rd16(priv, SMBHSTCLK);
if (!temp) {
/*
* We can't determine if we have 33 or 25 MHz clock for
@@ -154,50 +177,48 @@ static s32 sch_access(struct i2c_adapter *adap, u16 addr,
* 100 kHz. If we actually run at 25 MHz the bus will be
* run ~75 kHz instead which should do no harm.
*/
- dev_notice(&sch_adapter.dev,
- "Clock divider uninitialized. Setting defaults\n");
- outw(backbone_speed / (4 * 100), SMBHSTCLK);
+ dev_notice(&adap->dev, "Clock divider uninitialized. Setting defaults\n");
+ sch_io_wr16(priv, SMBHSTCLK, backbone_speed / (4 * 100));
}
- dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size,
- (read_write)?"READ":"WRITE");
+ dev_dbg(&adap->dev, "access size: %d %s\n", size, str_read_write(read_write));
switch (size) {
case I2C_SMBUS_QUICK:
- outb((addr << 1) | read_write, SMBHSTADD);
+ sch_io_wr8(priv, SMBHSTADD, (addr << 1) | read_write);
size = SCH_QUICK;
break;
case I2C_SMBUS_BYTE:
- outb((addr << 1) | read_write, SMBHSTADD);
+ sch_io_wr8(priv, SMBHSTADD, (addr << 1) | read_write);
if (read_write == I2C_SMBUS_WRITE)
- outb(command, SMBHSTCMD);
+ sch_io_wr8(priv, SMBHSTCMD, command);
size = SCH_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
- outb((addr << 1) | read_write, SMBHSTADD);
- outb(command, SMBHSTCMD);
+ sch_io_wr8(priv, SMBHSTADD, (addr << 1) | read_write);
+ sch_io_wr8(priv, SMBHSTCMD, command);
if (read_write == I2C_SMBUS_WRITE)
- outb(data->byte, SMBHSTDAT0);
+ sch_io_wr8(priv, SMBHSTDAT0, data->byte);
size = SCH_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
- outb((addr << 1) | read_write, SMBHSTADD);
- outb(command, SMBHSTCMD);
+ sch_io_wr8(priv, SMBHSTADD, (addr << 1) | read_write);
+ sch_io_wr8(priv, SMBHSTCMD, command);
if (read_write == I2C_SMBUS_WRITE) {
- outb(data->word & 0xff, SMBHSTDAT0);
- outb((data->word & 0xff00) >> 8, SMBHSTDAT1);
+ sch_io_wr8(priv, SMBHSTDAT0, data->word >> 0);
+ sch_io_wr8(priv, SMBHSTDAT1, data->word >> 8);
}
size = SCH_WORD_DATA;
break;
case I2C_SMBUS_BLOCK_DATA:
- outb((addr << 1) | read_write, SMBHSTADD);
- outb(command, SMBHSTCMD);
+ sch_io_wr8(priv, SMBHSTADD, (addr << 1) | read_write);
+ sch_io_wr8(priv, SMBHSTCMD, command);
if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0];
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
return -EINVAL;
- outb(len, SMBHSTDAT0);
+ sch_io_wr8(priv, SMBHSTDAT0, len);
for (i = 1; i <= len; i++)
- outb(data->block[i], SMBBLKDAT+i-1);
+ sch_io_wr8(priv, SMBBLKDAT + i - 1, data->block[i]);
}
size = SCH_BLOCK_DATA;
break;
@@ -205,10 +226,13 @@ static s32 sch_access(struct i2c_adapter *adap, u16 addr,
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -EOPNOTSUPP;
}
- dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT);
- outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT);
+ dev_dbg(&adap->dev, "write size %d to 0x%04x\n", size, SMBHSTCNT);
+
+ temp = sch_io_rd8(priv, SMBHSTCNT);
+ temp = (temp & 0xb0) | (size & 0x7);
+ sch_io_wr8(priv, SMBHSTCNT, temp);
- rc = sch_transaction();
+ rc = sch_transaction(adap);
if (rc) /* Error in transaction */
return rc;
@@ -218,17 +242,18 @@ static s32 sch_access(struct i2c_adapter *adap, u16 addr,
switch (size) {
case SCH_BYTE:
case SCH_BYTE_DATA:
- data->byte = inb(SMBHSTDAT0);
+ data->byte = sch_io_rd8(priv, SMBHSTDAT0);
break;
case SCH_WORD_DATA:
- data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8);
+ data->word = (sch_io_rd8(priv, SMBHSTDAT0) << 0) +
+ (sch_io_rd8(priv, SMBHSTDAT1) << 8);
break;
case SCH_BLOCK_DATA:
- data->block[0] = inb(SMBHSTDAT0);
+ data->block[0] = sch_io_rd8(priv, SMBHSTDAT0);
if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
for (i = 1; i <= data->block[0]; i++)
- data->block[i] = inb(SMBBLKDAT+i-1);
+ data->block[i] = sch_io_rd8(priv, SMBBLKDAT + i - 1);
break;
}
return 0;
@@ -246,51 +271,34 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = sch_func,
};
-static struct i2c_adapter sch_adapter = {
- .owner = THIS_MODULE,
- .class = I2C_CLASS_HWMON,
- .algo = &smbus_algorithm,
-};
-
-static int smbus_sch_probe(struct platform_device *dev)
+static int smbus_sch_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct sch_i2c *priv;
struct resource *res;
- int retval;
- res = platform_get_resource(dev, IORESOURCE_IO, 0);
- if (!res)
- return -EBUSY;
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- if (!devm_request_region(&dev->dev, res->start, resource_size(res),
- dev->name)) {
- dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
- sch_smba);
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res)
return -EBUSY;
- }
-
- sch_smba = res->start;
- dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
+ priv->smba = devm_ioport_map(dev, res->start, resource_size(res));
+ if (!priv->smba)
+ return dev_err_probe(dev, -EBUSY, "SMBus region %pR already in use!\n", res);
- /* set up the sysfs linkage to our parent device */
- sch_adapter.dev.parent = &dev->dev;
+ /* Set up the sysfs linkage to our parent device */
+ priv->adapter.dev.parent = dev;
+ priv->adapter.owner = THIS_MODULE,
+ priv->adapter.class = I2C_CLASS_HWMON,
+ priv->adapter.algo = &smbus_algorithm,
- snprintf(sch_adapter.name, sizeof(sch_adapter.name),
- "SMBus SCH adapter at %04x", sch_smba);
+ snprintf(priv->adapter.name, sizeof(priv->adapter.name),
+ "SMBus SCH adapter at %04x", (unsigned short)res->start);
- retval = i2c_add_adapter(&sch_adapter);
- if (retval)
- sch_smba = 0;
-
- return retval;
-}
-
-static void smbus_sch_remove(struct platform_device *pdev)
-{
- if (sch_smba) {
- i2c_del_adapter(&sch_adapter);
- sch_smba = 0;
- }
+ return devm_i2c_add_adapter(dev, &priv->adapter);
}
static struct platform_driver smbus_sch_driver = {
@@ -298,7 +306,6 @@ static struct platform_driver smbus_sch_driver = {
.name = "isch_smbus",
},
.probe = smbus_sch_probe,
- .remove_new = smbus_sch_remove,
};
module_platform_driver(smbus_sch_driver);
diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c
index 92cc5b091137..664a5471d933 100644
--- a/drivers/i2c/busses/i2c-jz4780.c
+++ b/drivers/i2c/busses/i2c-jz4780.c
@@ -847,7 +847,7 @@ static void jz4780_i2c_remove(struct platform_device *pdev)
static struct platform_driver jz4780_i2c_driver = {
.probe = jz4780_i2c_probe,
- .remove_new = jz4780_i2c_remove,
+ .remove = jz4780_i2c_remove,
.driver = {
.name = "jz4780-i2c",
.of_match_table = jz4780_i2c_of_matches,
diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c
index eb66942e0b7d..212196af68ba 100644
--- a/drivers/i2c/busses/i2c-kempld.c
+++ b/drivers/i2c/busses/i2c-kempld.c
@@ -385,7 +385,7 @@ static struct platform_driver kempld_i2c_driver = {
.pm = pm_sleep_ptr(&kempld_i2c_pm_ops),
},
.probe = kempld_i2c_probe,
- .remove_new = kempld_i2c_remove,
+ .remove = kempld_i2c_remove,
};
module_platform_driver(kempld_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c
index 9fb33cbf7419..6943a0de860a 100644
--- a/drivers/i2c/busses/i2c-lpc2k.c
+++ b/drivers/i2c/busses/i2c-lpc2k.c
@@ -462,7 +462,7 @@ MODULE_DEVICE_TABLE(of, lpc2k_i2c_match);
static struct platform_driver i2c_lpc2k_driver = {
.probe = i2c_lpc2k_probe,
- .remove_new = i2c_lpc2k_remove,
+ .remove = i2c_lpc2k_remove,
.driver = {
.name = "lpc2k-i2c",
.pm = pm_sleep_ptr(&i2c_lpc2k_dev_pm_ops),
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index c7b203cc4434..e1d69537353b 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -565,7 +565,7 @@ MODULE_DEVICE_TABLE(of, meson_i2c_match);
static struct platform_driver meson_i2c_driver = {
.probe = meson_i2c_probe,
- .remove_new = meson_i2c_remove,
+ .remove = meson_i2c_remove,
.driver = {
.name = "meson-i2c",
.of_match_table = meson_i2c_match,
diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c
index 0b0a1c4d17ca..d1543e7d8380 100644
--- a/drivers/i2c/busses/i2c-microchip-corei2c.c
+++ b/drivers/i2c/busses/i2c-microchip-corei2c.c
@@ -462,7 +462,7 @@ MODULE_DEVICE_TABLE(of, mchp_corei2c_of_match);
static struct platform_driver mchp_corei2c_driver = {
.probe = mchp_corei2c_probe,
- .remove_new = mchp_corei2c_remove,
+ .remove = mchp_corei2c_remove,
.driver = {
.name = "microchip-corei2c",
.of_match_table = mchp_corei2c_of_match,
diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c
index b3a73921ab69..21f67f3b65b6 100644
--- a/drivers/i2c/busses/i2c-mlxbf.c
+++ b/drivers/i2c/busses/i2c-mlxbf.c
@@ -2456,7 +2456,7 @@ static void mlxbf_i2c_remove(struct platform_device *pdev)
static struct platform_driver mlxbf_i2c_driver = {
.probe = mlxbf_i2c_probe,
- .remove_new = mlxbf_i2c_remove,
+ .remove = mlxbf_i2c_remove,
.driver = {
.name = "i2c-mlxbf",
.acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids),
diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
index 8223f6d29eb3..07d3cadbf510 100644
--- a/drivers/i2c/busses/i2c-mlxcpld.c
+++ b/drivers/i2c/busses/i2c-mlxcpld.c
@@ -591,7 +591,7 @@ static void mlxcpld_i2c_remove(struct platform_device *pdev)
static struct platform_driver mlxcpld_i2c_driver = {
.probe = mlxcpld_i2c_probe,
- .remove_new = mlxcpld_i2c_remove,
+ .remove = mlxcpld_i2c_remove,
.driver = {
.name = MLXCPLD_I2C_DEVICE_NAME,
},
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 236d6b8ba867..28c5c5c1fb7a 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -938,7 +938,7 @@ MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
/* Structure for a device driver */
static struct platform_driver mpc_i2c_driver = {
.probe = fsl_i2c_probe,
- .remove_new = fsl_i2c_remove,
+ .remove = fsl_i2c_remove,
.driver = {
.name = "mpc-i2c",
.of_match_table = mpc_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index e0ba653dec2d..5bd342047d59 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -1550,7 +1550,7 @@ static const struct dev_pm_ops mtk_i2c_pm = {
static struct platform_driver mtk_i2c_driver = {
.probe = mtk_i2c_probe,
- .remove_new = mtk_i2c_remove,
+ .remove = mtk_i2c_remove,
.driver = {
.name = I2C_DRV_NAME,
.pm = pm_sleep_ptr(&mtk_i2c_pm),
diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c
index 23d417ff5e71..2103f21f9ddd 100644
--- a/drivers/i2c/busses/i2c-mt7621.c
+++ b/drivers/i2c/busses/i2c-mt7621.c
@@ -331,7 +331,7 @@ static void mtk_i2c_remove(struct platform_device *pdev)
static struct platform_driver mtk_i2c_driver = {
.probe = mtk_i2c_probe,
- .remove_new = mtk_i2c_remove,
+ .remove = mtk_i2c_remove,
.driver = {
.name = "i2c-mt7621",
.of_match_table = i2c_mtk_dt_ids,
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 29f94efedf60..874309580c33 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -1104,7 +1104,7 @@ static const struct dev_pm_ops mv64xxx_i2c_pm_ops = {
static struct platform_driver mv64xxx_i2c_driver = {
.probe = mv64xxx_i2c_probe,
- .remove_new = mv64xxx_i2c_remove,
+ .remove = mv64xxx_i2c_remove,
.driver = {
.name = MV64XXX_I2C_CTLR_NAME,
.pm = &mv64xxx_i2c_pm_ops,
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 36def0a9c95c..ad62d56b2186 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -881,7 +881,7 @@ static struct platform_driver mxs_i2c_driver = {
.of_match_table = mxs_i2c_dt_ids,
},
.probe = mxs_i2c_probe,
- .remove_new = mxs_i2c_remove,
+ .remove = mxs_i2c_remove,
};
static int __init mxs_i2c_init(void)
diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c
deleted file mode 100644
index 69a71bc9830d..000000000000
--- a/drivers/i2c/busses/i2c-nforce2-s4985.c
+++ /dev/null
@@ -1,240 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard
- *
- * Copyright (C) 2008 Jean Delvare <jdelvare@suse.de>
- */
-
-/*
- * We select the channels by sending commands to the Philips
- * PCA9556 chip at I2C address 0x18. The main adapter is used for
- * the non-multiplexed part of the bus, and 4 virtual adapters
- * are defined for the multiplexed addresses: 0x50-0x53 (memory
- * module EEPROM) located on channels 1-4. We define one virtual
- * adapter per CPU, which corresponds to one multiplexed channel:
- * CPU0: virtual adapter 1, channel 1
- * CPU1: virtual adapter 2, channel 2
- * CPU2: virtual adapter 3, channel 3
- * CPU3: virtual adapter 4, channel 4
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-extern struct i2c_adapter *nforce2_smbus;
-
-static struct i2c_adapter *s4985_adapter;
-static struct i2c_algorithm *s4985_algo;
-
-/* Wrapper access functions for multiplexed SMBus */
-static DEFINE_MUTEX(nforce2_lock);
-
-static s32 nforce2_access_virt0(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data *data)
-{
- int error;
-
- /* We exclude the multiplexed addresses */
- if ((addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
- || addr == 0x18)
- return -ENXIO;
-
- mutex_lock(&nforce2_lock);
- error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
- command, size, data);
- mutex_unlock(&nforce2_lock);
-
- return error;
-}
-
-/* We remember the last used channels combination so as to only switch
- channels when it is really needed. This greatly reduces the SMBus
- overhead, but also assumes that nobody will be writing to the PCA9556
- in our back. */
-static u8 last_channels;
-
-static inline s32 nforce2_access_channel(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data *data,
- u8 channels)
-{
- int error;
-
- /* We exclude the non-multiplexed addresses */
- if ((addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
- return -ENXIO;
-
- mutex_lock(&nforce2_lock);
- if (last_channels != channels) {
- union i2c_smbus_data mplxdata;
- mplxdata.byte = channels;
-
- error = nforce2_smbus->algo->smbus_xfer(adap, 0x18, 0,
- I2C_SMBUS_WRITE, 0x01,
- I2C_SMBUS_BYTE_DATA,
- &mplxdata);
- if (error)
- goto UNLOCK;
- last_channels = channels;
- }
- error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
- command, size, data);
-
-UNLOCK:
- mutex_unlock(&nforce2_lock);
- return error;
-}
-
-static s32 nforce2_access_virt1(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data *data)
-{
- /* CPU0: channel 1 enabled */
- return nforce2_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x02);
-}
-
-static s32 nforce2_access_virt2(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data *data)
-{
- /* CPU1: channel 2 enabled */
- return nforce2_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x04);
-}
-
-static s32 nforce2_access_virt3(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data *data)
-{
- /* CPU2: channel 3 enabled */
- return nforce2_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x08);
-}
-
-static s32 nforce2_access_virt4(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size,
- union i2c_smbus_data *data)
-{
- /* CPU3: channel 4 enabled */
- return nforce2_access_channel(adap, addr, flags, read_write, command,
- size, data, 0x10);
-}
-
-static int __init nforce2_s4985_init(void)
-{
- int i, error;
- union i2c_smbus_data ioconfig;
-
- if (!nforce2_smbus)
- return -ENODEV;
-
- /* Configure the PCA9556 multiplexer */
- ioconfig.byte = 0x00; /* All I/O to output mode */
- error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
- I2C_SMBUS_BYTE_DATA, &ioconfig);
- if (error) {
- dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n");
- error = -EIO;
- goto ERROR0;
- }
-
- /* Unregister physical bus */
- i2c_del_adapter(nforce2_smbus);
-
- printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n");
- /* Define the 5 virtual adapters and algorithms structures */
- s4985_adapter = kcalloc(5, sizeof(struct i2c_adapter), GFP_KERNEL);
- if (!s4985_adapter) {
- error = -ENOMEM;
- goto ERROR1;
- }
- s4985_algo = kcalloc(5, sizeof(struct i2c_algorithm), GFP_KERNEL);
- if (!s4985_algo) {
- error = -ENOMEM;
- goto ERROR2;
- }
-
- /* Fill in the new structures */
- s4985_algo[0] = *(nforce2_smbus->algo);
- s4985_algo[0].smbus_xfer = nforce2_access_virt0;
- s4985_adapter[0] = *nforce2_smbus;
- s4985_adapter[0].algo = s4985_algo;
- s4985_adapter[0].dev.parent = nforce2_smbus->dev.parent;
- for (i = 1; i < 5; i++) {
- s4985_algo[i] = *(nforce2_smbus->algo);
- s4985_adapter[i] = *nforce2_smbus;
- snprintf(s4985_adapter[i].name, sizeof(s4985_adapter[i].name),
- "SMBus nForce2 adapter (CPU%d)", i - 1);
- s4985_adapter[i].algo = s4985_algo + i;
- s4985_adapter[i].dev.parent = nforce2_smbus->dev.parent;
- }
- s4985_algo[1].smbus_xfer = nforce2_access_virt1;
- s4985_algo[2].smbus_xfer = nforce2_access_virt2;
- s4985_algo[3].smbus_xfer = nforce2_access_virt3;
- s4985_algo[4].smbus_xfer = nforce2_access_virt4;
-
- /* Register virtual adapters */
- for (i = 0; i < 5; i++) {
- error = i2c_add_adapter(s4985_adapter + i);
- if (error) {
- printk(KERN_ERR "i2c-nforce2-s4985: "
- "Virtual adapter %d registration "
- "failed, module not inserted\n", i);
- for (i--; i >= 0; i--)
- i2c_del_adapter(s4985_adapter + i);
- goto ERROR3;
- }
- }
-
- return 0;
-
-ERROR3:
- kfree(s4985_algo);
- s4985_algo = NULL;
-ERROR2:
- kfree(s4985_adapter);
- s4985_adapter = NULL;
-ERROR1:
- /* Restore physical bus */
- i2c_add_adapter(nforce2_smbus);
-ERROR0:
- return error;
-}
-
-static void __exit nforce2_s4985_exit(void)
-{
- if (s4985_adapter) {
- int i;
-
- for (i = 0; i < 5; i++)
- i2c_del_adapter(s4985_adapter+i);
- kfree(s4985_adapter);
- s4985_adapter = NULL;
- }
- kfree(s4985_algo);
- s4985_algo = NULL;
-
- /* Restore physical bus */
- if (i2c_add_adapter(nforce2_smbus))
- printk(KERN_ERR "i2c-nforce2-s4985: "
- "Physical bus restoration failed\n");
-}
-
-MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
-MODULE_DESCRIPTION("S4985 SMBus multiplexing");
-MODULE_LICENSE("GPL");
-
-module_init(nforce2_s4985_init);
-module_exit(nforce2_s4985_exit);
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index fab662e6bc08..d58a308582e4 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -117,20 +117,6 @@ static const struct dmi_system_id nforce2_dmi_blacklist2[] = {
static struct pci_driver nforce2_driver;
-/* For multiplexing support, we need a global reference to the 1st
- SMBus channel */
-#if IS_ENABLED(CONFIG_I2C_NFORCE2_S4985)
-struct i2c_adapter *nforce2_smbus;
-EXPORT_SYMBOL_GPL(nforce2_smbus);
-
-static void nforce2_set_reference(struct i2c_adapter *adap)
-{
- nforce2_smbus = adap;
-}
-#else
-static inline void nforce2_set_reference(struct i2c_adapter *adap) { }
-#endif
-
static void nforce2_abort(struct i2c_adapter *adap)
{
struct nforce2_smbus *smbus = adap->algo_data;
@@ -411,7 +397,6 @@ static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV;
}
- nforce2_set_reference(&smbuses[0].adapter);
return 0;
}
@@ -420,7 +405,6 @@ static void nforce2_remove(struct pci_dev *dev)
{
struct nforce2_smbus *smbuses = pci_get_drvdata(dev);
- nforce2_set_reference(NULL);
if (smbuses[0].base) {
i2c_del_adapter(&smbuses[0].adapter);
release_region(smbuses[0].base, smbuses[0].size);
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index ad0f02acdb12..efb33802804f 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -6,10 +6,10 @@
* I2C master mode controller driver, used in Nomadik 8815
* and Ux500 platforms.
*
- * The Mobileye EyeQ5 platform is also supported; it uses
+ * The Mobileye EyeQ5 and EyeQ6H platforms are also supported; they use
* the same Ux500/DB8500 IP block with two quirks:
* - The memory bus only supports 32-bit accesses.
- * - A register must be configured for the I2C speed mode;
+ * - (only EyeQ5) A register must be configured for the I2C speed mode;
* it is located in a shared register region called OLB.
*
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
@@ -26,6 +26,7 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -396,7 +397,7 @@ static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *priv, u16 flags)
*/
static void setup_i2c_controller(struct nmk_i2c_dev *priv)
{
- u32 brcr1, brcr2;
+ u32 brcr;
u32 i2c_clk, div;
u32 ns;
u16 slsu;
@@ -443,7 +444,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv)
/*
* The spec says, in case of std. mode the divider is
* 2 whereas it is 3 for fast and fastplus mode of
- * operation. TODO - high speed support.
+ * operation.
*/
div = (priv->clk_freq > I2C_MAX_STANDARD_MODE_FREQ) ? 3 : 2;
@@ -451,30 +452,23 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv)
* generate the mask for baud rate counters. The controller
* has two baud rate counters. One is used for High speed
* operation, and the other is for std, fast mode, fast mode
- * plus operation. Currently we do not supprt high speed mode
- * so set brcr1 to 0.
+ * plus operation.
+ *
+ * BRCR is a clock divider amount. Pick highest value that
+ * leads to rate strictly below target. Eg when asking for
+ * 400kHz you want a bus rate <=400kHz (and not >=400kHz).
*/
- brcr1 = FIELD_PREP(I2C_BRCR_BRCNT1, 0);
- brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, i2c_clk / (priv->clk_freq * div));
+ brcr = DIV_ROUND_UP(i2c_clk, priv->clk_freq * div);
+
+ if (priv->sm == I2C_FREQ_MODE_HIGH_SPEED)
+ brcr = FIELD_PREP(I2C_BRCR_BRCNT1, brcr);
+ else
+ brcr = FIELD_PREP(I2C_BRCR_BRCNT2, brcr);
/* set the baud rate counter register */
- writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR);
+ writel(brcr, priv->virtbase + I2C_BRCR);
- /*
- * set the speed mode. Currently we support
- * only standard and fast mode of operation
- * TODO - support for fast mode plus (up to 1Mb/s)
- * and high speed (up to 3.4 Mb/s)
- */
- if (priv->sm > I2C_FREQ_MODE_FAST) {
- dev_err(&priv->adev->dev,
- "do not support this mode defaulting to std. mode\n");
- brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2,
- i2c_clk / (I2C_MAX_STANDARD_MODE_FREQ * 2));
- writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR);
- writel(FIELD_PREP(I2C_CR_SM, I2C_FREQ_MODE_STANDARD),
- priv->virtbase + I2C_CR);
- }
+ /* set the speed mode */
writel(FIELD_PREP(I2C_CR_SM, priv->sm), priv->virtbase + I2C_CR);
/* set the Tx and Rx FIFO threshold */
@@ -1015,11 +1009,14 @@ static void nmk_i2c_of_probe(struct device_node *np,
if (of_property_read_u32(np, "clock-frequency", &priv->clk_freq))
priv->clk_freq = I2C_MAX_STANDARD_MODE_FREQ;
- /* This driver only supports 'standard' and 'fast' modes of operation. */
if (priv->clk_freq <= I2C_MAX_STANDARD_MODE_FREQ)
priv->sm = I2C_FREQ_MODE_STANDARD;
- else
+ else if (priv->clk_freq <= I2C_MAX_FAST_MODE_FREQ)
priv->sm = I2C_FREQ_MODE_FAST;
+ else if (priv->clk_freq <= I2C_MAX_FAST_MODE_PLUS_FREQ)
+ priv->sm = I2C_FREQ_MODE_FAST_PLUS;
+ else
+ priv->sm = I2C_FREQ_MODE_HIGH_SPEED;
priv->tft = 1; /* Tx FIFO threshold */
priv->rft = 8; /* Rx FIFO threshold */
@@ -1046,8 +1043,6 @@ static int nmk_i2c_eyeq5_probe(struct nmk_i2c_dev *priv)
struct regmap *olb;
unsigned int id;
- priv->has_32b_bus = true;
-
olb = syscon_regmap_lookup_by_phandle_args(np, "mobileye,olb", 1, &id);
if (IS_ERR(olb))
return PTR_ERR(olb);
@@ -1068,15 +1063,39 @@ static int nmk_i2c_eyeq5_probe(struct nmk_i2c_dev *priv)
return 0;
}
+#define NMK_I2C_EYEQ_FLAG_32B_BUS BIT(0)
+#define NMK_I2C_EYEQ_FLAG_IS_EYEQ5 BIT(1)
+
+static const struct of_device_id nmk_i2c_eyeq_match_table[] = {
+ {
+ .compatible = "mobileye,eyeq5-i2c",
+ .data = (void *)(NMK_I2C_EYEQ_FLAG_32B_BUS | NMK_I2C_EYEQ_FLAG_IS_EYEQ5),
+ },
+ {
+ .compatible = "mobileye,eyeq6h-i2c",
+ .data = (void *)NMK_I2C_EYEQ_FLAG_32B_BUS,
+ },
+};
+
static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
{
- int ret = 0;
- struct nmk_i2c_dev *priv;
+ struct i2c_vendor_data *vendor = id->data;
+ u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1;
struct device_node *np = adev->dev.of_node;
+ const struct of_device_id *match;
struct device *dev = &adev->dev;
+ unsigned long match_flags = 0;
+ struct nmk_i2c_dev *priv;
struct i2c_adapter *adap;
- struct i2c_vendor_data *vendor = id->data;
- u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1;
+ int ret = 0;
+
+ /*
+ * We do not want to attach a .of_match_table to our amba driver.
+ * Do not convert to device_get_match_data().
+ */
+ match = of_match_device(nmk_i2c_eyeq_match_table, dev);
+ if (match)
+ match_flags = (unsigned long)match->data;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -1084,10 +1103,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
priv->vendor = vendor;
priv->adev = adev;
- priv->has_32b_bus = false;
+ priv->has_32b_bus = match_flags & NMK_I2C_EYEQ_FLAG_32B_BUS;
nmk_i2c_of_probe(np, priv);
- if (of_device_is_compatible(np, "mobileye,eyeq5-i2c")) {
+ if (match_flags & NMK_I2C_EYEQ_FLAG_IS_EYEQ5) {
ret = nmk_i2c_eyeq5_probe(priv);
if (ret)
return dev_err_probe(dev, ret, "failed OLB lookup\n");
diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
index bbcb4d6668ce..482a0074d448 100644
--- a/drivers/i2c/busses/i2c-npcm7xx.c
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
@@ -334,6 +334,7 @@ struct npcm_i2c {
u64 nack_cnt;
u64 timeout_cnt;
u64 tx_complete_cnt;
+ bool ber_state; /* Indicate the bus error state */
};
static inline void npcm_i2c_select_bank(struct npcm_i2c *bus,
@@ -1521,6 +1522,7 @@ static void npcm_i2c_irq_handle_ber(struct npcm_i2c *bus)
if (npcm_i2c_is_master(bus)) {
npcm_i2c_master_abort(bus);
} else {
+ bus->ber_state = true;
npcm_i2c_clear_master_status(bus);
/* Clear BB (BUS BUSY) bit */
@@ -1628,13 +1630,10 @@ static void npcm_i2c_irq_handle_sda(struct npcm_i2c *bus, u8 i2cst)
npcm_i2c_wr_byte(bus, bus->dest_addr | BIT(0));
/* SDA interrupt, after start\restart */
} else {
- if (NPCM_I2CST_XMIT & i2cst) {
- bus->operation = I2C_WRITE_OPER;
+ if (bus->operation == I2C_WRITE_OPER)
npcm_i2c_irq_master_handler_write(bus);
- } else {
- bus->operation = I2C_READ_OPER;
+ else if (bus->operation == I2C_READ_OPER)
npcm_i2c_irq_master_handler_read(bus);
- }
}
}
@@ -1702,6 +1701,7 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
dev_dbg(bus->dev, "bus%d-0x%x recovery skipped, bus not stuck",
bus->num, bus->dest_addr);
npcm_i2c_reset(bus);
+ bus->ber_state = false;
return 0;
}
@@ -1766,6 +1766,7 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
if (bus->rec_succ_cnt < ULLONG_MAX)
bus->rec_succ_cnt++;
}
+ bus->ber_state = false;
return status;
}
@@ -2161,7 +2162,16 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
} while (time_is_after_jiffies(time_left) && bus_busy);
- if (bus_busy) {
+ /*
+ * Check the BER (bus error) state, when ber_state is true, it means that the module
+ * detects the bus error which is caused by some factor like that the electricity
+ * noise occurs on the bus. Under this condition, the module is reset and the bus
+ * gets recovered.
+ *
+ * While ber_state is false, the module reset and bus recovery also get done as the
+ * bus is busy.
+ */
+ if (bus_busy || bus->ber_state) {
iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
npcm_i2c_reset(bus);
i2c_recover_bus(adap);
@@ -2363,7 +2373,7 @@ MODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table);
static struct platform_driver npcm_i2c_bus_driver = {
.probe = npcm_i2c_probe_bus,
- .remove_new = npcm_i2c_remove_bus,
+ .remove = npcm_i2c_remove_bus,
.driver = {
.name = "nuvoton-i2c",
.of_match_table = npcm_i2c_bus_of_table,
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 482b37c8a129..0f67e57cdeff 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -769,7 +769,7 @@ static DEFINE_NOIRQ_DEV_PM_OPS(ocores_i2c_pm,
static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe,
- .remove_new = ocores_i2c_remove,
+ .remove = ocores_i2c_remove,
.driver = {
.name = "ocores-i2c",
.of_match_table = ocores_i2c_match,
diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c
index dc6dff95c68c..edfca7b20f29 100644
--- a/drivers/i2c/busses/i2c-octeon-platdrv.c
+++ b/drivers/i2c/busses/i2c-octeon-platdrv.c
@@ -269,7 +269,7 @@ MODULE_DEVICE_TABLE(of, octeon_i2c_match);
static struct platform_driver octeon_i2c_driver = {
.probe = octeon_i2c_probe,
- .remove_new = octeon_i2c_remove,
+ .remove = octeon_i2c_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = octeon_i2c_match,
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 1d9ad25c89ae..92faf03d64cf 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1605,7 +1605,7 @@ static const struct dev_pm_ops omap_i2c_pm_ops = {
static struct platform_driver omap_i2c_driver = {
.probe = omap_i2c_probe,
- .remove_new = omap_i2c_remove,
+ .remove = omap_i2c_remove,
.driver = {
.name = "omap_i2c",
.pm = pm_ptr(&omap_i2c_pm_ops),
diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c
index d9dd71cf37fd..c9b62892397a 100644
--- a/drivers/i2c/busses/i2c-opal.c
+++ b/drivers/i2c/busses/i2c-opal.c
@@ -249,7 +249,7 @@ MODULE_DEVICE_TABLE(of, i2c_opal_of_match);
static struct platform_driver i2c_opal_driver = {
.probe = i2c_opal_probe,
- .remove_new = i2c_opal_remove,
+ .remove = i2c_opal_remove,
.driver = {
.name = "i2c-opal",
.of_match_table = i2c_opal_of_match,
diff --git a/drivers/i2c/busses/i2c-pasemi-platform.c b/drivers/i2c/busses/i2c-pasemi-platform.c
index 5fbfb9b41744..a486a37d3863 100644
--- a/drivers/i2c/busses/i2c-pasemi-platform.c
+++ b/drivers/i2c/busses/i2c-pasemi-platform.c
@@ -104,7 +104,7 @@ static struct platform_driver pasemi_platform_i2c_driver = {
.of_match_table = pasemi_platform_i2c_of_match,
},
.probe = pasemi_platform_i2c_probe,
- .remove_new = pasemi_platform_i2c_remove,
+ .remove = pasemi_platform_i2c_remove,
};
module_platform_driver(pasemi_platform_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index b8d5480c54f6..87da8241b927 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -238,7 +238,7 @@ MODULE_DEVICE_TABLE(of, i2c_pca_of_match_table);
static struct platform_driver i2c_pca_pf_driver = {
.probe = i2c_pca_pf_probe,
- .remove_new = i2c_pca_pf_remove,
+ .remove = i2c_pca_pf_remove,
.driver = {
.name = "i2c-pca-platform",
.of_match_table = of_match_ptr(i2c_pca_of_match_table),
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index febbd9950d8f..9402fa3811c5 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -35,20 +35,7 @@
#include <linux/acpi.h>
#include <linux/io.h>
-
-/* PIIX4 SMBus address offsets */
-#define SMBHSTSTS (0 + piix4_smba)
-#define SMBHSLVSTS (1 + piix4_smba)
-#define SMBHSTCNT (2 + piix4_smba)
-#define SMBHSTCMD (3 + piix4_smba)
-#define SMBHSTADD (4 + piix4_smba)
-#define SMBHSTDAT0 (5 + piix4_smba)
-#define SMBHSTDAT1 (6 + piix4_smba)
-#define SMBBLKDAT (7 + piix4_smba)
-#define SMBSLVCNT (8 + piix4_smba)
-#define SMBSHDWCMD (9 + piix4_smba)
-#define SMBSLVEVT (0xA + piix4_smba)
-#define SMBSLVDAT (0xC + piix4_smba)
+#include "i2c-piix4.h"
/* count for request_region */
#define SMBIOSIZE 9
@@ -70,7 +57,6 @@
#define PIIX4_BYTE 0x04
#define PIIX4_BYTE_DATA 0x08
#define PIIX4_WORD_DATA 0x0C
-#define PIIX4_BLOCK_DATA 0x14
/* Multi-port constants */
#define PIIX4_MAX_ADAPTERS 4
@@ -101,6 +87,7 @@
#define SB800_PIIX4_FCH_PM_ADDR 0xFED80300
#define SB800_PIIX4_FCH_PM_SIZE 8
+#define SB800_ASF_ACPI_PATH "\\_SB.ASFC"
/* insmod parameters */
@@ -160,11 +147,6 @@ static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
};
static const char *piix4_aux_port_name_sb800 = " port 1";
-struct sb800_mmio_cfg {
- void __iomem *addr;
- bool use_mmio;
-};
-
struct i2c_piix4_adapdata {
unsigned short smba;
@@ -175,8 +157,7 @@ struct i2c_piix4_adapdata {
struct sb800_mmio_cfg mmio_cfg;
};
-static int piix4_sb800_region_request(struct device *dev,
- struct sb800_mmio_cfg *mmio_cfg)
+int piix4_sb800_region_request(struct device *dev, struct sb800_mmio_cfg *mmio_cfg)
{
if (mmio_cfg->use_mmio) {
void __iomem *addr;
@@ -214,9 +195,9 @@ static int piix4_sb800_region_request(struct device *dev,
return 0;
}
+EXPORT_SYMBOL_NS_GPL(piix4_sb800_region_request, PIIX4_SMBUS);
-static void piix4_sb800_region_release(struct device *dev,
- struct sb800_mmio_cfg *mmio_cfg)
+void piix4_sb800_region_release(struct device *dev, struct sb800_mmio_cfg *mmio_cfg)
{
if (mmio_cfg->use_mmio) {
iounmap(mmio_cfg->addr);
@@ -227,6 +208,7 @@ static void piix4_sb800_region_release(struct device *dev,
release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
}
+EXPORT_SYMBOL_NS_GPL(piix4_sb800_region_release, PIIX4_SMBUS);
static bool piix4_sb800_use_mmio(struct pci_dev *PIIX4_dev)
{
@@ -536,10 +518,8 @@ static int piix4_setup_aux(struct pci_dev *PIIX4_dev,
return piix4_smba;
}
-static int piix4_transaction(struct i2c_adapter *piix4_adapter)
+int piix4_transaction(struct i2c_adapter *piix4_adapter, unsigned short piix4_smba)
{
- struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter);
- unsigned short piix4_smba = adapdata->smba;
int temp;
int result = 0;
int timeout = 0;
@@ -611,6 +591,7 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter)
inb_p(SMBHSTDAT1));
return result;
}
+EXPORT_SYMBOL_NS_GPL(piix4_transaction, PIIX4_SMBUS);
/* Return negative errno on error. */
static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
@@ -675,7 +656,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
- status = piix4_transaction(adap);
+ status = piix4_transaction(adap, piix4_smba);
if (status)
return status;
@@ -764,7 +745,7 @@ static void piix4_imc_wakeup(void)
release_region(KERNCZ_IMC_IDX, 2);
}
-static int piix4_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg)
+int piix4_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg)
{
u8 smba_en_lo, val;
@@ -786,6 +767,7 @@ static int piix4_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg)
return (smba_en_lo & piix4_port_mask_sb800);
}
+EXPORT_SYMBOL_NS_GPL(piix4_sb800_port_sel, PIIX4_SMBUS);
/*
* Handles access to multiple SMBus ports on the SB800.
@@ -1043,6 +1025,9 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int retval;
bool is_sb800 = false;
+ bool is_asf = false;
+ acpi_status status;
+ acpi_handle handle;
if ((dev->vendor == PCI_VENDOR_ID_ATI &&
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
@@ -1105,10 +1090,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
}
}
+ status = acpi_get_handle(NULL, (acpi_string)SB800_ASF_ACPI_PATH, &handle);
+ if (ACPI_SUCCESS(status))
+ is_asf = true;
+
if (dev->vendor == PCI_VENDOR_ID_AMD &&
(dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS ||
dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS)) {
- retval = piix4_setup_sb800(dev, id, 1);
+ /* Do not setup AUX port if ASF is enabled */
+ if (!is_asf)
+ retval = piix4_setup_sb800(dev, id, 1);
}
if (retval > 0) {
diff --git a/drivers/i2c/busses/i2c-piix4.h b/drivers/i2c/busses/i2c-piix4.h
new file mode 100644
index 000000000000..36bc6ce82a27
--- /dev/null
+++ b/drivers/i2c/busses/i2c-piix4.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PIIX4/SB800 SMBus Interfaces
+ *
+ * Copyright (c) 2024, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ * Sanket Goswami <Sanket.Goswami@amd.com>
+ */
+
+#ifndef I2C_PIIX4_H
+#define I2C_PIIX4_H
+
+#include <linux/types.h>
+
+/* PIIX4 SMBus address offsets */
+#define SMBHSTSTS (0x00 + piix4_smba)
+#define SMBHSLVSTS (0x01 + piix4_smba)
+#define SMBHSTCNT (0x02 + piix4_smba)
+#define SMBHSTCMD (0x03 + piix4_smba)
+#define SMBHSTADD (0x04 + piix4_smba)
+#define SMBHSTDAT0 (0x05 + piix4_smba)
+#define SMBHSTDAT1 (0x06 + piix4_smba)
+#define SMBBLKDAT (0x07 + piix4_smba)
+#define SMBSLVCNT (0x08 + piix4_smba)
+#define SMBSHDWCMD (0x09 + piix4_smba)
+#define SMBSLVEVT (0x0A + piix4_smba)
+#define SMBSLVDAT (0x0C + piix4_smba)
+
+/* PIIX4 constants */
+#define PIIX4_BLOCK_DATA 0x14
+
+struct sb800_mmio_cfg {
+ void __iomem *addr;
+ bool use_mmio;
+};
+
+int piix4_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg);
+int piix4_transaction(struct i2c_adapter *piix4_adapter, unsigned short piix4_smba);
+int piix4_sb800_region_request(struct device *dev, struct sb800_mmio_cfg *mmio_cfg);
+void piix4_sb800_region_release(struct device *dev, struct sb800_mmio_cfg *mmio_cfg);
+
+#endif /* I2C_PIIX4_H */
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 1dafadda73af..d4d139b97513 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -733,7 +733,7 @@ static struct platform_driver i2c_pnx_driver = {
.pm = pm_sleep_ptr(&i2c_pnx_pm),
},
.probe = i2c_pnx_probe,
- .remove_new = i2c_pnx_remove,
+ .remove = i2c_pnx_remove,
};
static int __init i2c_adap_pnx_init(void)
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index b6b03539f626..9a867c817db0 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -437,7 +437,7 @@ static int i2c_powermac_probe(struct platform_device *dev)
static struct platform_driver i2c_powermac_driver = {
.probe = i2c_powermac_probe,
- .remove_new = i2c_powermac_remove,
+ .remove = i2c_powermac_remove,
.driver = {
.name = "i2c-powermac",
.bus = &platform_bus_type,
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 4d76e71cdd4b..cb6988482673 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1574,7 +1574,7 @@ static const struct dev_pm_ops i2c_pxa_dev_pm_ops = {
static struct platform_driver i2c_pxa_driver = {
.probe = i2c_pxa_probe,
- .remove_new = i2c_pxa_remove,
+ .remove = i2c_pxa_remove,
.driver = {
.name = "pxa2xx-i2c",
.pm = pm_sleep_ptr(&i2c_pxa_dev_pm_ops),
diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c
index 414882c57d7f..05b73326afd4 100644
--- a/drivers/i2c/busses/i2c-qcom-cci.c
+++ b/drivers/i2c/busses/i2c-qcom-cci.c
@@ -120,7 +120,6 @@ struct cci_data {
unsigned int num_masters;
struct i2c_adapter_quirks quirks;
u16 queue_size[NUM_QUEUES];
- unsigned long cci_clk_rate;
struct hw_params params[3];
};
@@ -523,7 +522,6 @@ static const struct dev_pm_ops qcom_cci_pm = {
static int cci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- unsigned long cci_clk_rate = 0;
struct device_node *child;
struct resource *r;
struct cci *cci;
@@ -594,22 +592,6 @@ static int cci_probe(struct platform_device *pdev)
return dev_err_probe(dev, -EINVAL, "not enough clocks in DT\n");
cci->nclocks = ret;
- /* Retrieve CCI clock rate */
- for (i = 0; i < cci->nclocks; i++) {
- if (!strcmp(cci->clocks[i].id, "cci")) {
- cci_clk_rate = clk_get_rate(cci->clocks[i].clk);
- break;
- }
- }
-
- if (cci_clk_rate != cci->data->cci_clk_rate) {
- /* cci clock set by the bootloader or via assigned clock rate
- * in DT.
- */
- dev_warn(dev, "Found %lu cci clk rate while %lu was expected\n",
- cci_clk_rate, cci->data->cci_clk_rate);
- }
-
ret = cci_enable_clocks(cci);
if (ret < 0)
return ret;
@@ -699,7 +681,6 @@ static const struct cci_data cci_v1_data = {
.max_write_len = 10,
.max_read_len = 12,
},
- .cci_clk_rate = 19200000,
.params[I2C_MODE_STANDARD] = {
.thigh = 78,
.tlow = 114,
@@ -733,7 +714,6 @@ static const struct cci_data cci_v1_5_data = {
.max_write_len = 10,
.max_read_len = 12,
},
- .cci_clk_rate = 19200000,
.params[I2C_MODE_STANDARD] = {
.thigh = 78,
.tlow = 114,
@@ -767,7 +747,6 @@ static const struct cci_data cci_v2_data = {
.max_write_len = 11,
.max_read_len = 12,
},
- .cci_clk_rate = 37500000,
.params[I2C_MODE_STANDARD] = {
.thigh = 201,
.tlow = 174,
@@ -826,7 +805,7 @@ MODULE_DEVICE_TABLE(of, cci_dt_match);
static struct platform_driver qcom_cci_driver = {
.probe = cci_probe,
- .remove_new = cci_remove,
+ .remove = cci_remove,
.driver = {
.name = "i2c-qcom-cci",
.of_match_table = cci_dt_match,
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 212336f724a6..7a22e1f46e60 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -16,6 +16,7 @@
#include <linux/pm_runtime.h>
#include <linux/soc/qcom/geni-se.h>
#include <linux/spinlock.h>
+#include <linux/units.h>
#define SE_I2C_TX_TRANS_LEN 0x26c
#define SE_I2C_RX_TRANS_LEN 0x270
@@ -146,22 +147,36 @@ struct geni_i2c_clk_fld {
* clk_freq_out = t / t_cycle
* source_clock = 19.2 MHz
*/
-static const struct geni_i2c_clk_fld geni_i2c_clk_map[] = {
+static const struct geni_i2c_clk_fld geni_i2c_clk_map_19p2mhz[] = {
{KHZ(100), 7, 10, 11, 26},
{KHZ(400), 2, 5, 12, 24},
{KHZ(1000), 1, 3, 9, 18},
+ {},
+};
+
+/* source_clock = 32 MHz */
+static const struct geni_i2c_clk_fld geni_i2c_clk_map_32mhz[] = {
+ {KHZ(100), 8, 14, 18, 40},
+ {KHZ(400), 4, 3, 11, 20},
+ {KHZ(1000), 2, 3, 6, 15},
+ {},
};
static int geni_i2c_clk_map_idx(struct geni_i2c_dev *gi2c)
{
- int i;
- const struct geni_i2c_clk_fld *itr = geni_i2c_clk_map;
+ const struct geni_i2c_clk_fld *itr;
- for (i = 0; i < ARRAY_SIZE(geni_i2c_clk_map); i++, itr++) {
+ if (clk_get_rate(gi2c->se.clk) == 32 * HZ_PER_MHZ)
+ itr = geni_i2c_clk_map_32mhz;
+ else
+ itr = geni_i2c_clk_map_19p2mhz;
+
+ while (itr->clk_freq_out != 0) {
if (itr->clk_freq_out == gi2c->clk_freq_out) {
gi2c->clk_fld = itr;
return 0;
}
+ itr++;
}
return -EINVAL;
}
@@ -818,6 +833,8 @@ static int geni_i2c_probe(struct platform_device *pdev)
init_completion(&gi2c->done);
spin_lock_init(&gi2c->lock);
platform_set_drvdata(pdev, gi2c);
+
+ /* Keep interrupts disabled initially to allow for low-power modes */
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN,
dev_name(dev), gi2c);
if (ret) {
@@ -1049,7 +1066,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
static struct platform_driver geni_i2c_driver = {
.probe = geni_i2c_probe,
- .remove_new = geni_i2c_remove,
+ .remove = geni_i2c_remove,
.shutdown = geni_i2c_shutdown,
.driver = {
.name = "geni_i2c",
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index d480162a4d39..da20b4487c9a 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -17,9 +17,9 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/scatterlist.h>
/* QUP Registers */
@@ -1683,7 +1683,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
}
}
- if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
+ if (device_is_compatible(&pdev->dev, "qcom,i2c-qup-v1.1.1")) {
qup->adap.algo = &qup_i2c_algo;
qup->adap.quirks = &qup_i2c_quirks;
is_qup_v1 = true;
@@ -1974,7 +1974,7 @@ MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
static struct platform_driver qup_i2c_driver = {
.probe = qup_i2c_probe,
- .remove_new = qup_i2c_remove,
+ .remove = qup_i2c_remove,
.driver = {
.name = "i2c_qup",
.pm = pm_ptr(&qup_i2c_qup_pm_ops),
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 9267df38c2d0..a7b77d14ee86 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -1271,7 +1271,7 @@ static struct platform_driver rcar_i2c_driver = {
.pm = pm_sleep_ptr(&rcar_i2c_pm_ops),
},
.probe = rcar_i2c_probe,
- .remove_new = rcar_i2c_remove,
+ .remove = rcar_i2c_remove,
};
module_platform_driver(rcar_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index c7f3a4c02470..c218f73c3650 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -632,7 +632,7 @@ static const struct of_device_id riic_i2c_dt_ids[] = {
static struct platform_driver riic_i2c_driver = {
.probe = riic_i2c_probe,
- .remove_new = riic_i2c_remove,
+ .remove = riic_i2c_remove,
.driver = {
.name = "i2c-riic",
.of_match_table = riic_i2c_dt_ids,
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 4ef9bad77b85..d4e9196445c0 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -1398,7 +1398,7 @@ static SIMPLE_DEV_PM_OPS(rk3x_i2c_pm_ops, NULL, rk3x_i2c_resume);
static struct platform_driver rk3x_i2c_driver = {
.probe = rk3x_i2c_probe,
- .remove_new = rk3x_i2c_remove,
+ .remove = rk3x_i2c_remove,
.driver = {
.name = "rk3x-i2c",
.of_match_table = rk3x_i2c_match,
diff --git a/drivers/i2c/busses/i2c-rtl9300.c b/drivers/i2c/busses/i2c-rtl9300.c
new file mode 100644
index 000000000000..e064e8a4a1f0
--- /dev/null
+++ b/drivers/i2c/busses/i2c-rtl9300.c
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+enum rtl9300_bus_freq {
+ RTL9300_I2C_STD_FREQ,
+ RTL9300_I2C_FAST_FREQ,
+};
+
+struct rtl9300_i2c;
+
+struct rtl9300_i2c_chan {
+ struct i2c_adapter adap;
+ struct rtl9300_i2c *i2c;
+ enum rtl9300_bus_freq bus_freq;
+ u8 sda_pin;
+};
+
+#define RTL9300_I2C_MUX_NCHAN 8
+
+struct rtl9300_i2c {
+ struct regmap *regmap;
+ struct device *dev;
+ struct rtl9300_i2c_chan chans[RTL9300_I2C_MUX_NCHAN];
+ u32 reg_base;
+ u8 sda_pin;
+ struct mutex lock;
+};
+
+#define RTL9300_I2C_MST_CTRL1 0x0
+#define RTL9300_I2C_MST_CTRL1_MEM_ADDR_OFS 8
+#define RTL9300_I2C_MST_CTRL1_MEM_ADDR_MASK GENMASK(31, 8)
+#define RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_OFS 4
+#define RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_MASK GENMASK(6, 4)
+#define RTL9300_I2C_MST_CTRL1_GPIO_SCL_SEL BIT(3)
+#define RTL9300_I2C_MST_CTRL1_RWOP BIT(2)
+#define RTL9300_I2C_MST_CTRL1_I2C_FAIL BIT(1)
+#define RTL9300_I2C_MST_CTRL1_I2C_TRIG BIT(0)
+#define RTL9300_I2C_MST_CTRL2 0x4
+#define RTL9300_I2C_MST_CTRL2_RD_MODE BIT(15)
+#define RTL9300_I2C_MST_CTRL2_DEV_ADDR_OFS 8
+#define RTL9300_I2C_MST_CTRL2_DEV_ADDR_MASK GENMASK(14, 8)
+#define RTL9300_I2C_MST_CTRL2_DATA_WIDTH_OFS 4
+#define RTL9300_I2C_MST_CTRL2_DATA_WIDTH_MASK GENMASK(7, 4)
+#define RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_OFS 2
+#define RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_MASK GENMASK(3, 2)
+#define RTL9300_I2C_MST_CTRL2_SCL_FREQ_OFS 0
+#define RTL9300_I2C_MST_CTRL2_SCL_FREQ_MASK GENMASK(1, 0)
+#define RTL9300_I2C_MST_DATA_WORD0 0x8
+#define RTL9300_I2C_MST_DATA_WORD1 0xc
+#define RTL9300_I2C_MST_DATA_WORD2 0x10
+#define RTL9300_I2C_MST_DATA_WORD3 0x14
+
+#define RTL9300_I2C_MST_GLB_CTRL 0x384
+
+static int rtl9300_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len)
+{
+ u32 val, mask;
+ int ret;
+
+ val = len << RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_OFS;
+ mask = RTL9300_I2C_MST_CTRL2_MEM_ADDR_WIDTH_MASK;
+
+ ret = regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL2, mask, val);
+ if (ret)
+ return ret;
+
+ val = reg << RTL9300_I2C_MST_CTRL1_MEM_ADDR_OFS;
+ mask = RTL9300_I2C_MST_CTRL1_MEM_ADDR_MASK;
+
+ return regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, mask, val);
+}
+
+static int rtl9300_i2c_config_io(struct rtl9300_i2c *i2c, u8 sda_pin)
+{
+ int ret;
+ u32 val, mask;
+
+ ret = regmap_update_bits(i2c->regmap, RTL9300_I2C_MST_GLB_CTRL, BIT(sda_pin), BIT(sda_pin));
+ if (ret)
+ return ret;
+
+ val = (sda_pin << RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_OFS) |
+ RTL9300_I2C_MST_CTRL1_GPIO_SCL_SEL;
+ mask = RTL9300_I2C_MST_CTRL1_SDA_OUT_SEL_MASK | RTL9300_I2C_MST_CTRL1_GPIO_SCL_SEL;
+
+ return regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, mask, val);
+}
+
+static int rtl9300_i2c_config_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan,
+ u16 addr, u16 len)
+{
+ u32 val, mask;
+
+ val = chan->bus_freq << RTL9300_I2C_MST_CTRL2_SCL_FREQ_OFS;
+ mask = RTL9300_I2C_MST_CTRL2_SCL_FREQ_MASK;
+
+ val |= addr << RTL9300_I2C_MST_CTRL2_DEV_ADDR_OFS;
+ mask |= RTL9300_I2C_MST_CTRL2_DEV_ADDR_MASK;
+
+ val |= ((len - 1) & 0xf) << RTL9300_I2C_MST_CTRL2_DATA_WIDTH_OFS;
+ mask |= RTL9300_I2C_MST_CTRL2_DATA_WIDTH_MASK;
+
+ mask |= RTL9300_I2C_MST_CTRL2_RD_MODE;
+
+ return regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL2, mask, val);
+}
+
+static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, int len)
+{
+ u32 vals[4] = {};
+ int i, ret;
+
+ if (len > 16)
+ return -EIO;
+
+ ret = regmap_bulk_read(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0,
+ vals, ARRAY_SIZE(vals));
+ if (ret)
+ return ret;
+
+ for (i = 0; i < len; i++) {
+ buf[i] = vals[i/4] & 0xff;
+ vals[i/4] >>= 8;
+ }
+
+ return 0;
+}
+
+static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, int len)
+{
+ u32 vals[4] = {};
+ int i;
+
+ if (len > 16)
+ return -EIO;
+
+ for (i = 0; i < len; i++) {
+ if (i % 4 == 0)
+ vals[i/4] = 0;
+ vals[i/4] <<= 8;
+ vals[i/4] |= buf[i];
+ }
+
+ return regmap_bulk_write(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0,
+ vals, ARRAY_SIZE(vals));
+}
+
+static int rtl9300_i2c_writel(struct rtl9300_i2c *i2c, u32 data)
+{
+ return regmap_write(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, data);
+}
+
+static int rtl9300_i2c_execute_xfer(struct rtl9300_i2c *i2c, char read_write,
+ int size, union i2c_smbus_data *data, int len)
+{
+ u32 val, mask;
+ int ret;
+
+ val = read_write == I2C_SMBUS_WRITE ? RTL9300_I2C_MST_CTRL1_RWOP : 0;
+ mask = RTL9300_I2C_MST_CTRL1_RWOP;
+
+ val |= RTL9300_I2C_MST_CTRL1_I2C_TRIG;
+ mask |= RTL9300_I2C_MST_CTRL1_I2C_TRIG;
+
+ ret = regmap_update_bits(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, mask, val);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1,
+ val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 2000);
+ if (ret)
+ return ret;
+
+ if (val & RTL9300_I2C_MST_CTRL1_I2C_FAIL)
+ return -EIO;
+
+ if (read_write == I2C_SMBUS_READ) {
+ if (size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA) {
+ ret = regmap_read(i2c->regmap,
+ i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val);
+ if (ret)
+ return ret;
+ data->byte = val & 0xff;
+ } else if (size == I2C_SMBUS_WORD_DATA) {
+ ret = regmap_read(i2c->regmap,
+ i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val);
+ if (ret)
+ return ret;
+ data->word = val & 0xffff;
+ } else {
+ ret = rtl9300_i2c_read(i2c, &data->block[0], len);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+ char read_write, u8 command, int size,
+ union i2c_smbus_data *data)
+{
+ struct rtl9300_i2c_chan *chan = i2c_get_adapdata(adap);
+ struct rtl9300_i2c *i2c = chan->i2c;
+ int len = 0, ret;
+
+ mutex_lock(&i2c->lock);
+ if (chan->sda_pin != i2c->sda_pin) {
+ ret = rtl9300_i2c_config_io(i2c, chan->sda_pin);
+ if (ret)
+ goto out_unlock;
+ i2c->sda_pin = chan->sda_pin;
+ }
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 0);
+ if (ret)
+ goto out_unlock;
+ ret = rtl9300_i2c_reg_addr_set(i2c, 0, 0);
+ if (ret)
+ goto out_unlock;
+ break;
+
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_WRITE) {
+ ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 0);
+ if (ret)
+ goto out_unlock;
+ ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
+ if (ret)
+ goto out_unlock;
+ } else {
+ ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 1);
+ if (ret)
+ goto out_unlock;
+ ret = rtl9300_i2c_reg_addr_set(i2c, 0, 0);
+ if (ret)
+ goto out_unlock;
+ }
+ break;
+
+ case I2C_SMBUS_BYTE_DATA:
+ ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
+ if (ret)
+ goto out_unlock;
+ ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 1);
+ if (ret)
+ goto out_unlock;
+ if (read_write == I2C_SMBUS_WRITE) {
+ ret = rtl9300_i2c_writel(i2c, data->byte);
+ if (ret)
+ goto out_unlock;
+ }
+ break;
+
+ case I2C_SMBUS_WORD_DATA:
+ ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
+ if (ret)
+ goto out_unlock;
+ ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 2);
+ if (ret)
+ goto out_unlock;
+ if (read_write == I2C_SMBUS_WRITE) {
+ ret = rtl9300_i2c_writel(i2c, data->word);
+ if (ret)
+ goto out_unlock;
+ }
+ break;
+
+ case I2C_SMBUS_BLOCK_DATA:
+ ret = rtl9300_i2c_reg_addr_set(i2c, command, 1);
+ if (ret)
+ goto out_unlock;
+ ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0]);
+ if (ret)
+ goto out_unlock;
+ if (read_write == I2C_SMBUS_WRITE) {
+ ret = rtl9300_i2c_write(i2c, &data->block[1], data->block[0]);
+ if (ret)
+ goto out_unlock;
+ }
+ len = data->block[0];
+ break;
+
+ default:
+ dev_err(&adap->dev, "Unsupported transaction %d\n", size);
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+
+ ret = rtl9300_i2c_execute_xfer(i2c, read_write, size, data, len);
+
+out_unlock:
+ mutex_unlock(&i2c->lock);
+
+ return ret;
+}
+
+static u32 rtl9300_i2c_func(struct i2c_adapter *a)
+{
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static const struct i2c_algorithm rtl9300_i2c_algo = {
+ .smbus_xfer = rtl9300_i2c_smbus_xfer,
+ .functionality = rtl9300_i2c_func,
+};
+
+static struct i2c_adapter_quirks rtl9300_i2c_quirks = {
+ .flags = I2C_AQ_NO_CLK_STRETCH,
+ .max_read_len = 16,
+ .max_write_len = 16,
+};
+
+static int rtl9300_i2c_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rtl9300_i2c *i2c;
+ u32 clock_freq, sda_pin;
+ int ret, i = 0;
+ struct fwnode_handle *child;
+
+ i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
+ return -ENOMEM;
+
+ i2c->regmap = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(i2c->regmap))
+ return PTR_ERR(i2c->regmap);
+ i2c->dev = dev;
+
+ mutex_init(&i2c->lock);
+
+ ret = device_property_read_u32(dev, "reg", &i2c->reg_base);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, i2c);
+
+ if (device_get_child_node_count(dev) >= RTL9300_I2C_MUX_NCHAN)
+ return dev_err_probe(dev, -EINVAL, "Too many channels\n");
+
+ device_for_each_child_node(dev, child) {
+ struct rtl9300_i2c_chan *chan = &i2c->chans[i];
+ struct i2c_adapter *adap = &chan->adap;
+
+ ret = fwnode_property_read_u32(child, "reg", &sda_pin);
+ if (ret)
+ return ret;
+
+ ret = fwnode_property_read_u32(child, "clock-frequency", &clock_freq);
+ if (ret)
+ clock_freq = I2C_MAX_STANDARD_MODE_FREQ;
+
+ switch (clock_freq) {
+ case I2C_MAX_STANDARD_MODE_FREQ:
+ chan->bus_freq = RTL9300_I2C_STD_FREQ;
+ break;
+
+ case I2C_MAX_FAST_MODE_FREQ:
+ chan->bus_freq = RTL9300_I2C_FAST_FREQ;
+ break;
+ default:
+ dev_warn(i2c->dev, "SDA%d clock-frequency %d not supported using default\n",
+ sda_pin, clock_freq);
+ break;
+ }
+
+ chan->sda_pin = sda_pin;
+ chan->i2c = i2c;
+ adap = &i2c->chans[i].adap;
+ adap->owner = THIS_MODULE;
+ adap->algo = &rtl9300_i2c_algo;
+ adap->quirks = &rtl9300_i2c_quirks;
+ adap->retries = 3;
+ adap->dev.parent = dev;
+ i2c_set_adapdata(adap, chan);
+ adap->dev.of_node = to_of_node(child);
+ snprintf(adap->name, sizeof(adap->name), "%s SDA%d\n", dev_name(dev), sda_pin);
+ i++;
+
+ ret = devm_i2c_add_adapter(dev, adap);
+ if (ret)
+ return ret;
+ }
+ i2c->sda_pin = 0xff;
+
+ return 0;
+}
+
+static const struct of_device_id i2c_rtl9300_dt_ids[] = {
+ { .compatible = "realtek,rtl9301-i2c" },
+ { .compatible = "realtek,rtl9302b-i2c" },
+ { .compatible = "realtek,rtl9302c-i2c" },
+ { .compatible = "realtek,rtl9303-i2c" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, i2c_rtl9300_dt_ids);
+
+static struct platform_driver rtl9300_i2c_driver = {
+ .probe = rtl9300_i2c_probe,
+ .driver = {
+ .name = "i2c-rtl9300",
+ .of_match_table = i2c_rtl9300_dt_ids,
+ },
+};
+
+module_platform_driver(rtl9300_i2c_driver);
+
+MODULE_DESCRIPTION("RTL9300 I2C controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-rzv2m.c b/drivers/i2c/busses/i2c-rzv2m.c
index 8380a68538ab..02b76e24a476 100644
--- a/drivers/i2c/busses/i2c-rzv2m.c
+++ b/drivers/i2c/busses/i2c-rzv2m.c
@@ -536,7 +536,7 @@ static struct platform_driver rzv2m_i2c_driver = {
.pm = pm_sleep_ptr(&rzv2m_i2c_pm_ops),
},
.probe = rzv2m_i2c_probe,
- .remove_new = rzv2m_i2c_remove,
+ .remove = rzv2m_i2c_remove,
};
module_platform_driver(rzv2m_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 7698d9d59744..0f3cf500df68 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1176,7 +1176,7 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
static struct platform_driver s3c24xx_i2c_driver = {
.probe = s3c24xx_i2c_probe,
- .remove_new = s3c24xx_i2c_remove,
+ .remove = s3c24xx_i2c_remove,
.id_table = s3c24xx_driver_ids,
.driver = {
.name = "s3c-i2c",
diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c
index d7af8e0d7599..10a5146b3aa5 100644
--- a/drivers/i2c/busses/i2c-scmi.c
+++ b/drivers/i2c/busses/i2c-scmi.c
@@ -411,7 +411,7 @@ static void smbus_cmi_remove(struct platform_device *device)
static struct platform_driver smbus_cmi_driver = {
.probe = smbus_cmi_probe,
- .remove_new = smbus_cmi_remove,
+ .remove = smbus_cmi_remove,
.driver = {
.name = "smbus_cmi",
.acpi_match_table = acpi_smbus_cmi_ids,
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index 8a043f5fca1e..620f12596763 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -552,7 +552,7 @@ static struct platform_driver sh7760_i2c_drv = {
.name = SH7760_I2C_DEVNAME,
},
.probe = sh7760_i2c_probe,
- .remove_new = sh7760_i2c_remove,
+ .remove = sh7760_i2c_remove,
};
module_platform_driver(sh7760_i2c_drv);
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index f86c29737df1..efe29621b8d7 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -983,7 +983,7 @@ static struct platform_driver sh_mobile_i2c_driver = {
.pm = pm_sleep_ptr(&sh_mobile_i2c_pm_ops),
},
.probe = sh_mobile_i2c_probe,
- .remove_new = sh_mobile_i2c_remove,
+ .remove = sh_mobile_i2c_remove,
};
static int __init sh_mobile_i2c_adap_init(void)
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
index 18516bc64e04..d90606048611 100644
--- a/drivers/i2c/busses/i2c-simtec.c
+++ b/drivers/i2c/busses/i2c-simtec.c
@@ -144,7 +144,7 @@ static struct platform_driver simtec_i2c_driver = {
.name = "simtec-i2c",
},
.probe = simtec_i2c_probe,
- .remove_new = simtec_i2c_remove,
+ .remove = simtec_i2c_remove,
};
module_platform_driver(simtec_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c
index 9c45e75b9187..56b2e5c5fb49 100644
--- a/drivers/i2c/busses/i2c-sprd.c
+++ b/drivers/i2c/busses/i2c-sprd.c
@@ -643,7 +643,7 @@ MODULE_DEVICE_TABLE(of, sprd_i2c_of_match);
static struct platform_driver sprd_i2c_driver = {
.probe = sprd_i2c_probe,
- .remove_new = sprd_i2c_remove,
+ .remove = sprd_i2c_remove,
.driver = {
.name = "sprd-i2c",
.of_match_table = sprd_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index 05b19ede65a0..750fff3d2389 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -893,7 +893,7 @@ static struct platform_driver st_i2c_driver = {
.pm = pm_sleep_ptr(&st_i2c_pm),
},
.probe = st_i2c_probe,
- .remove_new = st_i2c_remove,
+ .remove = st_i2c_remove,
};
module_platform_driver(st_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
index 230fff0c0bf9..b3d56d0aa9d0 100644
--- a/drivers/i2c/busses/i2c-stm32f4.c
+++ b/drivers/i2c/busses/i2c-stm32f4.c
@@ -869,7 +869,7 @@ static struct platform_driver stm32f4_i2c_driver = {
.of_match_table = stm32f4_i2c_match,
},
.probe = stm32f4_i2c_probe,
- .remove_new = stm32f4_i2c_remove,
+ .remove = stm32f4_i2c_remove,
};
module_platform_driver(stm32f4_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index 0174ead99de6..973a3a8c6d4a 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -2532,7 +2532,7 @@ static struct platform_driver stm32f7_i2c_driver = {
.pm = &stm32f7_i2c_pm_ops,
},
.probe = stm32f7_i2c_probe,
- .remove_new = stm32f7_i2c_remove,
+ .remove = stm32f7_i2c_remove,
};
module_platform_driver(stm32f7_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c
index 074eade6c4a4..fb5280b8cf7f 100644
--- a/drivers/i2c/busses/i2c-sun6i-p2wi.c
+++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c
@@ -319,7 +319,7 @@ static void p2wi_remove(struct platform_device *dev)
static struct platform_driver p2wi_driver = {
.probe = p2wi_probe,
- .remove_new = p2wi_remove,
+ .remove = p2wi_remove,
.driver = {
.name = "i2c-sunxi-p2wi",
.of_match_table = p2wi_of_match_table,
diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c
index bbb9062669e4..31f8d08e32a4 100644
--- a/drivers/i2c/busses/i2c-synquacer.c
+++ b/drivers/i2c/busses/i2c-synquacer.c
@@ -629,7 +629,7 @@ MODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids);
static struct platform_driver synquacer_i2c_driver = {
.probe = synquacer_i2c_probe,
- .remove_new = synquacer_i2c_remove,
+ .remove = synquacer_i2c_remove,
.driver = {
.name = "synquacer_i2c",
.of_match_table = of_match_ptr(synquacer_i2c_dt_ids),
diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c
index dabadbcc6d6a..bb0de6db6391 100644
--- a/drivers/i2c/busses/i2c-tegra-bpmp.c
+++ b/drivers/i2c/busses/i2c-tegra-bpmp.c
@@ -335,7 +335,7 @@ static struct platform_driver tegra_bpmp_i2c_driver = {
.of_match_table = tegra_bpmp_i2c_of_match,
},
.probe = tegra_bpmp_i2c_probe,
- .remove_new = tegra_bpmp_i2c_remove,
+ .remove = tegra_bpmp_i2c_remove,
};
module_platform_driver(tegra_bpmp_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 1df5b4204142..87976e99e6d0 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1964,7 +1964,7 @@ MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match);
static struct platform_driver tegra_i2c_driver = {
.probe = tegra_i2c_probe,
- .remove_new = tegra_i2c_remove,
+ .remove = tegra_i2c_remove,
.driver = {
.name = "tegra-i2c",
.of_match_table = tegra_i2c_of_match,
diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
index 10a99cd08972..d877f5a1f579 100644
--- a/drivers/i2c/busses/i2c-uniphier-f.c
+++ b/drivers/i2c/busses/i2c-uniphier-f.c
@@ -615,7 +615,7 @@ MODULE_DEVICE_TABLE(of, uniphier_fi2c_match);
static struct platform_driver uniphier_fi2c_drv = {
.probe = uniphier_fi2c_probe,
- .remove_new = uniphier_fi2c_remove,
+ .remove = uniphier_fi2c_remove,
.driver = {
.name = "uniphier-fi2c",
.of_match_table = uniphier_fi2c_match,
diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c
index ef5753307469..b95d50d4d7db 100644
--- a/drivers/i2c/busses/i2c-uniphier.c
+++ b/drivers/i2c/busses/i2c-uniphier.c
@@ -409,7 +409,7 @@ MODULE_DEVICE_TABLE(of, uniphier_i2c_match);
static struct platform_driver uniphier_i2c_drv = {
.probe = uniphier_i2c_probe,
- .remove_new = uniphier_i2c_remove,
+ .remove = uniphier_i2c_remove,
.driver = {
.name = "uniphier-i2c",
.of_match_table = uniphier_i2c_match,
diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
index 76abfa77e200..a1ab6ef6f071 100644
--- a/drivers/i2c/busses/i2c-versatile.c
+++ b/drivers/i2c/busses/i2c-versatile.c
@@ -109,7 +109,7 @@ MODULE_DEVICE_TABLE(of, i2c_versatile_match);
static struct platform_driver i2c_versatile_driver = {
.probe = i2c_versatile_probe,
- .remove_new = i2c_versatile_remove,
+ .remove = i2c_versatile_remove,
.driver = {
.name = "versatile-i2c",
.of_match_table = i2c_versatile_match,
diff --git a/drivers/i2c/busses/i2c-viai2c-wmt.c b/drivers/i2c/busses/i2c-viai2c-wmt.c
index 3415683dab91..4eb740faf268 100644
--- a/drivers/i2c/busses/i2c-viai2c-wmt.c
+++ b/drivers/i2c/busses/i2c-viai2c-wmt.c
@@ -169,7 +169,7 @@ static const struct of_device_id wmt_i2c_dt_ids[] = {
static struct platform_driver wmt_i2c_driver = {
.probe = wmt_i2c_probe,
- .remove_new = wmt_i2c_remove,
+ .remove = wmt_i2c_remove,
.driver = {
.name = "wmt-i2c",
.of_match_table = wmt_i2c_dt_ids,
diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c
index 2ed4130c0339..503e2f4d6f84 100644
--- a/drivers/i2c/busses/i2c-viperboard.c
+++ b/drivers/i2c/busses/i2c-viperboard.c
@@ -415,7 +415,7 @@ static void vprbrd_i2c_remove(struct platform_device *pdev)
static struct platform_driver vprbrd_i2c_driver = {
.driver.name = "viperboard-i2c",
.probe = vprbrd_i2c_probe,
- .remove_new = vprbrd_i2c_remove,
+ .remove = vprbrd_i2c_remove,
};
static int __init vprbrd_i2c_init(void)
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
index 658396c9eeab..663fe5604dd6 100644
--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
+++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
@@ -581,7 +581,7 @@ MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids);
static struct platform_driver xgene_slimpro_i2c_driver = {
.probe = xgene_slimpro_i2c_probe,
- .remove_new = xgene_slimpro_i2c_remove,
+ .remove = xgene_slimpro_i2c_remove,
.driver = {
.name = "xgene-slimpro-i2c",
.of_match_table = of_match_ptr(xgene_slimpro_i2c_dt_ids),
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 1d68177241a6..c4d3eb02da09 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -1395,7 +1395,7 @@ static const struct dev_pm_ops xiic_dev_pm_ops = {
static struct platform_driver xiic_i2c_driver = {
.probe = xiic_i2c_probe,
- .remove_new = xiic_i2c_remove,
+ .remove = xiic_i2c_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(xiic_of_match),
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
index 08a59a920929..4d5e49b6321b 100644
--- a/drivers/i2c/busses/i2c-xlp9xx.c
+++ b/drivers/i2c/busses/i2c-xlp9xx.c
@@ -579,7 +579,7 @@ MODULE_DEVICE_TABLE(acpi, xlp9xx_i2c_acpi_ids);
static struct platform_driver xlp9xx_i2c_driver = {
.probe = xlp9xx_i2c_probe,
- .remove_new = xlp9xx_i2c_remove,
+ .remove = xlp9xx_i2c_remove,
.driver = {
.name = "xlp9xx-i2c",
.acpi_match_table = ACPI_PTR(xlp9xx_i2c_acpi_ids),
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 3648382b885a..4d6abd7e92ce 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -536,7 +536,7 @@ static struct platform_driver scx200_pci_driver = {
.name = "cs5535-smb",
},
.probe = scx200_probe,
- .remove_new = scx200_remove,
+ .remove = scx200_remove,
};
static const struct pci_device_id scx200_isa[] = {
diff --git a/drivers/i2c/i2c-core-of-prober.c b/drivers/i2c/i2c-core-of-prober.c
new file mode 100644
index 000000000000..b9ca785f8b17
--- /dev/null
+++ b/drivers/i2c/i2c-core-of-prober.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Linux I2C core OF component prober code
+ *
+ * Copyright (C) 2024 Google LLC
+ */
+
+#include <linux/cleanup.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/i2c-of-prober.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+
+/*
+ * Some devices, such as Google Hana Chromebooks, are produced by multiple
+ * vendors each using their preferred components. Such components are all
+ * in the device tree. Instead of having all of them enabled and having each
+ * driver separately try and probe its device while fighting over shared
+ * resources, they can be marked as "fail-needs-probe" and have a prober
+ * figure out which one is actually used beforehand.
+ *
+ * This prober assumes such drop-in parts are on the same I2C bus, have
+ * non-conflicting addresses, and can be directly probed by seeing which
+ * address responds.
+ *
+ * TODO:
+ * - Support I2C muxes
+ */
+
+static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type)
+{
+ struct device_node *node __free(device_node) = of_find_node_by_name(NULL, type);
+ if (!node) {
+ dev_err(dev, "Could not find %s device node\n", type);
+ return NULL;
+ }
+
+ struct device_node *i2c_node __free(device_node) = of_get_parent(node);
+ if (!of_node_name_eq(i2c_node, "i2c")) {
+ dev_err(dev, "%s device isn't on I2C bus\n", type);
+ return NULL;
+ }
+
+ if (!of_device_is_available(i2c_node)) {
+ dev_err(dev, "I2C controller not available\n");
+ return NULL;
+ }
+
+ return no_free_ptr(i2c_node);
+}
+
+static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node)
+{
+ int ret;
+
+ dev_dbg(dev, "Enabling %pOF\n", node);
+
+ struct of_changeset *ocs __free(kfree) = kzalloc(sizeof(*ocs), GFP_KERNEL);
+ if (!ocs)
+ return -ENOMEM;
+
+ of_changeset_init(ocs);
+ ret = of_changeset_update_prop_string(ocs, node, "status", "okay");
+ if (ret)
+ return ret;
+
+ ret = of_changeset_apply(ocs);
+ if (ret) {
+ /* ocs needs to be explicitly cleaned up before being freed. */
+ of_changeset_destroy(ocs);
+ } else {
+ /*
+ * ocs is intentionally kept around as it needs to
+ * exist as long as the change is applied.
+ */
+ void *ptr __always_unused = no_free_ptr(ocs);
+ }
+
+ return ret;
+}
+
+static const struct i2c_of_probe_ops i2c_of_probe_dummy_ops;
+
+/**
+ * i2c_of_probe_component() - probe for devices of "type" on the same i2c bus
+ * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages.
+ * @cfg: Pointer to the &struct i2c_of_probe_cfg containing callbacks and other options
+ * for the prober.
+ * @ctx: Context data for callbacks.
+ *
+ * Probe for possible I2C components of the same "type" (&i2c_of_probe_cfg->type)
+ * on the same I2C bus that have their status marked as "fail-needs-probe".
+ *
+ * Assumes that across the entire device tree the only instances of nodes
+ * with "type" prefixed node names (not including the address portion) are
+ * the ones that need handling for second source components. In other words,
+ * if "type" is "touchscreen", then all device nodes named "touchscreen*"
+ * are the ones that need probing. There cannot be another "touchscreen*"
+ * node that is already enabled.
+ *
+ * Assumes that for each "type" of component, only one actually exists. In
+ * other words, only one matching and existing device will be enabled.
+ *
+ * Context: Process context only. Does non-atomic I2C transfers.
+ * Should only be used from a driver probe function, as the function
+ * can return -EPROBE_DEFER if the I2C adapter or other resources
+ * are unavailable.
+ * Return: 0 on success or no-op, error code otherwise.
+ * A no-op can happen when it seems like the device tree already
+ * has components of the type to be probed already enabled. This
+ * can happen when the device tree had not been updated to mark
+ * the status of the to-be-probed components as "fail-needs-probe".
+ * Or this function was already run with the same parameters and
+ * succeeded in enabling a component. The latter could happen if
+ * the user had multiple types of components to probe, and one of
+ * them down the list caused a deferred probe. This is expected
+ * behavior.
+ */
+int i2c_of_probe_component(struct device *dev, const struct i2c_of_probe_cfg *cfg, void *ctx)
+{
+ const struct i2c_of_probe_ops *ops;
+ const char *type;
+ struct i2c_adapter *i2c;
+ int ret;
+
+ ops = cfg->ops ?: &i2c_of_probe_dummy_ops;
+ type = cfg->type;
+
+ struct device_node *i2c_node __free(device_node) = i2c_of_probe_get_i2c_node(dev, type);
+ if (!i2c_node)
+ return -ENODEV;
+
+ /*
+ * If any devices of the given "type" are already enabled then this function is a no-op.
+ * Either the device tree hasn't been modified to work with this probe function, or the
+ * function had already run before and enabled some component.
+ */
+ for_each_child_of_node_with_prefix(i2c_node, node, type)
+ if (of_device_is_available(node))
+ return 0;
+
+ i2c = of_get_i2c_adapter_by_node(i2c_node);
+ if (!i2c)
+ return dev_err_probe(dev, -EPROBE_DEFER, "Couldn't get I2C adapter\n");
+
+ /* Grab and enable resources */
+ ret = 0;
+ if (ops->enable)
+ ret = ops->enable(dev, i2c_node, ctx);
+ if (ret)
+ goto out_put_i2c_adapter;
+
+ for_each_child_of_node_with_prefix(i2c_node, node, type) {
+ union i2c_smbus_data data;
+ u32 addr;
+
+ if (of_property_read_u32(node, "reg", &addr))
+ continue;
+ if (i2c_smbus_xfer(i2c, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data) < 0)
+ continue;
+
+ /* Found a device that is responding */
+ if (ops->cleanup_early)
+ ops->cleanup_early(dev, ctx);
+ ret = i2c_of_probe_enable_node(dev, node);
+ break;
+ }
+
+ if (ops->cleanup)
+ ops->cleanup(dev, ctx);
+out_put_i2c_adapter:
+ i2c_put_adapter(i2c);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_component, I2C_OF_PROBER);
+
+static int i2c_of_probe_simple_get_supply(struct device *dev, struct device_node *node,
+ struct i2c_of_probe_simple_ctx *ctx)
+{
+ const char *supply_name;
+ struct regulator *supply;
+
+ /*
+ * It's entirely possible for the component's device node to not have the
+ * regulator supplies. While it does not make sense from a hardware perspective,
+ * the supplies could be always on or otherwise not modeled in the device tree,
+ * but the device would still work.
+ */
+ supply_name = ctx->opts->supply_name;
+ if (!supply_name)
+ return 0;
+
+ supply = of_regulator_get_optional(dev, node, supply_name);
+ if (IS_ERR(supply)) {
+ return dev_err_probe(dev, PTR_ERR(supply),
+ "Failed to get regulator supply \"%s\" from %pOF\n",
+ supply_name, node);
+ }
+
+ ctx->supply = supply;
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_put_supply(struct i2c_of_probe_simple_ctx *ctx)
+{
+ regulator_put(ctx->supply);
+ ctx->supply = NULL;
+}
+
+static int i2c_of_probe_simple_enable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ int ret;
+
+ if (!ctx->supply)
+ return 0;
+
+ dev_dbg(dev, "Enabling regulator supply \"%s\"\n", ctx->opts->supply_name);
+
+ ret = regulator_enable(ctx->supply);
+ if (ret)
+ return ret;
+
+ if (ctx->opts->post_power_on_delay_ms)
+ msleep(ctx->opts->post_power_on_delay_ms);
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_disable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ if (!ctx->supply)
+ return;
+
+ dev_dbg(dev, "Disabling regulator supply \"%s\"\n", ctx->opts->supply_name);
+
+ regulator_disable(ctx->supply);
+}
+
+static int i2c_of_probe_simple_get_gpiod(struct device *dev, struct device_node *node,
+ struct i2c_of_probe_simple_ctx *ctx)
+{
+ struct fwnode_handle *fwnode = of_fwnode_handle(node);
+ struct gpio_desc *gpiod;
+ const char *con_id;
+
+ /* NULL signals no GPIO needed */
+ if (!ctx->opts->gpio_name)
+ return 0;
+
+ /* An empty string signals an unnamed GPIO */
+ if (!ctx->opts->gpio_name[0])
+ con_id = NULL;
+ else
+ con_id = ctx->opts->gpio_name;
+
+ gpiod = fwnode_gpiod_get_index(fwnode, con_id, 0, GPIOD_ASIS, "i2c-of-prober");
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
+ ctx->gpiod = gpiod;
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_put_gpiod(struct i2c_of_probe_simple_ctx *ctx)
+{
+ gpiod_put(ctx->gpiod);
+ ctx->gpiod = NULL;
+}
+
+static int i2c_of_probe_simple_set_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ int ret;
+
+ if (!ctx->gpiod)
+ return 0;
+
+ dev_dbg(dev, "Configuring GPIO\n");
+
+ ret = gpiod_direction_output(ctx->gpiod, ctx->opts->gpio_assert_to_enable);
+ if (ret)
+ return ret;
+
+ if (ctx->opts->post_gpio_config_delay_ms)
+ msleep(ctx->opts->post_gpio_config_delay_ms);
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_disable_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ gpiod_set_value(ctx->gpiod, !ctx->opts->gpio_assert_to_enable);
+}
+
+/**
+ * i2c_of_probe_simple_enable - Simple helper for I2C OF prober to get and enable resources
+ * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
+ * @bus_node: Pointer to the &struct device_node of the I2C adapter.
+ * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
+ *
+ * If &i2c_of_probe_simple_opts->supply_name is given, request the named regulator supply.
+ * If &i2c_of_probe_simple_opts->gpio_name is given, request the named GPIO. Or if it is
+ * the empty string, request the unnamed GPIO.
+ * If a regulator supply was found, enable that regulator.
+ * If a GPIO line was found, configure the GPIO line to output and set value
+ * according to given options.
+ *
+ * Return: %0 on success or no-op, or a negative error number on failure.
+ */
+int i2c_of_probe_simple_enable(struct device *dev, struct device_node *bus_node, void *data)
+{
+ struct i2c_of_probe_simple_ctx *ctx = data;
+ struct device_node *node;
+ const char *compat;
+ int ret;
+
+ dev_dbg(dev, "Requesting resources for components under I2C bus %pOF\n", bus_node);
+
+ if (!ctx || !ctx->opts)
+ return -EINVAL;
+
+ compat = ctx->opts->res_node_compatible;
+ if (!compat)
+ return -EINVAL;
+
+ node = of_get_compatible_child(bus_node, compat);
+ if (!node)
+ return dev_err_probe(dev, -ENODEV, "No device compatible with \"%s\" found\n",
+ compat);
+
+ ret = i2c_of_probe_simple_get_supply(dev, node, ctx);
+ if (ret)
+ goto out_put_node;
+
+ ret = i2c_of_probe_simple_get_gpiod(dev, node, ctx);
+ if (ret)
+ goto out_put_supply;
+
+ ret = i2c_of_probe_simple_enable_regulator(dev, ctx);
+ if (ret)
+ goto out_put_gpiod;
+
+ ret = i2c_of_probe_simple_set_gpio(dev, ctx);
+ if (ret)
+ goto out_disable_regulator;
+
+ return 0;
+
+out_disable_regulator:
+ i2c_of_probe_simple_disable_regulator(dev, ctx);
+out_put_gpiod:
+ i2c_of_probe_simple_put_gpiod(ctx);
+out_put_supply:
+ i2c_of_probe_simple_put_supply(ctx);
+out_put_node:
+ of_node_put(node);
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_enable, I2C_OF_PROBER);
+
+/**
+ * i2c_of_probe_simple_cleanup_early - \
+ * Simple helper for I2C OF prober to release GPIOs before component is enabled
+ * @dev: Pointer to the &struct device of the caller; unused.
+ * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
+ *
+ * GPIO descriptors are exclusive and have to be released before the
+ * actual driver probes so that the latter can acquire them.
+ */
+void i2c_of_probe_simple_cleanup_early(struct device *dev, void *data)
+{
+ struct i2c_of_probe_simple_ctx *ctx = data;
+
+ i2c_of_probe_simple_put_gpiod(ctx);
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup_early, I2C_OF_PROBER);
+
+/**
+ * i2c_of_probe_simple_cleanup - Clean up and release resources for I2C OF prober simple helpers
+ * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
+ * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
+ *
+ * * If a GPIO line was found and not yet released, set its value to the opposite of that
+ * set in i2c_of_probe_simple_enable() and release it.
+ * * If a regulator supply was found, disable that regulator and release it.
+ */
+void i2c_of_probe_simple_cleanup(struct device *dev, void *data)
+{
+ struct i2c_of_probe_simple_ctx *ctx = data;
+
+ /* GPIO operations here are no-ops if i2c_of_probe_simple_cleanup_early was called. */
+ i2c_of_probe_simple_disable_gpio(dev, ctx);
+ i2c_of_probe_simple_put_gpiod(ctx);
+
+ i2c_of_probe_simple_disable_regulator(dev, ctx);
+ i2c_of_probe_simple_put_supply(ctx);
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup, I2C_OF_PROBER);
+
+struct i2c_of_probe_ops i2c_of_probe_simple_ops = {
+ .enable = i2c_of_probe_simple_enable,
+ .cleanup_early = i2c_of_probe_simple_cleanup_early,
+ .cleanup = i2c_of_probe_simple_cleanup,
+};
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_ops, I2C_OF_PROBER);
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index e3b96fc53b5c..e73afbefe222 100644
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -122,7 +122,7 @@ EXPORT_SYMBOL(i2c_smbus_read_byte);
s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
{
return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
- I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
+ I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
}
EXPORT_SYMBOL(i2c_smbus_write_byte);
@@ -712,12 +712,15 @@ int i2c_setup_smbus_alert(struct i2c_adapter *adapter)
if (!parent)
return 0;
+ /* Report serious errors */
irq = device_property_match_string(parent, "interrupt-names", "smbus_alert");
- if (irq == -EINVAL || irq == -ENODATA)
- return 0;
- else if (irq < 0)
+ if (irq < 0 && irq != -EINVAL && irq != -ENODATA)
return irq;
+ /* Skip setup when no irq was found */
+ if (irq < 0 && !device_property_present(parent, "smbalert-gpios"))
+ return 0;
+
return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL));
}
#endif
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 61f7c4003d2f..e9577f920286 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -251,10 +251,8 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
return -EOPNOTSUPP;
data_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL);
- if (data_ptrs == NULL) {
- kfree(msgs);
+ if (!data_ptrs)
return -ENOMEM;
- }
res = 0;
for (i = 0; i < nmsgs; i++) {
@@ -302,7 +300,6 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
for (j = 0; j < i; ++j)
kfree(msgs[j].buf);
kfree(data_ptrs);
- kfree(msgs);
return res;
}
@@ -316,7 +313,6 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
kfree(msgs[i].buf);
}
kfree(data_ptrs);
- kfree(msgs);
return res;
}
@@ -446,6 +442,7 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case I2C_RDWR: {
struct i2c_rdwr_ioctl_data rdwr_arg;
struct i2c_msg *rdwr_pa;
+ int res;
if (copy_from_user(&rdwr_arg,
(struct i2c_rdwr_ioctl_data __user *)arg,
@@ -467,7 +464,9 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (IS_ERR(rdwr_pa))
return PTR_ERR(rdwr_pa);
- return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
+ res = i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
+ kfree(rdwr_pa);
+ return res;
}
case I2C_SMBUS: {
@@ -540,7 +539,7 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo
struct i2c_rdwr_ioctl_data32 rdwr_arg;
struct i2c_msg32 __user *p;
struct i2c_msg *rdwr_pa;
- int i;
+ int i, res;
if (copy_from_user(&rdwr_arg,
(struct i2c_rdwr_ioctl_data32 __user *)arg,
@@ -573,7 +572,9 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo
};
}
- return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
+ res = i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
+ kfree(rdwr_pa);
+ return res;
}
case I2C_SMBUS: {
struct i2c_smbus_ioctl_data32 data32;
diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c
index 9fe3150378e8..0d6fbaa48248 100644
--- a/drivers/i2c/i2c-slave-testunit.c
+++ b/drivers/i2c/i2c-slave-testunit.c
@@ -183,6 +183,10 @@ static void i2c_slave_testunit_work(struct work_struct *work)
break;
case TU_CMD_SMBUS_ALERT_REQUEST:
+ if (!tu->gpio) {
+ ret = -ENOENT;
+ break;
+ }
i2c_slave_unregister(tu->client);
orig_addr = tu->client->addr;
tu->client->addr = 0x0c;
@@ -232,6 +236,9 @@ static int i2c_slave_testunit_probe(struct i2c_client *client)
INIT_DELAYED_WORK(&tu->worker, i2c_slave_testunit_work);
tu->gpio = devm_gpiod_get_index_optional(&client->dev, NULL, 0, GPIOD_OUT_LOW);
+ if (IS_ERR(tu->gpio))
+ return PTR_ERR(tu->gpio);
+
if (gpiod_cansleep(tu->gpio)) {
dev_err(&client->dev, "GPIO access which may sleep is not allowed\n");
return -EDEADLK;
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
index 8256f7aed0cf..7d40e7aa3799 100644
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/interrupt.h>
@@ -167,6 +168,8 @@ static int smbalert_probe(struct i2c_client *ara)
struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
struct i2c_smbus_alert *alert;
struct i2c_adapter *adapter = ara->adapter;
+ unsigned long irqflags = IRQF_SHARED | IRQF_ONESHOT;
+ struct gpio_desc *gpiod;
int res, irq;
alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
@@ -179,18 +182,25 @@ static int smbalert_probe(struct i2c_client *ara)
} else {
irq = fwnode_irq_get_byname(dev_fwnode(adapter->dev.parent),
"smbus_alert");
- if (irq <= 0)
- return irq;
+ if (irq <= 0) {
+ gpiod = devm_gpiod_get(adapter->dev.parent, "smbalert", GPIOD_IN);
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
+ irq = gpiod_to_irq(gpiod);
+ if (irq <= 0)
+ return irq;
+
+ irqflags |= IRQF_TRIGGER_FALLING;
+ }
}
INIT_WORK(&alert->alert, smbalert_work);
alert->ara = ara;
if (irq > 0) {
- res = devm_request_threaded_irq(&ara->dev, irq,
- NULL, smbus_alert,
- IRQF_SHARED | IRQF_ONESHOT,
- "smbus_alert", alert);
+ res = devm_request_threaded_irq(&ara->dev, irq, NULL, smbus_alert,
+ irqflags, "smbus_alert", alert);
if (res)
return res;
}
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 7aa6e795d833..d6ef91b888c6 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -190,7 +190,7 @@ MODULE_DEVICE_TABLE(of, i2c_arbitrator_of_match);
static struct platform_driver i2c_arbitrator_driver = {
.probe = i2c_arbitrator_probe,
- .remove_new = i2c_arbitrator_remove,
+ .remove = i2c_arbitrator_remove,
.driver = {
.name = "i2c-arb-gpio-challenge",
.of_match_table = i2c_arbitrator_of_match,
diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c
index 7e2686b606c0..dce18f763a09 100644
--- a/drivers/i2c/muxes/i2c-demux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c
@@ -314,7 +314,7 @@ static struct platform_driver i2c_demux_pinctrl_driver = {
.of_match_table = i2c_demux_pinctrl_of_match,
},
.probe = i2c_demux_pinctrl_probe,
- .remove_new = i2c_demux_pinctrl_remove,
+ .remove = i2c_demux_pinctrl_remove,
};
module_platform_driver(i2c_demux_pinctrl_driver);
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 944577bb09c1..9b46b84e84fb 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -247,7 +247,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match);
static struct platform_driver i2c_mux_gpio_driver = {
.probe = i2c_mux_gpio_probe,
- .remove_new = i2c_mux_gpio_remove,
+ .remove = i2c_mux_gpio_remove,
.driver = {
.name = "i2c-mux-gpio",
.of_match_table = i2c_mux_gpio_of_match,
diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c
index 10d63307b14d..ab8e11661052 100644
--- a/drivers/i2c/muxes/i2c-mux-gpmux.c
+++ b/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -152,7 +152,7 @@ static void i2c_mux_remove(struct platform_device *pdev)
static struct platform_driver i2c_mux_driver = {
.probe = i2c_mux_probe,
- .remove_new = i2c_mux_remove,
+ .remove = i2c_mux_remove,
.driver = {
.name = "i2c-mux-gpmux",
.of_match_table = i2c_mux_of_match,
diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
index 3f06aa3331a7..1c2debcf379c 100644
--- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c
+++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
@@ -182,7 +182,7 @@ static struct platform_driver mlxcpld_mux_driver = {
.name = "i2c-mux-mlxcpld",
},
.probe = mlxcpld_mux_probe,
- .remove_new = mlxcpld_mux_remove,
+ .remove = mlxcpld_mux_remove,
};
module_platform_driver(mlxcpld_mux_driver);
diff --git a/drivers/i2c/muxes/i2c-mux-mule.c b/drivers/i2c/muxes/i2c-mux-mule.c
index 8e942470b35f..284ff4afeeac 100644
--- a/drivers/i2c/muxes/i2c-mux-mule.c
+++ b/drivers/i2c/muxes/i2c-mux-mule.c
@@ -66,8 +66,8 @@ static int mule_i2c_mux_probe(struct platform_device *pdev)
priv = i2c_mux_priv(muxc);
priv->regmap = dev_get_regmap(mux_dev->parent, NULL);
- if (IS_ERR(priv->regmap))
- return dev_err_probe(mux_dev, PTR_ERR(priv->regmap),
+ if (!priv->regmap)
+ return dev_err_probe(mux_dev, -ENODEV,
"No parent i2c register map\n");
platform_set_drvdata(pdev, muxc);
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 02aaf0781e9c..fc686a350ae8 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -186,7 +186,7 @@ static struct platform_driver i2c_mux_pinctrl_driver = {
.of_match_table = i2c_mux_pinctrl_of_match,
},
.probe = i2c_mux_pinctrl_probe,
- .remove_new = i2c_mux_pinctrl_remove,
+ .remove = i2c_mux_pinctrl_remove,
};
module_platform_driver(i2c_mux_pinctrl_driver);
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index ef765fcd33f5..dfa472d514cc 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -247,7 +247,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_reg_of_match);
static struct platform_driver i2c_mux_reg_driver = {
.probe = i2c_mux_reg_probe,
- .remove_new = i2c_mux_reg_remove,
+ .remove = i2c_mux_reg_remove,
.driver = {
.name = "i2c-mux-reg",
.of_match_table = of_match_ptr(i2c_mux_reg_of_match),
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 6f3eb710a75d..42310c9a00c2 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -282,7 +282,8 @@ static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *e
struct i3c_device_info devinfo;
u16 manuf, part, ext;
- i3c_device_get_info(i3cdev, &devinfo);
+ if (i3cdev->desc)
+ devinfo = i3cdev->desc->info;
manuf = I3C_PID_MANUF_ID(devinfo.pid);
part = I3C_PID_PART_ID(devinfo.pid);
ext = I3C_PID_EXTRA_INFO(devinfo.pid);
@@ -345,10 +346,10 @@ const struct bus_type i3c_bus_type = {
EXPORT_SYMBOL_GPL(i3c_bus_type);
static enum i3c_addr_slot_status
-i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+i3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask)
{
unsigned long status;
- int bitpos = addr * 2;
+ int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
if (addr > I2C_MAX_ADDR)
return I3C_ADDR_SLOT_RSVD;
@@ -356,22 +357,33 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
status = bus->addrslots[bitpos / BITS_PER_LONG];
status >>= bitpos % BITS_PER_LONG;
- return status & I3C_ADDR_SLOT_STATUS_MASK;
+ return status & mask;
}
-static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
- enum i3c_addr_slot_status status)
+static enum i3c_addr_slot_status
+i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+{
+ return i3c_bus_get_addr_slot_status_mask(bus, addr, I3C_ADDR_SLOT_STATUS_MASK);
+}
+
+static void i3c_bus_set_addr_slot_status_mask(struct i3c_bus *bus, u16 addr,
+ enum i3c_addr_slot_status status, u32 mask)
{
- int bitpos = addr * 2;
+ int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
unsigned long *ptr;
if (addr > I2C_MAX_ADDR)
return;
ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
- *ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
- (bitpos % BITS_PER_LONG));
- *ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
+ *ptr &= ~((unsigned long)mask << (bitpos % BITS_PER_LONG));
+ *ptr |= ((unsigned long)status & mask) << (bitpos % BITS_PER_LONG);
+}
+
+static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
+ enum i3c_addr_slot_status status)
+{
+ i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_STATUS_MASK);
}
static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
@@ -383,13 +395,44 @@ static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
return status == I3C_ADDR_SLOT_FREE;
}
+/*
+ * ┌────┬─────────────┬───┬─────────┬───â”
+ * │S/Sr│ 7'h7E RnW=0 │ACK│ ENTDAA │ T ├────â”
+ * └────┴─────────────┴───┴─────────┴───┘ │
+ * ┌─────────────────────────────────────────┘
+ * │ ┌──┬─────────────┬───┬─────────────────┬────────────────┬───┬─────────â”
+ * └─►│Sr│7'h7E RnW=1 │ACK│48bit UID BCR DCR│Assign 7bit Addr│PAR│ ACK/NACK│
+ * └──┴─────────────┴───┴─────────────────┴────────────────┴───┴─────────┘
+ * Some master controllers (such as HCI) need to prepare the entire above transaction before
+ * sending it out to the I3C bus. This means that a 7-bit dynamic address needs to be allocated
+ * before knowing the target device's UID information.
+ *
+ * However, some I3C targets may request specific addresses (called as "init_dyn_addr"), which is
+ * typically specified by the DT-'s assigned-address property. Lower addresses having higher IBI
+ * priority. If it is available, i3c_bus_get_free_addr() preferably return a free address that is
+ * not in the list of desired addresses (called as "init_dyn_addr"). This allows the device with
+ * the "init_dyn_addr" to switch to its "init_dyn_addr" when it hot-joins the I3C bus. Otherwise,
+ * if the "init_dyn_addr" is already in use by another I3C device, the target device will not be
+ * able to switch to its desired address.
+ *
+ * If the previous step fails, fallback returning one of the remaining unassigned address,
+ * regardless of its state in the desired list.
+ */
static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
{
enum i3c_addr_slot_status status;
u8 addr;
for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
- status = i3c_bus_get_addr_slot_status(bus, addr);
+ status = i3c_bus_get_addr_slot_status_mask(bus, addr,
+ I3C_ADDR_SLOT_EXT_STATUS_MASK);
+ if (status == I3C_ADDR_SLOT_FREE)
+ return addr;
+ }
+
+ for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
+ status = i3c_bus_get_addr_slot_status_mask(bus, addr,
+ I3C_ADDR_SLOT_STATUS_MASK);
if (status == I3C_ADDR_SLOT_FREE)
return addr;
}
@@ -1417,7 +1460,7 @@ static void i3c_master_put_i3c_addrs(struct i3c_dev_desc *dev)
I3C_ADDR_SLOT_FREE);
if (dev->boardinfo && dev->boardinfo->init_dyn_addr)
- i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
+ i3c_bus_set_addr_slot_status(&master->bus, dev->boardinfo->init_dyn_addr,
I3C_ADDR_SLOT_FREE);
}
@@ -1506,16 +1549,9 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
u8 old_dyn_addr)
{
struct i3c_master_controller *master = i3c_dev_get_master(dev);
- enum i3c_addr_slot_status status;
int ret;
- if (dev->info.dyn_addr != old_dyn_addr &&
- (!dev->boardinfo ||
- dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
- status = i3c_bus_get_addr_slot_status(&master->bus,
- dev->info.dyn_addr);
- if (status != I3C_ADDR_SLOT_FREE)
- return -EBUSY;
+ if (dev->info.dyn_addr != old_dyn_addr) {
i3c_bus_set_addr_slot_status(&master->bus,
dev->info.dyn_addr,
I3C_ADDR_SLOT_I3C_DEV);
@@ -1918,9 +1954,11 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
goto err_rstdaa;
}
- i3c_bus_set_addr_slot_status(&master->bus,
- i3cboardinfo->init_dyn_addr,
- I3C_ADDR_SLOT_I3C_DEV);
+ /* Do not mark as occupied until real device exist in bus */
+ i3c_bus_set_addr_slot_status_mask(&master->bus,
+ i3cboardinfo->init_dyn_addr,
+ I3C_ADDR_SLOT_EXT_DESIRED,
+ I3C_ADDR_SLOT_EXT_STATUS_MASK);
/*
* Only try to create/attach devices that have a static
@@ -2051,11 +2089,16 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
ibireq.max_payload_len = olddev->ibi->max_payload_len;
ibireq.num_slots = olddev->ibi->num_slots;
- if (olddev->ibi->enabled) {
+ if (olddev->ibi->enabled)
enable_ibi = true;
- i3c_dev_disable_ibi_locked(olddev);
- }
-
+ /*
+ * The olddev should not receive any commands on the
+ * i3c bus as it does not exist and has been assigned
+ * a new address. This will result in NACK or timeout.
+ * So, update the olddev->ibi->enabled flag to false
+ * to avoid DISEC with OldAddr.
+ */
+ olddev->ibi->enabled = false;
i3c_dev_free_ibi_locked(olddev);
}
mutex_unlock(&olddev->ibi_lock);
@@ -2083,7 +2126,8 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
else
expected_dyn_addr = newdev->info.dyn_addr;
- if (newdev->info.dyn_addr != expected_dyn_addr) {
+ if (newdev->info.dyn_addr != expected_dyn_addr &&
+ i3c_bus_get_addr_slot_status(&master->bus, expected_dyn_addr) == I3C_ADDR_SLOT_FREE) {
/*
* Try to apply the expected dynamic address. If it fails, keep
* the address assigned by the master.
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 8d694672c110..5b5c2e4bdc51 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -220,6 +220,14 @@
#define XFER_TIMEOUT (msecs_to_jiffies(1000))
#define RPM_AUTOSUSPEND_TIMEOUT 1000 /* ms */
+
+/* Timing values to configure 12.5MHz frequency */
+#define AMD_I3C_OD_TIMING 0x4C007C
+#define AMD_I3C_PP_TIMING 0x8001A
+
+/* List of quirks */
+#define AMD_I3C_OD_PP_TIMING BIT(1)
+
struct dw_i3c_cmd {
u32 cmd_lo;
u32 cmd_hi;
@@ -794,6 +802,12 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
return ret;
}
+static void amd_configure_od_pp_quirk(struct dw_i3c_master *master)
+{
+ master->i3c_od_timing = AMD_I3C_OD_TIMING;
+ master->i3c_pp_timing = AMD_I3C_PP_TIMING;
+}
+
static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
struct i3c_ccc_cmd *ccc)
{
@@ -803,6 +817,13 @@ static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
if (ccc->id == I3C_CCC_ENTDAA)
return -EINVAL;
+ /* AMD platform specific OD and PP timings */
+ if (master->quirks & AMD_I3C_OD_PP_TIMING) {
+ amd_configure_od_pp_quirk(master);
+ writel(master->i3c_pp_timing, master->regs + SCL_I3C_PP_TIMING);
+ writel(master->i3c_od_timing, master->regs + SCL_I3C_OD_TIMING);
+ }
+
ret = pm_runtime_resume_and_get(master->dev);
if (ret < 0) {
dev_err(master->dev,
@@ -1602,6 +1623,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
master->maxdevs = ret >> 16;
master->free_pos = GENMASK(master->maxdevs - 1, 0);
+ master->quirks = (unsigned long)device_get_match_data(&pdev->dev);
+
INIT_WORK(&master->hj_work, dw_i3c_hj_work);
ret = i3c_master_register(&master->base, &pdev->dev,
&dw_mipi_i3c_ops, false);
@@ -1675,6 +1698,10 @@ static void dw_i3c_master_restore_addrs(struct dw_i3c_master *master)
static void dw_i3c_master_restore_timing_regs(struct dw_i3c_master *master)
{
+ /* AMD platform specific OD and PP timings */
+ if (master->quirks & AMD_I3C_OD_PP_TIMING)
+ amd_configure_od_pp_quirk(master);
+
writel(master->i3c_pp_timing, master->regs + SCL_I3C_PP_TIMING);
writel(master->bus_free_timing, master->regs + BUS_FREE_TIMING);
writel(master->i3c_od_timing, master->regs + SCL_I3C_OD_TIMING);
@@ -1748,12 +1775,19 @@ static const struct of_device_id dw_i3c_master_of_match[] = {
};
MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match);
+static const struct acpi_device_id amd_i3c_device_match[] = {
+ { "AMDI0015", AMD_I3C_OD_PP_TIMING },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, amd_i3c_device_match);
+
static struct platform_driver dw_i3c_driver = {
.probe = dw_i3c_probe,
.remove_new = dw_i3c_remove,
.driver = {
.name = "dw-i3c-master",
.of_match_table = dw_i3c_master_of_match,
+ .acpi_match_table = amd_i3c_device_match,
.pm = &dw_i3c_pm_ops,
},
};
diff --git a/drivers/i3c/master/dw-i3c-master.h b/drivers/i3c/master/dw-i3c-master.h
index 219ff815d3a7..c5cb695c16ab 100644
--- a/drivers/i3c/master/dw-i3c-master.h
+++ b/drivers/i3c/master/dw-i3c-master.h
@@ -50,6 +50,7 @@ struct dw_i3c_master {
u32 bus_free_timing;
u32 i2c_fm_timing;
u32 i2c_fmp_timing;
+ u32 quirks;
/*
* Per-device hardware data, used to manage the device address table
* (DAT)
diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index a82c47c9986d..e6e482a259b4 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -80,8 +80,6 @@
#define INTR_HC_CMD_SEQ_UFLOW_STAT BIT(12) /* Cmd Sequence Underflow */
#define INTR_HC_RESET_CANCEL BIT(11) /* HC Cancelled Reset */
#define INTR_HC_INTERNAL_ERR BIT(10) /* HC Internal Error */
-#define INTR_HC_PIO BIT(8) /* cascaded PIO interrupt */
-#define INTR_HC_RINGS GENMASK(7, 0)
#define DAT_SECTION 0x30 /* Device Address Table */
#define DAT_ENTRY_SIZE GENMASK(31, 28)
@@ -438,7 +436,8 @@ static int i3c_hci_attach_i3c_dev(struct i3c_dev_desc *dev)
kfree(dev_data);
return ret;
}
- mipi_i3c_hci_dat_v1.set_dynamic_addr(hci, ret, dev->info.dyn_addr);
+ mipi_i3c_hci_dat_v1.set_dynamic_addr(hci, ret,
+ dev->info.dyn_addr ?: dev->info.static_addr);
dev_data->dat_idx = ret;
}
i3c_dev_set_master_data(dev, dev_data);
@@ -597,9 +596,6 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
if (val) {
reg_write(INTR_STATUS, val);
- } else {
- /* v1.0 does not have PIO cascaded notification bits */
- val |= INTR_HC_PIO;
}
if (val & INTR_HC_RESET_CANCEL) {
@@ -610,14 +606,9 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
dev_err(&hci->master.dev, "Host Controller Internal Error\n");
val &= ~INTR_HC_INTERNAL_ERR;
}
- if (val & INTR_HC_PIO) {
- hci->io->irq_handler(hci, 0);
- val &= ~INTR_HC_PIO;
- }
- if (val & INTR_HC_RINGS) {
- hci->io->irq_handler(hci, val & INTR_HC_RINGS);
- val &= ~INTR_HC_RINGS;
- }
+
+ hci->io->irq_handler(hci);
+
if (val)
dev_err(&hci->master.dev, "unexpected INTR_STATUS %#x\n", val);
else
diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index a918e96b21fd..e8e56a8d2057 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -159,10 +159,10 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
for (i = 0; i < rings->total; i++) {
rh = &rings->headers[i];
+ rh_reg_write(INTR_SIGNAL_ENABLE, 0);
rh_reg_write(RING_CONTROL, 0);
rh_reg_write(CR_SETUP, 0);
rh_reg_write(IBI_SETUP, 0);
- rh_reg_write(INTR_SIGNAL_ENABLE, 0);
if (rh->xfer)
dma_free_coherent(&hci->master.dev,
@@ -733,20 +733,16 @@ done:
rh_reg_write(CHUNK_CONTROL, rh_reg_read(CHUNK_CONTROL) + ibi_chunks);
}
-static bool hci_dma_irq_handler(struct i3c_hci *hci, unsigned int mask)
+static bool hci_dma_irq_handler(struct i3c_hci *hci)
{
struct hci_rings_data *rings = hci->io_data;
unsigned int i;
bool handled = false;
- for (i = 0; mask && i < rings->total; i++) {
+ for (i = 0; i < rings->total; i++) {
struct hci_rh_data *rh;
u32 status;
- if (!(mask & BIT(i)))
- continue;
- mask &= ~BIT(i);
-
rh = &rings->headers[i];
status = rh_reg_read(INTR_STATUS);
DBG("rh%d status: %#x", i, status);
diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
index aaa47ac47381..69ea1d10414b 100644
--- a/drivers/i3c/master/mipi-i3c-hci/hci.h
+++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
@@ -115,7 +115,7 @@ static inline void hci_free_xfer(struct hci_xfer *xfer, unsigned int n)
/* This abstracts PIO vs DMA operations */
struct hci_io_ops {
- bool (*irq_handler)(struct i3c_hci *hci, unsigned int mask);
+ bool (*irq_handler)(struct i3c_hci *hci);
int (*queue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n);
bool (*dequeue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n);
int (*request_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev,
diff --git a/drivers/i3c/master/mipi-i3c-hci/pio.c b/drivers/i3c/master/mipi-i3c-hci/pio.c
index d0272aa93599..2fc71e696911 100644
--- a/drivers/i3c/master/mipi-i3c-hci/pio.c
+++ b/drivers/i3c/master/mipi-i3c-hci/pio.c
@@ -979,7 +979,7 @@ static void hci_pio_recycle_ibi_slot(struct i3c_hci *hci,
i3c_generic_ibi_recycle_slot(dev_ibi->pool, slot);
}
-static bool hci_pio_irq_handler(struct i3c_hci *hci, unsigned int unused)
+static bool hci_pio_irq_handler(struct i3c_hci *hci)
{
struct hci_pio_data *pio = hci->io_data;
u32 status;
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index a7bfc678153e..c1ee3828e7ee 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -130,8 +130,8 @@
#define SVC_I3C_PPBAUD_MAX 15
#define SVC_I3C_QUICK_I2C_CLK 4170000
-#define SVC_I3C_EVENT_IBI BIT(0)
-#define SVC_I3C_EVENT_HOTJOIN BIT(1)
+#define SVC_I3C_EVENT_IBI GENMASK(7, 0)
+#define SVC_I3C_EVENT_HOTJOIN BIT(31)
struct svc_i3c_cmd {
u8 addr;
@@ -214,7 +214,7 @@ struct svc_i3c_master {
spinlock_t lock;
} ibi;
struct mutex lock;
- int enabled_events;
+ u32 enabled_events;
u32 mctrl_config;
};
@@ -388,10 +388,11 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
return 0;
}
-static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master,
+static int svc_i3c_master_ack_ibi(struct svc_i3c_master *master,
bool mandatory_byte)
{
unsigned int ibi_ack_nack;
+ u32 reg;
ibi_ack_nack = SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK;
if (mandatory_byte)
@@ -400,13 +401,43 @@ static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master,
ibi_ack_nack |= SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE;
writel(ibi_ack_nack, master->regs + SVC_I3C_MCTRL);
+
+ return readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg,
+ SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000);
+
}
-static void svc_i3c_master_nack_ibi(struct svc_i3c_master *master)
+static int svc_i3c_master_nack_ibi(struct svc_i3c_master *master)
{
+ int ret;
+ u32 reg;
+
writel(SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK |
SVC_I3C_MCTRL_IBIRESP_NACK,
master->regs + SVC_I3C_MCTRL);
+
+ ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg,
+ SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000);
+ return ret;
+}
+
+static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 mstatus)
+{
+ u32 ibitype;
+ int ret = 0;
+
+ ibitype = SVC_I3C_MSTATUS_IBITYPE(mstatus);
+
+ writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
+
+ /* Hardware can't auto emit NACK for hot join and master request */
+ switch (ibitype) {
+ case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
+ case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
+ ret = svc_i3c_master_nack_ibi(master);
+ }
+
+ return ret;
}
static void svc_i3c_master_ibi_work(struct work_struct *work)
@@ -418,7 +449,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
u32 status, val;
int ret;
- mutex_lock(&master->lock);
+ /*
+ * According to I3C spec ver 1.1, 09-Jun-2021, section 5.1.2.5:
+ *
+ * The I3C Controller shall hold SCL low while the Bus is in ACK/NACK Phase of I3C/I2C
+ * transfer. But maximum stall time is 100us. The IRQs have to be disabled to prevent
+ * schedule during the whole I3C transaction, otherwise, the I3C bus timeout may happen if
+ * any irq or schedule happen during transaction.
+ */
+ guard(spinlock_irqsave)(&master->xferqueue.lock);
+
/*
* IBIWON may be set before SVC_I3C_MCTRL_REQUEST_AUTO_IBI, causing
* readl_relaxed_poll_timeout() to return immediately. Consequently,
@@ -438,8 +478,8 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
master->regs + SVC_I3C_MCTRL);
/* Wait for IBIWON, should take approximately 100us */
- ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val,
- SVC_I3C_MSTATUS_IBIWON(val), 0, 1000);
+ ret = readl_relaxed_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, val,
+ SVC_I3C_MSTATUS_IBIWON(val), 0, 100);
if (ret) {
dev_err(master->dev, "Timeout when polling for IBIWON\n");
svc_i3c_master_emit_stop(master);
@@ -511,7 +551,6 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
reenable_ibis:
svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
- mutex_unlock(&master->lock);
}
static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
@@ -854,6 +893,9 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
int ret, i;
while (true) {
+ /* clean SVC_I3C_MINT_IBIWON w1c bits */
+ writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
+
/* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA.
*
* ENTER DAA:
@@ -905,6 +947,11 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
ret = svc_i3c_master_readb(master, data, 2);
if (ret)
break;
+ } else if (SVC_I3C_MSTATUS_IBIWON(reg)) {
+ ret = svc_i3c_master_handle_ibi_won(master, reg);
+ if (ret)
+ break;
+ continue;
} else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) {
if (SVC_I3C_MSTATUS_STATE_IDLE(reg) &&
SVC_I3C_MSTATUS_COMPLETE(reg)) {
@@ -1056,12 +1103,27 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
if (ret)
goto rpm_out;
- /* Register all devices who participated to the core */
- for (i = 0; i < dev_nb; i++) {
- ret = i3c_master_add_i3c_dev_locked(m, addrs[i]);
- if (ret)
- goto rpm_out;
- }
+ /*
+ * Register all devices who participated to the core
+ *
+ * If two devices (A and B) are detected in DAA and address 0xa is assigned to
+ * device A and 0xb to device B, a failure in i3c_master_add_i3c_dev_locked()
+ * for device A (addr: 0xa) could prevent device B (addr: 0xb) from being
+ * registered on the bus. The I3C stack might still consider 0xb a free
+ * address. If a subsequent Hotjoin occurs, 0xb might be assigned to Device A,
+ * causing both devices A and B to use the same address 0xb, violating the I3C
+ * specification.
+ *
+ * The return value for i3c_master_add_i3c_dev_locked() should not be checked
+ * because subsequent steps will scan the entire I3C bus, independent of
+ * whether i3c_master_add_i3c_dev_locked() returns success.
+ *
+ * If device A registration fails, there is still a chance to register device
+ * B. i3c_master_add_i3c_dev_locked() can reset DAA if a failure occurs while
+ * retrieving device information.
+ */
+ for (i = 0; i < dev_nb; i++)
+ i3c_master_add_i3c_dev_locked(m, addrs[i]);
/* Configure IBI auto-rules */
ret = svc_i3c_update_ibirules(master);
@@ -1163,6 +1225,26 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
if (ret)
goto emit_stop;
+ /*
+ * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a
+ * Frame with I3C Target Address.
+ *
+ * The I3C Controller normally should start a Frame, the Address may be arbitrated,
+ * and so the Controller shall monitor to see whether an In-Band Interrupt request,
+ * a Controller Role Request (i.e., Secondary Controller requests to become the
+ * Active Controller), or a Hot-Join Request has been made.
+ *
+ * If missed IBIWON check, the wrong data will be return. When IBIWON happen, issue
+ * repeat start. Address arbitrate only happen at START, never happen at REPEAT
+ * start.
+ */
+ if (SVC_I3C_MSTATUS_IBIWON(reg)) {
+ ret = svc_i3c_master_handle_ibi_won(master, reg);
+ if (ret)
+ goto emit_stop;
+ continue;
+ }
+
if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) {
/*
* According to I3C Spec 1.1.1, 11-Jun-2021, section: 5.1.2.2.3.
@@ -1196,24 +1278,6 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
}
}
- /*
- * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a Frame
- * with I3C Target Address.
- *
- * The I3C Controller normally should start a Frame, the Address may be arbitrated, and so
- * the Controller shall monitor to see whether an In-Band Interrupt request, a Controller
- * Role Request (i.e., Secondary Controller requests to become the Active Controller), or
- * a Hot-Join Request has been made.
- *
- * If missed IBIWON check, the wrong data will be return. When IBIWON happen, return failure
- * and yield the above events handler.
- */
- if (SVC_I3C_MSTATUS_IBIWON(reg)) {
- ret = -EAGAIN;
- *actual_len = 0;
- goto emit_stop;
- }
-
if (rnw)
ret = svc_i3c_master_read(master, in, xfer_len);
else
@@ -1624,7 +1688,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
return ret;
}
- master->enabled_events |= SVC_I3C_EVENT_IBI;
+ master->enabled_events++;
svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
return i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
@@ -1636,7 +1700,7 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
struct svc_i3c_master *master = to_svc_i3c_master(m);
int ret;
- master->enabled_events &= ~SVC_I3C_EVENT_IBI;
+ master->enabled_events--;
if (!master->enabled_events)
svc_i3c_master_disable_interrupts(master);
@@ -1827,8 +1891,8 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
rpm_disable:
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
- pm_runtime_set_suspended(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
err_disable_clks:
svc_i3c_master_unprepare_clks(master);
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 67aebfe0fed6..ac4d8faa3886 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1069,6 +1069,47 @@ static struct cpuidle_state gnr_cstates[] __initdata = {
.enter = NULL }
};
+static struct cpuidle_state gnrd_cstates[] __initdata = {
+ {
+ .name = "C1",
+ .desc = "MWAIT 0x00",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 1,
+ .target_residency = 1,
+ .enter = &intel_idle,
+ .enter_s2idle = intel_idle_s2idle, },
+ {
+ .name = "C1E",
+ .desc = "MWAIT 0x01",
+ .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
+ .exit_latency = 4,
+ .target_residency = 4,
+ .enter = &intel_idle,
+ .enter_s2idle = intel_idle_s2idle, },
+ {
+ .name = "C6",
+ .desc = "MWAIT 0x20",
+ .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED |
+ CPUIDLE_FLAG_INIT_XSTATE |
+ CPUIDLE_FLAG_PARTIAL_HINT_MATCH,
+ .exit_latency = 220,
+ .target_residency = 650,
+ .enter = &intel_idle,
+ .enter_s2idle = intel_idle_s2idle, },
+ {
+ .name = "C6P",
+ .desc = "MWAIT 0x21",
+ .flags = MWAIT2flg(0x21) | CPUIDLE_FLAG_TLB_FLUSHED |
+ CPUIDLE_FLAG_INIT_XSTATE |
+ CPUIDLE_FLAG_PARTIAL_HINT_MATCH,
+ .exit_latency = 240,
+ .target_residency = 750,
+ .enter = &intel_idle,
+ .enter_s2idle = intel_idle_s2idle, },
+ {
+ .enter = NULL }
+};
+
static struct cpuidle_state atom_cstates[] __initdata = {
{
.name = "C1E",
@@ -1508,6 +1549,12 @@ static const struct idle_cpu idle_cpu_gnr __initconst = {
.use_acpi = true,
};
+static const struct idle_cpu idle_cpu_gnrd __initconst = {
+ .state_table = gnrd_cstates,
+ .disable_promotion_to_c1e = true,
+ .use_acpi = true,
+};
+
static const struct idle_cpu idle_cpu_avn __initconst = {
.state_table = avn_cstates,
.disable_promotion_to_c1e = true,
@@ -1593,6 +1640,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, &idle_cpu_spr),
X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, &idle_cpu_spr),
X86_MATCH_VFM(INTEL_GRANITERAPIDS_X, &idle_cpu_gnr),
+ X86_MATCH_VFM(INTEL_GRANITERAPIDS_D, &idle_cpu_gnrd),
X86_MATCH_VFM(INTEL_XEON_PHI_KNL, &idle_cpu_knl),
X86_MATCH_VFM(INTEL_XEON_PHI_KNM, &idle_cpu_knl),
X86_MATCH_VFM(INTEL_ATOM_GOLDMONT, &idle_cpu_bxt),
diff --git a/drivers/iio/accel/adxl355_core.c b/drivers/iio/accel/adxl355_core.c
index eabaefa92f19..7ccd2f653b9b 100644
--- a/drivers/iio/accel/adxl355_core.c
+++ b/drivers/iio/accel/adxl355_core.c
@@ -643,7 +643,7 @@ static irqreturn_t adxl355_trigger_handler(int irq, void *p)
* The acceleration data is 24 bits and big endian. It has to be saved
* in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer.
* The buf array is 14 bytes as it includes 3x4=12 bytes for
- * accelaration data of x, y, and z axis. It also includes 2 bytes for
+ * acceleration data of x, y, and z axis. It also includes 2 bytes for
* temperature data.
*/
ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG,
diff --git a/drivers/iio/accel/adxl367.c b/drivers/iio/accel/adxl367.c
index e790a66d86c7..705375f3b56e 100644
--- a/drivers/iio/accel/adxl367.c
+++ b/drivers/iio/accel/adxl367.c
@@ -1073,7 +1073,7 @@ static int adxl367_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
enum adxl367_activity_type act;
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index ef8dd557877b..5b9eb364760a 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -940,7 +940,7 @@ static int adxl372_read_event_config(struct iio_dev *indio_dev, const struct iio
static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,
enum iio_event_type type, enum iio_event_direction dir,
- int state)
+ bool state)
{
struct adxl372_state *st = iio_priv(indio_dev);
diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c
index f80527d899be..a1460120d9da 100644
--- a/drivers/iio/accel/adxl380.c
+++ b/drivers/iio/accel/adxl380.c
@@ -1181,7 +1181,7 @@ static int adxl380_read_raw(struct iio_dev *indio_dev,
ret = adxl380_read_chn(st, chan->address);
iio_device_release_direct_mode(indio_dev);
- if (ret)
+ if (ret < 0)
return ret;
*val = sign_extend32(ret >> chan->scan_type.shift,
@@ -1386,7 +1386,7 @@ static int adxl380_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct adxl380_state *st = iio_priv(indio_dev);
enum adxl380_axis axis;
@@ -1719,7 +1719,6 @@ static int adxl380_config_irq(struct iio_dev *indio_dev)
{
struct adxl380_state *st = iio_priv(indio_dev);
unsigned long irq_flag;
- struct irq_data *desc;
u32 irq_type;
u8 polarity;
int ret;
@@ -1737,11 +1736,7 @@ static int adxl380_config_irq(struct iio_dev *indio_dev)
st->int_map[1] = ADXL380_INT1_MAP1_REG;
}
- desc = irq_get_irq_data(st->irq);
- if (!desc)
- return dev_err_probe(st->dev, -EINVAL, "Could not find IRQ %d\n", st->irq);
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(st->irq);
if (irq_type == IRQ_TYPE_LEVEL_HIGH) {
polarity = 0;
irq_flag = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index 2445a0f7bc2b..128db14ba726 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -21,6 +21,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/types.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
@@ -144,7 +145,7 @@ struct bma180_data {
/* Ensure timestamp is naturally aligned */
struct {
s16 chan[4];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
};
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c
index fcbd695e4654..009e6243c6cb 100644
--- a/drivers/iio/accel/bma220_spi.c
+++ b/drivers/iio/accel/bma220_spi.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/types.h>
#include <linux/spi/spi.h>
#include <linux/iio/buffer.h>
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index e4fe36768216..906d2577be2d 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -115,7 +115,7 @@ struct bma400_data {
struct {
__le16 buff[3];
u8 temperature;
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buffer __aligned(IIO_DMA_MINALIGN);
__le16 status;
__be16 duration;
@@ -1293,7 +1293,7 @@ static int bma400_disable_adv_interrupt(struct bma400_data *data)
static int bma400_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bma400_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 0f32c1e92b4d..158579350d59 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -804,7 +804,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
index 7775c5edaeef..7a7baf52e595 100644
--- a/drivers/iio/accel/bmc150-accel.h
+++ b/drivers/iio/accel/bmc150-accel.h
@@ -6,6 +6,7 @@
#include <linux/iio/iio.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
#include <linux/workqueue.h>
struct regmap;
@@ -69,7 +70,7 @@ struct bmc150_accel_data {
*/
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
u8 bw_bits;
u32 slope_dur;
diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c
index acadabec4df7..f07fba17048e 100644
--- a/drivers/iio/accel/fxls8962af-core.c
+++ b/drivers/iio/accel/fxls8962af-core.c
@@ -22,6 +22,7 @@
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
@@ -163,7 +164,7 @@ struct fxls8962af_data {
const struct fxls8962af_chip_info *chip_info;
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
struct iio_mount_matrix orientation;
@@ -616,7 +617,7 @@ static int
fxls8962af_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct fxls8962af_data *data = iio_priv(indio_dev);
u8 enable_event, enable_bits;
@@ -1103,8 +1104,7 @@ static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq)
if (ret)
return ret;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(irq));
-
+ irq_type = irq_get_trigger_type(irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 9b7a73a4c48a..26b1033799fe 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -28,7 +28,7 @@ struct accel_3d_state {
/* Ensure timestamp is naturally aligned */
struct {
u32 accel_val[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -328,6 +328,7 @@ static int accel_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_accel_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
const char *name;
struct iio_dev *indio_dev;
@@ -335,8 +336,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
const struct iio_chan_spec *channel_spec;
int channel_size;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
-
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct accel_3d_state));
if (indio_dev == NULL)
@@ -424,7 +423,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_accel_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct accel_3d_state *accel_state = iio_priv(indio_dev);
@@ -452,7 +451,7 @@ static struct platform_driver hid_accel_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_accel_3d_probe,
- .remove_new = hid_accel_3d_remove,
+ .remove = hid_accel_3d_remove,
};
module_platform_driver(hid_accel_3d_platform_driver);
diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c
index 53d59a04ae15..53261e1d5d1f 100644
--- a/drivers/iio/accel/kionix-kx022a.c
+++ b/drivers/iio/accel/kionix-kx022a.c
@@ -16,6 +16,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
+#include <linux/types.h>
#include <linux/units.h>
#include <linux/iio/iio.h>
@@ -292,7 +293,7 @@ struct kx022a_data {
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
};
@@ -594,7 +595,7 @@ static int kx022a_get_axis(struct kx022a_data *data,
if (ret)
return ret;
- *val = le16_to_cpu(data->buffer[0]);
+ *val = (s16)le16_to_cpu(data->buffer[0]);
return IIO_VAL_INT;
}
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index b76df8816323..f2496cad8ec2 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -4,13 +4,15 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/bitops.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@@ -168,14 +170,73 @@
#define KXCJK1013_DEFAULT_WAKE_THRES 1
-enum kx_chipset {
- KXCJK1013,
- KXCJ91008,
- KXTJ21009,
- KXTF9,
- KX0221020,
- KX0231025,
- KX_MAX_CHIPS /* this must be last */
+/* Refer to section 4 of the specification */
+struct kx_odr_start_up_time {
+ int odr_bits;
+ int usec;
+};
+
+/* KXCJK-1013 */
+static const struct kx_odr_start_up_time kxcjk1013_odr_start_up_times[] = {
+ { 0x08, 100000 },
+ { 0x09, 100000 },
+ { 0x0A, 100000 },
+ { 0x0B, 100000 },
+ { 0x00, 80000 },
+ { 0x01, 41000 },
+ { 0x02, 21000 },
+ { 0x03, 11000 },
+ { 0x04, 6400 },
+ { 0x05, 3900 },
+ { 0x06, 2700 },
+ { 0x07, 2100 },
+ { }
+};
+
+/* KXCTJ2-1009 */
+static const struct kx_odr_start_up_time kxtj21009_odr_start_up_times[] = {
+ { 0x08, 1240000 },
+ { 0x09, 621000 },
+ { 0x0A, 309000 },
+ { 0x0B, 151000 },
+ { 0x00, 80000 },
+ { 0x01, 41000 },
+ { 0x02, 21000 },
+ { 0x03, 11000 },
+ { 0x04, 6000 },
+ { 0x05, 4000 },
+ { 0x06, 3000 },
+ { 0x07, 2000 },
+ { }
+};
+
+/* KXTF9 */
+static const struct kx_odr_start_up_time kxtf9_odr_start_up_times[] = {
+ { 0x01, 81000 },
+ { 0x02, 41000 },
+ { 0x03, 21000 },
+ { 0x04, 11000 },
+ { 0x05, 5100 },
+ { 0x06, 2700 },
+ { }
+};
+
+/* KX023-1025 */
+static const struct kx_odr_start_up_time kx0231025_odr_start_up_times[] = {
+ /* First 4 are not in datasheet, taken from KXCTJ2-1009 */
+ { 0x08, 1240000 },
+ { 0x09, 621000 },
+ { 0x0A, 309000 },
+ { 0x0B, 151000 },
+ { 0x00, 81000 },
+ { 0x01, 40000 },
+ { 0x02, 22000 },
+ { 0x03, 12000 },
+ { 0x04, 7000 },
+ { 0x05, 4400 },
+ { 0x06, 3000 },
+ { 0x07, 3000 },
+ { }
};
enum kx_acpi_type {
@@ -234,6 +295,55 @@ static const struct kx_chipset_regs kx0231025_regs = {
.wake_thres = KX023_REG_ATH,
};
+struct kx_chipset_info {
+ const struct kx_chipset_regs *regs;
+ const struct kx_odr_start_up_time *times;
+ enum kx_acpi_type acpi_type;
+};
+
+static const struct kx_chipset_info kxcjk1013_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxcj91008_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxcj91008_kiox010a_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_KIOX010A,
+};
+
+static const struct kx_chipset_info kxcj91008_kiox020a_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_GENERIC,
+};
+
+static const struct kx_chipset_info kxcj91008_smo8500_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_SMO8500,
+};
+
+static const struct kx_chipset_info kxtj21009_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxtj21009_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxtf9_info = {
+ .regs = &kxtf9_regs,
+ .times = pm_ptr(kxtf9_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kx0231025_info = {
+ .regs = &kx0231025_regs,
+ .times = pm_ptr(kx0231025_odr_start_up_times),
+};
+
enum kxcjk1013_axis {
AXIS_X,
AXIS_Y,
@@ -250,7 +360,7 @@ struct kxcjk1013_data {
/* Ensure timestamp naturally aligned */
struct {
s16 chans[AXIS_MAX];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
u8 odr_bits;
u8 range;
@@ -261,9 +371,7 @@ struct kxcjk1013_data {
int ev_enable_state;
bool motion_trigger_on;
int64_t timestamp;
- enum kx_chipset chipset;
- enum kx_acpi_type acpi_type;
- const struct kx_chipset_regs *regs;
+ const struct kx_chipset_info *info;
};
enum kxcjk1013_mode {
@@ -314,83 +422,6 @@ static const struct kx_odr_map kxtf9_samp_freq_table[] = {
static const char *const kxtf9_samp_freq_avail =
"25 50 100 200 400 800";
-/* Refer to section 4 of the specification */
-static __maybe_unused const struct {
- int odr_bits;
- int usec;
-} odr_start_up_times[KX_MAX_CHIPS][12] = {
- /* KXCJK-1013 */
- {
- {0x08, 100000},
- {0x09, 100000},
- {0x0A, 100000},
- {0x0B, 100000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6400},
- {0x05, 3900},
- {0x06, 2700},
- {0x07, 2100},
- },
- /* KXCJ9-1008 */
- {
- {0x08, 100000},
- {0x09, 100000},
- {0x0A, 100000},
- {0x0B, 100000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6400},
- {0x05, 3900},
- {0x06, 2700},
- {0x07, 2100},
- },
- /* KXCTJ2-1009 */
- {
- {0x08, 1240000},
- {0x09, 621000},
- {0x0A, 309000},
- {0x0B, 151000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6000},
- {0x05, 4000},
- {0x06, 3000},
- {0x07, 2000},
- },
- /* KXTF9 */
- {
- {0x01, 81000},
- {0x02, 41000},
- {0x03, 21000},
- {0x04, 11000},
- {0x05, 5100},
- {0x06, 2700},
- },
- /* KX023-1025 */
- {
- /* First 4 are not in datasheet, taken from KXCTJ2-1009 */
- {0x08, 1240000},
- {0x09, 621000},
- {0x0A, 309000},
- {0x0B, 151000},
- {0, 81000},
- {0x01, 40000},
- {0x02, 22000},
- {0x03, 12000},
- {0x04, 7000},
- {0x05, 4400},
- {0x06, 3000},
- {0x07, 3000},
- },
-};
-
static const struct {
u16 scale;
u8 gsel_0;
@@ -424,30 +455,15 @@ static int kiox010a_dsm(struct device *dev, int fn_index)
return 0;
}
-static const struct acpi_device_id kx_acpi_match[] = {
- {"KXCJ1013", KXCJK1013},
- {"KXCJ1008", KXCJ91008},
- {"KXCJ9000", KXCJ91008},
- {"KIOX0008", KXCJ91008},
- {"KIOX0009", KXTJ21009},
- {"KIOX000A", KXCJ91008},
- {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */
- {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */
- {"KXTJ1009", KXTJ21009},
- {"KXJ2109", KXTJ21009},
- {"SMO8500", KXCJ91008},
- { }
-};
-MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
-
#endif
static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode mode)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -458,7 +474,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
else
ret |= KXCJK1013_REG_CTRL1_BIT_PC1;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -470,9 +486,10 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
static int kxcjk1013_get_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode *mode)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -488,9 +505,10 @@ static int kxcjk1013_get_mode(struct kxcjk1013_data *data,
static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -501,7 +519,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3);
ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4);
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -514,10 +532,11 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
#ifdef CONFIG_ACPI
- if (data->acpi_type == ACPI_KIOX010A) {
+ if (data->info->acpi_type == ACPI_KIOX010A) {
/* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE);
}
@@ -535,7 +554,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -544,7 +563,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
/* Set 12 bit mode */
ret |= KXCJK1013_REG_CTRL1_BIT_RES;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl\n");
return ret;
@@ -555,7 +574,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->data_ctrl);
+ ret = i2c_smbus_read_byte_data(data->client, regs->data_ctrl);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
return ret;
@@ -564,7 +583,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
data->odr_bits = ret;
/* Set up INT polarity */
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -575,14 +594,14 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- /* On KX023 and KX022, route all used interrupts to INT1 for now */
- if ((data->chipset == KX0231025 || data->chipset == KX0221020) && data->client->irq > 0) {
+ /* On KX023, route all used interrupts to INT1 for now */
+ if (data->info == &kx0231025_info && data->client->irq > 0) {
ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4,
KX023_REG_INC4_DRDY1 |
KX023_REG_INC4_WUFI1);
@@ -601,20 +620,17 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
return 0;
}
-#ifdef CONFIG_PM
static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
{
- int i;
- int idx = data->chipset;
+ const struct kx_odr_start_up_time *times;
- for (i = 0; i < ARRAY_SIZE(odr_start_up_times[idx]); ++i) {
- if (odr_start_up_times[idx][i].odr_bits == data->odr_bits)
- return odr_start_up_times[idx][i].usec;
+ for (times = data->info->times; times->usec; times++) {
+ if (times->odr_bits == data->odr_bits)
+ return times->usec;
}
return KXCJK1013_MAX_STARTUP_TIME_US;
}
-#endif
static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
{
@@ -639,18 +655,17 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_timer,
- data->wake_dur);
+ ret = i2c_smbus_write_byte_data(data->client, regs->wake_timer, data->wake_dur);
if (ret < 0) {
dev_err(&data->client->dev,
"Error writing reg_wake_timer\n");
return ret;
}
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_thres,
- data->wake_thres);
+ ret = i2c_smbus_write_byte_data(data->client, regs->wake_thres, data->wake_thres);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_wake_thres\n");
return ret;
@@ -662,6 +677,7 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
bool status)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
@@ -678,7 +694,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -689,13 +705,13 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -706,7 +722,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -724,6 +740,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
bool status)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
@@ -736,7 +753,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -747,13 +764,13 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -764,7 +781,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -811,6 +828,7 @@ static int kxcjk1013_convert_odr_value(const struct kx_odr_map *map,
static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
const struct kx_odr_map *odr_setting;
@@ -819,7 +837,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
if (ret < 0)
return ret;
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
odr_setting = kxcjk1013_find_odr_value(kxtf9_samp_freq_table,
ARRAY_SIZE(kxtf9_samp_freq_table),
val, val2);
@@ -836,7 +854,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
if (ret < 0)
return ret;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->data_ctrl,
+ ret = i2c_smbus_write_byte_data(data->client, regs->data_ctrl,
odr_setting->odr_bits);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing data_ctrl\n");
@@ -845,7 +863,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
data->odr_bits = odr_setting->odr_bits;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wuf_ctrl,
+ ret = i2c_smbus_write_byte_data(data->client, regs->wuf_ctrl,
odr_setting->wuf_bits);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
@@ -863,7 +881,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2)
{
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
return kxcjk1013_convert_odr_value(kxtf9_samp_freq_table,
ARRAY_SIZE(kxtf9_samp_freq_table),
data->odr_bits, val, val2);
@@ -1063,7 +1081,7 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
@@ -1130,7 +1148,7 @@ static ssize_t kxcjk1013_get_samp_freq_avail(struct device *dev,
struct kxcjk1013_data *data = iio_priv(indio_dev);
const char *str;
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
str = kxtf9_samp_freq_avail;
else
str = kxcjk1013_samp_freq_avail;
@@ -1207,7 +1225,7 @@ static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = {
.postdisable = kxcjk1013_buffer_postdisable,
};
-static const struct iio_info kxcjk1013_info = {
+static const struct iio_info kxcjk1013_iio_info = {
.attrs = &kxcjk1013_attrs_group,
.read_raw = kxcjk1013_read_raw,
.write_raw = kxcjk1013_write_raw,
@@ -1247,9 +1265,10 @@ static void kxcjk1013_trig_reen(struct iio_trigger *trig)
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_rel);
if (ret < 0)
dev_err(&data->client->dev, "Error reading reg_int_rel\n");
}
@@ -1301,8 +1320,9 @@ static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev)
{
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
- int ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src2);
+ int ret = i2c_smbus_read_byte_data(data->client, regs->int_src2);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_src2\n");
return;
@@ -1367,16 +1387,17 @@ static irqreturn_t kxcjk1013_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_src1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_src1\n");
goto ack_intr;
}
if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) {
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
@@ -1392,7 +1413,7 @@ ack_intr:
if (data->dready_trigger_on)
return IRQ_HANDLED;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_rel);
if (ret < 0)
dev_err(&data->client->dev, "Error reading reg_int_rel\n");
@@ -1417,31 +1438,6 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
return IRQ_HANDLED;
}
-static const char *kxcjk1013_match_acpi_device(struct device *dev,
- enum kx_chipset *chipset,
- enum kx_acpi_type *acpi_type,
- const char **label)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- if (strcmp(id->id, "SMO8500") == 0) {
- *acpi_type = ACPI_SMO8500;
- } else if (strcmp(id->id, "KIOX010A") == 0) {
- *acpi_type = ACPI_KIOX010A;
- *label = "accel-display";
- } else if (strcmp(id->id, "KIOX020A") == 0) {
- *label = "accel-base";
- }
-
- *chipset = (enum kx_chipset)id->driver_data;
-
- return dev_name(dev);
-}
-
static int kxcjk1013_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1449,6 +1445,7 @@ static int kxcjk1013_probe(struct i2c_client *client)
struct kxcjk1013_data *data;
struct iio_dev *indio_dev;
struct kxcjk_1013_platform_data *pdata;
+ const void *ddata = NULL;
const char *name;
int ret;
@@ -1489,32 +1486,18 @@ static int kxcjk1013_probe(struct i2c_client *client)
msleep(20);
if (id) {
- data->chipset = (enum kx_chipset)(id->driver_data);
name = id->name;
- } else if (ACPI_HANDLE(&client->dev)) {
- name = kxcjk1013_match_acpi_device(&client->dev,
- &data->chipset,
- &data->acpi_type,
- &indio_dev->label);
- } else
- return -ENODEV;
-
- switch (data->chipset) {
- case KXCJK1013:
- case KXCJ91008:
- case KXTJ21009:
- data->regs = &kxcjk1013_regs;
- break;
- case KXTF9:
- data->regs = &kxtf9_regs;
- break;
- case KX0221020:
- case KX0231025:
- data->regs = &kx0231025_regs;
- break;
- default:
- return -EINVAL;
+ data->info = (const struct kx_chipset_info *)(id->driver_data);
+ } else {
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ data->info = ddata;
+ if (data->info == &kxcj91008_kiox010a_info)
+ indio_dev->label = "accel-display";
+ else if (data->info == &kxcj91008_kiox020a_info)
+ indio_dev->label = "accel-base";
}
+ if (!name)
+ return -ENODEV;
ret = kxcjk1013_chip_init(data);
if (ret < 0)
@@ -1527,9 +1510,9 @@ static int kxcjk1013_probe(struct i2c_client *client)
indio_dev->available_scan_masks = kxcjk1013_scan_masks;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->info = &kxcjk1013_info;
+ indio_dev->info = &kxcjk1013_iio_info;
- if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) {
+ if (client->irq > 0 && data->info->acpi_type != ACPI_SMO8500) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kxcjk1013_data_rdy_trig_poll,
kxcjk1013_event_handler,
@@ -1637,7 +1620,6 @@ static void kxcjk1013_remove(struct i2c_client *client)
mutex_unlock(&data->mutex);
}
-#ifdef CONFIG_PM_SLEEP
static int kxcjk1013_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1665,9 +1647,7 @@ static int kxcjk1013_resume(struct device *dev)
return ret;
}
-#endif
-#ifdef CONFIG_PM
static int kxcjk1013_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1701,44 +1681,56 @@ static int kxcjk1013_runtime_resume(struct device *dev)
return 0;
}
-#endif
static const struct dev_pm_ops kxcjk1013_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume)
- SET_RUNTIME_PM_OPS(kxcjk1013_runtime_suspend,
- kxcjk1013_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume)
+ RUNTIME_PM_OPS(kxcjk1013_runtime_suspend, kxcjk1013_runtime_resume, NULL)
};
static const struct i2c_device_id kxcjk1013_id[] = {
- {"kxcjk1013", KXCJK1013},
- {"kxcj91008", KXCJ91008},
- {"kxtj21009", KXTJ21009},
- {"kxtf9", KXTF9},
- {"kx022-1020", KX0221020},
- {"kx023-1025", KX0231025},
- {"SMO8500", KXCJ91008},
- {}
+ { "kxcjk1013", (kernel_ulong_t)&kxcjk1013_info },
+ { "kxcj91008", (kernel_ulong_t)&kxcj91008_info },
+ { "kxtj21009", (kernel_ulong_t)&kxtj21009_info },
+ { "kxtf9", (kernel_ulong_t)&kxtf9_info },
+ { "kx023-1025", (kernel_ulong_t)&kx0231025_info },
+ { }
};
-
MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
static const struct of_device_id kxcjk1013_of_match[] = {
- { .compatible = "kionix,kxcjk1013", },
- { .compatible = "kionix,kxcj91008", },
- { .compatible = "kionix,kxtj21009", },
- { .compatible = "kionix,kxtf9", },
- { .compatible = "kionix,kx022-1020", },
- { .compatible = "kionix,kx023-1025", },
+ { .compatible = "kionix,kxcjk1013", &kxcjk1013_info },
+ { .compatible = "kionix,kxcj91008", &kxcj91008_info },
+ { .compatible = "kionix,kxtj21009", &kxtj21009_info },
+ { .compatible = "kionix,kxtf9", &kxtf9_info },
+ { .compatible = "kionix,kx023-1025", &kx0231025_info },
{ }
};
MODULE_DEVICE_TABLE(of, kxcjk1013_of_match);
+static const struct acpi_device_id kx_acpi_match[] = {
+ { "KIOX0008", (kernel_ulong_t)&kxcj91008_info },
+ { "KIOX0009", (kernel_ulong_t)&kxtj21009_info },
+ { "KIOX000A", (kernel_ulong_t)&kxcj91008_info },
+ /* KXCJ91008 in the display of a yoga 2-in-1 */
+ { "KIOX010A", (kernel_ulong_t)&kxcj91008_kiox010a_info },
+ /* KXCJ91008 in the base of a yoga 2-in-1 */
+ { "KIOX020A", (kernel_ulong_t)&kxcj91008_kiox020a_info },
+ { "KXCJ1008", (kernel_ulong_t)&kxcj91008_info },
+ { "KXCJ1013", (kernel_ulong_t)&kxcjk1013_info },
+ { "KXCJ9000", (kernel_ulong_t)&kxcj91008_info },
+ { "KXJ2109", (kernel_ulong_t)&kxtj21009_info },
+ { "KXTJ1009", (kernel_ulong_t)&kxtj21009_info },
+ { "SMO8500", (kernel_ulong_t)&kxcj91008_smo8500_info },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
+
static struct i2c_driver kxcjk1013_driver = {
.driver = {
.name = KXCJK1013_DRV_NAME,
- .acpi_match_table = ACPI_PTR(kx_acpi_match),
+ .acpi_match_table = kx_acpi_match,
.of_match_table = kxcjk1013_of_match,
- .pm = &kxcjk1013_pm_ops,
+ .pm = pm_ptr(&kxcjk1013_pm_ops),
},
.probe = kxcjk1013_probe,
.remove = kxcjk1013_remove,
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 70dfd6e354db..6d2b0a22e550 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
+#include <linux/types.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/bitops.h>
@@ -215,7 +216,7 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
*/
struct {
__be16 chan[4];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} hw_values;
int ret;
diff --git a/drivers/iio/accel/mma7455_core.c b/drivers/iio/accel/mma7455_core.c
index a34195b3215d..50f7ac1845c6 100644
--- a/drivers/iio/accel/mma7455_core.c
+++ b/drivers/iio/accel/mma7455_core.c
@@ -19,6 +19,7 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include "mma7455.h"
@@ -58,7 +59,7 @@ struct mma7455_data {
*/
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
};
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index 62e6369e2269..962d289065ab 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
#define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
@@ -115,7 +116,7 @@ struct mma8452_data {
/* Ensure correct alignment of time stamp when present */
struct {
__be16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buffer;
};
@@ -973,7 +974,7 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mma8452_data *data = iio_priv(indio_dev);
int val, ret;
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index fa1799b0b0df..6d73eec95126 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -4,11 +4,11 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
@@ -45,7 +45,7 @@ enum mma9551_tilt_axis {
struct mma9551_data {
struct i2c_client *client;
struct mutex mutex;
- int event_enabled[3];
+ bool event_enabled[3];
int irqs[MMA9551_GPIO_COUNT];
};
@@ -162,7 +162,7 @@ static int mma9551_read_event_config(struct iio_dev *indio_dev,
static int mma9551_config_incli_event(struct iio_dev *indio_dev,
enum iio_modifier axis,
- int state)
+ bool state)
{
struct mma9551_data *data = iio_priv(indio_dev);
enum mma9551_tilt_axis mma_axis;
@@ -174,7 +174,7 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev,
if (data->event_enabled[mma_axis] == state)
return 0;
- if (state == 0) {
+ if (!state) {
ret = mma9551_gpio_config(data->client,
(enum mma9551_gpio_pin)mma_axis,
MMA9551_APPID_NONE, 0, 0);
@@ -225,7 +225,7 @@ static int mma9551_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
@@ -435,17 +435,6 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev)
return 0;
}
-static const char *mma9551_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
static int mma9551_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -464,8 +453,8 @@ static int mma9551_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = mma9551_match_acpi_device(&client->dev);
+ else
+ name = iio_get_acpi_device_name(&client->dev);
ret = mma9551_init(data);
if (ret < 0)
diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c
index 86543f34ef17..8536743a6886 100644
--- a/drivers/iio/accel/mma9553.c
+++ b/drivers/iio/accel/mma9553.c
@@ -4,11 +4,11 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -725,7 +725,8 @@ static int mma9553_read_event_config(struct iio_dev *indio_dev,
static int mma9553_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct mma9553_data *data = iio_priv(indio_dev);
struct mma9553_event *event;
@@ -1030,9 +1031,9 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) {
data->stepcnt = stepcnt;
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_DIR_NONE,
- IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0,
+ IIO_EV_TYPE_CHANGE,
+ IIO_EV_DIR_NONE),
data->timestamp);
}
@@ -1041,20 +1042,18 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
/* ev_activity can be NULL if activity == ACTIVITY_UNKNOWN */
if (ev_prev_activity && ev_prev_activity->enabled)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_prev_activity->info->mod,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH, 0, 0,
- 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ ev_prev_activity->info->mod,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
data->timestamp);
if (ev_activity && ev_activity->enabled)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_activity->info->mod,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH, 0, 0,
- 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ ev_activity->info->mod,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
data->timestamp);
}
mutex_unlock(&data->mutex);
@@ -1062,17 +1061,6 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
-static const char *mma9553_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
static int mma9553_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1091,9 +1079,9 @@ static int mma9553_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = mma9553_match_acpi_device(&client->dev);
else
+ name = iio_get_acpi_device_name(&client->dev);
+ if (!name)
return -ENOSYS;
mutex_init(&data->mutex);
diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c
index 57025354c7cd..e7fb860f3233 100644
--- a/drivers/iio/accel/msa311.c
+++ b/drivers/iio/accel/msa311.c
@@ -34,6 +34,7 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/string_choices.h>
+#include <linux/types.h>
#include <linux/units.h>
#include <linux/iio/buffer.h>
@@ -893,7 +894,7 @@ static irqreturn_t msa311_buffer_thread(int irq, void *p)
__le16 axis;
struct {
__le16 channels[MSA311_SI_Z + 1];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buf;
memset(&buf, 0, sizeof(buf));
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
index fc54a2a4693c..cb5c4e354fc0 100644
--- a/drivers/iio/accel/mxc4005.c
+++ b/drivers/iio/accel/mxc4005.c
@@ -11,6 +11,7 @@
#include <linux/iio/iio.h>
#include <linux/mod_devicetable.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>
@@ -69,7 +70,7 @@ struct mxc4005_data {
/* Ensure timestamp is naturally aligned */
struct {
__be16 chans[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
bool trigger_enabled;
unsigned int control;
diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
index 87c54e41f6cc..3fb0f386c3db 100644
--- a/drivers/iio/accel/sca3000.c
+++ b/drivers/iio/accel/sca3000.c
@@ -1158,7 +1158,7 @@ error_ret:
return ret;
}
-static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
+static int sca3000_freefall_set_state(struct iio_dev *indio_dev, bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
@@ -1181,7 +1181,7 @@ static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
}
static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis,
- int state)
+ bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret, ctrlval;
@@ -1253,7 +1253,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c
index abead190254b..471c154c3631 100644
--- a/drivers/iio/accel/stk8312.c
+++ b/drivers/iio/accel/stk8312.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -105,7 +106,7 @@ struct stk8312_data {
/* Ensure timestamp is naturally aligned */
struct {
s8 chans[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
};
diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c
index a32a77324e92..cab592a68622 100644
--- a/drivers/iio/accel/stk8ba50.c
+++ b/drivers/iio/accel/stk8ba50.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -94,7 +95,7 @@ struct stk8ba50_data {
/* Ensure timestamp is naturally aligned */
struct {
s16 chans[3];
- s64 timetamp __aligned(8);
+ aligned_s64 timetamp;
} scan;
};
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 6c4e74420fd2..849c90203071 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -226,12 +226,14 @@ config AD7606_IFACE_PARALLEL
tristate "Analog Devices AD7606 ADC driver with parallel interface support"
depends on HAS_IOPORT
select AD7606
+ select IIO_BACKEND
help
Say yes here to build parallel interface support for Analog Devices:
ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
+ It also support iio_backended devices for AD7606B.
To compile this driver as a module, choose M here: the
- module will be called ad7606_parallel.
+ module will be called ad7606_par.
config AD7606_IFACE_SPI
tristate "Analog Devices AD7606 ADC driver with spi interface support"
@@ -244,6 +246,22 @@ config AD7606_IFACE_SPI
To compile this driver as a module, choose M here: the
module will be called ad7606_spi.
+config AD7625
+ tristate "Analog Devices AD7625/AD7626 High Speed ADC driver"
+ depends on PWM
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices:
+ * AD7625 16-Bit, 6 MSPS PulSAR Analog-to-Digital Converter
+ * AD7626 16-Bit, 10 MSPS PulSAR Analog-to-Digital Converter
+ * AD7960 18-Bit, 5 MSPS PulSAR Analog-to-Digital Converter
+ * AD7961 16-Bit, 5 MSPS PulSAR Analog-to-Digital Converter
+
+ The driver requires the assistance of the AXI ADC IP core to operate.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7625.
+
config AD7766
tristate "Analog Devices AD7766/AD7767 ADC driver"
depends on SPI_MASTER
@@ -269,6 +287,18 @@ config AD7768_1
To compile this driver as a module, choose M here: the module will be
called ad7768-1.
+config AD7779
+ tristate "Analog Devices AD7779 ADC driver"
+ depends on SPI
+ select CRC8
+ select IIO_BUFFER
+ help
+ Say yes here to build support for Analog Devices AD777X family
+ (AD7770, AD7771, AD7779) analog to digital converter (ADC).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7779.
+
config AD7780
tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI
@@ -575,6 +605,16 @@ config FSL_MX25_ADC
Generic Conversion Queue driver used for general purpose ADC in the
MX25. This driver supports single measurements using the MX25 ADC.
+config GEHC_PMC_ADC
+ tristate "GE HealthCare PMC ADC driver"
+ depends on I2C
+ help
+ Say yes here to build support for the GE HealthCare PMC 16-bit
+ 16-Channel ADC.
+
+ To compile this driver as a module, choose M here: the module will be
+ called gehc-pmc-adc.
+
config HI8435
tristate "Holt Integrated Circuits HI-8435 threshold detector"
select IIO_TRIGGERED_EVENT
@@ -1580,7 +1620,6 @@ config TWL4030_MADC
config TWL6030_GPADC
tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
depends on TWL4030_CORE
- default n
help
Say yes here if you want support for the TWL6030/TWL6032 General
Purpose A/D Converter. This will add support for battery type
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 7b91cd98c0e0..ee19afba62b7 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -25,8 +25,10 @@ obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
obj-$(CONFIG_AD7606) += ad7606.o
+obj-$(CONFIG_AD7625) += ad7625.o
obj-$(CONFIG_AD7766) += ad7766.o
obj-$(CONFIG_AD7768_1) += ad7768-1.o
+obj-$(CONFIG_AD7779) += ad7779.o
obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
@@ -52,6 +54,7 @@ obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
+obj-$(CONFIG_GEHC_PMC_ADC) += gehc-pmc-adc.o
obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_HX711) += hx711.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index 59f66e9cb0e8..f3b057f92310 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -1194,7 +1194,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
static struct platform_driver ab8500_gpadc_driver = {
.probe = ab8500_gpadc_probe,
- .remove_new = ab8500_gpadc_remove,
+ .remove = ab8500_gpadc_remove,
.driver = {
.name = "ab8500-gpadc",
.pm = pm_ptr(&ab8500_gpadc_pm_ops),
diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c
index 6ea491245084..b3b82535f5c1 100644
--- a/drivers/iio/adc/ad4000.c
+++ b/drivers/iio/adc/ad4000.c
@@ -344,6 +344,8 @@ static int ad4000_single_conversion(struct iio_dev *indio_dev,
if (chan->scan_type.sign == 's')
*val = sign_extend32(sample, chan->scan_type.realbits - 1);
+ else
+ *val = sample;
return IIO_VAL_INT;
}
@@ -637,7 +639,9 @@ static int ad4000_probe(struct spi_device *spi)
indio_dev->name = chip->dev_name;
indio_dev->num_channels = 1;
- devm_mutex_init(dev, &st->lock);
+ ret = devm_mutex_init(dev, &st->lock);
+ if (ret)
+ return ret;
st->gain_milli = 1000;
if (chip->has_hardware_gain) {
diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
index d6876259ad14..eb0a059b4b0e 100644
--- a/drivers/iio/adc/ad7091r-base.c
+++ b/drivers/iio/adc/ad7091r-base.c
@@ -150,7 +150,8 @@ static int ad7091r_read_event_config(struct iio_dev *indio_dev,
static int ad7091r_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct ad7091r_state *st = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h
index 696bf7a897bb..092ddea0f395 100644
--- a/drivers/iio/adc/ad7091r-base.h
+++ b/drivers/iio/adc/ad7091r-base.h
@@ -65,7 +65,7 @@ struct ad7091r_state {
struct regulator *vref;
const struct ad7091r_chip_info *chip_info;
enum ad7091r_mode mode;
- struct mutex lock; /*lock to prevent concurent reads */
+ struct mutex lock; /*lock to prevent concurrent reads */
__be16 tx_buf __aligned(IIO_DMA_MINALIGN);
__be16 rx_buf;
};
diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c
index 0702ec71aa29..a0fca16c3be0 100644
--- a/drivers/iio/adc/ad7173.c
+++ b/drivers/iio/adc/ad7173.c
@@ -3,7 +3,7 @@
* AD717x and AD411x family SPI ADC driver
*
* Supported devices:
- * AD4111/AD4112/AD4114/AD4115/AD4116
+ * AD4111/AD4112/AD4113/AD4114/AD4115/AD4116
* AD7172-2/AD7172-4/AD7173-8/AD7175-2
* AD7175-8/AD7176-2/AD7177-2
*
@@ -76,14 +76,15 @@
(x) == AD7173_AIN_REF_NEG)
#define AD7172_2_ID 0x00d0
-#define AD7175_ID 0x0cd0
#define AD7176_ID 0x0c90
+#define AD7175_ID 0x0cd0
#define AD7175_2_ID 0x0cd0
#define AD7172_4_ID 0x2050
#define AD7173_ID 0x30d0
#define AD4111_ID AD7173_ID
#define AD4112_ID AD7173_ID
#define AD4114_ID AD7173_ID
+#define AD4113_ID 0x31d0
#define AD4116_ID 0x34d0
#define AD4115_ID 0x38d0
#define AD7175_8_ID 0x3cd0
@@ -170,6 +171,7 @@ struct ad7173_device_info {
bool has_temp;
/* ((AVDD1 − AVSS)/5) */
bool has_pow_supply_monitoring;
+ bool data_reg_only_16bit;
bool has_input_buf;
bool has_int_ref;
bool has_ref2;
@@ -294,6 +296,24 @@ static const struct ad7173_device_info ad4112_device_info = {
.num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
};
+static const struct ad7173_device_info ad4113_device_info = {
+ .name = "ad4113",
+ .id = AD4113_ID,
+ .num_voltage_in_div = 8,
+ .num_channels = 16,
+ .num_configs = 8,
+ .num_voltage_in = 8,
+ .num_gpios = 2,
+ .data_reg_only_16bit = true,
+ .higher_gpio_bits = true,
+ .has_vincom_input = true,
+ .has_input_buf = true,
+ .has_int_ref = true,
+ .clock = 2 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7173_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
+};
+
static const struct ad7173_device_info ad4114_device_info = {
.name = "ad4114",
.id = AD4114_ID,
@@ -985,6 +1005,13 @@ static const struct iio_info ad7173_info = {
.update_scan_mode = ad7173_update_scan_mode,
};
+static const struct iio_scan_type ad4113_scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_BE,
+};
+
static const struct iio_chan_spec ad7173_channel_template = {
.type = IIO_VOLTAGE,
.indexed = 1,
@@ -1226,6 +1253,8 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
chan_st_priv->cfg.input_buf = st->info->has_input_buf;
chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF;
st->adc_mode |= AD7173_ADC_MODE_REF_EN;
+ if (st->info->data_reg_only_16bit)
+ chan_arr[chan_index].scan_type = ad4113_scan_type;
chan_index++;
}
@@ -1306,6 +1335,9 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]);
}
+ if (st->info->data_reg_only_16bit)
+ chan_arr[chan_index].scan_type = ad4113_scan_type;
+
chan_index++;
}
return 0;
@@ -1434,6 +1466,7 @@ static int ad7173_probe(struct spi_device *spi)
static const struct of_device_id ad7173_of_match[] = {
{ .compatible = "adi,ad4111", .data = &ad4111_device_info },
{ .compatible = "adi,ad4112", .data = &ad4112_device_info },
+ { .compatible = "adi,ad4113", .data = &ad4113_device_info },
{ .compatible = "adi,ad4114", .data = &ad4114_device_info },
{ .compatible = "adi,ad4115", .data = &ad4115_device_info },
{ .compatible = "adi,ad4116", .data = &ad4116_device_info },
@@ -1451,6 +1484,7 @@ MODULE_DEVICE_TABLE(of, ad7173_of_match);
static const struct spi_device_id ad7173_id_table[] = {
{ "ad4111", (kernel_ulong_t)&ad4111_device_info },
{ "ad4112", (kernel_ulong_t)&ad4112_device_info },
+ { "ad4113", (kernel_ulong_t)&ad4113_device_info },
{ "ad4114", (kernel_ulong_t)&ad4114_device_info },
{ "ad4115", (kernel_ulong_t)&ad4115_device_info },
{ "ad4116", (kernel_ulong_t)&ad4116_device_info },
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 7042ddfdfc03..955e9eff0099 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -1394,6 +1394,9 @@ static int ad7192_probe(struct spi_device *spi)
st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI;
st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = st->chip_info->info;
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 7949b076fb87..858c8be2ff1a 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -383,7 +383,7 @@ static const char * const ad7266_gpio_labels[] = {
static int ad7266_probe(struct spi_device *spi)
{
- struct ad7266_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7266_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad7266_state *st;
unsigned int i;
diff --git a/drivers/iio/adc/ad7280a.c b/drivers/iio/adc/ad7280a.c
index 35aa39fe4bde..f9f32737db80 100644
--- a/drivers/iio/adc/ad7280a.c
+++ b/drivers/iio/adc/ad7280a.c
@@ -822,17 +822,15 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, channels[i]) <=
AD7280A_CELL_VOLTAGE_6_REG) {
if (val >= st->cell_threshhigh) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
+ u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING);
iio_push_event(indio_dev, tmp,
iio_get_time_ns(indio_dev));
} else if (val <= st->cell_threshlow) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
+ u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING);
iio_push_event(indio_dev, tmp,
iio_get_time_ns(indio_dev));
}
diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
index 4c7f887adbbf..60e12faa3207 100644
--- a/drivers/iio/adc/ad7291.c
+++ b/drivers/iio/adc/ad7291.c
@@ -269,7 +269,7 @@ static int ad7291_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
int ret = 0;
struct ad7291_chip_info *chip = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index fb728570debe..4f32cb22f140 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -13,6 +13,8 @@
* ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf
* ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf
* ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf
+ * adaq4370-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4370-4.pdf
+ * adaq4380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4380-4.pdf
*/
#include <linux/align.h>
@@ -22,11 +24,14 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
+#include <linux/units.h>
+#include <linux/util_macros.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
@@ -36,6 +41,8 @@
#define MAX_NUM_CHANNELS 8
/* 2.5V internal reference voltage */
#define AD7380_INTERNAL_REF_MV 2500
+/* 3.3V internal reference voltage for ADAQ */
+#define ADAQ4380_INTERNAL_REF_MV 3300
/* reading and writing registers is more reliable at lower than max speed */
#define AD7380_REG_WR_SPEED_HZ 10000000
@@ -77,6 +84,13 @@
#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */
#define T_POWERUP_US 5000 /* Power up */
+/*
+ * AD738x support several SDO lines to increase throughput, but driver currently
+ * supports only 1 SDO line (standard SPI transaction)
+ */
+#define AD7380_NUM_SDO_LINES 1
+#define AD7380_DEFAULT_GAIN_MILLI 1000
+
struct ad7380_timing_specs {
const unsigned int t_csh_ns; /* CS minimum high time */
};
@@ -86,10 +100,12 @@ struct ad7380_chip_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
unsigned int num_simult_channels;
+ bool has_hardware_gain;
bool has_mux;
const char * const *supplies;
unsigned int num_supplies;
bool external_ref_only;
+ bool adaq_internal_ref_only;
const char * const *vcm_supplies;
unsigned int num_vcm_supplies;
const unsigned long *available_scan_masks;
@@ -181,11 +197,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
},
};
-#define AD7380_CHANNEL(index, bits, diff, sign) { \
+#define _AD7380_CHANNEL(index, bits, diff, sign, gain) { \
.type = IIO_VOLTAGE, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ ((gain) ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \
((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ .info_mask_shared_by_type = ((gain) ? 0 : BIT(IIO_CHAN_INFO_SCALE)) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.info_mask_shared_by_type_available = \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
@@ -199,6 +216,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
.num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \
}
+#define AD7380_CHANNEL(index, bits, diff, sign) \
+ _AD7380_CHANNEL(index, bits, diff, sign, false)
+
+#define ADAQ4380_CHANNEL(index, bits, diff, sign) \
+ _AD7380_CHANNEL(index, bits, diff, sign, true)
+
#define DEFINE_AD7380_2_CHANNEL(name, bits, diff, sign) \
static const struct iio_chan_spec name[] = { \
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -215,6 +238,15 @@ static const struct iio_chan_spec name[] = { \
IIO_CHAN_SOFT_TIMESTAMP(4), \
}
+#define DEFINE_ADAQ4380_4_CHANNEL(name, bits, diff, sign) \
+static const struct iio_chan_spec name[] = { \
+ ADAQ4380_CHANNEL(0, bits, diff, sign), \
+ ADAQ4380_CHANNEL(1, bits, diff, sign), \
+ ADAQ4380_CHANNEL(2, bits, diff, sign), \
+ ADAQ4380_CHANNEL(3, bits, diff, sign), \
+ IIO_CHAN_SOFT_TIMESTAMP(4), \
+}
+
#define DEFINE_AD7380_8_CHANNEL(name, bits, diff, sign) \
static const struct iio_chan_spec name[] = { \
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -233,6 +265,7 @@ DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1, s);
DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1, s);
DEFINE_AD7380_4_CHANNEL(ad7380_4_channels, 16, 1, s);
DEFINE_AD7380_4_CHANNEL(ad7381_4_channels, 14, 1, s);
+DEFINE_ADAQ4380_4_CHANNEL(adaq4380_4_channels, 16, 1, s);
/* pseudo differential */
DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0, s);
DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0, s);
@@ -251,6 +284,10 @@ static const char * const ad7380_supplies[] = {
"vcc", "vlogic",
};
+static const char * const adaq4380_supplies[] = {
+ "ldo", "vcc", "vlogic", "vs-p", "vs-n", "refin",
+};
+
static const char * const ad7380_2_channel_vcm_supplies[] = {
"aina", "ainb",
};
@@ -341,6 +378,11 @@ static const int ad7380_oversampling_ratios[] = {
1, 2, 4, 8, 16, 32,
};
+/* Gains stored as fractions of 1000 so they can be expressed by integers. */
+static const int ad7380_gains[] = {
+ 300, 600, 1000, 1600,
+};
+
static const struct ad7380_chip_info ad7380_chip_info = {
.name = "ad7380",
.channels = ad7380_channels,
@@ -510,6 +552,32 @@ static const struct ad7380_chip_info ad7388_4_chip_info = {
.timing_specs = &ad7380_4_timing,
};
+static const struct ad7380_chip_info adaq4370_4_chip_info = {
+ .name = "adaq4370-4",
+ .channels = adaq4380_4_channels,
+ .num_channels = ARRAY_SIZE(adaq4380_4_channels),
+ .num_simult_channels = 4,
+ .supplies = adaq4380_supplies,
+ .num_supplies = ARRAY_SIZE(adaq4380_supplies),
+ .adaq_internal_ref_only = true,
+ .has_hardware_gain = true,
+ .available_scan_masks = ad7380_4_channel_scan_masks,
+ .timing_specs = &ad7380_4_timing,
+};
+
+static const struct ad7380_chip_info adaq4380_4_chip_info = {
+ .name = "adaq4380-4",
+ .channels = adaq4380_4_channels,
+ .num_channels = ARRAY_SIZE(adaq4380_4_channels),
+ .num_simult_channels = 4,
+ .supplies = adaq4380_supplies,
+ .num_supplies = ARRAY_SIZE(adaq4380_supplies),
+ .adaq_internal_ref_only = true,
+ .has_hardware_gain = true,
+ .available_scan_masks = ad7380_4_channel_scan_masks,
+ .timing_specs = &ad7380_4_timing,
+};
+
struct ad7380_state {
const struct ad7380_chip_info *chip_info;
struct spi_device *spi;
@@ -520,6 +588,7 @@ struct ad7380_state {
bool seq;
unsigned int vref_mv;
unsigned int vcm_mv[MAX_NUM_CHANNELS];
+ unsigned int gain_milli[MAX_NUM_CHANNELS];
/* xfers, message an buffer for reading sample data */
struct spi_transfer normal_xfer[2];
struct spi_message normal_msg;
@@ -649,7 +718,8 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
if (st->oversampling_ratio > 1)
xfer.delay.value = T_CONVERT_0_NS +
- T_CONVERT_X_NS * (st->oversampling_ratio - 1);
+ T_CONVERT_X_NS * (st->oversampling_ratio - 1) *
+ st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
return spi_sync_transfer(st->spi, &xfer, 1);
}
@@ -672,7 +742,8 @@ static void ad7380_update_xfers(struct ad7380_state *st,
*/
if (st->oversampling_ratio > 1)
t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS *
- (st->oversampling_ratio - 1);
+ (st->oversampling_ratio - 1) *
+ st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
if (st->seq) {
xfer[0].delay.value = xfer[1].delay.value = t_convert;
@@ -868,8 +939,15 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
* * (2 × VREF) / 2^N, for differential chips
* * VREF / 2^N, for pseudo-differential chips
* where N is the ADC resolution (i.e realbits)
+ *
+ * The gain is stored as a fraction of 1000 and, as we need to
+ * divide vref_mv by the gain, we invert the gain/1000 fraction.
*/
- *val = st->vref_mv;
+ if (st->chip_info->has_hardware_gain)
+ *val = mult_frac(st->vref_mv, MILLI,
+ st->gain_milli[chan->scan_index]);
+ else
+ *val = st->vref_mv;
*val2 = scan_type->realbits - chan->differential;
return IIO_VAL_FRACTIONAL_LOG2;
@@ -1021,17 +1099,19 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
/* SPI 1-wire mode */
return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
AD7380_CONFIG2_SDO,
- FIELD_PREP(AD7380_CONFIG2_SDO, 1));
+ FIELD_PREP(AD7380_CONFIG2_SDO,
+ AD7380_NUM_SDO_LINES));
}
static int ad7380_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct ad7380_state *st;
bool external_ref_en;
int ret, i;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -1039,21 +1119,32 @@ static int ad7380_probe(struct spi_device *spi)
st->spi = spi;
st->chip_info = spi_get_device_match_data(spi);
if (!st->chip_info)
- return dev_err_probe(&spi->dev, -EINVAL, "missing match data\n");
+ return dev_err_probe(dev, -EINVAL, "missing match data\n");
- ret = devm_regulator_bulk_get_enable(&spi->dev, st->chip_info->num_supplies,
+ ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies,
st->chip_info->supplies);
if (ret)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to enable power supplies\n");
fsleep(T_POWERUP_US);
- if (st->chip_info->external_ref_only) {
- ret = devm_regulator_get_enable_read_voltage(&spi->dev,
- "refin");
+ if (st->chip_info->adaq_internal_ref_only) {
+ /*
+ * ADAQ chips use fixed internal reference but still
+ * require a specific reference supply to power it.
+ * "refin" is already enabled with other power supplies
+ * in bulk_get_enable().
+ */
+
+ st->vref_mv = ADAQ4380_INTERNAL_REF_MV;
+
+ /* these chips don't have a register bit for this */
+ external_ref_en = false;
+ } else if (st->chip_info->external_ref_only) {
+ ret = devm_regulator_get_enable_read_voltage(dev, "refin");
if (ret < 0)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get refin regulator\n");
st->vref_mv = ret / 1000;
@@ -1065,10 +1156,9 @@ static int ad7380_probe(struct spi_device *spi)
* If there is no REFIO supply, then it means that we are using
* the internal reference, otherwise REFIO is reference voltage.
*/
- ret = devm_regulator_get_enable_read_voltage(&spi->dev,
- "refio");
+ ret = devm_regulator_get_enable_read_voltage(dev, "refio");
if (ret < 0 && ret != -ENODEV)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get refio regulator\n");
external_ref_en = ret != -ENODEV;
@@ -1076,7 +1166,7 @@ static int ad7380_probe(struct spi_device *spi)
}
if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv))
- return dev_err_probe(&spi->dev, -EINVAL,
+ return dev_err_probe(dev, -EINVAL,
"invalid number of VCM supplies\n");
/*
@@ -1086,18 +1176,54 @@ static int ad7380_probe(struct spi_device *spi)
for (i = 0; i < st->chip_info->num_vcm_supplies; i++) {
const char *vcm = st->chip_info->vcm_supplies[i];
- ret = devm_regulator_get_enable_read_voltage(&spi->dev, vcm);
+ ret = devm_regulator_get_enable_read_voltage(dev, vcm);
if (ret < 0)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get %s regulator\n",
vcm);
st->vcm_mv[i] = ret / 1000;
}
- st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config);
+ for (i = 0; i < MAX_NUM_CHANNELS; i++)
+ st->gain_milli[i] = AD7380_DEFAULT_GAIN_MILLI;
+
+ if (st->chip_info->has_hardware_gain) {
+ device_for_each_child_node_scoped(dev, node) {
+ unsigned int channel, gain;
+ int gain_idx;
+
+ ret = fwnode_property_read_u32(node, "reg", &channel);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to read reg property\n");
+
+ if (channel >= st->chip_info->num_channels - 1)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid channel number %i\n",
+ channel);
+
+ ret = fwnode_property_read_u32(node, "adi,gain-milli",
+ &gain);
+ if (ret && ret != -EINVAL)
+ return dev_err_probe(dev, ret,
+ "Failed to read gain for channel %i\n",
+ channel);
+ if (ret != -EINVAL) {
+ /*
+ * Match gain value from dt to one of supported
+ * gains
+ */
+ gain_idx = find_closest(gain, ad7380_gains,
+ ARRAY_SIZE(ad7380_gains));
+ st->gain_milli[channel] = ad7380_gains[gain_idx];
+ }
+ }
+ }
+
+ st->regmap = devm_regmap_init(dev, NULL, st, &ad7380_regmap_config);
if (IS_ERR(st->regmap))
- return dev_err_probe(&spi->dev, PTR_ERR(st->regmap),
+ return dev_err_probe(dev, PTR_ERR(st->regmap),
"failed to allocate register map\n");
/*
@@ -1148,7 +1274,7 @@ static int ad7380_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->available_scan_masks = st->chip_info->available_scan_masks;
- ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
iio_pollfunc_store_time,
ad7380_trigger_handler,
&ad7380_buffer_setup_ops);
@@ -1159,7 +1285,7 @@ static int ad7380_probe(struct spi_device *spi)
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct of_device_id ad7380_of_match_table[] = {
@@ -1177,6 +1303,8 @@ static const struct of_device_id ad7380_of_match_table[] = {
{ .compatible = "adi,ad7386-4", .data = &ad7386_4_chip_info },
{ .compatible = "adi,ad7387-4", .data = &ad7387_4_chip_info },
{ .compatible = "adi,ad7388-4", .data = &ad7388_4_chip_info },
+ { .compatible = "adi,adaq4370-4", .data = &adaq4370_4_chip_info },
+ { .compatible = "adi,adaq4380-4", .data = &adaq4380_4_chip_info },
{ }
};
@@ -1195,6 +1323,8 @@ static const struct spi_device_id ad7380_id_table[] = {
{ "ad7386-4", (kernel_ulong_t)&ad7386_4_chip_info },
{ "ad7387-4", (kernel_ulong_t)&ad7387_4_chip_info },
{ "ad7388-4", (kernel_ulong_t)&ad7388_4_chip_info },
+ { "adaq4370-4", (kernel_ulong_t)&adaq4370_4_chip_info },
+ { "adaq4380-4", (kernel_ulong_t)&adaq4380_4_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7380_id_table);
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 9b457472d49c..8b2046baaa3e 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -13,14 +13,17 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
+#include <linux/pwm.h>
#include <linux/regulator/consumer.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/units.h>
#include <linux/util_macros.h>
-#include <linux/iio/iio.h>
+#include <linux/iio/backend.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
@@ -30,15 +33,52 @@
/*
* Scales are computed as 5000/32768 and 10000/32768 respectively,
- * so that when applied to the raw values they provide mV values
+ * so that when applied to the raw values they provide mV values.
+ * The scale arrays are kept as IIO_VAL_INT_PLUS_MICRO, so index
+ * X is the integer part and X + 1 is the fractional part.
*/
-static const unsigned int ad7606_scale_avail[2] = {
- 152588, 305176
+static const unsigned int ad7606_16bit_hw_scale_avail[2][2] = {
+ { 0, 152588 }, { 0, 305176 }
+};
+
+static const unsigned int ad7606_18bit_hw_scale_avail[2][2] = {
+ { 0, 38147 }, { 0, 76294 }
+};
+
+static const unsigned int ad7606c_16bit_single_ended_unipolar_scale_avail[3][2] = {
+ { 0, 76294 }, { 0, 152588 }, { 0, 190735 }
+};
+
+static const unsigned int ad7606c_16bit_single_ended_bipolar_scale_avail[5][2] = {
+ { 0, 76294 }, { 0, 152588 }, { 0, 190735 }, { 0, 305176 }, { 0, 381470 }
+};
+
+static const unsigned int ad7606c_16bit_differential_bipolar_scale_avail[4][2] = {
+ { 0, 152588 }, { 0, 305176 }, { 0, 381470 }, { 0, 610352 }
+};
+
+static const unsigned int ad7606c_18bit_single_ended_unipolar_scale_avail[3][2] = {
+ { 0, 19073 }, { 0, 38147 }, { 0, 47684 }
+};
+
+static const unsigned int ad7606c_18bit_single_ended_bipolar_scale_avail[5][2] = {
+ { 0, 19073 }, { 0, 38147 }, { 0, 47684 }, { 0, 76294 }, { 0, 95367 }
};
+static const unsigned int ad7606c_18bit_differential_bipolar_scale_avail[4][2] = {
+ { 0, 38147 }, { 0, 76294 }, { 0, 95367 }, { 0, 152588 }
+};
+
+static const unsigned int ad7606_16bit_sw_scale_avail[3][2] = {
+ { 0, 76293 }, { 0, 152588 }, { 0, 305176 }
+};
-static const unsigned int ad7616_sw_scale_avail[3] = {
- 76293, 152588, 305176
+static const unsigned int ad7607_hw_scale_avail[2][2] = {
+ { 0, 610352 }, { 1, 220703 }
+};
+
+static const unsigned int ad7609_hw_scale_avail[2][2] = {
+ { 0, 152588 }, { 0, 305176 }
};
static const unsigned int ad7606_oversampling_avail[7] = {
@@ -49,6 +89,227 @@ static const unsigned int ad7616_oversampling_avail[8] = {
1, 2, 4, 8, 16, 32, 64, 128,
};
+static const struct iio_chan_spec ad7605_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ AD7605_CHANNEL(0),
+ AD7605_CHANNEL(1),
+ AD7605_CHANNEL(2),
+ AD7605_CHANNEL(3),
+};
+
+static const struct iio_chan_spec ad7606_channels_16bit[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 16),
+ AD7606_CHANNEL(1, 16),
+ AD7606_CHANNEL(2, 16),
+ AD7606_CHANNEL(3, 16),
+ AD7606_CHANNEL(4, 16),
+ AD7606_CHANNEL(5, 16),
+ AD7606_CHANNEL(6, 16),
+ AD7606_CHANNEL(7, 16),
+};
+
+static const struct iio_chan_spec ad7606_channels_18bit[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 18),
+ AD7606_CHANNEL(1, 18),
+ AD7606_CHANNEL(2, 18),
+ AD7606_CHANNEL(3, 18),
+ AD7606_CHANNEL(4, 18),
+ AD7606_CHANNEL(5, 18),
+ AD7606_CHANNEL(6, 18),
+ AD7606_CHANNEL(7, 18),
+};
+
+static const struct iio_chan_spec ad7607_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 14),
+ AD7606_CHANNEL(1, 14),
+ AD7606_CHANNEL(2, 14),
+ AD7606_CHANNEL(3, 14),
+ AD7606_CHANNEL(4, 14),
+ AD7606_CHANNEL(5, 14),
+ AD7606_CHANNEL(6, 14),
+ AD7606_CHANNEL(7, 14),
+};
+
+static const struct iio_chan_spec ad7608_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 18),
+ AD7606_CHANNEL(1, 18),
+ AD7606_CHANNEL(2, 18),
+ AD7606_CHANNEL(3, 18),
+ AD7606_CHANNEL(4, 18),
+ AD7606_CHANNEL(5, 18),
+ AD7606_CHANNEL(6, 18),
+ AD7606_CHANNEL(7, 18),
+};
+
+/*
+ * The current assumption that this driver makes for AD7616, is that it's
+ * working in Hardware Mode with Serial, Burst and Sequencer modes activated.
+ * To activate them, following pins must be pulled high:
+ * -SER/PAR
+ * -SEQEN
+ * And following pins must be pulled low:
+ * -WR/BURST
+ * -DB4/SER1W
+ */
+static const struct iio_chan_spec ad7616_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(16),
+ AD7606_CHANNEL(0, 16),
+ AD7606_CHANNEL(1, 16),
+ AD7606_CHANNEL(2, 16),
+ AD7606_CHANNEL(3, 16),
+ AD7606_CHANNEL(4, 16),
+ AD7606_CHANNEL(5, 16),
+ AD7606_CHANNEL(6, 16),
+ AD7606_CHANNEL(7, 16),
+ AD7606_CHANNEL(8, 16),
+ AD7606_CHANNEL(9, 16),
+ AD7606_CHANNEL(10, 16),
+ AD7606_CHANNEL(11, 16),
+ AD7606_CHANNEL(12, 16),
+ AD7606_CHANNEL(13, 16),
+ AD7606_CHANNEL(14, 16),
+ AD7606_CHANNEL(15, 16),
+};
+
+static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7607_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7608_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7609_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+
+const struct ad7606_chip_info ad7605_4_info = {
+ .channels = ad7605_channels,
+ .name = "ad7605-4",
+ .num_adc_channels = 4,
+ .num_channels = 5,
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7605_4_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606_8_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-8",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_8_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606_6_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-6",
+ .num_adc_channels = 6,
+ .num_channels = 7,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_6_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606_4_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-4",
+ .num_adc_channels = 4,
+ .num_channels = 5,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_4_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606b_info = {
+ .channels = ad7606_channels_16bit,
+ .max_samplerate = 800 * KILO,
+ .name = "ad7606b",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606b_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606c_16_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606c16",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606c_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7607_info = {
+ .channels = ad7607_channels,
+ .name = "ad7607",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7607_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7607_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7608_info = {
+ .channels = ad7608_channels,
+ .name = "ad7608",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7608_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7608_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7609_info = {
+ .channels = ad7608_channels,
+ .name = "ad7609",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7609_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7609_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7606c_18_info = {
+ .channels = ad7606_channels_18bit,
+ .name = "ad7606c18",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606c_18bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, IIO_AD7606);
+
+const struct ad7606_chip_info ad7616_info = {
+ .channels = ad7616_channels,
+ .init_delay_ms = 15,
+ .name = "ad7616",
+ .num_adc_channels = 16,
+ .num_channels = 17,
+ .oversampling_avail = ad7616_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
+ .os_req_reset = true,
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7616_info, IIO_AD7606);
+
int ad7606_reset(struct ad7606_state *st)
{
if (st->gpio_reset) {
@@ -62,6 +323,228 @@ int ad7606_reset(struct ad7606_state *st)
}
EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606);
+static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ if (!st->sw_mode_en) {
+ /* tied to logic low, analog input range is +/- 5V */
+ cs->range = 0;
+ cs->scale_avail = ad7606_16bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail);
+ return 0;
+ }
+
+ /* Scale of 0.076293 is only available in sw mode */
+ /* After reset, in software mode, ±10 V is set by default */
+ cs->range = 2;
+ cs->scale_avail = ad7606_16bit_sw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_sw_scale_avail);
+
+ return 0;
+}
+
+static int ad7606_get_chan_config(struct ad7606_state *st, int ch,
+ bool *bipolar, bool *differential)
+{
+ unsigned int num_channels = st->chip_info->num_channels - 1;
+ struct device *dev = st->dev;
+ int ret;
+
+ *bipolar = false;
+ *differential = false;
+
+ device_for_each_child_node_scoped(dev, child) {
+ u32 pins[2];
+ int reg;
+
+ ret = fwnode_property_read_u32(child, "reg", &reg);
+ if (ret)
+ continue;
+
+ /* channel number (here) is from 1 to num_channels */
+ if (reg == 0 || reg > num_channels) {
+ dev_warn(dev,
+ "Invalid channel number (ignoring): %d\n", reg);
+ continue;
+ }
+
+ if (reg != (ch + 1))
+ continue;
+
+ *bipolar = fwnode_property_read_bool(child, "bipolar");
+
+ ret = fwnode_property_read_u32_array(child, "diff-channels",
+ pins, ARRAY_SIZE(pins));
+ /* Channel is differential, if pins are the same as 'reg' */
+ if (ret == 0 && (pins[0] != reg || pins[1] != reg)) {
+ dev_err(dev,
+ "Differential pins must be the same as 'reg'");
+ return -EINVAL;
+ }
+
+ *differential = (ret == 0);
+
+ if (*differential && !*bipolar) {
+ dev_err(dev,
+ "'bipolar' must be added for diff channel %d\n",
+ reg);
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ bool bipolar, differential;
+ int ret;
+
+ if (!st->sw_mode_en) {
+ cs->range = 0;
+ cs->scale_avail = ad7606_18bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail);
+ return 0;
+ }
+
+ ret = ad7606_get_chan_config(st, ch, &bipolar, &differential);
+ if (ret)
+ return ret;
+
+ if (differential) {
+ cs->scale_avail = ad7606c_18bit_differential_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_differential_bipolar_scale_avail);
+ /* Bipolar differential ranges start at 8 (b1000) */
+ cs->reg_offset = 8;
+ cs->range = 1;
+ chan->differential = 1;
+ chan->channel2 = chan->channel;
+
+ return 0;
+ }
+
+ chan->differential = 0;
+
+ if (bipolar) {
+ cs->scale_avail = ad7606c_18bit_single_ended_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_single_ended_bipolar_scale_avail);
+ /* Bipolar single-ended ranges start at 0 (b0000) */
+ cs->reg_offset = 0;
+ cs->range = 3;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ cs->scale_avail = ad7606c_18bit_single_ended_unipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_single_ended_unipolar_scale_avail);
+ /* Unipolar single-ended ranges start at 5 (b0101) */
+ cs->reg_offset = 5;
+ cs->range = 1;
+ chan->scan_type.sign = 'u';
+
+ return 0;
+}
+
+static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ bool bipolar, differential;
+ int ret;
+
+ if (!st->sw_mode_en) {
+ cs->range = 0;
+ cs->scale_avail = ad7606_16bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail);
+ return 0;
+ }
+
+ ret = ad7606_get_chan_config(st, ch, &bipolar, &differential);
+ if (ret)
+ return ret;
+
+ if (differential) {
+ cs->scale_avail = ad7606c_16bit_differential_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_differential_bipolar_scale_avail);
+ /* Bipolar differential ranges start at 8 (b1000) */
+ cs->reg_offset = 8;
+ cs->range = 1;
+ chan->differential = 1;
+ chan->channel2 = chan->channel;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ chan->differential = 0;
+
+ if (bipolar) {
+ cs->scale_avail = ad7606c_16bit_single_ended_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_single_ended_bipolar_scale_avail);
+ /* Bipolar single-ended ranges start at 0 (b0000) */
+ cs->reg_offset = 0;
+ cs->range = 3;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ cs->scale_avail = ad7606c_16bit_single_ended_unipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_single_ended_unipolar_scale_avail);
+ /* Unipolar single-ended ranges start at 5 (b0101) */
+ cs->reg_offset = 5;
+ cs->range = 1;
+ chan->scan_type.sign = 'u';
+
+ return 0;
+}
+
+static int ad7607_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7607_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7607_hw_scale_avail);
+ return 0;
+}
+
+static int ad7608_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7606_18bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail);
+ return 0;
+}
+
+static int ad7609_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7609_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7609_hw_scale_avail);
+ return 0;
+}
+
static int ad7606_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
unsigned int writeval,
@@ -83,12 +566,85 @@ static int ad7606_reg_access(struct iio_dev *indio_dev,
}
}
+static int ad7606_pwm_set_high(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+ int ret;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period;
+
+ ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return ret;
+}
+
+static int ad7606_pwm_set_low(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+ int ret;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = 0;
+
+ ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return ret;
+}
+
+static int ad7606_pwm_set_swing(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2;
+
+ return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+}
+
+static bool ad7606_pwm_is_swinging(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return cnvst_pwm_state.duty_cycle != cnvst_pwm_state.period &&
+ cnvst_pwm_state.duty_cycle != 0;
+}
+
+static int ad7606_set_sampling_freq(struct ad7606_state *st, unsigned long freq)
+{
+ struct pwm_state cnvst_pwm_state;
+ bool is_swinging = ad7606_pwm_is_swinging(st);
+ bool is_high;
+
+ if (freq == 0)
+ return -EINVAL;
+
+ /* Retrieve the previous state. */
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ is_high = cnvst_pwm_state.duty_cycle == cnvst_pwm_state.period;
+
+ cnvst_pwm_state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq);
+ cnvst_pwm_state.polarity = PWM_POLARITY_NORMAL;
+ if (is_high)
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period;
+ else if (is_swinging)
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2;
+ else
+ cnvst_pwm_state.duty_cycle = 0;
+
+ return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+}
+
static int ad7606_read_samples(struct ad7606_state *st)
{
- unsigned int num = st->chip_info->num_channels - 1;
- u16 *data = st->data;
+ unsigned int num = st->chip_info->num_adc_channels;
- return st->bops->read_block(st->dev, num, data);
+ return st->bops->read_block(st->dev, num, &st->data);
}
static irqreturn_t ad7606_trigger_handler(int irq, void *p)
@@ -104,7 +660,7 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p)
if (ret)
goto error_ret;
- iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->data,
iio_get_time_ns(indio_dev));
error_ret:
iio_trigger_notify_done(indio_dev->trig);
@@ -114,24 +670,62 @@ error_ret:
return IRQ_HANDLED;
}
-static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
+static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
+ int *val)
{
struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int realbits = st->chip_info->channels[1].scan_type.realbits;
+ const struct iio_chan_spec *chan;
int ret;
- gpiod_set_value(st->gpio_convst, 1);
- ret = wait_for_completion_timeout(&st->completion,
- msecs_to_jiffies(1000));
- if (!ret) {
- ret = -ETIMEDOUT;
- goto error_ret;
+ if (st->gpio_convst) {
+ gpiod_set_value(st->gpio_convst, 1);
+ } else {
+ ret = ad7606_pwm_set_high(st);
+ if (ret < 0)
+ return ret;
+ }
+
+ /*
+ * If no backend, wait for the interruption on busy pin, otherwise just add
+ * a delay to leave time for the data to be available. For now, the latter
+ * will not happen because IIO_CHAN_INFO_RAW is not supported for the backend.
+ * TODO: Add support for reading a single value when the backend is used.
+ */
+ if (!st->back) {
+ ret = wait_for_completion_timeout(&st->completion,
+ msecs_to_jiffies(1000));
+ if (!ret) {
+ ret = -ETIMEDOUT;
+ goto error_ret;
+ }
+ } else {
+ fsleep(1);
}
ret = ad7606_read_samples(st);
- if (ret == 0)
- ret = st->data[ch];
+ if (ret)
+ goto error_ret;
+
+ chan = &indio_dev->channels[ch + 1];
+ if (chan->scan_type.sign == 'u') {
+ if (realbits > 16)
+ *val = st->data.buf32[ch];
+ else
+ *val = st->data.buf16[ch];
+ } else {
+ if (realbits > 16)
+ *val = sign_extend32(st->data.buf32[ch], realbits - 1);
+ else
+ *val = sign_extend32(st->data.buf16[ch], realbits - 1);
+ }
error_ret:
+ if (!st->gpio_convst) {
+ ret = ad7606_pwm_set_low(st);
+ if (ret < 0)
+ return ret;
+ }
gpiod_set_value(st->gpio_convst, 0);
return ret;
@@ -145,53 +739,57 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
{
int ret, ch = 0;
struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs;
+ struct pwm_state cnvst_pwm_state;
switch (m) {
case IIO_CHAN_INFO_RAW:
iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
- ret = ad7606_scan_direct(indio_dev, chan->address);
+ ret = ad7606_scan_direct(indio_dev, chan->address, val);
if (ret < 0)
return ret;
- *val = (short) ret;
return IIO_VAL_INT;
}
unreachable();
case IIO_CHAN_INFO_SCALE:
if (st->sw_mode_en)
ch = chan->address;
- *val = 0;
- *val2 = st->scale_avail[st->range[ch]];
+ cs = &st->chan_scales[ch];
+ *val = cs->scale_avail[cs->range][0];
+ *val2 = cs->scale_avail[cs->range][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
*val = st->oversampling;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ /*
+ * TODO: return the real frequency intead of the requested one once
+ * pwm_get_state_hw comes upstream.
+ */
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ *val = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, cnvst_pwm_state.period);
+ return IIO_VAL_INT;
}
return -EINVAL;
}
-static ssize_t ad7606_show_avail(char *buf, const unsigned int *vals,
- unsigned int n, bool micros)
-{
- size_t len = 0;
- int i;
-
- for (i = 0; i < n; i++) {
- len += scnprintf(buf + len, PAGE_SIZE - len,
- micros ? "0.%06u " : "%u ", vals[i]);
- }
- buf[len - 1] = '\n';
-
- return len;
-}
-
static ssize_t in_voltage_scale_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs = &st->chan_scales[0];
+ const unsigned int (*vals)[2] = cs->scale_avail;
+ unsigned int i;
+ size_t len = 0;
+
+ for (i = 0; i < cs->num_scales; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ",
+ vals[i][0], vals[i][1]);
+ buf[len - 1] = '\n';
- return ad7606_show_avail(buf, st->scale_avail, st->num_scales, true);
+ return len;
}
static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
@@ -229,19 +827,27 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int scale_avail_uv[AD760X_MAX_SCALES];
+ struct ad7606_chan_scale *cs;
int i, ret, ch = 0;
guard(mutex)(&st->lock);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
- i = find_closest(val2, st->scale_avail, st->num_scales);
if (st->sw_mode_en)
ch = chan->address;
- ret = st->write_scale(indio_dev, ch, i);
+ cs = &st->chan_scales[ch];
+ for (i = 0; i < cs->num_scales; i++) {
+ scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO +
+ cs->scale_avail[i][1];
+ }
+ val = (val * MICRO) + val2;
+ i = find_closest(val, scale_avail_uv, cs->num_scales);
+ ret = st->write_scale(indio_dev, ch, i + cs->reg_offset);
if (ret < 0)
return ret;
- st->range[ch] = i;
+ cs->range = i;
return 0;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -252,8 +858,13 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
ret = st->write_os(indio_dev, i);
if (ret < 0)
return ret;
+ st->oversampling = st->oversampling_avail[i];
return 0;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val < 0 && val2 != 0)
+ return -EINVAL;
+ return ad7606_set_sampling_freq(st, val);
default:
return -EINVAL;
}
@@ -265,9 +876,15 @@ static ssize_t ad7606_oversampling_ratio_avail(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
+ const unsigned int *vals = st->oversampling_avail;
+ unsigned int i;
+ size_t len = 0;
- return ad7606_show_avail(buf, st->oversampling_avail,
- st->num_os_ratios, false);
+ for (i = 0; i < st->num_os_ratios; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u ", vals[i]);
+ buf[len - 1] = '\n';
+
+ return len;
}
static IIO_DEVICE_ATTR(oversampling_ratio_available, 0444,
@@ -301,102 +918,13 @@ static const struct attribute_group ad7606_attribute_group_range = {
.attrs = ad7606_attributes_range,
};
-static const struct iio_chan_spec ad7605_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(4),
- AD7605_CHANNEL(0),
- AD7605_CHANNEL(1),
- AD7605_CHANNEL(2),
- AD7605_CHANNEL(3),
-};
-
-static const struct iio_chan_spec ad7606_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_CHANNEL(0),
- AD7606_CHANNEL(1),
- AD7606_CHANNEL(2),
- AD7606_CHANNEL(3),
- AD7606_CHANNEL(4),
- AD7606_CHANNEL(5),
- AD7606_CHANNEL(6),
- AD7606_CHANNEL(7),
-};
-
-/*
- * The current assumption that this driver makes for AD7616, is that it's
- * working in Hardware Mode with Serial, Burst and Sequencer modes activated.
- * To activate them, following pins must be pulled high:
- * -SER/PAR
- * -SEQEN
- * And following pins must be pulled low:
- * -WR/BURST
- * -DB4/SER1W
- */
-static const struct iio_chan_spec ad7616_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(16),
- AD7606_CHANNEL(0),
- AD7606_CHANNEL(1),
- AD7606_CHANNEL(2),
- AD7606_CHANNEL(3),
- AD7606_CHANNEL(4),
- AD7606_CHANNEL(5),
- AD7606_CHANNEL(6),
- AD7606_CHANNEL(7),
- AD7606_CHANNEL(8),
- AD7606_CHANNEL(9),
- AD7606_CHANNEL(10),
- AD7606_CHANNEL(11),
- AD7606_CHANNEL(12),
- AD7606_CHANNEL(13),
- AD7606_CHANNEL(14),
- AD7606_CHANNEL(15),
-};
-
-static const struct ad7606_chip_info ad7606_chip_info_tbl[] = {
- /* More devices added in future */
- [ID_AD7605_4] = {
- .channels = ad7605_channels,
- .num_channels = 5,
- },
- [ID_AD7606_8] = {
- .channels = ad7606_channels,
- .num_channels = 9,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606_6] = {
- .channels = ad7606_channels,
- .num_channels = 7,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606_4] = {
- .channels = ad7606_channels,
- .num_channels = 5,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606B] = {
- .channels = ad7606_channels,
- .num_channels = 9,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7616] = {
- .channels = ad7616_channels,
- .num_channels = 17,
- .oversampling_avail = ad7616_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
- .os_req_reset = true,
- .init_delay_ms = 15,
- },
-};
-
static int ad7606_request_gpios(struct ad7606_state *st)
{
struct device *dev = st->dev;
- st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start",
- GPIOD_OUT_LOW);
+ st->gpio_convst = devm_gpiod_get_optional(dev, "adi,conversion-start",
+ GPIOD_OUT_LOW);
+
if (IS_ERR(st->gpio_convst))
return PTR_ERR(st->gpio_convst);
@@ -438,14 +966,24 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
{
struct iio_dev *indio_dev = dev_id;
struct ad7606_state *st = iio_priv(indio_dev);
+ int ret;
if (iio_buffer_enabled(indio_dev)) {
- gpiod_set_value(st->gpio_convst, 0);
+ if (st->gpio_convst) {
+ gpiod_set_value(st->gpio_convst, 0);
+ } else {
+ ret = ad7606_pwm_set_low(st);
+ if (ret < 0) {
+ dev_err(st->dev, "PWM set low failed");
+ goto done;
+ }
+ }
iio_trigger_poll_nested(st->trig);
} else {
complete(&st->completion);
}
+done:
return IRQ_HANDLED;
};
@@ -478,14 +1016,81 @@ static int ad7606_buffer_predisable(struct iio_dev *indio_dev)
return 0;
}
+static int ad7606_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long info)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs;
+ unsigned int ch = 0;
+
+ switch (info) {
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *vals = st->oversampling_avail;
+ *length = st->num_os_ratios;
+ *type = IIO_VAL_INT;
+
+ return IIO_AVAIL_LIST;
+
+ case IIO_CHAN_INFO_SCALE:
+ if (st->sw_mode_en)
+ ch = chan->address;
+
+ cs = &st->chan_scales[ch];
+ *vals = (int *)cs->scale_avail;
+ *length = cs->num_scales;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+
+ return IIO_AVAIL_LIST;
+ }
+ return -EINVAL;
+}
+
+static int ad7606_backend_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ return ad7606_pwm_set_swing(st);
+}
+
+static int ad7606_backend_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ return ad7606_pwm_set_low(st);
+}
+
+static int ad7606_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ /*
+ * The update scan mode is only for iio backend compatible drivers.
+ * If the specific update_scan_mode is not defined in the bus ops,
+ * just do nothing and return 0.
+ */
+ if (!st->bops->update_scan_mode)
+ return 0;
+
+ return st->bops->update_scan_mode(indio_dev, scan_mask);
+}
+
static const struct iio_buffer_setup_ops ad7606_buffer_ops = {
.postenable = &ad7606_buffer_postenable,
.predisable = &ad7606_buffer_predisable,
};
+static const struct iio_buffer_setup_ops ad7606_backend_buffer_ops = {
+ .postenable = &ad7606_backend_buffer_postenable,
+ .predisable = &ad7606_backend_buffer_predisable,
+};
+
static const struct iio_info ad7606_info_no_os_or_range = {
.read_raw = &ad7606_read_raw,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_os_and_range = {
@@ -493,14 +1098,16 @@ static const struct iio_info ad7606_info_os_and_range = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os_and_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
-static const struct iio_info ad7606_info_os_range_and_debug = {
+static const struct iio_info ad7606_info_sw_mode = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
+ .read_avail = &ad7606_read_avail,
.debugfs_reg_access = &ad7606_reg_access,
- .attrs = &ad7606_attribute_group_os_and_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_os = {
@@ -508,6 +1115,7 @@ static const struct iio_info ad7606_info_os = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_range = {
@@ -515,14 +1123,60 @@ static const struct iio_info ad7606_info_range = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_trigger_ops ad7606_trigger_ops = {
.validate_device = iio_trigger_validate_own_device,
};
+static int ad7606_sw_mode_setup(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ st->sw_mode_en = st->bops->sw_mode_config &&
+ device_property_present(st->dev, "adi,sw-mode");
+ if (!st->sw_mode_en)
+ return 0;
+
+ indio_dev->info = &ad7606_info_sw_mode;
+
+ return st->bops->sw_mode_config(indio_dev);
+}
+
+static int ad7606_chan_scales_setup(struct iio_dev *indio_dev)
+{
+ unsigned int num_channels = indio_dev->num_channels - 1;
+ struct ad7606_state *st = iio_priv(indio_dev);
+ struct iio_chan_spec *chans;
+ size_t size;
+ int ch, ret;
+
+ /* Clone IIO channels, since some may be differential */
+ size = indio_dev->num_channels * sizeof(*indio_dev->channels);
+ chans = devm_kzalloc(st->dev, size, GFP_KERNEL);
+ if (!chans)
+ return -ENOMEM;
+
+ memcpy(chans, indio_dev->channels, size);
+ indio_dev->channels = chans;
+
+ for (ch = 0; ch < num_channels; ch++) {
+ ret = st->chip_info->scale_setup_cb(st, &chans[ch + 1], ch);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void ad7606_pwm_disable(void *data)
+{
+ pwm_disable(data);
+}
+
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
- const char *name, unsigned int id,
+ const struct ad7606_chip_info *chip_info,
const struct ad7606_bus_ops *bops)
{
struct ad7606_state *st;
@@ -540,18 +1194,14 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
mutex_init(&st->lock);
st->bops = bops;
st->base_address = base_address;
- /* tied to logic low, analog input range is +/- 5V */
- st->range[0] = 0;
st->oversampling = 1;
- st->scale_avail = ad7606_scale_avail;
- st->num_scales = ARRAY_SIZE(ad7606_scale_avail);
ret = devm_regulator_get_enable(dev, "avcc");
if (ret)
return dev_err_probe(dev, ret,
"Failed to enable specified AVcc supply\n");
- st->chip_info = &ad7606_chip_info_tbl[id];
+ st->chip_info = chip_info;
if (st->chip_info->oversampling_num) {
st->oversampling_avail = st->chip_info->oversampling_avail;
@@ -574,12 +1224,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
indio_dev->info = &ad7606_info_no_os_or_range;
}
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->name = name;
+ indio_dev->name = chip_info->name;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
- init_completion(&st->completion);
-
ret = ad7606_reset(st);
if (ret)
dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
@@ -593,52 +1241,90 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
st->write_scale = ad7606_write_scale_hw;
st->write_os = ad7606_write_os_hw;
- if (st->bops->sw_mode_config)
- st->sw_mode_en = device_property_present(st->dev,
- "adi,sw-mode");
+ ret = ad7606_sw_mode_setup(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7606_chan_scales_setup(indio_dev);
+ if (ret)
+ return ret;
+
+ /* If convst pin is not defined, setup PWM. */
+ if (!st->gpio_convst) {
+ st->cnvst_pwm = devm_pwm_get(dev, NULL);
+ if (IS_ERR(st->cnvst_pwm))
+ return PTR_ERR(st->cnvst_pwm);
- if (st->sw_mode_en) {
- /* Scale of 0.076293 is only available in sw mode */
- st->scale_avail = ad7616_sw_scale_avail;
- st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail);
+ /* The PWM is initialized at 1MHz to have a fast enough GPIO emulation. */
+ ret = ad7606_set_sampling_freq(st, 1 * MEGA);
+ if (ret)
+ return ret;
- /* After reset, in software mode, ±10 V is set by default */
- memset32(st->range, 2, ARRAY_SIZE(st->range));
- indio_dev->info = &ad7606_info_os_range_and_debug;
+ ret = ad7606_pwm_set_low(st);
+ if (ret)
+ return ret;
- ret = st->bops->sw_mode_config(indio_dev);
- if (ret < 0)
+ /*
+ * PWM is not disabled when sampling stops, but instead its duty cycle is set
+ * to 0% to be sure we have a "low" state. After we unload the driver, let's
+ * disable the PWM.
+ */
+ ret = devm_add_action_or_reset(dev, ad7606_pwm_disable,
+ st->cnvst_pwm);
+ if (ret)
return ret;
}
- st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
- indio_dev->name,
- iio_device_id(indio_dev));
- if (!st->trig)
- return -ENOMEM;
+ if (st->bops->iio_backend_config) {
+ /*
+ * If there is a backend, the PWM should not overpass the maximum sampling
+ * frequency the chip supports.
+ */
+ ret = ad7606_set_sampling_freq(st,
+ chip_info->max_samplerate ? : 2 * KILO);
+ if (ret)
+ return ret;
- st->trig->ops = &ad7606_trigger_ops;
- iio_trigger_set_drvdata(st->trig, indio_dev);
- ret = devm_iio_trigger_register(dev, st->trig);
- if (ret)
- return ret;
+ ret = st->bops->iio_backend_config(dev, indio_dev);
+ if (ret)
+ return ret;
- indio_dev->trig = iio_trigger_get(st->trig);
+ indio_dev->setup_ops = &ad7606_backend_buffer_ops;
+ } else {
- ret = devm_request_threaded_irq(dev, irq,
- NULL,
- &ad7606_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- name, indio_dev);
- if (ret)
- return ret;
+ /* Reserve the PWM use only for backend (force gpio_convst definition) */
+ if (!st->gpio_convst)
+ return dev_err_probe(dev, -EINVAL,
+ "No backend, connect convst to a GPIO");
+
+ init_completion(&st->completion);
+ st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->trig)
+ return -ENOMEM;
+
+ st->trig->ops = &ad7606_trigger_ops;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
+ ret = devm_iio_trigger_register(dev, st->trig);
+ if (ret)
+ return ret;
- ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
- &iio_pollfunc_store_time,
- &ad7606_trigger_handler,
- &ad7606_buffer_ops);
- if (ret)
- return ret;
+ indio_dev->trig = iio_trigger_get(st->trig);
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, &ad7606_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ chip_info->name, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7606_trigger_handler,
+ &ad7606_buffer_ops);
+ if (ret)
+ return ret;
+ }
return devm_iio_device_register(dev, indio_dev);
}
@@ -665,7 +1351,7 @@ static int ad7606_resume(struct device *dev)
struct ad7606_state *st = iio_priv(indio_dev);
if (st->gpio_standby) {
- gpiod_set_value(st->gpio_range, st->range[0]);
+ gpiod_set_value(st->gpio_range, st->chan_scales[0].range);
gpiod_set_value(st->gpio_standby, 1);
ad7606_reset(st);
}
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index 6649e84d25de..998814a92b82 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -8,7 +8,9 @@
#ifndef IIO_ADC_AD7606_H_
#define IIO_ADC_AD7606_H_
-#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \
+#define AD760X_MAX_CHANNELS 16
+
+#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all, bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
@@ -19,39 +21,79 @@
.scan_index = num, \
.scan_type = { \
.sign = 's', \
- .realbits = 16, \
- .storagebits = 16, \
+ .realbits = (bits), \
+ .storagebits = (bits) > 16 ? 32 : 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+#define AD7606_SW_CHANNEL(num, bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = num, \
+ .address = num, \
+ .info_mask_separate = \
+ BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_separate_available = \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .info_mask_shared_by_all_available = \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .scan_index = num, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = (bits), \
+ .storagebits = (bits) > 16 ? 32 : 16, \
.endianness = IIO_CPU, \
}, \
}
#define AD7605_CHANNEL(num) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
- BIT(IIO_CHAN_INFO_SCALE), 0)
+ BIT(IIO_CHAN_INFO_SCALE), 0, 16)
-#define AD7606_CHANNEL(num) \
+#define AD7606_CHANNEL(num, bits) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
BIT(IIO_CHAN_INFO_SCALE), \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), bits)
+
+#define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16)
+
+#define AD7606_BI_CHANNEL(num) \
+ AD760X_CHANNEL(num, 0, \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 16)
-#define AD7616_CHANNEL(num) \
- AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\
- 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+struct ad7606_state;
+
+typedef int (*ad7606_scale_setup_cb_t)(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
/**
* struct ad7606_chip_info - chip specific information
* @channels: channel specification
+ * @max_samplerate: maximum supported samplerate
+ * @name device name
* @num_channels: number of channels
+ * @num_adc_channels the number of channels the ADC actually inputs.
+ * @scale_setup_cb: callback to setup the scales for each channel
* @oversampling_avail pointer to the array which stores the available
* oversampling ratios.
* @oversampling_num number of elements stored in oversampling_avail array
* @os_req_reset some devices require a reset to update oversampling
- * @init_delay_ms required delay in miliseconds for initialization
+ * @init_delay_ms required delay in milliseconds for initialization
* after a restart
*/
struct ad7606_chip_info {
const struct iio_chan_spec *channels;
+ unsigned int max_samplerate;
+ const char *name;
+ unsigned int num_adc_channels;
unsigned int num_channels;
+ ad7606_scale_setup_cb_t scale_setup_cb;
const unsigned int *oversampling_avail;
unsigned int oversampling_num;
bool os_req_reset;
@@ -59,16 +101,31 @@ struct ad7606_chip_info {
};
/**
+ * struct ad7606_chan_scale - channel scale configuration
+ * @scale_avail pointer to the array which stores the available scales
+ * @num_scales number of elements stored in the scale_avail array
+ * @range voltage range selection, selects which scale to apply
+ * @reg_offset offset for the register value, to be applied when
+ * writing the value of 'range' to the register value
+ */
+struct ad7606_chan_scale {
+#define AD760X_MAX_SCALES 16
+ const unsigned int (*scale_avail)[2];
+ unsigned int num_scales;
+ unsigned int range;
+ unsigned int reg_offset;
+};
+
+/**
* struct ad7606_state - driver instance specific data
* @dev pointer to kernel device
* @chip_info entry in the table of chips that describes this device
* @bops bus operations (SPI or parallel)
- * @range voltage range selection, selects which scale to apply
+ * @chan_scales scale configuration for channels
* @oversampling oversampling selection
+ * @cnvst_pwm pointer to the PWM device connected to the cnvst pin
* @base_address address from where to read data in parallel operation
* @sw_mode_en software mode enabled
- * @scale_avail pointer to the array which stores the available scales
- * @num_scales number of elements stored in the scale_avail array
* @oversampling_avail pointer to the array which stores the available
* oversampling ratios.
* @num_os_ratios number of elements stored in oversampling_avail array
@@ -92,14 +149,14 @@ struct ad7606_state {
struct device *dev;
const struct ad7606_chip_info *chip_info;
const struct ad7606_bus_ops *bops;
- unsigned int range[16];
+ struct ad7606_chan_scale chan_scales[AD760X_MAX_CHANNELS];
unsigned int oversampling;
+ struct pwm_device *cnvst_pwm;
void __iomem *base_address;
bool sw_mode_en;
- const unsigned int *scale_avail;
- unsigned int num_scales;
const unsigned int *oversampling_avail;
unsigned int num_os_ratios;
+ struct iio_backend *back;
int (*write_scale)(struct iio_dev *indio_dev, int ch, int val);
int (*write_os)(struct iio_dev *indio_dev, int val);
@@ -116,24 +173,33 @@ struct ad7606_state {
/*
* DMA (thus cache coherency maintenance) may require the
* transfer buffers to live in their own cache lines.
- * 16 * 16-bit samples + 64-bit timestamp
+ * 16 * 16-bit samples + 64-bit timestamp - for AD7616
+ * 8 * 32-bit samples + 64-bit timestamp - for AD7616C-18 (and similar)
*/
- unsigned short data[20] __aligned(IIO_DMA_MINALIGN);
+ union {
+ u16 buf16[20];
+ u32 buf32[10];
+ } data __aligned(IIO_DMA_MINALIGN);
__be16 d16[2];
};
/**
* struct ad7606_bus_ops - driver bus operations
+ * @iio_backend_config function pointer for configuring the iio_backend for
+ * the compatibles that use it
* @read_block function pointer for reading blocks of data
* @sw_mode_config: pointer to a function which configured the device
* for software mode
* @reg_read function pointer for reading spi register
* @reg_write function pointer for writing spi register
* @write_mask function pointer for write spi register with mask
+ * @update_scan_mode function pointer for handling the calls to iio_info's update_scan
+ * mode when enabling/disabling channels.
* @rd_wr_cmd pointer to the function which calculates the spi address
*/
struct ad7606_bus_ops {
/* more methods added in future? */
+ int (*iio_backend_config)(struct device *dev, struct iio_dev *indio_dev);
int (*read_block)(struct device *dev, int num, void *data);
int (*sw_mode_config)(struct iio_dev *indio_dev);
int (*reg_read)(struct ad7606_state *st, unsigned int addr);
@@ -144,23 +210,37 @@ struct ad7606_bus_ops {
unsigned int addr,
unsigned long mask,
unsigned int val);
+ int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask);
u16 (*rd_wr_cmd)(int addr, char isWriteOp);
};
+/**
+ * struct ad7606_bus_info - agregate ad7606_chip_info and ad7606_bus_ops
+ * @chip_info entry in the table of chips that describes this device
+ * @bops bus operations (SPI or parallel)
+ */
+struct ad7606_bus_info {
+ const struct ad7606_chip_info *chip_info;
+ const struct ad7606_bus_ops *bops;
+};
+
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
- const char *name, unsigned int id,
+ const struct ad7606_chip_info *info,
const struct ad7606_bus_ops *bops);
int ad7606_reset(struct ad7606_state *st);
-enum ad7606_supported_device_ids {
- ID_AD7605_4,
- ID_AD7606_8,
- ID_AD7606_6,
- ID_AD7606_4,
- ID_AD7606B,
- ID_AD7616,
-};
+extern const struct ad7606_chip_info ad7605_4_info;
+extern const struct ad7606_chip_info ad7606_8_info;
+extern const struct ad7606_chip_info ad7606_6_info;
+extern const struct ad7606_chip_info ad7606_4_info;
+extern const struct ad7606_chip_info ad7606b_info;
+extern const struct ad7606_chip_info ad7606c_16_info;
+extern const struct ad7606_chip_info ad7606c_18_info;
+extern const struct ad7606_chip_info ad7607_info;
+extern const struct ad7606_chip_info ad7608_info;
+extern const struct ad7606_chip_info ad7609_info;
+extern const struct ad7606_chip_info ad7616_info;
#ifdef CONFIG_PM_SLEEP
extern const struct dev_pm_ops ad7606_pm_ops;
diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c
index 02d8c309304e..a25182a3daa7 100644
--- a/drivers/iio/adc/ad7606_par.c
+++ b/drivers/iio/adc/ad7606_par.c
@@ -2,20 +2,95 @@
/*
* AD7606 Parallel Interface ADC driver
*
- * Copyright 2011 Analog Devices Inc.
+ * Copyright 2011 - 2024 Analog Devices Inc.
+ * Copyright 2024 BayLibre SAS.
*/
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/io.h>
+#include <linux/iio/backend.h>
#include <linux/iio/iio.h>
+
#include "ad7606.h"
+static const struct iio_chan_spec ad7606b_bi_channels[] = {
+ AD7606_BI_CHANNEL(0),
+ AD7606_BI_CHANNEL(1),
+ AD7606_BI_CHANNEL(2),
+ AD7606_BI_CHANNEL(3),
+ AD7606_BI_CHANNEL(4),
+ AD7606_BI_CHANNEL(5),
+ AD7606_BI_CHANNEL(6),
+ AD7606_BI_CHANNEL(7),
+};
+
+static int ad7606_bi_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int c, ret;
+
+ for (c = 0; c < indio_dev->num_channels; c++) {
+ if (test_bit(c, scan_mask))
+ ret = iio_backend_chan_enable(st->back, c);
+ else
+ ret = iio_backend_chan_disable(st->back, c);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad7606_bi_setup_iio_backend(struct device *dev, struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int ret, c;
+ struct iio_backend_data_fmt data = {
+ .sign_extend = true,
+ .enable = true,
+ };
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ /* If the device is iio_backend powered the PWM is mandatory */
+ if (!st->cnvst_pwm)
+ return dev_err_probe(st->dev, -EINVAL,
+ "A PWM is mandatory when using backend.\n");
+
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+
+ for (c = 0; c < indio_dev->num_channels; c++) {
+ ret = iio_backend_data_format_set(st->back, c, &data);
+ if (ret)
+ return ret;
+ }
+
+ indio_dev->channels = ad7606b_bi_channels;
+ indio_dev->num_channels = 8;
+
+ return 0;
+}
+
+static const struct ad7606_bus_ops ad7606_bi_bops = {
+ .iio_backend_config = ad7606_bi_setup_iio_backend,
+ .update_scan_mode = ad7606_bi_update_scan_mode,
+};
+
static int ad7606_par16_read_block(struct device *dev,
int count, void *buf)
{
@@ -89,12 +164,32 @@ static const struct ad7606_bus_ops ad7606_par8_bops = {
static int ad7606_par_probe(struct platform_device *pdev)
{
- const struct platform_device_id *id = platform_get_device_id(pdev);
+ const struct ad7606_chip_info *chip_info;
+ const struct platform_device_id *id;
struct resource *res;
void __iomem *addr;
resource_size_t remap_size;
int irq;
+ /*
+ * If a firmware node is available (ACPI or DT), platform_device_id is null
+ * and we must use get_match_data.
+ */
+ if (dev_fwnode(&pdev->dev)) {
+ chip_info = device_get_match_data(&pdev->dev);
+ if (device_property_present(&pdev->dev, "io-backends"))
+ /*
+ * If a backend is available ,call the core probe with backend
+ * bops, otherwise use the former bops.
+ */
+ return ad7606_probe(&pdev->dev, 0, NULL,
+ chip_info,
+ &ad7606_bi_bops);
+ } else {
+ id = platform_get_device_id(pdev);
+ chip_info = (const struct ad7606_chip_info *)id->driver_data;
+ }
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -105,26 +200,33 @@ static int ad7606_par_probe(struct platform_device *pdev)
remap_size = resource_size(res);
- return ad7606_probe(&pdev->dev, irq, addr,
- id->name, id->driver_data,
+ return ad7606_probe(&pdev->dev, irq, addr, chip_info,
remap_size > 1 ? &ad7606_par16_bops :
&ad7606_par8_bops);
}
static const struct platform_device_id ad7606_driver_ids[] = {
- { .name = "ad7605-4", .driver_data = ID_AD7605_4, },
- { .name = "ad7606-4", .driver_data = ID_AD7606_4, },
- { .name = "ad7606-6", .driver_data = ID_AD7606_6, },
- { .name = "ad7606-8", .driver_data = ID_AD7606_8, },
+ { .name = "ad7605-4", .driver_data = (kernel_ulong_t)&ad7605_4_info, },
+ { .name = "ad7606-4", .driver_data = (kernel_ulong_t)&ad7606_4_info, },
+ { .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, },
+ { .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, },
+ { .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, },
+ { .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, },
+ { .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, },
+ { .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, },
{ }
};
MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
static const struct of_device_id ad7606_of_match[] = {
- { .compatible = "adi,ad7605-4" },
- { .compatible = "adi,ad7606-4" },
- { .compatible = "adi,ad7606-6" },
- { .compatible = "adi,ad7606-8" },
+ { .compatible = "adi,ad7605-4", .data = &ad7605_4_info },
+ { .compatible = "adi,ad7606-4", .data = &ad7606_4_info },
+ { .compatible = "adi,ad7606-6", .data = &ad7606_6_info },
+ { .compatible = "adi,ad7606-8", .data = &ad7606_8_info },
+ { .compatible = "adi,ad7606b", .data = &ad7606b_info },
+ { .compatible = "adi,ad7607", .data = &ad7607_info },
+ { .compatible = "adi,ad7608", .data = &ad7608_info },
+ { .compatible = "adi,ad7609", .data = &ad7609_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad7606_of_match);
@@ -144,3 +246,4 @@ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(IIO_AD7606);
+MODULE_IMPORT_NS(IIO_BACKEND);
diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
index 62ec12195307..0662300cde8d 100644
--- a/drivers/iio/adc/ad7606_spi.c
+++ b/drivers/iio/adc/ad7606_spi.c
@@ -5,10 +5,10 @@
* Copyright 2011 Analog Devices Inc.
*/
+#include <linux/err.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
-#include <linux/err.h>
#include <linux/iio/iio.h>
#include "ad7606.h"
@@ -67,14 +67,26 @@ static const struct iio_chan_spec ad7616_sw_channels[] = {
static const struct iio_chan_spec ad7606b_sw_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7616_CHANNEL(0),
- AD7616_CHANNEL(1),
- AD7616_CHANNEL(2),
- AD7616_CHANNEL(3),
- AD7616_CHANNEL(4),
- AD7616_CHANNEL(5),
- AD7616_CHANNEL(6),
- AD7616_CHANNEL(7),
+ AD7606_SW_CHANNEL(0, 16),
+ AD7606_SW_CHANNEL(1, 16),
+ AD7606_SW_CHANNEL(2, 16),
+ AD7606_SW_CHANNEL(3, 16),
+ AD7606_SW_CHANNEL(4, 16),
+ AD7606_SW_CHANNEL(5, 16),
+ AD7606_SW_CHANNEL(6, 16),
+ AD7606_SW_CHANNEL(7, 16),
+};
+
+static const struct iio_chan_spec ad7606c_18_sw_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_SW_CHANNEL(0, 18),
+ AD7606_SW_CHANNEL(1, 18),
+ AD7606_SW_CHANNEL(2, 18),
+ AD7606_SW_CHANNEL(3, 18),
+ AD7606_SW_CHANNEL(4, 18),
+ AD7606_SW_CHANNEL(5, 18),
+ AD7606_SW_CHANNEL(6, 18),
+ AD7606_SW_CHANNEL(7, 18),
};
static const unsigned int ad7606B_oversampling_avail[9] = {
@@ -120,6 +132,32 @@ static int ad7606_spi_read_block(struct device *dev,
return 0;
}
+static int ad7606_spi_read_block14to16(struct device *dev,
+ int count, void *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer = {
+ .bits_per_word = 14,
+ .len = count * sizeof(u16),
+ .rx_buf = buf,
+ };
+
+ return spi_sync_transfer(spi, &xfer, 1);
+}
+
+static int ad7606_spi_read_block18to32(struct device *dev,
+ int count, void *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer = {
+ .bits_per_word = 18,
+ .len = count * sizeof(u32),
+ .rx_buf = buf,
+ };
+
+ return spi_sync_transfer(spi, &xfer, 1);
+}
+
static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr)
{
struct spi_device *spi = to_spi_device(st->dev);
@@ -283,10 +321,31 @@ static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
return 0;
}
+static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev)
+{
+ int ret;
+
+ ret = ad7606B_sw_mode_config(indio_dev);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = ad7606c_18_sw_channels;
+
+ return 0;
+}
+
static const struct ad7606_bus_ops ad7606_spi_bops = {
.read_block = ad7606_spi_read_block,
};
+static const struct ad7606_bus_ops ad7607_spi_bops = {
+ .read_block = ad7606_spi_read_block14to16,
+};
+
+static const struct ad7606_bus_ops ad7608_spi_bops = {
+ .read_block = ad7606_spi_read_block18to32,
+};
+
static const struct ad7606_bus_ops ad7616_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
@@ -296,7 +355,7 @@ static const struct ad7606_bus_ops ad7616_spi_bops = {
.sw_mode_config = ad7616_sw_mode_config,
};
-static const struct ad7606_bus_ops ad7606B_spi_bops = {
+static const struct ad7606_bus_ops ad7606b_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
@@ -305,46 +364,106 @@ static const struct ad7606_bus_ops ad7606B_spi_bops = {
.sw_mode_config = ad7606B_sw_mode_config,
};
+static const struct ad7606_bus_ops ad7606c_18_spi_bops = {
+ .read_block = ad7606_spi_read_block18to32,
+ .reg_read = ad7606_spi_reg_read,
+ .reg_write = ad7606_spi_reg_write,
+ .write_mask = ad7606_spi_write_mask,
+ .rd_wr_cmd = ad7606B_spi_rd_wr_cmd,
+ .sw_mode_config = ad7606c_18_sw_mode_config,
+};
+
+static const struct ad7606_bus_info ad7605_4_bus_info = {
+ .chip_info = &ad7605_4_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_8_bus_info = {
+ .chip_info = &ad7606_8_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_6_bus_info = {
+ .chip_info = &ad7606_6_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_4_bus_info = {
+ .chip_info = &ad7606_4_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606b_bus_info = {
+ .chip_info = &ad7606b_info,
+ .bops = &ad7606b_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606c_16_bus_info = {
+ .chip_info = &ad7606c_16_info,
+ .bops = &ad7606b_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606c_18_bus_info = {
+ .chip_info = &ad7606c_18_info,
+ .bops = &ad7606c_18_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7607_bus_info = {
+ .chip_info = &ad7607_info,
+ .bops = &ad7607_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7608_bus_info = {
+ .chip_info = &ad7608_info,
+ .bops = &ad7608_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7609_bus_info = {
+ .chip_info = &ad7609_info,
+ .bops = &ad7608_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7616_bus_info = {
+ .chip_info = &ad7616_info,
+ .bops = &ad7616_spi_bops,
+};
+
static int ad7606_spi_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
- const struct ad7606_bus_ops *bops;
-
- switch (id->driver_data) {
- case ID_AD7616:
- bops = &ad7616_spi_bops;
- break;
- case ID_AD7606B:
- bops = &ad7606B_spi_bops;
- break;
- default:
- bops = &ad7606_spi_bops;
- break;
- }
+ const struct ad7606_bus_info *bus_info = spi_get_device_match_data(spi);
return ad7606_probe(&spi->dev, spi->irq, NULL,
- id->name, id->driver_data,
- bops);
+ bus_info->chip_info, bus_info->bops);
}
static const struct spi_device_id ad7606_id_table[] = {
- { "ad7605-4", ID_AD7605_4 },
- { "ad7606-4", ID_AD7606_4 },
- { "ad7606-6", ID_AD7606_6 },
- { "ad7606-8", ID_AD7606_8 },
- { "ad7606b", ID_AD7606B },
- { "ad7616", ID_AD7616 },
+ { "ad7605-4", (kernel_ulong_t)&ad7605_4_bus_info },
+ { "ad7606-4", (kernel_ulong_t)&ad7606_4_bus_info },
+ { "ad7606-6", (kernel_ulong_t)&ad7606_6_bus_info },
+ { "ad7606-8", (kernel_ulong_t)&ad7606_8_bus_info },
+ { "ad7606b", (kernel_ulong_t)&ad7606b_bus_info },
+ { "ad7606c-16", (kernel_ulong_t)&ad7606c_16_bus_info },
+ { "ad7606c-18", (kernel_ulong_t)&ad7606c_18_bus_info },
+ { "ad7607", (kernel_ulong_t)&ad7607_bus_info },
+ { "ad7608", (kernel_ulong_t)&ad7608_bus_info },
+ { "ad7609", (kernel_ulong_t)&ad7609_bus_info },
+ { "ad7616", (kernel_ulong_t)&ad7616_bus_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7606_id_table);
static const struct of_device_id ad7606_of_match[] = {
- { .compatible = "adi,ad7605-4" },
- { .compatible = "adi,ad7606-4" },
- { .compatible = "adi,ad7606-6" },
- { .compatible = "adi,ad7606-8" },
- { .compatible = "adi,ad7606b" },
- { .compatible = "adi,ad7616" },
+ { .compatible = "adi,ad7605-4", .data = &ad7605_4_bus_info },
+ { .compatible = "adi,ad7606-4", .data = &ad7606_4_bus_info },
+ { .compatible = "adi,ad7606-6", .data = &ad7606_6_bus_info },
+ { .compatible = "adi,ad7606-8", .data = &ad7606_8_bus_info },
+ { .compatible = "adi,ad7606b", .data = &ad7606b_bus_info },
+ { .compatible = "adi,ad7606c-16", .data = &ad7606c_16_bus_info },
+ { .compatible = "adi,ad7606c-18", .data = &ad7606c_18_bus_info },
+ { .compatible = "adi,ad7607", .data = &ad7607_bus_info },
+ { .compatible = "adi,ad7608", .data = &ad7608_bus_info },
+ { .compatible = "adi,ad7609", .data = &ad7609_bus_info },
+ { .compatible = "adi,ad7616", .data = &ad7616_bus_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad7606_of_match);
diff --git a/drivers/iio/adc/ad7625.c b/drivers/iio/adc/ad7625.c
new file mode 100644
index 000000000000..ddd1e4a26429
--- /dev/null
+++ b/drivers/iio/adc/ad7625.c
@@ -0,0 +1,684 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Analog Devices Inc. AD7625 ADC driver
+ *
+ * Copyright 2024 Analog Devices Inc.
+ * Copyright 2024 BayLibre, SAS
+ *
+ * Note that this driver requires the AXI ADC IP block configured for
+ * LVDS to function. See Documentation/iio/ad7625.rst for more
+ * information.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/backend.h>
+#include <linux/iio/iio.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#define AD7625_INTERNAL_REF_MV 4096
+#define AD7960_MAX_NBW_FREQ (2 * MEGA)
+
+struct ad7625_timing_spec {
+ /* Max conversion high time (t_{CNVH}). */
+ unsigned int conv_high_ns;
+ /* Max conversion to MSB delay (t_{MSB}). */
+ unsigned int conv_msb_ns;
+};
+
+struct ad7625_chip_info {
+ const char *name;
+ const unsigned int max_sample_freq_hz;
+ const struct ad7625_timing_spec *timing_spec;
+ const struct iio_chan_spec chan_spec;
+ const bool has_power_down_state;
+ const bool has_bandwidth_control;
+ const bool has_internal_vref;
+};
+
+/* AD7625_CHAN_SPEC - Define a chan spec structure for a specific chip */
+#define AD7625_CHAN_SPEC(_bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .differential = 1, \
+ .channel = 0, \
+ .channel2 = 1, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = 0, \
+ .scan_type.sign = 's', \
+ .scan_type.storagebits = (_bits) > 16 ? 32 : 16, \
+ .scan_type.realbits = (_bits), \
+}
+
+struct ad7625_state {
+ const struct ad7625_chip_info *info;
+ struct iio_backend *back;
+ /* rate of the clock gated by the "clk_gate" PWM */
+ u32 ref_clk_rate_hz;
+ /* PWM burst signal for transferring acquired data to the host */
+ struct pwm_device *clk_gate_pwm;
+ /*
+ * PWM control signal for initiating data conversion. Analog
+ * inputs are sampled beginning on this signal's rising edge.
+ */
+ struct pwm_device *cnv_pwm;
+ /*
+ * Waveforms containing the last-requested and rounded
+ * properties for the clk_gate and cnv PWMs
+ */
+ struct pwm_waveform clk_gate_wf;
+ struct pwm_waveform cnv_wf;
+ unsigned int vref_mv;
+ u32 sampling_freq_hz;
+ /*
+ * Optional GPIOs for controlling device state. EN0 and EN1
+ * determine voltage reference configuration and on/off state.
+ * EN2 controls the device -3dB bandwidth (and by extension, max
+ * sample rate). EN3 controls the VCM reference output. EN2 and
+ * EN3 are only present for the AD796x devices.
+ */
+ struct gpio_desc *en_gpios[4];
+ bool can_power_down;
+ bool can_refin;
+ bool can_ref_4v096;
+ /*
+ * Indicate whether the bandwidth can be narrow (9MHz).
+ * When true, device sample rate must also be < 2MSPS.
+ */
+ bool can_narrow_bandwidth;
+ /* Indicate whether the bandwidth can be wide (28MHz). */
+ bool can_wide_bandwidth;
+ bool can_ref_5v;
+ bool can_snooze;
+ bool can_test_pattern;
+ /* Indicate whether there is a REFIN supply connected */
+ bool have_refin;
+};
+
+static const struct ad7625_timing_spec ad7625_timing_spec = {
+ .conv_high_ns = 40,
+ .conv_msb_ns = 145,
+};
+
+static const struct ad7625_timing_spec ad7626_timing_spec = {
+ .conv_high_ns = 40,
+ .conv_msb_ns = 80,
+};
+
+/*
+ * conv_msb_ns is set to 0 instead of the datasheet maximum of 200ns to
+ * avoid exceeding the minimum conversion time, i.e. it is effectively
+ * modulo 200 and offset by a full period. Values greater than or equal
+ * to the period would be rejected by the PWM API.
+ */
+static const struct ad7625_timing_spec ad7960_timing_spec = {
+ .conv_high_ns = 80,
+ .conv_msb_ns = 0,
+};
+
+static const struct ad7625_chip_info ad7625_chip_info = {
+ .name = "ad7625",
+ .max_sample_freq_hz = 6 * MEGA,
+ .timing_spec = &ad7625_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = false,
+ .has_bandwidth_control = false,
+ .has_internal_vref = true,
+};
+
+static const struct ad7625_chip_info ad7626_chip_info = {
+ .name = "ad7626",
+ .max_sample_freq_hz = 10 * MEGA,
+ .timing_spec = &ad7626_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = true,
+ .has_bandwidth_control = false,
+ .has_internal_vref = true,
+};
+
+static const struct ad7625_chip_info ad7960_chip_info = {
+ .name = "ad7960",
+ .max_sample_freq_hz = 5 * MEGA,
+ .timing_spec = &ad7960_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(18),
+ .has_power_down_state = true,
+ .has_bandwidth_control = true,
+ .has_internal_vref = false,
+};
+
+static const struct ad7625_chip_info ad7961_chip_info = {
+ .name = "ad7961",
+ .max_sample_freq_hz = 5 * MEGA,
+ .timing_spec = &ad7960_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = true,
+ .has_bandwidth_control = true,
+ .has_internal_vref = false,
+};
+
+enum ad7960_mode {
+ AD7960_MODE_POWER_DOWN,
+ AD7960_MODE_SNOOZE,
+ AD7960_MODE_NARROW_BANDWIDTH,
+ AD7960_MODE_WIDE_BANDWIDTH,
+ AD7960_MODE_TEST_PATTERN,
+};
+
+static int ad7625_set_sampling_freq(struct ad7625_state *st, u32 freq)
+{
+ u32 target;
+ struct pwm_waveform clk_gate_wf = { }, cnv_wf = { };
+ int ret;
+
+ target = DIV_ROUND_UP(NSEC_PER_SEC, freq);
+ cnv_wf.period_length_ns = clamp(target, 100, 10 * KILO);
+
+ /*
+ * Use the maximum conversion time t_CNVH from the datasheet as
+ * the duty_cycle for ref_clk, cnv, and clk_gate
+ */
+ cnv_wf.duty_length_ns = st->info->timing_spec->conv_high_ns;
+
+ ret = pwm_round_waveform_might_sleep(st->cnv_pwm, &cnv_wf);
+ if (ret)
+ return ret;
+
+ /*
+ * Set up the burst signal for transferring data. period and
+ * offset should mirror the CNV signal
+ */
+ clk_gate_wf.period_length_ns = cnv_wf.period_length_ns;
+
+ clk_gate_wf.duty_length_ns = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC *
+ st->info->chan_spec.scan_type.realbits,
+ st->ref_clk_rate_hz);
+
+ /* max t_MSB from datasheet */
+ clk_gate_wf.duty_offset_ns = st->info->timing_spec->conv_msb_ns;
+
+ ret = pwm_round_waveform_might_sleep(st->clk_gate_pwm, &clk_gate_wf);
+ if (ret)
+ return ret;
+
+ st->cnv_wf = cnv_wf;
+ st->clk_gate_wf = clk_gate_wf;
+
+ /* TODO: Add a rounding API for PWMs that can simplify this */
+ target = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz, freq);
+ st->sampling_freq_hz = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz,
+ target);
+
+ return 0;
+}
+
+static int ad7625_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long info)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->sampling_freq_hz;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->vref_mv;
+ *val2 = chan->scan_type.realbits - 1;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad7625_set_sampling_freq(st, val);
+ unreachable();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_parse_mode(struct device *dev, struct ad7625_state *st,
+ int num_gpios)
+{
+ bool en_always_on[4], en_always_off[4];
+ bool en_may_be_on[4], en_may_be_off[4];
+ char en_gpio_buf[4];
+ char always_on_buf[18];
+ int i;
+
+ for (i = 0; i < num_gpios; i++) {
+ snprintf(en_gpio_buf, sizeof(en_gpio_buf), "en%d", i);
+ snprintf(always_on_buf, sizeof(always_on_buf),
+ "adi,en%d-always-on", i);
+ /* Set the device to 0b0000 (power-down mode) by default */
+ st->en_gpios[i] = devm_gpiod_get_optional(dev, en_gpio_buf,
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->en_gpios[i]))
+ return dev_err_probe(dev, PTR_ERR(st->en_gpios[i]),
+ "failed to get EN%d GPIO\n", i);
+
+ en_always_on[i] = device_property_read_bool(dev, always_on_buf);
+ if (st->en_gpios[i] && en_always_on[i])
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have adi,en%d-always-on and en%d-gpios\n", i, i);
+
+ en_may_be_off[i] = !en_always_on[i];
+ en_may_be_on[i] = en_always_on[i] || st->en_gpios[i];
+ en_always_off[i] = !en_always_on[i] && !st->en_gpios[i];
+ }
+
+ /*
+ * Power down is mode 0bXX00, but not all devices have a valid
+ * power down state.
+ */
+ st->can_power_down = en_may_be_off[1] && en_may_be_off[0] &&
+ st->info->has_power_down_state;
+ /*
+ * The REFIN pin can take a 1.2V (AD762x) or 2.048V (AD796x)
+ * external reference when the mode is 0bXX01.
+ */
+ st->can_refin = en_may_be_off[1] && en_may_be_on[0];
+ /* 4.096V can be applied to REF when the EN mode is 0bXX10. */
+ st->can_ref_4v096 = en_may_be_on[1] && en_may_be_off[0];
+
+ /* Avoid AD796x-specific setup if the part is an AD762x */
+ if (num_gpios == 2)
+ return 0;
+
+ /* mode 0b1100 (AD796x) is invalid */
+ if (en_always_on[3] && en_always_on[2] &&
+ en_always_off[1] && en_always_off[0])
+ return dev_err_probe(dev, -EINVAL,
+ "EN GPIOs set to invalid mode 0b1100\n");
+ /*
+ * 5V can be applied to the AD796x REF pin when the EN mode is
+ * the same (0bX001 or 0bX101) as for can_refin, and REFIN is
+ * 0V.
+ */
+ st->can_ref_5v = st->can_refin;
+ /*
+ * Bandwidth (AD796x) is controlled solely by EN2. If it's
+ * specified and not hard-wired, then we can configure it to
+ * change the bandwidth between 28MHz and 9MHz.
+ */
+ st->can_narrow_bandwidth = en_may_be_on[2];
+ /* Wide bandwidth mode is possible if EN2 can be 0. */
+ st->can_wide_bandwidth = en_may_be_off[2];
+ /* Snooze mode (AD796x) is 0bXX11 when REFIN = 0V. */
+ st->can_snooze = en_may_be_on[1] && en_may_be_on[0];
+ /* Test pattern mode (AD796x) is 0b0100. */
+ st->can_test_pattern = en_may_be_off[3] && en_may_be_on[2] &&
+ en_may_be_off[1] && en_may_be_off[0];
+
+ return 0;
+}
+
+/* Set EN1 and EN0 based on reference voltage source */
+static void ad7625_set_en_gpios_for_vref(struct ad7625_state *st,
+ bool have_refin, int ref_mv)
+{
+ if (have_refin || ref_mv == 5000) {
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+ } else if (ref_mv == 4096) {
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+ } else {
+ /*
+ * Unreachable by AD796x, since the driver will error if
+ * neither REF nor REFIN is provided
+ */
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+ }
+}
+
+static int ad7960_set_mode(struct ad7625_state *st, enum ad7960_mode mode,
+ bool have_refin, int ref_mv)
+{
+ switch (mode) {
+ case AD7960_MODE_POWER_DOWN:
+ if (!st->can_power_down)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 0);
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+
+ return 0;
+
+ case AD7960_MODE_SNOOZE:
+ if (!st->can_snooze)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+
+ return 0;
+
+ case AD7960_MODE_NARROW_BANDWIDTH:
+ if (!st->can_narrow_bandwidth)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 1);
+ ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv);
+
+ return 0;
+
+ case AD7960_MODE_WIDE_BANDWIDTH:
+ if (!st->can_wide_bandwidth)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 0);
+ ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv);
+
+ return 0;
+
+ case AD7960_MODE_TEST_PATTERN:
+ if (!st->can_test_pattern)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[3], 0);
+ gpiod_set_value_cansleep(st->en_gpios[2], 1);
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = pwm_set_waveform_might_sleep(st->cnv_pwm, &st->cnv_wf, false);
+ if (ret)
+ return ret;
+
+ ret = pwm_set_waveform_might_sleep(st->clk_gate_pwm,
+ &st->clk_gate_wf, false);
+ if (ret) {
+ /* Disable cnv PWM if clk_gate setup failed */
+ pwm_disable(st->cnv_pwm);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad7625_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ pwm_disable(st->clk_gate_pwm);
+ pwm_disable(st->cnv_pwm);
+
+ return 0;
+}
+
+static const struct iio_info ad7625_info = {
+ .read_raw = ad7625_read_raw,
+ .write_raw = ad7625_write_raw,
+};
+
+static const struct iio_buffer_setup_ops ad7625_buffer_setup_ops = {
+ .preenable = &ad7625_buffer_preenable,
+ .postdisable = &ad7625_buffer_postdisable,
+};
+
+static int devm_ad7625_pwm_get(struct device *dev,
+ struct ad7625_state *st)
+{
+ struct clk *ref_clk;
+ u32 ref_clk_rate_hz;
+
+ st->cnv_pwm = devm_pwm_get(dev, "cnv");
+ if (IS_ERR(st->cnv_pwm))
+ return dev_err_probe(dev, PTR_ERR(st->cnv_pwm),
+ "failed to get cnv pwm\n");
+
+ /* Preemptively disable the PWM in case it was enabled at boot */
+ pwm_disable(st->cnv_pwm);
+
+ st->clk_gate_pwm = devm_pwm_get(dev, "clk_gate");
+ if (IS_ERR(st->clk_gate_pwm))
+ return dev_err_probe(dev, PTR_ERR(st->clk_gate_pwm),
+ "failed to get clk_gate pwm\n");
+
+ /* Preemptively disable the PWM in case it was enabled at boot */
+ pwm_disable(st->clk_gate_pwm);
+
+ ref_clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(ref_clk))
+ return dev_err_probe(dev, PTR_ERR(ref_clk),
+ "failed to get ref_clk");
+
+ ref_clk_rate_hz = clk_get_rate(ref_clk);
+ if (!ref_clk_rate_hz)
+ return dev_err_probe(dev, -EINVAL,
+ "failed to get ref_clk rate");
+
+ st->ref_clk_rate_hz = ref_clk_rate_hz;
+
+ return 0;
+}
+
+/*
+ * There are three required input voltages for each device, plus two
+ * conditionally-optional (depending on part) REF and REFIN voltages
+ * where their validity depends upon the EN pin configuration.
+ *
+ * Power-up info for the device says to bring up vio, then vdd2, then
+ * vdd1, so list them in that order in the regulator_names array.
+ *
+ * The reference voltage source is determined like so:
+ * - internal reference: neither REF or REFIN is connected (invalid for
+ * AD796x)
+ * - internal buffer, external reference: REF not connected, REFIN
+ * connected
+ * - external reference: REF connected, REFIN not connected
+ */
+static int devm_ad7625_regulator_setup(struct device *dev,
+ struct ad7625_state *st)
+{
+ static const char * const regulator_names[] = { "vio", "vdd2", "vdd1" };
+ int ret, ref_mv;
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
+ regulator_names);
+ if (ret)
+ return ret;
+
+ ret = devm_regulator_get_enable_read_voltage(dev, "ref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to get REF voltage\n");
+
+ ref_mv = ret == -ENODEV ? 0 : ret / 1000;
+
+ ret = devm_regulator_get_enable_optional(dev, "refin");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to get REFIN voltage\n");
+
+ st->have_refin = ret != -ENODEV;
+
+ if (st->have_refin && !st->can_refin)
+ return dev_err_probe(dev, -EINVAL,
+ "REFIN provided in unsupported mode\n");
+
+ if (!st->info->has_internal_vref && !st->have_refin && !ref_mv)
+ return dev_err_probe(dev, -EINVAL,
+ "Need either REFIN or REF");
+
+ if (st->have_refin && ref_mv)
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have both REFIN and REF supplies\n");
+
+ if (ref_mv == 4096 && !st->can_ref_4v096)
+ return dev_err_probe(dev, -EINVAL,
+ "REF is 4.096V in unsupported mode\n");
+
+ if (ref_mv == 5000 && !st->can_ref_5v)
+ return dev_err_probe(dev, -EINVAL,
+ "REF is 5V in unsupported mode\n");
+
+ st->vref_mv = ref_mv ?: AD7625_INTERNAL_REF_MV;
+
+ return 0;
+}
+
+static int ad7625_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct iio_dev *indio_dev;
+ struct ad7625_state *st;
+ int ret;
+ u32 default_sample_freq;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->info = device_get_match_data(dev);
+ if (!st->info)
+ return dev_err_probe(dev, -EINVAL, "no chip info\n");
+
+ if (device_property_read_bool(dev, "adi,no-dco"))
+ return dev_err_probe(dev, -EINVAL,
+ "self-clocked mode not supported\n");
+
+ if (st->info->has_bandwidth_control)
+ ret = ad7625_parse_mode(dev, st, 4);
+ else
+ ret = ad7625_parse_mode(dev, st, 2);
+
+ if (ret)
+ return ret;
+
+ ret = devm_ad7625_regulator_setup(dev, st);
+ if (ret)
+ return ret;
+
+ /* Set the device mode based on detected EN configuration. */
+ if (!st->info->has_bandwidth_control) {
+ ad7625_set_en_gpios_for_vref(st, st->have_refin, st->vref_mv);
+ } else {
+ /*
+ * If neither sampling mode is available, then report an error,
+ * since the other modes are not useful defaults.
+ */
+ if (st->can_wide_bandwidth) {
+ ret = ad7960_set_mode(st, AD7960_MODE_WIDE_BANDWIDTH,
+ st->have_refin, st->vref_mv);
+ } else if (st->can_narrow_bandwidth) {
+ ret = ad7960_set_mode(st, AD7960_MODE_NARROW_BANDWIDTH,
+ st->have_refin, st->vref_mv);
+ } else {
+ return dev_err_probe(dev, -EINVAL,
+ "couldn't set device to wide or narrow bandwidth modes\n");
+ }
+
+ if (ret)
+ return dev_err_probe(dev, -EINVAL,
+ "failed to set EN pins\n");
+ }
+
+ ret = devm_ad7625_pwm_get(dev, st);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = &st->info->chan_spec;
+ indio_dev->num_channels = 1;
+ indio_dev->name = st->info->name;
+ indio_dev->info = &ad7625_info;
+ indio_dev->setup_ops = &ad7625_buffer_setup_ops;
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (IS_ERR(st->back))
+ return dev_err_probe(dev, PTR_ERR(st->back),
+ "failed to get IIO backend");
+
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+
+ /*
+ * Set the initial sampling frequency to the maximum, unless the
+ * AD796x device is limited to narrow bandwidth by EN2 == 1, in
+ * which case the sampling frequency should be limited to 2MSPS
+ */
+ default_sample_freq = st->info->max_sample_freq_hz;
+ if (st->info->has_bandwidth_control && !st->can_wide_bandwidth)
+ default_sample_freq = AD7960_MAX_NBW_FREQ;
+
+ ret = ad7625_set_sampling_freq(st, default_sample_freq);
+ if (ret)
+ dev_err_probe(dev, ret,
+ "failed to set valid sampling frequency\n");
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad7625_of_match[] = {
+ { .compatible = "adi,ad7625", .data = &ad7625_chip_info },
+ { .compatible = "adi,ad7626", .data = &ad7626_chip_info },
+ { .compatible = "adi,ad7960", .data = &ad7960_chip_info },
+ { .compatible = "adi,ad7961", .data = &ad7961_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7625_of_match);
+
+static const struct platform_device_id ad7625_device_ids[] = {
+ { .name = "ad7625", .driver_data = (kernel_ulong_t)&ad7625_chip_info },
+ { .name = "ad7626", .driver_data = (kernel_ulong_t)&ad7626_chip_info },
+ { .name = "ad7960", .driver_data = (kernel_ulong_t)&ad7960_chip_info },
+ { .name = "ad7961", .driver_data = (kernel_ulong_t)&ad7961_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, ad7625_device_ids);
+
+static struct platform_driver ad7625_driver = {
+ .probe = ad7625_probe,
+ .driver = {
+ .name = "ad7625",
+ .of_match_table = ad7625_of_match,
+ },
+ .id_table = ad7625_device_ids,
+};
+module_platform_driver(ad7625_driver);
+
+MODULE_AUTHOR("Trevor Gamblin <tgamblin@baylibre.com>");
+MODULE_DESCRIPTION("Analog Devices AD7625 ADC");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_IMPORT_NS(IIO_BACKEND);
diff --git a/drivers/iio/adc/ad7779.c b/drivers/iio/adc/ad7779.c
new file mode 100644
index 000000000000..2537dab69a35
--- /dev/null
+++ b/drivers/iio/adc/ad7779.c
@@ -0,0 +1,914 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD7770, AD7771, AD7779 ADC
+ *
+ * Copyright 2023-2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define AD7779_SPI_READ_CMD BIT(7)
+
+#define AD7779_DISABLE_SD BIT(7)
+
+#define AD7779_REG_CH_DISABLE 0x08
+#define AD7779_REG_CH_SYNC_OFFSET(ch) (0x09 + (ch))
+#define AD7779_REG_CH_CONFIG(ch) (0x00 + (ch))
+#define AD7779_REG_GENERAL_USER_CONFIG_1 0x11
+#define AD7779_REG_GENERAL_USER_CONFIG_2 0x12
+#define AD7779_REG_GENERAL_USER_CONFIG_3 0x13
+#define AD7779_REG_DOUT_FORMAT 0x14
+#define AD7779_REG_ADC_MUX_CONFIG 0x15
+#define AD7779_REG_GPIO_CONFIG 0x17
+#define AD7779_REG_BUFFER_CONFIG_1 0x19
+#define AD7779_REG_GLOBAL_MUX_CONFIG 0x16
+#define AD7779_REG_BUFFER_CONFIG_2 0x1A
+#define AD7779_REG_GPIO_DATA 0x18
+#define AD7779_REG_CH_OFFSET_UPPER_BYTE(ch) (0x1C + (ch) * 6)
+#define AD7779_REG_CH_OFFSET_LOWER_BYTE(ch) (0x1E + (ch) * 6)
+#define AD7779_REG_CH_GAIN_UPPER_BYTE(ch) (0x1F + (ch) * 6)
+#define AD7779_REG_CH_OFFSET_MID_BYTE(ch) (0x1D + (ch) * 6)
+#define AD7779_REG_CH_GAIN_MID_BYTE(ch) (0x20 + (ch) * 6)
+#define AD7779_REG_CH_ERR_REG(ch) (0x4C + (ch))
+#define AD7779_REG_CH0_1_SAT_ERR 0x54
+#define AD7779_REG_CH_GAIN_LOWER_BYTE(ch) (0x21 + (ch) * 6)
+#define AD7779_REG_CH2_3_SAT_ERR 0x55
+#define AD7779_REG_CH4_5_SAT_ERR 0x56
+#define AD7779_REG_CH6_7_SAT_ERR 0x57
+#define AD7779_REG_CHX_ERR_REG_EN 0x58
+#define AD7779_REG_GEN_ERR_REG_1 0x59
+#define AD7779_REG_GEN_ERR_REG_1_EN 0x5A
+#define AD7779_REG_GEN_ERR_REG_2 0x5B
+#define AD7779_REG_GEN_ERR_REG_2_EN 0x5C
+#define AD7779_REG_STATUS_REG_1 0x5D
+#define AD7779_REG_STATUS_REG_2 0x5E
+#define AD7779_REG_STATUS_REG_3 0x5F
+#define AD7779_REG_SRC_N_MSB 0x60
+#define AD7779_REG_SRC_N_LSB 0x61
+#define AD7779_REG_SRC_IF_MSB 0x62
+#define AD7779_REG_SRC_IF_LSB 0x63
+#define AD7779_REG_SRC_UPDATE 0x64
+
+#define AD7779_FILTER_MSK BIT(6)
+#define AD7779_MOD_POWERMODE_MSK BIT(6)
+#define AD7779_MOD_PDB_REFOUT_MSK BIT(4)
+#define AD7779_MOD_SPI_EN_MSK BIT(4)
+#define AD7779_USRMOD_INIT_MSK GENMASK(6, 4)
+
+/* AD7779_REG_DOUT_FORMAT */
+#define AD7779_DOUT_FORMAT_MSK GENMASK(7, 6)
+#define AD7779_DOUT_HEADER_FORMAT BIT(5)
+#define AD7779_DCLK_CLK_DIV_MSK GENMASK(3, 1)
+
+#define AD7779_REFMUX_CTRL_MSK GENMASK(7, 6)
+#define AD7779_SPI_CRC_EN_MSK BIT(0)
+
+#define AD7779_MAXCLK_LOWPOWER (4096 * HZ_PER_KHZ)
+#define AD7779_NUM_CHANNELS 8
+#define AD7779_RESET_BUF_SIZE 8
+#define AD7779_CHAN_DATA_SIZE 4
+
+#define AD7779_LOWPOWER_DIV 512
+#define AD7779_HIGHPOWER_DIV 2048
+
+#define AD7779_SINC3_MAXFREQ (16 * HZ_PER_KHZ)
+#define AD7779_SINC5_MAXFREQ (128 * HZ_PER_KHZ)
+
+#define AD7779_DEFAULT_SAMPLING_FREQ (8 * HZ_PER_KHZ)
+#define AD7779_DEFAULT_SAMPLING_2LINE (4 * HZ_PER_KHZ)
+#define AD7779_DEFAULT_SAMPLING_1LINE (2 * HZ_PER_KHZ)
+
+#define AD7779_SPIMODE_MAX_SAMP_FREQ (16 * HZ_PER_KHZ)
+
+#define GAIN_REL 0x555555
+#define AD7779_FREQ_MSB_MSK GENMASK(15, 8)
+#define AD7779_FREQ_LSB_MSK GENMASK(7, 0)
+#define AD7779_UPPER GENMASK(23, 16)
+#define AD7779_MID GENMASK(15, 8)
+#define AD7779_LOWER GENMASK(7, 0)
+
+#define AD7779_REG_MSK GENMASK(6, 0)
+
+#define AD7779_CRC8_POLY 0x07
+DECLARE_CRC8_TABLE(ad7779_crc8_table);
+
+enum ad7779_filter {
+ AD7779_SINC3,
+ AD7779_SINC5,
+};
+
+enum ad7779_variant {
+ ad7770,
+ ad7771,
+ ad7779,
+};
+
+enum ad7779_power_mode {
+ AD7779_LOW_POWER,
+ AD7779_HIGH_POWER,
+};
+
+struct ad7779_chip_info {
+ const char *name;
+ struct iio_chan_spec const *channels;
+};
+
+struct ad7779_state {
+ struct spi_device *spi;
+ const struct ad7779_chip_info *chip_info;
+ struct clk *mclk;
+ struct iio_trigger *trig;
+ struct completion completion;
+ unsigned int sampling_freq;
+ enum ad7779_filter filter_enabled;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ struct {
+ u32 chans[8];
+ aligned_s64 timestamp;
+ } data __aligned(IIO_DMA_MINALIGN);
+ u32 spidata_tx[8];
+ u8 reg_rx_buf[3];
+ u8 reg_tx_buf[3];
+ u8 reset_buf[8];
+};
+
+static const char * const ad7779_filter_type[] = {
+ [AD7779_SINC3] = "sinc3",
+ [AD7779_SINC5] = "sinc5",
+};
+
+static const char * const ad7779_power_supplies[] = {
+ "avdd1", "avdd2", "avdd4",
+};
+
+static int ad7779_spi_read(struct ad7779_state *st, u8 reg, u8 *rbuf)
+{
+ int ret;
+ u8 crc_buf[2];
+ u8 exp_crc;
+ struct spi_transfer t = {
+ .tx_buf = st->reg_tx_buf,
+ .rx_buf = st->reg_rx_buf,
+ };
+
+ st->reg_tx_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
+ st->reg_tx_buf[1] = 0;
+
+ if (reg == AD7779_REG_GEN_ERR_REG_1_EN) {
+ t.len = 2;
+ } else {
+ t.len = 3;
+ st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
+ t.len - 1, 0);
+ }
+
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret)
+ return ret;
+
+ crc_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
+ crc_buf[1] = st->reg_rx_buf[1];
+ exp_crc = crc8(ad7779_crc8_table, crc_buf, ARRAY_SIZE(crc_buf), 0);
+ if (reg != AD7779_REG_GEN_ERR_REG_1_EN && exp_crc != st->reg_rx_buf[2]) {
+ dev_err(&st->spi->dev, "Bad CRC %x, expected %x",
+ st->reg_rx_buf[2], exp_crc);
+ return -EINVAL;
+ }
+ *rbuf = st->reg_rx_buf[1];
+
+ return 0;
+}
+
+static int ad7779_spi_write(struct ad7779_state *st, u8 reg, u8 val)
+{
+ u8 length = 3;
+
+ st->reg_tx_buf[0] = FIELD_GET(AD7779_REG_MSK, reg);
+ st->reg_tx_buf[1] = val;
+ if (reg == AD7779_REG_GEN_ERR_REG_1_EN)
+ length = 2;
+ else
+ st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
+ length - 1, 0);
+
+ return spi_write(st->spi, st->reg_tx_buf, length);
+}
+
+static int ad7779_spi_write_mask(struct ad7779_state *st, u8 reg, u8 mask,
+ u8 val)
+{
+ int ret;
+ u8 regval, data;
+
+ ret = ad7779_spi_read(st, reg, &data);
+ if (ret)
+ return ret;
+
+ regval = (data & ~mask) | (val & mask);
+
+ if (regval == data)
+ return 0;
+
+ return ad7779_spi_write(st, reg, regval);
+}
+
+static int ad7779_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ u8 rval;
+ int ret;
+
+ if (readval) {
+ ret = ad7779_spi_read(st, reg, &rval);
+ *readval = rval;
+ return ret;
+ }
+
+ return ad7779_spi_write(st, reg, writeval);
+}
+
+static int ad7779_set_sampling_frequency(struct ad7779_state *st,
+ unsigned int sampling_freq)
+{
+ int ret;
+ unsigned int dec;
+ unsigned int frac;
+ unsigned int div;
+ unsigned int decimal;
+ unsigned int freq_khz;
+
+ if (st->filter_enabled == AD7779_SINC3 &&
+ sampling_freq > AD7779_SINC3_MAXFREQ)
+ return -EINVAL;
+
+ if (st->filter_enabled == AD7779_SINC5 &&
+ sampling_freq > AD7779_SINC5_MAXFREQ)
+ return -EINVAL;
+
+ if (sampling_freq > AD7779_SPIMODE_MAX_SAMP_FREQ)
+ return -EINVAL;
+
+ div = AD7779_HIGHPOWER_DIV;
+
+ freq_khz = sampling_freq / HZ_PER_KHZ;
+ dec = div / freq_khz;
+ frac = div % freq_khz;
+
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, dec));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, dec));
+ if (ret)
+ return ret;
+
+ if (frac) {
+ /*
+ * In order to obtain the first three decimals of the decimation
+ * the initial number is multiplied with 10^3 prior to the
+ * division, then the original division result is subtracted and
+ * the number is divided by 10^3.
+ */
+ decimal = ((mult_frac(div, KILO, freq_khz) - dec * KILO) << 16)
+ / KILO;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, decimal));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, decimal));
+ if (ret)
+ return ret;
+ } else {
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, 0x0));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, 0x0));
+ if (ret)
+ return ret;
+ }
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, BIT(0));
+ if (ret)
+ return ret;
+
+ /* SRC update settling time */
+ fsleep(15);
+
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, 0x0);
+ if (ret)
+ return ret;
+
+ /* SRC update settling time */
+ fsleep(15);
+
+ st->sampling_freq = sampling_freq;
+
+ return 0;
+}
+
+static int ad7779_get_filter(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ u8 temp;
+ int ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_GENERAL_USER_CONFIG_2, &temp);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(AD7779_FILTER_MSK, temp);
+}
+
+static int ad7779_set_filter(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ unsigned int mode)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = ad7779_spi_write_mask(st,
+ AD7779_REG_GENERAL_USER_CONFIG_2,
+ AD7779_FILTER_MSK,
+ FIELD_PREP(AD7779_FILTER_MSK, mode));
+ if (ret)
+ return ret;
+
+ ret = ad7779_set_sampling_frequency(st, st->sampling_freq);
+ if (ret)
+ return ret;
+
+ st->filter_enabled = mode;
+
+ return 0;
+}
+
+static int ad7779_get_calibscale(struct ad7779_state *st, int channel)
+{
+ int ret;
+ u8 calibscale[3];
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
+ &calibscale[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
+ &calibscale[1]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
+ &calibscale[2]);
+ if (ret)
+ return ret;
+
+ return get_unaligned_be24(calibscale);
+}
+
+static int ad7779_set_calibscale(struct ad7779_state *st, int channel, int val)
+{
+ int ret;
+ unsigned int gain;
+ u8 gain_bytes[3];
+
+ /*
+ * The gain value is relative to 0x555555, which represents a gain of 1
+ */
+ gain = DIV_ROUND_CLOSEST_ULL((u64)val * 5592405LL, MEGA);
+ put_unaligned_be24(gain, gain_bytes);
+ ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
+ gain_bytes[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
+ gain_bytes[1]);
+ if (ret)
+ return ret;
+
+ return ad7779_spi_write(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
+ gain_bytes[2]);
+}
+
+static int ad7779_get_calibbias(struct ad7779_state *st, int channel)
+{
+ int ret;
+ u8 calibbias[3];
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
+ &calibbias[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
+ &calibbias[1]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
+ &calibbias[2]);
+ if (ret)
+ return ret;
+
+ return get_unaligned_be24(calibbias);
+}
+
+static int ad7779_set_calibbias(struct ad7779_state *st, int channel, int val)
+{
+ int ret;
+ u8 calibbias[3];
+
+ put_unaligned_be24(val, calibbias);
+ ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
+ calibbias[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
+ calibbias[1]);
+ if (ret)
+ return ret;
+
+ return ad7779_spi_write(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
+ calibbias[2]);
+}
+
+static int ad7779_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ ret = ad7779_get_calibscale(st, chan->channel);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ *val2 = GAIN_REL;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = ad7779_get_calibbias(st, chan->channel);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->sampling_freq;
+ if (*val < 0)
+ return -EINVAL;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ }
+ unreachable();
+}
+
+static int ad7779_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return ad7779_set_calibscale(st, chan->channel, val2);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return ad7779_set_calibbias(st, chan->channel, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return ad7779_set_sampling_frequency(st, val);
+ default:
+ return -EINVAL;
+ }
+ }
+ unreachable();
+}
+
+static int ad7779_buffer_preenable(struct iio_dev *indio_dev)
+{
+ int ret;
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ ret = ad7779_spi_write_mask(st,
+ AD7779_REG_GENERAL_USER_CONFIG_3,
+ AD7779_MOD_SPI_EN_MSK,
+ FIELD_PREP(AD7779_MOD_SPI_EN_MSK, 1));
+ if (ret)
+ return ret;
+
+ /*
+ * DRDY output cannot be disabled at device level therefore we mask
+ * the irq at host end.
+ */
+ enable_irq(st->spi->irq);
+
+ return 0;
+}
+
+static int ad7779_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ disable_irq(st->spi->irq);
+
+ return ad7779_spi_write(st, AD7779_REG_GENERAL_USER_CONFIG_3,
+ AD7779_DISABLE_SD);
+}
+
+static irqreturn_t ad7779_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+ struct spi_transfer t = {
+ .rx_buf = st->data.chans,
+ .tx_buf = st->spidata_tx,
+ .len = AD7779_NUM_CHANNELS * AD7779_CHAN_DATA_SIZE,
+ };
+
+ st->spidata_tx[0] = AD7779_SPI_READ_CMD;
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret) {
+ dev_err(&st->spi->dev, "SPI transfer error in IRQ handler");
+ goto exit_handler;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp);
+
+exit_handler:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int ad7779_reset(struct iio_dev *indio_dev, struct gpio_desc *reset_gpio)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+ struct spi_transfer t = {
+ .tx_buf = st->reset_buf,
+ .len = 8,
+ };
+
+ if (reset_gpio) {
+ gpiod_set_value(reset_gpio, 1);
+ /* Delay for reset to occur is 225 microseconds */
+ fsleep(230);
+ ret = 0;
+ } else {
+ memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret)
+ return ret;
+ }
+
+ /* Delay for reset to occur is 225 microseconds */
+ fsleep(230);
+
+ return ret;
+}
+
+static const struct iio_info ad7779_info = {
+ .read_raw = ad7779_read_raw,
+ .write_raw = ad7779_write_raw,
+ .debugfs_reg_access = &ad7779_reg_access,
+};
+
+static const struct iio_enum ad7779_filter_enum = {
+ .items = ad7779_filter_type,
+ .num_items = ARRAY_SIZE(ad7779_filter_type),
+ .get = ad7779_get_filter,
+ .set = ad7779_set_filter,
+};
+
+static const struct iio_chan_spec_ext_info ad7779_ext_filter[] = {
+ IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7779_filter_enum),
+ IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL,
+ &ad7779_filter_enum),
+ { }
+};
+
+#define AD777x_CHAN_S(index, _ext_info) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+ .address = (index), \
+ .indexed = 1, \
+ .channel = (index), \
+ .scan_index = (index), \
+ .ext_info = (_ext_info), \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 24, \
+ .storagebits = 32, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define AD777x_CHAN_NO_FILTER_S(index) \
+ AD777x_CHAN_S(index, NULL)
+
+#define AD777x_CHAN_FILTER_S(index) \
+ AD777x_CHAN_S(index, ad7779_ext_filter)
+static const struct iio_chan_spec ad7779_channels[] = {
+ AD777x_CHAN_NO_FILTER_S(0),
+ AD777x_CHAN_NO_FILTER_S(1),
+ AD777x_CHAN_NO_FILTER_S(2),
+ AD777x_CHAN_NO_FILTER_S(3),
+ AD777x_CHAN_NO_FILTER_S(4),
+ AD777x_CHAN_NO_FILTER_S(5),
+ AD777x_CHAN_NO_FILTER_S(6),
+ AD777x_CHAN_NO_FILTER_S(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static const struct iio_chan_spec ad7779_channels_filter[] = {
+ AD777x_CHAN_FILTER_S(0),
+ AD777x_CHAN_FILTER_S(1),
+ AD777x_CHAN_FILTER_S(2),
+ AD777x_CHAN_FILTER_S(3),
+ AD777x_CHAN_FILTER_S(4),
+ AD777x_CHAN_FILTER_S(5),
+ AD777x_CHAN_FILTER_S(6),
+ AD777x_CHAN_FILTER_S(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static const struct iio_buffer_setup_ops ad7779_buffer_setup_ops = {
+ .preenable = ad7779_buffer_preenable,
+ .postdisable = ad7779_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops ad7779_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
+static int ad7779_conf(struct ad7779_state *st, struct gpio_desc *start_gpio)
+{
+ int ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_GEN_ERR_REG_1_EN,
+ AD7779_SPI_CRC_EN_MSK,
+ FIELD_PREP(AD7779_SPI_CRC_EN_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_USRMOD_INIT_MSK,
+ FIELD_PREP(AD7779_USRMOD_INIT_MSK, 5));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
+ AD7779_DCLK_CLK_DIV_MSK,
+ FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_ADC_MUX_CONFIG,
+ AD7779_REFMUX_CTRL_MSK,
+ FIELD_PREP(AD7779_REFMUX_CTRL_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_set_sampling_frequency(st, AD7779_DEFAULT_SAMPLING_FREQ);
+ if (ret)
+ return ret;
+
+ gpiod_set_value(start_gpio, 0);
+ /* Start setup time */
+ fsleep(15);
+ gpiod_set_value(start_gpio, 1);
+ /* Start setup time */
+ fsleep(15);
+ gpiod_set_value(start_gpio, 0);
+ /* Start setup time */
+ fsleep(15);
+
+ return 0;
+}
+
+static int ad7779_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct ad7779_state *st;
+ struct gpio_desc *reset_gpio, *start_gpio;
+ struct device *dev = &spi->dev;
+ int ret = -EINVAL;
+
+ if (!spi->irq)
+ return dev_err_probe(dev, ret, "DRDY irq not present\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ ret = devm_regulator_bulk_get_enable(dev,
+ ARRAY_SIZE(ad7779_power_supplies),
+ ad7779_power_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get and enable supplies\n");
+
+ st->mclk = devm_clk_get_enabled(dev, "mclk");
+ if (IS_ERR(st->mclk))
+ return PTR_ERR(st->mclk);
+
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ start_gpio = devm_gpiod_get(dev, "start", GPIOD_OUT_HIGH);
+ if (IS_ERR(start_gpio))
+ return PTR_ERR(start_gpio);
+
+ crc8_populate_msb(ad7779_crc8_table, AD7779_CRC8_POLY);
+ st->spi = spi;
+
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
+ ret = ad7779_reset(indio_dev, reset_gpio);
+ if (ret)
+ return ret;
+
+ ret = ad7779_conf(st, start_gpio);
+ if (ret)
+ return ret;
+
+ indio_dev->name = st->chip_info->name;
+ indio_dev->info = &ad7779_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->chip_info->channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad7779_channels);
+
+ st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->trig)
+ return -ENOMEM;
+
+ st->trig->ops = &ad7779_trigger_ops;
+
+ iio_trigger_set_drvdata(st->trig, st);
+
+ ret = devm_request_irq(dev, spi->irq, iio_trigger_generic_data_rdy_poll,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, indio_dev->name,
+ st->trig);
+ if (ret)
+ return dev_err_probe(dev, ret, "request IRQ %d failed\n",
+ st->spi->irq);
+
+ ret = devm_iio_trigger_register(dev, st->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(st->trig);
+
+ init_completion(&st->completion);
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7779_trigger_handler,
+ &ad7779_buffer_setup_ops);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
+ AD7779_DCLK_CLK_DIV_MSK,
+ FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 7));
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static int ad7779_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_MOD_POWERMODE_MSK,
+ FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
+ AD7779_LOW_POWER));
+}
+
+static int ad7779_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_MOD_POWERMODE_MSK,
+ FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
+ AD7779_HIGH_POWER));
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(ad7779_pm_ops, ad7779_suspend, ad7779_resume);
+
+static const struct ad7779_chip_info ad7770_chip_info = {
+ .name = "ad7770",
+ .channels = ad7779_channels,
+};
+
+static const struct ad7779_chip_info ad7771_chip_info = {
+ .name = "ad7771",
+ .channels = ad7779_channels_filter,
+};
+
+static const struct ad7779_chip_info ad7779_chip_info = {
+ .name = "ad7779",
+ .channels = ad7779_channels,
+};
+
+static const struct spi_device_id ad7779_id[] = {
+ {
+ .name = "ad7770",
+ .driver_data = (kernel_ulong_t)&ad7770_chip_info,
+ },
+ {
+ .name = "ad7771",
+ .driver_data = (kernel_ulong_t)&ad7771_chip_info,
+ },
+ {
+ .name = "ad7779",
+ .driver_data = (kernel_ulong_t)&ad7779_chip_info,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad7779_id);
+
+static const struct of_device_id ad7779_of_table[] = {
+ {
+ .compatible = "adi,ad7770",
+ .data = &ad7770_chip_info,
+ },
+ {
+ .compatible = "adi,ad7771",
+ .data = &ad7771_chip_info,
+ },
+ {
+ .compatible = "adi,ad7779",
+ .data = &ad7779_chip_info,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7779_of_table);
+
+static struct spi_driver ad7779_driver = {
+ .driver = {
+ .name = "ad7779",
+ .pm = pm_sleep_ptr(&ad7779_pm_ops),
+ .of_match_table = ad7779_of_table,
+ },
+ .probe = ad7779_probe,
+ .id_table = ad7779_id,
+};
+module_spi_driver(ad7779_driver);
+
+MODULE_AUTHOR("Ramona Alexandra Nechita <ramona.nechita@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7779 ADC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c
index e9b0c577c9cc..8ccb74f47030 100644
--- a/drivers/iio/adc/ad7780.c
+++ b/drivers/iio/adc/ad7780.c
@@ -152,7 +152,7 @@ static int ad7780_write_raw(struct iio_dev *indio_dev,
switch (m) {
case IIO_CHAN_INFO_SCALE:
- if (val != 0)
+ if (val != 0 || val2 == 0)
return -EINVAL;
vref = st->int_vref_mv * 1000000LL;
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index 86effe8501b4..5d2ad3dd6caa 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -371,7 +371,7 @@ static const struct iio_info ad7791_no_filter_info = {
};
static int ad7791_setup(struct ad7791_state *st,
- struct ad7791_platform_data *pdata)
+ const struct ad7791_platform_data *pdata)
{
/* Set to poweron-reset default values */
st->mode = AD7791_MODE_BUFFER;
@@ -401,7 +401,7 @@ static void ad7791_reg_disable(void *reg)
static int ad7791_probe(struct spi_device *spi)
{
- struct ad7791_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7791_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad7791_state *st;
int ret;
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index abebd519cafa..b86e89370e0d 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -770,7 +770,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
static int ad7793_probe(struct spi_device *spi)
{
- const struct ad7793_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7793_platform_data *pdata = dev_get_platdata(&spi->dev);
struct ad7793_state *st;
struct iio_dev *indio_dev;
int ret, vref_mv = 0;
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 6265ce7df703..69add1dc4b53 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -41,7 +41,7 @@ enum ad7887_channels {
};
/**
- * struct ad7887_chip_info - chip specifc information
+ * struct ad7887_chip_info - chip specific information
* @int_vref_mv: the internal reference voltage
* @channels: channels specification
* @num_channels: number of channels
@@ -234,7 +234,7 @@ static void ad7887_reg_disable(void *data)
static int ad7887_probe(struct spi_device *spi)
{
- struct ad7887_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7887_platform_data *pdata = dev_get_platdata(&spi->dev);
struct ad7887_state *st;
struct iio_dev *indio_dev;
uint8_t mode;
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 09680015a7ab..acc44cb34f82 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -48,7 +48,7 @@
struct ad7923_state {
struct spi_device *spi;
- struct spi_transfer ring_xfer[5];
+ struct spi_transfer ring_xfer[9];
struct spi_transfer scan_single_xfer[2];
struct spi_message ring_msg;
struct spi_message scan_single_msg;
@@ -64,7 +64,7 @@ struct ad7923_state {
* Length = 8 channels + 4 extra for 8 byte timestamp
*/
__be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN);
- __be16 tx_buf[4];
+ __be16 tx_buf[8];
};
struct ad7923_chip_info {
diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c
index 0f36138a7144..a5aea4e9f1a7 100644
--- a/drivers/iio/adc/ad7944.c
+++ b/drivers/iio/adc/ad7944.c
@@ -80,7 +80,7 @@ struct ad7944_adc {
};
/* quite time before CNV rising edge */
-#define T_QUIET_NS 20
+#define AD7944_T_QUIET_NS 20
static const struct ad7944_timing_spec ad7944_timing_spec = {
.conv_ns = 420,
@@ -150,7 +150,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *
* CS is tied to CNV and we need a low to high transition to start the
* conversion, so place CNV low for t_QUIET to prepare for this.
*/
- xfers[0].delay.value = T_QUIET_NS;
+ xfers[0].delay.value = AD7944_T_QUIET_NS;
xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
/*
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index 0f107e3fc2c8..aa44b4e2542b 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -406,7 +406,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct ad799x_state *st = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index ea4aabd3960a..2f3b61765055 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -469,7 +469,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
/*
* Data array after transfer will look like (if status is appended):
* data[] = { [0][sample][sample][sample][status] }
- * Keeping the first byte 0 shifts the status postion by 1 byte to the right.
+ * Keeping the first byte 0 shifts the status position by 1 byte to the right.
*/
status_pos = reg_size + 1;
@@ -656,7 +656,7 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
sigma_delta->spi = spi;
sigma_delta->info = info;
- /* If the field is unset in ad_sigma_delta_info, asume there can only be 1 slot. */
+ /* If the field is unset in ad_sigma_delta_info, assume there can only be 1 slot. */
if (!info->num_slots)
sigma_delta->num_slots = 1;
else
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index d7fd21e7c6e2..8e5aaf15a921 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -2625,7 +2625,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_match);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove_new = at91_adc_remove,
+ .remove = at91_adc_remove,
.driver = {
.name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match,
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 9c39acff17e6..a3f0a2321666 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -1341,7 +1341,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove_new = at91_adc_remove,
+ .remove = at91_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = at91_adc_dt_ids,
diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c
index 6c1a5d1b0a83..9fd7027623d0 100644
--- a/drivers/iio/adc/axp20x_adc.c
+++ b/drivers/iio/adc/axp20x_adc.c
@@ -155,52 +155,22 @@ enum axp813_adc_channel_v {
AXP813_BATT_V,
};
-static struct iio_map axp20x_maps[] = {
- {
- .consumer_dev_name = "axp20x-usb-power-supply",
- .consumer_channel = "vbus_v",
- .adc_channel_label = "vbus_v",
- }, {
- .consumer_dev_name = "axp20x-usb-power-supply",
- .consumer_channel = "vbus_i",
- .adc_channel_label = "vbus_i",
- }, {
- .consumer_dev_name = "axp20x-ac-power-supply",
- .consumer_channel = "acin_v",
- .adc_channel_label = "acin_v",
- }, {
- .consumer_dev_name = "axp20x-ac-power-supply",
- .consumer_channel = "acin_i",
- .adc_channel_label = "acin_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_v",
- .adc_channel_label = "batt_v",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_chrg_i",
- .adc_channel_label = "batt_chrg_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_dischrg_i",
- .adc_channel_label = "batt_dischrg_i",
- }, { /* sentinel */ }
+static const struct iio_map axp20x_maps[] = {
+ IIO_MAP("vbus_v", "axp20x-usb-power-supply", "vbus_v"),
+ IIO_MAP("vbus_i", "axp20x-usb-power-supply", "vbus_i"),
+ IIO_MAP("acin_v", "axp20x-ac-power-supply", "acin_v"),
+ IIO_MAP("acin_i", "axp20x-ac-power-supply", "acin_i"),
+ IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
+ IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
+ IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
+ { /* sentinel */ }
};
-static struct iio_map axp22x_maps[] = {
- {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_v",
- .adc_channel_label = "batt_v",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_chrg_i",
- .adc_channel_label = "batt_chrg_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_dischrg_i",
- .adc_channel_label = "batt_dischrg_i",
- }, { /* sentinel */ }
+static const struct iio_map axp22x_maps[] = {
+ IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
+ IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
+ IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
+ { /* sentinel */ }
};
static struct iio_map axp717_maps[] = {
@@ -1044,7 +1014,7 @@ struct axp_data {
unsigned long adc_en2_mask;
int (*adc_rate)(struct axp20x_adc_iio *info,
int rate);
- struct iio_map *maps;
+ const struct iio_map *maps;
};
static const struct axp_data axp192_data = {
@@ -1212,7 +1182,7 @@ static struct platform_driver axp20x_adc_driver = {
},
.id_table = axp20x_adc_id_match,
.probe = axp20x_probe,
- .remove_new = axp20x_remove,
+ .remove = axp20x_remove,
};
module_platform_driver(axp20x_adc_driver);
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
index 8c3acc0cd7e9..45542efc3ece 100644
--- a/drivers/iio/adc/axp288_adc.c
+++ b/drivers/iio/adc/axp288_adc.c
@@ -103,7 +103,7 @@ static const struct iio_chan_spec axp288_adc_channels[] = {
};
/* for consumer drivers */
-static struct iio_map axp288_adc_default_maps[] = {
+static const struct iio_map axp288_adc_default_maps[] = {
IIO_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
IIO_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
IIO_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c
index cdfe304eaa20..f258668b0dc7 100644
--- a/drivers/iio/adc/bcm_iproc_adc.c
+++ b/drivers/iio/adc/bcm_iproc_adc.c
@@ -611,10 +611,10 @@ static const struct of_device_id iproc_adc_of_match[] = {
MODULE_DEVICE_TABLE(of, iproc_adc_of_match);
static struct platform_driver iproc_adc_driver = {
- .probe = iproc_adc_probe,
- .remove_new = iproc_adc_remove,
- .driver = {
- .name = "iproc-static-adc",
+ .probe = iproc_adc_probe,
+ .remove = iproc_adc_remove,
+ .driver = {
+ .name = "iproc-static-adc",
.of_match_table = iproc_adc_of_match,
},
};
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
index 8f0d3fb63b67..0290345ade84 100644
--- a/drivers/iio/adc/da9150-gpadc.c
+++ b/drivers/iio/adc/da9150-gpadc.c
@@ -291,27 +291,11 @@ static const struct iio_chan_spec da9150_gpadc_channels[] = {
};
/* Default maps used by da9150-charger */
-static struct iio_map da9150_gpadc_default_maps[] = {
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_IBUS",
- .adc_channel_label = "IBUS",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_VBUS",
- .adc_channel_label = "VBUS",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_TJUNC",
- .adc_channel_label = "TJUNC_CORE",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_VBAT",
- .adc_channel_label = "VBAT",
- },
+static const struct iio_map da9150_gpadc_default_maps[] = {
+ IIO_MAP("IBUS", "da9150-charger", "CHAN_IBUS"),
+ IIO_MAP("VBUS", "da9150-charger", "CHAN_VBUS"),
+ IIO_MAP("TJUNC_CORE", "da9150-charger", "CHAN_TJUNC"),
+ IIO_MAP("VBAT", "da9150-charger", "CHAN_VBAT"),
{},
};
diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c
index de7252a10047..30328626d9be 100644
--- a/drivers/iio/adc/dln2-adc.c
+++ b/drivers/iio/adc/dln2-adc.c
@@ -700,7 +700,7 @@ static void dln2_adc_remove(struct platform_device *pdev)
static struct platform_driver dln2_adc_driver = {
.driver.name = DLN2_ADC_MOD_NAME,
.probe = dln2_adc_probe,
- .remove_new = dln2_adc_remove,
+ .remove = dln2_adc_remove,
};
module_platform_driver(dln2_adc_driver);
diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c
index cc38d5e0608e..a3e9c697e2cb 100644
--- a/drivers/iio/adc/ep93xx_adc.c
+++ b/drivers/iio/adc/ep93xx_adc.c
@@ -238,7 +238,7 @@ static struct platform_driver ep93xx_adc_driver = {
.of_match_table = ep93xx_adc_of_ids,
},
.probe = ep93xx_adc_probe,
- .remove_new = ep93xx_adc_remove,
+ .remove = ep93xx_adc_remove,
};
module_platform_driver(ep93xx_adc_driver);
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 4d00ee8dd14d..4614cf848535 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -1008,7 +1008,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, exynos_adc_suspend,
static struct platform_driver exynos_adc_driver = {
.probe = exynos_adc_probe,
- .remove_new = exynos_adc_remove,
+ .remove = exynos_adc_remove,
.driver = {
.name = "exynos-adc",
.of_match_table = exynos_adc_match,
diff --git a/drivers/iio/adc/gehc-pmc-adc.c b/drivers/iio/adc/gehc-pmc-adc.c
new file mode 100644
index 000000000000..d1167818b17d
--- /dev/null
+++ b/drivers/iio/adc/gehc-pmc-adc.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The GE HealthCare PMC ADC is a 16-Channel (Voltage and current), 16-Bit
+ * ADC with an I2C Interface.
+ *
+ * Copyright (C) 2024, GE HealthCare
+ *
+ * Authors:
+ * Herve Codina <herve.codina@bootlin.com>
+ */
+#include <dt-bindings/iio/adc/gehc,pmc-adc.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+struct pmc_adc {
+ struct i2c_client *client;
+};
+
+#define PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION 0x01
+#define PMC_ADC_CMD_READ_VOLTAGE(_ch) (0x10 | (_ch))
+#define PMC_ADC_CMD_READ_CURRENT(_ch) (0x20 | (_ch))
+
+#define PMC_ADC_VOLTAGE_CHANNEL(_ch, _ds_name) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = (_ch), \
+ .address = PMC_ADC_CMD_READ_VOLTAGE(_ch), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .datasheet_name = (_ds_name), \
+}
+
+#define PMC_ADC_CURRENT_CHANNEL(_ch, _ds_name) { \
+ .type = IIO_CURRENT, \
+ .indexed = 1, \
+ .channel = (_ch), \
+ .address = PMC_ADC_CMD_READ_CURRENT(_ch), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .datasheet_name = (_ds_name), \
+}
+
+static const struct iio_chan_spec pmc_adc_channels[] = {
+ PMC_ADC_VOLTAGE_CHANNEL(0, "CH0_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(1, "CH1_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(2, "CH2_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(3, "CH3_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(4, "CH4_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(5, "CH5_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(6, "CH6_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(7, "CH7_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(8, "CH8_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(9, "CH9_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(10, "CH10_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(11, "CH11_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(12, "CH12_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(13, "CH13_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(14, "CH14_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(15, "CH15_V"),
+
+ PMC_ADC_CURRENT_CHANNEL(0, "CH0_I"),
+ PMC_ADC_CURRENT_CHANNEL(1, "CH1_I"),
+ PMC_ADC_CURRENT_CHANNEL(2, "CH2_I"),
+ PMC_ADC_CURRENT_CHANNEL(3, "CH3_I"),
+ PMC_ADC_CURRENT_CHANNEL(4, "CH4_I"),
+ PMC_ADC_CURRENT_CHANNEL(5, "CH5_I"),
+ PMC_ADC_CURRENT_CHANNEL(6, "CH6_I"),
+ PMC_ADC_CURRENT_CHANNEL(7, "CH7_I"),
+ PMC_ADC_CURRENT_CHANNEL(8, "CH8_I"),
+ PMC_ADC_CURRENT_CHANNEL(9, "CH9_I"),
+ PMC_ADC_CURRENT_CHANNEL(10, "CH10_I"),
+ PMC_ADC_CURRENT_CHANNEL(11, "CH11_I"),
+ PMC_ADC_CURRENT_CHANNEL(12, "CH12_I"),
+ PMC_ADC_CURRENT_CHANNEL(13, "CH13_I"),
+ PMC_ADC_CURRENT_CHANNEL(14, "CH14_I"),
+ PMC_ADC_CURRENT_CHANNEL(15, "CH15_I"),
+};
+
+static int pmc_adc_read_raw_ch(struct pmc_adc *pmc_adc, u8 cmd, int *val)
+{
+ s32 ret;
+
+ ret = i2c_smbus_read_word_swapped(pmc_adc->client, cmd);
+ if (ret < 0) {
+ dev_err(&pmc_adc->client->dev, "i2c read word failed (%d)\n", ret);
+ return ret;
+ }
+
+ *val = sign_extend32(ret, 15);
+ return 0;
+}
+
+static int pmc_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct pmc_adc *pmc_adc = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ /* Values are directly read in mV or mA */
+ ret = pmc_adc_read_raw_ch(pmc_adc, chan->address, val);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int pmc_adc_fwnode_xlate(struct iio_dev *indio_dev,
+ const struct fwnode_reference_args *iiospec)
+{
+ enum iio_chan_type expected_type;
+ unsigned int i;
+
+ /*
+ * args[0]: Acquisition type (i.e. voltage or current)
+ * args[1]: PMC ADC channel number
+ */
+ if (iiospec->nargs != 2)
+ return -EINVAL;
+
+ switch (iiospec->args[0]) {
+ case GEHC_PMC_ADC_VOLTAGE:
+ expected_type = IIO_VOLTAGE;
+ break;
+ case GEHC_PMC_ADC_CURRENT:
+ expected_type = IIO_CURRENT;
+ break;
+ default:
+ dev_err(&indio_dev->dev, "Invalid channel type %llu\n",
+ iiospec->args[0]);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].type == expected_type &&
+ indio_dev->channels[i].channel == iiospec->args[1])
+ return i;
+
+ dev_err(&indio_dev->dev, "Invalid channel type %llu number %llu\n",
+ iiospec->args[0], iiospec->args[1]);
+ return -EINVAL;
+}
+
+static const struct iio_info pmc_adc_info = {
+ .read_raw = pmc_adc_read_raw,
+ .fwnode_xlate = pmc_adc_fwnode_xlate,
+};
+
+static const char *const pmc_adc_regulator_names[] = {
+ "vdd",
+ "vdda",
+ "vddio",
+ "vref",
+};
+
+static int pmc_adc_probe(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev;
+ struct pmc_adc *pmc_adc;
+ struct clk *clk;
+ s32 val;
+ int ret;
+
+ ret = devm_regulator_bulk_get_enable(&client->dev, ARRAY_SIZE(pmc_adc_regulator_names),
+ pmc_adc_regulator_names);
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to get regulators\n");
+
+ clk = devm_clk_get_optional_enabled(&client->dev, "osc");
+ if (IS_ERR(clk))
+ return dev_err_probe(&client->dev, PTR_ERR(clk), "Failed to get osc clock\n");
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*pmc_adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ pmc_adc = iio_priv(indio_dev);
+ pmc_adc->client = client;
+
+ val = i2c_smbus_read_byte_data(pmc_adc->client, PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION);
+ if (val < 0)
+ return dev_err_probe(&client->dev, val, "Failed to get protocol version\n");
+
+ if (val != 0x01)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Unsupported protocol version 0x%02x\n", val);
+
+ indio_dev->name = "pmc_adc";
+ indio_dev->info = &pmc_adc_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = pmc_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(pmc_adc_channels);
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id pmc_adc_of_match[] = {
+ { .compatible = "gehc,pmc-adc"},
+ { }
+};
+MODULE_DEVICE_TABLE(of, pmc_adc_of_match);
+
+static const struct i2c_device_id pmc_adc_id_table[] = {
+ { "pmc-adc" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pmc_adc_id_table);
+
+static struct i2c_driver pmc_adc_i2c_driver = {
+ .driver = {
+ .name = "pmc-adc",
+ .of_match_table = pmc_adc_of_match,
+ },
+ .id_table = pmc_adc_id_table,
+ .probe = pmc_adc_probe,
+};
+
+module_i2c_driver(pmc_adc_i2c_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("GE HealthCare PMC ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c
index fb635a756440..689e34f06987 100644
--- a/drivers/iio/adc/hi8435.c
+++ b/drivers/iio/adc/hi8435.c
@@ -132,7 +132,7 @@ static int hi8435_read_event_config(struct iio_dev *idev,
static int hi8435_write_event_config(struct iio_dev *idev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct hi8435_priv *priv = iio_priv(idev);
int ret;
diff --git a/drivers/iio/adc/imx8qxp-adc.c b/drivers/iio/adc/imx8qxp-adc.c
index fe82198170d5..3d19d7d744aa 100644
--- a/drivers/iio/adc/imx8qxp-adc.c
+++ b/drivers/iio/adc/imx8qxp-adc.c
@@ -487,7 +487,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_adc_match);
static struct platform_driver imx8qxp_adc_driver = {
.probe = imx8qxp_adc_probe,
- .remove_new = imx8qxp_adc_remove,
+ .remove = imx8qxp_adc_remove,
.driver = {
.name = ADC_DRIVER_NAME,
.of_match_table = imx8qxp_adc_match,
diff --git a/drivers/iio/adc/imx93_adc.c b/drivers/iio/adc/imx93_adc.c
index 4ccf4819f1f1..002eb19587d6 100644
--- a/drivers/iio/adc/imx93_adc.c
+++ b/drivers/iio/adc/imx93_adc.c
@@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, imx93_adc_match);
static struct platform_driver imx93_adc_driver = {
.probe = imx93_adc_probe,
- .remove_new = imx93_adc_remove,
+ .remove = imx93_adc_remove,
.driver = {
.name = IMX93_ADC_DRIVER_NAME,
.of_match_table = imx93_adc_match,
diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c
index 30733252aa56..c178850eaaab 100644
--- a/drivers/iio/adc/intel_mrfld_adc.c
+++ b/drivers/iio/adc/intel_mrfld_adc.c
@@ -164,7 +164,7 @@ static const struct iio_chan_spec mrfld_adc_channels[] = {
BCOVE_ADC_CHANNEL(IIO_TEMP, 8, "CH8", 0xC6),
};
-static struct iio_map iio_maps[] = {
+static const struct iio_map iio_maps[] = {
IIO_MAP("CH0", "bcove-battery", "VBATRSLT"),
IIO_MAP("CH1", "bcove-battery", "BATTID"),
IIO_MAP("CH2", "bcove-battery", "IBATRSLT"),
diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c
index 6d9b354bc705..33bf8aef79e3 100644
--- a/drivers/iio/adc/lp8788_adc.c
+++ b/drivers/iio/adc/lp8788_adc.c
@@ -26,7 +26,7 @@
struct lp8788_adc {
struct lp8788 *lp;
- struct iio_map *map;
+ const struct iio_map *map;
struct mutex lock;
};
@@ -149,17 +149,9 @@ static const struct iio_chan_spec lp8788_adc_channels[] = {
};
/* default maps used by iio consumer (lp8788-charger driver) */
-static struct iio_map lp8788_default_iio_maps[] = {
- {
- .consumer_dev_name = "lp8788-charger",
- .consumer_channel = "lp8788_vbatt_5p0",
- .adc_channel_label = "VBATT_5P0",
- },
- {
- .consumer_dev_name = "lp8788-charger",
- .consumer_channel = "lp8788_adc1",
- .adc_channel_label = "ADC1",
- },
+static const struct iio_map lp8788_default_iio_maps[] = {
+ IIO_MAP("VBATT_5P0", "lp8788-charger", "lp8788_vbatt_5p0"),
+ IIO_MAP("ADC1", "lp8788-charger", "lp8788_adc1"),
{ }
};
@@ -168,7 +160,7 @@ static int lp8788_iio_map_register(struct device *dev,
struct lp8788_platform_data *pdata,
struct lp8788_adc *adc)
{
- struct iio_map *map;
+ const struct iio_map *map;
int ret;
map = (!pdata || !pdata->adc_pdata) ?
diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c
index 996f6cbbed3c..ad8ddf80310e 100644
--- a/drivers/iio/adc/ltc2497-core.c
+++ b/drivers/iio/adc/ltc2497-core.c
@@ -168,6 +168,7 @@ static const struct iio_info ltc2497core_info = {
int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
{
struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
+ struct iio_map *plat_data = dev_get_platdata(dev);
int ret;
/*
@@ -200,16 +201,10 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
return ret;
}
- if (dev->platform_data) {
- struct iio_map *plat_data;
-
- plat_data = (struct iio_map *)dev->platform_data;
-
- ret = iio_map_array_register(indio_dev, plat_data);
- if (ret) {
- dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
- goto err_regulator_disable;
- }
+ ret = iio_map_array_register(indio_dev, plat_data);
+ if (ret) {
+ dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
+ goto err_regulator_disable;
}
ddata->addr_prev = LTC2497_CONFIG_DEFAULT;
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index d0c6e94f7204..9a0baea08ab6 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -392,7 +393,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
if (data < 0)
return data;
- data = (rxbuf[1] | rxbuf[0] << 8) &
+ data = get_unaligned_be16(rxbuf) &
((1 << st->chip_info->bits) - 1);
} else {
/* Get reading */
@@ -943,7 +944,7 @@ error_ret:
static int max1363_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct max1363_state *st = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/max34408.c b/drivers/iio/adc/max34408.c
index ffec22be2d59..971e6e5dee9b 100644
--- a/drivers/iio/adc/max34408.c
+++ b/drivers/iio/adc/max34408.c
@@ -161,7 +161,7 @@ static int max34408_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/*
- * calcluate current for 8bit ADC with Rsense
+ * calculate current for 8bit ADC with Rsense
* value.
* 10 mV * 1000 / Rsense uOhm = max current
* (max current * adc val * 1000) / (2^8 - 1) mA
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index e16b0e28974e..2d475b43e717 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -1483,7 +1483,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
static struct platform_driver meson_sar_adc_driver = {
.probe = meson_sar_adc_probe,
- .remove_new = meson_sar_adc_remove,
+ .remove = meson_sar_adc_remove,
.driver = {
.name = "meson-saradc",
.of_match_table = meson_sar_adc_of_match,
diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c
index 5fbf9b6abd9c..1cb043b17437 100644
--- a/drivers/iio/adc/mp2629_adc.c
+++ b/drivers/iio/adc/mp2629_adc.c
@@ -52,7 +52,7 @@ static struct iio_chan_spec mp2629_channels[] = {
MP2629_ADC_CHAN(INPUT_CURRENT, IIO_CURRENT)
};
-static struct iio_map mp2629_adc_maps[] = {
+static const struct iio_map mp2629_adc_maps[] = {
MP2629_MAP(BATT_VOLT, "batt-volt"),
MP2629_MAP(SYSTEM_VOLT, "system-volt"),
MP2629_MAP(INPUT_VOLT, "input-volt"),
@@ -195,7 +195,7 @@ static struct platform_driver mp2629_adc_driver = {
.of_match_table = mp2629_adc_of_match,
},
.probe = mp2629_adc_probe,
- .remove_new = mp2629_adc_remove,
+ .remove = mp2629_adc_remove,
};
module_platform_driver(mp2629_adc_driver);
diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c
index 83161e6d29b9..4eb2455d6ffa 100644
--- a/drivers/iio/adc/mt6360-adc.c
+++ b/drivers/iio/adc/mt6360-adc.c
@@ -124,7 +124,7 @@ static int mt6360_adc_read_channel(struct mt6360_adc_data *mad, int channel, int
usleep_range(ADC_LOOP_TIME_US / 2, ADC_LOOP_TIME_US);
}
- *val = rpt[1] << 8 | rpt[2];
+ *val = get_unaligned_be16(&rpt[1]);
ret = IIO_VAL_INT;
out_adc_conv:
diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
index 8c7b64e78dbb..152cbe265e1a 100644
--- a/drivers/iio/adc/mxs-lradc-adc.c
+++ b/drivers/iio/adc/mxs-lradc-adc.c
@@ -819,10 +819,10 @@ static void mxs_lradc_adc_remove(struct platform_device *pdev)
static struct platform_driver mxs_lradc_adc_driver = {
.driver = {
- .name = "mxs-lradc-adc",
+ .name = "mxs-lradc-adc",
},
- .probe = mxs_lradc_adc_probe,
- .remove_new = mxs_lradc_adc_remove,
+ .probe = mxs_lradc_adc_probe,
+ .remove = mxs_lradc_adc_remove,
};
module_platform_driver(mxs_lradc_adc_driver);
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index 3a55465951e7..7c1511ee3a4b 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -337,7 +337,7 @@ static void npcm_adc_remove(struct platform_device *pdev)
static struct platform_driver npcm_adc_driver = {
.probe = npcm_adc_probe,
- .remove_new = npcm_adc_remove,
+ .remove = npcm_adc_remove,
.driver = {
.name = "npcm_adc",
.of_match_table = npcm_adc_match,
diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c
index 36e813d9c73f..b0f6727cfe38 100644
--- a/drivers/iio/adc/pac1921.c
+++ b/drivers/iio/adc/pac1921.c
@@ -241,7 +241,7 @@ static inline void pac1921_calc_scale(int dividend, int divisor, int *val,
s64 tmp;
tmp = div_s64(dividend * (s64)NANO, divisor);
- *val = (int)div_s64_rem(tmp, NANO, val2);
+ *val = div_s64_rem(tmp, NANO, val2);
}
/*
@@ -260,7 +260,7 @@ static void pac1921_calc_current_scales(struct pac1921_priv *priv)
int max = (PAC1921_MAX_VSENSE_MV * MICRO) >> i;
int vsense_lsb = DIV_ROUND_CLOSEST(max, PAC1921_RES_RESOLUTION);
- pac1921_calc_scale(vsense_lsb, (int)priv->rshunt_uohm,
+ pac1921_calc_scale(vsense_lsb, priv->rshunt_uohm,
&priv->current_scales[i][0],
&priv->current_scales[i][1]);
}
@@ -314,7 +314,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp)
timestamp);
}
- priv->prev_ovf_flags = (u8)flags;
+ priv->prev_ovf_flags = flags;
return 0;
}
@@ -329,8 +329,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp)
static int pac1921_read_res(struct pac1921_priv *priv, unsigned long reg,
u16 *val)
{
- int ret = regmap_bulk_read(priv->regmap, (unsigned int)reg, val,
- sizeof(*val));
+ int ret = regmap_bulk_read(priv->regmap, reg, val, sizeof(*val));
if (ret)
return ret;
@@ -366,7 +365,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
if (ret)
return ret;
- *val = (int)res_val;
+ *val = res_val;
return IIO_VAL_INT;
}
@@ -400,10 +399,10 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
s64 tmp = curr_scale[0] * (s64)NANO + curr_scale[1];
/* Multiply by max_vbus (V) / dv_gain */
- tmp *= PAC1921_MAX_VBUS_V >> (int)priv->dv_gain;
+ tmp *= PAC1921_MAX_VBUS_V >> priv->dv_gain;
/* Convert back to INT_PLUS_NANO */
- *val = (int)div_s64_rem(tmp, NANO, val2);
+ *val = div_s64_rem(tmp, NANO, val2);
return IIO_VAL_INT_PLUS_NANO;
}
@@ -426,7 +425,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
* 1/(integr_period_usecs/MICRO) = MICRO/integr_period_usecs
*/
*val = MICRO;
- *val2 = (int)priv->integr_period_usecs;
+ *val2 = priv->integr_period_usecs;
return IIO_VAL_FRACTIONAL;
default:
@@ -503,7 +502,7 @@ static int pac1921_lookup_scale(const int (*const scales_tbl)[2], size_t size,
for (unsigned int i = 0; i < size; i++)
if (scales_tbl[i][0] == scale_val &&
scales_tbl[i][1] == scale_val2)
- return (int)i;
+ return i;
return -EINVAL;
}
@@ -553,7 +552,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->dv_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->dv_gain, ret,
PAC1921_GAIN_DV_GAIN_MASK);
case PAC1921_CHAN_VSENSE:
ret = pac1921_lookup_scale(pac1921_vsense_scales,
@@ -562,7 +561,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->di_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->di_gain, ret,
PAC1921_GAIN_DI_GAIN_MASK);
case PAC1921_CHAN_CURRENT:
ret = pac1921_lookup_scale(priv->current_scales,
@@ -571,7 +570,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->di_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->di_gain, ret,
PAC1921_GAIN_DI_GAIN_MASK);
default:
return -EINVAL;
@@ -586,7 +585,7 @@ static int pac1921_lookup_int_num_samples(int num_samples)
{
for (unsigned int i = 0; i < ARRAY_SIZE(pac1921_int_num_samples); i++)
if (pac1921_int_num_samples[i] == num_samples)
- return (int)i;
+ return i;
return -EINVAL;
}
@@ -607,7 +606,7 @@ static int pac1921_update_int_num_samples(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- n_samples = (u8)ret;
+ n_samples = ret;
if (priv->n_samples == n_samples)
return 0;
@@ -700,7 +699,8 @@ static int pac1921_read_event_config(struct iio_dev *indio_dev,
static int pac1921_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct pac1921_priv *priv = iio_priv(indio_dev);
u8 ovf_bit;
@@ -770,7 +770,7 @@ static ssize_t pac1921_read_shunt_resistor(struct iio_dev *indio_dev,
guard(mutex)(&priv->lock);
- vals[0] = (int)priv->rshunt_uohm;
+ vals[0] = priv->rshunt_uohm;
vals[1] = MICRO;
return iio_format_value(buf, IIO_VAL_FRACTIONAL, 1, vals);
@@ -793,13 +793,13 @@ static ssize_t pac1921_write_shunt_resistor(struct iio_dev *indio_dev,
if (ret)
return ret;
- rshunt_uohm = (u32)val * MICRO + (u32)val_fract;
+ rshunt_uohm = val * MICRO + val_fract;
if (rshunt_uohm == 0 || rshunt_uohm > INT_MAX)
return -EINVAL;
guard(mutex)(&priv->lock);
- priv->rshunt_uohm = (u32)rshunt_uohm;
+ priv->rshunt_uohm = rshunt_uohm;
pac1921_calc_current_scales(priv);
@@ -1077,7 +1077,7 @@ static int pac1921_init(struct pac1921_priv *priv)
/*
* Init control register:
* - VPower free run integration mode
- * - OUT pin full scale range: 3V (HW detault)
+ * - OUT pin full scale range: 3V (HW default)
* - no timeout, no sleep, no sleep override, no recalc (HW defaults)
*/
val = FIELD_PREP(PAC1921_CONTROL_MXSL_MASK,
@@ -1168,10 +1168,12 @@ static int pac1921_probe(struct i2c_client *client)
priv->regmap = devm_regmap_init_i2c(client, &pac1921_regmap_config);
if (IS_ERR(priv->regmap))
- return dev_err_probe(dev, (int)PTR_ERR(priv->regmap),
+ return dev_err_probe(dev, PTR_ERR(priv->regmap),
"Cannot initialize register map\n");
- devm_mutex_init(dev, &priv->lock);
+ ret = devm_mutex_init(dev, &priv->lock);
+ if (ret)
+ return ret;
priv->dv_gain = PAC1921_DEFAULT_DV_GAIN;
priv->di_gain = PAC1921_DEFAULT_DI_GAIN;
@@ -1191,7 +1193,7 @@ static int pac1921_probe(struct i2c_client *client)
priv->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(priv->vdd))
- return dev_err_probe(dev, (int)PTR_ERR(priv->vdd),
+ return dev_err_probe(dev, PTR_ERR(priv->vdd),
"Cannot get vdd regulator\n");
ret = regulator_enable(priv->vdd);
diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c
index 7ef249d83286..20802b7f49ea 100644
--- a/drivers/iio/adc/pac1934.c
+++ b/drivers/iio/adc/pac1934.c
@@ -1507,7 +1507,7 @@ static int pac1934_probe(struct i2c_client *client)
indio_dev->name = pac1934_chip_config[ret].name;
}
- if (acpi_match_device(dev->driver->acpi_match_table, dev))
+ if (is_acpi_device_node(dev_fwnode(dev)))
ret = pac1934_acpi_parse_channel_config(client, info);
else
/*
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 203cbbc70719..d283ee8fb1d2 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -456,7 +456,7 @@ static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,
* raw high threshold = (ideal threshold + INL) * gain error + offset error
*
* The gain error include both gain error, as specified in the datasheet, and
- * the gain error drift. These paramenters vary depending on device and whether
+ * the gain error drift. These parameters vary depending on device and whether
* the channel is calibrated (trimmed) or not.
*/
static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,
@@ -676,7 +676,7 @@ static int palmas_gpadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct palmas_gpadc *adc = iio_priv(indio_dev);
int adc_chan = chan->channel;
diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
index 9e1112f5acc6..31f88cf7f7f1 100644
--- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c
+++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
@@ -821,7 +821,6 @@ static int pm8xxx_xoadc_parse_channel(struct device *dev,
static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc)
{
- struct fwnode_handle *child;
struct pm8xxx_chan_info *ch;
int ret;
int i;
@@ -844,16 +843,15 @@ static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc)
return -ENOMEM;
i = 0;
- device_for_each_child_node(adc->dev, child) {
+ device_for_each_child_node_scoped(adc->dev, child) {
ch = &adc->chans[i];
ret = pm8xxx_xoadc_parse_channel(adc->dev, child,
adc->variant->channels,
&adc->iio_chans[i],
ch);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
+
i++;
}
@@ -1016,7 +1014,7 @@ static struct platform_driver pm8xxx_xoadc_driver = {
.of_match_table = pm8xxx_xoadc_id_table,
},
.probe = pm8xxx_xoadc_probe,
- .remove_new = pm8xxx_xoadc_remove,
+ .remove = pm8xxx_xoadc_remove,
};
module_platform_driver(pm8xxx_xoadc_driver);
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index 9b69f40beed8..af3c2f659f5e 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -830,7 +830,7 @@ static int adc5_get_fw_data(struct adc5_chip *adc)
adc->nchannels = device_get_child_node_count(adc->dev);
if (!adc->nchannels)
- return -EINVAL;
+ return dev_err_probe(adc->dev, -EINVAL, "no channels defined\n");
adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels,
sizeof(*adc->iio_chans), GFP_KERNEL);
@@ -903,7 +903,7 @@ static int adc5_probe(struct platform_device *pdev)
ret = adc5_get_fw_data(adc);
if (ret)
- return dev_err_probe(dev, ret, "adc get dt data failed\n");
+ return ret;
irq_eoc = platform_get_irq(pdev, 0);
if (irq_eoc < 0) {
diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
index f5c6f1f27b2c..00a7f0982025 100644
--- a/drivers/iio/adc/qcom-spmi-vadc.c
+++ b/drivers/iio/adc/qcom-spmi-vadc.c
@@ -754,7 +754,6 @@ static int vadc_get_fw_data(struct vadc_priv *vadc)
const struct vadc_channels *vadc_chan;
struct iio_chan_spec *iio_chan;
struct vadc_channel_prop prop;
- struct fwnode_handle *child;
unsigned int index = 0;
int ret;
@@ -774,12 +773,10 @@ static int vadc_get_fw_data(struct vadc_priv *vadc)
iio_chan = vadc->iio_chans;
- device_for_each_child_node(vadc->dev, child) {
+ device_for_each_child_node_scoped(vadc->dev, child) {
ret = vadc_get_fw_channel_data(vadc->dev, &prop, child);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type;
vadc->chan_props[index] = prop;
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index 15a21d2860e7..11170b5852d1 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -592,7 +592,7 @@ static const struct dev_pm_ops rcar_gyroadc_pm_ops = {
static struct platform_driver rcar_gyroadc_driver = {
.probe = rcar_gyroadc_probe,
- .remove_new = rcar_gyroadc_remove,
+ .remove = rcar_gyroadc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = rcar_gyroadc_match,
diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c
index ce5f3011fe00..b33536157adc 100644
--- a/drivers/iio/adc/rn5t618-adc.c
+++ b/drivers/iio/adc/rn5t618-adc.c
@@ -185,7 +185,7 @@ static const struct iio_chan_spec rn5t618_adc_iio_channels[] = {
RN5T618_ADC_CHANNEL(AIN0, IIO_VOLTAGE, "AIN0")
};
-static struct iio_map rn5t618_maps[] = {
+static const struct iio_map rn5t618_maps[] = {
IIO_MAP("VADP", "rn5t618-power", "vadp"),
IIO_MAP("VUSB", "rn5t618-power", "vusb"),
{ /* sentinel */ }
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 616dd729666a..2201ee9987ae 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -906,7 +906,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove_new = stm32_adc_remove,
+ .remove = stm32_adc_remove,
.driver = {
.name = "stm32-adc-core",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 32ca26ed59f7..9d3b23efcc06 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -2644,7 +2644,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove_new = stm32_adc_remove,
+ .remove = stm32_adc_remove,
.driver = {
.name = "stm32-adc",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 2037f73426d4..c2d4f5339cd4 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -1890,7 +1890,7 @@ static struct platform_driver stm32_dfsdm_adc_driver = {
.pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops),
},
.probe = stm32_dfsdm_adc_probe,
- .remove_new = stm32_dfsdm_adc_remove,
+ .remove = stm32_dfsdm_adc_remove,
};
module_platform_driver(stm32_dfsdm_adc_driver);
diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
index bef59fcc0d80..041dc9ebc048 100644
--- a/drivers/iio/adc/stm32-dfsdm-core.c
+++ b/drivers/iio/adc/stm32-dfsdm-core.c
@@ -506,7 +506,7 @@ static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = {
static struct platform_driver stm32_dfsdm_driver = {
.probe = stm32_dfsdm_probe,
- .remove_new = stm32_dfsdm_core_remove,
+ .remove = stm32_dfsdm_core_remove,
.driver = {
.name = "stm32-dfsdm",
.of_match_table = stm32_dfsdm_of_match,
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 6a893d484cf7..136b8d9c294f 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -155,7 +155,6 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
unsigned int channel;
int num_channels, i, ret;
struct iio_chan_spec *channels;
- struct fwnode_handle *node;
num_channels = device_get_child_node_count(dev);
if (num_channels == 0)
@@ -167,12 +166,10 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
return -ENOMEM;
i = 0;
- device_for_each_child_node(dev, node) {
+ device_for_each_child_node_scoped(dev, node) {
ret = fwnode_property_read_u32(node, "reg", &channel);
- if (ret) {
- fwnode_handle_put(node);
+ if (ret)
return dev_err_probe(dev, ret, "invalid channel number\n");
- }
channels[i].type = IIO_VOLTAGE;
channels[i].indexed = 1;
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 100ecced5fc1..8b27458dcd66 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -114,11 +114,8 @@ struct sun4i_gpadc_iio {
.datasheet_name = _name, \
}
-static struct iio_map sun4i_gpadc_hwmon_maps[] = {
- {
- .adc_channel_label = "temp_adc",
- .consumer_dev_name = "iio_hwmon.0",
- },
+static const struct iio_map sun4i_gpadc_hwmon_maps[] = {
+ IIO_MAP("temp_adc", "iio_hwmon.0", NULL),
{ /* sentinel */ },
};
@@ -700,7 +697,7 @@ static struct platform_driver sun4i_gpadc_driver = {
},
.id_table = sun4i_gpadc_id,
.probe = sun4i_gpadc_probe,
- .remove_new = sun4i_gpadc_remove,
+ .remove = sun4i_gpadc_remove,
};
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 6d1bc9659946..47fe8e16aee4 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -806,7 +806,7 @@ static int ads1015_disable_event_config(struct ads1015_data *data,
static int ads1015_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ads1015_data *data = iio_priv(indio_dev);
int ret;
@@ -1032,8 +1032,7 @@ static int ads1015_probe(struct i2c_client *client)
}
if (client->irq && chip->has_comparator) {
- unsigned long irq_trig =
- irqd_get_trigger_type(irq_get_irq_data(client->irq));
+ unsigned long irq_trig = irq_get_trigger_type(client->irq);
unsigned int cfg_comp_mask = ADS1015_CFG_COMP_QUE_MASK |
ADS1015_CFG_COMP_LAT_MASK | ADS1015_CFG_COMP_POL_MASK;
unsigned int cfg_comp =
diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c
index 1c7606375149..e9d9d4d46d38 100644
--- a/drivers/iio/adc/ti-ads1119.c
+++ b/drivers/iio/adc/ti-ads1119.c
@@ -804,7 +804,7 @@ static const struct of_device_id __maybe_unused ads1119_of_match[] = {
MODULE_DEVICE_TABLE(of, ads1119_of_match);
static const struct i2c_device_id ads1119_id[] = {
- { "ads1119", 0 },
+ { "ads1119" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ads1119_id);
diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c
index 0f9f75baaebb..36d43495f603 100644
--- a/drivers/iio/adc/ti-ads1298.c
+++ b/drivers/iio/adc/ti-ads1298.c
@@ -294,7 +294,7 @@ static int ads1298_get_scale(struct ads1298_private *priv,
if (ret)
return ret;
- /* Refererence in millivolts */
+ /* Reference in millivolts */
*val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400;
}
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 426e3c9f88a1..fe1509d3b1e7 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -494,7 +494,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
/*
* We check the complete FIFO. We programmed just one entry but in case
* something went wrong we left empty handed (-EAGAIN previously) and
- * then the value apeared somehow in the FIFO we would have two entries.
+ * then the value appeared somehow in the FIFO we would have two entries.
* Therefore we read every item and keep only the latest version of the
* requested channel.
*/
@@ -740,12 +740,12 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
static struct platform_driver tiadc_driver = {
.driver = {
- .name = "TI-am335x-adc",
- .pm = pm_sleep_ptr(&tiadc_pm_ops),
+ .name = "TI-am335x-adc",
+ .pm = pm_sleep_ptr(&tiadc_pm_ops),
.of_match_table = ti_adc_dt_ids,
},
- .probe = tiadc_probe,
- .remove_new = tiadc_remove,
+ .probe = tiadc_probe,
+ .remove = tiadc_remove,
};
module_platform_driver(tiadc_driver);
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 0253064fadec..0ea51ddeaa0a 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -248,7 +248,7 @@ static const struct s16_fract twl4030_divider_ratios[16] = {
{15, 100}, /* CHANNEL 11 */
{1, 4}, /* CHANNEL 12 */
{1, 1}, /* CHANNEL 13 Reserved channels */
- {1, 1}, /* CHANNEL 14 Reseved channels */
+ {1, 1}, /* CHANNEL 14 Reserved channels */
{5, 11}, /* CHANNEL 15 */
};
@@ -914,7 +914,7 @@ MODULE_DEVICE_TABLE(of, twl_madc_of_match);
static struct platform_driver twl4030_madc_driver = {
.probe = twl4030_madc_probe,
- .remove_new = twl4030_madc_remove,
+ .remove = twl4030_madc_remove,
.driver = {
.name = "twl4030_madc",
.of_match_table = twl_madc_of_match,
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 6a3db2bce460..ef7430e6877d 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -1003,7 +1003,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend,
static struct platform_driver twl6030_gpadc_driver = {
.probe = twl6030_gpadc_probe,
- .remove_new = twl6030_gpadc_remove,
+ .remove = twl6030_gpadc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops),
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 5afd2feb8c3d..4d83c12975c5 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -972,7 +972,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend,
static struct platform_driver vf610_adc_driver = {
.probe = vf610_adc_probe,
- .remove_new = vf610_adc_remove,
+ .remove = vf610_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = vf610_adc_match,
diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index ebc583b07e0c..76dd0343f5f7 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -905,7 +905,7 @@ static int ams_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct ams *ams = iio_priv(indio_dev);
unsigned int alarm;
diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
index 1bd375fb10e0..c188d3dcab48 100644
--- a/drivers/iio/adc/xilinx-xadc-events.c
+++ b/drivers/iio/adc/xilinx-xadc-events.c
@@ -121,7 +121,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev,
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
unsigned int alarm = xadc_get_alarm_mask(chan);
struct xadc *xadc = iio_priv(indio_dev);
@@ -220,7 +220,7 @@ int xadc_write_event_value(struct iio_dev *indio_dev,
/*
* Since we store the hysteresis as relative (to the threshold)
* value, but the hardware expects an absolute value we need to
- * recalcualte this value whenever the hysteresis or the
+ * recalculate this value whenever the hysteresis or the
* threshold changes.
*/
if (xadc->threshold[offset] < xadc->temp_hysteresis)
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
index 3036f4d613ff..b4d9d4683117 100644
--- a/drivers/iio/adc/xilinx-xadc.h
+++ b/drivers/iio/adc/xilinx-xadc.h
@@ -25,7 +25,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev,
enum iio_event_direction dir);
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state);
+ enum iio_event_direction dir, bool state);
int xadc_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
diff --git a/drivers/iio/addac/ad74115.c b/drivers/iio/addac/ad74115.c
index 3ee0dd5537c1..a7e480f2472d 100644
--- a/drivers/iio/addac/ad74115.c
+++ b/drivers/iio/addac/ad74115.c
@@ -191,7 +191,7 @@ enum ad74115_gpio_mode {
};
struct ad74115_channels {
- struct iio_chan_spec *channels;
+ const struct iio_chan_spec *channels;
unsigned int num_channels;
};
@@ -1295,46 +1295,46 @@ static const struct iio_info ad74115_info = {
_AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET))
-static struct iio_chan_spec ad74115_voltage_input_channels[] = {
+static const struct iio_chan_spec ad74115_voltage_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_voltage_output_channels[] = {
+static const struct iio_chan_spec ad74115_voltage_output_channels[] = {
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN),
AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_current_input_channels[] = {
+static const struct iio_chan_spec ad74115_current_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_current_output_channels[] = {
+static const struct iio_chan_spec ad74115_current_output_channels[] = {
AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
_AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1,
BIT(IIO_CHAN_INFO_PROCESSED)),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
+static const struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
+static const struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c
index 69c586525d21..daea2bde7acf 100644
--- a/drivers/iio/addac/ad74413r.c
+++ b/drivers/iio/addac/ad74413r.c
@@ -6,9 +6,11 @@
#include <linux/unaligned.h>
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/crc8.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
@@ -45,8 +47,8 @@ struct ad74413r_channel_config {
};
struct ad74413r_channels {
- struct iio_chan_spec *channels;
- unsigned int num_channels;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
};
struct ad74413r_state {
@@ -59,7 +61,7 @@ struct ad74413r_state {
unsigned int num_gpo_gpios;
unsigned int num_comparator_gpios;
u32 sense_resistor_ohms;
-
+ int refin_reg_uv;
/*
* Synchronize consecutive operations when doing a one-shot
* conversion and when updating the ADC samples SPI message.
@@ -68,11 +70,9 @@ struct ad74413r_state {
const struct ad74413r_chip_info *chip_info;
struct spi_device *spi;
- struct regulator *refin_reg;
struct regmap *regmap;
struct device *dev;
struct iio_trigger *trig;
- struct gpio_desc *reset_gpio;
size_t adc_active_channels;
struct spi_message adc_samples_msg;
@@ -407,12 +407,16 @@ static int ad74413r_gpio_set_comp_config(struct gpio_chip *chip,
static int ad74413r_reset(struct ad74413r_state *st)
{
+ struct gpio_desc *reset_gpio;
int ret;
- if (st->reset_gpio) {
- gpiod_set_value_cansleep(st->reset_gpio, 1);
+ reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ if (reset_gpio) {
fsleep(50);
- gpiod_set_value_cansleep(st->reset_gpio, 0);
+ gpiod_set_value_cansleep(reset_gpio, 0);
return 0;
}
@@ -660,7 +664,7 @@ static int ad74413r_get_output_voltage_scale(struct ad74413r_state *st,
static int ad74413r_get_output_current_scale(struct ad74413r_state *st,
int *val, int *val2)
{
- *val = regulator_get_voltage(st->refin_reg);
+ *val = st->refin_reg_uv;
*val2 = st->sense_resistor_ohms * AD74413R_DAC_CODE_MAX * 1000;
return IIO_VAL_FRACTIONAL;
@@ -861,19 +865,12 @@ static int ad74413r_get_single_adc_result(struct iio_dev *indio_dev,
unsigned int channel, int *val)
{
struct ad74413r_state *st = iio_priv(indio_dev);
- int ret;
-
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
-
- mutex_lock(&st->lock);
- ret = _ad74413r_get_single_adc_result(st, channel, val);
- mutex_unlock(&st->lock);
-
- iio_device_release_direct_mode(indio_dev);
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ guard(mutex)(&st->lock);
+ return _ad74413r_get_single_adc_result(st, channel, val);
+ }
+ unreachable();
}
static void ad74413r_adc_to_resistance_result(int adc_result, int *val)
@@ -895,7 +892,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
unsigned int channel;
int ret = -EINVAL;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
spi_message_init(&st->adc_samples_msg);
st->adc_active_channels = 0;
@@ -903,11 +900,11 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
for_each_clear_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
ret = ad74413r_set_adc_channel_enable(st, channel, false);
if (ret)
- goto out;
+ return ret;
}
if (*active_scan_mask == 0)
- goto out;
+ return ret;
/*
* The read select register is used to select which register's value
@@ -925,7 +922,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
for_each_set_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
ret = ad74413r_set_adc_channel_enable(st, channel, true);
if (ret)
- goto out;
+ return ret;
st->adc_active_channels++;
@@ -956,11 +953,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
xfer->cs_change = 0;
spi_message_add_tail(xfer, &st->adc_samples_msg);
-
-out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static int ad74413r_buffer_postenable(struct iio_dev *indio_dev)
@@ -1138,34 +1131,34 @@ static const struct iio_info ad74413r_info = {
AD74413R_ADC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET))
-static struct iio_chan_spec ad74413r_voltage_output_channels[] = {
+static const struct iio_chan_spec ad74413r_voltage_output_channels[] = {
AD74413R_DAC_CHANNEL(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_output_channels[] = {
+static const struct iio_chan_spec ad74413r_current_output_channels[] = {
AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_VOLTAGE_CHANNEL,
};
-static struct iio_chan_spec ad74413r_voltage_input_channels[] = {
+static const struct iio_chan_spec ad74413r_voltage_input_channels[] = {
AD74413R_ADC_VOLTAGE_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_input_channels[] = {
+static const struct iio_chan_spec ad74413r_current_input_channels[] = {
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_input_loop_channels[] = {
+static const struct iio_chan_spec ad74413r_current_input_loop_channels[] = {
AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74413r_resistance_input_channels[] = {
AD74413R_ADC_CHANNEL(IIO_RESISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)),
};
-static struct iio_chan_spec ad74413r_digital_input_channels[] = {
+static const struct iio_chan_spec ad74413r_digital_input_channels[] = {
AD74413R_ADC_VOLTAGE_CHANNEL,
};
@@ -1270,7 +1263,8 @@ static int ad74413r_setup_channels(struct iio_dev *indio_dev)
{
struct ad74413r_state *st = iio_priv(indio_dev);
struct ad74413r_channel_config *config;
- struct iio_chan_spec *channels, *chans;
+ const struct iio_chan_spec *chans;
+ struct iio_chan_spec *channels;
unsigned int i, num_chans, chan_i;
int ret;
@@ -1346,11 +1340,6 @@ static int ad74413r_setup_gpios(struct ad74413r_state *st)
return 0;
}
-static void ad74413r_regulator_disable(void *regulator)
-{
- regulator_disable(regulator);
-}
-
static int ad74413r_probe(struct spi_device *spi)
{
struct ad74413r_state *st;
@@ -1369,7 +1358,10 @@ static int ad74413r_probe(struct spi_device *spi)
if (!st->chip_info)
return -EINVAL;
- mutex_init(&st->lock);
+ ret = devm_mutex_init(st->dev, &st->lock);
+ if (ret)
+ return ret;
+
init_completion(&st->adc_data_completion);
st->regmap = devm_regmap_init(st->dev, NULL, st,
@@ -1377,23 +1369,11 @@ static int ad74413r_probe(struct spi_device *spi)
if (IS_ERR(st->regmap))
return PTR_ERR(st->regmap);
- st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(st->reset_gpio))
- return PTR_ERR(st->reset_gpio);
-
- st->refin_reg = devm_regulator_get(st->dev, "refin");
- if (IS_ERR(st->refin_reg))
- return dev_err_probe(st->dev, PTR_ERR(st->refin_reg),
- "Failed to get refin regulator\n");
-
- ret = regulator_enable(st->refin_reg);
- if (ret)
- return ret;
-
- ret = devm_add_action_or_reset(st->dev, ad74413r_regulator_disable,
- st->refin_reg);
- if (ret)
- return ret;
+ ret = devm_regulator_get_enable_read_voltage(st->dev, "refin");
+ if (ret < 0)
+ return dev_err_probe(st->dev, ret,
+ "Failed to get refin regulator voltage\n");
+ st->refin_reg_uv = ret;
st->sense_resistor_ohms = 100000000;
device_property_read_u32(st->dev, "shunt-resistor-micro-ohms",
diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c
index 4c03b9e834b8..e64a41bae32c 100644
--- a/drivers/iio/cdc/ad7150.c
+++ b/drivers/iio/cdc/ad7150.c
@@ -232,7 +232,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev,
static int ad7150_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ad7150_chip_info *chip = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index 6c87223f58d9..330fe0af946f 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -50,6 +50,8 @@ config BME680
select REGMAP
select BME680_I2C if I2C
select BME680_SPI if SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Bosch Sensortec BME680 sensor with
temperature, pressure, humidity and gas sensing capability.
diff --git a/drivers/iio/chemical/bme680.h b/drivers/iio/chemical/bme680.h
index b2c547ac8d34..00ab89b3138b 100644
--- a/drivers/iio/chemical/bme680.h
+++ b/drivers/iio/chemical/bme680.h
@@ -2,6 +2,8 @@
#ifndef BME680_H_
#define BME680_H_
+#include <linux/regmap.h>
+
#define BME680_REG_CHIP_ID 0xD0
#define BME680_CHIP_ID_VAL 0x61
#define BME680_REG_SOFT_RESET 0xE0
@@ -25,8 +27,6 @@
#define BME680_OSRS_TEMP_MASK GENMASK(7, 5)
#define BME680_OSRS_PRESS_MASK GENMASK(4, 2)
#define BME680_MODE_MASK GENMASK(1, 0)
-#define BME680_MODE_FORCED 1
-#define BME680_MODE_SLEEP 0
#define BME680_REG_CONFIG 0x75
#define BME680_FILTER_MASK GENMASK(4, 2)
@@ -42,6 +42,7 @@
#define BME680_RHRANGE_MASK GENMASK(5, 4)
#define BME680_REG_RES_HEAT_VAL 0x00
#define BME680_RSERROR_MASK GENMASK(7, 4)
+#define BME680_REG_IDAC_HEAT_0 0x50
#define BME680_REG_RES_HEAT_0 0x5A
#define BME680_REG_GAS_WAIT_0 0x64
#define BME680_ADC_GAS_RES GENMASK(15, 6)
@@ -63,7 +64,11 @@
#define BME680_MEAS_TRIM_MASK GENMASK(24, 4)
-#define BME680_STARTUP_TIME_US 5000
+/* Datasheet Section 1.1, Table 1 */
+#define BME680_STARTUP_TIME_US 2000
+
+#define BME680_NUM_CHANNELS 4
+#define BME680_NUM_BULK_READ_REGS 15
/* Calibration Parameters */
#define BME680_T2_LSB_REG 0x8A
diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c
index 0b96534c6867..9783953e64e0 100644
--- a/drivers/iio/chemical/bme680_core.c
+++ b/drivers/iio/chemical/bme680_core.c
@@ -16,8 +16,11 @@
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/unaligned.h>
@@ -95,6 +98,19 @@ struct bme680_calib {
s8 range_sw_err;
};
+/* values of CTRL_MEAS register */
+enum bme680_op_mode {
+ BME680_MODE_SLEEP = 0,
+ BME680_MODE_FORCED = 1,
+};
+
+enum bme680_scan {
+ BME680_TEMP,
+ BME680_PRESS,
+ BME680_HUMID,
+ BME680_GAS,
+};
+
struct bme680_data {
struct regmap *regmap;
struct bme680_calib bme680;
@@ -102,11 +118,17 @@ struct bme680_data {
u8 oversampling_temp;
u8 oversampling_press;
u8 oversampling_humid;
+ u8 preheat_curr_mA;
u16 heater_dur;
u16 heater_temp;
+ struct {
+ s32 chan[4];
+ aligned_s64 ts;
+ } scan;
+
union {
- u8 buf[3];
+ u8 buf[BME680_NUM_BULK_READ_REGS];
unsigned int check;
__be16 be16;
u8 bme680_cal_buf_1[BME680_CALIB_RANGE_1_LEN];
@@ -138,22 +160,66 @@ EXPORT_SYMBOL_NS(bme680_regmap_config, IIO_BME680);
static const struct iio_chan_spec bme680_channels[] = {
{
.type = IIO_TEMP,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_PRESSURE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_HUMIDITYRELATIVE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_RESISTANCE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ {
+ .type = IIO_CURRENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .output = 1,
+ .scan_index = -1,
},
};
@@ -224,7 +290,7 @@ static int bme680_read_calib(struct bme680_data *data,
calib->res_heat_val = data->bme680_cal_buf_3[RES_HEAT_VAL];
calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK,
- data->bme680_cal_buf_3[RES_HEAT_RANGE]);
+ data->bme680_cal_buf_3[RES_HEAT_RANGE]);
calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK,
data->bme680_cal_buf_3[RANGE_SW_ERR]);
@@ -438,19 +504,19 @@ static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
u32 calc_gas_res;
/* Look up table for the possible gas range values */
- static const u32 lookupTable[16] = {2147483647u, 2147483647u,
- 2147483647u, 2147483647u, 2147483647u,
- 2126008810u, 2147483647u, 2130303777u,
- 2147483647u, 2147483647u, 2143188679u,
- 2136746228u, 2147483647u, 2126008810u,
- 2147483647u, 2147483647u};
-
- var1 = ((1340 + (5 * (s64) calib->range_sw_err)) *
- ((s64) lookupTable[gas_range])) >> 16;
+ static const u32 lookup_table[16] = {
+ 2147483647u, 2147483647u, 2147483647u, 2147483647u,
+ 2147483647u, 2126008810u, 2147483647u, 2130303777u,
+ 2147483647u, 2147483647u, 2143188679u, 2136746228u,
+ 2147483647u, 2126008810u, 2147483647u, 2147483647u
+ };
+
+ var1 = ((1340LL + (5 * calib->range_sw_err)) *
+ (lookup_table[gas_range])) >> 16;
var2 = ((gas_res_adc << 15) - 16777216) + var1;
var3 = ((125000 << (15 - gas_range)) * var1) >> 9;
var3 += (var2 >> 1);
- calc_gas_res = div64_s64(var3, (s64) var2);
+ calc_gas_res = div64_s64(var3, (s64)var2);
return calc_gas_res;
}
@@ -468,7 +534,7 @@ static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp)
if (temp > 400) /* Cap temperature */
temp = 400;
- var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
+ var1 = (((s32)BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) *
temp * 5) / 100)
+ 3276800) / 10);
@@ -502,23 +568,22 @@ static u8 bme680_calc_heater_dur(u16 dur)
return durval;
}
-static int bme680_set_mode(struct bme680_data *data, bool mode)
+/* Taken from datasheet, section 5.3.3 */
+static u8 bme680_calc_heater_preheat_current(u8 curr)
+{
+ return 8 * curr - 1;
+}
+
+static int bme680_set_mode(struct bme680_data *data, enum bme680_op_mode mode)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
- if (mode) {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_FORCED);
- if (ret < 0)
- dev_err(dev, "failed to set forced mode\n");
-
- } else {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_SLEEP);
- if (ret < 0)
- dev_err(dev, "failed to set sleep mode\n");
-
+ ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
+ BME680_MODE_MASK, mode);
+ if (ret < 0) {
+ dev_err(dev, "failed to set ctrl_meas register\n");
+ return ret;
}
return ret;
@@ -546,7 +611,7 @@ static int bme680_wait_for_eoc(struct bme680_data *data)
data->oversampling_humid) * 1936) + (477 * 4) +
(477 * 5) + 1000 + (data->heater_dur * 1000);
- usleep_range(wait_eoc_us, wait_eoc_us + 100);
+ fsleep(wait_eoc_us);
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &data->check);
if (ret) {
@@ -571,9 +636,8 @@ static int bme680_chip_config(struct bme680_data *data)
int ret;
u8 osrs;
- osrs = FIELD_PREP(
- BME680_OSRS_HUMIDITY_MASK,
- bme680_oversampling_to_reg(data->oversampling_humid));
+ osrs = FIELD_PREP(BME680_OSRS_HUMIDITY_MASK,
+ bme680_oversampling_to_reg(data->oversampling_humid));
/*
* Highly recommended to set oversampling of humidity before
* temperature/pressure oversampling.
@@ -587,8 +651,7 @@ static int bme680_chip_config(struct bme680_data *data)
/* IIR filter settings */
ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG,
- BME680_FILTER_MASK,
- BME680_FILTER_COEFF_VAL);
+ BME680_FILTER_MASK, BME680_FILTER_COEFF_VAL);
if (ret < 0) {
dev_err(dev, "failed to write config register\n");
return ret;
@@ -609,14 +672,27 @@ static int bme680_chip_config(struct bme680_data *data)
return 0;
}
+static int bme680_preheat_curr_config(struct bme680_data *data, u8 val)
+{
+ struct device *dev = regmap_get_device(data->regmap);
+ u8 heatr_curr;
+ int ret;
+
+ heatr_curr = bme680_calc_heater_preheat_current(val);
+ ret = regmap_write(data->regmap, BME680_REG_IDAC_HEAT_0, heatr_curr);
+ if (ret < 0)
+ dev_err(dev, "failed to write idac_heat_0 register\n");
+
+ return ret;
+}
+
static int bme680_gas_config(struct bme680_data *data)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
u8 heatr_res, heatr_dur;
- /* Go to sleep */
- ret = bme680_set_mode(data, false);
+ ret = bme680_set_mode(data, BME680_MODE_SLEEP);
if (ret < 0)
return ret;
@@ -638,6 +714,10 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
+ ret = bme680_preheat_curr_config(data, data->preheat_curr_mA);
+ if (ret)
+ return ret;
+
/* Enable the gas sensor and select heater profile set-point 0 */
ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1,
BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK,
@@ -649,23 +729,20 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
-static int bme680_read_temp(struct bme680_data *data, int *val)
+static int bme680_read_temp(struct bme680_data *data, s16 *comp_temp)
{
int ret;
u32 adc_temp;
- s16 comp_temp;
ret = bme680_read_temp_adc(data, &adc_temp);
if (ret)
return ret;
- comp_temp = bme680_compensate_temp(data, adc_temp);
- *val = comp_temp * 10; /* Centidegrees to millidegrees */
- return IIO_VAL_INT;
+ *comp_temp = bme680_compensate_temp(data, adc_temp);
+ return 0;
}
-static int bme680_read_press(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_press(struct bme680_data *data, u32 *comp_press)
{
int ret;
u32 adc_press;
@@ -679,16 +756,14 @@ static int bme680_read_press(struct bme680_data *data,
if (ret)
return ret;
- *val = bme680_compensate_press(data, adc_press, t_fine);
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_press = bme680_compensate_press(data, adc_press, t_fine);
+ return 0;
}
-static int bme680_read_humid(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_humid(struct bme680_data *data, u32 *comp_humidity)
{
int ret;
- u32 adc_humidity, comp_humidity;
+ u32 adc_humidity;
s32 t_fine;
ret = bme680_get_t_fine(data, &t_fine);
@@ -699,15 +774,11 @@ static int bme680_read_humid(struct bme680_data *data,
if (ret)
return ret;
- comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
-
- *val = comp_humidity;
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
+ return 0;
}
-static int bme680_read_gas(struct bme680_data *data,
- int *val)
+static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
@@ -742,9 +813,8 @@ static int bme680_read_gas(struct bme680_data *data,
}
gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
-
- *val = bme680_compensate_gas(data, adc_gas_res, gas_range);
- return IIO_VAL_INT;
+ *comp_gas_res = bme680_compensate_gas(data, adc_gas_res, gas_range);
+ return 0;
}
static int bme680_read_raw(struct iio_dev *indio_dev,
@@ -752,12 +822,12 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct bme680_data *data = iio_priv(indio_dev);
- int ret;
+ int chan_val, ret;
+ s16 temp_chan_val;
guard(mutex)(&data->lock);
- /* set forced mode to trigger measurement */
- ret = bme680_set_mode(data, true);
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
if (ret < 0)
return ret;
@@ -769,13 +839,77 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_TEMP:
- return bme680_read_temp(data, val);
+ ret = bme680_read_temp(data, &temp_chan_val);
+ if (ret)
+ return ret;
+
+ *val = temp_chan_val * 10;
+ return IIO_VAL_INT;
case IIO_PRESSURE:
- return bme680_read_press(data, val, val2);
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_HUMIDITYRELATIVE:
- return bme680_read_humid(data, val, val2);
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_RESISTANCE:
- return bme680_read_gas(data, val);
+ ret = bme680_read_gas(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_TEMP:
+ ret = bme680_read_temp(data, (s16 *)&chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ case IIO_HUMIDITYRELATIVE:
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = 10;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_HUMIDITYRELATIVE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
@@ -836,6 +970,15 @@ static int bme680_write_raw(struct iio_dev *indio_dev,
return bme680_chip_config(data);
}
+ case IIO_CHAN_INFO_PROCESSED:
+ {
+ switch (chan->type) {
+ case IIO_CURRENT:
+ return bme680_preheat_curr_config(data, (u8)val);
+ default:
+ return -EINVAL;
+ }
+ }
default:
return -EINVAL;
}
@@ -861,6 +1004,86 @@ static const struct iio_info bme680_info = {
.attrs = &bme680_attribute_group,
};
+static const unsigned long bme680_avail_scan_masks[] = {
+ BIT(BME680_GAS) | BIT(BME680_HUMID) | BIT(BME680_PRESS) | BIT(BME680_TEMP),
+ 0
+};
+
+static irqreturn_t bme680_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+ u32 adc_temp, adc_press, adc_humid;
+ u16 adc_gas_res, gas_regs_val;
+ u8 gas_range;
+ s32 t_fine;
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
+ if (ret < 0)
+ goto out;
+
+ ret = bme680_wait_for_eoc(data);
+ if (ret)
+ goto out;
+
+ ret = regmap_bulk_read(data->regmap, BME680_REG_MEAS_STAT_0,
+ data->buf, sizeof(data->buf));
+ if (ret) {
+ dev_err(dev, "failed to burst read sensor data\n");
+ goto out;
+ }
+ if (data->buf[0] & BME680_GAS_MEAS_BIT) {
+ dev_err(dev, "gas measurement incomplete\n");
+ goto out;
+ }
+
+ /* Temperature calculations */
+ adc_temp = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[5]));
+ if (adc_temp == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading temperature skipped\n");
+ goto out;
+ }
+ data->scan.chan[0] = bme680_compensate_temp(data, adc_temp);
+ t_fine = bme680_calc_t_fine(data, adc_temp);
+
+ /* Pressure calculations */
+ adc_press = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[2]));
+ if (adc_press == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading pressure skipped\n");
+ goto out;
+ }
+ data->scan.chan[1] = bme680_compensate_press(data, adc_press, t_fine);
+
+ /* Humidity calculations */
+ adc_humid = get_unaligned_be16(&data->buf[8]);
+ if (adc_humid == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading humidity skipped\n");
+ goto out;
+ }
+ data->scan.chan[2] = bme680_compensate_humid(data, adc_humid, t_fine);
+
+ /* Gas calculations */
+ gas_regs_val = get_unaligned_be16(&data->buf[13]);
+ adc_gas_res = FIELD_GET(BME680_ADC_GAS_RES, gas_regs_val);
+ if ((gas_regs_val & BME680_GAS_STAB_BIT) == 0) {
+ dev_err(dev, "heater failed to reach the target temperature\n");
+ goto out;
+ }
+ gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
+ data->scan.chan[3] = bme680_compensate_gas(data, adc_gas_res, gas_range);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ iio_get_time_ns(indio_dev));
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
int bme680_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
@@ -879,6 +1102,7 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
indio_dev->name = name;
indio_dev->channels = bme680_channels;
indio_dev->num_channels = ARRAY_SIZE(bme680_channels);
+ indio_dev->available_scan_masks = bme680_avail_scan_masks;
indio_dev->info = &bme680_info;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -888,13 +1112,13 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
data->oversampling_temp = 8; /* 8X oversampling rate */
data->heater_temp = 320; /* degree Celsius */
data->heater_dur = 150; /* milliseconds */
+ data->preheat_curr_mA = 0;
- ret = regmap_write(regmap, BME680_REG_SOFT_RESET,
- BME680_CMD_SOFTRESET);
+ ret = regmap_write(regmap, BME680_REG_SOFT_RESET, BME680_CMD_SOFTRESET);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to reset chip\n");
- usleep_range(BME680_STARTUP_TIME_US, BME680_STARTUP_TIME_US + 1000);
+ fsleep(BME680_STARTUP_TIME_US);
ret = regmap_read(regmap, BME680_REG_CHIP_ID, &data->check);
if (ret < 0)
@@ -922,6 +1146,14 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
return dev_err_probe(dev, ret,
"failed to set gas config data\n");
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ bme680_trigger_handler,
+ NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "iio triggered buffer setup failed\n");
+
return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680);
diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
index f44458c380d9..37d0bdaa8d82 100644
--- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
+++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
@@ -70,6 +70,10 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts,
if (mult != ts->mult)
ts->new_mult = mult;
+ /* When FIFO is off, directly apply the new ODR */
+ if (!fifo)
+ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
+
return 0;
}
EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP);
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index a0df9250a69f..a55967208cdc 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -134,11 +134,11 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
iio_trigger_set_drvdata(sdata->trig, indio_dev);
sdata->trig->ops = trigger_ops;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq));
/*
* If the IRQ is triggered on falling edge, we need to mark the
* interrupt as active low, if the hardware supports this.
*/
+ irq_trig = irq_get_trigger_type(sdata->irq);
switch(irq_trig) {
case IRQF_TRIGGER_FALLING:
case IRQF_TRIGGER_LOW:
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 9f5d5ebb8653..5d01ba4edbf3 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -6,9 +6,28 @@
menu "Digital to analog converters"
+config AD3552R_HS
+ tristate "Analog Devices AD3552R DAC High Speed driver"
+ select AD3552R_LIB
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices AD3552R
+ Digital to Analog Converter High Speed driver.
+
+ The driver requires the assistance of an IP core to operate,
+ since data is streamed into target device via DMA, sent over a
+ QSPI + DDR (Double Data Rate) bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad3552r-hs.
+
+config AD3552R_LIB
+ tristate
+
config AD3552R
tristate "Analog Devices AD3552R DAC driver"
depends on SPI_MASTER
+ select AD3552R_LIB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
@@ -306,6 +325,19 @@ config AD7303
To compile this driver as module choose M here: the module will be called
ad7303.
+config AD8460
+ tristate "Analog Devices AD8460 DAC driver"
+ depends on SPI
+ select REGMAP_SPI
+ select IIO_BUFFER
+ select IIO_BUFFER_DMAENGINE
+ help
+ Say yes here to build support for Analog Devices AD8460 Digital to
+ Analog Converters (DAC).
+
+ To compile this driver as a module choose M here: the module will be called
+ ad8460.
+
config AD8801
tristate "Analog Devices AD8801/AD8803 DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 2cf148f16306..414c152be779 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -4,6 +4,8 @@
#
# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AD3552R_HS) += ad3552r-hs.o
+obj-$(CONFIG_AD3552R_LIB) += ad3552r-common.o
obj-$(CONFIG_AD3552R) += ad3552r.o
obj-$(CONFIG_AD5360) += ad5360.o
obj-$(CONFIG_AD5380) += ad5380.o
@@ -28,6 +30,7 @@ obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o
obj-$(CONFIG_AD7293) += ad7293.o
obj-$(CONFIG_AD7303) += ad7303.o
+obj-$(CONFIG_AD8460) += ad8460.o
obj-$(CONFIG_AD8801) += ad8801.o
obj-$(CONFIG_AD9739A) += ad9739a.o
obj-$(CONFIG_ADI_AXI_DAC) += adi-axi-dac.o
diff --git a/drivers/iio/dac/ad3552r-common.c b/drivers/iio/dac/ad3552r-common.c
new file mode 100644
index 000000000000..2dfeca3656d2
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-common.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2010-2024 Analog Devices Inc.
+// Copyright (c) 2024 Baylibre, SAS
+
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+
+#include "ad3552r.h"
+
+const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2] = {
+ [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 },
+ [AD3552R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 },
+ [AD3552R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 },
+ [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 },
+ [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = { -10000, 10000 }
+};
+EXPORT_SYMBOL_NS_GPL(ad3552r_ch_ranges, IIO_AD3552R);
+
+const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2] = {
+ [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 },
+ [AD3542R_CH_OUTPUT_RANGE_0__3V] = { 0, 3000 },
+ [AD3542R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 },
+ [AD3542R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 },
+ [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = { -2500, 7500 },
+ [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 }
+};
+EXPORT_SYMBOL_NS_GPL(ad3542r_ch_ranges, IIO_AD3552R);
+
+/* Gain * AD3552R_GAIN_SCALE */
+static const s32 gains_scaling_table[] = {
+ [AD3552R_CH_GAIN_SCALING_1] = 1000,
+ [AD3552R_CH_GAIN_SCALING_0_5] = 500,
+ [AD3552R_CH_GAIN_SCALING_0_25] = 250,
+ [AD3552R_CH_GAIN_SCALING_0_125] = 125
+};
+
+u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs)
+{
+ return FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1) |
+ FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, p) |
+ FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, n) |
+ FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, abs(goffs)) |
+ FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, goffs < 0);
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_calc_custom_gain, IIO_AD3552R);
+
+static void ad3552r_get_custom_range(struct ad3552r_ch_data *ch_data,
+ s32 *v_min, s32 *v_max)
+{
+ s64 vref, tmp, common, offset, gn, gp;
+ /*
+ * From datasheet formula (In Volts):
+ * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03]
+ * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03]
+ * Calculus are converted to milivolts
+ */
+ vref = 2500;
+ /* 2.5 * 1.03 * 1000 (To mV) */
+ common = 2575 * ch_data->rfb;
+ offset = ch_data->gain_offset;
+
+ gn = gains_scaling_table[ch_data->n];
+ tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common;
+ tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
+ *v_max = vref + tmp;
+
+ gp = gains_scaling_table[ch_data->p];
+ tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common;
+ tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
+ *v_min = vref - tmp;
+}
+
+void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data,
+ const struct ad3552r_model_data *model_data)
+{
+ s32 idx, v_max, v_min, span, rem;
+ s64 tmp;
+
+ if (ch_data->range_override) {
+ ad3552r_get_custom_range(ch_data, &v_min, &v_max);
+ } else {
+ /* Normal range */
+ idx = ch_data->range;
+ v_min = model_data->ranges_table[idx][0];
+ v_max = model_data->ranges_table[idx][1];
+ }
+
+ /*
+ * From datasheet formula:
+ * Vout = Span * (D / 65536) + Vmin
+ * Converted to scale and offset:
+ * Scale = Span / 65536
+ * Offset = 65536 * Vmin / Span
+ *
+ * Reminders are in micros in order to be printed as
+ * IIO_VAL_INT_PLUS_MICRO
+ */
+ span = v_max - v_min;
+ ch_data->scale_int = div_s64_rem(span, 65536, &rem);
+ /* Do operations in microvolts */
+ ch_data->scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000, 65536);
+
+ ch_data->offset_int = div_s64_rem(v_min * 65536, span, &rem);
+ tmp = (s64)rem * 1000000;
+ ch_data->offset_dec = div_s64(tmp, span);
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_calc_gain_and_offset, IIO_AD3552R);
+
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val)
+{
+ int voltage;
+ int delta = 100000;
+
+ voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
+ if (voltage < 0 && voltage != -ENODEV)
+ return dev_err_probe(dev, voltage,
+ "Error getting vref voltage\n");
+
+ if (voltage == -ENODEV) {
+ if (device_property_read_bool(dev, "adi,vref-out-en"))
+ *val = AD3552R_INTERNAL_VREF_PIN_2P5V;
+ else
+ *val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
+
+ return 0;
+ }
+
+ if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
+ dev_warn(dev, "vref-supply must be 2.5V");
+ return -EINVAL;
+ }
+
+ *val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_ref_voltage, IIO_AD3552R);
+
+int ad3552r_get_drive_strength(struct device *dev, u32 *val)
+{
+ int err;
+ u32 drive_strength;
+
+ err = device_property_read_u32(dev, "adi,sdo-drive-strength",
+ &drive_strength);
+ if (err)
+ return err;
+
+ if (drive_strength > 3) {
+ dev_err_probe(dev, -EINVAL,
+ "adi,sdo-drive-strength must be less than 4\n");
+ return -EINVAL;
+ }
+
+ *val = drive_strength;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_drive_strength, IIO_AD3552R);
+
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs)
+{
+ int err;
+ u32 val;
+ struct fwnode_handle *gain_child __free(fwnode_handle) =
+ fwnode_get_named_child_node(child,
+ "custom-output-range-config");
+
+ if (!gain_child)
+ return dev_err_probe(dev, -EINVAL,
+ "custom-output-range-config mandatory\n");
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-p mandatory\n");
+ *gs_p = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-n property mandatory\n");
+ *gs_n = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,rfb-ohms mandatory\n");
+ *rfb = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-offset mandatory\n");
+ *goffs = val;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_custom_gain, IIO_AD3552R);
+
+static int ad3552r_find_range(const struct ad3552r_model_data *model_info,
+ s32 *vals)
+{
+ int i;
+
+ for (i = 0; i < model_info->num_ranges; i++)
+ if (vals[0] == model_info->ranges_table[i][0] * 1000 &&
+ vals[1] == model_info->ranges_table[i][1] * 1000)
+ return i;
+
+ return -EINVAL;
+}
+
+int ad3552r_get_output_range(struct device *dev,
+ const struct ad3552r_model_data *model_info,
+ struct fwnode_handle *child, u32 *val)
+{
+ int ret;
+ s32 vals[2];
+
+ /* This property is optional, so returning -ENOENT if missing */
+ if (!fwnode_property_present(child, "adi,output-range-microvolt"))
+ return -ENOENT;
+
+ ret = fwnode_property_read_u32_array(child,
+ "adi,output-range-microvolt",
+ vals, 2);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt\n");
+
+ ret = ad3552r_find_range(model_info, vals);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt value\n");
+
+ *val = ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_output_range, IIO_AD3552R);
+
+MODULE_DESCRIPTION("ad3552r common functions");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/dac/ad3552r-hs.c b/drivers/iio/dac/ad3552r-hs.c
new file mode 100644
index 000000000000..d5c704adf5bf
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-hs.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices AD3552R
+ * Digital to Analog converter driver, High Speed version
+ *
+ * Copyright 2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/backend.h>
+#include <linux/iio/buffer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/units.h>
+
+#include "ad3552r.h"
+#include "ad3552r-hs.h"
+
+struct ad3552r_hs_state {
+ const struct ad3552r_model_data *model_data;
+ struct gpio_desc *reset_gpio;
+ struct device *dev;
+ struct iio_backend *back;
+ bool single_channel;
+ struct ad3552r_ch_data ch_data[AD3552R_MAX_CH];
+ struct ad3552r_hs_platform_data *data;
+};
+
+static int ad3552r_qspi_update_reg_bits(struct ad3552r_hs_state *st,
+ u32 reg, u32 mask, u32 val,
+ size_t xfer_size)
+{
+ u32 rval;
+ int ret;
+
+ ret = st->data->bus_reg_read(st->back, reg, &rval, xfer_size);
+ if (ret)
+ return ret;
+
+ rval = (rval & ~mask) | val;
+
+ return st->data->bus_reg_write(st->back, reg, rval, xfer_size);
+}
+
+static int ad3552r_hs_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ int ret;
+ int ch = chan->channel;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ /*
+ * Using 4 lanes (QSPI), then using 2 as DDR mode is
+ * considered always on (considering buffering mode always).
+ */
+ *val = DIV_ROUND_CLOSEST(st->data->bus_sample_data_clock_hz *
+ 4 * 2, chan->scan_type.realbits);
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_RAW:
+ ret = st->data->bus_reg_read(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(chan->channel),
+ val, 2);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->ch_data[ch].scale_int;
+ *val2 = st->ch_data[ch].scale_dec;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = st->ch_data[ch].offset_int;
+ *val2 = st->ch_data[ch].offset_dec;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_hs_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ return st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(chan->channel),
+ val, 2);
+ }
+ unreachable();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_hs_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ struct iio_backend_data_fmt fmt = {
+ .type = IIO_BACKEND_DATA_UNSIGNED
+ };
+ int loop_len, val, ret;
+
+ switch (*indio_dev->active_scan_mask) {
+ case AD3552R_CH0_ACTIVE:
+ st->single_channel = true;
+ loop_len = 2;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(0);
+ break;
+ case AD3552R_CH1_ACTIVE:
+ st->single_channel = true;
+ loop_len = 2;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ case AD3552R_CH0_ACTIVE | AD3552R_CH1_ACTIVE:
+ st->single_channel = false;
+ loop_len = 4;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE,
+ loop_len, 1);
+ if (ret)
+ return ret;
+
+ /* Inform DAC chip to switch into DDR mode */
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ AD3552R_MASK_SPI_CONFIG_DDR, 1);
+ if (ret)
+ return ret;
+
+ /* Inform DAC IP to go for DDR mode from now on */
+ ret = iio_backend_ddr_enable(st->back);
+ if (ret) {
+ dev_err(st->dev, "could not set DDR mode, not streaming");
+ goto exit_err;
+ }
+
+ ret = iio_backend_data_transfer_addr(st->back, val);
+ if (ret)
+ goto exit_err;
+
+ ret = iio_backend_data_format_set(st->back, 0, &fmt);
+ if (ret)
+ goto exit_err;
+
+ ret = iio_backend_data_stream_enable(st->back);
+ if (ret)
+ goto exit_err;
+
+ return 0;
+
+exit_err:
+ ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+
+ iio_backend_ddr_disable(st->back);
+
+ return ret;
+}
+
+static int ad3552r_hs_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_backend_data_stream_disable(st->back);
+ if (ret)
+ return ret;
+
+ /* Inform DAC to set in SDR mode */
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_ddr_disable(st->back);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static inline int ad3552r_hs_set_output_range(struct ad3552r_hs_state *st,
+ int ch, unsigned int mode)
+{
+ int val;
+
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH0_RANGE, mode);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH1_RANGE, mode);
+
+ return ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val, 1);
+}
+
+static int ad3552r_hs_reset(struct ad3552r_hs_state *st)
+{
+ int ret;
+
+ st->reset_gpio = devm_gpiod_get_optional(st->dev,
+ "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(st->reset_gpio))
+ return PTR_ERR(st->reset_gpio);
+
+ if (st->reset_gpio) {
+ fsleep(10);
+ gpiod_set_value_cansleep(st->reset_gpio, 0);
+ } else {
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_SOFTWARE_RESET,
+ AD3552R_MASK_SOFTWARE_RESET, 1);
+ if (ret)
+ return ret;
+ }
+ msleep(100);
+
+ return 0;
+}
+
+static int ad3552r_hs_scratch_pad_test(struct ad3552r_hs_state *st)
+{
+ int ret, val;
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ AD3552R_SCRATCH_PAD_TEST_VAL1, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL1)
+ return dev_err_probe(st->dev, -EIO,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL1, val);
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ AD3552R_SCRATCH_PAD_TEST_VAL2, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL2)
+ return dev_err_probe(st->dev, -EIO,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL2, val);
+
+ return 0;
+}
+
+static int ad3552r_hs_setup_custom_gain(struct ad3552r_hs_state *st,
+ int ch, u16 gain, u16 offset)
+{
+ int ret;
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_OFFSET(ch),
+ offset, 1);
+ if (ret)
+ return ret;
+
+ return st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_GAIN(ch),
+ gain, 1);
+}
+
+static int ad3552r_hs_setup(struct ad3552r_hs_state *st)
+{
+ u16 id;
+ u16 gain = 0, offset = 0;
+ u32 ch, val, range;
+ int ret;
+
+ ret = ad3552r_hs_reset(st);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_ddr_disable(st->back);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_hs_scratch_pad_test(st);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ id = val;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_H,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ id |= val << 8;
+ if (id != st->model_data->chip_id)
+ dev_info(st->dev, "Chip ID error. Expected 0x%x, Read 0x%x\n",
+ AD3552R_ID, id);
+
+ ret = st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ 0, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_TRANSFER_REGISTER,
+ FIELD_PREP(AD3552R_MASK_MULTI_IO_MODE,
+ AD3552R_QUAD_SPI) |
+ AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, 1);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_get_ref_voltage(st->dev, &val);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
+
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ val, 1);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_get_drive_strength(st->dev, &val);
+ if (!ret) {
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ val, 1);
+ if (ret)
+ return ret;
+ }
+
+ device_for_each_child_node_scoped(st->dev, child) {
+ ret = fwnode_property_read_u32(child, "reg", &ch);
+ if (ret)
+ return dev_err_probe(st->dev, ret,
+ "reg property missing\n");
+
+ ret = ad3552r_get_output_range(st->dev, st->model_data, child,
+ &range);
+ if (ret && ret != -ENOENT)
+ return ret;
+ if (ret == -ENOENT) {
+ ret = ad3552r_get_custom_gain(st->dev, child,
+ &st->ch_data[ch].p,
+ &st->ch_data[ch].n,
+ &st->ch_data[ch].rfb,
+ &st->ch_data[ch].gain_offset);
+ if (ret)
+ return ret;
+
+ gain = ad3552r_calc_custom_gain(st->ch_data[ch].p,
+ st->ch_data[ch].n,
+ st->ch_data[ch].gain_offset);
+ offset = abs(st->ch_data[ch].gain_offset);
+
+ st->ch_data[ch].range_override = 1;
+
+ ret = ad3552r_hs_setup_custom_gain(st, ch, gain,
+ offset);
+ if (ret)
+ return ret;
+ } else {
+ st->ch_data[ch].range = range;
+
+ ret = ad3552r_hs_set_output_range(st, ch, range);
+ if (ret)
+ return ret;
+ }
+
+ ad3552r_calc_gain_and_offset(&st->ch_data[ch], st->model_data);
+ }
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops ad3552r_hs_buffer_setup_ops = {
+ .postenable = ad3552r_hs_buffer_postenable,
+ .predisable = ad3552r_hs_buffer_predisable,
+};
+
+#define AD3552R_CHANNEL(ch) { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = (ch), \
+ .scan_index = (ch), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ } \
+}
+
+static const struct iio_chan_spec ad3552r_hs_channels[] = {
+ AD3552R_CHANNEL(0),
+ AD3552R_CHANNEL(1),
+};
+
+static const struct iio_info ad3552r_hs_info = {
+ .read_raw = &ad3552r_hs_read_raw,
+ .write_raw = &ad3552r_hs_write_raw,
+};
+
+static int ad3552r_hs_probe(struct platform_device *pdev)
+{
+ struct ad3552r_hs_state *st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ st->dev = &pdev->dev;
+
+ st->data = dev_get_platdata(st->dev);
+ if (!st->data)
+ return dev_err_probe(st->dev, -ENODEV, "No platform data !");
+
+ st->back = devm_iio_backend_get(&pdev->dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ ret = devm_iio_backend_enable(&pdev->dev, st->back);
+ if (ret)
+ return ret;
+
+ st->model_data = device_get_match_data(&pdev->dev);
+ if (!st->model_data)
+ return -ENODEV;
+
+ indio_dev->name = "ad3552r";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->setup_ops = &ad3552r_hs_buffer_setup_ops;
+ indio_dev->channels = ad3552r_hs_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad3552r_hs_channels);
+ indio_dev->info = &ad3552r_hs_info;
+
+ ret = devm_iio_backend_request_buffer(&pdev->dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_hs_setup(st);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&pdev->dev, indio_dev);
+}
+
+static const struct ad3552r_model_data ad3552r_model_data = {
+ .model_name = "ad3552r",
+ .chip_id = AD3552R_ID,
+ .num_hw_channels = 2,
+ .ranges_table = ad3552r_ch_ranges,
+ .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges),
+};
+
+static const struct of_device_id ad3552r_hs_of_id[] = {
+ { .compatible = "adi,ad3552r", .data = &ad3552r_model_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad3552r_hs_of_id);
+
+static struct platform_driver ad3552r_hs_driver = {
+ .driver = {
+ .name = "ad3552r-hs",
+ .of_match_table = ad3552r_hs_of_id,
+ },
+ .probe = ad3552r_hs_probe,
+};
+module_platform_driver(ad3552r_hs_driver);
+
+MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
+MODULE_AUTHOR("Angelo Dureghello <adueghello@baylibre.com>");
+MODULE_DESCRIPTION("AD3552R Driver - High Speed version");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS(IIO_AD3552R);
diff --git a/drivers/iio/dac/ad3552r-hs.h b/drivers/iio/dac/ad3552r-hs.h
new file mode 100644
index 000000000000..724261d38dea
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-hs.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2024 Analog Devices Inc.
+ * Copyright (c) 2024 Baylibre, SAS
+ */
+#ifndef __LINUX_PLATFORM_DATA_AD3552R_HS_H__
+#define __LINUX_PLATFORM_DATA_AD3552R_HS_H__
+
+struct iio_backend;
+
+struct ad3552r_hs_platform_data {
+ int (*bus_reg_read)(struct iio_backend *back, u32 reg, u32 *val,
+ size_t data_size);
+ int (*bus_reg_write)(struct iio_backend *back, u32 reg, u32 val,
+ size_t data_size);
+ u32 bus_sample_data_clock_hz;
+};
+
+#endif /* __LINUX_PLATFORM_DATA_AD3552R_HS_H__ */
diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c
index 7d61b2fe6624..92688d958f4f 100644
--- a/drivers/iio/dac/ad3552r.c
+++ b/drivers/iio/dac/ad3552r.c
@@ -6,271 +6,15 @@
* Copyright 2021 Analog Devices Inc.
*/
#include <linux/unaligned.h>
+#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
-#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
-/* Register addresses */
-/* Primary address space */
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
-#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
-#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
-#define AD3552R_MASK_SDO_ACTIVE BIT(4)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
-#define AD3552R_MASK_SINGLE_INST BIT(7)
-#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
-#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
-#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
-#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
-#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
-#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
-#define AD3552R_MASK_CLASS GENMASK(7, 0)
-#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
-#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
-#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
-#define AD3552R_MASK_GRADE GENMASK(7, 4)
-#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
-#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
-#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
-#define AD3552R_REG_ADDR_VENDOR_L 0x0C
-#define AD3552R_REG_ADDR_VENDOR_H 0x0D
-#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
-#define AD3552R_MASK_LENGTH GENMASK(7, 0)
-#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
-#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
-#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
-#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\
- GENMASK(1, 0))
-#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
-#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
-#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
-#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
-#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
-#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
-#define AD3552R_MASK_MEM_CRC_EN BIT(4)
-#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
-#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
-#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
-#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
-#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
-#define AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN BIT(5)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
-#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
-#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
-#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
-#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
-#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
-#define AD3552R_REG_ADDR_ERR_STATUS 0x17
-#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
-#define AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
-#define AD3552R_MASK_RESET_STATUS BIT(0)
-#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
-#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
-#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
-#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
-#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? GENMASK(7, 4) :\
- GENMASK(3, 0))
-#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
-#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
-#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
-#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
-#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
-#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
-#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
-#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0)
-/*
- * Secondary region
- * For multibyte registers specify the highest address because the access is
- * done in descending order
- */
-#define AD3552R_SECONDARY_REGION_START 0x28
-#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
-#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - ch) * 2)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
-#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
-#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
-#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - ch) * 2)
-/* 3 bytes registers */
-#define AD3552R_REG_START_24B 0x37
-#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
-#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - ch) * 3)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
-#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
-#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
-#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3)
-
-/* Useful defines */
-#define AD3552R_MAX_CH 2
-#define AD3552R_MASK_CH(ch) BIT(ch)
-#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
-#define AD3552R_MAX_REG_SIZE 3
-#define AD3552R_READ_BIT BIT(7)
-#define AD3552R_ADDR_MASK GENMASK(6, 0)
-#define AD3552R_MASK_DAC_12B 0xFFF0
-#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
-#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
-#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
-#define AD3552R_GAIN_SCALE 1000
-#define AD3552R_LDAC_PULSE_US 100
-
-enum ad3552r_ch_vref_select {
- /* Internal source with Vref I/O floating */
- AD3552R_INTERNAL_VREF_PIN_FLOATING,
- /* Internal source with Vref I/O at 2.5V */
- AD3552R_INTERNAL_VREF_PIN_2P5V,
- /* External source with Vref I/O as input */
- AD3552R_EXTERNAL_VREF_PIN_INPUT
-};
-
-enum ad3552r_id {
- AD3541R_ID = 0x400b,
- AD3542R_ID = 0x4009,
- AD3551R_ID = 0x400a,
- AD3552R_ID = 0x4008,
-};
-
-enum ad3552r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
- /* Range from -10 V to 10 V. Requires Rfb4x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
-};
-
-static const s32 ad3552r_ch_ranges[][2] = {
- [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
- [AD3552R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
- [AD3552R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
- [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000},
- [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = {-10000, 10000}
-};
-
-enum ad3542r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 3 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__3V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
-};
-
-static const s32 ad3542r_ch_ranges[][2] = {
- [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
- [AD3542R_CH_OUTPUT_RANGE_0__3V] = {0, 3000},
- [AD3542R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
- [AD3542R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
- [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = {-2500, 7500},
- [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000}
-};
-
-enum ad3552r_ch_gain_scaling {
- /* Gain scaling of 1 */
- AD3552R_CH_GAIN_SCALING_1,
- /* Gain scaling of 0.5 */
- AD3552R_CH_GAIN_SCALING_0_5,
- /* Gain scaling of 0.25 */
- AD3552R_CH_GAIN_SCALING_0_25,
- /* Gain scaling of 0.125 */
- AD3552R_CH_GAIN_SCALING_0_125,
-};
-
-/* Gain * AD3552R_GAIN_SCALE */
-static const s32 gains_scaling_table[] = {
- [AD3552R_CH_GAIN_SCALING_1] = 1000,
- [AD3552R_CH_GAIN_SCALING_0_5] = 500,
- [AD3552R_CH_GAIN_SCALING_0_25] = 250,
- [AD3552R_CH_GAIN_SCALING_0_125] = 125
-};
-
-enum ad3552r_dev_attributes {
- /* - Direct register values */
- /* From 0-3 */
- AD3552R_SDO_DRIVE_STRENGTH,
- /*
- * 0 -> Internal Vref, vref_io pin floating (default)
- * 1 -> Internal Vref, vref_io driven by internal vref
- * 2 or 3 -> External Vref
- */
- AD3552R_VREF_SELECT,
- /* Read registers in ascending order if set. Else descending */
- AD3552R_ADDR_ASCENSION,
-};
-
-enum ad3552r_ch_attributes {
- /* DAC powerdown */
- AD3552R_CH_DAC_POWERDOWN,
- /* DAC amplifier powerdown */
- AD3552R_CH_AMPLIFIER_POWERDOWN,
- /* Select the output range. Select from enum ad3552r_ch_output_range */
- AD3552R_CH_OUTPUT_RANGE_SEL,
- /*
- * Over-rider the range selector in order to manually set the output
- * voltage range
- */
- AD3552R_CH_RANGE_OVERRIDE,
- /* Manually set the offset voltage */
- AD3552R_CH_GAIN_OFFSET,
- /* Sets the polarity of the offset. */
- AD3552R_CH_GAIN_OFFSET_POLARITY,
- /* PDAC gain scaling */
- AD3552R_CH_GAIN_SCALING_P,
- /* NDAC gain scaling */
- AD3552R_CH_GAIN_SCALING_N,
- /* Rfb value */
- AD3552R_CH_RFB,
- /* Channel select. When set allow Input -> DAC and Mask -> DAC */
- AD3552R_CH_SELECT,
-};
-
-struct ad3552r_ch_data {
- s32 scale_int;
- s32 scale_dec;
- s32 offset_int;
- s32 offset_dec;
- s16 gain_offset;
- u16 rfb;
- u8 n;
- u8 p;
- u8 range;
- bool range_override;
-};
-
-struct ad3552r_model_data {
- const char *model_name;
- enum ad3552r_id chip_id;
- unsigned int num_hw_channels;
- const s32 (*ranges_table)[2];
- int num_ranges;
- bool requires_output_range;
-};
+#include "ad3552r.h"
struct ad3552r_desc {
const struct ad3552r_model_data *model_data;
@@ -285,45 +29,6 @@ struct ad3552r_desc {
unsigned int num_ch;
};
-static const u16 addr_mask_map[][2] = {
- [AD3552R_ADDR_ASCENSION] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
- AD3552R_MASK_ADDR_ASCENSION
- },
- [AD3552R_SDO_DRIVE_STRENGTH] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
- AD3552R_MASK_SDO_DRIVE_STRENGTH
- },
- [AD3552R_VREF_SELECT] = {
- AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
- AD3552R_MASK_REFERENCE_VOLTAGE_SEL
- },
-};
-
-/* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */
-static const u16 addr_mask_map_ch[][3] = {
- [AD3552R_CH_DAC_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_DAC_POWERDOWN(0),
- AD3552R_MASK_CH_DAC_POWERDOWN(1)
- },
- [AD3552R_CH_AMPLIFIER_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0),
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1)
- },
- [AD3552R_CH_OUTPUT_RANGE_SEL] = {
- AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0),
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1)
- },
- [AD3552R_CH_SELECT] = {
- AD3552R_REG_ADDR_CH_SELECT_16B,
- AD3552R_MASK_CH(0),
- AD3552R_MASK_CH(1)
- }
-};
-
static u8 _ad3552r_reg_len(u8 addr)
{
switch (addr) {
@@ -399,11 +104,6 @@ static int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val)
return 0;
}
-static u16 ad3552r_field_prep(u16 val, u16 mask)
-{
- return (val << __ffs(mask)) & mask;
-}
-
/* Update field of a register, shift val if needed */
static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
u16 val)
@@ -416,21 +116,11 @@ static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
return ret;
reg &= ~mask;
- reg |= ad3552r_field_prep(val, mask);
+ reg |= val;
return ad3552r_write_reg(dac, addr, reg);
}
-static int ad3552r_set_ch_value(struct ad3552r_desc *dac,
- enum ad3552r_ch_attributes attr,
- u8 ch,
- u16 val)
-{
- /* Update register related to attributes in chip */
- return ad3552r_update_reg_field(dac, addr_mask_map_ch[attr][0],
- addr_mask_map_ch[attr][ch + 1], val);
-}
-
#define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) { \
.type = IIO_VOLTAGE, \
.output = true, \
@@ -510,8 +200,14 @@ static int ad3552r_write_raw(struct iio_dev *indio_dev,
val);
break;
case IIO_CHAN_INFO_ENABLE:
- err = ad3552r_set_ch_value(dac, AD3552R_CH_DAC_POWERDOWN,
- chan->channel, !val);
+ if (chan->channel == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(0), !val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(1), !val);
+
+ err = ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_DAC_POWERDOWN(chan->channel),
+ val);
break;
default:
err = -EINVAL;
@@ -715,83 +411,9 @@ static int ad3552r_reset(struct ad3552r_desc *dac)
}
return ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_ADDR_ASCENSION][0],
- addr_mask_map[AD3552R_ADDR_ASCENSION][1],
- val);
-}
-
-static void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 *v_min,
- s32 *v_max)
-{
- s64 vref, tmp, common, offset, gn, gp;
- /*
- * From datasheet formula (In Volts):
- * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03]
- * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03]
- * Calculus are converted to milivolts
- */
- vref = 2500;
- /* 2.5 * 1.03 * 1000 (To mV) */
- common = 2575 * dac->ch_data[i].rfb;
- offset = dac->ch_data[i].gain_offset;
-
- gn = gains_scaling_table[dac->ch_data[i].n];
- tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common;
- tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
- *v_max = vref + tmp;
-
- gp = gains_scaling_table[dac->ch_data[i].p];
- tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common;
- tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
- *v_min = vref - tmp;
-}
-
-static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
-{
- s32 idx, v_max, v_min, span, rem;
- s64 tmp;
-
- if (dac->ch_data[ch].range_override) {
- ad3552r_get_custom_range(dac, ch, &v_min, &v_max);
- } else {
- /* Normal range */
- idx = dac->ch_data[ch].range;
- v_min = dac->model_data->ranges_table[idx][0];
- v_max = dac->model_data->ranges_table[idx][1];
- }
-
- /*
- * From datasheet formula:
- * Vout = Span * (D / 65536) + Vmin
- * Converted to scale and offset:
- * Scale = Span / 65536
- * Offset = 65536 * Vmin / Span
- *
- * Reminders are in micros in order to be printed as
- * IIO_VAL_INT_PLUS_MICRO
- */
- span = v_max - v_min;
- dac->ch_data[ch].scale_int = div_s64_rem(span, 65536, &rem);
- /* Do operations in microvolts */
- dac->ch_data[ch].scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000,
- 65536);
-
- dac->ch_data[ch].offset_int = div_s64_rem(v_min * 65536, span, &rem);
- tmp = (s64)rem * 1000000;
- dac->ch_data[ch].offset_dec = div_s64(tmp, span);
-}
-
-static int ad3552r_find_range(const struct ad3552r_model_data *model_data,
- s32 *vals)
-{
- int i;
-
- for (i = 0; i < model_data->num_ranges; i++)
- if (vals[0] == model_data->ranges_table[i][0] * 1000 &&
- vals[1] == model_data->ranges_table[i][1] * 1000)
- return i;
-
- return -EINVAL;
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_ADDR_ASCENSION,
+ FIELD_PREP(AD3552R_MASK_ADDR_ASCENSION, val));
}
static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
@@ -799,57 +421,30 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
u32 ch)
{
struct device *dev = &dac->spi->dev;
- u32 val;
int err;
u8 addr;
- u16 reg = 0, offset;
-
- struct fwnode_handle *gain_child __free(fwnode_handle)
- = fwnode_get_named_child_node(child,
- "custom-output-range-config");
- if (!gain_child)
- return dev_err_probe(dev, -EINVAL,
- "mandatory custom-output-range-config property missing\n");
-
- dac->ch_data[ch].range_override = 1;
- reg |= ad3552r_field_prep(1, AD3552R_MASK_CH_RANGE_OVERRIDE);
-
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-p property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_P);
- dac->ch_data[ch].p = val;
-
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-n property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_N);
- dac->ch_data[ch].n = val;
-
- err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,rfb-ohms property missing\n");
- dac->ch_data[ch].rfb = val;
+ u16 reg;
- err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
+ err = ad3552r_get_custom_gain(dev, child,
+ &dac->ch_data[ch].p,
+ &dac->ch_data[ch].n,
+ &dac->ch_data[ch].rfb,
+ &dac->ch_data[ch].gain_offset);
if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-offset property missing\n");
- dac->ch_data[ch].gain_offset = val;
+ return err;
- offset = abs((s32)val);
- reg |= ad3552r_field_prep((offset >> 8), AD3552R_MASK_CH_OFFSET_BIT_8);
+ dac->ch_data[ch].range_override = 1;
- reg |= ad3552r_field_prep((s32)val < 0, AD3552R_MASK_CH_OFFSET_POLARITY);
addr = AD3552R_REG_ADDR_CH_GAIN(ch);
err = ad3552r_write_reg(dac, addr,
- offset & AD3552R_MASK_CH_OFFSET_BITS_0_7);
+ abs((s32)dac->ch_data[ch].gain_offset) &
+ AD3552R_MASK_CH_OFFSET_BITS_0_7);
if (err)
return dev_err_probe(dev, err, "Error writing register\n");
+ reg = ad3552r_calc_custom_gain(dac->ch_data[ch].p, dac->ch_data[ch].n,
+ dac->ch_data[ch].gain_offset);
+
err = ad3552r_write_reg(dac, addr, reg);
if (err)
return dev_err_probe(dev, err, "Error writing register\n");
@@ -860,49 +455,31 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
static int ad3552r_configure_device(struct ad3552r_desc *dac)
{
struct device *dev = &dac->spi->dev;
- int err, cnt = 0, voltage, delta = 100000;
- u32 vals[2], val, ch;
+ int err, cnt = 0;
+ u32 val, ch;
dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH);
if (IS_ERR(dac->gpio_ldac))
return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac),
"Error getting gpio ldac");
- voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
- if (voltage < 0 && voltage != -ENODEV)
- return dev_err_probe(dev, voltage, "Error getting vref voltage\n");
-
- if (voltage == -ENODEV) {
- if (device_property_read_bool(dev, "adi,vref-out-en"))
- val = AD3552R_INTERNAL_VREF_PIN_2P5V;
- else
- val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
- } else {
- if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
- dev_warn(dev, "vref-supply must be 2.5V");
- return -EINVAL;
- }
- val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
- }
+ err = ad3552r_get_ref_voltage(dev, &val);
+ if (err < 0)
+ return err;
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_VREF_SELECT][0],
- addr_mask_map[AD3552R_VREF_SELECT][1],
- val);
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ FIELD_PREP(AD3552R_MASK_REFERENCE_VOLTAGE_SEL, val));
if (err)
return err;
- err = device_property_read_u32(dev, "adi,sdo-drive-strength", &val);
+ err = ad3552r_get_drive_strength(dev, &val);
if (!err) {
- if (val > 3) {
- dev_err(dev, "adi,sdo-drive-strength must be less than 4\n");
- return -EINVAL;
- }
-
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][0],
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][1],
- val);
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ FIELD_PREP(AD3552R_MASK_SDO_DRIVE_STRENGTH, val));
if (err)
return err;
}
@@ -923,24 +500,21 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
"reg must be less than %d\n",
dac->model_data->num_hw_channels);
- if (fwnode_property_present(child, "adi,output-range-microvolt")) {
- err = fwnode_property_read_u32_array(child,
- "adi,output-range-microvolt",
- vals,
- 2);
- if (err)
- return dev_err_probe(dev, err,
- "adi,output-range-microvolt property could not be parsed\n");
-
- err = ad3552r_find_range(dac->model_data, vals);
- if (err < 0)
- return dev_err_probe(dev, err,
- "Invalid adi,output-range-microvolt value\n");
-
- val = err;
- err = ad3552r_set_ch_value(dac,
- AD3552R_CH_OUTPUT_RANGE_SEL,
- ch, val);
+ err = ad3552r_get_output_range(dev, dac->model_data,
+ child, &val);
+ if (err && err != -ENOENT)
+ return err;
+
+ if (!err) {
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1), val);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val);
if (err)
return err;
@@ -955,10 +529,17 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
return err;
}
- ad3552r_calc_gain_and_offset(dac, ch);
+ ad3552r_calc_gain_and_offset(&dac->ch_data[ch], dac->model_data);
dac->enabled_ch |= BIT(ch);
- err = ad3552r_set_ch_value(dac, AD3552R_CH_SELECT, ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH_SELECT_16B,
+ AD3552R_MASK_CH(ch), val);
if (err < 0)
return err;
@@ -970,8 +551,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
/* Disable unused channels */
for_each_clear_bit(ch, &dac->enabled_ch,
dac->model_data->num_hw_channels) {
- err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN,
- ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch),
+ val);
if (err)
return err;
}
@@ -1140,3 +728,4 @@ module_spi_driver(ad3552r_driver);
MODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>");
MODULE_DESCRIPTION("Analog Device AD3552R DAC");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_AD3552R);
diff --git a/drivers/iio/dac/ad3552r.h b/drivers/iio/dac/ad3552r.h
new file mode 100644
index 000000000000..fd5a3dfd1d1c
--- /dev/null
+++ b/drivers/iio/dac/ad3552r.h
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AD3552R Digital <-> Analog converters common header
+ *
+ * Copyright 2021-2024 Analog Devices Inc.
+ * Author: Angelo Dureghello <adureghello@baylibre.com>
+ */
+
+#ifndef __DRIVERS_IIO_DAC_AD3552R_H__
+#define __DRIVERS_IIO_DAC_AD3552R_H__
+
+/* Register addresses */
+/* Primary address space */
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
+#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
+#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
+#define AD3552R_MASK_SDO_ACTIVE BIT(4)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
+#define AD3552R_MASK_SINGLE_INST BIT(7)
+#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
+#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
+#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
+#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
+#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
+#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
+#define AD3552R_MASK_CLASS GENMASK(7, 0)
+#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
+#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
+#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
+#define AD3552R_MASK_GRADE GENMASK(7, 4)
+#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
+#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
+#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
+#define AD3552R_REG_ADDR_VENDOR_L 0x0C
+#define AD3552R_REG_ADDR_VENDOR_H 0x0D
+#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
+#define AD3552R_MASK_LENGTH GENMASK(7, 0)
+#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
+#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
+#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
+#define AD3552R_MASK_CRC_ENABLE \
+ (GENMASK(7, 6) | GENMASK(1, 0))
+#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
+#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
+#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
+#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
+#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
+#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
+#define AD3552R_MASK_MEM_CRC_EN BIT(4)
+#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
+#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
+#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
+#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
+#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
+#define AD3552R_MASK_SAMPLE_HOLD_DIFF_USER_EN BIT(5)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
+#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
+#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
+#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
+#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
+#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
+#define AD3552R_REG_ADDR_ERR_STATUS 0x17
+#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
+#define AD3552R_MASK_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
+#define AD3552R_MASK_RESET_STATUS BIT(0)
+#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
+#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
+#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
+#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
+#define AD3552R_MASK_CH0_RANGE GENMASK(2, 0)
+#define AD3552R_MASK_CH1_RANGE GENMASK(6, 4)
+#define AD3552R_MASK_CH_OUTPUT_RANGE GENMASK(7, 0)
+#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) \
+ ((ch) ? GENMASK(7, 4) : GENMASK(3, 0))
+#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
+#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
+#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
+#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
+#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
+#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
+#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
+#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(8)
+/*
+ * Secondary region
+ * For multibyte registers specify the highest address because the access is
+ * done in descending order
+ */
+#define AD3552R_SECONDARY_REGION_START 0x28
+#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
+#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - (ch)) * 2)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
+#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
+#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
+#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - (ch)) * 2)
+/* 3 bytes registers */
+#define AD3552R_REG_START_24B 0x37
+#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
+#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - (ch)) * 3)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
+#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
+#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
+#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - (ch)) * 3)
+
+#define AD3552R_MAX_CH 2
+#define AD3552R_MASK_CH(ch) BIT(ch)
+#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
+#define AD3552R_MAX_REG_SIZE 3
+#define AD3552R_READ_BIT BIT(7)
+#define AD3552R_ADDR_MASK GENMASK(6, 0)
+#define AD3552R_MASK_DAC_12B GENMASK(15, 4)
+#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
+#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
+#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
+#define AD3552R_GAIN_SCALE 1000
+#define AD3552R_LDAC_PULSE_US 100
+
+#define AD3552R_CH0_ACTIVE BIT(0)
+#define AD3552R_CH1_ACTIVE BIT(1)
+
+#define AD3552R_MAX_RANGES 5
+#define AD3542R_MAX_RANGES 6
+#define AD3552R_QUAD_SPI 2
+
+extern const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2];
+extern const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2];
+
+enum ad3552r_id {
+ AD3541R_ID = 0x400b,
+ AD3542R_ID = 0x4009,
+ AD3551R_ID = 0x400a,
+ AD3552R_ID = 0x4008,
+};
+
+struct ad3552r_model_data {
+ const char *model_name;
+ enum ad3552r_id chip_id;
+ unsigned int num_hw_channels;
+ const s32 (*ranges_table)[2];
+ int num_ranges;
+ bool requires_output_range;
+};
+
+struct ad3552r_ch_data {
+ s32 scale_int;
+ s32 scale_dec;
+ s32 offset_int;
+ s32 offset_dec;
+ s16 gain_offset;
+ u16 rfb;
+ u8 n;
+ u8 p;
+ u8 range;
+ bool range_override;
+};
+
+enum ad3552r_ch_gain_scaling {
+ /* Gain scaling of 1 */
+ AD3552R_CH_GAIN_SCALING_1,
+ /* Gain scaling of 0.5 */
+ AD3552R_CH_GAIN_SCALING_0_5,
+ /* Gain scaling of 0.25 */
+ AD3552R_CH_GAIN_SCALING_0_25,
+ /* Gain scaling of 0.125 */
+ AD3552R_CH_GAIN_SCALING_0_125,
+};
+
+enum ad3552r_ch_vref_select {
+ /* Internal source with Vref I/O floating */
+ AD3552R_INTERNAL_VREF_PIN_FLOATING,
+ /* Internal source with Vref I/O at 2.5V */
+ AD3552R_INTERNAL_VREF_PIN_2P5V,
+ /* External source with Vref I/O as input */
+ AD3552R_EXTERNAL_VREF_PIN_INPUT
+};
+
+enum ad3542r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 3 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__3V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
+};
+
+enum ad3552r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
+ /* Range from -10 V to 10 V. Requires Rfb4x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
+};
+
+int ad3552r_get_output_range(struct device *dev,
+ const struct ad3552r_model_data *model_info,
+ struct fwnode_handle *child, u32 *val);
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs);
+u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs);
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val);
+int ad3552r_get_drive_strength(struct device *dev, u32 *val);
+void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data,
+ const struct ad3552r_model_data *model_data);
+
+#endif /* __DRIVERS_IIO_DAC_AD3552R_H__ */
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 2e3e33f92bc0..392a1c7aee03 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -47,7 +47,6 @@ struct ad5380_chip_info {
* struct ad5380_state - driver instance specific data
* @regmap: regmap instance used by the device
* @chip_info: chip model specific constants, available modes etc
- * @vref_reg: vref supply regulator
* @vref: actual reference voltage used in uA
* @pwr_down: whether the chip is currently in power down mode
* @lock: lock to protect the data buffer during regmap ops
@@ -55,7 +54,6 @@ struct ad5380_chip_info {
struct ad5380_state {
struct regmap *regmap;
const struct ad5380_chip_info *chip_info;
- struct regulator *vref_reg;
int vref;
bool pwr_down;
struct mutex lock;
@@ -341,14 +339,14 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
},
};
-static int ad5380_alloc_channels(struct iio_dev *indio_dev)
+static int ad5380_alloc_channels(struct device *dev, struct iio_dev *indio_dev)
{
struct ad5380_state *st = iio_priv(indio_dev);
struct iio_chan_spec *channels;
unsigned int i;
- channels = kcalloc(st->chip_info->num_channels,
- sizeof(struct iio_chan_spec), GFP_KERNEL);
+ channels = devm_kcalloc(dev, st->chip_info->num_channels,
+ sizeof(struct iio_chan_spec), GFP_KERNEL);
if (!channels)
return -ENOMEM;
@@ -379,7 +377,6 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
}
st = iio_priv(indio_dev);
- dev_set_drvdata(dev, indio_dev);
st->chip_info = &ad5380_chip_info_tbl[type];
st->regmap = regmap;
@@ -391,68 +388,32 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
mutex_init(&st->lock);
- ret = ad5380_alloc_channels(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to allocate channel spec: %d\n", ret);
- return ret;
- }
+ ret = ad5380_alloc_channels(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to allocate channel spec\n");
if (st->chip_info->int_vref == 2500)
ctrl |= AD5380_CTRL_INT_VREF_2V5;
- st->vref_reg = devm_regulator_get(dev, "vref");
- if (!IS_ERR(st->vref_reg)) {
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(dev, "Failed to enable vref regulators: %d\n",
- ret);
- goto error_free_reg;
- }
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0)
- goto error_disable_reg;
-
- st->vref = ret / 1000;
- } else {
+ ret = devm_regulator_get_enable_read_voltage(dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "Failed to get vref voltage\n");
+ if (ret == -ENODEV) {
st->vref = st->chip_info->int_vref;
ctrl |= AD5380_CTRL_INT_VREF_EN;
+ } else {
+ st->vref = ret / 1000;
}
ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl);
- if (ret) {
- dev_err(dev, "Failed to write to device: %d\n", ret);
- goto error_disable_reg;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to write to device\n");
- ret = iio_device_register(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to register iio device: %d\n", ret);
- goto error_disable_reg;
- }
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register iio device\n");
return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->vref_reg))
- regulator_disable(st->vref_reg);
-error_free_reg:
- kfree(indio_dev->channels);
-
- return ret;
-}
-
-static void ad5380_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- kfree(indio_dev->channels);
-
- if (!IS_ERR(st->vref_reg))
- regulator_disable(st->vref_reg);
}
static bool ad5380_reg_false(struct device *dev, unsigned int reg)
@@ -486,11 +447,6 @@ static int ad5380_spi_probe(struct spi_device *spi)
return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);
}
-static void ad5380_spi_remove(struct spi_device *spi)
-{
- ad5380_remove(&spi->dev);
-}
-
static const struct spi_device_id ad5380_spi_ids[] = {
{ "ad5380-3", ID_AD5380_3 },
{ "ad5380-5", ID_AD5380_5 },
@@ -517,7 +473,6 @@ static struct spi_driver ad5380_spi_driver = {
.name = "ad5380",
},
.probe = ad5380_spi_probe,
- .remove = ad5380_spi_remove,
.id_table = ad5380_spi_ids,
};
@@ -559,11 +514,6 @@ static int ad5380_i2c_probe(struct i2c_client *i2c)
return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name);
}
-static void ad5380_i2c_remove(struct i2c_client *i2c)
-{
- ad5380_remove(&i2c->dev);
-}
-
static const struct i2c_device_id ad5380_i2c_ids[] = {
{ "ad5380-3", ID_AD5380_3 },
{ "ad5380-5", ID_AD5380_5 },
@@ -590,7 +540,6 @@ static struct i2c_driver ad5380_i2c_driver = {
.name = "ad5380",
},
.probe = ad5380_i2c_probe,
- .remove = ad5380_i2c_remove,
.id_table = ad5380_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 7644acfd879e..1462ee640b16 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -384,7 +384,7 @@ static int ad5421_write_raw(struct iio_dev *indio_dev,
static int ad5421_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int mask;
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 708629efc157..6ad99f97eed5 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -32,7 +32,6 @@
* struct ad5446_state - driver instance specific data
* @dev: this device
* @chip_info: chip model specific constants, available modes etc
- * @reg: supply regulator
* @vref_mv: actual reference voltage used
* @cached_val: store/retrieve values during power down
* @pwr_down_mode: power down mode (1k, 100k or tristate)
@@ -43,7 +42,6 @@
struct ad5446_state {
struct device *dev;
const struct ad5446_chip_info *chip_info;
- struct regulator *reg;
unsigned short vref_mv;
unsigned cached_val;
unsigned pwr_down_mode;
@@ -226,32 +224,15 @@ static int ad5446_probe(struct device *dev, const char *name,
{
struct ad5446_state *st;
struct iio_dev *indio_dev;
- struct regulator *reg;
- int ret, voltage_uv = 0;
-
- reg = devm_regulator_get(dev, "vcc");
- if (!IS_ERR(reg)) {
- ret = regulator_enable(reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- }
+ int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
+ if (!indio_dev)
+ return -ENOMEM;
+
st = iio_priv(indio_dev);
st->chip_info = chip_info;
- dev_set_drvdata(dev, indio_dev);
- st->reg = reg;
st->dev = dev;
indio_dev->name = name;
@@ -264,33 +245,19 @@ static int ad5446_probe(struct device *dev, const char *name,
st->pwr_down_mode = MODE_PWRDWN_1k;
- if (st->chip_info->int_vref_mv)
- st->vref_mv = st->chip_info->int_vref_mv;
- else if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- dev_warn(dev, "reference voltage unspecified\n");
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(reg))
- regulator_disable(reg);
- return ret;
-}
-
-static void ad5446_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_priv(indio_dev);
+ ret = devm_regulator_get_enable_read_voltage(dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+ if (ret == -ENODEV) {
+ if (chip_info->int_vref_mv)
+ st->vref_mv = chip_info->int_vref_mv;
+ else
+ dev_warn(dev, "reference voltage unspecified\n");
+ } else {
+ st->vref_mv = ret / 1000;
+ }
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(dev, indio_dev);
}
#if IS_ENABLED(CONFIG_SPI_MASTER)
@@ -491,18 +458,12 @@ static int ad5446_spi_probe(struct spi_device *spi)
&ad5446_spi_chip_info[id->driver_data]);
}
-static void ad5446_spi_remove(struct spi_device *spi)
-{
- ad5446_remove(&spi->dev);
-}
-
static struct spi_driver ad5446_spi_driver = {
.driver = {
.name = "ad5446",
.of_match_table = ad5446_of_ids,
},
.probe = ad5446_spi_probe,
- .remove = ad5446_spi_remove,
.id_table = ad5446_spi_ids,
};
@@ -575,11 +536,6 @@ static int ad5446_i2c_probe(struct i2c_client *i2c)
&ad5446_i2c_chip_info[id->driver_data]);
}
-static void ad5446_i2c_remove(struct i2c_client *i2c)
-{
- ad5446_remove(&i2c->dev);
-}
-
static const struct i2c_device_id ad5446_i2c_ids[] = {
{"ad5301", ID_AD5602},
{"ad5311", ID_AD5612},
@@ -596,7 +552,6 @@ static struct i2c_driver ad5446_i2c_driver = {
.name = "ad5446",
},
.probe = ad5446_i2c_probe,
- .remove = ad5446_i2c_remove,
.id_table = ad5446_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index e6c5be728bb2..ff0765c8af47 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -270,38 +270,29 @@ static const struct iio_chan_spec ad5504_channels[] = {
static int ad5504_probe(struct spi_device *spi)
{
- struct ad5504_platform_data *pdata = spi->dev.platform_data;
+ const struct ad5504_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad5504_state *st;
- struct regulator *reg;
- int ret, voltage_uv = 0;
+ int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
- reg = devm_regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(reg)) {
- ret = regulator_enable(reg);
- if (ret)
- return ret;
- ret = regulator_get_voltage(reg);
- if (ret < 0)
- goto error_disable_reg;
+ st = iio_priv(indio_dev);
- voltage_uv = ret;
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+ if (ret == -ENODEV) {
+ if (pdata->vref_mv)
+ st->vref_mv = pdata->vref_mv;
+ else
+ dev_warn(&spi->dev, "reference voltage unspecified\n");
+ } else {
+ st->vref_mv = ret / 1000;
}
- spi_set_drvdata(spi, indio_dev);
- st = iio_priv(indio_dev);
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else if (pdata)
- st->vref_mv = pdata->vref_mv;
- else
- dev_warn(&spi->dev, "reference voltage unspecified\n");
-
- st->reg = reg;
st->spi = spi;
indio_dev->name = spi_get_device_id(st->spi)->name;
indio_dev->info = &ad5504_info;
@@ -320,31 +311,10 @@ static int ad5504_probe(struct spi_device *spi)
spi_get_device_id(st->spi)->name,
indio_dev);
if (ret)
- goto error_disable_reg;
+ return ret;
}
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(reg))
- regulator_disable(reg);
-
- return ret;
-}
-
-static void ad5504_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5504_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad5504_id[] = {
@@ -359,7 +329,6 @@ static struct spi_driver ad5504_driver = {
.name = "ad5504",
},
.probe = ad5504_probe,
- .remove = ad5504_remove,
.id_table = ad5504_id,
};
module_spi_driver(ad5504_driver);
diff --git a/drivers/iio/dac/ad5624r.h b/drivers/iio/dac/ad5624r.h
index 13964f3a22a4..14a439b06eb6 100644
--- a/drivers/iio/dac/ad5624r.h
+++ b/drivers/iio/dac/ad5624r.h
@@ -54,7 +54,6 @@ struct ad5624r_chip_info {
struct ad5624r_state {
struct spi_device *us;
const struct ad5624r_chip_info *chip_info;
- struct regulator *reg;
unsigned short vref_mv;
unsigned pwr_down_mask;
unsigned pwr_down_mode;
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index 9304d0499bae..2fd38ac8f698 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -223,50 +223,26 @@ static int ad5624r_probe(struct spi_device *spi)
{
struct ad5624r_state *st;
struct iio_dev *indio_dev;
- int ret, voltage_uv = 0;
+ bool external_vref;
+ int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = devm_regulator_get_optional(&spi->dev, "vref");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- } else {
- if (PTR_ERR(st->reg) != -ENODEV)
- return PTR_ERR(st->reg);
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret == -ENODEV)
/* Backwards compatibility. This naming is not correct */
- st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- }
- }
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+
+ external_vref = ret != -ENODEV;
+ st->vref_mv = external_vref ? ret / 1000 : st->chip_info->int_vref_mv;
- spi_set_drvdata(spi, indio_dev);
st->chip_info =
&ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- st->vref_mv = st->chip_info->int_vref_mv;
-
st->us = spi;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -276,31 +252,11 @@ static int ad5624r_probe(struct spi_device *spi)
indio_dev->num_channels = AD5624R_DAC_CHANNELS;
ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
- !!voltage_uv, 16);
- if (ret)
- goto error_disable_reg;
-
- ret = iio_device_register(indio_dev);
+ external_vref, 16);
if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
-
- return ret;
-}
-
-static void ad5624r_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5624r_state *st = iio_priv(indio_dev);
+ return ret;
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad5624r_id[] = {
@@ -319,7 +275,6 @@ static struct spi_driver ad5624r_driver = {
.name = "ad5624r",
},
.probe = ad5624r_probe,
- .remove = ad5624r_remove,
.id_table = ad5624r_id,
};
module_spi_driver(ad5624r_driver);
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 0b24cb19ac9d..05e80b6ae2cc 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -699,7 +699,6 @@ static const struct ad5755_platform_data ad5755_default_pdata = {
static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
{
- struct fwnode_handle *pp;
struct ad5755_platform_data *pdata;
unsigned int tmp;
unsigned int tmparray[3];
@@ -746,11 +745,12 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
}
devnr = 0;
- device_for_each_child_node(dev, pp) {
+ device_for_each_child_node_scoped(dev, pp) {
if (devnr >= AD5755_NUM_CHANNELS) {
dev_err(dev,
"There are too many channels defined in DT\n");
- goto error_out;
+ devm_kfree(dev, pdata);
+ return NULL;
}
pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;
@@ -800,11 +800,6 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
}
return pdata;
-
- error_out:
- fwnode_handle_put(pp);
- devm_kfree(dev, pdata);
- return NULL;
}
static int ad5755_probe(struct spi_device *spi)
diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c
index 6aa1a068adb0..0aa5ba7f4654 100644
--- a/drivers/iio/dac/ad5761.c
+++ b/drivers/iio/dac/ad5761.c
@@ -53,7 +53,6 @@ enum ad5761_supported_device_ids {
/**
* struct ad5761_state - driver instance specific data
* @spi: spi_device
- * @vref_reg: reference voltage regulator
* @use_intref: true when the internal voltage reference is used
* @vref: actual voltage reference in mVolts
* @range: output range mode used
@@ -62,7 +61,6 @@ enum ad5761_supported_device_ids {
*/
struct ad5761_state {
struct spi_device *spi;
- struct regulator *vref_reg;
struct mutex lock;
bool use_intref;
@@ -287,63 +285,6 @@ static const struct ad5761_chip_info ad5761_chip_infos[] = {
},
};
-static int ad5761_get_vref(struct ad5761_state *st,
- const struct ad5761_chip_info *chip_info)
-{
- int ret;
-
- st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref");
- if (PTR_ERR(st->vref_reg) == -ENODEV) {
- /* Use Internal regulator */
- if (!chip_info->int_vref) {
- dev_err(&st->spi->dev,
- "Voltage reference not found\n");
- return -EIO;
- }
-
- st->use_intref = true;
- st->vref = chip_info->int_vref;
- return 0;
- }
-
- if (IS_ERR(st->vref_reg)) {
- dev_err(&st->spi->dev,
- "Error getting voltage reference regulator\n");
- return PTR_ERR(st->vref_reg);
- }
-
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(&st->spi->dev,
- "Failed to enable voltage reference\n");
- return ret;
- }
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0) {
- dev_err(&st->spi->dev,
- "Failed to get voltage reference value\n");
- goto disable_regulator_vref;
- }
-
- if (ret < 2000000 || ret > 3000000) {
- dev_warn(&st->spi->dev,
- "Invalid external voltage ref. value %d uV\n", ret);
- ret = -EIO;
- goto disable_regulator_vref;
- }
-
- st->vref = ret / 1000;
- st->use_intref = false;
-
- return 0;
-
-disable_regulator_vref:
- regulator_disable(st->vref_reg);
- st->vref_reg = NULL;
- return ret;
-}
-
static int ad5761_probe(struct spi_device *spi)
{
struct iio_dev *iio_dev;
@@ -361,11 +302,28 @@ static int ad5761_probe(struct spi_device *spi)
st = iio_priv(iio_dev);
st->spi = spi;
- spi_set_drvdata(spi, iio_dev);
- ret = ad5761_get_vref(st, chip_info);
- if (ret)
- return ret;
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(&spi->dev, ret,
+ "Failed to get voltage reference value\n");
+ if (ret == -ENODEV) {
+ /* Use Internal regulator */
+ if (!chip_info->int_vref)
+ return dev_err_probe(&spi->dev, -EIO,
+ "Voltage reference not found\n");
+
+ st->use_intref = true;
+ st->vref = chip_info->int_vref;
+ } else {
+ if (ret < 2000000 || ret > 3000000)
+ return dev_err_probe(&spi->dev, -EIO,
+ "Invalid external voltage ref. value %d uV\n",
+ ret);
+
+ st->use_intref = false;
+ st->vref = ret / 1000;
+ }
if (pdata)
voltage_range = pdata->voltage_range;
@@ -374,35 +332,15 @@ static int ad5761_probe(struct spi_device *spi)
ret = ad5761_spi_set_range(st, voltage_range);
if (ret)
- goto disable_regulator_err;
+ return ret;
iio_dev->info = &ad5761_info;
iio_dev->modes = INDIO_DIRECT_MODE;
iio_dev->channels = &chip_info->channel;
iio_dev->num_channels = 1;
iio_dev->name = spi_get_device_id(st->spi)->name;
- ret = iio_device_register(iio_dev);
- if (ret)
- goto disable_regulator_err;
-
- return 0;
-
-disable_regulator_err:
- if (!IS_ERR_OR_NULL(st->vref_reg))
- regulator_disable(st->vref_reg);
-
- return ret;
-}
-
-static void ad5761_remove(struct spi_device *spi)
-{
- struct iio_dev *iio_dev = spi_get_drvdata(spi);
- struct ad5761_state *st = iio_priv(iio_dev);
-
- iio_device_unregister(iio_dev);
- if (!IS_ERR_OR_NULL(st->vref_reg))
- regulator_disable(st->vref_reg);
+ return devm_iio_device_register(&spi->dev, iio_dev);
}
static const struct spi_device_id ad5761_id[] = {
@@ -419,7 +357,6 @@ static struct spi_driver ad5761_driver = {
.name = "ad5761",
},
.probe = ad5761_probe,
- .remove = ad5761_remove,
.id_table = ad5761_id,
};
module_spi_driver(ad5761_driver);
diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c
index c360ebf5297a..25cf11d0471b 100644
--- a/drivers/iio/dac/ad5770r.c
+++ b/drivers/iio/dac/ad5770r.c
@@ -17,6 +17,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
+#include <linux/unaligned.h>
#define ADI_SPI_IF_CONFIG_A 0x00
#define ADI_SPI_IF_CONFIG_B 0x01
@@ -121,7 +122,6 @@ struct ad5770r_out_range {
* struct ad5770r_state - driver instance specific data
* @spi: spi_device
* @regmap: regmap
- * @vref_reg: fixed regulator for reference configuration
* @gpio_reset: gpio descriptor
* @output_mode: array contains channels output ranges
* @vref: reference value
@@ -133,7 +133,6 @@ struct ad5770r_out_range {
struct ad5770r_state {
struct spi_device *spi;
struct regmap *regmap;
- struct regulator *vref_reg;
struct gpio_desc *gpio_reset;
struct ad5770r_out_range output_mode[AD5770R_MAX_CHANNELS];
int vref;
@@ -325,7 +324,7 @@ static int ad5770r_read_raw(struct iio_dev *indio_dev,
if (ret)
return 0;
- buf16 = st->transf_buf[0] + (st->transf_buf[1] << 8);
+ buf16 = get_unaligned_le16(st->transf_buf);
*val = buf16 >> 2;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -590,13 +589,6 @@ static int ad5770r_init(struct ad5770r_state *st)
return ret;
}
-static void ad5770r_disable_regulator(void *data)
-{
- struct ad5770r_state *st = data;
-
- regulator_disable(st->vref_reg);
-}
-
static int ad5770r_probe(struct spi_device *spi)
{
struct ad5770r_state *st;
@@ -621,34 +613,12 @@ static int ad5770r_probe(struct spi_device *spi)
}
st->regmap = regmap;
- st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
- if (!IS_ERR(st->vref_reg)) {
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(&spi->dev,
- "Failed to enable vref regulators: %d\n", ret);
- return ret;
- }
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(&spi->dev, ret, "Failed to get vref voltage\n");
- ret = devm_add_action_or_reset(&spi->dev,
- ad5770r_disable_regulator,
- st);
- if (ret < 0)
- return ret;
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0)
- return ret;
-
- st->vref = ret / 1000;
- } else {
- if (PTR_ERR(st->vref_reg) == -ENODEV) {
- st->vref = AD5770R_LOW_VREF_mV;
- st->internal_ref = true;
- } else {
- return PTR_ERR(st->vref_reg);
- }
- }
+ st->internal_ref = ret == -ENODEV;
+ st->vref = st->internal_ref ? AD5770R_LOW_VREF_mV : ret / 1000;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad5770r_info;
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index 75b549827e15..57374f78f6b8 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -9,6 +9,7 @@
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/device.h>
+#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -61,11 +62,14 @@
/**
* struct ad5791_chip_info - chip specific information
+ * @name: name of the dac chip
+ * @channel: channel specification
* @get_lin_comp: function pointer to the device specific function
*/
-
struct ad5791_chip_info {
- int (*get_lin_comp) (unsigned int span);
+ const char *name;
+ const struct iio_chan_spec channel;
+ int (*get_lin_comp)(unsigned int span);
};
/**
@@ -73,6 +77,9 @@ struct ad5791_chip_info {
* @spi: spi_device
* @reg_vdd: positive supply regulator
* @reg_vss: negative supply regulator
+ * @gpio_reset: reset gpio
+ * @gpio_clear: clear gpio
+ * @gpio_ldac: load dac gpio
* @chip_info: chip model specific constants
* @vref_mv: actual reference voltage used
* @vref_neg_mv: voltage of the negative supply
@@ -85,6 +92,9 @@ struct ad5791_state {
struct spi_device *spi;
struct regulator *reg_vdd;
struct regulator *reg_vss;
+ struct gpio_desc *gpio_reset;
+ struct gpio_desc *gpio_clear;
+ struct gpio_desc *gpio_ldac;
const struct ad5791_chip_info *chip_info;
unsigned short vref_mv;
unsigned int vref_neg_mv;
@@ -98,13 +108,6 @@ struct ad5791_state {
} data[3] __aligned(IIO_DMA_MINALIGN);
};
-enum ad5791_supported_device_ids {
- ID_AD5760,
- ID_AD5780,
- ID_AD5781,
- ID_AD5791,
-};
-
static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val)
{
st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE |
@@ -228,20 +231,6 @@ static int ad5780_get_lin_comp(unsigned int span)
else
return AD5780_LINCOMP_10_20;
}
-static const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
- [ID_AD5760] = {
- .get_lin_comp = ad5780_get_lin_comp,
- },
- [ID_AD5780] = {
- .get_lin_comp = ad5780_get_lin_comp,
- },
- [ID_AD5781] = {
- .get_lin_comp = ad5791_get_lin_comp,
- },
- [ID_AD5791] = {
- .get_lin_comp = ad5791_get_lin_comp,
- },
-};
static int ad5791_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -289,30 +278,34 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
{ },
};
-#define AD5791_CHAN(bits, _shift) { \
- .type = IIO_VOLTAGE, \
- .output = 1, \
- .indexed = 1, \
- .address = AD5791_ADDR_DAC0, \
- .channel = 0, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_OFFSET), \
- .scan_type = { \
- .sign = 'u', \
- .realbits = (bits), \
- .storagebits = 24, \
- .shift = (_shift), \
- }, \
- .ext_info = ad5791_ext_info, \
+#define AD5791_DEFINE_CHIP_INFO(_name, bits, _shift, _lin_comp) \
+static const struct ad5791_chip_info _name##_chip_info = { \
+ .name = #_name, \
+ .get_lin_comp = &(_lin_comp), \
+ .channel = { \
+ .type = IIO_VOLTAGE, \
+ .output = 1, \
+ .indexed = 1, \
+ .address = AD5791_ADDR_DAC0, \
+ .channel = 0, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (bits), \
+ .storagebits = 24, \
+ .shift = (_shift), \
+ }, \
+ .ext_info = ad5791_ext_info, \
+ }, \
}
-static const struct iio_chan_spec ad5791_channels[] = {
- [ID_AD5760] = AD5791_CHAN(16, 4),
- [ID_AD5780] = AD5791_CHAN(18, 2),
- [ID_AD5781] = AD5791_CHAN(18, 2),
- [ID_AD5791] = AD5791_CHAN(20, 0)
-};
+AD5791_DEFINE_CHIP_INFO(ad5760, 16, 4, ad5780_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5780, 18, 2, ad5780_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5781, 18, 2, ad5791_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5790, 20, 0, ad5791_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5791, 20, 0, ad5791_get_lin_comp);
static int ad5791_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -341,7 +334,7 @@ static const struct iio_info ad5791_info = {
static int ad5791_probe(struct spi_device *spi)
{
- struct ad5791_platform_data *pdata = spi->dev.platform_data;
+ const struct ad5791_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad5791_state *st;
int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
@@ -351,31 +344,21 @@ static int ad5791_probe(struct spi_device *spi)
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg_vdd = devm_regulator_get(&spi->dev, "vdd");
- if (!IS_ERR(st->reg_vdd)) {
- ret = regulator_enable(st->reg_vdd);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg_vdd);
- if (ret < 0)
- goto error_disable_reg_pos;
-
- pos_voltage_uv = ret;
- }
- st->reg_vss = devm_regulator_get(&spi->dev, "vss");
- if (!IS_ERR(st->reg_vss)) {
- ret = regulator_enable(st->reg_vss);
- if (ret)
- goto error_disable_reg_pos;
+ st->gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(st->gpio_reset))
+ return PTR_ERR(st->gpio_reset);
- ret = regulator_get_voltage(st->reg_vss);
- if (ret < 0)
- goto error_disable_reg_neg;
+ st->gpio_clear = devm_gpiod_get_optional(&spi->dev, "clear",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->gpio_clear))
+ return PTR_ERR(st->gpio_clear);
- neg_voltage_uv = ret;
- }
+ st->gpio_ldac = devm_gpiod_get_optional(&spi->dev, "ldac",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(st->gpio_ldac))
+ return PTR_ERR(st->gpio_ldac);
st->pwr_down = true;
st->spi = spi;
@@ -386,7 +369,17 @@ static int ad5791_probe(struct spi_device *spi)
use_rbuf_gain2 = device_property_read_bool(&spi->dev,
"adi,rbuf-gain2-en");
- if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) {
+ pos_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vdd");
+ if (pos_voltage_uv < 0 && pos_voltage_uv != -ENODEV)
+ return dev_err_probe(&spi->dev, pos_voltage_uv,
+ "failed to get vdd voltage\n");
+
+ neg_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vss");
+ if (neg_voltage_uv < 0 && neg_voltage_uv != -ENODEV)
+ return dev_err_probe(&spi->dev, neg_voltage_uv,
+ "failed to get vss voltage\n");
+
+ if (neg_voltage_uv >= 0 && pos_voltage_uv >= 0) {
st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000;
st->vref_neg_mv = neg_voltage_uv / 1000;
} else if (pdata) {
@@ -396,13 +389,18 @@ static int ad5791_probe(struct spi_device *spi)
dev_warn(&spi->dev, "reference voltage unspecified\n");
}
- ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
- if (ret)
- goto error_disable_reg_neg;
-
- st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi)
- ->driver_data];
+ if (st->gpio_reset) {
+ fsleep(20);
+ gpiod_set_value_cansleep(st->gpio_reset, 0);
+ } else {
+ ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
+ if (ret)
+ return dev_err_probe(&spi->dev, ret, "fail to reset\n");
+ }
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return dev_err_probe(&spi->dev, -EINVAL, "no chip info\n");
st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
| (use_rbuf_gain2 ? 0 : AD5791_CTRL_RBUF) |
@@ -411,59 +409,42 @@ static int ad5791_probe(struct spi_device *spi)
ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl |
AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
if (ret)
- goto error_disable_reg_neg;
+ return dev_err_probe(&spi->dev, ret, "fail to write ctrl register\n");
- spi_set_drvdata(spi, indio_dev);
indio_dev->info = &ad5791_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels
- = &ad5791_channels[spi_get_device_id(spi)->driver_data];
+ indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
- indio_dev->name = spi_get_device_id(st->spi)->name;
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg_neg;
-
- return 0;
-
-error_disable_reg_neg:
- if (!IS_ERR(st->reg_vss))
- regulator_disable(st->reg_vss);
-error_disable_reg_pos:
- if (!IS_ERR(st->reg_vdd))
- regulator_disable(st->reg_vdd);
- return ret;
+ indio_dev->name = st->chip_info->name;
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
-static void ad5791_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5791_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg_vdd))
- regulator_disable(st->reg_vdd);
-
- if (!IS_ERR(st->reg_vss))
- regulator_disable(st->reg_vss);
-}
+static const struct of_device_id ad5791_of_match[] = {
+ { .compatible = "adi,ad5760", .data = &ad5760_chip_info },
+ { .compatible = "adi,ad5780", .data = &ad5780_chip_info },
+ { .compatible = "adi,ad5781", .data = &ad5781_chip_info },
+ { .compatible = "adi,ad5790", .data = &ad5790_chip_info },
+ { .compatible = "adi,ad5791", .data = &ad5791_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad5791_of_match);
static const struct spi_device_id ad5791_id[] = {
- {"ad5760", ID_AD5760},
- {"ad5780", ID_AD5780},
- {"ad5781", ID_AD5781},
- {"ad5790", ID_AD5791},
- {"ad5791", ID_AD5791},
- {}
+ { "ad5760", (kernel_ulong_t)&ad5760_chip_info },
+ { "ad5780", (kernel_ulong_t)&ad5780_chip_info },
+ { "ad5781", (kernel_ulong_t)&ad5781_chip_info },
+ { "ad5790", (kernel_ulong_t)&ad5790_chip_info },
+ { "ad5791", (kernel_ulong_t)&ad5791_chip_info },
+ { }
};
MODULE_DEVICE_TABLE(spi, ad5791_id);
static struct spi_driver ad5791_driver = {
.driver = {
.name = "ad5791",
+ .of_match_table = ad5791_of_match,
},
.probe = ad5791_probe,
- .remove = ad5791_remove,
.id_table = ad5791_id,
};
module_spi_driver(ad5791_driver);
diff --git a/drivers/iio/dac/ad8460.c b/drivers/iio/dac/ad8460.c
new file mode 100644
index 000000000000..f235394589df
--- /dev/null
+++ b/drivers/iio/dac/ad8460.c
@@ -0,0 +1,951 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AD8460 Waveform generator DAC Driver
+ *
+ * Copyright (C) 2024 Analog Devices, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/buffer-dma.h>
+#include <linux/iio/buffer-dmaengine.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+
+#define AD8460_CTRL_REG(x) (x)
+#define AD8460_HVDAC_DATA_WORD(x) (0x60 + (2 * (x)))
+
+#define AD8460_HV_RESET_MSK BIT(7)
+#define AD8460_HV_SLEEP_MSK BIT(4)
+#define AD8460_WAVE_GEN_MODE_MSK BIT(0)
+
+#define AD8460_HVDAC_SLEEP_MSK BIT(3)
+
+#define AD8460_FAULT_ARM_MSK BIT(7)
+#define AD8460_FAULT_LIMIT_MSK GENMASK(6, 0)
+
+#define AD8460_APG_MODE_ENABLE_MSK BIT(5)
+#define AD8460_PATTERN_DEPTH_MSK GENMASK(3, 0)
+
+#define AD8460_QUIESCENT_CURRENT_MSK GENMASK(7, 0)
+
+#define AD8460_SHUTDOWN_FLAG_MSK BIT(7)
+
+#define AD8460_DATA_BYTE_LOW_MSK GENMASK(7, 0)
+#define AD8460_DATA_BYTE_HIGH_MSK GENMASK(5, 0)
+#define AD8460_DATA_BYTE_FULL_MSK GENMASK(13, 0)
+
+#define AD8460_DEFAULT_FAULT_PROTECT 0x00
+#define AD8460_DATA_BYTE_WORD_LENGTH 2
+#define AD8460_NUM_DATA_WORDS 16
+#define AD8460_NOMINAL_VOLTAGE_SPAN 80
+#define AD8460_MIN_EXT_RESISTOR_OHMS 2000
+#define AD8460_MAX_EXT_RESISTOR_OHMS 20000
+#define AD8460_MIN_VREFIO_UV 120000
+#define AD8460_MAX_VREFIO_UV 1200000
+#define AD8460_ABS_MAX_OVERVOLTAGE_UV 55000000
+#define AD8460_ABS_MAX_OVERCURRENT_UA 1000000
+#define AD8460_MAX_OVERTEMPERATURE_MC 150000
+#define AD8460_MIN_OVERTEMPERATURE_MC 20000
+#define AD8460_CURRENT_LIMIT_CONV(x) ((x) / 15625)
+#define AD8460_VOLTAGE_LIMIT_CONV(x) ((x) / 1953000)
+#define AD8460_TEMP_LIMIT_CONV(x) (((x) + 266640) / 6510)
+
+enum ad8460_fault_type {
+ AD8460_OVERCURRENT_SRC,
+ AD8460_OVERCURRENT_SNK,
+ AD8460_OVERVOLTAGE_POS,
+ AD8460_OVERVOLTAGE_NEG,
+ AD8460_OVERTEMPERATURE,
+};
+
+struct ad8460_state {
+ struct spi_device *spi;
+ struct regmap *regmap;
+ struct iio_channel *tmp_adc_channel;
+ struct clk *sync_clk;
+ /* lock to protect against multiple access to the device and shared data */
+ struct mutex lock;
+ int refio_1p2v_mv;
+ u32 ext_resistor_ohms;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ __le16 spi_tx_buf __aligned(IIO_DMA_MINALIGN);
+};
+
+static int ad8460_hv_reset(struct ad8460_state *state)
+{
+ int ret;
+
+ ret = regmap_set_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_RESET_MSK);
+ if (ret)
+ return ret;
+
+ fsleep(20);
+
+ return regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_RESET_MSK);
+}
+
+static int ad8460_reset(const struct ad8460_state *state)
+{
+ struct device *dev = &state->spi->dev;
+ struct gpio_desc *reset;
+
+ reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset))
+ return dev_err_probe(dev, PTR_ERR(reset),
+ "Failed to get reset gpio");
+ if (reset) {
+ /* minimum duration of 10ns */
+ ndelay(10);
+ gpiod_set_value_cansleep(reset, 1);
+ return 0;
+ }
+
+ /* bring all registers to their default state */
+ return regmap_write(state->regmap, AD8460_CTRL_REG(0x03), 1);
+}
+
+static int ad8460_enable_apg_mode(struct ad8460_state *state, int val)
+{
+ int ret;
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02),
+ AD8460_APG_MODE_ENABLE_MSK,
+ FIELD_PREP(AD8460_APG_MODE_ENABLE_MSK, val));
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_WAVE_GEN_MODE_MSK,
+ FIELD_PREP(AD8460_WAVE_GEN_MODE_MSK, val));
+}
+
+static int ad8460_read_shutdown_flag(struct ad8460_state *state, u64 *flag)
+{
+ int ret, val;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x0E), &val);
+ if (ret)
+ return ret;
+
+ *flag = FIELD_GET(AD8460_SHUTDOWN_FLAG_MSK, val);
+ return 0;
+}
+
+static int ad8460_get_hvdac_word(struct ad8460_state *state, int index, int *val)
+{
+ int ret;
+
+ ret = regmap_bulk_read(state->regmap, AD8460_HVDAC_DATA_WORD(index),
+ &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH);
+ if (ret)
+ return ret;
+
+ *val = le16_to_cpu(state->spi_tx_buf);
+
+ return ret;
+}
+
+static int ad8460_set_hvdac_word(struct ad8460_state *state, int index, int val)
+{
+ state->spi_tx_buf = cpu_to_le16(FIELD_PREP(AD8460_DATA_BYTE_FULL_MSK, val));
+
+ return regmap_bulk_write(state->regmap, AD8460_HVDAC_DATA_WORD(index),
+ &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH);
+}
+
+static ssize_t ad8460_dac_input_read(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = ad8460_get_hvdac_word(state, private, &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%u\n", reg);
+}
+
+static ssize_t ad8460_dac_input_write(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = kstrtou32(buf, 10, &reg);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ return ad8460_set_hvdac_word(state, private, reg);
+}
+
+static ssize_t ad8460_read_symbol(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%lu\n", FIELD_GET(AD8460_PATTERN_DEPTH_MSK, reg));
+}
+
+static ssize_t ad8460_write_symbol(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ uint16_t sym;
+ int ret;
+
+ ret = kstrtou16(buf, 10, &sym);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ return regmap_update_bits(state->regmap,
+ AD8460_CTRL_REG(0x02),
+ AD8460_PATTERN_DEPTH_MSK,
+ FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, sym));
+}
+
+static ssize_t ad8460_read_toggle_en(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_APG_MODE_ENABLE_MSK, reg));
+}
+
+static ssize_t ad8460_write_toggle_en(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ bool toggle_en;
+ int ret;
+
+ ret = kstrtobool(buf, &toggle_en);
+ if (ret)
+ return ret;
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad8460_enable_apg_mode(state, toggle_en);
+ unreachable();
+}
+
+static ssize_t ad8460_read_powerdown(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x01), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_HVDAC_SLEEP_MSK, reg));
+}
+
+static ssize_t ad8460_write_powerdown(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ bool pwr_down;
+ u64 sdn_flag;
+ int ret;
+
+ ret = kstrtobool(buf, &pwr_down);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ /*
+ * If powerdown is set, HVDAC is enabled and the HV driver is
+ * enabled via HV_RESET in case it is in shutdown mode,
+ * If powerdown is cleared, HVDAC is set to shutdown state
+ * as well as the HV driver. Quiescent current decreases and ouput is
+ * floating (high impedance).
+ */
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x01),
+ AD8460_HVDAC_SLEEP_MSK,
+ FIELD_PREP(AD8460_HVDAC_SLEEP_MSK, pwr_down));
+ if (ret)
+ return ret;
+
+ if (!pwr_down) {
+ ret = ad8460_read_shutdown_flag(state, &sdn_flag);
+ if (ret)
+ return ret;
+
+ if (sdn_flag) {
+ ret = ad8460_hv_reset(state);
+ if (ret)
+ return ret;
+ }
+ }
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_SLEEP_MSK,
+ FIELD_PREP(AD8460_HV_SLEEP_MSK, !pwr_down));
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static const char * const ad8460_powerdown_modes[] = {
+ "three_state",
+};
+
+static int ad8460_get_powerdown_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ return 0;
+}
+
+static int ad8460_set_powerdown_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int type)
+{
+ return 0;
+}
+
+static int ad8460_set_sample(struct ad8460_state *state, int val)
+{
+ int ret;
+
+ ret = ad8460_enable_apg_mode(state, 1);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+ ret = ad8460_set_hvdac_word(state, 0, val);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02),
+ AD8460_PATTERN_DEPTH_MSK,
+ FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, 0));
+}
+
+static int ad8460_set_fault_threshold(struct ad8460_state *state,
+ enum ad8460_fault_type fault,
+ unsigned int threshold)
+{
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault),
+ AD8460_FAULT_LIMIT_MSK,
+ FIELD_PREP(AD8460_FAULT_LIMIT_MSK, threshold));
+}
+
+static int ad8460_get_fault_threshold(struct ad8460_state *state,
+ enum ad8460_fault_type fault,
+ unsigned int *threshold)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val);
+ if (ret)
+ return ret;
+
+ *threshold = FIELD_GET(AD8460_FAULT_LIMIT_MSK, val);
+
+ return ret;
+}
+
+static int ad8460_set_fault_threshold_en(struct ad8460_state *state,
+ enum ad8460_fault_type fault, bool en)
+{
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault),
+ AD8460_FAULT_ARM_MSK,
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, en));
+}
+
+static int ad8460_get_fault_threshold_en(struct ad8460_state *state,
+ enum ad8460_fault_type fault, bool *en)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val);
+ if (ret)
+ return ret;
+
+ *en = FIELD_GET(AD8460_FAULT_ARM_MSK, val);
+
+ return 0;
+}
+
+static int ad8460_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad8460_set_sample(state, val);
+ unreachable();
+ case IIO_CURRENT:
+ return regmap_write(state->regmap, AD8460_CTRL_REG(0x04),
+ FIELD_PREP(AD8460_QUIESCENT_CURRENT_MSK, val));
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int data, ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ scoped_guard(mutex, &state->lock) {
+ ret = ad8460_get_hvdac_word(state, 0, &data);
+ if (ret)
+ return ret;
+ }
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_CURRENT:
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x04),
+ &data);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_TEMP:
+ ret = iio_read_channel_raw(state->tmp_adc_channel, &data);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = clk_get_rate(state->sync_clk);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ /*
+ * vCONV = vNOMINAL_SPAN * (DAC_CODE / 2**14) - 40V
+ * vMAX = vNOMINAL_SPAN * (2**14 / 2**14) - 40V
+ * vMIN = vNOMINAL_SPAN * (0 / 2**14) - 40V
+ * vADJ = vCONV * (2000 / rSET) * (vREF / 1.2)
+ * vSPAN = vADJ_MAX - vADJ_MIN
+ * See datasheet page 49, section FULL-SCALE REDUCTION
+ */
+ *val = AD8460_NOMINAL_VOLTAGE_SPAN * 2000 * state->refio_1p2v_mv;
+ *val2 = state->ext_resistor_ohms * 1200;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_select_fault_type(int chan_type, enum iio_event_direction dir)
+{
+ switch (chan_type) {
+ case IIO_VOLTAGE:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERVOLTAGE_POS;
+ case IIO_EV_DIR_FALLING:
+ return AD8460_OVERVOLTAGE_NEG;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CURRENT:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERCURRENT_SRC;
+ case IIO_EV_DIR_FALLING:
+ return AD8460_OVERCURRENT_SNK;
+ default:
+ return -EINVAL;
+ }
+ case IIO_TEMP:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERTEMPERATURE;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int val, int val2)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_set_fault_threshold(state, fault, val);
+}
+
+static int ad8460_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int *val, int *val2)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_get_fault_threshold(state, fault, val);
+}
+
+static int ad8460_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, bool val)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_set_fault_threshold_en(state, fault, val);
+}
+
+static int ad8460_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault, ret;
+ bool en;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ ret = ad8460_get_fault_threshold_en(state, fault, &en);
+ if (ret)
+ return ret;
+
+ return en;
+}
+
+static int ad8460_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+ unsigned int writeval, unsigned int *readval)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ if (readval)
+ return regmap_read(state->regmap, reg, readval);
+
+ return regmap_write(state->regmap, reg, writeval);
+}
+
+static int ad8460_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ return ad8460_enable_apg_mode(state, 0);
+}
+
+static int ad8460_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ return ad8460_enable_apg_mode(state, 1);
+}
+
+static const struct iio_buffer_setup_ops ad8460_buffer_setup_ops = {
+ .preenable = &ad8460_buffer_preenable,
+ .postdisable = &ad8460_buffer_postdisable,
+};
+
+static const struct iio_info ad8460_info = {
+ .read_raw = &ad8460_read_raw,
+ .write_raw = &ad8460_write_raw,
+ .write_event_value = &ad8460_write_event_value,
+ .read_event_value = &ad8460_read_event_value,
+ .write_event_config = &ad8460_write_event_config,
+ .read_event_config = &ad8460_read_event_config,
+ .debugfs_reg_access = &ad8460_reg_access,
+};
+
+static const struct iio_enum ad8460_powerdown_mode_enum = {
+ .items = ad8460_powerdown_modes,
+ .num_items = ARRAY_SIZE(ad8460_powerdown_modes),
+ .get = ad8460_get_powerdown_mode,
+ .set = ad8460_set_powerdown_mode,
+};
+
+#define AD8460_CHAN_EXT_INFO(_name, _what, _read, _write) { \
+ .name = (_name), \
+ .read = (_read), \
+ .write = (_write), \
+ .private = (_what), \
+ .shared = IIO_SEPARATE, \
+}
+
+static const struct iio_chan_spec_ext_info ad8460_ext_info[] = {
+ AD8460_CHAN_EXT_INFO("raw0", 0, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw1", 1, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw2", 2, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw3", 3, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw4", 4, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw5", 5, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw6", 6, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw7", 7, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw8", 8, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw9", 9, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw10", 10, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw11", 11, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw12", 12, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw13", 13, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw14", 14, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw15", 15, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("toggle_en", 0, ad8460_read_toggle_en,
+ ad8460_write_toggle_en),
+ AD8460_CHAN_EXT_INFO("symbol", 0, ad8460_read_symbol,
+ ad8460_write_symbol),
+ AD8460_CHAN_EXT_INFO("powerdown", 0, ad8460_read_powerdown,
+ ad8460_write_powerdown),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad8460_powerdown_mode_enum),
+ IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
+ &ad8460_powerdown_mode_enum),
+ { }
+};
+
+static const struct iio_event_spec ad8460_events[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+#define AD8460_VOLTAGE_CHAN { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = 0, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 14, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ .ext_info = ad8460_ext_info, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = ARRAY_SIZE(ad8460_events), \
+}
+
+#define AD8460_CURRENT_CHAN { \
+ .type = IIO_CURRENT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = -1, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = ARRAY_SIZE(ad8460_events), \
+}
+
+#define AD8460_TEMP_CHAN { \
+ .type = IIO_TEMP, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = -1, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = 1, \
+}
+
+static const struct iio_chan_spec ad8460_channels[] = {
+ AD8460_VOLTAGE_CHAN,
+ AD8460_CURRENT_CHAN,
+};
+
+static const struct iio_chan_spec ad8460_channels_with_tmp_adc[] = {
+ AD8460_VOLTAGE_CHAN,
+ AD8460_CURRENT_CHAN,
+ AD8460_TEMP_CHAN,
+};
+
+static const struct regmap_config ad8460_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x7F,
+};
+
+static const char * const ad8460_supplies[] = {
+ "avdd_3p3v", "dvdd_3p3v", "vcc_5v", "hvcc", "hvee", "vref_5v"
+};
+
+static int ad8460_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ad8460_state *state;
+ struct iio_dev *indio_dev;
+ u32 tmp[2], temp;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+
+ indio_dev->name = "ad8460";
+ indio_dev->info = &ad8460_info;
+
+ state->spi = spi;
+
+ state->regmap = devm_regmap_init_spi(spi, &ad8460_regmap_config);
+ if (IS_ERR(state->regmap))
+ return dev_err_probe(dev, PTR_ERR(state->regmap),
+ "Failed to initialize regmap");
+
+ ret = devm_mutex_init(dev, &state->lock);
+ if (ret)
+ return ret;
+
+ state->sync_clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(state->sync_clk))
+ return dev_err_probe(dev, PTR_ERR(state->sync_clk),
+ "Failed to get sync clk\n");
+
+ state->tmp_adc_channel = devm_iio_channel_get(dev, "ad8460-tmp");
+ if (IS_ERR(state->tmp_adc_channel)) {
+ if (PTR_ERR(state->tmp_adc_channel) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ indio_dev->channels = ad8460_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad8460_channels);
+ } else {
+ indio_dev->channels = ad8460_channels_with_tmp_adc;
+ indio_dev->num_channels = ARRAY_SIZE(ad8460_channels_with_tmp_adc);
+ }
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad8460_supplies),
+ ad8460_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to enable power supplies\n");
+
+ ret = devm_regulator_get_enable_read_voltage(dev, "refio_1p2v");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "Failed to get reference voltage\n");
+
+ state->refio_1p2v_mv = ret == -ENODEV ? 1200 : ret / 1000;
+
+ if (!in_range(state->refio_1p2v_mv, AD8460_MIN_VREFIO_UV / 1000,
+ AD8460_MAX_VREFIO_UV / 1000))
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid ref voltage range(%u mV) [%u mV, %u mV]\n",
+ state->refio_1p2v_mv,
+ AD8460_MIN_VREFIO_UV / 1000,
+ AD8460_MAX_VREFIO_UV / 1000);
+
+ ret = device_property_read_u32(dev, "adi,external-resistor-ohms",
+ &state->ext_resistor_ohms);
+ if (ret)
+ state->ext_resistor_ohms = 2000;
+ else if (!in_range(state->ext_resistor_ohms, AD8460_MIN_EXT_RESISTOR_OHMS,
+ AD8460_MAX_EXT_RESISTOR_OHMS))
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid resistor set range(%u) [%u, %u]\n",
+ state->ext_resistor_ohms,
+ AD8460_MIN_EXT_RESISTOR_OHMS,
+ AD8460_MAX_EXT_RESISTOR_OHMS);
+
+ ret = device_property_read_u32_array(dev, "adi,range-microamp",
+ tmp, ARRAY_SIZE(tmp));
+ if (!ret) {
+ if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERCURRENT_UA))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x08),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_CURRENT_LIMIT_CONV(tmp[1]));
+
+ if (in_range(tmp[0], -AD8460_ABS_MAX_OVERCURRENT_UA, 0))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x09),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_CURRENT_LIMIT_CONV(abs(tmp[0])));
+ }
+
+ ret = device_property_read_u32_array(dev, "adi,range-microvolt",
+ tmp, ARRAY_SIZE(tmp));
+ if (!ret) {
+ if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERVOLTAGE_UV))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0A),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_VOLTAGE_LIMIT_CONV(tmp[1]));
+
+ if (in_range(tmp[0], -AD8460_ABS_MAX_OVERVOLTAGE_UV, 0))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0B),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_VOLTAGE_LIMIT_CONV(abs(tmp[0])));
+ }
+
+ ret = device_property_read_u32(dev, "adi,max-millicelsius", &temp);
+ if (!ret) {
+ if (in_range(temp, AD8460_MIN_OVERTEMPERATURE_MC,
+ AD8460_MAX_OVERTEMPERATURE_MC))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0C),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_TEMP_LIMIT_CONV(abs(temp)));
+ }
+
+ ret = ad8460_reset(state);
+ if (ret)
+ return ret;
+
+ /* Enables DAC by default */
+ ret = regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x01),
+ AD8460_HVDAC_SLEEP_MSK);
+ if (ret)
+ return ret;
+
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->setup_ops = &ad8460_buffer_setup_ops;
+
+ ret = devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, "tx",
+ IIO_BUFFER_DIRECTION_OUT);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get DMA buffer\n");
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad8460_of_match[] = {
+ { .compatible = "adi,ad8460" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad8460_of_match);
+
+static const struct spi_device_id ad8460_spi_match[] = {
+ { .name = "ad8460" },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad8460_spi_match);
+
+static struct spi_driver ad8460_driver = {
+ .driver = {
+ .name = "ad8460",
+ .of_match_table = ad8460_of_match,
+ },
+ .probe = ad8460_probe,
+ .id_table = ad8460_spi_match,
+};
+module_spi_driver(ad8460_driver);
+
+MODULE_AUTHOR("Mariel Tinaco <mariel.tinaco@analog.com");
+MODULE_DESCRIPTION("AD8460 DAC driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
index 0cb00f3bec04..dd1919441b6d 100644
--- a/drivers/iio/dac/adi-axi-dac.c
+++ b/drivers/iio/dac/adi-axi-dac.c
@@ -29,44 +29,77 @@
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include "ad3552r-hs.h"
+
/*
* Register definitions:
* https://wiki.analog.com/resources/fpga/docs/axi_dac_ip#register_map
*/
/* Base controls */
-#define AXI_DAC_REG_CONFIG 0x0c
-#define AXI_DDS_DISABLE BIT(6)
+#define AXI_DAC_CONFIG_REG 0x0c
+#define AXI_DAC_CONFIG_DDS_DISABLE BIT(6)
/* DAC controls */
-#define AXI_DAC_REG_RSTN 0x0040
-#define AXI_DAC_RSTN_CE_N BIT(2)
-#define AXI_DAC_RSTN_MMCM_RSTN BIT(1)
-#define AXI_DAC_RSTN_RSTN BIT(0)
-#define AXI_DAC_REG_CNTRL_1 0x0044
-#define AXI_DAC_SYNC BIT(0)
-#define AXI_DAC_REG_CNTRL_2 0x0048
-#define ADI_DAC_R1_MODE BIT(4)
-#define AXI_DAC_DRP_STATUS 0x0074
-#define AXI_DAC_DRP_LOCKED BIT(17)
+#define AXI_DAC_RSTN_REG 0x0040
+#define AXI_DAC_RSTN_CE_N BIT(2)
+#define AXI_DAC_RSTN_MMCM_RSTN BIT(1)
+#define AXI_DAC_RSTN_RSTN BIT(0)
+#define AXI_DAC_CNTRL_1_REG 0x0044
+#define AXI_DAC_CNTRL_1_SYNC BIT(0)
+#define AXI_DAC_CNTRL_2_REG 0x0048
+#define AXI_DAC_CNTRL_2_SDR_DDR_N BIT(16)
+#define AXI_DAC_CNTRL_2_SYMB_8B BIT(14)
+#define ADI_DAC_CNTRL_2_R1_MODE BIT(5)
+#define AXI_DAC_CNTRL_2_UNSIGNED_DATA BIT(4)
+#define AXI_DAC_STATUS_1_REG 0x0054
+#define AXI_DAC_STATUS_2_REG 0x0058
+#define AXI_DAC_DRP_STATUS_REG 0x0074
+#define AXI_DAC_DRP_STATUS_DRP_LOCKED BIT(17)
+#define AXI_DAC_CUSTOM_RD_REG 0x0080
+#define AXI_DAC_CUSTOM_WR_REG 0x0084
+#define AXI_DAC_CUSTOM_WR_DATA_8 GENMASK(23, 16)
+#define AXI_DAC_CUSTOM_WR_DATA_16 GENMASK(23, 8)
+#define AXI_DAC_UI_STATUS_REG 0x0088
+#define AXI_DAC_UI_STATUS_IF_BUSY BIT(4)
+#define AXI_DAC_CUSTOM_CTRL_REG 0x008C
+#define AXI_DAC_CUSTOM_CTRL_ADDRESS GENMASK(31, 24)
+#define AXI_DAC_CUSTOM_CTRL_SYNCED_TRANSFER BIT(2)
+#define AXI_DAC_CUSTOM_CTRL_STREAM BIT(1)
+#define AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA BIT(0)
+
+#define AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE (AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA | \
+ AXI_DAC_CUSTOM_CTRL_STREAM)
+
/* DAC Channel controls */
-#define AXI_DAC_REG_CHAN_CNTRL_1(c) (0x0400 + (c) * 0x40)
-#define AXI_DAC_REG_CHAN_CNTRL_3(c) (0x0408 + (c) * 0x40)
-#define AXI_DAC_SCALE_SIGN BIT(15)
-#define AXI_DAC_SCALE_INT BIT(14)
-#define AXI_DAC_SCALE GENMASK(14, 0)
-#define AXI_DAC_REG_CHAN_CNTRL_2(c) (0x0404 + (c) * 0x40)
-#define AXI_DAC_REG_CHAN_CNTRL_4(c) (0x040c + (c) * 0x40)
-#define AXI_DAC_PHASE GENMASK(31, 16)
-#define AXI_DAC_FREQUENCY GENMASK(15, 0)
-#define AXI_DAC_REG_CHAN_CNTRL_7(c) (0x0418 + (c) * 0x40)
-#define AXI_DAC_DATA_SEL GENMASK(3, 0)
+#define AXI_DAC_CHAN_CNTRL_1_REG(c) (0x0400 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_3_REG(c) (0x0408 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN BIT(15)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE_INT BIT(14)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE GENMASK(14, 0)
+#define AXI_DAC_CHAN_CNTRL_2_REG(c) (0x0404 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_2_PHASE GENMASK(31, 16)
+#define AXI_DAC_CHAN_CNTRL_2_FREQUENCY GENMASK(15, 0)
+#define AXI_DAC_CHAN_CNTRL_4_REG(c) (0x040c + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_7_REG(c) (0x0418 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_7_DATA_SEL GENMASK(3, 0)
+
+#define AXI_DAC_RD_ADDR(x) (BIT(7) | (x))
/* 360 degrees in rad */
-#define AXI_DAC_2_PI_MEGA 6283190
+#define AXI_DAC_2_PI_MEGA 6283190
+
enum {
AXI_DAC_DATA_INTERNAL_TONE,
AXI_DAC_DATA_DMA = 2,
+ AXI_DAC_DATA_INTERNAL_RAMP_16BIT = 11,
+};
+
+struct axi_dac_info {
+ unsigned int version;
+ const struct iio_backend_info *backend_info;
+ bool has_dac_clk;
+ bool has_child_nodes;
};
struct axi_dac_state {
@@ -77,9 +110,11 @@ struct axi_dac_state {
* data/variables.
*/
struct mutex lock;
+ const struct axi_dac_info *info;
u64 dac_clk;
u32 reg_config;
bool int_tone;
+ int dac_clk_rate;
};
static int axi_dac_enable(struct iio_backend *back)
@@ -89,7 +124,7 @@ static int axi_dac_enable(struct iio_backend *back)
int ret;
guard(mutex)(&st->lock);
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,
+ ret = regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
AXI_DAC_RSTN_MMCM_RSTN);
if (ret)
return ret;
@@ -98,12 +133,14 @@ static int axi_dac_enable(struct iio_backend *back)
* designs really use it but if they don't we still get the lock bit
* set. So let's do it all the time so the code is generic.
*/
- ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS, __val,
- __val & AXI_DAC_DRP_LOCKED, 100, 1000);
+ ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS_REG,
+ __val,
+ __val & AXI_DAC_DRP_STATUS_DRP_LOCKED,
+ 100, 1000);
if (ret)
return ret;
- return regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,
+ return regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
AXI_DAC_RSTN_RSTN | AXI_DAC_RSTN_MMCM_RSTN);
}
@@ -112,7 +149,7 @@ static void axi_dac_disable(struct iio_backend *back)
struct axi_dac_state *st = iio_backend_get_priv(back);
guard(mutex)(&st->lock);
- regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);
+ regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0);
}
static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back,
@@ -155,15 +192,15 @@ static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan,
}
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- raw = FIELD_GET(AXI_DAC_FREQUENCY, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw);
*freq = DIV_ROUND_CLOSEST_ULL(raw * st->dac_clk, BIT(16));
return 0;
@@ -194,17 +231,18 @@ static int axi_dac_scale_get(struct axi_dac_state *st,
u32 reg, raw;
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- sign = FIELD_GET(AXI_DAC_SCALE_SIGN, raw);
- raw = FIELD_GET(AXI_DAC_SCALE, raw);
- scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA, AXI_DAC_SCALE_INT);
+ sign = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE, raw);
+ scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA,
+ AXI_DAC_CHAN_CNTRL_3_SCALE_INT);
vals[0] = scale / MEGA;
vals[1] = scale % MEGA;
@@ -227,15 +265,15 @@ static int axi_dac_phase_get(struct axi_dac_state *st,
int ret, vals[2];
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- raw = FIELD_GET(AXI_DAC_PHASE, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_PHASE, raw);
phase = DIV_ROUND_CLOSEST_ULL((u64)raw * AXI_DAC_2_PI_MEGA, U16_MAX);
vals[0] = phase / MEGA;
@@ -260,18 +298,20 @@ static int __axi_dac_frequency_set(struct axi_dac_state *st, unsigned int chan,
}
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan);
raw = DIV64_U64_ROUND_CLOSEST((u64)freq * BIT(16), sample_rate);
- ret = regmap_update_bits(st->regmap, reg, AXI_DAC_FREQUENCY, raw);
+ ret = regmap_update_bits(st->regmap, reg,
+ AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw);
if (ret)
return ret;
/* synchronize channels */
- return regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
}
static int axi_dac_frequency_set(struct axi_dac_state *st,
@@ -312,16 +352,16 @@ static int axi_dac_scale_set(struct axi_dac_state *st,
/* format is 1.1.14 (sign, integer and fractional bits) */
if (scale < 0) {
- raw = FIELD_PREP(AXI_DAC_SCALE_SIGN, 1);
+ raw = FIELD_PREP(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, 1);
scale *= -1;
}
- raw |= div_u64((u64)scale * AXI_DAC_SCALE_INT, MEGA);
+ raw |= div_u64((u64)scale * AXI_DAC_CHAN_CNTRL_3_SCALE_INT, MEGA);
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel);
guard(mutex)(&st->lock);
ret = regmap_write(st->regmap, reg, raw);
@@ -329,7 +369,8 @@ static int axi_dac_scale_set(struct axi_dac_state *st,
return ret;
/* synchronize channels */
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
if (ret)
return ret;
@@ -355,18 +396,19 @@ static int axi_dac_phase_set(struct axi_dac_state *st,
raw = DIV_ROUND_CLOSEST_ULL((u64)phase * U16_MAX, AXI_DAC_2_PI_MEGA);
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel);
guard(mutex)(&st->lock);
- ret = regmap_update_bits(st->regmap, reg, AXI_DAC_PHASE,
- FIELD_PREP(AXI_DAC_PHASE, raw));
+ ret = regmap_update_bits(st->regmap, reg, AXI_DAC_CHAN_CNTRL_2_PHASE,
+ FIELD_PREP(AXI_DAC_CHAN_CNTRL_2_PHASE, raw));
if (ret)
return ret;
/* synchronize channels */
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
if (ret)
return ret;
@@ -437,7 +479,7 @@ static int axi_dac_extend_chan(struct iio_backend *back,
if (chan->type != IIO_ALTVOLTAGE)
return -EINVAL;
- if (st->reg_config & AXI_DDS_DISABLE)
+ if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE)
/* nothing to extend */
return 0;
@@ -454,13 +496,19 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
switch (data) {
case IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE:
return regmap_update_bits(st->regmap,
- AXI_DAC_REG_CHAN_CNTRL_7(chan),
- AXI_DAC_DATA_SEL,
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
AXI_DAC_DATA_INTERNAL_TONE);
case IIO_BACKEND_EXTERNAL:
return regmap_update_bits(st->regmap,
- AXI_DAC_REG_CHAN_CNTRL_7(chan),
- AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
+ AXI_DAC_DATA_DMA);
+ case IIO_BACKEND_INTERNAL_RAMP_16BIT:
+ return regmap_update_bits(st->regmap,
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
+ AXI_DAC_DATA_INTERNAL_RAMP_16BIT);
default:
return -EINVAL;
}
@@ -475,7 +523,7 @@ static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan,
if (!sample_rate)
return -EINVAL;
- if (st->reg_config & AXI_DDS_DISABLE)
+ if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE)
/* sample_rate has no meaning if DDS is disabled */
return 0;
@@ -518,6 +566,184 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,
return regmap_write(st->regmap, reg, writeval);
}
+static int axi_dac_ddr_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SDR_DDR_N);
+}
+
+static int axi_dac_ddr_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SDR_DDR_N);
+}
+
+static int axi_dac_data_stream_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE);
+}
+
+static int axi_dac_data_stream_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE);
+}
+
+static int axi_dac_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ if (address > FIELD_MAX(AXI_DAC_CUSTOM_CTRL_ADDRESS))
+ return -EINVAL;
+
+ /*
+ * Sample register address, when the DAC is configured, or stream
+ * start address when the FSM is in stream state.
+ */
+ return regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ address));
+}
+
+static int axi_dac_data_format_set(struct iio_backend *back, unsigned int ch,
+ const struct iio_backend_data_fmt *data)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ switch (data->type) {
+ case IIO_BACKEND_DATA_UNSIGNED:
+ return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_UNSIGNED_DATA);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __axi_dac_bus_reg_write(struct iio_backend *back, u32 reg,
+ u32 val, size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+ int ret;
+ u32 ival;
+
+ /*
+ * Both AXI_DAC_CNTRL_2_REG and AXI_DAC_CUSTOM_WR_REG need to know
+ * the data size. So keeping data size control here only,
+ * since data size is mandatory for the current transfer.
+ * DDR state handled separately by specific backend calls,
+ * generally all raw register writes are SDR.
+ */
+ if (data_size == sizeof(u16))
+ ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_16, val);
+ else
+ ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_8, val);
+
+ ret = regmap_write(st->regmap, AXI_DAC_CUSTOM_WR_REG, ival);
+ if (ret)
+ return ret;
+
+ if (data_size == sizeof(u8))
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SYMB_8B);
+ else
+ ret = regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SYMB_8B);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS, reg));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(st->regmap,
+ AXI_DAC_UI_STATUS_REG, ival,
+ FIELD_GET(AXI_DAC_UI_STATUS_IF_BUSY, ival) == 0,
+ 10, 100 * KILO);
+ if (ret == -ETIMEDOUT)
+ dev_err(st->dev, "AXI read timeout\n");
+
+ /* Cleaning always AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA */
+ return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA);
+}
+
+static int axi_dac_bus_reg_write(struct iio_backend *back, u32 reg,
+ u32 val, size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ guard(mutex)(&st->lock);
+ return __axi_dac_bus_reg_write(back, reg, val, data_size);
+}
+
+static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val,
+ size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ /*
+ * SPI, we write with read flag, then we read just at the AXI
+ * io address space to get data read.
+ */
+ ret = __axi_dac_bus_reg_write(back, AXI_DAC_RD_ADDR(reg), 0,
+ data_size);
+ if (ret)
+ return ret;
+
+ return regmap_read(st->regmap, AXI_DAC_CUSTOM_RD_REG, val);
+}
+
+static void axi_dac_child_remove(void *data)
+{
+ platform_device_unregister(data);
+}
+
+static int axi_dac_create_platform_device(struct axi_dac_state *st,
+ struct fwnode_handle *child)
+{
+ struct ad3552r_hs_platform_data pdata = {
+ .bus_reg_read = axi_dac_bus_reg_read,
+ .bus_reg_write = axi_dac_bus_reg_write,
+ .bus_sample_data_clock_hz = st->dac_clk_rate,
+ };
+ struct platform_device_info pi = {
+ .parent = st->dev,
+ .name = fwnode_get_name(child),
+ .id = PLATFORM_DEVID_AUTO,
+ .fwnode = child,
+ .data = &pdata,
+ .size_data = sizeof(pdata),
+ };
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_full(&pi);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ return devm_add_action_or_reset(st->dev, axi_dac_child_remove, pdev);
+}
+
static const struct iio_backend_ops axi_dac_generic_ops = {
.enable = axi_dac_enable,
.disable = axi_dac_disable,
@@ -531,11 +757,30 @@ static const struct iio_backend_ops axi_dac_generic_ops = {
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_dac_reg_access),
};
+static const struct iio_backend_ops axi_ad3552r_ops = {
+ .enable = axi_dac_enable,
+ .disable = axi_dac_disable,
+ .request_buffer = axi_dac_request_buffer,
+ .free_buffer = axi_dac_free_buffer,
+ .data_source_set = axi_dac_data_source_set,
+ .ddr_enable = axi_dac_ddr_enable,
+ .ddr_disable = axi_dac_ddr_disable,
+ .data_stream_enable = axi_dac_data_stream_enable,
+ .data_stream_disable = axi_dac_data_stream_disable,
+ .data_format_set = axi_dac_data_format_set,
+ .data_transfer_addr = axi_dac_data_transfer_addr,
+};
+
static const struct iio_backend_info axi_dac_generic = {
.name = "axi-dac",
.ops = &axi_dac_generic_ops,
};
+static const struct iio_backend_info axi_ad3552r = {
+ .name = "axi-ad3552r",
+ .ops = &axi_ad3552r_ops,
+};
+
static const struct regmap_config axi_dac_regmap_config = {
.val_bits = 32,
.reg_bits = 32,
@@ -545,7 +790,6 @@ static const struct regmap_config axi_dac_regmap_config = {
static int axi_dac_probe(struct platform_device *pdev)
{
- const unsigned int *expected_ver;
struct axi_dac_state *st;
void __iomem *base;
unsigned int ver;
@@ -556,14 +800,29 @@ static int axi_dac_probe(struct platform_device *pdev)
if (!st)
return -ENOMEM;
- expected_ver = device_get_match_data(&pdev->dev);
- if (!expected_ver)
+ st->info = device_get_match_data(&pdev->dev);
+ if (!st->info)
return -ENODEV;
+ clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
+ if (IS_ERR(clk)) {
+ /* Backward compat., old fdt versions without clock-names. */
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk),
+ "failed to get clock\n");
+ }
- clk = devm_clk_get_enabled(&pdev->dev, NULL);
- if (IS_ERR(clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(clk),
- "failed to get clock\n");
+ if (st->info->has_dac_clk) {
+ struct clk *dac_clk;
+
+ dac_clk = devm_clk_get_enabled(&pdev->dev, "dac_clk");
+ if (IS_ERR(dac_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dac_clk),
+ "failed to get dac_clk clock\n");
+
+ /* We only care about the streaming mode rate */
+ st->dac_clk_rate = clk_get_rate(dac_clk) / 2;
+ }
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
@@ -580,7 +839,7 @@ static int axi_dac_probe(struct platform_device *pdev)
* Force disable the core. Up to the frontend to enable us. And we can
* still read/write registers...
*/
- ret = regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);
+ ret = regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0);
if (ret)
return ret;
@@ -588,12 +847,13 @@ static int axi_dac_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
+ if (ADI_AXI_PCORE_VER_MAJOR(ver) !=
+ ADI_AXI_PCORE_VER_MAJOR(st->info->version)) {
dev_err(&pdev->dev,
"Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
- ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
- ADI_AXI_PCORE_VER_MINOR(*expected_ver),
- ADI_AXI_PCORE_VER_PATCH(*expected_ver),
+ ADI_AXI_PCORE_VER_MAJOR(st->info->version),
+ ADI_AXI_PCORE_VER_MINOR(st->info->version),
+ ADI_AXI_PCORE_VER_PATCH(st->info->version),
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
@@ -601,7 +861,7 @@ static int axi_dac_probe(struct platform_device *pdev)
}
/* Let's get the core read only configuration */
- ret = regmap_read(st->regmap, AXI_DAC_REG_CONFIG, &st->reg_config);
+ ret = regmap_read(st->regmap, AXI_DAC_CONFIG_REG, &st->reg_config);
if (ret)
return ret;
@@ -613,16 +873,40 @@ static int axi_dac_probe(struct platform_device *pdev)
* want independent channels let's override the core's default value and
* set the R1_MODE bit.
*/
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2, ADI_DAC_R1_MODE);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ ADI_DAC_CNTRL_2_R1_MODE);
if (ret)
return ret;
mutex_init(&st->lock);
- ret = devm_iio_backend_register(&pdev->dev, &axi_dac_generic, st);
+
+ ret = devm_iio_backend_register(&pdev->dev, st->info->backend_info, st);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"failed to register iio backend\n");
+ device_for_each_child_node_scoped(&pdev->dev, child) {
+ int val;
+
+ if (!st->info->has_child_nodes)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "invalid fdt axi-dac compatible.");
+
+ /* Processing only reg 0 node */
+ ret = fwnode_property_read_u32(child, "reg", &val);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "invalid reg property.");
+ if (val != 0)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "invalid node address.");
+
+ ret = axi_dac_create_platform_device(st, child);
+ if (ret)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "cannot create device.");
+ }
+
dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n",
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
@@ -631,10 +915,21 @@ static int axi_dac_probe(struct platform_device *pdev)
return 0;
}
-static unsigned int axi_dac_9_1_b_info = ADI_AXI_PCORE_VER(9, 1, 'b');
+static const struct axi_dac_info dac_generic = {
+ .version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+ .backend_info = &axi_dac_generic,
+};
+
+static const struct axi_dac_info dac_ad3552r = {
+ .version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+ .backend_info = &axi_ad3552r,
+ .has_dac_clk = true,
+ .has_child_nodes = true,
+};
static const struct of_device_id axi_dac_of_match[] = {
- { .compatible = "adi,axi-dac-9.1.b", .data = &axi_dac_9_1_b_info },
+ { .compatible = "adi,axi-dac-9.1.b", .data = &dac_generic },
+ { .compatible = "adi,axi-ad3552r", .data = &dac_ad3552r },
{}
};
MODULE_DEVICE_TABLE(of, axi_dac_of_match);
diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c
index 7332064d0852..f36f10bfb6be 100644
--- a/drivers/iio/dac/dpot-dac.c
+++ b/drivers/iio/dac/dpot-dac.c
@@ -243,7 +243,7 @@ MODULE_DEVICE_TABLE(of, dpot_dac_match);
static struct platform_driver dpot_dac_driver = {
.probe = dpot_dac_probe,
- .remove_new = dpot_dac_remove,
+ .remove = dpot_dac_remove,
.driver = {
.name = "iio-dpot-dac",
.of_match_table = dpot_dac_match,
diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
index b3aa4443a6a4..2332b0c22691 100644
--- a/drivers/iio/dac/lpc18xx_dac.c
+++ b/drivers/iio/dac/lpc18xx_dac.c
@@ -184,9 +184,9 @@ static const struct of_device_id lpc18xx_dac_match[] = {
MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
static struct platform_driver lpc18xx_dac_driver = {
- .probe = lpc18xx_dac_probe,
- .remove_new = lpc18xx_dac_remove,
- .driver = {
+ .probe = lpc18xx_dac_probe,
+ .remove = lpc18xx_dac_remove,
+ .driver = {
.name = "lpc18xx-dac",
.of_match_table = lpc18xx_dac_match,
},
diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c
index ae53baccec91..3497513854d7 100644
--- a/drivers/iio/dac/m62332.c
+++ b/drivers/iio/dac/m62332.c
@@ -201,7 +201,7 @@ static int m62332_probe(struct i2c_client *client)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &m62332_info;
- ret = iio_map_array_register(indio_dev, client->dev.platform_data);
+ ret = iio_map_array_register(indio_dev, dev_get_platdata(&client->dev));
if (ret < 0)
return ret;
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 685980184d3c..84336736a47b 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -143,10 +143,10 @@ static const struct iio_chan_spec max517_channels[] = {
static int max517_probe(struct i2c_client *client)
{
+ const struct max517_platform_data *platform_data = dev_get_platdata(&client->dev);
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct max517_data *data;
struct iio_dev *indio_dev;
- struct max517_platform_data *platform_data = client->dev.platform_data;
int chan;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
index 2d567073996b..95ed5197d16f 100644
--- a/drivers/iio/dac/stm32-dac-core.c
+++ b/drivers/iio/dac/stm32-dac-core.c
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove_new = stm32_dac_remove,
+ .remove = stm32_dac_remove,
.driver = {
.name = "stm32-dac-core",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
index 5a722f307e7e..3bfb368b3a23 100644
--- a/drivers/iio/dac/stm32-dac.c
+++ b/drivers/iio/dac/stm32-dac.c
@@ -398,7 +398,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove_new = stm32_dac_remove,
+ .remove = stm32_dac_remove,
.driver = {
.name = "stm32-dac",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c
index de73bc5a1c93..82a078fa98ad 100644
--- a/drivers/iio/dac/vf610_dac.c
+++ b/drivers/iio/dac/vf610_dac.c
@@ -272,7 +272,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_dac_pm_ops, vf610_dac_suspend,
static struct platform_driver vf610_dac_driver = {
.probe = vf610_dac_probe,
- .remove_new = vf610_dac_remove,
+ .remove = vf610_dac_remove,
.driver = {
.name = "vf610-dac",
.of_match_table = vf610_dac_match,
diff --git a/drivers/iio/dummy/iio_simple_dummy.h b/drivers/iio/dummy/iio_simple_dummy.h
index a91622ac54e0..8246f25dbad0 100644
--- a/drivers/iio/dummy/iio_simple_dummy.h
+++ b/drivers/iio/dummy/iio_simple_dummy.h
@@ -60,7 +60,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state);
+ bool state);
int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
diff --git a/drivers/iio/dummy/iio_simple_dummy_events.c b/drivers/iio/dummy/iio_simple_dummy_events.c
index 63a2b844be50..b51ec21b6309 100644
--- a/drivers/iio/dummy/iio_simple_dummy_events.c
+++ b/drivers/iio/dummy/iio_simple_dummy_events.c
@@ -53,7 +53,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iio_dummy_state *st = iio_priv(indio_dev);
@@ -183,36 +183,34 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private)
switch (st->regs->reg_data) {
case 0:
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->event_timestamp);
break;
case 1:
if (st->activity_running > st->event_val)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- IIO_MOD_RUNNING,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ IIO_MOD_RUNNING,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->event_timestamp);
break;
case 2:
if (st->activity_walking < st->event_val)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- IIO_MOD_WALKING,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ IIO_MOD_WALKING,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
st->event_timestamp);
break;
case 3:
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_DIR_NONE,
- IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0,
+ IIO_EV_TYPE_CHANGE,
+ IIO_EV_DIR_NONE),
st->event_timestamp);
break;
default:
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index b391c6e27ab0..b1554ced7a26 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -970,7 +970,7 @@ static int ad9523_setup(struct iio_dev *indio_dev)
static int ad9523_probe(struct spi_device *spi)
{
- struct ad9523_platform_data *pdata = spi->dev.platform_data;
+ struct ad9523_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad9523_state *st;
int ret;
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index e13e64a5164c..61828e61e275 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -603,7 +603,7 @@ static int adf4350_probe(struct spi_device *spi)
if (pdata == NULL)
return -EINVAL;
} else {
- pdata = spi->dev.platform_data;
+ pdata = dev_get_platdata(&spi->dev);
}
if (!pdata) {
diff --git a/drivers/iio/frequency/adf4371.c b/drivers/iio/frequency/adf4371.c
index b27088464826..d752507e0c98 100644
--- a/drivers/iio/frequency/adf4371.c
+++ b/drivers/iio/frequency/adf4371.c
@@ -4,6 +4,7 @@
*
* Copyright 2019 Analog Devices Inc.
*/
+#include "linux/dev_printk.h"
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/device.h>
@@ -150,6 +151,7 @@ static const struct regmap_config adf4371_regmap_config = {
};
struct adf4371_chip_info {
+ const char *name;
unsigned int num_channels;
const struct iio_chan_spec *channels;
};
@@ -157,7 +159,6 @@ struct adf4371_chip_info {
struct adf4371_state {
struct spi_device *spi;
struct regmap *regmap;
- struct clk *clkin;
/*
* Lock for accessing device registers. Some operations require
* multiple consecutive R/W operations, during which the device
@@ -444,15 +445,16 @@ static const struct iio_chan_spec adf4371_chan[] = {
ADF4371_CHANNEL(ADF4371_CH_RF32),
};
-static const struct adf4371_chip_info adf4371_chip_info[] = {
- [ADF4371] = {
- .channels = adf4371_chan,
- .num_channels = 4,
- },
- [ADF4372] = {
- .channels = adf4371_chan,
- .num_channels = 3,
- }
+static const struct adf4371_chip_info adf4371_chip_info = {
+ .name = "adf4371",
+ .channels = adf4371_chan,
+ .num_channels = 4,
+};
+
+static const struct adf4371_chip_info adf4372_chip_info = {
+ .name = "adf4372",
+ .channels = adf4371_chan,
+ .num_channels = 3,
};
static int adf4371_reg_access(struct iio_dev *indio_dev,
@@ -542,10 +544,10 @@ static int adf4371_setup(struct adf4371_state *st)
static int adf4371_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
struct iio_dev *indio_dev;
struct adf4371_state *st;
struct regmap *regmap;
+ struct clk *clkin;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
@@ -553,50 +555,49 @@ static int adf4371_probe(struct spi_device *spi)
return -ENOMEM;
regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
- PTR_ERR(regmap));
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&spi->dev, PTR_ERR(regmap),
+ "Error initializing spi regmap\n");
st = iio_priv(indio_dev);
- spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->regmap = regmap;
mutex_init(&st->lock);
- st->chip_info = &adf4371_chip_info[id->driver_data];
- indio_dev->name = id->name;
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
+ indio_dev->name = st->chip_info->name;
indio_dev->info = &adf4371_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
- st->clkin = devm_clk_get_enabled(&spi->dev, "clkin");
- if (IS_ERR(st->clkin))
- return PTR_ERR(st->clkin);
+ clkin = devm_clk_get_enabled(&spi->dev, "clkin");
+ if (IS_ERR(clkin))
+ return dev_err_probe(&spi->dev, PTR_ERR(clkin),
+ "Failed to get clkin\n");
- st->clkin_freq = clk_get_rate(st->clkin);
+ st->clkin_freq = clk_get_rate(clkin);
ret = adf4371_setup(st);
- if (ret < 0) {
- dev_err(&spi->dev, "ADF4371 setup failed\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&spi->dev, ret, "ADF4371 setup failed\n");
return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id adf4371_id_table[] = {
- { "adf4371", ADF4371 },
- { "adf4372", ADF4372 },
+ { "adf4371", (kernel_ulong_t)&adf4371_chip_info },
+ { "adf4372", (kernel_ulong_t)&adf4372_chip_info },
{}
};
MODULE_DEVICE_TABLE(spi, adf4371_id_table);
static const struct of_device_id adf4371_of_match[] = {
- { .compatible = "adi,adf4371" },
- { .compatible = "adi,adf4372" },
+ { .compatible = "adi,adf4371", .data = &adf4371_chip_info },
+ { .compatible = "adi,adf4372", .data = &adf4372_chip_info},
{ },
};
MODULE_DEVICE_TABLE(of, adf4371_of_match);
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 97b86c4a53a6..3e193ee0fb61 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -27,7 +27,7 @@ config ADIS16136
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
- ADIS16136 gyroscope devices.
+ ADIS16136, ADIS16137 gyroscope devices.
config ADIS16260
tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c
index 10728d5ccae3..ba877d067afb 100644
--- a/drivers/iio/gyro/bmg160_core.c
+++ b/drivers/iio/gyro/bmg160_core.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -444,7 +443,7 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data,
static int bmg160_get_bw(struct bmg160_data *data, int *val)
{
- struct device *dev = regmap_get_device(data->regmap);
+ struct device *dev = regmap_get_device(data->regmap);
int i;
unsigned int bw_bits;
int ret;
@@ -749,7 +748,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct bmg160_data *data = iio_priv(indio_dev);
int ret;
@@ -1055,17 +1054,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
.postdisable = bmg160_buffer_postdisable,
};
-static const char *bmg160_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name)
{
@@ -1098,9 +1086,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
mutex_init(&data->mutex);
- if (ACPI_HANDLE(dev))
- name = bmg160_match_acpi_device(dev);
-
indio_dev->channels = bmg160_channels;
indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
indio_dev->name = name;
diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c
index 672d0b720f61..9c5d7e8ee99c 100644
--- a/drivers/iio/gyro/bmg160_i2c.c
+++ b/drivers/iio/gyro/bmg160_i2c.c
@@ -17,7 +17,7 @@ static int bmg160_i2c_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct regmap *regmap;
- const char *name = NULL;
+ const char *name;
regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf);
if (IS_ERR(regmap)) {
@@ -28,6 +28,8 @@ static int bmg160_i2c_probe(struct i2c_client *client)
if (id)
name = id->name;
+ else
+ name = iio_get_acpi_device_name(&client->dev);
return bmg160_core_probe(&client->dev, regmap, client->irq, name);
}
@@ -39,8 +41,6 @@ static void bmg160_i2c_remove(struct i2c_client *client)
static const struct acpi_device_id bmg160_acpi_match[] = {
{"BMG0160", 0},
- {"BMI055B", 0},
- {"BMI088B", 0},
{},
};
diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c
index c28d17ca6f5e..688966129f70 100644
--- a/drivers/iio/gyro/fxas21002c_core.c
+++ b/drivers/iio/gyro/fxas21002c_core.c
@@ -849,8 +849,7 @@ static int fxas21002c_trigger_probe(struct fxas21002c_data *data)
if (!data->dready_trig)
return -ENOMEM;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(data->irq));
-
+ irq_trig = irq_get_trigger_type(data->irq);
if (irq_trig == IRQF_TRIGGER_RISING) {
ret = regmap_field_write(data->regmap_fields[F_IPOL], 1);
if (ret < 0)
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 59a38bf9459b..0598f1d3fbb3 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -27,7 +27,7 @@ struct gyro_3d_state {
struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX];
struct {
u32 gyro_val[GYRO_3D_CHANNEL_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -279,11 +279,11 @@ static int gyro_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_gyro_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "gyro_3d";
struct iio_dev *indio_dev;
struct gyro_3d_state *gyro_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state));
if (!indio_dev)
@@ -361,7 +361,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_gyro_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
@@ -386,7 +386,7 @@ static struct platform_driver hid_gyro_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_gyro_3d_probe,
- .remove_new = hid_gyro_3d_remove,
+ .remove = hid_gyro_3d_remove,
};
module_platform_driver(hid_gyro_3d_platform_driver);
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index 35af68b41408..b6883e8b2a8b 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -1059,12 +1059,12 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
/* Check if IRQ is open drain */
mpu3050->irq_opendrain = device_property_read_bool(dev, "drive-open-drain");
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
/*
* Configure the interrupt generator hardware to supply whatever
* the interrupt is configured for, edges low/high level low/high,
* we can provide it all.
*/
+ irq_trig = irq_get_trigger_type(irq);
switch (irq_trig) {
case IRQF_TRIGGER_RISING:
dev_info(&indio_dev->dev,
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index bf6d2636a85e..f2fa0e1631ff 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -18,7 +18,7 @@ struct hid_humidity_state {
struct hid_sensor_hub_attribute_info humidity_attr;
struct {
s32 humidity_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -287,7 +287,7 @@ static struct platform_driver hid_humidity_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_humidity_probe,
- .remove_new = hid_humidity_remove,
+ .remove = hid_humidity_remove,
};
module_platform_driver(hid_humidity_platform_driver);
diff --git a/drivers/iio/humidity/hts221_buffer.c b/drivers/iio/humidity/hts221_buffer.c
index 11ef38994a95..4d03db19063e 100644
--- a/drivers/iio/humidity/hts221_buffer.c
+++ b/drivers/iio/humidity/hts221_buffer.c
@@ -81,8 +81,7 @@ int hts221_allocate_trigger(struct iio_dev *iio_dev)
unsigned long irq_type;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 782fb80e44c2..ca0efecb5b5c 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -53,6 +53,7 @@ config ADIS16480
ADIS16485, ADIS16488 inertial sensors.
source "drivers/iio/imu/bmi160/Kconfig"
+source "drivers/iio/imu/bmi270/Kconfig"
source "drivers/iio/imu/bmi323/Kconfig"
source "drivers/iio/imu/bno055/Kconfig"
@@ -96,6 +97,20 @@ config KMX61
source "drivers/iio/imu/inv_icm42600/Kconfig"
source "drivers/iio/imu/inv_mpu6050/Kconfig"
+
+config SMI240
+ tristate "Bosch Sensor SMI240 Inertial Measurement Unit"
+ depends on SPI
+ select REGMAP_SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ If you say yes here you get support for SMI240 IMU on SPI with
+ accelerometer and gyroscope.
+
+ This driver can also be built as a module. If so, the module will be
+ called smi240.
+
source "drivers/iio/imu/st_lsm6dsx/Kconfig"
source "drivers/iio/imu/st_lsm9ds0/Kconfig"
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 7e2d7d5c3b7b..04c77c2c4df8 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -15,6 +15,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += bmi160/
+obj-y += bmi270/
obj-y += bmi323/
obj-y += bno055/
@@ -27,5 +28,7 @@ obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o
+obj-$(CONFIG_SMI240) += smi240.o
+
obj-y += st_lsm6dsx/
obj-y += st_lsm9ds0/
diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
index 495e8a74ac67..807c1a1476c2 100644
--- a/drivers/iio/imu/bmi160/bmi160_core.c
+++ b/drivers/iio/imu/bmi160/bmi160_core.c
@@ -690,18 +690,9 @@ static int bmi160_config_device_irq(struct iio_dev *indio_dev, int irq_type,
static int bmi160_setup_irq(struct iio_dev *indio_dev, int irq,
enum bmi160_int_pin pin)
{
- struct irq_data *desc;
- u32 irq_type;
+ u32 irq_type = irq_get_trigger_type(irq);
int ret;
- desc = irq_get_irq_data(irq);
- if (!desc) {
- dev_err(&indio_dev->dev, "Could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(desc);
-
ret = bmi160_config_device_irq(indio_dev, irq_type, pin);
if (ret)
return ret;
diff --git a/drivers/iio/imu/bmi270/Kconfig b/drivers/iio/imu/bmi270/Kconfig
new file mode 100644
index 000000000000..6362acc706da
--- /dev/null
+++ b/drivers/iio/imu/bmi270/Kconfig
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# BMI270 IMU driver
+#
+
+config BMI270
+ tristate
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+
+config BMI270_I2C
+ tristate "Bosch BMI270 I2C driver"
+ depends on I2C
+ select BMI270
+ select REGMAP_I2C
+ help
+ Enable support for the Bosch BMI270 6-Axis IMU connected to I2C
+ interface.
+
+ This driver can also be built as a module. If so, the module will be
+ called bmi270_i2c.
+
+config BMI270_SPI
+ tristate "Bosch BMI270 SPI driver"
+ depends on SPI
+ select BMI270
+ select REGMAP_SPI
+ help
+ Enable support for the Bosch BMI270 6-Axis IMU connected to SPI
+ interface.
+
+ This driver can also be built as a module. If so, the module will be
+ called bmi270_spi.
diff --git a/drivers/iio/imu/bmi270/Makefile b/drivers/iio/imu/bmi270/Makefile
new file mode 100644
index 000000000000..d96c96fc3d83
--- /dev/null
+++ b/drivers/iio/imu/bmi270/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Bosch BMI270 IMU
+#
+obj-$(CONFIG_BMI270) += bmi270_core.o
+obj-$(CONFIG_BMI270_I2C) += bmi270_i2c.o
+obj-$(CONFIG_BMI270_SPI) += bmi270_spi.o
diff --git a/drivers/iio/imu/bmi270/bmi270.h b/drivers/iio/imu/bmi270/bmi270.h
new file mode 100644
index 000000000000..fdfad5784cc5
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef BMI270_H_
+#define BMI270_H_
+
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
+struct device;
+struct bmi270_data {
+ struct device *dev;
+ struct regmap *regmap;
+ const struct bmi270_chip_info *chip_info;
+
+ /*
+ * Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to
+ * that to ensure a DMA safe buffer.
+ */
+ struct {
+ __le16 channels[6];
+ aligned_s64 timestamp;
+ } data __aligned(IIO_DMA_MINALIGN);
+};
+
+struct bmi270_chip_info {
+ const char *name;
+ int chip_id;
+ const char *fw_name;
+};
+
+extern const struct regmap_config bmi270_regmap_config;
+extern const struct bmi270_chip_info bmi260_chip_info;
+extern const struct bmi270_chip_info bmi270_chip_info;
+
+int bmi270_core_probe(struct device *dev, struct regmap *regmap,
+ const struct bmi270_chip_info *chip_info);
+
+#endif /* BMI270_H_ */
diff --git a/drivers/iio/imu/bmi270/bmi270_core.c b/drivers/iio/imu/bmi270/bmi270_core.c
new file mode 100644
index 000000000000..70db83a20239
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_core.c
@@ -0,0 +1,734 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/bitfield.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#include "bmi270.h"
+
+#define BMI270_CHIP_ID_REG 0x00
+
+/* Checked to prevent sending incompatible firmware to BMI160 devices */
+#define BMI160_CHIP_ID_VAL 0xD1
+
+#define BMI260_CHIP_ID_VAL 0x27
+#define BMI270_CHIP_ID_VAL 0x24
+#define BMI270_CHIP_ID_MSK GENMASK(7, 0)
+
+#define BMI270_ACCEL_X_REG 0x0c
+#define BMI270_ANG_VEL_X_REG 0x12
+
+#define BMI270_INTERNAL_STATUS_REG 0x21
+#define BMI270_INTERNAL_STATUS_MSG_MSK GENMASK(3, 0)
+#define BMI270_INTERNAL_STATUS_MSG_INIT_OK 0x01
+
+#define BMI270_INTERNAL_STATUS_AXES_REMAP_ERR_MSK BIT(5)
+#define BMI270_INTERNAL_STATUS_ODR_50HZ_ERR_MSK BIT(6)
+
+#define BMI270_ACC_CONF_REG 0x40
+#define BMI270_ACC_CONF_ODR_MSK GENMASK(3, 0)
+#define BMI270_ACC_CONF_ODR_100HZ 0x08
+#define BMI270_ACC_CONF_BWP_MSK GENMASK(6, 4)
+#define BMI270_ACC_CONF_BWP_NORMAL_MODE 0x02
+#define BMI270_ACC_CONF_FILTER_PERF_MSK BIT(7)
+
+#define BMI270_ACC_CONF_RANGE_REG 0x41
+#define BMI270_ACC_CONF_RANGE_MSK GENMASK(1, 0)
+
+#define BMI270_GYR_CONF_REG 0x42
+#define BMI270_GYR_CONF_ODR_MSK GENMASK(3, 0)
+#define BMI270_GYR_CONF_ODR_200HZ 0x09
+#define BMI270_GYR_CONF_BWP_MSK GENMASK(5, 4)
+#define BMI270_GYR_CONF_BWP_NORMAL_MODE 0x02
+#define BMI270_GYR_CONF_NOISE_PERF_MSK BIT(6)
+#define BMI270_GYR_CONF_FILTER_PERF_MSK BIT(7)
+
+#define BMI270_GYR_CONF_RANGE_REG 0x43
+#define BMI270_GYR_CONF_RANGE_MSK GENMASK(2, 0)
+
+#define BMI270_INIT_CTRL_REG 0x59
+#define BMI270_INIT_CTRL_LOAD_DONE_MSK BIT(0)
+
+#define BMI270_INIT_DATA_REG 0x5e
+
+#define BMI270_PWR_CONF_REG 0x7c
+#define BMI270_PWR_CONF_ADV_PWR_SAVE_MSK BIT(0)
+#define BMI270_PWR_CONF_FIFO_WKUP_MSK BIT(1)
+#define BMI270_PWR_CONF_FUP_EN_MSK BIT(2)
+
+#define BMI270_PWR_CTRL_REG 0x7d
+#define BMI270_PWR_CTRL_AUX_EN_MSK BIT(0)
+#define BMI270_PWR_CTRL_GYR_EN_MSK BIT(1)
+#define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2)
+#define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3)
+
+#define BMI260_INIT_DATA_FILE "bmi260-init-data.fw"
+#define BMI270_INIT_DATA_FILE "bmi270-init-data.fw"
+
+enum bmi270_scan {
+ BMI270_SCAN_ACCEL_X,
+ BMI270_SCAN_ACCEL_Y,
+ BMI270_SCAN_ACCEL_Z,
+ BMI270_SCAN_GYRO_X,
+ BMI270_SCAN_GYRO_Y,
+ BMI270_SCAN_GYRO_Z,
+ BMI270_SCAN_TIMESTAMP,
+};
+
+static const unsigned long bmi270_avail_scan_masks[] = {
+ (BIT(BMI270_SCAN_ACCEL_X) |
+ BIT(BMI270_SCAN_ACCEL_Y) |
+ BIT(BMI270_SCAN_ACCEL_Z) |
+ BIT(BMI270_SCAN_GYRO_X) |
+ BIT(BMI270_SCAN_GYRO_Y) |
+ BIT(BMI270_SCAN_GYRO_Z)),
+ 0
+};
+
+const struct bmi270_chip_info bmi260_chip_info = {
+ .name = "bmi260",
+ .chip_id = BMI260_CHIP_ID_VAL,
+ .fw_name = BMI260_INIT_DATA_FILE,
+};
+EXPORT_SYMBOL_NS_GPL(bmi260_chip_info, IIO_BMI270);
+
+const struct bmi270_chip_info bmi270_chip_info = {
+ .name = "bmi270",
+ .chip_id = BMI270_CHIP_ID_VAL,
+ .fw_name = BMI270_INIT_DATA_FILE,
+};
+EXPORT_SYMBOL_NS_GPL(bmi270_chip_info, IIO_BMI270);
+
+enum bmi270_sensor_type {
+ BMI270_ACCEL = 0,
+ BMI270_GYRO,
+};
+
+struct bmi270_scale {
+ int scale;
+ int uscale;
+};
+
+struct bmi270_odr {
+ int odr;
+ int uodr;
+};
+
+static const struct bmi270_scale bmi270_accel_scale[] = {
+ { 0, 598 },
+ { 0, 1197 },
+ { 0, 2394 },
+ { 0, 4788 },
+};
+
+static const struct bmi270_scale bmi270_gyro_scale[] = {
+ { 0, 1065 },
+ { 0, 532 },
+ { 0, 266 },
+ { 0, 133 },
+ { 0, 66 },
+};
+
+struct bmi270_scale_item {
+ const struct bmi270_scale *tbl;
+ int num;
+};
+
+static const struct bmi270_scale_item bmi270_scale_table[] = {
+ [BMI270_ACCEL] = {
+ .tbl = bmi270_accel_scale,
+ .num = ARRAY_SIZE(bmi270_accel_scale),
+ },
+ [BMI270_GYRO] = {
+ .tbl = bmi270_gyro_scale,
+ .num = ARRAY_SIZE(bmi270_gyro_scale),
+ },
+};
+
+static const struct bmi270_odr bmi270_accel_odr[] = {
+ { 0, 781250 },
+ { 1, 562500 },
+ { 3, 125000 },
+ { 6, 250000 },
+ { 12, 500000 },
+ { 25, 0 },
+ { 50, 0 },
+ { 100, 0 },
+ { 200, 0 },
+ { 400, 0 },
+ { 800, 0 },
+ { 1600, 0 },
+};
+
+static const u8 bmi270_accel_odr_vals[] = {
+ 0x01,
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+};
+
+static const struct bmi270_odr bmi270_gyro_odr[] = {
+ { 25, 0 },
+ { 50, 0 },
+ { 100, 0 },
+ { 200, 0 },
+ { 400, 0 },
+ { 800, 0 },
+ { 1600, 0 },
+ { 3200, 0 },
+};
+
+static const u8 bmi270_gyro_odr_vals[] = {
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+ 0x0D,
+};
+
+struct bmi270_odr_item {
+ const struct bmi270_odr *tbl;
+ const u8 *vals;
+ int num;
+};
+
+static const struct bmi270_odr_item bmi270_odr_table[] = {
+ [BMI270_ACCEL] = {
+ .tbl = bmi270_accel_odr,
+ .vals = bmi270_accel_odr_vals,
+ .num = ARRAY_SIZE(bmi270_accel_odr),
+ },
+ [BMI270_GYRO] = {
+ .tbl = bmi270_gyro_odr,
+ .vals = bmi270_gyro_odr_vals,
+ .num = ARRAY_SIZE(bmi270_gyro_odr),
+ },
+};
+
+static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale)
+{
+ int i;
+ int reg, mask;
+ struct bmi270_scale_item bmi270_scale_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACC_CONF_RANGE_REG;
+ mask = BMI270_ACC_CONF_RANGE_MSK;
+ bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_GYR_CONF_RANGE_REG;
+ mask = BMI270_GYR_CONF_RANGE_MSK;
+ bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_scale_item.num; i++) {
+ if (bmi270_scale_item.tbl[i].uscale != uscale)
+ continue;
+
+ return regmap_update_bits(data->regmap, reg, mask, i);
+ }
+
+ return -EINVAL;
+}
+
+static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
+ int *uscale)
+{
+ int ret;
+ unsigned int val;
+ struct bmi270_scale_item bmi270_scale_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ ret = regmap_read(bmi270_device->regmap,
+ BMI270_ACC_CONF_RANGE_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_ACC_CONF_RANGE_MSK, val);
+ bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ ret = regmap_read(bmi270_device->regmap,
+ BMI270_GYR_CONF_RANGE_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_GYR_CONF_RANGE_MSK, val);
+ bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (val >= bmi270_scale_item.num)
+ return -EINVAL;
+
+ *uscale = bmi270_scale_item.tbl[val].uscale;
+ return 0;
+}
+
+static int bmi270_set_odr(struct bmi270_data *data, int chan_type, int odr,
+ int uodr)
+{
+ int i;
+ int reg, mask;
+ struct bmi270_odr_item bmi270_odr_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACC_CONF_REG;
+ mask = BMI270_ACC_CONF_ODR_MSK;
+ bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_GYR_CONF_REG;
+ mask = BMI270_GYR_CONF_ODR_MSK;
+ bmi270_odr_item = bmi270_odr_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_odr_item.num; i++) {
+ if (bmi270_odr_item.tbl[i].odr != odr ||
+ bmi270_odr_item.tbl[i].uodr != uodr)
+ continue;
+
+ return regmap_update_bits(data->regmap, reg, mask,
+ bmi270_odr_item.vals[i]);
+ }
+
+ return -EINVAL;
+}
+
+static int bmi270_get_odr(struct bmi270_data *data, int chan_type, int *odr,
+ int *uodr)
+{
+ int i, val, ret;
+ struct bmi270_odr_item bmi270_odr_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ ret = regmap_read(data->regmap, BMI270_ACC_CONF_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_ACC_CONF_ODR_MSK, val);
+ bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ ret = regmap_read(data->regmap, BMI270_GYR_CONF_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_GYR_CONF_ODR_MSK, val);
+ bmi270_odr_item = bmi270_odr_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_odr_item.num; i++) {
+ if (val != bmi270_odr_item.vals[i])
+ continue;
+
+ *odr = bmi270_odr_item.tbl[i].odr;
+ *uodr = bmi270_odr_item.tbl[i].uodr;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t bmi270_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bmi270_data *bmi270_device = iio_priv(indio_dev);
+ int ret;
+
+ ret = regmap_bulk_read(bmi270_device->regmap, BMI270_ACCEL_X_REG,
+ &bmi270_device->data.channels,
+ sizeof(bmi270_device->data.channels));
+
+ if (ret)
+ goto done;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &bmi270_device->data,
+ pf->timestamp);
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int bmi270_get_data(struct bmi270_data *bmi270_device,
+ int chan_type, int axis, int *val)
+{
+ __le16 sample;
+ int reg;
+ int ret;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACCEL_X_REG + (axis - IIO_MOD_X) * 2;
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_ANG_VEL_X_REG + (axis - IIO_MOD_X) * 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_bulk_read(bmi270_device->regmap, reg, &sample, sizeof(sample));
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(le16_to_cpu(sample), 15);
+
+ return 0;
+}
+
+static int bmi270_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ struct bmi270_data *bmi270_device = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = bmi270_get_data(bmi270_device, chan->type, chan->channel2, val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ ret = bmi270_get_scale(bmi270_device, chan->type, val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = bmi270_get_odr(bmi270_device, chan->type, val, val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bmi270_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct bmi270_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return bmi270_set_scale(data, chan->type, val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return bmi270_set_odr(data, chan->type, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bmi270_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *vals = (const int *)bmi270_gyro_scale;
+ *length = ARRAY_SIZE(bmi270_gyro_scale) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_ACCEL:
+ *vals = (const int *)bmi270_accel_scale;
+ *length = ARRAY_SIZE(bmi270_accel_scale) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *vals = (const int *)bmi270_gyro_odr;
+ *length = ARRAY_SIZE(bmi270_gyro_odr) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_ACCEL:
+ *vals = (const int *)bmi270_accel_odr;
+ *length = ARRAY_SIZE(bmi270_accel_odr) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info bmi270_info = {
+ .read_raw = bmi270_read_raw,
+ .write_raw = bmi270_write_raw,
+ .read_avail = bmi270_read_avail,
+};
+
+#define BMI270_ACCEL_CHANNEL(_axis) { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = BMI270_SCAN_ACCEL_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+#define BMI270_ANG_VEL_CHANNEL(_axis) { \
+ .type = IIO_ANGL_VEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = BMI270_SCAN_GYRO_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+static const struct iio_chan_spec bmi270_channels[] = {
+ BMI270_ACCEL_CHANNEL(X),
+ BMI270_ACCEL_CHANNEL(Y),
+ BMI270_ACCEL_CHANNEL(Z),
+ BMI270_ANG_VEL_CHANNEL(X),
+ BMI270_ANG_VEL_CHANNEL(Y),
+ BMI270_ANG_VEL_CHANNEL(Z),
+ IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
+};
+
+static int bmi270_validate_chip_id(struct bmi270_data *bmi270_device)
+{
+ int chip_id;
+ int ret;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_read(regmap, BMI270_CHIP_ID_REG, &chip_id);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read chip id");
+
+ /*
+ * Some manufacturers use "BMI0160" for both the BMI160 and
+ * BMI260. If the device is actually a BMI160, the bmi160
+ * driver should handle it and this driver should not.
+ */
+ if (chip_id == BMI160_CHIP_ID_VAL)
+ return -ENODEV;
+
+ if (chip_id != bmi270_device->chip_info->chip_id)
+ dev_info(dev, "Unexpected chip id 0x%x", chip_id);
+
+ if (chip_id == bmi260_chip_info.chip_id)
+ bmi270_device->chip_info = &bmi260_chip_info;
+ else if (chip_id == bmi270_chip_info.chip_id)
+ bmi270_device->chip_info = &bmi270_chip_info;
+
+ return 0;
+}
+
+static int bmi270_write_calibration_data(struct bmi270_data *bmi270_device)
+{
+ int ret;
+ int status = 0;
+ const struct firmware *init_data;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_clear_bits(regmap, BMI270_PWR_CONF_REG,
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to write power configuration");
+
+ /*
+ * After disabling advanced power save, all registers are accessible
+ * after a 450us delay. This delay is specified in table A of the
+ * datasheet.
+ */
+ usleep_range(450, 1000);
+
+ ret = regmap_clear_bits(regmap, BMI270_INIT_CTRL_REG,
+ BMI270_INIT_CTRL_LOAD_DONE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to prepare device to load init data");
+
+ ret = request_firmware(&init_data,
+ bmi270_device->chip_info->fw_name, dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to load init data file");
+
+ ret = regmap_bulk_write(regmap, BMI270_INIT_DATA_REG,
+ init_data->data, init_data->size);
+ release_firmware(init_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to write init data");
+
+ ret = regmap_set_bits(regmap, BMI270_INIT_CTRL_REG,
+ BMI270_INIT_CTRL_LOAD_DONE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to stop device initialization");
+
+ /*
+ * Wait at least 140ms for the device to complete configuration.
+ * This delay is specified in table C of the datasheet.
+ */
+ usleep_range(140000, 160000);
+
+ ret = regmap_read(regmap, BMI270_INTERNAL_STATUS_REG, &status);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read internal status");
+
+ if (status != BMI270_INTERNAL_STATUS_MSG_INIT_OK)
+ return dev_err_probe(dev, -ENODEV, "Device failed to initialize");
+
+ return 0;
+}
+
+static int bmi270_configure_imu(struct bmi270_data *bmi270_device)
+{
+ int ret;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_set_bits(regmap, BMI270_PWR_CTRL_REG,
+ BMI270_PWR_CTRL_AUX_EN_MSK |
+ BMI270_PWR_CTRL_GYR_EN_MSK |
+ BMI270_PWR_CTRL_ACCEL_EN_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable accelerometer and gyroscope");
+
+ ret = regmap_set_bits(regmap, BMI270_ACC_CONF_REG,
+ FIELD_PREP(BMI270_ACC_CONF_ODR_MSK,
+ BMI270_ACC_CONF_ODR_100HZ) |
+ FIELD_PREP(BMI270_ACC_CONF_BWP_MSK,
+ BMI270_ACC_CONF_BWP_NORMAL_MODE) |
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to configure accelerometer");
+
+ ret = regmap_set_bits(regmap, BMI270_GYR_CONF_REG,
+ FIELD_PREP(BMI270_GYR_CONF_ODR_MSK,
+ BMI270_GYR_CONF_ODR_200HZ) |
+ FIELD_PREP(BMI270_GYR_CONF_BWP_MSK,
+ BMI270_GYR_CONF_BWP_NORMAL_MODE) |
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to configure gyroscope");
+
+ /* Enable FIFO_WKUP, Disable ADV_PWR_SAVE and FUP_EN */
+ ret = regmap_write(regmap, BMI270_PWR_CONF_REG,
+ BMI270_PWR_CONF_FIFO_WKUP_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set power configuration");
+
+ return 0;
+}
+
+static int bmi270_chip_init(struct bmi270_data *bmi270_device)
+{
+ int ret;
+
+ ret = bmi270_validate_chip_id(bmi270_device);
+ if (ret)
+ return ret;
+
+ ret = bmi270_write_calibration_data(bmi270_device);
+ if (ret)
+ return ret;
+
+ return bmi270_configure_imu(bmi270_device);
+}
+
+int bmi270_core_probe(struct device *dev, struct regmap *regmap,
+ const struct bmi270_chip_info *chip_info)
+{
+ int ret;
+ struct bmi270_data *bmi270_device;
+ struct iio_dev *indio_dev;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*bmi270_device));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ bmi270_device = iio_priv(indio_dev);
+ bmi270_device->dev = dev;
+ bmi270_device->regmap = regmap;
+ bmi270_device->chip_info = chip_info;
+
+ ret = bmi270_chip_init(bmi270_device);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = bmi270_channels;
+ indio_dev->num_channels = ARRAY_SIZE(bmi270_channels);
+ indio_dev->name = chip_info->name;
+ indio_dev->available_scan_masks = bmi270_avail_scan_masks;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &bmi270_info;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ bmi270_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+EXPORT_SYMBOL_NS_GPL(bmi270_core_probe, IIO_BMI270);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/bmi270/bmi270_i2c.c b/drivers/iio/imu/bmi270/bmi270_i2c.c
new file mode 100644
index 000000000000..6bd82e4362ab
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_i2c.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+
+#include "bmi270.h"
+
+static const struct regmap_config bmi270_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int bmi270_i2c_probe(struct i2c_client *client)
+{
+ struct regmap *regmap;
+ struct device *dev = &client->dev;
+ const struct bmi270_chip_info *chip_info;
+
+ chip_info = i2c_get_match_data(client);
+ if (!chip_info)
+ return -ENODEV;
+
+ regmap = devm_regmap_init_i2c(client, &bmi270_i2c_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init i2c regmap");
+
+ return bmi270_core_probe(dev, regmap, chip_info);
+}
+
+static const struct i2c_device_id bmi270_i2c_id[] = {
+ { "bmi260", (kernel_ulong_t)&bmi260_chip_info },
+ { "bmi270", (kernel_ulong_t)&bmi270_chip_info },
+ { }
+};
+
+static const struct acpi_device_id bmi270_acpi_match[] = {
+ /* GPD Win Mini, Aya Neo AIR Pro, OXP Mini Pro, etc. */
+ { "BMI0160", (kernel_ulong_t)&bmi260_chip_info },
+ { }
+};
+
+static const struct of_device_id bmi270_of_match[] = {
+ { .compatible = "bosch,bmi260", .data = &bmi260_chip_info },
+ { .compatible = "bosch,bmi270", .data = &bmi270_chip_info },
+ { }
+};
+
+static struct i2c_driver bmi270_i2c_driver = {
+ .driver = {
+ .name = "bmi270_i2c",
+ .acpi_match_table = bmi270_acpi_match,
+ .of_match_table = bmi270_of_match,
+ },
+ .probe = bmi270_i2c_probe,
+ .id_table = bmi270_i2c_id,
+};
+module_i2c_driver(bmi270_i2c_driver);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_BMI270);
diff --git a/drivers/iio/imu/bmi270/bmi270_spi.c b/drivers/iio/imu/bmi270/bmi270_spi.c
new file mode 100644
index 000000000000..30b6d13a329c
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_spi.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/iio/iio.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "bmi270.h"
+
+/*
+ * The following two functions are taken from the BMI323 spi driver code.
+ * In section 6.4 of the BMI270 data it specifies that after a read
+ * operation the first data byte from the device is a dummy byte
+ */
+static int bmi270_regmap_spi_read(void *spi, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ return spi_write_then_read(spi, reg_buf, reg_size, val_buf, val_size);
+}
+
+static int bmi270_regmap_spi_write(void *spi, const void *data,
+ size_t count)
+{
+ u8 *data_buff = (u8 *)data;
+
+ /*
+ * Remove the extra pad byte since its only needed for the read
+ * operation
+ */
+ data_buff[1] = data_buff[0];
+ return spi_write_then_read(spi, data_buff + 1, count - 1, NULL, 0);
+}
+
+static const struct regmap_bus bmi270_regmap_bus = {
+ .read = bmi270_regmap_spi_read,
+ .write = bmi270_regmap_spi_write,
+};
+
+static const struct regmap_config bmi270_spi_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .pad_bits = 8,
+ .read_flag_mask = BIT(7),
+};
+
+static int bmi270_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+ struct device *dev = &spi->dev;
+ const struct bmi270_chip_info *chip_info;
+
+ chip_info = spi_get_device_match_data(spi);
+ if (!chip_info)
+ return -ENODEV;
+
+ regmap = devm_regmap_init(dev, &bmi270_regmap_bus, dev,
+ &bmi270_spi_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init i2c regmap");
+
+ return bmi270_core_probe(dev, regmap, chip_info);
+}
+
+static const struct spi_device_id bmi270_spi_id[] = {
+ { "bmi260", (kernel_ulong_t)&bmi260_chip_info },
+ { "bmi270", (kernel_ulong_t)&bmi270_chip_info },
+ { }
+};
+
+static const struct of_device_id bmi270_of_match[] = {
+ { .compatible = "bosch,bmi260", .data = &bmi260_chip_info },
+ { .compatible = "bosch,bmi270", .data = &bmi270_chip_info },
+ { }
+};
+
+static struct spi_driver bmi270_spi_driver = {
+ .driver = {
+ .name = "bmi270",
+ .of_match_table = bmi270_of_match,
+ },
+ .probe = bmi270_spi_probe,
+ .id_table = bmi270_spi_id,
+};
+module_spi_driver(bmi270_spi_driver);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_BMI270);
diff --git a/drivers/iio/imu/bmi323/bmi323.h b/drivers/iio/imu/bmi323/bmi323.h
index 209bccb1f335..b4cfe92600a4 100644
--- a/drivers/iio/imu/bmi323/bmi323.h
+++ b/drivers/iio/imu/bmi323/bmi323.h
@@ -141,7 +141,6 @@
#define BMI323_STEP_SC1_REG 0x10
#define BMI323_STEP_SC1_WTRMRK_MSK GENMASK(9, 0)
#define BMI323_STEP_SC1_RST_CNT_MSK BIT(10)
-#define BMI323_STEP_SC1_REG 0x10
#define BMI323_STEP_LEN 2
/* Tap gesture config registers */
diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
index e1f3b0d778be..161bb1d2e761 100644
--- a/drivers/iio/imu/bmi323/bmi323_core.c
+++ b/drivers/iio/imu/bmi323/bmi323_core.c
@@ -467,7 +467,7 @@ static int bmi323_feature_engine_events(struct bmi323_data *data,
BMI323_FEAT_IO_STATUS_MSK);
}
-static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)
+static int bmi323_step_wtrmrk_en(struct bmi323_data *data, bool state)
{
enum bmi323_irq_pin step_irq;
int ret;
@@ -484,7 +484,7 @@ static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)
ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,
BMI323_STEP_SC1_WTRMRK_MSK,
FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK,
- state ? 1 : 0));
+ state));
if (ret)
return ret;
@@ -506,7 +506,7 @@ static int bmi323_motion_config_reg(enum iio_event_direction dir)
}
static int bmi323_motion_event_en(struct bmi323_data *data,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0;
int config, ret, msk, raw, field_value;
@@ -570,7 +570,7 @@ static int bmi323_motion_event_en(struct bmi323_data *data,
}
static int bmi323_tap_event_en(struct bmi323_data *data,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
enum bmi323_irq_pin tap_irq;
int ret, tap_enabled;
@@ -785,7 +785,7 @@ static const struct attribute_group bmi323_event_attribute_group = {
static int bmi323_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bmi323_data *data = iio_priv(indio_dev);
@@ -1881,7 +1881,6 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
struct fwnode_handle *fwnode;
enum bmi323_irq_pin irq_pin;
int ret, irq, irq_type;
- struct irq_data *desc;
fwnode = dev_fwnode(data->dev);
if (!fwnode)
@@ -1898,12 +1897,7 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
irq_pin = BMI323_IRQ_INT2;
}
- desc = irq_get_irq_data(irq);
- if (!desc)
- return dev_err_probe(data->dev, -EINVAL,
- "Could not find IRQ %d\n", irq);
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(irq);
switch (irq_type) {
case IRQF_TRIGGER_RISING:
latch = false;
diff --git a/drivers/iio/imu/fxos8700_core.c b/drivers/iio/imu/fxos8700_core.c
index 6d189c4b9ff9..281ebfd9c15a 100644
--- a/drivers/iio/imu/fxos8700_core.c
+++ b/drivers/iio/imu/fxos8700_core.c
@@ -8,7 +8,6 @@
*/
#include <linux/module.h>
#include <linux/regmap.h>
-#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 56ac19814250..7968aa27f9fd 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -200,7 +200,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
{
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
- struct inv_sensors_timestamp *ts = &accel_st->ts;
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_temp = 0;
@@ -229,7 +228,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
}
/* update data FIFO write */
- inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
out_unlock:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index c3924cc6190e..93b5d7a3339c 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -673,7 +673,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
{
struct device *dev = regmap_get_device(regmap);
struct inv_icm42600_state *st;
- struct irq_data *irq_desc;
int irq_type;
bool open_drain;
int ret;
@@ -683,14 +682,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
return -ENODEV;
}
- /* get irq properties, set trigger falling by default */
- irq_desc = irq_get_irq_data(irq);
- if (!irq_desc) {
- dev_err(dev, "could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(irq_desc);
+ irq_type = irq_get_trigger_type(irq);
if (!irq_type)
irq_type = IRQF_TRIGGER_FALLING;
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index 938af5b640b0..c6bb68bf5e14 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -99,8 +99,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
- struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
- struct inv_sensors_timestamp *ts = &gyro_st->ts;
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_gyro = 0;
@@ -128,7 +126,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
}
/* update data FIFO write */
- inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
out_unlock:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
index ebb31b385881..19563c58b4b1 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -71,6 +71,22 @@ static int inv_icm42600_probe(struct i2c_client *client)
inv_icm42600_i2c_bus_setup);
}
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct i2c_device_id inv_icm42600_id[] = {
+ { "icm42600", INV_CHIP_ICM42600 },
+ { "icm42602", INV_CHIP_ICM42602 },
+ { "icm42605", INV_CHIP_ICM42605 },
+ { "icm42686", INV_CHIP_ICM42686 },
+ { "icm42622", INV_CHIP_ICM42622 },
+ { "icm42688", INV_CHIP_ICM42688 },
+ { "icm42631", INV_CHIP_ICM42631 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, inv_icm42600_id);
+
static const struct of_device_id inv_icm42600_of_matches[] = {
{
.compatible = "invensense,icm42600",
@@ -104,6 +120,7 @@ static struct i2c_driver inv_icm42600_driver = {
.of_match_table = inv_icm42600_of_matches,
.pm = pm_ptr(&inv_icm42600_pm_ops),
},
+ .id_table = inv_icm42600_id,
.probe = inv_icm42600_probe,
};
module_i2c_driver(inv_icm42600_driver);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
index eae5ff7a3cc1..3b6d05fce65d 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -67,6 +67,22 @@ static int inv_icm42600_probe(struct spi_device *spi)
inv_icm42600_spi_bus_setup);
}
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct spi_device_id inv_icm42600_id[] = {
+ { "icm42600", INV_CHIP_ICM42600 },
+ { "icm42602", INV_CHIP_ICM42602 },
+ { "icm42605", INV_CHIP_ICM42605 },
+ { "icm42686", INV_CHIP_ICM42686 },
+ { "icm42622", INV_CHIP_ICM42622 },
+ { "icm42688", INV_CHIP_ICM42688 },
+ { "icm42631", INV_CHIP_ICM42631 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, inv_icm42600_id);
+
static const struct of_device_id inv_icm42600_of_matches[] = {
{
.compatible = "invensense,icm42600",
@@ -100,6 +116,7 @@ static struct spi_driver inv_icm42600_driver = {
.of_match_table = inv_icm42600_of_matches,
.pm = pm_ptr(&inv_icm42600_pm_ops),
},
+ .id_table = inv_icm42600_id,
.probe = inv_icm42600_probe,
};
module_spi_driver(inv_icm42600_driver);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index f7bce428d9eb..373e59f6d91a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -10,6 +10,8 @@
#include <linux/i2c.h>
#include <linux/dmi.h>
#include <linux/acpi.h>
+#include <linux/wordpart.h>
+
#include "inv_mpu_iio.h"
enum inv_mpu_product_name {
@@ -102,14 +104,11 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
unsigned short *secondary_addr)
{
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
- const struct acpi_device_id *id;
u32 i2c_addr = 0;
LIST_HEAD(resources);
int ret;
- id = acpi_match_device(client->dev.driver->acpi_match_table,
- &client->dev);
- if (!id)
+ if (!is_acpi_device_node(dev_fwnode(&client->dev)))
return -ENODEV;
ret = acpi_dev_get_resources(adev, &resources,
@@ -118,8 +117,8 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
return ret;
acpi_dev_free_resource_list(&resources);
- *primary_addr = i2c_addr & 0x0000ffff;
- *secondary_addr = (i2c_addr & 0xffff0000) >> 16;
+ *primary_addr = lower_16_bits(i2c_addr);
+ *secondary_addr = upper_16_bits(i2c_addr);
return 0;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 14d95f34e981..40271352b02c 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -286,6 +286,24 @@ static const struct inv_mpu6050_hw hw_info[] = {
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
.startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
+ {
+ .whoami = INV_IAM20680HP_WHOAMI_VALUE,
+ .name = "IAM20680HP",
+ .reg = &reg_set_6500,
+ .config = &chip_config_6500,
+ .fifo_size = 4 * 1024,
+ .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
+ },
+ {
+ .whoami = INV_IAM20680HT_WHOAMI_VALUE,
+ .name = "IAM20680HT",
+ .reg = &reg_set_6500,
+ .config = &chip_config_6500,
+ .fifo_size = 4 * 1024,
+ .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
+ },
};
static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep,
@@ -510,6 +528,8 @@ static int inv_mpu6050_set_accel_lpf_regs(struct inv_mpu6050_state *st,
return 0;
case INV_ICM20689:
case INV_ICM20690:
+ case INV_IAM20680HT:
+ case INV_IAM20680HP:
/* set FIFO size to maximum value */
val |= INV_ICM20689_BITS_FIFO_SIZE_MAX;
break;
@@ -1153,24 +1173,21 @@ static int inv_mpu6050_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct inv_mpu6050_state *st = iio_priv(indio_dev);
- int enable;
/* support only WoM (accel roc rising) event */
if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC ||
dir != IIO_EV_DIR_RISING)
return -EINVAL;
- enable = !!state;
-
guard(mutex)(&st->lock);
- if (st->chip_config.wom_en == enable)
+ if (st->chip_config.wom_en == state)
return 0;
- return inv_mpu6050_enable_wom(st, enable);
+ return inv_mpu6050_enable_wom(st, state);
}
static int inv_mpu6050_read_event_value(struct iio_dev *indio_dev,
@@ -1859,7 +1876,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
struct inv_mpu6050_platform_data *pdata;
struct device *dev = regmap_get_device(regmap);
int result;
- struct irq_data *desc;
int irq_type;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
@@ -1893,13 +1909,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
}
if (irq > 0) {
- desc = irq_get_irq_data(irq);
- if (!desc) {
- dev_err(dev, "Could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(irq);
if (!irq_type)
irq_type = IRQF_TRIGGER_RISING;
} else {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 0e03137fb3d4..7a5926ba6b97 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -188,6 +188,8 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
+ {"iam20680hp", INV_IAM20680HP},
+ {"iam20680ht", INV_IAM20680HT},
{}
};
@@ -254,6 +256,14 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,iam20680",
.data = (void *)INV_IAM20680
},
+ {
+ .compatible = "invensense,iam20680hp",
+ .data = (void *)INV_IAM20680HP
+ },
+ {
+ .compatible = "invensense,iam20680ht",
+ .data = (void *)INV_IAM20680HT
+ },
{ }
};
MODULE_DEVICE_TABLE(of, inv_of_match);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index e1c0c5146876..a6862cf42639 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -85,6 +85,8 @@ enum inv_devices {
INV_ICM20602,
INV_ICM20690,
INV_IAM20680,
+ INV_IAM20680HP,
+ INV_IAM20680HT,
INV_NUM_PARTS
};
@@ -424,6 +426,8 @@ struct inv_mpu6050_state {
#define INV_ICM20602_WHOAMI_VALUE 0x12
#define INV_ICM20690_WHOAMI_VALUE 0x20
#define INV_IAM20680_WHOAMI_VALUE 0xA9
+#define INV_IAM20680HP_WHOAMI_VALUE 0xF8
+#define INV_IAM20680HT_WHOAMI_VALUE 0xFA
/* scan element definition for generic MPU6xxx devices */
enum inv_mpu6050_scan {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
index 05451ca1580b..e6a291fcda95 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -80,6 +80,8 @@ static const struct spi_device_id inv_mpu_id[] = {
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
+ {"iam20680hp", INV_IAM20680HP},
+ {"iam20680ht", INV_IAM20680HT},
{}
};
@@ -142,6 +144,14 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,iam20680",
.data = (void *)INV_IAM20680
},
+ {
+ .compatible = "invensense,iam20680hp",
+ .data = (void *)INV_IAM20680HP
+ },
+ {
+ .compatible = "invensense,iam20680ht",
+ .data = (void *)INV_IAM20680HT
+ },
{ }
};
MODULE_DEVICE_TABLE(of, inv_of_match);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index 3bfeabab0ec4..5b1088cc3704 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -112,7 +112,6 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable)
if (enable) {
/* reset timestamping */
inv_sensors_timestamp_reset(&st->timestamp);
- inv_sensors_timestamp_apply_odr(&st->timestamp, 0, 0, 0);
/* reset FIFO */
d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST;
ret = regmap_write(st->map, st->reg->user_ctrl, d);
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index c61c012e25bb..324c38764656 100644
--- a/drivers/iio/imu/kmx61.c
+++ b/drivers/iio/imu/kmx61.c
@@ -7,12 +7,13 @@
* IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F).
*/
-#include <linux/module.h>
#include <linux/i2c.h>
-#include <linux/acpi.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -941,7 +942,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct kmx61_data *data = kmx61_get_data(indio_dev);
int ret = 0;
@@ -1217,16 +1218,6 @@ err:
return IRQ_HANDLED;
}
-static const char *kmx61_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
- return dev_name(dev);
-}
-
static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
const struct iio_info *info,
const struct iio_chan_spec *chan,
@@ -1293,8 +1284,6 @@ static int kmx61_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = kmx61_match_acpi_device(&client->dev);
else
return -ENODEV;
@@ -1496,13 +1485,6 @@ static const struct dev_pm_ops kmx61_pm_ops = {
RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL)
};
-static const struct acpi_device_id kmx61_acpi_match[] = {
- {"KMX61021", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match);
-
static const struct i2c_device_id kmx61_id[] = {
{ "kmx611021" },
{}
@@ -1513,7 +1495,6 @@ MODULE_DEVICE_TABLE(i2c, kmx61_id);
static struct i2c_driver kmx61_driver = {
.driver = {
.name = KMX61_DRV_NAME,
- .acpi_match_table = kmx61_acpi_match,
.pm = pm_ptr(&kmx61_pm_ops),
},
.probe = kmx61_probe,
diff --git a/drivers/iio/imu/smi240.c b/drivers/iio/imu/smi240.c
new file mode 100644
index 000000000000..4492c4d013bd
--- /dev/null
+++ b/drivers/iio/imu/smi240.c
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Copyright (c) 2024 Robert Bosch GmbH.
+ */
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define SMI240_CHIP_ID 0x0024
+
+#define SMI240_SOFT_CONFIG_EOC_MASK BIT(0)
+#define SMI240_SOFT_CONFIG_GYR_BW_MASK BIT(1)
+#define SMI240_SOFT_CONFIG_ACC_BW_MASK BIT(2)
+#define SMI240_SOFT_CONFIG_BITE_AUTO_MASK BIT(3)
+#define SMI240_SOFT_CONFIG_BITE_REP_MASK GENMASK(6, 4)
+
+#define SMI240_CHIP_ID_REG 0x00
+#define SMI240_SOFT_CONFIG_REG 0x0A
+#define SMI240_TEMP_CUR_REG 0x10
+#define SMI240_ACCEL_X_CUR_REG 0x11
+#define SMI240_GYRO_X_CUR_REG 0x14
+#define SMI240_DATA_CAP_FIRST_REG 0x17
+#define SMI240_CMD_REG 0x2F
+
+#define SMI240_SOFT_RESET_CMD 0xB6
+
+#define SMI240_BITE_SEQUENCE_DELAY_US 140000
+#define SMI240_FILTER_FLUSH_DELAY_US 60000
+#define SMI240_DIGITAL_STARTUP_DELAY_US 120000
+#define SMI240_MECH_STARTUP_DELAY_US 100000
+
+#define SMI240_BUS_ID 0x00
+#define SMI240_CRC_INIT 0x05
+#define SMI240_CRC_POLY 0x0B
+#define SMI240_CRC_MASK GENMASK(2, 0)
+
+#define SMI240_READ_SD_BIT_MASK BIT(31)
+#define SMI240_READ_DATA_MASK GENMASK(19, 4)
+#define SMI240_READ_CS_BIT_MASK BIT(3)
+
+#define SMI240_WRITE_BUS_ID_MASK GENMASK(31, 30)
+#define SMI240_WRITE_ADDR_MASK GENMASK(29, 22)
+#define SMI240_WRITE_BIT_MASK BIT(21)
+#define SMI240_WRITE_CAP_BIT_MASK BIT(20)
+#define SMI240_WRITE_DATA_MASK GENMASK(18, 3)
+
+/* T°C = (temp / 256) + 25 */
+#define SMI240_TEMP_OFFSET 6400 /* 25 * 256 */
+#define SMI240_TEMP_SCALE 3906250 /* (1 / 256) * 1e9 */
+
+#define SMI240_ACCEL_SCALE 500 /* (1 / 2000) * 1e6 */
+#define SMI240_GYRO_SCALE 10000 /* (1 / 100) * 1e6 */
+
+#define SMI240_LOW_BANDWIDTH_HZ 50
+#define SMI240_HIGH_BANDWIDTH_HZ 400
+
+#define SMI240_BUILT_IN_SELF_TEST_COUNT 3
+
+#define SMI240_DATA_CHANNEL(_type, _axis, _index) { \
+ .type = _type, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+#define SMI240_TEMP_CHANNEL(_index) { \
+ .type = IIO_TEMP, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_TEMP_OBJECT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+enum capture_mode { SMI240_CAPTURE_OFF = 0, SMI240_CAPTURE_ON = 1 };
+
+struct smi240_data {
+ struct regmap *regmap;
+ u16 accel_filter_freq;
+ u16 anglvel_filter_freq;
+ u8 built_in_self_test_count;
+ enum capture_mode capture;
+ /*
+ * Ensure natural alignment for timestamp if present.
+ * Channel size: 2 bytes.
+ * Max length needed: 2 * 3 channels + temp channel + 2 bytes padding + 8 byte ts.
+ * If fewer channels are enabled, less space may be needed, as
+ * long as the timestamp is still aligned to 8 bytes.
+ */
+ s16 buf[12] __aligned(8);
+
+ __be32 spi_buf __aligned(IIO_DMA_MINALIGN);
+};
+
+enum {
+ SMI240_TEMP_OBJECT,
+ SMI240_SCAN_ACCEL_X,
+ SMI240_SCAN_ACCEL_Y,
+ SMI240_SCAN_ACCEL_Z,
+ SMI240_SCAN_GYRO_X,
+ SMI240_SCAN_GYRO_Y,
+ SMI240_SCAN_GYRO_Z,
+ SMI240_SCAN_TIMESTAMP,
+};
+
+static const struct iio_chan_spec smi240_channels[] = {
+ SMI240_TEMP_CHANNEL(SMI240_TEMP_OBJECT),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, X, SMI240_SCAN_ACCEL_X),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, Y, SMI240_SCAN_ACCEL_Y),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, Z, SMI240_SCAN_ACCEL_Z),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, X, SMI240_SCAN_GYRO_X),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Y, SMI240_SCAN_GYRO_Y),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Z, SMI240_SCAN_GYRO_Z),
+ IIO_CHAN_SOFT_TIMESTAMP(SMI240_SCAN_TIMESTAMP),
+};
+
+static const int smi240_low_pass_freqs[] = { SMI240_LOW_BANDWIDTH_HZ,
+ SMI240_HIGH_BANDWIDTH_HZ };
+
+static u8 smi240_crc3(u32 data, u8 init, u8 poly)
+{
+ u8 crc = init;
+ u8 do_xor;
+ s8 i = 31;
+
+ do {
+ do_xor = crc & 0x04;
+ crc <<= 1;
+ crc |= 0x01 & (data >> i);
+ if (do_xor)
+ crc ^= poly;
+
+ crc &= SMI240_CRC_MASK;
+ } while (--i >= 0);
+
+ return crc;
+}
+
+static bool smi240_sensor_data_is_valid(u32 data)
+{
+ if (smi240_crc3(data, SMI240_CRC_INIT, SMI240_CRC_POLY) != 0)
+ return false;
+
+ if (FIELD_GET(SMI240_READ_SD_BIT_MASK, data) &
+ FIELD_GET(SMI240_READ_CS_BIT_MASK, data))
+ return false;
+
+ return true;
+}
+
+static int smi240_regmap_spi_read(void *context, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ int ret;
+ u32 request, response;
+ u16 *val = val_buf;
+ struct spi_device *spi = context;
+ struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
+ struct smi240_data *iio_priv_data = iio_priv(indio_dev);
+
+ if (reg_size != 1 || val_size != 2)
+ return -EINVAL;
+
+ request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
+ request |= FIELD_PREP(SMI240_WRITE_CAP_BIT_MASK, iio_priv_data->capture);
+ request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, *(u8 *)reg_buf);
+ request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
+
+ iio_priv_data->spi_buf = cpu_to_be32(request);
+
+ /*
+ * SMI240 module consists of a 32Bit Out Of Frame (OOF)
+ * SPI protocol, where the slave interface responds to
+ * the Master request in the next frame.
+ * CS signal must toggle (> 700 ns) between the frames.
+ */
+ ret = spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
+ if (ret)
+ return ret;
+
+ ret = spi_read(spi, &iio_priv_data->spi_buf, sizeof(response));
+ if (ret)
+ return ret;
+
+ response = be32_to_cpu(iio_priv_data->spi_buf);
+
+ if (!smi240_sensor_data_is_valid(response))
+ return -EIO;
+
+ *val = FIELD_GET(SMI240_READ_DATA_MASK, response);
+
+ return 0;
+}
+
+static int smi240_regmap_spi_write(void *context, const void *data,
+ size_t count)
+{
+ u8 reg_addr;
+ u16 reg_data;
+ u32 request;
+ const u8 *data_ptr = data;
+ struct spi_device *spi = context;
+ struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
+ struct smi240_data *iio_priv_data = iio_priv(indio_dev);
+
+ if (count < 2)
+ return -EINVAL;
+
+ reg_addr = data_ptr[0];
+ memcpy(&reg_data, &data_ptr[1], sizeof(reg_data));
+
+ request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
+ request |= FIELD_PREP(SMI240_WRITE_BIT_MASK, 1);
+ request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, reg_addr);
+ request |= FIELD_PREP(SMI240_WRITE_DATA_MASK, reg_data);
+ request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
+
+ iio_priv_data->spi_buf = cpu_to_be32(request);
+
+ return spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
+}
+
+static const struct regmap_bus smi240_regmap_bus = {
+ .read = smi240_regmap_spi_read,
+ .write = smi240_regmap_spi_write,
+};
+
+static const struct regmap_config smi240_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+};
+
+static int smi240_soft_reset(struct smi240_data *data)
+{
+ int ret;
+
+ ret = regmap_write(data->regmap, SMI240_CMD_REG, SMI240_SOFT_RESET_CMD);
+ if (ret)
+ return ret;
+ fsleep(SMI240_DIGITAL_STARTUP_DELAY_US);
+
+ return 0;
+}
+
+static int smi240_soft_config(struct smi240_data *data)
+{
+ int ret;
+ u8 acc_bw, gyr_bw;
+ u16 request;
+
+ switch (data->accel_filter_freq) {
+ case SMI240_LOW_BANDWIDTH_HZ:
+ acc_bw = 0x1;
+ break;
+ case SMI240_HIGH_BANDWIDTH_HZ:
+ acc_bw = 0x0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (data->anglvel_filter_freq) {
+ case SMI240_LOW_BANDWIDTH_HZ:
+ gyr_bw = 0x1;
+ break;
+ case SMI240_HIGH_BANDWIDTH_HZ:
+ gyr_bw = 0x0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ request = FIELD_PREP(SMI240_SOFT_CONFIG_EOC_MASK, 1);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_GYR_BW_MASK, gyr_bw);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_ACC_BW_MASK, acc_bw);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_AUTO_MASK, 1);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_REP_MASK,
+ data->built_in_self_test_count - 1);
+
+ ret = regmap_write(data->regmap, SMI240_SOFT_CONFIG_REG, request);
+ if (ret)
+ return ret;
+
+ fsleep(SMI240_MECH_STARTUP_DELAY_US +
+ data->built_in_self_test_count * SMI240_BITE_SEQUENCE_DELAY_US +
+ SMI240_FILTER_FLUSH_DELAY_US);
+
+ return 0;
+}
+
+static int smi240_get_low_pass_filter_freq(struct smi240_data *data,
+ int chan_type, int *val)
+{
+ switch (chan_type) {
+ case IIO_ACCEL:
+ *val = data->accel_filter_freq;
+ return 0;
+ case IIO_ANGL_VEL:
+ *val = data->anglvel_filter_freq;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_get_data(struct smi240_data *data, int chan_type, int axis,
+ int *val)
+{
+ u8 reg;
+ int ret, sample;
+
+ switch (chan_type) {
+ case IIO_TEMP:
+ reg = SMI240_TEMP_CUR_REG;
+ break;
+ case IIO_ACCEL:
+ reg = SMI240_ACCEL_X_CUR_REG + (axis - IIO_MOD_X);
+ break;
+ case IIO_ANGL_VEL:
+ reg = SMI240_GYRO_X_CUR_REG + (axis - IIO_MOD_X);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_read(data->regmap, reg, &sample);
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(sample, 15);
+
+ return 0;
+}
+
+static irqreturn_t smi240_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct smi240_data *data = iio_priv(indio_dev);
+ int base = SMI240_DATA_CAP_FIRST_REG, i = 0;
+ int ret, chan, sample;
+
+ data->capture = SMI240_CAPTURE_ON;
+
+ iio_for_each_active_channel(indio_dev, chan) {
+ ret = regmap_read(data->regmap, base + chan, &sample);
+ data->capture = SMI240_CAPTURE_OFF;
+ if (ret)
+ goto out;
+ data->buf[i++] = sample;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp);
+
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int smi240_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, const int **vals,
+ int *type, int *length, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ *vals = smi240_low_pass_freqs;
+ *length = ARRAY_SIZE(smi240_low_pass_freqs);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ int ret;
+ struct smi240_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ ret = smi240_get_data(data, chan->type, chan->channel2, val);
+ iio_device_release_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ ret = smi240_get_low_pass_filter_freq(data, chan->type, val);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = SMI240_TEMP_SCALE / GIGA;
+ *val2 = SMI240_TEMP_SCALE % GIGA;
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_ACCEL:
+ *val = 0;
+ *val2 = SMI240_ACCEL_SCALE;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ANGL_VEL:
+ *val = 0;
+ *val2 = SMI240_GYRO_SCALE;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+ case IIO_CHAN_INFO_OFFSET:
+ if (chan->type == IIO_TEMP) {
+ *val = SMI240_TEMP_OFFSET;
+ return IIO_VAL_INT;
+ } else {
+ return -EINVAL;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ int ret, i;
+ struct smi240_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ for (i = 0; i < ARRAY_SIZE(smi240_low_pass_freqs); i++) {
+ if (val == smi240_low_pass_freqs[i])
+ break;
+ }
+
+ if (i == ARRAY_SIZE(smi240_low_pass_freqs))
+ return -EINVAL;
+
+ switch (chan->type) {
+ case IIO_ACCEL:
+ data->accel_filter_freq = val;
+ break;
+ case IIO_ANGL_VEL:
+ data->anglvel_filter_freq = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Write access to soft config is locked until hard/soft reset */
+ ret = smi240_soft_reset(data);
+ if (ret)
+ return ret;
+
+ return smi240_soft_config(data);
+}
+
+static int smi240_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long info)
+{
+ switch (info) {
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+}
+
+static int smi240_init(struct smi240_data *data)
+{
+ int ret;
+
+ data->accel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
+ data->anglvel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
+ data->built_in_self_test_count = SMI240_BUILT_IN_SELF_TEST_COUNT;
+
+ ret = smi240_soft_reset(data);
+ if (ret)
+ return ret;
+
+ return smi240_soft_config(data);
+}
+
+static const struct iio_info smi240_info = {
+ .read_avail = smi240_read_avail,
+ .read_raw = smi240_read_raw,
+ .write_raw = smi240_write_raw,
+ .write_raw_get_fmt = smi240_write_raw_get_fmt,
+};
+
+static int smi240_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ struct smi240_data *data;
+ int ret, response;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ regmap = devm_regmap_init(dev, &smi240_regmap_bus, dev,
+ &smi240_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to initialize SPI Regmap\n");
+
+ data = iio_priv(indio_dev);
+ dev_set_drvdata(dev, indio_dev);
+ data->regmap = regmap;
+ data->capture = SMI240_CAPTURE_OFF;
+
+ ret = regmap_read(data->regmap, SMI240_CHIP_ID_REG, &response);
+ if (ret)
+ return dev_err_probe(dev, ret, "Read chip id failed\n");
+
+ if (response != SMI240_CHIP_ID)
+ dev_info(dev, "Unknown chip id: 0x%04x\n", response);
+
+ ret = smi240_init(data);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Device initialization failed\n");
+
+ indio_dev->channels = smi240_channels;
+ indio_dev->num_channels = ARRAY_SIZE(smi240_channels);
+ indio_dev->name = "smi240";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &smi240_info;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ smi240_trigger_handler, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Setup triggered buffer failed\n");
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Register IIO device failed\n");
+
+ return 0;
+}
+
+static const struct spi_device_id smi240_spi_id[] = {
+ { "smi240" },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, smi240_spi_id);
+
+static const struct of_device_id smi240_of_match[] = {
+ { .compatible = "bosch,smi240" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, smi240_of_match);
+
+static struct spi_driver smi240_spi_driver = {
+ .probe = smi240_probe,
+ .id_table = smi240_spi_id,
+ .driver = {
+ .of_match_table = smi240_of_match,
+ .name = "smi240",
+ },
+};
+module_spi_driver(smi240_spi_driver);
+
+MODULE_AUTHOR("Markus Lochmann <markus.lochmann@de.bosch.com>");
+MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>");
+MODULE_DESCRIPTION("Bosch SMI240 SPI driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index a3b93566533b..c225b246c8a5 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -447,7 +447,7 @@ struct st_lsm6dsx_hw {
/* Ensure natural alignment of buffer elements */
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan[ST_LSM6DSX_ID_MAX];
};
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index ed0267929725..509e0169dcd5 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -1865,7 +1865,7 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
return err;
}
-static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state)
+static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state)
{
const struct st_lsm6dsx_reg *reg;
unsigned int data;
@@ -1959,7 +1959,7 @@ static int
st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
struct st_lsm6dsx_hw *hw = sensor->hw;
@@ -2132,14 +2132,11 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
const struct st_lsm6dsx_reg **drdy_reg)
{
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
int err = 0, drdy_pin;
- if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0) {
- struct st_sensors_platform_data *pdata;
-
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
+ if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0)
drdy_pin = pdata ? pdata->drdy_int_pin : 1;
- }
switch (drdy_pin) {
case 1:
@@ -2162,14 +2159,13 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw)
{
const struct st_lsm6dsx_shub_settings *hub_settings;
- struct st_sensors_platform_data *pdata;
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
unsigned int data;
int err = 0;
hub_settings = &hw->settings->shub_settings;
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
if (device_property_read_bool(dev, "st,pullups") ||
(pdata && pdata->pullups)) {
if (hub_settings->pullup_en.sec_page) {
@@ -2524,15 +2520,14 @@ static irqreturn_t st_lsm6dsx_sw_trigger_handler_thread(int irq,
static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
{
- struct st_sensors_platform_data *pdata;
const struct st_lsm6dsx_reg *reg;
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
unsigned long irq_type;
bool irq_active_low;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
@@ -2554,7 +2549,6 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
if (err < 0)
return err;
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
if (device_property_read_bool(dev, "drive-open-drain") ||
(pdata && pdata->open_drain)) {
reg = &hw->settings->irq_config.od;
@@ -2639,7 +2633,7 @@ static int st_lsm6dsx_init_regulators(struct device *dev)
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
struct regmap *regmap)
{
- struct st_sensors_platform_data *pdata = dev->platform_data;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
const struct st_lsm6dsx_shub_settings *hub_settings;
struct st_lsm6dsx_hw *hw;
const char *name = NULL;
diff --git a/drivers/iio/industrialio-acpi.c b/drivers/iio/industrialio-acpi.c
index 981b75d40780..d67a43843799 100644
--- a/drivers/iio/industrialio-acpi.c
+++ b/drivers/iio/industrialio-acpi.c
@@ -2,7 +2,8 @@
/* IIO ACPI helper functions */
#include <linux/acpi.h>
-#include <linux/dev_printk.h>
+#include <linux/device.h>
+#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/sprintf.h>
@@ -28,17 +29,21 @@ bool iio_read_acpi_mount_matrix(struct device *dev,
char *acpi_method)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_device *adev = ACPI_COMPANION(dev);
char *str;
union acpi_object *obj, *elements;
+ acpi_handle handle;
acpi_status status;
int i, j, val[3];
bool ret = false;
- if (!adev || !acpi_has_method(adev->handle, acpi_method))
+ handle = ACPI_HANDLE(dev);
+ if (!handle)
return false;
- status = acpi_evaluate_object(adev->handle, acpi_method, NULL, &buffer);
+ if (!acpi_has_method(handle, acpi_method))
+ return false;
+
+ status = acpi_evaluate_object(handle, acpi_method, NULL, &buffer);
if (ACPI_FAILURE(status)) {
dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status);
return false;
@@ -83,3 +88,38 @@ out_free_buffer:
return ret;
}
EXPORT_SYMBOL_GPL(iio_read_acpi_mount_matrix);
+
+/**
+ * iio_get_acpi_device_name_and_data() - Return ACPI device instance name and driver data
+ * @dev: Device structure
+ * @data: Optional pointer to return driver data
+ *
+ * When device was enumerated by ACPI ID matching, the user might
+ * want to set description for the physical chip. In such cases
+ * the ACPI device instance name might be used. This call may be
+ * performed to retrieve this information.
+ *
+ * NOTE: This helper function exists only for backward compatibility,
+ * do not use in a new code!
+ *
+ * Returns: ACPI device instance name or %NULL.
+ */
+const char *iio_get_acpi_device_name_and_data(struct device *dev, const void **data)
+{
+ const struct acpi_device_id *id;
+ acpi_handle handle;
+
+ handle = ACPI_HANDLE(dev);
+ if (!handle)
+ return NULL;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id)
+ return NULL;
+
+ if (data)
+ *data = (const void *)id->driver_data;
+
+ return dev_name(dev);
+}
+EXPORT_SYMBOL_GPL(iio_get_acpi_device_name_and_data);
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index 20b3b5212da7..529b1087d3fb 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -718,6 +718,84 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
return 0;
}
+/**
+ * iio_backend_ddr_enable - Enable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Enable DDR, data is generated by the IP at each front (raising and falling)
+ * of the bus clock signal.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_enable, IIO_BACKEND);
+
+/**
+ * iio_backend_ddr_disable - Disable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Disable DDR, setting into SDR mode (Single Data Rate).
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_disable, IIO_BACKEND);
+
+/**
+ * iio_backend_data_stream_enable - Enable data stream
+ * @back: Backend device
+ *
+ * Enable data stream over the bus interface.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_stream_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, data_stream_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_enable, IIO_BACKEND);
+
+/**
+ * iio_backend_data_stream_disable - Disable data stream
+ * @back: Backend device
+ *
+ * Disable data stream over the bus interface.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_stream_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, data_stream_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_disable, IIO_BACKEND);
+
+/**
+ * iio_backend_data_transfer_addr - Set data address.
+ * @back: Backend device
+ * @address: Data register address
+ *
+ * Some devices may need to inform the backend about an address
+ * where to read or write the data.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ return iio_backend_op_call(back, data_transfer_addr, address);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, IIO_BACKEND);
+
static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name,
struct fwnode_handle *fwnode)
{
@@ -737,8 +815,8 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
}
fwnode_back = fwnode_find_reference(fwnode, "io-backends", index);
- if (IS_ERR(fwnode))
- return dev_err_cast_probe(dev, fwnode,
+ if (IS_ERR(fwnode_back))
+ return dev_err_cast_probe(dev, fwnode_back,
"Cannot get Firmware reference\n");
guard(mutex)(&iio_back_lock);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 6a6568d4a2cb..a2117ad1337d 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -95,6 +95,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_DELTA_VELOCITY] = "deltavelocity",
[IIO_COLORTEMP] = "colortemp",
[IIO_CHROMATICITY] = "chromaticity",
+ [IIO_ATTENTION] = "attention",
};
static const char * const iio_modifier_names[] = {
@@ -1665,7 +1666,7 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
indio_dev = &iio_dev_opaque->indio_dev;
if (sizeof_priv)
- indio_dev->priv = (char *)iio_dev_opaque +
+ ACCESS_PRIVATE(indio_dev, priv) = (char *)iio_dev_opaque +
ALIGN(sizeof(*iio_dev_opaque), IIO_DMA_MINALIGN);
indio_dev->dev.parent = parent;
diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c
index 5f131bc1a01e..291c0fc332c9 100644
--- a/drivers/iio/industrialio-gts-helper.c
+++ b/drivers/iio/industrialio-gts-helper.c
@@ -167,7 +167,7 @@ static int iio_gts_gain_cmp(const void *a, const void *b)
static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
{
- int ret, i, j, new_idx, time_idx;
+ int i, j, new_idx, time_idx, ret = 0;
int *all_gains;
size_t gain_bytes;
@@ -205,7 +205,7 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
memcpy(all_gains, gains[time_idx], gain_bytes);
new_idx = gts->num_hwgain;
- while (time_idx--) {
+ while (time_idx-- > 0) {
for (j = 0; j < gts->num_hwgain; j++) {
int candidate = gains[time_idx][j];
int chk;
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 151099be2863..136b225b6bc8 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -20,7 +20,7 @@
struct iio_map_internal {
struct iio_dev *indio_dev;
- struct iio_map *map;
+ const struct iio_map *map;
struct list_head l;
};
@@ -42,7 +42,7 @@ static int iio_map_array_unregister_locked(struct iio_dev *indio_dev)
return ret;
}
-int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
+int iio_map_array_register(struct iio_dev *indio_dev, const struct iio_map *maps)
{
struct iio_map_internal *mapi;
int i = 0;
@@ -86,7 +86,8 @@ static void iio_map_array_unregister_cb(void *indio_dev)
iio_map_array_unregister(indio_dev);
}
-int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev, struct iio_map *maps)
+int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev,
+ const struct iio_map *maps)
{
int ret;
@@ -269,7 +270,7 @@ struct iio_channel *fwnode_iio_channel_get_by_name(struct fwnode_handle *fwnode,
return ERR_PTR(-ENODEV);
}
- chan = __fwnode_iio_channel_get_by_name(fwnode, name);
+ chan = __fwnode_iio_channel_get_by_name(parent, name);
if (!IS_ERR(chan) || PTR_ERR(chan) != -ENODEV) {
fwnode_handle_put(parent);
return chan;
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index f2f3e414849a..29ffa8491927 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -248,7 +248,6 @@ config SENSORS_ISL29018
tristate "Intersil 29018 light and proximity sensor"
depends on I2C
select REGMAP_I2C
- default n
help
If you say yes here you get support for ambient light sensing and
proximity infrared sensing from Intersil ISL29018.
@@ -476,7 +475,7 @@ config OPT3001
depends on I2C
help
If you say Y or M here, you get support for Texas Instruments
- OPT3001 Ambient Light Sensor.
+ OPT3001 Ambient Light Sensor, OPT3002 Light-to-Digital Sensor.
If built as a dynamically linked module, it will be called
opt3001.
@@ -670,13 +669,24 @@ config VCNL4035
To compile this driver as a module, choose M here: the
module will be called vcnl4035.
+config VEML3235
+ tristate "VEML3235 ambient light sensor"
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Say Y here if you want to build a driver for the Vishay VEML3235
+ ambient light sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called veml3235.
+
config VEML6030
- tristate "VEML6030 ambient light sensor"
+ tristate "VEML6030 and VEML6035 ambient light sensors"
select REGMAP_I2C
depends on I2C
help
Say Y here if you want to build a driver for the Vishay VEML6030
- ambient light sensor (ALS).
+ and VEML6035 ambient light sensors (ALS).
To compile this driver as a module, choose M here: the
module will be called veml6030.
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 321010fc0b93..f14a37442712 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_US5182D) += us5182d.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o
obj-$(CONFIG_VCNL4035) += vcnl4035.o
+obj-$(CONFIG_VEML3235) += veml3235.o
obj-$(CONFIG_VEML6030) += veml6030.o
obj-$(CONFIG_VEML6040) += veml6040.o
obj-$(CONFIG_VEML6070) += veml6070.o
diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c
index 2e0170be077a..593d614b1689 100644
--- a/drivers/iio/light/adux1020.c
+++ b/drivers/iio/light/adux1020.c
@@ -502,7 +502,8 @@ fail:
static int adux1020_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct adux1020_data *data = iio_priv(indio_dev);
int ret, mask;
@@ -526,12 +527,11 @@ static int adux1020_write_event_config(struct iio_dev *indio_dev,
mask = ADUX1020_PROX_OFF1_INT;
if (state)
- state = 0;
+ ret = regmap_clear_bits(data->regmap,
+ ADUX1020_REG_INT_MASK, mask);
else
- state = mask;
-
- ret = regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
- mask, state);
+ ret = regmap_set_bits(data->regmap,
+ ADUX1020_REG_INT_MASK, mask);
if (ret < 0)
goto fail;
diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c
index 53569587ccb7..7cbb8b203300 100644
--- a/drivers/iio/light/al3010.c
+++ b/drivers/iio/light/al3010.c
@@ -87,7 +87,12 @@ static int al3010_init(struct al3010_data *data)
int ret;
ret = al3010_set_pwr(data->client, true);
+ if (ret < 0)
+ return ret;
+ ret = devm_add_action_or_reset(&data->client->dev,
+ al3010_set_pwr_off,
+ data);
if (ret < 0)
return ret;
@@ -190,12 +195,6 @@ static int al3010_probe(struct i2c_client *client)
return ret;
}
- ret = devm_add_action_or_reset(&client->dev,
- al3010_set_pwr_off,
- data);
- if (ret < 0)
- return ret;
-
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
index 11f2ab4ca261..938d76f7e312 100644
--- a/drivers/iio/light/apds9300.c
+++ b/drivers/iio/light/apds9300.c
@@ -46,10 +46,10 @@
struct apds9300_data {
struct i2c_client *client;
struct mutex mutex;
- int power_state;
+ bool power_state;
int thresh_low;
int thresh_hi;
- int intr_en;
+ bool intr_en;
};
/* Lux calculation */
@@ -148,7 +148,7 @@ static int apds9300_set_thresh_hi(struct apds9300_data *data, int value)
return 0;
}
-static int apds9300_set_intr_state(struct apds9300_data *data, int state)
+static int apds9300_set_intr_state(struct apds9300_data *data, bool state)
{
int ret;
u8 cmd;
@@ -169,7 +169,7 @@ static int apds9300_set_intr_state(struct apds9300_data *data, int state)
return 0;
}
-static int apds9300_set_power_state(struct apds9300_data *data, int state)
+static int apds9300_set_power_state(struct apds9300_data *data, bool state)
{
int ret;
u8 cmd;
@@ -221,7 +221,7 @@ static int apds9300_chip_init(struct apds9300_data *data)
* Disable interrupt to ensure thai it is doesn't enable
* i.e. after device soft reset
*/
- ret = apds9300_set_intr_state(data, 0);
+ ret = apds9300_set_intr_state(data, false);
if (ret < 0)
goto err;
@@ -321,7 +321,7 @@ static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct apds9300_data *data = iio_priv(indio_dev);
int ret;
@@ -459,8 +459,8 @@ static void apds9300_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
/* Ensure that power off and interrupts are disabled */
- apds9300_set_intr_state(data, 0);
- apds9300_set_power_state(data, 0);
+ apds9300_set_intr_state(data, false);
+ apds9300_set_power_state(data, false);
}
static int apds9300_suspend(struct device *dev)
@@ -470,7 +470,7 @@ static int apds9300_suspend(struct device *dev)
int ret;
mutex_lock(&data->mutex);
- ret = apds9300_set_power_state(data, 0);
+ ret = apds9300_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
@@ -483,7 +483,7 @@ static int apds9300_resume(struct device *dev)
int ret;
mutex_lock(&data->mutex);
- ret = apds9300_set_power_state(data, 1);
+ ret = apds9300_set_power_state(data, true);
mutex_unlock(&data->mutex);
return ret;
diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c
index 079e02be1005..9c08e7c3ad0c 100644
--- a/drivers/iio/light/apds9306.c
+++ b/drivers/iio/light/apds9306.c
@@ -1071,7 +1071,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct apds9306_data *data = iio_priv(indio_dev);
struct apds9306_regfields *rf = &data->rf;
@@ -1125,10 +1125,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev,
}
}
case IIO_EV_TYPE_THRESH_ADAPTIVE:
- if (state)
- return regmap_field_write(rf->int_thresh_var_en, 1);
- else
- return regmap_field_write(rf->int_thresh_var_en, 0);
+ return regmap_field_write(rf->int_thresh_var_en, state);
default:
return -EINVAL;
}
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index 3c14e4c30805..d30441d33703 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -133,8 +133,8 @@ struct apds9960_data {
struct regmap_field *reg_enable_pxs;
/* state */
- int als_int;
- int pxs_int;
+ bool als_int;
+ bool pxs_int;
int gesture_mode_running;
/* gain values */
@@ -749,21 +749,17 @@ static int apds9960_read_event_config(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
-
- return 0;
}
static int apds9960_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct apds9960_data *data = iio_priv(indio_dev);
int ret;
- state = !!state;
-
switch (chan->type) {
case IIO_PROXIMITY:
if (data->pxs_int == state)
diff --git a/drivers/iio/light/bh1745.c b/drivers/iio/light/bh1745.c
index 2e458e9d5d85..23e9f16090cc 100644
--- a/drivers/iio/light/bh1745.c
+++ b/drivers/iio/light/bh1745.c
@@ -638,46 +638,42 @@ static int bh1745_read_event_config(struct iio_dev *indio_dev,
static int bh1745_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bh1745_data *data = iio_priv(indio_dev);
int value;
- if (state == 0)
+ if (!state)
return regmap_clear_bits(data->regmap,
BH1745_INTR, BH1745_INTR_ENABLE);
- if (state == 1) {
- /* Latch is always enabled when enabling interrupt */
- value = BH1745_INTR_ENABLE;
+ /* Latch is always enabled when enabling interrupt */
+ value = BH1745_INTR_ENABLE;
- switch (chan->channel2) {
- case IIO_MOD_LIGHT_RED:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_RED));
+ switch (chan->channel2) {
+ case IIO_MOD_LIGHT_RED:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_RED));
- case IIO_MOD_LIGHT_GREEN:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_GREEN));
+ case IIO_MOD_LIGHT_GREEN:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_GREEN));
- case IIO_MOD_LIGHT_BLUE:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_BLUE));
+ case IIO_MOD_LIGHT_BLUE:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_BLUE));
- case IIO_MOD_LIGHT_CLEAR:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_CLEAR));
+ case IIO_MOD_LIGHT_CLEAR:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_CLEAR));
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
}
-
- return -EINVAL;
}
static int bh1745_read_avail(struct iio_dev *indio_dev,
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index 9df85b3999fa..aeae0566ec12 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -217,8 +217,7 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
cm32181->lux_per_bit = CM32181_LUX_PER_BIT;
cm32181->lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT;
- if (ACPI_HANDLE(cm32181->dev))
- cm32181_acpi_parse_cpm_tables(cm32181);
+ cm32181_acpi_parse_cpm_tables(cm32181);
/* Initialize registers*/
for_each_set_bit(i, &cm32181->init_regs_bitmap, CM32181_CONF_REG_NUM) {
diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c
index 22a63a89f289..675c0fd44db4 100644
--- a/drivers/iio/light/cm3605.c
+++ b/drivers/iio/light/cm3605.c
@@ -318,7 +318,7 @@ static struct platform_driver cm3605_driver = {
.pm = pm_sleep_ptr(&cm3605_dev_pm_ops),
},
.probe = cm3605_probe,
- .remove_new = cm3605_remove,
+ .remove = cm3605_remove,
};
module_platform_driver(cm3605_driver);
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index a4a1505534c0..ae3fc3299eec 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -529,7 +529,7 @@ static int cm36651_write_prox_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct cm36651_data *cm36651 = iio_priv(indio_dev);
int cmd, ret;
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
index f8b1d7dd6f5f..d56ee217fe53 100644
--- a/drivers/iio/light/gp2ap002.c
+++ b/drivers/iio/light/gp2ap002.c
@@ -340,7 +340,7 @@ static int gp2ap002_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index 81e718cdeae3..1a352c88598e 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -1159,7 +1159,7 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
enum gp2ap020a00f_cmd cmd;
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 260281194f61..4eb692322432 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -31,7 +31,7 @@ struct als_state {
struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1];
struct {
u32 illum[CHANNEL_SCAN_INDEX_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -356,11 +356,11 @@ static int als_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_als_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "als";
struct iio_dev *indio_dev;
struct als_state *als_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state));
if (!indio_dev)
@@ -438,7 +438,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_als_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct als_state *als_state = iio_priv(indio_dev);
@@ -467,7 +467,7 @@ static struct platform_driver hid_als_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_als_probe,
- .remove_new = hid_als_remove,
+ .remove = hid_als_remove,
};
module_platform_driver(hid_als_platform_driver);
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 26c481d2998c..e8e7b2999b4c 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -13,16 +13,32 @@
#include <linux/iio/buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
-#define CHANNEL_SCAN_INDEX_PRESENCE 0
+static const u32 prox_usage_ids[] = {
+ HID_USAGE_SENSOR_HUMAN_PRESENCE,
+ HID_USAGE_SENSOR_HUMAN_PROXIMITY,
+ HID_USAGE_SENSOR_HUMAN_ATTENTION,
+};
+
+#define MAX_CHANNELS ARRAY_SIZE(prox_usage_ids)
+
+enum {
+ HID_HUMAN_PRESENCE,
+ HID_HUMAN_PROXIMITY,
+ HID_HUMAN_ATTENTION,
+};
struct prox_state {
struct hid_sensor_hub_callbacks callbacks;
struct hid_sensor_common common_attributes;
- struct hid_sensor_hub_attribute_info prox_attr;
- u32 human_presence;
+ struct hid_sensor_hub_attribute_info prox_attr[MAX_CHANNELS];
+ struct iio_chan_spec channels[MAX_CHANNELS];
+ u32 channel2usage[MAX_CHANNELS];
+ u32 human_presence[MAX_CHANNELS];
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
+ unsigned long scan_mask[2]; /* One entry plus one terminator. */
+ int num_channels;
};
static const u32 prox_sensitivity_addresses[] = {
@@ -30,17 +46,24 @@ static const u32 prox_sensitivity_addresses[] = {
HID_USAGE_SENSOR_DATA_PRESENCE,
};
-/* Channel definitions */
-static const struct iio_chan_spec prox_channels[] = {
- {
- .type = IIO_PROXIMITY,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
- BIT(IIO_CHAN_INFO_SCALE) |
- BIT(IIO_CHAN_INFO_SAMP_FREQ) |
- BIT(IIO_CHAN_INFO_HYSTERESIS),
- .scan_index = CHANNEL_SCAN_INDEX_PRESENCE,
+#define PROX_CHANNEL(_is_proximity, _channel) \
+ {\
+ .type = _is_proximity ? IIO_PROXIMITY : IIO_ATTENTION,\
+ .info_mask_separate = _is_proximity ? BIT(IIO_CHAN_INFO_RAW) :\
+ BIT(IIO_CHAN_INFO_PROCESSED),\
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |\
+ BIT(IIO_CHAN_INFO_SCALE) |\
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |\
+ BIT(IIO_CHAN_INFO_HYSTERESIS),\
+ .indexed = _is_proximity,\
+ .channel = _channel,\
}
+
+/* Channel definitions (same order as prox_usage_ids) */
+static const struct iio_chan_spec prox_channels[] = {
+ PROX_CHANNEL(true, HID_HUMAN_PRESENCE),
+ PROX_CHANNEL(true, HID_HUMAN_PROXIMITY),
+ PROX_CHANNEL(false, 0),
};
/* Adjust channel real bits based on report descriptor */
@@ -62,7 +85,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
{
struct prox_state *prox_state = iio_priv(indio_dev);
struct hid_sensor_hub_device *hsdev;
- int report_id = -1;
+ int report_id;
u32 address;
int ret_type;
s32 min;
@@ -71,29 +94,23 @@ static int prox_read_raw(struct iio_dev *indio_dev,
*val2 = 0;
switch (mask) {
case IIO_CHAN_INFO_RAW:
- switch (chan->scan_index) {
- case CHANNEL_SCAN_INDEX_PRESENCE:
- report_id = prox_state->prox_attr.report_id;
- min = prox_state->prox_attr.logical_minimum;
- address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
- hsdev = prox_state->common_attributes.hsdev;
- break;
- default:
- report_id = -1;
- break;
- }
- if (report_id >= 0) {
- hid_sensor_power_state(&prox_state->common_attributes,
- true);
- *val = sensor_hub_input_attr_get_raw_value(
- hsdev, hsdev->usage, address, report_id,
- SENSOR_HUB_SYNC, min < 0);
- hid_sensor_power_state(&prox_state->common_attributes,
- false);
- } else {
- *val = 0;
+ if (chan->scan_index >= prox_state->num_channels)
return -EINVAL;
- }
+ address = prox_state->channel2usage[chan->scan_index];
+ report_id = prox_state->prox_attr[chan->scan_index].report_id;
+ hsdev = prox_state->common_attributes.hsdev;
+ min = prox_state->prox_attr[chan->scan_index].logical_minimum;
+ hid_sensor_power_state(&prox_state->common_attributes, true);
+ *val = sensor_hub_input_attr_get_raw_value(hsdev,
+ hsdev->usage,
+ address,
+ report_id,
+ SENSOR_HUB_SYNC,
+ min < 0);
+ if (prox_state->channel2usage[chan->scan_index] ==
+ HID_USAGE_SENSOR_HUMAN_ATTENTION)
+ *val *= 100;
+ hid_sensor_power_state(&prox_state->common_attributes, false);
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
@@ -103,7 +120,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_OFFSET:
*val = hid_sensor_convert_exponent(
- prox_state->prox_attr.unit_expo);
+ prox_state->prox_attr[chan->scan_index].unit_expo);
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -153,14 +170,6 @@ static const struct iio_info prox_info = {
.write_raw = &prox_write_raw,
};
-/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
- int len)
-{
- dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, data);
-}
-
/* Callback handler to send event after all samples are received and captured */
static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
unsigned usage_id,
@@ -170,10 +179,10 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
struct prox_state *prox_state = iio_priv(indio_dev);
dev_dbg(&indio_dev->dev, "prox_proc_event\n");
- if (atomic_read(&prox_state->common_attributes.data_ready))
- hid_sensor_push_data(indio_dev,
- &prox_state->human_presence,
- sizeof(prox_state->human_presence));
+ if (atomic_read(&prox_state->common_attributes.data_ready)) {
+ dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+ iio_push_to_buffers(indio_dev, &prox_state->human_presence);
+ }
return 0;
}
@@ -186,58 +195,77 @@ static int prox_capture_sample(struct hid_sensor_hub_device *hsdev,
{
struct iio_dev *indio_dev = platform_get_drvdata(priv);
struct prox_state *prox_state = iio_priv(indio_dev);
- int ret = -EINVAL;
-
- switch (usage_id) {
- case HID_USAGE_SENSOR_HUMAN_PRESENCE:
- switch (raw_len) {
- case 1:
- prox_state->human_presence = *(u8 *)raw_data;
- return 0;
- case 4:
- prox_state->human_presence = *(u32 *)raw_data;
- return 0;
- default:
+ int multiplier = 1;
+ int chan;
+
+ for (chan = 0; chan < prox_state->num_channels; chan++)
+ if (prox_state->channel2usage[chan] == usage_id)
break;
- }
- break;
+ if (chan == prox_state->num_channels)
+ return -EINVAL;
+
+ if (usage_id == HID_USAGE_SENSOR_HUMAN_ATTENTION)
+ multiplier = 100;
+
+ switch (raw_len) {
+ case 1:
+ prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier;
+ return 0;
+ case 4:
+ prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier;
+ return 0;
}
- return ret;
+ return -EINVAL;
}
/* Parse report which is specific to an usage id*/
static int prox_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
- struct iio_chan_spec *channels,
- unsigned usage_id,
struct prox_state *st)
{
+ struct iio_chan_spec *channels = st->channels;
+ int index = 0;
int ret;
+ int i;
+
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ u32 usage_id = prox_usage_ids[i];
+
+ ret = sensor_hub_input_get_attribute_info(hsdev,
+ HID_INPUT_REPORT,
+ hsdev->usage,
+ usage_id,
+ &st->prox_attr[index]);
+ if (ret < 0)
+ continue;
+ st->channel2usage[index] = usage_id;
+ st->scan_mask[0] |= BIT(index);
+ channels[index] = prox_channels[i];
+ channels[index].scan_index = index;
+ prox_adjust_channel_bit_mask(channels, index,
+ st->prox_attr[index].size);
+ dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr[index].index,
+ st->prox_attr[index].report_id);
+ index++;
+ }
- ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
- usage_id,
- HID_USAGE_SENSOR_HUMAN_PRESENCE,
- &st->prox_attr);
- if (ret < 0)
+ if (!index)
return ret;
- prox_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESENCE,
- st->prox_attr.size);
- dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr.index,
- st->prox_attr.report_id);
+ st->num_channels = index;
- return ret;
+ return 0;
}
/* Function to initialize the processing for usage id */
static int hid_prox_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "prox";
struct iio_dev *indio_dev;
struct prox_state *prox_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct prox_state));
@@ -258,22 +286,15 @@ static int hid_prox_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = devm_kmemdup(&pdev->dev, prox_channels,
- sizeof(prox_channels), GFP_KERNEL);
- if (!indio_dev->channels) {
- dev_err(&pdev->dev, "failed to duplicate channels\n");
- return -ENOMEM;
- }
-
- ret = prox_parse_report(pdev, hsdev,
- (struct iio_chan_spec *)indio_dev->channels,
- hsdev->usage, prox_state);
+ ret = prox_parse_report(pdev, hsdev, prox_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
return ret;
}
- indio_dev->num_channels = ARRAY_SIZE(prox_channels);
+ indio_dev->num_channels = prox_state->num_channels;
+ indio_dev->channels = prox_state->channels;
+ indio_dev->available_scan_masks = prox_state->scan_mask;
indio_dev->info = &prox_info;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -315,7 +336,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_prox_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct prox_state *prox_state = iio_priv(indio_dev);
@@ -344,7 +365,7 @@ static struct platform_driver hid_prox_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_prox_probe,
- .remove_new = hid_prox_remove,
+ .remove = hid_prox_remove,
};
module_platform_driver(hid_prox_platform_driver);
diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c
index 6de33feada3a..b9f230210f07 100644
--- a/drivers/iio/light/iqs621-als.c
+++ b/drivers/iio/light/iqs621-als.c
@@ -271,7 +271,7 @@ static int iqs621_als_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
struct iqs62x_core *iqs62x = iqs621_als->iqs62x;
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index 8dfc750e68c0..201eae1c4589 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -8,17 +8,18 @@
* Copyright (c) 2010, NVIDIA Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/acpi.h>
#define ISL29018_CONV_TIME_MS 100
@@ -687,20 +688,6 @@ static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
},
};
-static const char *isl29018_match_acpi_device(struct device *dev, int *data)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
-
- if (!id)
- return NULL;
-
- *data = (int)id->driver_data;
-
- return dev_name(dev);
-}
-
static void isl29018_disable_regulator_action(void *_data)
{
struct isl29018_chip *chip = _data;
@@ -716,9 +703,10 @@ static int isl29018_probe(struct i2c_client *client)
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct isl29018_chip *chip;
struct iio_dev *indio_dev;
+ const void *ddata = NULL;
+ const char *name;
+ int dev_id;
int err;
- const char *name = NULL;
- int dev_id = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
if (!indio_dev)
@@ -731,11 +719,11 @@ static int isl29018_probe(struct i2c_client *client)
if (id) {
name = id->name;
dev_id = id->driver_data;
+ } else {
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ dev_id = (intptr_t)ddata;
}
- if (ACPI_HANDLE(&client->dev))
- name = isl29018_match_acpi_device(&client->dev, &dev_id);
-
mutex_init(&chip->lock);
chip->type = dev_id;
@@ -832,15 +820,13 @@ static int isl29018_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend,
isl29018_resume);
-#ifdef CONFIG_ACPI
static const struct acpi_device_id isl29018_acpi_match[] = {
{"ISL29018", isl29018},
{"ISL29023", isl29023},
{"ISL29035", isl29035},
- {},
+ {}
};
MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
-#endif
static const struct i2c_device_id isl29018_id[] = {
{"isl29018", isl29018},
@@ -854,14 +840,14 @@ static const struct of_device_id isl29018_of_match[] = {
{ .compatible = "isil,isl29018", },
{ .compatible = "isil,isl29023", },
{ .compatible = "isil,isl29035", },
- { },
+ { }
};
MODULE_DEVICE_TABLE(of, isl29018_of_match);
static struct i2c_driver isl29018_driver = {
.driver = {
.name = "isl29018",
- .acpi_match_table = ACPI_PTR(isl29018_acpi_match),
+ .acpi_match_table = isl29018_acpi_match,
.pm = pm_sleep_ptr(&isl29018_pm_ops),
.of_match_table = isl29018_of_match,
},
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index 7800f7fa51b7..99f0b903018c 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -754,7 +754,7 @@ static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
}
static int lm3533_als_setup(struct lm3533_als *als,
- struct lm3533_als_platform_data *pdata)
+ const struct lm3533_als_platform_data *pdata)
{
int ret;
@@ -828,8 +828,8 @@ static const struct iio_info lm3533_als_info = {
static int lm3533_als_probe(struct platform_device *pdev)
{
+ const struct lm3533_als_platform_data *pdata;
struct lm3533 *lm3533;
- struct lm3533_als_platform_data *pdata;
struct lm3533_als *als;
struct iio_dev *indio_dev;
int ret;
@@ -838,7 +838,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
if (!lm3533)
return -EINVAL;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
@@ -912,7 +912,7 @@ static struct platform_driver lm3533_als_driver = {
.name = "lm3533-als",
},
.probe = lm3533_als_probe,
- .remove_new = lm3533_als_remove,
+ .remove = lm3533_als_remove,
};
module_platform_driver(lm3533_als_driver);
diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
index 4f6975e63a8f..df664f360903 100644
--- a/drivers/iio/light/ltr390.c
+++ b/drivers/iio/light/ltr390.c
@@ -18,14 +18,18 @@
* - Interrupt support
*/
+#include <linux/bitfield.h>
+#include <linux/device.h>
#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
-#include <linux/bitfield.h>
#include <linux/iio/iio.h>
+#include <linux/iio/events.h>
#include <linux/unaligned.h>
@@ -33,18 +37,27 @@
#define LTR390_ALS_UVS_MEAS_RATE 0x04
#define LTR390_ALS_UVS_GAIN 0x05
#define LTR390_PART_ID 0x06
+#define LTR390_MAIN_STATUS 0x07
#define LTR390_ALS_DATA 0x0D
#define LTR390_UVS_DATA 0x10
#define LTR390_INT_CFG 0x19
+#define LTR390_INT_PST 0x1A
+#define LTR390_THRESH_UP 0x21
+#define LTR390_THRESH_LOW 0x24
#define LTR390_PART_NUMBER_ID 0xb
-#define LTR390_ALS_UVS_GAIN_MASK 0x07
-#define LTR390_ALS_UVS_INT_TIME_MASK 0x70
+#define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
+#define LTR390_ALS_UVS_MEAS_RATE_MASK GENMASK(2, 0)
+#define LTR390_ALS_UVS_INT_TIME_MASK GENMASK(6, 4)
#define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x))
+#define LTR390_INT_PST_MASK GENMASK(7, 4)
+#define LTR390_INT_PST_VAL(x) FIELD_PREP(LTR390_INT_PST_MASK, (x))
#define LTR390_SW_RESET BIT(4)
#define LTR390_UVS_MODE BIT(3)
#define LTR390_SENSOR_ENABLE BIT(1)
+#define LTR390_LS_INT_EN BIT(2)
+#define LTR390_LS_INT_SEL_UVS BIT(5)
#define LTR390_FRACTIONAL_PRECISION 100
@@ -70,6 +83,11 @@ enum ltr390_mode {
LTR390_SET_UVS_MODE,
};
+enum ltr390_meas_rate {
+ LTR390_GET_FREQ,
+ LTR390_GET_PERIOD,
+};
+
struct ltr390_data {
struct regmap *regmap;
struct i2c_client *client;
@@ -87,6 +105,18 @@ static const struct regmap_config ltr390_regmap_config = {
.val_bits = 8,
};
+/* Sampling frequency is in mili Hz and mili Seconds */
+static const int ltr390_samp_freq_table[][2] = {
+ [0] = { 40000, 25 },
+ [1] = { 20000, 50 },
+ [2] = { 10000, 100 },
+ [3] = { 5000, 200 },
+ [4] = { 2000, 500 },
+ [5] = { 1000, 1000 },
+ [6] = { 500, 2000 },
+ [7] = { 500, 2000 },
+};
+
static int ltr390_register_read(struct ltr390_data *data, u8 register_address)
{
struct device *dev = &data->client->dev;
@@ -135,6 +165,19 @@ static int ltr390_counts_per_uvi(struct ltr390_data *data)
return DIV_ROUND_CLOSEST(23 * data->gain * data->int_time_us, 10 * orig_gain * orig_int_time);
}
+static int ltr390_get_samp_freq_or_period(struct ltr390_data *data,
+ enum ltr390_meas_rate option)
+{
+ int ret, value;
+
+ ret = regmap_read(data->regmap, LTR390_ALS_UVS_MEAS_RATE, &value);
+ if (ret < 0)
+ return ret;
+ value = FIELD_GET(LTR390_ALS_UVS_MEAS_RATE_MASK, value);
+
+ return ltr390_samp_freq_table[value][option];
+}
+
static int ltr390_read_raw(struct iio_dev *iio_device,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -191,6 +234,10 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
*val = data->int_time_us;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = ltr390_get_samp_freq_or_period(data, LTR390_GET_FREQ);
+ return IIO_VAL_INT;
+
default:
return -EINVAL;
}
@@ -199,6 +246,24 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
/* integration time in us */
static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 };
static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 };
+static const int ltr390_freq_map[] = { 40000, 20000, 10000, 5000, 2000, 1000, 500, 500 };
+
+static const struct iio_event_spec ltr390_event_spec[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_PERIOD),
+ }
+};
static const struct iio_chan_spec ltr390_channels[] = {
/* UV sensor */
@@ -206,16 +271,24 @@ static const struct iio_chan_spec ltr390_channels[] = {
.type = IIO_UVINDEX,
.scan_index = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
- .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = ltr390_event_spec,
+ .num_event_specs = ARRAY_SIZE(ltr390_event_spec),
},
/* ALS sensor */
{
.type = IIO_LIGHT,
.scan_index = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
- .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = ltr390_event_spec,
+ .num_event_specs = ARRAY_SIZE(ltr390_event_spec),
},
};
@@ -264,6 +337,23 @@ static int ltr390_set_int_time(struct ltr390_data *data, int val)
return -EINVAL;
}
+static int ltr390_set_samp_freq(struct ltr390_data *data, int val)
+{
+ int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(ltr390_samp_freq_table); idx++) {
+ if (ltr390_samp_freq_table[idx][0] != val)
+ continue;
+
+ guard(mutex)(&data->lock);
+ return regmap_update_bits(data->regmap,
+ LTR390_ALS_UVS_MEAS_RATE,
+ LTR390_ALS_UVS_MEAS_RATE_MASK, idx);
+ }
+
+ return -EINVAL;
+}
+
static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
const int **vals, int *type, int *length, long mask)
{
@@ -278,6 +368,11 @@ static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec con
*type = IIO_VAL_INT;
*vals = ltr390_int_time_map_us;
return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *length = ARRAY_SIZE(ltr390_freq_map);
+ *type = IIO_VAL_INT;
+ *vals = ltr390_freq_map;
+ return IIO_AVAIL_LIST;
default:
return -EINVAL;
}
@@ -301,6 +396,191 @@ static int ltr390_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec cons
return ltr390_set_int_time(data, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_set_samp_freq(data, val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_intr_prst(struct ltr390_data *data, int *val)
+{
+ int ret, prst, samp_period;
+
+ samp_period = ltr390_get_samp_freq_or_period(data, LTR390_GET_PERIOD);
+ ret = regmap_read(data->regmap, LTR390_INT_PST, &prst);
+ if (ret < 0)
+ return ret;
+ *val = prst * samp_period;
+
+ return IIO_VAL_INT;
+}
+
+static int ltr390_write_intr_prst(struct ltr390_data *data, int val)
+{
+ int ret, samp_period, new_val;
+
+ samp_period = ltr390_get_samp_freq_or_period(data, LTR390_GET_PERIOD);
+
+ /* persist period should be greater than or equal to samp period */
+ if (val < samp_period)
+ return -EINVAL;
+
+ new_val = DIV_ROUND_UP(val, samp_period);
+ if (new_val < 0 || new_val > 0x0f)
+ return -EINVAL;
+
+ guard(mutex)(&data->lock);
+ ret = regmap_update_bits(data->regmap,
+ LTR390_INT_PST,
+ LTR390_INT_PST_MASK,
+ LTR390_INT_PST_VAL(new_val));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ltr390_read_threshold(struct iio_dev *indio_dev,
+ enum iio_event_direction dir,
+ int *val, int *val2)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ ret = ltr390_register_read(data, LTR390_THRESH_UP);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+
+ case IIO_EV_DIR_FALLING:
+ ret = ltr390_register_read(data, LTR390_THRESH_LOW);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_write_threshold(struct iio_dev *indio_dev,
+ enum iio_event_direction dir,
+ int val, int val2)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ guard(mutex)(&data->lock);
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return regmap_bulk_write(data->regmap, LTR390_THRESH_UP, &val, 3);
+
+ case IIO_EV_DIR_FALLING:
+ return regmap_bulk_write(data->regmap, LTR390_THRESH_LOW, &val, 3);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ return ltr390_read_threshold(indio_dev, dir, val, val2);
+
+ case IIO_EV_INFO_PERIOD:
+ return ltr390_read_intr_prst(iio_priv(indio_dev), val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_write_threshold(indio_dev, dir, val, val2);
+
+ case IIO_EV_INFO_PERIOD:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_write_intr_prst(iio_priv(indio_dev), val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret, status;
+
+ ret = regmap_read(data->regmap, LTR390_INT_CFG, &status);
+ if (ret < 0)
+ return ret;
+
+ return FIELD_GET(LTR390_LS_INT_EN, status);
+}
+
+static int ltr390_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ bool state)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (!state)
+ return regmap_clear_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_EN);
+
+ guard(mutex)(&data->lock);
+ ret = regmap_set_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_EN);
+ if (ret < 0)
+ return ret;
+
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = ltr390_set_mode(data, LTR390_SET_ALS_MODE);
+ if (ret < 0)
+ return ret;
+
+ return regmap_clear_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_SEL_UVS);
+
+ case IIO_UVINDEX:
+ ret = ltr390_set_mode(data, LTR390_SET_UVS_MODE);
+ if (ret < 0)
+ return ret;
+
+ return regmap_set_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_SEL_UVS);
+
default:
return -EINVAL;
}
@@ -310,8 +590,44 @@ static const struct iio_info ltr390_info = {
.read_raw = ltr390_read_raw,
.write_raw = ltr390_write_raw,
.read_avail = ltr390_read_avail,
+ .read_event_value = ltr390_read_event_value,
+ .read_event_config = ltr390_read_event_config,
+ .write_event_value = ltr390_write_event_value,
+ .write_event_config = ltr390_write_event_config,
};
+static irqreturn_t ltr390_interrupt_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret, status;
+
+ /* Reading the status register to clear the interrupt flag, Datasheet pg: 17*/
+ ret = regmap_read(data->regmap, LTR390_MAIN_STATUS, &status);
+ if (ret < 0)
+ return ret;
+
+ switch (data->mode) {
+ case LTR390_SET_ALS_MODE:
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ iio_get_time_ns(indio_dev));
+ break;
+
+ case LTR390_SET_UVS_MODE:
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_UVINDEX, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ iio_get_time_ns(indio_dev));
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
static int ltr390_probe(struct i2c_client *client)
{
struct ltr390_data *data;
@@ -365,9 +681,40 @@ static int ltr390_probe(struct i2c_client *client)
if (ret)
return dev_err_probe(dev, ret, "failed to enable the sensor\n");
+ if (client->irq) {
+ ret = devm_request_threaded_irq(dev, client->irq,
+ NULL, ltr390_interrupt_handler,
+ IRQF_ONESHOT,
+ "ltr390_thresh_event",
+ indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "request irq (%d) failed\n", client->irq);
+ }
+
return devm_iio_device_register(dev, indio_dev);
}
+static int ltr390_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ return regmap_clear_bits(data->regmap, LTR390_MAIN_CTRL,
+ LTR390_SENSOR_ENABLE);
+}
+
+static int ltr390_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ return regmap_set_bits(data->regmap, LTR390_MAIN_CTRL,
+ LTR390_SENSOR_ENABLE);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(ltr390_pm_ops, ltr390_suspend, ltr390_resume);
+
static const struct i2c_device_id ltr390_id[] = {
{ "ltr390" },
{ /* Sentinel */ }
@@ -384,6 +731,7 @@ static struct i2c_driver ltr390_driver = {
.driver = {
.name = "ltr390",
.of_match_table = ltr390_of_table,
+ .pm = pm_sleep_ptr(&ltr390_pm_ops),
},
.probe = ltr390_probe,
.id_table = ltr390_id,
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 8c516ede9116..604f5f900a2e 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -15,7 +15,6 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/regmap.h>
-#include <linux/acpi.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
@@ -1078,15 +1077,11 @@ static int ltr501_read_event_config(struct iio_dev *indio_dev,
static int ltr501_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ltr501_data *data = iio_priv(indio_dev);
int ret;
- /* only 1 and 0 are valid inputs */
- if (state != 1 && state != 0)
- return -EINVAL;
-
switch (chan->type) {
case IIO_INTENSITY:
mutex_lock(&data->lock_als);
@@ -1422,17 +1417,6 @@ static int ltr501_powerdown(struct ltr501_data *data)
data->ps_contr & ~LTR501_CONTR_ACTIVE);
}
-static const char *ltr501_match_acpi_device(struct device *dev, int *chip_idx)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
- *chip_idx = id->driver_data;
- return dev_name(dev);
-}
-
static int ltr501_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1440,8 +1424,10 @@ static int ltr501_probe(struct i2c_client *client)
struct ltr501_data *data;
struct iio_dev *indio_dev;
struct regmap *regmap;
- int ret, partid, chip_idx = 0;
- const char *name = NULL;
+ const void *ddata = NULL;
+ int partid, chip_idx;
+ const char *name;
+ int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -1523,11 +1509,12 @@ static int ltr501_probe(struct i2c_client *client)
if (id) {
name = id->name;
chip_idx = id->driver_data;
- } else if (ACPI_HANDLE(&client->dev)) {
- name = ltr501_match_acpi_device(&client->dev, &chip_idx);
} else {
- return -ENODEV;
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ chip_idx = (intptr_t)ddata;
}
+ if (!name)
+ return -ENODEV;
data->chip_info = &ltr501_chip_info_tbl[chip_idx];
@@ -1610,9 +1597,9 @@ static int ltr501_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume);
static const struct acpi_device_id ltr_acpi_match[] = {
- { "LTER0501", ltr501 },
- { "LTER0559", ltr559 },
{ "LTER0301", ltr301 },
+ /* https://www.catalog.update.microsoft.com/Search.aspx?q=lter0303 */
+ { "LTER0303", ltr303 },
{ },
};
MODULE_DEVICE_TABLE(acpi, ltr_acpi_match);
diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c
index 37eecff571b9..dbec1e7cfeb8 100644
--- a/drivers/iio/light/ltrf216a.c
+++ b/drivers/iio/light/ltrf216a.c
@@ -561,6 +561,7 @@ MODULE_DEVICE_TABLE(i2c, ltrf216a_id);
static const struct of_device_id ltrf216a_of_match[] = {
{ .compatible = "liteon,ltr308", .data = &ltr308_chip_info },
{ .compatible = "liteon,ltrf216a", .data = &ltrf216a_chip_info },
+ /* For Valve's Steamdeck device, an ACPI platform using PRP0001 */
{ .compatible = "ltr,ltrf216a", .data = &ltrf216a_chip_info },
{}
};
diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c
index 3b92362675dc..8cd7f5664e5b 100644
--- a/drivers/iio/light/max44009.c
+++ b/drivers/iio/light/max44009.c
@@ -422,7 +422,7 @@ static int max44009_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct max44009_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 176e54bb48c3..65b295877b41 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -70,6 +70,35 @@
#define OPT3001_RESULT_READY_SHORT 150
#define OPT3001_RESULT_READY_LONG 1000
+struct opt3001_scale {
+ int val;
+ int val2;
+};
+
+struct opt3001_chip_info {
+ const struct iio_chan_spec (*channels)[2];
+ enum iio_chan_type chan_type;
+ int num_channels;
+
+ const struct opt3001_scale (*scales)[12];
+ /*
+ * Factor as specified by conversion equation in datasheet.
+ * eg. 0.01 (scaled to integer 10) for opt3001.
+ */
+ int factor_whole;
+ /*
+ * Factor to compensate for potentially scaled factor_whole.
+ */
+ int factor_integer;
+ /*
+ * Factor used to align decimal part of proccessed value to six decimal
+ * places.
+ */
+ int factor_decimal;
+
+ bool has_id;
+};
+
struct opt3001 {
struct i2c_client *client;
struct device *dev;
@@ -79,6 +108,7 @@ struct opt3001 {
bool result_ready;
wait_queue_head_t result_ready_queue;
u16 result;
+ const struct opt3001_chip_info *chip_info;
u32 int_time;
u32 mode;
@@ -92,11 +122,6 @@ struct opt3001 {
bool use_irq;
};
-struct opt3001_scale {
- int val;
- int val2;
-};
-
static const struct opt3001_scale opt3001_scales[] = {
{
.val = 40,
@@ -148,21 +173,68 @@ static const struct opt3001_scale opt3001_scales[] = {
},
};
+static const struct opt3001_scale opt3002_scales[] = {
+ {
+ .val = 4914,
+ .val2 = 0,
+ },
+ {
+ .val = 9828,
+ .val2 = 0,
+ },
+ {
+ .val = 19656,
+ .val2 = 0,
+ },
+ {
+ .val = 39312,
+ .val2 = 0,
+ },
+ {
+ .val = 78624,
+ .val2 = 0,
+ },
+ {
+ .val = 157248,
+ .val2 = 0,
+ },
+ {
+ .val = 314496,
+ .val2 = 0,
+ },
+ {
+ .val = 628992,
+ .val2 = 0,
+ },
+ {
+ .val = 1257984,
+ .val2 = 0,
+ },
+ {
+ .val = 2515968,
+ .val2 = 0,
+ },
+ {
+ .val = 5031936,
+ .val2 = 0,
+ },
+ {
+ .val = 10063872,
+ .val2 = 0,
+ },
+};
+
static int opt3001_find_scale(const struct opt3001 *opt, int val,
int val2, u8 *exponent)
{
int i;
-
- for (i = 0; i < ARRAY_SIZE(opt3001_scales); i++) {
- const struct opt3001_scale *scale = &opt3001_scales[i];
-
+ for (i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) {
+ const struct opt3001_scale *scale = &(*opt->chip_info->scales)[i];
/*
- * Combine the integer and micro parts for comparison
- * purposes. Use milli lux precision to avoid 32-bit integer
- * overflows.
+ * Compare the integer and micro parts to determine value scale.
*/
- if ((val * 1000 + val2 / 1000) <=
- (scale->val * 1000 + scale->val2 / 1000)) {
+ if (val < scale->val ||
+ (val == scale->val && val2 <= scale->val2)) {
*exponent = i;
return 0;
}
@@ -174,11 +246,14 @@ static int opt3001_find_scale(const struct opt3001 *opt, int val,
static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
u16 mantissa, int *val, int *val2)
{
- int lux;
+ int ret;
+ int whole = opt->chip_info->factor_whole;
+ int integer = opt->chip_info->factor_integer;
+ int decimal = opt->chip_info->factor_decimal;
- lux = 10 * (mantissa << exponent);
- *val = lux / 1000;
- *val2 = (lux - (*val * 1000)) * 1000;
+ ret = whole * (mantissa << exponent);
+ *val = ret / integer;
+ *val2 = (ret - (*val * integer)) * decimal;
}
static void opt3001_set_mode(struct opt3001 *opt, u16 *reg, u16 mode)
@@ -225,7 +300,18 @@ static const struct iio_chan_spec opt3001_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1),
};
-static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
+static const struct iio_chan_spec opt3002_channels[] = {
+ {
+ .type = IIO_INTENSITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME),
+ .event_spec = opt3001_event_spec,
+ .num_event_specs = ARRAY_SIZE(opt3001_event_spec),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
{
int ret;
u16 mantissa;
@@ -397,14 +483,15 @@ static int opt3001_read_raw(struct iio_dev *iio,
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
- if (chan->type != IIO_LIGHT)
+ if (chan->type != opt->chip_info->chan_type)
return -EINVAL;
mutex_lock(&opt->lock);
switch (mask) {
+ case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
- ret = opt3001_get_lux(opt, val, val2);
+ ret = opt3001_get_processed(opt, val, val2);
break;
case IIO_CHAN_INFO_INT_TIME:
ret = opt3001_get_int_time(opt, val, val2);
@@ -428,7 +515,7 @@ static int opt3001_write_raw(struct iio_dev *iio,
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
- if (chan->type != IIO_LIGHT)
+ if (chan->type != opt->chip_info->chan_type)
return -EINVAL;
if (mask != IIO_CHAN_INFO_INT_TIME)
@@ -479,6 +566,9 @@ static int opt3001_write_event_value(struct iio_dev *iio,
{
struct opt3001 *opt = iio_priv(iio);
int ret;
+ int whole;
+ int integer;
+ int decimal;
u16 mantissa;
u16 value;
@@ -497,7 +587,12 @@ static int opt3001_write_event_value(struct iio_dev *iio,
goto err;
}
- mantissa = (((val * 1000) + (val2 / 1000)) / 10) >> exponent;
+ whole = opt->chip_info->factor_whole;
+ integer = opt->chip_info->factor_integer;
+ decimal = opt->chip_info->factor_decimal;
+
+ mantissa = (((val * integer) + (val2 / decimal)) / whole) >> exponent;
+
value = (exponent << 12) | mantissa;
switch (dir) {
@@ -539,7 +634,7 @@ static int opt3001_read_event_config(struct iio_dev *iio,
static int opt3001_write_event_config(struct iio_dev *iio,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
@@ -610,7 +705,7 @@ static int opt3001_read_id(struct opt3001 *opt)
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_DEVICE_ID);
+ OPT3001_DEVICE_ID);
return ret;
}
@@ -692,6 +787,7 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
struct opt3001 *opt = iio_priv(iio);
int ret;
bool wake_result_ready_queue = false;
+ enum iio_chan_type chan_type = opt->chip_info->chan_type;
if (!opt->ok_to_ignore_lock)
mutex_lock(&opt->lock);
@@ -707,13 +803,13 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
OPT3001_CONFIGURATION_M_CONTINUOUS) {
if (ret & OPT3001_CONFIGURATION_FH)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
iio_get_time_ns(iio));
if (ret & OPT3001_CONFIGURATION_FL)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
iio_get_time_ns(iio));
@@ -755,22 +851,25 @@ static int opt3001_probe(struct i2c_client *client)
opt = iio_priv(iio);
opt->client = client;
opt->dev = dev;
+ opt->chip_info = i2c_get_match_data(client);
mutex_init(&opt->lock);
init_waitqueue_head(&opt->result_ready_queue);
i2c_set_clientdata(client, iio);
- ret = opt3001_read_id(opt);
- if (ret)
- return ret;
+ if (opt->chip_info->has_id) {
+ ret = opt3001_read_id(opt);
+ if (ret)
+ return ret;
+ }
ret = opt3001_configure(opt);
if (ret)
return ret;
iio->name = client->name;
- iio->channels = opt3001_channels;
- iio->num_channels = ARRAY_SIZE(opt3001_channels);
+ iio->channels = *opt->chip_info->channels;
+ iio->num_channels = opt->chip_info->num_channels;
iio->modes = INDIO_DIRECT_MODE;
iio->info = &opt3001_info;
@@ -825,14 +924,38 @@ static void opt3001_remove(struct i2c_client *client)
}
}
+static const struct opt3001_chip_info opt3001_chip_information = {
+ .channels = &opt3001_channels,
+ .chan_type = IIO_LIGHT,
+ .num_channels = ARRAY_SIZE(opt3001_channels),
+ .scales = &opt3001_scales,
+ .factor_whole = 10,
+ .factor_integer = 1000,
+ .factor_decimal = 1000,
+ .has_id = true,
+};
+
+static const struct opt3001_chip_info opt3002_chip_information = {
+ .channels = &opt3002_channels,
+ .chan_type = IIO_INTENSITY,
+ .num_channels = ARRAY_SIZE(opt3002_channels),
+ .scales = &opt3002_scales,
+ .factor_whole = 12,
+ .factor_integer = 10,
+ .factor_decimal = 100000,
+ .has_id = false,
+};
+
static const struct i2c_device_id opt3001_id[] = {
- { "opt3001" },
+ { "opt3001", (kernel_ulong_t)&opt3001_chip_information },
+ { "opt3002", (kernel_ulong_t)&opt3002_chip_information },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(i2c, opt3001_id);
static const struct of_device_id opt3001_of_match[] = {
- { .compatible = "ti,opt3001" },
+ { .compatible = "ti,opt3001", .data = &opt3001_chip_information },
+ { .compatible = "ti,opt3002", .data = &opt3002_chip_information },
{ }
};
MODULE_DEVICE_TABLE(of, opt3001_of_match);
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
index 78c08e0bd077..56f5fbbf79ac 100644
--- a/drivers/iio/light/rpr0521.c
+++ b/drivers/iio/light/rpr0521.c
@@ -438,18 +438,6 @@ static irqreturn_t rpr0521_drdy_irq_thread(int irq, void *private)
return IRQ_NONE;
}
-static irqreturn_t rpr0521_trigger_consumer_store_time(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
-
- /* Other trigger polls store time here. */
- if (!iio_trigger_using_own(indio_dev))
- pf->timestamp = iio_get_time_ns(indio_dev);
-
- return IRQ_WAKE_THREAD;
-}
-
static irqreturn_t rpr0521_trigger_consumer_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -1016,7 +1004,7 @@ static int rpr0521_probe(struct i2c_client *client)
/* Trigger consumer setup */
ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent,
indio_dev,
- rpr0521_trigger_consumer_store_time,
+ iio_pollfunc_store_time,
rpr0521_trigger_consumer_handler,
&rpr0521_buffer_setup_ops);
if (ret < 0) {
diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c
index fba3997574bb..f1fc8cb6f69a 100644
--- a/drivers/iio/light/st_uvis25_core.c
+++ b/drivers/iio/light/st_uvis25_core.c
@@ -174,8 +174,7 @@ static int st_uvis25_allocate_trigger(struct iio_dev *iio_dev)
unsigned long irq_type;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index ed20b6714546..b81cc44db43c 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -324,15 +324,12 @@ static int stk3310_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
int ret;
struct stk3310_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
- if (state < 0 || state > 7)
- return -EINVAL;
-
/* Set INT_PS value */
mutex_lock(&data->lock);
ret = regmap_field_write(data->reg_int_ps, state);
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
index 04452b4664f3..4186aac04902 100644
--- a/drivers/iio/light/tcs3472.c
+++ b/drivers/iio/light/tcs3472.c
@@ -327,7 +327,7 @@ static int tcs3472_read_event_config(struct iio_dev *indio_dev,
static int tcs3472_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tcs3472_data *data = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index 1a6f514bced6..f1fe7640fce6 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -630,7 +630,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c
index 850c2465992f..b81ca6f73f92 100644
--- a/drivers/iio/light/tsl2591.c
+++ b/drivers/iio/light/tsl2591.c
@@ -985,7 +985,7 @@ static int tsl2591_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct tsl2591_chip *chip = iio_priv(indio_dev);
struct i2c_client *client = chip->client;
diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c
index cab468a82b61..349afdcbe30d 100644
--- a/drivers/iio/light/tsl2772.c
+++ b/drivers/iio/light/tsl2772.c
@@ -1081,14 +1081,14 @@ static int tsl2772_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int val)
+ bool val)
{
struct tsl2772_chip *chip = iio_priv(indio_dev);
if (chan->type == IIO_INTENSITY)
- chip->settings.als_interrupt_en = val ? true : false;
+ chip->settings.als_interrupt_en = val;
else
- chip->settings.prox_interrupt_en = val ? true : false;
+ chip->settings.prox_interrupt_en = val;
return tsl2772_invoke_change(indio_dev);
}
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c
index de6967ac3b0b..c83114aed6b2 100644
--- a/drivers/iio/light/us5182d.c
+++ b/drivers/iio/light/us5182d.c
@@ -627,7 +627,7 @@ static int us5182d_read_event_config(struct iio_dev *indio_dev,
static int us5182d_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct us5182d_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 4e3641ff2ed4..e19199b17f2e 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -1456,7 +1456,7 @@ static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
switch (chan->type) {
case IIO_PROXIMITY:
@@ -1501,7 +1501,8 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
int ret = -EINVAL;
u16 val, mask;
diff --git a/drivers/iio/light/veml3235.c b/drivers/iio/light/veml3235.c
new file mode 100644
index 000000000000..66361c3012a3
--- /dev/null
+++ b/drivers/iio/light/veml3235.c
@@ -0,0 +1,495 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * VEML3235 Ambient Light Sensor
+ *
+ * Copyright (c) 2024, Javier Carrasco <javier.carrasco.cruz@gmail.com>
+ *
+ * Datasheet: https://www.vishay.com/docs/80131/veml3235.pdf
+ * Appnote-80222: https://www.vishay.com/docs/80222/designingveml3235.pdf
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define VEML3235_REG_CONF 0x00
+#define VEML3235_REG_WH_DATA 0x04
+#define VEML3235_REG_ALS_DATA 0x05
+#define VEML3235_REG_ID 0x09
+
+#define VEML3235_CONF_SD BIT(0)
+#define VEML3235_CONF_SD0 BIT(15)
+
+struct veml3235_rf {
+ struct regmap_field *it;
+ struct regmap_field *gain;
+ struct regmap_field *id;
+};
+
+struct veml3235_data {
+ struct i2c_client *client;
+ struct device *dev;
+ struct regmap *regmap;
+ struct veml3235_rf rf;
+};
+
+static const int veml3235_it_times[][2] = {
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
+
+static const int veml3235_scale_vals[] = { 1, 2, 4, 8 };
+
+static int veml3235_power_on(struct veml3235_data *data)
+{
+ int ret;
+
+ ret = regmap_clear_bits(data->regmap, VEML3235_REG_CONF,
+ VEML3235_CONF_SD | VEML3235_CONF_SD0);
+ if (ret)
+ return ret;
+
+ /* Wait 4 ms to let processor & oscillator start correctly */
+ fsleep(4000);
+
+ return 0;
+}
+
+static int veml3235_shut_down(struct veml3235_data *data)
+{
+ return regmap_set_bits(data->regmap, VEML3235_REG_CONF,
+ VEML3235_CONF_SD | VEML3235_CONF_SD0);
+}
+
+static void veml3235_shut_down_action(void *data)
+{
+ veml3235_shut_down(data);
+}
+
+enum veml3235_chan {
+ CH_ALS,
+ CH_WHITE,
+};
+
+static const struct iio_chan_spec veml3235_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel = CH_ALS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .channel = CH_WHITE,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static const struct regmap_config veml3235_regmap_config = {
+ .name = "veml3235_regmap",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = VEML3235_REG_ID,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+static int veml3235_get_it(struct veml3235_data *data, int *val, int *val2)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.it, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg) {
+ case 0:
+ *val2 = 50000;
+ break;
+ case 1:
+ *val2 = 100000;
+ break;
+ case 2:
+ *val2 = 200000;
+ break;
+ case 3:
+ *val2 = 400000;
+ break;
+ case 4:
+ *val2 = 800000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = 0;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int veml3235_set_it(struct iio_dev *indio_dev, int val, int val2)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ int ret, new_it;
+
+ if (val)
+ return -EINVAL;
+
+ switch (val2) {
+ case 50000:
+ new_it = 0x00;
+ break;
+ case 100000:
+ new_it = 0x01;
+ break;
+ case 200000:
+ new_it = 0x02;
+ break;
+ case 400000:
+ new_it = 0x03;
+ break;
+ case 800000:
+ new_it = 0x04;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_field_write(data->rf.it, new_it);
+ if (ret) {
+ dev_err(data->dev,
+ "failed to update integration time: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int veml3235_set_gain(struct iio_dev *indio_dev, int val, int val2)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ int ret, new_gain;
+
+ if (val2 != 0)
+ return -EINVAL;
+
+ switch (val) {
+ case 1:
+ new_gain = 0x00;
+ break;
+ case 2:
+ new_gain = 0x01;
+ break;
+ case 4:
+ new_gain = 0x03;
+ break;
+ case 8:
+ new_gain = 0x07;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_field_write(data->rf.gain, new_gain);
+ if (ret) {
+ dev_err(data->dev, "failed to set gain: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int veml3235_get_gain(struct veml3235_data *data, int *val)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.gain, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read gain %d\n", ret);
+ return ret;
+ }
+
+ switch (reg & 0x03) {
+ case 0:
+ *val = 1;
+ break;
+ case 1:
+ *val = 2;
+ break;
+ case 3:
+ *val = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Double gain */
+ if (reg & 0x04)
+ *val *= 2;
+
+ return IIO_VAL_INT;
+}
+
+static int veml3235_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ struct regmap *regmap = data->regmap;
+ int ret, reg;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = regmap_read(regmap, VEML3235_REG_ALS_DATA, &reg);
+ if (ret < 0)
+ return ret;
+
+ *val = reg;
+ return IIO_VAL_INT;
+ case IIO_INTENSITY:
+ ret = regmap_read(regmap, VEML3235_REG_WH_DATA, &reg);
+ if (ret < 0)
+ return ret;
+
+ *val = reg;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml3235_get_it(data, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return veml3235_get_gain(data, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml3235_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)&veml3235_it_times;
+ *length = 2 * ARRAY_SIZE(veml3235_it_times);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)&veml3235_scale_vals;
+ *length = ARRAY_SIZE(veml3235_scale_vals);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml3235_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml3235_set_it(indio_dev, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return veml3235_set_gain(indio_dev, val, val2);
+ }
+
+ return -EINVAL;
+}
+
+static void veml3235_read_id(struct veml3235_data *data)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.id, &reg);
+ if (ret) {
+ dev_info(data->dev, "failed to read ID\n");
+ return;
+ }
+
+ if (reg != 0x35)
+ dev_info(data->dev, "Unknown ID %d\n", reg);
+}
+
+static const struct reg_field veml3235_rf_it =
+ REG_FIELD(VEML3235_REG_CONF, 4, 6);
+
+static const struct reg_field veml3235_rf_gain =
+ REG_FIELD(VEML3235_REG_CONF, 11, 13);
+
+static const struct reg_field veml3235_rf_id =
+ REG_FIELD(VEML3235_REG_ID, 0, 7);
+
+static int veml3235_regfield_init(struct veml3235_data *data)
+{
+ struct regmap *regmap = data->regmap;
+ struct device *dev = data->dev;
+ struct regmap_field *rm_field;
+ struct veml3235_rf *rf = &data->rf;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_it);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->it = rm_field;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_gain);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->gain = rm_field;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_id);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->id = rm_field;
+
+ return 0;
+}
+
+static int veml3235_hw_init(struct iio_dev *indio_dev)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
+ int ret;
+
+ /* Set gain to 1 and integration time to 100 ms */
+ ret = regmap_field_write(data->rf.gain, 0x00);
+ if (ret)
+ return dev_err_probe(data->dev, ret, "failed to set gain\n");
+
+ ret = regmap_field_write(data->rf.it, 0x01);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "failed to set integration time\n");
+
+ ret = veml3235_power_on(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to power on\n");
+
+ return devm_add_action_or_reset(dev, veml3235_shut_down_action, data);
+}
+
+static const struct iio_info veml3235_info = {
+ .read_raw = veml3235_read_raw,
+ .read_avail = veml3235_read_avail,
+ .write_raw = veml3235_write_raw,
+};
+
+static int veml3235_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct veml3235_data *data;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(client, &veml3235_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "failed to setup regmap\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ data->dev = dev;
+ data->regmap = regmap;
+
+ ret = veml3235_regfield_init(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init regfield\n");
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable regulator\n");
+
+ indio_dev->name = "veml3235";
+ indio_dev->channels = veml3235_channels;
+ indio_dev->num_channels = ARRAY_SIZE(veml3235_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &veml3235_info;
+
+ veml3235_read_id(data);
+
+ ret = veml3235_hw_init(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static int veml3235_runtime_suspend(struct device *dev)
+{
+ struct veml3235_data *data = iio_priv(dev_get_drvdata(dev));
+ int ret;
+
+ ret = veml3235_shut_down(data);
+ if (ret < 0)
+ dev_err(data->dev, "failed to suspend: %d\n", ret);
+
+ return ret;
+}
+
+static int veml3235_runtime_resume(struct device *dev)
+{
+ struct veml3235_data *data = iio_priv(dev_get_drvdata(dev));
+ int ret;
+
+ ret = veml3235_power_on(data);
+ if (ret < 0)
+ dev_err(data->dev, "failed to resume: %d\n", ret);
+
+ return ret;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(veml3235_pm_ops, veml3235_runtime_suspend,
+ veml3235_runtime_resume, NULL);
+
+static const struct of_device_id veml3235_of_match[] = {
+ { .compatible = "vishay,veml3235" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, veml3235_of_match);
+
+static const struct i2c_device_id veml3235_id[] = {
+ { "veml3235" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, veml3235_id);
+
+static struct i2c_driver veml3235_driver = {
+ .driver = {
+ .name = "veml3235",
+ .of_match_table = veml3235_of_match,
+ .pm = pm_ptr(&veml3235_pm_ops),
+ },
+ .probe = veml3235_probe,
+ .id_table = veml3235_id,
+};
+module_i2c_driver(veml3235_driver);
+
+MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gmail.com>");
+MODULE_DESCRIPTION("VEML3235 Ambient Light Sensor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c
index 621428885455..ccb43dfd5cf7 100644
--- a/drivers/iio/light/veml6030.c
+++ b/drivers/iio/light/veml6030.c
@@ -1,19 +1,30 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * VEML6030 Ambient Light Sensor
+ * VEML6030, VMEL6035 and VEML7700 Ambient Light Sensors
*
* Copyright (c) 2019, Rishi Gupta <gupt21@gmail.com>
*
+ * VEML6030:
* Datasheet: https://www.vishay.com/docs/84366/veml6030.pdf
* Appnote-84367: https://www.vishay.com/docs/84367/designingveml6030.pdf
+ *
+ * VEML6035:
+ * Datasheet: https://www.vishay.com/docs/84889/veml6035.pdf
+ * Appnote-84944: https://www.vishay.com/docs/84944/designingveml6035.pdf
+ *
+ * VEML7700:
+ * Datasheet: https://www.vishay.com/docs/84286/veml7700.pdf
+ * Appnote-84323: https://www.vishay.com/docs/84323/designingveml7700.pdf
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -38,16 +49,35 @@
#define VEML6030_ALS_INT_EN BIT(1)
#define VEML6030_ALS_SD BIT(0)
+#define VEML6035_GAIN_M GENMASK(12, 10)
+#define VEML6035_GAIN BIT(10)
+#define VEML6035_DG BIT(11)
+#define VEML6035_SENS BIT(12)
+#define VEML6035_INT_CHAN BIT(3)
+#define VEML6035_CHAN_EN BIT(2)
+
+struct veml603x_chip {
+ const char *name;
+ const int(*scale_vals)[][2];
+ const int num_scale_vals;
+ const struct iio_chan_spec *channels;
+ const int num_channels;
+ int (*hw_init)(struct iio_dev *indio_dev, struct device *dev);
+ int (*set_info)(struct iio_dev *indio_dev);
+ int (*set_als_gain)(struct iio_dev *indio_dev, int val, int val2);
+ int (*get_als_gain)(struct iio_dev *indio_dev, int *val, int *val2);
+};
+
/*
* The resolution depends on both gain and integration time. The
* cur_resolution stores one of the resolution mentioned in the
* table during startup and gets updated whenever integration time
* or gain is changed.
*
- * Table 'resolution and maximum detection range' in appnote 84367
+ * Table 'resolution and maximum detection range' in the appnotes
* is visualized as a 2D array. The cur_gain stores index of gain
- * in this table (0-3) while the cur_integration_time holds index
- * of integration time (0-5).
+ * in this table (0-3 for VEML6030, 0-5 for VEML6035) while the
+ * cur_integration_time holds index of integration time (0-5).
*/
struct veml6030_data {
struct i2c_client *client;
@@ -55,27 +85,37 @@ struct veml6030_data {
int cur_resolution;
int cur_gain;
int cur_integration_time;
+ const struct veml603x_chip *chip;
};
-/* Integration time available in seconds */
-static IIO_CONST_ATTR(in_illuminance_integration_time_available,
- "0.025 0.05 0.1 0.2 0.4 0.8");
+static const int veml6030_it_times[][2] = {
+ { 0, 25000 },
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
/*
* Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is
- * ALS gain x (1/4), 1.0 = ALS gain x 1 and 2.0 is ALS gain x 2.
+ * ALS gain x (1/4), 0.5 is ALS gain x (1/2), 1.0 is ALS gain x 1,
+ * 2.0 is ALS gain x2, and 4.0 is ALS gain x 4.
*/
-static IIO_CONST_ATTR(in_illuminance_scale_available,
- "0.125 0.25 1.0 2.0");
-
-static struct attribute *veml6030_attributes[] = {
- &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
- &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
- NULL
+static const int veml6030_scale_vals[][2] = {
+ { 0, 125000 },
+ { 0, 250000 },
+ { 1, 0 },
+ { 2, 0 },
};
-static const struct attribute_group veml6030_attr_group = {
- .attrs = veml6030_attributes,
+static const int veml6035_scale_vals[][2] = {
+ { 0, 125000 },
+ { 0, 250000 },
+ { 0, 500000 },
+ { 1, 0 },
+ { 2, 0 },
+ { 4, 0 },
};
/*
@@ -143,14 +183,23 @@ static const struct attribute_group veml6030_event_attr_group = {
static int veml6030_als_pwr_on(struct veml6030_data *data)
{
- return regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,
- VEML6030_ALS_SD);
+ int ret;
+
+ ret = regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6030_ALS_SD);
+ if (ret)
+ return ret;
+
+ /* Wait 4 ms to let processor & oscillator start correctly */
+ fsleep(4000);
+
+ return 0;
}
static int veml6030_als_shut_down(struct veml6030_data *data)
{
- return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
- VEML6030_ALS_SD, 1);
+ return regmap_set_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6030_ALS_SD);
}
static void veml6030_als_shut_down_action(void *data)
@@ -189,6 +238,8 @@ static const struct iio_chan_spec veml6030_channels[] = {
BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_INT_TIME) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
.event_spec = veml6030_event_spec,
.num_event_specs = ARRAY_SIZE(veml6030_event_spec),
},
@@ -198,7 +249,34 @@ static const struct iio_chan_spec veml6030_channels[] = {
.modified = 1,
.channel2 = IIO_MOD_LIGHT_BOTH,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_PROCESSED),
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static const struct iio_chan_spec veml7700_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel = CH_ALS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .channel = CH_WHITE,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
},
};
@@ -371,6 +449,21 @@ static int veml6030_write_persistence(struct iio_dev *indio_dev,
return ret;
}
+/*
+ * Cache currently set gain & update resolution. For every
+ * increase in the gain to next level, resolution is halved
+ * and vice-versa.
+ */
+static void veml6030_update_gain_res(struct veml6030_data *data, int gain_idx)
+{
+ if (data->cur_gain < gain_idx)
+ data->cur_resolution <<= gain_idx - data->cur_gain;
+ else if (data->cur_gain > gain_idx)
+ data->cur_resolution >>= data->cur_gain - gain_idx;
+
+ data->cur_gain = gain_idx;
+}
+
static int veml6030_set_als_gain(struct iio_dev *indio_dev,
int val, int val2)
{
@@ -401,19 +494,49 @@ static int veml6030_set_als_gain(struct iio_dev *indio_dev,
return ret;
}
- /*
- * Cache currently set gain & update resolution. For every
- * increase in the gain to next level, resolution is halved
- * and vice-versa.
- */
- if (data->cur_gain < gain_idx)
- data->cur_resolution <<= gain_idx - data->cur_gain;
- else if (data->cur_gain > gain_idx)
- data->cur_resolution >>= data->cur_gain - gain_idx;
+ veml6030_update_gain_res(data, gain_idx);
- data->cur_gain = gain_idx;
+ return 0;
+}
- return ret;
+static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2)
+{
+ int ret, new_gain, gain_idx;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ if (val == 0 && val2 == 125000) {
+ new_gain = VEML6035_SENS;
+ gain_idx = 5;
+ } else if (val == 0 && val2 == 250000) {
+ new_gain = VEML6035_SENS | VEML6035_GAIN;
+ gain_idx = 4;
+ } else if (val == 0 && val2 == 500000) {
+ new_gain = VEML6035_SENS | VEML6035_GAIN |
+ VEML6035_DG;
+ gain_idx = 3;
+ } else if (val == 1 && val2 == 0) {
+ new_gain = 0x0000;
+ gain_idx = 2;
+ } else if (val == 2 && val2 == 0) {
+ new_gain = VEML6035_GAIN;
+ gain_idx = 1;
+ } else if (val == 4 && val2 == 0) {
+ new_gain = VEML6035_GAIN | VEML6035_DG;
+ gain_idx = 0;
+ } else {
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6035_GAIN_M, new_gain);
+ if (ret) {
+ dev_err(&data->client->dev, "can't set als gain %d\n", ret);
+ return ret;
+ }
+
+ veml6030_update_gain_res(data, gain_idx);
+
+ return 0;
}
static int veml6030_get_als_gain(struct iio_dev *indio_dev,
@@ -453,6 +576,52 @@ static int veml6030_get_als_gain(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_MICRO;
}
+static int veml6035_get_als_gain(struct iio_dev *indio_dev, int *val, int *val2)
+{
+ int ret, reg;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
+ if (ret) {
+ dev_err(&data->client->dev,
+ "can't read als conf register %d\n", ret);
+ return ret;
+ }
+
+ switch (FIELD_GET(VEML6035_GAIN_M, reg)) {
+ case 0:
+ *val = 1;
+ *val2 = 0;
+ break;
+ case 1:
+ case 2:
+ *val = 2;
+ *val2 = 0;
+ break;
+ case 3:
+ *val = 4;
+ *val2 = 0;
+ break;
+ case 4:
+ *val = 0;
+ *val2 = 125000;
+ break;
+ case 5:
+ case 6:
+ *val = 0;
+ *val2 = 250000;
+ break;
+ case 7:
+ *val = 0;
+ *val2 = 500000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
static int veml6030_read_thresh(struct iio_dev *indio_dev,
int *val, int *val2, int dir)
{
@@ -533,48 +702,54 @@ static int veml6030_read_raw(struct iio_dev *indio_dev,
dev_err(dev, "can't read white data %d\n", ret);
return ret;
}
- if (mask == IIO_CHAN_INFO_PROCESSED) {
- *val = (reg * data->cur_resolution) / 10000;
- *val2 = (reg * data->cur_resolution) % 10000;
- return IIO_VAL_INT_PLUS_MICRO;
- }
*val = reg;
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_INT_TIME:
- if (chan->type == IIO_LIGHT)
- return veml6030_get_intgrn_tm(indio_dev, val, val2);
- return -EINVAL;
+ return veml6030_get_intgrn_tm(indio_dev, val, val2);
case IIO_CHAN_INFO_SCALE:
- if (chan->type == IIO_LIGHT)
- return veml6030_get_als_gain(indio_dev, val, val2);
- return -EINVAL;
+ return data->chip->get_als_gain(indio_dev, val, val2);
default:
return -EINVAL;
}
}
+static int veml6030_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)&veml6030_it_times;
+ *length = 2 * ARRAY_SIZE(veml6030_it_times);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)*data->chip->scale_vals;
+ *length = 2 * data->chip->num_scale_vals;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ }
+
+ return -EINVAL;
+}
+
static int veml6030_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
+ struct veml6030_data *data = iio_priv(indio_dev);
+
switch (mask) {
case IIO_CHAN_INFO_INT_TIME:
- switch (chan->type) {
- case IIO_LIGHT:
- return veml6030_set_intgrn_tm(indio_dev, val, val2);
- default:
- return -EINVAL;
- }
+ return veml6030_set_intgrn_tm(indio_dev, val, val2);
case IIO_CHAN_INFO_SCALE:
- switch (chan->type) {
- case IIO_LIGHT:
- return veml6030_set_als_gain(indio_dev, val, val2);
- default:
- return -EINVAL;
- }
+ return data->chip->set_als_gain(indio_dev, val, val2);
default:
return -EINVAL;
}
@@ -646,14 +821,11 @@ static int veml6030_read_interrupt_config(struct iio_dev *indio_dev,
*/
static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
int ret;
struct veml6030_data *data = iio_priv(indio_dev);
- if (state < 0 || state > 1)
- return -EINVAL;
-
ret = veml6030_als_shut_down(data);
if (ret < 0) {
dev_err(&data->client->dev,
@@ -673,19 +845,19 @@ static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
static const struct iio_info veml6030_info = {
.read_raw = veml6030_read_raw,
+ .read_avail = veml6030_read_avail,
.write_raw = veml6030_write_raw,
.read_event_value = veml6030_read_event_val,
.write_event_value = veml6030_write_event_val,
.read_event_config = veml6030_read_interrupt_config,
.write_event_config = veml6030_write_interrupt_config,
- .attrs = &veml6030_attr_group,
.event_attrs = &veml6030_event_attr_group,
};
static const struct iio_info veml6030_info_no_irq = {
.read_raw = veml6030_read_raw,
+ .read_avail = veml6030_read_avail,
.write_raw = veml6030_write_raw,
- .attrs = &veml6030_attr_group,
};
static irqreturn_t veml6030_event_handler(int irq, void *private)
@@ -717,65 +889,82 @@ static irqreturn_t veml6030_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
+static int veml6030_set_info(struct iio_dev *indio_dev)
+{
+ struct veml6030_data *data = iio_priv(indio_dev);
+ struct i2c_client *client = data->client;
+ int ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, veml6030_event_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "irq %d request failed\n",
+ client->irq);
+
+ indio_dev->info = &veml6030_info;
+ } else {
+ indio_dev->info = &veml6030_info_no_irq;
+ }
+
+ return 0;
+}
+
+static int veml7700_set_info(struct iio_dev *indio_dev)
+{
+ indio_dev->info = &veml6030_info_no_irq;
+
+ return 0;
+}
+
/*
* Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,
* persistence to 1 x integration time and the threshold
* interrupt disabled by default. First shutdown the sensor,
* update registers and then power on the sensor.
*/
-static int veml6030_hw_init(struct iio_dev *indio_dev)
+static int veml6030_hw_init(struct iio_dev *indio_dev, struct device *dev)
{
int ret, val;
struct veml6030_data *data = iio_priv(indio_dev);
- struct i2c_client *client = data->client;
ret = veml6030_als_shut_down(data);
- if (ret) {
- dev_err(&client->dev, "can't shutdown als %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't shutdown als\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001);
- if (ret) {
- dev_err(&client->dev, "can't setup als configs %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup als configs\n");
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
VEML6030_PSM | VEML6030_PSM_EN, 0x03);
- if (ret) {
- dev_err(&client->dev, "can't setup default PSM %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup default PSM\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
- if (ret) {
- dev_err(&client->dev, "can't setup high threshold %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup high threshold\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
- if (ret) {
- dev_err(&client->dev, "can't setup low threshold %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup low threshold\n");
ret = veml6030_als_pwr_on(data);
- if (ret) {
- dev_err(&client->dev, "can't poweron als %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't poweron als\n");
- /* Wait 4 ms to let processor & oscillator start correctly */
- usleep_range(4000, 4002);
+ ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data);
+ if (ret < 0)
+ return ret;
/* Clear stale interrupt status bits if any during start */
ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
- if (ret < 0) {
- dev_err(&client->dev,
- "can't clear als interrupt status %d\n", ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "can't clear als interrupt status\n");
/* Cache currently active measurement parameters */
data->cur_gain = 3;
@@ -785,6 +974,62 @@ static int veml6030_hw_init(struct iio_dev *indio_dev)
return ret;
}
+/*
+ * Set ALS gain to 1/8, integration time to 100 ms, ALS and WHITE
+ * channel enabled, ALS channel interrupt, PSM enabled,
+ * PSM_WAIT = 0.8 s, persistence to 1 x integration time and the
+ * threshold interrupt disabled by default. First shutdown the sensor,
+ * update registers and then power on the sensor.
+ */
+static int veml6035_hw_init(struct iio_dev *indio_dev, struct device *dev)
+{
+ int ret, val;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ ret = veml6030_als_shut_down(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't shutdown als\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6035_SENS | VEML6035_CHAN_EN | VEML6030_ALS_SD);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup als configs\n");
+
+ ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
+ VEML6030_PSM | VEML6030_PSM_EN, 0x03);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup default PSM\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup high threshold\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup low threshold\n");
+
+ ret = veml6030_als_pwr_on(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't poweron als\n");
+
+ ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data);
+ if (ret < 0)
+ return ret;
+
+ /* Clear stale interrupt status bits if any during start */
+ ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "can't clear als interrupt status\n");
+
+ /* Cache currently active measurement parameters */
+ data->cur_gain = 5;
+ data->cur_resolution = 1024;
+ data->cur_integration_time = 3;
+
+ return 0;
+}
+
static int veml6030_probe(struct i2c_client *client)
{
int ret;
@@ -792,16 +1037,14 @@ static int veml6030_probe(struct i2c_client *client)
struct iio_dev *indio_dev;
struct regmap *regmap;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "i2c adapter doesn't support plain i2c\n");
- return -EOPNOTSUPP;
- }
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return dev_err_probe(&client->dev, -EOPNOTSUPP,
+ "i2c adapter doesn't support plain i2c\n");
regmap = devm_regmap_init_i2c(client, &veml6030_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&client->dev, "can't setup regmap\n");
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(regmap),
+ "can't setup regmap\n");
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -812,32 +1055,25 @@ static int veml6030_probe(struct i2c_client *client)
data->client = client;
data->regmap = regmap;
- indio_dev->name = "veml6030";
- indio_dev->channels = veml6030_channels;
- indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
- indio_dev->modes = INDIO_DIRECT_MODE;
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "failed to enable regulator\n");
- if (client->irq) {
- ret = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, veml6030_event_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "veml6030", indio_dev);
- if (ret < 0) {
- dev_err(&client->dev,
- "irq %d request failed\n", client->irq);
- return ret;
- }
- indio_dev->info = &veml6030_info;
- } else {
- indio_dev->info = &veml6030_info_no_irq;
- }
+ data->chip = i2c_get_match_data(client);
+ if (!data->chip)
+ return -EINVAL;
+
+ indio_dev->name = data->chip->name;
+ indio_dev->channels = data->chip->channels;
+ indio_dev->num_channels = data->chip->num_channels;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- ret = veml6030_hw_init(indio_dev);
+ ret = data->chip->set_info(indio_dev);
if (ret < 0)
return ret;
- ret = devm_add_action_or_reset(&client->dev,
- veml6030_als_shut_down_action, data);
+ ret = data->chip->hw_init(indio_dev, &client->dev);
if (ret < 0)
return ret;
@@ -873,14 +1109,63 @@ static int veml6030_runtime_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(veml6030_pm_ops, veml6030_runtime_suspend,
veml6030_runtime_resume, NULL);
+static const struct veml603x_chip veml6030_chip = {
+ .name = "veml6030",
+ .scale_vals = &veml6030_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
+ .hw_init = veml6030_hw_init,
+ .set_info = veml6030_set_info,
+ .set_als_gain = veml6030_set_als_gain,
+ .get_als_gain = veml6030_get_als_gain,
+};
+
+static const struct veml603x_chip veml6035_chip = {
+ .name = "veml6035",
+ .scale_vals = &veml6035_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6035_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
+ .hw_init = veml6035_hw_init,
+ .set_info = veml6030_set_info,
+ .set_als_gain = veml6035_set_als_gain,
+ .get_als_gain = veml6035_get_als_gain,
+};
+
+static const struct veml603x_chip veml7700_chip = {
+ .name = "veml7700",
+ .scale_vals = &veml6030_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml7700_channels,
+ .num_channels = ARRAY_SIZE(veml7700_channels),
+ .hw_init = veml6030_hw_init,
+ .set_info = veml7700_set_info,
+ .set_als_gain = veml6030_set_als_gain,
+ .get_als_gain = veml6030_get_als_gain,
+};
+
static const struct of_device_id veml6030_of_match[] = {
- { .compatible = "vishay,veml6030" },
+ {
+ .compatible = "vishay,veml6030",
+ .data = &veml6030_chip,
+ },
+ {
+ .compatible = "vishay,veml6035",
+ .data = &veml6035_chip,
+ },
+ {
+ .compatible = "vishay,veml7700",
+ .data = &veml7700_chip,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, veml6030_of_match);
static const struct i2c_device_id veml6030_id[] = {
- { "veml6030" },
+ { "veml6030", (kernel_ulong_t)&veml6030_chip},
+ { "veml6035", (kernel_ulong_t)&veml6035_chip},
+ { "veml7700", (kernel_ulong_t)&veml7700_chip},
{ }
};
MODULE_DEVICE_TABLE(i2c, veml6030_id);
diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c
index f8321d346d77..6d4483c85f30 100644
--- a/drivers/iio/light/veml6070.c
+++ b/drivers/iio/light/veml6070.c
@@ -6,14 +6,16 @@
*
* IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39)
*
- * TODO: integration time, ACK signal
+ * TODO: ACK signal
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/delay.h>
+#include <linux/units.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -28,50 +30,113 @@
#define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */
#define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */
-#define VEML6070_IT_10 0x04 /* integration time 1x */
+#define VEML6070_IT_05 0x00
+#define VEML6070_IT_10 0x01
+#define VEML6070_IT_20 0x02
+#define VEML6070_IT_40 0x03
+
+#define VEML6070_MIN_RSET_KOHM 75
+#define VEML6070_MIN_IT_US 15625 /* Rset = 75 kohm, IT = 1/2 */
struct veml6070_data {
struct i2c_client *client1;
struct i2c_client *client2;
u8 config;
struct mutex lock;
+ u32 rset;
+ int it[4][2];
};
+static int veml6070_calc_it(struct device *dev, struct veml6070_data *data)
+{
+ int i, tmp_it;
+
+ data->rset = 270000;
+ device_property_read_u32(dev, "vishay,rset-ohms", &data->rset);
+
+ if (data->rset < 75000 || data->rset > 1200000)
+ return dev_err_probe(dev, -EINVAL, "Rset out of range\n");
+
+ /*
+ * convert to kohm to avoid overflows and work with the same units as
+ * in the datasheet and simplify UVI operations.
+ */
+ data->rset /= KILO;
+
+ tmp_it = VEML6070_MIN_IT_US * data->rset / VEML6070_MIN_RSET_KOHM;
+ for (i = 0; i < ARRAY_SIZE(data->it); i++) {
+ data->it[i][0] = (tmp_it << i) / MICRO;
+ data->it[i][1] = (tmp_it << i) % MICRO;
+ }
+
+ return 0;
+}
+
+static int veml6070_get_it(struct veml6070_data *data, int *val, int *val2)
+{
+ int it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config);
+
+ *val = data->it[it_idx][0];
+ *val2 = data->it[it_idx][1];
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int veml6070_set_it(struct veml6070_data *data, int val, int val2)
+{
+ int it_idx;
+
+ for (it_idx = 0; it_idx < ARRAY_SIZE(data->it); it_idx++) {
+ if (data->it[it_idx][0] == val && data->it[it_idx][1] == val2)
+ break;
+ }
+
+ if (it_idx >= ARRAY_SIZE(data->it))
+ return -EINVAL;
+
+ data->config = (data->config & ~VEML6070_COMMAND_IT) |
+ FIELD_PREP(VEML6070_COMMAND_IT, it_idx);
+
+ return i2c_smbus_write_byte(data->client1, data->config);
+}
+
static int veml6070_read(struct veml6070_data *data)
{
- int ret;
+ int ret, it_ms, val, val2;
u8 msb, lsb;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
/* disable shutdown */
ret = i2c_smbus_write_byte(data->client1,
data->config & ~VEML6070_COMMAND_SD);
if (ret < 0)
- goto out;
+ return ret;
- msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */
+ veml6070_get_it(data, &val, &val2);
+ it_ms = val * MILLI + val2 / (MICRO / MILLI);
+ msleep(it_ms + 10);
ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */
if (ret < 0)
- goto out;
+ return ret;
+
msb = ret;
ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */
if (ret < 0)
- goto out;
+ return ret;
+
lsb = ret;
/* shutdown again */
ret = i2c_smbus_write_byte(data->client1, data->config);
if (ret < 0)
- goto out;
+ return ret;
ret = (msb << 8) | lsb;
-out:
- mutex_unlock(&data->lock);
- return ret;
+ return 0;
}
static const struct iio_chan_spec veml6070_channels[] = {
@@ -80,26 +145,37 @@ static const struct iio_chan_spec veml6070_channels[] = {
.modified = 1,
.channel2 = IIO_MOD_LIGHT_UV,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
},
{
.type = IIO_UVINDEX,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
}
};
-static int veml6070_to_uv_index(unsigned val)
+static int veml6070_to_uv_index(struct veml6070_data *data, unsigned int val)
{
/*
* conversion of raw UV intensity values to UV index depends on
* integration time (IT) and value of the resistor connected to
- * the RSET pin (default: 270 KOhm)
+ * the RSET pin.
*/
- unsigned uvi[11] = {
+ unsigned int uvi[11] = {
187, 373, 560, /* low */
746, 933, 1120, /* moderate */
1308, 1494, /* high */
1681, 1868, 2054}; /* very high */
- int i;
+ int i, it_idx;
+
+ it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config);
+
+ if (!it_idx)
+ val = (val * 270 / data->rset) << 1;
+ else
+ val = (val * 270 / data->rset) >> (it_idx - 1);
for (i = 0; i < ARRAY_SIZE(uvi); i++)
if (val <= uvi[i])
@@ -122,10 +198,44 @@ static int veml6070_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
if (mask == IIO_CHAN_INFO_PROCESSED)
- *val = veml6070_to_uv_index(ret);
+ *val = veml6070_to_uv_index(data, ret);
else
*val = ret;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml6070_get_it(data, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml6070_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct veml6070_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)data->it;
+ *length = 2 * ARRAY_SIZE(data->it);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml6070_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct veml6070_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml6070_set_it(data, val, val2);
default:
return -EINVAL;
}
@@ -133,8 +243,17 @@ static int veml6070_read_raw(struct iio_dev *indio_dev,
static const struct iio_info veml6070_info = {
.read_raw = veml6070_read_raw,
+ .read_avail = veml6070_read_avail,
+ .write_raw = veml6070_write_raw,
};
+static void veml6070_i2c_unreg(void *p)
+{
+ struct veml6070_data *data = p;
+
+ i2c_unregister_device(data->client2);
+}
+
static int veml6070_probe(struct i2c_client *client)
{
struct veml6070_data *data;
@@ -156,36 +275,30 @@ static int veml6070_probe(struct i2c_client *client)
indio_dev->name = VEML6070_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
- if (IS_ERR(data->client2)) {
- dev_err(&client->dev, "i2c device for second chip address failed\n");
- return PTR_ERR(data->client2);
- }
-
- data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD |
- VEML6070_COMMAND_SD;
- ret = i2c_smbus_write_byte(data->client1, data->config);
+ ret = veml6070_calc_it(&client->dev, data);
if (ret < 0)
- goto fail;
+ return ret;
- ret = iio_device_register(indio_dev);
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
if (ret < 0)
- goto fail;
+ return ret;
- return ret;
+ data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
+ if (IS_ERR(data->client2))
+ return dev_err_probe(&client->dev, PTR_ERR(data->client2),
+ "i2c device for second chip address failed\n");
-fail:
- i2c_unregister_device(data->client2);
- return ret;
-}
+ data->config = FIELD_PREP(VEML6070_COMMAND_IT, VEML6070_IT_10) |
+ VEML6070_COMMAND_RSRVD | VEML6070_COMMAND_SD;
+ ret = i2c_smbus_write_byte(data->client1, data->config);
+ if (ret < 0)
+ return ret;
-static void veml6070_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct veml6070_data *data = iio_priv(indio_dev);
+ ret = devm_add_action_or_reset(&client->dev, veml6070_i2c_unreg, data);
+ if (ret < 0)
+ return ret;
- iio_device_unregister(indio_dev);
- i2c_unregister_device(data->client2);
+ return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id veml6070_id[] = {
@@ -194,12 +307,18 @@ static const struct i2c_device_id veml6070_id[] = {
};
MODULE_DEVICE_TABLE(i2c, veml6070_id);
+static const struct of_device_id veml6070_of_match[] = {
+ { .compatible = "vishay,veml6070" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, veml6070_of_match);
+
static struct i2c_driver veml6070_driver = {
.driver = {
.name = VEML6070_DRV_NAME,
+ .of_match_table = veml6070_of_match,
},
.probe = veml6070_probe,
- .remove = veml6070_remove,
.id_table = veml6070_id,
};
diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c
index a1b2b3c0b4c8..6e2183a4243e 100644
--- a/drivers/iio/light/vl6180.c
+++ b/drivers/iio/light/vl6180.c
@@ -25,6 +25,10 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#define VL6180_DRV_NAME "vl6180"
@@ -38,7 +42,9 @@
#define VL6180_OUT_OF_RESET 0x016
#define VL6180_HOLD 0x017
#define VL6180_RANGE_START 0x018
+#define VL6180_RANGE_INTER_MEAS_TIME 0x01b
#define VL6180_ALS_START 0x038
+#define VL6180_ALS_INTER_MEAS_TIME 0x03e
#define VL6180_ALS_GAIN 0x03f
#define VL6180_ALS_IT 0x040
@@ -84,8 +90,17 @@
struct vl6180_data {
struct i2c_client *client;
struct mutex lock;
+ struct completion completion;
+ struct iio_trigger *trig;
unsigned int als_gain_milli;
unsigned int als_it_ms;
+ unsigned int als_meas_rate;
+ unsigned int range_meas_rate;
+
+ struct {
+ u16 chan[2];
+ aligned_s64 timestamp;
+ } scan;
};
enum { VL6180_ALS, VL6180_RANGE, VL6180_PROX };
@@ -207,29 +222,40 @@ static int vl6180_write_word(struct i2c_client *client, u16 cmd, u16 val)
static int vl6180_measure(struct vl6180_data *data, int addr)
{
struct i2c_client *client = data->client;
+ unsigned long time_left;
int tries = 20, ret;
u16 value;
mutex_lock(&data->lock);
+ reinit_completion(&data->completion);
+
/* Start single shot measurement */
ret = vl6180_write_byte(client,
vl6180_chan_regs_table[addr].start_reg, VL6180_STARTSTOP);
if (ret < 0)
goto fail;
- while (tries--) {
- ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
- if (ret < 0)
+ if (client->irq) {
+ time_left = wait_for_completion_timeout(&data->completion, HZ / 10);
+ if (time_left == 0) {
+ ret = -ETIMEDOUT;
goto fail;
+ }
+ } else {
+ while (tries--) {
+ ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
+ if (ret < 0)
+ goto fail;
+
+ if (ret & vl6180_chan_regs_table[addr].drdy_mask)
+ break;
+ msleep(20);
+ }
- if (ret & vl6180_chan_regs_table[addr].drdy_mask)
- break;
- msleep(20);
- }
-
- if (tries < 0) {
- ret = -EIO;
- goto fail;
+ if (tries < 0) {
+ ret = -EIO;
+ goto fail;
+ }
}
/* Read result value from appropriate registers */
@@ -258,20 +284,41 @@ static const struct iio_chan_spec vl6180_channels[] = {
{
.type = IIO_LIGHT,
.address = VL6180_ALS,
+ .scan_index = VL6180_ALS,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_INT_TIME) |
BIT(IIO_CHAN_INFO_SCALE) |
- BIT(IIO_CHAN_INFO_HARDWAREGAIN),
+ BIT(IIO_CHAN_INFO_HARDWAREGAIN) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
}, {
.type = IIO_DISTANCE,
.address = VL6180_RANGE,
+ .scan_index = VL6180_RANGE,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 8,
+ .storagebits = 8,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
}, {
.type = IIO_PROXIMITY,
.address = VL6180_PROX,
+ .scan_index = VL6180_PROX,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- }
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(3),
};
/*
@@ -333,6 +380,18 @@ static int vl6180_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (chan->type) {
+ case IIO_DISTANCE:
+ *val = data->range_meas_rate;
+ return IIO_VAL_INT;
+ case IIO_LIGHT:
+ *val = data->als_meas_rate;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+
default:
return -EINVAL;
}
@@ -412,11 +471,23 @@ fail:
return ret;
}
+static int vl6180_meas_reg_val_from_mhz(unsigned int mhz)
+{
+ unsigned int period = DIV_ROUND_CLOSEST(1000 * 1000, mhz);
+ unsigned int reg_val = 0;
+
+ if (period > 10)
+ reg_val = period < 2550 ? (DIV_ROUND_CLOSEST(period, 10) - 1) : 254;
+
+ return reg_val;
+}
+
static int vl6180_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct vl6180_data *data = iio_priv(indio_dev);
+ unsigned int reg_val;
switch (mask) {
case IIO_CHAN_INFO_INT_TIME:
@@ -427,18 +498,126 @@ static int vl6180_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
return vl6180_set_als_gain(data, val, val2);
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ {
+ guard(mutex)(&data->lock);
+ switch (chan->type) {
+ case IIO_DISTANCE:
+ data->range_meas_rate = val;
+ reg_val = vl6180_meas_reg_val_from_mhz(val);
+ return vl6180_write_byte(data->client,
+ VL6180_RANGE_INTER_MEAS_TIME, reg_val);
+
+ case IIO_LIGHT:
+ data->als_meas_rate = val;
+ reg_val = vl6180_meas_reg_val_from_mhz(val);
+ return vl6180_write_byte(data->client,
+ VL6180_ALS_INTER_MEAS_TIME, reg_val);
+
+ default:
+ return -EINVAL;
+ }
+ }
+
default:
return -EINVAL;
}
}
+static irqreturn_t vl6180_threaded_irq(int irq, void *priv)
+{
+ struct iio_dev *indio_dev = priv;
+ struct vl6180_data *data = iio_priv(indio_dev);
+
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll_nested(indio_dev->trig);
+ else
+ complete(&data->completion);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vl6180_trigger_handler(int irq, void *priv)
+{
+ struct iio_poll_func *pf = priv;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vl6180_data *data = iio_priv(indio_dev);
+ s64 time_ns = iio_get_time_ns(indio_dev);
+ int ret, bit, i = 0;
+
+ iio_for_each_active_channel(indio_dev, bit) {
+ if (vl6180_chan_regs_table[bit].word)
+ ret = vl6180_read_word(data->client,
+ vl6180_chan_regs_table[bit].value_reg);
+ else
+ ret = vl6180_read_byte(data->client,
+ vl6180_chan_regs_table[bit].value_reg);
+
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "failed to read from value regs: %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ data->scan.chan[i++] = ret;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ /* Clear the interrupt flag after data read */
+ ret = vl6180_write_byte(data->client, VL6180_INTR_CLEAR,
+ VL6180_CLEAR_ERROR | VL6180_CLEAR_ALS | VL6180_CLEAR_RANGE);
+ if (ret < 0)
+ dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
+
+ return IRQ_HANDLED;
+}
+
static const struct iio_info vl6180_info = {
.read_raw = vl6180_read_raw,
.write_raw = vl6180_write_raw,
.attrs = &vl6180_attribute_group,
+ .validate_trigger = iio_validate_own_trigger,
+};
+
+static int vl6180_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct vl6180_data *data = iio_priv(indio_dev);
+ int bit;
+
+ iio_for_each_active_channel(indio_dev, bit)
+ return vl6180_write_byte(data->client,
+ vl6180_chan_regs_table[bit].start_reg,
+ VL6180_MODE_CONT | VL6180_STARTSTOP);
+
+ return -EINVAL;
+}
+
+static int vl6180_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct vl6180_data *data = iio_priv(indio_dev);
+ int bit;
+
+ iio_for_each_active_channel(indio_dev, bit)
+ return vl6180_write_byte(data->client,
+ vl6180_chan_regs_table[bit].start_reg,
+ VL6180_STARTSTOP);
+
+ return -EINVAL;
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+ .postenable = &vl6180_buffer_postenable,
+ .postdisable = &vl6180_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops vl6180_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
};
-static int vl6180_init(struct vl6180_data *data)
+static int vl6180_init(struct vl6180_data *data, struct iio_dev *indio_dev)
{
struct i2c_client *client = data->client;
int ret;
@@ -473,6 +652,26 @@ static int vl6180_init(struct vl6180_data *data)
if (ret < 0)
return ret;
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ &vl6180_trigger_handler,
+ &iio_triggered_buffer_setup_ops);
+ if (ret)
+ return ret;
+
+ /* Default Range inter-measurement time: 50ms or 20000 mHz */
+ ret = vl6180_write_byte(client, VL6180_RANGE_INTER_MEAS_TIME,
+ vl6180_meas_reg_val_from_mhz(20000));
+ if (ret < 0)
+ return ret;
+ data->range_meas_rate = 20000;
+
+ /* Default ALS inter-measurement time: 10ms or 100000 mHz */
+ ret = vl6180_write_byte(client, VL6180_ALS_INTER_MEAS_TIME,
+ vl6180_meas_reg_val_from_mhz(100000));
+ if (ret < 0)
+ return ret;
+ data->als_meas_rate = 100000;
+
/* ALS integration time: 100ms */
data->als_it_ms = 100;
ret = vl6180_write_word(client, VL6180_ALS_IT, VL6180_ALS_IT_100);
@@ -513,10 +712,34 @@ static int vl6180_probe(struct i2c_client *client)
indio_dev->name = VL6180_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = vl6180_init(data);
+ ret = vl6180_init(data, indio_dev);
if (ret < 0)
return ret;
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vl6180_threaded_irq,
+ IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "devm_request_irq error \n");
+
+ init_completion(&data->completion);
+
+ data->trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name, iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = &vl6180_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+ ret = devm_iio_trigger_register(&client->dev, data->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+ }
+
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index f69ac75500f9..7177cd1d67cb 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -54,6 +54,19 @@ config AK09911
help
Deprecated: AK09911 is now supported by AK8975 driver.
+config ALS31300
+ tristate "Allegro MicroSystems ALS31300 3-D Linear Hall Effect Sensor"
+ depends on I2C
+ select REGMAP_I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for the Allegro MicroSystems
+ ALS31300 Hall Effect Sensor through its I2C interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called als31300.
+
config BMC150_MAGN
tristate
select IIO_BUFFER
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index ec5c46fbf999..3e4c2ecd9adf 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_AF8133J) += af8133j.o
obj-$(CONFIG_AK8974) += ak8974.o
obj-$(CONFIG_AK8975) += ak8975.o
+obj-$(CONFIG_ALS31300) += als31300.o
obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o
obj-$(CONFIG_BMC150_MAGN_SPI) += bmc150_magn_spi.o
diff --git a/drivers/iio/magnetometer/af8133j.c b/drivers/iio/magnetometer/af8133j.c
index d81d89af6283..acd291f3e792 100644
--- a/drivers/iio/magnetometer/af8133j.c
+++ b/drivers/iio/magnetometer/af8133j.c
@@ -312,10 +312,11 @@ static int af8133j_set_scale(struct af8133j_data *data,
* When suspended, just store the new range to data->range to be
* applied later during power up.
*/
- if (!pm_runtime_status_suspended(dev))
+ if (!pm_runtime_status_suspended(dev)) {
scoped_guard(mutex, &data->mutex)
ret = regmap_write(data->regmap,
AF8133J_REG_RANGE, range);
+ }
pm_runtime_enable(dev);
diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c
index 961b1e0bfb13..8306a18706ac 100644
--- a/drivers/iio/magnetometer/ak8974.c
+++ b/drivers/iio/magnetometer/ak8974.c
@@ -910,7 +910,7 @@ static int ak8974_probe(struct i2c_client *i2c)
/* If we have a valid DRDY IRQ, make use of it */
if (irq > 0) {
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irq_trig = irq_get_trigger_type(irq);
if (irq_trig == IRQF_TRIGGER_RISING) {
dev_info(&i2c->dev, "enable rising edge DRDY IRQ\n");
} else if (irq_trig == IRQF_TRIGGER_FALLING) {
diff --git a/drivers/iio/magnetometer/als31300.c b/drivers/iio/magnetometer/als31300.c
new file mode 100644
index 000000000000..87b60c4e81fa
--- /dev/null
+++ b/drivers/iio/magnetometer/als31300.c
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the Allegro MicroSystems ALS31300 3-D Linear Hall Effect Sensor
+ *
+ * Copyright (c) 2024 Linaro Limited
+ */
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+#include <linux/units.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+/*
+ * The Allegro MicroSystems ALS31300 has an EEPROM space to configure how
+ * the device works and how the interrupt line behaves.
+ * Only the default setup with external trigger is supported.
+ *
+ * While the bindings supports declaring an interrupt line, those
+ * events are not supported.
+ *
+ * It should be possible to adapt the driver to the current
+ * device EEPROM setup at runtime.
+ */
+
+#define ALS31300_EEPROM_CONFIG 0x02
+#define ALS31300_EEPROM_INTERRUPT 0x03
+#define ALS31300_EEPROM_CUSTOMER_1 0x0d
+#define ALS31300_EEPROM_CUSTOMER_2 0x0e
+#define ALS31300_EEPROM_CUSTOMER_3 0x0f
+#define ALS31300_VOL_MODE 0x27
+#define ALS31300_VOL_MODE_LPDCM GENMASK(6, 4)
+#define ALS31300_LPDCM_INACTIVE_0_5_MS 0
+#define ALS31300_LPDCM_INACTIVE_1_0_MS 1
+#define ALS31300_LPDCM_INACTIVE_5_0_MS 2
+#define ALS31300_LPDCM_INACTIVE_10_0_MS 3
+#define ALS31300_LPDCM_INACTIVE_50_0_MS 4
+#define ALS31300_LPDCM_INACTIVE_100_0_MS 5
+#define ALS31300_LPDCM_INACTIVE_500_0_MS 6
+#define ALS31300_LPDCM_INACTIVE_1000_0_MS 7
+#define ALS31300_VOL_MODE_SLEEP GENMASK(1, 0)
+#define ALS31300_VOL_MODE_ACTIVE_MODE 0
+#define ALS31300_VOL_MODE_SLEEP_MODE 1
+#define ALS31300_VOL_MODE_LPDCM_MODE 2
+#define ALS31300_VOL_MSB 0x28
+#define ALS31300_VOL_MSB_TEMPERATURE GENMASK(5, 0)
+#define ALS31300_VOL_MSB_INTERRUPT BIT(6)
+#define ALS31300_VOL_MSB_NEW_DATA BIT(7)
+#define ALS31300_VOL_MSB_Z_AXIS GENMASK(15, 8)
+#define ALS31300_VOL_MSB_Y_AXIS GENMASK(23, 16)
+#define ALS31300_VOL_MSB_X_AXIS GENMASK(31, 24)
+#define ALS31300_VOL_LSB 0x29
+#define ALS31300_VOL_LSB_TEMPERATURE GENMASK(5, 0)
+#define ALS31300_VOL_LSB_HALL_STATUS GENMASK(7, 7)
+#define ALS31300_VOL_LSB_Z_AXIS GENMASK(11, 8)
+#define ALS31300_VOL_LSB_Y_AXIS GENMASK(15, 12)
+#define ALS31300_VOL_LSB_X_AXIS GENMASK(19, 16)
+#define ALS31300_VOL_LSB_INTERRUPT_WRITE BIT(20)
+#define ALS31300_CUSTOMER_ACCESS 0x35
+
+#define ALS31300_DATA_X_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_X_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_X_AXIS, b[1]), 11)
+#define ALS31300_DATA_Y_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_Y_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_Y_AXIS, b[1]), 11)
+#define ALS31300_DATA_Z_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_Z_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_Z_AXIS, b[1]), 11)
+#define ALS31300_TEMPERATURE_GET(b) \
+ (FIELD_GET(ALS31300_VOL_MSB_TEMPERATURE, b[0]) << 6 | \
+ FIELD_GET(ALS31300_VOL_LSB_TEMPERATURE, b[1]))
+
+enum als31300_channels {
+ TEMPERATURE = 0,
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+};
+
+struct als31300_variant_info {
+ u8 sensitivity;
+};
+
+struct als31300_data {
+ struct device *dev;
+ /* protects power on/off the device and access HW */
+ struct mutex mutex;
+ const struct als31300_variant_info *variant_info;
+ struct regmap *map;
+};
+
+/* The whole measure is split into 2x32-bit registers, we need to read them both at once */
+static int als31300_get_measure(struct als31300_data *data,
+ u16 *t, s16 *x, s16 *y, s16 *z)
+{
+ u32 buf[2];
+ int ret, err;
+
+ guard(mutex)(&data->mutex);
+
+ ret = pm_runtime_resume_and_get(data->dev);
+ if (ret)
+ return ret;
+
+ /*
+ * Loop until data is valid, new data should have the
+ * ALS31300_VOL_MSB_NEW_DATA bit set to 1.
+ * Max update rate is 2KHz, wait up to 1ms.
+ */
+ ret = read_poll_timeout(regmap_bulk_read, err,
+ err || FIELD_GET(ALS31300_VOL_MSB_NEW_DATA, buf[0]),
+ 20, USEC_PER_MSEC, false,
+ data->map, ALS31300_VOL_MSB, buf, ARRAY_SIZE(buf));
+ /* Bail out on read_poll_timeout() error */
+ if (ret)
+ goto out;
+
+ /* Bail out on regmap_bulk_read() error */
+ if (err) {
+ dev_err(data->dev, "read data failed, error %d\n", ret);
+ ret = err;
+ goto out;
+ }
+
+ *t = ALS31300_TEMPERATURE_GET(buf);
+ *x = ALS31300_DATA_X_GET(buf);
+ *y = ALS31300_DATA_Y_GET(buf);
+ *z = ALS31300_DATA_Z_GET(buf);
+
+out:
+ pm_runtime_mark_last_busy(data->dev);
+ pm_runtime_put_autosuspend(data->dev);
+
+ return ret;
+}
+
+static int als31300_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int *val,
+ int *val2, long mask)
+{
+ struct als31300_data *data = iio_priv(indio_dev);
+ s16 x, y, z;
+ u16 t;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ case IIO_CHAN_INFO_RAW:
+ ret = als31300_get_measure(data, &t, &x, &y, &z);
+ if (ret)
+ return ret;
+
+ switch (chan->address) {
+ case TEMPERATURE:
+ *val = t;
+ return IIO_VAL_INT;
+ case AXIS_X:
+ *val = x;
+ return IIO_VAL_INT;
+ case AXIS_Y:
+ *val = y;
+ return IIO_VAL_INT;
+ case AXIS_Z:
+ *val = z;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ /*
+ * Fractional part of:
+ * 1000 * 302 * (value - 1708)
+ * temp = ----------------------------
+ * 4096
+ * to convert temperature in millicelcius.
+ */
+ *val = MILLI * 302;
+ *val2 = 4096;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_MAGN:
+ /*
+ * Devices are configured in factory
+ * with different sensitivities:
+ * - 500 GAUSS <-> 4 LSB/Gauss
+ * - 1000 GAUSS <-> 2 LSB/Gauss
+ * - 2000 GAUSS <-> 1 LSB/Gauss
+ * with translates by a division of the returned
+ * value to get Gauss value.
+ * The sensitivity cannot be read at runtime
+ * so the value depends on the model compatible
+ * or device id.
+ */
+ *val = 1;
+ *val2 = data->variant_info->sensitivity;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_OFFSET:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = -1708;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t als31300_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct als31300_data *data = iio_priv(indio_dev);
+ struct {
+ u16 temperature;
+ s16 channels[3];
+ aligned_s64 timestamp;
+ } scan;
+ s16 x, y, z;
+ int ret;
+ u16 t;
+
+ ret = als31300_get_measure(data, &t, &x, &y, &z);
+ if (ret)
+ goto trigger_out;
+
+ scan.temperature = t;
+ scan.channels[0] = x;
+ scan.channels[1] = y;
+ scan.channels[2] = z;
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
+ pf->timestamp);
+
+trigger_out:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+#define ALS31300_AXIS_CHANNEL(axis, index) \
+ { \
+ .type = IIO_MAGN, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ }
+
+static const struct iio_chan_spec als31300_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
+ .address = TEMPERATURE,
+ .scan_index = TEMPERATURE,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ ALS31300_AXIS_CHANNEL(X, AXIS_X),
+ ALS31300_AXIS_CHANNEL(Y, AXIS_Y),
+ ALS31300_AXIS_CHANNEL(Z, AXIS_Z),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct iio_info als31300_info = {
+ .read_raw = als31300_read_raw,
+};
+
+static int als31300_set_operating_mode(struct als31300_data *data,
+ unsigned int val)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->map, ALS31300_VOL_MODE,
+ ALS31300_VOL_MODE_SLEEP, val);
+ if (ret) {
+ dev_err(data->dev, "failed to set operating mode (%pe)\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ /* The time it takes to exit sleep mode is equivalent to Power-On Delay Time */
+ if (val == ALS31300_VOL_MODE_ACTIVE_MODE)
+ fsleep(600);
+
+ return 0;
+}
+
+static void als31300_power_down(void *data)
+{
+ als31300_set_operating_mode(data, ALS31300_VOL_MODE_SLEEP_MODE);
+}
+
+static const struct iio_buffer_setup_ops als31300_setup_ops = {};
+
+static const unsigned long als31300_scan_masks[] = { GENMASK(3, 0), 0 };
+
+static bool als31300_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return reg == ALS31300_VOL_MSB || reg == ALS31300_VOL_LSB;
+}
+
+static const struct regmap_config als31300_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .max_register = ALS31300_CUSTOMER_ACCESS,
+ .volatile_reg = als31300_volatile_reg,
+};
+
+static int als31300_probe(struct i2c_client *i2c)
+{
+ struct device *dev = &i2c->dev;
+ struct als31300_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->dev = dev;
+ i2c_set_clientdata(i2c, indio_dev);
+
+ ret = devm_mutex_init(dev, &data->mutex);
+ if (ret)
+ return ret;
+
+ data->variant_info = i2c_get_match_data(i2c);
+ if (!data->variant_info)
+ return -EINVAL;
+
+ data->map = devm_regmap_init_i2c(i2c, &als31300_regmap_config);
+ if (IS_ERR(data->map))
+ return dev_err_probe(dev, PTR_ERR(data->map),
+ "failed to allocate register map\n");
+
+ ret = devm_regulator_get_enable(dev, "vcc");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable regulator\n");
+
+ ret = als31300_set_operating_mode(data, ALS31300_VOL_MODE_ACTIVE_MODE);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to power on device\n");
+
+ ret = devm_add_action_or_reset(dev, als31300_power_down, data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add powerdown action\n");
+
+ indio_dev->info = &als31300_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = i2c->name;
+ indio_dev->channels = als31300_channels;
+ indio_dev->num_channels = ARRAY_SIZE(als31300_channels);
+ indio_dev->available_scan_masks = als31300_scan_masks;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ als31300_trigger_handler,
+ &als31300_setup_ops);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "iio triggered buffer setup failed\n");
+
+ ret = pm_runtime_set_active(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_autosuspend_delay(dev, 200);
+ pm_runtime_use_autosuspend(dev);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "device register failed\n");
+
+ return 0;
+}
+
+static int als31300_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct als31300_data *data = iio_priv(indio_dev);
+
+ return als31300_set_operating_mode(data, ALS31300_VOL_MODE_SLEEP_MODE);
+}
+
+static int als31300_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct als31300_data *data = iio_priv(indio_dev);
+
+ return als31300_set_operating_mode(data, ALS31300_VOL_MODE_ACTIVE_MODE);
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(als31300_pm_ops,
+ als31300_runtime_suspend, als31300_runtime_resume,
+ NULL);
+
+static const struct als31300_variant_info al31300_variant_500 = {
+ .sensitivity = 4,
+};
+
+static const struct als31300_variant_info al31300_variant_1000 = {
+ .sensitivity = 2,
+};
+
+static const struct als31300_variant_info al31300_variant_2000 = {
+ .sensitivity = 1,
+};
+
+static const struct i2c_device_id als31300_id[] = {
+ {
+ .name = "als31300-500",
+ .driver_data = (kernel_ulong_t)&al31300_variant_500,
+ },
+ {
+ .name = "als31300-1000",
+ .driver_data = (kernel_ulong_t)&al31300_variant_1000,
+ },
+ {
+ .name = "als31300-2000",
+ .driver_data = (kernel_ulong_t)&al31300_variant_2000,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, als31300_id);
+
+static const struct of_device_id als31300_of_match[] = {
+ {
+ .compatible = "allegromicro,als31300-500",
+ .data = &al31300_variant_500,
+ },
+ {
+ .compatible = "allegromicro,als31300-1000",
+ .data = &al31300_variant_1000,
+ },
+ {
+ .compatible = "allegromicro,als31300-2000",
+ .data = &al31300_variant_2000,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, als31300_of_match);
+
+static struct i2c_driver als31300_driver = {
+ .driver = {
+ .name = "als31300",
+ .of_match_table = als31300_of_match,
+ .pm = pm_ptr(&als31300_pm_ops),
+ },
+ .probe = als31300_probe,
+ .id_table = als31300_id,
+};
+module_i2c_driver(als31300_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ALS31300 3-D Linear Hall Effect Driver");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index 06d5a1ef1fbd..7de18c4a0ccb 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
+++ b/drivers/iio/magnetometer/bmc150_magn.c
@@ -14,7 +14,6 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -855,17 +854,6 @@ static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = {
.postdisable = bmc150_magn_buffer_postdisable,
};
-static const char *bmc150_magn_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
int irq, const char *name)
{
@@ -894,9 +882,6 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
if (ret)
return ret;
- if (!name && ACPI_HANDLE(dev))
- name = bmc150_magn_match_acpi_device(dev);
-
mutex_init(&data->mutex);
ret = bmc150_magn_init(data);
diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c
index a28d46d59875..17e10a462ac8 100644
--- a/drivers/iio/magnetometer/bmc150_magn_i2c.c
+++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c
@@ -38,14 +38,6 @@ static void bmc150_magn_i2c_remove(struct i2c_client *client)
bmc150_magn_remove(&client->dev);
}
-static const struct acpi_device_id bmc150_magn_acpi_match[] = {
- {"BMC150B", 0},
- {"BMC156B", 0},
- {"BMM150B", 0},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
-
static const struct i2c_device_id bmc150_magn_i2c_id[] = {
{ "bmc150_magn" },
{ "bmc156_magn" },
@@ -67,7 +59,6 @@ static struct i2c_driver bmc150_magn_driver = {
.driver = {
.name = "bmc150_magn_i2c",
.of_match_table = bmc150_magn_of_match,
- .acpi_match_table = bmc150_magn_acpi_match,
.pm = &bmc150_magn_pm_ops,
},
.probe = bmc150_magn_i2c_probe,
diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c
index abc75a05c46a..c850de1bc79b 100644
--- a/drivers/iio/magnetometer/bmc150_magn_spi.c
+++ b/drivers/iio/magnetometer/bmc150_magn_spi.c
@@ -41,20 +41,11 @@ static const struct spi_device_id bmc150_magn_spi_id[] = {
};
MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
-static const struct acpi_device_id bmc150_magn_acpi_match[] = {
- {"BMC150B", 0},
- {"BMC156B", 0},
- {"BMM150B", 0},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
-
static struct spi_driver bmc150_magn_spi_driver = {
.probe = bmc150_magn_spi_probe,
.remove = bmc150_magn_spi_remove,
.id_table = bmc150_magn_spi_id,
.driver = {
- .acpi_match_table = bmc150_magn_acpi_match,
.name = "bmc150_magn_spi",
},
};
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index 5c795a430d09..1d6fcbbae1c5 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -466,11 +466,11 @@ static int magn_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_magn_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static char *name = "magn_3d";
struct iio_dev *indio_dev;
struct magn_3d_state *magn_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
int chan_count = 0;
@@ -549,7 +549,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_magn_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct magn_3d_state *magn_state = iio_priv(indio_dev);
@@ -574,7 +574,7 @@ static struct platform_driver hid_magn_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_magn_3d_probe,
- .remove_new = hid_magn_3d_remove,
+ .remove = hid_magn_3d_remove,
};
module_platform_driver(hid_magn_3d_platform_driver);
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 8943d5c78bc0..c74b92d53d4d 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -29,7 +29,7 @@ struct incl_3d_state {
struct hid_sensor_hub_attribute_info incl[INCLI_3D_CHANNEL_MAX];
struct {
u32 incl_val[INCLI_3D_CHANNEL_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -299,11 +299,11 @@ static int incl_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_incl_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
static char *name = "incli_3d";
struct iio_dev *indio_dev;
struct incl_3d_state *incl_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct incl_3d_state));
@@ -385,7 +385,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_incl_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct incl_3d_state *incl_state = iio_priv(indio_dev);
@@ -410,7 +410,7 @@ static struct platform_driver hid_incl_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_incl_3d_probe,
- .remove_new = hid_incl_3d_remove,
+ .remove = hid_incl_3d_remove,
};
module_platform_driver(hid_incl_3d_platform_driver);
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 5e8cadd5177a..343be43163e4 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -20,7 +20,7 @@ struct dev_rot_state {
struct hid_sensor_hub_attribute_info quaternion;
struct {
s32 sampled_vals[4] __aligned(16);
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -230,11 +230,11 @@ static int dev_rot_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_dev_rot_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
char *name;
struct iio_dev *indio_dev;
struct dev_rot_state *rot_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct dev_rot_state));
@@ -329,7 +329,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_dev_rot_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct dev_rot_state *rot_state = iio_priv(indio_dev);
@@ -362,7 +362,7 @@ static struct platform_driver hid_dev_rot_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_dev_rot_probe,
- .remove_new = hid_dev_rot_remove,
+ .remove = hid_dev_rot_remove,
};
module_platform_driver(hid_dev_rot_platform_driver);
diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
index 76e173850a35..3a6c7e50cc70 100644
--- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c
+++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
@@ -39,7 +39,7 @@ struct hinge_state {
const char *labels[CHANNEL_SCAN_INDEX_MAX];
struct {
u32 hinge_val[3];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
@@ -263,9 +263,9 @@ static int hinge_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_hinge_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct hinge_state *st;
struct iio_dev *indio_dev;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
int ret;
int i;
@@ -344,7 +344,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_hinge_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hinge_state *st = iio_priv(indio_dev);
@@ -369,7 +369,7 @@ static struct platform_driver hid_hinge_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_hinge_probe,
- .remove_new = hid_hinge_remove,
+ .remove = hid_hinge_remove,
};
module_platform_driver(hid_hinge_platform_driver);
diff --git a/drivers/iio/position/iqs624-pos.c b/drivers/iio/position/iqs624-pos.c
index 4d7452314209..8239239c6ee2 100644
--- a/drivers/iio/position/iqs624-pos.c
+++ b/drivers/iio/position/iqs624-pos.c
@@ -181,7 +181,7 @@ static int iqs624_pos_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iqs624_pos_private *iqs624_pos = iio_priv(indio_dev);
struct iqs62x_core *iqs62x = iqs624_pos->iqs62x;
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index a8b97b9b0461..e5ec8137961f 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -16,6 +16,11 @@
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp390-ds002.pdf
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf
*
+ * Sensor API:
+ * https://github.com/boschsensortec/BME280_SensorAPI
+ * https://github.com/boschsensortec/BMP3_SensorAPI
+ * https://github.com/boschsensortec/BMP5_SensorAPI
+ *
* Notice:
* The link to the bmp180 datasheet points to an outdated version missing these changes:
* - Changed document referral from ANP015 to BST-MPS-AN004-00 on page 26
@@ -37,12 +42,14 @@
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/random.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
@@ -340,10 +347,19 @@ static int bmp280_read_calib(struct bmp280_data *data)
return 0;
}
+/*
+ * These enums are used for indexing into the array of humidity parameters
+ * for BME280. Due to some weird indexing, unaligned BE/LE accesses co-exist in
+ * order to prepare the FIELD_{GET/PREP}() fields. Table 16 in Section 4.2.2 of
+ * the datasheet.
+ */
+enum { H2 = 0, H3 = 2, H4 = 3, H5 = 4, H6 = 6 };
+
static int bme280_read_calib(struct bmp280_data *data)
{
struct bmp280_calib *calib = &data->calib.bmp280;
struct device *dev = data->dev;
+ s16 h4_upper, h4_lower, tmp_1, tmp_2, tmp_3;
unsigned int tmp;
int ret;
@@ -352,14 +368,6 @@ static int bme280_read_calib(struct bmp280_data *data)
if (ret)
return ret;
- /*
- * Read humidity calibration values.
- * Due to some odd register addressing we cannot just
- * do a big bulk read. Instead, we have to read each Hx
- * value separately and sometimes do some bit shifting...
- * Humidity data is only available on BME280.
- */
-
ret = regmap_read(data->regmap, BME280_REG_COMP_H1, &tmp);
if (ret) {
dev_err(dev, "failed to read H1 comp value\n");
@@ -368,43 +376,23 @@ static int bme280_read_calib(struct bmp280_data *data)
calib->H1 = tmp;
ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H2,
- &data->le16, sizeof(data->le16));
+ data->bme280_humid_cal_buf,
+ sizeof(data->bme280_humid_cal_buf));
if (ret) {
- dev_err(dev, "failed to read H2 comp value\n");
+ dev_err(dev, "failed to read humidity calibration values\n");
return ret;
}
- calib->H2 = sign_extend32(le16_to_cpu(data->le16), 15);
- ret = regmap_read(data->regmap, BME280_REG_COMP_H3, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H3 comp value\n");
- return ret;
- }
- calib->H3 = tmp;
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H4,
- &data->be16, sizeof(data->be16));
- if (ret) {
- dev_err(dev, "failed to read H4 comp value\n");
- return ret;
- }
- calib->H4 = sign_extend32(((be16_to_cpu(data->be16) >> 4) & 0xff0) |
- (be16_to_cpu(data->be16) & 0xf), 11);
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H5,
- &data->le16, sizeof(data->le16));
- if (ret) {
- dev_err(dev, "failed to read H5 comp value\n");
- return ret;
- }
- calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11);
-
- ret = regmap_read(data->regmap, BME280_REG_COMP_H6, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H6 comp value\n");
- return ret;
- }
- calib->H6 = sign_extend32(tmp, 7);
+ calib->H2 = get_unaligned_le16(&data->bme280_humid_cal_buf[H2]);
+ calib->H3 = data->bme280_humid_cal_buf[H3];
+ tmp_1 = get_unaligned_be16(&data->bme280_humid_cal_buf[H4]);
+ tmp_2 = FIELD_GET(BME280_COMP_H4_GET_MASK_UP, tmp_1);
+ h4_upper = FIELD_PREP(BME280_COMP_H4_PREP_MASK_UP, tmp_2);
+ h4_lower = FIELD_GET(BME280_COMP_H4_MASK_LOW, tmp_1);
+ calib->H4 = sign_extend32(h4_upper | h4_lower, 11);
+ tmp_3 = get_unaligned_le16(&data->bme280_humid_cal_buf[H5]);
+ calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, tmp_3), 11);
+ calib->H6 = data->bme280_humid_cal_buf[H6];
return 0;
}
@@ -635,6 +623,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -664,6 +660,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_CHAN_INFO_RAW:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -983,6 +987,92 @@ static const unsigned long bme280_avail_scan_masks[] = {
0
};
+static int bmp280_preinit(struct bmp280_data *data)
+{
+ struct device *dev = data->dev;
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_write(data->regmap, BMP280_REG_RESET, BMP280_RST_SOFT_CMD);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to reset device.\n");
+
+ /*
+ * According to the datasheet in Chapter 1: Specification, Table 2,
+ * after resetting, the device uses the complete power-on sequence so
+ * it needs to wait for the defined start-up time.
+ */
+ fsleep(data->start_up_time);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read status register.\n");
+
+ if (reg & BMP280_REG_STATUS_IM_UPDATE)
+ return dev_err_probe(dev, -EIO, "Failed to copy NVM contents.\n");
+
+ return 0;
+}
+
+static const u8 bmp280_operation_mode[] = {
+ [BMP280_SLEEP] = BMP280_MODE_SLEEP,
+ [BMP280_FORCED] = BMP280_MODE_FORCED,
+ [BMP280_NORMAL] = BMP280_MODE_NORMAL,
+};
+
+static int bmp280_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
+ BMP280_MODE_MASK, bmp280_operation_mode[mode]);
+ if (ret) {
+ dev_err(data->dev, "failed to write ctrl_meas register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp280_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg, meas_time_us;
+ int ret;
+
+ /* Check if we are using a BME280 device */
+ if (data->oversampling_humid)
+ meas_time_us = BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
+
+ else
+ meas_time_us = 0;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP280_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
+
+ /* Waiting time according to the BM(P/E)2 Sensor API */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (reg & BMP280_REG_STATUS_MEAS_BIT) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp280_chip_config(struct bmp280_data *data)
{
u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
@@ -993,7 +1083,7 @@ static int bmp280_chip_config(struct bmp280_data *data)
BMP280_OSRS_TEMP_MASK |
BMP280_OSRS_PRESS_MASK |
BMP280_MODE_MASK,
- osrs | BMP280_MODE_NORMAL);
+ osrs | BMP280_MODE_SLEEP);
if (ret) {
dev_err(data->dev, "failed to write ctrl_meas register\n");
return ret;
@@ -1015,7 +1105,9 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1035,7 +1127,7 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1045,10 +1137,12 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1099,6 +1193,9 @@ const struct bmp280_chip_info bmp280_chip_info = {
.read_temp = bmp280_read_temp,
.read_press = bmp280_read_press,
.read_calib = bmp280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bmp280_trigger_handler,
};
@@ -1128,7 +1225,9 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, adc_humidity, t_fine;
+ u32 adc_temp, adc_press, adc_humidity, comp_press, comp_humidity;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1148,7 +1247,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1158,8 +1257,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
-
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
/* Humidity calculations */
adc_humidity = get_unaligned_be16(&data->buf[6]);
@@ -1168,9 +1266,14 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
dev_err(data->dev, "reading humidity skipped\n");
goto out;
}
- data->sensor_data[2] = bme280_compensate_humidity(data, adc_humidity, t_fine);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ comp_humidity = bme280_compensate_humidity(data, adc_humidity, t_fine);
+
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
+ chans[2] = comp_humidity;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1179,6 +1282,63 @@ out:
return IRQ_HANDLED;
}
+static int __bmp280_trigger_probe(struct iio_dev *indio_dev,
+ const struct iio_trigger_ops *trigger_ops,
+ int (*int_pin_config)(struct bmp280_data *data),
+ irq_handler_t irq_thread_handler)
+{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
+ u32 irq_type;
+ int ret, irq;
+
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_type = irq_get_trigger_type(irq);
+ switch (irq_type) {
+ case IRQF_TRIGGER_RISING:
+ data->trig_active_high = true;
+ break;
+ case IRQF_TRIGGER_FALLING:
+ data->trig_active_high = false;
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL, "Invalid interrupt type specified.\n");
+ }
+
+ data->trig_open_drain =
+ fwnode_property_read_bool(dev_fwnode(dev), "int-open-drain");
+
+ ret = int_pin_config(data);
+ if (ret)
+ return ret;
+
+ data->trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = trigger_ops;
+ iio_trigger_set_drvdata(data->trig, data);
+
+ ret = devm_request_threaded_irq(data->dev, irq, NULL,
+ irq_thread_handler, IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "request IRQ failed.\n");
+
+ ret = devm_iio_trigger_register(data->dev, data->trig);
+ if (ret)
+ return dev_err_probe(dev, ret, "iio trigger register failed.\n");
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
+ return 0;
+}
+
static const u8 bme280_chip_ids[] = { BME280_CHIP_ID };
static const int bme280_humid_coeffs[] = { 1000, 1024 };
@@ -1216,6 +1376,9 @@ const struct bmp280_chip_info bme280_chip_info = {
.read_press = bmp280_read_press,
.read_humid = bme280_read_humid,
.read_calib = bme280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bme280_trigger_handler,
};
@@ -1502,6 +1665,64 @@ static int bmp380_preinit(struct bmp280_data *data)
return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
}
+static const u8 bmp380_operation_mode[] = {
+ [BMP280_SLEEP] = BMP380_MODE_SLEEP,
+ [BMP280_FORCED] = BMP380_MODE_FORCED,
+ [BMP280_NORMAL] = BMP380_MODE_NORMAL,
+};
+
+static int bmp380_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+ BMP380_MODE_MASK,
+ FIELD_PREP(BMP380_MODE_MASK,
+ bmp380_operation_mode[mode]));
+ if (ret) {
+ dev_err(data->dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp380_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg;
+ int ret, meas_time_us;
+
+ /* Offset measurement time */
+ meas_time_us = BMP380_MEAS_OFFSET;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP380_PRESS_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP380_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BMP380_TEMP_MEAS_OFFSET +
+ BIT(data->oversampling_temp) * BMP380_MEAS_DUR;
+
+ /* Measurement time defined in Datasheet Section 3.9.2 */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP380_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (!((reg & BMP380_STATUS_DRDY_PRESS_MASK) &&
+ (reg & BMP380_STATUS_DRDY_TEMP_MASK))) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp380_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -1545,14 +1766,12 @@ static int bmp380_chip_config(struct bmp280_data *data)
change = change || aux;
/* Set filter data */
- ret = regmap_update_bits_check(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
- FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff),
- &aux);
+ ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
+ FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff));
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
if (change) {
/*
@@ -1564,17 +1783,19 @@ static int bmp380_chip_config(struct bmp280_data *data)
* Resets sensor measurement loop toggling between sleep and
* normal operating modes.
*/
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_SLEEP));
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
if (ret) {
dev_err(data->dev, "failed to set sleep mode\n");
return ret;
}
- usleep_range(2000, 2500);
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL));
+
+ /*
+ * According to the BMP3 Sensor API, the sensor needs 5ms
+ * in order to go to the sleep mode.
+ */
+ fsleep(5 * USEC_PER_MSEC);
+
+ ret = bmp380_set_mode(data, BMP280_NORMAL);
if (ret) {
dev_err(data->dev, "failed to set normal mode\n");
return ret;
@@ -1600,7 +1821,77 @@ static int bmp380_chip_config(struct bmp280_data *data)
}
}
- return 0;
+ /* Dummy read to empty data registers. */
+ ret = bmp380_read_press(data, &tmp);
+ if (ret)
+ return ret;
+
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
+ if (ret)
+ dev_err(data->dev, "failed to set sleep mode.\n");
+
+ return ret;
+}
+
+static int bmp380_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_DRDY_EN,
+ FIELD_PREP(BMP380_INT_CTRL_DRDY_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp380_trigger_ops = {
+ .set_trigger_state = &bmp380_data_rdy_trigger_set_state,
+};
+
+static int bmp380_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP380_INT_CTRL_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP380_INT_CTRL_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_SETTINGS_MASK, int_pin_cfg);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp380_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP380_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP380_INT_STATUS_DRDY, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp380_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp380_trigger_ops,
+ bmp380_int_pin_config,
+ bmp380_irq_thread_handler);
}
static irqreturn_t bmp380_trigger_handler(int irq, void *p)
@@ -1608,7 +1899,9 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1628,7 +1921,7 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp380_compensate_temp(data, adc_temp);
+ comp_temp = bmp380_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = get_unaligned_le24(&data->buf[0]);
@@ -1638,10 +1931,12 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
}
t_fine = bmp380_calc_t_fine(data, adc_temp);
+ comp_press = bmp380_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp380_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1692,8 +1987,11 @@ const struct bmp280_chip_info bmp380_chip_info = {
.read_temp = bmp380_read_temp,
.read_press = bmp380_read_press,
.read_calib = bmp380_read_calib,
+ .set_mode = bmp380_set_mode,
+ .wait_conv = bmp380_wait_conv,
.preinit = bmp380_preinit,
+ .trigger_probe = bmp380_trigger_probe,
.trigger_handler = bmp380_trigger_handler,
};
EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
@@ -2079,6 +2377,70 @@ static int bmp580_preinit(struct bmp280_data *data)
return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
}
+static const u8 bmp580_operation_mode[] = {
+ [BMP280_SLEEP] = BMP580_MODE_SLEEP,
+ [BMP280_FORCED] = BMP580_MODE_FORCED,
+ [BMP280_NORMAL] = BMP580_MODE_NORMAL,
+};
+
+static int bmp580_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ struct device *dev = data->dev;
+ int ret;
+
+ if (mode == BMP280_FORCED) {
+ ret = regmap_set_bits(data->regmap, BMP580_REG_DSP_CONFIG,
+ BMP580_DSP_IIR_FORCED_FLUSH);
+ if (ret) {
+ dev_err(dev, "Could not flush IIR filter constants.\n");
+ return ret;
+ }
+ }
+
+ ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+ BMP580_MODE_MASK,
+ FIELD_PREP(BMP580_MODE_MASK,
+ bmp580_operation_mode[mode]));
+ if (ret) {
+ dev_err(dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp580_wait_conv(struct bmp280_data *data)
+{
+ /*
+ * Taken from datasheet, Section 2 "Specification, Table 3 "Electrical
+ * characteristics.
+ */
+ static const int time_conv_press[] = {
+ 0, 1050, 1785, 3045, 5670, 10920, 21420, 42420,
+ 84420,
+ };
+ static const int time_conv_temp[] = {
+ 0, 1050, 1105, 1575, 2205, 3465, 6090, 11340,
+ 21840,
+ };
+ int meas_time_us;
+
+ meas_time_us = 4 * USEC_PER_MSEC +
+ time_conv_temp[data->oversampling_temp] +
+ time_conv_press[data->oversampling_press];
+
+ /*
+ * Measurement time mentioned in Chapter 2, Table 4 of the datasheet.
+ * The extra 4ms is the required mode change to start of measurement
+ * time.
+ */
+ fsleep(meas_time_us);
+
+ return 0;
+}
+
static int bmp580_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -2141,26 +2503,13 @@ static int bmp580_chip_config(struct bmp280_data *data)
reg_val = FIELD_PREP(BMP580_DSP_IIR_PRESS_MASK, data->iir_filter_coeff) |
FIELD_PREP(BMP580_DSP_IIR_TEMP_MASK, data->iir_filter_coeff);
- ret = regmap_update_bits_check(data->regmap, BMP580_REG_DSP_IIR,
- BMP580_DSP_IIR_PRESS_MASK |
- BMP580_DSP_IIR_TEMP_MASK,
- reg_val, &aux);
+ ret = regmap_update_bits(data->regmap, BMP580_REG_DSP_IIR,
+ BMP580_DSP_IIR_PRESS_MASK | BMP580_DSP_IIR_TEMP_MASK,
+ reg_val);
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
-
- /* Restore sensor to normal operation mode */
- ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
- BMP580_MODE_MASK,
- FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_NORMAL));
- if (ret) {
- dev_err(data->dev, "failed to set normal mode\n");
- return ret;
- }
- /* From datasheet's table 4: electrical characteristics */
- usleep_range(3000, 3500);
if (change) {
/*
@@ -2185,12 +2534,80 @@ static int bmp580_chip_config(struct bmp280_data *data)
return 0;
}
+static int bmp580_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_INT_EN,
+ FIELD_PREP(BMP580_INT_CONFIG_INT_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp580_trigger_ops = {
+ .set_trigger_state = &bmp580_data_rdy_trigger_set_state,
+};
+
+static int bmp580_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP580_INT_CONFIG_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP580_INT_CONFIG_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_MASK, int_pin_cfg);
+ if (ret) {
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+ return ret;
+ }
+
+ ret = regmap_set_bits(data->regmap, BMP580_REG_INT_SOURCE,
+ BMP580_INT_SOURCE_DRDY);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt source.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp580_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP580_INT_STATUS_DRDY_MASK, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp580_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp580_trigger_ops,
+ bmp580_int_pin_config,
+ bmp580_irq_thread_handler);
+}
+
static irqreturn_t bmp580_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret;
+ int ret, offset;
guard(mutex)(&data->lock);
@@ -2202,13 +2619,17 @@ static irqreturn_t bmp580_trigger_handler(int irq, void *p)
goto out;
}
- /* Temperature calculations */
- memcpy(&data->sensor_data[1], &data->buf[0], 3);
+ offset = 0;
/* Pressure calculations */
- memcpy(&data->sensor_data[0], &data->buf[3], 3);
+ memcpy(&data->sensor_data[offset], &data->buf[3], 3);
+
+ offset += sizeof(s32);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ /* Temperature calculations */
+ memcpy(&data->sensor_data[offset], &data->buf[0], 3);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2257,8 +2678,11 @@ const struct bmp280_chip_info bmp580_chip_info = {
.chip_config = bmp580_chip_config,
.read_temp = bmp580_read_temp,
.read_press = bmp580_read_press,
+ .set_mode = bmp580_set_mode,
+ .wait_conv = bmp580_wait_conv,
.preinit = bmp580_preinit,
+ .trigger_probe = bmp580_trigger_probe,
.trigger_handler = bmp580_trigger_handler,
};
EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
@@ -2504,6 +2928,19 @@ static int bmp180_read_press(struct bmp280_data *data, u32 *comp_press)
return 0;
}
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_wait_conv(struct bmp280_data *data)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
static int bmp180_chip_config(struct bmp280_data *data)
{
return 0;
@@ -2514,23 +2951,24 @@ static irqreturn_t bmp180_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret, chan_value;
+ int ret, comp_temp, comp_press;
+ s32 *chans = (s32 *)data->sensor_data;
guard(mutex)(&data->lock);
- ret = bmp180_read_temp(data, &chan_value);
+ ret = bmp180_read_temp(data, &comp_temp);
if (ret)
goto out;
- data->sensor_data[1] = chan_value;
- ret = bmp180_read_press(data, &chan_value);
+ ret = bmp180_read_press(data, &comp_press);
if (ret)
goto out;
- data->sensor_data[0] = chan_value;
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2574,6 +3012,8 @@ const struct bmp280_chip_info bmp180_chip_info = {
.read_temp = bmp180_read_temp,
.read_press = bmp180_read_press,
.read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
.trigger_handler = bmp180_trigger_handler,
};
@@ -2588,15 +3028,18 @@ static irqreturn_t bmp085_eoc_irq(int irq, void *d)
return IRQ_HANDLED;
}
-static int bmp085_fetch_eoc_irq(struct device *dev,
- const char *name,
- int irq,
- struct bmp280_data *data)
+static int bmp085_trigger_probe(struct iio_dev *indio_dev)
{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
unsigned long irq_trig;
- int ret;
+ int ret, irq;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_trig = irq_get_trigger_type(irq);
if (irq_trig != IRQF_TRIGGER_RISING) {
dev_err(dev, "non-rising trigger given for EOC interrupt, trying to enforce it\n");
irq_trig = IRQF_TRIGGER_RISING;
@@ -2604,13 +3047,8 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
init_completion(&data->done);
- ret = devm_request_threaded_irq(dev,
- irq,
- bmp085_eoc_irq,
- NULL,
- irq_trig,
- name,
- data);
+ ret = devm_request_irq(dev, irq, bmp085_eoc_irq, irq_trig,
+ indio_dev->name, data);
if (ret) {
/* Bail out without IRQ but keep the driver in place */
dev_err(dev, "unable to request DRDY IRQ\n");
@@ -2618,14 +3056,54 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
}
data->use_eoc = true;
+
return 0;
}
+/* Identical to bmp180_chip_info + bmp085_trigger_probe */
+const struct bmp280_chip_info bmp085_chip_info = {
+ .id_reg = BMP280_REG_ID,
+ .chip_id = bmp180_chip_ids,
+ .num_chip_id = ARRAY_SIZE(bmp180_chip_ids),
+ .regmap_config = &bmp180_regmap_config,
+ .start_up_time = 2000,
+ .channels = bmp280_channels,
+ .num_channels = ARRAY_SIZE(bmp280_channels),
+ .avail_scan_masks = bmp280_avail_scan_masks,
+
+ .oversampling_temp_avail = bmp180_oversampling_temp_avail,
+ .num_oversampling_temp_avail =
+ ARRAY_SIZE(bmp180_oversampling_temp_avail),
+ .oversampling_temp_default = 0,
+
+ .oversampling_press_avail = bmp180_oversampling_press_avail,
+ .num_oversampling_press_avail =
+ ARRAY_SIZE(bmp180_oversampling_press_avail),
+ .oversampling_press_default = BMP180_MEAS_PRESS_8X,
+
+ .temp_coeffs = bmp180_temp_coeffs,
+ .temp_coeffs_type = IIO_VAL_FRACTIONAL,
+ .press_coeffs = bmp180_press_coeffs,
+ .press_coeffs_type = IIO_VAL_FRACTIONAL,
+
+ .chip_config = bmp180_chip_config,
+ .read_temp = bmp180_read_temp,
+ .read_press = bmp180_read_press,
+ .read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
+
+ .trigger_probe = bmp085_trigger_probe,
+ .trigger_handler = bmp180_trigger_handler,
+};
+EXPORT_SYMBOL_NS(bmp085_chip_info, IIO_BMP280);
+
static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
{
struct bmp280_data *data = iio_priv(indio_dev);
pm_runtime_get_sync(data->dev);
+ data->chip_info->set_mode(data, BMP280_NORMAL);
return 0;
}
@@ -2790,12 +3268,17 @@ int bmp280_common_probe(struct device *dev,
* however as it happens, the BMP085 shares the chip ID of BMP180
* so we look for an IRQ if we have that.
*/
- if (irq > 0 && (chip_id == BMP180_CHIP_ID)) {
- ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
+ if (irq > 0) {
+ if (data->chip_info->trigger_probe)
+ ret = data->chip_info->trigger_probe(indio_dev);
if (ret)
return ret;
}
+ ret = data->chip_info->set_mode(data, BMP280_SLEEP);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set sleep mode\n");
+
/* Enable runtime PM */
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
@@ -2821,6 +3304,9 @@ static int bmp280_runtime_suspend(struct device *dev)
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmp280_data *data = iio_priv(indio_dev);
+ data->chip_info->set_mode(data, BMP280_SLEEP);
+
+ fsleep(data->start_up_time);
return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
}
@@ -2835,7 +3321,12 @@ static int bmp280_runtime_resume(struct device *dev)
return ret;
usleep_range(data->start_up_time, data->start_up_time + 100);
- return data->chip_info->chip_config(data);
+
+ ret = data->chip_info->chip_config(data);
+ if (ret)
+ return ret;
+
+ return data->chip_info->set_mode(data, data->op_mode);
}
EXPORT_RUNTIME_DEV_PM_OPS(bmp280_dev_pm_ops, bmp280_runtime_suspend,
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index 5c3a63b4327c..2f7b25984c7b 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -27,7 +27,7 @@ static int bmp280_i2c_probe(struct i2c_client *client)
}
static const struct of_device_id bmp280_of_i2c_match[] = {
- { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
{ .compatible = "bosch,bme280", .data = &bme280_chip_info },
@@ -38,7 +38,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = {
MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
static const struct i2c_device_id bmp280_i2c_id[] = {
- {"bmp085", (kernel_ulong_t)&bmp180_chip_info },
+ {"bmp085", (kernel_ulong_t)&bmp085_chip_info },
{"bmp180", (kernel_ulong_t)&bmp180_chip_info },
{"bmp280", (kernel_ulong_t)&bmp280_chip_info },
{"bme280", (kernel_ulong_t)&bme280_chip_info },
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index d18549d9bb64..49aa8c2cd85b 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -114,7 +114,7 @@ static int bmp280_spi_probe(struct spi_device *spi)
}
static const struct of_device_id bmp280_of_spi_match[] = {
- { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
@@ -126,7 +126,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
MODULE_DEVICE_TABLE(of, bmp280_of_spi_match);
static const struct spi_device_id bmp280_spi_id[] = {
- { "bmp085", (kernel_ulong_t)&bmp180_chip_info },
+ { "bmp085", (kernel_ulong_t)&bmp085_chip_info },
{ "bmp180", (kernel_ulong_t)&bmp180_chip_info },
{ "bmp181", (kernel_ulong_t)&bmp180_chip_info },
{ "bmp280", (kernel_ulong_t)&bmp280_chip_info },
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index ccacc67c1473..2df1175b6b85 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -55,8 +55,17 @@
#define BMP580_CMD_NVM_WRITE_SEQ_1 0xA0
#define BMP580_CMD_SOFT_RESET 0xB6
+#define BMP580_INT_STATUS_DRDY_MASK BIT(0)
#define BMP580_INT_STATUS_POR_MASK BIT(4)
+#define BMP580_INT_SOURCE_DRDY BIT(0)
+
+#define BMP580_INT_CONFIG_MASK GENMASK(3, 0)
+#define BMP580_INT_CONFIG_LATCH BIT(0)
+#define BMP580_INT_CONFIG_LEVEL BIT(1)
+#define BMP580_INT_CONFIG_OPEN_DRAIN BIT(2)
+#define BMP580_INT_CONFIG_INT_EN BIT(3)
+
#define BMP580_STATUS_CORE_RDY_MASK BIT(0)
#define BMP580_STATUS_NVM_RDY_MASK BIT(1)
#define BMP580_STATUS_NVM_ERR_MASK BIT(2)
@@ -170,6 +179,19 @@
#define BMP380_MODE_FORCED 1
#define BMP380_MODE_NORMAL 3
+#define BMP380_MEAS_OFFSET 234
+#define BMP380_MEAS_DUR 2020
+#define BMP380_TEMP_MEAS_OFFSET 163
+#define BMP380_PRESS_MEAS_OFFSET 392
+
+#define BMP380_INT_STATUS_DRDY BIT(3)
+
+#define BMP380_INT_CTRL_SETTINGS_MASK GENMASK(2, 0)
+#define BMP380_INT_CTRL_OPEN_DRAIN BIT(0)
+#define BMP380_INT_CTRL_LEVEL BIT(1)
+#define BMP380_INT_CTRL_LATCH BIT(2)
+#define BMP380_INT_CTRL_DRDY_EN BIT(6)
+
#define BMP380_MIN_TEMP -4000
#define BMP380_MAX_TEMP 8500
#define BMP380_MIN_PRES 3000000
@@ -205,6 +227,10 @@
#define BMP280_REG_CONFIG 0xF5
#define BMP280_REG_CTRL_MEAS 0xF4
#define BMP280_REG_STATUS 0xF3
+#define BMP280_REG_STATUS_IM_UPDATE BIT(0)
+#define BMP280_REG_STATUS_MEAS_BIT BIT(3)
+#define BMP280_REG_RESET 0xE0
+#define BMP280_RST_SOFT_CMD 0xB6
#define BMP280_REG_COMP_TEMP_START 0x88
#define BMP280_COMP_TEMP_REG_COUNT 6
@@ -243,6 +269,10 @@
#define BMP280_MODE_FORCED 1
#define BMP280_MODE_NORMAL 3
+#define BMP280_MEAS_OFFSET 1250
+#define BMP280_MEAS_DUR 2300
+#define BMP280_PRESS_HUMID_MEAS_OFFSET 575
+
/* BME280 specific registers */
#define BME280_REG_HUMIDITY_LSB 0xFE
#define BME280_REG_HUMIDITY_MSB 0xFD
@@ -257,8 +287,13 @@
#define BME280_REG_COMP_H5 0xE5
#define BME280_REG_COMP_H6 0xE7
+#define BME280_COMP_H4_GET_MASK_UP GENMASK(15, 8)
+#define BME280_COMP_H4_PREP_MASK_UP GENMASK(11, 4)
+#define BME280_COMP_H4_MASK_LOW GENMASK(3, 0)
#define BME280_COMP_H5_MASK GENMASK(15, 4)
+#define BME280_CONTIGUOUS_CALIB_REGS 7
+
#define BME280_OSRS_HUMIDITY_MASK GENMASK(2, 0)
#define BME280_OSRS_HUMIDITY_SKIP 0
#define BME280_OSRS_HUMIDITY_1X 1
@@ -314,6 +349,7 @@
BMP280_NUM_TEMP_BYTES + \
BME280_NUM_HUMIDITY_BYTES)
+#define BME280_NUM_MAX_CHANNELS 3
/* Core exported structs */
static const char *const bmp280_supply_names[] = {
@@ -376,12 +412,21 @@ struct bmp380_calib {
s8 P11;
};
+enum bmp280_op_mode {
+ BMP280_SLEEP,
+ BMP280_FORCED,
+ BMP280_NORMAL,
+};
+
struct bmp280_data {
struct device *dev;
struct mutex lock;
struct regmap *regmap;
struct completion done;
bool use_eoc;
+ bool trig_open_drain;
+ bool trig_active_high;
+ struct iio_trigger *trig;
const struct bmp280_chip_info *chip_info;
union {
struct bmp180_calib bmp180;
@@ -411,7 +456,11 @@ struct bmp280_data {
* Data to push to userspace triggered buffer. Up to 3 channels and
* s64 timestamp, aligned.
*/
- s32 sensor_data[6] __aligned(8);
+ u8 sensor_data[ALIGN(sizeof(s32) * BME280_NUM_MAX_CHANNELS, sizeof(s64))
+ + sizeof(s64)] __aligned(sizeof(s64));
+
+ /* Value to hold the current operation mode of the device */
+ enum bmp280_op_mode op_mode;
/*
* DMA (thus cache coherency maintenance) may require the
@@ -423,6 +472,7 @@ struct bmp280_data {
/* Calibration data buffers */
__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
+ u8 bme280_humid_cal_buf[BME280_CONTIGUOUS_CALIB_REGS];
u8 bmp380_cal_buf[BMP380_CALIB_REG_COUNT];
/* Miscellaneous, endianness-aware data buffers */
__le16 le16;
@@ -476,11 +526,15 @@ struct bmp280_chip_info {
int (*read_humid)(struct bmp280_data *data, u32 *adc_humidity);
int (*read_calib)(struct bmp280_data *data);
int (*preinit)(struct bmp280_data *data);
+ int (*set_mode)(struct bmp280_data *data, enum bmp280_op_mode mode);
+ int (*wait_conv)(struct bmp280_data *data);
+ int (*trigger_probe)(struct iio_dev *indio_dev);
irqreturn_t (*trigger_handler)(int irq, void *p);
};
/* Chip infos for each variant */
+extern const struct bmp280_chip_info bmp085_chip_info;
extern const struct bmp280_chip_info bmp180_chip_info;
extern const struct bmp280_chip_info bmp280_chip_info;
extern const struct bmp280_chip_info bme280_chip_info;
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 956045e2db29..dfc36430c467 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -24,7 +24,7 @@ struct press_state {
struct hid_sensor_hub_attribute_info press_attr;
struct {
u32 press_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -241,11 +241,11 @@ static int press_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_press_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "press";
struct iio_dev *indio_dev;
struct press_state *press_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct press_state));
@@ -325,7 +325,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_press_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct press_state *press_state = iio_priv(indio_dev);
@@ -350,7 +350,7 @@ static struct platform_driver hid_press_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_press_probe,
- .remove_new = hid_press_remove,
+ .remove = hid_press_remove,
};
module_platform_driver(hid_press_platform_driver);
diff --git a/drivers/iio/pressure/rohm-bm1390.c b/drivers/iio/pressure/rohm-bm1390.c
index ccaa07a569c9..f24d9f927681 100644
--- a/drivers/iio/pressure/rohm-bm1390.c
+++ b/drivers/iio/pressure/rohm-bm1390.c
@@ -417,9 +417,6 @@ static int __bm1390_fifo_flush(struct iio_dev *idev, unsigned int samples,
return ret;
}
- if (ret)
- return ret;
-
for (i = 0; i < smp_lvl; i++) {
buffer[i].temp = temp;
iio_push_to_buffers(idev, &buffer[i]);
diff --git a/drivers/iio/proximity/aw96103.c b/drivers/iio/proximity/aw96103.c
index 707ba0a510aa..cdd254da9e50 100644
--- a/drivers/iio/proximity/aw96103.c
+++ b/drivers/iio/proximity/aw96103.c
@@ -422,7 +422,7 @@ static int aw96103_read_event_config(struct iio_dev *indio_dev,
static int aw96103_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct aw96103 *aw96103 = iio_priv(indio_dev);
diff --git a/drivers/iio/proximity/cros_ec_mkbp_proximity.c b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
index c25472b14d4b..667369be0555 100644
--- a/drivers/iio/proximity/cros_ec_mkbp_proximity.c
+++ b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
@@ -167,7 +167,7 @@ static int cros_ec_mkbp_proximity_read_event_config(struct iio_dev *indio_dev,
static int cros_ec_mkbp_proximity_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct cros_ec_mkbp_proximity_data *data = iio_priv(indio_dev);
@@ -261,7 +261,7 @@ static struct platform_driver cros_ec_mkbp_proximity_driver = {
.pm = pm_sleep_ptr(&cros_ec_mkbp_proximity_pm_ops),
},
.probe = cros_ec_mkbp_proximity_probe,
- .remove_new = cros_ec_mkbp_proximity_remove,
+ .remove = cros_ec_mkbp_proximity_remove,
};
module_platform_driver(cros_ec_mkbp_proximity_driver);
diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c
index d8fb34060d3d..4021feb7a7ac 100644
--- a/drivers/iio/proximity/hx9023s.c
+++ b/drivers/iio/proximity/hx9023s.c
@@ -874,12 +874,12 @@ static int hx9023s_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct hx9023s_data *data = iio_priv(indio_dev);
if (test_bit(chan->channel, &data->chan_in_use)) {
- hx9023s_ch_en(data, chan->channel, !!state);
+ hx9023s_ch_en(data, chan->channel, state);
__assign_bit(chan->channel, &data->chan_event,
data->ch_data[chan->channel].enable);
}
diff --git a/drivers/iio/proximity/irsd200.c b/drivers/iio/proximity/irsd200.c
index 6e96b764fed8..b09d15230111 100644
--- a/drivers/iio/proximity/irsd200.c
+++ b/drivers/iio/proximity/irsd200.c
@@ -648,7 +648,8 @@ static int irsd200_read_event_config(struct iio_dev *indio_dev,
static int irsd200_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct irsd200_data *data = iio_priv(indio_dev);
unsigned int tmp;
@@ -662,7 +663,7 @@ static int irsd200_write_event_config(struct iio_dev *indio_dev,
return ret;
return regmap_field_write(
- data->regfields[IRS_REGF_INTR_COUNT_THR_OR], !!state);
+ data->regfields[IRS_REGF_INTR_COUNT_THR_OR], state);
default:
return -EINVAL;
}
diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c
index 86c57672fc7e..71ad29e441b2 100644
--- a/drivers/iio/proximity/srf04.c
+++ b/drivers/iio/proximity/srf04.c
@@ -389,7 +389,7 @@ static const struct dev_pm_ops srf04_pm_ops = {
static struct platform_driver srf04_driver = {
.probe = srf04_probe,
- .remove_new = srf04_remove,
+ .remove = srf04_remove,
.driver = {
.name = "srf04-gpio",
.of_match_table = of_srf04_match,
diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c
index 629f83c37d59..40747d7f6e7e 100644
--- a/drivers/iio/proximity/sx9324.c
+++ b/drivers/iio/proximity/sx9324.c
@@ -868,6 +868,26 @@ static u8 sx9324_parse_phase_prop(struct device *dev,
return raw;
}
+static void sx_common_get_raw_register_config(struct device *dev,
+ struct sx_common_reg_default *reg_def)
+{
+#ifdef CONFIG_ACPI
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ u32 raw = 0, ret;
+ char prop[80];
+
+ if (!reg_def->property || !adev)
+ return;
+
+ snprintf(prop, ARRAY_SIZE(prop), "%s,reg_%s", acpi_device_hid(adev), reg_def->property);
+ ret = device_property_read_u32(dev, prop, &raw);
+ if (ret)
+ return;
+
+ reg_def->def = raw;
+#endif
+}
+
static const struct sx_common_reg_default *
sx9324_get_default_reg(struct device *dev, int idx,
struct sx_common_reg_default *reg_def)
diff --git a/drivers/iio/proximity/sx9360.c b/drivers/iio/proximity/sx9360.c
index 2b90bf45a201..07551e0decbd 100644
--- a/drivers/iio/proximity/sx9360.c
+++ b/drivers/iio/proximity/sx9360.c
@@ -7,7 +7,6 @@
* https://edit.wpgdadawant.com/uploads/news_file/program/2019/30184/tech_files/program_30184_suggest_other_file.pdf
*/
-#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c
index 3f4eace05cfc..c4e94d0fb163 100644
--- a/drivers/iio/proximity/sx9500.c
+++ b/drivers/iio/proximity/sx9500.c
@@ -540,7 +540,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct sx9500_data *data = iio_priv(indio_dev);
int ret;
@@ -551,7 +551,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
mutex_lock(&data->mutex);
- if (state == 1) {
+ if (state) {
ret = sx9500_inc_chan_users(data, chan->channel);
if (ret < 0)
goto out_unlock;
@@ -571,7 +571,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
goto out_unlock;
out_undo_chan:
- if (state == 1)
+ if (state)
sx9500_dec_chan_users(data, chan->channel);
else
sx9500_inc_chan_users(data, chan->channel);
diff --git a/drivers/iio/proximity/sx_common.c b/drivers/iio/proximity/sx_common.c
index 71aa6dced7d3..76384c74fe01 100644
--- a/drivers/iio/proximity/sx_common.c
+++ b/drivers/iio/proximity/sx_common.c
@@ -268,7 +268,7 @@ EXPORT_SYMBOL_NS_GPL(sx_common_read_event_config, SEMTECH_PROX);
int sx_common_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct sx_common_data *data = iio_priv(indio_dev);
unsigned int eventirq = SX_COMMON_FAR_IRQ | SX_COMMON_CLOSE_IRQ;
@@ -421,27 +421,6 @@ static const struct iio_buffer_setup_ops sx_common_buffer_setup_ops = {
.postdisable = sx_common_buffer_postdisable,
};
-void sx_common_get_raw_register_config(struct device *dev,
- struct sx_common_reg_default *reg_def)
-{
-#ifdef CONFIG_ACPI
- struct acpi_device *adev = ACPI_COMPANION(dev);
- u32 raw = 0, ret;
- char prop[80];
-
- if (!reg_def->property || !adev)
- return;
-
- snprintf(prop, ARRAY_SIZE(prop), "%s,reg_%s", acpi_device_hid(adev), reg_def->property);
- ret = device_property_read_u32(dev, prop, &raw);
- if (ret)
- return;
-
- reg_def->def = raw;
-#endif
-}
-EXPORT_SYMBOL_NS_GPL(sx_common_get_raw_register_config, SEMTECH_PROX);
-
#define SX_COMMON_SOFT_RESET 0xde
static int sx_common_init_device(struct device *dev, struct iio_dev *indio_dev)
diff --git a/drivers/iio/proximity/sx_common.h b/drivers/iio/proximity/sx_common.h
index 101b90e52ff2..fb14e6f06a6d 100644
--- a/drivers/iio/proximity/sx_common.h
+++ b/drivers/iio/proximity/sx_common.h
@@ -8,7 +8,6 @@
#ifndef IIO_SX_COMMON_H
#define IIO_SX_COMMON_H
-#include <linux/acpi.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>
#include <linux/regulator/consumer.h>
@@ -144,15 +143,12 @@ int sx_common_read_event_config(struct iio_dev *indio_dev,
int sx_common_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state);
+ enum iio_event_direction dir, bool state);
int sx_common_probe(struct i2c_client *client,
const struct sx_common_chip_info *chip_info,
const struct regmap_config *regmap_config);
-void sx_common_get_raw_register_config(struct device *dev,
- struct sx_common_reg_default *reg_def);
-
/* 3 is the number of events defined by a single phase. */
extern const struct iio_event_spec sx_common_events[3];
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
index d1ddf85f5383..bb6c9cc88b35 100644
--- a/drivers/iio/proximity/vcnl3020.c
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -449,7 +449,7 @@ static int vcnl3020_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
switch (chan->type) {
case IIO_PROXIMITY:
diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c
index 8d4f3f849fe2..87d10faaff9b 100644
--- a/drivers/iio/proximity/vl53l0x-i2c.c
+++ b/drivers/iio/proximity/vl53l0x-i2c.c
@@ -20,8 +20,13 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#define VL_REG_SYSRANGE_START 0x00
@@ -39,21 +44,74 @@
#define VL_REG_RESULT_INT_STATUS 0x13
#define VL_REG_RESULT_RANGE_STATUS 0x14
+#define VL_REG_IDENTIFICATION_MODEL_ID 0xC0
#define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0)
+#define VL53L0X_MODEL_ID_VAL 0xEE
+#define VL53L0X_CONTINUOUS_MODE 0x02
+#define VL53L0X_SINGLE_MODE 0x01
+
struct vl53l0x_data {
struct i2c_client *client;
struct completion completion;
struct regulator *vdd_supply;
struct gpio_desc *reset_gpio;
+ struct iio_trigger *trig;
+
+ struct {
+ u16 chan;
+ aligned_s64 timestamp;
+ } scan;
};
-static irqreturn_t vl53l0x_handle_irq(int irq, void *priv)
+static int vl53l0x_clear_irq(struct vl53l0x_data *data)
+{ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ VL_REG_SYSTEM_INTERRUPT_CLEAR, 1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t vl53l0x_trigger_handler(int irq, void *priv)
+{
+ struct iio_poll_func *pf = priv;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+ u8 buffer[12];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(data->client,
+ VL_REG_RESULT_RANGE_STATUS,
+ sizeof(buffer), buffer);
+ if (ret < 0)
+ return ret;
+ else if (ret != 12)
+ return -EREMOTEIO;
+
+ data->scan.chan = get_unaligned_be16(&buffer[10]);
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ iio_get_time_ns(indio_dev));
+
+ iio_trigger_notify_done(indio_dev->trig);
+ vl53l0x_clear_irq(data);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vl53l0x_threaded_irq(int irq, void *priv)
{
struct iio_dev *indio_dev = priv;
struct vl53l0x_data *data = iio_priv(indio_dev);
- complete(&data->completion);
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll_nested(indio_dev->trig);
+ else
+ complete(&data->completion);
return IRQ_HANDLED;
}
@@ -68,8 +126,9 @@ static int vl53l0x_configure_irq(struct i2c_client *client,
if (!irq_flags)
irq_flags = IRQF_TRIGGER_FALLING;
- ret = devm_request_irq(&client->dev, client->irq, vl53l0x_handle_irq,
- irq_flags, indio_dev->name, indio_dev);
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vl53l0x_threaded_irq,
+ irq_flags | IRQF_ONESHOT, indio_dev->name, indio_dev);
if (ret) {
dev_err(&client->dev, "devm_request_irq error: %d\n", ret);
return ret;
@@ -84,26 +143,6 @@ static int vl53l0x_configure_irq(struct i2c_client *client,
return ret;
}
-static void vl53l0x_clear_irq(struct vl53l0x_data *data)
-{
- struct device *dev = &data->client->dev;
- int ret;
-
- ret = i2c_smbus_write_byte_data(data->client,
- VL_REG_SYSTEM_INTERRUPT_CLEAR, 1);
- if (ret < 0)
- dev_err(dev, "failed to clear error irq: %d\n", ret);
-
- ret = i2c_smbus_write_byte_data(data->client,
- VL_REG_SYSTEM_INTERRUPT_CLEAR, 0);
- if (ret < 0)
- dev_err(dev, "failed to clear range irq: %d\n", ret);
-
- ret = i2c_smbus_read_byte_data(data->client, VL_REG_RESULT_INT_STATUS);
- if (ret < 0 || ret & 0x07)
- dev_err(dev, "failed to clear irq: %d\n", ret);
-}
-
static int vl53l0x_read_proximity(struct vl53l0x_data *data,
const struct iio_chan_spec *chan,
int *val)
@@ -125,7 +164,9 @@ static int vl53l0x_read_proximity(struct vl53l0x_data *data,
if (time_left == 0)
return -ETIMEDOUT;
- vl53l0x_clear_irq(data);
+ ret = vl53l0x_clear_irq(data);
+ if (ret < 0)
+ return ret;
} else {
do {
ret = i2c_smbus_read_byte_data(client,
@@ -150,7 +191,7 @@ static int vl53l0x_read_proximity(struct vl53l0x_data *data,
return -EREMOTEIO;
/* Values should be between 30~1200 in millimeters. */
- *val = (buffer[10] << 8) + buffer[11];
+ *val = get_unaligned_be16(&buffer[10]);
return 0;
}
@@ -160,7 +201,14 @@ static const struct iio_chan_spec vl53l0x_channels[] = {
.type = IIO_DISTANCE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
},
+ IIO_CHAN_SOFT_TIMESTAMP(1),
};
static int vl53l0x_read_raw(struct iio_dev *indio_dev,
@@ -190,8 +238,16 @@ static int vl53l0x_read_raw(struct iio_dev *indio_dev,
}
}
+static int vl53l0x_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+
+ return data->trig == trig ? 0 : -EINVAL;
+}
+
static const struct iio_info vl53l0x_info = {
.read_raw = vl53l0x_read_raw,
+ .validate_trigger = vl53l0x_validate_trigger,
};
static void vl53l0x_power_off(void *_data)
@@ -218,11 +274,46 @@ static int vl53l0x_power_on(struct vl53l0x_data *data)
return 0;
}
+static int vl53l0x_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+
+ return i2c_smbus_write_byte_data(data->client, VL_REG_SYSRANGE_START,
+ VL53L0X_CONTINUOUS_MODE);
+}
+
+static int vl53l0x_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, VL_REG_SYSRANGE_START,
+ VL53L0X_SINGLE_MODE);
+ if (ret < 0)
+ return ret;
+
+ /* Let the ongoing reading finish */
+ reinit_completion(&data->completion);
+ wait_for_completion_timeout(&data->completion, HZ / 10);
+
+ return vl53l0x_clear_irq(data);
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+ .postenable = &vl53l0x_buffer_postenable,
+ .postdisable = &vl53l0x_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops vl53l0x_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
static int vl53l0x_probe(struct i2c_client *client)
{
struct vl53l0x_data *data;
struct iio_dev *indio_dev;
int error;
+ int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -237,6 +328,13 @@ static int vl53l0x_probe(struct i2c_client *client)
I2C_FUNC_SMBUS_BYTE_DATA))
return -EOPNOTSUPP;
+ ret = i2c_smbus_read_byte_data(data->client, VL_REG_IDENTIFICATION_MODEL_ID);
+ if (ret < 0)
+ return -EINVAL;
+
+ if (ret != VL53L0X_MODEL_ID_VAL)
+ dev_info(&client->dev, "Unknown model id: 0x%x", ret);
+
data->vdd_supply = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(data->vdd_supply))
return dev_err_probe(&client->dev, PTR_ERR(data->vdd_supply),
@@ -265,13 +363,33 @@ static int vl53l0x_probe(struct i2c_client *client)
/* usage of interrupt is optional */
if (client->irq) {
- int ret;
-
init_completion(&data->completion);
+ data->trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = &vl53l0x_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+ ret = devm_iio_trigger_register(&client->dev, data->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
ret = vl53l0x_configure_irq(client, indio_dev);
if (ret)
return ret;
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev,
+ indio_dev,
+ NULL,
+ &vl53l0x_trigger_handler,
+ &iio_triggered_buffer_setup_ops);
+ if (ret)
+ return ret;
}
return devm_iio_device_register(&client->dev, indio_dev);
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
index ed0e4963362f..1244d8e17d50 100644
--- a/drivers/iio/temperature/Kconfig
+++ b/drivers/iio/temperature/Kconfig
@@ -91,6 +91,8 @@ config MLX90635
config TMP006
tristate "TMP006 infrared thermopile sensor"
depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
If you say yes here you get support for the Texas Instruments
TMP006 infrared thermopile sensor.
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index 0143fd478933..0e21217472ab 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -18,7 +18,7 @@ struct temperature_state {
struct hid_sensor_hub_attribute_info temperature_attr;
struct {
s32 temperature_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -283,7 +283,7 @@ static struct platform_driver hid_temperature_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_temperature_probe,
- .remove_new = hid_temperature_remove,
+ .remove = hid_temperature_remove,
};
module_platform_driver(hid_temperature_platform_driver);
diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c
index f1bb0976273d..c2447860adfd 100644
--- a/drivers/iio/temperature/mcp9600.c
+++ b/drivers/iio/temperature/mcp9600.c
@@ -200,7 +200,7 @@ static int mcp9600_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mcp9600_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index 6d8d661f0c82..0c844137d7aa 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -7,8 +7,6 @@
* Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
*
* (7-bit I2C slave address 0x40, changeable via ADR pins)
- *
- * TODO: data ready irq
*/
#include <linux/err.h>
@@ -21,6 +19,9 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
#define TMP006_VOBJECT 0x00
#define TMP006_TAMBIENT 0x01
@@ -45,6 +46,7 @@
struct tmp006_data {
struct i2c_client *client;
u16 config;
+ struct iio_trigger *drdy_trig;
};
static int tmp006_read_measurement(struct tmp006_data *data, u8 reg)
@@ -83,15 +85,19 @@ static int tmp006_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_RAW:
if (channel->type == IIO_VOLTAGE) {
/* LSB is 156.25 nV */
- ret = tmp006_read_measurement(data, TMP006_VOBJECT);
- if (ret < 0)
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ ret = tmp006_read_measurement(data, TMP006_VOBJECT);
+ if (ret < 0)
+ return ret;
+ }
*val = sign_extend32(ret, 15);
} else if (channel->type == IIO_TEMP) {
/* LSB is 0.03125 degrees Celsius */
- ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
- if (ret < 0)
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
+ if (ret < 0)
+ return ret;
+ }
*val = sign_extend32(ret, 15) >> TMP006_TAMBIENT_SHIFT;
} else {
break;
@@ -128,7 +134,7 @@ static int tmp006_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct tmp006_data *data = iio_priv(indio_dev);
- int i;
+ int ret, i;
if (mask != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
@@ -136,13 +142,19 @@ static int tmp006_write_raw(struct iio_dev *indio_dev,
for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++)
if ((val == tmp006_freqs[i][0]) &&
(val2 == tmp006_freqs[i][1])) {
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
data->config &= ~TMP006_CONFIG_CR_MASK;
data->config |= i << TMP006_CONFIG_CR_SHIFT;
- return i2c_smbus_write_word_swapped(data->client,
- TMP006_CONFIG,
- data->config);
+ ret = i2c_smbus_write_word_swapped(data->client,
+ TMP006_CONFIG,
+ data->config);
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
}
return -EINVAL;
}
@@ -164,13 +176,29 @@ static const struct iio_chan_spec tmp006_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_BE,
+ }
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- }
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ .shift = TMP006_TAMBIENT_SHIFT,
+ .endianness = IIO_BE,
+ }
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(2),
};
static const struct iio_info tmp006_info = {
@@ -213,6 +241,54 @@ static void tmp006_powerdown_cleanup(void *dev)
tmp006_power(dev, false);
}
+static irqreturn_t tmp006_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct tmp006_data *data = iio_priv(indio_dev);
+ struct {
+ s16 channels[2];
+ s64 ts __aligned(8);
+ } scan;
+ s32 ret;
+
+ ret = i2c_smbus_read_word_data(data->client, TMP006_VOBJECT);
+ if (ret < 0)
+ goto err;
+ scan.channels[0] = ret;
+
+ ret = i2c_smbus_read_word_data(data->client, TMP006_TAMBIENT);
+ if (ret < 0)
+ goto err;
+ scan.channels[1] = ret;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
+ iio_get_time_ns(indio_dev));
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int tmp006_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct tmp006_data *data = iio_priv(indio_dev);
+
+ if (state)
+ data->config |= TMP006_CONFIG_DRDY_EN;
+ else
+ data->config &= ~TMP006_CONFIG_DRDY_EN;
+
+ return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
+ data->config);
+}
+
+static const struct iio_trigger_ops tmp006_trigger_ops = {
+ .set_trigger_state = tmp006_set_trigger_state,
+};
+
+static const unsigned long tmp006_scan_masks[] = { 0x3, 0 };
+
static int tmp006_probe(struct i2c_client *client)
{
struct iio_dev *indio_dev;
@@ -241,6 +317,7 @@ static int tmp006_probe(struct i2c_client *client)
indio_dev->channels = tmp006_channels;
indio_dev->num_channels = ARRAY_SIZE(tmp006_channels);
+ indio_dev->available_scan_masks = tmp006_scan_masks;
ret = i2c_smbus_read_word_swapped(data->client, TMP006_CONFIG);
if (ret < 0)
@@ -258,6 +335,37 @@ static int tmp006_probe(struct i2c_client *client)
if (ret < 0)
return ret;
+ if (client->irq > 0) {
+ data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
+ "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->drdy_trig)
+ return -ENOMEM;
+
+ data->drdy_trig->ops = &tmp006_trigger_ops;
+ iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
+ ret = iio_trigger_register(data->drdy_trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->drdy_trig);
+
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ iio_trigger_generic_data_rdy_poll,
+ NULL,
+ IRQF_ONESHOT,
+ "tmp006_irq",
+ data->drdy_trig);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ tmp006_trigger_handler, NULL);
+ if (ret < 0)
+ return ret;
+
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
index 9bdfa9423492..fd4d389ce1df 100644
--- a/drivers/iio/temperature/tmp007.c
+++ b/drivers/iio/temperature/tmp007.c
@@ -216,7 +216,7 @@ static irqreturn_t tmp007_interrupt_handler(int irq, void *private)
static int tmp007_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tmp007_data *data = iio_priv(indio_dev);
unsigned int status_mask;
diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c
index dec256bfbd73..21c6b6292a72 100644
--- a/drivers/iio/trigger/iio-trig-interrupt.c
+++ b/drivers/iio/trigger/iio-trig-interrupt.c
@@ -96,7 +96,7 @@ static void iio_interrupt_trigger_remove(struct platform_device *pdev)
static struct platform_driver iio_interrupt_trigger_driver = {
.probe = iio_interrupt_trigger_probe,
- .remove_new = iio_interrupt_trigger_remove,
+ .remove = iio_interrupt_trigger_remove,
.driver = {
.name = "iio_interrupt_trigger",
},
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
index 0684329956d9..bb60b2d7b2ec 100644
--- a/drivers/iio/trigger/stm32-timer-trigger.c
+++ b/drivers/iio/trigger/stm32-timer-trigger.c
@@ -900,7 +900,7 @@ MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
static struct platform_driver stm32_timer_trigger_driver = {
.probe = stm32_timer_trigger_probe,
- .remove_new = stm32_timer_trigger_remove,
+ .remove = stm32_timer_trigger_remove,
.driver = {
.name = "stm32-timer-trigger",
.of_match_table = stm32_trig_of_match,
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index c4cf26f1d149..be0743dac3ff 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -269,8 +269,6 @@ rdma_find_ndev_for_src_ip_rcu(struct net *net, const struct sockaddr *src_in)
break;
#endif
}
- if (!ret && dev && is_vlan_dev(dev))
- dev = vlan_dev_real_dev(dev);
return ret ? ERR_PTR(ret) : dev;
}
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 07fb8d3c037f..142170473e75 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -35,6 +35,8 @@ MODULE_DESCRIPTION("InfiniBand CM");
MODULE_LICENSE("Dual BSD/GPL");
#define CM_DESTROY_ID_WAIT_TIMEOUT 10000 /* msecs */
+#define CM_DIRECT_RETRY_CTX ((void *) 1UL)
+
static const char * const ibcm_rej_reason_strs[] = {
[IB_CM_REJ_NO_QP] = "no QP",
[IB_CM_REJ_NO_EEC] = "no EEC",
@@ -93,8 +95,7 @@ static void cm_process_work(struct cm_id_private *cm_id_priv,
struct cm_work *work);
static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv,
struct ib_cm_sidr_rep_param *param);
-static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
- const void *private_data, u8 private_data_len);
+static void cm_issue_dreq(struct cm_id_private *cm_id_priv);
static int cm_send_drep_locked(struct cm_id_private *cm_id_priv,
void *private_data, u8 private_data_len);
static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
@@ -307,12 +308,7 @@ static struct ib_mad_send_buf *cm_alloc_msg(struct cm_id_private *cm_id_priv)
goto out;
}
- /* Timeout set by caller if response is expected. */
m->ah = ah;
- m->retries = cm_id_priv->max_cm_retries;
-
- refcount_inc(&cm_id_priv->refcount);
- m->context[0] = cm_id_priv;
out:
spin_unlock(&cm_id_priv->av.port->cm_dev->mad_agent_lock);
@@ -321,16 +317,13 @@ out:
static void cm_free_msg(struct ib_mad_send_buf *msg)
{
- struct cm_id_private *cm_id_priv = msg->context[0];
-
if (msg->ah)
rdma_destroy_ah(msg->ah, 0);
- cm_deref_id(cm_id_priv);
ib_free_send_mad(msg);
}
static struct ib_mad_send_buf *
-cm_alloc_priv_msg(struct cm_id_private *cm_id_priv)
+cm_alloc_priv_msg(struct cm_id_private *cm_id_priv, enum ib_cm_state state)
{
struct ib_mad_send_buf *msg;
@@ -339,7 +332,15 @@ cm_alloc_priv_msg(struct cm_id_private *cm_id_priv)
msg = cm_alloc_msg(cm_id_priv);
if (IS_ERR(msg))
return msg;
+
cm_id_priv->msg = msg;
+ refcount_inc(&cm_id_priv->refcount);
+ msg->context[0] = cm_id_priv;
+ msg->context[1] = (void *) (unsigned long) state;
+
+ msg->retries = cm_id_priv->max_cm_retries;
+ msg->timeout_ms = cm_id_priv->timeout_ms;
+
return msg;
}
@@ -358,13 +359,20 @@ static void cm_free_priv_msg(struct ib_mad_send_buf *msg)
ib_free_send_mad(msg);
}
-static struct ib_mad_send_buf *cm_alloc_response_msg_no_ah(struct cm_port *port,
- struct ib_mad_recv_wc *mad_recv_wc)
+static struct ib_mad_send_buf *
+cm_alloc_response_msg_no_ah(struct cm_port *port,
+ struct ib_mad_recv_wc *mad_recv_wc,
+ bool direct_retry)
{
- return ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
- 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
- GFP_ATOMIC,
- IB_MGMT_BASE_VERSION);
+ struct ib_mad_send_buf *m;
+
+ m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
+ 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
+ GFP_ATOMIC, IB_MGMT_BASE_VERSION);
+ if (!IS_ERR(m))
+ m->context[0] = direct_retry ? CM_DIRECT_RETRY_CTX : NULL;
+
+ return m;
}
static int cm_create_response_msg_ah(struct cm_port *port,
@@ -384,12 +392,13 @@ static int cm_create_response_msg_ah(struct cm_port *port,
static int cm_alloc_response_msg(struct cm_port *port,
struct ib_mad_recv_wc *mad_recv_wc,
+ bool direct_retry,
struct ib_mad_send_buf **msg)
{
struct ib_mad_send_buf *m;
int ret;
- m = cm_alloc_response_msg_no_ah(port, mad_recv_wc);
+ m = cm_alloc_response_msg_no_ah(port, mad_recv_wc, direct_retry);
if (IS_ERR(m))
return PTR_ERR(m);
@@ -403,13 +412,6 @@ static int cm_alloc_response_msg(struct cm_port *port,
return 0;
}
-static void cm_free_response_msg(struct ib_mad_send_buf *msg)
-{
- if (msg->ah)
- rdma_destroy_ah(msg->ah, 0);
- ib_free_send_mad(msg);
-}
-
static void *cm_copy_private_data(const void *private_data, u8 private_data_len)
{
void *data;
@@ -1109,7 +1111,8 @@ retest:
cm_id->state = IB_CM_IDLE;
break;
}
- cm_send_dreq_locked(cm_id_priv, NULL, 0);
+ cm_issue_dreq(cm_id_priv);
+ cm_enter_timewait(cm_id_priv);
goto retest;
case IB_CM_DREQ_SENT:
ib_cancel_mad(cm_id_priv->msg);
@@ -1557,7 +1560,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
if (param->alternate_path)
cm_move_av_from_path(&cm_id_priv->alt_av, &alt_av);
- msg = cm_alloc_priv_msg(cm_id_priv);
+ msg = cm_alloc_priv_msg(cm_id_priv, IB_CM_REQ_SENT);
if (IS_ERR(msg)) {
ret = PTR_ERR(msg);
goto out_unlock;
@@ -1566,8 +1569,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
req_msg = (struct cm_req_msg *)msg->mad;
cm_format_req(req_msg, cm_id_priv, param);
cm_id_priv->tid = req_msg->hdr.tid;
- msg->timeout_ms = cm_id_priv->timeout_ms;
- msg->context[1] = (void *)(unsigned long)IB_CM_REQ_SENT;
cm_id_priv->local_qpn = cpu_to_be32(IBA_GET(CM_REQ_LOCAL_QPN, req_msg));
cm_id_priv->rq_psn = cpu_to_be32(IBA_GET(CM_REQ_STARTING_PSN, req_msg));
@@ -1598,7 +1599,7 @@ static int cm_issue_rej(struct cm_port *port,
struct cm_rej_msg *rej_msg, *rcv_msg;
int ret;
- ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);
+ ret = cm_alloc_response_msg(port, mad_recv_wc, false, &msg);
if (ret)
return ret;
@@ -1624,7 +1625,7 @@ static int cm_issue_rej(struct cm_port *port,
IBA_GET(CM_REJ_REMOTE_COMM_ID, rcv_msg));
ret = ib_post_send_mad(msg, NULL);
if (ret)
- cm_free_response_msg(msg);
+ cm_free_msg(msg);
return ret;
}
@@ -1951,7 +1952,7 @@ static void cm_dup_req_handler(struct cm_work *work,
}
spin_unlock_irq(&cm_id_priv->lock);
- ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
+ ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, true, &msg);
if (ret)
return;
@@ -1980,7 +1981,7 @@ static void cm_dup_req_handler(struct cm_work *work,
return;
unlock: spin_unlock_irq(&cm_id_priv->lock);
-free: cm_free_response_msg(msg);
+free: cm_free_msg(msg);
}
static struct cm_id_private *cm_match_req(struct cm_work *work,
@@ -2294,7 +2295,7 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
goto out;
}
- msg = cm_alloc_priv_msg(cm_id_priv);
+ msg = cm_alloc_priv_msg(cm_id_priv, IB_CM_REP_SENT);
if (IS_ERR(msg)) {
ret = PTR_ERR(msg);
goto out;
@@ -2302,8 +2303,6 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
rep_msg = (struct cm_rep_msg *) msg->mad;
cm_format_rep(rep_msg, cm_id_priv, param);
- msg->timeout_ms = cm_id_priv->timeout_ms;
- msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;
trace_icm_send_rep(cm_id);
ret = ib_post_send_mad(msg, NULL);
@@ -2444,7 +2443,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
atomic_long_inc(
&work->port->counters[CM_RECV_DUPLICATES][CM_REP_COUNTER]);
- ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
+ ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, true, &msg);
if (ret)
goto deref;
@@ -2469,7 +2468,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
goto deref;
unlock: spin_unlock_irq(&cm_id_priv->lock);
-free: cm_free_response_msg(msg);
+free: cm_free_msg(msg);
deref: cm_deref_id(cm_id_priv);
}
@@ -2653,59 +2652,68 @@ static void cm_format_dreq(struct cm_dreq_msg *dreq_msg,
private_data_len);
}
-static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
- const void *private_data, u8 private_data_len)
+static void cm_issue_dreq(struct cm_id_private *cm_id_priv)
{
struct ib_mad_send_buf *msg;
int ret;
lockdep_assert_held(&cm_id_priv->lock);
+ msg = cm_alloc_msg(cm_id_priv);
+ if (IS_ERR(msg))
+ return;
+
+ cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv, NULL, 0);
+
+ trace_icm_send_dreq(&cm_id_priv->id);
+ ret = ib_post_send_mad(msg, NULL);
+ if (ret)
+ cm_free_msg(msg);
+}
+
+int ib_send_cm_dreq(struct ib_cm_id *cm_id, const void *private_data,
+ u8 private_data_len)
+{
+ struct cm_id_private *cm_id_priv =
+ container_of(cm_id, struct cm_id_private, id);
+ struct ib_mad_send_buf *msg;
+ unsigned long flags;
+ int ret;
+
if (private_data && private_data_len > IB_CM_DREQ_PRIVATE_DATA_SIZE)
return -EINVAL;
+ spin_lock_irqsave(&cm_id_priv->lock, flags);
if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {
trace_icm_dreq_skipped(&cm_id_priv->id);
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
if (cm_id_priv->id.lap_state == IB_CM_LAP_SENT ||
cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
ib_cancel_mad(cm_id_priv->msg);
- msg = cm_alloc_priv_msg(cm_id_priv);
+ msg = cm_alloc_priv_msg(cm_id_priv, IB_CM_DREQ_SENT);
if (IS_ERR(msg)) {
cm_enter_timewait(cm_id_priv);
- return PTR_ERR(msg);
+ ret = PTR_ERR(msg);
+ goto unlock;
}
cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
private_data, private_data_len);
- msg->timeout_ms = cm_id_priv->timeout_ms;
- msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT;
trace_icm_send_dreq(&cm_id_priv->id);
ret = ib_post_send_mad(msg, NULL);
if (ret) {
cm_enter_timewait(cm_id_priv);
cm_free_priv_msg(msg);
- return ret;
+ goto unlock;
}
cm_id_priv->id.state = IB_CM_DREQ_SENT;
- return 0;
-}
-
-int ib_send_cm_dreq(struct ib_cm_id *cm_id, const void *private_data,
- u8 private_data_len)
-{
- struct cm_id_private *cm_id_priv =
- container_of(cm_id, struct cm_id_private, id);
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&cm_id_priv->lock, flags);
- ret = cm_send_dreq_locked(cm_id_priv, private_data, private_data_len);
+unlock:
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
return ret;
}
@@ -2791,7 +2799,7 @@ static int cm_issue_drep(struct cm_port *port,
struct cm_drep_msg *drep_msg;
int ret;
- ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);
+ ret = cm_alloc_response_msg(port, mad_recv_wc, true, &msg);
if (ret)
return ret;
@@ -2809,7 +2817,7 @@ static int cm_issue_drep(struct cm_port *port,
IBA_GET(CM_DREQ_REMOTE_COMM_ID, dreq_msg));
ret = ib_post_send_mad(msg, NULL);
if (ret)
- cm_free_response_msg(msg);
+ cm_free_msg(msg);
return ret;
}
@@ -2856,7 +2864,8 @@ static int cm_dreq_handler(struct cm_work *work)
case IB_CM_TIMEWAIT:
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_DREQ_COUNTER]);
- msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc);
+ msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc,
+ true);
if (IS_ERR(msg))
goto unlock;
@@ -2867,7 +2876,7 @@ static int cm_dreq_handler(struct cm_work *work)
if (cm_create_response_msg_ah(work->port, work->mad_recv_wc, msg) ||
ib_post_send_mad(msg, NULL))
- cm_free_response_msg(msg);
+ cm_free_msg(msg);
goto deref;
case IB_CM_DREQ_RCVD:
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
@@ -3361,7 +3370,8 @@ static int cm_lap_handler(struct cm_work *work)
case IB_CM_MRA_LAP_SENT:
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_LAP_COUNTER]);
- msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc);
+ msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc,
+ true);
if (IS_ERR(msg))
goto unlock;
@@ -3374,7 +3384,7 @@ static int cm_lap_handler(struct cm_work *work)
if (cm_create_response_msg_ah(work->port, work->mad_recv_wc, msg) ||
ib_post_send_mad(msg, NULL))
- cm_free_response_msg(msg);
+ cm_free_msg(msg);
goto deref;
case IB_CM_LAP_RCVD:
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
@@ -3513,7 +3523,7 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
goto out_unlock;
}
- msg = cm_alloc_priv_msg(cm_id_priv);
+ msg = cm_alloc_priv_msg(cm_id_priv, IB_CM_SIDR_REQ_SENT);
if (IS_ERR(msg)) {
ret = PTR_ERR(msg);
goto out_unlock;
@@ -3521,8 +3531,6 @@ int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
cm_format_sidr_req((struct cm_sidr_req_msg *)msg->mad, cm_id_priv,
param);
- msg->timeout_ms = cm_id_priv->timeout_ms;
- msg->context[1] = (void *)(unsigned long)IB_CM_SIDR_REQ_SENT;
trace_icm_send_sidr_req(&cm_id_priv->id);
ret = ib_post_send_mad(msg, NULL);
@@ -3768,17 +3776,17 @@ out:
static void cm_process_send_error(struct cm_id_private *cm_id_priv,
struct ib_mad_send_buf *msg,
- enum ib_cm_state state,
enum ib_wc_status wc_status)
{
+ enum ib_cm_state state = (unsigned long) msg->context[1];
struct ib_cm_event cm_event = {};
int ret;
- /* Discard old sends or ones without a response. */
+ /* Discard old sends. */
spin_lock_irq(&cm_id_priv->lock);
if (msg != cm_id_priv->msg) {
spin_unlock_irq(&cm_id_priv->lock);
- cm_free_msg(msg);
+ cm_free_priv_msg(msg);
return;
}
cm_free_priv_msg(msg);
@@ -3826,9 +3834,7 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
struct ib_mad_send_wc *mad_send_wc)
{
struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
- struct cm_id_private *cm_id_priv = msg->context[0];
- enum ib_cm_state state =
- (enum ib_cm_state)(unsigned long)msg->context[1];
+ struct cm_id_private *cm_id_priv;
struct cm_port *port;
u16 attr_index;
@@ -3836,13 +3842,12 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
attr_index = be16_to_cpu(((struct ib_mad_hdr *)
msg->mad)->attr_id) - CM_ATTR_ID_OFFSET;
- /*
- * If the send was in response to a received message (context[0] is not
- * set to a cm_id), and is not a REJ, then it is a send that was
- * manually retried.
- */
- if (!cm_id_priv && (attr_index != CM_REJ_COUNTER))
+ if (msg->context[0] == CM_DIRECT_RETRY_CTX) {
msg->retries = 1;
+ cm_id_priv = NULL;
+ } else {
+ cm_id_priv = msg->context[0];
+ }
atomic_long_add(1 + msg->retries, &port->counters[CM_XMIT][attr_index]);
if (msg->retries)
@@ -3850,10 +3855,9 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
&port->counters[CM_XMIT_RETRIES][attr_index]);
if (cm_id_priv)
- cm_process_send_error(cm_id_priv, msg, state,
- mad_send_wc->status);
+ cm_process_send_error(cm_id_priv, msg, mad_send_wc->status);
else
- cm_free_response_msg(msg);
+ cm_free_msg(msg);
}
static void cm_work_handler(struct work_struct *_work)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index e029401b5680..ca9b956c034d 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -437,6 +437,7 @@ int ib_device_rename(struct ib_device *ibdev, const char *name)
client->rename(ibdev, client_data);
}
up_read(&ibdev->client_data_rwsem);
+ rdma_nl_notify_event(ibdev, 0, RDMA_RENAME_EVENT);
up_read(&devices_rwsem);
return 0;
}
@@ -2759,6 +2760,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
SET_DEVICE_OP(dev_ops, resize_cq);
SET_DEVICE_OP(dev_ops, set_vf_guid);
SET_DEVICE_OP(dev_ops, set_vf_link_state);
+ SET_DEVICE_OP(dev_ops, ufile_hw_cleanup);
SET_OBJ_SIZE(dev_ops, ib_ah);
SET_OBJ_SIZE(dev_ops, ib_counters);
@@ -2852,6 +2854,40 @@ static const struct rdma_nl_cbs ibnl_ls_cb_table[RDMA_NL_LS_NUM_OPS] = {
},
};
+static int ib_netdevice_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
+ struct net_device *ib_ndev;
+ struct ib_device *ibdev;
+ u32 port;
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+ ibdev = ib_device_get_by_netdev(ndev, RDMA_DRIVER_UNKNOWN);
+ if (!ibdev)
+ return NOTIFY_DONE;
+
+ rdma_for_each_port(ibdev, port) {
+ ib_ndev = ib_device_get_netdev(ibdev, port);
+ if (ndev == ib_ndev)
+ rdma_nl_notify_event(ibdev, port,
+ RDMA_NETDEV_RENAME_EVENT);
+ dev_put(ib_ndev);
+ }
+ ib_device_put(ibdev);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block nb_netdevice = {
+ .notifier_call = ib_netdevice_event,
+};
+
static int __init ib_core_init(void)
{
int ret = -ENOMEM;
@@ -2923,6 +2959,8 @@ static int __init ib_core_init(void)
goto err_parent;
}
+ register_netdevice_notifier(&nb_netdevice);
+
return 0;
err_parent:
@@ -2952,6 +2990,7 @@ err:
static void __exit ib_core_cleanup(void)
{
+ unregister_netdevice_notifier(&nb_netdevice);
roce_gid_mgmt_cleanup();
rdma_nl_unregister(RDMA_NL_LS);
nldev_exit();
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 7dc8e2ec62cc..ff121e59b9c0 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -2729,6 +2729,25 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
},
};
+static int fill_mon_netdev_rename(struct sk_buff *msg,
+ struct ib_device *device, u32 port,
+ const struct net *net)
+{
+ struct net_device *netdev = ib_device_get_netdev(device, port);
+ int ret = 0;
+
+ if (!netdev || !net_eq(dev_net(netdev), net))
+ goto out;
+
+ ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_NDEV_INDEX, netdev->ifindex);
+ if (ret)
+ goto out;
+ ret = nla_put_string(msg, RDMA_NLDEV_ATTR_NDEV_NAME, netdev->name);
+out:
+ dev_put(netdev);
+ return ret;
+}
+
static int fill_mon_netdev_association(struct sk_buff *msg,
struct ib_device *device, u32 port,
const struct net *net)
@@ -2793,6 +2812,18 @@ static void rdma_nl_notify_err_msg(struct ib_device *device, u32 port_num,
"Failed to send RDMA monitor netdev detach event: port %d\n",
port_num);
break;
+ case RDMA_RENAME_EVENT:
+ dev_warn_ratelimited(&device->dev,
+ "Failed to send RDMA monitor rename device event\n");
+ break;
+
+ case RDMA_NETDEV_RENAME_EVENT:
+ netdev = ib_device_get_netdev(device, port_num);
+ dev_warn_ratelimited(&device->dev,
+ "Failed to send RDMA monitor netdev rename event: port %d netdev %d\n",
+ port_num, netdev->ifindex);
+ dev_put(netdev);
+ break;
default:
break;
}
@@ -2822,14 +2853,19 @@ int rdma_nl_notify_event(struct ib_device *device, u32 port_num,
switch (type) {
case RDMA_REGISTER_EVENT:
case RDMA_UNREGISTER_EVENT:
+ case RDMA_RENAME_EVENT:
ret = fill_nldev_handle(skb, device);
if (ret)
goto err_free;
break;
case RDMA_NETDEV_ATTACH_EVENT:
case RDMA_NETDEV_DETACH_EVENT:
- ret = fill_mon_netdev_association(skb, device,
- port_num, net);
+ ret = fill_mon_netdev_association(skb, device, port_num, net);
+ if (ret)
+ goto err_free;
+ break;
+ case RDMA_NETDEV_RENAME_EVENT:
+ ret = fill_mon_netdev_rename(skb, device, port_num, net);
if (ret)
goto err_free;
break;
diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index 29b1ab1d5f93..90c177edf9b0 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -58,8 +58,8 @@ void uverbs_uobject_put(struct ib_uobject *uobject)
}
EXPORT_SYMBOL(uverbs_uobject_put);
-static int uverbs_try_lock_object(struct ib_uobject *uobj,
- enum rdma_lookup_mode mode)
+int uverbs_try_lock_object(struct ib_uobject *uobj,
+ enum rdma_lookup_mode mode)
{
/*
* When a shared access is required, we use a positive counter. Each
@@ -84,6 +84,7 @@ static int uverbs_try_lock_object(struct ib_uobject *uobj,
}
return 0;
}
+EXPORT_SYMBOL(uverbs_try_lock_object);
static void assert_uverbs_usecnt(struct ib_uobject *uobj,
enum rdma_lookup_mode mode)
@@ -880,9 +881,14 @@ static void ufile_destroy_ucontext(struct ib_uverbs_file *ufile,
static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,
enum rdma_remove_reason reason)
{
+ struct uverbs_attr_bundle attrs = { .ufile = ufile };
+ struct ib_ucontext *ucontext = ufile->ucontext;
+ struct ib_device *ib_dev = ucontext->device;
struct ib_uobject *obj, *next_obj;
int ret = -EINVAL;
- struct uverbs_attr_bundle attrs = { .ufile = ufile };
+
+ if (ib_dev->ops.ufile_hw_cleanup)
+ ib_dev->ops.ufile_hw_cleanup(ufile);
/*
* This shouldn't run while executing other commands on this
diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c
index d5131b3ba8ab..a9f2c6b1b29e 100644
--- a/drivers/infiniband/core/roce_gid_mgmt.c
+++ b/drivers/infiniband/core/roce_gid_mgmt.c
@@ -515,6 +515,27 @@ void rdma_roce_rescan_device(struct ib_device *ib_dev)
}
EXPORT_SYMBOL(rdma_roce_rescan_device);
+/**
+ * rdma_roce_rescan_port - Rescan all of the network devices in the system
+ * and add their gids if relevant to the port of the RoCE device.
+ *
+ * @ib_dev: IB device
+ * @port: Port number
+ */
+void rdma_roce_rescan_port(struct ib_device *ib_dev, u32 port)
+{
+ struct net_device *ndev = NULL;
+
+ if (rdma_protocol_roce(ib_dev, port)) {
+ ndev = ib_device_get_netdev(ib_dev, port);
+ if (!ndev)
+ return;
+ enum_all_gids_of_dev_cb(ib_dev, port, ndev, ndev);
+ dev_put(ndev);
+ }
+}
+EXPORT_SYMBOL(rdma_roce_rescan_port);
+
static void callback_for_addr_gid_device_scan(struct ib_device *device,
u32 port,
struct net_device *rdma_ndev,
@@ -575,16 +596,17 @@ static void handle_netdev_upper(struct ib_device *ib_dev, u32 port,
}
}
-static void _roce_del_all_netdev_gids(struct ib_device *ib_dev, u32 port,
- struct net_device *event_ndev)
+void roce_del_all_netdev_gids(struct ib_device *ib_dev,
+ u32 port, struct net_device *ndev)
{
- ib_cache_gid_del_all_netdev_gids(ib_dev, port, event_ndev);
+ ib_cache_gid_del_all_netdev_gids(ib_dev, port, ndev);
}
+EXPORT_SYMBOL(roce_del_all_netdev_gids);
static void del_netdev_upper_ips(struct ib_device *ib_dev, u32 port,
struct net_device *rdma_ndev, void *cookie)
{
- handle_netdev_upper(ib_dev, port, cookie, _roce_del_all_netdev_gids);
+ handle_netdev_upper(ib_dev, port, cookie, roce_del_all_netdev_gids);
}
static void add_netdev_upper_ips(struct ib_device *ib_dev, u32 port,
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 5dbb248e9625..02f1666f3cba 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -1615,7 +1615,6 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
struct ucma_event *uevent, *tmp;
struct ucma_context *ctx;
LIST_HEAD(event_list);
- struct fd f;
struct ucma_file *cur_file;
int ret = 0;
@@ -1623,21 +1622,17 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
return -EFAULT;
/* Get current fd to protect against it being closed */
- f = fdget(cmd.fd);
- if (!fd_file(f))
+ CLASS(fd, f)(cmd.fd);
+ if (fd_empty(f))
return -ENOENT;
- if (fd_file(f)->f_op != &ucma_fops) {
- ret = -EINVAL;
- goto file_put;
- }
+ if (fd_file(f)->f_op != &ucma_fops)
+ return -EINVAL;
cur_file = fd_file(f)->private_data;
/* Validate current fd and prevent destruction of id. */
ctx = ucma_get_ctx(cur_file, cmd.id);
- if (IS_ERR(ctx)) {
- ret = PTR_ERR(ctx);
- goto file_put;
- }
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
rdma_lock_handler(ctx->cm_id);
/*
@@ -1678,8 +1673,6 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
err_unlock:
rdma_unlock_handler(ctx->cm_id);
ucma_put_ctx(ctx);
-file_put:
- fdput(f);
return ret;
}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 821d93c8f712..797e2fcc8072 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -133,35 +133,6 @@ struct ib_uverbs_completion_event_file {
struct ib_uverbs_event_queue ev_queue;
};
-struct ib_uverbs_file {
- struct kref ref;
- struct ib_uverbs_device *device;
- struct mutex ucontext_lock;
- /*
- * ucontext must be accessed via ib_uverbs_get_ucontext() or with
- * ucontext_lock held
- */
- struct ib_ucontext *ucontext;
- struct ib_uverbs_async_event_file *default_async_file;
- struct list_head list;
-
- /*
- * To access the uobjects list hw_destroy_rwsem must be held for write
- * OR hw_destroy_rwsem held for read AND uobjects_lock held.
- * hw_destroy_rwsem should be called across any destruction of the HW
- * object of an associated uobject.
- */
- struct rw_semaphore hw_destroy_rwsem;
- spinlock_t uobjects_lock;
- struct list_head uobjects;
-
- struct mutex umap_lock;
- struct list_head umaps;
- struct page *disassociate_page;
-
- struct xarray idr;
-};
-
struct ib_uverbs_event {
union {
struct ib_uverbs_async_event_desc async;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index a4cce360df21..66b02fbf077a 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -584,7 +584,7 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
if (cmd.fd != -1) {
/* search for file descriptor */
f = fdget(cmd.fd);
- if (!fd_file(f)) {
+ if (fd_empty(f)) {
ret = -EBADF;
goto err_tree_mutex_unlock;
}
@@ -632,8 +632,7 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
atomic_inc(&xrcd->usecnt);
}
- if (fd_file(f))
- fdput(f);
+ fdput(f);
mutex_unlock(&ibudev->xrcd_tree_mutex);
uobj_finalize_uobj_create(&obj->uobject, attrs);
@@ -648,8 +647,7 @@ err:
uobj_alloc_abort(&obj->uobject, attrs);
err_tree_mutex_unlock:
- if (fd_file(f))
- fdput(f);
+ fdput(f);
mutex_unlock(&ibudev->xrcd_tree_mutex);
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 94454186ed81..85cfc790a7bb 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -76,6 +76,7 @@ static dev_t dynamic_uverbs_dev;
static DEFINE_IDA(uverbs_ida);
static int ib_uverbs_add_one(struct ib_device *device);
static void ib_uverbs_remove_one(struct ib_device *device, void *client_data);
+static struct ib_client uverbs_client;
static char *uverbs_devnode(const struct device *dev, umode_t *mode)
{
@@ -217,6 +218,7 @@ void ib_uverbs_release_file(struct kref *ref)
if (file->disassociate_page)
__free_pages(file->disassociate_page, 0);
+ mutex_destroy(&file->disassociation_lock);
mutex_destroy(&file->umap_lock);
mutex_destroy(&file->ucontext_lock);
kfree(file);
@@ -698,8 +700,13 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
ret = PTR_ERR(ucontext);
goto out;
}
+
+ mutex_lock(&file->disassociation_lock);
+
vma->vm_ops = &rdma_umap_ops;
ret = ucontext->device->ops.mmap(ucontext, vma);
+
+ mutex_unlock(&file->disassociation_lock);
out:
srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
return ret;
@@ -721,6 +728,8 @@ static void rdma_umap_open(struct vm_area_struct *vma)
/* We are racing with disassociation */
if (!down_read_trylock(&ufile->hw_destroy_rwsem))
goto out_zap;
+ mutex_lock(&ufile->disassociation_lock);
+
/*
* Disassociation already completed, the VMA should already be zapped.
*/
@@ -732,10 +741,12 @@ static void rdma_umap_open(struct vm_area_struct *vma)
goto out_unlock;
rdma_umap_priv_init(priv, vma, opriv->entry);
+ mutex_unlock(&ufile->disassociation_lock);
up_read(&ufile->hw_destroy_rwsem);
return;
out_unlock:
+ mutex_unlock(&ufile->disassociation_lock);
up_read(&ufile->hw_destroy_rwsem);
out_zap:
/*
@@ -819,7 +830,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
{
struct rdma_umap_priv *priv, *next_priv;
- lockdep_assert_held(&ufile->hw_destroy_rwsem);
+ mutex_lock(&ufile->disassociation_lock);
while (1) {
struct mm_struct *mm = NULL;
@@ -845,8 +856,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
break;
}
mutex_unlock(&ufile->umap_lock);
- if (!mm)
+ if (!mm) {
+ mutex_unlock(&ufile->disassociation_lock);
return;
+ }
/*
* The umap_lock is nested under mmap_lock since it used within
@@ -876,7 +889,31 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
mmap_read_unlock(mm);
mmput(mm);
}
+
+ mutex_unlock(&ufile->disassociation_lock);
+}
+
+/**
+ * rdma_user_mmap_disassociate() - Revoke mmaps for a device
+ * @device: device to revoke
+ *
+ * This function should be called by drivers that need to disable mmaps for the
+ * device, for instance because it is going to be reset.
+ */
+void rdma_user_mmap_disassociate(struct ib_device *device)
+{
+ struct ib_uverbs_device *uverbs_dev =
+ ib_get_client_data(device, &uverbs_client);
+ struct ib_uverbs_file *ufile;
+
+ mutex_lock(&uverbs_dev->lists_mutex);
+ list_for_each_entry(ufile, &uverbs_dev->uverbs_file_list, list) {
+ if (ufile->ucontext)
+ uverbs_user_mmap_disassociate(ufile);
+ }
+ mutex_unlock(&uverbs_dev->lists_mutex);
}
+EXPORT_SYMBOL(rdma_user_mmap_disassociate);
/*
* ib_uverbs_open() does not need the BKL:
@@ -947,6 +984,8 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
mutex_init(&file->umap_lock);
INIT_LIST_HEAD(&file->umaps);
+ mutex_init(&file->disassociation_lock);
+
filp->private_data = file;
list_add_tail(&file->list, &dev->uverbs_file_list);
mutex_unlock(&dev->lists_mutex);
diff --git a/drivers/infiniband/hw/bnxt_re/Makefile b/drivers/infiniband/hw/bnxt_re/Makefile
index ee9bb1be61ea..f63417d2ccc6 100644
--- a/drivers/infiniband/hw/bnxt_re/Makefile
+++ b/drivers/infiniband/hw/bnxt_re/Makefile
@@ -4,4 +4,5 @@ ccflags-y := -I $(srctree)/drivers/net/ethernet/broadcom/bnxt
obj-$(CONFIG_INFINIBAND_BNXT_RE) += bnxt_re.o
bnxt_re-y := main.o ib_verbs.o \
qplib_res.o qplib_rcfw.o \
- qplib_sp.o qplib_fp.o hw_counters.o
+ qplib_sp.o qplib_fp.o hw_counters.o \
+ debugfs.o
diff --git a/drivers/infiniband/hw/bnxt_re/bnxt_re.h b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
index e94518b12f86..2975b11b79bf 100644
--- a/drivers/infiniband/hw/bnxt_re/bnxt_re.h
+++ b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
@@ -154,8 +154,25 @@ struct bnxt_re_pacing {
#define BNXT_RE_GRC_FIFO_REG_BASE 0x2000
+#define BNXT_RE_MIN_MSIX 2
+#define BNXT_RE_MAX_MSIX BNXT_MAX_ROCE_MSIX
+struct bnxt_re_nq_record {
+ struct bnxt_msix_entry msix_entries[BNXT_RE_MAX_MSIX];
+ struct bnxt_qplib_nq nq[BNXT_RE_MAX_MSIX];
+ int num_msix;
+ /* serialize NQ access */
+ struct mutex load_lock;
+};
+
#define MAX_CQ_HASH_BITS (16)
#define MAX_SRQ_HASH_BITS (16)
+
+static inline bool bnxt_re_chip_gen_p7(u16 chip_num)
+{
+ return (chip_num == CHIP_NUM_58818 ||
+ chip_num == CHIP_NUM_57608);
+}
+
struct bnxt_re_dev {
struct ib_device ibdev;
struct list_head list;
@@ -174,27 +191,24 @@ struct bnxt_re_dev {
unsigned int version, major, minor;
struct bnxt_qplib_chip_ctx *chip_ctx;
struct bnxt_en_dev *en_dev;
- int num_msix;
int id;
struct delayed_work worker;
u8 cur_prio_map;
- /* FP Notification Queue (CQ & SRQ) */
- struct tasklet_struct nq_task;
-
/* RCFW Channel */
struct bnxt_qplib_rcfw rcfw;
- /* NQ */
- struct bnxt_qplib_nq nq[BNXT_MAX_ROCE_MSIX];
+ /* NQ record */
+ struct bnxt_re_nq_record *nqr;
/* Device Resources */
struct bnxt_qplib_dev_attr dev_attr;
struct bnxt_qplib_ctx qplib_ctx;
struct bnxt_qplib_res qplib_res;
struct bnxt_qplib_dpi dpi_privileged;
+ struct bnxt_qplib_cq_coal_param cq_coalescing;
struct mutex qp_lock; /* protect qp list */
struct list_head qp_list;
@@ -213,6 +227,8 @@ struct bnxt_re_dev {
struct delayed_work dbq_pacing_work;
DECLARE_HASHTABLE(cq_hash, MAX_CQ_HASH_BITS);
DECLARE_HASHTABLE(srq_hash, MAX_SRQ_HASH_BITS);
+ struct dentry *dbg_root;
+ struct dentry *qp_debugfs;
};
#define to_bnxt_re_dev(ptr, member) \
@@ -239,4 +255,23 @@ static inline void bnxt_re_set_pacing_dev_state(struct bnxt_re_dev *rdev)
rdev->qplib_res.pacing_data->dev_err_state =
test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags);
}
+
+static inline int bnxt_re_read_context_allowed(struct bnxt_re_dev *rdev)
+{
+ if (!bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx) ||
+ rdev->rcfw.res->cctx->hwrm_intf_ver < HWRM_VERSION_READ_CTX)
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+#define BNXT_RE_CONTEXT_TYPE_QPC_SIZE_P5 1088
+#define BNXT_RE_CONTEXT_TYPE_CQ_SIZE_P5 128
+#define BNXT_RE_CONTEXT_TYPE_MRW_SIZE_P5 128
+#define BNXT_RE_CONTEXT_TYPE_SRQ_SIZE_P5 192
+
+#define BNXT_RE_CONTEXT_TYPE_QPC_SIZE_P7 1088
+#define BNXT_RE_CONTEXT_TYPE_CQ_SIZE_P7 192
+#define BNXT_RE_CONTEXT_TYPE_MRW_SIZE_P7 192
+#define BNXT_RE_CONTEXT_TYPE_SRQ_SIZE_P7 192
+
#endif
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
new file mode 100644
index 000000000000..7c47039044ef
--- /dev/null
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Copyright (c) 2024, Broadcom. All rights reserved. The term
+ * Broadcom refers to Broadcom Limited and/or its subsidiaries.
+ *
+ * Description: Debugfs component of the bnxt_re driver
+ */
+
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <rdma/ib_addr.h>
+
+#include "bnxt_ulp.h"
+#include "roce_hsi.h"
+#include "qplib_res.h"
+#include "qplib_sp.h"
+#include "qplib_fp.h"
+#include "qplib_rcfw.h"
+#include "bnxt_re.h"
+#include "ib_verbs.h"
+#include "debugfs.h"
+
+static struct dentry *bnxt_re_debugfs_root;
+
+static inline const char *bnxt_re_qp_state_str(u8 state)
+{
+ switch (state) {
+ case CMDQ_MODIFY_QP_NEW_STATE_RESET:
+ return "RST";
+ case CMDQ_MODIFY_QP_NEW_STATE_INIT:
+ return "INIT";
+ case CMDQ_MODIFY_QP_NEW_STATE_RTR:
+ return "RTR";
+ case CMDQ_MODIFY_QP_NEW_STATE_RTS:
+ return "RTS";
+ case CMDQ_MODIFY_QP_NEW_STATE_SQE:
+ return "SQER";
+ case CMDQ_MODIFY_QP_NEW_STATE_SQD:
+ return "SQD";
+ case CMDQ_MODIFY_QP_NEW_STATE_ERR:
+ return "ERR";
+ default:
+ return "Invalid QP state";
+ }
+}
+
+static inline const char *bnxt_re_qp_type_str(u8 type)
+{
+ switch (type) {
+ case CMDQ_CREATE_QP1_TYPE_GSI: return "QP1";
+ case CMDQ_CREATE_QP_TYPE_GSI: return "QP1";
+ case CMDQ_CREATE_QP_TYPE_RC: return "RC";
+ case CMDQ_CREATE_QP_TYPE_UD: return "UD";
+ case CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE: return "RAW_ETHERTYPE";
+ default: return "Invalid transport type";
+ }
+}
+
+static ssize_t qp_info_read(struct file *filep,
+ char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct bnxt_re_qp *qp = filep->private_data;
+ char *buf;
+ int len;
+
+ if (*ppos)
+ return 0;
+
+ buf = kasprintf(GFP_KERNEL,
+ "QPN\t\t: %d\n"
+ "transport\t: %s\n"
+ "state\t\t: %s\n"
+ "mtu\t\t: %d\n"
+ "timeout\t\t: %d\n"
+ "remote QPN\t: %d\n",
+ qp->qplib_qp.id,
+ bnxt_re_qp_type_str(qp->qplib_qp.type),
+ bnxt_re_qp_state_str(qp->qplib_qp.state),
+ qp->qplib_qp.mtu,
+ qp->qplib_qp.timeout,
+ qp->qplib_qp.dest_qpn);
+ if (!buf)
+ return -ENOMEM;
+ if (count < strlen(buf)) {
+ kfree(buf);
+ return -ENOSPC;
+ }
+ len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
+ kfree(buf);
+ return len;
+}
+
+static const struct file_operations debugfs_qp_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = qp_info_read,
+};
+
+void bnxt_re_debug_add_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
+{
+ char resn[32];
+
+ sprintf(resn, "0x%x", qp->qplib_qp.id);
+ qp->dentry = debugfs_create_file(resn, 0400, rdev->qp_debugfs, qp, &debugfs_qp_fops);
+}
+
+void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
+{
+ debugfs_remove(qp->dentry);
+}
+
+void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev)
+{
+ struct pci_dev *pdev = rdev->en_dev->pdev;
+
+ rdev->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), bnxt_re_debugfs_root);
+
+ rdev->qp_debugfs = debugfs_create_dir("QPs", rdev->dbg_root);
+}
+
+void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev)
+{
+ debugfs_remove_recursive(rdev->qp_debugfs);
+
+ debugfs_remove_recursive(rdev->dbg_root);
+ rdev->dbg_root = NULL;
+}
+
+void bnxt_re_register_debugfs(void)
+{
+ bnxt_re_debugfs_root = debugfs_create_dir("bnxt_re", NULL);
+}
+
+void bnxt_re_unregister_debugfs(void)
+{
+ debugfs_remove(bnxt_re_debugfs_root);
+}
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.h b/drivers/infiniband/hw/bnxt_re/debugfs.h
new file mode 100644
index 000000000000..cd3be0a9ec7e
--- /dev/null
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Copyright (c) 2024, Broadcom. All rights reserved. The term
+ * Broadcom refers to Broadcom Limited and/or its subsidiaries.
+ *
+ * Description: Debugfs header
+ */
+
+#ifndef __BNXT_RE_DEBUGFS__
+#define __BNXT_RE_DEBUGFS__
+
+void bnxt_re_debug_add_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp);
+void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp);
+
+void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev);
+void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev);
+
+void bnxt_re_register_debugfs(void);
+void bnxt_re_unregister_debugfs(void);
+
+#endif
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index e66ae9f22c71..82023394e330 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -62,6 +62,7 @@
#include "bnxt_re.h"
#include "ib_verbs.h"
+#include "debugfs.h"
#include <rdma/uverbs_types.h>
#include <rdma/uverbs_std_types.h>
@@ -94,9 +95,9 @@ static int __from_ib_access_flags(int iflags)
return qflags;
};
-static enum ib_access_flags __to_ib_access_flags(int qflags)
+static int __to_ib_access_flags(int qflags)
{
- enum ib_access_flags iflags = 0;
+ int iflags = 0;
if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
iflags |= IB_ACCESS_LOCAL_WRITE;
@@ -113,7 +114,49 @@ static enum ib_access_flags __to_ib_access_flags(int qflags)
if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
iflags |= IB_ACCESS_ON_DEMAND;
return iflags;
-};
+}
+
+static u8 __qp_access_flags_from_ib(struct bnxt_qplib_chip_ctx *cctx, int iflags)
+{
+ u8 qflags = 0;
+
+ if (!bnxt_qplib_is_chip_gen_p5_p7(cctx))
+ /* For Wh+ */
+ return (u8)__from_ib_access_flags(iflags);
+
+ /* For P5, P7 and later chips */
+ if (iflags & IB_ACCESS_LOCAL_WRITE)
+ qflags |= CMDQ_MODIFY_QP_ACCESS_LOCAL_WRITE;
+ if (iflags & IB_ACCESS_REMOTE_WRITE)
+ qflags |= CMDQ_MODIFY_QP_ACCESS_REMOTE_WRITE;
+ if (iflags & IB_ACCESS_REMOTE_READ)
+ qflags |= CMDQ_MODIFY_QP_ACCESS_REMOTE_READ;
+ if (iflags & IB_ACCESS_REMOTE_ATOMIC)
+ qflags |= CMDQ_MODIFY_QP_ACCESS_REMOTE_ATOMIC;
+
+ return qflags;
+}
+
+static int __qp_access_flags_to_ib(struct bnxt_qplib_chip_ctx *cctx, u8 qflags)
+{
+ int iflags = 0;
+
+ if (!bnxt_qplib_is_chip_gen_p5_p7(cctx))
+ /* For Wh+ */
+ return __to_ib_access_flags(qflags);
+
+ /* For P5, P7 and later chips */
+ if (qflags & CMDQ_MODIFY_QP_ACCESS_LOCAL_WRITE)
+ iflags |= IB_ACCESS_LOCAL_WRITE;
+ if (qflags & CMDQ_MODIFY_QP_ACCESS_REMOTE_WRITE)
+ iflags |= IB_ACCESS_REMOTE_WRITE;
+ if (qflags & CMDQ_MODIFY_QP_ACCESS_REMOTE_READ)
+ iflags |= IB_ACCESS_REMOTE_READ;
+ if (qflags & CMDQ_MODIFY_QP_ACCESS_REMOTE_ATOMIC)
+ iflags |= IB_ACCESS_REMOTE_ATOMIC;
+
+ return iflags;
+}
static void bnxt_re_check_and_set_relaxed_ordering(struct bnxt_re_dev *rdev,
struct bnxt_qplib_mrw *qplib_mr)
@@ -211,6 +254,22 @@ int bnxt_re_query_device(struct ib_device *ibdev,
return 0;
}
+int bnxt_re_modify_device(struct ib_device *ibdev,
+ int device_modify_mask,
+ struct ib_device_modify *device_modify)
+{
+ ibdev_dbg(ibdev, "Modify device with mask 0x%x", device_modify_mask);
+
+ if (device_modify_mask & ~IB_DEVICE_MODIFY_NODE_DESC)
+ return -EOPNOTSUPP;
+
+ if (!(device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC))
+ return 0;
+
+ memcpy(ibdev->node_desc, device_modify->node_desc, IB_DEVICE_NODE_DESC_MAX);
+ return 0;
+}
+
/* Port */
int bnxt_re_query_port(struct ib_device *ibdev, u32 port_num,
struct ib_port_attr *port_attr)
@@ -939,6 +998,8 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
else if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD)
atomic_dec(&rdev->stats.res.ud_qp_count);
+ bnxt_re_debug_rem_qpinfo(rdev, qp);
+
ib_umem_release(qp->rumem);
ib_umem_release(qp->sumem);
@@ -1622,6 +1683,7 @@ int bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *qp_init_attr,
if (active_qps > rdev->stats.res.ud_qp_watermark)
rdev->stats.res.ud_qp_watermark = active_qps;
}
+ bnxt_re_debug_add_qpinfo(rdev, qp);
return 0;
qp_destroy:
@@ -1814,8 +1876,8 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
srq->qplib_srq.wqe_size = bnxt_re_get_rwqe_size(dev_attr->max_srq_sges);
srq->qplib_srq.threshold = srq_init_attr->attr.srq_limit;
srq->srq_limit = srq_init_attr->attr.srq_limit;
- srq->qplib_srq.eventq_hw_ring_id = rdev->nq[0].ring_id;
- nq = &rdev->nq[0];
+ srq->qplib_srq.eventq_hw_ring_id = rdev->nqr->nq[0].ring_id;
+ nq = &rdev->nqr->nq[0];
if (udata) {
rc = bnxt_re_init_user_srq(rdev, pd, srq, udata);
@@ -2041,12 +2103,10 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
if (qp_attr_mask & IB_QP_ACCESS_FLAGS) {
qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_ACCESS;
qp->qplib_qp.access =
- __from_ib_access_flags(qp_attr->qp_access_flags);
+ __qp_access_flags_from_ib(qp->qplib_qp.cctx,
+ qp_attr->qp_access_flags);
/* LOCAL_WRITE access must be set to allow RC receive */
- qp->qplib_qp.access |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
- /* Temp: Set all params on QP as of now */
- qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_WRITE;
- qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_REMOTE_READ;
+ qp->qplib_qp.access |= CMDQ_MODIFY_QP_ACCESS_LOCAL_WRITE;
}
if (qp_attr_mask & IB_QP_PKEY_INDEX) {
qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY;
@@ -2080,7 +2140,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
qp->qplib_qp.ah.sgid_index = ctx->idx;
qp->qplib_qp.ah.host_sgid_index = grh->sgid_index;
qp->qplib_qp.ah.hop_limit = grh->hop_limit;
- qp->qplib_qp.ah.traffic_class = grh->traffic_class;
+ qp->qplib_qp.ah.traffic_class = grh->traffic_class >> 2;
qp->qplib_qp.ah.sl = rdma_ah_get_sl(&qp_attr->ah_attr);
ether_addr_copy(qp->qplib_qp.ah.dmac,
qp_attr->ah_attr.roce.dmac);
@@ -2251,7 +2311,8 @@ int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
qp_attr->qp_state = __to_ib_qp_state(qplib_qp->state);
qp_attr->cur_qp_state = __to_ib_qp_state(qplib_qp->cur_qp_state);
qp_attr->en_sqd_async_notify = qplib_qp->en_sqd_async_notify ? 1 : 0;
- qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp->access);
+ qp_attr->qp_access_flags = __qp_access_flags_to_ib(qp->qplib_qp.cctx,
+ qplib_qp->access);
qp_attr->pkey_index = qplib_qp->pkey_index;
qp_attr->qkey = qplib_qp->qkey;
qp_attr->ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
@@ -2972,6 +3033,28 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, const struct ib_recv_wr *wr,
return rc;
}
+static struct bnxt_qplib_nq *bnxt_re_get_nq(struct bnxt_re_dev *rdev)
+{
+ int min, indx;
+
+ mutex_lock(&rdev->nqr->load_lock);
+ for (indx = 0, min = 0; indx < (rdev->nqr->num_msix - 1); indx++) {
+ if (rdev->nqr->nq[min].load > rdev->nqr->nq[indx].load)
+ min = indx;
+ }
+ rdev->nqr->nq[min].load++;
+ mutex_unlock(&rdev->nqr->load_lock);
+
+ return &rdev->nqr->nq[min];
+}
+
+static void bnxt_re_put_nq(struct bnxt_re_dev *rdev, struct bnxt_qplib_nq *nq)
+{
+ mutex_lock(&rdev->nqr->load_lock);
+ nq->load--;
+ mutex_unlock(&rdev->nqr->load_lock);
+}
+
/* Completion Queues */
int bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
{
@@ -2990,6 +3073,8 @@ int bnxt_re_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
hash_del(&cq->hash_entry);
}
bnxt_qplib_destroy_cq(&rdev->qplib_res, &cq->qplib_cq);
+
+ bnxt_re_put_nq(rdev, nq);
ib_umem_release(cq->umem);
atomic_dec(&rdev->stats.res.cq_count);
@@ -3008,8 +3093,6 @@ int bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
struct bnxt_qplib_chip_ctx *cctx;
- struct bnxt_qplib_nq *nq = NULL;
- unsigned int nq_alloc_cnt;
int cqe = attr->cqe;
int rc, entries;
u32 active_cqs;
@@ -3060,15 +3143,10 @@ int bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
cq->qplib_cq.dpi = &rdev->dpi_privileged;
}
- /*
- * Allocating the NQ in a round robin fashion. nq_alloc_cnt is a
- * used for getting the NQ index.
- */
- nq_alloc_cnt = atomic_inc_return(&rdev->nq_alloc_cnt);
- nq = &rdev->nq[nq_alloc_cnt % (rdev->num_msix - 1)];
cq->qplib_cq.max_wqe = entries;
- cq->qplib_cq.cnq_hw_ring_id = nq->ring_id;
- cq->qplib_cq.nq = nq;
+ cq->qplib_cq.coalescing = &rdev->cq_coalescing;
+ cq->qplib_cq.nq = bnxt_re_get_nq(rdev);
+ cq->qplib_cq.cnq_hw_ring_id = cq->qplib_cq.nq->ring_id;
rc = bnxt_qplib_create_cq(&rdev->qplib_res, &cq->qplib_cq);
if (rc) {
@@ -3078,7 +3156,6 @@ int bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
cq->ib_cq.cqe = entries;
cq->cq_period = cq->qplib_cq.period;
- nq->budget++;
active_cqs = atomic_inc_return(&rdev->stats.res.cq_count);
if (active_cqs > rdev->stats.res.cq_watermark)
@@ -3633,7 +3710,7 @@ static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp,
wc->byte_len = orig_cqe->length;
wc->qp = &gsi_qp->ib_qp;
- wc->ex.imm_data = cpu_to_be32(le32_to_cpu(orig_cqe->immdata));
+ wc->ex.imm_data = cpu_to_be32(orig_cqe->immdata);
wc->src_qp = orig_cqe->src_qp;
memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) {
@@ -3778,7 +3855,10 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
(unsigned long)(cqe->qp_handle),
struct bnxt_re_qp, qplib_qp);
wc->qp = &qp->ib_qp;
- wc->ex.imm_data = cpu_to_be32(le32_to_cpu(cqe->immdata));
+ if (cqe->flags & CQ_RES_RC_FLAGS_IMM)
+ wc->ex.imm_data = cpu_to_be32(cqe->immdata);
+ else
+ wc->ex.invalidate_rkey = cqe->invrkey;
wc->src_qp = cqe->src_qp;
memcpy(wc->smac, cqe->smac, ETH_ALEN);
wc->port_num = 1;
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index b789e47ec97a..ac59f1d73b15 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -95,6 +95,7 @@ struct bnxt_re_qp {
struct ib_ud_header qp1_hdr;
struct bnxt_re_cq *scq;
struct bnxt_re_cq *rcq;
+ struct dentry *dentry;
};
struct bnxt_re_cq {
@@ -196,6 +197,9 @@ static inline bool bnxt_re_is_var_size_supported(struct bnxt_re_dev *rdev,
int bnxt_re_query_device(struct ib_device *ibdev,
struct ib_device_attr *ib_attr,
struct ib_udata *udata);
+int bnxt_re_modify_device(struct ib_device *ibdev,
+ int device_modify_mask,
+ struct ib_device_modify *device_modify);
int bnxt_re_query_port(struct ib_device *ibdev, u32 port_num,
struct ib_port_attr *port_attr);
int bnxt_re_get_port_immutable(struct ib_device *ibdev, u32 port_num,
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index 6715c96a3eee..b7af0d5ff3b6 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -67,6 +67,7 @@
#include <rdma/bnxt_re-abi.h>
#include "bnxt.h"
#include "hw_counters.h"
+#include "debugfs.h"
static char version[] =
BNXT_RE_DESC "\n";
@@ -183,6 +184,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev)
rdev->rcfw.res = &rdev->qplib_res;
rdev->qplib_res.dattr = &rdev->dev_attr;
rdev->qplib_res.is_vf = BNXT_EN_VF(en_dev);
+ rdev->qplib_res.en_dev = en_dev;
bnxt_re_set_drv_mode(rdev);
@@ -287,12 +289,17 @@ static void bnxt_re_set_resource_limits(struct bnxt_re_dev *rdev)
static void bnxt_re_vf_res_config(struct bnxt_re_dev *rdev)
{
+ /*
+ * Use the total VF count since the actual VF count may not be
+ * available at this point.
+ */
rdev->num_vfs = pci_sriov_get_totalvfs(rdev->en_dev->pdev);
- if (!bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx)) {
- bnxt_re_set_resource_limits(rdev);
- bnxt_qplib_set_func_resources(&rdev->qplib_res, &rdev->rcfw,
- &rdev->qplib_ctx);
- }
+ if (!rdev->num_vfs)
+ return;
+
+ bnxt_re_set_resource_limits(rdev);
+ bnxt_qplib_set_func_resources(&rdev->qplib_res, &rdev->rcfw,
+ &rdev->qplib_ctx);
}
static void bnxt_re_shutdown(struct auxiliary_device *adev)
@@ -300,9 +307,6 @@ static void bnxt_re_shutdown(struct auxiliary_device *adev)
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev);
struct bnxt_re_dev *rdev;
- if (!en_info)
- return;
-
rdev = en_info->rdev;
ib_unregister_device(&rdev->ibdev);
bnxt_re_dev_uninit(rdev, BNXT_RE_COMPLETE_REMOVE);
@@ -316,14 +320,11 @@ static void bnxt_re_stop_irq(void *handle)
struct bnxt_qplib_nq *nq;
int indx;
- if (!en_info)
- return;
-
rdev = en_info->rdev;
rcfw = &rdev->rcfw;
- for (indx = BNXT_RE_NQ_IDX; indx < rdev->num_msix; indx++) {
- nq = &rdev->nq[indx - 1];
+ for (indx = BNXT_RE_NQ_IDX; indx < rdev->nqr->num_msix; indx++) {
+ nq = &rdev->nqr->nq[indx - 1];
bnxt_qplib_nq_stop_irq(nq, false);
}
@@ -339,11 +340,8 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
struct bnxt_qplib_nq *nq;
int indx, rc;
- if (!en_info)
- return;
-
rdev = en_info->rdev;
- msix_ent = rdev->en_dev->msix_entries;
+ msix_ent = rdev->nqr->msix_entries;
rcfw = &rdev->rcfw;
if (!ent) {
/* Not setting the f/w timeout bit in rcfw.
@@ -358,8 +356,8 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
/* Vectors may change after restart, so update with new vectors
* in device sctructure.
*/
- for (indx = 0; indx < rdev->num_msix; indx++)
- rdev->en_dev->msix_entries[indx].vector = ent[indx].vector;
+ for (indx = 0; indx < rdev->nqr->num_msix; indx++)
+ rdev->nqr->msix_entries[indx].vector = ent[indx].vector;
rc = bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector,
false);
@@ -367,8 +365,8 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
ibdev_warn(&rdev->ibdev, "Failed to reinit CREQ\n");
return;
}
- for (indx = BNXT_RE_NQ_IDX ; indx < rdev->num_msix; indx++) {
- nq = &rdev->nq[indx - 1];
+ for (indx = BNXT_RE_NQ_IDX ; indx < rdev->nqr->num_msix; indx++) {
+ nq = &rdev->nqr->nq[indx - 1];
rc = bnxt_qplib_nq_start_irq(nq, indx - 1,
msix_ent[indx].vector, false);
if (rc) {
@@ -882,6 +880,253 @@ static const struct attribute_group bnxt_re_dev_attr_group = {
.attrs = bnxt_re_attributes,
};
+static int bnxt_re_fill_res_mr_entry(struct sk_buff *msg, struct ib_mr *ib_mr)
+{
+ struct bnxt_qplib_hwq *mr_hwq;
+ struct nlattr *table_attr;
+ struct bnxt_re_mr *mr;
+
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_DRIVER);
+ if (!table_attr)
+ return -EMSGSIZE;
+
+ mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
+ mr_hwq = &mr->qplib_mr.hwq;
+
+ if (rdma_nl_put_driver_u32(msg, "page_size",
+ mr_hwq->qe_ppg * mr_hwq->element_size))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "max_elements", mr_hwq->max_elements))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "element_size", mr_hwq->element_size))
+ goto err;
+ if (rdma_nl_put_driver_u64_hex(msg, "hwq", (unsigned long)mr_hwq))
+ goto err;
+ if (rdma_nl_put_driver_u64_hex(msg, "va", mr->qplib_mr.va))
+ goto err;
+
+ nla_nest_end(msg, table_attr);
+ return 0;
+
+err:
+ nla_nest_cancel(msg, table_attr);
+ return -EMSGSIZE;
+}
+
+static int bnxt_re_fill_res_mr_entry_raw(struct sk_buff *msg, struct ib_mr *ib_mr)
+{
+ struct bnxt_re_dev *rdev;
+ struct bnxt_re_mr *mr;
+ int err, len;
+ void *data;
+
+ mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
+ rdev = mr->rdev;
+
+ err = bnxt_re_read_context_allowed(rdev);
+ if (err)
+ return err;
+
+ len = bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx) ? BNXT_RE_CONTEXT_TYPE_MRW_SIZE_P7 :
+ BNXT_RE_CONTEXT_TYPE_MRW_SIZE_P5;
+ data = kzalloc(len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ err = bnxt_qplib_read_context(&rdev->rcfw, CMDQ_READ_CONTEXT_TYPE_MRW,
+ mr->qplib_mr.lkey, len, data);
+ if (!err)
+ err = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, len, data);
+
+ kfree(data);
+ return err;
+}
+
+static int bnxt_re_fill_res_cq_entry(struct sk_buff *msg, struct ib_cq *ib_cq)
+{
+ struct bnxt_qplib_hwq *cq_hwq;
+ struct nlattr *table_attr;
+ struct bnxt_re_cq *cq;
+
+ cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
+ cq_hwq = &cq->qplib_cq.hwq;
+
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_DRIVER);
+ if (!table_attr)
+ return -EMSGSIZE;
+
+ if (rdma_nl_put_driver_u32(msg, "cq_depth", cq_hwq->depth))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "max_elements", cq_hwq->max_elements))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "element_size", cq_hwq->element_size))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "max_wqe", cq->qplib_cq.max_wqe))
+ goto err;
+
+ nla_nest_end(msg, table_attr);
+ return 0;
+
+err:
+ nla_nest_cancel(msg, table_attr);
+ return -EMSGSIZE;
+}
+
+static int bnxt_re_fill_res_cq_entry_raw(struct sk_buff *msg, struct ib_cq *ib_cq)
+{
+ struct bnxt_re_dev *rdev;
+ struct bnxt_re_cq *cq;
+ int err, len;
+ void *data;
+
+ cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
+ rdev = cq->rdev;
+
+ err = bnxt_re_read_context_allowed(rdev);
+ if (err)
+ return err;
+
+ len = bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx) ? BNXT_RE_CONTEXT_TYPE_CQ_SIZE_P7 :
+ BNXT_RE_CONTEXT_TYPE_CQ_SIZE_P5;
+ data = kzalloc(len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ err = bnxt_qplib_read_context(&rdev->rcfw,
+ CMDQ_READ_CONTEXT_TYPE_CQ,
+ cq->qplib_cq.id, len, data);
+ if (!err)
+ err = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, len, data);
+
+ kfree(data);
+ return err;
+}
+
+static int bnxt_re_fill_res_qp_entry(struct sk_buff *msg, struct ib_qp *ib_qp)
+{
+ struct bnxt_qplib_qp *qplib_qp;
+ struct nlattr *table_attr;
+ struct bnxt_re_qp *qp;
+
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_DRIVER);
+ if (!table_attr)
+ return -EMSGSIZE;
+
+ qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
+ qplib_qp = &qp->qplib_qp;
+
+ if (rdma_nl_put_driver_u32(msg, "sq_max_wqe", qplib_qp->sq.max_wqe))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "sq_max_sge", qplib_qp->sq.max_sge))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "sq_wqe_size", qplib_qp->sq.wqe_size))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "sq_swq_start", qplib_qp->sq.swq_start))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "sq_swq_last", qplib_qp->sq.swq_last))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "rq_max_wqe", qplib_qp->rq.max_wqe))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "rq_max_sge", qplib_qp->rq.max_sge))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "rq_wqe_size", qplib_qp->rq.wqe_size))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "rq_swq_start", qplib_qp->rq.swq_start))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "rq_swq_last", qplib_qp->rq.swq_last))
+ goto err;
+ if (rdma_nl_put_driver_u32(msg, "timeout", qplib_qp->timeout))
+ goto err;
+
+ nla_nest_end(msg, table_attr);
+ return 0;
+
+err:
+ nla_nest_cancel(msg, table_attr);
+ return -EMSGSIZE;
+}
+
+static int bnxt_re_fill_res_qp_entry_raw(struct sk_buff *msg, struct ib_qp *ibqp)
+{
+ struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibqp->device, ibdev);
+ int err, len;
+ void *data;
+
+ err = bnxt_re_read_context_allowed(rdev);
+ if (err)
+ return err;
+
+ len = bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx) ? BNXT_RE_CONTEXT_TYPE_QPC_SIZE_P7 :
+ BNXT_RE_CONTEXT_TYPE_QPC_SIZE_P5;
+ data = kzalloc(len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ err = bnxt_qplib_read_context(&rdev->rcfw, CMDQ_READ_CONTEXT_TYPE_QPC,
+ ibqp->qp_num, len, data);
+ if (!err)
+ err = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, len, data);
+
+ kfree(data);
+ return err;
+}
+
+static int bnxt_re_fill_res_srq_entry(struct sk_buff *msg, struct ib_srq *ib_srq)
+{
+ struct nlattr *table_attr;
+ struct bnxt_re_srq *srq;
+
+ table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_DRIVER);
+ if (!table_attr)
+ return -EMSGSIZE;
+
+ srq = container_of(ib_srq, struct bnxt_re_srq, ib_srq);
+
+ if (rdma_nl_put_driver_u32_hex(msg, "wqe_size", srq->qplib_srq.wqe_size))
+ goto err;
+ if (rdma_nl_put_driver_u32_hex(msg, "max_wqe", srq->qplib_srq.max_wqe))
+ goto err;
+ if (rdma_nl_put_driver_u32_hex(msg, "max_sge", srq->qplib_srq.max_sge))
+ goto err;
+
+ nla_nest_end(msg, table_attr);
+ return 0;
+
+err:
+ nla_nest_cancel(msg, table_attr);
+ return -EMSGSIZE;
+}
+
+static int bnxt_re_fill_res_srq_entry_raw(struct sk_buff *msg, struct ib_srq *ib_srq)
+{
+ struct bnxt_re_dev *rdev;
+ struct bnxt_re_srq *srq;
+ int err, len;
+ void *data;
+
+ srq = container_of(ib_srq, struct bnxt_re_srq, ib_srq);
+ rdev = srq->rdev;
+
+ err = bnxt_re_read_context_allowed(rdev);
+ if (err)
+ return err;
+
+ len = bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx) ? BNXT_RE_CONTEXT_TYPE_SRQ_SIZE_P7 :
+ BNXT_RE_CONTEXT_TYPE_SRQ_SIZE_P5;
+
+ data = kzalloc(len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ err = bnxt_qplib_read_context(&rdev->rcfw, CMDQ_READ_CONTEXT_TYPE_SRQ,
+ srq->qplib_srq.id, len, data);
+ if (!err)
+ err = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, len, data);
+
+ kfree(data);
+ return err;
+}
+
static const struct ib_device_ops bnxt_re_dev_ops = {
.owner = THIS_MODULE,
.driver_id = RDMA_DRIVER_BNXT_RE,
@@ -923,6 +1168,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
.post_srq_recv = bnxt_re_post_srq_recv,
.query_ah = bnxt_re_query_ah,
.query_device = bnxt_re_query_device,
+ .modify_device = bnxt_re_modify_device,
.query_pkey = bnxt_re_query_pkey,
.query_port = bnxt_re_query_port,
.query_qp = bnxt_re_query_qp,
@@ -939,6 +1185,17 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_ucontext, bnxt_re_ucontext, ib_uctx),
};
+static const struct ib_device_ops restrack_ops = {
+ .fill_res_cq_entry = bnxt_re_fill_res_cq_entry,
+ .fill_res_cq_entry_raw = bnxt_re_fill_res_cq_entry_raw,
+ .fill_res_qp_entry = bnxt_re_fill_res_qp_entry,
+ .fill_res_qp_entry_raw = bnxt_re_fill_res_qp_entry_raw,
+ .fill_res_mr_entry = bnxt_re_fill_res_mr_entry,
+ .fill_res_mr_entry_raw = bnxt_re_fill_res_mr_entry_raw,
+ .fill_res_srq_entry = bnxt_re_fill_res_srq_entry,
+ .fill_res_srq_entry_raw = bnxt_re_fill_res_srq_entry_raw,
+};
+
static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
{
struct ib_device *ibdev = &rdev->ibdev;
@@ -952,7 +1209,7 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
addrconf_addr_eui48((u8 *)&ibdev->node_guid, rdev->netdev->dev_addr);
- ibdev->num_comp_vectors = rdev->num_msix - 1;
+ ibdev->num_comp_vectors = rdev->nqr->num_msix - 1;
ibdev->dev.parent = &rdev->en_dev->pdev->dev;
ibdev->local_dma_lkey = BNXT_QPLIB_RSVD_LKEY;
@@ -960,6 +1217,7 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
ibdev->driver_def = bnxt_re_uapi_defs;
ib_set_device_ops(ibdev, &bnxt_re_dev_ops);
+ ib_set_device_ops(ibdev, &restrack_ops);
ret = ib_device_set_netdev(&rdev->ibdev, rdev->netdev, 1);
if (ret)
return ret;
@@ -999,6 +1257,15 @@ static struct bnxt_re_dev *bnxt_re_dev_add(struct auxiliary_device *adev,
atomic_set(&rdev->stats.res.pd_count, 0);
rdev->cosq[0] = 0xFFFF;
rdev->cosq[1] = 0xFFFF;
+ rdev->cq_coalescing.buf_maxtime = BNXT_QPLIB_CQ_COAL_DEF_BUF_MAXTIME;
+ if (bnxt_re_chip_gen_p7(en_dev->chip_num)) {
+ rdev->cq_coalescing.normal_maxbuf = BNXT_QPLIB_CQ_COAL_DEF_NORMAL_MAXBUF_P7;
+ rdev->cq_coalescing.during_maxbuf = BNXT_QPLIB_CQ_COAL_DEF_DURING_MAXBUF_P7;
+ } else {
+ rdev->cq_coalescing.normal_maxbuf = BNXT_QPLIB_CQ_COAL_DEF_NORMAL_MAXBUF_P5;
+ rdev->cq_coalescing.during_maxbuf = BNXT_QPLIB_CQ_COAL_DEF_DURING_MAXBUF_P5;
+ }
+ rdev->cq_coalescing.en_ring_idle_mode = BNXT_QPLIB_CQ_COAL_DEF_EN_RING_IDLE_MODE;
return rdev;
}
@@ -1285,8 +1552,8 @@ static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev)
{
int i;
- for (i = 1; i < rdev->num_msix; i++)
- bnxt_qplib_disable_nq(&rdev->nq[i - 1]);
+ for (i = 1; i < rdev->nqr->num_msix; i++)
+ bnxt_qplib_disable_nq(&rdev->nqr->nq[i - 1]);
if (rdev->qplib_res.rcfw)
bnxt_qplib_cleanup_res(&rdev->qplib_res);
@@ -1300,10 +1567,12 @@ static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
bnxt_qplib_init_res(&rdev->qplib_res);
- for (i = 1; i < rdev->num_msix ; i++) {
- db_offt = rdev->en_dev->msix_entries[i].db_offset;
- rc = bnxt_qplib_enable_nq(rdev->en_dev->pdev, &rdev->nq[i - 1],
- i - 1, rdev->en_dev->msix_entries[i].vector,
+ mutex_init(&rdev->nqr->load_lock);
+
+ for (i = 1; i < rdev->nqr->num_msix ; i++) {
+ db_offt = rdev->nqr->msix_entries[i].db_offset;
+ rc = bnxt_qplib_enable_nq(rdev->en_dev->pdev, &rdev->nqr->nq[i - 1],
+ i - 1, rdev->nqr->msix_entries[i].vector,
db_offt, &bnxt_re_cqn_handler,
&bnxt_re_srqn_handler);
if (rc) {
@@ -1316,20 +1585,22 @@ static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
return 0;
fail:
for (i = num_vec_enabled; i >= 0; i--)
- bnxt_qplib_disable_nq(&rdev->nq[i]);
+ bnxt_qplib_disable_nq(&rdev->nqr->nq[i]);
return rc;
}
static void bnxt_re_free_nq_res(struct bnxt_re_dev *rdev)
{
+ struct bnxt_qplib_nq *nq;
u8 type;
int i;
- for (i = 0; i < rdev->num_msix - 1; i++) {
+ for (i = 0; i < rdev->nqr->num_msix - 1; i++) {
type = bnxt_qplib_get_ring_type(rdev->chip_ctx);
- bnxt_re_net_ring_free(rdev, rdev->nq[i].ring_id, type);
- bnxt_qplib_free_nq(&rdev->nq[i]);
- rdev->nq[i].res = NULL;
+ nq = &rdev->nqr->nq[i];
+ bnxt_re_net_ring_free(rdev, nq->ring_id, type);
+ bnxt_qplib_free_nq(nq);
+ nq->res = NULL;
}
}
@@ -1371,12 +1642,12 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
if (rc)
goto dealloc_res;
- for (i = 0; i < rdev->num_msix - 1; i++) {
+ for (i = 0; i < rdev->nqr->num_msix - 1; i++) {
struct bnxt_qplib_nq *nq;
- nq = &rdev->nq[i];
+ nq = &rdev->nqr->nq[i];
nq->hwq.max_elements = BNXT_QPLIB_NQE_MAX_CNT;
- rc = bnxt_qplib_alloc_nq(&rdev->qplib_res, &rdev->nq[i]);
+ rc = bnxt_qplib_alloc_nq(&rdev->qplib_res, nq);
if (rc) {
ibdev_err(&rdev->ibdev, "Alloc Failed NQ%d rc:%#x",
i, rc);
@@ -1384,17 +1655,17 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
}
type = bnxt_qplib_get_ring_type(rdev->chip_ctx);
rattr.dma_arr = nq->hwq.pbl[PBL_LVL_0].pg_map_arr;
- rattr.pages = nq->hwq.pbl[rdev->nq[i].hwq.level].pg_count;
+ rattr.pages = nq->hwq.pbl[rdev->nqr->nq[i].hwq.level].pg_count;
rattr.type = type;
rattr.mode = RING_ALLOC_REQ_INT_MODE_MSIX;
rattr.depth = BNXT_QPLIB_NQE_MAX_CNT - 1;
- rattr.lrid = rdev->en_dev->msix_entries[i + 1].ring_idx;
+ rattr.lrid = rdev->nqr->msix_entries[i + 1].ring_idx;
rc = bnxt_re_net_ring_alloc(rdev, &rattr, &nq->ring_id);
if (rc) {
ibdev_err(&rdev->ibdev,
"Failed to allocate NQ fw id with rc = 0x%x",
rc);
- bnxt_qplib_free_nq(&rdev->nq[i]);
+ bnxt_qplib_free_nq(nq);
goto free_nq;
}
num_vec_created++;
@@ -1403,8 +1674,8 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
free_nq:
for (i = num_vec_created - 1; i >= 0; i--) {
type = bnxt_qplib_get_ring_type(rdev->chip_ctx);
- bnxt_re_net_ring_free(rdev, rdev->nq[i].ring_id, type);
- bnxt_qplib_free_nq(&rdev->nq[i]);
+ bnxt_re_net_ring_free(rdev, rdev->nqr->nq[i].ring_id, type);
+ bnxt_qplib_free_nq(&rdev->nqr->nq[i]);
}
bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
&rdev->dpi_privileged);
@@ -1599,11 +1870,28 @@ static int bnxt_re_ib_init(struct bnxt_re_dev *rdev)
return rc;
}
+static int bnxt_re_alloc_nqr_mem(struct bnxt_re_dev *rdev)
+{
+ rdev->nqr = kzalloc(sizeof(*rdev->nqr), GFP_KERNEL);
+ if (!rdev->nqr)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void bnxt_re_free_nqr_mem(struct bnxt_re_dev *rdev)
+{
+ kfree(rdev->nqr);
+ rdev->nqr = NULL;
+}
+
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type)
{
u8 type;
int rc;
+ bnxt_re_debugfs_rem_pdev(rdev);
+
if (test_and_clear_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags))
cancel_delayed_work_sync(&rdev->worker);
@@ -1626,11 +1914,12 @@ static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type)
bnxt_qplib_free_rcfw_channel(&rdev->rcfw);
}
- rdev->num_msix = 0;
+ rdev->nqr->num_msix = 0;
if (rdev->pacing.dbr_pacing)
bnxt_re_deinitialize_dbr_pacing(rdev);
+ bnxt_re_free_nqr_mem(rdev);
bnxt_re_destroy_chip_ctx(rdev);
if (op_type == BNXT_RE_COMPLETE_REMOVE) {
if (test_and_clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags))
@@ -1668,6 +1957,17 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
}
set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
+ if (rdev->en_dev->ulp_tbl->msix_requested < BNXT_RE_MIN_MSIX) {
+ ibdev_err(&rdev->ibdev,
+ "RoCE requires minimum 2 MSI-X vectors, but only %d reserved\n",
+ rdev->en_dev->ulp_tbl->msix_requested);
+ bnxt_unregister_dev(rdev->en_dev);
+ clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
+ return -EINVAL;
+ }
+ ibdev_dbg(&rdev->ibdev, "Got %d MSI-X vectors\n",
+ rdev->en_dev->ulp_tbl->msix_requested);
+
rc = bnxt_re_setup_chip_ctx(rdev);
if (rc) {
bnxt_unregister_dev(rdev->en_dev);
@@ -1676,19 +1976,20 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
return -EINVAL;
}
+ rc = bnxt_re_alloc_nqr_mem(rdev);
+ if (rc) {
+ bnxt_re_destroy_chip_ctx(rdev);
+ bnxt_unregister_dev(rdev->en_dev);
+ clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
+ return rc;
+ }
+ rdev->nqr->num_msix = rdev->en_dev->ulp_tbl->msix_requested;
+ memcpy(rdev->nqr->msix_entries, rdev->en_dev->msix_entries,
+ sizeof(struct bnxt_msix_entry) * rdev->nqr->num_msix);
+
/* Check whether VF or PF */
bnxt_re_get_sriov_func_type(rdev);
- if (!rdev->en_dev->ulp_tbl->msix_requested) {
- ibdev_err(&rdev->ibdev,
- "Failed to get MSI-X vectors: %#x\n", rc);
- rc = -EINVAL;
- goto fail;
- }
- ibdev_dbg(&rdev->ibdev, "Got %d MSI-X vectors\n",
- rdev->en_dev->ulp_tbl->msix_requested);
- rdev->num_msix = rdev->en_dev->ulp_tbl->msix_requested;
-
bnxt_re_query_hwrm_intf_version(rdev);
/* Establish RCFW Communication Channel to initialize the context
@@ -1710,14 +2011,14 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
rattr.type = type;
rattr.mode = RING_ALLOC_REQ_INT_MODE_MSIX;
rattr.depth = BNXT_QPLIB_CREQE_MAX_CNT - 1;
- rattr.lrid = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].ring_idx;
+ rattr.lrid = rdev->nqr->msix_entries[BNXT_RE_AEQ_IDX].ring_idx;
rc = bnxt_re_net_ring_alloc(rdev, &rattr, &creq->ring_id);
if (rc) {
ibdev_err(&rdev->ibdev, "Failed to allocate CREQ: %#x\n", rc);
goto free_rcfw;
}
- db_offt = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].db_offset;
- vid = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].vector;
+ db_offt = rdev->nqr->msix_entries[BNXT_RE_AEQ_IDX].db_offset;
+ vid = rdev->nqr->msix_entries[BNXT_RE_AEQ_IDX].vector;
rc = bnxt_qplib_enable_rcfw_channel(&rdev->rcfw,
vid, db_offt,
&bnxt_re_aeq_handler);
@@ -1794,16 +2095,16 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
INIT_DELAYED_WORK(&rdev->worker, bnxt_re_worker);
set_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags);
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
- /*
- * Use the total VF count since the actual VF count may not be
- * available at this point.
- */
- bnxt_re_vf_res_config(rdev);
+
+ if (!(rdev->qplib_res.en_dev->flags & BNXT_EN_FLAG_ROCE_VF_RES_MGMT))
+ bnxt_re_vf_res_config(rdev);
}
hash_init(rdev->cq_hash);
if (rdev->chip_ctx->modes.toggle_bits & BNXT_QPLIB_SRQ_TOGGLE_BIT)
hash_init(rdev->srq_hash);
+ bnxt_re_debugfs_add_pdev(rdev);
+
return 0;
free_sctx:
bnxt_re_net_stats_ctx_free(rdev, rdev->qplib_ctx.stats.fw_id);
@@ -1905,11 +2206,10 @@ static void bnxt_re_setup_cc(struct bnxt_re_dev *rdev, bool enable)
if (enable) {
cc_param.enable = 1;
- cc_param.cc_mode = CMDQ_MODIFY_ROCE_CC_CC_MODE_PROBABILISTIC_CC_MODE;
+ cc_param.tos_ecn = 1;
}
- cc_param.mask = (CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE |
- CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC |
+ cc_param.mask = (CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC |
CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN);
if (bnxt_qplib_modify_cc(&rdev->qplib_res, &cc_param))
@@ -1991,10 +2291,6 @@ static void bnxt_re_remove(struct auxiliary_device *adev)
struct bnxt_re_dev *rdev;
mutex_lock(&bnxt_re_mutex);
- if (!en_info) {
- mutex_unlock(&bnxt_re_mutex);
- return;
- }
rdev = en_info->rdev;
if (rdev)
@@ -2025,7 +2321,15 @@ static int bnxt_re_probe(struct auxiliary_device *adev,
auxiliary_set_drvdata(adev, en_info);
rc = bnxt_re_add_device(adev, BNXT_RE_COMPLETE_INIT);
+ if (rc)
+ goto err;
mutex_unlock(&bnxt_re_mutex);
+ return 0;
+
+err:
+ mutex_unlock(&bnxt_re_mutex);
+ kfree(en_info);
+
return rc;
}
@@ -2035,18 +2339,9 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state)
struct bnxt_en_dev *en_dev;
struct bnxt_re_dev *rdev;
- if (!en_info)
- return 0;
-
rdev = en_info->rdev;
en_dev = en_info->en_dev;
mutex_lock(&bnxt_re_mutex);
- /* L2 driver may invoke this callback during device error/crash or device
- * reset. Current RoCE driver doesn't recover the device in case of
- * error. Handle the error by dispatching fatal events to all qps
- * ie. by calling bnxt_re_dev_stop and release the MSIx vectors as
- * L2 driver want to modify the MSIx table.
- */
ibdev_info(&rdev->ibdev, "Handle device suspend call");
/* Check the current device state from bnxt_en_dev and move the
@@ -2054,17 +2349,12 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state)
* This prevents more commands to HW during clean-up,
* in case the device is already in error.
*/
- if (test_bit(BNXT_STATE_FW_FATAL_COND, &rdev->en_dev->en_state))
+ if (test_bit(BNXT_STATE_FW_FATAL_COND, &rdev->en_dev->en_state)) {
set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags);
-
- bnxt_re_dev_stop(rdev);
- bnxt_re_stop_irq(adev);
- /* Move the device states to detached and avoid sending any more
- * commands to HW
- */
- set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags);
- set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags);
- wake_up_all(&rdev->rcfw.cmdq.waitq);
+ set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags);
+ wake_up_all(&rdev->rcfw.cmdq.waitq);
+ bnxt_re_dev_stop(rdev);
+ }
if (rdev->pacing.dbr_pacing)
bnxt_re_set_pacing_dev_state(rdev);
@@ -2082,17 +2372,7 @@ static int bnxt_re_resume(struct auxiliary_device *adev)
struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(adev);
struct bnxt_re_dev *rdev;
- if (!en_info)
- return 0;
-
mutex_lock(&bnxt_re_mutex);
- /* L2 driver may invoke this callback during device recovery, resume.
- * reset. Current RoCE driver doesn't recover the device in case of
- * error. Handle the error by dispatching fatal events to all qps
- * ie. by calling bnxt_re_dev_stop and release the MSIx vectors as
- * L2 driver want to modify the MSIx table.
- */
-
bnxt_re_add_device(adev, BNXT_RE_POST_RECOVERY_INIT);
rdev = en_info->rdev;
ibdev_info(&rdev->ibdev, "Device resume completed");
@@ -2123,18 +2403,24 @@ static int __init bnxt_re_mod_init(void)
int rc;
pr_info("%s: %s", ROCE_DRV_MODULE_NAME, version);
+ bnxt_re_register_debugfs();
+
rc = auxiliary_driver_register(&bnxt_re_driver);
if (rc) {
pr_err("%s: Failed to register auxiliary driver\n",
ROCE_DRV_MODULE_NAME);
- return rc;
+ goto err_debug;
}
return 0;
+err_debug:
+ bnxt_re_unregister_debugfs();
+ return rc;
}
static void __exit bnxt_re_mod_exit(void)
{
auxiliary_driver_unregister(&bnxt_re_driver);
+ bnxt_re_unregister_debugfs();
}
module_init(bnxt_re_mod_init);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
index 7ad83566ab0f..e42abf5be6c0 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -556,6 +556,7 @@ int bnxt_qplib_enable_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq,
nq->pdev = pdev;
nq->cqn_handler = cqn_handler;
nq->srqn_handler = srqn_handler;
+ nq->load = 0;
/* Have a task to schedule CQ notifiers in post send case */
nq->cqn_wq = create_singlethread_workqueue("bnxt_qplib_nq");
@@ -1282,12 +1283,47 @@ static void __filter_modify_flags(struct bnxt_qplib_qp *qp)
}
}
+static void bnxt_set_mandatory_attributes(struct bnxt_qplib_qp *qp,
+ struct cmdq_modify_qp *req)
+{
+ u32 mandatory_flags = 0;
+
+ if (qp->type == CMDQ_MODIFY_QP_QP_TYPE_RC)
+ mandatory_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_ACCESS;
+
+ if (qp->cur_qp_state == CMDQ_MODIFY_QP_NEW_STATE_INIT &&
+ qp->state == CMDQ_MODIFY_QP_NEW_STATE_RTR) {
+ if (qp->type == CMDQ_MODIFY_QP_QP_TYPE_RC && qp->srq)
+ req->flags = cpu_to_le16(CMDQ_MODIFY_QP_FLAGS_SRQ_USED);
+ mandatory_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY;
+ }
+
+ if (qp->type == CMDQ_MODIFY_QP_QP_TYPE_UD ||
+ qp->type == CMDQ_MODIFY_QP_QP_TYPE_GSI)
+ mandatory_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY;
+
+ qp->modify_flags |= mandatory_flags;
+ req->qp_type = qp->type;
+}
+
+static bool is_optimized_state_transition(struct bnxt_qplib_qp *qp)
+{
+ if ((qp->cur_qp_state == CMDQ_MODIFY_QP_NEW_STATE_INIT &&
+ qp->state == CMDQ_MODIFY_QP_NEW_STATE_RTR) ||
+ (qp->cur_qp_state == CMDQ_MODIFY_QP_NEW_STATE_RTR &&
+ qp->state == CMDQ_MODIFY_QP_NEW_STATE_RTS))
+ return true;
+
+ return false;
+}
+
int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
{
struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct creq_modify_qp_resp resp = {};
struct bnxt_qplib_cmdqmsg msg = {};
struct cmdq_modify_qp req = {};
+ u16 vlan_pcp_vlan_dei_vlan_id;
u32 temp32[4];
u32 bmask;
int rc;
@@ -1298,6 +1334,12 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
/* Filter out the qp_attr_mask based on the state->new transition */
__filter_modify_flags(qp);
+ if (qp->modify_flags & CMDQ_MODIFY_QP_MODIFY_MASK_STATE) {
+ /* Set mandatory attributes for INIT -> RTR and RTR -> RTS transition */
+ if (_is_optimize_modify_qp_supported(res->dattr->dev_cap_flags2) &&
+ is_optimized_state_transition(qp))
+ bnxt_set_mandatory_attributes(qp, &req);
+ }
bmask = qp->modify_flags;
req.modify_mask = cpu_to_le32(qp->modify_flags);
req.qp_cid = cpu_to_le32(qp->id);
@@ -1378,7 +1420,16 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_DEST_QP_ID)
req.dest_qp_id = cpu_to_le32(qp->dest_qpn);
- req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id);
+ if (bmask & CMDQ_MODIFY_QP_MODIFY_MASK_VLAN_ID) {
+ vlan_pcp_vlan_dei_vlan_id =
+ ((res->sgid_tbl.tbl[qp->ah.sgid_index].vlan_id <<
+ CMDQ_MODIFY_QP_VLAN_ID_SFT) &
+ CMDQ_MODIFY_QP_VLAN_ID_MASK);
+ vlan_pcp_vlan_dei_vlan_id |=
+ ((qp->ah.sl << CMDQ_MODIFY_QP_VLAN_PCP_SFT) &
+ CMDQ_MODIFY_QP_VLAN_PCP_MASK);
+ req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(vlan_pcp_vlan_dei_vlan_id);
+ }
bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), sizeof(resp), 0);
rc = bnxt_qplib_rcfw_send_message(rcfw, &msg);
@@ -2151,6 +2202,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
struct bnxt_qplib_cmdqmsg msg = {};
struct cmdq_create_cq req = {};
struct bnxt_qplib_pbl *pbl;
+ u32 coalescing = 0;
u32 pg_sz_lvl;
int rc;
@@ -2177,6 +2229,25 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
req.dpi = cpu_to_le32(cq->dpi->dpi);
req.cq_handle = cpu_to_le64(cq->cq_handle);
req.cq_size = cpu_to_le32(cq->max_wqe);
+
+ if (_is_cq_coalescing_supported(res->dattr->dev_cap_flags2)) {
+ req.flags |= cpu_to_le16(CMDQ_CREATE_CQ_FLAGS_COALESCING_VALID);
+ coalescing |= ((cq->coalescing->buf_maxtime <<
+ CMDQ_CREATE_CQ_BUF_MAXTIME_SFT) &
+ CMDQ_CREATE_CQ_BUF_MAXTIME_MASK);
+ coalescing |= ((cq->coalescing->normal_maxbuf <<
+ CMDQ_CREATE_CQ_NORMAL_MAXBUF_SFT) &
+ CMDQ_CREATE_CQ_NORMAL_MAXBUF_MASK);
+ coalescing |= ((cq->coalescing->during_maxbuf <<
+ CMDQ_CREATE_CQ_DURING_MAXBUF_SFT) &
+ CMDQ_CREATE_CQ_DURING_MAXBUF_MASK);
+ if (cq->coalescing->en_ring_idle_mode)
+ coalescing |= CMDQ_CREATE_CQ_ENABLE_RING_IDLE_MODE;
+ else
+ coalescing &= ~CMDQ_CREATE_CQ_ENABLE_RING_IDLE_MODE;
+ req.coalescing = cpu_to_le32(coalescing);
+ }
+
pbl = &cq->hwq.pbl[PBL_LVL_0];
pg_sz_lvl = (bnxt_qplib_base_pg_size(&cq->hwq) <<
CMDQ_CREATE_CQ_PG_SIZE_SFT);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
index 820611a23943..ef3424c81345 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -383,6 +383,25 @@ static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_q *que,
return avail <= slots;
}
+/* CQ coalescing parameters */
+struct bnxt_qplib_cq_coal_param {
+ u16 buf_maxtime;
+ u8 normal_maxbuf;
+ u8 during_maxbuf;
+ u8 en_ring_idle_mode;
+};
+
+#define BNXT_QPLIB_CQ_COAL_DEF_BUF_MAXTIME 0x1
+#define BNXT_QPLIB_CQ_COAL_DEF_NORMAL_MAXBUF_P7 0x8
+#define BNXT_QPLIB_CQ_COAL_DEF_DURING_MAXBUF_P7 0x8
+#define BNXT_QPLIB_CQ_COAL_DEF_NORMAL_MAXBUF_P5 0x1
+#define BNXT_QPLIB_CQ_COAL_DEF_DURING_MAXBUF_P5 0x1
+#define BNXT_QPLIB_CQ_COAL_DEF_EN_RING_IDLE_MODE 0x1
+#define BNXT_QPLIB_CQ_COAL_MAX_BUF_MAXTIME 0x1bf
+#define BNXT_QPLIB_CQ_COAL_MAX_NORMAL_MAXBUF 0x1f
+#define BNXT_QPLIB_CQ_COAL_MAX_DURING_MAXBUF 0x1f
+#define BNXT_QPLIB_CQ_COAL_MAX_EN_RING_IDLE_MODE 0x1
+
struct bnxt_qplib_cqe {
u8 status;
u8 type;
@@ -391,7 +410,7 @@ struct bnxt_qplib_cqe {
u16 cfa_meta;
u64 wr_id;
union {
- __le32 immdata;
+ u32 immdata;
u32 invrkey;
};
u64 qp_handle;
@@ -445,6 +464,7 @@ struct bnxt_qplib_cq {
*/
spinlock_t flush_lock; /* QP flush management */
u16 cnq_events;
+ struct bnxt_qplib_cq_coal_param *coalescing;
};
#define BNXT_QPLIB_MAX_IRRQE_ENTRY_SIZE sizeof(struct xrrq_irrq)
@@ -499,6 +519,7 @@ struct bnxt_qplib_nq {
struct tasklet_struct nq_tasklet;
bool requested;
int budget;
+ u32 load;
cqn_handler_t cqn_handler;
srqn_handler_t srqn_handler;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index e82bd37158ad..5e90ea232de8 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -831,6 +831,7 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
struct creq_initialize_fw_resp resp = {};
struct cmdq_initialize_fw req = {};
struct bnxt_qplib_cmdqmsg msg = {};
+ u16 flags = 0;
u8 pgsz, lvl;
int rc;
@@ -849,10 +850,8 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
* shall setup this area for VF. Skipping the
* HW programming
*/
- if (is_virtfn)
+ if (is_virtfn || bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx))
goto skip_ctx_setup;
- if (bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx))
- goto config_vf_res;
lvl = ctx->qpc_tbl.level;
pgsz = bnxt_qplib_base_pg_size(&ctx->qpc_tbl);
@@ -896,16 +895,14 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
req.number_of_srq = cpu_to_le32(ctx->srqc_tbl.max_elements);
req.number_of_cq = cpu_to_le32(ctx->cq_tbl.max_elements);
-config_vf_res:
- req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf);
- req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf);
- req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf);
- req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf);
- req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf);
-
skip_ctx_setup:
if (BNXT_RE_HW_RETX(rcfw->res->dattr->dev_cap_flags))
- req.flags |= cpu_to_le16(CMDQ_INITIALIZE_FW_FLAGS_HW_REQUESTER_RETX_SUPPORTED);
+ flags |= CMDQ_INITIALIZE_FW_FLAGS_HW_REQUESTER_RETX_SUPPORTED;
+ if (_is_optimize_modify_qp_supported(rcfw->res->dattr->dev_cap_flags2))
+ flags |= CMDQ_INITIALIZE_FW_FLAGS_OPTIMIZE_MODIFY_QP_SUPPORTED;
+ if (rcfw->res->en_dev->flags & BNXT_EN_FLAG_ROCE_VF_RES_MGMT)
+ flags |= CMDQ_INITIALIZE_FW_FLAGS_L2_VF_RESOURCE_MGMT;
+ req.flags |= cpu_to_le16(flags);
req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id);
bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), sizeof(resp), 0);
rc = bnxt_qplib_rcfw_send_message(rcfw, &msg);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
index 07779aeb7575..88814cb3aa74 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
@@ -131,6 +131,8 @@ static inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
#define RCFW_CMD_IS_BLOCKING 0x8000
#define HWRM_VERSION_DEV_ATTR_MAX_DPI 0x1000A0000000DULL
+/* HWRM version 1.10.3.18 */
+#define HWRM_VERSION_READ_CTX 0x1000A00030012
/* Crsq buf is 1024-Byte */
struct bnxt_qplib_crsbe {
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
index c2f710364e0f..21fb148713a6 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
@@ -39,6 +39,8 @@
#ifndef __BNXT_QPLIB_RES_H__
#define __BNXT_QPLIB_RES_H__
+#include "bnxt_ulp.h"
+
extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero;
#define CHIP_NUM_57508 0x1750
@@ -302,6 +304,7 @@ struct bnxt_qplib_res {
struct bnxt_qplib_chip_ctx *cctx;
struct bnxt_qplib_dev_attr *dattr;
struct net_device *netdev;
+ struct bnxt_en_dev *en_dev;
struct bnxt_qplib_rcfw *rcfw;
struct bnxt_qplib_pd_tbl pd_tbl;
/* To protect the pd table bit map */
@@ -576,4 +579,14 @@ static inline bool _is_relaxed_ordering_supported(u16 dev_cap_ext_flags2)
return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_MEMORY_REGION_RO_SUPPORTED;
}
+static inline bool _is_optimize_modify_qp_supported(u16 dev_cap_ext_flags2)
+{
+ return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_OPTIMIZE_MODIFY_QP_SUPPORTED;
+}
+
+static inline bool _is_cq_coalescing_supported(u16 dev_cap_ext_flags2)
+{
+ return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_CQ_COALESCING_SUPPORTED;
+}
+
#endif /* __BNXT_QPLIB_RES_H__ */
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
index e29fbbdab9fd..7e20ae3d2c4f 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -981,3 +981,38 @@ int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res,
rc = bnxt_qplib_rcfw_send_message(res->rcfw, &msg);
return rc;
}
+
+int bnxt_qplib_read_context(struct bnxt_qplib_rcfw *rcfw, u8 res_type,
+ u32 xid, u32 resp_size, void *resp_va)
+{
+ struct creq_read_context resp = {};
+ struct bnxt_qplib_cmdqmsg msg = {};
+ struct cmdq_read_context req = {};
+ struct bnxt_qplib_rcfw_sbuf sbuf;
+ int rc;
+
+ sbuf.size = resp_size;
+ sbuf.sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf.size,
+ &sbuf.dma_addr, GFP_KERNEL);
+ if (!sbuf.sb)
+ return -ENOMEM;
+
+ bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
+ CMDQ_BASE_OPCODE_READ_CONTEXT, sizeof(req));
+ req.resp_addr = cpu_to_le64(sbuf.dma_addr);
+ req.resp_size = resp_size / BNXT_QPLIB_CMDQE_UNITS;
+
+ req.xid = cpu_to_le32(xid);
+ req.type = res_type;
+
+ bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req),
+ sizeof(resp), 0);
+ rc = bnxt_qplib_rcfw_send_message(rcfw, &msg);
+ if (rc)
+ goto free_mem;
+
+ memcpy(resp_va, sbuf.sb, resp_size);
+free_mem:
+ dma_free_coherent(&rcfw->pdev->dev, sbuf.size, sbuf.sb, sbuf.dma_addr);
+ return rc;
+}
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
index ecf3f45fea74..e6beeb514b7d 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
@@ -353,6 +353,8 @@ int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid,
struct bnxt_qplib_ext_stat *estat);
int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res,
struct bnxt_qplib_cc_param *cc_param);
+int bnxt_qplib_read_context(struct bnxt_qplib_rcfw *rcfw, u8 type, u32 xid,
+ u32 resp_size, void *resp_va);
#define BNXT_VAR_MAX_WQE 4352
#define BNXT_VAR_MAX_SLOT_ALIGN 256
diff --git a/drivers/infiniband/hw/bnxt_re/roce_hsi.h b/drivers/infiniband/hw/bnxt_re/roce_hsi.h
index 3ec895284e49..a98fc9c2313e 100644
--- a/drivers/infiniband/hw/bnxt_re/roce_hsi.h
+++ b/drivers/infiniband/hw/bnxt_re/roce_hsi.h
@@ -216,6 +216,8 @@ struct cmdq_initialize_fw {
__le16 flags;
#define CMDQ_INITIALIZE_FW_FLAGS_MRAV_RESERVATION_SPLIT 0x1UL
#define CMDQ_INITIALIZE_FW_FLAGS_HW_REQUESTER_RETX_SUPPORTED 0x2UL
+ #define CMDQ_INITIALIZE_FW_FLAGS_OPTIMIZE_MODIFY_QP_SUPPORTED 0x8UL
+ #define CMDQ_INITIALIZE_FW_FLAGS_L2_VF_RESOURCE_MGMT 0x10UL
__le16 cookie;
u8 resp_size;
u8 reserved8;
@@ -559,6 +561,7 @@ struct cmdq_modify_qp {
#define CMDQ_MODIFY_QP_OPCODE_LAST CMDQ_MODIFY_QP_OPCODE_MODIFY_QP
u8 cmd_size;
__le16 flags;
+ #define CMDQ_MODIFY_QP_FLAGS_SRQ_USED 0x1UL
__le16 cookie;
u8 resp_size;
u8 qp_type;
@@ -1137,6 +1140,7 @@ struct cmdq_create_cq {
#define CMDQ_CREATE_CQ_FLAGS_DISABLE_CQ_OVERFLOW_DETECTION 0x1UL
#define CMDQ_CREATE_CQ_FLAGS_STEERING_TAG_VALID 0x2UL
#define CMDQ_CREATE_CQ_FLAGS_INFINITE_CQ_MODE 0x4UL
+ #define CMDQ_CREATE_CQ_FLAGS_COALESCING_VALID 0x8UL
__le16 cookie;
u8 resp_size;
u8 reserved8;
@@ -1169,7 +1173,18 @@ struct cmdq_create_cq {
__le32 cq_size;
__le64 pbl;
__le16 steering_tag;
- u8 reserved48[6];
+ u8 reserved48[2];
+ __le32 coalescing;
+ #define CMDQ_CREATE_CQ_BUF_MAXTIME_MASK 0x1ffUL
+ #define CMDQ_CREATE_CQ_BUF_MAXTIME_SFT 0
+ #define CMDQ_CREATE_CQ_NORMAL_MAXBUF_MASK 0x3e00UL
+ #define CMDQ_CREATE_CQ_NORMAL_MAXBUF_SFT 9
+ #define CMDQ_CREATE_CQ_DURING_MAXBUF_MASK 0x7c000UL
+ #define CMDQ_CREATE_CQ_DURING_MAXBUF_SFT 14
+ #define CMDQ_CREATE_CQ_ENABLE_RING_IDLE_MODE 0x80000UL
+ #define CMDQ_CREATE_CQ_UNUSED12_MASK 0xfff00000UL
+ #define CMDQ_CREATE_CQ_UNUSED12_SFT 20
+ __le64 reserved64;
};
/* creq_create_cq_resp (size:128b/16B) */
@@ -2251,6 +2266,46 @@ struct creq_set_func_resources_resp {
u8 reserved48[6];
};
+/* cmdq_read_context (size:192b/24B) */
+struct cmdq_read_context {
+ u8 opcode;
+ #define CMDQ_READ_CONTEXT_OPCODE_READ_CONTEXT 0x85UL
+ #define CMDQ_READ_CONTEXT_OPCODE_LAST CMDQ_READ_CONTEXT_OPCODE_READ_CONTEXT
+ u8 cmd_size;
+ __le16 flags;
+ __le16 cookie;
+ u8 resp_size;
+ u8 reserved8;
+ __le64 resp_addr;
+ __le32 xid;
+ u8 type;
+ #define CMDQ_READ_CONTEXT_TYPE_QPC 0x0UL
+ #define CMDQ_READ_CONTEXT_TYPE_CQ 0x1UL
+ #define CMDQ_READ_CONTEXT_TYPE_MRW 0x2UL
+ #define CMDQ_READ_CONTEXT_TYPE_SRQ 0x3UL
+ #define CMDQ_READ_CONTEXT_TYPE_LAST CMDQ_READ_CONTEXT_TYPE_SRQ
+ u8 unused_0[3];
+};
+
+/* creq_read_context (size:128b/16B) */
+struct creq_read_context {
+ u8 type;
+ #define CREQ_READ_CONTEXT_TYPE_MASK 0x3fUL
+ #define CREQ_READ_CONTEXT_TYPE_SFT 0
+ #define CREQ_READ_CONTEXT_TYPE_QP_EVENT 0x38UL
+ #define CREQ_READ_CONTEXT_TYPE_LAST CREQ_READ_CONTEXT_TYPE_QP_EVENT
+ u8 status;
+ __le16 cookie;
+ __le32 reserved32;
+ u8 v;
+ #define CREQ_READ_CONTEXT_V 0x1UL
+ u8 event;
+ #define CREQ_READ_CONTEXT_EVENT_READ_CONTEXT 0x85UL
+ #define CREQ_READ_CONTEXT_EVENT_LAST CREQ_READ_CONTEXT_EVENT_READ_CONTEXT
+ __le16 reserved16;
+ __le32 reserved_32;
+};
+
/* cmdq_map_tc_to_cos (size:192b/24B) */
struct cmdq_map_tc_to_cos {
u8 opcode;
diff --git a/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h b/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h
index cd03a5429beb..fe0b6aec7839 100644
--- a/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h
+++ b/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h
@@ -30,7 +30,8 @@ enum efa_admin_aq_opcode {
EFA_ADMIN_DEALLOC_UAR = 17,
EFA_ADMIN_CREATE_EQ = 18,
EFA_ADMIN_DESTROY_EQ = 19,
- EFA_ADMIN_MAX_OPCODE = 19,
+ EFA_ADMIN_ALLOC_MR = 20,
+ EFA_ADMIN_MAX_OPCODE = 20,
};
enum efa_admin_aq_feature_id {
@@ -150,8 +151,11 @@ struct efa_admin_create_qp_cmd {
/* UAR number */
u16 uar;
+ /* Requested service level for the QP, 0 is the default SL */
+ u8 sl;
+
/* MBZ */
- u16 reserved;
+ u8 reserved;
/* MBZ */
u32 reserved2;
@@ -459,6 +463,41 @@ struct efa_admin_dereg_mr_resp {
struct efa_admin_acq_common_desc acq_common_desc;
};
+/*
+ * Allocation of MemoryRegion, required for QP working with Virtual
+ * Addresses in kernel verbs semantics, ready for fast registration use.
+ */
+struct efa_admin_alloc_mr_cmd {
+ /* Common Admin Queue descriptor */
+ struct efa_admin_aq_common_desc aq_common_desc;
+
+ /* Protection Domain */
+ u16 pd;
+
+ /* MBZ */
+ u16 reserved1;
+
+ /* Maximum number of pages this MR supports. */
+ u32 max_pages;
+};
+
+struct efa_admin_alloc_mr_resp {
+ /* Common Admin Queue completion descriptor */
+ struct efa_admin_acq_common_desc acq_common_desc;
+
+ /*
+ * L_Key, to be used in conjunction with local buffer references in
+ * SQ and RQ WQE, or with virtual RQ/CQ rings
+ */
+ u32 l_key;
+
+ /*
+ * R_Key, to be used in RDMA messages to refer to remotely accessed
+ * memory region
+ */
+ u32 r_key;
+};
+
struct efa_admin_create_cq_cmd {
struct efa_admin_aq_common_desc aq_common_desc;
@@ -483,8 +522,8 @@ struct efa_admin_create_cq_cmd {
*/
u8 cq_caps_2;
- /* completion queue depth in # of entries. must be power of 2 */
- u16 cq_depth;
+ /* Sub completion queue depth in # of entries. must be power of 2 */
+ u16 sub_cq_depth;
/* EQ number assigned to this cq */
u16 eqn;
@@ -519,8 +558,8 @@ struct efa_admin_create_cq_resp {
u16 cq_idx;
- /* actual cq depth in number of entries */
- u16 cq_actual_depth;
+ /* actual sub cq depth in number of entries */
+ u16 sub_cq_actual_depth;
/* CQ doorbell address, as offset to PCIe DB BAR */
u32 db_offset;
@@ -578,6 +617,8 @@ struct efa_admin_basic_stats {
u64 rx_pkts;
u64 rx_drops;
+
+ u64 qkey_viol;
};
struct efa_admin_messages_stats {
@@ -677,6 +718,15 @@ struct efa_admin_feature_device_attr_desc {
/* Unique global ID for an EFA device */
u64 guid;
+
+ /* The device maximum link speed in Gbit/sec */
+ u16 max_link_speed_gbps;
+
+ /* MBZ */
+ u16 reserved0;
+
+ /* MBZ */
+ u32 reserved1;
};
struct efa_admin_feature_queue_attr_desc {
@@ -1057,7 +1107,6 @@ struct efa_admin_host_info {
/* create_eq_cmd */
#define EFA_ADMIN_CREATE_EQ_CMD_ENTRY_SIZE_WORDS_MASK GENMASK(4, 0)
-#define EFA_ADMIN_CREATE_EQ_CMD_VIRT_MASK BIT(6)
#define EFA_ADMIN_CREATE_EQ_CMD_COMPLETION_EVENTS_MASK BIT(0)
/* host_info */
diff --git a/drivers/infiniband/hw/efa/efa_admin_defs.h b/drivers/infiniband/hw/efa/efa_admin_defs.h
index 83f20c38a840..35700c93e639 100644
--- a/drivers/infiniband/hw/efa/efa_admin_defs.h
+++ b/drivers/infiniband/hw/efa/efa_admin_defs.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/*
- * Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#ifndef _EFA_ADMIN_H_
@@ -96,7 +96,7 @@ struct efa_admin_acq_entry {
struct efa_admin_aenq_common_desc {
u16 group;
- u16 syndrom;
+ u16 syndrome;
/*
* 0 : phase
diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c b/drivers/infiniband/hw/efa/efa_com_cmd.c
index 5a774925cdea..c6b89c45fdc9 100644
--- a/drivers/infiniband/hw/efa/efa_com_cmd.c
+++ b/drivers/infiniband/hw/efa/efa_com_cmd.c
@@ -31,6 +31,7 @@ int efa_com_create_qp(struct efa_com_dev *edev,
create_qp_cmd.qp_alloc_size.recv_queue_depth =
params->rq_depth;
create_qp_cmd.uar = params->uarn;
+ create_qp_cmd.sl = params->sl;
if (params->unsolicited_write_recv)
EFA_SET(&create_qp_cmd.flags, EFA_ADMIN_CREATE_QP_CMD_UNSOLICITED_WRITE_RECV, 1);
@@ -163,7 +164,7 @@ int efa_com_create_cq(struct efa_com_dev *edev,
EFA_SET(&create_cmd.cq_caps_2,
EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS,
params->entry_size_in_bytes / 4);
- create_cmd.cq_depth = params->cq_depth;
+ create_cmd.sub_cq_depth = params->sub_cq_depth;
create_cmd.num_sub_cqs = params->num_sub_cqs;
create_cmd.uar = params->uarn;
if (params->interrupt_mode_enabled) {
@@ -191,7 +192,7 @@ int efa_com_create_cq(struct efa_com_dev *edev,
}
result->cq_idx = cmd_completion.cq_idx;
- result->actual_depth = params->cq_depth;
+ result->actual_depth = params->sub_cq_depth;
result->db_off = cmd_completion.db_offset;
result->db_valid = EFA_GET(&cmd_completion.flags,
EFA_ADMIN_CREATE_CQ_RESP_DB_VALID);
@@ -466,6 +467,7 @@ int efa_com_get_device_attr(struct efa_com_dev *edev,
result->max_rdma_size = resp.u.device_attr.max_rdma_size;
result->device_caps = resp.u.device_attr.device_caps;
result->guid = resp.u.device_attr.guid;
+ result->max_link_speed_gbps = resp.u.device_attr.max_link_speed_gbps;
if (result->admin_api_version < 1) {
ibdev_err_ratelimited(
diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.h b/drivers/infiniband/hw/efa/efa_com_cmd.h
index 668d033f7477..5511355b700d 100644
--- a/drivers/infiniband/hw/efa/efa_com_cmd.h
+++ b/drivers/infiniband/hw/efa/efa_com_cmd.h
@@ -27,6 +27,7 @@ struct efa_com_create_qp_params {
u16 pd;
u16 uarn;
u8 qp_type;
+ u8 sl;
u8 unsolicited_write_recv : 1;
};
@@ -71,7 +72,7 @@ struct efa_com_create_cq_params {
/* cq physical base address in OS memory */
dma_addr_t dma_addr;
/* completion queue depth in # of entries */
- u16 cq_depth;
+ u16 sub_cq_depth;
u16 num_sub_cqs;
u16 uarn;
u16 eqn;
@@ -141,6 +142,7 @@ struct efa_com_get_device_attr_result {
u16 max_wr_rdma_sge;
u16 max_tx_batch;
u16 min_sq_depth;
+ u16 max_link_speed_gbps;
u8 db_bar;
};
diff --git a/drivers/infiniband/hw/efa/efa_io_defs.h b/drivers/infiniband/hw/efa/efa_io_defs.h
index 2d8eb96eaa81..a4c9fd33da38 100644
--- a/drivers/infiniband/hw/efa/efa_io_defs.h
+++ b/drivers/infiniband/hw/efa/efa_io_defs.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/*
- * Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#ifndef _EFA_IO_H_
@@ -10,6 +10,7 @@
#define EFA_IO_TX_DESC_NUM_RDMA_BUFS 1
#define EFA_IO_TX_DESC_INLINE_MAX_SIZE 32
#define EFA_IO_TX_DESC_IMM_DATA_SIZE 4
+#define EFA_IO_TX_DESC_INLINE_PBL_SIZE 1
enum efa_io_queue_type {
/* send queue (of a QP) */
@@ -25,6 +26,10 @@ enum efa_io_send_op_type {
EFA_IO_RDMA_READ = 1,
/* RDMA write */
EFA_IO_RDMA_WRITE = 2,
+ /* Fast MR registration */
+ EFA_IO_FAST_REG = 3,
+ /* Fast MR invalidation */
+ EFA_IO_FAST_INV = 4,
};
enum efa_io_comp_status {
@@ -34,15 +39,15 @@ enum efa_io_comp_status {
EFA_IO_COMP_STATUS_FLUSHED = 1,
/* Internal QP error */
EFA_IO_COMP_STATUS_LOCAL_ERROR_QP_INTERNAL_ERROR = 2,
- /* Bad operation type */
- EFA_IO_COMP_STATUS_LOCAL_ERROR_INVALID_OP_TYPE = 3,
+ /* Unsupported operation */
+ EFA_IO_COMP_STATUS_LOCAL_ERROR_UNSUPPORTED_OP = 3,
/* Bad AH */
EFA_IO_COMP_STATUS_LOCAL_ERROR_INVALID_AH = 4,
/* LKEY not registered or does not match IOVA */
EFA_IO_COMP_STATUS_LOCAL_ERROR_INVALID_LKEY = 5,
/* Message too long */
EFA_IO_COMP_STATUS_LOCAL_ERROR_BAD_LENGTH = 6,
- /* Destination ENI is down or does not run EFA */
+ /* RKEY not registered or does not match remote IOVA */
EFA_IO_COMP_STATUS_REMOTE_ERROR_BAD_ADDRESS = 7,
/* Connection was reset by remote side */
EFA_IO_COMP_STATUS_REMOTE_ERROR_ABORT = 8,
@@ -54,8 +59,17 @@ enum efa_io_comp_status {
EFA_IO_COMP_STATUS_REMOTE_ERROR_BAD_LENGTH = 11,
/* Unexpected status returned by responder */
EFA_IO_COMP_STATUS_REMOTE_ERROR_BAD_STATUS = 12,
- /* Unresponsive remote - detected locally */
+ /* Unresponsive remote - was previously responsive */
EFA_IO_COMP_STATUS_LOCAL_ERROR_UNRESP_REMOTE = 13,
+ /* No valid AH at remote side (required for RDMA operations) */
+ EFA_IO_COMP_STATUS_REMOTE_ERROR_UNKNOWN_PEER = 14,
+ /* Unreachable remote - never received a response */
+ EFA_IO_COMP_STATUS_LOCAL_ERROR_UNREACH_REMOTE = 15,
+};
+
+enum efa_io_frwr_pbl_mode {
+ EFA_IO_FRWR_INLINE_PBL = 0,
+ EFA_IO_FRWR_DIRECT_PBL = 1,
};
struct efa_io_tx_meta_desc {
@@ -95,13 +109,13 @@ struct efa_io_tx_meta_desc {
/*
* If inline_msg bit is set, length of inline message in bytes,
- * otherwise length of SGL (number of buffers).
+ * otherwise length of SGL (number of buffers).
*/
u16 length;
/*
- * immediate data: if has_imm is set, then this field is included
- * within Tx message and reported in remote Rx completion.
+ * immediate data: if has_imm is set, then this field is included within
+ * Tx message and reported in remote Rx completion.
*/
u32 immediate_data;
@@ -158,6 +172,63 @@ struct efa_io_rdma_req {
struct efa_io_tx_buf_desc local_mem[1];
};
+struct efa_io_fast_mr_reg_req {
+ /* Updated local key of the MR after lkey/rkey increment */
+ u32 lkey;
+
+ /*
+ * permissions
+ * 0 : local_write_enable - Local write permissions:
+ * must be set for RQ buffers and buffers posted for
+ * RDMA Read requests
+ * 1 : remote_write_enable - Remote write
+ * permissions: must be set to enable RDMA write to
+ * the region
+ * 2 : remote_read_enable - Remote read permissions:
+ * must be set to enable RDMA read from the region
+ * 7:3 : reserved2 - MBZ
+ */
+ u8 permissions;
+
+ /*
+ * control flags
+ * 4:0 : phys_page_size_shift - page size is (1 <<
+ * phys_page_size_shift)
+ * 6:5 : pbl_mode - enum efa_io_frwr_pbl_mode
+ * 7 : reserved - MBZ
+ */
+ u8 flags;
+
+ /* MBZ */
+ u8 reserved[2];
+
+ /* IO Virtual Address associated with this MR */
+ u64 iova;
+
+ /* Memory region length, in bytes */
+ u64 mr_length;
+
+ /* Physical Buffer List, each element is page-aligned. */
+ union {
+ /*
+ * Inline array of physical page addresses (optimization
+ * for short region activation).
+ */
+ u64 inline_array[1];
+
+ /* points to PBL (Currently only direct) */
+ u64 dma_addr;
+ } pbl;
+};
+
+struct efa_io_fast_mr_inv_req {
+ /* Local key of the MR to invalidate */
+ u32 lkey;
+
+ /* MBZ */
+ u8 reserved[28];
+};
+
/*
* Tx WQE, composed of tx meta descriptors followed by either tx buffer
* descriptors or inline data
@@ -174,6 +245,12 @@ struct efa_io_tx_wqe {
/* RDMA local and remote memory addresses */
struct efa_io_rdma_req rdma_req;
+
+ /* Fast registration */
+ struct efa_io_fast_mr_reg_req reg_mr_req;
+
+ /* Fast invalidation */
+ struct efa_io_fast_mr_inv_req inv_mr_req;
} data;
};
@@ -208,7 +285,7 @@ struct efa_io_rx_desc {
struct efa_io_cdesc_common {
/*
* verbs-generated request ID, as provided in the completed tx or rx
- * descriptor.
+ * descriptor.
*/
u16 req_id;
@@ -221,7 +298,8 @@ struct efa_io_cdesc_common {
* 3 : has_imm - indicates that immediate data is
* present - for RX completions only
* 6:4 : op_type - enum efa_io_send_op_type
- * 7 : reserved31 - MBZ
+ * 7 : unsolicited - indicates that there is no
+ * matching request - for RDMA with imm. RX only
*/
u8 flags;
@@ -291,6 +369,13 @@ struct efa_io_rx_cdesc_ex {
/* tx_buf_desc */
#define EFA_IO_TX_BUF_DESC_LKEY_MASK GENMASK(23, 0)
+/* fast_mr_reg_req */
+#define EFA_IO_FAST_MR_REG_REQ_LOCAL_WRITE_ENABLE_MASK BIT(0)
+#define EFA_IO_FAST_MR_REG_REQ_REMOTE_WRITE_ENABLE_MASK BIT(1)
+#define EFA_IO_FAST_MR_REG_REQ_REMOTE_READ_ENABLE_MASK BIT(2)
+#define EFA_IO_FAST_MR_REG_REQ_PHYS_PAGE_SIZE_SHIFT_MASK GENMASK(4, 0)
+#define EFA_IO_FAST_MR_REG_REQ_PBL_MODE_MASK GENMASK(6, 5)
+
/* rx_desc */
#define EFA_IO_RX_DESC_LKEY_MASK GENMASK(23, 0)
#define EFA_IO_RX_DESC_FIRST_MASK BIT(30)
@@ -301,5 +386,6 @@ struct efa_io_rx_cdesc_ex {
#define EFA_IO_CDESC_COMMON_Q_TYPE_MASK GENMASK(2, 1)
#define EFA_IO_CDESC_COMMON_HAS_IMM_MASK BIT(3)
#define EFA_IO_CDESC_COMMON_OP_TYPE_MASK GENMASK(6, 4)
+#define EFA_IO_CDESC_COMMON_UNSOLICITED_MASK BIT(7)
#endif /* _EFA_IO_H_ */
diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index cc13415ff7e7..a8645a40730f 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -85,6 +85,8 @@ static const struct rdma_stat_desc efa_port_stats_descs[] = {
EFA_DEFINE_PORT_STATS(EFA_STATS_STR)
};
+#define EFA_DEFAULT_LINK_SPEED_GBPS 100
+
#define EFA_CHUNK_PAYLOAD_SHIFT 12
#define EFA_CHUNK_PAYLOAD_SIZE BIT(EFA_CHUNK_PAYLOAD_SHIFT)
#define EFA_CHUNK_PAYLOAD_PTR_SIZE 8
@@ -277,10 +279,47 @@ int efa_query_device(struct ib_device *ibdev,
return 0;
}
+static void efa_link_gbps_to_speed_and_width(u16 gbps,
+ enum ib_port_speed *speed,
+ enum ib_port_width *width)
+{
+ if (gbps >= 400) {
+ *width = IB_WIDTH_8X;
+ *speed = IB_SPEED_HDR;
+ } else if (gbps >= 200) {
+ *width = IB_WIDTH_4X;
+ *speed = IB_SPEED_HDR;
+ } else if (gbps >= 120) {
+ *width = IB_WIDTH_12X;
+ *speed = IB_SPEED_FDR10;
+ } else if (gbps >= 100) {
+ *width = IB_WIDTH_4X;
+ *speed = IB_SPEED_EDR;
+ } else if (gbps >= 60) {
+ *width = IB_WIDTH_12X;
+ *speed = IB_SPEED_DDR;
+ } else if (gbps >= 50) {
+ *width = IB_WIDTH_1X;
+ *speed = IB_SPEED_HDR;
+ } else if (gbps >= 40) {
+ *width = IB_WIDTH_4X;
+ *speed = IB_SPEED_FDR10;
+ } else if (gbps >= 30) {
+ *width = IB_WIDTH_12X;
+ *speed = IB_SPEED_SDR;
+ } else {
+ *width = IB_WIDTH_1X;
+ *speed = IB_SPEED_EDR;
+ }
+}
+
int efa_query_port(struct ib_device *ibdev, u32 port,
struct ib_port_attr *props)
{
struct efa_dev *dev = to_edev(ibdev);
+ enum ib_port_speed link_speed;
+ enum ib_port_width link_width;
+ u16 link_gbps;
props->lmc = 1;
@@ -288,8 +327,10 @@ int efa_query_port(struct ib_device *ibdev, u32 port,
props->phys_state = IB_PORT_PHYS_STATE_LINK_UP;
props->gid_tbl_len = 1;
props->pkey_tbl_len = 1;
- props->active_speed = IB_SPEED_EDR;
- props->active_width = IB_WIDTH_4X;
+ link_gbps = dev->dev_attr.max_link_speed_gbps ?: EFA_DEFAULT_LINK_SPEED_GBPS;
+ efa_link_gbps_to_speed_and_width(link_gbps, &link_speed, &link_width);
+ props->active_speed = link_speed;
+ props->active_width = link_width;
props->max_mtu = ib_mtu_int_to_enum(dev->dev_attr.mtu);
props->active_mtu = ib_mtu_int_to_enum(dev->dev_attr.mtu);
props->max_msg_sz = dev->dev_attr.mtu;
@@ -676,7 +717,7 @@ int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
goto err_out;
}
- if (cmd.comp_mask || !is_reserved_cleared(cmd.reserved_90)) {
+ if (cmd.comp_mask || !is_reserved_cleared(cmd.reserved_98)) {
ibdev_dbg(&dev->ibdev,
"Incompatible ABI params, unknown fields in udata\n");
err = -EINVAL;
@@ -732,6 +773,8 @@ int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
create_qp_params.rq_base_addr = qp->rq_dma_addr;
}
+ create_qp_params.sl = cmd.sl;
+
if (cmd.flags & EFA_CREATE_QP_WITH_UNSOLICITED_WRITE_RECV)
create_qp_params.unsolicited_write_recv = true;
@@ -1167,7 +1210,7 @@ int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
}
params.uarn = cq->ucontext->uarn;
- params.cq_depth = entries;
+ params.sub_cq_depth = entries;
params.dma_addr = cq->dma_addr;
params.entry_size_in_bytes = cmd.cq_entry_size;
params.num_sub_cqs = cmd.num_sub_cqs;
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index c52e6b2c9914..a442eca498b8 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -13235,7 +13235,7 @@ int set_intr_bits(struct hfi1_devdata *dd, u16 first, u16 last, bool set)
/*
* Clear all interrupt sources on the chip.
*/
-void clear_all_interrupts(struct hfi1_devdata *dd)
+static void clear_all_interrupts(struct hfi1_devdata *dd)
{
int i;
diff --git a/drivers/infiniband/hw/hfi1/chip.h b/drivers/infiniband/hw/hfi1/chip.h
index d861aa8fc640..8841db16bde7 100644
--- a/drivers/infiniband/hw/hfi1/chip.h
+++ b/drivers/infiniband/hw/hfi1/chip.h
@@ -1404,7 +1404,6 @@ irqreturn_t receive_context_interrupt_napi(int irq, void *data);
int set_intr_bits(struct hfi1_devdata *dd, u16 first, u16 last, bool set);
void init_qsfp_int(struct hfi1_devdata *dd);
-void clear_all_interrupts(struct hfi1_devdata *dd);
void remap_intr(struct hfi1_devdata *dd, int isrc, int msix_intr);
void remap_sdma_interrupts(struct hfi1_devdata *dd, int engine, int msix_intr);
void reset_interrupts(struct hfi1_devdata *dd);
diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c
index 4ec66611a143..4106423a1b39 100644
--- a/drivers/infiniband/hw/hns/hns_roce_cq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_cq.c
@@ -179,8 +179,8 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_CQC,
hr_cq->cqn);
if (ret)
- dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret,
- hr_cq->cqn);
+ dev_err_ratelimited(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n",
+ ret, hr_cq->cqn);
xa_erase_irq(&cq_table->array, hr_cq->cqn);
diff --git a/drivers/infiniband/hw/hns/hns_roce_debugfs.c b/drivers/infiniband/hw/hns/hns_roce_debugfs.c
index e8febb40f645..b869cdc54118 100644
--- a/drivers/infiniband/hw/hns/hns_roce_debugfs.c
+++ b/drivers/infiniband/hw/hns/hns_roce_debugfs.c
@@ -5,6 +5,7 @@
#include <linux/debugfs.h>
#include <linux/device.h>
+#include <linux/pci.h>
#include "hns_roce_device.h"
@@ -86,7 +87,7 @@ void hns_roce_register_debugfs(struct hns_roce_dev *hr_dev)
{
struct hns_roce_dev_debugfs *dbgfs = &hr_dev->dbgfs;
- dbgfs->root = debugfs_create_dir(dev_name(&hr_dev->ib_dev.dev),
+ dbgfs->root = debugfs_create_dir(pci_name(hr_dev->pci_dev),
hns_roce_dbgfs_root);
create_sw_stat_debugfs(hr_dev, dbgfs->root);
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 0b1e21cb6d2d..560a1d9de408 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -489,12 +489,6 @@ struct hns_roce_bank {
u32 next; /* Next ID to allocate. */
};
-struct hns_roce_idx_table {
- u32 *spare_idx;
- u32 head;
- u32 tail;
-};
-
struct hns_roce_qp_table {
struct hns_roce_hem_table qp_table;
struct hns_roce_hem_table irrl_table;
@@ -503,7 +497,7 @@ struct hns_roce_qp_table {
struct mutex scc_mutex;
struct hns_roce_bank bank[HNS_ROCE_QP_BANK_NUM];
struct mutex bank_mutex;
- struct hns_roce_idx_table idx_table;
+ struct xarray dip_xa;
};
struct hns_roce_cq_table {
@@ -593,6 +587,7 @@ struct hns_roce_dev;
enum {
HNS_ROCE_FLUSH_FLAG = 0,
+ HNS_ROCE_STOP_FLUSH_FLAG = 1,
};
struct hns_roce_work {
@@ -656,6 +651,8 @@ struct hns_roce_qp {
enum hns_roce_cong_type cong_type;
u8 tc_mode;
u8 priority;
+ spinlock_t flush_lock;
+ struct hns_roce_dip *dip;
};
struct hns_roce_ib_iboe {
@@ -982,8 +979,6 @@ struct hns_roce_dev {
enum hns_roce_device_state state;
struct list_head qp_list; /* list of all qps on this dev */
spinlock_t qp_list_lock; /* protect qp_list */
- struct list_head dip_list; /* list of all dest ips on this dev */
- spinlock_t dip_list_lock; /* protect dip_list */
struct list_head pgdir_list;
struct mutex pgdir_mutex;
@@ -1289,6 +1284,7 @@ void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn);
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type);
void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp);
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type);
+void hns_roce_flush_cqe(struct hns_roce_dev *hr_dev, u32 qpn);
void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type);
void hns_roce_handle_device_err(struct hns_roce_dev *hr_dev);
int hns_roce_init(struct hns_roce_dev *hr_dev);
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c
index c7c167e2a045..f84521be3bea 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hem.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hem.c
@@ -300,7 +300,7 @@ static int calc_hem_config(struct hns_roce_dev *hr_dev,
struct hns_roce_hem_mhop *mhop,
struct hns_roce_hem_index *index)
{
- struct ib_device *ibdev = &hr_dev->ib_dev;
+ struct device *dev = hr_dev->dev;
unsigned long mhop_obj = obj;
u32 l0_idx, l1_idx, l2_idx;
u32 chunk_ba_num;
@@ -331,14 +331,14 @@ static int calc_hem_config(struct hns_roce_dev *hr_dev,
index->buf = l0_idx;
break;
default:
- ibdev_err(ibdev, "table %u not support mhop.hop_num = %u!\n",
- table->type, mhop->hop_num);
+ dev_err(dev, "table %u not support mhop.hop_num = %u!\n",
+ table->type, mhop->hop_num);
return -EINVAL;
}
if (unlikely(index->buf >= table->num_hem)) {
- ibdev_err(ibdev, "table %u exceed hem limt idx %llu, max %lu!\n",
- table->type, index->buf, table->num_hem);
+ dev_err(dev, "table %u exceed hem limt idx %llu, max %lu!\n",
+ table->type, index->buf, table->num_hem);
return -EINVAL;
}
@@ -448,14 +448,14 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev,
struct hns_roce_hem_mhop *mhop,
struct hns_roce_hem_index *index)
{
- struct ib_device *ibdev = &hr_dev->ib_dev;
+ struct device *dev = hr_dev->dev;
u32 step_idx;
int ret = 0;
if (index->inited & HEM_INDEX_L0) {
ret = hr_dev->hw->set_hem(hr_dev, table, obj, 0);
if (ret) {
- ibdev_err(ibdev, "set HEM step 0 failed!\n");
+ dev_err(dev, "set HEM step 0 failed!\n");
goto out;
}
}
@@ -463,7 +463,7 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev,
if (index->inited & HEM_INDEX_L1) {
ret = hr_dev->hw->set_hem(hr_dev, table, obj, 1);
if (ret) {
- ibdev_err(ibdev, "set HEM step 1 failed!\n");
+ dev_err(dev, "set HEM step 1 failed!\n");
goto out;
}
}
@@ -475,7 +475,7 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev,
step_idx = mhop->hop_num;
ret = hr_dev->hw->set_hem(hr_dev, table, obj, step_idx);
if (ret)
- ibdev_err(ibdev, "set HEM step last failed!\n");
+ dev_err(dev, "set HEM step last failed!\n");
}
out:
return ret;
@@ -485,14 +485,14 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
struct hns_roce_hem_table *table,
unsigned long obj)
{
- struct ib_device *ibdev = &hr_dev->ib_dev;
struct hns_roce_hem_index index = {};
struct hns_roce_hem_mhop mhop = {};
+ struct device *dev = hr_dev->dev;
int ret;
ret = calc_hem_config(hr_dev, table, obj, &mhop, &index);
if (ret) {
- ibdev_err(ibdev, "calc hem config failed!\n");
+ dev_err(dev, "calc hem config failed!\n");
return ret;
}
@@ -504,7 +504,7 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
ret = alloc_mhop_hem(hr_dev, table, &mhop, &index);
if (ret) {
- ibdev_err(ibdev, "alloc mhop hem failed!\n");
+ dev_err(dev, "alloc mhop hem failed!\n");
goto out;
}
@@ -512,7 +512,7 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
if (table->type < HEM_TYPE_MTT) {
ret = set_mhop_hem(hr_dev, table, obj, &mhop, &index);
if (ret) {
- ibdev_err(ibdev, "set HEM address to HW failed!\n");
+ dev_err(dev, "set HEM address to HW failed!\n");
goto err_alloc;
}
}
@@ -575,7 +575,7 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev,
struct hns_roce_hem_mhop *mhop,
struct hns_roce_hem_index *index)
{
- struct ib_device *ibdev = &hr_dev->ib_dev;
+ struct device *dev = hr_dev->dev;
u32 hop_num = mhop->hop_num;
u32 chunk_ba_num;
u32 step_idx;
@@ -605,21 +605,21 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev,
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx);
if (ret)
- ibdev_warn(ibdev, "failed to clear hop%u HEM, ret = %d.\n",
- hop_num, ret);
+ dev_warn(dev, "failed to clear hop%u HEM, ret = %d.\n",
+ hop_num, ret);
if (index->inited & HEM_INDEX_L1) {
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 1);
if (ret)
- ibdev_warn(ibdev, "failed to clear HEM step 1, ret = %d.\n",
- ret);
+ dev_warn(dev, "failed to clear HEM step 1, ret = %d.\n",
+ ret);
}
if (index->inited & HEM_INDEX_L0) {
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 0);
if (ret)
- ibdev_warn(ibdev, "failed to clear HEM step 0, ret = %d.\n",
- ret);
+ dev_warn(dev, "failed to clear HEM step 0, ret = %d.\n",
+ ret);
}
}
}
@@ -629,14 +629,14 @@ static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
unsigned long obj,
int check_refcount)
{
- struct ib_device *ibdev = &hr_dev->ib_dev;
struct hns_roce_hem_index index = {};
struct hns_roce_hem_mhop mhop = {};
+ struct device *dev = hr_dev->dev;
int ret;
ret = calc_hem_config(hr_dev, table, obj, &mhop, &index);
if (ret) {
- ibdev_err(ibdev, "calc hem config failed!\n");
+ dev_err(dev, "calc hem config failed!\n");
return;
}
@@ -672,8 +672,8 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT);
if (ret)
- dev_warn(dev, "failed to clear HEM base address, ret = %d.\n",
- ret);
+ dev_warn_ratelimited(dev, "failed to clear HEM base address, ret = %d.\n",
+ ret);
hns_roce_free_hem(hr_dev, table->hem[i]);
table->hem[i] = NULL;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 24e906b9d3ae..697b17cca02e 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -373,19 +373,12 @@ static int set_rwqe_data_seg(struct ib_qp *ibqp, const struct ib_send_wr *wr,
static int check_send_valid(struct hns_roce_dev *hr_dev,
struct hns_roce_qp *hr_qp)
{
- struct ib_device *ibdev = &hr_dev->ib_dev;
-
if (unlikely(hr_qp->state == IB_QPS_RESET ||
hr_qp->state == IB_QPS_INIT ||
- hr_qp->state == IB_QPS_RTR)) {
- ibdev_err(ibdev, "failed to post WQE, QP state %u!\n",
- hr_qp->state);
+ hr_qp->state == IB_QPS_RTR))
return -EINVAL;
- } else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)) {
- ibdev_err(ibdev, "failed to post WQE, dev state %d!\n",
- hr_dev->state);
+ else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN))
return -EIO;
- }
return 0;
}
@@ -582,7 +575,7 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp,
if (WARN_ON(ret))
return ret;
- hr_reg_write(rc_sq_wqe, RC_SEND_WQE_FENCE,
+ hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SO,
(wr->send_flags & IB_SEND_FENCE) ? 1 : 0);
hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SE,
@@ -2560,20 +2553,19 @@ static void hns_roce_free_link_table(struct hns_roce_dev *hr_dev)
free_link_table_buf(hr_dev, &priv->ext_llm);
}
-static void free_dip_list(struct hns_roce_dev *hr_dev)
+static void free_dip_entry(struct hns_roce_dev *hr_dev)
{
struct hns_roce_dip *hr_dip;
- struct hns_roce_dip *tmp;
- unsigned long flags;
+ unsigned long idx;
- spin_lock_irqsave(&hr_dev->dip_list_lock, flags);
+ xa_lock(&hr_dev->qp_table.dip_xa);
- list_for_each_entry_safe(hr_dip, tmp, &hr_dev->dip_list, node) {
- list_del(&hr_dip->node);
+ xa_for_each(&hr_dev->qp_table.dip_xa, idx, hr_dip) {
+ __xa_erase(&hr_dev->qp_table.dip_xa, hr_dip->dip_idx);
kfree(hr_dip);
}
- spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags);
+ xa_unlock(&hr_dev->qp_table.dip_xa);
}
static struct ib_pd *free_mr_init_pd(struct hns_roce_dev *hr_dev)
@@ -2775,8 +2767,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev,
ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT,
IB_QPS_INIT, NULL);
if (ret) {
- ibdev_err(ibdev, "failed to modify qp to init, ret = %d.\n",
- ret);
+ ibdev_err_ratelimited(ibdev, "failed to modify qp to init, ret = %d.\n",
+ ret);
return ret;
}
@@ -2981,7 +2973,7 @@ static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev)
hns_roce_free_link_table(hr_dev);
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP09)
- free_dip_list(hr_dev);
+ free_dip_entry(hr_dev);
}
static int hns_roce_mbox_post(struct hns_roce_dev *hr_dev,
@@ -3421,8 +3413,8 @@ static int free_mr_post_send_lp_wqe(struct hns_roce_qp *hr_qp)
ret = hns_roce_v2_post_send(&hr_qp->ibqp, send_wr, &bad_wr);
if (ret) {
- ibdev_err(ibdev, "failed to post wqe for free mr, ret = %d.\n",
- ret);
+ ibdev_err_ratelimited(ibdev, "failed to post wqe for free mr, ret = %d.\n",
+ ret);
return ret;
}
@@ -3461,9 +3453,9 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev)
ret = free_mr_post_send_lp_wqe(hr_qp);
if (ret) {
- ibdev_err(ibdev,
- "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n",
- hr_qp->qpn, ret);
+ ibdev_err_ratelimited(ibdev,
+ "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n",
+ hr_qp->qpn, ret);
break;
}
@@ -3474,16 +3466,16 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev)
while (cqe_cnt) {
npolled = hns_roce_v2_poll_cq(&free_mr->rsv_cq->ib_cq, cqe_cnt, wc);
if (npolled < 0) {
- ibdev_err(ibdev,
- "failed to poll cqe for free mr, remain %d cqe.\n",
- cqe_cnt);
+ ibdev_err_ratelimited(ibdev,
+ "failed to poll cqe for free mr, remain %d cqe.\n",
+ cqe_cnt);
goto out;
}
if (time_after(jiffies, end)) {
- ibdev_err(ibdev,
- "failed to poll cqe for free mr and timeout, remain %d cqe.\n",
- cqe_cnt);
+ ibdev_err_ratelimited(ibdev,
+ "failed to poll cqe for free mr and timeout, remain %d cqe.\n",
+ cqe_cnt);
goto out;
}
cqe_cnt -= npolled;
@@ -4701,26 +4693,49 @@ static int modify_qp_rtr_to_rts(struct ib_qp *ibqp, int attr_mask,
return 0;
}
+static int alloc_dip_entry(struct xarray *dip_xa, u32 qpn)
+{
+ struct hns_roce_dip *hr_dip;
+ int ret;
+
+ hr_dip = xa_load(dip_xa, qpn);
+ if (hr_dip)
+ return 0;
+
+ hr_dip = kzalloc(sizeof(*hr_dip), GFP_KERNEL);
+ if (!hr_dip)
+ return -ENOMEM;
+
+ ret = xa_err(xa_store(dip_xa, qpn, hr_dip, GFP_KERNEL));
+ if (ret)
+ kfree(hr_dip);
+
+ return ret;
+}
+
static int get_dip_ctx_idx(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
u32 *dip_idx)
{
const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr);
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
- u32 *spare_idx = hr_dev->qp_table.idx_table.spare_idx;
- u32 *head = &hr_dev->qp_table.idx_table.head;
- u32 *tail = &hr_dev->qp_table.idx_table.tail;
+ struct xarray *dip_xa = &hr_dev->qp_table.dip_xa;
+ struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
struct hns_roce_dip *hr_dip;
- unsigned long flags;
+ unsigned long idx;
int ret = 0;
- spin_lock_irqsave(&hr_dev->dip_list_lock, flags);
+ ret = alloc_dip_entry(dip_xa, ibqp->qp_num);
+ if (ret)
+ return ret;
- spare_idx[*tail] = ibqp->qp_num;
- *tail = (*tail == hr_dev->caps.num_qps - 1) ? 0 : (*tail + 1);
+ xa_lock(dip_xa);
- list_for_each_entry(hr_dip, &hr_dev->dip_list, node) {
- if (!memcmp(grh->dgid.raw, hr_dip->dgid, GID_LEN_V2)) {
+ xa_for_each(dip_xa, idx, hr_dip) {
+ if (hr_dip->qp_cnt &&
+ !memcmp(grh->dgid.raw, hr_dip->dgid, GID_LEN_V2)) {
*dip_idx = hr_dip->dip_idx;
+ hr_dip->qp_cnt++;
+ hr_qp->dip = hr_dip;
goto out;
}
}
@@ -4728,19 +4743,24 @@ static int get_dip_ctx_idx(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
/* If no dgid is found, a new dip and a mapping between dgid and
* dip_idx will be created.
*/
- hr_dip = kzalloc(sizeof(*hr_dip), GFP_ATOMIC);
- if (!hr_dip) {
- ret = -ENOMEM;
- goto out;
+ xa_for_each(dip_xa, idx, hr_dip) {
+ if (hr_dip->qp_cnt)
+ continue;
+
+ *dip_idx = idx;
+ memcpy(hr_dip->dgid, grh->dgid.raw, sizeof(grh->dgid.raw));
+ hr_dip->dip_idx = idx;
+ hr_dip->qp_cnt++;
+ hr_qp->dip = hr_dip;
+ break;
}
- memcpy(hr_dip->dgid, grh->dgid.raw, sizeof(grh->dgid.raw));
- hr_dip->dip_idx = *dip_idx = spare_idx[*head];
- *head = (*head == hr_dev->caps.num_qps - 1) ? 0 : (*head + 1);
- list_add_tail(&hr_dip->node, &hr_dev->dip_list);
+ /* This should never happen. */
+ if (WARN_ON_ONCE(!hr_qp->dip))
+ ret = -ENOSPC;
out:
- spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags);
+ xa_unlock(dip_xa);
return ret;
}
@@ -5061,10 +5081,8 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp,
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
int ret = 0;
- if (!check_qp_state(cur_state, new_state)) {
- ibdev_err(&hr_dev->ib_dev, "Illegal state for QP!\n");
+ if (!check_qp_state(cur_state, new_state))
return -EINVAL;
- }
if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
memset(qpc_mask, 0, hr_dev->caps.qpc_sz);
@@ -5325,7 +5343,7 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
/* SW pass context to HW */
ret = hns_roce_v2_qp_modify(hr_dev, context, qpc_mask, hr_qp);
if (ret) {
- ibdev_err(ibdev, "failed to modify QP, ret = %d.\n", ret);
+ ibdev_err_ratelimited(ibdev, "failed to modify QP, ret = %d.\n", ret);
goto out;
}
@@ -5463,7 +5481,9 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
ret = hns_roce_v2_query_qpc(hr_dev, hr_qp->qpn, &context);
if (ret) {
- ibdev_err(ibdev, "failed to query QPC, ret = %d.\n", ret);
+ ibdev_err_ratelimited(ibdev,
+ "failed to query QPC, ret = %d.\n",
+ ret);
ret = -EINVAL;
goto out;
}
@@ -5471,7 +5491,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
state = hr_reg_read(&context, QPC_QP_ST);
tmp_qp_state = to_ib_qp_st((enum hns_roce_v2_qp_state)state);
if (tmp_qp_state == -1) {
- ibdev_err(ibdev, "Illegal ib_qp_state\n");
+ ibdev_err_ratelimited(ibdev, "Illegal ib_qp_state\n");
ret = -EINVAL;
goto out;
}
@@ -5564,9 +5584,9 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
ret = hns_roce_v2_modify_qp(&hr_qp->ibqp, NULL, 0,
hr_qp->state, IB_QPS_RESET, udata);
if (ret)
- ibdev_err(ibdev,
- "failed to modify QP to RST, ret = %d.\n",
- ret);
+ ibdev_err_ratelimited(ibdev,
+ "failed to modify QP to RST, ret = %d.\n",
+ ret);
}
send_cq = hr_qp->ibqp.send_cq ? to_hr_cq(hr_qp->ibqp.send_cq) : NULL;
@@ -5594,17 +5614,41 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
return ret;
}
+static void put_dip_ctx_idx(struct hns_roce_dev *hr_dev,
+ struct hns_roce_qp *hr_qp)
+{
+ struct hns_roce_dip *hr_dip = hr_qp->dip;
+
+ xa_lock(&hr_dev->qp_table.dip_xa);
+
+ hr_dip->qp_cnt--;
+ if (!hr_dip->qp_cnt)
+ memset(hr_dip->dgid, 0, GID_LEN_V2);
+
+ xa_unlock(&hr_dev->qp_table.dip_xa);
+}
+
int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
{
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+ unsigned long flags;
int ret;
+ /* Make sure flush_cqe() is completed */
+ spin_lock_irqsave(&hr_qp->flush_lock, flags);
+ set_bit(HNS_ROCE_STOP_FLUSH_FLAG, &hr_qp->flush_flag);
+ spin_unlock_irqrestore(&hr_qp->flush_lock, flags);
+ flush_work(&hr_qp->flush_work.work);
+
+ if (hr_qp->cong_type == CONG_TYPE_DIP)
+ put_dip_ctx_idx(hr_dev, hr_qp);
+
ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata);
if (ret)
- ibdev_err(&hr_dev->ib_dev,
- "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n",
- hr_qp->qpn, ret);
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
+ "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n",
+ hr_qp->qpn, ret);
hns_roce_qp_destroy(hr_dev, hr_qp, udata);
@@ -5898,9 +5942,9 @@ static int hns_roce_v2_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
HNS_ROCE_CMD_MODIFY_CQC, hr_cq->cqn);
hns_roce_free_cmd_mailbox(hr_dev, mailbox);
if (ret)
- ibdev_err(&hr_dev->ib_dev,
- "failed to process cmd when modifying CQ, ret = %d.\n",
- ret);
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
+ "failed to process cmd when modifying CQ, ret = %d.\n",
+ ret);
err_out:
if (ret)
@@ -5924,9 +5968,9 @@ static int hns_roce_v2_query_cqc(struct hns_roce_dev *hr_dev, u32 cqn,
ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma,
HNS_ROCE_CMD_QUERY_CQC, cqn);
if (ret) {
- ibdev_err(&hr_dev->ib_dev,
- "failed to process cmd when querying CQ, ret = %d.\n",
- ret);
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
+ "failed to process cmd when querying CQ, ret = %d.\n",
+ ret);
goto err_mailbox;
}
@@ -5967,11 +6011,10 @@ err_mailbox:
return ret;
}
-static void hns_roce_irq_work_handle(struct work_struct *work)
+static void dump_aeqe_log(struct hns_roce_work *irq_work)
{
- struct hns_roce_work *irq_work =
- container_of(work, struct hns_roce_work, work);
- struct ib_device *ibdev = &irq_work->hr_dev->ib_dev;
+ struct hns_roce_dev *hr_dev = irq_work->hr_dev;
+ struct ib_device *ibdev = &hr_dev->ib_dev;
switch (irq_work->event_type) {
case HNS_ROCE_EVENT_TYPE_PATH_MIG:
@@ -6015,6 +6058,8 @@ static void hns_roce_irq_work_handle(struct work_struct *work)
case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW:
ibdev_warn(ibdev, "DB overflow.\n");
break;
+ case HNS_ROCE_EVENT_TYPE_MB:
+ break;
case HNS_ROCE_EVENT_TYPE_FLR:
ibdev_warn(ibdev, "function level reset.\n");
break;
@@ -6025,8 +6070,46 @@ static void hns_roce_irq_work_handle(struct work_struct *work)
ibdev_err(ibdev, "invalid xrceth error.\n");
break;
default:
+ ibdev_info(ibdev, "Undefined event %d.\n",
+ irq_work->event_type);
break;
}
+}
+
+static void hns_roce_irq_work_handle(struct work_struct *work)
+{
+ struct hns_roce_work *irq_work =
+ container_of(work, struct hns_roce_work, work);
+ struct hns_roce_dev *hr_dev = irq_work->hr_dev;
+ int event_type = irq_work->event_type;
+ u32 queue_num = irq_work->queue_num;
+
+ switch (event_type) {
+ case HNS_ROCE_EVENT_TYPE_PATH_MIG:
+ case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED:
+ case HNS_ROCE_EVENT_TYPE_COMM_EST:
+ case HNS_ROCE_EVENT_TYPE_SQ_DRAINED:
+ case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR:
+ case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH:
+ case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR:
+ case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR:
+ case HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION:
+ case HNS_ROCE_EVENT_TYPE_INVALID_XRCETH:
+ hns_roce_qp_event(hr_dev, queue_num, event_type);
+ break;
+ case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH:
+ case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR:
+ hns_roce_srq_event(hr_dev, queue_num, event_type);
+ break;
+ case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR:
+ case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW:
+ hns_roce_cq_event(hr_dev, queue_num, event_type);
+ break;
+ default:
+ break;
+ }
+
+ dump_aeqe_log(irq_work);
kfree(irq_work);
}
@@ -6087,14 +6170,14 @@ static struct hns_roce_aeqe *next_aeqe_sw_v2(struct hns_roce_eq *eq)
static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
struct hns_roce_eq *eq)
{
- struct device *dev = hr_dev->dev;
struct hns_roce_aeqe *aeqe = next_aeqe_sw_v2(eq);
irqreturn_t aeqe_found = IRQ_NONE;
+ int num_aeqes = 0;
int event_type;
u32 queue_num;
int sub_type;
- while (aeqe) {
+ while (aeqe && num_aeqes < HNS_AEQ_POLLING_BUDGET) {
/* Make sure we read AEQ entry after we have checked the
* ownership bit
*/
@@ -6105,25 +6188,12 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
queue_num = hr_reg_read(aeqe, AEQE_EVENT_QUEUE_NUM);
switch (event_type) {
- case HNS_ROCE_EVENT_TYPE_PATH_MIG:
- case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED:
- case HNS_ROCE_EVENT_TYPE_COMM_EST:
- case HNS_ROCE_EVENT_TYPE_SQ_DRAINED:
case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR:
- case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH:
case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR:
case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR:
case HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION:
case HNS_ROCE_EVENT_TYPE_INVALID_XRCETH:
- hns_roce_qp_event(hr_dev, queue_num, event_type);
- break;
- case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH:
- case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR:
- hns_roce_srq_event(hr_dev, queue_num, event_type);
- break;
- case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR:
- case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW:
- hns_roce_cq_event(hr_dev, queue_num, event_type);
+ hns_roce_flush_cqe(hr_dev, queue_num);
break;
case HNS_ROCE_EVENT_TYPE_MB:
hns_roce_cmd_event(hr_dev,
@@ -6131,12 +6201,7 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
aeqe->event.cmd.status,
le64_to_cpu(aeqe->event.cmd.out_param));
break;
- case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW:
- case HNS_ROCE_EVENT_TYPE_FLR:
- break;
default:
- dev_err(dev, "unhandled event %d on EQ %d at idx %u.\n",
- event_type, eq->eqn, eq->cons_index);
break;
}
@@ -6150,6 +6215,7 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
hns_roce_v2_init_irq_work(hr_dev, eq, queue_num);
aeqe = next_aeqe_sw_v2(eq);
+ ++num_aeqes;
}
update_eq_db(eq);
@@ -6699,6 +6765,9 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_dev *hr_dev)
int ret;
int i;
+ if (hr_dev->caps.aeqe_depth < HNS_AEQ_POLLING_BUDGET)
+ return -EINVAL;
+
other_num = hr_dev->caps.num_other_vectors;
comp_num = hr_dev->caps.num_comp_vectors;
aeq_num = hr_dev->caps.num_aeq_vectors;
@@ -7017,6 +7086,7 @@ static void hns_roce_hw_v2_uninit_instance(struct hnae3_handle *handle,
handle->rinfo.instance_state = HNS_ROCE_STATE_NON_INIT;
}
+
static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle)
{
struct hns_roce_dev *hr_dev;
@@ -7035,6 +7105,9 @@ static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle)
hr_dev->active = false;
hr_dev->dis_db = true;
+
+ rdma_user_mmap_disassociate(&hr_dev->ib_dev);
+
hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN;
return 0;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
index c65f68a14a26..cbdbc9edbce6 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
@@ -85,6 +85,11 @@
#define HNS_ROCE_V2_TABLE_CHUNK_SIZE (1 << 18)
+/* budget must be smaller than aeqe_depth to guarantee that we update
+ * the ci before we polled all the entries in the EQ.
+ */
+#define HNS_AEQ_POLLING_BUDGET 64
+
enum {
HNS_ROCE_CMD_FLAG_IN = BIT(0),
HNS_ROCE_CMD_FLAG_OUT = BIT(1),
@@ -919,6 +924,7 @@ struct hns_roce_v2_rc_send_wqe {
#define RC_SEND_WQE_OWNER RC_SEND_WQE_FIELD_LOC(7, 7)
#define RC_SEND_WQE_CQE RC_SEND_WQE_FIELD_LOC(8, 8)
#define RC_SEND_WQE_FENCE RC_SEND_WQE_FIELD_LOC(9, 9)
+#define RC_SEND_WQE_SO RC_SEND_WQE_FIELD_LOC(10, 10)
#define RC_SEND_WQE_SE RC_SEND_WQE_FIELD_LOC(11, 11)
#define RC_SEND_WQE_INLINE RC_SEND_WQE_FIELD_LOC(12, 12)
#define RC_SEND_WQE_WQE_INDEX RC_SEND_WQE_FIELD_LOC(30, 15)
@@ -1342,7 +1348,7 @@ struct hns_roce_v2_priv {
struct hns_roce_dip {
u8 dgid[GID_LEN_V2];
u32 dip_idx;
- struct list_head node; /* all dips are on a list */
+ u32 qp_cnt;
};
struct fmea_ram_ecc {
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
index 4cb0af733587..ae24c81c9812 100644
--- a/drivers/infiniband/hw/hns/hns_roce_main.c
+++ b/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -466,6 +466,11 @@ static int hns_roce_mmap(struct ib_ucontext *uctx, struct vm_area_struct *vma)
pgprot_t prot;
int ret;
+ if (hr_dev->dis_db) {
+ atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MMAP_ERR_CNT]);
+ return -EPERM;
+ }
+
rdma_entry = rdma_user_mmap_entry_get_pgoff(uctx, vma->vm_pgoff);
if (!rdma_entry) {
atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MMAP_ERR_CNT]);
@@ -1130,8 +1135,6 @@ int hns_roce_init(struct hns_roce_dev *hr_dev)
INIT_LIST_HEAD(&hr_dev->qp_list);
spin_lock_init(&hr_dev->qp_list_lock);
- INIT_LIST_HEAD(&hr_dev->dip_list);
- spin_lock_init(&hr_dev->dip_list_lock);
ret = hns_roce_register_device(hr_dev);
if (ret)
diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
index 846da8c78b8b..bf30b3a65a9b 100644
--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
+++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
@@ -138,8 +138,8 @@ static void hns_roce_mr_free(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr
key_to_hw_index(mr->key) &
(hr_dev->caps.num_mtpts - 1));
if (ret)
- ibdev_warn(ibdev, "failed to destroy mpt, ret = %d.\n",
- ret);
+ ibdev_warn_ratelimited(ibdev, "failed to destroy mpt, ret = %d.\n",
+ ret);
}
free_mr_pbl(hr_dev, mr);
@@ -435,15 +435,16 @@ static int hns_roce_set_page(struct ib_mr *ibmr, u64 addr)
}
int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
- unsigned int *sg_offset)
+ unsigned int *sg_offset_p)
{
+ unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device);
struct ib_device *ibdev = &hr_dev->ib_dev;
struct hns_roce_mr *mr = to_hr_mr(ibmr);
struct hns_roce_mtr *mtr = &mr->pbl_mtr;
int ret, sg_num = 0;
- if (!IS_ALIGNED(*sg_offset, HNS_ROCE_FRMR_ALIGN_SIZE) ||
+ if (!IS_ALIGNED(sg_offset, HNS_ROCE_FRMR_ALIGN_SIZE) ||
ibmr->page_size < HNS_HW_PAGE_SIZE ||
ibmr->page_size > HNS_HW_MAX_PAGE_SIZE)
return sg_num;
@@ -454,7 +455,7 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
if (!mr->page_list)
return sg_num;
- sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page);
+ sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset_p, hns_roce_set_page);
if (sg_num < 1) {
ibdev_err(ibdev, "failed to store sg pages %u %u, cnt = %d.\n",
mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, sg_num);
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
index 6b03ba671ff8..9e2e76c59406 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -39,6 +39,25 @@
#include "hns_roce_device.h"
#include "hns_roce_hem.h"
+static struct hns_roce_qp *hns_roce_qp_lookup(struct hns_roce_dev *hr_dev,
+ u32 qpn)
+{
+ struct device *dev = hr_dev->dev;
+ struct hns_roce_qp *qp;
+ unsigned long flags;
+
+ xa_lock_irqsave(&hr_dev->qp_table_xa, flags);
+ qp = __hns_roce_qp_lookup(hr_dev, qpn);
+ if (qp)
+ refcount_inc(&qp->refcount);
+ xa_unlock_irqrestore(&hr_dev->qp_table_xa, flags);
+
+ if (!qp)
+ dev_warn(dev, "async event for bogus QP %08x\n", qpn);
+
+ return qp;
+}
+
static void flush_work_handle(struct work_struct *work)
{
struct hns_roce_work *flush_work = container_of(work,
@@ -71,11 +90,18 @@ static void flush_work_handle(struct work_struct *work)
void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
{
struct hns_roce_work *flush_work = &hr_qp->flush_work;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hr_qp->flush_lock, flags);
+ /* Exit directly after destroy_qp() */
+ if (test_bit(HNS_ROCE_STOP_FLUSH_FLAG, &hr_qp->flush_flag)) {
+ spin_unlock_irqrestore(&hr_qp->flush_lock, flags);
+ return;
+ }
- flush_work->hr_dev = hr_dev;
- INIT_WORK(&flush_work->work, flush_work_handle);
refcount_inc(&hr_qp->refcount);
queue_work(hr_dev->irq_workq, &flush_work->work);
+ spin_unlock_irqrestore(&hr_qp->flush_lock, flags);
}
void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp)
@@ -95,31 +121,28 @@ void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp)
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
{
- struct device *dev = hr_dev->dev;
struct hns_roce_qp *qp;
- xa_lock(&hr_dev->qp_table_xa);
- qp = __hns_roce_qp_lookup(hr_dev, qpn);
- if (qp)
- refcount_inc(&qp->refcount);
- xa_unlock(&hr_dev->qp_table_xa);
-
- if (!qp) {
- dev_warn(dev, "async event for bogus QP %08x\n", qpn);
+ qp = hns_roce_qp_lookup(hr_dev, qpn);
+ if (!qp)
return;
- }
- if (event_type == HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR ||
- event_type == HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR ||
- event_type == HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR ||
- event_type == HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION ||
- event_type == HNS_ROCE_EVENT_TYPE_INVALID_XRCETH) {
- qp->state = IB_QPS_ERR;
+ qp->event(qp, (enum hns_roce_event)event_type);
- flush_cqe(hr_dev, qp);
- }
+ if (refcount_dec_and_test(&qp->refcount))
+ complete(&qp->free);
+}
- qp->event(qp, (enum hns_roce_event)event_type);
+void hns_roce_flush_cqe(struct hns_roce_dev *hr_dev, u32 qpn)
+{
+ struct hns_roce_qp *qp;
+
+ qp = hns_roce_qp_lookup(hr_dev, qpn);
+ if (!qp)
+ return;
+
+ qp->state = IB_QPS_ERR;
+ flush_cqe(hr_dev, qp);
if (refcount_dec_and_test(&qp->refcount))
complete(&qp->free);
@@ -1124,6 +1147,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
struct ib_udata *udata,
struct hns_roce_qp *hr_qp)
{
+ struct hns_roce_work *flush_work = &hr_qp->flush_work;
struct hns_roce_ib_create_qp_resp resp = {};
struct ib_device *ibdev = &hr_dev->ib_dev;
struct hns_roce_ib_create_qp ucmd = {};
@@ -1132,9 +1156,12 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
mutex_init(&hr_qp->mutex);
spin_lock_init(&hr_qp->sq.lock);
spin_lock_init(&hr_qp->rq.lock);
+ spin_lock_init(&hr_qp->flush_lock);
hr_qp->state = IB_QPS_RESET;
hr_qp->flush_flag = 0;
+ flush_work->hr_dev = hr_dev;
+ INIT_WORK(&flush_work->work, flush_work_handle);
if (init_attr->create_flags)
return -EOPNOTSUPP;
@@ -1546,14 +1573,10 @@ int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
unsigned int reserved_from_bot;
unsigned int i;
- qp_table->idx_table.spare_idx = kcalloc(hr_dev->caps.num_qps,
- sizeof(u32), GFP_KERNEL);
- if (!qp_table->idx_table.spare_idx)
- return -ENOMEM;
-
mutex_init(&qp_table->scc_mutex);
mutex_init(&qp_table->bank_mutex);
xa_init(&hr_dev->qp_table_xa);
+ xa_init(&qp_table->dip_xa);
reserved_from_bot = hr_dev->caps.reserved_qps;
@@ -1578,7 +1601,7 @@ void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev)
for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++)
ida_destroy(&hr_dev->qp_table.bank[i].ida);
+ xa_destroy(&hr_dev->qp_table.dip_xa);
mutex_destroy(&hr_dev->qp_table.bank_mutex);
mutex_destroy(&hr_dev->qp_table.scc_mutex);
- kfree(hr_dev->qp_table.idx_table.spare_idx);
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c
index c9b8233f4b05..70c06ef65603 100644
--- a/drivers/infiniband/hw/hns/hns_roce_srq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_srq.c
@@ -151,8 +151,8 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_SRQ,
srq->srqn);
if (ret)
- dev_err(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n",
- ret, srq->srqn);
+ dev_err_ratelimited(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n",
+ ret, srq->srqn);
xa_erase_irq(&srq_table->xa, srq->srqn);
diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index 69999d8d24f3..4186884c66e1 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -27,6 +27,19 @@ enum devx_obj_flags {
DEVX_OBJ_FLAGS_INDIRECT_MKEY = 1 << 0,
DEVX_OBJ_FLAGS_DCT = 1 << 1,
DEVX_OBJ_FLAGS_CQ = 1 << 2,
+ DEVX_OBJ_FLAGS_HW_FREED = 1 << 3,
+};
+
+#define MAX_ASYNC_CMDS 8
+
+struct mlx5_async_cmd {
+ struct ib_uobject *uobject;
+ void *in;
+ int in_size;
+ u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
+ int err;
+ struct mlx5_async_work cb_work;
+ struct completion comp;
};
struct devx_async_data {
@@ -1405,7 +1418,9 @@ static int devx_obj_cleanup(struct ib_uobject *uobject,
*/
mlx5r_deref_wait_odp_mkey(&obj->mkey);
- if (obj->flags & DEVX_OBJ_FLAGS_DCT)
+ if (obj->flags & DEVX_OBJ_FLAGS_HW_FREED)
+ ret = 0;
+ else if (obj->flags & DEVX_OBJ_FLAGS_DCT)
ret = mlx5_core_destroy_dct(obj->ib_dev, &obj->core_dct);
else if (obj->flags & DEVX_OBJ_FLAGS_CQ)
ret = mlx5_core_destroy_cq(obj->ib_dev->mdev, &obj->core_cq);
@@ -2595,6 +2610,82 @@ void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev)
}
}
+static void devx_async_destroy_cb(int status, struct mlx5_async_work *context)
+{
+ struct mlx5_async_cmd *devx_out = container_of(context,
+ struct mlx5_async_cmd, cb_work);
+ struct devx_obj *obj = devx_out->uobject->object;
+
+ if (!status)
+ obj->flags |= DEVX_OBJ_FLAGS_HW_FREED;
+
+ complete(&devx_out->comp);
+}
+
+static void devx_async_destroy(struct mlx5_ib_dev *dev,
+ struct mlx5_async_cmd *cmd)
+{
+ init_completion(&cmd->comp);
+ cmd->err = mlx5_cmd_exec_cb(&dev->async_ctx, cmd->in, cmd->in_size,
+ &cmd->out, sizeof(cmd->out),
+ devx_async_destroy_cb, &cmd->cb_work);
+}
+
+static void devx_wait_async_destroy(struct mlx5_async_cmd *cmd)
+{
+ if (!cmd->err)
+ wait_for_completion(&cmd->comp);
+ atomic_set(&cmd->uobject->usecnt, 0);
+}
+
+void mlx5_ib_ufile_hw_cleanup(struct ib_uverbs_file *ufile)
+{
+ struct mlx5_async_cmd async_cmd[MAX_ASYNC_CMDS];
+ struct ib_ucontext *ucontext = ufile->ucontext;
+ struct ib_device *device = ucontext->device;
+ struct mlx5_ib_dev *dev = to_mdev(device);
+ struct ib_uobject *uobject;
+ struct devx_obj *obj;
+ int head = 0;
+ int tail = 0;
+
+ list_for_each_entry(uobject, &ufile->uobjects, list) {
+ WARN_ON(uverbs_try_lock_object(uobject, UVERBS_LOOKUP_WRITE));
+
+ /*
+ * Currently we only support QP destruction, if other objects
+ * are to be destroyed need to add type synchronization to the
+ * cleanup algorithm and handle pre/post FW cleanup for the
+ * new types if needed.
+ */
+ if (uobj_get_object_id(uobject) != MLX5_IB_OBJECT_DEVX_OBJ ||
+ (get_dec_obj_type(uobject->object, MLX5_EVENT_TYPE_MAX) !=
+ MLX5_OBJ_TYPE_QP)) {
+ atomic_set(&uobject->usecnt, 0);
+ continue;
+ }
+
+ obj = uobject->object;
+
+ async_cmd[tail % MAX_ASYNC_CMDS].in = obj->dinbox;
+ async_cmd[tail % MAX_ASYNC_CMDS].in_size = obj->dinlen;
+ async_cmd[tail % MAX_ASYNC_CMDS].uobject = uobject;
+
+ devx_async_destroy(dev, &async_cmd[tail % MAX_ASYNC_CMDS]);
+ tail++;
+
+ if (tail - head == MAX_ASYNC_CMDS) {
+ devx_wait_async_destroy(&async_cmd[head % MAX_ASYNC_CMDS]);
+ head++;
+ }
+ }
+
+ while (head != tail) {
+ devx_wait_async_destroy(&async_cmd[head % MAX_ASYNC_CMDS]);
+ head++;
+ }
+}
+
static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos)
{
diff --git a/drivers/infiniband/hw/mlx5/devx.h b/drivers/infiniband/hw/mlx5/devx.h
index ee2213275fd6..1344bf4c9d21 100644
--- a/drivers/infiniband/hw/mlx5/devx.h
+++ b/drivers/infiniband/hw/mlx5/devx.h
@@ -28,6 +28,7 @@ int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user);
void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid);
int mlx5_ib_devx_init(struct mlx5_ib_dev *dev);
void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev);
+void mlx5_ib_ufile_hw_cleanup(struct ib_uverbs_file *ufile);
#else
static inline int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user)
{
@@ -41,5 +42,8 @@ static inline int mlx5_ib_devx_init(struct mlx5_ib_dev *dev)
static inline void mlx5_ib_devx_cleanup(struct mlx5_ib_dev *dev)
{
}
+static inline void mlx5_ib_ufile_hw_cleanup(struct ib_uverbs_file *ufile)
+{
+}
#endif
#endif /* _MLX5_IB_DEVX_H */
diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c
index 1b6c5e37d169..2453ae4384a7 100644
--- a/drivers/infiniband/hw/mlx5/mad.c
+++ b/drivers/infiniband/hw/mlx5/mad.c
@@ -278,7 +278,13 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
goto done;
}
- err = query_ib_ppcnt(mdev, mdev_port_num, 0, out_cnt, sz, 0);
+ if (dev->ib_dev.type == RDMA_DEVICE_TYPE_SMI)
+ err = query_ib_ppcnt(mdev, mdev_port_num, port_num,
+ out_cnt, sz, 0);
+ else
+ err = query_ib_ppcnt(mdev, mdev_port_num, 0,
+ out_cnt, sz, 0);
+
if (!err)
pma_cnt_assign(pma_cnt, out_cnt);
}
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 4999239c8f41..bc7930d0c564 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1182,6 +1182,14 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE;
resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_SCAT2CQE_DCT;
+
+ if (MLX5_CAP_GEN_2(mdev, dp_ordering_force) &&
+ (MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_xrc) ||
+ MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_dc) ||
+ MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_rc) ||
+ MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_ud) ||
+ MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_uc)))
+ resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_OOO_DP;
}
if (offsetofend(typeof(resp), sw_parsing_caps) <= uhw_outlen) {
@@ -2997,7 +3005,6 @@ unlock:
static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
{
struct mlx5_ib_resources *devr = &dev->devr;
- int port;
int ret;
if (!MLX5_CAP_GEN(dev->mdev, xrc))
@@ -3013,10 +3020,6 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
return ret;
}
- for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
- INIT_WORK(&devr->ports[port].pkey_change_work,
- pkey_change_handler);
-
mutex_init(&devr->cq_lock);
mutex_init(&devr->srq_lock);
@@ -3026,16 +3029,6 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)
{
struct mlx5_ib_resources *devr = &dev->devr;
- int port;
-
- /*
- * Make sure no change P_Key work items are still executing.
- *
- * At this stage, the mlx5_ib_event should be unregistered
- * and it ensures that no new works are added.
- */
- for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
- cancel_work_sync(&devr->ports[port].pkey_change_work);
/* After s0/s1 init, they are not unset during the device lifetime. */
if (devr->s1) {
@@ -3211,12 +3204,14 @@ static int lag_event(struct notifier_block *nb, unsigned long event, void *data)
struct mlx5_ib_dev *dev = container_of(nb, struct mlx5_ib_dev,
lag_events);
struct mlx5_core_dev *mdev = dev->mdev;
+ struct ib_device *ibdev = &dev->ib_dev;
+ struct net_device *old_ndev = NULL;
struct mlx5_ib_port *port;
struct net_device *ndev;
- int i, err;
- int portnum;
+ u32 portnum = 0;
+ int ret = 0;
+ int i;
- portnum = 0;
switch (event) {
case MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE:
ndev = data;
@@ -3232,19 +3227,24 @@ static int lag_event(struct notifier_block *nb, unsigned long event, void *data)
}
}
}
- err = ib_device_set_netdev(&dev->ib_dev, ndev,
- portnum + 1);
- dev_put(ndev);
- if (err)
- return err;
- /* Rescan gids after new netdev assignment */
- rdma_roce_rescan_device(&dev->ib_dev);
+ old_ndev = ib_device_get_netdev(ibdev, portnum + 1);
+ ret = ib_device_set_netdev(ibdev, ndev, portnum + 1);
+ if (ret)
+ goto out;
+
+ if (old_ndev)
+ roce_del_all_netdev_gids(ibdev, portnum + 1,
+ old_ndev);
+ rdma_roce_rescan_port(ibdev, portnum + 1);
}
break;
default:
return NOTIFY_DONE;
}
- return NOTIFY_OK;
+
+out:
+ dev_put(old_ndev);
+ return notifier_from_errno(ret);
}
static void mlx5e_lag_event_register(struct mlx5_ib_dev *dev)
@@ -4134,6 +4134,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
.req_notify_cq = mlx5_ib_arm_cq,
.rereg_user_mr = mlx5_ib_rereg_user_mr,
.resize_cq = mlx5_ib_resize_cq,
+ .ufile_hw_cleanup = mlx5_ib_ufile_hw_cleanup,
INIT_RDMA_OBJ_SIZE(ib_ah, mlx5_ib_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs),
@@ -4464,6 +4465,13 @@ static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev)
static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev)
{
+ struct mlx5_ib_resources *devr = &dev->devr;
+ int port;
+
+ for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
+ INIT_WORK(&devr->ports[port].pkey_change_work,
+ pkey_change_handler);
+
dev->mdev_events.notifier_call = mlx5_ib_event;
mlx5_notifier_register(dev->mdev, &dev->mdev_events);
@@ -4474,8 +4482,14 @@ static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev)
static void mlx5_ib_stage_dev_notifier_cleanup(struct mlx5_ib_dev *dev)
{
+ struct mlx5_ib_resources *devr = &dev->devr;
+ int port;
+
mlx5r_macsec_event_unregister(dev);
mlx5_notifier_unregister(dev->mdev, &dev->mdev_events);
+
+ for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
+ cancel_work_sync(&devr->ports[port].pkey_change_work);
}
void mlx5_ib_data_direct_bind(struct mlx5_ib_dev *ibdev,
@@ -4565,9 +4579,6 @@ static const struct mlx5_ib_profile pf_profile = {
STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
mlx5_ib_dev_res_init,
mlx5_ib_dev_res_cleanup),
- STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
- mlx5_ib_stage_dev_notifier_init,
- mlx5_ib_stage_dev_notifier_cleanup),
STAGE_CREATE(MLX5_IB_STAGE_ODP,
mlx5_ib_odp_init_one,
mlx5_ib_odp_cleanup_one),
@@ -4592,6 +4603,9 @@ static const struct mlx5_ib_profile pf_profile = {
STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
mlx5_ib_stage_ib_reg_init,
mlx5_ib_stage_ib_reg_cleanup),
+ STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
+ mlx5_ib_stage_dev_notifier_init,
+ mlx5_ib_stage_dev_notifier_cleanup),
STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
mlx5_ib_stage_post_ib_reg_umr_init,
NULL),
@@ -4628,9 +4642,6 @@ const struct mlx5_ib_profile raw_eth_profile = {
STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
mlx5_ib_dev_res_init,
mlx5_ib_dev_res_cleanup),
- STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
- mlx5_ib_stage_dev_notifier_init,
- mlx5_ib_stage_dev_notifier_cleanup),
STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
mlx5_ib_counters_init,
mlx5_ib_counters_cleanup),
@@ -4652,6 +4663,9 @@ const struct mlx5_ib_profile raw_eth_profile = {
STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
mlx5_ib_stage_ib_reg_init,
mlx5_ib_stage_ib_reg_cleanup),
+ STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
+ mlx5_ib_stage_dev_notifier_init,
+ mlx5_ib_stage_dev_notifier_cleanup),
STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
mlx5_ib_stage_post_ib_reg_umr_init,
NULL),
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 23fd72f7f63d..a01b592aa716 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -521,6 +521,7 @@ struct mlx5_ib_qp {
struct mlx5_bf bf;
u8 has_rq:1;
u8 is_rss:1;
+ u8 is_ooo_rq:1;
/* only for user space QPs. For kernel
* we have it from the bf object
@@ -972,7 +973,6 @@ enum mlx5_ib_stages {
MLX5_IB_STAGE_QP,
MLX5_IB_STAGE_SRQ,
MLX5_IB_STAGE_DEVICE_RESOURCES,
- MLX5_IB_STAGE_DEVICE_NOTIFIER,
MLX5_IB_STAGE_ODP,
MLX5_IB_STAGE_COUNTERS,
MLX5_IB_STAGE_CONG_DEBUGFS,
@@ -981,6 +981,7 @@ enum mlx5_ib_stages {
MLX5_IB_STAGE_PRE_IB_REG_UMR,
MLX5_IB_STAGE_WHITELIST_UID,
MLX5_IB_STAGE_IB_REG,
+ MLX5_IB_STAGE_DEVICE_NOTIFIER,
MLX5_IB_STAGE_POST_IB_REG_UMR,
MLX5_IB_STAGE_DELAY_DROP,
MLX5_IB_STAGE_RESTRACK,
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 10ce3b44f645..a43eba9d3572 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -1960,7 +1960,7 @@ static int atomic_size_to_mode(int size_mask)
}
static int get_atomic_mode(struct mlx5_ib_dev *dev,
- enum ib_qp_type qp_type)
+ struct mlx5_ib_qp *qp)
{
u8 atomic_operations = MLX5_CAP_ATOMIC(dev->mdev, atomic_operations);
u8 atomic = MLX5_CAP_GEN(dev->mdev, atomic);
@@ -1970,7 +1970,7 @@ static int get_atomic_mode(struct mlx5_ib_dev *dev,
if (!atomic)
return -EOPNOTSUPP;
- if (qp_type == MLX5_IB_QPT_DCT)
+ if (qp->type == MLX5_IB_QPT_DCT)
atomic_size_mask = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_dc);
else
atomic_size_mask = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_qp);
@@ -1984,6 +1984,10 @@ static int get_atomic_mode(struct mlx5_ib_dev *dev,
atomic_operations & MLX5_ATOMIC_OPS_FETCH_ADD))
atomic_mode = MLX5_ATOMIC_MODE_IB_COMP;
+ /* OOO DP QPs do not support larger than 8-Bytes atomic operations */
+ if (atomic_mode > MLX5_ATOMIC_MODE_8B && qp->is_ooo_rq)
+ atomic_mode = MLX5_ATOMIC_MODE_8B;
+
return atomic_mode;
}
@@ -2839,6 +2843,29 @@ static int check_valid_flow(struct mlx5_ib_dev *dev, struct ib_pd *pd,
return 0;
}
+static bool get_dp_ooo_cap(struct mlx5_core_dev *mdev, enum ib_qp_type qp_type)
+{
+ if (!MLX5_CAP_GEN_2(mdev, dp_ordering_force))
+ return false;
+
+ switch (qp_type) {
+ case IB_QPT_RC:
+ return MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_rc);
+ case IB_QPT_XRC_INI:
+ case IB_QPT_XRC_TGT:
+ return MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_xrc);
+ case IB_QPT_UC:
+ return MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_uc);
+ case IB_QPT_UD:
+ return MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_ud);
+ case MLX5_IB_QPT_DCI:
+ case MLX5_IB_QPT_DCT:
+ return MLX5_CAP_GEN(mdev, dp_ordering_ooo_all_dc);
+ default:
+ return false;
+ }
+}
+
static void process_vendor_flag(struct mlx5_ib_dev *dev, int *flags, int flag,
bool cond, struct mlx5_ib_qp *qp)
{
@@ -3365,7 +3392,7 @@ static int set_qpc_atomic_flags(struct mlx5_ib_qp *qp,
if (access_flags & IB_ACCESS_REMOTE_ATOMIC) {
int atomic_mode;
- atomic_mode = get_atomic_mode(dev, qp->type);
+ atomic_mode = get_atomic_mode(dev, qp);
if (atomic_mode < 0)
return -EOPNOTSUPP;
@@ -4316,6 +4343,11 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
if (qp->flags & MLX5_IB_QP_CREATE_SQPN_QP1)
MLX5_SET(qpc, qpc, deth_sqpn, 1);
+ if (qp->is_ooo_rq && cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
+ MLX5_SET(qpc, qpc, dp_ordering_1, 1);
+ MLX5_SET(qpc, qpc, dp_ordering_force, 1);
+ }
+
mlx5_cur = to_mlx5_state(cur_state);
mlx5_new = to_mlx5_state(new_state);
@@ -4531,7 +4563,7 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC) {
int atomic_mode;
- atomic_mode = get_atomic_mode(dev, MLX5_IB_QPT_DCT);
+ atomic_mode = get_atomic_mode(dev, qp);
if (atomic_mode < 0)
return -EOPNOTSUPP;
@@ -4573,6 +4605,10 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
MLX5_SET(dctc, dctc, hop_limit, attr->ah_attr.grh.hop_limit);
if (attr->ah_attr.type == RDMA_AH_ATTR_TYPE_ROCE)
MLX5_SET(dctc, dctc, eth_prio, attr->ah_attr.sl & 0x7);
+ if (qp->is_ooo_rq) {
+ MLX5_SET(dctc, dctc, dp_ordering_1, 1);
+ MLX5_SET(dctc, dctc, dp_ordering_force, 1);
+ }
err = mlx5_core_create_dct(dev, &qp->dct.mdct, qp->dct.in,
MLX5_ST_SZ_BYTES(create_dct_in), out,
@@ -4676,11 +4712,16 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
min(udata->inlen, sizeof(ucmd))))
return -EFAULT;
- if (ucmd.comp_mask ||
+ if (ucmd.comp_mask & ~MLX5_IB_MODIFY_QP_OOO_DP ||
memchr_inv(&ucmd.burst_info.reserved, 0,
sizeof(ucmd.burst_info.reserved)))
return -EOPNOTSUPP;
+ if (ucmd.comp_mask & MLX5_IB_MODIFY_QP_OOO_DP) {
+ if (!get_dp_ooo_cap(dev->mdev, qp->type))
+ return -EOPNOTSUPP;
+ qp->is_ooo_rq = 1;
+ }
}
if (qp->type == IB_QPT_GSI)
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index 53ec7510e4eb..ba2cd68b53e6 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -283,7 +283,7 @@ static struct bin_attribute *port_ccmgta_attributes[] = {
};
static umode_t qib_ccmgta_is_bin_visible(struct kobject *kobj,
- struct bin_attribute *attr, int n)
+ const struct bin_attribute *attr, int n)
{
struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj);
diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c
index d2f7b5195c19..91d329e90308 100644
--- a/drivers/infiniband/sw/rxe/rxe_qp.c
+++ b/drivers/infiniband/sw/rxe/rxe_qp.c
@@ -775,6 +775,7 @@ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
* Yield the processor
*/
spin_lock_irqsave(&qp->state_lock, flags);
+ attr->cur_qp_state = qp_state(qp);
if (qp->attr.sq_draining) {
spin_unlock_irqrestore(&qp->state_lock, flags);
cond_resched();
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
index 479c07e6e4ed..87a02f0deb00 100644
--- a/drivers/infiniband/sw/rxe/rxe_req.c
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@ -663,10 +663,12 @@ int rxe_requester(struct rxe_qp *qp)
if (unlikely(qp_state(qp) == IB_QPS_ERR)) {
wqe = __req_next_wqe(qp);
spin_unlock_irqrestore(&qp->state_lock, flags);
- if (wqe)
+ if (wqe) {
+ wqe->status = IB_WC_WR_FLUSH_ERR;
goto err;
- else
+ } else {
goto exit;
+ }
}
if (unlikely(qp_state(qp) == IB_QPS_RESET)) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index 7da94fb8d7fa..4feb7170535c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -128,16 +128,13 @@ static void ipoib_get_ethtool_stats(struct net_device *dev,
static void ipoib_get_strings(struct net_device __always_unused *dev,
u32 stringset, u8 *data)
{
- u8 *p = data;
int i;
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0; i < IPOIB_GLOBAL_STATS_LEN; i++) {
- memcpy(p, ipoib_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < IPOIB_GLOBAL_STATS_LEN; i++)
+ ethtool_puts(&data,
+ ipoib_gstrings_stats[i].stat_string);
break;
default:
break;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 4e31bb0b6466..3b463db8ce39 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -49,6 +49,7 @@
#include <linux/jhash.h>
#include <net/arp.h>
#include <net/addrconf.h>
+#include <net/pkt_sched.h>
#include <linux/inetdevice.h>
#include <rdma/ib_cache.h>
@@ -2145,7 +2146,7 @@ void ipoib_setup_common(struct net_device *dev)
dev->hard_header_len = IPOIB_HARD_LEN;
dev->addr_len = INFINIBAND_ALEN;
dev->type = ARPHRD_INFINIBAND;
- dev->tx_queue_len = ipoib_sendq_size * 2;
+ dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
dev->features = (NETIF_F_VLAN_CHALLENGED |
NETIF_F_HIGHDMA);
netif_keep_dst(dev);
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c
index 29b3d8fce3f5..316959940d2f 100644
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c
+++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c
@@ -164,9 +164,7 @@ static void vnic_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
return;
for (i = 0; i < VNIC_STATS_LEN; i++)
- memcpy(data + i * ETH_GSTRING_LEN,
- vnic_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ ethtool_puts(&data, vnic_gstrings_stats[i].stat_string);
}
/* ethtool ops */
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c51858f1cdc5..7f0477e04ad2 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -605,6 +605,9 @@ int input_open_device(struct input_handle *handle)
handle->open++;
+ if (handle->handler->passive_observer)
+ goto out;
+
if (dev->users++ || dev->inhibited) {
/*
* Device is already opened and/or inhibited,
@@ -668,11 +671,13 @@ void input_close_device(struct input_handle *handle)
__input_release_device(handle);
- if (!--dev->users && !dev->inhibited) {
- if (dev->poller)
- input_dev_poller_stop(dev->poller);
- if (dev->close)
- dev->close(dev);
+ if (!handle->handler->passive_observer) {
+ if (!--dev->users && !dev->inhibited) {
+ if (dev->poller)
+ input_dev_poller_stop(dev->poller);
+ if (dev->close)
+ dev->close(dev);
+ }
}
if (!--handle->open) {
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 6373d7aa739a..a9f1946cf0d6 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -505,24 +505,22 @@ static int db9_open(struct input_dev *dev)
{
struct db9 *db9 = input_get_drvdata(dev);
struct parport *port = db9->pd->port;
- int err;
- err = mutex_lock_interruptible(&db9->mutex);
- if (err)
- return err;
-
- if (!db9->used++) {
- parport_claim(db9->pd);
- parport_write_data(port, 0xff);
- if (db9_modes[db9->mode].reverse) {
- parport_data_reverse(port);
- parport_write_control(port, DB9_NORMAL);
+ scoped_guard(mutex_intr, &db9->mutex) {
+ if (!db9->used++) {
+ parport_claim(db9->pd);
+ parport_write_data(port, 0xff);
+ if (db9_modes[db9->mode].reverse) {
+ parport_data_reverse(port);
+ parport_write_control(port, DB9_NORMAL);
+ }
+ mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
}
- mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
+
+ return 0;
}
- mutex_unlock(&db9->mutex);
- return 0;
+ return -EINTR;
}
static void db9_close(struct input_dev *dev)
@@ -530,14 +528,14 @@ static void db9_close(struct input_dev *dev)
struct db9 *db9 = input_get_drvdata(dev);
struct parport *port = db9->pd->port;
- mutex_lock(&db9->mutex);
+ guard(mutex)(&db9->mutex);
+
if (!--db9->used) {
del_timer_sync(&db9->timer);
parport_write_control(port, 0x00);
parport_data_forward(port);
parport_release(db9->pd);
}
- mutex_unlock(&db9->mutex);
}
static void db9_attach(struct parport *pp)
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 2b553e2d838f..b53cafd7a5ee 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -765,33 +765,31 @@ static void gc_timer(struct timer_list *t)
static int gc_open(struct input_dev *dev)
{
struct gc *gc = input_get_drvdata(dev);
- int err;
- err = mutex_lock_interruptible(&gc->mutex);
- if (err)
- return err;
+ scoped_guard(mutex_intr, &gc->mutex) {
+ if (!gc->used++) {
+ parport_claim(gc->pd);
+ parport_write_control(gc->pd->port, 0x04);
+ mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
+ }
- if (!gc->used++) {
- parport_claim(gc->pd);
- parport_write_control(gc->pd->port, 0x04);
- mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
+ return 0;
}
- mutex_unlock(&gc->mutex);
- return 0;
+ return -EINTR;
}
static void gc_close(struct input_dev *dev)
{
struct gc *gc = input_get_drvdata(dev);
- mutex_lock(&gc->mutex);
+ guard(mutex)(&gc->mutex);
+
if (!--gc->used) {
del_timer_sync(&gc->timer);
parport_write_control(gc->pd->port, 0x00);
parport_release(gc->pd);
}
- mutex_unlock(&gc->mutex);
}
static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 95c0348843e6..8c78cbe553c8 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -21,14 +21,13 @@ static int make_magnitude_modifier(struct iforce* iforce,
unsigned char data[3];
if (!no_alloc) {
- mutex_lock(&iforce->mem_mutex);
- if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- mutex_unlock(&iforce->mem_mutex);
+ guard(mutex)(&iforce->mem_mutex);
+
+ if (allocate_resource(&iforce->device_memory, mod_chunk, 2,
+ iforce->device_memory.start,
+ iforce->device_memory.end,
+ 2L, NULL, NULL))
return -ENOSPC;
- }
- mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -54,14 +53,13 @@ static int make_period_modifier(struct iforce* iforce,
period = TIME_SCALE(period);
if (!no_alloc) {
- mutex_lock(&iforce->mem_mutex);
- if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- mutex_unlock(&iforce->mem_mutex);
+ guard(mutex)(&iforce->mem_mutex);
+
+ if (allocate_resource(&iforce->device_memory, mod_chunk, 0x0c,
+ iforce->device_memory.start,
+ iforce->device_memory.end,
+ 2L, NULL, NULL))
return -ENOSPC;
- }
- mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -94,14 +92,13 @@ static int make_envelope_modifier(struct iforce* iforce,
fade_duration = TIME_SCALE(fade_duration);
if (!no_alloc) {
- mutex_lock(&iforce->mem_mutex);
+ guard(mutex)(&iforce->mem_mutex);
+
if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- mutex_unlock(&iforce->mem_mutex);
+ iforce->device_memory.start,
+ iforce->device_memory.end,
+ 2L, NULL, NULL))
return -ENOSPC;
- }
- mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -131,14 +128,13 @@ static int make_condition_modifier(struct iforce* iforce,
unsigned char data[10];
if (!no_alloc) {
- mutex_lock(&iforce->mem_mutex);
+ guard(mutex)(&iforce->mem_mutex);
+
if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
- iforce->device_memory.start, iforce->device_memory.end, 2L,
- NULL, NULL)) {
- mutex_unlock(&iforce->mem_mutex);
+ iforce->device_memory.start,
+ iforce->device_memory.end,
+ 2L, NULL, NULL))
return -ENOSPC;
- }
- mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 08c889a72f6c..74181d5123cd 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -31,49 +31,42 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
int c;
int empty;
int head, tail;
- unsigned long flags;
/*
* Update head and tail of xmit buffer
*/
- spin_lock_irqsave(&iforce->xmit_lock, flags);
-
- head = iforce->xmit.head;
- tail = iforce->xmit.tail;
-
-
- if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
- dev_warn(&iforce->dev->dev,
- "not enough space in xmit buffer to send new packet\n");
- spin_unlock_irqrestore(&iforce->xmit_lock, flags);
- return -1;
- }
+ scoped_guard(spinlock_irqsave, &iforce->xmit_lock) {
+ head = iforce->xmit.head;
+ tail = iforce->xmit.tail;
+
+ if (CIRC_SPACE(head, tail, XMIT_SIZE) < n + 2) {
+ dev_warn(&iforce->dev->dev,
+ "not enough space in xmit buffer to send new packet\n");
+ return -1;
+ }
- empty = head == tail;
- XMIT_INC(iforce->xmit.head, n+2);
+ empty = head == tail;
+ XMIT_INC(iforce->xmit.head, n + 2);
/*
* Store packet in xmit buffer
*/
- iforce->xmit.buf[head] = HI(cmd);
- XMIT_INC(head, 1);
- iforce->xmit.buf[head] = LO(cmd);
- XMIT_INC(head, 1);
-
- c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE);
- if (n < c) c=n;
-
- memcpy(&iforce->xmit.buf[head],
- data,
- c);
- if (n != c) {
- memcpy(&iforce->xmit.buf[0],
- data + c,
- n - c);
+ iforce->xmit.buf[head] = HI(cmd);
+ XMIT_INC(head, 1);
+ iforce->xmit.buf[head] = LO(cmd);
+ XMIT_INC(head, 1);
+
+ c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE);
+ if (n < c)
+ c = n;
+
+ memcpy(&iforce->xmit.buf[head], data, c);
+ if (n != c)
+ memcpy(&iforce->xmit.buf[0], data + c, n - c);
+
+ XMIT_INC(head, n);
}
- XMIT_INC(head, n);
- spin_unlock_irqrestore(&iforce->xmit_lock, flags);
/*
* If necessary, start the transmission
*/
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 2380546d7978..75b85c46dfa4 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -28,45 +28,39 @@ static void iforce_serio_xmit(struct iforce *iforce)
iforce);
unsigned char cs;
int i;
- unsigned long flags;
if (test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
set_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags);
return;
}
- spin_lock_irqsave(&iforce->xmit_lock, flags);
+ guard(spinlock_irqsave)(&iforce->xmit_lock);
-again:
- if (iforce->xmit.head == iforce->xmit.tail) {
- iforce_clear_xmit_and_wake(iforce);
- spin_unlock_irqrestore(&iforce->xmit_lock, flags);
- return;
- }
+ do {
+ if (iforce->xmit.head == iforce->xmit.tail)
+ break;
- cs = 0x2b;
+ cs = 0x2b;
- serio_write(iforce_serio->serio, 0x2b);
+ serio_write(iforce_serio->serio, 0x2b);
- serio_write(iforce_serio->serio, iforce->xmit.buf[iforce->xmit.tail]);
- cs ^= iforce->xmit.buf[iforce->xmit.tail];
- XMIT_INC(iforce->xmit.tail, 1);
-
- for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
serio_write(iforce_serio->serio,
iforce->xmit.buf[iforce->xmit.tail]);
cs ^= iforce->xmit.buf[iforce->xmit.tail];
XMIT_INC(iforce->xmit.tail, 1);
- }
- serio_write(iforce_serio->serio, cs);
+ for (i = iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
+ serio_write(iforce_serio->serio,
+ iforce->xmit.buf[iforce->xmit.tail]);
+ cs ^= iforce->xmit.buf[iforce->xmit.tail];
+ XMIT_INC(iforce->xmit.tail, 1);
+ }
- if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
- goto again;
+ serio_write(iforce_serio->serio, cs);
- iforce_clear_xmit_and_wake(iforce);
+ } while (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags));
- spin_unlock_irqrestore(&iforce->xmit_lock, flags);
+ iforce_clear_xmit_and_wake(iforce);
}
static int iforce_serio_get_id(struct iforce *iforce, u8 id,
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index cba92bd590a8..1f00f76b0174 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -25,13 +25,11 @@ static void __iforce_usb_xmit(struct iforce *iforce)
struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
iforce);
int n, c;
- unsigned long flags;
- spin_lock_irqsave(&iforce->xmit_lock, flags);
+ guard(spinlock_irqsave)(&iforce->xmit_lock);
if (iforce->xmit.head == iforce->xmit.tail) {
iforce_clear_xmit_and_wake(iforce);
- spin_unlock_irqrestore(&iforce->xmit_lock, flags);
return;
}
@@ -45,7 +43,8 @@ static void __iforce_usb_xmit(struct iforce *iforce)
/* Copy rest of data then */
c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
- if (n < c) c=n;
+ if (n < c)
+ c = n;
memcpy(iforce_usb->out->transfer_buffer + 1,
&iforce->xmit.buf[iforce->xmit.tail],
@@ -53,11 +52,12 @@ static void __iforce_usb_xmit(struct iforce *iforce)
if (n != c) {
memcpy(iforce_usb->out->transfer_buffer + 1 + c,
&iforce->xmit.buf[0],
- n-c);
+ n - c);
}
XMIT_INC(iforce->xmit.tail, n);
- if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) {
+ n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC);
+ if (n) {
dev_warn(&iforce_usb->intf->dev,
"usb_submit_urb failed %d\n", n);
iforce_clear_xmit_and_wake(iforce);
@@ -66,7 +66,6 @@ static void __iforce_usb_xmit(struct iforce *iforce)
/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
* As long as the urb completion handler is not called, the transmiting
* is considered to be running */
- spin_unlock_irqrestore(&iforce->xmit_lock, flags);
}
static void iforce_usb_xmit(struct iforce *iforce)
diff --git a/drivers/input/joystick/n64joy.c b/drivers/input/joystick/n64joy.c
index b0986d2195d6..c344dbc0c493 100644
--- a/drivers/input/joystick/n64joy.c
+++ b/drivers/input/joystick/n64joy.c
@@ -191,35 +191,32 @@ static void n64joy_poll(struct timer_list *t)
static int n64joy_open(struct input_dev *dev)
{
struct n64joy_priv *priv = input_get_drvdata(dev);
- int err;
-
- err = mutex_lock_interruptible(&priv->n64joy_mutex);
- if (err)
- return err;
-
- if (!priv->n64joy_opened) {
- /*
- * We could use the vblank irq, but it's not important if
- * the poll point slightly changes.
- */
- timer_setup(&priv->timer, n64joy_poll, 0);
- mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16));
- }
- priv->n64joy_opened++;
+ scoped_guard(mutex_intr, &priv->n64joy_mutex) {
+ if (!priv->n64joy_opened) {
+ /*
+ * We could use the vblank irq, but it's not important
+ * if the poll point slightly changes.
+ */
+ timer_setup(&priv->timer, n64joy_poll, 0);
+ mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16));
+ }
- mutex_unlock(&priv->n64joy_mutex);
- return err;
+ priv->n64joy_opened++;
+ return 0;
+ }
+
+ return -EINTR;
}
static void n64joy_close(struct input_dev *dev)
{
struct n64joy_priv *priv = input_get_drvdata(dev);
- mutex_lock(&priv->n64joy_mutex);
+ guard(mutex)(&priv->n64joy_mutex);
+
if (!--priv->n64joy_opened)
del_timer_sync(&priv->timer);
- mutex_unlock(&priv->n64joy_mutex);
}
static const u64 __initconst scandata[] ____cacheline_aligned = {
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 0a78dda3e0ea..db696ba61a3b 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -103,33 +103,31 @@ static void tgfx_timer(struct timer_list *t)
static int tgfx_open(struct input_dev *dev)
{
struct tgfx *tgfx = input_get_drvdata(dev);
- int err;
- err = mutex_lock_interruptible(&tgfx->sem);
- if (err)
- return err;
+ scoped_guard(mutex_intr, &tgfx->sem) {
+ if (!tgfx->used++) {
+ parport_claim(tgfx->pd);
+ parport_write_control(tgfx->pd->port, 0x04);
+ mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
+ }
- if (!tgfx->used++) {
- parport_claim(tgfx->pd);
- parport_write_control(tgfx->pd->port, 0x04);
- mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
+ return 0;
}
- mutex_unlock(&tgfx->sem);
- return 0;
+ return -EINTR;
}
static void tgfx_close(struct input_dev *dev)
{
struct tgfx *tgfx = input_get_drvdata(dev);
- mutex_lock(&tgfx->sem);
+ guard(mutex)(&tgfx->sem);
+
if (!--tgfx->used) {
del_timer_sync(&tgfx->timer);
parport_write_control(tgfx->pd->port, 0x00);
parport_release(tgfx->pd);
}
- mutex_unlock(&tgfx->sem);
}
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 22ea58bf76cb..ff9bc87f2f70 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1292,9 +1292,8 @@ static void xpad_irq_out(struct urb *urb)
struct device *dev = &xpad->intf->dev;
int status = urb->status;
int error;
- unsigned long flags;
- spin_lock_irqsave(&xpad->odata_lock, flags);
+ guard(spinlock_irqsave)(&xpad->odata_lock);
switch (status) {
case 0:
@@ -1328,8 +1327,6 @@ static void xpad_irq_out(struct urb *urb)
xpad->irq_out_active = false;
}
}
-
- spin_unlock_irqrestore(&xpad->odata_lock, flags);
}
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad,
@@ -1394,10 +1391,8 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
{
struct xpad_output_packet *packet =
&xpad->out_packets[XPAD_OUT_CMD_IDX];
- unsigned long flags;
- int retval;
- spin_lock_irqsave(&xpad->odata_lock, flags);
+ guard(spinlock_irqsave)(&xpad->odata_lock);
packet->data[0] = 0x08;
packet->data[1] = 0x00;
@@ -1416,17 +1411,12 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
/* Reset the sequence so we send out presence first */
xpad->last_out_packet = -1;
- retval = xpad_try_sending_next_out_packet(xpad);
-
- spin_unlock_irqrestore(&xpad->odata_lock, flags);
-
- return retval;
+ return xpad_try_sending_next_out_packet(xpad);
}
static int xpad_start_xbox_one(struct usb_xpad *xpad)
{
- unsigned long flags;
- int retval;
+ int error;
if (usb_ifnum_to_if(xpad->udev, GIP_WIRED_INTF_AUDIO)) {
/*
@@ -1435,15 +1425,15 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad)
* Controller for Series X|S (0x20d6:0x200e) to report the
* guide button.
*/
- retval = usb_set_interface(xpad->udev,
- GIP_WIRED_INTF_AUDIO, 0);
- if (retval)
+ error = usb_set_interface(xpad->udev,
+ GIP_WIRED_INTF_AUDIO, 0);
+ if (error)
dev_warn(&xpad->dev->dev,
"unable to disable audio interface: %d\n",
- retval);
+ error);
}
- spin_lock_irqsave(&xpad->odata_lock, flags);
+ guard(spinlock_irqsave)(&xpad->odata_lock);
/*
* Begin the init sequence by attempting to send a packet.
@@ -1451,16 +1441,11 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad)
* sending any packets from the output ring.
*/
xpad->init_seq = 0;
- retval = xpad_try_sending_next_out_packet(xpad);
-
- spin_unlock_irqrestore(&xpad->odata_lock, flags);
-
- return retval;
+ return xpad_try_sending_next_out_packet(xpad);
}
static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num)
{
- unsigned long flags;
struct xpad_output_packet *packet =
&xpad->out_packets[XPAD_OUT_CMD_IDX];
static const u8 mode_report_ack[] = {
@@ -1468,7 +1453,7 @@ static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num)
0x00, GIP_CMD_VIRTUAL_KEY, GIP_OPT_INTERNAL, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
};
- spin_lock_irqsave(&xpad->odata_lock, flags);
+ guard(spinlock_irqsave)(&xpad->odata_lock);
packet->len = sizeof(mode_report_ack);
memcpy(packet->data, mode_report_ack, packet->len);
@@ -1478,8 +1463,6 @@ static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num)
/* Reset the sequence so we send out the ack now */
xpad->last_out_packet = -1;
xpad_try_sending_next_out_packet(xpad);
-
- spin_unlock_irqrestore(&xpad->odata_lock, flags);
}
#ifdef CONFIG_JOYSTICK_XPAD_FF
@@ -1489,8 +1472,6 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_FF_IDX];
__u16 strong;
__u16 weak;
- int retval;
- unsigned long flags;
if (effect->type != FF_RUMBLE)
return 0;
@@ -1498,7 +1479,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
strong = effect->u.rumble.strong_magnitude;
weak = effect->u.rumble.weak_magnitude;
- spin_lock_irqsave(&xpad->odata_lock, flags);
+ guard(spinlock_irqsave)(&xpad->odata_lock);
switch (xpad->xtype) {
case XTYPE_XBOX:
@@ -1564,15 +1545,10 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
dev_dbg(&xpad->dev->dev,
"%s - rumble command sent to unsupported xpad type: %d\n",
__func__, xpad->xtype);
- retval = -EINVAL;
- goto out;
+ return -EINVAL;
}
- retval = xpad_try_sending_next_out_packet(xpad);
-
-out:
- spin_unlock_irqrestore(&xpad->odata_lock, flags);
- return retval;
+ return xpad_try_sending_next_out_packet(xpad);
}
static int xpad_init_ff(struct usb_xpad *xpad)
@@ -1625,11 +1601,10 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
{
struct xpad_output_packet *packet =
&xpad->out_packets[XPAD_OUT_LED_IDX];
- unsigned long flags;
command %= 16;
- spin_lock_irqsave(&xpad->odata_lock, flags);
+ guard(spinlock_irqsave)(&xpad->odata_lock);
switch (xpad->xtype) {
case XTYPE_XBOX360:
@@ -1659,8 +1634,6 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
}
xpad_try_sending_next_out_packet(xpad);
-
- spin_unlock_irqrestore(&xpad->odata_lock, flags);
}
/*
@@ -1785,11 +1758,10 @@ static void xpad_stop_input(struct usb_xpad *xpad)
static void xpad360w_poweroff_controller(struct usb_xpad *xpad)
{
- unsigned long flags;
struct xpad_output_packet *packet =
&xpad->out_packets[XPAD_OUT_CMD_IDX];
- spin_lock_irqsave(&xpad->odata_lock, flags);
+ guard(spinlock_irqsave)(&xpad->odata_lock);
packet->data[0] = 0x00;
packet->data[1] = 0x00;
@@ -1809,8 +1781,6 @@ static void xpad360w_poweroff_controller(struct usb_xpad *xpad)
/* Reset the sequence so we send out poweroff now */
xpad->last_out_packet = -1;
xpad_try_sending_next_out_packet(xpad);
-
- spin_unlock_irqrestore(&xpad->odata_lock, flags);
}
static int xpad360w_start_input(struct usb_xpad *xpad)
@@ -2234,10 +2204,10 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
if (auto_poweroff && xpad->pad_present)
xpad360w_poweroff_controller(xpad);
} else {
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
+
if (input_device_enabled(input))
xpad_stop_input(xpad);
- mutex_unlock(&input->mutex);
}
xpad_stop_output(xpad);
@@ -2249,26 +2219,25 @@ static int xpad_resume(struct usb_interface *intf)
{
struct usb_xpad *xpad = usb_get_intfdata(intf);
struct input_dev *input = xpad->dev;
- int retval = 0;
- if (xpad->xtype == XTYPE_XBOX360W) {
- retval = xpad360w_start_input(xpad);
- } else {
- mutex_lock(&input->mutex);
- if (input_device_enabled(input)) {
- retval = xpad_start_input(xpad);
- } else if (xpad->xtype == XTYPE_XBOXONE) {
- /*
- * Even if there are no users, we'll send Xbox One pads
- * the startup sequence so they don't sit there and
- * blink until somebody opens the input device again.
- */
- retval = xpad_start_xbox_one(xpad);
- }
- mutex_unlock(&input->mutex);
+ if (xpad->xtype == XTYPE_XBOX360W)
+ return xpad360w_start_input(xpad);
+
+ guard(mutex)(&input->mutex);
+
+ if (input_device_enabled(input))
+ return xpad_start_input(xpad);
+
+ if (xpad->xtype == XTYPE_XBOXONE) {
+ /*
+ * Even if there are no users, we'll send Xbox One pads
+ * the startup sequence so they don't sit there and
+ * blink until somebody opens the input device again.
+ */
+ return xpad_start_xbox_one(xpad);
}
- return retval;
+ return 0;
}
static struct usb_driver xpad_driver = {
diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c
index 10c248f0c1fc..980d739e45b8 100644
--- a/drivers/input/keyboard/adp5520-keys.c
+++ b/drivers/input/keyboard/adp5520-keys.c
@@ -181,7 +181,7 @@ static struct platform_driver adp5520_keys_driver = {
.name = "adp5520-keys",
},
.probe = adp5520_keys_probe,
- .remove_new = adp5520_keys_remove,
+ .remove = adp5520_keys_remove,
};
module_platform_driver(adp5520_keys_driver);
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index 922d3ab998f3..81d0876ee358 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -411,7 +411,7 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip,
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
if (val)
kpad->dat_out[bank] |= bit;
@@ -420,8 +420,6 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip,
adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) +
bank, kpad->dat_out[bank]);
-
- mutex_unlock(&kpad->gpio_lock);
}
static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off)
@@ -429,18 +427,13 @@ static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off)
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
- int ret;
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
kpad->dir[bank] &= ~bit;
- ret = adp5589_write(kpad->client,
- kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
- kpad->dir[bank]);
-
- mutex_unlock(&kpad->gpio_lock);
-
- return ret;
+ return adp5589_write(kpad->client,
+ kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
+ kpad->dir[bank]);
}
static int adp5589_gpio_direction_output(struct gpio_chip *chip,
@@ -449,9 +442,9 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip,
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
- int ret;
+ int error;
- mutex_lock(&kpad->gpio_lock);
+ guard(mutex)(&kpad->gpio_lock);
kpad->dir[bank] |= bit;
@@ -460,15 +453,19 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip,
else
kpad->dat_out[bank] &= ~bit;
- ret = adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A)
- + bank, kpad->dat_out[bank]);
- ret |= adp5589_write(kpad->client,
- kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
- kpad->dir[bank]);
+ error = adp5589_write(kpad->client,
+ kpad->var->reg(ADP5589_GPO_DATA_OUT_A) + bank,
+ kpad->dat_out[bank]);
+ if (error)
+ return error;
- mutex_unlock(&kpad->gpio_lock);
+ error = adp5589_write(kpad->client,
+ kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank,
+ kpad->dir[bank]);
+ if (error)
+ return error;
- return ret;
+ return 0;
}
static int adp5589_build_gpiomap(struct adp5589_kpad *kpad,
diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c
index 2c993fa8306a..b5ff71cd5a70 100644
--- a/drivers/input/keyboard/applespi.c
+++ b/drivers/input/keyboard/applespi.c
@@ -717,9 +717,7 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi);
static void applespi_msg_complete(struct applespi_data *applespi,
bool is_write_msg, bool is_read_compl)
{
- unsigned long flags;
-
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
if (is_read_compl)
applespi->read_active = false;
@@ -733,8 +731,6 @@ static void applespi_msg_complete(struct applespi_data *applespi,
applespi->cmd_msg_queued = 0;
applespi_send_cmd_msg(applespi);
}
-
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
}
static void applespi_async_write_complete(void *context)
@@ -888,33 +884,22 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi)
static void applespi_init(struct applespi_data *applespi, bool is_resume)
{
- unsigned long flags;
-
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
if (is_resume)
applespi->want_mt_init_cmd = true;
else
applespi->want_tp_info_cmd = true;
applespi_send_cmd_msg(applespi);
-
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
}
static int applespi_set_capsl_led(struct applespi_data *applespi,
bool capslock_on)
{
- unsigned long flags;
- int sts;
-
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
applespi->want_cl_led_on = capslock_on;
- sts = applespi_send_cmd_msg(applespi);
-
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
-
- return sts;
+ return applespi_send_cmd_msg(applespi);
}
static void applespi_set_bl_level(struct led_classdev *led_cdev,
@@ -922,9 +907,8 @@ static void applespi_set_bl_level(struct led_classdev *led_cdev,
{
struct applespi_data *applespi =
container_of(led_cdev, struct applespi_data, backlight_info);
- unsigned long flags;
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
if (value == 0) {
applespi->want_bl_level = value;
@@ -940,8 +924,6 @@ static void applespi_set_bl_level(struct led_classdev *led_cdev,
}
applespi_send_cmd_msg(applespi);
-
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
}
static int applespi_event(struct input_dev *dev, unsigned int type,
@@ -1427,9 +1409,7 @@ static void applespi_got_data(struct applespi_data *applespi)
/* process packet header */
if (!applespi_verify_crc(applespi, applespi->rx_buffer,
APPLESPI_PACKET_SIZE)) {
- unsigned long flags;
-
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
if (applespi->drain) {
applespi->read_active = false;
@@ -1438,8 +1418,6 @@ static void applespi_got_data(struct applespi_data *applespi)
wake_up_all(&applespi->drain_complete);
}
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
-
return;
}
@@ -1572,11 +1550,10 @@ static u32 applespi_notify(acpi_handle gpe_device, u32 gpe, void *context)
{
struct applespi_data *applespi = context;
int sts;
- unsigned long flags;
trace_applespi_irq_received(ET_RD_IRQ, PT_READ);
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
if (!applespi->suspended) {
sts = applespi_async(applespi, &applespi->rd_m,
@@ -1589,8 +1566,6 @@ static u32 applespi_notify(acpi_handle gpe_device, u32 gpe, void *context)
applespi->read_active = true;
}
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
-
return ACPI_INTERRUPT_HANDLED;
}
@@ -1818,29 +1793,21 @@ static int applespi_probe(struct spi_device *spi)
static void applespi_drain_writes(struct applespi_data *applespi)
{
- unsigned long flags;
-
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
applespi->drain = true;
wait_event_lock_irq(applespi->drain_complete, !applespi->write_active,
applespi->cmd_msg_lock);
-
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
}
static void applespi_drain_reads(struct applespi_data *applespi)
{
- unsigned long flags;
-
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
+ guard(spinlock_irqsave)(&applespi->cmd_msg_lock);
wait_event_lock_irq(applespi->drain_complete, !applespi->read_active,
applespi->cmd_msg_lock);
applespi->suspended = true;
-
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
}
static void applespi_remove(struct spi_device *spi)
@@ -1907,21 +1874,18 @@ static int applespi_resume(struct device *dev)
struct spi_device *spi = to_spi_device(dev);
struct applespi_data *applespi = spi_get_drvdata(spi);
acpi_status acpi_sts;
- unsigned long flags;
/* ensure our flags and state reflect a newly resumed device */
- spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
-
- applespi->drain = false;
- applespi->have_cl_led_on = false;
- applespi->have_bl_level = 0;
- applespi->cmd_msg_queued = 0;
- applespi->read_active = false;
- applespi->write_active = false;
-
- applespi->suspended = false;
+ scoped_guard(spinlock_irqsave, &applespi->cmd_msg_lock) {
+ applespi->drain = false;
+ applespi->have_cl_led_on = false;
+ applespi->have_bl_level = 0;
+ applespi->cmd_msg_queued = 0;
+ applespi->read_active = false;
+ applespi->write_active = false;
- spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
+ applespi->suspended = false;
+ }
/* switch on the SPI interface */
applespi_enable_spi(applespi);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 5855d4fc6e6a..ec94fcfa4cde 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -713,9 +713,9 @@ static int atkbd_event(struct input_dev *dev,
static inline void atkbd_enable(struct atkbd *atkbd)
{
- serio_pause_rx(atkbd->ps2dev.serio);
+ guard(serio_pause_rx)(atkbd->ps2dev.serio);
+
atkbd->enabled = true;
- serio_continue_rx(atkbd->ps2dev.serio);
}
/*
@@ -725,9 +725,9 @@ static inline void atkbd_enable(struct atkbd *atkbd)
static inline void atkbd_disable(struct atkbd *atkbd)
{
- serio_pause_rx(atkbd->ps2dev.serio);
+ guard(serio_pause_rx)(atkbd->ps2dev.serio);
+
atkbd->enabled = false;
- serio_continue_rx(atkbd->ps2dev.serio);
}
static int atkbd_activate(struct atkbd *atkbd)
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index b21ef9d6ff9d..0c17cbaa3d27 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -416,7 +416,7 @@ static int cap11xx_led_set(struct led_classdev *cdev,
static int cap11xx_init_leds(struct device *dev,
struct cap11xx_priv *priv, int num_leds)
{
- struct device_node *node = dev->of_node, *child;
+ struct device_node *node = dev->of_node;
struct cap11xx_led *led;
int cnt = of_get_child_count(node);
int error;
@@ -445,7 +445,7 @@ static int cap11xx_init_leds(struct device *dev,
if (error)
return error;
- for_each_child_of_node(node, child) {
+ for_each_child_of_node_scoped(node, child) {
u32 reg;
led->cdev.name =
@@ -458,19 +458,15 @@ static int cap11xx_init_leds(struct device *dev,
led->cdev.brightness = LED_OFF;
error = of_property_read_u32(child, "reg", &reg);
- if (error != 0 || reg >= num_leds) {
- of_node_put(child);
+ if (error != 0 || reg >= num_leds)
return -EINVAL;
- }
led->reg = reg;
led->priv = priv;
error = devm_led_classdev_register(dev, &led->cdev);
- if (error) {
- of_node_put(child);
+ if (error)
return error;
- }
priv->num_leds++;
led++;
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 4c81b20ff6af..c1e53d87c8a7 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -770,7 +770,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
static struct platform_driver cros_ec_keyb_driver = {
.probe = cros_ec_keyb_probe,
- .remove_new = cros_ec_keyb_remove,
+ .remove = cros_ec_keyb_remove,
.driver = {
.name = "cros-ec-keyb",
.dev_groups = cros_ec_keyb_groups,
diff --git a/drivers/input/keyboard/cypress-sf.c b/drivers/input/keyboard/cypress-sf.c
index eb1d0720784d..335b72efc5aa 100644
--- a/drivers/input/keyboard/cypress-sf.c
+++ b/drivers/input/keyboard/cypress-sf.c
@@ -208,7 +208,7 @@ static int cypress_sf_resume(struct device *dev)
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[] = {
+static const struct i2c_device_id cypress_sf_id_table[] = {
{ CYPRESS_SF_DEV_NAME },
{ }
};
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index dcbc50304a5a..817c23438f6e 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -168,15 +168,13 @@ static int ep93xx_keypad_suspend(struct device *dev)
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
struct input_dev *input_dev = keypad->input_dev;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (keypad->enabled) {
clk_disable(keypad->clk);
keypad->enabled = false;
}
- mutex_unlock(&input_dev->mutex);
-
return 0;
}
@@ -186,7 +184,7 @@ static int ep93xx_keypad_resume(struct device *dev)
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
struct input_dev *input_dev = keypad->input_dev;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev)) {
if (!keypad->enabled) {
@@ -196,8 +194,6 @@ static int ep93xx_keypad_resume(struct device *dev)
}
}
- mutex_unlock(&input_dev->mutex);
-
return 0;
}
@@ -289,7 +285,7 @@ static struct platform_driver ep93xx_keypad_driver = {
.of_match_table = ep93xx_keypad_of_ids,
},
.probe = ep93xx_keypad_probe,
- .remove_new = ep93xx_keypad_remove,
+ .remove = ep93xx_keypad_remove,
};
module_platform_driver(ep93xx_keypad_driver);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 380fe8dab3b0..5eef66516e37 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -531,12 +531,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
* Legacy GPIO number, so request the GPIO here and
* convert it to descriptor.
*/
- unsigned flags = GPIOF_IN;
-
- if (button->active_low)
- flags |= GPIOF_ACTIVE_LOW;
-
- error = devm_gpio_request_one(dev, button->gpio, flags, desc);
+ error = devm_gpio_request_one(dev, button->gpio, GPIOF_IN, desc);
if (error < 0) {
dev_err(dev, "Failed to request GPIO %d, error %d\n",
button->gpio, error);
@@ -546,6 +541,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
bdata->gpiod = gpio_to_desc(button->gpio);
if (!bdata->gpiod)
return -EINVAL;
+
+ if (button->active_low ^ gpiod_is_active_low(bdata->gpiod))
+ gpiod_toggle_active_low(bdata->gpiod);
}
if (bdata->gpiod) {
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 41ca0d3c9098..e6707d72210e 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -306,13 +306,8 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
* Legacy GPIO number so request the GPIO here and
* convert it to descriptor.
*/
- unsigned flags = GPIOF_IN;
-
- if (button->active_low)
- flags |= GPIOF_ACTIVE_LOW;
-
- error = devm_gpio_request_one(dev, button->gpio,
- flags, button->desc ? : DRV_NAME);
+ error = devm_gpio_request_one(dev, button->gpio, GPIOF_IN,
+ button->desc ? : DRV_NAME);
if (error)
return dev_err_probe(dev, error,
"unable to claim gpio %u\n",
@@ -325,6 +320,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
button->gpio);
return -EINVAL;
}
+
+ if (button->active_low ^ gpiod_is_active_low(bdata->gpiod))
+ gpiod_toggle_active_low(bdata->gpiod);
}
bdata->last_state = -1;
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index c1a4d5055de6..c8d8d0ea35b0 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -180,9 +180,8 @@ static irqreturn_t hil_interrupt(int irq, void *handle)
/* send a command to the HIL */
static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
{
- unsigned long flags;
+ guard(spinlock_irqsave)(&hil_dev.lock);
- spin_lock_irqsave(&hil_dev.lock, flags);
while (hil_busy())
/* wait */;
hil_command(cmd);
@@ -191,7 +190,6 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
/* wait */;
hil_write_data(*(data++));
}
- spin_unlock_irqrestore(&hil_dev.lock, flags);
}
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index e15a93619e82..b92268ddfd84 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -521,13 +521,11 @@ static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
struct input_dev *input_dev = kbd->input_dev;
unsigned short reg_val = readw(kbd->mmio_base + KPSR);
- /* imx kbd can wake up system even clock is disabled */
- mutex_lock(&input_dev->mutex);
-
- if (input_device_enabled(input_dev))
- clk_disable_unprepare(kbd->clk);
-
- mutex_unlock(&input_dev->mutex);
+ scoped_guard(mutex, &input_dev->mutex) {
+ /* imx kbd can wake up system even clock is disabled */
+ if (input_device_enabled(input_dev))
+ clk_disable_unprepare(kbd->clk);
+ }
if (device_may_wakeup(&pdev->dev)) {
if (reg_val & KBD_STAT_KPKD)
@@ -547,23 +545,20 @@ static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct imx_keypad *kbd = platform_get_drvdata(pdev);
struct input_dev *input_dev = kbd->input_dev;
- int ret = 0;
+ int error;
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(kbd->irq);
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev)) {
- ret = clk_prepare_enable(kbd->clk);
- if (ret)
- goto err_clk;
+ error = clk_prepare_enable(kbd->clk);
+ if (error)
+ return error;
}
-err_clk:
- mutex_unlock(&input_dev->mutex);
-
- return ret;
+ return 0;
}
static const struct dev_pm_ops imx_kbd_pm_ops = {
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index 1d71dd79ffd2..58631bf7ce55 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -54,18 +54,18 @@ static void micro_key_receive(void *data, int len, unsigned char *msg)
static void micro_key_start(struct ipaq_micro_keys *keys)
{
- spin_lock(&keys->micro->lock);
+ guard(spinlock)(&keys->micro->lock);
+
keys->micro->key = micro_key_receive;
keys->micro->key_data = keys;
- spin_unlock(&keys->micro->lock);
}
static void micro_key_stop(struct ipaq_micro_keys *keys)
{
- spin_lock(&keys->micro->lock);
+ guard(spinlock)(&keys->micro->lock);
+
keys->micro->key = NULL;
keys->micro->key_data = NULL;
- spin_unlock(&keys->micro->lock);
}
static int micro_key_open(struct input_dev *input)
@@ -141,13 +141,11 @@ static int micro_key_resume(struct device *dev)
struct ipaq_micro_keys *keys = dev_get_drvdata(dev);
struct input_dev *input = keys->input;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input))
micro_key_start(keys);
- mutex_unlock(&input->mutex);
-
return 0;
}
diff --git a/drivers/input/keyboard/iqs62x-keys.c b/drivers/input/keyboard/iqs62x-keys.c
index 1315b0f0862f..b086c7b28d5c 100644
--- a/drivers/input/keyboard/iqs62x-keys.c
+++ b/drivers/input/keyboard/iqs62x-keys.c
@@ -323,7 +323,7 @@ static struct platform_driver iqs62x_keys_platform_driver = {
.name = "iqs62x-keys",
},
.probe = iqs62x_keys_probe,
- .remove_new = iqs62x_keys_remove,
+ .remove = iqs62x_keys_remove,
};
module_platform_driver(iqs62x_keys_platform_driver);
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index cf67ba13477a..e26bf2956344 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -350,11 +350,11 @@ static int lm8323_configure(struct lm8323_chip *lm)
static void pwm_done(struct lm8323_pwm *pwm)
{
- mutex_lock(&pwm->lock);
+ guard(mutex)(&pwm->lock);
+
pwm->running = false;
if (pwm->desired_brightness != pwm->brightness)
schedule_work(&pwm->work);
- mutex_unlock(&pwm->lock);
}
/*
@@ -367,7 +367,7 @@ static irqreturn_t lm8323_irq(int irq, void *_lm)
u8 ints;
int i;
- mutex_lock(&lm->lock);
+ guard(mutex)(&lm->lock);
while ((lm8323_read(lm, LM8323_CMD_READ_INT, &ints, 1) == 1) && ints) {
if (likely(ints & INT_KEYPAD))
@@ -394,8 +394,6 @@ static irqreturn_t lm8323_irq(int irq, void *_lm)
}
}
- mutex_unlock(&lm->lock);
-
return IRQ_HANDLED;
}
@@ -445,7 +443,7 @@ static void lm8323_pwm_work(struct work_struct *work)
u16 pwm_cmds[3];
int num_cmds = 0;
- mutex_lock(&pwm->lock);
+ guard(mutex)(&pwm->lock);
/*
* Do nothing if we're already at the requested level,
@@ -454,7 +452,7 @@ static void lm8323_pwm_work(struct work_struct *work)
* finishes.
*/
if (pwm->running || pwm->desired_brightness == pwm->brightness)
- goto out;
+ return;
kill = (pwm->desired_brightness == 0);
up = (pwm->desired_brightness > pwm->brightness);
@@ -489,9 +487,6 @@ static void lm8323_pwm_work(struct work_struct *work)
lm8323_write_pwm(pwm, kill, num_cmds, pwm_cmds);
pwm->brightness = pwm->desired_brightness;
-
- out:
- mutex_unlock(&pwm->lock);
}
static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev,
@@ -500,9 +495,9 @@ static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev,
struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev);
struct lm8323_chip *lm = pwm->chip;
- mutex_lock(&pwm->lock);
- pwm->desired_brightness = brightness;
- mutex_unlock(&pwm->lock);
+ scoped_guard(mutex, &pwm->lock) {
+ pwm->desired_brightness = brightness;
+ }
if (in_interrupt()) {
schedule_work(&pwm->work);
@@ -510,12 +505,12 @@ static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev,
/*
* Schedule PWM work as usual unless we are going into suspend
*/
- mutex_lock(&lm->lock);
- if (likely(!lm->pm_suspend))
- schedule_work(&pwm->work);
- else
- lm8323_pwm_work(&pwm->work);
- mutex_unlock(&lm->lock);
+ scoped_guard(mutex, &lm->lock) {
+ if (likely(!lm->pm_suspend))
+ schedule_work(&pwm->work);
+ else
+ lm8323_pwm_work(&pwm->work);
+ }
}
}
@@ -608,9 +603,9 @@ static ssize_t lm8323_set_disable(struct device *dev,
if (ret)
return ret;
- mutex_lock(&lm->lock);
+ guard(mutex)(&lm->lock);
+
lm->kp_enabled = !i;
- mutex_unlock(&lm->lock);
return count;
}
@@ -758,9 +753,9 @@ static int lm8323_suspend(struct device *dev)
irq_set_irq_wake(client->irq, 0);
disable_irq(client->irq);
- mutex_lock(&lm->lock);
- lm->pm_suspend = true;
- mutex_unlock(&lm->lock);
+ scoped_guard(mutex, &lm->lock) {
+ lm->pm_suspend = true;
+ }
for (i = 0; i < 3; i++)
if (lm->pwm[i].enabled)
@@ -775,9 +770,9 @@ static int lm8323_resume(struct device *dev)
struct lm8323_chip *lm = i2c_get_clientdata(client);
int i;
- mutex_lock(&lm->lock);
- lm->pm_suspend = false;
- mutex_unlock(&lm->lock);
+ scoped_guard(mutex, &lm->lock) {
+ lm->pm_suspend = false;
+ }
for (i = 0; i < 3; i++)
if (lm->pwm[i].enabled)
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 4b0f8323c492..c501a93a4417 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -112,11 +112,10 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
{
unsigned int row, col, rowd;
- unsigned long flags;
unsigned int num_pressed;
unsigned long membase = locomokbd->base;
- spin_lock_irqsave(&locomokbd->lock, flags);
+ guard(spinlock_irqsave)(&locomokbd->lock);
locomokbd_charge_all(membase);
@@ -167,8 +166,6 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
else
locomokbd->count_cancel = 0;
-
- spin_unlock_irqrestore(&locomokbd->lock, flags);
}
/*
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index 423035be86fb..2392e7ec3b19 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -262,7 +262,7 @@ static int lpc32xx_kscan_suspend(struct device *dev)
struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
struct input_dev *input = kscandat->input;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input)) {
/* Clear IRQ and disable clock */
@@ -270,7 +270,6 @@ static int lpc32xx_kscan_suspend(struct device *dev)
clk_disable_unprepare(kscandat->clk);
}
- mutex_unlock(&input->mutex);
return 0;
}
@@ -279,19 +278,20 @@ static int lpc32xx_kscan_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
struct input_dev *input = kscandat->input;
- int retval = 0;
+ int error;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (input_device_enabled(input)) {
/* Enable clock and clear IRQ */
- retval = clk_prepare_enable(kscandat->clk);
- if (retval == 0)
- writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
+ error = clk_prepare_enable(kscandat->clk);
+ if (error)
+ return error;
+
+ writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
}
- mutex_unlock(&input->mutex);
- return retval;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(lpc32xx_kscan_pm_ops, lpc32xx_kscan_suspend,
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
index 91a1d2958109..1a8f1fa53fbb 100644
--- a/drivers/input/keyboard/maple_keyb.c
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -132,14 +132,11 @@ static void dc_kbd_callback(struct mapleq *mq)
* We should always get the lock because the only
* time it may be locked is if the driver is in the cleanup phase.
*/
- if (likely(mutex_trylock(&maple_keyb_mutex))) {
-
+ scoped_guard(mutex_try, &maple_keyb_mutex) {
if (buf[1] == mapledev->function) {
memcpy(kbd->new, buf + 2, 8);
dc_scan_kbd(kbd);
}
-
- mutex_unlock(&maple_keyb_mutex);
}
}
@@ -211,14 +208,12 @@ static int remove_maple_kbd(struct device *dev)
struct maple_device *mdev = to_maple_dev(dev);
struct dc_kbd *kbd = maple_get_drvdata(mdev);
- mutex_lock(&maple_keyb_mutex);
+ guard(mutex)(&maple_keyb_mutex);
input_unregister_device(kbd->dev);
kfree(kbd);
maple_set_drvdata(mdev, NULL);
-
- mutex_unlock(&maple_keyb_mutex);
return 0;
}
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index 3c38bae576ed..2a3b3bfc2878 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -17,7 +17,6 @@
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
#include <linux/input/matrix_keypad.h>
#include <linux/slab.h>
#include <linux/of.h>
@@ -158,18 +157,17 @@ static void matrix_keypad_scan(struct work_struct *work)
activate_all_cols(keypad, true);
/* Enable IRQs again */
- spin_lock_irq(&keypad->lock);
- keypad->scan_pending = false;
- enable_row_irqs(keypad);
- spin_unlock_irq(&keypad->lock);
+ scoped_guard(spinlock_irq, &keypad->lock) {
+ keypad->scan_pending = false;
+ enable_row_irqs(keypad);
+ }
}
static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
{
struct matrix_keypad *keypad = id;
- unsigned long flags;
- spin_lock_irqsave(&keypad->lock, flags);
+ guard(spinlock_irqsave)(&keypad->lock);
/*
* See if another IRQ beaten us to it and scheduled the
@@ -185,7 +183,6 @@ static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
msecs_to_jiffies(keypad->debounce_ms));
out:
- spin_unlock_irqrestore(&keypad->lock, flags);
return IRQ_HANDLED;
}
@@ -209,9 +206,9 @@ static void matrix_keypad_stop(struct input_dev *dev)
{
struct matrix_keypad *keypad = input_get_drvdata(dev);
- spin_lock_irq(&keypad->lock);
- keypad->stopped = true;
- spin_unlock_irq(&keypad->lock);
+ scoped_guard(spinlock_irq, &keypad->lock) {
+ keypad->stopped = true;
+ }
flush_delayed_work(&keypad->work);
/*
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 21827d2497fa..bd1a944ded46 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -82,42 +82,6 @@ static const struct mpr121_init_register init_reg_table[] = {
{ AUTO_CONFIG_CTRL_ADDR, 0x0b },
};
-static void mpr121_vdd_supply_disable(void *data)
-{
- struct regulator *vdd_supply = data;
-
- regulator_disable(vdd_supply);
-}
-
-static struct regulator *mpr121_vdd_supply_init(struct device *dev)
-{
- struct regulator *vdd_supply;
- int err;
-
- vdd_supply = devm_regulator_get(dev, "vdd");
- if (IS_ERR(vdd_supply)) {
- dev_err(dev, "failed to get vdd regulator: %ld\n",
- PTR_ERR(vdd_supply));
- return vdd_supply;
- }
-
- err = regulator_enable(vdd_supply);
- if (err) {
- dev_err(dev, "failed to enable vdd regulator: %d\n", err);
- return ERR_PTR(err);
- }
-
- err = devm_add_action_or_reset(dev, mpr121_vdd_supply_disable,
- vdd_supply);
- if (err) {
- dev_err(dev, "failed to add disable regulator action: %d\n",
- err);
- return ERR_PTR(err);
- }
-
- return vdd_supply;
-}
-
static void mpr_touchkey_report(struct input_dev *dev)
{
struct mpr121_touchkey *mpr121 = input_get_drvdata(dev);
@@ -233,7 +197,6 @@ err_i2c_write:
static int mpr_touchkey_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
- struct regulator *vdd_supply;
int vdd_uv;
struct mpr121_touchkey *mpr121;
struct input_dev *input_dev;
@@ -241,11 +204,9 @@ static int mpr_touchkey_probe(struct i2c_client *client)
int error;
int i;
- vdd_supply = mpr121_vdd_supply_init(dev);
- if (IS_ERR(vdd_supply))
- return PTR_ERR(vdd_supply);
-
- vdd_uv = regulator_get_voltage(vdd_supply);
+ vdd_uv = devm_regulator_get_enable_read_voltage(dev, "vdd");
+ if (vdd_uv < 0)
+ return dev_err_probe(dev, vdd_uv, "failed to get vdd voltage\n");
mpr121 = devm_kzalloc(dev, sizeof(*mpr121), GFP_KERNEL);
if (!mpr121)
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index 4364c3401ff1..5ad6be914160 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -307,7 +307,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
int error, index = 0;
unsigned int keycount;
struct mt6397_chip *pmic_chip = dev_get_drvdata(pdev->dev.parent);
- struct device_node *node = pdev->dev.of_node, *child;
+ struct device_node *node = pdev->dev.of_node;
static const char *const irqnames[] = { "powerkey", "homekey" };
static const char *const irqnames_r[] = { "powerkey_r", "homekey_r" };
struct mtk_pmic_keys *keys;
@@ -343,24 +343,20 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
return -EINVAL;
}
- for_each_child_of_node(node, child) {
+ for_each_child_of_node_scoped(node, child) {
keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index];
keys->keys[index].irq =
platform_get_irq_byname(pdev, irqnames[index]);
- if (keys->keys[index].irq < 0) {
- of_node_put(child);
+ if (keys->keys[index].irq < 0)
return keys->keys[index].irq;
- }
if (of_device_is_compatible(node, "mediatek,mt6358-keys")) {
keys->keys[index].irq_r = platform_get_irq_byname(pdev,
irqnames_r[index]);
- if (keys->keys[index].irq_r < 0) {
- of_node_put(child);
+ if (keys->keys[index].irq_r < 0)
return keys->keys[index].irq_r;
- }
}
error = of_property_read_u32(child,
@@ -369,7 +365,6 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
dev_err(keys->dev,
"failed to read key:%d linux,keycode property: %d\n",
index, error);
- of_node_put(child);
return error;
}
@@ -377,10 +372,8 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
keys->keys[index].wakeup = true;
error = mtk_pmic_key_setup(keys, &keys->keys[index]);
- if (error) {
- of_node_put(child);
+ if (error)
return error;
- }
index++;
}
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 57587541110b..9e13f3f70a81 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -156,15 +156,15 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute
if ((state != 1) && (state != 0))
return -EINVAL;
- mutex_lock(&kp_enable_mutex);
- if (state != kp_enable) {
- if (state)
- enable_irq(omap_kp->irq);
- else
- disable_irq(omap_kp->irq);
- kp_enable = state;
+ scoped_guard(mutex, &kp_enable_mutex) {
+ if (state != kp_enable) {
+ if (state)
+ enable_irq(omap_kp->irq);
+ else
+ disable_irq(omap_kp->irq);
+ kp_enable = state;
+ }
}
- mutex_unlock(&kp_enable_mutex);
return strnlen(buf, count);
}
@@ -290,7 +290,7 @@ static void omap_kp_remove(struct platform_device *pdev)
static struct platform_driver omap_kp_driver = {
.probe = omap_kp_probe,
- .remove_new = omap_kp_remove,
+ .remove = omap_kp_remove,
.driver = {
.name = "omap-keypad",
.dev_groups = omap_kp_groups,
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index 040b340995d8..bffe89c0717a 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -144,7 +144,7 @@ static void omap4_keypad_scan_keys(struct omap4_keypad *keypad_data, u64 keys)
{
u64 changed;
- mutex_lock(&keypad_data->lock);
+ guard(mutex)(&keypad_data->lock);
changed = keys ^ keypad_data->keys;
@@ -158,8 +158,6 @@ static void omap4_keypad_scan_keys(struct omap4_keypad *keypad_data, u64 keys)
omap4_keypad_report_keys(keypad_data, changed & keys, true);
keypad_data->keys = keys;
-
- mutex_unlock(&keypad_data->lock);
}
/* Interrupt handlers */
@@ -487,7 +485,7 @@ MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
static struct platform_driver omap4_keypad_driver = {
.probe = omap4_keypad_probe,
- .remove_new = omap4_keypad_remove,
+ .remove = omap4_keypad_remove,
.driver = {
.name = "omap4-keypad",
.of_match_table = omap_keypad_dt_match,
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index 26a005f9ace3..35d1aa2a22a5 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -630,12 +630,10 @@ static int pmic8xxx_kp_suspend(struct device *dev)
if (device_may_wakeup(dev)) {
enable_irq_wake(kp->key_sense_irq);
} else {
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev))
pmic8xxx_kp_disable(kp);
-
- mutex_unlock(&input_dev->mutex);
}
return 0;
@@ -650,12 +648,10 @@ static int pmic8xxx_kp_resume(struct device *dev)
if (device_may_wakeup(dev)) {
disable_irq_wake(kp->key_sense_irq);
} else {
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev))
pmic8xxx_kp_enable(kp);
-
- mutex_unlock(&input_dev->mutex);
}
return 0;
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 3724363d140e..38ec619aa359 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -682,7 +682,7 @@ static int pxa27x_keypad_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
struct input_dev *input_dev = keypad->input_dev;
- int ret = 0;
+ int error;
/*
* If the keypad is used as wake up source, the clock is not turned
@@ -691,19 +691,19 @@ static int pxa27x_keypad_resume(struct device *dev)
if (device_may_wakeup(&pdev->dev)) {
disable_irq_wake(keypad->irq);
} else {
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev)) {
/* Enable unit clock */
- ret = clk_prepare_enable(keypad->clk);
- if (!ret)
- pxa27x_keypad_config(keypad);
- }
+ error = clk_prepare_enable(keypad->clk);
+ if (error)
+ return error;
- mutex_unlock(&input_dev->mutex);
+ pxa27x_keypad_config(keypad);
+ }
}
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops,
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index e212eff7687c..9f1049aa3048 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -587,7 +587,7 @@ MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids);
static struct platform_driver samsung_keypad_driver = {
.probe = samsung_keypad_probe,
- .remove_new = samsung_keypad_remove,
+ .remove = samsung_keypad_remove,
.driver = {
.name = "samsung-keypad",
.of_match_table = of_match_ptr(samsung_keypad_dt_match),
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index 4ea4fd25c5d2..159f41eedd41 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -319,7 +319,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops,
static struct platform_driver sh_keysc_device_driver = {
.probe = sh_keysc_probe,
- .remove_new = sh_keysc_remove,
+ .remove = sh_keysc_remove,
.driver = {
.name = "sh_keysc",
.pm = pm_sleep_ptr(&sh_keysc_dev_pm_ops),
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 1df4feb8ba01..2fae337562a2 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pm_wakeup.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/platform_data/keyboard-spear.h>
@@ -274,7 +273,7 @@ static int spear_kbd_suspend(struct device *dev)
struct input_dev *input_dev = kbd->input;
unsigned int rate = 0, mode_ctl_reg, val;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
/* explicitly enable clock as we may program device */
clk_enable(kbd->clk);
@@ -315,8 +314,6 @@ static int spear_kbd_suspend(struct device *dev)
/* restore previous clk state */
clk_disable(kbd->clk);
- mutex_unlock(&input_dev->mutex);
-
return 0;
}
@@ -326,7 +323,7 @@ static int spear_kbd_resume(struct device *dev)
struct spear_kbd *kbd = platform_get_drvdata(pdev);
struct input_dev *input_dev = kbd->input;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (device_may_wakeup(&pdev->dev)) {
if (kbd->irq_wake_enabled) {
@@ -342,8 +339,6 @@ static int spear_kbd_resume(struct device *dev)
if (input_device_enabled(input_dev))
writel_relaxed(kbd->mode_ctl_reg, kbd->io_base + MODE_CTL_REG);
- mutex_unlock(&input_dev->mutex);
-
return 0;
}
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
index 0d27324af809..e53ef4c670e4 100644
--- a/drivers/input/keyboard/st-keyscan.c
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -216,14 +216,13 @@ static int keyscan_suspend(struct device *dev)
struct st_keyscan *keypad = platform_get_drvdata(pdev);
struct input_dev *input = keypad->input_dev;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
if (device_may_wakeup(dev))
enable_irq_wake(keypad->irq);
else if (input_device_enabled(input))
keyscan_stop(keypad);
- mutex_unlock(&input->mutex);
return 0;
}
@@ -232,17 +231,19 @@ static int keyscan_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct st_keyscan *keypad = platform_get_drvdata(pdev);
struct input_dev *input = keypad->input_dev;
- int retval = 0;
+ int error;
- mutex_lock(&input->mutex);
+ guard(mutex)(&input->mutex);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
disable_irq_wake(keypad->irq);
- else if (input_device_enabled(input))
- retval = keyscan_start(keypad);
+ } else if (input_device_enabled(input)) {
+ error = keyscan_start(keypad);
+ if (error)
+ return error;
+ }
- mutex_unlock(&input->mutex);
- return retval;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops,
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index ef2f44027894..0acded4fb9c9 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -414,7 +414,7 @@ static void stmpe_keypad_remove(struct platform_device *pdev)
static struct platform_driver stmpe_keypad_driver = {
.driver.name = "stmpe-keypad",
.probe = stmpe_keypad_probe,
- .remove_new = stmpe_keypad_remove,
+ .remove = stmpe_keypad_remove,
};
module_platform_driver(stmpe_keypad_driver);
diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c
index f304cab0ebdb..5730f08f82d7 100644
--- a/drivers/input/keyboard/sun4i-lradc-keys.c
+++ b/drivers/input/keyboard/sun4i-lradc-keys.c
@@ -24,7 +24,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
-#include <linux/pm_wakeup.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
@@ -202,7 +201,7 @@ static void sun4i_lradc_close(struct input_dev *dev)
static int sun4i_lradc_load_dt_keymap(struct device *dev,
struct sun4i_lradc_data *lradc)
{
- struct device_node *np, *pp;
+ struct device_node *np;
int i;
int error;
@@ -223,28 +222,25 @@ static int sun4i_lradc_load_dt_keymap(struct device *dev,
return -ENOMEM;
i = 0;
- for_each_child_of_node(np, pp) {
+ for_each_child_of_node_scoped(np, pp) {
struct sun4i_lradc_keymap *map = &lradc->chan0_map[i];
u32 channel;
error = of_property_read_u32(pp, "channel", &channel);
if (error || channel != 0) {
dev_err(dev, "%pOFn: Inval channel prop\n", pp);
- of_node_put(pp);
return -EINVAL;
}
error = of_property_read_u32(pp, "voltage", &map->voltage);
if (error) {
dev_err(dev, "%pOFn: Inval voltage prop\n", pp);
- of_node_put(pp);
return -EINVAL;
}
error = of_property_read_u32(pp, "linux,code", &map->keycode);
if (error) {
dev_err(dev, "%pOFn: Inval linux,code prop\n", pp);
- of_node_put(pp);
return -EINVAL;
}
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 72fb46029710..3299e1919b37 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -241,9 +241,8 @@ static void sunkbd_reinit(struct work_struct *work)
static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
{
- serio_pause_rx(sunkbd->serio);
- sunkbd->enabled = enable;
- serio_continue_rx(sunkbd->serio);
+ scoped_guard(serio_pause_rx, sunkbd->serio)
+ sunkbd->enabled = enable;
if (!enable) {
wake_up_interruptible(&sunkbd->wait);
diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c
index 6477a41c4bac..9159b5fec129 100644
--- a/drivers/input/misc/88pm80x_onkey.c
+++ b/drivers/input/misc/88pm80x_onkey.c
@@ -141,7 +141,7 @@ static struct platform_driver pm80x_onkey_driver = {
.pm = &pm80x_onkey_pm_ops,
},
.probe = pm80x_onkey_probe,
- .remove_new = pm80x_onkey_remove,
+ .remove = pm80x_onkey_remove,
};
module_platform_driver(pm80x_onkey_driver);
diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c
index 1acd8429c56c..d106f37df6bc 100644
--- a/drivers/input/misc/ad714x.c
+++ b/drivers/input/misc/ad714x.c
@@ -941,7 +941,7 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
struct ad714x_chip *ad714x = data;
int i;
- mutex_lock(&ad714x->mutex);
+ guard(mutex)(&ad714x->mutex);
ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
@@ -954,8 +954,6 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
for (i = 0; i < ad714x->hw->touchpad_num; i++)
ad714x_touchpad_state_machine(ad714x, i);
- mutex_unlock(&ad714x->mutex);
-
return IRQ_HANDLED;
}
@@ -1169,13 +1167,11 @@ static int ad714x_suspend(struct device *dev)
dev_dbg(ad714x->dev, "%s enter\n", __func__);
- mutex_lock(&ad714x->mutex);
+ guard(mutex)(&ad714x->mutex);
data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3;
ad714x->write(ad714x, AD714X_PWR_CTRL, data);
- mutex_unlock(&ad714x->mutex);
-
return 0;
}
@@ -1184,7 +1180,7 @@ static int ad714x_resume(struct device *dev)
struct ad714x_chip *ad714x = dev_get_drvdata(dev);
dev_dbg(ad714x->dev, "%s enter\n", __func__);
- mutex_lock(&ad714x->mutex);
+ guard(mutex)(&ad714x->mutex);
/* resume to non-shutdown mode */
@@ -1197,8 +1193,6 @@ static int ad714x_resume(struct device *dev)
ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
- mutex_unlock(&ad714x->mutex);
-
return 0;
}
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index 795f69edb4b2..e84649af801d 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -244,29 +244,21 @@ static int ati_remote2_open(struct input_dev *idev)
if (r) {
dev_err(&ar2->intf[0]->dev,
"%s(): usb_autopm_get_interface() = %d\n", __func__, r);
- goto fail1;
+ return r;
}
- mutex_lock(&ati_remote2_mutex);
+ scoped_guard(mutex, &ati_remote2_mutex) {
+ if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) {
+ r = ati_remote2_submit_urbs(ar2);
+ if (r)
+ break;
+ }
- if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) {
- r = ati_remote2_submit_urbs(ar2);
- if (r)
- goto fail2;
+ ar2->flags |= ATI_REMOTE2_OPENED;
}
- ar2->flags |= ATI_REMOTE2_OPENED;
-
- mutex_unlock(&ati_remote2_mutex);
-
usb_autopm_put_interface(ar2->intf[0]);
- return 0;
-
- fail2:
- mutex_unlock(&ati_remote2_mutex);
- usb_autopm_put_interface(ar2->intf[0]);
- fail1:
return r;
}
@@ -276,14 +268,12 @@ static void ati_remote2_close(struct input_dev *idev)
dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
- mutex_lock(&ati_remote2_mutex);
+ guard(mutex)(&ati_remote2_mutex);
if (!(ar2->flags & ATI_REMOTE2_SUSPENDED))
ati_remote2_kill_urbs(ar2);
ar2->flags &= ~ATI_REMOTE2_OPENED;
-
- mutex_unlock(&ati_remote2_mutex);
}
static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
@@ -713,16 +703,14 @@ static ssize_t ati_remote2_store_channel_mask(struct device *dev,
return r;
}
- mutex_lock(&ati_remote2_mutex);
-
- if (mask != ar2->channel_mask) {
- r = ati_remote2_setup(ar2, mask);
- if (!r)
- ar2->channel_mask = mask;
+ scoped_guard(mutex, &ati_remote2_mutex) {
+ if (mask != ar2->channel_mask) {
+ r = ati_remote2_setup(ar2, mask);
+ if (!r)
+ ar2->channel_mask = mask;
+ }
}
- mutex_unlock(&ati_remote2_mutex);
-
usb_autopm_put_interface(ar2->intf[0]);
return r ? r : count;
@@ -892,15 +880,13 @@ static int ati_remote2_suspend(struct usb_interface *interface,
dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
- mutex_lock(&ati_remote2_mutex);
+ guard(mutex)(&ati_remote2_mutex);
if (ar2->flags & ATI_REMOTE2_OPENED)
ati_remote2_kill_urbs(ar2);
ar2->flags |= ATI_REMOTE2_SUSPENDED;
- mutex_unlock(&ati_remote2_mutex);
-
return 0;
}
@@ -917,7 +903,7 @@ static int ati_remote2_resume(struct usb_interface *interface)
dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
- mutex_lock(&ati_remote2_mutex);
+ guard(mutex)(&ati_remote2_mutex);
if (ar2->flags & ATI_REMOTE2_OPENED)
r = ati_remote2_submit_urbs(ar2);
@@ -925,8 +911,6 @@ static int ati_remote2_resume(struct usb_interface *interface)
if (!r)
ar2->flags &= ~ATI_REMOTE2_SUSPENDED;
- mutex_unlock(&ati_remote2_mutex);
-
return r;
}
@@ -943,11 +927,11 @@ static int ati_remote2_reset_resume(struct usb_interface *interface)
dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
- mutex_lock(&ati_remote2_mutex);
+ guard(mutex)(&ati_remote2_mutex);
r = ati_remote2_setup(ar2, ar2->channel_mask);
if (r)
- goto out;
+ return r;
if (ar2->flags & ATI_REMOTE2_OPENED)
r = ati_remote2_submit_urbs(ar2);
@@ -955,9 +939,6 @@ static int ati_remote2_reset_resume(struct usb_interface *interface)
if (!r)
ar2->flags &= ~ATI_REMOTE2_SUSPENDED;
- out:
- mutex_unlock(&ati_remote2_mutex);
-
return r;
}
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
index 728325a2d574..0cfe5d4a573c 100644
--- a/drivers/input/misc/cm109.c
+++ b/drivers/input/misc/cm109.c
@@ -355,6 +355,35 @@ static void cm109_submit_buzz_toggle(struct cm109_dev *dev)
__func__, error);
}
+static void cm109_submit_ctl(struct cm109_dev *dev)
+{
+ int error;
+
+ guard(spinlock_irqsave)(&dev->ctl_submit_lock);
+
+ dev->irq_urb_pending = 0;
+
+ if (unlikely(dev->shutdown))
+ return;
+
+ if (dev->buzzer_state)
+ dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
+ else
+ dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
+
+ dev->ctl_data->byte[HID_OR1] = dev->keybit;
+ dev->ctl_data->byte[HID_OR2] = dev->keybit;
+
+ dev->buzzer_pending = 0;
+ dev->ctl_urb_pending = 1;
+
+ error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
+ if (error)
+ dev_err(&dev->intf->dev,
+ "%s: usb_submit_urb (urb_ctl) failed %d\n",
+ __func__, error);
+}
+
/*
* IRQ handler
*/
@@ -362,8 +391,6 @@ static void cm109_urb_irq_callback(struct urb *urb)
{
struct cm109_dev *dev = urb->context;
const int status = urb->status;
- int error;
- unsigned long flags;
dev_dbg(&dev->intf->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n",
dev->irq_data->byte[0],
@@ -401,32 +428,7 @@ static void cm109_urb_irq_callback(struct urb *urb)
}
out:
-
- spin_lock_irqsave(&dev->ctl_submit_lock, flags);
-
- dev->irq_urb_pending = 0;
-
- if (likely(!dev->shutdown)) {
-
- if (dev->buzzer_state)
- dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
- else
- dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
-
- dev->ctl_data->byte[HID_OR1] = dev->keybit;
- dev->ctl_data->byte[HID_OR2] = dev->keybit;
-
- dev->buzzer_pending = 0;
- dev->ctl_urb_pending = 1;
-
- error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
- if (error)
- dev_err(&dev->intf->dev,
- "%s: usb_submit_urb (urb_ctl) failed %d\n",
- __func__, error);
- }
-
- spin_unlock_irqrestore(&dev->ctl_submit_lock, flags);
+ cm109_submit_ctl(dev);
}
static void cm109_urb_ctl_callback(struct urb *urb)
@@ -434,7 +436,6 @@ static void cm109_urb_ctl_callback(struct urb *urb)
struct cm109_dev *dev = urb->context;
const int status = urb->status;
int error;
- unsigned long flags;
dev_dbg(&dev->intf->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n",
dev->ctl_data->byte[0],
@@ -449,35 +450,31 @@ static void cm109_urb_ctl_callback(struct urb *urb)
__func__, status);
}
- spin_lock_irqsave(&dev->ctl_submit_lock, flags);
+ guard(spinlock_irqsave)(&dev->ctl_submit_lock);
dev->ctl_urb_pending = 0;
- if (likely(!dev->shutdown)) {
-
- if (dev->buzzer_pending || status) {
- dev->buzzer_pending = 0;
- dev->ctl_urb_pending = 1;
- cm109_submit_buzz_toggle(dev);
- } else if (likely(!dev->irq_urb_pending)) {
- /* ask for key data */
- dev->irq_urb_pending = 1;
- error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC);
- if (error)
- dev_err(&dev->intf->dev,
- "%s: usb_submit_urb (urb_irq) failed %d\n",
- __func__, error);
- }
- }
+ if (unlikely(dev->shutdown))
+ return;
- spin_unlock_irqrestore(&dev->ctl_submit_lock, flags);
+ if (dev->buzzer_pending || status) {
+ dev->buzzer_pending = 0;
+ dev->ctl_urb_pending = 1;
+ cm109_submit_buzz_toggle(dev);
+ } else if (likely(!dev->irq_urb_pending)) {
+ /* ask for key data */
+ dev->irq_urb_pending = 1;
+ error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC);
+ if (error)
+ dev_err(&dev->intf->dev,
+ "%s: usb_submit_urb (urb_irq) failed %d\n",
+ __func__, error);
+ }
}
static void cm109_toggle_buzzer_async(struct cm109_dev *dev)
{
- unsigned long flags;
-
- spin_lock_irqsave(&dev->ctl_submit_lock, flags);
+ guard(spinlock_irqsave)(&dev->ctl_submit_lock);
if (dev->ctl_urb_pending) {
/* URB completion will resubmit */
@@ -486,8 +483,6 @@ static void cm109_toggle_buzzer_async(struct cm109_dev *dev)
dev->ctl_urb_pending = 1;
cm109_submit_buzz_toggle(dev);
}
-
- spin_unlock_irqrestore(&dev->ctl_submit_lock, flags);
}
static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on)
@@ -556,32 +551,30 @@ static int cm109_input_open(struct input_dev *idev)
return error;
}
- mutex_lock(&dev->pm_mutex);
-
- dev->buzzer_state = 0;
- dev->key_code = -1; /* no keys pressed */
- dev->keybit = 0xf;
+ scoped_guard(mutex, &dev->pm_mutex) {
+ dev->buzzer_state = 0;
+ dev->key_code = -1; /* no keys pressed */
+ dev->keybit = 0xf;
- /* issue INIT */
- dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF;
- dev->ctl_data->byte[HID_OR1] = dev->keybit;
- dev->ctl_data->byte[HID_OR2] = dev->keybit;
- dev->ctl_data->byte[HID_OR3] = 0x00;
+ /* issue INIT */
+ dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF;
+ dev->ctl_data->byte[HID_OR1] = dev->keybit;
+ dev->ctl_data->byte[HID_OR2] = dev->keybit;
+ dev->ctl_data->byte[HID_OR3] = 0x00;
- dev->ctl_urb_pending = 1;
- error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
- if (error) {
- dev->ctl_urb_pending = 0;
- dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n",
- __func__, error);
- } else {
- dev->open = 1;
+ dev->ctl_urb_pending = 1;
+ error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
+ if (!error) {
+ dev->open = 1;
+ return 0;
+ }
}
- mutex_unlock(&dev->pm_mutex);
+ dev->ctl_urb_pending = 0;
+ usb_autopm_put_interface(dev->intf);
- if (error)
- usb_autopm_put_interface(dev->intf);
+ dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n",
+ __func__, error);
return error;
}
@@ -590,17 +583,15 @@ static void cm109_input_close(struct input_dev *idev)
{
struct cm109_dev *dev = input_get_drvdata(idev);
- mutex_lock(&dev->pm_mutex);
-
- /*
- * Once we are here event delivery is stopped so we
- * don't need to worry about someone starting buzzer
- * again
- */
- cm109_stop_traffic(dev);
- dev->open = 0;
-
- mutex_unlock(&dev->pm_mutex);
+ scoped_guard(mutex, &dev->pm_mutex) {
+ /*
+ * Once we are here event delivery is stopped so we
+ * don't need to worry about someone starting buzzer
+ * again
+ */
+ cm109_stop_traffic(dev);
+ dev->open = 0;
+ }
usb_autopm_put_interface(dev->intf);
}
@@ -823,9 +814,9 @@ static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message)
dev_info(&intf->dev, "cm109: usb_suspend (event=%d)\n", message.event);
- mutex_lock(&dev->pm_mutex);
+ guard(mutex)(&dev->pm_mutex);
+
cm109_stop_traffic(dev);
- mutex_unlock(&dev->pm_mutex);
return 0;
}
@@ -836,9 +827,9 @@ static int cm109_usb_resume(struct usb_interface *intf)
dev_info(&intf->dev, "cm109: usb_resume\n");
- mutex_lock(&dev->pm_mutex);
+ guard(mutex)(&dev->pm_mutex);
+
cm109_restore_state(dev);
- mutex_unlock(&dev->pm_mutex);
return 0;
}
diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c
index 0c68e924a1cc..cfc12332bee1 100644
--- a/drivers/input/misc/cma3000_d0x.c
+++ b/drivers/input/misc/cma3000_d0x.c
@@ -217,15 +217,13 @@ static int cma3000_open(struct input_dev *input_dev)
{
struct cma3000_accl_data *data = input_get_drvdata(input_dev);
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
if (!data->suspended)
cma3000_poweron(data);
data->opened = true;
- mutex_unlock(&data->mutex);
-
return 0;
}
@@ -233,40 +231,34 @@ static void cma3000_close(struct input_dev *input_dev)
{
struct cma3000_accl_data *data = input_get_drvdata(input_dev);
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
if (!data->suspended)
cma3000_poweroff(data);
data->opened = false;
-
- mutex_unlock(&data->mutex);
}
void cma3000_suspend(struct cma3000_accl_data *data)
{
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
if (!data->suspended && data->opened)
cma3000_poweroff(data);
data->suspended = true;
-
- mutex_unlock(&data->mutex);
}
EXPORT_SYMBOL(cma3000_suspend);
void cma3000_resume(struct cma3000_accl_data *data)
{
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
if (data->suspended && data->opened)
cma3000_poweron(data);
data->suspended = false;
-
- mutex_unlock(&data->mutex);
}
EXPORT_SYMBOL(cma3000_resume);
diff --git a/drivers/input/misc/cs40l50-vibra.c b/drivers/input/misc/cs40l50-vibra.c
index 03bdb7c26ec0..dce3b0ec8cf3 100644
--- a/drivers/input/misc/cs40l50-vibra.c
+++ b/drivers/input/misc/cs40l50-vibra.c
@@ -334,11 +334,12 @@ static int cs40l50_add(struct input_dev *dev, struct ff_effect *effect,
work_data.custom_len = effect->u.periodic.custom_len;
work_data.vib = vib;
work_data.effect = effect;
- INIT_WORK(&work_data.work, cs40l50_add_worker);
+ INIT_WORK_ONSTACK(&work_data.work, cs40l50_add_worker);
/* Push to the workqueue to serialize with playbacks */
queue_work(vib->vib_wq, &work_data.work);
flush_work(&work_data.work);
+ destroy_work_on_stack(&work_data.work);
kfree(work_data.custom_data);
@@ -467,11 +468,12 @@ static int cs40l50_erase(struct input_dev *dev, int effect_id)
work_data.vib = vib;
work_data.effect = &dev->ff->effects[effect_id];
- INIT_WORK(&work_data.work, cs40l50_erase_worker);
+ INIT_WORK_ONSTACK(&work_data.work, cs40l50_erase_worker);
/* Push to workqueue to serialize with playbacks */
queue_work(vib->vib_wq, &work_data.work);
flush_work(&work_data.work);
+ destroy_work_on_stack(&work_data.work);
return work_data.error;
}
diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c
index 1629b7ea4cbd..e4a605c6af15 100644
--- a/drivers/input/misc/da7280.c
+++ b/drivers/input/misc/da7280.c
@@ -1263,39 +1263,37 @@ static int da7280_suspend(struct device *dev)
{
struct da7280_haptic *haptics = dev_get_drvdata(dev);
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
/*
* Make sure no new requests will be submitted while device is
* suspended.
*/
- spin_lock_irq(&haptics->input_dev->event_lock);
- haptics->suspended = true;
- spin_unlock_irq(&haptics->input_dev->event_lock);
+ scoped_guard(spinlock_irq, &haptics->input_dev->event_lock) {
+ haptics->suspended = true;
+ }
da7280_haptic_stop(haptics);
- mutex_unlock(&haptics->input_dev->mutex);
-
return 0;
}
static int da7280_resume(struct device *dev)
{
struct da7280_haptic *haptics = dev_get_drvdata(dev);
- int retval;
+ int error;
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
- retval = da7280_haptic_start(haptics);
- if (!retval) {
- spin_lock_irq(&haptics->input_dev->event_lock);
+ error = da7280_haptic_start(haptics);
+ if (error)
+ return error;
+
+ scoped_guard(spinlock_irq, &haptics->input_dev->event_lock) {
haptics->suspended = false;
- spin_unlock_irq(&haptics->input_dev->event_lock);
}
- mutex_unlock(&haptics->input_dev->mutex);
- return retval;
+ return 0;
}
#ifdef CONFIG_OF
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
index 7a1122e1efb9..cc23625019e3 100644
--- a/drivers/input/misc/da9052_onkey.c
+++ b/drivers/input/misc/da9052_onkey.c
@@ -140,8 +140,8 @@ static void da9052_onkey_remove(struct platform_device *pdev)
static struct platform_driver da9052_onkey_driver = {
.probe = da9052_onkey_probe,
- .remove_new = da9052_onkey_remove,
- .driver = {
+ .remove = da9052_onkey_remove,
+ .driver = {
.name = "da9052-onkey",
},
};
diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
index 871812f1b398..3e4fc2f01011 100644
--- a/drivers/input/misc/da9055_onkey.c
+++ b/drivers/input/misc/da9055_onkey.c
@@ -145,8 +145,8 @@ static void da9055_onkey_remove(struct platform_device *pdev)
static struct platform_driver da9055_onkey_driver = {
.probe = da9055_onkey_probe,
- .remove_new = da9055_onkey_remove,
- .driver = {
+ .remove = da9055_onkey_remove,
+ .driver = {
.name = "da9055-onkey",
},
};
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 61b503835aa6..96cd6a078c8a 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -537,64 +537,62 @@ static int drv260x_probe(struct i2c_client *client)
static int drv260x_suspend(struct device *dev)
{
struct drv260x_data *haptics = dev_get_drvdata(dev);
- int ret = 0;
+ int error;
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
if (input_device_enabled(haptics->input_dev)) {
- ret = regmap_update_bits(haptics->regmap,
- DRV260X_MODE,
- DRV260X_STANDBY_MASK,
- DRV260X_STANDBY);
- if (ret) {
+ error = regmap_update_bits(haptics->regmap,
+ DRV260X_MODE,
+ DRV260X_STANDBY_MASK,
+ DRV260X_STANDBY);
+ if (error) {
dev_err(dev, "Failed to set standby mode\n");
- goto out;
+ return error;
}
gpiod_set_value(haptics->enable_gpio, 0);
- ret = regulator_disable(haptics->regulator);
- if (ret) {
+ error = regulator_disable(haptics->regulator);
+ if (error) {
dev_err(dev, "Failed to disable regulator\n");
regmap_update_bits(haptics->regmap,
DRV260X_MODE,
DRV260X_STANDBY_MASK, 0);
+ return error;
}
}
-out:
- mutex_unlock(&haptics->input_dev->mutex);
- return ret;
+
+ return 0;
}
static int drv260x_resume(struct device *dev)
{
struct drv260x_data *haptics = dev_get_drvdata(dev);
- int ret = 0;
+ int error;
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
if (input_device_enabled(haptics->input_dev)) {
- ret = regulator_enable(haptics->regulator);
- if (ret) {
+ error = regulator_enable(haptics->regulator);
+ if (error) {
dev_err(dev, "Failed to enable regulator\n");
- goto out;
+ return error;
}
- ret = regmap_update_bits(haptics->regmap,
- DRV260X_MODE,
- DRV260X_STANDBY_MASK, 0);
- if (ret) {
+ error = regmap_update_bits(haptics->regmap,
+ DRV260X_MODE,
+ DRV260X_STANDBY_MASK, 0);
+ if (error) {
dev_err(dev, "Failed to unset standby mode\n");
regulator_disable(haptics->regulator);
- goto out;
+ return error;
}
gpiod_set_value(haptics->enable_gpio, 1);
}
-out:
- mutex_unlock(&haptics->input_dev->mutex);
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume);
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index f98e4d765307..46842cb8ddd7 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -15,7 +15,7 @@
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
-/* Contol registers */
+/* Control registers */
#define DRV2665_STATUS 0x00
#define DRV2665_CTRL_1 0x01
#define DRV2665_CTRL_2 0x02
@@ -225,59 +225,57 @@ static int drv2665_probe(struct i2c_client *client)
static int drv2665_suspend(struct device *dev)
{
struct drv2665_data *haptics = dev_get_drvdata(dev);
- int ret = 0;
+ int error;
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
if (input_device_enabled(haptics->input_dev)) {
- ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
- DRV2665_STANDBY, DRV2665_STANDBY);
- if (ret) {
+ error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
+ DRV2665_STANDBY, DRV2665_STANDBY);
+ if (error) {
dev_err(dev, "Failed to set standby mode\n");
regulator_disable(haptics->regulator);
- goto out;
+ return error;
}
- ret = regulator_disable(haptics->regulator);
- if (ret) {
+ error = regulator_disable(haptics->regulator);
+ if (error) {
dev_err(dev, "Failed to disable regulator\n");
regmap_update_bits(haptics->regmap,
DRV2665_CTRL_2,
DRV2665_STANDBY, 0);
+ return error;
}
}
-out:
- mutex_unlock(&haptics->input_dev->mutex);
- return ret;
+
+ return 0;
}
static int drv2665_resume(struct device *dev)
{
struct drv2665_data *haptics = dev_get_drvdata(dev);
- int ret = 0;
+ int error;
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
if (input_device_enabled(haptics->input_dev)) {
- ret = regulator_enable(haptics->regulator);
- if (ret) {
+ error = regulator_enable(haptics->regulator);
+ if (error) {
dev_err(dev, "Failed to enable regulator\n");
- goto out;
+ return error;
}
- ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
- DRV2665_STANDBY, 0);
- if (ret) {
+ error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
+ DRV2665_STANDBY, 0);
+ if (error) {
dev_err(dev, "Failed to unset standby mode\n");
regulator_disable(haptics->regulator);
- goto out;
+ return error;
}
}
-out:
- mutex_unlock(&haptics->input_dev->mutex);
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume);
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index ad49845374b9..f952a24ec595 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -16,7 +16,7 @@
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
-/* Contol registers */
+/* Control registers */
#define DRV2667_STATUS 0x00
#define DRV2667_CTRL_1 0x01
#define DRV2667_CTRL_2 0x02
@@ -402,59 +402,57 @@ static int drv2667_probe(struct i2c_client *client)
static int drv2667_suspend(struct device *dev)
{
struct drv2667_data *haptics = dev_get_drvdata(dev);
- int ret = 0;
+ int error;
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
if (input_device_enabled(haptics->input_dev)) {
- ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
- DRV2667_STANDBY, DRV2667_STANDBY);
- if (ret) {
+ error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
+ DRV2667_STANDBY, DRV2667_STANDBY);
+ if (error) {
dev_err(dev, "Failed to set standby mode\n");
regulator_disable(haptics->regulator);
- goto out;
+ return error;
}
- ret = regulator_disable(haptics->regulator);
- if (ret) {
+ error = regulator_disable(haptics->regulator);
+ if (error) {
dev_err(dev, "Failed to disable regulator\n");
regmap_update_bits(haptics->regmap,
DRV2667_CTRL_2,
DRV2667_STANDBY, 0);
+ return error;
}
}
-out:
- mutex_unlock(&haptics->input_dev->mutex);
- return ret;
+
+ return 0;
}
static int drv2667_resume(struct device *dev)
{
struct drv2667_data *haptics = dev_get_drvdata(dev);
- int ret = 0;
+ int error;
- mutex_lock(&haptics->input_dev->mutex);
+ guard(mutex)(&haptics->input_dev->mutex);
if (input_device_enabled(haptics->input_dev)) {
- ret = regulator_enable(haptics->regulator);
- if (ret) {
+ error = regulator_enable(haptics->regulator);
+ if (error) {
dev_err(dev, "Failed to enable regulator\n");
- goto out;
+ return error;
}
- ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
- DRV2667_STANDBY, 0);
- if (ret) {
+ error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
+ DRV2667_STANDBY, 0);
+ if (error) {
dev_err(dev, "Failed to unset standby mode\n");
regulator_disable(haptics->regulator);
- goto out;
+ return error;
}
}
-out:
- mutex_unlock(&haptics->input_dev->mutex);
- return ret;
+ return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c
index 867ac7aa10d2..aa48f62d7ea0 100644
--- a/drivers/input/misc/ibm-panel.c
+++ b/drivers/input/misc/ibm-panel.c
@@ -77,12 +77,11 @@ static void ibm_panel_process_command(struct ibm_panel *panel)
static int ibm_panel_i2c_slave_cb(struct i2c_client *client,
enum i2c_slave_event event, u8 *val)
{
- unsigned long flags;
struct ibm_panel *panel = i2c_get_clientdata(client);
dev_dbg(&panel->input->dev, "event: %u data: %02x\n", event, *val);
- spin_lock_irqsave(&panel->lock, flags);
+ guard(spinlock_irqsave)(&panel->lock);
switch (event) {
case I2C_SLAVE_STOP:
@@ -114,8 +113,6 @@ static int ibm_panel_i2c_slave_cb(struct i2c_client *client,
break;
}
- spin_unlock_irqrestore(&panel->lock, flags);
-
return 0;
}
diff --git a/drivers/input/misc/ideapad_slidebar.c b/drivers/input/misc/ideapad_slidebar.c
index fa4e7f67d713..f6e5fc807b4d 100644
--- a/drivers/input/misc/ideapad_slidebar.c
+++ b/drivers/input/misc/ideapad_slidebar.c
@@ -23,7 +23,7 @@
*
* The value is in byte range, however, I only figured out
* how bits 0b10011001 work. Some other bits, probably,
- * are meaningfull too.
+ * are meaningful too.
*
* Possible states:
*
@@ -95,41 +95,29 @@ static struct platform_device *slidebar_platform_dev;
static u8 slidebar_pos_get(void)
{
- u8 res;
- unsigned long flags;
+ guard(spinlock_irqsave)(&io_lock);
- spin_lock_irqsave(&io_lock, flags);
outb(0xf4, 0xff29);
outb(0xbf, 0xff2a);
- res = inb(0xff2b);
- spin_unlock_irqrestore(&io_lock, flags);
-
- return res;
+ return inb(0xff2b);
}
static u8 slidebar_mode_get(void)
{
- u8 res;
- unsigned long flags;
+ guard(spinlock_irqsave)(&io_lock);
- spin_lock_irqsave(&io_lock, flags);
outb(0xf7, 0xff29);
outb(0x8b, 0xff2a);
- res = inb(0xff2b);
- spin_unlock_irqrestore(&io_lock, flags);
-
- return res;
+ return inb(0xff2b);
}
static void slidebar_mode_set(u8 mode)
{
- unsigned long flags;
+ guard(spinlock_irqsave)(&io_lock);
- spin_lock_irqsave(&io_lock, flags);
outb(0xf7, 0xff29);
outb(0x8b, 0xff2a);
outb(mode, 0xff2b);
- spin_unlock_irqrestore(&io_lock, flags);
}
static bool slidebar_i8042_filter(unsigned char data, unsigned char str,
@@ -267,7 +255,7 @@ static struct platform_driver slidebar_drv = {
.driver = {
.name = "ideapad_slidebar",
},
- .remove_new = ideapad_remove,
+ .remove = ideapad_remove,
};
static int __init ideapad_dmi_check(const struct dmi_system_id *id)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 4215f9b9c2b0..d9ee14b1f451 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -739,7 +739,7 @@ static int ims_pcu_switch_to_bootloader(struct ims_pcu *pcu)
{
int error;
- /* Execute jump to the bootoloader */
+ /* Execute jump to the bootloader */
error = ims_pcu_execute_command(pcu, JUMP_TO_BTLDR, NULL, 0);
if (error) {
dev_err(pcu->dev,
diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c
index 843f8a3f3410..1851848e2cd3 100644
--- a/drivers/input/misc/iqs269a.c
+++ b/drivers/input/misc/iqs269a.c
@@ -365,7 +365,7 @@ static int iqs269_ati_mode_set(struct iqs269_private *iqs269,
if (mode > IQS269_CHx_ENG_A_ATI_MODE_MAX)
return -EINVAL;
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
engine_a = be16_to_cpu(ch_reg[ch_num].engine_a);
@@ -375,8 +375,6 @@ static int iqs269_ati_mode_set(struct iqs269_private *iqs269,
ch_reg[ch_num].engine_a = cpu_to_be16(engine_a);
iqs269->ati_current = false;
- mutex_unlock(&iqs269->lock);
-
return 0;
}
@@ -389,9 +387,9 @@ static int iqs269_ati_mode_get(struct iqs269_private *iqs269,
if (ch_num >= IQS269_NUM_CH)
return -EINVAL;
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
+
engine_a = be16_to_cpu(ch_reg[ch_num].engine_a);
- mutex_unlock(&iqs269->lock);
engine_a &= IQS269_CHx_ENG_A_ATI_MODE_MASK;
*mode = (engine_a >> IQS269_CHx_ENG_A_ATI_MODE_SHIFT);
@@ -429,7 +427,7 @@ static int iqs269_ati_base_set(struct iqs269_private *iqs269,
return -EINVAL;
}
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
engine_b = be16_to_cpu(ch_reg[ch_num].engine_b);
@@ -439,8 +437,6 @@ static int iqs269_ati_base_set(struct iqs269_private *iqs269,
ch_reg[ch_num].engine_b = cpu_to_be16(engine_b);
iqs269->ati_current = false;
- mutex_unlock(&iqs269->lock);
-
return 0;
}
@@ -453,9 +449,9 @@ static int iqs269_ati_base_get(struct iqs269_private *iqs269,
if (ch_num >= IQS269_NUM_CH)
return -EINVAL;
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
+
engine_b = be16_to_cpu(ch_reg[ch_num].engine_b);
- mutex_unlock(&iqs269->lock);
switch (engine_b & IQS269_CHx_ENG_B_ATI_BASE_MASK) {
case IQS269_CHx_ENG_B_ATI_BASE_75:
@@ -491,7 +487,7 @@ static int iqs269_ati_target_set(struct iqs269_private *iqs269,
if (target > IQS269_CHx_ENG_B_ATI_TARGET_MAX)
return -EINVAL;
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
engine_b = be16_to_cpu(ch_reg[ch_num].engine_b);
@@ -501,8 +497,6 @@ static int iqs269_ati_target_set(struct iqs269_private *iqs269,
ch_reg[ch_num].engine_b = cpu_to_be16(engine_b);
iqs269->ati_current = false;
- mutex_unlock(&iqs269->lock);
-
return 0;
}
@@ -515,10 +509,9 @@ static int iqs269_ati_target_get(struct iqs269_private *iqs269,
if (ch_num >= IQS269_NUM_CH)
return -EINVAL;
- mutex_lock(&iqs269->lock);
- engine_b = be16_to_cpu(ch_reg[ch_num].engine_b);
- mutex_unlock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
+ engine_b = be16_to_cpu(ch_reg[ch_num].engine_b);
*target = (engine_b & IQS269_CHx_ENG_B_ATI_TARGET_MASK) * 32;
return 0;
@@ -557,7 +550,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
const struct fwnode_handle *ch_node)
{
struct i2c_client *client = iqs269->client;
- struct fwnode_handle *ev_node;
struct iqs269_ch_reg *ch_reg;
u16 engine_a, engine_b;
unsigned int reg, val;
@@ -734,8 +726,9 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
}
for (i = 0; i < ARRAY_SIZE(iqs269_events); i++) {
- ev_node = fwnode_get_named_child_node(ch_node,
- iqs269_events[i].name);
+ struct fwnode_handle *ev_node __free(fwnode_handle) =
+ fwnode_get_named_child_node(ch_node,
+ iqs269_events[i].name);
if (!ev_node)
continue;
@@ -744,7 +737,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
dev_err(&client->dev,
"Invalid channel %u threshold: %u\n",
reg, val);
- fwnode_handle_put(ev_node);
return -EINVAL;
}
@@ -758,7 +750,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
dev_err(&client->dev,
"Invalid channel %u hysteresis: %u\n",
reg, val);
- fwnode_handle_put(ev_node);
return -EINVAL;
}
@@ -774,7 +765,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,
}
error = fwnode_property_read_u32(ev_node, "linux,code", &val);
- fwnode_handle_put(ev_node);
if (error == -EINVAL) {
continue;
} else if (error) {
@@ -1199,7 +1189,7 @@ static int iqs269_dev_init(struct iqs269_private *iqs269)
{
int error;
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
/*
* Early revisions of silicon require the following workaround in order
@@ -1210,19 +1200,19 @@ static int iqs269_dev_init(struct iqs269_private *iqs269)
error = regmap_multi_reg_write(iqs269->regmap, iqs269_tws_init,
ARRAY_SIZE(iqs269_tws_init));
if (error)
- goto err_mutex;
+ return error;
}
error = regmap_update_bits(iqs269->regmap, IQS269_HALL_UI,
IQS269_HALL_UI_ENABLE,
iqs269->hall_enable ? ~0 : 0);
if (error)
- goto err_mutex;
+ return error;
error = regmap_raw_write(iqs269->regmap, IQS269_SYS_SETTINGS,
&iqs269->sys_reg, sizeof(iqs269->sys_reg));
if (error)
- goto err_mutex;
+ return error;
/*
* The following delay gives the device time to deassert its RDY output
@@ -1232,10 +1222,7 @@ static int iqs269_dev_init(struct iqs269_private *iqs269)
iqs269->ati_current = true;
-err_mutex:
- mutex_unlock(&iqs269->lock);
-
- return error;
+ return 0;
}
static int iqs269_input_init(struct iqs269_private *iqs269)
@@ -1580,13 +1567,11 @@ static ssize_t hall_enable_store(struct device *dev,
if (error)
return error;
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
iqs269->hall_enable = val;
iqs269->ati_current = false;
- mutex_unlock(&iqs269->lock);
-
return count;
}
@@ -1643,13 +1628,11 @@ static ssize_t rx_enable_store(struct device *dev,
if (val > 0xFF)
return -EINVAL;
- mutex_lock(&iqs269->lock);
+ guard(mutex)(&iqs269->lock);
ch_reg[iqs269->ch_num].rx_enable = val;
iqs269->ati_current = false;
- mutex_unlock(&iqs269->lock);
-
return count;
}
diff --git a/drivers/input/misc/iqs626a.c b/drivers/input/misc/iqs626a.c
index 0dab54d3a060..7a6e6927f331 100644
--- a/drivers/input/misc/iqs626a.c
+++ b/drivers/input/misc/iqs626a.c
@@ -462,7 +462,6 @@ iqs626_parse_events(struct iqs626_private *iqs626,
{
struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg;
struct i2c_client *client = iqs626->client;
- struct fwnode_handle *ev_node;
const char *ev_name;
u8 *thresh, *hyst;
unsigned int val;
@@ -501,6 +500,7 @@ iqs626_parse_events(struct iqs626_private *iqs626,
if (!iqs626_channels[ch_id].events[i])
continue;
+ struct fwnode_handle *ev_node __free(fwnode_handle) = NULL;
if (ch_id == IQS626_CH_TP_2 || ch_id == IQS626_CH_TP_3) {
/*
* Trackpad touch events are simply described under the
@@ -530,7 +530,6 @@ iqs626_parse_events(struct iqs626_private *iqs626,
dev_err(&client->dev,
"Invalid input type: %u\n",
val);
- fwnode_handle_put(ev_node);
return -EINVAL;
}
@@ -545,7 +544,6 @@ iqs626_parse_events(struct iqs626_private *iqs626,
dev_err(&client->dev,
"Invalid %s channel hysteresis: %u\n",
fwnode_get_name(ch_node), val);
- fwnode_handle_put(ev_node);
return -EINVAL;
}
@@ -566,7 +564,6 @@ iqs626_parse_events(struct iqs626_private *iqs626,
dev_err(&client->dev,
"Invalid %s channel threshold: %u\n",
fwnode_get_name(ch_node), val);
- fwnode_handle_put(ev_node);
return -EINVAL;
}
@@ -575,8 +572,6 @@ iqs626_parse_events(struct iqs626_private *iqs626,
else
*(thresh + iqs626_events[i].th_offs) = val;
}
-
- fwnode_handle_put(ev_node);
}
return 0;
@@ -774,12 +769,12 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626,
for (i = 0; i < iqs626_channels[ch_id].num_ch; i++) {
u8 *ati_base = &sys_reg->tp_grp_reg.ch_reg_tp[i].ati_base;
u8 *thresh = &sys_reg->tp_grp_reg.ch_reg_tp[i].thresh;
- struct fwnode_handle *tc_node;
char tc_name[10];
snprintf(tc_name, sizeof(tc_name), "channel-%d", i);
- tc_node = fwnode_get_named_child_node(ch_node, tc_name);
+ struct fwnode_handle *tc_node __free(fwnode_handle) =
+ fwnode_get_named_child_node(ch_node, tc_name);
if (!tc_node)
continue;
@@ -790,7 +785,6 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626,
dev_err(&client->dev,
"Invalid %s %s ATI base: %u\n",
fwnode_get_name(ch_node), tc_name, val);
- fwnode_handle_put(tc_node);
return -EINVAL;
}
@@ -803,14 +797,11 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626,
dev_err(&client->dev,
"Invalid %s %s threshold: %u\n",
fwnode_get_name(ch_node), tc_name, val);
- fwnode_handle_put(tc_node);
return -EINVAL;
}
*thresh = val;
}
-
- fwnode_handle_put(tc_node);
}
if (!fwnode_property_present(ch_node, "linux,keycodes"))
@@ -1233,7 +1224,6 @@ static int iqs626_parse_prop(struct iqs626_private *iqs626)
{
struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg;
struct i2c_client *client = iqs626->client;
- struct fwnode_handle *ch_node;
unsigned int val;
int error, i;
u16 general;
@@ -1375,13 +1365,13 @@ static int iqs626_parse_prop(struct iqs626_private *iqs626)
sys_reg->active = 0;
for (i = 0; i < ARRAY_SIZE(iqs626_channels); i++) {
- ch_node = device_get_named_child_node(&client->dev,
- iqs626_channels[i].name);
+ struct fwnode_handle *ch_node __free(fwnode_handle) =
+ device_get_named_child_node(&client->dev,
+ iqs626_channels[i].name);
if (!ch_node)
continue;
error = iqs626_parse_channel(iqs626, ch_node, i);
- fwnode_handle_put(ch_node);
if (error)
return error;
diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
index be80a31de9f8..22022d11470d 100644
--- a/drivers/input/misc/iqs7222.c
+++ b/drivers/input/misc/iqs7222.c
@@ -2385,9 +2385,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
for (i = 0; i < ARRAY_SIZE(iqs7222_kp_events); i++) {
const char *event_name = iqs7222_kp_events[i].name;
u16 event_enable = iqs7222_kp_events[i].enable;
- struct fwnode_handle *event_node;
- event_node = fwnode_get_named_child_node(chan_node, event_name);
+ struct fwnode_handle *event_node __free(fwnode_handle) =
+ fwnode_get_named_child_node(chan_node, event_name);
if (!event_node)
continue;
@@ -2408,7 +2408,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
dev_err(&client->dev,
"Invalid %s press timeout: %u\n",
fwnode_get_name(event_node), val);
- fwnode_handle_put(event_node);
return -EINVAL;
}
@@ -2418,7 +2417,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
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;
}
@@ -2429,7 +2427,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
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;
@@ -2604,10 +2601,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
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);
+ struct fwnode_handle *event_node __free(fwnode_handle) =
+ fwnode_get_named_child_node(sldr_node, event_name);
if (!event_node)
continue;
@@ -2639,7 +2636,6 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
: sldr_setup[4 + reg_offset],
NULL,
&iqs7222->sl_code[sldr_index][i]);
- fwnode_handle_put(event_node);
if (error)
return error;
@@ -2742,9 +2738,9 @@ static int iqs7222_parse_tpad(struct iqs7222_private *iqs7222,
for (i = 0; i < ARRAY_SIZE(iqs7222_tp_events); i++) {
const char *event_name = iqs7222_tp_events[i].name;
- struct fwnode_handle *event_node;
- event_node = fwnode_get_named_child_node(tpad_node, event_name);
+ struct fwnode_handle *event_node __free(fwnode_handle) =
+ fwnode_get_named_child_node(tpad_node, event_name);
if (!event_node)
continue;
@@ -2760,7 +2756,6 @@ static int iqs7222_parse_tpad(struct iqs7222_private *iqs7222,
iqs7222_tp_events[i].link, 1566,
NULL,
&iqs7222->tp_code[i]);
- fwnode_handle_put(event_node);
if (error)
return error;
@@ -2818,9 +2813,9 @@ static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222,
int reg_grp_index)
{
struct i2c_client *client = iqs7222->client;
- struct fwnode_handle *reg_grp_node;
int error;
+ struct fwnode_handle *reg_grp_node __free(fwnode_handle) = NULL;
if (iqs7222_reg_grp_names[reg_grp]) {
char reg_grp_name[16];
@@ -2838,14 +2833,17 @@ static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222,
error = iqs7222_parse_props(iqs7222, reg_grp_node, reg_grp_index,
reg_grp, IQS7222_REG_KEY_NONE);
+ if (error)
+ return error;
- if (!error && iqs7222_parse_extra[reg_grp])
+ if (iqs7222_parse_extra[reg_grp]) {
error = iqs7222_parse_extra[reg_grp](iqs7222, reg_grp_node,
reg_grp_index);
+ if (error)
+ return error;
+ }
- fwnode_handle_put(reg_grp_node);
-
- return error;
+ return 0;
}
static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 837682cb2a7d..eb9788ea5215 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -25,7 +25,7 @@
/* CONTROL REGISTER 1 BITS */
#define PC1_OFF 0x7F
#define PC1_ON (1 << 7)
-/* Data ready funtion enable bit: set during probe if using irq mode */
+/* Data ready function enable bit: set during probe if using irq mode */
#define DRDYE (1 << 5)
/* DATA CONTROL REGISTER BITS */
#define ODR12_5F 0
@@ -314,9 +314,8 @@ static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr,
return error;
/* Lock the device to prevent races with open/close (and itself) */
- mutex_lock(&input_dev->mutex);
-
- disable_irq(client->irq);
+ guard(mutex)(&input_dev->mutex);
+ guard(disable_irq)(&client->irq);
/*
* Set current interval to the greater of the minimum interval or
@@ -326,9 +325,6 @@ static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr,
kxtj9_update_odr(tj9, tj9->last_poll_interval);
- enable_irq(client->irq);
- mutex_unlock(&input_dev->mutex);
-
return count;
}
@@ -504,12 +500,11 @@ static int kxtj9_suspend(struct device *dev)
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
struct input_dev *input_dev = tj9->input_dev;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev))
kxtj9_disable(tj9);
- mutex_unlock(&input_dev->mutex);
return 0;
}
@@ -519,12 +514,11 @@ static int kxtj9_resume(struct device *dev)
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
struct input_dev *input_dev = tj9->input_dev;
- mutex_lock(&input_dev->mutex);
+ guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev))
kxtj9_enable(tj9);
- mutex_unlock(&input_dev->mutex);
return 0;
}
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 3fe0a85c45e0..0542334df624 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -95,7 +95,7 @@ static struct platform_driver m68kspkr_platform_driver = {
.name = "m68kspkr",
},
.probe = m68kspkr_probe,
- .remove_new = m68kspkr_remove,
+ .remove = m68kspkr_remove,
.shutdown = m68kspkr_shutdown,
};
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index 11cac4b7dddc..f97f341ee0bb 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -153,19 +153,19 @@ static void max8997_haptic_enable(struct max8997_haptic *chip)
{
int error;
- mutex_lock(&chip->mutex);
+ guard(mutex)(&chip->mutex);
error = max8997_haptic_set_duty_cycle(chip);
if (error) {
dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error);
- goto out;
+ return;
}
if (!chip->enabled) {
error = regulator_enable(chip->regulator);
if (error) {
dev_err(chip->dev, "Failed to enable regulator\n");
- goto out;
+ return;
}
max8997_haptic_configure(chip);
if (chip->mode == MAX8997_EXTERNAL_MODE) {
@@ -173,19 +173,16 @@ static void max8997_haptic_enable(struct max8997_haptic *chip)
if (error) {
dev_err(chip->dev, "Failed to enable PWM\n");
regulator_disable(chip->regulator);
- goto out;
+ return;
}
}
chip->enabled = true;
}
-
-out:
- mutex_unlock(&chip->mutex);
}
static void max8997_haptic_disable(struct max8997_haptic *chip)
{
- mutex_lock(&chip->mutex);
+ guard(mutex)(&chip->mutex);
if (chip->enabled) {
chip->enabled = false;
@@ -194,8 +191,6 @@ static void max8997_haptic_disable(struct max8997_haptic *chip)
pwm_disable(chip->pwm);
regulator_disable(chip->regulator);
}
-
- mutex_unlock(&chip->mutex);
}
static void max8997_haptic_play_effect_work(struct work_struct *work)
@@ -389,7 +384,7 @@ static struct platform_driver max8997_haptic_driver = {
.pm = pm_sleep_ptr(&max8997_haptic_pm_ops),
},
.probe = max8997_haptic_probe,
- .remove_new = max8997_haptic_remove,
+ .remove = max8997_haptic_remove,
.id_table = max8997_haptic_id,
};
module_platform_driver(max8997_haptic_driver);
diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
index 1c8c939638f6..1c7faa9b7afe 100644
--- a/drivers/input/misc/mc13783-pwrbutton.c
+++ b/drivers/input/misc/mc13783-pwrbutton.c
@@ -253,7 +253,7 @@ static void mc13783_pwrbutton_remove(struct platform_device *pdev)
static struct platform_driver mc13783_pwrbutton_driver = {
.probe = mc13783_pwrbutton_probe,
- .remove_new = mc13783_pwrbutton_remove,
+ .remove = mc13783_pwrbutton_remove,
.driver = {
.name = "mc13783-pwrbutton",
},
diff --git a/drivers/input/misc/palmas-pwrbutton.c b/drivers/input/misc/palmas-pwrbutton.c
index 06d5972e8e84..39fc451c56e9 100644
--- a/drivers/input/misc/palmas-pwrbutton.c
+++ b/drivers/input/misc/palmas-pwrbutton.c
@@ -310,7 +310,7 @@ MODULE_DEVICE_TABLE(of, of_palmas_pwr_match);
static struct platform_driver palmas_pwron_driver = {
.probe = palmas_pwron_probe,
- .remove_new = palmas_pwron_remove,
+ .remove = palmas_pwron_remove,
.driver = {
.name = "palmas_pwrbutton",
.of_match_table = of_match_ptr(of_palmas_pwr_match),
diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
index f8954a2cab24..fe43fd72ba7b 100644
--- a/drivers/input/misc/pcap_keys.c
+++ b/drivers/input/misc/pcap_keys.c
@@ -112,7 +112,7 @@ static void pcap_keys_remove(struct platform_device *pdev)
static struct platform_driver pcap_keys_device_driver = {
.probe = pcap_keys_probe,
- .remove_new = pcap_keys_remove,
+ .remove = pcap_keys_remove,
.driver = {
.name = "pcap-keys",
}
diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
index c5c5fe236c18..6d046e236ba6 100644
--- a/drivers/input/misc/pcf50633-input.c
+++ b/drivers/input/misc/pcf50633-input.c
@@ -103,7 +103,7 @@ static struct platform_driver pcf50633_input_driver = {
.name = "pcf50633-input",
},
.probe = pcf50633_input_probe,
- .remove_new = pcf50633_input_remove,
+ .remove = pcf50633_input_remove,
};
module_platform_driver(pcf50633_input_driver);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 897854fd245f..0467808402f2 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -127,7 +127,7 @@ static struct platform_driver pcspkr_platform_driver = {
.pm = &pcspkr_pm_ops,
},
.probe = pcspkr_probe,
- .remove_new = pcspkr_remove,
+ .remove = pcspkr_remove,
.shutdown = pcspkr_shutdown,
};
module_platform_driver(pcspkr_platform_driver);
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
index bab710023d8f..d0c46665e527 100644
--- a/drivers/input/misc/pm8941-pwrkey.c
+++ b/drivers/input/misc/pm8941-pwrkey.c
@@ -465,7 +465,7 @@ MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
static struct platform_driver pm8941_pwrkey_driver = {
.probe = pm8941_pwrkey_probe,
- .remove_new = pm8941_pwrkey_remove,
+ .remove = pm8941_pwrkey_remove,
.driver = {
.name = "pm8941-pwrkey",
.pm = pm_sleep_ptr(&pm8941_pwr_key_pm_ops),
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 4b039abffc4b..ecb92ee5ebbc 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -194,22 +194,18 @@ static void powermate_sync_state(struct powermate_device *pm)
static void powermate_config_complete(struct urb *urb)
{
struct powermate_device *pm = urb->context;
- unsigned long flags;
if (urb->status)
printk(KERN_ERR "powermate: config urb returned %d\n", urb->status);
- spin_lock_irqsave(&pm->lock, flags);
+ guard(spinlock_irqsave)(&pm->lock);
powermate_sync_state(pm);
- spin_unlock_irqrestore(&pm->lock, flags);
}
/* Set the LED up as described and begin the sync with the hardware if required */
static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed,
int pulse_table, int pulse_asleep, int pulse_awake)
{
- unsigned long flags;
-
if (pulse_speed < 0)
pulse_speed = 0;
if (pulse_table < 0)
@@ -222,8 +218,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne
pulse_asleep = !!pulse_asleep;
pulse_awake = !!pulse_awake;
-
- spin_lock_irqsave(&pm->lock, flags);
+ guard(spinlock_irqsave)(&pm->lock);
/* mark state updates which are required */
if (static_brightness != pm->static_brightness) {
@@ -245,8 +240,6 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne
}
powermate_sync_state(pm);
-
- spin_unlock_irqrestore(&pm->lock, flags);
}
/* Callback from the Input layer when an event arrives from userspace to configure the LED */
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index 5b9aedf4362f..0e19e97d98ec 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -203,9 +203,9 @@ static int pwm_beeper_suspend(struct device *dev)
* beeper->suspended, but to ensure that pwm_beeper_event
* does not re-submit work once flag is set.
*/
- spin_lock_irq(&beeper->input->event_lock);
- beeper->suspended = true;
- spin_unlock_irq(&beeper->input->event_lock);
+ scoped_guard(spinlock_irq, &beeper->input->event_lock) {
+ beeper->suspended = true;
+ }
pwm_beeper_stop(beeper);
@@ -216,9 +216,9 @@ static int pwm_beeper_resume(struct device *dev)
{
struct pwm_beeper *beeper = dev_get_drvdata(dev);
- spin_lock_irq(&beeper->input->event_lock);
- beeper->suspended = false;
- spin_unlock_irq(&beeper->input->event_lock);
+ scoped_guard(spinlock_irq, &beeper->input->event_lock) {
+ beeper->suspended = false;
+ }
/* Let worker figure out if we should resume beeping */
schedule_work(&beeper->work);
diff --git a/drivers/input/misc/regulator-haptic.c b/drivers/input/misc/regulator-haptic.c
index 02f73b7c0462..3666ba6d1f30 100644
--- a/drivers/input/misc/regulator-haptic.c
+++ b/drivers/input/misc/regulator-haptic.c
@@ -83,12 +83,10 @@ static void regulator_haptic_work(struct work_struct *work)
struct regulator_haptic *haptic = container_of(work,
struct regulator_haptic, work);
- mutex_lock(&haptic->mutex);
+ guard(mutex)(&haptic->mutex);
if (!haptic->suspended)
regulator_haptic_set_voltage(haptic, haptic->magnitude);
-
- mutex_unlock(&haptic->mutex);
}
static int regulator_haptic_play_effect(struct input_dev *input, void *data,
@@ -205,19 +203,15 @@ static int regulator_haptic_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct regulator_haptic *haptic = platform_get_drvdata(pdev);
- int error;
- error = mutex_lock_interruptible(&haptic->mutex);
- if (error)
- return error;
-
- regulator_haptic_set_voltage(haptic, 0);
+ scoped_guard(mutex_intr, &haptic->mutex) {
+ regulator_haptic_set_voltage(haptic, 0);
+ haptic->suspended = true;
- haptic->suspended = true;
-
- mutex_unlock(&haptic->mutex);
+ return 0;
+ }
- return 0;
+ return -EINTR;
}
static int regulator_haptic_resume(struct device *dev)
@@ -226,7 +220,7 @@ static int regulator_haptic_resume(struct device *dev)
struct regulator_haptic *haptic = platform_get_drvdata(pdev);
unsigned int magnitude;
- mutex_lock(&haptic->mutex);
+ guard(mutex)(&haptic->mutex);
haptic->suspended = false;
@@ -234,8 +228,6 @@ static int regulator_haptic_resume(struct device *dev)
if (magnitude)
regulator_haptic_set_voltage(haptic, magnitude);
- mutex_unlock(&haptic->mutex);
-
return 0;
}
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index e94cab8133be..f706e1997417 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -106,7 +106,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
struct rotary_encoder *encoder = dev_id;
unsigned int state;
- mutex_lock(&encoder->access_mutex);
+ guard(mutex)(&encoder->access_mutex);
state = rotary_encoder_get_state(encoder);
@@ -129,8 +129,6 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
break;
}
- mutex_unlock(&encoder->access_mutex);
-
return IRQ_HANDLED;
}
@@ -139,7 +137,7 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
struct rotary_encoder *encoder = dev_id;
unsigned int state;
- mutex_lock(&encoder->access_mutex);
+ guard(mutex)(&encoder->access_mutex);
state = rotary_encoder_get_state(encoder);
@@ -152,8 +150,6 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
}
}
- mutex_unlock(&encoder->access_mutex);
-
return IRQ_HANDLED;
}
@@ -162,22 +158,19 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
struct rotary_encoder *encoder = dev_id;
unsigned int state;
- mutex_lock(&encoder->access_mutex);
+ guard(mutex)(&encoder->access_mutex);
state = rotary_encoder_get_state(encoder);
- if ((encoder->last_stable + 1) % 4 == state)
+ if ((encoder->last_stable + 1) % 4 == state) {
encoder->dir = 1;
- else if (encoder->last_stable == (state + 1) % 4)
+ rotary_encoder_report_event(encoder);
+ } else if (encoder->last_stable == (state + 1) % 4) {
encoder->dir = -1;
- else
- goto out;
-
- rotary_encoder_report_event(encoder);
+ rotary_encoder_report_event(encoder);
+ }
-out:
encoder->last_stable = state;
- mutex_unlock(&encoder->access_mutex);
return IRQ_HANDLED;
}
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 5c5d407fe965..b8cad415c62c 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -515,7 +515,7 @@ static const struct soc_device_data soc_device_INT33D3 = {
};
/*
- * Button info for Microsoft Surface 3 (non pro), this is indentical to
+ * Button info for Microsoft Surface 3 (non pro), this is identical to
* the PNP0C40 info except that the home button is active-high.
*
* The Surface 3 Pro also has a MSHW0028 ACPI device, but that uses a custom
@@ -612,7 +612,7 @@ MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match);
static struct platform_driver soc_button_driver = {
.probe = soc_button_probe,
- .remove_new = soc_button_remove,
+ .remove = soc_button_remove,
.driver = {
.name = KBUILD_MODNAME,
.acpi_match_table = ACPI_PTR(soc_button_acpi_match),
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 20020cbc0752..8d7303fc13bc 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -69,7 +69,6 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
struct bbc_beep_info *info = &state->u.bbc;
unsigned int count = 0;
- unsigned long flags;
if (type != EV_SND)
return -1;
@@ -85,7 +84,7 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
count = bbc_count_to_reg(info, count);
- spin_lock_irqsave(&state->lock, flags);
+ guard(spinlock_irqsave)(&state->lock);
if (count) {
sbus_writeb(0x01, info->regs + 0);
@@ -97,8 +96,6 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
sbus_writeb(0x00, info->regs + 0);
}
- spin_unlock_irqrestore(&state->lock, flags);
-
return 0;
}
@@ -107,7 +104,6 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
struct grover_beep_info *info = &state->u.grover;
unsigned int count = 0;
- unsigned long flags;
if (type != EV_SND)
return -1;
@@ -121,7 +117,7 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
if (value > 20 && value < 32767)
count = 1193182 / value;
- spin_lock_irqsave(&state->lock, flags);
+ guard(spinlock_irqsave)(&state->lock);
if (count) {
/* enable counter 2 */
@@ -136,8 +132,6 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
sbus_writeb(sbus_readb(info->enable_reg) & 0xFC, info->enable_reg);
}
- spin_unlock_irqrestore(&state->lock, flags);
-
return 0;
}
@@ -188,47 +182,38 @@ static int bbc_beep_probe(struct platform_device *op)
{
struct sparcspkr_state *state;
struct bbc_beep_info *info;
- struct device_node *dp;
- int err = -ENOMEM;
+ int err;
- state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state = devm_kzalloc(&op->dev, sizeof(*state), GFP_KERNEL);
if (!state)
- goto out_err;
+ return -ENOMEM;
state->name = "Sparc BBC Speaker";
state->event = bbc_spkr_event;
spin_lock_init(&state->lock);
- dp = of_find_node_by_path("/");
- err = -ENODEV;
+ struct device_node *dp __free(device_node) = of_find_node_by_path("/");
if (!dp)
- goto out_free;
+ return -ENODEV;
info = &state->u.bbc;
info->clock_freq = of_getintprop_default(dp, "clock-frequency", 0);
- of_node_put(dp);
if (!info->clock_freq)
- goto out_free;
+ return -ENODEV;
info->regs = of_ioremap(&op->resource[0], 0, 6, "bbc beep");
if (!info->regs)
- goto out_free;
+ return -ENODEV;
platform_set_drvdata(op, state);
err = sparcspkr_probe(&op->dev);
- if (err)
- goto out_clear_drvdata;
+ if (err) {
+ of_iounmap(&op->resource[0], info->regs, 6);
+ return err;
+ }
return 0;
-
-out_clear_drvdata:
- of_iounmap(&op->resource[0], info->regs, 6);
-
-out_free:
- kfree(state);
-out_err:
- return err;
}
static void bbc_remove(struct platform_device *op)
@@ -243,8 +228,6 @@ static void bbc_remove(struct platform_device *op)
input_unregister_device(input_dev);
of_iounmap(&op->resource[0], info->regs, 6);
-
- kfree(state);
}
static const struct of_device_id bbc_beep_match[] = {
@@ -262,7 +245,7 @@ static struct platform_driver bbc_beep_driver = {
.of_match_table = bbc_beep_match,
},
.probe = bbc_beep_probe,
- .remove_new = bbc_remove,
+ .remove = bbc_remove,
.shutdown = sparcspkr_shutdown,
};
@@ -272,9 +255,9 @@ static int grover_beep_probe(struct platform_device *op)
struct grover_beep_info *info;
int err = -ENOMEM;
- state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state = devm_kzalloc(&op->dev, sizeof(*state), GFP_KERNEL);
if (!state)
- goto out_err;
+ return err;
state->name = "Sparc Grover Speaker";
state->event = grover_spkr_event;
@@ -283,7 +266,7 @@ static int grover_beep_probe(struct platform_device *op)
info = &state->u.grover;
info->freq_regs = of_ioremap(&op->resource[2], 0, 2, "grover beep freq");
if (!info->freq_regs)
- goto out_free;
+ return err;
info->enable_reg = of_ioremap(&op->resource[3], 0, 1, "grover beep enable");
if (!info->enable_reg)
@@ -302,9 +285,7 @@ out_clear_drvdata:
out_unmap_freq_regs:
of_iounmap(&op->resource[2], info->freq_regs, 2);
-out_free:
- kfree(state);
-out_err:
+
return err;
}
@@ -321,8 +302,6 @@ static void grover_remove(struct platform_device *op)
of_iounmap(&op->resource[3], info->enable_reg, 1);
of_iounmap(&op->resource[2], info->freq_regs, 2);
-
- kfree(state);
}
static const struct of_device_id grover_beep_match[] = {
@@ -340,7 +319,7 @@ static struct platform_driver grover_beep_driver = {
.of_match_table = grover_beep_match,
},
.probe = grover_beep_probe,
- .remove_new = grover_remove,
+ .remove = grover_remove,
.shutdown = sparcspkr_shutdown,
};
diff --git a/drivers/input/misc/tps65219-pwrbutton.c b/drivers/input/misc/tps65219-pwrbutton.c
index eeb9f2334ab4..7a58bae4f1a0 100644
--- a/drivers/input/misc/tps65219-pwrbutton.c
+++ b/drivers/input/misc/tps65219-pwrbutton.c
@@ -137,7 +137,7 @@ MODULE_DEVICE_TABLE(platform, tps65219_pwrbtn_id_table);
static struct platform_driver tps65219_pb_driver = {
.probe = tps65219_pb_probe,
- .remove_new = tps65219_pb_remove,
+ .remove = tps65219_pb_remove,
.driver = {
.name = "tps65219_pwrbutton",
},
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 101548b35ee3..5fa7d4a7da36 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -165,15 +165,10 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
static bool twl4030_vibra_check_coexist(struct device_node *parent)
{
- struct device_node *node;
+ struct device_node *node __free(device_node) =
+ of_get_child_by_name(parent, "codec");
- node = of_get_child_by_name(parent, "codec");
- if (node) {
- of_node_put(node);
- return true;
- }
-
- return false;
+ return node != NULL;
}
static int twl4030_vibra_probe(struct platform_device *pdev)
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 78f0b63e5c20..afed9af65bf9 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -229,14 +229,13 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops,
static int twl6040_vibra_probe(struct platform_device *pdev)
{
struct device *twl6040_core_dev = pdev->dev.parent;
- struct device_node *twl6040_core_node;
struct vibra_info *info;
int vddvibl_uV = 0;
int vddvibr_uV = 0;
int error;
- twl6040_core_node = of_get_child_by_name(twl6040_core_dev->of_node,
- "vibra");
+ struct device_node *twl6040_core_node __free(device_node) =
+ of_get_child_by_name(twl6040_core_dev->of_node, "vibra");
if (!twl6040_core_node) {
dev_err(&pdev->dev, "parent of node is missing?\n");
return -EINVAL;
@@ -244,7 +243,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) {
- of_node_put(twl6040_core_node);
dev_err(&pdev->dev, "couldn't allocate memory\n");
return -ENOMEM;
}
@@ -264,8 +262,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
of_property_read_u32(twl6040_core_node, "ti,vddvibl-uV", &vddvibl_uV);
of_property_read_u32(twl6040_core_node, "ti,vddvibr-uV", &vddvibr_uV);
- of_node_put(twl6040_core_node);
-
if ((!info->vibldrv_res && !info->viblmotor_res) ||
(!info->vibrdrv_res && !info->vibrmotor_res)) {
dev_err(info->dev, "invalid vibra driver/motor resistance\n");
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 5a64557920fa..1b2bd2139aaa 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -271,7 +271,7 @@ static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = {
{ KE_BLUETOOTH, 0x30 }, /* Fn+F10 */
{ KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */
{ KE_KEY, 0x36, {KEY_WWW} }, /* www button */
- { KE_WIFI, 0x78 }, /* satelite dish button */
+ { KE_WIFI, 0x78 }, /* satellite dish button */
{ KE_END, FE_WIFI_LED }
};
@@ -1334,7 +1334,7 @@ static struct platform_driver wistron_driver = {
.pm = pm_sleep_ptr(&wistron_pm_ops),
},
.probe = wistron_probe,
- .remove_new = wistron_remove,
+ .remove = wistron_remove,
};
static int __init wb_module_init(void)
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
index e4a06c73b72d..18eb319bc6f7 100644
--- a/drivers/input/misc/wm831x-on.c
+++ b/drivers/input/misc/wm831x-on.c
@@ -134,7 +134,7 @@ static void wm831x_on_remove(struct platform_device *pdev)
static struct platform_driver wm831x_on_driver = {
.probe = wm831x_on_probe,
- .remove_new = wm831x_on_remove,
+ .remove = wm831x_on_remove,
.driver = {
.name = "wm831x-on",
},
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index 8866bf65d347..08dc53ae1b3c 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -377,7 +377,7 @@ send_update:
if (len > sizeof(yld->ctl_data->data))
len = sizeof(yld->ctl_data->data);
- /* Combine up to <len> consecutive LCD bytes in a singe request
+ /* Combine up to <len> consecutive LCD bytes in a single request
*/
yld->ctl_data->cmd = CMD_LCD;
yld->ctl_data->offset = cpu_to_be16(ix);
@@ -614,7 +614,7 @@ static ssize_t show_line3(struct device *dev, struct device_attribute *attr,
return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET);
}
-/* Writing to /sys/../lineX will set the coresponding LCD line.
+/* Writing to /sys/../lineX will set the corresponding LCD line.
* - Excess characters are ignored.
* - If less characters are written than allowed, the remaining digits are
* unchanged.
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4e37fc3f1a9e..0728b5c08f02 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1585,7 +1585,7 @@ static void alps_flush_packet(struct timer_list *t)
struct alps_data *priv = from_timer(priv, t, timer);
struct psmouse *psmouse = priv->psmouse;
- serio_pause_rx(psmouse->ps2dev.serio);
+ guard(serio_pause_rx)(psmouse->ps2dev.serio);
if (psmouse->pktcnt == psmouse->pktsize) {
@@ -1605,8 +1605,6 @@ static void alps_flush_packet(struct timer_list *t)
}
psmouse->pktcnt = 0;
}
-
- serio_continue_rx(psmouse->ps2dev.serio);
}
static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index 2fbbaeb76d70..d203c2a6c438 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -139,7 +139,7 @@ static void __exit amimouse_remove(struct platform_device *pdev)
* triggering a section mismatch warning.
*/
static struct platform_driver amimouse_driver __refdata = {
- .remove_new = __exit_p(amimouse_remove),
+ .remove = __exit_p(amimouse_remove),
.driver = {
.name = "amiga-mouse",
},
diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c
index 221a553f45cd..654b38d249f3 100644
--- a/drivers/input/mouse/byd.c
+++ b/drivers/input/mouse/byd.c
@@ -254,13 +254,12 @@ static void byd_clear_touch(struct timer_list *t)
struct byd_data *priv = from_timer(priv, t, timer);
struct psmouse *psmouse = priv->psmouse;
- serio_pause_rx(psmouse->ps2dev.serio);
+ guard(serio_pause_rx)(psmouse->ps2dev.serio);
+
priv->touch = false;
byd_report_input(psmouse);
- serio_continue_rx(psmouse->ps2dev.serio);
-
/*
* Move cursor back to center of pad when we lose touch - this
* specifically improves user experience when moving cursor with one
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 7521981274bd..a841883660fb 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -541,7 +541,8 @@ static int elan_update_firmware(struct elan_tp_data *data,
dev_dbg(&client->dev, "Starting firmware update....\n");
- disable_irq(client->irq);
+ guard(disable_irq)(&client->irq);
+
data->in_fw_update = true;
retval = __elan_update_firmware(data, fw);
@@ -555,7 +556,6 @@ static int elan_update_firmware(struct elan_tp_data *data,
}
data->in_fw_update = false;
- enable_irq(client->irq);
return retval;
}
@@ -621,8 +621,6 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
const char *buf, size_t count)
{
struct elan_tp_data *data = dev_get_drvdata(dev);
- const struct firmware *fw;
- char *fw_name;
int error;
const u8 *fw_signature;
static const u8 signature[] = {0xAA, 0x55, 0xCC, 0x33, 0xFF, 0xFF};
@@ -631,15 +629,16 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
return -EINVAL;
/* Look for a firmware with the product id appended. */
- fw_name = kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id);
+ const char *fw_name __free(kfree) =
+ kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id);
if (!fw_name) {
dev_err(dev, "failed to allocate memory for firmware name\n");
return -ENOMEM;
}
dev_info(dev, "requesting fw '%s'\n", fw_name);
+ const struct firmware *fw __free(firmware) = NULL;
error = request_firmware(&fw, fw_name, dev);
- kfree(fw_name);
if (error) {
dev_err(dev, "failed to request firmware: %d\n", error);
return error;
@@ -651,46 +650,36 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
dev_err(dev, "signature mismatch (expected %*ph, got %*ph)\n",
(int)sizeof(signature), signature,
(int)sizeof(signature), fw_signature);
- error = -EBADF;
- goto out_release_fw;
+ return -EBADF;
}
- error = mutex_lock_interruptible(&data->sysfs_mutex);
- if (error)
- goto out_release_fw;
-
- error = elan_update_firmware(data, fw);
-
- mutex_unlock(&data->sysfs_mutex);
+ scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) {
+ error = elan_update_firmware(data, fw);
+ if (error)
+ return error;
+ }
-out_release_fw:
- release_firmware(fw);
- return error ?: count;
+ return count;
}
-static ssize_t calibrate_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static int elan_calibrate(struct elan_tp_data *data)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct elan_tp_data *data = i2c_get_clientdata(client);
+ struct i2c_client *client = data->client;
+ struct device *dev = &client->dev;
int tries = 20;
int retval;
int error;
u8 val[ETP_CALIBRATE_MAX_LEN];
- retval = mutex_lock_interruptible(&data->sysfs_mutex);
- if (retval)
- return retval;
-
- disable_irq(client->irq);
+ guard(disable_irq)(&client->irq);
data->mode |= ETP_ENABLE_CALIBRATE;
retval = data->ops->set_mode(client, data->mode);
if (retval) {
+ data->mode &= ~ETP_ENABLE_CALIBRATE;
dev_err(dev, "failed to enable calibration mode: %d\n",
retval);
- goto out;
+ return retval;
}
retval = data->ops->calibrate(client);
@@ -728,10 +717,24 @@ out_disable_calibrate:
if (!retval)
retval = error;
}
-out:
- enable_irq(client->irq);
- mutex_unlock(&data->sysfs_mutex);
- return retval ?: count;
+ return retval;
+}
+
+static ssize_t calibrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct elan_tp_data *data = i2c_get_clientdata(client);
+ int error;
+
+ scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) {
+ error = elan_calibrate(data);
+ if (error)
+ return error;
+ }
+
+ return count;
}
static ssize_t elan_sysfs_read_mode(struct device *dev,
@@ -743,16 +746,11 @@ static ssize_t elan_sysfs_read_mode(struct device *dev,
int error;
enum tp_mode mode;
- error = mutex_lock_interruptible(&data->sysfs_mutex);
- if (error)
- return error;
-
- error = data->ops->iap_get_mode(data->client, &mode);
-
- mutex_unlock(&data->sysfs_mutex);
-
- if (error)
- return error;
+ scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) {
+ error = data->ops->iap_get_mode(data->client, &mode);
+ if (error)
+ return error;
+ }
return sysfs_emit(buf, "%d\n", (int)mode);
}
@@ -783,44 +781,40 @@ static const struct attribute_group elan_sysfs_group = {
.attrs = elan_sysfs_entries,
};
-static ssize_t acquire_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static int elan_acquire_baseline(struct elan_tp_data *data)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct elan_tp_data *data = i2c_get_clientdata(client);
- int error;
+ struct i2c_client *client = data->client;
+ struct device *dev = &client->dev;
int retval;
+ int error;
- retval = mutex_lock_interruptible(&data->sysfs_mutex);
- if (retval)
- return retval;
-
- disable_irq(client->irq);
+ guard(disable_irq)(&client->irq);
data->baseline_ready = false;
data->mode |= ETP_ENABLE_CALIBRATE;
- retval = data->ops->set_mode(data->client, data->mode);
+ retval = data->ops->set_mode(client, data->mode);
if (retval) {
+ data->mode &= ~ETP_ENABLE_CALIBRATE;
dev_err(dev, "Failed to enable calibration mode to get baseline: %d\n",
retval);
- goto out;
+ return retval;
}
msleep(250);
- retval = data->ops->get_baseline_data(data->client, true,
+ retval = data->ops->get_baseline_data(client, true,
&data->max_baseline);
if (retval) {
- dev_err(dev, "Failed to read max baseline form device: %d\n",
+ dev_err(dev, "Failed to read max baseline from device: %d\n",
retval);
goto out_disable_calibrate;
}
- retval = data->ops->get_baseline_data(data->client, false,
+ retval = data->ops->get_baseline_data(client, false,
&data->min_baseline);
if (retval) {
- dev_err(dev, "Failed to read min baseline form device: %d\n",
+ dev_err(dev, "Failed to read min baseline from device: %d\n",
retval);
goto out_disable_calibrate;
}
@@ -829,17 +823,31 @@ static ssize_t acquire_store(struct device *dev, struct device_attribute *attr,
out_disable_calibrate:
data->mode &= ~ETP_ENABLE_CALIBRATE;
- error = data->ops->set_mode(data->client, data->mode);
+ error = data->ops->set_mode(client, data->mode);
if (error) {
dev_err(dev, "Failed to disable calibration mode after acquiring baseline: %d\n",
error);
if (!retval)
retval = error;
}
-out:
- enable_irq(client->irq);
- mutex_unlock(&data->sysfs_mutex);
- return retval ?: count;
+
+ return retval;
+}
+
+static ssize_t acquire_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct elan_tp_data *data = i2c_get_clientdata(client);
+ int error;
+
+ scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) {
+ error = elan_acquire_baseline(data);
+ if (error)
+ return error;
+ }
+
+ return count;
}
static ssize_t min_show(struct device *dev,
@@ -847,22 +855,15 @@ static ssize_t min_show(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_tp_data *data = i2c_get_clientdata(client);
- int retval;
- retval = mutex_lock_interruptible(&data->sysfs_mutex);
- if (retval)
- return retval;
+ scoped_guard(mutex_intr, &data->sysfs_mutex) {
+ if (!data->baseline_ready)
+ return -ENODATA;
- if (!data->baseline_ready) {
- retval = -ENODATA;
- goto out;
+ return sysfs_emit(buf, "%d", data->min_baseline);
}
- retval = sysfs_emit(buf, "%d", data->min_baseline);
-
-out:
- mutex_unlock(&data->sysfs_mutex);
- return retval;
+ return -EINTR;
}
static ssize_t max_show(struct device *dev,
@@ -870,25 +871,17 @@ static ssize_t max_show(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_tp_data *data = i2c_get_clientdata(client);
- int retval;
- retval = mutex_lock_interruptible(&data->sysfs_mutex);
- if (retval)
- return retval;
+ scoped_guard(mutex_intr, &data->sysfs_mutex) {
+ if (!data->baseline_ready)
+ return -ENODATA;
- if (!data->baseline_ready) {
- retval = -ENODATA;
- goto out;
+ return sysfs_emit(buf, "%d", data->max_baseline);
}
- retval = sysfs_emit(buf, "%d", data->max_baseline);
-
-out:
- mutex_unlock(&data->sysfs_mutex);
- return retval;
+ return -EINTR;
}
-
static DEVICE_ATTR_WO(acquire);
static DEVICE_ATTR_RO(min);
static DEVICE_ATTR_RO(max);
@@ -1323,43 +1316,54 @@ static int elan_probe(struct i2c_client *client)
return 0;
}
+static int __elan_suspend(struct elan_tp_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+
+ if (device_may_wakeup(&client->dev))
+ return elan_sleep(data);
+
+ /* Touchpad is not a wakeup source */
+ error = elan_set_power(data, false);
+ if (error)
+ return error;
+
+ error = regulator_disable(data->vcc);
+ if (error) {
+ dev_err(&client->dev,
+ "failed to disable regulator when suspending: %d\n",
+ error);
+ /* Attempt to power the chip back up */
+ elan_set_power(data, true);
+ return error;
+ }
+
+ return 0;
+}
+
static int elan_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct elan_tp_data *data = i2c_get_clientdata(client);
- int ret;
+ int error;
/*
* We are taking the mutex to make sure sysfs operations are
* complete before we attempt to bring the device into low[er]
* power mode.
*/
- ret = mutex_lock_interruptible(&data->sysfs_mutex);
- if (ret)
- return ret;
-
- disable_irq(client->irq);
+ scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) {
+ disable_irq(client->irq);
- if (device_may_wakeup(dev)) {
- ret = elan_sleep(data);
- } else {
- ret = elan_set_power(data, false);
- if (ret)
- goto err;
-
- ret = regulator_disable(data->vcc);
- if (ret) {
- dev_err(dev, "error %d disabling regulator\n", ret);
- /* Attempt to power the chip back up */
- elan_set_power(data, true);
+ error = __elan_suspend(data);
+ if (error) {
+ enable_irq(client->irq);
+ return error;
}
}
-err:
- if (ret)
- enable_irq(client->irq);
- mutex_unlock(&data->sysfs_mutex);
- return ret;
+ return 0;
}
static int elan_resume(struct device *dev)
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index 15cf4463b64e..a9057d124a88 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -628,12 +628,11 @@ static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size,
const u8 *page, u16 checksum, int idx)
{
struct device *dev = &client->dev;
- u8 *page_store;
u8 val[3];
u16 result;
int ret, error;
- page_store = kmalloc(fw_page_size + 4, GFP_KERNEL);
+ u8 *page_store __free(kfree) = kmalloc(fw_page_size + 4, GFP_KERNEL);
if (!page_store)
return -ENOMEM;
@@ -647,7 +646,7 @@ static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size,
if (ret != fw_page_size + 4) {
error = ret < 0 ? ret : -EIO;
dev_err(dev, "Failed to write page %d: %d\n", idx, error);
- goto exit;
+ return error;
}
/* Wait for F/W to update one page ROM data. */
@@ -656,20 +655,17 @@ static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size,
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
if (error) {
dev_err(dev, "Failed to read IAP write result: %d\n", error);
- goto exit;
+ return error;
}
result = le16_to_cpup((__le16 *)val);
if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) {
dev_err(dev, "IAP reports failed write: %04hx\n",
result);
- error = -EIO;
- goto exit;
+ return -EIO;
}
-exit:
- kfree(page_store);
- return error;
+ return 0;
}
static int elan_i2c_finish_fw_update(struct i2c_client *client,
diff --git a/drivers/input/mouse/psmouse-smbus.c b/drivers/input/mouse/psmouse-smbus.c
index 2a2459b1b4f2..93420f07b7d0 100644
--- a/drivers/input/mouse/psmouse-smbus.c
+++ b/drivers/input/mouse/psmouse-smbus.c
@@ -35,7 +35,7 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY))
return;
- mutex_lock(&psmouse_smbus_mutex);
+ guard(mutex)(&psmouse_smbus_mutex);
list_for_each_entry(smbdev, &psmouse_smbus_list, node) {
if (smbdev->dead)
@@ -55,15 +55,13 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
"SMBus candidate adapter appeared, triggering rescan\n");
serio_rescan(smbdev->psmouse->ps2dev.serio);
}
-
- mutex_unlock(&psmouse_smbus_mutex);
}
static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
{
struct psmouse_smbus_dev *smbdev, *tmp;
- mutex_lock(&psmouse_smbus_mutex);
+ guard(mutex)(&psmouse_smbus_mutex);
list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
if (smbdev->client != client)
@@ -85,8 +83,6 @@ static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
kfree(smbdev);
}
}
-
- mutex_unlock(&psmouse_smbus_mutex);
}
static int psmouse_smbus_notifier_call(struct notifier_block *nb,
@@ -171,7 +167,7 @@ static void psmouse_smbus_disconnect(struct psmouse *psmouse)
{
struct psmouse_smbus_dev *smbdev = psmouse->private;
- mutex_lock(&psmouse_smbus_mutex);
+ guard(mutex)(&psmouse_smbus_mutex);
if (smbdev->dead) {
list_del(&smbdev->node);
@@ -186,8 +182,6 @@ static void psmouse_smbus_disconnect(struct psmouse *psmouse)
psmouse_smbus_schedule_remove(smbdev->client);
}
- mutex_unlock(&psmouse_smbus_mutex);
-
psmouse->private = NULL;
}
@@ -219,7 +213,7 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse)
{
struct psmouse_smbus_dev *smbdev, *tmp;
- mutex_lock(&psmouse_smbus_mutex);
+ guard(mutex)(&psmouse_smbus_mutex);
list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
if (psmouse == smbdev->psmouse) {
@@ -227,8 +221,6 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse)
kfree(smbdev);
}
}
-
- mutex_unlock(&psmouse_smbus_mutex);
}
int psmouse_smbus_init(struct psmouse *psmouse,
@@ -267,9 +259,9 @@ int psmouse_smbus_init(struct psmouse *psmouse,
psmouse->disconnect = psmouse_smbus_disconnect;
psmouse->resync_time = 0;
- mutex_lock(&psmouse_smbus_mutex);
- list_add_tail(&smbdev->node, &psmouse_smbus_list);
- mutex_unlock(&psmouse_smbus_mutex);
+ scoped_guard(mutex, &psmouse_smbus_mutex) {
+ list_add_tail(&smbdev->node, &psmouse_smbus_list);
+ }
/* Bind to already existing adapters right away */
error = i2c_for_each_dev(smbdev, psmouse_smbus_create_companion);
@@ -293,9 +285,9 @@ int psmouse_smbus_init(struct psmouse *psmouse,
smbdev->board.platform_data = NULL;
if (error < 0 || !leave_breadcrumbs) {
- mutex_lock(&psmouse_smbus_mutex);
- list_del(&smbdev->node);
- mutex_unlock(&psmouse_smbus_mutex);
+ scoped_guard(mutex, &psmouse_smbus_mutex) {
+ list_del(&smbdev->node);
+ }
kfree(smbdev);
}
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 380aa1614442..2735f86c23cc 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -650,9 +650,8 @@ static int synaptics_pt_start(struct serio *serio)
struct psmouse *parent = psmouse_from_serio(serio->parent);
struct synaptics_data *priv = parent->private;
- serio_pause_rx(parent->ps2dev.serio);
+ guard(serio_pause_rx)(parent->ps2dev.serio);
priv->pt_port = serio;
- serio_continue_rx(parent->ps2dev.serio);
return 0;
}
@@ -662,9 +661,8 @@ static void synaptics_pt_stop(struct serio *serio)
struct psmouse *parent = psmouse_from_serio(serio->parent);
struct synaptics_data *priv = parent->private;
- serio_pause_rx(parent->ps2dev.serio);
+ guard(serio_pause_rx)(parent->ps2dev.serio);
priv->pt_port = NULL;
- serio_continue_rx(parent->ps2dev.serio);
}
static int synaptics_is_pt_packet(u8 *buf)
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 08533d1b1b16..899aee598632 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -21,7 +21,7 @@
#define SYN_QUE_EXT_MIN_COORDS 0x0f
#define SYN_QUE_MEXT_CAPAB_10 0x10
-/* synatics modes */
+/* synaptics modes */
#define SYN_BIT_ABSOLUTE_MODE BIT(7)
#define SYN_BIT_HIGH_RATE BIT(6)
#define SYN_BIT_SLEEP_MODE BIT(3)
diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
index 1e11ea30d7bd..e1157ff0f00a 100644
--- a/drivers/input/rmi4/rmi_f03.c
+++ b/drivers/input/rmi4/rmi_f03.c
@@ -61,14 +61,14 @@ void rmi_f03_commit_buttons(struct rmi_function *fn)
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
struct serio *serio = f03->serio;
- serio_pause_rx(serio);
+ guard(serio_pause_rx)(serio);
+
if (serio->drv) {
serio->drv->interrupt(serio, PSMOUSE_OOB_EXTRA_BTNS,
SERIO_OOB_DATA);
serio->drv->interrupt(serio, f03->overwrite_buttons,
SERIO_OOB_DATA);
}
- serio_continue_rx(serio);
}
static int rmi_f03_pt_write(struct serio *id, unsigned char val)
diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c
index e2468bc04a5c..d760af4cc12e 100644
--- a/drivers/input/rmi4/rmi_f34.c
+++ b/drivers/input/rmi4/rmi_f34.c
@@ -246,7 +246,6 @@ static int rmi_f34_update_firmware(struct f34_data *f34,
(const struct rmi_f34_firmware *)fw->data;
u32 image_size = le32_to_cpu(syn_fw->image_size);
u32 config_size = le32_to_cpu(syn_fw->config_size);
- int ret;
BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) !=
F34_FW_IMAGE_OFFSET);
@@ -267,8 +266,7 @@ static int rmi_f34_update_firmware(struct f34_data *f34,
dev_err(&f34->fn->dev,
"Bad firmware image: fw size %d, expected %d\n",
image_size, f34->v5.fw_blocks * f34->v5.block_size);
- ret = -EILSEQ;
- goto out;
+ return -EILSEQ;
}
if (config_size &&
@@ -277,25 +275,18 @@ static int rmi_f34_update_firmware(struct f34_data *f34,
"Bad firmware image: config size %d, expected %d\n",
config_size,
f34->v5.config_blocks * f34->v5.block_size);
- ret = -EILSEQ;
- goto out;
+ return -EILSEQ;
}
if (image_size && !config_size) {
dev_err(&f34->fn->dev, "Bad firmware image: no config data\n");
- ret = -EILSEQ;
- goto out;
+ return -EILSEQ;
}
dev_info(&f34->fn->dev, "Firmware image OK\n");
- mutex_lock(&f34->v5.flash_mutex);
-
- ret = rmi_f34_flash_firmware(f34, syn_fw);
- mutex_unlock(&f34->v5.flash_mutex);
-
-out:
- return ret;
+ guard(mutex)(&f34->v5.flash_mutex);
+ return rmi_f34_flash_firmware(f34, syn_fw);
}
static int rmi_f34_status(struct rmi_function *fn)
@@ -461,9 +452,8 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev,
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
char fw_name[NAME_MAX];
- const struct firmware *fw;
size_t copy_count = count;
- int ret;
+ int error;
if (count == 0 || count >= NAME_MAX)
return -EINVAL;
@@ -474,17 +464,18 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev,
memcpy(fw_name, buf, copy_count);
fw_name[copy_count] = '\0';
- ret = request_firmware(&fw, fw_name, dev);
- if (ret)
- return ret;
+ const struct firmware *fw __free(firmware) = NULL;
+ error = request_firmware(&fw, fw_name, dev);
+ if (error)
+ return error;
dev_info(dev, "Flashing %s\n", fw_name);
- ret = rmi_firmware_update(data, fw);
-
- release_firmware(fw);
+ error = rmi_firmware_update(data, fw);
+ if (error)
+ return error;
- return ret ?: count;
+ return count;
}
static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store);
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
index 611eb9fe2d04..aa445b1941e9 100644
--- a/drivers/input/serio/altera_ps2.c
+++ b/drivers/input/serio/altera_ps2.c
@@ -146,7 +146,7 @@ MODULE_DEVICE_TABLE(of, altera_ps2_match);
*/
static struct platform_driver altera_ps2_driver = {
.probe = altera_ps2_probe,
- .remove_new = altera_ps2_remove,
+ .remove = altera_ps2_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(altera_ps2_match),
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index 0bd6ae106809..81b3a053df81 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -182,7 +182,7 @@ static void ams_delta_serio_exit(struct platform_device *pdev)
static struct platform_driver ams_delta_serio_driver = {
.probe = ams_delta_serio_init,
- .remove_new = ams_delta_serio_exit,
+ .remove = ams_delta_serio_exit,
.driver = {
.name = DRIVER_NAME
},
diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c
index 4015e75fcb90..b815337be2f4 100644
--- a/drivers/input/serio/apbps2.c
+++ b/drivers/input/serio/apbps2.c
@@ -208,7 +208,7 @@ static struct platform_driver apbps2_of_driver = {
.of_match_table = apbps2_of_match,
},
.probe = apbps2_of_probe,
- .remove_new = apbps2_of_remove,
+ .remove = apbps2_of_remove,
};
module_platform_driver(apbps2_of_driver);
diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
index a9180a005872..e991c72296c9 100644
--- a/drivers/input/serio/arc_ps2.c
+++ b/drivers/input/serio/arc_ps2.c
@@ -260,7 +260,7 @@ static struct platform_driver arc_ps2_driver = {
.of_match_table = of_match_ptr(arc_ps2_match),
},
.probe = arc_ps2_probe,
- .remove_new = arc_ps2_remove,
+ .remove = arc_ps2_remove,
};
module_platform_driver(arc_ps2_driver);
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 6834440b37f6..053a15988c45 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -190,7 +190,7 @@ static struct platform_driver ct82c710_driver = {
.name = "ct82c710",
},
.probe = ct82c710_probe,
- .remove_new = ct82c710_remove,
+ .remove = ct82c710_remove,
};
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index d94c01eb3fc9..4fada5bc2a38 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -145,7 +145,6 @@ static void gscps2_flush(struct gscps2port *ps2port)
static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
{
- unsigned long flags;
char __iomem *addr = ps2port->addr;
if (!wait_TBE(addr)) {
@@ -156,9 +155,8 @@ static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
while (gscps2_readb_status(addr) & GSC_STAT_RBNE)
/* wait */;
- spin_lock_irqsave(&ps2port->lock, flags);
- writeb(data, addr+GSC_XMTDATA);
- spin_unlock_irqrestore(&ps2port->lock, flags);
+ scoped_guard(spinlock_irqsave, &ps2port->lock)
+ writeb(data, addr+GSC_XMTDATA);
/* this is ugly, but due to timing of the port it seems to be necessary. */
mdelay(6);
@@ -177,19 +175,19 @@ static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
static void gscps2_enable(struct gscps2port *ps2port, int enable)
{
- unsigned long flags;
u8 data;
/* now enable/disable the port */
- spin_lock_irqsave(&ps2port->lock, flags);
- gscps2_flush(ps2port);
- data = gscps2_readb_control(ps2port->addr);
- if (enable)
- data |= GSC_CTRL_ENBL;
- else
- data &= ~GSC_CTRL_ENBL;
- gscps2_writeb_control(data, ps2port->addr);
- spin_unlock_irqrestore(&ps2port->lock, flags);
+ scoped_guard(spinlock_irqsave, &ps2port->lock) {
+ gscps2_flush(ps2port);
+ data = gscps2_readb_control(ps2port->addr);
+ if (enable)
+ data |= GSC_CTRL_ENBL;
+ else
+ data &= ~GSC_CTRL_ENBL;
+ gscps2_writeb_control(data, ps2port->addr);
+ }
+
wait_TBE(ps2port->addr);
gscps2_flush(ps2port);
}
@@ -200,18 +198,57 @@ static void gscps2_enable(struct gscps2port *ps2port, int enable)
static void gscps2_reset(struct gscps2port *ps2port)
{
- unsigned long flags;
-
/* reset the interface */
- spin_lock_irqsave(&ps2port->lock, flags);
+ guard(spinlock_irqsave)(&ps2port->lock);
gscps2_flush(ps2port);
writeb(0xff, ps2port->addr + GSC_RESET);
gscps2_flush(ps2port);
- spin_unlock_irqrestore(&ps2port->lock, flags);
}
static LIST_HEAD(ps2port_list);
+static void gscps2_read_data(struct gscps2port *ps2port)
+{
+ u8 status;
+
+ do {
+ status = gscps2_readb_status(ps2port->addr);
+ if (!(status & GSC_STAT_RBNE))
+ break;
+
+ ps2port->buffer[ps2port->append].str = status;
+ ps2port->buffer[ps2port->append].data =
+ gscps2_readb_input(ps2port->addr);
+ } while (true);
+}
+
+static bool gscps2_report_data(struct gscps2port *ps2port)
+{
+ unsigned int rxflags;
+ u8 data, status;
+
+ while (ps2port->act != ps2port->append) {
+ /*
+ * Did new data arrived while we read existing data ?
+ * If yes, exit now and let the new irq handler start
+ * over again.
+ */
+ if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR)
+ return true;
+
+ status = ps2port->buffer[ps2port->act].str;
+ data = ps2port->buffer[ps2port->act].data;
+
+ ps2port->act = (ps2port->act + 1) & BUFFER_SIZE;
+ rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
+ ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 );
+
+ serio_interrupt(ps2port->port, data, rxflags);
+ }
+
+ return false;
+}
+
/**
* gscps2_interrupt() - Interruption service routine
*
@@ -229,47 +266,18 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev)
struct gscps2port *ps2port;
list_for_each_entry(ps2port, &ps2port_list, node) {
+ guard(spinlock_irqsave)(&ps2port->lock);
- unsigned long flags;
- spin_lock_irqsave(&ps2port->lock, flags);
-
- while ( (ps2port->buffer[ps2port->append].str =
- gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) {
- ps2port->buffer[ps2port->append].data =
- gscps2_readb_input(ps2port->addr);
- ps2port->append = ((ps2port->append+1) & BUFFER_SIZE);
- }
-
- spin_unlock_irqrestore(&ps2port->lock, flags);
-
+ gscps2_read_data(ps2port);
} /* list_for_each_entry */
/* all data was read from the ports - now report the data to upper layer */
-
list_for_each_entry(ps2port, &ps2port_list, node) {
-
- while (ps2port->act != ps2port->append) {
-
- unsigned int rxflags;
- u8 data, status;
-
- /* Did new data arrived while we read existing data ?
- If yes, exit now and let the new irq handler start over again */
- if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR)
- return IRQ_HANDLED;
-
- status = ps2port->buffer[ps2port->act].str;
- data = ps2port->buffer[ps2port->act].data;
-
- ps2port->act = ((ps2port->act+1) & BUFFER_SIZE);
- rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
- ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 );
-
- serio_interrupt(ps2port->port, data, rxflags);
-
- } /* while() */
-
- } /* list_for_each_entry */
+ if (gscps2_report_data(ps2port)) {
+ /* More data ready - break early to restart interrupt */
+ break;
+ }
+ }
return IRQ_HANDLED;
}
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c
index 31d9dacd2fd1..0ee7505427ac 100644
--- a/drivers/input/serio/hyperv-keyboard.c
+++ b/drivers/input/serio/hyperv-keyboard.c
@@ -102,7 +102,6 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,
{
struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
struct synth_kbd_keystroke *ks_msg;
- unsigned long flags;
u32 msg_type = __le32_to_cpu(msg->header.type);
u32 info;
u16 scan_code;
@@ -147,21 +146,22 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,
/*
* Inject the information through the serio interrupt.
*/
- spin_lock_irqsave(&kbd_dev->lock, flags);
- if (kbd_dev->started) {
- if (info & IS_E0)
- serio_interrupt(kbd_dev->hv_serio,
- XTKBD_EMUL0, 0);
- if (info & IS_E1)
- serio_interrupt(kbd_dev->hv_serio,
- XTKBD_EMUL1, 0);
- scan_code = __le16_to_cpu(ks_msg->make_code);
- if (info & IS_BREAK)
- scan_code |= XTKBD_RELEASE;
+ scoped_guard(spinlock_irqsave, &kbd_dev->lock) {
+ if (kbd_dev->started) {
+ if (info & IS_E0)
+ serio_interrupt(kbd_dev->hv_serio,
+ XTKBD_EMUL0, 0);
+ if (info & IS_E1)
+ serio_interrupt(kbd_dev->hv_serio,
+ XTKBD_EMUL1, 0);
+ scan_code = __le16_to_cpu(ks_msg->make_code);
+ if (info & IS_BREAK)
+ scan_code |= XTKBD_RELEASE;
- serio_interrupt(kbd_dev->hv_serio, scan_code, 0);
+ serio_interrupt(kbd_dev->hv_serio,
+ scan_code, 0);
+ }
}
- spin_unlock_irqrestore(&kbd_dev->lock, flags);
/*
* Only trigger a wakeup on key down, otherwise
@@ -292,11 +292,10 @@ static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev)
static int hv_kbd_start(struct serio *serio)
{
struct hv_kbd_dev *kbd_dev = serio->port_data;
- unsigned long flags;
- spin_lock_irqsave(&kbd_dev->lock, flags);
+ guard(spinlock_irqsave)(&kbd_dev->lock);
+
kbd_dev->started = true;
- spin_unlock_irqrestore(&kbd_dev->lock, flags);
return 0;
}
@@ -304,11 +303,10 @@ static int hv_kbd_start(struct serio *serio)
static void hv_kbd_stop(struct serio *serio)
{
struct hv_kbd_dev *kbd_dev = serio->port_data;
- unsigned long flags;
- spin_lock_irqsave(&kbd_dev->lock, flags);
+ guard(spinlock_irqsave)(&kbd_dev->lock);
+
kbd_dev->started = false;
- spin_unlock_irqrestore(&kbd_dev->lock, flags);
}
static int hv_kbd_probe(struct hv_device *hv_dev,
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index 34d1f07ea4c3..127cfdc8668a 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -90,7 +90,7 @@ static inline void i8042_write_command(int val)
* ORDERING IS IMPORTANT! The first match will be apllied and the rest ignored.
* This allows entries to overwrite vendor wide quirks on a per device basis.
* Where this is irrelevant, entries are sorted case sensitive by DMI_SYS_VENDOR
- * and/or DMI_BOARD_VENDOR to make it easier to avoid dublicate entries.
+ * and/or DMI_BOARD_VENDOR to make it easier to avoid duplicate entries.
*/
static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
{
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index c2fda54dc384..0f97158fd14e 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -101,23 +101,15 @@ static struct platform_driver sparc_i8042_driver = {
.of_match_table = sparc_i8042_match,
},
.probe = sparc_i8042_probe,
- .remove_new = sparc_i8042_remove,
+ .remove = sparc_i8042_remove,
};
static bool i8042_is_mr_coffee(void)
{
- struct device_node *root;
- const char *name;
- bool is_mr_coffee;
+ struct device_node *root __free(device_node) = of_find_node_by_path("/");
+ const char *name = of_get_property(root, "name", NULL);
- root = of_find_node_by_path("/");
-
- name = of_get_property(root, "name", NULL);
- is_mr_coffee = name && !strcmp(name, "SUNW,JavaStation-1");
-
- of_node_put(root);
-
- return is_mr_coffee;
+ return name && !strcmp(name, "SUNW,JavaStation-1");
}
static int __init i8042_platform_init(void)
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 8ec4872b4471..509330a27880 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -178,7 +178,7 @@ static unsigned char i8042_suppress_kbd_ack;
static struct platform_device *i8042_platform_device;
static struct notifier_block i8042_kbd_bind_notifier_block;
-static irqreturn_t i8042_interrupt(int irq, void *dev_id);
+static bool i8042_handle_data(int irq);
static bool (*i8042_platform_filter)(unsigned char data, unsigned char str,
struct serio *serio);
@@ -197,42 +197,26 @@ EXPORT_SYMBOL(i8042_unlock_chip);
int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
- unsigned long flags;
- int ret = 0;
+ guard(spinlock_irqsave)(&i8042_lock);
- spin_lock_irqsave(&i8042_lock, flags);
-
- if (i8042_platform_filter) {
- ret = -EBUSY;
- goto out;
- }
+ if (i8042_platform_filter)
+ return -EBUSY;
i8042_platform_filter = filter;
-
-out:
- spin_unlock_irqrestore(&i8042_lock, flags);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(i8042_install_filter);
int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *port))
{
- unsigned long flags;
- int ret = 0;
+ guard(spinlock_irqsave)(&i8042_lock);
- spin_lock_irqsave(&i8042_lock, flags);
-
- if (i8042_platform_filter != filter) {
- ret = -EINVAL;
- goto out;
- }
+ if (i8042_platform_filter != filter)
+ return -EINVAL;
i8042_platform_filter = NULL;
-
-out:
- spin_unlock_irqrestore(&i8042_lock, flags);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(i8042_remove_filter);
@@ -271,28 +255,22 @@ static int i8042_wait_write(void)
static int i8042_flush(void)
{
- unsigned long flags;
unsigned char data, str;
int count = 0;
- int retval = 0;
- spin_lock_irqsave(&i8042_lock, flags);
+ guard(spinlock_irqsave)(&i8042_lock);
while ((str = i8042_read_status()) & I8042_STR_OBF) {
- if (count++ < I8042_BUFFER_SIZE) {
- udelay(50);
- data = i8042_read_data();
- dbg("%02x <- i8042 (flush, %s)\n",
- data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
- } else {
- retval = -EIO;
- break;
- }
- }
+ if (count++ >= I8042_BUFFER_SIZE)
+ return -EIO;
- spin_unlock_irqrestore(&i8042_lock, flags);
+ udelay(50);
+ data = i8042_read_data();
+ dbg("%02x <- i8042 (flush, %s)\n",
+ data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
+ }
- return retval;
+ return 0;
}
/*
@@ -349,17 +327,12 @@ static int __i8042_command(unsigned char *param, int command)
int i8042_command(unsigned char *param, int command)
{
- unsigned long flags;
- int retval;
-
if (!i8042_present)
return -1;
- spin_lock_irqsave(&i8042_lock, flags);
- retval = __i8042_command(param, command);
- spin_unlock_irqrestore(&i8042_lock, flags);
+ guard(spinlock_irqsave)(&i8042_lock);
- return retval;
+ return __i8042_command(param, command);
}
EXPORT_SYMBOL(i8042_command);
@@ -369,19 +342,18 @@ EXPORT_SYMBOL(i8042_command);
static int i8042_kbd_write(struct serio *port, unsigned char c)
{
- unsigned long flags;
- int retval = 0;
+ int error;
- spin_lock_irqsave(&i8042_lock, flags);
+ guard(spinlock_irqsave)(&i8042_lock);
- if (!(retval = i8042_wait_write())) {
- dbg("%02x -> i8042 (kbd-data)\n", c);
- i8042_write_data(c);
- }
+ error = i8042_wait_write();
+ if (error)
+ return error;
- spin_unlock_irqrestore(&i8042_lock, flags);
+ dbg("%02x -> i8042 (kbd-data)\n", c);
+ i8042_write_data(c);
- return retval;
+ return 0;
}
/*
@@ -434,7 +406,7 @@ static void i8042_port_close(struct serio *serio)
* See if there is any data appeared while we were messing with
* port state.
*/
- i8042_interrupt(0, NULL);
+ i8042_handle_data(0);
}
/*
@@ -460,9 +432,8 @@ static int i8042_start(struct serio *serio)
device_set_wakeup_enable(&serio->dev, true);
}
- spin_lock_irq(&i8042_lock);
+ guard(spinlock_irq)(&i8042_lock);
port->exists = true;
- spin_unlock_irq(&i8042_lock);
return 0;
}
@@ -476,10 +447,10 @@ static void i8042_stop(struct serio *serio)
{
struct i8042_port *port = serio->port_data;
- spin_lock_irq(&i8042_lock);
- port->exists = false;
- port->serio = NULL;
- spin_unlock_irq(&i8042_lock);
+ scoped_guard(spinlock_irq, &i8042_lock) {
+ port->exists = false;
+ port->serio = NULL;
+ }
/*
* We need to make sure that interrupt handler finishes using
@@ -518,44 +489,10 @@ static bool i8042_filter(unsigned char data, unsigned char str,
}
/*
- * i8042_interrupt() is the most important function in this driver -
- * it handles the interrupts from the i8042, and sends incoming bytes
- * to the upper layers.
- */
-
-static irqreturn_t i8042_interrupt(int irq, void *dev_id)
-{
- struct i8042_port *port;
- struct serio *serio;
- unsigned long flags;
- unsigned char str, data;
- unsigned int dfl;
- unsigned int port_no;
- bool filtered;
- int ret = 1;
-
- spin_lock_irqsave(&i8042_lock, flags);
-
- str = i8042_read_status();
- if (unlikely(~str & I8042_STR_OBF)) {
- spin_unlock_irqrestore(&i8042_lock, flags);
- if (irq)
- dbg("Interrupt %d, without any data\n", irq);
- ret = 0;
- goto out;
- }
-
- data = i8042_read_data();
-
- if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
- static unsigned long last_transmit;
- static unsigned char last_str;
-
- dfl = 0;
- if (str & I8042_STR_MUXERR) {
- dbg("MUX error, status is %02x, data is %02x\n",
- str, data);
-/*
+ * i8042_handle_mux() handles case when data is coming from one of
+ * the multiplexed ports. It would be simple if not for quirks with
+ * handling errors:
+ *
* When MUXERR condition is signalled the data register can only contain
* 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
* it is not always the case. Some KBCs also report 0xfc when there is
@@ -567,50 +504,106 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
* rest assume that the data came from the same serio last byte
* was transmitted (if transmission happened not too long ago).
*/
-
- switch (data) {
- default:
- if (time_before(jiffies, last_transmit + HZ/10)) {
- str = last_str;
- break;
- }
- fallthrough; /* report timeout */
- case 0xfc:
- case 0xfd:
- case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
- case 0xff: dfl = SERIO_PARITY; data = 0xfe; break;
+static int i8042_handle_mux(u8 str, u8 *data, unsigned int *dfl)
+{
+ static unsigned long last_transmit;
+ static unsigned long last_port;
+ unsigned int mux_port;
+
+ mux_port = (str >> 6) & 3;
+ *dfl = 0;
+
+ if (str & I8042_STR_MUXERR) {
+ dbg("MUX error, status is %02x, data is %02x\n",
+ str, *data);
+
+ switch (*data) {
+ default:
+ if (time_before(jiffies, last_transmit + HZ/10)) {
+ mux_port = last_port;
+ break;
}
+ fallthrough; /* report timeout */
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ *dfl = SERIO_TIMEOUT;
+ *data = 0xfe;
+ break;
+ case 0xff:
+ *dfl = SERIO_PARITY;
+ *data = 0xfe;
+ break;
}
+ }
- port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3);
- last_str = str;
- last_transmit = jiffies;
- } else {
+ last_port = mux_port;
+ last_transmit = jiffies;
- dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
- ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0);
+ return I8042_MUX_PORT_NO + mux_port;
+}
- port_no = (str & I8042_STR_AUXDATA) ?
- I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;
- }
+/*
+ * i8042_handle_data() is the most important function in this driver -
+ * it reads the data from the i8042, determines its destination serio
+ * port, and sends received byte to the upper layers.
+ *
+ * Returns true if there was data waiting, false otherwise.
+ */
+static bool i8042_handle_data(int irq)
+{
+ struct i8042_port *port;
+ struct serio *serio;
+ unsigned char str, data;
+ unsigned int dfl;
+ unsigned int port_no;
+ bool filtered;
+
+ scoped_guard(spinlock_irqsave, &i8042_lock) {
+ str = i8042_read_status();
+ if (unlikely(~str & I8042_STR_OBF))
+ return false;
+
+ data = i8042_read_data();
+
+ if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
+ port_no = i8042_handle_mux(str, &data, &dfl);
+ } else {
+
+ dfl = (str & I8042_STR_PARITY) ? SERIO_PARITY : 0;
+ if ((str & I8042_STR_TIMEOUT) && !i8042_notimeout)
+ dfl |= SERIO_TIMEOUT;
- port = &i8042_ports[port_no];
- serio = port->exists ? port->serio : NULL;
+ port_no = (str & I8042_STR_AUXDATA) ?
+ I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;
+ }
- filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n",
- port_no, irq,
- dfl & SERIO_PARITY ? ", bad parity" : "",
- dfl & SERIO_TIMEOUT ? ", timeout" : "");
+ port = &i8042_ports[port_no];
+ serio = port->exists ? port->serio : NULL;
- filtered = i8042_filter(data, str, serio);
+ filter_dbg(port->driver_bound,
+ data, "<- i8042 (interrupt, %d, %d%s%s)\n",
+ port_no, irq,
+ dfl & SERIO_PARITY ? ", bad parity" : "",
+ dfl & SERIO_TIMEOUT ? ", timeout" : "");
- spin_unlock_irqrestore(&i8042_lock, flags);
+ filtered = i8042_filter(data, str, serio);
+ }
if (likely(serio && !filtered))
serio_interrupt(serio, data, dfl);
- out:
- return IRQ_RETVAL(ret);
+ return true;
+}
+
+static irqreturn_t i8042_interrupt(int irq, void *dev_id)
+{
+ if (unlikely(!i8042_handle_data(irq))) {
+ dbg("Interrupt %d, without any data\n", irq);
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
}
/*
@@ -753,24 +746,22 @@ static bool i8042_irq_being_tested;
static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id)
{
- unsigned long flags;
unsigned char str, data;
- int ret = 0;
- spin_lock_irqsave(&i8042_lock, flags);
+ guard(spinlock_irqsave)(&i8042_lock);
+
str = i8042_read_status();
- if (str & I8042_STR_OBF) {
- data = i8042_read_data();
- dbg("%02x <- i8042 (aux_test_irq, %s)\n",
- data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
- if (i8042_irq_being_tested &&
- data == 0xa5 && (str & I8042_STR_AUXDATA))
- complete(&i8042_aux_irq_delivered);
- ret = 1;
- }
- spin_unlock_irqrestore(&i8042_lock, flags);
+ if (!(str & I8042_STR_OBF))
+ return IRQ_NONE;
+
+ data = i8042_read_data();
+ dbg("%02x <- i8042 (aux_test_irq, %s)\n",
+ data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
+
+ if (i8042_irq_being_tested && data == 0xa5 && (str & I8042_STR_AUXDATA))
+ complete(&i8042_aux_irq_delivered);
- return IRQ_RETVAL(ret);
+ return IRQ_HANDLED;
}
/*
@@ -811,7 +802,6 @@ static int i8042_check_aux(void)
int retval = -1;
bool irq_registered = false;
bool aux_loop_broken = false;
- unsigned long flags;
unsigned char param;
/*
@@ -895,18 +885,15 @@ static int i8042_check_aux(void)
if (i8042_enable_aux_port())
goto out;
- spin_lock_irqsave(&i8042_lock, flags);
-
- init_completion(&i8042_aux_irq_delivered);
- i8042_irq_being_tested = true;
+ scoped_guard(spinlock_irqsave, &i8042_lock) {
+ init_completion(&i8042_aux_irq_delivered);
+ i8042_irq_being_tested = true;
- param = 0xa5;
- retval = __i8042_command(&param, I8042_CMD_AUX_LOOP & 0xf0ff);
-
- spin_unlock_irqrestore(&i8042_lock, flags);
-
- if (retval)
- goto out;
+ param = 0xa5;
+ retval = __i8042_command(&param, I8042_CMD_AUX_LOOP & 0xf0ff);
+ if (retval)
+ goto out;
+ }
if (wait_for_completion_timeout(&i8042_aux_irq_delivered,
msecs_to_jiffies(250)) == 0) {
@@ -994,7 +981,6 @@ static int i8042_controller_selftest(void)
static int i8042_controller_init(void)
{
- unsigned long flags;
int n = 0;
unsigned char ctr[2];
@@ -1031,14 +1017,14 @@ static int i8042_controller_init(void)
* Handle keylock.
*/
- spin_lock_irqsave(&i8042_lock, flags);
- if (~i8042_read_status() & I8042_STR_KEYLOCK) {
- if (i8042_unlock)
- i8042_ctr |= I8042_CTR_IGNKEYLOCK;
- else
- pr_warn("Warning: Keylock active\n");
+ scoped_guard(spinlock_irqsave, &i8042_lock) {
+ if (~i8042_read_status() & I8042_STR_KEYLOCK) {
+ if (i8042_unlock)
+ i8042_ctr |= I8042_CTR_IGNKEYLOCK;
+ else
+ pr_warn("Warning: Keylock active\n");
+ }
}
- spin_unlock_irqrestore(&i8042_lock, flags);
/*
* If the chip is configured into nontranslated mode by the BIOS, don't
@@ -1216,13 +1202,14 @@ static int i8042_controller_resume(bool s2r_wants_reset)
if (i8042_mux_present) {
if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports())
pr_warn("failed to resume active multiplexor, mouse won't work\n");
- } else if (i8042_ports[I8042_AUX_PORT_NO].serio)
+ } else if (i8042_ports[I8042_AUX_PORT_NO].serio) {
i8042_enable_aux_port();
+ }
if (i8042_ports[I8042_KBD_PORT_NO].serio)
i8042_enable_kbd_port();
- i8042_interrupt(0, NULL);
+ i8042_handle_data(0);
return 0;
}
@@ -1253,7 +1240,7 @@ static int i8042_pm_suspend(struct device *dev)
static int i8042_pm_resume_noirq(struct device *dev)
{
if (i8042_forcenorestore || !pm_resume_via_firmware())
- i8042_interrupt(0, NULL);
+ i8042_handle_data(0);
return 0;
}
@@ -1290,7 +1277,7 @@ static int i8042_pm_resume(struct device *dev)
static int i8042_pm_thaw(struct device *dev)
{
- i8042_interrupt(0, NULL);
+ i8042_handle_data(0);
return 0;
}
@@ -1603,7 +1590,7 @@ static struct platform_driver i8042_driver = {
#endif
},
.probe = i8042_probe,
- .remove_new = i8042_remove,
+ .remove = i8042_remove,
.shutdown = i8042_shutdown,
};
diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
index 676b0bda3d72..d2c7ffb9a946 100644
--- a/drivers/input/serio/ioc3kbd.c
+++ b/drivers/input/serio/ioc3kbd.c
@@ -208,7 +208,7 @@ MODULE_DEVICE_TABLE(platform, ioc3kbd_id_table);
static struct platform_driver ioc3kbd_driver = {
.probe = ioc3kbd_probe,
- .remove_new = ioc3kbd_remove,
+ .remove = ioc3kbd_remove,
.id_table = ioc3kbd_id_table,
.driver = {
.name = "ioc3-kbd",
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 6d78a1fe00c1..c22ea532276e 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -108,13 +108,11 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
{
int retval;
- serio_pause_rx(ps2dev->serio);
+ guard(serio_pause_rx)(ps2dev->serio);
retval = ps2_do_sendbyte(ps2dev, byte, timeout, 1);
dev_dbg(&ps2dev->serio->dev, "%02x - %x\n", byte, ps2dev->nak);
- serio_continue_rx(ps2dev->serio);
-
return retval;
}
EXPORT_SYMBOL(ps2_sendbyte);
@@ -162,10 +160,10 @@ void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout)
ps2_begin_command(ps2dev);
- serio_pause_rx(ps2dev->serio);
- ps2dev->flags = PS2_FLAG_CMD;
- ps2dev->cmdcnt = maxbytes;
- serio_continue_rx(ps2dev->serio);
+ scoped_guard(serio_pause_rx, ps2dev->serio) {
+ ps2dev->flags = PS2_FLAG_CMD;
+ ps2dev->cmdcnt = maxbytes;
+ }
wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD),
@@ -224,9 +222,9 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev,
* use alternative probe to detect it.
*/
if (ps2dev->cmdbuf[1] == 0xaa) {
- serio_pause_rx(ps2dev->serio);
- ps2dev->flags = 0;
- serio_continue_rx(ps2dev->serio);
+ scoped_guard(serio_pause_rx, ps2dev->serio)
+ ps2dev->flags = 0;
+
timeout = 0;
}
@@ -235,9 +233,9 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev,
* won't be 2nd byte of ID response.
*/
if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) {
- serio_pause_rx(ps2dev->serio);
- ps2dev->flags = ps2dev->cmdcnt = 0;
- serio_continue_rx(ps2dev->serio);
+ scoped_guard(serio_pause_rx, ps2dev->serio)
+ ps2dev->flags = ps2dev->cmdcnt = 0;
+
timeout = 0;
}
break;
@@ -283,6 +281,10 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
memcpy(send_param, param, send);
+ /*
+ * Not using guard notation because we need to break critical
+ * section below while waiting for the response.
+ */
serio_pause_rx(ps2dev->serio);
ps2dev->cmdcnt = receive;
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index 42ac1eb94866..3d28a5cddd61 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -159,7 +159,7 @@ static struct platform_driver maceps2_driver = {
.name = "maceps2",
},
.probe = maceps2_probe,
- .remove_new = maceps2_remove,
+ .remove = maceps2_remove,
};
static int __init maceps2_init(void)
diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c
index 0ad95e880cc2..a24324830021 100644
--- a/drivers/input/serio/olpc_apsp.c
+++ b/drivers/input/serio/olpc_apsp.c
@@ -256,7 +256,7 @@ MODULE_DEVICE_TABLE(of, olpc_apsp_dt_ids);
static struct platform_driver olpc_apsp_driver = {
.probe = olpc_apsp_probe,
- .remove_new = olpc_apsp_remove,
+ .remove = olpc_apsp_remove,
.driver = {
.name = "olpc-apsp",
.of_match_table = olpc_apsp_dt_ids,
diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c
index 3a431395c464..93769910ce24 100644
--- a/drivers/input/serio/ps2-gpio.c
+++ b/drivers/input/serio/ps2-gpio.c
@@ -133,12 +133,12 @@ static int ps2_gpio_write(struct serio *serio, unsigned char val)
int ret = 0;
if (in_task()) {
- mutex_lock(&drvdata->tx.mutex);
+ guard(mutex)(&drvdata->tx.mutex);
+
__ps2_gpio_write(serio, val);
if (!wait_for_completion_timeout(&drvdata->tx.complete,
msecs_to_jiffies(10000)))
ret = SERIO_TIMEOUT;
- mutex_unlock(&drvdata->tx.mutex);
} else {
__ps2_gpio_write(serio, val);
}
@@ -491,7 +491,7 @@ MODULE_DEVICE_TABLE(of, ps2_gpio_match);
static struct platform_driver ps2_gpio_driver = {
.probe = ps2_gpio_probe,
- .remove_new = ps2_gpio_remove,
+ .remove = ps2_gpio_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(ps2_gpio_match),
diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c
index 937ecdea491d..b96cee52fc52 100644
--- a/drivers/input/serio/ps2mult.c
+++ b/drivers/input/serio/ps2mult.c
@@ -76,9 +76,8 @@ static int ps2mult_serio_write(struct serio *serio, unsigned char data)
struct ps2mult *psm = serio_get_drvdata(mx_port);
struct ps2mult_port *port = serio->port_data;
bool need_escape;
- unsigned long flags;
- spin_lock_irqsave(&psm->lock, flags);
+ guard(spinlock_irqsave)(&psm->lock);
if (psm->out_port != port)
ps2mult_select_port(psm, port);
@@ -93,8 +92,6 @@ static int ps2mult_serio_write(struct serio *serio, unsigned char data)
serio_write(mx_port, data);
- spin_unlock_irqrestore(&psm->lock, flags);
-
return 0;
}
@@ -102,11 +99,10 @@ static int ps2mult_serio_start(struct serio *serio)
{
struct ps2mult *psm = serio_get_drvdata(serio->parent);
struct ps2mult_port *port = serio->port_data;
- unsigned long flags;
- spin_lock_irqsave(&psm->lock, flags);
+ guard(spinlock_irqsave)(&psm->lock);
+
port->registered = true;
- spin_unlock_irqrestore(&psm->lock, flags);
return 0;
}
@@ -115,11 +111,10 @@ static void ps2mult_serio_stop(struct serio *serio)
{
struct ps2mult *psm = serio_get_drvdata(serio->parent);
struct ps2mult_port *port = serio->port_data;
- unsigned long flags;
- spin_lock_irqsave(&psm->lock, flags);
+ guard(spinlock_irqsave)(&psm->lock);
+
port->registered = false;
- spin_unlock_irqrestore(&psm->lock, flags);
}
static int ps2mult_create_port(struct ps2mult *psm, int i)
@@ -148,16 +143,12 @@ static int ps2mult_create_port(struct ps2mult *psm, int i)
static void ps2mult_reset(struct ps2mult *psm)
{
- unsigned long flags;
-
- spin_lock_irqsave(&psm->lock, flags);
+ guard(spinlock_irqsave)(&psm->lock);
serio_write(psm->mx_serio, PS2MULT_SESSION_END);
serio_write(psm->mx_serio, PS2MULT_SESSION_START);
ps2mult_select_port(psm, &psm->ports[PS2MULT_KBD_PORT]);
-
- spin_unlock_irqrestore(&psm->lock, flags);
}
static int ps2mult_connect(struct serio *serio, struct serio_driver *drv)
@@ -234,11 +225,10 @@ static irqreturn_t ps2mult_interrupt(struct serio *serio,
{
struct ps2mult *psm = serio_get_drvdata(serio);
struct ps2mult_port *in_port;
- unsigned long flags;
dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, dfl);
- spin_lock_irqsave(&psm->lock, flags);
+ guard(spinlock_irqsave)(&psm->lock);
if (psm->escape) {
psm->escape = false;
@@ -285,7 +275,6 @@ static irqreturn_t ps2mult_interrupt(struct serio *serio,
}
out:
- spin_unlock_irqrestore(&psm->lock, flags);
return IRQ_HANDLED;
}
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index cd4d5be946a3..ae55c4de092f 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -39,17 +39,14 @@ struct q40kbd {
static irqreturn_t q40kbd_interrupt(int irq, void *dev_id)
{
struct q40kbd *q40kbd = dev_id;
- unsigned long flags;
- spin_lock_irqsave(&q40kbd->lock, flags);
+ guard(spinlock_irqsave)(&q40kbd->lock);
if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
serio_interrupt(q40kbd->port, master_inb(KEYCODE_REG), 0);
master_outb(-1, KEYBOARD_UNLOCK_REG);
- spin_unlock_irqrestore(&q40kbd->lock, flags);
-
return IRQ_HANDLED;
}
@@ -60,14 +57,11 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id)
static void q40kbd_flush(struct q40kbd *q40kbd)
{
int maxread = 100;
- unsigned long flags;
- spin_lock_irqsave(&q40kbd->lock, flags);
+ guard(spinlock_irqsave)(&q40kbd->lock);
while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
master_inb(KEYCODE_REG);
-
- spin_unlock_irqrestore(&q40kbd->lock, flags);
}
static void q40kbd_stop(void)
@@ -166,7 +160,7 @@ static struct platform_driver q40kbd_driver = {
.driver = {
.name = "q40kbd",
},
- .remove_new = q40kbd_remove,
+ .remove = q40kbd_remove,
};
module_platform_driver_probe(q40kbd_driver, q40kbd_probe);
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index e236bb7e1014..c65c552b0c45 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -144,7 +144,7 @@ static void rpckbd_remove(struct platform_device *dev)
static struct platform_driver rpckbd_driver = {
.probe = rpckbd_probe,
- .remove_new = rpckbd_remove,
+ .remove = rpckbd_remove,
.driver = {
.name = "kart",
},
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 1311caf7dba4..375c6f5f905c 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -92,7 +92,8 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
struct ps2if *ps2if = dev_id;
unsigned int status;
- spin_lock(&ps2if->lock);
+ guard(spinlock)(&ps2if->lock);
+
status = readl_relaxed(ps2if->base + PS2STAT);
if (ps2if->head == ps2if->tail) {
disable_irq_nosync(irq);
@@ -101,7 +102,6 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
writel_relaxed(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA);
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
}
- spin_unlock(&ps2if->lock);
return IRQ_HANDLED;
}
@@ -113,10 +113,9 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
static int ps2_write(struct serio *io, unsigned char val)
{
struct ps2if *ps2if = io->port_data;
- unsigned long flags;
unsigned int head;
- spin_lock_irqsave(&ps2if->lock, flags);
+ guard(spinlock_irqsave)(&ps2if->lock);
/*
* If the TX register is empty, we can go straight out.
@@ -133,7 +132,6 @@ static int ps2_write(struct serio *io, unsigned char val)
}
}
- spin_unlock_irqrestore(&ps2if->lock, flags);
return 0;
}
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 97d8eacb9112..4468018cef66 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -38,33 +38,27 @@ static void serio_attach_driver(struct serio_driver *drv);
static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
{
- int retval;
-
- mutex_lock(&serio->drv_mutex);
- retval = drv->connect(serio, drv);
- mutex_unlock(&serio->drv_mutex);
+ guard(mutex)(&serio->drv_mutex);
- return retval;
+ return drv->connect(serio, drv);
}
static int serio_reconnect_driver(struct serio *serio)
{
- int retval = -1;
+ guard(mutex)(&serio->drv_mutex);
- mutex_lock(&serio->drv_mutex);
if (serio->drv && serio->drv->reconnect)
- retval = serio->drv->reconnect(serio);
- mutex_unlock(&serio->drv_mutex);
+ return serio->drv->reconnect(serio);
- return retval;
+ return -1;
}
static void serio_disconnect_driver(struct serio *serio)
{
- mutex_lock(&serio->drv_mutex);
+ guard(mutex)(&serio->drv_mutex);
+
if (serio->drv)
serio->drv->disconnect(serio);
- mutex_unlock(&serio->drv_mutex);
}
static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
@@ -147,9 +141,8 @@ static LIST_HEAD(serio_event_list);
static struct serio_event *serio_get_event(void)
{
struct serio_event *event = NULL;
- unsigned long flags;
- spin_lock_irqsave(&serio_event_lock, flags);
+ guard(spinlock_irqsave)(&serio_event_lock);
if (!list_empty(&serio_event_list)) {
event = list_first_entry(&serio_event_list,
@@ -157,7 +150,6 @@ static struct serio_event *serio_get_event(void)
list_del_init(&event->node);
}
- spin_unlock_irqrestore(&serio_event_lock, flags);
return event;
}
@@ -171,9 +163,8 @@ static void serio_remove_duplicate_events(void *object,
enum serio_event_type type)
{
struct serio_event *e, *next;
- unsigned long flags;
- spin_lock_irqsave(&serio_event_lock, flags);
+ guard(spinlock_irqsave)(&serio_event_lock);
list_for_each_entry_safe(e, next, &serio_event_list, node) {
if (object == e->object) {
@@ -189,15 +180,13 @@ static void serio_remove_duplicate_events(void *object,
serio_free_event(e);
}
}
-
- spin_unlock_irqrestore(&serio_event_lock, flags);
}
static void serio_handle_event(struct work_struct *work)
{
struct serio_event *event;
- mutex_lock(&serio_mutex);
+ guard(mutex)(&serio_mutex);
while ((event = serio_get_event())) {
@@ -228,8 +217,6 @@ static void serio_handle_event(struct work_struct *work)
serio_remove_duplicate_events(event->object, event->type);
serio_free_event(event);
}
-
- mutex_unlock(&serio_mutex);
}
static DECLARE_WORK(serio_event_work, serio_handle_event);
@@ -237,11 +224,9 @@ static DECLARE_WORK(serio_event_work, serio_handle_event);
static int serio_queue_event(void *object, struct module *owner,
enum serio_event_type event_type)
{
- unsigned long flags;
struct serio_event *event;
- int retval = 0;
- spin_lock_irqsave(&serio_event_lock, flags);
+ guard(spinlock_irqsave)(&serio_event_lock);
/*
* Scan event list for the other events for the same serio port,
@@ -253,7 +238,7 @@ static int serio_queue_event(void *object, struct module *owner,
list_for_each_entry_reverse(event, &serio_event_list, node) {
if (event->object == object) {
if (event->type == event_type)
- goto out;
+ return 0;
break;
}
}
@@ -261,16 +246,14 @@ static int serio_queue_event(void *object, struct module *owner,
event = kmalloc(sizeof(*event), GFP_ATOMIC);
if (!event) {
pr_err("Not enough memory to queue event %d\n", event_type);
- retval = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
if (!try_module_get(owner)) {
pr_warn("Can't get module reference, dropping event %d\n",
event_type);
kfree(event);
- retval = -EINVAL;
- goto out;
+ return -EINVAL;
}
event->type = event_type;
@@ -280,9 +263,7 @@ static int serio_queue_event(void *object, struct module *owner,
list_add_tail(&event->node, &serio_event_list);
queue_work(system_long_wq, &serio_event_work);
-out:
- spin_unlock_irqrestore(&serio_event_lock, flags);
- return retval;
+ return 0;
}
/*
@@ -292,9 +273,8 @@ out:
static void serio_remove_pending_events(void *object)
{
struct serio_event *event, *next;
- unsigned long flags;
- spin_lock_irqsave(&serio_event_lock, flags);
+ guard(spinlock_irqsave)(&serio_event_lock);
list_for_each_entry_safe(event, next, &serio_event_list, node) {
if (event->object == object) {
@@ -302,8 +282,6 @@ static void serio_remove_pending_events(void *object)
serio_free_event(event);
}
}
-
- spin_unlock_irqrestore(&serio_event_lock, flags);
}
/*
@@ -315,23 +293,19 @@ static void serio_remove_pending_events(void *object)
static struct serio *serio_get_pending_child(struct serio *parent)
{
struct serio_event *event;
- struct serio *serio, *child = NULL;
- unsigned long flags;
+ struct serio *serio;
- spin_lock_irqsave(&serio_event_lock, flags);
+ guard(spinlock_irqsave)(&serio_event_lock);
list_for_each_entry(event, &serio_event_list, node) {
if (event->type == SERIO_REGISTER_PORT) {
serio = event->object;
- if (serio->parent == parent) {
- child = serio;
- break;
- }
+ if (serio->parent == parent)
+ return serio;
}
}
- spin_unlock_irqrestore(&serio_event_lock, flags);
- return child;
+ return NULL;
}
/*
@@ -382,29 +356,27 @@ static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, c
struct device_driver *drv;
int error;
- error = mutex_lock_interruptible(&serio_mutex);
- if (error)
- return error;
-
- if (!strncmp(buf, "none", count)) {
- serio_disconnect_port(serio);
- } else if (!strncmp(buf, "reconnect", count)) {
- serio_reconnect_subtree(serio);
- } else if (!strncmp(buf, "rescan", count)) {
- serio_disconnect_port(serio);
- serio_find_driver(serio);
- serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
- } else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
- serio_disconnect_port(serio);
- error = serio_bind_driver(serio, to_serio_driver(drv));
- serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
- } else {
- error = -EINVAL;
+ scoped_cond_guard(mutex_intr, return -EINTR, &serio_mutex) {
+ if (!strncmp(buf, "none", count)) {
+ serio_disconnect_port(serio);
+ } else if (!strncmp(buf, "reconnect", count)) {
+ serio_reconnect_subtree(serio);
+ } else if (!strncmp(buf, "rescan", count)) {
+ serio_disconnect_port(serio);
+ serio_find_driver(serio);
+ serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
+ } else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
+ serio_disconnect_port(serio);
+ error = serio_bind_driver(serio, to_serio_driver(drv));
+ serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT);
+ if (error)
+ return error;
+ } else {
+ return -EINVAL;
+ }
}
- mutex_unlock(&serio_mutex);
-
- return error ? error : count;
+ return count;
}
static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf)
@@ -526,9 +498,9 @@ static void serio_add_port(struct serio *serio)
int error;
if (parent) {
- serio_pause_rx(parent);
+ guard(serio_pause_rx)(parent);
+
list_add_tail(&serio->child_node, &parent->children);
- serio_continue_rx(parent);
}
list_add_tail(&serio->node, &serio_list);
@@ -560,9 +532,9 @@ static void serio_destroy_port(struct serio *serio)
serio->stop(serio);
if (serio->parent) {
- serio_pause_rx(serio->parent);
+ guard(serio_pause_rx)(serio->parent);
+
list_del_init(&serio->child_node);
- serio_continue_rx(serio->parent);
serio->parent = NULL;
}
@@ -701,10 +673,10 @@ EXPORT_SYMBOL(__serio_register_port);
*/
void serio_unregister_port(struct serio *serio)
{
- mutex_lock(&serio_mutex);
+ guard(mutex)(&serio_mutex);
+
serio_disconnect_port(serio);
serio_destroy_port(serio);
- mutex_unlock(&serio_mutex);
}
EXPORT_SYMBOL(serio_unregister_port);
@@ -715,12 +687,12 @@ void serio_unregister_child_port(struct serio *serio)
{
struct serio *s, *next;
- mutex_lock(&serio_mutex);
+ guard(mutex)(&serio_mutex);
+
list_for_each_entry_safe(s, next, &serio->children, child_node) {
serio_disconnect_port(s);
serio_destroy_port(s);
}
- mutex_unlock(&serio_mutex);
}
EXPORT_SYMBOL(serio_unregister_child_port);
@@ -784,10 +756,10 @@ static void serio_driver_remove(struct device *dev)
static void serio_cleanup(struct serio *serio)
{
- mutex_lock(&serio->drv_mutex);
+ guard(mutex)(&serio->drv_mutex);
+
if (serio->drv && serio->drv->cleanup)
serio->drv->cleanup(serio);
- mutex_unlock(&serio->drv_mutex);
}
static void serio_shutdown(struct device *dev)
@@ -850,7 +822,7 @@ void serio_unregister_driver(struct serio_driver *drv)
{
struct serio *serio;
- mutex_lock(&serio_mutex);
+ guard(mutex)(&serio_mutex);
drv->manual_bind = true; /* so serio_find_driver ignores it */
serio_remove_pending_events(drv);
@@ -866,15 +838,14 @@ start_over:
}
driver_unregister(&drv->driver);
- mutex_unlock(&serio_mutex);
}
EXPORT_SYMBOL(serio_unregister_driver);
static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
{
- serio_pause_rx(serio);
+ guard(serio_pause_rx)(serio);
+
serio->drv = drv;
- serio_continue_rx(serio);
}
static int serio_bus_match(struct device *dev, const struct device_driver *drv)
@@ -935,14 +906,14 @@ static int serio_resume(struct device *dev)
struct serio *serio = to_serio_port(dev);
int error = -ENOENT;
- mutex_lock(&serio->drv_mutex);
- if (serio->drv && serio->drv->fast_reconnect) {
- error = serio->drv->fast_reconnect(serio);
- if (error && error != -ENOENT)
- dev_warn(dev, "fast reconnect failed with error %d\n",
- error);
+ scoped_guard(mutex, &serio->drv_mutex) {
+ if (serio->drv && serio->drv->fast_reconnect) {
+ error = serio->drv->fast_reconnect(serio);
+ if (error && error != -ENOENT)
+ dev_warn(dev, "fast reconnect failed with error %d\n",
+ error);
+ }
}
- mutex_unlock(&serio->drv_mutex);
if (error) {
/*
@@ -989,21 +960,17 @@ EXPORT_SYMBOL(serio_close);
irqreturn_t serio_interrupt(struct serio *serio,
unsigned char data, unsigned int dfl)
{
- unsigned long flags;
- irqreturn_t ret = IRQ_NONE;
+ guard(spinlock_irqsave)(&serio->lock);
- spin_lock_irqsave(&serio->lock, flags);
+ if (likely(serio->drv))
+ return serio->drv->interrupt(serio, data, dfl);
- if (likely(serio->drv)) {
- ret = serio->drv->interrupt(serio, data, dfl);
- } else if (!dfl && device_is_registered(&serio->dev)) {
+ if (!dfl && device_is_registered(&serio->dev)) {
serio_rescan(serio);
- ret = IRQ_HANDLED;
+ return IRQ_HANDLED;
}
- spin_unlock_irqrestore(&serio->lock, flags);
-
- return ret;
+ return IRQ_NONE;
}
EXPORT_SYMBOL(serio_interrupt);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 0186d1b38f49..4d6395088986 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -29,7 +29,7 @@ struct serio_raw {
unsigned char queue[SERIO_RAW_QUEUE_LEN];
unsigned int tail, head;
- char name[16];
+ char name[20];
struct kref kref;
struct serio *serio;
struct miscdevice dev;
@@ -75,41 +75,31 @@ static int serio_raw_open(struct inode *inode, struct file *file)
{
struct serio_raw *serio_raw;
struct serio_raw_client *client;
- int retval;
- retval = mutex_lock_interruptible(&serio_raw_mutex);
- if (retval)
- return retval;
+ scoped_guard(mutex_intr, &serio_raw_mutex) {
+ serio_raw = serio_raw_locate(iminor(inode));
+ if (!serio_raw)
+ return -ENODEV;
- serio_raw = serio_raw_locate(iminor(inode));
- if (!serio_raw) {
- retval = -ENODEV;
- goto out;
- }
+ if (serio_raw->dead)
+ return -ENODEV;
- if (serio_raw->dead) {
- retval = -ENODEV;
- goto out;
- }
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (!client) {
- retval = -ENOMEM;
- goto out;
- }
+ client->serio_raw = serio_raw;
+ file->private_data = client;
- client->serio_raw = serio_raw;
- file->private_data = client;
+ kref_get(&serio_raw->kref);
- kref_get(&serio_raw->kref);
+ scoped_guard(serio_pause_rx, serio_raw->serio)
+ list_add_tail(&client->node, &serio_raw->client_list);
- serio_pause_rx(serio_raw->serio);
- list_add_tail(&client->node, &serio_raw->client_list);
- serio_continue_rx(serio_raw->serio);
+ return 0;
+ }
-out:
- mutex_unlock(&serio_raw_mutex);
- return retval;
+ return -EINTR;
}
static void serio_raw_free(struct kref *kref)
@@ -126,9 +116,8 @@ static int serio_raw_release(struct inode *inode, struct file *file)
struct serio_raw_client *client = file->private_data;
struct serio_raw *serio_raw = client->serio_raw;
- serio_pause_rx(serio_raw->serio);
- list_del(&client->node);
- serio_continue_rx(serio_raw->serio);
+ scoped_guard(serio_pause_rx, serio_raw->serio)
+ list_del(&client->node);
kfree(client);
@@ -139,19 +128,15 @@ static int serio_raw_release(struct inode *inode, struct file *file)
static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
{
- bool empty;
+ guard(serio_pause_rx)(serio_raw->serio);
- serio_pause_rx(serio_raw->serio);
-
- empty = serio_raw->head == serio_raw->tail;
- if (!empty) {
- *c = serio_raw->queue[serio_raw->tail];
- serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
- }
+ if (serio_raw->head == serio_raw->tail)
+ return false; /* queue is empty */
- serio_continue_rx(serio_raw->serio);
+ *c = serio_raw->queue[serio_raw->tail];
+ serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
- return !empty;
+ return true;
}
static ssize_t serio_raw_read(struct file *file, char __user *buffer,
@@ -200,40 +185,32 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
{
struct serio_raw_client *client = file->private_data;
struct serio_raw *serio_raw = client->serio_raw;
- int retval = 0;
+ int written = 0;
unsigned char c;
- retval = mutex_lock_interruptible(&serio_raw_mutex);
- if (retval)
- return retval;
+ scoped_guard(mutex_intr, &serio_raw_mutex) {
+ if (serio_raw->dead)
+ return -ENODEV;
- if (serio_raw->dead) {
- retval = -ENODEV;
- goto out;
- }
+ if (count > 32)
+ count = 32;
- if (count > 32)
- count = 32;
+ while (count--) {
+ if (get_user(c, buffer++))
+ return -EFAULT;
- while (count--) {
- if (get_user(c, buffer++)) {
- retval = -EFAULT;
- goto out;
- }
+ if (serio_write(serio_raw->serio, c)) {
+ /* Either signal error or partial write */
+ return written ?: -EIO;
+ }
- if (serio_write(serio_raw->serio, c)) {
- /* Either signal error or partial write */
- if (retval == 0)
- retval = -EIO;
- goto out;
+ written++;
}
- retval++;
+ return written;
}
-out:
- mutex_unlock(&serio_raw_mutex);
- return retval;
+ return -EINTR;
}
static __poll_t serio_raw_poll(struct file *file, poll_table *wait)
@@ -300,7 +277,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
}
snprintf(serio_raw->name, sizeof(serio_raw->name),
- "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no));
+ "serio_raw%u", atomic_inc_return(&serio_raw_no));
kref_init(&serio_raw->kref);
INIT_LIST_HEAD(&serio_raw->client_list);
init_waitqueue_head(&serio_raw->wait);
@@ -379,10 +356,10 @@ static void serio_raw_hangup(struct serio_raw *serio_raw)
{
struct serio_raw_client *client;
- serio_pause_rx(serio_raw->serio);
- list_for_each_entry(client, &serio_raw->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- serio_continue_rx(serio_raw->serio);
+ scoped_guard(serio_pause_rx, serio_raw->serio) {
+ list_for_each_entry(client, &serio_raw->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ }
wake_up_interruptible(&serio_raw->wait);
}
@@ -394,10 +371,10 @@ static void serio_raw_disconnect(struct serio *serio)
misc_deregister(&serio_raw->dev);
- mutex_lock(&serio_raw_mutex);
- serio_raw->dead = true;
- list_del_init(&serio_raw->node);
- mutex_unlock(&serio_raw_mutex);
+ scoped_guard(mutex, &serio_raw_mutex) {
+ serio_raw->dead = true;
+ list_del_init(&serio_raw->node);
+ }
serio_raw_hangup(serio_raw);
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 5a2b5404ffc2..74ac88796187 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -50,11 +50,9 @@ static int serport_serio_write(struct serio *serio, unsigned char data)
static int serport_serio_open(struct serio *serio)
{
struct serport *serport = serio->port_data;
- unsigned long flags;
- spin_lock_irqsave(&serport->lock, flags);
+ guard(spinlock_irqsave)(&serport->lock);
set_bit(SERPORT_ACTIVE, &serport->flags);
- spin_unlock_irqrestore(&serport->lock, flags);
return 0;
}
@@ -63,11 +61,9 @@ static int serport_serio_open(struct serio *serio)
static void serport_serio_close(struct serio *serio)
{
struct serport *serport = serio->port_data;
- unsigned long flags;
- spin_lock_irqsave(&serport->lock, flags);
+ guard(spinlock_irqsave)(&serport->lock);
clear_bit(SERPORT_ACTIVE, &serport->flags);
- spin_unlock_irqrestore(&serport->lock, flags);
}
/*
@@ -118,14 +114,13 @@ static void serport_ldisc_receive(struct tty_struct *tty, const u8 *cp,
const u8 *fp, size_t count)
{
struct serport *serport = tty->disc_data;
- unsigned long flags;
unsigned int ch_flags = 0;
int i;
- spin_lock_irqsave(&serport->lock, flags);
+ guard(spinlock_irqsave)(&serport->lock);
if (!test_bit(SERPORT_ACTIVE, &serport->flags))
- goto out;
+ return;
for (i = 0; i < count; i++) {
if (fp) {
@@ -146,9 +141,6 @@ static void serport_ldisc_receive(struct tty_struct *tty, const u8 *cp,
serio_interrupt(serport->serio, cp[i], ch_flags);
}
-
-out:
- spin_unlock_irqrestore(&serport->lock, flags);
}
/*
@@ -246,11 +238,9 @@ static int serport_ldisc_compat_ioctl(struct tty_struct *tty,
static void serport_ldisc_hangup(struct tty_struct *tty)
{
struct serport *serport = tty->disc_data;
- unsigned long flags;
- spin_lock_irqsave(&serport->lock, flags);
- set_bit(SERPORT_DEAD, &serport->flags);
- spin_unlock_irqrestore(&serport->lock, flags);
+ scoped_guard(spinlock_irqsave, &serport->lock)
+ set_bit(SERPORT_DEAD, &serport->flags);
wake_up_interruptible(&serport->wait);
}
@@ -258,12 +248,11 @@ static void serport_ldisc_hangup(struct tty_struct *tty)
static void serport_ldisc_write_wakeup(struct tty_struct * tty)
{
struct serport *serport = tty->disc_data;
- unsigned long flags;
- spin_lock_irqsave(&serport->lock, flags);
+ guard(spinlock_irqsave)(&serport->lock);
+
if (test_bit(SERPORT_ACTIVE, &serport->flags))
serio_drv_write_wakeup(serport->serio);
- spin_unlock_irqrestore(&serport->lock, flags);
}
/*
diff --git a/drivers/input/serio/sun4i-ps2.c b/drivers/input/serio/sun4i-ps2.c
index 95cd8aaee65d..524929ce1cae 100644
--- a/drivers/input/serio/sun4i-ps2.c
+++ b/drivers/input/serio/sun4i-ps2.c
@@ -101,7 +101,7 @@ static irqreturn_t sun4i_ps2_interrupt(int irq, void *dev_id)
unsigned int rxflags = 0;
u32 rval;
- spin_lock(&drvdata->lock);
+ guard(spinlock)(&drvdata->lock);
/* Get the PS/2 interrupts and clear them */
intr_status = readl(drvdata->reg_base + PS2_REG_LSTS);
@@ -134,8 +134,6 @@ static irqreturn_t sun4i_ps2_interrupt(int irq, void *dev_id)
writel(intr_status, drvdata->reg_base + PS2_REG_LSTS);
writel(fifo_status, drvdata->reg_base + PS2_REG_FSTS);
- spin_unlock(&drvdata->lock);
-
return IRQ_HANDLED;
}
@@ -146,7 +144,6 @@ static int sun4i_ps2_open(struct serio *serio)
u32 clk_scdf;
u32 clk_pcdf;
u32 rval;
- unsigned long flags;
/* Set line control and enable interrupt */
rval = PS2_LCTL_STOPERREN | PS2_LCTL_ACKERREN
@@ -171,9 +168,8 @@ static int sun4i_ps2_open(struct serio *serio)
rval = PS2_GCTL_RESET | PS2_GCTL_INTEN | PS2_GCTL_MASTER
| PS2_GCTL_BUSEN;
- spin_lock_irqsave(&drvdata->lock, flags);
+ guard(spinlock_irqsave)(&drvdata->lock);
writel(rval, drvdata->reg_base + PS2_REG_GCTL);
- spin_unlock_irqrestore(&drvdata->lock, flags);
return 0;
}
@@ -322,7 +318,7 @@ MODULE_DEVICE_TABLE(of, sun4i_ps2_match);
static struct platform_driver sun4i_ps2_driver = {
.probe = sun4i_ps2_probe,
- .remove_new = sun4i_ps2_remove,
+ .remove = sun4i_ps2_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = sun4i_ps2_match,
diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c
index 1ab12b247f98..7f627b08055e 100644
--- a/drivers/input/serio/userio.c
+++ b/drivers/input/serio/userio.c
@@ -55,18 +55,15 @@ struct userio_device {
static int userio_device_write(struct serio *id, unsigned char val)
{
struct userio_device *userio = id->port_data;
- unsigned long flags;
- spin_lock_irqsave(&userio->buf_lock, flags);
+ scoped_guard(spinlock_irqsave, &userio->buf_lock) {
+ userio->buf[userio->head] = val;
+ userio->head = (userio->head + 1) % USERIO_BUFSIZE;
- userio->buf[userio->head] = val;
- userio->head = (userio->head + 1) % USERIO_BUFSIZE;
-
- if (userio->head == userio->tail)
- dev_warn(userio_misc.this_device,
- "Buffer overflowed, userio client isn't keeping up");
-
- spin_unlock_irqrestore(&userio->buf_lock, flags);
+ if (userio->head == userio->tail)
+ dev_warn(userio_misc.this_device,
+ "Buffer overflowed, userio client isn't keeping up");
+ }
wake_up_interruptible(&userio->waitq);
@@ -75,9 +72,8 @@ static int userio_device_write(struct serio *id, unsigned char val)
static int userio_char_open(struct inode *inode, struct file *file)
{
- struct userio_device *userio;
-
- userio = kzalloc(sizeof(*userio), GFP_KERNEL);
+ struct userio_device *userio __free(kfree) =
+ kzalloc(sizeof(*userio), GFP_KERNEL);
if (!userio)
return -ENOMEM;
@@ -86,15 +82,13 @@ static int userio_char_open(struct inode *inode, struct file *file)
init_waitqueue_head(&userio->waitq);
userio->serio = kzalloc(sizeof(*userio->serio), GFP_KERNEL);
- if (!userio->serio) {
- kfree(userio);
+ if (!userio->serio)
return -ENOMEM;
- }
userio->serio->write = userio_device_write;
userio->serio->port_data = userio;
- file->private_data = userio;
+ file->private_data = no_free_ptr(userio);
return 0;
}
@@ -118,14 +112,32 @@ static int userio_char_release(struct inode *inode, struct file *file)
return 0;
}
+static size_t userio_fetch_data(struct userio_device *userio, u8 *buf,
+ size_t count, size_t *copylen)
+{
+ size_t available, len;
+
+ guard(spinlock_irqsave)(&userio->buf_lock);
+
+ available = CIRC_CNT_TO_END(userio->head, userio->tail,
+ USERIO_BUFSIZE);
+ len = min(available, count);
+ if (len) {
+ memcpy(buf, &userio->buf[userio->tail], len);
+ userio->tail = (userio->tail + len) % USERIO_BUFSIZE;
+ }
+
+ *copylen = len;
+ return available;
+}
+
static ssize_t userio_char_read(struct file *file, char __user *user_buffer,
size_t count, loff_t *ppos)
{
struct userio_device *userio = file->private_data;
int error;
- size_t nonwrap_len, copylen;
- unsigned char buf[USERIO_BUFSIZE];
- unsigned long flags;
+ size_t available, copylen;
+ u8 buf[USERIO_BUFSIZE];
/*
* By the time we get here, the data that was waiting might have
@@ -135,21 +147,8 @@ static ssize_t userio_char_read(struct file *file, char __user *user_buffer,
* of course).
*/
for (;;) {
- spin_lock_irqsave(&userio->buf_lock, flags);
-
- nonwrap_len = CIRC_CNT_TO_END(userio->head,
- userio->tail,
- USERIO_BUFSIZE);
- copylen = min(nonwrap_len, count);
- if (copylen) {
- memcpy(buf, &userio->buf[userio->tail], copylen);
- userio->tail = (userio->tail + copylen) %
- USERIO_BUFSIZE;
- }
-
- spin_unlock_irqrestore(&userio->buf_lock, flags);
-
- if (nonwrap_len)
+ available = userio_fetch_data(userio, buf, count, &copylen);
+ if (available)
break;
/* buffer was/is empty */
@@ -176,40 +175,21 @@ static ssize_t userio_char_read(struct file *file, char __user *user_buffer,
return copylen;
}
-static ssize_t userio_char_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *ppos)
+static int userio_execute_cmd(struct userio_device *userio,
+ const struct userio_cmd *cmd)
{
- struct userio_device *userio = file->private_data;
- struct userio_cmd cmd;
- int error;
-
- if (count != sizeof(cmd)) {
- dev_warn(userio_misc.this_device, "Invalid payload size\n");
- return -EINVAL;
- }
-
- if (copy_from_user(&cmd, buffer, sizeof(cmd)))
- return -EFAULT;
-
- error = mutex_lock_interruptible(&userio->mutex);
- if (error)
- return error;
-
- switch (cmd.type) {
+ switch (cmd->type) {
case USERIO_CMD_REGISTER:
if (!userio->serio->id.type) {
dev_warn(userio_misc.this_device,
"No port type given on /dev/userio\n");
-
- error = -EINVAL;
- goto out;
+ return -EINVAL;
}
if (userio->running) {
dev_warn(userio_misc.this_device,
"Begin command sent, but we're already running\n");
- error = -EBUSY;
- goto out;
+ return -EBUSY;
}
userio->running = true;
@@ -220,32 +200,51 @@ static ssize_t userio_char_write(struct file *file, const char __user *buffer,
if (userio->running) {
dev_warn(userio_misc.this_device,
"Can't change port type on an already running userio instance\n");
- error = -EBUSY;
- goto out;
+ return -EBUSY;
}
- userio->serio->id.type = cmd.data;
+ userio->serio->id.type = cmd->data;
break;
case USERIO_CMD_SEND_INTERRUPT:
if (!userio->running) {
dev_warn(userio_misc.this_device,
"The device must be registered before sending interrupts\n");
- error = -ENODEV;
- goto out;
+ return -ENODEV;
}
- serio_interrupt(userio->serio, cmd.data, 0);
+ serio_interrupt(userio->serio, cmd->data, 0);
break;
default:
- error = -EOPNOTSUPP;
- goto out;
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static ssize_t userio_char_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct userio_device *userio = file->private_data;
+ struct userio_cmd cmd;
+ int error;
+
+ if (count != sizeof(cmd)) {
+ dev_warn(userio_misc.this_device, "Invalid payload size\n");
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&cmd, buffer, sizeof(cmd)))
+ return -EFAULT;
+
+ scoped_cond_guard(mutex_intr, return -EINTR, &userio->mutex) {
+ error = userio_execute_cmd(userio, &cmd);
+ if (error)
+ return error;
}
-out:
- mutex_unlock(&userio->mutex);
- return error ?: count;
+ return count;
}
static __poll_t userio_char_poll(struct file *file, poll_table *wait)
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 1543267d02ac..01433f0b48f1 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -155,22 +155,17 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
static int sxps2_write(struct serio *pserio, unsigned char c)
{
struct xps2data *drvdata = pserio->port_data;
- unsigned long flags;
u32 sr;
- int status = -1;
- spin_lock_irqsave(&drvdata->lock, flags);
+ guard(spinlock_irqsave)(&drvdata->lock);
/* If the PS/2 transmitter is empty send a byte of data */
sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
- if (!(sr & XPS2_STATUS_TX_FULL)) {
- out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
- status = 0;
- }
+ if (sr & XPS2_STATUS_TX_FULL)
+ return -EAGAIN;
- spin_unlock_irqrestore(&drvdata->lock, flags);
-
- return status;
+ out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
+ return 0;
}
/**
@@ -358,7 +353,7 @@ static struct platform_driver xps2_of_driver = {
.of_match_table = xps2_of_match,
},
.probe = xps2_of_probe,
- .remove_new = xps2_of_remove,
+ .remove = xps2_of_remove,
};
module_platform_driver(xps2_of_driver);
diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c
index a68da2988f9c..8d6b71d59793 100644
--- a/drivers/input/tablet/pegasus_notetaker.c
+++ b/drivers/input/tablet/pegasus_notetaker.c
@@ -214,6 +214,28 @@ static void pegasus_init(struct work_struct *work)
error);
}
+static int __pegasus_open(struct pegasus *pegasus)
+{
+ int error;
+
+ guard(mutex)(&pegasus->pm_mutex);
+
+ pegasus->irq->dev = pegasus->usbdev;
+ if (usb_submit_urb(pegasus->irq, GFP_KERNEL))
+ return -EIO;
+
+ error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE);
+ if (error) {
+ usb_kill_urb(pegasus->irq);
+ cancel_work_sync(&pegasus->init);
+ return error;
+ }
+
+ pegasus->is_open = true;
+
+ return 0;
+}
+
static int pegasus_open(struct input_dev *dev)
{
struct pegasus *pegasus = input_get_drvdata(dev);
@@ -223,39 +245,25 @@ static int pegasus_open(struct input_dev *dev)
if (error)
return error;
- mutex_lock(&pegasus->pm_mutex);
- pegasus->irq->dev = pegasus->usbdev;
- if (usb_submit_urb(pegasus->irq, GFP_KERNEL)) {
- error = -EIO;
- goto err_autopm_put;
+ error = __pegasus_open(pegasus);
+ if (error) {
+ usb_autopm_put_interface(pegasus->intf);
+ return error;
}
- error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE);
- if (error)
- goto err_kill_urb;
-
- pegasus->is_open = true;
- mutex_unlock(&pegasus->pm_mutex);
return 0;
-
-err_kill_urb:
- usb_kill_urb(pegasus->irq);
- cancel_work_sync(&pegasus->init);
-err_autopm_put:
- mutex_unlock(&pegasus->pm_mutex);
- usb_autopm_put_interface(pegasus->intf);
- return error;
}
static void pegasus_close(struct input_dev *dev)
{
struct pegasus *pegasus = input_get_drvdata(dev);
- mutex_lock(&pegasus->pm_mutex);
- usb_kill_urb(pegasus->irq);
- cancel_work_sync(&pegasus->init);
- pegasus->is_open = false;
- mutex_unlock(&pegasus->pm_mutex);
+ scoped_guard(mutex, &pegasus->pm_mutex) {
+ usb_kill_urb(pegasus->irq);
+ cancel_work_sync(&pegasus->init);
+
+ pegasus->is_open = false;
+ }
usb_autopm_put_interface(pegasus->intf);
}
@@ -411,10 +419,10 @@ static int pegasus_suspend(struct usb_interface *intf, pm_message_t message)
{
struct pegasus *pegasus = usb_get_intfdata(intf);
- mutex_lock(&pegasus->pm_mutex);
+ guard(mutex)(&pegasus->pm_mutex);
+
usb_kill_urb(pegasus->irq);
cancel_work_sync(&pegasus->init);
- mutex_unlock(&pegasus->pm_mutex);
return 0;
}
@@ -422,31 +430,33 @@ static int pegasus_suspend(struct usb_interface *intf, pm_message_t message)
static int pegasus_resume(struct usb_interface *intf)
{
struct pegasus *pegasus = usb_get_intfdata(intf);
- int retval = 0;
- mutex_lock(&pegasus->pm_mutex);
+ guard(mutex)(&pegasus->pm_mutex);
+
if (pegasus->is_open && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0)
- retval = -EIO;
- mutex_unlock(&pegasus->pm_mutex);
+ return -EIO;
- return retval;
+ return 0;
}
static int pegasus_reset_resume(struct usb_interface *intf)
{
struct pegasus *pegasus = usb_get_intfdata(intf);
- int retval = 0;
+ int error;
+
+ guard(mutex)(&pegasus->pm_mutex);
- mutex_lock(&pegasus->pm_mutex);
if (pegasus->is_open) {
- retval = pegasus_set_mode(pegasus, PEN_MODE_XY,
+ error = pegasus_set_mode(pegasus, PEN_MODE_XY,
NOTETAKER_LED_MOUSE);
- if (!retval && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0)
- retval = -EIO;
+ if (error)
+ return error;
+
+ if (usb_submit_urb(pegasus->irq, GFP_NOIO) < 0)
+ return -EIO;
}
- mutex_unlock(&pegasus->pm_mutex);
- return retval;
+ return 0;
}
static const struct usb_device_id pegasus_ids[] = {
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
index 81a3ea4b9a3d..0468ce2b216f 100644
--- a/drivers/input/touchscreen/88pm860x-ts.c
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -117,13 +117,14 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
struct pm860x_chip *chip,
int *res_x)
{
- struct device_node *np = pdev->dev.parent->of_node;
struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
: chip->companion;
int data, n, ret;
- if (!np)
+ if (!pdev->dev.parent->of_node)
return -ENODEV;
- np = of_get_child_by_name(np, "touch");
+
+ struct device_node *np __free(device_node) =
+ of_get_child_by_name(pdev->dev.parent->of_node, "touch");
if (!np) {
dev_err(&pdev->dev, "Can't find touch node\n");
return -EINVAL;
@@ -141,13 +142,13 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
if (data) {
ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
if (ret < 0)
- goto err_put_node;
+ return -EINVAL;
}
/* set tsi prebias time */
if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
if (ret < 0)
- goto err_put_node;
+ return -EINVAL;
}
/* set prebias & prechg time of pen detect */
data = 0;
@@ -158,18 +159,11 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
if (data) {
ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
if (ret < 0)
- goto err_put_node;
+ return -EINVAL;
}
of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
- of_node_put(np);
-
return 0;
-
-err_put_node:
- of_node_put(np);
-
- return -EINVAL;
}
#else
#define pm860x_touch_dt_init(x, y, z) (-1)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 1ac26fc2e3eb..1a03de7fcfa6 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -420,6 +420,7 @@ config TOUCHSCREEN_GOODIX_BERLIN_SPI
config TOUCHSCREEN_HIDEEP
tristate "HiDeep Touch IC"
depends on I2C
+ select REGMAP_I2C
help
Say Y here if you have a touchscreen using HiDeep.
@@ -431,6 +432,7 @@ config TOUCHSCREEN_HIDEEP
config TOUCHSCREEN_HYCON_HY46XX
tristate "Hycon hy46xx touchscreen support"
depends on I2C
+ select REGMAP_I2C
help
Say Y here if you have a touchscreen using Hycon hy46xx
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 607f18af7010..066dc04003fa 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -331,7 +331,7 @@ struct ser_req {
u8 ref_off;
u16 scratch;
struct spi_message msg;
- struct spi_transfer xfer[6];
+ struct spi_transfer xfer[8];
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
@@ -405,9 +405,19 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
req->xfer[5].rx_buf = &req->scratch;
req->xfer[5].len = 2;
- CS_CHANGE(req->xfer[5]);
spi_message_add_tail(&req->xfer[5], &req->msg);
+ /* clear the command register */
+ req->scratch = 0;
+ req->xfer[6].tx_buf = &req->scratch;
+ req->xfer[6].len = 1;
+ spi_message_add_tail(&req->xfer[6], &req->msg);
+
+ req->xfer[7].rx_buf = &req->scratch;
+ req->xfer[7].len = 2;
+ CS_CHANGE(req->xfer[7]);
+ spi_message_add_tail(&req->xfer[7], &req->msg);
+
mutex_lock(&ts->lock);
ads7846_stop(ts);
status = spi_sync(spi, &req->msg);
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 8db2a112a476..363a4a1f1560 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -72,7 +72,7 @@
/*
* Interrupt modes:
- * periodical: interrupt is asserted periodicaly
+ * periodical: interrupt is asserted periodically
* compare coordinates: interrupt is asserted when coordinates change
* indicate touch: interrupt is asserted during touch
*/
diff --git a/drivers/input/touchscreen/bcm_iproc_tsc.c b/drivers/input/touchscreen/bcm_iproc_tsc.c
index 9c84235327bf..e49bde50d77a 100644
--- a/drivers/input/touchscreen/bcm_iproc_tsc.c
+++ b/drivers/input/touchscreen/bcm_iproc_tsc.c
@@ -217,7 +217,7 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data)
"pen up-down (%d)\n", priv->pen_status);
}
- /* coordinates in FIFO exceed the theshold */
+ /* coordinates in FIFO exceed the threshold */
if (intr_status & TS_FIFO_INTR_MASK) {
for (i = 0; i < priv->cfg_params.fifo_threshold; i++) {
regmap_read(priv->regmap, FIFO_DATA, &raw_coordinate);
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
index 52e0e834e76f..c2d3252f8466 100644
--- a/drivers/input/touchscreen/da9052_tsi.c
+++ b/drivers/input/touchscreen/da9052_tsi.c
@@ -326,7 +326,7 @@ static void da9052_ts_remove(struct platform_device *pdev)
static struct platform_driver da9052_tsi_driver = {
.probe = da9052_ts_probe,
- .remove_new = da9052_ts_remove,
+ .remove = da9052_ts_remove,
.driver = {
.name = "da9052-tsi",
},
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 85c6d8ce003f..0d7bf18e2508 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -1237,7 +1237,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
}
/*
- * Check which sleep modes we can support. Power-off requieres the
+ * Check which sleep modes we can support. Power-off requires the
* reset-pin to ensure correct power-down/power-up behaviour. Start with
* the EDT_PMODE_POWEROFF test since this is the deepest possible sleep
* mode.
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index eb883db55420..ad209e6e82a6 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -225,10 +225,10 @@ static int elo_command_10(struct elo *elo, unsigned char *packet)
mutex_lock(&elo->cmd_mutex);
- serio_pause_rx(elo->serio);
- elo->expected_packet = toupper(packet[0]);
- init_completion(&elo->cmd_done);
- serio_continue_rx(elo->serio);
+ scoped_guard(serio_pause_rx, elo->serio) {
+ elo->expected_packet = toupper(packet[0]);
+ init_completion(&elo->cmd_done);
+ }
if (serio_write(elo->serio, ELO10_LEAD_BYTE))
goto out;
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 260c83dc23a2..fa38d70aded7 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -898,7 +898,7 @@ static umode_t ili210x_attributes_visible(struct kobject *kobj,
if (attr == &dev_attr_calibrate.attr)
return priv->chip->has_calibrate_reg ? attr->mode : 0;
- /* Firmware/Kernel/Protocol/BootMode is implememted only for ILI251x */
+ /* Firmware/Kernel/Protocol/BootMode is implemented only for ILI251x */
if (!priv->chip->has_firmware_proto)
return 0;
diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c
index aeabf8d057de..abeae9102323 100644
--- a/drivers/input/touchscreen/imagis.c
+++ b/drivers/input/touchscreen/imagis.c
@@ -395,6 +395,7 @@ static int imagis_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(imagis_pm_ops, imagis_suspend, imagis_resume);
+#ifdef CONFIG_OF
static const struct imagis_properties imagis_3032c_data = {
.interrupt_msg_cmd = IST3038C_REG_INTR_MESSAGE,
.touch_coord_cmd = IST3038C_REG_TOUCH_COORD,
@@ -427,7 +428,6 @@ static const struct imagis_properties imagis_3038c_data = {
.protocol_b = true,
};
-#ifdef CONFIG_OF
static const struct of_device_id imagis_of_match[] = {
{ .compatible = "imagis,ist3032c", .data = &imagis_3032c_data },
{ .compatible = "imagis,ist3038", .data = &imagis_3038_data },
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
index bfbebe245040..5abf164ae14c 100644
--- a/drivers/input/touchscreen/mainstone-wm97xx.c
+++ b/drivers/input/touchscreen/mainstone-wm97xx.c
@@ -261,7 +261,7 @@ static void mainstone_wm97xx_remove(struct platform_device *pdev)
static struct platform_driver mainstone_wm97xx_driver = {
.probe = mainstone_wm97xx_probe,
- .remove_new = mainstone_wm97xx_remove,
+ .remove = mainstone_wm97xx_remove,
.driver = {
.name = "wm97xx-touch",
},
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index cbcd6e34efb7..33635da85079 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -226,7 +226,7 @@ static void mc13783_ts_remove(struct platform_device *pdev)
}
static struct platform_driver mc13783_ts_driver = {
- .remove_new = mc13783_ts_remove,
+ .remove = mc13783_ts_remove,
.driver = {
.name = MC13783_TS_NAME,
},
diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
index 0afee41ac9de..44b58e0dc1ad 100644
--- a/drivers/input/touchscreen/novatek-nvt-ts.c
+++ b/drivers/input/touchscreen/novatek-nvt-ts.c
@@ -31,9 +31,6 @@
#define NVT_TS_PARAMS_CHIP_ID 0x0e
#define NVT_TS_PARAMS_SIZE 0x0f
-#define NVT_TS_SUPPORTED_WAKE_TYPE 0x05
-#define NVT_TS_SUPPORTED_CHIP_ID 0x05
-
#define NVT_TS_MAX_TOUCHES 10
#define NVT_TS_MAX_SIZE 4096
@@ -51,10 +48,16 @@ static const int nvt_ts_irq_type[4] = {
IRQF_TRIGGER_HIGH
};
+struct nvt_ts_i2c_chip_data {
+ u8 wake_type;
+ u8 chip_id;
+};
+
struct nvt_ts_data {
struct i2c_client *client;
struct input_dev *input;
struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data regulators[2];
struct touchscreen_properties prop;
int max_touches;
u8 buf[NVT_TS_TOUCH_SIZE * NVT_TS_MAX_TOUCHES];
@@ -142,6 +145,13 @@ static irqreturn_t nvt_ts_irq(int irq, void *dev_id)
static int nvt_ts_start(struct input_dev *dev)
{
struct nvt_ts_data *data = input_get_drvdata(dev);
+ int error;
+
+ error = regulator_bulk_enable(ARRAY_SIZE(data->regulators), data->regulators);
+ if (error) {
+ dev_err(&data->client->dev, "failed to enable regulators\n");
+ return error;
+ }
enable_irq(data->client->irq);
gpiod_set_value_cansleep(data->reset_gpio, 0);
@@ -155,6 +165,7 @@ static void nvt_ts_stop(struct input_dev *dev)
disable_irq(data->client->irq);
gpiod_set_value_cansleep(data->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
}
static int nvt_ts_suspend(struct device *dev)
@@ -188,6 +199,7 @@ static int nvt_ts_probe(struct i2c_client *client)
struct device *dev = &client->dev;
int error, width, height, irq_type;
struct nvt_ts_data *data;
+ const struct nvt_ts_i2c_chip_data *chip;
struct input_dev *input;
if (!client->irq) {
@@ -199,12 +211,35 @@ static int nvt_ts_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
+ chip = device_get_match_data(&client->dev);
+ if (!chip)
+ return -EINVAL;
+
data->client = client;
i2c_set_clientdata(client, data);
+ /*
+ * VCC is the analog voltage supply
+ * IOVCC is the digital voltage supply
+ */
+ data->regulators[0].supply = "vcc";
+ data->regulators[1].supply = "iovcc";
+ error = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators), data->regulators);
+ if (error) {
+ dev_err(dev, "cannot get regulators: %d\n", error);
+ return error;
+ }
+
+ error = regulator_bulk_enable(ARRAY_SIZE(data->regulators), data->regulators);
+ if (error) {
+ dev_err(dev, "failed to enable regulators: %d\n", error);
+ return error;
+ }
+
data->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
error = PTR_ERR_OR_ZERO(data->reset_gpio);
if (error) {
+ regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
dev_err(dev, "failed to request reset GPIO: %d\n", error);
return error;
}
@@ -214,6 +249,7 @@ static int nvt_ts_probe(struct i2c_client *client)
error = nvt_ts_read_data(data->client, NVT_TS_PARAMETERS_START,
data->buf, NVT_TS_PARAMS_SIZE);
gpiod_set_value_cansleep(data->reset_gpio, 1); /* Put back in reset */
+ regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
if (error)
return error;
@@ -225,8 +261,8 @@ static int nvt_ts_probe(struct i2c_client *client)
if (width > NVT_TS_MAX_SIZE || height >= NVT_TS_MAX_SIZE ||
data->max_touches > NVT_TS_MAX_TOUCHES ||
irq_type >= ARRAY_SIZE(nvt_ts_irq_type) ||
- data->buf[NVT_TS_PARAMS_WAKE_TYPE] != NVT_TS_SUPPORTED_WAKE_TYPE ||
- data->buf[NVT_TS_PARAMS_CHIP_ID] != NVT_TS_SUPPORTED_CHIP_ID) {
+ data->buf[NVT_TS_PARAMS_WAKE_TYPE] != chip->wake_type ||
+ data->buf[NVT_TS_PARAMS_CHIP_ID] != chip->chip_id) {
dev_err(dev, "Unsupported touchscreen parameters: %*ph\n",
NVT_TS_PARAMS_SIZE, data->buf);
return -EIO;
@@ -277,8 +313,26 @@ static int nvt_ts_probe(struct i2c_client *client)
return 0;
}
+static const struct nvt_ts_i2c_chip_data nvt_nt11205_ts_data = {
+ .wake_type = 0x05,
+ .chip_id = 0x05,
+};
+
+static const struct nvt_ts_i2c_chip_data nvt_nt36672a_ts_data = {
+ .wake_type = 0x01,
+ .chip_id = 0x08,
+};
+
+static const struct of_device_id nvt_ts_of_match[] = {
+ { .compatible = "novatek,nt11205-ts", .data = &nvt_nt11205_ts_data },
+ { .compatible = "novatek,nt36672a-ts", .data = &nvt_nt36672a_ts_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, nvt_ts_of_match);
+
static const struct i2c_device_id nvt_ts_i2c_id[] = {
- { "NVT-ts" },
+ { "nt11205-ts", (unsigned long) &nvt_nt11205_ts_data },
+ { "nt36672a-ts", (unsigned long) &nvt_nt36672a_ts_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, nvt_ts_i2c_id);
@@ -287,6 +341,7 @@ static struct i2c_driver nvt_ts_driver = {
.driver = {
.name = "novatek-nvt-ts",
.pm = pm_sleep_ptr(&nvt_ts_pm_ops),
+ .of_match_table = nvt_ts_of_match,
},
.probe = nvt_ts_probe,
.id_table = nvt_ts_i2c_id,
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
index 821245019fea..083206a3457b 100644
--- a/drivers/input/touchscreen/pcap_ts.c
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -238,7 +238,7 @@ static const struct dev_pm_ops pcap_ts_pm_ops = {
static struct platform_driver pcap_ts_driver = {
.probe = pcap_ts_probe,
- .remove_new = pcap_ts_remove,
+ .remove = pcap_ts_remove,
.driver = {
.name = "pcap-ts",
.pm = PCAP_TS_PM_OPS,
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 83bf27085ebc..dad5786e82a4 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -44,7 +44,7 @@ enum pixcir_power_mode {
/*
* Interrupt modes:
- * periodical: interrupt is asserted periodicaly
+ * periodical: interrupt is asserted periodically
* diff coordinates: interrupt is asserted when coordinates change
* level on touch: interrupt level asserted during touch
* pulse on touch: interrupt pulse asserted during touch
diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c
index 45c575df994e..841d39a449b3 100644
--- a/drivers/input/touchscreen/raspberrypi-ts.c
+++ b/drivers/input/touchscreen/raspberrypi-ts.c
@@ -122,20 +122,18 @@ static int rpi_ts_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct input_dev *input;
- struct device_node *fw_node;
struct rpi_firmware *fw;
struct rpi_ts *ts;
u32 touchbuf;
int error;
- fw_node = of_get_parent(np);
+ struct device_node *fw_node __free(device_node) = of_get_parent(np);
if (!fw_node) {
dev_err(dev, "Missing firmware node\n");
return -ENOENT;
}
fw = devm_rpi_firmware_get(&pdev->dev, fw_node);
- of_node_put(fw_node);
if (!fw)
return -EPROBE_DEFER;
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index 0e5cc9fbad17..295d8d75ba32 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -388,13 +388,13 @@ static int rohm_ts_manual_calibration(struct rohm_ts_data *ts)
err_y = (int)READ_CALIB_BUF(PRM1_Y_H) << 2 |
READ_CALIB_BUF(PRM1_Y_L);
- /* X axis ajust */
+ /* X axis adjust */
if (err_x <= 4)
calib_x -= AXIS_ADJUST;
else if (err_x >= 60)
calib_x += AXIS_ADJUST;
- /* Y axis ajust */
+ /* Y axis adjust */
if (err_y <= 4)
calib_y -= AXIS_ADJUST;
else if (err_y >= 60)
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
index b204fdb2d22c..a94a1997f96b 100644
--- a/drivers/input/touchscreen/stmpe-ts.c
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -107,7 +107,7 @@ static void stmpe_work(struct work_struct *work)
/*
* touch_det sometimes get desasserted or just get stuck. This appears
- * to be a silicon bug, We still have to clearify this with the
+ * to be a silicon bug, We still have to clarify this with the
* manufacture. As a workaround We release the key anyway if the
* touch_det keeps coming in after 4ms, while the FIFO contains no value
* during the whole time.
@@ -140,7 +140,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
/*
* The FIFO sometimes just crashes and stops generating interrupts. This
- * appears to be a silicon bug. We still have to clearify this with
+ * appears to be a silicon bug. We still have to clarify this with
* the manufacture. As a workaround we disable the TSC while we are
* collecting data and flush the FIFO after reading
*/
@@ -362,7 +362,7 @@ static struct platform_driver stmpe_ts_driver = {
.name = STMPE_TS_NAME,
},
.probe = stmpe_input_probe,
- .remove_new = stmpe_ts_remove,
+ .remove = stmpe_ts_remove,
};
module_platform_driver(stmpe_ts_driver);
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
index 92b2b840b4b7..e8286060043a 100644
--- a/drivers/input/touchscreen/sun4i-ts.c
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -396,12 +396,12 @@ static const struct of_device_id sun4i_ts_of_match[] = {
MODULE_DEVICE_TABLE(of, sun4i_ts_of_match);
static struct platform_driver sun4i_ts_driver = {
- .driver = {
+ .driver = {
.name = "sun4i-ts",
.of_match_table = sun4i_ts_of_match,
},
.probe = sun4i_ts_probe,
- .remove_new = sun4i_ts_remove,
+ .remove = sun4i_ts_remove,
};
module_platform_driver(sun4i_ts_driver);
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 294b7ceded27..93d659ff90aa 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -550,9 +550,9 @@ MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
static struct platform_driver ti_tsc_driver = {
.probe = titsc_probe,
- .remove_new = titsc_remove,
+ .remove = titsc_remove,
.driver = {
- .name = "TI-am335x-tsc",
+ .name = "TI-am335x-tsc",
.pm = pm_sleep_ptr(&titsc_pm_ops),
.of_match_table = ti_tsc_dt_ids,
},
diff --git a/drivers/input/touchscreen/ts4800-ts.c b/drivers/input/touchscreen/ts4800-ts.c
index 6cf66aadc10e..98422d1e80d6 100644
--- a/drivers/input/touchscreen/ts4800-ts.c
+++ b/drivers/input/touchscreen/ts4800-ts.c
@@ -110,18 +110,17 @@ static int ts4800_parse_dt(struct platform_device *pdev,
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- struct device_node *syscon_np;
u32 reg, bit;
int error;
- syscon_np = of_parse_phandle(np, "syscon", 0);
+ struct device_node *syscon_np __free(device_node) =
+ of_parse_phandle(np, "syscon", 0);
if (!syscon_np) {
dev_err(dev, "no syscon property\n");
return -ENODEV;
}
ts->regmap = syscon_node_to_regmap(syscon_np);
- of_node_put(syscon_np);
if (IS_ERR(ts->regmap)) {
dev_err(dev, "cannot get parent's regmap\n");
return PTR_ERR(ts->regmap);
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
index 9cee26b63341..98f8ec408cad 100644
--- a/drivers/input/touchscreen/wm831x-ts.c
+++ b/drivers/input/touchscreen/wm831x-ts.c
@@ -387,7 +387,7 @@ static struct platform_driver wm831x_ts_driver = {
.name = "wm831x-touch",
},
.probe = wm831x_ts_probe,
- .remove_new = wm831x_ts_remove,
+ .remove = wm831x_ts_remove,
};
module_platform_driver(wm831x_ts_driver);
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index f01f6cc9b59f..b25771a8df2b 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -222,7 +222,7 @@ EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
/*
* Codec GPIO pin configuration, this sets pin direction, polarity,
- * stickyness and wake up.
+ * stickiness and wake up.
*/
void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
enum wm97xx_gpio_pol pol, enum wm97xx_gpio_sticky sticky,
@@ -403,7 +403,7 @@ static int wm97xx_read_samples(struct wm97xx *wm)
* is actively working with the touchscreen we
* don't want to lose the quick response. So we
* will slowly increase sleep time after the
- * pen is up and quicky restore it to ~one task
+ * pen is up and quickly restore it to ~one task
* switch when pen is down again.
*/
if (wm->ts_reader_interval < HZ / 10)
@@ -876,7 +876,7 @@ static struct platform_driver wm97xx_mfd_driver = {
.pm = pm_sleep_ptr(&wm97xx_pm_ops),
},
.probe = wm97xx_mfd_probe,
- .remove_new = wm97xx_mfd_remove,
+ .remove = wm97xx_mfd_remove,
};
static int __init wm97xx_init(void)
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 7e9b996b47c8..9d5404a07e8a 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -808,7 +808,7 @@ void icc_put(struct icc_path *path)
mutex_unlock(&icc_bw_lock);
mutex_unlock(&icc_lock);
- kfree_const(path->name);
+ kfree(path->name);
kfree(path);
}
EXPORT_SYMBOL_GPL(icc_put);
@@ -1081,7 +1081,7 @@ static int of_count_icc_providers(struct device_node *np)
int count = 0;
for_each_available_child_of_node(np, child) {
- if (of_property_read_bool(child, "#interconnect-cells") &&
+ if (of_property_present(child, "#interconnect-cells") &&
likely(!of_match_node(ignore_list, child)))
count++;
count += of_count_icc_providers(child);
diff --git a/drivers/interconnect/imx/imx8mm.c b/drivers/interconnect/imx/imx8mm.c
index a36aaaf106ae..efed12d635c1 100644
--- a/drivers/interconnect/imx/imx8mm.c
+++ b/drivers/interconnect/imx/imx8mm.c
@@ -88,7 +88,7 @@ static int imx8mm_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mm_icc_driver = {
.probe = imx8mm_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mm-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mn.c b/drivers/interconnect/imx/imx8mn.c
index 2a97c74e875b..535fae791f2e 100644
--- a/drivers/interconnect/imx/imx8mn.c
+++ b/drivers/interconnect/imx/imx8mn.c
@@ -77,7 +77,7 @@ static int imx8mn_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mn_icc_driver = {
.probe = imx8mn_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mn-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mp.c b/drivers/interconnect/imx/imx8mp.c
index 86d4c1517b26..c5751ed18d51 100644
--- a/drivers/interconnect/imx/imx8mp.c
+++ b/drivers/interconnect/imx/imx8mp.c
@@ -241,7 +241,7 @@ static int imx8mp_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mp_icc_driver = {
.probe = imx8mp_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mp-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c
index f817d24aeefb..6aa4f06b4676 100644
--- a/drivers/interconnect/imx/imx8mq.c
+++ b/drivers/interconnect/imx/imx8mq.c
@@ -87,7 +87,7 @@ static int imx8mq_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mq_icc_driver = {
.probe = imx8mq_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mq-interconnect",
.sync_state = icc_sync_state,
diff --git a/drivers/interconnect/mediatek/mt8183.c b/drivers/interconnect/mediatek/mt8183.c
index 24245085c7a9..c212e79334cf 100644
--- a/drivers/interconnect/mediatek/mt8183.c
+++ b/drivers/interconnect/mediatek/mt8183.c
@@ -133,7 +133,7 @@ static struct platform_driver mtk_emi_icc_mt8183_driver = {
.sync_state = icc_sync_state,
},
.probe = mtk_emi_icc_probe,
- .remove_new = mtk_emi_icc_remove,
+ .remove = mtk_emi_icc_remove,
};
module_platform_driver(mtk_emi_icc_mt8183_driver);
diff --git a/drivers/interconnect/mediatek/mt8195.c b/drivers/interconnect/mediatek/mt8195.c
index 710e14c5447c..3ca23469ab18 100644
--- a/drivers/interconnect/mediatek/mt8195.c
+++ b/drivers/interconnect/mediatek/mt8195.c
@@ -329,7 +329,7 @@ static struct platform_driver mtk_emi_icc_mt8195_driver = {
.sync_state = icc_sync_state,
},
.probe = mtk_emi_icc_probe,
- .remove_new = mtk_emi_icc_remove,
+ .remove = mtk_emi_icc_remove,
};
module_platform_driver(mtk_emi_icc_mt8195_driver);
diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
index de96d4661340..362fb9b0a198 100644
--- a/drivers/interconnect/qcom/Kconfig
+++ b/drivers/interconnect/qcom/Kconfig
@@ -105,6 +105,26 @@ config INTERCONNECT_QCOM_QCS404
This is a driver for the Qualcomm Network-on-Chip on qcs404-based
platforms.
+config INTERCONNECT_QCOM_QCS615
+ tristate "Qualcomm QCS615 interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on qcs615-based
+ platforms.
+
+config INTERCONNECT_QCOM_QCS8300
+ tristate "Qualcomm QCS8300 interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
+ on QCS8300-based platforms. The interconnect provider collects and
+ aggreagates the cosumer bandwidth requests to satisfy constraints
+ placed on Network-on-Chip performance states.
+
config INTERCONNECT_QCOM_QDU1000
tristate "Qualcomm QDU1000/QRU1000 interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
@@ -137,6 +157,15 @@ config INTERCONNECT_QCOM_SA8775P
This is a driver for the Qualcomm Network-on-Chip on sa8775p-based
platforms.
+config INTERCONNECT_QCOM_SAR2130P
+ tristate "Qualcomm SAR2130P interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on SAR2130P-based
+ platforms.
+
config INTERCONNECT_QCOM_SC7180
tristate "Qualcomm SC7180 interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index bfeea8416fcf..9997728c02bf 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -15,9 +15,12 @@ qnoc-msm8996-objs := msm8996.o
icc-osm-l3-objs := osm-l3.o
qnoc-qcm2290-objs := qcm2290.o
qnoc-qcs404-objs := qcs404.o
+qnoc-qcs615-objs := qcs615.o
+qnoc-qcs8300-objs := qcs8300.o
qnoc-qdu1000-objs := qdu1000.o
icc-rpmh-obj := icc-rpmh.o
qnoc-sa8775p-objs := sa8775p.o
+qnoc-sar2130p-objs := sar2130p.o
qnoc-sc7180-objs := sc7180.o
qnoc-sc7280-objs := sc7280.o
qnoc-sc8180x-objs := sc8180x.o
@@ -52,9 +55,12 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o
obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
+obj-$(CONFIG_INTERCONNECT_QCOM_QCS615) += qnoc-qcs615.o
+obj-$(CONFIG_INTERCONNECT_QCOM_QCS8300) += qnoc-qcs8300.o
obj-$(CONFIG_INTERCONNECT_QCOM_QDU1000) += qnoc-qdu1000.o
obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o
obj-$(CONFIG_INTERCONNECT_QCOM_SA8775P) += qnoc-sa8775p.o
+obj-$(CONFIG_INTERCONNECT_QCOM_SAR2130P) += qnoc-sar2130p.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7280) += qnoc-sc7280.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC8180X) += qnoc-sc8180x.o
diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c
index f49a8e0cb03c..f2d63745be54 100644
--- a/drivers/interconnect/qcom/icc-rpmh.c
+++ b/drivers/interconnect/qcom/icc-rpmh.c
@@ -311,7 +311,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
}
qp->num_clks = devm_clk_bulk_get_all(qp->dev, &qp->clks);
- if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_clks_required)) {
+ if (qp->num_clks == -EPROBE_DEFER)
+ return dev_err_probe(dev, qp->num_clks, "Failed to get QoS clocks\n");
+
+ if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_requires_clocks)) {
dev_info(dev, "Skipping QoS, failed to get clk: %d\n", qp->num_clks);
goto skip_qos_config;
}
diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h
index 14db89850fb3..82344c734091 100644
--- a/drivers/interconnect/qcom/icc-rpmh.h
+++ b/drivers/interconnect/qcom/icc-rpmh.h
@@ -153,7 +153,7 @@ struct qcom_icc_desc {
size_t num_nodes;
struct qcom_icc_bcm * const *bcms;
size_t num_bcms;
- bool qos_clks_required;
+ bool qos_requires_clocks;
};
int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
diff --git a/drivers/interconnect/qcom/msm8909.c b/drivers/interconnect/qcom/msm8909.c
index 0d0cd7282f5b..dd656ce7b64d 100644
--- a/drivers/interconnect/qcom/msm8909.c
+++ b/drivers/interconnect/qcom/msm8909.c
@@ -1316,7 +1316,7 @@ MODULE_DEVICE_TABLE(of, msm8909_noc_of_match);
static struct platform_driver msm8909_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8909",
.of_match_table = msm8909_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8916.c b/drivers/interconnect/qcom/msm8916.c
index 499b1a9ac413..35148880b3e8 100644
--- a/drivers/interconnect/qcom/msm8916.c
+++ b/drivers/interconnect/qcom/msm8916.c
@@ -1344,7 +1344,7 @@ MODULE_DEVICE_TABLE(of, msm8916_noc_of_match);
static struct platform_driver msm8916_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8916",
.of_match_table = msm8916_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8937.c b/drivers/interconnect/qcom/msm8937.c
index 052b14c28ef8..58533d00266b 100644
--- a/drivers/interconnect/qcom/msm8937.c
+++ b/drivers/interconnect/qcom/msm8937.c
@@ -1175,7 +1175,7 @@ static struct qcom_icc_node slv_lpass = {
.qos.qos_mode = NOC_QOS_MODE_INVALID,
};
-static struct qcom_icc_node *msm8937_bimc_nodes[] = {
+static struct qcom_icc_node * const msm8937_bimc_nodes[] = {
[MAS_APPS_PROC] = &mas_apps_proc,
[MAS_OXILI] = &mas_oxili,
[MAS_SNOC_BIMC_0] = &mas_snoc_bimc_0,
@@ -1204,7 +1204,7 @@ static const struct qcom_icc_desc msm8937_bimc = {
.ab_coeff = 154,
};
-static struct qcom_icc_node *msm8937_pcnoc_nodes[] = {
+static struct qcom_icc_node * const msm8937_pcnoc_nodes[] = {
[MAS_SPDM] = &mas_spdm,
[MAS_BLSP_1] = &mas_blsp_1,
[MAS_BLSP_2] = &mas_blsp_2,
@@ -1268,7 +1268,7 @@ static const struct qcom_icc_desc msm8937_pcnoc = {
.regmap_cfg = &msm8937_pcnoc_regmap_config,
};
-static struct qcom_icc_node *msm8937_snoc_nodes[] = {
+static struct qcom_icc_node * const msm8937_snoc_nodes[] = {
[MAS_QDSS_BAM] = &mas_qdss_bam,
[MAS_BIMC_SNOC] = &mas_bimc_snoc,
[MAS_PCNOC_SNOC] = &mas_pcnoc_snoc,
@@ -1304,7 +1304,7 @@ static const struct qcom_icc_desc msm8937_snoc = {
.qos_offset = 0x7000,
};
-static struct qcom_icc_node *msm8937_snoc_mm_nodes[] = {
+static struct qcom_icc_node * const msm8937_snoc_mm_nodes[] = {
[MAS_JPEG] = &mas_jpeg,
[MAS_MDP] = &mas_mdp,
[MAS_VENUS] = &mas_venus,
@@ -1337,7 +1337,7 @@ MODULE_DEVICE_TABLE(of, msm8937_noc_of_match);
static struct platform_driver msm8937_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8937",
.of_match_table = msm8937_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8939.c b/drivers/interconnect/qcom/msm8939.c
index 8ff2c23b1ca0..b52c5ac1175c 100644
--- a/drivers/interconnect/qcom/msm8939.c
+++ b/drivers/interconnect/qcom/msm8939.c
@@ -1421,7 +1421,7 @@ MODULE_DEVICE_TABLE(of, msm8939_noc_of_match);
static struct platform_driver msm8939_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8939",
.of_match_table = msm8939_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8953.c b/drivers/interconnect/qcom/msm8953.c
index 62f8c0774b3e..be2b1a606612 100644
--- a/drivers/interconnect/qcom/msm8953.c
+++ b/drivers/interconnect/qcom/msm8953.c
@@ -1310,7 +1310,7 @@ static const struct of_device_id msm8953_noc_of_match[] = {
static struct platform_driver msm8953_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8953",
.of_match_table = msm8953_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8974.c b/drivers/interconnect/qcom/msm8974.c
index 241076b5f36b..469fc48ebfe9 100644
--- a/drivers/interconnect/qcom/msm8974.c
+++ b/drivers/interconnect/qcom/msm8974.c
@@ -762,7 +762,7 @@ MODULE_DEVICE_TABLE(of, msm8974_noc_of_match);
static struct platform_driver msm8974_noc_driver = {
.probe = msm8974_icc_probe,
- .remove_new = msm8974_icc_remove,
+ .remove = msm8974_icc_remove,
.driver = {
.name = "qnoc-msm8974",
.of_match_table = msm8974_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8976.c b/drivers/interconnect/qcom/msm8976.c
index ab963def77c3..4e2ac7ebe742 100644
--- a/drivers/interconnect/qcom/msm8976.c
+++ b/drivers/interconnect/qcom/msm8976.c
@@ -1427,7 +1427,7 @@ MODULE_DEVICE_TABLE(of, msm8976_noc_of_match);
static struct platform_driver msm8976_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8976",
.of_match_table = msm8976_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 788131400cd1..b73566c9b21f 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -2108,7 +2108,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8996",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c
index 61a8695a9adc..6a656ed44d49 100644
--- a/drivers/interconnect/qcom/osm-l3.c
+++ b/drivers/interconnect/qcom/osm-l3.c
@@ -290,7 +290,7 @@ MODULE_DEVICE_TABLE(of, osm_l3_of_match);
static struct platform_driver osm_l3_driver = {
.probe = qcom_osm_l3_probe,
- .remove_new = qcom_osm_l3_remove,
+ .remove = qcom_osm_l3_remove,
.driver = {
.name = "osm-l3",
.of_match_table = osm_l3_of_match,
diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c
index ccbdc6202c07..e120bc1395f3 100644
--- a/drivers/interconnect/qcom/qcm2290.c
+++ b/drivers/interconnect/qcom/qcm2290.c
@@ -1367,7 +1367,7 @@ MODULE_DEVICE_TABLE(of, qcm2290_noc_of_match);
static struct platform_driver qcm2290_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-qcm2290",
.of_match_table = qcm2290_noc_of_match,
diff --git a/drivers/interconnect/qcom/qcs404.c b/drivers/interconnect/qcom/qcs404.c
index 63e9ff223ac4..ceac7a698769 100644
--- a/drivers/interconnect/qcom/qcs404.c
+++ b/drivers/interconnect/qcom/qcs404.c
@@ -1204,7 +1204,7 @@ MODULE_DEVICE_TABLE(of, qcs404_noc_of_match);
static struct platform_driver qcs404_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-qcs404",
.of_match_table = qcs404_noc_of_match,
diff --git a/drivers/interconnect/qcom/qcs615.c b/drivers/interconnect/qcom/qcs615.c
new file mode 100644
index 000000000000..7e59e91ce886
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs615.c
@@ -0,0 +1,1563 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <dt-bindings/interconnect/qcom,qcs615-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+#include "qcs615.h"
+
+static struct qcom_icc_node qhm_a1noc_cfg = {
+ .name = "qhm_a1noc_cfg",
+ .id = QCS615_MASTER_A1NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_A2NOC },
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = QCS615_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qspi = {
+ .name = "qhm_qspi",
+ .id = QCS615_MASTER_QSPI,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = QCS615_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = QCS615_MASTER_BLSP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_cnoc = {
+ .name = "qnm_cnoc",
+ .id = QCS615_MASTER_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto = {
+ .name = "qxm_crypto",
+ .id = QCS615_MASTER_CRYPTO,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .id = QCS615_MASTER_IPA,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LPASS_SNOC },
+};
+
+static struct qcom_icc_node xm_emac_avb = {
+ .name = "xm_emac_avb",
+ .id = QCS615_MASTER_EMAC_EVB,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_pcie = {
+ .name = "xm_pcie",
+ .id = QCS615_MASTER_PCIE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_ANOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr = {
+ .name = "xm_qdss_etr",
+ .id = QCS615_MASTER_QDSS_ETR,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = QCS615_MASTER_SDCC_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc2 = {
+ .name = "xm_sdc2",
+ .id = QCS615_MASTER_SDCC_2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_ufs_mem = {
+ .name = "xm_ufs_mem",
+ .id = QCS615_MASTER_UFS_MEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb2 = {
+ .name = "xm_usb2",
+ .id = QCS615_MASTER_USB2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = QCS615_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf0_uncomp = {
+ .name = "qxm_camnoc_hf0_uncomp",
+ .id = QCS615_MASTER_CAMNOC_HF0_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf1_uncomp = {
+ .name = "qxm_camnoc_hf1_uncomp",
+ .id = QCS615_MASTER_CAMNOC_HF1_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qxm_camnoc_sf_uncomp = {
+ .name = "qxm_camnoc_sf_uncomp",
+ .id = QCS615_MASTER_CAMNOC_SF_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qhm_spdm = {
+ .name = "qhm_spdm",
+ .id = QCS615_MASTER_SPDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CNOC_A2NOC },
+};
+
+static struct qcom_icc_node qnm_snoc = {
+ .name = "qnm_snoc",
+ .id = QCS615_MASTER_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 39,
+ .links = { QCS615_SLAVE_A1NOC_CFG, QCS615_SLAVE_AHB2PHY_EAST,
+ QCS615_SLAVE_AHB2PHY_WEST, QCS615_SLAVE_AOP,
+ QCS615_SLAVE_AOSS, QCS615_SLAVE_CAMERA_CFG,
+ QCS615_SLAVE_CLK_CTL, QCS615_SLAVE_RBCPR_CX_CFG,
+ QCS615_SLAVE_RBCPR_MX_CFG, QCS615_SLAVE_CRYPTO_0_CFG,
+ QCS615_SLAVE_CNOC_DDRSS, QCS615_SLAVE_DISPLAY_CFG,
+ QCS615_SLAVE_EMAC_AVB_CFG, QCS615_SLAVE_GLM,
+ QCS615_SLAVE_GFX3D_CFG, QCS615_SLAVE_IMEM_CFG,
+ QCS615_SLAVE_IPA_CFG, QCS615_SLAVE_CNOC_MNOC_CFG,
+ QCS615_SLAVE_PCIE_CFG, QCS615_SLAVE_PIMEM_CFG,
+ QCS615_SLAVE_PRNG, QCS615_SLAVE_QDSS_CFG,
+ QCS615_SLAVE_QSPI, QCS615_SLAVE_QUP_0,
+ QCS615_SLAVE_QUP_1, QCS615_SLAVE_SDCC_1,
+ QCS615_SLAVE_SDCC_2, QCS615_SLAVE_SNOC_CFG,
+ QCS615_SLAVE_SPDM_WRAPPER, QCS615_SLAVE_TCSR,
+ QCS615_SLAVE_TLMM_EAST, QCS615_SLAVE_TLMM_SOUTH,
+ QCS615_SLAVE_TLMM_WEST, QCS615_SLAVE_UFS_MEM_CFG,
+ QCS615_SLAVE_USB2, QCS615_SLAVE_USB3,
+ QCS615_SLAVE_VENUS_CFG, QCS615_SLAVE_VSENSE_CTRL_CFG,
+ QCS615_SLAVE_SERVICE_CNOC },
+};
+
+static struct qcom_icc_node xm_qdss_dap = {
+ .name = "xm_qdss_dap",
+ .id = QCS615_MASTER_QDSS_DAP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 40,
+ .links = { QCS615_SLAVE_A1NOC_CFG, QCS615_SLAVE_AHB2PHY_EAST,
+ QCS615_SLAVE_AHB2PHY_WEST, QCS615_SLAVE_AOP,
+ QCS615_SLAVE_AOSS, QCS615_SLAVE_CAMERA_CFG,
+ QCS615_SLAVE_CLK_CTL, QCS615_SLAVE_RBCPR_CX_CFG,
+ QCS615_SLAVE_RBCPR_MX_CFG, QCS615_SLAVE_CRYPTO_0_CFG,
+ QCS615_SLAVE_CNOC_DDRSS, QCS615_SLAVE_DISPLAY_CFG,
+ QCS615_SLAVE_EMAC_AVB_CFG, QCS615_SLAVE_GLM,
+ QCS615_SLAVE_GFX3D_CFG, QCS615_SLAVE_IMEM_CFG,
+ QCS615_SLAVE_IPA_CFG, QCS615_SLAVE_CNOC_MNOC_CFG,
+ QCS615_SLAVE_PCIE_CFG, QCS615_SLAVE_PIMEM_CFG,
+ QCS615_SLAVE_PRNG, QCS615_SLAVE_QDSS_CFG,
+ QCS615_SLAVE_QSPI, QCS615_SLAVE_QUP_0,
+ QCS615_SLAVE_QUP_1, QCS615_SLAVE_SDCC_1,
+ QCS615_SLAVE_SDCC_2, QCS615_SLAVE_SNOC_CFG,
+ QCS615_SLAVE_SPDM_WRAPPER, QCS615_SLAVE_TCSR,
+ QCS615_SLAVE_TLMM_EAST, QCS615_SLAVE_TLMM_SOUTH,
+ QCS615_SLAVE_TLMM_WEST, QCS615_SLAVE_UFS_MEM_CFG,
+ QCS615_SLAVE_USB2, QCS615_SLAVE_USB3,
+ QCS615_SLAVE_VENUS_CFG, QCS615_SLAVE_VSENSE_CTRL_CFG,
+ QCS615_SLAVE_CNOC_A2NOC, QCS615_SLAVE_SERVICE_CNOC },
+};
+
+static struct qcom_icc_node qhm_cnoc = {
+ .name = "qhm_cnoc",
+ .id = QCS615_MASTER_CNOC_DC_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_DC_NOC_GEMNOC, QCS615_SLAVE_LLCC_CFG },
+};
+
+static struct qcom_icc_node acm_apps = {
+ .name = "acm_apps",
+ .id = QCS615_MASTER_APPSS_PROC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 3,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC,
+ QCS615_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node acm_gpu_tcu = {
+ .name = "acm_gpu_tcu",
+ .id = QCS615_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node acm_sys_tcu = {
+ .name = "acm_sys_tcu",
+ .id = QCS615_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qhm_gemnoc_cfg = {
+ .name = "qhm_gemnoc_cfg",
+ .id = QCS615_MASTER_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_MSS_PROC_MS_MPU_CFG, QCS615_SLAVE_SERVICE_GEM_NOC },
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = QCS615_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = QCS615_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = QCS615_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = QCS615_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = QCS615_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node ipa_core_master = {
+ .name = "ipa_core_master",
+ .id = QCS615_MASTER_IPA_CORE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_IPA_CORE },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = QCS615_MASTER_LLCC,
+ .channels = 2,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_EBI1 },
+};
+
+static struct qcom_icc_node qhm_mnoc_cfg = {
+ .name = "qhm_mnoc_cfg",
+ .id = QCS615_MASTER_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_MNOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf0 = {
+ .name = "qxm_camnoc_hf0",
+ .id = QCS615_MASTER_CAMNOC_HF0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf1 = {
+ .name = "qxm_camnoc_hf1",
+ .id = QCS615_MASTER_CAMNOC_HF1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_sf = {
+ .name = "qxm_camnoc_sf",
+ .id = QCS615_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_mdp0 = {
+ .name = "qxm_mdp0",
+ .id = QCS615_MASTER_MDP0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_rot = {
+ .name = "qxm_rot",
+ .id = QCS615_MASTER_ROTATOR,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_venus0 = {
+ .name = "qxm_venus0",
+ .id = QCS615_MASTER_VIDEO_P0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_venus_arm9 = {
+ .name = "qxm_venus_arm9",
+ .id = QCS615_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_snoc_cfg = {
+ .name = "qhm_snoc_cfg",
+ .id = QCS615_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_SNOC },
+};
+
+static struct qcom_icc_node qnm_aggre1_noc = {
+ .name = "qnm_aggre1_noc",
+ .id = QCS615_MASTER_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 8,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_PIMEM, QCS615_SLAVE_PCIE_0,
+ QCS615_SLAVE_QDSS_STM, QCS615_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc = {
+ .name = "qnm_gemnoc",
+ .id = QCS615_MASTER_GEM_NOC_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 6,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_IMEM, QCS615_SLAVE_PIMEM,
+ QCS615_SLAVE_QDSS_STM, QCS615_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = QCS615_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_PCIE_0 },
+};
+
+static struct qcom_icc_node qnm_lpass_anoc = {
+ .name = "qnm_lpass_anoc",
+ .id = QCS615_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 7,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_PIMEM, QCS615_SLAVE_PCIE_0,
+ QCS615_SLAVE_QDSS_STM },
+};
+
+static struct qcom_icc_node qnm_pcie_anoc = {
+ .name = "qnm_pcie_anoc",
+ .id = QCS615_MASTER_ANOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 5,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_QDSS_STM },
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = QCS615_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_SNOC_MEM_NOC_GC, QCS615_SLAVE_IMEM },
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = QCS615_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_SNOC_MEM_NOC_GC, QCS615_SLAVE_IMEM },
+};
+
+static struct qcom_icc_node qns_a1noc_snoc = {
+ .name = "qns_a1noc_snoc",
+ .id = QCS615_SLAVE_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_lpass_snoc = {
+ .name = "qns_lpass_snoc",
+ .id = QCS615_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node qns_pcie_snoc = {
+ .name = "qns_pcie_snoc",
+ .id = QCS615_SLAVE_ANOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_ANOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_aggre2_noc = {
+ .name = "srvc_aggre2_noc",
+ .id = QCS615_SLAVE_SERVICE_A2NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_camnoc_uncomp = {
+ .name = "qns_camnoc_uncomp",
+ .id = QCS615_SLAVE_CAMNOC_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_a1_noc_cfg = {
+ .name = "qhs_a1_noc_cfg",
+ .id = QCS615_SLAVE_A1NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_A1NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_ahb2phy_east = {
+ .name = "qhs_ahb2phy_east",
+ .id = QCS615_SLAVE_AHB2PHY_EAST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy_west = {
+ .name = "qhs_ahb2phy_west",
+ .id = QCS615_SLAVE_AHB2PHY_WEST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aop = {
+ .name = "qhs_aop",
+ .id = QCS615_SLAVE_AOP,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = QCS615_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = QCS615_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = QCS615_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = QCS615_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mx = {
+ .name = "qhs_cpr_mx",
+ .id = QCS615_SLAVE_RBCPR_MX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = QCS615_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ddrss_cfg = {
+ .name = "qhs_ddrss_cfg",
+ .id = QCS615_SLAVE_CNOC_DDRSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_DC_NOC },
+};
+
+static struct qcom_icc_node qhs_display_cfg = {
+ .name = "qhs_display_cfg",
+ .id = QCS615_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_emac_avb_cfg = {
+ .name = "qhs_emac_avb_cfg",
+ .id = QCS615_SLAVE_EMAC_AVB_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_glm = {
+ .name = "qhs_glm",
+ .id = QCS615_SLAVE_GLM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = QCS615_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = QCS615_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipa = {
+ .name = "qhs_ipa",
+ .id = QCS615_SLAVE_IPA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mnoc_cfg = {
+ .name = "qhs_mnoc_cfg",
+ .id = QCS615_SLAVE_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_MNOC_CFG },
+};
+
+static struct qcom_icc_node qhs_pcie_config = {
+ .name = "qhs_pcie_config",
+ .id = QCS615_SLAVE_PCIE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = QCS615_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_prng = {
+ .name = "qhs_prng",
+ .id = QCS615_SLAVE_PRNG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = QCS615_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qspi = {
+ .name = "qhs_qspi",
+ .id = QCS615_SLAVE_QSPI,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = QCS615_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = QCS615_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = QCS615_SLAVE_SDCC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc2 = {
+ .name = "qhs_sdc2",
+ .id = QCS615_SLAVE_SDCC_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_snoc_cfg = {
+ .name = "qhs_snoc_cfg",
+ .id = QCS615_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qhs_spdm = {
+ .name = "qhs_spdm",
+ .id = QCS615_SLAVE_SPDM_WRAPPER,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = QCS615_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_east = {
+ .name = "qhs_tlmm_east",
+ .id = QCS615_SLAVE_TLMM_EAST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_south = {
+ .name = "qhs_tlmm_south",
+ .id = QCS615_SLAVE_TLMM_SOUTH,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_west = {
+ .name = "qhs_tlmm_west",
+ .id = QCS615_SLAVE_TLMM_WEST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ufs_mem_cfg = {
+ .name = "qhs_ufs_mem_cfg",
+ .id = QCS615_SLAVE_UFS_MEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb2 = {
+ .name = "qhs_usb2",
+ .id = QCS615_SLAVE_USB2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3 = {
+ .name = "qhs_usb3",
+ .id = QCS615_SLAVE_USB3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = QCS615_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .id = QCS615_SLAVE_VSENSE_CTRL_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_cnoc_a2noc = {
+ .name = "qns_cnoc_a2noc",
+ .id = QCS615_SLAVE_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_A2NOC },
+};
+
+static struct qcom_icc_node srvc_cnoc = {
+ .name = "srvc_cnoc",
+ .id = QCS615_SLAVE_SERVICE_CNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_dc_noc_gemnoc = {
+ .name = "qhs_dc_noc_gemnoc",
+ .id = QCS615_SLAVE_DC_NOC_GEMNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_llcc = {
+ .name = "qhs_llcc",
+ .id = QCS615_SLAVE_LLCC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mdsp_ms_mpu_cfg = {
+ .name = "qhs_mdsp_ms_mpu_cfg",
+ .id = QCS615_SLAVE_MSS_PROC_MS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gem_noc_snoc = {
+ .name = "qns_gem_noc_snoc",
+ .id = QCS615_SLAVE_GEM_NOC_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = QCS615_SLAVE_LLCC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_sys_pcie = {
+ .name = "qns_sys_pcie",
+ .id = QCS615_SLAVE_MEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_gemnoc = {
+ .name = "srvc_gemnoc",
+ .id = QCS615_SLAVE_SERVICE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ipa_core_slave = {
+ .name = "ipa_core_slave",
+ .id = QCS615_SLAVE_IPA_CORE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = QCS615_SLAVE_EBI1,
+ .channels = 2,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns2_mem_noc = {
+ .name = "qns2_mem_noc",
+ .id = QCS615_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = QCS615_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc = {
+ .name = "srvc_mnoc",
+ .id = QCS615_SLAVE_SERVICE_MNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_apss = {
+ .name = "qhs_apss",
+ .id = QCS615_SLAVE_APPSS,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_cnoc = {
+ .name = "qns_cnoc",
+ .id = QCS615_SLAVE_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_CNOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = QCS615_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_memnoc_gc = {
+ .name = "qns_memnoc_gc",
+ .id = QCS615_SLAVE_SNOC_MEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = QCS615_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = QCS615_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = QCS615_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie = {
+ .name = "xs_pcie",
+ .id = QCS615_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = QCS615_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = QCS615_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+ .nodes = { &qxm_crypto },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .keepalive = true,
+ .num_nodes = 37,
+ .nodes = { &qhm_spdm, &qnm_snoc,
+ &qhs_a1_noc_cfg, &qhs_aop,
+ &qhs_aoss, &qhs_camera_cfg,
+ &qhs_clk_ctl, &qhs_cpr_cx,
+ &qhs_cpr_mx, &qhs_crypto0_cfg,
+ &qhs_ddrss_cfg, &qhs_display_cfg,
+ &qhs_emac_avb_cfg, &qhs_glm,
+ &qhs_gpuss_cfg, &qhs_imem_cfg,
+ &qhs_ipa, &qhs_mnoc_cfg,
+ &qhs_pcie_config, &qhs_pimem_cfg,
+ &qhs_prng, &qhs_qdss_cfg,
+ &qhs_qup0, &qhs_qup1,
+ &qhs_snoc_cfg, &qhs_spdm,
+ &qhs_tcsr, &qhs_tlmm_east,
+ &qhs_tlmm_south, &qhs_tlmm_west,
+ &qhs_ufs_mem_cfg, &qhs_usb2,
+ &qhs_usb3, &qhs_venus_cfg,
+ &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc,
+ &srvc_cnoc },
+};
+
+static struct qcom_icc_bcm bcm_cn1 = {
+ .name = "CN1",
+ .num_nodes = 8,
+ .nodes = { &qhm_qspi, &xm_sdc1,
+ &xm_sdc2, &qhs_ahb2phy_east,
+ &qhs_ahb2phy_west, &qhs_qspi,
+ &qhs_sdc1, &qhs_sdc2 },
+};
+
+static struct qcom_icc_bcm bcm_ip0 = {
+ .name = "IP0",
+ .num_nodes = 1,
+ .nodes = { &ipa_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .num_nodes = 7,
+ .nodes = { &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp,
+ &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0,
+ &qxm_camnoc_hf1, &qxm_mdp0,
+ &qxm_rot },
+};
+
+static struct qcom_icc_bcm bcm_mm2 = {
+ .name = "MM2",
+ .num_nodes = 2,
+ .nodes = { &qxm_camnoc_sf, &qns2_mem_noc },
+};
+
+static struct qcom_icc_bcm bcm_mm3 = {
+ .name = "MM3",
+ .num_nodes = 2,
+ .nodes = { &qxm_venus0, &qxm_venus_arm9 },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 2,
+ .nodes = { &qhm_qup0, &qhm_qup1 },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh2 = {
+ .name = "SH2",
+ .num_nodes = 1,
+ .nodes = { &acm_apps },
+};
+
+static struct qcom_icc_bcm bcm_sh3 = {
+ .name = "SH3",
+ .num_nodes = 1,
+ .nodes = { &qns_gem_noc_snoc },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .num_nodes = 1,
+ .nodes = { &qxs_imem },
+};
+
+static struct qcom_icc_bcm bcm_sn2 = {
+ .name = "SN2",
+ .num_nodes = 1,
+ .nodes = { &qns_memnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 2,
+ .nodes = { &srvc_aggre2_noc, &qns_cnoc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 1,
+ .nodes = { &qxs_pimem },
+};
+
+static struct qcom_icc_bcm bcm_sn5 = {
+ .name = "SN5",
+ .num_nodes = 1,
+ .nodes = { &xs_qdss_stm },
+};
+
+static struct qcom_icc_bcm bcm_sn8 = {
+ .name = "SN8",
+ .num_nodes = 2,
+ .nodes = { &qnm_gemnoc_pcie, &xs_pcie },
+};
+
+static struct qcom_icc_bcm bcm_sn9 = {
+ .name = "SN9",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn12 = {
+ .name = "SN12",
+ .num_nodes = 2,
+ .nodes = { &qxm_pimem, &xm_gic },
+};
+
+static struct qcom_icc_bcm bcm_sn13 = {
+ .name = "SN13",
+ .num_nodes = 1,
+ .nodes = { &qnm_lpass_anoc },
+};
+
+static struct qcom_icc_bcm bcm_sn14 = {
+ .name = "SN14",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_snoc },
+};
+
+static struct qcom_icc_bcm bcm_sn15 = {
+ .name = "SN15",
+ .num_nodes = 1,
+ .nodes = { &qnm_gemnoc },
+};
+
+static struct qcom_icc_bcm * const aggre1_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_cn1,
+ &bcm_qup0,
+ &bcm_sn3,
+ &bcm_sn14,
+ &bcm_ip0,
+};
+
+static struct qcom_icc_node * const aggre1_noc_nodes[] = {
+ [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QSPI] = &qhm_qspi,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_BLSP_1] = &qhm_qup1,
+ [MASTER_CNOC_A2NOC] = &qnm_cnoc,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_EMAC_EVB] = &xm_emac_avb,
+ [MASTER_PCIE] = &xm_pcie,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_SDCC_2] = &xm_sdc2,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB2] = &xm_usb2,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+ [SLAVE_LPASS_SNOC] = &qns_lpass_snoc,
+ [SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc,
+ [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc,
+};
+
+static const struct qcom_icc_desc qcs615_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .bcms = aggre1_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const camnoc_virt_bcms[] = {
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const camnoc_virt_nodes[] = {
+ [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp,
+ [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp,
+ [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp,
+ [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp,
+};
+
+static const struct qcom_icc_desc qcs615_camnoc_virt = {
+ .nodes = camnoc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(camnoc_virt_nodes),
+ .bcms = camnoc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(camnoc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+ &bcm_cn1,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_SPDM] = &qhm_spdm,
+ [MASTER_SNOC_CNOC] = &qnm_snoc,
+ [MASTER_QDSS_DAP] = &xm_qdss_dap,
+ [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg,
+ [SLAVE_AHB2PHY_EAST] = &qhs_ahb2phy_east,
+ [SLAVE_AHB2PHY_WEST] = &qhs_ahb2phy_west,
+ [SLAVE_AOP] = &qhs_aop,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_EMAC_AVB_CFG] = &qhs_emac_avb_cfg,
+ [SLAVE_GLM] = &qhs_glm,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg,
+ [SLAVE_PCIE_CFG] = &qhs_pcie_config,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QSPI] = &qhs_qspi,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_SDCC_1] = &qhs_sdc1,
+ [SLAVE_SDCC_2] = &qhs_sdc2,
+ [SLAVE_SNOC_CFG] = &qhs_snoc_cfg,
+ [SLAVE_SPDM_WRAPPER] = &qhs_spdm,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM_EAST] = &qhs_tlmm_east,
+ [SLAVE_TLMM_SOUTH] = &qhs_tlmm_south,
+ [SLAVE_TLMM_WEST] = &qhs_tlmm_west,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB2] = &qhs_usb2,
+ [SLAVE_USB3] = &qhs_usb3,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+};
+
+static const struct qcom_icc_desc qcs615_config_noc = {
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_node * const dc_noc_nodes[] = {
+ [MASTER_CNOC_DC_NOC] = &qhm_cnoc,
+ [SLAVE_DC_NOC_GEMNOC] = &qhs_dc_noc_gemnoc,
+ [SLAVE_LLCC_CFG] = &qhs_llcc,
+};
+
+static const struct qcom_icc_desc qcs615_dc_noc = {
+ .nodes = dc_noc_nodes,
+ .num_nodes = ARRAY_SIZE(dc_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh2,
+ &bcm_sh3,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_APPSS_PROC] = &acm_apps,
+ [MASTER_GPU_TCU] = &acm_gpu_tcu,
+ [MASTER_SYS_TCU] = &acm_sys_tcu,
+ [MASTER_GEM_NOC_CFG] = &qhm_gemnoc_cfg,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg,
+ [SLAVE_GEM_NOC_SNOC] = &qns_gem_noc_snoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_sys_pcie,
+ [SLAVE_SERVICE_GEM_NOC] = &srvc_gemnoc,
+};
+
+static const struct qcom_icc_desc qcs615_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const ipa_virt_bcms[] = {
+ &bcm_ip0,
+};
+
+static struct qcom_icc_node * const ipa_virt_nodes[] = {
+ [MASTER_IPA_CORE] = &ipa_core_master,
+ [SLAVE_IPA_CORE] = &ipa_core_slave,
+};
+
+static const struct qcom_icc_desc qcs615_ipa_virt = {
+ .nodes = ipa_virt_nodes,
+ .num_nodes = ARRAY_SIZE(ipa_virt_nodes),
+ .bcms = ipa_virt_bcms,
+ .num_bcms = ARRAY_SIZE(ipa_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc qcs615_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+ &bcm_mm2,
+ &bcm_mm3,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg,
+ [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0,
+ [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1,
+ [MASTER_CAMNOC_SF] = &qxm_camnoc_sf,
+ [MASTER_MDP0] = &qxm_mdp0,
+ [MASTER_ROTATOR] = &qxm_rot,
+ [MASTER_VIDEO_P0] = &qxm_venus0,
+ [MASTER_VIDEO_PROC] = &qxm_venus_arm9,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_SERVICE_MNOC] = &srvc_mnoc,
+};
+
+static const struct qcom_icc_desc qcs615_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn2,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn5,
+ &bcm_sn8,
+ &bcm_sn9,
+ &bcm_sn12,
+ &bcm_sn13,
+ &bcm_sn15,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_SNOC_CFG] = &qhm_snoc_cfg,
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_GEM_NOC_SNOC] = &qnm_gemnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_anoc,
+ [MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SLAVE_SNOC_CNOC] = &qns_cnoc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+ [SLAVE_PCIE_0] = &xs_pcie,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc qcs615_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,qcs615-aggre1-noc",
+ .data = &qcs615_aggre1_noc},
+ { .compatible = "qcom,qcs615-camnoc-virt",
+ .data = &qcs615_camnoc_virt},
+ { .compatible = "qcom,qcs615-config-noc",
+ .data = &qcs615_config_noc},
+ { .compatible = "qcom,qcs615-dc-noc",
+ .data = &qcs615_dc_noc},
+ { .compatible = "qcom,qcs615-gem-noc",
+ .data = &qcs615_gem_noc},
+ { .compatible = "qcom,qcs615-ipa-virt",
+ .data = &qcs615_ipa_virt},
+ { .compatible = "qcom,qcs615-mc-virt",
+ .data = &qcs615_mc_virt},
+ { .compatible = "qcom,qcs615-mmss-noc",
+ .data = &qcs615_mmss_noc},
+ { .compatible = "qcom,qcs615-system-noc",
+ .data = &qcs615_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-qcs615",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION("qcs615 NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/qcs615.h b/drivers/interconnect/qcom/qcs615.h
new file mode 100644
index 000000000000..66e66c7e23d4
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs615.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_QCOM_QCS615_H
+#define __DRIVERS_INTERCONNECT_QCOM_QCS615_H
+
+#define QCS615_MASTER_A1NOC_CFG 1
+#define QCS615_MASTER_A1NOC_SNOC 2
+#define QCS615_MASTER_ANOC_PCIE_SNOC 3
+#define QCS615_MASTER_APPSS_PROC 4
+#define QCS615_MASTER_BLSP_1 5
+#define QCS615_MASTER_CAMNOC_HF0 6
+#define QCS615_MASTER_CAMNOC_HF0_UNCOMP 7
+#define QCS615_MASTER_CAMNOC_HF1 8
+#define QCS615_MASTER_CAMNOC_HF1_UNCOMP 9
+#define QCS615_MASTER_CAMNOC_SF 10
+#define QCS615_MASTER_CAMNOC_SF_UNCOMP 11
+#define QCS615_MASTER_CNOC_A2NOC 12
+#define QCS615_MASTER_CNOC_DC_NOC 13
+#define QCS615_MASTER_CNOC_MNOC_CFG 14
+#define QCS615_MASTER_CRYPTO 15
+#define QCS615_MASTER_EMAC_EVB 16
+#define QCS615_MASTER_GEM_NOC_CFG 17
+#define QCS615_MASTER_GEM_NOC_PCIE_SNOC 18
+#define QCS615_MASTER_GEM_NOC_SNOC 19
+#define QCS615_MASTER_GFX3D 20
+#define QCS615_MASTER_GIC 21
+#define QCS615_MASTER_GPU_TCU 22
+#define QCS615_MASTER_IPA 23
+#define QCS615_MASTER_IPA_CORE 24
+#define QCS615_MASTER_LLCC 25
+#define QCS615_MASTER_LPASS_ANOC 26
+#define QCS615_MASTER_MDP0 27
+#define QCS615_MASTER_MNOC_HF_MEM_NOC 28
+#define QCS615_MASTER_MNOC_SF_MEM_NOC 29
+#define QCS615_MASTER_PCIE 30
+#define QCS615_MASTER_PIMEM 31
+#define QCS615_MASTER_QDSS_BAM 32
+#define QCS615_MASTER_QDSS_DAP 33
+#define QCS615_MASTER_QDSS_ETR 34
+#define QCS615_MASTER_QSPI 35
+#define QCS615_MASTER_QUP_0 36
+#define QCS615_MASTER_ROTATOR 37
+#define QCS615_MASTER_SDCC_1 38
+#define QCS615_MASTER_SDCC_2 39
+#define QCS615_MASTER_SNOC_CFG 40
+#define QCS615_MASTER_SNOC_CNOC 41
+#define QCS615_MASTER_SNOC_GC_MEM_NOC 42
+#define QCS615_MASTER_SNOC_SF_MEM_NOC 43
+#define QCS615_MASTER_SPDM 44
+#define QCS615_MASTER_SYS_TCU 45
+#define QCS615_MASTER_UFS_MEM 46
+#define QCS615_MASTER_USB2 47
+#define QCS615_MASTER_USB3_0 48
+#define QCS615_MASTER_VIDEO_P0 49
+#define QCS615_MASTER_VIDEO_PROC 50
+#define QCS615_SLAVE_A1NOC_CFG 51
+#define QCS615_SLAVE_A1NOC_SNOC 52
+#define QCS615_SLAVE_AHB2PHY_EAST 53
+#define QCS615_SLAVE_AHB2PHY_WEST 54
+#define QCS615_SLAVE_ANOC_PCIE_SNOC 55
+#define QCS615_SLAVE_AOP 56
+#define QCS615_SLAVE_AOSS 57
+#define QCS615_SLAVE_APPSS 58
+#define QCS615_SLAVE_CAMERA_CFG 59
+#define QCS615_SLAVE_CAMNOC_UNCOMP 60
+#define QCS615_SLAVE_CLK_CTL 61
+#define QCS615_SLAVE_CNOC_A2NOC 62
+#define QCS615_SLAVE_CNOC_DDRSS 63
+#define QCS615_SLAVE_CNOC_MNOC_CFG 64
+#define QCS615_SLAVE_CRYPTO_0_CFG 65
+#define QCS615_SLAVE_DC_NOC_GEMNOC 66
+#define QCS615_SLAVE_DISPLAY_CFG 67
+#define QCS615_SLAVE_EBI1 68
+#define QCS615_SLAVE_EMAC_AVB_CFG 69
+#define QCS615_SLAVE_GEM_NOC_SNOC 70
+#define QCS615_SLAVE_GFX3D_CFG 71
+#define QCS615_SLAVE_GLM 72
+#define QCS615_SLAVE_IMEM 73
+#define QCS615_SLAVE_IMEM_CFG 74
+#define QCS615_SLAVE_IPA_CFG 75
+#define QCS615_SLAVE_IPA_CORE 76
+#define QCS615_SLAVE_LLCC 77
+#define QCS615_SLAVE_LLCC_CFG 78
+#define QCS615_SLAVE_LPASS_SNOC 79
+#define QCS615_SLAVE_MEM_NOC_PCIE_SNOC 80
+#define QCS615_SLAVE_MNOC_HF_MEM_NOC 81
+#define QCS615_SLAVE_MNOC_SF_MEM_NOC 82
+#define QCS615_SLAVE_MSS_PROC_MS_MPU_CFG 83
+#define QCS615_SLAVE_PCIE_0 84
+#define QCS615_SLAVE_PCIE_CFG 85
+#define QCS615_SLAVE_PIMEM 86
+#define QCS615_SLAVE_PIMEM_CFG 87
+#define QCS615_SLAVE_PRNG 88
+#define QCS615_SLAVE_QDSS_CFG 89
+#define QCS615_SLAVE_QDSS_STM 90
+#define QCS615_SLAVE_QSPI 91
+#define QCS615_SLAVE_QUP_0 92
+#define QCS615_SLAVE_QUP_1 93
+#define QCS615_SLAVE_RBCPR_CX_CFG 94
+#define QCS615_SLAVE_RBCPR_MX_CFG 95
+#define QCS615_SLAVE_SDCC_1 96
+#define QCS615_SLAVE_SDCC_2 97
+#define QCS615_SLAVE_SERVICE_A2NOC 98
+#define QCS615_SLAVE_SERVICE_CNOC 99
+#define QCS615_SLAVE_SERVICE_GEM_NOC 100
+#define QCS615_SLAVE_SERVICE_MNOC 101
+#define QCS615_SLAVE_SERVICE_SNOC 102
+#define QCS615_SLAVE_SNOC_CFG 103
+#define QCS615_SLAVE_SNOC_CNOC 104
+#define QCS615_SLAVE_SNOC_GEM_NOC_SF 105
+#define QCS615_SLAVE_SNOC_MEM_NOC_GC 106
+#define QCS615_SLAVE_SPDM_WRAPPER 107
+#define QCS615_SLAVE_TCSR 108
+#define QCS615_SLAVE_TCU 109
+#define QCS615_SLAVE_TLMM_EAST 110
+#define QCS615_SLAVE_TLMM_SOUTH 111
+#define QCS615_SLAVE_TLMM_WEST 112
+#define QCS615_SLAVE_UFS_MEM_CFG 113
+#define QCS615_SLAVE_USB2 114
+#define QCS615_SLAVE_USB3 115
+#define QCS615_SLAVE_VENUS_CFG 116
+#define QCS615_SLAVE_VSENSE_CTRL_CFG 117
+
+#endif
+
diff --git a/drivers/interconnect/qcom/qcs8300.c b/drivers/interconnect/qcom/qcs8300.c
new file mode 100644
index 000000000000..e7a1b2fc69ba
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs8300.c
@@ -0,0 +1,2088 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <dt-bindings/interconnect/qcom,qcs8300-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+#include "qcs8300.h"
+
+static struct qcom_icc_node qxm_qup3 = {
+ .name = "qxm_qup3",
+ .id = QCS8300_MASTER_QUP_3,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_emac_0 = {
+ .name = "xm_emac_0",
+ .id = QCS8300_MASTER_EMAC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = QCS8300_MASTER_SDC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_ufs_mem = {
+ .name = "xm_ufs_mem",
+ .id = QCS8300_MASTER_UFS_MEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb2_2 = {
+ .name = "xm_usb2_2",
+ .id = QCS8300_MASTER_USB2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = QCS8300_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = QCS8300_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = QCS8300_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = QCS8300_MASTER_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_cnoc_datapath = {
+ .name = "qnm_cnoc_datapath",
+ .id = QCS8300_MASTER_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto_0 = {
+ .name = "qxm_crypto_0",
+ .id = QCS8300_MASTER_CRYPTO_CORE0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto_1 = {
+ .name = "qxm_crypto_1",
+ .id = QCS8300_MASTER_CRYPTO_CORE1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .id = QCS8300_MASTER_IPA,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr_0 = {
+ .name = "xm_qdss_etr_0",
+ .id = QCS8300_MASTER_QDSS_ETR_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr_1 = {
+ .name = "xm_qdss_etr_1",
+ .id = QCS8300_MASTER_QDSS_ETR_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_0 },
+};
+
+static struct qcom_icc_node qup1_core_master = {
+ .name = "qup1_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_1 },
+};
+
+static struct qcom_icc_node qup3_core_master = {
+ .name = "qup3_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_3 },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cnoc = {
+ .name = "qnm_gemnoc_cnoc",
+ .id = QCS8300_MASTER_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 71,
+ .links = { QCS8300_SLAVE_AHB2PHY_2, QCS8300_SLAVE_AHB2PHY_3,
+ QCS8300_SLAVE_ANOC_THROTTLE_CFG, QCS8300_SLAVE_AOSS,
+ QCS8300_SLAVE_APPSS, QCS8300_SLAVE_BOOT_ROM,
+ QCS8300_SLAVE_CAMERA_CFG, QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG, QCS8300_SLAVE_CLK_CTL,
+ QCS8300_SLAVE_CDSP_CFG, QCS8300_SLAVE_RBCPR_CX_CFG,
+ QCS8300_SLAVE_RBCPR_MMCX_CFG, QCS8300_SLAVE_RBCPR_MX_CFG,
+ QCS8300_SLAVE_CPR_NSPCX, QCS8300_SLAVE_CPR_NSPHMX,
+ QCS8300_SLAVE_CRYPTO_0_CFG, QCS8300_SLAVE_CX_RDPM,
+ QCS8300_SLAVE_DISPLAY_CFG, QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG,
+ QCS8300_SLAVE_EMAC_CFG, QCS8300_SLAVE_GP_DSP0_CFG,
+ QCS8300_SLAVE_GPDSP0_THROTTLE_CFG, QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG,
+ QCS8300_SLAVE_GFX3D_CFG, QCS8300_SLAVE_HWKM,
+ QCS8300_SLAVE_IMEM_CFG, QCS8300_SLAVE_IPA_CFG,
+ QCS8300_SLAVE_IPC_ROUTER_CFG, QCS8300_SLAVE_LPASS,
+ QCS8300_SLAVE_LPASS_THROTTLE_CFG, QCS8300_SLAVE_MX_RDPM,
+ QCS8300_SLAVE_MXC_RDPM, QCS8300_SLAVE_PCIE_0_CFG,
+ QCS8300_SLAVE_PCIE_1_CFG, QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG,
+ QCS8300_SLAVE_PCIE_THROTTLE_CFG, QCS8300_SLAVE_PDM,
+ QCS8300_SLAVE_PIMEM_CFG, QCS8300_SLAVE_PKA_WRAPPER_CFG,
+ QCS8300_SLAVE_QDSS_CFG, QCS8300_SLAVE_QM_CFG,
+ QCS8300_SLAVE_QM_MPU_CFG, QCS8300_SLAVE_QUP_0,
+ QCS8300_SLAVE_QUP_1, QCS8300_SLAVE_QUP_3,
+ QCS8300_SLAVE_SAIL_THROTTLE_CFG, QCS8300_SLAVE_SDC1,
+ QCS8300_SLAVE_SECURITY, QCS8300_SLAVE_SNOC_THROTTLE_CFG,
+ QCS8300_SLAVE_TCSR, QCS8300_SLAVE_TLMM,
+ QCS8300_SLAVE_TSC_CFG, QCS8300_SLAVE_UFS_MEM_CFG,
+ QCS8300_SLAVE_USB2, QCS8300_SLAVE_USB3_0,
+ QCS8300_SLAVE_VENUS_CFG, QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG,
+ QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG,
+ QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG,
+ QCS8300_SLAVE_DDRSS_CFG, QCS8300_SLAVE_GPDSP_NOC_CFG,
+ QCS8300_SLAVE_CNOC_MNOC_HF_CFG, QCS8300_SLAVE_CNOC_MNOC_SF_CFG,
+ QCS8300_SLAVE_PCIE_ANOC_CFG, QCS8300_SLAVE_SNOC_CFG,
+ QCS8300_SLAVE_BOOT_IMEM, QCS8300_SLAVE_IMEM,
+ QCS8300_SLAVE_PIMEM, QCS8300_SLAVE_QDSS_STM,
+ QCS8300_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = QCS8300_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_PCIE_0, QCS8300_SLAVE_PCIE_1 },
+};
+
+static struct qcom_icc_node qnm_cnoc_dc_noc = {
+ .name = "qnm_cnoc_dc_noc",
+ .id = QCS8300_MASTER_CNOC_DC_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_LLCC_CFG, QCS8300_SLAVE_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node alm_gpu_tcu = {
+ .name = "alm_gpu_tcu",
+ .id = QCS8300_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node alm_pcie_tcu = {
+ .name = "alm_pcie_tcu",
+ .id = QCS8300_MASTER_PCIE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node alm_sys_tcu = {
+ .name = "alm_sys_tcu",
+ .id = QCS8300_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node chm_apps = {
+ .name = "chm_apps",
+ .id = QCS8300_MASTER_APPSS_PROC,
+ .channels = 4,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_cmpnoc0 = {
+ .name = "qnm_cmpnoc0",
+ .id = QCS8300_MASTER_COMPUTE_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cfg = {
+ .name = "qnm_gemnoc_cfg",
+ .id = QCS8300_MASTER_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 4,
+ .links = { QCS8300_SLAVE_SERVICE_GEM_NOC_1, QCS8300_SLAVE_SERVICE_GEM_NOC_2,
+ QCS8300_SLAVE_SERVICE_GEM_NOC, QCS8300_SLAVE_SERVICE_GEM_NOC2 },
+};
+
+static struct qcom_icc_node qnm_gpdsp_sail = {
+ .name = "qnm_gpdsp_sail",
+ .id = QCS8300_MASTER_GPDSP_SAIL,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = QCS8300_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = QCS8300_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_LLCC, QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = QCS8300_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_pcie = {
+ .name = "qnm_pcie",
+ .id = QCS8300_MASTER_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = QCS8300_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = QCS8300_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_sailss_md0 = {
+ .name = "qnm_sailss_md0",
+ .id = QCS8300_MASTER_SAILSS_MD0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_GP_DSP_SAIL_NOC },
+};
+
+static struct qcom_icc_node qxm_dsp0 = {
+ .name = "qxm_dsp0",
+ .id = QCS8300_MASTER_DSP0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_GP_DSP_SAIL_NOC },
+};
+
+static struct qcom_icc_node qhm_config_noc = {
+ .name = "qhm_config_noc",
+ .id = QCS8300_MASTER_CNOC_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 6,
+ .links = { QCS8300_SLAVE_LPASS_CORE_CFG, QCS8300_SLAVE_LPASS_LPI_CFG,
+ QCS8300_SLAVE_LPASS_MPU_CFG, QCS8300_SLAVE_LPASS_TOP_CFG,
+ QCS8300_SLAVE_SERVICES_LPASS_AML_NOC, QCS8300_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qxm_lpass_dsp = {
+ .name = "qxm_lpass_dsp",
+ .id = QCS8300_MASTER_LPASS_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 4,
+ .links = { QCS8300_SLAVE_LPASS_TOP_CFG, QCS8300_SLAVE_LPASS_SNOC,
+ QCS8300_SLAVE_SERVICES_LPASS_AML_NOC, QCS8300_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = QCS8300_MASTER_LLCC,
+ .channels = 8,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_EBI1 },
+};
+
+static struct qcom_icc_node qnm_camnoc_hf = {
+ .name = "qnm_camnoc_hf",
+ .id = QCS8300_MASTER_CAMNOC_HF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_camnoc_icp = {
+ .name = "qnm_camnoc_icp",
+ .id = QCS8300_MASTER_CAMNOC_ICP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_camnoc_sf = {
+ .name = "qnm_camnoc_sf",
+ .id = QCS8300_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mdp0_0 = {
+ .name = "qnm_mdp0_0",
+ .id = QCS8300_MASTER_MDP0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mdp0_1 = {
+ .name = "qnm_mdp0_1",
+ .id = QCS8300_MASTER_MDP1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf_cfg = {
+ .name = "qnm_mnoc_hf_cfg",
+ .id = QCS8300_MASTER_CNOC_MNOC_HF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_MNOC_HF },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf_cfg = {
+ .name = "qnm_mnoc_sf_cfg",
+ .id = QCS8300_MASTER_CNOC_MNOC_SF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_MNOC_SF },
+};
+
+static struct qcom_icc_node qnm_video0 = {
+ .name = "qnm_video0",
+ .id = QCS8300_MASTER_VIDEO_P0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_video_cvp = {
+ .name = "qnm_video_cvp",
+ .id = QCS8300_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_video_v_cpu = {
+ .name = "qnm_video_v_cpu",
+ .id = QCS8300_MASTER_VIDEO_V_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_nsp_noc_config = {
+ .name = "qhm_nsp_noc_config",
+ .id = QCS8300_MASTER_CDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_NSP_NOC },
+};
+
+static struct qcom_icc_node qxm_nsp = {
+ .name = "qxm_nsp",
+ .id = QCS8300_MASTER_CDSP_PROC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_HCP_A, QCS8300_SLAVE_CDSP_MEM_NOC },
+};
+
+static struct qcom_icc_node xm_pcie3_0 = {
+ .name = "xm_pcie3_0",
+ .id = QCS8300_MASTER_PCIE_0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node xm_pcie3_1 = {
+ .name = "xm_pcie3_1",
+ .id = QCS8300_MASTER_PCIE_1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qhm_gic = {
+ .name = "qhm_gic",
+ .id = QCS8300_MASTER_GIC_AHB,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_aggre1_noc = {
+ .name = "qnm_aggre1_noc",
+ .id = QCS8300_MASTER_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_aggre2_noc = {
+ .name = "qnm_aggre2_noc",
+ .id = QCS8300_MASTER_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_lpass_noc = {
+ .name = "qnm_lpass_noc",
+ .id = QCS8300_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_snoc_cfg = {
+ .name = "qnm_snoc_cfg",
+ .id = QCS8300_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_SNOC },
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = QCS8300_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = QCS8300_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static struct qcom_icc_node qns_a1noc_snoc = {
+ .name = "qns_a1noc_snoc",
+ .id = QCS8300_SLAVE_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_a2noc_snoc = {
+ .name = "qns_a2noc_snoc",
+ .id = QCS8300_SLAVE_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup1_core_slave = {
+ .name = "qup1_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup3_core_slave = {
+ .name = "qup3_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy2 = {
+ .name = "qhs_ahb2phy2",
+ .id = QCS8300_SLAVE_AHB2PHY_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy3 = {
+ .name = "qhs_ahb2phy3",
+ .id = QCS8300_SLAVE_AHB2PHY_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_anoc_throttle_cfg = {
+ .name = "qhs_anoc_throttle_cfg",
+ .id = QCS8300_SLAVE_ANOC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = QCS8300_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_apss = {
+ .name = "qhs_apss",
+ .id = QCS8300_SLAVE_APPSS,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_boot_rom = {
+ .name = "qhs_boot_rom",
+ .id = QCS8300_SLAVE_BOOT_ROM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = QCS8300_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_nrt_throttle_cfg = {
+ .name = "qhs_camera_nrt_throttle_cfg",
+ .id = QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_rt_throttle_cfg = {
+ .name = "qhs_camera_rt_throttle_cfg",
+ .id = QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = QCS8300_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_compute0_cfg = {
+ .name = "qhs_compute0_cfg",
+ .id = QCS8300_SLAVE_CDSP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CDSP_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = QCS8300_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mmcx = {
+ .name = "qhs_cpr_mmcx",
+ .id = QCS8300_SLAVE_RBCPR_MMCX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mx = {
+ .name = "qhs_cpr_mx",
+ .id = QCS8300_SLAVE_RBCPR_MX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nspcx = {
+ .name = "qhs_cpr_nspcx",
+ .id = QCS8300_SLAVE_CPR_NSPCX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nsphmx = {
+ .name = "qhs_cpr_nsphmx",
+ .id = QCS8300_SLAVE_CPR_NSPHMX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = QCS8300_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cx_rdpm = {
+ .name = "qhs_cx_rdpm",
+ .id = QCS8300_SLAVE_CX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display0_cfg = {
+ .name = "qhs_display0_cfg",
+ .id = QCS8300_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display0_rt_throttle_cfg = {
+ .name = "qhs_display0_rt_throttle_cfg",
+ .id = QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_emac0_cfg = {
+ .name = "qhs_emac0_cfg",
+ .id = QCS8300_SLAVE_EMAC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gp_dsp0_cfg = {
+ .name = "qhs_gp_dsp0_cfg",
+ .id = QCS8300_SLAVE_GP_DSP0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpdsp0_throttle_cfg = {
+ .name = "qhs_gpdsp0_throttle_cfg",
+ .id = QCS8300_SLAVE_GPDSP0_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpu_tcu_throttle_cfg = {
+ .name = "qhs_gpu_tcu_throttle_cfg",
+ .id = QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = QCS8300_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_hwkm = {
+ .name = "qhs_hwkm",
+ .id = QCS8300_SLAVE_HWKM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = QCS8300_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipa = {
+ .name = "qhs_ipa",
+ .id = QCS8300_SLAVE_IPA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipc_router = {
+ .name = "qhs_ipc_router",
+ .id = QCS8300_SLAVE_IPC_ROUTER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_cfg = {
+ .name = "qhs_lpass_cfg",
+ .id = QCS8300_SLAVE_LPASS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qhs_lpass_throttle_cfg = {
+ .name = "qhs_lpass_throttle_cfg",
+ .id = QCS8300_SLAVE_LPASS_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mx_rdpm = {
+ .name = "qhs_mx_rdpm",
+ .id = QCS8300_SLAVE_MX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mxc_rdpm = {
+ .name = "qhs_mxc_rdpm",
+ .id = QCS8300_SLAVE_MXC_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie0_cfg = {
+ .name = "qhs_pcie0_cfg",
+ .id = QCS8300_SLAVE_PCIE_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie1_cfg = {
+ .name = "qhs_pcie1_cfg",
+ .id = QCS8300_SLAVE_PCIE_1_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie_tcu_throttle_cfg = {
+ .name = "qhs_pcie_tcu_throttle_cfg",
+ .id = QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie_throttle_cfg = {
+ .name = "qhs_pcie_throttle_cfg",
+ .id = QCS8300_SLAVE_PCIE_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pdm = {
+ .name = "qhs_pdm",
+ .id = QCS8300_SLAVE_PDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = QCS8300_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pke_wrapper_cfg = {
+ .name = "qhs_pke_wrapper_cfg",
+ .id = QCS8300_SLAVE_PKA_WRAPPER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = QCS8300_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qm_cfg = {
+ .name = "qhs_qm_cfg",
+ .id = QCS8300_SLAVE_QM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qm_mpu_cfg = {
+ .name = "qhs_qm_mpu_cfg",
+ .id = QCS8300_SLAVE_QM_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = QCS8300_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = QCS8300_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup3 = {
+ .name = "qhs_qup3",
+ .id = QCS8300_SLAVE_QUP_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sail_throttle_cfg = {
+ .name = "qhs_sail_throttle_cfg",
+ .id = QCS8300_SLAVE_SAIL_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = QCS8300_SLAVE_SDC1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_security = {
+ .name = "qhs_security",
+ .id = QCS8300_SLAVE_SECURITY,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_snoc_throttle_cfg = {
+ .name = "qhs_snoc_throttle_cfg",
+ .id = QCS8300_SLAVE_SNOC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = QCS8300_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .id = QCS8300_SLAVE_TLMM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tsc_cfg = {
+ .name = "qhs_tsc_cfg",
+ .id = QCS8300_SLAVE_TSC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ufs_mem_cfg = {
+ .name = "qhs_ufs_mem_cfg",
+ .id = QCS8300_SLAVE_UFS_MEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb2_0 = {
+ .name = "qhs_usb2_0",
+ .id = QCS8300_SLAVE_USB2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3_0 = {
+ .name = "qhs_usb3_0",
+ .id = QCS8300_SLAVE_USB3_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = QCS8300_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cvp_throttle_cfg = {
+ .name = "qhs_venus_cvp_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_v_cpu_throttle_cfg = {
+ .name = "qhs_venus_v_cpu_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_vcodec_throttle_cfg = {
+ .name = "qhs_venus_vcodec_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_ddrss_cfg = {
+ .name = "qns_ddrss_cfg",
+ .id = QCS8300_SLAVE_DDRSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_DC_NOC },
+};
+
+static struct qcom_icc_node qns_gpdsp_noc_cfg = {
+ .name = "qns_gpdsp_noc_cfg",
+ .id = QCS8300_SLAVE_GPDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mnoc_hf_cfg = {
+ .name = "qns_mnoc_hf_cfg",
+ .id = QCS8300_SLAVE_CNOC_MNOC_HF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_MNOC_HF_CFG },
+};
+
+static struct qcom_icc_node qns_mnoc_sf_cfg = {
+ .name = "qns_mnoc_sf_cfg",
+ .id = QCS8300_SLAVE_CNOC_MNOC_SF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_MNOC_SF_CFG },
+};
+
+static struct qcom_icc_node qns_pcie_anoc_cfg = {
+ .name = "qns_pcie_anoc_cfg",
+ .id = QCS8300_SLAVE_PCIE_ANOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_snoc_cfg = {
+ .name = "qns_snoc_cfg",
+ .id = QCS8300_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qxs_boot_imem = {
+ .name = "qxs_boot_imem",
+ .id = QCS8300_SLAVE_BOOT_IMEM,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = QCS8300_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = QCS8300_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_0 = {
+ .name = "xs_pcie_0",
+ .id = QCS8300_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_1 = {
+ .name = "xs_pcie_1",
+ .id = QCS8300_SLAVE_PCIE_1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = QCS8300_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = QCS8300_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_llcc = {
+ .name = "qhs_llcc",
+ .id = QCS8300_SLAVE_LLCC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gemnoc = {
+ .name = "qns_gemnoc",
+ .id = QCS8300_SLAVE_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node qns_gem_noc_cnoc = {
+ .name = "qns_gem_noc_cnoc",
+ .id = QCS8300_SLAVE_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_CNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = QCS8300_SLAVE_LLCC,
+ .channels = 4,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_pcie = {
+ .name = "qns_pcie",
+ .id = QCS8300_SLAVE_GEM_NOC_PCIE_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_even_gemnoc = {
+ .name = "srvc_even_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_odd_gemnoc = {
+ .name = "srvc_odd_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_sys_gemnoc = {
+ .name = "srvc_sys_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_sys_gemnoc_2 = {
+ .name = "srvc_sys_gemnoc_2",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gp_dsp_sail_noc = {
+ .name = "qns_gp_dsp_sail_noc",
+ .id = QCS8300_SLAVE_GP_DSP_SAIL_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GPDSP_SAIL },
+};
+
+static struct qcom_icc_node qhs_lpass_core = {
+ .name = "qhs_lpass_core",
+ .id = QCS8300_SLAVE_LPASS_CORE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_lpi = {
+ .name = "qhs_lpass_lpi",
+ .id = QCS8300_SLAVE_LPASS_LPI_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_mpu = {
+ .name = "qhs_lpass_mpu",
+ .id = QCS8300_SLAVE_LPASS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_top = {
+ .name = "qhs_lpass_top",
+ .id = QCS8300_SLAVE_LPASS_TOP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_sysnoc = {
+ .name = "qns_sysnoc",
+ .id = QCS8300_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node srvc_niu_aml_noc = {
+ .name = "srvc_niu_aml_noc",
+ .id = QCS8300_SLAVE_SERVICES_LPASS_AML_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_niu_lpass_agnoc = {
+ .name = "srvc_niu_lpass_agnoc",
+ .id = QCS8300_SLAVE_SERVICE_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = QCS8300_SLAVE_EBI1,
+ .channels = 8,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = QCS8300_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_sf = {
+ .name = "qns_mem_noc_sf",
+ .id = QCS8300_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc_hf = {
+ .name = "srvc_mnoc_hf",
+ .id = QCS8300_SLAVE_SERVICE_MNOC_HF,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_mnoc_sf = {
+ .name = "srvc_mnoc_sf",
+ .id = QCS8300_SLAVE_SERVICE_MNOC_SF,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_hcp = {
+ .name = "qns_hcp",
+ .id = QCS8300_SLAVE_HCP_A,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_nsp_gemnoc = {
+ .name = "qns_nsp_gemnoc",
+ .id = QCS8300_SLAVE_CDSP_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_COMPUTE_NOC },
+};
+
+static struct qcom_icc_node service_nsp_noc = {
+ .name = "service_nsp_noc",
+ .id = QCS8300_SLAVE_SERVICE_NSP_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_pcie_mem_noc = {
+ .name = "qns_pcie_mem_noc",
+ .id = QCS8300_SLAVE_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_gc = {
+ .name = "qns_gemnoc_gc",
+ .id = QCS8300_SLAVE_SNOC_GEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = QCS8300_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = QCS8300_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .enable_mask = BIT(3),
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 2,
+ .nodes = { &qxm_crypto_0, &qxm_crypto_1 },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .keepalive = true,
+ .num_nodes = 2,
+ .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie },
+};
+
+static struct qcom_icc_bcm bcm_cn1 = {
+ .name = "CN1",
+ .num_nodes = 66,
+ .nodes = { &qhs_ahb2phy2, &qhs_ahb2phy3,
+ &qhs_anoc_throttle_cfg, &qhs_aoss,
+ &qhs_apss, &qhs_boot_rom,
+ &qhs_camera_cfg, &qhs_camera_nrt_throttle_cfg,
+ &qhs_camera_rt_throttle_cfg, &qhs_clk_ctl,
+ &qhs_compute0_cfg, &qhs_cpr_cx,
+ &qhs_cpr_mmcx, &qhs_cpr_mx,
+ &qhs_cpr_nspcx, &qhs_cpr_nsphmx,
+ &qhs_crypto0_cfg, &qhs_cx_rdpm,
+ &qhs_display0_cfg, &qhs_display0_rt_throttle_cfg,
+ &qhs_emac0_cfg, &qhs_gp_dsp0_cfg,
+ &qhs_gpdsp0_throttle_cfg, &qhs_gpu_tcu_throttle_cfg,
+ &qhs_gpuss_cfg, &qhs_hwkm,
+ &qhs_imem_cfg, &qhs_ipa,
+ &qhs_ipc_router, &qhs_lpass_cfg,
+ &qhs_lpass_throttle_cfg, &qhs_mx_rdpm,
+ &qhs_mxc_rdpm, &qhs_pcie0_cfg,
+ &qhs_pcie1_cfg, &qhs_pcie_tcu_throttle_cfg,
+ &qhs_pcie_throttle_cfg, &qhs_pdm,
+ &qhs_pimem_cfg, &qhs_pke_wrapper_cfg,
+ &qhs_qdss_cfg, &qhs_qm_cfg,
+ &qhs_qm_mpu_cfg, &qhs_sail_throttle_cfg,
+ &qhs_sdc1, &qhs_security,
+ &qhs_snoc_throttle_cfg, &qhs_tcsr,
+ &qhs_tlmm, &qhs_tsc_cfg,
+ &qhs_ufs_mem_cfg, &qhs_usb2_0,
+ &qhs_usb3_0, &qhs_venus_cfg,
+ &qhs_venus_cvp_throttle_cfg, &qhs_venus_v_cpu_throttle_cfg,
+ &qhs_venus_vcodec_throttle_cfg, &qns_ddrss_cfg,
+ &qns_gpdsp_noc_cfg, &qns_mnoc_hf_cfg,
+ &qns_mnoc_sf_cfg, &qns_pcie_anoc_cfg,
+ &qns_snoc_cfg, &qxs_boot_imem,
+ &qxs_imem, &xs_sys_tcu_cfg },
+};
+
+static struct qcom_icc_bcm bcm_cn2 = {
+ .name = "CN2",
+ .num_nodes = 3,
+ .nodes = { &qhs_qup0, &qhs_qup1,
+ &qhs_qup3 },
+};
+
+static struct qcom_icc_bcm bcm_cn3 = {
+ .name = "CN3",
+ .num_nodes = 2,
+ .nodes = { &xs_pcie_0, &xs_pcie_1 },
+};
+
+static struct qcom_icc_bcm bcm_gna0 = {
+ .name = "GNA0",
+ .num_nodes = 1,
+ .nodes = { &qxm_dsp0 },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 4,
+ .nodes = { &qnm_camnoc_hf, &qnm_mdp0_0,
+ &qnm_mdp0_1, &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .num_nodes = 6,
+ .nodes = { &qnm_camnoc_icp, &qnm_camnoc_sf,
+ &qnm_video0, &qnm_video_cvp,
+ &qnm_video_v_cpu, &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_bcm bcm_nsa0 = {
+ .name = "NSA0",
+ .num_nodes = 2,
+ .nodes = { &qns_hcp, &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_bcm bcm_nsa1 = {
+ .name = "NSA1",
+ .num_nodes = 1,
+ .nodes = { &qxm_nsp },
+};
+
+static struct qcom_icc_bcm bcm_pci0 = {
+ .name = "PCI0",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup0_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup1 = {
+ .name = "QUP1",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup2 = {
+ .name = "QUP2",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup3_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh2 = {
+ .name = "SH2",
+ .num_nodes = 1,
+ .nodes = { &chm_apps },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn2 = {
+ .name = "SN2",
+ .num_nodes = 1,
+ .nodes = { &qxs_pimem },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 2,
+ .nodes = { &qns_a1noc_snoc, &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 2,
+ .nodes = { &qns_a2noc_snoc, &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn9 = {
+ .name = "SN9",
+ .num_nodes = 2,
+ .nodes = { &qns_sysnoc, &qnm_lpass_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn10 = {
+ .name = "SN10",
+ .num_nodes = 1,
+ .nodes = { &xs_qdss_stm },
+};
+
+static struct qcom_icc_bcm * const aggre1_noc_bcms[] = {
+ &bcm_sn3,
+};
+
+static struct qcom_icc_node * const aggre1_noc_nodes[] = {
+ [MASTER_QUP_3] = &qxm_qup3,
+ [MASTER_EMAC] = &xm_emac_0,
+ [MASTER_SDC] = &xm_sdc1,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB2] = &xm_usb2_2,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .bcms = aggre1_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_sn4,
+};
+
+static struct qcom_icc_node * const aggre2_noc_nodes[] = {
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_QUP_1] = &qhm_qup1,
+ [MASTER_CNOC_A2NOC] = &qnm_cnoc_datapath,
+ [MASTER_CRYPTO_CORE0] = &qxm_crypto_0,
+ [MASTER_CRYPTO_CORE1] = &qxm_crypto_1,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_QDSS_ETR_0] = &xm_qdss_etr_0,
+ [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_aggre2_noc = {
+ .nodes = aggre2_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
+ .bcms = aggre2_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+ &bcm_qup0,
+ &bcm_qup1,
+ &bcm_qup2,
+};
+
+static struct qcom_icc_node * const clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [MASTER_QUP_CORE_3] = &qup3_core_master,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+ [SLAVE_QUP_CORE_3] = &qup3_core_slave,
+};
+
+static const struct qcom_icc_desc qcs8300_clk_virt = {
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .bcms = clk_virt_bcms,
+ .num_bcms = ARRAY_SIZE(clk_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+ &bcm_cn1,
+ &bcm_cn2,
+ &bcm_cn3,
+ &bcm_sn2,
+ &bcm_sn10,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [SLAVE_AHB2PHY_2] = &qhs_ahb2phy2,
+ [SLAVE_AHB2PHY_3] = &qhs_ahb2phy3,
+ [SLAVE_ANOC_THROTTLE_CFG] = &qhs_anoc_throttle_cfg,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SLAVE_BOOT_ROM] = &qhs_boot_rom,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CAMERA_NRT_THROTTLE_CFG] = &qhs_camera_nrt_throttle_cfg,
+ [SLAVE_CAMERA_RT_THROTTLE_CFG] = &qhs_camera_rt_throttle_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &qhs_compute0_cfg,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MMCX_CFG] = &qhs_cpr_mmcx,
+ [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx,
+ [SLAVE_CPR_NSPCX] = &qhs_cpr_nspcx,
+ [SLAVE_CPR_NSPHMX] = &qhs_cpr_nsphmx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CX_RDPM] = &qhs_cx_rdpm,
+ [SLAVE_DISPLAY_CFG] = &qhs_display0_cfg,
+ [SLAVE_DISPLAY_RT_THROTTLE_CFG] = &qhs_display0_rt_throttle_cfg,
+ [SLAVE_EMAC_CFG] = &qhs_emac0_cfg,
+ [SLAVE_GP_DSP0_CFG] = &qhs_gp_dsp0_cfg,
+ [SLAVE_GPDSP0_THROTTLE_CFG] = &qhs_gpdsp0_throttle_cfg,
+ [SLAVE_GPU_TCU_THROTTLE_CFG] = &qhs_gpu_tcu_throttle_cfg,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_HWKM] = &qhs_hwkm,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router,
+ [SLAVE_LPASS] = &qhs_lpass_cfg,
+ [SLAVE_LPASS_THROTTLE_CFG] = &qhs_lpass_throttle_cfg,
+ [SLAVE_MX_RDPM] = &qhs_mx_rdpm,
+ [SLAVE_MXC_RDPM] = &qhs_mxc_rdpm,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &qhs_pcie1_cfg,
+ [SLAVE_PCIE_TCU_THROTTLE_CFG] = &qhs_pcie_tcu_throttle_cfg,
+ [SLAVE_PCIE_THROTTLE_CFG] = &qhs_pcie_throttle_cfg,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PKA_WRAPPER_CFG] = &qhs_pke_wrapper_cfg,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QM_CFG] = &qhs_qm_cfg,
+ [SLAVE_QM_MPU_CFG] = &qhs_qm_mpu_cfg,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_QUP_3] = &qhs_qup3,
+ [SLAVE_SAIL_THROTTLE_CFG] = &qhs_sail_throttle_cfg,
+ [SLAVE_SDC1] = &qhs_sdc1,
+ [SLAVE_SECURITY] = &qhs_security,
+ [SLAVE_SNOC_THROTTLE_CFG] = &qhs_snoc_throttle_cfg,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_TSC_CFG] = &qhs_tsc_cfg,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB2] = &qhs_usb2_0,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VENUS_CVP_THROTTLE_CFG] = &qhs_venus_cvp_throttle_cfg,
+ [SLAVE_VENUS_V_CPU_THROTTLE_CFG] = &qhs_venus_v_cpu_throttle_cfg,
+ [SLAVE_VENUS_VCODEC_THROTTLE_CFG] = &qhs_venus_vcodec_throttle_cfg,
+ [SLAVE_DDRSS_CFG] = &qns_ddrss_cfg,
+ [SLAVE_GPDSP_NOC_CFG] = &qns_gpdsp_noc_cfg,
+ [SLAVE_CNOC_MNOC_HF_CFG] = &qns_mnoc_hf_cfg,
+ [SLAVE_CNOC_MNOC_SF_CFG] = &qns_mnoc_sf_cfg,
+ [SLAVE_PCIE_ANOC_CFG] = &qns_pcie_anoc_cfg,
+ [SLAVE_SNOC_CFG] = &qns_snoc_cfg,
+ [SLAVE_BOOT_IMEM] = &qxs_boot_imem,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_PCIE_0] = &xs_pcie_0,
+ [SLAVE_PCIE_1] = &xs_pcie_1,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc qcs8300_config_noc = {
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_node * const dc_noc_nodes[] = {
+ [MASTER_CNOC_DC_NOC] = &qnm_cnoc_dc_noc,
+ [SLAVE_LLCC_CFG] = &qhs_llcc,
+ [SLAVE_GEM_NOC_CFG] = &qns_gemnoc,
+};
+
+static const struct qcom_icc_desc qcs8300_dc_noc = {
+ .nodes = dc_noc_nodes,
+ .num_nodes = ARRAY_SIZE(dc_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh2,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_GPU_TCU] = &alm_gpu_tcu,
+ [MASTER_PCIE_TCU] = &alm_pcie_tcu,
+ [MASTER_SYS_TCU] = &alm_sys_tcu,
+ [MASTER_APPSS_PROC] = &chm_apps,
+ [MASTER_COMPUTE_NOC] = &qnm_cmpnoc0,
+ [MASTER_GEM_NOC_CFG] = &qnm_gemnoc_cfg,
+ [MASTER_GPDSP_SAIL] = &qnm_gpdsp_sail,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_GEM_NOC_PCIE_CNOC] = &qns_pcie,
+ [SLAVE_SERVICE_GEM_NOC_1] = &srvc_even_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC_2] = &srvc_odd_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC] = &srvc_sys_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC2] = &srvc_sys_gemnoc_2,
+};
+
+static const struct qcom_icc_desc qcs8300_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const gpdsp_anoc_bcms[] = {
+ &bcm_gna0,
+};
+
+static struct qcom_icc_node * const gpdsp_anoc_nodes[] = {
+ [MASTER_SAILSS_MD0] = &qnm_sailss_md0,
+ [MASTER_DSP0] = &qxm_dsp0,
+ [SLAVE_GP_DSP_SAIL_NOC] = &qns_gp_dsp_sail_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_gpdsp_anoc = {
+ .nodes = gpdsp_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(gpdsp_anoc_nodes),
+ .bcms = gpdsp_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(gpdsp_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const lpass_ag_noc_bcms[] = {
+ &bcm_sn9,
+};
+
+static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
+ [MASTER_CNOC_LPASS_AG_NOC] = &qhm_config_noc,
+ [MASTER_LPASS_PROC] = &qxm_lpass_dsp,
+ [SLAVE_LPASS_CORE_CFG] = &qhs_lpass_core,
+ [SLAVE_LPASS_LPI_CFG] = &qhs_lpass_lpi,
+ [SLAVE_LPASS_MPU_CFG] = &qhs_lpass_mpu,
+ [SLAVE_LPASS_TOP_CFG] = &qhs_lpass_top,
+ [SLAVE_LPASS_SNOC] = &qns_sysnoc,
+ [SLAVE_SERVICES_LPASS_AML_NOC] = &srvc_niu_aml_noc,
+ [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc,
+};
+
+static const struct qcom_icc_desc qcs8300_lpass_ag_noc = {
+ .nodes = lpass_ag_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
+ .bcms = lpass_ag_noc_bcms,
+ .num_bcms = ARRAY_SIZE(lpass_ag_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc qcs8300_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CAMNOC_HF] = &qnm_camnoc_hf,
+ [MASTER_CAMNOC_ICP] = &qnm_camnoc_icp,
+ [MASTER_CAMNOC_SF] = &qnm_camnoc_sf,
+ [MASTER_MDP0] = &qnm_mdp0_0,
+ [MASTER_MDP1] = &qnm_mdp0_1,
+ [MASTER_CNOC_MNOC_HF_CFG] = &qnm_mnoc_hf_cfg,
+ [MASTER_CNOC_MNOC_SF_CFG] = &qnm_mnoc_sf_cfg,
+ [MASTER_VIDEO_P0] = &qnm_video0,
+ [MASTER_VIDEO_PROC] = &qnm_video_cvp,
+ [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf,
+ [SLAVE_SERVICE_MNOC_HF] = &srvc_mnoc_hf,
+ [SLAVE_SERVICE_MNOC_SF] = &srvc_mnoc_sf,
+};
+
+static const struct qcom_icc_desc qcs8300_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const nspa_noc_bcms[] = {
+ &bcm_nsa0,
+ &bcm_nsa1,
+};
+
+static struct qcom_icc_node * const nspa_noc_nodes[] = {
+ [MASTER_CDSP_NOC_CFG] = &qhm_nsp_noc_config,
+ [MASTER_CDSP_PROC] = &qxm_nsp,
+ [SLAVE_HCP_A] = &qns_hcp,
+ [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc,
+ [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_nspa_noc = {
+ .nodes = nspa_noc_nodes,
+ .num_nodes = ARRAY_SIZE(nspa_noc_nodes),
+ .bcms = nspa_noc_bcms,
+ .num_bcms = ARRAY_SIZE(nspa_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const pcie_anoc_bcms[] = {
+ &bcm_pci0,
+};
+
+static struct qcom_icc_node * const pcie_anoc_nodes[] = {
+ [MASTER_PCIE_0] = &xm_pcie3_0,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_pcie_anoc = {
+ .nodes = pcie_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
+ .bcms = pcie_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(pcie_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn9,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_GIC_AHB] = &qhm_gic,
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_noc,
+ [MASTER_SNOC_CFG] = &qnm_snoc_cfg,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,qcs8300-aggre1-noc",
+ .data = &qcs8300_aggre1_noc},
+ { .compatible = "qcom,qcs8300-aggre2-noc",
+ .data = &qcs8300_aggre2_noc},
+ { .compatible = "qcom,qcs8300-clk-virt",
+ .data = &qcs8300_clk_virt},
+ { .compatible = "qcom,qcs8300-config-noc",
+ .data = &qcs8300_config_noc},
+ { .compatible = "qcom,qcs8300-dc-noc",
+ .data = &qcs8300_dc_noc},
+ { .compatible = "qcom,qcs8300-gem-noc",
+ .data = &qcs8300_gem_noc},
+ { .compatible = "qcom,qcs8300-gpdsp-anoc",
+ .data = &qcs8300_gpdsp_anoc},
+ { .compatible = "qcom,qcs8300-lpass-ag-noc",
+ .data = &qcs8300_lpass_ag_noc},
+ { .compatible = "qcom,qcs8300-mc-virt",
+ .data = &qcs8300_mc_virt},
+ { .compatible = "qcom,qcs8300-mmss-noc",
+ .data = &qcs8300_mmss_noc},
+ { .compatible = "qcom,qcs8300-nspa-noc",
+ .data = &qcs8300_nspa_noc},
+ { .compatible = "qcom,qcs8300-pcie-anoc",
+ .data = &qcs8300_pcie_anoc},
+ { .compatible = "qcom,qcs8300-system-noc",
+ .data = &qcs8300_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-qcs8300",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION("QCS8300 NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/qcs8300.h b/drivers/interconnect/qcom/qcs8300.h
new file mode 100644
index 000000000000..6b9e2b424c2a
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs8300.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_QCOM_QCS8300_H
+#define __DRIVERS_INTERCONNECT_QCOM_QCS8300_H
+
+#define QCS8300_MASTER_GPU_TCU 0
+#define QCS8300_MASTER_PCIE_TCU 1
+#define QCS8300_MASTER_SYS_TCU 2
+#define QCS8300_MASTER_APPSS_PROC 3
+#define QCS8300_MASTER_LLCC 4
+#define QCS8300_MASTER_CNOC_LPASS_AG_NOC 5
+#define QCS8300_MASTER_GIC_AHB 6
+#define QCS8300_MASTER_CDSP_NOC_CFG 7
+#define QCS8300_MASTER_QDSS_BAM 8
+#define QCS8300_MASTER_QUP_0 9
+#define QCS8300_MASTER_QUP_1 10
+#define QCS8300_MASTER_A1NOC_SNOC 11
+#define QCS8300_MASTER_A2NOC_SNOC 12
+#define QCS8300_MASTER_CAMNOC_HF 13
+#define QCS8300_MASTER_CAMNOC_ICP 14
+#define QCS8300_MASTER_CAMNOC_SF 15
+#define QCS8300_MASTER_COMPUTE_NOC 16
+#define QCS8300_MASTER_CNOC_A2NOC 17
+#define QCS8300_MASTER_CNOC_DC_NOC 18
+#define QCS8300_MASTER_GEM_NOC_CFG 19
+#define QCS8300_MASTER_GEM_NOC_CNOC 20
+#define QCS8300_MASTER_GEM_NOC_PCIE_SNOC 21
+#define QCS8300_MASTER_GPDSP_SAIL 22
+#define QCS8300_MASTER_GFX3D 23
+#define QCS8300_MASTER_LPASS_ANOC 24
+#define QCS8300_MASTER_MDP0 25
+#define QCS8300_MASTER_MDP1 26
+#define QCS8300_MASTER_MNOC_HF_MEM_NOC 27
+#define QCS8300_MASTER_CNOC_MNOC_HF_CFG 28
+#define QCS8300_MASTER_MNOC_SF_MEM_NOC 29
+#define QCS8300_MASTER_CNOC_MNOC_SF_CFG 30
+#define QCS8300_MASTER_ANOC_PCIE_GEM_NOC 31
+#define QCS8300_MASTER_SAILSS_MD0 32
+#define QCS8300_MASTER_SNOC_CFG 33
+#define QCS8300_MASTER_SNOC_GC_MEM_NOC 34
+#define QCS8300_MASTER_SNOC_SF_MEM_NOC 35
+#define QCS8300_MASTER_VIDEO_P0 36
+#define QCS8300_MASTER_VIDEO_PROC 37
+#define QCS8300_MASTER_VIDEO_V_PROC 38
+#define QCS8300_MASTER_QUP_CORE_0 39
+#define QCS8300_MASTER_QUP_CORE_1 40
+#define QCS8300_MASTER_QUP_CORE_3 41
+#define QCS8300_MASTER_CRYPTO_CORE0 42
+#define QCS8300_MASTER_CRYPTO_CORE1 43
+#define QCS8300_MASTER_DSP0 44
+#define QCS8300_MASTER_IPA 45
+#define QCS8300_MASTER_LPASS_PROC 46
+#define QCS8300_MASTER_CDSP_PROC 47
+#define QCS8300_MASTER_PIMEM 48
+#define QCS8300_MASTER_QUP_3 49
+#define QCS8300_MASTER_EMAC 50
+#define QCS8300_MASTER_GIC 51
+#define QCS8300_MASTER_PCIE_0 52
+#define QCS8300_MASTER_PCIE_1 53
+#define QCS8300_MASTER_QDSS_ETR_0 54
+#define QCS8300_MASTER_QDSS_ETR_1 55
+#define QCS8300_MASTER_SDC 56
+#define QCS8300_MASTER_UFS_MEM 57
+#define QCS8300_MASTER_USB2 58
+#define QCS8300_MASTER_USB3_0 59
+#define QCS8300_SLAVE_EBI1 60
+#define QCS8300_SLAVE_AHB2PHY_2 61
+#define QCS8300_SLAVE_AHB2PHY_3 62
+#define QCS8300_SLAVE_ANOC_THROTTLE_CFG 63
+#define QCS8300_SLAVE_AOSS 64
+#define QCS8300_SLAVE_APPSS 65
+#define QCS8300_SLAVE_BOOT_ROM 66
+#define QCS8300_SLAVE_CAMERA_CFG 67
+#define QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG 68
+#define QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG 69
+#define QCS8300_SLAVE_CLK_CTL 70
+#define QCS8300_SLAVE_CDSP_CFG 71
+#define QCS8300_SLAVE_RBCPR_CX_CFG 72
+#define QCS8300_SLAVE_RBCPR_MMCX_CFG 73
+#define QCS8300_SLAVE_RBCPR_MX_CFG 74
+#define QCS8300_SLAVE_CPR_NSPCX 75
+#define QCS8300_SLAVE_CPR_NSPHMX 76
+#define QCS8300_SLAVE_CRYPTO_0_CFG 77
+#define QCS8300_SLAVE_CX_RDPM 78
+#define QCS8300_SLAVE_DISPLAY_CFG 79
+#define QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG 80
+#define QCS8300_SLAVE_EMAC_CFG 81
+#define QCS8300_SLAVE_GP_DSP0_CFG 82
+#define QCS8300_SLAVE_GPDSP0_THROTTLE_CFG 83
+#define QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG 84
+#define QCS8300_SLAVE_GFX3D_CFG 85
+#define QCS8300_SLAVE_HWKM 86
+#define QCS8300_SLAVE_IMEM_CFG 87
+#define QCS8300_SLAVE_IPA_CFG 88
+#define QCS8300_SLAVE_IPC_ROUTER_CFG 89
+#define QCS8300_SLAVE_LLCC_CFG 90
+#define QCS8300_SLAVE_LPASS 91
+#define QCS8300_SLAVE_LPASS_CORE_CFG 92
+#define QCS8300_SLAVE_LPASS_LPI_CFG 93
+#define QCS8300_SLAVE_LPASS_MPU_CFG 94
+#define QCS8300_SLAVE_LPASS_THROTTLE_CFG 95
+#define QCS8300_SLAVE_LPASS_TOP_CFG 96
+#define QCS8300_SLAVE_MX_RDPM 97
+#define QCS8300_SLAVE_MXC_RDPM 98
+#define QCS8300_SLAVE_PCIE_0_CFG 99
+#define QCS8300_SLAVE_PCIE_1_CFG 100
+#define QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG 101
+#define QCS8300_SLAVE_PCIE_THROTTLE_CFG 102
+#define QCS8300_SLAVE_PDM 103
+#define QCS8300_SLAVE_PIMEM_CFG 104
+#define QCS8300_SLAVE_PKA_WRAPPER_CFG 105
+#define QCS8300_SLAVE_QDSS_CFG 106
+#define QCS8300_SLAVE_QM_CFG 107
+#define QCS8300_SLAVE_QM_MPU_CFG 108
+#define QCS8300_SLAVE_QUP_0 109
+#define QCS8300_SLAVE_QUP_1 110
+#define QCS8300_SLAVE_QUP_3 111
+#define QCS8300_SLAVE_SAIL_THROTTLE_CFG 112
+#define QCS8300_SLAVE_SDC1 113
+#define QCS8300_SLAVE_SECURITY 114
+#define QCS8300_SLAVE_SNOC_THROTTLE_CFG 115
+#define QCS8300_SLAVE_TCSR 116
+#define QCS8300_SLAVE_TLMM 117
+#define QCS8300_SLAVE_TSC_CFG 118
+#define QCS8300_SLAVE_UFS_MEM_CFG 119
+#define QCS8300_SLAVE_USB2 120
+#define QCS8300_SLAVE_USB3_0 121
+#define QCS8300_SLAVE_VENUS_CFG 122
+#define QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG 123
+#define QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG 124
+#define QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG 125
+#define QCS8300_SLAVE_A1NOC_SNOC 126
+#define QCS8300_SLAVE_A2NOC_SNOC 127
+#define QCS8300_SLAVE_DDRSS_CFG 128
+#define QCS8300_SLAVE_GEM_NOC_CNOC 129
+#define QCS8300_SLAVE_GEM_NOC_CFG 130
+#define QCS8300_SLAVE_SNOC_GEM_NOC_GC 131
+#define QCS8300_SLAVE_SNOC_GEM_NOC_SF 132
+#define QCS8300_SLAVE_GP_DSP_SAIL_NOC 133
+#define QCS8300_SLAVE_GPDSP_NOC_CFG 134
+#define QCS8300_SLAVE_HCP_A 135
+#define QCS8300_SLAVE_LLCC 136
+#define QCS8300_SLAVE_MNOC_HF_MEM_NOC 137
+#define QCS8300_SLAVE_MNOC_SF_MEM_NOC 138
+#define QCS8300_SLAVE_CNOC_MNOC_HF_CFG 139
+#define QCS8300_SLAVE_CNOC_MNOC_SF_CFG 140
+#define QCS8300_SLAVE_CDSP_MEM_NOC 141
+#define QCS8300_SLAVE_GEM_NOC_PCIE_CNOC 142
+#define QCS8300_SLAVE_PCIE_ANOC_CFG 143
+#define QCS8300_SLAVE_ANOC_PCIE_GEM_NOC 144
+#define QCS8300_SLAVE_SNOC_CFG 145
+#define QCS8300_SLAVE_LPASS_SNOC 146
+#define QCS8300_SLAVE_QUP_CORE_0 147
+#define QCS8300_SLAVE_QUP_CORE_1 148
+#define QCS8300_SLAVE_QUP_CORE_3 149
+#define QCS8300_SLAVE_BOOT_IMEM 150
+#define QCS8300_SLAVE_IMEM 151
+#define QCS8300_SLAVE_PIMEM 152
+#define QCS8300_SLAVE_SERVICE_NSP_NOC 153
+#define QCS8300_SLAVE_SERVICE_GEM_NOC_1 154
+#define QCS8300_SLAVE_SERVICE_MNOC_HF 155
+#define QCS8300_SLAVE_SERVICE_MNOC_SF 156
+#define QCS8300_SLAVE_SERVICES_LPASS_AML_NOC 157
+#define QCS8300_SLAVE_SERVICE_LPASS_AG_NOC 158
+#define QCS8300_SLAVE_SERVICE_GEM_NOC_2 159
+#define QCS8300_SLAVE_SERVICE_SNOC 160
+#define QCS8300_SLAVE_SERVICE_GEM_NOC 161
+#define QCS8300_SLAVE_SERVICE_GEM_NOC2 162
+#define QCS8300_SLAVE_PCIE_0 163
+#define QCS8300_SLAVE_PCIE_1 164
+#define QCS8300_SLAVE_QDSS_STM 165
+#define QCS8300_SLAVE_TCU 166
+
+#endif
diff --git a/drivers/interconnect/qcom/qdu1000.c b/drivers/interconnect/qcom/qdu1000.c
index 9cb477d2bdfe..a7392eb73d4a 100644
--- a/drivers/interconnect/qcom/qdu1000.c
+++ b/drivers/interconnect/qcom/qdu1000.c
@@ -1046,7 +1046,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-qdu1000",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sa8775p.c b/drivers/interconnect/qcom/sa8775p.c
index a729775c2aa4..e2826af3ea2e 100644
--- a/drivers/interconnect/qcom/sa8775p.c
+++ b/drivers/interconnect/qcom/sa8775p.c
@@ -2519,7 +2519,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sa8775p",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sar2130p.c b/drivers/interconnect/qcom/sar2130p.c
new file mode 100644
index 000000000000..9eac0ac76812
--- /dev/null
+++ b/drivers/interconnect/qcom/sar2130p.c
@@ -0,0 +1,1930 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024, Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sort.h>
+#include <dt-bindings/interconnect/qcom,sar2130p-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-common.h"
+#include "icc-rpmh.h"
+
+enum {
+ SAR2130P_MASTER_QUP_CORE_0,
+ SAR2130P_MASTER_QUP_CORE_1,
+ SAR2130P_MASTER_GEM_NOC_CNOC,
+ SAR2130P_MASTER_GEM_NOC_PCIE_SNOC,
+ SAR2130P_MASTER_QDSS_DAP,
+ SAR2130P_MASTER_GPU_TCU,
+ SAR2130P_MASTER_SYS_TCU,
+ SAR2130P_MASTER_APPSS_PROC,
+ SAR2130P_MASTER_GFX3D,
+ SAR2130P_MASTER_MNOC_HF_MEM_NOC,
+ SAR2130P_MASTER_MNOC_SF_MEM_NOC,
+ SAR2130P_MASTER_COMPUTE_NOC,
+ SAR2130P_MASTER_ANOC_PCIE_GEM_NOC,
+ SAR2130P_MASTER_SNOC_GC_MEM_NOC,
+ SAR2130P_MASTER_SNOC_SF_MEM_NOC,
+ SAR2130P_MASTER_WLAN_Q6,
+ SAR2130P_MASTER_CNOC_LPASS_AG_NOC,
+ SAR2130P_MASTER_LPASS_PROC,
+ SAR2130P_MASTER_LLCC,
+ SAR2130P_MASTER_CAMNOC_HF,
+ SAR2130P_MASTER_CAMNOC_ICP,
+ SAR2130P_MASTER_CAMNOC_SF,
+ SAR2130P_MASTER_LSR,
+ SAR2130P_MASTER_MDP,
+ SAR2130P_MASTER_CNOC_MNOC_CFG,
+ SAR2130P_MASTER_VIDEO,
+ SAR2130P_MASTER_VIDEO_CV_PROC,
+ SAR2130P_MASTER_VIDEO_PROC,
+ SAR2130P_MASTER_VIDEO_V_PROC,
+ SAR2130P_MASTER_CDSP_NOC_CFG,
+ SAR2130P_MASTER_CDSP_PROC,
+ SAR2130P_MASTER_PCIE_0,
+ SAR2130P_MASTER_PCIE_1,
+ SAR2130P_MASTER_GIC_AHB,
+ SAR2130P_MASTER_QDSS_BAM,
+ SAR2130P_MASTER_QSPI_0,
+ SAR2130P_MASTER_QUP_0,
+ SAR2130P_MASTER_QUP_1,
+ SAR2130P_MASTER_A2NOC_SNOC,
+ SAR2130P_MASTER_CNOC_DATAPATH,
+ SAR2130P_MASTER_LPASS_ANOC,
+ SAR2130P_MASTER_SNOC_CFG,
+ SAR2130P_MASTER_CRYPTO,
+ SAR2130P_MASTER_PIMEM,
+ SAR2130P_MASTER_GIC,
+ SAR2130P_MASTER_QDSS_ETR,
+ SAR2130P_MASTER_QDSS_ETR_1,
+ SAR2130P_MASTER_SDCC_1,
+ SAR2130P_MASTER_USB3_0,
+ SAR2130P_SLAVE_QUP_CORE_0,
+ SAR2130P_SLAVE_QUP_CORE_1,
+ SAR2130P_SLAVE_AHB2PHY_SOUTH,
+ SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG,
+ SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG,
+ SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG,
+ SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG,
+ SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG,
+ SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG,
+ SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG,
+ SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS,
+ SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG,
+ SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM,
+ SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG,
+ SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0,
+ SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1,
+ SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR,
+ SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG,
+ SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG,
+ SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG,
+ SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG,
+ SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM,
+ SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC,
+ SAR2130P_SLAVE_PCIE_0,
+ SAR2130P_SLAVE_PCIE_1,
+ SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU,
+ SAR2130P_SLAVE_GEM_NOC_CNOC,
+ SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC,
+ SAR2130P_SLAVE_LPASS_CORE_CFG,
+ SAR2130P_SLAVE_LPASS_LPI_CFG,
+ SAR2130P_SLAVE_LPASS_MPU_CFG,
+ SAR2130P_SLAVE_LPASS_TOP_CFG,
+ SAR2130P_SLAVE_LPASS_SNOC,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC,
+ SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC,
+ SAR2130P_SLAVE_EBI1,
+ SAR2130P_SLAVE_MNOC_HF_MEM_NOC,
+ SAR2130P_SLAVE_MNOC_SF_MEM_NOC,
+ SAR2130P_SLAVE_SERVICE_MNOC,
+ SAR2130P_SLAVE_CDSP_MEM_NOC,
+ SAR2130P_SLAVE_SERVICE_NSP_NOC,
+ SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC,
+ SAR2130P_SLAVE_A2NOC_SNOC,
+ SAR2130P_SLAVE_SNOC_GEM_NOC_GC,
+ SAR2130P_SLAVE_SNOC_GEM_NOC_SF,
+ SAR2130P_SLAVE_SERVICE_SNOC,
+};
+
+static const struct regmap_config icc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+};
+
+static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = SAR2130P_MASTER_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_QUP_CORE_0 },
+};
+
+static struct qcom_icc_node qup1_core_master = {
+ .name = "qup1_core_master",
+ .id = SAR2130P_MASTER_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_QUP_CORE_1 },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cnoc = {
+ .name = "qnm_gemnoc_cnoc",
+ .id = SAR2130P_MASTER_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 43,
+ .links = { SAR2130P_SLAVE_AHB2PHY_SOUTH, SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG, SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG, SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG, SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG, SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG, SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG, SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG, SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS, SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG, SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM, SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG, SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0, SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1, SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR, SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG, SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG, SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG, SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG, SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM, SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC, SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = SAR2130P_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_PCIE_0, SAR2130P_SLAVE_PCIE_1 },
+};
+
+static struct qcom_icc_node xm_qdss_dap = {
+ .name = "xm_qdss_dap",
+ .id = SAR2130P_MASTER_QDSS_DAP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 43,
+ .links = { SAR2130P_SLAVE_AHB2PHY_SOUTH, SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG, SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG, SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG, SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG, SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG, SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG, SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG, SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS, SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG, SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM, SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG, SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0, SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1, SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR, SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG, SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG, SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG, SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG, SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM, SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC, SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU },
+};
+
+static const struct qcom_icc_qosbox alm_gpu_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9e000 },
+ .prio = 1,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_gpu_tcu = {
+ .name = "alm_gpu_tcu",
+ .id = SAR2130P_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_gpu_tcu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox alm_sys_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9f000 },
+ .prio = 6,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_sys_tcu = {
+ .name = "alm_sys_tcu",
+ .id = SAR2130P_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_sys_tcu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node chm_apps = {
+ .name = "chm_apps",
+ .id = SAR2130P_MASTER_APPSS_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_gpu_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0xe000, 0x4e000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = SAR2130P_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_gpu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_mnoc_hf_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0xf000, 0x4f000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = SAR2130P_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_hf_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_mnoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9d000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = SAR2130P_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_sf_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_nsp_gemnoc_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x10000, 0x50000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_nsp_gemnoc = {
+ .name = "qnm_nsp_gemnoc",
+ .id = SAR2130P_MASTER_COMPUTE_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_nsp_gemnoc_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_pcie_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa2000 },
+ .prio = 2,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_pcie = {
+ .name = "qnm_pcie",
+ .id = SAR2130P_MASTER_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_pcie_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_snoc_gc_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa0000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = SAR2130P_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_snoc_gc_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_snoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa1000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = SAR2130P_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_snoc_sf_qos,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qxm_wlan_q6 = {
+ .name = "qxm_wlan_q6",
+ .id = SAR2130P_MASTER_WLAN_Q6,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qhm_config_noc = {
+ .name = "qhm_config_noc",
+ .id = SAR2130P_MASTER_CNOC_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 6,
+ .links = { SAR2130P_SLAVE_LPASS_CORE_CFG, SAR2130P_SLAVE_LPASS_LPI_CFG,
+ SAR2130P_SLAVE_LPASS_MPU_CFG, SAR2130P_SLAVE_LPASS_TOP_CFG,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC, SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qxm_lpass_dsp = {
+ .name = "qxm_lpass_dsp",
+ .id = SAR2130P_MASTER_LPASS_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 4,
+ .links = { SAR2130P_SLAVE_LPASS_TOP_CFG, SAR2130P_SLAVE_LPASS_SNOC,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC, SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = SAR2130P_MASTER_LLCC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_EBI1 },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_hf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_hf = {
+ .name = "qnm_camnoc_hf",
+ .id = SAR2130P_MASTER_CAMNOC_HF,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_camnoc_hf_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_icp_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c080 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_icp = {
+ .name = "qnm_camnoc_icp",
+ .id = SAR2130P_MASTER_CAMNOC_ICP,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_camnoc_icp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c100 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_sf = {
+ .name = "qnm_camnoc_sf",
+ .id = SAR2130P_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_camnoc_sf_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_lsr_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1f000, 0x1f080 },
+ .prio = 3,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_lsr = {
+ .name = "qnm_lsr",
+ .id = SAR2130P_MASTER_LSR,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_lsr_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_mdp_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1d000, 0x1d080 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mdp = {
+ .name = "qnm_mdp",
+ .id = SAR2130P_MASTER_MDP,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mdp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_cfg = {
+ .name = "qnm_mnoc_cfg",
+ .id = SAR2130P_MASTER_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_MNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1e000, 0x1e080 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video = {
+ .name = "qnm_video",
+ .id = SAR2130P_MASTER_VIDEO,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_video_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_cv_cpu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e100 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_cv_cpu = {
+ .name = "qnm_video_cv_cpu",
+ .id = SAR2130P_MASTER_VIDEO_CV_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_video_cv_cpu_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_cvp_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e180 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_cvp = {
+ .name = "qnm_video_cvp",
+ .id = SAR2130P_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_video_cvp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_v_cpu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e200 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_v_cpu = {
+ .name = "qnm_video_v_cpu",
+ .id = SAR2130P_MASTER_VIDEO_V_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_video_v_cpu_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_nsp_noc_config = {
+ .name = "qhm_nsp_noc_config",
+ .id = SAR2130P_MASTER_CDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_NSP_NOC },
+};
+
+static struct qcom_icc_node qxm_nsp = {
+ .name = "qxm_nsp",
+ .id = SAR2130P_MASTER_CDSP_PROC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_CDSP_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox xm_pcie3_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9000 },
+ .prio = 3,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_pcie3_0 = {
+ .name = "xm_pcie3_0",
+ .id = SAR2130P_MASTER_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_pcie3_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static const struct qcom_icc_qosbox xm_pcie3_1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_pcie3_1 = {
+ .name = "xm_pcie3_1",
+ .id = SAR2130P_MASTER_PCIE_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_pcie3_1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qhm_gic_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1d000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_gic = {
+ .name = "qhm_gic",
+ .id = SAR2130P_MASTER_GIC_AHB,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_gic_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static const struct qcom_icc_qosbox qhm_qdss_bam_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x22000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = SAR2130P_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qdss_bam_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qspi_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x23000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qspi = {
+ .name = "qhm_qspi",
+ .id = SAR2130P_MASTER_QSPI_0,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qspi_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qup0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x24000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = SAR2130P_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qup0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qup1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x25000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = SAR2130P_MASTER_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qup1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_aggre2_noc = {
+ .name = "qnm_aggre2_noc",
+ .id = SAR2130P_MASTER_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static const struct qcom_icc_qosbox qnm_cnoc_datapath_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x26000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_cnoc_datapath = {
+ .name = "qnm_cnoc_datapath",
+ .id = SAR2130P_MASTER_CNOC_DATAPATH,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_cnoc_datapath_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_lpass_noc_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_lpass_noc = {
+ .name = "qnm_lpass_noc",
+ .id = SAR2130P_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_lpass_noc_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_snoc_cfg = {
+ .name = "qnm_snoc_cfg",
+ .id = SAR2130P_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_SNOC },
+};
+
+static const struct qcom_icc_qosbox qxm_crypto_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x27000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qxm_crypto = {
+ .name = "qxm_crypto",
+ .id = SAR2130P_MASTER_CRYPTO,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qxm_crypto_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qxm_pimem_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1f000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = SAR2130P_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qxm_pimem_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static const struct qcom_icc_qosbox xm_gic_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x21000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = SAR2130P_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_gic_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static const struct qcom_icc_qosbox xm_qdss_etr_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1b000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_qdss_etr_0 = {
+ .name = "xm_qdss_etr_0",
+ .id = SAR2130P_MASTER_QDSS_ETR,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_qdss_etr_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_qdss_etr_1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_qdss_etr_1 = {
+ .name = "xm_qdss_etr_1",
+ .id = SAR2130P_MASTER_QDSS_ETR_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_qdss_etr_1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_sdc1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x29000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = SAR2130P_MASTER_SDCC_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_sdc1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_usb3_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x28000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = SAR2130P_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_usb3_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = SAR2130P_SLAVE_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup1_core_slave = {
+ .name = "qup1_core_slave",
+ .id = SAR2130P_SLAVE_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy0 = {
+ .name = "qhs_ahb2phy0",
+ .id = SAR2130P_SLAVE_AHB2PHY_SOUTH,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = SAR2130P_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = SAR2130P_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = SAR2130P_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_compute_cfg = {
+ .name = "qhs_compute_cfg",
+ .id = SAR2130P_SLAVE_CDSP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CDSP_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = SAR2130P_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mmcx = {
+ .name = "qhs_cpr_mmcx",
+ .id = SAR2130P_SLAVE_RBCPR_MMCX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mxa = {
+ .name = "qhs_cpr_mxa",
+ .id = SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mxc = {
+ .name = "qhs_cpr_mxc",
+ .id = SAR2130P_SLAVE_RBCPR_MXC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nspcx = {
+ .name = "qhs_cpr_nspcx",
+ .id = SAR2130P_SLAVE_CPR_NSPCX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = SAR2130P_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cx_rdpm = {
+ .name = "qhs_cx_rdpm",
+ .id = SAR2130P_SLAVE_CX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display_cfg = {
+ .name = "qhs_display_cfg",
+ .id = SAR2130P_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = SAR2130P_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = SAR2130P_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipc_router = {
+ .name = "qhs_ipc_router",
+ .id = SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_cfg = {
+ .name = "qhs_lpass_cfg",
+ .id = SAR2130P_SLAVE_LPASS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CNOC_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qhs_mx_rdpm = {
+ .name = "qhs_mx_rdpm",
+ .id = SAR2130P_SLAVE_MX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie0_cfg = {
+ .name = "qhs_pcie0_cfg",
+ .id = SAR2130P_SLAVE_PCIE_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie1_cfg = {
+ .name = "qhs_pcie1_cfg",
+ .id = SAR2130P_SLAVE_PCIE_1_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pdm = {
+ .name = "qhs_pdm",
+ .id = SAR2130P_SLAVE_PDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = SAR2130P_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_prng = {
+ .name = "qhs_prng",
+ .id = SAR2130P_SLAVE_PRNG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = SAR2130P_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qspi = {
+ .name = "qhs_qspi",
+ .id = SAR2130P_SLAVE_QSPI_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = SAR2130P_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = SAR2130P_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = SAR2130P_SLAVE_SDCC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = SAR2130P_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .id = SAR2130P_SLAVE_TLMM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tme_cfg = {
+ .name = "qhs_tme_cfg",
+ .id = SAR2130P_SLAVE_TME_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3_0 = {
+ .name = "qhs_usb3_0",
+ .id = SAR2130P_SLAVE_USB3_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = SAR2130P_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .id = SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_wlan_q6 = {
+ .name = "qhs_wlan_q6",
+ .id = SAR2130P_SLAVE_WLAN_Q6_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_ddrss_cfg = {
+ .name = "qns_ddrss_cfg",
+ .id = SAR2130P_SLAVE_DDRSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mnoc_cfg = {
+ .name = "qns_mnoc_cfg",
+ .id = SAR2130P_SLAVE_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CNOC_MNOC_CFG },
+};
+
+static struct qcom_icc_node qns_snoc_cfg = {
+ .name = "qns_snoc_cfg",
+ .id = SAR2130P_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = SAR2130P_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = SAR2130P_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_cnoc = {
+ .name = "srvc_cnoc",
+ .id = SAR2130P_SLAVE_SERVICE_CNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_0 = {
+ .name = "xs_pcie_0",
+ .id = SAR2130P_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_1 = {
+ .name = "xs_pcie_1",
+ .id = SAR2130P_SLAVE_PCIE_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = SAR2130P_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = SAR2130P_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gem_noc_cnoc = {
+ .name = "qns_gem_noc_cnoc",
+ .id = SAR2130P_SLAVE_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_GEM_NOC_CNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = SAR2130P_SLAVE_LLCC,
+ .channels = 2,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_pcie = {
+ .name = "qns_pcie",
+ .id = SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qhs_lpass_core = {
+ .name = "qhs_lpass_core",
+ .id = SAR2130P_SLAVE_LPASS_CORE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_lpi = {
+ .name = "qhs_lpass_lpi",
+ .id = SAR2130P_SLAVE_LPASS_LPI_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_mpu = {
+ .name = "qhs_lpass_mpu",
+ .id = SAR2130P_SLAVE_LPASS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_top = {
+ .name = "qhs_lpass_top",
+ .id = SAR2130P_SLAVE_LPASS_TOP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_sysnoc = {
+ .name = "qns_sysnoc",
+ .id = SAR2130P_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node srvc_niu_aml_noc = {
+ .name = "srvc_niu_aml_noc",
+ .id = SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_niu_lpass_agnoc = {
+ .name = "srvc_niu_lpass_agnoc",
+ .id = SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = SAR2130P_SLAVE_EBI1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = SAR2130P_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_sf = {
+ .name = "qns_mem_noc_sf",
+ .id = SAR2130P_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc = {
+ .name = "srvc_mnoc",
+ .id = SAR2130P_SLAVE_SERVICE_MNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_nsp_gemnoc = {
+ .name = "qns_nsp_gemnoc",
+ .id = SAR2130P_SLAVE_CDSP_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_COMPUTE_NOC },
+};
+
+static struct qcom_icc_node service_nsp_noc = {
+ .name = "service_nsp_noc",
+ .id = SAR2130P_SLAVE_SERVICE_NSP_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_pcie_mem_noc = {
+ .name = "qns_pcie_mem_noc",
+ .id = SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qns_a2noc_snoc = {
+ .name = "qns_a2noc_snoc",
+ .id = SAR2130P_SLAVE_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_gc = {
+ .name = "qns_gemnoc_gc",
+ .id = SAR2130P_SLAVE_SNOC_GEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = SAR2130P_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = SAR2130P_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .enable_mask = BIT(3),
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+ .nodes = { &qxm_crypto },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .enable_mask = BIT(0),
+ .keepalive = true,
+ .num_nodes = 48,
+ .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie,
+ &xm_qdss_dap, &qhs_ahb2phy0,
+ &qhs_aoss, &qhs_camera_cfg,
+ &qhs_clk_ctl, &qhs_compute_cfg,
+ &qhs_cpr_cx, &qhs_cpr_mmcx,
+ &qhs_cpr_mxa, &qhs_cpr_mxc,
+ &qhs_cpr_nspcx, &qhs_crypto0_cfg,
+ &qhs_cx_rdpm, &qhs_display_cfg,
+ &qhs_gpuss_cfg, &qhs_imem_cfg,
+ &qhs_ipc_router, &qhs_lpass_cfg,
+ &qhs_mx_rdpm, &qhs_pcie0_cfg,
+ &qhs_pcie1_cfg, &qhs_pdm,
+ &qhs_pimem_cfg, &qhs_prng,
+ &qhs_qdss_cfg, &qhs_qspi,
+ &qhs_qup0, &qhs_qup1,
+ &qhs_sdc1, &qhs_tcsr,
+ &qhs_tlmm, &qhs_tme_cfg,
+ &qhs_usb3_0, &qhs_venus_cfg,
+ &qhs_vsense_ctrl_cfg, &qhs_wlan_q6,
+ &qns_ddrss_cfg, &qns_mnoc_cfg,
+ &qns_snoc_cfg, &qxs_imem,
+ &qxs_pimem, &srvc_cnoc,
+ &xs_pcie_0, &xs_pcie_1,
+ &xs_qdss_stm, &xs_sys_tcu_cfg },
+};
+
+static struct qcom_icc_bcm bcm_co0 = {
+ .name = "CO0",
+ .enable_mask = BIT(0),
+ .num_nodes = 2,
+ .nodes = { &qxm_nsp, &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .enable_mask = BIT(0),
+ .num_nodes = 11,
+ .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
+ &qnm_camnoc_sf, &qnm_lsr,
+ &qnm_mdp, &qnm_mnoc_cfg,
+ &qnm_video, &qnm_video_cv_cpu,
+ &qnm_video_cvp, &qnm_video_v_cpu,
+ &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 1,
+ .nodes = { &qup0_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup1 = {
+ .name = "QUP1",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 1,
+ .nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh1 = {
+ .name = "SH1",
+ .enable_mask = BIT(0),
+ .num_nodes = 13,
+ .nodes = { &alm_gpu_tcu, &alm_sys_tcu,
+ &chm_apps, &qnm_gpu,
+ &qnm_mnoc_hf, &qnm_mnoc_sf,
+ &qnm_nsp_gemnoc, &qnm_pcie,
+ &qnm_snoc_gc, &qnm_snoc_sf,
+ &qxm_wlan_q6, &qns_gem_noc_cnoc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .enable_mask = BIT(0),
+ .num_nodes = 4,
+ .nodes = { &qhm_gic, &qxm_pimem,
+ &xm_gic, &qns_gemnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 1,
+ .nodes = { &qnm_lpass_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn7 = {
+ .name = "SN7",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+ &bcm_qup0,
+ &bcm_qup1,
+};
+
+static struct qcom_icc_node * const clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+};
+
+static const struct qcom_icc_desc sar2130p_clk_virt = {
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .bcms = clk_virt_bcms,
+ .num_bcms = ARRAY_SIZE(clk_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [MASTER_QDSS_DAP] = &xm_qdss_dap,
+ [SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &qhs_compute_cfg,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MMCX_CFG] = &qhs_cpr_mmcx,
+ [SLAVE_RBCPR_MXA_CFG] = &qhs_cpr_mxa,
+ [SLAVE_RBCPR_MXC_CFG] = &qhs_cpr_mxc,
+ [SLAVE_CPR_NSPCX] = &qhs_cpr_nspcx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CX_RDPM] = &qhs_cx_rdpm,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router,
+ [SLAVE_LPASS] = &qhs_lpass_cfg,
+ [SLAVE_MX_RDPM] = &qhs_mx_rdpm,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &qhs_pcie1_cfg,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QSPI_0] = &qhs_qspi,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_SDCC_1] = &qhs_sdc1,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_TME_CFG] = &qhs_tme_cfg,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_WLAN_Q6_CFG] = &qhs_wlan_q6,
+ [SLAVE_DDRSS_CFG] = &qns_ddrss_cfg,
+ [SLAVE_CNOC_MNOC_CFG] = &qns_mnoc_cfg,
+ [SLAVE_SNOC_CFG] = &qns_snoc_cfg,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+ [SLAVE_PCIE_0] = &xs_pcie_0,
+ [SLAVE_PCIE_1] = &xs_pcie_1,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc sar2130p_config_noc = {
+ .config = &icc_regmap_config,
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh1,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_GPU_TCU] = &alm_gpu_tcu,
+ [MASTER_SYS_TCU] = &alm_sys_tcu,
+ [MASTER_APPSS_PROC] = &chm_apps,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_COMPUTE_NOC] = &qnm_nsp_gemnoc,
+ [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [MASTER_WLAN_Q6] = &qxm_wlan_q6,
+ [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie,
+};
+
+static const struct qcom_icc_desc sar2130p_gem_noc = {
+ .config = &icc_regmap_config,
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const lpass_ag_noc_bcms[] = {
+};
+
+static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
+ [MASTER_CNOC_LPASS_AG_NOC] = &qhm_config_noc,
+ [MASTER_LPASS_PROC] = &qxm_lpass_dsp,
+ [SLAVE_LPASS_CORE_CFG] = &qhs_lpass_core,
+ [SLAVE_LPASS_LPI_CFG] = &qhs_lpass_lpi,
+ [SLAVE_LPASS_MPU_CFG] = &qhs_lpass_mpu,
+ [SLAVE_LPASS_TOP_CFG] = &qhs_lpass_top,
+ [SLAVE_LPASS_SNOC] = &qns_sysnoc,
+ [SLAVE_SERVICES_LPASS_AML_NOC] = &srvc_niu_aml_noc,
+ [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc,
+};
+
+static const struct qcom_icc_desc sar2130p_lpass_ag_noc = {
+ .config = &icc_regmap_config,
+ .nodes = lpass_ag_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
+ .bcms = lpass_ag_noc_bcms,
+ .num_bcms = ARRAY_SIZE(lpass_ag_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc sar2130p_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CAMNOC_HF] = &qnm_camnoc_hf,
+ [MASTER_CAMNOC_ICP] = &qnm_camnoc_icp,
+ [MASTER_CAMNOC_SF] = &qnm_camnoc_sf,
+ [MASTER_LSR] = &qnm_lsr,
+ [MASTER_MDP] = &qnm_mdp,
+ [MASTER_CNOC_MNOC_CFG] = &qnm_mnoc_cfg,
+ [MASTER_VIDEO] = &qnm_video,
+ [MASTER_VIDEO_CV_PROC] = &qnm_video_cv_cpu,
+ [MASTER_VIDEO_PROC] = &qnm_video_cvp,
+ [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf,
+ [SLAVE_SERVICE_MNOC] = &srvc_mnoc,
+};
+
+static const struct qcom_icc_desc sar2130p_mmss_noc = {
+ .config = &icc_regmap_config,
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const nsp_noc_bcms[] = {
+ &bcm_co0,
+};
+
+static struct qcom_icc_node * const nsp_noc_nodes[] = {
+ [MASTER_CDSP_NOC_CFG] = &qhm_nsp_noc_config,
+ [MASTER_CDSP_PROC] = &qxm_nsp,
+ [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc,
+ [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc,
+};
+
+static const struct qcom_icc_desc sar2130p_nsp_noc = {
+ .config = &icc_regmap_config,
+ .nodes = nsp_noc_nodes,
+ .num_nodes = ARRAY_SIZE(nsp_noc_nodes),
+ .bcms = nsp_noc_bcms,
+ .num_bcms = ARRAY_SIZE(nsp_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const pcie_anoc_bcms[] = {
+ &bcm_sn7,
+};
+
+static struct qcom_icc_node * const pcie_anoc_nodes[] = {
+ [MASTER_PCIE_0] = &xm_pcie3_0,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
+};
+
+static const struct qcom_icc_desc sar2130p_pcie_anoc = {
+ .config = &icc_regmap_config,
+ .nodes = pcie_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
+ .bcms = pcie_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(pcie_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn3,
+ &bcm_sn4,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_GIC_AHB] = &qhm_gic,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QSPI_0] = &qhm_qspi,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_QUP_1] = &qhm_qup1,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_CNOC_DATAPATH] = &qnm_cnoc_datapath,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_noc,
+ [MASTER_SNOC_CFG] = &qnm_snoc_cfg,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr_0,
+ [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+ [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+};
+
+static const struct qcom_icc_desc sar2130p_system_noc = {
+ .config = &icc_regmap_config,
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,sar2130p-clk-virt", .data = &sar2130p_clk_virt},
+ { .compatible = "qcom,sar2130p-config-noc", .data = &sar2130p_config_noc},
+ { .compatible = "qcom,sar2130p-gem-noc", .data = &sar2130p_gem_noc},
+ { .compatible = "qcom,sar2130p-lpass-ag-noc", .data = &sar2130p_lpass_ag_noc},
+ { .compatible = "qcom,sar2130p-mc-virt", .data = &sar2130p_mc_virt},
+ { .compatible = "qcom,sar2130p-mmss-noc", .data = &sar2130p_mmss_noc},
+ { .compatible = "qcom,sar2130p-nsp-noc", .data = &sar2130p_nsp_noc},
+ { .compatible = "qcom,sar2130p-pcie-anoc", .data = &sar2130p_pcie_anoc},
+ { .compatible = "qcom,sar2130p-system-noc", .data = &sar2130p_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-sar2130p",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+
+module_exit(qnoc_driver_exit);
+MODULE_DESCRIPTION("Qualcomm SAR2130P NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/sc7180.c b/drivers/interconnect/qcom/sc7180.c
index 34a1d163d6e1..af2be1543840 100644
--- a/drivers/interconnect/qcom/sc7180.c
+++ b/drivers/interconnect/qcom/sc7180.c
@@ -1807,7 +1807,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7180",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c
index 167971f8e8be..346f18d70e9e 100644
--- a/drivers/interconnect/qcom/sc7280.c
+++ b/drivers/interconnect/qcom/sc7280.c
@@ -1691,7 +1691,7 @@ static const struct qcom_icc_desc sc7280_aggre1_noc = {
.num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
.bcms = aggre1_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
- .qos_clks_required = true,
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
@@ -1723,7 +1723,7 @@ static const struct qcom_icc_desc sc7280_aggre2_noc = {
.num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
.bcms = aggre2_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
- .qos_clks_required = true,
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const clk_virt_bcms[] = {
@@ -2111,7 +2111,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7280",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc8180x.c b/drivers/interconnect/qcom/sc8180x.c
index 03d626776ba1..a741badaa966 100644
--- a/drivers/interconnect/qcom/sc8180x.c
+++ b/drivers/interconnect/qcom/sc8180x.c
@@ -1889,7 +1889,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc8180x",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc8280xp.c b/drivers/interconnect/qcom/sc8280xp.c
index 7acd152bf0dd..0270f6c64481 100644
--- a/drivers/interconnect/qcom/sc8280xp.c
+++ b/drivers/interconnect/qcom/sc8280xp.c
@@ -2391,7 +2391,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc8280xp",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index ab91de446da8..7392bebba334 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -1714,7 +1714,7 @@ MODULE_DEVICE_TABLE(of, sdm660_noc_of_match);
static struct platform_driver sdm660_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-sdm660",
.of_match_table = sdm660_noc_of_match,
diff --git a/drivers/interconnect/qcom/sdm670.c b/drivers/interconnect/qcom/sdm670.c
index e5ee7fbaa641..907e1ff4ff81 100644
--- a/drivers/interconnect/qcom/sdm670.c
+++ b/drivers/interconnect/qcom/sdm670.c
@@ -1533,7 +1533,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdm670",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index 584800ac871a..855802be93fe 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -1802,7 +1802,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdm845",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx55.c b/drivers/interconnect/qcom/sdx55.c
index e97f28b8d2b2..4117db046fa0 100644
--- a/drivers/interconnect/qcom/sdx55.c
+++ b/drivers/interconnect/qcom/sdx55.c
@@ -913,7 +913,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx55",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx65.c b/drivers/interconnect/qcom/sdx65.c
index 2f3f5479d8a5..d3a6c6c148e5 100644
--- a/drivers/interconnect/qcom/sdx65.c
+++ b/drivers/interconnect/qcom/sdx65.c
@@ -897,7 +897,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx65",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx75.c b/drivers/interconnect/qcom/sdx75.c
index 7f422c27488d..7ef1f17f3292 100644
--- a/drivers/interconnect/qcom/sdx75.c
+++ b/drivers/interconnect/qcom/sdx75.c
@@ -1083,7 +1083,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx75",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm6115.c b/drivers/interconnect/qcom/sm6115.c
index 271b07c74862..3ee12c8a4d56 100644
--- a/drivers/interconnect/qcom/sm6115.c
+++ b/drivers/interconnect/qcom/sm6115.c
@@ -1402,7 +1402,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-sm6115",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm6350.c b/drivers/interconnect/qcom/sm6350.c
index 20923e8e6110..f41d7e19ba26 100644
--- a/drivers/interconnect/qcom/sm6350.c
+++ b/drivers/interconnect/qcom/sm6350.c
@@ -1702,7 +1702,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm6350",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm7150.c b/drivers/interconnect/qcom/sm7150.c
index dc0d1343f510..c8c77407cd50 100644
--- a/drivers/interconnect/qcom/sm7150.c
+++ b/drivers/interconnect/qcom/sm7150.c
@@ -1730,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm7150",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8150.c b/drivers/interconnect/qcom/sm8150.c
index f29b77556a79..edfe824cad35 100644
--- a/drivers/interconnect/qcom/sm8150.c
+++ b/drivers/interconnect/qcom/sm8150.c
@@ -1864,7 +1864,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8150",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8250.c b/drivers/interconnect/qcom/sm8250.c
index 1879fa15761f..cc1b14c13529 100644
--- a/drivers/interconnect/qcom/sm8250.c
+++ b/drivers/interconnect/qcom/sm8250.c
@@ -1991,7 +1991,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8250",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8350.c b/drivers/interconnect/qcom/sm8350.c
index 4236a43dc256..38105ead4f29 100644
--- a/drivers/interconnect/qcom/sm8350.c
+++ b/drivers/interconnect/qcom/sm8350.c
@@ -1807,7 +1807,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8350",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8450.c b/drivers/interconnect/qcom/sm8450.c
index b3cd0087377c..eb7e17df32ba 100644
--- a/drivers/interconnect/qcom/sm8450.c
+++ b/drivers/interconnect/qcom/sm8450.c
@@ -1884,7 +1884,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8450",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8550.c b/drivers/interconnect/qcom/sm8550.c
index 4d0e6fa9e003..fdb97d1f1d07 100644
--- a/drivers/interconnect/qcom/sm8550.c
+++ b/drivers/interconnect/qcom/sm8550.c
@@ -1645,7 +1645,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8550",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8650.c b/drivers/interconnect/qcom/sm8650.c
index b962e6c233ef..20ac5bc5e1fb 100644
--- a/drivers/interconnect/qcom/sm8650.c
+++ b/drivers/interconnect/qcom/sm8650.c
@@ -1650,7 +1650,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8650",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/smd-rpm.c b/drivers/interconnect/qcom/smd-rpm.c
index 3816bfb4e2f3..8316c87a2c60 100644
--- a/drivers/interconnect/qcom/smd-rpm.c
+++ b/drivers/interconnect/qcom/smd-rpm.c
@@ -85,7 +85,7 @@ static struct platform_driver qcom_interconnect_rpm_smd_driver = {
.name = "icc_smd_rpm",
},
.probe = qcom_icc_rpm_smd_probe,
- .remove_new = qcom_icc_rpm_smd_remove,
+ .remove = qcom_icc_rpm_smd_remove,
};
module_platform_driver(qcom_interconnect_rpm_smd_driver);
MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>");
diff --git a/drivers/interconnect/qcom/x1e80100.c b/drivers/interconnect/qcom/x1e80100.c
index 654abb9ce08e..2c46fdb4a054 100644
--- a/drivers/interconnect/qcom/x1e80100.c
+++ b/drivers/interconnect/qcom/x1e80100.c
@@ -1964,7 +1964,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-x1e80100",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/samsung/exynos.c b/drivers/interconnect/samsung/exynos.c
index c9e5361e17c5..9e041365d909 100644
--- a/drivers/interconnect/samsung/exynos.c
+++ b/drivers/interconnect/samsung/exynos.c
@@ -180,7 +180,7 @@ static struct platform_driver exynos_generic_icc_driver = {
.sync_state = icc_sync_state,
},
.probe = exynos_generic_icc_probe,
- .remove_new = exynos_generic_icc_remove,
+ .remove = exynos_generic_icc_remove,
};
module_platform_driver(exynos_generic_icc_driver);
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index b3aa1f5d5321..47c46e4b739e 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -195,6 +195,7 @@ config MSM_IOMMU
source "drivers/iommu/amd/Kconfig"
source "drivers/iommu/intel/Kconfig"
source "drivers/iommu/iommufd/Kconfig"
+source "drivers/iommu/riscv/Kconfig"
config IRQ_REMAP
bool "Support for Interrupt Remapping"
@@ -415,6 +416,15 @@ config ARM_SMMU_V3_SVA
Say Y here if your system supports SVA extensions such as PCIe PASID
and PRI.
+config ARM_SMMU_V3_IOMMUFD
+ bool "Enable IOMMUFD features for ARM SMMUv3 (EXPERIMENTAL)"
+ depends on IOMMUFD
+ help
+ Support for IOMMUFD features intended to support virtual machines
+ with accelerated virtual IOMMUs.
+
+ Say Y here if you are doing development and testing on this feature.
+
config ARM_SMMU_V3_KUNIT_TEST
tristate "KUnit tests for arm-smmu-v3 driver" if !KUNIT_ALL_TESTS
depends on KUNIT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 542760d963ec..5e5a83c6c2aa 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y += amd/ intel/ arm/ iommufd/
+obj-y += amd/ intel/ arm/ iommufd/ riscv/
obj-$(CONFIG_IOMMU_API) += iommu.o
obj-$(CONFIG_IOMMU_API) += iommu-traces.o
obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 6386fa4556d9..1bef5d55b2f9 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -46,13 +46,15 @@ extern int amd_iommu_gpt_level;
extern unsigned long amd_iommu_pgsize_bitmap;
/* Protection domain ops */
+void amd_iommu_init_identity_domain(void);
struct protection_domain *protection_domain_alloc(unsigned int type, int nid);
void protection_domain_free(struct protection_domain *domain);
struct iommu_domain *amd_iommu_domain_alloc_sva(struct device *dev,
struct mm_struct *mm);
void amd_iommu_domain_free(struct iommu_domain *dom);
int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
- struct device *dev, ioasid_t pasid);
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old);
void amd_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
struct iommu_domain *domain);
@@ -118,9 +120,14 @@ static inline bool check_feature2(u64 mask)
return (amd_iommu_efr2 & mask);
}
+static inline bool amd_iommu_v2_pgtbl_supported(void)
+{
+ return (check_feature(FEATURE_GIOSUP) && check_feature(FEATURE_GT));
+}
+
static inline bool amd_iommu_gt_ppr_supported(void)
{
- return (check_feature(FEATURE_GT) &&
+ return (amd_iommu_v2_pgtbl_supported() &&
check_feature(FEATURE_PPR) &&
check_feature(FEATURE_EPHSUP));
}
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 601fb4ee6900..fdb0357e0bb9 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -565,6 +565,12 @@ struct pdom_dev_data {
struct list_head list;
};
+/* Keeps track of the IOMMUs attached to protection domain */
+struct pdom_iommu_info {
+ struct amd_iommu *iommu; /* IOMMUs attach to protection domain */
+ u32 refcnt; /* Count of attached dev/pasid per domain/IOMMU */
+};
+
/*
* This structure contains generic data for IOMMU protection domains
* independent of their use.
@@ -578,8 +584,7 @@ struct protection_domain {
u16 id; /* the domain id written to the device table */
enum protection_domain_mode pd_mode; /* Track page table type */
bool dirty_tracking; /* dirty tracking is enabled in the domain */
- unsigned dev_cnt; /* devices assigned to this domain */
- unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
+ struct xarray iommu_array; /* per-IOMMU reference count */
struct mmu_notifier mn; /* mmu notifier for the SVA domain */
struct list_head dev_data_list; /* List of pdom_dev_data */
@@ -831,7 +836,7 @@ struct devid_map {
*/
struct iommu_dev_data {
/*Protect against attach/detach races */
- spinlock_t lock;
+ struct mutex mutex;
struct list_head list; /* For domain->dev_list */
struct llist_node dev_data_list; /* For global dev_data_list */
@@ -873,12 +878,6 @@ extern struct list_head amd_iommu_pci_seg_list;
extern struct list_head amd_iommu_list;
/*
- * Array with pointers to each IOMMU struct
- * The indices are referenced in the protection domains
- */
-extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
-
-/*
* Structure defining one entry in the device table
*/
struct dev_table_entry {
@@ -912,14 +911,14 @@ struct unity_map_entry {
/* size of the dma_ops aperture as power of 2 */
extern unsigned amd_iommu_aperture_order;
-/* allocation bitmap for domain ids */
-extern unsigned long *amd_iommu_pd_alloc_bitmap;
-
extern bool amd_iommu_force_isolation;
/* Max levels of glxval supported */
extern int amd_iommu_max_glx_val;
+/* IDA to track protection domain IDs */
+extern struct ida pdom_ids;
+
/* Global EFR and EFR2 registers */
extern u64 amd_iommu_efr;
extern u64 amd_iommu_efr2;
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 43131c3a2172..0e0a531042ac 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -177,9 +177,6 @@ LIST_HEAD(amd_iommu_pci_seg_list); /* list of all PCI segments */
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
system */
-/* Array to assign indices to IOMMUs*/
-struct amd_iommu *amd_iommus[MAX_IOMMUS];
-
/* Number of IOMMUs present in the system */
static int amd_iommus_present;
@@ -194,12 +191,6 @@ bool amd_iommu_force_isolation __read_mostly;
unsigned long amd_iommu_pgsize_bitmap __ro_after_init = AMD_IOMMU_PGSIZES;
-/*
- * AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
- * to know which ones are already in use.
- */
-unsigned long *amd_iommu_pd_alloc_bitmap;
-
enum iommu_init_state {
IOMMU_START_STATE,
IOMMU_IVRS_DETECTED,
@@ -1082,7 +1073,12 @@ static bool __copy_device_table(struct amd_iommu *iommu)
if (dte_v && dom_id) {
pci_seg->old_dev_tbl_cpy[devid].data[0] = old_devtb[devid].data[0];
pci_seg->old_dev_tbl_cpy[devid].data[1] = old_devtb[devid].data[1];
- __set_bit(dom_id, amd_iommu_pd_alloc_bitmap);
+ /* Reserve the Domain IDs used by previous kernel */
+ if (ida_alloc_range(&pdom_ids, dom_id, dom_id, GFP_ATOMIC) != dom_id) {
+ pr_err("Failed to reserve domain ID 0x%x\n", dom_id);
+ memunmap(old_devtb);
+ return false;
+ }
/* If gcr3 table existed, mask it out */
if (old_devtb[devid].data[0] & DTE_FLAG_GV) {
tmp = DTE_GCR3_VAL_B(~0ULL) << DTE_GCR3_SHIFT_B;
@@ -1744,9 +1740,6 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
return -ENOSYS;
}
- /* Index is fine - add IOMMU to the array */
- amd_iommus[iommu->index] = iommu;
-
/*
* Copy data from ACPI table entry to the iommu struct
*/
@@ -2070,14 +2063,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
init_iommu_perf_ctr(iommu);
- if (amd_iommu_pgtable == AMD_IOMMU_V2) {
- if (!check_feature(FEATURE_GIOSUP) ||
- !check_feature(FEATURE_GT)) {
- pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n");
- amd_iommu_pgtable = AMD_IOMMU_V1;
- }
- }
-
if (is_rd890_iommu(iommu->dev)) {
int i, j;
@@ -2172,6 +2157,9 @@ static int __init amd_iommu_init_pci(void)
struct amd_iommu_pci_seg *pci_seg;
int ret;
+ /* Init global identity domain before registering IOMMU */
+ amd_iommu_init_identity_domain();
+
for_each_iommu(iommu) {
ret = iommu_init_pci(iommu);
if (ret) {
@@ -2882,11 +2870,6 @@ static void enable_iommus_vapic(void)
#endif
}
-static void enable_iommus(void)
-{
- early_enable_iommus();
-}
-
static void disable_iommus(void)
{
struct amd_iommu *iommu;
@@ -2913,7 +2896,8 @@ static void amd_iommu_resume(void)
iommu_apply_resume_quirks(iommu);
/* re-load the hardware */
- enable_iommus();
+ for_each_iommu(iommu)
+ early_enable_iommu(iommu);
amd_iommu_enable_interrupts();
}
@@ -2994,9 +2978,7 @@ static bool __init check_ioapic_information(void)
static void __init free_dma_resources(void)
{
- iommu_free_pages(amd_iommu_pd_alloc_bitmap,
- get_order(MAX_DOMAIN_ID / 8));
- amd_iommu_pd_alloc_bitmap = NULL;
+ ida_destroy(&pdom_ids);
free_unity_maps();
}
@@ -3064,20 +3046,6 @@ static int __init early_amd_iommu_init(void)
amd_iommu_target_ivhd_type = get_highest_supported_ivhd_type(ivrs_base);
DUMP_printk("Using IVHD type %#x\n", amd_iommu_target_ivhd_type);
- /* Device table - directly used by all IOMMUs */
- ret = -ENOMEM;
-
- amd_iommu_pd_alloc_bitmap = iommu_alloc_pages(GFP_KERNEL,
- get_order(MAX_DOMAIN_ID / 8));
- if (amd_iommu_pd_alloc_bitmap == NULL)
- goto out;
-
- /*
- * never allocate domain 0 because its used as the non-allocated and
- * error value placeholder
- */
- __set_bit(0, amd_iommu_pd_alloc_bitmap);
-
/*
* now the data structures are allocated and basically initialized
* start the real acpi table scan
@@ -3091,6 +3059,13 @@ static int __init early_amd_iommu_init(void)
FIELD_GET(FEATURE_GATS, amd_iommu_efr) == GUEST_PGTABLE_5_LEVEL)
amd_iommu_gpt_level = PAGE_MODE_5_LEVEL;
+ if (amd_iommu_pgtable == AMD_IOMMU_V2) {
+ if (!amd_iommu_v2_pgtbl_supported()) {
+ pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n");
+ amd_iommu_pgtable = AMD_IOMMU_V1;
+ }
+ }
+
/* Disable any previously enabled IOMMUs */
if (!is_kdump_kernel() || amd_iommu_disabled)
disable_iommus();
diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index 804b788f3f16..f3399087859f 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -118,6 +118,7 @@ static void free_sub_pt(u64 *root, int mode, struct list_head *freelist)
*/
static bool increase_address_space(struct amd_io_pgtable *pgtable,
unsigned long address,
+ unsigned int page_size_level,
gfp_t gfp)
{
struct io_pgtable_cfg *cfg = &pgtable->pgtbl.cfg;
@@ -133,7 +134,8 @@ static bool increase_address_space(struct amd_io_pgtable *pgtable,
spin_lock_irqsave(&domain->lock, flags);
- if (address <= PM_LEVEL_SIZE(pgtable->mode))
+ if (address <= PM_LEVEL_SIZE(pgtable->mode) &&
+ pgtable->mode - 1 >= page_size_level)
goto out;
ret = false;
@@ -163,18 +165,21 @@ static u64 *alloc_pte(struct amd_io_pgtable *pgtable,
gfp_t gfp,
bool *updated)
{
+ unsigned long last_addr = address + (page_size - 1);
struct io_pgtable_cfg *cfg = &pgtable->pgtbl.cfg;
int level, end_lvl;
u64 *pte, *page;
BUG_ON(!is_power_of_2(page_size));
- while (address > PM_LEVEL_SIZE(pgtable->mode)) {
+ while (last_addr > PM_LEVEL_SIZE(pgtable->mode) ||
+ pgtable->mode - 1 < PAGE_SIZE_LEVEL(page_size)) {
/*
* Return an error if there is no memory to update the
* page-table.
*/
- if (!increase_address_space(pgtable, address, gfp))
+ if (!increase_address_space(pgtable, last_addr,
+ PAGE_SIZE_LEVEL(page_size), gfp))
return NULL;
}
diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c
index 25b9042fa453..c616de2c5926 100644
--- a/drivers/iommu/amd/io_pgtable_v2.c
+++ b/drivers/iommu/amd/io_pgtable_v2.c
@@ -268,8 +268,11 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
out:
if (updated) {
struct protection_domain *pdom = io_pgtable_ops_to_domain(ops);
+ unsigned long flags;
+ spin_lock_irqsave(&pdom->lock, flags);
amd_iommu_domain_flush_pages(pdom, o_iova, size);
+ spin_unlock_irqrestore(&pdom->lock, flags);
}
if (mapped)
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 8364cd6fa47d..3f691e1fd22c 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -18,6 +18,7 @@
#include <linux/scatterlist.h>
#include <linux/dma-map-ops.h>
#include <linux/dma-direct.h>
+#include <linux/idr.h>
#include <linux/iommu-helper.h>
#include <linux/delay.h>
#include <linux/amd-iommu.h>
@@ -52,8 +53,6 @@
#define HT_RANGE_START (0xfd00000000ULL)
#define HT_RANGE_END (0xffffffffffULL)
-static DEFINE_SPINLOCK(pd_bitmap_lock);
-
LIST_HEAD(ioapic_map);
LIST_HEAD(hpet_map);
LIST_HEAD(acpihid_map);
@@ -70,9 +69,16 @@ struct iommu_cmd {
u32 data[4];
};
+/*
+ * AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
+ * to know which ones are already in use.
+ */
+DEFINE_IDA(pdom_ids);
+
struct kmem_cache *amd_iommu_irq_cache;
-static void detach_device(struct device *dev);
+static int amd_iommu_attach_device(struct iommu_domain *dom,
+ struct device *dev);
static void set_dte_entry(struct amd_iommu *iommu,
struct iommu_dev_data *dev_data);
@@ -202,7 +208,7 @@ static struct iommu_dev_data *alloc_dev_data(struct amd_iommu *iommu, u16 devid)
if (!dev_data)
return NULL;
- spin_lock_init(&dev_data->lock);
+ mutex_init(&dev_data->mutex);
dev_data->devid = devid;
ratelimit_default_init(&dev_data->rs);
@@ -555,22 +561,6 @@ static void iommu_ignore_device(struct amd_iommu *iommu, struct device *dev)
setup_aliases(iommu, dev);
}
-static void amd_iommu_uninit_device(struct device *dev)
-{
- struct iommu_dev_data *dev_data;
-
- dev_data = dev_iommu_priv_get(dev);
- if (!dev_data)
- return;
-
- if (dev_data->domain)
- detach_device(dev);
-
- /*
- * We keep dev_data around for unplugged devices and reuse it when the
- * device is re-plugged - not doing so would introduce a ton of races.
- */
-}
/****************************************************************************
*
@@ -1230,7 +1220,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
if (!iommu->need_sync)
return 0;
- data = atomic64_add_return(1, &iommu->cmd_sem_val);
+ data = atomic64_inc_return(&iommu->cmd_sem_val);
build_completion_wait(&cmd, iommu, data);
raw_spin_lock_irqsave(&iommu->lock, flags);
@@ -1249,18 +1239,17 @@ out_unlock:
static void domain_flush_complete(struct protection_domain *domain)
{
- int i;
+ struct pdom_iommu_info *pdom_iommu_info;
+ unsigned long i;
- for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
- if (domain && !domain->dev_iommu[i])
- continue;
+ lockdep_assert_held(&domain->lock);
- /*
- * Devices of this domain are behind this IOMMU
- * We need to wait for completion of all commands.
- */
- iommu_completion_wait(amd_iommus[i]);
- }
+ /*
+ * Devices of this domain are behind this IOMMU
+ * We need to wait for completion of all commands.
+ */
+ xa_for_each(&domain->iommu_array, i, pdom_iommu_info)
+ iommu_completion_wait(pdom_iommu_info->iommu);
}
static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid)
@@ -1442,21 +1431,22 @@ static int domain_flush_pages_v2(struct protection_domain *pdom,
static int domain_flush_pages_v1(struct protection_domain *pdom,
u64 address, size_t size)
{
+ struct pdom_iommu_info *pdom_iommu_info;
struct iommu_cmd cmd;
- int ret = 0, i;
+ int ret = 0;
+ unsigned long i;
+
+ lockdep_assert_held(&pdom->lock);
build_inv_iommu_pages(&cmd, address, size,
pdom->id, IOMMU_NO_PASID, false);
- for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
- if (!pdom->dev_iommu[i])
- continue;
-
+ xa_for_each(&pdom->iommu_array, i, pdom_iommu_info) {
/*
* Devices of this domain are behind this IOMMU
* We need a TLB flush
*/
- ret |= iommu_queue_command(amd_iommus[i], &cmd);
+ ret |= iommu_queue_command(pdom_iommu_info->iommu, &cmd);
}
return ret;
@@ -1495,6 +1485,8 @@ static void __domain_flush_pages(struct protection_domain *domain,
void amd_iommu_domain_flush_pages(struct protection_domain *domain,
u64 address, size_t size)
{
+ lockdep_assert_held(&domain->lock);
+
if (likely(!amd_iommu_np_cache)) {
__domain_flush_pages(domain, address, size);
@@ -1640,31 +1632,14 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
*
****************************************************************************/
-static u16 domain_id_alloc(void)
+static int pdom_id_alloc(void)
{
- unsigned long flags;
- int id;
-
- spin_lock_irqsave(&pd_bitmap_lock, flags);
- id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID);
- BUG_ON(id == 0);
- if (id > 0 && id < MAX_DOMAIN_ID)
- __set_bit(id, amd_iommu_pd_alloc_bitmap);
- else
- id = 0;
- spin_unlock_irqrestore(&pd_bitmap_lock, flags);
-
- return id;
+ return ida_alloc_range(&pdom_ids, 1, MAX_DOMAIN_ID - 1, GFP_ATOMIC);
}
-static void domain_id_free(int id)
+static void pdom_id_free(int id)
{
- unsigned long flags;
-
- spin_lock_irqsave(&pd_bitmap_lock, flags);
- if (id > 0 && id < MAX_DOMAIN_ID)
- __clear_bit(id, amd_iommu_pd_alloc_bitmap);
- spin_unlock_irqrestore(&pd_bitmap_lock, flags);
+ ida_free(&pdom_ids, id);
}
static void free_gcr3_tbl_level1(u64 *tbl)
@@ -1709,7 +1684,7 @@ static void free_gcr3_table(struct gcr3_tbl_info *gcr3_info)
gcr3_info->glx = 0;
/* Free per device domain ID */
- domain_id_free(gcr3_info->domid);
+ pdom_id_free(gcr3_info->domid);
iommu_free_page(gcr3_info->gcr3_tbl);
gcr3_info->gcr3_tbl = NULL;
@@ -1736,6 +1711,7 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
{
int levels = get_gcr3_levels(pasids);
int nid = iommu ? dev_to_node(&iommu->dev->dev) : NUMA_NO_NODE;
+ int domid;
if (levels > amd_iommu_max_glx_val)
return -EINVAL;
@@ -1744,11 +1720,14 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
return -EBUSY;
/* Allocate per device domain ID */
- gcr3_info->domid = domain_id_alloc();
+ domid = pdom_id_alloc();
+ if (domid <= 0)
+ return -ENOSPC;
+ gcr3_info->domid = domid;
gcr3_info->gcr3_tbl = iommu_alloc_page_node(nid, GFP_ATOMIC);
if (gcr3_info->gcr3_tbl == NULL) {
- domain_id_free(gcr3_info->domid);
+ pdom_id_free(domid);
return -ENOMEM;
}
@@ -2019,57 +1998,69 @@ static void destroy_gcr3_table(struct iommu_dev_data *dev_data,
free_gcr3_table(gcr3_info);
}
-static int do_attach(struct iommu_dev_data *dev_data,
- struct protection_domain *domain)
+static int pdom_attach_iommu(struct amd_iommu *iommu,
+ struct protection_domain *pdom)
{
- struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
- struct io_pgtable_cfg *cfg = &domain->iop.pgtbl.cfg;
+ struct pdom_iommu_info *pdom_iommu_info, *curr;
+ struct io_pgtable_cfg *cfg = &pdom->iop.pgtbl.cfg;
+ unsigned long flags;
int ret = 0;
- /* Update data structures */
- dev_data->domain = domain;
- list_add(&dev_data->list, &domain->dev_list);
+ spin_lock_irqsave(&pdom->lock, flags);
- /* Update NUMA Node ID */
- if (cfg->amd.nid == NUMA_NO_NODE)
- cfg->amd.nid = dev_to_node(dev_data->dev);
+ pdom_iommu_info = xa_load(&pdom->iommu_array, iommu->index);
+ if (pdom_iommu_info) {
+ pdom_iommu_info->refcnt++;
+ goto out_unlock;
+ }
- /* Do reference counting */
- domain->dev_iommu[iommu->index] += 1;
- domain->dev_cnt += 1;
+ pdom_iommu_info = kzalloc(sizeof(*pdom_iommu_info), GFP_ATOMIC);
+ if (!pdom_iommu_info) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
- /* Setup GCR3 table */
- if (pdom_is_sva_capable(domain)) {
- ret = init_gcr3_table(dev_data, domain);
- if (ret)
- return ret;
+ pdom_iommu_info->iommu = iommu;
+ pdom_iommu_info->refcnt = 1;
+
+ curr = xa_cmpxchg(&pdom->iommu_array, iommu->index,
+ NULL, pdom_iommu_info, GFP_ATOMIC);
+ if (curr) {
+ kfree(pdom_iommu_info);
+ ret = -ENOSPC;
+ goto out_unlock;
}
+ /* Update NUMA Node ID */
+ if (cfg->amd.nid == NUMA_NO_NODE)
+ cfg->amd.nid = dev_to_node(&iommu->dev->dev);
+
+out_unlock:
+ spin_unlock_irqrestore(&pdom->lock, flags);
return ret;
}
-static void do_detach(struct iommu_dev_data *dev_data)
+static void pdom_detach_iommu(struct amd_iommu *iommu,
+ struct protection_domain *pdom)
{
- struct protection_domain *domain = dev_data->domain;
- struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
-
- /* Clear DTE and flush the entry */
- dev_update_dte(dev_data, false);
+ struct pdom_iommu_info *pdom_iommu_info;
+ unsigned long flags;
- /* Flush IOTLB and wait for the flushes to finish */
- amd_iommu_domain_flush_all(domain);
+ spin_lock_irqsave(&pdom->lock, flags);
- /* Clear GCR3 table */
- if (pdom_is_sva_capable(domain))
- destroy_gcr3_table(dev_data, domain);
+ pdom_iommu_info = xa_load(&pdom->iommu_array, iommu->index);
+ if (!pdom_iommu_info) {
+ spin_unlock_irqrestore(&pdom->lock, flags);
+ return;
+ }
- /* Update data structures */
- dev_data->domain = NULL;
- list_del(&dev_data->list);
+ pdom_iommu_info->refcnt--;
+ if (pdom_iommu_info->refcnt == 0) {
+ xa_erase(&pdom->iommu_array, iommu->index);
+ kfree(pdom_iommu_info);
+ }
- /* decrease reference counters - needs to happen after the flushes */
- domain->dev_iommu[iommu->index] -= 1;
- domain->dev_cnt -= 1;
+ spin_unlock_irqrestore(&pdom->lock, flags);
}
/*
@@ -2079,27 +2070,56 @@ static void do_detach(struct iommu_dev_data *dev_data)
static int attach_device(struct device *dev,
struct protection_domain *domain)
{
- struct iommu_dev_data *dev_data;
- unsigned long flags;
+ struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
+ struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
+ struct pci_dev *pdev;
int ret = 0;
- spin_lock_irqsave(&domain->lock, flags);
-
- dev_data = dev_iommu_priv_get(dev);
-
- spin_lock(&dev_data->lock);
+ mutex_lock(&dev_data->mutex);
if (dev_data->domain != NULL) {
ret = -EBUSY;
goto out;
}
- ret = do_attach(dev_data, domain);
+ /* Do reference counting */
+ ret = pdom_attach_iommu(iommu, domain);
+ if (ret)
+ goto out;
-out:
- spin_unlock(&dev_data->lock);
+ /* Setup GCR3 table */
+ if (pdom_is_sva_capable(domain)) {
+ ret = init_gcr3_table(dev_data, domain);
+ if (ret) {
+ pdom_detach_iommu(iommu, domain);
+ goto out;
+ }
+ }
- spin_unlock_irqrestore(&domain->lock, flags);
+ pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
+ if (pdev && pdom_is_sva_capable(domain)) {
+ pdev_enable_caps(pdev);
+
+ /*
+ * Device can continue to function even if IOPF
+ * enablement failed. Hence in error path just
+ * disable device PRI support.
+ */
+ if (amd_iommu_iopf_add_device(iommu, dev_data))
+ pdev_disable_cap_pri(pdev);
+ } else if (pdev) {
+ pdev_enable_cap_ats(pdev);
+ }
+
+ /* Update data structures */
+ dev_data->domain = domain;
+ list_add(&dev_data->list, &domain->dev_list);
+
+ /* Update device table */
+ dev_update_dte(dev_data, true);
+
+out:
+ mutex_unlock(&dev_data->mutex);
return ret;
}
@@ -2110,14 +2130,11 @@ out:
static void detach_device(struct device *dev)
{
struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
- struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
+ struct protection_domain *domain = dev_data->domain;
unsigned long flags;
- bool ppr = dev_data->ppr;
-
- spin_lock_irqsave(&domain->lock, flags);
- spin_lock(&dev_data->lock);
+ mutex_lock(&dev_data->mutex);
/*
* First check if the device is still attached. It might already
@@ -2128,27 +2145,36 @@ static void detach_device(struct device *dev)
if (WARN_ON(!dev_data->domain))
goto out;
- if (ppr) {
+ /* Remove IOPF handler */
+ if (dev_data->ppr) {
iopf_queue_flush_dev(dev);
-
- /* Updated here so that it gets reflected in DTE */
- dev_data->ppr = false;
+ amd_iommu_iopf_remove_device(iommu, dev_data);
}
- do_detach(dev_data);
+ if (dev_is_pci(dev))
+ pdev_disable_caps(to_pci_dev(dev));
-out:
- spin_unlock(&dev_data->lock);
+ /* Clear DTE and flush the entry */
+ dev_update_dte(dev_data, false);
+ /* Flush IOTLB and wait for the flushes to finish */
+ spin_lock_irqsave(&domain->lock, flags);
+ amd_iommu_domain_flush_all(domain);
spin_unlock_irqrestore(&domain->lock, flags);
- /* Remove IOPF handler */
- if (ppr)
- amd_iommu_iopf_remove_device(iommu, dev_data);
+ /* Clear GCR3 table */
+ if (pdom_is_sva_capable(domain))
+ destroy_gcr3_table(dev_data, domain);
- if (dev_is_pci(dev))
- pdev_disable_caps(to_pci_dev(dev));
+ /* Update data structures */
+ dev_data->domain = NULL;
+ list_del(&dev_data->list);
+
+ /* decrease reference counters - needs to happen after the flushes */
+ pdom_detach_iommu(iommu, domain);
+out:
+ mutex_unlock(&dev_data->mutex);
}
static struct iommu_device *amd_iommu_probe_device(struct device *dev)
@@ -2205,17 +2231,14 @@ out_err:
static void amd_iommu_release_device(struct device *dev)
{
- struct amd_iommu *iommu;
-
- if (!check_device(dev))
- return;
+ struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
- iommu = rlookup_amd_iommu(dev);
- if (!iommu)
- return;
+ WARN_ON(dev_data->domain);
- amd_iommu_uninit_device(dev);
- iommu_completion_wait(iommu);
+ /*
+ * We keep dev_data around for unplugged devices and reuse it when the
+ * device is re-plugged - not doing so would introduce a ton of races.
+ */
}
static struct iommu_group *amd_iommu_device_group(struct device *dev)
@@ -2236,70 +2259,53 @@ static struct iommu_group *amd_iommu_device_group(struct device *dev)
*
*****************************************************************************/
-static void cleanup_domain(struct protection_domain *domain)
-{
- struct iommu_dev_data *entry;
-
- lockdep_assert_held(&domain->lock);
-
- if (!domain->dev_cnt)
- return;
-
- while (!list_empty(&domain->dev_list)) {
- entry = list_first_entry(&domain->dev_list,
- struct iommu_dev_data, list);
- BUG_ON(!entry->domain);
- do_detach(entry);
- }
- WARN_ON(domain->dev_cnt != 0);
-}
-
void protection_domain_free(struct protection_domain *domain)
{
WARN_ON(!list_empty(&domain->dev_list));
if (domain->domain.type & __IOMMU_DOMAIN_PAGING)
free_io_pgtable_ops(&domain->iop.pgtbl.ops);
- domain_id_free(domain->id);
+ pdom_id_free(domain->id);
kfree(domain);
}
+static void protection_domain_init(struct protection_domain *domain, int nid)
+{
+ spin_lock_init(&domain->lock);
+ INIT_LIST_HEAD(&domain->dev_list);
+ INIT_LIST_HEAD(&domain->dev_data_list);
+ xa_init(&domain->iommu_array);
+ domain->iop.pgtbl.cfg.amd.nid = nid;
+}
+
struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
{
- struct io_pgtable_ops *pgtbl_ops;
struct protection_domain *domain;
- int pgtable;
+ int domid;
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
- domain->id = domain_id_alloc();
- if (!domain->id)
- goto err_free;
+ domid = pdom_id_alloc();
+ if (domid <= 0) {
+ kfree(domain);
+ return NULL;
+ }
+ domain->id = domid;
- spin_lock_init(&domain->lock);
- INIT_LIST_HEAD(&domain->dev_list);
- INIT_LIST_HEAD(&domain->dev_data_list);
- domain->iop.pgtbl.cfg.amd.nid = nid;
+ protection_domain_init(domain, nid);
+
+ return domain;
+}
+
+static int pdom_setup_pgtable(struct protection_domain *domain,
+ unsigned int type, int pgtable)
+{
+ struct io_pgtable_ops *pgtbl_ops;
- switch (type) {
/* No need to allocate io pgtable ops in passthrough mode */
- case IOMMU_DOMAIN_IDENTITY:
- case IOMMU_DOMAIN_SVA:
- return domain;
- case IOMMU_DOMAIN_DMA:
- pgtable = amd_iommu_pgtable;
- break;
- /*
- * Force IOMMU v1 page table when allocating
- * domain for pass-through devices.
- */
- case IOMMU_DOMAIN_UNMANAGED:
- pgtable = AMD_IOMMU_V1;
- break;
- default:
- goto err_id;
- }
+ if (!(type & __IOMMU_DOMAIN_PAGING))
+ return 0;
switch (pgtable) {
case AMD_IOMMU_V1:
@@ -2309,25 +2315,20 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
domain->pd_mode = PD_MODE_V2;
break;
default:
- goto err_id;
+ return -EINVAL;
}
pgtbl_ops =
alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl.cfg, domain);
if (!pgtbl_ops)
- goto err_id;
+ return -ENOMEM;
- return domain;
-err_id:
- domain_id_free(domain->id);
-err_free:
- kfree(domain);
- return NULL;
+ return 0;
}
-static inline u64 dma_max_address(void)
+static inline u64 dma_max_address(int pgtable)
{
- if (amd_iommu_pgtable == AMD_IOMMU_V1)
+ if (pgtable == AMD_IOMMU_V1)
return ~0ULL;
/* V2 with 4/5 level page table */
@@ -2340,11 +2341,13 @@ static bool amd_iommu_hd_support(struct amd_iommu *iommu)
}
static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
- struct device *dev, u32 flags)
+ struct device *dev,
+ u32 flags, int pgtable)
{
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
struct protection_domain *domain;
struct amd_iommu *iommu = NULL;
+ int ret;
if (dev)
iommu = get_amd_iommu_from_dev(dev);
@@ -2356,16 +2359,20 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
if (amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY))
return ERR_PTR(-EINVAL);
- if (dirty_tracking && !amd_iommu_hd_support(iommu))
- return ERR_PTR(-EOPNOTSUPP);
-
domain = protection_domain_alloc(type,
dev ? dev_to_node(dev) : NUMA_NO_NODE);
if (!domain)
return ERR_PTR(-ENOMEM);
+ ret = pdom_setup_pgtable(domain, type, pgtable);
+ if (ret) {
+ pdom_id_free(domain->id);
+ kfree(domain);
+ return ERR_PTR(ret);
+ }
+
domain->domain.geometry.aperture_start = 0;
- domain->domain.geometry.aperture_end = dma_max_address();
+ domain->domain.geometry.aperture_end = dma_max_address(pgtable);
domain->domain.geometry.force_aperture = true;
domain->domain.pgsize_bitmap = domain->iop.pgtbl.cfg.pgsize_bitmap;
@@ -2383,8 +2390,16 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type)
{
struct iommu_domain *domain;
+ int pgtable = amd_iommu_pgtable;
- domain = do_iommu_domain_alloc(type, NULL, 0);
+ /*
+ * Force IOMMU v1 page table when allocating
+ * domain for pass-through devices.
+ */
+ if (type == IOMMU_DOMAIN_UNMANAGED)
+ pgtable = AMD_IOMMU_V1;
+
+ domain = do_iommu_domain_alloc(type, NULL, 0, pgtable);
if (IS_ERR(domain))
return NULL;
@@ -2392,31 +2407,46 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type)
}
static struct iommu_domain *
-amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+amd_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
{
unsigned int type = IOMMU_DOMAIN_UNMANAGED;
+ struct amd_iommu *iommu = NULL;
+ const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
+ IOMMU_HWPT_ALLOC_PASID;
- if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data)
+ if (dev)
+ iommu = get_amd_iommu_from_dev(dev);
+
+ if ((flags & ~supported_flags) || user_data)
return ERR_PTR(-EOPNOTSUPP);
- return do_iommu_domain_alloc(type, dev, flags);
-}
+ /* Allocate domain with v2 page table if IOMMU supports PASID. */
+ if (flags & IOMMU_HWPT_ALLOC_PASID) {
+ if (!amd_iommu_pasid_supported())
+ return ERR_PTR(-EOPNOTSUPP);
-void amd_iommu_domain_free(struct iommu_domain *dom)
-{
- struct protection_domain *domain;
- unsigned long flags;
+ return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2);
+ }
- domain = to_pdomain(dom);
+ /* Allocate domain with v1 page table for dirty tracking */
+ if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) {
+ if (iommu && amd_iommu_hd_support(iommu)) {
+ return do_iommu_domain_alloc(type, dev,
+ flags, AMD_IOMMU_V1);
+ }
- spin_lock_irqsave(&domain->lock, flags);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
- cleanup_domain(domain);
+ /* If nothing specific is required use the kernel commandline default */
+ return do_iommu_domain_alloc(type, dev, 0, amd_iommu_pgtable);
+}
- spin_unlock_irqrestore(&domain->lock, flags);
+void amd_iommu_domain_free(struct iommu_domain *dom)
+{
+ struct protection_domain *domain = to_pdomain(dom);
protection_domain_free(domain);
}
@@ -2430,9 +2460,9 @@ static int blocked_domain_attach_device(struct iommu_domain *domain,
detach_device(dev);
/* Clear DTE and flush the entry */
- spin_lock(&dev_data->lock);
+ mutex_lock(&dev_data->mutex);
dev_update_dte(dev_data, false);
- spin_unlock(&dev_data->lock);
+ mutex_unlock(&dev_data->mutex);
return 0;
}
@@ -2444,13 +2474,39 @@ static struct iommu_domain blocked_domain = {
}
};
+static struct protection_domain identity_domain;
+
+static const struct iommu_domain_ops identity_domain_ops = {
+ .attach_dev = amd_iommu_attach_device,
+};
+
+void amd_iommu_init_identity_domain(void)
+{
+ struct iommu_domain *domain = &identity_domain.domain;
+
+ domain->type = IOMMU_DOMAIN_IDENTITY;
+ domain->ops = &identity_domain_ops;
+ domain->owner = &amd_iommu_ops;
+
+ identity_domain.id = pdom_id_alloc();
+
+ protection_domain_init(&identity_domain, NUMA_NO_NODE);
+}
+
+/* Same as blocked domain except it supports only ops->attach_dev() */
+static struct iommu_domain release_domain = {
+ .type = IOMMU_DOMAIN_BLOCKED,
+ .ops = &(const struct iommu_domain_ops) {
+ .attach_dev = blocked_domain_attach_device,
+ }
+};
+
static int amd_iommu_attach_device(struct iommu_domain *dom,
struct device *dev)
{
struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
struct protection_domain *domain = to_pdomain(dom);
struct amd_iommu *iommu = get_amd_iommu_from_dev(dev);
- struct pci_dev *pdev;
int ret;
/*
@@ -2483,24 +2539,6 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
}
#endif
- pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
- if (pdev && pdom_is_sva_capable(domain)) {
- pdev_enable_caps(pdev);
-
- /*
- * Device can continue to function even if IOPF
- * enablement failed. Hence in error path just
- * disable device PRI support.
- */
- if (amd_iommu_iopf_add_device(iommu, dev_data))
- pdev_disable_cap_pri(pdev);
- } else if (pdev) {
- pdev_enable_cap_ats(pdev);
- }
-
- /* Update device table */
- dev_update_dte(dev_data, true);
-
return ret;
}
@@ -2842,8 +2880,10 @@ static int amd_iommu_dev_disable_feature(struct device *dev,
const struct iommu_ops amd_iommu_ops = {
.capable = amd_iommu_capable,
.blocked_domain = &blocked_domain,
+ .release_domain = &release_domain,
+ .identity_domain = &identity_domain.domain,
.domain_alloc = amd_iommu_domain_alloc,
- .domain_alloc_user = amd_iommu_domain_alloc_user,
+ .domain_alloc_paging_flags = amd_iommu_domain_alloc_paging_flags,
.domain_alloc_sva = amd_iommu_domain_alloc_sva,
.probe_device = amd_iommu_probe_device,
.release_device = amd_iommu_release_device,
@@ -2890,7 +2930,7 @@ static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid)
return;
build_inv_irt(&cmd, devid);
- data = atomic64_add_return(1, &iommu->cmd_sem_val);
+ data = atomic64_inc_return(&iommu->cmd_sem_val);
build_completion_wait(&cmd2, iommu, data);
raw_spin_lock_irqsave(&iommu->lock, flags);
diff --git a/drivers/iommu/amd/pasid.c b/drivers/iommu/amd/pasid.c
index 0657b9373be5..8c73a30c2800 100644
--- a/drivers/iommu/amd/pasid.c
+++ b/drivers/iommu/amd/pasid.c
@@ -100,7 +100,8 @@ static const struct mmu_notifier_ops sva_mn = {
};
int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
- struct device *dev, ioasid_t pasid)
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
{
struct pdom_dev_data *pdom_dev_data;
struct protection_domain *sva_pdom = to_pdomain(domain);
@@ -108,6 +109,9 @@ int iommu_sva_set_dev_pasid(struct iommu_domain *domain,
unsigned long flags;
int ret = -EINVAL;
+ if (old)
+ return -EOPNOTSUPP;
+
/* PASID zero is used for requests from the I/O device without PASID */
if (!is_pasid_valid(dev_data, pasid))
return ret;
diff --git a/drivers/iommu/arm/arm-smmu-v3/Makefile b/drivers/iommu/arm/arm-smmu-v3/Makefile
index dc98c88b48c8..493a659cc66b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/Makefile
+++ b/drivers/iommu/arm/arm-smmu-v3/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ARM_SMMU_V3) += arm_smmu_v3.o
arm_smmu_v3-y := arm-smmu-v3.o
+arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_IOMMUFD) += arm-smmu-v3-iommufd.o
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
arm_smmu_v3-$(CONFIG_TEGRA241_CMDQV) += tegra241-cmdqv.o
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
new file mode 100644
index 000000000000..6cc14d82399f
--- /dev/null
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
+ */
+
+#include <uapi/linux/iommufd.h>
+
+#include "arm-smmu-v3.h"
+
+void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type)
+{
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ struct iommu_hw_info_arm_smmuv3 *info;
+ u32 __iomem *base_idr;
+ unsigned int i;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ base_idr = master->smmu->base + ARM_SMMU_IDR0;
+ for (i = 0; i <= 5; i++)
+ info->idr[i] = readl_relaxed(base_idr + i);
+ info->iidr = readl_relaxed(master->smmu->base + ARM_SMMU_IIDR);
+ info->aidr = readl_relaxed(master->smmu->base + ARM_SMMU_AIDR);
+
+ *length = sizeof(*info);
+ *type = IOMMU_HW_INFO_TYPE_ARM_SMMUV3;
+
+ return info;
+}
+
+static void arm_smmu_make_nested_cd_table_ste(
+ struct arm_smmu_ste *target, struct arm_smmu_master *master,
+ struct arm_smmu_nested_domain *nested_domain, bool ats_enabled)
+{
+ arm_smmu_make_s2_domain_ste(
+ target, master, nested_domain->vsmmu->s2_parent, ats_enabled);
+
+ target->data[0] = cpu_to_le64(STRTAB_STE_0_V |
+ FIELD_PREP(STRTAB_STE_0_CFG,
+ STRTAB_STE_0_CFG_NESTED));
+ target->data[0] |= nested_domain->ste[0] &
+ ~cpu_to_le64(STRTAB_STE_0_CFG);
+ target->data[1] |= nested_domain->ste[1];
+}
+
+/*
+ * Create a physical STE from the virtual STE that userspace provided when it
+ * created the nested domain. Using the vSTE userspace can request:
+ * - Non-valid STE
+ * - Abort STE
+ * - Bypass STE (install the S2, no CD table)
+ * - CD table STE (install the S2 and the userspace CD table)
+ */
+static void arm_smmu_make_nested_domain_ste(
+ struct arm_smmu_ste *target, struct arm_smmu_master *master,
+ struct arm_smmu_nested_domain *nested_domain, bool ats_enabled)
+{
+ unsigned int cfg =
+ FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(nested_domain->ste[0]));
+
+ /*
+ * Userspace can request a non-valid STE through the nesting interface.
+ * We relay that into an abort physical STE with the intention that
+ * C_BAD_STE for this SID can be generated to userspace.
+ */
+ if (!(nested_domain->ste[0] & cpu_to_le64(STRTAB_STE_0_V)))
+ cfg = STRTAB_STE_0_CFG_ABORT;
+
+ switch (cfg) {
+ case STRTAB_STE_0_CFG_S1_TRANS:
+ arm_smmu_make_nested_cd_table_ste(target, master, nested_domain,
+ ats_enabled);
+ break;
+ case STRTAB_STE_0_CFG_BYPASS:
+ arm_smmu_make_s2_domain_ste(target, master,
+ nested_domain->vsmmu->s2_parent,
+ ats_enabled);
+ break;
+ case STRTAB_STE_0_CFG_ABORT:
+ default:
+ arm_smmu_make_abort_ste(target);
+ break;
+ }
+}
+
+static int arm_smmu_attach_dev_nested(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct arm_smmu_nested_domain *nested_domain =
+ to_smmu_nested_domain(domain);
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ struct arm_smmu_attach_state state = {
+ .master = master,
+ .old_domain = iommu_get_domain_for_dev(dev),
+ .ssid = IOMMU_NO_PASID,
+ };
+ struct arm_smmu_ste ste;
+ int ret;
+
+ if (nested_domain->vsmmu->smmu != master->smmu)
+ return -EINVAL;
+ if (arm_smmu_ssids_in_use(&master->cd_table))
+ return -EBUSY;
+
+ mutex_lock(&arm_smmu_asid_lock);
+ /*
+ * The VM has to control the actual ATS state at the PCI device because
+ * we forward the invalidations directly from the VM. If the VM doesn't
+ * think ATS is on it will not generate ATC flushes and the ATC will
+ * become incoherent. Since we can't access the actual virtual PCI ATS
+ * config bit here base this off the EATS value in the STE. If the EATS
+ * is set then the VM must generate ATC flushes.
+ */
+ state.disable_ats = !nested_domain->enable_ats;
+ ret = arm_smmu_attach_prepare(&state, domain);
+ if (ret) {
+ mutex_unlock(&arm_smmu_asid_lock);
+ return ret;
+ }
+
+ arm_smmu_make_nested_domain_ste(&ste, master, nested_domain,
+ state.ats_enabled);
+ arm_smmu_install_ste_for_dev(master, &ste);
+ arm_smmu_attach_commit(&state);
+ mutex_unlock(&arm_smmu_asid_lock);
+ return 0;
+}
+
+static void arm_smmu_domain_nested_free(struct iommu_domain *domain)
+{
+ kfree(to_smmu_nested_domain(domain));
+}
+
+static const struct iommu_domain_ops arm_smmu_nested_ops = {
+ .attach_dev = arm_smmu_attach_dev_nested,
+ .free = arm_smmu_domain_nested_free,
+};
+
+static int arm_smmu_validate_vste(struct iommu_hwpt_arm_smmuv3 *arg,
+ bool *enable_ats)
+{
+ unsigned int eats;
+ unsigned int cfg;
+
+ if (!(arg->ste[0] & cpu_to_le64(STRTAB_STE_0_V))) {
+ memset(arg->ste, 0, sizeof(arg->ste));
+ return 0;
+ }
+
+ /* EIO is reserved for invalid STE data. */
+ if ((arg->ste[0] & ~STRTAB_STE_0_NESTING_ALLOWED) ||
+ (arg->ste[1] & ~STRTAB_STE_1_NESTING_ALLOWED))
+ return -EIO;
+
+ cfg = FIELD_GET(STRTAB_STE_0_CFG, le64_to_cpu(arg->ste[0]));
+ if (cfg != STRTAB_STE_0_CFG_ABORT && cfg != STRTAB_STE_0_CFG_BYPASS &&
+ cfg != STRTAB_STE_0_CFG_S1_TRANS)
+ return -EIO;
+
+ /*
+ * Only Full ATS or ATS UR is supported
+ * The EATS field will be set by arm_smmu_make_nested_domain_ste()
+ */
+ eats = FIELD_GET(STRTAB_STE_1_EATS, le64_to_cpu(arg->ste[1]));
+ arg->ste[1] &= ~cpu_to_le64(STRTAB_STE_1_EATS);
+ if (eats != STRTAB_STE_1_EATS_ABT && eats != STRTAB_STE_1_EATS_TRANS)
+ return -EIO;
+
+ if (cfg == STRTAB_STE_0_CFG_S1_TRANS)
+ *enable_ats = (eats == STRTAB_STE_1_EATS_TRANS);
+ return 0;
+}
+
+static struct iommu_domain *
+arm_vsmmu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
+ const struct iommu_user_data *user_data)
+{
+ struct arm_vsmmu *vsmmu = container_of(viommu, struct arm_vsmmu, core);
+ const u32 SUPPORTED_FLAGS = IOMMU_HWPT_FAULT_ID_VALID;
+ struct arm_smmu_nested_domain *nested_domain;
+ struct iommu_hwpt_arm_smmuv3 arg;
+ bool enable_ats = false;
+ int ret;
+
+ /*
+ * Faults delivered to the nested domain are faults that originated by
+ * the S1 in the domain. The core code will match all PASIDs when
+ * delivering the fault due to user_pasid_table
+ */
+ if (flags & ~SUPPORTED_FLAGS)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ ret = iommu_copy_struct_from_user(&arg, user_data,
+ IOMMU_HWPT_DATA_ARM_SMMUV3, ste);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = arm_smmu_validate_vste(&arg, &enable_ats);
+ if (ret)
+ return ERR_PTR(ret);
+
+ nested_domain = kzalloc(sizeof(*nested_domain), GFP_KERNEL_ACCOUNT);
+ if (!nested_domain)
+ return ERR_PTR(-ENOMEM);
+
+ nested_domain->domain.type = IOMMU_DOMAIN_NESTED;
+ nested_domain->domain.ops = &arm_smmu_nested_ops;
+ nested_domain->enable_ats = enable_ats;
+ nested_domain->vsmmu = vsmmu;
+ nested_domain->ste[0] = arg.ste[0];
+ nested_domain->ste[1] = arg.ste[1] & ~cpu_to_le64(STRTAB_STE_1_EATS);
+
+ return &nested_domain->domain;
+}
+
+static int arm_vsmmu_vsid_to_sid(struct arm_vsmmu *vsmmu, u32 vsid, u32 *sid)
+{
+ struct arm_smmu_master *master;
+ struct device *dev;
+ int ret = 0;
+
+ xa_lock(&vsmmu->core.vdevs);
+ dev = iommufd_viommu_find_dev(&vsmmu->core, (unsigned long)vsid);
+ if (!dev) {
+ ret = -EIO;
+ goto unlock;
+ }
+ master = dev_iommu_priv_get(dev);
+
+ /* At this moment, iommufd only supports PCI device that has one SID */
+ if (sid)
+ *sid = master->streams[0].id;
+unlock:
+ xa_unlock(&vsmmu->core.vdevs);
+ return ret;
+}
+
+/* This is basically iommu_viommu_arm_smmuv3_invalidate in u64 for conversion */
+struct arm_vsmmu_invalidation_cmd {
+ union {
+ u64 cmd[2];
+ struct iommu_viommu_arm_smmuv3_invalidate ucmd;
+ };
+};
+
+/*
+ * Convert, in place, the raw invalidation command into an internal format that
+ * can be passed to arm_smmu_cmdq_issue_cmdlist(). Internally commands are
+ * stored in CPU endian.
+ *
+ * Enforce the VMID or SID on the command.
+ */
+static int arm_vsmmu_convert_user_cmd(struct arm_vsmmu *vsmmu,
+ struct arm_vsmmu_invalidation_cmd *cmd)
+{
+ /* Commands are le64 stored in u64 */
+ cmd->cmd[0] = le64_to_cpu(cmd->ucmd.cmd[0]);
+ cmd->cmd[1] = le64_to_cpu(cmd->ucmd.cmd[1]);
+
+ switch (cmd->cmd[0] & CMDQ_0_OP) {
+ case CMDQ_OP_TLBI_NSNH_ALL:
+ /* Convert to NH_ALL */
+ cmd->cmd[0] = CMDQ_OP_TLBI_NH_ALL |
+ FIELD_PREP(CMDQ_TLBI_0_VMID, vsmmu->vmid);
+ cmd->cmd[1] = 0;
+ break;
+ case CMDQ_OP_TLBI_NH_VA:
+ case CMDQ_OP_TLBI_NH_VAA:
+ case CMDQ_OP_TLBI_NH_ALL:
+ case CMDQ_OP_TLBI_NH_ASID:
+ cmd->cmd[0] &= ~CMDQ_TLBI_0_VMID;
+ cmd->cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, vsmmu->vmid);
+ break;
+ case CMDQ_OP_ATC_INV:
+ case CMDQ_OP_CFGI_CD:
+ case CMDQ_OP_CFGI_CD_ALL: {
+ u32 sid, vsid = FIELD_GET(CMDQ_CFGI_0_SID, cmd->cmd[0]);
+
+ if (arm_vsmmu_vsid_to_sid(vsmmu, vsid, &sid))
+ return -EIO;
+ cmd->cmd[0] &= ~CMDQ_CFGI_0_SID;
+ cmd->cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SID, sid);
+ break;
+ }
+ default:
+ return -EIO;
+ }
+ return 0;
+}
+
+static int arm_vsmmu_cache_invalidate(struct iommufd_viommu *viommu,
+ struct iommu_user_data_array *array)
+{
+ struct arm_vsmmu *vsmmu = container_of(viommu, struct arm_vsmmu, core);
+ struct arm_smmu_device *smmu = vsmmu->smmu;
+ struct arm_vsmmu_invalidation_cmd *last;
+ struct arm_vsmmu_invalidation_cmd *cmds;
+ struct arm_vsmmu_invalidation_cmd *cur;
+ struct arm_vsmmu_invalidation_cmd *end;
+ int ret;
+
+ cmds = kcalloc(array->entry_num, sizeof(*cmds), GFP_KERNEL);
+ if (!cmds)
+ return -ENOMEM;
+ cur = cmds;
+ end = cmds + array->entry_num;
+
+ static_assert(sizeof(*cmds) == 2 * sizeof(u64));
+ ret = iommu_copy_struct_from_full_user_array(
+ cmds, sizeof(*cmds), array,
+ IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3);
+ if (ret)
+ goto out;
+
+ last = cmds;
+ while (cur != end) {
+ ret = arm_vsmmu_convert_user_cmd(vsmmu, cur);
+ if (ret)
+ goto out;
+
+ /* FIXME work in blocks of CMDQ_BATCH_ENTRIES and copy each block? */
+ cur++;
+ if (cur != end && (cur - last) != CMDQ_BATCH_ENTRIES - 1)
+ continue;
+
+ /* FIXME always uses the main cmdq rather than trying to group by type */
+ ret = arm_smmu_cmdq_issue_cmdlist(smmu, &smmu->cmdq, last->cmd,
+ cur - last, true);
+ if (ret) {
+ cur--;
+ goto out;
+ }
+ last = cur;
+ }
+out:
+ array->entry_num = cur - cmds;
+ kfree(cmds);
+ return ret;
+}
+
+static const struct iommufd_viommu_ops arm_vsmmu_ops = {
+ .alloc_domain_nested = arm_vsmmu_alloc_domain_nested,
+ .cache_invalidate = arm_vsmmu_cache_invalidate,
+};
+
+struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
+ struct iommu_domain *parent,
+ struct iommufd_ctx *ictx,
+ unsigned int viommu_type)
+{
+ struct arm_smmu_device *smmu =
+ iommu_get_iommu_dev(dev, struct arm_smmu_device, iommu);
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ struct arm_smmu_domain *s2_parent = to_smmu_domain(parent);
+ struct arm_vsmmu *vsmmu;
+
+ if (viommu_type != IOMMU_VIOMMU_TYPE_ARM_SMMUV3)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ if (!(smmu->features & ARM_SMMU_FEAT_NESTING))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ if (s2_parent->smmu != master->smmu)
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * FORCE_SYNC is not set with FEAT_NESTING. Some study of the exact HW
+ * defect is needed to determine if arm_vsmmu_cache_invalidate() needs
+ * any change to remove this.
+ */
+ if (WARN_ON(smmu->options & ARM_SMMU_OPT_CMDQ_FORCE_SYNC))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ /*
+ * Must support some way to prevent the VM from bypassing the cache
+ * because VFIO currently does not do any cache maintenance. canwbs
+ * indicates the device is fully coherent and no cache maintenance is
+ * ever required, even for PCI No-Snoop. S2FWB means the S1 can't make
+ * things non-coherent using the memattr, but No-Snoop behavior is not
+ * effected.
+ */
+ if (!arm_smmu_master_canwbs(master) &&
+ !(smmu->features & ARM_SMMU_FEAT_S2FWB))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ vsmmu = iommufd_viommu_alloc(ictx, struct arm_vsmmu, core,
+ &arm_vsmmu_ops);
+ if (IS_ERR(vsmmu))
+ return ERR_CAST(vsmmu);
+
+ vsmmu->smmu = smmu;
+ vsmmu->s2_parent = s2_parent;
+ /* FIXME Move VMID allocation from the S2 domain allocation to here */
+ vsmmu->vmid = s2_parent->s2_cfg.vmid;
+
+ return &vsmmu->core;
+}
+
+MODULE_IMPORT_NS(IOMMUFD);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index a7c36654dee5..1d3e71569775 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -332,7 +332,8 @@ void arm_smmu_sva_notifier_synchronize(void)
}
static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
- struct device *dev, ioasid_t id)
+ struct device *dev, ioasid_t id,
+ struct iommu_domain *old)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
@@ -348,7 +349,7 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
* get reassigned
*/
arm_smmu_make_sva_cd(&target, master, domain->mm, smmu_domain->cd.asid);
- ret = arm_smmu_set_pasid(master, smmu_domain, id, &target);
+ ret = arm_smmu_set_pasid(master, smmu_domain, id, &target, old);
mmput(domain->mm);
return ret;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 353fea58cd31..e4ebd9e12ad4 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -295,6 +295,7 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
case CMDQ_OP_TLBI_NH_ASID:
cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
fallthrough;
+ case CMDQ_OP_TLBI_NH_ALL:
case CMDQ_OP_TLBI_S12_VMALL:
cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid);
break;
@@ -765,9 +766,9 @@ static void arm_smmu_cmdq_write_entries(struct arm_smmu_cmdq *cmdq, u64 *cmds,
* insert their own list of commands then all of the commands from one
* CPU will appear before any of the commands from the other CPU.
*/
-static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
- struct arm_smmu_cmdq *cmdq,
- u64 *cmds, int n, bool sync)
+int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
+ struct arm_smmu_cmdq *cmdq, u64 *cmds, int n,
+ bool sync)
{
u64 cmd_sync[CMDQ_ENT_DWORDS];
u32 prod;
@@ -1045,7 +1046,8 @@ void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits)
/* S2 translates */
if (cfg & BIT(1)) {
used_bits[1] |=
- cpu_to_le64(STRTAB_STE_1_EATS | STRTAB_STE_1_SHCFG);
+ cpu_to_le64(STRTAB_STE_1_S2FWB | STRTAB_STE_1_EATS |
+ STRTAB_STE_1_SHCFG);
used_bits[2] |=
cpu_to_le64(STRTAB_STE_2_S2VMID | STRTAB_STE_2_VTCR |
STRTAB_STE_2_S2AA64 | STRTAB_STE_2_S2ENDI |
@@ -1549,7 +1551,6 @@ static void arm_smmu_write_ste(struct arm_smmu_master *master, u32 sid,
}
}
-VISIBLE_IF_KUNIT
void arm_smmu_make_abort_ste(struct arm_smmu_ste *target)
{
memset(target, 0, sizeof(*target));
@@ -1632,7 +1633,6 @@ void arm_smmu_make_cdtable_ste(struct arm_smmu_ste *target,
}
EXPORT_SYMBOL_IF_KUNIT(arm_smmu_make_cdtable_ste);
-VISIBLE_IF_KUNIT
void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
struct arm_smmu_master *master,
struct arm_smmu_domain *smmu_domain,
@@ -1655,6 +1655,8 @@ void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
FIELD_PREP(STRTAB_STE_1_EATS,
ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0));
+ if (pgtbl_cfg->quirks & IO_PGTABLE_QUIRK_ARM_S2FWB)
+ target->data[1] |= cpu_to_le64(STRTAB_STE_1_S2FWB);
if (smmu->features & ARM_SMMU_FEAT_ATTR_TYPES_OVR)
target->data[1] |= cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG,
STRTAB_STE_1_SHCFG_INCOMING));
@@ -2105,7 +2107,16 @@ int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain,
if (!master->ats_enabled)
continue;
- arm_smmu_atc_inv_to_cmd(master_domain->ssid, iova, size, &cmd);
+ if (master_domain->nested_ats_flush) {
+ /*
+ * If a S2 used as a nesting parent is changed we have
+ * no option but to completely flush the ATC.
+ */
+ arm_smmu_atc_inv_to_cmd(IOMMU_NO_PASID, 0, 0, &cmd);
+ } else {
+ arm_smmu_atc_inv_to_cmd(master_domain->ssid, iova, size,
+ &cmd);
+ }
for (i = 0; i < master->num_streams; i++) {
cmd.atc.sid = master->streams[i].id;
@@ -2232,6 +2243,15 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size,
}
__arm_smmu_tlb_inv_range(&cmd, iova, size, granule, smmu_domain);
+ if (smmu_domain->nest_parent) {
+ /*
+ * When the S2 domain changes all the nested S1 ASIDs have to be
+ * flushed too.
+ */
+ cmd.opcode = CMDQ_OP_TLBI_NH_ALL;
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu_domain->smmu, &cmd);
+ }
+
/*
* Unfortunately, this can't be leaf-only since we may have
* zapped an entire table.
@@ -2293,6 +2313,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
case IOMMU_CAP_CACHE_COHERENCY:
/* Assume that a coherent TCU implies coherent TBUs */
return master->smmu->features & ARM_SMMU_FEAT_COHERENCY;
+ case IOMMU_CAP_ENFORCE_CACHE_COHERENCY:
+ return arm_smmu_master_canwbs(master);
case IOMMU_CAP_NOEXEC:
case IOMMU_CAP_DEFERRED_FLUSH:
return true;
@@ -2303,6 +2325,26 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
}
}
+static bool arm_smmu_enforce_cache_coherency(struct iommu_domain *domain)
+{
+ struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ struct arm_smmu_master_domain *master_domain;
+ unsigned long flags;
+ bool ret = true;
+
+ spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+ list_for_each_entry(master_domain, &smmu_domain->devices,
+ devices_elm) {
+ if (!arm_smmu_master_canwbs(master_domain->master)) {
+ ret = false;
+ break;
+ }
+ }
+ smmu_domain->enforce_cache_coherency = ret;
+ spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
+ return ret;
+}
+
struct arm_smmu_domain *arm_smmu_domain_alloc(void)
{
struct arm_smmu_domain *smmu_domain;
@@ -2442,6 +2484,9 @@ static int arm_smmu_domain_finalise(struct arm_smmu_domain *smmu_domain,
pgtbl_cfg.oas = smmu->oas;
fmt = ARM_64_LPAE_S2;
finalise_stage_fn = arm_smmu_domain_finalise_s2;
+ if ((smmu->features & ARM_SMMU_FEAT_S2FWB) &&
+ (flags & IOMMU_HWPT_ALLOC_NEST_PARENT))
+ pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_ARM_S2FWB;
break;
default:
return -EINVAL;
@@ -2483,8 +2528,8 @@ arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
}
}
-static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master,
- const struct arm_smmu_ste *target)
+void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master,
+ const struct arm_smmu_ste *target)
{
int i, j;
struct arm_smmu_device *smmu = master->smmu;
@@ -2595,7 +2640,7 @@ static void arm_smmu_disable_pasid(struct arm_smmu_master *master)
static struct arm_smmu_master_domain *
arm_smmu_find_master_domain(struct arm_smmu_domain *smmu_domain,
struct arm_smmu_master *master,
- ioasid_t ssid)
+ ioasid_t ssid, bool nested_ats_flush)
{
struct arm_smmu_master_domain *master_domain;
@@ -2604,7 +2649,8 @@ arm_smmu_find_master_domain(struct arm_smmu_domain *smmu_domain,
list_for_each_entry(master_domain, &smmu_domain->devices,
devices_elm) {
if (master_domain->master == master &&
- master_domain->ssid == ssid)
+ master_domain->ssid == ssid &&
+ master_domain->nested_ats_flush == nested_ats_flush)
return master_domain;
}
return NULL;
@@ -2624,6 +2670,8 @@ to_smmu_domain_devices(struct iommu_domain *domain)
if ((domain->type & __IOMMU_DOMAIN_PAGING) ||
domain->type == IOMMU_DOMAIN_SVA)
return to_smmu_domain(domain);
+ if (domain->type == IOMMU_DOMAIN_NESTED)
+ return to_smmu_nested_domain(domain)->vsmmu->s2_parent;
return NULL;
}
@@ -2633,13 +2681,18 @@ static void arm_smmu_remove_master_domain(struct arm_smmu_master *master,
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain_devices(domain);
struct arm_smmu_master_domain *master_domain;
+ bool nested_ats_flush = false;
unsigned long flags;
if (!smmu_domain)
return;
+ if (domain->type == IOMMU_DOMAIN_NESTED)
+ nested_ats_flush = to_smmu_nested_domain(domain)->enable_ats;
+
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
- master_domain = arm_smmu_find_master_domain(smmu_domain, master, ssid);
+ master_domain = arm_smmu_find_master_domain(smmu_domain, master, ssid,
+ nested_ats_flush);
if (master_domain) {
list_del(&master_domain->devices_elm);
kfree(master_domain);
@@ -2649,16 +2702,6 @@ static void arm_smmu_remove_master_domain(struct arm_smmu_master *master,
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
}
-struct arm_smmu_attach_state {
- /* Inputs */
- struct iommu_domain *old_domain;
- struct arm_smmu_master *master;
- bool cd_needs_ats;
- ioasid_t ssid;
- /* Resulting state */
- bool ats_enabled;
-};
-
/*
* Start the sequence to attach a domain to a master. The sequence contains three
* steps:
@@ -2679,8 +2722,8 @@ struct arm_smmu_attach_state {
* new_domain can be a non-paging domain. In this case ATS will not be enabled,
* and invalidations won't be tracked.
*/
-static int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
- struct iommu_domain *new_domain)
+int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
+ struct iommu_domain *new_domain)
{
struct arm_smmu_master *master = state->master;
struct arm_smmu_master_domain *master_domain;
@@ -2706,7 +2749,8 @@ static int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
* enabled if we have arm_smmu_domain, those always have page
* tables.
*/
- state->ats_enabled = arm_smmu_ats_supported(master);
+ state->ats_enabled = !state->disable_ats &&
+ arm_smmu_ats_supported(master);
}
if (smmu_domain) {
@@ -2715,6 +2759,9 @@ static int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
return -ENOMEM;
master_domain->master = master;
master_domain->ssid = state->ssid;
+ if (new_domain->type == IOMMU_DOMAIN_NESTED)
+ master_domain->nested_ats_flush =
+ to_smmu_nested_domain(new_domain)->enable_ats;
/*
* During prepare we want the current smmu_domain and new
@@ -2731,6 +2778,14 @@ static int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
* one of them.
*/
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+ if (smmu_domain->enforce_cache_coherency &&
+ !arm_smmu_master_canwbs(master)) {
+ spin_unlock_irqrestore(&smmu_domain->devices_lock,
+ flags);
+ kfree(master_domain);
+ return -EINVAL;
+ }
+
if (state->ats_enabled)
atomic_inc(&smmu_domain->nr_ats_masters);
list_add(&master_domain->devices_elm, &smmu_domain->devices);
@@ -2754,7 +2809,7 @@ static int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
* completes synchronizing the PCI device's ATC and finishes manipulating the
* smmu_domain->devices list.
*/
-static void arm_smmu_attach_commit(struct arm_smmu_attach_state *state)
+void arm_smmu_attach_commit(struct arm_smmu_attach_state *state)
{
struct arm_smmu_master *master = state->master;
@@ -2856,7 +2911,8 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
}
static int arm_smmu_s1_set_dev_pasid(struct iommu_domain *domain,
- struct device *dev, ioasid_t id)
+ struct device *dev, ioasid_t id,
+ struct iommu_domain *old)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
@@ -2882,7 +2938,7 @@ static int arm_smmu_s1_set_dev_pasid(struct iommu_domain *domain,
*/
arm_smmu_make_s1_cd(&target_cd, master, smmu_domain);
return arm_smmu_set_pasid(master, to_smmu_domain(domain), id,
- &target_cd);
+ &target_cd, old);
}
static void arm_smmu_update_ste(struct arm_smmu_master *master,
@@ -2912,16 +2968,13 @@ static void arm_smmu_update_ste(struct arm_smmu_master *master,
int arm_smmu_set_pasid(struct arm_smmu_master *master,
struct arm_smmu_domain *smmu_domain, ioasid_t pasid,
- struct arm_smmu_cd *cd)
+ struct arm_smmu_cd *cd, struct iommu_domain *old)
{
struct iommu_domain *sid_domain = iommu_get_domain_for_dev(master->dev);
struct arm_smmu_attach_state state = {
.master = master,
- /*
- * For now the core code prevents calling this when a domain is
- * already attached, no need to set old_domain.
- */
.ssid = pasid,
+ .old_domain = old,
};
struct arm_smmu_cd *cdptr;
int ret;
@@ -3079,24 +3132,37 @@ static struct iommu_domain arm_smmu_blocked_domain = {
};
static struct iommu_domain *
-arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+arm_smmu_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
{
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
- const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
+ const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
+ IOMMU_HWPT_ALLOC_PASID |
+ IOMMU_HWPT_ALLOC_NEST_PARENT;
struct arm_smmu_domain *smmu_domain;
int ret;
if (flags & ~PAGING_FLAGS)
return ERR_PTR(-EOPNOTSUPP);
- if (parent || user_data)
+ if (user_data)
return ERR_PTR(-EOPNOTSUPP);
+ if (flags & IOMMU_HWPT_ALLOC_PASID)
+ return arm_smmu_domain_alloc_paging(dev);
+
smmu_domain = arm_smmu_domain_alloc();
if (IS_ERR(smmu_domain))
return ERR_CAST(smmu_domain);
+ if (flags & IOMMU_HWPT_ALLOC_NEST_PARENT) {
+ if (!(master->smmu->features & ARM_SMMU_FEAT_NESTING)) {
+ ret = -EOPNOTSUPP;
+ goto err_free;
+ }
+ smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
+ smmu_domain->nest_parent = true;
+ }
+
smmu_domain->domain.type = IOMMU_DOMAIN_UNMANAGED;
smmu_domain->domain.ops = arm_smmu_ops.default_domain_ops;
ret = arm_smmu_domain_finalise(smmu_domain, master->smmu, flags);
@@ -3378,21 +3444,6 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
return group;
}
-static int arm_smmu_enable_nesting(struct iommu_domain *domain)
-{
- struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
- int ret = 0;
-
- mutex_lock(&smmu_domain->init_mutex);
- if (smmu_domain->smmu)
- ret = -EPERM;
- else
- smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
- mutex_unlock(&smmu_domain->init_mutex);
-
- return ret;
-}
-
static int arm_smmu_of_xlate(struct device *dev,
const struct of_phandle_args *args)
{
@@ -3491,9 +3542,10 @@ static struct iommu_ops arm_smmu_ops = {
.identity_domain = &arm_smmu_identity_domain,
.blocked_domain = &arm_smmu_blocked_domain,
.capable = arm_smmu_capable,
+ .hw_info = arm_smmu_hw_info,
.domain_alloc_paging = arm_smmu_domain_alloc_paging,
.domain_alloc_sva = arm_smmu_sva_domain_alloc,
- .domain_alloc_user = arm_smmu_domain_alloc_user,
+ .domain_alloc_paging_flags = arm_smmu_domain_alloc_paging_flags,
.probe_device = arm_smmu_probe_device,
.release_device = arm_smmu_release_device,
.device_group = arm_smmu_device_group,
@@ -3504,17 +3556,19 @@ static struct iommu_ops arm_smmu_ops = {
.dev_disable_feat = arm_smmu_dev_disable_feature,
.page_response = arm_smmu_page_response,
.def_domain_type = arm_smmu_def_domain_type,
+ .viommu_alloc = arm_vsmmu_alloc,
+ .user_pasid_table = 1,
.pgsize_bitmap = -1UL, /* Restricted during device attach */
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
.attach_dev = arm_smmu_attach_dev,
+ .enforce_cache_coherency = arm_smmu_enforce_cache_coherency,
.set_dev_pasid = arm_smmu_s1_set_dev_pasid,
.map_pages = arm_smmu_map_pages,
.unmap_pages = arm_smmu_unmap_pages,
.flush_iotlb_all = arm_smmu_flush_iotlb_all,
.iotlb_sync = arm_smmu_iotlb_sync,
.iova_to_phys = arm_smmu_iova_to_phys,
- .enable_nesting = arm_smmu_enable_nesting,
.free = arm_smmu_domain_free_paging,
}
};
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 1e9952ca989f..0107d3f333a1 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -10,6 +10,7 @@
#include <linux/bitfield.h>
#include <linux/iommu.h>
+#include <linux/iommufd.h>
#include <linux/kernel.h>
#include <linux/mmzone.h>
#include <linux/sizes.h>
@@ -57,6 +58,7 @@ struct arm_smmu_device;
#define IDR1_SIDSIZE GENMASK(5, 0)
#define ARM_SMMU_IDR3 0xc
+#define IDR3_FWB (1 << 8)
#define IDR3_RIL (1 << 10)
#define ARM_SMMU_IDR5 0x14
@@ -81,6 +83,8 @@ struct arm_smmu_device;
#define IIDR_REVISION GENMASK(15, 12)
#define IIDR_IMPLEMENTER GENMASK(11, 0)
+#define ARM_SMMU_AIDR 0x1C
+
#define ARM_SMMU_CR0 0x20
#define CR0_ATSCHK (1 << 4)
#define CR0_CMDQEN (1 << 3)
@@ -241,6 +245,7 @@ static inline u32 arm_smmu_strtab_l2_idx(u32 sid)
#define STRTAB_STE_0_CFG_BYPASS 4
#define STRTAB_STE_0_CFG_S1_TRANS 5
#define STRTAB_STE_0_CFG_S2_TRANS 6
+#define STRTAB_STE_0_CFG_NESTED 7
#define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4)
#define STRTAB_STE_0_S1FMT_LINEAR 0
@@ -261,6 +266,7 @@ static inline u32 arm_smmu_strtab_l2_idx(u32 sid)
#define STRTAB_STE_1_S1COR GENMASK_ULL(5, 4)
#define STRTAB_STE_1_S1CSH GENMASK_ULL(7, 6)
+#define STRTAB_STE_1_S2FWB (1UL << 25)
#define STRTAB_STE_1_S1STALLD (1UL << 27)
#define STRTAB_STE_1_EATS GENMASK_ULL(29, 28)
@@ -292,6 +298,15 @@ static inline u32 arm_smmu_strtab_l2_idx(u32 sid)
#define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4)
+/* These bits can be controlled by userspace for STRTAB_STE_0_CFG_NESTED */
+#define STRTAB_STE_0_NESTING_ALLOWED \
+ cpu_to_le64(STRTAB_STE_0_V | STRTAB_STE_0_CFG | STRTAB_STE_0_S1FMT | \
+ STRTAB_STE_0_S1CTXPTR_MASK | STRTAB_STE_0_S1CDMAX)
+#define STRTAB_STE_1_NESTING_ALLOWED \
+ cpu_to_le64(STRTAB_STE_1_S1DSS | STRTAB_STE_1_S1CIR | \
+ STRTAB_STE_1_S1COR | STRTAB_STE_1_S1CSH | \
+ STRTAB_STE_1_S1STALLD | STRTAB_STE_1_EATS)
+
/*
* Context descriptors.
*
@@ -511,8 +526,10 @@ struct arm_smmu_cmdq_ent {
};
} cfgi;
+ #define CMDQ_OP_TLBI_NH_ALL 0x10
#define CMDQ_OP_TLBI_NH_ASID 0x11
#define CMDQ_OP_TLBI_NH_VA 0x12
+ #define CMDQ_OP_TLBI_NH_VAA 0x13
#define CMDQ_OP_TLBI_EL2_ALL 0x20
#define CMDQ_OP_TLBI_EL2_ASID 0x21
#define CMDQ_OP_TLBI_EL2_VA 0x22
@@ -726,6 +743,7 @@ struct arm_smmu_device {
#define ARM_SMMU_FEAT_ATTR_TYPES_OVR (1 << 20)
#define ARM_SMMU_FEAT_HA (1 << 21)
#define ARM_SMMU_FEAT_HD (1 << 22)
+#define ARM_SMMU_FEAT_S2FWB (1 << 23)
u32 features;
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
@@ -811,10 +829,20 @@ struct arm_smmu_domain {
/* List of struct arm_smmu_master_domain */
struct list_head devices;
spinlock_t devices_lock;
+ bool enforce_cache_coherency : 1;
+ bool nest_parent : 1;
struct mmu_notifier mmu_notifier;
};
+struct arm_smmu_nested_domain {
+ struct iommu_domain domain;
+ struct arm_vsmmu *vsmmu;
+ bool enable_ats : 1;
+
+ __le64 ste[2];
+};
+
/* The following are exposed for testing purposes. */
struct arm_smmu_entry_writer_ops;
struct arm_smmu_entry_writer {
@@ -827,21 +855,22 @@ struct arm_smmu_entry_writer_ops {
void (*sync)(struct arm_smmu_entry_writer *writer);
};
+void arm_smmu_make_abort_ste(struct arm_smmu_ste *target);
+void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
+ struct arm_smmu_master *master,
+ struct arm_smmu_domain *smmu_domain,
+ bool ats_enabled);
+
#if IS_ENABLED(CONFIG_KUNIT)
void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits);
void arm_smmu_write_entry(struct arm_smmu_entry_writer *writer, __le64 *cur,
const __le64 *target);
void arm_smmu_get_cd_used(const __le64 *ent, __le64 *used_bits);
-void arm_smmu_make_abort_ste(struct arm_smmu_ste *target);
void arm_smmu_make_bypass_ste(struct arm_smmu_device *smmu,
struct arm_smmu_ste *target);
void arm_smmu_make_cdtable_ste(struct arm_smmu_ste *target,
struct arm_smmu_master *master, bool ats_enabled,
unsigned int s1dss);
-void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
- struct arm_smmu_master *master,
- struct arm_smmu_domain *smmu_domain,
- bool ats_enabled);
void arm_smmu_make_sva_cd(struct arm_smmu_cd *target,
struct arm_smmu_master *master, struct mm_struct *mm,
u16 asid);
@@ -851,6 +880,7 @@ struct arm_smmu_master_domain {
struct list_head devices_elm;
struct arm_smmu_master *master;
ioasid_t ssid;
+ bool nested_ats_flush : 1;
};
static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
@@ -858,6 +888,12 @@ static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
return container_of(dom, struct arm_smmu_domain, domain);
}
+static inline struct arm_smmu_nested_domain *
+to_smmu_nested_domain(struct iommu_domain *dom)
+{
+ return container_of(dom, struct arm_smmu_nested_domain, domain);
+}
+
extern struct xarray arm_smmu_asid_xa;
extern struct mutex arm_smmu_asid_lock;
@@ -875,7 +911,7 @@ void arm_smmu_write_cd_entry(struct arm_smmu_master *master, int ssid,
int arm_smmu_set_pasid(struct arm_smmu_master *master,
struct arm_smmu_domain *smmu_domain, ioasid_t pasid,
- struct arm_smmu_cd *cd);
+ struct arm_smmu_cd *cd, struct iommu_domain *old);
void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid,
@@ -893,6 +929,33 @@ int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
int arm_smmu_cmdq_init(struct arm_smmu_device *smmu,
struct arm_smmu_cmdq *cmdq);
+static inline bool arm_smmu_master_canwbs(struct arm_smmu_master *master)
+{
+ return dev_iommu_fwspec_get(master->dev)->flags &
+ IOMMU_FWSPEC_PCI_RC_CANWBS;
+}
+
+struct arm_smmu_attach_state {
+ /* Inputs */
+ struct iommu_domain *old_domain;
+ struct arm_smmu_master *master;
+ bool cd_needs_ats;
+ bool disable_ats;
+ ioasid_t ssid;
+ /* Resulting state */
+ bool ats_enabled;
+};
+
+int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
+ struct iommu_domain *new_domain);
+void arm_smmu_attach_commit(struct arm_smmu_attach_state *state);
+void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master,
+ const struct arm_smmu_ste *target);
+
+int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
+ struct arm_smmu_cmdq *cmdq, u64 *cmds, int n,
+ bool sync);
+
#ifdef CONFIG_ARM_SMMU_V3_SVA
bool arm_smmu_sva_supported(struct arm_smmu_device *smmu);
bool arm_smmu_master_sva_supported(struct arm_smmu_master *master);
@@ -949,4 +1012,23 @@ tegra241_cmdqv_probe(struct arm_smmu_device *smmu)
return ERR_PTR(-ENODEV);
}
#endif /* CONFIG_TEGRA241_CMDQV */
+
+struct arm_vsmmu {
+ struct iommufd_viommu core;
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_domain *s2_parent;
+ u16 vmid;
+};
+
+#if IS_ENABLED(CONFIG_ARM_SMMU_V3_IOMMUFD)
+void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type);
+struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
+ struct iommu_domain *parent,
+ struct iommufd_ctx *ictx,
+ unsigned int viommu_type);
+#else
+#define arm_smmu_hw_info NULL
+#define arm_vsmmu_alloc NULL
+#endif /* CONFIG_ARM_SMMU_V3_IOMMUFD */
+
#endif /* _ARM_SMMU_V3_H */
diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
index fcd13d301fff..c8ec74f089f3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
@@ -509,7 +509,8 @@ static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
snprintf(name, 16, "vcmdq%u", vcmdq->idx);
- q->llq.max_n_shift = VCMDQ_LOG2SIZE_MAX;
+ /* Queue size, capped to ensure natural alignment */
+ q->llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, VCMDQ_LOG2SIZE_MAX);
/* Use the common helper to init the VCMDQ, and then... */
ret = arm_smmu_init_one_queue(smmu, q, vcmdq->page0,
@@ -800,7 +801,9 @@ out_fallback:
return 0;
}
-struct dentry *cmdqv_debugfs_dir;
+#ifdef CONFIG_IOMMU_DEBUGFS
+static struct dentry *cmdqv_debugfs_dir;
+#endif
static struct arm_smmu_device *
__tegra241_cmdqv_probe(struct arm_smmu_device *smmu, struct resource *res,
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 8321962b3714..ade4684c14c9 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1437,6 +1437,17 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
goto out_free;
} else {
smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
+
+ /*
+ * Defer probe if the relevant SMMU instance hasn't finished
+ * probing yet. This is a fragile hack and we'd ideally
+ * avoid this race in the core code. Until that's ironed
+ * out, however, this is the most pragmatic option on the
+ * table.
+ */
+ if (!smmu)
+ return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER,
+ "smmu dev has not bound yet\n"));
}
ret = -EINVAL;
@@ -1558,21 +1569,6 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
return group;
}
-static int arm_smmu_enable_nesting(struct iommu_domain *domain)
-{
- struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
- int ret = 0;
-
- mutex_lock(&smmu_domain->init_mutex);
- if (smmu_domain->smmu)
- ret = -EPERM;
- else
- smmu_domain->stage = ARM_SMMU_DOMAIN_NESTED;
- mutex_unlock(&smmu_domain->init_mutex);
-
- return ret;
-}
-
static int arm_smmu_set_pgtable_quirks(struct iommu_domain *domain,
unsigned long quirks)
{
@@ -1656,7 +1652,6 @@ static struct iommu_ops arm_smmu_ops = {
.flush_iotlb_all = arm_smmu_flush_iotlb_all,
.iotlb_sync = arm_smmu_iotlb_sync,
.iova_to_phys = arm_smmu_iova_to_phys,
- .enable_nesting = arm_smmu_enable_nesting,
.set_pgtable_quirks = arm_smmu_set_pgtable_quirks,
.free = arm_smmu_domain_free,
}
diff --git a/drivers/iommu/intel/Kconfig b/drivers/iommu/intel/Kconfig
index 88fd32a9323c..f2f538c70650 100644
--- a/drivers/iommu/intel/Kconfig
+++ b/drivers/iommu/intel/Kconfig
@@ -14,6 +14,7 @@ config INTEL_IOMMU
depends on PCI_MSI && ACPI && X86
select IOMMU_API
select IOMMU_IOVA
+ select IOMMU_IOPF
select IOMMUFD_DRIVER if IOMMUFD
select NEED_DMA_MAP_STATE
select DMAR_TABLE
@@ -50,7 +51,6 @@ config INTEL_IOMMU_SVM
depends on X86_64
select MMU_NOTIFIER
select IOMMU_SVA
- select IOMMU_IOPF
help
Shared Virtual Memory (SVM) provides a facility for devices
to access DMA resources through process address space by
diff --git a/drivers/iommu/intel/Makefile b/drivers/iommu/intel/Makefile
index c8beb0281559..d3bb0798092d 100644
--- a/drivers/iommu/intel/Makefile
+++ b/drivers/iommu/intel/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_DMAR_TABLE) += dmar.o
-obj-$(CONFIG_INTEL_IOMMU) += iommu.o pasid.o nested.o cache.o
+obj-$(CONFIG_INTEL_IOMMU) += iommu.o pasid.o nested.o cache.o prq.o
obj-$(CONFIG_DMAR_TABLE) += trace.o cap_audit.o
obj-$(CONFIG_DMAR_PERF) += perf.o
obj-$(CONFIG_INTEL_IOMMU_DEBUGFS) += debugfs.o
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index eaf862e8dea1..9f424acf474e 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -1060,7 +1060,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
err = iommu->seq_id;
goto error;
}
- sprintf(iommu->name, "dmar%d", iommu->seq_id);
+ snprintf(iommu->name, sizeof(iommu->name), "dmar%d", iommu->seq_id);
err = map_iommu(iommu, drhd);
if (err) {
@@ -1895,19 +1895,6 @@ void dmar_msi_write(int irq, struct msi_msg *msg)
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}
-void dmar_msi_read(int irq, struct msi_msg *msg)
-{
- struct intel_iommu *iommu = irq_get_handler_data(irq);
- int reg = dmar_msi_reg(iommu, irq);
- unsigned long flag;
-
- raw_spin_lock_irqsave(&iommu->register_lock, flag);
- msg->data = readl(iommu->reg + reg + 4);
- msg->address_lo = readl(iommu->reg + reg + 8);
- msg->address_hi = readl(iommu->reg + reg + 12);
- raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
u8 fault_reason, u32 pasid, u16 source_id,
unsigned long long addr)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index e860bc9439a2..7d0acb74d5a5 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -352,89 +352,6 @@ static bool iommu_paging_structure_coherency(struct intel_iommu *iommu)
ecap_smpwc(iommu->ecap) : ecap_coherent(iommu->ecap);
}
-static void domain_update_iommu_coherency(struct dmar_domain *domain)
-{
- struct iommu_domain_info *info;
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu;
- bool found = false;
- unsigned long i;
-
- domain->iommu_coherency = true;
- xa_for_each(&domain->iommu_array, i, info) {
- found = true;
- if (!iommu_paging_structure_coherency(info->iommu)) {
- domain->iommu_coherency = false;
- break;
- }
- }
- if (found)
- return;
-
- /* No hardware attached; use lowest common denominator */
- rcu_read_lock();
- for_each_active_iommu(iommu, drhd) {
- if (!iommu_paging_structure_coherency(iommu)) {
- domain->iommu_coherency = false;
- break;
- }
- }
- rcu_read_unlock();
-}
-
-static int domain_update_iommu_superpage(struct dmar_domain *domain,
- struct intel_iommu *skip)
-{
- struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu;
- int mask = 0x3;
-
- if (!intel_iommu_superpage)
- return 0;
-
- /* set iommu_superpage to the smallest common denominator */
- rcu_read_lock();
- for_each_active_iommu(iommu, drhd) {
- if (iommu != skip) {
- if (domain && domain->use_first_level) {
- if (!cap_fl1gp_support(iommu->cap))
- mask = 0x1;
- } else {
- mask &= cap_super_page_val(iommu->cap);
- }
-
- if (!mask)
- break;
- }
- }
- rcu_read_unlock();
-
- return fls(mask);
-}
-
-static int domain_update_device_node(struct dmar_domain *domain)
-{
- struct device_domain_info *info;
- int nid = NUMA_NO_NODE;
- unsigned long flags;
-
- spin_lock_irqsave(&domain->lock, flags);
- list_for_each_entry(info, &domain->devices, link) {
- /*
- * There could possibly be multiple device numa nodes as devices
- * within the same domain may sit behind different IOMMUs. There
- * isn't perfect answer in such situation, so we select first
- * come first served policy.
- */
- nid = dev_to_node(info->dev);
- if (nid != NUMA_NO_NODE)
- break;
- }
- spin_unlock_irqrestore(&domain->lock, flags);
-
- return nid;
-}
-
/* Return the super pagesize bitmap if supported. */
static unsigned long domain_super_pgsize_bitmap(struct dmar_domain *domain)
{
@@ -452,34 +369,6 @@ static unsigned long domain_super_pgsize_bitmap(struct dmar_domain *domain)
return bitmap;
}
-/* Some capabilities may be different across iommus */
-void domain_update_iommu_cap(struct dmar_domain *domain)
-{
- domain_update_iommu_coherency(domain);
- domain->iommu_superpage = domain_update_iommu_superpage(domain, NULL);
-
- /*
- * If RHSA is missing, we should default to the device numa domain
- * as fall back.
- */
- if (domain->nid == NUMA_NO_NODE)
- domain->nid = domain_update_device_node(domain);
-
- /*
- * First-level translation restricts the input-address to a
- * canonical address (i.e., address bits 63:N have the same
- * value as address bit [N-1], where N is 48-bits with 4-level
- * paging and 57-bits with 5-level paging). Hence, skip bit
- * [N-1].
- */
- if (domain->use_first_level)
- domain->domain.geometry.aperture_end = __DOMAIN_MAX_ADDR(domain->gaw - 1);
- else
- domain->domain.geometry.aperture_end = __DOMAIN_MAX_ADDR(domain->gaw);
-
- domain->domain.pgsize_bitmap |= domain_super_pgsize_bitmap(domain);
-}
-
struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
u8 devfn, int alloc)
{
@@ -707,14 +596,15 @@ static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn,
while (1) {
offset = pfn_level_offset(pfn, level);
pte = &parent[offset];
- if (!pte || (dma_pte_superpage(pte) || !dma_pte_present(pte))) {
- pr_info("PTE not present at level %d\n", level);
- break;
- }
pr_info("pte level: %d, pte value: 0x%016llx\n", level, pte->val);
- if (level == 1)
+ if (!dma_pte_present(pte)) {
+ pr_info("page table not present at level %d\n", level - 1);
+ break;
+ }
+
+ if (level == 1 || dma_pte_superpage(pte))
break;
parent = phys_to_virt(dma_pte_addr(pte));
@@ -737,11 +627,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
pr_info("Dump %s table entries for IOVA 0x%llx\n", iommu->name, addr);
/* root entry dump */
- rt_entry = &iommu->root_entry[bus];
- if (!rt_entry) {
- pr_info("root table entry is not present\n");
+ if (!iommu->root_entry) {
+ pr_info("root table is not present\n");
return;
}
+ rt_entry = &iommu->root_entry[bus];
if (sm_supported(iommu))
pr_info("scalable mode root entry: hi 0x%016llx, low 0x%016llx\n",
@@ -752,7 +642,7 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
/* context entry dump */
ctx_entry = iommu_context_addr(iommu, bus, devfn, 0);
if (!ctx_entry) {
- pr_info("context table entry is not present\n");
+ pr_info("context table is not present\n");
return;
}
@@ -761,17 +651,23 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
/* legacy mode does not require PASID entries */
if (!sm_supported(iommu)) {
+ if (!context_present(ctx_entry)) {
+ pr_info("legacy mode page table is not present\n");
+ return;
+ }
level = agaw_to_level(ctx_entry->hi & 7);
pgtable = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
goto pgtable_walk;
}
- /* get the pointer to pasid directory entry */
- dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
- if (!dir) {
- pr_info("pasid directory entry is not present\n");
+ if (!context_present(ctx_entry)) {
+ pr_info("pasid directory table is not present\n");
return;
}
+
+ /* get the pointer to pasid directory entry */
+ dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
+
/* For request-without-pasid, get the pasid from context entry */
if (intel_iommu_sm && pasid == IOMMU_PASID_INVALID)
pasid = IOMMU_NO_PASID;
@@ -783,7 +679,7 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
/* get the pointer to the pasid table entry */
entries = get_pasid_table_from_pde(pde);
if (!entries) {
- pr_info("pasid table entry is not present\n");
+ pr_info("pasid table is not present\n");
return;
}
index = pasid & PASID_PTE_MASK;
@@ -791,6 +687,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
for (i = 0; i < ARRAY_SIZE(pte->val); i++)
pr_info("pasid table entry[%d]: 0x%016llx\n", i, pte->val[i]);
+ if (!pasid_pte_is_present(pte)) {
+ pr_info("scalable mode page table is not present\n");
+ return;
+ }
+
if (pasid_pte_get_pgtt(pte) == PASID_ENTRY_PGTT_FL_ONLY) {
level = pte->val[2] & BIT_ULL(2) ? 5 : 4;
pgtable = phys_to_virt(pte->val[2] & VTD_PAGE_MASK);
@@ -1428,51 +1329,25 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
/* free context mapping */
free_context_table(iommu);
-#ifdef CONFIG_INTEL_IOMMU_SVM
- if (pasid_supported(iommu)) {
- if (ecap_prs(iommu->ecap))
- intel_svm_finish_prq(iommu);
- }
-#endif
+ if (ecap_prs(iommu->ecap))
+ intel_iommu_finish_prq(iommu);
}
/*
* Check and return whether first level is used by default for
* DMA translation.
*/
-static bool first_level_by_default(unsigned int type)
+static bool first_level_by_default(struct intel_iommu *iommu)
{
/* Only SL is available in legacy mode */
- if (!scalable_mode_support())
+ if (!sm_supported(iommu))
return false;
/* Only level (either FL or SL) is available, just use it */
- if (intel_cap_flts_sanity() ^ intel_cap_slts_sanity())
- return intel_cap_flts_sanity();
-
- /* Both levels are available, decide it based on domain type */
- return type != IOMMU_DOMAIN_UNMANAGED;
-}
+ if (ecap_flts(iommu->ecap) ^ ecap_slts(iommu->ecap))
+ return ecap_flts(iommu->ecap);
-static struct dmar_domain *alloc_domain(unsigned int type)
-{
- struct dmar_domain *domain;
-
- domain = kzalloc(sizeof(*domain), GFP_KERNEL);
- if (!domain)
- return NULL;
-
- domain->nid = NUMA_NO_NODE;
- if (first_level_by_default(type))
- domain->use_first_level = true;
- INIT_LIST_HEAD(&domain->devices);
- INIT_LIST_HEAD(&domain->dev_pasids);
- INIT_LIST_HEAD(&domain->cache_tags);
- spin_lock_init(&domain->lock);
- spin_lock_init(&domain->cache_lock);
- xa_init(&domain->iommu_array);
-
- return domain;
+ return true;
}
int domain_attach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
@@ -1514,7 +1389,6 @@ int domain_attach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
ret = xa_err(curr) ? : -EBUSY;
goto err_clear;
}
- domain_update_iommu_cap(domain);
spin_unlock(&iommu->lock);
return 0;
@@ -1540,26 +1414,11 @@ void domain_detach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
clear_bit(info->did, iommu->domain_ids);
xa_erase(&domain->iommu_array, iommu->seq_id);
domain->nid = NUMA_NO_NODE;
- domain_update_iommu_cap(domain);
kfree(info);
}
spin_unlock(&iommu->lock);
}
-static int guestwidth_to_adjustwidth(int gaw)
-{
- int agaw;
- int r = (gaw - 12) % 9;
-
- if (r == 0)
- agaw = gaw;
- else
- agaw = gaw + 9 - r;
- if (agaw > 64)
- agaw = 64;
- return agaw;
-}
-
static void domain_exit(struct dmar_domain *domain)
{
if (domain->pgd) {
@@ -1601,7 +1460,7 @@ static void copied_context_tear_down(struct intel_iommu *iommu,
if (did_old < cap_ndoms(iommu->cap)) {
iommu->flush.flush_context(iommu, did_old,
- (((u16)bus) << 8) | devfn,
+ PCI_DEVID(bus, devfn),
DMA_CCMD_MASK_NOBIT,
DMA_CCMD_DEVICE_INVL);
iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
@@ -1622,7 +1481,7 @@ static void context_present_cache_flush(struct intel_iommu *iommu, u16 did,
{
if (cap_caching_mode(iommu->cap)) {
iommu->flush.flush_context(iommu, 0,
- (((u16)bus) << 8) | devfn,
+ PCI_DEVID(bus, devfn),
DMA_CCMD_MASK_NOBIT,
DMA_CCMD_DEVICE_INVL);
iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
@@ -1641,7 +1500,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
int translation = CONTEXT_TT_MULTI_LEVEL;
struct dma_pte *pgd = domain->pgd;
struct context_entry *context;
- int agaw, ret;
+ int ret;
pr_debug("Set context mapping for %02x:%02x.%d\n",
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
@@ -1658,27 +1517,15 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
copied_context_tear_down(iommu, context, bus, devfn);
context_clear_entry(context);
-
context_set_domain_id(context, did);
- /*
- * Skip top levels of page tables for iommu which has
- * less agaw than default. Unnecessary for PT mode.
- */
- for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
- ret = -ENOMEM;
- pgd = phys_to_virt(dma_pte_addr(pgd));
- if (!dma_pte_present(pgd))
- goto out_unlock;
- }
-
if (info && info->ats_supported)
translation = CONTEXT_TT_DEV_IOTLB;
else
translation = CONTEXT_TT_MULTI_LEVEL;
context_set_address_root(context, virt_to_phys(pgd));
- context_set_address_width(context, agaw);
+ context_set_address_width(context, domain->agaw);
context_set_translation_type(context, translation);
context_set_fault_enable(context);
context_set_present(context);
@@ -1905,26 +1752,52 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
intel_context_flush_present(info, context, did, true);
}
+int __domain_setup_first_level(struct intel_iommu *iommu,
+ struct device *dev, ioasid_t pasid,
+ u16 did, pgd_t *pgd, int flags,
+ struct iommu_domain *old)
+{
+ if (!old)
+ return intel_pasid_setup_first_level(iommu, dev, pgd,
+ pasid, did, flags);
+ return intel_pasid_replace_first_level(iommu, dev, pgd, pasid, did,
+ iommu_domain_did(old, iommu),
+ flags);
+}
+
+static int domain_setup_second_level(struct intel_iommu *iommu,
+ struct dmar_domain *domain,
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
+{
+ if (!old)
+ return intel_pasid_setup_second_level(iommu, domain,
+ dev, pasid);
+ return intel_pasid_replace_second_level(iommu, domain, dev,
+ iommu_domain_did(old, iommu),
+ pasid);
+}
+
+static int domain_setup_passthrough(struct intel_iommu *iommu,
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
+{
+ if (!old)
+ return intel_pasid_setup_pass_through(iommu, dev, pasid);
+ return intel_pasid_replace_pass_through(iommu, dev,
+ iommu_domain_did(old, iommu),
+ pasid);
+}
+
static int domain_setup_first_level(struct intel_iommu *iommu,
struct dmar_domain *domain,
struct device *dev,
- u32 pasid)
+ u32 pasid, struct iommu_domain *old)
{
struct dma_pte *pgd = domain->pgd;
- int agaw, level;
- int flags = 0;
+ int level, flags = 0;
- /*
- * Skip top levels of page tables for iommu which has
- * less agaw than default. Unnecessary for PT mode.
- */
- for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
- pgd = phys_to_virt(dma_pte_addr(pgd));
- if (!dma_pte_present(pgd))
- return -ENOMEM;
- }
-
- level = agaw_to_level(agaw);
+ level = agaw_to_level(domain->agaw);
if (level != 4 && level != 5)
return -EINVAL;
@@ -1934,15 +1807,9 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
if (domain->force_snooping)
flags |= PASID_FLAG_PAGE_SNOOP;
- return intel_pasid_setup_first_level(iommu, dev, (pgd_t *)pgd, pasid,
- domain_id_iommu(domain, iommu),
- flags);
-}
-
-static bool dev_is_real_dma_subdevice(struct device *dev)
-{
- return dev && dev_is_pci(dev) &&
- pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev);
+ return __domain_setup_first_level(iommu, dev, pasid,
+ domain_id_iommu(domain, iommu),
+ (pgd_t *)pgd, flags, old);
}
static int dmar_domain_attach_device(struct dmar_domain *domain,
@@ -1968,9 +1835,11 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
if (!sm_supported(iommu))
ret = domain_context_mapping(domain, dev);
else if (domain->use_first_level)
- ret = domain_setup_first_level(iommu, domain, dev, IOMMU_NO_PASID);
+ ret = domain_setup_first_level(iommu, domain, dev,
+ IOMMU_NO_PASID, NULL);
else
- ret = intel_pasid_setup_second_level(iommu, domain, dev, IOMMU_NO_PASID);
+ ret = domain_setup_second_level(iommu, domain, dev,
+ IOMMU_NO_PASID, NULL);
if (ret)
goto out_block_translation;
@@ -2354,19 +2223,18 @@ static int __init init_dmars(void)
iommu_flush_write_buffer(iommu);
-#ifdef CONFIG_INTEL_IOMMU_SVM
- if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
+ if (ecap_prs(iommu->ecap)) {
/*
* Call dmar_alloc_hwirq() with dmar_global_lock held,
* could cause possible lock race condition.
*/
up_write(&dmar_global_lock);
- ret = intel_svm_enable_prq(iommu);
+ ret = intel_iommu_enable_prq(iommu);
down_write(&dmar_global_lock);
if (ret)
goto free_iommu;
}
-#endif
+
ret = dmar_set_interrupt(iommu);
if (ret)
goto free_iommu;
@@ -2746,20 +2614,13 @@ int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg)
static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
{
- int sp, ret;
struct intel_iommu *iommu = dmaru->iommu;
+ int ret;
ret = intel_cap_audit(CAP_AUDIT_HOTPLUG_DMAR, iommu);
if (ret)
goto out;
- sp = domain_update_iommu_superpage(NULL, iommu) - 1;
- if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
- pr_warn("%s: Doesn't support large page.\n",
- iommu->name);
- return -ENXIO;
- }
-
/*
* Disable translation if already enabled prior to OS handover.
*/
@@ -2786,13 +2647,12 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
intel_iommu_init_qi(iommu);
iommu_flush_write_buffer(iommu);
-#ifdef CONFIG_INTEL_IOMMU_SVM
- if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
- ret = intel_svm_enable_prq(iommu);
+ if (ecap_prs(iommu->ecap)) {
+ ret = intel_iommu_enable_prq(iommu);
if (ret)
goto disable_iommu;
}
-#endif
+
ret = dmar_set_interrupt(iommu);
if (ret)
goto disable_iommu;
@@ -3288,7 +3148,7 @@ int __init intel_iommu_init(void)
* the virtual and physical IOMMU page-tables.
*/
if (cap_caching_mode(iommu->cap) &&
- !first_level_by_default(IOMMU_DOMAIN_DMA)) {
+ !first_level_by_default(iommu)) {
pr_info_once("IOMMU batching disallowed due to virtualization\n");
iommu_set_dma_strict();
}
@@ -3381,27 +3241,6 @@ void device_block_translation(struct device *dev)
info->domain = NULL;
}
-static int md_domain_init(struct dmar_domain *domain, int guest_width)
-{
- int adjust_width;
-
- /* calculate AGAW */
- domain->gaw = guest_width;
- adjust_width = guestwidth_to_adjustwidth(guest_width);
- domain->agaw = width_to_agaw(adjust_width);
-
- domain->iommu_coherency = false;
- domain->iommu_superpage = 0;
- domain->max_addr = 0;
-
- /* always allocate the top pgd */
- domain->pgd = iommu_alloc_page_node(domain->nid, GFP_ATOMIC);
- if (!domain->pgd)
- return -ENOMEM;
- domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
- return 0;
-}
-
static int blocking_domain_attach_dev(struct iommu_domain *domain,
struct device *dev)
{
@@ -3488,43 +3327,9 @@ static struct dmar_domain *paging_domain_alloc(struct device *dev, bool first_st
return domain;
}
-static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
-{
- struct dmar_domain *dmar_domain;
- struct iommu_domain *domain;
-
- switch (type) {
- case IOMMU_DOMAIN_DMA:
- case IOMMU_DOMAIN_UNMANAGED:
- dmar_domain = alloc_domain(type);
- if (!dmar_domain) {
- pr_err("Can't allocate dmar_domain\n");
- return NULL;
- }
- if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
- pr_err("Domain initialization failed\n");
- domain_exit(dmar_domain);
- return NULL;
- }
-
- domain = &dmar_domain->domain;
- domain->geometry.aperture_start = 0;
- domain->geometry.aperture_end =
- __DOMAIN_MAX_ADDR(dmar_domain->gaw);
- domain->geometry.force_aperture = true;
-
- return domain;
- default:
- return NULL;
- }
-
- return NULL;
-}
-
static struct iommu_domain *
-intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+intel_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
@@ -3532,24 +3337,31 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
struct intel_iommu *iommu = info->iommu;
struct dmar_domain *dmar_domain;
struct iommu_domain *domain;
-
- /* Must be NESTING domain */
- if (parent) {
- if (!nested_supported(iommu) || flags)
- return ERR_PTR(-EOPNOTSUPP);
- return intel_nested_domain_alloc(parent, user_data);
- }
+ bool first_stage;
if (flags &
- (~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING)))
+ (~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING
+ | IOMMU_HWPT_FAULT_ID_VALID)))
return ERR_PTR(-EOPNOTSUPP);
if (nested_parent && !nested_supported(iommu))
return ERR_PTR(-EOPNOTSUPP);
if (user_data || (dirty_tracking && !ssads_supported(iommu)))
return ERR_PTR(-EOPNOTSUPP);
- /* Do not use first stage for user domain translation. */
- dmar_domain = paging_domain_alloc(dev, false);
+ /*
+ * Always allocate the guest compatible page table unless
+ * IOMMU_HWPT_ALLOC_NEST_PARENT or IOMMU_HWPT_ALLOC_DIRTY_TRACKING
+ * is specified.
+ */
+ if (nested_parent || dirty_tracking) {
+ if (!sm_supported(iommu) || !ecap_slts(iommu->ecap))
+ return ERR_PTR(-EOPNOTSUPP);
+ first_stage = false;
+ } else {
+ first_stage = first_level_by_default(iommu);
+ }
+
+ dmar_domain = paging_domain_alloc(dev, first_stage);
if (IS_ERR(dmar_domain))
return ERR_CAST(dmar_domain);
domain = &dmar_domain->domain;
@@ -3583,42 +3395,41 @@ static void intel_iommu_domain_free(struct iommu_domain *domain)
domain_exit(dmar_domain);
}
-int prepare_domain_attach_device(struct iommu_domain *domain,
- struct device *dev)
+int paging_domain_compatible(struct iommu_domain *domain, struct device *dev)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
struct intel_iommu *iommu = info->iommu;
int addr_width;
+ if (WARN_ON_ONCE(!(domain->type & __IOMMU_DOMAIN_PAGING)))
+ return -EPERM;
+
if (dmar_domain->force_snooping && !ecap_sc_support(iommu->ecap))
return -EINVAL;
if (domain->dirty_ops && !ssads_supported(iommu))
return -EINVAL;
+ if (dmar_domain->iommu_coherency !=
+ iommu_paging_structure_coherency(iommu))
+ return -EINVAL;
+
+ if (dmar_domain->iommu_superpage !=
+ iommu_superpage_capability(iommu, dmar_domain->use_first_level))
+ return -EINVAL;
+
+ if (dmar_domain->use_first_level &&
+ (!sm_supported(iommu) || !ecap_flts(iommu->ecap)))
+ return -EINVAL;
+
/* check if this iommu agaw is sufficient for max mapped address */
addr_width = agaw_to_width(iommu->agaw);
if (addr_width > cap_mgaw(iommu->cap))
addr_width = cap_mgaw(iommu->cap);
- if (dmar_domain->max_addr > (1LL << addr_width))
+ if (dmar_domain->gaw > addr_width || dmar_domain->agaw > iommu->agaw)
return -EINVAL;
- dmar_domain->gaw = addr_width;
-
- /*
- * Knock out extra levels of page tables if necessary
- */
- while (iommu->agaw < dmar_domain->agaw) {
- struct dma_pte *pte;
-
- pte = dmar_domain->pgd;
- if (dma_pte_present(pte)) {
- dmar_domain->pgd = phys_to_virt(dma_pte_addr(pte));
- iommu_free_page(pte);
- }
- dmar_domain->agaw--;
- }
if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev) &&
context_copied(iommu, info->bus, info->devfn))
@@ -3634,7 +3445,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
device_block_translation(dev);
- ret = prepare_domain_attach_device(domain, dev);
+ ret = paging_domain_compatible(domain, dev);
if (ret)
return ret;
@@ -4252,8 +4063,8 @@ static int intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
return 0;
}
-static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
- struct iommu_domain *domain)
+void domain_remove_dev_pasid(struct iommu_domain *domain,
+ struct device *dev, ioasid_t pasid)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
struct dev_pasid_info *curr, *dev_pasid = NULL;
@@ -4261,10 +4072,12 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
struct dmar_domain *dmar_domain;
unsigned long flags;
- if (domain->type == IOMMU_DOMAIN_IDENTITY) {
- intel_pasid_tear_down_entry(iommu, dev, pasid, false);
+ if (!domain)
+ return;
+
+ /* Identity domain has no meta data for pasid. */
+ if (domain->type == IOMMU_DOMAIN_IDENTITY)
return;
- }
dmar_domain = to_dmar_domain(domain);
spin_lock_irqsave(&dmar_domain->lock, flags);
@@ -4282,12 +4095,20 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
domain_detach_iommu(dmar_domain, iommu);
intel_iommu_debugfs_remove_dev_pasid(dev_pasid);
kfree(dev_pasid);
- intel_pasid_tear_down_entry(iommu, dev, pasid, false);
- intel_drain_pasid_prq(dev, pasid);
}
-static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
- struct device *dev, ioasid_t pasid)
+static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
+ struct iommu_domain *domain)
+{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+
+ intel_pasid_tear_down_entry(info->iommu, dev, pasid, false);
+ domain_remove_dev_pasid(domain, dev, pasid);
+}
+
+struct dev_pasid_info *
+domain_add_dev_pasid(struct iommu_domain *domain,
+ struct device *dev, ioasid_t pasid)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
@@ -4296,22 +4117,9 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
unsigned long flags;
int ret;
- if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
- return -EOPNOTSUPP;
-
- if (domain->dirty_ops)
- return -EINVAL;
-
- if (context_copied(iommu, info->bus, info->devfn))
- return -EBUSY;
-
- ret = prepare_domain_attach_device(domain, dev);
- if (ret)
- return ret;
-
dev_pasid = kzalloc(sizeof(*dev_pasid), GFP_KERNEL);
if (!dev_pasid)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
ret = domain_attach_iommu(dmar_domain, iommu);
if (ret)
@@ -4321,31 +4129,67 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
if (ret)
goto out_detach_iommu;
- if (dmar_domain->use_first_level)
- ret = domain_setup_first_level(iommu, dmar_domain,
- dev, pasid);
- else
- ret = intel_pasid_setup_second_level(iommu, dmar_domain,
- dev, pasid);
- if (ret)
- goto out_unassign_tag;
-
dev_pasid->dev = dev;
dev_pasid->pasid = pasid;
spin_lock_irqsave(&dmar_domain->lock, flags);
list_add(&dev_pasid->link_domain, &dmar_domain->dev_pasids);
spin_unlock_irqrestore(&dmar_domain->lock, flags);
- if (domain->type & __IOMMU_DOMAIN_PAGING)
- intel_iommu_debugfs_create_dev_pasid(dev_pasid);
-
- return 0;
-out_unassign_tag:
- cache_tag_unassign_domain(dmar_domain, dev, pasid);
+ return dev_pasid;
out_detach_iommu:
domain_detach_iommu(dmar_domain, iommu);
out_free:
kfree(dev_pasid);
+ return ERR_PTR(ret);
+}
+
+static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
+{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ struct dmar_domain *dmar_domain = to_dmar_domain(domain);
+ struct intel_iommu *iommu = info->iommu;
+ struct dev_pasid_info *dev_pasid;
+ int ret;
+
+ if (WARN_ON_ONCE(!(domain->type & __IOMMU_DOMAIN_PAGING)))
+ return -EINVAL;
+
+ if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
+ return -EOPNOTSUPP;
+
+ if (domain->dirty_ops)
+ return -EINVAL;
+
+ if (context_copied(iommu, info->bus, info->devfn))
+ return -EBUSY;
+
+ ret = paging_domain_compatible(domain, dev);
+ if (ret)
+ return ret;
+
+ dev_pasid = domain_add_dev_pasid(domain, dev, pasid);
+ if (IS_ERR(dev_pasid))
+ return PTR_ERR(dev_pasid);
+
+ if (dmar_domain->use_first_level)
+ ret = domain_setup_first_level(iommu, dmar_domain,
+ dev, pasid, old);
+ else
+ ret = domain_setup_second_level(iommu, dmar_domain,
+ dev, pasid, old);
+ if (ret)
+ goto out_remove_dev_pasid;
+
+ domain_remove_dev_pasid(old, dev, pasid);
+
+ intel_iommu_debugfs_create_dev_pasid(dev_pasid);
+
+ return 0;
+
+out_remove_dev_pasid:
+ domain_remove_dev_pasid(domain, dev, pasid);
return ret;
}
@@ -4573,15 +4417,22 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device
}
static int identity_domain_set_dev_pasid(struct iommu_domain *domain,
- struct device *dev, ioasid_t pasid)
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
struct intel_iommu *iommu = info->iommu;
+ int ret;
if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
return -EOPNOTSUPP;
- return intel_pasid_setup_pass_through(iommu, dev, pasid);
+ ret = domain_setup_passthrough(iommu, dev, pasid, old);
+ if (ret)
+ return ret;
+
+ domain_remove_dev_pasid(old, dev, pasid);
+ return 0;
}
static struct iommu_domain identity_domain = {
@@ -4592,15 +4443,31 @@ static struct iommu_domain identity_domain = {
},
};
+static struct iommu_domain *intel_iommu_domain_alloc_paging(struct device *dev)
+{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ struct intel_iommu *iommu = info->iommu;
+ struct dmar_domain *dmar_domain;
+ bool first_stage;
+
+ first_stage = first_level_by_default(iommu);
+ dmar_domain = paging_domain_alloc(dev, first_stage);
+ if (IS_ERR(dmar_domain))
+ return ERR_CAST(dmar_domain);
+
+ return &dmar_domain->domain;
+}
+
const struct iommu_ops intel_iommu_ops = {
.blocked_domain = &blocking_domain,
.release_domain = &blocking_domain,
.identity_domain = &identity_domain,
.capable = intel_iommu_capable,
.hw_info = intel_iommu_hw_info,
- .domain_alloc = intel_iommu_domain_alloc,
- .domain_alloc_user = intel_iommu_domain_alloc_user,
+ .domain_alloc_paging_flags = intel_iommu_domain_alloc_paging_flags,
.domain_alloc_sva = intel_svm_domain_alloc,
+ .domain_alloc_paging = intel_iommu_domain_alloc_paging,
+ .domain_alloc_nested = intel_iommu_domain_alloc_nested,
.probe_device = intel_iommu_probe_device,
.release_device = intel_iommu_release_device,
.get_resv_regions = intel_iommu_get_resv_regions,
@@ -4611,9 +4478,7 @@ const struct iommu_ops intel_iommu_ops = {
.def_domain_type = device_def_domain_type,
.remove_dev_pasid = intel_iommu_remove_dev_pasid,
.pgsize_bitmap = SZ_4K,
-#ifdef CONFIG_INTEL_IOMMU_SVM
- .page_response = intel_svm_page_response,
-#endif
+ .page_response = intel_iommu_page_response,
.default_domain_ops = &(const struct iommu_domain_ops) {
.attach_dev = intel_iommu_attach_device,
.set_dev_pasid = intel_iommu_set_dev_pasid,
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 1497f3112b12..6ea7bbe26b19 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -22,6 +22,7 @@
#include <linux/bitfield.h>
#include <linux/xarray.h>
#include <linux/perf_event.h>
+#include <linux/pci.h>
#include <asm/cacheflush.h>
#include <asm/iommu.h>
@@ -653,8 +654,6 @@ struct dmar_domain {
struct {
/* parent page table which the user domain is nested on */
struct dmar_domain *s2_domain;
- /* user page table pointer (in GPA) */
- unsigned long s1_pgtbl;
/* page table attributes */
struct iommu_hwpt_vtd_s1 s1_cfg;
/* link to parent domain siblings */
@@ -720,7 +719,7 @@ struct intel_iommu {
int msagaw; /* max sagaw of this iommu */
unsigned int irq, pr_irq, perf_irq;
u16 segment; /* PCI segment# */
- unsigned char name[13]; /* Device Name */
+ unsigned char name[16]; /* Device Name */
#ifdef CONFIG_INTEL_IOMMU
unsigned long *domain_ids; /* bitmap of domains */
@@ -730,12 +729,10 @@ struct intel_iommu {
struct iommu_flush flush;
#endif
-#ifdef CONFIG_INTEL_IOMMU_SVM
struct page_req_dsc *prq;
unsigned char prq_name[16]; /* Name for PRQ interrupt */
unsigned long prq_seq_number;
struct completion prq_complete;
-#endif
struct iopf_queue *iopf_queue;
unsigned char iopfq_name[16];
/* Synchronization between fault report and iommu device release. */
@@ -810,6 +807,13 @@ static inline struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
return container_of(dom, struct dmar_domain, domain);
}
+/*
+ * Domain ID reserved for pasid entries programmed for first-level
+ * only and pass-through transfer modes.
+ */
+#define FLPT_DEFAULT_DID 1
+#define NUM_RESERVED_DID 2
+
/* Retrieve the domain ID which has allocated to the domain */
static inline u16
domain_id_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
@@ -820,6 +824,21 @@ domain_id_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
return info->did;
}
+static inline u16
+iommu_domain_did(struct iommu_domain *domain, struct intel_iommu *iommu)
+{
+ if (domain->type == IOMMU_DOMAIN_SVA ||
+ domain->type == IOMMU_DOMAIN_IDENTITY)
+ return FLPT_DEFAULT_DID;
+ return domain_id_iommu(to_dmar_domain(domain), iommu);
+}
+
+static inline bool dev_is_real_dma_subdevice(struct device *dev)
+{
+ return dev && dev_is_pci(dev) &&
+ pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev);
+}
+
/*
* 0: readable
* 1: writable
@@ -1230,15 +1249,26 @@ void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
int domain_attach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu);
void domain_detach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu);
void device_block_translation(struct device *dev);
-int prepare_domain_attach_device(struct iommu_domain *domain,
- struct device *dev);
-void domain_update_iommu_cap(struct dmar_domain *domain);
+int paging_domain_compatible(struct iommu_domain *domain, struct device *dev);
+
+struct dev_pasid_info *
+domain_add_dev_pasid(struct iommu_domain *domain,
+ struct device *dev, ioasid_t pasid);
+void domain_remove_dev_pasid(struct iommu_domain *domain,
+ struct device *dev, ioasid_t pasid);
+
+int __domain_setup_first_level(struct intel_iommu *iommu,
+ struct device *dev, ioasid_t pasid,
+ u16 did, pgd_t *pgd, int flags,
+ struct iommu_domain *old);
int dmar_ir_support(void);
void iommu_flush_write_buffer(struct intel_iommu *iommu);
-struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
- const struct iommu_user_data *user_data);
+struct iommu_domain *
+intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+ u32 flags,
+ const struct iommu_user_data *user_data);
struct device *device_rbtree_find(struct intel_iommu *iommu, u16 rid);
enum cache_tag_type {
@@ -1278,18 +1308,18 @@ void intel_context_flush_present(struct device_domain_info *info,
struct context_entry *context,
u16 did, bool affect_domains);
+int intel_iommu_enable_prq(struct intel_iommu *iommu);
+int intel_iommu_finish_prq(struct intel_iommu *iommu);
+void intel_iommu_page_response(struct device *dev, struct iopf_fault *evt,
+ struct iommu_page_response *msg);
+void intel_iommu_drain_pasid_prq(struct device *dev, u32 pasid);
+
#ifdef CONFIG_INTEL_IOMMU_SVM
void intel_svm_check(struct intel_iommu *iommu);
-int intel_svm_enable_prq(struct intel_iommu *iommu);
-int intel_svm_finish_prq(struct intel_iommu *iommu);
-void intel_svm_page_response(struct device *dev, struct iopf_fault *evt,
- struct iommu_page_response *msg);
struct iommu_domain *intel_svm_domain_alloc(struct device *dev,
struct mm_struct *mm);
-void intel_drain_pasid_prq(struct device *dev, u32 pasid);
#else
static inline void intel_svm_check(struct intel_iommu *iommu) {}
-static inline void intel_drain_pasid_prq(struct device *dev, u32 pasid) {}
static inline struct iommu_domain *intel_svm_domain_alloc(struct device *dev,
struct mm_struct *mm)
{
diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c
index 7a6d188e3bea..466c1412dd45 100644
--- a/drivers/iommu/intel/irq_remapping.c
+++ b/drivers/iommu/intel/irq_remapping.c
@@ -312,7 +312,7 @@ static int set_ioapic_sid(struct irte *irte, int apic)
for (i = 0; i < MAX_IO_APICS; i++) {
if (ir_ioapic[i].iommu && ir_ioapic[i].id == apic) {
- sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
+ sid = PCI_DEVID(ir_ioapic[i].bus, ir_ioapic[i].devfn);
break;
}
}
@@ -337,7 +337,7 @@ static int set_hpet_sid(struct irte *irte, u8 id)
for (i = 0; i < MAX_HPET_TBS; i++) {
if (ir_hpet[i].iommu && ir_hpet[i].id == id) {
- sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
+ sid = PCI_DEVID(ir_hpet[i].bus, ir_hpet[i].devfn);
break;
}
}
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index 433c58944401..aba92c00b427 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -40,7 +40,7 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
* The s2_domain will be used in nested translation, hence needs
* to ensure the s2_domain is compatible with this IOMMU.
*/
- ret = prepare_domain_attach_device(&dmar_domain->s2_domain->domain, dev);
+ ret = paging_domain_compatible(&dmar_domain->s2_domain->domain, dev);
if (ret) {
dev_err_ratelimited(dev, "s2 domain is not compatible\n");
return ret;
@@ -130,20 +130,77 @@ out:
return ret;
}
+static int domain_setup_nested(struct intel_iommu *iommu,
+ struct dmar_domain *domain,
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
+{
+ if (!old)
+ return intel_pasid_setup_nested(iommu, dev, pasid, domain);
+ return intel_pasid_replace_nested(iommu, dev, pasid,
+ iommu_domain_did(old, iommu),
+ domain);
+}
+
+static int intel_nested_set_dev_pasid(struct iommu_domain *domain,
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
+{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ struct dmar_domain *dmar_domain = to_dmar_domain(domain);
+ struct intel_iommu *iommu = info->iommu;
+ struct dev_pasid_info *dev_pasid;
+ int ret;
+
+ if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
+ return -EOPNOTSUPP;
+
+ if (context_copied(iommu, info->bus, info->devfn))
+ return -EBUSY;
+
+ ret = paging_domain_compatible(&dmar_domain->s2_domain->domain, dev);
+ if (ret)
+ return ret;
+
+ dev_pasid = domain_add_dev_pasid(domain, dev, pasid);
+ if (IS_ERR(dev_pasid))
+ return PTR_ERR(dev_pasid);
+
+ ret = domain_setup_nested(iommu, dmar_domain, dev, pasid, old);
+ if (ret)
+ goto out_remove_dev_pasid;
+
+ domain_remove_dev_pasid(old, dev, pasid);
+
+ return 0;
+
+out_remove_dev_pasid:
+ domain_remove_dev_pasid(domain, dev, pasid);
+ return ret;
+}
+
static const struct iommu_domain_ops intel_nested_domain_ops = {
.attach_dev = intel_nested_attach_dev,
+ .set_dev_pasid = intel_nested_set_dev_pasid,
.free = intel_nested_domain_free,
.cache_invalidate_user = intel_nested_cache_invalidate_user,
};
-struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+struct iommu_domain *
+intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+ u32 flags,
+ const struct iommu_user_data *user_data)
{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
struct dmar_domain *s2_domain = to_dmar_domain(parent);
+ struct intel_iommu *iommu = info->iommu;
struct iommu_hwpt_vtd_s1 vtd;
struct dmar_domain *domain;
int ret;
+ if (!nested_supported(iommu) || flags)
+ return ERR_PTR(-EOPNOTSUPP);
+
/* Must be nested domain */
if (user_data->type != IOMMU_HWPT_DATA_VTD_S1)
return ERR_PTR(-EOPNOTSUPP);
@@ -162,7 +219,6 @@ struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
domain->use_first_level = true;
domain->s2_domain = s2_domain;
- domain->s1_pgtbl = vtd.pgtbl_addr;
domain->s1_cfg = vtd;
domain->domain.ops = &intel_nested_domain_ops;
domain->domain.type = IOMMU_DOMAIN_NESTED;
diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index 2e5fa0a23299..0f2a926d3bd5 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -220,7 +220,7 @@ devtlb_invalidation_with_pasid(struct intel_iommu *iommu,
if (pci_dev_is_disconnected(to_pci_dev(dev)))
return;
- sid = info->bus << 8 | info->devfn;
+ sid = PCI_DEVID(info->bus, info->devfn);
qdep = info->ats_qdep;
pfsid = info->pfsid;
@@ -265,6 +265,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
devtlb_invalidation_with_pasid(iommu, dev, pasid);
+ intel_iommu_drain_pasid_prq(dev, pasid);
}
/*
@@ -287,9 +288,68 @@ static void pasid_flush_caches(struct intel_iommu *iommu,
}
/*
+ * This function is supposed to be used after caller updates the fields
+ * except for the SSADE and P bit of a pasid table entry. It does the
+ * below:
+ * - Flush cacheline if needed
+ * - Flush the caches per Table 28 â€Guidance to Software for Invalidations“
+ * of VT-d spec 5.0.
+ */
+static void intel_pasid_flush_present(struct intel_iommu *iommu,
+ struct device *dev,
+ u32 pasid, u16 did,
+ struct pasid_entry *pte)
+{
+ if (!ecap_coherent(iommu->ecap))
+ clflush_cache_range(pte, sizeof(*pte));
+
+ /*
+ * VT-d spec 5.0 table28 states guides for cache invalidation:
+ *
+ * - PASID-selective-within-Domain PASID-cache invalidation
+ * - PASID-selective PASID-based IOTLB invalidation
+ * - If (pasid is RID_PASID)
+ * - Global Device-TLB invalidation to affected functions
+ * Else
+ * - PASID-based Device-TLB invalidation (with S=1 and
+ * Addr[63:12]=0x7FFFFFFF_FFFFF) to affected functions
+ */
+ pasid_cache_invalidation_with_pasid(iommu, did, pasid);
+ qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+
+ devtlb_invalidation_with_pasid(iommu, dev, pasid);
+}
+
+/*
* Set up the scalable mode pasid table entry for first only
* translation type.
*/
+static void pasid_pte_config_first_level(struct intel_iommu *iommu,
+ struct pasid_entry *pte,
+ pgd_t *pgd, u16 did, int flags)
+{
+ lockdep_assert_held(&iommu->lock);
+
+ pasid_clear_entry(pte);
+
+ /* Setup the first level page table pointer: */
+ pasid_set_flptr(pte, (u64)__pa(pgd));
+
+ if (flags & PASID_FLAG_FL5LP)
+ pasid_set_flpm(pte, 1);
+
+ if (flags & PASID_FLAG_PAGE_SNOOP)
+ pasid_set_pgsnp(pte);
+
+ pasid_set_domain_id(pte, did);
+ pasid_set_address_width(pte, iommu->agaw);
+ pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+
+ /* Setup Present and PASID Granular Transfer Type: */
+ pasid_set_translation_type(pte, PASID_ENTRY_PGTT_FL_ONLY);
+ pasid_set_present(pte);
+}
+
int intel_pasid_setup_first_level(struct intel_iommu *iommu,
struct device *dev, pgd_t *pgd,
u32 pasid, u16 did, int flags)
@@ -320,53 +380,82 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
return -EBUSY;
}
- pasid_clear_entry(pte);
+ pasid_pte_config_first_level(iommu, pte, pgd, did, flags);
- /* Setup the first level page table pointer: */
- pasid_set_flptr(pte, (u64)__pa(pgd));
+ spin_unlock(&iommu->lock);
- if (flags & PASID_FLAG_FL5LP)
- pasid_set_flpm(pte, 1);
+ pasid_flush_caches(iommu, pte, pasid, did);
- if (flags & PASID_FLAG_PAGE_SNOOP)
- pasid_set_pgsnp(pte);
+ return 0;
+}
- pasid_set_domain_id(pte, did);
- pasid_set_address_width(pte, iommu->agaw);
- pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+int intel_pasid_replace_first_level(struct intel_iommu *iommu,
+ struct device *dev, pgd_t *pgd,
+ u32 pasid, u16 did, u16 old_did,
+ int flags)
+{
+ struct pasid_entry *pte, new_pte;
- /* Setup Present and PASID Granular Transfer Type: */
- pasid_set_translation_type(pte, PASID_ENTRY_PGTT_FL_ONLY);
- pasid_set_present(pte);
+ if (!ecap_flts(iommu->ecap)) {
+ pr_err("No first level translation support on %s\n",
+ iommu->name);
+ return -EINVAL;
+ }
+
+ if ((flags & PASID_FLAG_FL5LP) && !cap_fl5lp_support(iommu->cap)) {
+ pr_err("No 5-level paging support for first-level on %s\n",
+ iommu->name);
+ return -EINVAL;
+ }
+
+ pasid_pte_config_first_level(iommu, &new_pte, pgd, did, flags);
+
+ spin_lock(&iommu->lock);
+ pte = intel_pasid_get_entry(dev, pasid);
+ if (!pte) {
+ spin_unlock(&iommu->lock);
+ return -ENODEV;
+ }
+
+ if (!pasid_pte_is_present(pte)) {
+ spin_unlock(&iommu->lock);
+ return -EINVAL;
+ }
+
+ WARN_ON(old_did != pasid_get_domain_id(pte));
+
+ *pte = new_pte;
spin_unlock(&iommu->lock);
- pasid_flush_caches(iommu, pte, pasid, did);
+ intel_pasid_flush_present(iommu, dev, pasid, old_did, pte);
+ intel_iommu_drain_pasid_prq(dev, pasid);
return 0;
}
/*
- * Skip top levels of page tables for iommu which has less agaw
- * than default. Unnecessary for PT mode.
+ * Set up the scalable mode pasid entry for second only translation type.
*/
-static int iommu_skip_agaw(struct dmar_domain *domain,
- struct intel_iommu *iommu,
- struct dma_pte **pgd)
+static void pasid_pte_config_second_level(struct intel_iommu *iommu,
+ struct pasid_entry *pte,
+ u64 pgd_val, int agaw, u16 did,
+ bool dirty_tracking)
{
- int agaw;
+ lockdep_assert_held(&iommu->lock);
- for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
- *pgd = phys_to_virt(dma_pte_addr(*pgd));
- if (!dma_pte_present(*pgd))
- return -EINVAL;
- }
+ pasid_clear_entry(pte);
+ pasid_set_domain_id(pte, did);
+ pasid_set_slptr(pte, pgd_val);
+ pasid_set_address_width(pte, agaw);
+ pasid_set_translation_type(pte, PASID_ENTRY_PGTT_SL_ONLY);
+ pasid_set_fault_enable(pte);
+ pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+ if (dirty_tracking)
+ pasid_set_ssade(pte);
- return agaw;
+ pasid_set_present(pte);
}
-/*
- * Set up the scalable mode pasid entry for second only translation type.
- */
int intel_pasid_setup_second_level(struct intel_iommu *iommu,
struct dmar_domain *domain,
struct device *dev, u32 pasid)
@@ -374,7 +463,6 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
struct pasid_entry *pte;
struct dma_pte *pgd;
u64 pgd_val;
- int agaw;
u16 did;
/*
@@ -388,15 +476,58 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
}
pgd = domain->pgd;
- agaw = iommu_skip_agaw(domain, iommu, &pgd);
- if (agaw < 0) {
- dev_err(dev, "Invalid domain page table\n");
+ pgd_val = virt_to_phys(pgd);
+ did = domain_id_iommu(domain, iommu);
+
+ spin_lock(&iommu->lock);
+ pte = intel_pasid_get_entry(dev, pasid);
+ if (!pte) {
+ spin_unlock(&iommu->lock);
+ return -ENODEV;
+ }
+
+ if (pasid_pte_is_present(pte)) {
+ spin_unlock(&iommu->lock);
+ return -EBUSY;
+ }
+
+ pasid_pte_config_second_level(iommu, pte, pgd_val, domain->agaw,
+ did, domain->dirty_tracking);
+ spin_unlock(&iommu->lock);
+
+ pasid_flush_caches(iommu, pte, pasid, did);
+
+ return 0;
+}
+
+int intel_pasid_replace_second_level(struct intel_iommu *iommu,
+ struct dmar_domain *domain,
+ struct device *dev, u16 old_did,
+ u32 pasid)
+{
+ struct pasid_entry *pte, new_pte;
+ struct dma_pte *pgd;
+ u64 pgd_val;
+ u16 did;
+
+ /*
+ * If hardware advertises no support for second level
+ * translation, return directly.
+ */
+ if (!ecap_slts(iommu->ecap)) {
+ pr_err("No second level translation support on %s\n",
+ iommu->name);
return -EINVAL;
}
+ pgd = domain->pgd;
pgd_val = virt_to_phys(pgd);
did = domain_id_iommu(domain, iommu);
+ pasid_pte_config_second_level(iommu, &new_pte, pgd_val,
+ domain->agaw, did,
+ domain->dirty_tracking);
+
spin_lock(&iommu->lock);
pte = intel_pasid_get_entry(dev, pasid);
if (!pte) {
@@ -404,25 +535,18 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
return -ENODEV;
}
- if (pasid_pte_is_present(pte)) {
+ if (!pasid_pte_is_present(pte)) {
spin_unlock(&iommu->lock);
- return -EBUSY;
+ return -EINVAL;
}
- pasid_clear_entry(pte);
- pasid_set_domain_id(pte, did);
- pasid_set_slptr(pte, pgd_val);
- pasid_set_address_width(pte, agaw);
- pasid_set_translation_type(pte, PASID_ENTRY_PGTT_SL_ONLY);
- pasid_set_fault_enable(pte);
- pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
- if (domain->dirty_tracking)
- pasid_set_ssade(pte);
+ WARN_ON(old_did != pasid_get_domain_id(pte));
- pasid_set_present(pte);
+ *pte = new_pte;
spin_unlock(&iommu->lock);
- pasid_flush_caches(iommu, pte, pasid, did);
+ intel_pasid_flush_present(iommu, dev, pasid, old_did, pte);
+ intel_iommu_drain_pasid_prq(dev, pasid);
return 0;
}
@@ -499,6 +623,20 @@ int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu,
/*
* Set up the scalable mode pasid entry for passthrough translation type.
*/
+static void pasid_pte_config_pass_through(struct intel_iommu *iommu,
+ struct pasid_entry *pte, u16 did)
+{
+ lockdep_assert_held(&iommu->lock);
+
+ pasid_clear_entry(pte);
+ pasid_set_domain_id(pte, did);
+ pasid_set_address_width(pte, iommu->agaw);
+ pasid_set_translation_type(pte, PASID_ENTRY_PGTT_PT);
+ pasid_set_fault_enable(pte);
+ pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+ pasid_set_present(pte);
+}
+
int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
struct device *dev, u32 pasid)
{
@@ -517,13 +655,7 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
return -EBUSY;
}
- pasid_clear_entry(pte);
- pasid_set_domain_id(pte, did);
- pasid_set_address_width(pte, iommu->agaw);
- pasid_set_translation_type(pte, PASID_ENTRY_PGTT_PT);
- pasid_set_fault_enable(pte);
- pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
- pasid_set_present(pte);
+ pasid_pte_config_pass_through(iommu, pte, did);
spin_unlock(&iommu->lock);
pasid_flush_caches(iommu, pte, pasid, did);
@@ -531,6 +663,38 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
return 0;
}
+int intel_pasid_replace_pass_through(struct intel_iommu *iommu,
+ struct device *dev, u16 old_did,
+ u32 pasid)
+{
+ struct pasid_entry *pte, new_pte;
+ u16 did = FLPT_DEFAULT_DID;
+
+ pasid_pte_config_pass_through(iommu, &new_pte, did);
+
+ spin_lock(&iommu->lock);
+ pte = intel_pasid_get_entry(dev, pasid);
+ if (!pte) {
+ spin_unlock(&iommu->lock);
+ return -ENODEV;
+ }
+
+ if (!pasid_pte_is_present(pte)) {
+ spin_unlock(&iommu->lock);
+ return -EINVAL;
+ }
+
+ WARN_ON(old_did != pasid_get_domain_id(pte));
+
+ *pte = new_pte;
+ spin_unlock(&iommu->lock);
+
+ intel_pasid_flush_present(iommu, dev, pasid, old_did, pte);
+ intel_iommu_drain_pasid_prq(dev, pasid);
+
+ return 0;
+}
+
/*
* Set the page snoop control for a pasid entry which has been set up.
*/
@@ -551,24 +715,47 @@ void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
did = pasid_get_domain_id(pte);
spin_unlock(&iommu->lock);
- if (!ecap_coherent(iommu->ecap))
- clflush_cache_range(pte, sizeof(*pte));
+ intel_pasid_flush_present(iommu, dev, pasid, did, pte);
+}
- /*
- * VT-d spec 3.4 table23 states guides for cache invalidation:
- *
- * - PASID-selective-within-Domain PASID-cache invalidation
- * - PASID-selective PASID-based IOTLB invalidation
- * - If (pasid is RID_PASID)
- * - Global Device-TLB invalidation to affected functions
- * Else
- * - PASID-based Device-TLB invalidation (with S=1 and
- * Addr[63:12]=0x7FFFFFFF_FFFFF) to affected functions
- */
- pasid_cache_invalidation_with_pasid(iommu, did, pasid);
- qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+static void pasid_pte_config_nestd(struct intel_iommu *iommu,
+ struct pasid_entry *pte,
+ struct iommu_hwpt_vtd_s1 *s1_cfg,
+ struct dmar_domain *s2_domain,
+ u16 did)
+{
+ struct dma_pte *pgd = s2_domain->pgd;
- devtlb_invalidation_with_pasid(iommu, dev, pasid);
+ lockdep_assert_held(&iommu->lock);
+
+ pasid_clear_entry(pte);
+
+ if (s1_cfg->addr_width == ADDR_WIDTH_5LEVEL)
+ pasid_set_flpm(pte, 1);
+
+ pasid_set_flptr(pte, s1_cfg->pgtbl_addr);
+
+ if (s1_cfg->flags & IOMMU_VTD_S1_SRE) {
+ pasid_set_sre(pte);
+ if (s1_cfg->flags & IOMMU_VTD_S1_WPE)
+ pasid_set_wpe(pte);
+ }
+
+ if (s1_cfg->flags & IOMMU_VTD_S1_EAFE)
+ pasid_set_eafe(pte);
+
+ if (s2_domain->force_snooping)
+ pasid_set_pgsnp(pte);
+
+ pasid_set_slptr(pte, virt_to_phys(pgd));
+ pasid_set_fault_enable(pte);
+ pasid_set_domain_id(pte, did);
+ pasid_set_address_width(pte, s2_domain->agaw);
+ pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+ if (s2_domain->dirty_tracking)
+ pasid_set_ssade(pte);
+ pasid_set_translation_type(pte, PASID_ENTRY_PGTT_NESTED);
+ pasid_set_present(pte);
}
/**
@@ -586,10 +773,8 @@ int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
u32 pasid, struct dmar_domain *domain)
{
struct iommu_hwpt_vtd_s1 *s1_cfg = &domain->s1_cfg;
- pgd_t *s1_gpgd = (pgd_t *)(uintptr_t)domain->s1_pgtbl;
struct dmar_domain *s2_domain = domain->s2_domain;
u16 did = domain_id_iommu(domain, iommu);
- struct dma_pte *pgd = s2_domain->pgd;
struct pasid_entry *pte;
/* Address width should match the address width supported by hardware */
@@ -632,37 +817,73 @@ int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
return -EBUSY;
}
- pasid_clear_entry(pte);
+ pasid_pte_config_nestd(iommu, pte, s1_cfg, s2_domain, did);
+ spin_unlock(&iommu->lock);
- if (s1_cfg->addr_width == ADDR_WIDTH_5LEVEL)
- pasid_set_flpm(pte, 1);
+ pasid_flush_caches(iommu, pte, pasid, did);
- pasid_set_flptr(pte, (uintptr_t)s1_gpgd);
+ return 0;
+}
- if (s1_cfg->flags & IOMMU_VTD_S1_SRE) {
- pasid_set_sre(pte);
- if (s1_cfg->flags & IOMMU_VTD_S1_WPE)
- pasid_set_wpe(pte);
+int intel_pasid_replace_nested(struct intel_iommu *iommu,
+ struct device *dev, u32 pasid,
+ u16 old_did, struct dmar_domain *domain)
+{
+ struct iommu_hwpt_vtd_s1 *s1_cfg = &domain->s1_cfg;
+ struct dmar_domain *s2_domain = domain->s2_domain;
+ u16 did = domain_id_iommu(domain, iommu);
+ struct pasid_entry *pte, new_pte;
+
+ /* Address width should match the address width supported by hardware */
+ switch (s1_cfg->addr_width) {
+ case ADDR_WIDTH_4LEVEL:
+ break;
+ case ADDR_WIDTH_5LEVEL:
+ if (!cap_fl5lp_support(iommu->cap)) {
+ dev_err_ratelimited(dev,
+ "5-level paging not supported\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err_ratelimited(dev, "Invalid stage-1 address width %d\n",
+ s1_cfg->addr_width);
+ return -EINVAL;
}
- if (s1_cfg->flags & IOMMU_VTD_S1_EAFE)
- pasid_set_eafe(pte);
+ if ((s1_cfg->flags & IOMMU_VTD_S1_SRE) && !ecap_srs(iommu->ecap)) {
+ pr_err_ratelimited("No supervisor request support on %s\n",
+ iommu->name);
+ return -EINVAL;
+ }
- if (s2_domain->force_snooping)
- pasid_set_pgsnp(pte);
+ if ((s1_cfg->flags & IOMMU_VTD_S1_EAFE) && !ecap_eafs(iommu->ecap)) {
+ pr_err_ratelimited("No extended access flag support on %s\n",
+ iommu->name);
+ return -EINVAL;
+ }
- pasid_set_slptr(pte, virt_to_phys(pgd));
- pasid_set_fault_enable(pte);
- pasid_set_domain_id(pte, did);
- pasid_set_address_width(pte, s2_domain->agaw);
- pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
- if (s2_domain->dirty_tracking)
- pasid_set_ssade(pte);
- pasid_set_translation_type(pte, PASID_ENTRY_PGTT_NESTED);
- pasid_set_present(pte);
+ pasid_pte_config_nestd(iommu, &new_pte, s1_cfg, s2_domain, did);
+
+ spin_lock(&iommu->lock);
+ pte = intel_pasid_get_entry(dev, pasid);
+ if (!pte) {
+ spin_unlock(&iommu->lock);
+ return -ENODEV;
+ }
+
+ if (!pasid_pte_is_present(pte)) {
+ spin_unlock(&iommu->lock);
+ return -EINVAL;
+ }
+
+ WARN_ON(old_did != pasid_get_domain_id(pte));
+
+ *pte = new_pte;
spin_unlock(&iommu->lock);
- pasid_flush_caches(iommu, pte, pasid, did);
+ intel_pasid_flush_present(iommu, dev, pasid, old_did, pte);
+ intel_iommu_drain_pasid_prq(dev, pasid);
return 0;
}
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index dde6d3ba5ae0..082f4fe20216 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -22,13 +22,6 @@
#define is_pasid_enabled(entry) (((entry)->lo >> 3) & 0x1)
#define get_pasid_dir_size(entry) (1 << ((((entry)->lo >> 9) & 0x7) + 7))
-/*
- * Domain ID reserved for pasid entries programmed for first-level
- * only and pass-through transfer modes.
- */
-#define FLPT_DEFAULT_DID 1
-#define NUM_RESERVED_DID 2
-
#define PASID_FLAG_NESTED BIT(1)
#define PASID_FLAG_PAGE_SNOOP BIT(2)
@@ -303,6 +296,21 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
struct device *dev, u32 pasid);
int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
u32 pasid, struct dmar_domain *domain);
+int intel_pasid_replace_first_level(struct intel_iommu *iommu,
+ struct device *dev, pgd_t *pgd,
+ u32 pasid, u16 did, u16 old_did,
+ int flags);
+int intel_pasid_replace_second_level(struct intel_iommu *iommu,
+ struct dmar_domain *domain,
+ struct device *dev, u16 old_did,
+ u32 pasid);
+int intel_pasid_replace_pass_through(struct intel_iommu *iommu,
+ struct device *dev, u16 old_did,
+ u32 pasid);
+int intel_pasid_replace_nested(struct intel_iommu *iommu,
+ struct device *dev, u32 pasid,
+ u16 old_did, struct dmar_domain *domain);
+
void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
struct device *dev, u32 pasid,
bool fault_ignore);
diff --git a/drivers/iommu/intel/prq.c b/drivers/iommu/intel/prq.c
new file mode 100644
index 000000000000..c2d792db52c3
--- /dev/null
+++ b/drivers/iommu/intel/prq.c
@@ -0,0 +1,396 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * Originally split from drivers/iommu/intel/svm.c
+ */
+
+#include <linux/pci.h>
+#include <linux/pci-ats.h>
+
+#include "iommu.h"
+#include "pasid.h"
+#include "../iommu-pages.h"
+#include "trace.h"
+
+/* Page request queue descriptor */
+struct page_req_dsc {
+ union {
+ struct {
+ u64 type:8;
+ u64 pasid_present:1;
+ u64 rsvd:7;
+ u64 rid:16;
+ u64 pasid:20;
+ u64 exe_req:1;
+ u64 pm_req:1;
+ u64 rsvd2:10;
+ };
+ u64 qw_0;
+ };
+ union {
+ struct {
+ u64 rd_req:1;
+ u64 wr_req:1;
+ u64 lpig:1;
+ u64 prg_index:9;
+ u64 addr:52;
+ };
+ u64 qw_1;
+ };
+ u64 qw_2;
+ u64 qw_3;
+};
+
+/**
+ * intel_iommu_drain_pasid_prq - Drain page requests and responses for a pasid
+ * @dev: target device
+ * @pasid: pasid for draining
+ *
+ * Drain all pending page requests and responses related to @pasid in both
+ * software and hardware. This is supposed to be called after the device
+ * driver has stopped DMA, the pasid entry has been cleared, and both IOTLB
+ * and DevTLB have been invalidated.
+ *
+ * It waits until all pending page requests for @pasid in the page fault
+ * queue are completed by the prq handling thread. Then follow the steps
+ * described in VT-d spec CH7.10 to drain all page requests and page
+ * responses pending in the hardware.
+ */
+void intel_iommu_drain_pasid_prq(struct device *dev, u32 pasid)
+{
+ struct device_domain_info *info;
+ struct dmar_domain *domain;
+ struct intel_iommu *iommu;
+ struct qi_desc desc[3];
+ int head, tail;
+ u16 sid, did;
+
+ info = dev_iommu_priv_get(dev);
+ if (!info->pri_enabled)
+ return;
+
+ iommu = info->iommu;
+ domain = info->domain;
+ sid = PCI_DEVID(info->bus, info->devfn);
+ did = domain ? domain_id_iommu(domain, iommu) : FLPT_DEFAULT_DID;
+
+ /*
+ * Check and wait until all pending page requests in the queue are
+ * handled by the prq handling thread.
+ */
+prq_retry:
+ reinit_completion(&iommu->prq_complete);
+ tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
+ head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
+ while (head != tail) {
+ struct page_req_dsc *req;
+
+ req = &iommu->prq[head / sizeof(*req)];
+ if (!req->pasid_present || req->pasid != pasid) {
+ head = (head + sizeof(*req)) & PRQ_RING_MASK;
+ continue;
+ }
+
+ wait_for_completion(&iommu->prq_complete);
+ goto prq_retry;
+ }
+
+ iopf_queue_flush_dev(dev);
+
+ /*
+ * Perform steps described in VT-d spec CH7.10 to drain page
+ * requests and responses in hardware.
+ */
+ memset(desc, 0, sizeof(desc));
+ desc[0].qw0 = QI_IWD_STATUS_DATA(QI_DONE) |
+ QI_IWD_FENCE |
+ QI_IWD_TYPE;
+ if (pasid == IOMMU_NO_PASID) {
+ qi_desc_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH, &desc[1]);
+ qi_desc_dev_iotlb(sid, info->pfsid, info->ats_qdep, 0,
+ MAX_AGAW_PFN_WIDTH, &desc[2]);
+ } else {
+ qi_desc_piotlb(did, pasid, 0, -1, 0, &desc[1]);
+ qi_desc_dev_iotlb_pasid(sid, info->pfsid, pasid, info->ats_qdep,
+ 0, MAX_AGAW_PFN_WIDTH, &desc[2]);
+ }
+qi_retry:
+ reinit_completion(&iommu->prq_complete);
+ qi_submit_sync(iommu, desc, 3, QI_OPT_WAIT_DRAIN);
+ if (readl(iommu->reg + DMAR_PRS_REG) & DMA_PRS_PRO) {
+ wait_for_completion(&iommu->prq_complete);
+ goto qi_retry;
+ }
+}
+
+static bool is_canonical_address(u64 addr)
+{
+ int shift = 64 - (__VIRTUAL_MASK_SHIFT + 1);
+ long saddr = (long)addr;
+
+ return (((saddr << shift) >> shift) == saddr);
+}
+
+static void handle_bad_prq_event(struct intel_iommu *iommu,
+ struct page_req_dsc *req, int result)
+{
+ struct qi_desc desc = { };
+
+ pr_err("%s: Invalid page request: %08llx %08llx\n",
+ iommu->name, ((unsigned long long *)req)[0],
+ ((unsigned long long *)req)[1]);
+
+ if (!req->lpig)
+ return;
+
+ desc.qw0 = QI_PGRP_PASID(req->pasid) |
+ QI_PGRP_DID(req->rid) |
+ QI_PGRP_PASID_P(req->pasid_present) |
+ QI_PGRP_RESP_CODE(result) |
+ QI_PGRP_RESP_TYPE;
+ desc.qw1 = QI_PGRP_IDX(req->prg_index) |
+ QI_PGRP_LPIG(req->lpig);
+
+ qi_submit_sync(iommu, &desc, 1, 0);
+}
+
+static int prq_to_iommu_prot(struct page_req_dsc *req)
+{
+ int prot = 0;
+
+ if (req->rd_req)
+ prot |= IOMMU_FAULT_PERM_READ;
+ if (req->wr_req)
+ prot |= IOMMU_FAULT_PERM_WRITE;
+ if (req->exe_req)
+ prot |= IOMMU_FAULT_PERM_EXEC;
+ if (req->pm_req)
+ prot |= IOMMU_FAULT_PERM_PRIV;
+
+ return prot;
+}
+
+static void intel_prq_report(struct intel_iommu *iommu, struct device *dev,
+ struct page_req_dsc *desc)
+{
+ struct iopf_fault event = { };
+
+ /* Fill in event data for device specific processing */
+ event.fault.type = IOMMU_FAULT_PAGE_REQ;
+ event.fault.prm.addr = (u64)desc->addr << VTD_PAGE_SHIFT;
+ event.fault.prm.pasid = desc->pasid;
+ event.fault.prm.grpid = desc->prg_index;
+ event.fault.prm.perm = prq_to_iommu_prot(desc);
+
+ if (desc->lpig)
+ event.fault.prm.flags |= IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
+ if (desc->pasid_present) {
+ event.fault.prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
+ event.fault.prm.flags |= IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID;
+ }
+
+ iommu_report_device_fault(dev, &event);
+}
+
+static irqreturn_t prq_event_thread(int irq, void *d)
+{
+ struct intel_iommu *iommu = d;
+ struct page_req_dsc *req;
+ int head, tail, handled;
+ struct device *dev;
+ u64 address;
+
+ /*
+ * Clear PPR bit before reading head/tail registers, to ensure that
+ * we get a new interrupt if needed.
+ */
+ writel(DMA_PRS_PPR, iommu->reg + DMAR_PRS_REG);
+
+ tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
+ head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
+ handled = (head != tail);
+ while (head != tail) {
+ req = &iommu->prq[head / sizeof(*req)];
+ address = (u64)req->addr << VTD_PAGE_SHIFT;
+
+ if (unlikely(!is_canonical_address(address))) {
+ pr_err("IOMMU: %s: Address is not canonical\n",
+ iommu->name);
+bad_req:
+ handle_bad_prq_event(iommu, req, QI_RESP_INVALID);
+ goto prq_advance;
+ }
+
+ if (unlikely(req->pm_req && (req->rd_req | req->wr_req))) {
+ pr_err("IOMMU: %s: Page request in Privilege Mode\n",
+ iommu->name);
+ goto bad_req;
+ }
+
+ if (unlikely(req->exe_req && req->rd_req)) {
+ pr_err("IOMMU: %s: Execution request not supported\n",
+ iommu->name);
+ goto bad_req;
+ }
+
+ /* Drop Stop Marker message. No need for a response. */
+ if (unlikely(req->lpig && !req->rd_req && !req->wr_req))
+ goto prq_advance;
+
+ /*
+ * If prq is to be handled outside iommu driver via receiver of
+ * the fault notifiers, we skip the page response here.
+ */
+ mutex_lock(&iommu->iopf_lock);
+ dev = device_rbtree_find(iommu, req->rid);
+ if (!dev) {
+ mutex_unlock(&iommu->iopf_lock);
+ goto bad_req;
+ }
+
+ intel_prq_report(iommu, dev, req);
+ trace_prq_report(iommu, dev, req->qw_0, req->qw_1,
+ req->qw_2, req->qw_3,
+ iommu->prq_seq_number++);
+ mutex_unlock(&iommu->iopf_lock);
+prq_advance:
+ head = (head + sizeof(*req)) & PRQ_RING_MASK;
+ }
+
+ dmar_writeq(iommu->reg + DMAR_PQH_REG, tail);
+
+ /*
+ * Clear the page request overflow bit and wake up all threads that
+ * are waiting for the completion of this handling.
+ */
+ if (readl(iommu->reg + DMAR_PRS_REG) & DMA_PRS_PRO) {
+ pr_info_ratelimited("IOMMU: %s: PRQ overflow detected\n",
+ iommu->name);
+ head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
+ tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
+ if (head == tail) {
+ iopf_queue_discard_partial(iommu->iopf_queue);
+ writel(DMA_PRS_PRO, iommu->reg + DMAR_PRS_REG);
+ pr_info_ratelimited("IOMMU: %s: PRQ overflow cleared",
+ iommu->name);
+ }
+ }
+
+ if (!completion_done(&iommu->prq_complete))
+ complete(&iommu->prq_complete);
+
+ return IRQ_RETVAL(handled);
+}
+
+int intel_iommu_enable_prq(struct intel_iommu *iommu)
+{
+ struct iopf_queue *iopfq;
+ int irq, ret;
+
+ iommu->prq = iommu_alloc_pages_node(iommu->node, GFP_KERNEL, PRQ_ORDER);
+ if (!iommu->prq) {
+ pr_warn("IOMMU: %s: Failed to allocate page request queue\n",
+ iommu->name);
+ return -ENOMEM;
+ }
+
+ irq = dmar_alloc_hwirq(IOMMU_IRQ_ID_OFFSET_PRQ + iommu->seq_id, iommu->node, iommu);
+ if (irq <= 0) {
+ pr_err("IOMMU: %s: Failed to create IRQ vector for page request queue\n",
+ iommu->name);
+ ret = -EINVAL;
+ goto free_prq;
+ }
+ iommu->pr_irq = irq;
+
+ snprintf(iommu->iopfq_name, sizeof(iommu->iopfq_name),
+ "dmar%d-iopfq", iommu->seq_id);
+ iopfq = iopf_queue_alloc(iommu->iopfq_name);
+ if (!iopfq) {
+ pr_err("IOMMU: %s: Failed to allocate iopf queue\n", iommu->name);
+ ret = -ENOMEM;
+ goto free_hwirq;
+ }
+ iommu->iopf_queue = iopfq;
+
+ snprintf(iommu->prq_name, sizeof(iommu->prq_name), "dmar%d-prq", iommu->seq_id);
+
+ ret = request_threaded_irq(irq, NULL, prq_event_thread, IRQF_ONESHOT,
+ iommu->prq_name, iommu);
+ if (ret) {
+ pr_err("IOMMU: %s: Failed to request IRQ for page request queue\n",
+ iommu->name);
+ goto free_iopfq;
+ }
+ dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQA_REG, virt_to_phys(iommu->prq) | PRQ_ORDER);
+
+ init_completion(&iommu->prq_complete);
+
+ return 0;
+
+free_iopfq:
+ iopf_queue_free(iommu->iopf_queue);
+ iommu->iopf_queue = NULL;
+free_hwirq:
+ dmar_free_hwirq(irq);
+ iommu->pr_irq = 0;
+free_prq:
+ iommu_free_pages(iommu->prq, PRQ_ORDER);
+ iommu->prq = NULL;
+
+ return ret;
+}
+
+int intel_iommu_finish_prq(struct intel_iommu *iommu)
+{
+ dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL);
+ dmar_writeq(iommu->reg + DMAR_PQA_REG, 0ULL);
+
+ if (iommu->pr_irq) {
+ free_irq(iommu->pr_irq, iommu);
+ dmar_free_hwirq(iommu->pr_irq);
+ iommu->pr_irq = 0;
+ }
+
+ if (iommu->iopf_queue) {
+ iopf_queue_free(iommu->iopf_queue);
+ iommu->iopf_queue = NULL;
+ }
+
+ iommu_free_pages(iommu->prq, PRQ_ORDER);
+ iommu->prq = NULL;
+
+ return 0;
+}
+
+void intel_iommu_page_response(struct device *dev, struct iopf_fault *evt,
+ struct iommu_page_response *msg)
+{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ struct intel_iommu *iommu = info->iommu;
+ u8 bus = info->bus, devfn = info->devfn;
+ struct iommu_fault_page_request *prm;
+ struct qi_desc desc;
+ bool pasid_present;
+ bool last_page;
+ u16 sid;
+
+ prm = &evt->fault.prm;
+ sid = PCI_DEVID(bus, devfn);
+ pasid_present = prm->flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
+ last_page = prm->flags & IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
+
+ desc.qw0 = QI_PGRP_PASID(prm->pasid) | QI_PGRP_DID(sid) |
+ QI_PGRP_PASID_P(pasid_present) |
+ QI_PGRP_RESP_CODE(msg->code) |
+ QI_PGRP_RESP_TYPE;
+ desc.qw1 = QI_PGRP_IDX(prm->grpid) | QI_PGRP_LPIG(last_page);
+ desc.qw2 = 0;
+ desc.qw3 = 0;
+
+ qi_submit_sync(iommu, &desc, 1, 0);
+}
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 078d1e32a24e..f5569347591f 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -25,92 +25,6 @@
#include "../iommu-pages.h"
#include "trace.h"
-static irqreturn_t prq_event_thread(int irq, void *d);
-
-int intel_svm_enable_prq(struct intel_iommu *iommu)
-{
- struct iopf_queue *iopfq;
- int irq, ret;
-
- iommu->prq = iommu_alloc_pages_node(iommu->node, GFP_KERNEL, PRQ_ORDER);
- if (!iommu->prq) {
- pr_warn("IOMMU: %s: Failed to allocate page request queue\n",
- iommu->name);
- return -ENOMEM;
- }
-
- irq = dmar_alloc_hwirq(IOMMU_IRQ_ID_OFFSET_PRQ + iommu->seq_id, iommu->node, iommu);
- if (irq <= 0) {
- pr_err("IOMMU: %s: Failed to create IRQ vector for page request queue\n",
- iommu->name);
- ret = -EINVAL;
- goto free_prq;
- }
- iommu->pr_irq = irq;
-
- snprintf(iommu->iopfq_name, sizeof(iommu->iopfq_name),
- "dmar%d-iopfq", iommu->seq_id);
- iopfq = iopf_queue_alloc(iommu->iopfq_name);
- if (!iopfq) {
- pr_err("IOMMU: %s: Failed to allocate iopf queue\n", iommu->name);
- ret = -ENOMEM;
- goto free_hwirq;
- }
- iommu->iopf_queue = iopfq;
-
- snprintf(iommu->prq_name, sizeof(iommu->prq_name), "dmar%d-prq", iommu->seq_id);
-
- ret = request_threaded_irq(irq, NULL, prq_event_thread, IRQF_ONESHOT,
- iommu->prq_name, iommu);
- if (ret) {
- pr_err("IOMMU: %s: Failed to request IRQ for page request queue\n",
- iommu->name);
- goto free_iopfq;
- }
- dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL);
- dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL);
- dmar_writeq(iommu->reg + DMAR_PQA_REG, virt_to_phys(iommu->prq) | PRQ_ORDER);
-
- init_completion(&iommu->prq_complete);
-
- return 0;
-
-free_iopfq:
- iopf_queue_free(iommu->iopf_queue);
- iommu->iopf_queue = NULL;
-free_hwirq:
- dmar_free_hwirq(irq);
- iommu->pr_irq = 0;
-free_prq:
- iommu_free_pages(iommu->prq, PRQ_ORDER);
- iommu->prq = NULL;
-
- return ret;
-}
-
-int intel_svm_finish_prq(struct intel_iommu *iommu)
-{
- dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL);
- dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL);
- dmar_writeq(iommu->reg + DMAR_PQA_REG, 0ULL);
-
- if (iommu->pr_irq) {
- free_irq(iommu->pr_irq, iommu);
- dmar_free_hwirq(iommu->pr_irq);
- iommu->pr_irq = 0;
- }
-
- if (iommu->iopf_queue) {
- iopf_queue_free(iommu->iopf_queue);
- iommu->iopf_queue = NULL;
- }
-
- iommu_free_pages(iommu->prq, PRQ_ORDER);
- iommu->prq = NULL;
-
- return 0;
-}
-
void intel_svm_check(struct intel_iommu *iommu)
{
if (!pasid_supported(iommu))
@@ -197,360 +111,37 @@ static const struct mmu_notifier_ops intel_mmuops = {
};
static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
- struct device *dev, ioasid_t pasid)
+ struct device *dev, ioasid_t pasid,
+ struct iommu_domain *old)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
- struct dmar_domain *dmar_domain = to_dmar_domain(domain);
struct intel_iommu *iommu = info->iommu;
struct mm_struct *mm = domain->mm;
struct dev_pasid_info *dev_pasid;
unsigned long sflags;
- unsigned long flags;
int ret = 0;
- dev_pasid = kzalloc(sizeof(*dev_pasid), GFP_KERNEL);
- if (!dev_pasid)
- return -ENOMEM;
-
- dev_pasid->dev = dev;
- dev_pasid->pasid = pasid;
-
- ret = cache_tag_assign_domain(to_dmar_domain(domain), dev, pasid);
- if (ret)
- goto free_dev_pasid;
+ dev_pasid = domain_add_dev_pasid(domain, dev, pasid);
+ if (IS_ERR(dev_pasid))
+ return PTR_ERR(dev_pasid);
/* Setup the pasid table: */
sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
- ret = intel_pasid_setup_first_level(iommu, dev, mm->pgd, pasid,
- FLPT_DEFAULT_DID, sflags);
+ ret = __domain_setup_first_level(iommu, dev, pasid,
+ FLPT_DEFAULT_DID, mm->pgd,
+ sflags, old);
if (ret)
- goto unassign_tag;
+ goto out_remove_dev_pasid;
- spin_lock_irqsave(&dmar_domain->lock, flags);
- list_add(&dev_pasid->link_domain, &dmar_domain->dev_pasids);
- spin_unlock_irqrestore(&dmar_domain->lock, flags);
+ domain_remove_dev_pasid(old, dev, pasid);
return 0;
-unassign_tag:
- cache_tag_unassign_domain(to_dmar_domain(domain), dev, pasid);
-free_dev_pasid:
- kfree(dev_pasid);
-
+out_remove_dev_pasid:
+ domain_remove_dev_pasid(domain, dev, pasid);
return ret;
}
-/* Page request queue descriptor */
-struct page_req_dsc {
- union {
- struct {
- u64 type:8;
- u64 pasid_present:1;
- u64 rsvd:7;
- u64 rid:16;
- u64 pasid:20;
- u64 exe_req:1;
- u64 pm_req:1;
- u64 rsvd2:10;
- };
- u64 qw_0;
- };
- union {
- struct {
- u64 rd_req:1;
- u64 wr_req:1;
- u64 lpig:1;
- u64 prg_index:9;
- u64 addr:52;
- };
- u64 qw_1;
- };
- u64 qw_2;
- u64 qw_3;
-};
-
-static bool is_canonical_address(u64 addr)
-{
- int shift = 64 - (__VIRTUAL_MASK_SHIFT + 1);
- long saddr = (long) addr;
-
- return (((saddr << shift) >> shift) == saddr);
-}
-
-/**
- * intel_drain_pasid_prq - Drain page requests and responses for a pasid
- * @dev: target device
- * @pasid: pasid for draining
- *
- * Drain all pending page requests and responses related to @pasid in both
- * software and hardware. This is supposed to be called after the device
- * driver has stopped DMA, the pasid entry has been cleared, and both IOTLB
- * and DevTLB have been invalidated.
- *
- * It waits until all pending page requests for @pasid in the page fault
- * queue are completed by the prq handling thread. Then follow the steps
- * described in VT-d spec CH7.10 to drain all page requests and page
- * responses pending in the hardware.
- */
-void intel_drain_pasid_prq(struct device *dev, u32 pasid)
-{
- struct device_domain_info *info;
- struct dmar_domain *domain;
- struct intel_iommu *iommu;
- struct qi_desc desc[3];
- struct pci_dev *pdev;
- int head, tail;
- u16 sid, did;
- int qdep;
-
- info = dev_iommu_priv_get(dev);
- if (WARN_ON(!info || !dev_is_pci(dev)))
- return;
-
- if (!info->pri_enabled)
- return;
-
- iommu = info->iommu;
- domain = info->domain;
- pdev = to_pci_dev(dev);
- sid = PCI_DEVID(info->bus, info->devfn);
- did = domain ? domain_id_iommu(domain, iommu) : FLPT_DEFAULT_DID;
- qdep = pci_ats_queue_depth(pdev);
-
- /*
- * Check and wait until all pending page requests in the queue are
- * handled by the prq handling thread.
- */
-prq_retry:
- reinit_completion(&iommu->prq_complete);
- tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
- head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
- while (head != tail) {
- struct page_req_dsc *req;
-
- req = &iommu->prq[head / sizeof(*req)];
- if (!req->pasid_present || req->pasid != pasid) {
- head = (head + sizeof(*req)) & PRQ_RING_MASK;
- continue;
- }
-
- wait_for_completion(&iommu->prq_complete);
- goto prq_retry;
- }
-
- iopf_queue_flush_dev(dev);
-
- /*
- * Perform steps described in VT-d spec CH7.10 to drain page
- * requests and responses in hardware.
- */
- memset(desc, 0, sizeof(desc));
- desc[0].qw0 = QI_IWD_STATUS_DATA(QI_DONE) |
- QI_IWD_FENCE |
- QI_IWD_TYPE;
- desc[1].qw0 = QI_EIOTLB_PASID(pasid) |
- QI_EIOTLB_DID(did) |
- QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
- QI_EIOTLB_TYPE;
- desc[2].qw0 = QI_DEV_EIOTLB_PASID(pasid) |
- QI_DEV_EIOTLB_SID(sid) |
- QI_DEV_EIOTLB_QDEP(qdep) |
- QI_DEIOTLB_TYPE |
- QI_DEV_IOTLB_PFSID(info->pfsid);
-qi_retry:
- reinit_completion(&iommu->prq_complete);
- qi_submit_sync(iommu, desc, 3, QI_OPT_WAIT_DRAIN);
- if (readl(iommu->reg + DMAR_PRS_REG) & DMA_PRS_PRO) {
- wait_for_completion(&iommu->prq_complete);
- goto qi_retry;
- }
-}
-
-static int prq_to_iommu_prot(struct page_req_dsc *req)
-{
- int prot = 0;
-
- if (req->rd_req)
- prot |= IOMMU_FAULT_PERM_READ;
- if (req->wr_req)
- prot |= IOMMU_FAULT_PERM_WRITE;
- if (req->exe_req)
- prot |= IOMMU_FAULT_PERM_EXEC;
- if (req->pm_req)
- prot |= IOMMU_FAULT_PERM_PRIV;
-
- return prot;
-}
-
-static void intel_svm_prq_report(struct intel_iommu *iommu, struct device *dev,
- struct page_req_dsc *desc)
-{
- struct iopf_fault event = { };
-
- /* Fill in event data for device specific processing */
- event.fault.type = IOMMU_FAULT_PAGE_REQ;
- event.fault.prm.addr = (u64)desc->addr << VTD_PAGE_SHIFT;
- event.fault.prm.pasid = desc->pasid;
- event.fault.prm.grpid = desc->prg_index;
- event.fault.prm.perm = prq_to_iommu_prot(desc);
-
- if (desc->lpig)
- event.fault.prm.flags |= IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
- if (desc->pasid_present) {
- event.fault.prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
- event.fault.prm.flags |= IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID;
- }
-
- iommu_report_device_fault(dev, &event);
-}
-
-static void handle_bad_prq_event(struct intel_iommu *iommu,
- struct page_req_dsc *req, int result)
-{
- struct qi_desc desc = { };
-
- pr_err("%s: Invalid page request: %08llx %08llx\n",
- iommu->name, ((unsigned long long *)req)[0],
- ((unsigned long long *)req)[1]);
-
- if (!req->lpig)
- return;
-
- desc.qw0 = QI_PGRP_PASID(req->pasid) |
- QI_PGRP_DID(req->rid) |
- QI_PGRP_PASID_P(req->pasid_present) |
- QI_PGRP_RESP_CODE(result) |
- QI_PGRP_RESP_TYPE;
- desc.qw1 = QI_PGRP_IDX(req->prg_index) |
- QI_PGRP_LPIG(req->lpig);
-
- qi_submit_sync(iommu, &desc, 1, 0);
-}
-
-static irqreturn_t prq_event_thread(int irq, void *d)
-{
- struct intel_iommu *iommu = d;
- struct page_req_dsc *req;
- int head, tail, handled;
- struct device *dev;
- u64 address;
-
- /*
- * Clear PPR bit before reading head/tail registers, to ensure that
- * we get a new interrupt if needed.
- */
- writel(DMA_PRS_PPR, iommu->reg + DMAR_PRS_REG);
-
- tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
- head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
- handled = (head != tail);
- while (head != tail) {
- req = &iommu->prq[head / sizeof(*req)];
- address = (u64)req->addr << VTD_PAGE_SHIFT;
-
- if (unlikely(!req->pasid_present)) {
- pr_err("IOMMU: %s: Page request without PASID\n",
- iommu->name);
-bad_req:
- handle_bad_prq_event(iommu, req, QI_RESP_INVALID);
- goto prq_advance;
- }
-
- if (unlikely(!is_canonical_address(address))) {
- pr_err("IOMMU: %s: Address is not canonical\n",
- iommu->name);
- goto bad_req;
- }
-
- if (unlikely(req->pm_req && (req->rd_req | req->wr_req))) {
- pr_err("IOMMU: %s: Page request in Privilege Mode\n",
- iommu->name);
- goto bad_req;
- }
-
- if (unlikely(req->exe_req && req->rd_req)) {
- pr_err("IOMMU: %s: Execution request not supported\n",
- iommu->name);
- goto bad_req;
- }
-
- /* Drop Stop Marker message. No need for a response. */
- if (unlikely(req->lpig && !req->rd_req && !req->wr_req))
- goto prq_advance;
-
- /*
- * If prq is to be handled outside iommu driver via receiver of
- * the fault notifiers, we skip the page response here.
- */
- mutex_lock(&iommu->iopf_lock);
- dev = device_rbtree_find(iommu, req->rid);
- if (!dev) {
- mutex_unlock(&iommu->iopf_lock);
- goto bad_req;
- }
-
- intel_svm_prq_report(iommu, dev, req);
- trace_prq_report(iommu, dev, req->qw_0, req->qw_1,
- req->qw_2, req->qw_3,
- iommu->prq_seq_number++);
- mutex_unlock(&iommu->iopf_lock);
-prq_advance:
- head = (head + sizeof(*req)) & PRQ_RING_MASK;
- }
-
- dmar_writeq(iommu->reg + DMAR_PQH_REG, tail);
-
- /*
- * Clear the page request overflow bit and wake up all threads that
- * are waiting for the completion of this handling.
- */
- if (readl(iommu->reg + DMAR_PRS_REG) & DMA_PRS_PRO) {
- pr_info_ratelimited("IOMMU: %s: PRQ overflow detected\n",
- iommu->name);
- head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
- tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
- if (head == tail) {
- iopf_queue_discard_partial(iommu->iopf_queue);
- writel(DMA_PRS_PRO, iommu->reg + DMAR_PRS_REG);
- pr_info_ratelimited("IOMMU: %s: PRQ overflow cleared",
- iommu->name);
- }
- }
-
- if (!completion_done(&iommu->prq_complete))
- complete(&iommu->prq_complete);
-
- return IRQ_RETVAL(handled);
-}
-
-void intel_svm_page_response(struct device *dev, struct iopf_fault *evt,
- struct iommu_page_response *msg)
-{
- struct device_domain_info *info = dev_iommu_priv_get(dev);
- struct intel_iommu *iommu = info->iommu;
- u8 bus = info->bus, devfn = info->devfn;
- struct iommu_fault_page_request *prm;
- struct qi_desc desc;
- bool pasid_present;
- bool last_page;
- u16 sid;
-
- prm = &evt->fault.prm;
- sid = PCI_DEVID(bus, devfn);
- pasid_present = prm->flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
- last_page = prm->flags & IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
-
- desc.qw0 = QI_PGRP_PASID(prm->pasid) | QI_PGRP_DID(sid) |
- QI_PGRP_PASID_P(pasid_present) |
- QI_PGRP_RESP_CODE(msg->code) |
- QI_PGRP_RESP_TYPE;
- desc.qw1 = QI_PGRP_IDX(prm->grpid) | QI_PGRP_LPIG(last_page);
- desc.qw2 = 0;
- desc.qw3 = 0;
-
- qi_submit_sync(iommu, &desc, 1, 0);
-}
-
static void intel_svm_domain_free(struct iommu_domain *domain)
{
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 06ffc683b28f..523355e91a2c 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -166,7 +166,6 @@ struct arm_v7s_io_pgtable {
arm_v7s_iopte *pgd;
struct kmem_cache *l2_tables;
- spinlock_t split_lock;
};
static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl);
@@ -363,25 +362,6 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl,
return pte;
}
-static int arm_v7s_pte_to_prot(arm_v7s_iopte pte, int lvl)
-{
- int prot = IOMMU_READ;
- arm_v7s_iopte attr = pte >> ARM_V7S_ATTR_SHIFT(lvl);
-
- if (!(attr & ARM_V7S_PTE_AP_RDONLY))
- prot |= IOMMU_WRITE;
- if (!(attr & ARM_V7S_PTE_AP_UNPRIV))
- prot |= IOMMU_PRIV;
- if ((attr & (ARM_V7S_TEX_MASK << ARM_V7S_TEX_SHIFT)) == 0)
- prot |= IOMMU_MMIO;
- else if (pte & ARM_V7S_ATTR_C)
- prot |= IOMMU_CACHE;
- if (pte & ARM_V7S_ATTR_XN(lvl))
- prot |= IOMMU_NOEXEC;
-
- return prot;
-}
-
static arm_v7s_iopte arm_v7s_pte_to_cont(arm_v7s_iopte pte, int lvl)
{
if (lvl == 1) {
@@ -398,23 +378,6 @@ static arm_v7s_iopte arm_v7s_pte_to_cont(arm_v7s_iopte pte, int lvl)
return pte;
}
-static arm_v7s_iopte arm_v7s_cont_to_pte(arm_v7s_iopte pte, int lvl)
-{
- if (lvl == 1) {
- pte &= ~ARM_V7S_CONT_SECTION;
- } else if (lvl == 2) {
- arm_v7s_iopte xn = pte & BIT(ARM_V7S_CONT_PAGE_XN_SHIFT);
- arm_v7s_iopte tex = pte & (ARM_V7S_CONT_PAGE_TEX_MASK <<
- ARM_V7S_CONT_PAGE_TEX_SHIFT);
-
- pte ^= xn | tex | ARM_V7S_PTE_TYPE_CONT_PAGE;
- pte |= (xn >> ARM_V7S_CONT_PAGE_XN_SHIFT) |
- (tex >> ARM_V7S_CONT_PAGE_TEX_SHIFT) |
- ARM_V7S_PTE_TYPE_PAGE;
- }
- return pte;
-}
-
static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl)
{
if (lvl == 1 && !ARM_V7S_PTE_IS_TABLE(pte, lvl))
@@ -591,77 +554,6 @@ static void arm_v7s_free_pgtable(struct io_pgtable *iop)
kfree(data);
}
-static arm_v7s_iopte arm_v7s_split_cont(struct arm_v7s_io_pgtable *data,
- unsigned long iova, int idx, int lvl,
- arm_v7s_iopte *ptep)
-{
- struct io_pgtable *iop = &data->iop;
- arm_v7s_iopte pte;
- size_t size = ARM_V7S_BLOCK_SIZE(lvl);
- int i;
-
- /* Check that we didn't lose a race to get the lock */
- pte = *ptep;
- if (!arm_v7s_pte_is_cont(pte, lvl))
- return pte;
-
- ptep -= idx & (ARM_V7S_CONT_PAGES - 1);
- pte = arm_v7s_cont_to_pte(pte, lvl);
- for (i = 0; i < ARM_V7S_CONT_PAGES; i++)
- ptep[i] = pte + i * size;
-
- __arm_v7s_pte_sync(ptep, ARM_V7S_CONT_PAGES, &iop->cfg);
-
- size *= ARM_V7S_CONT_PAGES;
- io_pgtable_tlb_flush_walk(iop, iova, size, size);
- return pte;
-}
-
-static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
- struct iommu_iotlb_gather *gather,
- unsigned long iova, size_t size,
- arm_v7s_iopte blk_pte,
- arm_v7s_iopte *ptep)
-{
- struct io_pgtable_cfg *cfg = &data->iop.cfg;
- arm_v7s_iopte pte, *tablep;
- int i, unmap_idx, num_entries, num_ptes;
-
- tablep = __arm_v7s_alloc_table(2, GFP_ATOMIC, data);
- if (!tablep)
- return 0; /* Bytes unmapped */
-
- num_ptes = ARM_V7S_PTES_PER_LVL(2, cfg);
- num_entries = size >> ARM_V7S_LVL_SHIFT(2);
- unmap_idx = ARM_V7S_LVL_IDX(iova, 2, cfg);
-
- pte = arm_v7s_prot_to_pte(arm_v7s_pte_to_prot(blk_pte, 1), 2, cfg);
- if (num_entries > 1)
- pte = arm_v7s_pte_to_cont(pte, 2);
-
- for (i = 0; i < num_ptes; i += num_entries, pte += size) {
- /* Unmap! */
- if (i == unmap_idx)
- continue;
-
- __arm_v7s_set_pte(&tablep[i], pte, num_entries, cfg);
- }
-
- pte = arm_v7s_install_table(tablep, ptep, blk_pte, cfg);
- if (pte != blk_pte) {
- __arm_v7s_free_table(tablep, 2, data);
-
- if (!ARM_V7S_PTE_IS_TABLE(pte, 1))
- return 0;
-
- tablep = iopte_deref(pte, 1, data);
- return __arm_v7s_unmap(data, gather, iova, size, 2, tablep);
- }
-
- io_pgtable_tlb_add_page(&data->iop, gather, iova, size);
- return size;
-}
-
static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size, int lvl,
@@ -694,11 +586,8 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
* case in a lock for the sake of correctness and be done with it.
*/
if (num_entries <= 1 && arm_v7s_pte_is_cont(pte[0], lvl)) {
- unsigned long flags;
-
- spin_lock_irqsave(&data->split_lock, flags);
- pte[0] = arm_v7s_split_cont(data, iova, idx, lvl, ptep);
- spin_unlock_irqrestore(&data->split_lock, flags);
+ WARN_ONCE(true, "Unmap of a partial large IOPTE is not allowed");
+ return 0;
}
/* If the size matches this level, we're in the right place */
@@ -721,12 +610,8 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
}
return size;
} else if (lvl == 1 && !ARM_V7S_PTE_IS_TABLE(pte[0], lvl)) {
- /*
- * Insert a table at the next level to map the old region,
- * minus the part we want to unmap
- */
- return arm_v7s_split_blk_unmap(data, gather, iova, size, pte[0],
- ptep);
+ WARN_ONCE(true, "Unmap of a partial large IOPTE is not allowed");
+ return 0;
}
/* Keep on walkin' */
@@ -811,8 +696,6 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
if (!data)
return NULL;
- spin_lock_init(&data->split_lock);
-
/*
* ARM_MTK_TTBR_EXT extend the translation table base support larger
* memory address.
@@ -936,8 +819,8 @@ static int __init arm_v7s_do_selftests(void)
.quirks = IO_PGTABLE_QUIRK_ARM_NS,
.pgsize_bitmap = SZ_4K | SZ_64K | SZ_1M | SZ_16M,
};
- unsigned int iova, size, iova_start;
- unsigned int i, loopnr = 0;
+ unsigned int iova, size;
+ unsigned int i;
size_t mapped;
selftest_running = true;
@@ -985,26 +868,6 @@ static int __init arm_v7s_do_selftests(void)
return __FAIL(ops);
iova += SZ_16M;
- loopnr++;
- }
-
- /* Partial unmap */
- i = 1;
- size = 1UL << __ffs(cfg.pgsize_bitmap);
- while (i < loopnr) {
- iova_start = i * SZ_16M;
- if (ops->unmap_pages(ops, iova_start + size, size, 1, NULL) != size)
- return __FAIL(ops);
-
- /* Remap of partial unmap */
- if (ops->map_pages(ops, iova_start + size, size, size, 1,
- IOMMU_READ, GFP_KERNEL, &mapped))
- return __FAIL(ops);
-
- if (ops->iova_to_phys(ops, iova_start + size + 42)
- != (size + 42))
- return __FAIL(ops);
- i++;
}
/* Full unmap */
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 0e67f1721a3d..6b9bb58a414f 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -106,6 +106,18 @@
#define ARM_LPAE_PTE_HAP_FAULT (((arm_lpae_iopte)0) << 6)
#define ARM_LPAE_PTE_HAP_READ (((arm_lpae_iopte)1) << 6)
#define ARM_LPAE_PTE_HAP_WRITE (((arm_lpae_iopte)2) << 6)
+/*
+ * For !FWB these code to:
+ * 1111 = Normal outer write back cachable / Inner Write Back Cachable
+ * Permit S1 to override
+ * 0101 = Normal Non-cachable / Inner Non-cachable
+ * 0001 = Device / Device-nGnRE
+ * For S2FWB these code:
+ * 0110 Force Normal Write Back
+ * 0101 Normal* is forced Normal-NC, Device unchanged
+ * 0001 Force Device-nGnRE
+ */
+#define ARM_LPAE_PTE_MEMATTR_FWB_WB (((arm_lpae_iopte)0x6) << 2)
#define ARM_LPAE_PTE_MEMATTR_OIWB (((arm_lpae_iopte)0xf) << 2)
#define ARM_LPAE_PTE_MEMATTR_NC (((arm_lpae_iopte)0x5) << 2)
#define ARM_LPAE_PTE_MEMATTR_DEV (((arm_lpae_iopte)0x1) << 2)
@@ -199,6 +211,18 @@ static phys_addr_t iopte_to_paddr(arm_lpae_iopte pte,
return (paddr | (paddr << (48 - 12))) & (ARM_LPAE_PTE_ADDR_MASK << 4);
}
+/*
+ * Convert an index returned by ARM_LPAE_PGD_IDX(), which can point into
+ * a concatenated PGD, into the maximum number of entries that can be
+ * mapped in the same table page.
+ */
+static inline int arm_lpae_max_entries(int i, struct arm_lpae_io_pgtable *data)
+{
+ int ptes_per_table = ARM_LPAE_PTES_PER_TABLE(data);
+
+ return ptes_per_table - (i & (ptes_per_table - 1));
+}
+
static bool selftest_running = false;
static dma_addr_t __arm_lpae_dma_addr(void *pages)
@@ -390,7 +414,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
/* If we can install a leaf entry at this level, then do so */
if (size == block_size) {
- max_entries = ARM_LPAE_PTES_PER_TABLE(data) - map_idx_start;
+ max_entries = arm_lpae_max_entries(map_idx_start, data);
num_entries = min_t(int, pgcount, max_entries);
ret = arm_lpae_init_pte(data, iova, paddr, prot, lvl, num_entries, ptep);
if (!ret)
@@ -458,12 +482,16 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
*/
if (data->iop.fmt == ARM_64_LPAE_S2 ||
data->iop.fmt == ARM_32_LPAE_S2) {
- if (prot & IOMMU_MMIO)
+ if (prot & IOMMU_MMIO) {
pte |= ARM_LPAE_PTE_MEMATTR_DEV;
- else if (prot & IOMMU_CACHE)
- pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
- else
+ } else if (prot & IOMMU_CACHE) {
+ if (data->iop.cfg.quirks & IO_PGTABLE_QUIRK_ARM_S2FWB)
+ pte |= ARM_LPAE_PTE_MEMATTR_FWB_WB;
+ else
+ pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
+ } else {
pte |= ARM_LPAE_PTE_MEMATTR_NC;
+ }
} else {
if (prot & IOMMU_MMIO)
pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV
@@ -569,66 +597,6 @@ static void arm_lpae_free_pgtable(struct io_pgtable *iop)
kfree(data);
}
-static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
- struct iommu_iotlb_gather *gather,
- unsigned long iova, size_t size,
- arm_lpae_iopte blk_pte, int lvl,
- arm_lpae_iopte *ptep, size_t pgcount)
-{
- struct io_pgtable_cfg *cfg = &data->iop.cfg;
- arm_lpae_iopte pte, *tablep;
- phys_addr_t blk_paddr;
- size_t tablesz = ARM_LPAE_GRANULE(data);
- size_t split_sz = ARM_LPAE_BLOCK_SIZE(lvl, data);
- int ptes_per_table = ARM_LPAE_PTES_PER_TABLE(data);
- int i, unmap_idx_start = -1, num_entries = 0, max_entries;
-
- if (WARN_ON(lvl == ARM_LPAE_MAX_LEVELS))
- return 0;
-
- tablep = __arm_lpae_alloc_pages(tablesz, GFP_ATOMIC, cfg, data->iop.cookie);
- if (!tablep)
- return 0; /* Bytes unmapped */
-
- if (size == split_sz) {
- unmap_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data);
- max_entries = ptes_per_table - unmap_idx_start;
- num_entries = min_t(int, pgcount, max_entries);
- }
-
- blk_paddr = iopte_to_paddr(blk_pte, data);
- pte = iopte_prot(blk_pte);
-
- for (i = 0; i < ptes_per_table; i++, blk_paddr += split_sz) {
- /* Unmap! */
- if (i >= unmap_idx_start && i < (unmap_idx_start + num_entries))
- continue;
-
- __arm_lpae_init_pte(data, blk_paddr, pte, lvl, 1, &tablep[i]);
- }
-
- pte = arm_lpae_install_table(tablep, ptep, blk_pte, data);
- if (pte != blk_pte) {
- __arm_lpae_free_pages(tablep, tablesz, cfg, data->iop.cookie);
- /*
- * We may race against someone unmapping another part of this
- * block, but anything else is invalid. We can't misinterpret
- * a page entry here since we're never at the last level.
- */
- if (iopte_type(pte) != ARM_LPAE_PTE_TYPE_TABLE)
- return 0;
-
- tablep = iopte_deref(pte, data);
- } else if (unmap_idx_start >= 0) {
- for (i = 0; i < num_entries; i++)
- io_pgtable_tlb_add_page(&data->iop, gather, iova + i * size, size);
-
- return num_entries * size;
- }
-
- return __arm_lpae_unmap(data, gather, iova, size, pgcount, lvl, tablep);
-}
-
static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
struct iommu_iotlb_gather *gather,
unsigned long iova, size_t size, size_t pgcount,
@@ -650,7 +618,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
/* If the size matches this level, we're in the right place */
if (size == ARM_LPAE_BLOCK_SIZE(lvl, data)) {
- max_entries = ARM_LPAE_PTES_PER_TABLE(data) - unmap_idx_start;
+ max_entries = arm_lpae_max_entries(unmap_idx_start, data);
num_entries = min_t(int, pgcount, max_entries);
/* Find and handle non-leaf entries */
@@ -678,12 +646,8 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
return i * size;
} else if (iopte_leaf(pte, lvl, iop->fmt)) {
- /*
- * Insert a table at the next level to map the old region,
- * minus the part we want to unmap
- */
- return arm_lpae_split_blk_unmap(data, gather, iova, size, pte,
- lvl + 1, ptep, pgcount);
+ WARN_ONCE(true, "Unmap of a partial large IOPTE is not allowed");
+ return 0;
}
/* Keep on walkin' */
@@ -1035,8 +999,7 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
struct arm_lpae_io_pgtable *data;
typeof(&cfg->arm_lpae_s2_cfg.vtcr) vtcr = &cfg->arm_lpae_s2_cfg.vtcr;
- /* The NS quirk doesn't apply at stage 2 */
- if (cfg->quirks)
+ if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_S2FWB))
return NULL;
data = arm_lpae_alloc_pgtable(cfg);
@@ -1347,19 +1310,6 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
iova += SZ_1G;
}
- /* Partial unmap */
- size = 1UL << __ffs(cfg->pgsize_bitmap);
- if (ops->unmap_pages(ops, SZ_1G + size, size, 1, NULL) != size)
- return __FAIL(ops, i);
-
- /* Remap of partial unmap */
- if (ops->map_pages(ops, SZ_1G + size, size, size, 1,
- IOMMU_READ, GFP_KERNEL, &mapped))
- return __FAIL(ops, i);
-
- if (ops->iova_to_phys(ops, SZ_1G + size + 42) != (size + 42))
- return __FAIL(ops, i);
-
/* Full unmap */
iova = 0;
for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) {
@@ -1382,6 +1332,23 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
iova += SZ_1G;
}
+ /*
+ * Map/unmap the last largest supported page of the IAS, this can
+ * trigger corner cases in the concatednated page tables.
+ */
+ mapped = 0;
+ size = 1UL << __fls(cfg->pgsize_bitmap);
+ iova = (1UL << cfg->ias) - size;
+ if (ops->map_pages(ops, iova, iova, size, 1,
+ IOMMU_READ | IOMMU_WRITE |
+ IOMMU_NOEXEC | IOMMU_CACHE,
+ GFP_KERNEL, &mapped))
+ return __FAIL(ops, i);
+ if (mapped != size)
+ return __FAIL(ops, i);
+ if (ops->unmap_pages(ops, iova, size, 1, NULL) != size)
+ return __FAIL(ops, i);
+
free_io_pgtable_ops(ops);
}
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
index cbe378c34ba3..170022c09536 100644
--- a/drivers/iommu/iommu-sysfs.c
+++ b/drivers/iommu/iommu-sysfs.c
@@ -34,7 +34,7 @@ static void release_device(struct device *dev)
kfree(dev);
}
-static struct class iommu_class = {
+static const struct class iommu_class = {
.name = "iommu",
.dev_release = release_device,
.dev_groups = dev_groups,
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 83c8e617a2c5..9bc0c74cca3c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -32,6 +32,7 @@
#include <trace/events/iommu.h>
#include <linux/sched/mm.h>
#include <linux/msi.h>
+#include <uapi/linux/iommufd.h>
#include "dma-iommu.h"
#include "iommu-priv.h"
@@ -90,15 +91,17 @@ static const char * const iommu_group_resv_type_string[] = {
#define IOMMU_CMD_LINE_DMA_API BIT(0)
#define IOMMU_CMD_LINE_STRICT BIT(1)
+static int bus_iommu_probe(const struct bus_type *bus);
static int iommu_bus_notifier(struct notifier_block *nb,
unsigned long action, void *data);
static void iommu_release_device(struct device *dev);
-static struct iommu_domain *
-__iommu_group_domain_alloc(struct iommu_group *group, unsigned int type);
static int __iommu_attach_device(struct iommu_domain *domain,
struct device *dev);
static int __iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group);
+static struct iommu_domain *__iommu_paging_domain_alloc_flags(struct device *dev,
+ unsigned int type,
+ unsigned int flags);
enum {
IOMMU_SET_DOMAIN_MUST_SUCCEED = 1 << 0,
@@ -133,6 +136,8 @@ static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
struct device *dev);
static void __iommu_group_free_device(struct iommu_group *group,
struct group_device *grp_dev);
+static void iommu_domain_init(struct iommu_domain *domain, unsigned int type,
+ const struct iommu_ops *ops);
#define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \
struct iommu_group_attribute iommu_group_attr_##_name = \
@@ -1141,10 +1146,6 @@ map_end:
}
}
-
- if (!list_empty(&mappings) && iommu_is_dma_domain(domain))
- iommu_flush_iotlb_all(domain);
-
out:
iommu_put_resv_regions(dev, &mappings);
@@ -1586,12 +1587,59 @@ struct iommu_group *fsl_mc_device_group(struct device *dev)
}
EXPORT_SYMBOL_GPL(fsl_mc_device_group);
+static struct iommu_domain *__iommu_alloc_identity_domain(struct device *dev)
+{
+ const struct iommu_ops *ops = dev_iommu_ops(dev);
+ struct iommu_domain *domain;
+
+ if (ops->identity_domain)
+ return ops->identity_domain;
+
+ /* Older drivers create the identity domain via ops->domain_alloc() */
+ if (!ops->domain_alloc)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ domain = ops->domain_alloc(IOMMU_DOMAIN_IDENTITY);
+ if (IS_ERR(domain))
+ return domain;
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+
+ iommu_domain_init(domain, IOMMU_DOMAIN_IDENTITY, ops);
+ return domain;
+}
+
static struct iommu_domain *
__iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
{
+ struct device *dev = iommu_group_first_dev(group);
+ struct iommu_domain *dom;
+
if (group->default_domain && group->default_domain->type == req_type)
return group->default_domain;
- return __iommu_group_domain_alloc(group, req_type);
+
+ /*
+ * When allocating the DMA API domain assume that the driver is going to
+ * use PASID and make sure the RID's domain is PASID compatible.
+ */
+ if (req_type & __IOMMU_DOMAIN_PAGING) {
+ dom = __iommu_paging_domain_alloc_flags(dev, req_type,
+ dev->iommu->max_pasids ? IOMMU_HWPT_ALLOC_PASID : 0);
+
+ /*
+ * If driver does not support PASID feature then
+ * try to allocate non-PASID domain
+ */
+ if (PTR_ERR(dom) == -EOPNOTSUPP)
+ dom = __iommu_paging_domain_alloc_flags(dev, req_type, 0);
+
+ return dom;
+ }
+
+ if (req_type == IOMMU_DOMAIN_IDENTITY)
+ return __iommu_alloc_identity_domain(dev);
+
+ return ERR_PTR(-EINVAL);
}
/*
@@ -1795,7 +1843,7 @@ static void iommu_group_do_probe_finalize(struct device *dev)
ops->probe_finalize(dev);
}
-int bus_iommu_probe(const struct bus_type *bus)
+static int bus_iommu_probe(const struct bus_type *bus)
{
struct iommu_group *group, *next;
LIST_HEAD(group_list);
@@ -1841,31 +1889,6 @@ int bus_iommu_probe(const struct bus_type *bus)
}
/**
- * iommu_present() - make platform-specific assumptions about an IOMMU
- * @bus: bus to check
- *
- * Do not use this function. You want device_iommu_mapped() instead.
- *
- * Return: true if some IOMMU is present and aware of devices on the given bus;
- * in general it may not be the only IOMMU, and it may not have anything to do
- * with whatever device you are ultimately interested in.
- */
-bool iommu_present(const struct bus_type *bus)
-{
- bool ret = false;
-
- for (int i = 0; i < ARRAY_SIZE(iommu_buses); i++) {
- if (iommu_buses[i] == bus) {
- spin_lock(&iommu_device_lock);
- ret = !list_empty(&iommu_device_list);
- spin_unlock(&iommu_device_lock);
- }
- }
- return ret;
-}
-EXPORT_SYMBOL_GPL(iommu_present);
-
-/**
* device_iommu_capable() - check for a general IOMMU capability
* @dev: device to which the capability would be relevant, if available
* @cap: IOMMU capability
@@ -1934,117 +1957,67 @@ void iommu_set_fault_handler(struct iommu_domain *domain,
}
EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
-static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,
- struct device *dev,
- unsigned int type)
+static void iommu_domain_init(struct iommu_domain *domain, unsigned int type,
+ const struct iommu_ops *ops)
{
- struct iommu_domain *domain;
- unsigned int alloc_type = type & IOMMU_DOMAIN_ALLOC_FLAGS;
-
- if (alloc_type == IOMMU_DOMAIN_IDENTITY && ops->identity_domain)
- return ops->identity_domain;
- else if (alloc_type == IOMMU_DOMAIN_BLOCKED && ops->blocked_domain)
- return ops->blocked_domain;
- else if (type & __IOMMU_DOMAIN_PAGING && ops->domain_alloc_paging)
- domain = ops->domain_alloc_paging(dev);
- else if (ops->domain_alloc)
- domain = ops->domain_alloc(alloc_type);
- else
- return ERR_PTR(-EOPNOTSUPP);
-
- /*
- * Many domain_alloc ops now return ERR_PTR, make things easier for the
- * driver by accepting ERR_PTR from all domain_alloc ops instead of
- * having two rules.
- */
- if (IS_ERR(domain))
- return domain;
- if (!domain)
- return ERR_PTR(-ENOMEM);
-
domain->type = type;
domain->owner = ops;
+ if (!domain->ops)
+ domain->ops = ops->default_domain_ops;
+
/*
* If not already set, assume all sizes by default; the driver
* may override this later
*/
if (!domain->pgsize_bitmap)
domain->pgsize_bitmap = ops->pgsize_bitmap;
-
- if (!domain->ops)
- domain->ops = ops->default_domain_ops;
-
- if (iommu_is_dma_domain(domain)) {
- int rc;
-
- rc = iommu_get_dma_cookie(domain);
- if (rc) {
- iommu_domain_free(domain);
- return ERR_PTR(rc);
- }
- }
- return domain;
}
static struct iommu_domain *
-__iommu_group_domain_alloc(struct iommu_group *group, unsigned int type)
-{
- struct device *dev = iommu_group_first_dev(group);
-
- return __iommu_domain_alloc(dev_iommu_ops(dev), dev, type);
-}
-
-static int __iommu_domain_alloc_dev(struct device *dev, void *data)
+__iommu_paging_domain_alloc_flags(struct device *dev, unsigned int type,
+ unsigned int flags)
{
- const struct iommu_ops **ops = data;
+ const struct iommu_ops *ops;
+ struct iommu_domain *domain;
if (!dev_has_iommu(dev))
- return 0;
-
- if (WARN_ONCE(*ops && *ops != dev_iommu_ops(dev),
- "Multiple IOMMU drivers present for bus %s, which the public IOMMU API can't fully support yet. You will still need to disable one or more for this to work, sorry!\n",
- dev_bus_name(dev)))
- return -EBUSY;
-
- *ops = dev_iommu_ops(dev);
- return 0;
-}
+ return ERR_PTR(-ENODEV);
-/*
- * The iommu ops in bus has been retired. Do not use this interface in
- * new drivers.
- */
-struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus)
-{
- const struct iommu_ops *ops = NULL;
- int err = bus_for_each_dev(bus, NULL, &ops, __iommu_domain_alloc_dev);
- struct iommu_domain *domain;
+ ops = dev_iommu_ops(dev);
- if (err || !ops)
- return NULL;
+ if (ops->domain_alloc_paging && !flags)
+ domain = ops->domain_alloc_paging(dev);
+ else if (ops->domain_alloc_paging_flags)
+ domain = ops->domain_alloc_paging_flags(dev, flags, NULL);
+ else if (ops->domain_alloc && !flags)
+ domain = ops->domain_alloc(IOMMU_DOMAIN_UNMANAGED);
+ else
+ return ERR_PTR(-EOPNOTSUPP);
- domain = __iommu_domain_alloc(ops, NULL, IOMMU_DOMAIN_UNMANAGED);
if (IS_ERR(domain))
- return NULL;
+ return domain;
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+
+ iommu_domain_init(domain, type, ops);
return domain;
}
-EXPORT_SYMBOL_GPL(iommu_domain_alloc);
/**
- * iommu_paging_domain_alloc() - Allocate a paging domain
+ * iommu_paging_domain_alloc_flags() - Allocate a paging domain
* @dev: device for which the domain is allocated
+ * @flags: Bitmap of iommufd_hwpt_alloc_flags
*
* Allocate a paging domain which will be managed by a kernel driver. Return
- * allocated domain if successful, or a ERR pointer for failure.
+ * allocated domain if successful, or an ERR pointer for failure.
*/
-struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
+struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
+ unsigned int flags)
{
- if (!dev_has_iommu(dev))
- return ERR_PTR(-ENODEV);
-
- return __iommu_domain_alloc(dev_iommu_ops(dev), dev, IOMMU_DOMAIN_UNMANAGED);
+ return __iommu_paging_domain_alloc_flags(dev,
+ IOMMU_DOMAIN_UNMANAGED, flags);
}
-EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc);
+EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc_flags);
void iommu_domain_free(struct iommu_domain *domain)
{
@@ -2216,8 +2189,8 @@ EXPORT_SYMBOL_GPL(iommu_attach_group);
/**
* iommu_group_replace_domain - replace the domain that a group is attached to
- * @new_domain: new IOMMU domain to replace with
* @group: IOMMU group that will be attached to the new domain
+ * @new_domain: new IOMMU domain to replace with
*
* This API allows the group to switch domains without being forced to go to
* the blocking domain in-between.
@@ -2586,6 +2559,20 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
return unmapped;
}
+/**
+ * iommu_unmap() - Remove mappings from a range of IOVA
+ * @domain: Domain to manipulate
+ * @iova: IO virtual address to start
+ * @size: Length of the range starting from @iova
+ *
+ * iommu_unmap() will remove a translation created by iommu_map(). It cannot
+ * subdivide a mapping created by iommu_map(), so it should be called with IOVA
+ * ranges that match what was passed to iommu_map(). The range can aggregate
+ * contiguous iommu_map() calls so long as no individual range is split.
+ *
+ * Returns: Number of bytes of IOVA unmapped. iova + res will be the point
+ * unmapping stopped.
+ */
size_t iommu_unmap(struct iommu_domain *domain,
unsigned long iova, size_t size)
{
@@ -2723,16 +2710,6 @@ static int __init iommu_init(void)
}
core_initcall(iommu_init);
-int iommu_enable_nesting(struct iommu_domain *domain)
-{
- if (domain->type != IOMMU_DOMAIN_UNMANAGED)
- return -EINVAL;
- if (!domain->ops->enable_nesting)
- return -EINVAL;
- return domain->ops->enable_nesting(domain);
-}
-EXPORT_SYMBOL_GPL(iommu_enable_nesting);
-
int iommu_set_pgtable_quirks(struct iommu_domain *domain,
unsigned long quirk)
{
@@ -2965,6 +2942,14 @@ static int iommu_setup_default_domain(struct iommu_group *group,
if (group->default_domain == dom)
return 0;
+ if (iommu_is_dma_domain(dom)) {
+ ret = iommu_get_dma_cookie(dom);
+ if (ret) {
+ iommu_domain_free(dom);
+ return ret;
+ }
+ }
+
/*
* IOMMU_RESV_DIRECT and IOMMU_RESV_DIRECT_RELAXABLE regions must be
* mapped before their device is attached, in order to guarantee
@@ -3152,22 +3137,25 @@ void iommu_device_unuse_default_domain(struct device *dev)
static int __iommu_group_alloc_blocking_domain(struct iommu_group *group)
{
+ struct device *dev = iommu_group_first_dev(group);
+ const struct iommu_ops *ops = dev_iommu_ops(dev);
struct iommu_domain *domain;
if (group->blocking_domain)
return 0;
- domain = __iommu_group_domain_alloc(group, IOMMU_DOMAIN_BLOCKED);
- if (IS_ERR(domain)) {
- /*
- * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED
- * create an empty domain instead.
- */
- domain = __iommu_group_domain_alloc(group,
- IOMMU_DOMAIN_UNMANAGED);
- if (IS_ERR(domain))
- return PTR_ERR(domain);
+ if (ops->blocked_domain) {
+ group->blocking_domain = ops->blocked_domain;
+ return 0;
}
+
+ /*
+ * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED create an
+ * empty PAGING domain instead.
+ */
+ domain = iommu_paging_domain_alloc(dev);
+ if (IS_ERR(domain))
+ return PTR_ERR(domain);
group->blocking_domain = domain;
return 0;
}
@@ -3331,7 +3319,8 @@ static int __iommu_set_group_pasid(struct iommu_domain *domain,
int ret;
for_each_group_device(group, device) {
- ret = domain->ops->set_dev_pasid(domain, device->dev, pasid);
+ ret = domain->ops->set_dev_pasid(domain, device->dev,
+ pasid, NULL);
if (ret)
goto err_revert;
}
diff --git a/drivers/iommu/iommufd/Kconfig b/drivers/iommu/iommufd/Kconfig
index 76656fe0470d..0a07f9449fd9 100644
--- a/drivers/iommu/iommufd/Kconfig
+++ b/drivers/iommu/iommufd/Kconfig
@@ -1,4 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
+config IOMMUFD_DRIVER_CORE
+ tristate
+ default (IOMMUFD_DRIVER || IOMMUFD) if IOMMUFD!=n
+
config IOMMUFD
tristate "IOMMU Userspace API"
select INTERVAL_TREE
diff --git a/drivers/iommu/iommufd/Makefile b/drivers/iommu/iommufd/Makefile
index cf4605962bea..cb784da6cddc 100644
--- a/drivers/iommu/iommufd/Makefile
+++ b/drivers/iommu/iommufd/Makefile
@@ -7,9 +7,13 @@ iommufd-y := \
ioas.o \
main.o \
pages.o \
- vfio_compat.o
+ vfio_compat.o \
+ viommu.o
iommufd-$(CONFIG_IOMMUFD_TEST) += selftest.o
obj-$(CONFIG_IOMMUFD) += iommufd.o
obj-$(CONFIG_IOMMUFD_DRIVER) += iova_bitmap.o
+
+iommufd_driver-y := driver.o
+obj-$(CONFIG_IOMMUFD_DRIVER_CORE) += iommufd_driver.o
diff --git a/drivers/iommu/iommufd/driver.c b/drivers/iommu/iommufd/driver.c
new file mode 100644
index 000000000000..7b67fdf44134
--- /dev/null
+++ b/drivers/iommu/iommufd/driver.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
+ */
+#include "iommufd_private.h"
+
+struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
+ size_t size,
+ enum iommufd_object_type type)
+{
+ struct iommufd_object *obj;
+ int rc;
+
+ obj = kzalloc(size, GFP_KERNEL_ACCOUNT);
+ if (!obj)
+ return ERR_PTR(-ENOMEM);
+ obj->type = type;
+ /* Starts out bias'd by 1 until it is removed from the xarray */
+ refcount_set(&obj->shortterm_users, 1);
+ refcount_set(&obj->users, 1);
+
+ /*
+ * Reserve an ID in the xarray but do not publish the pointer yet since
+ * the caller hasn't initialized it yet. Once the pointer is published
+ * in the xarray and visible to other threads we can't reliably destroy
+ * it anymore, so the caller must complete all errorable operations
+ * before calling iommufd_object_finalize().
+ */
+ rc = xa_alloc(&ictx->objects, &obj->id, XA_ZERO_ENTRY, xa_limit_31b,
+ GFP_KERNEL_ACCOUNT);
+ if (rc)
+ goto out_free;
+ return obj;
+out_free:
+ kfree(obj);
+ return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_NS_GPL(_iommufd_object_alloc, IOMMUFD);
+
+/* Caller should xa_lock(&viommu->vdevs) to protect the return value */
+struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
+ unsigned long vdev_id)
+{
+ struct iommufd_vdevice *vdev;
+
+ lockdep_assert_held(&viommu->vdevs.xa_lock);
+
+ vdev = xa_load(&viommu->vdevs, vdev_id);
+ return vdev ? vdev->dev : NULL;
+}
+EXPORT_SYMBOL_NS_GPL(iommufd_viommu_find_dev, IOMMUFD);
+
+MODULE_DESCRIPTION("iommufd code shared with builtin modules");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
index e590973ce5cf..053b0e30f55a 100644
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pci.h>
+#include <linux/pci-ats.h>
#include <linux/poll.h>
#include <uapi/linux/iommufd.h>
@@ -27,8 +28,12 @@ static int iommufd_fault_iopf_enable(struct iommufd_device *idev)
* resource between PF and VFs. There is no coordination for this
* shared capability. This waits for a vPRI reset to recover.
*/
- if (dev_is_pci(dev) && to_pci_dev(dev)->is_virtfn)
- return -EINVAL;
+ if (dev_is_pci(dev)) {
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ if (pdev->is_virtfn && pci_pri_supported(pdev))
+ return -EINVAL;
+ }
mutex_lock(&idev->iopf_lock);
/* Device iopf has already been on. */
diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index d06bf6e6c19f..ce03c3804651 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -57,7 +57,10 @@ void iommufd_hwpt_nested_destroy(struct iommufd_object *obj)
container_of(obj, struct iommufd_hwpt_nested, common.obj);
__iommufd_hwpt_destroy(&hwpt_nested->common);
- refcount_dec(&hwpt_nested->parent->common.obj.users);
+ if (hwpt_nested->viommu)
+ refcount_dec(&hwpt_nested->viommu->obj.users);
+ else
+ refcount_dec(&hwpt_nested->parent->common.obj.users);
}
void iommufd_hwpt_nested_abort(struct iommufd_object *obj)
@@ -107,7 +110,8 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
const struct iommu_user_data *user_data)
{
const u32 valid_flags = IOMMU_HWPT_ALLOC_NEST_PARENT |
- IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
+ IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
+ IOMMU_HWPT_FAULT_ID_VALID;
const struct iommu_ops *ops = dev_iommu_ops(idev->dev);
struct iommufd_hwpt_paging *hwpt_paging;
struct iommufd_hw_pagetable *hwpt;
@@ -115,7 +119,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
lockdep_assert_held(&ioas->mutex);
- if ((flags || user_data) && !ops->domain_alloc_user)
+ if ((flags || user_data) && !ops->domain_alloc_paging_flags)
return ERR_PTR(-EOPNOTSUPP);
if (flags & ~valid_flags)
return ERR_PTR(-EOPNOTSUPP);
@@ -135,9 +139,9 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
hwpt_paging->ioas = ioas;
hwpt_paging->nest_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT;
- if (ops->domain_alloc_user) {
- hwpt->domain = ops->domain_alloc_user(idev->dev, flags, NULL,
- user_data);
+ if (ops->domain_alloc_paging_flags) {
+ hwpt->domain = ops->domain_alloc_paging_flags(idev->dev, flags,
+ user_data);
if (IS_ERR(hwpt->domain)) {
rc = PTR_ERR(hwpt->domain);
hwpt->domain = NULL;
@@ -223,7 +227,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
int rc;
if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) ||
- !user_data->len || !ops->domain_alloc_user)
+ !user_data->len || !ops->domain_alloc_nested)
return ERR_PTR(-EOPNOTSUPP);
if (parent->auto_domain || !parent->nest_parent ||
parent->common.domain->owner != ops)
@@ -238,9 +242,9 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
refcount_inc(&parent->common.obj.users);
hwpt_nested->parent = parent;
- hwpt->domain = ops->domain_alloc_user(idev->dev,
- flags & ~IOMMU_HWPT_FAULT_ID_VALID,
- parent->common.domain, user_data);
+ hwpt->domain = ops->domain_alloc_nested(
+ idev->dev, parent->common.domain,
+ flags & ~IOMMU_HWPT_FAULT_ID_VALID, user_data);
if (IS_ERR(hwpt->domain)) {
rc = PTR_ERR(hwpt->domain);
hwpt->domain = NULL;
@@ -248,8 +252,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
}
hwpt->domain->owner = ops;
- if (WARN_ON_ONCE(hwpt->domain->type != IOMMU_DOMAIN_NESTED ||
- !hwpt->domain->ops->cache_invalidate_user)) {
+ if (WARN_ON_ONCE(hwpt->domain->type != IOMMU_DOMAIN_NESTED)) {
rc = -EINVAL;
goto out_abort;
}
@@ -260,6 +263,58 @@ out_abort:
return ERR_PTR(rc);
}
+/**
+ * iommufd_viommu_alloc_hwpt_nested() - Get a hwpt_nested for a vIOMMU
+ * @viommu: vIOMMU ojbect to associate the hwpt_nested/domain with
+ * @flags: Flags from userspace
+ * @user_data: user_data pointer. Must be valid
+ *
+ * Allocate a new IOMMU_DOMAIN_NESTED for a vIOMMU and return it as a NESTED
+ * hw_pagetable.
+ */
+static struct iommufd_hwpt_nested *
+iommufd_viommu_alloc_hwpt_nested(struct iommufd_viommu *viommu, u32 flags,
+ const struct iommu_user_data *user_data)
+{
+ struct iommufd_hwpt_nested *hwpt_nested;
+ struct iommufd_hw_pagetable *hwpt;
+ int rc;
+
+ if (!user_data->len)
+ return ERR_PTR(-EOPNOTSUPP);
+ if (!viommu->ops || !viommu->ops->alloc_domain_nested)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ hwpt_nested = __iommufd_object_alloc(
+ viommu->ictx, hwpt_nested, IOMMUFD_OBJ_HWPT_NESTED, common.obj);
+ if (IS_ERR(hwpt_nested))
+ return ERR_CAST(hwpt_nested);
+ hwpt = &hwpt_nested->common;
+
+ hwpt_nested->viommu = viommu;
+ refcount_inc(&viommu->obj.users);
+ hwpt_nested->parent = viommu->hwpt;
+
+ hwpt->domain =
+ viommu->ops->alloc_domain_nested(viommu, flags, user_data);
+ if (IS_ERR(hwpt->domain)) {
+ rc = PTR_ERR(hwpt->domain);
+ hwpt->domain = NULL;
+ goto out_abort;
+ }
+ hwpt->domain->owner = viommu->iommu_dev->ops;
+
+ if (WARN_ON_ONCE(hwpt->domain->type != IOMMU_DOMAIN_NESTED)) {
+ rc = -EINVAL;
+ goto out_abort;
+ }
+ return hwpt_nested;
+
+out_abort:
+ iommufd_object_abort_and_destroy(viommu->ictx, &hwpt->obj);
+ return ERR_PTR(rc);
+}
+
int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
{
struct iommu_hwpt_alloc *cmd = ucmd->cmd;
@@ -316,6 +371,22 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
goto out_unlock;
}
hwpt = &hwpt_nested->common;
+ } else if (pt_obj->type == IOMMUFD_OBJ_VIOMMU) {
+ struct iommufd_hwpt_nested *hwpt_nested;
+ struct iommufd_viommu *viommu;
+
+ viommu = container_of(pt_obj, struct iommufd_viommu, obj);
+ if (viommu->iommu_dev != __iommu_get_iommu_dev(idev->dev)) {
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+ hwpt_nested = iommufd_viommu_alloc_hwpt_nested(
+ viommu, cmd->flags, &user_data);
+ if (IS_ERR(hwpt_nested)) {
+ rc = PTR_ERR(hwpt_nested);
+ goto out_unlock;
+ }
+ hwpt = &hwpt_nested->common;
} else {
rc = -EINVAL;
goto out_put_pt;
@@ -412,7 +483,7 @@ int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd)
.entry_len = cmd->entry_len,
.entry_num = cmd->entry_num,
};
- struct iommufd_hw_pagetable *hwpt;
+ struct iommufd_object *pt_obj;
u32 done_num = 0;
int rc;
@@ -426,17 +497,40 @@ int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd)
goto out;
}
- hwpt = iommufd_get_hwpt_nested(ucmd, cmd->hwpt_id);
- if (IS_ERR(hwpt)) {
- rc = PTR_ERR(hwpt);
+ pt_obj = iommufd_get_object(ucmd->ictx, cmd->hwpt_id, IOMMUFD_OBJ_ANY);
+ if (IS_ERR(pt_obj)) {
+ rc = PTR_ERR(pt_obj);
goto out;
}
+ if (pt_obj->type == IOMMUFD_OBJ_HWPT_NESTED) {
+ struct iommufd_hw_pagetable *hwpt =
+ container_of(pt_obj, struct iommufd_hw_pagetable, obj);
+
+ if (!hwpt->domain->ops ||
+ !hwpt->domain->ops->cache_invalidate_user) {
+ rc = -EOPNOTSUPP;
+ goto out_put_pt;
+ }
+ rc = hwpt->domain->ops->cache_invalidate_user(hwpt->domain,
+ &data_array);
+ } else if (pt_obj->type == IOMMUFD_OBJ_VIOMMU) {
+ struct iommufd_viommu *viommu =
+ container_of(pt_obj, struct iommufd_viommu, obj);
+
+ if (!viommu->ops || !viommu->ops->cache_invalidate) {
+ rc = -EOPNOTSUPP;
+ goto out_put_pt;
+ }
+ rc = viommu->ops->cache_invalidate(viommu, &data_array);
+ } else {
+ rc = -EINVAL;
+ goto out_put_pt;
+ }
- rc = hwpt->domain->ops->cache_invalidate_user(hwpt->domain,
- &data_array);
done_num = data_array.entry_num;
- iommufd_put_object(ucmd->ictx, &hwpt->obj);
+out_put_pt:
+ iommufd_put_object(ucmd->ictx, pt_obj);
out:
cmd->entry_num = done_num;
if (iommufd_ucmd_respond(ucmd, sizeof(*cmd)))
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c
index 4bf7ccd39d46..8a790e597e12 100644
--- a/drivers/iommu/iommufd/io_pagetable.c
+++ b/drivers/iommu/iommufd/io_pagetable.c
@@ -107,9 +107,9 @@ static bool __alloc_iova_check_used(struct interval_tree_span_iter *span,
* Does not return a 0 IOVA even if it is valid.
*/
static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova,
- unsigned long uptr, unsigned long length)
+ unsigned long addr, unsigned long length)
{
- unsigned long page_offset = uptr % PAGE_SIZE;
+ unsigned long page_offset = addr % PAGE_SIZE;
struct interval_tree_double_span_iter used_span;
struct interval_tree_span_iter allowed_span;
unsigned long max_alignment = PAGE_SIZE;
@@ -122,15 +122,15 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova,
return -EOVERFLOW;
/*
- * Keep alignment present in the uptr when building the IOVA, this
+ * Keep alignment present in addr when building the IOVA, which
* increases the chance we can map a THP.
*/
- if (!uptr)
+ if (!addr)
iova_alignment = roundup_pow_of_two(length);
else
iova_alignment = min_t(unsigned long,
roundup_pow_of_two(length),
- 1UL << __ffs64(uptr));
+ 1UL << __ffs64(addr));
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
max_alignment = HPAGE_SIZE;
@@ -248,6 +248,7 @@ static int iopt_alloc_area_pages(struct io_pagetable *iopt,
int iommu_prot, unsigned int flags)
{
struct iopt_pages_list *elm;
+ unsigned long start;
unsigned long iova;
int rc = 0;
@@ -267,9 +268,15 @@ static int iopt_alloc_area_pages(struct io_pagetable *iopt,
/* Use the first entry to guess the ideal IOVA alignment */
elm = list_first_entry(pages_list, struct iopt_pages_list,
next);
- rc = iopt_alloc_iova(
- iopt, dst_iova,
- (uintptr_t)elm->pages->uptr + elm->start_byte, length);
+ switch (elm->pages->type) {
+ case IOPT_ADDRESS_USER:
+ start = elm->start_byte + (uintptr_t)elm->pages->uptr;
+ break;
+ case IOPT_ADDRESS_FILE:
+ start = elm->start_byte + elm->pages->start;
+ break;
+ }
+ rc = iopt_alloc_iova(iopt, dst_iova, start, length);
if (rc)
goto out_unlock;
if (IS_ENABLED(CONFIG_IOMMUFD_TEST) &&
@@ -384,6 +391,34 @@ out_unlock_domains:
return rc;
}
+static int iopt_map_common(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
+ struct iopt_pages *pages, unsigned long *iova,
+ unsigned long length, unsigned long start_byte,
+ int iommu_prot, unsigned int flags)
+{
+ struct iopt_pages_list elm = {};
+ LIST_HEAD(pages_list);
+ int rc;
+
+ elm.pages = pages;
+ elm.start_byte = start_byte;
+ if (ictx->account_mode == IOPT_PAGES_ACCOUNT_MM &&
+ elm.pages->account_mode == IOPT_PAGES_ACCOUNT_USER)
+ elm.pages->account_mode = IOPT_PAGES_ACCOUNT_MM;
+ elm.length = length;
+ list_add(&elm.next, &pages_list);
+
+ rc = iopt_map_pages(iopt, &pages_list, length, iova, iommu_prot, flags);
+ if (rc) {
+ if (elm.area)
+ iopt_abort_area(elm.area);
+ if (elm.pages)
+ iopt_put_pages(elm.pages);
+ return rc;
+ }
+ return 0;
+}
+
/**
* iopt_map_user_pages() - Map a user VA to an iova in the io page table
* @ictx: iommufd_ctx the iopt is part of
@@ -408,29 +443,41 @@ int iopt_map_user_pages(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
unsigned long length, int iommu_prot,
unsigned int flags)
{
- struct iopt_pages_list elm = {};
- LIST_HEAD(pages_list);
- int rc;
+ struct iopt_pages *pages;
- elm.pages = iopt_alloc_pages(uptr, length, iommu_prot & IOMMU_WRITE);
- if (IS_ERR(elm.pages))
- return PTR_ERR(elm.pages);
- if (ictx->account_mode == IOPT_PAGES_ACCOUNT_MM &&
- elm.pages->account_mode == IOPT_PAGES_ACCOUNT_USER)
- elm.pages->account_mode = IOPT_PAGES_ACCOUNT_MM;
- elm.start_byte = uptr - elm.pages->uptr;
- elm.length = length;
- list_add(&elm.next, &pages_list);
+ pages = iopt_alloc_user_pages(uptr, length, iommu_prot & IOMMU_WRITE);
+ if (IS_ERR(pages))
+ return PTR_ERR(pages);
- rc = iopt_map_pages(iopt, &pages_list, length, iova, iommu_prot, flags);
- if (rc) {
- if (elm.area)
- iopt_abort_area(elm.area);
- if (elm.pages)
- iopt_put_pages(elm.pages);
- return rc;
- }
- return 0;
+ return iopt_map_common(ictx, iopt, pages, iova, length,
+ uptr - pages->uptr, iommu_prot, flags);
+}
+
+/**
+ * iopt_map_file_pages() - Like iopt_map_user_pages, but map a file.
+ * @ictx: iommufd_ctx the iopt is part of
+ * @iopt: io_pagetable to act on
+ * @iova: If IOPT_ALLOC_IOVA is set this is unused on input and contains
+ * the chosen iova on output. Otherwise is the iova to map to on input
+ * @file: file to map
+ * @start: map file starting at this byte offset
+ * @length: Number of bytes to map
+ * @iommu_prot: Combination of IOMMU_READ/WRITE/etc bits for the mapping
+ * @flags: IOPT_ALLOC_IOVA or zero
+ */
+int iopt_map_file_pages(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
+ unsigned long *iova, struct file *file,
+ unsigned long start, unsigned long length,
+ int iommu_prot, unsigned int flags)
+{
+ struct iopt_pages *pages;
+
+ pages = iopt_alloc_file_pages(file, start, length,
+ iommu_prot & IOMMU_WRITE);
+ if (IS_ERR(pages))
+ return PTR_ERR(pages);
+ return iopt_map_common(ictx, iopt, pages, iova, length,
+ start - pages->start, iommu_prot, flags);
}
struct iova_bitmap_fn_arg {
diff --git a/drivers/iommu/iommufd/io_pagetable.h b/drivers/iommu/iommufd/io_pagetable.h
index c61d74471684..10c928a9a463 100644
--- a/drivers/iommu/iommufd/io_pagetable.h
+++ b/drivers/iommu/iommufd/io_pagetable.h
@@ -173,6 +173,12 @@ enum {
IOPT_PAGES_ACCOUNT_NONE = 0,
IOPT_PAGES_ACCOUNT_USER = 1,
IOPT_PAGES_ACCOUNT_MM = 2,
+ IOPT_PAGES_ACCOUNT_MODE_NUM = 3,
+};
+
+enum iopt_address_type {
+ IOPT_ADDRESS_USER = 0,
+ IOPT_ADDRESS_FILE = 1,
};
/*
@@ -195,7 +201,14 @@ struct iopt_pages {
struct task_struct *source_task;
struct mm_struct *source_mm;
struct user_struct *source_user;
- void __user *uptr;
+ enum iopt_address_type type;
+ union {
+ void __user *uptr; /* IOPT_ADDRESS_USER */
+ struct { /* IOPT_ADDRESS_FILE */
+ struct file *file;
+ unsigned long start;
+ };
+ };
bool writable:1;
u8 account_mode;
@@ -206,8 +219,10 @@ struct iopt_pages {
struct rb_root_cached domains_itree;
};
-struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
- bool writable);
+struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
+ unsigned long length, bool writable);
+struct iopt_pages *iopt_alloc_file_pages(struct file *file, unsigned long start,
+ unsigned long length, bool writable);
void iopt_release_pages(struct kref *kref);
static inline void iopt_put_pages(struct iopt_pages *pages)
{
@@ -238,4 +253,9 @@ struct iopt_pages_access {
unsigned int users;
};
+struct pfn_reader_user;
+
+int iopt_pages_update_pinned(struct iopt_pages *pages, unsigned long npages,
+ bool inc, struct pfn_reader_user *user);
+
#endif
diff --git a/drivers/iommu/iommufd/ioas.c b/drivers/iommu/iommufd/ioas.c
index 2c4b2bb11e78..1542c5fd10a8 100644
--- a/drivers/iommu/iommufd/ioas.c
+++ b/drivers/iommu/iommufd/ioas.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
*/
+#include <linux/file.h>
#include <linux/interval_tree.h>
#include <linux/iommu.h>
#include <linux/iommufd.h>
@@ -51,7 +52,10 @@ int iommufd_ioas_alloc_ioctl(struct iommufd_ucmd *ucmd)
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
if (rc)
goto out_table;
+
+ down_read(&ucmd->ictx->ioas_creation_lock);
iommufd_object_finalize(ucmd->ictx, &ioas->obj);
+ up_read(&ucmd->ictx->ioas_creation_lock);
return 0;
out_table:
@@ -197,6 +201,52 @@ static int conv_iommu_prot(u32 map_flags)
return iommu_prot;
}
+int iommufd_ioas_map_file(struct iommufd_ucmd *ucmd)
+{
+ struct iommu_ioas_map_file *cmd = ucmd->cmd;
+ unsigned long iova = cmd->iova;
+ struct iommufd_ioas *ioas;
+ unsigned int flags = 0;
+ struct file *file;
+ int rc;
+
+ if (cmd->flags &
+ ~(IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE |
+ IOMMU_IOAS_MAP_READABLE))
+ return -EOPNOTSUPP;
+
+ if (cmd->iova >= ULONG_MAX || cmd->length >= ULONG_MAX)
+ return -EOVERFLOW;
+
+ if (!(cmd->flags &
+ (IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_READABLE)))
+ return -EINVAL;
+
+ ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
+ if (IS_ERR(ioas))
+ return PTR_ERR(ioas);
+
+ if (!(cmd->flags & IOMMU_IOAS_MAP_FIXED_IOVA))
+ flags = IOPT_ALLOC_IOVA;
+
+ file = fget(cmd->fd);
+ if (!file)
+ return -EBADF;
+
+ rc = iopt_map_file_pages(ucmd->ictx, &ioas->iopt, &iova, file,
+ cmd->start, cmd->length,
+ conv_iommu_prot(cmd->flags), flags);
+ if (rc)
+ goto out_put;
+
+ cmd->iova = iova;
+ rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
+out_put:
+ iommufd_put_object(ucmd->ictx, &ioas->obj);
+ fput(file);
+ return rc;
+}
+
int iommufd_ioas_map(struct iommufd_ucmd *ucmd)
{
struct iommu_ioas_map *cmd = ucmd->cmd;
@@ -327,6 +377,215 @@ out_put:
return rc;
}
+static void iommufd_release_all_iova_rwsem(struct iommufd_ctx *ictx,
+ struct xarray *ioas_list)
+{
+ struct iommufd_ioas *ioas;
+ unsigned long index;
+
+ xa_for_each(ioas_list, index, ioas) {
+ up_write(&ioas->iopt.iova_rwsem);
+ refcount_dec(&ioas->obj.users);
+ }
+ up_write(&ictx->ioas_creation_lock);
+ xa_destroy(ioas_list);
+}
+
+static int iommufd_take_all_iova_rwsem(struct iommufd_ctx *ictx,
+ struct xarray *ioas_list)
+{
+ struct iommufd_object *obj;
+ unsigned long index;
+ int rc;
+
+ /*
+ * This is very ugly, it is done instead of adding a lock around
+ * pages->source_mm, which is a performance path for mdev, we just
+ * obtain the write side of all the iova_rwsems which also protects the
+ * pages->source_*. Due to copies we can't know which IOAS could read
+ * from the pages, so we just lock everything. This is the only place
+ * locks are nested and they are uniformly taken in ID order.
+ *
+ * ioas_creation_lock prevents new IOAS from being installed in the
+ * xarray while we do this, and also prevents more than one thread from
+ * holding nested locks.
+ */
+ down_write(&ictx->ioas_creation_lock);
+ xa_lock(&ictx->objects);
+ xa_for_each(&ictx->objects, index, obj) {
+ struct iommufd_ioas *ioas;
+
+ if (!obj || obj->type != IOMMUFD_OBJ_IOAS)
+ continue;
+
+ if (!refcount_inc_not_zero(&obj->users))
+ continue;
+
+ xa_unlock(&ictx->objects);
+
+ ioas = container_of(obj, struct iommufd_ioas, obj);
+ down_write_nest_lock(&ioas->iopt.iova_rwsem,
+ &ictx->ioas_creation_lock);
+
+ rc = xa_err(xa_store(ioas_list, index, ioas, GFP_KERNEL));
+ if (rc) {
+ iommufd_release_all_iova_rwsem(ictx, ioas_list);
+ return rc;
+ }
+
+ xa_lock(&ictx->objects);
+ }
+ xa_unlock(&ictx->objects);
+ return 0;
+}
+
+static bool need_charge_update(struct iopt_pages *pages)
+{
+ switch (pages->account_mode) {
+ case IOPT_PAGES_ACCOUNT_NONE:
+ return false;
+ case IOPT_PAGES_ACCOUNT_MM:
+ return pages->source_mm != current->mm;
+ case IOPT_PAGES_ACCOUNT_USER:
+ /*
+ * Update when mm changes because it also accounts
+ * in mm->pinned_vm.
+ */
+ return (pages->source_user != current_user()) ||
+ (pages->source_mm != current->mm);
+ }
+ return true;
+}
+
+static int charge_current(unsigned long *npinned)
+{
+ struct iopt_pages tmp = {
+ .source_mm = current->mm,
+ .source_task = current->group_leader,
+ .source_user = current_user(),
+ };
+ unsigned int account_mode;
+ int rc;
+
+ for (account_mode = 0; account_mode != IOPT_PAGES_ACCOUNT_MODE_NUM;
+ account_mode++) {
+ if (!npinned[account_mode])
+ continue;
+
+ tmp.account_mode = account_mode;
+ rc = iopt_pages_update_pinned(&tmp, npinned[account_mode], true,
+ NULL);
+ if (rc)
+ goto err_undo;
+ }
+ return 0;
+
+err_undo:
+ while (account_mode != 0) {
+ account_mode--;
+ if (!npinned[account_mode])
+ continue;
+ tmp.account_mode = account_mode;
+ iopt_pages_update_pinned(&tmp, npinned[account_mode], false,
+ NULL);
+ }
+ return rc;
+}
+
+static void change_mm(struct iopt_pages *pages)
+{
+ struct task_struct *old_task = pages->source_task;
+ struct user_struct *old_user = pages->source_user;
+ struct mm_struct *old_mm = pages->source_mm;
+
+ pages->source_mm = current->mm;
+ mmgrab(pages->source_mm);
+ mmdrop(old_mm);
+
+ pages->source_task = current->group_leader;
+ get_task_struct(pages->source_task);
+ put_task_struct(old_task);
+
+ pages->source_user = get_uid(current_user());
+ free_uid(old_user);
+}
+
+#define for_each_ioas_area(_xa, _index, _ioas, _area) \
+ xa_for_each((_xa), (_index), (_ioas)) \
+ for (_area = iopt_area_iter_first(&_ioas->iopt, 0, ULONG_MAX); \
+ _area; \
+ _area = iopt_area_iter_next(_area, 0, ULONG_MAX))
+
+int iommufd_ioas_change_process(struct iommufd_ucmd *ucmd)
+{
+ struct iommu_ioas_change_process *cmd = ucmd->cmd;
+ struct iommufd_ctx *ictx = ucmd->ictx;
+ unsigned long all_npinned[IOPT_PAGES_ACCOUNT_MODE_NUM] = {};
+ struct iommufd_ioas *ioas;
+ struct iopt_area *area;
+ struct iopt_pages *pages;
+ struct xarray ioas_list;
+ unsigned long index;
+ int rc;
+
+ if (cmd->__reserved)
+ return -EOPNOTSUPP;
+
+ xa_init(&ioas_list);
+ rc = iommufd_take_all_iova_rwsem(ictx, &ioas_list);
+ if (rc)
+ return rc;
+
+ for_each_ioas_area(&ioas_list, index, ioas, area) {
+ if (area->pages->type != IOPT_ADDRESS_FILE) {
+ rc = -EINVAL;
+ goto out;
+ }
+ }
+
+ /*
+ * Count last_pinned pages, then clear it to avoid double counting
+ * if the same iopt_pages is visited multiple times in this loop.
+ * Since we are under all the locks, npinned == last_npinned, so we
+ * can easily restore last_npinned before we return.
+ */
+ for_each_ioas_area(&ioas_list, index, ioas, area) {
+ pages = area->pages;
+
+ if (need_charge_update(pages)) {
+ all_npinned[pages->account_mode] += pages->last_npinned;
+ pages->last_npinned = 0;
+ }
+ }
+
+ rc = charge_current(all_npinned);
+
+ if (rc) {
+ /* Charge failed. Fix last_npinned and bail. */
+ for_each_ioas_area(&ioas_list, index, ioas, area)
+ area->pages->last_npinned = area->pages->npinned;
+ goto out;
+ }
+
+ for_each_ioas_area(&ioas_list, index, ioas, area) {
+ pages = area->pages;
+
+ /* Uncharge the old one (which also restores last_npinned) */
+ if (need_charge_update(pages)) {
+ int r = iopt_pages_update_pinned(pages, pages->npinned,
+ false, NULL);
+
+ if (WARN_ON(r))
+ rc = r;
+ }
+ change_mm(pages);
+ }
+
+out:
+ iommufd_release_all_iova_rwsem(ictx, &ioas_list);
+ return rc;
+}
+
int iommufd_option_rlimit_mode(struct iommu_option *cmd,
struct iommufd_ctx *ictx)
{
diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index f1d865e6fab6..b6d706cf2c66 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -5,8 +5,8 @@
#define __IOMMUFD_PRIVATE_H
#include <linux/iommu.h>
+#include <linux/iommufd.h>
#include <linux/iova_bitmap.h>
-#include <linux/refcount.h>
#include <linux/rwsem.h>
#include <linux/uaccess.h>
#include <linux/xarray.h>
@@ -24,6 +24,7 @@ struct iommufd_ctx {
struct xarray objects;
struct xarray groups;
wait_queue_head_t destroy_wait;
+ struct rw_semaphore ioas_creation_lock;
u8 account_mode;
/* Compatibility with VFIO no iommu */
@@ -69,6 +70,10 @@ int iopt_map_user_pages(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
unsigned long *iova, void __user *uptr,
unsigned long length, int iommu_prot,
unsigned int flags);
+int iopt_map_file_pages(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
+ unsigned long *iova, struct file *file,
+ unsigned long start, unsigned long length,
+ int iommu_prot, unsigned int flags);
int iopt_map_pages(struct io_pagetable *iopt, struct list_head *pages_list,
unsigned long length, unsigned long *dst_iova,
int iommu_prot, unsigned int flags);
@@ -122,29 +127,6 @@ static inline int iommufd_ucmd_respond(struct iommufd_ucmd *ucmd,
return 0;
}
-enum iommufd_object_type {
- IOMMUFD_OBJ_NONE,
- IOMMUFD_OBJ_ANY = IOMMUFD_OBJ_NONE,
- IOMMUFD_OBJ_DEVICE,
- IOMMUFD_OBJ_HWPT_PAGING,
- IOMMUFD_OBJ_HWPT_NESTED,
- IOMMUFD_OBJ_IOAS,
- IOMMUFD_OBJ_ACCESS,
- IOMMUFD_OBJ_FAULT,
-#ifdef CONFIG_IOMMUFD_TEST
- IOMMUFD_OBJ_SELFTEST,
-#endif
- IOMMUFD_OBJ_MAX,
-};
-
-/* Base struct for all objects with a userspace ID handle. */
-struct iommufd_object {
- refcount_t shortterm_users;
- refcount_t users;
- enum iommufd_object_type type;
- unsigned int id;
-};
-
static inline bool iommufd_lock_obj(struct iommufd_object *obj)
{
if (!refcount_inc_not_zero(&obj->users))
@@ -225,10 +207,6 @@ iommufd_object_put_and_try_destroy(struct iommufd_ctx *ictx,
iommufd_object_remove(ictx, obj, obj->id, 0);
}
-struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
- size_t size,
- enum iommufd_object_type type);
-
#define __iommufd_object_alloc(ictx, ptr, type, obj) \
container_of(_iommufd_object_alloc( \
ictx, \
@@ -276,6 +254,8 @@ void iommufd_ioas_destroy(struct iommufd_object *obj);
int iommufd_ioas_iova_ranges(struct iommufd_ucmd *ucmd);
int iommufd_ioas_allow_iovas(struct iommufd_ucmd *ucmd);
int iommufd_ioas_map(struct iommufd_ucmd *ucmd);
+int iommufd_ioas_map_file(struct iommufd_ucmd *ucmd);
+int iommufd_ioas_change_process(struct iommufd_ucmd *ucmd);
int iommufd_ioas_copy(struct iommufd_ucmd *ucmd);
int iommufd_ioas_unmap(struct iommufd_ucmd *ucmd);
int iommufd_ioas_option(struct iommufd_ucmd *ucmd);
@@ -312,6 +292,7 @@ struct iommufd_hwpt_paging {
struct iommufd_hwpt_nested {
struct iommufd_hw_pagetable common;
struct iommufd_hwpt_paging *parent;
+ struct iommufd_viommu *viommu;
};
static inline bool hwpt_is_paging(struct iommufd_hw_pagetable *hwpt)
@@ -528,6 +509,27 @@ static inline int iommufd_hwpt_replace_device(struct iommufd_device *idev,
return iommu_group_replace_domain(idev->igroup->group, hwpt->domain);
}
+static inline struct iommufd_viommu *
+iommufd_get_viommu(struct iommufd_ucmd *ucmd, u32 id)
+{
+ return container_of(iommufd_get_object(ucmd->ictx, id,
+ IOMMUFD_OBJ_VIOMMU),
+ struct iommufd_viommu, obj);
+}
+
+int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd);
+void iommufd_viommu_destroy(struct iommufd_object *obj);
+int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd);
+void iommufd_vdevice_destroy(struct iommufd_object *obj);
+
+struct iommufd_vdevice {
+ struct iommufd_object obj;
+ struct iommufd_ctx *ictx;
+ struct iommufd_viommu *viommu;
+ struct device *dev;
+ u64 id; /* per-vIOMMU virtual ID */
+};
+
#ifdef CONFIG_IOMMUFD_TEST
int iommufd_test(struct iommufd_ucmd *ucmd);
void iommufd_selftest_destroy(struct iommufd_object *obj);
diff --git a/drivers/iommu/iommufd/iommufd_test.h b/drivers/iommu/iommufd/iommufd_test.h
index f4bc23a92f9a..a6b7a163f636 100644
--- a/drivers/iommu/iommufd/iommufd_test.h
+++ b/drivers/iommu/iommufd/iommufd_test.h
@@ -23,6 +23,7 @@ enum {
IOMMU_TEST_OP_DIRTY,
IOMMU_TEST_OP_MD_CHECK_IOTLB,
IOMMU_TEST_OP_TRIGGER_IOPF,
+ IOMMU_TEST_OP_DEV_CHECK_CACHE,
};
enum {
@@ -54,6 +55,11 @@ enum {
MOCK_NESTED_DOMAIN_IOTLB_NUM = 4,
};
+enum {
+ MOCK_DEV_CACHE_ID_MAX = 3,
+ MOCK_DEV_CACHE_NUM = 4,
+};
+
struct iommu_test_cmd {
__u32 size;
__u32 op;
@@ -135,6 +141,10 @@ struct iommu_test_cmd {
__u32 perm;
__u64 addr;
} trigger_iopf;
+ struct {
+ __u32 id;
+ __u32 cache;
+ } check_dev_cache;
};
__u32 last;
};
@@ -152,6 +162,7 @@ struct iommu_test_hw_info {
/* Should not be equal to any defined value in enum iommu_hwpt_data_type */
#define IOMMU_HWPT_DATA_SELFTEST 0xdead
#define IOMMU_TEST_IOTLB_DEFAULT 0xbadbeef
+#define IOMMU_TEST_DEV_CACHE_DEFAULT 0xbaddad
/**
* struct iommu_hwpt_selftest
@@ -180,4 +191,25 @@ struct iommu_hwpt_invalidate_selftest {
__u32 iotlb_id;
};
+#define IOMMU_VIOMMU_TYPE_SELFTEST 0xdeadbeef
+
+/* Should not be equal to any defined value in enum iommu_viommu_invalidate_data_type */
+#define IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST 0xdeadbeef
+#define IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST_INVALID 0xdadbeef
+
+/**
+ * struct iommu_viommu_invalidate_selftest - Invalidation data for Mock VIOMMU
+ * (IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST)
+ * @flags: Invalidate flags
+ * @cache_id: Invalidate cache entry index
+ *
+ * If IOMMU_TEST_INVALIDATE_ALL is set in @flags, @cache_id will be ignored
+ */
+struct iommu_viommu_invalidate_selftest {
+#define IOMMU_TEST_INVALIDATE_FLAG_ALL (1 << 0)
+ __u32 flags;
+ __u32 vdev_id;
+ __u32 cache_id;
+};
+
#endif
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index b5f5d27ee963..0a96cc8f27da 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -29,38 +29,6 @@ struct iommufd_object_ops {
static const struct iommufd_object_ops iommufd_object_ops[];
static struct miscdevice vfio_misc_dev;
-struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
- size_t size,
- enum iommufd_object_type type)
-{
- struct iommufd_object *obj;
- int rc;
-
- obj = kzalloc(size, GFP_KERNEL_ACCOUNT);
- if (!obj)
- return ERR_PTR(-ENOMEM);
- obj->type = type;
- /* Starts out bias'd by 1 until it is removed from the xarray */
- refcount_set(&obj->shortterm_users, 1);
- refcount_set(&obj->users, 1);
-
- /*
- * Reserve an ID in the xarray but do not publish the pointer yet since
- * the caller hasn't initialized it yet. Once the pointer is published
- * in the xarray and visible to other threads we can't reliably destroy
- * it anymore, so the caller must complete all errorable operations
- * before calling iommufd_object_finalize().
- */
- rc = xa_alloc(&ictx->objects, &obj->id, XA_ZERO_ENTRY,
- xa_limit_31b, GFP_KERNEL_ACCOUNT);
- if (rc)
- goto out_free;
- return obj;
-out_free:
- kfree(obj);
- return ERR_PTR(rc);
-}
-
/*
* Allow concurrent access to the object.
*
@@ -73,20 +41,26 @@ out_free:
void iommufd_object_finalize(struct iommufd_ctx *ictx,
struct iommufd_object *obj)
{
+ XA_STATE(xas, &ictx->objects, obj->id);
void *old;
- old = xa_store(&ictx->objects, obj->id, obj, GFP_KERNEL);
- /* obj->id was returned from xa_alloc() so the xa_store() cannot fail */
- WARN_ON(old);
+ xa_lock(&ictx->objects);
+ old = xas_store(&xas, obj);
+ xa_unlock(&ictx->objects);
+ /* obj->id was returned from xa_alloc() so the xas_store() cannot fail */
+ WARN_ON(old != XA_ZERO_ENTRY);
}
/* Undo _iommufd_object_alloc() if iommufd_object_finalize() was not called */
void iommufd_object_abort(struct iommufd_ctx *ictx, struct iommufd_object *obj)
{
+ XA_STATE(xas, &ictx->objects, obj->id);
void *old;
- old = xa_erase(&ictx->objects, obj->id);
- WARN_ON(old);
+ xa_lock(&ictx->objects);
+ old = xas_store(&xas, NULL);
+ xa_unlock(&ictx->objects);
+ WARN_ON(old != XA_ZERO_ENTRY);
kfree(obj);
}
@@ -248,6 +222,7 @@ static int iommufd_fops_open(struct inode *inode, struct file *filp)
pr_info_once("IOMMUFD is providing /dev/vfio/vfio, not VFIO.\n");
}
+ init_rwsem(&ictx->ioas_creation_lock);
xa_init_flags(&ictx->objects, XA_FLAGS_ALLOC1 | XA_FLAGS_ACCOUNT);
xa_init(&ictx->groups);
ictx->file = filp;
@@ -333,6 +308,8 @@ union ucmd_buffer {
struct iommu_ioas_unmap unmap;
struct iommu_option option;
struct iommu_vfio_ioas vfio_ioas;
+ struct iommu_viommu_alloc viommu;
+ struct iommu_vdevice_alloc vdev;
#ifdef CONFIG_IOMMUFD_TEST
struct iommu_test_cmd test;
#endif
@@ -372,18 +349,26 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
struct iommu_ioas_alloc, out_ioas_id),
IOCTL_OP(IOMMU_IOAS_ALLOW_IOVAS, iommufd_ioas_allow_iovas,
struct iommu_ioas_allow_iovas, allowed_iovas),
+ IOCTL_OP(IOMMU_IOAS_CHANGE_PROCESS, iommufd_ioas_change_process,
+ struct iommu_ioas_change_process, __reserved),
IOCTL_OP(IOMMU_IOAS_COPY, iommufd_ioas_copy, struct iommu_ioas_copy,
src_iova),
IOCTL_OP(IOMMU_IOAS_IOVA_RANGES, iommufd_ioas_iova_ranges,
struct iommu_ioas_iova_ranges, out_iova_alignment),
IOCTL_OP(IOMMU_IOAS_MAP, iommufd_ioas_map, struct iommu_ioas_map,
iova),
+ IOCTL_OP(IOMMU_IOAS_MAP_FILE, iommufd_ioas_map_file,
+ struct iommu_ioas_map_file, iova),
IOCTL_OP(IOMMU_IOAS_UNMAP, iommufd_ioas_unmap, struct iommu_ioas_unmap,
length),
IOCTL_OP(IOMMU_OPTION, iommufd_option, struct iommu_option,
val64),
IOCTL_OP(IOMMU_VFIO_IOAS, iommufd_vfio_ioas, struct iommu_vfio_ioas,
__reserved),
+ IOCTL_OP(IOMMU_VIOMMU_ALLOC, iommufd_viommu_alloc_ioctl,
+ struct iommu_viommu_alloc, out_viommu_id),
+ IOCTL_OP(IOMMU_VDEVICE_ALLOC, iommufd_vdevice_alloc_ioctl,
+ struct iommu_vdevice_alloc, virt_id),
#ifdef CONFIG_IOMMUFD_TEST
IOCTL_OP(IOMMU_TEST_CMD, iommufd_test, struct iommu_test_cmd, last),
#endif
@@ -519,6 +504,12 @@ static const struct iommufd_object_ops iommufd_object_ops[] = {
[IOMMUFD_OBJ_FAULT] = {
.destroy = iommufd_fault_destroy,
},
+ [IOMMUFD_OBJ_VIOMMU] = {
+ .destroy = iommufd_viommu_destroy,
+ },
+ [IOMMUFD_OBJ_VDEVICE] = {
+ .destroy = iommufd_vdevice_destroy,
+ },
#ifdef CONFIG_IOMMUFD_TEST
[IOMMUFD_OBJ_SELFTEST] = {
.destroy = iommufd_selftest_destroy,
diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index 93d806c9c073..3427749bc5ce 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -45,6 +45,7 @@
* last_iova + 1 can overflow. An iopt_pages index will always be much less than
* ULONG_MAX so last_index + 1 cannot overflow.
*/
+#include <linux/file.h>
#include <linux/highmem.h>
#include <linux/iommu.h>
#include <linux/iommufd.h>
@@ -346,27 +347,41 @@ static void batch_destroy(struct pfn_batch *batch, void *backup)
kfree(batch->pfns);
}
-/* true if the pfn was added, false otherwise */
-static bool batch_add_pfn(struct pfn_batch *batch, unsigned long pfn)
+static bool batch_add_pfn_num(struct pfn_batch *batch, unsigned long pfn,
+ u32 nr)
{
const unsigned int MAX_NPFNS = type_max(typeof(*batch->npfns));
-
- if (batch->end &&
- pfn == batch->pfns[batch->end - 1] + batch->npfns[batch->end - 1] &&
- batch->npfns[batch->end - 1] != MAX_NPFNS) {
- batch->npfns[batch->end - 1]++;
- batch->total_pfns++;
- return true;
- }
- if (batch->end == batch->array_size)
+ unsigned int end = batch->end;
+
+ if (end && pfn == batch->pfns[end - 1] + batch->npfns[end - 1] &&
+ nr <= MAX_NPFNS - batch->npfns[end - 1]) {
+ batch->npfns[end - 1] += nr;
+ } else if (end < batch->array_size) {
+ batch->pfns[end] = pfn;
+ batch->npfns[end] = nr;
+ batch->end++;
+ } else {
return false;
- batch->total_pfns++;
- batch->pfns[batch->end] = pfn;
- batch->npfns[batch->end] = 1;
- batch->end++;
+ }
+
+ batch->total_pfns += nr;
return true;
}
+static void batch_remove_pfn_num(struct pfn_batch *batch, unsigned long nr)
+{
+ batch->npfns[batch->end - 1] -= nr;
+ if (batch->npfns[batch->end - 1] == 0)
+ batch->end--;
+ batch->total_pfns -= nr;
+}
+
+/* true if the pfn was added, false otherwise */
+static bool batch_add_pfn(struct pfn_batch *batch, unsigned long pfn)
+{
+ return batch_add_pfn_num(batch, pfn, 1);
+}
+
/*
* Fill the batch with pfns from the domain. When the batch is full, or it
* reaches last_index, the function will return. The caller should use
@@ -622,6 +637,41 @@ static void batch_from_pages(struct pfn_batch *batch, struct page **pages,
break;
}
+static int batch_from_folios(struct pfn_batch *batch, struct folio ***folios_p,
+ unsigned long *offset_p, unsigned long npages)
+{
+ int rc = 0;
+ struct folio **folios = *folios_p;
+ unsigned long offset = *offset_p;
+
+ while (npages) {
+ struct folio *folio = *folios;
+ unsigned long nr = folio_nr_pages(folio) - offset;
+ unsigned long pfn = page_to_pfn(folio_page(folio, offset));
+
+ nr = min(nr, npages);
+ npages -= nr;
+
+ if (!batch_add_pfn_num(batch, pfn, nr))
+ break;
+ if (nr > 1) {
+ rc = folio_add_pins(folio, nr - 1);
+ if (rc) {
+ batch_remove_pfn_num(batch, nr);
+ goto out;
+ }
+ }
+
+ folios++;
+ offset = 0;
+ }
+
+out:
+ *folios_p = folios;
+ *offset_p = offset;
+ return rc;
+}
+
static void batch_unpin(struct pfn_batch *batch, struct iopt_pages *pages,
unsigned int first_page_off, size_t npages)
{
@@ -703,19 +753,32 @@ struct pfn_reader_user {
* neither
*/
int locked;
+
+ /* The following are only valid if file != NULL. */
+ struct file *file;
+ struct folio **ufolios;
+ size_t ufolios_len;
+ unsigned long ufolios_offset;
+ struct folio **ufolios_next;
};
static void pfn_reader_user_init(struct pfn_reader_user *user,
struct iopt_pages *pages)
{
user->upages = NULL;
+ user->upages_len = 0;
user->upages_start = 0;
user->upages_end = 0;
user->locked = -1;
-
user->gup_flags = FOLL_LONGTERM;
if (pages->writable)
user->gup_flags |= FOLL_WRITE;
+
+ user->file = (pages->type == IOPT_ADDRESS_FILE) ? pages->file : NULL;
+ user->ufolios = NULL;
+ user->ufolios_len = 0;
+ user->ufolios_next = NULL;
+ user->ufolios_offset = 0;
}
static void pfn_reader_user_destroy(struct pfn_reader_user *user,
@@ -724,13 +787,67 @@ static void pfn_reader_user_destroy(struct pfn_reader_user *user,
if (user->locked != -1) {
if (user->locked)
mmap_read_unlock(pages->source_mm);
- if (pages->source_mm != current->mm)
+ if (!user->file && pages->source_mm != current->mm)
mmput(pages->source_mm);
user->locked = -1;
}
kfree(user->upages);
user->upages = NULL;
+ kfree(user->ufolios);
+ user->ufolios = NULL;
+}
+
+static long pin_memfd_pages(struct pfn_reader_user *user, unsigned long start,
+ unsigned long npages)
+{
+ unsigned long i;
+ unsigned long offset;
+ unsigned long npages_out = 0;
+ struct page **upages = user->upages;
+ unsigned long end = start + (npages << PAGE_SHIFT) - 1;
+ long nfolios = user->ufolios_len / sizeof(*user->ufolios);
+
+ /*
+ * todo: memfd_pin_folios should return the last pinned offset so
+ * we can compute npages pinned, and avoid looping over folios here
+ * if upages == NULL.
+ */
+ nfolios = memfd_pin_folios(user->file, start, end, user->ufolios,
+ nfolios, &offset);
+ if (nfolios <= 0)
+ return nfolios;
+
+ offset >>= PAGE_SHIFT;
+ user->ufolios_next = user->ufolios;
+ user->ufolios_offset = offset;
+
+ for (i = 0; i < nfolios; i++) {
+ struct folio *folio = user->ufolios[i];
+ unsigned long nr = folio_nr_pages(folio);
+ unsigned long npin = min(nr - offset, npages);
+
+ npages -= npin;
+ npages_out += npin;
+
+ if (upages) {
+ if (npin == 1) {
+ *upages++ = folio_page(folio, offset);
+ } else {
+ int rc = folio_add_pins(folio, npin - 1);
+
+ if (rc)
+ return rc;
+
+ while (npin--)
+ *upages++ = folio_page(folio, offset++);
+ }
+ }
+
+ offset = 0;
+ }
+
+ return npages_out;
}
static int pfn_reader_user_pin(struct pfn_reader_user *user,
@@ -739,7 +856,9 @@ static int pfn_reader_user_pin(struct pfn_reader_user *user,
unsigned long last_index)
{
bool remote_mm = pages->source_mm != current->mm;
- unsigned long npages;
+ unsigned long npages = last_index - start_index + 1;
+ unsigned long start;
+ unsigned long unum;
uintptr_t uptr;
long rc;
@@ -747,40 +866,50 @@ static int pfn_reader_user_pin(struct pfn_reader_user *user,
WARN_ON(last_index < start_index))
return -EINVAL;
- if (!user->upages) {
+ if (!user->file && !user->upages) {
/* All undone in pfn_reader_destroy() */
- user->upages_len =
- (last_index - start_index + 1) * sizeof(*user->upages);
+ user->upages_len = npages * sizeof(*user->upages);
user->upages = temp_kmalloc(&user->upages_len, NULL, 0);
if (!user->upages)
return -ENOMEM;
}
+ if (user->file && !user->ufolios) {
+ user->ufolios_len = npages * sizeof(*user->ufolios);
+ user->ufolios = temp_kmalloc(&user->ufolios_len, NULL, 0);
+ if (!user->ufolios)
+ return -ENOMEM;
+ }
+
if (user->locked == -1) {
/*
* The majority of usages will run the map task within the mm
* providing the pages, so we can optimize into
* get_user_pages_fast()
*/
- if (remote_mm) {
+ if (!user->file && remote_mm) {
if (!mmget_not_zero(pages->source_mm))
return -EFAULT;
}
user->locked = 0;
}
- npages = min_t(unsigned long, last_index - start_index + 1,
- user->upages_len / sizeof(*user->upages));
-
+ unum = user->file ? user->ufolios_len / sizeof(*user->ufolios) :
+ user->upages_len / sizeof(*user->upages);
+ npages = min_t(unsigned long, npages, unum);
if (iommufd_should_fail())
return -EFAULT;
- uptr = (uintptr_t)(pages->uptr + start_index * PAGE_SIZE);
- if (!remote_mm)
+ if (user->file) {
+ start = pages->start + (start_index * PAGE_SIZE);
+ rc = pin_memfd_pages(user, start, npages);
+ } else if (!remote_mm) {
+ uptr = (uintptr_t)(pages->uptr + start_index * PAGE_SIZE);
rc = pin_user_pages_fast(uptr, npages, user->gup_flags,
user->upages);
- else {
+ } else {
+ uptr = (uintptr_t)(pages->uptr + start_index * PAGE_SIZE);
if (!user->locked) {
mmap_read_lock(pages->source_mm);
user->locked = 1;
@@ -838,7 +967,8 @@ static int update_mm_locked_vm(struct iopt_pages *pages, unsigned long npages,
mmap_read_unlock(pages->source_mm);
user->locked = 0;
/* If we had the lock then we also have a get */
- } else if ((!user || !user->upages) &&
+
+ } else if ((!user || (!user->upages && !user->ufolios)) &&
pages->source_mm != current->mm) {
if (!mmget_not_zero(pages->source_mm))
return -EINVAL;
@@ -855,8 +985,8 @@ static int update_mm_locked_vm(struct iopt_pages *pages, unsigned long npages,
return rc;
}
-static int do_update_pinned(struct iopt_pages *pages, unsigned long npages,
- bool inc, struct pfn_reader_user *user)
+int iopt_pages_update_pinned(struct iopt_pages *pages, unsigned long npages,
+ bool inc, struct pfn_reader_user *user)
{
int rc = 0;
@@ -890,8 +1020,8 @@ static void update_unpinned(struct iopt_pages *pages)
return;
if (pages->npinned == pages->last_npinned)
return;
- do_update_pinned(pages, pages->last_npinned - pages->npinned, false,
- NULL);
+ iopt_pages_update_pinned(pages, pages->last_npinned - pages->npinned,
+ false, NULL);
}
/*
@@ -921,7 +1051,7 @@ static int pfn_reader_user_update_pinned(struct pfn_reader_user *user,
npages = pages->npinned - pages->last_npinned;
inc = true;
}
- return do_update_pinned(pages, npages, inc, user);
+ return iopt_pages_update_pinned(pages, npages, inc, user);
}
/*
@@ -978,6 +1108,8 @@ static int pfn_reader_fill_span(struct pfn_reader *pfns)
{
struct interval_tree_double_span_iter *span = &pfns->span;
unsigned long start_index = pfns->batch_end_index;
+ struct pfn_reader_user *user = &pfns->user;
+ unsigned long npages;
struct iopt_area *area;
int rc;
@@ -1015,11 +1147,17 @@ static int pfn_reader_fill_span(struct pfn_reader *pfns)
return rc;
}
- batch_from_pages(&pfns->batch,
- pfns->user.upages +
- (start_index - pfns->user.upages_start),
- pfns->user.upages_end - start_index);
- return 0;
+ npages = user->upages_end - start_index;
+ start_index -= user->upages_start;
+ rc = 0;
+
+ if (!user->file)
+ batch_from_pages(&pfns->batch, user->upages + start_index,
+ npages);
+ else
+ rc = batch_from_folios(&pfns->batch, &user->ufolios_next,
+ &user->ufolios_offset, npages);
+ return rc;
}
static bool pfn_reader_done(struct pfn_reader *pfns)
@@ -1092,16 +1230,25 @@ static int pfn_reader_init(struct pfn_reader *pfns, struct iopt_pages *pages,
static void pfn_reader_release_pins(struct pfn_reader *pfns)
{
struct iopt_pages *pages = pfns->pages;
+ struct pfn_reader_user *user = &pfns->user;
- if (pfns->user.upages_end > pfns->batch_end_index) {
- size_t npages = pfns->user.upages_end - pfns->batch_end_index;
-
+ if (user->upages_end > pfns->batch_end_index) {
/* Any pages not transferred to the batch are just unpinned */
- unpin_user_pages(pfns->user.upages + (pfns->batch_end_index -
- pfns->user.upages_start),
- npages);
+
+ unsigned long npages = user->upages_end - pfns->batch_end_index;
+ unsigned long start_index = pfns->batch_end_index -
+ user->upages_start;
+
+ if (!user->file) {
+ unpin_user_pages(user->upages + start_index, npages);
+ } else {
+ long n = user->ufolios_len / sizeof(*user->ufolios);
+
+ unpin_folios(user->ufolios_next,
+ user->ufolios + n - user->ufolios_next);
+ }
iopt_pages_sub_npinned(pages, npages);
- pfns->user.upages_end = pfns->batch_end_index;
+ user->upages_end = pfns->batch_end_index;
}
if (pfns->batch_start_index != pfns->batch_end_index) {
pfn_reader_unpin(pfns);
@@ -1139,11 +1286,11 @@ static int pfn_reader_first(struct pfn_reader *pfns, struct iopt_pages *pages,
return 0;
}
-struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
- bool writable)
+static struct iopt_pages *iopt_alloc_pages(unsigned long start_byte,
+ unsigned long length,
+ bool writable)
{
struct iopt_pages *pages;
- unsigned long end;
/*
* The iommu API uses size_t as the length, and protect the DIV_ROUND_UP
@@ -1152,9 +1299,6 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
if (length > SIZE_MAX - PAGE_SIZE || length == 0)
return ERR_PTR(-EINVAL);
- if (check_add_overflow((unsigned long)uptr, length, &end))
- return ERR_PTR(-EOVERFLOW);
-
pages = kzalloc(sizeof(*pages), GFP_KERNEL_ACCOUNT);
if (!pages)
return ERR_PTR(-ENOMEM);
@@ -1164,8 +1308,7 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
mutex_init(&pages->mutex);
pages->source_mm = current->mm;
mmgrab(pages->source_mm);
- pages->uptr = (void __user *)ALIGN_DOWN((uintptr_t)uptr, PAGE_SIZE);
- pages->npages = DIV_ROUND_UP(length + (uptr - pages->uptr), PAGE_SIZE);
+ pages->npages = DIV_ROUND_UP(length + start_byte, PAGE_SIZE);
pages->access_itree = RB_ROOT_CACHED;
pages->domains_itree = RB_ROOT_CACHED;
pages->writable = writable;
@@ -1179,6 +1322,45 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
return pages;
}
+struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
+ unsigned long length, bool writable)
+{
+ struct iopt_pages *pages;
+ unsigned long end;
+ void __user *uptr_down =
+ (void __user *) ALIGN_DOWN((uintptr_t)uptr, PAGE_SIZE);
+
+ if (check_add_overflow((unsigned long)uptr, length, &end))
+ return ERR_PTR(-EOVERFLOW);
+
+ pages = iopt_alloc_pages(uptr - uptr_down, length, writable);
+ if (IS_ERR(pages))
+ return pages;
+ pages->uptr = uptr_down;
+ pages->type = IOPT_ADDRESS_USER;
+ return pages;
+}
+
+struct iopt_pages *iopt_alloc_file_pages(struct file *file, unsigned long start,
+ unsigned long length, bool writable)
+
+{
+ struct iopt_pages *pages;
+ unsigned long start_down = ALIGN_DOWN(start, PAGE_SIZE);
+ unsigned long end;
+
+ if (length && check_add_overflow(start, length - 1, &end))
+ return ERR_PTR(-EOVERFLOW);
+
+ pages = iopt_alloc_pages(start - start_down, length, writable);
+ if (IS_ERR(pages))
+ return pages;
+ pages->file = get_file(file);
+ pages->start = start_down;
+ pages->type = IOPT_ADDRESS_FILE;
+ return pages;
+}
+
void iopt_release_pages(struct kref *kref)
{
struct iopt_pages *pages = container_of(kref, struct iopt_pages, kref);
@@ -1191,6 +1373,8 @@ void iopt_release_pages(struct kref *kref)
mutex_destroy(&pages->mutex);
put_task_struct(pages->source_task);
free_uid(pages->source_user);
+ if (pages->type == IOPT_ADDRESS_FILE)
+ fput(pages->file);
kfree(pages);
}
@@ -1630,11 +1814,11 @@ static int iopt_pages_fill_from_domain(struct iopt_pages *pages,
return 0;
}
-static int iopt_pages_fill_from_mm(struct iopt_pages *pages,
- struct pfn_reader_user *user,
- unsigned long start_index,
- unsigned long last_index,
- struct page **out_pages)
+static int iopt_pages_fill(struct iopt_pages *pages,
+ struct pfn_reader_user *user,
+ unsigned long start_index,
+ unsigned long last_index,
+ struct page **out_pages)
{
unsigned long cur_index = start_index;
int rc;
@@ -1708,8 +1892,8 @@ int iopt_pages_fill_xarray(struct iopt_pages *pages, unsigned long start_index,
/* hole */
cur_pages = out_pages + (span.start_hole - start_index);
- rc = iopt_pages_fill_from_mm(pages, &user, span.start_hole,
- span.last_hole, cur_pages);
+ rc = iopt_pages_fill(pages, &user, span.start_hole,
+ span.last_hole, cur_pages);
if (rc)
goto out_clean_xa;
rc = pages_to_xarray(&pages->pinned_pfns, span.start_hole,
@@ -1789,6 +1973,10 @@ static int iopt_pages_rw_page(struct iopt_pages *pages, unsigned long index,
struct page *page = NULL;
int rc;
+ if (IS_ENABLED(CONFIG_IOMMUFD_TEST) &&
+ WARN_ON(pages->type != IOPT_ADDRESS_USER))
+ return -EINVAL;
+
if (!mmget_not_zero(pages->source_mm))
return iopt_pages_rw_slow(pages, index, index, offset, data,
length, flags);
@@ -1844,6 +2032,15 @@ int iopt_pages_rw_access(struct iopt_pages *pages, unsigned long start_byte,
if ((flags & IOMMUFD_ACCESS_RW_WRITE) && !pages->writable)
return -EPERM;
+ if (pages->type == IOPT_ADDRESS_FILE)
+ return iopt_pages_rw_slow(pages, start_index, last_index,
+ start_byte % PAGE_SIZE, data, length,
+ flags);
+
+ if (IS_ENABLED(CONFIG_IOMMUFD_TEST) &&
+ WARN_ON(pages->type != IOPT_ADDRESS_USER))
+ return -EINVAL;
+
if (!(flags & IOMMUFD_ACCESS_RW_KTHREAD) && change_mm) {
if (start_index == last_index)
return iopt_pages_rw_page(pages, start_index,
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 540437be168a..a0de6d6d4e68 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -126,12 +126,35 @@ struct mock_iommu_domain {
struct xarray pfns;
};
+static inline struct mock_iommu_domain *
+to_mock_domain(struct iommu_domain *domain)
+{
+ return container_of(domain, struct mock_iommu_domain, domain);
+}
+
struct mock_iommu_domain_nested {
struct iommu_domain domain;
+ struct mock_viommu *mock_viommu;
struct mock_iommu_domain *parent;
u32 iotlb[MOCK_NESTED_DOMAIN_IOTLB_NUM];
};
+static inline struct mock_iommu_domain_nested *
+to_mock_nested(struct iommu_domain *domain)
+{
+ return container_of(domain, struct mock_iommu_domain_nested, domain);
+}
+
+struct mock_viommu {
+ struct iommufd_viommu core;
+ struct mock_iommu_domain *s2_parent;
+};
+
+static inline struct mock_viommu *to_mock_viommu(struct iommufd_viommu *viommu)
+{
+ return container_of(viommu, struct mock_viommu, core);
+}
+
enum selftest_obj_type {
TYPE_IDEV,
};
@@ -140,8 +163,14 @@ struct mock_dev {
struct device dev;
unsigned long flags;
int id;
+ u32 cache[MOCK_DEV_CACHE_NUM];
};
+static inline struct mock_dev *to_mock_dev(struct device *dev)
+{
+ return container_of(dev, struct mock_dev, dev);
+}
+
struct selftest_obj {
struct iommufd_object obj;
enum selftest_obj_type type;
@@ -155,10 +184,15 @@ struct selftest_obj {
};
};
+static inline struct selftest_obj *to_selftest_obj(struct iommufd_object *obj)
+{
+ return container_of(obj, struct selftest_obj, obj);
+}
+
static int mock_domain_nop_attach(struct iommu_domain *domain,
struct device *dev)
{
- struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
+ struct mock_dev *mdev = to_mock_dev(dev);
if (domain->dirty_ops && (mdev->flags & MOCK_FLAGS_DEVICE_NO_DIRTY))
return -EINVAL;
@@ -193,8 +227,7 @@ static void *mock_domain_hw_info(struct device *dev, u32 *length, u32 *type)
static int mock_domain_set_dirty_tracking(struct iommu_domain *domain,
bool enable)
{
- struct mock_iommu_domain *mock =
- container_of(domain, struct mock_iommu_domain, domain);
+ struct mock_iommu_domain *mock = to_mock_domain(domain);
unsigned long flags = mock->flags;
if (enable && !domain->dirty_ops)
@@ -243,8 +276,7 @@ static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain,
unsigned long flags,
struct iommu_dirty_bitmap *dirty)
{
- struct mock_iommu_domain *mock =
- container_of(domain, struct mock_iommu_domain, domain);
+ struct mock_iommu_domain *mock = to_mock_domain(domain);
unsigned long end = iova + size;
void *ent;
@@ -281,7 +313,7 @@ static const struct iommu_dirty_ops dirty_ops = {
static struct iommu_domain *mock_domain_alloc_paging(struct device *dev)
{
- struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
+ struct mock_dev *mdev = to_mock_dev(dev);
struct mock_iommu_domain *mock;
mock = kzalloc(sizeof(*mock), GFP_KERNEL);
@@ -298,76 +330,81 @@ static struct iommu_domain *mock_domain_alloc_paging(struct device *dev)
return &mock->domain;
}
-static struct iommu_domain *
-__mock_domain_alloc_nested(struct mock_iommu_domain *mock_parent,
- const struct iommu_hwpt_selftest *user_cfg)
+static struct mock_iommu_domain_nested *
+__mock_domain_alloc_nested(const struct iommu_user_data *user_data)
{
struct mock_iommu_domain_nested *mock_nested;
- int i;
+ struct iommu_hwpt_selftest user_cfg;
+ int rc, i;
+
+ if (user_data->type != IOMMU_HWPT_DATA_SELFTEST)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ rc = iommu_copy_struct_from_user(&user_cfg, user_data,
+ IOMMU_HWPT_DATA_SELFTEST, iotlb);
+ if (rc)
+ return ERR_PTR(rc);
mock_nested = kzalloc(sizeof(*mock_nested), GFP_KERNEL);
if (!mock_nested)
return ERR_PTR(-ENOMEM);
- mock_nested->parent = mock_parent;
mock_nested->domain.ops = &domain_nested_ops;
mock_nested->domain.type = IOMMU_DOMAIN_NESTED;
for (i = 0; i < MOCK_NESTED_DOMAIN_IOTLB_NUM; i++)
- mock_nested->iotlb[i] = user_cfg->iotlb;
- return &mock_nested->domain;
+ mock_nested->iotlb[i] = user_cfg.iotlb;
+ return mock_nested;
}
static struct iommu_domain *
-mock_domain_alloc_user(struct device *dev, u32 flags,
- struct iommu_domain *parent,
- const struct iommu_user_data *user_data)
+mock_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+ u32 flags, const struct iommu_user_data *user_data)
{
+ struct mock_iommu_domain_nested *mock_nested;
struct mock_iommu_domain *mock_parent;
- struct iommu_hwpt_selftest user_cfg;
- int rc;
- /* must be mock_domain */
- if (!parent) {
- struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
- bool has_dirty_flag = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
- bool no_dirty_ops = mdev->flags & MOCK_FLAGS_DEVICE_NO_DIRTY;
- struct iommu_domain *domain;
-
- if (flags & (~(IOMMU_HWPT_ALLOC_NEST_PARENT |
- IOMMU_HWPT_ALLOC_DIRTY_TRACKING)))
- return ERR_PTR(-EOPNOTSUPP);
- if (user_data || (has_dirty_flag && no_dirty_ops))
- return ERR_PTR(-EOPNOTSUPP);
- domain = mock_domain_alloc_paging(dev);
- if (!domain)
- return ERR_PTR(-ENOMEM);
- if (has_dirty_flag)
- container_of(domain, struct mock_iommu_domain, domain)
- ->domain.dirty_ops = &dirty_ops;
- return domain;
- }
-
- /* must be mock_domain_nested */
- if (user_data->type != IOMMU_HWPT_DATA_SELFTEST || flags)
+ if (flags)
return ERR_PTR(-EOPNOTSUPP);
if (!parent || parent->ops != mock_ops.default_domain_ops)
return ERR_PTR(-EINVAL);
- mock_parent = container_of(parent, struct mock_iommu_domain, domain);
+ mock_parent = to_mock_domain(parent);
if (!mock_parent)
return ERR_PTR(-EINVAL);
- rc = iommu_copy_struct_from_user(&user_cfg, user_data,
- IOMMU_HWPT_DATA_SELFTEST, iotlb);
- if (rc)
- return ERR_PTR(rc);
+ mock_nested = __mock_domain_alloc_nested(user_data);
+ if (IS_ERR(mock_nested))
+ return ERR_CAST(mock_nested);
+ mock_nested->parent = mock_parent;
+ return &mock_nested->domain;
+}
- return __mock_domain_alloc_nested(mock_parent, &user_cfg);
+static struct iommu_domain *
+mock_domain_alloc_paging_flags(struct device *dev, u32 flags,
+ const struct iommu_user_data *user_data)
+{
+ bool has_dirty_flag = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
+ const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
+ IOMMU_HWPT_ALLOC_NEST_PARENT;
+ bool no_dirty_ops = to_mock_dev(dev)->flags &
+ MOCK_FLAGS_DEVICE_NO_DIRTY;
+ struct iommu_domain *domain;
+
+ if (user_data)
+ return ERR_PTR(-EOPNOTSUPP);
+ if ((flags & ~PAGING_FLAGS) || (has_dirty_flag && no_dirty_ops))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ domain = mock_domain_alloc_paging(dev);
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+ if (has_dirty_flag)
+ domain->dirty_ops = &dirty_ops;
+ return domain;
}
static void mock_domain_free(struct iommu_domain *domain)
{
- struct mock_iommu_domain *mock =
- container_of(domain, struct mock_iommu_domain, domain);
+ struct mock_iommu_domain *mock = to_mock_domain(domain);
WARN_ON(!xa_empty(&mock->pfns));
kfree(mock);
@@ -378,8 +415,7 @@ static int mock_domain_map_pages(struct iommu_domain *domain,
size_t pgsize, size_t pgcount, int prot,
gfp_t gfp, size_t *mapped)
{
- struct mock_iommu_domain *mock =
- container_of(domain, struct mock_iommu_domain, domain);
+ struct mock_iommu_domain *mock = to_mock_domain(domain);
unsigned long flags = MOCK_PFN_START_IOVA;
unsigned long start_iova = iova;
@@ -430,8 +466,7 @@ static size_t mock_domain_unmap_pages(struct iommu_domain *domain,
size_t pgcount,
struct iommu_iotlb_gather *iotlb_gather)
{
- struct mock_iommu_domain *mock =
- container_of(domain, struct mock_iommu_domain, domain);
+ struct mock_iommu_domain *mock = to_mock_domain(domain);
bool first = true;
size_t ret = 0;
void *ent;
@@ -479,8 +514,7 @@ static size_t mock_domain_unmap_pages(struct iommu_domain *domain,
static phys_addr_t mock_domain_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{
- struct mock_iommu_domain *mock =
- container_of(domain, struct mock_iommu_domain, domain);
+ struct mock_iommu_domain *mock = to_mock_domain(domain);
void *ent;
WARN_ON(iova % MOCK_IO_PAGE_SIZE);
@@ -491,7 +525,7 @@ static phys_addr_t mock_domain_iova_to_phys(struct iommu_domain *domain,
static bool mock_domain_capable(struct device *dev, enum iommu_cap cap)
{
- struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
+ struct mock_dev *mdev = to_mock_dev(dev);
switch (cap) {
case IOMMU_CAP_CACHE_COHERENCY:
@@ -507,14 +541,17 @@ static bool mock_domain_capable(struct device *dev, enum iommu_cap cap)
static struct iopf_queue *mock_iommu_iopf_queue;
-static struct iommu_device mock_iommu_device = {
-};
+static struct mock_iommu_device {
+ struct iommu_device iommu_dev;
+ struct completion complete;
+ refcount_t users;
+} mock_iommu;
static struct iommu_device *mock_probe_device(struct device *dev)
{
if (dev->bus != &iommufd_mock_bus_type.bus)
return ERR_PTR(-ENODEV);
- return &mock_iommu_device;
+ return &mock_iommu.iommu_dev;
}
static void mock_domain_page_response(struct device *dev, struct iopf_fault *evt,
@@ -540,6 +577,132 @@ static int mock_dev_disable_feat(struct device *dev, enum iommu_dev_features fea
return 0;
}
+static void mock_viommu_destroy(struct iommufd_viommu *viommu)
+{
+ struct mock_iommu_device *mock_iommu = container_of(
+ viommu->iommu_dev, struct mock_iommu_device, iommu_dev);
+
+ if (refcount_dec_and_test(&mock_iommu->users))
+ complete(&mock_iommu->complete);
+
+ /* iommufd core frees mock_viommu and viommu */
+}
+
+static struct iommu_domain *
+mock_viommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
+ const struct iommu_user_data *user_data)
+{
+ struct mock_viommu *mock_viommu = to_mock_viommu(viommu);
+ struct mock_iommu_domain_nested *mock_nested;
+
+ if (flags & ~IOMMU_HWPT_FAULT_ID_VALID)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ mock_nested = __mock_domain_alloc_nested(user_data);
+ if (IS_ERR(mock_nested))
+ return ERR_CAST(mock_nested);
+ mock_nested->mock_viommu = mock_viommu;
+ mock_nested->parent = mock_viommu->s2_parent;
+ return &mock_nested->domain;
+}
+
+static int mock_viommu_cache_invalidate(struct iommufd_viommu *viommu,
+ struct iommu_user_data_array *array)
+{
+ struct iommu_viommu_invalidate_selftest *cmds;
+ struct iommu_viommu_invalidate_selftest *cur;
+ struct iommu_viommu_invalidate_selftest *end;
+ int rc;
+
+ /* A zero-length array is allowed to validate the array type */
+ if (array->entry_num == 0 &&
+ array->type == IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST) {
+ array->entry_num = 0;
+ return 0;
+ }
+
+ cmds = kcalloc(array->entry_num, sizeof(*cmds), GFP_KERNEL);
+ if (!cmds)
+ return -ENOMEM;
+ cur = cmds;
+ end = cmds + array->entry_num;
+
+ static_assert(sizeof(*cmds) == 3 * sizeof(u32));
+ rc = iommu_copy_struct_from_full_user_array(
+ cmds, sizeof(*cmds), array,
+ IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST);
+ if (rc)
+ goto out;
+
+ while (cur != end) {
+ struct mock_dev *mdev;
+ struct device *dev;
+ int i;
+
+ if (cur->flags & ~IOMMU_TEST_INVALIDATE_FLAG_ALL) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (cur->cache_id > MOCK_DEV_CACHE_ID_MAX) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ xa_lock(&viommu->vdevs);
+ dev = iommufd_viommu_find_dev(viommu,
+ (unsigned long)cur->vdev_id);
+ if (!dev) {
+ xa_unlock(&viommu->vdevs);
+ rc = -EINVAL;
+ goto out;
+ }
+ mdev = container_of(dev, struct mock_dev, dev);
+
+ if (cur->flags & IOMMU_TEST_INVALIDATE_FLAG_ALL) {
+ /* Invalidate all cache entries and ignore cache_id */
+ for (i = 0; i < MOCK_DEV_CACHE_NUM; i++)
+ mdev->cache[i] = 0;
+ } else {
+ mdev->cache[cur->cache_id] = 0;
+ }
+ xa_unlock(&viommu->vdevs);
+
+ cur++;
+ }
+out:
+ array->entry_num = cur - cmds;
+ kfree(cmds);
+ return rc;
+}
+
+static struct iommufd_viommu_ops mock_viommu_ops = {
+ .destroy = mock_viommu_destroy,
+ .alloc_domain_nested = mock_viommu_alloc_domain_nested,
+ .cache_invalidate = mock_viommu_cache_invalidate,
+};
+
+static struct iommufd_viommu *mock_viommu_alloc(struct device *dev,
+ struct iommu_domain *domain,
+ struct iommufd_ctx *ictx,
+ unsigned int viommu_type)
+{
+ struct mock_iommu_device *mock_iommu =
+ iommu_get_iommu_dev(dev, struct mock_iommu_device, iommu_dev);
+ struct mock_viommu *mock_viommu;
+
+ if (viommu_type != IOMMU_VIOMMU_TYPE_SELFTEST)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ mock_viommu = iommufd_viommu_alloc(ictx, struct mock_viommu, core,
+ &mock_viommu_ops);
+ if (IS_ERR(mock_viommu))
+ return ERR_CAST(mock_viommu);
+
+ refcount_inc(&mock_iommu->users);
+ return &mock_viommu->core;
+}
+
static const struct iommu_ops mock_ops = {
/*
* IOMMU_DOMAIN_BLOCKED cannot be returned from def_domain_type()
@@ -551,7 +714,8 @@ static const struct iommu_ops mock_ops = {
.pgsize_bitmap = MOCK_IO_PAGE_SIZE,
.hw_info = mock_domain_hw_info,
.domain_alloc_paging = mock_domain_alloc_paging,
- .domain_alloc_user = mock_domain_alloc_user,
+ .domain_alloc_paging_flags = mock_domain_alloc_paging_flags,
+ .domain_alloc_nested = mock_domain_alloc_nested,
.capable = mock_domain_capable,
.device_group = generic_device_group,
.probe_device = mock_probe_device,
@@ -559,6 +723,7 @@ static const struct iommu_ops mock_ops = {
.dev_enable_feat = mock_dev_enable_feat,
.dev_disable_feat = mock_dev_disable_feat,
.user_pasid_table = true,
+ .viommu_alloc = mock_viommu_alloc,
.default_domain_ops =
&(struct iommu_domain_ops){
.free = mock_domain_free,
@@ -571,18 +736,14 @@ static const struct iommu_ops mock_ops = {
static void mock_domain_free_nested(struct iommu_domain *domain)
{
- struct mock_iommu_domain_nested *mock_nested =
- container_of(domain, struct mock_iommu_domain_nested, domain);
-
- kfree(mock_nested);
+ kfree(to_mock_nested(domain));
}
static int
mock_domain_cache_invalidate_user(struct iommu_domain *domain,
struct iommu_user_data_array *array)
{
- struct mock_iommu_domain_nested *mock_nested =
- container_of(domain, struct mock_iommu_domain_nested, domain);
+ struct mock_iommu_domain_nested *mock_nested = to_mock_nested(domain);
struct iommu_hwpt_invalidate_selftest inv;
u32 processed = 0;
int i = 0, j;
@@ -657,7 +818,7 @@ get_md_pagetable(struct iommufd_ucmd *ucmd, u32 mockpt_id,
iommufd_put_object(ucmd->ictx, &hwpt->obj);
return ERR_PTR(-EINVAL);
}
- *mock = container_of(hwpt->domain, struct mock_iommu_domain, domain);
+ *mock = to_mock_domain(hwpt->domain);
return hwpt;
}
@@ -675,14 +836,13 @@ get_md_pagetable_nested(struct iommufd_ucmd *ucmd, u32 mockpt_id,
iommufd_put_object(ucmd->ictx, &hwpt->obj);
return ERR_PTR(-EINVAL);
}
- *mock_nested = container_of(hwpt->domain,
- struct mock_iommu_domain_nested, domain);
+ *mock_nested = to_mock_nested(hwpt->domain);
return hwpt;
}
static void mock_dev_release(struct device *dev)
{
- struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
+ struct mock_dev *mdev = to_mock_dev(dev);
ida_free(&mock_dev_ida, mdev->id);
kfree(mdev);
@@ -691,7 +851,7 @@ static void mock_dev_release(struct device *dev)
static struct mock_dev *mock_dev_create(unsigned long dev_flags)
{
struct mock_dev *mdev;
- int rc;
+ int rc, i;
if (dev_flags &
~(MOCK_FLAGS_DEVICE_NO_DIRTY | MOCK_FLAGS_DEVICE_HUGE_IOVA))
@@ -705,6 +865,8 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
mdev->flags = dev_flags;
mdev->dev.release = mock_dev_release;
mdev->dev.bus = &iommufd_mock_bus_type.bus;
+ for (i = 0; i < MOCK_DEV_CACHE_NUM; i++)
+ mdev->cache[i] = IOMMU_TEST_DEV_CACHE_DEFAULT;
rc = ida_alloc(&mock_dev_ida, GFP_KERNEL);
if (rc < 0)
@@ -813,7 +975,7 @@ static int iommufd_test_mock_domain_replace(struct iommufd_ucmd *ucmd,
if (IS_ERR(dev_obj))
return PTR_ERR(dev_obj);
- sobj = container_of(dev_obj, struct selftest_obj, obj);
+ sobj = to_selftest_obj(dev_obj);
if (sobj->type != TYPE_IDEV) {
rc = -EINVAL;
goto out_dev_obj;
@@ -951,8 +1113,7 @@ static int iommufd_test_md_check_iotlb(struct iommufd_ucmd *ucmd,
if (IS_ERR(hwpt))
return PTR_ERR(hwpt);
- mock_nested = container_of(hwpt->domain,
- struct mock_iommu_domain_nested, domain);
+ mock_nested = to_mock_nested(hwpt->domain);
if (iotlb_id > MOCK_NESTED_DOMAIN_IOTLB_ID_MAX ||
mock_nested->iotlb[iotlb_id] != iotlb)
@@ -961,6 +1122,24 @@ static int iommufd_test_md_check_iotlb(struct iommufd_ucmd *ucmd,
return rc;
}
+static int iommufd_test_dev_check_cache(struct iommufd_ucmd *ucmd, u32 idev_id,
+ unsigned int cache_id, u32 cache)
+{
+ struct iommufd_device *idev;
+ struct mock_dev *mdev;
+ int rc = 0;
+
+ idev = iommufd_get_device(ucmd, idev_id);
+ if (IS_ERR(idev))
+ return PTR_ERR(idev);
+ mdev = container_of(idev->dev, struct mock_dev, dev);
+
+ if (cache_id > MOCK_DEV_CACHE_ID_MAX || mdev->cache[cache_id] != cache)
+ rc = -EINVAL;
+ iommufd_put_object(ucmd->ictx, &idev->obj);
+ return rc;
+}
+
struct selftest_access {
struct iommufd_access *access;
struct file *file;
@@ -1431,7 +1610,7 @@ static int iommufd_test_trigger_iopf(struct iommufd_ucmd *ucmd,
void iommufd_selftest_destroy(struct iommufd_object *obj)
{
- struct selftest_obj *sobj = container_of(obj, struct selftest_obj, obj);
+ struct selftest_obj *sobj = to_selftest_obj(obj);
switch (sobj->type) {
case TYPE_IDEV:
@@ -1470,6 +1649,10 @@ int iommufd_test(struct iommufd_ucmd *ucmd)
return iommufd_test_md_check_iotlb(ucmd, cmd->id,
cmd->check_iotlb.id,
cmd->check_iotlb.iotlb);
+ case IOMMU_TEST_OP_DEV_CHECK_CACHE:
+ return iommufd_test_dev_check_cache(ucmd, cmd->id,
+ cmd->check_dev_cache.id,
+ cmd->check_dev_cache.cache);
case IOMMU_TEST_OP_CREATE_ACCESS:
return iommufd_test_create_access(ucmd, cmd->id,
cmd->create_access.flags);
@@ -1536,24 +1719,27 @@ int __init iommufd_test_init(void)
if (rc)
goto err_platform;
- rc = iommu_device_sysfs_add(&mock_iommu_device,
+ rc = iommu_device_sysfs_add(&mock_iommu.iommu_dev,
&selftest_iommu_dev->dev, NULL, "%s",
dev_name(&selftest_iommu_dev->dev));
if (rc)
goto err_bus;
- rc = iommu_device_register_bus(&mock_iommu_device, &mock_ops,
+ rc = iommu_device_register_bus(&mock_iommu.iommu_dev, &mock_ops,
&iommufd_mock_bus_type.bus,
&iommufd_mock_bus_type.nb);
if (rc)
goto err_sysfs;
+ refcount_set(&mock_iommu.users, 1);
+ init_completion(&mock_iommu.complete);
+
mock_iommu_iopf_queue = iopf_queue_alloc("mock-iopfq");
return 0;
err_sysfs:
- iommu_device_sysfs_remove(&mock_iommu_device);
+ iommu_device_sysfs_remove(&mock_iommu.iommu_dev);
err_bus:
bus_unregister(&iommufd_mock_bus_type.bus);
err_platform:
@@ -1563,6 +1749,22 @@ err_dbgfs:
return rc;
}
+static void iommufd_test_wait_for_users(void)
+{
+ if (refcount_dec_and_test(&mock_iommu.users))
+ return;
+ /*
+ * Time out waiting for iommu device user count to become 0.
+ *
+ * Note that this is just making an example here, since the selftest is
+ * built into the iommufd module, i.e. it only unplugs the iommu device
+ * when unloading the module. So, it is expected that this WARN_ON will
+ * not trigger, as long as any iommufd FDs are open.
+ */
+ WARN_ON(!wait_for_completion_timeout(&mock_iommu.complete,
+ msecs_to_jiffies(10000)));
+}
+
void iommufd_test_exit(void)
{
if (mock_iommu_iopf_queue) {
@@ -1570,8 +1772,9 @@ void iommufd_test_exit(void)
mock_iommu_iopf_queue = NULL;
}
- iommu_device_sysfs_remove(&mock_iommu_device);
- iommu_device_unregister_bus(&mock_iommu_device,
+ iommufd_test_wait_for_users();
+ iommu_device_sysfs_remove(&mock_iommu.iommu_dev);
+ iommu_device_unregister_bus(&mock_iommu.iommu_dev,
&iommufd_mock_bus_type.bus,
&iommufd_mock_bus_type.nb);
bus_unregister(&iommufd_mock_bus_type.bus);
diff --git a/drivers/iommu/iommufd/vfio_compat.c b/drivers/iommu/iommufd/vfio_compat.c
index a3ad5f0b6c59..514aacd64009 100644
--- a/drivers/iommu/iommufd/vfio_compat.c
+++ b/drivers/iommu/iommufd/vfio_compat.c
@@ -291,12 +291,7 @@ static int iommufd_vfio_check_extension(struct iommufd_ctx *ictx,
case VFIO_DMA_CC_IOMMU:
return iommufd_vfio_cc_iommu(ictx);
- /*
- * This is obsolete, and to be removed from VFIO. It was an incomplete
- * idea that got merged.
- * https://lore.kernel.org/kvm/0-v1-0093c9b0e345+19-vfio_no_nesting_jgg@nvidia.com/
- */
- case VFIO_TYPE1_NESTING_IOMMU:
+ case __VFIO_RESERVED_TYPE1_NESTING_IOMMU:
return 0;
/*
diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
new file mode 100644
index 000000000000..69b88e8c7c26
--- /dev/null
+++ b/drivers/iommu/iommufd/viommu.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
+ */
+#include "iommufd_private.h"
+
+void iommufd_viommu_destroy(struct iommufd_object *obj)
+{
+ struct iommufd_viommu *viommu =
+ container_of(obj, struct iommufd_viommu, obj);
+
+ if (viommu->ops && viommu->ops->destroy)
+ viommu->ops->destroy(viommu);
+ refcount_dec(&viommu->hwpt->common.obj.users);
+ xa_destroy(&viommu->vdevs);
+}
+
+int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
+{
+ struct iommu_viommu_alloc *cmd = ucmd->cmd;
+ struct iommufd_hwpt_paging *hwpt_paging;
+ struct iommufd_viommu *viommu;
+ struct iommufd_device *idev;
+ const struct iommu_ops *ops;
+ int rc;
+
+ if (cmd->flags || cmd->type == IOMMU_VIOMMU_TYPE_DEFAULT)
+ return -EOPNOTSUPP;
+
+ idev = iommufd_get_device(ucmd, cmd->dev_id);
+ if (IS_ERR(idev))
+ return PTR_ERR(idev);
+
+ ops = dev_iommu_ops(idev->dev);
+ if (!ops->viommu_alloc) {
+ rc = -EOPNOTSUPP;
+ goto out_put_idev;
+ }
+
+ hwpt_paging = iommufd_get_hwpt_paging(ucmd, cmd->hwpt_id);
+ if (IS_ERR(hwpt_paging)) {
+ rc = PTR_ERR(hwpt_paging);
+ goto out_put_idev;
+ }
+
+ if (!hwpt_paging->nest_parent) {
+ rc = -EINVAL;
+ goto out_put_hwpt;
+ }
+
+ viommu = ops->viommu_alloc(idev->dev, hwpt_paging->common.domain,
+ ucmd->ictx, cmd->type);
+ if (IS_ERR(viommu)) {
+ rc = PTR_ERR(viommu);
+ goto out_put_hwpt;
+ }
+
+ xa_init(&viommu->vdevs);
+ viommu->type = cmd->type;
+ viommu->ictx = ucmd->ictx;
+ viommu->hwpt = hwpt_paging;
+ refcount_inc(&viommu->hwpt->common.obj.users);
+ /*
+ * It is the most likely case that a physical IOMMU is unpluggable. A
+ * pluggable IOMMU instance (if exists) is responsible for refcounting
+ * on its own.
+ */
+ viommu->iommu_dev = __iommu_get_iommu_dev(idev->dev);
+
+ cmd->out_viommu_id = viommu->obj.id;
+ rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
+ if (rc)
+ goto out_abort;
+ iommufd_object_finalize(ucmd->ictx, &viommu->obj);
+ goto out_put_hwpt;
+
+out_abort:
+ iommufd_object_abort_and_destroy(ucmd->ictx, &viommu->obj);
+out_put_hwpt:
+ iommufd_put_object(ucmd->ictx, &hwpt_paging->common.obj);
+out_put_idev:
+ iommufd_put_object(ucmd->ictx, &idev->obj);
+ return rc;
+}
+
+void iommufd_vdevice_destroy(struct iommufd_object *obj)
+{
+ struct iommufd_vdevice *vdev =
+ container_of(obj, struct iommufd_vdevice, obj);
+ struct iommufd_viommu *viommu = vdev->viommu;
+
+ /* xa_cmpxchg is okay to fail if alloc failed xa_cmpxchg previously */
+ xa_cmpxchg(&viommu->vdevs, vdev->id, vdev, NULL, GFP_KERNEL);
+ refcount_dec(&viommu->obj.users);
+ put_device(vdev->dev);
+}
+
+int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
+{
+ struct iommu_vdevice_alloc *cmd = ucmd->cmd;
+ struct iommufd_vdevice *vdev, *curr;
+ struct iommufd_viommu *viommu;
+ struct iommufd_device *idev;
+ u64 virt_id = cmd->virt_id;
+ int rc = 0;
+
+ /* virt_id indexes an xarray */
+ if (virt_id > ULONG_MAX)
+ return -EINVAL;
+
+ viommu = iommufd_get_viommu(ucmd, cmd->viommu_id);
+ if (IS_ERR(viommu))
+ return PTR_ERR(viommu);
+
+ idev = iommufd_get_device(ucmd, cmd->dev_id);
+ if (IS_ERR(idev)) {
+ rc = PTR_ERR(idev);
+ goto out_put_viommu;
+ }
+
+ if (viommu->iommu_dev != __iommu_get_iommu_dev(idev->dev)) {
+ rc = -EINVAL;
+ goto out_put_idev;
+ }
+
+ vdev = iommufd_object_alloc(ucmd->ictx, vdev, IOMMUFD_OBJ_VDEVICE);
+ if (IS_ERR(vdev)) {
+ rc = PTR_ERR(vdev);
+ goto out_put_idev;
+ }
+
+ vdev->id = virt_id;
+ vdev->dev = idev->dev;
+ get_device(idev->dev);
+ vdev->viommu = viommu;
+ refcount_inc(&viommu->obj.users);
+
+ curr = xa_cmpxchg(&viommu->vdevs, virt_id, NULL, vdev, GFP_KERNEL);
+ if (curr) {
+ rc = xa_err(curr) ?: -EEXIST;
+ goto out_abort;
+ }
+
+ cmd->out_vdevice_id = vdev->obj.id;
+ rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
+ if (rc)
+ goto out_abort;
+ iommufd_object_finalize(ucmd->ictx, &vdev->obj);
+ goto out_put_idev;
+
+out_abort:
+ iommufd_object_abort_and_destroy(ucmd->ictx, &vdev->obj);
+out_put_idev:
+ iommufd_put_object(ucmd->ictx, &idev->obj);
+out_put_viommu:
+ iommufd_put_object(ucmd->ictx, &viommu->obj);
+ return rc;
+}
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 16c6adff3eb7..18f839721813 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -6,6 +6,7 @@
*/
#include <linux/iova.h>
+#include <linux/kmemleak.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/smp.h>
@@ -506,7 +507,7 @@ __adjust_overlap_range(struct iova *iova,
* reserve_iova - reserves an iova in the given range
* @iovad: - iova domain pointer
* @pfn_lo: - lower page frame address
- * @pfn_hi:- higher pfn adderss
+ * @pfn_hi:- higher pfn address
* This function allocates reserves the address range from pfn_lo to pfn_hi so
* that this address is not dished out as part of alloc_iova.
*/
@@ -673,6 +674,11 @@ static struct iova_magazine *iova_depot_pop(struct iova_rcache *rcache)
{
struct iova_magazine *mag = rcache->depot;
+ /*
+ * As the mag->next pointer is moved to rcache->depot and reset via
+ * the mag->size assignment, mark it as a transient false positive.
+ */
+ kmemleak_transient_leak(mag->next);
rcache->depot = mag->next;
mag->size = IOVA_MAG_SIZE;
rcache->depot_size--;
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 6a2707fe7a78..c45313c43b9e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1599,7 +1599,7 @@ static const unsigned int mt8186_larb_region_msk[MT8192_MULTI_REGION_NR_MAX][MTK
static const struct mtk_iommu_plat_data mt8186_data_mm = {
.m4u_plat = M4U_MT8186,
.flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN |
- WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM,
+ WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM | PGTABLE_PA_35_EN,
.larbid_remap = {{0}, {1, MTK_INVALID_LARBID, 8}, {4}, {7}, {2}, {9, 11, 19, 20},
{MTK_INVALID_LARBID, 14, 16},
{MTK_INVALID_LARBID, 13, MTK_INVALID_LARBID, 17}},
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c9528065a59a..3f72aef8bd5b 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1230,25 +1230,24 @@ static int omap_iommu_probe(struct platform_device *pdev)
if (err)
return err;
- err = iommu_device_register(&obj->iommu, &omap_iommu_ops, &pdev->dev);
- if (err)
- goto out_sysfs;
obj->has_iommu_driver = true;
}
+ err = iommu_device_register(&obj->iommu, &omap_iommu_ops, &pdev->dev);
+ if (err)
+ goto out_sysfs;
+
pm_runtime_enable(obj->dev);
omap_iommu_debugfs_add(obj);
dev_info(&pdev->dev, "%s registered\n", obj->name);
- /* Re-probe bus to probe device attached to this IOMMU */
- bus_iommu_probe(&platform_bus_type);
-
return 0;
out_sysfs:
- iommu_device_sysfs_remove(&obj->iommu);
+ if (obj->has_iommu_driver)
+ iommu_device_sysfs_remove(&obj->iommu);
return err;
}
@@ -1256,10 +1255,10 @@ static void omap_iommu_remove(struct platform_device *pdev)
{
struct omap_iommu *obj = platform_get_drvdata(pdev);
- if (obj->has_iommu_driver) {
+ if (obj->has_iommu_driver)
iommu_device_sysfs_remove(&obj->iommu);
- iommu_device_unregister(&obj->iommu);
- }
+
+ iommu_device_unregister(&obj->iommu);
omap_iommu_debugfs_remove(obj);
@@ -1723,12 +1722,19 @@ static void omap_iommu_release_device(struct device *dev)
}
+static int omap_iommu_of_xlate(struct device *dev, const struct of_phandle_args *args)
+{
+ /* TODO: collect args->np to save re-parsing in probe above */
+ return 0;
+}
+
static const struct iommu_ops omap_iommu_ops = {
.identity_domain = &omap_iommu_identity_domain,
.domain_alloc_paging = omap_iommu_domain_alloc_paging,
.probe_device = omap_iommu_probe_device,
.release_device = omap_iommu_release_device,
.device_group = generic_single_device_group,
+ .of_xlate = omap_iommu_of_xlate,
.pgsize_bitmap = OMAP_IOMMU_PGSIZES,
.default_domain_ops = &(const struct iommu_domain_ops) {
.attach_dev = omap_iommu_attach_dev,
diff --git a/drivers/iommu/riscv/Kconfig b/drivers/iommu/riscv/Kconfig
new file mode 100644
index 000000000000..c071816f59a6
--- /dev/null
+++ b/drivers/iommu/riscv/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# RISC-V IOMMU support
+
+config RISCV_IOMMU
+ bool "RISC-V IOMMU Support"
+ depends on RISCV && 64BIT
+ default y
+ select IOMMU_API
+ help
+ Support for implementations of the RISC-V IOMMU architecture that
+ complements the RISC-V MMU capabilities, providing similar address
+ translation and protection functions for accesses from I/O devices.
+
+ Say Y here if your SoC includes an IOMMU device implementing
+ the RISC-V IOMMU architecture.
+
+config RISCV_IOMMU_PCI
+ def_bool y if RISCV_IOMMU && PCI_MSI
+ help
+ Support for the PCIe implementation of RISC-V IOMMU architecture.
diff --git a/drivers/iommu/riscv/Makefile b/drivers/iommu/riscv/Makefile
new file mode 100644
index 000000000000..f54c9ed17d41
--- /dev/null
+++ b/drivers/iommu/riscv/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_RISCV_IOMMU) += iommu.o iommu-platform.o
+obj-$(CONFIG_RISCV_IOMMU_PCI) += iommu-pci.o
diff --git a/drivers/iommu/riscv/iommu-bits.h b/drivers/iommu/riscv/iommu-bits.h
new file mode 100644
index 000000000000..98daf0e1a306
--- /dev/null
+++ b/drivers/iommu/riscv/iommu-bits.h
@@ -0,0 +1,784 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2022-2024 Rivos Inc.
+ * Copyright © 2023 FORTH-ICS/CARV
+ * Copyright © 2023 RISC-V IOMMU Task Group
+ *
+ * RISC-V IOMMU - Register Layout and Data Structures.
+ *
+ * Based on the 'RISC-V IOMMU Architecture Specification', Version 1.0
+ * Published at https://github.com/riscv-non-isa/riscv-iommu
+ *
+ */
+
+#ifndef _RISCV_IOMMU_BITS_H_
+#define _RISCV_IOMMU_BITS_H_
+
+#include <linux/types.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+/*
+ * Chapter 5: Memory Mapped register interface
+ */
+
+/* Common field positions */
+#define RISCV_IOMMU_PPN_FIELD GENMASK_ULL(53, 10)
+#define RISCV_IOMMU_QUEUE_LOG2SZ_FIELD GENMASK_ULL(4, 0)
+#define RISCV_IOMMU_QUEUE_INDEX_FIELD GENMASK_ULL(31, 0)
+#define RISCV_IOMMU_QUEUE_ENABLE BIT(0)
+#define RISCV_IOMMU_QUEUE_INTR_ENABLE BIT(1)
+#define RISCV_IOMMU_QUEUE_MEM_FAULT BIT(8)
+#define RISCV_IOMMU_QUEUE_OVERFLOW BIT(9)
+#define RISCV_IOMMU_QUEUE_ACTIVE BIT(16)
+#define RISCV_IOMMU_QUEUE_BUSY BIT(17)
+
+#define RISCV_IOMMU_ATP_PPN_FIELD GENMASK_ULL(43, 0)
+#define RISCV_IOMMU_ATP_MODE_FIELD GENMASK_ULL(63, 60)
+
+/* 5.3 IOMMU Capabilities (64bits) */
+#define RISCV_IOMMU_REG_CAPABILITIES 0x0000
+#define RISCV_IOMMU_CAPABILITIES_VERSION GENMASK_ULL(7, 0)
+#define RISCV_IOMMU_CAPABILITIES_SV32 BIT_ULL(8)
+#define RISCV_IOMMU_CAPABILITIES_SV39 BIT_ULL(9)
+#define RISCV_IOMMU_CAPABILITIES_SV48 BIT_ULL(10)
+#define RISCV_IOMMU_CAPABILITIES_SV57 BIT_ULL(11)
+#define RISCV_IOMMU_CAPABILITIES_SVPBMT BIT_ULL(15)
+#define RISCV_IOMMU_CAPABILITIES_SV32X4 BIT_ULL(16)
+#define RISCV_IOMMU_CAPABILITIES_SV39X4 BIT_ULL(17)
+#define RISCV_IOMMU_CAPABILITIES_SV48X4 BIT_ULL(18)
+#define RISCV_IOMMU_CAPABILITIES_SV57X4 BIT_ULL(19)
+#define RISCV_IOMMU_CAPABILITIES_AMO_MRIF BIT_ULL(21)
+#define RISCV_IOMMU_CAPABILITIES_MSI_FLAT BIT_ULL(22)
+#define RISCV_IOMMU_CAPABILITIES_MSI_MRIF BIT_ULL(23)
+#define RISCV_IOMMU_CAPABILITIES_AMO_HWAD BIT_ULL(24)
+#define RISCV_IOMMU_CAPABILITIES_ATS BIT_ULL(25)
+#define RISCV_IOMMU_CAPABILITIES_T2GPA BIT_ULL(26)
+#define RISCV_IOMMU_CAPABILITIES_END BIT_ULL(27)
+#define RISCV_IOMMU_CAPABILITIES_IGS GENMASK_ULL(29, 28)
+#define RISCV_IOMMU_CAPABILITIES_HPM BIT_ULL(30)
+#define RISCV_IOMMU_CAPABILITIES_DBG BIT_ULL(31)
+#define RISCV_IOMMU_CAPABILITIES_PAS GENMASK_ULL(37, 32)
+#define RISCV_IOMMU_CAPABILITIES_PD8 BIT_ULL(38)
+#define RISCV_IOMMU_CAPABILITIES_PD17 BIT_ULL(39)
+#define RISCV_IOMMU_CAPABILITIES_PD20 BIT_ULL(40)
+
+/**
+ * enum riscv_iommu_igs_settings - Interrupt Generation Support Settings
+ * @RISCV_IOMMU_CAPABILITIES_IGS_MSI: IOMMU supports only MSI generation
+ * @RISCV_IOMMU_CAPABILITIES_IGS_WSI: IOMMU supports only Wired-Signaled interrupt
+ * @RISCV_IOMMU_CAPABILITIES_IGS_BOTH: IOMMU supports both MSI and WSI generation
+ * @RISCV_IOMMU_CAPABILITIES_IGS_RSRV: Reserved for standard use
+ */
+enum riscv_iommu_igs_settings {
+ RISCV_IOMMU_CAPABILITIES_IGS_MSI = 0,
+ RISCV_IOMMU_CAPABILITIES_IGS_WSI = 1,
+ RISCV_IOMMU_CAPABILITIES_IGS_BOTH = 2,
+ RISCV_IOMMU_CAPABILITIES_IGS_RSRV = 3
+};
+
+/* 5.4 Features control register (32bits) */
+#define RISCV_IOMMU_REG_FCTL 0x0008
+#define RISCV_IOMMU_FCTL_BE BIT(0)
+#define RISCV_IOMMU_FCTL_WSI BIT(1)
+#define RISCV_IOMMU_FCTL_GXL BIT(2)
+
+/* 5.5 Device-directory-table pointer (64bits) */
+#define RISCV_IOMMU_REG_DDTP 0x0010
+#define RISCV_IOMMU_DDTP_IOMMU_MODE GENMASK_ULL(3, 0)
+#define RISCV_IOMMU_DDTP_BUSY BIT_ULL(4)
+#define RISCV_IOMMU_DDTP_PPN RISCV_IOMMU_PPN_FIELD
+
+/**
+ * enum riscv_iommu_ddtp_modes - IOMMU translation modes
+ * @RISCV_IOMMU_DDTP_IOMMU_MODE_OFF: No inbound transactions allowed
+ * @RISCV_IOMMU_DDTP_IOMMU_MODE_BARE: Pass-through mode
+ * @RISCV_IOMMU_DDTP_IOMMU_MODE_1LVL: One-level DDT
+ * @RISCV_IOMMU_DDTP_IOMMU_MODE_2LVL: Two-level DDT
+ * @RISCV_IOMMU_DDTP_IOMMU_MODE_3LVL: Three-level DDT
+ * @RISCV_IOMMU_DDTP_IOMMU_MODE_MAX: Max value allowed by specification
+ */
+enum riscv_iommu_ddtp_modes {
+ RISCV_IOMMU_DDTP_IOMMU_MODE_OFF = 0,
+ RISCV_IOMMU_DDTP_IOMMU_MODE_BARE = 1,
+ RISCV_IOMMU_DDTP_IOMMU_MODE_1LVL = 2,
+ RISCV_IOMMU_DDTP_IOMMU_MODE_2LVL = 3,
+ RISCV_IOMMU_DDTP_IOMMU_MODE_3LVL = 4,
+ RISCV_IOMMU_DDTP_IOMMU_MODE_MAX = 4
+};
+
+/* 5.6 Command Queue Base (64bits) */
+#define RISCV_IOMMU_REG_CQB 0x0018
+#define RISCV_IOMMU_CQB_ENTRIES RISCV_IOMMU_QUEUE_LOG2SZ_FIELD
+#define RISCV_IOMMU_CQB_PPN RISCV_IOMMU_PPN_FIELD
+
+/* 5.7 Command Queue head (32bits) */
+#define RISCV_IOMMU_REG_CQH 0x0020
+#define RISCV_IOMMU_CQH_INDEX RISCV_IOMMU_QUEUE_INDEX_FIELD
+
+/* 5.8 Command Queue tail (32bits) */
+#define RISCV_IOMMU_REG_CQT 0x0024
+#define RISCV_IOMMU_CQT_INDEX RISCV_IOMMU_QUEUE_INDEX_FIELD
+
+/* 5.9 Fault Queue Base (64bits) */
+#define RISCV_IOMMU_REG_FQB 0x0028
+#define RISCV_IOMMU_FQB_ENTRIES RISCV_IOMMU_QUEUE_LOG2SZ_FIELD
+#define RISCV_IOMMU_FQB_PPN RISCV_IOMMU_PPN_FIELD
+
+/* 5.10 Fault Queue Head (32bits) */
+#define RISCV_IOMMU_REG_FQH 0x0030
+#define RISCV_IOMMU_FQH_INDEX RISCV_IOMMU_QUEUE_INDEX_FIELD
+
+/* 5.11 Fault Queue tail (32bits) */
+#define RISCV_IOMMU_REG_FQT 0x0034
+#define RISCV_IOMMU_FQT_INDEX RISCV_IOMMU_QUEUE_INDEX_FIELD
+
+/* 5.12 Page Request Queue base (64bits) */
+#define RISCV_IOMMU_REG_PQB 0x0038
+#define RISCV_IOMMU_PQB_ENTRIES RISCV_IOMMU_QUEUE_LOG2SZ_FIELD
+#define RISCV_IOMMU_PQB_PPN RISCV_IOMMU_PPN_FIELD
+
+/* 5.13 Page Request Queue head (32bits) */
+#define RISCV_IOMMU_REG_PQH 0x0040
+#define RISCV_IOMMU_PQH_INDEX RISCV_IOMMU_QUEUE_INDEX_FIELD
+
+/* 5.14 Page Request Queue tail (32bits) */
+#define RISCV_IOMMU_REG_PQT 0x0044
+#define RISCV_IOMMU_PQT_INDEX_MASK RISCV_IOMMU_QUEUE_INDEX_FIELD
+
+/* 5.15 Command Queue CSR (32bits) */
+#define RISCV_IOMMU_REG_CQCSR 0x0048
+#define RISCV_IOMMU_CQCSR_CQEN RISCV_IOMMU_QUEUE_ENABLE
+#define RISCV_IOMMU_CQCSR_CIE RISCV_IOMMU_QUEUE_INTR_ENABLE
+#define RISCV_IOMMU_CQCSR_CQMF RISCV_IOMMU_QUEUE_MEM_FAULT
+#define RISCV_IOMMU_CQCSR_CMD_TO BIT(9)
+#define RISCV_IOMMU_CQCSR_CMD_ILL BIT(10)
+#define RISCV_IOMMU_CQCSR_FENCE_W_IP BIT(11)
+#define RISCV_IOMMU_CQCSR_CQON RISCV_IOMMU_QUEUE_ACTIVE
+#define RISCV_IOMMU_CQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY
+
+/* 5.16 Fault Queue CSR (32bits) */
+#define RISCV_IOMMU_REG_FQCSR 0x004C
+#define RISCV_IOMMU_FQCSR_FQEN RISCV_IOMMU_QUEUE_ENABLE
+#define RISCV_IOMMU_FQCSR_FIE RISCV_IOMMU_QUEUE_INTR_ENABLE
+#define RISCV_IOMMU_FQCSR_FQMF RISCV_IOMMU_QUEUE_MEM_FAULT
+#define RISCV_IOMMU_FQCSR_FQOF RISCV_IOMMU_QUEUE_OVERFLOW
+#define RISCV_IOMMU_FQCSR_FQON RISCV_IOMMU_QUEUE_ACTIVE
+#define RISCV_IOMMU_FQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY
+
+/* 5.17 Page Request Queue CSR (32bits) */
+#define RISCV_IOMMU_REG_PQCSR 0x0050
+#define RISCV_IOMMU_PQCSR_PQEN RISCV_IOMMU_QUEUE_ENABLE
+#define RISCV_IOMMU_PQCSR_PIE RISCV_IOMMU_QUEUE_INTR_ENABLE
+#define RISCV_IOMMU_PQCSR_PQMF RISCV_IOMMU_QUEUE_MEM_FAULT
+#define RISCV_IOMMU_PQCSR_PQOF RISCV_IOMMU_QUEUE_OVERFLOW
+#define RISCV_IOMMU_PQCSR_PQON RISCV_IOMMU_QUEUE_ACTIVE
+#define RISCV_IOMMU_PQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY
+
+/* 5.18 Interrupt Pending Status (32bits) */
+#define RISCV_IOMMU_REG_IPSR 0x0054
+
+#define RISCV_IOMMU_INTR_CQ 0
+#define RISCV_IOMMU_INTR_FQ 1
+#define RISCV_IOMMU_INTR_PM 2
+#define RISCV_IOMMU_INTR_PQ 3
+#define RISCV_IOMMU_INTR_COUNT 4
+
+#define RISCV_IOMMU_IPSR_CIP BIT(RISCV_IOMMU_INTR_CQ)
+#define RISCV_IOMMU_IPSR_FIP BIT(RISCV_IOMMU_INTR_FQ)
+#define RISCV_IOMMU_IPSR_PMIP BIT(RISCV_IOMMU_INTR_PM)
+#define RISCV_IOMMU_IPSR_PIP BIT(RISCV_IOMMU_INTR_PQ)
+
+/* 5.19 Performance monitoring counter overflow status (32bits) */
+#define RISCV_IOMMU_REG_IOCOUNTOVF 0x0058
+#define RISCV_IOMMU_IOCOUNTOVF_CY BIT(0)
+#define RISCV_IOMMU_IOCOUNTOVF_HPM GENMASK_ULL(31, 1)
+
+/* 5.20 Performance monitoring counter inhibits (32bits) */
+#define RISCV_IOMMU_REG_IOCOUNTINH 0x005C
+#define RISCV_IOMMU_IOCOUNTINH_CY BIT(0)
+#define RISCV_IOMMU_IOCOUNTINH_HPM GENMASK(31, 1)
+
+/* 5.21 Performance monitoring cycles counter (64bits) */
+#define RISCV_IOMMU_REG_IOHPMCYCLES 0x0060
+#define RISCV_IOMMU_IOHPMCYCLES_COUNTER GENMASK_ULL(62, 0)
+#define RISCV_IOMMU_IOHPMCYCLES_OF BIT_ULL(63)
+
+/* 5.22 Performance monitoring event counters (31 * 64bits) */
+#define RISCV_IOMMU_REG_IOHPMCTR_BASE 0x0068
+#define RISCV_IOMMU_REG_IOHPMCTR(_n) (RISCV_IOMMU_REG_IOHPMCTR_BASE + ((_n) * 0x8))
+
+/* 5.23 Performance monitoring event selectors (31 * 64bits) */
+#define RISCV_IOMMU_REG_IOHPMEVT_BASE 0x0160
+#define RISCV_IOMMU_REG_IOHPMEVT(_n) (RISCV_IOMMU_REG_IOHPMEVT_BASE + ((_n) * 0x8))
+#define RISCV_IOMMU_IOHPMEVT_EVENTID GENMASK_ULL(14, 0)
+#define RISCV_IOMMU_IOHPMEVT_DMASK BIT_ULL(15)
+#define RISCV_IOMMU_IOHPMEVT_PID_PSCID GENMASK_ULL(35, 16)
+#define RISCV_IOMMU_IOHPMEVT_DID_GSCID GENMASK_ULL(59, 36)
+#define RISCV_IOMMU_IOHPMEVT_PV_PSCV BIT_ULL(60)
+#define RISCV_IOMMU_IOHPMEVT_DV_GSCV BIT_ULL(61)
+#define RISCV_IOMMU_IOHPMEVT_IDT BIT_ULL(62)
+#define RISCV_IOMMU_IOHPMEVT_OF BIT_ULL(63)
+
+/* Number of defined performance-monitoring event selectors */
+#define RISCV_IOMMU_IOHPMEVT_CNT 31
+
+/**
+ * enum riscv_iommu_hpmevent_id - Performance-monitoring event identifier
+ *
+ * @RISCV_IOMMU_HPMEVENT_INVALID: Invalid event, do not count
+ * @RISCV_IOMMU_HPMEVENT_URQ: Untranslated requests
+ * @RISCV_IOMMU_HPMEVENT_TRQ: Translated requests
+ * @RISCV_IOMMU_HPMEVENT_ATS_RQ: ATS translation requests
+ * @RISCV_IOMMU_HPMEVENT_TLB_MISS: TLB misses
+ * @RISCV_IOMMU_HPMEVENT_DD_WALK: Device directory walks
+ * @RISCV_IOMMU_HPMEVENT_PD_WALK: Process directory walks
+ * @RISCV_IOMMU_HPMEVENT_S_VS_WALKS: First-stage page table walks
+ * @RISCV_IOMMU_HPMEVENT_G_WALKS: Second-stage page table walks
+ * @RISCV_IOMMU_HPMEVENT_MAX: Value to denote maximum Event IDs
+ */
+enum riscv_iommu_hpmevent_id {
+ RISCV_IOMMU_HPMEVENT_INVALID = 0,
+ RISCV_IOMMU_HPMEVENT_URQ = 1,
+ RISCV_IOMMU_HPMEVENT_TRQ = 2,
+ RISCV_IOMMU_HPMEVENT_ATS_RQ = 3,
+ RISCV_IOMMU_HPMEVENT_TLB_MISS = 4,
+ RISCV_IOMMU_HPMEVENT_DD_WALK = 5,
+ RISCV_IOMMU_HPMEVENT_PD_WALK = 6,
+ RISCV_IOMMU_HPMEVENT_S_VS_WALKS = 7,
+ RISCV_IOMMU_HPMEVENT_G_WALKS = 8,
+ RISCV_IOMMU_HPMEVENT_MAX = 9
+};
+
+/* 5.24 Translation request IOVA (64bits) */
+#define RISCV_IOMMU_REG_TR_REQ_IOVA 0x0258
+#define RISCV_IOMMU_TR_REQ_IOVA_VPN GENMASK_ULL(63, 12)
+
+/* 5.25 Translation request control (64bits) */
+#define RISCV_IOMMU_REG_TR_REQ_CTL 0x0260
+#define RISCV_IOMMU_TR_REQ_CTL_GO_BUSY BIT_ULL(0)
+#define RISCV_IOMMU_TR_REQ_CTL_PRIV BIT_ULL(1)
+#define RISCV_IOMMU_TR_REQ_CTL_EXE BIT_ULL(2)
+#define RISCV_IOMMU_TR_REQ_CTL_NW BIT_ULL(3)
+#define RISCV_IOMMU_TR_REQ_CTL_PID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_TR_REQ_CTL_PV BIT_ULL(32)
+#define RISCV_IOMMU_TR_REQ_CTL_DID GENMASK_ULL(63, 40)
+
+/* 5.26 Translation request response (64bits) */
+#define RISCV_IOMMU_REG_TR_RESPONSE 0x0268
+#define RISCV_IOMMU_TR_RESPONSE_FAULT BIT_ULL(0)
+#define RISCV_IOMMU_TR_RESPONSE_PBMT GENMASK_ULL(8, 7)
+#define RISCV_IOMMU_TR_RESPONSE_SZ BIT_ULL(9)
+#define RISCV_IOMMU_TR_RESPONSE_PPN RISCV_IOMMU_PPN_FIELD
+
+/* 5.27 Interrupt cause to vector (64bits) */
+#define RISCV_IOMMU_REG_ICVEC 0x02F8
+#define RISCV_IOMMU_ICVEC_CIV GENMASK_ULL(3, 0)
+#define RISCV_IOMMU_ICVEC_FIV GENMASK_ULL(7, 4)
+#define RISCV_IOMMU_ICVEC_PMIV GENMASK_ULL(11, 8)
+#define RISCV_IOMMU_ICVEC_PIV GENMASK_ULL(15, 12)
+
+/* 5.28 MSI Configuration table (32 * 64bits) */
+#define RISCV_IOMMU_REG_MSI_CFG_TBL 0x0300
+#define RISCV_IOMMU_REG_MSI_CFG_TBL_ADDR(_n) \
+ (RISCV_IOMMU_REG_MSI_CFG_TBL + ((_n) * 0x10))
+#define RISCV_IOMMU_MSI_CFG_TBL_ADDR GENMASK_ULL(55, 2)
+#define RISCV_IOMMU_REG_MSI_CFG_TBL_DATA(_n) \
+ (RISCV_IOMMU_REG_MSI_CFG_TBL + ((_n) * 0x10) + 0x08)
+#define RISCV_IOMMU_MSI_CFG_TBL_DATA GENMASK_ULL(31, 0)
+#define RISCV_IOMMU_REG_MSI_CFG_TBL_CTRL(_n) \
+ (RISCV_IOMMU_REG_MSI_CFG_TBL + ((_n) * 0x10) + 0x0C)
+#define RISCV_IOMMU_MSI_CFG_TBL_CTRL_M BIT_ULL(0)
+
+#define RISCV_IOMMU_REG_SIZE 0x1000
+
+/*
+ * Chapter 2: Data structures
+ */
+
+/*
+ * Device Directory Table macros for non-leaf nodes
+ */
+#define RISCV_IOMMU_DDTE_V BIT_ULL(0)
+#define RISCV_IOMMU_DDTE_PPN RISCV_IOMMU_PPN_FIELD
+
+/**
+ * struct riscv_iommu_dc - Device Context
+ * @tc: Translation Control
+ * @iohgatp: I/O Hypervisor guest address translation and protection
+ * (Second stage context)
+ * @ta: Translation Attributes
+ * @fsc: First stage context
+ * @msiptp: MSI page table pointer
+ * @msi_addr_mask: MSI address mask
+ * @msi_addr_pattern: MSI address pattern
+ * @_reserved: Reserved for future use, padding
+ *
+ * This structure is used for leaf nodes on the Device Directory Table,
+ * in case RISCV_IOMMU_CAPABILITIES_MSI_FLAT is not set, the bottom 4 fields
+ * are not present and are skipped with pointer arithmetic to avoid
+ * casting, check out riscv_iommu_get_dc().
+ * See section 2.1 for more details
+ */
+struct riscv_iommu_dc {
+ u64 tc;
+ u64 iohgatp;
+ u64 ta;
+ u64 fsc;
+ u64 msiptp;
+ u64 msi_addr_mask;
+ u64 msi_addr_pattern;
+ u64 _reserved;
+};
+
+/* Translation control fields */
+#define RISCV_IOMMU_DC_TC_V BIT_ULL(0)
+#define RISCV_IOMMU_DC_TC_EN_ATS BIT_ULL(1)
+#define RISCV_IOMMU_DC_TC_EN_PRI BIT_ULL(2)
+#define RISCV_IOMMU_DC_TC_T2GPA BIT_ULL(3)
+#define RISCV_IOMMU_DC_TC_DTF BIT_ULL(4)
+#define RISCV_IOMMU_DC_TC_PDTV BIT_ULL(5)
+#define RISCV_IOMMU_DC_TC_PRPR BIT_ULL(6)
+#define RISCV_IOMMU_DC_TC_GADE BIT_ULL(7)
+#define RISCV_IOMMU_DC_TC_SADE BIT_ULL(8)
+#define RISCV_IOMMU_DC_TC_DPE BIT_ULL(9)
+#define RISCV_IOMMU_DC_TC_SBE BIT_ULL(10)
+#define RISCV_IOMMU_DC_TC_SXL BIT_ULL(11)
+
+/* Second-stage (aka G-stage) context fields */
+#define RISCV_IOMMU_DC_IOHGATP_PPN RISCV_IOMMU_ATP_PPN_FIELD
+#define RISCV_IOMMU_DC_IOHGATP_GSCID GENMASK_ULL(59, 44)
+#define RISCV_IOMMU_DC_IOHGATP_MODE RISCV_IOMMU_ATP_MODE_FIELD
+
+/**
+ * enum riscv_iommu_dc_iohgatp_modes - Guest address translation/protection modes
+ * @RISCV_IOMMU_DC_IOHGATP_MODE_BARE: No translation/protection
+ * @RISCV_IOMMU_DC_IOHGATP_MODE_SV32X4: Sv32x4 (2-bit extension of Sv32), when fctl.GXL == 1
+ * @RISCV_IOMMU_DC_IOHGATP_MODE_SV39X4: Sv39x4 (2-bit extension of Sv39), when fctl.GXL == 0
+ * @RISCV_IOMMU_DC_IOHGATP_MODE_SV48X4: Sv48x4 (2-bit extension of Sv48), when fctl.GXL == 0
+ * @RISCV_IOMMU_DC_IOHGATP_MODE_SV57X4: Sv57x4 (2-bit extension of Sv57), when fctl.GXL == 0
+ */
+enum riscv_iommu_dc_iohgatp_modes {
+ RISCV_IOMMU_DC_IOHGATP_MODE_BARE = 0,
+ RISCV_IOMMU_DC_IOHGATP_MODE_SV32X4 = 8,
+ RISCV_IOMMU_DC_IOHGATP_MODE_SV39X4 = 8,
+ RISCV_IOMMU_DC_IOHGATP_MODE_SV48X4 = 9,
+ RISCV_IOMMU_DC_IOHGATP_MODE_SV57X4 = 10
+};
+
+/* Translation attributes fields */
+#define RISCV_IOMMU_DC_TA_PSCID GENMASK_ULL(31, 12)
+
+/* First-stage context fields */
+#define RISCV_IOMMU_DC_FSC_PPN RISCV_IOMMU_ATP_PPN_FIELD
+#define RISCV_IOMMU_DC_FSC_MODE RISCV_IOMMU_ATP_MODE_FIELD
+
+/**
+ * enum riscv_iommu_dc_fsc_atp_modes - First stage address translation/protection modes
+ * @RISCV_IOMMU_DC_FSC_MODE_BARE: No translation/protection
+ * @RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32: Sv32, when dc.tc.SXL == 1
+ * @RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39: Sv39, when dc.tc.SXL == 0
+ * @RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV48: Sv48, when dc.tc.SXL == 0
+ * @RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV57: Sv57, when dc.tc.SXL == 0
+ * @RISCV_IOMMU_DC_FSC_PDTP_MODE_PD8: 1lvl PDT, 8bit process ids
+ * @RISCV_IOMMU_DC_FSC_PDTP_MODE_PD17: 2lvl PDT, 17bit process ids
+ * @RISCV_IOMMU_DC_FSC_PDTP_MODE_PD20: 3lvl PDT, 20bit process ids
+ *
+ * FSC holds IOSATP when RISCV_IOMMU_DC_TC_PDTV is 0 and PDTP otherwise.
+ * IOSATP controls the first stage address translation (same as the satp register on
+ * the RISC-V MMU), and PDTP holds the process directory table, used to select a
+ * first stage page table based on a process id (for devices that support multiple
+ * process ids).
+ */
+enum riscv_iommu_dc_fsc_atp_modes {
+ RISCV_IOMMU_DC_FSC_MODE_BARE = 0,
+ RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 = 8,
+ RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39 = 8,
+ RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV48 = 9,
+ RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV57 = 10,
+ RISCV_IOMMU_DC_FSC_PDTP_MODE_PD8 = 1,
+ RISCV_IOMMU_DC_FSC_PDTP_MODE_PD17 = 2,
+ RISCV_IOMMU_DC_FSC_PDTP_MODE_PD20 = 3
+};
+
+/* MSI page table pointer */
+#define RISCV_IOMMU_DC_MSIPTP_PPN RISCV_IOMMU_ATP_PPN_FIELD
+#define RISCV_IOMMU_DC_MSIPTP_MODE RISCV_IOMMU_ATP_MODE_FIELD
+#define RISCV_IOMMU_DC_MSIPTP_MODE_OFF 0
+#define RISCV_IOMMU_DC_MSIPTP_MODE_FLAT 1
+
+/* MSI address mask */
+#define RISCV_IOMMU_DC_MSI_ADDR_MASK GENMASK_ULL(51, 0)
+
+/* MSI address pattern */
+#define RISCV_IOMMU_DC_MSI_PATTERN GENMASK_ULL(51, 0)
+
+/**
+ * struct riscv_iommu_pc - Process Context
+ * @ta: Translation Attributes
+ * @fsc: First stage context
+ *
+ * This structure is used for leaf nodes on the Process Directory Table
+ * See section 2.3 for more details
+ */
+struct riscv_iommu_pc {
+ u64 ta;
+ u64 fsc;
+};
+
+/* Translation attributes fields */
+#define RISCV_IOMMU_PC_TA_V BIT_ULL(0)
+#define RISCV_IOMMU_PC_TA_ENS BIT_ULL(1)
+#define RISCV_IOMMU_PC_TA_SUM BIT_ULL(2)
+#define RISCV_IOMMU_PC_TA_PSCID GENMASK_ULL(31, 12)
+
+/* First stage context fields */
+#define RISCV_IOMMU_PC_FSC_PPN RISCV_IOMMU_ATP_PPN_FIELD
+#define RISCV_IOMMU_PC_FSC_MODE RISCV_IOMMU_ATP_MODE_FIELD
+
+/*
+ * Chapter 3: In-memory queue interface
+ */
+
+/**
+ * struct riscv_iommu_command - Generic IOMMU command structure
+ * @dword0: Includes the opcode and the function identifier
+ * @dword1: Opcode specific data
+ *
+ * The commands are interpreted as two 64bit fields, where the first
+ * 7bits of the first field are the opcode which also defines the
+ * command's format, followed by a 3bit field that specifies the
+ * function invoked by that command, and the rest is opcode-specific.
+ * This is a generic struct which will be populated differently
+ * according to each command. For more infos on the commands and
+ * the command queue check section 3.1.
+ */
+struct riscv_iommu_command {
+ u64 dword0;
+ u64 dword1;
+};
+
+/* Fields on dword0, common for all commands */
+#define RISCV_IOMMU_CMD_OPCODE GENMASK_ULL(6, 0)
+#define RISCV_IOMMU_CMD_FUNC GENMASK_ULL(9, 7)
+
+/* 3.1.1 IOMMU Page-table cache invalidation */
+/* Fields on dword0 */
+#define RISCV_IOMMU_CMD_IOTINVAL_OPCODE 1
+#define RISCV_IOMMU_CMD_IOTINVAL_FUNC_VMA 0
+#define RISCV_IOMMU_CMD_IOTINVAL_FUNC_GVMA 1
+#define RISCV_IOMMU_CMD_IOTINVAL_AV BIT_ULL(10)
+#define RISCV_IOMMU_CMD_IOTINVAL_PSCID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_CMD_IOTINVAL_PSCV BIT_ULL(32)
+#define RISCV_IOMMU_CMD_IOTINVAL_GV BIT_ULL(33)
+#define RISCV_IOMMU_CMD_IOTINVAL_GSCID GENMASK_ULL(59, 44)
+/* dword1[61:10] is the 4K-aligned page address */
+#define RISCV_IOMMU_CMD_IOTINVAL_ADDR GENMASK_ULL(61, 10)
+
+/* 3.1.2 IOMMU Command Queue Fences */
+/* Fields on dword0 */
+#define RISCV_IOMMU_CMD_IOFENCE_OPCODE 2
+#define RISCV_IOMMU_CMD_IOFENCE_FUNC_C 0
+#define RISCV_IOMMU_CMD_IOFENCE_AV BIT_ULL(10)
+#define RISCV_IOMMU_CMD_IOFENCE_WSI BIT_ULL(11)
+#define RISCV_IOMMU_CMD_IOFENCE_PR BIT_ULL(12)
+#define RISCV_IOMMU_CMD_IOFENCE_PW BIT_ULL(13)
+#define RISCV_IOMMU_CMD_IOFENCE_DATA GENMASK_ULL(63, 32)
+/* dword1 is the address, word-size aligned and shifted to the right by two bits. */
+
+/* 3.1.3 IOMMU Directory cache invalidation */
+/* Fields on dword0 */
+#define RISCV_IOMMU_CMD_IODIR_OPCODE 3
+#define RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_DDT 0
+#define RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_PDT 1
+#define RISCV_IOMMU_CMD_IODIR_PID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_CMD_IODIR_DV BIT_ULL(33)
+#define RISCV_IOMMU_CMD_IODIR_DID GENMASK_ULL(63, 40)
+/* dword1 is reserved for standard use */
+
+/* 3.1.4 IOMMU PCIe ATS */
+/* Fields on dword0 */
+#define RISCV_IOMMU_CMD_ATS_OPCODE 4
+#define RISCV_IOMMU_CMD_ATS_FUNC_INVAL 0
+#define RISCV_IOMMU_CMD_ATS_FUNC_PRGR 1
+#define RISCV_IOMMU_CMD_ATS_PID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_CMD_ATS_PV BIT_ULL(32)
+#define RISCV_IOMMU_CMD_ATS_DSV BIT_ULL(33)
+#define RISCV_IOMMU_CMD_ATS_RID GENMASK_ULL(55, 40)
+#define RISCV_IOMMU_CMD_ATS_DSEG GENMASK_ULL(63, 56)
+/* dword1 is the ATS payload, two different payload types for INVAL and PRGR */
+
+/* ATS.INVAL payload*/
+#define RISCV_IOMMU_CMD_ATS_INVAL_G BIT_ULL(0)
+/* Bits 1 - 10 are zeroed */
+#define RISCV_IOMMU_CMD_ATS_INVAL_S BIT_ULL(11)
+#define RISCV_IOMMU_CMD_ATS_INVAL_UADDR GENMASK_ULL(63, 12)
+
+/* ATS.PRGR payload */
+/* Bits 0 - 31 are zeroed */
+#define RISCV_IOMMU_CMD_ATS_PRGR_PRG_INDEX GENMASK_ULL(40, 32)
+/* Bits 41 - 43 are zeroed */
+#define RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE GENMASK_ULL(47, 44)
+#define RISCV_IOMMU_CMD_ATS_PRGR_DST_ID GENMASK_ULL(63, 48)
+
+/**
+ * struct riscv_iommu_fq_record - Fault/Event Queue Record
+ * @hdr: Header, includes fault/event cause, PID/DID, transaction type etc
+ * @_reserved: Low 32bits for custom use, high 32bits for standard use
+ * @iotval: Transaction-type/cause specific format
+ * @iotval2: Cause specific format
+ *
+ * The fault/event queue reports events and failures raised when
+ * processing transactions. Each record is a 32byte structure where
+ * the first dword has a fixed format for providing generic infos
+ * regarding the fault/event, and two more dwords are there for
+ * fault/event-specific information. For more details see section
+ * 3.2.
+ */
+struct riscv_iommu_fq_record {
+ u64 hdr;
+ u64 _reserved;
+ u64 iotval;
+ u64 iotval2;
+};
+
+/* Fields on header */
+#define RISCV_IOMMU_FQ_HDR_CAUSE GENMASK_ULL(11, 0)
+#define RISCV_IOMMU_FQ_HDR_PID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_FQ_HDR_PV BIT_ULL(32)
+#define RISCV_IOMMU_FQ_HDR_PRIV BIT_ULL(33)
+#define RISCV_IOMMU_FQ_HDR_TTYP GENMASK_ULL(39, 34)
+#define RISCV_IOMMU_FQ_HDR_DID GENMASK_ULL(63, 40)
+
+/**
+ * enum riscv_iommu_fq_causes - Fault/event cause values
+ * @RISCV_IOMMU_FQ_CAUSE_INST_FAULT: Instruction access fault
+ * @RISCV_IOMMU_FQ_CAUSE_RD_ADDR_MISALIGNED: Read address misaligned
+ * @RISCV_IOMMU_FQ_CAUSE_RD_FAULT: Read load fault
+ * @RISCV_IOMMU_FQ_CAUSE_WR_ADDR_MISALIGNED: Write/AMO address misaligned
+ * @RISCV_IOMMU_FQ_CAUSE_WR_FAULT: Write/AMO access fault
+ * @RISCV_IOMMU_FQ_CAUSE_INST_FAULT_S: Instruction page fault
+ * @RISCV_IOMMU_FQ_CAUSE_RD_FAULT_S: Read page fault
+ * @RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S: Write/AMO page fault
+ * @RISCV_IOMMU_FQ_CAUSE_INST_FAULT_VS: Instruction guest page fault
+ * @RISCV_IOMMU_FQ_CAUSE_RD_FAULT_VS: Read guest page fault
+ * @RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS: Write/AMO guest page fault
+ * @RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED: All inbound transactions disallowed
+ * @RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT: DDT entry load access fault
+ * @RISCV_IOMMU_FQ_CAUSE_DDT_INVALID: DDT entry invalid
+ * @RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED: DDT entry misconfigured
+ * @RISCV_IOMMU_FQ_CAUSE_TTYP_BLOCKED: Transaction type disallowed
+ * @RISCV_IOMMU_FQ_CAUSE_MSI_LOAD_FAULT: MSI PTE load access fault
+ * @RISCV_IOMMU_FQ_CAUSE_MSI_INVALID: MSI PTE invalid
+ * @RISCV_IOMMU_FQ_CAUSE_MSI_MISCONFIGURED: MSI PTE misconfigured
+ * @RISCV_IOMMU_FQ_CAUSE_MRIF_FAULT: MRIF access fault
+ * @RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT: PDT entry load access fault
+ * @RISCV_IOMMU_FQ_CAUSE_PDT_INVALID: PDT entry invalid
+ * @RISCV_IOMMU_FQ_CAUSE_PDT_MISCONFIGURED: PDT entry misconfigured
+ * @RISCV_IOMMU_FQ_CAUSE_DDT_CORRUPTED: DDT data corruption
+ * @RISCV_IOMMU_FQ_CAUSE_PDT_CORRUPTED: PDT data corruption
+ * @RISCV_IOMMU_FQ_CAUSE_MSI_PT_CORRUPTED: MSI page table data corruption
+ * @RISCV_IOMMU_FQ_CAUSE_MRIF_CORRUIPTED: MRIF data corruption
+ * @RISCV_IOMMU_FQ_CAUSE_INTERNAL_DP_ERROR: Internal data path error
+ * @RISCV_IOMMU_FQ_CAUSE_MSI_WR_FAULT: IOMMU MSI write access fault
+ * @RISCV_IOMMU_FQ_CAUSE_PT_CORRUPTED: First/second stage page table data corruption
+ *
+ * Values are on table 11 of the spec, encodings 275 - 2047 are reserved for standard
+ * use, and 2048 - 4095 for custom use.
+ */
+enum riscv_iommu_fq_causes {
+ RISCV_IOMMU_FQ_CAUSE_INST_FAULT = 1,
+ RISCV_IOMMU_FQ_CAUSE_RD_ADDR_MISALIGNED = 4,
+ RISCV_IOMMU_FQ_CAUSE_RD_FAULT = 5,
+ RISCV_IOMMU_FQ_CAUSE_WR_ADDR_MISALIGNED = 6,
+ RISCV_IOMMU_FQ_CAUSE_WR_FAULT = 7,
+ RISCV_IOMMU_FQ_CAUSE_INST_FAULT_S = 12,
+ RISCV_IOMMU_FQ_CAUSE_RD_FAULT_S = 13,
+ RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S = 15,
+ RISCV_IOMMU_FQ_CAUSE_INST_FAULT_VS = 20,
+ RISCV_IOMMU_FQ_CAUSE_RD_FAULT_VS = 21,
+ RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS = 23,
+ RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED = 256,
+ RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT = 257,
+ RISCV_IOMMU_FQ_CAUSE_DDT_INVALID = 258,
+ RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED = 259,
+ RISCV_IOMMU_FQ_CAUSE_TTYP_BLOCKED = 260,
+ RISCV_IOMMU_FQ_CAUSE_MSI_LOAD_FAULT = 261,
+ RISCV_IOMMU_FQ_CAUSE_MSI_INVALID = 262,
+ RISCV_IOMMU_FQ_CAUSE_MSI_MISCONFIGURED = 263,
+ RISCV_IOMMU_FQ_CAUSE_MRIF_FAULT = 264,
+ RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT = 265,
+ RISCV_IOMMU_FQ_CAUSE_PDT_INVALID = 266,
+ RISCV_IOMMU_FQ_CAUSE_PDT_MISCONFIGURED = 267,
+ RISCV_IOMMU_FQ_CAUSE_DDT_CORRUPTED = 268,
+ RISCV_IOMMU_FQ_CAUSE_PDT_CORRUPTED = 269,
+ RISCV_IOMMU_FQ_CAUSE_MSI_PT_CORRUPTED = 270,
+ RISCV_IOMMU_FQ_CAUSE_MRIF_CORRUIPTED = 271,
+ RISCV_IOMMU_FQ_CAUSE_INTERNAL_DP_ERROR = 272,
+ RISCV_IOMMU_FQ_CAUSE_MSI_WR_FAULT = 273,
+ RISCV_IOMMU_FQ_CAUSE_PT_CORRUPTED = 274
+};
+
+/**
+ * enum riscv_iommu_fq_ttypes: Fault/event transaction types
+ * @RISCV_IOMMU_FQ_TTYP_NONE: None. Fault not caused by an inbound transaction.
+ * @RISCV_IOMMU_FQ_TTYP_UADDR_INST_FETCH: Instruction fetch from untranslated address
+ * @RISCV_IOMMU_FQ_TTYP_UADDR_RD: Read from untranslated address
+ * @RISCV_IOMMU_FQ_TTYP_UADDR_WR: Write/AMO to untranslated address
+ * @RISCV_IOMMU_FQ_TTYP_TADDR_INST_FETCH: Instruction fetch from translated address
+ * @RISCV_IOMMU_FQ_TTYP_TADDR_RD: Read from translated address
+ * @RISCV_IOMMU_FQ_TTYP_TADDR_WR: Write/AMO to translated address
+ * @RISCV_IOMMU_FQ_TTYP_PCIE_ATS_REQ: PCIe ATS translation request
+ * @RISCV_IOMMU_FQ_TTYP_PCIE_MSG_REQ: PCIe message request
+ *
+ * Values are on table 12 of the spec, type 4 and 10 - 31 are reserved for standard use
+ * and 31 - 63 for custom use.
+ */
+enum riscv_iommu_fq_ttypes {
+ RISCV_IOMMU_FQ_TTYP_NONE = 0,
+ RISCV_IOMMU_FQ_TTYP_UADDR_INST_FETCH = 1,
+ RISCV_IOMMU_FQ_TTYP_UADDR_RD = 2,
+ RISCV_IOMMU_FQ_TTYP_UADDR_WR = 3,
+ RISCV_IOMMU_FQ_TTYP_TADDR_INST_FETCH = 5,
+ RISCV_IOMMU_FQ_TTYP_TADDR_RD = 6,
+ RISCV_IOMMU_FQ_TTYP_TADDR_WR = 7,
+ RISCV_IOMMU_FQ_TTYP_PCIE_ATS_REQ = 8,
+ RISCV_IOMMU_FQ_TTYP_PCIE_MSG_REQ = 9,
+};
+
+/**
+ * struct riscv_iommu_pq_record - PCIe Page Request record
+ * @hdr: Header, includes PID, DID etc
+ * @payload: Holds the page address, request group and permission bits
+ *
+ * For more infos on the PCIe Page Request queue see chapter 3.3.
+ */
+struct riscv_iommu_pq_record {
+ u64 hdr;
+ u64 payload;
+};
+
+/* Header fields */
+#define RISCV_IOMMU_PQ_HDR_PID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_PQ_HDR_PV BIT_ULL(32)
+#define RISCV_IOMMU_PQ_HDR_PRIV BIT_ULL(33)
+#define RISCV_IOMMU_PQ_HDR_EXEC BIT_ULL(34)
+#define RISCV_IOMMU_PQ_HDR_DID GENMASK_ULL(63, 40)
+
+/* Payload fields */
+#define RISCV_IOMMU_PQ_PAYLOAD_R BIT_ULL(0)
+#define RISCV_IOMMU_PQ_PAYLOAD_W BIT_ULL(1)
+#define RISCV_IOMMU_PQ_PAYLOAD_L BIT_ULL(2)
+#define RISCV_IOMMU_PQ_PAYLOAD_RWL_MASK GENMASK_ULL(2, 0)
+#define RISCV_IOMMU_PQ_PAYLOAD_PRGI GENMASK_ULL(11, 3) /* Page Request Group Index */
+#define RISCV_IOMMU_PQ_PAYLOAD_ADDR GENMASK_ULL(63, 12)
+
+/**
+ * struct riscv_iommu_msipte - MSI Page Table Entry
+ * @pte: MSI PTE
+ * @mrif_info: Memory-resident interrupt file info
+ *
+ * The MSI Page Table is used for virtualizing MSIs, so that when
+ * a device sends an MSI to a guest, the IOMMU can reroute it
+ * by translating the MSI address, either to a guest interrupt file
+ * or a memory resident interrupt file (MRIF). Note that this page table
+ * is an array of MSI PTEs, not a multi-level pt, each entry
+ * is a leaf entry. For more infos check out the AIA spec, chapter 9.5.
+ *
+ * Also in basic mode the mrif_info field is ignored by the IOMMU and can
+ * be used by software, any other reserved fields on pte must be zeroed-out
+ * by software.
+ */
+struct riscv_iommu_msipte {
+ u64 pte;
+ u64 mrif_info;
+};
+
+/* Fields on pte */
+#define RISCV_IOMMU_MSIPTE_V BIT_ULL(0)
+#define RISCV_IOMMU_MSIPTE_M GENMASK_ULL(2, 1)
+#define RISCV_IOMMU_MSIPTE_MRIF_ADDR GENMASK_ULL(53, 7) /* When M == 1 (MRIF mode) */
+#define RISCV_IOMMU_MSIPTE_PPN RISCV_IOMMU_PPN_FIELD /* When M == 3 (basic mode) */
+#define RISCV_IOMMU_MSIPTE_C BIT_ULL(63)
+
+/* Fields on mrif_info */
+#define RISCV_IOMMU_MSIPTE_MRIF_NID GENMASK_ULL(9, 0)
+#define RISCV_IOMMU_MSIPTE_MRIF_NPPN RISCV_IOMMU_PPN_FIELD
+#define RISCV_IOMMU_MSIPTE_MRIF_NID_MSB BIT_ULL(60)
+
+/* Helper functions: command structure builders. */
+
+static inline void riscv_iommu_cmd_inval_vma(struct riscv_iommu_command *cmd)
+{
+ cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IOTINVAL_OPCODE) |
+ FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IOTINVAL_FUNC_VMA);
+ cmd->dword1 = 0;
+}
+
+static inline void riscv_iommu_cmd_inval_set_addr(struct riscv_iommu_command *cmd,
+ u64 addr)
+{
+ cmd->dword1 = FIELD_PREP(RISCV_IOMMU_CMD_IOTINVAL_ADDR, phys_to_pfn(addr));
+ cmd->dword0 |= RISCV_IOMMU_CMD_IOTINVAL_AV;
+}
+
+static inline void riscv_iommu_cmd_inval_set_pscid(struct riscv_iommu_command *cmd,
+ int pscid)
+{
+ cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IOTINVAL_PSCID, pscid) |
+ RISCV_IOMMU_CMD_IOTINVAL_PSCV;
+}
+
+static inline void riscv_iommu_cmd_inval_set_gscid(struct riscv_iommu_command *cmd,
+ int gscid)
+{
+ cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IOTINVAL_GSCID, gscid) |
+ RISCV_IOMMU_CMD_IOTINVAL_GV;
+}
+
+static inline void riscv_iommu_cmd_iofence(struct riscv_iommu_command *cmd)
+{
+ cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IOFENCE_OPCODE) |
+ FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IOFENCE_FUNC_C) |
+ RISCV_IOMMU_CMD_IOFENCE_PR | RISCV_IOMMU_CMD_IOFENCE_PW;
+ cmd->dword1 = 0;
+}
+
+static inline void riscv_iommu_cmd_iofence_set_av(struct riscv_iommu_command *cmd,
+ u64 addr, u32 data)
+{
+ cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IOFENCE_OPCODE) |
+ FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IOFENCE_FUNC_C) |
+ FIELD_PREP(RISCV_IOMMU_CMD_IOFENCE_DATA, data) |
+ RISCV_IOMMU_CMD_IOFENCE_AV;
+ cmd->dword1 = addr >> 2;
+}
+
+static inline void riscv_iommu_cmd_iodir_inval_ddt(struct riscv_iommu_command *cmd)
+{
+ cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IODIR_OPCODE) |
+ FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_DDT);
+ cmd->dword1 = 0;
+}
+
+static inline void riscv_iommu_cmd_iodir_inval_pdt(struct riscv_iommu_command *cmd)
+{
+ cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IODIR_OPCODE) |
+ FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_PDT);
+ cmd->dword1 = 0;
+}
+
+static inline void riscv_iommu_cmd_iodir_set_did(struct riscv_iommu_command *cmd,
+ unsigned int devid)
+{
+ cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IODIR_DID, devid) |
+ RISCV_IOMMU_CMD_IODIR_DV;
+}
+
+static inline void riscv_iommu_cmd_iodir_set_pid(struct riscv_iommu_command *cmd,
+ unsigned int pasid)
+{
+ cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IODIR_PID, pasid);
+}
+
+#endif /* _RISCV_IOMMU_BITS_H_ */
diff --git a/drivers/iommu/riscv/iommu-pci.c b/drivers/iommu/riscv/iommu-pci.c
new file mode 100644
index 000000000000..c7a89143014c
--- /dev/null
+++ b/drivers/iommu/riscv/iommu-pci.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright © 2022-2024 Rivos Inc.
+ * Copyright © 2023 FORTH-ICS/CARV
+ *
+ * RISCV IOMMU as a PCIe device
+ *
+ * Authors
+ * Tomasz Jeznach <tjeznach@rivosinc.com>
+ * Nick Kossifidis <mick@ics.forth.gr>
+ */
+
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/iommu.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include "iommu-bits.h"
+#include "iommu.h"
+
+/* QEMU RISC-V IOMMU implementation */
+#define PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014
+
+/* Rivos Inc. assigned PCI Vendor and Device IDs */
+#ifndef PCI_VENDOR_ID_RIVOS
+#define PCI_VENDOR_ID_RIVOS 0x1efd
+#endif
+
+#define PCI_DEVICE_ID_RIVOS_RISCV_IOMMU_GA 0x0008
+
+static int riscv_iommu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ struct riscv_iommu_device *iommu;
+ int rc, vec;
+
+ rc = pcim_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM))
+ return -ENODEV;
+
+ if (pci_resource_len(pdev, 0) < RISCV_IOMMU_REG_SIZE)
+ return -ENODEV;
+
+ rc = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
+ if (rc)
+ return dev_err_probe(dev, rc, "pcim_iomap_regions failed\n");
+
+ iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
+ if (!iommu)
+ return -ENOMEM;
+
+ iommu->dev = dev;
+ iommu->reg = pcim_iomap_table(pdev)[0];
+
+ pci_set_master(pdev);
+ dev_set_drvdata(dev, iommu);
+
+ /* Check device reported capabilities / features. */
+ iommu->caps = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_CAPABILITIES);
+ iommu->fctl = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL);
+
+ /* The PCI driver only uses MSIs, make sure the IOMMU supports this */
+ switch (FIELD_GET(RISCV_IOMMU_CAPABILITIES_IGS, iommu->caps)) {
+ case RISCV_IOMMU_CAPABILITIES_IGS_MSI:
+ case RISCV_IOMMU_CAPABILITIES_IGS_BOTH:
+ break;
+ default:
+ return dev_err_probe(dev, -ENODEV,
+ "unable to use message-signaled interrupts\n");
+ }
+
+ /* Allocate and assign IRQ vectors for the various events */
+ rc = pci_alloc_irq_vectors(pdev, 1, RISCV_IOMMU_INTR_COUNT,
+ PCI_IRQ_MSIX | PCI_IRQ_MSI);
+ if (rc <= 0)
+ return dev_err_probe(dev, -ENODEV,
+ "unable to allocate irq vectors\n");
+
+ iommu->irqs_count = rc;
+ for (vec = 0; vec < iommu->irqs_count; vec++)
+ iommu->irqs[vec] = msi_get_virq(dev, vec);
+
+ /* Enable message-signaled interrupts, fctl.WSI */
+ if (iommu->fctl & RISCV_IOMMU_FCTL_WSI) {
+ iommu->fctl ^= RISCV_IOMMU_FCTL_WSI;
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FCTL, iommu->fctl);
+ }
+
+ return riscv_iommu_init(iommu);
+}
+
+static void riscv_iommu_pci_remove(struct pci_dev *pdev)
+{
+ struct riscv_iommu_device *iommu = dev_get_drvdata(&pdev->dev);
+
+ riscv_iommu_remove(iommu);
+}
+
+static const struct pci_device_id riscv_iommu_pci_tbl[] = {
+ {PCI_VDEVICE(REDHAT, PCI_DEVICE_ID_REDHAT_RISCV_IOMMU), 0},
+ {PCI_VDEVICE(RIVOS, PCI_DEVICE_ID_RIVOS_RISCV_IOMMU_GA), 0},
+ {0,}
+};
+
+static struct pci_driver riscv_iommu_pci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = riscv_iommu_pci_tbl,
+ .probe = riscv_iommu_pci_probe,
+ .remove = riscv_iommu_pci_remove,
+ .driver = {
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_pci_driver(riscv_iommu_pci_driver);
diff --git a/drivers/iommu/riscv/iommu-platform.c b/drivers/iommu/riscv/iommu-platform.c
new file mode 100644
index 000000000000..da336863f152
--- /dev/null
+++ b/drivers/iommu/riscv/iommu-platform.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RISC-V IOMMU as a platform device
+ *
+ * Copyright © 2023 FORTH-ICS/CARV
+ * Copyright © 2023-2024 Rivos Inc.
+ *
+ * Authors
+ * Nick Kossifidis <mick@ics.forth.gr>
+ * Tomasz Jeznach <tjeznach@rivosinc.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include "iommu-bits.h"
+#include "iommu.h"
+
+static int riscv_iommu_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct riscv_iommu_device *iommu = NULL;
+ struct resource *res = NULL;
+ int vec;
+
+ iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
+ if (!iommu)
+ return -ENOMEM;
+
+ iommu->dev = dev;
+ iommu->reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(iommu->reg))
+ return dev_err_probe(dev, PTR_ERR(iommu->reg),
+ "could not map register region\n");
+
+ dev_set_drvdata(dev, iommu);
+
+ /* Check device reported capabilities / features. */
+ iommu->caps = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_CAPABILITIES);
+ iommu->fctl = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL);
+
+ /* For now we only support WSI */
+ switch (FIELD_GET(RISCV_IOMMU_CAPABILITIES_IGS, iommu->caps)) {
+ case RISCV_IOMMU_CAPABILITIES_IGS_WSI:
+ case RISCV_IOMMU_CAPABILITIES_IGS_BOTH:
+ break;
+ default:
+ return dev_err_probe(dev, -ENODEV,
+ "unable to use wire-signaled interrupts\n");
+ }
+
+ iommu->irqs_count = platform_irq_count(pdev);
+ if (iommu->irqs_count <= 0)
+ return dev_err_probe(dev, -ENODEV,
+ "no IRQ resources provided\n");
+ if (iommu->irqs_count > RISCV_IOMMU_INTR_COUNT)
+ iommu->irqs_count = RISCV_IOMMU_INTR_COUNT;
+
+ for (vec = 0; vec < iommu->irqs_count; vec++)
+ iommu->irqs[vec] = platform_get_irq(pdev, vec);
+
+ /* Enable wire-signaled interrupts, fctl.WSI */
+ if (!(iommu->fctl & RISCV_IOMMU_FCTL_WSI)) {
+ iommu->fctl |= RISCV_IOMMU_FCTL_WSI;
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FCTL, iommu->fctl);
+ }
+
+ return riscv_iommu_init(iommu);
+};
+
+static void riscv_iommu_platform_remove(struct platform_device *pdev)
+{
+ riscv_iommu_remove(dev_get_drvdata(&pdev->dev));
+};
+
+static const struct of_device_id riscv_iommu_of_match[] = {
+ {.compatible = "riscv,iommu",},
+ {},
+};
+
+static struct platform_driver riscv_iommu_platform_driver = {
+ .probe = riscv_iommu_platform_probe,
+ .remove_new = riscv_iommu_platform_remove,
+ .driver = {
+ .name = "riscv,iommu",
+ .of_match_table = riscv_iommu_of_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_platform_driver(riscv_iommu_platform_driver);
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
new file mode 100644
index 000000000000..8a05def774bd
--- /dev/null
+++ b/drivers/iommu/riscv/iommu.c
@@ -0,0 +1,1661 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IOMMU API for RISC-V IOMMU implementations.
+ *
+ * Copyright © 2022-2024 Rivos Inc.
+ * Copyright © 2023 FORTH-ICS/CARV
+ *
+ * Authors
+ * Tomasz Jeznach <tjeznach@rivosinc.com>
+ * Nick Kossifidis <mick@ics.forth.gr>
+ */
+
+#define pr_fmt(fmt) "riscv-iommu: " fmt
+
+#include <linux/compiler.h>
+#include <linux/crash_dump.h>
+#include <linux/init.h>
+#include <linux/iommu.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include "../iommu-pages.h"
+#include "iommu-bits.h"
+#include "iommu.h"
+
+/* Timeouts in [us] */
+#define RISCV_IOMMU_QCSR_TIMEOUT 150000
+#define RISCV_IOMMU_QUEUE_TIMEOUT 150000
+#define RISCV_IOMMU_DDTP_TIMEOUT 10000000
+#define RISCV_IOMMU_IOTINVAL_TIMEOUT 90000000
+
+/* Number of entries per CMD/FLT queue, should be <= INT_MAX */
+#define RISCV_IOMMU_DEF_CQ_COUNT 8192
+#define RISCV_IOMMU_DEF_FQ_COUNT 4096
+
+/* RISC-V IOMMU PPN <> PHYS address conversions, PHYS <=> PPN[53:10] */
+#define phys_to_ppn(pa) (((pa) >> 2) & (((1ULL << 44) - 1) << 10))
+#define ppn_to_phys(pn) (((pn) << 2) & (((1ULL << 44) - 1) << 12))
+
+#define dev_to_iommu(dev) \
+ iommu_get_iommu_dev(dev, struct riscv_iommu_device, iommu)
+
+/* IOMMU PSCID allocation namespace. */
+static DEFINE_IDA(riscv_iommu_pscids);
+#define RISCV_IOMMU_MAX_PSCID (BIT(20) - 1)
+
+/* Device resource-managed allocations */
+struct riscv_iommu_devres {
+ void *addr;
+ int order;
+};
+
+static void riscv_iommu_devres_pages_release(struct device *dev, void *res)
+{
+ struct riscv_iommu_devres *devres = res;
+
+ iommu_free_pages(devres->addr, devres->order);
+}
+
+static int riscv_iommu_devres_pages_match(struct device *dev, void *res, void *p)
+{
+ struct riscv_iommu_devres *devres = res;
+ struct riscv_iommu_devres *target = p;
+
+ return devres->addr == target->addr;
+}
+
+static void *riscv_iommu_get_pages(struct riscv_iommu_device *iommu, int order)
+{
+ struct riscv_iommu_devres *devres;
+ void *addr;
+
+ addr = iommu_alloc_pages_node(dev_to_node(iommu->dev),
+ GFP_KERNEL_ACCOUNT, order);
+ if (unlikely(!addr))
+ return NULL;
+
+ devres = devres_alloc(riscv_iommu_devres_pages_release,
+ sizeof(struct riscv_iommu_devres), GFP_KERNEL);
+
+ if (unlikely(!devres)) {
+ iommu_free_pages(addr, order);
+ return NULL;
+ }
+
+ devres->addr = addr;
+ devres->order = order;
+
+ devres_add(iommu->dev, devres);
+
+ return addr;
+}
+
+static void riscv_iommu_free_pages(struct riscv_iommu_device *iommu, void *addr)
+{
+ struct riscv_iommu_devres devres = { .addr = addr };
+
+ devres_release(iommu->dev, riscv_iommu_devres_pages_release,
+ riscv_iommu_devres_pages_match, &devres);
+}
+
+/*
+ * Hardware queue allocation and management.
+ */
+
+/* Setup queue base, control registers and default queue length */
+#define RISCV_IOMMU_QUEUE_INIT(q, name) do { \
+ struct riscv_iommu_queue *_q = q; \
+ _q->qid = RISCV_IOMMU_INTR_ ## name; \
+ _q->qbr = RISCV_IOMMU_REG_ ## name ## B; \
+ _q->qcr = RISCV_IOMMU_REG_ ## name ## CSR; \
+ _q->mask = _q->mask ?: (RISCV_IOMMU_DEF_ ## name ## _COUNT) - 1;\
+} while (0)
+
+/* Note: offsets are the same for all queues */
+#define Q_HEAD(q) ((q)->qbr + (RISCV_IOMMU_REG_CQH - RISCV_IOMMU_REG_CQB))
+#define Q_TAIL(q) ((q)->qbr + (RISCV_IOMMU_REG_CQT - RISCV_IOMMU_REG_CQB))
+#define Q_ITEM(q, index) ((q)->mask & (index))
+#define Q_IPSR(q) BIT((q)->qid)
+
+/*
+ * Discover queue ring buffer hardware configuration, allocate in-memory
+ * ring buffer or use fixed I/O memory location, configure queue base register.
+ * Must be called before hardware queue is enabled.
+ *
+ * @queue - data structure, configured with RISCV_IOMMU_QUEUE_INIT()
+ * @entry_size - queue single element size in bytes.
+ */
+static int riscv_iommu_queue_alloc(struct riscv_iommu_device *iommu,
+ struct riscv_iommu_queue *queue,
+ size_t entry_size)
+{
+ unsigned int logsz;
+ u64 qb, rb;
+
+ /*
+ * Use WARL base register property to discover maximum allowed
+ * number of entries and optional fixed IO address for queue location.
+ */
+ riscv_iommu_writeq(iommu, queue->qbr, RISCV_IOMMU_QUEUE_LOG2SZ_FIELD);
+ qb = riscv_iommu_readq(iommu, queue->qbr);
+
+ /*
+ * Calculate and verify hardware supported queue length, as reported
+ * by the field LOG2SZ, where max queue length is equal to 2^(LOG2SZ + 1).
+ * Update queue size based on hardware supported value.
+ */
+ logsz = ilog2(queue->mask);
+ if (logsz > FIELD_GET(RISCV_IOMMU_QUEUE_LOG2SZ_FIELD, qb))
+ logsz = FIELD_GET(RISCV_IOMMU_QUEUE_LOG2SZ_FIELD, qb);
+
+ /*
+ * Use WARL base register property to discover an optional fixed IO
+ * address for queue ring buffer location. Otherwise allocate contiguous
+ * system memory.
+ */
+ if (FIELD_GET(RISCV_IOMMU_PPN_FIELD, qb)) {
+ const size_t queue_size = entry_size << (logsz + 1);
+
+ queue->phys = pfn_to_phys(FIELD_GET(RISCV_IOMMU_PPN_FIELD, qb));
+ queue->base = devm_ioremap(iommu->dev, queue->phys, queue_size);
+ } else {
+ do {
+ const size_t queue_size = entry_size << (logsz + 1);
+ const int order = get_order(queue_size);
+
+ queue->base = riscv_iommu_get_pages(iommu, order);
+ queue->phys = __pa(queue->base);
+ } while (!queue->base && logsz-- > 0);
+ }
+
+ if (!queue->base)
+ return -ENOMEM;
+
+ qb = phys_to_ppn(queue->phys) |
+ FIELD_PREP(RISCV_IOMMU_QUEUE_LOG2SZ_FIELD, logsz);
+
+ /* Update base register and read back to verify hw accepted our write */
+ riscv_iommu_writeq(iommu, queue->qbr, qb);
+ rb = riscv_iommu_readq(iommu, queue->qbr);
+ if (rb != qb) {
+ dev_err(iommu->dev, "queue #%u allocation failed\n", queue->qid);
+ return -ENODEV;
+ }
+
+ /* Update actual queue mask */
+ queue->mask = (2U << logsz) - 1;
+
+ dev_dbg(iommu->dev, "queue #%u allocated 2^%u entries",
+ queue->qid, logsz + 1);
+
+ return 0;
+}
+
+/* Check interrupt queue status, IPSR */
+static irqreturn_t riscv_iommu_queue_ipsr(int irq, void *data)
+{
+ struct riscv_iommu_queue *queue = (struct riscv_iommu_queue *)data;
+
+ if (riscv_iommu_readl(queue->iommu, RISCV_IOMMU_REG_IPSR) & Q_IPSR(queue))
+ return IRQ_WAKE_THREAD;
+
+ return IRQ_NONE;
+}
+
+static int riscv_iommu_queue_vec(struct riscv_iommu_device *iommu, int n)
+{
+ /* Reuse ICVEC.CIV mask for all interrupt vectors mapping. */
+ return (iommu->icvec >> (n * 4)) & RISCV_IOMMU_ICVEC_CIV;
+}
+
+/*
+ * Enable queue processing in the hardware, register interrupt handler.
+ *
+ * @queue - data structure, already allocated with riscv_iommu_queue_alloc()
+ * @irq_handler - threaded interrupt handler.
+ */
+static int riscv_iommu_queue_enable(struct riscv_iommu_device *iommu,
+ struct riscv_iommu_queue *queue,
+ irq_handler_t irq_handler)
+{
+ const unsigned int irq = iommu->irqs[riscv_iommu_queue_vec(iommu, queue->qid)];
+ u32 csr;
+ int rc;
+
+ if (queue->iommu)
+ return -EBUSY;
+
+ /* Polling not implemented */
+ if (!irq)
+ return -ENODEV;
+
+ queue->iommu = iommu;
+ rc = request_threaded_irq(irq, riscv_iommu_queue_ipsr, irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ dev_name(iommu->dev), queue);
+ if (rc) {
+ queue->iommu = NULL;
+ return rc;
+ }
+
+ /*
+ * Enable queue with interrupts, clear any memory fault if any.
+ * Wait for the hardware to acknowledge request and activate queue
+ * processing.
+ * Note: All CSR bitfields are in the same offsets for all queues.
+ */
+ riscv_iommu_writel(iommu, queue->qcr,
+ RISCV_IOMMU_QUEUE_ENABLE |
+ RISCV_IOMMU_QUEUE_INTR_ENABLE |
+ RISCV_IOMMU_QUEUE_MEM_FAULT);
+
+ riscv_iommu_readl_timeout(iommu, queue->qcr,
+ csr, !(csr & RISCV_IOMMU_QUEUE_BUSY),
+ 10, RISCV_IOMMU_QCSR_TIMEOUT);
+
+ if (RISCV_IOMMU_QUEUE_ACTIVE != (csr & (RISCV_IOMMU_QUEUE_ACTIVE |
+ RISCV_IOMMU_QUEUE_BUSY |
+ RISCV_IOMMU_QUEUE_MEM_FAULT))) {
+ /* Best effort to stop and disable failing hardware queue. */
+ riscv_iommu_writel(iommu, queue->qcr, 0);
+ free_irq(irq, queue);
+ queue->iommu = NULL;
+ dev_err(iommu->dev, "queue #%u failed to start\n", queue->qid);
+ return -EBUSY;
+ }
+
+ /* Clear any pending interrupt flag. */
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_IPSR, Q_IPSR(queue));
+
+ return 0;
+}
+
+/*
+ * Disable queue. Wait for the hardware to acknowledge request and
+ * stop processing enqueued requests. Report errors but continue.
+ */
+static void riscv_iommu_queue_disable(struct riscv_iommu_queue *queue)
+{
+ struct riscv_iommu_device *iommu = queue->iommu;
+ u32 csr;
+
+ if (!iommu)
+ return;
+
+ free_irq(iommu->irqs[riscv_iommu_queue_vec(iommu, queue->qid)], queue);
+ riscv_iommu_writel(iommu, queue->qcr, 0);
+ riscv_iommu_readl_timeout(iommu, queue->qcr,
+ csr, !(csr & RISCV_IOMMU_QUEUE_BUSY),
+ 10, RISCV_IOMMU_QCSR_TIMEOUT);
+
+ if (csr & (RISCV_IOMMU_QUEUE_ACTIVE | RISCV_IOMMU_QUEUE_BUSY))
+ dev_err(iommu->dev, "fail to disable hardware queue #%u, csr 0x%x\n",
+ queue->qid, csr);
+
+ queue->iommu = NULL;
+}
+
+/*
+ * Returns number of available valid queue entries and the first item index.
+ * Update shadow producer index if necessary.
+ */
+static int riscv_iommu_queue_consume(struct riscv_iommu_queue *queue,
+ unsigned int *index)
+{
+ unsigned int head = atomic_read(&queue->head);
+ unsigned int tail = atomic_read(&queue->tail);
+ unsigned int last = Q_ITEM(queue, tail);
+ int available = (int)(tail - head);
+
+ *index = head;
+
+ if (available > 0)
+ return available;
+
+ /* read hardware producer index, check reserved register bits are not set. */
+ if (riscv_iommu_readl_timeout(queue->iommu, Q_TAIL(queue),
+ tail, (tail & ~queue->mask) == 0,
+ 0, RISCV_IOMMU_QUEUE_TIMEOUT)) {
+ dev_err_once(queue->iommu->dev,
+ "Hardware error: queue access timeout\n");
+ return 0;
+ }
+
+ if (tail == last)
+ return 0;
+
+ /* update shadow producer index */
+ return (int)(atomic_add_return((tail - last) & queue->mask, &queue->tail) - head);
+}
+
+/*
+ * Release processed queue entries, should match riscv_iommu_queue_consume() calls.
+ */
+static void riscv_iommu_queue_release(struct riscv_iommu_queue *queue, int count)
+{
+ const unsigned int head = atomic_add_return(count, &queue->head);
+
+ riscv_iommu_writel(queue->iommu, Q_HEAD(queue), Q_ITEM(queue, head));
+}
+
+/* Return actual consumer index based on hardware reported queue head index. */
+static unsigned int riscv_iommu_queue_cons(struct riscv_iommu_queue *queue)
+{
+ const unsigned int cons = atomic_read(&queue->head);
+ const unsigned int last = Q_ITEM(queue, cons);
+ unsigned int head;
+
+ if (riscv_iommu_readl_timeout(queue->iommu, Q_HEAD(queue), head,
+ !(head & ~queue->mask),
+ 0, RISCV_IOMMU_QUEUE_TIMEOUT))
+ return cons;
+
+ return cons + ((head - last) & queue->mask);
+}
+
+/* Wait for submitted item to be processed. */
+static int riscv_iommu_queue_wait(struct riscv_iommu_queue *queue,
+ unsigned int index,
+ unsigned int timeout_us)
+{
+ unsigned int cons = atomic_read(&queue->head);
+
+ /* Already processed by the consumer */
+ if ((int)(cons - index) > 0)
+ return 0;
+
+ /* Monitor consumer index */
+ return readx_poll_timeout(riscv_iommu_queue_cons, queue, cons,
+ (int)(cons - index) > 0, 0, timeout_us);
+}
+
+/* Enqueue an entry and wait to be processed if timeout_us > 0
+ *
+ * Error handling for IOMMU hardware not responding in reasonable time
+ * will be added as separate patch series along with other RAS features.
+ * For now, only report hardware failure and continue.
+ */
+static unsigned int riscv_iommu_queue_send(struct riscv_iommu_queue *queue,
+ void *entry, size_t entry_size)
+{
+ unsigned int prod;
+ unsigned int head;
+ unsigned int tail;
+ unsigned long flags;
+
+ /* Do not preempt submission flow. */
+ local_irq_save(flags);
+
+ /* 1. Allocate some space in the queue */
+ prod = atomic_inc_return(&queue->prod) - 1;
+ head = atomic_read(&queue->head);
+
+ /* 2. Wait for space availability. */
+ if ((prod - head) > queue->mask) {
+ if (readx_poll_timeout(atomic_read, &queue->head,
+ head, (prod - head) < queue->mask,
+ 0, RISCV_IOMMU_QUEUE_TIMEOUT))
+ goto err_busy;
+ } else if ((prod - head) == queue->mask) {
+ const unsigned int last = Q_ITEM(queue, head);
+
+ if (riscv_iommu_readl_timeout(queue->iommu, Q_HEAD(queue), head,
+ !(head & ~queue->mask) && head != last,
+ 0, RISCV_IOMMU_QUEUE_TIMEOUT))
+ goto err_busy;
+ atomic_add((head - last) & queue->mask, &queue->head);
+ }
+
+ /* 3. Store entry in the ring buffer */
+ memcpy(queue->base + Q_ITEM(queue, prod) * entry_size, entry, entry_size);
+
+ /* 4. Wait for all previous entries to be ready */
+ if (readx_poll_timeout(atomic_read, &queue->tail, tail, prod == tail,
+ 0, RISCV_IOMMU_QUEUE_TIMEOUT))
+ goto err_busy;
+
+ /*
+ * 5. Make sure the ring buffer update (whether in normal or I/O memory) is
+ * completed and visible before signaling the tail doorbell to fetch
+ * the next command. 'fence ow, ow'
+ */
+ dma_wmb();
+ riscv_iommu_writel(queue->iommu, Q_TAIL(queue), Q_ITEM(queue, prod + 1));
+
+ /*
+ * 6. Make sure the doorbell write to the device has finished before updating
+ * the shadow tail index in normal memory. 'fence o, w'
+ */
+ mmiowb();
+ atomic_inc(&queue->tail);
+
+ /* 7. Complete submission and restore local interrupts */
+ local_irq_restore(flags);
+
+ return prod;
+
+err_busy:
+ local_irq_restore(flags);
+ dev_err_once(queue->iommu->dev, "Hardware error: command enqueue failed\n");
+
+ return prod;
+}
+
+/*
+ * IOMMU Command queue chapter 3.1
+ */
+
+/* Command queue interrupt handler thread function */
+static irqreturn_t riscv_iommu_cmdq_process(int irq, void *data)
+{
+ const struct riscv_iommu_queue *queue = (struct riscv_iommu_queue *)data;
+ unsigned int ctrl;
+
+ /* Clear MF/CQ errors, complete error recovery to be implemented. */
+ ctrl = riscv_iommu_readl(queue->iommu, queue->qcr);
+ if (ctrl & (RISCV_IOMMU_CQCSR_CQMF | RISCV_IOMMU_CQCSR_CMD_TO |
+ RISCV_IOMMU_CQCSR_CMD_ILL | RISCV_IOMMU_CQCSR_FENCE_W_IP)) {
+ riscv_iommu_writel(queue->iommu, queue->qcr, ctrl);
+ dev_warn(queue->iommu->dev,
+ "Queue #%u error; fault:%d timeout:%d illegal:%d fence_w_ip:%d\n",
+ queue->qid,
+ !!(ctrl & RISCV_IOMMU_CQCSR_CQMF),
+ !!(ctrl & RISCV_IOMMU_CQCSR_CMD_TO),
+ !!(ctrl & RISCV_IOMMU_CQCSR_CMD_ILL),
+ !!(ctrl & RISCV_IOMMU_CQCSR_FENCE_W_IP));
+ }
+
+ /* Placeholder for command queue interrupt notifiers */
+
+ /* Clear command interrupt pending. */
+ riscv_iommu_writel(queue->iommu, RISCV_IOMMU_REG_IPSR, Q_IPSR(queue));
+
+ return IRQ_HANDLED;
+}
+
+/* Send command to the IOMMU command queue */
+static void riscv_iommu_cmd_send(struct riscv_iommu_device *iommu,
+ struct riscv_iommu_command *cmd)
+{
+ riscv_iommu_queue_send(&iommu->cmdq, cmd, sizeof(*cmd));
+}
+
+/* Send IOFENCE.C command and wait for all scheduled commands to complete. */
+static void riscv_iommu_cmd_sync(struct riscv_iommu_device *iommu,
+ unsigned int timeout_us)
+{
+ struct riscv_iommu_command cmd;
+ unsigned int prod;
+
+ riscv_iommu_cmd_iofence(&cmd);
+ prod = riscv_iommu_queue_send(&iommu->cmdq, &cmd, sizeof(cmd));
+
+ if (!timeout_us)
+ return;
+
+ if (riscv_iommu_queue_wait(&iommu->cmdq, prod, timeout_us))
+ dev_err_once(iommu->dev,
+ "Hardware error: command execution timeout\n");
+}
+
+/*
+ * IOMMU Fault/Event queue chapter 3.2
+ */
+
+static void riscv_iommu_fault(struct riscv_iommu_device *iommu,
+ struct riscv_iommu_fq_record *event)
+{
+ unsigned int err = FIELD_GET(RISCV_IOMMU_FQ_HDR_CAUSE, event->hdr);
+ unsigned int devid = FIELD_GET(RISCV_IOMMU_FQ_HDR_DID, event->hdr);
+
+ /* Placeholder for future fault handling implementation, report only. */
+ if (err)
+ dev_warn_ratelimited(iommu->dev,
+ "Fault %d devid: 0x%x iotval: %llx iotval2: %llx\n",
+ err, devid, event->iotval, event->iotval2);
+}
+
+/* Fault queue interrupt handler thread function */
+static irqreturn_t riscv_iommu_fltq_process(int irq, void *data)
+{
+ struct riscv_iommu_queue *queue = (struct riscv_iommu_queue *)data;
+ struct riscv_iommu_device *iommu = queue->iommu;
+ struct riscv_iommu_fq_record *events;
+ unsigned int ctrl, idx;
+ int cnt, len;
+
+ events = (struct riscv_iommu_fq_record *)queue->base;
+
+ /* Clear fault interrupt pending and process all received fault events. */
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_IPSR, Q_IPSR(queue));
+
+ do {
+ cnt = riscv_iommu_queue_consume(queue, &idx);
+ for (len = 0; len < cnt; idx++, len++)
+ riscv_iommu_fault(iommu, &events[Q_ITEM(queue, idx)]);
+ riscv_iommu_queue_release(queue, cnt);
+ } while (cnt > 0);
+
+ /* Clear MF/OF errors, complete error recovery to be implemented. */
+ ctrl = riscv_iommu_readl(iommu, queue->qcr);
+ if (ctrl & (RISCV_IOMMU_FQCSR_FQMF | RISCV_IOMMU_FQCSR_FQOF)) {
+ riscv_iommu_writel(iommu, queue->qcr, ctrl);
+ dev_warn(iommu->dev,
+ "Queue #%u error; memory fault:%d overflow:%d\n",
+ queue->qid,
+ !!(ctrl & RISCV_IOMMU_FQCSR_FQMF),
+ !!(ctrl & RISCV_IOMMU_FQCSR_FQOF));
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* Lookup and initialize device context info structure. */
+static struct riscv_iommu_dc *riscv_iommu_get_dc(struct riscv_iommu_device *iommu,
+ unsigned int devid)
+{
+ const bool base_format = !(iommu->caps & RISCV_IOMMU_CAPABILITIES_MSI_FLAT);
+ unsigned int depth;
+ unsigned long ddt, old, new;
+ void *ptr;
+ u8 ddi_bits[3] = { 0 };
+ u64 *ddtp = NULL;
+
+ /* Make sure the mode is valid */
+ if (iommu->ddt_mode < RISCV_IOMMU_DDTP_IOMMU_MODE_1LVL ||
+ iommu->ddt_mode > RISCV_IOMMU_DDTP_IOMMU_MODE_3LVL)
+ return NULL;
+
+ /*
+ * Device id partitioning for base format:
+ * DDI[0]: bits 0 - 6 (1st level) (7 bits)
+ * DDI[1]: bits 7 - 15 (2nd level) (9 bits)
+ * DDI[2]: bits 16 - 23 (3rd level) (8 bits)
+ *
+ * For extended format:
+ * DDI[0]: bits 0 - 5 (1st level) (6 bits)
+ * DDI[1]: bits 6 - 14 (2nd level) (9 bits)
+ * DDI[2]: bits 15 - 23 (3rd level) (9 bits)
+ */
+ if (base_format) {
+ ddi_bits[0] = 7;
+ ddi_bits[1] = 7 + 9;
+ ddi_bits[2] = 7 + 9 + 8;
+ } else {
+ ddi_bits[0] = 6;
+ ddi_bits[1] = 6 + 9;
+ ddi_bits[2] = 6 + 9 + 9;
+ }
+
+ /* Make sure device id is within range */
+ depth = iommu->ddt_mode - RISCV_IOMMU_DDTP_IOMMU_MODE_1LVL;
+ if (devid >= (1 << ddi_bits[depth]))
+ return NULL;
+
+ /* Get to the level of the non-leaf node that holds the device context */
+ for (ddtp = iommu->ddt_root; depth-- > 0;) {
+ const int split = ddi_bits[depth];
+ /*
+ * Each non-leaf node is 64bits wide and on each level
+ * nodes are indexed by DDI[depth].
+ */
+ ddtp += (devid >> split) & 0x1FF;
+
+ /*
+ * Check if this node has been populated and if not
+ * allocate a new level and populate it.
+ */
+ do {
+ ddt = READ_ONCE(*(unsigned long *)ddtp);
+ if (ddt & RISCV_IOMMU_DDTE_V) {
+ ddtp = __va(ppn_to_phys(ddt));
+ break;
+ }
+
+ ptr = riscv_iommu_get_pages(iommu, 0);
+ if (!ptr)
+ return NULL;
+
+ new = phys_to_ppn(__pa(ptr)) | RISCV_IOMMU_DDTE_V;
+ old = cmpxchg_relaxed((unsigned long *)ddtp, ddt, new);
+
+ if (old == ddt) {
+ ddtp = (u64 *)ptr;
+ break;
+ }
+
+ /* Race setting DDT detected, re-read and retry. */
+ riscv_iommu_free_pages(iommu, ptr);
+ } while (1);
+ }
+
+ /*
+ * Grab the node that matches DDI[depth], note that when using base
+ * format the device context is 4 * 64bits, and the extended format
+ * is 8 * 64bits, hence the (3 - base_format) below.
+ */
+ ddtp += (devid & ((64 << base_format) - 1)) << (3 - base_format);
+
+ return (struct riscv_iommu_dc *)ddtp;
+}
+
+/*
+ * This is best effort IOMMU translation shutdown flow.
+ * Disable IOMMU without waiting for hardware response.
+ */
+static void riscv_iommu_disable(struct riscv_iommu_device *iommu)
+{
+ riscv_iommu_writeq(iommu, RISCV_IOMMU_REG_DDTP, 0);
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_CQCSR, 0);
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FQCSR, 0);
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_PQCSR, 0);
+}
+
+#define riscv_iommu_read_ddtp(iommu) ({ \
+ u64 ddtp; \
+ riscv_iommu_readq_timeout((iommu), RISCV_IOMMU_REG_DDTP, ddtp, \
+ !(ddtp & RISCV_IOMMU_DDTP_BUSY), 10, \
+ RISCV_IOMMU_DDTP_TIMEOUT); \
+ ddtp; })
+
+static int riscv_iommu_iodir_alloc(struct riscv_iommu_device *iommu)
+{
+ u64 ddtp;
+ unsigned int mode;
+
+ ddtp = riscv_iommu_read_ddtp(iommu);
+ if (ddtp & RISCV_IOMMU_DDTP_BUSY)
+ return -EBUSY;
+
+ /*
+ * It is optional for the hardware to report a fixed address for device
+ * directory root page when DDT.MODE is OFF or BARE.
+ */
+ mode = FIELD_GET(RISCV_IOMMU_DDTP_IOMMU_MODE, ddtp);
+ if (mode == RISCV_IOMMU_DDTP_IOMMU_MODE_BARE ||
+ mode == RISCV_IOMMU_DDTP_IOMMU_MODE_OFF) {
+ /* Use WARL to discover hardware fixed DDT PPN */
+ riscv_iommu_writeq(iommu, RISCV_IOMMU_REG_DDTP,
+ FIELD_PREP(RISCV_IOMMU_DDTP_IOMMU_MODE, mode));
+ ddtp = riscv_iommu_read_ddtp(iommu);
+ if (ddtp & RISCV_IOMMU_DDTP_BUSY)
+ return -EBUSY;
+
+ iommu->ddt_phys = ppn_to_phys(ddtp);
+ if (iommu->ddt_phys)
+ iommu->ddt_root = devm_ioremap(iommu->dev,
+ iommu->ddt_phys, PAGE_SIZE);
+ if (iommu->ddt_root)
+ memset(iommu->ddt_root, 0, PAGE_SIZE);
+ }
+
+ if (!iommu->ddt_root) {
+ iommu->ddt_root = riscv_iommu_get_pages(iommu, 0);
+ iommu->ddt_phys = __pa(iommu->ddt_root);
+ }
+
+ if (!iommu->ddt_root)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/*
+ * Discover supported DDT modes starting from requested value,
+ * configure DDTP register with accepted mode and root DDT address.
+ * Accepted iommu->ddt_mode is updated on success.
+ */
+static int riscv_iommu_iodir_set_mode(struct riscv_iommu_device *iommu,
+ unsigned int ddtp_mode)
+{
+ struct device *dev = iommu->dev;
+ u64 ddtp, rq_ddtp;
+ unsigned int mode, rq_mode = ddtp_mode;
+ struct riscv_iommu_command cmd;
+
+ ddtp = riscv_iommu_read_ddtp(iommu);
+ if (ddtp & RISCV_IOMMU_DDTP_BUSY)
+ return -EBUSY;
+
+ /* Disallow state transition from xLVL to xLVL. */
+ mode = FIELD_GET(RISCV_IOMMU_DDTP_IOMMU_MODE, ddtp);
+ if (mode != RISCV_IOMMU_DDTP_IOMMU_MODE_BARE &&
+ mode != RISCV_IOMMU_DDTP_IOMMU_MODE_OFF &&
+ rq_mode != RISCV_IOMMU_DDTP_IOMMU_MODE_BARE &&
+ rq_mode != RISCV_IOMMU_DDTP_IOMMU_MODE_OFF)
+ return -EINVAL;
+
+ do {
+ rq_ddtp = FIELD_PREP(RISCV_IOMMU_DDTP_IOMMU_MODE, rq_mode);
+ if (rq_mode > RISCV_IOMMU_DDTP_IOMMU_MODE_BARE)
+ rq_ddtp |= phys_to_ppn(iommu->ddt_phys);
+
+ riscv_iommu_writeq(iommu, RISCV_IOMMU_REG_DDTP, rq_ddtp);
+ ddtp = riscv_iommu_read_ddtp(iommu);
+ if (ddtp & RISCV_IOMMU_DDTP_BUSY) {
+ dev_err(dev, "timeout when setting ddtp (ddt mode: %u, read: %llx)\n",
+ rq_mode, ddtp);
+ return -EBUSY;
+ }
+
+ /* Verify IOMMU hardware accepts new DDTP config. */
+ mode = FIELD_GET(RISCV_IOMMU_DDTP_IOMMU_MODE, ddtp);
+
+ if (rq_mode == mode)
+ break;
+
+ /* Hardware mandatory DDTP mode has not been accepted. */
+ if (rq_mode < RISCV_IOMMU_DDTP_IOMMU_MODE_1LVL && rq_ddtp != ddtp) {
+ dev_err(dev, "DDTP update failed hw: %llx vs %llx\n",
+ ddtp, rq_ddtp);
+ return -EINVAL;
+ }
+
+ /*
+ * Mode field is WARL, an IOMMU may support a subset of
+ * directory table levels in which case if we tried to set
+ * an unsupported number of levels we'll readback either
+ * a valid xLVL or off/bare. If we got off/bare, try again
+ * with a smaller xLVL.
+ */
+ if (mode < RISCV_IOMMU_DDTP_IOMMU_MODE_1LVL &&
+ rq_mode > RISCV_IOMMU_DDTP_IOMMU_MODE_1LVL) {
+ dev_dbg(dev, "DDTP hw mode %u vs %u\n", mode, rq_mode);
+ rq_mode--;
+ continue;
+ }
+
+ /*
+ * We tried all supported modes and IOMMU hardware failed to
+ * accept new settings, something went very wrong since off/bare
+ * and at least one xLVL must be supported.
+ */
+ dev_err(dev, "DDTP hw mode %u, failed to set %u\n",
+ mode, ddtp_mode);
+ return -EINVAL;
+ } while (1);
+
+ iommu->ddt_mode = mode;
+ if (mode != ddtp_mode)
+ dev_dbg(dev, "DDTP hw mode %u, requested %u\n", mode, ddtp_mode);
+
+ /* Invalidate device context cache */
+ riscv_iommu_cmd_iodir_inval_ddt(&cmd);
+ riscv_iommu_cmd_send(iommu, &cmd);
+
+ /* Invalidate address translation cache */
+ riscv_iommu_cmd_inval_vma(&cmd);
+ riscv_iommu_cmd_send(iommu, &cmd);
+
+ /* IOFENCE.C */
+ riscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);
+
+ return 0;
+}
+
+/* This struct contains protection domain specific IOMMU driver data. */
+struct riscv_iommu_domain {
+ struct iommu_domain domain;
+ struct list_head bonds;
+ spinlock_t lock; /* protect bonds list updates. */
+ int pscid;
+ bool amo_enabled;
+ int numa_node;
+ unsigned int pgd_mode;
+ unsigned long *pgd_root;
+};
+
+#define iommu_domain_to_riscv(iommu_domain) \
+ container_of(iommu_domain, struct riscv_iommu_domain, domain)
+
+/* Private IOMMU data for managed devices, dev_iommu_priv_* */
+struct riscv_iommu_info {
+ struct riscv_iommu_domain *domain;
+};
+
+/*
+ * Linkage between an iommu_domain and attached devices.
+ *
+ * Protection domain requiring IOATC and DevATC translation cache invalidations,
+ * should be linked to attached devices using a riscv_iommu_bond structure.
+ * Devices should be linked to the domain before first use and unlinked after
+ * the translations from the referenced protection domain can no longer be used.
+ * Blocking and identity domains are not tracked here, as the IOMMU hardware
+ * does not cache negative and/or identity (BARE mode) translations, and DevATC
+ * is disabled for those protection domains.
+ *
+ * The device pointer and IOMMU data remain stable in the bond struct after
+ * _probe_device() where it's attached to the managed IOMMU, up to the
+ * completion of the _release_device() call. The release of the bond structure
+ * is synchronized with the device release.
+ */
+struct riscv_iommu_bond {
+ struct list_head list;
+ struct rcu_head rcu;
+ struct device *dev;
+};
+
+static int riscv_iommu_bond_link(struct riscv_iommu_domain *domain,
+ struct device *dev)
+{
+ struct riscv_iommu_device *iommu = dev_to_iommu(dev);
+ struct riscv_iommu_bond *bond;
+ struct list_head *bonds;
+
+ bond = kzalloc(sizeof(*bond), GFP_KERNEL);
+ if (!bond)
+ return -ENOMEM;
+ bond->dev = dev;
+
+ /*
+ * List of devices attached to the domain is arranged based on
+ * managed IOMMU device.
+ */
+
+ spin_lock(&domain->lock);
+ list_for_each(bonds, &domain->bonds)
+ if (dev_to_iommu(list_entry(bonds, struct riscv_iommu_bond, list)->dev) == iommu)
+ break;
+ list_add_rcu(&bond->list, bonds);
+ spin_unlock(&domain->lock);
+
+ /* Synchronize with riscv_iommu_iotlb_inval() sequence. See comment below. */
+ smp_mb();
+
+ return 0;
+}
+
+static void riscv_iommu_bond_unlink(struct riscv_iommu_domain *domain,
+ struct device *dev)
+{
+ struct riscv_iommu_device *iommu = dev_to_iommu(dev);
+ struct riscv_iommu_bond *bond, *found = NULL;
+ struct riscv_iommu_command cmd;
+ int count = 0;
+
+ if (!domain)
+ return;
+
+ spin_lock(&domain->lock);
+ list_for_each_entry(bond, &domain->bonds, list) {
+ if (found && count)
+ break;
+ else if (bond->dev == dev)
+ found = bond;
+ else if (dev_to_iommu(bond->dev) == iommu)
+ count++;
+ }
+ if (found)
+ list_del_rcu(&found->list);
+ spin_unlock(&domain->lock);
+ kfree_rcu(found, rcu);
+
+ /*
+ * If this was the last bond between this domain and the IOMMU
+ * invalidate all cached entries for domain's PSCID.
+ */
+ if (!count) {
+ riscv_iommu_cmd_inval_vma(&cmd);
+ riscv_iommu_cmd_inval_set_pscid(&cmd, domain->pscid);
+ riscv_iommu_cmd_send(iommu, &cmd);
+
+ riscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);
+ }
+}
+
+/*
+ * Send IOTLB.INVAL for whole address space for ranges larger than 2MB.
+ * This limit will be replaced with range invalidations, if supported by
+ * the hardware, when RISC-V IOMMU architecture specification update for
+ * range invalidations update will be available.
+ */
+#define RISCV_IOMMU_IOTLB_INVAL_LIMIT (2 << 20)
+
+static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
+ unsigned long start, unsigned long end)
+{
+ struct riscv_iommu_bond *bond;
+ struct riscv_iommu_device *iommu, *prev;
+ struct riscv_iommu_command cmd;
+ unsigned long len = end - start + 1;
+ unsigned long iova;
+
+ /*
+ * For each IOMMU linked with this protection domain (via bonds->dev),
+ * an IOTLB invaliation command will be submitted and executed.
+ *
+ * Possbile race with domain attach flow is handled by sequencing
+ * bond creation - riscv_iommu_bond_link(), and device directory
+ * update - riscv_iommu_iodir_update().
+ *
+ * PTE Update / IOTLB Inval Device attach & directory update
+ * -------------------------- --------------------------
+ * update page table entries add dev to the bond list
+ * FENCE RW,RW FENCE RW,RW
+ * For all IOMMUs: (can be empty) Update FSC/PSCID
+ * FENCE IOW,IOW FENCE IOW,IOW
+ * IOTLB.INVAL IODIR.INVAL
+ * IOFENCE.C
+ *
+ * If bond list is not updated with new device, directory context will
+ * be configured with already valid page table content. If an IOMMU is
+ * linked to the protection domain it will receive invalidation
+ * requests for updated page table entries.
+ */
+ smp_mb();
+
+ rcu_read_lock();
+
+ prev = NULL;
+ list_for_each_entry_rcu(bond, &domain->bonds, list) {
+ iommu = dev_to_iommu(bond->dev);
+
+ /*
+ * IOTLB invalidation request can be safely omitted if already sent
+ * to the IOMMU for the same PSCID, and with domain->bonds list
+ * arranged based on the device's IOMMU, it's sufficient to check
+ * last device the invalidation was sent to.
+ */
+ if (iommu == prev)
+ continue;
+
+ riscv_iommu_cmd_inval_vma(&cmd);
+ riscv_iommu_cmd_inval_set_pscid(&cmd, domain->pscid);
+ if (len && len < RISCV_IOMMU_IOTLB_INVAL_LIMIT) {
+ for (iova = start; iova < end; iova += PAGE_SIZE) {
+ riscv_iommu_cmd_inval_set_addr(&cmd, iova);
+ riscv_iommu_cmd_send(iommu, &cmd);
+ }
+ } else {
+ riscv_iommu_cmd_send(iommu, &cmd);
+ }
+ prev = iommu;
+ }
+
+ prev = NULL;
+ list_for_each_entry_rcu(bond, &domain->bonds, list) {
+ iommu = dev_to_iommu(bond->dev);
+ if (iommu == prev)
+ continue;
+
+ riscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);
+ prev = iommu;
+ }
+ rcu_read_unlock();
+}
+
+#define RISCV_IOMMU_FSC_BARE 0
+
+/*
+ * Update IODIR for the device.
+ *
+ * During the execution of riscv_iommu_probe_device(), IODIR entries are
+ * allocated for the device's identifiers. Device context invalidation
+ * becomes necessary only if one of the updated entries was previously
+ * marked as valid, given that invalid device context entries are not
+ * cached by the IOMMU hardware.
+ * In this implementation, updating a valid device context while the
+ * device is not quiesced might be disruptive, potentially causing
+ * interim translation faults.
+ */
+static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,
+ struct device *dev, u64 fsc, u64 ta)
+{
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct riscv_iommu_dc *dc;
+ struct riscv_iommu_command cmd;
+ bool sync_required = false;
+ u64 tc;
+ int i;
+
+ for (i = 0; i < fwspec->num_ids; i++) {
+ dc = riscv_iommu_get_dc(iommu, fwspec->ids[i]);
+ tc = READ_ONCE(dc->tc);
+ if (!(tc & RISCV_IOMMU_DC_TC_V))
+ continue;
+
+ WRITE_ONCE(dc->tc, tc & ~RISCV_IOMMU_DC_TC_V);
+
+ /* Invalidate device context cached values */
+ riscv_iommu_cmd_iodir_inval_ddt(&cmd);
+ riscv_iommu_cmd_iodir_set_did(&cmd, fwspec->ids[i]);
+ riscv_iommu_cmd_send(iommu, &cmd);
+ sync_required = true;
+ }
+
+ if (sync_required)
+ riscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);
+
+ /*
+ * For device context with DC_TC_PDTV = 0, translation attributes valid bit
+ * is stored as DC_TC_V bit (both sharing the same location at BIT(0)).
+ */
+ for (i = 0; i < fwspec->num_ids; i++) {
+ dc = riscv_iommu_get_dc(iommu, fwspec->ids[i]);
+ tc = READ_ONCE(dc->tc);
+ tc |= ta & RISCV_IOMMU_DC_TC_V;
+
+ WRITE_ONCE(dc->fsc, fsc);
+ WRITE_ONCE(dc->ta, ta & RISCV_IOMMU_PC_TA_PSCID);
+ /* Update device context, write TC.V as the last step. */
+ dma_wmb();
+ WRITE_ONCE(dc->tc, tc);
+
+ /* Invalidate device context after update */
+ riscv_iommu_cmd_iodir_inval_ddt(&cmd);
+ riscv_iommu_cmd_iodir_set_did(&cmd, fwspec->ids[i]);
+ riscv_iommu_cmd_send(iommu, &cmd);
+ }
+
+ riscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);
+}
+
+/*
+ * IOVA page translation tree management.
+ */
+
+static void riscv_iommu_iotlb_flush_all(struct iommu_domain *iommu_domain)
+{
+ struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
+
+ riscv_iommu_iotlb_inval(domain, 0, ULONG_MAX);
+}
+
+static void riscv_iommu_iotlb_sync(struct iommu_domain *iommu_domain,
+ struct iommu_iotlb_gather *gather)
+{
+ struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
+
+ riscv_iommu_iotlb_inval(domain, gather->start, gather->end);
+}
+
+#define PT_SHIFT (PAGE_SHIFT - ilog2(sizeof(pte_t)))
+
+#define _io_pte_present(pte) ((pte) & (_PAGE_PRESENT | _PAGE_PROT_NONE))
+#define _io_pte_leaf(pte) ((pte) & _PAGE_LEAF)
+#define _io_pte_none(pte) ((pte) == 0)
+#define _io_pte_entry(pn, prot) ((_PAGE_PFN_MASK & ((pn) << _PAGE_PFN_SHIFT)) | (prot))
+
+static void riscv_iommu_pte_free(struct riscv_iommu_domain *domain,
+ unsigned long pte, struct list_head *freelist)
+{
+ unsigned long *ptr;
+ int i;
+
+ if (!_io_pte_present(pte) || _io_pte_leaf(pte))
+ return;
+
+ ptr = (unsigned long *)pfn_to_virt(__page_val_to_pfn(pte));
+
+ /* Recursively free all sub page table pages */
+ for (i = 0; i < PTRS_PER_PTE; i++) {
+ pte = READ_ONCE(ptr[i]);
+ if (!_io_pte_none(pte) && cmpxchg_relaxed(ptr + i, pte, 0) == pte)
+ riscv_iommu_pte_free(domain, pte, freelist);
+ }
+
+ if (freelist)
+ list_add_tail(&virt_to_page(ptr)->lru, freelist);
+ else
+ iommu_free_page(ptr);
+}
+
+static unsigned long *riscv_iommu_pte_alloc(struct riscv_iommu_domain *domain,
+ unsigned long iova, size_t pgsize,
+ gfp_t gfp)
+{
+ unsigned long *ptr = domain->pgd_root;
+ unsigned long pte, old;
+ int level = domain->pgd_mode - RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39 + 2;
+ void *addr;
+
+ do {
+ const int shift = PAGE_SHIFT + PT_SHIFT * level;
+
+ ptr += ((iova >> shift) & (PTRS_PER_PTE - 1));
+ /*
+ * Note: returned entry might be a non-leaf if there was
+ * existing mapping with smaller granularity. Up to the caller
+ * to replace and invalidate.
+ */
+ if (((size_t)1 << shift) == pgsize)
+ return ptr;
+pte_retry:
+ pte = READ_ONCE(*ptr);
+ /*
+ * This is very likely incorrect as we should not be adding
+ * new mapping with smaller granularity on top
+ * of existing 2M/1G mapping. Fail.
+ */
+ if (_io_pte_present(pte) && _io_pte_leaf(pte))
+ return NULL;
+ /*
+ * Non-leaf entry is missing, allocate and try to add to the
+ * page table. This might race with other mappings, retry.
+ */
+ if (_io_pte_none(pte)) {
+ addr = iommu_alloc_page_node(domain->numa_node, gfp);
+ if (!addr)
+ return NULL;
+ old = pte;
+ pte = _io_pte_entry(virt_to_pfn(addr), _PAGE_TABLE);
+ if (cmpxchg_relaxed(ptr, old, pte) != old) {
+ iommu_free_page(addr);
+ goto pte_retry;
+ }
+ }
+ ptr = (unsigned long *)pfn_to_virt(__page_val_to_pfn(pte));
+ } while (level-- > 0);
+
+ return NULL;
+}
+
+static unsigned long *riscv_iommu_pte_fetch(struct riscv_iommu_domain *domain,
+ unsigned long iova, size_t *pte_pgsize)
+{
+ unsigned long *ptr = domain->pgd_root;
+ unsigned long pte;
+ int level = domain->pgd_mode - RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39 + 2;
+
+ do {
+ const int shift = PAGE_SHIFT + PT_SHIFT * level;
+
+ ptr += ((iova >> shift) & (PTRS_PER_PTE - 1));
+ pte = READ_ONCE(*ptr);
+ if (_io_pte_present(pte) && _io_pte_leaf(pte)) {
+ *pte_pgsize = (size_t)1 << shift;
+ return ptr;
+ }
+ if (_io_pte_none(pte))
+ return NULL;
+ ptr = (unsigned long *)pfn_to_virt(__page_val_to_pfn(pte));
+ } while (level-- > 0);
+
+ return NULL;
+}
+
+static int riscv_iommu_map_pages(struct iommu_domain *iommu_domain,
+ unsigned long iova, phys_addr_t phys,
+ size_t pgsize, size_t pgcount, int prot,
+ gfp_t gfp, size_t *mapped)
+{
+ struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
+ size_t size = 0;
+ unsigned long *ptr;
+ unsigned long pte, old, pte_prot;
+ int rc = 0;
+ LIST_HEAD(freelist);
+
+ if (!(prot & IOMMU_WRITE))
+ pte_prot = _PAGE_BASE | _PAGE_READ;
+ else if (domain->amo_enabled)
+ pte_prot = _PAGE_BASE | _PAGE_READ | _PAGE_WRITE;
+ else
+ pte_prot = _PAGE_BASE | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY;
+
+ while (pgcount) {
+ ptr = riscv_iommu_pte_alloc(domain, iova, pgsize, gfp);
+ if (!ptr) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ old = READ_ONCE(*ptr);
+ pte = _io_pte_entry(phys_to_pfn(phys), pte_prot);
+ if (cmpxchg_relaxed(ptr, old, pte) != old)
+ continue;
+
+ riscv_iommu_pte_free(domain, old, &freelist);
+
+ size += pgsize;
+ iova += pgsize;
+ phys += pgsize;
+ --pgcount;
+ }
+
+ *mapped = size;
+
+ if (!list_empty(&freelist)) {
+ /*
+ * In 1.0 spec version, the smallest scope we can use to
+ * invalidate all levels of page table (i.e. leaf and non-leaf)
+ * is an invalidate-all-PSCID IOTINVAL.VMA with AV=0.
+ * This will be updated with hardware support for
+ * capability.NL (non-leaf) IOTINVAL command.
+ */
+ riscv_iommu_iotlb_inval(domain, 0, ULONG_MAX);
+ iommu_put_pages_list(&freelist);
+ }
+
+ return rc;
+}
+
+static size_t riscv_iommu_unmap_pages(struct iommu_domain *iommu_domain,
+ unsigned long iova, size_t pgsize,
+ size_t pgcount,
+ struct iommu_iotlb_gather *gather)
+{
+ struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
+ size_t size = pgcount << __ffs(pgsize);
+ unsigned long *ptr, old;
+ size_t unmapped = 0;
+ size_t pte_size;
+
+ while (unmapped < size) {
+ ptr = riscv_iommu_pte_fetch(domain, iova, &pte_size);
+ if (!ptr)
+ return unmapped;
+
+ /* partial unmap is not allowed, fail. */
+ if (iova & (pte_size - 1))
+ return unmapped;
+
+ old = READ_ONCE(*ptr);
+ if (cmpxchg_relaxed(ptr, old, 0) != old)
+ continue;
+
+ iommu_iotlb_gather_add_page(&domain->domain, gather, iova,
+ pte_size);
+
+ iova += pte_size;
+ unmapped += pte_size;
+ }
+
+ return unmapped;
+}
+
+static phys_addr_t riscv_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
+ dma_addr_t iova)
+{
+ struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
+ unsigned long pte_size;
+ unsigned long *ptr;
+
+ ptr = riscv_iommu_pte_fetch(domain, iova, &pte_size);
+ if (_io_pte_none(*ptr) || !_io_pte_present(*ptr))
+ return 0;
+
+ return pfn_to_phys(__page_val_to_pfn(*ptr)) | (iova & (pte_size - 1));
+}
+
+static void riscv_iommu_free_paging_domain(struct iommu_domain *iommu_domain)
+{
+ struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
+ const unsigned long pfn = virt_to_pfn(domain->pgd_root);
+
+ WARN_ON(!list_empty(&domain->bonds));
+
+ if ((int)domain->pscid > 0)
+ ida_free(&riscv_iommu_pscids, domain->pscid);
+
+ riscv_iommu_pte_free(domain, _io_pte_entry(pfn, _PAGE_TABLE), NULL);
+ kfree(domain);
+}
+
+static bool riscv_iommu_pt_supported(struct riscv_iommu_device *iommu, int pgd_mode)
+{
+ switch (pgd_mode) {
+ case RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39;
+
+ case RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV48:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV48;
+
+ case RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV57:
+ return iommu->caps & RISCV_IOMMU_CAPABILITIES_SV57;
+ }
+ return false;
+}
+
+static int riscv_iommu_attach_paging_domain(struct iommu_domain *iommu_domain,
+ struct device *dev)
+{
+ struct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);
+ struct riscv_iommu_device *iommu = dev_to_iommu(dev);
+ struct riscv_iommu_info *info = dev_iommu_priv_get(dev);
+ u64 fsc, ta;
+
+ if (!riscv_iommu_pt_supported(iommu, domain->pgd_mode))
+ return -ENODEV;
+
+ fsc = FIELD_PREP(RISCV_IOMMU_PC_FSC_MODE, domain->pgd_mode) |
+ FIELD_PREP(RISCV_IOMMU_PC_FSC_PPN, virt_to_pfn(domain->pgd_root));
+ ta = FIELD_PREP(RISCV_IOMMU_PC_TA_PSCID, domain->pscid) |
+ RISCV_IOMMU_PC_TA_V;
+
+ if (riscv_iommu_bond_link(domain, dev))
+ return -ENOMEM;
+
+ riscv_iommu_iodir_update(iommu, dev, fsc, ta);
+ riscv_iommu_bond_unlink(info->domain, dev);
+ info->domain = domain;
+
+ return 0;
+}
+
+static const struct iommu_domain_ops riscv_iommu_paging_domain_ops = {
+ .attach_dev = riscv_iommu_attach_paging_domain,
+ .free = riscv_iommu_free_paging_domain,
+ .map_pages = riscv_iommu_map_pages,
+ .unmap_pages = riscv_iommu_unmap_pages,
+ .iova_to_phys = riscv_iommu_iova_to_phys,
+ .iotlb_sync = riscv_iommu_iotlb_sync,
+ .flush_iotlb_all = riscv_iommu_iotlb_flush_all,
+};
+
+static struct iommu_domain *riscv_iommu_alloc_paging_domain(struct device *dev)
+{
+ struct riscv_iommu_domain *domain;
+ struct riscv_iommu_device *iommu;
+ unsigned int pgd_mode;
+ dma_addr_t va_mask;
+ int va_bits;
+
+ iommu = dev_to_iommu(dev);
+ if (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV57) {
+ pgd_mode = RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV57;
+ va_bits = 57;
+ } else if (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV48) {
+ pgd_mode = RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV48;
+ va_bits = 48;
+ } else if (iommu->caps & RISCV_IOMMU_CAPABILITIES_SV39) {
+ pgd_mode = RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39;
+ va_bits = 39;
+ } else {
+ dev_err(dev, "cannot find supported page table mode\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD_RCU(&domain->bonds);
+ spin_lock_init(&domain->lock);
+ domain->numa_node = dev_to_node(iommu->dev);
+ domain->amo_enabled = !!(iommu->caps & RISCV_IOMMU_CAPABILITIES_AMO_HWAD);
+ domain->pgd_mode = pgd_mode;
+ domain->pgd_root = iommu_alloc_page_node(domain->numa_node,
+ GFP_KERNEL_ACCOUNT);
+ if (!domain->pgd_root) {
+ kfree(domain);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ domain->pscid = ida_alloc_range(&riscv_iommu_pscids, 1,
+ RISCV_IOMMU_MAX_PSCID, GFP_KERNEL);
+ if (domain->pscid < 0) {
+ iommu_free_page(domain->pgd_root);
+ kfree(domain);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /*
+ * Note: RISC-V Privilege spec mandates that virtual addresses
+ * need to be sign-extended, so if (VA_BITS - 1) is set, all
+ * bits >= VA_BITS need to also be set or else we'll get a
+ * page fault. However the code that creates the mappings
+ * above us (e.g. iommu_dma_alloc_iova()) won't do that for us
+ * for now, so we'll end up with invalid virtual addresses
+ * to map. As a workaround until we get this sorted out
+ * limit the available virtual addresses to VA_BITS - 1.
+ */
+ va_mask = DMA_BIT_MASK(va_bits - 1);
+
+ domain->domain.geometry.aperture_start = 0;
+ domain->domain.geometry.aperture_end = va_mask;
+ domain->domain.geometry.force_aperture = true;
+ domain->domain.pgsize_bitmap = va_mask & (SZ_4K | SZ_2M | SZ_1G | SZ_512G);
+
+ domain->domain.ops = &riscv_iommu_paging_domain_ops;
+
+ return &domain->domain;
+}
+
+static int riscv_iommu_attach_blocking_domain(struct iommu_domain *iommu_domain,
+ struct device *dev)
+{
+ struct riscv_iommu_device *iommu = dev_to_iommu(dev);
+ struct riscv_iommu_info *info = dev_iommu_priv_get(dev);
+
+ /* Make device context invalid, translation requests will fault w/ #258 */
+ riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, 0);
+ riscv_iommu_bond_unlink(info->domain, dev);
+ info->domain = NULL;
+
+ return 0;
+}
+
+static struct iommu_domain riscv_iommu_blocking_domain = {
+ .type = IOMMU_DOMAIN_BLOCKED,
+ .ops = &(const struct iommu_domain_ops) {
+ .attach_dev = riscv_iommu_attach_blocking_domain,
+ }
+};
+
+static int riscv_iommu_attach_identity_domain(struct iommu_domain *iommu_domain,
+ struct device *dev)
+{
+ struct riscv_iommu_device *iommu = dev_to_iommu(dev);
+ struct riscv_iommu_info *info = dev_iommu_priv_get(dev);
+
+ riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, RISCV_IOMMU_PC_TA_V);
+ riscv_iommu_bond_unlink(info->domain, dev);
+ info->domain = NULL;
+
+ return 0;
+}
+
+static struct iommu_domain riscv_iommu_identity_domain = {
+ .type = IOMMU_DOMAIN_IDENTITY,
+ .ops = &(const struct iommu_domain_ops) {
+ .attach_dev = riscv_iommu_attach_identity_domain,
+ }
+};
+
+static struct iommu_group *riscv_iommu_device_group(struct device *dev)
+{
+ if (dev_is_pci(dev))
+ return pci_device_group(dev);
+ return generic_device_group(dev);
+}
+
+static int riscv_iommu_of_xlate(struct device *dev, const struct of_phandle_args *args)
+{
+ return iommu_fwspec_add_ids(dev, args->args, 1);
+}
+
+static struct iommu_device *riscv_iommu_probe_device(struct device *dev)
+{
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct riscv_iommu_device *iommu;
+ struct riscv_iommu_info *info;
+ struct riscv_iommu_dc *dc;
+ u64 tc;
+ int i;
+
+ if (!fwspec || !fwspec->iommu_fwnode->dev || !fwspec->num_ids)
+ return ERR_PTR(-ENODEV);
+
+ iommu = dev_get_drvdata(fwspec->iommu_fwnode->dev);
+ if (!iommu)
+ return ERR_PTR(-ENODEV);
+
+ /*
+ * IOMMU hardware operating in fail-over BARE mode will provide
+ * identity translation for all connected devices anyway...
+ */
+ if (iommu->ddt_mode <= RISCV_IOMMU_DDTP_IOMMU_MODE_BARE)
+ return ERR_PTR(-ENODEV);
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+ /*
+ * Allocate and pre-configure device context entries in
+ * the device directory. Do not mark the context valid yet.
+ */
+ tc = 0;
+ if (iommu->caps & RISCV_IOMMU_CAPABILITIES_AMO_HWAD)
+ tc |= RISCV_IOMMU_DC_TC_SADE;
+ for (i = 0; i < fwspec->num_ids; i++) {
+ dc = riscv_iommu_get_dc(iommu, fwspec->ids[i]);
+ if (!dc) {
+ kfree(info);
+ return ERR_PTR(-ENODEV);
+ }
+ if (READ_ONCE(dc->tc) & RISCV_IOMMU_DC_TC_V)
+ dev_warn(dev, "already attached to IOMMU device directory\n");
+ WRITE_ONCE(dc->tc, tc);
+ }
+
+ dev_iommu_priv_set(dev, info);
+
+ return &iommu->iommu;
+}
+
+static void riscv_iommu_release_device(struct device *dev)
+{
+ struct riscv_iommu_info *info = dev_iommu_priv_get(dev);
+
+ kfree_rcu_mightsleep(info);
+}
+
+static const struct iommu_ops riscv_iommu_ops = {
+ .pgsize_bitmap = SZ_4K,
+ .of_xlate = riscv_iommu_of_xlate,
+ .identity_domain = &riscv_iommu_identity_domain,
+ .blocked_domain = &riscv_iommu_blocking_domain,
+ .release_domain = &riscv_iommu_blocking_domain,
+ .domain_alloc_paging = riscv_iommu_alloc_paging_domain,
+ .device_group = riscv_iommu_device_group,
+ .probe_device = riscv_iommu_probe_device,
+ .release_device = riscv_iommu_release_device,
+};
+
+static int riscv_iommu_init_check(struct riscv_iommu_device *iommu)
+{
+ u64 ddtp;
+
+ /*
+ * Make sure the IOMMU is switched off or in pass-through mode during
+ * regular boot flow and disable translation when we boot into a kexec
+ * kernel and the previous kernel left them enabled.
+ */
+ ddtp = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_DDTP);
+ if (ddtp & RISCV_IOMMU_DDTP_BUSY)
+ return -EBUSY;
+
+ if (FIELD_GET(RISCV_IOMMU_DDTP_IOMMU_MODE, ddtp) >
+ RISCV_IOMMU_DDTP_IOMMU_MODE_BARE) {
+ if (!is_kdump_kernel())
+ return -EBUSY;
+ riscv_iommu_disable(iommu);
+ }
+
+ /* Configure accesses to in-memory data structures for CPU-native byte order. */
+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) !=
+ !!(iommu->fctl & RISCV_IOMMU_FCTL_BE)) {
+ if (!(iommu->caps & RISCV_IOMMU_CAPABILITIES_END))
+ return -EINVAL;
+ riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FCTL,
+ iommu->fctl ^ RISCV_IOMMU_FCTL_BE);
+ iommu->fctl = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL);
+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) !=
+ !!(iommu->fctl & RISCV_IOMMU_FCTL_BE))
+ return -EINVAL;
+ }
+
+ /*
+ * Distribute interrupt vectors, always use first vector for CIV.
+ * At least one interrupt is required. Read back and verify.
+ */
+ if (!iommu->irqs_count)
+ return -EINVAL;
+
+ iommu->icvec = FIELD_PREP(RISCV_IOMMU_ICVEC_FIV, 1 % iommu->irqs_count) |
+ FIELD_PREP(RISCV_IOMMU_ICVEC_PIV, 2 % iommu->irqs_count) |
+ FIELD_PREP(RISCV_IOMMU_ICVEC_PMIV, 3 % iommu->irqs_count);
+ riscv_iommu_writeq(iommu, RISCV_IOMMU_REG_ICVEC, iommu->icvec);
+ iommu->icvec = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_ICVEC);
+ if (max(max(FIELD_GET(RISCV_IOMMU_ICVEC_CIV, iommu->icvec),
+ FIELD_GET(RISCV_IOMMU_ICVEC_FIV, iommu->icvec)),
+ max(FIELD_GET(RISCV_IOMMU_ICVEC_PIV, iommu->icvec),
+ FIELD_GET(RISCV_IOMMU_ICVEC_PMIV, iommu->icvec))) >= iommu->irqs_count)
+ return -EINVAL;
+
+ return 0;
+}
+
+void riscv_iommu_remove(struct riscv_iommu_device *iommu)
+{
+ iommu_device_unregister(&iommu->iommu);
+ iommu_device_sysfs_remove(&iommu->iommu);
+ riscv_iommu_iodir_set_mode(iommu, RISCV_IOMMU_DDTP_IOMMU_MODE_OFF);
+ riscv_iommu_queue_disable(&iommu->cmdq);
+ riscv_iommu_queue_disable(&iommu->fltq);
+}
+
+int riscv_iommu_init(struct riscv_iommu_device *iommu)
+{
+ int rc;
+
+ RISCV_IOMMU_QUEUE_INIT(&iommu->cmdq, CQ);
+ RISCV_IOMMU_QUEUE_INIT(&iommu->fltq, FQ);
+
+ rc = riscv_iommu_init_check(iommu);
+ if (rc)
+ return dev_err_probe(iommu->dev, rc, "unexpected device state\n");
+
+ rc = riscv_iommu_iodir_alloc(iommu);
+ if (rc)
+ return rc;
+
+ rc = riscv_iommu_queue_alloc(iommu, &iommu->cmdq,
+ sizeof(struct riscv_iommu_command));
+ if (rc)
+ return rc;
+
+ rc = riscv_iommu_queue_alloc(iommu, &iommu->fltq,
+ sizeof(struct riscv_iommu_fq_record));
+ if (rc)
+ return rc;
+
+ rc = riscv_iommu_queue_enable(iommu, &iommu->cmdq, riscv_iommu_cmdq_process);
+ if (rc)
+ return rc;
+
+ rc = riscv_iommu_queue_enable(iommu, &iommu->fltq, riscv_iommu_fltq_process);
+ if (rc)
+ goto err_queue_disable;
+
+ rc = riscv_iommu_iodir_set_mode(iommu, RISCV_IOMMU_DDTP_IOMMU_MODE_MAX);
+ if (rc)
+ goto err_queue_disable;
+
+ rc = iommu_device_sysfs_add(&iommu->iommu, NULL, NULL, "riscv-iommu@%s",
+ dev_name(iommu->dev));
+ if (rc) {
+ dev_err_probe(iommu->dev, rc, "cannot register sysfs interface\n");
+ goto err_iodir_off;
+ }
+
+ rc = iommu_device_register(&iommu->iommu, &riscv_iommu_ops, iommu->dev);
+ if (rc) {
+ dev_err_probe(iommu->dev, rc, "cannot register iommu interface\n");
+ goto err_remove_sysfs;
+ }
+
+ return 0;
+
+err_remove_sysfs:
+ iommu_device_sysfs_remove(&iommu->iommu);
+err_iodir_off:
+ riscv_iommu_iodir_set_mode(iommu, RISCV_IOMMU_DDTP_IOMMU_MODE_OFF);
+err_queue_disable:
+ riscv_iommu_queue_disable(&iommu->fltq);
+ riscv_iommu_queue_disable(&iommu->cmdq);
+ return rc;
+}
diff --git a/drivers/iommu/riscv/iommu.h b/drivers/iommu/riscv/iommu.h
new file mode 100644
index 000000000000..b1c4664542b4
--- /dev/null
+++ b/drivers/iommu/riscv/iommu.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2022-2024 Rivos Inc.
+ * Copyright © 2023 FORTH-ICS/CARV
+ *
+ * Authors
+ * Tomasz Jeznach <tjeznach@rivosinc.com>
+ * Nick Kossifidis <mick@ics.forth.gr>
+ */
+
+#ifndef _RISCV_IOMMU_H_
+#define _RISCV_IOMMU_H_
+
+#include <linux/iommu.h>
+#include <linux/types.h>
+#include <linux/iopoll.h>
+
+#include "iommu-bits.h"
+
+struct riscv_iommu_device;
+
+struct riscv_iommu_queue {
+ atomic_t prod; /* unbounded producer allocation index */
+ atomic_t head; /* unbounded shadow ring buffer consumer index */
+ atomic_t tail; /* unbounded shadow ring buffer producer index */
+ unsigned int mask; /* index mask, queue length - 1 */
+ unsigned int irq; /* allocated interrupt number */
+ struct riscv_iommu_device *iommu; /* iommu device handling the queue when active */
+ void *base; /* ring buffer kernel pointer */
+ dma_addr_t phys; /* ring buffer physical address */
+ u16 qbr; /* base register offset, head and tail reference */
+ u16 qcr; /* control and status register offset */
+ u8 qid; /* queue identifier, same as RISCV_IOMMU_INTR_XX */
+};
+
+struct riscv_iommu_device {
+ /* iommu core interface */
+ struct iommu_device iommu;
+
+ /* iommu hardware */
+ struct device *dev;
+
+ /* hardware control register space */
+ void __iomem *reg;
+
+ /* supported and enabled hardware capabilities */
+ u64 caps;
+ u32 fctl;
+
+ /* available interrupt numbers, MSI or WSI */
+ unsigned int irqs[RISCV_IOMMU_INTR_COUNT];
+ unsigned int irqs_count;
+ unsigned int icvec;
+
+ /* hardware queues */
+ struct riscv_iommu_queue cmdq;
+ struct riscv_iommu_queue fltq;
+
+ /* device directory */
+ unsigned int ddt_mode;
+ dma_addr_t ddt_phys;
+ u64 *ddt_root;
+};
+
+int riscv_iommu_init(struct riscv_iommu_device *iommu);
+void riscv_iommu_remove(struct riscv_iommu_device *iommu);
+
+#define riscv_iommu_readl(iommu, addr) \
+ readl_relaxed((iommu)->reg + (addr))
+
+#define riscv_iommu_readq(iommu, addr) \
+ readq_relaxed((iommu)->reg + (addr))
+
+#define riscv_iommu_writel(iommu, addr, val) \
+ writel_relaxed((val), (iommu)->reg + (addr))
+
+#define riscv_iommu_writeq(iommu, addr, val) \
+ writeq_relaxed((val), (iommu)->reg + (addr))
+
+#define riscv_iommu_readq_timeout(iommu, addr, val, cond, delay_us, timeout_us) \
+ readx_poll_timeout(readq_relaxed, (iommu)->reg + (addr), val, cond, \
+ delay_us, timeout_us)
+
+#define riscv_iommu_readl_timeout(iommu, addr, val, cond, delay_us, timeout_us) \
+ readx_poll_timeout(readl_relaxed, (iommu)->reg + (addr), val, cond, \
+ delay_us, timeout_us)
+
+#endif
diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
index d8eaa7ea380b..fbdeded3d48b 100644
--- a/drivers/iommu/s390-iommu.c
+++ b/drivers/iommu/s390-iommu.c
@@ -33,6 +33,8 @@ struct s390_domain {
struct rcu_head rcu;
};
+static struct iommu_domain blocking_domain;
+
static inline unsigned int calc_rtx(dma_addr_t ptr)
{
return ((unsigned long)ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK;
@@ -369,20 +371,36 @@ static void s390_domain_free(struct iommu_domain *domain)
call_rcu(&s390_domain->rcu, s390_iommu_rcu_free_domain);
}
-static void s390_iommu_detach_device(struct iommu_domain *domain,
- struct device *dev)
+static void zdev_s390_domain_update(struct zpci_dev *zdev,
+ struct iommu_domain *domain)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&zdev->dom_lock, flags);
+ zdev->s390_domain = domain;
+ spin_unlock_irqrestore(&zdev->dom_lock, flags);
+}
+
+static int blocking_domain_attach_device(struct iommu_domain *domain,
+ struct device *dev)
{
- struct s390_domain *s390_domain = to_s390_domain(domain);
struct zpci_dev *zdev = to_zpci_dev(dev);
+ struct s390_domain *s390_domain;
unsigned long flags;
+ if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED)
+ return 0;
+
+ s390_domain = to_s390_domain(zdev->s390_domain);
spin_lock_irqsave(&s390_domain->list_lock, flags);
list_del_rcu(&zdev->iommu_list);
spin_unlock_irqrestore(&s390_domain->list_lock, flags);
zpci_unregister_ioat(zdev, 0);
- zdev->s390_domain = NULL;
zdev->dma_table = NULL;
+ zdev_s390_domain_update(zdev, domain);
+
+ return 0;
}
static int s390_iommu_attach_device(struct iommu_domain *domain,
@@ -401,20 +419,15 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
domain->geometry.aperture_end < zdev->start_dma))
return -EINVAL;
- if (zdev->s390_domain)
- s390_iommu_detach_device(&zdev->s390_domain->domain, dev);
+ blocking_domain_attach_device(&blocking_domain, dev);
+ /* If we fail now DMA remains blocked via blocking domain */
cc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
virt_to_phys(s390_domain->dma_table), &status);
- /*
- * If the device is undergoing error recovery the reset code
- * will re-establish the new domain.
- */
if (cc && status != ZPCI_PCI_ST_FUNC_NOT_AVAIL)
return -EIO;
-
zdev->dma_table = s390_domain->dma_table;
- zdev->s390_domain = s390_domain;
+ zdev_s390_domain_update(zdev, domain);
spin_lock_irqsave(&s390_domain->list_lock, flags);
list_add_rcu(&zdev->iommu_list, &s390_domain->devices);
@@ -466,19 +479,11 @@ static struct iommu_device *s390_iommu_probe_device(struct device *dev)
if (zdev->tlb_refresh)
dev->iommu->shadow_on_flush = 1;
- return &zdev->iommu_dev;
-}
+ /* Start with DMA blocked */
+ spin_lock_init(&zdev->dom_lock);
+ zdev_s390_domain_update(zdev, &blocking_domain);
-static void s390_iommu_release_device(struct device *dev)
-{
- struct zpci_dev *zdev = to_zpci_dev(dev);
-
- /*
- * release_device is expected to detach any domain currently attached
- * to the device, but keep it attached to other devices in the group.
- */
- if (zdev)
- s390_iommu_detach_device(&zdev->s390_domain->domain, dev);
+ return &zdev->iommu_dev;
}
static int zpci_refresh_all(struct zpci_dev *zdev)
@@ -697,9 +702,15 @@ static size_t s390_iommu_unmap_pages(struct iommu_domain *domain,
struct zpci_iommu_ctrs *zpci_get_iommu_ctrs(struct zpci_dev *zdev)
{
- if (!zdev || !zdev->s390_domain)
+ struct s390_domain *s390_domain;
+
+ lockdep_assert_held(&zdev->dom_lock);
+
+ if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED)
return NULL;
- return &zdev->s390_domain->ctrs;
+
+ s390_domain = to_s390_domain(zdev->s390_domain);
+ return &s390_domain->ctrs;
}
int zpci_init_iommu(struct zpci_dev *zdev)
@@ -776,11 +787,19 @@ static int __init s390_iommu_init(void)
}
subsys_initcall(s390_iommu_init);
+static struct iommu_domain blocking_domain = {
+ .type = IOMMU_DOMAIN_BLOCKED,
+ .ops = &(const struct iommu_domain_ops) {
+ .attach_dev = blocking_domain_attach_device,
+ }
+};
+
static const struct iommu_ops s390_iommu_ops = {
+ .blocked_domain = &blocking_domain,
+ .release_domain = &blocking_domain,
.capable = s390_iommu_capable,
.domain_alloc_paging = s390_domain_alloc_paging,
.probe_device = s390_iommu_probe_device,
- .release_device = s390_iommu_release_device,
.device_group = generic_device_group,
.pgsize_bitmap = SZ_4K,
.get_resv_regions = s390_iommu_get_resv_regions,
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d82bcab233a1..55d7122121e2 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -258,6 +258,13 @@ config RENESAS_RZG2L_IRQC
Enable support for the Renesas RZ/G2L (and alike SoC) Interrupt Controller
for external devices.
+config RENESAS_RZV2H_ICU
+ bool "Renesas RZ/V2H(P) ICU support" if COMPILE_TEST
+ select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN_HIERARCHY
+ help
+ Enable support for the Renesas RZ/V2H(P) Interrupt Control Unit (ICU)
+
config SL28CPLD_INTC
bool "Kontron sl28cpld IRQ controller"
depends on MFD_SL28CPLD=y || COMPILE_TEST
@@ -338,6 +345,7 @@ config KEYSTONE_IRQ
config MIPS_GIC
bool
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
select GENERIC_IRQ_IPI if SMP
select IRQ_DOMAIN_HIERARCHY
select MIPS_CM
@@ -604,6 +612,18 @@ config STARFIVE_JH8100_INTC
If you don't know what to do here, say Y.
+config THEAD_C900_ACLINT_SSWI
+ bool "THEAD C9XX ACLINT S-mode IPI Interrupt Controller"
+ depends on RISCV
+ depends on SMP
+ select IRQ_DOMAIN_HIERARCHY
+ select GENERIC_IRQ_IPI_MUX
+ help
+ This enables support for T-HEAD specific ACLINT SSWI device
+ support.
+
+ If you don't know what to do here, say Y.
+
config EXYNOS_IRQ_COMBINER
bool "Samsung Exynos IRQ combiner support" if COMPILE_TEST
depends on (ARCH_EXYNOS && ARM) || COMPILE_TEST
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index e3679ec2b9f7..25e9ad29b8c4 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
obj-$(CONFIG_RENESAS_RZA1_IRQC) += irq-renesas-rza1.o
obj-$(CONFIG_RENESAS_RZG2L_IRQC) += irq-renesas-rzg2l.o
+obj-$(CONFIG_RENESAS_RZV2H_ICU) += irq-renesas-rzv2h.o
obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o
obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o
@@ -84,6 +85,7 @@ obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o
obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o
+obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-intc.o
obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o
@@ -101,6 +103,7 @@ obj-$(CONFIG_RISCV_APLIC_MSI) += irq-riscv-aplic-msi.o
obj-$(CONFIG_RISCV_IMSIC) += irq-riscv-imsic-state.o irq-riscv-imsic-early.o irq-riscv-imsic-platform.o
obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o
obj-$(CONFIG_STARFIVE_JH8100_INTC) += irq-starfive-jh8100-intc.o
+obj-$(CONFIG_THEAD_C900_ACLINT_SSWI) += irq-thead-c900-aclint-sswi.o
obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o
obj-$(CONFIG_IMX_INTMUX) += irq-imx-intmux.o
obj-$(CONFIG_IMX_MU_MSI) += irq-imx-mu-msi.o
diff --git a/drivers/irqchip/irq-aspeed-intc.c b/drivers/irqchip/irq-aspeed-intc.c
new file mode 100644
index 000000000000..bd3b759b4b2c
--- /dev/null
+++ b/drivers/irqchip/irq-aspeed-intc.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Aspeed Interrupt Controller.
+ *
+ * Copyright (C) 2023 ASPEED Technology Inc.
+ */
+
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#define INTC_INT_ENABLE_REG 0x00
+#define INTC_INT_STATUS_REG 0x04
+#define INTC_IRQS_PER_WORD 32
+
+struct aspeed_intc_ic {
+ void __iomem *base;
+ raw_spinlock_t gic_lock;
+ raw_spinlock_t intc_lock;
+ struct irq_domain *irq_domain;
+};
+
+static void aspeed_intc_ic_irq_handler(struct irq_desc *desc)
+{
+ struct aspeed_intc_ic *intc_ic = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
+
+ scoped_guard(raw_spinlock, &intc_ic->gic_lock) {
+ unsigned long bit, status;
+
+ status = readl(intc_ic->base + INTC_INT_STATUS_REG);
+ for_each_set_bit(bit, &status, INTC_IRQS_PER_WORD) {
+ generic_handle_domain_irq(intc_ic->irq_domain, bit);
+ writel(BIT(bit), intc_ic->base + INTC_INT_STATUS_REG);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void aspeed_intc_irq_mask(struct irq_data *data)
+{
+ struct aspeed_intc_ic *intc_ic = irq_data_get_irq_chip_data(data);
+ unsigned int mask = readl(intc_ic->base + INTC_INT_ENABLE_REG) & ~BIT(data->hwirq);
+
+ guard(raw_spinlock)(&intc_ic->intc_lock);
+ writel(mask, intc_ic->base + INTC_INT_ENABLE_REG);
+}
+
+static void aspeed_intc_irq_unmask(struct irq_data *data)
+{
+ struct aspeed_intc_ic *intc_ic = irq_data_get_irq_chip_data(data);
+ unsigned int unmask = readl(intc_ic->base + INTC_INT_ENABLE_REG) | BIT(data->hwirq);
+
+ guard(raw_spinlock)(&intc_ic->intc_lock);
+ writel(unmask, intc_ic->base + INTC_INT_ENABLE_REG);
+}
+
+static struct irq_chip aspeed_intc_chip = {
+ .name = "ASPEED INTC",
+ .irq_mask = aspeed_intc_irq_mask,
+ .irq_unmask = aspeed_intc_irq_unmask,
+};
+
+static int aspeed_intc_ic_map_irq_domain(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &aspeed_intc_chip, handle_level_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops aspeed_intc_ic_irq_domain_ops = {
+ .map = aspeed_intc_ic_map_irq_domain,
+};
+
+static int __init aspeed_intc_ic_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct aspeed_intc_ic *intc_ic;
+ int irq, i, ret = 0;
+
+ intc_ic = kzalloc(sizeof(*intc_ic), GFP_KERNEL);
+ if (!intc_ic)
+ return -ENOMEM;
+
+ intc_ic->base = of_iomap(node, 0);
+ if (!intc_ic->base) {
+ pr_err("Failed to iomap intc_ic base\n");
+ ret = -ENOMEM;
+ goto err_free_ic;
+ }
+ writel(0xffffffff, intc_ic->base + INTC_INT_STATUS_REG);
+ writel(0x0, intc_ic->base + INTC_INT_ENABLE_REG);
+
+ intc_ic->irq_domain = irq_domain_add_linear(node, INTC_IRQS_PER_WORD,
+ &aspeed_intc_ic_irq_domain_ops, intc_ic);
+ if (!intc_ic->irq_domain) {
+ ret = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ raw_spin_lock_init(&intc_ic->gic_lock);
+ raw_spin_lock_init(&intc_ic->intc_lock);
+
+ /* Check all the irq numbers valid. If not, unmaps all the base and frees the data. */
+ for (i = 0; i < of_irq_count(node); i++) {
+ irq = irq_of_parse_and_map(node, i);
+ if (!irq) {
+ pr_err("Failed to get irq number\n");
+ ret = -EINVAL;
+ goto err_iounmap;
+ }
+ }
+
+ for (i = 0; i < of_irq_count(node); i++) {
+ irq = irq_of_parse_and_map(node, i);
+ irq_set_chained_handler_and_data(irq, aspeed_intc_ic_irq_handler, intc_ic);
+ }
+
+ return 0;
+
+err_iounmap:
+ iounmap(intc_ic->base);
+err_free_ic:
+ kfree(intc_ic);
+ return ret;
+}
+
+IRQCHIP_DECLARE(ast2700_intc_ic, "aspeed,ast2700-intc-ic", aspeed_intc_ic_of_init);
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index c0f55dc7b050..e98c2875af9e 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -319,6 +319,7 @@ static const struct of_device_id aic5_irq_fixups[] __initconst = {
{ .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
{ .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup },
{ .compatible = "microchip,sam9x60", .data = sam9x60_aic_irq_fixup },
+ { .compatible = "microchip,sam9x7", .data = sam9x60_aic_irq_fixup },
{ /* sentinel */ },
};
@@ -405,3 +406,11 @@ static int __init sam9x60_aic5_of_init(struct device_node *node,
return aic5_of_init(node, parent, NR_SAM9X60_IRQS);
}
IRQCHIP_DECLARE(sam9x60_aic5, "microchip,sam9x60-aic", sam9x60_aic5_of_init);
+
+#define NR_SAM9X7_IRQS 70
+
+static int __init sam9x7_aic5_of_init(struct device_node *node, struct device_node *parent)
+{
+ return aic5_of_init(node, parent, NR_SAM9X7_IRQS);
+}
+IRQCHIP_DECLARE(sam9x7_aic5, "microchip,sam9x7-aic", sam9x7_aic5_of_init);
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 52f625e07658..92244cfa0464 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -12,12 +12,14 @@
#include <linux/crash_dump.h>
#include <linux/delay.h>
#include <linux/efi.h>
+#include <linux/genalloc.h>
#include <linux/interrupt.h>
#include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/irqdomain.h>
#include <linux/list.h>
#include <linux/log2.h>
+#include <linux/mem_encrypt.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/msi.h>
@@ -27,6 +29,7 @@
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/percpu.h>
+#include <linux/set_memory.h>
#include <linux/slab.h>
#include <linux/syscore_ops.h>
@@ -44,6 +47,7 @@
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
#define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3)
+#define ITS_FLAGS_WORKAROUND_HISILICON_162100801 (1ULL << 4)
#define RD_LOCAL_LPI_ENABLED BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
@@ -61,6 +65,7 @@ static u32 lpi_id_bits;
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
static u8 __ro_after_init lpi_prop_prio;
+static struct its_node *find_4_1_its(void);
/*
* Collection structure - just an ID, and a redistributor address to
@@ -164,6 +169,7 @@ struct its_device {
struct its_node *its;
struct event_lpi_map event_map;
void *itt;
+ u32 itt_sz;
u32 nr_ites;
u32 device_id;
bool shared;
@@ -199,6 +205,87 @@ static DEFINE_IDA(its_vpeid_ida);
#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
#define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K)
+static struct page *its_alloc_pages_node(int node, gfp_t gfp,
+ unsigned int order)
+{
+ struct page *page;
+ int ret = 0;
+
+ page = alloc_pages_node(node, gfp, order);
+
+ if (!page)
+ return NULL;
+
+ ret = set_memory_decrypted((unsigned long)page_address(page),
+ 1 << order);
+ /*
+ * If set_memory_decrypted() fails then we don't know what state the
+ * page is in, so we can't free it. Instead we leak it.
+ * set_memory_decrypted() will already have WARNed.
+ */
+ if (ret)
+ return NULL;
+
+ return page;
+}
+
+static struct page *its_alloc_pages(gfp_t gfp, unsigned int order)
+{
+ return its_alloc_pages_node(NUMA_NO_NODE, gfp, order);
+}
+
+static void its_free_pages(void *addr, unsigned int order)
+{
+ /*
+ * If the memory cannot be encrypted again then we must leak the pages.
+ * set_memory_encrypted() will already have WARNed.
+ */
+ if (set_memory_encrypted((unsigned long)addr, 1 << order))
+ return;
+ free_pages((unsigned long)addr, order);
+}
+
+static struct gen_pool *itt_pool;
+
+static void *itt_alloc_pool(int node, int size)
+{
+ unsigned long addr;
+ struct page *page;
+
+ if (size >= PAGE_SIZE) {
+ page = its_alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, get_order(size));
+
+ return page ? page_address(page) : NULL;
+ }
+
+ do {
+ addr = gen_pool_alloc(itt_pool, size);
+ if (addr)
+ break;
+
+ page = its_alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
+ if (!page)
+ break;
+
+ gen_pool_add(itt_pool, (unsigned long)page_address(page), PAGE_SIZE, node);
+ } while (!addr);
+
+ return (void *)addr;
+}
+
+static void itt_free_pool(void *addr, int size)
+{
+ if (!addr)
+ return;
+
+ if (size >= PAGE_SIZE) {
+ its_free_pages(addr, get_order(size));
+ return;
+ }
+
+ gen_pool_free(itt_pool, (unsigned long)addr, size);
+}
+
/*
* Skip ITSs that have no vLPIs mapped, unless we're on GICv4.1, as we
* always have vSGIs mapped.
@@ -621,7 +708,6 @@ static struct its_collection *its_build_mapd_cmd(struct its_node *its,
u8 size = ilog2(desc->its_mapd_cmd.dev->nr_ites);
itt_addr = virt_to_phys(desc->its_mapd_cmd.dev->itt);
- itt_addr = ALIGN(itt_addr, ITS_ITT_ALIGN);
its_encode_cmd(cmd, GITS_CMD_MAPD);
its_encode_devid(cmd, desc->its_mapd_cmd.dev->device_id);
@@ -2181,7 +2267,8 @@ static struct page *its_allocate_prop_table(gfp_t gfp_flags)
{
struct page *prop_page;
- prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ));
+ prop_page = its_alloc_pages(gfp_flags,
+ get_order(LPI_PROPBASE_SZ));
if (!prop_page)
return NULL;
@@ -2192,8 +2279,7 @@ static struct page *its_allocate_prop_table(gfp_t gfp_flags)
static void its_free_prop_table(struct page *prop_page)
{
- free_pages((unsigned long)page_address(prop_page),
- get_order(LPI_PROPBASE_SZ));
+ its_free_pages(page_address(prop_page), get_order(LPI_PROPBASE_SZ));
}
static bool gic_check_reserved_range(phys_addr_t addr, unsigned long size)
@@ -2315,7 +2401,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
order = get_order(GITS_BASER_PAGES_MAX * psz);
}
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order);
+ page = its_alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order);
if (!page)
return -ENOMEM;
@@ -2328,7 +2414,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
/* 52bit PA is supported only when PageSize=64K */
if (psz != SZ_64K) {
pr_err("ITS: no 52bit PA support when psz=%d\n", psz);
- free_pages((unsigned long)base, order);
+ its_free_pages(base, order);
return -ENXIO;
}
@@ -2384,7 +2470,7 @@ retry_baser:
pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n",
&its->phys_base, its_base_type_string[type],
val, tmp);
- free_pages((unsigned long)base, order);
+ its_free_pages(base, order);
return -ENXIO;
}
@@ -2523,8 +2609,7 @@ static void its_free_tables(struct its_node *its)
for (i = 0; i < GITS_BASER_NR_REGS; i++) {
if (its->tables[i].base) {
- free_pages((unsigned long)its->tables[i].base,
- its->tables[i].order);
+ its_free_pages(its->tables[i].base, its->tables[i].order);
its->tables[i].base = NULL;
}
}
@@ -2790,7 +2875,7 @@ static bool allocate_vpe_l2_table(int cpu, u32 id)
/* Allocate memory for 2nd level table */
if (!table[idx]) {
- page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(psz));
+ page = its_alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(psz));
if (!page)
return false;
@@ -2909,7 +2994,7 @@ static int allocate_vpe_l1_table(void)
pr_debug("np = %d, npg = %lld, psz = %d, epp = %d, esz = %d\n",
np, npg, psz, epp, esz);
- page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE));
+ page = its_alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE));
if (!page)
return -ENOMEM;
@@ -2955,8 +3040,7 @@ static struct page *its_allocate_pending_table(gfp_t gfp_flags)
{
struct page *pend_page;
- pend_page = alloc_pages(gfp_flags | __GFP_ZERO,
- get_order(LPI_PENDBASE_SZ));
+ pend_page = its_alloc_pages(gfp_flags | __GFP_ZERO, get_order(LPI_PENDBASE_SZ));
if (!pend_page)
return NULL;
@@ -2968,7 +3052,7 @@ static struct page *its_allocate_pending_table(gfp_t gfp_flags)
static void its_free_pending_table(struct page *pt)
{
- free_pages((unsigned long)page_address(pt), get_order(LPI_PENDBASE_SZ));
+ its_free_pages(page_address(pt), get_order(LPI_PENDBASE_SZ));
}
/*
@@ -3303,8 +3387,8 @@ static bool its_alloc_table_entry(struct its_node *its,
/* Allocate memory for 2nd level table */
if (!table[idx]) {
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
- get_order(baser->psz));
+ page = its_alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
+ get_order(baser->psz));
if (!page)
return false;
@@ -3399,15 +3483,18 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
if (WARN_ON(!is_power_of_2(nvecs)))
nvecs = roundup_pow_of_two(nvecs);
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
/*
* Even if the device wants a single LPI, the ITT must be
* sized as a power of two (and you need at least one bit...).
*/
nr_ites = max(2, nvecs);
sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
- sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
- itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
+ sz = max(sz, ITS_ITT_ALIGN);
+
+ itt = itt_alloc_pool(its->numa_node, sz);
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+
if (alloc_lpis) {
lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
if (lpi_map)
@@ -3419,9 +3506,9 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
lpi_base = 0;
}
- if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) {
+ if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) {
kfree(dev);
- kfree(itt);
+ itt_free_pool(itt, sz);
bitmap_free(lpi_map);
kfree(col_map);
return NULL;
@@ -3431,6 +3518,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
dev->its = its;
dev->itt = itt;
+ dev->itt_sz = sz;
dev->nr_ites = nr_ites;
dev->event_map.lpi_map = lpi_map;
dev->event_map.col_map = col_map;
@@ -3458,7 +3546,7 @@ static void its_free_device(struct its_device *its_dev)
list_del(&its_dev->entry);
raw_spin_unlock_irqrestore(&its_dev->its->lock, flags);
kfree(its_dev->event_map.col_map);
- kfree(its_dev->itt);
+ itt_free_pool(its_dev->itt, its_dev->itt_sz);
kfree(its_dev);
}
@@ -3797,6 +3885,20 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags);
}
+static void its_vpe_4_1_invall_locked(int cpu, struct its_vpe *vpe)
+{
+ void __iomem *rdbase;
+ u64 val;
+
+ val = GICR_INVALLR_V;
+ val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
+
+ guard(raw_spinlock)(&gic_data_rdist_cpu(cpu)->rd_lock);
+ rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
+ gic_write_lpir(val, rdbase + GICR_INVALLR);
+ wait_for_syncr(rdbase);
+}
+
static int its_vpe_set_affinity(struct irq_data *d,
const struct cpumask *mask_val,
bool force)
@@ -3804,6 +3906,7 @@ static int its_vpe_set_affinity(struct irq_data *d,
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
unsigned int from, cpu = nr_cpu_ids;
struct cpumask *table_mask;
+ struct its_node *its;
unsigned long flags;
/*
@@ -3866,6 +3969,11 @@ static int its_vpe_set_affinity(struct irq_data *d,
vpe->col_idx = cpu;
its_send_vmovp(vpe);
+
+ its = find_4_1_its();
+ if (its && its->flags & ITS_FLAGS_WORKAROUND_HISILICON_162100801)
+ its_vpe_4_1_invall_locked(cpu, vpe);
+
its_vpe_db_proxy_move(vpe, from, cpu);
out:
@@ -4173,22 +4281,12 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
static void its_vpe_4_1_invall(struct its_vpe *vpe)
{
- void __iomem *rdbase;
unsigned long flags;
- u64 val;
int cpu;
- val = GICR_INVALLR_V;
- val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
-
/* Target the redistributor this vPE is currently known on */
cpu = vpe_to_cpuid_lock(vpe, &flags);
- raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
- rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
- gic_write_lpir(val, rdbase + GICR_INVALLR);
-
- wait_for_syncr(rdbase);
- raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+ its_vpe_4_1_invall_locked(cpu, vpe);
vpe_to_cpuid_unlock(vpe, flags);
}
@@ -4781,6 +4879,14 @@ static bool its_set_non_coherent(void *data)
return true;
}
+static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
+{
+ struct its_node *its = data;
+
+ its->flags |= ITS_FLAGS_WORKAROUND_HISILICON_162100801;
+ return true;
+}
+
static const struct gic_quirk its_quirks[] = {
#ifdef CONFIG_CAVIUM_ERRATUM_22375
{
@@ -4827,6 +4933,14 @@ static const struct gic_quirk its_quirks[] = {
.init = its_enable_quirk_hip07_161600802,
},
#endif
+#ifdef CONFIG_HISILICON_ERRATUM_162100801
+ {
+ .desc = "ITS: Hip09 erratum 162100801",
+ .iidr = 0x00051736,
+ .mask = 0xffffffff,
+ .init = its_enable_quirk_hip09_162100801,
+ },
+#endif
#ifdef CONFIG_ROCKCHIP_ERRATUM_3588001
{
.desc = "ITS: Rockchip erratum RK3588001",
@@ -5132,8 +5246,9 @@ static int __init its_probe_one(struct its_node *its)
}
}
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
- get_order(ITS_CMD_QUEUE_SZ));
+ page = its_alloc_pages_node(its->numa_node,
+ GFP_KERNEL | __GFP_ZERO,
+ get_order(ITS_CMD_QUEUE_SZ));
if (!page) {
err = -ENOMEM;
goto out_unmap_sgir;
@@ -5197,7 +5312,7 @@ static int __init its_probe_one(struct its_node *its)
out_free_tables:
its_free_tables(its);
out_free_cmd:
- free_pages((unsigned long)its->cmd_base, get_order(ITS_CMD_QUEUE_SZ));
+ its_free_pages(its->cmd_base, get_order(ITS_CMD_QUEUE_SZ));
out_unmap_sgir:
if (its->sgir_base)
iounmap(its->sgir_base);
@@ -5683,6 +5798,10 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
bool has_v4_1 = false;
int err;
+ itt_pool = gen_pool_create(get_order(ITS_ITT_ALIGN), -1);
+ if (!itt_pool)
+ return -ENOMEM;
+
gic_rdists = rdists;
lpi_prop_prio = irq_prio;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index ce87205e3e82..8b6159f4cdaf 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -524,6 +524,13 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
}
gic_poke_irq(d, reg);
+
+ /*
+ * Force read-back to guarantee that the active state has taken
+ * effect, and won't race with a guest-driven deactivation.
+ */
+ if (reg == GICD_ISACTIVER)
+ gic_peek_irq(d, reg);
return 0;
}
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 3be7bd8cd8cd..8fae6dc01024 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -400,7 +400,7 @@ static void gic_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gic_chip_data *gic = irq_data_get_irq_chip_data(d);
if (gic->domain->pm_dev)
- seq_printf(p, gic->domain->pm_dev->of_node->name);
+ seq_puts(p, gic->domain->pm_dev->of_node->name);
else
seq_printf(p, "GIC-%d", (int)(gic - &gic_data[0]));
}
diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c
index b42ed68acfa6..85f80bac0961 100644
--- a/drivers/irqchip/irq-imgpdc.c
+++ b/drivers/irqchip/irq-imgpdc.c
@@ -479,7 +479,7 @@ static struct platform_driver pdc_intc_driver = {
.of_match_table = pdc_intc_match,
},
.probe = pdc_intc_probe,
- .remove_new = pdc_intc_remove,
+ .remove = pdc_intc_remove,
};
static int __init pdc_intc_init(void)
diff --git a/drivers/irqchip/irq-imx-intmux.c b/drivers/irqchip/irq-imx-intmux.c
index 511adfaeec82..787543d07565 100644
--- a/drivers/irqchip/irq-imx-intmux.c
+++ b/drivers/irqchip/irq-imx-intmux.c
@@ -361,6 +361,6 @@ static struct platform_driver imx_intmux_driver = {
.pm = &imx_intmux_pm_ops,
},
.probe = imx_intmux_probe,
- .remove_new = imx_intmux_remove,
+ .remove = imx_intmux_remove,
};
builtin_platform_driver(imx_intmux_driver);
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 75a0e980ff35..b0e9788c0045 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -328,6 +328,6 @@ static struct platform_driver imx_irqsteer_driver = {
.pm = &imx_irqsteer_pm_ops,
},
.probe = imx_irqsteer_probe,
- .remove_new = imx_irqsteer_remove,
+ .remove = imx_irqsteer_remove,
};
builtin_platform_driver(imx_irqsteer_driver);
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
index 30f1979fa124..808c781e2548 100644
--- a/drivers/irqchip/irq-keystone.c
+++ b/drivers/irqchip/irq-keystone.c
@@ -211,7 +211,7 @@ MODULE_DEVICE_TABLE(of, keystone_irq_dt_ids);
static struct platform_driver keystone_irq_device_driver = {
.probe = keystone_irq_probe,
- .remove_new = keystone_irq_remove,
+ .remove = keystone_irq_remove,
.driver = {
.name = "keystone_irq",
.of_match_table = of_match_ptr(keystone_irq_dt_ids),
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c
index e24db71a8783..bb79e19dfb59 100644
--- a/drivers/irqchip/irq-loongson-eiointc.c
+++ b/drivers/irqchip/irq-loongson-eiointc.c
@@ -14,6 +14,7 @@
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/kernel.h>
+#include <linux/kvm_para.h>
#include <linux/syscore_ops.h>
#include <asm/numa.h>
@@ -26,15 +27,37 @@
#define EIOINTC_REG_ISR 0x1800
#define EIOINTC_REG_ROUTE 0x1c00
+#define EXTIOI_VIRT_FEATURES 0x40000000
+#define EXTIOI_HAS_VIRT_EXTENSION BIT(0)
+#define EXTIOI_HAS_ENABLE_OPTION BIT(1)
+#define EXTIOI_HAS_INT_ENCODE BIT(2)
+#define EXTIOI_HAS_CPU_ENCODE BIT(3)
+#define EXTIOI_VIRT_CONFIG 0x40000004
+#define EXTIOI_ENABLE BIT(1)
+#define EXTIOI_ENABLE_INT_ENCODE BIT(2)
+#define EXTIOI_ENABLE_CPU_ENCODE BIT(3)
+
#define VEC_REG_COUNT 4
#define VEC_COUNT_PER_REG 64
#define VEC_COUNT (VEC_REG_COUNT * VEC_COUNT_PER_REG)
#define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG)
#define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG)
#define EIOINTC_ALL_ENABLE 0xffffffff
+#define EIOINTC_ALL_ENABLE_VEC_MASK(vector) (EIOINTC_ALL_ENABLE & ~BIT(vector & 0x1f))
+#define EIOINTC_REG_ENABLE_VEC(vector) (EIOINTC_REG_ENABLE + ((vector >> 5) << 2))
+#define EIOINTC_USE_CPU_ENCODE BIT(0)
#define MAX_EIO_NODES (NR_CPUS / CORES_PER_EIO_NODE)
+/*
+ * Routing registers are 32bit, and there is 8-bit route setting for every
+ * interrupt vector. So one Route register contains four vectors routing
+ * information.
+ */
+#define EIOINTC_REG_ROUTE_VEC(vector) (EIOINTC_REG_ROUTE + (vector & ~0x03))
+#define EIOINTC_REG_ROUTE_VEC_SHIFT(vector) ((vector & 0x03) << 3)
+#define EIOINTC_REG_ROUTE_VEC_MASK(vector) (0xff << EIOINTC_REG_ROUTE_VEC_SHIFT(vector))
+
static int nr_pics;
struct eiointc_priv {
@@ -44,6 +67,7 @@ struct eiointc_priv {
cpumask_t cpuspan_map;
struct fwnode_handle *domain_handle;
struct irq_domain *eiointc_domain;
+ int flags;
};
static struct eiointc_priv *eiointc_priv[MAX_IO_PICS];
@@ -59,7 +83,10 @@ static void eiointc_enable(void)
static int cpu_to_eio_node(int cpu)
{
- return cpu_logical_map(cpu) / CORES_PER_EIO_NODE;
+ if (!kvm_para_has_feature(KVM_FEATURE_VIRT_EXTIOI))
+ return cpu_logical_map(cpu) / CORES_PER_EIO_NODE;
+ else
+ return cpu_logical_map(cpu) / CORES_PER_VEIO_NODE;
}
#ifdef CONFIG_SMP
@@ -89,6 +116,17 @@ static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode,
}
}
+static void veiointc_set_irq_route(unsigned int vector, unsigned int cpu)
+{
+ unsigned long reg = EIOINTC_REG_ROUTE_VEC(vector);
+ unsigned int data;
+
+ data = iocsr_read32(reg);
+ data &= ~EIOINTC_REG_ROUTE_VEC_MASK(vector);
+ data |= cpu_logical_map(cpu) << EIOINTC_REG_ROUTE_VEC_SHIFT(vector);
+ iocsr_write32(data, reg);
+}
+
static DEFINE_RAW_SPINLOCK(affinity_lock);
static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, bool force)
@@ -107,18 +145,24 @@ static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *af
}
vector = d->hwirq;
- regaddr = EIOINTC_REG_ENABLE + ((vector >> 5) << 2);
-
- /* Mask target vector */
- csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)),
- 0x0, priv->node * CORES_PER_EIO_NODE);
-
- /* Set route for target vector */
- eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map);
-
- /* Unmask target vector */
- csr_any_send(regaddr, EIOINTC_ALL_ENABLE,
- 0x0, priv->node * CORES_PER_EIO_NODE);
+ regaddr = EIOINTC_REG_ENABLE_VEC(vector);
+
+ if (priv->flags & EIOINTC_USE_CPU_ENCODE) {
+ iocsr_write32(EIOINTC_ALL_ENABLE_VEC_MASK(vector), regaddr);
+ veiointc_set_irq_route(vector, cpu);
+ iocsr_write32(EIOINTC_ALL_ENABLE, regaddr);
+ } else {
+ /* Mask target vector */
+ csr_any_send(regaddr, EIOINTC_ALL_ENABLE_VEC_MASK(vector),
+ 0x0, priv->node * CORES_PER_EIO_NODE);
+
+ /* Set route for target vector */
+ eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map);
+
+ /* Unmask target vector */
+ csr_any_send(regaddr, EIOINTC_ALL_ENABLE,
+ 0x0, priv->node * CORES_PER_EIO_NODE);
+ }
irq_data_update_effective_affinity(d, cpumask_of(cpu));
@@ -142,17 +186,23 @@ static int eiointc_index(int node)
static int eiointc_router_init(unsigned int cpu)
{
- int i, bit;
- uint32_t data;
- uint32_t node = cpu_to_eio_node(cpu);
- int index = eiointc_index(node);
+ int i, bit, cores, index, node;
+ unsigned int data;
+
+ node = cpu_to_eio_node(cpu);
+ index = eiointc_index(node);
if (index < 0) {
pr_err("Error: invalid nodemap!\n");
- return -1;
+ return -EINVAL;
}
- if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) {
+ if (!(eiointc_priv[index]->flags & EIOINTC_USE_CPU_ENCODE))
+ cores = CORES_PER_EIO_NODE;
+ else
+ cores = CORES_PER_VEIO_NODE;
+
+ if ((cpu_logical_map(cpu) % cores) == 0) {
eiointc_enable();
for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) {
@@ -168,7 +218,9 @@ static int eiointc_router_init(unsigned int cpu)
for (i = 0; i < eiointc_priv[0]->vec_count / 4; i++) {
/* Route to Node-0 Core-0 */
- if (index == 0)
+ if (eiointc_priv[index]->flags & EIOINTC_USE_CPU_ENCODE)
+ bit = cpu_logical_map(0);
+ else if (index == 0)
bit = BIT(cpu_logical_map(0));
else
bit = (eiointc_priv[index]->node << 4) | 1;
@@ -375,7 +427,7 @@ static int __init acpi_cascade_irqdomain_init(void)
static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq,
u64 node_map)
{
- int i;
+ int i, val;
node_map = node_map ? node_map : -1ULL;
for_each_possible_cpu(i) {
@@ -395,6 +447,20 @@ static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq,
return -ENOMEM;
}
+ if (kvm_para_has_feature(KVM_FEATURE_VIRT_EXTIOI)) {
+ val = iocsr_read32(EXTIOI_VIRT_FEATURES);
+ /*
+ * With EXTIOI_ENABLE_CPU_ENCODE set
+ * interrupts can route to 256 vCPUs.
+ */
+ if (val & EXTIOI_HAS_CPU_ENCODE) {
+ val = iocsr_read32(EXTIOI_VIRT_CONFIG);
+ val |= EXTIOI_ENABLE_CPU_ENCODE;
+ iocsr_write32(val, EXTIOI_VIRT_CONFIG);
+ priv->flags = EIOINTC_USE_CPU_ENCODE;
+ }
+ }
+
eiointc_priv[nr_pics++] = priv;
eiointc_router_init(0);
irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 1aef5c4d27c6..c0e1aafe468c 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -418,7 +418,7 @@ static struct platform_driver ls_scfg_msi_driver = {
.of_match_table = ls_scfg_msi_id,
},
.probe = ls_scfg_msi_probe,
- .remove_new = ls_scfg_msi_remove,
+ .remove = ls_scfg_msi_remove,
};
module_platform_driver(ls_scfg_msi_driver);
diff --git a/drivers/irqchip/irq-madera.c b/drivers/irqchip/irq-madera.c
index acceb6e7fa95..b32982c11515 100644
--- a/drivers/irqchip/irq-madera.c
+++ b/drivers/irqchip/irq-madera.c
@@ -236,7 +236,7 @@ static void madera_irq_remove(struct platform_device *pdev)
static struct platform_driver madera_irq_driver = {
.probe = madera_irq_probe,
- .remove_new = madera_irq_remove,
+ .remove = madera_irq_remove,
.driver = {
.name = "madera-irq",
.pm = &madera_irq_pm_ops,
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 76253e864f23..bca8053864b2 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -66,6 +66,87 @@ static struct gic_all_vpes_chip_data {
bool mask;
} gic_all_vpes_chip_data[GIC_NUM_LOCAL_INTRS];
+static int __gic_with_next_online_cpu(int prev)
+{
+ unsigned int cpu;
+
+ /* Discover the next online CPU */
+ cpu = cpumask_next(prev, cpu_online_mask);
+
+ /* If there isn't one, we're done */
+ if (cpu >= nr_cpu_ids)
+ return cpu;
+
+ /*
+ * Move the access lock to the next CPU's GIC local register block.
+ *
+ * Set GIC_VL_OTHER. Since the caller holds gic_lock nothing can
+ * clobber the written value.
+ */
+ write_gic_vl_other(mips_cm_vp_id(cpu));
+
+ return cpu;
+}
+
+static inline void gic_unlock_cluster(void)
+{
+ if (mips_cps_multicluster_cpus())
+ mips_cm_unlock_other();
+}
+
+/**
+ * for_each_online_cpu_gic() - Iterate over online CPUs, access local registers
+ * @cpu: An integer variable to hold the current CPU number
+ * @gic_lock: A pointer to raw spin lock used as a guard
+ *
+ * Iterate over online CPUs & configure the other/redirect register region to
+ * access each CPUs GIC local register block, which can be accessed from the
+ * loop body using read_gic_vo_*() or write_gic_vo_*() accessor functions or
+ * their derivatives.
+ */
+#define for_each_online_cpu_gic(cpu, gic_lock) \
+ guard(raw_spinlock_irqsave)(gic_lock); \
+ for ((cpu) = __gic_with_next_online_cpu(-1); \
+ (cpu) < nr_cpu_ids; \
+ gic_unlock_cluster(), \
+ (cpu) = __gic_with_next_online_cpu(cpu))
+
+/**
+ * gic_irq_lock_cluster() - Lock redirect block access to IRQ's cluster
+ * @d: struct irq_data corresponding to the interrupt we're interested in
+ *
+ * Locks redirect register block access to the global register block of the GIC
+ * within the remote cluster that the IRQ corresponding to @d is affine to,
+ * returning true when this redirect block setup & locking has been performed.
+ *
+ * If @d is affine to the local cluster then no locking is performed and this
+ * function will return false, indicating to the caller that it should access
+ * the local clusters registers without the overhead of indirection through the
+ * redirect block.
+ *
+ * In summary, if this function returns true then the caller should access GIC
+ * registers using redirect register block accessors & then call
+ * mips_cm_unlock_other() when done. If this function returns false then the
+ * caller should trivially access GIC registers in the local cluster.
+ *
+ * Returns true if locking performed, else false.
+ */
+static bool gic_irq_lock_cluster(struct irq_data *d)
+{
+ unsigned int cpu, cl;
+
+ cpu = cpumask_first(irq_data_get_effective_affinity_mask(d));
+ BUG_ON(cpu >= NR_CPUS);
+
+ cl = cpu_cluster(&cpu_data[cpu]);
+ if (cl == cpu_cluster(&current_cpu_data))
+ return false;
+ if (mips_cps_numcores(cl) == 0)
+ return false;
+ mips_cm_lock_other(cl, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
+ return true;
+}
+
static void gic_clear_pcpu_masks(unsigned int intr)
{
unsigned int i;
@@ -112,7 +193,12 @@ static void gic_send_ipi(struct irq_data *d, unsigned int cpu)
{
irq_hw_number_t hwirq = GIC_HWIRQ_TO_SHARED(irqd_to_hwirq(d));
- write_gic_wedge(GIC_WEDGE_RW | hwirq);
+ if (gic_irq_lock_cluster(d)) {
+ write_gic_redir_wedge(GIC_WEDGE_RW | hwirq);
+ mips_cm_unlock_other();
+ } else {
+ write_gic_wedge(GIC_WEDGE_RW | hwirq);
+ }
}
int gic_get_c0_compare_int(void)
@@ -180,7 +266,13 @@ static void gic_mask_irq(struct irq_data *d)
{
unsigned int intr = GIC_HWIRQ_TO_SHARED(d->hwirq);
- write_gic_rmask(intr);
+ if (gic_irq_lock_cluster(d)) {
+ write_gic_redir_rmask(intr);
+ mips_cm_unlock_other();
+ } else {
+ write_gic_rmask(intr);
+ }
+
gic_clear_pcpu_masks(intr);
}
@@ -189,7 +281,12 @@ static void gic_unmask_irq(struct irq_data *d)
unsigned int intr = GIC_HWIRQ_TO_SHARED(d->hwirq);
unsigned int cpu;
- write_gic_smask(intr);
+ if (gic_irq_lock_cluster(d)) {
+ write_gic_redir_smask(intr);
+ mips_cm_unlock_other();
+ } else {
+ write_gic_smask(intr);
+ }
gic_clear_pcpu_masks(intr);
cpu = cpumask_first(irq_data_get_effective_affinity_mask(d));
@@ -200,7 +297,12 @@ static void gic_ack_irq(struct irq_data *d)
{
unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
- write_gic_wedge(irq);
+ if (gic_irq_lock_cluster(d)) {
+ write_gic_redir_wedge(irq);
+ mips_cm_unlock_other();
+ } else {
+ write_gic_wedge(irq);
+ }
}
static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -240,9 +342,16 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
break;
}
- change_gic_pol(irq, pol);
- change_gic_trig(irq, trig);
- change_gic_dual(irq, dual);
+ if (gic_irq_lock_cluster(d)) {
+ change_gic_redir_pol(irq, pol);
+ change_gic_redir_trig(irq, trig);
+ change_gic_redir_dual(irq, dual);
+ mips_cm_unlock_other();
+ } else {
+ change_gic_pol(irq, pol);
+ change_gic_trig(irq, trig);
+ change_gic_dual(irq, dual);
+ }
if (trig == GIC_TRIG_EDGE)
irq_set_chip_handler_name_locked(d, &gic_edge_irq_controller,
@@ -260,25 +369,72 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
bool force)
{
unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
+ unsigned int cpu, cl, old_cpu, old_cl;
unsigned long flags;
- unsigned int cpu;
+ /*
+ * The GIC specifies that we can only route an interrupt to one VP(E),
+ * ie. CPU in Linux parlance, at a time. Therefore we always route to
+ * the first online CPU in the mask.
+ */
cpu = cpumask_first_and(cpumask, cpu_online_mask);
if (cpu >= NR_CPUS)
return -EINVAL;
- /* Assumption : cpumask refers to a single CPU */
- raw_spin_lock_irqsave(&gic_lock, flags);
+ old_cpu = cpumask_first(irq_data_get_effective_affinity_mask(d));
+ old_cl = cpu_cluster(&cpu_data[old_cpu]);
+ cl = cpu_cluster(&cpu_data[cpu]);
- /* Re-route this IRQ */
- write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
+ raw_spin_lock_irqsave(&gic_lock, flags);
- /* Update the pcpu_masks */
- gic_clear_pcpu_masks(irq);
- if (read_gic_mask(irq))
- set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
+ /*
+ * If we're moving affinity between clusters, stop routing the
+ * interrupt to any VP(E) in the old cluster.
+ */
+ if (cl != old_cl) {
+ if (gic_irq_lock_cluster(d)) {
+ write_gic_redir_map_vp(irq, 0);
+ mips_cm_unlock_other();
+ } else {
+ write_gic_map_vp(irq, 0);
+ }
+ }
+ /*
+ * Update effective affinity - after this gic_irq_lock_cluster() will
+ * begin operating on the new cluster.
+ */
irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
+ /*
+ * If we're moving affinity between clusters, configure the interrupt
+ * trigger type in the new cluster.
+ */
+ if (cl != old_cl)
+ gic_set_type(d, irqd_get_trigger_type(d));
+
+ /* Route the interrupt to its new VP(E) */
+ if (gic_irq_lock_cluster(d)) {
+ write_gic_redir_map_pin(irq,
+ GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
+ write_gic_redir_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
+
+ /* Update the pcpu_masks */
+ gic_clear_pcpu_masks(irq);
+ if (read_gic_redir_mask(irq))
+ set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
+
+ mips_cm_unlock_other();
+ } else {
+ write_gic_map_pin(irq, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
+ write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
+
+ /* Update the pcpu_masks */
+ gic_clear_pcpu_masks(irq);
+ if (read_gic_mask(irq))
+ set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
+ }
+
raw_spin_unlock_irqrestore(&gic_lock, flags);
return IRQ_SET_MASK_OK;
@@ -350,37 +506,33 @@ static struct irq_chip gic_local_irq_controller = {
static void gic_mask_local_irq_all_vpes(struct irq_data *d)
{
struct gic_all_vpes_chip_data *cd;
- unsigned long flags;
int intr, cpu;
+ if (!mips_cps_multicluster_cpus())
+ return;
+
intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
cd = irq_data_get_irq_chip_data(d);
cd->mask = false;
- raw_spin_lock_irqsave(&gic_lock, flags);
- for_each_online_cpu(cpu) {
- write_gic_vl_other(mips_cm_vp_id(cpu));
+ for_each_online_cpu_gic(cpu, &gic_lock)
write_gic_vo_rmask(BIT(intr));
- }
- raw_spin_unlock_irqrestore(&gic_lock, flags);
}
static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
{
struct gic_all_vpes_chip_data *cd;
- unsigned long flags;
int intr, cpu;
+ if (!mips_cps_multicluster_cpus())
+ return;
+
intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
cd = irq_data_get_irq_chip_data(d);
cd->mask = true;
- raw_spin_lock_irqsave(&gic_lock, flags);
- for_each_online_cpu(cpu) {
- write_gic_vl_other(mips_cm_vp_id(cpu));
+ for_each_online_cpu_gic(cpu, &gic_lock)
write_gic_vo_smask(BIT(intr));
- }
- raw_spin_unlock_irqrestore(&gic_lock, flags);
}
static void gic_all_vpes_irq_cpu_online(void)
@@ -436,11 +588,21 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
unsigned long flags;
data = irq_get_irq_data(virq);
+ irq_data_update_effective_affinity(data, cpumask_of(cpu));
raw_spin_lock_irqsave(&gic_lock, flags);
- write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
- write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
- irq_data_update_effective_affinity(data, cpumask_of(cpu));
+
+ /* Route the interrupt to its VP(E) */
+ if (gic_irq_lock_cluster(data)) {
+ write_gic_redir_map_pin(intr,
+ GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
+ write_gic_redir_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
+ mips_cm_unlock_other();
+ } else {
+ write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
+ write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
+ }
+
raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0;
@@ -469,7 +631,6 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hwirq)
{
struct gic_all_vpes_chip_data *cd;
- unsigned long flags;
unsigned int intr;
int err, cpu;
u32 map;
@@ -533,12 +694,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
if (!gic_local_irq_is_routable(intr))
return -EPERM;
- raw_spin_lock_irqsave(&gic_lock, flags);
- for_each_online_cpu(cpu) {
- write_gic_vl_other(mips_cm_vp_id(cpu));
- write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
+ if (mips_cps_multicluster_cpus()) {
+ for_each_online_cpu_gic(cpu, &gic_lock)
+ write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
}
- raw_spin_unlock_irqrestore(&gic_lock, flags);
return 0;
}
@@ -621,6 +780,9 @@ static int gic_ipi_domain_alloc(struct irq_domain *d, unsigned int virq,
if (ret)
goto error;
+ /* Set affinity to cpu. */
+ irq_data_update_effective_affinity(irq_get_irq_data(virq + i),
+ cpumask_of(cpu));
ret = irq_set_irq_type(virq + i, IRQ_TYPE_EDGE_RISING);
if (ret)
goto error;
@@ -734,7 +896,7 @@ static int gic_cpu_startup(unsigned int cpu)
static int __init gic_of_init(struct device_node *node,
struct device_node *parent)
{
- unsigned int cpu_vec, i, gicconfig;
+ unsigned int cpu_vec, i, gicconfig, cl, nclusters;
unsigned long reserved;
phys_addr_t gic_base;
struct resource res;
@@ -815,11 +977,32 @@ static int __init gic_of_init(struct device_node *node,
board_bind_eic_interrupt = &gic_bind_eic_interrupt;
- /* Setup defaults */
- for (i = 0; i < gic_shared_intrs; i++) {
- change_gic_pol(i, GIC_POL_ACTIVE_HIGH);
- change_gic_trig(i, GIC_TRIG_LEVEL);
- write_gic_rmask(i);
+ /*
+ * Initialise each cluster's GIC shared registers to sane default
+ * values.
+ * Otherwise, the IPI set up will be erased if we move code
+ * to gic_cpu_startup for each cpu.
+ */
+ nclusters = mips_cps_numclusters();
+ for (cl = 0; cl < nclusters; cl++) {
+ if (cl == cpu_cluster(&current_cpu_data)) {
+ for (i = 0; i < gic_shared_intrs; i++) {
+ change_gic_pol(i, GIC_POL_ACTIVE_HIGH);
+ change_gic_trig(i, GIC_TRIG_LEVEL);
+ write_gic_rmask(i);
+ }
+ } else if (mips_cps_numcores(cl) != 0) {
+ mips_cm_lock_other(cl, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
+ for (i = 0; i < gic_shared_intrs; i++) {
+ change_gic_redir_pol(i, GIC_POL_ACTIVE_HIGH);
+ change_gic_redir_trig(i, GIC_TRIG_LEVEL);
+ write_gic_redir_rmask(i);
+ }
+ mips_cm_unlock_other();
+
+ } else {
+ pr_warn("No CPU cores on the cluster %d skip it\n", cl);
+ }
}
return cpuhp_setup_state(CPUHP_AP_IRQ_MIPS_GIC_STARTING,
diff --git a/drivers/irqchip/irq-mvebu-pic.c b/drivers/irqchip/irq-mvebu-pic.c
index 08b0cc862adf..3888b7585981 100644
--- a/drivers/irqchip/irq-mvebu-pic.c
+++ b/drivers/irqchip/irq-mvebu-pic.c
@@ -71,7 +71,7 @@ static void mvebu_pic_print_chip(struct irq_data *d, struct seq_file *p)
{
struct mvebu_pic *pic = irq_data_get_irq_chip_data(d);
- seq_printf(p, dev_name(&pic->pdev->dev));
+ seq_puts(p, dev_name(&pic->pdev->dev));
}
static const struct irq_chip mvebu_pic_chip = {
@@ -183,7 +183,7 @@ MODULE_DEVICE_TABLE(of, mvebu_pic_of_match);
static struct platform_driver mvebu_pic_driver = {
.probe = mvebu_pic_probe,
- .remove_new = mvebu_pic_remove,
+ .remove = mvebu_pic_remove,
.driver = {
.name = "mvebu-pic",
.of_match_table = mvebu_pic_of_match,
diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c
index f8c70f2d100a..065166ab5dbc 100644
--- a/drivers/irqchip/irq-mvebu-sei.c
+++ b/drivers/irqchip/irq-mvebu-sei.c
@@ -192,7 +192,6 @@ static void mvebu_sei_domain_free(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops mvebu_sei_domain_ops = {
- .select = msi_lib_irq_domain_select,
.alloc = mvebu_sei_domain_alloc,
.free = mvebu_sei_domain_free,
};
@@ -306,6 +305,7 @@ static void mvebu_sei_cp_domain_free(struct irq_domain *domain,
}
static const struct irq_domain_ops mvebu_sei_cp_domain_ops = {
+ .select = msi_lib_irq_domain_select,
.alloc = mvebu_sei_cp_domain_alloc,
.free = mvebu_sei_cp_domain_free,
};
diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
index 060eb000e9d3..bee01980b463 100644
--- a/drivers/irqchip/irq-pruss-intc.c
+++ b/drivers/irqchip/irq-pruss-intc.c
@@ -648,7 +648,7 @@ static struct platform_driver pruss_intc_driver = {
.suppress_bind_attrs = true,
},
.probe = pruss_intc_probe,
- .remove_new = pruss_intc_remove,
+ .remove = pruss_intc_remove,
};
module_platform_driver(pruss_intc_driver);
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 9ad37237ba95..954419f2460d 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -584,7 +584,7 @@ static SIMPLE_DEV_PM_OPS(intc_irqpin_pm_ops, intc_irqpin_suspend, NULL);
static struct platform_driver intc_irqpin_device_driver = {
.probe = intc_irqpin_probe,
- .remove_new = intc_irqpin_remove,
+ .remove = intc_irqpin_remove,
.driver = {
.name = "renesas_intc_irqpin",
.of_match_table = intc_irqpin_dt_ids,
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index 76026e0b8e20..cbce8ffc7de4 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -247,7 +247,7 @@ MODULE_DEVICE_TABLE(of, irqc_dt_ids);
static struct platform_driver irqc_device_driver = {
.probe = irqc_probe,
- .remove_new = irqc_remove,
+ .remove = irqc_remove,
.driver = {
.name = "renesas_irqc",
.of_match_table = irqc_dt_ids,
diff --git a/drivers/irqchip/irq-renesas-rza1.c b/drivers/irqchip/irq-renesas-rza1.c
index f05afe82db4d..d4e6a68889ec 100644
--- a/drivers/irqchip/irq-renesas-rza1.c
+++ b/drivers/irqchip/irq-renesas-rza1.c
@@ -259,7 +259,7 @@ MODULE_DEVICE_TABLE(of, rza1_irqc_dt_ids);
static struct platform_driver rza1_irqc_device_driver = {
.probe = rza1_irqc_probe,
- .remove_new = rza1_irqc_remove,
+ .remove = rza1_irqc_remove,
.driver = {
.name = "renesas_rza1_irqc",
.of_match_table = rza1_irqc_dt_ids,
diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c
new file mode 100644
index 000000000000..fe2d29e91026
--- /dev/null
+++ b/drivers/irqchip/irq-renesas-rzv2h.c
@@ -0,0 +1,513 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/V2H(P) ICU Driver
+ *
+ * Based on irq-renesas-rzg2l.c
+ *
+ * Copyright (C) 2024 Renesas Electronics Corporation.
+ *
+ * Author: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
+
+/* DT "interrupts" indexes */
+#define ICU_IRQ_START 1
+#define ICU_IRQ_COUNT 16
+#define ICU_TINT_START (ICU_IRQ_START + ICU_IRQ_COUNT)
+#define ICU_TINT_COUNT 32
+#define ICU_NUM_IRQ (ICU_TINT_START + ICU_TINT_COUNT)
+
+/* Registers */
+#define ICU_NSCNT 0x00
+#define ICU_NSCLR 0x04
+#define ICU_NITSR 0x08
+#define ICU_ISCTR 0x10
+#define ICU_ISCLR 0x14
+#define ICU_IITSR 0x18
+#define ICU_TSCTR 0x20
+#define ICU_TSCLR 0x24
+#define ICU_TITSR(k) (0x28 + (k) * 4)
+#define ICU_TSSR(k) (0x30 + (k) * 4)
+
+/* NMI */
+#define ICU_NMI_EDGE_FALLING 0
+#define ICU_NMI_EDGE_RISING 1
+
+#define ICU_NSCLR_NCLR BIT(0)
+
+/* IRQ */
+#define ICU_IRQ_LEVEL_LOW 0
+#define ICU_IRQ_EDGE_FALLING 1
+#define ICU_IRQ_EDGE_RISING 2
+#define ICU_IRQ_EDGE_BOTH 3
+
+#define ICU_IITSR_IITSEL_PREP(iitsel, n) ((iitsel) << ((n) * 2))
+#define ICU_IITSR_IITSEL_GET(iitsr, n) (((iitsr) >> ((n) * 2)) & 0x03)
+#define ICU_IITSR_IITSEL_MASK(n) ICU_IITSR_IITSEL_PREP(0x03, n)
+
+/* TINT */
+#define ICU_TINT_EDGE_RISING 0
+#define ICU_TINT_EDGE_FALLING 1
+#define ICU_TINT_LEVEL_HIGH 2
+#define ICU_TINT_LEVEL_LOW 3
+
+#define ICU_TSSR_K(tint_nr) ((tint_nr) / 4)
+#define ICU_TSSR_TSSEL_N(tint_nr) ((tint_nr) % 4)
+#define ICU_TSSR_TSSEL_PREP(tssel, n) ((tssel) << ((n) * 8))
+#define ICU_TSSR_TSSEL_MASK(n) ICU_TSSR_TSSEL_PREP(0x7F, n)
+#define ICU_TSSR_TIEN(n) (BIT(7) << ((n) * 8))
+
+#define ICU_TITSR_K(tint_nr) ((tint_nr) / 16)
+#define ICU_TITSR_TITSEL_N(tint_nr) ((tint_nr) % 16)
+#define ICU_TITSR_TITSEL_PREP(titsel, n) ICU_IITSR_IITSEL_PREP(titsel, n)
+#define ICU_TITSR_TITSEL_MASK(n) ICU_IITSR_IITSEL_MASK(n)
+#define ICU_TITSR_TITSEL_GET(titsr, n) ICU_IITSR_IITSEL_GET(titsr, n)
+
+#define ICU_TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
+#define ICU_TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
+#define ICU_PB5_TINT 0x55
+
+/**
+ * struct rzv2h_icu_priv - Interrupt Control Unit controller private data structure.
+ * @base: Controller's base address
+ * @irqchip: Pointer to struct irq_chip
+ * @fwspec: IRQ firmware specific data
+ * @lock: Lock to serialize access to hardware registers
+ */
+struct rzv2h_icu_priv {
+ void __iomem *base;
+ const struct irq_chip *irqchip;
+ struct irq_fwspec fwspec[ICU_NUM_IRQ];
+ raw_spinlock_t lock;
+};
+
+static inline struct rzv2h_icu_priv *irq_data_to_priv(struct irq_data *data)
+{
+ return data->domain->host_data;
+}
+
+static void rzv2h_icu_eoi(struct irq_data *d)
+{
+ struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
+ unsigned int hw_irq = irqd_to_hwirq(d);
+ unsigned int tintirq_nr;
+ u32 bit;
+
+ scoped_guard(raw_spinlock, &priv->lock) {
+ if (hw_irq >= ICU_TINT_START) {
+ tintirq_nr = hw_irq - ICU_TINT_START;
+ bit = BIT(tintirq_nr);
+ if (!irqd_is_level_type(d))
+ writel_relaxed(bit, priv->base + ICU_TSCLR);
+ } else if (hw_irq >= ICU_IRQ_START) {
+ tintirq_nr = hw_irq - ICU_IRQ_START;
+ bit = BIT(tintirq_nr);
+ if (!irqd_is_level_type(d))
+ writel_relaxed(bit, priv->base + ICU_ISCLR);
+ } else {
+ writel_relaxed(ICU_NSCLR_NCLR, priv->base + ICU_NSCLR);
+ }
+ }
+
+ irq_chip_eoi_parent(d);
+}
+
+static void rzv2h_tint_irq_endisable(struct irq_data *d, bool enable)
+{
+ struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
+ unsigned int hw_irq = irqd_to_hwirq(d);
+ u32 tint_nr, tssel_n, k, tssr;
+
+ if (hw_irq < ICU_TINT_START)
+ return;
+
+ tint_nr = hw_irq - ICU_TINT_START;
+ k = ICU_TSSR_K(tint_nr);
+ tssel_n = ICU_TSSR_TSSEL_N(tint_nr);
+
+ guard(raw_spinlock)(&priv->lock);
+ tssr = readl_relaxed(priv->base + ICU_TSSR(k));
+ if (enable)
+ tssr |= ICU_TSSR_TIEN(tssel_n);
+ else
+ tssr &= ~ICU_TSSR_TIEN(tssel_n);
+ writel_relaxed(tssr, priv->base + ICU_TSSR(k));
+}
+
+static void rzv2h_icu_irq_disable(struct irq_data *d)
+{
+ irq_chip_disable_parent(d);
+ rzv2h_tint_irq_endisable(d, false);
+}
+
+static void rzv2h_icu_irq_enable(struct irq_data *d)
+{
+ rzv2h_tint_irq_endisable(d, true);
+ irq_chip_enable_parent(d);
+}
+
+static int rzv2h_nmi_set_type(struct irq_data *d, unsigned int type)
+{
+ struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
+ u32 sense;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_FALLING:
+ sense = ICU_NMI_EDGE_FALLING;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ sense = ICU_NMI_EDGE_RISING;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ writel_relaxed(sense, priv->base + ICU_NITSR);
+
+ return 0;
+}
+
+static void rzv2h_clear_irq_int(struct rzv2h_icu_priv *priv, unsigned int hwirq)
+{
+ unsigned int irq_nr = hwirq - ICU_IRQ_START;
+ u32 isctr, iitsr, iitsel;
+ u32 bit = BIT(irq_nr);
+
+ isctr = readl_relaxed(priv->base + ICU_ISCTR);
+ iitsr = readl_relaxed(priv->base + ICU_IITSR);
+ iitsel = ICU_IITSR_IITSEL_GET(iitsr, irq_nr);
+
+ /*
+ * When level sensing is used, the interrupt flag gets automatically cleared when the
+ * interrupt signal is de-asserted by the source of the interrupt request, therefore clear
+ * the interrupt only for edge triggered interrupts.
+ */
+ if ((isctr & bit) && (iitsel != ICU_IRQ_LEVEL_LOW))
+ writel_relaxed(bit, priv->base + ICU_ISCLR);
+}
+
+static int rzv2h_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
+ unsigned int hwirq = irqd_to_hwirq(d);
+ u32 irq_nr = hwirq - ICU_IRQ_START;
+ u32 iitsr, sense;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_LEVEL_LOW:
+ sense = ICU_IRQ_LEVEL_LOW;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ sense = ICU_IRQ_EDGE_FALLING;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ sense = ICU_IRQ_EDGE_RISING;
+ break;
+
+ case IRQ_TYPE_EDGE_BOTH:
+ sense = ICU_IRQ_EDGE_BOTH;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ guard(raw_spinlock)(&priv->lock);
+ iitsr = readl_relaxed(priv->base + ICU_IITSR);
+ iitsr &= ~ICU_IITSR_IITSEL_MASK(irq_nr);
+ iitsr |= ICU_IITSR_IITSEL_PREP(sense, irq_nr);
+ rzv2h_clear_irq_int(priv, hwirq);
+ writel_relaxed(iitsr, priv->base + ICU_IITSR);
+
+ return 0;
+}
+
+static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq)
+{
+ unsigned int tint_nr = hwirq - ICU_TINT_START;
+ int titsel_n = ICU_TITSR_TITSEL_N(tint_nr);
+ u32 tsctr, titsr, titsel;
+ u32 bit = BIT(tint_nr);
+ int k = tint_nr / 16;
+
+ tsctr = readl_relaxed(priv->base + ICU_TSCTR);
+ titsr = readl_relaxed(priv->base + ICU_TITSR(k));
+ titsel = ICU_TITSR_TITSEL_GET(titsr, titsel_n);
+
+ /*
+ * Writing 1 to the corresponding flag from register ICU_TSCTR only has effect if
+ * TSTATn = 1b and if it's a rising edge or a falling edge interrupt.
+ */
+ if ((tsctr & bit) && ((titsel == ICU_TINT_EDGE_RISING) ||
+ (titsel == ICU_TINT_EDGE_FALLING)))
+ writel_relaxed(bit, priv->base + ICU_TSCLR);
+}
+
+static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
+{
+ u32 titsr, titsr_k, titsel_n, tien;
+ struct rzv2h_icu_priv *priv;
+ u32 tssr, tssr_k, tssel_n;
+ unsigned int hwirq;
+ u32 tint, sense;
+ int tint_nr;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_LEVEL_LOW:
+ sense = ICU_TINT_LEVEL_LOW;
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ sense = ICU_TINT_LEVEL_HIGH;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ sense = ICU_TINT_EDGE_RISING;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ sense = ICU_TINT_EDGE_FALLING;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d);
+ if (tint > ICU_PB5_TINT)
+ return -EINVAL;
+
+ priv = irq_data_to_priv(d);
+ hwirq = irqd_to_hwirq(d);
+
+ tint_nr = hwirq - ICU_TINT_START;
+
+ tssr_k = ICU_TSSR_K(tint_nr);
+ tssel_n = ICU_TSSR_TSSEL_N(tint_nr);
+
+ titsr_k = ICU_TITSR_K(tint_nr);
+ titsel_n = ICU_TITSR_TITSEL_N(tint_nr);
+ tien = ICU_TSSR_TIEN(titsel_n);
+
+ guard(raw_spinlock)(&priv->lock);
+
+ tssr = readl_relaxed(priv->base + ICU_TSSR(tssr_k));
+ tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n) | tien);
+ tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n);
+
+ writel_relaxed(tssr, priv->base + ICU_TSSR(tssr_k));
+
+ titsr = readl_relaxed(priv->base + ICU_TITSR(titsr_k));
+ titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n);
+ titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n);
+
+ writel_relaxed(titsr, priv->base + ICU_TITSR(titsr_k));
+
+ rzv2h_clear_tint_int(priv, hwirq);
+
+ writel_relaxed(tssr | tien, priv->base + ICU_TSSR(tssr_k));
+
+ return 0;
+}
+
+static int rzv2h_icu_set_type(struct irq_data *d, unsigned int type)
+{
+ unsigned int hw_irq = irqd_to_hwirq(d);
+ int ret;
+
+ if (hw_irq >= ICU_TINT_START)
+ ret = rzv2h_tint_set_type(d, type);
+ else if (hw_irq >= ICU_IRQ_START)
+ ret = rzv2h_irq_set_type(d, type);
+ else
+ ret = rzv2h_nmi_set_type(d, type);
+
+ if (ret)
+ return ret;
+
+ return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static const struct irq_chip rzv2h_icu_chip = {
+ .name = "rzv2h-icu",
+ .irq_eoi = rzv2h_icu_eoi,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_disable = rzv2h_icu_irq_disable,
+ .irq_enable = rzv2h_icu_irq_enable,
+ .irq_get_irqchip_state = irq_chip_get_parent_state,
+ .irq_set_irqchip_state = irq_chip_set_parent_state,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_set_type = rzv2h_icu_set_type,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
+static int rzv2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs,
+ void *arg)
+{
+ struct rzv2h_icu_priv *priv = domain->host_data;
+ unsigned long tint = 0;
+ irq_hw_number_t hwirq;
+ unsigned int type;
+ int ret;
+
+ ret = irq_domain_translate_twocell(domain, arg, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ /*
+ * For TINT interrupts the hwirq and TINT are encoded in
+ * fwspec->param[0].
+ * hwirq is embedded in bits 0-15.
+ * TINT is embedded in bits 16-31.
+ */
+ if (hwirq >= ICU_TINT_START) {
+ tint = ICU_TINT_EXTRACT_GPIOINT(hwirq);
+ hwirq = ICU_TINT_EXTRACT_HWIRQ(hwirq);
+
+ if (hwirq < ICU_TINT_START)
+ return -EINVAL;
+ }
+
+ if (hwirq > (ICU_NUM_IRQ - 1))
+ return -EINVAL;
+
+ ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, priv->irqchip,
+ (void *)(uintptr_t)tint);
+ if (ret)
+ return ret;
+
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]);
+}
+
+static const struct irq_domain_ops rzv2h_icu_domain_ops = {
+ .alloc = rzv2h_icu_alloc,
+ .free = irq_domain_free_irqs_common,
+ .translate = irq_domain_translate_twocell,
+};
+
+static int rzv2h_icu_parse_interrupts(struct rzv2h_icu_priv *priv, struct device_node *np)
+{
+ struct of_phandle_args map;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ICU_NUM_IRQ; i++) {
+ ret = of_irq_parse_one(np, i, &map);
+ if (ret)
+ return ret;
+
+ of_phandle_args_to_fwspec(np, map.args, map.args_count, &priv->fwspec[i]);
+ }
+
+ return 0;
+}
+
+static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
+{
+ struct irq_domain *irq_domain, *parent_domain;
+ struct rzv2h_icu_priv *rzv2h_icu_data;
+ struct platform_device *pdev;
+ struct reset_control *resetn;
+ int ret;
+
+ pdev = of_find_device_by_node(node);
+ if (!pdev)
+ return -ENODEV;
+
+ parent_domain = irq_find_host(parent);
+ if (!parent_domain) {
+ dev_err(&pdev->dev, "cannot find parent domain\n");
+ ret = -ENODEV;
+ goto put_dev;
+ }
+
+ rzv2h_icu_data = devm_kzalloc(&pdev->dev, sizeof(*rzv2h_icu_data), GFP_KERNEL);
+ if (!rzv2h_icu_data) {
+ ret = -ENOMEM;
+ goto put_dev;
+ }
+
+ rzv2h_icu_data->irqchip = &rzv2h_icu_chip;
+
+ rzv2h_icu_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
+ if (IS_ERR(rzv2h_icu_data->base)) {
+ ret = PTR_ERR(rzv2h_icu_data->base);
+ goto put_dev;
+ }
+
+ ret = rzv2h_icu_parse_interrupts(rzv2h_icu_data, node);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
+ goto put_dev;
+ }
+
+ resetn = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(resetn)) {
+ ret = PTR_ERR(resetn);
+ goto put_dev;
+ }
+
+ ret = reset_control_deassert(resetn);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to deassert resetn pin, %d\n", ret);
+ goto put_dev;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret);
+ goto pm_disable;
+ }
+
+ raw_spin_lock_init(&rzv2h_icu_data->lock);
+
+ irq_domain = irq_domain_add_hierarchy(parent_domain, 0, ICU_NUM_IRQ, node,
+ &rzv2h_icu_domain_ops, rzv2h_icu_data);
+ if (!irq_domain) {
+ dev_err(&pdev->dev, "failed to add irq domain\n");
+ ret = -ENOMEM;
+ goto pm_put;
+ }
+
+ /*
+ * coccicheck complains about a missing put_device call before returning, but it's a false
+ * positive. We still need &pdev->dev after successfully returning from this function.
+ */
+ return 0;
+
+pm_put:
+ pm_runtime_put(&pdev->dev);
+pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ reset_control_assert(resetn);
+put_dev:
+ put_device(&pdev->dev);
+
+ return ret;
+}
+
+IRQCHIP_PLATFORM_DRIVER_BEGIN(rzv2h_icu)
+IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_init)
+IRQCHIP_PLATFORM_DRIVER_END(rzv2h_icu)
+MODULE_AUTHOR("Fabrizio Castro <fabrizio.castro.jz@renesas.com>");
+MODULE_DESCRIPTION("Renesas RZ/V2H(P) ICU Driver");
diff --git a/drivers/irqchip/irq-riscv-aplic-main.c b/drivers/irqchip/irq-riscv-aplic-main.c
index 900e72541db9..93e7c51f944a 100644
--- a/drivers/irqchip/irq-riscv-aplic-main.c
+++ b/drivers/irqchip/irq-riscv-aplic-main.c
@@ -207,7 +207,8 @@ static int aplic_probe(struct platform_device *pdev)
else
rc = aplic_direct_setup(dev, regs);
if (rc)
- dev_err(dev, "failed to setup APLIC in %s mode\n", msi_mode ? "MSI" : "direct");
+ dev_err_probe(dev, rc, "failed to setup APLIC in %s mode\n",
+ msi_mode ? "MSI" : "direct");
#ifdef CONFIG_ACPI
if (!acpi_disabled)
diff --git a/drivers/irqchip/irq-riscv-aplic-msi.c b/drivers/irqchip/irq-riscv-aplic-msi.c
index 945bff28265c..fb8d1838609f 100644
--- a/drivers/irqchip/irq-riscv-aplic-msi.c
+++ b/drivers/irqchip/irq-riscv-aplic-msi.c
@@ -266,6 +266,9 @@ int aplic_msi_setup(struct device *dev, void __iomem *regs)
if (msi_domain)
dev_set_msi_domain(dev, msi_domain);
}
+
+ if (!dev_get_msi_domain(dev))
+ return -EPROBE_DEFER;
}
if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, &aplic_msi_template,
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 36dbcf2d728a..bf69a4802b71 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -252,11 +252,10 @@ static int plic_irq_suspend(void)
priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv;
- for (i = 0; i < priv->nr_irqs; i++)
- if (readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID))
- __set_bit(i, priv->prio_save);
- else
- __clear_bit(i, priv->prio_save);
+ for (i = 0; i < priv->nr_irqs; i++) {
+ __assign_bit(i, priv->prio_save,
+ readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID));
+ }
for_each_cpu(cpu, cpu_present_mask) {
struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
diff --git a/drivers/irqchip/irq-stm32mp-exti.c b/drivers/irqchip/irq-stm32mp-exti.c
index 33e0cfdea654..cb83d6cc6113 100644
--- a/drivers/irqchip/irq-stm32mp-exti.c
+++ b/drivers/irqchip/irq-stm32mp-exti.c
@@ -696,8 +696,7 @@ static int stm32mp_exti_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (of_property_read_bool(np, "interrupts-extended"))
- host_data->dt_has_irqs_desc = true;
+ host_data->dt_has_irqs_desc = of_property_present(np, "interrupts-extended");
return 0;
}
diff --git a/drivers/irqchip/irq-thead-c900-aclint-sswi.c b/drivers/irqchip/irq-thead-c900-aclint-sswi.c
new file mode 100644
index 000000000000..b0e366ade427
--- /dev/null
+++ b/drivers/irqchip/irq-thead-c900-aclint-sswi.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com>
+ */
+
+#define pr_fmt(fmt) "thead-c900-aclint-sswi: " fmt
+#include <linux/cpu.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/string_choices.h>
+#include <asm/sbi.h>
+#include <asm/vendorid_list.h>
+
+#define THEAD_ACLINT_xSWI_REGISTER_SIZE 4
+
+#define THEAD_C9XX_CSR_SXSTATUS 0x5c0
+#define THEAD_C9XX_SXSTATUS_CLINTEE BIT(17)
+
+static int sswi_ipi_virq __ro_after_init;
+static DEFINE_PER_CPU(void __iomem *, sswi_cpu_regs);
+
+static void thead_aclint_sswi_ipi_send(unsigned int cpu)
+{
+ writel_relaxed(0x1, per_cpu(sswi_cpu_regs, cpu));
+}
+
+static void thead_aclint_sswi_ipi_clear(void)
+{
+ writel_relaxed(0x0, this_cpu_read(sswi_cpu_regs));
+}
+
+static void thead_aclint_sswi_ipi_handle(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
+
+ csr_clear(CSR_IP, IE_SIE);
+ thead_aclint_sswi_ipi_clear();
+
+ ipi_mux_process();
+
+ chained_irq_exit(chip, desc);
+}
+
+static int thead_aclint_sswi_starting_cpu(unsigned int cpu)
+{
+ enable_percpu_irq(sswi_ipi_virq, irq_get_trigger_type(sswi_ipi_virq));
+
+ return 0;
+}
+
+static int thead_aclint_sswi_dying_cpu(unsigned int cpu)
+{
+ thead_aclint_sswi_ipi_clear();
+
+ disable_percpu_irq(sswi_ipi_virq);
+
+ return 0;
+}
+
+static int __init thead_aclint_sswi_parse_irq(struct fwnode_handle *fwnode,
+ void __iomem *reg)
+{
+ struct of_phandle_args parent;
+ unsigned long hartid;
+ u32 contexts, i;
+ int rc, cpu;
+
+ contexts = of_irq_count(to_of_node(fwnode));
+ if (!(contexts)) {
+ pr_err("%pfwP: no ACLINT SSWI context available\n", fwnode);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < contexts; i++) {
+ rc = of_irq_parse_one(to_of_node(fwnode), i, &parent);
+ if (rc)
+ return rc;
+
+ rc = riscv_of_parent_hartid(parent.np, &hartid);
+ if (rc)
+ return rc;
+
+ if (parent.args[0] != RV_IRQ_SOFT)
+ return -ENOTSUPP;
+
+ cpu = riscv_hartid_to_cpuid(hartid);
+
+ per_cpu(sswi_cpu_regs, cpu) = reg + i * THEAD_ACLINT_xSWI_REGISTER_SIZE;
+ }
+
+ pr_info("%pfwP: register %u CPU%s\n", fwnode, contexts, str_plural(contexts));
+
+ return 0;
+}
+
+static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode)
+{
+ struct irq_domain *domain;
+ void __iomem *reg;
+ int virq, rc;
+
+ /* If it is T-HEAD CPU, check whether SSWI is enabled */
+ if (riscv_cached_mvendorid(0) == THEAD_VENDOR_ID &&
+ !(csr_read(THEAD_C9XX_CSR_SXSTATUS) & THEAD_C9XX_SXSTATUS_CLINTEE))
+ return -ENOTSUPP;
+
+ if (!is_of_node(fwnode))
+ return -EINVAL;
+
+ reg = of_iomap(to_of_node(fwnode), 0);
+ if (!reg)
+ return -ENOMEM;
+
+ /* Parse SSWI setting */
+ rc = thead_aclint_sswi_parse_irq(fwnode, reg);
+ if (rc < 0)
+ return rc;
+
+ /* If mulitple SSWI devices are present, do not register irq again */
+ if (sswi_ipi_virq)
+ return 0;
+
+ /* Find riscv intc domain and create IPI irq mapping */
+ domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
+ if (!domain) {
+ pr_err("%pfwP: Failed to find INTC domain\n", fwnode);
+ return -ENOENT;
+ }
+
+ sswi_ipi_virq = irq_create_mapping(domain, RV_IRQ_SOFT);
+ if (!sswi_ipi_virq) {
+ pr_err("unable to create ACLINT SSWI IRQ mapping\n");
+ return -ENOMEM;
+ }
+
+ /* Register SSWI irq and handler */
+ virq = ipi_mux_create(BITS_PER_BYTE, thead_aclint_sswi_ipi_send);
+ if (virq <= 0) {
+ pr_err("unable to create muxed IPIs\n");
+ irq_dispose_mapping(sswi_ipi_virq);
+ return virq < 0 ? virq : -ENOMEM;
+ }
+
+ irq_set_chained_handler(sswi_ipi_virq, thead_aclint_sswi_ipi_handle);
+
+ cpuhp_setup_state(CPUHP_AP_IRQ_THEAD_ACLINT_SSWI_STARTING,
+ "irqchip/thead-aclint-sswi:starting",
+ thead_aclint_sswi_starting_cpu,
+ thead_aclint_sswi_dying_cpu);
+
+ riscv_ipi_set_virq_range(virq, BITS_PER_BYTE);
+
+ /* Announce that SSWI is providing IPIs */
+ pr_info("providing IPIs using THEAD ACLINT SSWI\n");
+
+ return 0;
+}
+
+static int __init thead_aclint_sswi_early_probe(struct device_node *node,
+ struct device_node *parent)
+{
+ return thead_aclint_sswi_probe(&node->fwnode);
+}
+IRQCHIP_DECLARE(thead_aclint_sswi, "thead,c900-aclint-sswi", thead_aclint_sswi_early_probe);
diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c
index b5dddb3c1568..cc219f28d317 100644
--- a/drivers/irqchip/irq-ts4800.c
+++ b/drivers/irqchip/irq-ts4800.c
@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(of, ts4800_ic_of_match);
static struct platform_driver ts4800_ic_driver = {
.probe = ts4800_ic_probe,
- .remove_new = ts4800_ic_remove,
+ .remove = ts4800_ic_remove,
.driver = {
.name = "ts4800-irqc",
.of_match_table = ts4800_ic_of_match,
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index ca471c6fee99..0abc8934c2ee 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -69,7 +69,7 @@ static void fpga_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
- seq_printf(p, irq_domain_get_of_node(f->domain)->name);
+ seq_puts(p, irq_domain_get_of_node(f->domain)->name);
}
static const struct irq_chip fpga_chip = {
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index e5a483fd9ad8..45ff0e198f8f 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -25,8 +25,8 @@
* Bit 8 = 0x00100 = uLaw (instead of aLaw)
* Bit 9 = 0x00200 = Disable DTMF detect on all B-channels via hardware
* Bit 10 = spare
- * Bit 11 = 0x00800 = Force PCM bus into slave mode. (otherwhise auto)
- * or Bit 12 = 0x01000 = Force PCM bus into master mode. (otherwhise auto)
+ * Bit 11 = 0x00800 = Force PCM bus into slave mode. (otherwise auto)
+ * or Bit 12 = 0x01000 = Force PCM bus into master mode. (otherwise auto)
* Bit 13 = spare
* Bit 14 = 0x04000 = Use external ram (128K)
* Bit 15 = 0x08000 = Use external ram (512K)
@@ -41,7 +41,7 @@
* port: (optional or required for all ports on all installed cards)
* HFC-4S/HFC-8S only bits:
* Bit 0 = 0x001 = Use master clock for this S/T interface
- * (ony once per chip).
+ * (only once per chip).
* Bit 1 = 0x002 = transmitter line setup (non capacitive mode)
* Don't use this unless you know what you are doing!
* Bit 2 = 0x004 = Disable E-channel. (No E-channel processing)
@@ -82,7 +82,7 @@
* By default (0), the PCM bus id is 100 for the card that is PCM master.
* If multiple cards are PCM master (because they are not interconnected),
* each card with PCM master will have increasing PCM id.
- * All PCM busses with the same ID are expected to be connected and have
+ * All PCM buses with the same ID are expected to be connected and have
* common time slots slots.
* Only one chip of the PCM bus must be master, the others slave.
* -1 means no support of PCM bus not even.
@@ -930,7 +930,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm)
if (newmaster) {
hc = newmaster;
if (debug & DEBUG_HFCMULTI_PLXSD)
- printk(KERN_DEBUG "id=%d (0x%p) = syncronized with "
+ printk(KERN_DEBUG "id=%d (0x%p) = synchronized with "
"interface.\n", hc->id, hc);
/* Enable new sync master */
plx_acc_32 = hc->plx_membase + PLX_GPIOC;
@@ -949,7 +949,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm)
hc = pcmmaster;
if (debug & DEBUG_HFCMULTI_PLXSD)
printk(KERN_DEBUG
- "id=%d (0x%p) = PCM master syncronized "
+ "id=%d (0x%p) = PCM master synchronized "
"with QUARTZ\n", hc->id, hc);
if (hc->ctype == HFC_TYPE_E1) {
/* Use the crystal clock for the PCM
@@ -2001,7 +2001,7 @@ next_frame:
if (Zspace <= 0)
Zspace += hc->Zlen;
Zspace -= 4; /* keep not too full, so pointers will not overrun */
- /* fill transparent data only to maxinum transparent load (minus 4) */
+ /* fill transparent data only to maximum transparent load (minus 4) */
if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
Zspace = Zspace - hc->Zlen + hc->max_trans;
if (Zspace <= 0) /* no space of 4 bytes */
@@ -4672,7 +4672,7 @@ init_e1_port_hw(struct hfc_multi *hc, struct hm_map *m)
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG
"%s: PORT set optical "
- "interfacs: card(%d) "
+ "interface: card(%d) "
"port(%d)\n",
__func__,
HFC_cnt + 1, 1);
diff --git a/drivers/leds/blink/leds-bcm63138.c b/drivers/leds/blink/leds-bcm63138.c
index 3a5e0b98bfbc..ef2e511438cc 100644
--- a/drivers/leds/blink/leds-bcm63138.c
+++ b/drivers/leds/blink/leds-bcm63138.c
@@ -2,6 +2,8 @@
/*
* Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
*/
+#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/leds.h>
@@ -19,8 +21,10 @@
#define BCM63138_LEDS_PER_REG (32 / BCM63138_LED_BITS) /* 8 */
#define BCM63138_GLB_CTRL 0x00
-#define BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL 0x00000002
-#define BCM63138_GLB_CTRL_SERIAL_LED_EN_POL 0x00000008
+#define BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL BIT(1)
+#define BCM63138_GLB_CTRL_SERIAL_LED_CLK_POL BIT(2)
+#define BCM63138_GLB_CTRL_SERIAL_LED_EN_POL BIT(3)
+#define BCM63138_GLB_CTRL_SERIAL_LED_MSB_FIRST BIT(4)
#define BCM63138_MASK 0x04
#define BCM63138_HW_LED_EN 0x08
#define BCM63138_SERIAL_LED_SHIFT_SEL 0x0c
@@ -33,6 +37,7 @@
#define BCM63138_BRIGHT_CTRL3 0x28
#define BCM63138_BRIGHT_CTRL4 0x2c
#define BCM63138_POWER_LED_CFG 0x30
+#define BCM63138_POWER_LUT_BASE0 0x34 /* -> b0 */
#define BCM63138_HW_POLARITY 0xb4
#define BCM63138_SW_DATA 0xb8
#define BCM63138_SW_POLARITY 0xbc
@@ -125,17 +130,14 @@ static void bcm63138_leds_brightness_set(struct led_classdev *led_cdev,
{
struct bcm63138_led *led = container_of(led_cdev, struct bcm63138_led, cdev);
struct bcm63138_leds *leds = led->leds;
- unsigned long flags;
- spin_lock_irqsave(&leds->lock, flags);
+ guard(spinlock_irqsave)(&leds->lock);
bcm63138_leds_enable_led(leds, led, value);
if (!value)
bcm63138_leds_set_flash_rate(leds, led, 0);
else
bcm63138_leds_set_bright(leds, led, value);
-
- spin_unlock_irqrestore(&leds->lock, flags);
}
static int bcm63138_leds_blink_set(struct led_classdev *led_cdev,
@@ -144,7 +146,6 @@ static int bcm63138_leds_blink_set(struct led_classdev *led_cdev,
{
struct bcm63138_led *led = container_of(led_cdev, struct bcm63138_led, cdev);
struct bcm63138_leds *leds = led->leds;
- unsigned long flags;
u8 value;
if (!*delay_on && !*delay_off) {
@@ -179,13 +180,11 @@ static int bcm63138_leds_blink_set(struct led_classdev *led_cdev,
return -EINVAL;
}
- spin_lock_irqsave(&leds->lock, flags);
+ guard(spinlock_irqsave)(&leds->lock);
bcm63138_leds_enable_led(leds, led, BCM63138_MAX_BRIGHTNESS);
bcm63138_leds_set_flash_rate(leds, led, value);
- spin_unlock_irqrestore(&leds->lock, flags);
-
return 0;
}
@@ -259,7 +258,7 @@ static int bcm63138_leds_probe(struct platform_device *pdev)
struct device_node *np = dev_of_node(&pdev->dev);
struct device *dev = &pdev->dev;
struct bcm63138_leds *leds;
- struct device_node *child;
+ u32 shift_bits;
leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL);
if (!leds)
@@ -273,6 +272,12 @@ static int bcm63138_leds_probe(struct platform_device *pdev)
spin_lock_init(&leds->lock);
+ /* If this property is not present, we use boot defaults */
+ if (!of_property_read_u32(np, "brcm,serial-shift-bits", &shift_bits)) {
+ bcm63138_leds_write(leds, BCM63138_SERIAL_LED_SHIFT_SEL,
+ GENMASK(shift_bits - 1, 0));
+ }
+
bcm63138_leds_write(leds, BCM63138_GLB_CTRL,
BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL |
BCM63138_GLB_CTRL_SERIAL_LED_EN_POL);
@@ -280,7 +285,7 @@ static int bcm63138_leds_probe(struct platform_device *pdev)
bcm63138_leds_write(leds, BCM63138_SERIAL_LED_POLARITY, 0);
bcm63138_leds_write(leds, BCM63138_PARALLEL_LED_POLARITY, 0);
- for_each_available_child_of_node(np, child) {
+ for_each_available_child_of_node_scoped(np, child) {
bcm63138_leds_create_led(leds, child);
}
diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c
index 7b04ea146260..effaaaf302b5 100644
--- a/drivers/leds/blink/leds-lgm-sso.c
+++ b/drivers/leds/blink/leds-lgm-sso.c
@@ -861,7 +861,7 @@ MODULE_DEVICE_TABLE(of, of_sso_led_match);
static struct platform_driver intel_sso_led_driver = {
.probe = intel_sso_led_probe,
- .remove_new = intel_sso_led_remove,
+ .remove = intel_sso_led_remove,
.driver = {
.name = "lgm-ssoled",
.of_match_table = of_sso_led_match,
diff --git a/drivers/leds/flash/leds-aat1290.c b/drivers/leds/flash/leds-aat1290.c
index c7b6a1f01288..49251cfd3350 100644
--- a/drivers/leds/flash/leds-aat1290.c
+++ b/drivers/leds/flash/leds-aat1290.c
@@ -536,7 +536,7 @@ MODULE_DEVICE_TABLE(of, aat1290_led_dt_match);
static struct platform_driver aat1290_led_driver = {
.probe = aat1290_led_probe,
- .remove_new = aat1290_led_remove,
+ .remove = aat1290_led_remove,
.driver = {
.name = "aat1290",
.of_match_table = aat1290_led_dt_match,
diff --git a/drivers/leds/flash/leds-ktd2692.c b/drivers/leds/flash/leds-ktd2692.c
index 16a01a200c0b..743830a10f99 100644
--- a/drivers/leds/flash/leds-ktd2692.c
+++ b/drivers/leds/flash/leds-ktd2692.c
@@ -292,6 +292,7 @@ static int ktd2692_probe(struct platform_device *pdev)
fled_cdev = &led->fled_cdev;
led_cdev = &fled_cdev->led_cdev;
+ led->props.timing = ktd2692_timing;
ret = ktd2692_parse_dt(led, &pdev->dev, &led_cfg);
if (ret)
@@ -343,7 +344,7 @@ static struct platform_driver ktd2692_driver = {
.of_match_table = ktd2692_match,
},
.probe = ktd2692_probe,
- .remove_new = ktd2692_remove,
+ .remove = ktd2692_remove,
};
module_platform_driver(ktd2692_driver);
diff --git a/drivers/leds/flash/leds-max77693.c b/drivers/leds/flash/leds-max77693.c
index 90d78b3d22f8..daee10986108 100644
--- a/drivers/leds/flash/leds-max77693.c
+++ b/drivers/leds/flash/leds-max77693.c
@@ -1042,7 +1042,7 @@ MODULE_DEVICE_TABLE(of, max77693_led_dt_match);
static struct platform_driver max77693_led_driver = {
.probe = max77693_led_probe,
- .remove_new = max77693_led_remove,
+ .remove = max77693_led_remove,
.driver = {
.name = "max77693-led",
.of_match_table = max77693_led_dt_match,
diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c
index 4c74f1cf01f0..462a902f54e0 100644
--- a/drivers/leds/flash/leds-mt6360.c
+++ b/drivers/leds/flash/leds-mt6360.c
@@ -784,7 +784,6 @@ static void mt6360_v4l2_flash_release(struct mt6360_priv *priv)
static int mt6360_led_probe(struct platform_device *pdev)
{
struct mt6360_priv *priv;
- struct fwnode_handle *child;
size_t count;
int i = 0, ret;
@@ -811,7 +810,7 @@ static int mt6360_led_probe(struct platform_device *pdev)
return -ENODEV;
}
- device_for_each_child_node(&pdev->dev, child) {
+ device_for_each_child_node_scoped(&pdev->dev, child) {
struct mt6360_led *led = priv->leds + i;
struct led_init_data init_data = { .fwnode = child, };
u32 reg, led_color;
@@ -887,7 +886,7 @@ static struct platform_driver mt6360_led_driver = {
.of_match_table = mt6360_led_of_id,
},
.probe = mt6360_led_probe,
- .remove_new = mt6360_led_remove,
+ .remove = mt6360_led_remove,
};
module_platform_driver(mt6360_led_driver);
diff --git a/drivers/leds/flash/leds-mt6370-flash.c b/drivers/leds/flash/leds-mt6370-flash.c
index 912d9d622320..dbdbe92309db 100644
--- a/drivers/leds/flash/leds-mt6370-flash.c
+++ b/drivers/leds/flash/leds-mt6370-flash.c
@@ -509,7 +509,6 @@ static int mt6370_led_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mt6370_priv *priv;
- struct fwnode_handle *child;
size_t count;
int i = 0, ret;
@@ -529,22 +528,18 @@ static int mt6370_led_probe(struct platform_device *pdev)
if (!priv->regmap)
return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n");
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct mt6370_led *led = priv->leds + i;
led->priv = priv;
ret = mt6370_init_flash_properties(dev, led, child);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
ret = mt6370_led_register(dev, led, child);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
i++;
}
diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c
index 41ce034f700e..b4c19be51c4d 100644
--- a/drivers/leds/flash/leds-qcom-flash.c
+++ b/drivers/leds/flash/leds-qcom-flash.c
@@ -812,7 +812,6 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
{
struct qcom_flash_data *flash_data;
struct qcom_flash_led *led;
- struct fwnode_handle *child;
struct device *dev = &pdev->dev;
struct regmap *regmap;
struct reg_field *regs;
@@ -896,7 +895,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
if (!flash_data->v4l2_flash)
return -ENOMEM;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
if (!led) {
rc = -ENOMEM;
@@ -914,7 +913,6 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
return 0;
release:
- fwnode_handle_put(child);
while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count)
v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]);
return rc;
@@ -942,7 +940,7 @@ static struct platform_driver qcom_flash_led_driver = {
.of_match_table = qcom_flash_led_match_table,
},
.probe = qcom_flash_led_probe,
- .remove_new = qcom_flash_led_remove,
+ .remove = qcom_flash_led_remove,
};
module_platform_driver(qcom_flash_led_driver);
diff --git a/drivers/leds/flash/leds-rt8515.c b/drivers/leds/flash/leds-rt8515.c
index eef426924eaf..6b051f182b72 100644
--- a/drivers/leds/flash/leds-rt8515.c
+++ b/drivers/leds/flash/leds-rt8515.c
@@ -388,7 +388,7 @@ static struct platform_driver rt8515_driver = {
.of_match_table = rt8515_match,
},
.probe = rt8515_probe,
- .remove_new = rt8515_remove,
+ .remove = rt8515_remove,
};
module_platform_driver(rt8515_driver);
diff --git a/drivers/leds/flash/leds-sgm3140.c b/drivers/leds/flash/leds-sgm3140.c
index db0ac6641954..3c01739c0b46 100644
--- a/drivers/leds/flash/leds-sgm3140.c
+++ b/drivers/leds/flash/leds-sgm3140.c
@@ -300,7 +300,7 @@ MODULE_DEVICE_TABLE(of, sgm3140_dt_match);
static struct platform_driver sgm3140_driver = {
.probe = sgm3140_probe,
- .remove_new = sgm3140_remove,
+ .remove = sgm3140_remove,
.driver = {
.name = "sgm3140",
.of_match_table = sgm3140_dt_match,
diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
index 6fe9d700dfef..f4e26ce84862 100644
--- a/drivers/leds/led-class-flash.c
+++ b/drivers/leds/led-class-flash.c
@@ -12,7 +12,6 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include "leds.h"
#define has_flash_op(fled_cdev, op) \
(fled_cdev && fled_cdev->ops->op)
diff --git a/drivers/leds/led-class-multicolor.c b/drivers/leds/led-class-multicolor.c
index 30c1ecb5f361..b2a87c994816 100644
--- a/drivers/leds/led-class-multicolor.c
+++ b/drivers/leds/led-class-multicolor.c
@@ -11,8 +11,6 @@
#include <linux/slab.h>
#include <linux/uaccess.h>
-#include "leds.h"
-
int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev,
enum led_brightness brightness)
{
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 06b97fd49ad9..2a04ac61574d 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -25,15 +25,20 @@
static DEFINE_MUTEX(leds_lookup_lock);
static LIST_HEAD(leds_lookup_list);
+static struct workqueue_struct *leds_wq;
+
static ssize_t brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ unsigned int brightness;
- /* no lock needed for this */
+ mutex_lock(&led_cdev->led_access);
led_update_brightness(led_cdev);
+ brightness = led_cdev->brightness;
+ mutex_unlock(&led_cdev->led_access);
- return sprintf(buf, "%u\n", led_cdev->brightness);
+ return sprintf(buf, "%u\n", brightness);
}
static ssize_t brightness_store(struct device *dev,
@@ -57,7 +62,6 @@ static ssize_t brightness_store(struct device *dev,
if (state == LED_OFF)
led_trigger_remove(led_cdev);
led_set_brightness(led_cdev, state);
- flush_work(&led_cdev->set_brightness_work);
ret = size;
unlock:
@@ -70,8 +74,13 @@ static ssize_t max_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ unsigned int max_brightness;
- return sprintf(buf, "%u\n", led_cdev->max_brightness);
+ mutex_lock(&led_cdev->led_access);
+ max_brightness = led_cdev->max_brightness;
+ mutex_unlock(&led_cdev->led_access);
+
+ return sprintf(buf, "%u\n", max_brightness);
}
static DEVICE_ATTR_RO(max_brightness);
@@ -549,6 +558,8 @@ int led_classdev_register_ext(struct device *parent,
led_update_brightness(led_cdev);
+ led_cdev->wq = leds_wq;
+
led_init_core(led_cdev);
#ifdef CONFIG_LEDS_TRIGGERS
@@ -667,12 +678,19 @@ EXPORT_SYMBOL_GPL(devm_led_classdev_unregister);
static int __init leds_init(void)
{
+ leds_wq = alloc_ordered_workqueue("leds", 0);
+ if (!leds_wq) {
+ pr_err("Failed to create LEDs ordered workqueue\n");
+ return -ENOMEM;
+ }
+
return class_register(&leds_class);
}
static void __exit leds_exit(void)
{
class_unregister(&leds_class);
+ destroy_workqueue(leds_wq);
}
subsys_initcall(leds_init);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 001c290bc07b..f6c46d2e5276 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -273,7 +273,7 @@ void led_blink_set_nosleep(struct led_classdev *led_cdev, unsigned long delay_on
led_cdev->delayed_delay_on = delay_on;
led_cdev->delayed_delay_off = delay_off;
set_bit(LED_SET_BLINK, &led_cdev->work_flags);
- schedule_work(&led_cdev->set_brightness_work);
+ queue_work(led_cdev->wq, &led_cdev->set_brightness_work);
return;
}
@@ -304,7 +304,7 @@ void led_set_brightness(struct led_classdev *led_cdev, unsigned int brightness)
*/
if (!brightness) {
set_bit(LED_BLINK_DISABLE, &led_cdev->work_flags);
- schedule_work(&led_cdev->set_brightness_work);
+ queue_work(led_cdev->wq, &led_cdev->set_brightness_work);
} else {
set_bit(LED_BLINK_BRIGHTNESS_CHANGE,
&led_cdev->work_flags);
@@ -340,7 +340,7 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int value)
set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags);
}
- schedule_work(&led_cdev->set_brightness_work);
+ queue_work(led_cdev->wq, &led_cdev->set_brightness_work);
}
EXPORT_SYMBOL_GPL(led_set_brightness_nopm);
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 81238376484b..ef5c6c4667ab 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -226,7 +226,7 @@ static struct platform_driver pm860x_led_driver = {
.name = "88pm860x-led",
},
.probe = pm860x_led_probe,
- .remove_new = pm860x_led_remove,
+ .remove = pm860x_led_remove,
};
module_platform_driver(pm860x_led_driver);
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index d89a4dca50ae..13e5bc80e56e 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -184,7 +184,7 @@ static struct platform_driver adp5520_led_driver = {
.name = "adp5520-led",
},
.probe = adp5520_led_probe,
- .remove_new = adp5520_led_remove,
+ .remove = adp5520_led_remove,
};
module_platform_driver(adp5520_led_driver);
diff --git a/drivers/leds/leds-aw200xx.c b/drivers/leds/leds-aw200xx.c
index f9d9844e0273..08cca128458c 100644
--- a/drivers/leds/leds-aw200xx.c
+++ b/drivers/leds/leds-aw200xx.c
@@ -409,7 +409,6 @@ static int aw200xx_probe_get_display_rows(struct device *dev,
static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip)
{
- struct fwnode_handle *child;
u32 current_min, current_max, min_uA;
int ret;
int i;
@@ -424,7 +423,7 @@ static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip)
min_uA = UINT_MAX;
i = 0;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct led_init_data init_data = {};
struct aw200xx_led *led;
u32 source, imax;
@@ -468,10 +467,8 @@ static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip)
ret = devm_led_classdev_register_ext(dev, &led->cdev,
&init_data);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
break;
- }
i++;
}
diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c
index 29f5bad61796..592bbf4b7e35 100644
--- a/drivers/leds/leds-bcm6328.c
+++ b/drivers/leds/leds-bcm6328.c
@@ -113,7 +113,7 @@ static void bcm6328_led_mode(struct bcm6328_led *led, unsigned long value)
unsigned long val, shift;
shift = bcm6328_pin2shift(led->pin);
- if (shift / 16)
+ if (shift >= 16)
mode = led->mem + BCM6328_REG_MODE_HI;
else
mode = led->mem + BCM6328_REG_MODE_LO;
@@ -357,7 +357,7 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
break;
case LEDS_DEFSTATE_KEEP:
shift = bcm6328_pin2shift(led->pin);
- if (shift / 16)
+ if (shift >= 16)
mode = mem + BCM6328_REG_MODE_HI;
else
mode = mem + BCM6328_REG_MODE_LO;
diff --git a/drivers/leds/leds-cht-wcove.c b/drivers/leds/leds-cht-wcove.c
index b4998402b8c6..8246f048edcb 100644
--- a/drivers/leds/leds-cht-wcove.c
+++ b/drivers/leds/leds-cht-wcove.c
@@ -461,7 +461,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cht_wc_leds_pm, cht_wc_leds_suspend, cht_wc_leds
static struct platform_driver cht_wc_leds_driver = {
.probe = cht_wc_leds_probe,
- .remove_new = cht_wc_leds_remove,
+ .remove = cht_wc_leds_remove,
.shutdown = cht_wc_leds_disable,
.driver = {
.name = "cht_wcove_leds",
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index 82da0fe688ad..f00b16ac1586 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -165,7 +165,7 @@ static void clevo_mail_led_remove(struct platform_device *pdev)
}
static struct platform_driver clevo_mail_led_driver = {
- .remove_new = clevo_mail_led_remove,
+ .remove = clevo_mail_led_remove,
.driver = {
.name = KBUILD_MODNAME,
},
diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c
index c9914fc51f20..7e51c374edd4 100644
--- a/drivers/leds/leds-cr0014114.c
+++ b/drivers/leds/leds-cr0014114.c
@@ -181,11 +181,10 @@ static int cr0014114_probe_dt(struct cr0014114 *priv)
{
size_t i = 0;
struct cr0014114_led *led;
- struct fwnode_handle *child;
struct led_init_data init_data = {};
int ret;
- device_for_each_child_node(priv->dev, child) {
+ device_for_each_child_node_scoped(priv->dev, child) {
led = &priv->leds[i];
led->priv = priv;
@@ -201,7 +200,6 @@ static int cr0014114_probe_dt(struct cr0014114 *priv)
if (ret) {
dev_err(priv->dev,
"failed to register LED device, err %d", ret);
- fwnode_handle_put(child);
return ret;
}
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index f067a5f4d3c4..71209b3c8f1e 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -133,7 +133,7 @@ static struct platform_driver da903x_led_driver = {
.name = "da903x-led",
},
.probe = da903x_led_probe,
- .remove_new = da903x_led_remove,
+ .remove = da903x_led_remove,
};
module_platform_driver(da903x_led_driver);
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
index 64679d62076b..7c9051184a59 100644
--- a/drivers/leds/leds-da9052.c
+++ b/drivers/leds/leds-da9052.c
@@ -179,7 +179,7 @@ static struct platform_driver da9052_led_driver = {
.name = "da9052-leds",
},
.probe = da9052_led_probe,
- .remove_new = da9052_led_remove,
+ .remove = da9052_led_remove,
};
module_platform_driver(da9052_led_driver);
diff --git a/drivers/leds/leds-el15203000.c b/drivers/leds/leds-el15203000.c
index d40194a3029f..e26d1654bd0d 100644
--- a/drivers/leds/leds-el15203000.c
+++ b/drivers/leds/leds-el15203000.c
@@ -237,22 +237,20 @@ static int el15203000_pattern_clear(struct led_classdev *ldev)
static int el15203000_probe_dt(struct el15203000 *priv)
{
struct el15203000_led *led = priv->leds;
- struct fwnode_handle *child;
int ret;
- device_for_each_child_node(priv->dev, child) {
+ device_for_each_child_node_scoped(priv->dev, child) {
struct led_init_data init_data = {};
ret = fwnode_property_read_u32(child, "reg", &led->reg);
if (ret) {
dev_err(priv->dev, "LED without ID number");
- goto err_child_out;
+ return ret;
}
if (led->reg > U8_MAX) {
dev_err(priv->dev, "LED value %d is invalid", led->reg);
- ret = -EINVAL;
- goto err_child_out;
+ return -EINVAL;
}
led->priv = priv;
@@ -274,17 +272,13 @@ static int el15203000_probe_dt(struct el15203000 *priv)
dev_err(priv->dev,
"failed to register LED device %s, err %d",
led->ldev.name, ret);
- goto err_child_out;
+ return ret;
}
led++;
}
return 0;
-
-err_child_out:
- fwnode_handle_put(child);
- return ret;
}
static int el15203000_probe(struct spi_device *spi)
diff --git a/drivers/leds/leds-gpio-register.c b/drivers/leds/leds-gpio-register.c
index de3f12c2b80d..ccc01fa72e6f 100644
--- a/drivers/leds/leds-gpio-register.c
+++ b/drivers/leds/leds-gpio-register.c
@@ -10,8 +10,8 @@
/**
* gpio_led_register_device - register a gpio-led device
- * @pdata: the platform data used for the new device
* @id: platform ID
+ * @pdata: the platform data used for the new device
*
* Makes a copy of pdata and pdata->leds and registers a new leds-gpio device
* with the result. This allows to have pdata and pdata-leds in .init.rodata
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 4d1612d557c8..a3428b22de3a 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -21,8 +21,6 @@
#include <linux/slab.h>
#include <linux/types.h>
-#include "leds.h"
-
struct gpio_led_data {
struct led_classdev cdev;
struct gpio_desc *gpiod;
@@ -148,7 +146,6 @@ struct gpio_leds_priv {
static struct gpio_leds_priv *gpio_leds_create(struct device *dev)
{
- struct fwnode_handle *child;
struct gpio_leds_priv *priv;
int count, used, ret;
@@ -162,7 +159,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev)
priv->num_leds = count;
used = 0;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct gpio_led_data *led_dat = &priv->leds[used];
struct gpio_led led = {};
@@ -176,7 +173,6 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev)
if (IS_ERR(led.gpiod)) {
dev_err_probe(dev, PTR_ERR(led.gpiod), "Failed to get GPIO '%pfw'\n",
child);
- fwnode_handle_put(child);
return ERR_CAST(led.gpiod);
}
@@ -192,10 +188,9 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev)
led.panic_indicator = 1;
ret = create_gpio_led(&led, led_dat, dev, child, NULL);
- if (ret < 0) {
- fwnode_handle_put(child);
+ if (ret < 0)
return ERR_PTR(ret);
- }
+
/* Set gpiod label to match the corresponding LED name. */
gpiod_set_consumer_name(led_dat->gpiod,
led_dat->cdev.dev->kobj.name);
@@ -217,7 +212,6 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
const struct gpio_led *template)
{
struct gpio_desc *gpiod;
- unsigned long flags = GPIOF_OUT_INIT_LOW;
int ret;
/*
@@ -244,10 +238,7 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
if (!gpio_is_valid(template->gpio))
return ERR_PTR(-ENOENT);
- if (template->active_low)
- flags |= GPIOF_ACTIVE_LOW;
-
- ret = devm_gpio_request_one(dev, template->gpio, flags,
+ ret = devm_gpio_request_one(dev, template->gpio, GPIOF_OUT_INIT_LOW,
template->name);
if (ret < 0)
return ERR_PTR(ret);
@@ -256,6 +247,9 @@ static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
if (!gpiod)
return ERR_PTR(-EINVAL);
+ if (template->active_low ^ gpiod_is_active_low(gpiod))
+ gpiod_toggle_active_low(gpiod);
+
return gpiod;
}
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
index 54b5650877f7..24dc8ad27bb3 100644
--- a/drivers/leds/leds-lm3532.c
+++ b/drivers/leds/leds-lm3532.c
@@ -551,7 +551,6 @@ static void gpio_set_low_action(void *data)
static int lm3532_parse_node(struct lm3532_data *priv)
{
- struct fwnode_handle *child = NULL;
struct lm3532_led *led;
int control_bank;
u32 ramp_time;
@@ -587,7 +586,7 @@ static int lm3532_parse_node(struct lm3532_data *priv)
else
priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time);
- device_for_each_child_node(priv->dev, child) {
+ device_for_each_child_node_scoped(priv->dev, child) {
struct led_init_data idata = {
.fwnode = child,
.default_label = ":",
@@ -599,7 +598,7 @@ static int lm3532_parse_node(struct lm3532_data *priv)
ret = fwnode_property_read_u32(child, "reg", &control_bank);
if (ret) {
dev_err(&priv->client->dev, "reg property missing\n");
- goto child_out;
+ return ret;
}
if (control_bank > LM3532_CONTROL_C) {
@@ -613,7 +612,7 @@ static int lm3532_parse_node(struct lm3532_data *priv)
&led->mode);
if (ret) {
dev_err(&priv->client->dev, "ti,led-mode property missing\n");
- goto child_out;
+ return ret;
}
if (fwnode_property_present(child, "led-max-microamp") &&
@@ -647,7 +646,7 @@ static int lm3532_parse_node(struct lm3532_data *priv)
led->num_leds);
if (ret) {
dev_err(&priv->client->dev, "led-sources property missing\n");
- goto child_out;
+ return ret;
}
led->priv = priv;
@@ -657,23 +656,20 @@ static int lm3532_parse_node(struct lm3532_data *priv)
if (ret) {
dev_err(&priv->client->dev, "led register err: %d\n",
ret);
- goto child_out;
+ return ret;
}
ret = lm3532_init_registers(led);
if (ret) {
dev_err(&priv->client->dev, "register init err: %d\n",
ret);
- goto child_out;
+ return ret;
}
i++;
}
- return 0;
-child_out:
- fwnode_handle_put(child);
- return ret;
+ return 0;
}
static int lm3532_probe(struct i2c_client *client)
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index a3d33165d262..45795f2a1042 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -744,7 +744,7 @@ static struct platform_driver lm3533_led_driver = {
.name = "lm3533-leds",
},
.probe = lm3533_led_probe,
- .remove_new = lm3533_led_remove,
+ .remove = lm3533_led_remove,
.shutdown = lm3533_led_shutdown,
};
module_platform_driver(lm3533_led_driver);
diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c
index 99de2a331727..7ad232780a31 100644
--- a/drivers/leds/leds-lm3697.c
+++ b/drivers/leds/leds-lm3697.c
@@ -202,7 +202,6 @@ out:
static int lm3697_probe_dt(struct lm3697 *priv)
{
- struct fwnode_handle *child = NULL;
struct device *dev = priv->dev;
struct lm3697_led *led;
int ret = -EINVAL;
@@ -220,19 +219,18 @@ static int lm3697_probe_dt(struct lm3697 *priv)
if (IS_ERR(priv->regulator))
priv->regulator = NULL;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct led_init_data init_data = {};
ret = fwnode_property_read_u32(child, "reg", &control_bank);
if (ret) {
dev_err(dev, "reg property missing\n");
- goto child_out;
+ return ret;
}
if (control_bank > LM3697_CONTROL_B) {
dev_err(dev, "reg property is invalid\n");
- ret = -EINVAL;
- goto child_out;
+ return -EINVAL;
}
led = &priv->leds[i];
@@ -262,7 +260,7 @@ static int lm3697_probe_dt(struct lm3697 *priv)
led->num_leds);
if (ret) {
dev_err(dev, "led-sources property missing\n");
- goto child_out;
+ return ret;
}
for (j = 0; j < led->num_leds; j++)
@@ -286,17 +284,13 @@ static int lm3697_probe_dt(struct lm3697 *priv)
&init_data);
if (ret) {
dev_err(dev, "led register err: %d\n", ret);
- goto child_out;
+ return ret;
}
i++;
}
- return ret;
-
-child_out:
- fwnode_handle_put(child);
- return ret;
+ return 0;
}
static int lm3697_probe(struct i2c_client *client)
diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
index 175d4b06659b..02cb1565a9fb 100644
--- a/drivers/leds/leds-lp50xx.c
+++ b/drivers/leds/leds-lp50xx.c
@@ -16,8 +16,6 @@
#include <linux/led-class-multicolor.h>
-#include "leds.h"
-
#define LP50XX_DEV_CFG0 0x00
#define LP50XX_DEV_CFG1 0x01
#define LP50XX_LED_CFG0 0x02
@@ -434,7 +432,6 @@ static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
static int lp50xx_probe_dt(struct lp50xx *priv)
{
- struct fwnode_handle *child = NULL;
struct fwnode_handle *led_node = NULL;
struct led_init_data init_data = {};
struct led_classdev *led_cdev;
@@ -454,17 +451,17 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
if (IS_ERR(priv->regulator))
priv->regulator = NULL;
- device_for_each_child_node(priv->dev, child) {
+ device_for_each_child_node_scoped(priv->dev, child) {
led = &priv->leds[i];
ret = fwnode_property_count_u32(child, "reg");
if (ret < 0) {
dev_err(priv->dev, "reg property is invalid\n");
- goto child_out;
+ return ret;
}
ret = lp50xx_probe_leds(child, priv, led, ret);
if (ret)
- goto child_out;
+ return ret;
init_data.fwnode = child;
num_colors = 0;
@@ -475,10 +472,8 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
*/
mc_led_info = devm_kcalloc(priv->dev, LP50XX_LEDS_PER_MODULE,
sizeof(*mc_led_info), GFP_KERNEL);
- if (!mc_led_info) {
- ret = -ENOMEM;
- goto child_out;
- }
+ if (!mc_led_info)
+ return -ENOMEM;
fwnode_for_each_child_node(child, led_node) {
ret = fwnode_property_read_u32(led_node, "color",
@@ -486,7 +481,7 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
if (ret) {
fwnode_handle_put(led_node);
dev_err(priv->dev, "Cannot read color\n");
- goto child_out;
+ return ret;
}
mc_led_info[num_colors].color_index = color_id;
@@ -504,16 +499,12 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
&init_data);
if (ret) {
dev_err(priv->dev, "led register err: %d\n", ret);
- goto child_out;
+ return ret;
}
i++;
}
return 0;
-
-child_out:
- fwnode_handle_put(child);
- return ret;
}
static int lp50xx_probe(struct i2c_client *client)
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index b26bcc81d079..14a4af361b26 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -161,6 +161,30 @@ static int lp5562_post_init_device(struct lp55xx_chip *chip)
return 0;
}
+static int lp5562_multicolor_brightness(struct lp55xx_led *led)
+{
+ struct lp55xx_chip *chip = led->chip;
+ static const u8 addr[] = {
+ LP5562_REG_R_PWM,
+ LP5562_REG_G_PWM,
+ LP5562_REG_B_PWM,
+ LP5562_REG_W_PWM,
+ };
+ int ret;
+ int i;
+
+ guard(mutex)(&chip->lock);
+ for (i = 0; i < led->mc_cdev.num_colors; i++) {
+ ret = lp55xx_write(chip,
+ addr[led->mc_cdev.subled_info[i].channel],
+ led->mc_cdev.subled_info[i].brightness);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
static int lp5562_led_brightness(struct lp55xx_led *led)
{
struct lp55xx_chip *chip = led->chip;
@@ -364,6 +388,7 @@ static struct lp55xx_device_config lp5562_cfg = {
.post_init_device = lp5562_post_init_device,
.set_led_current = lp5562_set_led_current,
.brightness_fn = lp5562_led_brightness,
+ .multicolor_brightness_fn = lp5562_multicolor_brightness,
.run_engine = lp5562_run_engine,
.firmware_cb = lp55xx_firmware_loaded_cb,
.dev_attr_group = &lp5562_group,
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 5a2e259679cf..e71456a56ab8 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -1132,9 +1132,6 @@ static int lp55xx_parse_common_child(struct device_node *np,
if (ret)
return ret;
- if (*chan_nr < 0 || *chan_nr > cfg->max_channel)
- return -EINVAL;
-
return 0;
}
diff --git a/drivers/leds/leds-max5970.c b/drivers/leds/leds-max5970.c
index 56a584311581..285074c53b23 100644
--- a/drivers/leds/leds-max5970.c
+++ b/drivers/leds/leds-max5970.c
@@ -45,7 +45,7 @@ static int max5970_led_set_brightness(struct led_classdev *cdev,
static int max5970_led_probe(struct platform_device *pdev)
{
- struct fwnode_handle *led_node, *child;
+ struct fwnode_handle *child;
struct device *dev = &pdev->dev;
struct regmap *regmap;
struct max5970_led *ddata;
@@ -55,7 +55,8 @@ static int max5970_led_probe(struct platform_device *pdev)
if (!regmap)
return -ENODEV;
- led_node = device_get_named_child_node(dev->parent, "leds");
+ struct fwnode_handle *led_node __free(fwnode_handle) =
+ device_get_named_child_node(dev->parent, "leds");
if (!led_node)
return -ENODEV;
diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c
index 1eeac56b0014..f8c47078a3bb 100644
--- a/drivers/leds/leds-max77650.c
+++ b/drivers/leds/leds-max77650.c
@@ -62,7 +62,6 @@ static int max77650_led_brightness_set(struct led_classdev *cdev,
static int max77650_led_probe(struct platform_device *pdev)
{
- struct fwnode_handle *child;
struct max77650_led *leds, *led;
struct device *dev;
struct regmap *map;
@@ -84,14 +83,12 @@ static int max77650_led_probe(struct platform_device *pdev)
if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS)
return -ENODEV;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct led_init_data init_data = {};
rv = fwnode_property_read_u32(child, "reg", &reg);
- if (rv || reg >= MAX77650_LED_NUM_LEDS) {
- rv = -EINVAL;
- goto err_node_put;
- }
+ if (rv || reg >= MAX77650_LED_NUM_LEDS)
+ return -EINVAL;
led = &leds[reg];
led->map = map;
@@ -108,23 +105,20 @@ static int max77650_led_probe(struct platform_device *pdev)
rv = devm_led_classdev_register_ext(dev, &led->cdev,
&init_data);
if (rv)
- goto err_node_put;
+ return rv;
rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT);
if (rv)
- goto err_node_put;
+ return rv;
rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT);
if (rv)
- goto err_node_put;
+ return rv;
}
return regmap_write(map,
MAX77650_REG_CNFG_LED_TOP,
MAX77650_LED_TOP_DEFAULT);
-err_node_put:
- fwnode_handle_put(child);
- return rv;
}
static const struct of_device_id max77650_led_of_match[] = {
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index da99d114bfb2..e22f09d13798 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -301,7 +301,7 @@ static struct platform_driver mc13xxx_led_driver = {
.driver = {
.name = "mc13xxx-led",
},
- .remove_new = mc13xxx_led_remove,
+ .remove = mc13xxx_led_remove,
.id_table = mc13xxx_led_id_table,
};
module_platform_driver_probe(mc13xxx_led_driver, mc13xxx_led_probe);
diff --git a/drivers/leds/leds-mt6323.c b/drivers/leds/leds-mt6323.c
index a19e8e0b6d1b..dbdc221c3828 100644
--- a/drivers/leds/leds-mt6323.c
+++ b/drivers/leds/leds-mt6323.c
@@ -713,7 +713,7 @@ MODULE_DEVICE_TABLE(of, mt6323_led_dt_match);
static struct platform_driver mt6323_led_driver = {
.probe = mt6323_led_probe,
- .remove_new = mt6323_led_remove,
+ .remove = mt6323_led_remove,
.driver = {
.name = "mt6323-led",
.of_match_table = mt6323_led_dt_match,
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index f3010c472bbd..4c6f04a5bd87 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -238,7 +238,6 @@ static int ns2_led_register(struct device *dev, struct fwnode_handle *node,
static int ns2_led_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct fwnode_handle *child;
struct ns2_led *leds;
int count;
int ret;
@@ -251,12 +250,10 @@ static int ns2_led_probe(struct platform_device *pdev)
if (!leds)
return -ENOMEM;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
ret = ns2_led_register(dev, child, leds++);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
}
return 0;
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index b53905da3592..050e93b04884 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -306,7 +306,6 @@ static int pca963x_register_leds(struct i2c_client *client,
struct pca963x_chipdef *chipdef = chip->chipdef;
struct pca963x_led *led = chip->leds;
struct device *dev = &client->dev;
- struct fwnode_handle *child;
bool hw_blink;
s32 mode2;
u32 reg;
@@ -338,7 +337,7 @@ static int pca963x_register_leds(struct i2c_client *client,
if (ret < 0)
return ret;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct led_init_data init_data = {};
char default_label[32];
@@ -346,8 +345,7 @@ static int pca963x_register_leds(struct i2c_client *client,
if (ret || reg >= chipdef->n_leds) {
dev_err(dev, "Invalid 'reg' property for node %pfw\n",
child);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
led->led_num = reg;
@@ -369,16 +367,13 @@ static int pca963x_register_leds(struct i2c_client *client,
if (ret) {
dev_err(dev, "Failed to register LED for node %pfw\n",
child);
- goto err;
+ return ret;
}
++led;
}
return 0;
-err:
- fwnode_handle_put(child);
- return ret;
}
static int pca963x_suspend(struct device *dev)
diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c
index 49ab8c9a3f29..3a38578ce8e4 100644
--- a/drivers/leds/leds-powernv.c
+++ b/drivers/leds/leds-powernv.c
@@ -323,8 +323,8 @@ static const struct of_device_id powernv_led_match[] = {
MODULE_DEVICE_TABLE(of, powernv_led_match);
static struct platform_driver powernv_led_driver = {
- .probe = powernv_led_probe,
- .remove_new = powernv_led_remove,
+ .probe = powernv_led_probe,
+ .remove = powernv_led_remove,
.driver = {
.name = "powernv-led-driver",
.of_match_table = powernv_led_match,
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index e1b414b40353..c73134e7b951 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -17,7 +17,6 @@
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/slab.h>
-#include "leds.h"
struct led_pwm {
const char *name;
@@ -63,6 +62,20 @@ static int led_pwm_set(struct led_classdev *led_cdev,
return pwm_apply_might_sleep(led_dat->pwm, &led_dat->pwmstate);
}
+static int led_pwm_default_brightness_get(struct fwnode_handle *fwnode,
+ int max_brightness)
+{
+ unsigned int default_brightness;
+ int ret;
+
+ ret = fwnode_property_read_u32(fwnode, "default-brightness",
+ &default_brightness);
+ if (ret < 0 || default_brightness > max_brightness)
+ default_brightness = max_brightness;
+
+ return default_brightness;
+}
+
__attribute__((nonnull))
static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
struct led_pwm *led, struct fwnode_handle *fwnode)
@@ -104,7 +117,8 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
/* set brightness */
switch (led->default_state) {
case LEDS_DEFSTATE_ON:
- led_data->cdev.brightness = led->max_brightness;
+ led_data->cdev.brightness =
+ led_pwm_default_brightness_get(fwnode, led->max_brightness);
break;
case LEDS_DEFSTATE_KEEP:
{
@@ -140,21 +154,18 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
{
- struct fwnode_handle *fwnode;
struct led_pwm led;
int ret;
- device_for_each_child_node(dev, fwnode) {
+ device_for_each_child_node_scoped(dev, fwnode) {
memset(&led, 0, sizeof(led));
ret = fwnode_property_read_string(fwnode, "label", &led.name);
if (ret && is_of_node(fwnode))
led.name = to_of_node(fwnode)->name;
- if (!led.name) {
- ret = -EINVAL;
- goto err_child_out;
- }
+ if (!led.name)
+ return -EINVAL;
led.active_low = fwnode_property_read_bool(fwnode,
"active-low");
@@ -165,14 +176,10 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
ret = led_pwm_add(dev, priv, &led, fwnode);
if (ret)
- goto err_child_out;
+ return ret;
}
return 0;
-
-err_child_out:
- fwnode_handle_put(fwnode);
- return ret;
}
static int led_pwm_probe(struct platform_device *pdev)
diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
index e66f73879c8e..782e1c11ee44 100644
--- a/drivers/leds/leds-rb532.c
+++ b/drivers/leds/leds-rb532.c
@@ -49,7 +49,7 @@ static void rb532_led_remove(struct platform_device *pdev)
static struct platform_driver rb532_led_driver = {
.probe = rb532_led_probe,
- .remove_new = rb532_led_remove,
+ .remove = rb532_led_remove,
.driver = {
.name = "rb532-led",
},
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index 848e929c4a61..ade64629431a 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -193,7 +193,7 @@ static struct platform_driver regulator_led_driver = {
.of_match_table = regulator_led_of_match,
},
.probe = regulator_led_probe,
- .remove_new = regulator_led_remove,
+ .remove = regulator_led_remove,
};
module_platform_driver(regulator_led_driver);
diff --git a/drivers/leds/leds-sc27xx-bltc.c b/drivers/leds/leds-sc27xx-bltc.c
index cca98c644aa6..0c5169773949 100644
--- a/drivers/leds/leds-sc27xx-bltc.c
+++ b/drivers/leds/leds-sc27xx-bltc.c
@@ -344,7 +344,7 @@ static struct platform_driver sc27xx_led_driver = {
.of_match_table = sc27xx_led_of_match,
},
.probe = sc27xx_led_probe,
- .remove_new = sc27xx_led_remove,
+ .remove = sc27xx_led_remove,
};
module_platform_driver(sc27xx_led_driver);
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 2ef9fc7371bd..f24ca75c7cb1 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -451,7 +451,7 @@ static ssize_t blink_show(struct device *dev,
int blinking = 0;
if (nasgpio_led_get_attr(led, GPO_BLINK))
blinking = 1;
- return sprintf(buf, "%u\n", blinking);
+ return sprintf(buf, "%d\n", blinking);
}
static ssize_t blink_store(struct device *dev,
diff --git a/drivers/leds/leds-sun50i-a100.c b/drivers/leds/leds-sun50i-a100.c
index 4c468d487486..2c9bd360ab81 100644
--- a/drivers/leds/leds-sun50i-a100.c
+++ b/drivers/leds/leds-sun50i-a100.c
@@ -392,7 +392,6 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev)
struct sun50i_a100_ledc_led *led;
struct device *dev = &pdev->dev;
struct sun50i_a100_ledc *priv;
- struct fwnode_handle *child;
struct resource *mem;
u32 max_addr = 0;
u32 num_leds = 0;
@@ -402,21 +401,17 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev)
* The maximum LED address must be known in sun50i_a100_ledc_resume() before
* class device registration, so parse and validate the subnodes up front.
*/
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
u32 addr, color;
ret = fwnode_property_read_u32(child, "reg", &addr);
- if (ret || addr >= LEDC_MAX_LEDS) {
- fwnode_handle_put(child);
+ if (ret || addr >= LEDC_MAX_LEDS)
return dev_err_probe(dev, -EINVAL, "'reg' must be between 0 and %d\n",
LEDC_MAX_LEDS - 1);
- }
ret = fwnode_property_read_u32(child, "color", &color);
- if (ret || color != LED_COLOR_ID_RGB) {
- fwnode_handle_put(child);
+ if (ret || color != LED_COLOR_ID_RGB)
return dev_err_probe(dev, -EINVAL, "'color' must be LED_COLOR_ID_RGB\n");
- }
max_addr = max(max_addr, addr);
num_leds++;
@@ -502,7 +497,7 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev)
return ret;
led = priv->leds;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct led_classdev *cdev;
/* The node was already validated above. */
@@ -527,7 +522,11 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev)
ret = led_classdev_multicolor_register_ext(dev, &led->mc_cdev, &init_data);
if (ret) {
dev_err_probe(dev, ret, "Failed to register multicolor LED %u", led->addr);
- goto err_put_child;
+ while (led-- > priv->leds)
+ led_classdev_multicolor_unregister(&led->mc_cdev);
+ sun50i_a100_ledc_suspend(&pdev->dev);
+
+ return ret;
}
led++;
@@ -536,14 +535,6 @@ static int sun50i_a100_ledc_probe(struct platform_device *pdev)
dev_info(dev, "Registered %u LEDs\n", num_leds);
return 0;
-
-err_put_child:
- fwnode_handle_put(child);
- while (led-- > priv->leds)
- led_classdev_multicolor_unregister(&led->mc_cdev);
- sun50i_a100_ledc_suspend(&pdev->dev);
-
- return ret;
}
static void sun50i_a100_ledc_remove(struct platform_device *pdev)
@@ -567,7 +558,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(sun50i_a100_ledc_pm,
static struct platform_driver sun50i_a100_ledc_driver = {
.probe = sun50i_a100_ledc_probe,
- .remove_new = sun50i_a100_ledc_remove,
+ .remove = sun50i_a100_ledc_remove,
.shutdown = sun50i_a100_ledc_remove,
.driver = {
.name = "sun50i-a100-ledc",
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
index a621e5e5c75c..bd24e7f5947a 100644
--- a/drivers/leds/leds-sunfire.c
+++ b/drivers/leds/leds-sunfire.c
@@ -219,7 +219,7 @@ MODULE_ALIAS("platform:sunfire-fhc-leds");
static struct platform_driver sunfire_clockboard_led_driver = {
.probe = sunfire_clockboard_led_probe,
- .remove_new = sunfire_led_generic_remove,
+ .remove = sunfire_led_generic_remove,
.driver = {
.name = "sunfire-clockboard-leds",
},
@@ -227,7 +227,7 @@ static struct platform_driver sunfire_clockboard_led_driver = {
static struct platform_driver sunfire_fhc_led_driver = {
.probe = sunfire_fhc_led_probe,
- .remove_new = sunfire_led_generic_remove,
+ .remove = sunfire_led_generic_remove,
.driver = {
.name = "sunfire-fhc-leds",
},
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
index 4f22f4224946..acbd8169723c 100644
--- a/drivers/leds/leds-tca6507.c
+++ b/drivers/leds/leds-tca6507.c
@@ -658,7 +658,6 @@ static struct tca6507_platform_data *
tca6507_led_dt_init(struct device *dev)
{
struct tca6507_platform_data *pdata;
- struct fwnode_handle *child;
struct led_info *tca_leds;
int count;
@@ -671,7 +670,7 @@ tca6507_led_dt_init(struct device *dev)
if (!tca_leds)
return ERR_PTR(-ENOMEM);
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct led_info led;
u32 reg;
int ret;
@@ -688,10 +687,8 @@ tca6507_led_dt_init(struct device *dev)
led.flags |= TCA6507_MAKE_GPIO;
ret = fwnode_property_read_u32(child, "reg", &reg);
- if (ret || reg >= NUM_LEDS) {
- fwnode_handle_put(child);
+ if (ret || reg >= NUM_LEDS)
return ERR_PTR(ret ? : -EINVAL);
- }
tca_leds[reg] = led;
}
diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c
index 4cff8c4b020c..2de825ac08b3 100644
--- a/drivers/leds/leds-turris-omnia.c
+++ b/drivers/leds/leds-turris-omnia.c
@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
-#include "leds.h"
#define OMNIA_BOARD_LEDS 12
#define OMNIA_LED_NUM_CHANNELS 3
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index 70b32d80f960..05930e9e8887 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -292,7 +292,7 @@ static struct platform_driver wm831x_status_driver = {
.name = "wm831x-status",
},
.probe = wm831x_status_probe,
- .remove_new = wm831x_status_remove,
+ .remove = wm831x_status_remove,
};
module_platform_driver(wm831x_status_driver);
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 61cbefa05710..87e60ea927b9 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -255,7 +255,7 @@ static struct platform_driver wm8350_led_driver = {
.name = "wm8350-led",
},
.probe = wm8350_led_probe,
- .remove_new = wm8350_led_remove,
+ .remove = wm8350_led_remove,
.shutdown = wm8350_led_shutdown,
};
diff --git a/drivers/leds/rgb/leds-group-multicolor.c b/drivers/leds/rgb/leds-group-multicolor.c
index b6c7679015fd..548c7dd63ba1 100644
--- a/drivers/leds/rgb/leds-group-multicolor.c
+++ b/drivers/leds/rgb/leds-group-multicolor.c
@@ -55,7 +55,7 @@ static void restore_sysfs_write_access(void *data)
{
struct led_classdev *led_cdev = data;
- /* Restore the write acccess to the LED */
+ /* Restore the write access to the LED */
mutex_lock(&led_cdev->led_access);
led_sysfs_enable(led_cdev);
mutex_unlock(&led_cdev->led_access);
diff --git a/drivers/leds/rgb/leds-ktd202x.c b/drivers/leds/rgb/leds-ktd202x.c
index d5c442163c46..04e62faa3a00 100644
--- a/drivers/leds/rgb/leds-ktd202x.c
+++ b/drivers/leds/rgb/leds-ktd202x.c
@@ -495,7 +495,6 @@ static int ktd202x_add_led(struct ktd202x *chip, struct fwnode_handle *fwnode, u
static int ktd202x_probe_fw(struct ktd202x *chip)
{
- struct fwnode_handle *child;
struct device *dev = chip->dev;
int count;
int i = 0;
@@ -509,13 +508,12 @@ static int ktd202x_probe_fw(struct ktd202x *chip)
/* Allow the device to execute the complete reset */
usleep_range(200, 300);
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
int ret = ktd202x_add_led(chip, child, i);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
+
i++;
}
diff --git a/drivers/leds/rgb/leds-mt6370-rgb.c b/drivers/leds/rgb/leds-mt6370-rgb.c
index 10a0b5b45227..ebd3ba878dd5 100644
--- a/drivers/leds/rgb/leds-mt6370-rgb.c
+++ b/drivers/leds/rgb/leds-mt6370-rgb.c
@@ -587,7 +587,7 @@ static inline int mt6370_mc_pattern_clear(struct led_classdev *lcdev)
struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc);
struct mt6370_priv *priv = led->priv;
struct mc_subled *subled;
- int i, ret;
+ int i, ret = 0;
mutex_lock(&led->priv->lock);
@@ -905,7 +905,6 @@ static int mt6370_leds_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mt6370_priv *priv;
- struct fwnode_handle *child;
size_t count;
unsigned int i = 0;
int ret;
@@ -936,37 +935,27 @@ static int mt6370_leds_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Failed to allocate regmap field\n");
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct mt6370_led *led = priv->leds + i++;
struct led_init_data init_data = { .fwnode = child };
u32 reg, color;
ret = fwnode_property_read_u32(child, "reg", &reg);
- if (ret) {
- dev_err(dev, "Failed to parse reg property\n");
- goto fwnode_release;
- }
+ if (ret)
+ dev_err_probe(dev, ret, "Failed to parse reg property\n");
- if (reg >= MT6370_MAX_LEDS) {
- ret = -EINVAL;
- dev_err(dev, "Error reg property number\n");
- goto fwnode_release;
- }
+ if (reg >= MT6370_MAX_LEDS)
+ return dev_err_probe(dev, -EINVAL, "Error reg property number\n");
ret = fwnode_property_read_u32(child, "color", &color);
- if (ret) {
- dev_err(dev, "Failed to parse color property\n");
- goto fwnode_release;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to parse color property\n");
if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI)
reg = MT6370_VIRTUAL_MULTICOLOR;
- if (priv->leds_active & BIT(reg)) {
- ret = -EINVAL;
- dev_err(dev, "Duplicate reg property\n");
- goto fwnode_release;
- }
+ if (priv->leds_active & BIT(reg))
+ return dev_err_probe(dev, -EINVAL, "Duplicate reg property\n");
priv->leds_active |= BIT(reg);
@@ -975,18 +964,14 @@ static int mt6370_leds_probe(struct platform_device *pdev)
ret = mt6370_init_led_properties(dev, led, &init_data);
if (ret)
- goto fwnode_release;
+ return ret;
ret = mt6370_led_register(dev, led, &init_data);
if (ret)
- goto fwnode_release;
+ return ret;
}
return 0;
-
-fwnode_release:
- fwnode_handle_put(child);
- return ret;
}
static const struct of_device_id mt6370_rgbled_device_table[] = {
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c
index 726c186391af..c98c370687c2 100644
--- a/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c
@@ -53,7 +53,7 @@ static void simatic_ipc_leds_gpio_apollolake_remove(struct platform_device *pdev
static struct platform_driver simatic_ipc_led_gpio_apollolake_driver = {
.probe = simatic_ipc_leds_gpio_apollolake_probe,
- .remove_new = simatic_ipc_leds_gpio_apollolake_remove,
+ .remove = simatic_ipc_leds_gpio_apollolake_remove,
.driver = {
.name = KBUILD_MODNAME,
},
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c b/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c
index 3fec96c549c1..7f7cff275448 100644
--- a/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c
@@ -43,7 +43,7 @@ static void simatic_ipc_leds_gpio_elkhartlake_remove(struct platform_device *pde
static struct platform_driver simatic_ipc_led_gpio_elkhartlake_driver = {
.probe = simatic_ipc_leds_gpio_elkhartlake_probe,
- .remove_new = simatic_ipc_leds_gpio_elkhartlake_remove,
+ .remove = simatic_ipc_leds_gpio_elkhartlake_remove,
.driver = {
.name = KBUILD_MODNAME,
},
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
index a1f10952513c..bc23d701bcb7 100644
--- a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
@@ -93,7 +93,7 @@ static void simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev)
static struct platform_driver simatic_ipc_led_gpio_driver = {
.probe = simatic_ipc_leds_gpio_f7188x_probe,
- .remove_new = simatic_ipc_leds_gpio_f7188x_remove,
+ .remove = simatic_ipc_leds_gpio_f7188x_remove,
.driver = {
.name = KBUILD_MODNAME,
},
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
index a4fb16d7db3c..fc1af74b6596 100644
--- a/drivers/macintosh/via-pmu-led.c
+++ b/drivers/macintosh/via-pmu-led.c
@@ -92,18 +92,15 @@ static int __init via_pmu_led_init(void)
if (dt == NULL)
return -ENODEV;
model = of_get_property(dt, "model", NULL);
- if (model == NULL) {
- of_node_put(dt);
- return -ENODEV;
- }
+ if (!model)
+ goto put_node;
+
if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
strncmp(model, "iBook", strlen("iBook")) != 0 &&
strcmp(model, "PowerMac7,2") != 0 &&
- strcmp(model, "PowerMac7,3") != 0) {
- of_node_put(dt);
- /* ignore */
- return -ENODEV;
- }
+ strcmp(model, "PowerMac7,3") != 0)
+ goto put_node;
+
of_node_put(dt);
spin_lock_init(&pmu_blink_lock);
@@ -112,6 +109,10 @@ static int __init via_pmu_led_init(void)
pmu_blink_req.done = pmu_req_done;
return led_classdev_register(NULL, &pmu_led);
+
+put_node:
+ of_node_put(dt);
+ return -ENODEV;
}
late_initcall(via_pmu_led_init);
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 6fb995778636..8ecba7fb999e 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -127,7 +127,7 @@ config STI_MBOX
config TI_MESSAGE_MANAGER
tristate "Texas Instruments Message Manager Driver"
- depends on ARCH_KEYSTONE || ARCH_K3
+ depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
default ARCH_K3
help
An implementation of Message Manager slave driver for Keystone
@@ -168,6 +168,7 @@ config MAILBOX_TEST
config POLARFIRE_SOC_MAILBOX
tristate "PolarFire SoC (MPFS) Mailbox"
depends on HAS_IOMEM
+ depends on MFD_SYSCON
depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
help
This driver adds support for the PolarFire SoC (MPFS) mailbox controller.
@@ -295,4 +296,14 @@ config QCOM_IPCC
acts as an interrupt controller for receiving interrupts from clients.
Say Y here if you want to build this driver.
+config THEAD_TH1520_MBOX
+ tristate "T-head TH1520 Mailbox"
+ depends on ARCH_THEAD || COMPILE_TEST
+ help
+ Mailbox driver implementation for the Thead TH-1520 platform. Enables
+ two cores within the SoC to communicate and coordinate by passing
+ messages. Could be used to communicate between E910 core, on which the
+ kernel is running, and E902 core used for power management among other
+ things.
+
endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 3c3c27d54c13..5f4f5b0ce2cc 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -64,3 +64,5 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
obj-$(CONFIG_QCOM_CPUCP_MBOX) += qcom-cpucp-mbox.o
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
+
+obj-$(CONFIG_THEAD_TH1520_MBOX) += mailbox-th1520.o
diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c
index 0ec21dcdbde7..cff7c343ee08 100644
--- a/drivers/mailbox/arm_mhuv2.c
+++ b/drivers/mailbox/arm_mhuv2.c
@@ -500,7 +500,7 @@ static const struct mhuv2_protocol_ops mhuv2_data_transfer_ops = {
static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg)
{
struct mbox_chan *chans = mhu->mbox.chans;
- int channel = 0, i, offset = 0, windows, protocol, ch_wn;
+ int channel = 0, i, j, offset = 0, windows, protocol, ch_wn;
u32 stat;
for (i = 0; i < MHUV2_CMB_INT_ST_REG_CNT; i++) {
@@ -510,9 +510,9 @@ static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg)
ch_wn = i * MHUV2_STAT_BITS + __builtin_ctz(stat);
- for (i = 0; i < mhu->length; i += 2) {
- protocol = mhu->protocols[i];
- windows = mhu->protocols[i + 1];
+ for (j = 0; j < mhu->length; j += 2) {
+ protocol = mhu->protocols[j];
+ windows = mhu->protocols[j + 1];
if (ch_wn >= offset + windows) {
if (protocol == DOORBELL)
diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c
index b1abc2a0c971..41f79e51d9e5 100644
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -1675,7 +1675,7 @@ static struct platform_driver flexrm_mbox_driver = {
.of_match_table = flexrm_mbox_of_match,
},
.probe = flexrm_mbox_probe,
- .remove_new = flexrm_mbox_remove,
+ .remove = flexrm_mbox_remove,
};
module_platform_driver(flexrm_mbox_driver);
diff --git a/drivers/mailbox/bcm-pdc-mailbox.c b/drivers/mailbox/bcm-pdc-mailbox.c
index a873672a9082..406bc41cba60 100644
--- a/drivers/mailbox/bcm-pdc-mailbox.c
+++ b/drivers/mailbox/bcm-pdc-mailbox.c
@@ -1618,7 +1618,7 @@ static void pdc_remove(struct platform_device *pdev)
static struct platform_driver pdc_mbox_driver = {
.probe = pdc_probe,
- .remove_new = pdc_remove,
+ .remove = pdc_remove,
.driver = {
.name = "brcm-iproc-pdc-mbox",
.of_match_table = pdc_mbox_of_match,
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
index f815dab3be50..6ef8338add0d 100644
--- a/drivers/mailbox/imx-mailbox.c
+++ b/drivers/mailbox/imx-mailbox.c
@@ -782,7 +782,7 @@ static int imx_mu_init_generic(struct imx_mu_priv *priv)
cp->chan = &priv->mbox_chans[i];
priv->mbox_chans[i].con_priv = cp;
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
- "%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);
+ "%s[%i-%u]", dev_name(priv->dev), cp->type, cp->idx);
}
priv->mbox.num_chans = IMX_MU_CHANS;
@@ -819,7 +819,7 @@ static int imx_mu_init_specific(struct imx_mu_priv *priv)
cp->chan = &priv->mbox_chans[i];
priv->mbox_chans[i].con_priv = cp;
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
- "%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);
+ "%s[%i-%u]", dev_name(priv->dev), cp->type, cp->idx);
}
priv->mbox.num_chans = num_chans;
@@ -1120,7 +1120,7 @@ static const struct dev_pm_ops imx_mu_pm_ops = {
static struct platform_driver imx_mu_driver = {
.probe = imx_mu_probe,
- .remove_new = imx_mu_remove,
+ .remove = imx_mu_remove,
.driver = {
.name = "imx_mu",
.of_match_table = imx_mu_dt_ids,
diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c
index 20ee283a04cc..4df546e3b7ea 100644
--- a/drivers/mailbox/mailbox-mpfs.c
+++ b/drivers/mailbox/mailbox-mpfs.c
@@ -13,12 +13,15 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/regmap.h>
#include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/mailbox_controller.h>
#include <soc/microchip/mpfs.h>
+#define MESSAGE_INT_OFFSET 0x18cu
#define SERVICES_CR_OFFSET 0x50u
#define SERVICES_SR_OFFSET 0x54u
#define MAILBOX_REG_OFFSET 0x800u
@@ -68,6 +71,7 @@ struct mpfs_mbox {
void __iomem *int_reg;
struct mbox_chan chans[1];
struct mpfs_mss_response *response;
+ struct regmap *sysreg_scb, *control_scb;
u16 resp_offset;
};
@@ -75,7 +79,10 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
{
u32 status;
- status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
+ if (mbox->control_scb)
+ regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &status);
+ else
+ status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
return status & SCB_STATUS_BUSY_MASK;
}
@@ -95,7 +102,11 @@ static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
* Failed services are intended to generated interrupts, but in reality
* this does not happen, so the status must be checked here.
*/
- val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
+ if (mbox->control_scb)
+ regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &val);
+ else
+ val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
+
response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS;
return true;
@@ -143,7 +154,12 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK;
tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK;
- writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
+
+ if (mbox->control_scb)
+ regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, tx_trigger);
+ else
+ writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
+
return 0;
}
@@ -185,7 +201,10 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data)
struct mbox_chan *chan = data;
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
- writel_relaxed(0, mbox->int_reg);
+ if (mbox->control_scb)
+ regmap_write(mbox->sysreg_scb, MESSAGE_INT_OFFSET, 0);
+ else
+ writel_relaxed(0, mbox->int_reg);
mpfs_mbox_rx_data(chan);
@@ -221,28 +240,62 @@ static const struct mbox_chan_ops mpfs_mbox_ops = {
.last_tx_done = mpfs_mbox_last_tx_done,
};
-static int mpfs_mbox_probe(struct platform_device *pdev)
+static inline int mpfs_mbox_syscon_probe(struct mpfs_mbox *mbox, struct platform_device *pdev)
{
- struct mpfs_mbox *mbox;
- struct resource *regs;
- int ret;
+ mbox->control_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-control-scb");
+ if (IS_ERR(mbox->control_scb))
+ return PTR_ERR(mbox->control_scb);
- mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
- if (!mbox)
- return -ENOMEM;
+ mbox->sysreg_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb");
+ if (IS_ERR(mbox->sysreg_scb))
+ return PTR_ERR(mbox->sysreg_scb);
+
+ mbox->mbox_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mbox->ctrl_base))
+ return PTR_ERR(mbox->mbox_base);
+
+ return 0;
+}
+
+static inline int mpfs_mbox_old_format_probe(struct mpfs_mbox *mbox, struct platform_device *pdev)
+{
+ dev_warn(&pdev->dev, "falling back to old devicetree format");
- mbox->ctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
+ mbox->ctrl_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mbox->ctrl_base))
return PTR_ERR(mbox->ctrl_base);
- mbox->int_reg = devm_platform_get_and_ioremap_resource(pdev, 1, &regs);
+ mbox->int_reg = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(mbox->int_reg))
return PTR_ERR(mbox->int_reg);
- mbox->mbox_base = devm_platform_get_and_ioremap_resource(pdev, 2, &regs);
+ mbox->mbox_base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs
mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET;
+ return 0;
+}
+
+static int mpfs_mbox_probe(struct platform_device *pdev)
+{
+ struct mpfs_mbox *mbox;
+ int ret;
+
+ mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
+ if (!mbox)
+ return -ENOMEM;
+
+ ret = mpfs_mbox_syscon_probe(mbox, pdev);
+ if (ret) {
+ /*
+ * set this to null, so it can be used as the decision for to
+ * regmap or not to regmap
+ */
+ mbox->control_scb = NULL;
+ ret = mpfs_mbox_old_format_probe(mbox, pdev);
+ if (ret)
+ return ret;
+ }
mbox->irq = platform_get_irq(pdev, 0);
if (mbox->irq < 0)
return mbox->irq;
diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c
index 3386b4e72551..c9dd8c42c0cd 100644
--- a/drivers/mailbox/mailbox-test.c
+++ b/drivers/mailbox/mailbox-test.c
@@ -441,8 +441,8 @@ static struct platform_driver mbox_test_driver = {
.name = "mailbox_test",
.of_match_table = mbox_test_match,
},
- .probe = mbox_test_probe,
- .remove_new = mbox_test_remove,
+ .probe = mbox_test_probe,
+ .remove = mbox_test_remove,
};
module_platform_driver(mbox_test_driver);
diff --git a/drivers/mailbox/mailbox-th1520.c b/drivers/mailbox/mailbox-th1520.c
new file mode 100644
index 000000000000..4e84640ac3b8
--- /dev/null
+++ b/drivers/mailbox/mailbox-th1520.c
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* Status Register */
+#define TH_1520_MBOX_STA 0x0
+#define TH_1520_MBOX_CLR 0x4
+#define TH_1520_MBOX_MASK 0xc
+
+/* Transmit/receive data register:
+ * INFO0 ~ INFO6
+ */
+#define TH_1520_MBOX_INFO_NUM 8
+#define TH_1520_MBOX_DATA_INFO_NUM 7
+#define TH_1520_MBOX_INFO0 0x14
+/* Transmit ack register: INFO7 */
+#define TH_1520_MBOX_INFO7 0x30
+
+/* Generate remote icu IRQ Register */
+#define TH_1520_MBOX_GEN 0x10
+#define TH_1520_MBOX_GEN_RX_DATA BIT(6)
+#define TH_1520_MBOX_GEN_TX_ACK BIT(7)
+
+#define TH_1520_MBOX_CHAN_RES_SIZE 0x1000
+#define TH_1520_MBOX_CHANS 4
+#define TH_1520_MBOX_CHAN_NAME_SIZE 20
+
+#define TH_1520_MBOX_ACK_MAGIC 0xdeadbeaf
+
+#ifdef CONFIG_PM_SLEEP
+/* store MBOX context across system-wide suspend/resume transitions */
+struct th1520_mbox_context {
+ u32 intr_mask[TH_1520_MBOX_CHANS - 1];
+};
+#endif
+
+enum th1520_mbox_icu_cpu_id {
+ TH_1520_MBOX_ICU_KERNEL_CPU0, /* 910T */
+ TH_1520_MBOX_ICU_CPU1, /* 902 */
+ TH_1520_MBOX_ICU_CPU2, /* 906 */
+ TH_1520_MBOX_ICU_CPU3, /* 910R */
+};
+
+struct th1520_mbox_con_priv {
+ enum th1520_mbox_icu_cpu_id idx;
+ void __iomem *comm_local_base;
+ void __iomem *comm_remote_base;
+ char irq_desc[TH_1520_MBOX_CHAN_NAME_SIZE];
+ struct mbox_chan *chan;
+};
+
+struct th1520_mbox_priv {
+ struct device *dev;
+ void __iomem *local_icu[TH_1520_MBOX_CHANS];
+ void __iomem *remote_icu[TH_1520_MBOX_CHANS - 1];
+ void __iomem *cur_cpu_ch_base;
+ spinlock_t mbox_lock; /* control register lock */
+
+ struct mbox_controller mbox;
+ struct mbox_chan mbox_chans[TH_1520_MBOX_CHANS];
+ struct clk_bulk_data clocks[TH_1520_MBOX_CHANS];
+ struct th1520_mbox_con_priv con_priv[TH_1520_MBOX_CHANS];
+ int irq;
+#ifdef CONFIG_PM_SLEEP
+ struct th1520_mbox_context *ctx;
+#endif
+};
+
+static struct th1520_mbox_priv *
+to_th1520_mbox_priv(struct mbox_controller *mbox)
+{
+ return container_of(mbox, struct th1520_mbox_priv, mbox);
+}
+
+static void th1520_mbox_write(struct th1520_mbox_priv *priv, u32 val, u32 offs)
+{
+ iowrite32(val, priv->cur_cpu_ch_base + offs);
+}
+
+static u32 th1520_mbox_read(struct th1520_mbox_priv *priv, u32 offs)
+{
+ return ioread32(priv->cur_cpu_ch_base + offs);
+}
+
+static u32 th1520_mbox_rmw(struct th1520_mbox_priv *priv, u32 off, u32 set,
+ u32 clr)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&priv->mbox_lock, flags);
+ val = th1520_mbox_read(priv, off);
+ val &= ~clr;
+ val |= set;
+ th1520_mbox_write(priv, val, off);
+ spin_unlock_irqrestore(&priv->mbox_lock, flags);
+
+ return val;
+}
+
+static void th1520_mbox_chan_write(struct th1520_mbox_con_priv *cp, u32 val,
+ u32 offs, bool is_remote)
+{
+ if (is_remote)
+ iowrite32(val, cp->comm_remote_base + offs);
+ else
+ iowrite32(val, cp->comm_local_base + offs);
+}
+
+static u32 th1520_mbox_chan_read(struct th1520_mbox_con_priv *cp, u32 offs,
+ bool is_remote)
+{
+ if (is_remote)
+ return ioread32(cp->comm_remote_base + offs);
+ else
+ return ioread32(cp->comm_local_base + offs);
+}
+
+static void th1520_mbox_chan_rmw(struct th1520_mbox_con_priv *cp, u32 off,
+ u32 set, u32 clr, bool is_remote)
+{
+ struct th1520_mbox_priv *priv = to_th1520_mbox_priv(cp->chan->mbox);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&priv->mbox_lock, flags);
+ val = th1520_mbox_chan_read(cp, off, is_remote);
+ val &= ~clr;
+ val |= set;
+ th1520_mbox_chan_write(cp, val, off, is_remote);
+ spin_unlock_irqrestore(&priv->mbox_lock, flags);
+}
+
+static void th1520_mbox_chan_rd_data(struct th1520_mbox_con_priv *cp,
+ void *data, bool is_remote)
+{
+ u32 off = TH_1520_MBOX_INFO0;
+ u32 *arg = data;
+ u32 i;
+
+ /* read info0 ~ info6, totally 28 bytes
+ * requires data memory size is 28 bytes
+ */
+ for (i = 0; i < TH_1520_MBOX_DATA_INFO_NUM; i++) {
+ *arg = th1520_mbox_chan_read(cp, off, is_remote);
+ off += 4;
+ arg++;
+ }
+}
+
+static void th1520_mbox_chan_wr_data(struct th1520_mbox_con_priv *cp,
+ void *data, bool is_remote)
+{
+ u32 off = TH_1520_MBOX_INFO0;
+ u32 *arg = data;
+ u32 i;
+
+ /* write info0 ~ info6, totally 28 bytes
+ * requires data memory is 28 bytes valid data
+ */
+ for (i = 0; i < TH_1520_MBOX_DATA_INFO_NUM; i++) {
+ th1520_mbox_chan_write(cp, *arg, off, is_remote);
+ off += 4;
+ arg++;
+ }
+}
+
+static void th1520_mbox_chan_wr_ack(struct th1520_mbox_con_priv *cp, void *data,
+ bool is_remote)
+{
+ u32 off = TH_1520_MBOX_INFO7;
+ u32 *arg = data;
+
+ th1520_mbox_chan_write(cp, *arg, off, is_remote);
+}
+
+static int th1520_mbox_chan_id_to_mapbit(struct th1520_mbox_con_priv *cp)
+{
+ int mapbit = 0;
+ int i;
+
+ for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
+ if (i == cp->idx)
+ return mapbit;
+
+ if (i != TH_1520_MBOX_ICU_KERNEL_CPU0)
+ mapbit++;
+ }
+
+ if (i == TH_1520_MBOX_CHANS)
+ dev_err(cp->chan->mbox->dev, "convert to mapbit failed\n");
+
+ return 0;
+}
+
+static irqreturn_t th1520_mbox_isr(int irq, void *p)
+{
+ struct mbox_chan *chan = p;
+ struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox);
+ struct th1520_mbox_con_priv *cp = chan->con_priv;
+ int mapbit = th1520_mbox_chan_id_to_mapbit(cp);
+ u32 sta, dat[TH_1520_MBOX_DATA_INFO_NUM];
+ u32 ack_magic = TH_1520_MBOX_ACK_MAGIC;
+ u32 info0_data, info7_data;
+
+ sta = th1520_mbox_read(priv, TH_1520_MBOX_STA);
+ if (!(sta & BIT(mapbit)))
+ return IRQ_NONE;
+
+ /* clear chan irq bit in STA register */
+ th1520_mbox_rmw(priv, TH_1520_MBOX_CLR, BIT(mapbit), 0);
+
+ /* info0 is the protocol word, should not be zero! */
+ info0_data = th1520_mbox_chan_read(cp, TH_1520_MBOX_INFO0, false);
+ if (info0_data) {
+ /* read info0~info6 data */
+ th1520_mbox_chan_rd_data(cp, dat, false);
+
+ /* clear local info0 */
+ th1520_mbox_chan_write(cp, 0x0, TH_1520_MBOX_INFO0, false);
+
+ /* notify remote cpu */
+ th1520_mbox_chan_wr_ack(cp, &ack_magic, true);
+ /* CPU1 902/906 use polling mode to monitor info7 */
+ if (cp->idx != TH_1520_MBOX_ICU_CPU1 &&
+ cp->idx != TH_1520_MBOX_ICU_CPU2)
+ th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN,
+ TH_1520_MBOX_GEN_TX_ACK, 0, true);
+
+ /* transfer the data to client */
+ mbox_chan_received_data(chan, (void *)dat);
+ }
+
+ /* info7 magic value mean the real ack signal, not generate bit7 */
+ info7_data = th1520_mbox_chan_read(cp, TH_1520_MBOX_INFO7, false);
+ if (info7_data == TH_1520_MBOX_ACK_MAGIC) {
+ /* clear local info7 */
+ th1520_mbox_chan_write(cp, 0x0, TH_1520_MBOX_INFO7, false);
+
+ /* notify framework the last TX has completed */
+ mbox_chan_txdone(chan, 0);
+ }
+
+ if (!info0_data && !info7_data)
+ return IRQ_NONE;
+
+ return IRQ_HANDLED;
+}
+
+static int th1520_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+ struct th1520_mbox_con_priv *cp = chan->con_priv;
+
+ th1520_mbox_chan_wr_data(cp, data, true);
+ th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, TH_1520_MBOX_GEN_RX_DATA, 0,
+ true);
+ return 0;
+}
+
+static int th1520_mbox_startup(struct mbox_chan *chan)
+{
+ struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox);
+ struct th1520_mbox_con_priv *cp = chan->con_priv;
+ u32 data[8] = {};
+ int mask_bit;
+ int ret;
+
+ /* clear local and remote generate and info0~info7 */
+ th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, 0x0, 0xff, true);
+ th1520_mbox_chan_rmw(cp, TH_1520_MBOX_GEN, 0x0, 0xff, false);
+ th1520_mbox_chan_wr_ack(cp, &data[7], true);
+ th1520_mbox_chan_wr_ack(cp, &data[7], false);
+ th1520_mbox_chan_wr_data(cp, &data[0], true);
+ th1520_mbox_chan_wr_data(cp, &data[0], false);
+
+ /* enable the chan mask */
+ mask_bit = th1520_mbox_chan_id_to_mapbit(cp);
+ th1520_mbox_rmw(priv, TH_1520_MBOX_MASK, BIT(mask_bit), 0);
+
+ /*
+ * Mixing devm_ managed resources with manual IRQ handling is generally
+ * discouraged due to potential complexities with resource management,
+ * especially when dealing with shared interrupts. However, in this case,
+ * the approach is safe and effective because:
+ *
+ * 1. Each mailbox channel requests its IRQ within the .startup() callback
+ * and frees it within the .shutdown() callback.
+ * 2. During device unbinding, the devm_ managed mailbox controller first
+ * iterates through all channels, ensuring that their IRQs are freed before
+ * any other devm_ resources are released.
+ *
+ * This ordering guarantees that no interrupts can be triggered from the device
+ * while it is being unbound, preventing race conditions and ensuring system
+ * stability.
+ */
+ ret = request_irq(priv->irq, th1520_mbox_isr,
+ IRQF_SHARED | IRQF_NO_SUSPEND, cp->irq_desc, chan);
+ if (ret) {
+ dev_err(priv->dev, "Unable to acquire IRQ %d\n", priv->irq);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void th1520_mbox_shutdown(struct mbox_chan *chan)
+{
+ struct th1520_mbox_priv *priv = to_th1520_mbox_priv(chan->mbox);
+ struct th1520_mbox_con_priv *cp = chan->con_priv;
+ int mask_bit;
+
+ free_irq(priv->irq, chan);
+
+ /* clear the chan mask */
+ mask_bit = th1520_mbox_chan_id_to_mapbit(cp);
+ th1520_mbox_rmw(priv, TH_1520_MBOX_MASK, 0, BIT(mask_bit));
+}
+
+static const struct mbox_chan_ops th1520_mbox_ops = {
+ .send_data = th1520_mbox_send_data,
+ .startup = th1520_mbox_startup,
+ .shutdown = th1520_mbox_shutdown,
+};
+
+static int th1520_mbox_init_generic(struct th1520_mbox_priv *priv)
+{
+#ifdef CONFIG_PM_SLEEP
+ priv->ctx = devm_kzalloc(priv->dev, sizeof(*priv->ctx), GFP_KERNEL);
+ if (!priv->ctx)
+ return -ENOMEM;
+#endif
+ /* Set default configuration */
+ th1520_mbox_write(priv, 0xff, TH_1520_MBOX_CLR);
+ th1520_mbox_write(priv, 0x0, TH_1520_MBOX_MASK);
+ return 0;
+}
+
+static struct mbox_chan *th1520_mbox_xlate(struct mbox_controller *mbox,
+ const struct of_phandle_args *sp)
+{
+ u32 chan;
+
+ if (sp->args_count != 1) {
+ dev_err(mbox->dev, "Invalid argument count %d\n",
+ sp->args_count);
+ return ERR_PTR(-EINVAL);
+ }
+
+ chan = sp->args[0]; /* comm remote channel */
+
+ if (chan >= mbox->num_chans) {
+ dev_err(mbox->dev, "Not supported channel number: %d\n", chan);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (chan == TH_1520_MBOX_ICU_KERNEL_CPU0) {
+ dev_err(mbox->dev, "Cannot communicate with yourself\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return &mbox->chans[chan];
+}
+
+static void __iomem *th1520_map_mmio(struct platform_device *pdev,
+ char *res_name, size_t offset)
+{
+ void __iomem *mapped;
+ struct resource *res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get resource: %s\n", res_name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ mapped = devm_ioremap(&pdev->dev, res->start + offset,
+ resource_size(res) - offset);
+ if (IS_ERR(mapped))
+ dev_err(&pdev->dev, "Failed to map resource: %s\n", res_name);
+
+ return mapped;
+}
+
+static void th1520_disable_clk(void *data)
+{
+ struct th1520_mbox_priv *priv = data;
+
+ clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks);
+}
+
+static int th1520_mbox_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct th1520_mbox_priv *priv;
+ unsigned int remote_idx = 0;
+ unsigned int i;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+
+ priv->clocks[0].id = "clk-local";
+ priv->clocks[1].id = "clk-remote-icu0";
+ priv->clocks[2].id = "clk-remote-icu1";
+ priv->clocks[3].id = "clk-remote-icu2";
+
+ ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clocks),
+ priv->clocks);
+ if (ret) {
+ dev_err(dev, "Failed to get clocks\n");
+ return ret;
+ }
+
+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks);
+ if (ret) {
+ dev_err(dev, "Failed to enable clocks\n");
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(dev, th1520_disable_clk, priv);
+ if (ret) {
+ clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks);
+ return ret;
+ }
+
+ /*
+ * The address mappings in the device tree align precisely with those
+ * outlined in the manual. However, register offsets within these
+ * mapped regions are irregular, particularly for remote-icu0.
+ * Consequently, th1520_map_mmio() requires an additional parameter to
+ * handle this quirk.
+ */
+ priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] =
+ th1520_map_mmio(pdev, "local", 0x0);
+ if (IS_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]))
+ return PTR_ERR(priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0]);
+
+ priv->remote_icu[0] = th1520_map_mmio(pdev, "remote-icu0", 0x4000);
+ if (IS_ERR(priv->remote_icu[0]))
+ return PTR_ERR(priv->remote_icu[0]);
+
+ priv->remote_icu[1] = th1520_map_mmio(pdev, "remote-icu1", 0x0);
+ if (IS_ERR(priv->remote_icu[1]))
+ return PTR_ERR(priv->remote_icu[1]);
+
+ priv->remote_icu[2] = th1520_map_mmio(pdev, "remote-icu2", 0x0);
+ if (IS_ERR(priv->remote_icu[2]))
+ return PTR_ERR(priv->remote_icu[2]);
+
+ priv->local_icu[TH_1520_MBOX_ICU_CPU1] =
+ priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0] +
+ TH_1520_MBOX_CHAN_RES_SIZE;
+ priv->local_icu[TH_1520_MBOX_ICU_CPU2] =
+ priv->local_icu[TH_1520_MBOX_ICU_CPU1] +
+ TH_1520_MBOX_CHAN_RES_SIZE;
+ priv->local_icu[TH_1520_MBOX_ICU_CPU3] =
+ priv->local_icu[TH_1520_MBOX_ICU_CPU2] +
+ TH_1520_MBOX_CHAN_RES_SIZE;
+
+ priv->cur_cpu_ch_base = priv->local_icu[TH_1520_MBOX_ICU_KERNEL_CPU0];
+
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq < 0)
+ return priv->irq;
+
+ /* init the chans */
+ for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
+ struct th1520_mbox_con_priv *cp = &priv->con_priv[i];
+
+ cp->idx = i;
+ cp->chan = &priv->mbox_chans[i];
+ priv->mbox_chans[i].con_priv = cp;
+ snprintf(cp->irq_desc, sizeof(cp->irq_desc),
+ "th1520_mbox_chan[%i]", cp->idx);
+
+ cp->comm_local_base = priv->local_icu[i];
+ if (i != TH_1520_MBOX_ICU_KERNEL_CPU0) {
+ cp->comm_remote_base = priv->remote_icu[remote_idx];
+ remote_idx++;
+ }
+ }
+
+ spin_lock_init(&priv->mbox_lock);
+
+ priv->mbox.dev = dev;
+ priv->mbox.ops = &th1520_mbox_ops;
+ priv->mbox.chans = priv->mbox_chans;
+ priv->mbox.num_chans = TH_1520_MBOX_CHANS;
+ priv->mbox.of_xlate = th1520_mbox_xlate;
+ priv->mbox.txdone_irq = true;
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = th1520_mbox_init_generic(priv);
+ if (ret) {
+ dev_err(dev, "Failed to init mailbox context\n");
+ return ret;
+ }
+
+ return devm_mbox_controller_register(dev, &priv->mbox);
+}
+
+static const struct of_device_id th1520_mbox_dt_ids[] = {
+ { .compatible = "thead,th1520-mbox" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, th1520_mbox_dt_ids);
+
+#ifdef CONFIG_PM_SLEEP
+static int __maybe_unused th1520_mbox_suspend_noirq(struct device *dev)
+{
+ struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
+ struct th1520_mbox_context *ctx = priv->ctx;
+ u32 i;
+ /*
+ * ONLY interrupt mask bit should be stored and restores.
+ * INFO data all assumed to be lost.
+ */
+ for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
+ ctx->intr_mask[i] =
+ ioread32(priv->local_icu[i] + TH_1520_MBOX_MASK);
+ }
+ return 0;
+}
+
+static int __maybe_unused th1520_mbox_resume_noirq(struct device *dev)
+{
+ struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
+ struct th1520_mbox_context *ctx = priv->ctx;
+ u32 i;
+
+ for (i = 0; i < TH_1520_MBOX_CHANS; i++) {
+ iowrite32(ctx->intr_mask[i],
+ priv->local_icu[i] + TH_1520_MBOX_MASK);
+ }
+
+ return 0;
+}
+#endif
+
+static int __maybe_unused th1520_mbox_runtime_suspend(struct device *dev)
+{
+ struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks);
+
+ return 0;
+}
+
+static int __maybe_unused th1520_mbox_runtime_resume(struct device *dev)
+{
+ struct th1520_mbox_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks);
+ if (ret)
+ dev_err(dev, "Failed to enable clocks in runtime resume\n");
+
+ return ret;
+}
+
+static const struct dev_pm_ops th1520_mbox_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(th1520_mbox_suspend_noirq,
+ th1520_mbox_resume_noirq)
+#endif
+ SET_RUNTIME_PM_OPS(th1520_mbox_runtime_suspend,
+ th1520_mbox_runtime_resume, NULL)
+};
+
+static struct platform_driver th1520_mbox_driver = {
+ .probe = th1520_mbox_probe,
+ .driver = {
+ .name = "th1520-mbox",
+ .of_match_table = th1520_mbox_dt_ids,
+ .pm = &th1520_mbox_pm_ops,
+ },
+};
+module_platform_driver(th1520_mbox_driver);
+
+MODULE_DESCRIPTION("Thead TH-1520 mailbox IPC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index 4bff73532085..d186865b8dce 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -397,7 +397,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
task = kzalloc(sizeof(*task), GFP_ATOMIC);
if (!task) {
- pm_runtime_put_autosuspend(cmdq->mbox.dev);
+ __pm_runtime_put_autosuspend(cmdq->mbox.dev);
return -ENOMEM;
}
@@ -447,7 +447,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
list_move_tail(&task->list_entry, &thread->task_busy_list);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
- pm_runtime_put_autosuspend(cmdq->mbox.dev);
+ __pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
}
@@ -495,7 +495,7 @@ done:
spin_unlock_irqrestore(&thread->chan->lock, flags);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
- pm_runtime_put_autosuspend(cmdq->mbox.dev);
+ __pm_runtime_put_autosuspend(cmdq->mbox.dev);
}
static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
@@ -535,7 +535,7 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
out:
spin_unlock_irqrestore(&thread->chan->lock, flags);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
- pm_runtime_put_autosuspend(cmdq->mbox.dev);
+ __pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
@@ -550,7 +550,7 @@ wait:
return -EFAULT;
}
pm_runtime_mark_last_busy(cmdq->mbox.dev);
- pm_runtime_put_autosuspend(cmdq->mbox.dev);
+ __pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
}
@@ -584,7 +584,7 @@ static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq)
struct clk_bulk_data *clks;
cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num,
- sizeof(cmdq->clocks), GFP_KERNEL);
+ sizeof(*cmdq->clocks), GFP_KERNEL);
if (!cmdq->clocks)
return -ENOMEM;
@@ -796,7 +796,7 @@ MODULE_DEVICE_TABLE(of, cmdq_of_ids);
static struct platform_driver cmdq_drv = {
.probe = cmdq_probe,
- .remove_new = cmdq_remove,
+ .remove = cmdq_remove,
.driver = {
.name = "mtk_cmdq",
.pm = &cmdq_pm_ops,
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index 6797770474a5..680243751d62 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/kfifo.h>
#include <linux/err.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 94885e411085..82102a4c5d68 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -269,6 +269,35 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan)
return !!val;
}
+static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan)
+{
+ struct acpi_pcct_ext_pcc_shared_memory pcc_hdr;
+
+ if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
+ return;
+ /* If the memory region has not been mapped, we cannot
+ * determine if we need to send the message, but we still
+ * need to set the cmd_update flag before returning.
+ */
+ if (pchan->chan.shmem == NULL) {
+ pcc_chan_reg_read_modify_write(&pchan->cmd_update);
+ return;
+ }
+ memcpy_fromio(&pcc_hdr, pchan->chan.shmem,
+ sizeof(struct acpi_pcct_ext_pcc_shared_memory));
+ /*
+ * The PCC slave subspace channel needs to set the command complete bit
+ * after processing message. If the PCC_ACK_FLAG is set, it should also
+ * ring the doorbell.
+ *
+ * The PCC master subspace channel clears chan_in_use to free channel.
+ */
+ if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK)
+ pcc_send_data(chan, NULL);
+ else
+ pcc_chan_reg_read_modify_write(&pchan->cmd_update);
+}
+
/**
* pcc_mbox_irq - PCC mailbox interrupt handler
* @irq: interrupt number
@@ -306,14 +335,7 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
mbox_chan_received_data(chan, NULL);
- /*
- * The PCC slave subspace channel needs to set the command complete bit
- * and ring doorbell after processing message.
- *
- * The PCC master subspace channel clears chan_in_use to free channel.
- */
- if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
- pcc_send_data(chan, NULL);
+ check_and_ack(pchan, chan);
pchan->chan_in_use = false;
return IRQ_HANDLED;
@@ -365,14 +387,37 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
{
struct mbox_chan *chan = pchan->mchan;
+ struct pcc_chan_info *pchan_info;
+ struct pcc_mbox_chan *pcc_mbox_chan;
if (!chan || !chan->cl)
return;
+ pchan_info = chan->con_priv;
+ pcc_mbox_chan = &pchan_info->chan;
+ if (pcc_mbox_chan->shmem) {
+ iounmap(pcc_mbox_chan->shmem);
+ pcc_mbox_chan->shmem = NULL;
+ }
mbox_free_channel(chan);
}
EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
+int pcc_mbox_ioremap(struct mbox_chan *chan)
+{
+ struct pcc_chan_info *pchan_info;
+ struct pcc_mbox_chan *pcc_mbox_chan;
+
+ if (!chan || !chan->cl)
+ return -1;
+ pchan_info = chan->con_priv;
+ pcc_mbox_chan = &pchan_info->chan;
+ pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr,
+ pcc_mbox_chan->shmem_size);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcc_mbox_ioremap);
+
/**
* pcc_send_data - Called from Mailbox Controller code. Used
* here only to ring the channel doorbell. The PCC client
diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
index 7d91e7c016ba..f0d1fc0fb9ff 100644
--- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
@@ -167,7 +167,7 @@ MODULE_DEVICE_TABLE(of, qcom_apcs_ipc_of_match);
static struct platform_driver qcom_apcs_ipc_driver = {
.probe = qcom_apcs_ipc_probe,
- .remove_new = qcom_apcs_ipc_remove,
+ .remove = qcom_apcs_ipc_remove,
.driver = {
.name = "qcom_apcs_ipc",
.of_match_table = qcom_apcs_ipc_of_match,
diff --git a/drivers/mailbox/qcom-cpucp-mbox.c b/drivers/mailbox/qcom-cpucp-mbox.c
index e5437c294803..44f4ed15f818 100644
--- a/drivers/mailbox/qcom-cpucp-mbox.c
+++ b/drivers/mailbox/qcom-cpucp-mbox.c
@@ -138,7 +138,7 @@ static int qcom_cpucp_mbox_probe(struct platform_device *pdev)
return irq;
ret = devm_request_irq(dev, irq, qcom_cpucp_mbox_irq_fn,
- IRQF_TRIGGER_HIGH, "apss_cpucp_mbox", cpucp);
+ IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, "apss_cpucp_mbox", cpucp);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to register irq: %d\n", irq);
diff --git a/drivers/mailbox/qcom-ipcc.c b/drivers/mailbox/qcom-ipcc.c
index d537cc9c4d4b..14c7907c6632 100644
--- a/drivers/mailbox/qcom-ipcc.c
+++ b/drivers/mailbox/qcom-ipcc.c
@@ -346,7 +346,7 @@ static const struct dev_pm_ops qcom_ipcc_dev_pm_ops = {
static struct platform_driver qcom_ipcc_driver = {
.probe = qcom_ipcc_probe,
- .remove_new = qcom_ipcc_remove,
+ .remove = qcom_ipcc_remove,
.driver = {
.name = "qcom-ipcc",
.of_match_table = qcom_ipcc_of_match,
diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c
index 1442f275782b..4f63f1a14ca6 100644
--- a/drivers/mailbox/stm32-ipcc.c
+++ b/drivers/mailbox/stm32-ipcc.c
@@ -379,7 +379,7 @@ static struct platform_driver stm32_ipcc_driver = {
.of_match_table = stm32_ipcc_of_match,
},
.probe = stm32_ipcc_probe,
- .remove_new = stm32_ipcc_remove,
+ .remove = stm32_ipcc_remove,
};
module_platform_driver(stm32_ipcc_driver);
diff --git a/drivers/mailbox/sun6i-msgbox.c b/drivers/mailbox/sun6i-msgbox.c
index 3dcc54dc83b2..6ba6920f4645 100644
--- a/drivers/mailbox/sun6i-msgbox.c
+++ b/drivers/mailbox/sun6i-msgbox.c
@@ -307,8 +307,8 @@ static struct platform_driver sun6i_msgbox_driver = {
.name = "sun6i-msgbox",
.of_match_table = sun6i_msgbox_of_match,
},
- .probe = sun6i_msgbox_probe,
- .remove_new = sun6i_msgbox_remove,
+ .probe = sun6i_msgbox_probe,
+ .remove = sun6i_msgbox_remove,
};
module_platform_driver(sun6i_msgbox_driver);
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 19ef56cbcfd3..8d5e2d7dc03b 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -951,7 +951,7 @@ static struct platform_driver tegra_hsp_driver = {
.pm = &tegra_hsp_pm_ops,
},
.probe = tegra_hsp_probe,
- .remove_new = tegra_hsp_remove,
+ .remove = tegra_hsp_remove,
};
static int __init tegra_hsp_init(void)
diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c
index 9d2d4ff6cda4..8eb8df8d95a4 100644
--- a/drivers/mailbox/ti-msgmgr.c
+++ b/drivers/mailbox/ti-msgmgr.c
@@ -920,7 +920,7 @@ static struct platform_driver ti_msgmgr_driver = {
.probe = ti_msgmgr_probe,
.driver = {
.name = "ti-msgmgr",
- .of_match_table = of_match_ptr(ti_msgmgr_of_match),
+ .of_match_table = ti_msgmgr_of_match,
.pm = &ti_msgmgr_pm_ops,
},
};
diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c
index 521d08b9ab47..aa5249da59b2 100644
--- a/drivers/mailbox/zynqmp-ipi-mailbox.c
+++ b/drivers/mailbox/zynqmp-ipi-mailbox.c
@@ -940,10 +940,10 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
pdata->num_mboxes = num_mboxes;
mbox = pdata->ipi_mboxes;
- mbox->setup_ipi_fn = ipi_fn;
-
for_each_available_child_of_node(np, nc) {
mbox->pdata = pdata;
+ mbox->setup_ipi_fn = ipi_fn;
+
ret = zynqmp_ipi_mbox_probe(mbox, nc);
if (ret) {
of_node_put(nc);
@@ -1015,7 +1015,7 @@ MODULE_DEVICE_TABLE(of, zynqmp_ipi_of_match);
static struct platform_driver zynqmp_ipi_driver = {
.probe = zynqmp_ipi_probe,
- .remove_new = zynqmp_ipi_remove,
+ .remove = zynqmp_ipi_remove,
.driver = {
.name = "zynqmp-ipi",
.of_match_table = of_match_ptr(zynqmp_ipi_of_match),
diff --git a/drivers/md/bcache/Kconfig b/drivers/md/bcache/Kconfig
index b2d10063d35f..d4697e79d5a3 100644
--- a/drivers/md/bcache/Kconfig
+++ b/drivers/md/bcache/Kconfig
@@ -5,6 +5,7 @@ config BCACHE
select BLOCK_HOLDER_DEPRECATED if SYSFS
select CRC64
select CLOSURES
+ select MIN_HEAP
help
Allows a block device to be used as cache for other devices; uses
a btree for indexing and the layout is optimized for SSDs.
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index da50f6661bae..8998e61efa40 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -189,23 +189,16 @@ static inline bool new_bucket_min_cmp(const void *l, const void *r, void *args)
return new_bucket_prio(ca, *lhs) < new_bucket_prio(ca, *rhs);
}
-static inline void new_bucket_swap(void *l, void *r, void __always_unused *args)
-{
- struct bucket **lhs = l, **rhs = r;
-
- swap(*lhs, *rhs);
-}
-
static void invalidate_buckets_lru(struct cache *ca)
{
struct bucket *b;
const struct min_heap_callbacks bucket_max_cmp_callback = {
.less = new_bucket_max_cmp,
- .swp = new_bucket_swap,
+ .swp = NULL,
};
const struct min_heap_callbacks bucket_min_cmp_callback = {
.less = new_bucket_min_cmp,
- .swp = new_bucket_swap,
+ .swp = NULL,
};
ca->heap.nr = 0;
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index bd97d8626887..68258a16e125 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -1093,14 +1093,6 @@ static inline bool new_btree_iter_cmp(const void *l, const void *r, void __alway
return bkey_cmp(_l->k, _r->k) <= 0;
}
-static inline void new_btree_iter_swap(void *iter1, void *iter2, void __always_unused *args)
-{
- struct btree_iter_set *_iter1 = iter1;
- struct btree_iter_set *_iter2 = iter2;
-
- swap(*_iter1, *_iter2);
-}
-
static inline bool btree_iter_end(struct btree_iter *iter)
{
return !iter->heap.nr;
@@ -1111,7 +1103,7 @@ void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k,
{
const struct min_heap_callbacks callbacks = {
.less = new_btree_iter_cmp,
- .swp = new_btree_iter_swap,
+ .swp = NULL,
};
if (k != end)
@@ -1157,7 +1149,7 @@ static inline struct bkey *__bch_btree_iter_next(struct btree_iter *iter,
struct bkey *ret = NULL;
const struct min_heap_callbacks callbacks = {
.less = cmp,
- .swp = new_btree_iter_swap,
+ .swp = NULL,
};
if (!btree_iter_end(iter)) {
@@ -1231,7 +1223,7 @@ static void btree_mergesort(struct btree_keys *b, struct bset *out,
: bch_ptr_invalid;
const struct min_heap_callbacks callbacks = {
.less = b->ops->sort_cmp,
- .swp = new_btree_iter_swap,
+ .swp = NULL,
};
/* Heapify the iterator, using our comparison function */
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c
index a7221e5dbe81..4b84fda1530a 100644
--- a/drivers/md/bcache/extents.c
+++ b/drivers/md/bcache/extents.c
@@ -266,20 +266,12 @@ static bool new_bch_extent_sort_cmp(const void *l, const void *r, void __always_
return !(c ? c > 0 : _l->k < _r->k);
}
-static inline void new_btree_iter_swap(void *iter1, void *iter2, void __always_unused *args)
-{
- struct btree_iter_set *_iter1 = iter1;
- struct btree_iter_set *_iter2 = iter2;
-
- swap(*_iter1, *_iter2);
-}
-
static struct bkey *bch_extent_sort_fixup(struct btree_iter *iter,
struct bkey *tmp)
{
const struct min_heap_callbacks callbacks = {
.less = new_bch_extent_sort_cmp,
- .swp = new_btree_iter_swap,
+ .swp = NULL,
};
while (iter->heap.nr > 1) {
struct btree_iter_set *top = iter->heap.data, *i = top + 1;
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 7f482729c56d..ef6abf33f926 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -190,14 +190,6 @@ static bool new_bucket_cmp(const void *l, const void *r, void __always_unused *a
return GC_SECTORS_USED(*_l) >= GC_SECTORS_USED(*_r);
}
-static void new_bucket_swap(void *l, void *r, void __always_unused *args)
-{
- struct bucket **_l = l;
- struct bucket **_r = r;
-
- swap(*_l, *_r);
-}
-
static unsigned int bucket_heap_top(struct cache *ca)
{
struct bucket *b;
@@ -212,7 +204,7 @@ void bch_moving_gc(struct cache_set *c)
unsigned long sectors_to_move, reserve_sectors;
const struct min_heap_callbacks callbacks = {
.less = new_bucket_cmp,
- .swp = new_bucket_swap,
+ .swp = NULL,
};
if (!c->copy_gc_enabled)
diff --git a/drivers/md/dm-bio-prison-v1.c b/drivers/md/dm-bio-prison-v1.c
index bca0f39e15b8..b4d1c4329df3 100644
--- a/drivers/md/dm-bio-prison-v1.c
+++ b/drivers/md/dm-bio-prison-v1.c
@@ -198,15 +198,6 @@ int dm_bio_detain(struct dm_bio_prison *prison,
}
EXPORT_SYMBOL_GPL(dm_bio_detain);
-int dm_get_cell(struct dm_bio_prison *prison,
- struct dm_cell_key *key,
- struct dm_bio_prison_cell *cell_prealloc,
- struct dm_bio_prison_cell **cell_result)
-{
- return bio_detain(prison, key, NULL, cell_prealloc, cell_result);
-}
-EXPORT_SYMBOL_GPL(dm_get_cell);
-
/*
* @inmates must have been initialised prior to this call
*/
@@ -288,32 +279,6 @@ void dm_cell_visit_release(struct dm_bio_prison *prison,
}
EXPORT_SYMBOL_GPL(dm_cell_visit_release);
-static int __promote_or_release(struct rb_root *root,
- struct dm_bio_prison_cell *cell)
-{
- if (bio_list_empty(&cell->bios)) {
- rb_erase(&cell->node, root);
- return 1;
- }
-
- cell->holder = bio_list_pop(&cell->bios);
- return 0;
-}
-
-int dm_cell_promote_or_release(struct dm_bio_prison *prison,
- struct dm_bio_prison_cell *cell)
-{
- int r;
- unsigned l = lock_nr(&cell->key, prison->num_locks);
-
- spin_lock_irq(&prison->regions[l].lock);
- r = __promote_or_release(&prison->regions[l].cell, cell);
- spin_unlock_irq(&prison->regions[l].lock);
-
- return r;
-}
-EXPORT_SYMBOL_GPL(dm_cell_promote_or_release);
-
/*----------------------------------------------------------------*/
#define DEFERRED_SET_SIZE 64
diff --git a/drivers/md/dm-bio-prison-v1.h b/drivers/md/dm-bio-prison-v1.h
index 2a097ed0d85e..d39706c48447 100644
--- a/drivers/md/dm-bio-prison-v1.h
+++ b/drivers/md/dm-bio-prison-v1.h
@@ -73,17 +73,6 @@ void dm_bio_prison_free_cell(struct dm_bio_prison *prison,
struct dm_bio_prison_cell *cell);
/*
- * Creates, or retrieves a cell that overlaps the given key.
- *
- * Returns 1 if pre-existing cell returned, zero if new cell created using
- * @cell_prealloc.
- */
-int dm_get_cell(struct dm_bio_prison *prison,
- struct dm_cell_key *key,
- struct dm_bio_prison_cell *cell_prealloc,
- struct dm_bio_prison_cell **cell_result);
-
-/*
* Returns false if key is beyond BIO_PRISON_MAX_RANGE or spans a boundary.
*/
bool dm_cell_key_has_valid_range(struct dm_cell_key *key);
@@ -117,19 +106,6 @@ void dm_cell_visit_release(struct dm_bio_prison *prison,
void (*visit_fn)(void *, struct dm_bio_prison_cell *),
void *context, struct dm_bio_prison_cell *cell);
-/*
- * Rather than always releasing the prisoners in a cell, the client may
- * want to promote one of them to be the new holder. There is a race here
- * though between releasing an empty cell, and other threads adding new
- * inmates. So this function makes the decision with its lock held.
- *
- * This function can have two outcomes:
- * i) An inmate is promoted to be the holder of the cell (return value of 0).
- * ii) The cell has no inmate for promotion and is released (return value of 1).
- */
-int dm_cell_promote_or_release(struct dm_bio_prison *prison,
- struct dm_bio_prison_cell *cell);
-
/*----------------------------------------------------------------*/
/*
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index d478aafa02c9..aab8240429b0 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -318,9 +318,10 @@ static struct lru_entry *lru_evict(struct lru *lru, le_predicate pred, void *con
*/
enum data_mode {
DATA_MODE_SLAB = 0,
- DATA_MODE_GET_FREE_PAGES = 1,
- DATA_MODE_VMALLOC = 2,
- DATA_MODE_LIMIT = 3
+ DATA_MODE_KMALLOC = 1,
+ DATA_MODE_GET_FREE_PAGES = 2,
+ DATA_MODE_VMALLOC = 3,
+ DATA_MODE_LIMIT = 4
};
struct dm_buffer {
@@ -1062,6 +1063,7 @@ static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
static unsigned long dm_bufio_peak_allocated;
static unsigned long dm_bufio_allocated_kmem_cache;
+static unsigned long dm_bufio_allocated_kmalloc;
static unsigned long dm_bufio_allocated_get_free_pages;
static unsigned long dm_bufio_allocated_vmalloc;
static unsigned long dm_bufio_current_allocated;
@@ -1104,6 +1106,7 @@ static void adjust_total_allocated(struct dm_buffer *b, bool unlink)
static unsigned long * const class_ptr[DATA_MODE_LIMIT] = {
&dm_bufio_allocated_kmem_cache,
+ &dm_bufio_allocated_kmalloc,
&dm_bufio_allocated_get_free_pages,
&dm_bufio_allocated_vmalloc,
};
@@ -1181,6 +1184,11 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
return kmem_cache_alloc(c->slab_cache, gfp_mask);
}
+ if (unlikely(c->block_size < PAGE_SIZE)) {
+ *data_mode = DATA_MODE_KMALLOC;
+ return kmalloc(c->block_size, gfp_mask | __GFP_RECLAIMABLE);
+ }
+
if (c->block_size <= KMALLOC_MAX_SIZE &&
gfp_mask & __GFP_NORETRY) {
*data_mode = DATA_MODE_GET_FREE_PAGES;
@@ -1204,6 +1212,10 @@ static void free_buffer_data(struct dm_bufio_client *c,
kmem_cache_free(c->slab_cache, data);
break;
+ case DATA_MODE_KMALLOC:
+ kfree(data);
+ break;
+
case DATA_MODE_GET_FREE_PAGES:
free_pages((unsigned long)data,
c->sectors_per_block_bits - (PAGE_SHIFT - SECTOR_SHIFT));
@@ -2471,7 +2483,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
int r;
unsigned int num_locks;
struct dm_bufio_client *c;
- char slab_name[27];
+ char slab_name[64];
+ static atomic_t seqno = ATOMIC_INIT(0);
if (!block_size || block_size & ((1 << SECTOR_SHIFT) - 1)) {
DMERR("%s: block size not specified or is not multiple of 512b", __func__);
@@ -2518,11 +2531,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
goto bad_dm_io;
}
- if (block_size <= KMALLOC_MAX_SIZE &&
- (block_size < PAGE_SIZE || !is_power_of_2(block_size))) {
+ if (block_size <= KMALLOC_MAX_SIZE && !is_power_of_2(block_size)) {
unsigned int align = min(1U << __ffs(block_size), (unsigned int)PAGE_SIZE);
- snprintf(slab_name, sizeof(slab_name), "dm_bufio_cache-%u", block_size);
+ snprintf(slab_name, sizeof(slab_name), "dm_bufio_cache-%u-%u",
+ block_size, atomic_inc_return(&seqno));
c->slab_cache = kmem_cache_create(slab_name, block_size, align,
SLAB_RECLAIM_ACCOUNT, NULL);
if (!c->slab_cache) {
@@ -2531,9 +2544,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
}
}
if (aux_size)
- snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer-%u", aux_size);
+ snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer-%u-%u",
+ aux_size, atomic_inc_return(&seqno));
else
- snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer");
+ snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer-%u",
+ atomic_inc_return(&seqno));
c->slab_buffer = kmem_cache_create(slab_name, sizeof(struct dm_buffer) + aux_size,
0, SLAB_RECLAIM_ACCOUNT, NULL);
if (!c->slab_buffer) {
@@ -2898,6 +2913,7 @@ static int __init dm_bufio_init(void)
__u64 mem;
dm_bufio_allocated_kmem_cache = 0;
+ dm_bufio_allocated_kmalloc = 0;
dm_bufio_allocated_get_free_pages = 0;
dm_bufio_allocated_vmalloc = 0;
dm_bufio_current_allocated = 0;
@@ -2986,6 +3002,9 @@ MODULE_PARM_DESC(peak_allocated_bytes, "Tracks the maximum allocated memory");
module_param_named(allocated_kmem_cache_bytes, dm_bufio_allocated_kmem_cache, ulong, 0444);
MODULE_PARM_DESC(allocated_kmem_cache_bytes, "Memory allocated with kmem_cache_alloc");
+module_param_named(allocated_kmalloc_bytes, dm_bufio_allocated_kmalloc, ulong, 0444);
+MODULE_PARM_DESC(allocated_kmalloc_bytes, "Memory allocated with kmalloc_alloc");
+
module_param_named(allocated_get_free_pages_bytes, dm_bufio_allocated_get_free_pages, ulong, 0444);
MODULE_PARM_DESC(allocated_get_free_pages_bytes, "Memory allocated with get_free_pages");
diff --git a/drivers/md/dm-cache-background-tracker.c b/drivers/md/dm-cache-background-tracker.c
index 9c5308298cf1..b4165f172d62 100644
--- a/drivers/md/dm-cache-background-tracker.c
+++ b/drivers/md/dm-cache-background-tracker.c
@@ -11,12 +11,6 @@
#define DM_MSG_PREFIX "dm-background-tracker"
-struct bt_work {
- struct list_head list;
- struct rb_node node;
- struct policy_work work;
-};
-
struct background_tracker {
unsigned int max_work;
atomic_t pending_promotes;
@@ -26,10 +20,10 @@ struct background_tracker {
struct list_head issued;
struct list_head queued;
struct rb_root pending;
-
- struct kmem_cache *work_cache;
};
+struct kmem_cache *btracker_work_cache = NULL;
+
struct background_tracker *btracker_create(unsigned int max_work)
{
struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL);
@@ -48,12 +42,6 @@ struct background_tracker *btracker_create(unsigned int max_work)
INIT_LIST_HEAD(&b->queued);
b->pending = RB_ROOT;
- b->work_cache = KMEM_CACHE(bt_work, 0);
- if (!b->work_cache) {
- DMERR("couldn't create mempool for background work items");
- kfree(b);
- b = NULL;
- }
return b;
}
@@ -66,10 +54,9 @@ void btracker_destroy(struct background_tracker *b)
BUG_ON(!list_empty(&b->issued));
list_for_each_entry_safe (w, tmp, &b->queued, list) {
list_del(&w->list);
- kmem_cache_free(b->work_cache, w);
+ kmem_cache_free(btracker_work_cache, w);
}
- kmem_cache_destroy(b->work_cache);
kfree(b);
}
EXPORT_SYMBOL_GPL(btracker_destroy);
@@ -156,12 +143,6 @@ static void update_stats(struct background_tracker *b, struct policy_work *w, in
}
}
-unsigned int btracker_nr_writebacks_queued(struct background_tracker *b)
-{
- return atomic_read(&b->pending_writebacks);
-}
-EXPORT_SYMBOL_GPL(btracker_nr_writebacks_queued);
-
unsigned int btracker_nr_demotions_queued(struct background_tracker *b)
{
return atomic_read(&b->pending_demotes);
@@ -180,7 +161,7 @@ static struct bt_work *alloc_work(struct background_tracker *b)
if (max_work_reached(b))
return NULL;
- return kmem_cache_alloc(b->work_cache, GFP_NOWAIT);
+ return kmem_cache_alloc(btracker_work_cache, GFP_NOWAIT);
}
int btracker_queue(struct background_tracker *b,
@@ -203,7 +184,7 @@ int btracker_queue(struct background_tracker *b,
* There was a race, we'll just ignore this second
* bit of work for the same oblock.
*/
- kmem_cache_free(b->work_cache, w);
+ kmem_cache_free(btracker_work_cache, w);
return -EINVAL;
}
@@ -244,7 +225,7 @@ void btracker_complete(struct background_tracker *b,
update_stats(b, &w->work, -1);
rb_erase(&w->node, &b->pending);
list_del(&w->list);
- kmem_cache_free(b->work_cache, w);
+ kmem_cache_free(btracker_work_cache, w);
}
EXPORT_SYMBOL_GPL(btracker_complete);
diff --git a/drivers/md/dm-cache-background-tracker.h b/drivers/md/dm-cache-background-tracker.h
index 5b8f5c667b81..47156c14a44a 100644
--- a/drivers/md/dm-cache-background-tracker.h
+++ b/drivers/md/dm-cache-background-tracker.h
@@ -26,6 +26,14 @@
* protected with a spinlock.
*/
+struct bt_work {
+ struct list_head list;
+ struct rb_node node;
+ struct policy_work work;
+};
+
+extern struct kmem_cache *btracker_work_cache;
+
struct background_work;
struct background_tracker;
@@ -42,7 +50,6 @@ struct background_tracker *btracker_create(unsigned int max_work);
*/
void btracker_destroy(struct background_tracker *b);
-unsigned int btracker_nr_writebacks_queued(struct background_tracker *b);
unsigned int btracker_nr_demotions_queued(struct background_tracker *b);
/*
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 24cd87fddf75..a9a1ab284076 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -1218,15 +1218,6 @@ int dm_cache_load_discards(struct dm_cache_metadata *cmd,
return r;
}
-int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result)
-{
- READ_LOCK(cmd);
- *result = cmd->cache_blocks;
- READ_UNLOCK(cmd);
-
- return 0;
-}
-
static int __remove(struct dm_cache_metadata *cmd, dm_cblock_t cblock)
{
int r;
@@ -1507,30 +1498,6 @@ int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
return r;
}
-static int __dump_mapping(void *context, uint64_t cblock, void *leaf)
-{
- __le64 value;
- dm_oblock_t oblock;
- unsigned int flags;
-
- memcpy(&value, leaf, sizeof(value));
- unpack_value(value, &oblock, &flags);
-
- return 0;
-}
-
-static int __dump_mappings(struct dm_cache_metadata *cmd)
-{
- return dm_array_walk(&cmd->info, cmd->root, __dump_mapping, NULL);
-}
-
-void dm_cache_dump(struct dm_cache_metadata *cmd)
-{
- READ_LOCK_VOID(cmd);
- __dump_mappings(cmd);
- READ_UNLOCK(cmd);
-}
-
int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd)
{
int r;
diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h
index 57afc7047947..5f77890207fe 100644
--- a/drivers/md/dm-cache-metadata.h
+++ b/drivers/md/dm-cache-metadata.h
@@ -71,7 +71,6 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd);
* origin blocks to map to.
*/
int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size);
-int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result);
int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
sector_t discard_block_size,
@@ -123,8 +122,6 @@ int dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd,
int dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd,
dm_block_t *result);
-void dm_cache_dump(struct dm_cache_metadata *cmd);
-
/*
* The policy is invited to save a 32bit hint value for every cblock (eg,
* for a hit count). These are stored against the policy name. If
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index aaeeabfab09b..9cb797a561d6 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -10,6 +10,7 @@
#include "dm-bio-record.h"
#include "dm-cache-metadata.h"
#include "dm-io-tracker.h"
+#include "dm-cache-background-tracker.h"
#include <linux/dm-io.h>
#include <linux/dm-kcopyd.h>
@@ -1905,16 +1906,13 @@ static void check_migrations(struct work_struct *ws)
* This function gets called on the error paths of the constructor, so we
* have to cope with a partially initialised struct.
*/
-static void destroy(struct cache *cache)
+static void __destroy(struct cache *cache)
{
- unsigned int i;
-
mempool_exit(&cache->migration_pool);
if (cache->prison)
dm_bio_prison_destroy_v2(cache->prison);
- cancel_delayed_work_sync(&cache->waker);
if (cache->wq)
destroy_workqueue(cache->wq);
@@ -1942,13 +1940,22 @@ static void destroy(struct cache *cache)
if (cache->policy)
dm_cache_policy_destroy(cache->policy);
+ bioset_exit(&cache->bs);
+
+ kfree(cache);
+}
+
+static void destroy(struct cache *cache)
+{
+ unsigned int i;
+
+ cancel_delayed_work_sync(&cache->waker);
+
for (i = 0; i < cache->nr_ctr_args ; i++)
kfree(cache->ctr_args[i]);
kfree(cache->ctr_args);
- bioset_exit(&cache->bs);
-
- kfree(cache);
+ __destroy(cache);
}
static void cache_dtr(struct dm_target *ti)
@@ -2003,7 +2010,6 @@ struct cache_args {
sector_t cache_sectors;
struct dm_dev *origin_dev;
- sector_t origin_sectors;
uint32_t block_size;
@@ -2084,6 +2090,7 @@ static int parse_cache_dev(struct cache_args *ca, struct dm_arg_set *as,
static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as,
char **error)
{
+ sector_t origin_sectors;
int r;
if (!at_least_one_arg(as, error))
@@ -2096,8 +2103,8 @@ static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as,
return r;
}
- ca->origin_sectors = get_dev_size(ca->origin_dev);
- if (ca->ti->len > ca->origin_sectors) {
+ origin_sectors = get_dev_size(ca->origin_dev);
+ if (ca->ti->len > origin_sectors) {
*error = "Device size larger than cached device";
return -EINVAL;
}
@@ -2257,7 +2264,7 @@ static int parse_cache_args(struct cache_args *ca, int argc, char **argv,
/*----------------------------------------------------------------*/
-static struct kmem_cache *migration_cache;
+static struct kmem_cache *migration_cache = NULL;
#define NOT_CORE_OPTION 1
@@ -2407,7 +2414,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
ca->metadata_dev = ca->origin_dev = ca->cache_dev = NULL;
- origin_blocks = cache->origin_sectors = ca->origin_sectors;
+ origin_blocks = cache->origin_sectors = ti->len;
origin_blocks = block_div(origin_blocks, ca->block_size);
cache->origin_blocks = to_oblock(origin_blocks);
@@ -2561,7 +2568,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
*result = cache;
return 0;
bad:
- destroy(cache);
+ __destroy(cache);
return r;
}
@@ -2612,7 +2619,7 @@ static int cache_ctr(struct dm_target *ti, unsigned int argc, char **argv)
r = copy_ctr_args(cache, argc - 3, (const char **)argv + 3);
if (r) {
- destroy(cache);
+ __destroy(cache);
goto out;
}
@@ -2895,19 +2902,19 @@ static dm_cblock_t get_cache_dev_size(struct cache *cache)
static bool can_resize(struct cache *cache, dm_cblock_t new_size)
{
if (from_cblock(new_size) > from_cblock(cache->cache_size)) {
- if (cache->sized) {
- DMERR("%s: unable to extend cache due to missing cache table reload",
- cache_device_name(cache));
- return false;
- }
+ DMERR("%s: unable to extend cache due to missing cache table reload",
+ cache_device_name(cache));
+ return false;
}
/*
* We can't drop a dirty block when shrinking the cache.
*/
- while (from_cblock(new_size) < from_cblock(cache->cache_size)) {
- new_size = to_cblock(from_cblock(new_size) + 1);
- if (is_dirty(cache, new_size)) {
+ if (cache->loaded_mappings) {
+ new_size = to_cblock(find_next_bit(cache->dirty_bitset,
+ from_cblock(cache->cache_size),
+ from_cblock(new_size)));
+ if (new_size != cache->cache_size) {
DMERR("%s: unable to shrink cache; cache block %llu is dirty",
cache_device_name(cache),
(unsigned long long) from_cblock(new_size));
@@ -2943,20 +2950,15 @@ static int cache_preresume(struct dm_target *ti)
/*
* Check to see if the cache has resized.
*/
- if (!cache->sized) {
- r = resize_cache_dev(cache, csize);
- if (r)
- return r;
-
- cache->sized = true;
-
- } else if (csize != cache->cache_size) {
+ if (!cache->sized || csize != cache->cache_size) {
if (!can_resize(cache, csize))
return -EINVAL;
r = resize_cache_dev(cache, csize);
if (r)
return r;
+
+ cache->sized = true;
}
if (!cache->loaded_mappings) {
@@ -3360,7 +3362,7 @@ static int cache_iterate_devices(struct dm_target *ti,
static void disable_passdown_if_not_supported(struct cache *cache)
{
struct block_device *origin_bdev = cache->origin_dev->bdev;
- struct queue_limits *origin_limits = &bdev_get_queue(origin_bdev)->limits;
+ struct queue_limits *origin_limits = bdev_limits(origin_bdev);
const char *reason = NULL;
if (!cache->features.discard_passdown)
@@ -3382,7 +3384,7 @@ static void disable_passdown_if_not_supported(struct cache *cache)
static void set_discard_limits(struct cache *cache, struct queue_limits *limits)
{
struct block_device *origin_bdev = cache->origin_dev->bdev;
- struct queue_limits *origin_limits = &bdev_get_queue(origin_bdev)->limits;
+ struct queue_limits *origin_limits = bdev_limits(origin_bdev);
if (!cache->features.discard_passdown) {
/* No passdown is done so setting own virtual limits */
@@ -3444,22 +3446,36 @@ static int __init dm_cache_init(void)
int r;
migration_cache = KMEM_CACHE(dm_cache_migration, 0);
- if (!migration_cache)
- return -ENOMEM;
+ if (!migration_cache) {
+ r = -ENOMEM;
+ goto err;
+ }
+
+ btracker_work_cache = kmem_cache_create("dm_cache_bt_work",
+ sizeof(struct bt_work), __alignof__(struct bt_work), 0, NULL);
+ if (!btracker_work_cache) {
+ r = -ENOMEM;
+ goto err;
+ }
r = dm_register_target(&cache_target);
if (r) {
- kmem_cache_destroy(migration_cache);
- return r;
+ goto err;
}
return 0;
+
+err:
+ kmem_cache_destroy(migration_cache);
+ kmem_cache_destroy(btracker_work_cache);
+ return r;
}
static void __exit dm_cache_exit(void)
{
dm_unregister_target(&cache_target);
kmem_cache_destroy(migration_cache);
+ kmem_cache_destroy(btracker_work_cache);
}
module_init(dm_cache_init);
diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c
index 12bbe487a4c8..e956d980672c 100644
--- a/drivers/md/dm-clone-target.c
+++ b/drivers/md/dm-clone-target.c
@@ -2020,7 +2020,7 @@ static void clone_resume(struct dm_target *ti)
static void disable_passdown_if_not_supported(struct clone *clone)
{
struct block_device *dest_dev = clone->dest_dev->bdev;
- struct queue_limits *dest_limits = &bdev_get_queue(dest_dev)->limits;
+ struct queue_limits *dest_limits = bdev_limits(dest_dev);
const char *reason = NULL;
if (!test_bit(DM_CLONE_DISCARD_PASSDOWN, &clone->flags))
@@ -2041,7 +2041,7 @@ static void disable_passdown_if_not_supported(struct clone *clone)
static void set_discard_limits(struct clone *clone, struct queue_limits *limits)
{
struct block_device *dest_bdev = clone->dest_dev->bdev;
- struct queue_limits *dest_limits = &bdev_get_queue(dest_bdev)->limits;
+ struct queue_limits *dest_limits = bdev_limits(dest_bdev);
if (!test_bit(DM_CLONE_DISCARD_PASSDOWN, &clone->flags)) {
/* No passdown is done so we set our own virtual limits */
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index f299ff393a6a..d42eac944eb5 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1912,7 +1912,7 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user,
if ((kernel_params->version[0] != DM_VERSION_MAJOR) ||
(kernel_params->version[1] > DM_VERSION_MINOR)) {
- DMERR("ioctl interface mismatch: kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
+ DMERR_LIMIT("ioctl interface mismatch: kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
DM_VERSION_MAJOR, DM_VERSION_MINOR,
DM_VERSION_PATCHLEVEL,
kernel_params->version[0],
@@ -1961,7 +1961,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
if (unlikely(param_kernel->data_size < minimum_data_size) ||
unlikely(param_kernel->data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS)) {
- DMERR("Invalid data size in the ioctl structure: %u",
+ DMERR_LIMIT("Invalid data size in the ioctl structure: %u",
param_kernel->data_size);
return -EINVAL;
}
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index dbd39b9722b9..bd8b796ae683 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1033,11 +1033,6 @@ struct dm_target *dm_table_get_wildcard_target(struct dm_table *t)
return NULL;
}
-bool dm_table_bio_based(struct dm_table *t)
-{
- return __table_type_bio_based(dm_table_get_type(t));
-}
-
bool dm_table_request_based(struct dm_table *t)
{
return __table_type_request_based(dm_table_get_type(t));
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 89632ce97760..bf0f9dddd146 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2484,6 +2484,7 @@ static void pool_work_wait(struct pool_work *pw, struct pool *pool,
init_completion(&pw->complete);
queue_work(pool->wq, &pw->worker);
wait_for_completion(&pw->complete);
+ destroy_work_on_stack(&pw->worker);
}
/*----------------------------------------------------------------*/
@@ -2842,7 +2843,7 @@ static void disable_discard_passdown_if_not_supported(struct pool_c *pt)
{
struct pool *pool = pt->pool;
struct block_device *data_bdev = pt->data_dev->bdev;
- struct queue_limits *data_limits = &bdev_get_queue(data_bdev)->limits;
+ struct queue_limits *data_limits = bdev_limits(data_bdev);
const char *reason = NULL;
if (!pt->adjusted_pf.discard_passdown)
diff --git a/drivers/md/dm-unstripe.c b/drivers/md/dm-unstripe.c
index 48587c16c445..e8a9432057dc 100644
--- a/drivers/md/dm-unstripe.c
+++ b/drivers/md/dm-unstripe.c
@@ -85,8 +85,8 @@ static int unstripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
uc->physical_start = start;
- uc->unstripe_offset = uc->unstripe * uc->chunk_size;
- uc->unstripe_width = (uc->stripes - 1) * uc->chunk_size;
+ uc->unstripe_offset = (sector_t)uc->unstripe * uc->chunk_size;
+ uc->unstripe_width = (sector_t)(uc->stripes - 1) * uc->chunk_size;
uc->chunk_shift = is_power_of_2(uc->chunk_size) ? fls(uc->chunk_size) - 1 : 0;
tmp_len = ti->len;
diff --git a/drivers/md/dm-vdo/Kconfig b/drivers/md/dm-vdo/Kconfig
index 111ecd2c2a24..2400b2bc4bc7 100644
--- a/drivers/md/dm-vdo/Kconfig
+++ b/drivers/md/dm-vdo/Kconfig
@@ -7,6 +7,7 @@ config DM_VDO
select DM_BUFIO
select LZ4_COMPRESS
select LZ4_DECOMPRESS
+ select MIN_HEAP
help
This device mapper target presents a block device with
deduplication, compression and thin-provisioning.
diff --git a/drivers/md/dm-vdo/block-map.c b/drivers/md/dm-vdo/block-map.c
index a0a7c1bd634e..89cb7942ec5c 100644
--- a/drivers/md/dm-vdo/block-map.c
+++ b/drivers/md/dm-vdo/block-map.c
@@ -209,8 +209,6 @@ static int initialize_info(struct vdo_page_cache *cache)
/**
* allocate_cache_components() - Allocate components of the cache which require their own
* allocation.
- * @maximum_age: The number of journal blocks before a dirtied page is considered old and must be
- * written out.
*
* The caller is responsible for all clean up on errors.
*
diff --git a/drivers/md/dm-vdo/data-vio.c b/drivers/md/dm-vdo/data-vio.c
index 0d502f6a86ad..810002747091 100644
--- a/drivers/md/dm-vdo/data-vio.c
+++ b/drivers/md/dm-vdo/data-vio.c
@@ -327,8 +327,9 @@ static u32 __must_check pack_status(struct data_vio_compression_status status)
/**
* set_data_vio_compression_status() - Set the compression status of a data_vio.
- * @state: The expected current status of the data_vio.
- * @new_state: The status to set.
+ * @data_vio: The data_vio to change.
+ * @status: The expected current status of the data_vio.
+ * @new_status: The status to set.
*
* Return: true if the new status was set, false if the data_vio's compression status did not
* match the expected state, and so was left unchanged.
@@ -836,7 +837,7 @@ static void destroy_data_vio(struct data_vio *data_vio)
* @vdo: The vdo to which the pool will belong.
* @pool_size: The number of data_vios in the pool.
* @discard_limit: The maximum number of data_vios which may be used for discards.
- * @pool: A pointer to hold the newly allocated pool.
+ * @pool_ptr: A pointer to hold the newly allocated pool.
*/
int make_data_vio_pool(struct vdo *vdo, data_vio_count_t pool_size,
data_vio_count_t discard_limit, struct data_vio_pool **pool_ptr)
@@ -1074,35 +1075,6 @@ void dump_data_vio_pool(struct data_vio_pool *pool, bool dump_vios)
spin_unlock(&pool->lock);
}
-data_vio_count_t get_data_vio_pool_active_discards(struct data_vio_pool *pool)
-{
- return READ_ONCE(pool->discard_limiter.busy);
-}
-
-data_vio_count_t get_data_vio_pool_discard_limit(struct data_vio_pool *pool)
-{
- return READ_ONCE(pool->discard_limiter.limit);
-}
-
-data_vio_count_t get_data_vio_pool_maximum_discards(struct data_vio_pool *pool)
-{
- return READ_ONCE(pool->discard_limiter.max_busy);
-}
-
-int set_data_vio_pool_discard_limit(struct data_vio_pool *pool, data_vio_count_t limit)
-{
- if (get_data_vio_pool_request_limit(pool) < limit) {
- // The discard limit may not be higher than the data_vio limit.
- return -EINVAL;
- }
-
- spin_lock(&pool->lock);
- pool->discard_limiter.limit = limit;
- spin_unlock(&pool->lock);
-
- return VDO_SUCCESS;
-}
-
data_vio_count_t get_data_vio_pool_active_requests(struct data_vio_pool *pool)
{
return READ_ONCE(pool->limiter.busy);
diff --git a/drivers/md/dm-vdo/data-vio.h b/drivers/md/dm-vdo/data-vio.h
index 25926b6cd98b..067b983bb291 100644
--- a/drivers/md/dm-vdo/data-vio.h
+++ b/drivers/md/dm-vdo/data-vio.h
@@ -336,11 +336,6 @@ void drain_data_vio_pool(struct data_vio_pool *pool, struct vdo_completion *comp
void resume_data_vio_pool(struct data_vio_pool *pool, struct vdo_completion *completion);
void dump_data_vio_pool(struct data_vio_pool *pool, bool dump_vios);
-data_vio_count_t get_data_vio_pool_active_discards(struct data_vio_pool *pool);
-data_vio_count_t get_data_vio_pool_discard_limit(struct data_vio_pool *pool);
-data_vio_count_t get_data_vio_pool_maximum_discards(struct data_vio_pool *pool);
-int __must_check set_data_vio_pool_discard_limit(struct data_vio_pool *pool,
- data_vio_count_t limit);
data_vio_count_t get_data_vio_pool_active_requests(struct data_vio_pool *pool);
data_vio_count_t get_data_vio_pool_request_limit(struct data_vio_pool *pool);
data_vio_count_t get_data_vio_pool_maximum_requests(struct data_vio_pool *pool);
diff --git a/drivers/md/dm-vdo/dedupe.c b/drivers/md/dm-vdo/dedupe.c
index 80628ae93fba..b6f8e2dc7729 100644
--- a/drivers/md/dm-vdo/dedupe.c
+++ b/drivers/md/dm-vdo/dedupe.c
@@ -565,7 +565,7 @@ static void wait_on_hash_lock(struct hash_lock *lock, struct data_vio *data_vio)
* @waiter: The data_vio's waiter link.
* @context: Not used.
*/
-static void abort_waiter(struct vdo_waiter *waiter, void *context __always_unused)
+static void abort_waiter(struct vdo_waiter *waiter, void __always_unused *context)
{
write_data_vio(vdo_waiter_as_data_vio(waiter));
}
@@ -1727,7 +1727,7 @@ static void report_bogus_lock_state(struct hash_lock *lock, struct data_vio *dat
/**
* vdo_continue_hash_lock() - Continue the processing state after writing, compressing, or
* deduplicating.
- * @data_vio: The data_vio to continue processing in its hash lock.
+ * @completion: The data_vio completion to continue processing in its hash lock.
*
* Asynchronously continue processing a data_vio in its hash lock after it has finished writing,
* compressing, or deduplicating, so it can share the result with any data_vios waiting in the hash
@@ -1825,7 +1825,7 @@ static inline int assert_hash_lock_preconditions(const struct data_vio *data_vio
/**
* vdo_acquire_hash_lock() - Acquire or share a lock on a record name.
- * @data_vio: The data_vio acquiring a lock on its record name.
+ * @completion: The data_vio completion acquiring a lock on its record name.
*
* Acquire or share a lock on the hash (record name) of the data in a data_vio, updating the
* data_vio to reference the lock. This must only be called in the correct thread for the zone. In
@@ -2679,7 +2679,8 @@ static void get_index_statistics(struct hash_zones *zones,
/**
* vdo_get_dedupe_statistics() - Tally the statistics from all the hash zones and the UDS index.
- * @hash_zones: The hash zones to query
+ * @zones: The hash zones to query
+ * @stats: A structure to store the statistics
*
* Return: The sum of the hash lock statistics from all hash zones plus the statistics from the UDS
* index
diff --git a/drivers/md/dm-vdo/encodings.c b/drivers/md/dm-vdo/encodings.c
index a34ea0229d53..100e92f8f866 100644
--- a/drivers/md/dm-vdo/encodings.c
+++ b/drivers/md/dm-vdo/encodings.c
@@ -858,7 +858,7 @@ static int __must_check make_partition(struct layout *layout, enum partition_id
/**
* vdo_initialize_layout() - Lay out the partitions of a vdo.
* @size: The entire size of the vdo.
- * @origin: The start of the layout on the underlying storage in blocks.
+ * @offset: The start of the layout on the underlying storage in blocks.
* @block_map_blocks: The size of the block map partition.
* @journal_blocks: The size of the journal partition.
* @summary_blocks: The size of the slab summary partition.
diff --git a/drivers/md/dm-vdo/indexer/index-layout.c b/drivers/md/dm-vdo/indexer/index-layout.c
index 627adc24af3b..af8fab83b0f3 100644
--- a/drivers/md/dm-vdo/indexer/index-layout.c
+++ b/drivers/md/dm-vdo/indexer/index-layout.c
@@ -248,32 +248,6 @@ static int __must_check compute_sizes(const struct uds_configuration *config,
return UDS_SUCCESS;
}
-int uds_compute_index_size(const struct uds_parameters *parameters, u64 *index_size)
-{
- int result;
- struct uds_configuration *index_config;
- struct save_layout_sizes sizes;
-
- if (index_size == NULL) {
- vdo_log_error("Missing output size pointer");
- return -EINVAL;
- }
-
- result = uds_make_configuration(parameters, &index_config);
- if (result != UDS_SUCCESS) {
- vdo_log_error_strerror(result, "cannot compute index size");
- return uds_status_to_errno(result);
- }
-
- result = compute_sizes(index_config, &sizes);
- uds_free_configuration(index_config);
- if (result != UDS_SUCCESS)
- return uds_status_to_errno(result);
-
- *index_size = sizes.total_size;
- return UDS_SUCCESS;
-}
-
/* Create unique data using the current time and a pseudorandom number. */
static void create_unique_nonce_data(u8 *buffer)
{
diff --git a/drivers/md/dm-vdo/indexer/indexer.h b/drivers/md/dm-vdo/indexer/indexer.h
index 3744aaf625b0..183a94eb7e92 100644
--- a/drivers/md/dm-vdo/indexer/indexer.h
+++ b/drivers/md/dm-vdo/indexer/indexer.h
@@ -283,10 +283,6 @@ struct uds_request {
enum uds_index_region location;
};
-/* Compute the number of bytes needed to store an index. */
-int __must_check uds_compute_index_size(const struct uds_parameters *parameters,
- u64 *index_size);
-
/* A session is required for most index operations. */
int __must_check uds_create_index_session(struct uds_index_session **session);
diff --git a/drivers/md/dm-vdo/int-map.c b/drivers/md/dm-vdo/int-map.c
index f6fe58e437b3..aeb690415dbd 100644
--- a/drivers/md/dm-vdo/int-map.c
+++ b/drivers/md/dm-vdo/int-map.c
@@ -70,7 +70,7 @@
* it's crucial to keep the hop fields near the buckets that they use them so they'll tend to share
* cache lines.
*/
-struct __packed bucket {
+struct bucket {
/**
* @first_hop: The biased offset of the first entry in the hop list of the neighborhood
* that hashes to this bucket.
@@ -82,7 +82,7 @@ struct __packed bucket {
u64 key;
/** @value: The value stored in this bucket (NULL if empty). */
void *value;
-};
+} __packed;
/**
* struct int_map - The concrete definition of the opaque int_map type.
@@ -310,7 +310,6 @@ static struct bucket *select_bucket(const struct int_map *map, u64 key)
/**
* search_hop_list() - Search the hop list associated with given hash bucket for a given search
* key.
- * @map: The map being searched.
* @bucket: The map bucket to search for the key.
* @key: The mapping key.
* @previous_ptr: Output. if not NULL, a pointer in which to store the bucket in the list preceding
@@ -321,9 +320,7 @@ static struct bucket *select_bucket(const struct int_map *map, u64 key)
*
* Return: An entry that matches the key, or NULL if not found.
*/
-static struct bucket *search_hop_list(struct int_map *map __always_unused,
- struct bucket *bucket,
- u64 key,
+static struct bucket *search_hop_list(struct bucket *bucket, u64 key,
struct bucket **previous_ptr)
{
struct bucket *previous = NULL;
@@ -357,7 +354,7 @@ static struct bucket *search_hop_list(struct int_map *map __always_unused,
*/
void *vdo_int_map_get(struct int_map *map, u64 key)
{
- struct bucket *match = search_hop_list(map, select_bucket(map, key), key, NULL);
+ struct bucket *match = search_hop_list(select_bucket(map, key), key, NULL);
return ((match != NULL) ? match->value : NULL);
}
@@ -443,7 +440,6 @@ find_empty_bucket(struct int_map *map, struct bucket *bucket, unsigned int max_p
/**
* move_empty_bucket() - Move an empty bucket closer to the start of the bucket array.
- * @map: The map containing the bucket.
* @hole: The empty bucket to fill with an entry that precedes it in one of its enclosing
* neighborhoods.
*
@@ -454,8 +450,7 @@ find_empty_bucket(struct int_map *map, struct bucket *bucket, unsigned int max_p
* Return: The bucket that was vacated by moving its entry to the provided hole, or NULL if no
* entry could be moved.
*/
-static struct bucket *move_empty_bucket(struct int_map *map __always_unused,
- struct bucket *hole)
+static struct bucket *move_empty_bucket(struct bucket *hole)
{
/*
* Examine every neighborhood that the empty bucket is part of, starting with the one in
@@ -516,7 +511,6 @@ static struct bucket *move_empty_bucket(struct int_map *map __always_unused,
/**
* update_mapping() - Find and update any existing mapping for a given key, returning the value
* associated with the key in the provided pointer.
- * @map: The int_map to attempt to modify.
* @neighborhood: The first bucket in the neighborhood that would contain the search key
* @key: The key with which to associate the new value.
* @new_value: The value to be associated with the key.
@@ -525,10 +519,10 @@ static struct bucket *move_empty_bucket(struct int_map *map __always_unused,
*
* Return: true if the map contains a mapping for the key, false if it does not.
*/
-static bool update_mapping(struct int_map *map, struct bucket *neighborhood,
- u64 key, void *new_value, bool update, void **old_value_ptr)
+static bool update_mapping(struct bucket *neighborhood, u64 key, void *new_value,
+ bool update, void **old_value_ptr)
{
- struct bucket *bucket = search_hop_list(map, neighborhood, key, NULL);
+ struct bucket *bucket = search_hop_list(neighborhood, key, NULL);
if (bucket == NULL) {
/* There is no bucket containing the key in the neighborhood. */
@@ -584,7 +578,7 @@ static struct bucket *find_or_make_vacancy(struct int_map *map,
* The nearest empty bucket isn't within the neighborhood that must contain the new
* entry, so try to swap it with bucket that is closer.
*/
- hole = move_empty_bucket(map, hole);
+ hole = move_empty_bucket(hole);
}
return NULL;
@@ -625,7 +619,7 @@ int vdo_int_map_put(struct int_map *map, u64 key, void *new_value, bool update,
* Check whether the neighborhood already contains an entry for the key, in which case we
* optionally update it, returning the old value.
*/
- if (update_mapping(map, neighborhood, key, new_value, update, old_value_ptr))
+ if (update_mapping(neighborhood, key, new_value, update, old_value_ptr))
return VDO_SUCCESS;
/*
@@ -679,7 +673,7 @@ void *vdo_int_map_remove(struct int_map *map, u64 key)
/* Select the bucket to search and search it for an existing entry. */
struct bucket *bucket = select_bucket(map, key);
struct bucket *previous;
- struct bucket *victim = search_hop_list(map, bucket, key, &previous);
+ struct bucket *victim = search_hop_list(bucket, key, &previous);
if (victim == NULL) {
/* There is no matching entry to remove. */
diff --git a/drivers/md/dm-vdo/io-submitter.c b/drivers/md/dm-vdo/io-submitter.c
index ab62abe18827..421e5436c32c 100644
--- a/drivers/md/dm-vdo/io-submitter.c
+++ b/drivers/md/dm-vdo/io-submitter.c
@@ -367,7 +367,7 @@ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
* completions.
* @max_requests_active: Number of bios for merge tracking.
* @vdo: The vdo which will use this submitter.
- * @io_submitter: pointer to the new data structure.
+ * @io_submitter_ptr: pointer to the new data structure.
*
* Return: VDO_SUCCESS or an error.
*/
diff --git a/drivers/md/dm-vdo/murmurhash3.c b/drivers/md/dm-vdo/murmurhash3.c
index 13008b089206..b0b0587d85f3 100644
--- a/drivers/md/dm-vdo/murmurhash3.c
+++ b/drivers/md/dm-vdo/murmurhash3.c
@@ -44,14 +44,11 @@ void murmurhash3_128(const void *key, const int len, const u32 seed, void *out)
u64 *hash_out = out;
/* body */
-
- const u64 *blocks = (const u64 *)(data);
-
int i;
for (i = 0; i < nblocks; i++) {
- u64 k1 = get_unaligned_le64(&blocks[i * 2]);
- u64 k2 = get_unaligned_le64(&blocks[i * 2 + 1]);
+ u64 k1 = get_unaligned_le64(&data[i * 16]);
+ u64 k2 = get_unaligned_le64(&data[i * 16 + 8]);
k1 *= c1;
k1 = ROTL64(k1, 31);
diff --git a/drivers/md/dm-vdo/packer.c b/drivers/md/dm-vdo/packer.c
index 16cf29b4c90a..f70f5edabc10 100644
--- a/drivers/md/dm-vdo/packer.c
+++ b/drivers/md/dm-vdo/packer.c
@@ -250,7 +250,6 @@ static void abort_packing(struct data_vio *data_vio)
/**
* release_compressed_write_waiter() - Update a data_vio for which a successful compressed write
* has completed and send it on its way.
-
* @data_vio: The data_vio to release.
* @allocation: The allocation to which the compressed block was written.
*/
@@ -383,7 +382,7 @@ static void initialize_compressed_block(struct compressed_block *block, u16 size
* @compression: The agent's compression_state to pack in to.
* @data_vio: The data_vio to pack.
* @offset: The offset into the compressed block at which to pack the fragment.
- * @compressed_block: The compressed block which will be written out when batch is fully packed.
+ * @block: The compressed block which will be written out when batch is fully packed.
*
* Return: The new amount of space used.
*/
diff --git a/drivers/md/dm-vdo/physical-zone.c b/drivers/md/dm-vdo/physical-zone.c
index 2fee3a7c1191..a43b5c45fab7 100644
--- a/drivers/md/dm-vdo/physical-zone.c
+++ b/drivers/md/dm-vdo/physical-zone.c
@@ -517,7 +517,7 @@ static int allocate_and_lock_block(struct allocation *allocation)
* @waiter: The allocating_vio that was waiting to allocate.
* @context: The context (unused).
*/
-static void retry_allocation(struct vdo_waiter *waiter, void *context __always_unused)
+static void retry_allocation(struct vdo_waiter *waiter, void __always_unused *context)
{
struct data_vio *data_vio = vdo_waiter_as_data_vio(waiter);
diff --git a/drivers/md/dm-vdo/recovery-journal.c b/drivers/md/dm-vdo/recovery-journal.c
index ee6321a3e523..de58184f538f 100644
--- a/drivers/md/dm-vdo/recovery-journal.c
+++ b/drivers/md/dm-vdo/recovery-journal.c
@@ -1365,7 +1365,7 @@ static void add_queued_recovery_entries(struct recovery_journal_block *block)
*
* Implements waiter_callback_fn.
*/
-static void write_block(struct vdo_waiter *waiter, void *context __always_unused)
+static void write_block(struct vdo_waiter *waiter, void __always_unused *context)
{
struct recovery_journal_block *block =
container_of(waiter, struct recovery_journal_block, write_waiter);
diff --git a/drivers/md/dm-vdo/repair.c b/drivers/md/dm-vdo/repair.c
index ffff2c999518..8c006fb3afcf 100644
--- a/drivers/md/dm-vdo/repair.c
+++ b/drivers/md/dm-vdo/repair.c
@@ -166,7 +166,7 @@ static void swap_mappings(void *item1, void *item2, void __always_unused *args)
static const struct min_heap_callbacks repair_min_heap = {
.less = mapping_is_less_than,
- .swp = swap_mappings,
+ .swp = NULL,
};
static struct numbered_block_mapping *sort_next_heap_element(struct repair_completion *repair)
diff --git a/drivers/md/dm-vdo/slab-depot.c b/drivers/md/dm-vdo/slab-depot.c
index 274f9ccd072f..8f0a35c63af6 100644
--- a/drivers/md/dm-vdo/slab-depot.c
+++ b/drivers/md/dm-vdo/slab-depot.c
@@ -1287,7 +1287,7 @@ static struct reference_block * __must_check get_reference_block(struct vdo_slab
* slab_block_number_from_pbn() - Determine the index within the slab of a particular physical
* block number.
* @slab: The slab.
- * @physical_block_number: The physical block number.
+ * @pbn: The physical block number.
* @slab_block_number_ptr: A pointer to the slab block number.
*
* Return: VDO_SUCCESS or an error code.
@@ -1459,7 +1459,6 @@ static int increment_for_data(struct vdo_slab *slab, struct reference_block *blo
* @block_number: The block to update.
* @old_status: The reference status of the data block before this decrement.
* @updater: The reference updater doing this operation in case we need to look up the pbn lock.
- * @lock: The pbn_lock associated with the block being decremented (may be NULL).
* @counter_ptr: A pointer to the count for the data block (in, out).
* @adjust_block_count: Whether to update the allocator's free block count.
*
@@ -3232,8 +3231,7 @@ int vdo_enqueue_clean_slab_waiter(struct block_allocator *allocator,
/**
* vdo_modify_reference_count() - Modify the reference count of a block by first making a slab
* journal entry and then updating the reference counter.
- *
- * @data_vio: The data_vio for which to add the entry.
+ * @completion: The data_vio completion for which to add the entry.
* @updater: Which of the data_vio's reference updaters is being submitted.
*/
void vdo_modify_reference_count(struct vdo_completion *completion,
@@ -3301,17 +3299,9 @@ static bool slab_status_is_less_than(const void *item1, const void *item2,
return info1->slab_number < info2->slab_number;
}
-static void swap_slab_statuses(void *item1, void *item2, void __always_unused *args)
-{
- struct slab_status *info1 = item1;
- struct slab_status *info2 = item2;
-
- swap(*info1, *info2);
-}
-
static const struct min_heap_callbacks slab_status_min_heap = {
.less = slab_status_is_less_than,
- .swp = swap_slab_statuses,
+ .swp = NULL,
};
/* Inform the slab actor that a action has finished on some slab; used by apply_to_slabs(). */
@@ -4750,8 +4740,7 @@ void vdo_use_new_slabs(struct slab_depot *depot, struct vdo_completion *parent)
/**
* stop_scrubbing() - Tell the scrubber to stop scrubbing after it finishes the slab it is
* currently working on.
- * @scrubber: The scrubber to stop.
- * @parent: The completion to notify when scrubbing has stopped.
+ * @allocator: The block allocator owning the scrubber to stop.
*/
static void stop_scrubbing(struct block_allocator *allocator)
{
diff --git a/drivers/md/dm-vdo/vdo.c b/drivers/md/dm-vdo/vdo.c
index fff847767755..a7e32baab4af 100644
--- a/drivers/md/dm-vdo/vdo.c
+++ b/drivers/md/dm-vdo/vdo.c
@@ -643,7 +643,7 @@ static void finish_vdo(struct vdo *vdo)
/**
* free_listeners() - Free the list of read-only listeners associated with a thread.
- * @thread_data: The thread holding the list to free.
+ * @thread: The thread holding the list to free.
*/
static void free_listeners(struct vdo_thread *thread)
{
@@ -852,7 +852,7 @@ int vdo_synchronous_flush(struct vdo *vdo)
/**
* vdo_get_state() - Get the current state of the vdo.
* @vdo: The vdo.
-
+ *
* Context: This method may be called from any thread.
*
* Return: The current state of the vdo.
diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c
index b291578f726f..e710f3c5a972 100644
--- a/drivers/md/dm-vdo/vio.c
+++ b/drivers/md/dm-vdo/vio.c
@@ -202,6 +202,7 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
if (data == NULL)
return VDO_SUCCESS;
+ bio->bi_ioprio = 0;
bio->bi_io_vec = bio->bi_inline_vecs;
bio->bi_max_vecs = vio->block_count + 1;
len = VDO_BLOCK_SIZE * vio->block_count;
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index 7d4d90b4395a..47d595f6a76e 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -93,7 +93,7 @@ static void dm_bufio_alloc_callback(struct dm_buffer *buf)
*/
static sector_t verity_map_sector(struct dm_verity *v, sector_t bi_sector)
{
- return v->data_start + dm_target_offset(v->ti, bi_sector);
+ return dm_target_offset(v->ti, bi_sector);
}
/*
@@ -356,9 +356,9 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
else if (verity_handle_err(v,
DM_VERITY_BLOCK_TYPE_METADATA,
hash_block)) {
- struct bio *bio =
- dm_bio_from_per_bio_data(io,
- v->ti->per_io_data_size);
+ struct bio *bio;
+ io->had_mismatch = true;
+ bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
dm_audit_log_bio(DM_MSG_PREFIX, "verify-metadata", bio,
block, 0);
r = -EIO;
@@ -482,6 +482,7 @@ static int verity_handle_data_hash_mismatch(struct dm_verity *v,
return -EIO; /* Error correction failed; Just return error */
if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA, blkno)) {
+ io->had_mismatch = true;
dm_audit_log_bio(DM_MSG_PREFIX, "verify-data", bio, blkno, 0);
return -EIO;
}
@@ -606,6 +607,7 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
if (unlikely(status != BLK_STS_OK) &&
unlikely(!(bio->bi_opf & REQ_RAHEAD)) &&
+ !io->had_mismatch &&
!verity_is_system_shutting_down()) {
if (v->error_mode == DM_VERITY_MODE_PANIC) {
panic("dm-verity device has I/O error");
@@ -779,6 +781,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
io->orig_bi_end_io = bio->bi_end_io;
io->block = bio->bi_iter.bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT);
io->n_blocks = bio->bi_iter.bi_size >> v->data_dev_block_bits;
+ io->had_mismatch = false;
bio->bi_end_io = verity_end_io;
bio->bi_private = io;
@@ -949,7 +952,7 @@ static int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
*bdev = v->data_dev->bdev;
- if (v->data_start || ti->len != bdev_nr_sectors(v->data_dev->bdev))
+ if (ti->len != bdev_nr_sectors(v->data_dev->bdev))
return 1;
return 0;
}
@@ -959,7 +962,7 @@ static int verity_iterate_devices(struct dm_target *ti,
{
struct dm_verity *v = ti->private;
- return fn(ti, v->data_dev, v->data_start, ti->len, data);
+ return fn(ti, v->data_dev, 0, ti->len, data);
}
static void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h
index 6b75159bf835..8cbb57862ae1 100644
--- a/drivers/md/dm-verity.h
+++ b/drivers/md/dm-verity.h
@@ -50,7 +50,6 @@ struct dm_verity {
unsigned int sig_size; /* root digest signature size */
#endif /* CONFIG_SECURITY */
unsigned int salt_size;
- sector_t data_start; /* data offset in 512-byte sectors */
sector_t hash_start; /* hash start in blocks */
sector_t data_blocks; /* the number of data blocks */
sector_t hash_blocks; /* the number of hash blocks */
@@ -92,6 +91,7 @@ struct dm_verity_io {
sector_t block;
unsigned int n_blocks;
bool in_bh;
+ bool had_mismatch;
struct work_struct work;
struct work_struct bh_work;
diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
index c0d41c36e06e..20edd3fabbab 100644
--- a/drivers/md/dm-zone.c
+++ b/drivers/md/dm-zone.c
@@ -344,7 +344,7 @@ int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
} else {
set_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
- lim->max_zone_append_sectors = 0;
+ lim->max_hw_zone_append_sectors = 0;
}
/*
@@ -379,7 +379,7 @@ int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
if (!zlim.mapped_nr_seq_zones) {
lim->max_open_zones = 0;
lim->max_active_zones = 0;
- lim->max_zone_append_sectors = 0;
+ lim->max_hw_zone_append_sectors = 0;
lim->zone_write_granularity = 0;
lim->chunk_sectors = 0;
lim->features &= ~BLK_FEAT_ZONED;
diff --git a/drivers/md/dm-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c
index 8156881a31de..deff22ecccbb 100644
--- a/drivers/md/dm-zoned-metadata.c
+++ b/drivers/md/dm-zoned-metadata.c
@@ -245,11 +245,6 @@ unsigned int dmz_zone_nr_blocks(struct dmz_metadata *zmd)
return zmd->zone_nr_blocks;
}
-unsigned int dmz_zone_nr_blocks_shift(struct dmz_metadata *zmd)
-{
- return zmd->zone_nr_blocks_shift;
-}
-
unsigned int dmz_zone_nr_sectors(struct dmz_metadata *zmd)
{
return zmd->zone_nr_sectors;
@@ -3005,48 +3000,3 @@ void dmz_dtr_metadata(struct dmz_metadata *zmd)
dmz_cleanup_metadata(zmd);
kfree(zmd);
}
-
-/*
- * Check zone information on resume.
- */
-int dmz_resume_metadata(struct dmz_metadata *zmd)
-{
- struct dm_zone *zone;
- sector_t wp_block;
- unsigned int i;
- int ret;
-
- /* Check zones */
- for (i = 0; i < zmd->nr_zones; i++) {
- zone = dmz_get(zmd, i);
- if (!zone) {
- dmz_zmd_err(zmd, "Unable to get zone %u", i);
- return -EIO;
- }
- wp_block = zone->wp_block;
-
- ret = dmz_update_zone(zmd, zone);
- if (ret) {
- dmz_zmd_err(zmd, "Broken zone %u", i);
- return ret;
- }
-
- if (dmz_is_offline(zone)) {
- dmz_zmd_warn(zmd, "Zone %u is offline", i);
- continue;
- }
-
- /* Check write pointer */
- if (!dmz_is_seq(zone))
- zone->wp_block = 0;
- else if (zone->wp_block != wp_block) {
- dmz_zmd_err(zmd, "Zone %u: Invalid wp (%llu / %llu)",
- i, (u64)zone->wp_block, (u64)wp_block);
- zone->wp_block = wp_block;
- dmz_invalidate_blocks(zmd, zone, zone->wp_block,
- zmd->zone_nr_blocks - zone->wp_block);
- }
- }
-
- return 0;
-}
diff --git a/drivers/md/dm-zoned.h b/drivers/md/dm-zoned.h
index 265494d3f711..59ba0aaa9531 100644
--- a/drivers/md/dm-zoned.h
+++ b/drivers/md/dm-zoned.h
@@ -192,7 +192,6 @@ enum {
int dmz_ctr_metadata(struct dmz_dev *dev, int num_dev,
struct dmz_metadata **zmd, const char *devname);
void dmz_dtr_metadata(struct dmz_metadata *zmd);
-int dmz_resume_metadata(struct dmz_metadata *zmd);
void dmz_lock_map(struct dmz_metadata *zmd);
void dmz_unlock_map(struct dmz_metadata *zmd);
@@ -230,7 +229,6 @@ unsigned int dmz_nr_unmap_rnd_zones(struct dmz_metadata *zmd, int idx);
unsigned int dmz_nr_seq_zones(struct dmz_metadata *zmd, int idx);
unsigned int dmz_nr_unmap_seq_zones(struct dmz_metadata *zmd, int idx);
unsigned int dmz_zone_nr_blocks(struct dmz_metadata *zmd);
-unsigned int dmz_zone_nr_blocks_shift(struct dmz_metadata *zmd);
unsigned int dmz_zone_nr_sectors(struct dmz_metadata *zmd);
unsigned int dmz_zone_nr_sectors_shift(struct dmz_metadata *zmd);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ff4a6b570b76..12ecf07a3841 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -2290,8 +2290,10 @@ static struct mapped_device *alloc_dev(int minor)
* override accordingly.
*/
md->disk = blk_alloc_disk(NULL, md->numa_node_id);
- if (IS_ERR(md->disk))
+ if (IS_ERR(md->disk)) {
+ md->disk = NULL;
goto bad;
+ }
md->queue = md->disk->queue;
init_waitqueue_head(&md->wait);
@@ -2515,12 +2517,6 @@ void dm_unlock_md_type(struct mapped_device *md)
mutex_unlock(&md->type_lock);
}
-void dm_set_md_type(struct mapped_device *md, enum dm_queue_mode type)
-{
- BUG_ON(!mutex_is_locked(&md->type_lock));
- md->type = type;
-}
-
enum dm_queue_mode dm_get_md_type(struct mapped_device *md)
{
return md->type;
@@ -3347,6 +3343,59 @@ void dm_free_md_mempools(struct dm_md_mempools *pools)
kfree(pools);
}
+struct dm_blkdev_id {
+ u8 *id;
+ enum blk_unique_id type;
+};
+
+static int __dm_get_unique_id(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct dm_blkdev_id *dm_id = data;
+ const struct block_device_operations *fops = dev->bdev->bd_disk->fops;
+
+ if (!fops->get_unique_id)
+ return 0;
+
+ return fops->get_unique_id(dev->bdev->bd_disk, dm_id->id, dm_id->type);
+}
+
+/*
+ * Allow access to get_unique_id() for the first device returning a
+ * non-zero result. Reasonable use expects all devices to have the
+ * same unique id.
+ */
+static int dm_blk_get_unique_id(struct gendisk *disk, u8 *id,
+ enum blk_unique_id type)
+{
+ struct mapped_device *md = disk->private_data;
+ struct dm_table *table;
+ struct dm_target *ti;
+ int ret = 0, srcu_idx;
+
+ struct dm_blkdev_id dm_id = {
+ .id = id,
+ .type = type,
+ };
+
+ table = dm_get_live_table(md, &srcu_idx);
+ if (!table || !dm_table_get_size(table))
+ goto out;
+
+ /* We only support devices that have a single target */
+ if (table->num_targets != 1)
+ goto out;
+ ti = dm_table_get_target(table, 0);
+
+ if (!ti->type->iterate_devices)
+ goto out;
+
+ ret = ti->type->iterate_devices(ti, __dm_get_unique_id, &dm_id);
+out:
+ dm_put_live_table(md, srcu_idx);
+ return ret;
+}
+
struct dm_pr {
u64 old_key;
u64 new_key;
@@ -3672,6 +3721,7 @@ static const struct block_device_operations dm_blk_dops = {
.ioctl = dm_blk_ioctl,
.getgeo = dm_blk_getgeo,
.report_zones = dm_blk_report_zones,
+ .get_unique_id = dm_blk_get_unique_id,
.pr_ops = &dm_pr_ops,
.owner = THIS_MODULE
};
@@ -3681,6 +3731,7 @@ static const struct block_device_operations dm_rq_blk_dops = {
.release = dm_blk_close,
.ioctl = dm_blk_ioctl,
.getgeo = dm_blk_getgeo,
+ .get_unique_id = dm_blk_get_unique_id,
.pr_ops = &dm_pr_ops,
.owner = THIS_MODULE
};
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 8ad782249af8..a0a8ff119815 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -71,12 +71,10 @@ enum dm_queue_mode dm_table_get_type(struct dm_table *t);
struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
struct dm_target *dm_table_get_immutable_target(struct dm_table *t);
struct dm_target *dm_table_get_wildcard_target(struct dm_table *t);
-bool dm_table_bio_based(struct dm_table *t);
bool dm_table_request_based(struct dm_table *t);
void dm_lock_md_type(struct mapped_device *md);
void dm_unlock_md_type(struct mapped_device *md);
-void dm_set_md_type(struct mapped_device *md, enum dm_queue_mode type);
enum dm_queue_mode dm_get_md_type(struct mapped_device *md);
struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 29da10e6f703..c3a42dd66ce5 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -1285,6 +1285,7 @@ static void bitmap_unplug_async(struct bitmap *bitmap)
queue_work(md_bitmap_wq, &unplug_work.work);
wait_for_completion(&done);
+ destroy_work_on_stack(&unplug_work.work);
}
static void bitmap_unplug(struct mddev *mddev, bool sync)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 67108c397c5a..aebe12b0ee27 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9784,9 +9784,7 @@ EXPORT_SYMBOL(md_reap_sync_thread);
void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
sysfs_notify_dirent_safe(rdev->sysfs_state);
- wait_event_timeout(rdev->blocked_wait,
- !test_bit(Blocked, &rdev->flags) &&
- !test_bit(BlockedBadBlocks, &rdev->flags),
+ wait_event_timeout(rdev->blocked_wait, !rdev_blocked(rdev),
msecs_to_jiffies(5000));
rdev_dec_pending(rdev, mddev);
}
@@ -9815,6 +9813,17 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
{
struct mddev *mddev = rdev->mddev;
int rv;
+
+ /*
+ * Recording new badblocks for faulty rdev will force unnecessary
+ * super block updating. This is fragile for external management because
+ * userspace daemon may trying to remove this device and deadlock may
+ * occur. This will be probably solved in the mdadm, but it is safer to
+ * avoid it.
+ */
+ if (test_bit(Faulty, &rdev->flags))
+ return 1;
+
if (is_new)
s += rdev->new_data_offset;
else
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 5d2e6bd58e4d..4ba93af36126 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -1002,6 +1002,30 @@ static inline void mddev_trace_remap(struct mddev *mddev, struct bio *bio,
trace_block_bio_remap(bio, disk_devt(mddev->gendisk), sector);
}
+static inline bool rdev_blocked(struct md_rdev *rdev)
+{
+ /*
+ * Blocked will be set by error handler and cleared by daemon after
+ * updating superblock, meanwhile write IO should be blocked to prevent
+ * reading old data after power failure.
+ */
+ if (test_bit(Blocked, &rdev->flags))
+ return true;
+
+ /*
+ * Faulty device should not be accessed anymore, there is no need to
+ * wait for bad block to be acknowledged.
+ */
+ if (test_bit(Faulty, &rdev->flags))
+ return false;
+
+ /* rdev is blocked by badblocks. */
+ if (test_bit(BlockedBadBlocks, &rdev->flags))
+ return true;
+
+ return false;
+}
+
#define mddev_add_trace_msg(mddev, fmt, args...) \
do { \
if (!mddev_is_dm(mddev)) \
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
index 3a19124ee279..22a551c407da 100644
--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -51,7 +51,7 @@ static int index_check(const struct dm_block_validator *v,
block_size - sizeof(__le32),
INDEX_CSUM_XOR));
if (csum_disk != mi_le->csum) {
- DMERR_LIMIT("i%s failed: csum %u != wanted %u", __func__,
+ DMERR_LIMIT("%s failed: csum %u != wanted %u", __func__,
le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
return -EILSEQ;
}
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 32d587524778..7049ec7fb8eb 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -384,6 +384,7 @@ static int raid0_set_limits(struct mddev *mddev)
lim.max_write_zeroes_sectors = mddev->chunk_sectors;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * mddev->raid_disks;
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
@@ -466,6 +467,12 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
struct bio *split = bio_split(bio,
zone->zone_end - bio->bi_iter.bi_sector, GFP_NOIO,
&mddev->bio_set);
+
+ if (IS_ERR(split)) {
+ bio->bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_endio(bio);
+ return;
+ }
bio_chain(split, bio);
submit_bio_noacct(bio);
bio = split;
@@ -608,6 +615,12 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
if (sectors < bio_sectors(bio)) {
struct bio *split = bio_split(bio, sectors, GFP_NOIO,
&mddev->bio_set);
+
+ if (IS_ERR(split)) {
+ bio->bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_endio(bio);
+ return true;
+ }
bio_chain(split, bio);
raid0_map_submit_bio(mddev, bio);
bio = split;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 6c9d24203f39..519c56f0ee3d 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1322,7 +1322,7 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio,
const enum req_op op = bio_op(bio);
const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC;
int max_sectors;
- int rdisk;
+ int rdisk, error;
bool r1bio_existed = !!r1_bio;
/*
@@ -1383,6 +1383,11 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio,
if (max_sectors < bio_sectors(bio)) {
struct bio *split = bio_split(bio, max_sectors,
gfp, &conf->bio_split);
+
+ if (IS_ERR(split)) {
+ error = PTR_ERR(split);
+ goto err_handle;
+ }
bio_chain(split, bio);
submit_bio_noacct(bio);
bio = split;
@@ -1410,6 +1415,47 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio,
read_bio->bi_private = r1_bio;
mddev_trace_remap(mddev, read_bio, r1_bio->sector);
submit_bio_noacct(read_bio);
+ return;
+
+err_handle:
+ atomic_dec(&mirror->rdev->nr_pending);
+ bio->bi_status = errno_to_blk_status(error);
+ set_bit(R1BIO_Uptodate, &r1_bio->state);
+ raid_end_bio_io(r1_bio);
+}
+
+static bool wait_blocked_rdev(struct mddev *mddev, struct bio *bio)
+{
+ struct r1conf *conf = mddev->private;
+ int disks = conf->raid_disks * 2;
+ int i;
+
+retry:
+ for (i = 0; i < disks; i++) {
+ struct md_rdev *rdev = conf->mirrors[i].rdev;
+
+ if (!rdev)
+ continue;
+
+ /* don't write here until the bad block is acknowledged */
+ if (test_bit(WriteErrorSeen, &rdev->flags) &&
+ rdev_has_badblock(rdev, bio->bi_iter.bi_sector,
+ bio_sectors(bio)) < 0)
+ set_bit(BlockedBadBlocks, &rdev->flags);
+
+ if (rdev_blocked(rdev)) {
+ if (bio->bi_opf & REQ_NOWAIT)
+ return false;
+
+ mddev_add_trace_msg(rdev->mddev, "raid1 wait rdev %d blocked",
+ rdev->raid_disk);
+ atomic_inc(&rdev->nr_pending);
+ md_wait_for_blocked_rdev(rdev, rdev->mddev);
+ goto retry;
+ }
+ }
+
+ return true;
}
static void raid1_write_request(struct mddev *mddev, struct bio *bio,
@@ -1417,9 +1463,8 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
{
struct r1conf *conf = mddev->private;
struct r1bio *r1_bio;
- int i, disks;
+ int i, disks, k, error;
unsigned long flags;
- struct md_rdev *blocked_rdev;
int first_clone;
int max_sectors;
bool write_behind = false;
@@ -1457,7 +1502,11 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
return;
}
- retry_write:
+ if (!wait_blocked_rdev(mddev, bio)) {
+ bio_wouldblock_error(bio);
+ return;
+ }
+
r1_bio = alloc_r1bio(mddev, bio);
r1_bio->sectors = max_write_sectors;
@@ -1473,7 +1522,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
*/
disks = conf->raid_disks * 2;
- blocked_rdev = NULL;
max_sectors = r1_bio->sectors;
for (i = 0; i < disks; i++) {
struct md_rdev *rdev = conf->mirrors[i].rdev;
@@ -1486,11 +1534,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
if (!is_discard && rdev && test_bit(WriteMostly, &rdev->flags))
write_behind = true;
- if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
- atomic_inc(&rdev->nr_pending);
- blocked_rdev = rdev;
- break;
- }
r1_bio->bios[i] = NULL;
if (!rdev || test_bit(Faulty, &rdev->flags)) {
if (i < conf->raid_disks)
@@ -1506,13 +1549,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
is_bad = is_badblock(rdev, r1_bio->sector, max_sectors,
&first_bad, &bad_sectors);
- if (is_bad < 0) {
- /* mustn't write here until the bad block is
- * acknowledged*/
- set_bit(BlockedBadBlocks, &rdev->flags);
- blocked_rdev = rdev;
- break;
- }
if (is_bad && first_bad <= r1_bio->sector) {
/* Cannot write here at all */
bad_sectors -= (r1_bio->sector - first_bad);
@@ -1535,7 +1571,21 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
continue;
}
if (is_bad) {
- int good_sectors = first_bad - r1_bio->sector;
+ int good_sectors;
+
+ /*
+ * We cannot atomically write this, so just
+ * error in that case. It could be possible to
+ * atomically write other mirrors, but the
+ * complexity of supporting that is not worth
+ * the benefit.
+ */
+ if (bio->bi_opf & REQ_ATOMIC) {
+ error = -EIO;
+ goto err_handle;
+ }
+
+ good_sectors = first_bad - r1_bio->sector;
if (good_sectors < max_sectors)
max_sectors = good_sectors;
}
@@ -1543,27 +1593,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
r1_bio->bios[i] = bio;
}
- if (unlikely(blocked_rdev)) {
- /* Wait for this device to become unblocked */
- int j;
-
- for (j = 0; j < i; j++)
- if (r1_bio->bios[j])
- rdev_dec_pending(conf->mirrors[j].rdev, mddev);
- mempool_free(r1_bio, &conf->r1bio_pool);
- allow_barrier(conf, bio->bi_iter.bi_sector);
-
- if (bio->bi_opf & REQ_NOWAIT) {
- bio_wouldblock_error(bio);
- return;
- }
- mddev_add_trace_msg(mddev, "raid1 wait rdev %d blocked",
- blocked_rdev->raid_disk);
- md_wait_for_blocked_rdev(blocked_rdev, mddev);
- wait_barrier(conf, bio->bi_iter.bi_sector, false);
- goto retry_write;
- }
-
/*
* When using a bitmap, we may call alloc_behind_master_bio below.
* alloc_behind_master_bio allocates a copy of the data payload a page
@@ -1576,6 +1605,11 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
if (max_sectors < bio_sectors(bio)) {
struct bio *split = bio_split(bio, max_sectors,
GFP_NOIO, &conf->bio_split);
+
+ if (IS_ERR(split)) {
+ error = PTR_ERR(split);
+ goto err_handle;
+ }
bio_chain(split, bio);
submit_bio_noacct(bio);
bio = split;
@@ -1637,7 +1671,8 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
mbio->bi_iter.bi_sector = (r1_bio->sector + rdev->data_offset);
mbio->bi_end_io = raid1_end_write_request;
- mbio->bi_opf = bio_op(bio) | (bio->bi_opf & (REQ_SYNC | REQ_FUA));
+ mbio->bi_opf = bio_op(bio) |
+ (bio->bi_opf & (REQ_SYNC | REQ_FUA | REQ_ATOMIC));
if (test_bit(FailFast, &rdev->flags) &&
!test_bit(WriteMostly, &rdev->flags) &&
conf->raid_disks - mddev->degraded > 1)
@@ -1660,6 +1695,18 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
/* In case raid1d snuck in to freeze_array */
wake_up_barrier(conf);
+ return;
+err_handle:
+ for (k = 0; k < i; k++) {
+ if (r1_bio->bios[k]) {
+ rdev_dec_pending(conf->mirrors[k].rdev, mddev);
+ r1_bio->bios[k] = NULL;
+ }
+ }
+
+ bio->bi_status = errno_to_blk_status(error);
+ set_bit(R1BIO_Uptodate, &r1_bio->state);
+ raid_end_bio_io(r1_bio);
}
static bool raid1_make_request(struct mddev *mddev, struct bio *bio)
@@ -3192,6 +3239,7 @@ static int raid1_set_limits(struct mddev *mddev)
md_init_stacking_limits(&lim);
lim.max_write_zeroes_sectors = 0;
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 862b1fb71d86..7d7a8a2524dc 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1159,6 +1159,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
int slot = r10_bio->read_slot;
struct md_rdev *err_rdev = NULL;
gfp_t gfp = GFP_NOIO;
+ int error;
if (slot >= 0 && r10_bio->devs[slot].rdev) {
/*
@@ -1206,6 +1207,10 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
if (max_sectors < bio_sectors(bio)) {
struct bio *split = bio_split(bio, max_sectors,
gfp, &conf->bio_split);
+ if (IS_ERR(split)) {
+ error = PTR_ERR(split);
+ goto err_handle;
+ }
bio_chain(split, bio);
allow_barrier(conf);
submit_bio_noacct(bio);
@@ -1236,6 +1241,11 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
mddev_trace_remap(mddev, read_bio, r10_bio->sector);
submit_bio_noacct(read_bio);
return;
+err_handle:
+ atomic_dec(&rdev->nr_pending);
+ bio->bi_status = errno_to_blk_status(error);
+ set_bit(R10BIO_Uptodate, &r10_bio->state);
+ raid_end_bio_io(r10_bio);
}
static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
@@ -1245,6 +1255,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
const enum req_op op = bio_op(bio);
const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC;
const blk_opf_t do_fua = bio->bi_opf & REQ_FUA;
+ const blk_opf_t do_atomic = bio->bi_opf & REQ_ATOMIC;
unsigned long flags;
struct r10conf *conf = mddev->private;
struct md_rdev *rdev;
@@ -1263,7 +1274,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
mbio->bi_iter.bi_sector = (r10_bio->devs[n_copy].addr +
choose_data_offset(r10_bio, rdev));
mbio->bi_end_io = raid10_end_write_request;
- mbio->bi_opf = op | do_sync | do_fua;
+ mbio->bi_opf = op | do_sync | do_fua | do_atomic;
if (!replacement && test_bit(FailFast,
&conf->mirrors[devnum].rdev->flags)
&& enough(conf, devnum))
@@ -1285,9 +1296,9 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
static void wait_blocked_dev(struct mddev *mddev, struct r10bio *r10_bio)
{
- int i;
struct r10conf *conf = mddev->private;
struct md_rdev *blocked_rdev;
+ int i;
retry_wait:
blocked_rdev = NULL;
@@ -1295,40 +1306,36 @@ retry_wait:
struct md_rdev *rdev, *rrdev;
rdev = conf->mirrors[i].rdev;
- rrdev = conf->mirrors[i].replacement;
- if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
- atomic_inc(&rdev->nr_pending);
- blocked_rdev = rdev;
- break;
- }
- if (rrdev && unlikely(test_bit(Blocked, &rrdev->flags))) {
- atomic_inc(&rrdev->nr_pending);
- blocked_rdev = rrdev;
- break;
- }
-
- if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
+ if (rdev) {
sector_t dev_sector = r10_bio->devs[i].addr;
/*
* Discard request doesn't care the write result
* so it doesn't need to wait blocked disk here.
*/
- if (!r10_bio->sectors)
- continue;
-
- if (rdev_has_badblock(rdev, dev_sector,
- r10_bio->sectors) < 0) {
+ if (test_bit(WriteErrorSeen, &rdev->flags) &&
+ r10_bio->sectors &&
+ rdev_has_badblock(rdev, dev_sector,
+ r10_bio->sectors) < 0)
/*
- * Mustn't write here until the bad block
- * is acknowledged
+ * Mustn't write here until the bad
+ * block is acknowledged
*/
- atomic_inc(&rdev->nr_pending);
set_bit(BlockedBadBlocks, &rdev->flags);
+
+ if (rdev_blocked(rdev)) {
blocked_rdev = rdev;
+ atomic_inc(&rdev->nr_pending);
break;
}
}
+
+ rrdev = conf->mirrors[i].replacement;
+ if (rrdev && rdev_blocked(rrdev)) {
+ atomic_inc(&rrdev->nr_pending);
+ blocked_rdev = rrdev;
+ break;
+ }
}
if (unlikely(blocked_rdev)) {
@@ -1347,9 +1354,10 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
struct r10bio *r10_bio)
{
struct r10conf *conf = mddev->private;
- int i;
+ int i, k;
sector_t sectors;
int max_sectors;
+ int error;
if ((mddev_is_clustered(mddev) &&
md_cluster_ops->area_resyncing(mddev, WRITE,
@@ -1461,7 +1469,21 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
continue;
}
if (is_bad) {
- int good_sectors = first_bad - dev_sector;
+ int good_sectors;
+
+ /*
+ * We cannot atomically write this, so just
+ * error in that case. It could be possible to
+ * atomically write other mirrors, but the
+ * complexity of supporting that is not worth
+ * the benefit.
+ */
+ if (bio->bi_opf & REQ_ATOMIC) {
+ error = -EIO;
+ goto err_handle;
+ }
+
+ good_sectors = first_bad - dev_sector;
if (good_sectors < max_sectors)
max_sectors = good_sectors;
}
@@ -1482,6 +1504,10 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
if (r10_bio->sectors < bio_sectors(bio)) {
struct bio *split = bio_split(bio, r10_bio->sectors,
GFP_NOIO, &conf->bio_split);
+ if (IS_ERR(split)) {
+ error = PTR_ERR(split);
+ goto err_handle;
+ }
bio_chain(split, bio);
allow_barrier(conf);
submit_bio_noacct(bio);
@@ -1503,6 +1529,26 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
raid10_write_one_disk(mddev, r10_bio, bio, true, i);
}
one_write_done(r10_bio);
+ return;
+err_handle:
+ for (k = 0; k < i; k++) {
+ int d = r10_bio->devs[k].devnum;
+ struct md_rdev *rdev = conf->mirrors[d].rdev;
+ struct md_rdev *rrdev = conf->mirrors[d].replacement;
+
+ if (r10_bio->devs[k].bio) {
+ rdev_dec_pending(rdev, mddev);
+ r10_bio->devs[k].bio = NULL;
+ }
+ if (r10_bio->devs[k].repl_bio) {
+ rdev_dec_pending(rrdev, mddev);
+ r10_bio->devs[k].repl_bio = NULL;
+ }
+ }
+
+ bio->bi_status = errno_to_blk_status(error);
+ set_bit(R10BIO_Uptodate, &r10_bio->state);
+ raid_end_bio_io(r10_bio);
}
static void __make_request(struct mddev *mddev, struct bio *bio, int sectors)
@@ -1644,6 +1690,11 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
if (remainder) {
split_size = stripe_size - remainder;
split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
+ if (IS_ERR(split)) {
+ bio->bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_endio(bio);
+ return 0;
+ }
bio_chain(split, bio);
allow_barrier(conf);
/* Resend the fist split part */
@@ -1654,6 +1705,11 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
if (remainder) {
split_size = bio_sectors(bio) - remainder;
split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
+ if (IS_ERR(split)) {
+ bio->bi_status = errno_to_blk_status(PTR_ERR(split));
+ bio_endio(bio);
+ return 0;
+ }
bio_chain(split, bio);
allow_barrier(conf);
/* Resend the second split part */
@@ -3984,6 +4040,7 @@ static int raid10_set_queue_limits(struct mddev *mddev)
lim.max_write_zeroes_sectors = 0;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * raid10_nr_stripes(conf);
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c
index a70cbec12ed0..37c4da5311ca 100644
--- a/drivers/md/raid5-ppl.c
+++ b/drivers/md/raid5-ppl.c
@@ -258,7 +258,7 @@ static struct ppl_io_unit *ppl_new_iounit(struct ppl_log *log,
memset(pplhdr->reserved, 0xff, PPL_HDR_RESERVED);
pplhdr->signature = cpu_to_le32(ppl_conf->signature);
- io->seq = atomic64_add_return(1, &ppl_conf->seq);
+ io->seq = atomic64_inc_return(&ppl_conf->seq);
pplhdr->generation = cpu_to_le64(io->seq);
return io;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index dc2ea636d173..f09e7677ee9f 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4724,14 +4724,13 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
if (rdev) {
is_bad = rdev_has_badblock(rdev, sh->sector,
RAID5_STRIPE_SECTORS(conf));
- if (s->blocked_rdev == NULL
- && (test_bit(Blocked, &rdev->flags)
- || is_bad < 0)) {
+ if (s->blocked_rdev == NULL) {
if (is_bad < 0)
- set_bit(BlockedBadBlocks,
- &rdev->flags);
- s->blocked_rdev = rdev;
- atomic_inc(&rdev->nr_pending);
+ set_bit(BlockedBadBlocks, &rdev->flags);
+ if (rdev_blocked(rdev)) {
+ s->blocked_rdev = rdev;
+ atomic_inc(&rdev->nr_pending);
+ }
}
}
clear_bit(R5_Insync, &dev->flags);
@@ -7177,6 +7176,8 @@ raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len)
err = mddev_suspend_and_lock(mddev);
if (err)
return err;
+ raid5_quiesce(mddev, true);
+
conf = mddev->private;
if (!conf)
err = -ENODEV;
@@ -7198,6 +7199,8 @@ raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len)
kfree(old_groups);
}
}
+
+ raid5_quiesce(mddev, false);
mddev_unlock_and_resume(mddev);
return err ?: len;
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 896ecfc4afa6..d174e586698f 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -633,7 +633,7 @@ struct r5conf {
* two caches.
*/
int active_name;
- char cache_name[2][32];
+ char cache_name[2][48];
struct kmem_cache *slab_cache; /* for allocating stripes */
struct mutex cache_size_mutex; /* Protect changes to cache size */
diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
index 48282d272fe6..ca0db8d457b4 100644
--- a/drivers/media/cec/core/cec-core.c
+++ b/drivers/media/cec/core/cec-core.c
@@ -438,6 +438,6 @@ static void __exit cec_devnode_exit(void)
subsys_initcall(cec_devnode_init);
module_exit(cec_devnode_exit)
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_DESCRIPTION("Device node registration for cec drivers");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/cec/platform/Kconfig b/drivers/media/cec/platform/Kconfig
index ede81fe331b0..e40413609f53 100644
--- a/drivers/media/cec/platform/Kconfig
+++ b/drivers/media/cec/platform/Kconfig
@@ -99,7 +99,7 @@ config CEC_TEGRA
config CEC_SECO
tristate "SECO Boards HDMI CEC driver"
- depends on X86 || COMPILE_TEST
+ depends on X86 || (COMPILE_TEST && HAS_IOPORT)
depends on PCI && DMI
select CEC_CORE
select CEC_NOTIFIER
diff --git a/drivers/media/cec/platform/cec-gpio/cec-gpio.c b/drivers/media/cec/platform/cec-gpio/cec-gpio.c
index 98dacb0919b6..cf64e8871fe5 100644
--- a/drivers/media/cec/platform/cec-gpio/cec-gpio.c
+++ b/drivers/media/cec/platform/cec-gpio/cec-gpio.c
@@ -279,7 +279,7 @@ MODULE_DEVICE_TABLE(of, cec_gpio_match);
static struct platform_driver cec_gpio_pdrv = {
.probe = cec_gpio_probe,
- .remove_new = cec_gpio_remove,
+ .remove = cec_gpio_remove,
.driver = {
.name = "cec-gpio",
.of_match_table = cec_gpio_match,
@@ -288,6 +288,6 @@ static struct platform_driver cec_gpio_pdrv = {
module_platform_driver(cec_gpio_pdrv);
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CEC GPIO driver");
diff --git a/drivers/media/cec/platform/cros-ec/cros-ec-cec.c b/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
index 8fbbb4091455..12b73ea0f31d 100644
--- a/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
+++ b/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
@@ -582,7 +582,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_cec_id);
static struct platform_driver cros_ec_cec_driver = {
.probe = cros_ec_cec_probe,
- .remove_new = cros_ec_cec_remove,
+ .remove = cros_ec_cec_remove,
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_cec_pm_ops,
diff --git a/drivers/media/cec/platform/meson/ao-cec-g12a.c b/drivers/media/cec/platform/meson/ao-cec-g12a.c
index 51294b9b6cd5..41f5b8669cb0 100644
--- a/drivers/media/cec/platform/meson/ao-cec-g12a.c
+++ b/drivers/media/cec/platform/meson/ao-cec-g12a.c
@@ -778,7 +778,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
static struct platform_driver meson_ao_cec_g12a_driver = {
.probe = meson_ao_cec_g12a_probe,
- .remove_new = meson_ao_cec_g12a_remove,
+ .remove = meson_ao_cec_g12a_remove,
.driver = {
.name = "meson-ao-cec-g12a",
.of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
diff --git a/drivers/media/cec/platform/meson/ao-cec.c b/drivers/media/cec/platform/meson/ao-cec.c
index 494738daf09a..145efd9af6ac 100644
--- a/drivers/media/cec/platform/meson/ao-cec.c
+++ b/drivers/media/cec/platform/meson/ao-cec.c
@@ -714,7 +714,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
static struct platform_driver meson_ao_cec_driver = {
.probe = meson_ao_cec_probe,
- .remove_new = meson_ao_cec_remove,
+ .remove = meson_ao_cec_remove,
.driver = {
.name = "meson-ao-cec",
.of_match_table = meson_ao_cec_of_match,
diff --git a/drivers/media/cec/platform/s5p/s5p_cec.c b/drivers/media/cec/platform/s5p/s5p_cec.c
index 51ab4a80aafe..4a92d3230f66 100644
--- a/drivers/media/cec/platform/s5p/s5p_cec.c
+++ b/drivers/media/cec/platform/s5p/s5p_cec.c
@@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(of, s5p_cec_match);
static struct platform_driver s5p_cec_pdrv = {
.probe = s5p_cec_probe,
- .remove_new = s5p_cec_remove,
+ .remove = s5p_cec_remove,
.driver = {
.name = CEC_NAME,
.of_match_table = s5p_cec_match,
diff --git a/drivers/media/cec/platform/seco/seco-cec.c b/drivers/media/cec/platform/seco/seco-cec.c
index 5d4c5a2cae09..b7bb49f02395 100644
--- a/drivers/media/cec/platform/seco/seco-cec.c
+++ b/drivers/media/cec/platform/seco/seco-cec.c
@@ -778,7 +778,7 @@ static struct platform_driver secocec_driver = {
.pm = SECOCEC_PM_OPS,
},
.probe = secocec_probe,
- .remove_new = secocec_remove,
+ .remove = secocec_remove,
};
module_platform_driver(secocec_driver);
diff --git a/drivers/media/cec/platform/sti/stih-cec.c b/drivers/media/cec/platform/sti/stih-cec.c
index 99978a7c8d9b..49843d576c7c 100644
--- a/drivers/media/cec/platform/sti/stih-cec.c
+++ b/drivers/media/cec/platform/sti/stih-cec.c
@@ -383,7 +383,7 @@ MODULE_DEVICE_TABLE(of, stih_cec_match);
static struct platform_driver stih_cec_pdrv = {
.probe = stih_cec_probe,
- .remove_new = stih_cec_remove,
+ .remove = stih_cec_remove,
.driver = {
.name = CEC_NAME,
.of_match_table = stih_cec_match,
diff --git a/drivers/media/cec/platform/stm32/stm32-cec.c b/drivers/media/cec/platform/stm32/stm32-cec.c
index bda9d254041a..fea2d65acffc 100644
--- a/drivers/media/cec/platform/stm32/stm32-cec.c
+++ b/drivers/media/cec/platform/stm32/stm32-cec.c
@@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(of, stm32_cec_of_match);
static struct platform_driver stm32_cec_driver = {
.probe = stm32_cec_probe,
- .remove_new = stm32_cec_remove,
+ .remove = stm32_cec_remove,
.driver = {
.name = CEC_NAME,
.of_match_table = stm32_cec_of_match,
diff --git a/drivers/media/cec/platform/tegra/tegra_cec.c b/drivers/media/cec/platform/tegra/tegra_cec.c
index 7c1022cee1e8..3ed50097262f 100644
--- a/drivers/media/cec/platform/tegra/tegra_cec.c
+++ b/drivers/media/cec/platform/tegra/tegra_cec.c
@@ -465,7 +465,7 @@ static struct platform_driver tegra_cec_driver = {
.of_match_table = tegra_cec_of_match,
},
.probe = tegra_cec_probe,
- .remove_new = tegra_cec_remove,
+ .remove = tegra_cec_remove,
#ifdef CONFIG_PM
.suspend = tegra_cec_suspend,
diff --git a/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c b/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c
index 8526f613a40e..cfbfc4c1b2e6 100644
--- a/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c
+++ b/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c
@@ -348,12 +348,12 @@ static int get_edid_tag_location(const u8 *edid, unsigned int size,
/* Return if not a CTA-861 extension block */
if (size < 256 || edid[0] != 0x02 || edid[1] != 0x03)
- return -1;
+ return -ENOENT;
/* search tag */
d = edid[0x02] & 0x7f;
if (d <= 4)
- return -1;
+ return -ENOENT;
i = 0x04;
end = 0x00 + d;
@@ -371,7 +371,7 @@ static int get_edid_tag_location(const u8 *edid, unsigned int size,
return offset + i;
i += len + 1;
} while (i < end);
- return -1;
+ return -ENOENT;
}
static void extron_edid_crc(u8 *edid)
diff --git a/drivers/media/cec/usb/pulse8/pulse8-cec.c b/drivers/media/cec/usb/pulse8/pulse8-cec.c
index ba67587bd43e..171366fe3544 100644
--- a/drivers/media/cec/usb/pulse8/pulse8-cec.c
+++ b/drivers/media/cec/usb/pulse8/pulse8-cec.c
@@ -685,7 +685,7 @@ static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio,
err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 4);
if (err)
return err;
- date = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ date = ((unsigned)data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
dev_info(pulse8->dev, "Firmware build date %ptT\n", &date);
dev_dbg(pulse8->dev, "Persistent config:\n");
diff --git a/drivers/media/common/saa7146/saa7146_vbi.c b/drivers/media/common/saa7146/saa7146_vbi.c
index bb7d81f7eba6..a1854b3dd004 100644
--- a/drivers/media/common/saa7146/saa7146_vbi.c
+++ b/drivers/media/common/saa7146/saa7146_vbi.c
@@ -407,8 +407,6 @@ const struct vb2_ops vbi_qops = {
.buf_cleanup = buf_cleanup,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* ------------------------------------------------------------------ */
diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c
index 040489e15ea0..94e1cd4eaedb 100644
--- a/drivers/media/common/saa7146/saa7146_video.c
+++ b/drivers/media/common/saa7146/saa7146_video.c
@@ -681,8 +681,6 @@ const struct vb2_ops video_qops = {
.buf_cleanup = buf_cleanup,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/********************************************************************************/
diff --git a/drivers/media/common/siano/smsdvb-debugfs.c b/drivers/media/common/siano/smsdvb-debugfs.c
index 73990e469df9..d14ba271db50 100644
--- a/drivers/media/common/siano/smsdvb-debugfs.c
+++ b/drivers/media/common/siano/smsdvb-debugfs.c
@@ -398,8 +398,6 @@ void smsdvb_debugfs_release(struct smsdvb_client_t *client)
void smsdvb_debugfs_register(void)
{
- struct dentry *d;
-
/*
* FIXME: This was written to debug Siano USB devices. So, it creates
* the debugfs node under <debugfs>/usb.
@@ -410,12 +408,7 @@ void smsdvb_debugfs_register(void)
* node for sdio-based boards, but this may need some logic at sdio
* subsystem.
*/
- d = debugfs_create_dir("smsdvb", usb_debug_root);
- if (IS_ERR_OR_NULL(d)) {
- pr_err("Couldn't create sysfs node for smsdvb\n");
- return;
- }
- smsdvb_debugfs_usb_root = d;
+ smsdvb_debugfs_usb_root = debugfs_create_dir("smsdvb", usb_debug_root);
}
void smsdvb_debugfs_unregister(void)
diff --git a/drivers/media/common/uvc.c b/drivers/media/common/uvc.c
index c54c2268fee6..1ad4604474ac 100644
--- a/drivers/media/common/uvc.c
+++ b/drivers/media/common/uvc.c
@@ -97,6 +97,10 @@ static const struct uvc_format_desc uvc_fmts[] = {
.fcc = V4L2_PIX_FMT_RGB565,
},
{
+ .guid = UVC_GUID_FORMAT_D3DFMT_R5G6B5,
+ .fcc = V4L2_PIX_FMT_RGB565,
+ },
+ {
.guid = UVC_GUID_FORMAT_BGR3,
.fcc = V4L2_PIX_FMT_BGR24,
},
@@ -121,6 +125,10 @@ static const struct uvc_format_desc uvc_fmts[] = {
.fcc = V4L2_PIX_FMT_Y12I,
},
{
+ .guid = UVC_GUID_FORMAT_Y16I,
+ .fcc = V4L2_PIX_FMT_Y16I,
+ },
+ {
.guid = UVC_GUID_FORMAT_Z16,
.fcc = V4L2_PIX_FMT_Z16,
},
diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
index 642c48e8c1f5..ded11cd8dbf7 100644
--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
@@ -1795,6 +1795,9 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
unsigned p;
unsigned x;
+ if (WARN_ON_ONCE(!tpg->src_width || !tpg->scaled_width))
+ return;
+
switch (tpg->pattern) {
case TPG_PAT_GREEN:
contrast = TPG_COLOR_100_RED;
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 29a8d876e6c2..c0cc441b5164 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1482,18 +1482,23 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
}
vb->planes[plane].dbuf_mapped = 1;
}
+ } else {
+ for (plane = 0; plane < vb->num_planes; ++plane)
+ dma_buf_put(planes[plane].dbuf);
+ }
- /*
- * Now that everything is in order, copy relevant information
- * provided by userspace.
- */
- for (plane = 0; plane < vb->num_planes; ++plane) {
- vb->planes[plane].bytesused = planes[plane].bytesused;
- vb->planes[plane].length = planes[plane].length;
- vb->planes[plane].m.fd = planes[plane].m.fd;
- vb->planes[plane].data_offset = planes[plane].data_offset;
- }
+ /*
+ * Now that everything is in order, copy relevant information
+ * provided by userspace.
+ */
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ vb->planes[plane].bytesused = planes[plane].bytesused;
+ vb->planes[plane].length = planes[plane].length;
+ vb->planes[plane].m.fd = planes[plane].m.fd;
+ vb->planes[plane].data_offset = planes[plane].data_offset;
+ }
+ if (reacquired) {
/*
* Call driver-specific initialization on the newly acquired buffer,
* if provided.
@@ -1503,9 +1508,6 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
dprintk(q, 1, "buffer initialization failed\n");
goto err_put_vb2_buf;
}
- } else {
- for (plane = 0; plane < vb->num_planes; ++plane)
- dma_buf_put(planes[plane].dbuf);
}
ret = call_vb_qop(vb, buf_prepare, vb);
@@ -2035,7 +2037,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
* become ready or for streamoff. Driver's lock is released to
* allow streamoff or qbuf to be called while waiting.
*/
- call_void_qop(q, wait_prepare, q);
+ if (q->ops->wait_prepare)
+ call_void_qop(q, wait_prepare, q);
+ else if (q->lock)
+ mutex_unlock(q->lock);
/*
* All locks have been released, it is safe to sleep now.
@@ -2045,12 +2050,16 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
!list_empty(&q->done_list) || !q->streaming ||
q->error);
+ if (q->ops->wait_finish)
+ call_void_qop(q, wait_finish, q);
+ else if (q->lock)
+ mutex_lock(q->lock);
+
+ q->waiting_in_dqbuf = 0;
/*
* We need to reevaluate both conditions again after reacquiring
* the locks or return an error if one occurred.
*/
- call_void_qop(q, wait_finish, q);
- q->waiting_in_dqbuf = 0;
if (ret) {
dprintk(q, 1, "sleep was interrupted\n");
return ret;
@@ -2322,7 +2331,7 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
}
if (q_num_bufs < q->min_queued_buffers) {
- dprintk(q, 1, "need at least %u queued buffers\n",
+ dprintk(q, 1, "need at least %u allocated buffers\n",
q->min_queued_buffers);
return -EINVAL;
}
@@ -2644,6 +2653,14 @@ int vb2_core_queue_init(struct vb2_queue *q)
if (WARN_ON(q->min_reqbufs_allocation > q->max_num_buffers))
return -EINVAL;
+ /* Either both or none are set */
+ if (WARN_ON(!q->ops->wait_prepare ^ !q->ops->wait_finish))
+ return -EINVAL;
+
+ /* Warn if q->lock is NULL and no custom wait_prepare is provided */
+ if (WARN_ON(!q->lock && !q->ops->wait_prepare))
+ return -EINVAL;
+
INIT_LIST_HEAD(&q->queued_list);
INIT_LIST_HEAD(&q->done_list);
spin_lock_init(&q->done_lock);
@@ -3203,10 +3220,17 @@ static int vb2_thread(void *data)
continue;
prequeue--;
} else {
- call_void_qop(q, wait_finish, q);
- if (!threadio->stop)
+ if (!threadio->stop) {
+ if (q->ops->wait_finish)
+ call_void_qop(q, wait_finish, q);
+ else if (q->lock)
+ mutex_lock(q->lock);
ret = vb2_core_dqbuf(q, &index, NULL, 0);
- call_void_qop(q, wait_prepare, q);
+ if (q->ops->wait_prepare)
+ call_void_qop(q, wait_prepare, q);
+ else if (q->lock)
+ mutex_unlock(q->lock);
+ }
dprintk(q, 5, "file io: vb2_dqbuf result: %d\n", ret);
if (!ret)
vb = vb2_get_buffer(q, index);
@@ -3218,12 +3242,19 @@ static int vb2_thread(void *data)
if (vb->state != VB2_BUF_STATE_ERROR)
if (threadio->fnc(vb, threadio->priv))
break;
- call_void_qop(q, wait_finish, q);
if (copy_timestamp)
vb->timestamp = ktime_get_ns();
- if (!threadio->stop)
+ if (!threadio->stop) {
+ if (q->ops->wait_finish)
+ call_void_qop(q, wait_finish, q);
+ else if (q->lock)
+ mutex_lock(q->lock);
ret = vb2_core_qbuf(q, vb, NULL, NULL);
- call_void_qop(q, wait_prepare, q);
+ if (q->ops->wait_prepare)
+ call_void_qop(q, wait_prepare, q);
+ else if (q->lock)
+ mutex_unlock(q->lock);
+ }
if (ret || threadio->stop)
break;
}
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 293f3d5f1c4e..9201d854dbcc 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -231,7 +231,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b
break;
}
- /* Fill in driver-provided information for OUTPUT types */
+ /* Fill in user-provided information for OUTPUT types */
if (V4L2_TYPE_IS_OUTPUT(b->type)) {
/*
* Will have to go up to b->length when API starts
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 4f78f30b3646..a05aa271a1ba 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -443,8 +443,8 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
default:
fepriv->auto_step++;
- fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */
- break;
+ fepriv->auto_sub_step = 0;
+ continue;
}
if (!ready) fepriv->auto_sub_step++;
diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c
index 192a8230c4aa..29edaaff7a5c 100644
--- a/drivers/media/dvb-core/dvb_vb2.c
+++ b/drivers/media/dvb-core/dvb_vb2.c
@@ -366,9 +366,15 @@ int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
{
struct vb2_queue *q = &ctx->vb_q;
+ struct vb2_buffer *vb2 = vb2_get_buffer(q, exp->index);
int ret;
- ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, q->bufs[exp->index],
+ if (!vb2) {
+ dprintk(1, "[%s] invalid buffer index\n", ctx->name);
+ return -EINVAL;
+ }
+
+ ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, vb2,
0, exp->flags);
if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index b43695bc51e7..9df7c213716a 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -86,10 +86,15 @@ static DECLARE_RWSEM(minor_rwsem);
static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
+ unsigned int minor = iminor(inode);
+
+ if (minor >= MAX_DVB_MINORS)
+ return -ENODEV;
mutex_lock(&dvbdev_mutex);
down_read(&minor_rwsem);
- dvbdev = dvb_minors[iminor(inode)];
+
+ dvbdev = dvb_minors[minor];
if (dvbdev && dvbdev->fops) {
int err = 0;
@@ -525,7 +530,10 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
if (!dvb_minors[minor])
break;
- if (minor == MAX_DVB_MINORS) {
+#else
+ minor = nums2minor(adap->num, type, id);
+#endif
+ if (minor >= MAX_DVB_MINORS) {
if (new_node) {
list_del(&new_node->list_head);
kfree(dvbdevfops);
@@ -538,9 +546,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_unlock(&dvbdev_register_lock);
return -EINVAL;
}
-#else
- minor = nums2minor(adap->num, type, id);
-#endif
+
dvbdev->minor = minor;
dvb_minors[minor] = dvb_device_get(dvbdev);
up_write(&minor_rwsem);
diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c
index 27f1de21f571..d935fb10e620 100644
--- a/drivers/media/dvb-frontends/bcm3510.c
+++ b/drivers/media/dvb-frontends/bcm3510.c
@@ -729,7 +729,7 @@ static int bcm3510_init_cold(struct bcm3510_state *st)
int ret;
bcm3510_register_value v;
- /* read Acquisation Processor status register and check it is not in RUN mode */
+ /* read Acquisition Processor status register and check it is not in RUN mode */
if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
return ret;
if (v.APSTAT1_a2.RUN) {
diff --git a/drivers/media/dvb-frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c
index 8b978a9f74a4..f5dd3a81725a 100644
--- a/drivers/media/dvb-frontends/cx24116.c
+++ b/drivers/media/dvb-frontends/cx24116.c
@@ -741,6 +741,7 @@ static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
{
struct cx24116_state *state = fe->demodulator_priv;
u8 snr_reading;
+ int ret;
static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
@@ -749,7 +750,11 @@ static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
dprintk("%s()\n", __func__);
- snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
+ ret = cx24116_readreg(state, CX24116_REG_QUALITY0);
+ if (ret < 0)
+ return ret;
+
+ snr_reading = ret;
if (snr_reading >= 0xa0 /* 100% */)
*snr = 0xffff;
diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c
index c958bcff026e..6cbbb351d545 100644
--- a/drivers/media/dvb-frontends/dib0090.c
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -78,7 +78,7 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define SOC_8090_P1G_11R1 0x86
#define SOC_8090_P1G_21R1 0x8e
-/* else use thos ones to check */
+/* else use those ones to check */
#define P1A_B 0x0
#define P1C 0x1
#define P1D_E_F 0x3
@@ -1574,7 +1574,7 @@ static int dib0090_reset(struct dvb_frontend *fe)
if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
dib0090_set_EFUSE(state);
- /* Congigure in function of the crystal */
+ /* Configure in function of the crystal */
if (state->config->force_crystal_mode != 0)
dib0090_write_reg(state, 0x14,
state->config->force_crystal_mode & 3);
diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c
index c598b2a63325..822639f11c04 100644
--- a/drivers/media/dvb-frontends/dib3000mb.c
+++ b/drivers/media/dvb-frontends/dib3000mb.c
@@ -640,7 +640,7 @@ static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
return 0;
}
-/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */
+/* see dib3000-watch dvb-apps for exact calculations of signal_strength and snr */
static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{
struct dib3000_state* state = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 023db6e793f8..05254d8717db 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -947,8 +947,6 @@ static const struct vb2_ops rtl2832_sdr_vb2_ops = {
.buf_queue = rtl2832_sdr_buf_queue,
.start_streaming = rtl2832_sdr_start_streaming,
.stop_streaming = rtl2832_sdr_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
@@ -1487,7 +1485,7 @@ static struct platform_driver rtl2832_sdr_driver = {
.name = "rtl2832_sdr",
},
.probe = rtl2832_sdr_probe,
- .remove_new = rtl2832_sdr_remove,
+ .remove = rtl2832_sdr_remove,
};
module_platform_driver(rtl2832_sdr_driver);
diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c
index df89c33dac23..40537c4ccb0d 100644
--- a/drivers/media/dvb-frontends/stb0899_algo.c
+++ b/drivers/media/dvb-frontends/stb0899_algo.c
@@ -269,7 +269,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state)
short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3;
int index = 0;
- u8 cfr[2];
+ u8 cfr[2] = {0};
u8 reg;
internal->status = NOCARRIER;
diff --git a/drivers/media/dvb-frontends/stv6111.c b/drivers/media/dvb-frontends/stv6111.c
index 2d0adb6fcb08..0ac15273922d 100644
--- a/drivers/media/dvb-frontends/stv6111.c
+++ b/drivers/media/dvb-frontends/stv6111.c
@@ -161,7 +161,7 @@ static const struct slookup gain_rfagc_lookup[] = {
};
/*
- * This table is 6 dB too low comapred to the others (probably created with
+ * This table is 6 dB too low compared to the others (probably created with
* a different BB_MAG setting)
*/
static const struct slookup gain_channel_agc_nf_lookup[] = {
diff --git a/drivers/media/dvb-frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c
index fd928787207e..c11563853c07 100644
--- a/drivers/media/dvb-frontends/tda18271c2dd.c
+++ b/drivers/media/dvb-frontends/tda18271c2dd.c
@@ -954,7 +954,7 @@ static int RFTrackingFiltersCorrection(struct tda_state *state,
Capprox = 255;
- /* TODO Temperature compensation. There is defenitely a scale factor */
+ /* TODO Temperature compensation. There is definitely a scale factor */
/* missing in the datasheet, so leave it out for now. */
state->m_Regs[EB14] = Capprox;
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
index a5baca2449c7..e25add6cc38e 100644
--- a/drivers/media/dvb-frontends/ts2020.c
+++ b/drivers/media/dvb-frontends/ts2020.c
@@ -553,13 +553,19 @@ static void ts2020_regmap_unlock(void *__dev)
static int ts2020_probe(struct i2c_client *client)
{
struct ts2020_config *pdata = client->dev.platform_data;
- struct dvb_frontend *fe = pdata->fe;
+ struct dvb_frontend *fe;
struct ts2020_priv *dev;
int ret;
u8 u8tmp;
unsigned int utmp;
char *chip_str;
+ if (!pdata) {
+ dev_err(&client->dev, "platform data is mandatory\n");
+ return -EINVAL;
+ }
+
+ fe = pdata->fe;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
diff --git a/drivers/media/dvb-frontends/zd1301_demod.c b/drivers/media/dvb-frontends/zd1301_demod.c
index 17f6e373c13d..e8b9e67a8717 100644
--- a/drivers/media/dvb-frontends/zd1301_demod.c
+++ b/drivers/media/dvb-frontends/zd1301_demod.c
@@ -531,7 +531,7 @@ static struct platform_driver zd1301_demod_driver = {
.suppress_bind_attrs = true,
},
.probe = zd1301_demod_probe,
- .remove_new = zd1301_demod_remove,
+ .remove = zd1301_demod_remove,
};
module_platform_driver(zd1301_demod_driver);
diff --git a/drivers/media/dvb-frontends/zl10036.c b/drivers/media/dvb-frontends/zl10036.c
index 3df055be66d6..5ad987c6861b 100644
--- a/drivers/media/dvb-frontends/zl10036.c
+++ b/drivers/media/dvb-frontends/zl10036.c
@@ -89,7 +89,7 @@ static int zl10036_write(struct zl10036_state *state, u8 buf[], u8 count)
int ret;
if (zl10036_debug & 0x02) {
- /* every 8bit-value satisifes this!
+ /* every 8bit-value satisfies this!
* so only check for debug log */
if ((buf[0] & 0x80) == 0x00)
reg = 2;
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index 819ff9f7c90f..ff7dfa0278a7 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -1440,7 +1440,8 @@ static int adv7180_probe(struct i2c_client *client)
return ret;
}
- if (of_property_read_bool(np, "adv,force-bt656-4"))
+ if (of_property_read_bool(np, "adv,force-bt656-4") ||
+ of_property_read_bool(np, "adi,force-bt656-4"))
state->force_bt656_4 = true;
if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c
index e9406d552699..4036972af3a6 100644
--- a/drivers/media/i2c/adv7511-v4l2.c
+++ b/drivers/media/i2c/adv7511-v4l2.c
@@ -116,6 +116,9 @@ struct adv7511_state {
unsigned edid_detect_counter;
struct workqueue_struct *work_queue;
struct delayed_work edid_handler; /* work entry */
+
+ struct dentry *debugfs_dir;
+ struct v4l2_debugfs_if *infoframes;
};
static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd);
@@ -483,27 +486,25 @@ static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
return 256 - csum;
}
-static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_infoframe *cri)
+static int read_infoframe(struct v4l2_subdev *sd,
+ const struct adv7511_cfg_read_infoframe *cri,
+ u8 *buffer)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct device *dev = &client->dev;
- union hdmi_infoframe frame;
- u8 buffer[32];
u8 len;
int i;
if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) {
v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc);
- return;
+ return 0;
}
memcpy(buffer, cri->header, sizeof(cri->header));
len = buffer[2];
- if (len + 4 > sizeof(buffer)) {
+ if (len + 4 > V4L2_DEBUGFS_IF_MAX_LEN) {
v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
- return;
+ return 0;
}
if (cri->payload_addr >= 0x100) {
@@ -516,21 +517,38 @@ static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_
buffer[3] = 0;
buffer[3] = hdmi_infoframe_checksum(buffer, len + 4);
- if (hdmi_infoframe_unpack(&frame, buffer, len + 4) < 0) {
- v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
+ return len + 4;
+}
+
+static void log_infoframe(struct v4l2_subdev *sd,
+ const struct adv7511_cfg_read_infoframe *cri)
+{
+ union hdmi_infoframe frame;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct device *dev = &client->dev;
+ u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {};
+ int len = read_infoframe(sd, cri, buffer);
+
+ if (len <= 0)
+ return;
+
+ if (hdmi_infoframe_unpack(&frame, buffer, len) < 0) {
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n",
+ __func__, cri->desc);
return;
}
hdmi_infoframe_log(KERN_INFO, dev, &frame);
}
+static const struct adv7511_cfg_read_infoframe cri[] = {
+ { "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 },
+ { "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 },
+ { "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 },
+};
+
static void adv7511_log_infoframes(struct v4l2_subdev *sd)
{
- static const struct adv7511_cfg_read_infoframe cri[] = {
- { "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 },
- { "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 },
- { "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 },
- };
int i;
for (i = 0; i < ARRAY_SIZE(cri); i++)
@@ -1693,6 +1711,34 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd)
return false;
}
+static ssize_t
+adv7511_debugfs_if_read(u32 type, void *priv,
+ struct file *filp, char __user *ubuf, size_t count, loff_t *ppos)
+{
+ u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
+ struct v4l2_subdev *sd = priv;
+ int index;
+ int len;
+
+ switch (type) {
+ case V4L2_DEBUGFS_IF_AVI:
+ index = 0;
+ break;
+ case V4L2_DEBUGFS_IF_AUDIO:
+ index = 1;
+ break;
+ case V4L2_DEBUGFS_IF_SPD:
+ index = 2;
+ break;
+ default:
+ return 0;
+ }
+ len = read_infoframe(sd, &cri[index], buf);
+ if (len > 0)
+ len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
+ return len < 0 ? 0 : len;
+}
+
static int adv7511_registered(struct v4l2_subdev *sd)
{
struct adv7511_state *state = get_adv7511_state(sd);
@@ -1700,9 +1746,16 @@ static int adv7511_registered(struct v4l2_subdev *sd)
int err;
err = cec_register_adapter(state->cec_adap, &client->dev);
- if (err)
+ if (err) {
cec_delete_adapter(state->cec_adap);
- return err;
+ return err;
+ }
+
+ state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
+ state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
+ V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO |
+ V4L2_DEBUGFS_IF_SPD, sd, adv7511_debugfs_if_read);
+ return 0;
}
static void adv7511_unregistered(struct v4l2_subdev *sd)
@@ -1710,6 +1763,10 @@ static void adv7511_unregistered(struct v4l2_subdev *sd)
struct adv7511_state *state = get_adv7511_state(sd);
cec_unregister_adapter(state->cec_adap);
+ v4l2_debugfs_if_free(state->infoframes);
+ state->infoframes = NULL;
+ debugfs_remove_recursive(state->debugfs_dir);
+ state->debugfs_dir = NULL;
}
static const struct v4l2_subdev_internal_ops adv7511_int_ops = {
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 48230d5109f0..e271782b7b70 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -42,7 +42,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_DESCRIPTION("Analog Devices ADV7604/10/11/12 video decoder driver");
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>");
MODULE_LICENSE("GPL");
@@ -193,6 +193,9 @@ struct adv76xx_state {
struct delayed_work delayed_work_enable_hotplug;
bool restart_stdi_once;
+ struct dentry *debugfs_dir;
+ struct v4l2_debugfs_if *infoframes;
+
/* CEC */
struct cec_adapter *cec_adap;
u8 cec_addr[ADV76XX_MAX_ADDRS];
@@ -1405,12 +1408,13 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- false, timings))
+ false, adv76xx_get_dv_timings_cap(sd, -1), timings))
return 0;
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- false, state->aspect_ratio, timings))
+ false, state->aspect_ratio,
+ adv76xx_get_dv_timings_cap(sd, -1), timings))
return 0;
v4l2_dbg(2, debug, sd,
@@ -2458,10 +2462,9 @@ static const struct adv76xx_cfg_read_infoframe adv76xx_cri[] = {
{ "Vendor", 0x10, 0xec, 0x54 }
};
-static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
- union hdmi_infoframe *frame)
+static int adv76xx_read_infoframe_buf(struct v4l2_subdev *sd, int index,
+ u8 buf[V4L2_DEBUGFS_IF_MAX_LEN])
{
- uint8_t buffer[32];
u8 len;
int i;
@@ -2472,27 +2475,20 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
}
for (i = 0; i < 3; i++)
- buffer[i] = infoframe_read(sd,
- adv76xx_cri[index].head_addr + i);
+ buf[i] = infoframe_read(sd, adv76xx_cri[index].head_addr + i);
- len = buffer[2] + 1;
+ len = buf[2] + 1;
- if (len + 3 > sizeof(buffer)) {
+ if (len + 3 > V4L2_DEBUGFS_IF_MAX_LEN) {
v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__,
adv76xx_cri[index].desc, len);
return -ENOENT;
}
for (i = 0; i < len; i++)
- buffer[i + 3] = infoframe_read(sd,
- adv76xx_cri[index].payload_addr + i);
-
- if (hdmi_infoframe_unpack(frame, buffer, len + 3) < 0) {
- v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
- adv76xx_cri[index].desc);
- return -ENOENT;
- }
- return 0;
+ buf[i + 3] = infoframe_read(sd,
+ adv76xx_cri[index].payload_addr + i);
+ return len + 3;
}
static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
@@ -2505,10 +2501,19 @@ static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
}
for (i = 0; i < ARRAY_SIZE(adv76xx_cri); i++) {
- union hdmi_infoframe frame;
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {};
+ union hdmi_infoframe frame;
+ int len;
+
+ len = adv76xx_read_infoframe_buf(sd, i, buffer);
+ if (len < 0)
+ continue;
- if (!adv76xx_read_infoframe(sd, i, &frame))
+ if (hdmi_infoframe_unpack(&frame, buffer, len) < 0)
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n",
+ __func__, adv76xx_cri[i].desc);
+ else
hdmi_infoframe_log(KERN_INFO, &client->dev, &frame);
}
}
@@ -2519,10 +2524,10 @@ static int adv76xx_log_status(struct v4l2_subdev *sd)
const struct adv76xx_chip_info *info = state->info;
struct v4l2_dv_timings timings;
struct stdi_readback stdi;
- u8 reg_io_0x02 = io_read(sd, 0x02);
+ int ret;
+ u8 reg_io_0x02;
u8 edid_enabled;
u8 cable_det;
-
static const char * const csc_coeff_sel_rb[16] = {
"bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
"reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709",
@@ -2621,13 +2626,21 @@ static int adv76xx_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "-----Color space-----\n");
v4l2_info(sd, "RGB quantization range ctrl: %s\n",
rgb_quantization_range_txt[state->rgb_quantization_range]);
- v4l2_info(sd, "Input color space: %s\n",
- input_color_space_txt[reg_io_0x02 >> 4]);
- v4l2_info(sd, "Output color space: %s %s, alt-gamma %s\n",
- (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
- (((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
- "(16-235)" : "(0-255)",
- (reg_io_0x02 & 0x08) ? "enabled" : "disabled");
+
+ ret = io_read(sd, 0x02);
+ if (ret < 0) {
+ v4l2_info(sd, "Can't read Input/Output color space\n");
+ } else {
+ reg_io_0x02 = ret;
+
+ v4l2_info(sd, "Input color space: %s\n",
+ input_color_space_txt[reg_io_0x02 >> 4]);
+ v4l2_info(sd, "Output color space: %s %s, alt-gamma %s\n",
+ (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
+ (((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
+ "(16-235)" : "(0-255)",
+ (reg_io_0x02 & 0x08) ? "enabled" : "disabled");
+ }
v4l2_info(sd, "Color space conversion: %s\n",
csc_coeff_sel_rb[cp_read(sd, info->cp_csc) >> 4]);
@@ -2686,6 +2699,41 @@ static int adv76xx_subscribe_event(struct v4l2_subdev *sd,
}
}
+static ssize_t
+adv76xx_debugfs_if_read(u32 type, void *priv, struct file *filp,
+ char __user *ubuf, size_t count, loff_t *ppos)
+{
+ u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
+ struct v4l2_subdev *sd = priv;
+ int index;
+ int len;
+
+ if (!is_hdmi(sd))
+ return 0;
+
+ switch (type) {
+ case V4L2_DEBUGFS_IF_AVI:
+ index = 0;
+ break;
+ case V4L2_DEBUGFS_IF_AUDIO:
+ index = 1;
+ break;
+ case V4L2_DEBUGFS_IF_SPD:
+ index = 2;
+ break;
+ case V4L2_DEBUGFS_IF_HDMI:
+ index = 3;
+ break;
+ default:
+ return 0;
+ }
+
+ len = adv76xx_read_infoframe_buf(sd, index, buf);
+ if (len > 0)
+ len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
+ return len < 0 ? 0 : len;
+}
+
static int adv76xx_registered(struct v4l2_subdev *sd)
{
struct adv76xx_state *state = to_state(sd);
@@ -2693,9 +2741,16 @@ static int adv76xx_registered(struct v4l2_subdev *sd)
int err;
err = cec_register_adapter(state->cec_adap, &client->dev);
- if (err)
+ if (err) {
cec_delete_adapter(state->cec_adap);
- return err;
+ return err;
+ }
+ state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
+ state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
+ V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO |
+ V4L2_DEBUGFS_IF_SPD | V4L2_DEBUGFS_IF_HDMI, sd,
+ adv76xx_debugfs_if_read);
+ return 0;
}
static void adv76xx_unregistered(struct v4l2_subdev *sd)
@@ -2703,6 +2758,10 @@ static void adv76xx_unregistered(struct v4l2_subdev *sd)
struct adv76xx_state *state = to_state(sd);
cec_unregister_adapter(state->cec_adap);
+ v4l2_debugfs_if_free(state->infoframes);
+ state->infoframes = NULL;
+ debugfs_remove_recursive(state->debugfs_dir);
+ state->debugfs_dir = NULL;
}
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 014fc913225c..5545cd23e113 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -38,7 +38,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_DESCRIPTION("Analog Devices ADV7842 video decoder driver");
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>");
MODULE_LICENSE("GPL");
@@ -114,6 +114,9 @@ struct adv7842_state {
bool restart_stdi_once;
bool hdmi_port_a;
+ struct dentry *debugfs_dir;
+ struct v4l2_debugfs_if *infoframes;
+
/* i2c clients */
struct i2c_client *i2c_sdp_io;
struct i2c_client *i2c_sdp;
@@ -1431,14 +1434,15 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
}
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0,
- (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
- (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- false, timings))
+ (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
+ (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
+ false, adv7842_get_dv_timings_cap(sd), timings))
return 0;
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
- (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
- (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
- false, state->aspect_ratio, timings))
+ (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
+ (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
+ false, state->aspect_ratio,
+ adv7842_get_dv_timings_cap(sd), timings))
return 0;
v4l2_dbg(2, debug, sd,
@@ -2565,58 +2569,65 @@ struct adv7842_cfg_read_infoframe {
u8 payload_addr;
};
-static void log_infoframe(struct v4l2_subdev *sd, const struct adv7842_cfg_read_infoframe *cri)
+static const struct adv7842_cfg_read_infoframe adv7842_cri[] = {
+ { "AVI", 0x01, 0xe0, 0x00 },
+ { "Audio", 0x02, 0xe3, 0x1c },
+ { "SDP", 0x04, 0xe6, 0x2a },
+ { "Vendor", 0x10, 0xec, 0x54 }
+};
+
+static int adv7842_read_infoframe_buf(struct v4l2_subdev *sd, int index,
+ u8 buf[V4L2_DEBUGFS_IF_MAX_LEN])
{
- int i;
- u8 buffer[32];
- union hdmi_infoframe frame;
- u8 len;
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct device *dev = &client->dev;
+ const struct adv7842_cfg_read_infoframe *cri = &adv7842_cri[index];
+ int len, i;
if (!(io_read(sd, 0x60) & cri->present_mask)) {
- v4l2_info(sd, "%s infoframe not received\n", cri->desc);
- return;
+ v4l2_dbg(1, debug, sd,
+ "%s infoframe not received\n", cri->desc);
+ return -ENOENT;
}
for (i = 0; i < 3; i++)
- buffer[i] = infoframe_read(sd, cri->head_addr + i);
+ buf[i] = infoframe_read(sd, cri->head_addr + i);
- len = buffer[2] + 1;
+ len = buf[2] + 1;
- if (len + 3 > sizeof(buffer)) {
- v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
- return;
+ if (len + 3 > V4L2_DEBUGFS_IF_MAX_LEN) {
+ v4l2_err(sd, "%s: invalid %s infoframe length %d\n",
+ __func__, cri->desc, len);
+ return -ENOENT;
}
for (i = 0; i < len; i++)
- buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i);
-
- if (hdmi_infoframe_unpack(&frame, buffer, len + 3) < 0) {
- v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
- return;
- }
-
- hdmi_infoframe_log(KERN_INFO, dev, &frame);
+ buf[i + 3] = infoframe_read(sd, cri->payload_addr + i);
+ return len + 3;
}
static void adv7842_log_infoframes(struct v4l2_subdev *sd)
{
- int i;
- static const struct adv7842_cfg_read_infoframe cri[] = {
- { "AVI", 0x01, 0xe0, 0x00 },
- { "Audio", 0x02, 0xe3, 0x1c },
- { "SDP", 0x04, 0xe6, 0x2a },
- { "Vendor", 0x10, 0xec, 0x54 }
- };
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct device *dev = &client->dev;
+ union hdmi_infoframe frame;
+ u8 buffer[V4L2_DEBUGFS_IF_MAX_LEN] = {};
+ int len, i;
if (!(hdmi_read(sd, 0x05) & 0x80)) {
v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
return;
}
- for (i = 0; i < ARRAY_SIZE(cri); i++)
- log_infoframe(sd, &cri[i]);
+ for (i = 0; i < ARRAY_SIZE(adv7842_cri); i++) {
+ len = adv7842_read_infoframe_buf(sd, i, buffer);
+ if (len < 0)
+ continue;
+
+ if (hdmi_infoframe_unpack(&frame, buffer, len) < 0)
+ v4l2_err(sd, "%s: unpack of %s infoframe failed\n",
+ __func__, adv7842_cri[i].desc);
+ else
+ hdmi_infoframe_log(KERN_INFO, dev, &frame);
+ }
}
#if 0
@@ -3263,6 +3274,41 @@ static int adv7842_subscribe_event(struct v4l2_subdev *sd,
}
}
+static ssize_t
+adv7842_debugfs_if_read(u32 type, void *priv, struct file *filp,
+ char __user *ubuf, size_t count, loff_t *ppos)
+{
+ u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
+ struct v4l2_subdev *sd = priv;
+ int index;
+ int len;
+
+ if (!is_hdmi(sd))
+ return 0;
+
+ switch (type) {
+ case V4L2_DEBUGFS_IF_AVI:
+ index = 0;
+ break;
+ case V4L2_DEBUGFS_IF_AUDIO:
+ index = 1;
+ break;
+ case V4L2_DEBUGFS_IF_SPD:
+ index = 2;
+ break;
+ case V4L2_DEBUGFS_IF_HDMI:
+ index = 3;
+ break;
+ default:
+ return 0;
+ }
+
+ len = adv7842_read_infoframe_buf(sd, index, buf);
+ if (len > 0)
+ len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
+ return len < 0 ? 0 : len;
+}
+
static int adv7842_registered(struct v4l2_subdev *sd)
{
struct adv7842_state *state = to_state(sd);
@@ -3270,8 +3316,15 @@ static int adv7842_registered(struct v4l2_subdev *sd)
int err;
err = cec_register_adapter(state->cec_adap, &client->dev);
- if (err)
+ if (err) {
cec_delete_adapter(state->cec_adap);
+ } else {
+ state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
+ state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
+ V4L2_DEBUGFS_IF_AVI | V4L2_DEBUGFS_IF_AUDIO |
+ V4L2_DEBUGFS_IF_SPD | V4L2_DEBUGFS_IF_HDMI, sd,
+ adv7842_debugfs_if_read);
+ }
return err;
}
@@ -3280,6 +3333,10 @@ static void adv7842_unregistered(struct v4l2_subdev *sd)
struct adv7842_state *state = to_state(sd);
cec_unregister_adapter(state->cec_adap);
+ v4l2_debugfs_if_free(state->infoframes);
+ state->infoframes = NULL;
+ debugfs_remove_recursive(state->debugfs_dir);
+ state->debugfs_dir = NULL;
}
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/i2c/alvium-csi2.c b/drivers/media/i2c/alvium-csi2.c
index 5ddfd3dcb188..05b708bd0a64 100644
--- a/drivers/media/i2c/alvium-csi2.c
+++ b/drivers/media/i2c/alvium-csi2.c
@@ -16,7 +16,6 @@
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -2240,8 +2239,6 @@ free_ctrls:
static const struct v4l2_subdev_core_ops alvium_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_video_ops alvium_video_ops = {
@@ -2289,7 +2286,7 @@ static int alvium_subdev_init(struct alvium_dev *alvium)
v4l2_i2c_subdev_init(sd, client, &alvium_subdev_ops);
sd->internal_ops = &alvium_internal_ops;
- sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
alvium->pad.flags = MEDIA_PAD_FL_SOURCE;
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c
index fc27238dd4d3..24873149096c 100644
--- a/drivers/media/i2c/ar0521.c
+++ b/drivers/media/i2c/ar0521.c
@@ -255,10 +255,10 @@ static u32 calc_pll(struct ar0521_dev *sensor, u32 freq, u16 *pre_ptr, u16 *mult
continue; /* Minimum value */
if (new_mult > 254)
break; /* Maximum, larger pre won't work either */
- if (sensor->extclk_freq * (u64)new_mult < AR0521_PLL_MIN *
+ if (sensor->extclk_freq * (u64)new_mult < (u64)AR0521_PLL_MIN *
new_pre)
continue;
- if (sensor->extclk_freq * (u64)new_mult > AR0521_PLL_MAX *
+ if (sensor->extclk_freq * (u64)new_mult > (u64)AR0521_PLL_MAX *
new_pre)
break; /* Larger pre won't work either */
new_pll = div64_round_up(sensor->extclk_freq * (u64)new_mult,
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 16f88db14981..8b028a84f5bc 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -24,7 +24,6 @@
#include <media/i2c/ds90ub9xx.h>
#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h>
@@ -717,8 +716,6 @@ static const struct v4l2_subdev_pad_ops ub953_pad_ops = {
static const struct v4l2_subdev_core_ops ub953_subdev_core_ops = {
.log_status = ub953_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_ops ub953_subdev_ops = {
@@ -1246,7 +1243,7 @@ static int ub953_subdev_init(struct ub953_data *priv)
priv->sd.internal_ops = &ub953_internal_ops;
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS;
+ V4L2_SUBDEV_FL_STREAMS;
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
priv->sd.entity.ops = &ub953_entity_ops;
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index ffe5f25f8647..33f362a00875 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -48,7 +48,6 @@
#include <media/i2c/ds90ub9xx.h>
#include <media/mipi-csi2.h>
#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -1286,7 +1285,7 @@ static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
clk_delay += v & UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK;
- ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v);
if (ret)
return ret;
@@ -3085,8 +3084,6 @@ static int ub960_log_status(struct v4l2_subdev *sd)
static const struct v4l2_subdev_core_ops ub960_subdev_core_ops = {
.log_status = ub960_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_internal_ops ub960_internal_ops = {
@@ -3667,7 +3664,7 @@ static int ub960_create_subdev(struct ub960_data *priv)
}
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS;
+ V4L2_SUBDEV_FL_STREAMS;
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
priv->sd.entity.ops = &ub960_entity_ops;
diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c
index 18ef2b35c9aa..3a4d100b9199 100644
--- a/drivers/media/i2c/dw9768.c
+++ b/drivers/media/i2c/dw9768.c
@@ -374,7 +374,8 @@ static int dw9768_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
- pm_runtime_put(sd->dev);
+ pm_runtime_mark_last_busy(sd->dev);
+ pm_runtime_put_autosuspend(sd->dev);
return 0;
}
@@ -471,10 +472,9 @@ static int dw9768_probe(struct i2c_client *client)
* to be powered on in an ACPI system. Similarly for power off in
* remove.
*/
- pm_runtime_enable(dev);
full_power = (is_acpi_node(dev_fwnode(dev)) &&
acpi_dev_state_d0(dev)) ||
- (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev));
+ (is_of_node(dev_fwnode(dev)) && !IS_ENABLED(CONFIG_PM));
if (full_power) {
ret = dw9768_runtime_resume(dev);
if (ret < 0) {
@@ -484,23 +484,26 @@ static int dw9768_probe(struct i2c_client *client)
pm_runtime_set_active(dev);
}
+ pm_runtime_enable(dev);
ret = v4l2_async_register_subdev(&dw9768->sd);
if (ret < 0) {
dev_err(dev, "failed to register V4L2 subdev: %d", ret);
goto err_power_off;
}
+ pm_runtime_set_autosuspend_delay(dev, 1000);
+ pm_runtime_use_autosuspend(dev);
pm_runtime_idle(dev);
return 0;
err_power_off:
+ pm_runtime_disable(dev);
if (full_power) {
dw9768_runtime_suspend(dev);
pm_runtime_set_suspended(dev);
}
err_clean_entity:
- pm_runtime_disable(dev);
media_entity_cleanup(&dw9768->sd.entity);
err_free_handler:
v4l2_ctrl_handler_free(&dw9768->ctrls);
@@ -517,12 +520,12 @@ static void dw9768_remove(struct i2c_client *client)
v4l2_async_unregister_subdev(&dw9768->sd);
v4l2_ctrl_handler_free(&dw9768->ctrls);
media_entity_cleanup(&dw9768->sd.entity);
+ pm_runtime_disable(dev);
if ((is_acpi_node(dev_fwnode(dev)) && acpi_dev_state_d0(dev)) ||
- (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev))) {
+ (is_of_node(dev_fwnode(dev)) && !IS_ENABLED(CONFIG_PM))) {
dw9768_runtime_suspend(dev);
pm_runtime_set_suspended(dev);
}
- pm_runtime_disable(dev);
}
static const struct of_device_id dw9768_of_table[] = {
diff --git a/drivers/media/i2c/gc0308.c b/drivers/media/i2c/gc0308.c
index fa754a8a39a6..069f42785b3c 100644
--- a/drivers/media/i2c/gc0308.c
+++ b/drivers/media/i2c/gc0308.c
@@ -18,7 +18,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -987,8 +986,6 @@ static const struct v4l2_ctrl_ops gc0308_ctrl_ops = {
static const struct v4l2_subdev_core_ops gc0308_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = gc0308_g_register,
.s_register = gc0308_s_register,
@@ -1338,7 +1335,6 @@ static int gc0308_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&gc0308->sd, client, &gc0308_subdev_ops);
gc0308->sd.internal_ops = &gc0308_internal_ops;
gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
ret = gc0308_init_controls(gc0308);
if (ret)
diff --git a/drivers/media/i2c/gc05a2.c b/drivers/media/i2c/gc05a2.c
index 0413c557e594..3f7f3d5abeeb 100644
--- a/drivers/media/i2c/gc05a2.c
+++ b/drivers/media/i2c/gc05a2.c
@@ -24,7 +24,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -1059,13 +1058,7 @@ static const struct v4l2_subdev_pad_ops gc05a2_subdev_pad_ops = {
.get_selection = gc05a2_get_selection,
};
-static const struct v4l2_subdev_core_ops gc05a2_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_ops gc05a2_subdev_ops = {
- .core = &gc05a2_core_ops,
.video = &gc05a2_video_ops,
.pad = &gc05a2_subdev_pad_ops,
};
@@ -1271,8 +1264,7 @@ static int gc05a2_probe(struct i2c_client *client)
return dev_err_probe(dev, ret,
"failed to init controls\n");
- gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
+ gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
gc05a2->pad.flags = MEDIA_PAD_FL_SOURCE;
gc05a2->sd.dev = &client->dev;
gc05a2->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
diff --git a/drivers/media/i2c/gc08a3.c b/drivers/media/i2c/gc08a3.c
index 84de5cff958d..938709a677b6 100644
--- a/drivers/media/i2c/gc08a3.c
+++ b/drivers/media/i2c/gc08a3.c
@@ -24,7 +24,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -1001,13 +1000,7 @@ static const struct v4l2_subdev_pad_ops gc08a3_subdev_pad_ops = {
.get_selection = gc08a3_get_selection,
};
-static const struct v4l2_subdev_core_ops gc08a3_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_ops gc08a3_subdev_ops = {
- .core = &gc08a3_core_ops,
.video = &gc08a3_video_ops,
.pad = &gc08a3_subdev_pad_ops,
};
@@ -1247,8 +1240,7 @@ static int gc08a3_probe(struct i2c_client *client)
goto err_power_off;
}
- gc08a3->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
+ gc08a3->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
gc08a3->pad.flags = MEDIA_PAD_FL_SOURCE;
gc08a3->sd.dev = &client->dev;
gc08a3->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
diff --git a/drivers/media/i2c/gc2145.c b/drivers/media/i2c/gc2145.c
index 667bb756d056..ba02161d46e7 100644
--- a/drivers/media/i2c/gc2145.c
+++ b/drivers/media/i2c/gc2145.c
@@ -21,7 +21,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
@@ -899,9 +898,11 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145,
return ret;
}
-static int gc2145_start_streaming(struct gc2145 *gc2145,
- struct v4l2_subdev_state *state)
+static int gc2145_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
+ struct gc2145 *gc2145 = to_gc2145(sd);
struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
const struct gc2145_format *gc2145_format;
struct v4l2_mbus_framefmt *fmt;
@@ -967,8 +968,11 @@ err_rpm_put:
return ret;
}
-static void gc2145_stop_streaming(struct gc2145 *gc2145)
+static int gc2145_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
+ struct gc2145 *gc2145 = to_gc2145(sd);
struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
int ret = 0;
@@ -983,22 +987,6 @@ static void gc2145_stop_streaming(struct gc2145 *gc2145)
pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
-}
-
-static int gc2145_set_stream(struct v4l2_subdev *sd, int enable)
-{
- struct gc2145 *gc2145 = to_gc2145(sd);
- struct v4l2_subdev_state *state;
- int ret = 0;
-
- state = v4l2_subdev_lock_and_get_active_state(sd);
-
- if (enable)
- ret = gc2145_start_streaming(gc2145, state);
- else
- gc2145_stop_streaming(gc2145);
-
- v4l2_subdev_unlock_state(state);
return ret;
}
@@ -1123,13 +1111,8 @@ static const u8 test_pattern_val[] = {
GC2145_TEST_UNIFORM | GC2145_TEST_BLACK,
};
-static const struct v4l2_subdev_core_ops gc2145_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_video_ops gc2145_video_ops = {
- .s_stream = gc2145_set_stream,
+ .s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_pad_ops gc2145_pad_ops = {
@@ -1138,10 +1121,11 @@ static const struct v4l2_subdev_pad_ops gc2145_pad_ops = {
.set_fmt = gc2145_set_pad_format,
.get_selection = gc2145_get_selection,
.enum_frame_size = gc2145_enum_frame_size,
+ .enable_streams = gc2145_enable_streams,
+ .disable_streams = gc2145_disable_streams,
};
static const struct v4l2_subdev_ops gc2145_subdev_ops = {
- .core = &gc2145_core_ops,
.video = &gc2145_video_ops,
.pad = &gc2145_pad_ops,
};
@@ -1407,8 +1391,7 @@ static int gc2145_probe(struct i2c_client *client)
goto error_power_off;
/* Initialize subdev */
- gc2145->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
+ gc2145->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
gc2145->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
/* Initialize source pad */
diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index f31f9886c924..3ac42d1ab8b4 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -644,7 +644,7 @@ struct hi556 {
/* Current mode */
const struct hi556_mode *cur_mode;
- /* To serialize asynchronus callbacks */
+ /* To serialize asynchronous callbacks */
struct mutex mutex;
/* True if the device has been identified */
diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index e78a80b2bb2e..2d54cea113e1 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -26,7 +26,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
@@ -922,11 +921,6 @@ static int imx219_init_state(struct v4l2_subdev *sd,
return 0;
}
-static const struct v4l2_subdev_core_ops imx219_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_video_ops imx219_video_ops = {
.s_stream = imx219_set_stream,
};
@@ -940,7 +934,6 @@ static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
};
static const struct v4l2_subdev_ops imx219_subdev_ops = {
- .core = &imx219_core_ops,
.video = &imx219_video_ops,
.pad = &imx219_pad_ops,
};
@@ -1166,8 +1159,7 @@ static int imx219_probe(struct i2c_client *client)
goto error_power_off;
/* Initialize subdev */
- imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
+ imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
/* Initialize source pad */
diff --git a/drivers/media/i2c/imx283.c b/drivers/media/i2c/imx283.c
index 94276f4f2d83..f676faf4b301 100644
--- a/drivers/media/i2c/imx283.c
+++ b/drivers/media/i2c/imx283.c
@@ -32,7 +32,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
@@ -1284,11 +1283,6 @@ static int imx283_get_selection(struct v4l2_subdev *sd,
}
}
-static const struct v4l2_subdev_core_ops imx283_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_video_ops imx283_video_ops = {
.s_stream = v4l2_subdev_s_stream_helper,
};
@@ -1308,7 +1302,6 @@ static const struct v4l2_subdev_internal_ops imx283_internal_ops = {
};
static const struct v4l2_subdev_ops imx283_subdev_ops = {
- .core = &imx283_core_ops,
.video = &imx283_video_ops,
.pad = &imx283_pad_ops,
};
@@ -1548,8 +1541,7 @@ static int imx283_probe(struct i2c_client *client)
goto error_pm;
/* Initialize subdev */
- imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
+ imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
imx283->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
imx283->sd.internal_ops = &imx283_internal_ops;
diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 458905dfb3e1..f5ee6bd3b52d 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -24,7 +24,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -78,7 +77,6 @@
#define IMX290_ADBIT2 CCI_REG8(0x317c)
#define IMX290_ADBIT2_10BIT 0x12
#define IMX290_ADBIT2_12BIT 0x00
-#define IMX290_CHIP_ID CCI_REG16_LE(0x319a)
#define IMX290_ADBIT3 CCI_REG8(0x31ec)
#define IMX290_ADBIT3_10BIT 0x37
#define IMX290_ADBIT3_12BIT 0x0e
@@ -1211,11 +1209,6 @@ static int imx290_entity_init_state(struct v4l2_subdev *subdev,
return 0;
}
-static const struct v4l2_subdev_core_ops imx290_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_video_ops imx290_video_ops = {
.s_stream = imx290_set_stream,
};
@@ -1229,7 +1222,6 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
};
static const struct v4l2_subdev_ops imx290_subdev_ops = {
- .core = &imx290_core_ops,
.video = &imx290_video_ops,
.pad = &imx290_pad_ops,
};
@@ -1250,11 +1242,20 @@ static int imx290_subdev_init(struct imx290 *imx290)
imx290->current_mode = &imx290_modes_ptr(imx290)[0];
+ /*
+ * After linking the subdev with the imx290 instance, we are allowed to
+ * use the pm_runtime functions. Decrease the PM usage count. The device
+ * will get suspended after the autosuspend delay, turning the power
+ * off. However, the communication happening in imx290_ctrl_update()
+ * will already be prevented even before the delay.
+ */
v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
- imx290->sd.internal_ops = &imx290_internal_ops;
- imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
imx290->sd.dev = imx290->dev;
+ pm_runtime_mark_last_busy(imx290->dev);
+ pm_runtime_put_autosuspend(imx290->dev);
+
+ imx290->sd.internal_ops = &imx290_internal_ops;
+ imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
imx290->sd.entity.ops = &imx290_subdev_entity_ops;
imx290->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
@@ -1580,6 +1581,16 @@ static int imx290_probe(struct i2c_client *client)
pm_runtime_set_autosuspend_delay(dev, 1000);
pm_runtime_use_autosuspend(dev);
+ /*
+ * Make sure the sensor is available, in STANDBY and not streaming
+ * before the V4L2 subdev is initialized.
+ */
+ ret = imx290_stop_streaming(imx290);
+ if (ret) {
+ ret = dev_err_probe(dev, ret, "Could not initialize device\n");
+ goto err_pm;
+ }
+
/* Initialize the V4L2 subdev. */
ret = imx290_subdev_init(imx290);
if (ret)
@@ -1599,13 +1610,6 @@ static int imx290_probe(struct i2c_client *client)
goto err_subdev;
}
- /*
- * Decrease the PM usage count. The device will get suspended after the
- * autosuspend delay, turning the power off.
- */
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-
return 0;
err_subdev:
diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c
index a20b0db330d3..3f7924aa1bd3 100644
--- a/drivers/media/i2c/imx415.c
+++ b/drivers/media/i2c/imx415.c
@@ -1113,8 +1113,7 @@ static int imx415_subdev_init(struct imx415 *sensor)
if (ret)
return ret;
- sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
+ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad);
diff --git a/drivers/media/i2c/max96717.c b/drivers/media/i2c/max96717.c
index 4e85b8eb1e77..9259d58ba734 100644
--- a/drivers/media/i2c/max96717.c
+++ b/drivers/media/i2c/max96717.c
@@ -697,8 +697,10 @@ static int max96717_subdev_init(struct max96717_priv *priv)
priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to init pads\n");
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to init pads\n");
+ goto err_free_ctrl;
+ }
ret = v4l2_subdev_init_finalize(&priv->sd);
if (ret) {
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
index d8735c246e52..4ef5fb06131d 100644
--- a/drivers/media/i2c/mt9p031.c
+++ b/drivers/media/i2c/mt9p031.c
@@ -17,14 +17,12 @@
#include <linux/log2.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_graph.h>
#include <linux/pm.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
-#include <media/i2c/mt9p031.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@@ -113,18 +111,25 @@
#define MT9P031_TEST_PATTERN_RED 0xa2
#define MT9P031_TEST_PATTERN_BLUE 0xa3
+struct mt9p031_model_info {
+ u32 code;
+};
+
struct mt9p031 {
struct v4l2_subdev subdev;
struct media_pad pad;
struct v4l2_rect crop; /* Sensor window */
struct v4l2_mbus_framefmt format;
- struct mt9p031_platform_data *pdata;
struct mutex power_lock; /* lock to protect power_count */
int power_count;
struct clk *clk;
struct regulator_bulk_data regulators[3];
+ unsigned int pixclk_pol:1;
+ int ext_freq;
+ int target_freq;
+
u32 code;
struct aptina_pll pll;
unsigned int clk_div;
@@ -225,7 +230,6 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
};
struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
- struct mt9p031_platform_data *pdata = mt9p031->pdata;
unsigned long ext_freq;
int ret;
@@ -233,7 +237,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
if (IS_ERR(mt9p031->clk))
return PTR_ERR(mt9p031->clk);
- ret = clk_set_rate(mt9p031->clk, pdata->ext_freq);
+ ret = clk_set_rate(mt9p031->clk, mt9p031->ext_freq);
if (ret < 0)
return ret;
@@ -245,7 +249,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
if (ext_freq > limits.ext_clock_max) {
unsigned int div;
- div = DIV_ROUND_UP(ext_freq, pdata->target_freq);
+ div = DIV_ROUND_UP(ext_freq, mt9p031->target_freq);
div = roundup_pow_of_two(div) / 2;
mt9p031->clk_div = min_t(unsigned int, div, 64);
@@ -255,7 +259,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
}
mt9p031->pll.ext_clock = ext_freq;
- mt9p031->pll.pix_clock = pdata->target_freq;
+ mt9p031->pll.pix_clock = mt9p031->target_freq;
mt9p031->use_pll = true;
return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll);
@@ -376,7 +380,7 @@ static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on)
}
/* Configure the pixel clock polarity */
- if (mt9p031->pdata && mt9p031->pdata->pixclk_pol) {
+ if (mt9p031->pixclk_pol) {
ret = mt9p031_write(client, MT9P031_PIXEL_CLOCK_CONTROL,
MT9P031_PIXEL_CLOCK_INVERT);
if (ret < 0)
@@ -1057,53 +1061,41 @@ static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
* Driver initialization and probing
*/
-static struct mt9p031_platform_data *
-mt9p031_get_pdata(struct i2c_client *client)
+static int mt9p031_parse_properties(struct mt9p031 *mt9p031, struct device *dev)
{
- struct mt9p031_platform_data *pdata = NULL;
- struct device_node *np;
struct v4l2_fwnode_endpoint endpoint = {
.bus_type = V4L2_MBUS_PARALLEL
};
+ struct fwnode_handle *np;
+ int ret;
- if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
- return client->dev.platform_data;
-
- np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1);
+ np = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
if (!np)
- return NULL;
-
- if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &endpoint) < 0)
- goto done;
+ return dev_err_probe(dev, -EINVAL, "endpoint node not found\n");
- pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- goto done;
+ ret = v4l2_fwnode_endpoint_parse(np, &endpoint);
+ fwnode_handle_put(np);
+ if (ret)
+ return dev_err_probe(dev, -EINVAL, "could not parse endpoint\n");
- of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq);
- of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq);
+ fwnode_property_read_u32(np, "input-clock-frequency",
+ &mt9p031->ext_freq);
+ fwnode_property_read_u32(np, "pixel-clock-frequency",
+ &mt9p031->target_freq);
- pdata->pixclk_pol = !!(endpoint.bus.parallel.flags &
- V4L2_MBUS_PCLK_SAMPLE_RISING);
+ mt9p031->pixclk_pol = !!(endpoint.bus.parallel.flags &
+ V4L2_MBUS_PCLK_SAMPLE_RISING);
-done:
- of_node_put(np);
- return pdata;
+ return 0;
}
static int mt9p031_probe(struct i2c_client *client)
{
- struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client);
struct i2c_adapter *adapter = client->adapter;
struct mt9p031 *mt9p031;
unsigned int i;
int ret;
- if (pdata == NULL) {
- dev_err(&client->dev, "No platform data\n");
- return -EINVAL;
- }
-
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
dev_warn(&client->dev,
"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
@@ -1114,10 +1106,13 @@ static int mt9p031_probe(struct i2c_client *client)
if (mt9p031 == NULL)
return -ENOMEM;
- mt9p031->pdata = pdata;
+ ret = mt9p031_parse_properties(mt9p031, &client->dev);
+ if (ret)
+ return ret;
+
mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF;
mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC;
- mt9p031->code = (uintptr_t)i2c_get_match_data(client);
+ mt9p031->code = (uintptr_t)device_get_match_data(&client->dev);
mt9p031->regulators[0].supply = "vdd";
mt9p031->regulators[1].supply = "vdd_io";
@@ -1145,8 +1140,8 @@ static int mt9p031_probe(struct i2c_client *client)
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
- V4L2_CID_PIXEL_RATE, pdata->target_freq,
- pdata->target_freq, 1, pdata->target_freq);
+ V4L2_CID_PIXEL_RATE, mt9p031->target_freq,
+ mt9p031->target_freq, 1, mt9p031->target_freq);
v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0,
@@ -1213,18 +1208,18 @@ static void mt9p031_remove(struct i2c_client *client)
mutex_destroy(&mt9p031->power_lock);
}
-static const struct i2c_device_id mt9p031_id[] = {
- { "mt9p006", MEDIA_BUS_FMT_SGRBG12_1X12 },
- { "mt9p031", MEDIA_BUS_FMT_SGRBG12_1X12 },
- { "mt9p031m", MEDIA_BUS_FMT_Y12_1X12 },
- { /* sentinel */ }
+static const struct mt9p031_model_info mt9p031_models_bayer = {
+ .code = MEDIA_BUS_FMT_SGRBG12_1X12
+};
+
+static const struct mt9p031_model_info mt9p031_models_mono = {
+ .code = MEDIA_BUS_FMT_Y12_1X12
};
-MODULE_DEVICE_TABLE(i2c, mt9p031_id);
static const struct of_device_id mt9p031_of_match[] = {
- { .compatible = "aptina,mt9p006", .data = (void *)MEDIA_BUS_FMT_SGRBG12_1X12 },
- { .compatible = "aptina,mt9p031", .data = (void *)MEDIA_BUS_FMT_SGRBG12_1X12 },
- { .compatible = "aptina,mt9p031m", .data = (void *)MEDIA_BUS_FMT_Y12_1X12 },
+ { .compatible = "aptina,mt9p006", .data = &mt9p031_models_bayer },
+ { .compatible = "aptina,mt9p031", .data = &mt9p031_models_bayer },
+ { .compatible = "aptina,mt9p031m", .data = &mt9p031_models_mono },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mt9p031_of_match);
@@ -1236,7 +1231,6 @@ static struct i2c_driver mt9p031_i2c_driver = {
},
.probe = mt9p031_probe,
.remove = mt9p031_remove,
- .id_table = mt9p031_id,
};
module_i2c_driver(mt9p031_i2c_driver);
diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c
index 0b9fb1ddbe59..141cb6f75b55 100644
--- a/drivers/media/i2c/ov01a10.c
+++ b/drivers/media/i2c/ov01a10.c
@@ -13,7 +13,6 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#define OV01A10_LINK_FREQ_400MHZ 400000000ULL
@@ -804,8 +803,6 @@ static int ov01a10_get_selection(struct v4l2_subdev *sd,
static const struct v4l2_subdev_core_ops ov01a10_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_video_ops ov01a10_video_ops = {
@@ -892,8 +889,7 @@ static int ov01a10_probe(struct i2c_client *client)
}
ov01a10->sd.state_lock = ov01a10->ctrl_handler.lock;
- ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
- V4L2_SUBDEV_FL_HAS_EVENTS;
+ ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops;
ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c
index 7ead3c720e0e..b9682264e2f5 100644
--- a/drivers/media/i2c/ov08x40.c
+++ b/drivers/media/i2c/ov08x40.c
@@ -3,10 +3,13 @@
#include <linux/unaligned.h>
#include <linux/acpi.h>
+#include <linux/clk.h>
#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
@@ -1215,7 +1218,7 @@ static const char * const ov08x40_test_pattern_menu[] = {
/* Configurations for supported link frequencies */
#define OV08X40_LINK_FREQ_400MHZ 400000000ULL
#define OV08X40_SCLK_96MHZ 96000000ULL
-#define OV08X40_EXT_CLK 19200000
+#define OV08X40_XVCLK 19200000
#define OV08X40_DATA_LANES 4
/*
@@ -1279,6 +1282,12 @@ static const struct ov08x40_mode supported_modes[] = {
},
};
+static const char * const ov08x40_supply_names[] = {
+ "dovdd", /* Digital I/O power */
+ "avdd", /* Analog power */
+ "dvdd", /* Digital core power */
+};
+
struct ov08x40 {
struct v4l2_subdev sd;
struct media_pad pad;
@@ -1291,6 +1300,10 @@ struct ov08x40 {
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *exposure;
+ struct clk *xvclk;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(ov08x40_supply_names)];
+
/* Current mode */
const struct ov08x40_mode *cur_mode;
@@ -1303,6 +1316,61 @@ struct ov08x40 {
#define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd)
+static int ov08x40_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov08x40 *ov08x = to_ov08x40(sd);
+ int ret;
+
+ if (is_acpi_node(dev_fwnode(dev)))
+ return 0;
+
+ ret = clk_prepare_enable(ov08x->xvclk);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable xvclk\n");
+ return ret;
+ }
+
+ if (ov08x->reset_gpio) {
+ gpiod_set_value_cansleep(ov08x->reset_gpio, 1);
+ usleep_range(1000, 2000);
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ov08x40_supply_names),
+ ov08x->supplies);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable regulators\n");
+ goto disable_clk;
+ }
+
+ gpiod_set_value_cansleep(ov08x->reset_gpio, 0);
+ usleep_range(1500, 1800);
+
+ return 0;
+
+disable_clk:
+ gpiod_set_value_cansleep(ov08x->reset_gpio, 1);
+ clk_disable_unprepare(ov08x->xvclk);
+
+ return ret;
+}
+
+static int ov08x40_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov08x40 *ov08x = to_ov08x40(sd);
+
+ if (is_acpi_node(dev_fwnode(dev)))
+ return 0;
+
+ gpiod_set_value_cansleep(ov08x->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ov08x40_supply_names),
+ ov08x->supplies);
+ clk_disable_unprepare(ov08x->xvclk);
+
+ return 0;
+}
+
/* Read registers up to 4 at a time */
static int ov08x40_read_reg(struct ov08x40 *ov08x,
u16 reg, u32 len, u32 *val)
@@ -1339,15 +1407,13 @@ static int ov08x40_read_reg(struct ov08x40 *ov08x,
return 0;
}
-static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,
- u16 last_reg, u8 val)
+static int __ov08x40_burst_fill_regs(struct i2c_client *client, u16 first_reg,
+ u16 last_reg, size_t num_regs, u8 val)
{
- struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
struct i2c_msg msgs;
- size_t i, num_regs;
+ size_t i;
int ret;
- num_regs = last_reg - first_reg + 1;
msgs.addr = client->addr;
msgs.flags = 0;
msgs.len = 2 + num_regs;
@@ -1373,6 +1439,31 @@ static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,
return 0;
}
+static int ov08x40_burst_fill_regs(struct ov08x40 *ov08x, u16 first_reg,
+ u16 last_reg, u8 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
+ size_t num_regs, num_write_regs;
+ int ret;
+
+ num_regs = last_reg - first_reg + 1;
+ num_write_regs = num_regs;
+
+ if (client->adapter->quirks && client->adapter->quirks->max_write_len)
+ num_write_regs = client->adapter->quirks->max_write_len - 2;
+
+ while (first_reg < last_reg) {
+ ret = __ov08x40_burst_fill_regs(client, first_reg, last_reg,
+ num_write_regs, val);
+ if (ret)
+ return ret;
+
+ first_reg += num_write_regs;
+ }
+
+ return 0;
+}
+
/* Write registers up to 4 at a time */
static int ov08x40_write_reg(struct ov08x40 *ov08x,
u16 reg, u32 len, u32 __val)
@@ -2049,7 +2140,7 @@ static void ov08x40_free_controls(struct ov08x40 *ov08x)
mutex_destroy(&ov08x->mutex);
}
-static int ov08x40_check_hwcfg(struct device *dev)
+static int ov08x40_check_hwcfg(struct ov08x40 *ov08x, struct device *dev)
{
struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY
@@ -2058,21 +2149,46 @@ static int ov08x40_check_hwcfg(struct device *dev)
struct fwnode_handle *fwnode = dev_fwnode(dev);
unsigned int i, j;
int ret;
- u32 ext_clk;
+ u32 xvclk_rate;
if (!fwnode)
return -ENXIO;
- ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
- &ext_clk);
- if (ret) {
- dev_err(dev, "can't get clock frequency");
- return ret;
+ if (!is_acpi_node(fwnode)) {
+ ov08x->xvclk = devm_clk_get(dev, NULL);
+ if (IS_ERR(ov08x->xvclk)) {
+ dev_err(dev, "could not get xvclk clock (%pe)\n",
+ ov08x->xvclk);
+ return PTR_ERR(ov08x->xvclk);
+ }
+
+ xvclk_rate = clk_get_rate(ov08x->xvclk);
+
+ ov08x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ov08x->reset_gpio))
+ return PTR_ERR(ov08x->reset_gpio);
+
+ for (i = 0; i < ARRAY_SIZE(ov08x40_supply_names); i++)
+ ov08x->supplies[i].supply = ov08x40_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev,
+ ARRAY_SIZE(ov08x40_supply_names),
+ ov08x->supplies);
+ if (ret)
+ return ret;
+ } else {
+ ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
+ &xvclk_rate);
+ if (ret) {
+ dev_err(dev, "can't get clock frequency");
+ return ret;
+ }
}
- if (ext_clk != OV08X40_EXT_CLK) {
+ if (xvclk_rate != OV08X40_XVCLK) {
dev_err(dev, "external clock %d is not supported",
- ext_clk);
+ xvclk_rate);
return -EINVAL;
}
@@ -2120,32 +2236,37 @@ out_err:
}
static int ov08x40_probe(struct i2c_client *client)
-{
- struct ov08x40 *ov08x;
+{ struct ov08x40 *ov08x;
int ret;
bool full_power;
+ ov08x = devm_kzalloc(&client->dev, sizeof(*ov08x), GFP_KERNEL);
+ if (!ov08x)
+ return -ENOMEM;
+
/* Check HW config */
- ret = ov08x40_check_hwcfg(&client->dev);
+ ret = ov08x40_check_hwcfg(ov08x, &client->dev);
if (ret) {
dev_err(&client->dev, "failed to check hwcfg: %d", ret);
return ret;
}
- ov08x = devm_kzalloc(&client->dev, sizeof(*ov08x), GFP_KERNEL);
- if (!ov08x)
- return -ENOMEM;
-
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops);
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
+ ret = ov08x40_power_on(&client->dev);
+ if (ret) {
+ dev_err(&client->dev, "failed to power on\n");
+ return ret;
+ }
+
/* Check module identity */
ret = ov08x40_identify_module(ov08x);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d\n", ret);
- return ret;
+ goto probe_power_off;
}
}
@@ -2154,7 +2275,7 @@ static int ov08x40_probe(struct i2c_client *client)
ret = ov08x40_init_controls(ov08x);
if (ret)
- return ret;
+ goto probe_power_off;
/* Initialize subdev */
ov08x->sd.internal_ops = &ov08x40_internal_ops;
@@ -2187,6 +2308,9 @@ error_media_entity:
error_handler_free:
ov08x40_free_controls(ov08x);
+probe_power_off:
+ ov08x40_power_off(&client->dev);
+
return ret;
}
@@ -2201,6 +2325,8 @@ static void ov08x40_remove(struct i2c_client *client)
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
+
+ ov08x40_power_off(&client->dev);
}
#ifdef CONFIG_ACPI
@@ -2212,10 +2338,17 @@ static const struct acpi_device_id ov08x40_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids);
#endif
+static const struct of_device_id ov08x40_of_match[] = {
+ { .compatible = "ovti,ov08x40" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ov08x40_of_match);
+
static struct i2c_driver ov08x40_i2c_driver = {
.driver = {
.name = "ov08x40",
.acpi_match_table = ACPI_PTR(ov08x40_acpi_ids),
+ .of_match_table = ov08x40_of_match,
},
.probe = ov08x40_probe,
.remove = ov08x40_remove,
diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index bd0b2f0f0d45..c484b753a718 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -530,7 +530,7 @@ struct ov2740 {
/* Current mode */
const struct ov2740_mode *cur_mode;
- /* NVM data inforamtion */
+ /* NVM data information */
struct nvm_data *nvm;
/* Supported modes */
@@ -1132,7 +1132,8 @@ static int ov2740_check_hwcfg(struct device *dev)
*/
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep)
- return -EPROBE_DEFER;
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "waiting for fwnode graph endpoint\n");
ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
if (ret) {
@@ -1330,7 +1331,7 @@ static int ov2740_probe(struct i2c_client *client)
ret = ov2740_check_hwcfg(dev);
if (ret)
- return dev_err_probe(dev, ret, "failed to check HW configuration\n");
+ return ret;
ov2740->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ov2740->reset_gpio)) {
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index c1d3fce4a7d3..da5cb5f45a4f 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -377,7 +377,7 @@ struct reg_value {
struct ov5640_timings {
/* Analog crop rectangle. */
struct v4l2_rect analog_crop;
- /* Visibile crop: from analog crop top-left corner. */
+ /* Visible crop: from analog crop top-left corner. */
struct v4l2_rect crop;
/* Total pixels per line: width + fixed hblank. */
u32 htot;
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index 0c32bd2940ec..004d0ee5c3f5 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -88,7 +88,6 @@ struct ov5645 {
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_fwnode_endpoint ep;
- struct v4l2_mbus_framefmt fmt;
struct v4l2_rect crop;
struct clk *xclk;
@@ -105,8 +104,6 @@ struct ov5645 {
u8 timing_tc_reg20;
u8 timing_tc_reg21;
- struct mutex power_lock; /* lock to protect power state */
-
struct gpio_desc *enable_gpio;
struct gpio_desc *rst_gpio;
};
@@ -781,11 +778,8 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
struct ov5645, ctrls);
int ret;
- mutex_lock(&ov5645->power_lock);
- if (!pm_runtime_get_if_in_use(ov5645->dev)) {
- mutex_unlock(&ov5645->power_lock);
+ if (!pm_runtime_get_if_in_use(ov5645->dev))
return 0;
- }
switch (ctrl->id) {
case V4L2_CID_SATURATION:
@@ -816,7 +810,6 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)
pm_runtime_mark_last_busy(ov5645->dev);
pm_runtime_put_autosuspend(ov5645->dev);
- mutex_unlock(&ov5645->power_lock);
return ret;
}
@@ -855,49 +848,6 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
return 0;
}
-static struct v4l2_mbus_framefmt *
-__ov5645_get_pad_format(struct ov5645 *ov5645,
- struct v4l2_subdev_state *sd_state,
- unsigned int pad,
- enum v4l2_subdev_format_whence which)
-{
- switch (which) {
- case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_state_get_format(sd_state, pad);
- case V4L2_SUBDEV_FORMAT_ACTIVE:
- return &ov5645->fmt;
- default:
- return NULL;
- }
-}
-
-static int ov5645_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *format)
-{
- struct ov5645 *ov5645 = to_ov5645(sd);
-
- format->format = *__ov5645_get_pad_format(ov5645, sd_state,
- format->pad,
- format->which);
- return 0;
-}
-
-static struct v4l2_rect *
-__ov5645_get_pad_crop(struct ov5645 *ov5645,
- struct v4l2_subdev_state *sd_state,
- unsigned int pad, enum v4l2_subdev_format_whence which)
-{
- switch (which) {
- case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_state_get_crop(sd_state, pad);
- case V4L2_SUBDEV_FORMAT_ACTIVE:
- return &ov5645->crop;
- default:
- return NULL;
- }
-}
-
static int ov5645_set_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
@@ -908,33 +858,30 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
const struct ov5645_mode_info *new_mode;
int ret;
- __crop = __ov5645_get_pad_crop(ov5645, sd_state, format->pad,
- format->which);
-
+ __crop = v4l2_subdev_state_get_crop(sd_state, 0);
new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
- ARRAY_SIZE(ov5645_mode_info_data),
- width, height,
- format->format.width, format->format.height);
+ ARRAY_SIZE(ov5645_mode_info_data),
+ width, height, format->format.width,
+ format->format.height);
__crop->width = new_mode->width;
__crop->height = new_mode->height;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- ret = v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
- new_mode->pixel_clock);
+ ret = __v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,
+ new_mode->pixel_clock);
if (ret < 0)
return ret;
- ret = v4l2_ctrl_s_ctrl(ov5645->link_freq,
- new_mode->link_freq);
+ ret = __v4l2_ctrl_s_ctrl(ov5645->link_freq,
+ new_mode->link_freq);
if (ret < 0)
return ret;
ov5645->current_mode = new_mode;
}
- __format = __ov5645_get_pad_format(ov5645, sd_state, format->pad,
- format->which);
+ __format = v4l2_subdev_state_get_format(sd_state, 0);
__format->width = __crop->width;
__format->height = __crop->height;
__format->code = MEDIA_BUS_FMT_UYVY8_1X16;
@@ -949,11 +896,15 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
static int ov5645_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state)
{
- struct v4l2_subdev_format fmt = { 0 };
-
- fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- fmt.format.width = 1920;
- fmt.format.height = 1080;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ .pad = 0,
+ .format = {
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .width = ov5645_mode_info_data[1].width,
+ .height = ov5645_mode_info_data[1].height,
+ },
+ };
ov5645_set_format(subdev, sd_state, &fmt);
@@ -964,82 +915,88 @@ static int ov5645_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
- struct ov5645 *ov5645 = to_ov5645(sd);
-
if (sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
- sel->r = *__ov5645_get_pad_crop(ov5645, sd_state, sel->pad,
- sel->which);
+ sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
return 0;
}
-static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
+static int ov5645_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
- struct ov5645 *ov5645 = to_ov5645(subdev);
+ struct ov5645 *ov5645 = to_ov5645(sd);
int ret;
- if (enable) {
- ret = pm_runtime_resume_and_get(ov5645->dev);
- if (ret < 0)
- return ret;
+ ret = pm_runtime_resume_and_get(ov5645->dev);
+ if (ret < 0)
+ return ret;
- ret = ov5645_set_register_array(ov5645,
+ ret = ov5645_set_register_array(ov5645,
ov5645->current_mode->data,
ov5645->current_mode->data_size);
- if (ret < 0) {
- dev_err(ov5645->dev, "could not set mode %dx%d\n",
- ov5645->current_mode->width,
- ov5645->current_mode->height);
- goto err_rpm_put;
- }
- ret = v4l2_ctrl_handler_setup(&ov5645->ctrls);
- if (ret < 0) {
- dev_err(ov5645->dev, "could not sync v4l2 controls\n");
- goto err_rpm_put;
- }
-
- ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);
- if (ret < 0)
- goto err_rpm_put;
-
- ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
- OV5645_SYSTEM_CTRL0_START);
- if (ret < 0)
- goto err_rpm_put;
- } else {
- ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
- if (ret < 0)
- goto stream_off_rpm_put;
+ if (ret < 0) {
+ dev_err(ov5645->dev, "could not set mode %dx%d\n",
+ ov5645->current_mode->width,
+ ov5645->current_mode->height);
+ goto err_rpm_put;
+ }
+ ret = __v4l2_ctrl_handler_setup(&ov5645->ctrls);
+ if (ret < 0) {
+ dev_err(ov5645->dev, "could not sync v4l2 controls\n");
+ goto err_rpm_put;
+ }
- ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
- OV5645_SYSTEM_CTRL0_STOP);
+ ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);
+ if (ret < 0)
+ goto err_rpm_put;
- goto stream_off_rpm_put;
- }
+ ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
+ OV5645_SYSTEM_CTRL0_START);
+ if (ret < 0)
+ goto err_rpm_put;
return 0;
err_rpm_put:
pm_runtime_put_sync(ov5645->dev);
return ret;
+}
+
+static int ov5645_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct ov5645 *ov5645 = to_ov5645(sd);
+ int ret;
+
+ ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);
+ if (ret < 0)
+ goto rpm_put;
-stream_off_rpm_put:
+ ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
+ OV5645_SYSTEM_CTRL0_STOP);
+
+rpm_put:
pm_runtime_mark_last_busy(ov5645->dev);
pm_runtime_put_autosuspend(ov5645->dev);
+
return ret;
}
static const struct v4l2_subdev_video_ops ov5645_video_ops = {
- .s_stream = ov5645_s_stream,
+ .s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
.enum_mbus_code = ov5645_enum_mbus_code,
.enum_frame_size = ov5645_enum_frame_size,
- .get_fmt = ov5645_get_format,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ov5645_set_format,
.get_selection = ov5645_get_selection,
+ .enable_streams = ov5645_enable_streams,
+ .disable_streams = ov5645_disable_streams,
};
static const struct v4l2_subdev_ops ov5645_subdev_ops = {
@@ -1069,51 +1026,44 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->dev = dev;
endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
- if (!endpoint) {
- dev_err(dev, "endpoint node not found\n");
- return -EINVAL;
- }
+ if (!endpoint)
+ return dev_err_probe(dev, -EINVAL,
+ "endpoint node not found\n");
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&ov5645->ep);
of_node_put(endpoint);
- if (ret < 0) {
- dev_err(dev, "parsing endpoint node failed\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "parsing endpoint node failed\n");
- if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
- dev_err(dev, "invalid bus type, must be CSI2\n");
- return -EINVAL;
- }
+ if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
+ return dev_err_probe(dev, -EINVAL,
+ "invalid bus type, must be CSI2\n");
/* get system clock (xclk) */
ov5645->xclk = devm_clk_get(dev, NULL);
- if (IS_ERR(ov5645->xclk)) {
- dev_err(dev, "could not get xclk");
- return PTR_ERR(ov5645->xclk);
- }
+ if (IS_ERR(ov5645->xclk))
+ return dev_err_probe(dev, PTR_ERR(ov5645->xclk),
+ "could not get xclk");
ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);
- if (ret) {
- dev_err(dev, "could not get xclk frequency\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "could not get xclk frequency\n");
/* external clock must be 24MHz, allow 1% tolerance */
- if (xclk_freq < 23760000 || xclk_freq > 24240000) {
- dev_err(dev, "external clock frequency %u is not supported\n",
- xclk_freq);
- return -EINVAL;
- }
+ if (xclk_freq < 23760000 || xclk_freq > 24240000)
+ return dev_err_probe(dev, -EINVAL,
+ "unsupported xclk frequency %u\n",
+ xclk_freq);
ret = clk_set_rate(ov5645->xclk, xclk_freq);
- if (ret) {
- dev_err(dev, "could not set xclk frequency\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "could not set xclk frequency\n");
for (i = 0; i < OV5645_NUM_SUPPLIES; i++)
ov5645->supplies[i].supply = ov5645_supply_name[i];
@@ -1124,18 +1074,14 @@ static int ov5645_probe(struct i2c_client *client)
return ret;
ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
- if (IS_ERR(ov5645->enable_gpio)) {
- dev_err(dev, "cannot get enable gpio\n");
- return PTR_ERR(ov5645->enable_gpio);
- }
+ if (IS_ERR(ov5645->enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(ov5645->enable_gpio),
+ "cannot get enable gpio\n");
ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(ov5645->rst_gpio)) {
- dev_err(dev, "cannot get reset gpio\n");
- return PTR_ERR(ov5645->rst_gpio);
- }
-
- mutex_init(&ov5645->power_lock);
+ if (IS_ERR(ov5645->rst_gpio))
+ return dev_err_probe(dev, PTR_ERR(ov5645->rst_gpio),
+ "cannot get reset gpio\n");
v4l2_ctrl_handler_init(&ov5645->ctrls, 9);
v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,
@@ -1170,9 +1116,8 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->sd.ctrl_handler = &ov5645->ctrls;
if (ov5645->ctrls.error) {
- dev_err(dev, "%s: control initialization error %d\n",
- __func__, ov5645->ctrls.error);
ret = ov5645->ctrls.error;
+ dev_err_probe(dev, ret, "failed to add controls\n");
goto free_ctrl;
}
@@ -1180,12 +1125,12 @@ static int ov5645_probe(struct i2c_client *client)
ov5645->sd.internal_ops = &ov5645_internal_ops;
ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
- ov5645->sd.dev = &client->dev;
+ ov5645->sd.dev = dev;
ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);
if (ret < 0) {
- dev_err(dev, "could not register media entity\n");
+ dev_err_probe(dev, ret, "could not register media entity\n");
goto free_ctrl;
}
@@ -1195,14 +1140,14 @@ static int ov5645_probe(struct i2c_client *client)
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);
if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {
- dev_err(dev, "could not read ID high\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read ID high\n");
goto power_down;
}
ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);
if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {
- dev_err(dev, "could not read ID low\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read ID low\n");
goto power_down;
}
@@ -1211,24 +1156,31 @@ static int ov5645_probe(struct i2c_client *client)
ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,
&ov5645->aec_pk_manual);
if (ret < 0) {
- dev_err(dev, "could not read AEC/AGC mode\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read AEC/AGC mode\n");
goto power_down;
}
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,
&ov5645->timing_tc_reg20);
if (ret < 0) {
- dev_err(dev, "could not read vflip value\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read vflip value\n");
goto power_down;
}
ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,
&ov5645->timing_tc_reg21);
if (ret < 0) {
- dev_err(dev, "could not read hflip value\n");
ret = -ENODEV;
+ dev_err_probe(dev, ret, "could not read hflip value\n");
+ goto power_down;
+ }
+
+ ov5645->sd.state_lock = ov5645->ctrls.lock;
+ ret = v4l2_subdev_init_finalize(&ov5645->sd);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "subdev init error\n");
goto power_down;
}
@@ -1236,11 +1188,9 @@ static int ov5645_probe(struct i2c_client *client)
pm_runtime_get_noresume(dev);
pm_runtime_enable(dev);
- ov5645_init_state(&ov5645->sd, NULL);
-
- ret = v4l2_async_register_subdev(&ov5645->sd);
+ ret = v4l2_async_register_subdev_sensor(&ov5645->sd);
if (ret < 0) {
- dev_err(dev, "could not register v4l2 device\n");
+ dev_err_probe(dev, ret, "could not register v4l2 device\n");
goto err_pm_runtime;
}
@@ -1254,13 +1204,13 @@ static int ov5645_probe(struct i2c_client *client)
err_pm_runtime:
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
+ v4l2_subdev_cleanup(&ov5645->sd);
power_down:
ov5645_set_power_off(dev);
free_entity:
media_entity_cleanup(&ov5645->sd.entity);
free_ctrl:
v4l2_ctrl_handler_free(&ov5645->ctrls);
- mutex_destroy(&ov5645->power_lock);
return ret;
}
@@ -1271,13 +1221,13 @@ static void ov5645_remove(struct i2c_client *client)
struct ov5645 *ov5645 = to_ov5645(sd);
v4l2_async_unregister_subdev(&ov5645->sd);
+ v4l2_subdev_cleanup(sd);
media_entity_cleanup(&ov5645->sd.entity);
v4l2_ctrl_handler_free(&ov5645->ctrls);
pm_runtime_disable(ov5645->dev);
if (!pm_runtime_status_suspended(ov5645->dev))
ov5645_set_power_off(ov5645->dev);
pm_runtime_set_suspended(ov5645->dev);
- mutex_destroy(&ov5645->power_lock);
}
static const struct i2c_device_id ov5645_id[] = {
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c
index f051045d340f..c54bbc207189 100644
--- a/drivers/media/i2c/ov5670.c
+++ b/drivers/media/i2c/ov5670.c
@@ -1879,7 +1879,7 @@ struct ov5670 {
struct gpio_desc *pwdn_gpio; /* PWDNB pin. */
struct gpio_desc *reset_gpio; /* XSHUTDOWN pin. */
- /* To serialize asynchronus callbacks */
+ /* To serialize asynchronous callbacks */
struct mutex mutex;
/* True if the device has been identified */
diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c
index 2833b14ee139..c1081deffc2f 100644
--- a/drivers/media/i2c/ov5675.c
+++ b/drivers/media/i2c/ov5675.c
@@ -510,7 +510,7 @@ struct ov5675 {
/* Current mode */
const struct ov5675_mode *cur_mode;
- /* To serialize asynchronus callbacks */
+ /* To serialize asynchronous callbacks */
struct mutex mutex;
/* True if the device has been identified */
@@ -732,7 +732,7 @@ static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE:
/* 4 least significant bits of expsoure are fractional part
* val = val << 4
- * for ov5675, the unit of exposure is differnt from other
+ * for ov5675, the unit of exposure is different from other
* OmniVision sensors, its exposure value is twice of the
* register value, the exposure should be divided by 2 before
* set register, e.g. val << 3.
diff --git a/drivers/media/i2c/ov64a40.c b/drivers/media/i2c/ov64a40.c
index 541bf74581d2..a5da4fe47e0b 100644
--- a/drivers/media/i2c/ov64a40.c
+++ b/drivers/media/i2c/ov64a40.c
@@ -18,7 +18,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h>
@@ -3200,13 +3199,7 @@ static const struct v4l2_subdev_pad_ops ov64a40_pad_ops = {
.get_selection = ov64a40_get_selection,
};
-static const struct v4l2_subdev_core_ops ov64a40_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_ops ov64a40_subdev_ops = {
- .core = &ov64a40_core_ops,
.video = &ov64a40_video_ops,
.pad = &ov64a40_pad_ops,
};
@@ -3605,8 +3598,7 @@ static int ov64a40_probe(struct i2c_client *client)
/* Initialize subdev */
ov64a40->sd.internal_ops = &ov64a40_internal_ops;
- ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE
- | V4L2_SUBDEV_FL_HAS_EVENTS;
+ ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
index 3b0fdb3c70c0..062e1023a411 100644
--- a/drivers/media/i2c/ov772x.c
+++ b/drivers/media/i2c/ov772x.c
@@ -269,7 +269,7 @@
#define AF_8x 0x08 /* Add frame when AGC reaches 8x gain */
#define AF_16x 0x0c /* Add frame when AGC reaches 16x gain */
/* AEC max step control */
-#define AEC_NO_LIMIT 0x01 /* 0 : AEC incease step has limit */
+#define AEC_NO_LIMIT 0x01 /* 0 : AEC increase step has limit */
/* 1 : No limit to AEC increase step */
/* CLKRC */
/* Input clock divider register */
diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c
index 0830676e5d5a..1f1c0de8e510 100644
--- a/drivers/media/i2c/ov7740.c
+++ b/drivers/media/i2c/ov7740.c
@@ -117,7 +117,7 @@ struct ov7740 {
struct v4l2_ctrl *brightness;
struct v4l2_ctrl *contrast;
- struct mutex mutex; /* To serialize asynchronus callbacks */
+ struct mutex mutex; /* To serialize asynchronous callbacks */
struct gpio_desc *resetb_gpio;
struct gpio_desc *pwdn_gpio;
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
index 3b94338f55ed..e6704d018248 100644
--- a/drivers/media/i2c/ov8856.c
+++ b/drivers/media/i2c/ov8856.c
@@ -1435,7 +1435,7 @@ struct ov8856 {
/* Application specified mbus format */
u32 cur_mbus_index;
- /* To serialize asynchronus callbacks */
+ /* To serialize asynchronous callbacks */
struct mutex mutex;
/* lanes index */
diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c
index 326f50a5ab51..95f9ae794846 100644
--- a/drivers/media/i2c/ov8858.c
+++ b/drivers/media/i2c/ov8858.c
@@ -24,7 +24,6 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h>
@@ -1500,13 +1499,7 @@ static const struct v4l2_subdev_pad_ops ov8858_pad_ops = {
.set_fmt = ov8858_set_fmt,
};
-static const struct v4l2_subdev_core_ops ov8858_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
static const struct v4l2_subdev_ops ov8858_subdev_ops = {
- .core = &ov8858_core_ops,
.video = &ov8858_video_ops,
.pad = &ov8858_pad_ops,
};
@@ -1917,7 +1910,7 @@ static int ov8858_probe(struct i2c_client *client)
return ret;
sd = &ov8858->subdev;
- sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov8858->pad.flags = MEDIA_PAD_FL_SOURCE;
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad);
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c
index 56df97c9886b..026ea34d6291 100644
--- a/drivers/media/i2c/ov9650.c
+++ b/drivers/media/i2c/ov9650.c
@@ -286,7 +286,7 @@ static const struct i2c_rv ov965x_init_regs[] = {
{ REG_COM5, 0x00 }, /* System clock options */
{ REG_COM2, 0x01 }, /* Output drive, soft sleep mode */
{ REG_COM10, 0x00 }, /* Slave mode, HREF vs HSYNC, signals negate */
- { REG_EDGE, 0xa6 }, /* Edge enhancement treshhold and factor */
+ { REG_EDGE, 0xa6 }, /* Edge enhancement threshold and factor */
{ REG_COM16, 0x02 }, /* Color matrix coeff double option */
{ REG_COM17, 0x08 }, /* Single frame out, banding filter */
{ 0x16, 0x06 },
diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c
index bf9e2adbff34..cae3aeefb616 100644
--- a/drivers/media/i2c/ov9734.c
+++ b/drivers/media/i2c/ov9734.c
@@ -335,7 +335,7 @@ struct ov9734 {
/* Current mode */
const struct ov9734_mode *cur_mode;
- /* To serialize asynchronus callbacks */
+ /* To serialize asynchronous callbacks */
struct mutex mutex;
};
diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
index b947a55281f0..f08db3cfe076 100644
--- a/drivers/media/i2c/st-mipid02.c
+++ b/drivers/media/i2c/st-mipid02.c
@@ -14,6 +14,7 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
#include <media/mipi-csi2.h>
@@ -67,9 +68,6 @@ static const u32 mipid02_supported_fmt_codes[] = {
MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YVYU8_1X16,
MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_VYUY8_1X16,
MEDIA_BUS_FMT_RGB565_1X16, MEDIA_BUS_FMT_BGR888_1X24,
- MEDIA_BUS_FMT_RGB565_2X8_LE, MEDIA_BUS_FMT_RGB565_2X8_BE,
- MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YVYU8_2X8,
- MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_VYUY8_2X8,
MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_JPEG_1X8
};
@@ -100,6 +98,7 @@ struct mipid02_dev {
/* remote source */
struct v4l2_async_notifier notifier;
struct v4l2_subdev *s_subdev;
+ u16 s_subdev_pad_id;
/* registers */
struct {
u8 clk_lane_reg1;
@@ -138,12 +137,6 @@ static int bpp_from_code(__u32 code)
case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_VYUY8_1X16:
case MEDIA_BUS_FMT_RGB565_1X16:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
- case MEDIA_BUS_FMT_VYUY8_2X8:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
return 16;
case MEDIA_BUS_FMT_BGR888_1X24:
return 24;
@@ -175,16 +168,10 @@ static u8 data_type_from_code(__u32 code)
case MEDIA_BUS_FMT_YVYU8_1X16:
case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_VYUY8_1X16:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
- case MEDIA_BUS_FMT_VYUY8_2X8:
return MIPI_CSI2_DT_YUV422_8B;
case MEDIA_BUS_FMT_BGR888_1X24:
return MIPI_CSI2_DT_RGB888;
case MEDIA_BUS_FMT_RGB565_1X16:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
return MIPI_CSI2_DT_RGB565;
default:
return 0;
@@ -248,8 +235,10 @@ static void mipid02_apply_reset(struct mipid02_dev *bridge)
usleep_range(5000, 10000);
}
-static int mipid02_set_power_on(struct mipid02_dev *bridge)
+static int mipid02_set_power_on(struct device *dev)
{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client;
int ret;
@@ -282,10 +271,15 @@ xclk_off:
return ret;
}
-static void mipid02_set_power_off(struct mipid02_dev *bridge)
+static int mipid02_set_power_off(struct device *dev)
{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct mipid02_dev *bridge = to_mipid02_dev(sd);
+
regulator_bulk_disable(MIPID02_NUM_SUPPLIES, bridge->supplies);
clk_disable_unprepare(bridge->xclk);
+
+ return 0;
}
static int mipid02_detect(struct mipid02_dev *bridge)
@@ -447,15 +441,19 @@ static int mipid02_configure_from_code(struct mipid02_dev *bridge,
return 0;
}
-static int mipid02_stream_disable(struct mipid02_dev *bridge)
+static int mipid02_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
+ struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client;
int ret = -EINVAL;
if (!bridge->s_subdev)
goto error;
- ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 0);
+ ret = v4l2_subdev_disable_streams(bridge->s_subdev,
+ bridge->s_subdev_pad_id, BIT(0));
if (ret)
goto error;
@@ -465,6 +463,10 @@ static int mipid02_stream_disable(struct mipid02_dev *bridge)
cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret);
if (ret)
goto error;
+
+ pm_runtime_mark_last_busy(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+
error:
if (ret)
dev_err(&client->dev, "failed to stream off %d", ret);
@@ -472,33 +474,36 @@ error:
return ret;
}
-static int mipid02_stream_enable(struct mipid02_dev *bridge)
+static int mipid02_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
{
+ struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client;
- struct v4l2_subdev_state *state;
struct v4l2_mbus_framefmt *fmt;
int ret = -EINVAL;
if (!bridge->s_subdev)
- goto error;
+ return ret;
memset(&bridge->r, 0, sizeof(bridge->r));
- state = v4l2_subdev_lock_and_get_active_state(&bridge->sd);
fmt = v4l2_subdev_state_get_format(state, MIPID02_SINK_0);
/* build registers content */
ret = mipid02_configure_from_rx(bridge, fmt);
if (ret)
- goto error;
+ return ret;
ret = mipid02_configure_from_tx(bridge);
if (ret)
- goto error;
+ return ret;
ret = mipid02_configure_from_code(bridge, fmt);
if (ret)
- goto error;
+ return ret;
- v4l2_subdev_unlock_state(state);
+ ret = pm_runtime_resume_and_get(&client->dev);
+ if (ret < 0)
+ return ret;
/* write mipi registers */
cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1,
@@ -524,33 +529,20 @@ static int mipid02_stream_enable(struct mipid02_dev *bridge)
if (ret)
goto error;
- ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 1);
+ ret = v4l2_subdev_enable_streams(bridge->s_subdev,
+ bridge->s_subdev_pad_id, BIT(0));
if (ret)
goto error;
return 0;
error:
- dev_err(&client->dev, "failed to stream on %d", ret);
- mipid02_stream_disable(bridge);
-
- return ret;
-}
-
-static int mipid02_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct mipid02_dev *bridge = to_mipid02_dev(sd);
- struct i2c_client *client = bridge->i2c_client;
- int ret = 0;
-
- dev_dbg(&client->dev, "%s : requested %d\n", __func__, enable);
-
- ret = enable ? mipid02_stream_enable(bridge) :
- mipid02_stream_disable(bridge);
- if (ret)
- dev_err(&client->dev, "failed to stream %s (%d)\n",
- enable ? "enable" : "disable", ret);
+ cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, 0, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret);
+ pm_runtime_mark_last_busy(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
return ret;
}
@@ -640,13 +632,15 @@ static int mipid02_set_fmt(struct v4l2_subdev *sd,
}
static const struct v4l2_subdev_video_ops mipid02_video_ops = {
- .s_stream = mipid02_s_stream,
+ .s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_pad_ops mipid02_pad_ops = {
.enum_mbus_code = mipid02_enum_mbus_code,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = mipid02_set_fmt,
+ .enable_streams = mipid02_enable_streams,
+ .disable_streams = mipid02_disable_streams,
};
static const struct v4l2_subdev_ops mipid02_subdev_ops = {
@@ -692,6 +686,7 @@ static int mipid02_async_bound(struct v4l2_async_notifier *notifier,
}
bridge->s_subdev = s_subdev;
+ bridge->s_subdev_pad_id = source_pad;
return 0;
}
@@ -875,7 +870,7 @@ static int mipid02_probe(struct i2c_client *client)
}
/* enable clock, power and reset device if available */
- ret = mipid02_set_power_on(bridge);
+ ret = mipid02_set_power_on(&client->dev);
if (ret)
goto entity_cleanup;
@@ -897,6 +892,15 @@ static int mipid02_probe(struct i2c_client *client)
goto power_off;
}
+ /* Enable runtime PM and turn off the device */
+ pm_runtime_set_active(dev);
+ pm_runtime_get_noresume(&client->dev);
+ pm_runtime_enable(dev);
+
+ pm_runtime_set_autosuspend_delay(&client->dev, 1000);
+ pm_runtime_use_autosuspend(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+
ret = v4l2_async_register_subdev(&bridge->sd);
if (ret < 0) {
dev_err(&client->dev, "v4l2_async_register_subdev failed %d",
@@ -911,8 +915,10 @@ static int mipid02_probe(struct i2c_client *client)
unregister_notifier:
v4l2_async_nf_unregister(&bridge->notifier);
v4l2_async_nf_cleanup(&bridge->notifier);
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
power_off:
- mipid02_set_power_off(bridge);
+ mipid02_set_power_off(&client->dev);
entity_cleanup:
media_entity_cleanup(&bridge->sd.entity);
@@ -927,7 +933,11 @@ static void mipid02_remove(struct i2c_client *client)
v4l2_async_nf_unregister(&bridge->notifier);
v4l2_async_nf_cleanup(&bridge->notifier);
v4l2_async_unregister_subdev(&bridge->sd);
- mipid02_set_power_off(bridge);
+
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ mipid02_set_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
media_entity_cleanup(&bridge->sd.entity);
}
@@ -937,10 +947,15 @@ static const struct of_device_id mipid02_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, mipid02_dt_ids);
+static const struct dev_pm_ops mipid02_pm_ops = {
+ RUNTIME_PM_OPS(mipid02_set_power_off, mipid02_set_power_on, NULL)
+};
+
static struct i2c_driver mipid02_i2c_driver = {
.driver = {
.name = "st-mipid02",
.of_match_table = mipid02_dt_ids,
+ .pm = pm_ptr(&mipid02_pm_ops),
},
.probe = mipid02_probe,
.remove = mipid02_remove,
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index 65d58ddf0287..c50d4e85dfd1 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -87,6 +87,10 @@ struct tc358743_state {
struct timer_list timer;
struct work_struct work_i2c_poll;
+ /* debugfs */
+ struct dentry *debugfs_dir;
+ struct v4l2_debugfs_if *infoframes;
+
/* edid */
u8 edid_blocks_written;
@@ -430,12 +434,35 @@ static void tc358743_erase_bksv(struct v4l2_subdev *sd)
/* --------------- AVI infoframe --------------- */
+static ssize_t
+tc358743_debugfs_if_read(u32 type, void *priv, struct file *filp,
+ char __user *ubuf, size_t count, loff_t *ppos)
+{
+ u8 buf[V4L2_DEBUGFS_IF_MAX_LEN] = {};
+ struct v4l2_subdev *sd = priv;
+ int len;
+
+ if (!is_hdmi(sd))
+ return 0;
+
+ if (type != V4L2_DEBUGFS_IF_AVI)
+ return 0;
+
+ i2c_rd(sd, PK_AVI_0HEAD, buf, PK_AVI_16BYTE - PK_AVI_0HEAD + 1);
+ len = buf[2] + 4;
+ if (len > V4L2_DEBUGFS_IF_MAX_LEN)
+ len = -ENOENT;
+ if (len > 0)
+ len = simple_read_from_buffer(ubuf, count, ppos, buf, len);
+ return len < 0 ? 0 : len;
+}
+
static void print_avi_infoframe(struct v4l2_subdev *sd)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct device *dev = &client->dev;
union hdmi_infoframe frame;
- u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
+ u8 buffer[HDMI_INFOFRAME_SIZE(AVI)] = {};
if (!is_hdmi(sd)) {
v4l2_info(sd, "DVI-D signal - AVI infoframe not supported\n");
@@ -2161,6 +2188,11 @@ static int tc358743_probe(struct i2c_client *client)
if (err < 0)
goto err_work_queues;
+ state->debugfs_dir = debugfs_create_dir(sd->name, v4l2_debugfs_root());
+ state->infoframes = v4l2_debugfs_if_alloc(state->debugfs_dir,
+ V4L2_DEBUGFS_IF_AVI, sd,
+ tc358743_debugfs_if_read);
+
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
client->addr << 1, client->adapter->name);
@@ -2168,8 +2200,10 @@ static int tc358743_probe(struct i2c_client *client)
err_work_queues:
cec_unregister_adapter(state->cec_adap);
- if (!state->i2c_client->irq)
+ if (!state->i2c_client->irq) {
+ del_timer(&state->timer);
flush_work(&state->work_i2c_poll);
+ }
cancel_delayed_work(&state->delayed_work_enable_hotplug);
mutex_destroy(&state->confctl_mutex);
err_hdl:
@@ -2188,6 +2222,8 @@ static void tc358743_remove(struct i2c_client *client)
flush_work(&state->work_i2c_poll);
}
cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
+ v4l2_debugfs_if_free(state->infoframes);
+ debugfs_remove_recursive(state->debugfs_dir);
cec_unregister_adapter(state->cec_adap);
v4l2_async_unregister_subdev(sd);
v4l2_device_unregister_subdev(sd);
diff --git a/drivers/media/i2c/thp7312.c b/drivers/media/i2c/thp7312.c
index c77440ff098c..8852c56431fe 100644
--- a/drivers/media/i2c/thp7312.c
+++ b/drivers/media/i2c/thp7312.c
@@ -27,7 +27,6 @@
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -879,8 +878,6 @@ static int thp7312_init_state(struct v4l2_subdev *sd,
static const struct v4l2_subdev_core_ops thp7312_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_subdev_video_ops thp7312_video_ops = {
@@ -2127,7 +2124,7 @@ static int thp7312_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&thp7312->sd, client, &thp7312_subdev_ops);
thp7312->sd.internal_ops = &thp7312_internal_ops;
- thp7312->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+ thp7312->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
thp7312->pad.flags = MEDIA_PAD_FL_SOURCE;
thp7312->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c
index 7526fabc7ee4..b7cedc5b3e8e 100644
--- a/drivers/media/i2c/ths7303.c
+++ b/drivers/media/i2c/ths7303.c
@@ -7,7 +7,7 @@
* Author: Chaithrika U S <chaithrika@ti.com>
*
* Contributors:
- * Hans Verkuil <hans.verkuil@cisco.com>
+ * Hans Verkuil <hansverk@cisco.com>
* Lad, Prabhakar <prabhakar.lad@ti.com>
* Martin Bugge <marbugge@cisco.com>
*
diff --git a/drivers/media/i2c/vgxy61.c b/drivers/media/i2c/vgxy61.c
index 409d2d4ffb4b..d77468c8587b 100644
--- a/drivers/media/i2c/vgxy61.c
+++ b/drivers/media/i2c/vgxy61.c
@@ -1617,7 +1617,7 @@ static int vgxy61_detect(struct vgxy61_dev *sensor)
ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL);
if (ret < 0)
- return st;
+ return ret;
if (st != VGXY61_NVM_OK)
dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st);
diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index 56dbe07a1c99..036a6375627a 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -566,8 +566,6 @@ static const struct vb2_ops video_i2c_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int video_i2c_querycap(struct file *file, void *priv,
@@ -798,13 +796,13 @@ static int video_i2c_probe(struct i2c_client *client)
queue->min_queued_buffers = 1;
queue->ops = &video_i2c_video_qops;
queue->mem_ops = &vb2_vmalloc_memops;
+ queue->lock = &data->queue_lock;
ret = vb2_queue_init(queue);
if (ret < 0)
goto error_unregister_device;
data->vdev.queue = queue;
- data->vdev.queue->lock = &data->queue_lock;
snprintf(data->vdev.name, sizeof(data->vdev.name),
"I2C %d-%d Transport Video",
diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
index 96dd0f6ccd0d..045590905582 100644
--- a/drivers/media/mc/mc-entity.c
+++ b/drivers/media/mc/mc-entity.c
@@ -768,10 +768,10 @@ done:
return ret;
}
-__must_check int __media_pipeline_start(struct media_pad *pad,
+__must_check int __media_pipeline_start(struct media_pad *origin,
struct media_pipeline *pipe)
{
- struct media_device *mdev = pad->graph_obj.mdev;
+ struct media_device *mdev = origin->graph_obj.mdev;
struct media_pipeline_pad *err_ppad;
struct media_pipeline_pad *ppad;
int ret;
@@ -782,7 +782,7 @@ __must_check int __media_pipeline_start(struct media_pad *pad,
* If the pad is already part of a pipeline, that pipeline must be the
* same as the pipe given to media_pipeline_start().
*/
- if (WARN_ON(pad->pipe && pad->pipe != pipe))
+ if (WARN_ON(origin->pipe && origin->pipe != pipe))
return -EINVAL;
/*
@@ -799,7 +799,7 @@ __must_check int __media_pipeline_start(struct media_pad *pad,
* with media_pipeline_pad instances for each pad found during graph
* walk.
*/
- ret = media_pipeline_populate(pipe, pad);
+ ret = media_pipeline_populate(pipe, origin);
if (ret)
return ret;
@@ -914,14 +914,14 @@ error:
}
EXPORT_SYMBOL_GPL(__media_pipeline_start);
-__must_check int media_pipeline_start(struct media_pad *pad,
+__must_check int media_pipeline_start(struct media_pad *origin,
struct media_pipeline *pipe)
{
- struct media_device *mdev = pad->graph_obj.mdev;
+ struct media_device *mdev = origin->graph_obj.mdev;
int ret;
mutex_lock(&mdev->graph_mutex);
- ret = __media_pipeline_start(pad, pipe);
+ ret = __media_pipeline_start(origin, pipe);
mutex_unlock(&mdev->graph_mutex);
return ret;
}
diff --git a/drivers/media/mc/mc-request.c b/drivers/media/mc/mc-request.c
index e064914c476e..5edfc2791ce7 100644
--- a/drivers/media/mc/mc-request.c
+++ b/drivers/media/mc/mc-request.c
@@ -6,7 +6,7 @@
* Copyright (C) 2018 Intel Corporation
* Copyright (C) 2018 Google, Inc.
*
- * Author: Hans Verkuil <hans.verkuil@cisco.com>
+ * Author: Hans Verkuil <hansverk@cisco.com>
* Author: Sakari Ailus <sakari.ailus@linux.intel.com>
*/
@@ -246,22 +246,21 @@ static const struct file_operations request_fops = {
struct media_request *
media_request_get_by_fd(struct media_device *mdev, int request_fd)
{
- struct fd f;
struct media_request *req;
if (!mdev || !mdev->ops ||
!mdev->ops->req_validate || !mdev->ops->req_queue)
return ERR_PTR(-EBADR);
- f = fdget(request_fd);
- if (!fd_file(f))
- goto err_no_req_fd;
+ CLASS(fd, f)(request_fd);
+ if (fd_empty(f))
+ goto err;
if (fd_file(f)->f_op != &request_fops)
- goto err_fput;
+ goto err;
req = fd_file(f)->private_data;
if (req->mdev != mdev)
- goto err_fput;
+ goto err;
/*
* Note: as long as someone has an open filehandle of the request,
@@ -272,14 +271,9 @@ media_request_get_by_fd(struct media_device *mdev, int request_fd)
* before media_request_get() is called.
*/
media_request_get(req);
- fdput(f);
-
return req;
-err_fput:
- fdput(f);
-
-err_no_req_fd:
+err:
dev_dbg(mdev->dev, "cannot find request_fd %d\n", request_fd);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 511f013cc338..2782832f5eb8 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -1584,8 +1584,6 @@ static const struct vb2_ops bttv_video_qops = {
.buf_cleanup = buf_cleanup,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static void radio_enable(struct bttv *btv)
diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c
index e489a3acb4b9..a71440611e46 100644
--- a/drivers/media/pci/bt8xx/bttv-vbi.c
+++ b/drivers/media/pci/bt8xx/bttv-vbi.c
@@ -170,8 +170,6 @@ const struct vb2_ops bttv_vbi_qops = {
.buf_cleanup = buf_cleanup_vbi,
.start_streaming = start_streaming_vbi,
.stop_streaming = stop_streaming_vbi,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c
index 6e1a0614e6d0..39e25cc53edb 100644
--- a/drivers/media/pci/cobalt/cobalt-driver.c
+++ b/drivers/media/pci/cobalt/cobalt-driver.c
@@ -44,7 +44,7 @@ module_param_named(ignore_err, cobalt_ignore_err, int, 0644);
MODULE_PARM_DESC(ignore_err,
"If set then ignore missing i2c adapters/receivers. Default: 0\n");
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com> & Morten Hestnes");
+MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com> & Morten Hestnes");
MODULE_DESCRIPTION("cobalt driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
index d4d7b264c965..ae82427e3479 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -424,8 +424,6 @@ static const struct vb2_ops cobalt_qops = {
.buf_queue = cobalt_buf_queue,
.start_streaming = cobalt_start_streaming,
.stop_streaming = cobalt_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* V4L2 ioctls */
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index acc6418db425..42d6f7b90ede 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -229,8 +229,6 @@ static const struct vb2_ops cx18_vb2_qops = {
.buf_prepare = cx18_buf_prepare,
.start_streaming = cx18_start_streaming,
.stop_streaming = cx18_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int cx18_stream_init(struct cx18 *cx, int type)
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index fdb96f80c036..219937a153b3 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1210,8 +1210,6 @@ static const struct vb2_ops cx23885_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = cx23885_start_streaming,
.stop_streaming = cx23885_stop_streaming,
};
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 3d01cdc4c7f3..05a7859cbe57 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -170,8 +170,6 @@ static const struct vb2_ops dvb_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = cx23885_start_streaming,
.stop_streaming = cx23885_stop_streaming,
};
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index 4bdd2bea3713..40817cc52fc1 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -249,8 +249,6 @@ const struct vb2_ops cx23885_vbi_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = cx23885_start_streaming,
.stop_streaming = cx23885_stop_streaming,
};
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 7d4a409c433e..35d58328db56 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -519,8 +519,6 @@ static const struct vb2_ops cx23885_video_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = cx23885_start_streaming,
.stop_streaming = cx23885_stop_streaming,
};
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index 0bee4b728a60..84aa1209e717 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -295,8 +295,6 @@ static const struct vb2_ops cx25821_video_qops = {
.buf_prepare = cx25821_buffer_prepare,
.buf_finish = cx25821_buffer_finish,
.buf_queue = cx25821_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = cx25821_start_streaming,
.stop_streaming = cx25821_stop_streaming,
};
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index d55df8fdb3b6..13b8cc46835b 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -781,8 +781,6 @@ static const struct vb2_ops blackbird_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index b33b3a5e32ec..c9cfceed2f1b 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -152,8 +152,6 @@ static const struct vb2_ops dvb_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 469aeaa725ad..e3e379e6f620 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -228,8 +228,6 @@ const struct vb2_ops cx8800_vbi_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index cefb6b25e921..0c87327689d3 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -562,8 +562,6 @@ static const struct vb2_ops cx8800_video_qops = {
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
index dff853e73fdc..7bddcbba4cf1 100644
--- a/drivers/media/pci/dt3155/dt3155.c
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -222,8 +222,6 @@ static void dt3155_buf_queue(struct vb2_buffer *vb)
static const struct vb2_ops q_ops = {
.queue_setup = dt3155_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_prepare = dt3155_buf_prepare,
.start_streaming = dt3155_start_streaming,
.stop_streaming = dt3155_stop_streaming,
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 81ec8630453b..4e98f432ed55 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -1045,8 +1045,6 @@ static const struct vb2_ops cio2_vb2_ops = {
.queue_setup = cio2_vb2_queue_setup,
.start_streaming = cio2_vb2_start_streaming,
.stop_streaming = cio2_vb2_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/**************** V4L2 interface ****************/
diff --git a/drivers/media/pci/intel/ipu6/Kconfig b/drivers/media/pci/intel/ipu6/Kconfig
index 49e4fb696573..1129e2beb4be 100644
--- a/drivers/media/pci/intel/ipu6/Kconfig
+++ b/drivers/media/pci/intel/ipu6/Kconfig
@@ -2,19 +2,13 @@ config VIDEO_INTEL_IPU6
tristate "Intel IPU6 driver"
depends on ACPI || COMPILE_TEST
depends on VIDEO_DEV
- depends on X86 && X86_64 && HAS_DMA
+ depends on X86 && HAS_DMA
depends on IPU_BRIDGE || !IPU_BRIDGE
- #
- # This driver incorrectly tries to override the dma_ops. It should
- # never have done that, but for now keep it working on architectures
- # that use dma ops
- #
- depends on ARCH_HAS_DMA_OPS
select AUXILIARY_BUS
select IOMMU_IOVA
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
- select VIDEOBUF2_DMA_CONTIG
+ select VIDEOBUF2_DMA_SG
select V4L2_FWNODE
help
This is the 6th Gen Intel Image Processing Unit, found in Intel SoCs
diff --git a/drivers/media/pci/intel/ipu6/ipu6-bus.c b/drivers/media/pci/intel/ipu6/ipu6-bus.c
index 149ec098cdbf..37d88ddb6ee7 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-bus.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-bus.c
@@ -94,8 +94,6 @@ ipu6_bus_initialize_device(struct pci_dev *pdev, struct device *parent,
if (!adev)
return ERR_PTR(-ENOMEM);
- adev->dma_mask = DMA_BIT_MASK(isp->secure_mode ? IPU6_MMU_ADDR_BITS :
- IPU6_MMU_ADDR_BITS_NON_SECURE);
adev->isp = isp;
adev->ctrl = ctrl;
adev->pdata = pdata;
@@ -106,10 +104,6 @@ ipu6_bus_initialize_device(struct pci_dev *pdev, struct device *parent,
auxdev->dev.parent = parent;
auxdev->dev.release = ipu6_bus_release;
- auxdev->dev.dma_ops = &ipu6_dma_ops;
- auxdev->dev.dma_mask = &adev->dma_mask;
- auxdev->dev.dma_parms = pdev->dev.dma_parms;
- auxdev->dev.coherent_dma_mask = adev->dma_mask;
ret = auxiliary_device_init(auxdev);
if (ret < 0) {
diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
index e47f84c30e10..277e101da137 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
@@ -24,6 +24,7 @@
#include "ipu6.h"
#include "ipu6-bus.h"
+#include "ipu6-dma.h"
#include "ipu6-buttress.h"
#include "ipu6-platform-buttress-regs.h"
@@ -214,20 +215,17 @@ static void ipu6_buttress_ipc_recv(struct ipu6_device *isp,
}
static int ipu6_buttress_ipc_send_bulk(struct ipu6_device *isp,
- enum ipu6_buttress_ipc_domain ipc_domain,
struct ipu6_ipc_buttress_bulk_msg *msgs,
u32 size)
{
unsigned long tx_timeout_jiffies, rx_timeout_jiffies;
unsigned int i, retry = BUTTRESS_IPC_CMD_SEND_RETRY;
struct ipu6_buttress *b = &isp->buttress;
- struct ipu6_buttress_ipc *ipc;
+ struct ipu6_buttress_ipc *ipc = &b->cse;
u32 val;
int ret;
int tout;
- ipc = ipc_domain == IPU6_BUTTRESS_IPC_CSE ? &b->cse : &b->ish;
-
mutex_lock(&b->ipc_mutex);
ret = ipu6_buttress_ipc_validity_open(isp, ipc);
@@ -305,7 +303,6 @@ out:
static int
ipu6_buttress_ipc_send(struct ipu6_device *isp,
- enum ipu6_buttress_ipc_domain ipc_domain,
u32 ipc_msg, u32 size, bool require_resp,
u32 expected_resp)
{
@@ -316,7 +313,7 @@ ipu6_buttress_ipc_send(struct ipu6_device *isp,
.expected_resp = expected_resp,
};
- return ipu6_buttress_ipc_send_bulk(isp, ipc_domain, &msg, 1);
+ return ipu6_buttress_ipc_send_bulk(isp, &msg, 1);
}
static irqreturn_t ipu6_buttress_call_isr(struct ipu6_bus_device *adev)
@@ -345,12 +342,16 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
u32 disable_irqs = 0;
u32 irq_status;
u32 i, count = 0;
+ int active;
- pm_runtime_get_noresume(&isp->pdev->dev);
+ active = pm_runtime_get_if_active(&isp->pdev->dev);
+ if (!active)
+ return IRQ_NONE;
irq_status = readl(isp->base + reg_irq_sts);
- if (!irq_status) {
- pm_runtime_put_noidle(&isp->pdev->dev);
+ if (irq_status == 0 || WARN_ON_ONCE(irq_status == 0xffffffffu)) {
+ if (active > 0)
+ pm_runtime_put_noidle(&isp->pdev->dev);
return IRQ_NONE;
}
@@ -381,25 +382,12 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
complete(&b->cse.recv_complete);
}
- if (irq_status & BUTTRESS_ISR_IPC_FROM_ISH_IS_WAITING) {
- dev_dbg(&isp->pdev->dev,
- "BUTTRESS_ISR_IPC_FROM_ISH_IS_WAITING\n");
- ipu6_buttress_ipc_recv(isp, &b->ish, &b->ish.recv_data);
- complete(&b->ish.recv_complete);
- }
-
if (irq_status & BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE) {
dev_dbg(&isp->pdev->dev,
"BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE\n");
complete(&b->cse.send_complete);
}
- if (irq_status & BUTTRESS_ISR_IPC_EXEC_DONE_BY_ISH) {
- dev_dbg(&isp->pdev->dev,
- "BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE\n");
- complete(&b->ish.send_complete);
- }
-
if (irq_status & BUTTRESS_ISR_SAI_VIOLATION &&
ipu6_buttress_get_secure_mode(isp))
dev_err(&isp->pdev->dev,
@@ -426,7 +414,8 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
writel(BUTTRESS_IRQS & ~disable_irqs,
isp->base + BUTTRESS_REG_ISR_ENABLE);
- pm_runtime_put(&isp->pdev->dev);
+ if (active > 0)
+ pm_runtime_put(&isp->pdev->dev);
return ret;
}
@@ -553,6 +542,7 @@ int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys,
const struct firmware *fw, struct sg_table *sgt)
{
bool is_vmalloc = is_vmalloc_addr(fw->data);
+ struct pci_dev *pdev = sys->isp->pdev;
struct page **pages;
const void *addr;
unsigned long n_pages;
@@ -562,7 +552,7 @@ int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys,
if (!is_vmalloc && !virt_addr_valid(fw->data))
return -EDOM;
- n_pages = PHYS_PFN(PAGE_ALIGN(fw->size));
+ n_pages = PFN_UP(fw->size);
pages = kmalloc_array(n_pages, sizeof(*pages), GFP_KERNEL);
if (!pages)
@@ -588,14 +578,20 @@ int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys,
goto out;
}
- ret = dma_map_sgtable(&sys->auxdev.dev, sgt, DMA_TO_DEVICE, 0);
- if (ret < 0) {
- ret = -ENOMEM;
+ ret = dma_map_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0);
+ if (ret) {
+ sg_free_table(sgt);
+ goto out;
+ }
+
+ ret = ipu6_dma_map_sgtable(sys, sgt, DMA_TO_DEVICE, 0);
+ if (ret) {
+ dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0);
sg_free_table(sgt);
goto out;
}
- dma_sync_sgtable_for_device(&sys->auxdev.dev, sgt, DMA_TO_DEVICE);
+ ipu6_dma_sync_sgtable(sys, sgt);
out:
kfree(pages);
@@ -607,7 +603,10 @@ EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6);
void ipu6_buttress_unmap_fw_image(struct ipu6_bus_device *sys,
struct sg_table *sgt)
{
- dma_unmap_sgtable(&sys->auxdev.dev, sgt, DMA_TO_DEVICE, 0);
+ struct pci_dev *pdev = sys->isp->pdev;
+
+ ipu6_dma_unmap_sgtable(sys, sgt, DMA_TO_DEVICE, 0);
+ dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0);
sg_free_table(sgt);
}
EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6);
@@ -650,7 +649,7 @@ int ipu6_buttress_authenticate(struct ipu6_device *isp)
*/
dev_info(&isp->pdev->dev, "Sending BOOT_LOAD to CSE\n");
- ret = ipu6_buttress_ipc_send(isp, IPU6_BUTTRESS_IPC_CSE,
+ ret = ipu6_buttress_ipc_send(isp,
BUTTRESS_IU2CSEDATA0_IPC_BOOT_LOAD,
1, true,
BUTTRESS_CSE2IUDATA0_IPC_BOOT_LOAD_DONE);
@@ -692,7 +691,7 @@ int ipu6_buttress_authenticate(struct ipu6_device *isp)
* IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as
*/
dev_info(&isp->pdev->dev, "Sending AUTHENTICATE_RUN to CSE\n");
- ret = ipu6_buttress_ipc_send(isp, IPU6_BUTTRESS_IPC_CSE,
+ ret = ipu6_buttress_ipc_send(isp,
BUTTRESS_IU2CSEDATA0_IPC_AUTH_RUN,
1, true,
BUTTRESS_CSE2IUDATA0_IPC_AUTH_RUN_DONE);
@@ -833,9 +832,7 @@ int ipu6_buttress_init(struct ipu6_device *isp)
mutex_init(&b->auth_mutex);
mutex_init(&b->cons_mutex);
mutex_init(&b->ipc_mutex);
- init_completion(&b->ish.send_complete);
init_completion(&b->cse.send_complete);
- init_completion(&b->ish.recv_complete);
init_completion(&b->cse.recv_complete);
b->cse.nack = BUTTRESS_CSE2IUDATA0_IPC_NACK;
@@ -847,8 +844,6 @@ int ipu6_buttress_init(struct ipu6_device *isp)
b->cse.data0_in = BUTTRESS_REG_CSE2IUDATA0;
b->cse.data0_out = BUTTRESS_REG_IU2CSEDATA0;
- /* no ISH on IPU6 */
- memset(&b->ish, 0, sizeof(b->ish));
INIT_LIST_HEAD(&b->constraints);
isp->secure_mode = ipu6_buttress_get_secure_mode(isp);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.h b/drivers/media/pci/intel/ipu6/ipu6-buttress.h
index 9b6f56958be7..482978c2a09d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-buttress.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.h
@@ -46,18 +46,12 @@ struct ipu6_buttress_ipc {
struct ipu6_buttress {
struct mutex power_mutex, auth_mutex, cons_mutex, ipc_mutex;
struct ipu6_buttress_ipc cse;
- struct ipu6_buttress_ipc ish;
struct list_head constraints;
u32 wdt_cached_value;
bool force_suspend;
u32 ref_clk;
};
-enum ipu6_buttress_ipc_domain {
- IPU6_BUTTRESS_IPC_CSE,
- IPU6_BUTTRESS_IPC_ISH,
-};
-
struct ipu6_ipc_buttress_bulk_msg {
u32 cmd;
u32 expected_resp;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.c b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
index 715b21ab4b8e..55ffd988ae4f 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-cpd.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
@@ -15,6 +15,7 @@
#include "ipu6.h"
#include "ipu6-bus.h"
#include "ipu6-cpd.h"
+#include "ipu6-dma.h"
/* 15 entries + header*/
#define MAX_PKG_DIR_ENT_CNT 16
@@ -43,9 +44,9 @@
* 63:56 55 54:48 47:32 31:24 23:0
* Rsvd Rsvd Type Version Rsvd Size
*/
-#define PKG_DIR_SIZE_MASK GENMASK(23, 0)
-#define PKG_DIR_VERSION_MASK GENMASK(47, 32)
-#define PKG_DIR_TYPE_MASK GENMASK(54, 48)
+#define PKG_DIR_SIZE_MASK GENMASK_ULL(23, 0)
+#define PKG_DIR_VERSION_MASK GENMASK_ULL(47, 32)
+#define PKG_DIR_TYPE_MASK GENMASK_ULL(54, 48)
static inline const struct ipu6_cpd_ent *ipu6_cpd_get_entry(const void *cpd,
u8 idx)
@@ -162,7 +163,6 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src)
{
dma_addr_t dma_addr_src = sg_dma_address(adev->fw_sgt.sgl);
const struct ipu6_cpd_ent *ent, *man_ent, *met_ent;
- struct device *dev = &adev->auxdev.dev;
struct ipu6_device *isp = adev->isp;
unsigned int man_sz, met_sz;
void *pkg_dir_pos;
@@ -175,8 +175,8 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src)
met_sz = met_ent->len;
adev->pkg_dir_size = PKG_DIR_SIZE + man_sz + met_sz;
- adev->pkg_dir = dma_alloc_attrs(dev, adev->pkg_dir_size,
- &adev->pkg_dir_dma_addr, GFP_KERNEL, 0);
+ adev->pkg_dir = ipu6_dma_alloc(adev, adev->pkg_dir_size,
+ &adev->pkg_dir_dma_addr, GFP_KERNEL, 0);
if (!adev->pkg_dir)
return -ENOMEM;
@@ -198,8 +198,8 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src)
met_ent->len);
if (ret) {
dev_err(&isp->pdev->dev, "Failed to parse module data\n");
- dma_free_attrs(dev, adev->pkg_dir_size,
- adev->pkg_dir, adev->pkg_dir_dma_addr, 0);
+ ipu6_dma_free(adev, adev->pkg_dir_size,
+ adev->pkg_dir, adev->pkg_dir_dma_addr, 0);
return ret;
}
@@ -211,8 +211,8 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src)
pkg_dir_pos += man_sz;
memcpy(pkg_dir_pos, src + met_ent->offset, met_sz);
- dma_sync_single_range_for_device(dev, adev->pkg_dir_dma_addr,
- 0, adev->pkg_dir_size, DMA_TO_DEVICE);
+ ipu6_dma_sync_single(adev, adev->pkg_dir_dma_addr,
+ adev->pkg_dir_size);
return 0;
}
@@ -220,8 +220,8 @@ EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, INTEL_IPU6);
void ipu6_cpd_free_pkg_dir(struct ipu6_bus_device *adev)
{
- dma_free_attrs(&adev->auxdev.dev, adev->pkg_dir_size, adev->pkg_dir,
- adev->pkg_dir_dma_addr, 0);
+ ipu6_dma_free(adev, adev->pkg_dir_size, adev->pkg_dir,
+ adev->pkg_dir_dma_addr, 0);
}
EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, INTEL_IPU6);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.c b/drivers/media/pci/intel/ipu6/ipu6-dma.c
index 92530a1cc90f..287b77a6aeab 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-dma.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.c
@@ -39,8 +39,7 @@ static struct vm_info *get_vm_info(struct ipu6_mmu *mmu, dma_addr_t iova)
return NULL;
}
-static void __dma_clear_buffer(struct page *page, size_t size,
- unsigned long attrs)
+static void __clear_buffer(struct page *page, size_t size, unsigned long attrs)
{
void *ptr;
@@ -56,8 +55,7 @@ static void __dma_clear_buffer(struct page *page, size_t size,
clflush_cache_range(ptr, size);
}
-static struct page **__dma_alloc_buffer(struct device *dev, size_t size,
- gfp_t gfp, unsigned long attrs)
+static struct page **__alloc_buffer(size_t size, gfp_t gfp, unsigned long attrs)
{
int count = PHYS_PFN(size);
int array_size = count * sizeof(struct page *);
@@ -86,7 +84,7 @@ static struct page **__dma_alloc_buffer(struct device *dev, size_t size,
pages[i + j] = pages[i] + j;
}
- __dma_clear_buffer(pages[i], PAGE_SIZE << order, attrs);
+ __clear_buffer(pages[i], PAGE_SIZE << order, attrs);
i += 1 << order;
count -= 1 << order;
}
@@ -100,29 +98,26 @@ error:
return NULL;
}
-static void __dma_free_buffer(struct device *dev, struct page **pages,
- size_t size, unsigned long attrs)
+static void __free_buffer(struct page **pages, size_t size, unsigned long attrs)
{
int count = PHYS_PFN(size);
unsigned int i;
for (i = 0; i < count && pages[i]; i++) {
- __dma_clear_buffer(pages[i], PAGE_SIZE, attrs);
+ __clear_buffer(pages[i], PAGE_SIZE, attrs);
__free_pages(pages[i], 0);
}
kvfree(pages);
}
-static void ipu6_dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle,
- size_t size,
- enum dma_data_direction dir)
+void ipu6_dma_sync_single(struct ipu6_bus_device *sys, dma_addr_t dma_handle,
+ size_t size)
{
void *vaddr;
u32 offset;
struct vm_info *info;
- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu;
+ struct ipu6_mmu *mmu = sys->mmu;
info = get_vm_info(mmu, dma_handle);
if (WARN_ON(!info))
@@ -135,25 +130,33 @@ static void ipu6_dma_sync_single_for_cpu(struct device *dev,
vaddr = info->vaddr + offset;
clflush_cache_range(vaddr, size);
}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, INTEL_IPU6);
-static void ipu6_dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sglist,
- int nents, enum dma_data_direction dir)
+void ipu6_dma_sync_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents)
{
struct scatterlist *sg;
int i;
for_each_sg(sglist, sg, nents, i)
- clflush_cache_range(page_to_virt(sg_page(sg)), sg->length);
+ clflush_cache_range(sg_virt(sg), sg->length);
}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, INTEL_IPU6);
-static void *ipu6_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp,
- unsigned long attrs)
+void ipu6_dma_sync_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt)
{
- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu;
- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev;
+ ipu6_dma_sync_sg(sys, sgt->sgl, sgt->orig_nents);
+}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, INTEL_IPU6);
+
+void *ipu6_dma_alloc(struct ipu6_bus_device *sys, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ unsigned long attrs)
+{
+ struct device *dev = &sys->auxdev.dev;
+ struct pci_dev *pdev = sys->isp->pdev;
dma_addr_t pci_dma_addr, ipu6_iova;
+ struct ipu6_mmu *mmu = sys->mmu;
struct vm_info *info;
unsigned long count;
struct page **pages;
@@ -173,7 +176,7 @@ static void *ipu6_dma_alloc(struct device *dev, size_t size,
if (!iova)
goto out_kfree;
- pages = __dma_alloc_buffer(dev, size, gfp, attrs);
+ pages = __alloc_buffer(size, gfp, attrs);
if (!pages)
goto out_free_iova;
@@ -227,7 +230,7 @@ out_unmap:
ipu6_mmu_unmap(mmu->dmap->mmu_info, ipu6_iova, PAGE_SIZE);
}
- __dma_free_buffer(dev, pages, size, attrs);
+ __free_buffer(pages, size, attrs);
out_free_iova:
__free_iova(&mmu->dmap->iovad, iova);
@@ -236,13 +239,13 @@ out_kfree:
return NULL;
}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, INTEL_IPU6);
-static void ipu6_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle,
- unsigned long attrs)
+void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr,
+ dma_addr_t dma_handle, unsigned long attrs)
{
- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu;
- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev;
+ struct ipu6_mmu *mmu = sys->mmu;
+ struct pci_dev *pdev = sys->isp->pdev;
struct iova *iova = find_iova(&mmu->dmap->iovad, PHYS_PFN(dma_handle));
dma_addr_t pci_dma_addr, ipu6_iova;
struct vm_info *info;
@@ -281,7 +284,7 @@ static void ipu6_dma_free(struct device *dev, size_t size, void *vaddr,
ipu6_mmu_unmap(mmu->dmap->mmu_info, PFN_PHYS(iova->pfn_lo),
PFN_PHYS(iova_size(iova)));
- __dma_free_buffer(dev, pages, size, attrs);
+ __free_buffer(pages, size, attrs);
mmu->tlb_invalidate(mmu);
@@ -289,13 +292,14 @@ static void ipu6_dma_free(struct device *dev, size_t size, void *vaddr,
kfree(info);
}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, INTEL_IPU6);
-static int ipu6_dma_mmap(struct device *dev, struct vm_area_struct *vma,
- void *addr, dma_addr_t iova, size_t size,
- unsigned long attrs)
+int ipu6_dma_mmap(struct ipu6_bus_device *sys, struct vm_area_struct *vma,
+ void *addr, dma_addr_t iova, size_t size,
+ unsigned long attrs)
{
- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu;
- size_t count = PHYS_PFN(PAGE_ALIGN(size));
+ struct ipu6_mmu *mmu = sys->mmu;
+ size_t count = PFN_UP(size);
struct vm_info *info;
size_t i;
int ret;
@@ -323,18 +327,17 @@ static int ipu6_dma_mmap(struct device *dev, struct vm_area_struct *vma,
return 0;
}
-static void ipu6_dma_unmap_sg(struct device *dev,
- struct scatterlist *sglist,
- int nents, enum dma_data_direction dir,
- unsigned long attrs)
+void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs)
{
- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev;
- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu;
+ struct device *dev = &sys->auxdev.dev;
+ struct ipu6_mmu *mmu = sys->mmu;
struct iova *iova = find_iova(&mmu->dmap->iovad,
PHYS_PFN(sg_dma_address(sglist)));
- int i, npages, count;
struct scatterlist *sg;
dma_addr_t pci_dma_addr;
+ unsigned int i;
if (!nents)
return;
@@ -342,31 +345,15 @@ static void ipu6_dma_unmap_sg(struct device *dev,
if (WARN_ON(!iova))
return;
- if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
- ipu6_dma_sync_sg_for_cpu(dev, sglist, nents, DMA_BIDIRECTIONAL);
-
- /* get the nents as orig_nents given by caller */
- count = 0;
- npages = iova_size(iova);
- for_each_sg(sglist, sg, nents, i) {
- if (sg_dma_len(sg) == 0 ||
- sg_dma_address(sg) == DMA_MAPPING_ERROR)
- break;
-
- npages -= PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg)));
- count++;
- if (npages <= 0)
- break;
- }
-
/*
* Before IPU6 mmu unmap, return the pci dma address back to sg
* assume the nents is less than orig_nents as the least granule
* is 1 SZ_4K page
*/
- dev_dbg(dev, "trying to unmap concatenated %u ents\n", count);
- for_each_sg(sglist, sg, count, i) {
- dev_dbg(dev, "ipu unmap sg[%d] %pad\n", i, &sg_dma_address(sg));
+ dev_dbg(dev, "trying to unmap concatenated %u ents\n", nents);
+ for_each_sg(sglist, sg, nents, i) {
+ dev_dbg(dev, "unmap sg[%d] %pad size %u\n", i,
+ &sg_dma_address(sg), sg_dma_len(sg));
pci_dma_addr = ipu6_mmu_iova_to_phys(mmu->dmap->mmu_info,
sg_dma_address(sg));
dev_dbg(dev, "return pci_dma_addr %pad back to sg[%d]\n",
@@ -380,23 +367,21 @@ static void ipu6_dma_unmap_sg(struct device *dev,
PFN_PHYS(iova_size(iova)));
mmu->tlb_invalidate(mmu);
-
- dma_unmap_sg_attrs(&pdev->dev, sglist, nents, dir, attrs);
-
__free_iova(&mmu->dmap->iovad, iova);
}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, INTEL_IPU6);
-static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction dir,
- unsigned long attrs)
+int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs)
{
- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu;
- struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev;
+ struct device *dev = &sys->auxdev.dev;
+ struct ipu6_mmu *mmu = sys->mmu;
struct scatterlist *sg;
struct iova *iova;
size_t npages = 0;
unsigned long iova_addr;
- int i, count;
+ int i;
for_each_sg(sglist, sg, nents, i) {
if (sg->offset) {
@@ -406,17 +391,11 @@ static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist,
}
}
- dev_dbg(dev, "pci_dma_map_sg trying to map %d ents\n", nents);
- count = dma_map_sg_attrs(&pdev->dev, sglist, nents, dir, attrs);
- if (count <= 0) {
- dev_err(dev, "pci_dma_map_sg %d ents failed\n", nents);
- return 0;
- }
-
- dev_dbg(dev, "pci_dma_map_sg %d ents mapped\n", count);
+ for_each_sg(sglist, sg, nents, i)
+ npages += PFN_UP(sg_dma_len(sg));
- for_each_sg(sglist, sg, count, i)
- npages += PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg)));
+ dev_dbg(dev, "dmamap trying to map %d ents %zu pages\n",
+ nents, npages);
iova = alloc_iova(&mmu->dmap->iovad, npages,
PHYS_PFN(dma_get_mask(dev)), 0);
@@ -427,12 +406,13 @@ static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist,
iova->pfn_hi);
iova_addr = iova->pfn_lo;
- for_each_sg(sglist, sg, count, i) {
+ for_each_sg(sglist, sg, nents, i) {
+ phys_addr_t iova_pa;
int ret;
- dev_dbg(dev, "mapping entry %d: iova 0x%llx phy %pad size %d\n",
- i, PFN_PHYS(iova_addr), &sg_dma_address(sg),
- sg_dma_len(sg));
+ iova_pa = PFN_PHYS(iova_addr);
+ dev_dbg(dev, "mapping entry %d: iova %pap phy %pap size %d\n",
+ i, &iova_pa, &sg_dma_address(sg), sg_dma_len(sg));
ret = ipu6_mmu_map(mmu->dmap->mmu_info, PFN_PHYS(iova_addr),
sg_dma_address(sg),
@@ -442,28 +422,51 @@ static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist,
sg_dma_address(sg) = PFN_PHYS(iova_addr);
- iova_addr += PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg)));
+ iova_addr += PFN_UP(sg_dma_len(sg));
}
- if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
- ipu6_dma_sync_sg_for_cpu(dev, sglist, nents, DMA_BIDIRECTIONAL);
+ dev_dbg(dev, "dmamap %d ents %zu pages mapped\n", nents, npages);
- return count;
+ return nents;
out_fail:
- ipu6_dma_unmap_sg(dev, sglist, i, dir, attrs);
+ ipu6_dma_unmap_sg(sys, sglist, i, dir, attrs);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, INTEL_IPU6);
+
+int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ int nents;
+
+ nents = ipu6_dma_map_sg(sys, sgt->sgl, sgt->nents, dir, attrs);
+ if (nents < 0)
+ return nents;
+
+ sgt->nents = nents;
return 0;
}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, INTEL_IPU6);
+
+void ipu6_dma_unmap_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ ipu6_dma_unmap_sg(sys, sgt->sgl, sgt->nents, dir, attrs);
+}
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, INTEL_IPU6);
/*
* Create scatter-list for the already allocated DMA buffer
*/
-static int ipu6_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
- void *cpu_addr, dma_addr_t handle, size_t size,
- unsigned long attrs)
+int ipu6_dma_get_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ void *cpu_addr, dma_addr_t handle, size_t size,
+ unsigned long attrs)
{
- struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu;
+ struct device *dev = &sys->auxdev.dev;
+ struct ipu6_mmu *mmu = sys->mmu;
struct vm_info *info;
int n_pages;
int ret = 0;
@@ -478,25 +481,12 @@ static int ipu6_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
if (WARN_ON(!info->pages))
return -ENOMEM;
- n_pages = PHYS_PFN(PAGE_ALIGN(size));
+ n_pages = PFN_UP(size);
ret = sg_alloc_table_from_pages(sgt, info->pages, n_pages, 0, size,
GFP_KERNEL);
if (ret)
- dev_warn(dev, "IPU6 get sgt table failed\n");
+ dev_warn(dev, "get sgt table failed\n");
return ret;
}
-
-const struct dma_map_ops ipu6_dma_ops = {
- .alloc = ipu6_dma_alloc,
- .free = ipu6_dma_free,
- .mmap = ipu6_dma_mmap,
- .map_sg = ipu6_dma_map_sg,
- .unmap_sg = ipu6_dma_unmap_sg,
- .sync_single_for_cpu = ipu6_dma_sync_single_for_cpu,
- .sync_single_for_device = ipu6_dma_sync_single_for_cpu,
- .sync_sg_for_cpu = ipu6_dma_sync_sg_for_cpu,
- .sync_sg_for_device = ipu6_dma_sync_sg_for_cpu,
- .get_sgtable = ipu6_dma_get_sgtable,
-};
diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.h b/drivers/media/pci/intel/ipu6/ipu6-dma.h
index 847ea5b7c925..b51244add9e6 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-dma.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.h
@@ -5,7 +5,13 @@
#define IPU6_DMA_H
#include <linux/dma-map-ops.h>
+#include <linux/dma-mapping.h>
#include <linux/iova.h>
+#include <linux/iova.h>
+#include <linux/scatterlist.h>
+#include <linux/types.h>
+
+#include "ipu6-bus.h"
struct ipu6_mmu_info;
@@ -14,6 +20,30 @@ struct ipu6_dma_mapping {
struct iova_domain iovad;
};
-extern const struct dma_map_ops ipu6_dma_ops;
-
+void ipu6_dma_sync_single(struct ipu6_bus_device *sys, dma_addr_t dma_handle,
+ size_t size);
+void ipu6_dma_sync_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents);
+void ipu6_dma_sync_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt);
+void *ipu6_dma_alloc(struct ipu6_bus_device *sys, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ unsigned long attrs);
+void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr,
+ dma_addr_t dma_handle, unsigned long attrs);
+int ipu6_dma_mmap(struct ipu6_bus_device *sys, struct vm_area_struct *vma,
+ void *addr, dma_addr_t iova, size_t size,
+ unsigned long attrs);
+int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs);
+void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs);
+int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs);
+void ipu6_dma_unmap_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs);
+int ipu6_dma_get_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
+ void *cpu_addr, dma_addr_t handle, size_t size,
+ unsigned long attrs);
#endif /* IPU6_DMA_H */
diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-com.c b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c
index 0b33fe9e703d..53edb445d939 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-com.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include "ipu6-bus.h"
+#include "ipu6-dma.h"
#include "ipu6-fw-com.h"
/*
@@ -88,7 +89,6 @@ struct ipu6_fw_com_context {
void *dma_buffer;
dma_addr_t dma_addr;
unsigned int dma_size;
- unsigned long attrs;
struct ipu6_fw_sys_queue *input_queue; /* array of host to SP queues */
struct ipu6_fw_sys_queue *output_queue; /* array of SP to host */
@@ -164,7 +164,6 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg,
struct ipu6_fw_com_context *ctx;
struct device *dev = &adev->auxdev.dev;
size_t sizeall, offset;
- unsigned long attrs = 0;
void *specific_host_addr;
unsigned int i;
@@ -206,9 +205,8 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg,
sizeall += sizeinput + sizeoutput;
- ctx->dma_buffer = dma_alloc_attrs(dev, sizeall, &ctx->dma_addr,
- GFP_KERNEL, attrs);
- ctx->attrs = attrs;
+ ctx->dma_buffer = ipu6_dma_alloc(adev, sizeall, &ctx->dma_addr,
+ GFP_KERNEL, 0);
if (!ctx->dma_buffer) {
dev_err(dev, "failed to allocate dma memory\n");
kfree(ctx);
@@ -239,10 +237,12 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg,
memcpy(specific_host_addr, cfg->specific_addr,
cfg->specific_size);
+ ipu6_dma_sync_single(adev, ctx->config_vied_addr, sizeall);
+
/* initialize input queues */
offset += specific_size;
res.reg = SYSCOM_QPR_BASE_REG;
- res.host_address = (u64)(ctx->dma_buffer + offset);
+ res.host_address = (uintptr_t)(ctx->dma_buffer + offset);
res.vied_address = ctx->dma_addr + offset;
for (i = 0; i < cfg->num_input_queues; i++)
ipu6_sys_queue_init(ctx->input_queue + i,
@@ -251,7 +251,7 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg,
/* initialize output queues */
offset += sizeinput;
- res.host_address = (u64)(ctx->dma_buffer + offset);
+ res.host_address = (uintptr_t)(ctx->dma_buffer + offset);
res.vied_address = ctx->dma_addr + offset;
for (i = 0; i < cfg->num_output_queues; i++) {
ipu6_sys_queue_init(ctx->output_queue + i,
@@ -315,8 +315,8 @@ int ipu6_fw_com_release(struct ipu6_fw_com_context *ctx, unsigned int force)
if (!force && !ctx->cell_ready(ctx->adev))
return -EBUSY;
- dma_free_attrs(&ctx->adev->auxdev.dev, ctx->dma_size,
- ctx->dma_buffer, ctx->dma_addr, ctx->attrs);
+ ipu6_dma_free(ctx->adev, ctx->dma_size,
+ ctx->dma_buffer, ctx->dma_addr, 0);
kfree(ctx);
return 0;
}
@@ -358,7 +358,7 @@ void *ipu6_send_get_token(struct ipu6_fw_com_context *ctx, int q_nbr)
index = readl(q_dmem + FW_COM_WR_REG);
- return (void *)(q->host_address + index * q->token_size);
+ return (void *)((uintptr_t)q->host_address + index * q->token_size);
}
EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, INTEL_IPU6);
@@ -395,7 +395,7 @@ void *ipu6_recv_get_token(struct ipu6_fw_com_context *ctx, int q_nbr)
if (!packets)
return NULL;
- return (void *)(q->host_address + rd * q->token_size);
+ return (void *)((uintptr_t)q->host_address + rd * q->token_size);
}
EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, INTEL_IPU6);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c b/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c
index 1715275e6776..db2874843453 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c
@@ -67,7 +67,7 @@ static void dwc_dphy_write(struct ipu6_isys *isys, u32 phy_id, u32 addr,
void __iomem *isys_base = isys->pdata->base;
void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id);
- dev_dbg(dev, "write: reg 0x%lx = data 0x%x", base + addr - isys_base,
+ dev_dbg(dev, "write: reg 0x%zx = data 0x%x", base + addr - isys_base,
data);
writel(data, base + addr);
}
@@ -80,7 +80,7 @@ static u32 dwc_dphy_read(struct ipu6_isys *isys, u32 phy_id, u32 addr)
u32 data;
data = readl(base + addr);
- dev_dbg(dev, "read: reg 0x%lx = data 0x%x", base + addr - isys_base,
+ dev_dbg(dev, "read: reg 0x%zx = data 0x%x", base + addr - isys_base,
data);
return data;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
index 03dbb0e0ea79..bbb66b56ee88 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c
@@ -13,17 +13,48 @@
#include <media/media-entity.h>
#include <media/v4l2-subdev.h>
-#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
#include <media/videobuf2-v4l2.h>
#include "ipu6-bus.h"
+#include "ipu6-dma.h"
#include "ipu6-fw-isys.h"
#include "ipu6-isys.h"
#include "ipu6-isys-video.h"
-static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers,
- unsigned int *num_planes, unsigned int sizes[],
- struct device *alloc_devs[])
+static int ipu6_isys_buf_init(struct vb2_buffer *vb)
+{
+ struct ipu6_isys *isys = vb2_get_drv_priv(vb->vb2_queue);
+ struct sg_table *sg = vb2_dma_sg_plane_desc(vb, 0);
+ struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb);
+ struct ipu6_isys_video_buffer *ivb =
+ vb2_buffer_to_ipu6_isys_video_buffer(vvb);
+ int ret;
+
+ ret = ipu6_dma_map_sgtable(isys->adev, sg, DMA_TO_DEVICE, 0);
+ if (ret)
+ return ret;
+
+ ivb->dma_addr = sg_dma_address(sg->sgl);
+
+ return 0;
+}
+
+static void ipu6_isys_buf_cleanup(struct vb2_buffer *vb)
+{
+ struct ipu6_isys *isys = vb2_get_drv_priv(vb->vb2_queue);
+ struct sg_table *sg = vb2_dma_sg_plane_desc(vb, 0);
+ struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb);
+ struct ipu6_isys_video_buffer *ivb =
+ vb2_buffer_to_ipu6_isys_video_buffer(vvb);
+
+ ivb->dma_addr = 0;
+ ipu6_dma_unmap_sgtable(isys->adev, sg, DMA_TO_DEVICE, 0);
+}
+
+static int ipu6_isys_queue_setup(struct vb2_queue *q, unsigned int *num_buffers,
+ unsigned int *num_planes, unsigned int sizes[],
+ struct device *alloc_devs[])
{
struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(q);
struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq);
@@ -207,9 +238,11 @@ ipu6_isys_buf_to_fw_frame_buf_pin(struct vb2_buffer *vb,
struct ipu6_fw_isys_frame_buff_set_abi *set)
{
struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb);
+ struct ipu6_isys_video_buffer *ivb =
+ vb2_buffer_to_ipu6_isys_video_buffer(vvb);
- set->output_pins[aq->fw_output].addr =
- vb2_dma_contig_plane_dma_addr(vb, 0);
+ set->output_pins[aq->fw_output].addr = ivb->dma_addr;
set->output_pins[aq->fw_output].out_buf_id = vb->index + 1;
}
@@ -332,7 +365,7 @@ static void buf_queue(struct vb2_buffer *vb)
dev_dbg(dev, "queue buffer %u for %s\n", vb->index, av->vdev.name);
- dma = vb2_dma_contig_plane_dma_addr(vb, 0);
+ dma = ivb->dma_addr;
dev_dbg(dev, "iova: iova %pad\n", &dma);
spin_lock_irqsave(&aq->lock, flags);
@@ -724,10 +757,14 @@ void ipu6_isys_queue_buf_ready(struct ipu6_isys_stream *stream,
}
list_for_each_entry_reverse(ib, &aq->active, head) {
+ struct ipu6_isys_video_buffer *ivb;
+ struct vb2_v4l2_buffer *vvb;
dma_addr_t addr;
vb = ipu6_isys_buffer_to_vb2_buffer(ib);
- addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ vvb = to_vb2_v4l2_buffer(vb);
+ ivb = vb2_buffer_to_ipu6_isys_video_buffer(vvb);
+ addr = ivb->dma_addr;
if (info->pin.addr != addr) {
if (first)
@@ -766,10 +803,12 @@ void ipu6_isys_queue_buf_ready(struct ipu6_isys_stream *stream,
}
static const struct vb2_ops ipu6_isys_queue_ops = {
- .queue_setup = queue_setup,
+ .queue_setup = ipu6_isys_queue_setup,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
+ .buf_init = ipu6_isys_buf_init,
.buf_prepare = ipu6_isys_buf_prepare,
+ .buf_cleanup = ipu6_isys_buf_cleanup,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
.buf_queue = buf_queue,
@@ -779,16 +818,17 @@ int ipu6_isys_queue_init(struct ipu6_isys_queue *aq)
{
struct ipu6_isys *isys = ipu6_isys_queue_to_video(aq)->isys;
struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq);
+ struct ipu6_bus_device *adev = isys->adev;
int ret;
/* no support for userptr */
if (!aq->vbq.io_modes)
aq->vbq.io_modes = VB2_MMAP | VB2_DMABUF;
- aq->vbq.drv_priv = aq;
+ aq->vbq.drv_priv = isys;
aq->vbq.ops = &ipu6_isys_queue_ops;
aq->vbq.lock = &av->mutex;
- aq->vbq.mem_ops = &vb2_dma_contig_memops;
+ aq->vbq.mem_ops = &vb2_dma_sg_memops;
aq->vbq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
aq->vbq.min_queued_buffers = 1;
aq->vbq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
@@ -797,8 +837,8 @@ int ipu6_isys_queue_init(struct ipu6_isys_queue *aq)
if (ret)
return ret;
- aq->dev = &isys->adev->auxdev.dev;
- aq->vbq.dev = &isys->adev->auxdev.dev;
+ aq->dev = &adev->auxdev.dev;
+ aq->vbq.dev = &adev->isp->pdev->dev;
spin_lock_init(&aq->lock);
INIT_LIST_HEAD(&aq->active);
INIT_LIST_HEAD(&aq->incoming);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h
index 95cfd4869d93..fe8fc796a58f 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h
@@ -38,6 +38,7 @@ struct ipu6_isys_buffer {
struct ipu6_isys_video_buffer {
struct vb2_v4l2_buffer vb_v4l2;
struct ipu6_isys_buffer ib;
+ dma_addr_t dma_addr;
};
#define IPU6_ISYS_BUFFER_LIST_FL_INCOMING BIT(0)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index b37561352ead..387963529adb 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -543,7 +543,7 @@ static int start_stream_firmware(struct ipu6_isys_video *av,
ret = ipu6_isys_fw_pin_cfg(__av, stream_cfg);
if (ret < 0) {
- ipu6_put_fw_msg_buf(av->isys, (u64)stream_cfg);
+ ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg);
return ret;
}
}
@@ -560,7 +560,7 @@ static int start_stream_firmware(struct ipu6_isys_video *av,
IPU6_FW_ISYS_SEND_TYPE_STREAM_OPEN);
if (ret < 0) {
dev_err(dev, "can't open stream (%d)\n", ret);
- ipu6_put_fw_msg_buf(av->isys, (u64)stream_cfg);
+ ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg);
return ret;
}
@@ -569,7 +569,7 @@ static int start_stream_firmware(struct ipu6_isys_video *av,
tout = wait_for_completion_timeout(&stream->stream_open_completion,
IPU6_FW_CALL_TIMEOUT_JIFFIES);
- ipu6_put_fw_msg_buf(av->isys, (u64)stream_cfg);
+ ipu6_put_fw_msg_buf(av->isys, (uintptr_t)stream_cfg);
if (!tout) {
dev_err(dev, "stream open time out\n");
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index c4aff2e2009b..7148f8fe23f5 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -34,6 +34,7 @@
#include "ipu6-bus.h"
#include "ipu6-cpd.h"
+#include "ipu6-dma.h"
#include "ipu6-isys.h"
#include "ipu6-isys-csi2.h"
#include "ipu6-mmu.h"
@@ -576,7 +577,7 @@ void update_watermark_setting(struct ipu6_isys *isys)
}
enable_iwake(isys, true);
- calc_fill_time_us = max_sram_size / isys_pb_datarate_mbs;
+ calc_fill_time_us = div64_u64(max_sram_size, isys_pb_datarate_mbs);
if (isys->pdata->ipdata->enhanced_iwake) {
ltr = isys->pdata->ipdata->ltr;
@@ -933,29 +934,27 @@ static const struct dev_pm_ops isys_pm_ops = {
static void free_fw_msg_bufs(struct ipu6_isys *isys)
{
- struct device *dev = &isys->adev->auxdev.dev;
struct isys_fw_msgs *fwmsg, *safe;
list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head)
- dma_free_attrs(dev, sizeof(struct isys_fw_msgs), fwmsg,
- fwmsg->dma_addr, 0);
+ ipu6_dma_free(isys->adev, sizeof(struct isys_fw_msgs), fwmsg,
+ fwmsg->dma_addr, 0);
list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head)
- dma_free_attrs(dev, sizeof(struct isys_fw_msgs), fwmsg,
- fwmsg->dma_addr, 0);
+ ipu6_dma_free(isys->adev, sizeof(struct isys_fw_msgs), fwmsg,
+ fwmsg->dma_addr, 0);
}
static int alloc_fw_msg_bufs(struct ipu6_isys *isys, int amount)
{
- struct device *dev = &isys->adev->auxdev.dev;
struct isys_fw_msgs *addr;
dma_addr_t dma_addr;
unsigned long flags;
unsigned int i;
for (i = 0; i < amount; i++) {
- addr = dma_alloc_attrs(dev, sizeof(struct isys_fw_msgs),
- &dma_addr, GFP_KERNEL, 0);
+ addr = ipu6_dma_alloc(isys->adev, sizeof(*addr),
+ &dma_addr, GFP_KERNEL, 0);
if (!addr)
break;
addr->dma_addr = dma_addr;
@@ -974,8 +973,8 @@ static int alloc_fw_msg_bufs(struct ipu6_isys *isys, int amount)
struct isys_fw_msgs, head);
list_del(&addr->head);
spin_unlock_irqrestore(&isys->listlock, flags);
- dma_free_attrs(dev, sizeof(struct isys_fw_msgs), addr,
- addr->dma_addr, 0);
+ ipu6_dma_free(isys->adev, sizeof(struct isys_fw_msgs), addr,
+ addr->dma_addr, 0);
spin_lock_irqsave(&isys->listlock, flags);
}
spin_unlock_irqrestore(&isys->listlock, flags);
@@ -1026,11 +1025,11 @@ void ipu6_cleanup_fw_msg_bufs(struct ipu6_isys *isys)
spin_unlock_irqrestore(&isys->listlock, flags);
}
-void ipu6_put_fw_msg_buf(struct ipu6_isys *isys, u64 data)
+void ipu6_put_fw_msg_buf(struct ipu6_isys *isys, uintptr_t data)
{
struct isys_fw_msgs *msg;
unsigned long flags;
- u64 *ptr = (u64 *)data;
+ void *ptr = (void *)data;
if (!ptr)
return;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index 86dfc2eff5d0..610b60e69152 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -180,7 +180,7 @@ struct isys_fw_msgs {
};
struct isys_fw_msgs *ipu6_get_fw_msg_buf(struct ipu6_isys_stream *stream);
-void ipu6_put_fw_msg_buf(struct ipu6_isys *isys, u64 data);
+void ipu6_put_fw_msg_buf(struct ipu6_isys *isys, uintptr_t data);
void ipu6_cleanup_fw_msg_bufs(struct ipu6_isys *isys);
extern const struct v4l2_ioctl_ops ipu6_isys_ioctl_ops;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
index c3a20507d6db..a81e9b09a3c5 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-mmu.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
@@ -97,13 +97,15 @@ static void page_table_dump(struct ipu6_mmu_info *mmu_info)
for (l1_idx = 0; l1_idx < ISP_L1PT_PTES; l1_idx++) {
u32 l2_idx;
u32 iova = (phys_addr_t)l1_idx << ISP_L1PT_SHIFT;
+ phys_addr_t l2_phys;
if (mmu_info->l1_pt[l1_idx] == mmu_info->dummy_l2_pteval)
continue;
+
+ l2_phys = TBL_PHYS_ADDR(mmu_info->l1_pt[l1_idx];)
dev_dbg(mmu_info->dev,
- "l1 entry %u; iovas 0x%8.8x-0x%8.8x, at %pa\n",
- l1_idx, iova, iova + ISP_PAGE_SIZE,
- TBL_PHYS_ADDR(mmu_info->l1_pt[l1_idx]));
+ "l1 entry %u; iovas 0x%8.8x-0x%8.8x, at %pap\n",
+ l1_idx, iova, iova + ISP_PAGE_SIZE, &l2_phys);
for (l2_idx = 0; l2_idx < ISP_L2PT_PTES; l2_idx++) {
u32 *l2_pt = mmu_info->l2_pts[l1_idx];
@@ -227,7 +229,7 @@ static u32 *alloc_l1_pt(struct ipu6_mmu_info *mmu_info)
}
mmu_info->l1_pt_dma = dma >> ISP_PADDR_SHIFT;
- dev_dbg(mmu_info->dev, "l1 pt %p mapped at %llx\n", pt, dma);
+ dev_dbg(mmu_info->dev, "l1 pt %p mapped at %pad\n", pt, &dma);
return pt;
@@ -252,75 +254,142 @@ static u32 *alloc_l2_pt(struct ipu6_mmu_info *mmu_info)
return pt;
}
+static void l2_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
+ phys_addr_t dummy, size_t size)
+{
+ unsigned int l2_entries;
+ unsigned int l2_idx;
+ unsigned long flags;
+ u32 l1_idx;
+ u32 *l2_pt;
+
+ spin_lock_irqsave(&mmu_info->lock, flags);
+ for (l1_idx = iova >> ISP_L1PT_SHIFT;
+ size > 0 && l1_idx < ISP_L1PT_PTES; l1_idx++) {
+ dev_dbg(mmu_info->dev,
+ "unmapping l2 pgtable (l1 index %u (iova 0x%8.8lx))\n",
+ l1_idx, iova);
+
+ if (mmu_info->l1_pt[l1_idx] == mmu_info->dummy_l2_pteval) {
+ dev_err(mmu_info->dev,
+ "unmap not mapped iova 0x%8.8lx l1 index %u\n",
+ iova, l1_idx);
+ continue;
+ }
+ l2_pt = mmu_info->l2_pts[l1_idx];
+
+ l2_entries = 0;
+ for (l2_idx = (iova & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT;
+ size > 0 && l2_idx < ISP_L2PT_PTES; l2_idx++) {
+ phys_addr_t pteval = TBL_PHYS_ADDR(l2_pt[l2_idx]);
+
+ dev_dbg(mmu_info->dev,
+ "unmap l2 index %u with pteval 0x%p\n",
+ l2_idx, &pteval);
+ l2_pt[l2_idx] = mmu_info->dummy_page_pteval;
+
+ iova += ISP_PAGE_SIZE;
+ size -= ISP_PAGE_SIZE;
+
+ l2_entries++;
+ }
+
+ WARN_ON_ONCE(!l2_entries);
+ clflush_cache_range(&l2_pt[l2_idx - l2_entries],
+ sizeof(l2_pt[0]) * l2_entries);
+ }
+
+ WARN_ON_ONCE(size);
+ spin_unlock_irqrestore(&mmu_info->lock, flags);
+}
+
static int l2_map(struct ipu6_mmu_info *mmu_info, unsigned long iova,
phys_addr_t paddr, size_t size)
{
- u32 l1_idx = iova >> ISP_L1PT_SHIFT;
- u32 iova_start = iova;
+ struct device *dev = mmu_info->dev;
+ unsigned int l2_entries;
u32 *l2_pt, *l2_virt;
unsigned int l2_idx;
unsigned long flags;
+ size_t mapped = 0;
dma_addr_t dma;
u32 l1_entry;
-
- dev_dbg(mmu_info->dev,
- "mapping l2 page table for l1 index %u (iova %8.8x)\n",
- l1_idx, (u32)iova);
+ u32 l1_idx;
+ int err = 0;
spin_lock_irqsave(&mmu_info->lock, flags);
- l1_entry = mmu_info->l1_pt[l1_idx];
- if (l1_entry == mmu_info->dummy_l2_pteval) {
- l2_virt = mmu_info->l2_pts[l1_idx];
- if (likely(!l2_virt)) {
- l2_virt = alloc_l2_pt(mmu_info);
- if (!l2_virt) {
- spin_unlock_irqrestore(&mmu_info->lock, flags);
- return -ENOMEM;
+
+ paddr = ALIGN(paddr, ISP_PAGE_SIZE);
+ for (l1_idx = iova >> ISP_L1PT_SHIFT;
+ size > 0 && l1_idx < ISP_L1PT_PTES; l1_idx++) {
+ dev_dbg(dev,
+ "mapping l2 page table for l1 index %u (iova %8.8x)\n",
+ l1_idx, (u32)iova);
+
+ l1_entry = mmu_info->l1_pt[l1_idx];
+ if (l1_entry == mmu_info->dummy_l2_pteval) {
+ l2_virt = mmu_info->l2_pts[l1_idx];
+ if (likely(!l2_virt)) {
+ l2_virt = alloc_l2_pt(mmu_info);
+ if (!l2_virt) {
+ err = -ENOMEM;
+ goto error;
+ }
}
- }
- dma = map_single(mmu_info, l2_virt);
- if (!dma) {
- dev_err(mmu_info->dev, "Failed to map l2pt page\n");
- free_page((unsigned long)l2_virt);
- spin_unlock_irqrestore(&mmu_info->lock, flags);
- return -EINVAL;
- }
+ dma = map_single(mmu_info, l2_virt);
+ if (!dma) {
+ dev_err(dev, "Failed to map l2pt page\n");
+ free_page((unsigned long)l2_virt);
+ err = -EINVAL;
+ goto error;
+ }
- l1_entry = dma >> ISP_PADDR_SHIFT;
+ l1_entry = dma >> ISP_PADDR_SHIFT;
- dev_dbg(mmu_info->dev, "page for l1_idx %u %p allocated\n",
- l1_idx, l2_virt);
- mmu_info->l1_pt[l1_idx] = l1_entry;
- mmu_info->l2_pts[l1_idx] = l2_virt;
- clflush_cache_range((void *)&mmu_info->l1_pt[l1_idx],
- sizeof(mmu_info->l1_pt[l1_idx]));
- }
+ dev_dbg(dev, "page for l1_idx %u %p allocated\n",
+ l1_idx, l2_virt);
+ mmu_info->l1_pt[l1_idx] = l1_entry;
+ mmu_info->l2_pts[l1_idx] = l2_virt;
- l2_pt = mmu_info->l2_pts[l1_idx];
+ clflush_cache_range(&mmu_info->l1_pt[l1_idx],
+ sizeof(mmu_info->l1_pt[l1_idx]));
+ }
- dev_dbg(mmu_info->dev, "l2_pt at %p with dma 0x%x\n", l2_pt, l1_entry);
+ l2_pt = mmu_info->l2_pts[l1_idx];
+ l2_entries = 0;
- paddr = ALIGN(paddr, ISP_PAGE_SIZE);
+ for (l2_idx = (iova & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT;
+ size > 0 && l2_idx < ISP_L2PT_PTES; l2_idx++) {
+ l2_pt[l2_idx] = paddr >> ISP_PADDR_SHIFT;
- l2_idx = (iova_start & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT;
+ dev_dbg(dev, "l2 index %u mapped as 0x%8.8x\n", l2_idx,
+ l2_pt[l2_idx]);
- dev_dbg(mmu_info->dev, "l2_idx %u, phys 0x%8.8x\n", l2_idx,
- l2_pt[l2_idx]);
- if (l2_pt[l2_idx] != mmu_info->dummy_page_pteval) {
- spin_unlock_irqrestore(&mmu_info->lock, flags);
- return -EINVAL;
- }
+ iova += ISP_PAGE_SIZE;
+ paddr += ISP_PAGE_SIZE;
+ mapped += ISP_PAGE_SIZE;
+ size -= ISP_PAGE_SIZE;
+
+ l2_entries++;
+ }
- l2_pt[l2_idx] = paddr >> ISP_PADDR_SHIFT;
+ WARN_ON_ONCE(!l2_entries);
+ clflush_cache_range(&l2_pt[l2_idx - l2_entries],
+ sizeof(l2_pt[0]) * l2_entries);
+ }
- clflush_cache_range((void *)&l2_pt[l2_idx], sizeof(l2_pt[l2_idx]));
spin_unlock_irqrestore(&mmu_info->lock, flags);
- dev_dbg(mmu_info->dev, "l2 index %u mapped as 0x%8.8x\n", l2_idx,
- l2_pt[l2_idx]);
-
return 0;
+
+error:
+ spin_unlock_irqrestore(&mmu_info->lock, flags);
+ /* unroll mapping in case something went wrong */
+ if (mapped)
+ l2_unmap(mmu_info, iova - mapped, paddr - mapped, mapped);
+
+ return err;
}
static int __ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova,
@@ -330,61 +399,21 @@ static int __ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova,
u32 iova_end = ALIGN(iova + size, ISP_PAGE_SIZE);
dev_dbg(mmu_info->dev,
- "mapping iova 0x%8.8x--0x%8.8x, size %zu at paddr 0x%10.10llx\n",
- iova_start, iova_end, size, paddr);
+ "mapping iova 0x%8.8x--0x%8.8x, size %zu at paddr %pap\n",
+ iova_start, iova_end, size, &paddr);
return l2_map(mmu_info, iova_start, paddr, size);
}
-static size_t l2_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
- phys_addr_t dummy, size_t size)
+static void __ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info,
+ unsigned long iova, size_t size)
{
- u32 l1_idx = iova >> ISP_L1PT_SHIFT;
- u32 iova_start = iova;
- unsigned int l2_idx;
- size_t unmapped = 0;
- unsigned long flags;
- u32 *l2_pt;
-
- dev_dbg(mmu_info->dev, "unmapping l2 page table for l1 index %u (iova 0x%8.8lx)\n",
- l1_idx, iova);
-
- spin_lock_irqsave(&mmu_info->lock, flags);
- if (mmu_info->l1_pt[l1_idx] == mmu_info->dummy_l2_pteval) {
- spin_unlock_irqrestore(&mmu_info->lock, flags);
- dev_err(mmu_info->dev,
- "unmap iova 0x%8.8lx l1 idx %u which was not mapped\n",
- iova, l1_idx);
- return 0;
- }
-
- for (l2_idx = (iova_start & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT;
- (iova_start & ISP_L1PT_MASK) + (l2_idx << ISP_PAGE_SHIFT)
- < iova_start + size && l2_idx < ISP_L2PT_PTES; l2_idx++) {
- l2_pt = mmu_info->l2_pts[l1_idx];
- dev_dbg(mmu_info->dev,
- "unmap l2 index %u with pteval 0x%10.10llx\n",
- l2_idx, TBL_PHYS_ADDR(l2_pt[l2_idx]));
- l2_pt[l2_idx] = mmu_info->dummy_page_pteval;
-
- clflush_cache_range((void *)&l2_pt[l2_idx],
- sizeof(l2_pt[l2_idx]));
- unmapped++;
- }
- spin_unlock_irqrestore(&mmu_info->lock, flags);
-
- return unmapped << ISP_PAGE_SHIFT;
-}
-
-static size_t __ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info,
- unsigned long iova, size_t size)
-{
- return l2_unmap(mmu_info, iova, 0, size);
+ l2_unmap(mmu_info, iova, 0, size);
}
static int allocate_trash_buffer(struct ipu6_mmu *mmu)
{
- unsigned int n_pages = PHYS_PFN(PAGE_ALIGN(IPU6_MMUV2_TRASH_RANGE));
+ unsigned int n_pages = PFN_UP(IPU6_MMUV2_TRASH_RANGE);
struct iova *iova;
unsigned int i;
dma_addr_t dma;
@@ -525,9 +554,10 @@ static struct ipu6_mmu_info *ipu6_mmu_alloc(struct ipu6_device *isp)
return NULL;
mmu_info->aperture_start = 0;
- mmu_info->aperture_end = DMA_BIT_MASK(isp->secure_mode ?
- IPU6_MMU_ADDR_BITS :
- IPU6_MMU_ADDR_BITS_NON_SECURE);
+ mmu_info->aperture_end =
+ (dma_addr_t)DMA_BIT_MASK(isp->secure_mode ?
+ IPU6_MMU_ADDR_BITS :
+ IPU6_MMU_ADDR_BITS_NON_SECURE);
mmu_info->pgsize_bitmap = SZ_4K;
mmu_info->dev = &isp->pdev->dev;
@@ -619,40 +649,13 @@ phys_addr_t ipu6_mmu_iova_to_phys(struct ipu6_mmu_info *mmu_info,
return phy_addr;
}
-static size_t ipu6_mmu_pgsize(unsigned long pgsize_bitmap,
- unsigned long addr_merge, size_t size)
-{
- unsigned int pgsize_idx;
- size_t pgsize;
-
- /* Max page size that still fits into 'size' */
- pgsize_idx = __fls(size);
-
- if (likely(addr_merge)) {
- /* Max page size allowed by address */
- unsigned int align_pgsize_idx = __ffs(addr_merge);
-
- pgsize_idx = min(pgsize_idx, align_pgsize_idx);
- }
-
- pgsize = (1UL << (pgsize_idx + 1)) - 1;
- pgsize &= pgsize_bitmap;
-
- WARN_ON(!pgsize);
-
- /* pick the biggest page */
- pgsize_idx = __fls(pgsize);
- pgsize = 1UL << pgsize_idx;
-
- return pgsize;
-}
-
-size_t ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
- size_t size)
+void ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
+ size_t size)
{
- size_t unmapped_page, unmapped = 0;
unsigned int min_pagesz;
+ dev_dbg(mmu_info->dev, "unmapping iova 0x%lx size 0x%zx\n", iova, size);
+
/* find out the minimum page size supported */
min_pagesz = 1 << __ffs(mmu_info->pgsize_bitmap);
@@ -664,38 +667,16 @@ size_t ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
if (!IS_ALIGNED(iova | size, min_pagesz)) {
dev_err(NULL, "unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n",
iova, size, min_pagesz);
- return -EINVAL;
- }
-
- /*
- * Keep iterating until we either unmap 'size' bytes (or more)
- * or we hit an area that isn't mapped.
- */
- while (unmapped < size) {
- size_t pgsize = ipu6_mmu_pgsize(mmu_info->pgsize_bitmap,
- iova, size - unmapped);
-
- unmapped_page = __ipu6_mmu_unmap(mmu_info, iova, pgsize);
- if (!unmapped_page)
- break;
-
- dev_dbg(mmu_info->dev, "unmapped: iova 0x%lx size 0x%zx\n",
- iova, unmapped_page);
-
- iova += unmapped_page;
- unmapped += unmapped_page;
+ return;
}
- return unmapped;
+ __ipu6_mmu_unmap(mmu_info, iova, size);
}
int ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova,
phys_addr_t paddr, size_t size)
{
- unsigned long orig_iova = iova;
unsigned int min_pagesz;
- size_t orig_size = size;
- int ret = 0;
if (mmu_info->pgsize_bitmap == 0UL)
return -ENODEV;
@@ -718,28 +699,7 @@ int ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova,
dev_dbg(mmu_info->dev, "map: iova 0x%lx pa %pa size 0x%zx\n",
iova, &paddr, size);
- while (size) {
- size_t pgsize = ipu6_mmu_pgsize(mmu_info->pgsize_bitmap,
- iova | paddr, size);
-
- dev_dbg(mmu_info->dev,
- "mapping: iova 0x%lx pa %pa pgsize 0x%zx\n",
- iova, &paddr, pgsize);
-
- ret = __ipu6_mmu_map(mmu_info, iova, paddr, pgsize);
- if (ret)
- break;
-
- iova += pgsize;
- paddr += pgsize;
- size -= pgsize;
- }
-
- /* unroll mapping in case something went wrong */
- if (ret)
- ipu6_mmu_unmap(mmu_info, orig_iova, orig_size - size);
-
- return ret;
+ return __ipu6_mmu_map(mmu_info, iova, paddr, size);
}
static void ipu6_mmu_destroy(struct ipu6_mmu *mmu)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.h b/drivers/media/pci/intel/ipu6/ipu6-mmu.h
index 21cdb0f146eb..8e40b4a66d7d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-mmu.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.h
@@ -66,8 +66,8 @@ int ipu6_mmu_hw_init(struct ipu6_mmu *mmu);
void ipu6_mmu_hw_cleanup(struct ipu6_mmu *mmu);
int ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova,
phys_addr_t paddr, size_t size);
-size_t ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
- size_t size);
+void ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova,
+ size_t size);
phys_addr_t ipu6_mmu_iova_to_phys(struct ipu6_mmu_info *mmu_info,
dma_addr_t iova);
#endif
diff --git a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
index 20f27011df43..efd65e494c16 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
@@ -219,8 +219,6 @@ enum {
BUTTRESS_ISR_IS_IRQ | BUTTRESS_ISR_PS_IRQ)
#define BUTTRESS_EVENT (BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING | \
- BUTTRESS_ISR_IPC_FROM_ISH_IS_WAITING | \
BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE | \
- BUTTRESS_ISR_IPC_EXEC_DONE_BY_ISH | \
BUTTRESS_ISR_SAI_VIOLATION)
#endif /* IPU6_PLATFORM_BUTTRESS_REGS_H */
diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c
index 7fb707d35309..a38292e8eaac 100644
--- a/drivers/media/pci/intel/ipu6/ipu6.c
+++ b/drivers/media/pci/intel/ipu6/ipu6.c
@@ -247,7 +247,8 @@ ipu6_pkg_dir_configure_spc(struct ipu6_device *isp,
dma_addr = sg_dma_address(isp->psys->fw_sgt.sgl);
pg_offset = server_fw_addr - dma_addr;
- prog = (struct ipu6_cell_program *)((u64)isp->cpd_fw->data + pg_offset);
+ prog = (struct ipu6_cell_program *)((uintptr_t)isp->cpd_fw->data +
+ pg_offset);
spc_base = base + prog->regs_addr;
if (spc_base != (base + hw_variant->spc_offset))
dev_warn(&isp->pdev->dev,
@@ -752,6 +753,9 @@ static void ipu6_pci_reset_done(struct pci_dev *pdev)
*/
static int ipu6_suspend(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ synchronize_irq(pdev->irq);
return 0;
}
diff --git a/drivers/media/pci/mantis/mantis_core.h b/drivers/media/pci/mantis/mantis_core.h
deleted file mode 100644
index 93c89a10a2c7..000000000000
--- a/drivers/media/pci/mantis/mantis_core.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- Mantis PCI bridge driver
-
- Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-*/
-
-#ifndef __MANTIS_CORE_H
-#define __MANTIS_CORE_H
-
-#include "mantis_common.h"
-
-
-#define FE_TYPE_SAT 0
-#define FE_TYPE_CAB 1
-#define FE_TYPE_TER 2
-
-#define FE_TYPE_TS204 0
-#define FE_TYPE_TS188 1
-
-
-struct vendorname {
- u8 *sub_vendor_name;
- u32 sub_vendor_id;
-};
-
-struct devicetype {
- u8 *sub_device_name;
- u32 sub_device_id;
- u8 device_type;
- u32 type_flags;
-};
-
-
-extern int mantis_dma_init(struct mantis_pci *mantis);
-extern int mantis_dma_exit(struct mantis_pci *mantis);
-extern void mantis_dma_start(struct mantis_pci *mantis);
-extern void mantis_dma_stop(struct mantis_pci *mantis);
-extern int mantis_i2c_init(struct mantis_pci *mantis);
-extern int mantis_i2c_exit(struct mantis_pci *mantis);
-
-#endif /* __MANTIS_CORE_H */
diff --git a/drivers/media/pci/mgb4/mgb4_cmt.c b/drivers/media/pci/mgb4/mgb4_cmt.c
index 70dc78ef193c..a25b68403bc6 100644
--- a/drivers/media/pci/mgb4/mgb4_cmt.c
+++ b/drivers/media/pci/mgb4/mgb4_cmt.c
@@ -227,6 +227,8 @@ void mgb4_cmt_set_vin_freq_range(struct mgb4_vin_dev *vindev,
u32 config;
size_t i;
+ freq_range = array_index_nospec(freq_range, ARRAY_SIZE(cmt_vals_in));
+
addr = cmt_addrs_in[vindev->config->id];
reg_set = cmt_vals_in[freq_range];
diff --git a/drivers/media/pci/mgb4/mgb4_core.c b/drivers/media/pci/mgb4/mgb4_core.c
index 2819bbdab484..bc63dc81bcae 100644
--- a/drivers/media/pci/mgb4/mgb4_core.c
+++ b/drivers/media/pci/mgb4/mgb4_core.c
@@ -582,9 +582,7 @@ static int mgb4_probe(struct pci_dev *pdev, const struct pci_device_id *id)
NULL);
#endif
-#ifdef CONFIG_DEBUG_FS
mgbdev->debugfs = debugfs_create_dir(dev_name(&pdev->dev), NULL);
-#endif
/* Get card serial number. On systems without MTD flash support we may
* get an error thus ignore the return value. An invalid serial number
@@ -646,6 +644,8 @@ static void mgb4_remove(struct pci_dev *pdev)
hwmon_device_unregister(mgbdev->hwmon_dev);
#endif
+ debugfs_remove_recursive(mgbdev->debugfs);
+
if (mgbdev->indio_dev)
mgb4_trigger_free(mgbdev->indio_dev);
@@ -656,10 +656,6 @@ static void mgb4_remove(struct pci_dev *pdev)
if (mgbdev->vin[i])
mgb4_vin_free(mgbdev->vin[i]);
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove_recursive(mgbdev->debugfs);
-#endif
-
device_remove_groups(&mgbdev->pdev->dev, mgb4_pci_groups);
free_spi(mgbdev);
free_i2c(mgbdev);
diff --git a/drivers/media/pci/mgb4/mgb4_core.h b/drivers/media/pci/mgb4/mgb4_core.h
index b52cd67270b5..9aec62514c0b 100644
--- a/drivers/media/pci/mgb4/mgb4_core.h
+++ b/drivers/media/pci/mgb4/mgb4_core.h
@@ -68,9 +68,7 @@ struct mgb4_dev {
u8 module_version;
u32 serial_number;
-#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs;
-#endif
};
#endif
diff --git a/drivers/media/pci/mgb4/mgb4_vin.c b/drivers/media/pci/mgb4/mgb4_vin.c
index e9332abb3172..3f171c624b40 100644
--- a/drivers/media/pci/mgb4/mgb4_vin.c
+++ b/drivers/media/pci/mgb4/mgb4_vin.c
@@ -260,6 +260,7 @@ static void buffer_queue(struct vb2_buffer *vb)
static void stop_streaming(struct vb2_queue *vq)
{
struct mgb4_vin_dev *vindev = vb2_get_drv_priv(vq);
+ struct mgb4_regs *video = &vindev->mgbdev->video;
const struct mgb4_vin_config *config = vindev->config;
int irq = xdma_get_user_irq(vindev->mgbdev->xdev, config->vin_irq);
@@ -273,6 +274,9 @@ static void stop_streaming(struct vb2_queue *vq)
mgb4_mask_reg(&vindev->mgbdev->video, config->regs.config, 0x2,
0x0);
+ mgb4_write_reg(video, vindev->config->regs.padding, 0);
+ set_loopback_padding(vindev, 0);
+
cancel_work_sync(&vindev->dma_work);
return_all_buffers(vindev, VB2_BUF_STATE_ERROR);
}
@@ -280,6 +284,7 @@ static void stop_streaming(struct vb2_queue *vq)
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct mgb4_vin_dev *vindev = vb2_get_drv_priv(vq);
+ struct mgb4_regs *video = &vindev->mgbdev->video;
const struct mgb4_vin_config *config = vindev->config;
int irq = xdma_get_user_irq(vindev->mgbdev->xdev, config->vin_irq);
@@ -292,6 +297,9 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
mgb4_mask_reg(&vindev->mgbdev->video, config->regs.config, 0x2,
0x2);
+ mgb4_write_reg(video, vindev->config->regs.padding, vindev->padding);
+ set_loopback_padding(vindev, vindev->padding);
+
xdma_enable_user_irq(vindev->mgbdev->xdev, irq);
return 0;
@@ -304,8 +312,6 @@ static const struct vb2_ops queue_ops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish
};
static int fh_open(struct file *file)
@@ -324,34 +330,16 @@ static int fh_open(struct file *file)
if (get_timings(vindev, &vindev->timings) < 0)
vindev->timings = cea1080p60;
- set_loopback_padding(vindev, vindev->padding);
out:
mutex_unlock(&vindev->lock);
return rv;
}
-static int fh_release(struct file *file)
-{
- struct mgb4_vin_dev *vindev = video_drvdata(file);
- int rv;
-
- mutex_lock(&vindev->lock);
-
- if (v4l2_fh_is_singular_file(file))
- set_loopback_padding(vindev, 0);
-
- rv = _vb2_fop_release(file, NULL);
-
- mutex_unlock(&vindev->lock);
-
- return rv;
-}
-
static const struct v4l2_file_operations video_fops = {
.owner = THIS_MODULE,
.open = fh_open,
- .release = fh_release,
+ .release = vb2_fop_release,
.unlocked_ioctl = video_ioctl2,
.read = vb2_fop_read,
.mmap = vb2_fop_mmap,
@@ -507,8 +495,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
vindev->padding = (f->fmt.pix.bytesperline - (f->fmt.pix.width
* pixelsize)) / pixelsize;
- mgb4_write_reg(video, vindev->config->regs.padding, vindev->padding);
- set_loopback_padding(vindev, vindev->padding);
return 0;
}
@@ -853,14 +839,16 @@ static void fpga_init(struct mgb4_vin_dev *vindev)
mgb4_write_reg(video, regs->config, 1U << 9);
}
-#ifdef CONFIG_DEBUG_FS
-static void debugfs_init(struct mgb4_vin_dev *vindev)
+static void create_debugfs(struct mgb4_vin_dev *vindev)
{
+#ifdef CONFIG_DEBUG_FS
struct mgb4_regs *video = &vindev->mgbdev->video;
+ struct dentry *entry;
- vindev->debugfs = debugfs_create_dir(vindev->vdev.name,
- vindev->mgbdev->debugfs);
- if (!vindev->debugfs)
+ if (IS_ERR_OR_NULL(vindev->mgbdev->debugfs))
+ return;
+ entry = debugfs_create_dir(vindev->vdev.name, vindev->mgbdev->debugfs);
+ if (IS_ERR(entry))
return;
vindev->regs[0].name = "CONFIG";
@@ -892,10 +880,9 @@ static void debugfs_init(struct mgb4_vin_dev *vindev)
vindev->regset.base = video->membase;
vindev->regset.regs = vindev->regs;
- debugfs_create_regset32("registers", 0444, vindev->debugfs,
- &vindev->regset);
-}
+ debugfs_create_regset32("registers", 0444, entry, &vindev->regset);
#endif
+}
struct mgb4_vin_dev *mgb4_vin_create(struct mgb4_dev *mgbdev, int id)
{
@@ -1001,9 +988,7 @@ struct mgb4_vin_dev *mgb4_vin_create(struct mgb4_dev *mgbdev, int id)
goto err_video_dev;
}
-#ifdef CONFIG_DEBUG_FS
- debugfs_init(vindev);
-#endif
+ create_debugfs(vindev);
return vindev;
@@ -1034,10 +1019,6 @@ void mgb4_vin_free(struct mgb4_vin_dev *vindev)
free_irq(vin_irq, vindev);
free_irq(err_irq, vindev);
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove_recursive(vindev->debugfs);
-#endif
-
groups = MGB4_IS_GMSL(vindev->mgbdev)
? mgb4_gmsl_in_groups : mgb4_fpdl3_in_groups;
device_remove_groups(&vindev->vdev.dev, groups);
diff --git a/drivers/media/pci/mgb4/mgb4_vin.h b/drivers/media/pci/mgb4/mgb4_vin.h
index 9693bd0ce180..8fd10c0a5554 100644
--- a/drivers/media/pci/mgb4/mgb4_vin.h
+++ b/drivers/media/pci/mgb4/mgb4_vin.h
@@ -58,7 +58,6 @@ struct mgb4_vin_dev {
const struct mgb4_vin_config *config;
#ifdef CONFIG_DEBUG_FS
- struct dentry *debugfs;
struct debugfs_regset32 regset;
struct debugfs_reg32 regs[sizeof(struct mgb4_vin_regs) / 4];
#endif
diff --git a/drivers/media/pci/mgb4/mgb4_vout.c b/drivers/media/pci/mgb4/mgb4_vout.c
index 998edcbd9723..6b2791e29de1 100644
--- a/drivers/media/pci/mgb4/mgb4_vout.c
+++ b/drivers/media/pci/mgb4/mgb4_vout.c
@@ -230,8 +230,6 @@ static const struct vb2_ops queue_ops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish
};
static int vidioc_querycap(struct file *file, void *priv,
@@ -676,14 +674,16 @@ static void fpga_init(struct mgb4_vout_dev *voutdev)
(voutdev->config->id + MGB4_VIN_DEVICES) << 2 | 1 << 4);
}
-#ifdef CONFIG_DEBUG_FS
-static void debugfs_init(struct mgb4_vout_dev *voutdev)
+static void create_debugfs(struct mgb4_vout_dev *voutdev)
{
+#ifdef CONFIG_DEBUG_FS
struct mgb4_regs *video = &voutdev->mgbdev->video;
+ struct dentry *entry;
- voutdev->debugfs = debugfs_create_dir(voutdev->vdev.name,
- voutdev->mgbdev->debugfs);
- if (!voutdev->debugfs)
+ if (IS_ERR_OR_NULL(voutdev->mgbdev->debugfs))
+ return;
+ entry = debugfs_create_dir(voutdev->vdev.name, voutdev->mgbdev->debugfs);
+ if (IS_ERR(entry))
return;
voutdev->regs[0].name = "CONFIG";
@@ -711,10 +711,9 @@ static void debugfs_init(struct mgb4_vout_dev *voutdev)
voutdev->regset.base = video->membase;
voutdev->regset.regs = voutdev->regs;
- debugfs_create_regset32("registers", 0444, voutdev->debugfs,
- &voutdev->regset);
-}
+ debugfs_create_regset32("registers", 0444, entry, &voutdev->regset);
#endif
+}
struct mgb4_vout_dev *mgb4_vout_create(struct mgb4_dev *mgbdev, int id)
{
@@ -808,9 +807,7 @@ struct mgb4_vout_dev *mgb4_vout_create(struct mgb4_dev *mgbdev, int id)
goto err_video_dev;
}
-#ifdef CONFIG_DEBUG_FS
- debugfs_init(voutdev);
-#endif
+ create_debugfs(voutdev);
return voutdev;
@@ -833,10 +830,6 @@ void mgb4_vout_free(struct mgb4_vout_dev *voutdev)
free_irq(irq, voutdev);
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove_recursive(voutdev->debugfs);
-#endif
-
groups = MGB4_IS_GMSL(voutdev->mgbdev)
? mgb4_gmsl_out_groups : mgb4_fpdl3_out_groups;
device_remove_groups(&voutdev->vdev.dev, groups);
diff --git a/drivers/media/pci/mgb4/mgb4_vout.h b/drivers/media/pci/mgb4/mgb4_vout.h
index adc8fe1e7ae6..a07eeabdcf34 100644
--- a/drivers/media/pci/mgb4/mgb4_vout.h
+++ b/drivers/media/pci/mgb4/mgb4_vout.h
@@ -54,7 +54,6 @@ struct mgb4_vout_dev {
const struct mgb4_vout_config *config;
#ifdef CONFIG_DEBUG_FS
- struct dentry *debugfs;
struct debugfs_regset32 regset;
struct debugfs_reg32 regs[sizeof(struct mgb4_vout_regs) / 4];
#endif
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
index e90aa1c1584c..34d6d52f1e4e 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
@@ -175,11 +175,11 @@ int netup_spi_init(struct netup_unidvb_dev *ndev)
struct spi_controller *ctlr;
struct netup_spi *nspi;
- ctlr = devm_spi_alloc_master(&ndev->pci_dev->dev,
- sizeof(struct netup_spi));
+ ctlr = devm_spi_alloc_host(&ndev->pci_dev->dev,
+ sizeof(struct netup_spi));
if (!ctlr) {
dev_err(&ndev->pci_dev->dev,
- "%s(): unable to alloc SPI master\n", __func__);
+ "%s(): unable to alloc SPI host\n", __func__);
return -EINVAL;
}
nspi = spi_controller_get_devdata(ctlr);
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index bbf480ab31ca..8c4f70e4177d 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -78,8 +78,6 @@ static const struct vb2_ops saa7134_empress_qops = {
.buf_init = saa7134_ts_buffer_init,
.buf_prepare = saa7134_ts_buffer_prepare,
.buf_queue = saa7134_vb2_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 437dbe5e75e2..ec699ea14799 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -166,8 +166,6 @@ struct vb2_ops saa7134_ts_qops = {
.buf_init = saa7134_ts_buffer_init,
.buf_prepare = saa7134_ts_buffer_prepare,
.buf_queue = saa7134_vb2_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = saa7134_ts_stop_streaming,
};
EXPORT_SYMBOL_GPL(saa7134_ts_qops);
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index 3e773690468b..efa6e4fa423a 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -161,8 +161,6 @@ const struct vb2_ops saa7134_vbi_qops = {
.buf_init = buffer_init,
.buf_prepare = buffer_prepare,
.buf_queue = saa7134_vb2_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = saa7134_vb2_start_streaming,
.stop_streaming = saa7134_vb2_stop_streaming,
};
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 56b4481a40e6..43e7b006eb59 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -844,8 +844,6 @@ static const struct vb2_ops vb2_qops = {
.buf_init = buffer_init,
.buf_prepare = buffer_prepare,
.buf_queue = saa7134_vb2_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = saa7134_vb2_start_streaming,
.stop_streaming = saa7134_vb2_stop_streaming,
};
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 0adf3d80f248..5ee59b3844cc 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -756,8 +756,6 @@ static const struct vb2_ops solo_enc_video_qops = {
.buf_finish = solo_enc_buf_finish,
.start_streaming = solo_enc_start_streaming,
.stop_streaming = solo_enc_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int solo_enc_querycap(struct file *file, void *priv,
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index e18cc41fca83..35715b21dbdf 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -365,8 +365,6 @@ static const struct vb2_ops solo_video_qops = {
.buf_queue = solo_buf_queue,
.start_streaming = solo_start_streaming,
.stop_streaming = solo_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int solo_querycap(struct file *file, void *priv,
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 364ce9e57018..3049bad20f14 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -372,8 +372,6 @@ static const struct vb2_ops vip_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c
index 4f35c159efe5..0a08708e52b0 100644
--- a/drivers/media/pci/tw5864/tw5864-video.c
+++ b/drivers/media/pci/tw5864/tw5864-video.c
@@ -471,8 +471,6 @@ static const struct vb2_ops tw5864_video_qops = {
.buf_queue = tw5864_buf_queue,
.start_streaming = tw5864_start_streaming,
.stop_streaming = tw5864_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int tw5864_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index cdf5d733b863..77773dec48b8 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -524,8 +524,6 @@ static const struct vb2_ops tw68_video_qops = {
.buf_finish = tw68_buf_finish,
.start_streaming = tw68_start_streaming,
.stop_streaming = tw68_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* ------------------------------------------------------------------ */
diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c
index 63be95fce83d..785dd797d921 100644
--- a/drivers/media/pci/tw686x/tw686x-video.c
+++ b/drivers/media/pci/tw686x/tw686x-video.c
@@ -579,8 +579,6 @@ static const struct vb2_ops tw686x_video_qops = {
.buf_prepare = tw686x_buf_prepare,
.start_streaming = tw686x_start_streaming,
.stop_streaming = tw686x_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int tw686x_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
index 5c05e64c71a9..f42f596d3e62 100644
--- a/drivers/media/pci/zoran/zoran_driver.c
+++ b/drivers/media/pci/zoran/zoran_driver.c
@@ -950,8 +950,6 @@ static const struct vb2_ops zr_video_qops = {
.buf_prepare = zr_vb2_prepare,
.start_streaming = zr_vb2_start_streaming,
.stop_streaming = zr_vb2_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir)
diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c
index 73606cee586e..e491399afcc9 100644
--- a/drivers/media/platform/allegro-dvt/allegro-core.c
+++ b/drivers/media/platform/allegro-dvt/allegro-core.c
@@ -1509,8 +1509,10 @@ static int allocate_buffers_internal(struct allegro_channel *channel,
INIT_LIST_HEAD(&buffer->head);
err = allegro_alloc_buffer(dev, buffer, size);
- if (err)
+ if (err) {
+ kfree(buffer);
goto err;
+ }
list_add(&buffer->head, list);
}
@@ -2895,8 +2897,6 @@ static const struct vb2_ops allegro_queue_ops = {
.buf_queue = allegro_buf_queue,
.start_streaming = allegro_start_streaming,
.stop_streaming = allegro_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int allegro_queue_init(void *priv,
@@ -4003,7 +4003,7 @@ static const struct dev_pm_ops allegro_pm_ops = {
static struct platform_driver allegro_driver = {
.probe = allegro_probe,
- .remove_new = allegro_remove,
+ .remove = allegro_remove,
.driver = {
.name = "allegro",
.of_match_table = allegro_dt_ids,
diff --git a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
index 09409908ba5d..0c004bb8ba05 100644
--- a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
+++ b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
@@ -391,8 +391,6 @@ static const struct vb2_ops ge2d_qops = {
.buf_queue = ge2d_buf_queue,
.start_streaming = ge2d_start_streaming,
.stop_streaming = ge2d_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int
@@ -1045,7 +1043,7 @@ MODULE_DEVICE_TABLE(of, meson_ge2d_match);
static struct platform_driver ge2d_drv = {
.probe = ge2d_probe,
- .remove_new = ge2d_remove,
+ .remove = ge2d_remove,
.driver = {
.name = "meson-ge2d",
.of_match_table = meson_ge2d_match,
diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c
index 351b4edc8742..c5c1f1fbaa80 100644
--- a/drivers/media/platform/amphion/venc.c
+++ b/drivers/media/platform/amphion/venc.c
@@ -52,6 +52,7 @@ struct venc_t {
u32 ready_count;
u32 enable;
u32 stopped;
+ u32 memory_resource_configured;
u32 skipped_count;
u32 skipped_bytes;
@@ -943,10 +944,19 @@ static int venc_start_session(struct vpu_inst *inst, u32 type)
ret = vpu_iface_set_encode_params(inst, &venc->params, 0);
if (ret)
goto error;
+
+ venc->memory_resource_configured = false;
ret = vpu_session_configure_codec(inst);
if (ret)
goto error;
+ if (!venc->memory_resource_configured) {
+ vb2_queue_error(v4l2_m2m_get_src_vq(inst->fh.m2m_ctx));
+ vb2_queue_error(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx));
+ ret = -ENOMEM;
+ goto error;
+ }
+
inst->state = VPU_CODEC_STATE_CONFIGURED;
/*vpu_iface_config_memory_resource*/
@@ -985,6 +995,7 @@ static void venc_cleanup_mem_resource(struct vpu_inst *inst)
u32 i;
venc = inst->priv;
+ venc->memory_resource_configured = false;
for (i = 0; i < ARRAY_SIZE(venc->enc); i++)
vpu_free_dma(&venc->enc[i]);
@@ -1048,6 +1059,7 @@ static void venc_request_mem_resource(struct vpu_inst *inst,
vpu_iface_config_memory_resource(inst, MEM_RES_REF, i, &venc->ref[i]);
for (i = 0; i < act_frame_num; i++)
vpu_iface_config_memory_resource(inst, MEM_RES_ACT, i, &venc->act[i]);
+ venc->memory_resource_configured = true;
}
static void venc_cleanup_frames(struct venc_t *venc)
diff --git a/drivers/media/platform/amphion/vpu_core.c b/drivers/media/platform/amphion/vpu_core.c
index 3a2030d02e45..8df85c14ab3f 100644
--- a/drivers/media/platform/amphion/vpu_core.c
+++ b/drivers/media/platform/amphion/vpu_core.c
@@ -864,7 +864,7 @@ MODULE_DEVICE_TABLE(of, vpu_core_dt_match);
static struct platform_driver amphion_vpu_core_driver = {
.probe = vpu_core_probe,
- .remove_new = vpu_core_remove,
+ .remove = vpu_core_remove,
.driver = {
.name = "amphion-vpu-core",
.of_match_table = vpu_core_dt_match,
diff --git a/drivers/media/platform/amphion/vpu_drv.c b/drivers/media/platform/amphion/vpu_drv.c
index 2bf70aafd2ba..efbfd2652721 100644
--- a/drivers/media/platform/amphion/vpu_drv.c
+++ b/drivers/media/platform/amphion/vpu_drv.c
@@ -151,8 +151,8 @@ err_add_decoder:
media_device_cleanup(&vpu->mdev);
v4l2_device_unregister(&vpu->v4l2_dev);
err_vpu_deinit:
- pm_runtime_set_suspended(dev);
pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
return ret;
}
@@ -227,7 +227,7 @@ MODULE_DEVICE_TABLE(of, vpu_dt_match);
static struct platform_driver amphion_vpu_driver = {
.probe = vpu_probe,
- .remove_new = vpu_remove,
+ .remove = vpu_remove,
.driver = {
.name = "amphion-vpu",
.of_match_table = vpu_dt_match,
diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c
index 83db57bc80b7..45707931bc4f 100644
--- a/drivers/media/platform/amphion/vpu_v4l2.c
+++ b/drivers/media/platform/amphion/vpu_v4l2.c
@@ -646,8 +646,6 @@ static const struct vb2_ops vpu_vb2_ops = {
.start_streaming = vpu_vb2_start_streaming,
.stop_streaming = vpu_vb2_stop_streaming,
.buf_queue = vpu_vb2_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
@@ -841,6 +839,7 @@ int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func)
vfd->fops = vdec_get_fops();
vfd->ioctl_ops = vdec_get_ioctl_ops();
}
+ video_set_drvdata(vfd, vpu);
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
if (ret) {
@@ -848,7 +847,6 @@ int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func)
v4l2_m2m_release(func->m2m_dev);
return ret;
}
- video_set_drvdata(vfd, vpu);
func->vfd = vfd;
ret = v4l2_m2m_register_media_controller(func->m2m_dev, func->vfd, func->function);
diff --git a/drivers/media/platform/aspeed/aspeed-video.c b/drivers/media/platform/aspeed/aspeed-video.c
index fc6050e3be0d..54cae0da9aca 100644
--- a/drivers/media/platform/aspeed/aspeed-video.c
+++ b/drivers/media/platform/aspeed/aspeed-video.c
@@ -1891,8 +1891,6 @@ static void aspeed_video_buf_queue(struct vb2_buffer *vb)
static const struct vb2_ops aspeed_video_vb2_ops = {
.queue_setup = aspeed_video_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_prepare = aspeed_video_buf_prepare,
.start_streaming = aspeed_video_start_streaming,
.stop_streaming = aspeed_video_stop_streaming,
@@ -2226,7 +2224,7 @@ static struct platform_driver aspeed_video_driver = {
.of_match_table = aspeed_video_of_match,
},
.probe = aspeed_video_probe,
- .remove_new = aspeed_video_remove,
+ .remove = aspeed_video_remove,
};
module_platform_driver(aspeed_video_driver);
diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
index 5c823d3f9cc0..0d1c39347529 100644
--- a/drivers/media/platform/atmel/atmel-isi.c
+++ b/drivers/media/platform/atmel/atmel-isi.c
@@ -526,8 +526,6 @@ static const struct vb2_ops isi_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int isi_g_fmt_vid_cap(struct file *file, void *priv,
@@ -1367,7 +1365,7 @@ static struct platform_driver atmel_isi_driver = {
.pm = &atmel_isi_dev_pm_ops,
},
.probe = atmel_isi_probe,
- .remove_new = atmel_isi_remove,
+ .remove = atmel_isi_remove,
};
module_platform_driver(atmel_isi_driver);
diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c
index a1d93c14553d..3aed0e493c81 100644
--- a/drivers/media/platform/broadcom/bcm2835-unicam.c
+++ b/drivers/media/platform/broadcom/bcm2835-unicam.c
@@ -1801,8 +1801,6 @@ static void unicam_buffer_queue(struct vb2_buffer *vb)
static const struct vb2_ops unicam_video_qops = {
.queue_setup = unicam_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_prepare = unicam_buffer_prepare,
.start_streaming = unicam_start_streaming,
.stop_streaming = unicam_stop_streaming,
@@ -2724,7 +2722,7 @@ MODULE_DEVICE_TABLE(of, unicam_of_match);
static struct platform_driver unicam_driver = {
.probe = unicam_probe,
- .remove_new = unicam_remove,
+ .remove = unicam_remove,
.driver = {
.name = UNICAM_MODULE_NAME,
.pm = pm_ptr(&unicam_pm_ops),
diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 6f7d27a48eff..4d64df829e75 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -751,7 +751,7 @@ MODULE_DEVICE_TABLE(of, csi2rx_of_table);
static struct platform_driver csi2rx_driver = {
.probe = csi2rx_probe,
- .remove_new = csi2rx_remove,
+ .remove = csi2rx_remove,
.driver = {
.name = "cdns-csi2rx",
diff --git a/drivers/media/platform/cadence/cdns-csi2tx.c b/drivers/media/platform/cadence/cdns-csi2tx.c
index 3d98f91f1bee..e22b133f346d 100644
--- a/drivers/media/platform/cadence/cdns-csi2tx.c
+++ b/drivers/media/platform/cadence/cdns-csi2tx.c
@@ -644,7 +644,7 @@ static void csi2tx_remove(struct platform_device *pdev)
static struct platform_driver csi2tx_driver = {
.probe = csi2tx_probe,
- .remove_new = csi2tx_remove,
+ .remove = csi2tx_remove,
.driver = {
.name = "cdns-csi2tx",
diff --git a/drivers/media/platform/chips-media/coda/coda-common.c b/drivers/media/platform/chips-media/coda/coda-common.c
index 7da0194ec850..289a076c3bcc 100644
--- a/drivers/media/platform/chips-media/coda/coda-common.c
+++ b/drivers/media/platform/chips-media/coda/coda-common.c
@@ -2171,8 +2171,6 @@ static const struct vb2_ops coda_qops = {
.buf_queue = coda_buf_queue,
.start_streaming = coda_start_streaming,
.stop_streaming = coda_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -3346,7 +3344,7 @@ static const struct dev_pm_ops coda_pm_ops = {
static struct platform_driver coda_driver = {
.probe = coda_probe,
- .remove_new = coda_remove,
+ .remove = coda_remove,
.driver = {
.name = CODA_NAME,
.of_match_table = coda_dt_ids,
diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c
index d60841c54a80..2c9d8cbca6e4 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-helper.c
+++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c
@@ -7,6 +7,8 @@
#include "wave5-helper.h"
+#define DEFAULT_BS_SIZE(width, height) ((width) * (height) / 8 * 3)
+
const char *state_to_str(enum vpu_instance_state state)
{
switch (state) {
@@ -58,7 +60,6 @@ int wave5_vpu_release_device(struct file *filp,
char *name)
{
struct vpu_instance *inst = wave5_to_vpu_inst(filp->private_data);
- struct vpu_device *dev = inst->dev;
int ret = 0;
v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx);
@@ -78,18 +79,6 @@ int wave5_vpu_release_device(struct file *filp,
}
wave5_cleanup_instance(inst);
- if (dev->irq < 0) {
- ret = mutex_lock_interruptible(&dev->dev_lock);
- if (ret)
- return ret;
-
- if (list_empty(&dev->instances)) {
- dev_dbg(dev->dev, "Disabling the hrtimer\n");
- hrtimer_cancel(&dev->hrtimer);
- }
-
- mutex_unlock(&dev->dev_lock);
- }
return ret;
}
@@ -230,3 +219,25 @@ void wave5_return_bufs(struct vb2_queue *q, u32 state)
v4l2_m2m_buf_done(vbuf, state);
}
}
+
+void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp,
+ int pix_fmt_type,
+ unsigned int width,
+ unsigned int height,
+ const struct v4l2_frmsize_stepwise *frmsize)
+{
+ v4l2_apply_frmsize_constraints(&width, &height, frmsize);
+
+ if (pix_fmt_type == VPU_FMT_TYPE_CODEC) {
+ pix_mp->width = width;
+ pix_mp->height = height;
+ pix_mp->num_planes = 1;
+ pix_mp->plane_fmt[0].bytesperline = 0;
+ pix_mp->plane_fmt[0].sizeimage = max(DEFAULT_BS_SIZE(width, height),
+ pix_mp->plane_fmt[0].sizeimage);
+ } else {
+ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, width, height);
+ }
+ pix_mp->flags = 0;
+ pix_mp->field = V4L2_FIELD_NONE;
+}
diff --git a/drivers/media/platform/chips-media/wave5/wave5-helper.h b/drivers/media/platform/chips-media/wave5/wave5-helper.h
index 6cee1c14d3ce..9937fce553fc 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-helper.h
+++ b/drivers/media/platform/chips-media/wave5/wave5-helper.h
@@ -28,4 +28,9 @@ const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx,
const struct vpu_format fmt_list[MAX_FMTS]);
enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type);
void wave5_return_bufs(struct vb2_queue *q, u32 state);
+void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp,
+ int pix_fmt_type,
+ unsigned int width,
+ unsigned int height,
+ const struct v4l2_frmsize_stepwise *frmsize);
#endif
diff --git a/drivers/media/platform/chips-media/wave5/wave5-hw.c b/drivers/media/platform/chips-media/wave5/wave5-hw.c
index c89aafabc742..c8a905994109 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-hw.c
+++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c
@@ -23,6 +23,15 @@
#define W521_FEATURE_AVC_ENCODER BIT(1)
#define W521_FEATURE_HEVC_ENCODER BIT(0)
+#define ENC_AVC_INTRA_IDR_PARAM_MASK 0x7ff
+#define ENC_AVC_INTRA_PERIOD_SHIFT 6
+#define ENC_AVC_IDR_PERIOD_SHIFT 17
+#define ENC_AVC_FORCED_IDR_HEADER_SHIFT 28
+
+#define ENC_HEVC_INTRA_QP_SHIFT 3
+#define ENC_HEVC_FORCED_IDR_HEADER_SHIFT 9
+#define ENC_HEVC_INTRA_PERIOD_SHIFT 16
+
/* Decoder support fields */
#define W521_FEATURE_AVC_DECODER BIT(3)
#define W521_FEATURE_HEVC_DECODER BIT(2)
@@ -35,7 +44,7 @@
#define REMAP_CTRL_MAX_SIZE_BITS ((W5_REMAP_MAX_SIZE >> 12) & 0x1ff)
#define REMAP_CTRL_REGISTER_VALUE(index) ( \
- (BIT(31) | (index << 12) | BIT(11) | REMAP_CTRL_MAX_SIZE_BITS) \
+ (BIT(31) | ((index) << 12) | BIT(11) | REMAP_CTRL_MAX_SIZE_BITS)\
)
#define FASTIO_ADDRESS_MASK GENMASK(15, 0)
@@ -1219,8 +1228,8 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size)
return setup_wave5_properties(dev);
}
-static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code,
- size_t size)
+int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code,
+ size_t size)
{
u32 reg_val;
struct vpu_buf *common_vb;
@@ -1772,12 +1781,19 @@ int wave5_vpu_enc_init_seq(struct vpu_instance *inst)
if (inst->std == W_AVC_ENC)
vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM, p_param->intra_qp |
- ((p_param->intra_period & 0x7ff) << 6) |
- ((p_param->avc_idr_period & 0x7ff) << 17));
+ ((p_param->intra_period & ENC_AVC_INTRA_IDR_PARAM_MASK)
+ << ENC_AVC_INTRA_PERIOD_SHIFT) |
+ ((p_param->avc_idr_period & ENC_AVC_INTRA_IDR_PARAM_MASK)
+ << ENC_AVC_IDR_PERIOD_SHIFT) |
+ (p_param->forced_idr_header_enable
+ << ENC_AVC_FORCED_IDR_HEADER_SHIFT));
else if (inst->std == W_HEVC_ENC)
vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM,
- p_param->decoding_refresh_type | (p_param->intra_qp << 3) |
- (p_param->intra_period << 16));
+ p_param->decoding_refresh_type |
+ (p_param->intra_qp << ENC_HEVC_INTRA_QP_SHIFT) |
+ (p_param->forced_idr_header_enable
+ << ENC_HEVC_FORCED_IDR_HEADER_SHIFT) |
+ (p_param->intra_period << ENC_HEVC_INTRA_PERIOD_SHIFT));
reg_val = (p_param->rdo_skip << 2) |
(p_param->lambda_scaling_enable << 3) |
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
index 0c5c9a8de91f..d3ff420c52ce 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
@@ -5,116 +5,98 @@
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
+#include <linux/pm_runtime.h>
#include "wave5-helper.h"
#define VPU_DEC_DEV_NAME "C&M Wave5 VPU decoder"
#define VPU_DEC_DRV_NAME "wave5-dec"
-#define DEFAULT_SRC_SIZE(width, height) ({ \
- (width) * (height) / 8 * 3; \
-})
+static const struct v4l2_frmsize_stepwise dec_hevc_frmsize = {
+ .min_width = W5_MIN_DEC_PIC_8_WIDTH,
+ .max_width = W5_MAX_DEC_PIC_WIDTH,
+ .step_width = W5_DEC_CODEC_STEP_WIDTH,
+ .min_height = W5_MIN_DEC_PIC_8_HEIGHT,
+ .max_height = W5_MAX_DEC_PIC_HEIGHT,
+ .step_height = W5_DEC_CODEC_STEP_HEIGHT,
+};
+
+static const struct v4l2_frmsize_stepwise dec_h264_frmsize = {
+ .min_width = W5_MIN_DEC_PIC_32_WIDTH,
+ .max_width = W5_MAX_DEC_PIC_WIDTH,
+ .step_width = W5_DEC_CODEC_STEP_WIDTH,
+ .min_height = W5_MIN_DEC_PIC_32_HEIGHT,
+ .max_height = W5_MAX_DEC_PIC_HEIGHT,
+ .step_height = W5_DEC_CODEC_STEP_HEIGHT,
+};
+
+static const struct v4l2_frmsize_stepwise dec_raw_frmsize = {
+ .min_width = W5_MIN_DEC_PIC_8_WIDTH,
+ .max_width = W5_MAX_DEC_PIC_WIDTH,
+ .step_width = W5_DEC_RAW_STEP_WIDTH,
+ .min_height = W5_MIN_DEC_PIC_8_HEIGHT,
+ .max_height = W5_MAX_DEC_PIC_HEIGHT,
+ .step_height = W5_DEC_RAW_STEP_HEIGHT,
+};
static const struct vpu_format dec_fmt_list[FMT_TYPES][MAX_FMTS] = {
[VPU_FMT_TYPE_CODEC] = {
{
.v4l2_pix_fmt = V4L2_PIX_FMT_HEVC,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_hevc_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_H264,
- .max_width = 8192,
- .min_width = 32,
- .max_height = 4320,
- .min_height = 32,
+ .v4l2_frmsize = &dec_h264_frmsize,
},
},
[VPU_FMT_TYPE_RAW] = {
{
.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV12,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV21,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_YUV422P,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV16,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV61,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV12M,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV21M,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_YUV422M,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV16M,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV61M,
- .max_width = 8192,
- .min_width = 8,
- .max_height = 4320,
- .min_height = 8,
+ .v4l2_frmsize = &dec_raw_frmsize,
},
}
};
@@ -233,74 +215,6 @@ static void wave5_handle_src_buffer(struct vpu_instance *inst, dma_addr_t rd_ptr
inst->remaining_consumed_bytes = consumed_bytes;
}
-static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned int width,
- unsigned int height)
-{
- switch (pix_mp->pixelformat) {
- case V4L2_PIX_FMT_YUV420:
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- pix_mp->width = round_up(width, 32);
- pix_mp->height = round_up(height, 16);
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = width * height * 3 / 2;
- break;
- case V4L2_PIX_FMT_YUV422P:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- pix_mp->width = round_up(width, 32);
- pix_mp->height = round_up(height, 16);
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = width * height * 2;
- break;
- case V4L2_PIX_FMT_YUV420M:
- pix_mp->width = round_up(width, 32);
- pix_mp->height = round_up(height, 16);
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = width * height;
- pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2;
- pix_mp->plane_fmt[1].sizeimage = width * height / 4;
- pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2;
- pix_mp->plane_fmt[2].sizeimage = width * height / 4;
- break;
- case V4L2_PIX_FMT_NV12M:
- case V4L2_PIX_FMT_NV21M:
- pix_mp->width = round_up(width, 32);
- pix_mp->height = round_up(height, 16);
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = width * height;
- pix_mp->plane_fmt[1].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[1].sizeimage = width * height / 2;
- break;
- case V4L2_PIX_FMT_YUV422M:
- pix_mp->width = round_up(width, 32);
- pix_mp->height = round_up(height, 16);
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = width * height;
- pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2;
- pix_mp->plane_fmt[1].sizeimage = width * height / 2;
- pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2;
- pix_mp->plane_fmt[2].sizeimage = width * height / 2;
- break;
- case V4L2_PIX_FMT_NV16M:
- case V4L2_PIX_FMT_NV61M:
- pix_mp->width = round_up(width, 32);
- pix_mp->height = round_up(height, 16);
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = width * height;
- pix_mp->plane_fmt[1].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[1].sizeimage = width * height;
- break;
- default:
- pix_mp->width = width;
- pix_mp->height = height;
- pix_mp->plane_fmt[0].bytesperline = 0;
- pix_mp->plane_fmt[0].sizeimage = max(DEFAULT_SRC_SIZE(width, height),
- pix_mp->plane_fmt[0].sizeimage);
- break;
- }
-}
-
static int start_decode(struct vpu_instance *inst, u32 *fail_res)
{
struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx;
@@ -388,6 +302,8 @@ static int handle_dynamic_resolution_change(struct vpu_instance *inst)
}
if (p_dec_info->initial_info_obtained) {
+ const struct vpu_format *vpu_fmt;
+
inst->conf_win.left = initial_info->pic_crop_rect.left;
inst->conf_win.top = initial_info->pic_crop_rect.top;
inst->conf_win.width = initial_info->pic_width -
@@ -395,10 +311,27 @@ static int handle_dynamic_resolution_change(struct vpu_instance *inst)
inst->conf_win.height = initial_info->pic_height -
initial_info->pic_crop_rect.top - initial_info->pic_crop_rect.bottom;
- wave5_update_pix_fmt(&inst->src_fmt, initial_info->pic_width,
- initial_info->pic_height);
- wave5_update_pix_fmt(&inst->dst_fmt, initial_info->pic_width,
- initial_info->pic_height);
+ vpu_fmt = wave5_find_vpu_fmt(inst->src_fmt.pixelformat,
+ dec_fmt_list[VPU_FMT_TYPE_CODEC]);
+ if (!vpu_fmt)
+ return -EINVAL;
+
+ wave5_update_pix_fmt(&inst->src_fmt,
+ VPU_FMT_TYPE_CODEC,
+ initial_info->pic_width,
+ initial_info->pic_height,
+ vpu_fmt->v4l2_frmsize);
+
+ vpu_fmt = wave5_find_vpu_fmt(inst->dst_fmt.pixelformat,
+ dec_fmt_list[VPU_FMT_TYPE_RAW]);
+ if (!vpu_fmt)
+ return -EINVAL;
+
+ wave5_update_pix_fmt(&inst->dst_fmt,
+ VPU_FMT_TYPE_RAW,
+ initial_info->pic_width,
+ initial_info->pic_height,
+ vpu_fmt->v4l2_frmsize);
}
v4l2_event_queue_fh(fh, &vpu_event_src_ch);
@@ -518,6 +451,8 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst)
if (q_status.report_queue_count == 0 &&
(q_status.instance_queue_count == 0 || dec_info.sequence_changed)) {
dev_dbg(inst->dev->dev, "%s: finishing job.\n", __func__);
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx);
}
}
@@ -545,12 +480,12 @@ static int wave5_vpu_dec_enum_framesizes(struct file *f, void *fh, struct v4l2_f
}
fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
- fsize->stepwise.min_width = vpu_fmt->min_width;
- fsize->stepwise.max_width = vpu_fmt->max_width;
- fsize->stepwise.step_width = 1;
- fsize->stepwise.min_height = vpu_fmt->min_height;
- fsize->stepwise.max_height = vpu_fmt->max_height;
- fsize->stepwise.step_height = 1;
+ fsize->stepwise.min_width = vpu_fmt->v4l2_frmsize->min_width;
+ fsize->stepwise.max_width = vpu_fmt->v4l2_frmsize->max_width;
+ fsize->stepwise.step_width = W5_DEC_CODEC_STEP_WIDTH;
+ fsize->stepwise.min_height = vpu_fmt->v4l2_frmsize->min_height;
+ fsize->stepwise.max_height = vpu_fmt->v4l2_frmsize->max_height;
+ fsize->stepwise.step_height = W5_DEC_CODEC_STEP_HEIGHT;
return 0;
}
@@ -573,6 +508,7 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo
{
struct vpu_instance *inst = wave5_to_vpu_inst(fh);
struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+ const struct v4l2_frmsize_stepwise *frmsize;
const struct vpu_format *vpu_fmt;
int width, height;
@@ -586,14 +522,12 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo
width = inst->dst_fmt.width;
height = inst->dst_fmt.height;
f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat;
- f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes;
+ frmsize = &dec_raw_frmsize;
} else {
- const struct v4l2_format_info *info = v4l2_format_info(vpu_fmt->v4l2_pix_fmt);
-
- width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
- height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
+ width = f->fmt.pix_mp.width;
+ height = f->fmt.pix_mp.height;
f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
- f->fmt.pix_mp.num_planes = info->mem_planes;
+ frmsize = vpu_fmt->v4l2_frmsize;
}
if (p_dec_info->initial_info_obtained) {
@@ -601,9 +535,8 @@ static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo
height = inst->dst_fmt.height;
}
- wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
- f->fmt.pix_mp.flags = 0;
- f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+ wave5_update_pix_fmt(&f->fmt.pix_mp, VPU_FMT_TYPE_RAW,
+ width, height, frmsize);
f->fmt.pix_mp.colorspace = inst->colorspace;
f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
f->fmt.pix_mp.quantization = inst->quantization;
@@ -715,7 +648,9 @@ static int wave5_vpu_dec_enum_fmt_out(struct file *file, void *fh, struct v4l2_f
static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
{
struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+ const struct v4l2_frmsize_stepwise *frmsize;
const struct vpu_format *vpu_fmt;
+ int width, height;
dev_dbg(inst->dev->dev,
"%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n",
@@ -724,20 +659,19 @@ static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_fo
vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, dec_fmt_list[VPU_FMT_TYPE_CODEC]);
if (!vpu_fmt) {
+ width = inst->src_fmt.width;
+ height = inst->src_fmt.height;
f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat;
- f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes;
- wave5_update_pix_fmt(&f->fmt.pix_mp, inst->src_fmt.width, inst->src_fmt.height);
+ frmsize = &dec_hevc_frmsize;
} else {
- int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
- int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
-
+ width = f->fmt.pix_mp.width;
+ height = f->fmt.pix_mp.height;
f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
- f->fmt.pix_mp.num_planes = 1;
- wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
+ frmsize = vpu_fmt->v4l2_frmsize;
}
- f->fmt.pix_mp.flags = 0;
- f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+ wave5_update_pix_fmt(&f->fmt.pix_mp, VPU_FMT_TYPE_CODEC,
+ width, height, frmsize);
return 0;
}
@@ -745,6 +679,7 @@ static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_fo
static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
{
struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+ const struct vpu_format *vpu_fmt;
int i, ret;
dev_dbg(inst->dev->dev,
@@ -779,7 +714,13 @@ static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_form
inst->quantization = f->fmt.pix_mp.quantization;
inst->xfer_func = f->fmt.pix_mp.xfer_func;
- wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height);
+ vpu_fmt = wave5_find_vpu_fmt(inst->dst_fmt.pixelformat, dec_fmt_list[VPU_FMT_TYPE_RAW]);
+ if (!vpu_fmt)
+ return -EINVAL;
+
+ wave5_update_pix_fmt(&inst->dst_fmt, VPU_FMT_TYPE_RAW,
+ f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+ vpu_fmt->v4l2_frmsize);
return 0;
}
@@ -1002,6 +943,7 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff
struct vpu_instance *inst = vb2_get_drv_priv(q);
struct v4l2_pix_format_mplane inst_format =
(q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->dst_fmt;
+ unsigned int i;
dev_dbg(inst->dev->dev, "%s: num_buffers: %u | num_planes: %u | type: %u\n", __func__,
*num_buffers, *num_planes, q->type);
@@ -1015,31 +957,9 @@ static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buff
if (*num_buffers < inst->fbc_buf_count)
*num_buffers = inst->fbc_buf_count;
- if (*num_planes == 1) {
- if (inst->output_format == FORMAT_422)
- sizes[0] = inst_format.width * inst_format.height * 2;
- else
- sizes[0] = inst_format.width * inst_format.height * 3 / 2;
- dev_dbg(inst->dev->dev, "%s: size[0]: %u\n", __func__, sizes[0]);
- } else if (*num_planes == 2) {
- sizes[0] = inst_format.width * inst_format.height;
- if (inst->output_format == FORMAT_422)
- sizes[1] = inst_format.width * inst_format.height;
- else
- sizes[1] = inst_format.width * inst_format.height / 2;
- dev_dbg(inst->dev->dev, "%s: size[0]: %u | size[1]: %u\n",
- __func__, sizes[0], sizes[1]);
- } else if (*num_planes == 3) {
- sizes[0] = inst_format.width * inst_format.height;
- if (inst->output_format == FORMAT_422) {
- sizes[1] = inst_format.width * inst_format.height / 2;
- sizes[2] = inst_format.width * inst_format.height / 2;
- } else {
- sizes[1] = inst_format.width * inst_format.height / 4;
- sizes[2] = inst_format.width * inst_format.height / 4;
- }
- dev_dbg(inst->dev->dev, "%s: size[0]: %u | size[1]: %u | size[2]: %u\n",
- __func__, sizes[0], sizes[1], sizes[2]);
+ for (i = 0; i < *num_planes; i++) {
+ sizes[i] = inst_format.plane_fmt[i].sizeimage;
+ dev_dbg(inst->dev->dev, "%s: size[%u]: %u\n", __func__, i, sizes[i]);
}
}
@@ -1398,6 +1318,7 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count
int ret = 0;
dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type);
+ pm_runtime_resume_and_get(inst->dev->dev);
v4l2_m2m_update_start_streaming_state(m2m_ctx, q);
@@ -1429,13 +1350,15 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count
if (ret)
goto return_buffers;
}
-
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
return ret;
free_bitstream_vbuf:
wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf);
return_buffers:
wave5_return_bufs(q, VB2_BUF_STATE_QUEUED);
+ pm_runtime_put_autosuspend(inst->dev->dev);
return ret;
}
@@ -1521,6 +1444,7 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q)
bool check_cmd = TRUE;
dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type);
+ pm_runtime_resume_and_get(inst->dev->dev);
while (check_cmd) {
struct queue_status_info q_status;
@@ -1544,12 +1468,13 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q)
streamoff_output(q);
else
streamoff_capture(q);
+
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
}
static const struct vb2_ops wave5_vpu_dec_vb2_ops = {
.queue_setup = wave5_vpu_dec_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_queue = wave5_vpu_dec_buf_queue,
.start_streaming = wave5_vpu_dec_start_streaming,
.stop_streaming = wave5_vpu_dec_stop_streaming,
@@ -1558,20 +1483,15 @@ static const struct vb2_ops wave5_vpu_dec_vb2_ops = {
static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt,
struct v4l2_pix_format_mplane *dst_fmt)
{
- unsigned int dst_pix_fmt = dec_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt;
- const struct v4l2_format_info *dst_fmt_info = v4l2_format_info(dst_pix_fmt);
-
src_fmt->pixelformat = dec_fmt_list[VPU_FMT_TYPE_CODEC][0].v4l2_pix_fmt;
- src_fmt->field = V4L2_FIELD_NONE;
- src_fmt->flags = 0;
- src_fmt->num_planes = 1;
- wave5_update_pix_fmt(src_fmt, 720, 480);
-
- dst_fmt->pixelformat = dst_pix_fmt;
- dst_fmt->field = V4L2_FIELD_NONE;
- dst_fmt->flags = 0;
- dst_fmt->num_planes = dst_fmt_info->mem_planes;
- wave5_update_pix_fmt(dst_fmt, 736, 480);
+ wave5_update_pix_fmt(src_fmt, VPU_FMT_TYPE_CODEC,
+ W5_DEF_DEC_PIC_WIDTH, W5_DEF_DEC_PIC_HEIGHT,
+ &dec_hevc_frmsize);
+
+ dst_fmt->pixelformat = dec_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt;
+ wave5_update_pix_fmt(dst_fmt, VPU_FMT_TYPE_RAW,
+ W5_DEF_DEC_PIC_WIDTH, W5_DEF_DEC_PIC_HEIGHT,
+ &dec_raw_frmsize);
}
static int wave5_vpu_dec_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
@@ -1630,7 +1550,7 @@ static void wave5_vpu_dec_device_run(void *priv)
int ret = 0;
dev_dbg(inst->dev->dev, "%s: Fill the ring buffer with new bitstream data", __func__);
-
+ pm_runtime_resume_and_get(inst->dev->dev);
ret = fill_ringbuffer(inst);
if (ret) {
dev_warn(inst->dev->dev, "Filling ring buffer failed\n");
@@ -1713,6 +1633,8 @@ static void wave5_vpu_dec_device_run(void *priv)
finish_job_and_return:
dev_dbg(inst->dev->dev, "%s: leave and finish job", __func__);
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx);
}
@@ -1879,9 +1801,8 @@ static int wave5_vpu_open_dec(struct file *filp)
if (ret)
goto cleanup_inst;
- if (dev->irq < 0 && !hrtimer_active(&dev->hrtimer) && list_empty(&dev->instances))
- hrtimer_start(&dev->hrtimer, ns_to_ktime(dev->vpu_poll_interval * NSEC_PER_MSEC),
- HRTIMER_MODE_REL_PINNED);
+ if (list_empty(&dev->instances))
+ pm_runtime_use_autosuspend(inst->dev->dev);
list_add_tail(&inst->list, &dev->instances);
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c
index 3e35a05c2d8d..1e5fc5f8b856 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c
@@ -5,70 +5,90 @@
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
+#include <linux/pm_runtime.h>
#include "wave5-helper.h"
#define VPU_ENC_DEV_NAME "C&M Wave5 VPU encoder"
#define VPU_ENC_DRV_NAME "wave5-enc"
+static const struct v4l2_frmsize_stepwise enc_frmsize[FMT_TYPES] = {
+ [VPU_FMT_TYPE_CODEC] = {
+ .min_width = W5_MIN_ENC_PIC_WIDTH,
+ .max_width = W5_MAX_ENC_PIC_WIDTH,
+ .step_width = W5_ENC_CODEC_STEP_WIDTH,
+ .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .max_height = W5_MAX_ENC_PIC_HEIGHT,
+ .step_height = W5_ENC_CODEC_STEP_HEIGHT,
+ },
+ [VPU_FMT_TYPE_RAW] = {
+ .min_width = W5_MIN_ENC_PIC_WIDTH,
+ .max_width = W5_MAX_ENC_PIC_WIDTH,
+ .step_width = W5_ENC_RAW_STEP_WIDTH,
+ .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .max_height = W5_MAX_ENC_PIC_HEIGHT,
+ .step_height = W5_ENC_RAW_STEP_HEIGHT,
+ },
+};
+
static const struct vpu_format enc_fmt_list[FMT_TYPES][MAX_FMTS] = {
[VPU_FMT_TYPE_CODEC] = {
{
.v4l2_pix_fmt = V4L2_PIX_FMT_HEVC,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_CODEC],
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_H264,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_CODEC],
},
},
[VPU_FMT_TYPE_RAW] = {
{
.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV12,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV21,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV12M,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
},
{
.v4l2_pix_fmt = V4L2_PIX_FMT_NV21M,
- .max_width = W5_MAX_ENC_PIC_WIDTH,
- .min_width = W5_MIN_ENC_PIC_WIDTH,
- .max_height = W5_MAX_ENC_PIC_HEIGHT,
- .min_height = W5_MIN_ENC_PIC_HEIGHT,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
+ },
+ {
+ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422P,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
+ },
+ {
+ .v4l2_pix_fmt = V4L2_PIX_FMT_NV16,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
+ },
+ {
+ .v4l2_pix_fmt = V4L2_PIX_FMT_NV61,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
+ },
+ {
+ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422M,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
+ },
+ {
+ .v4l2_pix_fmt = V4L2_PIX_FMT_NV16M,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
+ },
+ {
+ .v4l2_pix_fmt = V4L2_PIX_FMT_NV61M,
+ .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW],
},
}
};
@@ -105,46 +125,6 @@ invalid_state_switch:
return -EINVAL;
}
-static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned int width,
- unsigned int height)
-{
- switch (pix_mp->pixelformat) {
- case V4L2_PIX_FMT_YUV420:
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- pix_mp->width = width;
- pix_mp->height = height;
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height * 3 / 2;
- break;
- case V4L2_PIX_FMT_YUV420M:
- pix_mp->width = width;
- pix_mp->height = height;
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height;
- pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2;
- pix_mp->plane_fmt[1].sizeimage = round_up(width, 32) * height / 4;
- pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2;
- pix_mp->plane_fmt[2].sizeimage = round_up(width, 32) * height / 4;
- break;
- case V4L2_PIX_FMT_NV12M:
- case V4L2_PIX_FMT_NV21M:
- pix_mp->width = width;
- pix_mp->height = height;
- pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height;
- pix_mp->plane_fmt[1].bytesperline = round_up(width, 32);
- pix_mp->plane_fmt[1].sizeimage = round_up(width, 32) * height / 2;
- break;
- default:
- pix_mp->width = width;
- pix_mp->height = height;
- pix_mp->plane_fmt[0].bytesperline = 0;
- pix_mp->plane_fmt[0].sizeimage = width * height / 8 * 3;
- break;
- }
-}
-
static int start_encode(struct vpu_instance *inst, u32 *fail_res)
{
struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx;
@@ -153,13 +133,26 @@ static int start_encode(struct vpu_instance *inst, u32 *fail_res)
struct vb2_v4l2_buffer *dst_buf;
struct frame_buffer frame_buf;
struct enc_param pic_param;
- u32 stride = ALIGN(inst->dst_fmt.width, 32);
- u32 luma_size = (stride * inst->dst_fmt.height);
- u32 chroma_size = ((stride / 2) * (inst->dst_fmt.height / 2));
+ const struct v4l2_format_info *info;
+ u32 stride = inst->src_fmt.plane_fmt[0].bytesperline;
+ u32 luma_size = 0;
+ u32 chroma_size = 0;
memset(&pic_param, 0, sizeof(struct enc_param));
memset(&frame_buf, 0, sizeof(struct frame_buffer));
+ info = v4l2_format_info(inst->src_fmt.pixelformat);
+ if (!info)
+ return -EINVAL;
+
+ if (info->mem_planes == 1) {
+ luma_size = stride * inst->dst_fmt.height;
+ chroma_size = luma_size / (info->hdiv * info->vdiv);
+ } else {
+ luma_size = inst->src_fmt.plane_fmt[0].sizeimage;
+ chroma_size = inst->src_fmt.plane_fmt[1].sizeimage;
+ }
+
dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx);
if (!dst_buf) {
dev_dbg(inst->dev->dev, "%s: No destination buffer found\n", __func__);
@@ -359,13 +352,8 @@ static int wave5_vpu_enc_enum_framesizes(struct file *f, void *fh, struct v4l2_f
return -EINVAL;
}
- fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
- fsize->stepwise.min_width = vpu_fmt->min_width;
- fsize->stepwise.max_width = vpu_fmt->max_width;
- fsize->stepwise.step_width = 1;
- fsize->stepwise.min_height = vpu_fmt->min_height;
- fsize->stepwise.max_height = vpu_fmt->max_height;
- fsize->stepwise.step_height = 1;
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise = enc_frmsize[VPU_FMT_TYPE_CODEC];
return 0;
}
@@ -390,7 +378,9 @@ static int wave5_vpu_enc_enum_fmt_cap(struct file *file, void *fh, struct v4l2_f
static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
{
struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+ const struct v4l2_frmsize_stepwise *frmsize;
const struct vpu_format *vpu_fmt;
+ int width, height;
dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
@@ -398,20 +388,19 @@ static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_fo
vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, enc_fmt_list[VPU_FMT_TYPE_CODEC]);
if (!vpu_fmt) {
+ width = inst->dst_fmt.width;
+ height = inst->dst_fmt.height;
f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat;
- f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes;
- wave5_update_pix_fmt(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height);
+ frmsize = &enc_frmsize[VPU_FMT_TYPE_CODEC];
} else {
- int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
- int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
-
+ width = f->fmt.pix_mp.width;
+ height = f->fmt.pix_mp.height;
f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
- f->fmt.pix_mp.num_planes = 1;
- wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
+ frmsize = vpu_fmt->v4l2_frmsize;
}
- f->fmt.pix_mp.flags = 0;
- f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+ wave5_update_pix_fmt(&f->fmt.pix_mp, VPU_FMT_TYPE_CODEC,
+ width, height, frmsize);
f->fmt.pix_mp.colorspace = inst->colorspace;
f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
f->fmt.pix_mp.quantization = inst->quantization;
@@ -498,7 +487,9 @@ static int wave5_vpu_enc_enum_fmt_out(struct file *file, void *fh, struct v4l2_f
static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
{
struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+ const struct v4l2_frmsize_stepwise *frmsize;
const struct vpu_format *vpu_fmt;
+ int width, height;
dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
@@ -506,28 +497,27 @@ static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_fo
vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, enc_fmt_list[VPU_FMT_TYPE_RAW]);
if (!vpu_fmt) {
+ width = inst->src_fmt.width;
+ height = inst->src_fmt.height;
f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat;
- f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes;
- wave5_update_pix_fmt(&f->fmt.pix_mp, inst->src_fmt.width, inst->src_fmt.height);
+ frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW];
} else {
- int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
- int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
- const struct v4l2_format_info *info = v4l2_format_info(vpu_fmt->v4l2_pix_fmt);
-
+ width = f->fmt.pix_mp.width;
+ height = f->fmt.pix_mp.height;
f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
- f->fmt.pix_mp.num_planes = info->mem_planes;
- wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
+ frmsize = vpu_fmt->v4l2_frmsize;
}
- f->fmt.pix_mp.flags = 0;
- f->fmt.pix_mp.field = V4L2_FIELD_NONE;
-
+ wave5_update_pix_fmt(&f->fmt.pix_mp, VPU_FMT_TYPE_RAW,
+ width, height, frmsize);
return 0;
}
static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
{
struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+ const struct vpu_format *vpu_fmt;
+ const struct v4l2_format_info *info;
int i, ret;
dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
@@ -549,16 +539,20 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form
inst->src_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage;
}
- if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12 ||
- inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12M) {
- inst->cbcr_interleave = true;
- inst->nv21 = false;
- } else if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21 ||
- inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21M) {
- inst->cbcr_interleave = true;
+ info = v4l2_format_info(inst->src_fmt.pixelformat);
+ if (!info)
+ return -EINVAL;
+
+ inst->cbcr_interleave = (info->comp_planes == 2) ? true : false;
+
+ switch (inst->src_fmt.pixelformat) {
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV21M:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV61M:
inst->nv21 = true;
- } else {
- inst->cbcr_interleave = false;
+ break;
+ default:
inst->nv21 = false;
}
@@ -567,7 +561,15 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form
inst->quantization = f->fmt.pix_mp.quantization;
inst->xfer_func = f->fmt.pix_mp.xfer_func;
- wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height);
+ vpu_fmt = wave5_find_vpu_fmt(inst->dst_fmt.pixelformat, enc_fmt_list[VPU_FMT_TYPE_CODEC]);
+ if (!vpu_fmt)
+ return -EINVAL;
+
+ wave5_update_pix_fmt(&inst->dst_fmt, VPU_FMT_TYPE_CODEC,
+ f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+ vpu_fmt->v4l2_frmsize);
+ inst->conf_win.width = inst->dst_fmt.width;
+ inst->conf_win.height = inst->dst_fmt.height;
return 0;
}
@@ -583,12 +585,17 @@ static int wave5_vpu_enc_g_selection(struct file *file, void *fh, struct v4l2_se
switch (s->target) {
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP:
s->r.left = 0;
s->r.top = 0;
s->r.width = inst->dst_fmt.width;
s->r.height = inst->dst_fmt.height;
break;
+ case V4L2_SEL_TGT_CROP:
+ s->r.left = 0;
+ s->r.top = 0;
+ s->r.width = inst->conf_win.width;
+ s->r.height = inst->conf_win.height;
+ break;
default:
return -EINVAL;
}
@@ -611,8 +618,10 @@ static int wave5_vpu_enc_s_selection(struct file *file, void *fh, struct v4l2_se
s->r.left = 0;
s->r.top = 0;
- s->r.width = inst->src_fmt.width;
- s->r.height = inst->src_fmt.height;
+ s->r.width = min(s->r.width, inst->dst_fmt.width);
+ s->r.height = min(s->r.height, inst->dst_fmt.height);
+
+ inst->conf_win = s->r;
return 0;
}
@@ -1061,6 +1070,9 @@ static int wave5_vpu_enc_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
inst->enc_param.entropy_coding_mode = ctrl->val;
break;
+ case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
+ inst->enc_param.forced_idr_header_enable = ctrl->val;
+ break;
case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
break;
default:
@@ -1125,13 +1137,23 @@ static void wave5_vpu_enc_buf_queue(struct vb2_buffer *vb)
v4l2_m2m_buf_queue(m2m_ctx, vbuf);
}
-static void wave5_set_enc_openparam(struct enc_open_param *open_param,
- struct vpu_instance *inst)
+static int wave5_set_enc_openparam(struct enc_open_param *open_param,
+ struct vpu_instance *inst)
{
struct enc_wave_param input = inst->enc_param;
+ const struct v4l2_format_info *info;
u32 num_ctu_row = ALIGN(inst->dst_fmt.height, 64) / 64;
u32 num_mb_row = ALIGN(inst->dst_fmt.height, 16) / 16;
+ info = v4l2_format_info(inst->src_fmt.pixelformat);
+ if (!info)
+ return -EINVAL;
+
+ if (info->hdiv == 2 && info->vdiv == 1)
+ open_param->src_format = FORMAT_422;
+ else
+ open_param->src_format = FORMAT_420;
+
open_param->wave_param.gop_preset_idx = PRESET_IDX_IPP_SINGLE;
open_param->wave_param.hvs_qp_scale = 2;
open_param->wave_param.hvs_max_delta_qp = 10;
@@ -1147,8 +1169,8 @@ static void wave5_set_enc_openparam(struct enc_open_param *open_param,
open_param->wave_param.lambda_scaling_enable = 1;
open_param->line_buf_int_en = true;
- open_param->pic_width = inst->dst_fmt.width;
- open_param->pic_height = inst->dst_fmt.height;
+ open_param->pic_width = inst->conf_win.width;
+ open_param->pic_height = inst->conf_win.height;
open_param->frame_rate_info = inst->frame_rate;
open_param->rc_enable = inst->rc_enable;
if (inst->rc_enable) {
@@ -1219,6 +1241,9 @@ static void wave5_set_enc_openparam(struct enc_open_param *open_param,
else
open_param->wave_param.intra_refresh_arg = num_ctu_row;
}
+ open_param->wave_param.forced_idr_header_enable = input.forced_idr_header_enable;
+
+ return 0;
}
static int initialize_sequence(struct vpu_instance *inst)
@@ -1306,6 +1331,7 @@ static int wave5_vpu_enc_start_streaming(struct vb2_queue *q, unsigned int count
struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx;
int ret = 0;
+ pm_runtime_resume_and_get(inst->dev->dev);
v4l2_m2m_update_start_streaming_state(m2m_ctx, q);
if (inst->state == VPU_INST_STATE_NONE && q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
@@ -1313,7 +1339,12 @@ static int wave5_vpu_enc_start_streaming(struct vb2_queue *q, unsigned int count
memset(&open_param, 0, sizeof(struct enc_open_param));
- wave5_set_enc_openparam(&open_param, inst);
+ ret = wave5_set_enc_openparam(&open_param, inst);
+ if (ret) {
+ dev_dbg(inst->dev->dev, "%s: wave5_set_enc_openparam, fail: %d\n",
+ __func__, ret);
+ goto return_buffers;
+ }
ret = wave5_vpu_enc_open(inst, &open_param);
if (ret) {
@@ -1360,9 +1391,13 @@ static int wave5_vpu_enc_start_streaming(struct vb2_queue *q, unsigned int count
if (ret)
goto return_buffers;
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
return 0;
return_buffers:
wave5_return_bufs(q, VB2_BUF_STATE_QUEUED);
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
return ret;
}
@@ -1404,6 +1439,7 @@ static void wave5_vpu_enc_stop_streaming(struct vb2_queue *q)
*/
dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type);
+ pm_runtime_resume_and_get(inst->dev->dev);
if (wave5_vpu_both_queues_are_streaming(inst))
switch_state(inst, VPU_INST_STATE_STOP);
@@ -1428,12 +1464,13 @@ static void wave5_vpu_enc_stop_streaming(struct vb2_queue *q)
streamoff_output(inst, q);
else
streamoff_capture(inst, q);
+
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
}
static const struct vb2_ops wave5_vpu_enc_vb2_ops = {
.queue_setup = wave5_vpu_enc_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_queue = wave5_vpu_enc_buf_queue,
.start_streaming = wave5_vpu_enc_start_streaming,
.stop_streaming = wave5_vpu_enc_stop_streaming,
@@ -1442,20 +1479,15 @@ static const struct vb2_ops wave5_vpu_enc_vb2_ops = {
static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt,
struct v4l2_pix_format_mplane *dst_fmt)
{
- unsigned int src_pix_fmt = enc_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt;
- const struct v4l2_format_info *src_fmt_info = v4l2_format_info(src_pix_fmt);
-
- src_fmt->pixelformat = src_pix_fmt;
- src_fmt->field = V4L2_FIELD_NONE;
- src_fmt->flags = 0;
- src_fmt->num_planes = src_fmt_info->mem_planes;
- wave5_update_pix_fmt(src_fmt, 416, 240);
+ src_fmt->pixelformat = enc_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt;
+ wave5_update_pix_fmt(src_fmt, VPU_FMT_TYPE_RAW,
+ W5_DEF_ENC_PIC_WIDTH, W5_DEF_ENC_PIC_HEIGHT,
+ &enc_frmsize[VPU_FMT_TYPE_RAW]);
dst_fmt->pixelformat = enc_fmt_list[VPU_FMT_TYPE_CODEC][0].v4l2_pix_fmt;
- dst_fmt->field = V4L2_FIELD_NONE;
- dst_fmt->flags = 0;
- dst_fmt->num_planes = 1;
- wave5_update_pix_fmt(dst_fmt, 416, 240);
+ wave5_update_pix_fmt(dst_fmt, VPU_FMT_TYPE_CODEC,
+ W5_DEF_ENC_PIC_WIDTH, W5_DEF_ENC_PIC_HEIGHT,
+ &enc_frmsize[VPU_FMT_TYPE_CODEC]);
}
static int wave5_vpu_enc_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
@@ -1474,6 +1506,7 @@ static void wave5_vpu_enc_device_run(void *priv)
u32 fail_res = 0;
int ret = 0;
+ pm_runtime_resume_and_get(inst->dev->dev);
switch (inst->state) {
case VPU_INST_STATE_PIC_RUN:
ret = start_encode(inst, &fail_res);
@@ -1487,6 +1520,8 @@ static void wave5_vpu_enc_device_run(void *priv)
break;
}
dev_dbg(inst->dev->dev, "%s: leave with active job", __func__);
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
return;
default:
WARN(1, "Execution of a job in state %s is invalid.\n",
@@ -1494,6 +1529,8 @@ static void wave5_vpu_enc_device_run(void *priv)
break;
}
dev_dbg(inst->dev->dev, "%s: leave and finish job", __func__);
+ pm_runtime_mark_last_busy(inst->dev->dev);
+ pm_runtime_put_autosuspend(inst->dev->dev);
v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx);
}
@@ -1701,6 +1738,9 @@ static int wave5_vpu_open_enc(struct file *filp)
0, 1, 1, 0);
v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 1);
+ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR,
+ 0, 1, 1, 0);
if (v4l2_ctrl_hdl->error) {
ret = -ENODEV;
@@ -1711,6 +1751,8 @@ static int wave5_vpu_open_enc(struct file *filp)
v4l2_ctrl_handler_setup(v4l2_ctrl_hdl);
wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt);
+ inst->conf_win.width = inst->dst_fmt.width;
+ inst->conf_win.height = inst->dst_fmt.height;
inst->colorspace = V4L2_COLORSPACE_REC709;
inst->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
inst->quantization = V4L2_QUANTIZATION_DEFAULT;
@@ -1732,9 +1774,8 @@ static int wave5_vpu_open_enc(struct file *filp)
if (ret)
goto cleanup_inst;
- if (dev->irq < 0 && !hrtimer_active(&dev->hrtimer) && list_empty(&dev->instances))
- hrtimer_start(&dev->hrtimer, ns_to_ktime(dev->vpu_poll_interval * NSEC_PER_MSEC),
- HRTIMER_MODE_REL_PINNED);
+ if (list_empty(&dev->instances))
+ pm_runtime_use_autosuspend(inst->dev->dev);
list_add_tail(&inst->list, &dev->instances);
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.c b/drivers/media/platform/chips-media/wave5/wave5-vpu.c
index 7273254ecb03..6b294a2d6717 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/firmware.h>
#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include "wave5-vpu.h"
#include "wave5-regdefine.h"
@@ -153,6 +154,45 @@ static int wave5_vpu_load_firmware(struct device *dev, const char *fw_name,
return 0;
}
+static __maybe_unused int wave5_pm_suspend(struct device *dev)
+{
+ struct vpu_device *vpu = dev_get_drvdata(dev);
+
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ if (vpu->irq < 0)
+ hrtimer_cancel(&vpu->hrtimer);
+
+ wave5_vpu_sleep_wake(dev, true, NULL, 0);
+ clk_bulk_disable_unprepare(vpu->num_clks, vpu->clks);
+
+ return 0;
+}
+
+static __maybe_unused int wave5_pm_resume(struct device *dev)
+{
+ struct vpu_device *vpu = dev_get_drvdata(dev);
+ int ret = 0;
+
+ wave5_vpu_sleep_wake(dev, false, NULL, 0);
+ ret = clk_bulk_prepare_enable(vpu->num_clks, vpu->clks);
+ if (ret) {
+ dev_err(dev, "Enabling clocks, fail: %d\n", ret);
+ return ret;
+ }
+
+ if (vpu->irq < 0 && !hrtimer_active(&vpu->hrtimer))
+ hrtimer_start(&vpu->hrtimer, ns_to_ktime(vpu->vpu_poll_interval * NSEC_PER_MSEC),
+ HRTIMER_MODE_REL_PINNED);
+
+ return ret;
+}
+
+static const struct dev_pm_ops wave5_pm_ops = {
+ SET_RUNTIME_PM_OPS(wave5_pm_suspend, wave5_pm_resume, NULL)
+};
+
static int wave5_vpu_probe(struct platform_device *pdev)
{
int ret;
@@ -281,6 +321,12 @@ static int wave5_vpu_probe(struct platform_device *pdev)
(match_data->flags & WAVE5_IS_DEC) ? "'DECODE'" : "");
dev_info(&pdev->dev, "Product Code: 0x%x\n", dev->product_code);
dev_info(&pdev->dev, "Firmware Revision: %u\n", fw_revision);
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ wave5_vpu_sleep_wake(&pdev->dev, true, NULL, 0);
+
return 0;
err_enc_unreg:
@@ -310,6 +356,9 @@ static void wave5_vpu_remove(struct platform_device *pdev)
hrtimer_cancel(&dev->hrtimer);
}
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
mutex_destroy(&dev->dev_lock);
mutex_destroy(&dev->hw_lock);
reset_control_assert(dev->resets);
@@ -337,9 +386,10 @@ static struct platform_driver wave5_vpu_driver = {
.driver = {
.name = VPU_PLATFORM_DEVICE_NAME,
.of_match_table = of_match_ptr(wave5_dt_ids),
+ .pm = &wave5_pm_ops,
},
.probe = wave5_vpu_probe,
- .remove_new = wave5_vpu_remove,
+ .remove = wave5_vpu_remove,
};
module_platform_driver(wave5_vpu_driver);
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.h b/drivers/media/platform/chips-media/wave5/wave5-vpu.h
index 32b7fd3730b5..3847332551fc 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu.h
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.h
@@ -38,10 +38,7 @@ enum vpu_fmt_type {
struct vpu_format {
unsigned int v4l2_pix_fmt;
- unsigned int max_width;
- unsigned int min_width;
- unsigned int max_height;
- unsigned int min_height;
+ const struct v4l2_frmsize_stepwise *v4l2_frmsize;
};
static inline struct vpu_instance *wave5_to_vpu_inst(struct v4l2_fh *vfh)
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c
index 1a3efb638dde..e16b990041c2 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c
@@ -6,6 +6,8 @@
*/
#include <linux/bug.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
#include "wave5-vpuapi.h"
#include "wave5-regdefine.h"
#include "wave5.h"
@@ -195,14 +197,20 @@ int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res)
int retry = 0;
struct vpu_device *vpu_dev = inst->dev;
int i;
+ int inst_count = 0;
+ struct vpu_instance *inst_elm;
*fail_res = 0;
if (!inst->codec_info)
return -EINVAL;
+ pm_runtime_resume_and_get(inst->dev->dev);
+
ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
- if (ret)
+ if (ret) {
+ pm_runtime_put_sync(inst->dev->dev);
return ret;
+ }
do {
ret = wave5_vpu_dec_finish_seq(inst, fail_res);
@@ -232,9 +240,14 @@ int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res)
wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_task);
+ list_for_each_entry(inst_elm, &vpu_dev->instances, list)
+ inst_count++;
+ if (inst_count == 1)
+ pm_runtime_dont_use_autosuspend(vpu_dev->dev);
+
unlock_and_return:
mutex_unlock(&vpu_dev->hw_lock);
-
+ pm_runtime_put_sync(inst->dev->dev);
return ret;
}
@@ -697,25 +710,33 @@ int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res)
int ret;
int retry = 0;
struct vpu_device *vpu_dev = inst->dev;
+ int inst_count = 0;
+ struct vpu_instance *inst_elm;
*fail_res = 0;
if (!inst->codec_info)
return -EINVAL;
+ pm_runtime_resume_and_get(inst->dev->dev);
+
ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
- if (ret)
+ if (ret) {
+ pm_runtime_resume_and_get(inst->dev->dev);
return ret;
+ }
do {
ret = wave5_vpu_enc_finish_seq(inst, fail_res);
if (ret < 0 && *fail_res != WAVE5_SYSERR_VPU_STILL_RUNNING) {
dev_warn(inst->dev->dev, "enc_finish_seq timed out\n");
+ pm_runtime_resume_and_get(inst->dev->dev);
mutex_unlock(&vpu_dev->hw_lock);
return ret;
}
if (*fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING &&
retry++ >= MAX_FIRMWARE_CALL_RETRY) {
+ pm_runtime_resume_and_get(inst->dev->dev);
mutex_unlock(&vpu_dev->hw_lock);
return -ETIMEDOUT;
}
@@ -734,7 +755,13 @@ int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res)
wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_task);
+ list_for_each_entry(inst_elm, &vpu_dev->instances, list)
+ inst_count++;
+ if (inst_count == 1)
+ pm_runtime_dont_use_autosuspend(vpu_dev->dev);
+
mutex_unlock(&vpu_dev->hw_lock);
+ pm_runtime_put_sync(inst->dev->dev);
return 0;
}
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
index d2370511faf8..45615c15beca 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
@@ -568,6 +568,7 @@ struct enc_wave_param {
u32 lambda_scaling_enable: 1; /* enable lambda scaling using custom GOP */
u32 transform8x8_enable: 1; /* enable 8x8 intra prediction and 8x8 transform */
u32 mb_level_rc_enable: 1; /* enable MB-level rate control */
+ u32 forced_idr_header_enable: 1; /* enable header encoding before IDR frame */
};
struct enc_open_param {
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
index e4bc2e467cb5..1ea9f5f31499 100644
--- a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
@@ -32,10 +32,29 @@
#define MAX_NUM_INSTANCE 32
-#define W5_MIN_ENC_PIC_WIDTH 256
-#define W5_MIN_ENC_PIC_HEIGHT 128
-#define W5_MAX_ENC_PIC_WIDTH 8192
-#define W5_MAX_ENC_PIC_HEIGHT 8192
+#define W5_DEF_DEC_PIC_WIDTH 720U
+#define W5_DEF_DEC_PIC_HEIGHT 480U
+#define W5_MIN_DEC_PIC_8_WIDTH 8U
+#define W5_MIN_DEC_PIC_8_HEIGHT 8U
+#define W5_MIN_DEC_PIC_32_WIDTH 32U
+#define W5_MIN_DEC_PIC_32_HEIGHT 32U
+#define W5_MAX_DEC_PIC_WIDTH 8192U
+#define W5_MAX_DEC_PIC_HEIGHT 4320U
+#define W5_DEC_CODEC_STEP_WIDTH 1U
+#define W5_DEC_CODEC_STEP_HEIGHT 1U
+#define W5_DEC_RAW_STEP_WIDTH 32U
+#define W5_DEC_RAW_STEP_HEIGHT 16U
+
+#define W5_DEF_ENC_PIC_WIDTH 416U
+#define W5_DEF_ENC_PIC_HEIGHT 240U
+#define W5_MIN_ENC_PIC_WIDTH 256U
+#define W5_MIN_ENC_PIC_HEIGHT 128U
+#define W5_MAX_ENC_PIC_WIDTH 8192U
+#define W5_MAX_ENC_PIC_HEIGHT 8192U
+#define W5_ENC_CODEC_STEP_WIDTH 8U
+#define W5_ENC_CODEC_STEP_HEIGHT 8U
+#define W5_ENC_RAW_STEP_WIDTH 32U
+#define W5_ENC_RAW_STEP_HEIGHT 16U
// application specific configuration
#define VPU_ENC_TIMEOUT 60000
diff --git a/drivers/media/platform/chips-media/wave5/wave5.h b/drivers/media/platform/chips-media/wave5/wave5.h
index 2a29b9164f97..2caab356f3e1 100644
--- a/drivers/media/platform/chips-media/wave5/wave5.h
+++ b/drivers/media/platform/chips-media/wave5/wave5.h
@@ -62,6 +62,9 @@ int wave5_vpu_get_version(struct vpu_device *vpu_dev, u32 *revision);
int wave5_vpu_init(struct device *dev, u8 *fw, size_t size);
+int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code,
+ size_t size);
+
int wave5_vpu_reset(struct device *dev, enum sw_reset_mode reset_mode);
int wave5_vpu_build_up_dec_param(struct vpu_instance *inst, struct dec_open_param *param);
diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.c b/drivers/media/platform/imagination/e5010-jpeg-enc.c
index 187f2d8abfbb..c194f830577f 100644
--- a/drivers/media/platform/imagination/e5010-jpeg-enc.c
+++ b/drivers/media/platform/imagination/e5010-jpeg-enc.c
@@ -1593,8 +1593,6 @@ static const struct vb2_ops e5010_video_ops = {
.buf_finish = e5010_buf_finish,
.buf_prepare = e5010_buf_prepare,
.buf_out_validate = e5010_buf_out_validate,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = e5010_start_streaming,
.stop_streaming = e5010_stop_streaming,
};
@@ -1619,7 +1617,7 @@ MODULE_DEVICE_TABLE(of, e5010_of_match);
static struct platform_driver e5010_driver = {
.probe = e5010_probe,
- .remove_new = e5010_remove,
+ .remove = e5010_remove,
.driver = {
.name = E5010_MODULE_NAME,
.of_match_table = e5010_of_match,
diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c
index f118aaac0b38..bef1e7137f23 100644
--- a/drivers/media/platform/intel/pxa_camera.c
+++ b/drivers/media/platform/intel/pxa_camera.c
@@ -1504,8 +1504,6 @@ static const struct vb2_ops pxac_vb2_ops = {
.buf_cleanup = pxac_vb2_cleanup,
.start_streaming = pxac_vb2_start_streaming,
.stop_streaming = pxac_vb2_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int pxa_camera_init_videobuf2(struct pxa_camera_dev *pcdev)
@@ -2460,7 +2458,7 @@ static struct platform_driver pxa_camera_driver = {
.of_match_table = pxa_camera_of_match,
},
.probe = pxa_camera_probe,
- .remove_new = pxa_camera_remove,
+ .remove = pxa_camera_remove,
};
module_platform_driver(pxa_camera_driver);
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index 5adcef80c698..5188f3189096 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -784,8 +784,6 @@ static const struct vb2_ops deinterlace_qops = {
.queue_setup = deinterlace_queue_setup,
.buf_prepare = deinterlace_buf_prepare,
.buf_queue = deinterlace_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -993,7 +991,7 @@ static void deinterlace_remove(struct platform_device *pdev)
static struct platform_driver deinterlace_pdrv = {
.probe = deinterlace_probe,
- .remove_new = deinterlace_remove,
+ .remove = deinterlace_remove,
.driver = {
.name = MEM2MEM_NAME,
},
diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c
index c81593c969e0..9ec01228f907 100644
--- a/drivers/media/platform/marvell/mcam-core.c
+++ b/drivers/media/platform/marvell/mcam-core.c
@@ -1203,8 +1203,6 @@ static const struct vb2_ops mcam_vb2_ops = {
.buf_queue = mcam_vb_buf_queue,
.start_streaming = mcam_vb_start_streaming,
.stop_streaming = mcam_vb_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
@@ -1267,8 +1265,6 @@ static const struct vb2_ops mcam_vb2_sg_ops = {
.buf_cleanup = mcam_vb_sg_buf_cleanup,
.start_streaming = mcam_vb_start_streaming,
.stop_streaming = mcam_vb_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
#endif /* MCAM_MODE_DMA_SG */
diff --git a/drivers/media/platform/marvell/mmp-driver.c b/drivers/media/platform/marvell/mmp-driver.c
index ff9d151121d5..3fd4fc1b9c48 100644
--- a/drivers/media/platform/marvell/mmp-driver.c
+++ b/drivers/media/platform/marvell/mmp-driver.c
@@ -359,7 +359,7 @@ MODULE_DEVICE_TABLE(of, mmpcam_of_match);
static struct platform_driver mmpcam_driver = {
.probe = mmpcam_probe,
- .remove_new = mmpcam_remove,
+ .remove = mmpcam_remove,
.driver = {
.name = "mmp-camera",
.of_match_table = mmpcam_of_match,
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index ac48658e2de4..834d2a354692 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -884,8 +884,6 @@ static const struct vb2_ops mtk_jpeg_dec_qops = {
.queue_setup = mtk_jpeg_queue_setup,
.buf_prepare = mtk_jpeg_buf_prepare,
.buf_queue = mtk_jpeg_dec_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = mtk_jpeg_dec_stop_streaming,
};
@@ -893,8 +891,6 @@ static const struct vb2_ops mtk_jpeg_enc_qops = {
.queue_setup = mtk_jpeg_queue_setup,
.buf_prepare = mtk_jpeg_buf_prepare,
.buf_queue = mtk_jpeg_enc_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = mtk_jpeg_enc_stop_streaming,
};
@@ -1293,6 +1289,11 @@ static int mtk_jpeg_single_core_init(struct platform_device *pdev,
return 0;
}
+static void mtk_jpeg_destroy_workqueue(void *data)
+{
+ destroy_workqueue(data);
+}
+
static int mtk_jpeg_probe(struct platform_device *pdev)
{
struct mtk_jpeg_dev *jpeg;
@@ -1337,6 +1338,11 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
| WQ_FREEZABLE);
if (!jpeg->workqueue)
return -EINVAL;
+ ret = devm_add_action_or_reset(&pdev->dev,
+ mtk_jpeg_destroy_workqueue,
+ jpeg->workqueue);
+ if (ret)
+ return ret;
}
ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
@@ -1950,7 +1956,7 @@ MODULE_DEVICE_TABLE(of, mtk_jpeg_match);
static struct platform_driver mtk_jpeg_driver = {
.probe = mtk_jpeg_probe,
- .remove_new = mtk_jpeg_remove,
+ .remove = mtk_jpeg_remove,
.driver = {
.name = MTK_JPEG_NAME,
.of_match_table = mtk_jpeg_match,
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
index 4a6ee211e18f..2c5d74939d0a 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
@@ -578,11 +578,6 @@ static int mtk_jpegdec_hw_init_irq(struct mtk_jpegdec_comp_dev *dev)
return 0;
}
-static void mtk_jpegdec_destroy_workqueue(void *data)
-{
- destroy_workqueue(data);
-}
-
static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
{
struct mtk_jpegdec_clk *jpegdec_clk;
@@ -606,12 +601,6 @@ static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
dev->plat_dev = pdev;
dev->dev = &pdev->dev;
- ret = devm_add_action_or_reset(&pdev->dev,
- mtk_jpegdec_destroy_workqueue,
- master_dev->workqueue);
- if (ret)
- return ret;
-
spin_lock_init(&dev->hw_lock);
dev->hw_state = MTK_JPEG_HW_IDLE;
diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c
index 917cdf38f230..80fdc6ff57e0 100644
--- a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c
+++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c
@@ -298,7 +298,7 @@ static const struct dev_pm_ops mtk_mdp_pm_ops = {
static struct platform_driver mtk_mdp_driver = {
.probe = mtk_mdp_probe,
- .remove_new = mtk_mdp_remove,
+ .remove = mtk_mdp_remove,
.driver = {
.name = MTK_MDP_MODULE_NAME,
.pm = &mtk_mdp_pm_ops,
diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c
index f14779e7596e..28c998bd3a81 100644
--- a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c
+++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c
@@ -584,8 +584,6 @@ static const struct vb2_ops mtk_mdp_m2m_qops = {
.buf_queue = mtk_mdp_m2m_buf_queue,
.stop_streaming = mtk_mdp_m2m_stop_streaming,
.start_streaming = mtk_mdp_m2m_start_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int mtk_mdp_m2m_querycap(struct file *file, void *fh,
diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
index 37e7b985d52c..5e94ff0d0756 100644
--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
+++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
@@ -413,7 +413,7 @@ static const struct dev_pm_ops mdp_pm_ops = {
static struct platform_driver mdp_driver = {
.probe = mdp_probe,
- .remove_new = mdp_remove,
+ .remove = mdp_remove,
.driver = {
.name = MDP_MODULE_NAME,
.pm = &mdp_pm_ops,
diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c
index 0e69128a3772..59ce5cce0698 100644
--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c
+++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c
@@ -266,8 +266,6 @@ static void mdp_m2m_buf_queue(struct vb2_buffer *vb)
static const struct vb2_ops mdp_m2m_qops = {
.queue_setup = mdp_m2m_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_prepare = mdp_m2m_buf_prepare,
.start_streaming = mdp_m2m_start_streaming,
.stop_streaming = mdp_m2m_stop_streaming,
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
index 2073781ccadb..9247d92d431d 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
@@ -591,7 +591,7 @@ static void mtk_vcodec_dec_remove(struct platform_device *pdev)
static struct platform_driver mtk_vcodec_dec_driver = {
.probe = mtk_vcodec_probe,
- .remove_new = mtk_vcodec_dec_remove,
+ .remove = mtk_vcodec_dec_remove,
.driver = {
.name = MTK_VCODEC_DEC_NAME,
.of_match_table = mtk_vcodec_match,
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
index e62c1c18758b..aa9bdee7a96c 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
@@ -598,8 +598,6 @@ static void mtk_init_vdec_params(struct mtk_vcodec_dec_ctx *ctx)
static const struct vb2_ops mtk_vdec_frame_vb2_ops = {
.queue_setup = vb2ops_vdec_queue_setup,
.buf_prepare = vb2ops_vdec_buf_prepare,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = vb2ops_vdec_start_streaming,
.buf_queue = vb2ops_vdec_stateful_buf_queue,
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index 3307dc15fc1d..afa224da0f41 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -856,8 +856,6 @@ static int vb2ops_vdec_out_buf_validate(struct vb2_buffer *vb)
static const struct vb2_ops mtk_vdec_request_vb2_ops = {
.queue_setup = vb2ops_vdec_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = vb2ops_vdec_start_streaming,
.stop_streaming = vb2ops_vdec_stop_streaming,
diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c
index 7eaf0e24c9fc..a01dc25a7699 100644
--- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c
@@ -1009,8 +1009,6 @@ static const struct vb2_ops mtk_venc_vb2_ops = {
.buf_out_validate = vb2ops_venc_buf_out_validate,
.buf_prepare = vb2ops_venc_buf_prepare,
.buf_queue = vb2ops_venc_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = vb2ops_venc_start_streaming,
.stop_streaming = vb2ops_venc_stop_streaming,
};
diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c
index 3cb8a1622222..a1e4483abcdb 100644
--- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c
@@ -473,7 +473,7 @@ static void mtk_vcodec_enc_remove(struct platform_device *pdev)
static struct platform_driver mtk_vcodec_enc_driver = {
.probe = mtk_vcodec_probe,
- .remove_new = mtk_vcodec_enc_remove,
+ .remove = mtk_vcodec_enc_remove,
.driver = {
.name = MTK_VCODEC_ENC_NAME,
.of_match_table = mtk_vcodec_enc_match,
diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.c b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
index 724ae7c2ab3b..8d8319f0cd22 100644
--- a/drivers/media/platform/mediatek/vpu/mtk_vpu.c
+++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
@@ -1041,7 +1041,7 @@ static const struct dev_pm_ops mtk_vpu_pm = {
static struct platform_driver mtk_vpu_driver = {
.probe = mtk_vpu_probe,
- .remove_new = mtk_vpu_remove,
+ .remove = mtk_vpu_remove,
.driver = {
.name = "mtk_vpu",
.pm = &mtk_vpu_pm,
diff --git a/drivers/media/platform/microchip/microchip-csi2dc.c b/drivers/media/platform/microchip/microchip-csi2dc.c
index fee73260bb1e..70303a0b6919 100644
--- a/drivers/media/platform/microchip/microchip-csi2dc.c
+++ b/drivers/media/platform/microchip/microchip-csi2dc.c
@@ -782,7 +782,7 @@ MODULE_DEVICE_TABLE(of, csi2dc_of_match);
static struct platform_driver csi2dc_driver = {
.probe = csi2dc_probe,
- .remove_new = csi2dc_remove,
+ .remove = csi2dc_remove,
.driver = {
.name = "microchip-csi2dc",
.pm = &csi2dc_dev_pm_ops,
diff --git a/drivers/media/platform/microchip/microchip-isc-base.c b/drivers/media/platform/microchip/microchip-isc-base.c
index 28e56f6a695d..a7cdc743fda7 100644
--- a/drivers/media/platform/microchip/microchip-isc-base.c
+++ b/drivers/media/platform/microchip/microchip-isc-base.c
@@ -465,8 +465,6 @@ static void isc_buffer_queue(struct vb2_buffer *vb)
static const struct vb2_ops isc_vb2_ops = {
.queue_setup = isc_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_prepare = isc_buffer_prepare,
.start_streaming = isc_start_streaming,
.stop_streaming = isc_stop_streaming,
diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
index 60b6d922d764..66d3d7891991 100644
--- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
@@ -658,7 +658,7 @@ MODULE_DEVICE_TABLE(of, microchip_isc_of_match);
static struct platform_driver microchip_isc_driver = {
.probe = microchip_isc_probe,
- .remove_new = microchip_isc_remove,
+ .remove = microchip_isc_remove,
.driver = {
.name = "microchip-sama5d2-isc",
.pm = &microchip_isc_dev_pm_ops,
diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
index e97abe3e35af..b0302dfc3278 100644
--- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
@@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, microchip_xisc_of_match);
static struct platform_driver microchip_xisc_driver = {
.probe = microchip_xisc_probe,
- .remove_new = microchip_xisc_remove,
+ .remove = microchip_xisc_remove,
.driver = {
.name = "microchip-sama7g5-xisc",
.pm = &microchip_xisc_dev_pm_ops,
diff --git a/drivers/media/platform/nuvoton/npcm-video.c b/drivers/media/platform/nuvoton/npcm-video.c
index 60fbb9140035..4f5d75645b2b 100644
--- a/drivers/media/platform/nuvoton/npcm-video.c
+++ b/drivers/media/platform/nuvoton/npcm-video.c
@@ -1558,8 +1558,6 @@ static const struct regmap_config npcm_video_ece_regmap_cfg = {
static const struct vb2_ops npcm_video_vb2_ops = {
.queue_setup = npcm_video_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_prepare = npcm_video_buf_prepare,
.buf_finish = npcm_video_buf_finish,
.start_streaming = npcm_video_start_streaming,
@@ -1814,7 +1812,7 @@ static struct platform_driver npcm_video_driver = {
.of_match_table = npcm_video_match,
},
.probe = npcm_video_probe,
- .remove_new = npcm_video_remove,
+ .remove = npcm_video_remove,
};
module_platform_driver(npcm_video_driver);
diff --git a/drivers/media/platform/nvidia/tegra-vde/iommu.c b/drivers/media/platform/nvidia/tegra-vde/iommu.c
index 5521ed3e465f..b1d9d841d944 100644
--- a/drivers/media/platform/nvidia/tegra-vde/iommu.c
+++ b/drivers/media/platform/nvidia/tegra-vde/iommu.c
@@ -78,9 +78,10 @@ int tegra_vde_iommu_init(struct tegra_vde *vde)
arm_iommu_release_mapping(mapping);
}
#endif
- vde->domain = iommu_domain_alloc(&platform_bus_type);
- if (!vde->domain) {
- err = -ENOMEM;
+ vde->domain = iommu_paging_domain_alloc(dev);
+ if (IS_ERR(vde->domain)) {
+ err = PTR_ERR(vde->domain);
+ vde->domain = NULL;
goto put_group;
}
diff --git a/drivers/media/platform/nvidia/tegra-vde/v4l2.c b/drivers/media/platform/nvidia/tegra-vde/v4l2.c
index 0f48ce6f243e..e3726cab0c82 100644
--- a/drivers/media/platform/nvidia/tegra-vde/v4l2.c
+++ b/drivers/media/platform/nvidia/tegra-vde/v4l2.c
@@ -328,8 +328,6 @@ static const struct vb2_ops tegra_qops = {
.buf_request_complete = tegra_buf_request_complete,
.start_streaming = tegra_start_streaming,
.stop_streaming = tegra_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int tegra_queue_init(void *priv,
@@ -929,13 +927,13 @@ int tegra_vde_v4l2_init(struct tegra_vde *vde)
media_device_init(&vde->mdev);
video_set_drvdata(&vde->vdev, vde);
- vde->vdev.lock = &vde->v4l2_lock,
- vde->vdev.fops = &tegra_v4l2_fops,
- vde->vdev.vfl_dir = VFL_DIR_M2M,
- vde->vdev.release = video_device_release_empty,
+ vde->vdev.lock = &vde->v4l2_lock;
+ vde->vdev.fops = &tegra_v4l2_fops;
+ vde->vdev.vfl_dir = VFL_DIR_M2M;
+ vde->vdev.release = video_device_release_empty;
vde->vdev.v4l2_dev = &vde->v4l2_dev;
- vde->vdev.ioctl_ops = &tegra_v4l2_ioctl_ops,
- vde->vdev.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
+ vde->vdev.ioctl_ops = &tegra_v4l2_ioctl_ops;
+ vde->vdev.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
vde->v4l2_dev.mdev = &vde->mdev;
vde->mdev.ops = &tegra_media_device_ops;
diff --git a/drivers/media/platform/nvidia/tegra-vde/vde.c b/drivers/media/platform/nvidia/tegra-vde/vde.c
index 81a0d3b76b88..3232392c60e2 100644
--- a/drivers/media/platform/nvidia/tegra-vde/vde.c
+++ b/drivers/media/platform/nvidia/tegra-vde/vde.c
@@ -535,7 +535,7 @@ MODULE_DEVICE_TABLE(of, tegra_vde_of_match);
static struct platform_driver tegra_vde_driver = {
.probe = tegra_vde_probe,
- .remove_new = tegra_vde_remove,
+ .remove = tegra_vde_remove,
.shutdown = tegra_vde_shutdown,
.driver = {
.name = "tegra-vde",
diff --git a/drivers/media/platform/nxp/dw100/dw100.c b/drivers/media/platform/nxp/dw100/dw100.c
index 0024d6175ad9..66582e7f92fc 100644
--- a/drivers/media/platform/nxp/dw100/dw100.c
+++ b/drivers/media/platform/nxp/dw100/dw100.c
@@ -558,8 +558,6 @@ static const struct vb2_ops dw100_qops = {
.buf_queue = dw100_buf_queue,
.start_streaming = dw100_start_streaming,
.stop_streaming = dw100_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int dw100_m2m_queue_init(void *priv, struct vb2_queue *src_vq,
@@ -1311,7 +1309,7 @@ static void dw100_hw_set_destination(struct dw100_device *dw_dev,
}
dev_dbg(&dw_dev->pdev->dev,
- "Set HW source registers for %ux%u - stride %u, pixfmt: %p4cc, dma:%pad\n",
+ "Set HW destination registers for %ux%u - stride %u, pixfmt: %p4cc, dma:%pad\n",
width, height, stride, &fourcc, &addr_y);
/* Pixel Format */
@@ -1688,7 +1686,7 @@ MODULE_DEVICE_TABLE(of, dw100_dt_ids);
static struct platform_driver dw100_driver = {
.probe = dw100_probe,
- .remove_new = dw100_remove,
+ .remove = dw100_remove,
.driver = {
.name = DRV_NAME,
.pm = &dw100_pm,
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 1d8913813037..7f5fe551179b 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1965,8 +1965,6 @@ static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)
static const struct vb2_ops mxc_jpeg_qops = {
.queue_setup = mxc_jpeg_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_out_validate = mxc_jpeg_buf_out_validate,
.buf_prepare = mxc_jpeg_buf_prepare,
.start_streaming = mxc_jpeg_start_streaming,
@@ -2679,6 +2677,8 @@ static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)
int i;
for (i = 0; i < jpeg->num_domains; i++) {
+ if (jpeg->pd_dev[i] && !pm_runtime_suspended(jpeg->pd_dev[i]))
+ pm_runtime_force_suspend(jpeg->pd_dev[i]);
if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i]))
device_link_del(jpeg->pd_link[i]);
if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i]))
@@ -2842,6 +2842,7 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
V4L2_CAP_VIDEO_M2M_MPLANE;
+ video_set_drvdata(jpeg->dec_vdev, jpeg);
if (mode == MXC_JPEG_ENCODE) {
v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_DECODER_CMD);
v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_DECODER_CMD);
@@ -2854,7 +2855,6 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
dev_err(dev, "failed to register video device\n");
goto err_vdev_register;
}
- video_set_drvdata(jpeg->dec_vdev, jpeg);
if (mode == MXC_JPEG_ENCODE)
v4l2_info(&jpeg->v4l2_dev,
"encoder device registered as /dev/video%d (%d,%d)\n",
@@ -2888,7 +2888,6 @@ err_clk:
return ret;
}
-#ifdef CONFIG_PM
static int mxc_jpeg_runtime_resume(struct device *dev)
{
struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
@@ -2911,9 +2910,7 @@ static int mxc_jpeg_runtime_suspend(struct device *dev)
return 0;
}
-#endif
-#ifdef CONFIG_PM_SLEEP
static int mxc_jpeg_suspend(struct device *dev)
{
struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
@@ -2934,12 +2931,10 @@ static int mxc_jpeg_resume(struct device *dev)
v4l2_m2m_resume(jpeg->m2m_dev);
return ret;
}
-#endif
static const struct dev_pm_ops mxc_jpeg_pm_ops = {
- SET_RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend,
- mxc_jpeg_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(mxc_jpeg_suspend, mxc_jpeg_resume)
+ RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend, mxc_jpeg_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(mxc_jpeg_suspend, mxc_jpeg_resume)
};
static void mxc_jpeg_remove(struct platform_device *pdev)
@@ -2959,11 +2954,11 @@ MODULE_DEVICE_TABLE(of, mxc_jpeg_match);
static struct platform_driver mxc_jpeg_driver = {
.probe = mxc_jpeg_probe,
- .remove_new = mxc_jpeg_remove,
+ .remove = mxc_jpeg_remove,
.driver = {
.name = "mxc-jpeg",
.of_match_table = mxc_jpeg_match,
- .pm = &mxc_jpeg_pm_ops,
+ .pm = pm_ptr(&mxc_jpeg_pm_ops),
},
};
module_platform_driver(mxc_jpeg_driver);
diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
index 44e1402e8be1..29523bb84d95 100644
--- a/drivers/media/platform/nxp/imx-mipi-csis.c
+++ b/drivers/media/platform/nxp/imx-mipi-csis.c
@@ -1570,7 +1570,7 @@ MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
static struct platform_driver mipi_csis_driver = {
.probe = mipi_csis_probe,
- .remove_new = mipi_csis_remove,
+ .remove = mipi_csis_remove,
.driver = {
.of_match_table = mipi_csis_of_match,
.name = CSIS_DRIVER_NAME,
diff --git a/drivers/media/platform/nxp/imx-pxp.c b/drivers/media/platform/nxp/imx-pxp.c
index e4427e6487fb..7f8ffbac582f 100644
--- a/drivers/media/platform/nxp/imx-pxp.c
+++ b/drivers/media/platform/nxp/imx-pxp.c
@@ -1606,8 +1606,6 @@ static const struct vb2_ops pxp_qops = {
.buf_queue = pxp_buf_queue,
.start_streaming = pxp_start_streaming,
.stop_streaming = pxp_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -1943,7 +1941,7 @@ MODULE_DEVICE_TABLE(of, pxp_dt_ids);
static struct platform_driver pxp_driver = {
.probe = pxp_probe,
- .remove_new = pxp_remove,
+ .remove = pxp_remove,
.driver = {
.name = MEM2MEM_NAME,
.of_match_table = pxp_dt_ids,
diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c
index 9566ff738818..34a92642bbfe 100644
--- a/drivers/media/platform/nxp/imx7-media-csi.c
+++ b/drivers/media/platform/nxp/imx7-media-csi.c
@@ -1507,8 +1507,6 @@ static const struct vb2_ops imx7_csi_video_qops = {
.buf_init = imx7_csi_video_buf_init,
.buf_prepare = imx7_csi_video_buf_prepare,
.buf_queue = imx7_csi_video_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = imx7_csi_video_start_streaming,
.stop_streaming = imx7_csi_video_stop_streaming,
};
@@ -2281,7 +2279,7 @@ MODULE_DEVICE_TABLE(of, imx7_csi_of_match);
static struct platform_driver imx7_csi_driver = {
.probe = imx7_csi_probe,
- .remove_new = imx7_csi_remove,
+ .remove = imx7_csi_remove,
.driver = {
.of_match_table = imx7_csi_of_match,
.name = "imx7-csi",
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
index c2013995049c..aaf58063677c 100644
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
@@ -535,7 +535,7 @@ MODULE_DEVICE_TABLE(of, mxc_isi_of_match);
static struct platform_driver mxc_isi_driver = {
.probe = mxc_isi_probe,
- .remove_new = mxc_isi_remove,
+ .remove = mxc_isi_remove,
.driver = {
.of_match_table = mxc_isi_of_match,
.name = MXC_ISI_DRIVER_NAME,
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
index 9745d6219a16..794050a6a919 100644
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
@@ -269,8 +269,6 @@ static const struct vb2_ops mxc_isi_m2m_vb2_qops = {
.buf_init = mxc_isi_m2m_vb2_buffer_init,
.buf_prepare = mxc_isi_m2m_vb2_buffer_prepare,
.buf_queue = mxc_isi_m2m_vb2_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = mxc_isi_m2m_vb2_start_streaming,
.stop_streaming = mxc_isi_m2m_vb2_stop_streaming,
};
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
index 4091f1c0e78b..c0ba34ea82fd 100644
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
@@ -987,8 +987,6 @@ static const struct vb2_ops mxc_isi_vb2_qops = {
.buf_init = mxc_isi_vb2_buffer_init,
.buf_prepare = mxc_isi_vb2_buffer_prepare,
.buf_queue = mxc_isi_vb2_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = mxc_isi_vb2_start_streaming,
.stop_streaming = mxc_isi_vb2_stop_streaming,
};
diff --git a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
index d4a6c5532969..1f2657cf6e82 100644
--- a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
+++ b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c
@@ -953,7 +953,7 @@ MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match);
static struct platform_driver imx8mq_mipi_csi_driver = {
.probe = imx8mq_mipi_csi_probe,
- .remove_new = imx8mq_mipi_csi_remove,
+ .remove = imx8mq_mipi_csi_remove,
.driver = {
.of_match_table = imx8mq_mipi_csi_of_match,
.name = MIPI_CSI2_DRIVER_NAME,
diff --git a/drivers/media/platform/nxp/mx2_emmaprp.c b/drivers/media/platform/nxp/mx2_emmaprp.c
index 023ed40c6b08..0c6cc120fd2a 100644
--- a/drivers/media/platform/nxp/mx2_emmaprp.c
+++ b/drivers/media/platform/nxp/mx2_emmaprp.c
@@ -677,8 +677,6 @@ static const struct vb2_ops emmaprp_qops = {
.queue_setup = emmaprp_queue_setup,
.buf_prepare = emmaprp_buf_prepare,
.buf_queue = emmaprp_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -902,7 +900,7 @@ static void emmaprp_remove(struct platform_device *pdev)
static struct platform_driver emmaprp_pdrv = {
.probe = emmaprp_probe,
- .remove_new = emmaprp_remove,
+ .remove = emmaprp_remove,
.driver = {
.name = MEM2MEM_NAME,
},
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
index 2f7361dfd461..5af2b382a843 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -212,14 +212,25 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on)
if (ret < 0)
return ret;
+ ret = regulator_bulk_enable(csiphy->num_supplies,
+ csiphy->supplies);
+ if (ret < 0) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
ret = csiphy_set_clock_rates(csiphy);
if (ret < 0) {
+ regulator_bulk_disable(csiphy->num_supplies,
+ csiphy->supplies);
pm_runtime_put_sync(dev);
return ret;
}
ret = camss_enable_clocks(csiphy->nclocks, csiphy->clock, dev);
if (ret < 0) {
+ regulator_bulk_disable(csiphy->num_supplies,
+ csiphy->supplies);
pm_runtime_put_sync(dev);
return ret;
}
@@ -234,6 +245,8 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on)
camss_disable_clocks(csiphy->nclocks, csiphy->clock);
+ regulator_bulk_disable(csiphy->num_supplies, csiphy->supplies);
+
pm_runtime_put_sync(dev);
}
@@ -583,6 +596,7 @@ int msm_csiphy_subdev_init(struct camss *camss,
return PTR_ERR(csiphy->base);
if (camss->res->version == CAMSS_8x16 ||
+ camss->res->version == CAMSS_8x53 ||
camss->res->version == CAMSS_8x96) {
csiphy->base_clk_mux =
devm_platform_ioremap_resource_byname(pdev, res->reg[1]);
@@ -676,7 +690,27 @@ int msm_csiphy_subdev_init(struct camss *camss,
}
}
- return 0;
+ /* CSIPHY supplies */
+ for (i = 0; i < ARRAY_SIZE(res->regulators); i++) {
+ if (res->regulators[i])
+ csiphy->num_supplies++;
+ }
+
+ if (csiphy->num_supplies) {
+ csiphy->supplies = devm_kmalloc_array(camss->dev,
+ csiphy->num_supplies,
+ sizeof(*csiphy->supplies),
+ GFP_KERNEL);
+ if (!csiphy->supplies)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < csiphy->num_supplies; i++)
+ csiphy->supplies[i].supply = res->regulators[i];
+
+ ret = devm_regulator_bulk_get(camss->dev, csiphy->num_supplies,
+ csiphy->supplies);
+ return ret;
}
/*
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h
index 47f0b6b09eba..eebc1ff1cfab 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.h
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.h
@@ -91,6 +91,8 @@ struct csiphy_device {
bool *rate_set;
int nclocks;
u32 timer_clk_rate;
+ struct regulator_bulk_data *supplies;
+ int num_supplies;
struct csiphy_config cfg;
struct v4l2_mbus_framefmt fmt[MSM_CSIPHY_PADS_NUM];
const struct csiphy_subdev_resources *res;
diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c
index a12dcc7ff438..2dc585c6123d 100644
--- a/drivers/media/platform/qcom/camss/camss-ispif.c
+++ b/drivers/media/platform/qcom/camss/camss-ispif.c
@@ -830,6 +830,7 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable)
ispif_select_cid(ispif, intf, cid, vfe, 1);
ispif_config_irq(ispif, intf, vfe, 1);
if (camss->res->version == CAMSS_8x96 ||
+ camss->res->version == CAMSS_8x53 ||
camss->res->version == CAMSS_660)
ispif_config_pack(ispif,
line->fmt[MSM_ISPIF_PAD_SINK].code,
@@ -848,6 +849,7 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable)
mutex_lock(&ispif->config_lock);
if (camss->res->version == CAMSS_8x96 ||
+ camss->res->version == CAMSS_8x53 ||
camss->res->version == CAMSS_660)
ispif_config_pack(ispif,
line->fmt[MSM_ISPIF_PAD_SINK].code,
@@ -1111,6 +1113,7 @@ int msm_ispif_subdev_init(struct camss *camss,
if (camss->res->version == CAMSS_8x16)
ispif->line_num = 2;
else if (camss->res->version == CAMSS_8x96 ||
+ camss->res->version == CAMSS_8x53 ||
camss->res->version == CAMSS_660)
ispif->line_num = 4;
else
@@ -1130,6 +1133,7 @@ int msm_ispif_subdev_init(struct camss *camss,
ispif->line[i].nformats =
ARRAY_SIZE(ispif_formats_8x16);
} else if (camss->res->version == CAMSS_8x96 ||
+ camss->res->version == CAMSS_8x53 ||
camss->res->version == CAMSS_660) {
ispif->line[i].formats = ispif_formats_8x96;
ispif->line[i].nformats =
@@ -1162,6 +1166,7 @@ int msm_ispif_subdev_init(struct camss *camss,
ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x16,
IRQF_TRIGGER_RISING, ispif->irq_name, ispif);
else if (camss->res->version == CAMSS_8x96 ||
+ camss->res->version == CAMSS_8x53 ||
camss->res->version == CAMSS_660)
ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x96,
IRQF_TRIGGER_RISING, ispif->irq_name, ispif);
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
index 1bd3a6ef1d04..9a9007c3ff33 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
@@ -938,7 +938,10 @@ static irqreturn_t vfe_isr(int irq, void *dev)
*/
static void vfe_4_1_pm_domain_off(struct vfe_device *vfe)
{
- /* nop */
+ if (!vfe->res->has_pd)
+ return;
+
+ vfe_pm_domain_off(vfe);
}
/*
@@ -947,7 +950,10 @@ static void vfe_4_1_pm_domain_off(struct vfe_device *vfe)
*/
static int vfe_4_1_pm_domain_on(struct vfe_device *vfe)
{
- return 0;
+ if (!vfe->res->has_pd)
+ return 0;
+
+ return vfe_pm_domain_on(vfe);
}
static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_1 = {
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
index 83c5a36d071f..80a62ba11295 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
@@ -285,6 +285,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
switch (vfe->camss->res->version) {
case CAMSS_8x16:
+ case CAMSS_8x53:
switch (sink_code) {
case MEDIA_BUS_FMT_YUYV8_1X16:
{
diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c
index 3b8fc31d957c..aa021fd5e123 100644
--- a/drivers/media/platform/qcom/camss/camss-video.c
+++ b/drivers/media/platform/qcom/camss/camss-video.c
@@ -310,8 +310,6 @@ static void video_stop_streaming(struct vb2_queue *q)
static const struct vb2_ops msm_video_vb2_q_ops = {
.queue_setup = video_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_init = video_buf_init,
.buf_prepare = video_buf_prepare,
.buf_queue = video_buf_queue,
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index d64985ca6e88..9fb31f4c18ad 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -152,6 +152,160 @@ static const struct camss_subdev_resources vfe_res_8x16[] = {
}
};
+static const struct camss_subdev_resources csid_res_8x53[] = {
+ /* CSID0 */
+ {
+ .regulators = { "vdda" },
+ .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb",
+ "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" },
+ .clock_rate = { { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 100000000, 200000000, 310000000,
+ 400000000, 465000000 },
+ { 0 },
+ { 0 },
+ { 0 } },
+ .reg = { "csid0" },
+ .interrupt = { "csid0" },
+ .csid = {
+ .hw_ops = &csid_ops_4_7,
+ .parent_dev_ops = &vfe_parent_dev_ops,
+ .formats = &csid_formats_4_7
+ }
+ },
+
+ /* CSID1 */
+ {
+ .regulators = { "vdda" },
+ .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb",
+ "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" },
+ .clock_rate = { { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 100000000, 200000000, 310000000,
+ 400000000, 465000000 },
+ { 0 },
+ { 0 },
+ { 0 } },
+ .reg = { "csid1" },
+ .interrupt = { "csid1" },
+ .csid = {
+ .hw_ops = &csid_ops_4_7,
+ .parent_dev_ops = &vfe_parent_dev_ops,
+ .formats = &csid_formats_4_7
+ }
+ },
+
+ /* CSID2 */
+ {
+ .regulators = { "vdda" },
+ .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb",
+ "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" },
+ .clock_rate = { { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 100000000, 200000000, 310000000,
+ 400000000, 465000000 },
+ { 0 },
+ { 0 },
+ { 0 } },
+ .reg = { "csid2" },
+ .interrupt = { "csid2" },
+ .csid = {
+ .hw_ops = &csid_ops_4_7,
+ .parent_dev_ops = &vfe_parent_dev_ops,
+ .formats = &csid_formats_4_7
+ }
+ },
+};
+
+static const struct camss_subdev_resources ispif_res_8x53 = {
+ /* ISPIF */
+ .clock = { "top_ahb", "ahb", "ispif_ahb",
+ "csi0", "csi0_pix", "csi0_rdi",
+ "csi1", "csi1_pix", "csi1_rdi",
+ "csi2", "csi2_pix", "csi2_rdi" },
+ .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" },
+ .reg = { "ispif", "csi_clk_mux" },
+ .interrupt = { "ispif" },
+};
+
+static const struct camss_subdev_resources vfe_res_8x53[] = {
+ /* VFE0 */
+ {
+ .regulators = {},
+ .clock = { "top_ahb", "ahb", "ispif_ahb",
+ "vfe0", "csi_vfe0", "vfe0_ahb", "vfe0_axi" },
+ .clock_rate = { { 0 },
+ { 0 },
+ { 0 },
+ { 50000000, 100000000, 133330000,
+ 160000000, 200000000, 266670000,
+ 310000000, 400000000, 465000000 },
+ { 0 },
+ { 0 },
+ { 0 } },
+ .reg = { "vfe0" },
+ .interrupt = { "vfe0" },
+ .vfe = {
+ .line_num = 3,
+ .has_pd = true,
+ .pd_name = "vfe0",
+ .hw_ops = &vfe_ops_4_1,
+ .formats_rdi = &vfe_formats_rdi_8x16,
+ .formats_pix = &vfe_formats_pix_8x16
+ }
+ },
+
+ /* VFE1 */
+ {
+ .regulators = {},
+ .clock = { "top_ahb", "ahb", "ispif_ahb",
+ "vfe1", "csi_vfe1", "vfe1_ahb", "vfe1_axi" },
+ .clock_rate = { { 0 },
+ { 0 },
+ { 0 },
+ { 50000000, 100000000, 133330000,
+ 160000000, 200000000, 266670000,
+ 310000000, 400000000, 465000000 },
+ { 0 },
+ { 0 },
+ { 0 } },
+ .reg = { "vfe1" },
+ .interrupt = { "vfe1" },
+ .vfe = {
+ .line_num = 3,
+ .has_pd = true,
+ .pd_name = "vfe1",
+ .hw_ops = &vfe_ops_4_1,
+ .formats_rdi = &vfe_formats_rdi_8x16,
+ .formats_pix = &vfe_formats_pix_8x16
+ }
+ }
+};
+
+static const struct resources_icc icc_res_8x53[] = {
+ {
+ .name = "cam_ahb",
+ .icc_bw_tbl.avg = 38400,
+ .icc_bw_tbl.peak = 76800,
+ },
+ {
+ .name = "cam_vfe0_mem",
+ .icc_bw_tbl.avg = 939524,
+ .icc_bw_tbl.peak = 1342177,
+ },
+ {
+ .name = "cam_vfe1_mem",
+ .icc_bw_tbl.avg = 939524,
+ .icc_bw_tbl.peak = 1342177,
+ },
+};
+
static const struct camss_subdev_resources csiphy_res_8x96[] = {
/* CSIPHY0 */
{
@@ -837,7 +991,7 @@ static const struct camss_subdev_resources vfe_res_845[] = {
static const struct camss_subdev_resources csiphy_res_8250[] = {
/* CSIPHY0 */
{
- .regulators = {},
+ .regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy0", "csiphy0_timer" },
.clock_rate = { { 400000000 },
{ 300000000 } },
@@ -850,7 +1004,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
},
/* CSIPHY1 */
{
- .regulators = {},
+ .regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy1", "csiphy1_timer" },
.clock_rate = { { 400000000 },
{ 300000000 } },
@@ -863,7 +1017,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
},
/* CSIPHY2 */
{
- .regulators = {},
+ .regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy2", "csiphy2_timer" },
.clock_rate = { { 400000000 },
{ 300000000 } },
@@ -876,7 +1030,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
},
/* CSIPHY3 */
{
- .regulators = {},
+ .regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy3", "csiphy3_timer" },
.clock_rate = { { 400000000 },
{ 300000000 } },
@@ -889,7 +1043,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
},
/* CSIPHY4 */
{
- .regulators = {},
+ .regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy4", "csiphy4_timer" },
.clock_rate = { { 400000000 },
{ 300000000 } },
@@ -902,7 +1056,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
},
/* CSIPHY5 */
{
- .regulators = {},
+ .regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy5", "csiphy5_timer" },
.clock_rate = { { 400000000 },
{ 300000000 } },
@@ -918,7 +1072,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
static const struct camss_subdev_resources csid_res_8250[] = {
/* CSID0 */
{
- .regulators = { "vdda-phy", "vdda-pll" },
+ .regulators = {},
.clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_areg", "vfe0_ahb" },
.clock_rate = { { 400000000 },
{ 400000000 },
@@ -935,7 +1089,7 @@ static const struct camss_subdev_resources csid_res_8250[] = {
},
/* CSID1 */
{
- .regulators = { "vdda-phy", "vdda-pll" },
+ .regulators = {},
.clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_areg", "vfe1_ahb" },
.clock_rate = { { 400000000 },
{ 400000000 },
@@ -952,7 +1106,7 @@ static const struct camss_subdev_resources csid_res_8250[] = {
},
/* CSID2 */
{
- .regulators = { "vdda-phy", "vdda-pll" },
+ .regulators = {},
.clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" },
.clock_rate = { { 400000000 },
{ 400000000 },
@@ -969,7 +1123,7 @@ static const struct camss_subdev_resources csid_res_8250[] = {
},
/* CSID3 */
{
- .regulators = { "vdda-phy", "vdda-pll" },
+ .regulators = {},
.clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" },
.clock_rate = { { 400000000 },
{ 400000000 },
@@ -1780,6 +1934,7 @@ err_cleanup:
*/
static int camss_init_subdevices(struct camss *camss)
{
+ struct platform_device *pdev = to_platform_device(camss->dev);
const struct camss_resources *res = camss->res;
unsigned int i;
int ret;
@@ -1806,6 +1961,17 @@ static int camss_init_subdevices(struct camss *camss)
}
}
+ /* Get optional CSID wrapper regs shared between CSID devices */
+ if (res->csid_wrapper_res) {
+ char *reg = res->csid_wrapper_res->reg;
+ void __iomem *base;
+
+ base = devm_platform_ioremap_resource_byname(pdev, reg);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+ camss->csid_wrapper_base = base;
+ }
+
for (i = 0; i < camss->res->csid_num; i++) {
ret = msm_csid_subdev_init(camss, &camss->csid[i],
&res->csid_res[i], i);
@@ -2130,10 +2296,8 @@ static int camss_configure_pd(struct camss *camss)
if (camss->res->pd_name) {
camss->genpd = dev_pm_domain_attach_by_name(camss->dev,
camss->res->pd_name);
- if (IS_ERR(camss->genpd)) {
- ret = PTR_ERR(camss->genpd);
- goto fail_pm;
- }
+ if (IS_ERR(camss->genpd))
+ return PTR_ERR(camss->genpd);
}
if (!camss->genpd) {
@@ -2143,14 +2307,13 @@ static int camss_configure_pd(struct camss *camss)
*/
camss->genpd = dev_pm_domain_attach_by_id(camss->dev,
camss->genpd_num - 1);
+ if (IS_ERR(camss->genpd))
+ return PTR_ERR(camss->genpd);
}
- if (IS_ERR_OR_NULL(camss->genpd)) {
- if (!camss->genpd)
- ret = -ENODEV;
- else
- ret = PTR_ERR(camss->genpd);
- goto fail_pm;
- }
+
+ if (!camss->genpd)
+ return -ENODEV;
+
camss->genpd_link = device_link_add(camss->dev, camss->genpd,
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE);
@@ -2239,6 +2402,7 @@ static int camss_probe(struct platform_device *pdev)
return -ENOMEM;
if (camss->res->version == CAMSS_8x16 ||
+ camss->res->version == CAMSS_8x53 ||
camss->res->version == CAMSS_8x96) {
camss->ispif = devm_kcalloc(dev, 1, sizeof(*camss->ispif), GFP_KERNEL);
if (!camss->ispif)
@@ -2380,6 +2544,20 @@ static const struct camss_resources msm8916_resources = {
.link_entities = camss_link_entities
};
+static const struct camss_resources msm8953_resources = {
+ .version = CAMSS_8x53,
+ .icc_res = icc_res_8x53,
+ .icc_path_num = ARRAY_SIZE(icc_res_8x53),
+ .csiphy_res = csiphy_res_8x96,
+ .csid_res = csid_res_8x53,
+ .ispif_res = &ispif_res_8x53,
+ .vfe_res = vfe_res_8x53,
+ .csiphy_num = ARRAY_SIZE(csiphy_res_8x96),
+ .csid_num = ARRAY_SIZE(csid_res_8x53),
+ .vfe_num = ARRAY_SIZE(vfe_res_8x53),
+ .link_entities = camss_link_entities
+};
+
static const struct camss_resources msm8996_resources = {
.version = CAMSS_8x96,
.csiphy_res = csiphy_res_8x96,
@@ -2446,6 +2624,7 @@ static const struct camss_resources sc8280xp_resources = {
static const struct of_device_id camss_dt_match[] = {
{ .compatible = "qcom,msm8916-camss", .data = &msm8916_resources },
+ { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources },
{ .compatible = "qcom,msm8996-camss", .data = &msm8996_resources },
{ .compatible = "qcom,sdm660-camss", .data = &sdm660_resources },
{ .compatible = "qcom,sdm845-camss", .data = &sdm845_resources },
@@ -2497,7 +2676,7 @@ static const struct dev_pm_ops camss_pm_ops = {
static struct platform_driver qcom_camss_driver = {
.probe = camss_probe,
- .remove_new = camss_remove,
+ .remove = camss_remove,
.driver = {
.name = "qcom-camss",
.of_match_table = camss_dt_match,
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 73c47c07fc30..9da7f48f5dd7 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -66,6 +66,10 @@ struct resources_icc {
struct icc_bw_tbl icc_bw_tbl;
};
+struct resources_wrapper {
+ char *reg;
+};
+
enum pm_domain {
PM_DOMAIN_VFE0 = 0,
PM_DOMAIN_VFE1 = 1,
@@ -74,6 +78,7 @@ enum pm_domain {
enum camss_version {
CAMSS_8x16,
+ CAMSS_8x53,
CAMSS_8x96,
CAMSS_660,
CAMSS_845,
@@ -93,6 +98,7 @@ struct camss_resources {
const struct camss_subdev_resources *csid_res;
const struct camss_subdev_resources *ispif_res;
const struct camss_subdev_resources *vfe_res;
+ const struct resources_wrapper *csid_wrapper_res;
const struct resources_icc *icc_res;
const unsigned int icc_path_num;
const unsigned int csiphy_num;
@@ -110,6 +116,7 @@ struct camss {
struct csid_device *csid;
struct ispif_device *ispif;
struct vfe_device *vfe;
+ void __iomem *csid_wrapper_base;
atomic_t ref_count;
int genpd_num;
struct device *genpd;
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 84e95a46dfc9..2d27c5167246 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -19,6 +19,7 @@
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <media/videobuf2-v4l2.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-ioctl.h>
@@ -412,8 +413,8 @@ err_of_depopulate:
of_platform_depopulate(dev);
err_runtime_disable:
pm_runtime_put_noidle(dev);
- pm_runtime_set_suspended(dev);
pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
hfi_destroy(core);
err_core_deinit:
hfi_core_deinit(core, false);
@@ -502,6 +503,30 @@ err_cpucfg_path:
return ret;
}
+void venus_close_common(struct venus_inst *inst)
+{
+ /*
+ * First, remove the inst from the ->instances list, so that
+ * to_instance() will return NULL.
+ */
+ hfi_session_destroy(inst);
+ /*
+ * Second, make sure we don't have IRQ/IRQ-thread currently running
+ * or pending execution, which would race with the inst destruction.
+ */
+ synchronize_irq(inst->core->irq);
+
+ v4l2_m2m_ctx_release(inst->m2m_ctx);
+ v4l2_m2m_release(inst->m2m_dev);
+ v4l2_fh_del(&inst->fh);
+ v4l2_fh_exit(&inst->fh);
+ v4l2_ctrl_handler_free(&inst->ctrl_handler);
+
+ mutex_destroy(&inst->lock);
+ mutex_destroy(&inst->ctx_q_lock);
+}
+EXPORT_SYMBOL_GPL(venus_close_common);
+
static __maybe_unused int venus_runtime_resume(struct device *dev)
{
struct venus_core *core = dev_get_drvdata(dev);
@@ -752,7 +777,7 @@ static const struct venus_resources sdm845_res_v2 = {
.vcodec_clks_num = 2,
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" },
.vcodec_pmdomains_num = 3,
- .opp_pmdomain = (const char *[]) { "cx", NULL },
+ .opp_pmdomain = (const char *[]) { "cx" },
.vcodec_num = 2,
.max_load = 3110400, /* 4096x2160@90 */
.hfi_version = HFI_VERSION_4XX,
@@ -801,7 +826,7 @@ static const struct venus_resources sc7180_res = {
.vcodec_clks_num = 2,
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
- .opp_pmdomain = (const char *[]) { "cx", NULL },
+ .opp_pmdomain = (const char *[]) { "cx" },
.vcodec_num = 1,
.hfi_version = HFI_VERSION_4XX,
.vpu_version = VPU_VERSION_AR50,
@@ -858,7 +883,7 @@ static const struct venus_resources sm8250_res = {
.vcodec_clks_num = 1,
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
- .opp_pmdomain = (const char *[]) { "mx", NULL },
+ .opp_pmdomain = (const char *[]) { "mx" },
.vcodec_num = 1,
.max_load = 7833600,
.hfi_version = HFI_VERSION_6XX,
@@ -917,7 +942,7 @@ static const struct venus_resources sc7280_res = {
.vcodec_clks_num = 2,
.vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" },
.vcodec_pmdomains_num = 2,
- .opp_pmdomain = (const char *[]) { "cx", NULL },
+ .opp_pmdomain = (const char *[]) { "cx" },
.vcodec_num = 1,
.hfi_version = HFI_VERSION_6XX,
.vpu_version = VPU_VERSION_IRIS2_1,
@@ -949,7 +974,7 @@ MODULE_DEVICE_TABLE(of, venus_dt_match);
static struct platform_driver qcom_venus_driver = {
.probe = venus_probe,
- .remove_new = venus_remove,
+ .remove = venus_remove,
.driver = {
.name = "qcom-venus",
.of_match_table = venus_dt_match,
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 55202b89e1b9..44f1c3bc4186 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -26,6 +26,7 @@
#define VIDC_CLKS_NUM_MAX 4
#define VIDC_VCODEC_CLKS_NUM_MAX 2
#define VIDC_RESETS_NUM_MAX 2
+#define VIDC_MAX_HIER_CODING_LAYER 6
extern int venus_fw_debug;
@@ -132,9 +133,7 @@ struct venus_format {
* @vcodec1_clks: an array of vcodec1 struct clk pointers
* @video_path: an interconnect handle to video to/from memory path
* @cpucfg_path: an interconnect handle to cpu configuration path
- * @has_opp_table: does OPP table exist
* @pmdomains: a pointer to a list of pmdomains
- * @opp_dl_venus: an device-link for device OPP
* @opp_pmdomain: an OPP power-domain
* @resets: an array of reset signals
* @vdev_dec: a reference to video device structure for decoder instances
@@ -186,10 +185,8 @@ struct venus_core {
struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX];
struct icc_path *video_path;
struct icc_path *cpucfg_path;
- bool has_opp_table;
struct dev_pm_domain_list *pmdomains;
- struct device_link *opp_dl_venus;
- struct device *opp_pmdomain;
+ struct dev_pm_domain_list *opp_pmdomain;
struct reset_control *resets[VIDC_RESETS_NUM_MAX];
struct video_device *vdev_dec;
struct video_device *vdev_enc;
@@ -255,6 +252,7 @@ struct venc_controls {
u32 rc_enable;
u32 const_quality;
u32 frame_skip_mode;
+ u32 layer_bitrate;
u32 h264_i_period;
u32 h264_entropy_mode;
@@ -273,6 +271,8 @@ struct venc_controls {
s32 h264_loop_filter_alpha;
s32 h264_loop_filter_beta;
u32 h264_8x8_transform;
+ u32 h264_hier_layers;
+ u32 h264_hier_layer_bitrate[VIDC_MAX_HIER_CODING_LAYER];
u32 hevc_i_qp;
u32 hevc_p_qp;
@@ -564,4 +564,6 @@ is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev)
(core)->venus_ver.minor == vminor &&
(core)->venus_ver.rev <= vrev);
}
+
+void venus_close_common(struct venus_inst *inst);
#endif
diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
index ea8a2bd9419e..33a5a659c0ad 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -864,7 +864,6 @@ static int venc_power_v4(struct device *dev, int on)
static int vcodec_domains_get(struct venus_core *core)
{
int ret;
- struct device **opp_virt_dev;
struct device *dev = core->dev;
const struct venus_resources *res = core->res;
struct dev_pm_domain_attach_data vcodec_data = {
@@ -872,6 +871,11 @@ static int vcodec_domains_get(struct venus_core *core)
.num_pd_names = res->vcodec_pmdomains_num,
.pd_flags = PD_FLAG_NO_DEV_LINK,
};
+ struct dev_pm_domain_attach_data opp_pd_data = {
+ .pd_names = res->opp_pmdomain,
+ .num_pd_names = 1,
+ .pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP,
+ };
if (!res->vcodec_pmdomains_num)
goto skip_pmdomains;
@@ -881,37 +885,15 @@ static int vcodec_domains_get(struct venus_core *core)
return ret;
skip_pmdomains:
- if (!core->res->opp_pmdomain)
+ if (!res->opp_pmdomain)
return 0;
/* Attach the power domain for setting performance state */
- ret = devm_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev);
- if (ret)
- goto opp_attach_err;
-
- core->opp_pmdomain = *opp_virt_dev;
- core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
- DL_FLAG_RPM_ACTIVE |
- DL_FLAG_PM_RUNTIME |
- DL_FLAG_STATELESS);
- if (!core->opp_dl_venus) {
- ret = -ENODEV;
- goto opp_attach_err;
- }
+ ret = devm_pm_domain_attach_list(dev, &opp_pd_data, &core->opp_pmdomain);
+ if (ret < 0)
+ return ret;
return 0;
-
-opp_attach_err:
- return ret;
-}
-
-static void vcodec_domains_put(struct venus_core *core)
-{
- if (!core->has_opp_table)
- return;
-
- if (core->opp_dl_venus)
- device_link_del(core->opp_dl_venus);
}
static int core_resets_reset(struct venus_core *core)
@@ -1000,9 +982,7 @@ static int core_get_v4(struct venus_core *core)
if (core->res->opp_pmdomain) {
ret = devm_pm_opp_of_add_table(dev);
- if (!ret) {
- core->has_opp_table = true;
- } else if (ret != -ENODEV) {
+ if (ret && ret != -ENODEV) {
dev_err(dev, "invalid OPP table in device tree\n");
return ret;
}
@@ -1013,10 +993,6 @@ static int core_get_v4(struct venus_core *core)
static void core_put_v4(struct venus_core *core)
{
- if (legacy_binding)
- return;
-
- vcodec_domains_put(core);
}
static int core_power_v4(struct venus_core *core, int on)
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index d12089370d91..98c22b9f9372 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -1735,7 +1735,7 @@ err_m2m_release:
err_session_destroy:
hfi_session_destroy(inst);
err_ctrl_deinit:
- vdec_ctrl_deinit(inst);
+ v4l2_ctrl_handler_free(&inst->ctrl_handler);
err_free:
kfree(inst);
return ret;
@@ -1746,18 +1746,9 @@ static int vdec_close(struct file *file)
struct venus_inst *inst = to_inst(file);
vdec_pm_get(inst);
-
cancel_work_sync(&inst->delayed_process_work);
- v4l2_m2m_ctx_release(inst->m2m_ctx);
- v4l2_m2m_release(inst->m2m_dev);
- vdec_ctrl_deinit(inst);
+ venus_close_common(inst);
ida_destroy(&inst->dpb_ids);
- hfi_session_destroy(inst);
- mutex_destroy(&inst->lock);
- mutex_destroy(&inst->ctx_q_lock);
- v4l2_fh_del(&inst->fh);
- v4l2_fh_exit(&inst->fh);
-
vdec_pm_put(inst, false);
kfree(inst);
@@ -1875,7 +1866,7 @@ MODULE_DEVICE_TABLE(of, vdec_dt_match);
static struct platform_driver qcom_venus_dec_driver = {
.probe = vdec_probe,
- .remove_new = vdec_remove,
+ .remove = vdec_remove,
.driver = {
.name = "qcom-venus-decoder",
.of_match_table = vdec_dt_match,
diff --git a/drivers/media/platform/qcom/venus/vdec.h b/drivers/media/platform/qcom/venus/vdec.h
index 6b262d0bf561..0cf981108ff0 100644
--- a/drivers/media/platform/qcom/venus/vdec.h
+++ b/drivers/media/platform/qcom/venus/vdec.h
@@ -9,6 +9,5 @@
struct venus_inst;
int vdec_ctrl_init(struct venus_inst *inst);
-void vdec_ctrl_deinit(struct venus_inst *inst);
#endif
diff --git a/drivers/media/platform/qcom/venus/vdec_ctrls.c b/drivers/media/platform/qcom/venus/vdec_ctrls.c
index 7e0f29bf7fae..36ed955b0419 100644
--- a/drivers/media/platform/qcom/venus/vdec_ctrls.c
+++ b/drivers/media/platform/qcom/venus/vdec_ctrls.c
@@ -187,8 +187,3 @@ int vdec_ctrl_init(struct venus_inst *inst)
return 0;
}
-
-void vdec_ctrl_deinit(struct venus_inst *inst)
-{
- v4l2_ctrl_handler_free(&inst->ctrl_handler);
-}
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 3ec2fb8d9fab..c1c543535aaf 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -734,6 +734,29 @@ static int venc_set_properties(struct venus_inst *inst)
if (ret)
return ret;
+ if (ctr->layer_bitrate) {
+ unsigned int i;
+
+ ptype = HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER;
+ ret = hfi_session_set_property(inst, ptype, &ctr->h264_hier_layers);
+ if (ret)
+ return ret;
+
+ ptype = HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER;
+ ret = hfi_session_set_property(inst, ptype, &ctr->layer_bitrate);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ctr->h264_hier_layers; ++i) {
+ ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
+ brate.bitrate = ctr->h264_hier_layer_bitrate[i];
+ brate.layer_id = i;
+
+ ret = hfi_session_set_property(inst, ptype, &brate);
+ if (ret)
+ return ret;
+ }
+ }
}
if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
@@ -823,18 +846,33 @@ static int venc_set_properties(struct venus_inst *inst)
return ret;
}
- if (!ctr->bitrate)
- bitrate = 64000;
- else
- bitrate = ctr->bitrate;
+ if (!ctr->layer_bitrate) {
+ if (!ctr->bitrate)
+ bitrate = 64000;
+ else
+ bitrate = ctr->bitrate;
- ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
- brate.bitrate = bitrate;
- brate.layer_id = 0;
+ ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
+ brate.bitrate = bitrate;
+ brate.layer_id = 0;
- ret = hfi_session_set_property(inst, ptype, &brate);
- if (ret)
- return ret;
+ ret = hfi_session_set_property(inst, ptype, &brate);
+ if (ret)
+ return ret;
+
+ if (!ctr->bitrate_peak)
+ bitrate *= 2;
+ else
+ bitrate = ctr->bitrate_peak;
+
+ ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
+ brate.bitrate = bitrate;
+ brate.layer_id = 0;
+
+ ret = hfi_session_set_property(inst, ptype, &brate);
+ if (ret)
+ return ret;
+ }
if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
@@ -849,19 +887,6 @@ static int venc_set_properties(struct venus_inst *inst)
return ret;
}
- if (!ctr->bitrate_peak)
- bitrate *= 2;
- else
- bitrate = ctr->bitrate_peak;
-
- ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
- brate.bitrate = bitrate;
- brate.layer_id = 0;
-
- ret = hfi_session_set_property(inst, ptype, &brate);
- if (ret)
- return ret;
-
ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP;
if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
quant.qp_i = ctr->hevc_i_qp;
@@ -1503,7 +1528,7 @@ err_m2m_release:
err_session_destroy:
hfi_session_destroy(inst);
err_ctrl_deinit:
- venc_ctrl_deinit(inst);
+ v4l2_ctrl_handler_free(&inst->ctrl_handler);
err_free:
kfree(inst);
return ret;
@@ -1514,18 +1539,8 @@ static int venc_close(struct file *file)
struct venus_inst *inst = to_inst(file);
venc_pm_get(inst);
-
- v4l2_m2m_ctx_release(inst->m2m_ctx);
- v4l2_m2m_release(inst->m2m_dev);
- venc_ctrl_deinit(inst);
- hfi_session_destroy(inst);
- mutex_destroy(&inst->lock);
- mutex_destroy(&inst->ctx_q_lock);
- v4l2_fh_del(&inst->fh);
- v4l2_fh_exit(&inst->fh);
-
+ venus_close_common(inst);
inst->enc_state = VENUS_ENC_STATE_DEINIT;
-
venc_pm_put(inst, false);
kfree(inst);
@@ -1643,7 +1658,7 @@ MODULE_DEVICE_TABLE(of, venc_dt_match);
static struct platform_driver qcom_venus_enc_driver = {
.probe = venc_probe,
- .remove_new = venc_remove,
+ .remove = venc_remove,
.driver = {
.name = "qcom-venus-encoder",
.of_match_table = venc_dt_match,
diff --git a/drivers/media/platform/qcom/venus/venc.h b/drivers/media/platform/qcom/venus/venc.h
index 4ea37fdcd9b8..719d0f73b14b 100644
--- a/drivers/media/platform/qcom/venus/venc.h
+++ b/drivers/media/platform/qcom/venus/venc.h
@@ -9,6 +9,5 @@
struct venus_inst;
int venc_ctrl_init(struct venus_inst *inst);
-void venc_ctrl_deinit(struct venus_inst *inst);
#endif
diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c
index d9d2a293f3ef..51801a962ed2 100644
--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
+++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
@@ -67,12 +67,28 @@ static int venc_calc_bpframes(u32 gop_size, u32 conseq_b, u32 *bf, u32 *pf)
return 0;
}
+static int dynamic_bitrate_update(struct venus_inst *inst, u32 bitrate,
+ u32 layer_id)
+{
+ int ret = 0;
+
+ mutex_lock(&inst->lock);
+ if (inst->streamon_out && inst->streamon_cap) {
+ u32 ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
+ struct hfi_bitrate brate = { .bitrate = bitrate, .layer_id = layer_id };
+
+ ret = hfi_session_set_property(inst, ptype, &brate);
+ }
+ mutex_unlock(&inst->lock);
+
+ return ret;
+}
+
static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct venus_inst *inst = ctrl_to_inst(ctrl);
struct venc_controls *ctr = &inst->controls.enc;
struct hfi_enable en = { .enable = 1 };
- struct hfi_bitrate brate;
struct hfi_ltr_use ltr_use;
struct hfi_ltr_mark ltr_mark;
u32 bframes;
@@ -85,19 +101,9 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
break;
case V4L2_CID_MPEG_VIDEO_BITRATE:
ctr->bitrate = ctrl->val;
- mutex_lock(&inst->lock);
- if (inst->streamon_out && inst->streamon_cap) {
- ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
- brate.bitrate = ctr->bitrate;
- brate.layer_id = 0;
-
- ret = hfi_session_set_property(inst, ptype, &brate);
- if (ret) {
- mutex_unlock(&inst->lock);
- return ret;
- }
- }
- mutex_unlock(&inst->lock);
+ ret = dynamic_bitrate_update(inst, ctr->bitrate, 0);
+ if (ret)
+ return ret;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
ctr->bitrate_peak = ctrl->val;
@@ -340,6 +346,55 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
ctr->h264_8x8_transform = ctrl->val;
break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
+ if (ctrl->val != V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P)
+ return -EINVAL;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:
+ ctr->layer_bitrate = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:
+ if (ctrl->val > VIDC_MAX_HIER_CODING_LAYER)
+ return -EINVAL;
+ ctr->h264_hier_layers = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR:
+ ctr->h264_hier_layer_bitrate[0] = ctrl->val;
+ ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[0], 0);
+ if (ret)
+ return ret;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR:
+ ctr->h264_hier_layer_bitrate[1] = ctrl->val;
+ ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[1], 1);
+ if (ret)
+ return ret;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR:
+ ctr->h264_hier_layer_bitrate[2] = ctrl->val;
+ ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[2], 2);
+ if (ret)
+ return ret;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR:
+ ctr->h264_hier_layer_bitrate[3] = ctrl->val;
+ ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[3], 3);
+ if (ret)
+ return ret;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR:
+ ctr->h264_hier_layer_bitrate[4] = ctrl->val;
+ ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[4], 4);
+ if (ret)
+ return ret;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR:
+ ctr->h264_hier_layer_bitrate[5] = ctrl->val;
+ ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[5], 5);
+ if (ret)
+ return ret;
+ break;
+
default:
return -EINVAL;
}
@@ -622,6 +677,49 @@ int venc_ctrl_init(struct venus_inst *inst)
V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD, 0,
((4096 * 2304) >> 8), 1, 0);
+ if (IS_V4(inst->core) || IS_V6(inst->core)) {
+ v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE,
+ V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+ 1, V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING, 0, 1, 1, 0);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER, 0,
+ VIDC_MAX_HIER_CODING_LAYER, 1, 0);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR,
+ BITRATE_MIN, BITRATE_MAX, BITRATE_STEP, BITRATE_DEFAULT);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR,
+ BITRATE_MIN, BITRATE_MAX,
+ BITRATE_STEP, BITRATE_DEFAULT);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR,
+ BITRATE_MIN, BITRATE_MAX,
+ BITRATE_STEP, BITRATE_DEFAULT);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR,
+ BITRATE_MIN, BITRATE_MAX,
+ BITRATE_STEP, BITRATE_DEFAULT);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR,
+ BITRATE_MIN, BITRATE_MAX,
+ BITRATE_STEP, BITRATE_DEFAULT);
+
+ v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR,
+ BITRATE_MIN, BITRATE_MAX,
+ BITRATE_STEP, BITRATE_DEFAULT);
+ }
+
ret = inst->ctrl_handler.error;
if (ret)
goto err;
@@ -635,8 +733,3 @@ err:
v4l2_ctrl_handler_free(&inst->ctrl_handler);
return ret;
}
-
-void venc_ctrl_deinit(struct venus_inst *inst)
-{
- v4l2_ctrl_handler_free(&inst->ctrl_handler);
-}
diff --git a/drivers/media/platform/raspberrypi/Kconfig b/drivers/media/platform/raspberrypi/Kconfig
index e928f979019e..bd5101ffefb5 100644
--- a/drivers/media/platform/raspberrypi/Kconfig
+++ b/drivers/media/platform/raspberrypi/Kconfig
@@ -3,3 +3,4 @@
comment "Raspberry Pi media platform drivers"
source "drivers/media/platform/raspberrypi/pisp_be/Kconfig"
+source "drivers/media/platform/raspberrypi/rp1-cfe/Kconfig"
diff --git a/drivers/media/platform/raspberrypi/Makefile b/drivers/media/platform/raspberrypi/Makefile
index c0d1a2dab486..af7fde84eefe 100644
--- a/drivers/media/platform/raspberrypi/Makefile
+++ b/drivers/media/platform/raspberrypi/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += pisp_be/
+obj-y += rp1-cfe/
diff --git a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c
index 65ff2382cffe..7596ae1f7de6 100644
--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c
+++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c
@@ -1781,7 +1781,7 @@ MODULE_DEVICE_TABLE(of, pispbe_of_match);
static struct platform_driver pispbe_pdrv = {
.probe = pispbe_probe,
- .remove_new = pispbe_remove,
+ .remove = pispbe_remove,
.driver = {
.name = PISPBE_NAME,
.of_match_table = pispbe_of_match,
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/Kconfig b/drivers/media/platform/raspberrypi/rp1-cfe/Kconfig
new file mode 100644
index 000000000000..327b61f1134b
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/Kconfig
@@ -0,0 +1,15 @@
+# RP1 V4L2 camera support
+
+config VIDEO_RP1_CFE
+ tristate "Raspberry Pi RP1 Camera Front End (CFE) video capture driver"
+ depends on VIDEO_DEV
+ depends on PM
+ select VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ select VIDEOBUF2_DMA_CONTIG
+ select V4L2_FWNODE
+ help
+ Say Y here to enable support for the Raspberry Pi RP1 Camera Front End.
+
+ To compile this driver as a module, choose M here. The module will be
+ called rp1-cfe.
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/Makefile b/drivers/media/platform/raspberrypi/rp1-cfe/Makefile
new file mode 100644
index 000000000000..3f0d0fc8570e
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for RP1 Camera Front End driver
+#
+rp1-cfe-objs := cfe.o csi2.o pisp-fe.o dphy.o
+obj-$(CONFIG_VIDEO_RP1_CFE) += rp1-cfe.o
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h b/drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h
new file mode 100644
index 000000000000..7aecf7f83733
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h
@@ -0,0 +1,332 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RP1 Camera Front End formats definition
+ *
+ * Copyright (C) 2021-2024 - Raspberry Pi Ltd.
+ */
+#ifndef _CFE_FMTS_H_
+#define _CFE_FMTS_H_
+
+#include "cfe.h"
+#include <media/mipi-csi2.h>
+
+static const struct cfe_fmt formats[] = {
+ /* YUV Formats */
+ {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .code = MEDIA_BUS_FMT_YUYV8_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_YUV422_8B,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_YUV422_8B,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .code = MEDIA_BUS_FMT_YVYU8_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_YUV422_8B,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_VYUY,
+ .code = MEDIA_BUS_FMT_VYUY8_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_YUV422_8B,
+ },
+ {
+ /* RGB Formats */
+ .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+ .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RGB565,
+ },
+ { .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+ .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RGB565,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+ .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RGB555,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+ .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RGB555,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
+ .code = MEDIA_BUS_FMT_RGB888_1X24,
+ .depth = 24,
+ .csi_dt = MIPI_CSI2_DT_RGB888,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
+ .code = MEDIA_BUS_FMT_BGR888_1X24,
+ .depth = 24,
+ .csi_dt = MIPI_CSI2_DT_RGB888,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
+ .code = MEDIA_BUS_FMT_ARGB8888_1X32,
+ .depth = 32,
+ .csi_dt = 0x0,
+ },
+
+ /* Bayer Formats */
+ {
+ .fourcc = V4L2_PIX_FMT_SBGGR8,
+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .depth = 8,
+ .csi_dt = MIPI_CSI2_DT_RAW8,
+ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG8,
+ .code = MEDIA_BUS_FMT_SGBRG8_1X8,
+ .depth = 8,
+ .csi_dt = MIPI_CSI2_DT_RAW8,
+ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG8,
+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .depth = 8,
+ .csi_dt = MIPI_CSI2_DT_RAW8,
+ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB8,
+ .code = MEDIA_BUS_FMT_SRGGB8_1X8,
+ .depth = 8,
+ .csi_dt = MIPI_CSI2_DT_RAW8,
+ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SBGGR10P,
+ .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .depth = 10,
+ .csi_dt = MIPI_CSI2_DT_RAW10,
+ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG10P,
+ .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+ .depth = 10,
+ .csi_dt = MIPI_CSI2_DT_RAW10,
+ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG10P,
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .depth = 10,
+ .csi_dt = MIPI_CSI2_DT_RAW10,
+ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB10P,
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .depth = 10,
+ .csi_dt = MIPI_CSI2_DT_RAW10,
+ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SBGGR12P,
+ .code = MEDIA_BUS_FMT_SBGGR12_1X12,
+ .depth = 12,
+ .csi_dt = MIPI_CSI2_DT_RAW12,
+ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG12P,
+ .code = MEDIA_BUS_FMT_SGBRG12_1X12,
+ .depth = 12,
+ .csi_dt = MIPI_CSI2_DT_RAW12,
+ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG12P,
+ .code = MEDIA_BUS_FMT_SGRBG12_1X12,
+ .depth = 12,
+ .csi_dt = MIPI_CSI2_DT_RAW12,
+ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB12P,
+ .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+ .depth = 12,
+ .csi_dt = MIPI_CSI2_DT_RAW12,
+ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SBGGR14P,
+ .code = MEDIA_BUS_FMT_SBGGR14_1X14,
+ .depth = 14,
+ .csi_dt = MIPI_CSI2_DT_RAW14,
+ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG14P,
+ .code = MEDIA_BUS_FMT_SGBRG14_1X14,
+ .depth = 14,
+ .csi_dt = MIPI_CSI2_DT_RAW14,
+ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG14P,
+ .code = MEDIA_BUS_FMT_SGRBG14_1X14,
+ .depth = 14,
+ .csi_dt = MIPI_CSI2_DT_RAW14,
+ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB14P,
+ .code = MEDIA_BUS_FMT_SRGGB14_1X14,
+ .depth = 14,
+ .csi_dt = MIPI_CSI2_DT_RAW14,
+ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SBGGR16,
+ .code = MEDIA_BUS_FMT_SBGGR16_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RAW16,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG16,
+ .code = MEDIA_BUS_FMT_SGBRG16_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RAW16,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG16,
+ .code = MEDIA_BUS_FMT_SGRBG16_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RAW16,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB16,
+ .code = MEDIA_BUS_FMT_SRGGB16_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RAW16,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
+ },
+ /* PiSP Compressed Mode 1 */
+ {
+ .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB,
+ .code = MEDIA_BUS_FMT_SRGGB16_1X16,
+ .depth = 8,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR,
+ .code = MEDIA_BUS_FMT_SBGGR16_1X16,
+ .depth = 8,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG,
+ .code = MEDIA_BUS_FMT_SGBRG16_1X16,
+ .depth = 8,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG,
+ .code = MEDIA_BUS_FMT_SGRBG16_1X16,
+ .depth = 8,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ },
+ /* Greyscale format */
+ {
+ .fourcc = V4L2_PIX_FMT_GREY,
+ .code = MEDIA_BUS_FMT_Y8_1X8,
+ .depth = 8,
+ .csi_dt = MIPI_CSI2_DT_RAW8,
+ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_Y10P,
+ .code = MEDIA_BUS_FMT_Y10_1X10,
+ .depth = 10,
+ .csi_dt = MIPI_CSI2_DT_RAW10,
+ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_Y12P,
+ .code = MEDIA_BUS_FMT_Y12_1X12,
+ .depth = 12,
+ .csi_dt = MIPI_CSI2_DT_RAW12,
+ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_Y14P,
+ .code = MEDIA_BUS_FMT_Y14_1X14,
+ .depth = 14,
+ .csi_dt = MIPI_CSI2_DT_RAW14,
+ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_Y16,
+ .code = MEDIA_BUS_FMT_Y16_1X16,
+ .depth = 16,
+ .csi_dt = MIPI_CSI2_DT_RAW16,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_PISP_COMP1_MONO,
+ .code = MEDIA_BUS_FMT_Y16_1X16,
+ .depth = 8,
+ .flags = CFE_FORMAT_FLAG_FE_OUT,
+ },
+
+ /* Embedded data formats */
+ {
+ .fourcc = V4L2_META_FMT_GENERIC_8,
+ .code = MEDIA_BUS_FMT_META_8,
+ .depth = 8,
+ .csi_dt = MIPI_CSI2_DT_EMBEDDED_8B,
+ .flags = CFE_FORMAT_FLAG_META_CAP,
+ },
+ {
+ .fourcc = V4L2_META_FMT_GENERIC_CSI2_10,
+ .code = MEDIA_BUS_FMT_META_10,
+ .depth = 10,
+ .csi_dt = MIPI_CSI2_DT_EMBEDDED_8B,
+ .flags = CFE_FORMAT_FLAG_META_CAP,
+ },
+ {
+ .fourcc = V4L2_META_FMT_GENERIC_CSI2_12,
+ .code = MEDIA_BUS_FMT_META_12,
+ .depth = 12,
+ .csi_dt = MIPI_CSI2_DT_EMBEDDED_8B,
+ .flags = CFE_FORMAT_FLAG_META_CAP,
+ },
+
+ /* Frontend formats */
+ {
+ .fourcc = V4L2_META_FMT_RPI_FE_CFG,
+ .code = MEDIA_BUS_FMT_FIXED,
+ .flags = CFE_FORMAT_FLAG_META_OUT,
+ },
+ {
+ .fourcc = V4L2_META_FMT_RPI_FE_STATS,
+ .code = MEDIA_BUS_FMT_FIXED,
+ .flags = CFE_FORMAT_FLAG_META_CAP,
+ },
+};
+
+#endif /* _CFE_FMTS_H_ */
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace.h b/drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace.h
new file mode 100644
index 000000000000..1a36259f51b7
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace.h
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Raspberry Pi Ltd.
+ * Copyright (c) 2024 Ideas on Board Oy
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cfe
+
+#if !defined(_CFE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _CFE_TRACE_H
+
+#include <linux/tracepoint.h>
+#include <media/videobuf2-v4l2.h>
+
+TRACE_EVENT(cfe_return_buffer,
+ TP_PROTO(u32 node_id, u32 buf_idx, u32 queue_id),
+ TP_ARGS(node_id, buf_idx, queue_id),
+ TP_STRUCT__entry(
+ __field(u32, node_id)
+ __field(u32, buf_idx)
+ __field(u32, queue_id)
+ ),
+ TP_fast_assign(
+ __entry->node_id = node_id;
+ __entry->buf_idx = buf_idx;
+ __entry->queue_id = queue_id;
+ ),
+ TP_printk("node=%u buf=%u, queue=%u", __entry->node_id,
+ __entry->buf_idx, __entry->queue_id)
+);
+
+DECLARE_EVENT_CLASS(cfe_buffer_template,
+ TP_PROTO(u32 node_id, struct vb2_buffer *buf),
+ TP_ARGS(node_id, buf),
+ TP_STRUCT__entry(
+ __field(u32, node_id)
+ __field(u32, buf_idx)
+ ),
+ TP_fast_assign(
+ __entry->node_id = node_id;
+ __entry->buf_idx = buf->index;
+ ),
+ TP_printk("node=%u buf=%u", __entry->node_id, __entry->buf_idx)
+);
+
+DEFINE_EVENT(cfe_buffer_template, cfe_buffer_prepare,
+ TP_PROTO(u32 node_id, struct vb2_buffer *buf),
+ TP_ARGS(node_id, buf));
+
+TRACE_EVENT(cfe_buffer_queue,
+ TP_PROTO(u32 node_id, struct vb2_buffer *buf, bool schedule_now),
+ TP_ARGS(node_id, buf, schedule_now),
+ TP_STRUCT__entry(
+ __field(u32, node_id)
+ __field(u32, buf_idx)
+ __field(bool, schedule_now)
+ ),
+ TP_fast_assign(
+ __entry->node_id = node_id;
+ __entry->buf_idx = buf->index;
+ __entry->schedule_now = schedule_now;
+ ),
+ TP_printk("node=%u buf=%u%s", __entry->node_id, __entry->buf_idx,
+ __entry->schedule_now ? " schedule immediately" : "")
+);
+
+DEFINE_EVENT(cfe_buffer_template, cfe_csi2_schedule,
+ TP_PROTO(u32 node_id, struct vb2_buffer *buf),
+ TP_ARGS(node_id, buf));
+
+DEFINE_EVENT(cfe_buffer_template, cfe_fe_schedule,
+ TP_PROTO(u32 node_id, struct vb2_buffer *buf),
+ TP_ARGS(node_id, buf));
+
+TRACE_EVENT(cfe_buffer_complete,
+ TP_PROTO(u32 node_id, struct vb2_v4l2_buffer *buf),
+ TP_ARGS(node_id, buf),
+ TP_STRUCT__entry(
+ __field(u32, node_id)
+ __field(u32, buf_idx)
+ __field(u32, seq)
+ __field(u64, ts)
+ ),
+ TP_fast_assign(
+ __entry->node_id = node_id;
+ __entry->buf_idx = buf->vb2_buf.index;
+ __entry->seq = buf->sequence;
+ __entry->ts = buf->vb2_buf.timestamp;
+ ),
+ TP_printk("node=%u buf=%u seq=%u ts=%llu", __entry->node_id,
+ __entry->buf_idx, __entry->seq, __entry->ts)
+);
+
+TRACE_EVENT(cfe_frame_start,
+ TP_PROTO(u32 node_id, u32 fs_count),
+ TP_ARGS(node_id, fs_count),
+ TP_STRUCT__entry(
+ __field(u32, node_id)
+ __field(u32, fs_count)
+ ),
+ TP_fast_assign(
+ __entry->node_id = node_id;
+ __entry->fs_count = fs_count;
+ ),
+ TP_printk("node=%u fs_count=%u", __entry->node_id, __entry->fs_count)
+);
+
+TRACE_EVENT(cfe_frame_end,
+ TP_PROTO(u32 node_id, u32 fs_count),
+ TP_ARGS(node_id, fs_count),
+ TP_STRUCT__entry(
+ __field(u32, node_id)
+ __field(u32, fs_count)
+ ),
+ TP_fast_assign(
+ __entry->node_id = node_id;
+ __entry->fs_count = fs_count;
+ ),
+ TP_printk("node=%u fs_count=%u", __entry->node_id, __entry->fs_count)
+);
+
+TRACE_EVENT(cfe_prepare_next_job,
+ TP_PROTO(bool fe_enabled),
+ TP_ARGS(fe_enabled),
+ TP_STRUCT__entry(
+ __field(bool, fe_enabled)
+ ),
+ TP_fast_assign(
+ __entry->fe_enabled = fe_enabled;
+ ),
+ TP_printk("fe_enabled=%u", __entry->fe_enabled)
+);
+
+/* These are copied from csi2.c */
+#define CSI2_STATUS_IRQ_FS(x) (BIT(0) << (x))
+#define CSI2_STATUS_IRQ_FE(x) (BIT(4) << (x))
+#define CSI2_STATUS_IRQ_FE_ACK(x) (BIT(8) << (x))
+#define CSI2_STATUS_IRQ_LE(x) (BIT(12) << (x))
+#define CSI2_STATUS_IRQ_LE_ACK(x) (BIT(16) << (x))
+
+TRACE_EVENT(csi2_irq,
+ TP_PROTO(u32 channel, u32 status, u32 dbg),
+ TP_ARGS(channel, status, dbg),
+ TP_STRUCT__entry(
+ __field(u32, channel)
+ __field(u32, status)
+ __field(u32, dbg)
+ ),
+ TP_fast_assign(
+ __entry->channel = channel;
+ __entry->status = status;
+ __entry->dbg = dbg;
+ ),
+ TP_printk("ch=%u flags=[ %s%s%s%s%s] frame=%u line=%u\n",
+ __entry->channel,
+ (__entry->status & CSI2_STATUS_IRQ_FS(__entry->channel)) ?
+ "FS " : "",
+ (__entry->status & CSI2_STATUS_IRQ_FE(__entry->channel)) ?
+ "FE " : "",
+ (__entry->status & CSI2_STATUS_IRQ_FE_ACK(__entry->channel)) ?
+ "FE_ACK " : "",
+ (__entry->status & CSI2_STATUS_IRQ_LE(__entry->channel)) ?
+ "LE " : "",
+ (__entry->status & CSI2_STATUS_IRQ_LE_ACK(__entry->channel)) ?
+ "LE_ACK " : "",
+ __entry->dbg >> 16, __entry->dbg & 0xffff)
+);
+
+TRACE_EVENT(fe_irq,
+ TP_PROTO(u32 status, u32 output_status, u32 frame_status,
+ u32 error_status, u32 int_status),
+ TP_ARGS(status, output_status, frame_status, error_status, int_status),
+ TP_STRUCT__entry(
+ __field(u32, status)
+ __field(u32, output_status)
+ __field(u32, frame_status)
+ __field(u32, error_status)
+ __field(u32, int_status)
+ ),
+ TP_fast_assign(
+ __entry->status = status;
+ __entry->output_status = output_status;
+ __entry->frame_status = frame_status;
+ __entry->error_status = error_status;
+ __entry->int_status = int_status;
+ ),
+ TP_printk("status 0x%x out_status 0x%x frame_status 0x%x error_status 0x%x int_status 0x%x",
+ __entry->status,
+ __entry->output_status,
+ __entry->frame_status,
+ __entry->error_status,
+ __entry->int_status)
+);
+
+#endif /* _CFE_TRACE_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE ../../drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace
+#include <trace/define_trace.h>
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c b/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c
new file mode 100644
index 000000000000..12660087b12f
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c
@@ -0,0 +1,2509 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RP1 Camera Front End Driver
+ *
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ * Copyright (c) 2023-2024 Ideas on Board Oy
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/fwnode.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/lcm.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include <linux/media/raspberrypi/pisp_fe_config.h>
+#include <linux/media/raspberrypi/pisp_fe_statistics.h>
+
+#include "cfe-fmts.h"
+#include "cfe.h"
+#include "csi2.h"
+#include "pisp-fe.h"
+
+#define CREATE_TRACE_POINTS
+#include "cfe-trace.h"
+
+#define CFE_MODULE_NAME "rp1-cfe"
+#define CFE_VERSION "1.0"
+
+#define cfe_dbg(cfe, fmt, arg...) dev_dbg(&(cfe)->pdev->dev, fmt, ##arg)
+#define cfe_info(cfe, fmt, arg...) dev_info(&(cfe)->pdev->dev, fmt, ##arg)
+#define cfe_err(cfe, fmt, arg...) dev_err(&(cfe)->pdev->dev, fmt, ##arg)
+
+/* MIPICFG registers */
+#define MIPICFG_CFG 0x004
+#define MIPICFG_INTR 0x028
+#define MIPICFG_INTE 0x02c
+#define MIPICFG_INTF 0x030
+#define MIPICFG_INTS 0x034
+
+#define MIPICFG_CFG_SEL_CSI BIT(0)
+
+#define MIPICFG_INT_CSI_DMA BIT(0)
+#define MIPICFG_INT_CSI_HOST BIT(2)
+#define MIPICFG_INT_PISP_FE BIT(4)
+
+#define BPL_ALIGNMENT 16
+#define MAX_BYTESPERLINE 0xffffff00
+#define MAX_BUFFER_SIZE 0xffffff00
+/*
+ * Max width is therefore determined by the max stride divided by the number of
+ * bits per pixel.
+ *
+ * However, to avoid overflow issues let's use a 16k maximum. This lets us
+ * calculate 16k * 16k * 4 with 32bits. If we need higher maximums, a careful
+ * review and adjustment of the code is needed so that it will deal with
+ * overflows correctly.
+ */
+#define MAX_WIDTH 16384
+#define MAX_HEIGHT MAX_WIDTH
+/* Define a nominal minimum image size */
+#define MIN_WIDTH 16
+#define MIN_HEIGHT 16
+
+#define MIN_META_WIDTH 4
+#define MIN_META_HEIGHT 1
+
+const struct v4l2_mbus_framefmt cfe_default_format = {
+ .width = 640,
+ .height = 480,
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .ycbcr_enc = V4L2_YCBCR_ENC_601,
+ .quantization = V4L2_QUANTIZATION_FULL_RANGE,
+ .xfer_func = V4L2_XFER_FUNC_NONE,
+};
+
+enum node_ids {
+ /* CSI2 HW output nodes first. */
+ CSI2_CH0,
+ CSI2_CH1,
+ CSI2_CH2,
+ CSI2_CH3,
+ /* FE only nodes from here on. */
+ FE_OUT0,
+ FE_OUT1,
+ FE_STATS,
+ FE_CONFIG,
+ NUM_NODES
+};
+
+struct node_description {
+ enum node_ids id;
+ const char *name;
+ unsigned int caps;
+ unsigned int pad_flags;
+ unsigned int link_pad;
+};
+
+/* Must match the ordering of enum ids */
+static const struct node_description node_desc[NUM_NODES] = {
+ [CSI2_CH0] = {
+ .name = "csi2-ch0",
+ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE,
+ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = CSI2_PAD_FIRST_SOURCE + 0
+ },
+ /*
+ * At the moment the main userspace component (libcamera) doesn't
+ * support metadata with video nodes that support both video and
+ * metadata. So for the time being this node is set to only support
+ * V4L2_CAP_META_CAPTURE.
+ */
+ [CSI2_CH1] = {
+ .name = "csi2-ch1",
+ .caps = V4L2_CAP_META_CAPTURE,
+ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = CSI2_PAD_FIRST_SOURCE + 1
+ },
+ [CSI2_CH2] = {
+ .name = "csi2-ch2",
+ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE,
+ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = CSI2_PAD_FIRST_SOURCE + 2
+ },
+ [CSI2_CH3] = {
+ .name = "csi2-ch3",
+ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE,
+ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = CSI2_PAD_FIRST_SOURCE + 3
+ },
+ [FE_OUT0] = {
+ .name = "fe-image0",
+ .caps = V4L2_CAP_VIDEO_CAPTURE,
+ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = FE_OUTPUT0_PAD
+ },
+ [FE_OUT1] = {
+ .name = "fe-image1",
+ .caps = V4L2_CAP_VIDEO_CAPTURE,
+ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = FE_OUTPUT1_PAD
+ },
+ [FE_STATS] = {
+ .name = "fe-stats",
+ .caps = V4L2_CAP_META_CAPTURE,
+ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = FE_STATS_PAD
+ },
+ [FE_CONFIG] = {
+ .name = "fe-config",
+ .caps = V4L2_CAP_META_OUTPUT,
+ .pad_flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT,
+ .link_pad = FE_CONFIG_PAD
+ },
+};
+
+#define is_fe_node(node) (((node)->id) >= FE_OUT0)
+#define is_csi2_node(node) (!is_fe_node(node))
+
+#define node_supports_image_output(node) \
+ (node_desc[(node)->id].caps & V4L2_CAP_VIDEO_CAPTURE)
+#define node_supports_meta_output(node) \
+ (node_desc[(node)->id].caps & V4L2_CAP_META_CAPTURE)
+#define node_supports_image_input(node) \
+ (node_desc[(node)->id].caps & V4L2_CAP_VIDEO_OUTPUT)
+#define node_supports_meta_input(node) \
+ (node_desc[(node)->id].caps & V4L2_CAP_META_OUTPUT)
+#define node_supports_image(node) \
+ (node_supports_image_output(node) || node_supports_image_input(node))
+#define node_supports_meta(node) \
+ (node_supports_meta_output(node) || node_supports_meta_input(node))
+
+#define is_image_output_node(node) \
+ ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+#define is_image_input_node(node) \
+ ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+#define is_image_node(node) \
+ (is_image_output_node(node) || is_image_input_node(node))
+#define is_meta_output_node(node) \
+ ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_CAPTURE)
+#define is_meta_input_node(node) \
+ ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_OUTPUT)
+#define is_meta_node(node) \
+ (is_meta_output_node(node) || is_meta_input_node(node))
+
+/* To track state across all nodes. */
+#define NODE_REGISTERED BIT(0)
+#define NODE_ENABLED BIT(1)
+#define NODE_STREAMING BIT(2)
+#define FS_INT BIT(3)
+#define FE_INT BIT(4)
+#define NUM_STATES 5
+
+struct cfe_buffer {
+ struct vb2_v4l2_buffer vb;
+ struct list_head list;
+};
+
+struct cfe_config_buffer {
+ struct cfe_buffer buf;
+ struct pisp_fe_config config;
+};
+
+static inline struct cfe_buffer *to_cfe_buffer(struct vb2_buffer *vb)
+{
+ return container_of(vb, struct cfe_buffer, vb.vb2_buf);
+}
+
+static inline
+struct cfe_config_buffer *to_cfe_config_buffer(struct cfe_buffer *buf)
+{
+ return container_of(buf, struct cfe_config_buffer, buf);
+}
+
+struct cfe_node {
+ /* Node id */
+ enum node_ids id;
+ /* Pointer pointing to current v4l2_buffer */
+ struct cfe_buffer *cur_frm;
+ /* Pointer pointing to next v4l2_buffer */
+ struct cfe_buffer *next_frm;
+ /* Used to store current pixel format */
+ struct v4l2_format vid_fmt;
+ /* Used to store current meta format */
+ struct v4l2_format meta_fmt;
+ /* Buffer queue used in video-buf */
+ struct vb2_queue buffer_queue;
+ /* Queue of filled frames */
+ struct list_head dma_queue;
+ /* lock used to access this structure */
+ struct mutex lock;
+ /* Identifies video device for this channel */
+ struct video_device video_dev;
+ /* Pointer to the parent handle */
+ struct cfe_device *cfe;
+ /* Media pad for this node */
+ struct media_pad pad;
+ /* Frame-start counter */
+ unsigned int fs_count;
+ /* Timestamp of the current buffer */
+ u64 ts;
+};
+
+struct cfe_device {
+ struct dentry *debugfs;
+ struct kref kref;
+
+ /* peripheral base address */
+ void __iomem *mipi_cfg_base;
+
+ struct clk *clk;
+
+ /* V4l2 device */
+ struct v4l2_device v4l2_dev;
+ struct media_device mdev;
+ struct media_pipeline pipe;
+
+ /* IRQ lock for node state and DMA queues */
+ spinlock_t state_lock;
+ bool job_ready;
+ bool job_queued;
+
+ /* parent device */
+ struct platform_device *pdev;
+ /* subdevice async Notifier */
+ struct v4l2_async_notifier notifier;
+
+ /* Source sub device */
+ struct v4l2_subdev *source_sd;
+ /* Source subdev's pad */
+ u32 source_pad;
+
+ struct cfe_node node[NUM_NODES];
+ DECLARE_BITMAP(node_flags, NUM_STATES * NUM_NODES);
+
+ struct csi2_device csi2;
+ struct pisp_fe_device fe;
+
+ int fe_csi2_channel;
+
+ /* Mask of enabled streams */
+ u64 streams_mask;
+};
+
+static inline bool is_fe_enabled(struct cfe_device *cfe)
+{
+ return cfe->fe_csi2_channel != -1;
+}
+
+static inline struct cfe_device *to_cfe_device(struct v4l2_device *v4l2_dev)
+{
+ return container_of(v4l2_dev, struct cfe_device, v4l2_dev);
+}
+
+static inline u32 cfg_reg_read(struct cfe_device *cfe, u32 offset)
+{
+ return readl(cfe->mipi_cfg_base + offset);
+}
+
+static inline void cfg_reg_write(struct cfe_device *cfe, u32 offset, u32 val)
+{
+ writel(val, cfe->mipi_cfg_base + offset);
+}
+
+static bool check_state(struct cfe_device *cfe, unsigned long state,
+ unsigned int node_id)
+{
+ unsigned long bit;
+
+ for_each_set_bit(bit, &state, sizeof(state)) {
+ if (!test_bit(bit + (node_id * NUM_STATES), cfe->node_flags))
+ return false;
+ }
+
+ return true;
+}
+
+static void set_state(struct cfe_device *cfe, unsigned long state,
+ unsigned int node_id)
+{
+ unsigned long bit;
+
+ for_each_set_bit(bit, &state, sizeof(state))
+ set_bit(bit + (node_id * NUM_STATES), cfe->node_flags);
+}
+
+static void clear_state(struct cfe_device *cfe, unsigned long state,
+ unsigned int node_id)
+{
+ unsigned long bit;
+
+ for_each_set_bit(bit, &state, sizeof(state))
+ clear_bit(bit + (node_id * NUM_STATES), cfe->node_flags);
+}
+
+static bool test_any_node(struct cfe_device *cfe, unsigned long cond)
+{
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ if (check_state(cfe, cond, i))
+ return true;
+ }
+
+ return false;
+}
+
+static bool test_all_nodes(struct cfe_device *cfe, unsigned long precond,
+ unsigned long cond)
+{
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ if (check_state(cfe, precond, i)) {
+ if (!check_state(cfe, cond, i))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int mipi_cfg_regs_show(struct seq_file *s, void *data)
+{
+ struct cfe_device *cfe = s->private;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(&cfe->pdev->dev);
+ if (ret)
+ return ret;
+
+#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", cfg_reg_read(cfe, reg))
+ DUMP(MIPICFG_CFG);
+ DUMP(MIPICFG_INTR);
+ DUMP(MIPICFG_INTE);
+ DUMP(MIPICFG_INTF);
+ DUMP(MIPICFG_INTS);
+#undef DUMP
+
+ pm_runtime_put(&cfe->pdev->dev);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(mipi_cfg_regs);
+
+/* Format setup functions */
+const struct cfe_fmt *find_format_by_code(u32 code)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(formats); i++) {
+ if (formats[i].code == code)
+ return &formats[i];
+ }
+
+ return NULL;
+}
+
+const struct cfe_fmt *find_format_by_pix(u32 pixelformat)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(formats); i++) {
+ if (formats[i].fourcc == pixelformat)
+ return &formats[i];
+ }
+
+ return NULL;
+}
+
+static const struct cfe_fmt *find_format_by_code_and_fourcc(u32 code,
+ u32 fourcc)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(formats); i++) {
+ if (formats[i].code == code && formats[i].fourcc == fourcc)
+ return &formats[i];
+ }
+
+ return NULL;
+}
+
+/*
+ * Given the mbus code, find the 16 bit remapped code. Returns 0 if no remap
+ * possible.
+ */
+u32 cfe_find_16bit_code(u32 code)
+{
+ const struct cfe_fmt *cfe_fmt;
+
+ cfe_fmt = find_format_by_code(code);
+
+ if (!cfe_fmt || !cfe_fmt->remap[CFE_REMAP_16BIT])
+ return 0;
+
+ cfe_fmt = find_format_by_pix(cfe_fmt->remap[CFE_REMAP_16BIT]);
+ if (!cfe_fmt)
+ return 0;
+
+ return cfe_fmt->code;
+}
+
+/*
+ * Given the mbus code, find the 8 bit compressed code. Returns 0 if no remap
+ * possible.
+ */
+u32 cfe_find_compressed_code(u32 code)
+{
+ const struct cfe_fmt *cfe_fmt;
+
+ cfe_fmt = find_format_by_code(code);
+
+ if (!cfe_fmt || !cfe_fmt->remap[CFE_REMAP_COMPRESSED])
+ return 0;
+
+ cfe_fmt = find_format_by_pix(cfe_fmt->remap[CFE_REMAP_COMPRESSED]);
+ if (!cfe_fmt)
+ return 0;
+
+ return cfe_fmt->code;
+}
+
+static void cfe_calc_vid_format_size_bpl(struct cfe_device *cfe,
+ const struct cfe_fmt *fmt,
+ struct v4l2_format *f)
+{
+ unsigned int min_bytesperline;
+
+ v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 2,
+ &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0, 0);
+
+ min_bytesperline =
+ ALIGN((f->fmt.pix.width * fmt->depth) >> 3, BPL_ALIGNMENT);
+
+ if (f->fmt.pix.bytesperline > min_bytesperline &&
+ f->fmt.pix.bytesperline <= MAX_BYTESPERLINE)
+ f->fmt.pix.bytesperline =
+ ALIGN(f->fmt.pix.bytesperline, BPL_ALIGNMENT);
+ else
+ f->fmt.pix.bytesperline = min_bytesperline;
+
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+ cfe_dbg(cfe, "%s: %p4cc size: %ux%u bpl:%u img_size:%u\n", __func__,
+ &f->fmt.pix.pixelformat, f->fmt.pix.width, f->fmt.pix.height,
+ f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
+}
+
+static void cfe_calc_meta_format_size_bpl(struct cfe_device *cfe,
+ const struct cfe_fmt *fmt,
+ struct v4l2_format *f)
+{
+ v4l_bound_align_image(&f->fmt.meta.width, MIN_META_WIDTH, MAX_WIDTH, 2,
+ &f->fmt.meta.height, MIN_META_HEIGHT, MAX_HEIGHT,
+ 0, 0);
+
+ f->fmt.meta.bytesperline = (f->fmt.meta.width * fmt->depth) >> 3;
+ f->fmt.meta.buffersize = f->fmt.meta.height * f->fmt.pix.bytesperline;
+
+ cfe_dbg(cfe, "%s: %p4cc size: %ux%u bpl:%u buf_size:%u\n", __func__,
+ &f->fmt.meta.dataformat, f->fmt.meta.width, f->fmt.meta.height,
+ f->fmt.meta.bytesperline, f->fmt.meta.buffersize);
+}
+
+static void cfe_schedule_next_csi2_job(struct cfe_device *cfe)
+{
+ struct cfe_buffer *buf;
+ dma_addr_t addr;
+
+ for (unsigned int i = 0; i < CSI2_NUM_CHANNELS; i++) {
+ struct cfe_node *node = &cfe->node[i];
+ unsigned int stride, size;
+
+ if (!check_state(cfe, NODE_STREAMING, i))
+ continue;
+
+ buf = list_first_entry(&node->dma_queue, struct cfe_buffer,
+ list);
+ node->next_frm = buf;
+ list_del(&buf->list);
+
+ trace_cfe_csi2_schedule(node->id, &buf->vb.vb2_buf);
+
+ if (is_meta_node(node)) {
+ size = node->meta_fmt.fmt.meta.buffersize;
+ /* We use CSI2_CH_CTRL_PACK_BYTES, so stride == 0 */
+ stride = 0;
+ } else {
+ size = node->vid_fmt.fmt.pix.sizeimage;
+ stride = node->vid_fmt.fmt.pix.bytesperline;
+ }
+
+ addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+ csi2_set_buffer(&cfe->csi2, node->id, addr, stride, size);
+ }
+}
+
+static void cfe_schedule_next_pisp_job(struct cfe_device *cfe)
+{
+ struct vb2_buffer *vb2_bufs[FE_NUM_PADS] = { 0 };
+ struct cfe_config_buffer *config_buf;
+ struct cfe_buffer *buf;
+
+ for (unsigned int i = CSI2_NUM_CHANNELS; i < NUM_NODES; i++) {
+ struct cfe_node *node = &cfe->node[i];
+
+ if (!check_state(cfe, NODE_STREAMING, i))
+ continue;
+
+ buf = list_first_entry(&node->dma_queue, struct cfe_buffer,
+ list);
+
+ trace_cfe_fe_schedule(node->id, &buf->vb.vb2_buf);
+
+ node->next_frm = buf;
+ vb2_bufs[node_desc[i].link_pad] = &buf->vb.vb2_buf;
+ list_del(&buf->list);
+ }
+
+ config_buf = to_cfe_config_buffer(cfe->node[FE_CONFIG].next_frm);
+ pisp_fe_submit_job(&cfe->fe, vb2_bufs, &config_buf->config);
+}
+
+static bool cfe_check_job_ready(struct cfe_device *cfe)
+{
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ struct cfe_node *node = &cfe->node[i];
+
+ if (!check_state(cfe, NODE_ENABLED, i))
+ continue;
+
+ if (list_empty(&node->dma_queue))
+ return false;
+ }
+
+ return true;
+}
+
+static void cfe_prepare_next_job(struct cfe_device *cfe)
+{
+ trace_cfe_prepare_next_job(is_fe_enabled(cfe));
+
+ cfe->job_queued = true;
+ cfe_schedule_next_csi2_job(cfe);
+ if (is_fe_enabled(cfe))
+ cfe_schedule_next_pisp_job(cfe);
+
+ /* Flag if another job is ready after this. */
+ cfe->job_ready = cfe_check_job_ready(cfe);
+}
+
+static void cfe_process_buffer_complete(struct cfe_node *node,
+ enum vb2_buffer_state state)
+{
+ trace_cfe_buffer_complete(node->id, &node->cur_frm->vb);
+
+ node->cur_frm->vb.sequence = node->fs_count - 1;
+ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, state);
+}
+
+static void cfe_queue_event_sof(struct cfe_node *node)
+{
+ struct v4l2_event event = {
+ .type = V4L2_EVENT_FRAME_SYNC,
+ .u.frame_sync.frame_sequence = node->fs_count - 1,
+ };
+
+ v4l2_event_queue(&node->video_dev, &event);
+}
+
+static void cfe_sof_isr(struct cfe_node *node)
+{
+ struct cfe_device *cfe = node->cfe;
+ bool matching_fs = true;
+
+ trace_cfe_frame_start(node->id, node->fs_count);
+
+ /*
+ * If the sensor is producing unexpected frame event ordering over a
+ * sustained period of time, guard against the possibility of coming
+ * here and orphaning the cur_frm if it's not been dequeued already.
+ * Unfortunately, there is not enough hardware state to tell if this
+ * may have occurred.
+ */
+ if (WARN(node->cur_frm, "%s: [%s] Orphaned frame at seq %u\n",
+ __func__, node_desc[node->id].name, node->fs_count))
+ cfe_process_buffer_complete(node, VB2_BUF_STATE_ERROR);
+
+ node->cur_frm = node->next_frm;
+ node->next_frm = NULL;
+ node->fs_count++;
+
+ node->ts = ktime_get_ns();
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ if (!check_state(cfe, NODE_STREAMING, i) || i == node->id)
+ continue;
+ /*
+ * This checks if any other node has seen a FS. If yes, use the
+ * same timestamp, eventually across all node buffers.
+ */
+ if (cfe->node[i].fs_count >= node->fs_count)
+ node->ts = cfe->node[i].ts;
+ /*
+ * This checks if all other node have seen a matching FS. If
+ * yes, we can flag another job to be queued.
+ */
+ if (matching_fs && cfe->node[i].fs_count != node->fs_count)
+ matching_fs = false;
+ }
+
+ if (matching_fs)
+ cfe->job_queued = false;
+
+ if (node->cur_frm)
+ node->cur_frm->vb.vb2_buf.timestamp = node->ts;
+
+ set_state(cfe, FS_INT, node->id);
+ clear_state(cfe, FE_INT, node->id);
+
+ if (is_image_output_node(node))
+ cfe_queue_event_sof(node);
+}
+
+static void cfe_eof_isr(struct cfe_node *node)
+{
+ struct cfe_device *cfe = node->cfe;
+
+ trace_cfe_frame_end(node->id, node->fs_count - 1);
+
+ if (node->cur_frm)
+ cfe_process_buffer_complete(node, VB2_BUF_STATE_DONE);
+
+ node->cur_frm = NULL;
+ set_state(cfe, FE_INT, node->id);
+ clear_state(cfe, FS_INT, node->id);
+}
+
+static irqreturn_t cfe_isr(int irq, void *dev)
+{
+ struct cfe_device *cfe = dev;
+ bool sof[NUM_NODES] = { 0 }, eof[NUM_NODES] = { 0 };
+ u32 sts;
+
+ sts = cfg_reg_read(cfe, MIPICFG_INTS);
+
+ if (sts & MIPICFG_INT_CSI_DMA)
+ csi2_isr(&cfe->csi2, sof, eof);
+
+ if (sts & MIPICFG_INT_PISP_FE)
+ pisp_fe_isr(&cfe->fe, sof + CSI2_NUM_CHANNELS,
+ eof + CSI2_NUM_CHANNELS);
+
+ spin_lock(&cfe->state_lock);
+
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ struct cfe_node *node = &cfe->node[i];
+
+ /*
+ * The check_state(NODE_STREAMING) is to ensure we do not loop
+ * over the CSI2_CHx nodes when the FE is active since they
+ * generate interrupts even though the node is not streaming.
+ */
+ if (!check_state(cfe, NODE_STREAMING, i) || !(sof[i] || eof[i]))
+ continue;
+
+ /*
+ * There are 3 cases where we could get FS + FE_ACK at
+ * the same time:
+ * 1) FE of the current frame, and FS of the next frame.
+ * 2) FS + FE of the same frame.
+ * 3) FE of the current frame, and FS + FE of the next
+ * frame. To handle this, see the sof handler below.
+ *
+ * (1) is handled implicitly by the ordering of the FE and FS
+ * handlers below.
+ */
+ if (eof[i]) {
+ /*
+ * The condition below tests for (2). Run the FS handler
+ * first before the FE handler, both for the current
+ * frame.
+ */
+ if (sof[i] && !check_state(cfe, FS_INT, i)) {
+ cfe_sof_isr(node);
+ sof[i] = false;
+ }
+
+ cfe_eof_isr(node);
+ }
+
+ if (sof[i]) {
+ /*
+ * The condition below tests for (3). In such cases, we
+ * come in here with FS flag set in the node state from
+ * the previous frame since it only gets cleared in
+ * cfe_eof_isr(). Handle the FE for the previous
+ * frame first before the FS handler for the current
+ * frame.
+ */
+ if (check_state(cfe, FS_INT, node->id) &&
+ !check_state(cfe, FE_INT, node->id)) {
+ cfe_dbg(cfe, "%s: [%s] Handling missing previous FE interrupt\n",
+ __func__, node_desc[node->id].name);
+ cfe_eof_isr(node);
+ }
+
+ cfe_sof_isr(node);
+ }
+
+ if (!cfe->job_queued && cfe->job_ready)
+ cfe_prepare_next_job(cfe);
+ }
+
+ spin_unlock(&cfe->state_lock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Stream helpers
+ */
+
+static int cfe_get_vc_dt_fallback(struct cfe_device *cfe, u8 *vc, u8 *dt)
+{
+ struct v4l2_subdev_state *state;
+ struct v4l2_mbus_framefmt *fmt;
+ const struct cfe_fmt *cfe_fmt;
+
+ state = v4l2_subdev_get_locked_active_state(&cfe->csi2.sd);
+
+ fmt = v4l2_subdev_state_get_format(state, CSI2_PAD_SINK, 0);
+ if (!fmt)
+ return -EINVAL;
+
+ cfe_fmt = find_format_by_code(fmt->code);
+ if (!cfe_fmt)
+ return -EINVAL;
+
+ *vc = 0;
+ *dt = cfe_fmt->csi_dt;
+
+ return 0;
+}
+
+static int cfe_get_vc_dt(struct cfe_device *cfe, unsigned int channel, u8 *vc,
+ u8 *dt)
+{
+ struct v4l2_mbus_frame_desc remote_desc;
+ struct v4l2_subdev_state *state;
+ u32 sink_stream;
+ unsigned int i;
+ int ret;
+
+ state = v4l2_subdev_get_locked_active_state(&cfe->csi2.sd);
+
+ ret = v4l2_subdev_routing_find_opposite_end(&state->routing,
+ CSI2_PAD_FIRST_SOURCE + channel, 0, NULL, &sink_stream);
+ if (ret)
+ return ret;
+
+ ret = v4l2_subdev_call(cfe->source_sd, pad, get_frame_desc,
+ cfe->source_pad, &remote_desc);
+ if (ret == -ENOIOCTLCMD) {
+ cfe_dbg(cfe, "source does not support get_frame_desc, use fallback\n");
+ return cfe_get_vc_dt_fallback(cfe, vc, dt);
+ } else if (ret) {
+ cfe_err(cfe, "Failed to get frame descriptor\n");
+ return ret;
+ }
+
+ if (remote_desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
+ cfe_err(cfe, "Frame descriptor does not describe CSI-2 link");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < remote_desc.num_entries; i++) {
+ if (remote_desc.entry[i].stream == sink_stream)
+ break;
+ }
+
+ if (i == remote_desc.num_entries) {
+ cfe_err(cfe, "Stream %u not found in remote frame desc\n",
+ sink_stream);
+ return -EINVAL;
+ }
+
+ *vc = remote_desc.entry[i].bus.csi2.vc;
+ *dt = remote_desc.entry[i].bus.csi2.dt;
+
+ return 0;
+}
+
+static int cfe_start_channel(struct cfe_node *node)
+{
+ struct cfe_device *cfe = node->cfe;
+ struct v4l2_subdev_state *state;
+ struct v4l2_mbus_framefmt *source_fmt;
+ const struct cfe_fmt *fmt;
+ unsigned long flags;
+ bool start_fe;
+ int ret;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ start_fe = is_fe_enabled(cfe) &&
+ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING);
+
+ state = v4l2_subdev_get_locked_active_state(&cfe->csi2.sd);
+
+ if (start_fe) {
+ unsigned int width, height;
+ u8 vc, dt;
+
+ cfe_dbg(cfe, "%s: %s using csi2 channel %d\n", __func__,
+ node_desc[FE_OUT0].name, cfe->fe_csi2_channel);
+
+ ret = cfe_get_vc_dt(cfe, cfe->fe_csi2_channel, &vc, &dt);
+ if (ret)
+ return ret;
+
+ source_fmt = v4l2_subdev_state_get_format(state,
+ node_desc[cfe->fe_csi2_channel].link_pad);
+ fmt = find_format_by_code(source_fmt->code);
+
+ width = source_fmt->width;
+ height = source_fmt->height;
+
+ /* Must have a valid CSI2 datatype. */
+ WARN_ON(!fmt->csi_dt);
+
+ /*
+ * Start the associated CSI2 Channel as well.
+ *
+ * Must write to the ADDR register to latch the ctrl values
+ * even if we are connected to the front end. Once running,
+ * this is handled by the CSI2 AUTO_ARM mode.
+ */
+ csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel,
+ CSI2_MODE_FE_STREAMING,
+ true, false, width, height, vc, dt);
+ csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1);
+ pisp_fe_start(&cfe->fe);
+ }
+
+ if (is_csi2_node(node)) {
+ unsigned int width = 0, height = 0;
+ u8 vc, dt;
+
+ ret = cfe_get_vc_dt(cfe, node->id, &vc, &dt);
+ if (ret) {
+ if (start_fe) {
+ csi2_stop_channel(&cfe->csi2,
+ cfe->fe_csi2_channel);
+ pisp_fe_stop(&cfe->fe);
+ }
+
+ return ret;
+ }
+
+ u32 mode = CSI2_MODE_NORMAL;
+
+ source_fmt = v4l2_subdev_state_get_format(state,
+ node_desc[node->id].link_pad);
+ fmt = find_format_by_code(source_fmt->code);
+
+ /* Must have a valid CSI2 datatype. */
+ WARN_ON(!fmt->csi_dt);
+
+ if (is_image_output_node(node)) {
+ u32 pixfmt;
+
+ width = source_fmt->width;
+ height = source_fmt->height;
+
+ pixfmt = node->vid_fmt.fmt.pix.pixelformat;
+
+ if (pixfmt == fmt->remap[CFE_REMAP_16BIT]) {
+ mode = CSI2_MODE_REMAP;
+ } else if (pixfmt == fmt->remap[CFE_REMAP_COMPRESSED]) {
+ mode = CSI2_MODE_COMPRESSED;
+ csi2_set_compression(&cfe->csi2, node->id,
+ CSI2_COMPRESSION_DELTA, 0,
+ 0);
+ }
+ }
+ /* Unconditionally start this CSI2 channel. */
+ csi2_start_channel(&cfe->csi2, node->id,
+ mode,
+ /* Auto arm */
+ false,
+ /* Pack bytes */
+ is_meta_node(node) ? true : false,
+ width, height, vc, dt);
+ }
+
+ spin_lock_irqsave(&cfe->state_lock, flags);
+ if (cfe->job_ready && test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING))
+ cfe_prepare_next_job(cfe);
+ spin_unlock_irqrestore(&cfe->state_lock, flags);
+
+ return 0;
+}
+
+static void cfe_stop_channel(struct cfe_node *node, bool fe_stop)
+{
+ struct cfe_device *cfe = node->cfe;
+
+ cfe_dbg(cfe, "%s: [%s] fe_stop %u\n", __func__,
+ node_desc[node->id].name, fe_stop);
+
+ if (fe_stop) {
+ csi2_stop_channel(&cfe->csi2, cfe->fe_csi2_channel);
+ pisp_fe_stop(&cfe->fe);
+ }
+
+ if (is_csi2_node(node))
+ csi2_stop_channel(&cfe->csi2, node->id);
+}
+
+static void cfe_return_buffers(struct cfe_node *node,
+ enum vb2_buffer_state state)
+{
+ struct cfe_device *cfe = node->cfe;
+ struct cfe_buffer *buf, *tmp;
+ unsigned long flags;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ spin_lock_irqsave(&cfe->state_lock, flags);
+ list_for_each_entry_safe(buf, tmp, &node->dma_queue, list) {
+ list_del(&buf->list);
+ trace_cfe_return_buffer(node->id, buf->vb.vb2_buf.index, 2);
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
+ }
+
+ if (node->cur_frm) {
+ trace_cfe_return_buffer(node->id,
+ node->cur_frm->vb.vb2_buf.index, 0);
+ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, state);
+ }
+ if (node->next_frm && node->cur_frm != node->next_frm) {
+ trace_cfe_return_buffer(node->id,
+ node->next_frm->vb.vb2_buf.index, 1);
+ vb2_buffer_done(&node->next_frm->vb.vb2_buf, state);
+ }
+
+ node->cur_frm = NULL;
+ node->next_frm = NULL;
+ spin_unlock_irqrestore(&cfe->state_lock, flags);
+}
+
+/*
+ * vb2 ops
+ */
+
+static int cfe_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+ unsigned int *nplanes, unsigned int sizes[],
+ struct device *alloc_devs[])
+{
+ struct cfe_node *node = vb2_get_drv_priv(vq);
+ struct cfe_device *cfe = node->cfe;
+ unsigned int size = is_image_node(node) ?
+ node->vid_fmt.fmt.pix.sizeimage :
+ node->meta_fmt.fmt.meta.buffersize;
+
+ cfe_dbg(cfe, "%s: [%s] type:%u\n", __func__, node_desc[node->id].name,
+ node->buffer_queue.type);
+
+ if (vq->max_num_buffers + *nbuffers < 3)
+ *nbuffers = 3 - vq->max_num_buffers;
+
+ if (*nplanes) {
+ if (sizes[0] < size) {
+ cfe_err(cfe, "sizes[0] %i < size %u\n", sizes[0], size);
+ return -EINVAL;
+ }
+ size = sizes[0];
+ }
+
+ *nplanes = 1;
+ sizes[0] = size;
+
+ return 0;
+}
+
+static int cfe_buffer_prepare(struct vb2_buffer *vb)
+{
+ struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue);
+ struct cfe_device *cfe = node->cfe;
+ struct cfe_buffer *buf = to_cfe_buffer(vb);
+ unsigned long size;
+
+ trace_cfe_buffer_prepare(node->id, vb);
+
+ size = is_image_node(node) ? node->vid_fmt.fmt.pix.sizeimage :
+ node->meta_fmt.fmt.meta.buffersize;
+ if (vb2_plane_size(vb, 0) < size) {
+ cfe_err(cfe, "data will not fit into plane (%lu < %lu)\n",
+ vb2_plane_size(vb, 0), size);
+ return -EINVAL;
+ }
+
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
+
+ if (node->id == FE_CONFIG) {
+ struct cfe_config_buffer *b = to_cfe_config_buffer(buf);
+ void *addr = vb2_plane_vaddr(vb, 0);
+
+ memcpy(&b->config, addr, sizeof(struct pisp_fe_config));
+ return pisp_fe_validate_config(&cfe->fe, &b->config,
+ &cfe->node[FE_OUT0].vid_fmt,
+ &cfe->node[FE_OUT1].vid_fmt);
+ }
+
+ return 0;
+}
+
+static void cfe_buffer_queue(struct vb2_buffer *vb)
+{
+ struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue);
+ struct cfe_device *cfe = node->cfe;
+ struct cfe_buffer *buf = to_cfe_buffer(vb);
+ unsigned long flags;
+ bool schedule_now;
+
+ spin_lock_irqsave(&cfe->state_lock, flags);
+
+ list_add_tail(&buf->list, &node->dma_queue);
+
+ if (!cfe->job_ready)
+ cfe->job_ready = cfe_check_job_ready(cfe);
+
+ schedule_now = !cfe->job_queued && cfe->job_ready &&
+ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING);
+
+ trace_cfe_buffer_queue(node->id, vb, schedule_now);
+
+ if (schedule_now)
+ cfe_prepare_next_job(cfe);
+
+ spin_unlock_irqrestore(&cfe->state_lock, flags);
+}
+
+static s64 cfe_get_source_link_freq(struct cfe_device *cfe)
+{
+ struct v4l2_subdev_state *state;
+ s64 link_freq;
+ u32 bpp;
+
+ state = v4l2_subdev_get_locked_active_state(&cfe->csi2.sd);
+
+ /*
+ * v4l2_get_link_freq() uses V4L2_CID_LINK_FREQ first, and falls back
+ * to V4L2_CID_PIXEL_RATE if V4L2_CID_LINK_FREQ is not available.
+ *
+ * With multistream input there is no single pixel rate, and thus we
+ * cannot use V4L2_CID_PIXEL_RATE, so we pass 0 as the bpp which
+ * causes v4l2_get_link_freq() to return an error if it falls back to
+ * V4L2_CID_PIXEL_RATE.
+ */
+
+ if (state->routing.num_routes == 1) {
+ struct v4l2_subdev_route *route = &state->routing.routes[0];
+ struct v4l2_mbus_framefmt *source_fmt;
+ const struct cfe_fmt *fmt;
+
+ source_fmt = v4l2_subdev_state_get_format(state,
+ route->sink_pad,
+ route->sink_stream);
+
+ fmt = find_format_by_code(source_fmt->code);
+ if (!fmt)
+ return -EINVAL;
+
+ bpp = fmt->depth;
+ } else {
+ bpp = 0;
+ }
+
+ link_freq = v4l2_get_link_freq(cfe->source_sd->ctrl_handler, bpp,
+ 2 * cfe->csi2.dphy.active_lanes);
+ if (link_freq < 0)
+ cfe_err(cfe, "failed to get link freq for subdev '%s'\n",
+ cfe->source_sd->name);
+
+ return link_freq;
+}
+
+static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct v4l2_mbus_config mbus_config = { 0 };
+ struct cfe_node *node = vb2_get_drv_priv(vq);
+ struct cfe_device *cfe = node->cfe;
+ struct v4l2_subdev_state *state;
+ struct v4l2_subdev_route *route;
+ s64 link_freq;
+ int ret;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ if (!check_state(cfe, NODE_ENABLED, node->id)) {
+ cfe_err(cfe, "%s node link is not enabled.\n",
+ node_desc[node->id].name);
+ ret = -EINVAL;
+ goto err_streaming;
+ }
+
+ ret = pm_runtime_resume_and_get(&cfe->pdev->dev);
+ if (ret < 0) {
+ cfe_err(cfe, "pm_runtime_resume_and_get failed\n");
+ goto err_streaming;
+ }
+
+ /* When using the Frontend, we must enable the FE_CONFIG node. */
+ if (is_fe_enabled(cfe) &&
+ !check_state(cfe, NODE_ENABLED, cfe->node[FE_CONFIG].id)) {
+ cfe_err(cfe, "FE enabled, but FE_CONFIG node is not\n");
+ ret = -EINVAL;
+ goto err_pm_put;
+ }
+
+ ret = media_pipeline_start(&node->pad, &cfe->pipe);
+ if (ret < 0) {
+ cfe_err(cfe, "Failed to start media pipeline: %d\n", ret);
+ goto err_pm_put;
+ }
+
+ state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd);
+
+ clear_state(cfe, FS_INT | FE_INT, node->id);
+ set_state(cfe, NODE_STREAMING, node->id);
+ node->fs_count = 0;
+
+ ret = cfe_start_channel(node);
+ if (ret)
+ goto err_unlock_state;
+
+ if (!test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) {
+ cfe_dbg(cfe, "Streaming on hold, as all nodes are not set to streaming yet\n");
+ v4l2_subdev_unlock_state(state);
+ return 0;
+ }
+
+ cfg_reg_write(cfe, MIPICFG_CFG, MIPICFG_CFG_SEL_CSI);
+ cfg_reg_write(cfe, MIPICFG_INTE,
+ MIPICFG_INT_CSI_DMA | MIPICFG_INT_PISP_FE);
+
+ ret = v4l2_subdev_call(cfe->source_sd, pad, get_mbus_config, 0,
+ &mbus_config);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ cfe_err(cfe, "g_mbus_config failed\n");
+ goto err_clear_inte;
+ }
+
+ cfe->csi2.dphy.active_lanes = mbus_config.bus.mipi_csi2.num_data_lanes;
+ if (!cfe->csi2.dphy.active_lanes)
+ cfe->csi2.dphy.active_lanes = cfe->csi2.dphy.max_lanes;
+ if (cfe->csi2.dphy.active_lanes > cfe->csi2.dphy.max_lanes) {
+ cfe_err(cfe, "Device has requested %u data lanes, which is >%u configured in DT\n",
+ cfe->csi2.dphy.active_lanes, cfe->csi2.dphy.max_lanes);
+ ret = -EINVAL;
+ goto err_clear_inte;
+ }
+
+ link_freq = cfe_get_source_link_freq(cfe);
+ if (link_freq < 0)
+ goto err_clear_inte;
+
+ cfe->csi2.dphy.dphy_rate = div_s64(link_freq * 2, 1000000);
+ csi2_open_rx(&cfe->csi2);
+
+ cfe->streams_mask = 0;
+
+ for_each_active_route(&state->routing, route)
+ cfe->streams_mask |= BIT_ULL(route->sink_stream);
+
+ ret = v4l2_subdev_enable_streams(cfe->source_sd, cfe->source_pad,
+ cfe->streams_mask);
+ if (ret) {
+ cfe_err(cfe, "stream on failed in subdev\n");
+ goto err_disable_cfe;
+ }
+
+ cfe_dbg(cfe, "Streaming enabled\n");
+
+ v4l2_subdev_unlock_state(state);
+
+ return 0;
+
+err_disable_cfe:
+ csi2_close_rx(&cfe->csi2);
+err_clear_inte:
+ cfg_reg_write(cfe, MIPICFG_INTE, 0);
+
+ cfe_stop_channel(node,
+ is_fe_enabled(cfe) && test_all_nodes(cfe, NODE_ENABLED,
+ NODE_STREAMING));
+err_unlock_state:
+ v4l2_subdev_unlock_state(state);
+ media_pipeline_stop(&node->pad);
+err_pm_put:
+ pm_runtime_put(&cfe->pdev->dev);
+err_streaming:
+ cfe_return_buffers(node, VB2_BUF_STATE_QUEUED);
+ clear_state(cfe, NODE_STREAMING, node->id);
+
+ return ret;
+}
+
+static void cfe_stop_streaming(struct vb2_queue *vq)
+{
+ struct cfe_node *node = vb2_get_drv_priv(vq);
+ struct cfe_device *cfe = node->cfe;
+ unsigned long flags;
+ bool fe_stop;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ spin_lock_irqsave(&cfe->state_lock, flags);
+ fe_stop = is_fe_enabled(cfe) &&
+ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING);
+
+ cfe->job_ready = false;
+ clear_state(cfe, NODE_STREAMING, node->id);
+ spin_unlock_irqrestore(&cfe->state_lock, flags);
+
+ cfe_stop_channel(node, fe_stop);
+
+ if (!test_any_node(cfe, NODE_STREAMING)) {
+ struct v4l2_subdev_state *state;
+ int ret;
+
+ state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd);
+
+ ret = v4l2_subdev_disable_streams(cfe->source_sd,
+ cfe->source_pad,
+ cfe->streams_mask);
+ if (ret)
+ cfe_err(cfe, "stream disable failed in subdev\n");
+
+ v4l2_subdev_unlock_state(state);
+
+ csi2_close_rx(&cfe->csi2);
+
+ cfg_reg_write(cfe, MIPICFG_INTE, 0);
+
+ cfe_dbg(cfe, "%s: Streaming disabled\n", __func__);
+ }
+
+ media_pipeline_stop(&node->pad);
+
+ /* Clear all queued buffers for the node */
+ cfe_return_buffers(node, VB2_BUF_STATE_ERROR);
+
+ pm_runtime_put(&cfe->pdev->dev);
+}
+
+static const struct vb2_ops cfe_video_qops = {
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .queue_setup = cfe_queue_setup,
+ .buf_prepare = cfe_buffer_prepare,
+ .buf_queue = cfe_buffer_queue,
+ .start_streaming = cfe_start_streaming,
+ .stop_streaming = cfe_stop_streaming,
+};
+
+/*
+ * v4l2 ioctl ops
+ */
+
+static int cfe_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ strscpy(cap->driver, CFE_MODULE_NAME, sizeof(cap->driver));
+ strscpy(cap->card, CFE_MODULE_NAME, sizeof(cap->card));
+
+ cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE |
+ V4L2_CAP_META_OUTPUT;
+
+ return 0;
+}
+
+static int cfe_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+ unsigned int i, j;
+
+ if (!node_supports_image_output(node))
+ return -EINVAL;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) {
+ if (f->mbus_code && formats[i].code != f->mbus_code)
+ continue;
+
+ if (formats[i].flags & CFE_FORMAT_FLAG_META_OUT ||
+ formats[i].flags & CFE_FORMAT_FLAG_META_CAP)
+ continue;
+
+ if (is_fe_node(node) &&
+ !(formats[i].flags & CFE_FORMAT_FLAG_FE_OUT))
+ continue;
+
+ if (j == f->index) {
+ f->pixelformat = formats[i].fourcc;
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ return 0;
+ }
+ j++;
+ }
+
+ return -EINVAL;
+}
+
+static int cfe_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+
+ if (!node_supports_image(node))
+ return -EINVAL;
+
+ *f = node->vid_fmt;
+
+ return 0;
+}
+
+static int cfe_validate_fmt_vid_cap(struct cfe_node *node,
+ struct v4l2_format *f)
+{
+ struct cfe_device *cfe = node->cfe;
+ const struct cfe_fmt *fmt;
+
+ cfe_dbg(cfe, "%s: [%s] %ux%u, V4L2 pix %p4cc\n", __func__,
+ node_desc[node->id].name, f->fmt.pix.width, f->fmt.pix.height,
+ &f->fmt.pix.pixelformat);
+
+ if (!node_supports_image_output(node))
+ return -EINVAL;
+
+ /*
+ * Default to a format that works for both CSI2 and FE.
+ */
+ fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+ if (!fmt)
+ fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10);
+
+ f->fmt.pix.pixelformat = fmt->fourcc;
+
+ if (is_fe_node(node) && fmt->remap[CFE_REMAP_16BIT]) {
+ f->fmt.pix.pixelformat = fmt->remap[CFE_REMAP_16BIT];
+ fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+ }
+
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+
+ cfe_calc_vid_format_size_bpl(cfe, fmt, f);
+
+ return 0;
+}
+
+static int cfe_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+ struct vb2_queue *q = &node->buffer_queue;
+ int ret;
+
+ if (vb2_is_busy(q))
+ return -EBUSY;
+
+ ret = cfe_validate_fmt_vid_cap(node, f);
+ if (ret)
+ return ret;
+
+ node->vid_fmt = *f;
+
+ cfe_dbg(cfe, "%s: Set %ux%u, V4L2 pix %p4cc\n", __func__,
+ node->vid_fmt.fmt.pix.width, node->vid_fmt.fmt.pix.height,
+ &node->vid_fmt.fmt.pix.pixelformat);
+
+ return 0;
+}
+
+static int cfe_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ return cfe_validate_fmt_vid_cap(node, f);
+}
+
+static int cfe_enum_fmt_meta(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ if (!node_supports_meta(node))
+ return -EINVAL;
+
+ switch (node->id) {
+ case CSI2_CH0...CSI2_CH3:
+ f->flags = V4L2_FMT_FLAG_META_LINE_BASED;
+
+ switch (f->index) {
+ case 0:
+ f->pixelformat = V4L2_META_FMT_GENERIC_8;
+ return 0;
+ case 1:
+ f->pixelformat = V4L2_META_FMT_GENERIC_CSI2_10;
+ return 0;
+ case 2:
+ f->pixelformat = V4L2_META_FMT_GENERIC_CSI2_12;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ default:
+ break;
+ }
+
+ if (f->index != 0)
+ return -EINVAL;
+
+ switch (node->id) {
+ case FE_STATS:
+ f->pixelformat = V4L2_META_FMT_RPI_FE_STATS;
+ return 0;
+ case FE_CONFIG:
+ f->pixelformat = V4L2_META_FMT_RPI_FE_CFG;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int cfe_validate_fmt_meta(struct cfe_node *node, struct v4l2_format *f)
+{
+ struct cfe_device *cfe = node->cfe;
+ const struct cfe_fmt *fmt;
+
+ switch (node->id) {
+ case CSI2_CH0...CSI2_CH3:
+ cfe_dbg(cfe, "%s: [%s] %ux%u, V4L2 meta %p4cc\n", __func__,
+ node_desc[node->id].name, f->fmt.meta.width,
+ f->fmt.meta.height, &f->fmt.meta.dataformat);
+ break;
+ case FE_STATS:
+ case FE_CONFIG:
+ cfe_dbg(cfe, "%s: [%s] %u bytes, V4L2 meta %p4cc\n", __func__,
+ node_desc[node->id].name, f->fmt.meta.buffersize,
+ &f->fmt.meta.dataformat);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!node_supports_meta(node))
+ return -EINVAL;
+
+ switch (node->id) {
+ case CSI2_CH0...CSI2_CH3:
+ fmt = find_format_by_pix(f->fmt.meta.dataformat);
+ if (!fmt || !(fmt->flags & CFE_FORMAT_FLAG_META_CAP))
+ fmt = find_format_by_pix(V4L2_META_FMT_GENERIC_CSI2_10);
+
+ f->fmt.meta.dataformat = fmt->fourcc;
+
+ cfe_calc_meta_format_size_bpl(cfe, fmt, f);
+
+ return 0;
+ case FE_STATS:
+ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_STATS;
+ f->fmt.meta.buffersize = sizeof(struct pisp_statistics);
+ return 0;
+ case FE_CONFIG:
+ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_CFG;
+ f->fmt.meta.buffersize = sizeof(struct pisp_fe_config);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int cfe_g_fmt_meta(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ if (!node_supports_meta(node))
+ return -EINVAL;
+
+ *f = node->meta_fmt;
+
+ return 0;
+}
+
+static int cfe_s_fmt_meta(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+ struct vb2_queue *q = &node->buffer_queue;
+ int ret;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+
+ if (vb2_is_busy(q))
+ return -EBUSY;
+
+ if (!node_supports_meta(node))
+ return -EINVAL;
+
+ ret = cfe_validate_fmt_meta(node, f);
+ if (ret)
+ return ret;
+
+ node->meta_fmt = *f;
+
+ cfe_dbg(cfe, "%s: Set %p4cc\n", __func__,
+ &node->meta_fmt.fmt.meta.dataformat);
+
+ return 0;
+}
+
+static int cfe_try_fmt_meta(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+
+ cfe_dbg(cfe, "%s: [%s]\n", __func__, node_desc[node->id].name);
+ return cfe_validate_fmt_meta(node, f);
+}
+
+static int cfe_enum_framesizes(struct file *file, void *priv,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct cfe_node *node = video_drvdata(file);
+ struct cfe_device *cfe = node->cfe;
+ const struct cfe_fmt *fmt;
+
+ cfe_dbg(cfe, "%s [%s]\n", __func__, node_desc[node->id].name);
+
+ if (fsize->index > 0)
+ return -EINVAL;
+
+ /* check for valid format */
+ fmt = find_format_by_pix(fsize->pixel_format);
+ if (!fmt) {
+ cfe_dbg(cfe, "Invalid pixel code: %x\n", fsize->pixel_format);
+ return -EINVAL;
+ }
+
+ /* TODO: Do we have limits on the step_width? */
+
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise.min_width = MIN_WIDTH;
+ fsize->stepwise.max_width = MAX_WIDTH;
+ fsize->stepwise.step_width = 2;
+ fsize->stepwise.min_height = MIN_HEIGHT;
+ fsize->stepwise.max_height = MAX_HEIGHT;
+ fsize->stepwise.step_height = 1;
+
+ return 0;
+}
+
+static int cfe_vb2_ioctl_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *p)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cfe_node *node = video_get_drvdata(vdev);
+ struct cfe_device *cfe = node->cfe;
+ int ret;
+
+ cfe_dbg(cfe, "%s: [%s] type:%u\n", __func__, node_desc[node->id].name,
+ p->type);
+
+ if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ p->type != V4L2_BUF_TYPE_META_CAPTURE &&
+ p->type != V4L2_BUF_TYPE_META_OUTPUT)
+ return -EINVAL;
+
+ ret = vb2_queue_change_type(vdev->queue, p->type);
+ if (ret)
+ return ret;
+
+ return vb2_ioctl_reqbufs(file, priv, p);
+}
+
+static int cfe_vb2_ioctl_create_bufs(struct file *file, void *priv,
+ struct v4l2_create_buffers *p)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cfe_node *node = video_get_drvdata(vdev);
+ struct cfe_device *cfe = node->cfe;
+ int ret;
+
+ cfe_dbg(cfe, "%s: [%s] type:%u\n", __func__, node_desc[node->id].name,
+ p->format.type);
+
+ if (p->format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ p->format.type != V4L2_BUF_TYPE_META_CAPTURE &&
+ p->format.type != V4L2_BUF_TYPE_META_OUTPUT)
+ return -EINVAL;
+
+ ret = vb2_queue_change_type(vdev->queue, p->format.type);
+ if (ret)
+ return ret;
+
+ return vb2_ioctl_create_bufs(file, priv, p);
+}
+
+static int cfe_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
+ struct cfe_node *node = video_get_drvdata(fh->vdev);
+
+ switch (sub->type) {
+ case V4L2_EVENT_FRAME_SYNC:
+ if (!node_supports_image_output(node))
+ break;
+
+ return v4l2_event_subscribe(fh, sub, 2, NULL);
+ case V4L2_EVENT_SOURCE_CHANGE:
+ if (!node_supports_image_output(node) &&
+ !node_supports_meta_output(node))
+ break;
+
+ return v4l2_event_subscribe(fh, sub, 4, NULL);
+ }
+
+ return v4l2_ctrl_subscribe_event(fh, sub);
+}
+
+static const struct v4l2_ioctl_ops cfe_ioctl_ops = {
+ .vidioc_querycap = cfe_querycap,
+ .vidioc_enum_fmt_vid_cap = cfe_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = cfe_g_fmt,
+ .vidioc_s_fmt_vid_cap = cfe_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = cfe_try_fmt_vid_cap,
+
+ .vidioc_enum_fmt_meta_cap = cfe_enum_fmt_meta,
+ .vidioc_g_fmt_meta_cap = cfe_g_fmt_meta,
+ .vidioc_s_fmt_meta_cap = cfe_s_fmt_meta,
+ .vidioc_try_fmt_meta_cap = cfe_try_fmt_meta,
+
+ .vidioc_enum_fmt_meta_out = cfe_enum_fmt_meta,
+ .vidioc_g_fmt_meta_out = cfe_g_fmt_meta,
+ .vidioc_s_fmt_meta_out = cfe_s_fmt_meta,
+ .vidioc_try_fmt_meta_out = cfe_try_fmt_meta,
+
+ .vidioc_enum_framesizes = cfe_enum_framesizes,
+
+ .vidioc_reqbufs = cfe_vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = cfe_vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+
+ .vidioc_subscribe_event = cfe_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static void cfe_notify(struct v4l2_subdev *sd, unsigned int notification,
+ void *arg)
+{
+ struct cfe_device *cfe = to_cfe_device(sd->v4l2_dev);
+
+ switch (notification) {
+ case V4L2_DEVICE_NOTIFY_EVENT:
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ struct cfe_node *node = &cfe->node[i];
+
+ if (check_state(cfe, NODE_REGISTERED, i))
+ continue;
+
+ v4l2_event_queue(&node->video_dev, arg);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/* cfe capture driver file operations */
+static const struct v4l2_file_operations cfe_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .poll = vb2_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = vb2_fop_mmap,
+};
+
+static int cfe_video_link_validate(struct media_link *link)
+{
+ struct video_device *vd = container_of(link->sink->entity,
+ struct video_device, entity);
+ struct cfe_node *node = container_of(vd, struct cfe_node, video_dev);
+ struct cfe_device *cfe = node->cfe;
+ struct v4l2_mbus_framefmt *source_fmt;
+ struct v4l2_subdev_state *state;
+ struct v4l2_subdev *source_sd;
+ int ret = 0;
+
+ cfe_dbg(cfe, "%s: [%s] link \"%s\":%u -> \"%s\":%u\n", __func__,
+ node_desc[node->id].name,
+ link->source->entity->name, link->source->index,
+ link->sink->entity->name, link->sink->index);
+
+ if (!media_entity_remote_source_pad_unique(link->sink->entity)) {
+ cfe_err(cfe, "video node %s pad not connected\n", vd->name);
+ return -ENOTCONN;
+ }
+
+ source_sd = media_entity_to_v4l2_subdev(link->source->entity);
+
+ state = v4l2_subdev_lock_and_get_active_state(source_sd);
+
+ source_fmt = v4l2_subdev_state_get_format(state, link->source->index);
+ if (!source_fmt) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (is_image_output_node(node)) {
+ struct v4l2_pix_format *pix_fmt = &node->vid_fmt.fmt.pix;
+ const struct cfe_fmt *fmt;
+
+ if (source_fmt->width != pix_fmt->width ||
+ source_fmt->height != pix_fmt->height) {
+ cfe_err(cfe, "Wrong width or height %ux%u (remote pad set to %ux%u)\n",
+ pix_fmt->width, pix_fmt->height,
+ source_fmt->width, source_fmt->height);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ fmt = find_format_by_code_and_fourcc(source_fmt->code,
+ pix_fmt->pixelformat);
+ if (!fmt) {
+ cfe_err(cfe, "Format mismatch!\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ } else if (is_csi2_node(node) && is_meta_output_node(node)) {
+ struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta;
+ const struct cfe_fmt *fmt;
+
+ if (source_fmt->width != meta_fmt->width ||
+ source_fmt->height != meta_fmt->height) {
+ cfe_err(cfe, "Wrong width or height %ux%u (remote pad set to %ux%u)\n",
+ meta_fmt->width, meta_fmt->height,
+ source_fmt->width, source_fmt->height);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ fmt = find_format_by_code_and_fourcc(source_fmt->code,
+ meta_fmt->dataformat);
+ if (!fmt) {
+ cfe_err(cfe, "Format mismatch!\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+out:
+ v4l2_subdev_unlock_state(state);
+
+ return ret;
+}
+
+static const struct media_entity_operations cfe_media_entity_ops = {
+ .link_validate = cfe_video_link_validate,
+};
+
+static int cfe_video_link_notify(struct media_link *link, u32 flags,
+ unsigned int notification)
+{
+ struct media_device *mdev = link->graph_obj.mdev;
+ struct cfe_device *cfe = container_of(mdev, struct cfe_device, mdev);
+ struct media_entity *fe = &cfe->fe.sd.entity;
+ struct media_entity *csi2 = &cfe->csi2.sd.entity;
+ unsigned long lock_flags;
+
+ if (notification != MEDIA_DEV_NOTIFY_POST_LINK_CH)
+ return 0;
+
+ cfe_dbg(cfe, "%s: %s[%u] -> %s[%u] 0x%x", __func__,
+ link->source->entity->name, link->source->index,
+ link->sink->entity->name, link->sink->index, flags);
+
+ spin_lock_irqsave(&cfe->state_lock, lock_flags);
+
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ if (link->sink->entity != &cfe->node[i].video_dev.entity &&
+ link->source->entity != &cfe->node[i].video_dev.entity)
+ continue;
+
+ if (link->flags & MEDIA_LNK_FL_ENABLED)
+ set_state(cfe, NODE_ENABLED, i);
+ else
+ clear_state(cfe, NODE_ENABLED, i);
+
+ break;
+ }
+
+ spin_unlock_irqrestore(&cfe->state_lock, lock_flags);
+
+ if (link->source->entity != csi2)
+ return 0;
+ if (link->sink->entity != fe)
+ return 0;
+ if (link->sink->index != 0)
+ return 0;
+
+ cfe->fe_csi2_channel = -1;
+ if (link->flags & MEDIA_LNK_FL_ENABLED) {
+ if (link->source->index == node_desc[CSI2_CH0].link_pad)
+ cfe->fe_csi2_channel = CSI2_CH0;
+ else if (link->source->index == node_desc[CSI2_CH1].link_pad)
+ cfe->fe_csi2_channel = CSI2_CH1;
+ else if (link->source->index == node_desc[CSI2_CH2].link_pad)
+ cfe->fe_csi2_channel = CSI2_CH2;
+ else if (link->source->index == node_desc[CSI2_CH3].link_pad)
+ cfe->fe_csi2_channel = CSI2_CH3;
+ }
+
+ if (is_fe_enabled(cfe))
+ cfe_dbg(cfe, "%s: Found CSI2:%d -> FE:0 link\n", __func__,
+ cfe->fe_csi2_channel);
+ else
+ cfe_dbg(cfe, "%s: Unable to find CSI2:x -> FE:0 link\n",
+ __func__);
+
+ return 0;
+}
+
+static const struct media_device_ops cfe_media_device_ops = {
+ .link_notify = cfe_video_link_notify,
+};
+
+static void cfe_release(struct kref *kref)
+{
+ struct cfe_device *cfe = container_of(kref, struct cfe_device, kref);
+
+ media_device_cleanup(&cfe->mdev);
+
+ kfree(cfe);
+}
+
+static void cfe_put(struct cfe_device *cfe)
+{
+ kref_put(&cfe->kref, cfe_release);
+}
+
+static void cfe_get(struct cfe_device *cfe)
+{
+ kref_get(&cfe->kref);
+}
+
+static void cfe_node_release(struct video_device *vdev)
+{
+ struct cfe_node *node = video_get_drvdata(vdev);
+
+ cfe_put(node->cfe);
+}
+
+static int cfe_register_node(struct cfe_device *cfe, int id)
+{
+ struct video_device *vdev;
+ const struct cfe_fmt *fmt;
+ struct vb2_queue *q;
+ struct cfe_node *node = &cfe->node[id];
+ int ret;
+
+ node->cfe = cfe;
+ node->id = id;
+
+ if (node_supports_image(node)) {
+ if (node_supports_image_output(node))
+ node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ else
+ node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ fmt = find_format_by_code(cfe_default_format.code);
+ if (!fmt) {
+ cfe_err(cfe, "Failed to find format code\n");
+ return -EINVAL;
+ }
+
+ node->vid_fmt.fmt.pix.pixelformat = fmt->fourcc;
+ v4l2_fill_pix_format(&node->vid_fmt.fmt.pix,
+ &cfe_default_format);
+
+ ret = cfe_validate_fmt_vid_cap(node, &node->vid_fmt);
+ if (ret)
+ return ret;
+ }
+
+ if (node_supports_meta(node)) {
+ if (node_supports_meta_output(node))
+ node->meta_fmt.type = V4L2_BUF_TYPE_META_CAPTURE;
+ else
+ node->meta_fmt.type = V4L2_BUF_TYPE_META_OUTPUT;
+
+ ret = cfe_validate_fmt_meta(node, &node->meta_fmt);
+ if (ret)
+ return ret;
+ }
+
+ mutex_init(&node->lock);
+
+ q = &node->buffer_queue;
+ q->type = node_supports_image(node) ? node->vid_fmt.type :
+ node->meta_fmt.type;
+ q->io_modes = VB2_MMAP | VB2_DMABUF;
+ q->drv_priv = node;
+ q->ops = &cfe_video_qops;
+ q->mem_ops = &vb2_dma_contig_memops;
+ q->buf_struct_size = id == FE_CONFIG ? sizeof(struct cfe_config_buffer)
+ : sizeof(struct cfe_buffer);
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &node->lock;
+ q->min_queued_buffers = 1;
+ q->dev = &cfe->pdev->dev;
+
+ ret = vb2_queue_init(q);
+ if (ret) {
+ cfe_err(cfe, "vb2_queue_init() failed\n");
+ return ret;
+ }
+
+ INIT_LIST_HEAD(&node->dma_queue);
+
+ vdev = &node->video_dev;
+ vdev->release = cfe_node_release;
+ vdev->fops = &cfe_fops;
+ vdev->ioctl_ops = &cfe_ioctl_ops;
+ vdev->entity.ops = &cfe_media_entity_ops;
+ vdev->v4l2_dev = &cfe->v4l2_dev;
+ vdev->vfl_dir = (node_supports_image_output(node) ||
+ node_supports_meta_output(node)) ?
+ VFL_DIR_RX :
+ VFL_DIR_TX;
+ vdev->queue = q;
+ vdev->lock = &node->lock;
+ vdev->device_caps = node_desc[id].caps;
+ vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_IO_MC;
+
+ /* Define the device names */
+ snprintf(vdev->name, sizeof(vdev->name), "%s-%s", CFE_MODULE_NAME,
+ node_desc[id].name);
+
+ video_set_drvdata(vdev, node);
+ node->pad.flags = node_desc[id].pad_flags;
+ media_entity_pads_init(&vdev->entity, 1, &node->pad);
+
+ if (!node_supports_image(node)) {
+ v4l2_disable_ioctl(&node->video_dev,
+ VIDIOC_ENUM_FRAMEINTERVALS);
+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUM_FRAMESIZES);
+ }
+
+ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+ if (ret) {
+ cfe_err(cfe, "Unable to register video device %s\n",
+ vdev->name);
+ return ret;
+ }
+
+ cfe_info(cfe, "Registered [%s] node id %d as /dev/video%u\n",
+ vdev->name, id, vdev->num);
+
+ /*
+ * Acquire a reference to cfe, which will be released when the video
+ * device will be unregistered and userspace will have closed all open
+ * file handles.
+ */
+ cfe_get(cfe);
+ set_state(cfe, NODE_REGISTERED, id);
+
+ return 0;
+}
+
+static void cfe_unregister_nodes(struct cfe_device *cfe)
+{
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ struct cfe_node *node = &cfe->node[i];
+
+ if (check_state(cfe, NODE_REGISTERED, i)) {
+ clear_state(cfe, NODE_REGISTERED, i);
+ video_unregister_device(&node->video_dev);
+ }
+ }
+}
+
+static int cfe_link_node_pads(struct cfe_device *cfe)
+{
+ struct media_pad *remote_pad;
+ int ret;
+
+ /* Source -> CSI2 */
+
+ ret = v4l2_create_fwnode_links_to_pad(cfe->source_sd,
+ &cfe->csi2.pad[CSI2_PAD_SINK],
+ MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+
+ if (ret) {
+ cfe_err(cfe, "Failed to create links to the source: %d\n", ret);
+ return ret;
+ }
+
+ remote_pad = media_pad_remote_pad_unique(&cfe->csi2.pad[CSI2_PAD_SINK]);
+ if (IS_ERR(remote_pad)) {
+ ret = PTR_ERR(remote_pad);
+ cfe_err(cfe, "Failed to get unique remote source pad: %d\n",
+ ret);
+ return ret;
+ }
+
+ cfe->source_pad = remote_pad->index;
+
+ for (unsigned int i = 0; i < CSI2_NUM_CHANNELS; i++) {
+ struct cfe_node *node = &cfe->node[i];
+
+ if (!check_state(cfe, NODE_REGISTERED, i))
+ continue;
+
+ /* CSI2 channel # -> /dev/video# */
+ ret = media_create_pad_link(&cfe->csi2.sd.entity,
+ node_desc[i].link_pad,
+ &node->video_dev.entity, 0, 0);
+ if (ret)
+ return ret;
+
+ if (node_supports_image(node)) {
+ /* CSI2 channel # -> FE Input */
+ ret = media_create_pad_link(&cfe->csi2.sd.entity,
+ node_desc[i].link_pad,
+ &cfe->fe.sd.entity,
+ FE_STREAM_PAD, 0);
+ if (ret)
+ return ret;
+ }
+ }
+
+ for (unsigned int i = CSI2_NUM_CHANNELS; i < NUM_NODES; i++) {
+ struct cfe_node *node = &cfe->node[i];
+ struct media_entity *src, *dst;
+ unsigned int src_pad, dst_pad;
+
+ if (node_desc[i].pad_flags & MEDIA_PAD_FL_SINK) {
+ /* FE -> /dev/video# */
+ src = &cfe->fe.sd.entity;
+ src_pad = node_desc[i].link_pad;
+ dst = &node->video_dev.entity;
+ dst_pad = 0;
+ } else {
+ /* /dev/video# -> FE */
+ dst = &cfe->fe.sd.entity;
+ dst_pad = node_desc[i].link_pad;
+ src = &node->video_dev.entity;
+ src_pad = 0;
+ }
+
+ ret = media_create_pad_link(src, src_pad, dst, dst_pad, 0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cfe_probe_complete(struct cfe_device *cfe)
+{
+ int ret;
+
+ cfe->v4l2_dev.notify = cfe_notify;
+
+ for (unsigned int i = 0; i < NUM_NODES; i++) {
+ ret = cfe_register_node(cfe, i);
+ if (ret) {
+ cfe_err(cfe, "Unable to register video node %u.\n", i);
+ goto unregister;
+ }
+ }
+
+ ret = cfe_link_node_pads(cfe);
+ if (ret) {
+ cfe_err(cfe, "Unable to link node pads.\n");
+ goto unregister;
+ }
+
+ ret = v4l2_device_register_subdev_nodes(&cfe->v4l2_dev);
+ if (ret) {
+ cfe_err(cfe, "Unable to register subdev nodes.\n");
+ goto unregister;
+ }
+
+ return 0;
+
+unregister:
+ cfe_unregister_nodes(cfe);
+ return ret;
+}
+
+static int cfe_async_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *subdev,
+ struct v4l2_async_connection *asd)
+{
+ struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev);
+
+ if (cfe->source_sd) {
+ cfe_err(cfe, "Rejecting subdev %s (Already set!!)",
+ subdev->name);
+ return 0;
+ }
+
+ cfe->source_sd = subdev;
+
+ cfe_dbg(cfe, "Using source %s for capture\n", subdev->name);
+
+ return 0;
+}
+
+static int cfe_async_complete(struct v4l2_async_notifier *notifier)
+{
+ struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev);
+
+ return cfe_probe_complete(cfe);
+}
+
+static const struct v4l2_async_notifier_operations cfe_async_ops = {
+ .bound = cfe_async_bound,
+ .complete = cfe_async_complete,
+};
+
+static int cfe_register_async_nf(struct cfe_device *cfe)
+{
+ struct platform_device *pdev = cfe->pdev;
+ struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
+ struct fwnode_handle *local_ep_fwnode;
+ struct v4l2_async_connection *asd;
+ int ret;
+
+ local_ep_fwnode = fwnode_graph_get_endpoint_by_id(pdev->dev.fwnode, 0,
+ 0, 0);
+ if (!local_ep_fwnode) {
+ cfe_err(cfe, "Failed to find local endpoint fwnode\n");
+ return -ENODEV;
+ }
+
+ /* Parse the local endpoint and validate its configuration. */
+ ret = v4l2_fwnode_endpoint_parse(local_ep_fwnode, &ep);
+ if (ret) {
+ cfe_err(cfe, "Failed to find remote endpoint fwnode\n");
+ goto err_put_local_fwnode;
+ }
+
+ for (unsigned int lane = 0; lane < ep.bus.mipi_csi2.num_data_lanes;
+ lane++) {
+ if (ep.bus.mipi_csi2.data_lanes[lane] != lane + 1) {
+ cfe_err(cfe, "Data lanes reordering not supported\n");
+ ret = -EINVAL;
+ goto err_put_local_fwnode;
+ }
+ }
+
+ cfe->csi2.dphy.max_lanes = ep.bus.mipi_csi2.num_data_lanes;
+ cfe->csi2.bus_flags = ep.bus.mipi_csi2.flags;
+
+ /* Initialize and register the async notifier. */
+ v4l2_async_nf_init(&cfe->notifier, &cfe->v4l2_dev);
+ cfe->notifier.ops = &cfe_async_ops;
+
+ asd = v4l2_async_nf_add_fwnode_remote(&cfe->notifier, local_ep_fwnode,
+ struct v4l2_async_connection);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ cfe_err(cfe, "Error adding subdevice: %d\n", ret);
+ goto err_put_local_fwnode;
+ }
+
+ ret = v4l2_async_nf_register(&cfe->notifier);
+ if (ret) {
+ cfe_err(cfe, "Error registering async notifier: %d\n", ret);
+ goto err_nf_cleanup;
+ }
+
+ fwnode_handle_put(local_ep_fwnode);
+
+ return 0;
+
+err_nf_cleanup:
+ v4l2_async_nf_cleanup(&cfe->notifier);
+err_put_local_fwnode:
+ fwnode_handle_put(local_ep_fwnode);
+
+ return ret;
+}
+
+static int cfe_probe(struct platform_device *pdev)
+{
+ struct cfe_device *cfe;
+ char debugfs_name[32];
+ int ret;
+
+ cfe = kzalloc(sizeof(*cfe), GFP_KERNEL);
+ if (!cfe)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, cfe);
+
+ kref_init(&cfe->kref);
+ cfe->pdev = pdev;
+ cfe->fe_csi2_channel = -1;
+ spin_lock_init(&cfe->state_lock);
+
+ cfe->csi2.base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(cfe->csi2.base)) {
+ dev_err(&pdev->dev, "Failed to get dma io block\n");
+ ret = PTR_ERR(cfe->csi2.base);
+ goto err_cfe_put;
+ }
+
+ cfe->csi2.dphy.base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(cfe->csi2.dphy.base)) {
+ dev_err(&pdev->dev, "Failed to get host io block\n");
+ ret = PTR_ERR(cfe->csi2.dphy.base);
+ goto err_cfe_put;
+ }
+
+ cfe->mipi_cfg_base = devm_platform_ioremap_resource(pdev, 2);
+ if (IS_ERR(cfe->mipi_cfg_base)) {
+ dev_err(&pdev->dev, "Failed to get mipi cfg io block\n");
+ ret = PTR_ERR(cfe->mipi_cfg_base);
+ goto err_cfe_put;
+ }
+
+ cfe->fe.base = devm_platform_ioremap_resource(pdev, 3);
+ if (IS_ERR(cfe->fe.base)) {
+ dev_err(&pdev->dev, "Failed to get pisp fe io block\n");
+ ret = PTR_ERR(cfe->fe.base);
+ goto err_cfe_put;
+ }
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ ret = -EINVAL;
+ goto err_cfe_put;
+ }
+
+ ret = devm_request_irq(&pdev->dev, ret, cfe_isr, 0, "rp1-cfe", cfe);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to request interrupt\n");
+ ret = -EINVAL;
+ goto err_cfe_put;
+ }
+
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (ret) {
+ dev_err(&pdev->dev, "DMA enable failed\n");
+ goto err_cfe_put;
+ }
+
+ ret = vb2_dma_contig_set_max_seg_size(&pdev->dev, UINT_MAX);
+ if (ret)
+ goto err_cfe_put;
+
+ /* TODO: Enable clock only when running. */
+ cfe->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(cfe->clk)) {
+ ret = dev_err_probe(&pdev->dev, PTR_ERR(cfe->clk),
+ "clock not found\n");
+ goto err_cfe_put;
+ }
+
+ cfe->mdev.dev = &pdev->dev;
+ cfe->mdev.ops = &cfe_media_device_ops;
+ strscpy(cfe->mdev.model, CFE_MODULE_NAME, sizeof(cfe->mdev.model));
+ strscpy(cfe->mdev.serial, "", sizeof(cfe->mdev.serial));
+ snprintf(cfe->mdev.bus_info, sizeof(cfe->mdev.bus_info), "platform:%s",
+ dev_name(&pdev->dev));
+
+ media_device_init(&cfe->mdev);
+
+ cfe->v4l2_dev.mdev = &cfe->mdev;
+
+ ret = v4l2_device_register(&pdev->dev, &cfe->v4l2_dev);
+ if (ret) {
+ cfe_err(cfe, "Unable to register v4l2 device.\n");
+ goto err_cfe_put;
+ }
+
+ snprintf(debugfs_name, sizeof(debugfs_name), "rp1-cfe:%s",
+ dev_name(&pdev->dev));
+ cfe->debugfs = debugfs_create_dir(debugfs_name, NULL);
+ debugfs_create_file("regs", 0440, cfe->debugfs, cfe,
+ &mipi_cfg_regs_fops);
+
+ /* Enable the block power domain */
+ pm_runtime_enable(&pdev->dev);
+
+ ret = pm_runtime_resume_and_get(&cfe->pdev->dev);
+ if (ret)
+ goto err_runtime_disable;
+
+ cfe->csi2.v4l2_dev = &cfe->v4l2_dev;
+ ret = csi2_init(&cfe->csi2, cfe->debugfs);
+ if (ret) {
+ cfe_err(cfe, "Failed to init csi2 (%d)\n", ret);
+ goto err_runtime_put;
+ }
+
+ cfe->fe.v4l2_dev = &cfe->v4l2_dev;
+ ret = pisp_fe_init(&cfe->fe, cfe->debugfs);
+ if (ret) {
+ cfe_err(cfe, "Failed to init pisp fe (%d)\n", ret);
+ goto err_csi2_uninit;
+ }
+
+ cfe->mdev.hw_revision = cfe->fe.hw_revision;
+ ret = media_device_register(&cfe->mdev);
+ if (ret < 0) {
+ cfe_err(cfe, "Unable to register media-controller device.\n");
+ goto err_pisp_fe_uninit;
+ }
+
+ ret = cfe_register_async_nf(cfe);
+ if (ret) {
+ cfe_err(cfe, "Failed to connect subdevs\n");
+ goto err_media_unregister;
+ }
+
+ pm_runtime_put(&cfe->pdev->dev);
+
+ return 0;
+
+err_media_unregister:
+ media_device_unregister(&cfe->mdev);
+err_pisp_fe_uninit:
+ pisp_fe_uninit(&cfe->fe);
+err_csi2_uninit:
+ csi2_uninit(&cfe->csi2);
+err_runtime_put:
+ pm_runtime_put(&cfe->pdev->dev);
+err_runtime_disable:
+ pm_runtime_disable(&pdev->dev);
+ debugfs_remove(cfe->debugfs);
+ v4l2_device_unregister(&cfe->v4l2_dev);
+err_cfe_put:
+ cfe_put(cfe);
+
+ return ret;
+}
+
+static void cfe_remove(struct platform_device *pdev)
+{
+ struct cfe_device *cfe = platform_get_drvdata(pdev);
+
+ debugfs_remove(cfe->debugfs);
+
+ v4l2_async_nf_unregister(&cfe->notifier);
+ v4l2_async_nf_cleanup(&cfe->notifier);
+
+ media_device_unregister(&cfe->mdev);
+ cfe_unregister_nodes(cfe);
+
+ pisp_fe_uninit(&cfe->fe);
+ csi2_uninit(&cfe->csi2);
+
+ pm_runtime_disable(&pdev->dev);
+
+ v4l2_device_unregister(&cfe->v4l2_dev);
+
+ cfe_put(cfe);
+}
+
+static int cfe_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct cfe_device *cfe = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(cfe->clk);
+
+ return 0;
+}
+
+static int cfe_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct cfe_device *cfe = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = clk_prepare_enable(cfe->clk);
+ if (ret) {
+ dev_err(dev, "Unable to enable clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops cfe_pm_ops = {
+ SET_RUNTIME_PM_OPS(cfe_runtime_suspend, cfe_runtime_resume, NULL)
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+};
+
+static const struct of_device_id cfe_of_match[] = {
+ { .compatible = "raspberrypi,rp1-cfe" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, cfe_of_match);
+
+static struct platform_driver cfe_driver = {
+ .probe = cfe_probe,
+ .remove = cfe_remove,
+ .driver = {
+ .name = CFE_MODULE_NAME,
+ .of_match_table = cfe_of_match,
+ .pm = &cfe_pm_ops,
+ },
+};
+
+module_platform_driver(cfe_driver);
+
+MODULE_AUTHOR("Naushir Patuck <naush@raspberrypi.com>");
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
+MODULE_DESCRIPTION("Raspberry Pi RP1 Camera Front End driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CFE_VERSION);
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/cfe.h b/drivers/media/platform/raspberrypi/rp1-cfe/cfe.h
new file mode 100644
index 000000000000..c63cc314be3c
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/cfe.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RP1 CFE Driver
+ *
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ * Copyright (c) 2023-2024 Ideas on Board Oy
+ */
+#ifndef _RP1_CFE_
+#define _RP1_CFE_
+
+#include <linux/media-bus-format.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+extern bool cfe_debug_verbose;
+
+enum cfe_remap_types {
+ CFE_REMAP_16BIT,
+ CFE_REMAP_COMPRESSED,
+ CFE_NUM_REMAP,
+};
+
+#define CFE_FORMAT_FLAG_META_OUT BIT(0)
+#define CFE_FORMAT_FLAG_META_CAP BIT(1)
+#define CFE_FORMAT_FLAG_FE_OUT BIT(2)
+
+struct cfe_fmt {
+ u32 fourcc;
+ u32 code;
+ u8 depth;
+ u8 csi_dt;
+ u32 remap[CFE_NUM_REMAP];
+ u32 flags;
+};
+
+extern const struct v4l2_mbus_framefmt cfe_default_format;
+
+const struct cfe_fmt *find_format_by_code(u32 code);
+const struct cfe_fmt *find_format_by_pix(u32 pixelformat);
+u32 cfe_find_16bit_code(u32 code);
+u32 cfe_find_compressed_code(u32 code);
+
+#endif
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c
new file mode 100644
index 000000000000..35c2ab1e2cd4
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.c
@@ -0,0 +1,586 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RP1 CSI-2 Driver
+ *
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ * Copyright (c) 2023-2024 Ideas on Board Oy
+ */
+
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
+#include <linux/pm_runtime.h>
+#include <linux/seq_file.h>
+
+#include <media/videobuf2-dma-contig.h>
+
+#include "cfe.h"
+#include "csi2.h"
+
+#include "cfe-trace.h"
+
+static bool csi2_track_errors;
+module_param_named(track_csi2_errors, csi2_track_errors, bool, 0);
+MODULE_PARM_DESC(track_csi2_errors, "track csi-2 errors");
+
+#define csi2_dbg(csi2, fmt, arg...) dev_dbg((csi2)->v4l2_dev->dev, fmt, ##arg)
+#define csi2_err(csi2, fmt, arg...) dev_err((csi2)->v4l2_dev->dev, fmt, ##arg)
+
+/* CSI2-DMA registers */
+#define CSI2_STATUS 0x000
+#define CSI2_QOS 0x004
+#define CSI2_DISCARDS_OVERFLOW 0x008
+#define CSI2_DISCARDS_INACTIVE 0x00c
+#define CSI2_DISCARDS_UNMATCHED 0x010
+#define CSI2_DISCARDS_LEN_LIMIT 0x014
+
+#define CSI2_DISCARDS_AMOUNT_SHIFT 0
+#define CSI2_DISCARDS_AMOUNT_MASK GENMASK(23, 0)
+#define CSI2_DISCARDS_DT_SHIFT 24
+#define CSI2_DISCARDS_DT_MASK GENMASK(29, 24)
+#define CSI2_DISCARDS_VC_SHIFT 30
+#define CSI2_DISCARDS_VC_MASK GENMASK(31, 30)
+
+#define CSI2_LLEV_PANICS 0x018
+#define CSI2_ULEV_PANICS 0x01c
+#define CSI2_IRQ_MASK 0x020
+#define CSI2_IRQ_MASK_IRQ_OVERFLOW BIT(0)
+#define CSI2_IRQ_MASK_IRQ_DISCARD_OVERFLOW BIT(1)
+#define CSI2_IRQ_MASK_IRQ_DISCARD_LENGTH_LIMIT BIT(2)
+#define CSI2_IRQ_MASK_IRQ_DISCARD_UNMATCHED BIT(3)
+#define CSI2_IRQ_MASK_IRQ_DISCARD_INACTIVE BIT(4)
+#define CSI2_IRQ_MASK_IRQ_ALL \
+ (CSI2_IRQ_MASK_IRQ_OVERFLOW | CSI2_IRQ_MASK_IRQ_DISCARD_OVERFLOW | \
+ CSI2_IRQ_MASK_IRQ_DISCARD_LENGTH_LIMIT | \
+ CSI2_IRQ_MASK_IRQ_DISCARD_UNMATCHED | \
+ CSI2_IRQ_MASK_IRQ_DISCARD_INACTIVE)
+
+#define CSI2_CTRL 0x024
+#define CSI2_CH_CTRL(x) ((x) * 0x40 + 0x28)
+#define CSI2_CH_ADDR0(x) ((x) * 0x40 + 0x2c)
+#define CSI2_CH_ADDR1(x) ((x) * 0x40 + 0x3c)
+#define CSI2_CH_STRIDE(x) ((x) * 0x40 + 0x30)
+#define CSI2_CH_LENGTH(x) ((x) * 0x40 + 0x34)
+#define CSI2_CH_DEBUG(x) ((x) * 0x40 + 0x38)
+#define CSI2_CH_FRAME_SIZE(x) ((x) * 0x40 + 0x40)
+#define CSI2_CH_COMP_CTRL(x) ((x) * 0x40 + 0x44)
+#define CSI2_CH_FE_FRAME_ID(x) ((x) * 0x40 + 0x48)
+
+/* CSI2_STATUS */
+#define CSI2_STATUS_IRQ_FS(x) (BIT(0) << (x))
+#define CSI2_STATUS_IRQ_FE(x) (BIT(4) << (x))
+#define CSI2_STATUS_IRQ_FE_ACK(x) (BIT(8) << (x))
+#define CSI2_STATUS_IRQ_LE(x) (BIT(12) << (x))
+#define CSI2_STATUS_IRQ_LE_ACK(x) (BIT(16) << (x))
+#define CSI2_STATUS_IRQ_CH_MASK(x) \
+ (CSI2_STATUS_IRQ_FS(x) | CSI2_STATUS_IRQ_FE(x) | \
+ CSI2_STATUS_IRQ_FE_ACK(x) | CSI2_STATUS_IRQ_LE(x) | \
+ CSI2_STATUS_IRQ_LE_ACK(x))
+#define CSI2_STATUS_IRQ_OVERFLOW BIT(20)
+#define CSI2_STATUS_IRQ_DISCARD_OVERFLOW BIT(21)
+#define CSI2_STATUS_IRQ_DISCARD_LEN_LIMIT BIT(22)
+#define CSI2_STATUS_IRQ_DISCARD_UNMATCHED BIT(23)
+#define CSI2_STATUS_IRQ_DISCARD_INACTIVE BIT(24)
+
+/* CSI2_CTRL */
+#define CSI2_CTRL_EOP_IS_EOL BIT(0)
+
+/* CSI2_CH_CTRL */
+#define CSI2_CH_CTRL_DMA_EN BIT(0)
+#define CSI2_CH_CTRL_FORCE BIT(3)
+#define CSI2_CH_CTRL_AUTO_ARM BIT(4)
+#define CSI2_CH_CTRL_IRQ_EN_FS BIT(13)
+#define CSI2_CH_CTRL_IRQ_EN_FE BIT(14)
+#define CSI2_CH_CTRL_IRQ_EN_FE_ACK BIT(15)
+#define CSI2_CH_CTRL_IRQ_EN_LE BIT(16)
+#define CSI2_CH_CTRL_IRQ_EN_LE_ACK BIT(17)
+#define CSI2_CH_CTRL_FLUSH_FE BIT(28)
+#define CSI2_CH_CTRL_PACK_LINE BIT(29)
+#define CSI2_CH_CTRL_PACK_BYTES BIT(30)
+#define CSI2_CH_CTRL_CH_MODE_MASK GENMASK(2, 1)
+#define CSI2_CH_CTRL_VC_MASK GENMASK(6, 5)
+#define CSI2_CH_CTRL_DT_MASK GENMASK(12, 7)
+#define CSI2_CH_CTRL_LC_MASK GENMASK(27, 18)
+
+/* CHx_COMPRESSION_CONTROL */
+#define CSI2_CH_COMP_CTRL_OFFSET_MASK GENMASK(15, 0)
+#define CSI2_CH_COMP_CTRL_SHIFT_MASK GENMASK(19, 16)
+#define CSI2_CH_COMP_CTRL_MODE_MASK GENMASK(25, 24)
+
+static inline u32 csi2_reg_read(struct csi2_device *csi2, u32 offset)
+{
+ return readl(csi2->base + offset);
+}
+
+static inline void csi2_reg_write(struct csi2_device *csi2, u32 offset, u32 val)
+{
+ writel(val, csi2->base + offset);
+}
+
+static inline void set_field(u32 *valp, u32 field, u32 mask)
+{
+ u32 val = *valp;
+
+ val &= ~mask;
+ val |= (field << __ffs(mask)) & mask;
+ *valp = val;
+}
+
+static int csi2_regs_show(struct seq_file *s, void *data)
+{
+ struct csi2_device *csi2 = s->private;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(csi2->v4l2_dev->dev);
+ if (ret)
+ return ret;
+
+#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", csi2_reg_read(csi2, reg))
+#define DUMP_CH(idx, reg) seq_printf(s, #reg "(%u) \t0x%08x\n", idx, \
+ csi2_reg_read(csi2, reg(idx)))
+
+ DUMP(CSI2_STATUS);
+ DUMP(CSI2_DISCARDS_OVERFLOW);
+ DUMP(CSI2_DISCARDS_INACTIVE);
+ DUMP(CSI2_DISCARDS_UNMATCHED);
+ DUMP(CSI2_DISCARDS_LEN_LIMIT);
+ DUMP(CSI2_LLEV_PANICS);
+ DUMP(CSI2_ULEV_PANICS);
+ DUMP(CSI2_IRQ_MASK);
+ DUMP(CSI2_CTRL);
+
+ for (unsigned int i = 0; i < CSI2_NUM_CHANNELS; ++i) {
+ DUMP_CH(i, CSI2_CH_CTRL);
+ DUMP_CH(i, CSI2_CH_ADDR0);
+ DUMP_CH(i, CSI2_CH_ADDR1);
+ DUMP_CH(i, CSI2_CH_STRIDE);
+ DUMP_CH(i, CSI2_CH_LENGTH);
+ DUMP_CH(i, CSI2_CH_DEBUG);
+ DUMP_CH(i, CSI2_CH_FRAME_SIZE);
+ DUMP_CH(i, CSI2_CH_COMP_CTRL);
+ DUMP_CH(i, CSI2_CH_FE_FRAME_ID);
+ }
+
+#undef DUMP
+#undef DUMP_CH
+
+ pm_runtime_put(csi2->v4l2_dev->dev);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(csi2_regs);
+
+static int csi2_errors_show(struct seq_file *s, void *data)
+{
+ struct csi2_device *csi2 = s->private;
+ unsigned long flags;
+ u32 discards_table[DISCARDS_TABLE_NUM_VCS][DISCARDS_TABLE_NUM_ENTRIES];
+ u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES];
+ u32 overflows;
+
+ spin_lock_irqsave(&csi2->errors_lock, flags);
+
+ memcpy(discards_table, csi2->discards_table, sizeof(discards_table));
+ memcpy(discards_dt_table, csi2->discards_dt_table,
+ sizeof(discards_dt_table));
+ overflows = csi2->overflows;
+
+ csi2->overflows = 0;
+ memset(csi2->discards_table, 0, sizeof(discards_table));
+ memset(csi2->discards_dt_table, 0, sizeof(discards_dt_table));
+
+ spin_unlock_irqrestore(&csi2->errors_lock, flags);
+
+ seq_printf(s, "Overflows %u\n", overflows);
+ seq_puts(s, "Discards:\n");
+ seq_puts(s, "VC OVLF LEN UNMATCHED INACTIVE\n");
+
+ for (unsigned int vc = 0; vc < DISCARDS_TABLE_NUM_VCS; ++vc) {
+ seq_printf(s, "%u %10u %10u %10u %10u\n", vc,
+ discards_table[vc][DISCARDS_TABLE_OVERFLOW],
+ discards_table[vc][DISCARDS_TABLE_LENGTH_LIMIT],
+ discards_table[vc][DISCARDS_TABLE_UNMATCHED],
+ discards_table[vc][DISCARDS_TABLE_INACTIVE]);
+ }
+
+ seq_printf(s, "Last DT %10u %10u %10u %10u\n",
+ discards_dt_table[DISCARDS_TABLE_OVERFLOW],
+ discards_dt_table[DISCARDS_TABLE_LENGTH_LIMIT],
+ discards_dt_table[DISCARDS_TABLE_UNMATCHED],
+ discards_dt_table[DISCARDS_TABLE_INACTIVE]);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(csi2_errors);
+
+static void csi2_isr_handle_errors(struct csi2_device *csi2, u32 status)
+{
+ spin_lock(&csi2->errors_lock);
+
+ if (status & CSI2_STATUS_IRQ_OVERFLOW)
+ csi2->overflows++;
+
+ for (unsigned int i = 0; i < DISCARDS_TABLE_NUM_ENTRIES; ++i) {
+ static const u32 discard_bits[] = {
+ CSI2_STATUS_IRQ_DISCARD_OVERFLOW,
+ CSI2_STATUS_IRQ_DISCARD_LEN_LIMIT,
+ CSI2_STATUS_IRQ_DISCARD_UNMATCHED,
+ CSI2_STATUS_IRQ_DISCARD_INACTIVE,
+ };
+ static const u8 discard_regs[] = {
+ CSI2_DISCARDS_OVERFLOW,
+ CSI2_DISCARDS_LEN_LIMIT,
+ CSI2_DISCARDS_UNMATCHED,
+ CSI2_DISCARDS_INACTIVE,
+ };
+ u32 amount;
+ u8 dt, vc;
+ u32 v;
+
+ if (!(status & discard_bits[i]))
+ continue;
+
+ v = csi2_reg_read(csi2, discard_regs[i]);
+ csi2_reg_write(csi2, discard_regs[i], 0);
+
+ amount = (v & CSI2_DISCARDS_AMOUNT_MASK) >>
+ CSI2_DISCARDS_AMOUNT_SHIFT;
+ dt = (v & CSI2_DISCARDS_DT_MASK) >> CSI2_DISCARDS_DT_SHIFT;
+ vc = (v & CSI2_DISCARDS_VC_MASK) >> CSI2_DISCARDS_VC_SHIFT;
+
+ csi2->discards_table[vc][i] += amount;
+ csi2->discards_dt_table[i] = dt;
+ }
+
+ spin_unlock(&csi2->errors_lock);
+}
+
+void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof)
+{
+ u32 status;
+
+ status = csi2_reg_read(csi2, CSI2_STATUS);
+
+ /* Write value back to clear the interrupts */
+ csi2_reg_write(csi2, CSI2_STATUS, status);
+
+ for (unsigned int i = 0; i < CSI2_NUM_CHANNELS; i++) {
+ u32 dbg;
+
+ if ((status & CSI2_STATUS_IRQ_CH_MASK(i)) == 0)
+ continue;
+
+ dbg = csi2_reg_read(csi2, CSI2_CH_DEBUG(i));
+
+ trace_csi2_irq(i, status, dbg);
+
+ sof[i] = !!(status & CSI2_STATUS_IRQ_FS(i));
+ eof[i] = !!(status & CSI2_STATUS_IRQ_FE_ACK(i));
+ }
+
+ if (csi2_track_errors)
+ csi2_isr_handle_errors(csi2, status);
+}
+
+void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel,
+ dma_addr_t dmaaddr, unsigned int stride, unsigned int size)
+{
+ u64 addr = dmaaddr;
+ /*
+ * ADDRESS0 must be written last as it triggers the double buffering
+ * mechanism for all buffer registers within the hardware.
+ */
+ addr >>= 4;
+ csi2_reg_write(csi2, CSI2_CH_LENGTH(channel), size >> 4);
+ csi2_reg_write(csi2, CSI2_CH_STRIDE(channel), stride >> 4);
+ csi2_reg_write(csi2, CSI2_CH_ADDR1(channel), addr >> 32);
+ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), addr & 0xffffffff);
+}
+
+void csi2_set_compression(struct csi2_device *csi2, unsigned int channel,
+ enum csi2_compression_mode mode, unsigned int shift,
+ unsigned int offset)
+{
+ u32 compression = 0;
+
+ set_field(&compression, CSI2_CH_COMP_CTRL_OFFSET_MASK, offset);
+ set_field(&compression, CSI2_CH_COMP_CTRL_SHIFT_MASK, shift);
+ set_field(&compression, CSI2_CH_COMP_CTRL_MODE_MASK, mode);
+ csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression);
+}
+
+void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
+ enum csi2_mode mode, bool auto_arm, bool pack_bytes,
+ unsigned int width, unsigned int height,
+ u8 vc, u8 dt)
+{
+ u32 ctrl;
+
+ csi2_dbg(csi2, "%s [%u]\n", __func__, channel);
+
+ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0);
+ csi2_reg_write(csi2, CSI2_CH_DEBUG(channel), 0);
+ csi2_reg_write(csi2, CSI2_STATUS, CSI2_STATUS_IRQ_CH_MASK(channel));
+
+ /* Enable channel and FS/FE interrupts. */
+ ctrl = CSI2_CH_CTRL_DMA_EN | CSI2_CH_CTRL_IRQ_EN_FS |
+ CSI2_CH_CTRL_IRQ_EN_FE_ACK | CSI2_CH_CTRL_PACK_LINE;
+ /* PACK_BYTES ensures no striding for embedded data. */
+ if (pack_bytes)
+ ctrl |= CSI2_CH_CTRL_PACK_BYTES;
+
+ if (auto_arm)
+ ctrl |= CSI2_CH_CTRL_AUTO_ARM;
+
+ if (width && height) {
+ set_field(&ctrl, mode, CSI2_CH_CTRL_CH_MODE_MASK);
+ csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel),
+ (height << 16) | width);
+ } else {
+ set_field(&ctrl, 0x0, CSI2_CH_CTRL_CH_MODE_MASK);
+ csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0);
+ }
+
+ set_field(&ctrl, vc, CSI2_CH_CTRL_VC_MASK);
+ set_field(&ctrl, dt, CSI2_CH_CTRL_DT_MASK);
+ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl);
+ csi2->num_lines[channel] = height;
+}
+
+void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel)
+{
+ csi2_dbg(csi2, "%s [%u]\n", __func__, channel);
+
+ /* Channel disable. Use FORCE to allow stopping mid-frame. */
+ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), CSI2_CH_CTRL_FORCE);
+ /* Latch the above change by writing to the ADDR0 register. */
+ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0);
+ /* Write this again, the HW needs it! */
+ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0);
+}
+
+void csi2_open_rx(struct csi2_device *csi2)
+{
+ csi2_reg_write(csi2, CSI2_IRQ_MASK,
+ csi2_track_errors ? CSI2_IRQ_MASK_IRQ_ALL : 0);
+
+ dphy_start(&csi2->dphy);
+
+ csi2_reg_write(csi2, CSI2_CTRL, CSI2_CTRL_EOP_IS_EOL);
+}
+
+void csi2_close_rx(struct csi2_device *csi2)
+{
+ dphy_stop(&csi2->dphy);
+
+ csi2_reg_write(csi2, CSI2_IRQ_MASK, 0);
+}
+
+static int csi2_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct v4l2_subdev_route routes[] = { {
+ .sink_pad = CSI2_PAD_SINK,
+ .sink_stream = 0,
+ .source_pad = CSI2_PAD_FIRST_SOURCE,
+ .source_stream = 0,
+ .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+ } };
+
+ struct v4l2_subdev_krouting routing = {
+ .num_routes = ARRAY_SIZE(routes),
+ .routes = routes,
+ };
+
+ int ret;
+
+ ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
+ &cfe_default_format);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int csi2_pad_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *format)
+{
+ if (format->pad == CSI2_PAD_SINK) {
+ /* Store the sink format and propagate it to the source. */
+
+ const struct cfe_fmt *cfe_fmt;
+
+ cfe_fmt = find_format_by_code(format->format.code);
+ if (!cfe_fmt) {
+ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB10_1X10);
+ format->format.code = cfe_fmt->code;
+ }
+
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = v4l2_subdev_state_get_format(state, format->pad,
+ format->stream);
+ if (!fmt)
+ return -EINVAL;
+
+ *fmt = format->format;
+
+ fmt = v4l2_subdev_state_get_opposite_stream_format(state,
+ format->pad,
+ format->stream);
+ if (!fmt)
+ return -EINVAL;
+
+ format->format.field = V4L2_FIELD_NONE;
+
+ *fmt = format->format;
+ } else {
+ /* Only allow changing the source pad mbus code. */
+
+ struct v4l2_mbus_framefmt *sink_fmt, *source_fmt;
+ u32 sink_code;
+ u32 code;
+
+ sink_fmt = v4l2_subdev_state_get_opposite_stream_format(state,
+ format->pad,
+ format->stream);
+ if (!sink_fmt)
+ return -EINVAL;
+
+ source_fmt = v4l2_subdev_state_get_format(state, format->pad,
+ format->stream);
+ if (!source_fmt)
+ return -EINVAL;
+
+ sink_code = sink_fmt->code;
+ code = format->format.code;
+
+ /*
+ * Only allow changing the mbus code to:
+ * - The sink's mbus code
+ * - The 16-bit version of the sink's mbus code
+ * - The compressed version of the sink's mbus code
+ */
+ if (code == sink_code ||
+ code == cfe_find_16bit_code(sink_code) ||
+ code == cfe_find_compressed_code(sink_code))
+ source_fmt->code = code;
+
+ format->format.code = source_fmt->code;
+ }
+
+ return 0;
+}
+
+static int csi2_set_routing(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ enum v4l2_subdev_format_whence which,
+ struct v4l2_subdev_krouting *routing)
+{
+ int ret;
+
+ ret = v4l2_subdev_routing_validate(sd, routing,
+ V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 |
+ V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING);
+ if (ret)
+ return ret;
+
+ /* Only stream ID 0 allowed on source pads */
+ for (unsigned int i = 0; i < routing->num_routes; ++i) {
+ const struct v4l2_subdev_route *route = &routing->routes[i];
+
+ if (route->source_stream != 0)
+ return -EINVAL;
+ }
+
+ ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing,
+ &cfe_default_format);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_pad_ops csi2_subdev_pad_ops = {
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = csi2_pad_set_fmt,
+ .set_routing = csi2_set_routing,
+ .link_validate = v4l2_subdev_link_validate_default,
+};
+
+static const struct media_entity_operations csi2_entity_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+ .has_pad_interdep = v4l2_subdev_has_pad_interdep,
+};
+
+static const struct v4l2_subdev_ops csi2_subdev_ops = {
+ .pad = &csi2_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
+ .init_state = csi2_init_state,
+};
+
+int csi2_init(struct csi2_device *csi2, struct dentry *debugfs)
+{
+ unsigned int ret;
+
+ spin_lock_init(&csi2->errors_lock);
+
+ csi2->dphy.dev = csi2->v4l2_dev->dev;
+ dphy_probe(&csi2->dphy);
+
+ debugfs_create_file("csi2_regs", 0440, debugfs, csi2, &csi2_regs_fops);
+
+ if (csi2_track_errors)
+ debugfs_create_file("csi2_errors", 0440, debugfs, csi2,
+ &csi2_errors_fops);
+
+ csi2->pad[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+
+ for (unsigned int i = CSI2_PAD_FIRST_SOURCE;
+ i < CSI2_PAD_FIRST_SOURCE + CSI2_PAD_NUM_SOURCES; i++)
+ csi2->pad[i].flags = MEDIA_PAD_FL_SOURCE;
+
+ ret = media_entity_pads_init(&csi2->sd.entity, ARRAY_SIZE(csi2->pad),
+ csi2->pad);
+ if (ret)
+ return ret;
+
+ /* Initialize subdev */
+ v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops);
+ csi2->sd.internal_ops = &csi2_internal_ops;
+ csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+ csi2->sd.entity.ops = &csi2_entity_ops;
+ csi2->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
+ csi2->sd.owner = THIS_MODULE;
+ snprintf(csi2->sd.name, sizeof(csi2->sd.name), "csi2");
+
+ ret = v4l2_subdev_init_finalize(&csi2->sd);
+ if (ret)
+ goto err_entity_cleanup;
+
+ ret = v4l2_device_register_subdev(csi2->v4l2_dev, &csi2->sd);
+ if (ret) {
+ csi2_err(csi2, "Failed register csi2 subdev (%d)\n", ret);
+ goto err_subdev_cleanup;
+ }
+
+ return 0;
+
+err_subdev_cleanup:
+ v4l2_subdev_cleanup(&csi2->sd);
+err_entity_cleanup:
+ media_entity_cleanup(&csi2->sd.entity);
+
+ return ret;
+}
+
+void csi2_uninit(struct csi2_device *csi2)
+{
+ v4l2_device_unregister_subdev(&csi2->sd);
+ v4l2_subdev_cleanup(&csi2->sd);
+ media_entity_cleanup(&csi2->sd.entity);
+}
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/csi2.h b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.h
new file mode 100644
index 000000000000..a8ee5de565fb
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/csi2.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RP1 CSI-2 Driver
+ *
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ * Copyright (c) 2023-2024 Ideas on Board Oy
+ */
+
+#ifndef _RP1_CSI2_
+#define _RP1_CSI2_
+
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "dphy.h"
+
+#define CSI2_NUM_CHANNELS 4
+
+#define CSI2_PAD_SINK 0
+#define CSI2_PAD_FIRST_SOURCE 1
+#define CSI2_PAD_NUM_SOURCES 4
+#define CSI2_NUM_PADS 5
+
+#define DISCARDS_TABLE_NUM_VCS 4
+
+enum csi2_mode {
+ CSI2_MODE_NORMAL = 0,
+ CSI2_MODE_REMAP = 1,
+ CSI2_MODE_COMPRESSED = 2,
+ CSI2_MODE_FE_STREAMING = 3,
+};
+
+enum csi2_compression_mode {
+ CSI2_COMPRESSION_DELTA = 1,
+ CSI2_COMPRESSION_SIMPLE = 2,
+ CSI2_COMPRESSION_COMBINED = 3,
+};
+
+enum discards_table_index {
+ DISCARDS_TABLE_OVERFLOW = 0,
+ DISCARDS_TABLE_LENGTH_LIMIT,
+ DISCARDS_TABLE_UNMATCHED,
+ DISCARDS_TABLE_INACTIVE,
+ DISCARDS_TABLE_NUM_ENTRIES,
+};
+
+struct csi2_device {
+ /* Parent V4l2 device */
+ struct v4l2_device *v4l2_dev;
+
+ void __iomem *base;
+
+ struct dphy_data dphy;
+
+ enum v4l2_mbus_type bus_type;
+ unsigned int bus_flags;
+ unsigned int num_lines[CSI2_NUM_CHANNELS];
+
+ struct media_pad pad[CSI2_NUM_PADS];
+ struct v4l2_subdev sd;
+
+ /* lock for csi2 errors counters */
+ spinlock_t errors_lock;
+ u32 overflows;
+ u32 discards_table[DISCARDS_TABLE_NUM_VCS][DISCARDS_TABLE_NUM_ENTRIES];
+ u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES];
+};
+
+void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof);
+void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel,
+ dma_addr_t dmaaddr, unsigned int stride,
+ unsigned int size);
+void csi2_set_compression(struct csi2_device *csi2, unsigned int channel,
+ enum csi2_compression_mode mode, unsigned int shift,
+ unsigned int offset);
+void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
+ enum csi2_mode mode, bool auto_arm,
+ bool pack_bytes, unsigned int width,
+ unsigned int height, u8 vc, u8 dt);
+void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel);
+void csi2_open_rx(struct csi2_device *csi2);
+void csi2_close_rx(struct csi2_device *csi2);
+int csi2_init(struct csi2_device *csi2, struct dentry *debugfs);
+void csi2_uninit(struct csi2_device *csi2);
+
+#endif
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/dphy.c b/drivers/media/platform/raspberrypi/rp1-cfe/dphy.c
new file mode 100644
index 000000000000..b443f0f56ddc
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/dphy.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RP1 CSI-2 Driver
+ *
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ * Copyright (c) 2023-2024 Ideas on Board Oy
+ */
+
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+
+#include "dphy.h"
+
+#define dphy_dbg(dphy, fmt, arg...) dev_dbg((dphy)->dev, fmt, ##arg)
+#define dphy_err(dphy, fmt, arg...) dev_err((dphy)->dev, fmt, ##arg)
+
+/* DW dphy Host registers */
+#define DPHY_VERSION 0x000
+#define DPHY_N_LANES 0x004
+#define DPHY_RESETN 0x008
+#define DPHY_PHY_SHUTDOWNZ 0x040
+#define DPHY_PHY_RSTZ 0x044
+#define DPHY_PHY_RX 0x048
+#define DPHY_PHY_STOPSTATE 0x04c
+#define DPHY_PHY_TST_CTRL0 0x050
+#define DPHY_PHY_TST_CTRL1 0x054
+#define DPHY_PHY2_TST_CTRL0 0x058
+#define DPHY_PHY2_TST_CTRL1 0x05c
+
+/* DW dphy Host Transactions */
+#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44
+#define DPHY_PLL_INPUT_DIV_OFFSET 0x17
+#define DPHY_PLL_LOOP_DIV_OFFSET 0x18
+#define DPHY_PLL_DIV_CTRL_OFFSET 0x19
+
+static u32 dw_csi2_host_read(struct dphy_data *dphy, u32 offset)
+{
+ return readl(dphy->base + offset);
+}
+
+static void dw_csi2_host_write(struct dphy_data *dphy, u32 offset, u32 data)
+{
+ writel(data, dphy->base + offset);
+}
+
+static void set_tstclr(struct dphy_data *dphy, u32 val)
+{
+ u32 ctrl0 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL0);
+
+ dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL0, (ctrl0 & ~1) | val);
+}
+
+static void set_tstclk(struct dphy_data *dphy, u32 val)
+{
+ u32 ctrl0 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL0);
+
+ dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL0, (ctrl0 & ~2) | (val << 1));
+}
+
+static uint8_t get_tstdout(struct dphy_data *dphy)
+{
+ u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1);
+
+ return ((ctrl1 >> 8) & 0xff);
+}
+
+static void set_testen(struct dphy_data *dphy, u32 val)
+{
+ u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1);
+
+ dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL1,
+ (ctrl1 & ~(1 << 16)) | (val << 16));
+}
+
+static void set_testdin(struct dphy_data *dphy, u32 val)
+{
+ u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1);
+
+ dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL1, (ctrl1 & ~0xff) | val);
+}
+
+static uint8_t dphy_transaction(struct dphy_data *dphy, u8 test_code,
+ uint8_t test_data)
+{
+ /* See page 101 of the MIPI DPHY databook. */
+ set_tstclk(dphy, 1);
+ set_testen(dphy, 0);
+ set_testdin(dphy, test_code);
+ set_testen(dphy, 1);
+ set_tstclk(dphy, 0);
+ set_testen(dphy, 0);
+ set_testdin(dphy, test_data);
+ set_tstclk(dphy, 1);
+ return get_tstdout(dphy);
+}
+
+static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t mbps)
+{
+ /* See Table 5-1 on page 65 of dphy databook */
+ static const u16 hsfreqrange_table[][2] = {
+ { 89, 0b000000 }, { 99, 0b010000 }, { 109, 0b100000 },
+ { 129, 0b000001 }, { 139, 0b010001 }, { 149, 0b100001 },
+ { 169, 0b000010 }, { 179, 0b010010 }, { 199, 0b100010 },
+ { 219, 0b000011 }, { 239, 0b010011 }, { 249, 0b100011 },
+ { 269, 0b000100 }, { 299, 0b010100 }, { 329, 0b000101 },
+ { 359, 0b010101 }, { 399, 0b100101 }, { 449, 0b000110 },
+ { 499, 0b010110 }, { 549, 0b000111 }, { 599, 0b010111 },
+ { 649, 0b001000 }, { 699, 0b011000 }, { 749, 0b001001 },
+ { 799, 0b011001 }, { 849, 0b101001 }, { 899, 0b111001 },
+ { 949, 0b001010 }, { 999, 0b011010 }, { 1049, 0b101010 },
+ { 1099, 0b111010 }, { 1149, 0b001011 }, { 1199, 0b011011 },
+ { 1249, 0b101011 }, { 1299, 0b111011 }, { 1349, 0b001100 },
+ { 1399, 0b011100 }, { 1449, 0b101100 }, { 1500, 0b111100 },
+ };
+ unsigned int i;
+
+ if (mbps < 80 || mbps > 1500)
+ dphy_err(dphy, "DPHY: Datarate %u Mbps out of range\n", mbps);
+
+ for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) {
+ if (mbps <= hsfreqrange_table[i][0])
+ break;
+ }
+
+ dphy_transaction(dphy, DPHY_HS_RX_CTRL_LANE0_OFFSET,
+ hsfreqrange_table[i][1] << 1);
+}
+
+static void dphy_init(struct dphy_data *dphy)
+{
+ dw_csi2_host_write(dphy, DPHY_PHY_RSTZ, 0);
+ dw_csi2_host_write(dphy, DPHY_PHY_SHUTDOWNZ, 0);
+ set_tstclk(dphy, 1);
+ set_testen(dphy, 0);
+ set_tstclr(dphy, 1);
+ usleep_range(15, 20);
+ set_tstclr(dphy, 0);
+ usleep_range(15, 20);
+
+ dphy_set_hsfreqrange(dphy, dphy->dphy_rate);
+
+ usleep_range(5, 10);
+ dw_csi2_host_write(dphy, DPHY_PHY_SHUTDOWNZ, 1);
+ usleep_range(5, 10);
+ dw_csi2_host_write(dphy, DPHY_PHY_RSTZ, 1);
+}
+
+void dphy_start(struct dphy_data *dphy)
+{
+ dphy_dbg(dphy, "%s: Link rate %u Mbps, %u data lanes\n", __func__,
+ dphy->dphy_rate, dphy->active_lanes);
+
+ dw_csi2_host_write(dphy, DPHY_N_LANES, (dphy->active_lanes - 1));
+ dphy_init(dphy);
+ dw_csi2_host_write(dphy, DPHY_RESETN, 0xffffffff);
+ usleep_range(10, 50);
+}
+
+void dphy_stop(struct dphy_data *dphy)
+{
+ dphy_dbg(dphy, "%s\n", __func__);
+
+ /* Set only one lane (lane 0) as active (ON) */
+ dw_csi2_host_write(dphy, DPHY_N_LANES, 0);
+ dw_csi2_host_write(dphy, DPHY_RESETN, 0);
+}
+
+void dphy_probe(struct dphy_data *dphy)
+{
+ u32 host_ver;
+ u8 host_ver_major, host_ver_minor;
+
+ host_ver = dw_csi2_host_read(dphy, DPHY_VERSION);
+ host_ver_major = (u8)((host_ver >> 24) - '0');
+ host_ver_minor = (u8)((host_ver >> 16) - '0');
+ host_ver_minor = host_ver_minor * 10;
+ host_ver_minor += (u8)((host_ver >> 8) - '0');
+
+ dphy_dbg(dphy, "DW dphy Host HW v%u.%u\n", host_ver_major,
+ host_ver_minor);
+}
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/dphy.h b/drivers/media/platform/raspberrypi/rp1-cfe/dphy.h
new file mode 100644
index 000000000000..84fa370957cc
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/dphy.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ * Copyright (c) 2023-2024 Ideas on Board Oy
+ */
+
+#ifndef _RP1_DPHY_
+#define _RP1_DPHY_
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+struct dphy_data {
+ struct device *dev;
+
+ void __iomem *base;
+
+ u32 dphy_rate;
+ u32 max_lanes;
+ u32 active_lanes;
+};
+
+void dphy_probe(struct dphy_data *dphy);
+void dphy_start(struct dphy_data *dphy);
+void dphy_stop(struct dphy_data *dphy);
+
+#endif
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.c b/drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.c
new file mode 100644
index 000000000000..05762b1be2bc
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.c
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PiSP Front End Driver
+ *
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
+#include <linux/pm_runtime.h>
+#include <linux/seq_file.h>
+
+#include <media/videobuf2-dma-contig.h>
+
+#include "cfe.h"
+#include "pisp-fe.h"
+
+#include "cfe-trace.h"
+
+#define FE_VERSION 0x000
+#define FE_CONTROL 0x004
+#define FE_STATUS 0x008
+#define FE_FRAME_STATUS 0x00c
+#define FE_ERROR_STATUS 0x010
+#define FE_OUTPUT_STATUS 0x014
+#define FE_INT_EN 0x018
+#define FE_INT_STATUS 0x01c
+
+/* CONTROL */
+#define FE_CONTROL_QUEUE BIT(0)
+#define FE_CONTROL_ABORT BIT(1)
+#define FE_CONTROL_RESET BIT(2)
+#define FE_CONTROL_LATCH_REGS BIT(3)
+
+/* INT_EN / INT_STATUS */
+#define FE_INT_EOF BIT(0)
+#define FE_INT_SOF BIT(1)
+#define FE_INT_LINES0 BIT(8)
+#define FE_INT_LINES1 BIT(9)
+#define FE_INT_STATS BIT(16)
+#define FE_INT_QREADY BIT(24)
+
+/* STATUS */
+#define FE_STATUS_QUEUED BIT(0)
+#define FE_STATUS_WAITING BIT(1)
+#define FE_STATUS_ACTIVE BIT(2)
+
+#define PISP_FE_CONFIG_BASE_OFFSET 0x0040
+
+#define PISP_FE_ENABLE_STATS_CLUSTER \
+ (PISP_FE_ENABLE_STATS_CROP | PISP_FE_ENABLE_DECIMATE | \
+ PISP_FE_ENABLE_BLC | PISP_FE_ENABLE_CDAF_STATS | \
+ PISP_FE_ENABLE_AWB_STATS | PISP_FE_ENABLE_RGBY | \
+ PISP_FE_ENABLE_LSC | PISP_FE_ENABLE_AGC_STATS)
+
+#define PISP_FE_ENABLE_OUTPUT_CLUSTER(i) \
+ ((PISP_FE_ENABLE_CROP0 | PISP_FE_ENABLE_DOWNSCALE0 | \
+ PISP_FE_ENABLE_COMPRESS0 | PISP_FE_ENABLE_OUTPUT0) << (4 * (i)))
+
+struct pisp_fe_config_param {
+ u32 dirty_flags;
+ u32 dirty_flags_extra;
+ size_t offset;
+ size_t size;
+};
+
+static const struct pisp_fe_config_param pisp_fe_config_map[] = {
+ /* *_dirty_flag_extra types */
+ { 0, PISP_FE_DIRTY_GLOBAL,
+ offsetof(struct pisp_fe_config, global),
+ sizeof(struct pisp_fe_global_config) },
+ { 0, PISP_FE_DIRTY_FLOATING,
+ offsetof(struct pisp_fe_config, floating_stats),
+ sizeof(struct pisp_fe_floating_stats_config) },
+ { 0, PISP_FE_DIRTY_OUTPUT_AXI,
+ offsetof(struct pisp_fe_config, output_axi),
+ sizeof(struct pisp_fe_output_axi_config) },
+ /* *_dirty_flag types */
+ { PISP_FE_ENABLE_INPUT, 0,
+ offsetof(struct pisp_fe_config, input),
+ sizeof(struct pisp_fe_input_config) },
+ { PISP_FE_ENABLE_DECOMPRESS, 0,
+ offsetof(struct pisp_fe_config, decompress),
+ sizeof(struct pisp_decompress_config) },
+ { PISP_FE_ENABLE_DECOMPAND, 0,
+ offsetof(struct pisp_fe_config, decompand),
+ sizeof(struct pisp_fe_decompand_config) },
+ { PISP_FE_ENABLE_BLA, 0,
+ offsetof(struct pisp_fe_config, bla),
+ sizeof(struct pisp_bla_config) },
+ { PISP_FE_ENABLE_DPC, 0,
+ offsetof(struct pisp_fe_config, dpc),
+ sizeof(struct pisp_fe_dpc_config) },
+ { PISP_FE_ENABLE_STATS_CROP, 0,
+ offsetof(struct pisp_fe_config, stats_crop),
+ sizeof(struct pisp_fe_crop_config) },
+ { PISP_FE_ENABLE_BLC, 0,
+ offsetof(struct pisp_fe_config, blc),
+ sizeof(struct pisp_bla_config) },
+ { PISP_FE_ENABLE_CDAF_STATS, 0,
+ offsetof(struct pisp_fe_config, cdaf_stats),
+ sizeof(struct pisp_fe_cdaf_stats_config) },
+ { PISP_FE_ENABLE_AWB_STATS, 0,
+ offsetof(struct pisp_fe_config, awb_stats),
+ sizeof(struct pisp_fe_awb_stats_config) },
+ { PISP_FE_ENABLE_RGBY, 0,
+ offsetof(struct pisp_fe_config, rgby),
+ sizeof(struct pisp_fe_rgby_config) },
+ { PISP_FE_ENABLE_LSC, 0,
+ offsetof(struct pisp_fe_config, lsc),
+ sizeof(struct pisp_fe_lsc_config) },
+ { PISP_FE_ENABLE_AGC_STATS, 0,
+ offsetof(struct pisp_fe_config, agc_stats),
+ sizeof(struct pisp_agc_statistics) },
+ { PISP_FE_ENABLE_CROP0, 0,
+ offsetof(struct pisp_fe_config, ch[0].crop),
+ sizeof(struct pisp_fe_crop_config) },
+ { PISP_FE_ENABLE_DOWNSCALE0, 0,
+ offsetof(struct pisp_fe_config, ch[0].downscale),
+ sizeof(struct pisp_fe_downscale_config) },
+ { PISP_FE_ENABLE_COMPRESS0, 0,
+ offsetof(struct pisp_fe_config, ch[0].compress),
+ sizeof(struct pisp_compress_config) },
+ { PISP_FE_ENABLE_OUTPUT0, 0,
+ offsetof(struct pisp_fe_config, ch[0].output),
+ sizeof(struct pisp_fe_output_config) },
+ { PISP_FE_ENABLE_CROP1, 0,
+ offsetof(struct pisp_fe_config, ch[1].crop),
+ sizeof(struct pisp_fe_crop_config) },
+ { PISP_FE_ENABLE_DOWNSCALE1, 0,
+ offsetof(struct pisp_fe_config, ch[1].downscale),
+ sizeof(struct pisp_fe_downscale_config) },
+ { PISP_FE_ENABLE_COMPRESS1, 0,
+ offsetof(struct pisp_fe_config, ch[1].compress),
+ sizeof(struct pisp_compress_config) },
+ { PISP_FE_ENABLE_OUTPUT1, 0,
+ offsetof(struct pisp_fe_config, ch[1].output),
+ sizeof(struct pisp_fe_output_config) },
+};
+
+#define pisp_fe_dbg(fe, fmt, arg...) dev_dbg((fe)->v4l2_dev->dev, fmt, ##arg)
+#define pisp_fe_info(fe, fmt, arg...) dev_info((fe)->v4l2_dev->dev, fmt, ##arg)
+#define pisp_fe_err(fe, fmt, arg...) dev_err((fe)->v4l2_dev->dev, fmt, ##arg)
+
+static inline u32 pisp_fe_reg_read(struct pisp_fe_device *fe, u32 offset)
+{
+ return readl(fe->base + offset);
+}
+
+static inline void pisp_fe_reg_write(struct pisp_fe_device *fe, u32 offset,
+ u32 val)
+{
+ writel(val, fe->base + offset);
+}
+
+static inline void pisp_fe_reg_write_relaxed(struct pisp_fe_device *fe,
+ u32 offset, u32 val)
+{
+ writel_relaxed(val, fe->base + offset);
+}
+
+static int pisp_fe_regs_show(struct seq_file *s, void *data)
+{
+ struct pisp_fe_device *fe = s->private;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(fe->v4l2_dev->dev);
+ if (ret)
+ return ret;
+
+ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS);
+
+#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", pisp_fe_reg_read(fe, reg))
+ DUMP(FE_VERSION);
+ DUMP(FE_CONTROL);
+ DUMP(FE_STATUS);
+ DUMP(FE_FRAME_STATUS);
+ DUMP(FE_ERROR_STATUS);
+ DUMP(FE_OUTPUT_STATUS);
+ DUMP(FE_INT_EN);
+ DUMP(FE_INT_STATUS);
+#undef DUMP
+
+ pm_runtime_put(fe->v4l2_dev->dev);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(pisp_fe_regs);
+
+static void pisp_fe_config_write(struct pisp_fe_device *fe,
+ struct pisp_fe_config *config,
+ unsigned int start_offset, unsigned int size)
+{
+ const unsigned int max_offset =
+ offsetof(struct pisp_fe_config, ch[PISP_FE_NUM_OUTPUTS]);
+ unsigned int end_offset;
+ u32 *cfg = (u32 *)config;
+
+ start_offset = min(start_offset, max_offset);
+ end_offset = min(start_offset + size, max_offset);
+
+ cfg += start_offset >> 2;
+ for (unsigned int i = start_offset; i < end_offset; i += 4, cfg++)
+ pisp_fe_reg_write_relaxed(fe, PISP_FE_CONFIG_BASE_OFFSET + i,
+ *cfg);
+}
+
+void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof)
+{
+ u32 status, int_status, out_status, frame_status, error_status;
+
+ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS);
+ status = pisp_fe_reg_read(fe, FE_STATUS);
+ out_status = pisp_fe_reg_read(fe, FE_OUTPUT_STATUS);
+ frame_status = pisp_fe_reg_read(fe, FE_FRAME_STATUS);
+ error_status = pisp_fe_reg_read(fe, FE_ERROR_STATUS);
+
+ int_status = pisp_fe_reg_read(fe, FE_INT_STATUS);
+ pisp_fe_reg_write(fe, FE_INT_STATUS, int_status);
+
+ trace_fe_irq(status, out_status, frame_status, error_status,
+ int_status);
+
+ /* We do not report interrupts for the input/stream pad. */
+ for (unsigned int i = 0; i < FE_NUM_PADS - 1; i++) {
+ sof[i] = !!(int_status & FE_INT_SOF);
+ eof[i] = !!(int_status & FE_INT_EOF);
+ }
+}
+
+static bool pisp_fe_validate_output(struct pisp_fe_config const *cfg,
+ unsigned int c, struct v4l2_format const *f)
+{
+ unsigned int wbytes;
+
+ wbytes = cfg->ch[c].output.format.width;
+ if (cfg->ch[c].output.format.format & PISP_IMAGE_FORMAT_BPS_MASK)
+ wbytes *= 2;
+
+ /* Check output image dimensions are nonzero and not too big */
+ if (cfg->ch[c].output.format.width < 2 ||
+ cfg->ch[c].output.format.height < 2 ||
+ cfg->ch[c].output.format.height > f->fmt.pix.height ||
+ cfg->ch[c].output.format.stride > f->fmt.pix.bytesperline ||
+ wbytes > f->fmt.pix.bytesperline)
+ return false;
+
+ /* Check for zero-sized crops, which could cause lockup */
+ if ((cfg->global.enables & PISP_FE_ENABLE_CROP(c)) &&
+ ((cfg->ch[c].crop.offset_x >= (cfg->input.format.width & ~1) ||
+ cfg->ch[c].crop.offset_y >= cfg->input.format.height ||
+ cfg->ch[c].crop.width < 2 || cfg->ch[c].crop.height < 2)))
+ return false;
+
+ if ((cfg->global.enables & PISP_FE_ENABLE_DOWNSCALE(c)) &&
+ (cfg->ch[c].downscale.output_width < 2 ||
+ cfg->ch[c].downscale.output_height < 2))
+ return false;
+
+ return true;
+}
+
+static bool pisp_fe_validate_stats(struct pisp_fe_config const *cfg)
+{
+ /* Check for zero-sized crop, which could cause lockup */
+ return (!(cfg->global.enables & PISP_FE_ENABLE_STATS_CROP) ||
+ (cfg->stats_crop.offset_x < (cfg->input.format.width & ~1) &&
+ cfg->stats_crop.offset_y < cfg->input.format.height &&
+ cfg->stats_crop.width >= 2 && cfg->stats_crop.height >= 2));
+}
+
+int pisp_fe_validate_config(struct pisp_fe_device *fe,
+ struct pisp_fe_config *cfg,
+ struct v4l2_format const *f0,
+ struct v4l2_format const *f1)
+{
+ /*
+ * Check the input is enabled, streaming and has nonzero size;
+ * to avoid cases where the hardware might lock up or try to
+ * read inputs from memory (which this driver doesn't support).
+ */
+ if (!(cfg->global.enables & PISP_FE_ENABLE_INPUT) ||
+ cfg->input.streaming != 1 || cfg->input.format.width < 2 ||
+ cfg->input.format.height < 2) {
+ pisp_fe_err(fe, "%s: Input config not valid", __func__);
+ return -EINVAL;
+ }
+
+ for (unsigned int i = 0; i < PISP_FE_NUM_OUTPUTS; i++) {
+ if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) {
+ if (cfg->global.enables &
+ PISP_FE_ENABLE_OUTPUT_CLUSTER(i)) {
+ pisp_fe_err(fe, "%s: Output %u not valid",
+ __func__, i);
+ return -EINVAL;
+ }
+ continue;
+ }
+
+ if (!pisp_fe_validate_output(cfg, i, i ? f1 : f0))
+ return -EINVAL;
+ }
+
+ if ((cfg->global.enables & PISP_FE_ENABLE_STATS_CLUSTER) &&
+ !pisp_fe_validate_stats(cfg)) {
+ pisp_fe_err(fe, "%s: Stats config not valid", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs,
+ struct pisp_fe_config *cfg)
+{
+ u64 addr;
+ u32 status;
+
+ /*
+ * Check output buffers exist and outputs are correctly configured.
+ * If valid, set the buffer's DMA address; otherwise disable.
+ */
+ for (unsigned int i = 0; i < PISP_FE_NUM_OUTPUTS; i++) {
+ struct vb2_buffer *buf = vb2_bufs[FE_OUTPUT0_PAD + i];
+
+ if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i)))
+ continue;
+
+ addr = vb2_dma_contig_plane_dma_addr(buf, 0);
+ cfg->output_buffer[i].addr_lo = addr & 0xffffffff;
+ cfg->output_buffer[i].addr_hi = addr >> 32;
+ }
+
+ if (vb2_bufs[FE_STATS_PAD]) {
+ addr = vb2_dma_contig_plane_dma_addr(vb2_bufs[FE_STATS_PAD], 0);
+ cfg->stats_buffer.addr_lo = addr & 0xffffffff;
+ cfg->stats_buffer.addr_hi = addr >> 32;
+ }
+
+ /* Set up ILINES interrupts 3/4 of the way down each output */
+ cfg->ch[0].output.ilines =
+ max(0x80u, (3u * cfg->ch[0].output.format.height) >> 2);
+ cfg->ch[1].output.ilines =
+ max(0x80u, (3u * cfg->ch[1].output.format.height) >> 2);
+
+ /*
+ * The hardware must have consumed the previous config by now.
+ * This read of status also serves as a memory barrier before the
+ * sequence of relaxed writes which follow.
+ */
+ status = pisp_fe_reg_read(fe, FE_STATUS);
+ if (WARN_ON(status & FE_STATUS_QUEUED))
+ return;
+
+ /*
+ * Unconditionally write buffers, global and input parameters.
+ * Write cropping and output parameters whenever they are enabled.
+ * Selectively write other parameters that have been marked as
+ * changed through the dirty flags.
+ */
+ pisp_fe_config_write(fe, cfg, 0,
+ offsetof(struct pisp_fe_config, decompress));
+ cfg->dirty_flags_extra &= ~PISP_FE_DIRTY_GLOBAL;
+ cfg->dirty_flags &= ~PISP_FE_ENABLE_INPUT;
+ cfg->dirty_flags |= (cfg->global.enables &
+ (PISP_FE_ENABLE_STATS_CROP |
+ PISP_FE_ENABLE_OUTPUT_CLUSTER(0) |
+ PISP_FE_ENABLE_OUTPUT_CLUSTER(1)));
+ for (unsigned int i = 0; i < ARRAY_SIZE(pisp_fe_config_map); i++) {
+ const struct pisp_fe_config_param *p = &pisp_fe_config_map[i];
+
+ if (cfg->dirty_flags & p->dirty_flags ||
+ cfg->dirty_flags_extra & p->dirty_flags_extra)
+ pisp_fe_config_write(fe, cfg, p->offset, p->size);
+ }
+
+ /* This final non-relaxed write serves as a memory barrier */
+ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_QUEUE);
+}
+
+void pisp_fe_start(struct pisp_fe_device *fe)
+{
+ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_RESET);
+ pisp_fe_reg_write(fe, FE_INT_STATUS, ~0);
+ pisp_fe_reg_write(fe, FE_INT_EN, FE_INT_EOF | FE_INT_SOF |
+ FE_INT_LINES0 | FE_INT_LINES1);
+ fe->inframe_count = 0;
+}
+
+void pisp_fe_stop(struct pisp_fe_device *fe)
+{
+ pisp_fe_reg_write(fe, FE_INT_EN, 0);
+ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_ABORT);
+ usleep_range(1000, 2000);
+ WARN_ON(pisp_fe_reg_read(fe, FE_STATUS));
+ pisp_fe_reg_write(fe, FE_INT_STATUS, ~0);
+}
+
+static int pisp_fe_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_STREAM_PAD);
+ *fmt = cfe_default_format;
+ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_CONFIG_PAD);
+ fmt->code = MEDIA_BUS_FMT_FIXED;
+ fmt->width = sizeof(struct pisp_fe_config);
+ fmt->height = 1;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT0_PAD);
+ *fmt = cfe_default_format;
+ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT1_PAD);
+ *fmt = cfe_default_format;
+ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_STATS_PAD);
+ fmt->code = MEDIA_BUS_FMT_FIXED;
+ fmt->width = sizeof(struct pisp_statistics);
+ fmt->height = 1;
+
+ return 0;
+}
+
+static int pisp_fe_pad_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *fmt;
+ const struct cfe_fmt *cfe_fmt;
+
+ /* TODO: format propagation to source pads */
+ /* TODO: format validation */
+
+ switch (format->pad) {
+ case FE_STREAM_PAD:
+ cfe_fmt = find_format_by_code(format->format.code);
+ if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT))
+ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16);
+
+ format->format.code = cfe_fmt->code;
+ format->format.field = V4L2_FIELD_NONE;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_STREAM_PAD);
+ *fmt = format->format;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT0_PAD);
+ *fmt = format->format;
+
+ fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT1_PAD);
+ *fmt = format->format;
+
+ return 0;
+
+ case FE_OUTPUT0_PAD:
+ case FE_OUTPUT1_PAD: {
+ /*
+ * TODO: we should allow scaling and cropping by allowing the
+ * user to set the size here.
+ */
+ struct v4l2_mbus_framefmt *sink_fmt, *source_fmt;
+ u32 sink_code;
+ u32 code;
+
+ cfe_fmt = find_format_by_code(format->format.code);
+ if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT))
+ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16);
+
+ format->format.code = cfe_fmt->code;
+
+ sink_fmt = v4l2_subdev_state_get_format(state, FE_STREAM_PAD);
+ if (!sink_fmt)
+ return -EINVAL;
+
+ source_fmt = v4l2_subdev_state_get_format(state, format->pad);
+ if (!source_fmt)
+ return -EINVAL;
+
+ sink_code = sink_fmt->code;
+ code = format->format.code;
+
+ /*
+ * If the source code from the user does not match the code in
+ * the sink pad, check that the source code matches the
+ * compressed version of the sink code.
+ */
+
+ if (code != sink_code &&
+ code == cfe_find_compressed_code(sink_code))
+ source_fmt->code = code;
+
+ return 0;
+ }
+
+ case FE_CONFIG_PAD:
+ case FE_STATS_PAD:
+ default:
+ return v4l2_subdev_get_fmt(sd, state, format);
+ }
+}
+
+static const struct v4l2_subdev_pad_ops pisp_fe_subdev_pad_ops = {
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = pisp_fe_pad_set_fmt,
+ .link_validate = v4l2_subdev_link_validate_default,
+};
+
+static int pisp_fe_link_validate(struct media_link *link)
+{
+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(link->sink->entity);
+ struct pisp_fe_device *fe = container_of(sd, struct pisp_fe_device, sd);
+
+ pisp_fe_dbg(fe, "%s: link \"%s\":%u -> \"%s\":%u\n", __func__,
+ link->source->entity->name, link->source->index,
+ link->sink->entity->name, link->sink->index);
+
+ if (link->sink->index == FE_STREAM_PAD)
+ return v4l2_subdev_link_validate(link);
+
+ if (link->sink->index == FE_CONFIG_PAD)
+ return 0;
+
+ return -EINVAL;
+}
+
+static const struct media_entity_operations pisp_fe_entity_ops = {
+ .link_validate = pisp_fe_link_validate,
+};
+
+static const struct v4l2_subdev_ops pisp_fe_subdev_ops = {
+ .pad = &pisp_fe_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops pisp_fe_internal_ops = {
+ .init_state = pisp_fe_init_state,
+};
+
+int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs)
+{
+ int ret;
+
+ debugfs_create_file("fe_regs", 0440, debugfs, fe, &pisp_fe_regs_fops);
+
+ fe->hw_revision = pisp_fe_reg_read(fe, FE_VERSION);
+ pisp_fe_info(fe, "PiSP FE HW v%u.%u\n",
+ (fe->hw_revision >> 24) & 0xff,
+ (fe->hw_revision >> 20) & 0x0f);
+
+ fe->pad[FE_STREAM_PAD].flags =
+ MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
+ fe->pad[FE_CONFIG_PAD].flags = MEDIA_PAD_FL_SINK;
+ fe->pad[FE_OUTPUT0_PAD].flags = MEDIA_PAD_FL_SOURCE;
+ fe->pad[FE_OUTPUT1_PAD].flags = MEDIA_PAD_FL_SOURCE;
+ fe->pad[FE_STATS_PAD].flags = MEDIA_PAD_FL_SOURCE;
+
+ ret = media_entity_pads_init(&fe->sd.entity, ARRAY_SIZE(fe->pad),
+ fe->pad);
+ if (ret)
+ return ret;
+
+ /* Initialize subdev */
+ v4l2_subdev_init(&fe->sd, &pisp_fe_subdev_ops);
+ fe->sd.internal_ops = &pisp_fe_internal_ops;
+ fe->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
+ fe->sd.entity.ops = &pisp_fe_entity_ops;
+ fe->sd.entity.name = "pisp-fe";
+ fe->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+ fe->sd.owner = THIS_MODULE;
+ snprintf(fe->sd.name, sizeof(fe->sd.name), "pisp-fe");
+
+ ret = v4l2_subdev_init_finalize(&fe->sd);
+ if (ret)
+ goto err_entity_cleanup;
+
+ ret = v4l2_device_register_subdev(fe->v4l2_dev, &fe->sd);
+ if (ret) {
+ pisp_fe_err(fe, "Failed register pisp fe subdev (%d)\n", ret);
+ goto err_subdev_cleanup;
+ }
+
+ /* Must be in IDLE state (STATUS == 0) here. */
+ WARN_ON(pisp_fe_reg_read(fe, FE_STATUS));
+
+ return 0;
+
+err_subdev_cleanup:
+ v4l2_subdev_cleanup(&fe->sd);
+err_entity_cleanup:
+ media_entity_cleanup(&fe->sd.entity);
+
+ return ret;
+}
+
+void pisp_fe_uninit(struct pisp_fe_device *fe)
+{
+ v4l2_device_unregister_subdev(&fe->sd);
+ v4l2_subdev_cleanup(&fe->sd);
+ media_entity_cleanup(&fe->sd.entity);
+}
diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.h b/drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.h
new file mode 100644
index 000000000000..54d506e19cf2
--- /dev/null
+++ b/drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PiSP Front End Driver
+ *
+ * Copyright (c) 2021-2024 Raspberry Pi Ltd.
+ */
+#ifndef _PISP_FE_H_
+#define _PISP_FE_H_
+
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include <linux/media/raspberrypi/pisp_fe_config.h>
+
+enum pisp_fe_pads {
+ FE_STREAM_PAD,
+ FE_CONFIG_PAD,
+ FE_OUTPUT0_PAD,
+ FE_OUTPUT1_PAD,
+ FE_STATS_PAD,
+ FE_NUM_PADS
+};
+
+struct pisp_fe_device {
+ /* Parent V4l2 device */
+ struct v4l2_device *v4l2_dev;
+ void __iomem *base;
+ u32 hw_revision;
+
+ u16 inframe_count;
+ struct media_pad pad[FE_NUM_PADS];
+ struct v4l2_subdev sd;
+};
+
+void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof);
+int pisp_fe_validate_config(struct pisp_fe_device *fe,
+ struct pisp_fe_config *cfg,
+ struct v4l2_format const *f0,
+ struct v4l2_format const *f1);
+void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs,
+ struct pisp_fe_config *cfg);
+void pisp_fe_start(struct pisp_fe_device *fe);
+void pisp_fe_stop(struct pisp_fe_device *fe);
+int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs);
+void pisp_fe_uninit(struct pisp_fe_device *fe);
+
+#endif
diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
index c419ddb4c5a2..27ffdd28cbf7 100644
--- a/drivers/media/platform/renesas/rcar-csi2.c
+++ b/drivers/media/platform/renesas/rcar-csi2.c
@@ -135,13 +135,23 @@ struct rcar_csi2;
/* V4H BASE registers */
#define V4H_N_LANES_REG 0x0004
#define V4H_CSI2_RESETN_REG 0x0008
+
#define V4H_PHY_MODE_REG 0x001c
+#define V4H_PHY_MODE_DPHY 0
+#define V4H_PHY_MODE_CPHY 1
+
#define V4H_PHY_SHUTDOWNZ_REG 0x0040
#define V4H_DPHY_RSTZ_REG 0x0044
#define V4H_FLDC_REG 0x0804
#define V4H_FLDD_REG 0x0808
#define V4H_IDIC_REG 0x0810
+
#define V4H_PHY_EN_REG 0x2000
+#define V4H_PHY_EN_ENABLE_3 BIT(7)
+#define V4H_PHY_EN_ENABLE_2 BIT(6)
+#define V4H_PHY_EN_ENABLE_1 BIT(5)
+#define V4H_PHY_EN_ENABLE_0 BIT(4)
+#define V4H_PHY_EN_ENABLE_CLK BIT(0)
#define V4H_ST_PHYST_REG 0x2814
#define V4H_ST_PHYST_ST_PHY_READY BIT(31)
@@ -237,17 +247,37 @@ static const struct rcsi2_cphy_setting cphy_setting_table_r8a779g0[] = {
{ /* sentinel */ },
};
+/* V4M registers */
+#define V4M_OVR1_REG 0x0848
+#define V4M_OVR1_FORCERXMODE_3 BIT(12)
+#define V4M_OVR1_FORCERXMODE_2 BIT(11)
+#define V4M_OVR1_FORCERXMODE_1 BIT(10)
+#define V4M_OVR1_FORCERXMODE_0 BIT(9)
+
+#define V4M_FRXM_REG 0x2004
+#define V4M_FRXM_FORCERXMODE_3 BIT(3)
+#define V4M_FRXM_FORCERXMODE_2 BIT(2)
+#define V4M_FRXM_FORCERXMODE_1 BIT(1)
+#define V4M_FRXM_FORCERXMODE_0 BIT(0)
+
+#define V4M_PHYPLL_REG 0x02050
+#define V4M_CSI0CLKFCPR_REG 0x02054
+#define V4M_PHTW_REG 0x02060
+#define V4M_PHTR_REG 0x02064
+#define V4M_PHTC_REG 0x02068
+
struct phtw_value {
- u16 data;
- u16 code;
+ u8 data;
+ u8 code;
};
-struct rcsi2_mbps_reg {
+struct rcsi2_mbps_info {
u16 mbps;
- u16 reg;
+ u8 reg;
+ u16 osc_freq; /* V4M */
};
-static const struct rcsi2_mbps_reg phtw_mbps_v3u[] = {
+static const struct rcsi2_mbps_info phtw_mbps_v3u[] = {
{ .mbps = 1500, .reg = 0xcc },
{ .mbps = 1550, .reg = 0x1d },
{ .mbps = 1600, .reg = 0x27 },
@@ -272,7 +302,7 @@ static const struct rcsi2_mbps_reg phtw_mbps_v3u[] = {
{ /* sentinel */ },
};
-static const struct rcsi2_mbps_reg phtw_mbps_h3_v3h_m3n[] = {
+static const struct rcsi2_mbps_info phtw_mbps_h3_v3h_m3n[] = {
{ .mbps = 80, .reg = 0x86 },
{ .mbps = 90, .reg = 0x86 },
{ .mbps = 100, .reg = 0x87 },
@@ -292,7 +322,7 @@ static const struct rcsi2_mbps_reg phtw_mbps_h3_v3h_m3n[] = {
{ /* sentinel */ },
};
-static const struct rcsi2_mbps_reg phtw_mbps_v3m_e3[] = {
+static const struct rcsi2_mbps_info phtw_mbps_v3m_e3[] = {
{ .mbps = 80, .reg = 0x00 },
{ .mbps = 90, .reg = 0x20 },
{ .mbps = 100, .reg = 0x40 },
@@ -336,7 +366,7 @@ static const struct rcsi2_mbps_reg phtw_mbps_v3m_e3[] = {
#define PHYPLL_REG 0x68
#define PHYPLL_HSFREQRANGE(n) ((n) << 16)
-static const struct rcsi2_mbps_reg hsfreqrange_v3u[] = {
+static const struct rcsi2_mbps_info hsfreqrange_v3u[] = {
{ .mbps = 80, .reg = 0x00 },
{ .mbps = 90, .reg = 0x10 },
{ .mbps = 100, .reg = 0x20 },
@@ -402,7 +432,7 @@ static const struct rcsi2_mbps_reg hsfreqrange_v3u[] = {
{ /* sentinel */ },
};
-static const struct rcsi2_mbps_reg hsfreqrange_h3_v3h_m3n[] = {
+static const struct rcsi2_mbps_info hsfreqrange_h3_v3h_m3n[] = {
{ .mbps = 80, .reg = 0x00 },
{ .mbps = 90, .reg = 0x10 },
{ .mbps = 100, .reg = 0x20 },
@@ -449,7 +479,7 @@ static const struct rcsi2_mbps_reg hsfreqrange_h3_v3h_m3n[] = {
{ /* sentinel */ },
};
-static const struct rcsi2_mbps_reg hsfreqrange_m3w[] = {
+static const struct rcsi2_mbps_info hsfreqrange_m3w[] = {
{ .mbps = 80, .reg = 0x00 },
{ .mbps = 90, .reg = 0x10 },
{ .mbps = 100, .reg = 0x20 },
@@ -496,6 +526,73 @@ static const struct rcsi2_mbps_reg hsfreqrange_m3w[] = {
{ /* sentinel */ },
};
+static const struct rcsi2_mbps_info hsfreqrange_v4m[] = {
+ { .mbps = 80, .reg = 0x00, .osc_freq = 0x01a9 },
+ { .mbps = 90, .reg = 0x10, .osc_freq = 0x01a9 },
+ { .mbps = 100, .reg = 0x20, .osc_freq = 0x01a9 },
+ { .mbps = 110, .reg = 0x30, .osc_freq = 0x01a9 },
+ { .mbps = 120, .reg = 0x01, .osc_freq = 0x01a9 },
+ { .mbps = 130, .reg = 0x11, .osc_freq = 0x01a9 },
+ { .mbps = 140, .reg = 0x21, .osc_freq = 0x01a9 },
+ { .mbps = 150, .reg = 0x31, .osc_freq = 0x01a9 },
+ { .mbps = 160, .reg = 0x02, .osc_freq = 0x01a9 },
+ { .mbps = 170, .reg = 0x12, .osc_freq = 0x01a9 },
+ { .mbps = 180, .reg = 0x22, .osc_freq = 0x01a9 },
+ { .mbps = 190, .reg = 0x32, .osc_freq = 0x01a9 },
+ { .mbps = 205, .reg = 0x03, .osc_freq = 0x01a9 },
+ { .mbps = 220, .reg = 0x13, .osc_freq = 0x01a9 },
+ { .mbps = 235, .reg = 0x23, .osc_freq = 0x01a9 },
+ { .mbps = 250, .reg = 0x33, .osc_freq = 0x01a9 },
+ { .mbps = 275, .reg = 0x04, .osc_freq = 0x01a9 },
+ { .mbps = 300, .reg = 0x14, .osc_freq = 0x01a9 },
+ { .mbps = 325, .reg = 0x25, .osc_freq = 0x01a9 },
+ { .mbps = 350, .reg = 0x35, .osc_freq = 0x01a9 },
+ { .mbps = 400, .reg = 0x05, .osc_freq = 0x01a9 },
+ { .mbps = 450, .reg = 0x16, .osc_freq = 0x01a9 },
+ { .mbps = 500, .reg = 0x26, .osc_freq = 0x01a9 },
+ { .mbps = 550, .reg = 0x37, .osc_freq = 0x01a9 },
+ { .mbps = 600, .reg = 0x07, .osc_freq = 0x01a9 },
+ { .mbps = 650, .reg = 0x18, .osc_freq = 0x01a9 },
+ { .mbps = 700, .reg = 0x28, .osc_freq = 0x01a9 },
+ { .mbps = 750, .reg = 0x39, .osc_freq = 0x01a9 },
+ { .mbps = 800, .reg = 0x09, .osc_freq = 0x01a9 },
+ { .mbps = 850, .reg = 0x19, .osc_freq = 0x01a9 },
+ { .mbps = 900, .reg = 0x29, .osc_freq = 0x01a9 },
+ { .mbps = 950, .reg = 0x3a, .osc_freq = 0x01a9 },
+ { .mbps = 1000, .reg = 0x0a, .osc_freq = 0x01a9 },
+ { .mbps = 1050, .reg = 0x1a, .osc_freq = 0x01a9 },
+ { .mbps = 1100, .reg = 0x2a, .osc_freq = 0x01a9 },
+ { .mbps = 1150, .reg = 0x3b, .osc_freq = 0x01a9 },
+ { .mbps = 1200, .reg = 0x0b, .osc_freq = 0x01a9 },
+ { .mbps = 1250, .reg = 0x1b, .osc_freq = 0x01a9 },
+ { .mbps = 1300, .reg = 0x2b, .osc_freq = 0x01a9 },
+ { .mbps = 1350, .reg = 0x3c, .osc_freq = 0x01a9 },
+ { .mbps = 1400, .reg = 0x0c, .osc_freq = 0x01a9 },
+ { .mbps = 1450, .reg = 0x1c, .osc_freq = 0x01a9 },
+ { .mbps = 1500, .reg = 0x2c, .osc_freq = 0x01a9 },
+ { .mbps = 1550, .reg = 0x3d, .osc_freq = 0x0108 },
+ { .mbps = 1600, .reg = 0x0d, .osc_freq = 0x0110 },
+ { .mbps = 1650, .reg = 0x1d, .osc_freq = 0x0119 },
+ { .mbps = 1700, .reg = 0x2e, .osc_freq = 0x0121 },
+ { .mbps = 1750, .reg = 0x3e, .osc_freq = 0x012a },
+ { .mbps = 1800, .reg = 0x0e, .osc_freq = 0x0132 },
+ { .mbps = 1850, .reg = 0x1e, .osc_freq = 0x013b },
+ { .mbps = 1900, .reg = 0x2f, .osc_freq = 0x0143 },
+ { .mbps = 1950, .reg = 0x3f, .osc_freq = 0x014c },
+ { .mbps = 2000, .reg = 0x0f, .osc_freq = 0x0154 },
+ { .mbps = 2050, .reg = 0x40, .osc_freq = 0x015d },
+ { .mbps = 2100, .reg = 0x41, .osc_freq = 0x0165 },
+ { .mbps = 2150, .reg = 0x42, .osc_freq = 0x016e },
+ { .mbps = 2200, .reg = 0x43, .osc_freq = 0x0176 },
+ { .mbps = 2250, .reg = 0x44, .osc_freq = 0x017f },
+ { .mbps = 2300, .reg = 0x45, .osc_freq = 0x0187 },
+ { .mbps = 2350, .reg = 0x46, .osc_freq = 0x0190 },
+ { .mbps = 2400, .reg = 0x47, .osc_freq = 0x0198 },
+ { .mbps = 2450, .reg = 0x48, .osc_freq = 0x01a1 },
+ { .mbps = 2500, .reg = 0x49, .osc_freq = 0x01a9 },
+ { /* sentinel */ },
+};
+
/* PHY ESC Error Monitor */
#define PHEERM_REG 0x74
@@ -584,13 +681,19 @@ enum rcar_csi2_pads {
NR_OF_RCAR_CSI2_PAD,
};
+struct rcsi2_register_layout {
+ unsigned int phtw;
+ unsigned int phypll;
+};
+
struct rcar_csi2_info {
+ const struct rcsi2_register_layout *regs;
int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps);
int (*phy_post_init)(struct rcar_csi2 *priv);
int (*start_receiver)(struct rcar_csi2 *priv,
struct v4l2_subdev_state *state);
void (*enter_standby)(struct rcar_csi2 *priv);
- const struct rcsi2_mbps_reg *hsfreqrange;
+ const struct rcsi2_mbps_info *hsfreqrange;
unsigned int csi0clkfreqrange;
unsigned int num_channels;
bool clear_ulps;
@@ -656,6 +759,70 @@ static void rcsi2_write16(struct rcar_csi2 *priv, unsigned int reg, u16 data)
iowrite16(data, priv->base + reg);
}
+static int rcsi2_phtw_write(struct rcar_csi2 *priv, u8 data, u8 code)
+{
+ unsigned int timeout;
+
+ rcsi2_write(priv, priv->info->regs->phtw,
+ PHTW_DWEN | PHTW_TESTDIN_DATA(data) |
+ PHTW_CWEN | PHTW_TESTDIN_CODE(code));
+
+ /* Wait for DWEN and CWEN to be cleared by hardware. */
+ for (timeout = 0; timeout <= 20; timeout++) {
+ if (!(rcsi2_read(priv, priv->info->regs->phtw) & (PHTW_DWEN | PHTW_CWEN)))
+ return 0;
+
+ usleep_range(1000, 2000);
+ }
+
+ dev_err(priv->dev, "Timeout waiting for PHTW_DWEN and/or PHTW_CWEN\n");
+
+ return -ETIMEDOUT;
+}
+
+static int rcsi2_phtw_write_array(struct rcar_csi2 *priv,
+ const struct phtw_value *values,
+ unsigned int size)
+{
+ int ret;
+
+ for (unsigned int i = 0; i < size; i++) {
+ ret = rcsi2_phtw_write(priv, values[i].data, values[i].code);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct rcsi2_mbps_info *
+rcsi2_mbps_to_info(struct rcar_csi2 *priv,
+ const struct rcsi2_mbps_info *infotable, unsigned int mbps)
+{
+ const struct rcsi2_mbps_info *info;
+ const struct rcsi2_mbps_info *prev = NULL;
+
+ if (mbps < infotable->mbps)
+ dev_warn(priv->dev, "%u Mbps less than min PHY speed %u Mbps",
+ mbps, infotable->mbps);
+
+ for (info = infotable; info->mbps != 0; info++) {
+ if (info->mbps >= mbps)
+ break;
+ prev = info;
+ }
+
+ if (!info->mbps) {
+ dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps);
+ return NULL;
+ }
+
+ if (prev && ((mbps - prev->mbps) <= (info->mbps - mbps)))
+ info = prev;
+
+ return info;
+}
+
static void rcsi2_enter_standby_gen3(struct rcar_csi2 *priv)
{
rcsi2_write(priv, PHYCNT_REG, 0);
@@ -708,29 +875,13 @@ static int rcsi2_wait_phy_start(struct rcar_csi2 *priv,
static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps)
{
- const struct rcsi2_mbps_reg *hsfreq;
- const struct rcsi2_mbps_reg *hsfreq_prev = NULL;
-
- if (mbps < priv->info->hsfreqrange->mbps)
- dev_warn(priv->dev, "%u Mbps less than min PHY speed %u Mbps",
- mbps, priv->info->hsfreqrange->mbps);
-
- for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) {
- if (hsfreq->mbps >= mbps)
- break;
- hsfreq_prev = hsfreq;
- }
+ const struct rcsi2_mbps_info *info;
- if (!hsfreq->mbps) {
- dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps);
+ info = rcsi2_mbps_to_info(priv, priv->info->hsfreqrange, mbps);
+ if (!info)
return -ERANGE;
- }
- if (hsfreq_prev &&
- ((mbps - hsfreq_prev->mbps) <= (hsfreq->mbps - mbps)))
- hsfreq = hsfreq_prev;
-
- rcsi2_write(priv, PHYPLL_REG, PHYPLL_HSFREQRANGE(hsfreq->reg));
+ rcsi2_write(priv, priv->info->regs->phypll, PHYPLL_HSFREQRANGE(info->reg));
return 0;
}
@@ -1092,11 +1243,11 @@ static int rcsi2_start_receiver_v4h(struct rcar_csi2 *priv,
rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, 0);
/* PHY static setting */
- rcsi2_write(priv, V4H_PHY_EN_REG, BIT(0));
+ rcsi2_write(priv, V4H_PHY_EN_REG, V4H_PHY_EN_ENABLE_CLK);
rcsi2_write(priv, V4H_FLDC_REG, 0);
rcsi2_write(priv, V4H_FLDD_REG, 0);
rcsi2_write(priv, V4H_IDIC_REG, 0);
- rcsi2_write(priv, V4H_PHY_MODE_REG, BIT(0));
+ rcsi2_write(priv, V4H_PHY_MODE_REG, V4H_PHY_MODE_CPHY);
rcsi2_write(priv, V4H_N_LANES_REG, lanes - 1);
/* Reset CSI2 */
@@ -1131,6 +1282,195 @@ static int rcsi2_start_receiver_v4h(struct rcar_csi2 *priv,
return 0;
}
+static int rcsi2_d_phy_setting_v4m(struct rcar_csi2 *priv, int data_rate)
+{
+ unsigned int timeout;
+ int ret;
+
+ static const struct phtw_value step1[] = {
+ { .data = 0x00, .code = 0x00 },
+ { .data = 0x00, .code = 0x1e },
+ };
+
+ /* Shutdown and reset PHY. */
+ rcsi2_write(priv, V4H_DPHY_RSTZ_REG, BIT(0));
+ rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, BIT(0));
+
+ /* Start internal calibration (POR). */
+ ret = rcsi2_phtw_write_array(priv, step1, ARRAY_SIZE(step1));
+ if (ret)
+ return ret;
+
+ /* Wait for POR to complete. */
+ for (timeout = 10; timeout > 0; timeout--) {
+ if ((rcsi2_read(priv, V4M_PHTR_REG) & 0xf0000) == 0x70000)
+ break;
+ usleep_range(1000, 2000);
+ }
+
+ if (!timeout) {
+ dev_err(priv->dev, "D-PHY calibration failed\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int rcsi2_set_osc_freq(struct rcar_csi2 *priv, unsigned int mbps)
+{
+ const struct rcsi2_mbps_info *info;
+ struct phtw_value steps[] = {
+ { .data = 0x00, .code = 0x00 },
+ { .code = 0xe2 }, /* Data filled in below. */
+ { .code = 0xe3 }, /* Data filled in below. */
+ { .data = 0x01, .code = 0xe4 },
+ };
+
+ info = rcsi2_mbps_to_info(priv, priv->info->hsfreqrange, mbps);
+ if (!info)
+ return -ERANGE;
+
+ /* Fill in data for command. */
+ steps[1].data = (info->osc_freq & 0x00ff) >> 0;
+ steps[2].data = (info->osc_freq & 0x0f00) >> 8;
+
+ return rcsi2_phtw_write_array(priv, steps, ARRAY_SIZE(steps));
+}
+
+static int rcsi2_init_common_v4m(struct rcar_csi2 *priv, unsigned int mbps)
+{
+ int ret;
+
+ static const struct phtw_value step1[] = {
+ { .data = 0x00, .code = 0x00 },
+ { .data = 0x3c, .code = 0x08 },
+ };
+
+ static const struct phtw_value step2[] = {
+ { .data = 0x00, .code = 0x00 },
+ { .data = 0x80, .code = 0xe0 },
+ { .data = 0x01, .code = 0xe1 },
+ { .data = 0x06, .code = 0x00 },
+ { .data = 0x0f, .code = 0x11 },
+ { .data = 0x08, .code = 0x00 },
+ { .data = 0x0f, .code = 0x11 },
+ { .data = 0x0a, .code = 0x00 },
+ { .data = 0x0f, .code = 0x11 },
+ { .data = 0x0c, .code = 0x00 },
+ { .data = 0x0f, .code = 0x11 },
+ { .data = 0x01, .code = 0x00 },
+ { .data = 0x31, .code = 0xaa },
+ { .data = 0x05, .code = 0x00 },
+ { .data = 0x05, .code = 0x09 },
+ { .data = 0x07, .code = 0x00 },
+ { .data = 0x05, .code = 0x09 },
+ { .data = 0x09, .code = 0x00 },
+ { .data = 0x05, .code = 0x09 },
+ { .data = 0x0b, .code = 0x00 },
+ { .data = 0x05, .code = 0x09 },
+ };
+
+ if (priv->info->hsfreqrange) {
+ ret = rcsi2_set_phypll(priv, mbps);
+ if (ret)
+ return ret;
+
+ ret = rcsi2_set_osc_freq(priv, mbps);
+ if (ret)
+ return ret;
+ }
+
+ if (mbps <= 1500) {
+ ret = rcsi2_phtw_write_array(priv, step1, ARRAY_SIZE(step1));
+ if (ret)
+ return ret;
+ }
+
+ if (priv->info->csi0clkfreqrange)
+ rcsi2_write(priv, V4M_CSI0CLKFCPR_REG,
+ CSI0CLKFREQRANGE(priv->info->csi0clkfreqrange));
+
+ rcsi2_write(priv, V4H_PHY_EN_REG, V4H_PHY_EN_ENABLE_CLK |
+ V4H_PHY_EN_ENABLE_0 | V4H_PHY_EN_ENABLE_1 |
+ V4H_PHY_EN_ENABLE_2 | V4H_PHY_EN_ENABLE_3);
+
+ if (mbps > 1500) {
+ ret = rcsi2_phtw_write_array(priv, step2, ARRAY_SIZE(step2));
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int rcsi2_start_receiver_v4m(struct rcar_csi2 *priv,
+ struct v4l2_subdev_state *state)
+{
+ const struct rcar_csi2_format *format;
+ const struct v4l2_mbus_framefmt *fmt;
+ unsigned int lanes;
+ int mbps;
+ int ret;
+
+ /* Calculate parameters */
+ fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
+ format = rcsi2_code_to_fmt(fmt->code);
+ if (!format)
+ return -EINVAL;
+
+ ret = rcsi2_get_active_lanes(priv, &lanes);
+ if (ret)
+ return ret;
+
+ mbps = rcsi2_calc_mbps(priv, format->bpp, lanes);
+ if (mbps < 0)
+ return mbps;
+
+ /* Reset LINK and PHY */
+ rcsi2_write(priv, V4H_CSI2_RESETN_REG, 0);
+ rcsi2_write(priv, V4H_DPHY_RSTZ_REG, 0);
+ rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, 0);
+ rcsi2_write(priv, V4M_PHTC_REG, PHTC_TESTCLR);
+
+ /* PHY static setting */
+ rcsi2_write(priv, V4H_PHY_EN_REG, V4H_PHY_EN_ENABLE_CLK);
+ rcsi2_write(priv, V4H_FLDC_REG, 0);
+ rcsi2_write(priv, V4H_FLDD_REG, 0);
+ rcsi2_write(priv, V4H_IDIC_REG, 0);
+ rcsi2_write(priv, V4H_PHY_MODE_REG, V4H_PHY_MODE_DPHY);
+ rcsi2_write(priv, V4H_N_LANES_REG, lanes - 1);
+
+ rcsi2_write(priv, V4M_FRXM_REG,
+ V4M_FRXM_FORCERXMODE_0 | V4M_FRXM_FORCERXMODE_1 |
+ V4M_FRXM_FORCERXMODE_2 | V4M_FRXM_FORCERXMODE_3);
+ rcsi2_write(priv, V4M_OVR1_REG,
+ V4M_OVR1_FORCERXMODE_0 | V4M_OVR1_FORCERXMODE_1 |
+ V4M_OVR1_FORCERXMODE_2 | V4M_OVR1_FORCERXMODE_3);
+
+ /* Reset CSI2 */
+ rcsi2_write(priv, V4M_PHTC_REG, 0);
+ rcsi2_write(priv, V4H_CSI2_RESETN_REG, BIT(0));
+
+ /* Common settings */
+ ret = rcsi2_init_common_v4m(priv, mbps);
+ if (ret)
+ return ret;
+
+ /* D-PHY settings */
+ ret = rcsi2_d_phy_setting_v4m(priv, mbps);
+ if (ret)
+ return ret;
+
+ rcsi2_wait_phy_start_v4h(priv, V4H_ST_PHYST_ST_STOPSTATE_0 |
+ V4H_ST_PHYST_ST_STOPSTATE_1 |
+ V4H_ST_PHYST_ST_STOPSTATE_2 |
+ V4H_ST_PHYST_ST_STOPSTATE_3);
+
+ rcsi2_write(priv, V4M_FRXM_REG, 0);
+
+ return 0;
+}
+
static int rcsi2_start(struct rcar_csi2 *priv, struct v4l2_subdev_state *state)
{
int ret;
@@ -1451,64 +1791,16 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
* NOTE: Magic values are from the datasheet and lack documentation.
*/
-static int rcsi2_phtw_write(struct rcar_csi2 *priv, u16 data, u16 code)
-{
- unsigned int timeout;
-
- rcsi2_write(priv, PHTW_REG,
- PHTW_DWEN | PHTW_TESTDIN_DATA(data) |
- PHTW_CWEN | PHTW_TESTDIN_CODE(code));
-
- /* Wait for DWEN and CWEN to be cleared by hardware. */
- for (timeout = 0; timeout <= 20; timeout++) {
- if (!(rcsi2_read(priv, PHTW_REG) & (PHTW_DWEN | PHTW_CWEN)))
- return 0;
-
- usleep_range(1000, 2000);
- }
-
- dev_err(priv->dev, "Timeout waiting for PHTW_DWEN and/or PHTW_CWEN\n");
-
- return -ETIMEDOUT;
-}
-
-static int rcsi2_phtw_write_array(struct rcar_csi2 *priv,
- const struct phtw_value *values)
-{
- const struct phtw_value *value;
- int ret;
-
- for (value = values; value->data || value->code; value++) {
- ret = rcsi2_phtw_write(priv, value->data, value->code);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static int rcsi2_phtw_write_mbps(struct rcar_csi2 *priv, unsigned int mbps,
- const struct rcsi2_mbps_reg *values, u16 code)
+ const struct rcsi2_mbps_info *values, u8 code)
{
- const struct rcsi2_mbps_reg *value;
- const struct rcsi2_mbps_reg *prev_value = NULL;
-
- for (value = values; value->mbps; value++) {
- if (value->mbps >= mbps)
- break;
- prev_value = value;
- }
+ const struct rcsi2_mbps_info *info;
- if (prev_value &&
- ((mbps - prev_value->mbps) <= (value->mbps - mbps)))
- value = prev_value;
-
- if (!value->mbps) {
- dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps);
+ info = rcsi2_mbps_to_info(priv, values, mbps);
+ if (!info)
return -ERANGE;
- }
- return rcsi2_phtw_write(priv, value->reg, code);
+ return rcsi2_phtw_write(priv, info->reg, code);
}
static int __rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv,
@@ -1520,7 +1812,6 @@ static int __rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv,
{ .data = 0x11, .code = 0xe4 },
{ .data = 0x01, .code = 0xe5 },
{ .data = 0x10, .code = 0x04 },
- { /* sentinel */ },
};
static const struct phtw_value step2[] = {
@@ -1529,12 +1820,11 @@ static int __rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv,
{ .data = 0x4b, .code = 0xac },
{ .data = 0x03, .code = 0x00 },
{ .data = 0x80, .code = 0x07 },
- { /* sentinel */ },
};
int ret;
- ret = rcsi2_phtw_write_array(priv, step1);
+ ret = rcsi2_phtw_write_array(priv, step1, ARRAY_SIZE(step1));
if (ret)
return ret;
@@ -1549,7 +1839,7 @@ static int __rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv,
return ret;
}
- return rcsi2_phtw_write_array(priv, step2);
+ return rcsi2_phtw_write_array(priv, step2, ARRAY_SIZE(step2));
}
static int rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, unsigned int mbps)
@@ -1575,10 +1865,9 @@ static int rcsi2_phy_post_init_v3m_e3(struct rcar_csi2 *priv)
{ .data = 0xee, .code = 0x54 },
{ .data = 0xee, .code = 0x84 },
{ .data = 0xee, .code = 0x94 },
- { /* sentinel */ },
};
- return rcsi2_phtw_write_array(priv, step1);
+ return rcsi2_phtw_write_array(priv, step1, ARRAY_SIZE(step1));
}
static int rcsi2_init_phtw_v3u(struct rcar_csi2 *priv,
@@ -1587,20 +1876,17 @@ static int rcsi2_init_phtw_v3u(struct rcar_csi2 *priv,
/* In case of 1500Mbps or less */
static const struct phtw_value step1[] = {
{ .data = 0xcc, .code = 0xe2 },
- { /* sentinel */ },
};
static const struct phtw_value step2[] = {
{ .data = 0x01, .code = 0xe3 },
{ .data = 0x11, .code = 0xe4 },
{ .data = 0x01, .code = 0xe5 },
- { /* sentinel */ },
};
/* In case of 1500Mbps or less */
static const struct phtw_value step3[] = {
{ .data = 0x38, .code = 0x08 },
- { /* sentinel */ },
};
static const struct phtw_value step4[] = {
@@ -1608,29 +1894,28 @@ static int rcsi2_init_phtw_v3u(struct rcar_csi2 *priv,
{ .data = 0x4b, .code = 0xac },
{ .data = 0x03, .code = 0x00 },
{ .data = 0x80, .code = 0x07 },
- { /* sentinel */ },
};
int ret;
if (mbps != 0 && mbps <= 1500)
- ret = rcsi2_phtw_write_array(priv, step1);
+ ret = rcsi2_phtw_write_array(priv, step1, ARRAY_SIZE(step1));
else
ret = rcsi2_phtw_write_mbps(priv, mbps, phtw_mbps_v3u, 0xe2);
if (ret)
return ret;
- ret = rcsi2_phtw_write_array(priv, step2);
+ ret = rcsi2_phtw_write_array(priv, step2, ARRAY_SIZE(step2));
if (ret)
return ret;
if (mbps != 0 && mbps <= 1500) {
- ret = rcsi2_phtw_write_array(priv, step3);
+ ret = rcsi2_phtw_write_array(priv, step3, ARRAY_SIZE(step3));
if (ret)
return ret;
}
- ret = rcsi2_phtw_write_array(priv, step4);
+ ret = rcsi2_phtw_write_array(priv, step4, ARRAY_SIZE(step4));
if (ret)
return ret;
@@ -1714,7 +1999,13 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
return PTR_ERR_OR_ZERO(priv->rstc);
}
+static const struct rcsi2_register_layout rcsi2_registers_gen3 = {
+ .phtw = PHTW_REG,
+ .phypll = PHYPLL_REG,
+};
+
static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = {
+ .regs = &rcsi2_registers_gen3,
.init_phtw = rcsi2_init_phtw_h3_v3h_m3n,
.start_receiver = rcsi2_start_receiver_gen3,
.enter_standby = rcsi2_enter_standby_gen3,
@@ -1726,6 +2017,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = {
+ .regs = &rcsi2_registers_gen3,
.init_phtw = rcsi2_init_phtw_h3es2,
.start_receiver = rcsi2_start_receiver_gen3,
.enter_standby = rcsi2_enter_standby_gen3,
@@ -1737,6 +2029,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = {
+ .regs = &rcsi2_registers_gen3,
.start_receiver = rcsi2_start_receiver_gen3,
.enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_m3w,
@@ -1745,6 +2038,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = {
+ .regs = &rcsi2_registers_gen3,
.start_receiver = rcsi2_start_receiver_gen3,
.enter_standby = rcsi2_enter_standby_gen3,
.hsfreqrange = hsfreqrange_m3w,
@@ -1753,6 +2047,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = {
+ .regs = &rcsi2_registers_gen3,
.init_phtw = rcsi2_init_phtw_h3_v3h_m3n,
.start_receiver = rcsi2_start_receiver_gen3,
.enter_standby = rcsi2_enter_standby_gen3,
@@ -1764,6 +2059,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = {
+ .regs = &rcsi2_registers_gen3,
.init_phtw = rcsi2_init_phtw_v3m_e3,
.phy_post_init = rcsi2_phy_post_init_v3m_e3,
.start_receiver = rcsi2_start_receiver_gen3,
@@ -1773,6 +2069,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = {
+ .regs = &rcsi2_registers_gen3,
.init_phtw = rcsi2_init_phtw_h3_v3h_m3n,
.start_receiver = rcsi2_start_receiver_gen3,
.enter_standby = rcsi2_enter_standby_gen3,
@@ -1783,6 +2080,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = {
+ .regs = &rcsi2_registers_gen3,
.init_phtw = rcsi2_init_phtw_v3m_e3,
.phy_post_init = rcsi2_phy_post_init_v3m_e3,
.start_receiver = rcsi2_start_receiver_gen3,
@@ -1792,6 +2090,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = {
+ .regs = &rcsi2_registers_gen3,
.init_phtw = rcsi2_init_phtw_v3u,
.start_receiver = rcsi2_start_receiver_gen3,
.enter_standby = rcsi2_enter_standby_gen3,
@@ -1803,11 +2102,26 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = {
};
static const struct rcar_csi2_info rcar_csi2_info_r8a779g0 = {
+ .regs = &rcsi2_registers_gen3,
.start_receiver = rcsi2_start_receiver_v4h,
.use_isp = true,
.support_cphy = true,
};
+static const struct rcsi2_register_layout rcsi2_registers_v4m = {
+ .phtw = V4M_PHTW_REG,
+ .phypll = V4M_PHYPLL_REG,
+};
+
+static const struct rcar_csi2_info rcar_csi2_info_r8a779h0 = {
+ .regs = &rcsi2_registers_v4m,
+ .start_receiver = rcsi2_start_receiver_v4m,
+ .hsfreqrange = hsfreqrange_v4m,
+ .csi0clkfreqrange = 0x0c,
+ .use_isp = true,
+ .support_dphy = true,
+};
+
static const struct of_device_id rcar_csi2_of_table[] = {
{
.compatible = "renesas,r8a774a1-csi2",
@@ -1861,6 +2175,10 @@ static const struct of_device_id rcar_csi2_of_table[] = {
.compatible = "renesas,r8a779g0-csi2",
.data = &rcar_csi2_info_r8a779g0,
},
+ {
+ .compatible = "renesas,r8a779h0-csi2",
+ .data = &rcar_csi2_info_r8a779h0,
+ },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, rcar_csi2_of_table);
@@ -1974,7 +2292,7 @@ static void rcsi2_remove(struct platform_device *pdev)
}
static struct platform_driver rcar_csi2_pdrv = {
- .remove_new = rcsi2_remove,
+ .remove = rcsi2_remove,
.probe = rcsi2_probe,
.driver = {
.name = "rcar-csi2",
diff --git a/drivers/media/platform/renesas/rcar-fcp.c b/drivers/media/platform/renesas/rcar-fcp.c
index bcef7b87da7c..cee9bbce4e3a 100644
--- a/drivers/media/platform/renesas/rcar-fcp.c
+++ b/drivers/media/platform/renesas/rcar-fcp.c
@@ -164,7 +164,7 @@ MODULE_DEVICE_TABLE(of, rcar_fcp_of_match);
static struct platform_driver rcar_fcp_platform_driver = {
.probe = rcar_fcp_probe,
- .remove_new = rcar_fcp_remove,
+ .remove = rcar_fcp_remove,
.driver = {
.name = "rcar-fcp",
.of_match_table = rcar_fcp_of_match,
diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c
index 4512ac338ca5..c515278e3be5 100644
--- a/drivers/media/platform/renesas/rcar-isp.c
+++ b/drivers/media/platform/renesas/rcar-isp.c
@@ -431,7 +431,9 @@ static int risp_probe_resources(struct rcar_isp *isp,
static const struct of_device_id risp_of_id_table[] = {
{ .compatible = "renesas,r8a779a0-isp" },
{ .compatible = "renesas,r8a779g0-isp" },
- { /* sentinel */ },
+ /* Keep above for compatibility with old DTB files. */
+ { .compatible = "renesas,rcar-gen4-isp" },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, risp_of_id_table);
@@ -522,7 +524,7 @@ static struct platform_driver rcar_isp_driver = {
.of_match_table = risp_of_id_table,
},
.probe = risp_probe,
- .remove_new = risp_remove,
+ .remove = risp_remove,
};
module_platform_driver(rcar_isp_driver);
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
index 695d884a22d1..ddfb18e6e7a4 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c
@@ -1279,6 +1279,7 @@ static const struct rvin_info rcar_info_gen4 = {
.use_mc = true,
.use_isp = true,
.nv12 = true,
+ .raw10 = true,
.max_width = 4096,
.max_height = 4096,
};
@@ -1443,7 +1444,7 @@ static struct platform_driver rcar_vin_driver = {
.of_match_table = rvin_of_id_table,
},
.probe = rcar_vin_probe,
- .remove_new = rcar_vin_remove,
+ .remove = rcar_vin_remove,
};
module_platform_driver(rcar_vin_driver);
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c
index 21d5b2815e86..8773998101ff 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c
@@ -123,7 +123,9 @@
/* Video n Data Mode Register bits */
#define VNDMR_A8BIT(n) (((n) & 0xff) << 24)
#define VNDMR_A8BIT_MASK (0xff << 24)
+#define VNDMR_RMODE_RAW10 (2 << 19)
#define VNDMR_YMODE_Y8 (1 << 12)
+#define VNDMR_YC_THR (1 << 11)
#define VNDMR_EXRGB (1 << 8)
#define VNDMR_BPSM (1 << 4)
#define VNDMR_ABIT (1 << 2)
@@ -790,6 +792,12 @@ static int rvin_setup(struct rvin_dev *vin)
case MEDIA_BUS_FMT_Y8_1X8:
vnmc |= VNMC_INF_RAW8;
break;
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ vnmc |= VNMC_INF_RGB666;
+ break;
default:
break;
}
@@ -898,6 +906,12 @@ static int rvin_setup(struct rvin_dev *vin)
dmr = 0;
}
break;
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ dmr = VNDMR_RMODE_RAW10 | VNDMR_YC_THR;
+ break;
default:
vin_err(vin, "Invalid pixelformat (0x%x)\n",
vin->format.pixelformat);
@@ -1280,6 +1294,22 @@ static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd,
if (vin->format.pixelformat != V4L2_PIX_FMT_GREY)
return -EPIPE;
break;
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR10)
+ return -EPIPE;
+ break;
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG10)
+ return -EPIPE;
+ break;
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG10)
+ return -EPIPE;
+ break;
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB10)
+ return -EPIPE;
+ break;
default:
return -EPIPE;
}
@@ -1529,8 +1559,6 @@ static const struct vb2_ops rvin_qops = {
.buf_queue = rvin_buffer_queue,
.start_streaming = rvin_start_streaming_vq,
.stop_streaming = rvin_stop_streaming_vq,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
void rvin_dma_unregister(struct rvin_dev *vin)
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
index bb4b07bed28d..756fdfdbce61 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c
@@ -86,6 +86,22 @@ static const struct rvin_video_format rvin_formats[] = {
.fourcc = V4L2_PIX_FMT_GREY,
.bpp = 1,
},
+ {
+ .fourcc = V4L2_PIX_FMT_SBGGR10,
+ .bpp = 4,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGBRG10,
+ .bpp = 4,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SGRBG10,
+ .bpp = 4,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB10,
+ .bpp = 4,
+ },
};
const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
@@ -106,6 +122,13 @@ const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
if (!vin->info->nv12 || !(BIT(vin->id) & 0x3333))
return NULL;
break;
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ if (!vin->info->raw10)
+ return NULL;
+ break;
default:
break;
}
@@ -407,6 +430,26 @@ static int rvin_enum_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
f->pixelformat = V4L2_PIX_FMT_SRGGB8;
return 0;
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ if (f->index)
+ return -EINVAL;
+ f->pixelformat = V4L2_PIX_FMT_SBGGR10;
+ return 0;
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ if (f->index)
+ return -EINVAL;
+ f->pixelformat = V4L2_PIX_FMT_SGBRG10;
+ return 0;
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ if (f->index)
+ return -EINVAL;
+ f->pixelformat = V4L2_PIX_FMT_SGRBG10;
+ return 0;
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ if (f->index)
+ return -EINVAL;
+ f->pixelformat = V4L2_PIX_FMT_SRGGB10;
+ return 0;
default:
return -EINVAL;
}
diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
index 997a66318a29..f87d4bc9e53e 100644
--- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
@@ -151,7 +151,8 @@ struct rvin_group_route {
* @model: VIN model
* @use_mc: use media controller instead of controlling subdevice
* @use_isp: the VIN is connected to the ISP and not to the CSI-2
- * @nv12: support outputing NV12 pixel format
+ * @nv12: support outputting NV12 pixel format
+ * @raw10: support outputting RAW10 pixel format
* @max_width: max input width the VIN supports
* @max_height: max input height the VIN supports
* @routes: list of possible routes from the CSI-2 recivers to
@@ -163,6 +164,7 @@ struct rvin_info {
bool use_mc;
bool use_isp;
bool nv12;
+ bool raw10;
unsigned int max_width;
unsigned int max_height;
diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c
index f21d05054341..fc8b6bbef793 100644
--- a/drivers/media/platform/renesas/rcar_drif.c
+++ b/drivers/media/platform/renesas/rcar_drif.c
@@ -861,8 +861,6 @@ static const struct vb2_ops rcar_drif_vb2_ops = {
.buf_queue = rcar_drif_buf_queue,
.start_streaming = rcar_drif_start_streaming,
.stop_streaming = rcar_drif_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int rcar_drif_querycap(struct file *file, void *fh,
@@ -1071,7 +1069,6 @@ static int rcar_drif_sdr_register(struct rcar_drif_sdr *sdr)
sdr->vdev->release = video_device_release;
sdr->vdev->lock = &sdr->v4l2_mutex;
sdr->vdev->queue = &sdr->vb_queue;
- sdr->vdev->queue->lock = &sdr->vb_queue_mutex;
sdr->vdev->ctrl_handler = &sdr->ctrl_hdl;
sdr->vdev->v4l2_dev = &sdr->v4l2_dev;
sdr->vdev->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
@@ -1316,6 +1313,7 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr)
sdr->vb_queue.ops = &rcar_drif_vb2_ops;
sdr->vb_queue.mem_ops = &vb2_vmalloc_memops;
sdr->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ sdr->vb_queue.lock = &sdr->vb_queue_mutex;
/* Init videobuf2 queue */
ret = vb2_queue_init(&sdr->vb_queue);
@@ -1475,7 +1473,7 @@ static struct platform_driver rcar_drif_driver = {
.pm = &rcar_drif_pm_ops,
},
.probe = rcar_drif_probe,
- .remove_new = rcar_drif_remove,
+ .remove = rcar_drif_remove,
};
module_platform_driver(rcar_drif_driver);
diff --git a/drivers/media/platform/renesas/rcar_fdp1.c b/drivers/media/platform/renesas/rcar_fdp1.c
index a2565b269f3b..5d453a7a8988 100644
--- a/drivers/media/platform/renesas/rcar_fdp1.c
+++ b/drivers/media/platform/renesas/rcar_fdp1.c
@@ -2032,8 +2032,6 @@ static const struct vb2_ops fdp1_qops = {
.buf_queue = fdp1_buf_queue,
.start_streaming = fdp1_start_streaming,
.stop_streaming = fdp1_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -2444,7 +2442,7 @@ MODULE_DEVICE_TABLE(of, fdp1_dt_ids);
static struct platform_driver fdp1_pdrv = {
.probe = fdp1_probe,
- .remove_new = fdp1_remove,
+ .remove = fdp1_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = fdp1_dt_ids,
diff --git a/drivers/media/platform/renesas/rcar_jpu.c b/drivers/media/platform/renesas/rcar_jpu.c
index e50fe7525a73..81038df71bb5 100644
--- a/drivers/media/platform/renesas/rcar_jpu.c
+++ b/drivers/media/platform/renesas/rcar_jpu.c
@@ -1171,8 +1171,6 @@ static const struct vb2_ops jpu_qops = {
.buf_finish = jpu_buf_finish,
.start_streaming = jpu_start_streaming,
.stop_streaming = jpu_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int jpu_queue_init(void *priv, struct vb2_queue *src_vq,
@@ -1736,7 +1734,7 @@ static const struct dev_pm_ops jpu_pm_ops = {
static struct platform_driver jpu_driver = {
.probe = jpu_probe,
- .remove_new = jpu_remove,
+ .remove = jpu_remove,
.driver = {
.of_match_table = jpu_dt_ids,
.name = DRV_NAME,
diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c
index 167760276796..8cceafe491b1 100644
--- a/drivers/media/platform/renesas/renesas-ceu.c
+++ b/drivers/media/platform/renesas/renesas-ceu.c
@@ -761,8 +761,6 @@ static const struct vb2_ops ceu_vb2_ops = {
.queue_setup = ceu_vb2_setup,
.buf_queue = ceu_vb2_queue,
.buf_prepare = ceu_vb2_prepare,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = ceu_start_streaming,
.stop_streaming = ceu_stop_streaming,
};
@@ -1723,7 +1721,7 @@ static struct platform_driver ceu_driver = {
.of_match_table = of_match_ptr(ceu_of_match),
},
.probe = ceu_probe,
- .remove_new = ceu_remove,
+ .remove = ceu_remove,
};
module_platform_driver(ceu_driver);
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
index 280efd2a8185..89be584a4988 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
@@ -72,7 +72,6 @@ static int rzg2l_cru_group_notify_complete(struct v4l2_async_notifier *notifier)
source->name, sink->name);
return ret;
}
- cru->csi.channel = 0;
cru->ip.remote = cru->csi.subdev;
/* Create media device link between CRU IP <-> CRU OUTPUT */
@@ -209,7 +208,7 @@ static int rzg2l_cru_media_init(struct rzg2l_cru_dev *cru)
const struct of_device_id *match;
int ret;
- cru->pad.flags = MEDIA_PAD_FL_SINK;
+ cru->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
ret = media_entity_pads_init(&cru->vdev.entity, 1, &cru->pad);
if (ret)
return ret;
@@ -242,7 +241,7 @@ static int rzg2l_cru_media_init(struct rzg2l_cru_dev *cru)
static int rzg2l_cru_probe(struct platform_device *pdev)
{
struct rzg2l_cru_dev *cru;
- int ret;
+ int irq, ret;
cru = devm_kzalloc(&pdev->dev, sizeof(*cru), GFP_KERNEL);
if (!cru)
@@ -270,9 +269,14 @@ static int rzg2l_cru_probe(struct platform_device *pdev)
cru->dev = &pdev->dev;
cru->info = of_device_get_match_data(&pdev->dev);
- cru->image_conv_irq = platform_get_irq(pdev, 0);
- if (cru->image_conv_irq < 0)
- return cru->image_conv_irq;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(&pdev->dev, irq, rzg2l_cru_irq, 0,
+ KBUILD_MODNAME, cru);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to request irq\n");
platform_set_drvdata(pdev, cru);
@@ -325,7 +329,7 @@ static struct platform_driver rzg2l_cru_driver = {
.of_match_table = rzg2l_cru_of_id_table,
},
.probe = rzg2l_cru_probe,
- .remove_new = rzg2l_cru_remove,
+ .remove = rzg2l_cru_remove,
};
module_platform_driver(rzg2l_cru_driver);
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru-regs.h b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru-regs.h
new file mode 100644
index 000000000000..1c9f22118a5d
--- /dev/null
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru-regs.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * rzg2l-cru-regs.h--RZ/G2L (and alike SoCs) CRU Registers Definitions
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#ifndef __RZG2L_CRU_REGS_H__
+#define __RZG2L_CRU_REGS_H__
+
+/* HW CRU Registers Definition */
+
+/* CRU Control Register */
+#define CRUnCTRL 0x0
+#define CRUnCTRL_VINSEL(x) ((x) << 0)
+
+/* CRU Interrupt Enable Register */
+#define CRUnIE 0x4
+#define CRUnIE_EFE BIT(17)
+
+/* CRU Interrupt Status Register */
+#define CRUnINTS 0x8
+#define CRUnINTS_SFS BIT(16)
+
+/* CRU Reset Register */
+#define CRUnRST 0xc
+#define CRUnRST_VRESETN BIT(0)
+
+/* Memory Bank Base Address (Lower) Register for CRU Image Data */
+#define AMnMBxADDRL(x) (0x100 + ((x) * 8))
+
+/* Memory Bank Base Address (Higher) Register for CRU Image Data */
+#define AMnMBxADDRH(x) (0x104 + ((x) * 8))
+
+/* Memory Bank Enable Register for CRU Image Data */
+#define AMnMBVALID 0x148
+#define AMnMBVALID_MBVALID(x) GENMASK(x, 0)
+
+/* Memory Bank Status Register for CRU Image Data */
+#define AMnMBS 0x14c
+#define AMnMBS_MBSTS 0x7
+
+/* AXI Master Transfer Setting Register for CRU Image Data */
+#define AMnAXIATTR 0x158
+#define AMnAXIATTR_AXILEN_MASK GENMASK(3, 0)
+#define AMnAXIATTR_AXILEN (0xf)
+
+/* AXI Master FIFO Pointer Register for CRU Image Data */
+#define AMnFIFOPNTR 0x168
+#define AMnFIFOPNTR_FIFOWPNTR GENMASK(7, 0)
+#define AMnFIFOPNTR_FIFORPNTR_Y GENMASK(23, 16)
+
+/* AXI Master Transfer Stop Register for CRU Image Data */
+#define AMnAXISTP 0x174
+#define AMnAXISTP_AXI_STOP BIT(0)
+
+/* AXI Master Transfer Stop Status Register for CRU Image Data */
+#define AMnAXISTPACK 0x178
+#define AMnAXISTPACK_AXI_STOP_ACK BIT(0)
+
+/* CRU Image Processing Enable Register */
+#define ICnEN 0x200
+#define ICnEN_ICEN BIT(0)
+
+/* CRU Image Processing Main Control Register */
+#define ICnMC 0x208
+#define ICnMC_CSCTHR BIT(5)
+#define ICnMC_INF(x) ((x) << 16)
+#define ICnMC_VCSEL(x) ((x) << 22)
+#define ICnMC_INF_MASK GENMASK(21, 16)
+
+/* CRU Module Status Register */
+#define ICnMS 0x254
+#define ICnMS_IA BIT(2)
+
+/* CRU Data Output Mode Register */
+#define ICnDMR 0x26c
+#define ICnDMR_YCMODE_UYVY (1 << 4)
+
+#endif /* __RZG2L_CRU_REGS_H__ */
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h
index a5a99b004322..8b898ce05b84 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h
@@ -8,6 +8,7 @@
#ifndef __RZG2L_CRU__
#define __RZG2L_CRU__
+#include <linux/irqreturn.h>
#include <linux/reset.h>
#include <media/v4l2-async.h>
@@ -30,6 +31,11 @@
#define RZG2L_CRU_MIN_INPUT_HEIGHT 240
#define RZG2L_CRU_MAX_INPUT_HEIGHT 4095
+enum rzg2l_csi2_pads {
+ RZG2L_CRU_IP_SINK = 0,
+ RZG2L_CRU_IP_SOURCE,
+};
+
/**
* enum rzg2l_cru_dma_state - DMA states
* @RZG2L_CRU_DMA_STOPPED: No operation in progress
@@ -47,7 +53,6 @@ enum rzg2l_cru_dma_state {
struct rzg2l_cru_csi {
struct v4l2_async_connection *asd;
struct v4l2_subdev *subdev;
- u32 channel;
};
struct rzg2l_cru_ip {
@@ -58,6 +63,24 @@ struct rzg2l_cru_ip {
};
/**
+ * struct rzg2l_cru_ip_format - CRU IP format
+ * @code: Media bus code
+ * @datatype: MIPI CSI2 data type
+ * @format: 4CC format identifier (V4L2_PIX_FMT_*)
+ * @icndmr: ICnDMR register value
+ * @bpp: bytes per pixel
+ * @yuv: Flag to indicate whether the format is YUV-based.
+ */
+struct rzg2l_cru_ip_format {
+ u32 code;
+ u32 datatype;
+ u32 format;
+ u32 icndmr;
+ u8 bpp;
+ bool yuv;
+};
+
+/**
* struct rzg2l_cru_dev - Renesas CRU device structure
* @dev: (OF) device
* @base: device I/O register space remapped to virtual memory
@@ -68,8 +91,6 @@ struct rzg2l_cru_ip {
*
* @vclk: CRU Main clock
*
- * @image_conv_irq: Holds image conversion interrupt number
- *
* @vdev: V4L2 video device associated with CRU
* @v4l2_dev: V4L2 device
* @num_buf: Holds the current number of buffers enabled
@@ -105,8 +126,6 @@ struct rzg2l_cru_dev {
struct clk *vclk;
- int image_conv_irq;
-
struct video_device vdev;
struct v4l2_device v4l2_dev;
u8 num_buf;
@@ -141,6 +160,7 @@ void rzg2l_cru_dma_unregister(struct rzg2l_cru_dev *cru);
int rzg2l_cru_video_register(struct rzg2l_cru_dev *cru);
void rzg2l_cru_video_unregister(struct rzg2l_cru_dev *cru);
+irqreturn_t rzg2l_cru_irq(int irq, void *data);
const struct v4l2_format_info *rzg2l_cru_format_from_pixel(u32 format);
@@ -148,4 +168,8 @@ int rzg2l_cru_ip_subdev_register(struct rzg2l_cru_dev *cru);
void rzg2l_cru_ip_subdev_unregister(struct rzg2l_cru_dev *cru);
struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru);
+const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code);
+const struct rzg2l_cru_ip_format *rzg2l_cru_ip_format_to_fmt(u32 format);
+const struct rzg2l_cru_ip_format *rzg2l_cru_ip_index_to_fmt(u32 index);
+
#endif
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
index c7fdee347ac8..881e910dce02 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
@@ -183,12 +183,15 @@ static const struct rzg2l_csi2_timings rzg2l_csi2_global_timings[] = {
struct rzg2l_csi2_format {
u32 code;
- unsigned int datatype;
unsigned int bpp;
};
static const struct rzg2l_csi2_format rzg2l_csi2_formats[] = {
- { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, .bpp = 16 },
+ { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16 },
+ { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, },
+ { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, },
+ { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, },
+ { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, },
};
static inline struct rzg2l_csi2 *sd_to_csi2(struct v4l2_subdev *sd)
@@ -574,6 +577,9 @@ static int rzg2l_csi2_enum_frame_size(struct v4l2_subdev *sd,
if (fse->index != 0)
return -EINVAL;
+ if (!rzg2l_csi2_code_to_fmt(fse->code))
+ return -EINVAL;
+
fse->min_width = RZG2L_CSI2_MIN_WIDTH;
fse->min_height = RZG2L_CSI2_MIN_HEIGHT;
fse->max_width = RZG2L_CSI2_MAX_WIDTH;
@@ -582,6 +588,25 @@ static int rzg2l_csi2_enum_frame_size(struct v4l2_subdev *sd,
return 0;
}
+static int rzg2l_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+ struct v4l2_mbus_frame_desc *fd)
+{
+ struct rzg2l_csi2 *csi2 = sd_to_csi2(sd);
+ struct media_pad *remote_pad;
+
+ if (!csi2->remote_source)
+ return -ENODEV;
+
+ remote_pad = media_pad_remote_pad_unique(&csi2->pads[RZG2L_CSI2_SINK]);
+ if (IS_ERR(remote_pad)) {
+ dev_err(csi2->dev, "can't get source pad of %s (%ld)\n",
+ csi2->remote_source->name, PTR_ERR(remote_pad));
+ return PTR_ERR(remote_pad);
+ }
+ return v4l2_subdev_call(csi2->remote_source, pad, get_frame_desc,
+ remote_pad->index, fd);
+}
+
static const struct v4l2_subdev_video_ops rzg2l_csi2_video_ops = {
.s_stream = rzg2l_csi2_s_stream,
.pre_streamon = rzg2l_csi2_pre_streamon,
@@ -593,6 +618,7 @@ static const struct v4l2_subdev_pad_ops rzg2l_csi2_pad_ops = {
.enum_frame_size = rzg2l_csi2_enum_frame_size,
.set_fmt = rzg2l_csi2_set_format,
.get_fmt = v4l2_subdev_get_fmt,
+ .get_frame_desc = rzg2l_csi2_get_frame_desc,
};
static const struct v4l2_subdev_ops rzg2l_csi2_subdev_ops = {
@@ -795,14 +821,17 @@ static int rzg2l_csi2_probe(struct platform_device *pdev)
csi2->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
csi2->subdev.entity.ops = &rzg2l_csi2_entity_ops;
- csi2->pads[RZG2L_CSI2_SINK].flags = MEDIA_PAD_FL_SINK;
+ csi2->pads[RZG2L_CSI2_SINK].flags = MEDIA_PAD_FL_SINK |
+ MEDIA_PAD_FL_MUST_CONNECT;
/*
* TODO: RZ/G2L CSI2 supports 4 virtual channels, as virtual
* channels should be implemented by streams API which is under
* development lets hardcode to VC0 for now.
*/
- csi2->pads[RZG2L_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
- ret = media_entity_pads_init(&csi2->subdev.entity, 2, csi2->pads);
+ csi2->pads[RZG2L_CSI2_SOURCE].flags = MEDIA_PAD_FL_SOURCE |
+ MEDIA_PAD_FL_MUST_CONNECT;
+ ret = media_entity_pads_init(&csi2->subdev.entity, ARRAY_SIZE(csi2->pads),
+ csi2->pads);
if (ret)
goto error_pm;
@@ -868,7 +897,7 @@ static const struct of_device_id rzg2l_csi2_of_table[] = {
MODULE_DEVICE_TABLE(of, rzg2l_csi2_of_table);
static struct platform_driver rzg2l_csi2_pdrv = {
- .remove_new = rzg2l_csi2_remove,
+ .remove = rzg2l_csi2_remove,
.probe = rzg2l_csi2_probe,
.driver = {
.name = "rzg2l-csi2",
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
index ac8ebae4ed07..76a2b451f1da 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c
@@ -6,24 +6,55 @@
*/
#include <linux/delay.h>
-#include "rzg2l-cru.h"
+#include <media/mipi-csi2.h>
-struct rzg2l_cru_ip_format {
- u32 code;
- unsigned int datatype;
- unsigned int bpp;
-};
+#include "rzg2l-cru.h"
+#include "rzg2l-cru-regs.h"
static const struct rzg2l_cru_ip_format rzg2l_cru_ip_formats[] = {
- { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, .bpp = 16 },
-};
-
-enum rzg2l_csi2_pads {
- RZG2L_CRU_IP_SINK = 0,
- RZG2L_CRU_IP_SOURCE,
+ {
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .datatype = MIPI_CSI2_DT_YUV422_8B,
+ .format = V4L2_PIX_FMT_UYVY,
+ .bpp = 2,
+ .icndmr = ICnDMR_YCMODE_UYVY,
+ .yuv = true,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .format = V4L2_PIX_FMT_SBGGR8,
+ .datatype = MIPI_CSI2_DT_RAW8,
+ .bpp = 1,
+ .icndmr = 0,
+ .yuv = false,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGBRG8_1X8,
+ .format = V4L2_PIX_FMT_SGBRG8,
+ .datatype = MIPI_CSI2_DT_RAW8,
+ .bpp = 1,
+ .icndmr = 0,
+ .yuv = false,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .format = V4L2_PIX_FMT_SGRBG8,
+ .datatype = MIPI_CSI2_DT_RAW8,
+ .bpp = 1,
+ .icndmr = 0,
+ .yuv = false,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SRGGB8_1X8,
+ .format = V4L2_PIX_FMT_SRGGB8,
+ .datatype = MIPI_CSI2_DT_RAW8,
+ .bpp = 1,
+ .icndmr = 0,
+ .yuv = false,
+ },
};
-static const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code)
+const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code)
{
unsigned int i;
@@ -34,6 +65,26 @@ static const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int c
return NULL;
}
+const struct rzg2l_cru_ip_format *rzg2l_cru_ip_format_to_fmt(u32 format)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) {
+ if (rzg2l_cru_ip_formats[i].format == format)
+ return &rzg2l_cru_ip_formats[i];
+ }
+
+ return NULL;
+}
+
+const struct rzg2l_cru_ip_format *rzg2l_cru_ip_index_to_fmt(u32 index)
+{
+ if (index >= ARRAY_SIZE(rzg2l_cru_ip_formats))
+ return NULL;
+
+ return &rzg2l_cru_ip_formats[index];
+}
+
struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru)
{
struct v4l2_subdev_state *state;
@@ -149,7 +200,7 @@ static int rzg2l_cru_ip_enum_frame_size(struct v4l2_subdev *sd,
if (fse->index != 0)
return -EINVAL;
- if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)
+ if (!rzg2l_cru_ip_code_to_fmt(fse->code))
return -EINVAL;
fse->min_width = RZG2L_CRU_MIN_INPUT_WIDTH;
@@ -217,8 +268,10 @@ int rzg2l_cru_ip_subdev_register(struct rzg2l_cru_dev *cru)
ip->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
ip->subdev.entity.ops = &rzg2l_cru_ip_entity_ops;
- ip->pads[0].flags = MEDIA_PAD_FL_SINK;
- ip->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+ ip->pads[RZG2L_CRU_IP_SINK].flags = MEDIA_PAD_FL_SINK |
+ MEDIA_PAD_FL_MUST_CONNECT;
+ ip->pads[RZG2L_CRU_IP_SOURCE].flags = MEDIA_PAD_FL_SOURCE |
+ MEDIA_PAD_FL_MUST_CONNECT;
ret = media_entity_pads_init(&ip->subdev.entity, 2, ip->pads);
if (ret)
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c
index b16b8af6e8f8..17a1af507a27 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c
@@ -15,75 +15,12 @@
#include <linux/delay.h>
#include <linux/pm_runtime.h>
+#include <media/mipi-csi2.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-dma-contig.h>
#include "rzg2l-cru.h"
-
-/* HW CRU Registers Definition */
-
-/* CRU Control Register */
-#define CRUnCTRL 0x0
-#define CRUnCTRL_VINSEL(x) ((x) << 0)
-
-/* CRU Interrupt Enable Register */
-#define CRUnIE 0x4
-#define CRUnIE_EFE BIT(17)
-
-/* CRU Interrupt Status Register */
-#define CRUnINTS 0x8
-#define CRUnINTS_SFS BIT(16)
-
-/* CRU Reset Register */
-#define CRUnRST 0xc
-#define CRUnRST_VRESETN BIT(0)
-
-/* Memory Bank Base Address (Lower) Register for CRU Image Data */
-#define AMnMBxADDRL(x) (0x100 + ((x) * 8))
-
-/* Memory Bank Base Address (Higher) Register for CRU Image Data */
-#define AMnMBxADDRH(x) (0x104 + ((x) * 8))
-
-/* Memory Bank Enable Register for CRU Image Data */
-#define AMnMBVALID 0x148
-#define AMnMBVALID_MBVALID(x) GENMASK(x, 0)
-
-/* Memory Bank Status Register for CRU Image Data */
-#define AMnMBS 0x14c
-#define AMnMBS_MBSTS 0x7
-
-/* AXI Master FIFO Pointer Register for CRU Image Data */
-#define AMnFIFOPNTR 0x168
-#define AMnFIFOPNTR_FIFOWPNTR GENMASK(7, 0)
-#define AMnFIFOPNTR_FIFORPNTR_Y GENMASK(23, 16)
-
-/* AXI Master Transfer Stop Register for CRU Image Data */
-#define AMnAXISTP 0x174
-#define AMnAXISTP_AXI_STOP BIT(0)
-
-/* AXI Master Transfer Stop Status Register for CRU Image Data */
-#define AMnAXISTPACK 0x178
-#define AMnAXISTPACK_AXI_STOP_ACK BIT(0)
-
-/* CRU Image Processing Enable Register */
-#define ICnEN 0x200
-#define ICnEN_ICEN BIT(0)
-
-/* CRU Image Processing Main Control Register */
-#define ICnMC 0x208
-#define ICnMC_CSCTHR BIT(5)
-#define ICnMC_INF_YUV8_422 (0x1e << 16)
-#define ICnMC_INF_USER (0x30 << 16)
-#define ICnMC_VCSEL(x) ((x) << 22)
-#define ICnMC_INF_MASK GENMASK(21, 16)
-
-/* CRU Module Status Register */
-#define ICnMS 0x254
-#define ICnMS_IA BIT(2)
-
-/* CRU Data Output Mode Register */
-#define ICnDMR 0x26c
-#define ICnDMR_YCMODE_UYVY (1 << 4)
+#include "rzg2l-cru-regs.h"
#define RZG2L_TIMEOUT_MS 100
#define RZG2L_RETRIES 10
@@ -184,46 +121,6 @@ static void rzg2l_cru_buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&cru->qlock, flags);
}
-static int rzg2l_cru_mc_validate_format(struct rzg2l_cru_dev *cru,
- struct v4l2_subdev *sd,
- struct media_pad *pad)
-{
- struct v4l2_subdev_format fmt = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
-
- fmt.pad = pad->index;
- if (v4l2_subdev_call_state_active(sd, pad, get_fmt, &fmt))
- return -EPIPE;
-
- switch (fmt.format.code) {
- case MEDIA_BUS_FMT_UYVY8_1X16:
- break;
- default:
- return -EPIPE;
- }
-
- switch (fmt.format.field) {
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- case V4L2_FIELD_NONE:
- case V4L2_FIELD_INTERLACED_TB:
- case V4L2_FIELD_INTERLACED_BT:
- case V4L2_FIELD_INTERLACED:
- case V4L2_FIELD_SEQ_TB:
- case V4L2_FIELD_SEQ_BT:
- break;
- default:
- return -EPIPE;
- }
-
- if (fmt.format.width != cru->format.width ||
- fmt.format.height != cru->format.height)
- return -EPIPE;
-
- return 0;
-}
-
static void rzg2l_cru_set_slot_addr(struct rzg2l_cru_dev *cru,
int slot, dma_addr_t addr)
{
@@ -278,6 +175,7 @@ static void rzg2l_cru_fill_hw_slot(struct rzg2l_cru_dev *cru, int slot)
static void rzg2l_cru_initialize_axi(struct rzg2l_cru_dev *cru)
{
unsigned int slot;
+ u32 amnaxiattr;
/*
* Set image data memory banks.
@@ -287,55 +185,47 @@ static void rzg2l_cru_initialize_axi(struct rzg2l_cru_dev *cru)
for (slot = 0; slot < cru->num_buf; slot++)
rzg2l_cru_fill_hw_slot(cru, slot);
+
+ /* Set AXI burst max length to recommended setting */
+ amnaxiattr = rzg2l_cru_read(cru, AMnAXIATTR) & ~AMnAXIATTR_AXILEN_MASK;
+ amnaxiattr |= AMnAXIATTR_AXILEN;
+ rzg2l_cru_write(cru, AMnAXIATTR, amnaxiattr);
}
-static void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru, bool *input_is_yuv,
- struct v4l2_mbus_framefmt *ip_sd_fmt)
+static void rzg2l_cru_csi2_setup(struct rzg2l_cru_dev *cru,
+ const struct rzg2l_cru_ip_format *ip_fmt,
+ u8 csi_vc)
{
- u32 icnmc;
-
- switch (ip_sd_fmt->code) {
- case MEDIA_BUS_FMT_UYVY8_1X16:
- icnmc = ICnMC_INF_YUV8_422;
- *input_is_yuv = true;
- break;
- default:
- *input_is_yuv = false;
- icnmc = ICnMC_INF_USER;
- break;
- }
+ u32 icnmc = ICnMC_INF(ip_fmt->datatype);
icnmc |= (rzg2l_cru_read(cru, ICnMC) & ~ICnMC_INF_MASK);
/* Set virtual channel CSI2 */
- icnmc |= ICnMC_VCSEL(cru->csi.channel);
+ icnmc |= ICnMC_VCSEL(csi_vc);
rzg2l_cru_write(cru, ICnMC, icnmc);
}
static int rzg2l_cru_initialize_image_conv(struct rzg2l_cru_dev *cru,
- struct v4l2_mbus_framefmt *ip_sd_fmt)
+ struct v4l2_mbus_framefmt *ip_sd_fmt,
+ u8 csi_vc)
{
- bool output_is_yuv = false;
- bool input_is_yuv = false;
- u32 icndmr;
+ const struct rzg2l_cru_ip_format *cru_video_fmt;
+ const struct rzg2l_cru_ip_format *cru_ip_fmt;
- rzg2l_cru_csi2_setup(cru, &input_is_yuv, ip_sd_fmt);
+ cru_ip_fmt = rzg2l_cru_ip_code_to_fmt(ip_sd_fmt->code);
+ rzg2l_cru_csi2_setup(cru, cru_ip_fmt, csi_vc);
/* Output format */
- switch (cru->format.pixelformat) {
- case V4L2_PIX_FMT_UYVY:
- icndmr = ICnDMR_YCMODE_UYVY;
- output_is_yuv = true;
- break;
- default:
+ cru_video_fmt = rzg2l_cru_ip_format_to_fmt(cru->format.pixelformat);
+ if (!cru_video_fmt) {
dev_err(cru->dev, "Invalid pixelformat (0x%x)\n",
cru->format.pixelformat);
return -EINVAL;
}
/* If input and output use same colorspace, do bypass mode */
- if (output_is_yuv == input_is_yuv)
+ if (cru_ip_fmt->yuv == cru_video_fmt->yuv)
rzg2l_cru_write(cru, ICnMC,
rzg2l_cru_read(cru, ICnMC) | ICnMC_CSCTHR);
else
@@ -343,7 +233,7 @@ static int rzg2l_cru_initialize_image_conv(struct rzg2l_cru_dev *cru,
rzg2l_cru_read(cru, ICnMC) & (~ICnMC_CSCTHR));
/* Set output data format */
- rzg2l_cru_write(cru, ICnDMR, icndmr);
+ rzg2l_cru_write(cru, ICnDMR, cru_video_fmt->icndmr);
return 0;
}
@@ -422,12 +312,47 @@ void rzg2l_cru_stop_image_processing(struct rzg2l_cru_dev *cru)
spin_unlock_irqrestore(&cru->qlock, flags);
}
+static int rzg2l_cru_get_virtual_channel(struct rzg2l_cru_dev *cru)
+{
+ struct v4l2_mbus_frame_desc fd = { };
+ struct media_pad *remote_pad;
+ int ret;
+
+ remote_pad = media_pad_remote_pad_unique(&cru->ip.pads[RZG2L_CRU_IP_SINK]);
+ ret = v4l2_subdev_call(cru->ip.remote, pad, get_frame_desc, remote_pad->index, &fd);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ dev_err(cru->dev, "get_frame_desc failed on IP remote subdev\n");
+ return ret;
+ }
+ /* If remote subdev does not implement .get_frame_desc default to VC0. */
+ if (ret == -ENOIOCTLCMD)
+ return 0;
+
+ if (fd.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
+ dev_err(cru->dev, "get_frame_desc returned invalid bus type %d\n", fd.type);
+ return -EINVAL;
+ }
+
+ if (!fd.num_entries) {
+ dev_err(cru->dev, "get_frame_desc returned zero entries\n");
+ return -EINVAL;
+ }
+
+ return fd.entry[0].bus.csi2.vc;
+}
+
int rzg2l_cru_start_image_processing(struct rzg2l_cru_dev *cru)
{
struct v4l2_mbus_framefmt *fmt = rzg2l_cru_ip_get_src_fmt(cru);
unsigned long flags;
+ u8 csi_vc;
int ret;
+ ret = rzg2l_cru_get_virtual_channel(cru);
+ if (ret < 0)
+ return ret;
+ csi_vc = ret;
+
spin_lock_irqsave(&cru->qlock, flags);
/* Select a video input */
@@ -444,7 +369,7 @@ int rzg2l_cru_start_image_processing(struct rzg2l_cru_dev *cru)
rzg2l_cru_initialize_axi(cru);
/* Initialize image convert */
- ret = rzg2l_cru_initialize_image_conv(cru, fmt);
+ ret = rzg2l_cru_initialize_image_conv(cru, fmt, csi_vc);
if (ret) {
spin_unlock_irqrestore(&cru->qlock, flags);
return ret;
@@ -492,10 +417,6 @@ static int rzg2l_cru_set_stream(struct rzg2l_cru_dev *cru, int on)
return stream_off_ret;
}
- ret = rzg2l_cru_mc_validate_format(cru, sd, pad);
- if (ret)
- return ret;
-
pipe = media_entity_pipeline(&sd->entity) ? : &cru->vdev.pipe;
ret = video_device_pipeline_start(&cru->vdev, pipe);
if (ret)
@@ -527,7 +448,7 @@ static void rzg2l_cru_stop_streaming(struct rzg2l_cru_dev *cru)
rzg2l_cru_set_stream(cru, 0);
}
-static irqreturn_t rzg2l_cru_irq(int irq, void *data)
+irqreturn_t rzg2l_cru_irq(int irq, void *data)
{
struct rzg2l_cru_dev *cru = data;
unsigned int handled = 0;
@@ -637,13 +558,6 @@ static int rzg2l_cru_start_streaming_vq(struct vb2_queue *vq, unsigned int count
goto assert_aresetn;
}
- ret = request_irq(cru->image_conv_irq, rzg2l_cru_irq,
- IRQF_SHARED, KBUILD_MODNAME, cru);
- if (ret) {
- dev_err(cru->dev, "failed to request irq\n");
- goto assert_presetn;
- }
-
/* Allocate scratch buffer. */
cru->scratch = dma_alloc_coherent(cru->dev, cru->format.sizeimage,
&cru->scratch_phys, GFP_KERNEL);
@@ -651,7 +565,7 @@ static int rzg2l_cru_start_streaming_vq(struct vb2_queue *vq, unsigned int count
return_unused_buffers(cru, VB2_BUF_STATE_QUEUED);
dev_err(cru->dev, "Failed to allocate scratch buffer\n");
ret = -ENOMEM;
- goto free_image_conv_irq;
+ goto assert_presetn;
}
cru->sequence = 0;
@@ -670,9 +584,6 @@ out:
if (ret)
dma_free_coherent(cru->dev, cru->format.sizeimage, cru->scratch,
cru->scratch_phys);
-free_image_conv_irq:
- free_irq(cru->image_conv_irq, cru);
-
assert_presetn:
reset_control_assert(cru->presetn);
@@ -698,7 +609,6 @@ static void rzg2l_cru_stop_streaming_vq(struct vb2_queue *vq)
dma_free_coherent(cru->dev, cru->format.sizeimage,
cru->scratch, cru->scratch_phys);
- free_irq(cru->image_conv_irq, cru);
return_unused_buffers(cru, VB2_BUF_STATE_ERROR);
reset_control_assert(cru->presetn);
@@ -712,8 +622,6 @@ static const struct vb2_ops rzg2l_cru_qops = {
.buf_queue = rzg2l_cru_buffer_queue,
.start_streaming = rzg2l_cru_start_streaming_vq,
.stop_streaming = rzg2l_cru_stop_streaming_vq,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
void rzg2l_cru_dma_unregister(struct rzg2l_cru_dev *cru)
@@ -775,46 +683,16 @@ error:
* V4L2 stuff
*/
-static const struct v4l2_format_info rzg2l_cru_formats[] = {
- {
- .format = V4L2_PIX_FMT_UYVY,
- .bpp[0] = 2,
- },
-};
-
-const struct v4l2_format_info *rzg2l_cru_format_from_pixel(u32 format)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(rzg2l_cru_formats); i++)
- if (rzg2l_cru_formats[i].format == format)
- return rzg2l_cru_formats + i;
-
- return NULL;
-}
-
-static u32 rzg2l_cru_format_bytesperline(struct v4l2_pix_format *pix)
-{
- const struct v4l2_format_info *fmt;
-
- fmt = rzg2l_cru_format_from_pixel(pix->pixelformat);
-
- if (WARN_ON(!fmt))
- return -EINVAL;
-
- return pix->width * fmt->bpp[0];
-}
-
-static u32 rzg2l_cru_format_sizeimage(struct v4l2_pix_format *pix)
-{
- return pix->bytesperline * pix->height;
-}
-
static void rzg2l_cru_format_align(struct rzg2l_cru_dev *cru,
struct v4l2_pix_format *pix)
{
- if (!rzg2l_cru_format_from_pixel(pix->pixelformat))
+ const struct rzg2l_cru_ip_format *fmt;
+
+ fmt = rzg2l_cru_ip_format_to_fmt(pix->pixelformat);
+ if (!fmt) {
pix->pixelformat = RZG2L_CRU_DEFAULT_FORMAT;
+ fmt = rzg2l_cru_ip_format_to_fmt(pix->pixelformat);
+ }
switch (pix->field) {
case V4L2_FIELD_TOP:
@@ -833,8 +711,8 @@ static void rzg2l_cru_format_align(struct rzg2l_cru_dev *cru,
v4l_bound_align_image(&pix->width, 320, RZG2L_CRU_MAX_INPUT_WIDTH, 1,
&pix->height, 240, RZG2L_CRU_MAX_INPUT_HEIGHT, 2, 0);
- pix->bytesperline = rzg2l_cru_format_bytesperline(pix);
- pix->sizeimage = rzg2l_cru_format_sizeimage(pix);
+ pix->bytesperline = pix->width * fmt->bpp;
+ pix->sizeimage = pix->bytesperline * pix->height;
dev_dbg(cru->dev, "Format %ux%u bpl: %u size: %u\n",
pix->width, pix->height, pix->bytesperline, pix->sizeimage);
@@ -905,10 +783,13 @@ static int rzg2l_cru_g_fmt_vid_cap(struct file *file, void *priv,
static int rzg2l_cru_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- if (f->index >= ARRAY_SIZE(rzg2l_cru_formats))
+ const struct rzg2l_cru_ip_format *fmt;
+
+ fmt = rzg2l_cru_ip_index_to_fmt(f->index);
+ if (!fmt)
return -EINVAL;
- f->pixelformat = rzg2l_cru_formats[f->index].format;
+ f->pixelformat = fmt->format;
return 0;
}
@@ -984,6 +865,43 @@ static const struct v4l2_file_operations rzg2l_cru_fops = {
.read = vb2_fop_read,
};
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+static int rzg2l_cru_video_link_validate(struct media_link *link)
+{
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ const struct rzg2l_cru_ip_format *video_fmt;
+ struct v4l2_subdev *subdev;
+ struct rzg2l_cru_dev *cru;
+ int ret;
+
+ subdev = media_entity_to_v4l2_subdev(link->source->entity);
+ fmt.pad = link->source->index;
+ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+ if (ret < 0)
+ return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+
+ cru = container_of(media_entity_to_video_device(link->sink->entity),
+ struct rzg2l_cru_dev, vdev);
+ video_fmt = rzg2l_cru_ip_format_to_fmt(cru->format.pixelformat);
+
+ if (fmt.format.width != cru->format.width ||
+ fmt.format.height != cru->format.height ||
+ fmt.format.field != cru->format.field ||
+ video_fmt->code != fmt.format.code)
+ return -EPIPE;
+
+ return 0;
+}
+
+static const struct media_entity_operations rzg2l_cru_video_media_ops = {
+ .link_validate = rzg2l_cru_video_link_validate,
+};
+
static void rzg2l_cru_v4l2_init(struct rzg2l_cru_dev *cru)
{
struct video_device *vdev = &cru->vdev;
@@ -995,6 +913,7 @@ static void rzg2l_cru_v4l2_init(struct rzg2l_cru_dev *cru)
vdev->lock = &cru->lock;
vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
vdev->device_caps |= V4L2_CAP_IO_MC;
+ vdev->entity.ops = &rzg2l_cru_video_media_ops;
vdev->fops = &rzg2l_cru_fops;
vdev->ioctl_ops = &rzg2l_cru_ioctl_ops;
diff --git a/drivers/media/platform/renesas/sh_vou.c b/drivers/media/platform/renesas/sh_vou.c
index 1e74dd601c2b..4ad7ae188d5b 100644
--- a/drivers/media/platform/renesas/sh_vou.c
+++ b/drivers/media/platform/renesas/sh_vou.c
@@ -360,8 +360,6 @@ static const struct vb2_ops sh_vou_qops = {
.buf_queue = sh_vou_buf_queue,
.start_streaming = sh_vou_start_streaming,
.stop_streaming = sh_vou_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* Video IOCTLs */
@@ -1359,7 +1357,7 @@ static void sh_vou_remove(struct platform_device *pdev)
}
static struct platform_driver sh_vou = {
- .remove_new = sh_vou_remove,
+ .remove = sh_vou_remove,
.driver = {
.name = "sh-vou",
},
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c
index 1aac44d68731..9fc6bf624a52 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c
@@ -1005,7 +1005,7 @@ MODULE_DEVICE_TABLE(of, vsp1_of_match);
static struct platform_driver vsp1_platform_driver = {
.probe = vsp1_probe,
- .remove_new = vsp1_remove,
+ .remove = vsp1_remove,
.driver = {
.name = "vsp1",
.pm = &vsp1_pm_ops,
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_histo.c b/drivers/media/platform/renesas/vsp1/vsp1_histo.c
index 9c2d4c91bfad..c762202877ba 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_histo.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_histo.c
@@ -155,8 +155,6 @@ static const struct vb2_ops histo_video_queue_qops = {
.queue_setup = histo_queue_setup,
.buf_prepare = histo_buffer_prepare,
.buf_queue = histo_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = histo_start_streaming,
.stop_streaming = histo_stop_streaming,
};
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c
index e728f9f5160e..03f4efd6b82b 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_video.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c
@@ -873,8 +873,6 @@ static const struct vb2_ops vsp1_video_queue_qops = {
.queue_setup = vsp1_video_queue_setup,
.buf_prepare = vsp1_video_buffer_prepare,
.buf_queue = vsp1_video_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = vsp1_video_start_streaming,
.stop_streaming = vsp1_video_stop_streaming,
};
diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
index 70808049d2e8..8a48e9d91f96 100644
--- a/drivers/media/platform/rockchip/rga/rga-buf.c
+++ b/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -218,8 +218,6 @@ const struct vb2_ops rga_qops = {
.buf_prepare = rga_buf_prepare,
.buf_queue = rga_buf_queue,
.buf_cleanup = rga_buf_cleanup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = rga_buf_start_streaming,
.stop_streaming = rga_buf_stop_streaming,
};
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 0e768f3e9eda..1739ac0c8e92 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -102,7 +102,7 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
src_vq->drv_priv = ctx;
src_vq->ops = &rga_qops;
src_vq->mem_ops = &vb2_dma_sg_memops;
- dst_vq->gfp_flags = __GFP_DMA32;
+ src_vq->gfp_flags = __GFP_DMA32;
src_vq->buf_struct_size = sizeof(struct rga_vb_buffer);
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
src_vq->lock = &ctx->rga->mutex;
@@ -972,7 +972,7 @@ MODULE_DEVICE_TABLE(of, rockchip_rga_match);
static struct platform_driver rga_pdrv = {
.probe = rga_probe,
- .remove_new = rga_remove,
+ .remove = rga_remove,
.driver = {
.name = RGA_NAME,
.pm = &rga_pm,
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
index 2bddb4fa8a5c..02339cd94486 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
@@ -1203,8 +1203,6 @@ static const struct vb2_ops rkisp1_vb2_ops = {
.buf_init = rkisp1_vb2_buf_init,
.buf_queue = rkisp1_vb2_buf_queue,
.buf_prepare = rkisp1_vb2_buf_prepare,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = rkisp1_vb2_stop_streaming,
.start_streaming = rkisp1_vb2_start_streaming,
};
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
index dd114ab77800..0100b9c3edbe 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
@@ -752,7 +752,7 @@ static struct platform_driver rkisp1_drv = {
.pm = &rkisp1_pm_ops,
},
.probe = rkisp1_probe,
- .remove_new = rkisp1_remove,
+ .remove = rkisp1_remove,
};
module_platform_driver(rkisp1_drv);
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 320581a9f866..b28f4140c8a3 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -2704,8 +2704,6 @@ static const struct vb2_ops rkisp1_params_vb2_ops = {
.queue_setup = rkisp1_params_vb2_queue_setup,
.buf_init = rkisp1_params_vb2_buf_init,
.buf_cleanup = rkisp1_params_vb2_buf_cleanup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_queue = rkisp1_params_vb2_buf_queue,
.buf_prepare = rkisp1_params_vb2_buf_prepare,
.stop_streaming = rkisp1_params_vb2_stop_streaming,
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
index a502719e916a..d5fdb8f82dc7 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c
@@ -150,8 +150,6 @@ static const struct vb2_ops rkisp1_stats_vb2_ops = {
.queue_setup = rkisp1_stats_vb2_queue_setup,
.buf_queue = rkisp1_stats_vb2_buf_queue,
.buf_prepare = rkisp1_stats_vb2_buf_prepare,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = rkisp1_stats_vb2_stop_streaming,
};
diff --git a/drivers/media/platform/samsung/exynos-gsc/gsc-core.c b/drivers/media/platform/samsung/exynos-gsc/gsc-core.c
index f45f5c8612a6..a06d7cace92f 100644
--- a/drivers/media/platform/samsung/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/samsung/exynos-gsc/gsc-core.c
@@ -1309,7 +1309,7 @@ static const struct dev_pm_ops gsc_pm_ops = {
static struct platform_driver gsc_driver = {
.probe = gsc_probe,
- .remove_new = gsc_remove,
+ .remove = gsc_remove,
.driver = {
.name = GSC_MODULE_NAME,
.pm = &gsc_pm_ops,
diff --git a/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c b/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c
index b7854ce5fb8e..4bda1c369c44 100644
--- a/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/samsung/exynos-gsc/gsc-m2m.c
@@ -276,8 +276,6 @@ static const struct vb2_ops gsc_m2m_qops = {
.queue_setup = gsc_m2m_queue_setup,
.buf_prepare = gsc_m2m_buf_prepare,
.buf_queue = gsc_m2m_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = gsc_m2m_stop_streaming,
.start_streaming = gsc_m2m_start_streaming,
};
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-capture.c b/drivers/media/platform/samsung/exynos4-is/fimc-capture.c
index ffa4ea21387d..c3c2e474a18a 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-capture.c
@@ -455,8 +455,6 @@ static const struct vb2_ops fimc_capture_qops = {
.queue_setup = queue_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.c b/drivers/media/platform/samsung/exynos4-is/fimc-core.c
index adfc2d73d04b..2c9edd0a559b 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.c
@@ -1157,7 +1157,7 @@ static const struct dev_pm_ops fimc_pm_ops = {
static struct platform_driver fimc_driver = {
.probe = fimc_probe,
- .remove_new = fimc_remove,
+ .remove = fimc_remove,
.driver = {
.of_match_table = fimc_of_match,
.name = FIMC_DRIVER_NAME,
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c
index 44363c4241d5..b243cbb1d010 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c
@@ -137,7 +137,7 @@ static const struct of_device_id fimc_is_i2c_of_match[] = {
static struct platform_driver fimc_is_i2c_driver = {
.probe = fimc_is_i2c_probe,
- .remove_new = fimc_is_i2c_remove,
+ .remove = fimc_is_i2c_remove,
.driver = {
.of_match_table = fimc_is_i2c_of_match,
.name = "fimc-isp-i2c",
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-is.c b/drivers/media/platform/samsung/exynos4-is/fimc-is.c
index 0a4b58daf924..2e8fe9e49735 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-is.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-is.c
@@ -963,7 +963,7 @@ static const struct dev_pm_ops fimc_is_pm_ops = {
static struct platform_driver fimc_is_driver = {
.probe = fimc_is_probe,
- .remove_new = fimc_is_remove,
+ .remove = fimc_is_remove,
.driver = {
.of_match_table = fimc_is_of_match,
.name = FIMC_IS_DRV_NAME,
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c b/drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c
index 06c4352562b3..ad219ac1b951 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c
@@ -255,8 +255,6 @@ static const struct vb2_ops isp_video_capture_qops = {
.queue_setup = isp_video_capture_queue_setup,
.buf_prepare = isp_video_capture_buffer_prepare,
.buf_queue = isp_video_capture_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = isp_video_capture_start_streaming,
.stop_streaming = isp_video_capture_stop_streaming,
};
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c
index 1a4d75443215..f23e51e3da2f 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c
@@ -441,8 +441,6 @@ static const struct vb2_ops fimc_lite_qops = {
.queue_setup = queue_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
@@ -1654,7 +1652,7 @@ MODULE_DEVICE_TABLE(of, flite_of_match);
static struct platform_driver fimc_lite_driver = {
.probe = fimc_lite_probe,
- .remove_new = fimc_lite_remove,
+ .remove = fimc_lite_remove,
.driver = {
.of_match_table = flite_of_match,
.name = FIMC_LITE_DRV_NAME,
diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c b/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c
index 199997eec1cc..951433c8e92a 100644
--- a/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/samsung/exynos4-is/fimc-m2m.c
@@ -216,8 +216,6 @@ static const struct vb2_ops fimc_qops = {
.queue_setup = fimc_queue_setup,
.buf_prepare = fimc_buf_prepare,
.buf_queue = fimc_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = stop_streaming,
.start_streaming = start_streaming,
};
diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c
index 5f10bb4eb4f7..b5ee3c547789 100644
--- a/drivers/media/platform/samsung/exynos4-is/media-dev.c
+++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c
@@ -1564,7 +1564,7 @@ MODULE_DEVICE_TABLE(of, fimc_md_of_match);
static struct platform_driver fimc_md_driver = {
.probe = fimc_md_probe,
- .remove_new = fimc_md_remove,
+ .remove = fimc_md_remove,
.driver = {
.of_match_table = of_match_ptr(fimc_md_of_match),
.name = "s5p-fimc-md",
diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.h b/drivers/media/platform/samsung/exynos4-is/media-dev.h
index 786264cf79dc..a50e58ab7ef7 100644
--- a/drivers/media/platform/samsung/exynos4-is/media-dev.h
+++ b/drivers/media/platform/samsung/exynos4-is/media-dev.h
@@ -178,8 +178,9 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
#ifdef CONFIG_OF
static inline bool fimc_md_is_isp_available(struct device_node *node)
{
- node = of_get_child_by_name(node, FIMC_IS_OF_NODE_NAME);
- return node ? of_device_is_available(node) : false;
+ struct device_node *child __free(device_node) =
+ of_get_child_by_name(node, FIMC_IS_OF_NODE_NAME);
+ return child ? of_device_is_available(child) : false;
}
#else
#define fimc_md_is_isp_available(node) (false)
diff --git a/drivers/media/platform/samsung/exynos4-is/mipi-csis.c b/drivers/media/platform/samsung/exynos4-is/mipi-csis.c
index 4b9b20ba3504..63f3eecdd7e6 100644
--- a/drivers/media/platform/samsung/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/samsung/exynos4-is/mipi-csis.c
@@ -1020,7 +1020,7 @@ MODULE_DEVICE_TABLE(of, s5pcsis_of_match);
static struct platform_driver s5pcsis_driver = {
.probe = s5pcsis_probe,
- .remove_new = s5pcsis_remove,
+ .remove = s5pcsis_remove,
.driver = {
.of_match_table = s5pcsis_of_match,
.name = CSIS_DRIVER_NAME,
diff --git a/drivers/media/platform/samsung/s3c-camif/camif-capture.c b/drivers/media/platform/samsung/s3c-camif/camif-capture.c
index be58260ea67e..bd1149e8abc2 100644
--- a/drivers/media/platform/samsung/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/samsung/s3c-camif/camif-capture.c
@@ -525,8 +525,6 @@ static const struct vb2_ops s3c_camif_qops = {
.queue_setup = queue_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
diff --git a/drivers/media/platform/samsung/s3c-camif/camif-core.c b/drivers/media/platform/samsung/s3c-camif/camif-core.c
index e4529f666e20..de6e8f151849 100644
--- a/drivers/media/platform/samsung/s3c-camif/camif-core.c
+++ b/drivers/media/platform/samsung/s3c-camif/camif-core.c
@@ -622,7 +622,7 @@ static const struct dev_pm_ops s3c_camif_pm_ops = {
static struct platform_driver s3c_camif_driver = {
.probe = s3c_camif_probe,
- .remove_new = s3c_camif_remove,
+ .remove = s3c_camif_remove,
.id_table = s3c_camif_driver_ids,
.driver = {
.name = S3C_CAMIF_DRIVER_NAME,
diff --git a/drivers/media/platform/samsung/s5p-g2d/g2d.c b/drivers/media/platform/samsung/s5p-g2d/g2d.c
index 89aeba47ed07..ffed16a34493 100644
--- a/drivers/media/platform/samsung/s5p-g2d/g2d.c
+++ b/drivers/media/platform/samsung/s5p-g2d/g2d.c
@@ -133,8 +133,6 @@ static const struct vb2_ops g2d_qops = {
.queue_setup = g2d_queue_setup,
.buf_prepare = g2d_buf_prepare,
.buf_queue = g2d_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -777,7 +775,7 @@ MODULE_DEVICE_TABLE(of, exynos_g2d_match);
static struct platform_driver g2d_pdrv = {
.probe = g2d_probe,
- .remove_new = g2d_remove,
+ .remove = g2d_remove,
.driver = {
.name = G2D_NAME,
.of_match_table = exynos_g2d_match,
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c
index d2c4a0178b3c..ac4cf269456a 100644
--- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c
@@ -775,11 +775,14 @@ static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx)
(unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sos + 2;
jpeg_buffer.curr = 0;
- word = 0;
-
if (get_word_be(&jpeg_buffer, &word))
return;
- jpeg_buffer.size = (long)word - 2;
+
+ if (word < 2)
+ jpeg_buffer.size = 0;
+ else
+ jpeg_buffer.size = (long)word - 2;
+
jpeg_buffer.data += 2;
jpeg_buffer.curr = 0;
@@ -1058,6 +1061,7 @@ static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
if (byte == -1)
return -1;
*word = (unsigned int)byte | temp;
+
return 0;
}
@@ -1145,7 +1149,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
if (get_word_be(&jpeg_buffer, &word))
break;
length = (long)word - 2;
- if (!length)
+ if (length <= 0)
return false;
sof = jpeg_buffer.curr; /* after 0xffc0 */
sof_len = length;
@@ -1176,7 +1180,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
if (get_word_be(&jpeg_buffer, &word))
break;
length = (long)word - 2;
- if (!length)
+ if (length <= 0)
return false;
if (n_dqt >= S5P_JPEG_MAX_MARKER)
return false;
@@ -1189,7 +1193,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
if (get_word_be(&jpeg_buffer, &word))
break;
length = (long)word - 2;
- if (!length)
+ if (length <= 0)
return false;
if (n_dht >= S5P_JPEG_MAX_MARKER)
return false;
@@ -1214,6 +1218,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
if (get_word_be(&jpeg_buffer, &word))
break;
length = (long)word - 2;
+ /* No need to check underflows as skip() does it */
skip(&jpeg_buffer, length);
break;
}
@@ -2590,8 +2595,6 @@ static const struct vb2_ops s5p_jpeg_qops = {
.queue_setup = s5p_jpeg_queue_setup,
.buf_prepare = s5p_jpeg_buf_prepare,
.buf_queue = s5p_jpeg_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = s5p_jpeg_start_streaming,
.stop_streaming = s5p_jpeg_stop_streaming,
};
@@ -3160,7 +3163,7 @@ static void *jpeg_get_drv_data(struct device *dev)
static struct platform_driver s5p_jpeg_driver = {
.probe = s5p_jpeg_probe,
- .remove_new = s5p_jpeg_remove,
+ .remove = s5p_jpeg_remove,
.driver = {
.of_match_table = samsung_jpeg_match,
.name = S5P_JPEG_M2M_NAME,
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c
index 637a5104d948..6657d294c10a 100644
--- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c
+++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c
@@ -427,11 +427,6 @@ void exynos3250_jpeg_clear_int_status(void __iomem *regs,
writel(value, regs + EXYNOS3250_JPGINTST);
}
-unsigned int exynos3250_jpeg_operating(void __iomem *regs)
-{
- return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;
-}
-
unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)
{
return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h
index 15af928fad76..709c61ae322c 100644
--- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h
+++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h
@@ -45,7 +45,6 @@ void exynos3250_jpeg_rstart(void __iomem *regs);
unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs);
void exynos3250_jpeg_clear_int_status(void __iomem *regs,
unsigned int value);
-unsigned int exynos3250_jpeg_operating(void __iomem *regs);
unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs);
void exynos3250_jpeg_dec_stream_size(void __iomem *regs, unsigned int size);
void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs, unsigned int sratio);
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c
index 0828cfa783fe..479288fc8c77 100644
--- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c
+++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c
@@ -185,11 +185,6 @@ unsigned int exynos4_jpeg_get_int_status(void __iomem *base)
return readl(base + EXYNOS4_INT_STATUS_REG);
}
-unsigned int exynos4_jpeg_get_fifo_status(void __iomem *base)
-{
- return readl(base + EXYNOS4_FIFO_STATUS_REG);
-}
-
void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value)
{
unsigned int reg;
@@ -300,22 +295,8 @@ void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size)
writel(size, base + EXYNOS4_BITSTREAM_SIZE_REG);
}
-void exynos4_jpeg_get_frame_size(void __iomem *base,
- unsigned int *width, unsigned int *height)
-{
- *width = (readl(base + EXYNOS4_DECODE_XY_SIZE_REG) &
- EXYNOS4_DECODED_SIZE_MASK);
- *height = (readl(base + EXYNOS4_DECODE_XY_SIZE_REG) >> 16) &
- EXYNOS4_DECODED_SIZE_MASK;
-}
-
unsigned int exynos4_jpeg_get_frame_fmt(void __iomem *base)
{
return readl(base + EXYNOS4_DECODE_IMG_FMT_REG) &
EXYNOS4_JPEG_DECODED_IMG_FMT_MASK;
}
-
-void exynos4_jpeg_set_timer_count(void __iomem *base, unsigned int size)
-{
- writel(size, base + EXYNOS4_INT_TIMER_COUNT_REG);
-}
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h
index 3e2887526960..b941cc89e4ba 100644
--- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h
+++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h
@@ -35,10 +35,6 @@ void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x);
void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt);
void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size);
unsigned int exynos4_jpeg_get_stream_size(void __iomem *base);
-void exynos4_jpeg_get_frame_size(void __iomem *base,
- unsigned int *width, unsigned int *height);
unsigned int exynos4_jpeg_get_frame_fmt(void __iomem *base);
-unsigned int exynos4_jpeg_get_fifo_status(void __iomem *base);
-void exynos4_jpeg_set_timer_count(void __iomem *base, unsigned int size);
#endif /* JPEG_HW_EXYNOS4_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
index 50451984d59f..2fe3c9228ac5 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
@@ -1721,7 +1721,7 @@ MODULE_DEVICE_TABLE(of, exynos_mfc_match);
static struct platform_driver s5p_mfc_driver = {
.probe = s5p_mfc_probe,
- .remove_new = s5p_mfc_remove,
+ .remove = s5p_mfc_remove,
.driver = {
.name = S5P_MFC_NAME,
.pm = &s5p_mfc_pm_ops,
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c
index 91e102d4ec4e..3efbc3367906 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c
@@ -1161,8 +1161,6 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
static const struct vb2_ops s5p_mfc_dec_qops = {
.queue_setup = s5p_mfc_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_init = s5p_mfc_buf_init,
.start_streaming = s5p_mfc_start_streaming,
.stop_streaming = s5p_mfc_stop_streaming,
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
index 81cbb36fb382..6c603dcd5664 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
@@ -2652,8 +2652,6 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
static const struct vb2_ops s5p_mfc_enc_qops = {
.queue_setup = s5p_mfc_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_init = s5p_mfc_buf_init,
.buf_prepare = s5p_mfc_buf_prepare,
.start_streaming = s5p_mfc_start_streaming,
diff --git a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c
index c7ee6e1a4451..73ad66ed20f2 100644
--- a/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c
+++ b/drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c
@@ -531,8 +531,6 @@ static const struct vb2_ops bdisp_qops = {
.queue_setup = bdisp_queue_setup,
.buf_prepare = bdisp_buf_prepare,
.buf_queue = bdisp_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = bdisp_stop_streaming,
.start_streaming = bdisp_start_streaming,
};
@@ -1411,7 +1409,7 @@ MODULE_DEVICE_TABLE(of, bdisp_match_types);
static struct platform_driver bdisp_driver = {
.probe = bdisp_probe,
- .remove_new = bdisp_remove,
+ .remove = bdisp_remove,
.driver = {
.name = BDISP_NAME,
.of_match_table = bdisp_match_types,
diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
index 67d3d6e50d2e..7b3a37957e3a 100644
--- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
+++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
@@ -1158,7 +1158,7 @@ static struct platform_driver c8sectpfe_driver = {
.of_match_table = c8sectpfe_match,
},
.probe = c8sectpfe_probe,
- .remove_new = c8sectpfe_remove,
+ .remove = c8sectpfe_remove,
};
module_platform_driver(c8sectpfe_driver);
diff --git a/drivers/media/platform/st/sti/delta/delta-v4l2.c b/drivers/media/platform/st/sti/delta/delta-v4l2.c
index da402d1e9171..196e6a40335d 100644
--- a/drivers/media/platform/st/sti/delta/delta-v4l2.c
+++ b/drivers/media/platform/st/sti/delta/delta-v4l2.c
@@ -1559,8 +1559,6 @@ static const struct vb2_ops delta_vb2_au_ops = {
.queue_setup = delta_vb2_au_queue_setup,
.buf_prepare = delta_vb2_au_prepare,
.buf_queue = delta_vb2_au_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = delta_vb2_au_start_streaming,
.stop_streaming = delta_vb2_au_stop_streaming,
};
@@ -1570,8 +1568,6 @@ static const struct vb2_ops delta_vb2_frame_ops = {
.buf_prepare = delta_vb2_frame_prepare,
.buf_finish = delta_vb2_frame_finish,
.buf_queue = delta_vb2_frame_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = delta_vb2_frame_stop_streaming,
};
@@ -1954,7 +1950,7 @@ MODULE_DEVICE_TABLE(of, delta_match_types);
static struct platform_driver delta_driver = {
.probe = delta_probe,
- .remove_new = delta_remove,
+ .remove = delta_remove,
.driver = {
.name = DELTA_NAME,
.of_match_table = delta_match_types,
diff --git a/drivers/media/platform/st/sti/hva/hva-v4l2.c b/drivers/media/platform/st/sti/hva/hva-v4l2.c
index 161a5c0fbc4e..5366c0f92549 100644
--- a/drivers/media/platform/st/sti/hva/hva-v4l2.c
+++ b/drivers/media/platform/st/sti/hva/hva-v4l2.c
@@ -1114,8 +1114,6 @@ static const struct vb2_ops hva_qops = {
.buf_queue = hva_buf_queue,
.start_streaming = hva_start_streaming,
.stop_streaming = hva_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/*
@@ -1456,7 +1454,7 @@ MODULE_DEVICE_TABLE(of, hva_match_types);
static struct platform_driver hva_driver = {
.probe = hva_probe,
- .remove_new = hva_remove,
+ .remove = hva_remove,
.driver = {
.name = HVA_NAME,
.of_match_table = hva_match_types,
diff --git a/drivers/media/platform/st/stm32/dma2d/dma2d.c b/drivers/media/platform/st/stm32/dma2d/dma2d.c
index 92f1edee58f8..b6c8400fb92d 100644
--- a/drivers/media/platform/st/stm32/dma2d/dma2d.c
+++ b/drivers/media/platform/st/stm32/dma2d/dma2d.c
@@ -186,8 +186,6 @@ static const struct vb2_ops dma2d_qops = {
.buf_queue = dma2d_buf_queue,
.start_streaming = dma2d_start_streaming,
.stop_streaming = dma2d_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -717,7 +715,7 @@ MODULE_DEVICE_TABLE(of, stm32_dma2d_match);
static struct platform_driver dma2d_pdrv = {
.probe = dma2d_probe,
- .remove_new = dma2d_remove,
+ .remove = dma2d_remove,
.driver = {
.name = DMA2D_NAME,
.of_match_table = stm32_dma2d_match,
diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c
index ff3331af9406..9b699ee2b1e0 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
@@ -898,8 +898,6 @@ static const struct vb2_ops dcmi_video_qops = {
.buf_queue = dcmi_buf_queue,
.start_streaming = dcmi_start_streaming,
.stop_streaming = dcmi_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int dcmi_g_fmt_vid_cap(struct file *file, void *priv,
@@ -2149,7 +2147,7 @@ static const struct dev_pm_ops dcmi_pm_ops = {
static struct platform_driver stm32_dcmi_driver = {
.probe = dcmi_probe,
- .remove_new = dcmi_remove,
+ .remove = dcmi_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(stm32_dcmi_of_match),
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
index 9f768f011fa2..7edd49bfe7e5 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
@@ -625,12 +625,6 @@ static const struct vb2_ops dcmipp_bytecap_qops = {
.buf_prepare = dcmipp_bytecap_buf_prepare,
.buf_queue = dcmipp_bytecap_buf_queue,
.queue_setup = dcmipp_bytecap_queue_setup,
- /*
- * Since q->lock is set we can use the standard
- * vb2_ops_wait_prepare/finish helper functions.
- */
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static void dcmipp_bytecap_release(struct video_device *vdev)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
index 7f771ea49b78..3806f7c6e2fe 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
@@ -583,7 +583,7 @@ static const struct dev_pm_ops dcmipp_pm_ops = {
static struct platform_driver dcmipp_pdrv = {
.probe = dcmipp_probe,
- .remove_new = dcmipp_remove,
+ .remove = dcmipp_remove,
.driver = {
.name = DCMIPP_PDEV_NAME,
.of_match_table = dcmipp_of_match,
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
index d07e980aba61..e53a07b770b7 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
@@ -340,7 +340,7 @@ static const struct dev_pm_ops sun4i_csi_pm_ops = {
static struct platform_driver sun4i_csi_driver = {
.probe = sun4i_csi_probe,
- .remove_new = sun4i_csi_remove,
+ .remove = sun4i_csi_remove,
.driver = {
.name = "sun4i-csi",
.of_match_table = sun4i_csi_of_match,
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
index d1371e130113..e911c7f7acc5 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
@@ -371,8 +371,6 @@ static const struct vb2_ops sun4i_csi_qops = {
.buf_queue = sun4i_csi_buffer_queue,
.start_streaming = sun4i_csi_start_streaming,
.stop_streaming = sun4i_csi_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static irqreturn_t sun4i_csi_irq(int irq, void *data)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
index c6ba385c0c86..af2a32c226a5 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
@@ -423,7 +423,7 @@ MODULE_DEVICE_TABLE(of, sun6i_csi_of_match);
static struct platform_driver sun6i_csi_platform_driver = {
.probe = sun6i_csi_probe,
- .remove_new = sun6i_csi_remove,
+ .remove = sun6i_csi_remove,
.driver = {
.name = SUN6I_CSI_NAME,
.of_match_table = sun6i_csi_of_match,
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index 14c0dc827c52..76356bc7f10e 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -657,8 +657,6 @@ static const struct vb2_ops sun6i_csi_capture_queue_ops = {
.buf_queue = sun6i_csi_capture_buffer_queue,
.start_streaming = sun6i_csi_capture_start_streaming,
.stop_streaming = sun6i_csi_capture_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* V4L2 Device */
diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
index f9d4dc45b490..b06cb73015cd 100644
--- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
@@ -757,7 +757,7 @@ MODULE_DEVICE_TABLE(of, sun6i_mipi_csi2_of_match);
static struct platform_driver sun6i_mipi_csi2_platform_driver = {
.probe = sun6i_mipi_csi2_probe,
- .remove_new = sun6i_mipi_csi2_remove,
+ .remove = sun6i_mipi_csi2_remove,
.driver = {
.name = SUN6I_MIPI_CSI2_NAME,
.of_match_table = sun6i_mipi_csi2_of_match,
diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
index 4a5698eb12b7..dbc51daa4fe3 100644
--- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
@@ -824,7 +824,7 @@ MODULE_DEVICE_TABLE(of, sun8i_a83t_mipi_csi2_of_match);
static struct platform_driver sun8i_a83t_mipi_csi2_platform_driver = {
.probe = sun8i_a83t_mipi_csi2_probe,
- .remove_new = sun8i_a83t_mipi_csi2_remove,
+ .remove = sun8i_a83t_mipi_csi2_remove,
.driver = {
.name = SUN8I_A83T_MIPI_CSI2_NAME,
.of_match_table = sun8i_a83t_mipi_csi2_of_match,
diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
index a1c35a2b68ed..3e7f2df70408 100644
--- a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
+++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
@@ -659,8 +659,6 @@ static const struct vb2_ops deinterlace_qops = {
.buf_queue = deinterlace_buf_queue,
.start_streaming = deinterlace_start_streaming,
.stop_streaming = deinterlace_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int deinterlace_queue_init(void *priv, struct vb2_queue *src_vq,
@@ -1001,7 +999,7 @@ static const struct dev_pm_ops deinterlace_pm_ops = {
static struct platform_driver deinterlace_driver = {
.probe = deinterlace_probe,
- .remove_new = deinterlace_remove,
+ .remove = deinterlace_remove,
.driver = {
.name = DEINTERLACE_NAME,
.of_match_table = deinterlace_dt_match,
diff --git a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
index a12323ca89fa..abd10b218aa1 100644
--- a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
+++ b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
@@ -522,8 +522,6 @@ static const struct vb2_ops rotate_qops = {
.buf_queue = rotate_buf_queue,
.start_streaming = rotate_start_streaming,
.stop_streaming = rotate_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int rotate_queue_init(void *priv, struct vb2_queue *src_vq,
@@ -905,7 +903,7 @@ static const struct dev_pm_ops rotate_pm_ops = {
static struct platform_driver rotate_driver = {
.probe = rotate_probe,
- .remove_new = rotate_remove,
+ .remove = rotate_remove,
.driver = {
.name = ROTATE_NAME,
.of_match_table = rotate_dt_match,
diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c
index 009ff68a2b43..44cdccb89377 100644
--- a/drivers/media/platform/ti/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c
@@ -2079,8 +2079,6 @@ static long vpfe_ioctl_default(struct file *file, void *priv,
}
static const struct vb2_ops vpfe_video_qops = {
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.queue_setup = vpfe_queue_setup,
.buf_prepare = vpfe_buffer_prepare,
.buf_queue = vpfe_buffer_queue,
@@ -2617,7 +2615,7 @@ MODULE_DEVICE_TABLE(of, vpfe_of_match);
static struct platform_driver vpfe_driver = {
.probe = vpfe_probe,
- .remove_new = vpfe_remove,
+ .remove = vpfe_remove,
.driver = {
.name = VPFE_MODULE_NAME,
.pm = &vpfe_pm_ops,
diff --git a/drivers/media/platform/ti/cal/cal-video.c b/drivers/media/platform/ti/cal/cal-video.c
index e1ba5dfc217e..e29743ae61e2 100644
--- a/drivers/media/platform/ti/cal/cal-video.c
+++ b/drivers/media/platform/ti/cal/cal-video.c
@@ -808,8 +808,6 @@ static const struct vb2_ops cal_video_qops = {
.buf_queue = cal_buffer_queue,
.start_streaming = cal_start_streaming,
.stop_streaming = cal_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* ------------------------------------------------------------------
diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c
index 5c2c04142aee..4bd2092e0255 100644
--- a/drivers/media/platform/ti/cal/cal.c
+++ b/drivers/media/platform/ti/cal/cal.c
@@ -1332,7 +1332,7 @@ static const struct dev_pm_ops cal_pm_ops = {
static struct platform_driver cal_pdrv = {
.probe = cal_probe,
- .remove_new = cal_remove,
+ .remove = cal_remove,
.driver = {
.name = CAL_MODULE_NAME,
.pm = &cal_pm_ops,
diff --git a/drivers/media/platform/ti/davinci/vpif.c b/drivers/media/platform/ti/davinci/vpif.c
index f4e1fa76bf37..a81719702a22 100644
--- a/drivers/media/platform/ti/davinci/vpif.c
+++ b/drivers/media/platform/ti/davinci/vpif.c
@@ -589,7 +589,7 @@ static struct platform_driver vpif_driver = {
.name = VPIF_DRIVER_NAME,
.pm = vpif_pm_ops,
},
- .remove_new = vpif_remove,
+ .remove = vpif_remove,
.probe = vpif_probe,
};
diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c
index 16326437767f..d053972888d1 100644
--- a/drivers/media/platform/ti/davinci/vpif_capture.c
+++ b/drivers/media/platform/ti/davinci/vpif_capture.c
@@ -310,8 +310,6 @@ static const struct vb2_ops video_qops = {
.start_streaming = vpif_start_streaming,
.stop_streaming = vpif_stop_streaming,
.buf_queue = vpif_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/**
@@ -1815,7 +1813,7 @@ static __refdata struct platform_driver vpif_driver = {
.pm = &vpif_pm_ops,
},
.probe = vpif_probe,
- .remove_new = vpif_remove,
+ .remove = vpif_remove,
};
module_platform_driver(vpif_driver);
diff --git a/drivers/media/platform/ti/davinci/vpif_display.c b/drivers/media/platform/ti/davinci/vpif_display.c
index 76d8fa8ad088..70c89549f4b6 100644
--- a/drivers/media/platform/ti/davinci/vpif_display.c
+++ b/drivers/media/platform/ti/davinci/vpif_display.c
@@ -293,8 +293,6 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
static const struct vb2_ops video_qops = {
.queue_setup = vpif_buffer_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_prepare = vpif_buffer_prepare,
.start_streaming = vpif_start_streaming,
.stop_streaming = vpif_stop_streaming,
@@ -1398,7 +1396,7 @@ static __refdata struct platform_driver vpif_driver = {
.pm = &vpif_pm_ops,
},
.probe = vpif_probe,
- .remove_new = vpif_remove,
+ .remove = vpif_remove,
};
module_platform_driver(vpif_driver);
diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
index 22442fce7607..6412a00be8ea 100644
--- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
+++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
@@ -878,8 +878,6 @@ static const struct vb2_ops csi_vb2_qops = {
.buf_queue = ti_csi2rx_buffer_queue,
.start_streaming = ti_csi2rx_start_streaming,
.stop_streaming = ti_csi2rx_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int ti_csi2rx_init_vb2q(struct ti_csi2rx_dev *csi)
@@ -1014,9 +1012,9 @@ static int ti_csi2rx_v4l2_init(struct ti_csi2rx_dev *csi)
pix_fmt->height = 480;
pix_fmt->field = V4L2_FIELD_NONE;
pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
- pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601,
- pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE,
- pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB,
+ pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
+ pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+ pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
ti_csi2rx_fill_fmt(fmt, &csi->v_fmt);
@@ -1163,7 +1161,7 @@ MODULE_DEVICE_TABLE(of, ti_csi2rx_of_match);
static struct platform_driver ti_csi2rx_pdrv = {
.probe = ti_csi2rx_probe,
- .remove_new = ti_csi2rx_remove,
+ .remove = ti_csi2rx_remove,
.driver = {
.name = TI_CSI2RX_MODULE_NAME,
.of_match_table = ti_csi2rx_of_match,
diff --git a/drivers/media/platform/ti/omap/omap_vout.c b/drivers/media/platform/ti/omap/omap_vout.c
index 1c56b6a87ced..a87d5030ac35 100644
--- a/drivers/media/platform/ti/omap/omap_vout.c
+++ b/drivers/media/platform/ti/omap/omap_vout.c
@@ -1300,8 +1300,6 @@ static const struct vb2_ops omap_vout_vb2_ops = {
.buf_prepare = omap_vout_vb2_prepare,
.start_streaming = omap_vout_vb2_start_streaming,
.stop_streaming = omap_vout_vb2_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* Init functions used during driver initialization */
@@ -1721,7 +1719,7 @@ static struct platform_driver omap_vout_driver = {
.driver = {
.name = VOUT_NAME,
},
- .remove_new = omap_vout_remove,
+ .remove = omap_vout_remove,
};
static int __init omap_vout_init(void)
diff --git a/drivers/media/platform/ti/omap/omap_voutdef.h b/drivers/media/platform/ti/omap/omap_voutdef.h
index b586193341d2..159e5e670d91 100644
--- a/drivers/media/platform/ti/omap/omap_voutdef.h
+++ b/drivers/media/platform/ti/omap/omap_voutdef.h
@@ -48,7 +48,7 @@
#define VRFB_TX_TIMEOUT 1000
#define VRFB_NUM_BUFS 4
-/* Max buffer size tobe allocated during init */
+/* Max buffer size to be allocated during init */
#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4)
enum dma_channel_state {
diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c
index 91101ba88ef0..405ca215179d 100644
--- a/drivers/media/platform/ti/omap3isp/isp.c
+++ b/drivers/media/platform/ti/omap3isp/isp.c
@@ -2472,7 +2472,7 @@ MODULE_DEVICE_TABLE(of, omap3isp_of_table);
static struct platform_driver omap3isp_driver = {
.probe = isp_probe,
- .remove_new = isp_remove,
+ .remove = isp_remove,
.id_table = omap3isp_id_table,
.driver = {
.name = "omap3isp",
diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.c b/drivers/media/platform/ti/omap3isp/ispvideo.c
index daca689dc082..5c9aa80023fd 100644
--- a/drivers/media/platform/ti/omap3isp/ispvideo.c
+++ b/drivers/media/platform/ti/omap3isp/ispvideo.c
@@ -480,11 +480,29 @@ static int isp_video_start_streaming(struct vb2_queue *queue,
return 0;
}
+static void omap3isp_wait_prepare(struct vb2_queue *vq)
+{
+ struct isp_video_fh *vfh = vb2_get_drv_priv(vq);
+ struct isp_video *video = vfh->video;
+
+ mutex_unlock(&video->queue_lock);
+}
+
+static void omap3isp_wait_finish(struct vb2_queue *vq)
+{
+ struct isp_video_fh *vfh = vb2_get_drv_priv(vq);
+ struct isp_video *video = vfh->video;
+
+ mutex_lock(&video->queue_lock);
+}
+
static const struct vb2_ops isp_video_queue_ops = {
.queue_setup = isp_video_queue_setup,
.buf_prepare = isp_video_buffer_prepare,
.buf_queue = isp_video_buffer_queue,
.start_streaming = isp_video_start_streaming,
+ .wait_prepare = omap3isp_wait_prepare,
+ .wait_finish = omap3isp_wait_finish,
};
/*
diff --git a/drivers/media/platform/ti/vpe/vpe.c b/drivers/media/platform/ti/vpe/vpe.c
index 6848cbc82f52..636d76ecebcd 100644
--- a/drivers/media/platform/ti/vpe/vpe.c
+++ b/drivers/media/platform/ti/vpe/vpe.c
@@ -2210,8 +2210,6 @@ static const struct vb2_ops vpe_qops = {
.queue_setup = vpe_queue_setup,
.buf_prepare = vpe_buf_prepare,
.buf_queue = vpe_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = vpe_start_streaming,
.stop_streaming = vpe_stop_streaming,
};
@@ -2649,7 +2647,7 @@ MODULE_DEVICE_TABLE(of, vpe_of_match);
static struct platform_driver vpe_pdrv = {
.probe = vpe_probe,
- .remove_new = vpe_remove,
+ .remove = vpe_remove,
.driver = {
.name = VPE_MODULE_NAME,
.of_match_table = of_match_ptr(vpe_of_match),
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 05bbac853c4f..8542238e0fb1 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -1277,7 +1277,7 @@ static const struct dev_pm_ops hantro_pm_ops = {
static struct platform_driver hantro_driver = {
.probe = hantro_probe,
- .remove_new = hantro_remove,
+ .remove = hantro_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_hantro_match,
diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c
index 62d3962c18d9..2513adfbd825 100644
--- a/drivers/media/platform/verisilicon/hantro_v4l2.c
+++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
@@ -201,7 +201,15 @@ static int vidioc_enum_fmt(struct file *file, void *priv,
struct hantro_ctx *ctx = fh_to_ctx(priv);
const struct hantro_fmt *fmt, *formats;
unsigned int num_fmts, i, j = 0;
- bool skip_mode_none;
+ bool skip_mode_none, enum_all_formats;
+ u32 index = f->index & ~V4L2_FMTDESC_FLAG_ENUM_ALL;
+
+ /*
+ * If the V4L2_FMTDESC_FLAG_ENUM_ALL flag is set, we want to enumerate all
+ * hardware supported pixel formats
+ */
+ enum_all_formats = !!(f->index & V4L2_FMTDESC_FLAG_ENUM_ALL);
+ f->index = index;
/*
* When dealing with an encoder:
@@ -222,9 +230,9 @@ static int vidioc_enum_fmt(struct file *file, void *priv,
if (skip_mode_none == mode_none)
continue;
- if (!hantro_check_depth_match(fmt, ctx->bit_depth))
+ if (!hantro_check_depth_match(fmt, ctx->bit_depth) && !enum_all_formats)
continue;
- if (j == f->index) {
+ if (j == index) {
f->pixelformat = fmt->fourcc;
return 0;
}
@@ -242,9 +250,9 @@ static int vidioc_enum_fmt(struct file *file, void *priv,
for (i = 0; i < num_fmts; i++) {
fmt = &formats[i];
- if (!hantro_check_depth_match(fmt, ctx->bit_depth))
+ if (!hantro_check_depth_match(fmt, ctx->bit_depth) && !enum_all_formats)
continue;
- if (j == f->index) {
+ if (j == index) {
f->pixelformat = fmt->fourcc;
return 0;
}
@@ -996,6 +1004,4 @@ const struct vb2_ops hantro_queue_ops = {
.buf_request_complete = hantro_buf_request_complete,
.start_streaming = hantro_start_streaming,
.stop_streaming = hantro_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
index 65e8f2d07400..e54f5fac325b 100644
--- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
+++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
@@ -161,8 +161,7 @@ static int rockchip_vpu981_av1_dec_frame_ref(struct hantro_ctx *ctx,
av1_dec->frame_refs[i].timestamp = timestamp;
av1_dec->frame_refs[i].frame_type = frame->frame_type;
av1_dec->frame_refs[i].order_hint = frame->order_hint;
- if (!av1_dec->frame_refs[i].vb2_ref)
- av1_dec->frame_refs[i].vb2_ref = hantro_get_dst_buf(ctx);
+ av1_dec->frame_refs[i].vb2_ref = hantro_get_dst_buf(ctx);
for (j = 0; j < V4L2_AV1_TOTAL_REFS_PER_FRAME; j++)
av1_dec->frame_refs[i].order_hints[j] = frame->order_hints[j];
diff --git a/drivers/media/platform/via/via-camera.c b/drivers/media/platform/via/via-camera.c
index 4cb8f29e2f14..5702eff664d4 100644
--- a/drivers/media/platform/via/via-camera.c
+++ b/drivers/media/platform/via/via-camera.c
@@ -666,8 +666,6 @@ static const struct vb2_ops viacam_vb2_ops = {
.buf_prepare = viacam_vb2_prepare,
.start_streaming = viacam_vb2_start_streaming,
.stop_streaming = viacam_vb2_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* --------------------------------------------------------------------------*/
@@ -1307,7 +1305,7 @@ static struct platform_driver viacam_driver = {
.name = "viafb-camera",
},
.probe = viacam_probe,
- .remove_new = viacam_remove,
+ .remove = viacam_remove,
};
module_platform_driver(viacam_driver);
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index 31e9e92e723e..cba34893258a 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -52,6 +52,7 @@ static int video_mux_link_setup(struct media_entity *entity,
const struct media_pad *remote, u32 flags)
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+ struct v4l2_subdev_state *sd_state;
struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
u16 source_pad = entity->num_pads - 1;
int ret = 0;
@@ -67,10 +68,10 @@ static int video_mux_link_setup(struct media_entity *entity,
remote->entity->name, remote->index, local->entity->name,
local->index, flags & MEDIA_LNK_FL_ENABLED);
+ sd_state = v4l2_subdev_lock_and_get_active_state(sd);
mutex_lock(&vmux->lock);
if (flags & MEDIA_LNK_FL_ENABLED) {
- struct v4l2_subdev_state *sd_state;
struct v4l2_mbus_framefmt *source_mbusformat;
if (vmux->active == local->index)
@@ -88,12 +89,10 @@ static int video_mux_link_setup(struct media_entity *entity,
vmux->active = local->index;
/* Propagate the active format to the source */
- sd_state = v4l2_subdev_lock_and_get_active_state(sd);
source_mbusformat = v4l2_subdev_state_get_format(sd_state,
source_pad);
*source_mbusformat = *v4l2_subdev_state_get_format(sd_state,
vmux->active);
- v4l2_subdev_unlock_state(sd_state);
} else {
if (vmux->active != local->index)
goto out;
@@ -105,6 +104,7 @@ static int video_mux_link_setup(struct media_entity *entity,
out:
mutex_unlock(&vmux->lock);
+ v4l2_subdev_unlock_state(sd_state);
return ret;
}
@@ -486,7 +486,7 @@ MODULE_DEVICE_TABLE(of, video_mux_dt_ids);
static struct platform_driver video_mux_driver = {
.probe = video_mux_probe,
- .remove_new = video_mux_remove,
+ .remove = video_mux_remove,
.driver = {
.of_match_table = video_mux_dt_ids,
.name = "video-mux",
diff --git a/drivers/media/platform/xilinx/xilinx-csi2rxss.c b/drivers/media/platform/xilinx/xilinx-csi2rxss.c
index f953d5474ae0..146131b8f37e 100644
--- a/drivers/media/platform/xilinx/xilinx-csi2rxss.c
+++ b/drivers/media/platform/xilinx/xilinx-csi2rxss.c
@@ -1028,7 +1028,7 @@ static struct platform_driver xcsi2rxss_driver = {
.of_match_table = xcsi2rxss_of_id_table,
},
.probe = xcsi2rxss_probe,
- .remove_new = xcsi2rxss_remove,
+ .remove = xcsi2rxss_remove,
};
module_platform_driver(xcsi2rxss_driver);
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index a1687b868a44..18bfa6001909 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -458,8 +458,6 @@ static const struct vb2_ops xvip_dma_queue_qops = {
.queue_setup = xvip_dma_queue_setup,
.buf_prepare = xvip_dma_buffer_prepare,
.buf_queue = xvip_dma_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = xvip_dma_start_streaming,
.stop_streaming = xvip_dma_stop_streaming,
};
diff --git a/drivers/media/platform/xilinx/xilinx-tpg.c b/drivers/media/platform/xilinx/xilinx-tpg.c
index e05e528ffc6f..cb93711ea3e3 100644
--- a/drivers/media/platform/xilinx/xilinx-tpg.c
+++ b/drivers/media/platform/xilinx/xilinx-tpg.c
@@ -13,6 +13,7 @@
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/xilinx-v4l2-controls.h>
@@ -711,22 +712,13 @@ static int xtpg_parse_of(struct xtpg_device *xtpg)
{
struct device *dev = xtpg->xvip.dev;
struct device_node *node = xtpg->xvip.dev->of_node;
- struct device_node *ports;
- struct device_node *port;
unsigned int nports = 0;
bool has_endpoint = false;
- ports = of_get_child_by_name(node, "ports");
- if (ports == NULL)
- ports = node;
-
- for_each_child_of_node(ports, port) {
+ for_each_of_graph_port(node, port) {
const struct xvip_video_format *format;
struct device_node *endpoint;
- if (!of_node_name_eq(port, "port"))
- continue;
-
format = xvip_of_get_format(port);
if (IS_ERR(format)) {
dev_err(dev, "invalid format in DT");
@@ -744,7 +736,7 @@ static int xtpg_parse_of(struct xtpg_device *xtpg)
}
if (nports == 0) {
- endpoint = of_get_next_child(port, NULL);
+ endpoint = of_graph_get_next_port_endpoint(port, NULL);
if (endpoint)
has_endpoint = true;
of_node_put(endpoint);
@@ -920,7 +912,7 @@ static struct platform_driver xtpg_driver = {
.of_match_table = xtpg_of_id_table,
},
.probe = xtpg_probe,
- .remove_new = xtpg_remove,
+ .remove = xtpg_remove,
};
module_platform_driver(xtpg_driver);
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index bfe48cc0ab52..024b439feec9 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -618,7 +618,7 @@ static struct platform_driver xvip_composite_driver = {
.of_match_table = xvip_composite_of_id_table,
},
.probe = xvip_composite_probe,
- .remove_new = xvip_composite_remove,
+ .remove = xvip_composite_remove,
};
module_platform_driver(xvip_composite_driver);
diff --git a/drivers/media/platform/xilinx/xilinx-vtc.c b/drivers/media/platform/xilinx/xilinx-vtc.c
index dda70719f004..92fec7bb47da 100644
--- a/drivers/media/platform/xilinx/xilinx-vtc.c
+++ b/drivers/media/platform/xilinx/xilinx-vtc.c
@@ -365,7 +365,7 @@ static struct platform_driver xvtc_driver = {
.of_match_table = xvtc_of_id_table,
},
.probe = xvtc_probe,
- .remove_new = xvtc_remove,
+ .remove = xvtc_remove,
};
module_platform_driver(xvtc_driver);
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 0e9a3787724c..3c8c17d64821 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -4,7 +4,7 @@
*
* Copyright 1997 M. Kirkwood
*
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
+ * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com>
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org>
* Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
* Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index a532f63aa9d9..5ca6274c45bd 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -15,7 +15,7 @@
* Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
* Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
*
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
+ * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com>
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org>
*
* Note: this card seems to swap the left and right audio channels!
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index ad49151f5ff0..4f87c76a2a96 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -4,7 +4,7 @@
* This takes care of all the V4L2 scaffolding, allowing the ISA drivers
* to concentrate on the actual hardware operation.
*
- * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com>
+ * Copyright (C) 2012 Hans Verkuil <hansverk@cisco.com>
*/
#include <linux/module.h>
diff --git a/drivers/media/radio/radio-isa.h b/drivers/media/radio/radio-isa.h
index c9159958203e..0f3db473da5e 100644
--- a/drivers/media/radio/radio-isa.h
+++ b/drivers/media/radio/radio-isa.h
@@ -4,7 +4,7 @@
* This takes care of all the V4L2 scaffolding, allowing the ISA drivers
* to concentrate on the actual hardware operation.
*
- * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com>
+ * Copyright (C) 2012 Hans Verkuil <hansverk@cisco.com>
*/
#ifndef _RADIO_ISA_H_
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
index 08be77b8f3b7..27f058c5e677 100644
--- a/drivers/media/radio/radio-miropcm20.c
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -23,7 +23,7 @@
* This code has been reintroduced and converted to use
* the new V4L2 RDS API by:
*
- * Hans Verkuil <hans.verkuil@cisco.com>
+ * Hans Verkuil <hansverk@cisco.com>
*/
#include <linux/module.h>
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 73d2c187f122..16b13a63bfed 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -7,7 +7,7 @@
* Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
* Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
*
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
+ * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com>
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org>
*
* Fully tested with actual hardware and the v4l2-compliance tool.
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
index b2c5809a8bc7..9980346cb5ea 100644
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -1513,7 +1513,7 @@ static struct platform_driver si476x_radio_driver = {
.name = DRIVER_NAME,
},
.probe = si476x_radio_probe,
- .remove_new = si476x_radio_remove,
+ .remove = si476x_radio_remove,
};
module_platform_driver(si476x_radio_driver);
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 621bb8523271..720080634454 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -17,7 +17,7 @@
* Frequency control is done digitally -- ie out(port,encodefreq(95.8));
* Volume Control is done digitally
*
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
+ * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com>
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@kernel.org>
*/
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index 04daa9c358c2..a6069b106fd3 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -164,7 +164,7 @@ static struct platform_driver timbradio_platform_driver = {
.name = DRIVER_NAME,
},
.probe = timbradio_probe,
- .remove_new = timbradio_remove,
+ .remove = timbradio_remove,
};
module_platform_driver(timbradio_platform_driver);
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index f6b98c304b72..511a8ede05ec 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -2145,7 +2145,7 @@ pdata_err:
static struct platform_driver wl1273_fm_radio_driver = {
.probe = wl1273_fm_radio_probe,
- .remove_new = wl1273_fm_radio_remove,
+ .remove = wl1273_fm_radio_remove,
.driver = {
.name = "wl1273_fm_radio",
},
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index f3dc57c75131..099b7af6a410 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -30,7 +30,7 @@
* 2006-07-24 - Converted to V4L2 API
* by Mauro Carvalho Chehab <mchehab@kernel.org>
*
- * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
+ * Converted to the radio-isa framework by Hans Verkuil <hansverk@cisco.com>
*
* Note that this is the driver for the Zoltrix Radio Plus.
* This driver does not work for the Zoltrix Radio Plus 108 or the
diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c
index 9fdaed68a962..67b4afadc95a 100644
--- a/drivers/media/radio/si4713/radio-platform-si4713.c
+++ b/drivers/media/radio/si4713/radio-platform-si4713.c
@@ -205,7 +205,7 @@ static struct platform_driver radio_si4713_pdriver = {
.name = "radio-si4713",
},
.probe = radio_si4713_pdriver_probe,
- .remove_new = radio_si4713_pdriver_remove,
+ .remove = radio_si4713_pdriver_remove,
};
module_platform_driver(radio_si4713_pdriver);
diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
index 3d36f323a8f8..4d032436691c 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -466,11 +466,12 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
return -ETIMEDOUT;
}
+ spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
if (!fmdev->resp_skb) {
+ spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
fmerr("Response SKB is missing\n");
return -EFAULT;
}
- spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
skb = fmdev->resp_skb;
fmdev->resp_skb = NULL;
spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 74d69ce22a33..0a8aeafdb7e0 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -184,6 +184,7 @@ config IR_GPIO_TX
tristate "GPIO IR Bit Banging Transmitter"
depends on LIRC
depends on (OF && GPIOLIB) || COMPILE_TEST
+ depends on !PREEMPT_RT
help
Say Y if you want to a GPIO based IR transmitter. This is a
bit banging driver.
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index d7721e60776e..a733914a2574 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -311,9 +311,9 @@ static void ati_remote_dump(struct device *dev, unsigned char *data,
if (data[0] != (unsigned char)0xff && data[0] != 0x00)
dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
} else if (len == 4)
- dev_warn(dev, "Weird key %*ph\n", 4, data);
+ dev_warn(dev, "Weird key %4ph\n", data);
else
- dev_warn(dev, "Weird data, len=%d %*ph ...\n", len, 6, data);
+ dev_warn(dev, "Weird data, len=%d %6ph ...\n", len, data);
}
/*
@@ -502,7 +502,7 @@ static void ati_remote_input_report(struct urb *urb)
if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) {
dbginfo(&ati_remote->interface->dev,
- "wrong checksum in input: %*ph\n", 4, data);
+ "wrong checksum in input: %4ph\n", data);
return;
}
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index b29a1a9f381d..bf6d8fa983bf 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -201,7 +201,7 @@ MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match);
static struct platform_driver gpio_ir_recv_driver = {
.probe = gpio_ir_recv_probe,
- .remove_new = gpio_ir_recv_remove,
+ .remove = gpio_ir_recv_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = gpio_ir_recv_of_match,
diff --git a/drivers/media/rc/gpio-ir-tx.c b/drivers/media/rc/gpio-ir-tx.c
index 1a8fea357f14..e185ead40464 100644
--- a/drivers/media/rc/gpio-ir-tx.c
+++ b/drivers/media/rc/gpio-ir-tx.c
@@ -78,8 +78,6 @@ static void gpio_ir_tx_unmodulated(struct gpio_ir *gpio_ir, uint *txbuf,
ktime_t edge;
int i;
- local_irq_disable();
-
edge = ktime_get();
for (i = 0; i < count; i++) {
@@ -110,8 +108,6 @@ static void gpio_ir_tx_modulated(struct gpio_ir *gpio_ir, uint *txbuf,
space = DIV_ROUND_CLOSEST((100 - gpio_ir->duty_cycle) *
(NSEC_PER_SEC / 100), gpio_ir->carrier);
- local_irq_disable();
-
edge = ktime_get();
for (i = 0; i < count; i++) {
diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c
index d87d8e14c556..067f4bc7fcc3 100644
--- a/drivers/media/rc/img-ir/img-ir-core.c
+++ b/drivers/media/rc/img-ir/img-ir-core.c
@@ -181,7 +181,7 @@ static struct platform_driver img_ir_driver = {
.pm = &img_ir_pmops,
},
.probe = img_ir_probe,
- .remove_new = img_ir_remove,
+ .remove = img_ir_remove,
};
module_platform_driver(img_ir_driver);
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index de5bb9a08ea4..afd80d2350c6 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -394,7 +394,7 @@ static struct platform_driver hix5hd2_ir_driver = {
.pm = &hix5hd2_ir_pm_ops,
},
.probe = hix5hd2_ir_probe,
- .remove_new = hix5hd2_ir_remove,
+ .remove = hix5hd2_ir_remove,
};
module_platform_driver(hix5hd2_ir_driver);
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index f042f3f14afa..a2257dc2f25d 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -815,28 +815,23 @@ void __exit lirc_dev_exit(void)
struct rc_dev *rc_dev_get_from_fd(int fd, bool write)
{
- struct fd f = fdget(fd);
+ CLASS(fd, f)(fd);
struct lirc_fh *fh;
struct rc_dev *dev;
- if (!fd_file(f))
+ if (fd_empty(f))
return ERR_PTR(-EBADF);
- if (fd_file(f)->f_op != &lirc_fops) {
- fdput(f);
+ if (fd_file(f)->f_op != &lirc_fops)
return ERR_PTR(-EINVAL);
- }
- if (write && !(fd_file(f)->f_mode & FMODE_WRITE)) {
- fdput(f);
+ if (write && !(fd_file(f)->f_mode & FMODE_WRITE))
return ERR_PTR(-EPERM);
- }
fh = fd_file(f)->private_data;
dev = fh->rc;
get_device(&dev->dev);
- fdput(f);
return dev;
}
diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index 9cdb45821ecc..272ebb0d97c8 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -628,7 +628,7 @@ MODULE_DEVICE_TABLE(of, meson_ir_match);
static struct platform_driver meson_ir_driver = {
.probe = meson_ir_probe,
- .remove_new = meson_ir_remove,
+ .remove = meson_ir_remove,
.shutdown = meson_ir_shutdown,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c
index b2f82b2d1c8d..85c9436b0a20 100644
--- a/drivers/media/rc/mtk-cir.c
+++ b/drivers/media/rc/mtk-cir.c
@@ -440,7 +440,7 @@ static void mtk_ir_remove(struct platform_device *pdev)
static struct platform_driver mtk_ir_driver = {
.probe = mtk_ir_probe,
- .remove_new = mtk_ir_remove,
+ .remove = mtk_ir_remove,
.driver = {
.name = MTK_IR_DEV,
.of_match_table = mtk_ir_match,
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
index 988b09191c4c..6539fa0a6e79 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -408,7 +408,7 @@ static struct platform_driver st_rc_driver = {
.pm = &st_rc_pm_ops,
},
.probe = st_rc_probe,
- .remove_new = st_rc_remove,
+ .remove = st_rc_remove,
};
module_platform_driver(st_rc_driver);
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
index b49df8355e6b..92ef4e7c6f69 100644
--- a/drivers/media/rc/sunxi-cir.c
+++ b/drivers/media/rc/sunxi-cir.c
@@ -413,7 +413,7 @@ MODULE_DEVICE_TABLE(of, sunxi_ir_match);
static struct platform_driver sunxi_ir_driver = {
.probe = sunxi_ir_probe,
- .remove_new = sunxi_ir_remove,
+ .remove = sunxi_ir_remove,
.shutdown = sunxi_ir_shutdown,
.driver = {
.name = SUNXI_IR_DEV,
diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c
index 846e90c06291..c45f5cf12ded 100644
--- a/drivers/media/test-drivers/vicodec/vicodec-core.c
+++ b/drivers/media/test-drivers/vicodec/vicodec-core.c
@@ -26,7 +26,7 @@
#include "codec-v4l2-fwht.h"
MODULE_DESCRIPTION("Virtual codec device");
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Hans Verkuil <hansverk@cisco.com>");
MODULE_LICENSE("GPL v2");
static bool multiplanar;
@@ -43,6 +43,8 @@ MODULE_PARM_DESC(debug, " activates debug info");
#define MIN_WIDTH 640U
#define MAX_HEIGHT 2160U
#define MIN_HEIGHT 360U
+/* Recommended number of buffers for the stateful codecs */
+#define VICODEC_REC_BUFS 2
#define dprintk(dev, fmt, arg...) \
v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
@@ -1688,8 +1690,6 @@ static const struct vb2_ops vicodec_qops = {
.buf_request_complete = vicodec_buf_request_complete,
.start_streaming = vicodec_start_streaming,
.stop_streaming = vicodec_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -1707,12 +1707,14 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->ops = &vicodec_qops;
src_vq->mem_ops = &vb2_vmalloc_memops;
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- if (ctx->is_enc)
+ if (ctx->is_enc) {
src_vq->lock = &ctx->dev->stateful_enc.mutex;
- else if (ctx->is_stateless)
+ src_vq->min_reqbufs_allocation = VICODEC_REC_BUFS;
+ } else if (ctx->is_stateless) {
src_vq->lock = &ctx->dev->stateless_dec.mutex;
- else
+ } else {
src_vq->lock = &ctx->dev->stateful_dec.mutex;
+ }
src_vq->supports_requests = ctx->is_stateless;
src_vq->requires_requests = ctx->is_stateless;
ret = vb2_queue_init(src_vq);
@@ -1730,6 +1732,8 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->mem_ops = &vb2_vmalloc_memops;
dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
dst_vq->lock = src_vq->lock;
+ if (!ctx->is_stateless && !ctx->is_enc)
+ dst_vq->min_reqbufs_allocation = VICODEC_REC_BUFS;
return vb2_queue_init(dst_vq);
}
@@ -1854,11 +1858,16 @@ static int vicodec_open(struct file *file)
1, 31, 1, 20);
v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP,
1, 31, 1, 20);
- if (ctx->is_enc)
- v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops,
- V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 1, 1, 1);
+
if (ctx->is_stateless)
v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_stateless_state, NULL);
+ else
+ v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, ctx->is_enc ?
+ V4L2_CID_MIN_BUFFERS_FOR_OUTPUT :
+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+ VICODEC_REC_BUFS, VICODEC_REC_BUFS, 1,
+ VICODEC_REC_BUFS);
+
if (hdl->error) {
rc = hdl->error;
v4l2_ctrl_handler_free(hdl);
@@ -2207,7 +2216,7 @@ static void vicodec_remove(struct platform_device *pdev)
static struct platform_driver vicodec_pdrv = {
.probe = vicodec_probe,
- .remove_new = vicodec_remove,
+ .remove = vicodec_remove,
.driver = {
.name = VICODEC_NAME,
},
diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c b/drivers/media/test-drivers/vidtv/vidtv_bridge.c
index 613949df897d..e1dd8adeba46 100644
--- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c
@@ -572,7 +572,7 @@ static struct platform_driver vidtv_bridge_driver = {
.name = VIDTV_PDEV_NAME,
},
.probe = vidtv_bridge_probe,
- .remove_new = vidtv_bridge_remove,
+ .remove = vidtv_bridge_remove,
};
static void __exit vidtv_bridge_exit(void)
diff --git a/drivers/media/test-drivers/vim2m.c b/drivers/media/test-drivers/vim2m.c
index 3e3b424b4860..6c24dcf27eb0 100644
--- a/drivers/media/test-drivers/vim2m.c
+++ b/drivers/media/test-drivers/vim2m.c
@@ -1100,8 +1100,6 @@ static const struct vb2_ops vim2m_qops = {
.buf_queue = vim2m_buf_queue,
.start_streaming = vim2m_start_streaming,
.stop_streaming = vim2m_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_request_complete = vim2m_buf_request_complete,
};
@@ -1394,7 +1392,7 @@ static void vim2m_remove(struct platform_device *pdev)
static struct platform_driver vim2m_pdrv = {
.probe = vim2m_probe,
- .remove_new = vim2m_remove,
+ .remove = vim2m_remove,
.driver = {
.name = MEM2MEM_NAME,
},
diff --git a/drivers/media/test-drivers/vimc/vimc-capture.c b/drivers/media/test-drivers/vimc/vimc-capture.c
index 89506ae00901..10df039278e7 100644
--- a/drivers/media/test-drivers/vimc/vimc-capture.c
+++ b/drivers/media/test-drivers/vimc/vimc-capture.c
@@ -326,12 +326,6 @@ static const struct vb2_ops vimc_capture_qops = {
.buf_queue = vimc_capture_buf_queue,
.queue_setup = vimc_capture_queue_setup,
.buf_prepare = vimc_capture_buffer_prepare,
- /*
- * Since q->lock is set we can use the standard
- * vb2_ops_wait_prepare/finish helper functions.
- */
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static const struct media_entity_operations vimc_capture_mops = {
diff --git a/drivers/media/test-drivers/vimc/vimc-core.c b/drivers/media/test-drivers/vimc/vimc-core.c
index 2083c60e34d6..c812fa9f0650 100644
--- a/drivers/media/test-drivers/vimc/vimc-core.c
+++ b/drivers/media/test-drivers/vimc/vimc-core.c
@@ -410,7 +410,7 @@ static struct platform_device vimc_pdev = {
static struct platform_driver vimc_pdrv = {
.probe = vimc_probe,
- .remove_new = vimc_remove,
+ .remove = vimc_remove,
.driver = {
.name = VIMC_PDEV_NAME,
},
diff --git a/drivers/media/test-drivers/visl/visl-core.c b/drivers/media/test-drivers/visl/visl-core.c
index c46464bcaf2e..01c964ea6f76 100644
--- a/drivers/media/test-drivers/visl/visl-core.c
+++ b/drivers/media/test-drivers/visl/visl-core.c
@@ -523,7 +523,7 @@ static void visl_remove(struct platform_device *pdev)
static struct platform_driver visl_pdrv = {
.probe = visl_probe,
- .remove_new = visl_remove,
+ .remove = visl_remove,
.driver = {
.name = VISL_NAME,
},
diff --git a/drivers/media/test-drivers/visl/visl-video.c b/drivers/media/test-drivers/visl/visl-video.c
index f8d970319764..8be505d8908c 100644
--- a/drivers/media/test-drivers/visl/visl-video.c
+++ b/drivers/media/test-drivers/visl/visl-video.c
@@ -136,6 +136,12 @@ static const u32 visl_decoded_fmts[] = {
V4L2_PIX_FMT_YUV420,
};
+static const u32 visl_extended_decoded_fmts[] = {
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_YUV420,
+ V4L2_PIX_FMT_P010,
+};
+
const struct visl_coded_format_desc visl_coded_fmts[] = {
{
.pixelformat = V4L2_PIX_FMT_FWHT_STATELESS,
@@ -341,11 +347,21 @@ static int visl_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct visl_ctx *ctx = visl_file_to_ctx(file);
+ u32 index = f->index & ~V4L2_FMTDESC_FLAG_ENUM_ALL;
+ int max_fmts = ctx->coded_format_desc->num_decoded_fmts;
+ const u32 *decoded_fmts = ctx->coded_format_desc->decoded_fmts;
+
+ if (f->index & V4L2_FMTDESC_FLAG_ENUM_ALL) {
+ max_fmts = ARRAY_SIZE(visl_extended_decoded_fmts);
+ decoded_fmts = visl_extended_decoded_fmts;
+ }
+
+ f->index = index;
- if (f->index >= ctx->coded_format_desc->num_decoded_fmts)
+ if (index >= max_fmts)
return -EINVAL;
- f->pixelformat = ctx->coded_format_desc->decoded_fmts[f->index];
+ f->pixelformat = decoded_fmts[index];
return 0;
}
@@ -716,8 +732,6 @@ static const struct vb2_ops visl_qops = {
.buf_queue = visl_buf_queue,
.start_streaming = visl_start_streaming,
.stop_streaming = visl_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.buf_request_complete = visl_buf_request_complete,
};
diff --git a/drivers/media/test-drivers/vivid/vivid-core.c b/drivers/media/test-drivers/vivid/vivid-core.c
index 00e0d08af357..7477ac8cb955 100644
--- a/drivers/media/test-drivers/vivid/vivid-core.c
+++ b/drivers/media/test-drivers/vivid/vivid-core.c
@@ -910,7 +910,7 @@ static int vivid_create_queue(struct vivid_dev *dev,
* videobuf2-core.c to MAX_BUFFER_INDEX.
*/
if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- q->max_num_buffers = 64;
+ q->max_num_buffers = MAX_VID_CAP_BUFFERS;
if (buf_type == V4L2_BUF_TYPE_SDR_CAPTURE)
q->max_num_buffers = 1024;
if (buf_type == V4L2_BUF_TYPE_VBI_CAPTURE)
@@ -2239,7 +2239,7 @@ static struct platform_device vivid_pdev = {
static struct platform_driver vivid_pdrv = {
.probe = vivid_probe,
- .remove_new = vivid_remove,
+ .remove = vivid_remove,
.driver = {
.name = "vivid",
},
diff --git a/drivers/media/test-drivers/vivid/vivid-core.h b/drivers/media/test-drivers/vivid/vivid-core.h
index cc18a3bc6dc0..d2d52763b119 100644
--- a/drivers/media/test-drivers/vivid/vivid-core.h
+++ b/drivers/media/test-drivers/vivid/vivid-core.h
@@ -26,6 +26,8 @@
#define MAX_INPUTS 16
/* The maximum number of outputs */
#define MAX_OUTPUTS 16
+/* The maximum number of video capture buffers */
+#define MAX_VID_CAP_BUFFERS 64
/* The maximum up or down scaling factor is 4 */
#define MAX_ZOOM 4
/* The maximum image width/height are set to 4K DMT */
@@ -481,7 +483,7 @@ struct vivid_dev {
/* video capture */
struct tpg_data tpg;
unsigned ms_vid_cap;
- bool must_blank[VIDEO_MAX_FRAME];
+ bool must_blank[MAX_VID_CAP_BUFFERS];
const struct vivid_fmt *fmt_cap;
struct v4l2_fract timeperframe_vid_cap;
diff --git a/drivers/media/test-drivers/vivid/vivid-ctrls.c b/drivers/media/test-drivers/vivid/vivid-ctrls.c
index 8bb38bc7b8cc..2b5c8fbcd0a2 100644
--- a/drivers/media/test-drivers/vivid/vivid-ctrls.c
+++ b/drivers/media/test-drivers/vivid/vivid-ctrls.c
@@ -553,7 +553,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
break;
case VIVID_CID_PERCENTAGE_FILL:
tpg_s_perc_fill(&dev->tpg, ctrl->val);
- for (i = 0; i < VIDEO_MAX_FRAME; i++)
+ for (i = 0; i < MAX_VID_CAP_BUFFERS; i++)
dev->must_blank[i] = ctrl->val < 100;
break;
case VIVID_CID_INSERT_SAV:
diff --git a/drivers/media/test-drivers/vivid/vivid-meta-cap.c b/drivers/media/test-drivers/vivid/vivid-meta-cap.c
index 0a718d037e59..c7aaecc0b5a2 100644
--- a/drivers/media/test-drivers/vivid/vivid-meta-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-meta-cap.c
@@ -122,8 +122,6 @@ const struct vb2_ops vivid_meta_cap_qops = {
.start_streaming = meta_cap_start_streaming,
.stop_streaming = meta_cap_stop_streaming,
.buf_request_complete = meta_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
int vidioc_enum_fmt_meta_cap(struct file *file, void *priv,
diff --git a/drivers/media/test-drivers/vivid/vivid-meta-out.c b/drivers/media/test-drivers/vivid/vivid-meta-out.c
index 82ab3b26914e..55e5e5dec2f2 100644
--- a/drivers/media/test-drivers/vivid/vivid-meta-out.c
+++ b/drivers/media/test-drivers/vivid/vivid-meta-out.c
@@ -122,8 +122,6 @@ const struct vb2_ops vivid_meta_out_qops = {
.start_streaming = meta_out_start_streaming,
.stop_streaming = meta_out_stop_streaming,
.buf_request_complete = meta_out_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
int vidioc_enum_fmt_meta_out(struct file *file, void *priv,
diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
index 38cda33dffb2..74a91d28c8be 100644
--- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
@@ -337,8 +337,6 @@ const struct vb2_ops vivid_sdr_cap_qops = {
.start_streaming = sdr_cap_start_streaming,
.stop_streaming = sdr_cap_stop_streaming,
.buf_request_complete = sdr_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
int vivid_sdr_enum_freq_bands(struct file *file, void *fh,
diff --git a/drivers/media/test-drivers/vivid/vivid-touch-cap.c b/drivers/media/test-drivers/vivid/vivid-touch-cap.c
index 3600b084bca5..36a781fa17bc 100644
--- a/drivers/media/test-drivers/vivid/vivid-touch-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-touch-cap.c
@@ -110,8 +110,6 @@ const struct vb2_ops vivid_touch_cap_qops = {
.start_streaming = touch_cap_start_streaming,
.stop_streaming = touch_cap_stop_streaming,
.buf_request_complete = touch_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
int vivid_enum_fmt_tch(struct file *file, void *priv, struct v4l2_fmtdesc *f)
diff --git a/drivers/media/test-drivers/vivid/vivid-vbi-cap.c b/drivers/media/test-drivers/vivid/vivid-vbi-cap.c
index 99138f63585c..a09f62c66c33 100644
--- a/drivers/media/test-drivers/vivid/vivid-vbi-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-vbi-cap.c
@@ -230,8 +230,6 @@ const struct vb2_ops vivid_vbi_cap_qops = {
.start_streaming = vbi_cap_start_streaming,
.stop_streaming = vbi_cap_stop_streaming,
.buf_request_complete = vbi_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
diff --git a/drivers/media/test-drivers/vivid/vivid-vbi-out.c b/drivers/media/test-drivers/vivid/vivid-vbi-out.c
index 871a56d93425..b7a09d2f394e 100644
--- a/drivers/media/test-drivers/vivid/vivid-vbi-out.c
+++ b/drivers/media/test-drivers/vivid/vivid-vbi-out.c
@@ -128,8 +128,6 @@ const struct vb2_ops vivid_vbi_out_qops = {
.start_streaming = vbi_out_start_streaming,
.stop_streaming = vbi_out_stop_streaming,
.buf_request_complete = vbi_out_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
int vidioc_g_fmt_vbi_out(struct file *file, void *priv,
diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
index 69620e0a35a0..b166d90177c6 100644
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <linux/videodev2.h>
+#include <linux/prandom.h>
#include <linux/v4l2-dv-timings.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
@@ -213,7 +214,7 @@ static int vid_cap_start_streaming(struct vb2_queue *vq, unsigned count)
dev->vid_cap_seq_count = 0;
dprintk(dev, 1, "%s\n", __func__);
- for (i = 0; i < VIDEO_MAX_FRAME; i++)
+ for (i = 0; i < MAX_VID_CAP_BUFFERS; i++)
dev->must_blank[i] = tpg_g_perc_fill(&dev->tpg) < 100;
if (dev->start_streaming_error) {
dev->start_streaming_error = false;
@@ -257,8 +258,6 @@ const struct vb2_ops vivid_vid_cap_qops = {
.start_streaming = vid_cap_start_streaming,
.stop_streaming = vid_cap_stop_streaming,
.buf_request_complete = vid_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/*
@@ -1459,12 +1458,19 @@ static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
h_freq = (u32)bt->pixelclock / total_h_pixel;
if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_CVT)) {
+ struct v4l2_dv_timings cvt = {};
+
if (v4l2_detect_cvt(total_v_lines, h_freq, bt->vsync, bt->width,
- bt->polarities, bt->interlaced, timings))
+ bt->polarities, bt->interlaced,
+ &vivid_dv_timings_cap, &cvt) &&
+ cvt.bt.width == bt->width && cvt.bt.height == bt->height) {
+ *timings = cvt;
return true;
+ }
}
if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_GTF)) {
+ struct v4l2_dv_timings gtf = {};
struct v4l2_fract aspect_ratio;
find_aspect_ratio(bt->width, bt->height,
@@ -1472,8 +1478,12 @@ static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
&aspect_ratio.denominator);
if (v4l2_detect_gtf(total_v_lines, h_freq, bt->vsync,
bt->polarities, bt->interlaced,
- aspect_ratio, timings))
+ aspect_ratio, &vivid_dv_timings_cap,
+ &gtf) &&
+ gtf.bt.width == bt->width && gtf.bt.height == bt->height) {
+ *timings = gtf;
return true;
+ }
}
return false;
}
diff --git a/drivers/media/test-drivers/vivid/vivid-vid-out.c b/drivers/media/test-drivers/vivid/vivid-vid-out.c
index 60327f3612af..5ec84db934d6 100644
--- a/drivers/media/test-drivers/vivid/vivid-vid-out.c
+++ b/drivers/media/test-drivers/vivid/vivid-vid-out.c
@@ -201,8 +201,6 @@ const struct vb2_ops vivid_vid_out_qops = {
.start_streaming = vid_out_start_streaming,
.stop_streaming = vid_out_stop_streaming,
.buf_request_complete = vid_out_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/*
diff --git a/drivers/media/tuners/it913x.c b/drivers/media/tuners/it913x.c
index 4d5b1c878028..9186174a46fd 100644
--- a/drivers/media/tuners/it913x.c
+++ b/drivers/media/tuners/it913x.c
@@ -444,7 +444,7 @@ static struct platform_driver it913x_driver = {
.suppress_bind_attrs = true,
},
.probe = it913x_probe,
- .remove_new = it913x_remove,
+ .remove = it913x_remove,
.id_table = it913x_id_table,
};
diff --git a/drivers/media/tuners/mt2063.c b/drivers/media/tuners/mt2063.c
index 6afef11a49cb..2c8ce74ddca4 100644
--- a/drivers/media/tuners/mt2063.c
+++ b/drivers/media/tuners/mt2063.c
@@ -1476,7 +1476,7 @@ static u32 MT2063_CalcLO2Mult(u32 *Div,
}
/*
- * FindClearTuneFilter() - Calculate the corrrect ClearTune filter to be
+ * FindClearTuneFilter() - Calculate the correct ClearTune filter to be
* used for a given input frequency.
*
* @state: ptr to tuner data structure
diff --git a/drivers/media/tuners/mxl301rf.c b/drivers/media/tuners/mxl301rf.c
index 7c03d4132763..3b61c3afed18 100644
--- a/drivers/media/tuners/mxl301rf.c
+++ b/drivers/media/tuners/mxl301rf.c
@@ -64,7 +64,7 @@ static int reg_read(struct mxl301rf_state *state, u8 reg, u8 *val)
/* tuner_ops */
-/* get RSSI and update propery cache, set to *out in % */
+/* get RSSI and update property cache, set to *out in % */
static int mxl301rf_get_rf_strength(struct dvb_frontend *fe, u16 *out)
{
struct mxl301rf_state *state;
diff --git a/drivers/media/tuners/mxl5005s.c b/drivers/media/tuners/mxl5005s.c
index d9bfa257a005..0e811c5eae6c 100644
--- a/drivers/media/tuners/mxl5005s.c
+++ b/drivers/media/tuners/mxl5005s.c
@@ -2639,7 +2639,7 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
E5A = (((Fmax - state->RF_LO)/1000)*4/((Fmax-Fmin)/1000)) + 1 ;
status += MXL_ControlWrite(fe, RFSYN_LPF_R, E5A);
- /* Euqation E5B CHCAL_EN_INIT_RF */
+ /* Equation E5B CHCAL_EN_INIT_RF */
status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, ((E5 == 0) ? 1 : 0));
/*if (E5 == 0)
* status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, 1);
diff --git a/drivers/media/tuners/tda18271-fe.c b/drivers/media/tuners/tda18271-fe.c
index a7e721baaa99..3a3309bc0151 100644
--- a/drivers/media/tuners/tda18271-fe.c
+++ b/drivers/media/tuners/tda18271-fe.c
@@ -279,7 +279,9 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
if (approx > 255)
approx = 255;
- tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt);
+ ret = tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt);
+ if (tda_fail(ret))
+ goto fail;
/* calculate temperature compensation */
rfcal_comp = dc_over_dt * (s32)(tm_current - priv->tm_rfcal) / 1000;
diff --git a/drivers/media/tuners/tea5761.c b/drivers/media/tuners/tea5761.c
index d78a2bdb3e36..425e9fd3f3d4 100644
--- a/drivers/media/tuners/tea5761.c
+++ b/drivers/media/tuners/tea5761.c
@@ -46,7 +46,7 @@ struct tea5761_priv {
/* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */
/* First byte */
-#define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from botton to up */
+#define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from bottom to up */
#define TEA5761_FRQSET_SEARCH_MODE 0x40 /* 1=Search mode */
/* Bits 0-5 for divider MSB */
@@ -132,7 +132,7 @@ static void tea5761_status_dump(unsigned char *buffer)
frq / 1000, frq % 1000, div);
}
-/* Freq should be specifyed at 62.5 Hz */
+/* Freq should be specified at 62.5 Hz */
static int __set_radio_freq(struct dvb_frontend *fe,
unsigned int freq,
bool mono)
diff --git a/drivers/media/tuners/tea5767.c b/drivers/media/tuners/tea5767.c
index 016d0d5ec50b..ef4acb1f1bfa 100644
--- a/drivers/media/tuners/tea5767.c
+++ b/drivers/media/tuners/tea5767.c
@@ -44,7 +44,7 @@ struct tea5767_priv {
/* Third register */
-/* Station search from botton to up */
+/* Station search from bottom to up */
#define TEA5767_SEARCH_UP 0x80
/* Searches with ADC output = 10 */
@@ -183,7 +183,7 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
(buffer[4] & TEA5767_RESERVED_MASK));
}
-/* Freq should be specifyed at 62.5 Hz */
+/* Freq should be specified at 62.5 Hz */
static int set_radio_freq(struct dvb_frontend *fe,
struct analog_parameters *params)
{
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index e24e655fb1db..08f0920cf6ca 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -603,8 +603,6 @@ static const struct vb2_ops airspy_vb2_ops = {
.buf_queue = airspy_buf_queue,
.start_streaming = airspy_start_streaming,
.stop_streaming = airspy_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int airspy_querycap(struct file *file, void *fh,
@@ -1017,6 +1015,7 @@ static int airspy_probe(struct usb_interface *intf,
s->vb_queue.ops = &airspy_vb2_ops;
s->vb_queue.mem_ops = &vb2_vmalloc_memops;
s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ s->vb_queue.lock = &s->vb_queue_lock;
ret = vb2_queue_init(&s->vb_queue);
if (ret) {
dev_err(s->dev, "Could not initialize vb2 queue\n");
@@ -1026,7 +1025,6 @@ static int airspy_probe(struct usb_interface *intf,
/* Init video_device structure */
s->vdev = airspy_template;
s->vdev.queue = &s->vb_queue;
- s->vdev.queue->lock = &s->vb_queue_lock;
video_set_drvdata(&s->vdev, s);
/* Register the v4l2_device structure */
diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c
index b0333637b747..11203adf47ea 100644
--- a/drivers/media/usb/au0828/au0828-vbi.c
+++ b/drivers/media/usb/au0828/au0828-vbi.c
@@ -74,6 +74,4 @@ const struct vb2_ops au0828_vbi_qops = {
.prepare_streaming = v4l_vb2q_enable_media_source,
.start_streaming = au0828_start_analog_streaming,
.stop_streaming = au0828_stop_vbi_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 2ec49ea479d5..e9cd2a335f7f 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -915,8 +915,6 @@ static const struct vb2_ops au0828_video_qops = {
.prepare_streaming = v4l_vb2q_enable_media_source,
.start_streaming = au0828_start_analog_streaming,
.stop_streaming = au0828_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* ------------------------------------------------------------------
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index abb967c8bd35..a4a9781328c5 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -1458,8 +1458,6 @@ static const struct vb2_ops cx231xx_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* ------------------------------------------------------------------ */
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
index 3d3c881c8e58..6139ef5d891d 100644
--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c
@@ -623,7 +623,7 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input)
}
int cx231xx_set_decoder_video_input(struct cx231xx *dev,
- u8 pin_type, u8 input)
+ u8 pin_type, u32 input)
{
int status = 0;
u32 value = 0;
@@ -1338,39 +1338,6 @@ void update_HH_register_after_set_DIF(struct cx231xx *dev)
*/
}
-void cx231xx_dump_HH_reg(struct cx231xx *dev)
-{
- u32 value = 0;
- u16 i = 0;
-
- value = 0x45005390;
- vid_blk_write_word(dev, 0x104, value);
-
- for (i = 0x100; i < 0x140; i++) {
- vid_blk_read_word(dev, i, &value);
- dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
- i = i+3;
- }
-
- for (i = 0x300; i < 0x400; i++) {
- vid_blk_read_word(dev, i, &value);
- dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
- i = i+3;
- }
-
- for (i = 0x400; i < 0x440; i++) {
- vid_blk_read_word(dev, i, &value);
- dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
- i = i+3;
- }
-
- vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
- dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
- vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
- vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
- dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
-}
-
#if 0
static void cx231xx_dump_SC_reg(struct cx231xx *dev)
{
@@ -2460,30 +2427,6 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
return status;
}
-int cx231xx_power_suspend(struct cx231xx *dev)
-{
- u8 value[4] = { 0, 0, 0, 0 };
- u32 tmp = 0;
- int status = 0;
-
- status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
- value, 4);
- if (status > 0)
- return status;
-
- tmp = le32_to_cpu(*((__le32 *) value));
- tmp &= (~PWR_MODE_MASK);
-
- value[0] = (u8) tmp;
- value[1] = (u8) (tmp >> 8);
- value[2] = (u8) (tmp >> 16);
- value[3] = (u8) (tmp >> 24);
- status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN,
- value, 4);
-
- return status;
-}
-
/******************************************************************************
* S T R E A M C O N T R O L functions *
******************************************************************************/
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index 92efe6c1f47b..691f073892b3 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -679,8 +679,7 @@ struct cx231xx_board cx231xx_boards[] = {
}, {
.type = CX231XX_VMUX_SVIDEO,
.vmux = CX231XX_VIN_1_1 |
- (CX231XX_VIN_1_2 << 8) |
- CX25840_SVIDEO_ON,
+ (CX231XX_VIN_3_2 << 8),
.amux = CX231XX_AMUX_LINE_IN,
.gpio = NULL,
}
@@ -990,10 +989,11 @@ struct cx231xx_board cx231xx_boards[] = {
} },
},
};
-const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
/* table of devices that work with this driver */
struct usb_device_id cx231xx_id_table[] = {
+ {USB_DEVICE(0x1D19, 0x6108),
+ .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
{USB_DEVICE(0x1D19, 0x6109),
.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
{USB_DEVICE(0x0572, 0x5A3C),
diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c
index 33431d9f54c2..338e10148465 100644
--- a/drivers/media/usb/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c
@@ -243,8 +243,6 @@ struct vb2_ops cx231xx_vbi_qops = {
.buf_queue = vbi_buf_queue,
.start_streaming = vbi_start_streaming,
.stop_streaming = vbi_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/* ------------------------------------------------------------------
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index 435eb0b32cb1..2cd4e333bc4b 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -800,8 +800,6 @@ static const struct vb2_ops cx231xx_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/********************* v4l2 interface **************************************/
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
index 74339a6a2f71..19f5036a78d7 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -790,7 +790,6 @@ void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq,
u8 spectral_invert, u32 mode);
void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev);
void reset_s5h1432_demod(struct cx231xx *dev);
-void cx231xx_dump_HH_reg(struct cx231xx *dev);
void update_HH_register_after_set_DIF(struct cx231xx *dev);
@@ -905,7 +904,6 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type);
/* Power control functions */
int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode);
-int cx231xx_power_suspend(struct cx231xx *dev);
/* chip specific control functions */
int cx231xx_init_ctrl_pin_status(struct cx231xx *dev);
@@ -916,7 +914,7 @@ int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3);
/* video audio decoder related functions */
void video_mux(struct cx231xx *dev, int index);
int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input);
-int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input);
+int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u32 input);
int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev);
int cx231xx_set_audio_input(struct cx231xx *dev, u8 input);
@@ -949,7 +947,6 @@ extern void cx231xx_pre_card_setup(struct cx231xx *dev);
extern void cx231xx_card_setup(struct cx231xx *dev);
extern struct cx231xx_board cx231xx_boards[];
extern struct usb_device_id cx231xx_id_table[];
-extern const unsigned int cx231xx_bcount;
int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
/* cx23885-417.c */
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index 8699846eb416..bea12cdc85e8 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -46,24 +46,15 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d,
dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, state->buf);
- /* We need receive one message more after dvb_usb_generic_rw due
- to weird transaction flow, which is 1 x send + 2 x receive. */
+ /*
+ * We need receive one message more after dvb_usbv2_generic_rw_locked()
+ * due to weird transaction flow, which is 1 x send + 2 x receive.
+ */
ret = dvb_usbv2_generic_rw_locked(d, state->buf, sizeof(state->buf),
state->buf, sizeof(state->buf));
if (ret)
goto error_unlock;
- /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
- * (EPIPE, Broken pipe). Function supports currently msleep() as a
- * parameter but I would not like to use it, since according to
- * Documentation/timers/timers-howto.rst it should not be used such
- * short, under < 20ms, sleeps. Repeating failed message would be
- * better choice as not to add unwanted delays...
- * Fixing that correctly is one of those or both;
- * 1) use repeat if possible
- * 2) add suitable delay
- */
-
/* get answer, retry few times if error returned */
for (i = 0; i < 3; i++) {
/* receive 2nd answer */
diff --git a/drivers/media/usb/dvb-usb/cxusb-analog.c b/drivers/media/usb/dvb-usb/cxusb-analog.c
index b5d8c6b75ae1..8253046cd6e6 100644
--- a/drivers/media/usb/dvb-usb/cxusb-analog.c
+++ b/drivers/media/usb/dvb-usb/cxusb-analog.c
@@ -956,8 +956,6 @@ static const struct vb2_ops cxdev_video_qops = {
.start_streaming = cxusb_medion_v_start_streaming,
.stop_streaming = cxusb_medion_v_stop_streaming,
.buf_queue = cxusub_medion_v_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish
};
static const __u32 videocaps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index b253c44c9724..8c5d95181223 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -84,6 +84,4 @@ const struct vb2_ops em28xx_vbi_qops = {
.buf_queue = vbi_buffer_queue,
.start_streaming = em28xx_start_analog_streaming,
.stop_streaming = em28xx_stop_vbi_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 4aef584e21da..66c09bc6d59e 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1229,8 +1229,6 @@ static const struct vb2_ops em28xx_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = em28xx_start_analog_streaming,
.stop_streaming = em28xx_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int em28xx_vb2_setup(struct em28xx *dev)
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index 13256565b034..2087ffcb85a5 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -452,8 +452,6 @@ static const struct vb2_ops go7007_video_qops = {
.buf_finish = go7007_buf_finish,
.start_streaming = go7007_start_streaming,
.stop_streaming = go7007_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int vidioc_g_parm(struct file *filp, void *priv,
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index e8c8bdb9c40b..25edd2189654 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -1380,8 +1380,6 @@ static const struct vb2_ops gspca_qops = {
.buf_queue = gspca_buffer_queue,
.start_streaming = gspca_start_streaming,
.stop_streaming = gspca_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static const struct v4l2_file_operations dev_fops = {
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
index 8b6a57f170d0..bdff64a29a33 100644
--- a/drivers/media/usb/gspca/ov534.c
+++ b/drivers/media/usb/gspca/ov534.c
@@ -847,7 +847,7 @@ static void set_frame_rate(struct gspca_dev *gspca_dev)
r = rate_1;
i = ARRAY_SIZE(rate_1);
}
- while (--i > 0) {
+ while (--i >= 0) {
if (sd->frame_rate >= r->fps)
break;
r++;
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index 9c0ecd5f056c..0b50de8775a3 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -888,8 +888,6 @@ static const struct vb2_ops hackrf_vb2_ops = {
.buf_queue = hackrf_buf_queue,
.start_streaming = hackrf_start_streaming,
.stop_streaming = hackrf_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int hackrf_querycap(struct file *file, void *fh,
@@ -1398,6 +1396,7 @@ static int hackrf_probe(struct usb_interface *intf,
dev->rx_vb2_queue.drv_priv = dev;
dev->rx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer);
dev->rx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ dev->rx_vb2_queue.lock = &dev->vb_queue_lock;
ret = vb2_queue_init(&dev->rx_vb2_queue);
if (ret) {
dev_err(dev->dev, "Could not initialize rx vb2 queue\n");
@@ -1413,6 +1412,7 @@ static int hackrf_probe(struct usb_interface *intf,
dev->tx_vb2_queue.drv_priv = dev;
dev->tx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer);
dev->tx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ dev->tx_vb2_queue.lock = &dev->vb_queue_lock;
ret = vb2_queue_init(&dev->tx_vb2_queue);
if (ret) {
dev_err(dev->dev, "Could not initialize tx vb2 queue\n");
@@ -1474,7 +1474,6 @@ static int hackrf_probe(struct usb_interface *intf,
/* Init video_device structure for receiver */
dev->rx_vdev = hackrf_template;
dev->rx_vdev.queue = &dev->rx_vb2_queue;
- dev->rx_vdev.queue->lock = &dev->vb_queue_lock;
dev->rx_vdev.v4l2_dev = &dev->v4l2_dev;
dev->rx_vdev.ctrl_handler = &dev->rx_ctrl_handler;
dev->rx_vdev.lock = &dev->v4l2_lock;
@@ -1494,7 +1493,6 @@ static int hackrf_probe(struct usb_interface *intf,
/* Init video_device structure for transmitter */
dev->tx_vdev = hackrf_template;
dev->tx_vdev.queue = &dev->tx_vb2_queue;
- dev->tx_vdev.queue->lock = &dev->vb_queue_lock;
dev->tx_vdev.v4l2_dev = &dev->v4l2_dev;
dev->tx_vdev.ctrl_handler = &dev->tx_ctrl_handler;
dev->tx_vdev.lock = &dev->v4l2_lock;
diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c
index 5138486abfa0..33099f39146a 100644
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -883,8 +883,6 @@ static const struct vb2_ops msi2500_vb2_ops = {
.buf_queue = msi2500_buf_queue,
.start_streaming = msi2500_start_streaming,
.stop_streaming = msi2500_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int msi2500_enum_fmt_sdr_cap(struct file *file, void *priv,
@@ -1199,6 +1197,7 @@ static int msi2500_probe(struct usb_interface *intf,
dev->vb_queue.ops = &msi2500_vb2_ops;
dev->vb_queue.mem_ops = &vb2_vmalloc_memops;
dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ dev->vb_queue.lock = &dev->vb_queue_lock;
ret = vb2_queue_init(&dev->vb_queue);
if (ret) {
dev_err(dev->dev, "Could not initialize vb2 queue\n");
@@ -1208,7 +1207,6 @@ static int msi2500_probe(struct usb_interface *intf,
/* Init video_device structure */
dev->vdev = msi2500_template;
dev->vdev.queue = &dev->vb_queue;
- dev->vdev.queue->lock = &dev->vb_queue_lock;
video_set_drvdata(&dev->vdev, dev);
/* Register the v4l2_device structure */
@@ -1219,8 +1217,8 @@ static int msi2500_probe(struct usb_interface *intf,
goto err_free_mem;
}
- /* SPI master adapter */
- ctlr = spi_alloc_master(dev->dev, 0);
+ /* SPI host adapter */
+ ctlr = spi_alloc_host(dev->dev, 0);
if (ctlr == NULL) {
ret = -ENOMEM;
goto err_unregister_v4l2_dev;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.c b/drivers/media/usb/pvrusb2/pvrusb2-io.c
index 675dc7153e2b..28ffe7981f8c 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-io.c
@@ -335,8 +335,8 @@ static int pvr2_stream_buffer_count(struct pvr2_stream *sp, unsigned int cnt)
if (scnt < sp->buffer_slot_count) {
struct pvr2_buffer **nb = NULL;
if (scnt) {
- nb = kmemdup(sp->buffers, scnt * sizeof(*nb),
- GFP_KERNEL);
+ nb = kmemdup_array(sp->buffers, scnt, sizeof(*nb),
+ GFP_KERNEL);
if (!nb) return -ENOMEM;
}
kfree(sp->buffers);
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index e342199711d3..3ec9eb5956ed 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -760,8 +760,6 @@ static const struct vb2_ops pwc_vb_queue_ops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/***************************************************************************/
@@ -1054,6 +1052,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->vb_queue.ops = &pwc_vb_queue_ops;
pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
pdev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ pdev->vb_queue.lock = &pdev->vb_queue_lock;
rc = vb2_queue_init(&pdev->vb_queue);
if (rc < 0) {
PWC_ERROR("Oops, could not initialize vb2 queue.\n");
@@ -1064,7 +1063,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->vdev = pwc_template;
strscpy(pdev->vdev.name, name, sizeof(pdev->vdev.name));
pdev->vdev.queue = &pdev->vb_queue;
- pdev->vdev.queue->lock = &pdev->vb_queue_lock;
video_set_drvdata(&pdev->vdev, pdev);
pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index a6e450181fd0..899a7a67e2ba 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -704,8 +704,6 @@ static const struct vb2_ops s2255_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int vidioc_querycap(struct file *file, void *priv,
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index a1f785a5ffd8..5ba3d9c4b3fb 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -734,8 +734,6 @@ static const struct vb2_ops stk1160_video_qops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static const struct video_device v4l_template = {
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 702f1c8bd2ab..be22a9697197 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -780,8 +780,6 @@ static const struct vb2_ops usbtv_vb2_ops = {
.buf_queue = usbtv_buf_queue,
.start_streaming = usbtv_start_streaming,
.stop_streaming = usbtv_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 0fac689c6350..b3c8411dc05c 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -371,7 +371,7 @@ static int uvc_parse_format(struct uvc_device *dev,
* Parse the frame descriptors. Only uncompressed, MJPEG and frame
* based formats have frame descriptors.
*/
- while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+ while (ftype && buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
buffer[2] == ftype) {
unsigned int maxIntervalIndex;
@@ -775,14 +775,27 @@ static const u8 uvc_media_transport_input_guid[16] =
UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT;
static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;
-static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id,
- unsigned int num_pads, unsigned int extra_size)
+static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type,
+ u16 id, unsigned int num_pads,
+ unsigned int extra_size)
{
struct uvc_entity *entity;
unsigned int num_inputs;
unsigned int size;
unsigned int i;
+ /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */
+ if (id == 0) {
+ dev_err(&dev->udev->dev, "Found Unit with invalid ID 0.\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */
+ if (uvc_entity_by_id(dev, id)) {
+ dev_err(&dev->udev->dev, "Found multiple Units with ID %u\n", id);
+ return ERR_PTR(-EINVAL);
+ }
+
extra_size = roundup(extra_size, sizeof(*entity->pads));
if (num_pads)
num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1;
@@ -792,7 +805,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id,
+ num_inputs;
entity = kzalloc(size, GFP_KERNEL);
if (entity == NULL)
- return NULL;
+ return ERR_PTR(-ENOMEM);
entity->id = id;
entity->type = type;
@@ -904,10 +917,10 @@ static int uvc_parse_vendor_control(struct uvc_device *dev,
break;
}
- unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
- p + 1, 2*n);
- if (unit == NULL)
- return -ENOMEM;
+ unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT,
+ buffer[3], p + 1, 2 * n);
+ if (IS_ERR(unit))
+ return PTR_ERR(unit);
memcpy(unit->guid, &buffer[4], 16);
unit->extension.bNumControls = buffer[20];
@@ -1016,10 +1029,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL;
}
- term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
- 1, n + p);
- if (term == NULL)
- return -ENOMEM;
+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT,
+ buffer[3], 1, n + p);
+ if (IS_ERR(term))
+ return PTR_ERR(term);
if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
term->camera.bControlSize = n;
@@ -1075,10 +1088,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return 0;
}
- term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
- 1, 0);
- if (term == NULL)
- return -ENOMEM;
+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT,
+ buffer[3], 1, 0);
+ if (IS_ERR(term))
+ return PTR_ERR(term);
memcpy(term->baSourceID, &buffer[7], 1);
@@ -1097,9 +1110,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL;
}
- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
- if (unit == NULL)
- return -ENOMEM;
+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3],
+ p + 1, 0);
+ if (IS_ERR(unit))
+ return PTR_ERR(unit);
memcpy(unit->baSourceID, &buffer[5], p);
@@ -1119,9 +1133,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL;
}
- unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
- if (unit == NULL)
- return -ENOMEM;
+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n);
+ if (IS_ERR(unit))
+ return PTR_ERR(unit);
memcpy(unit->baSourceID, &buffer[4], 1);
unit->processing.wMaxMultiplier =
@@ -1148,9 +1162,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL;
}
- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
- if (unit == NULL)
- return -ENOMEM;
+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3],
+ p + 1, n);
+ if (IS_ERR(unit))
+ return PTR_ERR(unit);
memcpy(unit->guid, &buffer[4], 16);
unit->extension.bNumControls = buffer[20];
@@ -1290,9 +1305,10 @@ static int uvc_gpio_parse(struct uvc_device *dev)
return dev_err_probe(&dev->udev->dev, irq,
"No IRQ for privacy GPIO\n");
- unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1);
- if (!unit)
- return -ENOMEM;
+ unit = uvc_alloc_new_entity(dev, UVC_EXT_GPIO_UNIT,
+ UVC_EXT_GPIO_UNIT_ID, 0, 1);
+ if (IS_ERR(unit))
+ return PTR_ERR(unit);
unit->gpio.gpio_privacy = gpio_privacy;
unit->gpio.irq = irq;
@@ -1919,11 +1935,41 @@ static void uvc_unregister_video(struct uvc_device *dev)
struct uvc_streaming *stream;
list_for_each_entry(stream, &dev->streams, list) {
+ /* Nothing to do here, continue. */
if (!video_is_registered(&stream->vdev))
continue;
+ /*
+ * For stream->vdev we follow the same logic as:
+ * vb2_video_unregister_device().
+ */
+
+ /* 1. Take a reference to vdev */
+ get_device(&stream->vdev.dev);
+
+ /* 2. Ensure that no new ioctls can be called. */
video_unregister_device(&stream->vdev);
- video_unregister_device(&stream->meta.vdev);
+
+ /* 3. Wait for old ioctls to finish. */
+ mutex_lock(&stream->mutex);
+
+ /* 4. Stop streaming. */
+ uvc_queue_release(&stream->queue);
+
+ mutex_unlock(&stream->mutex);
+
+ put_device(&stream->vdev.dev);
+
+ /*
+ * For stream->meta.vdev we can directly call:
+ * vb2_video_unregister_device().
+ */
+ vb2_video_unregister_device(&stream->meta.vdev);
+
+ /*
+ * Now both vdevs are not streaming and all the ioctls will
+ * return -ENODEV.
+ */
uvc_debugfs_cleanup_stream(stream);
}
@@ -2116,7 +2162,6 @@ static int uvc_probe(struct usb_interface *intf,
INIT_LIST_HEAD(&dev->streams);
kref_init(&dev->ref);
atomic_set(&dev->nmappings, 0);
- mutex_init(&dev->lock);
dev->udev = usb_get_dev(udev);
dev->intf = usb_get_intf(intf);
@@ -2288,10 +2333,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
/* Controls are cached on the fly so they don't need to be saved. */
if (intf->cur_altsetting->desc.bInterfaceSubClass ==
UVC_SC_VIDEOCONTROL) {
- mutex_lock(&dev->lock);
- if (dev->users)
- uvc_status_stop(dev);
- mutex_unlock(&dev->lock);
+ uvc_status_suspend(dev);
return 0;
}
@@ -2322,12 +2364,7 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
return ret;
}
- mutex_lock(&dev->lock);
- if (dev->users)
- ret = uvc_status_start(dev, GFP_NOIO);
- mutex_unlock(&dev->lock);
-
- return ret;
+ return uvc_status_resume(dev);
}
list_for_each_entry(stream, &dev->streams, list) {
@@ -2428,12 +2465,25 @@ static const struct uvc_device_info uvc_quirk_force_y8 = {
* The Logitech cameras listed below have their interface class set to
* VENDOR_SPEC because they don't announce themselves as UVC devices, even
* though they are compliant.
+ *
+ * Sort these by vendor/product ID.
*/
static const struct usb_device_id uvc_ids[] = {
/* Quanta ACER HD User Facing */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x0408,
+ .idProduct = 0x4033,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_15,
+ .driver_info = (kernel_ulong_t)&(const struct uvc_device_info){
+ .uvc_version = 0x010a,
+ } },
+ /* Quanta ACER HD User Facing */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x0408,
.idProduct = 0x4035,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
@@ -2964,6 +3014,15 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceProtocol = 0,
.driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_IGNORE_SELECTOR_UNIT) },
+ /* NXP Semiconductors IR VIDEO */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x1fc9,
+ .idProduct = 0x009b,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = (kernel_ulong_t)&uvc_quirk_probe_minmax },
/* Oculus VR Positional Tracker DK2 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -3072,6 +3131,15 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* Intel D421 Depth Module */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x8086,
+ .idProduct = 0x1155,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 16fa17bbd15e..26ee85657fc8 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -197,8 +197,6 @@ static const struct vb2_ops uvc_queue_qops = {
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue,
.buf_finish = uvc_buffer_finish,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.start_streaming = uvc_start_streaming,
.stop_streaming = uvc_stop_streaming,
};
@@ -207,8 +205,6 @@ static const struct vb2_ops uvc_meta_queue_qops = {
.queue_setup = uvc_queue_setup,
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
.stop_streaming = uvc_stop_streaming,
};
diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c
index a78a88c710e2..06c867510c8f 100644
--- a/drivers/media/usb/uvc/uvc_status.c
+++ b/drivers/media/usb/uvc/uvc_status.c
@@ -257,6 +257,8 @@ int uvc_status_init(struct uvc_device *dev)
unsigned int pipe;
int interval;
+ mutex_init(&dev->status_lock);
+
if (ep == NULL)
return 0;
@@ -292,7 +294,7 @@ int uvc_status_init(struct uvc_device *dev)
void uvc_status_unregister(struct uvc_device *dev)
{
- usb_kill_urb(dev->int_urb);
+ uvc_status_suspend(dev);
uvc_input_unregister(dev);
}
@@ -302,18 +304,25 @@ void uvc_status_cleanup(struct uvc_device *dev)
kfree(dev->status);
}
-int uvc_status_start(struct uvc_device *dev, gfp_t flags)
+static int uvc_status_start(struct uvc_device *dev, gfp_t flags)
{
- if (dev->int_urb == NULL)
+ lockdep_assert_held(&dev->status_lock);
+
+ if (!dev->int_urb)
return 0;
return usb_submit_urb(dev->int_urb, flags);
}
-void uvc_status_stop(struct uvc_device *dev)
+static void uvc_status_stop(struct uvc_device *dev)
{
struct uvc_ctrl_work *w = &dev->async_ctrl;
+ lockdep_assert_held(&dev->status_lock);
+
+ if (!dev->int_urb)
+ return;
+
/*
* Prevent the asynchronous control handler from requeing the URB. The
* barrier is needed so the flush_status change is visible to other
@@ -350,3 +359,49 @@ void uvc_status_stop(struct uvc_device *dev)
*/
smp_store_release(&dev->flush_status, false);
}
+
+int uvc_status_resume(struct uvc_device *dev)
+{
+ guard(mutex)(&dev->status_lock);
+
+ if (dev->status_users)
+ return uvc_status_start(dev, GFP_NOIO);
+
+ return 0;
+}
+
+void uvc_status_suspend(struct uvc_device *dev)
+{
+ guard(mutex)(&dev->status_lock);
+
+ if (dev->status_users)
+ uvc_status_stop(dev);
+}
+
+int uvc_status_get(struct uvc_device *dev)
+{
+ int ret;
+
+ guard(mutex)(&dev->status_lock);
+
+ if (!dev->status_users) {
+ ret = uvc_status_start(dev, GFP_KERNEL);
+ if (ret)
+ return ret;
+ }
+
+ dev->status_users++;
+
+ return 0;
+}
+
+void uvc_status_put(struct uvc_device *dev)
+{
+ guard(mutex)(&dev->status_lock);
+
+ if (dev->status_users == 1)
+ uvc_status_stop(dev);
+ WARN_ON(!dev->status_users);
+ if (dev->status_users)
+ dev->status_users--;
+}
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index f4988f03640a..97c5407f6603 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -628,20 +628,13 @@ static int uvc_v4l2_open(struct file *file)
return -ENOMEM;
}
- mutex_lock(&stream->dev->lock);
- if (stream->dev->users == 0) {
- ret = uvc_status_start(stream->dev, GFP_KERNEL);
- if (ret < 0) {
- mutex_unlock(&stream->dev->lock);
- usb_autopm_put_interface(stream->dev->intf);
- kfree(handle);
- return ret;
- }
+ ret = uvc_status_get(stream->dev);
+ if (ret) {
+ usb_autopm_put_interface(stream->dev->intf);
+ kfree(handle);
+ return ret;
}
- stream->dev->users++;
- mutex_unlock(&stream->dev->lock);
-
v4l2_fh_init(&handle->vfh, &stream->vdev);
v4l2_fh_add(&handle->vfh);
handle->chain = stream->chain;
@@ -670,10 +663,7 @@ static int uvc_v4l2_release(struct file *file)
kfree(handle);
file->private_data = NULL;
- mutex_lock(&stream->dev->lock);
- if (--stream->dev->users == 0)
- uvc_status_stop(stream->dev);
- mutex_unlock(&stream->dev->lock);
+ uvc_status_put(stream->dev);
usb_autopm_put_interface(stream->dev->intf);
return 0;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index b7d24a853ce4..07f9921d83f2 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -563,8 +563,6 @@ struct uvc_device {
const struct uvc_device_info *info;
- struct mutex lock; /* Protects users */
- unsigned int users;
atomic_t nmappings;
/* Video control interface */
@@ -586,6 +584,8 @@ struct uvc_device {
struct usb_host_endpoint *int_ep;
struct urb *int_urb;
struct uvc_status *status;
+ struct mutex status_lock; /* Protects status_users */
+ unsigned int status_users;
bool flush_status;
struct input_dev *input;
@@ -752,8 +752,10 @@ int uvc_register_video_device(struct uvc_device *dev,
int uvc_status_init(struct uvc_device *dev);
void uvc_status_unregister(struct uvc_device *dev);
void uvc_status_cleanup(struct uvc_device *dev);
-int uvc_status_start(struct uvc_device *dev, gfp_t flags);
-void uvc_status_stop(struct uvc_device *dev);
+int uvc_status_resume(struct uvc_device *dev);
+void uvc_status_suspend(struct uvc_device *dev);
+int uvc_status_get(struct uvc_device *dev);
+void uvc_status_put(struct uvc_device *dev);
/* Controls */
extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops;
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c
index e5a364efd5e6..95a2202879d8 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-api.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c
@@ -753,9 +753,10 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
for (i = 0; i < master->ncontrols; i++)
cur_to_new(master->cluster[i]);
ret = call_op(master, g_volatile_ctrl);
- new_to_user(c, ctrl);
+ if (!ret)
+ ret = new_to_user(c, ctrl);
} else {
- cur_to_user(c, ctrl);
+ ret = cur_to_user(c, ctrl);
}
v4l2_ctrl_unlock(master);
return ret;
@@ -770,7 +771,10 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
if (!ctrl || !ctrl->is_int)
return -EINVAL;
ret = get_ctrl(ctrl, &c);
- control->value = c.value;
+
+ if (!ret)
+ control->value = c.value;
+
return ret;
}
EXPORT_SYMBOL(v4l2_g_ctrl);
@@ -811,10 +815,11 @@ static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
int ret;
v4l2_ctrl_lock(ctrl);
- user_to_new(c, ctrl);
- ret = set_ctrl(fh, ctrl, 0);
+ ret = user_to_new(c, ctrl);
+ if (!ret)
+ ret = set_ctrl(fh, ctrl, 0);
if (!ret)
- cur_to_user(c, ctrl);
+ ret = cur_to_user(c, ctrl);
v4l2_ctrl_unlock(ctrl);
return ret;
}
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 3d7711cc42bc..5bcaeeba4d09 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -93,6 +93,8 @@ static struct attribute *video_device_attrs[] = {
};
ATTRIBUTE_GROUPS(video_device);
+static struct dentry *v4l2_debugfs_root_dir;
+
/*
* Active devices
*/
@@ -227,7 +229,7 @@ static void v4l2_device_release(struct device *cd)
v4l2_device_put(v4l2_dev);
}
-static struct class video_class = {
+static const struct class video_class = {
.name = VIDEO_NAME,
.dev_groups = video_device_groups,
};
@@ -1118,6 +1120,16 @@ void video_unregister_device(struct video_device *vdev)
}
EXPORT_SYMBOL(video_unregister_device);
+#ifdef CONFIG_DEBUG_FS
+struct dentry *v4l2_debugfs_root(void)
+{
+ if (!v4l2_debugfs_root_dir)
+ v4l2_debugfs_root_dir = debugfs_create_dir("v4l2", NULL);
+ return v4l2_debugfs_root_dir;
+}
+EXPORT_SYMBOL_GPL(v4l2_debugfs_root);
+#endif
+
#if defined(CONFIG_MEDIA_CONTROLLER)
__must_check int video_device_pipeline_start(struct video_device *vdev,
@@ -1222,6 +1234,8 @@ static void __exit videodev_exit(void)
class_unregister(&video_class);
unregister_chrdev_region(dev, VIDEO_NUM_DEVICES);
+ debugfs_remove_recursive(v4l2_debugfs_root_dir);
+ v4l2_debugfs_root_dir = NULL;
}
subsys_initcall(videodev_init);
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c
index 942d0005c55e..d26edf157e64 100644
--- a/drivers/media/v4l2-core/v4l2-dv-timings.c
+++ b/drivers/media/v4l2-core/v4l2-dv-timings.c
@@ -481,25 +481,28 @@ EXPORT_SYMBOL_GPL(v4l2_calc_timeperframe);
* @polarities - the horizontal and vertical polarities (same as struct
* v4l2_bt_timings polarities).
* @interlaced - if this flag is true, it indicates interlaced format
- * @fmt - the resulting timings.
+ * @cap - the v4l2_dv_timings_cap capabilities.
+ * @timings - the resulting timings.
*
* This function will attempt to detect if the given values correspond to a
* valid CVT format. If so, then it will return true, and fmt will be filled
* in with the found CVT timings.
*/
-bool v4l2_detect_cvt(unsigned frame_height,
- unsigned hfreq,
- unsigned vsync,
- unsigned active_width,
+bool v4l2_detect_cvt(unsigned int frame_height,
+ unsigned int hfreq,
+ unsigned int vsync,
+ unsigned int active_width,
u32 polarities,
bool interlaced,
- struct v4l2_dv_timings *fmt)
+ const struct v4l2_dv_timings_cap *cap,
+ struct v4l2_dv_timings *timings)
{
- int v_fp, v_bp, h_fp, h_bp, hsync;
- int frame_width, image_height, image_width;
+ struct v4l2_dv_timings t = {};
+ int v_fp, v_bp, h_fp, h_bp, hsync;
+ int frame_width, image_height, image_width;
bool reduced_blanking;
bool rb_v2 = false;
- unsigned pix_clk;
+ unsigned int pix_clk;
if (vsync < 4 || vsync > 8)
return false;
@@ -625,36 +628,39 @@ bool v4l2_detect_cvt(unsigned frame_height,
h_fp = h_blank - hsync - h_bp;
}
- fmt->type = V4L2_DV_BT_656_1120;
- fmt->bt.polarities = polarities;
- fmt->bt.width = image_width;
- fmt->bt.height = image_height;
- fmt->bt.hfrontporch = h_fp;
- fmt->bt.vfrontporch = v_fp;
- fmt->bt.hsync = hsync;
- fmt->bt.vsync = vsync;
- fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
+ t.type = V4L2_DV_BT_656_1120;
+ t.bt.polarities = polarities;
+ t.bt.width = image_width;
+ t.bt.height = image_height;
+ t.bt.hfrontporch = h_fp;
+ t.bt.vfrontporch = v_fp;
+ t.bt.hsync = hsync;
+ t.bt.vsync = vsync;
+ t.bt.hbackporch = frame_width - image_width - h_fp - hsync;
if (!interlaced) {
- fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
- fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
+ t.bt.vbackporch = frame_height - image_height - v_fp - vsync;
+ t.bt.interlaced = V4L2_DV_PROGRESSIVE;
} else {
- fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
+ t.bt.vbackporch = (frame_height - image_height - 2 * v_fp -
2 * vsync) / 2;
- fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
- 2 * vsync - fmt->bt.vbackporch;
- fmt->bt.il_vfrontporch = v_fp;
- fmt->bt.il_vsync = vsync;
- fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
- fmt->bt.interlaced = V4L2_DV_INTERLACED;
+ t.bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
+ 2 * vsync - t.bt.vbackporch;
+ t.bt.il_vfrontporch = v_fp;
+ t.bt.il_vsync = vsync;
+ t.bt.flags |= V4L2_DV_FL_HALF_LINE;
+ t.bt.interlaced = V4L2_DV_INTERLACED;
}
- fmt->bt.pixelclock = pix_clk;
- fmt->bt.standards = V4L2_DV_BT_STD_CVT;
+ t.bt.pixelclock = pix_clk;
+ t.bt.standards = V4L2_DV_BT_STD_CVT;
if (reduced_blanking)
- fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+ t.bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+ if (!v4l2_valid_dv_timings(&t, cap, NULL, NULL))
+ return false;
+ *timings = t;
return true;
}
EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
@@ -699,22 +705,25 @@ EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
* image height, so it has to be passed explicitly. Usually
* the native screen aspect ratio is used for this. If it
* is not filled in correctly, then 16:9 will be assumed.
- * @fmt - the resulting timings.
+ * @cap - the v4l2_dv_timings_cap capabilities.
+ * @timings - the resulting timings.
*
* This function will attempt to detect if the given values correspond to a
* valid GTF format. If so, then it will return true, and fmt will be filled
* in with the found GTF timings.
*/
-bool v4l2_detect_gtf(unsigned frame_height,
- unsigned hfreq,
- unsigned vsync,
- u32 polarities,
- bool interlaced,
- struct v4l2_fract aspect,
- struct v4l2_dv_timings *fmt)
+bool v4l2_detect_gtf(unsigned int frame_height,
+ unsigned int hfreq,
+ unsigned int vsync,
+ u32 polarities,
+ bool interlaced,
+ struct v4l2_fract aspect,
+ const struct v4l2_dv_timings_cap *cap,
+ struct v4l2_dv_timings *timings)
{
+ struct v4l2_dv_timings t = {};
int pix_clk;
- int v_fp, v_bp, h_fp, hsync;
+ int v_fp, v_bp, h_fp, hsync;
int frame_width, image_height, image_width;
bool default_gtf;
int h_blank;
@@ -783,36 +792,39 @@ bool v4l2_detect_gtf(unsigned frame_height,
h_fp = h_blank / 2 - hsync;
- fmt->type = V4L2_DV_BT_656_1120;
- fmt->bt.polarities = polarities;
- fmt->bt.width = image_width;
- fmt->bt.height = image_height;
- fmt->bt.hfrontporch = h_fp;
- fmt->bt.vfrontporch = v_fp;
- fmt->bt.hsync = hsync;
- fmt->bt.vsync = vsync;
- fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
+ t.type = V4L2_DV_BT_656_1120;
+ t.bt.polarities = polarities;
+ t.bt.width = image_width;
+ t.bt.height = image_height;
+ t.bt.hfrontporch = h_fp;
+ t.bt.vfrontporch = v_fp;
+ t.bt.hsync = hsync;
+ t.bt.vsync = vsync;
+ t.bt.hbackporch = frame_width - image_width - h_fp - hsync;
if (!interlaced) {
- fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
- fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
+ t.bt.vbackporch = frame_height - image_height - v_fp - vsync;
+ t.bt.interlaced = V4L2_DV_PROGRESSIVE;
} else {
- fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
+ t.bt.vbackporch = (frame_height - image_height - 2 * v_fp -
2 * vsync) / 2;
- fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
- 2 * vsync - fmt->bt.vbackporch;
- fmt->bt.il_vfrontporch = v_fp;
- fmt->bt.il_vsync = vsync;
- fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
- fmt->bt.interlaced = V4L2_DV_INTERLACED;
+ t.bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
+ 2 * vsync - t.bt.vbackporch;
+ t.bt.il_vfrontporch = v_fp;
+ t.bt.il_vsync = vsync;
+ t.bt.flags |= V4L2_DV_FL_HALF_LINE;
+ t.bt.interlaced = V4L2_DV_INTERLACED;
}
- fmt->bt.pixelclock = pix_clk;
- fmt->bt.standards = V4L2_DV_BT_STD_GTF;
+ t.bt.pixelclock = pix_clk;
+ t.bt.standards = V4L2_DV_BT_STD_GTF;
if (!default_gtf)
- fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+ t.bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+ if (!v4l2_valid_dv_timings(&t, cap, NULL, NULL))
+ return false;
+ *timings = t;
return true;
}
EXPORT_SYMBOL_GPL(v4l2_detect_gtf);
@@ -1154,3 +1166,70 @@ int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_phys_addr_validate);
+
+#ifdef CONFIG_DEBUG_FS
+
+#define DEBUGFS_FOPS(type, flag) \
+static ssize_t \
+infoframe_read_##type(struct file *filp, \
+ char __user *ubuf, size_t count, loff_t *ppos) \
+{ \
+ struct v4l2_debugfs_if *infoframes = filp->private_data; \
+ \
+ return infoframes->if_read((flag), infoframes->priv, filp, \
+ ubuf, count, ppos); \
+} \
+ \
+static const struct file_operations infoframe_##type##_fops = { \
+ .owner = THIS_MODULE, \
+ .open = simple_open, \
+ .read = infoframe_read_##type, \
+}
+
+DEBUGFS_FOPS(avi, V4L2_DEBUGFS_IF_AVI);
+DEBUGFS_FOPS(audio, V4L2_DEBUGFS_IF_AUDIO);
+DEBUGFS_FOPS(spd, V4L2_DEBUGFS_IF_SPD);
+DEBUGFS_FOPS(hdmi, V4L2_DEBUGFS_IF_HDMI);
+
+struct v4l2_debugfs_if *v4l2_debugfs_if_alloc(struct dentry *root, u32 if_types,
+ void *priv,
+ v4l2_debugfs_if_read_t if_read)
+{
+ struct v4l2_debugfs_if *infoframes;
+
+ if (IS_ERR_OR_NULL(root) || !if_types || !if_read)
+ return NULL;
+
+ infoframes = kzalloc(sizeof(*infoframes), GFP_KERNEL);
+ if (!infoframes)
+ return NULL;
+
+ infoframes->if_dir = debugfs_create_dir("infoframes", root);
+ infoframes->priv = priv;
+ infoframes->if_read = if_read;
+ if (if_types & V4L2_DEBUGFS_IF_AVI)
+ debugfs_create_file("avi", 0400, infoframes->if_dir,
+ infoframes, &infoframe_avi_fops);
+ if (if_types & V4L2_DEBUGFS_IF_AUDIO)
+ debugfs_create_file("audio", 0400, infoframes->if_dir,
+ infoframes, &infoframe_audio_fops);
+ if (if_types & V4L2_DEBUGFS_IF_SPD)
+ debugfs_create_file("spd", 0400, infoframes->if_dir,
+ infoframes, &infoframe_spd_fops);
+ if (if_types & V4L2_DEBUGFS_IF_HDMI)
+ debugfs_create_file("hdmi", 0400, infoframes->if_dir,
+ infoframes, &infoframe_hdmi_fops);
+ return infoframes;
+}
+EXPORT_SYMBOL_GPL(v4l2_debugfs_if_alloc);
+
+void v4l2_debugfs_if_free(struct v4l2_debugfs_if *infoframes)
+{
+ if (infoframes) {
+ debugfs_remove_recursive(infoframes->if_dir);
+ kfree(infoframes);
+ }
+}
+EXPORT_SYMBOL_GPL(v4l2_debugfs_if_free);
+
+#endif
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index e14db67be97c..0304daa8471d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1327,6 +1327,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_Y14P: descr = "14-bit Greyscale (MIPI Packed)"; break;
case V4L2_PIX_FMT_Y8I: descr = "Interleaved 8-bit Greyscale"; break;
case V4L2_PIX_FMT_Y12I: descr = "Interleaved 12-bit Greyscale"; break;
+ case V4L2_PIX_FMT_Y16I: descr = "Interleaved 16-bit Greyscale"; break;
case V4L2_PIX_FMT_Z16: descr = "16-bit Depth"; break;
case V4L2_PIX_FMT_INZI: descr = "Planar 10:16 Greyscale Depth"; break;
case V4L2_PIX_FMT_CNF4: descr = "4-bit Depth Confidence (Packed)"; break;
@@ -1467,6 +1468,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_Y212: descr = "12-bit YUYV Packed"; break;
case V4L2_PIX_FMT_Y216: descr = "16-bit YUYV Packed"; break;
case V4L2_META_FMT_RPI_BE_CFG: descr = "RPi PiSP BE Config format"; break;
+ case V4L2_META_FMT_RPI_FE_CFG: descr = "RPi PiSP FE Config format"; break;
+ case V4L2_META_FMT_RPI_FE_STATS: descr = "RPi PiSP FE Statistics format"; break;
case V4L2_META_FMT_GENERIC_8: descr = "8-bit Generic Metadata"; break;
case V4L2_META_FMT_GENERIC_CSI2_10: descr = "8-bit Generic Meta, 10b CSI-2"; break;
case V4L2_META_FMT_GENERIC_CSI2_12: descr = "8-bit Generic Meta, 12b CSI-2"; break;
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 3a4ba08810d2..cde1774c9098 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -334,6 +334,11 @@ static int call_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
unsigned int i;
int ret;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
+ return -EOPNOTSUPP;
+#endif
+
memset(fd, 0, sizeof(*fd));
ret = sd->ops->pad->get_frame_desc(sd, pad, fd);
@@ -691,10 +696,25 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK);
case VIDIOC_SUBSCRIBE_EVENT:
- return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg);
+ if (v4l2_subdev_has_op(sd, core, subscribe_event))
+ return v4l2_subdev_call(sd, core, subscribe_event,
+ vfh, arg);
+
+ if ((sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) &&
+ vfh->ctrl_handler)
+ return v4l2_ctrl_subdev_subscribe_event(sd, vfh, arg);
+
+ return -ENOIOCTLCMD;
case VIDIOC_UNSUBSCRIBE_EVENT:
- return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+ if (v4l2_subdev_has_op(sd, core, unsubscribe_event))
+ return v4l2_subdev_call(sd, core, unsubscribe_event,
+ vfh, arg);
+
+ if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)
+ return v4l2_event_subdev_unsubscribe(sd, vfh, arg);
+
+ return -ENOIOCTLCMD;
#ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_DBG_G_REGISTER:
@@ -1641,6 +1661,9 @@ int __v4l2_subdev_init_finalize(struct v4l2_subdev *sd, const char *name,
}
}
+ if (sd->ctrl_handler)
+ sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+
state = __v4l2_subdev_state_alloc(sd, name, key);
if (IS_ERR(state))
return PTR_ERR(state);
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index 9a3a784054cc..ae4e8b8e6eb7 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -26,7 +26,7 @@ static DEFINE_IDR(memstick_host_idr);
static DEFINE_SPINLOCK(memstick_host_lock);
static int memstick_dev_match(struct memstick_dev *card,
- struct memstick_device_id *id)
+ const struct memstick_device_id *id)
{
if (id->match_flags & MEMSTICK_MATCH_ALL) {
if ((id->type == card->id.type)
@@ -44,7 +44,7 @@ static int memstick_bus_match(struct device *dev, const struct device_driver *dr
dev);
const struct memstick_driver *ms_drv = container_of_const(drv, struct memstick_driver,
driver);
- struct memstick_device_id *ids = ms_drv->id_table;
+ const struct memstick_device_id *ids = ms_drv->id_table;
if (ids) {
while (ids->match_flags) {
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
index 47a314a4eb6f..20a2466bec23 100644
--- a/drivers/memstick/core/ms_block.c
+++ b/drivers/memstick/core/ms_block.c
@@ -996,7 +996,7 @@ static int msb_verify_block(struct msb_data *msb, u16 pba,
return 0;
}
-/* Writes exectly one block + oob */
+/* Writes exactly one block + oob */
static int msb_write_block(struct msb_data *msb,
u16 pba, u32 lba, struct scatterlist *sg, int offset)
{
@@ -1684,7 +1684,7 @@ static int msb_cache_read(struct msb_data *msb, int lba,
*/
static const struct chs_entry chs_table[] = {
-/* size sectors cylynders heads */
+/* size sectors cylinders heads */
{ 4, 16, 247, 2 },
{ 8, 16, 495, 2 },
{ 16, 16, 495, 4 },
@@ -1729,7 +1729,7 @@ static int msb_init_card(struct memstick_dev *card)
boot_block = &msb->boot_page[0];
- /* Save intersting attributes from boot page */
+ /* Save interesting attributes from boot page */
msb->block_count = boot_block->attr.number_of_blocks;
msb->page_size = boot_block->attr.page_size;
@@ -2279,7 +2279,7 @@ out:
#endif /* CONFIG_PM */
-static struct memstick_device_id msb_id_tbl[] = {
+static const struct memstick_device_id msb_id_tbl[] = {
{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_LEGACY, MEMSTICK_CATEGORY_STORAGE,
MEMSTICK_CLASS_FLASH},
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 49accfdc89d6..13b317c56069 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -1349,7 +1349,7 @@ out_unlock:
#endif /* CONFIG_PM */
-static struct memstick_device_id mspro_block_id_tbl[] = {
+static const struct memstick_device_id mspro_block_id_tbl[] = {
{MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO,
MEMSTICK_CLASS_DUO},
{}
diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c
index 461f5ffd02bc..544a31ff46e5 100644
--- a/drivers/memstick/host/r592.c
+++ b/drivers/memstick/host/r592.c
@@ -675,7 +675,7 @@ static irqreturn_t r592_irq(int irq, void *data)
return ret;
}
-/* External inteface: set settings */
+/* External interface: set settings */
static int r592_set_param(struct memstick_host *host,
enum memstick_param param, int value)
{
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index a1ec7e84d6fe..40b34f670065 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -51,10 +51,7 @@
#define LINUX_MPTLAN_H_INCLUDED
/*****************************************************************************/
-#if !defined(__GENKSYMS__)
#include <linux/module.h>
-#endif
-
#include <linux/netdevice.h>
#include <linux/errno.h>
// #include <linux/etherdevice.h>
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index a0bcb0864ecd..a798e26c6402 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -4231,10 +4231,8 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
static void
mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
{
- int rc;
-
sdev->no_uld_attach = data ? 1 : 0;
- rc = scsi_device_reprobe(sdev);
+ WARN_ON(scsi_device_reprobe(sdev));
}
static void
diff --git a/drivers/mfd/88pm886.c b/drivers/mfd/88pm886.c
index dbe9efc027d2..891fdce5d8c1 100644
--- a/drivers/mfd/88pm886.c
+++ b/drivers/mfd/88pm886.c
@@ -37,6 +37,7 @@ static struct resource pm886_onkey_resources[] = {
static struct mfd_cell pm886_devs[] = {
MFD_CELL_RES("88pm886-onkey", pm886_onkey_resources),
MFD_CELL_NAME("88pm886-regulator"),
+ MFD_CELL_NAME("88pm886-rtc"),
};
static int pm886_power_off_handler(struct sys_off_data *sys_off_data)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f9325bcce1b9..ae23b317a64e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -25,7 +25,7 @@ config MFD_ADP5585
select MFD_CORE
select REGMAP_I2C
depends on I2C
- depends on OF || COMPILE_TEST
+ depends on OF
help
Say yes here to add support for the Analog Devices ADP5585 GPIO
expander, PWM and keypad controller. This includes the I2C driver and
@@ -236,6 +236,18 @@ config MFD_AXP20X_RSB
components like regulators or the PEK (Power Enable Key) under the
corresponding menus.
+config MFD_CGBC
+ tristate "Congatec Board Controller"
+ select MFD_CORE
+ depends on X86
+ help
+ This is the core driver of the Board Controller found on some Congatec
+ SMARC modules. The Board Controller provides functions like watchdog,
+ I2C busses, and GPIO controller.
+
+ To compile this driver as a module, choose M here: the module will be
+ called cgbc-core.
+
config MFD_CROS_EC_DEV
tristate "ChromeOS Embedded Controller multifunction device"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2a9f91e81af8..e057d6d6faef 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
+obj-$(CONFIG_MFD_CGBC) += cgbc-core.o
obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o
obj-$(CONFIG_MFD_CS42L43) += cs42l43.o
obj-$(CONFIG_MFD_CS42L43_I2C) += cs42l43-i2c.o
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index 8f3ebe651eea..b6b44e2e3198 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -159,7 +159,7 @@ static struct platform_driver ab8500_sysctrl_driver = {
.of_match_table = ab8500_sysctrl_match,
},
.probe = ab8500_sysctrl_probe,
- .remove_new = ab8500_sysctrl_remove,
+ .remove = ab8500_sysctrl_remove,
};
static int __init ab8500_sysctrl_init(void)
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
index b52f7ffdad35..d5df5466eaf5 100644
--- a/drivers/mfd/atmel-flexcom.c
+++ b/drivers/mfd/atmel-flexcom.c
@@ -95,7 +95,7 @@ static int __maybe_unused atmel_flexcom_resume_noirq(struct device *dev)
if (err)
return err;
- val = FLEX_MR_OPMODE(ddata->opmode),
+ val = FLEX_MR_OPMODE(ddata->opmode);
writel(val, ddata->base + FLEX_MR);
clk_disable_unprepare(ddata->clk);
diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c
index e560066e5885..4628ca14e766 100644
--- a/drivers/mfd/atmel-smc.c
+++ b/drivers/mfd/atmel-smc.c
@@ -255,8 +255,8 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply);
/**
* atmel_hsmc_cs_conf_apply - apply an SMC CS conf
* @regmap: the HSMC regmap
- * @cs: the CS id
* @layout: the layout of registers
+ * @cs: the CS id
* @conf: the SMC CS conf to apply
*
* Applies an SMC CS configuration.
@@ -296,8 +296,8 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_get);
/**
* atmel_hsmc_cs_conf_get - retrieve the current SMC CS conf
* @regmap: the HSMC regmap
- * @cs: the CS id
* @layout: the layout of registers
+ * @cs: the CS id
* @conf: the SMC CS conf object to store the current conf
*
* Retrieve the SMC CS configuration.
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
index 791a0b4cb64b..5c93136f977e 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
{ .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
{ .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID },
+ { .compatible = "x-powers,axp323", .data = (void *)AXP323_ID },
{ .compatible = "x-powers,axp717", .data = (void *)AXP717_ID },
{ .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
{ .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 4051551757f2..251465a656d0 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -34,20 +34,21 @@
#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4)
static const char * const axp20x_model_names[] = {
- "AXP152",
- "AXP192",
- "AXP202",
- "AXP209",
- "AXP221",
- "AXP223",
- "AXP288",
- "AXP313a",
- "AXP717",
- "AXP803",
- "AXP806",
- "AXP809",
- "AXP813",
- "AXP15060",
+ [AXP152_ID] = "AXP152",
+ [AXP192_ID] = "AXP192",
+ [AXP202_ID] = "AXP202",
+ [AXP209_ID] = "AXP209",
+ [AXP221_ID] = "AXP221",
+ [AXP223_ID] = "AXP223",
+ [AXP288_ID] = "AXP288",
+ [AXP313A_ID] = "AXP313a",
+ [AXP323_ID] = "AXP323",
+ [AXP717_ID] = "AXP717",
+ [AXP803_ID] = "AXP803",
+ [AXP806_ID] = "AXP806",
+ [AXP809_ID] = "AXP809",
+ [AXP813_ID] = "AXP813",
+ [AXP15060_ID] = "AXP15060",
};
static const struct regmap_range axp152_writeable_ranges[] = {
@@ -193,6 +194,10 @@ static const struct regmap_range axp313a_writeable_ranges[] = {
regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE),
};
+static const struct regmap_range axp323_writeable_ranges[] = {
+ regmap_reg_range(AXP313A_ON_INDICATE, AXP323_DCDC_MODE_CTRL2),
+};
+
static const struct regmap_range axp313a_volatile_ranges[] = {
regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL),
regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE),
@@ -203,6 +208,11 @@ static const struct regmap_access_table axp313a_writeable_table = {
.n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges),
};
+static const struct regmap_access_table axp323_writeable_table = {
+ .yes_ranges = axp323_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp323_writeable_ranges),
+};
+
static const struct regmap_access_table axp313a_volatile_table = {
.yes_ranges = axp313a_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
@@ -433,6 +443,15 @@ static const struct regmap_config axp313a_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
+static const struct regmap_config axp323_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp323_writeable_table,
+ .volatile_table = &axp313a_volatile_table,
+ .max_register = AXP323_DCDC_MODE_CTRL2,
+ .cache_type = REGCACHE_MAPLE,
+};
+
static const struct regmap_config axp717_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -1221,6 +1240,7 @@ static int axp20x_power_off(struct sys_off_data *data)
unsigned int shutdown_reg;
switch (axp20x->variant) {
+ case AXP323_ID:
case AXP313A_ID:
shutdown_reg = AXP313A_SHUTDOWN_CTRL;
break;
@@ -1289,6 +1309,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_cfg = &axp313a_regmap_config;
axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
break;
+ case AXP323_ID:
+ axp20x->nr_cells = ARRAY_SIZE(axp313a_cells);
+ axp20x->cells = axp313a_cells;
+ axp20x->regmap_cfg = &axp323_regmap_config;
+ axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
+ break;
case AXP717_ID:
axp20x->nr_cells = ARRAY_SIZE(axp717_cells);
axp20x->cells = axp717_cells;
@@ -1345,7 +1371,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
break;
default:
- dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
+ dev_err(dev, "unsupported AXP20X ID %u\n", axp20x->variant);
return -EINVAL;
}
@@ -1419,7 +1445,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
}
}
- ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
+ ret = mfd_add_devices(axp20x->dev, PLATFORM_DEVID_AUTO, axp20x->cells,
axp20x->nr_cells, NULL, 0, NULL);
if (ret) {
diff --git a/drivers/mfd/cgbc-core.c b/drivers/mfd/cgbc-core.c
new file mode 100644
index 000000000000..85283c8dde25
--- /dev/null
+++ b/drivers/mfd/cgbc-core.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Congatec Board Controller core driver.
+ *
+ * The x86 Congatec modules have an embedded micro controller named Board
+ * Controller. This Board Controller has a Watchdog timer, some GPIOs, and two
+ * I2C busses.
+ *
+ * Copyright (C) 2024 Bootlin
+ *
+ * Author: Thomas Richard <thomas.richard@bootlin.com>
+ */
+
+#include <linux/dmi.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/cgbc.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+
+#define CGBC_IO_SESSION_BASE 0x0E20
+#define CGBC_IO_SESSION_END 0x0E30
+#define CGBC_IO_CMD_BASE 0x0E00
+#define CGBC_IO_CMD_END 0x0E10
+
+#define CGBC_MASK_STATUS (BIT(6) | BIT(7))
+#define CGBC_MASK_DATA_COUNT 0x1F
+#define CGBC_MASK_ERROR_CODE 0x1F
+
+#define CGBC_STATUS_DATA_READY 0x00
+#define CGBC_STATUS_CMD_READY BIT(6)
+#define CGBC_STATUS_ERROR (BIT(6) | BIT(7))
+
+#define CGBC_SESSION_CMD 0x00
+#define CGBC_SESSION_CMD_IDLE 0x00
+#define CGBC_SESSION_CMD_REQUEST 0x01
+#define CGBC_SESSION_DATA 0x01
+#define CGBC_SESSION_STATUS 0x02
+#define CGBC_SESSION_STATUS_FREE 0x03
+#define CGBC_SESSION_ACCESS 0x04
+#define CGBC_SESSION_ACCESS_GAINED 0x00
+
+#define CGBC_SESSION_VALID_MIN 0x02
+#define CGBC_SESSION_VALID_MAX 0xFE
+
+#define CGBC_CMD_STROBE 0x00
+#define CGBC_CMD_INDEX 0x02
+#define CGBC_CMD_INDEX_CBM_MAN8 0x00
+#define CGBC_CMD_INDEX_CBM_AUTO32 0x03
+#define CGBC_CMD_DATA 0x04
+#define CGBC_CMD_ACCESS 0x0C
+
+#define CGBC_CMD_GET_FW_REV 0x21
+
+static struct platform_device *cgbc_pdev;
+
+/* Wait the Board Controller is ready to receive some session commands */
+static int cgbc_wait_device(struct cgbc_device_data *cgbc)
+{
+ u16 status;
+ int ret;
+
+ ret = readx_poll_timeout(ioread16, cgbc->io_session + CGBC_SESSION_STATUS, status,
+ status == CGBC_SESSION_STATUS_FREE, 0, 500000);
+
+ if (ret || ioread32(cgbc->io_session + CGBC_SESSION_ACCESS))
+ ret = -ENODEV;
+
+ return ret;
+}
+
+static int cgbc_session_command(struct cgbc_device_data *cgbc, u8 cmd)
+{
+ int ret;
+ u8 val;
+
+ ret = readx_poll_timeout(ioread8, cgbc->io_session + CGBC_SESSION_CMD, val,
+ val == CGBC_SESSION_CMD_IDLE, 0, 100000);
+ if (ret)
+ return ret;
+
+ iowrite8(cmd, cgbc->io_session + CGBC_SESSION_CMD);
+
+ ret = readx_poll_timeout(ioread8, cgbc->io_session + CGBC_SESSION_CMD, val,
+ val == CGBC_SESSION_CMD_IDLE, 0, 100000);
+ if (ret)
+ return ret;
+
+ ret = (int)ioread8(cgbc->io_session + CGBC_SESSION_DATA);
+
+ iowrite8(CGBC_SESSION_STATUS_FREE, cgbc->io_session + CGBC_SESSION_STATUS);
+
+ return ret;
+}
+
+static int cgbc_session_request(struct cgbc_device_data *cgbc)
+{
+ unsigned int ret;
+
+ ret = cgbc_wait_device(cgbc);
+
+ if (ret)
+ return dev_err_probe(cgbc->dev, ret, "device not found or not ready\n");
+
+ cgbc->session = cgbc_session_command(cgbc, CGBC_SESSION_CMD_REQUEST);
+
+ /* The Board Controller sent us a wrong session handle, we cannot communicate with it */
+ if (cgbc->session < CGBC_SESSION_VALID_MIN || cgbc->session > CGBC_SESSION_VALID_MAX)
+ return dev_err_probe(cgbc->dev, -ECONNREFUSED,
+ "failed to get a valid session handle\n");
+
+ return 0;
+}
+
+static void cgbc_session_release(struct cgbc_device_data *cgbc)
+{
+ if (cgbc_session_command(cgbc, cgbc->session) != cgbc->session)
+ dev_warn(cgbc->dev, "failed to release session\n");
+}
+
+static bool cgbc_command_lock(struct cgbc_device_data *cgbc)
+{
+ iowrite8(cgbc->session, cgbc->io_cmd + CGBC_CMD_ACCESS);
+
+ return ioread8(cgbc->io_cmd + CGBC_CMD_ACCESS) == cgbc->session;
+}
+
+static void cgbc_command_unlock(struct cgbc_device_data *cgbc)
+{
+ iowrite8(cgbc->session, cgbc->io_cmd + CGBC_CMD_ACCESS);
+}
+
+int cgbc_command(struct cgbc_device_data *cgbc, void *cmd, unsigned int cmd_size, void *data,
+ unsigned int data_size, u8 *status)
+{
+ u8 checksum = 0, data_checksum = 0, istatus = 0, val;
+ u8 *_data = (u8 *)data;
+ u8 *_cmd = (u8 *)cmd;
+ int mode_change = -1;
+ bool lock;
+ int ret, i;
+
+ mutex_lock(&cgbc->lock);
+
+ /* Request access */
+ ret = readx_poll_timeout(cgbc_command_lock, cgbc, lock, lock, 0, 100000);
+ if (ret)
+ goto out;
+
+ /* Wait board controller is ready */
+ ret = readx_poll_timeout(ioread8, cgbc->io_cmd + CGBC_CMD_STROBE, val,
+ val == CGBC_CMD_STROBE, 0, 100000);
+ if (ret)
+ goto release;
+
+ /* Write command packet */
+ if (cmd_size <= 2) {
+ iowrite8(CGBC_CMD_INDEX_CBM_MAN8, cgbc->io_cmd + CGBC_CMD_INDEX);
+ } else {
+ iowrite8(CGBC_CMD_INDEX_CBM_AUTO32, cgbc->io_cmd + CGBC_CMD_INDEX);
+ if ((cmd_size % 4) != 0x03)
+ mode_change = (cmd_size & 0xFFFC) - 1;
+ }
+
+ for (i = 0; i < cmd_size; i++) {
+ iowrite8(_cmd[i], cgbc->io_cmd + CGBC_CMD_DATA + (i % 4));
+ checksum ^= _cmd[i];
+ if (mode_change == i)
+ iowrite8((i + 1) | CGBC_CMD_INDEX_CBM_MAN8, cgbc->io_cmd + CGBC_CMD_INDEX);
+ }
+
+ /* Append checksum byte */
+ iowrite8(checksum, cgbc->io_cmd + CGBC_CMD_DATA + (i % 4));
+
+ /* Perform command strobe */
+ iowrite8(cgbc->session, cgbc->io_cmd + CGBC_CMD_STROBE);
+
+ /* Rewind cmd buffer index */
+ iowrite8(CGBC_CMD_INDEX_CBM_AUTO32, cgbc->io_cmd + CGBC_CMD_INDEX);
+
+ /* Wait command completion */
+ ret = read_poll_timeout(ioread8, val, val == CGBC_CMD_STROBE, 0, 100000, false,
+ cgbc->io_cmd + CGBC_CMD_STROBE);
+ if (ret)
+ goto release;
+
+ istatus = ioread8(cgbc->io_cmd + CGBC_CMD_DATA);
+ checksum = istatus;
+
+ /* Check command status */
+ switch (istatus & CGBC_MASK_STATUS) {
+ case CGBC_STATUS_DATA_READY:
+ if (istatus > data_size)
+ istatus = data_size;
+ for (i = 0; i < istatus; i++) {
+ _data[i] = ioread8(cgbc->io_cmd + CGBC_CMD_DATA + ((i + 1) % 4));
+ checksum ^= _data[i];
+ }
+ data_checksum = ioread8(cgbc->io_cmd + CGBC_CMD_DATA + ((i + 1) % 4));
+ istatus &= CGBC_MASK_DATA_COUNT;
+ break;
+ case CGBC_STATUS_ERROR:
+ case CGBC_STATUS_CMD_READY:
+ data_checksum = ioread8(cgbc->io_cmd + CGBC_CMD_DATA + 1);
+ if ((istatus & CGBC_MASK_STATUS) == CGBC_STATUS_ERROR)
+ ret = -EIO;
+ istatus = istatus & CGBC_MASK_ERROR_CODE;
+ break;
+ default:
+ data_checksum = ioread8(cgbc->io_cmd + CGBC_CMD_DATA + 1);
+ istatus &= CGBC_MASK_ERROR_CODE;
+ ret = -EIO;
+ break;
+ }
+
+ /* Checksum verification */
+ if (ret == 0 && data_checksum != checksum)
+ ret = -EIO;
+
+release:
+ cgbc_command_unlock(cgbc);
+
+out:
+ mutex_unlock(&cgbc->lock);
+
+ if (status)
+ *status = istatus;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cgbc_command);
+
+static struct mfd_cell cgbc_devs[] = {
+ { .name = "cgbc-wdt" },
+ { .name = "cgbc-gpio" },
+ { .name = "cgbc-i2c", .id = 1 },
+ { .name = "cgbc-i2c", .id = 2 },
+};
+
+static int cgbc_map(struct cgbc_device_data *cgbc)
+{
+ struct device *dev = cgbc->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *ioport;
+
+ ioport = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!ioport)
+ return -EINVAL;
+
+ cgbc->io_session = devm_ioport_map(dev, ioport->start, resource_size(ioport));
+ if (!cgbc->io_session)
+ return -ENOMEM;
+
+ ioport = platform_get_resource(pdev, IORESOURCE_IO, 1);
+ if (!ioport)
+ return -EINVAL;
+
+ cgbc->io_cmd = devm_ioport_map(dev, ioport->start, resource_size(ioport));
+ if (!cgbc->io_cmd)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static const struct resource cgbc_resources[] = {
+ {
+ .start = CGBC_IO_SESSION_BASE,
+ .end = CGBC_IO_SESSION_END,
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = CGBC_IO_CMD_BASE,
+ .end = CGBC_IO_CMD_END,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static ssize_t cgbc_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cgbc_device_data *cgbc = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "CGBCP%c%c%c\n", cgbc->version.feature, cgbc->version.major,
+ cgbc->version.minor);
+}
+
+static DEVICE_ATTR_RO(cgbc_version);
+
+static struct attribute *cgbc_attrs[] = {
+ &dev_attr_cgbc_version.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(cgbc);
+
+static int cgbc_get_version(struct cgbc_device_data *cgbc)
+{
+ u8 cmd = CGBC_CMD_GET_FW_REV;
+ u8 data[4];
+ int ret;
+
+ ret = cgbc_command(cgbc, &cmd, 1, &data, sizeof(data), NULL);
+ if (ret)
+ return ret;
+
+ cgbc->version.feature = data[0];
+ cgbc->version.major = data[1];
+ cgbc->version.minor = data[2];
+
+ return 0;
+}
+
+static int cgbc_init_device(struct cgbc_device_data *cgbc)
+{
+ int ret;
+
+ ret = cgbc_session_request(cgbc);
+ if (ret)
+ return ret;
+
+ ret = cgbc_get_version(cgbc);
+ if (ret)
+ goto release_session;
+
+ ret = mfd_add_devices(cgbc->dev, -1, cgbc_devs, ARRAY_SIZE(cgbc_devs),
+ NULL, 0, NULL);
+ if (ret)
+ goto release_session;
+
+ return 0;
+
+release_session:
+ cgbc_session_release(cgbc);
+ return ret;
+}
+
+static int cgbc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct cgbc_device_data *cgbc;
+ int ret;
+
+ cgbc = devm_kzalloc(dev, sizeof(*cgbc), GFP_KERNEL);
+ if (!cgbc)
+ return -ENOMEM;
+
+ cgbc->dev = dev;
+
+ ret = cgbc_map(cgbc);
+ if (ret)
+ return ret;
+
+ mutex_init(&cgbc->lock);
+
+ platform_set_drvdata(pdev, cgbc);
+
+ return cgbc_init_device(cgbc);
+}
+
+static void cgbc_remove(struct platform_device *pdev)
+{
+ struct cgbc_device_data *cgbc = platform_get_drvdata(pdev);
+
+ cgbc_session_release(cgbc);
+
+ mfd_remove_devices(&pdev->dev);
+}
+
+static struct platform_driver cgbc_driver = {
+ .driver = {
+ .name = "cgbc",
+ .dev_groups = cgbc_groups,
+ },
+ .probe = cgbc_probe,
+ .remove = cgbc_remove,
+};
+
+static const struct dmi_system_id cgbc_dmi_table[] __initconst = {
+ {
+ .ident = "SA7",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "congatec"),
+ DMI_MATCH(DMI_BOARD_NAME, "conga-SA7"),
+ },
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(dmi, cgbc_dmi_table);
+
+static int __init cgbc_init(void)
+{
+ const struct dmi_system_id *id;
+ int ret = -ENODEV;
+
+ id = dmi_first_match(cgbc_dmi_table);
+ if (IS_ERR_OR_NULL(id))
+ return ret;
+
+ cgbc_pdev = platform_device_register_simple("cgbc", PLATFORM_DEVID_NONE, cgbc_resources,
+ ARRAY_SIZE(cgbc_resources));
+ if (IS_ERR(cgbc_pdev))
+ return PTR_ERR(cgbc_pdev);
+
+ return platform_driver_register(&cgbc_driver);
+}
+
+static void __exit cgbc_exit(void)
+{
+ platform_device_unregister(cgbc_pdev);
+ platform_driver_unregister(&cgbc_driver);
+}
+
+module_init(cgbc_init);
+module_exit(cgbc_exit);
+
+MODULE_DESCRIPTION("Congatec Board Controller Core Driver");
+MODULE_AUTHOR("Thomas Richard <thomas.richard@bootlin.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cgbc-core");
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index f3dc812b359f..9f84a52b48d6 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -108,6 +108,10 @@ static const struct mfd_cell cros_ec_keyboard_leds_cells[] = {
{ .name = "cros-keyboard-leds", },
};
+static const struct mfd_cell cros_ec_ucsi_cells[] = {
+ { .name = "cros_ec_ucsi", },
+};
+
static const struct cros_feature_to_cells cros_subdevices[] = {
{
.id = EC_FEATURE_CEC,
@@ -125,9 +129,9 @@ static const struct cros_feature_to_cells cros_subdevices[] = {
.num_cells = ARRAY_SIZE(cros_ec_rtc_cells),
},
{
- .id = EC_FEATURE_USB_PD,
- .mfd_cells = cros_usbpd_charger_cells,
- .num_cells = ARRAY_SIZE(cros_usbpd_charger_cells),
+ .id = EC_FEATURE_UCSI_PPM,
+ .mfd_cells = cros_ec_ucsi_cells,
+ .num_cells = ARRAY_SIZE(cros_ec_ucsi_cells),
},
{
.id = EC_FEATURE_HANG_DETECT,
@@ -253,6 +257,21 @@ static int ec_device_probe(struct platform_device *pdev)
}
/*
+ * UCSI provides power supply information so we don't need to separately
+ * load the cros_usbpd_charger driver.
+ */
+ if (cros_ec_check_features(ec, EC_FEATURE_USB_PD) &&
+ !cros_ec_check_features(ec, EC_FEATURE_UCSI_PPM)) {
+ retval = mfd_add_hotplug_devices(ec->dev,
+ cros_usbpd_charger_cells,
+ ARRAY_SIZE(cros_usbpd_charger_cells));
+
+ if (retval)
+ dev_warn(ec->dev, "failed to add usbpd-charger: %d\n",
+ retval);
+ }
+
+ /*
* Lightbar is a special case. Newer devices support autodetection,
* but older ones do not.
*/
@@ -346,7 +365,7 @@ static struct platform_driver cros_ec_dev_driver = {
},
.id_table = cros_ec_id,
.probe = ec_device_probe,
- .remove_new = ec_device_remove,
+ .remove = ec_device_remove,
};
static int __init cros_ec_dev_init(void)
diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c
index ae8fd37afb75..e5f17fc430e4 100644
--- a/drivers/mfd/cs42l43.c
+++ b/drivers/mfd/cs42l43.c
@@ -967,7 +967,6 @@ static void cs42l43_boot_work(struct work_struct *work)
err:
pm_runtime_put_sync(cs42l43->dev);
- cs42l43_dev_remove(cs42l43);
}
static int cs42l43_power_up(struct cs42l43 *cs42l43)
@@ -1101,6 +1100,8 @@ EXPORT_SYMBOL_NS_GPL(cs42l43_dev_probe, MFD_CS42L43);
void cs42l43_dev_remove(struct cs42l43 *cs42l43)
{
+ cancel_work_sync(&cs42l43->boot_work);
+
cs42l43_power_down(cs42l43);
}
EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43);
@@ -1108,16 +1109,39 @@ EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43);
static int cs42l43_suspend(struct device *dev)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+ static const struct reg_sequence mask_all[] = {
+ { CS42L43_DECIM_MASK, 0xFFFFFFFF, },
+ { CS42L43_EQ_MIX_MASK, 0xFFFFFFFF, },
+ { CS42L43_ASP_MASK, 0xFFFFFFFF, },
+ { CS42L43_PLL_MASK, 0xFFFFFFFF, },
+ { CS42L43_SOFT_MASK, 0xFFFFFFFF, },
+ { CS42L43_SWIRE_MASK, 0xFFFFFFFF, },
+ { CS42L43_MSM_MASK, 0xFFFFFFFF, },
+ { CS42L43_ACC_DET_MASK, 0xFFFFFFFF, },
+ { CS42L43_I2C_TGT_MASK, 0xFFFFFFFF, },
+ { CS42L43_SPI_MSTR_MASK, 0xFFFFFFFF, },
+ { CS42L43_SW_TO_SPI_BRIDGE_MASK, 0xFFFFFFFF, },
+ { CS42L43_OTP_MASK, 0xFFFFFFFF, },
+ { CS42L43_CLASS_D_AMP_MASK, 0xFFFFFFFF, },
+ { CS42L43_GPIO_INT_MASK, 0xFFFFFFFF, },
+ { CS42L43_ASRC_MASK, 0xFFFFFFFF, },
+ { CS42L43_HPOUT_MASK, 0xFFFFFFFF, },
+ };
int ret;
- /*
- * Don't care about being resumed here, but the driver does want
- * force_resume to always trigger an actual resume, so that register
- * state for the MCU/GPIOs is returned as soon as possible after system
- * resume. force_resume will resume if the reference count is resumed on
- * suspend hence the get_noresume.
- */
- pm_runtime_get_noresume(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret) {
+ dev_err(cs42l43->dev, "Failed to resume for suspend: %d\n", ret);
+ return ret;
+ }
+
+ /* The IRQs will be re-enabled on resume by the cache sync */
+ ret = regmap_multi_reg_write_bypassed(cs42l43->regmap,
+ mask_all, ARRAY_SIZE(mask_all));
+ if (ret) {
+ dev_err(cs42l43->dev, "Failed to mask IRQs: %d\n", ret);
+ return ret;
+ }
ret = pm_runtime_force_suspend(dev);
if (ret) {
@@ -1132,6 +1156,26 @@ static int cs42l43_suspend(struct device *dev)
if (ret)
return ret;
+ disable_irq(cs42l43->irq);
+
+ return 0;
+}
+
+static int cs42l43_suspend_noirq(struct device *dev)
+{
+ struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+
+ enable_irq(cs42l43->irq);
+
+ return 0;
+}
+
+static int cs42l43_resume_noirq(struct device *dev)
+{
+ struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
+
+ disable_irq(cs42l43->irq);
+
return 0;
}
@@ -1144,6 +1188,8 @@ static int cs42l43_resume(struct device *dev)
if (ret)
return ret;
+ enable_irq(cs42l43->irq);
+
ret = pm_runtime_force_resume(dev);
if (ret) {
dev_err(cs42l43->dev, "Failed to force resume: %d\n", ret);
@@ -1211,6 +1257,7 @@ err:
EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = {
SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume)
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend_noirq, cs42l43_resume_noirq)
RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL)
};
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
index be5f2b34e18a..80fc5c0cac2f 100644
--- a/drivers/mfd/da9052-spi.c
+++ b/drivers/mfd/da9052-spi.c
@@ -37,7 +37,7 @@ static int da9052_spi_probe(struct spi_device *spi)
spi_set_drvdata(spi, da9052);
config = da9052_regmap_config;
- config.read_flag_mask = 1;
+ config.write_flag_mask = 1;
config.reg_bits = 7;
config.pad_bits = 1;
config.val_bits = 8;
diff --git a/drivers/mfd/exynos-lpass.c b/drivers/mfd/exynos-lpass.c
index e58990c85ed8..6a585173230b 100644
--- a/drivers/mfd/exynos-lpass.c
+++ b/drivers/mfd/exynos-lpass.c
@@ -179,13 +179,13 @@ static const struct of_device_id exynos_lpass_of_match[] = {
MODULE_DEVICE_TABLE(of, exynos_lpass_of_match);
static struct platform_driver exynos_lpass_driver = {
- .driver = {
+ .driver = {
.name = "exynos-lpass",
.pm = &lpass_pm_ops,
.of_match_table = exynos_lpass_of_match,
},
.probe = exynos_lpass_probe,
- .remove_new = exynos_lpass_remove,
+ .remove = exynos_lpass_remove,
};
module_platform_driver(exynos_lpass_driver);
diff --git a/drivers/mfd/fsl-imx25-tsadc.c b/drivers/mfd/fsl-imx25-tsadc.c
index 2e4ab2404154..6fe388da6fb6 100644
--- a/drivers/mfd/fsl-imx25-tsadc.c
+++ b/drivers/mfd/fsl-imx25-tsadc.c
@@ -211,7 +211,7 @@ static struct platform_driver mx25_tsadc_driver = {
.of_match_table = mx25_tsadc_ids,
},
.probe = mx25_tsadc_probe,
- .remove_new = mx25_tsadc_remove,
+ .remove = mx25_tsadc_remove,
};
module_platform_driver(mx25_tsadc_driver);
diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c
index 5f61909c85e9..3b4ffcbbee20 100644
--- a/drivers/mfd/hi655x-pmic.c
+++ b/drivers/mfd/hi655x-pmic.c
@@ -159,12 +159,12 @@ static const struct of_device_id hi655x_pmic_match[] = {
MODULE_DEVICE_TABLE(of, hi655x_pmic_match);
static struct platform_driver hi655x_pmic_driver = {
- .driver = {
- .name = "hi655x-pmic",
+ .driver = {
+ .name = "hi655x-pmic",
.of_match_table = hi655x_pmic_match,
},
- .probe = hi655x_pmic_probe,
- .remove_new = hi655x_pmic_remove,
+ .probe = hi655x_pmic_probe,
+ .remove = hi655x_pmic_remove,
};
module_platform_driver(hi655x_pmic_driver);
diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c
index 2a83f8678f1d..557061856e58 100644
--- a/drivers/mfd/intel-lpss-acpi.c
+++ b/drivers/mfd/intel-lpss-acpi.c
@@ -208,7 +208,7 @@ static void intel_lpss_acpi_remove(struct platform_device *pdev)
static struct platform_driver intel_lpss_acpi_driver = {
.probe = intel_lpss_acpi_probe,
- .remove_new = intel_lpss_acpi_remove,
+ .remove = intel_lpss_acpi_remove,
.driver = {
.name = "intel-lpss",
.acpi_match_table = intel_lpss_acpi_ids,
diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c
index ccd76800d8e4..9d89171d83f9 100644
--- a/drivers/mfd/intel_soc_pmic_bxtwc.c
+++ b/drivers/mfd/intel_soc_pmic_bxtwc.c
@@ -6,16 +6,27 @@
*/
#include <linux/acpi.h>
+#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/gfp_types.h>
#include <linux/interrupt.h>
-#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/kstrtox.h>
#include <linux/mfd/core.h>
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/mfd/intel_soc_pmic_bxtwc.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_data/x86/intel_scu_ipc.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
/* PMIC device registers */
#define REG_ADDR_MASK GENMASK(15, 8)
@@ -148,6 +159,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip = {
static const struct regmap_irq_chip bxtwc_regmap_irq_chip_pwrbtn = {
.name = "bxtwc_irq_chip_pwrbtn",
+ .domain_suffix = "PWRBTN",
.status_base = BXTWC_PWRBTNIRQ,
.mask_base = BXTWC_MPWRBTNIRQ,
.irqs = bxtwc_regmap_irqs_pwrbtn,
@@ -157,6 +169,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_pwrbtn = {
static const struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = {
.name = "bxtwc_irq_chip_tmu",
+ .domain_suffix = "TMU",
.status_base = BXTWC_TMUIRQ,
.mask_base = BXTWC_MTMUIRQ,
.irqs = bxtwc_regmap_irqs_tmu,
@@ -166,6 +179,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = {
static const struct regmap_irq_chip bxtwc_regmap_irq_chip_bcu = {
.name = "bxtwc_irq_chip_bcu",
+ .domain_suffix = "BCU",
.status_base = BXTWC_BCUIRQ,
.mask_base = BXTWC_MBCUIRQ,
.irqs = bxtwc_regmap_irqs_bcu,
@@ -175,6 +189,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_bcu = {
static const struct regmap_irq_chip bxtwc_regmap_irq_chip_adc = {
.name = "bxtwc_irq_chip_adc",
+ .domain_suffix = "ADC",
.status_base = BXTWC_ADCIRQ,
.mask_base = BXTWC_MADCIRQ,
.irqs = bxtwc_regmap_irqs_adc,
@@ -184,6 +199,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_adc = {
static const struct regmap_irq_chip bxtwc_regmap_irq_chip_chgr = {
.name = "bxtwc_irq_chip_chgr",
+ .domain_suffix = "CHGR",
.status_base = BXTWC_CHGR0IRQ,
.mask_base = BXTWC_MCHGR0IRQ,
.irqs = bxtwc_regmap_irqs_chgr,
@@ -193,6 +209,7 @@ static const struct regmap_irq_chip bxtwc_regmap_irq_chip_chgr = {
static const struct regmap_irq_chip bxtwc_regmap_irq_chip_crit = {
.name = "bxtwc_irq_chip_crit",
+ .domain_suffix = "CRIT",
.status_base = BXTWC_CRITIRQ,
.mask_base = BXTWC_MCRITIRQ,
.irqs = bxtwc_regmap_irqs_crit,
@@ -231,43 +248,54 @@ static const struct resource tmu_resources[] = {
static struct mfd_cell bxt_wc_dev[] = {
{
- .name = "bxt_wcove_gpadc",
- .num_resources = ARRAY_SIZE(adc_resources),
- .resources = adc_resources,
- },
- {
.name = "bxt_wcove_thermal",
.num_resources = ARRAY_SIZE(thermal_resources),
.resources = thermal_resources,
},
{
- .name = "bxt_wcove_usbc",
- .num_resources = ARRAY_SIZE(usbc_resources),
- .resources = usbc_resources,
+ .name = "bxt_wcove_gpio",
+ .num_resources = ARRAY_SIZE(gpio_resources),
+ .resources = gpio_resources,
},
{
- .name = "bxt_wcove_ext_charger",
- .num_resources = ARRAY_SIZE(charger_resources),
- .resources = charger_resources,
+ .name = "bxt_wcove_region",
},
+};
+
+static const struct mfd_cell bxt_wc_tmu_dev[] = {
+ {
+ .name = "bxt_wcove_tmu",
+ .num_resources = ARRAY_SIZE(tmu_resources),
+ .resources = tmu_resources,
+ },
+};
+
+static const struct mfd_cell bxt_wc_bcu_dev[] = {
{
.name = "bxt_wcove_bcu",
.num_resources = ARRAY_SIZE(bcu_resources),
.resources = bcu_resources,
},
+};
+
+static const struct mfd_cell bxt_wc_adc_dev[] = {
{
- .name = "bxt_wcove_tmu",
- .num_resources = ARRAY_SIZE(tmu_resources),
- .resources = tmu_resources,
+ .name = "bxt_wcove_gpadc",
+ .num_resources = ARRAY_SIZE(adc_resources),
+ .resources = adc_resources,
},
+};
+static struct mfd_cell bxt_wc_chgr_dev[] = {
{
- .name = "bxt_wcove_gpio",
- .num_resources = ARRAY_SIZE(gpio_resources),
- .resources = gpio_resources,
+ .name = "bxt_wcove_usbc",
+ .num_resources = ARRAY_SIZE(usbc_resources),
+ .resources = usbc_resources,
},
{
- .name = "bxt_wcove_region",
+ .name = "bxt_wcove_ext_charger",
+ .num_resources = ARRAY_SIZE(charger_resources),
+ .resources = charger_resources,
},
};
@@ -347,6 +375,7 @@ static ssize_t addr_store(struct device *dev,
return count;
}
+static DEVICE_ATTR_ADMIN_RW(addr);
static ssize_t val_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -383,23 +412,14 @@ static ssize_t val_store(struct device *dev,
}
return count;
}
-
-static DEVICE_ATTR_ADMIN_RW(addr);
static DEVICE_ATTR_ADMIN_RW(val);
+
static struct attribute *bxtwc_attrs[] = {
&dev_attr_addr.attr,
&dev_attr_val.attr,
NULL
};
-
-static const struct attribute_group bxtwc_group = {
- .attrs = bxtwc_attrs,
-};
-
-static const struct attribute_group *bxtwc_groups[] = {
- &bxtwc_group,
- NULL
-};
+ATTRIBUTE_GROUPS(bxtwc);
static const struct regmap_config bxtwc_regmap_config = {
.reg_bits = 16,
@@ -414,15 +434,39 @@ static int bxtwc_add_chained_irq_chip(struct intel_soc_pmic *pmic,
const struct regmap_irq_chip *chip,
struct regmap_irq_chip_data **data)
{
- int irq;
+ struct device *dev = pmic->dev;
+ int irq, ret;
irq = regmap_irq_get_virq(pdata, pirq);
if (irq < 0)
- return dev_err_probe(pmic->dev, irq, "Failed to get parent vIRQ(%d) for chip %s\n",
+ return dev_err_probe(dev, irq, "Failed to get parent vIRQ(%d) for chip %s\n",
pirq, chip->name);
- return devm_regmap_add_irq_chip(pmic->dev, pmic->regmap, irq, irq_flags,
- 0, chip, data);
+ ret = devm_regmap_add_irq_chip(dev, pmic->regmap, irq, irq_flags, 0, chip, data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name);
+
+ return 0;
+}
+
+static int bxtwc_add_chained_devices(struct intel_soc_pmic *pmic,
+ const struct mfd_cell *cells, int n_devs,
+ struct regmap_irq_chip_data *pdata,
+ int pirq, int irq_flags,
+ const struct regmap_irq_chip *chip,
+ struct regmap_irq_chip_data **data)
+{
+ struct device *dev = pmic->dev;
+ struct irq_domain *domain;
+ int ret;
+
+ ret = bxtwc_add_chained_irq_chip(pmic, pdata, pirq, irq_flags, chip, data);
+ if (ret)
+ return ret;
+
+ domain = regmap_irq_get_domain(*data);
+
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, cells, n_devs, NULL, 0, domain);
}
static int bxtwc_probe(struct platform_device *pdev)
@@ -466,48 +510,49 @@ static int bxtwc_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_tmu_dev, ARRAY_SIZE(bxt_wc_tmu_dev),
+ pmic->irq_chip_data,
+ BXTWC_TMU_LVL1_IRQ,
+ IRQF_ONESHOT,
+ &bxtwc_regmap_irq_chip_tmu,
+ &pmic->irq_chip_data_tmu);
+ if (ret)
+ return ret;
+
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
BXTWC_PWRBTN_LVL1_IRQ,
IRQF_ONESHOT,
&bxtwc_regmap_irq_chip_pwrbtn,
&pmic->irq_chip_data_pwrbtn);
if (ret)
- return dev_err_probe(dev, ret, "Failed to add PWRBTN IRQ chip\n");
-
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
- BXTWC_TMU_LVL1_IRQ,
- IRQF_ONESHOT,
- &bxtwc_regmap_irq_chip_tmu,
- &pmic->irq_chip_data_tmu);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to add TMU IRQ chip\n");
+ return ret;
- /* Add chained IRQ handler for BCU IRQs */
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
- BXTWC_BCU_LVL1_IRQ,
- IRQF_ONESHOT,
- &bxtwc_regmap_irq_chip_bcu,
- &pmic->irq_chip_data_bcu);
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_bcu_dev, ARRAY_SIZE(bxt_wc_bcu_dev),
+ pmic->irq_chip_data,
+ BXTWC_BCU_LVL1_IRQ,
+ IRQF_ONESHOT,
+ &bxtwc_regmap_irq_chip_bcu,
+ &pmic->irq_chip_data_bcu);
if (ret)
- return dev_err_probe(dev, ret, "Failed to add BUC IRQ chip\n");
+ return ret;
- /* Add chained IRQ handler for ADC IRQs */
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
- BXTWC_ADC_LVL1_IRQ,
- IRQF_ONESHOT,
- &bxtwc_regmap_irq_chip_adc,
- &pmic->irq_chip_data_adc);
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_adc_dev, ARRAY_SIZE(bxt_wc_adc_dev),
+ pmic->irq_chip_data,
+ BXTWC_ADC_LVL1_IRQ,
+ IRQF_ONESHOT,
+ &bxtwc_regmap_irq_chip_adc,
+ &pmic->irq_chip_data_adc);
if (ret)
- return dev_err_probe(dev, ret, "Failed to add ADC IRQ chip\n");
+ return ret;
- /* Add chained IRQ handler for CHGR IRQs */
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
- BXTWC_CHGR_LVL1_IRQ,
- IRQF_ONESHOT,
- &bxtwc_regmap_irq_chip_chgr,
- &pmic->irq_chip_data_chgr);
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_chgr_dev, ARRAY_SIZE(bxt_wc_chgr_dev),
+ pmic->irq_chip_data,
+ BXTWC_CHGR_LVL1_IRQ,
+ IRQF_ONESHOT,
+ &bxtwc_regmap_irq_chip_chgr,
+ &pmic->irq_chip_data_chgr);
if (ret)
- return dev_err_probe(dev, ret, "Failed to add CHGR IRQ chip\n");
+ return ret;
/* Add chained IRQ handler for CRIT IRQs */
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
@@ -516,7 +561,7 @@ static int bxtwc_probe(struct platform_device *pdev)
&bxtwc_regmap_irq_chip_crit,
&pmic->irq_chip_data_crit);
if (ret)
- return dev_err_probe(dev, ret, "Failed to add CRIT IRQ chip\n");
+ return ret;
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, bxt_wc_dev, ARRAY_SIZE(bxt_wc_dev),
NULL, 0, NULL);
@@ -571,7 +616,7 @@ static struct platform_driver bxtwc_driver = {
.probe = bxtwc_probe,
.shutdown = bxtwc_shutdown,
.driver = {
- .name = "BXTWC PMIC",
+ .name = "intel_soc_pmic_bxtwc",
.pm = pm_sleep_ptr(&bxtwc_pm_ops),
.acpi_match_table = bxtwc_acpi_ids,
.dev_groups = bxtwc_groups,
diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c
index 2a83f540d4c9..aa71a7d83fcd 100644
--- a/drivers/mfd/intel_soc_pmic_chtwc.c
+++ b/drivers/mfd/intel_soc_pmic_chtwc.c
@@ -267,7 +267,7 @@ static const struct acpi_device_id cht_wc_acpi_ids[] = {
static struct i2c_driver cht_wc_driver = {
.driver = {
- .name = "CHT Whiskey Cove PMIC",
+ .name = "intel_soc_pmic_chtwc",
.pm = pm_sleep_ptr(&cht_wc_pm_ops),
.acpi_match_table = cht_wc_acpi_ids,
},
diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c
index 876d017f74fe..879fbf5cd162 100644
--- a/drivers/mfd/intel_soc_pmic_crc.c
+++ b/drivers/mfd/intel_soc_pmic_crc.c
@@ -259,12 +259,19 @@ static const struct acpi_device_id crystal_cove_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, crystal_cove_acpi_match);
+static const struct i2c_device_id crystal_cove_i2c_match[] = {
+ { "intel_soc_pmic_crc" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, crystal_cove_i2c_match);
+
static struct i2c_driver crystal_cove_i2c_driver = {
.driver = {
- .name = "crystal_cove_i2c",
+ .name = "intel_soc_pmic_crc",
.pm = pm_sleep_ptr(&crystal_cove_pm_ops),
.acpi_match_table = crystal_cove_acpi_match,
},
+ .id_table = crystal_cove_i2c_match,
.probe = crystal_cove_i2c_probe,
.remove = crystal_cove_i2c_remove,
.shutdown = crystal_cove_shutdown,
diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c
index c964ea6539aa..2370b44e2214 100644
--- a/drivers/mfd/ipaq-micro.c
+++ b/drivers/mfd/ipaq-micro.c
@@ -130,6 +130,7 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
default:
dev_err(micro->dev,
"unknown msg %d [%d] %*ph\n", id, len, len, data);
+ break;
}
spin_unlock(&micro->lock);
}
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 8a332852bf97..c5bfb6440a93 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -486,7 +486,7 @@ static struct platform_driver kempld_driver = {
.dev_groups = pld_groups,
},
.probe = kempld_probe,
- .remove_new = kempld_remove,
+ .remove = kempld_remove,
};
static const struct dmi_system_id kempld_dmi_table[] __initconst = {
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 3883e472b739..228c4a2f4c1f 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -286,7 +286,7 @@ static const struct dev_pm_ops mcp_sa11x0_pm_ops = {
static struct platform_driver mcp_sa11x0_driver = {
.probe = mcp_sa11x0_probe,
- .remove_new = mcp_sa11x0_remove,
+ .remove = mcp_sa11x0_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&mcp_sa11x0_pm_ops),
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index c2939e785818..0e5d59ae064a 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -13,12 +13,14 @@
#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mt6323/core.h>
+#include <linux/mfd/mt6328/core.h>
#include <linux/mfd/mt6331/core.h>
#include <linux/mfd/mt6357/core.h>
#include <linux/mfd/mt6358/core.h>
#include <linux/mfd/mt6359/core.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6328/registers.h>
#include <linux/mfd/mt6331/registers.h>
#include <linux/mfd/mt6357/registers.h>
#include <linux/mfd/mt6358/registers.h>
@@ -87,6 +89,13 @@ static const struct resource mt6323_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
};
+static const struct resource mt6328_keys_resources[] = {
+ DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_PWRKEY, "powerkey"),
+ DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_HOMEKEY, "homekey"),
+ DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_PWRKEY_R, "powerkey_r"),
+ DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_HOMEKEY_R, "homekey_r"),
+};
+
static const struct resource mt6357_keys_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY, "powerkey"),
DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY, "homekey"),
@@ -133,6 +142,18 @@ static const struct mfd_cell mt6323_devs[] = {
},
};
+static const struct mfd_cell mt6328_devs[] = {
+ {
+ .name = "mt6328-regulator",
+ .of_compatible = "mediatek,mt6328-regulator"
+ }, {
+ .name = "mtk-pmic-keys",
+ .num_resources = ARRAY_SIZE(mt6328_keys_resources),
+ .resources = mt6328_keys_resources,
+ .of_compatible = "mediatek,mt6328-keys"
+ },
+};
+
static const struct mfd_cell mt6357_devs[] = {
{
.name = "mt6359-auxadc",
@@ -262,6 +283,14 @@ static const struct chip_data mt6323_core = {
.irq_init = mt6397_irq_init,
};
+static const struct chip_data mt6328_core = {
+ .cid_addr = MT6328_HWCID,
+ .cid_shift = 0,
+ .cells = mt6328_devs,
+ .cell_size = ARRAY_SIZE(mt6328_devs),
+ .irq_init = mt6397_irq_init,
+};
+
static const struct chip_data mt6357_core = {
.cid_addr = MT6357_SWCID,
.cid_shift = 8,
@@ -361,6 +390,9 @@ static const struct of_device_id mt6397_of_match[] = {
.compatible = "mediatek,mt6323",
.data = &mt6323_core,
}, {
+ .compatible = "mediatek,mt6328",
+ .data = &mt6328_core,
+ }, {
.compatible = "mediatek,mt6331",
.data = &mt6331_mt6332_core,
}, {
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index 886745b5b607..1310665200ed 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -11,6 +11,8 @@
#include <linux/suspend.h>
#include <linux/mfd/mt6323/core.h>
#include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6328/core.h>
+#include <linux/mfd/mt6328/registers.h>
#include <linux/mfd/mt6331/core.h>
#include <linux/mfd/mt6331/registers.h>
#include <linux/mfd/mt6397/core.h>
@@ -31,6 +33,9 @@ static void mt6397_irq_sync_unlock(struct irq_data *data)
mt6397->irq_masks_cur[0]);
regmap_write(mt6397->regmap, mt6397->int_con[1],
mt6397->irq_masks_cur[1]);
+ if (mt6397->int_con[2])
+ regmap_write(mt6397->regmap, mt6397->int_con[2],
+ mt6397->irq_masks_cur[2]);
mutex_unlock(&mt6397->irqlock);
}
@@ -105,6 +110,8 @@ static irqreturn_t mt6397_irq_thread(int irq, void *data)
mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0);
mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16);
+ if (mt6397->int_status[2])
+ mt6397_irq_handle_reg(mt6397, mt6397->int_status[2], 32);
return IRQ_HANDLED;
}
@@ -138,6 +145,9 @@ static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
chip->int_con[0], chip->wake_mask[0]);
regmap_write(chip->regmap,
chip->int_con[1], chip->wake_mask[1]);
+ if (chip->int_con[2])
+ regmap_write(chip->regmap,
+ chip->int_con[2], chip->wake_mask[2]);
enable_irq_wake(chip->irq);
break;
@@ -146,6 +156,9 @@ static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
chip->int_con[0], chip->irq_masks_cur[0]);
regmap_write(chip->regmap,
chip->int_con[1], chip->irq_masks_cur[1]);
+ if (chip->int_con[2])
+ regmap_write(chip->regmap,
+ chip->int_con[2], chip->irq_masks_cur[2]);
disable_irq_wake(chip->irq);
break;
@@ -169,6 +182,14 @@ int mt6397_irq_init(struct mt6397_chip *chip)
chip->int_status[0] = MT6323_INT_STATUS0;
chip->int_status[1] = MT6323_INT_STATUS1;
break;
+ case MT6328_CHIP_ID:
+ chip->int_con[0] = MT6328_INT_CON0;
+ chip->int_con[1] = MT6328_INT_CON1;
+ chip->int_con[2] = MT6328_INT_CON2;
+ chip->int_status[0] = MT6328_INT_STATUS0;
+ chip->int_status[1] = MT6328_INT_STATUS1;
+ chip->int_status[2] = MT6328_INT_STATUS2;
+ break;
case MT6331_CHIP_ID:
chip->int_con[0] = MT6331_INT_CON0;
chip->int_con[1] = MT6331_INT_CON1;
@@ -191,6 +212,8 @@ int mt6397_irq_init(struct mt6397_chip *chip)
/* Mask all interrupt sources */
regmap_write(chip->regmap, chip->int_con[0], 0x0);
regmap_write(chip->regmap, chip->int_con[1], 0x0);
+ if (chip->int_con[2])
+ regmap_write(chip->regmap, chip->int_con[2], 0x0);
chip->pm_nb.notifier_call = mt6397_irq_pm_notifier;
chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
diff --git a/drivers/mfd/mxs-lradc.c b/drivers/mfd/mxs-lradc.c
index b2ebb5433121..64afc7631790 100644
--- a/drivers/mfd/mxs-lradc.c
+++ b/drivers/mfd/mxs-lradc.c
@@ -243,7 +243,7 @@ static struct platform_driver mxs_lradc_driver = {
.of_match_table = mxs_lradc_dt_ids,
},
.probe = mxs_lradc_probe,
- .remove_new = mxs_lradc_remove,
+ .remove = mxs_lradc_remove,
};
module_platform_driver(mxs_lradc_driver);
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 6de7ba752345..a77b6fc790f2 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -843,7 +843,7 @@ static struct platform_driver usbhs_omap_driver = {
.of_match_table = usbhs_omap_dt_ids,
},
.probe = usbhs_omap_probe,
- .remove_new = usbhs_omap_remove,
+ .remove = usbhs_omap_remove,
};
MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 5f25ac514ff2..0f7fdb99c809 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -301,7 +301,7 @@ static struct platform_driver usbtll_omap_driver = {
.of_match_table = usbtll_omap_dt_ids,
},
.probe = usbtll_omap_probe,
- .remove_new = usbtll_omap_remove,
+ .remove = usbtll_omap_remove,
};
int omap_tll_init(struct usbhs_omap_platform_data *pdata)
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index ab55906f91f9..1fbba0e666d5 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -243,7 +243,7 @@ static struct platform_driver pcf50633_adc_driver = {
.name = "pcf50633-adc",
},
.probe = pcf50633_adc_probe,
- .remove_new = pcf50633_adc_remove,
+ .remove = pcf50633_adc_remove,
};
module_platform_driver(pcf50633_adc_driver);
diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c
index 8b6285f687da..f9ebdf5845b8 100644
--- a/drivers/mfd/qcom-pm8xxx.c
+++ b/drivers/mfd/qcom-pm8xxx.c
@@ -595,7 +595,7 @@ static void pm8xxx_remove(struct platform_device *pdev)
static struct platform_driver pm8xxx_driver = {
.probe = pm8xxx_probe,
- .remove_new = pm8xxx_remove,
+ .remove = pm8xxx_remove,
.driver = {
.name = "pm8xxx-core",
.of_match_table = pm8xxx_id_table,
diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c
index 39ab114ea669..71c2b80a4678 100644
--- a/drivers/mfd/rk8xx-core.c
+++ b/drivers/mfd/rk8xx-core.c
@@ -618,7 +618,7 @@ static int rk808_power_off(struct sys_off_data *data)
bit = DEV_OFF;
break;
case RK808_ID:
- reg = RK808_DEVCTRL_REG,
+ reg = RK808_DEVCTRL_REG;
bit = DEV_OFF_RST;
break;
case RK809_ID:
@@ -785,8 +785,8 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
if (ret)
return dev_err_probe(dev, ret, "failed to add MFD devices\n");
- if (device_property_read_bool(dev, "rockchip,system-power-controller") ||
- device_property_read_bool(dev, "system-power-controller")) {
+ if (device_property_read_bool(dev, "system-power-controller") ||
+ device_property_read_bool(dev, "rockchip,system-power-controller")) {
ret = devm_register_sys_off_handler(dev,
SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,
&rk808_power_off, rk808);
diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c
index 39f7514aa3d8..738d8b3b9ffe 100644
--- a/drivers/mfd/rohm-bd71828.c
+++ b/drivers/mfd/rohm-bd71828.c
@@ -32,15 +32,15 @@ static struct gpio_keys_platform_data bd71828_powerkey_data = {
};
static const struct resource bd71815_rtc_irqs[] = {
- DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC0, "bd71815-rtc-alm-0"),
- DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC1, "bd71815-rtc-alm-1"),
- DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC2, "bd71815-rtc-alm-2"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC0, "bd70528-rtc-alm-0"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC1, "bd70528-rtc-alm-1"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC2, "bd70528-rtc-alm-2"),
};
static const struct resource bd71828_rtc_irqs[] = {
- DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"),
- DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"),
- DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd71828-rtc-alm-2"),
+ DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd70528-rtc-alm-0"),
+ DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd70528-rtc-alm-1"),
+ DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd70528-rtc-alm-2"),
};
static struct resource bd71815_power_irqs[] = {
diff --git a/drivers/mfd/rohm-bd96801.c b/drivers/mfd/rohm-bd96801.c
index 714f08ed544b..60ec8db790a7 100644
--- a/drivers/mfd/rohm-bd96801.c
+++ b/drivers/mfd/rohm-bd96801.c
@@ -5,13 +5,9 @@
* ROHM BD96801 PMIC driver
*
* This version of the "BD86801 scalable PMIC"'s driver supports only very
- * basic set of the PMIC features. Most notably, there is no support for
- * the ERRB interrupt and the configurations which should be done when the
- * PMIC is in STBY mode.
- *
- * Supporting the ERRB interrupt would require dropping the regmap-IRQ
- * usage or working around (or accepting a presense of) a naming conflict
- * in debugFS IRQs.
+ * basic set of the PMIC features.
+ * Most notably, there is no support for the configurations which should
+ * be done when the PMIC is in STBY mode.
*
* Being able to reliably do the configurations like changing the
* regulator safety limits (like limits for the over/under -voltages, over
@@ -23,16 +19,14 @@
* be the need to configure these safety limits. Hence it's not simple to
* come up with a generic solution.
*
- * Users who require the ERRB handling and STBY state configurations can
- * have a look at the original RFC:
+ * Users who require the STBY state configurations can have a look at the
+ * original RFC:
* https://lore.kernel.org/all/cover.1712920132.git.mazziesaccount@gmail.com/
- * which implements a workaround to debugFS naming conflict and some of
- * the safety limit configurations - but leaves the state change handling
- * and synchronization to be implemented.
+ * which implements some of the safety limit configurations - but leaves the
+ * state change handling and synchronization to be implemented.
*
* It would be great to hear (and receive a patch!) if you implement the
- * STBY configuration support or a proper fix to the debugFS naming
- * conflict in your downstream driver ;)
+ * STBY configuration support or a proper fix in your downstream driver ;)
*/
#include <linux/i2c.h>
@@ -46,6 +40,64 @@
#include <linux/mfd/rohm-bd96801.h>
#include <linux/mfd/rohm-generic.h>
+static const struct resource regulator_errb_irqs[] = {
+ DEFINE_RES_IRQ_NAMED(BD96801_OTP_ERR_STAT, "bd96801-otp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_DBIST_ERR_STAT, "bd96801-dbist-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_EEP_ERR_STAT, "bd96801-eep-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_ABIST_ERR_STAT, "bd96801-abist-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_PRSTB_ERR_STAT, "bd96801-prstb-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_DRMOS1_ERR_STAT, "bd96801-drmoserr1"),
+ DEFINE_RES_IRQ_NAMED(BD96801_DRMOS2_ERR_STAT, "bd96801-drmoserr2"),
+ DEFINE_RES_IRQ_NAMED(BD96801_SLAVE_ERR_STAT, "bd96801-slave-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_VREF_ERR_STAT, "bd96801-vref-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_TSD_ERR_STAT, "bd96801-tsd"),
+ DEFINE_RES_IRQ_NAMED(BD96801_UVLO_ERR_STAT, "bd96801-uvlo-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_OVLO_ERR_STAT, "bd96801-ovlo-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_OSC_ERR_STAT, "bd96801-osc-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_PON_ERR_STAT, "bd96801-pon-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_POFF_ERR_STAT, "bd96801-poff-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_CMD_SHDN_ERR_STAT, "bd96801-cmd-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_INT_PRSTB_WDT_ERR, "bd96801-prstb-wdt-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_INT_CHIP_IF_ERR, "bd96801-chip-if-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_INT_SHDN_ERR_STAT, "bd96801-int-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_PVIN_ERR_STAT, "bd96801-buck1-pvin-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVP_ERR_STAT, "bd96801-buck1-ovp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVP_ERR_STAT, "bd96801-buck1-uvp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_SHDN_ERR_STAT, "bd96801-buck1-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_PVIN_ERR_STAT, "bd96801-buck2-pvin-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVP_ERR_STAT, "bd96801-buck2-ovp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVP_ERR_STAT, "bd96801-buck2-uvp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_SHDN_ERR_STAT, "bd96801-buck2-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_PVIN_ERR_STAT, "bd96801-buck3-pvin-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVP_ERR_STAT, "bd96801-buck3-ovp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVP_ERR_STAT, "bd96801-buck3-uvp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_SHDN_ERR_STAT, "bd96801-buck3-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_PVIN_ERR_STAT, "bd96801-buck4-pvin-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVP_ERR_STAT, "bd96801-buck4-ovp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVP_ERR_STAT, "bd96801-buck4-uvp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_SHDN_ERR_STAT, "bd96801-buck4-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_PVIN_ERR_STAT, "bd96801-ldo5-pvin-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVP_ERR_STAT, "bd96801-ldo5-ovp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVP_ERR_STAT, "bd96801-ldo5-uvp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_SHDN_ERR_STAT, "bd96801-ldo5-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_PVIN_ERR_STAT, "bd96801-ldo6-pvin-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVP_ERR_STAT, "bd96801-ldo6-ovp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVP_ERR_STAT, "bd96801-ldo6-uvp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_SHDN_ERR_STAT, "bd96801-ldo6-shdn-err"),
+
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_PVIN_ERR_STAT, "bd96801-ldo7-pvin-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVP_ERR_STAT, "bd96801-ldo7-ovp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVP_ERR_STAT, "bd96801-ldo7-uvp-err"),
+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_SHDN_ERR_STAT, "bd96801-ldo7-shdn-err"),
+};
+
static const struct resource regulator_intb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96801_TW_STAT, "bd96801-core-thermal"),
@@ -90,20 +142,14 @@ static const struct resource regulator_intb_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVD_STAT, "bd96801-ldo7-undervolt"),
};
-static const struct resource wdg_intb_irqs[] = {
- DEFINE_RES_IRQ_NAMED(BD96801_WDT_ERR_STAT, "bd96801-wdg"),
+enum {
+ WDG_CELL = 0,
+ REGULATOR_CELL,
};
static struct mfd_cell bd96801_cells[] = {
- {
- .name = "bd96801-wdt",
- .resources = wdg_intb_irqs,
- .num_resources = ARRAY_SIZE(wdg_intb_irqs),
- }, {
- .name = "bd96801-regulator",
- .resources = regulator_intb_irqs,
- .num_resources = ARRAY_SIZE(regulator_intb_irqs),
- },
+ [WDG_CELL] = { .name = "bd96801-wdt", },
+ [REGULATOR_CELL] = { .name = "bd96801-regulator", },
};
static const struct regmap_range bd96801_volatile_ranges[] = {
@@ -128,6 +174,91 @@ static const struct regmap_access_table volatile_regs = {
.n_yes_ranges = ARRAY_SIZE(bd96801_volatile_ranges),
};
+/*
+ * For ERRB we need main register bit mapping as bit(0) indicates active IRQ
+ * in one of the first 3 sub IRQ registers, For INTB we can use default 1 to 1
+ * mapping.
+ */
+static unsigned int bit0_offsets[] = {0, 1, 2}; /* System stat, 3 registers */
+static unsigned int bit1_offsets[] = {3}; /* Buck 1 stat */
+static unsigned int bit2_offsets[] = {4}; /* Buck 2 stat */
+static unsigned int bit3_offsets[] = {5}; /* Buck 3 stat */
+static unsigned int bit4_offsets[] = {6}; /* Buck 4 stat */
+static unsigned int bit5_offsets[] = {7}; /* LDO 5 stat */
+static unsigned int bit6_offsets[] = {8}; /* LDO 6 stat */
+static unsigned int bit7_offsets[] = {9}; /* LDO 7 stat */
+
+static const struct regmap_irq_sub_irq_map errb_sub_irq_offsets[] = {
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets),
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets),
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets),
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets),
+ REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
+};
+
+static const struct regmap_irq bd96801_errb_irqs[] = {
+ /* Reg 0x52 Fatal ERRB1 */
+ REGMAP_IRQ_REG(BD96801_OTP_ERR_STAT, 0, BD96801_OTP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_DBIST_ERR_STAT, 0, BD96801_DBIST_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_EEP_ERR_STAT, 0, BD96801_EEP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_ABIST_ERR_STAT, 0, BD96801_ABIST_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_PRSTB_ERR_STAT, 0, BD96801_PRSTB_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_DRMOS1_ERR_STAT, 0, BD96801_DRMOS1_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_DRMOS2_ERR_STAT, 0, BD96801_DRMOS2_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_SLAVE_ERR_STAT, 0, BD96801_SLAVE_ERR_MASK),
+ /* 0x53 Fatal ERRB2 */
+ REGMAP_IRQ_REG(BD96801_VREF_ERR_STAT, 1, BD96801_VREF_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_TSD_ERR_STAT, 1, BD96801_TSD_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_UVLO_ERR_STAT, 1, BD96801_UVLO_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_OVLO_ERR_STAT, 1, BD96801_OVLO_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_OSC_ERR_STAT, 1, BD96801_OSC_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_PON_ERR_STAT, 1, BD96801_PON_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_POFF_ERR_STAT, 1, BD96801_POFF_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_CMD_SHDN_ERR_STAT, 1, BD96801_CMD_SHDN_ERR_MASK),
+ /* 0x54 Fatal INTB shadowed to ERRB */
+ REGMAP_IRQ_REG(BD96801_INT_PRSTB_WDT_ERR, 2, BD96801_INT_PRSTB_WDT_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_INT_CHIP_IF_ERR, 2, BD96801_INT_CHIP_IF_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_INT_SHDN_ERR_STAT, 2, BD96801_INT_SHDN_ERR_MASK),
+ /* Reg 0x55 BUCK1 ERR IRQs */
+ REGMAP_IRQ_REG(BD96801_BUCK1_PVIN_ERR_STAT, 3, BD96801_OUT_PVIN_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK1_OVP_ERR_STAT, 3, BD96801_OUT_OVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK1_UVP_ERR_STAT, 3, BD96801_OUT_UVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK1_SHDN_ERR_STAT, 3, BD96801_OUT_SHDN_ERR_MASK),
+ /* Reg 0x56 BUCK2 ERR IRQs */
+ REGMAP_IRQ_REG(BD96801_BUCK2_PVIN_ERR_STAT, 4, BD96801_OUT_PVIN_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK2_OVP_ERR_STAT, 4, BD96801_OUT_OVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK2_UVP_ERR_STAT, 4, BD96801_OUT_UVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK2_SHDN_ERR_STAT, 4, BD96801_OUT_SHDN_ERR_MASK),
+ /* Reg 0x57 BUCK3 ERR IRQs */
+ REGMAP_IRQ_REG(BD96801_BUCK3_PVIN_ERR_STAT, 5, BD96801_OUT_PVIN_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK3_OVP_ERR_STAT, 5, BD96801_OUT_OVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK3_UVP_ERR_STAT, 5, BD96801_OUT_UVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK3_SHDN_ERR_STAT, 5, BD96801_OUT_SHDN_ERR_MASK),
+ /* Reg 0x58 BUCK4 ERR IRQs */
+ REGMAP_IRQ_REG(BD96801_BUCK4_PVIN_ERR_STAT, 6, BD96801_OUT_PVIN_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK4_OVP_ERR_STAT, 6, BD96801_OUT_OVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK4_UVP_ERR_STAT, 6, BD96801_OUT_UVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_BUCK4_SHDN_ERR_STAT, 6, BD96801_OUT_SHDN_ERR_MASK),
+ /* Reg 0x59 LDO5 ERR IRQs */
+ REGMAP_IRQ_REG(BD96801_LDO5_PVIN_ERR_STAT, 7, BD96801_OUT_PVIN_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO5_OVP_ERR_STAT, 7, BD96801_OUT_OVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO5_UVP_ERR_STAT, 7, BD96801_OUT_UVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO5_SHDN_ERR_STAT, 7, BD96801_OUT_SHDN_ERR_MASK),
+ /* Reg 0x5a LDO6 ERR IRQs */
+ REGMAP_IRQ_REG(BD96801_LDO6_PVIN_ERR_STAT, 8, BD96801_OUT_PVIN_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO6_OVP_ERR_STAT, 8, BD96801_OUT_OVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO6_UVP_ERR_STAT, 8, BD96801_OUT_UVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO6_SHDN_ERR_STAT, 8, BD96801_OUT_SHDN_ERR_MASK),
+ /* Reg 0x5b LDO7 ERR IRQs */
+ REGMAP_IRQ_REG(BD96801_LDO7_PVIN_ERR_STAT, 9, BD96801_OUT_PVIN_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO7_OVP_ERR_STAT, 9, BD96801_OUT_OVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO7_UVP_ERR_STAT, 9, BD96801_OUT_UVP_ERR_MASK),
+ REGMAP_IRQ_REG(BD96801_LDO7_SHDN_ERR_STAT, 9, BD96801_OUT_SHDN_ERR_MASK),
+};
+
static const struct regmap_irq bd96801_intb_irqs[] = {
/* STATUS SYSTEM INTB */
REGMAP_IRQ_REG(BD96801_TW_STAT, 0, BD96801_TW_STAT_MASK),
@@ -176,8 +307,25 @@ static const struct regmap_irq bd96801_intb_irqs[] = {
REGMAP_IRQ_REG(BD96801_LDO7_UVD_STAT, 7, BD96801_LDO_UVD_STAT_MASK),
};
-static struct regmap_irq_chip bd96801_irq_chip_intb = {
+static const struct regmap_irq_chip bd96801_irq_chip_errb = {
+ .name = "bd96801-irq-errb",
+ .domain_suffix = "errb",
+ .main_status = BD96801_REG_INT_MAIN,
+ .num_main_regs = 1,
+ .irqs = &bd96801_errb_irqs[0],
+ .num_irqs = ARRAY_SIZE(bd96801_errb_irqs),
+ .status_base = BD96801_REG_INT_SYS_ERRB1,
+ .mask_base = BD96801_REG_MASK_SYS_ERRB,
+ .ack_base = BD96801_REG_INT_SYS_ERRB1,
+ .init_ack_masked = true,
+ .num_regs = 10,
+ .irq_reg_stride = 1,
+ .sub_reg_offsets = &errb_sub_irq_offsets[0],
+};
+
+static const struct regmap_irq_chip bd96801_irq_chip_intb = {
.name = "bd96801-irq-intb",
+ .domain_suffix = "intb",
.main_status = BD96801_REG_INT_MAIN,
.num_main_regs = 1,
.irqs = &bd96801_intb_irqs[0],
@@ -194,16 +342,20 @@ static const struct regmap_config bd96801_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_table = &volatile_regs,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int bd96801_i2c_probe(struct i2c_client *i2c)
{
- struct regmap_irq_chip_data *intb_irq_data;
+ struct regmap_irq_chip_data *intb_irq_data, *errb_irq_data;
+ struct irq_domain *intb_domain, *errb_domain;
const struct fwnode_handle *fwnode;
- struct irq_domain *intb_domain;
+ struct resource *regulator_res;
+ struct resource wdg_irq;
struct regmap *regmap;
- int ret, intb_irq;
+ int intb_irq, errb_irq, num_intb, num_errb = 0;
+ int num_regu_irqs, wdg_irq_no;
+ int i, ret;
fwnode = dev_fwnode(&i2c->dev);
if (!fwnode)
@@ -213,6 +365,23 @@ static int bd96801_i2c_probe(struct i2c_client *i2c)
if (intb_irq < 0)
return dev_err_probe(&i2c->dev, intb_irq, "INTB IRQ not configured\n");
+ num_intb = ARRAY_SIZE(regulator_intb_irqs);
+
+ /* ERRB may be omitted if processor is powered by the PMIC */
+ errb_irq = fwnode_irq_get_byname(fwnode, "errb");
+ if (errb_irq < 0)
+ errb_irq = 0;
+
+ if (errb_irq)
+ num_errb = ARRAY_SIZE(regulator_errb_irqs);
+
+ num_regu_irqs = num_intb + num_errb;
+
+ regulator_res = devm_kcalloc(&i2c->dev, num_regu_irqs,
+ sizeof(*regulator_res), GFP_KERNEL);
+ if (!regulator_res)
+ return -ENOMEM;
+
regmap = devm_regmap_init_i2c(i2c, &bd96801_regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(&i2c->dev, PTR_ERR(regmap),
@@ -230,12 +399,50 @@ static int bd96801_i2c_probe(struct i2c_client *i2c)
intb_domain = regmap_irq_get_domain(intb_irq_data);
- ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
- bd96801_cells,
- ARRAY_SIZE(bd96801_cells), NULL, 0,
- intb_domain);
+ /*
+ * MFD core code is built to handle only one IRQ domain. BD96801
+ * has two domains so we do IRQ mapping here and provide the
+ * already mapped IRQ numbers to sub-devices.
+ */
+ for (i = 0; i < num_intb; i++) {
+ struct resource *res = &regulator_res[i];
+
+ *res = regulator_intb_irqs[i];
+ res->start = res->end = irq_create_mapping(intb_domain,
+ res->start);
+ }
+
+ wdg_irq_no = irq_create_mapping(intb_domain, BD96801_WDT_ERR_STAT);
+ wdg_irq = DEFINE_RES_IRQ_NAMED(wdg_irq_no, "bd96801-wdg");
+ bd96801_cells[WDG_CELL].resources = &wdg_irq;
+ bd96801_cells[WDG_CELL].num_resources = 1;
+
+ if (!num_errb)
+ goto skip_errb;
+
+ ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, errb_irq, IRQF_ONESHOT,
+ 0, &bd96801_irq_chip_errb, &errb_irq_data);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to add ERRB IRQ chip\n");
+
+ errb_domain = regmap_irq_get_domain(errb_irq_data);
+
+ for (i = 0; i < num_errb; i++) {
+ struct resource *res = &regulator_res[num_intb + i];
+
+ *res = regulator_errb_irqs[i];
+ res->start = res->end = irq_create_mapping(errb_domain, res->start);
+ }
+
+skip_errb:
+ bd96801_cells[REGULATOR_CELL].resources = regulator_res;
+ bd96801_cells[REGULATOR_CELL].num_resources = num_regu_irqs;
+
+ ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, bd96801_cells,
+ ARRAY_SIZE(bd96801_cells), NULL, 0, NULL);
if (ret)
- dev_err(&i2c->dev, "Failed to create subdevices\n");
+ dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n");
return ret;
}
diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c
index 7e23ab3d5842..84ebc96f58e4 100644
--- a/drivers/mfd/rt5033.c
+++ b/drivers/mfd/rt5033.c
@@ -81,8 +81,8 @@ static int rt5033_i2c_probe(struct i2c_client *i2c)
chip_rev = dev_id & RT5033_CHIP_REV_MASK;
dev_info(&i2c->dev, "Device found (rev. %d)\n", chip_rev);
- ret = regmap_add_irq_chip(rt5033->regmap, rt5033->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ ret = devm_regmap_add_irq_chip(rt5033->dev, rt5033->regmap,
+ rt5033->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
0, &rt5033_irq_chip, &rt5033->irq_data);
if (ret) {
dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index a6b0d7300b2d..cdfe738e1d76 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -34,6 +34,10 @@ static const struct mfd_cell s5m8767_devs[] = {
},
};
+static const struct mfd_cell s2dos05_devs[] = {
+ { .name = "s2dos05-regulator", },
+};
+
static const struct mfd_cell s2mps11_devs[] = {
{ .name = "s2mps11-regulator", },
{ .name = "s2mps14-rtc", },
@@ -84,6 +88,9 @@ static const struct of_device_id sec_dt_match[] = {
.compatible = "samsung,s5m8767-pmic",
.data = (void *)S5M8767X,
}, {
+ .compatible = "samsung,s2dos05",
+ .data = (void *)S2DOS05,
+ }, {
.compatible = "samsung,s2mps11-pmic",
.data = (void *)S2MPS11X,
}, {
@@ -339,6 +346,10 @@ static int sec_pmic_probe(struct i2c_client *i2c)
sec_devs = s5m8767_devs;
num_sec_devs = ARRAY_SIZE(s5m8767_devs);
break;
+ case S2DOS05:
+ sec_devs = s2dos05_devs;
+ num_sec_devs = ARRAY_SIZE(s2dos05_devs);
+ break;
case S2MPA01:
sec_devs = s2mpa01_devs;
num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index b3592982a83b..0469e85d72cf 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1705,7 +1705,7 @@ static struct platform_driver sm501_plat_driver = {
.of_match_table = of_sm501_match_tbl,
},
.probe = sm501_plat_probe,
- .remove_new = sm501_plat_remove,
+ .remove = sm501_plat_remove,
.suspend = pm_sleep_ptr(sm501_plat_suspend),
.resume = pm_sleep_ptr(sm501_plat_resume),
};
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
index 9fd13d88950c..650724e19b88 100644
--- a/drivers/mfd/stm32-timers.c
+++ b/drivers/mfd/stm32-timers.c
@@ -326,7 +326,7 @@ MODULE_DEVICE_TABLE(of, stm32_timers_of_match);
static struct platform_driver stm32_timers_driver = {
.probe = stm32_timers_probe,
- .remove_new = stm32_timers_remove,
+ .remove = stm32_timers_remove,
.driver = {
.name = "stm32-timers",
.of_match_table = stm32_timers_of_match,
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 2ce15f60eb10..3e1d699ba934 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -108,6 +108,8 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size(&res) - reg_io_width;
+ if (!syscon_config.max_register)
+ syscon_config.max_register_is_0 = true;
regmap = regmap_init_mmio(NULL, base, &syscon_config);
kfree(syscon_config.name);
@@ -357,6 +359,9 @@ static int syscon_probe(struct platform_device *pdev)
return -ENOMEM;
syscon_config.max_register = resource_size(res) - 4;
+ if (!syscon_config.max_register)
+ syscon_config.max_register_is_0 = true;
+
if (pdata)
syscon_config.name = pdata->label;
syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_config);
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 0c1364d88469..068c25401c6c 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -377,7 +377,7 @@ static struct platform_driver ti_tscadc_driver = {
.of_match_table = ti_tscadc_dt_ids,
},
.probe = ti_tscadc_probe,
- .remove_new = ti_tscadc_remove,
+ .remove = ti_tscadc_remove,
};
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index 2b9105295f30..710364435b6b 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -544,17 +544,13 @@ static int tps65010_probe(struct i2c_client *client)
*/
if (client->irq > 0) {
status = request_irq(client->irq, tps65010_irq,
- IRQF_TRIGGER_FALLING, DRIVER_NAME, tps);
+ IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN,
+ DRIVER_NAME, tps);
if (status < 0) {
dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
client->irq, status);
return status;
}
- /* annoying race here, ideally we'd have an option
- * to claim the irq now and enable it later.
- * FIXME genirq IRQF_NOAUTOEN now solves that ...
- */
- disable_irq(client->irq);
set_bit(FLAG_IRQ_ENABLE, &tps->flags);
} else
dev_warn(&client->dev, "IRQ not configured!\n");
diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
index f206a9c50e9d..7098712ea008 100644
--- a/drivers/mfd/tps65911-comparator.c
+++ b/drivers/mfd/tps65911-comparator.c
@@ -154,7 +154,7 @@ static struct platform_driver tps65911_comparator_driver = {
.name = "tps65911-comparator",
},
.probe = tps65911_comparator_probe,
- .remove_new = tps65911_comparator_remove,
+ .remove = tps65911_comparator_remove,
};
static int __init tps65911_comparator_init(void)
diff --git a/drivers/mfd/tqmx86.c b/drivers/mfd/tqmx86.c
index fac02875fe7d..1cba3b67b0fb 100644
--- a/drivers/mfd/tqmx86.c
+++ b/drivers/mfd/tqmx86.c
@@ -35,11 +35,14 @@
#define TQMX86_REG_BOARD_ID_E39C2 7
#define TQMX86_REG_BOARD_ID_70EB 8
#define TQMX86_REG_BOARD_ID_80UC 9
+#define TQMX86_REG_BOARD_ID_120UC 10
#define TQMX86_REG_BOARD_ID_110EB 11
#define TQMX86_REG_BOARD_ID_E40M 12
#define TQMX86_REG_BOARD_ID_E40S 13
#define TQMX86_REG_BOARD_ID_E40C1 14
#define TQMX86_REG_BOARD_ID_E40C2 15
+#define TQMX86_REG_BOARD_ID_130UC 16
+#define TQMX86_REG_BOARD_ID_E41S 19
#define TQMX86_REG_BOARD_REV 0x01
#define TQMX86_REG_IO_EXT_INT 0x06
#define TQMX86_REG_IO_EXT_INT_NONE 0
@@ -47,6 +50,7 @@
#define TQMX86_REG_IO_EXT_INT_9 2
#define TQMX86_REG_IO_EXT_INT_12 3
#define TQMX86_REG_IO_EXT_INT_MASK 0x3
+#define TQMX86_REG_IO_EXT_INT_I2C1_SHIFT 0
#define TQMX86_REG_IO_EXT_INT_GPIO_SHIFT 4
#define TQMX86_REG_SAUC 0x17
@@ -55,23 +59,36 @@
static uint gpio_irq;
module_param(gpio_irq, uint, 0);
-MODULE_PARM_DESC(gpio_irq, "GPIO IRQ number (7, 9, 12)");
+MODULE_PARM_DESC(gpio_irq, "GPIO IRQ number (valid parameters: 7, 9, 12)");
-static const struct resource tqmx_i2c_soft_resources[] = {
- DEFINE_RES_IO(TQMX86_IOBASE_I2C, TQMX86_IOSIZE_I2C),
+static uint i2c1_irq;
+module_param(i2c1_irq, uint, 0);
+MODULE_PARM_DESC(i2c1_irq, "I2C1 IRQ number (valid parameters: 7, 9, 12)");
+
+enum tqmx86_i2c1_resource_type {
+ TQMX86_I2C1_IO,
+ TQMX86_I2C1_IRQ,
+};
+
+static struct resource tqmx_i2c_soft_resources[] = {
+ [TQMX86_I2C1_IO] = DEFINE_RES_IO(TQMX86_IOBASE_I2C, TQMX86_IOSIZE_I2C),
+ /* Placeholder for IRQ resource */
+ [TQMX86_I2C1_IRQ] = {},
};
static const struct resource tqmx_watchdog_resources[] = {
DEFINE_RES_IO(TQMX86_IOBASE_WATCHDOG, TQMX86_IOSIZE_WATCHDOG),
};
-/*
- * The IRQ resource must be first, since it is updated with the
- * configured IRQ in the probe function.
- */
+enum tqmx86_gpio_resource_type {
+ TQMX86_GPIO_IO,
+ TQMX86_GPIO_IRQ,
+};
+
static struct resource tqmx_gpio_resources[] = {
- DEFINE_RES_IRQ(0),
- DEFINE_RES_IO(TQMX86_IOBASE_GPIO, TQMX86_IOSIZE_GPIO),
+ [TQMX86_GPIO_IO] = DEFINE_RES_IO(TQMX86_IOBASE_GPIO, TQMX86_IOSIZE_GPIO),
+ /* Placeholder for IRQ resource */
+ [TQMX86_GPIO_IRQ] = {},
};
static struct i2c_board_info tqmx86_i2c_devices[] = {
@@ -132,6 +149,8 @@ static const char *tqmx86_board_id_to_name(u8 board_id, u8 sauc)
return "TQMx70EB";
case TQMX86_REG_BOARD_ID_80UC:
return "TQMx80UC";
+ case TQMX86_REG_BOARD_ID_120UC:
+ return "TQMx120UC";
case TQMX86_REG_BOARD_ID_110EB:
return "TQMx110EB";
case TQMX86_REG_BOARD_ID_E40M:
@@ -142,6 +161,10 @@ static const char *tqmx86_board_id_to_name(u8 board_id, u8 sauc)
return "TQMxE40C1";
case TQMX86_REG_BOARD_ID_E40C2:
return "TQMxE40C2";
+ case TQMX86_REG_BOARD_ID_130UC:
+ return "TQMx130UC";
+ case TQMX86_REG_BOARD_ID_E41S:
+ return "TQMxE41S";
default:
return "Unknown";
}
@@ -154,11 +177,14 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
case TQMX86_REG_BOARD_ID_60EB:
case TQMX86_REG_BOARD_ID_70EB:
case TQMX86_REG_BOARD_ID_80UC:
+ case TQMX86_REG_BOARD_ID_120UC:
case TQMX86_REG_BOARD_ID_110EB:
case TQMX86_REG_BOARD_ID_E40M:
case TQMX86_REG_BOARD_ID_E40S:
case TQMX86_REG_BOARD_ID_E40C1:
case TQMX86_REG_BOARD_ID_E40C2:
+ case TQMX86_REG_BOARD_ID_130UC:
+ case TQMX86_REG_BOARD_ID_E41S:
return 24000;
case TQMX86_REG_BOARD_ID_E39MS:
case TQMX86_REG_BOARD_ID_E39C1:
@@ -174,33 +200,52 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id)
}
}
-static int tqmx86_probe(struct platform_device *pdev)
+static int tqmx86_setup_irq(struct device *dev, const char *label, u8 irq,
+ void __iomem *io_base, u8 reg_shift)
{
- u8 board_id, sauc, rev, i2c_det, io_ext_int_val;
- struct device *dev = &pdev->dev;
- u8 gpio_irq_cfg, readback;
- const char *board_name;
- void __iomem *io_base;
- int err;
+ u8 val, readback;
+ int irq_cfg;
- switch (gpio_irq) {
+ switch (irq) {
case 0:
- gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_NONE;
+ irq_cfg = TQMX86_REG_IO_EXT_INT_NONE;
break;
case 7:
- gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_7;
+ irq_cfg = TQMX86_REG_IO_EXT_INT_7;
break;
case 9:
- gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_9;
+ irq_cfg = TQMX86_REG_IO_EXT_INT_9;
break;
case 12:
- gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_12;
+ irq_cfg = TQMX86_REG_IO_EXT_INT_12;
break;
default:
- pr_err("tqmx86: Invalid GPIO IRQ (%d)\n", gpio_irq);
+ dev_err(dev, "invalid %s IRQ (%d)\n", label, irq);
return -EINVAL;
}
+ val = ioread8(io_base + TQMX86_REG_IO_EXT_INT);
+ val &= ~(TQMX86_REG_IO_EXT_INT_MASK << reg_shift);
+ val |= (irq_cfg & TQMX86_REG_IO_EXT_INT_MASK) << reg_shift;
+
+ iowrite8(val, io_base + TQMX86_REG_IO_EXT_INT);
+ readback = ioread8(io_base + TQMX86_REG_IO_EXT_INT);
+ if (readback != val) {
+ dev_warn(dev, "%s interrupts not supported\n", label);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tqmx86_probe(struct platform_device *pdev)
+{
+ u8 board_id, sauc, rev, i2c_det;
+ struct device *dev = &pdev->dev;
+ const char *board_name;
+ void __iomem *io_base;
+ int err;
+
io_base = devm_ioport_map(dev, TQMX86_IOBASE, TQMX86_IOSIZE);
if (!io_base)
return -ENOMEM;
@@ -221,25 +266,23 @@ static int tqmx86_probe(struct platform_device *pdev)
*/
i2c_det = inb(TQMX86_REG_I2C_DETECT);
- if (gpio_irq_cfg) {
- io_ext_int_val =
- gpio_irq_cfg << TQMX86_REG_IO_EXT_INT_GPIO_SHIFT;
- iowrite8(io_ext_int_val, io_base + TQMX86_REG_IO_EXT_INT);
- readback = ioread8(io_base + TQMX86_REG_IO_EXT_INT);
- if (readback != io_ext_int_val) {
- dev_warn(dev, "GPIO interrupts not supported.\n");
- return -EINVAL;
- }
-
- /* Assumes the IRQ resource is first. */
- tqmx_gpio_resources[0].start = gpio_irq;
- } else {
- tqmx_gpio_resources[0].flags = 0;
+ if (gpio_irq) {
+ err = tqmx86_setup_irq(dev, "GPIO", gpio_irq, io_base,
+ TQMX86_REG_IO_EXT_INT_GPIO_SHIFT);
+ if (!err)
+ tqmx_gpio_resources[TQMX86_GPIO_IRQ] = DEFINE_RES_IRQ(gpio_irq);
}
ocores_platform_data.clock_khz = tqmx86_board_id_to_clk_rate(dev, board_id);
if (i2c_det == TQMX86_REG_I2C_DETECT_SOFT) {
+ if (i2c1_irq) {
+ err = tqmx86_setup_irq(dev, "I2C1", i2c1_irq, io_base,
+ TQMX86_REG_IO_EXT_INT_I2C1_SHIFT);
+ if (!err)
+ tqmx_i2c_soft_resources[TQMX86_I2C1_IRQ] = DEFINE_RES_IRQ(i2c1_irq);
+ }
+
err = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
tqmx86_i2c_soft_dev,
ARRAY_SIZE(tqmx86_i2c_soft_dev),
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index c130ffef182f..f89eda4a17fe 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -711,6 +711,10 @@ static struct of_dev_auxdata twl_auxdata_lookup[] = {
{ /* sentinel */ },
};
+static const struct mfd_cell twl6030_cells[] = {
+ { .name = "twl6030-clk" },
+};
+
static const struct mfd_cell twl6032_cells[] = {
{ .name = "twl6032-clk" },
};
@@ -861,17 +865,23 @@ twl_probe(struct i2c_client *client)
TWL4030_DCDC_GLOBAL_CFG);
}
- if (id->driver_data == (TWL6030_CLASS | TWL6032_SUBCLASS)) {
- status = devm_mfd_add_devices(&client->dev,
- PLATFORM_DEVID_NONE,
- twl6032_cells,
- ARRAY_SIZE(twl6032_cells),
- NULL, 0, NULL);
+ if (twl_class_is_6030()) {
+ const struct mfd_cell *cells;
+ int num_cells;
+
+ if (id->driver_data & TWL6032_SUBCLASS) {
+ cells = twl6032_cells;
+ num_cells = ARRAY_SIZE(twl6032_cells);
+ } else {
+ cells = twl6030_cells;
+ num_cells = ARRAY_SIZE(twl6030_cells);
+ }
+
+ status = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
+ cells, num_cells, NULL, 0, NULL);
if (status < 0)
goto free;
- }
- if (twl_class_is_6030()) {
if (of_device_is_system_power_controller(node)) {
if (!pm_power_off)
pm_power_off = twl6030_power_off;
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index d436ddf661da..a4a550bafb3c 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -276,7 +276,7 @@ static struct platform_driver twl4030_audio_driver = {
.of_match_table = twl4030_audio_of_match,
},
.probe = twl4030_audio_probe,
- .remove_new = twl4030_audio_remove,
+ .remove = twl4030_audio_remove,
};
module_platform_driver(twl4030_audio_driver);
diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c
index fcd182d51981..3c3080e8c8cf 100644
--- a/drivers/mfd/wcd934x.c
+++ b/drivers/mfd/wcd934x.c
@@ -284,6 +284,7 @@ static const struct slim_device_id wcd934x_slim_id[] = {
SLIM_DEV_IDX_WCD9340, SLIM_DEV_INSTANCE_ID_WCD9340 },
{}
};
+MODULE_DEVICE_TABLE(slim, wcd934x_slim_id);
static struct slim_driver wcd934x_slim_driver = {
.driver = {
@@ -298,5 +299,4 @@ static struct slim_driver wcd934x_slim_driver = {
module_slim_driver(wcd934x_slim_driver);
MODULE_DESCRIPTION("WCD934X slim driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("slim:217:250:*");
MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 3fe7e2a9bd29..09cbe3f0ab1e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -610,10 +610,33 @@ config MARVELL_CN10K_DPI
To compile this driver as a module, choose M here: the module
will be called mrvl_cn10k_dpi.
+config MCHP_LAN966X_PCI
+ tristate "Microchip LAN966x PCIe Support"
+ depends on PCI
+ select OF
+ select OF_OVERLAY
+ select IRQ_DOMAIN
+ help
+ This enables the support for the LAN966x PCIe device.
+
+ This is used to drive the LAN966x PCIe device from the host system
+ to which it is connected. The driver uses a device tree overlay to
+ load other drivers to support for LAN966x internal components.
+
+ Even if this driver does not depend on those other drivers, in order
+ to have a fully functional board, the following drivers are needed:
+ - fixed-clock (COMMON_CLK)
+ - lan966x-oic (LAN966X_OIC)
+ - lan966x-cpu-syscon (MFD_SYSCON)
+ - lan966x-switch-reset (RESET_MCHP_SPARX5)
+ - lan966x-pinctrl (PINCTRL_OCELOT)
+ - lan966x-serdes (PHY_LAN966X_SERDES)
+ - lan966x-miim (MDIO_MSCC_MIIM)
+ - lan966x-switch (LAN966X_SWITCH)
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
-source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a9f94525e181..40bf953185c7 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -40,7 +40,6 @@ obj-y += eeprom/
obj-y += cb710/
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
obj-$(CONFIG_PCH_PHUB) += pch_phub.o
-obj-y += ti-st/
obj-y += lis3lv02d/
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_INTEL_MEI) += mei/
@@ -71,4 +70,7 @@ obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o
obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o
obj-$(CONFIG_NSM) += nsm.o
obj-$(CONFIG_MARVELL_CN10K_DPI) += mrvl_cn10k_dpi.o
+lan966x-pci-objs := lan966x_pci.o
+lan966x-pci-objs += lan966x_pci.dtbo.o
+obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o
obj-y += keba/
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 6d4edd69db12..e7d73c972f65 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -1147,7 +1147,7 @@ static int apds990x_probe(struct i2c_client *client)
err = chip->pdata->setup_resources();
if (err) {
err = -EINVAL;
- goto fail3;
+ goto fail4;
}
}
@@ -1155,7 +1155,7 @@ static int apds990x_probe(struct i2c_client *client)
apds990x_attribute_group);
if (err < 0) {
dev_err(&chip->client->dev, "Sysfs registration failed\n");
- goto fail4;
+ goto fail5;
}
err = request_threaded_irq(client->irq, NULL,
@@ -1166,15 +1166,17 @@ static int apds990x_probe(struct i2c_client *client)
if (err) {
dev_err(&client->dev, "could not get IRQ %d\n",
client->irq);
- goto fail5;
+ goto fail6;
}
return err;
-fail5:
+fail6:
sysfs_remove_group(&chip->client->dev.kobj,
&apds990x_attribute_group[0]);
-fail4:
+fail5:
if (chip->pdata && chip->pdata->release_resources)
chip->pdata->release_resources();
+fail4:
+ pm_runtime_disable(&client->dev);
fail3:
regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
fail2:
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 6eac0f335915..1d0322dfaf79 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -153,7 +153,7 @@ static int ssc_sound_dai_probe(struct ssc_device *ssc)
ssc->sound_dai = false;
- if (!of_property_read_bool(np, "#sound-dai-cells"))
+ if (!of_property_present(np, "#sound-dai-cells"))
return 0;
id = of_alias_get_id(np, "ssc");
@@ -176,7 +176,7 @@ static void ssc_sound_dai_remove(struct ssc_device *ssc)
#else
static inline int ssc_sound_dai_probe(struct ssc_device *ssc)
{
- if (of_property_read_bool(ssc->pdev->dev.of_node, "#sound-dai-cells"))
+ if (of_property_present(ssc->pdev->dev.of_node, "#sound-dai-cells"))
return -ENOTSUPP;
return 0;
diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c
index 0142c4bf4f42..a5549eaf52d0 100644
--- a/drivers/misc/cardreader/alcor_pci.c
+++ b/drivers/misc/cardreader/alcor_pci.c
@@ -17,8 +17,6 @@
#include <linux/alcor_pci.h>
-#define DRV_NAME_ALCOR_PCI "alcor_pci"
-
static DEFINE_IDA(alcor_pci_idr);
static struct mfd_cell alcor_pci_cells[] = {
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index f150d8769f19..77b0490a1b38 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -20,11 +20,11 @@ MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
static const struct mfd_cell rtsx_usb_cells[] = {
[RTSX_USB_SD_CARD] = {
- .name = "rtsx_usb_sdmmc",
+ .name = DRV_NAME_RTSX_USB_SDMMC,
.pdata_size = 0,
},
[RTSX_USB_MS_CARD] = {
- .name = "rtsx_usb_ms",
+ .name = DRV_NAME_RTSX_USB_MS,
.pdata_size = 0,
},
};
@@ -780,7 +780,7 @@ static const struct usb_device_id rtsx_usb_usb_ids[] = {
MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
static struct usb_driver rtsx_usb_driver = {
- .name = "rtsx_usb",
+ .name = DRV_NAME_RTSX_USB,
.probe = rtsx_usb_probe,
.disconnect = rtsx_usb_disconnect,
.suspend = rtsx_usb_suspend,
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9df12399bda3..cb1c4b8e7fd3 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -97,11 +97,11 @@ config EEPROM_DIGSY_MTC_CFG
If unsure, say N.
config EEPROM_IDT_89HPESX
- tristate "IDT 89HPESx PCIe-swtiches EEPROM / CSR support"
+ tristate "IDT 89HPESx PCIe-switches EEPROM / CSR support"
depends on I2C && SYSFS
help
Enable this driver to get read/write access to EEPROM / CSRs
- over IDT PCIe-swtich i2c-slave interface.
+ over IDT PCIe-switch i2c-slave interface.
This driver can also be built as a module. If so, the module
will be called idt_89hpesx.
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index ca872e3465ed..0a7c7f29406c 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -207,6 +207,8 @@ AT24_CHIP_DATA(at24_data_24cs64, 16,
AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
AT24_CHIP_DATA(at24_data_24c128, 131072 / 8, AT24_FLAG_ADDR16);
AT24_CHIP_DATA(at24_data_24c256, 262144 / 8, AT24_FLAG_ADDR16);
+/* M24256E Additional Write lockable page (M24256E-F order codes) */
+AT24_CHIP_DATA(at24_data_24256e_wlp, 64, AT24_FLAG_ADDR16);
AT24_CHIP_DATA(at24_data_24c512, 524288 / 8, AT24_FLAG_ADDR16);
AT24_CHIP_DATA(at24_data_24c1024, 1048576 / 8, AT24_FLAG_ADDR16);
AT24_CHIP_DATA_BS(at24_data_24c1025, 1048576 / 8, AT24_FLAG_ADDR16, 2);
@@ -240,6 +242,7 @@ static const struct i2c_device_id at24_ids[] = {
{ "24cs64", (kernel_ulong_t)&at24_data_24cs64 },
{ "24c128", (kernel_ulong_t)&at24_data_24c128 },
{ "24c256", (kernel_ulong_t)&at24_data_24c256 },
+ { "24256e-wl", (kernel_ulong_t)&at24_data_24256e_wlp },
{ "24c512", (kernel_ulong_t)&at24_data_24c512 },
{ "24c1024", (kernel_ulong_t)&at24_data_24c1024 },
{ "24c1025", (kernel_ulong_t)&at24_data_24c1025 },
@@ -278,6 +281,7 @@ static const struct of_device_id __maybe_unused at24_of_match[] = {
{ .compatible = "atmel,24c2048", .data = &at24_data_24c2048 },
{ .compatible = "microchip,24aa025e48", .data = &at24_data_24aa025e48 },
{ .compatible = "microchip,24aa025e64", .data = &at24_data_24aa025e64 },
+ { .compatible = "st,24256e-wl", .data = &at24_data_24256e_wlp },
{ /* END OF LIST */ },
};
MODULE_DEVICE_TABLE(of, at24_of_match);
diff --git a/drivers/misc/eeprom/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c
index 9627294fe3e9..e6f0e0fc1ca2 100644
--- a/drivers/misc/eeprom/eeprom_93cx6.c
+++ b/drivers/misc/eeprom/eeprom_93cx6.c
@@ -8,6 +8,7 @@
* Supported chipsets: 93c46 & 93c66.
*/
+#include <linux/bits.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -102,7 +103,7 @@ static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
/*
* Check if this bit needs to be set.
*/
- eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+ eeprom->reg_data_in = !!(data & BIT(i - 1));
/*
* Write the bit to the eeprom register.
@@ -152,7 +153,7 @@ static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
* Read if the bit has been set.
*/
if (eeprom->reg_data_out)
- buf |= (1 << (i - 1));
+ buf |= BIT(i - 1);
eeprom_93cx6_pulse_low(eeprom);
}
@@ -186,6 +187,11 @@ void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
eeprom_93cx6_write_bits(eeprom, command,
PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+ if (has_quirk_extra_read_cycle(eeprom)) {
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
/*
* Read the requested 16 bits.
*/
@@ -252,6 +258,11 @@ void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
eeprom_93cx6_write_bits(eeprom, command,
PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
+ if (has_quirk_extra_read_cycle(eeprom)) {
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
/*
* Read the requested 8 bits.
*/
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index e2221be88445..9cae6f530679 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -229,7 +229,7 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
static ssize_t
eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
- const char *buf, unsigned off)
+ const char *buf, unsigned int off)
{
struct spi_message m;
struct spi_transfer t[2] = {};
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
index 1643ba2ff964..c288aeec16c0 100644
--- a/drivers/misc/isl29020.c
+++ b/drivers/misc/isl29020.c
@@ -68,7 +68,7 @@ static ssize_t als_lux_input_data_show(struct device *dev,
if (val < 0)
return val;
lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / 65536;
- return sprintf(buf, "%ld\n", lux);
+ return sprintf(buf, "%lu\n", lux);
}
static ssize_t als_sensing_range_store(struct device *dev,
diff --git a/drivers/misc/keba/Kconfig b/drivers/misc/keba/Kconfig
index 5fbcbc2252ac..d6d47197a963 100644
--- a/drivers/misc/keba/Kconfig
+++ b/drivers/misc/keba/Kconfig
@@ -1,7 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
config KEBA_CP500
tristate "KEBA CP500 system FPGA support"
+ depends on X86_64 || ARM64 || COMPILE_TEST
depends on PCI
+ depends on I2C
select AUXILIARY_BUS
help
This driver supports the KEBA CP500 system FPGA, which is used in
@@ -11,3 +13,14 @@ config KEBA_CP500
This driver can also be built as a module. If so, the module will be
called cp500.
+
+config KEBA_LAN9252
+ tristate "KEBA CP500 LAN9252 configuration"
+ depends on SPI
+ depends on KEBA_CP500 || COMPILE_TEST
+ help
+ This driver is used for updating the configuration of the LAN9252
+ controller on KEBA CP500 devices.
+
+ This driver can also be built as a module. If so, the module will be
+ called lan9252.
diff --git a/drivers/misc/keba/Makefile b/drivers/misc/keba/Makefile
index 0a8b846cda7d..05e9efcad54f 100644
--- a/drivers/misc/keba/Makefile
+++ b/drivers/misc/keba/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_KEBA_CP500) += cp500.o
+obj-$(CONFIG_KEBA_LAN9252) += lan9252.o
diff --git a/drivers/misc/keba/cp500.c b/drivers/misc/keba/cp500.c
index ae0922817881..255d3022dae8 100644
--- a/drivers/misc/keba/cp500.c
+++ b/drivers/misc/keba/cp500.c
@@ -12,7 +12,12 @@
#include <linux/i2c.h>
#include <linux/misc/keba.h>
#include <linux/module.h>
+#include <linux/mtd/partitions.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
#include <linux/pci.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
#define CP500 "cp500"
@@ -27,6 +32,7 @@
/* BAR 0 registers */
#define CP500_VERSION_REG 0x00
#define CP500_RECONFIG_REG 0x11 /* upper 8-bits of STARTUP register */
+#define CP500_PRESENT_REG 0x20
#define CP500_AXI_REG 0x40
/* Bits in BUILD_REG */
@@ -35,14 +41,35 @@
/* Bits in RECONFIG_REG */
#define CP500_RECFG_REQ 0x01 /* reconfigure FPGA on next reset */
+/* Bits in PRESENT_REG */
+#define CP500_PRESENT_FAN0 0x01
+
/* MSIX */
#define CP500_AXI_MSIX 3
+#define CP500_RFB_UART_MSIX 4
+#define CP500_DEBUG_UART_MSIX 5
+#define CP500_SI1_UART_MSIX 6
#define CP500_NUM_MSIX 8
#define CP500_NUM_MSIX_NO_MMI 2
#define CP500_NUM_MSIX_NO_AXI 3
/* EEPROM */
-#define CP500_HW_CPU_EEPROM_NAME "cp500_cpu_eeprom"
+#define CP500_EEPROM_DA_OFFSET 0x016F
+#define CP500_EEPROM_DA_ESC_TYPE_MASK 0x01
+#define CP500_EEPROM_ESC_LAN9252 0x00
+#define CP500_EEPROM_ESC_ET1100 0x01
+#define CP500_EEPROM_CPU_NAME "cpu_eeprom"
+#define CP500_EEPROM_CPU_OFFSET 0
+#define CP500_EEPROM_CPU_SIZE 3072
+#define CP500_EEPROM_USER_NAME "user_eeprom"
+#define CP500_EEPROM_USER_OFFSET 3072
+#define CP500_EEPROM_USER_SIZE 1024
+
+/* SPI flash running at full speed */
+#define CP500_FLASH_HZ (33 * 1000 * 1000)
+
+/* LAN9252 */
+#define CP500_LAN9252_HZ (10 * 1000 * 1000)
#define CP500_IS_CP035(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035)
#define CP500_IS_CP505(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505)
@@ -51,29 +78,56 @@
struct cp500_dev_info {
off_t offset;
size_t size;
+ unsigned int msix;
};
struct cp500_devs {
struct cp500_dev_info startup;
+ struct cp500_dev_info spi;
struct cp500_dev_info i2c;
+ struct cp500_dev_info fan;
+ struct cp500_dev_info batt;
+ struct cp500_dev_info uart0_rfb;
+ struct cp500_dev_info uart1_dbg;
+ struct cp500_dev_info uart2_si1;
};
/* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */
static struct cp500_devs cp035_devices = {
.startup = { 0x0000, SZ_4K },
+ .spi = { 0x1000, SZ_4K },
.i2c = { 0x4000, SZ_4K },
+ .fan = { 0x9000, SZ_4K },
+ .batt = { 0xA000, SZ_4K },
+ .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */
static struct cp500_devs cp505_devices = {
.startup = { 0x0000, SZ_4K },
+ .spi = { 0x4000, SZ_4K },
.i2c = { 0x5000, SZ_4K },
+ .fan = { 0x9000, SZ_4K },
+ .batt = { 0xA000, SZ_4K },
+ .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP520 family (CP520, CP530) */
static struct cp500_devs cp520_devices = {
- .startup = { 0x0000, SZ_4K },
- .i2c = { 0x5000, SZ_4K },
+ .startup = { 0x0000, SZ_4K },
+ .spi = { 0x4000, SZ_4K },
+ .i2c = { 0x5000, SZ_4K },
+ .fan = { 0x8000, SZ_4K },
+ .batt = { 0x9000, SZ_4K },
+ .uart0_rfb = { 0xC000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart1_dbg = { 0xD000, SZ_4K, CP500_DEBUG_UART_MSIX },
+};
+
+struct cp500_nvmem {
+ struct nvmem_device *nvmem;
+ unsigned int offset;
};
struct cp500 {
@@ -85,18 +139,31 @@ struct cp500 {
int minor;
int build;
} version;
+ struct notifier_block nvmem_notifier;
+ atomic_t nvmem_notified;
/* system FPGA BAR */
resource_size_t sys_hwbase;
+ struct keba_spi_auxdev *spi;
struct keba_i2c_auxdev *i2c;
+ struct keba_fan_auxdev *fan;
+ struct keba_batt_auxdev *batt;
+ struct keba_uart_auxdev *uart0_rfb;
+ struct keba_uart_auxdev *uart1_dbg;
+ struct keba_uart_auxdev *uart2_si1;
/* ECM EtherCAT BAR */
resource_size_t ecm_hwbase;
+ /* NVMEM devices */
+ struct cp500_nvmem nvmem_cpu;
+ struct cp500_nvmem nvmem_user;
+
void __iomem *system_startup_addr;
};
/* I2C devices */
+#define CP500_EEPROM_ADDR 0x50
static struct i2c_board_info cp500_i2c_info[] = {
{ /* temperature sensor */
I2C_BOARD_INFO("emc1403", 0x4c),
@@ -107,30 +174,66 @@ static struct i2c_board_info cp500_i2c_info[] = {
* CP505 family: bridge board
* CP520 family: carrier board
*/
- I2C_BOARD_INFO("24c32", 0x50),
- .dev_name = CP500_HW_CPU_EEPROM_NAME,
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR),
},
{ /* interface board EEPROM */
- I2C_BOARD_INFO("24c32", 0x51),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 1),
},
{ /*
* EEPROM (optional)
* CP505 family: CPU board
* CP520 family: MMI board
*/
- I2C_BOARD_INFO("24c32", 0x52),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 2),
},
{ /* extension module 0 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x53),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 3),
},
{ /* extension module 1 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x54),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 4),
},
{ /* extension module 2 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x55),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 5),
},
{ /* extension module 3 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x56),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 6),
+ }
+};
+
+/* SPI devices */
+static struct mtd_partition cp500_partitions[] = {
+ {
+ .name = "system-flash-parts",
+ .size = MTDPART_SIZ_FULL,
+ .offset = 0,
+ .mask_flags = 0
+ }
+};
+static const struct flash_platform_data cp500_w25q32 = {
+ .type = "w25q32",
+ .name = "system-flash",
+ .parts = cp500_partitions,
+ .nr_parts = ARRAY_SIZE(cp500_partitions),
+};
+static const struct flash_platform_data cp500_m25p16 = {
+ .type = "m25p16",
+ .name = "system-flash",
+ .parts = cp500_partitions,
+ .nr_parts = ARRAY_SIZE(cp500_partitions),
+};
+static struct spi_board_info cp500_spi_info[] = {
+ { /* system FPGA configuration bitstream flash */
+ .modalias = "m25p80",
+ .platform_data = &cp500_m25p16,
+ .max_speed_hz = CP500_FLASH_HZ,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ }, { /* LAN9252 EtherCAT slave controller */
+ .modalias = "lan9252",
+ .platform_data = NULL,
+ .max_speed_hz = CP500_LAN9252_HZ,
+ .chip_select = 1,
+ .mode = SPI_MODE_3,
}
};
@@ -229,7 +332,7 @@ static void cp500_i2c_release(struct device *dev)
static int cp500_register_i2c(struct cp500 *cp500)
{
- int retval;
+ int ret;
cp500->i2c = kzalloc(sizeof(*cp500->i2c), GFP_KERNEL);
if (!cp500->i2c)
@@ -251,30 +354,412 @@ static int cp500_register_i2c(struct cp500 *cp500)
cp500->i2c->info_size = ARRAY_SIZE(cp500_i2c_info);
cp500->i2c->info = cp500_i2c_info;
- retval = auxiliary_device_init(&cp500->i2c->auxdev);
- if (retval) {
+ ret = auxiliary_device_init(&cp500->i2c->auxdev);
+ if (ret) {
kfree(cp500->i2c);
cp500->i2c = NULL;
- return retval;
+ return ret;
}
- retval = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");
- if (retval) {
+ ret = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");
+ if (ret) {
auxiliary_device_uninit(&cp500->i2c->auxdev);
cp500->i2c = NULL;
- return retval;
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_spi_release(struct device *dev)
+{
+ struct keba_spi_auxdev *spi =
+ container_of(dev, struct keba_spi_auxdev, auxdev.dev);
+
+ kfree(spi);
+}
+
+static int cp500_register_spi(struct cp500 *cp500, u8 esc_type)
+{
+ int info_size;
+ int ret;
+
+ cp500->spi = kzalloc(sizeof(*cp500->spi), GFP_KERNEL);
+ if (!cp500->spi)
+ return -ENOMEM;
+
+ if (CP500_IS_CP035(cp500))
+ cp500_spi_info[0].platform_data = &cp500_w25q32;
+ if (esc_type == CP500_EEPROM_ESC_LAN9252)
+ info_size = ARRAY_SIZE(cp500_spi_info);
+ else
+ info_size = ARRAY_SIZE(cp500_spi_info) - 1;
+
+ cp500->spi->auxdev.name = "spi";
+ cp500->spi->auxdev.id = 0;
+ cp500->spi->auxdev.dev.release = cp500_spi_release;
+ cp500->spi->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->spi->io = (struct resource) {
+ /* SPI register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->spi.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->spi.offset +
+ cp500->devs->spi.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ cp500->spi->info_size = info_size;
+ cp500->spi->info = cp500_spi_info;
+
+ ret = auxiliary_device_init(&cp500->spi->auxdev);
+ if (ret) {
+ kfree(cp500->spi);
+ cp500->spi = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->spi->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->spi->auxdev);
+ cp500->spi = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_fan_release(struct device *dev)
+{
+ struct keba_fan_auxdev *fan =
+ container_of(dev, struct keba_fan_auxdev, auxdev.dev);
+
+ kfree(fan);
+}
+
+static int cp500_register_fan(struct cp500 *cp500)
+{
+ int ret;
+
+ cp500->fan = kzalloc(sizeof(*cp500->fan), GFP_KERNEL);
+ if (!cp500->fan)
+ return -ENOMEM;
+
+ cp500->fan->auxdev.name = "fan";
+ cp500->fan->auxdev.id = 0;
+ cp500->fan->auxdev.dev.release = cp500_fan_release;
+ cp500->fan->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->fan->io = (struct resource) {
+ /* fan register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->fan.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->fan.offset +
+ cp500->devs->fan.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+
+ ret = auxiliary_device_init(&cp500->fan->auxdev);
+ if (ret) {
+ kfree(cp500->fan);
+ cp500->fan = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->fan->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->fan->auxdev);
+ cp500->fan = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_batt_release(struct device *dev)
+{
+ struct keba_batt_auxdev *fan =
+ container_of(dev, struct keba_batt_auxdev, auxdev.dev);
+
+ kfree(fan);
+}
+
+static int cp500_register_batt(struct cp500 *cp500)
+{
+ int ret;
+
+ cp500->batt = kzalloc(sizeof(*cp500->batt), GFP_KERNEL);
+ if (!cp500->batt)
+ return -ENOMEM;
+
+ cp500->batt->auxdev.name = "batt";
+ cp500->batt->auxdev.id = 0;
+ cp500->batt->auxdev.dev.release = cp500_batt_release;
+ cp500->batt->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->batt->io = (struct resource) {
+ /* battery register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->batt.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->batt.offset +
+ cp500->devs->batt.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+
+ ret = auxiliary_device_init(&cp500->batt->auxdev);
+ if (ret) {
+ kfree(cp500->batt);
+ cp500->batt = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->batt->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->batt->auxdev);
+ cp500->batt = NULL;
+
+ return ret;
}
return 0;
}
+static void cp500_uart_release(struct device *dev)
+{
+ struct keba_uart_auxdev *uart =
+ container_of(dev, struct keba_uart_auxdev, auxdev.dev);
+
+ kfree(uart);
+}
+
+static int cp500_register_uart(struct cp500 *cp500,
+ struct keba_uart_auxdev **uart, const char *name,
+ struct cp500_dev_info *info, unsigned int irq)
+{
+ int ret;
+
+ *uart = kzalloc(sizeof(**uart), GFP_KERNEL);
+ if (!*uart)
+ return -ENOMEM;
+
+ (*uart)->auxdev.name = name;
+ (*uart)->auxdev.id = 0;
+ (*uart)->auxdev.dev.release = cp500_uart_release;
+ (*uart)->auxdev.dev.parent = &cp500->pci_dev->dev;
+ (*uart)->io = (struct resource) {
+ /* UART register area */
+ .start = (resource_size_t) cp500->sys_hwbase + info->offset,
+ .end = (resource_size_t) cp500->sys_hwbase + info->offset +
+ info->size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ (*uart)->irq = irq;
+
+ ret = auxiliary_device_init(&(*uart)->auxdev);
+ if (ret) {
+ kfree(*uart);
+ *uart = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&(*uart)->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&(*uart)->auxdev);
+ *uart = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cp500_nvmem_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct cp500_nvmem *nvmem = priv;
+ int ret;
+
+ ret = nvmem_device_read(nvmem->nvmem, nvmem->offset + offset, bytes,
+ val);
+ if (ret != bytes)
+ return ret;
+
+ return 0;
+}
+
+static int cp500_nvmem_write(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct cp500_nvmem *nvmem = priv;
+ int ret;
+
+ ret = nvmem_device_write(nvmem->nvmem, nvmem->offset + offset, bytes,
+ val);
+ if (ret != bytes)
+ return ret;
+
+ return 0;
+}
+
+static int cp500_nvmem_register(struct cp500 *cp500, struct nvmem_device *nvmem)
+{
+ struct device *dev = &cp500->pci_dev->dev;
+ struct nvmem_config nvmem_config = {};
+ struct nvmem_device *tmp;
+
+ /*
+ * The main EEPROM of CP500 devices is logically split into two EEPROMs.
+ * The first logical EEPROM with 3 kB contains the type label which is
+ * programmed during production of the device. The second logical EEPROM
+ * with 1 kB is not programmed during production and can be used for
+ * arbitrary user data.
+ */
+
+ nvmem_config.dev = dev;
+ nvmem_config.owner = THIS_MODULE;
+ nvmem_config.id = NVMEM_DEVID_NONE;
+ nvmem_config.type = NVMEM_TYPE_EEPROM;
+ nvmem_config.root_only = true;
+ nvmem_config.reg_read = cp500_nvmem_read;
+ nvmem_config.reg_write = cp500_nvmem_write;
+
+ cp500->nvmem_cpu.nvmem = nvmem;
+ cp500->nvmem_cpu.offset = CP500_EEPROM_CPU_OFFSET;
+ nvmem_config.name = CP500_EEPROM_CPU_NAME;
+ nvmem_config.size = CP500_EEPROM_CPU_SIZE;
+ nvmem_config.priv = &cp500->nvmem_cpu;
+ tmp = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ cp500->nvmem_user.nvmem = nvmem;
+ cp500->nvmem_user.offset = CP500_EEPROM_USER_OFFSET;
+ nvmem_config.name = CP500_EEPROM_USER_NAME;
+ nvmem_config.size = CP500_EEPROM_USER_SIZE;
+ nvmem_config.priv = &cp500->nvmem_user;
+ tmp = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ return 0;
+}
+
+static int cp500_nvmem_match(struct device *dev, const void *data)
+{
+ const struct cp500 *cp500 = data;
+ struct i2c_client *client;
+
+ /* match only CPU EEPROM below the cp500 device */
+ dev = dev->parent;
+ client = i2c_verify_client(dev);
+ if (!client || client->addr != CP500_EEPROM_ADDR)
+ return 0;
+ while ((dev = dev->parent))
+ if (dev == &cp500->pci_dev->dev)
+ return 1;
+
+ return 0;
+}
+
+static void cp500_devm_nvmem_put(void *data)
+{
+ struct nvmem_device *nvmem = data;
+
+ nvmem_device_put(nvmem);
+}
+
+static int cp500_nvmem(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct nvmem_device *nvmem;
+ struct cp500 *cp500;
+ struct device *dev;
+ int notified;
+ u8 esc_type;
+ int ret;
+
+ if (action != NVMEM_ADD)
+ return NOTIFY_DONE;
+ cp500 = container_of(nb, struct cp500, nvmem_notifier);
+ dev = &cp500->pci_dev->dev;
+
+ /* process CPU EEPROM content only once */
+ notified = atomic_read(&cp500->nvmem_notified);
+ if (notified)
+ return NOTIFY_DONE;
+ nvmem = nvmem_device_find(cp500, cp500_nvmem_match);
+ if (IS_ERR_OR_NULL(nvmem))
+ return NOTIFY_DONE;
+ if (!atomic_try_cmpxchg_relaxed(&cp500->nvmem_notified, &notified, 1)) {
+ nvmem_device_put(nvmem);
+
+ return NOTIFY_DONE;
+ }
+
+ ret = devm_add_action_or_reset(dev, cp500_devm_nvmem_put, nvmem);
+ if (ret)
+ return ret;
+
+ ret = cp500_nvmem_register(cp500, nvmem);
+ if (ret)
+ return ret;
+
+ ret = nvmem_device_read(nvmem, CP500_EEPROM_DA_OFFSET, sizeof(esc_type),
+ (void *)&esc_type);
+ if (ret != sizeof(esc_type)) {
+ dev_warn(dev, "Failed to read device assembly!\n");
+
+ return NOTIFY_DONE;
+ }
+ esc_type &= CP500_EEPROM_DA_ESC_TYPE_MASK;
+
+ if (cp500_register_spi(cp500, esc_type))
+ dev_warn(dev, "Failed to register SPI!\n");
+
+ return NOTIFY_OK;
+}
+
static void cp500_register_auxiliary_devs(struct cp500 *cp500)
{
struct device *dev = &cp500->pci_dev->dev;
+ u8 present = ioread8(cp500->system_startup_addr + CP500_PRESENT_REG);
if (cp500_register_i2c(cp500))
- dev_warn(dev, "Failed to register i2c!\n");
+ dev_warn(dev, "Failed to register I2C!\n");
+ if (present & CP500_PRESENT_FAN0)
+ if (cp500_register_fan(cp500))
+ dev_warn(dev, "Failed to register fan!\n");
+ if (cp500_register_batt(cp500))
+ dev_warn(dev, "Failed to register battery!\n");
+ if (cp500->devs->uart0_rfb.size &&
+ cp500->devs->uart0_rfb.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart0_rfb.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart0_rfb, "rs485-uart",
+ &cp500->devs->uart0_rfb, irq))
+ dev_warn(dev, "Failed to register RFB UART!\n");
+ }
+ if (cp500->devs->uart1_dbg.size &&
+ cp500->devs->uart1_dbg.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart1_dbg.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart1_dbg, "rs232-uart",
+ &cp500->devs->uart1_dbg, irq))
+ dev_warn(dev, "Failed to register debug UART!\n");
+ }
+ if (cp500->devs->uart2_si1.size &&
+ cp500->devs->uart2_si1.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart2_si1.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart2_si1, "uart",
+ &cp500->devs->uart2_si1, irq))
+ dev_warn(dev, "Failed to register SI1 UART!\n");
+ }
}
static void cp500_unregister_dev(struct auxiliary_device *auxdev)
@@ -285,11 +770,34 @@ static void cp500_unregister_dev(struct auxiliary_device *auxdev)
static void cp500_unregister_auxiliary_devs(struct cp500 *cp500)
{
-
+ if (cp500->spi) {
+ cp500_unregister_dev(&cp500->spi->auxdev);
+ cp500->spi = NULL;
+ }
if (cp500->i2c) {
cp500_unregister_dev(&cp500->i2c->auxdev);
cp500->i2c = NULL;
}
+ if (cp500->fan) {
+ cp500_unregister_dev(&cp500->fan->auxdev);
+ cp500->fan = NULL;
+ }
+ if (cp500->batt) {
+ cp500_unregister_dev(&cp500->batt->auxdev);
+ cp500->batt = NULL;
+ }
+ if (cp500->uart0_rfb) {
+ cp500_unregister_dev(&cp500->uart0_rfb->auxdev);
+ cp500->uart0_rfb = NULL;
+ }
+ if (cp500->uart1_dbg) {
+ cp500_unregister_dev(&cp500->uart1_dbg->auxdev);
+ cp500->uart1_dbg = NULL;
+ }
+ if (cp500->uart2_si1) {
+ cp500_unregister_dev(&cp500->uart2_si1->auxdev);
+ cp500->uart2_si1 = NULL;
+ }
}
static irqreturn_t cp500_axi_handler(int irq, void *dev)
@@ -396,15 +904,21 @@ static int cp500_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
pci_set_drvdata(pci_dev, cp500);
+ cp500->nvmem_notifier.notifier_call = cp500_nvmem;
+ ret = nvmem_register_notifier(&cp500->nvmem_notifier);
+ if (ret != 0)
+ goto out_free_irq;
ret = cp500_enable(cp500);
if (ret != 0)
- goto out_free_irq;
+ goto out_unregister_nvmem;
cp500_register_auxiliary_devs(cp500);
return 0;
+out_unregister_nvmem:
+ nvmem_unregister_notifier(&cp500->nvmem_notifier);
out_free_irq:
pci_free_irq_vectors(pci_dev);
out_disable:
@@ -422,6 +936,8 @@ static void cp500_remove(struct pci_dev *pci_dev)
cp500_disable(cp500);
+ nvmem_unregister_notifier(&cp500->nvmem_notifier);
+
pci_set_drvdata(pci_dev, 0);
pci_free_irq_vectors(pci_dev);
diff --git a/drivers/misc/keba/lan9252.c b/drivers/misc/keba/lan9252.c
new file mode 100644
index 000000000000..fc54afd1d05b
--- /dev/null
+++ b/drivers/misc/keba/lan9252.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) KEBA Industrial Automation Gmbh 2024
+ *
+ * Driver for LAN9252 on KEBA CP500 devices
+ *
+ * This driver is used for updating the configuration of the LAN9252 controller
+ * on KEBA CP500 devices. The LAN9252 is connected over SPI, which is also named
+ * PDI.
+ */
+
+#include <linux/spi/spi.h>
+#include <linux/mii.h>
+
+/* SPI commands */
+#define LAN9252_SPI_READ 0x3
+#define LAN9252_SPI_WRITE 0x2
+
+struct lan9252_read_cmd {
+ u8 cmd;
+ u8 addr_0;
+ u8 addr_1;
+} __packed;
+
+struct lan9252_write_cmd {
+ u8 cmd;
+ u8 addr_0;
+ u8 addr_1;
+ u32 data;
+} __packed;
+
+/* byte test register */
+#define LAN9252_BYTE_TEST 0x64
+#define LAN9252_BYTE_TEST_VALUE 0x87654321
+
+/* hardware configuration register */
+#define LAN9252_HW_CFG 0x74
+#define LAN9252_HW_CFG_READY 0x08000000
+
+/* EtherCAT CSR interface data register */
+#define LAN9252_ECAT_CSR_DATA 0x300
+
+/* EtherCAT CSR interface command register */
+#define LAN9252_ECAT_CSR_CMD 0x304
+#define LAN9252_ECAT_CSR_BUSY 0x80000000
+#define LAN9252_ECAT_CSR_READ 0x40000000
+
+/* EtherCAT slave controller MII register */
+#define LAN9252_ESC_MII 0x510
+#define LAN9252_ESC_MII_BUSY 0x8000
+#define LAN9252_ESC_MII_CMD_ERR 0x4000
+#define LAN9252_ESC_MII_READ_ERR 0x2000
+#define LAN9252_ESC_MII_ERR_MASK (LAN9252_ESC_MII_CMD_ERR | \
+ LAN9252_ESC_MII_READ_ERR)
+#define LAN9252_ESC_MII_WRITE 0x0200
+#define LAN9252_ESC_MII_READ 0x0100
+
+/* EtherCAT slave controller PHY address register */
+#define LAN9252_ESC_PHY_ADDR 0x512
+
+/* EtherCAT slave controller PHY register address register */
+#define LAN9252_ESC_PHY_REG_ADDR 0x513
+
+/* EtherCAT slave controller PHY data register */
+#define LAN9252_ESC_PHY_DATA 0x514
+
+/* EtherCAT slave controller PDI access state register */
+#define LAN9252_ESC_MII_PDI 0x517
+#define LAN9252_ESC_MII_ACCESS_PDI 0x01
+#define LAN9252_ESC_MII_ACCESS_ECAT 0x00
+
+/* PHY address */
+#define PHY_ADDRESS 2
+
+#define SPI_RETRY_COUNT 10
+#define SPI_WAIT_US 100
+#define SPI_CSR_WAIT_US 500
+
+static int lan9252_spi_read(struct spi_device *spi, u16 addr, u32 *data)
+{
+ struct lan9252_read_cmd cmd;
+
+ cmd.cmd = LAN9252_SPI_READ;
+ cmd.addr_0 = (addr >> 8) & 0xFF;
+ cmd.addr_1 = addr & 0xFF;
+
+ return spi_write_then_read(spi, (u8 *)&cmd,
+ sizeof(struct lan9252_read_cmd),
+ (u8 *)data, sizeof(u32));
+}
+
+static int lan9252_spi_write(struct spi_device *spi, u16 addr, u32 data)
+{
+ struct lan9252_write_cmd cmd;
+
+ cmd.cmd = LAN9252_SPI_WRITE;
+ cmd.addr_0 = (addr >> 8) & 0xFF;
+ cmd.addr_1 = addr & 0xFF;
+ cmd.data = data;
+
+ return spi_write(spi, (u8 *)&cmd, sizeof(struct lan9252_write_cmd));
+}
+
+static bool lan9252_init(struct spi_device *spi)
+{
+ u32 data;
+ int ret;
+
+ ret = lan9252_spi_read(spi, LAN9252_BYTE_TEST, &data);
+ if (ret || data != LAN9252_BYTE_TEST_VALUE)
+ return false;
+
+ ret = lan9252_spi_read(spi, LAN9252_HW_CFG, &data);
+ if (ret || !(data & LAN9252_HW_CFG_READY))
+ return false;
+
+ return true;
+}
+
+static u8 lan9252_esc_get_size(u16 addr)
+{
+ if (addr == LAN9252_ESC_MII || addr == LAN9252_ESC_PHY_DATA)
+ return 2;
+
+ return 1;
+}
+
+static int lan9252_esc_wait(struct spi_device *spi)
+{
+ ktime_t timeout = ktime_add_us(ktime_get(), SPI_WAIT_US);
+ u32 data;
+ int ret;
+
+ /* wait while CSR command is busy */
+ for (;;) {
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data);
+ if (ret)
+ return ret;
+ if (!(data & LAN9252_ECAT_CSR_BUSY))
+ return 0;
+
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data);
+ if (ret)
+ return ret;
+ break;
+ }
+ }
+
+ return (!(data & LAN9252_ECAT_CSR_BUSY)) ? 0 : -ETIMEDOUT;
+}
+
+static int lan9252_esc_read(struct spi_device *spi, u16 addr, u32 *data)
+{
+ u32 csr_cmd;
+ u8 size;
+ int ret;
+
+ size = lan9252_esc_get_size(addr);
+ csr_cmd = LAN9252_ECAT_CSR_BUSY | LAN9252_ECAT_CSR_READ;
+ csr_cmd |= (size << 16) | addr;
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_wait(spi);
+ if (ret)
+ return ret;
+
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_DATA, data);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lan9252_esc_write(struct spi_device *spi, u16 addr, u32 data)
+{
+ u32 csr_cmd;
+ u8 size;
+ int ret;
+
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_DATA, data);
+ if (ret)
+ return ret;
+
+ size = lan9252_esc_get_size(addr);
+ csr_cmd = LAN9252_ECAT_CSR_BUSY;
+ csr_cmd |= (size << 16) | addr;
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_wait(spi);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lan9252_access_mii(struct spi_device *spi, bool access)
+{
+ u32 data;
+
+ if (access)
+ data = LAN9252_ESC_MII_ACCESS_PDI;
+ else
+ data = LAN9252_ESC_MII_ACCESS_ECAT;
+
+ return lan9252_esc_write(spi, LAN9252_ESC_MII_PDI, data);
+}
+
+static int lan9252_mii_wait(struct spi_device *spi)
+{
+ ktime_t timeout = ktime_add_us(ktime_get(), SPI_CSR_WAIT_US);
+ u32 data;
+ int ret;
+
+ /* wait while MII control state machine is busy */
+ for (;;) {
+ ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data);
+ if (ret)
+ return ret;
+ if (data & LAN9252_ESC_MII_ERR_MASK)
+ return -EIO;
+ if (!(data & LAN9252_ESC_MII_BUSY))
+ return 0;
+
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data);
+ if (ret)
+ return ret;
+ if (data & LAN9252_ESC_MII_ERR_MASK)
+ return -EIO;
+ break;
+ }
+ }
+
+ return (!(data & LAN9252_ESC_MII_BUSY)) ? 0 : -ETIMEDOUT;
+}
+
+static int lan9252_mii_read(struct spi_device *spi, u8 phy_addr, u8 reg_addr,
+ u32 *data)
+{
+ int ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_READ);
+ if (ret)
+ return ret;
+
+ ret = lan9252_mii_wait(spi);
+ if (ret)
+ return ret;
+
+ return lan9252_esc_read(spi, LAN9252_ESC_PHY_DATA, data);
+}
+
+static int lan9252_mii_write(struct spi_device *spi, u8 phy_addr, u8 reg_addr,
+ u32 data)
+{
+ int ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_DATA, data);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_WRITE);
+ if (ret)
+ return ret;
+
+ return lan9252_mii_wait(spi);
+}
+
+static int lan9252_probe(struct spi_device *spi)
+{
+ u32 data;
+ int retry = SPI_RETRY_COUNT;
+ int ret;
+
+ /* execute specified initialization sequence */
+ while (retry && !lan9252_init(spi))
+ retry--;
+ if (retry == 0) {
+ dev_err(&spi->dev,
+ "Can't initialize LAN9252 SPI communication!");
+ return -EIO;
+ }
+
+ /* enable access to MII management for PDI */
+ ret = lan9252_access_mii(spi, true);
+ if (ret) {
+ dev_err(&spi->dev, "Can't enable access to MII management!");
+ return ret;
+ }
+
+ /*
+ * check PHY configuration and configure if necessary
+ * - full duplex
+ * - auto negotiation disabled
+ * - 100 Mbps
+ */
+ ret = lan9252_mii_read(spi, PHY_ADDRESS, MII_BMCR, &data);
+ if (ret) {
+ dev_err(&spi->dev, "Can't read LAN9252 configuration!");
+ goto out;
+ }
+ if (!(data & BMCR_FULLDPLX) || (data & BMCR_ANENABLE) ||
+ !(data & BMCR_SPEED100)) {
+ /*
+ */
+ data &= ~(BMCR_ANENABLE);
+ data |= (BMCR_FULLDPLX | BMCR_SPEED100);
+ ret = lan9252_mii_write(spi, PHY_ADDRESS, MII_BMCR, data);
+ if (ret)
+ dev_err(&spi->dev,
+ "Can't write LAN9252 configuration!");
+ }
+
+ dev_info(&spi->dev, "LAN9252 PHY configuration");
+
+out:
+ /* disable access to MII management for PDI */
+ lan9252_access_mii(spi, false);
+
+ return ret;
+}
+
+static const struct spi_device_id lan9252_id[] = {
+ {"lan9252"},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, lan9252_id);
+
+static struct spi_driver lan9252_driver = {
+ .driver = {
+ .name = "lan9252",
+ },
+ .probe = lan9252_probe,
+ .id_table = lan9252_id,
+};
+module_spi_driver(lan9252_driver);
+
+MODULE_AUTHOR("Petar Bojanic <boja@keba.com>");
+MODULE_AUTHOR("Gerhard Engleder <eg@keba.com>");
+MODULE_DESCRIPTION("KEBA LAN9252 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/lan966x_pci.c b/drivers/misc/lan966x_pci.c
new file mode 100644
index 000000000000..9c79b58137e5
--- /dev/null
+++ b/drivers/misc/lan966x_pci.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip LAN966x PCI driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries.
+ *
+ * Authors:
+ * Clément Léger <clement.leger@bootlin.com>
+ * Hervé Codina <herve.codina@bootlin.com>
+ */
+
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+
+/* Embedded dtbo symbols created by cmd_wrap_S_dtb in scripts/Makefile.lib */
+extern char __dtbo_lan966x_pci_begin[];
+extern char __dtbo_lan966x_pci_end[];
+
+struct pci_dev_intr_ctrl {
+ struct pci_dev *pci_dev;
+ struct irq_domain *irq_domain;
+ int irq;
+};
+
+static int pci_dev_irq_domain_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq);
+ return 0;
+}
+
+static const struct irq_domain_ops pci_dev_irq_domain_ops = {
+ .map = pci_dev_irq_domain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static irqreturn_t pci_dev_irq_handler(int irq, void *data)
+{
+ struct pci_dev_intr_ctrl *intr_ctrl = data;
+ int ret;
+
+ ret = generic_handle_domain_irq(intr_ctrl->irq_domain, 0);
+ return ret ? IRQ_NONE : IRQ_HANDLED;
+}
+
+static struct pci_dev_intr_ctrl *pci_dev_create_intr_ctrl(struct pci_dev *pdev)
+{
+ struct pci_dev_intr_ctrl *intr_ctrl __free(kfree) = NULL;
+ struct fwnode_handle *fwnode;
+ int ret;
+
+ fwnode = dev_fwnode(&pdev->dev);
+ if (!fwnode)
+ return ERR_PTR(-ENODEV);
+
+ intr_ctrl = kmalloc(sizeof(*intr_ctrl), GFP_KERNEL);
+ if (!intr_ctrl)
+ return ERR_PTR(-ENOMEM);
+
+ intr_ctrl->pci_dev = pdev;
+
+ intr_ctrl->irq_domain = irq_domain_create_linear(fwnode, 1, &pci_dev_irq_domain_ops,
+ intr_ctrl);
+ if (!intr_ctrl->irq_domain) {
+ pci_err(pdev, "Failed to create irqdomain\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX);
+ if (ret < 0) {
+ pci_err(pdev, "Unable alloc irq vector (%d)\n", ret);
+ goto err_remove_domain;
+ }
+ intr_ctrl->irq = pci_irq_vector(pdev, 0);
+ ret = request_irq(intr_ctrl->irq, pci_dev_irq_handler, IRQF_SHARED,
+ pci_name(pdev), intr_ctrl);
+ if (ret) {
+ pci_err(pdev, "Unable to request irq %d (%d)\n", intr_ctrl->irq, ret);
+ goto err_free_irq_vector;
+ }
+
+ return_ptr(intr_ctrl);
+
+err_free_irq_vector:
+ pci_free_irq_vectors(pdev);
+err_remove_domain:
+ irq_domain_remove(intr_ctrl->irq_domain);
+ return ERR_PTR(ret);
+}
+
+static void pci_dev_remove_intr_ctrl(struct pci_dev_intr_ctrl *intr_ctrl)
+{
+ free_irq(intr_ctrl->irq, intr_ctrl);
+ pci_free_irq_vectors(intr_ctrl->pci_dev);
+ irq_dispose_mapping(irq_find_mapping(intr_ctrl->irq_domain, 0));
+ irq_domain_remove(intr_ctrl->irq_domain);
+ kfree(intr_ctrl);
+}
+
+static void devm_pci_dev_remove_intr_ctrl(void *intr_ctrl)
+{
+ pci_dev_remove_intr_ctrl(intr_ctrl);
+}
+
+static int devm_pci_dev_create_intr_ctrl(struct pci_dev *pdev)
+{
+ struct pci_dev_intr_ctrl *intr_ctrl;
+
+ intr_ctrl = pci_dev_create_intr_ctrl(pdev);
+ if (IS_ERR(intr_ctrl))
+ return PTR_ERR(intr_ctrl);
+
+ return devm_add_action_or_reset(&pdev->dev, devm_pci_dev_remove_intr_ctrl, intr_ctrl);
+}
+
+struct lan966x_pci {
+ struct device *dev;
+ int ovcs_id;
+};
+
+static int lan966x_pci_load_overlay(struct lan966x_pci *data)
+{
+ u32 dtbo_size = __dtbo_lan966x_pci_end - __dtbo_lan966x_pci_begin;
+ void *dtbo_start = __dtbo_lan966x_pci_begin;
+
+ return of_overlay_fdt_apply(dtbo_start, dtbo_size, &data->ovcs_id, dev_of_node(data->dev));
+}
+
+static void lan966x_pci_unload_overlay(struct lan966x_pci *data)
+{
+ of_overlay_remove(&data->ovcs_id);
+}
+
+static int lan966x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct device *dev = &pdev->dev;
+ struct lan966x_pci *data;
+ int ret;
+
+ /*
+ * On ACPI system, fwnode can point to the ACPI node.
+ * This driver needs an of_node to be used as the device-tree overlay
+ * target. This of_node should be set by the PCI core if it succeeds in
+ * creating it (CONFIG_PCI_DYNAMIC_OF_NODES feature).
+ * Check here for the validity of this of_node.
+ */
+ if (!dev_of_node(dev))
+ return dev_err_probe(dev, -EINVAL, "Missing of_node for device\n");
+
+ /* Need to be done before devm_pci_dev_create_intr_ctrl.
+ * It allocates an IRQ and so pdev->irq is updated.
+ */
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ ret = devm_pci_dev_create_intr_ctrl(pdev);
+ if (ret)
+ return ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ pci_set_drvdata(pdev, data);
+ data->dev = dev;
+
+ ret = lan966x_pci_load_overlay(data);
+ if (ret)
+ return ret;
+
+ pci_set_master(pdev);
+
+ ret = of_platform_default_populate(dev_of_node(dev), NULL, dev);
+ if (ret)
+ goto err_unload_overlay;
+
+ return 0;
+
+err_unload_overlay:
+ lan966x_pci_unload_overlay(data);
+ return ret;
+}
+
+static void lan966x_pci_remove(struct pci_dev *pdev)
+{
+ struct lan966x_pci *data = pci_get_drvdata(pdev);
+
+ of_platform_depopulate(data->dev);
+
+ lan966x_pci_unload_overlay(data);
+}
+
+static struct pci_device_id lan966x_pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_EFAR, 0x9660) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, lan966x_pci_ids);
+
+static struct pci_driver lan966x_pci_driver = {
+ .name = "mchp_lan966x_pci",
+ .id_table = lan966x_pci_ids,
+ .probe = lan966x_pci_probe,
+ .remove = lan966x_pci_remove,
+};
+module_pci_driver(lan966x_pci_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("Microchip LAN966x PCI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/lan966x_pci.dtso b/drivers/misc/lan966x_pci.dtso
new file mode 100644
index 000000000000..7b196b0a0eb6
--- /dev/null
+++ b/drivers/misc/lan966x_pci.dtso
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Microchip UNG
+ */
+
+#include <dt-bindings/clock/microchip,lan966x.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/mfd/atmel-flexcom.h>
+#include <dt-bindings/phy/phy-lan966x-serdes.h>
+
+/dts-v1/;
+/plugin/;
+
+/ {
+ fragment@0 {
+ target-path = "";
+
+ /*
+ * These properties allow to avoid a dtc warnings.
+ * The real interrupt controller is the PCI device itself. It
+ * is the node on which the device tree overlay will be applied.
+ * This node has those properties.
+ */
+ #interrupt-cells = <1>;
+ interrupt-controller;
+
+ __overlay__ {
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ cpu_clk: clock-600000000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <600000000>; /* CPU clock = 600MHz */
+ };
+
+ ddr_clk: clock-30000000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>; /* Fabric clock = 30MHz */
+ };
+
+ sys_clk: clock-15625000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <15625000>; /* System clock = 15.625MHz */
+ };
+
+ pci-ep-bus@0 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /*
+ * map @0xe2000000 (32MB) to BAR0 (CPU)
+ * map @0xe0000000 (16MB) to BAR1 (AMBA)
+ */
+ ranges = <0xe2000000 0x00 0x00 0x00 0x2000000
+ 0xe0000000 0x01 0x00 0x00 0x1000000>;
+
+ oic: oic@e00c0120 {
+ compatible = "microchip,lan966x-oic";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupts = <0>; /* PCI INTx assigned interrupt */
+ reg = <0xe00c0120 0x190>;
+ };
+
+ cpu_ctrl: syscon@e00c0000 {
+ compatible = "microchip,lan966x-cpu-syscon", "syscon";
+ reg = <0xe00c0000 0xa8>;
+ };
+
+ reset: reset@e200400c {
+ compatible = "microchip,lan966x-switch-reset";
+ reg = <0xe200400c 0x4>, <0xe00c0000 0xa8>;
+ reg-names = "gcb","cpu";
+ #reset-cells = <1>;
+ cpu-syscon = <&cpu_ctrl>;
+ };
+
+ gpio: pinctrl@e2004064 {
+ compatible = "microchip,lan966x-pinctrl";
+ reg = <0xe2004064 0xb4>,
+ <0xe2010024 0x138>;
+ resets = <&reset 0>;
+ reset-names = "switch";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&gpio 0 0 78>;
+ interrupt-parent = <&oic>;
+ interrupt-controller;
+ interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <2>;
+
+ tod_pins: tod_pins {
+ pins = "GPIO_36";
+ function = "ptpsync_1";
+ };
+
+ fc0_a_pins: fcb4-i2c-pins {
+ /* RXD, TXD */
+ pins = "GPIO_9", "GPIO_10";
+ function = "fc0_a";
+ };
+
+ };
+
+ serdes: serdes@e202c000 {
+ compatible = "microchip,lan966x-serdes";
+ reg = <0xe202c000 0x9c>,
+ <0xe2004010 0x4>;
+ #phy-cells = <2>;
+ };
+
+ mdio1: mdio@e200413c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "microchip,lan966x-miim";
+ reg = <0xe200413c 0x24>,
+ <0xe2010020 0x4>;
+
+ resets = <&reset 0>;
+ reset-names = "switch";
+
+ lan966x_phy0: ethernet-lan966x_phy@1 {
+ reg = <1>;
+ };
+
+ lan966x_phy1: ethernet-lan966x_phy@2 {
+ reg = <2>;
+ };
+ };
+
+ switch: switch@e0000000 {
+ compatible = "microchip,lan966x-switch";
+ reg = <0xe0000000 0x0100000>,
+ <0xe2000000 0x0800000>;
+ reg-names = "cpu", "gcb";
+
+ interrupt-parent = <&oic>;
+ interrupts = <12 IRQ_TYPE_LEVEL_HIGH>,
+ <9 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "xtr", "ana";
+
+ resets = <&reset 0>;
+ reset-names = "switch";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&tod_pins>;
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port0: port@0 {
+ phy-handle = <&lan966x_phy0>;
+
+ reg = <0>;
+ phy-mode = "gmii";
+ phys = <&serdes 0 CU(0)>;
+ };
+
+ port1: port@1 {
+ phy-handle = <&lan966x_phy1>;
+
+ reg = <1>;
+ phy-mode = "gmii";
+ phys = <&serdes 1 CU(1)>;
+ };
+ };
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index 62ba01525479..376047beea3d 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -445,7 +445,7 @@ static void lkdtm_FAM_BOUNDS(void)
pr_err("FAIL: survived access of invalid flexible array member index!\n");
- if (!__has_attribute(__counted_by__))
+ if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY))
pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by\n",
lkdtm_kernel_info);
else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS))
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 5576146ab13b..718ec5d81d94 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -145,8 +145,8 @@ out:
* @cl: host client
* @buf: buffer to receive
* @length: buffer length
- * @mode: io mode
* @vtag: virtual tag
+ * @mode: io mode
* @timeout: recv timeout, 0 for infinite timeout
*
* Return: read size in bytes of < 0 on error
diff --git a/drivers/misc/mei/platform-vsc.c b/drivers/misc/mei/platform-vsc.c
index 20a11b299bcd..71f9994da2cc 100644
--- a/drivers/misc/mei/platform-vsc.c
+++ b/drivers/misc/mei/platform-vsc.c
@@ -256,8 +256,6 @@ static int mei_vsc_hw_reset(struct mei_device *mei_dev, bool intr_enable)
vsc_tp_reset(hw->tp);
- vsc_tp_intr_disable(hw->tp);
-
return vsc_tp_init(hw->tp, mei_dev->dev);
}
diff --git a/drivers/misc/mei/vsc-fw-loader.c b/drivers/misc/mei/vsc-fw-loader.c
index 9f129bc641f6..308b090d81bb 100644
--- a/drivers/misc/mei/vsc-fw-loader.c
+++ b/drivers/misc/mei/vsc-fw-loader.c
@@ -317,28 +317,34 @@ static int vsc_identify_silicon(struct vsc_fw_loader *fw_loader)
cmd->data.dump_mem.addr = cpu_to_le32(VSC_EFUSE_ADDR);
cmd->data.dump_mem.len = cpu_to_le16(sizeof(__le32));
ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
- if (ret)
- return ret;
- if (ack->token == VSC_TOKEN_ERROR)
- return -EINVAL;
+ if (ret || ack->token == VSC_TOKEN_ERROR) {
+ dev_err(fw_loader->dev, "CMD_DUMP_MEM error %d token %d\n", ret, ack->token);
+ return ret ?: -EINVAL;
+ }
cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
cmd->cmd_id = VSC_CMD_GET_CONT;
ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
- if (ret)
- return ret;
- if (ack->token != VSC_TOKEN_DUMP_RESP)
- return -EINVAL;
+ if (ret || ack->token != VSC_TOKEN_DUMP_RESP) {
+ dev_err(fw_loader->dev, "CMD_GETCONT error %d token %d\n", ret, ack->token);
+ return ret ?: -EINVAL;
+ }
version = FIELD_GET(VSC_MAINSTEPPING_VERSION_MASK, ack->payload[0]);
sub_version = FIELD_GET(VSC_SUBSTEPPING_VERSION_MASK, ack->payload[0]);
- if (version != VSC_MAINSTEPPING_VERSION_A)
+ if (version != VSC_MAINSTEPPING_VERSION_A) {
+ dev_err(fw_loader->dev, "mainstepping mismatch expected %d got %d\n",
+ VSC_MAINSTEPPING_VERSION_A, version);
return -EINVAL;
+ }
if (sub_version != VSC_SUBSTEPPING_VERSION_0 &&
- sub_version != VSC_SUBSTEPPING_VERSION_1)
+ sub_version != VSC_SUBSTEPPING_VERSION_1) {
+ dev_err(fw_loader->dev, "substepping %d is out of supported range %d - %d\n",
+ sub_version, VSC_SUBSTEPPING_VERSION_0, VSC_SUBSTEPPING_VERSION_1);
return -EINVAL;
+ }
dev_info(fw_loader->dev, "silicon stepping version is %u:%u\n",
version, sub_version);
diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
index 1618cca9a731..107177b05dcd 100644
--- a/drivers/misc/mei/vsc-tp.c
+++ b/drivers/misc/mei/vsc-tp.c
@@ -364,8 +364,6 @@ void vsc_tp_reset(struct vsc_tp *tp)
gpiod_set_value_cansleep(tp->wakeupfw, 1);
atomic_set(&tp->assert_cnt, 0);
-
- enable_irq(tp->spi->irq);
}
EXPORT_SYMBOL_NS_GPL(vsc_tp_reset, VSC_TP);
diff --git a/drivers/misc/ocxl/sysfs.c b/drivers/misc/ocxl/sysfs.c
index 405180d47d9b..07520d6e6dc5 100644
--- a/drivers/misc/ocxl/sysfs.c
+++ b/drivers/misc/ocxl/sysfs.c
@@ -125,7 +125,7 @@ static const struct vm_operations_struct global_mmio_vmops = {
};
static int global_mmio_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
struct vm_area_struct *vma)
{
struct ocxl_afu *afu = to_afu(kobj_to_dev(kobj));
diff --git a/drivers/misc/rpmb-core.c b/drivers/misc/rpmb-core.c
index bc68cde1a8bf..2d653926cdbb 100644
--- a/drivers/misc/rpmb-core.c
+++ b/drivers/misc/rpmb-core.c
@@ -13,7 +13,6 @@
#include <linux/slab.h>
static DEFINE_IDA(rpmb_ida);
-static DEFINE_MUTEX(rpmb_mutex);
/**
* rpmb_dev_get() - increase rpmb device ref counter
@@ -63,9 +62,7 @@ static void rpmb_dev_release(struct device *dev)
{
struct rpmb_dev *rdev = to_rpmb_dev(dev);
- mutex_lock(&rpmb_mutex);
- ida_simple_remove(&rpmb_ida, rdev->id);
- mutex_unlock(&rpmb_mutex);
+ ida_free(&rpmb_ida, rdev->id);
kfree(rdev->descr.dev_id);
kfree(rdev);
}
@@ -175,9 +172,7 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
goto err_free_rdev;
}
- mutex_lock(&rpmb_mutex);
- ret = ida_simple_get(&rpmb_ida, 0, 0, GFP_KERNEL);
- mutex_unlock(&rpmb_mutex);
+ ret = ida_alloc(&rpmb_ida, GFP_KERNEL);
if (ret < 0)
goto err_free_dev_id;
rdev->id = ret;
diff --git a/drivers/misc/ti-st/Kconfig b/drivers/misc/ti-st/Kconfig
deleted file mode 100644
index 1503a6496f63..000000000000
--- a/drivers/misc/ti-st/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# TI's shared transport line discipline and the protocol
-# drivers (BT, FM and GPS)
-#
-menu "Texas Instruments shared transport line discipline"
-config TI_ST
- tristate "Shared transport core driver"
- depends on NET && TTY
- depends on GPIOLIB || COMPILE_TEST
- select FW_LOADER
- help
- This enables the shared transport core driver for TI
- BT / FM and GPS combo chips. This enables protocol drivers
- to register themselves with core and send data, the responses
- are returned to relevant protocol drivers based on their
- packet types.
-
-endmenu
diff --git a/drivers/misc/ti-st/Makefile b/drivers/misc/ti-st/Makefile
deleted file mode 100644
index 93393100952e..000000000000
--- a/drivers/misc/ti-st/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for TI's shared transport line discipline
-# and its protocol drivers (BT, FM, GPS)
-#
-obj-$(CONFIG_TI_ST) += st_drv.o
-st_drv-objs := st_core.o st_kim.o st_ll.o
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
deleted file mode 100644
index b878431553ab..000000000000
--- a/drivers/misc/ti-st/st_core.c
+++ /dev/null
@@ -1,918 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport Line discipline driver Core
- * This hooks up ST KIM driver and ST LL driver
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stc): " fmt
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-
-#include <linux/seq_file.h>
-#include <linux/skbuff.h>
-
-#include <linux/ti_wilink_st.h>
-#include <linux/netdevice.h>
-
-/*
- * function pointer pointing to either,
- * st_kim_recv during registration to receive fw download responses
- * st_int_recv after registration to receive proto stack responses
- */
-static void (*st_recv)(void *disc_data, const u8 *ptr, size_t count);
-
-/********************************************************************/
-static void add_channel_to_table(struct st_data_s *st_gdata,
- struct st_proto_s *new_proto)
-{
- pr_info("%s: id %d\n", __func__, new_proto->chnl_id);
- /* list now has the channel id as index itself */
- st_gdata->list[new_proto->chnl_id] = new_proto;
- st_gdata->is_registered[new_proto->chnl_id] = true;
-}
-
-static void remove_channel_from_table(struct st_data_s *st_gdata,
- struct st_proto_s *proto)
-{
- pr_info("%s: id %d\n", __func__, proto->chnl_id);
-/* st_gdata->list[proto->chnl_id] = NULL; */
- st_gdata->is_registered[proto->chnl_id] = false;
-}
-
-/*
- * called from KIM during firmware download.
- *
- * This is a wrapper function to tty->ops->write_room.
- * It returns number of free space available in
- * uart tx buffer.
- */
-int st_get_uart_wr_room(struct st_data_s *st_gdata)
-{
- if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
- pr_err("tty unavailable to perform write");
- return -1;
- }
-
- return tty_write_room(st_gdata->tty);
-}
-
-/*
- * can be called in from
- * -- KIM (during fw download)
- * -- ST Core (during st_write)
- *
- * This is the internal write function - a wrapper
- * to tty->ops->write
- */
-int st_int_write(struct st_data_s *st_gdata,
- const unsigned char *data, int count)
-{
- struct tty_struct *tty;
- if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
- pr_err("tty unavailable to perform write");
- return -EINVAL;
- }
- tty = st_gdata->tty;
-#ifdef VERBOSE
- print_hex_dump(KERN_DEBUG, "<out<", DUMP_PREFIX_NONE,
- 16, 1, data, count, 0);
-#endif
- return tty->ops->write(tty, data, count);
-
-}
-
-/*
- * push the skb received to relevant
- * protocol stacks
- */
-static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
-{
- pr_debug(" %s(prot:%d) ", __func__, chnl_id);
-
- if (unlikely
- (st_gdata == NULL || st_gdata->rx_skb == NULL
- || st_gdata->is_registered[chnl_id] == false)) {
- pr_err("chnl_id %d not registered, no data to send?",
- chnl_id);
- kfree_skb(st_gdata->rx_skb);
- return;
- }
- /*
- * this cannot fail
- * this shouldn't take long
- * - should be just skb_queue_tail for the
- * protocol stack driver
- */
- if (likely(st_gdata->list[chnl_id]->recv != NULL)) {
- if (unlikely
- (st_gdata->list[chnl_id]->recv
- (st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb)
- != 0)) {
- pr_err(" proto stack %d's ->recv failed", chnl_id);
- kfree_skb(st_gdata->rx_skb);
- return;
- }
- } else {
- pr_err(" proto stack %d's ->recv null", chnl_id);
- kfree_skb(st_gdata->rx_skb);
- }
- return;
-}
-
-/*
- * st_reg_complete - to call registration complete callbacks
- * of all protocol stack drivers
- * This function is being called with spin lock held, protocol drivers are
- * only expected to complete their waits and do nothing more than that.
- */
-static void st_reg_complete(struct st_data_s *st_gdata, int err)
-{
- unsigned char i = 0;
- pr_info(" %s ", __func__);
- for (i = 0; i < ST_MAX_CHANNELS; i++) {
- if (likely(st_gdata != NULL &&
- st_gdata->is_registered[i] == true &&
- st_gdata->list[i]->reg_complete_cb != NULL)) {
- st_gdata->list[i]->reg_complete_cb
- (st_gdata->list[i]->priv_data, err);
- pr_info("protocol %d's cb sent %d\n", i, err);
- if (err) { /* cleanup registered protocol */
- st_gdata->is_registered[i] = false;
- if (st_gdata->protos_registered)
- st_gdata->protos_registered--;
- }
- }
- }
-}
-
-static inline int st_check_data_len(struct st_data_s *st_gdata,
- unsigned char chnl_id, int len)
-{
- int room = skb_tailroom(st_gdata->rx_skb);
-
- pr_debug("len %d room %d", len, room);
-
- if (!len) {
- /*
- * Received packet has only packet header and
- * has zero length payload. So, ask ST CORE to
- * forward the packet to protocol driver (BT/FM/GPS)
- */
- st_send_frame(chnl_id, st_gdata);
-
- } else if (len > room) {
- /*
- * Received packet's payload length is larger.
- * We can't accommodate it in created skb.
- */
- pr_err("Data length is too large len %d room %d", len,
- room);
- kfree_skb(st_gdata->rx_skb);
- } else {
- /*
- * Packet header has non-zero payload length and
- * we have enough space in created skb. Lets read
- * payload data */
- st_gdata->rx_state = ST_W4_DATA;
- st_gdata->rx_count = len;
- return len;
- }
-
- /* Change ST state to continue to process next packet */
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- st_gdata->rx_skb = NULL;
- st_gdata->rx_count = 0;
- st_gdata->rx_chnl = 0;
-
- return 0;
-}
-
-/*
- * st_wakeup_ack - internal function for action when wake-up ack
- * received
- */
-static inline void st_wakeup_ack(struct st_data_s *st_gdata,
- unsigned char cmd)
-{
- struct sk_buff *waiting_skb;
- unsigned long flags = 0;
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /*
- * de-Q from waitQ and Q in txQ now that the
- * chip is awake
- */
- while ((waiting_skb = skb_dequeue(&st_gdata->tx_waitq)))
- skb_queue_tail(&st_gdata->txq, waiting_skb);
-
- /* state forwarded to ST LL */
- st_ll_sleep_state(st_gdata, (unsigned long)cmd);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- /* wake up to send the recently copied skbs from waitQ */
- st_tx_wakeup(st_gdata);
-}
-
-/*
- * st_int_recv - ST's internal receive function.
- * Decodes received RAW data and forwards to corresponding
- * client drivers (Bluetooth,FM,GPS..etc).
- * This can receive various types of packets,
- * HCI-Events, ACL, SCO, 4 types of HCI-LL PM packets
- * CH-8 packets from FM, CH-9 packets from GPS cores.
- */
-static void st_int_recv(void *disc_data, const u8 *ptr, size_t count)
-{
- struct st_proto_s *proto;
- unsigned short payload_len = 0;
- int len = 0;
- unsigned char type = 0;
- unsigned char *plen;
- struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
- unsigned long flags;
-
- if (st_gdata == NULL) {
- pr_err(" received null from TTY ");
- return;
- }
-
- pr_debug("count %zu rx_state %ld"
- "rx_count %ld", count, st_gdata->rx_state,
- st_gdata->rx_count);
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /* Decode received bytes here */
- while (count) {
- if (st_gdata->rx_count) {
- len = min_t(unsigned int, st_gdata->rx_count, count);
- skb_put_data(st_gdata->rx_skb, ptr, len);
- st_gdata->rx_count -= len;
- count -= len;
- ptr += len;
-
- if (st_gdata->rx_count)
- continue;
-
- /* Check ST RX state machine , where are we? */
- switch (st_gdata->rx_state) {
- /* Waiting for complete packet ? */
- case ST_W4_DATA:
- pr_debug("Complete pkt received");
- /*
- * Ask ST CORE to forward
- * the packet to protocol driver
- */
- st_send_frame(st_gdata->rx_chnl, st_gdata);
-
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- st_gdata->rx_skb = NULL;
- continue;
- /* parse the header to know details */
- case ST_W4_HEADER:
- proto = st_gdata->list[st_gdata->rx_chnl];
- plen =
- &st_gdata->rx_skb->data
- [proto->offset_len_in_hdr];
- pr_debug("plen pointing to %x\n", *plen);
- if (proto->len_size == 1) /* 1 byte len field */
- payload_len = *(unsigned char *)plen;
- else if (proto->len_size == 2)
- payload_len =
- __le16_to_cpu(*(unsigned short *)plen);
- else
- pr_info("%s: invalid length "
- "for id %d\n",
- __func__, proto->chnl_id);
- st_check_data_len(st_gdata, proto->chnl_id,
- payload_len);
- pr_debug("off %d, pay len %d\n",
- proto->offset_len_in_hdr, payload_len);
- continue;
- } /* end of switch rx_state */
- }
-
- /* end of if rx_count */
-
- /*
- * Check first byte of packet and identify module
- * owner (BT/FM/GPS)
- */
- switch (*ptr) {
- case LL_SLEEP_IND:
- case LL_SLEEP_ACK:
- case LL_WAKE_UP_IND:
- pr_debug("PM packet");
- /*
- * this takes appropriate action based on
- * sleep state received --
- */
- st_ll_sleep_state(st_gdata, *ptr);
- /*
- * if WAKEUP_IND collides copy from waitq to txq
- * and assume chip awake
- */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- if (st_ll_getstate(st_gdata) == ST_LL_AWAKE)
- st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- ptr++;
- count--;
- continue;
- case LL_WAKE_UP_ACK:
- pr_debug("PM packet");
-
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- /* wake up ack received */
- st_wakeup_ack(st_gdata, *ptr);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- ptr++;
- count--;
- continue;
- /* Unknown packet? */
- default:
- type = *ptr;
-
- /*
- * Default case means non-HCILL packets,
- * possibilities are packets for:
- * (a) valid protocol - Supported Protocols within
- * the ST_MAX_CHANNELS.
- * (b) registered protocol - Checked by
- * "st_gdata->list[type] == NULL)" are supported
- * protocols only.
- * Rules out any invalid protocol and
- * unregistered protocols with channel ID < 16.
- */
-
- if ((type >= ST_MAX_CHANNELS) ||
- (st_gdata->list[type] == NULL)) {
- pr_err("chip/interface misbehavior: "
- "dropping frame starting "
- "with 0x%02x\n", type);
- goto done;
- }
-
- st_gdata->rx_skb = alloc_skb(
- st_gdata->list[type]->max_frame_size,
- GFP_ATOMIC);
- if (st_gdata->rx_skb == NULL) {
- pr_err("out of memory: dropping\n");
- goto done;
- }
-
- skb_reserve(st_gdata->rx_skb,
- st_gdata->list[type]->reserve);
- /* next 2 required for BT only */
- st_gdata->rx_skb->cb[0] = type; /*pkt_type*/
- st_gdata->rx_skb->cb[1] = 0; /*incoming*/
- st_gdata->rx_chnl = *ptr;
- st_gdata->rx_state = ST_W4_HEADER;
- st_gdata->rx_count = st_gdata->list[type]->hdr_len;
- pr_debug("rx_count %ld\n", st_gdata->rx_count);
- }
- ptr++;
- count--;
- }
-done:
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- pr_debug("done %s", __func__);
- return;
-}
-
-/*
- * st_int_dequeue - internal de-Q function.
- * If the previous data set was not written
- * completely, return that skb which has the pending data.
- * In normal cases, return top of txq.
- */
-static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
-{
- struct sk_buff *returning_skb;
-
- pr_debug("%s", __func__);
- if (st_gdata->tx_skb != NULL) {
- returning_skb = st_gdata->tx_skb;
- st_gdata->tx_skb = NULL;
- return returning_skb;
- }
- return skb_dequeue(&st_gdata->txq);
-}
-
-/*
- * st_int_enqueue - internal Q-ing function.
- * Will either Q the skb to txq or the tx_waitq
- * depending on the ST LL state.
- * If the chip is asleep, then Q it onto waitq and
- * wakeup the chip.
- * txq and waitq needs protection since the other contexts
- * may be sending data, waking up chip.
- */
-static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
-{
- unsigned long flags = 0;
-
- pr_debug("%s", __func__);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- switch (st_ll_getstate(st_gdata)) {
- case ST_LL_AWAKE:
- pr_debug("ST LL is AWAKE, sending normally");
- skb_queue_tail(&st_gdata->txq, skb);
- break;
- case ST_LL_ASLEEP_TO_AWAKE:
- skb_queue_tail(&st_gdata->tx_waitq, skb);
- break;
- case ST_LL_AWAKE_TO_ASLEEP:
- pr_err("ST LL is illegal state(%ld),"
- "purging received skb.", st_ll_getstate(st_gdata));
- dev_kfree_skb_irq(skb);
- break;
- case ST_LL_ASLEEP:
- skb_queue_tail(&st_gdata->tx_waitq, skb);
- st_ll_wakeup(st_gdata);
- break;
- default:
- pr_err("ST LL is illegal state(%ld),"
- "purging received skb.", st_ll_getstate(st_gdata));
- dev_kfree_skb_irq(skb);
- break;
- }
-
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- pr_debug("done %s", __func__);
- return;
-}
-
-/*
- * internal wakeup function
- * called from either
- * - TTY layer when write's finished
- * - st_write (in context of the protocol stack)
- */
-static void work_fn_write_wakeup(struct work_struct *work)
-{
- struct st_data_s *st_gdata = container_of(work, struct st_data_s,
- work_write_wakeup);
-
- st_tx_wakeup((void *)st_gdata);
-}
-void st_tx_wakeup(struct st_data_s *st_data)
-{
- struct sk_buff *skb;
- unsigned long flags; /* for irq save flags */
- pr_debug("%s", __func__);
- /* check for sending & set flag sending here */
- if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) {
- pr_debug("ST already sending");
- /* keep sending */
- set_bit(ST_TX_WAKEUP, &st_data->tx_state);
- return;
- /* TX_WAKEUP will be checked in another
- * context
- */
- }
- do { /* come back if st_tx_wakeup is set */
- /* woke-up to write */
- clear_bit(ST_TX_WAKEUP, &st_data->tx_state);
- while ((skb = st_int_dequeue(st_data))) {
- int len;
- spin_lock_irqsave(&st_data->lock, flags);
- /* enable wake-up from TTY */
- set_bit(TTY_DO_WRITE_WAKEUP, &st_data->tty->flags);
- len = st_int_write(st_data, skb->data, skb->len);
- skb_pull(skb, len);
- /* if skb->len = len as expected, skb->len=0 */
- if (skb->len) {
- /* would be the next skb to be sent */
- st_data->tx_skb = skb;
- spin_unlock_irqrestore(&st_data->lock, flags);
- break;
- }
- dev_kfree_skb_irq(skb);
- spin_unlock_irqrestore(&st_data->lock, flags);
- }
- /* if wake-up is set in another context- restart sending */
- } while (test_bit(ST_TX_WAKEUP, &st_data->tx_state));
-
- /* clear flag sending */
- clear_bit(ST_TX_SENDING, &st_data->tx_state);
-}
-
-/********************************************************************/
-/* functions called from ST KIM
-*/
-void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf)
-{
- seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
- st_gdata->protos_registered,
- st_gdata->is_registered[0x04] == true ? 'R' : 'U',
- st_gdata->is_registered[0x08] == true ? 'R' : 'U',
- st_gdata->is_registered[0x09] == true ? 'R' : 'U');
-}
-
-/********************************************************************/
-/*
- * functions called from protocol stack drivers
- * to be EXPORT-ed
- */
-long st_register(struct st_proto_s *new_proto)
-{
- struct st_data_s *st_gdata;
- long err = 0;
- unsigned long flags = 0;
-
- st_kim_ref(&st_gdata, 0);
- if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
- || new_proto->reg_complete_cb == NULL) {
- pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
- return -EINVAL;
- }
-
- if (new_proto->chnl_id >= ST_MAX_CHANNELS) {
- pr_err("chnl_id %d not supported", new_proto->chnl_id);
- return -EPROTONOSUPPORT;
- }
-
- if (st_gdata->is_registered[new_proto->chnl_id] == true) {
- pr_err("chnl_id %d already registered", new_proto->chnl_id);
- return -EALREADY;
- }
-
- /* can be from process context only */
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) {
- pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id);
- /* fw download in progress */
-
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
-
- set_bit(ST_REG_PENDING, &st_gdata->st_state);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EINPROGRESS;
- } else if (st_gdata->protos_registered == ST_EMPTY) {
- pr_info(" chnl_id list empty :%d ", new_proto->chnl_id);
- set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- st_recv = st_kim_recv;
-
- /* enable the ST LL - to set default chip state */
- st_ll_enable(st_gdata);
-
- /* release lock previously held - re-locked below */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- /*
- * this may take a while to complete
- * since it involves BT fw download
- */
- err = st_kim_start(st_gdata->kim_data);
- if (err != 0) {
- clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- if ((st_gdata->protos_registered != ST_EMPTY) &&
- (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_err(" KIM failure complete callback ");
- spin_lock_irqsave(&st_gdata->lock, flags);
- st_reg_complete(st_gdata, err);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- clear_bit(ST_REG_PENDING, &st_gdata->st_state);
- }
- return -EINVAL;
- }
-
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- st_recv = st_int_recv;
-
- /*
- * this is where all pending registration
- * are signalled to be complete by calling callback functions
- */
- if ((st_gdata->protos_registered != ST_EMPTY) &&
- (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_debug(" call reg complete callback ");
- st_reg_complete(st_gdata, 0);
- }
- clear_bit(ST_REG_PENDING, &st_gdata->st_state);
-
- /*
- * check for already registered once more,
- * since the above check is old
- */
- if (st_gdata->is_registered[new_proto->chnl_id] == true) {
- pr_err(" proto %d already registered ",
- new_proto->chnl_id);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EALREADY;
- }
-
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return err;
- }
- /* if fw is already downloaded & new stack registers protocol */
- else {
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
-
- /* lock already held before entering else */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return err;
- }
-}
-EXPORT_SYMBOL_GPL(st_register);
-
-/*
- * to unregister a protocol -
- * to be called from protocol stack driver
- */
-long st_unregister(struct st_proto_s *proto)
-{
- long err = 0;
- unsigned long flags = 0;
- struct st_data_s *st_gdata;
-
- pr_debug("%s: %d ", __func__, proto->chnl_id);
-
- st_kim_ref(&st_gdata, 0);
- if (!st_gdata || proto->chnl_id >= ST_MAX_CHANNELS) {
- pr_err(" chnl_id %d not supported", proto->chnl_id);
- return -EPROTONOSUPPORT;
- }
-
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- if (st_gdata->is_registered[proto->chnl_id] == false) {
- pr_err(" chnl_id %d not registered", proto->chnl_id);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EPROTONOSUPPORT;
- }
-
- if (st_gdata->protos_registered)
- st_gdata->protos_registered--;
-
- remove_channel_from_table(st_gdata, proto);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- if ((st_gdata->protos_registered == ST_EMPTY) &&
- (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_info(" all chnl_ids unregistered ");
-
- /* stop traffic on tty */
- if (st_gdata->tty) {
- tty_ldisc_flush(st_gdata->tty);
- stop_tty(st_gdata->tty);
- }
-
- /* all chnl_ids now unregistered */
- st_kim_stop(st_gdata->kim_data);
- /* disable ST LL */
- st_ll_disable(st_gdata);
- }
- return err;
-}
-
-/*
- * called in protocol stack drivers
- * via the write function pointer
- */
-long st_write(struct sk_buff *skb)
-{
- struct st_data_s *st_gdata;
- long len;
-
- st_kim_ref(&st_gdata, 0);
- if (unlikely(skb == NULL || st_gdata == NULL
- || st_gdata->tty == NULL)) {
- pr_err("data/tty unavailable to perform write");
- return -EINVAL;
- }
-
- pr_debug("%d to be written", skb->len);
- len = skb->len;
-
- /* st_ll to decide where to enqueue the skb */
- st_int_enqueue(st_gdata, skb);
- /* wake up */
- st_tx_wakeup(st_gdata);
-
- /* return number of bytes written */
- return len;
-}
-
-/* for protocols making use of shared transport */
-EXPORT_SYMBOL_GPL(st_unregister);
-
-/********************************************************************/
-/*
- * functions called from TTY layer
- */
-static int st_tty_open(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata;
- pr_info("%s ", __func__);
-
- st_kim_ref(&st_gdata, 0);
- st_gdata->tty = tty;
- tty->disc_data = st_gdata;
-
- /* don't do an wakeup for now */
- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-
- /* mem already allocated
- */
- tty->receive_room = 65536;
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
- /*
- * signal to UIM via KIM that -
- * installation of N_TI_WL ldisc is complete
- */
- st_kim_complete(st_gdata->kim_data);
- pr_debug("done %s", __func__);
-
- return 0;
-}
-
-static void st_tty_close(struct tty_struct *tty)
-{
- unsigned char i;
- unsigned long flags;
- struct st_data_s *st_gdata = tty->disc_data;
-
- pr_info("%s ", __func__);
-
- /*
- * TODO:
- * if a protocol has been registered & line discipline
- * un-installed for some reason - what should be done ?
- */
- spin_lock_irqsave(&st_gdata->lock, flags);
- for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
- if (st_gdata->is_registered[i] == true)
- pr_err("%d not un-registered", i);
- st_gdata->list[i] = NULL;
- st_gdata->is_registered[i] = false;
- }
- st_gdata->protos_registered = 0;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- /*
- * signal to UIM via KIM that -
- * N_TI_WL ldisc is un-installed
- */
- st_kim_complete(st_gdata->kim_data);
- st_gdata->tty = NULL;
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /* empty out txq and tx_waitq */
- skb_queue_purge(&st_gdata->txq);
- skb_queue_purge(&st_gdata->tx_waitq);
- /* reset the TTY Rx states of ST */
- st_gdata->rx_count = 0;
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- kfree_skb(st_gdata->rx_skb);
- st_gdata->rx_skb = NULL;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- pr_debug("%s: done ", __func__);
-}
-
-static void st_tty_receive(struct tty_struct *tty, const u8 *data,
- const u8 *tty_flags, size_t count)
-{
-#ifdef VERBOSE
- print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
- 16, 1, data, count, 0);
-#endif
-
- /*
- * if fw download is in progress then route incoming data
- * to KIM for validation
- */
- st_recv(tty->disc_data, data, count);
- pr_debug("done %s", __func__);
-}
-
-/*
- * wake-up function called in from the TTY layer
- * inside the internal wakeup function will be called
- */
-static void st_tty_wakeup(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata = tty->disc_data;
- pr_debug("%s ", __func__);
- /* don't do an wakeup for now */
- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-
- /*
- * schedule the internal wakeup instead of calling directly to
- * avoid lockup (port->lock needed in tty->ops->write is
- * already taken here
- */
- schedule_work(&st_gdata->work_write_wakeup);
-}
-
-static void st_tty_flush_buffer(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata = tty->disc_data;
- pr_debug("%s ", __func__);
-
- kfree_skb(st_gdata->tx_skb);
- st_gdata->tx_skb = NULL;
-
- tty_driver_flush_buffer(tty);
- return;
-}
-
-static struct tty_ldisc_ops st_ldisc_ops = {
- .num = N_TI_WL,
- .name = "n_st",
- .open = st_tty_open,
- .close = st_tty_close,
- .receive_buf = st_tty_receive,
- .write_wakeup = st_tty_wakeup,
- .flush_buffer = st_tty_flush_buffer,
- .owner = THIS_MODULE
-};
-
-/********************************************************************/
-int st_core_init(struct st_data_s **core_data)
-{
- struct st_data_s *st_gdata;
- long err;
-
- err = tty_register_ldisc(&st_ldisc_ops);
- if (err) {
- pr_err("error registering %d line discipline %ld",
- N_TI_WL, err);
- return err;
- }
- pr_debug("registered n_shared line discipline");
-
- st_gdata = kzalloc(sizeof(struct st_data_s), GFP_KERNEL);
- if (!st_gdata) {
- pr_err("memory allocation failed");
- err = -ENOMEM;
- goto err_unreg_ldisc;
- }
-
- /* Initialize ST TxQ and Tx waitQ queue head. All BT/FM/GPS module skb's
- * will be pushed in this queue for actual transmission.
- */
- skb_queue_head_init(&st_gdata->txq);
- skb_queue_head_init(&st_gdata->tx_waitq);
-
- /* Locking used in st_int_enqueue() to avoid multiple execution */
- spin_lock_init(&st_gdata->lock);
-
- err = st_ll_init(st_gdata);
- if (err) {
- pr_err("error during st_ll initialization(%ld)", err);
- goto err_free_gdata;
- }
-
- INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup);
-
- *core_data = st_gdata;
- return 0;
-err_free_gdata:
- kfree(st_gdata);
-err_unreg_ldisc:
- tty_unregister_ldisc(&st_ldisc_ops);
- return err;
-}
-
-void st_core_exit(struct st_data_s *st_gdata)
-{
- long err;
- /* internal module cleanup */
- err = st_ll_deinit(st_gdata);
- if (err)
- pr_err("error during deinit of ST LL %ld", err);
-
- if (st_gdata != NULL) {
- /* Free ST Tx Qs and skbs */
- skb_queue_purge(&st_gdata->txq);
- skb_queue_purge(&st_gdata->tx_waitq);
- kfree_skb(st_gdata->rx_skb);
- kfree_skb(st_gdata->tx_skb);
- /* TTY ldisc cleanup */
- tty_unregister_ldisc(&st_ldisc_ops);
- /* free the global data pointer */
- kfree(st_gdata);
- }
-}
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
deleted file mode 100644
index ff172cf4614d..000000000000
--- a/drivers/misc/ti-st/st_kim.c
+++ /dev/null
@@ -1,839 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport Line discipline driver Core
- * Init Manager module responsible for GPIO control
- * and firmware download
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stk) :" fmt
-#include <linux/platform_device.h>
-#include <linux/jiffies.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/gpio.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/sched.h>
-#include <linux/sysfs.h>
-#include <linux/tty.h>
-
-#include <linux/skbuff.h>
-#include <linux/ti_wilink_st.h>
-#include <linux/module.h>
-
-#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */
-static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
-
-/**********************************************************************/
-/* internal functions */
-
-/*
- * st_get_plat_device -
- * function which returns the reference to the platform device
- * requested by id. As of now only 1 such device exists (id=0)
- * the context requesting for reference can get the id to be
- * requested by a. The protocol driver which is registering or
- * b. the tty device which is opened.
- */
-static struct platform_device *st_get_plat_device(int id)
-{
- return st_kim_devices[id];
-}
-
-/*
- * validate_firmware_response -
- * function to return whether the firmware response was proper
- * in case of error don't complete so that waiting for proper
- * response times out
- */
-static void validate_firmware_response(struct kim_data_s *kim_gdata)
-{
- struct sk_buff *skb = kim_gdata->rx_skb;
- if (!skb)
- return;
-
- /*
- * these magic numbers are the position in the response buffer which
- * allows us to distinguish whether the response is for the read
- * version info. command
- */
- if (skb->data[2] == 0x01 && skb->data[3] == 0x01 &&
- skb->data[4] == 0x10 && skb->data[5] == 0x00) {
- /* fw version response */
- memcpy(kim_gdata->resp_buffer,
- kim_gdata->rx_skb->data,
- kim_gdata->rx_skb->len);
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- kim_gdata->rx_count = 0;
- } else if (unlikely(skb->data[5] != 0)) {
- pr_err("no proper response during fw download");
- pr_err("data6 %x", skb->data[5]);
- kfree_skb(skb);
- return; /* keep waiting for the proper response */
- }
- /* becos of all the script being downloaded */
- complete_all(&kim_gdata->kim_rcvd);
- kfree_skb(skb);
-}
-
-/*
- * check for data len received inside kim_int_recv
- * most often hit the last case to update state to waiting for data
- */
-static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len)
-{
- register int room = skb_tailroom(kim_gdata->rx_skb);
-
- pr_debug("len %d room %d", len, room);
-
- if (!len) {
- validate_firmware_response(kim_gdata);
- } else if (len > room) {
- /*
- * Received packet's payload length is larger.
- * We can't accommodate it in created skb.
- */
- pr_err("Data length is too large len %d room %d", len,
- room);
- kfree_skb(kim_gdata->rx_skb);
- } else {
- /*
- * Packet header has non-zero payload length and
- * we have enough space in created skb. Lets read
- * payload data */
- kim_gdata->rx_state = ST_W4_DATA;
- kim_gdata->rx_count = len;
- return len;
- }
-
- /*
- * Change ST LL state to continue to process next
- * packet
- */
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- kim_gdata->rx_count = 0;
-
- return 0;
-}
-
-/*
- * kim_int_recv - receive function called during firmware download
- * firmware download responses on different UART drivers
- * have been observed to come in bursts of different
- * tty_receive and hence the logic
- */
-static void kim_int_recv(struct kim_data_s *kim_gdata, const u8 *ptr,
- size_t count)
-{
- int len = 0;
- unsigned char *plen;
-
- pr_debug("%s", __func__);
- /* Decode received bytes here */
- while (count) {
- if (kim_gdata->rx_count) {
- len = min_t(unsigned int, kim_gdata->rx_count, count);
- skb_put_data(kim_gdata->rx_skb, ptr, len);
- kim_gdata->rx_count -= len;
- count -= len;
- ptr += len;
-
- if (kim_gdata->rx_count)
- continue;
-
- /* Check ST RX state machine , where are we? */
- switch (kim_gdata->rx_state) {
- /* Waiting for complete packet ? */
- case ST_W4_DATA:
- pr_debug("Complete pkt received");
- validate_firmware_response(kim_gdata);
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- continue;
- /* Waiting for Bluetooth event header ? */
- case ST_W4_HEADER:
- plen =
- (unsigned char *)&kim_gdata->rx_skb->data[1];
- pr_debug("event hdr: plen 0x%02x\n", *plen);
- kim_check_data_len(kim_gdata, *plen);
- continue;
- } /* end of switch */
- } /* end of if rx_state */
- switch (*ptr) {
- /* Bluetooth event packet? */
- case 0x04:
- kim_gdata->rx_state = ST_W4_HEADER;
- kim_gdata->rx_count = 2;
- break;
- default:
- pr_info("unknown packet");
- ptr++;
- count--;
- continue;
- }
- ptr++;
- count--;
- kim_gdata->rx_skb =
- alloc_skb(1024+8, GFP_ATOMIC);
- if (!kim_gdata->rx_skb) {
- pr_err("can't allocate mem for new packet");
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_count = 0;
- return;
- }
- skb_reserve(kim_gdata->rx_skb, 8);
- kim_gdata->rx_skb->cb[0] = 4;
- kim_gdata->rx_skb->cb[1] = 0;
-
- }
- return;
-}
-
-static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
-{
- unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0;
- static const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 };
- long time_left;
-
- pr_debug("%s", __func__);
-
- reinit_completion(&kim_gdata->kim_rcvd);
- if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) {
- pr_err("kim: couldn't write 4 bytes");
- return -EIO;
- }
-
- time_left = wait_for_completion_interruptible_timeout(
- &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME));
- if (time_left <= 0) {
- pr_err(" waiting for ver info- timed out or received signal");
- return time_left ? -ERESTARTSYS : -ETIMEDOUT;
- }
- reinit_completion(&kim_gdata->kim_rcvd);
- /*
- * the positions 12 & 13 in the response buffer provide with the
- * chip, major & minor numbers
- */
-
- version =
- MAKEWORD(kim_gdata->resp_buffer[12],
- kim_gdata->resp_buffer[13]);
- chip = (version & 0x7C00) >> 10;
- min_ver = (version & 0x007F);
- maj_ver = (version & 0x0380) >> 7;
-
- if (version & 0x8000)
- maj_ver |= 0x0008;
-
- sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts",
- chip, maj_ver, min_ver);
-
- /* to be accessed later via sysfs entry */
- kim_gdata->version.full = version;
- kim_gdata->version.chip = chip;
- kim_gdata->version.maj_ver = maj_ver;
- kim_gdata->version.min_ver = min_ver;
-
- pr_info("%s", bts_scr_name);
- return 0;
-}
-
-static void skip_change_remote_baud(unsigned char **ptr, long *len)
-{
- unsigned char *nxt_action, *cur_action;
- cur_action = *ptr;
-
- nxt_action = cur_action + sizeof(struct bts_action) +
- ((struct bts_action *) cur_action)->size;
-
- if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) {
- pr_err("invalid action after change remote baud command");
- } else {
- *ptr = *ptr + sizeof(struct bts_action) +
- ((struct bts_action *)cur_action)->size;
- *len = *len - (sizeof(struct bts_action) +
- ((struct bts_action *)cur_action)->size);
- /* warn user on not commenting these in firmware */
- pr_warn("skipping the wait event of change remote baud");
- }
-}
-
-/*
- * download_firmware -
- * internal function which parses through the .bts firmware
- * script file intreprets SEND, DELAY actions only as of now
- */
-static long download_firmware(struct kim_data_s *kim_gdata)
-{
- long err = 0;
- long len = 0;
- unsigned char *ptr = NULL;
- unsigned char *action_ptr = NULL;
- unsigned char bts_scr_name[40] = { 0 }; /* 40 char long bts scr name? */
- int wr_room_space;
- int cmd_size;
- unsigned long timeout;
-
- err = read_local_version(kim_gdata, bts_scr_name);
- if (err != 0) {
- pr_err("kim: failed to read local ver");
- return err;
- }
- err =
- request_firmware(&kim_gdata->fw_entry, bts_scr_name,
- &kim_gdata->kim_pdev->dev);
- if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) ||
- (kim_gdata->fw_entry->size == 0))) {
- pr_err(" request_firmware failed(errno %ld) for %s", err,
- bts_scr_name);
- return -EINVAL;
- }
- ptr = (void *)kim_gdata->fw_entry->data;
- len = kim_gdata->fw_entry->size;
- /*
- * bts_header to remove out magic number and
- * version
- */
- ptr += sizeof(struct bts_header);
- len -= sizeof(struct bts_header);
-
- while (len > 0 && ptr) {
- pr_debug(" action size %d, type %d ",
- ((struct bts_action *)ptr)->size,
- ((struct bts_action *)ptr)->type);
-
- switch (((struct bts_action *)ptr)->type) {
- case ACTION_SEND_COMMAND: /* action send */
- pr_debug("S");
- action_ptr = &(((struct bts_action *)ptr)->data[0]);
- if (unlikely
- (((struct hci_command *)action_ptr)->opcode ==
- 0xFF36)) {
- /*
- * ignore remote change
- * baud rate HCI VS command
- */
- pr_warn("change remote baud"
- " rate command in firmware");
- skip_change_remote_baud(&ptr, &len);
- break;
- }
- /*
- * Make sure we have enough free space in uart
- * tx buffer to write current firmware command
- */
- cmd_size = ((struct bts_action *)ptr)->size;
- timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME);
- do {
- wr_room_space =
- st_get_uart_wr_room(kim_gdata->core_data);
- if (wr_room_space < 0) {
- pr_err("Unable to get free "
- "space info from uart tx buffer");
- release_firmware(kim_gdata->fw_entry);
- return wr_room_space;
- }
- mdelay(1); /* wait 1ms before checking room */
- } while ((wr_room_space < cmd_size) &&
- time_before(jiffies, timeout));
-
- /* Timeout happened ? */
- if (time_after_eq(jiffies, timeout)) {
- pr_err("Timeout while waiting for free "
- "free space in uart tx buffer");
- release_firmware(kim_gdata->fw_entry);
- return -ETIMEDOUT;
- }
- /*
- * reinit completion before sending for the
- * relevant wait
- */
- reinit_completion(&kim_gdata->kim_rcvd);
-
- /*
- * Free space found in uart buffer, call st_int_write
- * to send current firmware command to the uart tx
- * buffer.
- */
- err = st_int_write(kim_gdata->core_data,
- ((struct bts_action_send *)action_ptr)->data,
- ((struct bts_action *)ptr)->size);
- if (unlikely(err < 0)) {
- release_firmware(kim_gdata->fw_entry);
- return err;
- }
- /*
- * Check number of bytes written to the uart tx buffer
- * and requested command write size
- */
- if (err != cmd_size) {
- pr_err("Number of bytes written to uart "
- "tx buffer are not matching with "
- "requested cmd write size");
- release_firmware(kim_gdata->fw_entry);
- return -EIO;
- }
- break;
- case ACTION_WAIT_EVENT: /* wait */
- pr_debug("W");
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->kim_rcvd,
- msecs_to_jiffies(CMD_RESP_TIME));
- if (err <= 0) {
- pr_err("response timeout/signaled during fw download ");
- /* timed out */
- release_firmware(kim_gdata->fw_entry);
- return err ? -ERESTARTSYS : -ETIMEDOUT;
- }
- reinit_completion(&kim_gdata->kim_rcvd);
- break;
- case ACTION_DELAY: /* sleep */
- pr_info("sleep command in scr");
- action_ptr = &(((struct bts_action *)ptr)->data[0]);
- mdelay(((struct bts_action_delay *)action_ptr)->msec);
- break;
- }
- len =
- len - (sizeof(struct bts_action) +
- ((struct bts_action *)ptr)->size);
- ptr =
- ptr + sizeof(struct bts_action) +
- ((struct bts_action *)ptr)->size;
- }
- /* fw download complete */
- release_firmware(kim_gdata->fw_entry);
- return 0;
-}
-
-/**********************************************************************/
-/* functions called from ST core */
-/* called from ST Core, when REG_IN_PROGRESS (registration in progress)
- * can be because of
- * 1. response to read local version
- * 2. during send/recv's of firmware download
- */
-void st_kim_recv(void *disc_data, const u8 *data, size_t count)
-{
- struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
- struct kim_data_s *kim_gdata = st_gdata->kim_data;
-
- /*
- * proceed to gather all data and distinguish read fw version response
- * from other fw responses when data gathering is complete
- */
- kim_int_recv(kim_gdata, data, count);
- return;
-}
-
-/*
- * to signal completion of line discipline installation
- * called from ST Core, upon tty_open
- */
-void st_kim_complete(void *kim_data)
-{
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
- complete(&kim_gdata->ldisc_installed);
-}
-
-/*
- * st_kim_start - called from ST Core upon 1st registration
- * This involves toggling the chip enable gpio, reading
- * the firmware version from chip, forming the fw file name
- * based on the chip version, requesting the fw, parsing it
- * and perform download(send/recv).
- */
-long st_kim_start(void *kim_data)
-{
- long err = 0;
- long retry = POR_RETRY_COUNT;
- struct ti_st_plat_data *pdata;
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
-
- pr_info(" %s", __func__);
- pdata = kim_gdata->kim_pdev->dev.platform_data;
-
- do {
- /* platform specific enabling code here */
- if (pdata->chip_enable)
- pdata->chip_enable(kim_gdata);
-
- /* Configure BT nShutdown to HIGH state */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(5); /* FIXME: a proper toggle */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(100);
- /* re-initialize the completion */
- reinit_completion(&kim_gdata->ldisc_installed);
- /* send notification to UIM */
- kim_gdata->ldisc_install = 1;
- pr_info("ldisc_install = 1");
- sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
- NULL, "install");
- /* wait for ldisc to be installed */
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
- if (!err) {
- /*
- * ldisc installation timeout,
- * flush uart, power cycle BT_EN
- */
- pr_err("ldisc installation timeout");
- err = st_kim_stop(kim_gdata);
- continue;
- } else {
- /* ldisc installed now */
- pr_info("line discipline installed");
- err = download_firmware(kim_gdata);
- if (err != 0) {
- /*
- * ldisc installed but fw download failed,
- * flush uart & power cycle BT_EN
- */
- pr_err("download firmware failed");
- err = st_kim_stop(kim_gdata);
- continue;
- } else { /* on success don't retry */
- break;
- }
- }
- } while (retry--);
- return err;
-}
-
-/*
- * st_kim_stop - stop communication with chip.
- * This can be called from ST Core/KIM, on the-
- * (a) last un-register when chip need not be powered there-after,
- * (b) upon failure to either install ldisc or download firmware.
- * The function is responsible to (a) notify UIM about un-installation,
- * (b) flush UART if the ldisc was installed.
- * (c) reset BT_EN - pull down nshutdown at the end.
- * (d) invoke platform's chip disabling routine.
- */
-long st_kim_stop(void *kim_data)
-{
- long err = 0;
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
- struct ti_st_plat_data *pdata =
- kim_gdata->kim_pdev->dev.platform_data;
- struct tty_struct *tty = kim_gdata->core_data->tty;
-
- reinit_completion(&kim_gdata->ldisc_installed);
-
- if (tty) { /* can be called before ldisc is installed */
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
- }
-
- /* send uninstall notification to UIM */
- pr_info("ldisc_install = 0");
- kim_gdata->ldisc_install = 0;
- sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
-
- /* wait for ldisc to be un-installed */
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
- if (!err) { /* timeout */
- pr_err(" timed out waiting for ldisc to be un-installed");
- err = -ETIMEDOUT;
- }
-
- /* By default configure BT nShutdown to LOW state */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(1);
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(1);
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
-
- /* platform specific disable */
- if (pdata->chip_disable)
- pdata->chip_disable(kim_gdata);
- return err;
-}
-
-/**********************************************************************/
-/* functions called from subsystems */
-/* called when debugfs entry is read from */
-
-static int version_show(struct seq_file *s, void *unused)
-{
- struct kim_data_s *kim_gdata = s->private;
- seq_printf(s, "%04X %d.%d.%d\n", kim_gdata->version.full,
- kim_gdata->version.chip, kim_gdata->version.maj_ver,
- kim_gdata->version.min_ver);
- return 0;
-}
-
-static int list_show(struct seq_file *s, void *unused)
-{
- struct kim_data_s *kim_gdata = s->private;
- kim_st_list_protocols(kim_gdata->core_data, s);
- return 0;
-}
-
-static ssize_t show_install(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->ldisc_install);
-}
-
-#ifdef DEBUG
-static ssize_t store_dev_name(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- pr_debug("storing dev name >%s<", buf);
- strscpy(kim_data->dev_name, buf, sizeof(kim_data->dev_name));
- pr_debug("stored dev name >%s<", kim_data->dev_name);
- return count;
-}
-
-static ssize_t store_baud_rate(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- pr_debug("storing baud rate >%s<", buf);
- sscanf(buf, "%ld", &kim_data->baud_rate);
- pr_debug("stored baud rate >%ld<", kim_data->baud_rate);
- return count;
-}
-#endif /* if DEBUG */
-
-static ssize_t show_dev_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", kim_data->dev_name);
-}
-
-static ssize_t show_baud_rate(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->baud_rate);
-}
-
-static ssize_t show_flow_cntrl(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->flow_cntrl);
-}
-
-/* structures specific for sysfs entries */
-static struct kobj_attribute ldisc_install =
-__ATTR(install, 0444, (void *)show_install, NULL);
-
-static struct kobj_attribute uart_dev_name =
-#ifdef DEBUG /* TODO: move this to debug-fs if possible */
-__ATTR(dev_name, 0644, (void *)show_dev_name, (void *)store_dev_name);
-#else
-__ATTR(dev_name, 0444, (void *)show_dev_name, NULL);
-#endif
-
-static struct kobj_attribute uart_baud_rate =
-#ifdef DEBUG /* TODO: move to debugfs */
-__ATTR(baud_rate, 0644, (void *)show_baud_rate, (void *)store_baud_rate);
-#else
-__ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL);
-#endif
-
-static struct kobj_attribute uart_flow_cntrl =
-__ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL);
-
-static struct attribute *uim_attrs[] = {
- &ldisc_install.attr,
- &uart_dev_name.attr,
- &uart_baud_rate.attr,
- &uart_flow_cntrl.attr,
- NULL,
-};
-
-static const struct attribute_group uim_attr_grp = {
- .attrs = uim_attrs,
-};
-
-/*
- * st_kim_ref - reference the core's data
- * This references the per-ST platform device in the arch/xx/
- * board-xx.c file.
- * This would enable multiple such platform devices to exist
- * on a given platform
- */
-void st_kim_ref(struct st_data_s **core_data, int id)
-{
- struct platform_device *pdev;
- struct kim_data_s *kim_gdata;
- /* get kim_gdata reference from platform device */
- pdev = st_get_plat_device(id);
- if (!pdev)
- goto err;
- kim_gdata = platform_get_drvdata(pdev);
- if (!kim_gdata)
- goto err;
-
- *core_data = kim_gdata->core_data;
- return;
-err:
- *core_data = NULL;
-}
-
-DEFINE_SHOW_ATTRIBUTE(version);
-DEFINE_SHOW_ATTRIBUTE(list);
-
-/**********************************************************************/
-/* functions called from platform device driver subsystem
- * need to have a relevant platform device entry in the platform's
- * board-*.c file
- */
-
-static struct dentry *kim_debugfs_dir;
-static int kim_probe(struct platform_device *pdev)
-{
- struct kim_data_s *kim_gdata;
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
- int err;
-
- if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
- /* multiple devices could exist */
- st_kim_devices[pdev->id] = pdev;
- } else {
- /* platform's sure about existence of 1 device */
- st_kim_devices[0] = pdev;
- }
-
- kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_KERNEL);
- if (!kim_gdata) {
- pr_err("no mem to allocate");
- return -ENOMEM;
- }
- platform_set_drvdata(pdev, kim_gdata);
-
- err = st_core_init(&kim_gdata->core_data);
- if (err != 0) {
- pr_err(" ST core init failed");
- err = -EIO;
- goto err_core_init;
- }
- /* refer to itself */
- kim_gdata->core_data->kim_data = kim_gdata;
-
- /* Claim the chip enable nShutdown gpio from the system */
- kim_gdata->nshutdown = pdata->nshutdown_gpio;
- err = gpio_request(kim_gdata->nshutdown, "kim");
- if (unlikely(err)) {
- pr_err(" gpio %d request failed ", kim_gdata->nshutdown);
- goto err_sysfs_group;
- }
-
- /* Configure nShutdown GPIO as output=0 */
- err = gpio_direction_output(kim_gdata->nshutdown, 0);
- if (unlikely(err)) {
- pr_err(" unable to configure gpio %d", kim_gdata->nshutdown);
- goto err_sysfs_group;
- }
- /* get reference of pdev for request_firmware */
- kim_gdata->kim_pdev = pdev;
- init_completion(&kim_gdata->kim_rcvd);
- init_completion(&kim_gdata->ldisc_installed);
-
- err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
- if (err) {
- pr_err("failed to create sysfs entries");
- goto err_sysfs_group;
- }
-
- /* copying platform data */
- strscpy(kim_gdata->dev_name, pdata->dev_name,
- sizeof(kim_gdata->dev_name));
- kim_gdata->flow_cntrl = pdata->flow_cntrl;
- kim_gdata->baud_rate = pdata->baud_rate;
- pr_info("sysfs entries created\n");
-
- kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
-
- debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
- kim_gdata, &version_fops);
- debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir,
- kim_gdata, &list_fops);
- return 0;
-
-err_sysfs_group:
- st_core_exit(kim_gdata->core_data);
-
-err_core_init:
- kfree(kim_gdata);
-
- return err;
-}
-
-static void kim_remove(struct platform_device *pdev)
-{
- /* free the GPIOs requested */
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
- struct kim_data_s *kim_gdata;
-
- kim_gdata = platform_get_drvdata(pdev);
-
- /*
- * Free the Bluetooth/FM/GPIO
- * nShutdown gpio from the system
- */
- gpio_free(pdata->nshutdown_gpio);
- pr_info("nshutdown GPIO Freed");
-
- debugfs_remove_recursive(kim_debugfs_dir);
- sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
- pr_info("sysfs entries removed");
-
- kim_gdata->kim_pdev = NULL;
- st_core_exit(kim_gdata->core_data);
-
- kfree(kim_gdata);
- kim_gdata = NULL;
-}
-
-static int kim_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
-
- if (pdata->suspend)
- return pdata->suspend(pdev, state);
-
- return 0;
-}
-
-static int kim_resume(struct platform_device *pdev)
-{
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
-
- if (pdata->resume)
- return pdata->resume(pdev);
-
- return 0;
-}
-
-/**********************************************************************/
-/* entry point for ST KIM module, called in from ST Core */
-static struct platform_driver kim_platform_driver = {
- .probe = kim_probe,
- .remove_new = kim_remove,
- .suspend = kim_suspend,
- .resume = kim_resume,
- .driver = {
- .name = "kim",
- },
-};
-
-module_platform_driver(kim_platform_driver);
-
-MODULE_AUTHOR("Pavan Savoy <pavan_savoy@ti.com>");
-MODULE_DESCRIPTION("Shared Transport Driver for TI BT/FM/GPS combo chips ");
-MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
deleted file mode 100644
index 07406140d277..000000000000
--- a/drivers/misc/ti-st/st_ll.c
+++ /dev/null
@@ -1,156 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport driver
- * HCI-LL module responsible for TI proprietary HCI_LL protocol
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stll) :" fmt
-#include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/ti_wilink_st.h>
-
-/**********************************************************************/
-/* internal functions */
-static void send_ll_cmd(struct st_data_s *st_data,
- unsigned char cmd)
-{
-
- pr_debug("%s: writing %x", __func__, cmd);
- st_int_write(st_data, &cmd, 1);
- return;
-}
-
-static void ll_device_want_to_sleep(struct st_data_s *st_data)
-{
- struct kim_data_s *kim_data;
- struct ti_st_plat_data *pdata;
-
- pr_debug("%s", __func__);
- /* sanity check */
- if (st_data->ll_state != ST_LL_AWAKE)
- pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
- "in state %ld", st_data->ll_state);
-
- send_ll_cmd(st_data, LL_SLEEP_ACK);
- /* update state */
- st_data->ll_state = ST_LL_ASLEEP;
-
- /* communicate to platform about chip asleep */
- kim_data = st_data->kim_data;
- pdata = kim_data->kim_pdev->dev.platform_data;
- if (pdata->chip_asleep)
- pdata->chip_asleep(NULL);
-}
-
-static void ll_device_want_to_wakeup(struct st_data_s *st_data)
-{
- struct kim_data_s *kim_data;
- struct ti_st_plat_data *pdata;
-
- /* diff actions in diff states */
- switch (st_data->ll_state) {
- case ST_LL_ASLEEP:
- send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
- break;
- case ST_LL_ASLEEP_TO_AWAKE:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind while waiting for Wake ack");
- break;
- case ST_LL_AWAKE:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind already AWAKE");
- break;
- case ST_LL_AWAKE_TO_ASLEEP:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind");
- break;
- }
- /* update state */
- st_data->ll_state = ST_LL_AWAKE;
-
- /* communicate to platform about chip wakeup */
- kim_data = st_data->kim_data;
- pdata = kim_data->kim_pdev->dev.platform_data;
- if (pdata->chip_awake)
- pdata->chip_awake(NULL);
-}
-
-/**********************************************************************/
-/* functions invoked by ST Core */
-
-/* called when ST Core wants to
- * enable ST LL */
-void st_ll_enable(struct st_data_s *ll)
-{
- ll->ll_state = ST_LL_AWAKE;
-}
-
-/* called when ST Core /local module wants to
- * disable ST LL */
-void st_ll_disable(struct st_data_s *ll)
-{
- ll->ll_state = ST_LL_INVALID;
-}
-
-/* called when ST Core wants to update the state */
-void st_ll_wakeup(struct st_data_s *ll)
-{
- if (likely(ll->ll_state != ST_LL_AWAKE)) {
- send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
- ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
- } else {
- /* don't send the duplicate wake_indication */
- pr_err(" Chip already AWAKE ");
- }
-}
-
-/* called when ST Core wants the state */
-unsigned long st_ll_getstate(struct st_data_s *ll)
-{
- pr_debug(" returning state %ld", ll->ll_state);
- return ll->ll_state;
-}
-
-/* called from ST Core, when a PM related packet arrives */
-unsigned long st_ll_sleep_state(struct st_data_s *st_data,
- unsigned char cmd)
-{
- switch (cmd) {
- case LL_SLEEP_IND: /* sleep ind */
- pr_debug("sleep indication recvd");
- ll_device_want_to_sleep(st_data);
- break;
- case LL_SLEEP_ACK: /* sleep ack */
- pr_err("sleep ack rcvd: host shouldn't");
- break;
- case LL_WAKE_UP_IND: /* wake ind */
- pr_debug("wake indication recvd");
- ll_device_want_to_wakeup(st_data);
- break;
- case LL_WAKE_UP_ACK: /* wake ack */
- pr_debug("wake ack rcvd");
- st_data->ll_state = ST_LL_AWAKE;
- break;
- default:
- pr_err(" unknown input/state ");
- return -EINVAL;
- }
- return 0;
-}
-
-/* Called from ST CORE to initialize ST LL */
-long st_ll_init(struct st_data_s *ll)
-{
- /* set state to invalid */
- ll->ll_state = ST_LL_INVALID;
- return 0;
-}
-
-/* Called from ST CORE to de-initialize ST LL */
-long st_ll_deinit(struct st_data_s *ll)
-{
- return 0;
-}
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 6a907736cd7a..15b067e8b0d1 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_MMC) += mmc_core.o
mmc_core-y := core.o bus.o host.o \
mmc.o mmc_ops.o sd.o sd_ops.o \
sdio.o sdio_ops.o sdio_bus.o \
- sdio_cis.o sdio_io.o sdio_irq.o \
+ sdio_cis.o sdio_io.o sdio_irq.o sd_uhs2.o\
slot-gpio.o regulator.o
mmc_core-$(CONFIG_OF) += pwrseq.o
obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index ef06a4d5d65b..4830628510e6 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -50,6 +50,7 @@
#include <linux/mmc/sd.h>
#include <linux/uaccess.h>
+#include <linux/unaligned.h>
#include "queue.h"
#include "block.h"
@@ -993,11 +994,12 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
int err;
u32 result;
__be32 *blocks;
+ u8 resp_sz = mmc_card_ult_capacity(card) ? 8 : 4;
+ unsigned int noio_flag;
struct mmc_request mrq = {};
struct mmc_command cmd = {};
struct mmc_data data = {};
-
struct scatterlist sg;
err = mmc_app_cmd(card->host, card);
@@ -1008,7 +1010,7 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
cmd.arg = 0;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- data.blksz = 4;
+ data.blksz = resp_sz;
data.blocks = 1;
data.flags = MMC_DATA_READ;
data.sg = &sg;
@@ -1018,15 +1020,29 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
mrq.cmd = &cmd;
mrq.data = &data;
- blocks = kmalloc(4, GFP_KERNEL);
+ noio_flag = memalloc_noio_save();
+ blocks = kmalloc(resp_sz, GFP_KERNEL);
+ memalloc_noio_restore(noio_flag);
if (!blocks)
return -ENOMEM;
- sg_init_one(&sg, blocks, 4);
+ sg_init_one(&sg, blocks, resp_sz);
mmc_wait_for_req(card->host, &mrq);
- result = ntohl(*blocks);
+ if (mmc_card_ult_capacity(card)) {
+ /*
+ * Normally, ACMD22 returns the number of written sectors as
+ * u32. SDUC, however, returns it as u64. This is not a
+ * superfluous requirement, because SDUC writes may exceed 2TB.
+ * For Linux mmc however, the previously write operation could
+ * not be more than the block layer limits, thus just make room
+ * for a u64 and cast the response back to u32.
+ */
+ result = clamp_val(get_unaligned_be64(blocks), 0, UINT_MAX);
+ } else {
+ result = ntohl(*blocks);
+ }
kfree(blocks);
if (cmd.error || data.error)
@@ -1199,7 +1215,8 @@ static void mmc_blk_issue_erase_rq(struct mmc_queue *mq, struct request *req,
{
struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
- unsigned int from, nr;
+ unsigned int nr;
+ sector_t from;
int err = 0;
blk_status_t status = BLK_STS_OK;
@@ -1254,7 +1271,8 @@ static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
{
struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
- unsigned int from, nr, arg;
+ unsigned int nr, arg;
+ sector_t from;
int err = 0, type = MMC_BLK_SECDISCARD;
blk_status_t status = BLK_STS_OK;
@@ -1759,6 +1777,11 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
brq->mrq.sbc = &brq->sbc;
}
+
+ if (mmc_card_ult_capacity(card)) {
+ brq->cmd.ext_addr = blk_rq_pos(req) >> 32;
+ brq->cmd.has_ext_addr = true;
+ }
}
#define MMC_MAX_RETRIES 5
@@ -2501,6 +2524,56 @@ static inline int mmc_blk_readonly(struct mmc_card *card)
!(card->csd.cmdclass & CCC_BLOCK_WRITE);
}
+/*
+ * Search for a declared partitions node for the disk in mmc-card related node.
+ *
+ * This is to permit support for partition table defined in DT in special case
+ * where a partition table is not written in the disk and is expected to be
+ * passed from the running system.
+ *
+ * For the user disk, "partitions" node is searched.
+ * For the special HW disk, "partitions-" node with the appended name is used
+ * following this conversion table (to adhere to JEDEC naming)
+ * - boot0 -> partitions-boot1
+ * - boot1 -> partitions-boot2
+ * - gp0 -> partitions-gp1
+ * - gp1 -> partitions-gp2
+ * - gp2 -> partitions-gp3
+ * - gp3 -> partitions-gp4
+ */
+static struct fwnode_handle *mmc_blk_get_partitions_node(struct device *mmc_dev,
+ const char *subname)
+{
+ const char *node_name = "partitions";
+
+ if (subname) {
+ mmc_dev = mmc_dev->parent;
+
+ /*
+ * Check if we are allocating a BOOT disk boot0/1 disk.
+ * In DT we use the JEDEC naming boot1/2.
+ */
+ if (!strcmp(subname, "boot0"))
+ node_name = "partitions-boot1";
+ if (!strcmp(subname, "boot1"))
+ node_name = "partitions-boot2";
+ /*
+ * Check if we are allocating a GP disk gp0/1/2/3 disk.
+ * In DT we use the JEDEC naming gp1/2/3/4.
+ */
+ if (!strcmp(subname, "gp0"))
+ node_name = "partitions-gp1";
+ if (!strcmp(subname, "gp1"))
+ node_name = "partitions-gp2";
+ if (!strcmp(subname, "gp2"))
+ node_name = "partitions-gp3";
+ if (!strcmp(subname, "gp3"))
+ node_name = "partitions-gp4";
+ }
+
+ return device_get_named_child_node(mmc_dev, node_name);
+}
+
static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
struct device *parent,
sector_t size,
@@ -2509,6 +2582,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
int area_type,
unsigned int part_type)
{
+ struct fwnode_handle *disk_fwnode;
struct mmc_blk_data *md;
int devidx, ret;
char cap_str[10];
@@ -2547,7 +2621,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
if (mmc_host_cmd23(card->host)) {
if ((mmc_card_mmc(card) &&
card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
- (mmc_card_sd(card) &&
+ (mmc_card_sd(card) && !mmc_card_ult_capacity(card) &&
card->scr.cmds & SD_SCR_CMD23_SUPPORT))
md->flags |= MMC_BLK_CMD23;
}
@@ -2610,7 +2684,9 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
/* used in ->open, must be set before add_disk: */
if (area_type == MMC_BLK_DATA_AREA_MAIN)
dev_set_drvdata(&card->dev, md);
- ret = device_add_disk(md->parent, md->disk, mmc_disk_attr_groups);
+ disk_fwnode = mmc_blk_get_partitions_node(parent, subname);
+ ret = add_disk_fwnode(md->parent, md->disk, mmc_disk_attr_groups,
+ disk_fwnode);
if (ret)
goto err_put_disk;
return md;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 0ddaee0eae54..9283b28bc69f 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -299,6 +299,7 @@ int mmc_add_card(struct mmc_card *card)
{
int ret;
const char *type;
+ const char *speed_mode = "";
const char *uhs_bus_speed_mode = "";
static const char *const uhs_speeds[] = {
[UHS_SDR12_BUS_SPEED] = "SDR12 ",
@@ -321,7 +322,9 @@ int mmc_add_card(struct mmc_card *card)
case MMC_TYPE_SD:
type = "SD";
if (mmc_card_blockaddr(card)) {
- if (mmc_card_ext_capacity(card))
+ if (mmc_card_ult_capacity(card))
+ type = "SDUC";
+ else if (mmc_card_ext_capacity(card))
type = "SDXC";
else
type = "SDHC";
@@ -340,27 +343,32 @@ int mmc_add_card(struct mmc_card *card)
break;
}
+ if (mmc_card_hs(card))
+ speed_mode = "high speed ";
+ else if (mmc_card_uhs(card))
+ speed_mode = "UHS-I speed ";
+ else if (mmc_card_uhs2(card->host))
+ speed_mode = "UHS-II speed ";
+ else if (mmc_card_ddr52(card))
+ speed_mode = "high speed DDR ";
+ else if (mmc_card_hs200(card))
+ speed_mode = "HS200 ";
+ else if (mmc_card_hs400es(card))
+ speed_mode = "HS400 Enhanced strobe ";
+ else if (mmc_card_hs400(card))
+ speed_mode = "HS400 ";
+
if (mmc_card_uhs(card) &&
(card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))
uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];
- if (mmc_host_is_spi(card->host)) {
- pr_info("%s: new %s%s%s card on SPI\n",
- mmc_hostname(card->host),
- mmc_card_hs(card) ? "high speed " : "",
- mmc_card_ddr52(card) ? "DDR " : "",
- type);
- } else {
- pr_info("%s: new %s%s%s%s%s%s card at address %04x\n",
- mmc_hostname(card->host),
- mmc_card_uhs(card) ? "ultra high speed " :
- (mmc_card_hs(card) ? "high speed " : ""),
- mmc_card_hs400(card) ? "HS400 " :
- (mmc_card_hs200(card) ? "HS200 " : ""),
- mmc_card_hs400es(card) ? "Enhanced strobe " : "",
- mmc_card_ddr52(card) ? "DDR " : "",
+ if (mmc_host_is_spi(card->host))
+ pr_info("%s: new %s%s card on SPI\n",
+ mmc_hostname(card->host), speed_mode, type);
+ else
+ pr_info("%s: new %s%s%s card at address %04x\n",
+ mmc_hostname(card->host), speed_mode,
uhs_bus_speed_mode, type, card->rca);
- }
mmc_add_card_debugfs(card);
card->dev.of_node = mmc_of_find_child_device(card->host, 0);
diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
index b7754a1b8d97..3205feb1e8ff 100644
--- a/drivers/mmc/core/card.h
+++ b/drivers/mmc/core/card.h
@@ -23,6 +23,7 @@
#define MMC_CARD_SDXC (1<<3) /* card is SDXC */
#define MMC_CARD_REMOVED (1<<4) /* card has been removed */
#define MMC_STATE_SUSPENDED (1<<5) /* card is suspended */
+#define MMC_CARD_SDUC (1<<6) /* card is SDUC */
#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
@@ -30,11 +31,13 @@
#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
#define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
+#define mmc_card_ult_capacity(c) ((c)->state & MMC_CARD_SDUC)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
+#define mmc_card_set_ult_capacity(c) ((c)->state |= MMC_CARD_SDUC)
#define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
#define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
#define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
@@ -82,6 +85,7 @@ struct mmc_fixup {
#define CID_MANFID_SANDISK_SD 0x3
#define CID_MANFID_ATP 0x9
#define CID_MANFID_TOSHIBA 0x11
+#define CID_MANFID_GIGASTONE 0x12
#define CID_MANFID_MICRON 0x13
#define CID_MANFID_SAMSUNG 0x15
#define CID_MANFID_APACER 0x27
@@ -284,4 +288,10 @@ static inline int mmc_card_broken_cache_flush(const struct mmc_card *c)
{
return c->quirks & MMC_QUIRK_BROKEN_CACHE_FLUSH;
}
+
+static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c)
+{
+ return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY;
+}
+
#endif
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d6c819dd68ed..a499f3c59de5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -336,6 +336,9 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
int err;
+ if (mrq->cmd && mrq->cmd->has_ext_addr)
+ mmc_send_ext_addr(host, mrq->cmd->ext_addr);
+
init_completion(&mrq->cmd_completion);
mmc_retune_hold(host);
@@ -351,6 +354,9 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
if (err)
return err;
+ if (host->uhs2_sd_tran)
+ mmc_uhs2_prepare_cmd(host, mrq);
+
led_trigger_event(host->led, LED_FULL);
__mmc_start_request(host, mrq);
@@ -450,6 +456,9 @@ int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq)
if (err)
goto out_err;
+ if (host->uhs2_sd_tran)
+ mmc_uhs2_prepare_cmd(host, mrq);
+
err = host->cqe_ops->cqe_request(host, mrq);
if (err)
goto out_err;
@@ -1132,7 +1141,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
return 0;
}
- if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
+ if (!mmc_card_uhs2(host) && host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
bit = ffs(ocr) - 1;
ocr &= 3 << bit;
mmc_power_cycle(host, ocr);
@@ -1598,8 +1607,8 @@ static unsigned int mmc_erase_timeout(struct mmc_card *card,
return mmc_mmc_erase_timeout(card, arg, qty);
}
-static int mmc_do_erase(struct mmc_card *card, unsigned int from,
- unsigned int to, unsigned int arg)
+static int mmc_do_erase(struct mmc_card *card, sector_t from,
+ sector_t to, unsigned int arg)
{
struct mmc_command cmd = {};
unsigned int qty = 0, busy_timeout = 0;
@@ -1630,8 +1639,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
else if (mmc_card_sd(card))
qty += to - from + 1;
else
- qty += ((to / card->erase_size) -
- (from / card->erase_size)) + 1;
+ qty += (mmc_sector_div(to, card->erase_size) -
+ mmc_sector_div(from, card->erase_size)) + 1;
if (!mmc_card_blockaddr(card)) {
from <<= 9;
@@ -1644,6 +1653,12 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.opcode = MMC_ERASE_GROUP_START;
cmd.arg = from;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+
+ if (mmc_card_ult_capacity(card)) {
+ cmd.ext_addr = from >> 32;
+ cmd.has_ext_addr = true;
+ }
+
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
pr_err("mmc_erase: group start error %d, "
@@ -1659,6 +1674,12 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.opcode = MMC_ERASE_GROUP_END;
cmd.arg = to;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+
+ if (mmc_card_ult_capacity(card)) {
+ cmd.ext_addr = to >> 32;
+ cmd.has_ext_addr = true;
+ }
+
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
pr_err("mmc_erase: group end error %d, status %#x\n",
@@ -1700,18 +1721,19 @@ out:
}
static unsigned int mmc_align_erase_size(struct mmc_card *card,
- unsigned int *from,
- unsigned int *to,
+ sector_t *from,
+ sector_t *to,
unsigned int nr)
{
- unsigned int from_new = *from, nr_new = nr, rem;
+ sector_t from_new = *from;
+ unsigned int nr_new = nr, rem;
/*
* When the 'card->erase_size' is power of 2, we can use round_up/down()
* to align the erase size efficiently.
*/
if (is_power_of_2(card->erase_size)) {
- unsigned int temp = from_new;
+ sector_t temp = from_new;
from_new = round_up(temp, card->erase_size);
rem = from_new - temp;
@@ -1723,7 +1745,7 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card,
nr_new = round_down(nr_new, card->erase_size);
} else {
- rem = from_new % card->erase_size;
+ rem = mmc_sector_mod(from_new, card->erase_size);
if (rem) {
rem = card->erase_size - rem;
from_new += rem;
@@ -1756,10 +1778,12 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card,
*
* Caller must claim host before calling this function.
*/
-int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
+int mmc_erase(struct mmc_card *card, sector_t from, unsigned int nr,
unsigned int arg)
{
- unsigned int rem, to = from + nr;
+ unsigned int rem;
+ sector_t to = from + nr;
+
int err;
if (!(card->csd.cmdclass & CCC_ERASE))
@@ -1780,7 +1804,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
return -EOPNOTSUPP;
if (arg == MMC_SECURE_ERASE_ARG) {
- if (from % card->erase_size || nr % card->erase_size)
+ if (mmc_sector_mod(from, card->erase_size) || nr % card->erase_size)
return -EINVAL;
}
@@ -1804,7 +1828,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
* and call mmc_do_erase() twice if necessary. This special case is
* identified by the card->eg_boundary flag.
*/
- rem = card->erase_size - (from % card->erase_size);
+ rem = card->erase_size - mmc_sector_mod(from, card->erase_size);
if ((arg & MMC_TRIM_OR_DISCARD_ARGS) && card->eg_boundary && nr > rem) {
err = mmc_do_erase(card, from, from + rem - 1, arg);
from += rem;
@@ -1863,12 +1887,12 @@ int mmc_can_secure_erase_trim(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_can_secure_erase_trim);
-int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
+int mmc_erase_group_aligned(struct mmc_card *card, sector_t from,
unsigned int nr)
{
if (!card->erase_size)
return 0;
- if (from % card->erase_size || nr % card->erase_size)
+ if (mmc_sector_mod(from, card->erase_size) || nr % card->erase_size)
return 0;
return 1;
}
@@ -2249,6 +2273,18 @@ void mmc_rescan(struct work_struct *work)
goto out;
}
+ /*
+ * Ideally we should favor initialization of legacy SD cards and defer
+ * UHS-II enumeration. However, it seems like cards doesn't reliably
+ * announce their support for UHS-II in the response to the ACMD41,
+ * while initializing the legacy SD interface. Therefore, let's start
+ * with UHS-II for now.
+ */
+ if (!mmc_attach_sd_uhs2(host)) {
+ mmc_release_host(host);
+ goto out;
+ }
+
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
unsigned int freq = freqs[i];
if (freq > host->f_max) {
@@ -2281,10 +2317,13 @@ void mmc_rescan(struct work_struct *work)
void mmc_start_host(struct mmc_host *host)
{
+ bool power_up = !(host->caps2 &
+ (MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_SD_UHS2));
+
host->f_init = max(min(freqs[0], host->f_max), host->f_min);
host->rescan_disable = 0;
- if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) {
+ if (power_up) {
mmc_claim_host(host);
mmc_power_up(host, host->ocr_avail);
mmc_release_host(host);
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 37091a6589ed..fc9c066e6468 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -81,6 +81,7 @@ int mmc_detect_card_removed(struct mmc_host *host);
int mmc_attach_mmc(struct mmc_host *host);
int mmc_attach_sd(struct mmc_host *host);
int mmc_attach_sdio(struct mmc_host *host);
+int mmc_attach_sd_uhs2(struct mmc_host *host);
/* Module parameters */
extern bool use_spi_crc;
@@ -116,15 +117,13 @@ bool mmc_is_req_done(struct mmc_host *host, struct mmc_request *mrq);
int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq);
-int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
- unsigned int arg);
+int mmc_erase(struct mmc_card *card, sector_t from, unsigned int nr, unsigned int arg);
int mmc_can_erase(struct mmc_card *card);
int mmc_can_trim(struct mmc_card *card);
int mmc_can_discard(struct mmc_card *card);
int mmc_can_sanitize(struct mmc_card *card);
int mmc_can_secure_erase_trim(struct mmc_card *card);
-int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
- unsigned int nr);
+int mmc_erase_group_aligned(struct mmc_card *card, sector_t from, unsigned int nr);
unsigned int mmc_calc_max_discard(struct mmc_card *card);
int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
@@ -199,4 +198,14 @@ static inline int mmc_flush_cache(struct mmc_host *host)
return 0;
}
+static inline unsigned int mmc_sector_div(sector_t dividend, u32 divisor)
+{
+ return div_u64(dividend, divisor);
+}
+
+static inline unsigned int mmc_sector_mod(sector_t dividend, u32 divisor)
+{
+ return sector_div(dividend, divisor);
+}
+
#endif
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 3b3adbddf664..5c8e62e8f331 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -144,10 +144,24 @@ int mmc_set_dsr(struct mmc_host *host)
return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
}
+int __mmc_go_idle(struct mmc_host *host)
+{
+ struct mmc_command cmd = {};
+ int err;
+
+ cmd.opcode = MMC_GO_IDLE_STATE;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ mmc_delay(1);
+
+ return err;
+}
+
int mmc_go_idle(struct mmc_host *host)
{
int err;
- struct mmc_command cmd = {};
/*
* Non-SPI hosts need to prevent chipselect going active during
@@ -163,13 +177,7 @@ int mmc_go_idle(struct mmc_host *host)
mmc_delay(1);
}
- cmd.opcode = MMC_GO_IDLE_STATE;
- cmd.arg = 0;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
-
- err = mmc_wait_for_cmd(host, &cmd, 0);
-
- mmc_delay(1);
+ err = __mmc_go_idle(host);
if (!mmc_host_is_spi(host)) {
mmc_set_chip_select(host, MMC_CS_DONTCARE);
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 06017110e1b0..0df3ebd900d1 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -25,6 +25,7 @@ struct mmc_command;
int mmc_select_card(struct mmc_card *card);
int mmc_deselect_cards(struct mmc_host *host);
int mmc_set_dsr(struct mmc_host *host);
+int __mmc_go_idle(struct mmc_host *host);
int mmc_go_idle(struct mmc_host *host);
int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_set_relative_addr(struct mmc_card *card);
diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c
index b7f627a9fdea..4f4286b8e0f2 100644
--- a/drivers/mmc/core/mmc_test.c
+++ b/drivers/mmc/core/mmc_test.c
@@ -3241,6 +3241,12 @@ static int mmc_test_probe(struct mmc_card *card)
if (!mmc_card_mmc(card) && !mmc_card_sd(card))
return -ENODEV;
+ if (mmc_card_ult_capacity(card)) {
+ pr_info("%s: mmc-test currently UNSUPPORTED for SDUC\n",
+ mmc_hostname(card->host));
+ return -EOPNOTSUPP;
+ }
+
ret = mmc_test_register_dbgfs_file(card);
if (ret)
return ret;
diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c
index 96fa4c508900..35af67e26945 100644
--- a/drivers/mmc/core/pwrseq_emmc.c
+++ b/drivers/mmc/core/pwrseq_emmc.c
@@ -107,7 +107,7 @@ MODULE_DEVICE_TABLE(of, mmc_pwrseq_emmc_of_match);
static struct platform_driver mmc_pwrseq_emmc_driver = {
.probe = mmc_pwrseq_emmc_probe,
- .remove_new = mmc_pwrseq_emmc_remove,
+ .remove = mmc_pwrseq_emmc_remove,
.driver = {
.name = "pwrseq_emmc",
.of_match_table = mmc_pwrseq_emmc_of_match,
diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c
index f24bbd68e251..30282155a0e1 100644
--- a/drivers/mmc/core/pwrseq_sd8787.c
+++ b/drivers/mmc/core/pwrseq_sd8787.c
@@ -122,7 +122,7 @@ static void mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
static struct platform_driver mmc_pwrseq_sd8787_driver = {
.probe = mmc_pwrseq_sd8787_probe,
- .remove_new = mmc_pwrseq_sd8787_remove,
+ .remove = mmc_pwrseq_sd8787_remove,
.driver = {
.name = "pwrseq_sd8787",
.of_match_table = mmc_pwrseq_sd8787_of_match,
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 154a8921ae75..37cd858df0f4 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -17,6 +17,8 @@
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/property.h>
+#include <linux/of.h>
+#include <linux/reset.h>
#include <linux/mmc/host.h>
@@ -29,6 +31,7 @@ struct mmc_pwrseq_simple {
u32 power_off_delay_us;
struct clk *ext_clk;
struct gpio_descs *reset_gpios;
+ struct reset_control *reset_ctrl;
};
#define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
@@ -67,14 +70,21 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
pwrseq->clk_enabled = true;
}
- mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+ if (pwrseq->reset_ctrl) {
+ reset_control_deassert(pwrseq->reset_ctrl);
+ reset_control_assert(pwrseq->reset_ctrl);
+ } else
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
}
static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
{
struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
- mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
+ if (pwrseq->reset_ctrl)
+ reset_control_deassert(pwrseq->reset_ctrl);
+ else
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
if (pwrseq->post_power_on_delay_ms)
msleep(pwrseq->post_power_on_delay_ms);
@@ -84,7 +94,10 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
{
struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
- mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+ if (pwrseq->reset_ctrl)
+ reset_control_assert(pwrseq->reset_ctrl);
+ else
+ mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
if (pwrseq->power_off_delay_us)
usleep_range(pwrseq->power_off_delay_us,
@@ -112,6 +125,7 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
{
struct mmc_pwrseq_simple *pwrseq;
struct device *dev = &pdev->dev;
+ int ngpio;
pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
if (!pwrseq)
@@ -121,12 +135,26 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT)
return dev_err_probe(dev, PTR_ERR(pwrseq->ext_clk), "external clock not ready\n");
- pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset",
- GPIOD_OUT_HIGH);
- if (IS_ERR(pwrseq->reset_gpios) &&
- PTR_ERR(pwrseq->reset_gpios) != -ENOENT &&
- PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) {
- return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios), "reset GPIOs not ready\n");
+ ngpio = of_count_phandle_with_args(dev->of_node, "reset-gpios", "#gpio-cells");
+ if (ngpio == 1) {
+ pwrseq->reset_ctrl = devm_reset_control_get_optional_shared(dev, NULL);
+ if (IS_ERR(pwrseq->reset_ctrl))
+ return dev_err_probe(dev, PTR_ERR(pwrseq->reset_ctrl),
+ "reset control not ready\n");
+ }
+
+ /*
+ * Fallback to GPIO based reset control in case of multiple reset lines
+ * are specified or the platform doesn't have support for RESET at all.
+ */
+ if (!pwrseq->reset_ctrl) {
+ pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(pwrseq->reset_gpios) &&
+ PTR_ERR(pwrseq->reset_gpios) != -ENOENT &&
+ PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) {
+ return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios),
+ "reset GPIOs not ready\n");
+ }
}
device_property_read_u32(dev, "post-power-on-delay-ms",
@@ -151,7 +179,7 @@ static void mmc_pwrseq_simple_remove(struct platform_device *pdev)
static struct platform_driver mmc_pwrseq_simple_driver = {
.probe = mmc_pwrseq_simple_probe,
- .remove_new = mmc_pwrseq_simple_remove,
+ .remove = mmc_pwrseq_simple_remove,
.driver = {
.name = "pwrseq_simple",
.of_match_table = mmc_pwrseq_simple_of_match,
diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
index 92905fc46436..89b512905be1 100644
--- a/drivers/mmc/core/quirks.h
+++ b/drivers/mmc/core/quirks.h
@@ -25,6 +25,15 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = {
0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY),
+ /*
+ * GIGASTONE Gaming Plus microSD cards manufactured on 02/2022 never
+ * clear Flush Cache bit and set Poweroff Notification Ready bit.
+ */
+ _FIXUP_EXT("ASTC", CID_MANFID_GIGASTONE, 0x3456, 2022, 2,
+ 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
+ MMC_QUIRK_BROKEN_SD_CACHE | MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY,
+ EXT_CSD_REV_ANY),
+
END_FIXUP
};
diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c
index 01747ab1024e..3dae2e9b7978 100644
--- a/drivers/mmc/core/regulator.c
+++ b/drivers/mmc/core/regulator.c
@@ -226,6 +226,33 @@ int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
}
EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc);
+/**
+ * mmc_regulator_set_vqmmc2 - Set vqmmc2 as per the ios->vqmmc2_voltage
+ * @mmc: The mmc host to regulate
+ * @ios: The io bus settings
+ *
+ * Sets a new voltage level for the vqmmc2 regulator, which may correspond to
+ * the vdd2 regulator for an SD UHS-II interface. This function is expected to
+ * be called by mmc host drivers.
+ *
+ * Returns a negative error code on failure, zero if the voltage level was
+ * changed successfully or a positive value if the level didn't need to change.
+ */
+int mmc_regulator_set_vqmmc2(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ if (IS_ERR(mmc->supply.vqmmc2))
+ return -EINVAL;
+
+ switch (ios->vqmmc2_voltage) {
+ case MMC_VQMMC2_VOLTAGE_180:
+ return mmc_regulator_set_voltage_if_supported(
+ mmc->supply.vqmmc2, 1700000, 1800000, 1950000);
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc2);
+
#else
static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
@@ -252,6 +279,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc");
+ mmc->supply.vqmmc2 = devm_regulator_get_optional(dev, "vqmmc2");
if (IS_ERR(mmc->supply.vmmc)) {
if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
@@ -275,6 +303,12 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
dev_dbg(dev, "No vqmmc regulator found\n");
}
+ if (IS_ERR(mmc->supply.vqmmc2)) {
+ if (PTR_ERR(mmc->supply.vqmmc2) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_dbg(dev, "No vqmmc2 regulator found\n");
+ }
+
return 0;
}
EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 12fe282bea77..cc757b850e79 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -100,7 +100,7 @@ void mmc_decode_cid(struct mmc_card *card)
/*
* Given a 128-bit response, decode to our card CSD structure.
*/
-static int mmc_decode_csd(struct mmc_card *card)
+static int mmc_decode_csd(struct mmc_card *card, bool is_sduc)
{
struct mmc_csd *csd = &card->csd;
unsigned int e, m, csd_struct;
@@ -144,9 +144,10 @@ static int mmc_decode_csd(struct mmc_card *card)
mmc_card_set_readonly(card);
break;
case 1:
+ case 2:
/*
- * This is a block-addressed SDHC or SDXC card. Most
- * interesting fields are unused and have fixed
+ * This is a block-addressed SDHC, SDXC or SDUC card.
+ * Most interesting fields are unused and have fixed
* values. To avoid getting tripped by buggy cards,
* we assume those fixed values ourselves.
*/
@@ -159,14 +160,19 @@ static int mmc_decode_csd(struct mmc_card *card)
e = unstuff_bits(resp, 96, 3);
csd->max_dtr = tran_exp[e] * tran_mant[m];
csd->cmdclass = unstuff_bits(resp, 84, 12);
- csd->c_size = unstuff_bits(resp, 48, 22);
- /* SDXC cards have a minimum C_SIZE of 0x00FFFF */
- if (csd->c_size >= 0xFFFF)
+ if (csd_struct == 1)
+ m = unstuff_bits(resp, 48, 22);
+ else
+ m = unstuff_bits(resp, 48, 28);
+ csd->c_size = m;
+
+ if (csd->c_size >= 0x400000 && is_sduc)
+ mmc_card_set_ult_capacity(card);
+ else if (csd->c_size >= 0xFFFF)
mmc_card_set_ext_capacity(card);
- m = unstuff_bits(resp, 48, 22);
- csd->capacity = (1 + m) << 10;
+ csd->capacity = (1 + (typeof(sector_t))m) << 10;
csd->read_blkbits = 9;
csd->read_partial = 0;
@@ -194,7 +200,7 @@ static int mmc_decode_csd(struct mmc_card *card)
/*
* Given a 64-bit response, decode to our card SCR structure.
*/
-static int mmc_decode_scr(struct mmc_card *card)
+int mmc_decode_scr(struct mmc_card *card)
{
struct sd_scr *scr = &card->scr;
unsigned int scr_struct;
@@ -830,8 +836,11 @@ try_again:
* block-addressed SDHC cards.
*/
err = mmc_send_if_cond(host, ocr);
- if (!err)
+ if (!err) {
ocr |= SD_OCR_CCS;
+ /* Set HO2T as well - SDUC card won't respond otherwise */
+ ocr |= SD_OCR_2T;
+ }
/*
* If the host supports one of UHS-I modes, request the card
@@ -876,7 +885,7 @@ try_again:
return err;
}
-int mmc_sd_get_csd(struct mmc_card *card)
+int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc)
{
int err;
@@ -887,14 +896,14 @@ int mmc_sd_get_csd(struct mmc_card *card)
if (err)
return err;
- err = mmc_decode_csd(card);
+ err = mmc_decode_csd(card, is_sduc);
if (err)
return err;
return 0;
}
-static int mmc_sd_get_ro(struct mmc_host *host)
+int mmc_sd_get_ro(struct mmc_host *host)
{
int ro;
@@ -1107,7 +1116,7 @@ static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page,
card->ext_power.rev = reg_buf[0] & 0xf;
/* Power Off Notification support at bit 4. */
- if (reg_buf[1] & BIT(4))
+ if ((reg_buf[1] & BIT(4)) && !mmc_card_broken_sd_poweroff_notify(card))
card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY;
/* Power Sustenance support at bit 5. */
@@ -1442,7 +1451,10 @@ retry:
}
if (!oldcard) {
- err = mmc_sd_get_csd(card);
+ u32 sduc_arg = SD_OCR_CCS | SD_OCR_2T;
+ bool is_sduc = (rocr & sduc_arg) == sduc_arg;
+
+ err = mmc_sd_get_csd(card, is_sduc);
if (err)
goto free_card;
@@ -1552,7 +1564,7 @@ cont:
goto free_card;
}
- if (host->cqe_ops && !host->cqe_enabled) {
+ if (!mmc_card_ult_capacity(card) && host->cqe_ops && !host->cqe_enabled) {
err = host->cqe_ops->cqe_enable(host, card);
if (!err) {
host->cqe_enabled = true;
diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h
index fe6dd46927a4..301dc34b8b63 100644
--- a/drivers/mmc/core/sd.h
+++ b/drivers/mmc/core/sd.h
@@ -10,7 +10,9 @@ struct mmc_host;
struct mmc_card;
int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr);
-int mmc_sd_get_csd(struct mmc_card *card);
+int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc);
+int mmc_decode_scr(struct mmc_card *card);
+int mmc_sd_get_ro(struct mmc_host *host);
void mmc_decode_cid(struct mmc_card *card);
int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
bool reinit);
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index f93c392040ae..cd86463dd306 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -16,6 +16,7 @@
#include <linux/mmc/sd.h>
#include "core.h"
+#include "card.h"
#include "sd_ops.h"
#include "mmc_ops.h"
@@ -41,6 +42,15 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
if (WARN_ON(card && card->host != host))
return -EINVAL;
+ /*
+ * UHS2 packet has APP bit so only set APP_CMD flag here.
+ * Will set the APP bit when assembling UHS2 packet.
+ */
+ if (host->uhs2_sd_tran) {
+ host->uhs2_app_cmd = true;
+ return 0;
+ }
+
cmd.opcode = MMC_APP_CMD;
if (card) {
@@ -188,6 +198,20 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
return 0;
}
+int mmc_send_ext_addr(struct mmc_host *host, u32 addr)
+{
+ struct mmc_command cmd = {
+ .opcode = SD_ADDR_EXT,
+ .arg = addr,
+ .flags = MMC_RSP_R1 | MMC_CMD_AC,
+ };
+
+ if (!mmc_card_ult_capacity(host->card))
+ return 0;
+
+ return mmc_wait_for_cmd(host, &cmd, 0);
+}
+
static int __mmc_send_if_cond(struct mmc_host *host, u32 ocr, u8 pcie_bits,
u32 *resp)
{
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
index 7667fc223b74..8fffc1b29757 100644
--- a/drivers/mmc/core/sd_ops.h
+++ b/drivers/mmc/core/sd_ops.h
@@ -12,6 +12,7 @@
struct mmc_card;
struct mmc_host;
+struct mmc_request;
int mmc_app_set_bus_width(struct mmc_card *card, int width);
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
@@ -21,6 +22,8 @@ int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
int mmc_app_send_scr(struct mmc_card *card);
int mmc_app_sd_status(struct mmc_card *card, void *ssr);
int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
+int mmc_send_ext_addr(struct mmc_host *host, u32 addr);
+void mmc_uhs2_prepare_cmd(struct mmc_host *host, struct mmc_request *mrq);
#endif
diff --git a/drivers/mmc/core/sd_uhs2.c b/drivers/mmc/core/sd_uhs2.c
new file mode 100644
index 000000000000..1c31d0dfa961
--- /dev/null
+++ b/drivers/mmc/core/sd_uhs2.c
@@ -0,0 +1,1304 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Linaro Ltd
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * Copyright (C) 2014 Intel Corp, All Rights Reserved.
+ * Author: Yi Sun <yi.y.sun@intel.com>
+ *
+ * Copyright (C) 2020 Genesys Logic, Inc.
+ * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw>
+ *
+ * Copyright (C) 2020 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * Copyright (C) 2022 Genesys Logic, Inc.
+ * Authors: Jason Lai <jason.lai@genesyslogic.com.tw>
+ *
+ * Copyright (C) 2023 Genesys Logic, Inc.
+ * Authors: Victor Shih <victor.shih@genesyslogic.com.tw>
+ *
+ * Support for SD UHS-II cards
+ */
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/sd_uhs2.h>
+
+#include "card.h"
+#include "core.h"
+#include "bus.h"
+#include "sd.h"
+#include "sd_ops.h"
+#include "mmc_ops.h"
+
+#define UHS2_WAIT_CFG_COMPLETE_PERIOD_US (1 * 1000)
+#define UHS2_WAIT_CFG_COMPLETE_TIMEOUT_MS 100
+
+static const unsigned int sd_uhs2_freqs[] = { 52000000, 26000000 };
+
+struct sd_uhs2_wait_active_state_data {
+ struct mmc_host *host;
+ struct mmc_command *cmd;
+};
+
+static int sd_uhs2_power_up(struct mmc_host *host)
+{
+ if (host->ios.power_mode == MMC_POWER_ON)
+ return 0;
+
+ host->ios.vdd = fls(host->ocr_avail) - 1;
+ host->ios.clock = host->f_init;
+ host->ios.timing = MMC_TIMING_UHS2_SPEED_A;
+ host->ios.power_mode = MMC_POWER_ON;
+
+ return host->ops->uhs2_control(host, UHS2_SET_IOS);
+}
+
+static int sd_uhs2_power_off(struct mmc_host *host)
+{
+ int err;
+
+ if (host->ios.power_mode == MMC_POWER_OFF)
+ return 0;
+
+ host->ios.vdd = 0;
+ host->ios.clock = 0;
+ host->ios.power_mode = MMC_POWER_OFF;
+ host->uhs2_sd_tran = false;
+
+ err = host->ops->uhs2_control(host, UHS2_SET_IOS);
+ if (err)
+ return err;
+
+ /* For consistency, let's restore the initial timing. */
+ host->ios.timing = MMC_TIMING_LEGACY;
+ return 0;
+}
+
+/*
+ * Run the phy initialization sequence, which mainly relies on the UHS-II host
+ * to check that we reach the expected electrical state, between the host and
+ * the card.
+ */
+static int sd_uhs2_phy_init(struct mmc_host *host)
+{
+ int err;
+
+ err = host->ops->uhs2_control(host, UHS2_PHY_INIT);
+ if (err) {
+ pr_err("%s: failed to initial phy for UHS-II!\n",
+ mmc_hostname(host));
+ }
+
+ return err;
+}
+
+/*
+ * sd_uhs2_cmd_assemble() - build up UHS-II command packet which is embedded in
+ * mmc_command structure
+ * @cmd: MMC command to executed
+ * @uhs2_cmd: UHS2 command corresponded to MMC command
+ * @header: Header field of UHS-II command cxpacket
+ * @arg: Argument field of UHS-II command packet
+ * @payload: Payload field of UHS-II command packet
+ * @plen: Payload length
+ * @resp: Response buffer is allocated by caller and it is used to keep
+ * the response of CM-TRAN command. For SD-TRAN command, uhs2_resp
+ * should be null and SD-TRAN command response should be stored in
+ * resp of mmc_command.
+ * @resp_len: Response buffer length
+ *
+ * The uhs2_command structure contains message packets which are transmited/
+ * received on UHS-II bus. This function fills in the contents of uhs2_command
+ * structure and embededs UHS2 command into mmc_command structure, which is used
+ * in legacy SD operation functions.
+ *
+ */
+static void sd_uhs2_cmd_assemble(struct mmc_command *cmd,
+ struct uhs2_command *uhs2_cmd,
+ u8 plen, u8 resp_len)
+{
+ uhs2_cmd->payload_len = plen * sizeof(u32);
+ uhs2_cmd->packet_len = uhs2_cmd->payload_len + 4;
+
+ cmd->uhs2_cmd = uhs2_cmd;
+ cmd->uhs2_cmd->uhs2_resp_len = resp_len;
+}
+
+/*
+ * Do the early initialization of the card, by sending the device init broadcast
+ * command and wait for the process to be completed.
+ */
+static int sd_uhs2_dev_init(struct mmc_host *host)
+{
+ struct mmc_command cmd = {0};
+ struct uhs2_command uhs2_cmd = {};
+ u32 cnt;
+ u32 dap, gap, resp_gap;
+ u32 payload0;
+ u8 gd = 0;
+ int err;
+
+ dap = host->uhs2_caps.dap;
+ gap = host->uhs2_caps.gap;
+
+ /*
+ * Refer to UHS-II Addendum Version 1.02 Figure 6-21 to see DEVICE_INIT CCMD format.
+ * Head:
+ * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b).
+ * - IOADR = CMD_BASE + 002h
+ * Payload:
+ * - bit [3:0] : GAP(Group Allocated Power)
+ * - bit [7:4] : GD(Group Descriptor)
+ * - bit [11] : Complete Flag
+ * - bit [15:12]: DAP(Device Allocated Power)
+ */
+ uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD;
+ uhs2_cmd.arg = ((UHS2_DEV_CMD_DEVICE_INIT & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_WRITE |
+ UHS2_NATIVE_CMD_PLEN_4B |
+ (UHS2_DEV_CMD_DEVICE_INIT >> 8);
+
+ /*
+ * Refer to UHS-II Addendum Version 1.02 section 6.3.1.
+ * Max. time from DEVICE_INIT CCMD EOP reception on Device
+ * Rx to its SOP transmission on Device Tx(Tfwd_init_cmd) is
+ * 1 second.
+ */
+ cmd.busy_timeout = 1000;
+
+ /*
+ * Refer to UHS-II Addendum Version 1.02 section 6.2.6.3.
+ * Let's retry the DEVICE_INIT command no more than 30 times.
+ */
+ for (cnt = 0; cnt < 30; cnt++) {
+ payload0 = ((dap & 0xF) << 12) |
+ UHS2_DEV_INIT_COMPLETE_FLAG |
+ ((gd & 0xF) << 4) |
+ (gap & 0xF);
+ uhs2_cmd.payload[0] = (__force __be32)payload0;
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_DEV_INIT_PAYLOAD_LEN,
+ UHS2_DEV_INIT_RESP_LEN);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ continue;
+ }
+
+ if (uhs2_cmd.uhs2_resp[3] != (UHS2_DEV_CMD_DEVICE_INIT & 0xFF)) {
+ pr_err("%s: DEVICE_INIT response is wrong!\n",
+ mmc_hostname(host));
+ return -EIO;
+ }
+
+ if (uhs2_cmd.uhs2_resp[5] & 0x8) {
+ host->uhs2_caps.group_desc = gd;
+ return 0;
+ }
+ resp_gap = uhs2_cmd.uhs2_resp[4] & 0x0F;
+ if (gap == resp_gap)
+ gd++;
+ }
+
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * Run the enumeration process by sending the enumerate command to the card.
+ * Note that, we currently support only the point to point connection, which
+ * means only one card can be attached per host/slot.
+ */
+static int sd_uhs2_enum(struct mmc_host *host, u32 *node_id)
+{
+ struct mmc_command cmd = {0};
+ struct uhs2_command uhs2_cmd = {};
+ u32 payload0;
+ u8 id_f = 0xF, id_l = 0x0;
+ int err;
+
+ /*
+ * Refer to UHS-II Addendum Version 1.02 Figure 6-28 to see ENUMERATE CCMD format.
+ * Header:
+ * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b).
+ * - IOADR = CMD_BASE + 003h
+ * Payload:
+ * - bit [3:0]: ID_L(Last Node ID)
+ * - bit [7:4]: ID_F(First Node ID)
+ */
+ uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD;
+ uhs2_cmd.arg = ((UHS2_DEV_CMD_ENUMERATE & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_WRITE |
+ UHS2_NATIVE_CMD_PLEN_4B |
+ (UHS2_DEV_CMD_ENUMERATE >> 8);
+
+ payload0 = (id_f << 4) | id_l;
+ uhs2_cmd.payload[0] = cpu_to_be32(payload0);
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_DEV_ENUM_PAYLOAD_LEN, UHS2_DEV_ENUM_RESP_LEN);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ if (uhs2_cmd.uhs2_resp[3] != (UHS2_DEV_CMD_ENUMERATE & 0xFF)) {
+ pr_err("%s: ENUMERATE response is wrong!\n",
+ mmc_hostname(host));
+ return -EIO;
+ }
+
+ id_f = (uhs2_cmd.uhs2_resp[4] >> 4) & 0xF;
+ id_l = uhs2_cmd.uhs2_resp[4] & 0xF;
+ *node_id = id_f;
+
+ return 0;
+}
+
+/*
+ * Read the UHS-II configuration registers (CFG_REG) of the card, by sending it
+ * commands and by parsing the responses. Store a copy of the relevant data in
+ * card->uhs2_config.
+ */
+static int sd_uhs2_config_read(struct mmc_host *host, struct mmc_card *card)
+{
+ struct mmc_command cmd = {0};
+ struct uhs2_command uhs2_cmd = {};
+ u32 cap;
+ int err;
+
+ /*
+ * Use Control Read CCMD to read Generic Capability from Configuration Register.
+ * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b).
+ * - IOADR = Generic Capability Register(CFG_BASE + 000h)
+ */
+ uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | card->uhs2_config.node_id;
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_CAPS & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_READ |
+ UHS2_NATIVE_CMD_PLEN_4B |
+ (UHS2_DEV_CONFIG_GEN_CAPS >> 8);
+
+ /*
+ * There is no payload because per spec, there should be
+ * no payload field for read CCMD.
+ * Plen is set in arg. Per spec, plen for read CCMD
+ * represents the len of read data which is assigned in payload
+ * of following RES (p136).
+ */
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /*
+ * Generic Capability Register:
+ * bit [7:0] : Reserved
+ * bit [13:8] : Device-Specific Number of Lanes and Functionality
+ * bit 8: 2L-HD
+ * bit 9: 2D-1U FD
+ * bit 10: 1D-2U FD
+ * bit 11: 2D-2U FD
+ * Others: Reserved
+ * bit [14] : DADR Length
+ * 0: 4 bytes
+ * 1: Reserved
+ * bit [23:16]: Application Type
+ * bit 16: 0=Non-SD memory, 1=SD memory
+ * bit 17: 0=Non-SDIO, 1=SDIO
+ * bit 18: 0=Card, 1=Embedded
+ * bit [63:24]: Reserved
+ */
+ cap = cmd.resp[0];
+ card->uhs2_config.n_lanes =
+ (cap >> UHS2_DEV_CONFIG_N_LANES_POS) &
+ UHS2_DEV_CONFIG_N_LANES_MASK;
+ card->uhs2_config.dadr_len =
+ (cap >> UHS2_DEV_CONFIG_DADR_POS) &
+ UHS2_DEV_CONFIG_DADR_MASK;
+ card->uhs2_config.app_type =
+ (cap >> UHS2_DEV_CONFIG_APP_POS) &
+ UHS2_DEV_CONFIG_APP_MASK;
+
+ /*
+ * Use Control Read CCMD to read PHY Capability from Configuration Register.
+ * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b).
+ * - IOADR = PHY Capability Register(CFG_BASE + 002h)
+ */
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_PHY_CAPS & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_READ |
+ UHS2_NATIVE_CMD_PLEN_8B |
+ (UHS2_DEV_CONFIG_PHY_CAPS >> 8);
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /*
+ * PHY Capability Register:
+ * bit [3:0] : PHY Minor Revision
+ * bit [5:4] : PHY Major Revision
+ * bit [15] : Support Hibernate Mode
+ * 0: Not support Hibernate Mode
+ * 1: Support Hibernate Mode
+ * bit [31:16]: Reserved
+ * bit [35:32]: Device-Specific N_LSS_SYN
+ * bit [39:36]: Device-Specific N_LSS_DIR
+ * bit [63:40]: Reserved
+ */
+ cap = cmd.resp[0];
+ card->uhs2_config.phy_minor_rev =
+ cap & UHS2_DEV_CONFIG_PHY_MINOR_MASK;
+ card->uhs2_config.phy_major_rev =
+ (cap >> UHS2_DEV_CONFIG_PHY_MAJOR_POS) &
+ UHS2_DEV_CONFIG_PHY_MAJOR_MASK;
+ card->uhs2_config.can_hibernate =
+ (cap >> UHS2_DEV_CONFIG_CAN_HIBER_POS) &
+ UHS2_DEV_CONFIG_CAN_HIBER_MASK;
+
+ cap = cmd.resp[1];
+ card->uhs2_config.n_lss_sync =
+ cap & UHS2_DEV_CONFIG_N_LSS_SYN_MASK;
+ card->uhs2_config.n_lss_dir =
+ (cap >> UHS2_DEV_CONFIG_N_LSS_DIR_POS) &
+ UHS2_DEV_CONFIG_N_LSS_DIR_MASK;
+ if (card->uhs2_config.n_lss_sync == 0)
+ card->uhs2_config.n_lss_sync = 16 << 2;
+ else
+ card->uhs2_config.n_lss_sync <<= 2;
+
+ if (card->uhs2_config.n_lss_dir == 0)
+ card->uhs2_config.n_lss_dir = 16 << 3;
+ else
+ card->uhs2_config.n_lss_dir <<= 3;
+
+ /*
+ * Use Control Read CCMD to read LINK/TRAN Capability from Configuration Register.
+ * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b).
+ * - IOADR = LINK/TRAN Capability Register(CFG_BASE + 004h)
+ */
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_LINK_TRAN_CAPS & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_READ |
+ UHS2_NATIVE_CMD_PLEN_8B |
+ (UHS2_DEV_CONFIG_LINK_TRAN_CAPS >> 8);
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /*
+ * LINK/TRAN Capability Register:
+ * bit [3:0] : LINK_TRAN Minor Revision
+ * bit [5:4] : LINK/TRAN Major Revision
+ * bit [7:6] : Reserved
+ * bit [15:8] : Device-Specific N_FCU
+ * bit [18:16]: Device Type
+ * 001b=Host
+ * 010b=Device
+ * 011b=Reserved for CMD issuable Device
+ * bit [19] : Reserved
+ * bit [31:20]: Device-Specific MAX_BLKLEN
+ * bit [39:32]: Device-Specific N_DATA_GAP
+ * bit [63:40]: Reserved
+ */
+ cap = cmd.resp[0];
+ card->uhs2_config.link_minor_rev =
+ cap & UHS2_DEV_CONFIG_LT_MINOR_MASK;
+ card->uhs2_config.link_major_rev =
+ (cap >> UHS2_DEV_CONFIG_LT_MAJOR_POS) &
+ UHS2_DEV_CONFIG_LT_MAJOR_MASK;
+ card->uhs2_config.n_fcu =
+ (cap >> UHS2_DEV_CONFIG_N_FCU_POS) &
+ UHS2_DEV_CONFIG_N_FCU_MASK;
+ card->uhs2_config.dev_type =
+ (cap >> UHS2_DEV_CONFIG_DEV_TYPE_POS) &
+ UHS2_DEV_CONFIG_DEV_TYPE_MASK;
+ card->uhs2_config.maxblk_len =
+ (cap >> UHS2_DEV_CONFIG_MAX_BLK_LEN_POS) &
+ UHS2_DEV_CONFIG_MAX_BLK_LEN_MASK;
+
+ cap = cmd.resp[1];
+ card->uhs2_config.n_data_gap =
+ cap & UHS2_DEV_CONFIG_N_DATA_GAP_MASK;
+ if (card->uhs2_config.n_fcu == 0)
+ card->uhs2_config.n_fcu = 256;
+
+ return 0;
+}
+
+/*
+ * Based on the card's and host's UHS-II capabilities, let's update the
+ * configuration of the card and the host. This may also include to move to a
+ * greater speed range/mode. Depending on the updated configuration, we may need
+ * to do a soft reset of the card via sending it a GO_DORMANT_STATE command.
+ *
+ * In the final step, let's check if the card signals "config completion", which
+ * indicates that the card has moved from config state into active state.
+ */
+static int sd_uhs2_config_write(struct mmc_host *host, struct mmc_card *card)
+{
+ struct mmc_command cmd = {0};
+ struct uhs2_command uhs2_cmd = {};
+ u32 payload0, payload1;
+ u8 nMinDataGap;
+ int err;
+
+ /*
+ * Use Control Write CCMD to set Generic Setting in Configuration Register.
+ * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b).
+ * - IOADR = Generic Setting Register(CFG_BASE + 008h)
+ * - Payload = New contents to be written to Generic Setting Register
+ */
+ uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | card->uhs2_config.node_id;
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_WRITE |
+ UHS2_NATIVE_CMD_PLEN_8B |
+ (UHS2_DEV_CONFIG_GEN_SET >> 8);
+
+ /*
+ * Most UHS-II cards only support FD and 2L-HD mode. Other lane numbers
+ * defined in UHS-II addendem Ver1.01 are optional.
+ */
+ host->uhs2_caps.n_lanes_set = UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD;
+ card->uhs2_config.n_lanes_set = UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD;
+
+ payload0 = card->uhs2_config.n_lanes_set << UHS2_DEV_CONFIG_N_LANES_POS;
+ payload1 = 0;
+ uhs2_cmd.payload[0] = cpu_to_be32(payload0);
+ uhs2_cmd.payload[1] = cpu_to_be32(payload1);
+
+ /*
+ * There is no payload because per spec, there should be
+ * no payload field for read CCMD.
+ * Plen is set in arg. Per spec, plen for read CCMD
+ * represents the len of read data which is assigned in payload
+ * of following RES (p136).
+ */
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN, 0);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /*
+ * Use Control Write CCMD to set PHY Setting in Configuration Register.
+ * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b).
+ * - IOADR = PHY Setting Register(CFG_BASE + 00Ah)
+ * - Payload = New contents to be written to PHY Setting Register
+ */
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_PHY_SET & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_WRITE |
+ UHS2_NATIVE_CMD_PLEN_8B |
+ (UHS2_DEV_CONFIG_PHY_SET >> 8);
+
+ if (host->uhs2_caps.speed_range == UHS2_DEV_CONFIG_PHY_SET_SPEED_B) {
+ if (card->uhs2_config.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD &&
+ host->uhs2_caps.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD) {
+ /* Support HD */
+ host->ios.timing = MMC_TIMING_UHS2_SPEED_B_HD;
+ nMinDataGap = 1;
+ } else {
+ /* Only support 2L-FD so far */
+ host->ios.timing = MMC_TIMING_UHS2_SPEED_B;
+ nMinDataGap = 3;
+ }
+ card->uhs2_config.speed_range_set = UHS2_DEV_CONFIG_PHY_SET_SPEED_B;
+ } else {
+ if (card->uhs2_config.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD &&
+ host->uhs2_caps.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD) {
+ /* Support HD */
+ host->ios.timing = MMC_TIMING_UHS2_SPEED_A_HD;
+ nMinDataGap = 1;
+ } else {
+ /* Only support 2L-FD so far */
+ host->ios.timing = MMC_TIMING_UHS2_SPEED_A;
+ nMinDataGap = 3;
+ }
+ card->uhs2_config.speed_range_set = UHS2_DEV_CONFIG_PHY_SET_SPEED_A;
+ }
+
+ payload0 = card->uhs2_config.speed_range_set << UHS2_DEV_CONFIG_PHY_SET_SPEED_POS;
+
+ card->uhs2_config.n_lss_sync_set = (max(card->uhs2_config.n_lss_sync,
+ host->uhs2_caps.n_lss_sync) >> 2) &
+ UHS2_DEV_CONFIG_N_LSS_SYN_MASK;
+ host->uhs2_caps.n_lss_sync_set = card->uhs2_config.n_lss_sync_set;
+
+ card->uhs2_config.n_lss_dir_set = (max(card->uhs2_config.n_lss_dir,
+ host->uhs2_caps.n_lss_dir) >> 3) &
+ UHS2_DEV_CONFIG_N_LSS_DIR_MASK;
+ host->uhs2_caps.n_lss_dir_set = card->uhs2_config.n_lss_dir_set;
+
+ payload1 = (card->uhs2_config.n_lss_dir_set << UHS2_DEV_CONFIG_N_LSS_DIR_POS) |
+ card->uhs2_config.n_lss_sync_set;
+ uhs2_cmd.payload[0] = cpu_to_be32(payload0);
+ uhs2_cmd.payload[1] = cpu_to_be32(payload1);
+
+ memset(uhs2_cmd.uhs2_resp, 0, sizeof(uhs2_cmd.uhs2_resp));
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN,
+ UHS2_CFG_WRITE_PHY_SET_RESP_LEN);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ if ((uhs2_cmd.uhs2_resp[2] & 0x80)) {
+ pr_err("%s: %s: UHS2 CMD not accepted, resp= 0x%x!\n",
+ mmc_hostname(host), __func__, uhs2_cmd.uhs2_resp[2]);
+ return -EIO;
+ }
+
+ /*
+ * Use Control Write CCMD to set LINK/TRAN Setting in Configuration Register.
+ * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b).
+ * - IOADR = LINK/TRAN Setting Register(CFG_BASE + 00Ch)
+ * - Payload = New contents to be written to LINK/TRAN Setting Register
+ */
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_LINK_TRAN_SET & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_WRITE |
+ UHS2_NATIVE_CMD_PLEN_8B |
+ (UHS2_DEV_CONFIG_LINK_TRAN_SET >> 8);
+
+ if (card->uhs2_config.app_type == UHS2_DEV_CONFIG_APP_SD_MEM)
+ card->uhs2_config.maxblk_len_set = UHS2_DEV_CONFIG_LT_SET_MAX_BLK_LEN;
+ else
+ card->uhs2_config.maxblk_len_set = min(card->uhs2_config.maxblk_len,
+ host->uhs2_caps.maxblk_len);
+ host->uhs2_caps.maxblk_len_set = card->uhs2_config.maxblk_len_set;
+
+ card->uhs2_config.n_fcu_set = min(card->uhs2_config.n_fcu, host->uhs2_caps.n_fcu);
+ host->uhs2_caps.n_fcu_set = card->uhs2_config.n_fcu_set;
+
+ card->uhs2_config.n_data_gap_set = max(nMinDataGap, card->uhs2_config.n_data_gap);
+ host->uhs2_caps.n_data_gap_set = card->uhs2_config.n_data_gap_set;
+
+ host->uhs2_caps.max_retry_set = 3;
+ card->uhs2_config.max_retry_set = host->uhs2_caps.max_retry_set;
+
+ payload0 = (card->uhs2_config.maxblk_len_set << UHS2_DEV_CONFIG_MAX_BLK_LEN_POS) |
+ (card->uhs2_config.max_retry_set << UHS2_DEV_CONFIG_LT_SET_MAX_RETRY_POS) |
+ (card->uhs2_config.n_fcu_set << UHS2_DEV_CONFIG_N_FCU_POS);
+ payload1 = card->uhs2_config.n_data_gap_set;
+ uhs2_cmd.payload[0] = cpu_to_be32(payload0);
+ uhs2_cmd.payload[1] = cpu_to_be32(payload1);
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN, 0);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /*
+ * Use Control Write CCMD to set Config Completion(payload bit 63) in Generic Setting
+ * Register.
+ * Header:
+ * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b).
+ * - IOADR = PGeneric Setting Register(CFG_BASE + 008h)
+ * Payload:
+ * - bit [63]: Config Completion
+ *
+ * DLSM transits to Active state immediately when Config Completion is set to 1.
+ */
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_WRITE |
+ UHS2_NATIVE_CMD_PLEN_8B |
+ (UHS2_DEV_CONFIG_GEN_SET >> 8);
+
+ payload0 = 0;
+ payload1 = UHS2_DEV_CONFIG_GEN_SET_CFG_COMPLETE;
+ uhs2_cmd.payload[0] = cpu_to_be32(payload0);
+ uhs2_cmd.payload[1] = cpu_to_be32(payload1);
+
+ memset(uhs2_cmd.uhs2_resp, 0, sizeof(uhs2_cmd.uhs2_resp));
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN,
+ UHS2_CFG_WRITE_GENERIC_SET_RESP_LEN);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /* Set host Config Setting registers */
+ err = host->ops->uhs2_control(host, UHS2_SET_CONFIG);
+ if (err) {
+ pr_err("%s: %s: UHS2 SET_CONFIG fail!\n", mmc_hostname(host), __func__);
+ return err;
+ }
+
+ return 0;
+}
+
+static int sd_uhs2_go_dormant(struct mmc_host *host, u32 node_id)
+{
+ struct mmc_command cmd = {0};
+ struct uhs2_command uhs2_cmd = {};
+ int err;
+
+ /* Disable Normal INT */
+ err = host->ops->uhs2_control(host, UHS2_DISABLE_INT);
+ if (err) {
+ pr_err("%s: %s: UHS2 DISABLE_INT fail!\n",
+ mmc_hostname(host), __func__);
+ return err;
+ }
+
+ /*
+ * Refer to UHS-II Addendum Version 1.02 Figure 6-17 to see GO_DORMANT_STATE CCMD format.
+ * Header:
+ * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b).
+ * - IOADR = CMD_BASE + 001h
+ * Payload:
+ * - bit [7]: HBR(Entry to Hibernate Mode)
+ * 1: Host intends to enter Hibernate mode during Dormant state.
+ * The default setting is 0 because hibernate is currently not supported.
+ */
+ uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | node_id;
+ uhs2_cmd.arg = ((UHS2_DEV_CMD_GO_DORMANT_STATE & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_WRITE |
+ UHS2_NATIVE_CMD_PLEN_4B |
+ (UHS2_DEV_CMD_GO_DORMANT_STATE >> 8);
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_GO_DORMANT_PAYLOAD_LEN, 0);
+
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ if (err) {
+ pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /* Check Dormant State in Present */
+ err = host->ops->uhs2_control(host, UHS2_CHECK_DORMANT);
+ if (err)
+ return err;
+
+ /* Disable UHS2 card clock */
+ err = host->ops->uhs2_control(host, UHS2_DISABLE_CLK);
+ if (err)
+ return err;
+
+ /* Restore sd clock */
+ mmc_delay(5);
+ err = host->ops->uhs2_control(host, UHS2_ENABLE_CLK);
+ if (err)
+ return err;
+
+ /* Enable Normal INT */
+ err = host->ops->uhs2_control(host, UHS2_ENABLE_INT);
+ if (err)
+ return err;
+
+ /* Detect UHS2 */
+ err = host->ops->uhs2_control(host, UHS2_PHY_INIT);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int sd_uhs2_wait_active_state_cb(void *cb_data, bool *busy)
+{
+ struct sd_uhs2_wait_active_state_data *data = cb_data;
+ struct mmc_host *host = data->host;
+ struct mmc_command *cmd = data->cmd;
+ int err;
+
+ err = mmc_wait_for_cmd(host, cmd, 0);
+ if (err)
+ return err;
+
+ if (cmd->resp[1] & UHS2_DEV_CONFIG_GEN_SET_CFG_COMPLETE)
+ *busy = false;
+ else
+ *busy = true;
+
+ return 0;
+}
+
+static int sd_uhs2_go_dormant_state(struct mmc_host *host, u32 node_id)
+{
+ struct mmc_command cmd = {0};
+ struct uhs2_command uhs2_cmd = {};
+ int err;
+ struct sd_uhs2_wait_active_state_data cb_data = {
+ .host = host,
+ .cmd = &cmd
+ };
+
+ err = sd_uhs2_go_dormant(host, node_id);
+ if (err) {
+ pr_err("%s: %s: UHS2 GO_DORMANT_STATE fail, err= 0x%x!\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ /*
+ * Use Control Read CCMD to check Config Completion(bit 63) in Generic Setting Register.
+ * - Control Read(R/W=0) with 8-Byte payload(PLEN=10b).
+ * - IOADR = Generic Setting Register(CFG_BASE + 008h)
+ *
+ * When UHS-II card been switched to new speed mode, it will set Config Completion to 1.
+ */
+ uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | node_id;
+ uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) |
+ UHS2_NATIVE_CMD_READ |
+ UHS2_NATIVE_CMD_PLEN_8B |
+ (UHS2_DEV_CONFIG_GEN_SET >> 8);
+
+ sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0);
+ err = __mmc_poll_for_busy(host, UHS2_WAIT_CFG_COMPLETE_PERIOD_US,
+ UHS2_WAIT_CFG_COMPLETE_TIMEOUT_MS,
+ &sd_uhs2_wait_active_state_cb, &cb_data);
+ if (err) {
+ pr_err("%s: %s: Not switch to Active in 100 ms\n", mmc_hostname(host), __func__);
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * Allocate the data structure for the mmc_card and run the UHS-II specific
+ * initialization sequence.
+ */
+static int sd_uhs2_init_card(struct mmc_host *host, struct mmc_card *oldcard)
+{
+ struct mmc_card *card;
+ u32 node_id = 0;
+ int err;
+
+ err = sd_uhs2_dev_init(host);
+ if (err)
+ return err;
+
+ err = sd_uhs2_enum(host, &node_id);
+ if (err)
+ return err;
+
+ if (oldcard) {
+ card = oldcard;
+ } else {
+ card = mmc_alloc_card(host, &sd_type);
+ if (IS_ERR(card))
+ return PTR_ERR(card);
+ }
+
+ card->uhs2_config.node_id = node_id;
+ card->type = MMC_TYPE_SD;
+
+ err = sd_uhs2_config_read(host, card);
+ if (err)
+ goto err;
+
+ err = sd_uhs2_config_write(host, card);
+ if (err)
+ goto err;
+
+ /* If change speed to Range B, need to GO_DORMANT_STATE */
+ if (host->ios.timing == MMC_TIMING_UHS2_SPEED_B ||
+ host->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD) {
+ err = sd_uhs2_go_dormant_state(host, node_id);
+ if (err)
+ goto err;
+ }
+
+ host->uhs2_sd_tran = true;
+ host->card = card;
+ return 0;
+
+err:
+ if (!oldcard)
+ mmc_remove_card(card);
+ return err;
+}
+
+/*
+ * Initialize the UHS-II card through the SD-TRAN transport layer. This enables
+ * commands/requests to be backwards compatible through the legacy SD protocol.
+ * UHS-II cards has a specific power limit specified for VDD1/VDD2, that should
+ * be set through a legacy CMD6. Note that, the power limit that becomes set,
+ * survives a soft reset through the GO_DORMANT_STATE command.
+ */
+static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card,
+ bool reinit)
+{
+ int err;
+ u32 cid[4];
+ u32 ocr;
+ u32 rocr;
+ u8 *status;
+ int ro;
+
+ /* Send CMD0 to reset SD card */
+ err = __mmc_go_idle(host);
+ if (err)
+ return err;
+
+ mmc_delay(1);
+
+ /* Send CMD8 to communicate SD interface operation condition */
+ err = mmc_send_if_cond(host, host->ocr_avail);
+ if (err)
+ return err;
+
+ /*
+ * Probe SD card working voltage.
+ */
+ err = mmc_send_app_op_cond(host, 0, &ocr);
+ if (err)
+ return err;
+
+ card->ocr = ocr;
+
+ /*
+ * Some SD cards claims an out of spec VDD voltage range. Let's treat
+ * these bits as being in-valid and especially also bit7.
+ */
+ ocr &= ~0x7FFF;
+ rocr = mmc_select_voltage(host, ocr);
+ /*
+ * Some cards have zero value of rocr in UHS-II mode. Assign host's
+ * ocr value to rocr.
+ */
+ if (!rocr)
+ rocr = host->ocr_avail;
+
+ rocr |= (SD_OCR_CCS | SD_OCR_XPC);
+
+ /* Wait SD power on ready */
+ ocr = rocr;
+
+ err = mmc_send_app_op_cond(host, ocr, &rocr);
+ if (err)
+ return err;
+
+ err = mmc_send_cid(host, cid);
+ if (err)
+ return err;
+
+ if (reinit) {
+ if (memcmp(cid, card->raw_cid, sizeof(cid)) != 0) {
+ pr_debug("%s: Perhaps the card was replaced\n",
+ mmc_hostname(host));
+ return -ENOENT;
+ }
+ } else {
+ memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+ mmc_decode_cid(card);
+ }
+
+ /*
+ * For native busses: get card RCA and quit open drain mode.
+ */
+ err = mmc_send_relative_addr(host, &card->rca);
+ if (err)
+ return err;
+
+ err = mmc_sd_get_csd(card, false);
+ if (err)
+ return err;
+
+ /*
+ * Select card, as all following commands rely on that.
+ */
+ err = mmc_select_card(card);
+ if (err)
+ return err;
+
+ /*
+ * Fetch SCR from card.
+ */
+ err = mmc_app_send_scr(card);
+ if (err)
+ return err;
+
+ err = mmc_decode_scr(card);
+ if (err)
+ return err;
+
+ /*
+ * Switch to high power consumption mode.
+ * Even switch failed, sd card can still work at lower power consumption mode, but
+ * performance will be lower than high power consumption mode.
+ */
+ status = kmalloc(64, GFP_KERNEL);
+ if (!status)
+ return -ENOMEM;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH)) {
+ pr_warn("%s: card lacks mandatory switch function, performance might suffer\n",
+ mmc_hostname(card->host));
+ } else {
+ /*
+ * Send CMD6 to set Maximum Power Consumption to get better
+ * performance. Ignore errors and continue.
+ */
+ err = mmc_sd_switch(card, 0, 3, SD4_SET_POWER_LIMIT_1_80W, status);
+ if (!err)
+ mmc_sd_switch(card, 1, 3, SD4_SET_POWER_LIMIT_1_80W, status);
+ }
+
+ /*
+ * Check if read-only switch is active.
+ */
+ ro = mmc_sd_get_ro(host);
+ if (ro < 0)
+ pr_warn("%s: host does not support read-only switch, assuming write-enable\n",
+ mmc_hostname(host));
+ else if (ro > 0)
+ mmc_card_set_readonly(card);
+
+ kfree(status);
+ return 0;
+}
+
+static int sd_uhs2_reinit(struct mmc_host *host)
+{
+ struct mmc_card *card = host->card;
+ int err;
+
+ err = sd_uhs2_power_up(host);
+ if (err)
+ return err;
+
+ err = sd_uhs2_phy_init(host);
+ if (err)
+ return err;
+
+ err = sd_uhs2_init_card(host, card);
+ if (err)
+ return err;
+
+ return sd_uhs2_legacy_init(host, card, true);
+}
+
+static void sd_uhs2_remove(struct mmc_host *host)
+{
+ mmc_remove_card(host->card);
+ host->card = NULL;
+}
+
+static int sd_uhs2_alive(struct mmc_host *host)
+{
+ return mmc_send_status(host->card, NULL);
+}
+
+static void sd_uhs2_detect(struct mmc_host *host)
+{
+ int err;
+
+ mmc_get_card(host->card, NULL);
+ err = _mmc_detect_card_removed(host);
+ mmc_put_card(host->card, NULL);
+
+ if (err) {
+ sd_uhs2_remove(host);
+
+ mmc_claim_host(host);
+ mmc_detach_bus(host);
+ sd_uhs2_power_off(host);
+ mmc_release_host(host);
+ }
+}
+
+static int _sd_uhs2_suspend(struct mmc_host *host)
+{
+ struct mmc_card *card = host->card;
+
+ mmc_claim_host(host);
+
+ if (mmc_card_suspended(card))
+ goto out;
+
+ sd_uhs2_power_off(host);
+ mmc_card_set_suspended(card);
+
+out:
+ mmc_release_host(host);
+ return 0;
+}
+
+/*
+ * Callback for suspend
+ */
+static int sd_uhs2_suspend(struct mmc_host *host)
+{
+ int err;
+
+ err = _sd_uhs2_suspend(host);
+ if (!err) {
+ pm_runtime_disable(&host->card->dev);
+ pm_runtime_set_suspended(&host->card->dev);
+ }
+
+ return err;
+}
+
+/*
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static int _mmc_sd_uhs2_resume(struct mmc_host *host)
+{
+ int err = 0;
+
+ mmc_claim_host(host);
+
+ if (!mmc_card_suspended(host->card))
+ goto out;
+
+ /* Power up UHS2 SD card and re-initialize it. */
+ err = sd_uhs2_reinit(host);
+ mmc_card_clr_suspended(host->card);
+
+out:
+ mmc_release_host(host);
+ return err;
+}
+
+/*
+ * Callback for resume
+ */
+static int sd_uhs2_resume(struct mmc_host *host)
+{
+ pm_runtime_enable(&host->card->dev);
+ return 0;
+}
+
+/*
+ * Callback for runtime_suspend.
+ */
+static int sd_uhs2_runtime_suspend(struct mmc_host *host)
+{
+ int err;
+
+ if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
+ return 0;
+
+ err = _sd_uhs2_suspend(host);
+ if (err)
+ pr_err("%s: error %d doing aggressive suspend\n", mmc_hostname(host), err);
+
+ return err;
+}
+
+static int sd_uhs2_runtime_resume(struct mmc_host *host)
+{
+ int err;
+
+ err = _mmc_sd_uhs2_resume(host);
+ if (err && err != -ENOMEDIUM)
+ pr_err("%s: error %d doing runtime resume\n", mmc_hostname(host), err);
+
+ return err;
+}
+
+static int sd_uhs2_hw_reset(struct mmc_host *host)
+{
+ sd_uhs2_power_off(host);
+ /* Wait at least 1 ms according to SD spec */
+ mmc_delay(1);
+
+ return sd_uhs2_reinit(host);
+}
+
+static const struct mmc_bus_ops sd_uhs2_ops = {
+ .remove = sd_uhs2_remove,
+ .alive = sd_uhs2_alive,
+ .detect = sd_uhs2_detect,
+ .suspend = sd_uhs2_suspend,
+ .resume = sd_uhs2_resume,
+ .runtime_suspend = sd_uhs2_runtime_suspend,
+ .runtime_resume = sd_uhs2_runtime_resume,
+ .shutdown = sd_uhs2_suspend,
+ .hw_reset = sd_uhs2_hw_reset,
+};
+
+static int sd_uhs2_attach(struct mmc_host *host)
+{
+ int err;
+
+ err = sd_uhs2_power_up(host);
+ if (err)
+ goto err;
+
+ err = sd_uhs2_phy_init(host);
+ if (err)
+ goto err;
+
+ err = sd_uhs2_init_card(host, NULL);
+ if (err)
+ goto err;
+
+ err = sd_uhs2_legacy_init(host, host->card, false);
+ if (err)
+ goto remove_card;
+
+ mmc_attach_bus(host, &sd_uhs2_ops);
+
+ mmc_release_host(host);
+
+ err = mmc_add_card(host->card);
+ if (err)
+ goto remove_card;
+
+ mmc_claim_host(host);
+ return 0;
+
+remove_card:
+ sd_uhs2_remove(host);
+ mmc_claim_host(host);
+err:
+ mmc_detach_bus(host);
+ sd_uhs2_power_off(host);
+ return err;
+}
+
+/**
+ * mmc_attach_sd_uhs2 - select UHS2 interface
+ * @host: MMC host
+ *
+ * Try to select UHS2 interface and initialize the bus for a given
+ * frequency, @freq.
+ *
+ * Return: 0 on success, non-zero error on failure
+ */
+int mmc_attach_sd_uhs2(struct mmc_host *host)
+{
+ int i, err;
+
+ if (!(host->caps2 & MMC_CAP2_SD_UHS2))
+ return -EOPNOTSUPP;
+
+ /* Turn off the legacy SD interface before trying with UHS-II. */
+ mmc_power_off(host);
+
+ /*
+ * Start UHS-II initialization at 52MHz and possibly make a retry at
+ * 26MHz according to the spec. It's required that the host driver
+ * validates ios->clock, to set a rate within the correct range.
+ */
+ for (i = 0; i < ARRAY_SIZE(sd_uhs2_freqs); i++) {
+ host->f_init = sd_uhs2_freqs[i];
+ pr_debug("%s: %s: trying to init UHS-II card at %u Hz\n",
+ mmc_hostname(host), __func__, host->f_init);
+ err = sd_uhs2_attach(host);
+ if (!err)
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * mmc_uhs2_prepare_cmd - prepare for SD command packet
+ * @host: MMC host
+ * @mrq: MMC request
+ *
+ * Initialize and fill in a header and a payload of SD command packet.
+ * The caller should allocate uhs2_command in host->cmd->uhs2_cmd in
+ * advance.
+ *
+ * Return: 0 on success, non-zero error on failure
+ */
+void mmc_uhs2_prepare_cmd(struct mmc_host *host, struct mmc_request *mrq)
+{
+ struct mmc_command *cmd;
+ struct uhs2_command *uhs2_cmd;
+ u8 plen;
+
+ cmd = mrq->cmd;
+ cmd->uhs2_cmd = &mrq->uhs2_cmd;
+ uhs2_cmd = cmd->uhs2_cmd;
+ uhs2_cmd->header = host->card->uhs2_config.node_id;
+ if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC)
+ uhs2_cmd->header |= UHS2_PACKET_TYPE_DCMD;
+ else
+ uhs2_cmd->header |= UHS2_PACKET_TYPE_CCMD;
+
+ uhs2_cmd->arg = cmd->opcode << UHS2_SD_CMD_INDEX_POS;
+ if (host->uhs2_app_cmd) {
+ uhs2_cmd->arg |= UHS2_SD_CMD_APP;
+ host->uhs2_app_cmd = false;
+ }
+
+ /*
+ * UHS-II Addendum 7.2.1.2
+ * Host may set DM to 1 for DCMD which supports multi-block read/write regardless of
+ * data transfer length (e.g., CMD18, CMD25). Otherwise, it shall not set DM to 1.
+ * (e.g., CMD6, CMD17, CMD24). These rules are also applied to other multi-block read/write
+ * commands defined in other Part of SD specifications (for example, Host may set DM to 1
+ * for ACMD18 or ACMD25).
+ */
+ if (mmc_op_multi(cmd->opcode))
+ cmd->uhs2_cmd->tmode_half_duplex = mmc_card_uhs2_hd_mode(host);
+ else
+ cmd->uhs2_cmd->tmode_half_duplex = 0;
+
+ uhs2_cmd = cmd->uhs2_cmd;
+ plen = 2; /* at the maximum */
+
+ if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC &&
+ cmd->uhs2_cmd->tmode_half_duplex) {
+ if (mmc_card_uhs2_hd_mode(host))
+ uhs2_cmd->arg |= UHS2_DCMD_2L_HD_MODE;
+
+ uhs2_cmd->arg |= UHS2_DCMD_LM_TLEN_EXIST;
+
+ if (cmd->data->blocks == 1 &&
+ cmd->data->blksz != 512 &&
+ cmd->opcode != MMC_READ_SINGLE_BLOCK &&
+ cmd->opcode != MMC_WRITE_BLOCK) {
+ uhs2_cmd->arg |= UHS2_DCMD_TLUM_BYTE_MODE;
+ uhs2_cmd->payload[1] = cpu_to_be32(cmd->data->blksz);
+ } else {
+ uhs2_cmd->payload[1] = cpu_to_be32(cmd->data->blocks);
+ }
+ } else {
+ plen = 1;
+ }
+
+ uhs2_cmd->payload[0] = cpu_to_be32(cmd->arg);
+ sd_uhs2_cmd_assemble(cmd, uhs2_cmd, plen, 0);
+}
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 4fb247fde5c0..9566837c9848 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -769,7 +769,7 @@ try_again:
* Read CSD, before selecting the card
*/
if (!oldcard && mmc_card_sd_combo(card)) {
- err = mmc_sd_get_csd(card);
+ err = mmc_sd_get_csd(card, false);
if (err)
goto remove;
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7199cb0bd0b9..6824131b69b1 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -98,10 +98,20 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
This is the case for the Nintendo Wii SDHCI.
+config MMC_SDHCI_UHS2
+ tristate "UHS2 support on SDHCI controller" if COMPILE_TEST
+ depends on MMC_SDHCI
+ help
+ This option is selected by SDHCI controller drivers that want to
+ support UHS2-capable devices.
+
+ If you have a controller with this feature, say Y or M here.
+
config MMC_SDHCI_PCI
tristate "SDHCI support on PCI bus"
depends on MMC_SDHCI && PCI
select MMC_CQHCI
+ select MMC_SDHCI_UHS2
select IOSF_MBI if X86
select MMC_SDHCI_IO_ACCESSORS
help
@@ -1009,6 +1019,7 @@ config MMC_MTK
depends on COMMON_CLK
select REGULATOR
select MMC_CQHCI
+ select MMC_HSQ
help
This selects the MediaTek(R) Secure digital and Multimedia card Interface.
If you have a machine with a integrated SD/MMC card reader, say Y or M here.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3ccffebbe59b..5147467ec825 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_MMC_PXA) += pxamci.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
+obj-$(CONFIG_MMC_SDHCI_UHS2) += sdhci-uhs2.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
sdhci-pci-y += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o \
sdhci-pci-dwc-mshc.o sdhci-pci-gli.o
diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c
index 42aa43740ba8..b6b6dd677ae5 100644
--- a/drivers/mmc/host/alcor.c
+++ b/drivers/mmc/host/alcor.c
@@ -1175,7 +1175,7 @@ MODULE_DEVICE_TABLE(platform, alcor_pci_sdmmc_ids);
static struct platform_driver alcor_pci_sdmmc_driver = {
.probe = alcor_pci_sdmmc_drv_probe,
- .remove_new = alcor_pci_sdmmc_drv_remove,
+ .remove = alcor_pci_sdmmc_drv_remove,
.id_table = alcor_pci_sdmmc_ids,
.driver = {
.name = DRV_NAME_ALCOR_PCI_SDMMC,
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index cdbd2edf4b2e..fc360902729d 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -860,7 +860,7 @@ static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
}
/*
- * Configure given PDC buffer taking care of alignement issues.
+ * Configure given PDC buffer taking care of alignment issues.
* Update host->data_size and host->sg.
*/
static void atmci_pdc_set_single_buf(struct atmel_mci *host,
@@ -2653,7 +2653,7 @@ static const struct dev_pm_ops atmci_dev_pm_ops = {
static struct platform_driver atmci_driver = {
.probe = atmci_probe,
- .remove_new = atmci_remove,
+ .remove = atmci_remove,
.driver = {
.name = "atmel_mci",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 6e80bcb668ec..057d42307832 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -543,7 +543,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
}
} else {
- /* Techincally, we should be getting all 48 bits of
+ /* Technically, we should be getting all 48 bits of
* the response (SD_RESP1 + SD_RESP2), but because
* our response omits the CRC, our data ends up
* being shifted 8 bits to the right. In this case,
@@ -1185,7 +1185,7 @@ static int au1xmmc_resume(struct platform_device *pdev)
static struct platform_driver au1xmmc_driver = {
.probe = au1xmmc_probe,
- .remove_new = au1xmmc_remove,
+ .remove = au1xmmc_remove,
.suspend = au1xmmc_suspend,
.resume = au1xmmc_resume,
.driver = {
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 35d8fdea668b..7847f0c8b465 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -148,9 +148,10 @@ struct bcm2835_host {
void __iomem *ioaddr;
u32 phys_addr;
+ struct clk *clk;
struct platform_device *pdev;
- int clock; /* Current clock speed */
+ unsigned int clock; /* Current clock speed */
unsigned int max_clk; /* Max possible freq */
struct work_struct dma_work;
struct delayed_work timeout_work; /* Timer for timeouts */
@@ -1345,7 +1346,6 @@ static int bcm2835_add_host(struct bcm2835_host *host)
static int bcm2835_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct clk *clk;
struct bcm2835_host *host;
struct mmc_host *mmc;
const __be32 *regaddr_p;
@@ -1393,15 +1393,6 @@ static int bcm2835_probe(struct platform_device *pdev)
/* Ignore errors to fall back to PIO mode */
}
-
- clk = devm_clk_get(dev, NULL);
- if (IS_ERR(clk)) {
- ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n");
- goto err;
- }
-
- host->max_clk = clk_get_rate(clk);
-
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
ret = host->irq;
@@ -1412,16 +1403,30 @@ static int bcm2835_probe(struct platform_device *pdev)
if (ret)
goto err;
- ret = bcm2835_add_host(host);
+ host->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(host->clk)) {
+ ret = dev_err_probe(dev, PTR_ERR(host->clk), "could not get clk\n");
+ goto err;
+ }
+
+ ret = clk_prepare_enable(host->clk);
if (ret)
goto err;
+ host->max_clk = clk_get_rate(host->clk);
+
+ ret = bcm2835_add_host(host);
+ if (ret)
+ goto err_clk;
+
platform_set_drvdata(pdev, host);
dev_dbg(dev, "%s -> OK\n", __func__);
return 0;
+err_clk:
+ clk_disable_unprepare(host->clk);
err:
dev_dbg(dev, "%s -> err %d\n", __func__, ret);
if (host->dma_chan_rxtx)
@@ -1445,6 +1450,8 @@ static void bcm2835_remove(struct platform_device *pdev)
cancel_work_sync(&host->dma_work);
cancel_delayed_work_sync(&host->timeout_work);
+ clk_disable_unprepare(host->clk);
+
if (host->dma_chan_rxtx)
dma_release_channel(host->dma_chan_rxtx);
@@ -1459,7 +1466,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_match);
static struct platform_driver bcm2835_driver = {
.probe = bcm2835_probe,
- .remove_new = bcm2835_remove,
+ .remove = bcm2835_remove,
.driver = {
.name = "sdhost-bcm2835",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c
index 060ec4f4800f..0592f356b1e5 100644
--- a/drivers/mmc/host/cavium-octeon.c
+++ b/drivers/mmc/host/cavium-octeon.c
@@ -217,7 +217,7 @@ static int octeon_mmc_probe(struct platform_device *pdev)
return PTR_ERR(base);
host->dma_base = base;
/*
- * To keep the register addresses shared we intentionaly use
+ * To keep the register addresses shared we intentionally use
* a negative offset here, first register used on Octeon therefore
* starts at 0x20 (MIO_EMM_DMA_CFG).
*/
@@ -326,7 +326,7 @@ MODULE_DEVICE_TABLE(of, octeon_mmc_match);
static struct platform_driver octeon_mmc_driver = {
.probe = octeon_mmc_probe,
- .remove_new = octeon_mmc_remove,
+ .remove = octeon_mmc_remove,
.driver = {
.name = KBUILD_MODNAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index 902f7f20abaa..d741c1f9cf87 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -771,7 +771,7 @@ static void cb710_mmc_exit(struct platform_device *pdev)
static struct platform_driver cb710_mmc_driver = {
.driver.name = "cb710-mmc",
.probe = cb710_mmc_init,
- .remove_new = cb710_mmc_exit,
+ .remove = cb710_mmc_exit,
#ifdef CONFIG_PM
.suspend = cb710_mmc_suspend,
.resume = cb710_mmc_resume,
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 9cbde800685d..cde4c4339ab7 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -7,24 +7,23 @@
* Copyright (C) 2009 David Brownell
*/
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
#include <linux/clk.h>
-#include <linux/err.h>
#include <linux/cpufreq.h>
-#include <linux/mmc/host.h>
-#include <linux/io.h>
-#include <linux/irq.h>
#include <linux/delay.h>
-#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
-#include <linux/of.h>
#include <linux/mmc/slot-gpio.h>
-#include <linux/interrupt.h>
-
+#include <linux/module.h>
#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
/*
* Register Definitions
@@ -1229,7 +1228,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
host->mmc_input_clk = clk_get_rate(host->clk);
- pdev->id_entry = of_device_get_match_data(&pdev->dev);
+ pdev->id_entry = device_get_match_data(&pdev->dev);
if (pdev->id_entry) {
ret = mmc_of_parse(mmc);
if (ret) {
@@ -1400,7 +1399,7 @@ static struct platform_driver davinci_mmcsd_driver = {
.of_match_table = davinci_mmc_dt_ids,
},
.probe = davinci_mmcsd_probe,
- .remove_new = davinci_mmcsd_remove,
+ .remove = davinci_mmcsd_remove,
.id_table = davinci_mmc_devtype,
};
diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c
index 24e0b604b405..3cf526ab0387 100644
--- a/drivers/mmc/host/dw_mmc-bluefield.c
+++ b/drivers/mmc/host/dw_mmc-bluefield.c
@@ -68,7 +68,7 @@ static int dw_mci_bluefield_probe(struct platform_device *pdev)
static struct platform_driver dw_mci_bluefield_pltfm_driver = {
.probe = dw_mci_bluefield_probe,
- .remove_new = dw_mci_pltfm_remove,
+ .remove = dw_mci_pltfm_remove,
.driver = {
.name = "dwmmc_bluefield",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 6dc057718d2c..53d32d0f2709 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -682,7 +682,7 @@ static const struct dev_pm_ops dw_mci_exynos_pmops = {
static struct platform_driver dw_mci_exynos_pltfm_driver = {
.probe = dw_mci_exynos_probe,
- .remove_new = dw_mci_exynos_remove,
+ .remove = dw_mci_exynos_remove,
.driver = {
.name = "dwmmc_exynos",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-hi3798cv200.c b/drivers/mmc/host/dw_mmc-hi3798cv200.c
index 6099756e59b3..0ccfae1b2dbe 100644
--- a/drivers/mmc/host/dw_mmc-hi3798cv200.c
+++ b/drivers/mmc/host/dw_mmc-hi3798cv200.c
@@ -189,7 +189,7 @@ static const struct of_device_id dw_mci_hi3798cv200_match[] = {
MODULE_DEVICE_TABLE(of, dw_mci_hi3798cv200_match);
static struct platform_driver dw_mci_hi3798cv200_driver = {
.probe = dw_mci_hi3798cv200_probe,
- .remove_new = dw_mci_hi3798cv200_remove,
+ .remove = dw_mci_hi3798cv200_remove,
.driver = {
.name = "dwmmc_hi3798cv200",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-hi3798mv200.c b/drivers/mmc/host/dw_mmc-hi3798mv200.c
index 96af693e3e37..cce174b5249b 100644
--- a/drivers/mmc/host/dw_mmc-hi3798mv200.c
+++ b/drivers/mmc/host/dw_mmc-hi3798mv200.c
@@ -237,7 +237,7 @@ static void dw_mci_hi3798mv200_remove(struct platform_device *pdev)
MODULE_DEVICE_TABLE(of, dw_mci_hi3798mv200_match);
static struct platform_driver dw_mci_hi3798mv200_driver = {
.probe = dw_mci_hi3798mv200_probe,
- .remove_new = dw_mci_hi3798mv200_remove,
+ .remove = dw_mci_hi3798mv200_remove,
.driver = {
.name = "dwmmc_hi3798mv200",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
index e8ee7c43f60b..0311a37dd4ab 100644
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -470,7 +470,7 @@ static const struct dev_pm_ops dw_mci_k3_dev_pm_ops = {
static struct platform_driver dw_mci_k3_pltfm_driver = {
.probe = dw_mci_k3_probe,
- .remove_new = dw_mci_pltfm_remove,
+ .remove = dw_mci_pltfm_remove,
.driver = {
.name = "dwmmc_k3",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 2353fadceda1..de820ffd2133 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -131,7 +131,7 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
static struct platform_driver dw_mci_pltfm_driver = {
.probe = dw_mci_pltfm_probe,
- .remove_new = dw_mci_pltfm_remove,
+ .remove = dw_mci_pltfm_remove,
.driver = {
.name = "dw_mmc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index f96260fd143b..baa23b517731 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -577,7 +577,7 @@ static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
static struct platform_driver dw_mci_rockchip_pltfm_driver = {
.probe = dw_mci_rockchip_probe,
- .remove_new = dw_mci_rockchip_remove,
+ .remove = dw_mci_rockchip_remove,
.driver = {
.name = "dwmmc_rockchip",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc-starfive.c b/drivers/mmc/host/dw_mmc-starfive.c
index b4d81ef0f3af..34964b0dab21 100644
--- a/drivers/mmc/host/dw_mmc-starfive.c
+++ b/drivers/mmc/host/dw_mmc-starfive.c
@@ -115,7 +115,7 @@ static int dw_mci_starfive_probe(struct platform_device *pdev)
static struct platform_driver dw_mci_starfive_driver = {
.probe = dw_mci_starfive_probe,
- .remove_new = dw_mci_pltfm_remove,
+ .remove = dw_mci_pltfm_remove,
.driver = {
.name = "dwmmc_starfive",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 41e451235f63..3cbda98d08d2 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1182,7 +1182,7 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
/*
* Use the initial fifoth_val for PIO mode. If wm_algined
* is set, we set watermark same as data size.
- * If next issued data may be transfered by DMA mode,
+ * If next issued data may be transferred by DMA mode,
* prev_blksz should be invalidated.
*/
if (host->wm_aligned)
@@ -2957,8 +2957,8 @@ static int dw_mci_init_slot(struct dw_mci *host)
if (host->use_dma == TRANS_MODE_IDMAC) {
mmc->max_segs = host->ring_size;
mmc->max_blk_size = 65535;
- mmc->max_req_size = DW_MCI_DESC_DATA_LENGTH * host->ring_size;
- mmc->max_seg_size = mmc->max_req_size;
+ mmc->max_seg_size = 0x1000;
+ mmc->max_req_size = mmc->max_seg_size * host->ring_size;
mmc->max_blk_count = mmc->max_req_size / 512;
} else if (host->use_dma == TRANS_MODE_EDMAC) {
mmc->max_segs = 64;
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 6a45991ca056..596012d5afac 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -1191,7 +1191,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend,
static struct platform_driver jz4740_mmc_driver = {
.probe = jz4740_mmc_probe,
- .remove_new = jz4740_mmc_remove,
+ .remove = jz4740_mmc_remove,
.driver = {
.name = "jz4740-mmc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index 4ec8072dc60b..b338ccfa8f33 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -644,7 +644,7 @@ MODULE_DEVICE_TABLE(of, litex_match);
static struct platform_driver litex_mmc_driver = {
.probe = litex_mmc_probe,
- .remove_new = litex_mmc_remove,
+ .remove = litex_mmc_remove,
.driver = {
.name = "litex-mmc",
.of_match_table = litex_match,
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index c7c067b9415a..694bb443d5f3 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -879,7 +879,7 @@ static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
/*
* The memory at the end of the controller used as bounce buffer for
* the dram_access_quirk only accepts 32bit read/write access,
- * check the aligment and length of the data before starting the request.
+ * check the alignment and length of the data before starting the request.
*/
if (host->dram_access_quirk && mrq->data) {
mrq->cmd->error = meson_mmc_validate_dram_access(mmc, mrq->data);
@@ -1334,7 +1334,7 @@ MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
static struct platform_driver meson_mmc_driver = {
.probe = meson_mmc_probe,
- .remove_new = meson_mmc_remove,
+ .remove = meson_mmc_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c
index 31f750301dc1..b4e56ccffca2 100644
--- a/drivers/mmc/host/meson-mx-sdhc-mmc.c
+++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c
@@ -904,7 +904,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_sdhc_of_match);
static struct platform_driver meson_mx_sdhc_driver = {
.probe = meson_mx_sdhc_probe,
- .remove_new = meson_mx_sdhc_remove,
+ .remove = meson_mx_sdhc_remove,
.driver = {
.name = "meson-mx-sdhc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c
index a11577f2ee69..ad351805eed4 100644
--- a/drivers/mmc/host/meson-mx-sdio.c
+++ b/drivers/mmc/host/meson-mx-sdio.c
@@ -754,7 +754,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_mmc_of_match);
static struct platform_driver meson_mx_mmc_driver = {
.probe = meson_mx_mmc_probe,
- .remove_new = meson_mx_mmc_remove,
+ .remove = meson_mx_mmc_remove,
.driver = {
.name = "meson-mx-sdio",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 8fee7052f2ef..47443fb5eb33 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -222,10 +222,6 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
u8 leftover = 0;
unsigned short rotator;
int i;
- char tag[32];
-
- snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s",
- cmd->opcode, maptype(cmd));
/* Except for data block reads, the whole response will already
* be stored in the scratch buffer. It's somewhere after the
@@ -378,8 +374,9 @@ checkstatus:
}
if (value < 0)
- dev_dbg(&host->spi->dev, "%s: resp %04x %08x\n",
- tag, cmd->resp[0], cmd->resp[1]);
+ dev_dbg(&host->spi->dev,
+ " ... CMD%d response SPI_%s: resp %04x %08x\n",
+ cmd->opcode, maptype(cmd), cmd->resp[0], cmd->resp[1]);
/* disable chipselect on errors and some success cases */
if (value >= 0 && cs_on)
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index a5eb4ced4d5d..4d3647f9ec06 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -77,7 +77,7 @@
#define MCI_CPSM_INTERRUPT BIT(8)
#define MCI_CPSM_PENDING BIT(9)
#define MCI_CPSM_ENABLE BIT(10)
-/* Command register flag extenstions in the ST Micro versions */
+/* Command register flag extensions in the ST Micro versions */
#define MCI_CPSM_ST_SDIO_SUSP BIT(11)
#define MCI_CPSM_ST_ENCMD_COMPL BIT(12)
#define MCI_CPSM_ST_NIEN BIT(13)
diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
index 8ede4ce93271..a12048e5de63 100644
--- a/drivers/mmc/host/moxart-mmc.c
+++ b/drivers/mmc/host/moxart-mmc.c
@@ -719,7 +719,7 @@ MODULE_DEVICE_TABLE(of, moxart_mmc_match);
static struct platform_driver moxart_mmc_driver = {
.probe = moxart_probe,
- .remove_new = moxart_remove,
+ .remove = moxart_remove,
.driver = {
.name = "mmc-moxart",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 89018b6c97b9..efb0d2d5716b 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -33,6 +33,7 @@
#include <linux/mmc/slot-gpio.h>
#include "cqhci.h"
+#include "mmc_hsq.h"
#define MAX_BD_NUM 1024
#define MSDC_NR_CLOCKS 3
@@ -65,6 +66,7 @@
#define SDC_RESP3 0x4c
#define SDC_BLK_NUM 0x50
#define SDC_ADV_CFG0 0x64
+#define MSDC_NEW_RX_CFG 0x68
#define EMMC_IOCON 0x7c
#define SDC_ACMD_RESP 0x80
#define DMA_SA_H4BIT 0x8c
@@ -91,6 +93,7 @@
#define EMMC_TOP_CONTROL 0x00
#define EMMC_TOP_CMD 0x04
#define EMMC50_PAD_DS_TUNE 0x0c
+#define LOOP_TEST_CONTROL 0x30
/*--------------------------------------------------------------------------*/
/* Register Mask */
@@ -202,9 +205,13 @@
#define SDC_STS_CMDBUSY BIT(1) /* RW */
#define SDC_STS_SWR_COMPL BIT(31) /* RW */
-#define SDC_DAT1_IRQ_TRIGGER BIT(19) /* RW */
/* SDC_ADV_CFG0 mask */
+#define SDC_DAT1_IRQ_TRIGGER BIT(19) /* RW */
#define SDC_RX_ENHANCE_EN BIT(20) /* RW */
+#define SDC_NEW_TX_EN BIT(31) /* RW */
+
+/* MSDC_NEW_RX_CFG mask */
+#define MSDC_NEW_RX_PATH_SEL BIT(0) /* RW */
/* DMA_SA_H4BIT mask */
#define DMA_ADDR_HIGH_4BIT GENMASK(3, 0) /* RW */
@@ -226,6 +233,7 @@
/* MSDC_PATCH_BIT mask */
#define MSDC_PATCH_BIT_ODDSUPP BIT(1) /* RW */
+#define MSDC_PATCH_BIT_RD_DAT_SEL BIT(3) /* RW */
#define MSDC_INT_DAT_LATCH_CK_SEL GENMASK(9, 7)
#define MSDC_CKGEN_MSDC_DLY_SEL GENMASK(14, 10)
#define MSDC_PATCH_BIT_IODSSEL BIT(16) /* RW */
@@ -247,6 +255,8 @@
#define MSDC_PB2_SUPPORT_64G BIT(1) /* RW */
#define MSDC_PB2_RESPWAIT GENMASK(3, 2) /* RW */
#define MSDC_PB2_RESPSTSENSEL GENMASK(18, 16) /* RW */
+#define MSDC_PB2_POP_EN_CNT GENMASK(23, 20) /* RW */
+#define MSDC_PB2_CFGCRCSTSEDGE BIT(25) /* RW */
#define MSDC_PB2_CRCSTSENSEL GENMASK(31, 29) /* RW */
#define MSDC_PAD_TUNE_DATWRDLY GENMASK(4, 0) /* RW */
@@ -311,6 +321,12 @@
#define PAD_DS_DLY1 GENMASK(14, 10) /* RW */
#define PAD_DS_DLY3 GENMASK(4, 0) /* RW */
+/* LOOP_TEST_CONTROL mask */
+#define TEST_LOOP_DSCLK_MUX_SEL BIT(0) /* RW */
+#define TEST_LOOP_LATCH_MUX_SEL BIT(1) /* RW */
+#define LOOP_EN_SEL_CLK BIT(20) /* RW */
+#define TEST_HS400_CMD_LOOP_MUX_SEL BIT(31) /* RW */
+
#define REQ_CMD_EIO BIT(0)
#define REQ_CMD_TMO BIT(1)
#define REQ_DAT_ERR BIT(2)
@@ -391,6 +407,7 @@ struct msdc_save_para {
u32 emmc_top_control;
u32 emmc_top_cmd;
u32 emmc50_pad_ds_tune;
+ u32 loop_test_control;
};
struct mtk_mmc_compatible {
@@ -402,9 +419,13 @@ struct mtk_mmc_compatible {
bool data_tune;
bool busy_check;
bool stop_clk_fix;
+ u8 stop_dly_sel;
+ u8 pop_en_cnt;
bool enhance_rx;
bool support_64g;
bool use_internal_cd;
+ bool support_new_tx;
+ bool support_new_rx;
};
struct msdc_tune_para {
@@ -473,6 +494,7 @@ struct msdc_host {
bool hs400_tuning; /* hs400 mode online tuning */
bool internal_cd; /* Use internal card-detect logic */
bool cqhci; /* support eMMC hw cmdq */
+ bool hsq_en; /* Host Software Queue is enabled */
struct msdc_save_para save_para; /* used when gate HCLK */
struct msdc_tune_para def_tune_para; /* default tune setting */
struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
@@ -502,6 +524,7 @@ static const struct mtk_mmc_compatible mt2712_compat = {
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
+ .stop_dly_sel = 3,
.enhance_rx = true,
.support_64g = true,
};
@@ -515,6 +538,7 @@ static const struct mtk_mmc_compatible mt6779_compat = {
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
+ .stop_dly_sel = 3,
.enhance_rx = true,
.support_64g = true,
};
@@ -554,6 +578,7 @@ static const struct mtk_mmc_compatible mt7622_compat = {
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
+ .stop_dly_sel = 3,
.enhance_rx = true,
.support_64g = false,
};
@@ -567,6 +592,7 @@ static const struct mtk_mmc_compatible mt7986_compat = {
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
+ .stop_dly_sel = 3,
.enhance_rx = true,
.support_64g = true,
};
@@ -606,6 +632,7 @@ static const struct mtk_mmc_compatible mt8183_compat = {
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
+ .stop_dly_sel = 3,
.enhance_rx = true,
.support_64g = true,
};
@@ -619,6 +646,24 @@ static const struct mtk_mmc_compatible mt8516_compat = {
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
+ .stop_dly_sel = 3,
+};
+
+static const struct mtk_mmc_compatible mt8196_compat = {
+ .clk_div_bits = 12,
+ .recheck_sdio_irq = false,
+ .hs400_tune = false,
+ .pad_tune_reg = MSDC_PAD_TUNE0,
+ .async_fifo = true,
+ .data_tune = true,
+ .busy_check = true,
+ .stop_clk_fix = true,
+ .stop_dly_sel = 1,
+ .pop_en_cnt = 2,
+ .enhance_rx = true,
+ .support_64g = true,
+ .support_new_tx = true,
+ .support_new_rx = true,
};
static const struct of_device_id msdc_of_ids[] = {
@@ -629,9 +674,11 @@ static const struct of_device_id msdc_of_ids[] = {
{ .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat},
{ .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat},
{ .compatible = "mediatek,mt7986-mmc", .data = &mt7986_compat},
+ { .compatible = "mediatek,mt7988-mmc", .data = &mt7986_compat},
{ .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat},
{ .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat},
{ .compatible = "mediatek,mt8183-mmc", .data = &mt8183_compat},
+ { .compatible = "mediatek,mt8196-mmc", .data = &mt8196_compat},
{ .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat},
{}
@@ -872,6 +919,41 @@ static int msdc_ungate_clock(struct msdc_host *host)
(val & MSDC_CFG_CKSTB), 1, 20000);
}
+static void msdc_new_tx_setting(struct msdc_host *host)
+{
+ if (!host->top_base)
+ return;
+
+ sdr_set_bits(host->top_base + LOOP_TEST_CONTROL,
+ TEST_LOOP_DSCLK_MUX_SEL);
+ sdr_set_bits(host->top_base + LOOP_TEST_CONTROL,
+ TEST_LOOP_LATCH_MUX_SEL);
+ sdr_clr_bits(host->top_base + LOOP_TEST_CONTROL,
+ TEST_HS400_CMD_LOOP_MUX_SEL);
+
+ switch (host->timing) {
+ case MMC_TIMING_LEGACY:
+ case MMC_TIMING_MMC_HS:
+ case MMC_TIMING_SD_HS:
+ case MMC_TIMING_UHS_SDR12:
+ case MMC_TIMING_UHS_SDR25:
+ case MMC_TIMING_UHS_DDR50:
+ case MMC_TIMING_MMC_DDR52:
+ sdr_clr_bits(host->top_base + LOOP_TEST_CONTROL,
+ LOOP_EN_SEL_CLK);
+ break;
+ case MMC_TIMING_UHS_SDR50:
+ case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_MMC_HS200:
+ case MMC_TIMING_MMC_HS400:
+ sdr_set_bits(host->top_base + LOOP_TEST_CONTROL,
+ LOOP_EN_SEL_CLK);
+ break;
+ default:
+ break;
+ }
+}
+
static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
{
struct mmc_host *mmc = mmc_from_priv(host);
@@ -881,6 +963,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
u32 sclk;
u32 tune_reg = host->dev_comp->pad_tune_reg;
u32 val;
+ bool timing_changed;
if (!hz) {
dev_dbg(host->dev, "set mclk to 0\n");
@@ -890,6 +973,11 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
return;
}
+ if (host->timing != timing)
+ timing_changed = true;
+ else
+ timing_changed = false;
+
flags = readl(host->base + MSDC_INTEN);
sdr_clr_bits(host->base + MSDC_INTEN, flags);
if (host->dev_comp->clk_div_bits == 8)
@@ -996,6 +1084,9 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
sdr_set_field(host->base + tune_reg,
MSDC_PAD_TUNE_CMDRRDLY,
host->hs400_cmd_int_delay);
+ if (host->dev_comp->support_new_tx && timing_changed)
+ msdc_new_tx_setting(host);
+
dev_dbg(host->dev, "sclk: %d, timing: %d\n", mmc->actual_clock,
timing);
}
@@ -1163,7 +1254,9 @@ static void msdc_track_cmd_data(struct msdc_host *host, struct mmc_command *cmd)
static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
{
+ struct mmc_host *mmc = mmc_from_priv(host);
unsigned long flags;
+ bool hsq_req_done;
/*
* No need check the return value of cancel_delayed_work, as only ONE
@@ -1171,6 +1264,27 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
*/
cancel_delayed_work(&host->req_timeout);
+ /*
+ * If the request was handled from Host Software Queue, there's almost
+ * nothing to do here, and we also don't need to reset mrq as any race
+ * condition would not have any room to happen, since HSQ stores the
+ * "scheduled" mrqs in an internal array of mrq slots anyway.
+ * However, if the controller experienced an error, we still want to
+ * reset it as soon as possible.
+ *
+ * Note that non-HSQ requests will still be happening at times, even
+ * though it is enabled, and that's what is going to reset host->mrq.
+ * Also, msdc_unprepare_data() is going to be called by HSQ when needed
+ * as HSQ request finalization will eventually call the .post_req()
+ * callback of this driver which, in turn, unprepares the data.
+ */
+ hsq_req_done = host->hsq_en ? mmc_hsq_finalize_request(mmc, mrq) : false;
+ if (hsq_req_done) {
+ if (host->error)
+ msdc_reset_hw(host);
+ return;
+ }
+
spin_lock_irqsave(&host->lock, flags);
host->mrq = NULL;
spin_unlock_irqrestore(&host->lock, flags);
@@ -1180,7 +1294,7 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
msdc_unprepare_data(host, mrq->data);
if (host->error)
msdc_reset_hw(host);
- mmc_request_done(mmc_from_priv(host), mrq);
+ mmc_request_done(mmc, mrq);
if (host->dev_comp->recheck_sdio_irq)
msdc_recheck_sdio_irq(host);
}
@@ -1340,7 +1454,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
struct msdc_host *host = mmc_priv(mmc);
host->error = 0;
- WARN_ON(host->mrq);
+ WARN_ON(!host->hsq_en && host->mrq);
host->mrq = mrq;
if (mrq->data)
@@ -1704,6 +1818,17 @@ static void msdc_init_hw(struct msdc_host *host)
reset_control_deassert(host->reset);
}
+ /* New tx/rx enable bit need to be 0->1 for hardware check */
+ if (host->dev_comp->support_new_tx) {
+ sdr_clr_bits(host->base + SDC_ADV_CFG0, SDC_NEW_TX_EN);
+ sdr_set_bits(host->base + SDC_ADV_CFG0, SDC_NEW_TX_EN);
+ msdc_new_tx_setting(host);
+ }
+ if (host->dev_comp->support_new_rx) {
+ sdr_clr_bits(host->base + MSDC_NEW_RX_CFG, MSDC_NEW_RX_PATH_SEL);
+ sdr_set_bits(host->base + MSDC_NEW_RX_CFG, MSDC_NEW_RX_PATH_SEL);
+ }
+
/* Configure to MMC/SD mode, clock free running */
sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN);
@@ -1742,8 +1867,16 @@ static void msdc_init_hw(struct msdc_host *host)
sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
if (host->dev_comp->stop_clk_fix) {
- sdr_set_field(host->base + MSDC_PATCH_BIT1,
- MSDC_PATCH_BIT1_STOP_DLY, 3);
+ if (host->dev_comp->stop_dly_sel)
+ sdr_set_field(host->base + MSDC_PATCH_BIT1,
+ MSDC_PATCH_BIT1_STOP_DLY,
+ host->dev_comp->stop_dly_sel);
+
+ if (host->dev_comp->pop_en_cnt)
+ sdr_set_field(host->base + MSDC_PATCH_BIT2,
+ MSDC_PB2_POP_EN_CNT,
+ host->dev_comp->pop_en_cnt);
+
sdr_clr_bits(host->base + SDC_FIFO_CFG,
SDC_FIFO_CFG_WRVALIDSEL);
sdr_clr_bits(host->base + SDC_FIFO_CFG,
@@ -2055,6 +2188,19 @@ static inline void msdc_set_data_delay(struct msdc_host *host, u32 value)
}
}
+static inline void msdc_set_data_sample_edge(struct msdc_host *host, bool rising)
+{
+ u32 value = rising ? 0 : 1;
+
+ if (host->dev_comp->support_new_rx) {
+ sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_PATCH_BIT_RD_DAT_SEL, value);
+ sdr_set_field(host->base + MSDC_PATCH_BIT2, MSDC_PB2_CFGCRCSTSEDGE, value);
+ } else {
+ sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL, value);
+ sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL, value);
+ }
+}
+
static int msdc_tune_response(struct mmc_host *mmc, u32 opcode)
{
struct msdc_host *host = mmc_priv(mmc);
@@ -2210,8 +2356,7 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_INT_DAT_LATCH_CK_SEL,
host->latch_ck);
- sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
- sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, true);
for (i = 0; i < host->tuning_step; i++) {
msdc_set_data_delay(host, i);
ret = mmc_send_tuning(mmc, opcode, NULL);
@@ -2224,8 +2369,7 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
(final_rise_delay.start == 0 && final_rise_delay.maxlen >= 4))
goto skip_fall;
- sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
- sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, false);
for (i = 0; i < host->tuning_step; i++) {
msdc_set_data_delay(host, i);
ret = mmc_send_tuning(mmc, opcode, NULL);
@@ -2237,12 +2381,10 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode)
skip_fall:
final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
if (final_maxlen == final_rise_delay.maxlen) {
- sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
- sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, true);
final_delay = final_rise_delay.final_phase;
} else {
- sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL);
- sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, false);
final_delay = final_fall_delay.final_phase;
}
msdc_set_data_delay(host, final_delay);
@@ -2267,8 +2409,7 @@ static int msdc_tune_together(struct mmc_host *mmc, u32 opcode)
host->latch_ck);
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
- sdr_clr_bits(host->base + MSDC_IOCON,
- MSDC_IOCON_DSPL | MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, true);
for (i = 0; i < host->tuning_step; i++) {
msdc_set_cmd_delay(host, i);
msdc_set_data_delay(host, i);
@@ -2283,8 +2424,7 @@ static int msdc_tune_together(struct mmc_host *mmc, u32 opcode)
goto skip_fall;
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
- sdr_set_bits(host->base + MSDC_IOCON,
- MSDC_IOCON_DSPL | MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, false);
for (i = 0; i < host->tuning_step; i++) {
msdc_set_cmd_delay(host, i);
msdc_set_data_delay(host, i);
@@ -2298,13 +2438,11 @@ skip_fall:
final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen);
if (final_maxlen == final_rise_delay.maxlen) {
sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
- sdr_clr_bits(host->base + MSDC_IOCON,
- MSDC_IOCON_DSPL | MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, true);
final_delay = final_rise_delay.final_phase;
} else {
sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL);
- sdr_set_bits(host->base + MSDC_IOCON,
- MSDC_IOCON_DSPL | MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, false);
final_delay = final_fall_delay.final_phase;
}
@@ -2324,8 +2462,7 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode)
if (host->dev_comp->data_tune && host->dev_comp->async_fifo) {
ret = msdc_tune_together(mmc, opcode);
if (host->hs400_mode) {
- sdr_clr_bits(host->base + MSDC_IOCON,
- MSDC_IOCON_DSPL | MSDC_IOCON_W_DSPL);
+ msdc_set_data_sample_edge(host, true);
msdc_set_data_delay(host, 0);
}
goto tune_done;
@@ -2727,7 +2864,6 @@ static int msdc_drv_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct msdc_host *host;
- struct resource *res;
int ret;
if (!pdev->dev.of_node) {
@@ -2736,77 +2872,64 @@ static int msdc_drv_probe(struct platform_device *pdev)
}
/* Allocate MMC host for this device */
- mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
+ mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(struct msdc_host));
if (!mmc)
return -ENOMEM;
host = mmc_priv(mmc);
ret = mmc_of_parse(mmc);
if (ret)
- goto host_free;
+ return ret;
host->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(host->base)) {
- ret = PTR_ERR(host->base);
- goto host_free;
- }
+ if (IS_ERR(host->base))
+ return PTR_ERR(host->base);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res) {
- host->top_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(host->top_base))
- host->top_base = NULL;
- }
+ host->top_base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(host->top_base))
+ host->top_base = NULL;
ret = mmc_regulator_get_supply(mmc);
if (ret)
- goto host_free;
+ return ret;
ret = msdc_of_clock_parse(pdev, host);
if (ret)
- goto host_free;
+ return ret;
host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
"hrst");
- if (IS_ERR(host->reset)) {
- ret = PTR_ERR(host->reset);
- goto host_free;
- }
+ if (IS_ERR(host->reset))
+ return PTR_ERR(host->reset);
/* only eMMC has crypto property */
if (!(mmc->caps2 & MMC_CAP2_NO_MMC)) {
host->crypto_clk = devm_clk_get_optional(&pdev->dev, "crypto");
if (IS_ERR(host->crypto_clk))
- host->crypto_clk = NULL;
- else
+ return PTR_ERR(host->crypto_clk);
+ else if (host->crypto_clk)
mmc->caps2 |= MMC_CAP2_CRYPTO;
}
host->irq = platform_get_irq(pdev, 0);
- if (host->irq < 0) {
- ret = host->irq;
- goto host_free;
- }
+ if (host->irq < 0)
+ return host->irq;
host->pinctrl = devm_pinctrl_get(&pdev->dev);
- if (IS_ERR(host->pinctrl)) {
- ret = PTR_ERR(host->pinctrl);
- dev_err(&pdev->dev, "Cannot find pinctrl!\n");
- goto host_free;
- }
+ if (IS_ERR(host->pinctrl))
+ return dev_err_probe(&pdev->dev, PTR_ERR(host->pinctrl),
+ "Cannot find pinctrl");
host->pins_default = pinctrl_lookup_state(host->pinctrl, "default");
if (IS_ERR(host->pins_default)) {
- ret = PTR_ERR(host->pins_default);
dev_err(&pdev->dev, "Cannot find pinctrl default!\n");
- goto host_free;
+ return PTR_ERR(host->pins_default);
}
host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs");
if (IS_ERR(host->pins_uhs)) {
- ret = PTR_ERR(host->pins_uhs);
dev_err(&pdev->dev, "Cannot find pinctrl uhs!\n");
- goto host_free;
+ return PTR_ERR(host->pins_uhs);
}
/* Support for SDIO eint irq ? */
@@ -2885,7 +3008,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
ret = msdc_ungate_clock(host);
if (ret) {
dev_err(&pdev->dev, "Cannot ungate clocks!\n");
- goto release_mem;
+ goto release_clk;
}
msdc_init_hw(host);
@@ -2895,20 +3018,33 @@ static int msdc_drv_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!host->cq_host) {
ret = -ENOMEM;
- goto host_free;
+ goto release;
}
host->cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
host->cq_host->mmio = host->base + 0x800;
host->cq_host->ops = &msdc_cmdq_ops;
ret = cqhci_init(host->cq_host, mmc, true);
if (ret)
- goto host_free;
+ goto release;
mmc->max_segs = 128;
/* cqhci 16bit length */
/* 0 size, means 65536 so we don't have to -1 here */
mmc->max_seg_size = 64 * 1024;
/* Reduce CIT to 0x40 that corresponds to 2.35us */
msdc_cqe_cit_cal(host, 2350);
+ } else if (mmc->caps2 & MMC_CAP2_NO_SDIO) {
+ /* Use HSQ on eMMC/SD (but not on SDIO) if HW CQE not supported */
+ struct mmc_hsq *hsq = devm_kzalloc(&pdev->dev, sizeof(*hsq), GFP_KERNEL);
+ if (!hsq) {
+ ret = -ENOMEM;
+ goto release;
+ }
+
+ ret = mmc_hsq_init(hsq, mmc);
+ if (ret)
+ goto release;
+
+ host->hsq_en = true;
}
ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
@@ -2929,9 +3065,10 @@ static int msdc_drv_probe(struct platform_device *pdev)
end:
pm_runtime_disable(host->dev);
release:
- platform_set_drvdata(pdev, NULL);
msdc_deinit_hw(host);
+release_clk:
msdc_gate_clock(host);
+ platform_set_drvdata(pdev, NULL);
release_mem:
if (host->dma.gpd)
dma_free_coherent(&pdev->dev,
@@ -2939,11 +3076,8 @@ release_mem:
host->dma.gpd, host->dma.gpd_addr);
if (host->dma.bd)
dma_free_coherent(&pdev->dev,
- MAX_BD_NUM * sizeof(struct mt_bdma_desc),
- host->dma.bd, host->dma.bd_addr);
-host_free:
- mmc_free_host(mmc);
-
+ MAX_BD_NUM * sizeof(struct mt_bdma_desc),
+ host->dma.bd, host->dma.bd_addr);
return ret;
}
@@ -2968,9 +3102,7 @@ static void msdc_drv_remove(struct platform_device *pdev)
2 * sizeof(struct mt_gpdma_desc),
host->dma.gpd, host->dma.gpd_addr);
dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
- host->dma.bd, host->dma.bd_addr);
-
- mmc_free_host(mmc);
+ host->dma.bd, host->dma.bd_addr);
}
static void msdc_save_reg(struct msdc_host *host)
@@ -2995,6 +3127,8 @@ static void msdc_save_reg(struct msdc_host *host)
readl(host->top_base + EMMC_TOP_CMD);
host->save_para.emmc50_pad_ds_tune =
readl(host->top_base + EMMC50_PAD_DS_TUNE);
+ host->save_para.loop_test_control =
+ readl(host->top_base + LOOP_TEST_CONTROL);
} else {
host->save_para.pad_tune = readl(host->base + tune_reg);
}
@@ -3005,6 +3139,15 @@ static void msdc_restore_reg(struct msdc_host *host)
struct mmc_host *mmc = mmc_from_priv(host);
u32 tune_reg = host->dev_comp->pad_tune_reg;
+ if (host->dev_comp->support_new_tx) {
+ sdr_clr_bits(host->base + SDC_ADV_CFG0, SDC_NEW_TX_EN);
+ sdr_set_bits(host->base + SDC_ADV_CFG0, SDC_NEW_TX_EN);
+ }
+ if (host->dev_comp->support_new_rx) {
+ sdr_clr_bits(host->base + MSDC_NEW_RX_CFG, MSDC_NEW_RX_PATH_SEL);
+ sdr_set_bits(host->base + MSDC_NEW_RX_CFG, MSDC_NEW_RX_PATH_SEL);
+ }
+
writel(host->save_para.msdc_cfg, host->base + MSDC_CFG);
writel(host->save_para.iocon, host->base + MSDC_IOCON);
writel(host->save_para.sdc_cfg, host->base + SDC_CFG);
@@ -3023,6 +3166,8 @@ static void msdc_restore_reg(struct msdc_host *host)
host->top_base + EMMC_TOP_CMD);
writel(host->save_para.emmc50_pad_ds_tune,
host->top_base + EMMC50_PAD_DS_TUNE);
+ writel(host->save_para.loop_test_control,
+ host->top_base + LOOP_TEST_CONTROL);
} else {
writel(host->save_para.pad_tune, host->base + tune_reg);
}
@@ -3036,6 +3181,9 @@ static int __maybe_unused msdc_runtime_suspend(struct device *dev)
struct mmc_host *mmc = dev_get_drvdata(dev);
struct msdc_host *host = mmc_priv(mmc);
+ if (host->hsq_en)
+ mmc_hsq_suspend(mmc);
+
msdc_save_reg(host);
if (sdio_irq_claimed(mmc)) {
@@ -3066,6 +3214,10 @@ static int __maybe_unused msdc_runtime_resume(struct device *dev)
pinctrl_select_state(host->pinctrl, host->pins_uhs);
enable_irq(host->irq);
}
+
+ if (host->hsq_en)
+ mmc_hsq_resume(mmc);
+
return 0;
}
@@ -3112,7 +3264,7 @@ static const struct dev_pm_ops msdc_dev_pm_ops = {
static struct platform_driver mt_msdc_driver = {
.probe = msdc_drv_probe,
- .remove_new = msdc_drv_remove,
+ .remove = msdc_drv_remove,
.driver = {
.name = "mtk-msdc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 12df4ff9eeee..b92f3ba38663 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -819,7 +819,7 @@ MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
static struct platform_driver mvsd_driver = {
.probe = mvsd_probe,
- .remove_new = mvsd_remove,
+ .remove = mvsd_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 1edf65291354..e7a286c3216f 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -1225,7 +1225,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume);
static struct platform_driver mxcmci_driver = {
.probe = mxcmci_probe,
- .remove_new = mxcmci_remove,
+ .remove = mxcmci_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 6751da9b60f9..80e6f48c83aa 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -714,7 +714,7 @@ static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume);
static struct platform_driver mxs_mmc_driver = {
.probe = mxs_mmc_probe,
- .remove_new = mxs_mmc_remove,
+ .remove = mxs_mmc_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 335350a4e99a..62252ad4e20d 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1554,7 +1554,7 @@ MODULE_DEVICE_TABLE(of, mmc_omap_match);
static struct platform_driver mmc_omap_driver = {
.probe = mmc_omap_probe,
- .remove_new = mmc_omap_remove,
+ .remove = mmc_omap_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e120aeb869b8..59e36e0ebbbf 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2121,7 +2121,7 @@ static const struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
static struct platform_driver omap_hsmmc_driver = {
.probe = omap_hsmmc_probe,
- .remove_new = omap_hsmmc_remove,
+ .remove = omap_hsmmc_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c
index fc08f25c34eb..797ef48d9204 100644
--- a/drivers/mmc/host/owl-mmc.c
+++ b/drivers/mmc/host/owl-mmc.c
@@ -692,7 +692,7 @@ static struct platform_driver owl_mmc_driver = {
.of_match_table = owl_mmc_of_match,
},
.probe = owl_mmc_probe,
- .remove_new = owl_mmc_remove,
+ .remove = owl_mmc_remove,
};
module_platform_driver(owl_mmc_driver);
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index fae3192c3a14..2d0ad006913d 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -810,7 +810,7 @@ static void pxamci_remove(struct platform_device *pdev)
static struct platform_driver pxamci_driver = {
.probe = pxamci_probe,
- .remove_new = pxamci_remove,
+ .remove = pxamci_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index 1dcaa050f264..4b389e92399e 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -613,7 +613,7 @@ static struct platform_driver renesas_internal_dmac_sdhi_driver = {
.of_match_table = renesas_sdhi_internal_dmac_of_match,
},
.probe = renesas_sdhi_internal_dmac_probe,
- .remove_new = renesas_sdhi_remove,
+ .remove = renesas_sdhi_remove,
};
module_platform_driver(renesas_internal_dmac_sdhi_driver);
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index 0ba3f62a9b49..822a310c9bba 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -471,7 +471,7 @@ static struct platform_driver renesas_sys_dmac_sdhi_driver = {
.of_match_table = renesas_sdhi_sys_dmac_of_match,
},
.probe = renesas_sdhi_sys_dmac_probe,
- .remove_new = renesas_sdhi_remove,
+ .remove = renesas_sdhi_remove,
};
module_platform_driver(renesas_sys_dmac_sdhi_driver);
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 20e79109be16..48d3b0aae5a0 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -1591,7 +1591,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids);
static struct platform_driver rtsx_pci_sdmmc_driver = {
.probe = rtsx_pci_sdmmc_drv_probe,
- .remove_new = rtsx_pci_sdmmc_drv_remove,
+ .remove = rtsx_pci_sdmmc_drv_remove,
.id_table = rtsx_pci_sdmmc_ids,
.driver = {
.name = DRV_NAME_RTSX_PCI_SDMMC,
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c
index 4e86f0a705b6..107c78df53cf 100644
--- a/drivers/mmc/host/rtsx_usb_sdmmc.c
+++ b/drivers/mmc/host/rtsx_usb_sdmmc.c
@@ -1453,7 +1453,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids);
static struct platform_driver rtsx_usb_sdmmc_driver = {
.probe = rtsx_usb_sdmmc_drv_probe,
- .remove_new = rtsx_usb_sdmmc_drv_remove,
+ .remove = rtsx_usb_sdmmc_drv_remove,
.id_table = rtsx_usb_sdmmc_ids,
.driver = {
.name = "rtsx_usb_sdmmc",
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index eb8f427f9770..d1ce9193ece9 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -1080,7 +1080,7 @@ static struct platform_driver sdhci_acpi_driver = {
.pm = &sdhci_acpi_pm_ops,
},
.probe = sdhci_acpi_probe,
- .remove_new = sdhci_acpi_remove,
+ .remove = sdhci_acpi_remove,
};
module_platform_driver(sdhci_acpi_driver);
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
index e067c7f5c537..fda911fb28e5 100644
--- a/drivers/mmc/host/sdhci-bcm-kona.c
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -328,7 +328,7 @@ static struct platform_driver sdhci_bcm_kona_driver = {
.of_match_table = sdhci_bcm_kona_of_match,
},
.probe = sdhci_bcm_kona_probe,
- .remove_new = sdhci_bcm_kona_remove,
+ .remove = sdhci_bcm_kona_remove,
};
module_platform_driver(sdhci_bcm_kona_driver);
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 031a4b514d16..0ef4d578ade8 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -545,7 +545,7 @@ static struct platform_driver sdhci_brcmstb_driver = {
.of_match_table = of_match_ptr(sdhci_brcm_of_match),
},
.probe = sdhci_brcmstb_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
.shutdown = sdhci_brcmstb_shutdown,
};
diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index be1505e8c536..a94b297fcf2a 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -608,7 +608,7 @@ static struct platform_driver sdhci_cdns_driver = {
.of_match_table = sdhci_cdns_match,
},
.probe = sdhci_cdns_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_cdns_driver);
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 88ec23417808..77034b13fa66 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -106,7 +106,7 @@ static struct platform_driver sdhci_dove_driver = {
.of_match_table = sdhci_dove_of_match_table,
},
.probe = sdhci_dove_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_dove_driver);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 8f0bc6dca2b0..d55d045ef236 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -30,7 +30,8 @@
#include "sdhci-esdhc.h"
#include "cqhci.h"
-#define ESDHC_SYS_CTRL_DTOCV_MASK 0x0f
+#define ESDHC_SYS_CTRL_DTOCV_MASK GENMASK(19, 16)
+#define ESDHC_SYS_CTRL_IPP_RST_N BIT(23)
#define ESDHC_CTRL_D3CD 0x08
#define ESDHC_BURST_LEN_EN_INCR (1 << 27)
/* VENDOR SPEC register */
@@ -238,6 +239,7 @@ struct esdhc_platform_data {
struct esdhc_soc_data {
u32 flags;
+ u32 quirks;
};
static const struct esdhc_soc_data esdhc_imx25_data = {
@@ -309,10 +311,12 @@ static struct esdhc_soc_data usdhc_imx7ulp_data = {
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_PMQOS | ESDHC_FLAG_HS400
| ESDHC_FLAG_STATE_LOST_IN_LPMODE,
+ .quirks = SDHCI_QUIRK_NO_LED,
};
static struct esdhc_soc_data usdhc_imxrt1050_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200,
+ .quirks = SDHCI_QUIRK_NO_LED,
};
static struct esdhc_soc_data usdhc_imx8qxp_data = {
@@ -321,6 +325,7 @@ static struct esdhc_soc_data usdhc_imx8qxp_data = {
| ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES
| ESDHC_FLAG_STATE_LOST_IN_LPMODE
| ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME,
+ .quirks = SDHCI_QUIRK_NO_LED,
};
static struct esdhc_soc_data usdhc_imx8mm_data = {
@@ -328,6 +333,7 @@ static struct esdhc_soc_data usdhc_imx8mm_data = {
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES
| ESDHC_FLAG_STATE_LOST_IN_LPMODE,
+ .quirks = SDHCI_QUIRK_NO_LED,
};
struct pltfm_imx_data {
@@ -1385,8 +1391,8 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
/* use maximum timeout counter */
esdhc_clrset_le(host, ESDHC_SYS_CTRL_DTOCV_MASK,
- esdhc_is_usdhc(imx_data) ? 0xF : 0xE,
- SDHCI_TIMEOUT_CONTROL);
+ esdhc_is_usdhc(imx_data) ? 0xF0000 : 0xE0000,
+ ESDHC_SYSTEM_CONTROL);
}
static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask)
@@ -1402,6 +1408,17 @@ static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask)
return 0;
}
+static void esdhc_hw_reset(struct sdhci_host *host)
+{
+ esdhc_clrset_le(host, ESDHC_SYS_CTRL_IPP_RST_N, 0, ESDHC_SYSTEM_CONTROL);
+ /* eMMC spec requires minimum 1us, here delay between 1-10us */
+ usleep_range(1, 10);
+ esdhc_clrset_le(host, ESDHC_SYS_CTRL_IPP_RST_N,
+ ESDHC_SYS_CTRL_IPP_RST_N, ESDHC_SYSTEM_CONTROL);
+ /* eMMC spec requires minimum 200us, here delay between 200-300us */
+ usleep_range(200, 300);
+}
+
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@@ -1420,6 +1437,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.reset = esdhc_reset,
.irq = esdhc_cqhci_irq,
.dump_vendor_regs = esdhc_dump_debug_regs,
+ .hw_reset = esdhc_hw_reset,
};
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -1524,7 +1542,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
} else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
/*
- * ESDHC_STD_TUNING_EN may be configed in bootloader
+ * ESDHC_STD_TUNING_EN may be configured in bootloader
* or ROM code, so clear this bit here to make sure
* the manual tuning can work.
*/
@@ -1626,7 +1644,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
/*
* If we have this property, then activate WP check.
- * Retrieveing and requesting the actual WP GPIO will happen
+ * Retrieving and requesting the actual WP GPIO will happen
* in the call to mmc_of_parse().
*/
if (of_property_read_bool(np, "wp-gpios"))
@@ -1687,6 +1705,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
imx_data->socdata = device_get_match_data(&pdev->dev);
+ host->quirks |= imx_data->socdata->quirks;
if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0);
@@ -2015,7 +2034,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
.pm = &sdhci_esdhc_pmops,
},
.probe = sdhci_esdhc_imx_probe,
- .remove_new = sdhci_esdhc_imx_remove,
+ .remove = sdhci_esdhc_imx_remove,
};
module_platform_driver(sdhci_esdhc_imx_driver);
diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c b/drivers/mmc/host/sdhci-esdhc-mcf.c
index 3ad87322f6a5..327662ba5bd9 100644
--- a/drivers/mmc/host/sdhci-esdhc-mcf.c
+++ b/drivers/mmc/host/sdhci-esdhc-mcf.c
@@ -512,7 +512,7 @@ static struct platform_driver sdhci_esdhc_mcf_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = sdhci_esdhc_mcf_probe,
- .remove_new = sdhci_esdhc_mcf_remove,
+ .remove = sdhci_esdhc_mcf_remove,
};
module_platform_driver(sdhci_esdhc_mcf_driver);
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
index 10235fdff246..80b2567a488b 100644
--- a/drivers/mmc/host/sdhci-iproc.c
+++ b/drivers/mmc/host/sdhci-iproc.c
@@ -424,7 +424,7 @@ static struct platform_driver sdhci_iproc_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_iproc_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
.shutdown = sdhci_iproc_shutdown,
};
module_platform_driver(sdhci_iproc_driver);
diff --git a/drivers/mmc/host/sdhci-milbeaut.c b/drivers/mmc/host/sdhci-milbeaut.c
index 83706edc9796..a4675456f9c7 100644
--- a/drivers/mmc/host/sdhci-milbeaut.c
+++ b/drivers/mmc/host/sdhci-milbeaut.c
@@ -335,7 +335,7 @@ static struct platform_driver sdhci_milbeaut_driver = {
.of_match_table = mlb_dt_ids,
},
.probe = sdhci_milbeaut_probe,
- .remove_new = sdhci_milbeaut_remove,
+ .remove = sdhci_milbeaut_remove,
};
module_platform_driver(sdhci_milbeaut_driver);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index e113b99a3eab..e00208535bd1 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2601,7 +2601,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
sdhci_msm_handle_pwr_irq(host, 0);
/*
- * Ensure that above writes are propogated before interrupt enablement
+ * Ensure that above writes are propagated before interrupt enablement
* in GIC.
*/
mb();
@@ -2753,7 +2753,7 @@ static const struct dev_pm_ops sdhci_msm_pm_ops = {
static struct platform_driver sdhci_msm_driver = {
.probe = sdhci_msm_probe,
- .remove_new = sdhci_msm_remove,
+ .remove = sdhci_msm_remove,
.driver = {
.name = "sdhci_msm",
.of_match_table = sdhci_msm_dt_match,
diff --git a/drivers/mmc/host/sdhci-npcm.c b/drivers/mmc/host/sdhci-npcm.c
index 5bf9d18f364e..bee0585ba5c1 100644
--- a/drivers/mmc/host/sdhci-npcm.c
+++ b/drivers/mmc/host/sdhci-npcm.c
@@ -85,7 +85,7 @@ static struct platform_driver npcm_sdhci_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = npcm_sdhci_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
};
module_platform_driver(npcm_sdhci_driver);
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index 5edd024347bd..8c29676ab662 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -76,6 +76,8 @@
#define FREQSEL_225M_200M 0x7
#define PHY_DLL_TIMEOUT_MS 100
+#define SDHCI_HW_RST_EN BIT(4)
+
/* Default settings for ZynqMP Clock Phases */
#define ZYNQMP_ICLK_PHASE {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0}
#define ZYNQMP_OCLK_PHASE {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0}
@@ -475,6 +477,21 @@ static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask)
}
}
+static void sdhci_arasan_hw_reset(struct sdhci_host *host)
+{
+ u8 reg;
+
+ reg = sdhci_readb(host, SDHCI_POWER_CONTROL);
+ reg |= SDHCI_HW_RST_EN;
+ sdhci_writeb(host, reg, SDHCI_POWER_CONTROL);
+ /* As per eMMC spec, minimum 1us is required but give it 2us for good measure */
+ usleep_range(2, 5);
+ reg &= ~SDHCI_HW_RST_EN;
+ sdhci_writeb(host, reg, SDHCI_POWER_CONTROL);
+ /* As per eMMC spec, minimum 200us is required but give it 300us for good measure */
+ usleep_range(300, 500);
+}
+
static int sdhci_arasan_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios)
{
@@ -505,6 +522,7 @@ static const struct sdhci_ops sdhci_arasan_ops = {
.reset = sdhci_arasan_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.set_power = sdhci_set_power_and_bus_voltage,
+ .hw_reset = sdhci_arasan_hw_reset,
};
static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
@@ -2046,7 +2064,7 @@ static struct platform_driver sdhci_arasan_driver = {
.pm = &sdhci_arasan_dev_pm_ops,
},
.probe = sdhci_arasan_probe,
- .remove_new = sdhci_arasan_remove,
+ .remove = sdhci_arasan_remove,
};
module_platform_driver(sdhci_arasan_driver);
diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c
index 37240895ffaa..d6de010551b9 100644
--- a/drivers/mmc/host/sdhci-of-aspeed.c
+++ b/drivers/mmc/host/sdhci-of-aspeed.c
@@ -519,7 +519,7 @@ static struct platform_driver aspeed_sdhci_driver = {
.of_match_table = aspeed_sdhci_of_match,
},
.probe = aspeed_sdhci_probe,
- .remove_new = aspeed_sdhci_remove,
+ .remove = aspeed_sdhci_remove,
};
static int aspeed_sdc_probe(struct platform_device *pdev)
@@ -596,7 +596,7 @@ static struct platform_driver aspeed_sdc_driver = {
.of_match_table = aspeed_sdc_of_match,
},
.probe = aspeed_sdc_probe,
- .remove_new = aspeed_sdc_remove,
+ .remove = aspeed_sdc_remove,
};
#if defined(CONFIG_MMC_SDHCI_OF_ASPEED_TEST)
diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c
index 23a9faad2ff8..97988ed37467 100644
--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -471,7 +471,7 @@ static struct platform_driver sdhci_at91_driver = {
.pm = &sdhci_at91_dev_pm_ops,
},
.probe = sdhci_at91_probe,
- .remove_new = sdhci_at91_remove,
+ .remove = sdhci_at91_remove,
};
module_platform_driver(sdhci_at91_driver);
diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
index 8fd80dac11bf..7ea3da45db32 100644
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -1626,7 +1626,7 @@ static struct platform_driver sdhci_dwcmshc_driver = {
.pm = &dwcmshc_pmops,
},
.probe = dwcmshc_probe,
- .remove_new = dwcmshc_remove,
+ .remove = dwcmshc_remove,
};
module_platform_driver(sdhci_dwcmshc_driver);
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 3ae9aa25745a..002d0d59b992 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -1521,7 +1521,7 @@ static struct platform_driver sdhci_esdhc_driver = {
.pm = &esdhc_of_dev_pm_ops,
},
.probe = sdhci_esdhc_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_esdhc_driver);
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 9c1c0ce610ef..5bb845d13599 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -85,7 +85,7 @@ static struct platform_driver sdhci_hlwd_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_hlwd_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_hlwd_driver);
diff --git a/drivers/mmc/host/sdhci-of-ma35d1.c b/drivers/mmc/host/sdhci-of-ma35d1.c
index b84c2927bd4a..1e6d180100ad 100644
--- a/drivers/mmc/host/sdhci-of-ma35d1.c
+++ b/drivers/mmc/host/sdhci-of-ma35d1.c
@@ -305,7 +305,7 @@ static struct platform_driver sdhci_ma35_driver = {
.of_match_table = sdhci_ma35_dt_ids,
},
.probe = ma35_probe,
- .remove_new = ma35_remove,
+ .remove = ma35_remove,
};
module_platform_driver(sdhci_ma35_driver);
diff --git a/drivers/mmc/host/sdhci-of-sparx5.c b/drivers/mmc/host/sdhci-of-sparx5.c
index 64b77e7d14cd..d2aa684e786f 100644
--- a/drivers/mmc/host/sdhci-of-sparx5.c
+++ b/drivers/mmc/host/sdhci-of-sparx5.c
@@ -255,7 +255,7 @@ static struct platform_driver sdhci_sparx5_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_sparx5_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_sparx5_driver);
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index 5841a9afeb9f..54d795205fb4 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -1478,7 +1478,7 @@ static const struct dev_pm_ops sdhci_omap_dev_pm_ops = {
static struct platform_driver sdhci_omap_driver = {
.probe = sdhci_omap_probe,
- .remove_new = sdhci_omap_remove,
+ .remove = sdhci_omap_remove,
.driver = {
.name = "sdhci-omap",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index ed45ed0bdafd..2b300bc4a701 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -40,6 +40,7 @@
#include "sdhci.h"
#include "sdhci-cqhci.h"
#include "sdhci-pci.h"
+#include "sdhci-uhs2.h"
static void sdhci_pci_hw_reset(struct sdhci_host *host);
@@ -2181,7 +2182,10 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
if (scratch == (u32)-1)
dead = 1;
- sdhci_remove_host(slot->host, dead);
+ if (slot->chip->fixes && slot->chip->fixes->remove_host)
+ slot->chip->fixes->remove_host(slot, dead);
+ else
+ sdhci_remove_host(slot->host, dead);
if (slot->chip->fixes && slot->chip->fixes->remove_slot)
slot->chip->fixes->remove_slot(slot, dead);
@@ -2189,6 +2193,16 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
sdhci_free_host(slot->host);
}
+int sdhci_pci_uhs2_add_host(struct sdhci_pci_slot *slot)
+{
+ return sdhci_uhs2_add_host(slot->host);
+}
+
+void sdhci_pci_uhs2_remove_host(struct sdhci_pci_slot *slot, int dead)
+{
+ sdhci_uhs2_remove_host(slot->host, dead);
+}
+
static void sdhci_pci_runtime_pm_allow(struct device *dev)
{
pm_suspend_ignore_children(dev, 1);
diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
index 0f81586a19df..4c2ae71770f7 100644
--- a/drivers/mmc/host/sdhci-pci-gli.c
+++ b/drivers/mmc/host/sdhci-pci-gli.c
@@ -18,6 +18,7 @@
#include "sdhci-cqhci.h"
#include "sdhci-pci.h"
#include "cqhci.h"
+#include "sdhci-uhs2.h"
/* Genesys Logic extra registers */
#define SDHCI_GLI_9750_WT 0x800
@@ -139,13 +140,49 @@
#define PCI_GLI_9755_PLLSSC 0x68
#define PCI_GLI_9755_PLLSSC_PPM GENMASK(15, 0)
+#define PCI_GLI_9755_PLLSSC_RTL BIT(24)
+#define GLI_9755_PLLSSC_RTL_VALUE 0x1
+#define PCI_GLI_9755_PLLSSC_TRANS_PASS BIT(27)
+#define GLI_9755_PLLSSC_TRANS_PASS_VALUE 0x1
+#define PCI_GLI_9755_PLLSSC_RECV GENMASK(29, 28)
+#define GLI_9755_PLLSSC_RECV_VALUE 0x0
+#define PCI_GLI_9755_PLLSSC_TRAN GENMASK(31, 30)
+#define GLI_9755_PLLSSC_TRAN_VALUE 0x3
+
+#define PCI_GLI_9755_UHS2_PLL 0x6C
+#define PCI_GLI_9755_UHS2_PLL_SSC GENMASK(9, 8)
+#define GLI_9755_UHS2_PLL_SSC_VALUE 0x0
+#define PCI_GLI_9755_UHS2_PLL_DELAY BIT(18)
+#define GLI_9755_UHS2_PLL_DELAY_VALUE 0x1
+#define PCI_GLI_9755_UHS2_PLL_PDRST BIT(27)
+#define GLI_9755_UHS2_PLL_PDRST_VALUE 0x1
#define PCI_GLI_9755_SerDes 0x70
+#define PCI_GLI_9755_UHS2_SERDES_INTR GENMASK(2, 0)
+#define GLI_9755_UHS2_SERDES_INTR_VALUE 0x3
+#define PCI_GLI_9755_UHS2_SERDES_ZC1 BIT(3)
+#define GLI_9755_UHS2_SERDES_ZC1_VALUE 0x0
+#define PCI_GLI_9755_UHS2_SERDES_ZC2 GENMASK(7, 4)
+#define GLI_9755_UHS2_SERDES_ZC2_DEFAULT 0xB
+#define GLI_9755_UHS2_SERDES_ZC2_SANDISK 0x0
#define PCI_GLI_9755_SCP_DIS BIT(19)
+#define PCI_GLI_9755_UHS2_SERDES_TRAN GENMASK(27, 24)
+#define GLI_9755_UHS2_SERDES_TRAN_VALUE 0xC
+#define PCI_GLI_9755_UHS2_SERDES_RECV GENMASK(31, 28)
+#define GLI_9755_UHS2_SERDES_RECV_VALUE 0xF
#define PCI_GLI_9755_MISC 0x78
#define PCI_GLI_9755_MISC_SSC_OFF BIT(26)
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL 0x508
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_CMD_CONFLICT_CHECK BIT(0)
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE GENMASK(21, 16)
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_PLUG_IN_VALUE 0x05
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_PLUG_OUT_VALUE 0x3F
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE GENMASK(23, 22)
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE_1MS 0x2
+#define SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE_10MS 0x3
+
#define SDHCI_GLI_9767_GM_BURST_SIZE 0x510
#define SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET BIT(8)
@@ -182,6 +219,13 @@
#define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
#define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
+#define PCIE_GLI_9767_RESET_REG 0x8E4
+#define PCIE_GLI_9767_RESET_REG_SD_HOST_SW_RESET BIT(0)
+
+#define PCIE_GLI_9767_UHS2_PHY_SET_REG1 0x90C
+#define PCIE_GLI_9767_UHS2_PHY_SET_REG1_SERDES_INTR GENMASK(31, 29)
+#define PCIE_GLI_9767_UHS2_PHY_SET_REG1_SERDES_INTR_VALUE 0x3
+
#define PCIE_GLI_9767_SDHC_CAP 0x91C
#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5)
@@ -200,9 +244,15 @@
#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1)
#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_SELECT_UHS2 BIT(5)
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_UHS2_SWITCH_CTL BIT(8)
#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16)
#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64
+#define PCIE_GLI_9767_UHS2_PHY_SET_REG2 0x948
+#define PCIE_GLI_9767_UHS2_PHY_SET_REG2_SSC_PPM_SETTING GENMASK(22, 21)
+#define PCIE_GLI_9767_UHS2_PHY_SET_REG2_SSC_PPM_SETTING_VALUE 0x0
+
#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950
#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0)
@@ -212,6 +262,28 @@
#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958
#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN BIT(0)
+#define PCIE_GLI_9767_UHS2_CTL1 0x95C
+#define PCIE_GLI_9767_UHS2_CTL1_TRANS_PASS BIT(5)
+#define PCIE_GLI_9767_UHS2_CTL1_TRANS_PASS_VALUE 0x1
+#define PCIE_GLI_9767_UHS2_CTL1_DECODING_CTL BIT(6)
+#define PCIE_GLI_9767_UHS2_CTL1_DECODING_CTL_VALUE 0x1
+#define PCIE_GLI_9767_UHS2_CTL1_SERDES_TRAN GENMASK(10, 7)
+#define PCIE_GLI_9767_UHS2_CTL1_SERDES_TRAN_VALUE 0x3
+#define PCIE_GLI_9767_UHS2_CTL1_SERDES_RECV GENMASK(14, 11)
+#define PCIE_GLI_9767_UHS2_CTL1_SERDES_RECV_VALUE 0xf
+#define PCIE_GLI_9767_UHS2_CTL1_DIR_TRANS GENMASK(16, 15)
+#define PCIE_GLI_9767_UHS2_CTL1_DIR_TRANS_VALUE 0x0
+#define PCIE_GLI_9767_UHS2_CTL1_DIR_RECV GENMASK(18, 17)
+#define PCIE_GLI_9767_UHS2_CTL1_DIR_RECV_VALUE 0x0
+#define PCIE_GLI_9767_UHS2_CTL1_PDRST BIT(25)
+#define PCIE_GLI_9767_UHS2_CTL1_PDRST_VALUE 0x1
+
+#define PCIE_GLI_9767_UHS2_CTL2 0x964
+#define PCIE_GLI_9767_UHS2_CTL2_ZC GENMASK(3, 0)
+#define PCIE_GLI_9767_UHS2_CTL2_ZC_VALUE 0xb
+#define PCIE_GLI_9767_UHS2_CTL2_ZC_CTL BIT(6)
+#define PCIE_GLI_9767_UHS2_CTL2_ZC_CTL_VALUE 0x1
+
#define GLI_MAX_TUNING_LOOP 40
/* Genesys Logic chipset */
@@ -779,6 +851,203 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
gl9755_wt_off(pdev);
}
+static void gl9755_vendor_init(struct sdhci_host *host)
+{
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ struct pci_dev *pdev = slot->chip->pdev;
+ u32 serdes;
+ u32 pllssc;
+ u32 uhs2_pll;
+
+ gl9755_wt_on(pdev);
+
+ pci_read_config_dword(pdev, PCI_GLI_9755_SerDes, &serdes);
+ serdes &= ~PCI_GLI_9755_UHS2_SERDES_TRAN;
+ serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_TRAN,
+ GLI_9755_UHS2_SERDES_TRAN_VALUE);
+ serdes &= ~PCI_GLI_9755_UHS2_SERDES_RECV;
+ serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_RECV,
+ GLI_9755_UHS2_SERDES_RECV_VALUE);
+ serdes &= ~PCI_GLI_9755_UHS2_SERDES_INTR;
+ serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_INTR,
+ GLI_9755_UHS2_SERDES_INTR_VALUE);
+ serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC1;
+ serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_ZC1,
+ GLI_9755_UHS2_SERDES_ZC1_VALUE);
+ serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC2;
+ serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_ZC2,
+ GLI_9755_UHS2_SERDES_ZC2_DEFAULT);
+ pci_write_config_dword(pdev, PCI_GLI_9755_SerDes, serdes);
+
+ pci_read_config_dword(pdev, PCI_GLI_9755_UHS2_PLL, &uhs2_pll);
+ uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_SSC;
+ uhs2_pll |= FIELD_PREP(PCI_GLI_9755_UHS2_PLL_SSC,
+ GLI_9755_UHS2_PLL_SSC_VALUE);
+ uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_DELAY;
+ uhs2_pll |= FIELD_PREP(PCI_GLI_9755_UHS2_PLL_DELAY,
+ GLI_9755_UHS2_PLL_DELAY_VALUE);
+ uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_PDRST;
+ uhs2_pll |= FIELD_PREP(PCI_GLI_9755_UHS2_PLL_PDRST,
+ GLI_9755_UHS2_PLL_PDRST_VALUE);
+ pci_write_config_dword(pdev, PCI_GLI_9755_UHS2_PLL, uhs2_pll);
+
+ pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &pllssc);
+ pllssc &= ~PCI_GLI_9755_PLLSSC_RTL;
+ pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_RTL,
+ GLI_9755_PLLSSC_RTL_VALUE);
+ pllssc &= ~PCI_GLI_9755_PLLSSC_TRANS_PASS;
+ pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_TRANS_PASS,
+ GLI_9755_PLLSSC_TRANS_PASS_VALUE);
+ pllssc &= ~PCI_GLI_9755_PLLSSC_RECV;
+ pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_RECV,
+ GLI_9755_PLLSSC_RECV_VALUE);
+ pllssc &= ~PCI_GLI_9755_PLLSSC_TRAN;
+ pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_TRAN,
+ GLI_9755_PLLSSC_TRAN_VALUE);
+ pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, pllssc);
+
+ gl9755_wt_off(pdev);
+}
+
+static void sdhci_gli_pre_detect_init(struct sdhci_host *host)
+{
+ /* Need more time on UHS2 detect flow */
+ sdhci_writeb(host, 0xA7, SDHCI_UHS2_TIMER_CTRL);
+}
+
+static void sdhci_gli_overcurrent_event_enable(struct sdhci_host *host, bool enable)
+{
+ u32 mask;
+
+ mask = sdhci_readl(host, SDHCI_SIGNAL_ENABLE);
+ if (enable)
+ mask |= SDHCI_INT_BUS_POWER;
+ else
+ mask &= ~SDHCI_INT_BUS_POWER;
+
+ sdhci_writel(host, mask, SDHCI_SIGNAL_ENABLE);
+
+ mask = sdhci_readl(host, SDHCI_INT_ENABLE);
+ if (enable)
+ mask |= SDHCI_INT_BUS_POWER;
+ else
+ mask &= ~SDHCI_INT_BUS_POWER;
+
+ sdhci_writel(host, mask, SDHCI_INT_ENABLE);
+}
+
+static void gl9755_set_power(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd)
+{
+ u8 pwr = 0;
+
+ if (mode != MMC_POWER_OFF) {
+ pwr = sdhci_get_vdd_value(vdd);
+ if (!pwr)
+ WARN(1, "%s: Invalid vdd %#x\n", mmc_hostname(host->mmc), vdd);
+ pwr |= SDHCI_VDD2_POWER_180;
+ }
+
+ if (host->pwr == pwr)
+ return;
+
+ host->pwr = pwr;
+
+ if (pwr == 0) {
+ sdhci_gli_overcurrent_event_enable(host, false);
+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+ } else {
+ sdhci_gli_overcurrent_event_enable(host, false);
+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+
+ pwr |= (SDHCI_POWER_ON | SDHCI_VDD2_POWER_ON);
+
+ sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL);
+ /* wait stable */
+ mdelay(5);
+ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ /* wait stable */
+ mdelay(5);
+ sdhci_gli_overcurrent_event_enable(host, true);
+ }
+}
+
+static bool sdhci_wait_clock_stable(struct sdhci_host *host)
+{
+ u16 clk = 0;
+
+ if (read_poll_timeout_atomic(sdhci_readw, clk, (clk & SDHCI_CLOCK_INT_STABLE),
+ 10, 20000, false, host, SDHCI_CLOCK_CONTROL)) {
+ pr_err("%s: Internal clock never stabilised.\n", mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ return false;
+ }
+ return true;
+}
+
+static void sdhci_gli_enable_internal_clock(struct sdhci_host *host)
+{
+ u16 ctrl2;
+
+ ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+ sdhci_writew(host, SDHCI_CLOCK_INT_EN, SDHCI_CLOCK_CONTROL);
+
+ if (!((ctrl2 & SDHCI_CTRL_V4_MODE) &&
+ (ctrl2 & SDHCI_CTRL_UHS2_ENABLE))) {
+ sdhci_wait_clock_stable(host);
+ sdhci_writew(host, SDHCI_CTRL_V4_MODE, SDHCI_HOST_CONTROL2);
+ }
+}
+
+static int sdhci_gli_wait_software_reset_done(struct sdhci_host *host, u8 mask)
+{
+ u8 rst;
+
+ /* hw clears the bit when it's done */
+ if (read_poll_timeout_atomic(sdhci_readb, rst, !(rst & mask),
+ 10, 100000, false, host, SDHCI_SOFTWARE_RESET)) {
+ pr_err("%s: Reset 0x%x never completed.\n", mmc_hostname(host->mmc), (int)mask);
+ sdhci_dumpregs(host);
+ /* manual clear */
+ sdhci_writeb(host, 0, SDHCI_SOFTWARE_RESET);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void sdhci_gli_uhs2_reset_sd_tran(struct sdhci_host *host)
+{
+ /* do this on UHS2 mode */
+ if (host->mmc->uhs2_sd_tran) {
+ sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD);
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ sdhci_uhs2_clear_set_irqs(host,
+ SDHCI_INT_ALL_MASK,
+ SDHCI_UHS2_INT_ERROR_MASK);
+ }
+}
+
+static void sdhci_gl9755_reset(struct sdhci_host *host, u8 mask)
+{
+ /* need internal clock */
+ if (mask & SDHCI_RESET_ALL)
+ sdhci_gli_enable_internal_clock(host);
+
+ sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
+
+ /* reset sd-tran on UHS2 mode if need to reset cmd/data */
+ if ((mask & SDHCI_RESET_CMD) | (mask & SDHCI_RESET_DATA))
+ sdhci_gli_uhs2_reset_sd_tran(host);
+
+ if (mask & SDHCI_RESET_ALL)
+ host->clock = 0;
+
+ sdhci_gli_wait_software_reset_done(host, mask);
+}
+
static inline void gl9767_vhs_read(struct pci_dev *pdev)
{
u32 vhs_enable;
@@ -892,28 +1161,40 @@ static void gl9767_disable_ssc_pll(struct pci_dev *pdev)
gl9767_vhs_read(pdev);
}
+static void gl9767_set_low_power_negotiation(struct pci_dev *pdev, bool enable)
+{
+ u32 value;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
+ if (enable)
+ value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
+ else
+ value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
+
+ gl9767_vhs_read(pdev);
+}
+
static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_pci_slot *slot = sdhci_priv(host);
struct mmc_ios *ios = &host->mmc->ios;
struct pci_dev *pdev;
- u32 value;
u16 clk;
pdev = slot->chip->pdev;
host->mmc->actual_clock = 0;
- gl9767_vhs_write(pdev);
-
- pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
- value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
- pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
-
+ gl9767_set_low_power_negotiation(pdev, false);
gl9767_disable_ssc_pll(pdev);
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
- if (clock == 0)
+ if (clock == 0) {
+ gl9767_set_low_power_negotiation(pdev, true);
return;
+ }
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
@@ -922,12 +1203,32 @@ static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
}
sdhci_enable_clk(host, clk);
+ gl9767_set_low_power_negotiation(pdev, true);
+}
- pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
- value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
- pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
+static void sdhci_gl9767_set_card_detect_debounce_time(struct sdhci_host *host)
+{
+ u32 value;
- gl9767_vhs_read(pdev);
+ value = sdhci_readl(host, SDHCI_GLI_9767_SD_HOST_OPERATION_CTL);
+ value &= ~(SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE |
+ SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE);
+ if (sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)
+ value |= FIELD_PREP(SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE,
+ SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_PLUG_IN_VALUE) |
+ FIELD_PREP(SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE,
+ SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE_1MS);
+ else
+ value |= FIELD_PREP(SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE,
+ SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_PLUG_OUT_VALUE) |
+ FIELD_PREP(SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE,
+ SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_DEBOUNCE_SCALE_10MS);
+ sdhci_writel(host, value, SDHCI_GLI_9767_SD_HOST_OPERATION_CTL);
+}
+
+static void sdhci_gl9767_card_event(struct sdhci_host *host)
+{
+ sdhci_gl9767_set_card_detect_debounce_time(host);
}
static void gli_set_9767(struct sdhci_host *host)
@@ -937,6 +1238,12 @@ static void gli_set_9767(struct sdhci_host *host)
value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE);
value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET;
sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE);
+
+ value = sdhci_readl(host, SDHCI_GLI_9767_SD_HOST_OPERATION_CTL);
+ value &= ~SDHCI_GLI_9767_SD_HOST_OPERATION_CTL_CMD_CONFLICT_CHECK;
+ sdhci_writel(host, value, SDHCI_GLI_9767_SD_HOST_OPERATION_CTL);
+
+ sdhci_gl9767_set_card_detect_debounce_time(host);
}
static void gl9767_hw_setting(struct sdhci_pci_slot *slot)
@@ -975,7 +1282,43 @@ static void gl9767_hw_setting(struct sdhci_pci_slot *slot)
static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
{
- sdhci_reset(host, mask);
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ struct pci_dev *pdev = slot->chip->pdev;
+ u32 value;
+
+ /* need internal clock */
+ if (mask & SDHCI_RESET_ALL) {
+ sdhci_gli_enable_internal_clock(host);
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_RESET_REG, &value);
+ value &= ~PCIE_GLI_9767_RESET_REG_SD_HOST_SW_RESET;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_RESET_REG, value);
+
+ if (read_poll_timeout_atomic(pci_read_config_dword, value,
+ !(value & PCIE_GLI_9767_RESET_REG_SD_HOST_SW_RESET),
+ 1, 5, true, pdev, PCIE_GLI_9767_RESET_REG, &value)) {
+ pr_warn("%s: %s: Reset SDHC AHB and TL-AMBA failure.\n",
+ __func__, mmc_hostname(host->mmc));
+ gl9767_vhs_read(pdev);
+ return;
+ }
+ gl9767_vhs_read(pdev);
+ }
+
+ if (mmc_card_uhs2(host->mmc)) {
+ if (mask & (SDHCI_RESET_CMD | SDHCI_RESET_DATA)) {
+ sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
+ sdhci_gli_uhs2_reset_sd_tran(host);
+ sdhci_gli_wait_software_reset_done(host, mask);
+ } else {
+ sdhci_uhs2_reset(host, mask);
+ }
+ } else {
+ sdhci_reset(host, mask);
+ }
+
gli_set_9767(host);
}
@@ -1061,11 +1404,94 @@ static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
}
+ pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
+ value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
gl9767_vhs_read(pdev);
return 0;
}
+static void gl9767_vendor_init(struct sdhci_host *host)
+{
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ struct pci_dev *pdev = slot->chip->pdev;
+ u32 value;
+
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_UHS2_PHY_SET_REG1, &value);
+ value |= FIELD_PREP(PCIE_GLI_9767_UHS2_PHY_SET_REG1_SERDES_INTR,
+ PCIE_GLI_9767_UHS2_PHY_SET_REG1_SERDES_INTR_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_PHY_SET_REG1, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_UHS2_PHY_SET_REG2, &value);
+ value |= FIELD_PREP(PCIE_GLI_9767_UHS2_PHY_SET_REG2_SSC_PPM_SETTING,
+ PCIE_GLI_9767_UHS2_PHY_SET_REG2_SSC_PPM_SETTING_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_PHY_SET_REG2, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL1, &value);
+ value |= FIELD_PREP(PCIE_GLI_9767_UHS2_CTL1_TRANS_PASS,
+ PCIE_GLI_9767_UHS2_CTL1_TRANS_PASS_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_UHS2_CTL1_DECODING_CTL,
+ PCIE_GLI_9767_UHS2_CTL1_DECODING_CTL_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_UHS2_CTL1_SERDES_TRAN,
+ PCIE_GLI_9767_UHS2_CTL1_SERDES_TRAN_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_UHS2_CTL1_SERDES_RECV,
+ PCIE_GLI_9767_UHS2_CTL1_SERDES_RECV_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_UHS2_CTL1_DIR_TRANS,
+ PCIE_GLI_9767_UHS2_CTL1_DIR_TRANS_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_UHS2_CTL1_DIR_RECV,
+ PCIE_GLI_9767_UHS2_CTL1_DIR_RECV_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_UHS2_CTL1_PDRST,
+ PCIE_GLI_9767_UHS2_CTL1_PDRST_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL1, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, &value);
+ value |= FIELD_PREP(PCIE_GLI_9767_UHS2_CTL2_ZC,
+ PCIE_GLI_9767_UHS2_CTL2_ZC_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_UHS2_CTL2_ZC_CTL,
+ PCIE_GLI_9767_UHS2_CTL2_ZC_CTL_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, value);
+
+ gl9767_vhs_read(pdev);
+}
+
+static void sdhci_gl9767_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd)
+{
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ struct pci_dev *pdev = slot->chip->pdev;
+ u32 value;
+
+ if (mmc_card_uhs2(host->mmc)) {
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
+ value |= PCIE_GLI_9767_SD_DATA_MULTI_CTL_SELECT_UHS2 |
+ PCIE_GLI_9767_SD_DATA_MULTI_CTL_UHS2_SWITCH_CTL;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
+
+ gl9767_vhs_read(pdev);
+
+ sdhci_gli_overcurrent_event_enable(host, false);
+ sdhci_uhs2_set_power(host, mode, vdd);
+ sdhci_gli_overcurrent_event_enable(host, true);
+ } else {
+ gl9767_vhs_write(pdev);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
+ value &= ~(PCIE_GLI_9767_SD_DATA_MULTI_CTL_SELECT_UHS2 |
+ PCIE_GLI_9767_SD_DATA_MULTI_CTL_UHS2_SWITCH_CTL);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
+
+ gl9767_vhs_read(pdev);
+
+ sdhci_gli_overcurrent_event_enable(host, false);
+ sdhci_set_power(host, mode, vdd);
+ sdhci_gli_overcurrent_event_enable(host, true);
+ }
+}
+
static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
{
struct sdhci_host *host = slot->host;
@@ -1086,6 +1512,7 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot)
gli_pcie_enable_msi(slot);
slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
sdhci_enable_v4_mode(host);
+ gl9755_vendor_init(host);
return 0;
}
@@ -1101,6 +1528,7 @@ static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
host->mmc->caps2 |= MMC_CAP2_SD_EXP;
host->mmc_host_ops.init_sd_express = gl9767_init_sd_express;
sdhci_enable_v4_mode(host);
+ gl9767_vendor_init(host);
return 0;
}
@@ -1524,17 +1952,24 @@ static const struct sdhci_ops sdhci_gl9755_ops = {
.read_w = sdhci_gli_readw,
.read_b = sdhci_gli_readb,
.set_clock = sdhci_gl9755_set_clock,
+ .set_power = gl9755_set_power,
.enable_dma = sdhci_pci_enable_dma,
.set_bus_width = sdhci_set_bus_width,
- .reset = sdhci_reset,
+ .reset = sdhci_gl9755_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.voltage_switch = sdhci_gli_voltage_switch,
+ .dump_uhs2_regs = sdhci_uhs2_dump_regs,
+ .set_timeout = sdhci_uhs2_set_timeout,
+ .irq = sdhci_uhs2_irq,
+ .uhs2_pre_detect_init = sdhci_gli_pre_detect_init,
};
const struct sdhci_pci_fixes sdhci_gl9755 = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_BROKEN_DDR50,
.probe_slot = gli_probe_slot_gl9755,
+ .add_host = sdhci_pci_uhs2_add_host,
+ .remove_host = sdhci_pci_uhs2_remove_host,
.ops = &sdhci_gl9755_ops,
#ifdef CONFIG_PM_SLEEP
.resume = sdhci_pci_gli_resume,
@@ -1597,12 +2032,20 @@ static const struct sdhci_ops sdhci_gl9767_ops = {
.reset = sdhci_gl9767_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
.voltage_switch = sdhci_gl9767_voltage_switch,
+ .dump_uhs2_regs = sdhci_uhs2_dump_regs,
+ .set_timeout = sdhci_uhs2_set_timeout,
+ .irq = sdhci_uhs2_irq,
+ .set_power = sdhci_gl9767_set_power,
+ .uhs2_pre_detect_init = sdhci_gli_pre_detect_init,
+ .card_event = sdhci_gl9767_card_event,
};
const struct sdhci_pci_fixes sdhci_gl9767 = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_BROKEN_DDR50,
.probe_slot = gli_probe_slot_gl9767,
+ .add_host = sdhci_pci_uhs2_add_host,
+ .remove_host = sdhci_pci_uhs2_remove_host,
.ops = &sdhci_gl9767_ops,
#ifdef CONFIG_PM_SLEEP
.resume = sdhci_pci_gli_resume,
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 153704f812ed..e807c039a8b1 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -145,6 +145,7 @@ struct sdhci_pci_fixes {
int (*probe_slot) (struct sdhci_pci_slot *);
int (*add_host) (struct sdhci_pci_slot *);
void (*remove_slot) (struct sdhci_pci_slot *, int);
+ void (*remove_host) (struct sdhci_pci_slot *, int);
#ifdef CONFIG_PM_SLEEP
int (*suspend) (struct sdhci_pci_chip *);
@@ -189,6 +190,8 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot)
return (void *)slot->private;
}
+int sdhci_pci_uhs2_add_host(struct sdhci_pci_slot *slot);
+void sdhci_pci_uhs2_remove_host(struct sdhci_pci_slot *slot, int dead);
#ifdef CONFIG_PM_SLEEP
int sdhci_pci_resume_host(struct sdhci_pci_chip *chip);
#endif
diff --git a/drivers/mmc/host/sdhci-pic32.c b/drivers/mmc/host/sdhci-pic32.c
index 7a0351a9c74e..d6a299f49900 100644
--- a/drivers/mmc/host/sdhci-pic32.c
+++ b/drivers/mmc/host/sdhci-pic32.c
@@ -236,7 +236,7 @@ static struct platform_driver pic32_sdhci_driver = {
.of_match_table = of_match_ptr(pic32_sdhci_id_table),
},
.probe = pic32_sdhci_probe,
- .remove_new = pic32_sdhci_remove,
+ .remove = pic32_sdhci_remove,
};
module_platform_driver(pic32_sdhci_driver);
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 7b957f6d5588..45b6f0891c47 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -351,7 +351,7 @@ static struct platform_driver sdhci_pxav2_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_pxav2_probe,
- .remove_new = sdhci_pltfm_remove,
+ .remove = sdhci_pltfm_remove,
};
module_platform_driver(sdhci_pxav2_driver);
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index 3af43ac05825..990723a008ae 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -568,7 +568,7 @@ static struct platform_driver sdhci_pxav3_driver = {
.pm = &sdhci_pxav3_pmops,
},
.probe = sdhci_pxav3_probe,
- .remove_new = sdhci_pxav3_remove,
+ .remove = sdhci_pxav3_remove,
};
module_platform_driver(sdhci_pxav3_driver);
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index a71d56c7031f..bdf4dc0d6b77 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -774,7 +774,7 @@ MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
static struct platform_driver sdhci_s3c_driver = {
.probe = sdhci_s3c_probe,
- .remove_new = sdhci_s3c_remove,
+ .remove = sdhci_s3c_remove,
.id_table = sdhci_s3c_driver_ids,
.driver = {
.name = "s3c-sdhci",
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index c81bdfa97b89..770dc12b9ae9 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -182,7 +182,7 @@ static struct platform_driver sdhci_driver = {
.of_match_table = sdhci_spear_id_table,
},
.probe = sdhci_probe,
- .remove_new = sdhci_remove,
+ .remove = sdhci_remove,
};
module_platform_driver(sdhci_driver);
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
index 8776f4287119..db5e253b0f79 100644
--- a/drivers/mmc/host/sdhci-sprd.c
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -975,7 +975,7 @@ static const struct dev_pm_ops sdhci_sprd_pm_ops = {
static struct platform_driver sdhci_sprd_driver = {
.probe = sdhci_sprd_probe,
- .remove_new = sdhci_sprd_remove,
+ .remove = sdhci_sprd_remove,
.driver = {
.name = "sdhci_sprd_r11",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c
index d12532b96b51..4973e08a98f8 100644
--- a/drivers/mmc/host/sdhci-st.c
+++ b/drivers/mmc/host/sdhci-st.c
@@ -507,7 +507,7 @@ MODULE_DEVICE_TABLE(of, st_sdhci_match);
static struct platform_driver sdhci_st_driver = {
.probe = sdhci_st_probe,
- .remove_new = sdhci_st_remove,
+ .remove = sdhci_st_remove,
.driver = {
.name = "sdhci-st",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 1ad0a6b3a2eb..4d402b601883 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -1930,7 +1930,7 @@ static struct platform_driver sdhci_tegra_driver = {
.pm = &sdhci_tegra_dev_pm_ops,
},
.probe = sdhci_tegra_probe,
- .remove_new = sdhci_tegra_remove,
+ .remove = sdhci_tegra_remove,
};
module_platform_driver(sdhci_tegra_driver);
diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c
new file mode 100644
index 000000000000..c53b64d50c0d
--- /dev/null
+++ b/drivers/mmc/host/sdhci-uhs2.c
@@ -0,0 +1,1250 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/mmc/host/sdhci_uhs2.c - Secure Digital Host Controller
+ * Interface driver
+ *
+ * Copyright (C) 2014 Intel Corp, All Rights Reserved.
+ * Copyright (C) 2020 Genesys Logic, Inc.
+ * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw>
+ * Copyright (C) 2020 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/iopoll.h>
+#include <linux/bitfield.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+
+#include "sdhci.h"
+#include "sdhci-uhs2.h"
+
+#define DRIVER_NAME "sdhci_uhs2"
+#define DBG(f, x...) \
+ pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x)
+#define SDHCI_UHS2_DUMP(f, x...) \
+ pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x)
+
+#define UHS2_RESET_TIMEOUT_100MS 100000
+#define UHS2_CHECK_DORMANT_TIMEOUT_100MS 100000
+#define UHS2_INTERFACE_DETECT_TIMEOUT_100MS 100000
+#define UHS2_LANE_SYNC_TIMEOUT_150MS 150000
+
+#define UHS2_ARG_IOADR_MASK 0xfff
+
+void sdhci_uhs2_dump_regs(struct sdhci_host *host)
+{
+ if (!(mmc_card_uhs2(host->mmc)))
+ return;
+
+ SDHCI_UHS2_DUMP("==================== UHS2 ==================\n");
+ SDHCI_UHS2_DUMP("Blk Size: 0x%08x | Blk Cnt: 0x%08x\n",
+ sdhci_readw(host, SDHCI_UHS2_BLOCK_SIZE),
+ sdhci_readl(host, SDHCI_UHS2_BLOCK_COUNT));
+ SDHCI_UHS2_DUMP("Cmd: 0x%08x | Trn mode: 0x%08x\n",
+ sdhci_readw(host, SDHCI_UHS2_CMD),
+ sdhci_readw(host, SDHCI_UHS2_TRANS_MODE));
+ SDHCI_UHS2_DUMP("Int Stat: 0x%08x | Dev Sel : 0x%08x\n",
+ sdhci_readw(host, SDHCI_UHS2_DEV_INT_STATUS),
+ sdhci_readb(host, SDHCI_UHS2_DEV_SELECT));
+ SDHCI_UHS2_DUMP("Dev Int Code: 0x%08x\n",
+ sdhci_readb(host, SDHCI_UHS2_DEV_INT_CODE));
+ SDHCI_UHS2_DUMP("Reset: 0x%08x | Timer: 0x%08x\n",
+ sdhci_readw(host, SDHCI_UHS2_SW_RESET),
+ sdhci_readw(host, SDHCI_UHS2_TIMER_CTRL));
+ SDHCI_UHS2_DUMP("ErrInt: 0x%08x | ErrIntEn: 0x%08x\n",
+ sdhci_readl(host, SDHCI_UHS2_INT_STATUS),
+ sdhci_readl(host, SDHCI_UHS2_INT_STATUS_ENABLE));
+ SDHCI_UHS2_DUMP("ErrSigEn: 0x%08x\n",
+ sdhci_readl(host, SDHCI_UHS2_INT_SIGNAL_ENABLE));
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_dump_regs);
+
+/*****************************************************************************\
+ * *
+ * Low level functions *
+ * *
+\*****************************************************************************/
+
+static inline u16 uhs2_dev_cmd(struct mmc_command *cmd)
+{
+ return be16_to_cpu((__force __be16)cmd->uhs2_cmd->arg) & UHS2_ARG_IOADR_MASK;
+}
+
+static inline int mmc_opt_regulator_set_ocr(struct mmc_host *mmc,
+ struct regulator *supply,
+ unsigned short vdd_bit)
+{
+ return IS_ERR_OR_NULL(supply) ? 0 : mmc_regulator_set_ocr(mmc, supply, vdd_bit);
+}
+
+/**
+ * sdhci_uhs2_reset - invoke SW reset
+ * @host: SDHCI host
+ * @mask: Control mask
+ *
+ * Invoke SW reset, depending on a bit in @mask and wait for completion.
+ */
+void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask)
+{
+ u32 val;
+
+ sdhci_writew(host, mask, SDHCI_UHS2_SW_RESET);
+
+ if (mask & SDHCI_UHS2_SW_RESET_FULL)
+ host->clock = 0;
+
+ /* hw clears the bit when it's done */
+ if (read_poll_timeout_atomic(sdhci_readw, val, !(val & mask), 10,
+ UHS2_RESET_TIMEOUT_100MS, true, host, SDHCI_UHS2_SW_RESET)) {
+ pr_warn("%s: %s: Reset 0x%x never completed. %s: clean reset bit.\n", __func__,
+ mmc_hostname(host->mmc), (int)mask, mmc_hostname(host->mmc));
+ sdhci_writeb(host, 0, SDHCI_UHS2_SW_RESET);
+ return;
+ }
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_reset);
+
+static void sdhci_uhs2_reset_cmd_data(struct sdhci_host *host)
+{
+ sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
+ if (host->mmc->uhs2_sd_tran) {
+ sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD);
+
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, SDHCI_UHS2_INT_ERROR_MASK);
+ }
+}
+
+void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd)
+{
+ struct mmc_host *mmc = host->mmc;
+ u8 pwr = 0;
+
+ if (mode != MMC_POWER_OFF) {
+ pwr = sdhci_get_vdd_value(vdd);
+ if (!pwr)
+ WARN(1, "%s: Invalid vdd %#x\n",
+ mmc_hostname(host->mmc), vdd);
+ pwr |= SDHCI_VDD2_POWER_180;
+ }
+
+ if (host->pwr == pwr)
+ return;
+ host->pwr = pwr;
+
+ if (pwr == 0) {
+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+
+ mmc_opt_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+ mmc_regulator_set_vqmmc2(mmc, &mmc->ios);
+ } else {
+ mmc_opt_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+ /* support 1.8v only for now */
+ mmc_regulator_set_vqmmc2(mmc, &mmc->ios);
+
+ /* Clear the power reg before setting a new value */
+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+
+ /* vdd first */
+ pwr |= SDHCI_POWER_ON;
+ sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL);
+ mdelay(5);
+
+ pwr |= SDHCI_VDD2_POWER_ON;
+ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ mdelay(5);
+ }
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_set_power);
+
+static u8 sdhci_calc_timeout_uhs2(struct sdhci_host *host, u8 *cmd_res, u8 *dead_lock)
+{
+ /* timeout in us */
+ unsigned int dead_lock_timeout = 1 * 1000 * 1000;
+ unsigned int cmd_res_timeout = 5 * 1000;
+ unsigned int current_timeout;
+ u8 count;
+
+ /*
+ * Figure out needed cycles.
+ * We do this in steps in order to fit inside a 32 bit int.
+ * The first step is the minimum timeout, which will have a
+ * minimum resolution of 6 bits:
+ * (1) 2^13*1000 > 2^22,
+ * (2) host->timeout_clk < 2^16
+ * =>
+ * (1) / (2) > 2^6
+ */
+ count = 0;
+ current_timeout = (1 << 13) * 1000 / host->timeout_clk;
+ while (current_timeout < cmd_res_timeout) {
+ count++;
+ current_timeout <<= 1;
+ if (count >= 0xF)
+ break;
+ }
+
+ if (count >= 0xF) {
+ DBG("%s: Too large timeout 0x%x requested for CMD_RES!\n",
+ mmc_hostname(host->mmc), count);
+ count = 0xE;
+ }
+ *cmd_res = count;
+
+ count = 0;
+ current_timeout = (1 << 13) * 1000 / host->timeout_clk;
+ while (current_timeout < dead_lock_timeout) {
+ count++;
+ current_timeout <<= 1;
+ if (count >= 0xF)
+ break;
+ }
+
+ if (count >= 0xF) {
+ DBG("%s: Too large timeout 0x%x requested for DEADLOCK!\n",
+ mmc_hostname(host->mmc), count);
+ count = 0xE;
+ }
+ *dead_lock = count;
+
+ return count;
+}
+
+static void __sdhci_uhs2_set_timeout(struct sdhci_host *host)
+{
+ u8 cmd_res, dead_lock;
+
+ sdhci_calc_timeout_uhs2(host, &cmd_res, &dead_lock);
+ cmd_res |= FIELD_PREP(SDHCI_UHS2_TIMER_CTRL_DEADLOCK_MASK, dead_lock);
+ sdhci_writeb(host, cmd_res, SDHCI_UHS2_TIMER_CTRL);
+}
+
+void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+{
+ __sdhci_set_timeout(host, cmd);
+
+ if (mmc_card_uhs2(host->mmc))
+ __sdhci_uhs2_set_timeout(host);
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_set_timeout);
+
+/**
+ * sdhci_uhs2_clear_set_irqs - set Error Interrupt Status Enable register
+ * @host: SDHCI host
+ * @clear: bit-wise clear mask
+ * @set: bit-wise set mask
+ *
+ * Set/unset bits in UHS-II Error Interrupt Status Enable register
+ */
+void sdhci_uhs2_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
+{
+ u32 ier;
+
+ ier = sdhci_readl(host, SDHCI_UHS2_INT_STATUS_ENABLE);
+ ier &= ~clear;
+ ier |= set;
+ sdhci_writel(host, ier, SDHCI_UHS2_INT_STATUS_ENABLE);
+ sdhci_writel(host, ier, SDHCI_UHS2_INT_SIGNAL_ENABLE);
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_clear_set_irqs);
+
+static void __sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u8 cmd_res, dead_lock;
+ u16 ctrl_2;
+
+ /* UHS2 Timeout Control */
+ sdhci_calc_timeout_uhs2(host, &cmd_res, &dead_lock);
+
+ /* change to use calculate value */
+ cmd_res |= FIELD_PREP(SDHCI_UHS2_TIMER_CTRL_DEADLOCK_MASK, dead_lock);
+
+ sdhci_uhs2_clear_set_irqs(host,
+ SDHCI_UHS2_INT_CMD_TIMEOUT |
+ SDHCI_UHS2_INT_DEADLOCK_TIMEOUT,
+ 0);
+ sdhci_writeb(host, cmd_res, SDHCI_UHS2_TIMER_CTRL);
+ sdhci_uhs2_clear_set_irqs(host, 0,
+ SDHCI_UHS2_INT_CMD_TIMEOUT |
+ SDHCI_UHS2_INT_DEADLOCK_TIMEOUT);
+
+ /* UHS2 timing. Note, UHS2 timing is disabled when powering off */
+ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ if (ios->power_mode != MMC_POWER_OFF &&
+ (ios->timing == MMC_TIMING_UHS2_SPEED_A ||
+ ios->timing == MMC_TIMING_UHS2_SPEED_A_HD ||
+ ios->timing == MMC_TIMING_UHS2_SPEED_B ||
+ ios->timing == MMC_TIMING_UHS2_SPEED_B_HD))
+ ctrl_2 |= SDHCI_CTRL_UHS2 | SDHCI_CTRL_UHS2_ENABLE;
+ else
+ ctrl_2 &= ~(SDHCI_CTRL_UHS2 | SDHCI_CTRL_UHS2_ENABLE);
+ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+ host->timing = ios->timing;
+
+ if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
+ sdhci_enable_preset_value(host, true);
+
+ if (host->ops->set_power)
+ host->ops->set_power(host, ios->power_mode, ios->vdd);
+ else
+ sdhci_uhs2_set_power(host, ios->power_mode, ios->vdd);
+
+ sdhci_set_clock(host, host->clock);
+}
+
+static int sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ pr_debug("%s: clock %uHz powermode %u Vdd %u timing %u\n",
+ mmc_hostname(mmc), ios->clock, ios->power_mode, ios->vdd, ios->timing);
+
+ if (!mmc_card_uhs2(mmc)) {
+ sdhci_set_ios(mmc, ios);
+ return 0;
+ }
+
+ if (ios->power_mode == MMC_POWER_UNDEFINED)
+ return 0;
+
+ if (host->flags & SDHCI_DEVICE_DEAD) {
+ if (ios->power_mode == MMC_POWER_OFF) {
+ mmc_opt_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+ mmc_regulator_set_vqmmc2(mmc, ios);
+ }
+ return -1;
+ }
+
+ sdhci_set_ios_common(mmc, ios);
+
+ __sdhci_uhs2_set_ios(mmc, ios);
+
+ return 0;
+}
+
+static int sdhci_uhs2_interface_detect(struct sdhci_host *host)
+{
+ u32 val;
+
+ if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_IF_DETECT),
+ 100, UHS2_INTERFACE_DETECT_TIMEOUT_100MS, true,
+ host, SDHCI_PRESENT_STATE)) {
+ pr_warn("%s: not detect UHS2 interface in 100ms.\n", mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ return -EIO;
+ }
+
+ /* Enable UHS2 error interrupts */
+ sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, SDHCI_UHS2_INT_ERROR_MASK);
+
+ if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_LANE_SYNC),
+ 100, UHS2_LANE_SYNC_TIMEOUT_150MS, true, host, SDHCI_PRESENT_STATE)) {
+ pr_warn("%s: UHS2 Lane sync fail in 150ms.\n", mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ return -EIO;
+ }
+
+ DBG("%s: UHS2 Lane synchronized in UHS2 mode, PHY is initialized.\n",
+ mmc_hostname(host->mmc));
+ return 0;
+}
+
+static int sdhci_uhs2_init(struct sdhci_host *host)
+{
+ u16 caps_ptr = 0;
+ u32 caps_gen = 0;
+ u32 caps_phy = 0;
+ u32 caps_tran[2] = {0, 0};
+ struct mmc_host *mmc = host->mmc;
+
+ caps_ptr = sdhci_readw(host, SDHCI_UHS2_CAPS_PTR);
+ if (caps_ptr < 0x100 || caps_ptr > 0x1FF) {
+ pr_err("%s: SDHCI_UHS2_CAPS_PTR(%d) is wrong.\n",
+ mmc_hostname(mmc), caps_ptr);
+ return -ENODEV;
+ }
+ caps_gen = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_OFFSET);
+ caps_phy = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_PHY_OFFSET);
+ caps_tran[0] = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_TRAN_OFFSET);
+ caps_tran[1] = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_TRAN_1_OFFSET);
+
+ /* General Caps */
+ mmc->uhs2_caps.dap = caps_gen & SDHCI_UHS2_CAPS_DAP_MASK;
+ mmc->uhs2_caps.gap = FIELD_GET(SDHCI_UHS2_CAPS_GAP_MASK, caps_gen);
+ mmc->uhs2_caps.n_lanes = FIELD_GET(SDHCI_UHS2_CAPS_LANE_MASK, caps_gen);
+ mmc->uhs2_caps.addr64 = (caps_gen & SDHCI_UHS2_CAPS_ADDR_64) ? 1 : 0;
+ mmc->uhs2_caps.card_type = FIELD_GET(SDHCI_UHS2_CAPS_DEV_TYPE_MASK, caps_gen);
+
+ /* PHY Caps */
+ mmc->uhs2_caps.phy_rev = caps_phy & SDHCI_UHS2_CAPS_PHY_REV_MASK;
+ mmc->uhs2_caps.speed_range = FIELD_GET(SDHCI_UHS2_CAPS_PHY_RANGE_MASK, caps_phy);
+ mmc->uhs2_caps.n_lss_sync = FIELD_GET(SDHCI_UHS2_CAPS_PHY_N_LSS_SYN_MASK, caps_phy);
+ mmc->uhs2_caps.n_lss_dir = FIELD_GET(SDHCI_UHS2_CAPS_PHY_N_LSS_DIR_MASK, caps_phy);
+ if (mmc->uhs2_caps.n_lss_sync == 0)
+ mmc->uhs2_caps.n_lss_sync = 16 << 2;
+ else
+ mmc->uhs2_caps.n_lss_sync <<= 2;
+ if (mmc->uhs2_caps.n_lss_dir == 0)
+ mmc->uhs2_caps.n_lss_dir = 16 << 3;
+ else
+ mmc->uhs2_caps.n_lss_dir <<= 3;
+
+ /* LINK/TRAN Caps */
+ mmc->uhs2_caps.link_rev = caps_tran[0] & SDHCI_UHS2_CAPS_TRAN_LINK_REV_MASK;
+ mmc->uhs2_caps.n_fcu = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_N_FCU_MASK, caps_tran[0]);
+ if (mmc->uhs2_caps.n_fcu == 0)
+ mmc->uhs2_caps.n_fcu = 256;
+ mmc->uhs2_caps.host_type = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_HOST_TYPE_MASK, caps_tran[0]);
+ mmc->uhs2_caps.maxblk_len = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_BLK_LEN_MASK, caps_tran[0]);
+ mmc->uhs2_caps.n_data_gap = caps_tran[1] & SDHCI_UHS2_CAPS_TRAN_1_N_DATA_GAP_MASK;
+
+ return 0;
+}
+
+static int sdhci_uhs2_do_detect_init(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ DBG("Begin do uhs2 detect init.\n");
+
+ if (host->ops->uhs2_pre_detect_init)
+ host->ops->uhs2_pre_detect_init(host);
+
+ if (sdhci_uhs2_interface_detect(host)) {
+ pr_warn("%s: cannot detect UHS2 interface.\n", mmc_hostname(host->mmc));
+ return -EIO;
+ }
+
+ if (sdhci_uhs2_init(host)) {
+ pr_warn("%s: UHS2 init fail.\n", mmc_hostname(host->mmc));
+ return -EIO;
+ }
+
+ /* Init complete, do soft reset and enable UHS2 error irqs. */
+ sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD);
+ sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, SDHCI_UHS2_INT_ERROR_MASK);
+ /*
+ * N.B SDHCI_INT_ENABLE and SDHCI_SIGNAL_ENABLE was cleared
+ * by SDHCI_UHS2_SW_RESET_SD
+ */
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+
+ return 0;
+}
+
+static int sdhci_uhs2_disable_clk(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+
+ clk &= ~SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+ return 0;
+}
+
+static int sdhci_uhs2_enable_clk(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ int timeout_us = 20000; /* 20ms */
+ u32 val;
+
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+ if (read_poll_timeout(sdhci_readw, val, (val & SDHCI_CLOCK_INT_STABLE),
+ 10, timeout_us, true, host, SDHCI_CLOCK_CONTROL)) {
+ pr_err("%s: Internal clock never stabilised.\n", mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ return -EIO;
+ }
+ return 0;
+}
+
+static void sdhci_uhs2_set_config(struct sdhci_host *host)
+{
+ u32 value;
+ u16 sdhci_uhs2_set_ptr = sdhci_readw(host, SDHCI_UHS2_SETTINGS_PTR);
+ u16 sdhci_uhs2_gen_set_reg = sdhci_uhs2_set_ptr;
+ u16 sdhci_uhs2_phy_set_reg = sdhci_uhs2_set_ptr + 4;
+ u16 sdhci_uhs2_tran_set_reg = sdhci_uhs2_set_ptr + 8;
+ u16 sdhci_uhs2_tran_set_1_reg = sdhci_uhs2_set_ptr + 12;
+
+ /* Set Gen Settings */
+ value = FIELD_PREP(SDHCI_UHS2_GEN_SETTINGS_N_LANES_MASK, host->mmc->uhs2_caps.n_lanes_set);
+ sdhci_writel(host, value, sdhci_uhs2_gen_set_reg);
+
+ /* Set PHY Settings */
+ value = FIELD_PREP(SDHCI_UHS2_PHY_N_LSS_DIR_MASK, host->mmc->uhs2_caps.n_lss_dir_set) |
+ FIELD_PREP(SDHCI_UHS2_PHY_N_LSS_SYN_MASK, host->mmc->uhs2_caps.n_lss_sync_set);
+ if (host->mmc->ios.timing == MMC_TIMING_UHS2_SPEED_B ||
+ host->mmc->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD)
+ value |= SDHCI_UHS2_PHY_SET_SPEED_B;
+ sdhci_writel(host, value, sdhci_uhs2_phy_set_reg);
+
+ /* Set LINK-TRAN Settings */
+ value = FIELD_PREP(SDHCI_UHS2_TRAN_RETRY_CNT_MASK, host->mmc->uhs2_caps.max_retry_set) |
+ FIELD_PREP(SDHCI_UHS2_TRAN_N_FCU_MASK, host->mmc->uhs2_caps.n_fcu_set);
+ sdhci_writel(host, value, sdhci_uhs2_tran_set_reg);
+ sdhci_writel(host, host->mmc->uhs2_caps.n_data_gap_set, sdhci_uhs2_tran_set_1_reg);
+}
+
+static int sdhci_uhs2_check_dormant(struct sdhci_host *host)
+{
+ u32 val;
+
+ if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_IN_DORMANT_STATE),
+ 100, UHS2_CHECK_DORMANT_TIMEOUT_100MS, true, host,
+ SDHCI_PRESENT_STATE)) {
+ pr_warn("%s: UHS2 IN_DORMANT fail in 100ms.\n", mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int sdhci_uhs2_control(struct mmc_host *mmc, enum sd_uhs2_operation op)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct mmc_ios *ios = &mmc->ios;
+ int err = 0;
+
+ DBG("Begin uhs2 control, act %d.\n", op);
+
+ switch (op) {
+ case UHS2_PHY_INIT:
+ err = sdhci_uhs2_do_detect_init(mmc);
+ break;
+ case UHS2_SET_CONFIG:
+ sdhci_uhs2_set_config(host);
+ break;
+ case UHS2_ENABLE_INT:
+ sdhci_uhs2_clear_set_irqs(host, 0, SDHCI_INT_CARD_INT);
+ break;
+ case UHS2_DISABLE_INT:
+ sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_CARD_INT, 0);
+ break;
+ case UHS2_CHECK_DORMANT:
+ err = sdhci_uhs2_check_dormant(host);
+ break;
+ case UHS2_DISABLE_CLK:
+ err = sdhci_uhs2_disable_clk(mmc);
+ break;
+ case UHS2_ENABLE_CLK:
+ err = sdhci_uhs2_enable_clk(mmc);
+ break;
+ case UHS2_SET_IOS:
+ err = sdhci_uhs2_set_ios(mmc, ios);
+ break;
+ default:
+ pr_err("%s: input sd uhs2 operation %d is wrong!\n",
+ mmc_hostname(host->mmc), op);
+ err = -EIO;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************\
+ * *
+ * Core functions *
+ * *
+\*****************************************************************************/
+
+static void sdhci_uhs2_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+{
+ struct mmc_data *data = cmd->data;
+
+ sdhci_initialize_data(host, data);
+
+ sdhci_prepare_dma(host, data);
+
+ sdhci_writew(host, data->blksz, SDHCI_UHS2_BLOCK_SIZE);
+ sdhci_writew(host, data->blocks, SDHCI_UHS2_BLOCK_COUNT);
+}
+
+static void sdhci_uhs2_finish_data(struct sdhci_host *host)
+{
+ struct mmc_data *data = host->data;
+
+ __sdhci_finish_data_common(host, true);
+
+ __sdhci_finish_mrq(host, data->mrq);
+}
+
+static void sdhci_uhs2_set_transfer_mode(struct sdhci_host *host, struct mmc_command *cmd)
+{
+ u16 mode;
+ struct mmc_data *data = cmd->data;
+
+ if (!data) {
+ /* clear Auto CMD settings for no data CMDs */
+ if (uhs2_dev_cmd(cmd) == UHS2_DEV_CMD_TRANS_ABORT) {
+ mode = 0;
+ } else {
+ mode = sdhci_readw(host, SDHCI_UHS2_TRANS_MODE);
+ if (cmd->opcode == MMC_STOP_TRANSMISSION || cmd->opcode == MMC_ERASE)
+ mode |= SDHCI_UHS2_TRNS_WAIT_EBSY;
+ else
+ /* send status mode */
+ if (cmd->opcode == MMC_SEND_STATUS)
+ mode = 0;
+ }
+
+ DBG("UHS2 no data trans mode is 0x%x.\n", mode);
+
+ sdhci_writew(host, mode, SDHCI_UHS2_TRANS_MODE);
+ return;
+ }
+
+ WARN_ON(!host->data);
+
+ mode = SDHCI_UHS2_TRNS_BLK_CNT_EN | SDHCI_UHS2_TRNS_WAIT_EBSY;
+ if (data->flags & MMC_DATA_WRITE)
+ mode |= SDHCI_UHS2_TRNS_DATA_TRNS_WRT;
+
+ if (data->blocks == 1 &&
+ data->blksz != 512 &&
+ cmd->opcode != MMC_READ_SINGLE_BLOCK &&
+ cmd->opcode != MMC_WRITE_BLOCK) {
+ mode &= ~SDHCI_UHS2_TRNS_BLK_CNT_EN;
+ mode |= SDHCI_UHS2_TRNS_BLK_BYTE_MODE;
+ }
+
+ if (host->flags & SDHCI_REQ_USE_DMA)
+ mode |= SDHCI_UHS2_TRNS_DMA;
+
+ if (cmd->uhs2_cmd->tmode_half_duplex)
+ mode |= SDHCI_UHS2_TRNS_2L_HD;
+
+ sdhci_writew(host, mode, SDHCI_UHS2_TRANS_MODE);
+
+ DBG("UHS2 trans mode is 0x%x.\n", mode);
+}
+
+static void __sdhci_uhs2_send_command(struct sdhci_host *host, struct mmc_command *cmd)
+{
+ int i, j;
+ int cmd_reg;
+
+ i = 0;
+ sdhci_writel(host,
+ ((u32)cmd->uhs2_cmd->arg << 16) |
+ (u32)cmd->uhs2_cmd->header,
+ SDHCI_UHS2_CMD_PACKET + i);
+ i += 4;
+
+ /*
+ * Per spec, payload (config) should be MSB before sending out.
+ * But we don't need convert here because had set payload as
+ * MSB when preparing config read/write commands.
+ */
+ for (j = 0; j < cmd->uhs2_cmd->payload_len / sizeof(u32); j++) {
+ sdhci_writel(host, *(__force u32 *)(cmd->uhs2_cmd->payload + j),
+ SDHCI_UHS2_CMD_PACKET + i);
+ i += 4;
+ }
+
+ for ( ; i < SDHCI_UHS2_CMD_PACK_MAX_LEN; i += 4)
+ sdhci_writel(host, 0, SDHCI_UHS2_CMD_PACKET + i);
+
+ DBG("UHS2 CMD packet_len = %d.\n", cmd->uhs2_cmd->packet_len);
+ for (i = 0; i < cmd->uhs2_cmd->packet_len; i++)
+ DBG("UHS2 CMD_PACKET[%d] = 0x%x.\n", i,
+ sdhci_readb(host, SDHCI_UHS2_CMD_PACKET + i));
+
+ cmd_reg = FIELD_PREP(SDHCI_UHS2_CMD_PACK_LEN_MASK, cmd->uhs2_cmd->packet_len);
+ if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC)
+ cmd_reg |= SDHCI_UHS2_CMD_DATA;
+ if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ cmd_reg |= SDHCI_UHS2_CMD_CMD12;
+
+ /* UHS2 Native ABORT */
+ if ((cmd->uhs2_cmd->header & UHS2_NATIVE_PACKET) &&
+ (uhs2_dev_cmd(cmd) == UHS2_DEV_CMD_TRANS_ABORT))
+ cmd_reg |= SDHCI_UHS2_CMD_TRNS_ABORT;
+
+ /* UHS2 Native DORMANT */
+ if ((cmd->uhs2_cmd->header & UHS2_NATIVE_PACKET) &&
+ (uhs2_dev_cmd(cmd) == UHS2_DEV_CMD_GO_DORMANT_STATE))
+ cmd_reg |= SDHCI_UHS2_CMD_DORMANT;
+
+ DBG("0x%x is set to UHS2 CMD register.\n", cmd_reg);
+
+ sdhci_writew(host, cmd_reg, SDHCI_UHS2_CMD);
+}
+
+static bool sdhci_uhs2_send_command(struct sdhci_host *host, struct mmc_command *cmd)
+{
+ u32 mask;
+ unsigned long timeout;
+
+ WARN_ON(host->cmd);
+
+ /* Initially, a command has no error */
+ cmd->error = 0;
+
+ if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ cmd->flags |= MMC_RSP_BUSY;
+
+ mask = SDHCI_CMD_INHIBIT;
+
+ if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)
+ return false;
+
+ host->cmd = cmd;
+ host->data_timeout = 0;
+ if (sdhci_data_line_cmd(cmd)) {
+ WARN_ON(host->data_cmd);
+ host->data_cmd = cmd;
+ __sdhci_uhs2_set_timeout(host);
+ }
+
+ if (cmd->data)
+ sdhci_uhs2_prepare_data(host, cmd);
+
+ sdhci_uhs2_set_transfer_mode(host, cmd);
+
+ timeout = jiffies;
+ if (host->data_timeout)
+ timeout += nsecs_to_jiffies(host->data_timeout);
+ else if (!cmd->data && cmd->busy_timeout > 9000)
+ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
+ else
+ timeout += 10 * HZ;
+ sdhci_mod_timer(host, cmd->mrq, timeout);
+
+ __sdhci_uhs2_send_command(host, cmd);
+
+ return true;
+}
+
+static bool sdhci_uhs2_send_command_retry(struct sdhci_host *host,
+ struct mmc_command *cmd,
+ unsigned long flags)
+ __releases(host->lock)
+ __acquires(host->lock)
+{
+ struct mmc_command *deferred_cmd = host->deferred_cmd;
+ int timeout = 10; /* Approx. 10 ms */
+ bool present;
+
+ while (!sdhci_uhs2_send_command(host, cmd)) {
+ if (!timeout--) {
+ pr_err("%s: Controller never released inhibit bit(s).\n",
+ mmc_hostname(host->mmc));
+ sdhci_dumpregs(host);
+ cmd->error = -EIO;
+ return false;
+ }
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ usleep_range(1000, 1250);
+
+ present = host->mmc->ops->get_cd(host->mmc);
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ /* A deferred command might disappear, handle that */
+ if (cmd == deferred_cmd && cmd != host->deferred_cmd)
+ return true;
+
+ if (sdhci_present_error(host, cmd, present))
+ return false;
+ }
+
+ if (cmd == host->deferred_cmd)
+ host->deferred_cmd = NULL;
+
+ return true;
+}
+
+static void __sdhci_uhs2_finish_command(struct sdhci_host *host)
+{
+ struct mmc_command *cmd = host->cmd;
+ u8 resp;
+ u8 error_code;
+ bool breada0 = 0;
+ int i;
+
+ if (host->mmc->uhs2_sd_tran) {
+ resp = sdhci_readb(host, SDHCI_UHS2_RESPONSE + 2);
+ if (resp & UHS2_RES_NACK_MASK) {
+ error_code = (resp >> UHS2_RES_ECODE_POS) & UHS2_RES_ECODE_MASK;
+ pr_err("%s: NACK response, ECODE=0x%x.\n",
+ mmc_hostname(host->mmc), error_code);
+ }
+ breada0 = 1;
+ }
+
+ if (cmd->uhs2_cmd->uhs2_resp_len) {
+ int len = min_t(int, cmd->uhs2_cmd->uhs2_resp_len, UHS2_MAX_RESP_LEN);
+
+ /* Get whole response of some native CCMD, like
+ * DEVICE_INIT, ENUMERATE.
+ */
+ for (i = 0; i < len; i++)
+ cmd->uhs2_cmd->uhs2_resp[i] = sdhci_readb(host, SDHCI_UHS2_RESPONSE + i);
+ } else {
+ /* Get SD CMD response and Payload for some read
+ * CCMD, like INQUIRY_CFG.
+ */
+ /* Per spec (p136), payload field is divided into
+ * a unit of DWORD and transmission order within
+ * a DWORD is big endian.
+ */
+ if (!breada0)
+ sdhci_readl(host, SDHCI_UHS2_RESPONSE);
+ for (i = 4; i < 20; i += 4) {
+ cmd->resp[i / 4 - 1] =
+ (sdhci_readb(host,
+ SDHCI_UHS2_RESPONSE + i) << 24) |
+ (sdhci_readb(host,
+ SDHCI_UHS2_RESPONSE + i + 1)
+ << 16) |
+ (sdhci_readb(host,
+ SDHCI_UHS2_RESPONSE + i + 2)
+ << 8) |
+ sdhci_readb(host, SDHCI_UHS2_RESPONSE + i + 3);
+ }
+ }
+}
+
+static void sdhci_uhs2_finish_command(struct sdhci_host *host)
+{
+ struct mmc_command *cmd = host->cmd;
+
+ __sdhci_uhs2_finish_command(host);
+
+ host->cmd = NULL;
+
+ if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd)
+ mmc_command_done(host->mmc, cmd->mrq);
+
+ /*
+ * The host can send and interrupt when the busy state has
+ * ended, allowing us to wait without wasting CPU cycles.
+ * The busy signal uses DAT0 so this is similar to waiting
+ * for data to complete.
+ *
+ * Note: The 1.0 specification is a bit ambiguous about this
+ * feature so there might be some problems with older
+ * controllers.
+ */
+ if (cmd->flags & MMC_RSP_BUSY) {
+ if (cmd->data) {
+ DBG("Cannot wait for busy signal when also doing a data transfer");
+ } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+ cmd == host->data_cmd) {
+ /* Command complete before busy is ended */
+ return;
+ }
+ }
+
+ /* Processed actual command. */
+ if (host->data && host->data_early)
+ sdhci_uhs2_finish_data(host);
+
+ if (!cmd->data)
+ __sdhci_finish_mrq(host, cmd->mrq);
+}
+
+static void sdhci_uhs2_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct mmc_command *cmd;
+ unsigned long flags;
+ bool present;
+
+ if (!(mmc_card_uhs2(mmc))) {
+ sdhci_request(mmc, mrq);
+ return;
+ }
+
+ mrq->stop = NULL;
+ mrq->sbc = NULL;
+ if (mrq->data)
+ mrq->data->stop = NULL;
+
+ /* Firstly check card presence */
+ present = mmc->ops->get_cd(mmc);
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ if (sdhci_present_error(host, mrq->cmd, present))
+ goto out_finish;
+
+ cmd = mrq->cmd;
+
+ if (!sdhci_uhs2_send_command_retry(host, cmd, flags))
+ goto out_finish;
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return;
+
+out_finish:
+ sdhci_finish_mrq(host, mrq);
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*****************************************************************************\
+ * *
+ * Request done *
+ * *
+\*****************************************************************************/
+
+static bool sdhci_uhs2_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)
+{
+ return sdhci_needs_reset(host, mrq) ||
+ (!(host->flags & SDHCI_DEVICE_DEAD) && mrq->data && mrq->data->error);
+}
+
+static bool sdhci_uhs2_request_done(struct sdhci_host *host)
+{
+ unsigned long flags;
+ struct mmc_request *mrq;
+ int i;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ for (i = 0; i < SDHCI_MAX_MRQS; i++) {
+ mrq = host->mrqs_done[i];
+ if (mrq)
+ break;
+ }
+
+ if (!mrq) {
+ spin_unlock_irqrestore(&host->lock, flags);
+ return true;
+ }
+
+ /*
+ * Always unmap the data buffers if they were mapped by
+ * sdhci_prepare_data() whenever we finish with a request.
+ * This avoids leaking DMA mappings on error.
+ */
+ if (host->flags & SDHCI_REQ_USE_DMA)
+ sdhci_request_done_dma(host, mrq);
+
+ /*
+ * The controller needs a reset of internal state machines
+ * upon error conditions.
+ */
+ if (sdhci_uhs2_needs_reset(host, mrq)) {
+ /*
+ * Do not finish until command and data lines are available for
+ * reset. Note there can only be one other mrq, so it cannot
+ * also be in mrqs_done, otherwise host->cmd and host->data_cmd
+ * would both be null.
+ */
+ if (host->cmd || host->data_cmd) {
+ spin_unlock_irqrestore(&host->lock, flags);
+ return true;
+ }
+
+ if (mrq->cmd->error || mrq->data->error)
+ sdhci_uhs2_reset_cmd_data(host);
+ else
+ sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD);
+ host->pending_reset = false;
+ }
+
+ host->mrqs_done[i] = NULL;
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ if (host->ops->request_done)
+ host->ops->request_done(host, mrq);
+ else
+ mmc_request_done(host->mmc, mrq);
+
+ return false;
+}
+
+static void sdhci_uhs2_complete_work(struct work_struct *work)
+{
+ struct sdhci_host *host = container_of(work, struct sdhci_host,
+ complete_work);
+
+ if (!mmc_card_uhs2(host->mmc)) {
+ sdhci_complete_work(work);
+ return;
+ }
+
+ while (!sdhci_uhs2_request_done(host))
+ ;
+}
+
+/*****************************************************************************\
+ * *
+ * Interrupt handling *
+ * *
+\*****************************************************************************/
+
+static void __sdhci_uhs2_irq(struct sdhci_host *host, u32 uhs2mask)
+{
+ struct mmc_command *cmd = host->cmd;
+
+ DBG("*** %s got UHS2 error interrupt: 0x%08x\n",
+ mmc_hostname(host->mmc), uhs2mask);
+
+ if (uhs2mask & SDHCI_UHS2_INT_CMD_ERR_MASK) {
+ if (!host->cmd) {
+ pr_err("%s: Got cmd interrupt 0x%08x but no cmd.\n",
+ mmc_hostname(host->mmc),
+ (unsigned int)uhs2mask);
+ sdhci_dumpregs(host);
+ return;
+ }
+ host->cmd->error = -EILSEQ;
+ if (uhs2mask & SDHCI_UHS2_INT_CMD_TIMEOUT)
+ host->cmd->error = -ETIMEDOUT;
+ }
+
+ if (uhs2mask & SDHCI_UHS2_INT_DATA_ERR_MASK) {
+ if (!host->data) {
+ pr_err("%s: Got data interrupt 0x%08x but no data.\n",
+ mmc_hostname(host->mmc),
+ (unsigned int)uhs2mask);
+ sdhci_dumpregs(host);
+ return;
+ }
+
+ if (uhs2mask & SDHCI_UHS2_INT_DEADLOCK_TIMEOUT) {
+ pr_err("%s: Got deadlock timeout interrupt 0x%08x\n",
+ mmc_hostname(host->mmc),
+ (unsigned int)uhs2mask);
+ host->data->error = -ETIMEDOUT;
+ } else if (uhs2mask & SDHCI_UHS2_INT_ADMA_ERROR) {
+ pr_err("%s: ADMA error = 0x %x\n",
+ mmc_hostname(host->mmc),
+ sdhci_readb(host, SDHCI_ADMA_ERROR));
+ host->data->error = -EIO;
+ } else {
+ host->data->error = -EILSEQ;
+ }
+ }
+
+ if (host->data && host->data->error)
+ sdhci_uhs2_finish_data(host);
+ else
+ sdhci_finish_mrq(host, cmd->mrq);
+
+}
+
+u32 sdhci_uhs2_irq(struct sdhci_host *host, u32 intmask)
+{
+ u32 mask = intmask, uhs2mask;
+
+ if (!mmc_card_uhs2(host->mmc))
+ goto out;
+
+ if (intmask & SDHCI_INT_ERROR) {
+ uhs2mask = sdhci_readl(host, SDHCI_UHS2_INT_STATUS);
+ if (!(uhs2mask & SDHCI_UHS2_INT_ERROR_MASK))
+ goto cmd_irq;
+
+ /* Clear error interrupts */
+ sdhci_writel(host, uhs2mask & SDHCI_UHS2_INT_ERROR_MASK,
+ SDHCI_UHS2_INT_STATUS);
+
+ /* Handle error interrupts */
+ __sdhci_uhs2_irq(host, uhs2mask);
+
+ /* Caller, sdhci_irq(), doesn't have to care about UHS-2 errors */
+ intmask &= ~SDHCI_INT_ERROR;
+ mask &= SDHCI_INT_ERROR;
+ }
+
+cmd_irq:
+ if (intmask & SDHCI_INT_CMD_MASK) {
+ /* Clear command interrupt */
+ sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS);
+
+ /* Handle command interrupt */
+ if (intmask & SDHCI_INT_RESPONSE)
+ sdhci_uhs2_finish_command(host);
+
+ /* Caller, sdhci_irq(), doesn't have to care about UHS-2 commands */
+ intmask &= ~SDHCI_INT_CMD_MASK;
+ mask &= SDHCI_INT_CMD_MASK;
+ }
+
+ /* Clear already-handled interrupts. */
+ sdhci_writel(host, mask, SDHCI_INT_STATUS);
+
+out:
+ return intmask;
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_irq);
+
+static irqreturn_t sdhci_uhs2_thread_irq(int irq, void *dev_id)
+{
+ struct sdhci_host *host = dev_id;
+ struct mmc_command *cmd;
+ unsigned long flags;
+ u32 isr;
+
+ if (!mmc_card_uhs2(host->mmc))
+ return sdhci_thread_irq(irq, dev_id);
+
+ while (!sdhci_uhs2_request_done(host))
+ ;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ isr = host->thread_isr;
+ host->thread_isr = 0;
+
+ cmd = host->deferred_cmd;
+ if (cmd && !sdhci_uhs2_send_command_retry(host, cmd, flags))
+ sdhci_finish_mrq(host, cmd->mrq);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+ struct mmc_host *mmc = host->mmc;
+
+ mmc->ops->card_event(mmc);
+ mmc_detect_change(mmc, msecs_to_jiffies(200));
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int sdhci_uhs2_host_ops_init(struct sdhci_host *host)
+{
+ host->mmc_host_ops.uhs2_control = sdhci_uhs2_control;
+ host->mmc_host_ops.request = sdhci_uhs2_request;
+
+ return 0;
+}
+
+static int __init sdhci_uhs2_mod_init(void)
+{
+ return 0;
+}
+module_init(sdhci_uhs2_mod_init);
+
+static void __exit sdhci_uhs2_mod_exit(void)
+{
+}
+module_exit(sdhci_uhs2_mod_exit);
+
+/*****************************************************************************\
+ *
+ * Device allocation/registration *
+ * *
+\*****************************************************************************/
+
+static void __sdhci_uhs2_add_host_v4(struct sdhci_host *host, u32 caps1)
+{
+ struct mmc_host *mmc;
+ u32 max_current_caps2;
+
+ mmc = host->mmc;
+
+ /* Support UHS2 */
+ if (caps1 & SDHCI_SUPPORT_UHS2)
+ mmc->caps2 |= MMC_CAP2_SD_UHS2;
+
+ max_current_caps2 = sdhci_readl(host, SDHCI_MAX_CURRENT_1);
+
+ if ((caps1 & SDHCI_CAN_VDD2_180) &&
+ !max_current_caps2 &&
+ !IS_ERR(mmc->supply.vqmmc2)) {
+ /* UHS2 - VDD2 */
+ int curr = regulator_get_current_limit(mmc->supply.vqmmc2);
+
+ if (curr > 0) {
+ /* convert to SDHCI_MAX_CURRENT format */
+ curr = curr / 1000; /* convert to mA */
+ curr = curr / SDHCI_MAX_CURRENT_MULTIPLIER;
+ curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT);
+ max_current_caps2 = curr;
+ }
+ }
+
+ if (!(caps1 & SDHCI_CAN_VDD2_180))
+ mmc->caps2 &= ~MMC_CAP2_SD_UHS2;
+}
+
+static void __sdhci_uhs2_remove_host(struct sdhci_host *host, int dead)
+{
+ if (!mmc_card_uhs2(host->mmc))
+ return;
+
+ if (!dead)
+ sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_FULL);
+}
+
+int sdhci_uhs2_add_host(struct sdhci_host *host)
+{
+ struct mmc_host *mmc = host->mmc;
+ int ret;
+
+ ret = sdhci_setup_host(host);
+ if (ret)
+ return ret;
+
+ if (host->version >= SDHCI_SPEC_400)
+ __sdhci_uhs2_add_host_v4(host, host->caps1);
+
+ if ((mmc->caps2 & MMC_CAP2_SD_UHS2) && !host->v4_mode)
+ /* host doesn't want to enable UHS2 support */
+ mmc->caps2 &= ~MMC_CAP2_SD_UHS2;
+
+ /* overwrite ops */
+ if (mmc->caps2 & MMC_CAP2_SD_UHS2)
+ sdhci_uhs2_host_ops_init(host);
+
+ host->complete_work_fn = sdhci_uhs2_complete_work;
+ host->thread_irq_fn = sdhci_uhs2_thread_irq;
+
+ /* LED support not implemented for UHS2 */
+ host->quirks |= SDHCI_QUIRK_NO_LED;
+
+ ret = __sdhci_add_host(host);
+ if (ret)
+ goto cleanup;
+
+ return 0;
+
+cleanup:
+ if (host->version >= SDHCI_SPEC_400)
+ __sdhci_uhs2_remove_host(host, 0);
+
+ sdhci_cleanup_host(host);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_add_host);
+
+void sdhci_uhs2_remove_host(struct sdhci_host *host, int dead)
+{
+ __sdhci_uhs2_remove_host(host, dead);
+
+ sdhci_remove_host(host, dead);
+}
+EXPORT_SYMBOL_GPL(sdhci_uhs2_remove_host);
+
+MODULE_AUTHOR("Intel, Genesys Logic, Linaro");
+MODULE_DESCRIPTION("MMC UHS-II Support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h
new file mode 100644
index 000000000000..da6905919630
--- /dev/null
+++ b/drivers/mmc/host/sdhci-uhs2.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Header file for Host Controller UHS2 related registers.
+ *
+ * Copyright (C) 2014 Intel Corp, All Rights Reserved.
+ */
+#ifndef __SDHCI_UHS2_H
+#define __SDHCI_UHS2_H
+
+#include <linux/bits.h>
+
+/* SDHCI Category C registers : UHS2 usage */
+
+#define SDHCI_UHS2_CM_TRAN_RESP 0x10
+#define SDHCI_UHS2_SD_TRAN_RESP 0x18
+#define SDHCI_UHS2_SD_TRAN_RESP_1 0x1C
+
+/* SDHCI Category B registers : UHS2 only */
+
+#define SDHCI_UHS2_BLOCK_SIZE 0x80
+#define SDHCI_UHS2_MAKE_BLKSZ(dma, blksz) ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF))
+
+#define SDHCI_UHS2_BLOCK_COUNT 0x84
+
+#define SDHCI_UHS2_CMD_PACKET 0x88
+#define SDHCI_UHS2_CMD_PACK_MAX_LEN 20
+
+#define SDHCI_UHS2_TRANS_MODE 0x9C
+#define SDHCI_UHS2_TRNS_DMA BIT(0)
+#define SDHCI_UHS2_TRNS_BLK_CNT_EN BIT(1)
+#define SDHCI_UHS2_TRNS_DATA_TRNS_WRT BIT(4)
+#define SDHCI_UHS2_TRNS_BLK_BYTE_MODE BIT(5)
+#define SDHCI_UHS2_TRNS_RES_R5 BIT(6)
+#define SDHCI_UHS2_TRNS_RES_ERR_CHECK_EN BIT(7)
+#define SDHCI_UHS2_TRNS_RES_INT_DIS BIT(8)
+#define SDHCI_UHS2_TRNS_WAIT_EBSY BIT(14)
+#define SDHCI_UHS2_TRNS_2L_HD BIT(15)
+
+#define SDHCI_UHS2_CMD 0x9E
+#define SDHCI_UHS2_CMD_SUB_CMD BIT(2)
+#define SDHCI_UHS2_CMD_DATA BIT(5)
+#define SDHCI_UHS2_CMD_TRNS_ABORT BIT(6)
+#define SDHCI_UHS2_CMD_CMD12 BIT(7)
+#define SDHCI_UHS2_CMD_DORMANT GENMASK(7, 6)
+#define SDHCI_UHS2_CMD_PACK_LEN_MASK GENMASK(12, 8)
+
+#define SDHCI_UHS2_RESPONSE 0xA0
+#define SDHCI_UHS2_RESPONSE_MAX_LEN 20
+
+#define SDHCI_UHS2_MSG_SELECT 0xB4
+#define SDHCI_UHS2_MSG_SELECT_CURR 0x0
+#define SDHCI_UHS2_MSG_SELECT_ONE 0x1
+#define SDHCI_UHS2_MSG_SELECT_TWO 0x2
+#define SDHCI_UHS2_MSG_SELECT_THREE 0x3
+
+#define SDHCI_UHS2_MSG 0xB8
+
+#define SDHCI_UHS2_DEV_INT_STATUS 0xBC
+
+#define SDHCI_UHS2_DEV_SELECT 0xBE
+#define SDHCI_UHS2_DEV_SEL_MASK GENMASK(3, 0)
+#define SDHCI_UHS2_DEV_SEL_INT_MSG_EN BIT(7)
+
+#define SDHCI_UHS2_DEV_INT_CODE 0xBF
+
+#define SDHCI_UHS2_SW_RESET 0xC0
+#define SDHCI_UHS2_SW_RESET_FULL BIT(0)
+#define SDHCI_UHS2_SW_RESET_SD BIT(1)
+
+#define SDHCI_UHS2_TIMER_CTRL 0xC2
+#define SDHCI_UHS2_TIMER_CTRL_DEADLOCK_MASK GENMASK(7, 4)
+
+#define SDHCI_UHS2_INT_STATUS 0xC4
+#define SDHCI_UHS2_INT_STATUS_ENABLE 0xC8
+#define SDHCI_UHS2_INT_SIGNAL_ENABLE 0xCC
+#define SDHCI_UHS2_INT_HEADER_ERR BIT(0)
+#define SDHCI_UHS2_INT_RES_ERR BIT(1)
+#define SDHCI_UHS2_INT_RETRY_EXP BIT(2)
+#define SDHCI_UHS2_INT_CRC BIT(3)
+#define SDHCI_UHS2_INT_FRAME_ERR BIT(4)
+#define SDHCI_UHS2_INT_TID_ERR BIT(5)
+#define SDHCI_UHS2_INT_UNRECOVER BIT(7)
+#define SDHCI_UHS2_INT_EBUSY_ERR BIT(8)
+#define SDHCI_UHS2_INT_ADMA_ERROR BIT(15)
+#define SDHCI_UHS2_INT_CMD_TIMEOUT BIT(16)
+#define SDHCI_UHS2_INT_DEADLOCK_TIMEOUT BIT(17)
+#define SDHCI_UHS2_INT_VENDOR_ERR BIT(27)
+#define SDHCI_UHS2_INT_ERROR_MASK ( \
+ SDHCI_UHS2_INT_HEADER_ERR | \
+ SDHCI_UHS2_INT_RES_ERR | \
+ SDHCI_UHS2_INT_RETRY_EXP | \
+ SDHCI_UHS2_INT_CRC | \
+ SDHCI_UHS2_INT_FRAME_ERR | \
+ SDHCI_UHS2_INT_TID_ERR | \
+ SDHCI_UHS2_INT_UNRECOVER | \
+ SDHCI_UHS2_INT_EBUSY_ERR | \
+ SDHCI_UHS2_INT_ADMA_ERROR | \
+ SDHCI_UHS2_INT_CMD_TIMEOUT | \
+ SDHCI_UHS2_INT_DEADLOCK_TIMEOUT)
+#define SDHCI_UHS2_INT_CMD_ERR_MASK ( \
+ SDHCI_UHS2_INT_HEADER_ERR | \
+ SDHCI_UHS2_INT_RES_ERR | \
+ SDHCI_UHS2_INT_FRAME_ERR | \
+ SDHCI_UHS2_INT_TID_ERR | \
+ SDHCI_UHS2_INT_CMD_TIMEOUT)
+/* CRC Error occurs during a packet receiving */
+#define SDHCI_UHS2_INT_DATA_ERR_MASK ( \
+ SDHCI_UHS2_INT_RETRY_EXP | \
+ SDHCI_UHS2_INT_CRC | \
+ SDHCI_UHS2_INT_UNRECOVER | \
+ SDHCI_UHS2_INT_EBUSY_ERR | \
+ SDHCI_UHS2_INT_ADMA_ERROR | \
+ SDHCI_UHS2_INT_DEADLOCK_TIMEOUT)
+
+#define SDHCI_UHS2_SETTINGS_PTR 0xE0
+#define SDHCI_UHS2_GEN_SETTINGS_POWER_LOW BIT(0)
+#define SDHCI_UHS2_GEN_SETTINGS_N_LANES_MASK GENMASK(11, 8)
+#define SDHCI_UHS2_FD_OR_2L_HD 0x0 /* 2 lanes */
+#define SDHCI_UHS2_2D1U_FD 0x2 /* 3 lanes, 2 down, 1 up, full duplex */
+#define SDHCI_UHS2_1D2U_FD 0x3 /* 3 lanes, 1 down, 2 up, full duplex */
+#define SDHCI_UHS2_2D2U_FD 0x4 /* 4 lanes, 2 down, 2 up, full duplex */
+
+#define SDHCI_UHS2_PHY_SET_SPEED_B BIT(6)
+#define SDHCI_UHS2_PHY_HIBERNATE_EN BIT(12)
+#define SDHCI_UHS2_PHY_N_LSS_SYN_MASK GENMASK(19, 16)
+#define SDHCI_UHS2_PHY_N_LSS_DIR_MASK GENMASK(23, 20)
+
+#define SDHCI_UHS2_TRAN_N_FCU_MASK GENMASK(15, 8)
+#define SDHCI_UHS2_TRAN_RETRY_CNT_MASK GENMASK(17, 16)
+#define SDHCI_UHS2_TRAN_1_N_DAT_GAP_MASK GENMASK(7, 0)
+
+#define SDHCI_UHS2_CAPS_PTR 0xE2
+#define SDHCI_UHS2_CAPS_OFFSET 0
+#define SDHCI_UHS2_CAPS_DAP_MASK GENMASK(3, 0)
+#define SDHCI_UHS2_CAPS_GAP_MASK GENMASK(7, 4)
+#define SDHCI_UHS2_CAPS_GAP(gap) ((gap) * 360)
+#define SDHCI_UHS2_CAPS_LANE_MASK GENMASK(13, 8)
+#define SDHCI_UHS2_CAPS_2L_HD_FD 1
+#define SDHCI_UHS2_CAPS_2D1U_FD 2
+#define SDHCI_UHS2_CAPS_1D2U_FD 4
+#define SDHCI_UHS2_CAPS_2D2U_FD 8
+#define SDHCI_UHS2_CAPS_ADDR_64 BIT(14)
+#define SDHCI_UHS2_CAPS_BOOT BIT(15)
+#define SDHCI_UHS2_CAPS_DEV_TYPE_MASK GENMASK(17, 16)
+#define SDHCI_UHS2_CAPS_DEV_TYPE_RMV 0
+#define SDHCI_UHS2_CAPS_DEV_TYPE_EMB 1
+#define SDHCI_UHS2_CAPS_DEV_TYPE_EMB_RMV 2
+#define SDHCI_UHS2_CAPS_NUM_DEV_MASK GENMASK(21, 18)
+#define SDHCI_UHS2_CAPS_BUS_TOPO_MASK GENMASK(23, 22)
+#define SDHCI_UHS2_CAPS_BUS_TOPO_SHIFT 22
+#define SDHCI_UHS2_CAPS_BUS_TOPO_P2P 0
+#define SDHCI_UHS2_CAPS_BUS_TOPO_RING 1
+#define SDHCI_UHS2_CAPS_BUS_TOPO_HUB 2
+#define SDHCI_UHS2_CAPS_BUS_TOPO_HUB_RING 3
+
+#define SDHCI_UHS2_CAPS_PHY_OFFSET 4
+#define SDHCI_UHS2_CAPS_PHY_REV_MASK GENMASK(5, 0)
+#define SDHCI_UHS2_CAPS_PHY_RANGE_MASK GENMASK(7, 6)
+#define SDHCI_UHS2_CAPS_PHY_RANGE_A 0
+#define SDHCI_UHS2_CAPS_PHY_RANGE_B 1
+#define SDHCI_UHS2_CAPS_PHY_N_LSS_SYN_MASK GENMASK(19, 16)
+#define SDHCI_UHS2_CAPS_PHY_N_LSS_DIR_MASK GENMASK(23, 20)
+#define SDHCI_UHS2_CAPS_TRAN_OFFSET 8
+#define SDHCI_UHS2_CAPS_TRAN_LINK_REV_MASK GENMASK(5, 0)
+#define SDHCI_UHS2_CAPS_TRAN_N_FCU_MASK GENMASK(15, 8)
+#define SDHCI_UHS2_CAPS_TRAN_HOST_TYPE_MASK GENMASK(18, 16)
+#define SDHCI_UHS2_CAPS_TRAN_BLK_LEN_MASK GENMASK(31, 20)
+
+#define SDHCI_UHS2_CAPS_TRAN_1_OFFSET 12
+#define SDHCI_UHS2_CAPS_TRAN_1_N_DATA_GAP_MASK GENMASK(7, 0)
+
+#define SDHCI_UHS2_EMBED_CTRL_PTR 0xE6
+#define SDHCI_UHS2_VENDOR_PTR 0xE8
+
+struct sdhci_host;
+struct mmc_command;
+struct mmc_request;
+
+void sdhci_uhs2_dump_regs(struct sdhci_host *host);
+void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask);
+void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd);
+void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd);
+int sdhci_uhs2_add_host(struct sdhci_host *host);
+void sdhci_uhs2_remove_host(struct sdhci_host *host, int dead);
+void sdhci_uhs2_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set);
+u32 sdhci_uhs2_irq(struct sdhci_host *host, u32 intmask);
+
+#endif /* __SDHCI_UHS2_H */
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
index 0e52867f6e91..098f0ea45cbe 100644
--- a/drivers/mmc/host/sdhci-xenon.c
+++ b/drivers/mmc/host/sdhci-xenon.c
@@ -734,7 +734,7 @@ static struct platform_driver sdhci_xenon_driver = {
.pm = &sdhci_xenon_dev_pm_ops,
},
.probe = xenon_probe,
- .remove_new = xenon_remove,
+ .remove = xenon_remove,
};
module_platform_driver(sdhci_xenon_driver);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 4b91c9e96635..f4a7733a8ad2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -23,7 +23,7 @@
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
-
+#include <linux/bug.h>
#include <linux/leds.h>
#include <linux/mmc/mmc.h>
@@ -47,8 +47,6 @@
static unsigned int debug_quirks = 0;
static unsigned int debug_quirks2;
-static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
-
static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd);
void sdhci_dumpregs(struct sdhci_host *host)
@@ -110,6 +108,9 @@ void sdhci_dumpregs(struct sdhci_host *host)
}
}
+ if (host->ops->dump_uhs2_regs)
+ host->ops->dump_uhs2_regs(host);
+
if (host->ops->dump_vendor_regs)
host->ops->dump_vendor_regs(host);
@@ -146,10 +147,11 @@ void sdhci_enable_v4_mode(struct sdhci_host *host)
}
EXPORT_SYMBOL_GPL(sdhci_enable_v4_mode);
-static inline bool sdhci_data_line_cmd(struct mmc_command *cmd)
+bool sdhci_data_line_cmd(struct mmc_command *cmd)
{
return cmd->data || cmd->flags & MMC_RSP_BUSY;
}
+EXPORT_SYMBOL_GPL(sdhci_data_line_cmd);
static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
{
@@ -233,7 +235,7 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
}
EXPORT_SYMBOL_GPL(sdhci_reset);
-static bool sdhci_do_reset(struct sdhci_host *host, u8 mask)
+bool sdhci_do_reset(struct sdhci_host *host, u8 mask)
{
if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
struct mmc_host *mmc = host->mmc;
@@ -246,6 +248,7 @@ static bool sdhci_do_reset(struct sdhci_host *host, u8 mask)
return true;
}
+EXPORT_SYMBOL_GPL(sdhci_do_reset);
static void sdhci_reset_for_all(struct sdhci_host *host)
{
@@ -501,14 +504,15 @@ static inline void sdhci_led_deactivate(struct sdhci_host *host)
#endif
-static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq,
- unsigned long timeout)
+void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq,
+ unsigned long timeout)
{
if (sdhci_data_line_cmd(mrq->cmd))
mod_timer(&host->data_timer, timeout);
else
mod_timer(&host->timer, timeout);
}
+EXPORT_SYMBOL_GPL(sdhci_mod_timer);
static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq)
{
@@ -1075,8 +1079,7 @@ static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
__sdhci_set_timeout(host, cmd);
}
-static void sdhci_initialize_data(struct sdhci_host *host,
- struct mmc_data *data)
+void sdhci_initialize_data(struct sdhci_host *host, struct mmc_data *data)
{
WARN_ON(host->data);
@@ -1089,6 +1092,7 @@ static void sdhci_initialize_data(struct sdhci_host *host,
host->data_early = 0;
host->data->bytes_xfered = 0;
}
+EXPORT_SYMBOL_GPL(sdhci_initialize_data);
static inline void sdhci_set_block_info(struct sdhci_host *host,
struct mmc_data *data)
@@ -1111,12 +1115,8 @@ static inline void sdhci_set_block_info(struct sdhci_host *host,
}
}
-static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data)
{
- struct mmc_data *data = cmd->data;
-
- sdhci_initialize_data(host, data);
-
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
struct scatterlist *sg;
unsigned int length_mask, offset_mask;
@@ -1201,6 +1201,16 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
}
sdhci_set_transfer_irqs(host);
+}
+EXPORT_SYMBOL_GPL(sdhci_prepare_dma);
+
+static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+{
+ struct mmc_data *data = cmd->data;
+
+ sdhci_initialize_data(host, data);
+
+ sdhci_prepare_dma(host, data);
sdhci_set_block_info(host, data);
}
@@ -1488,7 +1498,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
}
-static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)
+bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)
{
return (!(host->flags & SDHCI_DEVICE_DEAD) &&
((mrq->cmd && mrq->cmd->error) ||
@@ -1496,6 +1506,7 @@ static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)
(mrq->data && mrq->data->stop && mrq->data->stop->error) ||
(host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)));
}
+EXPORT_SYMBOL_GPL(sdhci_needs_reset);
static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq)
{
@@ -1518,7 +1529,7 @@ static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq)
WARN_ON(i >= SDHCI_MAX_MRQS);
}
-static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
+void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
{
if (host->cmd && host->cmd->mrq == mrq)
host->cmd = NULL;
@@ -1542,15 +1553,17 @@ static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
if (!sdhci_has_requests(host))
sdhci_led_deactivate(host);
}
+EXPORT_SYMBOL_GPL(__sdhci_finish_mrq);
-static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
+void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
{
__sdhci_finish_mrq(host, mrq);
queue_work(host->complete_wq, &host->complete_work);
}
+EXPORT_SYMBOL_GPL(sdhci_finish_mrq);
-static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
+void __sdhci_finish_data_common(struct sdhci_host *host, bool defer_reset)
{
struct mmc_command *data_cmd = host->data_cmd;
struct mmc_data *data = host->data;
@@ -1563,7 +1576,9 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
* conditions.
*/
if (data->error) {
- if (!host->cmd || host->cmd == data_cmd)
+ if (defer_reset)
+ host->pending_reset = true;
+ else if (!host->cmd || host->cmd == data_cmd)
sdhci_reset_for(host, REQUEST_ERROR);
else
sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY);
@@ -1584,6 +1599,14 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
data->bytes_xfered = 0;
else
data->bytes_xfered = data->blksz * data->blocks;
+}
+EXPORT_SYMBOL_GPL(__sdhci_finish_data_common);
+
+static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
+{
+ struct mmc_data *data = host->data;
+
+ __sdhci_finish_data_common(host, false);
/*
* Need to send CMD12 if -
@@ -1718,8 +1741,8 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
return true;
}
-static bool sdhci_present_error(struct sdhci_host *host,
- struct mmc_command *cmd, bool present)
+bool sdhci_present_error(struct sdhci_host *host,
+ struct mmc_command *cmd, bool present)
{
if (!present || host->flags & SDHCI_DEVICE_DEAD) {
cmd->error = -ENOMEDIUM;
@@ -1728,6 +1751,7 @@ static bool sdhci_present_error(struct sdhci_host *host,
return false;
}
+EXPORT_SYMBOL_GPL(sdhci_present_error);
static bool sdhci_send_command_retry(struct sdhci_host *host,
struct mmc_command *cmd,
@@ -1874,6 +1898,12 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
case MMC_TIMING_MMC_HS400:
preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400);
break;
+ case MMC_TIMING_UHS2_SPEED_A:
+ case MMC_TIMING_UHS2_SPEED_A_HD:
+ case MMC_TIMING_UHS2_SPEED_B:
+ case MMC_TIMING_UHS2_SPEED_B_HD:
+ preset = sdhci_readw(host, SDHCI_PRESET_FOR_UHS2);
+ break;
default:
pr_warn("%s: Invalid UHS-I mode selected\n",
mmc_hostname(host->mmc));
@@ -2058,41 +2088,46 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
}
+unsigned short sdhci_get_vdd_value(unsigned short vdd)
+{
+ switch (1 << vdd) {
+ case MMC_VDD_165_195:
+ /*
+ * Without a regulator, SDHCI does not support 2.0v
+ * so we only get here if the driver deliberately
+ * added the 2.0v range to ocr_avail. Map it to 1.8v
+ * for the purpose of turning on the power.
+ */
+ case MMC_VDD_20_21:
+ return SDHCI_POWER_180;
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ return SDHCI_POWER_300;
+ case MMC_VDD_32_33:
+ case MMC_VDD_33_34:
+ /*
+ * 3.4V ~ 3.6V are valid only for those platforms where it's
+ * known that the voltage range is supported by hardware.
+ */
+ case MMC_VDD_34_35:
+ case MMC_VDD_35_36:
+ return SDHCI_POWER_330;
+ default:
+ return 0;
+ }
+}
+EXPORT_SYMBOL_GPL(sdhci_get_vdd_value);
+
void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
unsigned short vdd)
{
u8 pwr = 0;
if (mode != MMC_POWER_OFF) {
- switch (1 << vdd) {
- case MMC_VDD_165_195:
- /*
- * Without a regulator, SDHCI does not support 2.0v
- * so we only get here if the driver deliberately
- * added the 2.0v range to ocr_avail. Map it to 1.8v
- * for the purpose of turning on the power.
- */
- case MMC_VDD_20_21:
- pwr = SDHCI_POWER_180;
- break;
- case MMC_VDD_29_30:
- case MMC_VDD_30_31:
- pwr = SDHCI_POWER_300;
- break;
- case MMC_VDD_32_33:
- case MMC_VDD_33_34:
- /*
- * 3.4 ~ 3.6V are valid only for those platforms where it's
- * known that the voltage range is supported by hardware.
- */
- case MMC_VDD_34_35:
- case MMC_VDD_35_36:
- pwr = SDHCI_POWER_330;
- break;
- default:
+ pwr = sdhci_get_vdd_value(vdd);
+ if (!pwr) {
WARN(1, "%s: Invalid vdd %#x\n",
mmc_hostname(host->mmc), vdd);
- break;
}
}
@@ -2315,24 +2350,9 @@ static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_i
(sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type);
}
-void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+void sdhci_set_ios_common(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdhci_host *host = mmc_priv(mmc);
- bool reinit_uhs = host->reinit_uhs;
- bool turning_on_clk = false;
- u8 ctrl;
-
- host->reinit_uhs = false;
-
- if (ios->power_mode == MMC_POWER_UNDEFINED)
- return;
-
- if (host->flags & SDHCI_DEVICE_DEAD) {
- if (!IS_ERR(mmc->supply.vmmc) &&
- ios->power_mode == MMC_POWER_OFF)
- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
- return;
- }
/*
* Reset the chip on each power off.
@@ -2349,8 +2369,6 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_enable_preset_value(host, false);
if (!ios->clock || ios->clock != host->clock) {
- turning_on_clk = ios->clock && !host->clock;
-
host->ops->set_clock(host, ios->clock);
host->clock = ios->clock;
@@ -2366,6 +2384,31 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
mmc->max_busy_timeout /= host->timeout_clk;
}
}
+}
+EXPORT_SYMBOL_GPL(sdhci_set_ios_common);
+
+void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ bool reinit_uhs = host->reinit_uhs;
+ bool turning_on_clk;
+ u8 ctrl;
+
+ host->reinit_uhs = false;
+
+ if (ios->power_mode == MMC_POWER_UNDEFINED)
+ return;
+
+ if (host->flags & SDHCI_DEVICE_DEAD) {
+ if (!IS_ERR(mmc->supply.vmmc) &&
+ ios->power_mode == MMC_POWER_OFF)
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+ return;
+ }
+
+ turning_on_clk = ios->clock != host->clock && ios->clock && !host->clock;
+
+ sdhci_set_ios_common(mmc, ios);
if (host->ops->set_power)
host->ops->set_power(host, ios->power_mode, ios->vdd);
@@ -2934,7 +2977,7 @@ out:
}
EXPORT_SYMBOL_GPL(sdhci_execute_tuning);
-static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
+void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
{
/* Host Controller v3.00 defines preset value registers */
if (host->version < SDHCI_SPEC_300)
@@ -2962,6 +3005,7 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
host->preset_enabled = enable;
}
}
+EXPORT_SYMBOL_GPL(sdhci_enable_preset_value);
static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
int err)
@@ -3055,6 +3099,53 @@ static const struct mmc_host_ops sdhci_ops = {
* *
\*****************************************************************************/
+void sdhci_request_done_dma(struct sdhci_host *host, struct mmc_request *mrq)
+{
+ struct mmc_data *data = mrq->data;
+
+ if (data && data->host_cookie == COOKIE_MAPPED) {
+ if (host->bounce_buffer) {
+ /*
+ * On reads, copy the bounced data into the
+ * sglist
+ */
+ if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) {
+ unsigned int length = data->bytes_xfered;
+
+ if (length > host->bounce_buffer_size) {
+ pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n",
+ mmc_hostname(host->mmc),
+ host->bounce_buffer_size,
+ data->bytes_xfered);
+ /* Cap it down and continue */
+ length = host->bounce_buffer_size;
+ }
+ dma_sync_single_for_cpu(mmc_dev(host->mmc),
+ host->bounce_addr,
+ host->bounce_buffer_size,
+ DMA_FROM_DEVICE);
+ sg_copy_from_buffer(data->sg,
+ data->sg_len,
+ host->bounce_buffer,
+ length);
+ } else {
+ /* No copying, just switch ownership */
+ dma_sync_single_for_cpu(mmc_dev(host->mmc),
+ host->bounce_addr,
+ host->bounce_buffer_size,
+ mmc_get_dma_dir(data));
+ }
+ } else {
+ /* Unmap the raw data */
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len,
+ mmc_get_dma_dir(data));
+ }
+ data->host_cookie = COOKIE_UNMAPPED;
+ }
+}
+EXPORT_SYMBOL_GPL(sdhci_request_done_dma);
+
static bool sdhci_request_done(struct sdhci_host *host)
{
unsigned long flags;
@@ -3119,48 +3210,7 @@ static bool sdhci_request_done(struct sdhci_host *host)
sdhci_set_mrq_done(host, mrq);
}
- if (data && data->host_cookie == COOKIE_MAPPED) {
- if (host->bounce_buffer) {
- /*
- * On reads, copy the bounced data into the
- * sglist
- */
- if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) {
- unsigned int length = data->bytes_xfered;
-
- if (length > host->bounce_buffer_size) {
- pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n",
- mmc_hostname(host->mmc),
- host->bounce_buffer_size,
- data->bytes_xfered);
- /* Cap it down and continue */
- length = host->bounce_buffer_size;
- }
- dma_sync_single_for_cpu(
- mmc_dev(host->mmc),
- host->bounce_addr,
- host->bounce_buffer_size,
- DMA_FROM_DEVICE);
- sg_copy_from_buffer(data->sg,
- data->sg_len,
- host->bounce_buffer,
- length);
- } else {
- /* No copying, just switch ownership */
- dma_sync_single_for_cpu(
- mmc_dev(host->mmc),
- host->bounce_addr,
- host->bounce_buffer_size,
- mmc_get_dma_dir(data));
- }
- } else {
- /* Unmap the raw data */
- dma_unmap_sg(mmc_dev(host->mmc), data->sg,
- data->sg_len,
- mmc_get_dma_dir(data));
- }
- data->host_cookie = COOKIE_UNMAPPED;
- }
+ sdhci_request_done_dma(host, mrq);
}
host->mrqs_done[i] = NULL;
@@ -3175,7 +3225,7 @@ static bool sdhci_request_done(struct sdhci_host *host)
return false;
}
-static void sdhci_complete_work(struct work_struct *work)
+void sdhci_complete_work(struct work_struct *work)
{
struct sdhci_host *host = container_of(work, struct sdhci_host,
complete_work);
@@ -3183,6 +3233,7 @@ static void sdhci_complete_work(struct work_struct *work)
while (!sdhci_request_done(host))
;
}
+EXPORT_SYMBOL_GPL(sdhci_complete_work);
static void sdhci_timeout_timer(struct timer_list *t)
{
@@ -3644,7 +3695,7 @@ out:
return result;
}
-static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
+irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
{
struct sdhci_host *host = dev_id;
struct mmc_command *cmd;
@@ -3674,6 +3725,7 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(sdhci_thread_irq);
/*****************************************************************************\
* *
@@ -4046,6 +4098,9 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev,
host->max_timeout_count = 0xE;
+ host->complete_work_fn = sdhci_complete_work;
+ host->thread_irq_fn = sdhci_thread_irq;
+
return host;
}
@@ -4810,7 +4865,7 @@ int __sdhci_add_host(struct sdhci_host *host)
if (!host->complete_wq)
return -ENOMEM;
- INIT_WORK(&host->complete_work, sdhci_complete_work);
+ INIT_WORK(&host->complete_work, host->complete_work_fn);
timer_setup(&host->timer, sdhci_timeout_timer, 0);
timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0);
@@ -4819,7 +4874,7 @@ int __sdhci_add_host(struct sdhci_host *host)
sdhci_init(host, 0);
- ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
+ ret = request_threaded_irq(host->irq, sdhci_irq, host->thread_irq_fn,
IRQF_SHARED, mmc_hostname(mmc), host);
if (ret) {
pr_err("%s: Failed to request IRQ %d: %d\n",
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index f531b617f28d..cd0e35a80542 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -43,8 +43,23 @@
#define SDHCI_TRNS_READ 0x10
#define SDHCI_TRNS_MULTI 0x20
+/*
+ * Defined in Host Version 4.0.
+ */
+#define SDHCI_TRNS_RES_TYPE 0x40
+#define SDHCI_TRNS_RES_ERR_CHECK 0x80
+#define SDHCI_TRNS_RES_INT_DIS 0x0100
+
#define SDHCI_COMMAND 0x0E
#define SDHCI_CMD_RESP_MASK 0x03
+
+/*
+ * Host Version 4.10 adds this bit to distinguish a main command or
+ * sub command.
+ * For example with SDIO, CMD52 (sub command) issued during CMD53 (main command).
+ */
+#define SDHCI_CMD_SUB_CMD 0x04
+
#define SDHCI_CMD_CRC 0x08
#define SDHCI_CMD_INDEX 0x10
#define SDHCI_CMD_DATA 0x20
@@ -65,6 +80,9 @@
#define SDHCI_PRESENT_STATE 0x24
#define SDHCI_CMD_INHIBIT 0x00000001
#define SDHCI_DATA_INHIBIT 0x00000002
+
+#define SDHCI_DAT_4_TO_7_LVL_MASK 0x000000F0
+
#define SDHCI_DOING_WRITE 0x00000100
#define SDHCI_DOING_READ 0x00000200
#define SDHCI_SPACE_AVAILABLE 0x00000400
@@ -80,6 +98,15 @@
#define SDHCI_DATA_0_LVL_MASK 0x00100000
#define SDHCI_CMD_LVL 0x01000000
+/* Host Version 4.10 */
+
+#define SDHCI_HOST_REGULATOR_STABLE 0x02000000
+#define SDHCI_CMD_NOT_ISSUED_ERR 0x08000000
+#define SDHCI_SUB_CMD_STATUS 0x10000000
+#define SDHCI_UHS2_IN_DORMANT_STATE 0x20000000
+#define SDHCI_UHS2_LANE_SYNC 0x40000000
+#define SDHCI_UHS2_IF_DETECT 0x80000000
+
#define SDHCI_HOST_CONTROL 0x28
#define SDHCI_CTRL_LED 0x01
#define SDHCI_CTRL_4BITBUS 0x02
@@ -117,7 +144,7 @@
#define SDHCI_CLOCK_CONTROL 0x2C
#define SDHCI_DIVIDER_SHIFT 8
#define SDHCI_DIVIDER_HI_SHIFT 6
-#define SDHCI_DIV_MASK 0xFF
+#define SDHCI_DIV_MASK 0xFF
#define SDHCI_DIV_MASK_LEN 8
#define SDHCI_DIV_HI_MASK 0x300
#define SDHCI_PROG_CLOCK_MODE 0x0020
@@ -146,6 +173,10 @@
#define SDHCI_INT_CARD_REMOVE 0x00000080
#define SDHCI_INT_CARD_INT 0x00000100
#define SDHCI_INT_RETUNE 0x00001000
+
+/* Host Version 4.10 */
+#define SDHCI_INT_FX_EVENT 0x00002000
+
#define SDHCI_INT_CQE 0x00004000
#define SDHCI_INT_ERROR 0x00008000
#define SDHCI_INT_TIMEOUT 0x00010000
@@ -160,6 +191,9 @@
#define SDHCI_INT_ADMA_ERROR 0x02000000
#define SDHCI_INT_TUNING_ERROR 0x04000000
+/* Host Version 4.0 */
+#define SDHCI_INT_RESP_ERR 0x08000000
+
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
@@ -186,6 +220,9 @@
#define SDHCI_AUTO_CMD_END_BIT 0x00000008
#define SDHCI_AUTO_CMD_INDEX 0x00000010
+/* Host Version 4.10 */
+#define SDHCI_AUTO_CMD_RESP_ERR 0x0020
+
#define SDHCI_HOST_CONTROL2 0x3E
#define SDHCI_CTRL_UHS_MASK 0x0007
#define SDHCI_CTRL_UHS_SDR12 0x0000
@@ -194,6 +231,7 @@
#define SDHCI_CTRL_UHS_SDR104 0x0003
#define SDHCI_CTRL_UHS_DDR50 0x0004
#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
+#define SDHCI_CTRL_UHS2 0x0007
#define SDHCI_CTRL_VDD_180 0x0008
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
@@ -202,9 +240,12 @@
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
#define SDHCI_CTRL_EXEC_TUNING 0x0040
#define SDHCI_CTRL_TUNED_CLK 0x0080
+#define SDHCI_CTRL_UHS2_ENABLE 0x0100
+#define SDHCI_CTRL_ADMA2_LEN_MODE 0x0400
#define SDHCI_CMD23_ENABLE 0x0800
#define SDHCI_CTRL_V4_MODE 0x1000
#define SDHCI_CTRL_64BIT_ADDR 0x2000
+#define SDHCI_CTRL_ASYNC_INT_ENABLE 0x4000
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
#define SDHCI_CAPABILITIES 0x40
@@ -227,11 +268,13 @@
#define SDHCI_CAN_VDD_180 0x04000000
#define SDHCI_CAN_64BIT_V4 0x08000000
#define SDHCI_CAN_64BIT 0x10000000
+#define SDHCI_CAN_ASYNC_INT 0x20000000
#define SDHCI_CAPABILITIES_1 0x44
#define SDHCI_SUPPORT_SDR50 0x00000001
#define SDHCI_SUPPORT_SDR104 0x00000002
#define SDHCI_SUPPORT_DDR50 0x00000004
+#define SDHCI_SUPPORT_UHS2 0x00000008
#define SDHCI_DRIVER_TYPE_A 0x00000010
#define SDHCI_DRIVER_TYPE_C 0x00000020
#define SDHCI_DRIVER_TYPE_D 0x00000040
@@ -240,6 +283,7 @@
#define SDHCI_RETUNING_MODE_MASK GENMASK(15, 14)
#define SDHCI_CLOCK_MUL_MASK GENMASK(23, 16)
#define SDHCI_CAN_DO_ADMA3 0x08000000
+#define SDHCI_CAN_VDD2_180 0x10000000 /* UHS-2 1.8V VDD2 */
#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */
#define SDHCI_MAX_CURRENT 0x48
@@ -247,11 +291,14 @@
#define SDHCI_MAX_CURRENT_330_MASK GENMASK(7, 0)
#define SDHCI_MAX_CURRENT_300_MASK GENMASK(15, 8)
#define SDHCI_MAX_CURRENT_180_MASK GENMASK(23, 16)
+#define SDHCI_MAX_CURRENT_1 0x4C
+#define SDHCI_MAX_CURRENT_VDD2_180_MASK GENMASK(7, 0) /* UHS2 */
#define SDHCI_MAX_CURRENT_MULTIPLIER 4
/* 4C-4F reserved for more max current */
#define SDHCI_SET_ACMD12_ERROR 0x50
+/* Host Version 4.10 */
#define SDHCI_SET_INT_ERROR 0x52
#define SDHCI_ADMA_ERROR 0x54
@@ -270,10 +317,15 @@
#define SDHCI_PRESET_FOR_SDR104 0x6C
#define SDHCI_PRESET_FOR_DDR50 0x6E
#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */
+
+/* UHS2 */
+#define SDHCI_PRESET_FOR_UHS2 0x74
#define SDHCI_PRESET_DRV_MASK GENMASK(15, 14)
#define SDHCI_PRESET_CLKGEN_SEL BIT(10)
#define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0)
+#define SDHCI_ADMA3_ADDRESS 0x78
+
#define SDHCI_SLOT_INT_STATUS 0xFC
#define SDHCI_HOST_VERSION 0xFE
@@ -573,6 +625,9 @@ struct sdhci_host {
struct timer_list timer; /* Timer for timeouts */
struct timer_list data_timer; /* Timer for data timeouts */
+ void (*complete_work_fn)(struct work_struct *work);
+ irqreturn_t (*thread_irq_fn)(int irq, void *dev_id);
+
#if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA)
struct dma_chan *rx_chan;
struct dma_chan *tx_chan;
@@ -667,6 +722,8 @@ struct sdhci_ops {
void (*request_done)(struct sdhci_host *host,
struct mmc_request *mrq);
void (*dump_vendor_regs)(struct sdhci_host *host);
+ void (*dump_uhs2_regs)(struct sdhci_host *host);
+ void (*uhs2_pre_detect_init)(struct sdhci_host *host);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
@@ -774,6 +831,15 @@ static inline void sdhci_read_caps(struct sdhci_host *host)
__sdhci_read_caps(host, NULL, NULL, NULL);
}
+bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq);
+bool sdhci_data_line_cmd(struct mmc_command *cmd);
+void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, unsigned long timeout);
+void sdhci_initialize_data(struct sdhci_host *host, struct mmc_data *data);
+void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data);
+void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq);
+void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq);
+void __sdhci_finish_data_common(struct sdhci_host *host, bool defer_reset);
+bool sdhci_present_error(struct sdhci_host *host, struct mmc_command *cmd, bool present);
u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
unsigned int *actual_clock);
void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
@@ -783,6 +849,7 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
void sdhci_set_power_and_bus_voltage(struct sdhci_host *host,
unsigned char mode,
unsigned short vdd);
+unsigned short sdhci_get_vdd_value(unsigned short vdd);
void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
unsigned short vdd);
int sdhci_get_cd_nogpio(struct mmc_host *mmc);
@@ -791,13 +858,19 @@ void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq);
int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq);
void sdhci_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask);
+bool sdhci_do_reset(struct sdhci_host *host, u8 mask);
void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode);
+void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
+void sdhci_set_ios_common(struct mmc_host *mmc, struct mmc_ios *ios);
void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios);
void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable);
+void sdhci_request_done_dma(struct sdhci_host *host, struct mmc_request *mrq);
+void sdhci_complete_work(struct work_struct *work);
+irqreturn_t sdhci_thread_irq(int irq, void *dev_id);
void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
dma_addr_t addr, int len, unsigned int cmd);
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
index 0aa3c40ea6ed..b73f673db92b 100644
--- a/drivers/mmc/host/sdhci_am654.c
+++ b/drivers/mmc/host/sdhci_am654.c
@@ -155,6 +155,7 @@ struct sdhci_am654_data {
u32 tuning_loop;
#define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0)
+#define SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA BIT(1)
};
struct window {
@@ -356,6 +357,29 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,
sdhci_set_clock(host, clock);
}
+static int sdhci_am654_start_signal_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
+ int ret;
+
+ if ((sdhci_am654->quirks & SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA) &&
+ ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+ if (!IS_ERR(mmc->supply.vqmmc)) {
+ ret = mmc_regulator_set_vqmmc(mmc, ios);
+ if (ret < 0) {
+ pr_err("%s: Switching to 1.8V signalling voltage failed,\n",
+ mmc_hostname(mmc));
+ return -EIO;
+ }
+ }
+ return 0;
+ }
+
+ return sdhci_start_signal_voltage_switch(mmc, ios);
+}
+
static u8 sdhci_am654_write_power_on(struct sdhci_host *host, u8 val, int reg)
{
writeb(val, host->ioaddr + reg);
@@ -844,6 +868,11 @@ static int sdhci_am654_get_of_property(struct platform_device *pdev,
if (device_property_read_bool(dev, "ti,fails-without-test-cd"))
sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST;
+ /* Suppress v1p8 ena for eMMC and SD with vqmmc supply */
+ if (!!of_parse_phandle(dev->of_node, "vmmc-supply", 0) ==
+ !!of_parse_phandle(dev->of_node, "vqmmc-supply", 0))
+ sdhci_am654->quirks |= SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA;
+
sdhci_get_of_property(pdev);
return 0;
@@ -940,6 +969,7 @@ static int sdhci_am654_probe(struct platform_device *pdev)
goto err_pltfm_free;
}
+ host->mmc_host_ops.start_signal_voltage_switch = sdhci_am654_start_signal_voltage_switch;
host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning;
pm_runtime_get_noresume(dev);
@@ -1100,7 +1130,7 @@ static struct platform_driver sdhci_am654_driver = {
.of_match_table = sdhci_am654_of_match,
},
.probe = sdhci_am654_probe,
- .remove_new = sdhci_am654_remove,
+ .remove = sdhci_am654_remove,
};
module_platform_driver(sdhci_am654_driver);
diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c
index c58e7cb1e2a7..ee66e4f3683d 100644
--- a/drivers/mmc/host/sdhci_f_sdh30.c
+++ b/drivers/mmc/host/sdhci_f_sdh30.c
@@ -247,7 +247,7 @@ static struct platform_driver sdhci_f_sdh30_driver = {
.pm = &sdhci_pltfm_pmops,
},
.probe = sdhci_f_sdh30_probe,
- .remove_new = sdhci_f_sdh30_remove,
+ .remove = sdhci_f_sdh30_remove,
};
module_platform_driver(sdhci_f_sdh30_driver);
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 08b4312af94e..ce60cec26b98 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -439,14 +439,15 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host)
if (IS_ERR(host->chan_rx))
host->chan_rx = NULL;
}
- dev_dbg(dev, "%s: got channel TX %p RX %p\n", __func__, host->chan_tx,
- host->chan_rx);
if (!host->chan_tx || !host->chan_rx ||
sh_mmcif_dma_slave_config(host, host->chan_tx, DMA_MEM_TO_DEV) ||
sh_mmcif_dma_slave_config(host, host->chan_rx, DMA_DEV_TO_MEM))
goto error;
+ dev_dbg(dev, "%s: got channel TX %p RX %p\n", __func__, host->chan_tx,
+ host->chan_rx);
+
return;
error:
@@ -1596,7 +1597,7 @@ static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
static struct platform_driver sh_mmcif_driver = {
.probe = sh_mmcif_probe,
- .remove_new = sh_mmcif_remove,
+ .remove = sh_mmcif_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/sunplus-mmc.c b/drivers/mmc/host/sunplus-mmc.c
index 13c7cc0b6180..1cddea615a27 100644
--- a/drivers/mmc/host/sunplus-mmc.c
+++ b/drivers/mmc/host/sunplus-mmc.c
@@ -982,7 +982,7 @@ MODULE_DEVICE_TABLE(of, spmmc_of_table);
static struct platform_driver spmmc_driver = {
.probe = spmmc_drv_probe,
- .remove_new = spmmc_drv_remove,
+ .remove = spmmc_drv_remove,
.driver = {
.name = "spmmc",
.pm = pm_ptr(&spmmc_pm_ops),
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index d3bd0ac99ec4..1508eead5d01 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -1191,10 +1191,9 @@ static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = {
.needs_new_timings = true,
};
-static const struct sunxi_mmc_cfg sun50i_a100_cfg = {
+static const struct sunxi_mmc_cfg sun50i_h616_cfg = {
.idma_des_size_bits = 16,
.idma_des_shift = 2,
- .clk_delays = NULL,
.can_calibrate = true,
.mask_data0 = true,
.needs_new_timings = true,
@@ -1217,8 +1216,9 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun20i-d1-mmc", .data = &sun20i_d1_cfg },
{ .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
- { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg },
+ { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun20i_d1_cfg },
{ .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg },
+ { .compatible = "allwinner,sun50i-h616-mmc", .data = &sun50i_h616_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
@@ -1554,7 +1554,7 @@ static struct platform_driver sunxi_mmc_driver = {
.pm = &sunxi_mmc_pm_ops,
},
.probe = sunxi_mmc_probe,
- .remove_new = sunxi_mmc_remove,
+ .remove = sunxi_mmc_remove,
};
module_platform_driver(sunxi_mmc_driver);
diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c
index 46ee8a0b2b85..4ad02cfdc238 100644
--- a/drivers/mmc/host/uniphier-sd.c
+++ b/drivers/mmc/host/uniphier-sd.c
@@ -754,7 +754,7 @@ MODULE_DEVICE_TABLE(of, uniphier_sd_match);
static struct platform_driver uniphier_sd_driver = {
.probe = uniphier_sd_probe,
- .remove_new = uniphier_sd_remove,
+ .remove = uniphier_sd_remove,
.driver = {
.name = "uniphier-sd",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
index 6e421445d56c..49efb960a052 100644
--- a/drivers/mmc/host/usdhi6rol0.c
+++ b/drivers/mmc/host/usdhi6rol0.c
@@ -1899,7 +1899,7 @@ static void usdhi6_remove(struct platform_device *pdev)
static struct platform_driver usdhi6_driver = {
.probe = usdhi6_probe,
- .remove_new = usdhi6_remove,
+ .remove = usdhi6_remove,
.driver = {
.name = "usdhi6rol0",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 6e20405d0430..8b268e8a0ec9 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1896,7 +1896,7 @@ static struct platform_device *wbsd_device;
static struct platform_driver wbsd_driver = {
.probe = wbsd_probe,
- .remove_new = wbsd_remove,
+ .remove = wbsd_remove,
.suspend = wbsd_platform_suspend,
.resume = wbsd_platform_resume,
.driver = {
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
index 860380931b6c..cdb36a9f9e38 100644
--- a/drivers/mmc/host/wmt-sdmmc.c
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -982,7 +982,7 @@ static const struct dev_pm_ops wmt_mci_pm = {
static struct platform_driver wmt_mci_driver = {
.probe = wmt_mci_probe,
- .remove_new = wmt_mci_remove,
+ .remove = wmt_mci_remove,
.driver = {
.name = DRIVER_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 9f2223d3e8e1..7c91429a670b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -1779,10 +1779,8 @@ static int __xipram do_write_oneword_retry(struct map_info *map,
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
- if (++retry_cnt <= MAX_RETRIES) {
- ret = 0;
+ if (++retry_cnt <= MAX_RETRIES)
goto retry;
- }
}
xip_enable(map, chip, adr);
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
index 74f559bf8dfb..2edc46741774 100644
--- a/drivers/mtd/devices/bcm47xxsflash.c
+++ b/drivers/mtd/devices/bcm47xxsflash.c
@@ -367,7 +367,7 @@ static void bcm47xxsflash_bcma_remove(struct platform_device *pdev)
static struct platform_driver bcma_sflash_driver = {
.probe = bcm47xxsflash_bcma_probe,
- .remove_new = bcm47xxsflash_bcma_remove,
+ .remove = bcm47xxsflash_bcma_remove,
.driver = {
.name = "bcma_sflash",
},
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index a2b643af7019..c93769c233d9 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -2075,7 +2075,7 @@ static struct platform_driver g3_driver = {
},
.suspend = docg3_suspend,
.resume = docg3_resume,
- .remove_new = docg3_release,
+ .remove = docg3_release,
};
module_platform_driver_probe(g3_driver, docg3_probe);
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 1bf192f229d7..f756c60a4931 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -399,7 +399,7 @@ static void phram_remove(struct platform_device *pdev)
static struct platform_driver phram_driver = {
.probe = phram_probe,
- .remove_new = phram_remove,
+ .remove = phram_remove,
.driver = {
.name = "phram",
.of_match_table = of_match_ptr(phram_of_match),
diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c
index 10cd1d9b4885..a12427d9e20f 100644
--- a/drivers/mtd/devices/powernv_flash.c
+++ b/drivers/mtd/devices/powernv_flash.c
@@ -286,7 +286,7 @@ static struct platform_driver powernv_flash_driver = {
.name = "powernv_flash",
.of_match_table = powernv_flash_match,
},
- .remove_new = powernv_flash_release,
+ .remove = powernv_flash_release,
.probe = powernv_flash_probe,
};
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
index 1574296d47e2..f02f96bff450 100644
--- a/drivers/mtd/devices/spear_smi.c
+++ b/drivers/mtd/devices/spear_smi.c
@@ -1093,7 +1093,7 @@ static struct platform_driver spear_smi_driver = {
.pm = &spear_smi_pm_ops,
},
.probe = spear_smi_probe,
- .remove_new = spear_smi_remove,
+ .remove = spear_smi_remove,
};
module_platform_driver(spear_smi_driver);
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c
index 3268de5fc780..dba584fa2a53 100644
--- a/drivers/mtd/devices/st_spi_fsm.c
+++ b/drivers/mtd/devices/st_spi_fsm.c
@@ -2132,7 +2132,7 @@ MODULE_DEVICE_TABLE(of, stfsm_match);
static struct platform_driver stfsm_driver = {
.probe = stfsm_probe,
- .remove_new = stfsm_remove,
+ .remove = stfsm_remove,
.driver = {
.name = "st-spi-fsm",
.of_match_table = stfsm_match,
diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c
index dbe3eb361cca..217f4e69233f 100644
--- a/drivers/mtd/hyperbus/hbmc-am654.c
+++ b/drivers/mtd/hyperbus/hbmc-am654.c
@@ -254,7 +254,7 @@ MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids);
static struct platform_driver am654_hbmc_platform_driver = {
.probe = am654_hbmc_probe,
- .remove_new = am654_hbmc_remove,
+ .remove = am654_hbmc_remove,
.driver = {
.name = "hbmc-am654",
.of_match_table = am654_hbmc_dt_ids,
diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c
index b22aa57119f2..f448e23f9260 100644
--- a/drivers/mtd/hyperbus/rpc-if.c
+++ b/drivers/mtd/hyperbus/rpc-if.c
@@ -163,9 +163,16 @@ static void rpcif_hb_remove(struct platform_device *pdev)
pm_runtime_disable(hyperbus->rpc.dev);
}
+static const struct platform_device_id rpc_if_hyperflash_id_table[] = {
+ { .name = "rpc-if-hyperflash" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, rpc_if_hyperflash_id_table);
+
static struct platform_driver rpcif_platform_driver = {
.probe = rpcif_hb_probe,
- .remove_new = rpcif_hb_remove,
+ .remove = rpcif_hb_remove,
+ .id_table = rpc_if_hyperflash_id_table,
.driver = {
.name = "rpc-if-hyperflash",
},
diff --git a/drivers/mtd/lpddr/lpddr2_nvm.c b/drivers/mtd/lpddr/lpddr2_nvm.c
index 9169e1155dbb..565b71f7fdd5 100644
--- a/drivers/mtd/lpddr/lpddr2_nvm.c
+++ b/drivers/mtd/lpddr/lpddr2_nvm.c
@@ -487,7 +487,7 @@ static struct platform_driver lpddr2_nvm_drv = {
.name = "lpddr2_nvm",
},
.probe = lpddr2_nvm_probe,
- .remove_new = lpddr2_nvm_remove,
+ .remove = lpddr2_nvm_remove,
};
module_platform_driver(lpddr2_nvm_drv);
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index 124b13c5d747..80d467eba92a 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -184,7 +184,7 @@ MODULE_DEVICE_TABLE(of, ltq_mtd_match);
static struct platform_driver ltq_mtd_driver = {
.probe = ltq_mtd_probe,
- .remove_new = ltq_mtd_remove,
+ .remove = ltq_mtd_remove,
.driver = {
.name = "ltq-nor",
.of_match_table = ltq_mtd_match,
diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c
index 96eb2e782c38..2bd7a1af898c 100644
--- a/drivers/mtd/maps/physmap-core.c
+++ b/drivers/mtd/maps/physmap-core.c
@@ -621,7 +621,7 @@ static void physmap_flash_shutdown(struct platform_device *dev)
static struct platform_driver physmap_flash_driver = {
.probe = physmap_flash_probe,
- .remove_new = physmap_flash_remove,
+ .remove = physmap_flash_remove,
.shutdown = physmap_flash_shutdown,
.driver = {
.name = "physmap-flash",
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 8b736f029f81..1c541eaf477a 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -205,7 +205,7 @@ MODULE_ALIAS("platform:mtd-ram");
static struct platform_driver platram_driver = {
.probe = platram_probe,
- .remove_new = platram_remove,
+ .remove = platram_remove,
.driver = {
.name = "mtd-ram",
},
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index f2a2d4706f1f..f27c25db6778 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -128,7 +128,7 @@ static struct platform_driver pxa2xx_flash_driver = {
.name = "pxa2xx-flash",
},
.probe = pxa2xx_flash_probe,
- .remove_new = pxa2xx_flash_remove,
+ .remove = pxa2xx_flash_remove,
.shutdown = pxa2xx_flash_shutdown,
};
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index ac8a0a19a021..6a54a84d0d9c 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -293,7 +293,7 @@ static void sa1100_mtd_remove(struct platform_device *pdev)
static struct platform_driver sa1100_mtd_driver = {
.probe = sa1100_mtd_probe,
- .remove_new = sa1100_mtd_remove,
+ .remove = sa1100_mtd_remove,
.driver = {
.name = "sa1100-mtd",
},
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index b69dade3f7ad..ea3aa026b55b 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -149,7 +149,7 @@ static struct platform_driver uflash_driver = {
.of_match_table = uflash_match,
},
.probe = uflash_probe,
- .remove_new = uflash_remove,
+ .remove = uflash_remove,
};
module_platform_driver(uflash_driver);
diff --git a/drivers/mtd/nand/ecc-mxic.c b/drivers/mtd/nand/ecc-mxic.c
index 47e10945b8d2..56b56f726b99 100644
--- a/drivers/mtd/nand/ecc-mxic.c
+++ b/drivers/mtd/nand/ecc-mxic.c
@@ -723,21 +723,21 @@ static int mxic_ecc_finish_io_req_pipelined(struct nand_device *nand,
return ret;
}
-static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
+static const struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
.init_ctx = mxic_ecc_init_ctx_external,
.cleanup_ctx = mxic_ecc_cleanup_ctx,
.prepare_io_req = mxic_ecc_prepare_io_req_external,
.finish_io_req = mxic_ecc_finish_io_req_external,
};
-static struct nand_ecc_engine_ops mxic_ecc_engine_pipelined_ops = {
+static const struct nand_ecc_engine_ops mxic_ecc_engine_pipelined_ops = {
.init_ctx = mxic_ecc_init_ctx_pipelined,
.cleanup_ctx = mxic_ecc_cleanup_ctx,
.prepare_io_req = mxic_ecc_prepare_io_req_pipelined,
.finish_io_req = mxic_ecc_finish_io_req_pipelined,
};
-struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
+const struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
{
return &mxic_ecc_engine_pipelined_ops;
}
@@ -869,7 +869,7 @@ static struct platform_driver mxic_ecc_driver = {
.of_match_table = mxic_ecc_of_ids,
},
.probe = mxic_ecc_probe,
- .remove_new = mxic_ecc_remove,
+ .remove = mxic_ecc_remove,
};
module_platform_driver(mxic_ecc_driver);
diff --git a/drivers/mtd/nand/ecc-sw-bch.c b/drivers/mtd/nand/ecc-sw-bch.c
index 405552d014a8..0d9310dd6f52 100644
--- a/drivers/mtd/nand/ecc-sw-bch.c
+++ b/drivers/mtd/nand/ecc-sw-bch.c
@@ -384,7 +384,7 @@ static int nand_ecc_sw_bch_finish_io_req(struct nand_device *nand,
return max_bitflips;
}
-static struct nand_ecc_engine_ops nand_ecc_sw_bch_engine_ops = {
+static const struct nand_ecc_engine_ops nand_ecc_sw_bch_engine_ops = {
.init_ctx = nand_ecc_sw_bch_init_ctx,
.cleanup_ctx = nand_ecc_sw_bch_cleanup_ctx,
.prepare_io_req = nand_ecc_sw_bch_prepare_io_req,
diff --git a/drivers/mtd/nand/ecc-sw-hamming.c b/drivers/mtd/nand/ecc-sw-hamming.c
index 254db2e7f8bb..f2d0effad9d2 100644
--- a/drivers/mtd/nand/ecc-sw-hamming.c
+++ b/drivers/mtd/nand/ecc-sw-hamming.c
@@ -638,7 +638,7 @@ static int nand_ecc_sw_hamming_finish_io_req(struct nand_device *nand,
return max_bitflips;
}
-static struct nand_ecc_engine_ops nand_ecc_sw_hamming_engine_ops = {
+static const struct nand_ecc_engine_ops nand_ecc_sw_hamming_engine_ops = {
.init_ctx = nand_ecc_sw_hamming_init_ctx,
.cleanup_ctx = nand_ecc_sw_hamming_cleanup_ctx,
.prepare_io_req = nand_ecc_sw_hamming_prepare_io_req,
diff --git a/drivers/mtd/nand/onenand/generic.c b/drivers/mtd/nand/onenand/generic.c
index 4e7de48f07a6..4e6fd1c34484 100644
--- a/drivers/mtd/nand/onenand/generic.c
+++ b/drivers/mtd/nand/onenand/generic.c
@@ -104,7 +104,7 @@ static struct platform_driver generic_onenand_driver = {
.name = DRIVER_NAME,
},
.probe = generic_onenand_probe,
- .remove_new = generic_onenand_remove,
+ .remove = generic_onenand_remove,
};
module_platform_driver(generic_onenand_driver);
diff --git a/drivers/mtd/nand/onenand/onenand_omap2.c b/drivers/mtd/nand/onenand/onenand_omap2.c
index a12f8f3efd07..f9a386b69050 100644
--- a/drivers/mtd/nand/onenand/onenand_omap2.c
+++ b/drivers/mtd/nand/onenand/onenand_omap2.c
@@ -593,7 +593,7 @@ MODULE_DEVICE_TABLE(of, omap2_onenand_id_table);
static struct platform_driver omap2_onenand_driver = {
.probe = omap2_onenand_probe,
- .remove_new = omap2_onenand_remove,
+ .remove = omap2_onenand_remove,
.shutdown = omap2_onenand_shutdown,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/mtd/nand/onenand/onenand_samsung.c b/drivers/mtd/nand/onenand/onenand_samsung.c
index fd6890a03d55..f37a6138e461 100644
--- a/drivers/mtd/nand/onenand/onenand_samsung.c
+++ b/drivers/mtd/nand/onenand/onenand_samsung.c
@@ -991,7 +991,7 @@ static struct platform_driver s3c_onenand_driver = {
},
.id_table = s3c_onenand_driver_ids,
.probe = s3c_onenand_probe,
- .remove_new = s3c_onenand_remove,
+ .remove = s3c_onenand_remove,
};
module_platform_driver(s3c_onenand_driver);
diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 919816a7aca7..fb2b7db70297 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -432,7 +432,7 @@ MODULE_DEVICE_TABLE(platform, gpio_nand_plat_id_table);
static struct platform_driver gpio_nand_driver = {
.probe = gpio_nand_probe,
- .remove_new = gpio_nand_remove,
+ .remove = gpio_nand_remove,
.id_table = gpio_nand_plat_id_table,
.driver = {
.name = "ams-delta-nand",
diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
index 5436ec4a8fde..db42aa0c7b6b 100644
--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
@@ -1500,7 +1500,7 @@ static struct platform_driver anfc_driver = {
.of_match_table = anfc_ids,
},
.probe = anfc_probe,
- .remove_new = anfc_remove,
+ .remove = anfc_remove,
};
module_platform_driver(anfc_driver);
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index f9ccfd02e804..dedcca87defc 100644
--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -2663,7 +2663,7 @@ static struct platform_driver atmel_nand_controller_driver = {
.pm = &atmel_nand_controller_pm_ops,
},
.probe = atmel_nand_controller_probe,
- .remove_new = atmel_nand_controller_remove,
+ .remove = atmel_nand_controller_remove,
};
module_platform_driver(atmel_nand_controller_driver);
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c
index 4d7dc8a9c373..a22aab4ed4e8 100644
--- a/drivers/mtd/nand/raw/atmel/pmecc.c
+++ b/drivers/mtd/nand/raw/atmel/pmecc.c
@@ -362,7 +362,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
size = ALIGN(size, sizeof(s32));
size += (req->ecc.strength + 1) * sizeof(s32) * 3;
- user = kzalloc(size, GFP_KERNEL);
+ user = devm_kzalloc(pmecc->dev, size, GFP_KERNEL);
if (!user)
return ERR_PTR(-ENOMEM);
@@ -408,12 +408,6 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
}
EXPORT_SYMBOL_GPL(atmel_pmecc_create_user);
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
-{
- kfree(user);
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user);
-
static int get_strength(struct atmel_pmecc_user *user)
{
const int *strengths = user->pmecc->caps->strengths;
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.h b/drivers/mtd/nand/raw/atmel/pmecc.h
index 7851c05126cf..cc0c5af1f4f1 100644
--- a/drivers/mtd/nand/raw/atmel/pmecc.h
+++ b/drivers/mtd/nand/raw/atmel/pmecc.h
@@ -55,8 +55,6 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *dev);
struct atmel_pmecc_user *
atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
struct atmel_pmecc_user_req *req);
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
-
void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
void atmel_pmecc_disable(struct atmel_pmecc_user *user);
diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c
index 063a5e0b8d4b..04d64724c400 100644
--- a/drivers/mtd/nand/raw/au1550nd.c
+++ b/drivers/mtd/nand/raw/au1550nd.c
@@ -357,7 +357,7 @@ static struct platform_driver au1550nd_driver = {
.name = "au1550-nand",
},
.probe = au1550nd_probe,
- .remove_new = au1550nd_remove,
+ .remove = au1550nd_remove,
};
module_platform_driver(au1550nd_driver);
diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/main.c b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
index ebcf508e0606..4d4e185c22e5 100644
--- a/drivers/mtd/nand/raw/bcm47xxnflash/main.c
+++ b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
@@ -70,7 +70,7 @@ static void bcm47xxnflash_remove(struct platform_device *pdev)
static struct platform_driver bcm47xxnflash_driver = {
.probe = bcm47xxnflash_probe,
- .remove_new = bcm47xxnflash_remove,
+ .remove = bcm47xxnflash_remove,
.driver = {
.name = "bcma_nflash",
},
diff --git a/drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c
index 05b7b653bdf3..a06cd87f839a 100644
--- a/drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c
@@ -117,7 +117,7 @@ MODULE_DEVICE_TABLE(of, bcm6368_nand_of_match);
static struct platform_driver bcm6368_nand_driver = {
.probe = bcm6368_nand_probe,
- .remove_new = brcmnand_remove,
+ .remove = brcmnand_remove,
.driver = {
.name = "bcm6368_nand",
.pm = &brcmnand_pm_ops,
diff --git a/drivers/mtd/nand/raw/brcmnand/bcma_nand.c b/drivers/mtd/nand/raw/brcmnand/bcma_nand.c
index 4e7e435ba339..dd27977919fb 100644
--- a/drivers/mtd/nand/raw/brcmnand/bcma_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/bcma_nand.c
@@ -119,7 +119,7 @@ static int brcmnand_bcma_nand_probe(struct platform_device *pdev)
static struct platform_driver brcmnand_bcma_nand_driver = {
.probe = brcmnand_bcma_nand_probe,
- .remove_new = brcmnand_remove,
+ .remove = brcmnand_remove,
.driver = {
.name = "bcma_brcmnand",
.pm = &brcmnand_pm_ops,
diff --git a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c
index ea534850b97a..c31d7f37dc52 100644
--- a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c
@@ -112,7 +112,7 @@ MODULE_DEVICE_TABLE(of, bcmbca_nand_of_match);
static struct platform_driver bcmbca_nand_driver = {
.probe = bcmbca_nand_probe,
- .remove_new = brcmnand_remove,
+ .remove = brcmnand_remove,
.driver = {
.name = "bcmbca_nand",
.pm = &brcmnand_pm_ops,
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index 1b2ec0fec60c..9c253a511e45 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -1561,7 +1561,7 @@ static int write_oob_to_regs(struct brcmnand_controller *ctrl, int i,
(oob[j + 2] << 8) |
(oob[j + 3] << 0));
- /* handle the remaing bytes */
+ /* handle the remaining bytes */
while (j < tbytes)
plast[k++] = oob[j++];
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c b/drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c
index 558f083b92e9..950923d977b7 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c
@@ -23,7 +23,7 @@ static int brcmstb_nand_probe(struct platform_device *pdev)
static struct platform_driver brcmstb_nand_driver = {
.probe = brcmstb_nand_probe,
- .remove_new = brcmnand_remove,
+ .remove = brcmnand_remove,
.driver = {
.name = "brcmstb_nand",
.pm = &brcmnand_pm_ops,
diff --git a/drivers/mtd/nand/raw/brcmnand/iproc_nand.c b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
index bf46c8b85898..089c70fc6edf 100644
--- a/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
@@ -134,7 +134,7 @@ MODULE_DEVICE_TABLE(of, iproc_nand_of_match);
static struct platform_driver iproc_nand_driver = {
.probe = iproc_nand_probe,
- .remove_new = brcmnand_remove,
+ .remove = brcmnand_remove,
.driver = {
.name = "iproc_nand",
.pm = &brcmnand_pm_ops,
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index 3bc89b356963..8d1d710e439d 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -1891,7 +1891,7 @@ static int cadence_nand_read_buf(struct cdns_nand_ctrl *cdns_ctrl,
int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
- /* read alingment data */
+ /* read alignment data */
if (data_dma_width == 4)
ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words);
#ifdef CONFIG_64BIT
@@ -3055,7 +3055,7 @@ static void cadence_nand_dt_remove(struct platform_device *ofdev)
static struct platform_driver cadence_nand_dt_driver = {
.probe = cadence_nand_dt_probe,
- .remove_new = cadence_nand_dt_remove,
+ .remove = cadence_nand_dt_remove,
.driver = {
.name = "cadence-nand-controller",
.of_match_table = cadence_nand_dt_ids,
diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c
index f0a15717cf05..341318024a19 100644
--- a/drivers/mtd/nand/raw/cs553x_nand.c
+++ b/drivers/mtd/nand/raw/cs553x_nand.c
@@ -26,7 +26,7 @@
#define NR_CS553X_CONTROLLERS 4
-#define MSR_DIVIL_GLD_CAP 0x51400000 /* DIVIL capabilitiies */
+#define MSR_DIVIL_GLD_CAP 0x51400000 /* DIVIL capabilities */
#define CAP_CS5535 0x2df000ULL
#define CAP_CS5536 0x5df500ULL
diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 392678143a36..1f8354acfb50 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -10,15 +10,15 @@
* Dirk Behme <Dirk.Behme@gmail.com>
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/iopoll.h>
-#include <linux/mtd/rawnand.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/mtd/partitions.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
-#include <linux/of.h>
#define NRCSR_OFFSET 0x00
#define NANDFCR_OFFSET 0x60
@@ -487,10 +487,10 @@ static const struct of_device_id davinci_nand_of_match[] = {
};
MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
-static struct davinci_nand_pdata
- *nand_davinci_get_pdata(struct platform_device *pdev)
+static struct davinci_nand_pdata *
+nand_davinci_get_pdata(struct platform_device *pdev)
{
- if (!dev_get_platdata(&pdev->dev) && pdev->dev.of_node) {
+ if (!dev_get_platdata(&pdev->dev)) {
struct davinci_nand_pdata *pdata;
const char *mode;
u32 prop;
@@ -501,23 +501,24 @@ static struct davinci_nand_pdata
pdev->dev.platform_data = pdata;
if (!pdata)
return ERR_PTR(-ENOMEM);
- if (!of_property_read_u32(pdev->dev.of_node,
- "ti,davinci-chipselect", &prop))
+ if (!device_property_read_u32(&pdev->dev,
+ "ti,davinci-chipselect", &prop))
pdata->core_chipsel = prop;
else
return ERR_PTR(-EINVAL);
- if (!of_property_read_u32(pdev->dev.of_node,
- "ti,davinci-mask-ale", &prop))
+ if (!device_property_read_u32(&pdev->dev,
+ "ti,davinci-mask-ale", &prop))
pdata->mask_ale = prop;
- if (!of_property_read_u32(pdev->dev.of_node,
- "ti,davinci-mask-cle", &prop))
+ if (!device_property_read_u32(&pdev->dev,
+ "ti,davinci-mask-cle", &prop))
pdata->mask_cle = prop;
- if (!of_property_read_u32(pdev->dev.of_node,
- "ti,davinci-mask-chipsel", &prop))
+ if (!device_property_read_u32(&pdev->dev,
+ "ti,davinci-mask-chipsel", &prop))
pdata->mask_chipsel = prop;
- if (!of_property_read_string(pdev->dev.of_node,
- "ti,davinci-ecc-mode", &mode)) {
+ if (!device_property_read_string(&pdev->dev,
+ "ti,davinci-ecc-mode",
+ &mode)) {
if (!strncmp("none", mode, 4))
pdata->engine_type = NAND_ECC_ENGINE_TYPE_NONE;
if (!strncmp("soft", mode, 4))
@@ -525,16 +526,17 @@ static struct davinci_nand_pdata
if (!strncmp("hw", mode, 2))
pdata->engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
}
- if (!of_property_read_u32(pdev->dev.of_node,
- "ti,davinci-ecc-bits", &prop))
+ if (!device_property_read_u32(&pdev->dev,
+ "ti,davinci-ecc-bits", &prop))
pdata->ecc_bits = prop;
- if (!of_property_read_u32(pdev->dev.of_node,
- "ti,davinci-nand-buswidth", &prop) && prop == 16)
+ if (!device_property_read_u32(&pdev->dev,
+ "ti,davinci-nand-buswidth",
+ &prop) && prop == 16)
pdata->options |= NAND_BUSWIDTH_16;
- if (of_property_read_bool(pdev->dev.of_node,
- "ti,davinci-nand-use-bbt"))
+ if (device_property_read_bool(&pdev->dev,
+ "ti,davinci-nand-use-bbt"))
pdata->bbt_options = NAND_BBT_USE_FLASH;
/*
@@ -548,17 +550,15 @@ static struct davinci_nand_pdata
* then use "ti,davinci-nand" as the compatible in your
* device-tree file.
*/
- if (of_device_is_compatible(pdev->dev.of_node,
- "ti,keystone-nand")) {
+ if (device_is_compatible(&pdev->dev, "ti,keystone-nand"))
pdata->options |= NAND_NO_SUBPAGE_WRITE;
- }
}
return dev_get_platdata(&pdev->dev);
}
#else
-static struct davinci_nand_pdata
- *nand_davinci_get_pdata(struct platform_device *pdev)
+static struct davinci_nand_pdata *
+nand_davinci_get_pdata(struct platform_device *pdev)
{
return dev_get_platdata(&pdev->dev);
}
@@ -901,7 +901,7 @@ static void nand_davinci_remove(struct platform_device *pdev)
static struct platform_driver nand_davinci_driver = {
.probe = nand_davinci_probe,
- .remove_new = nand_davinci_remove,
+ .remove = nand_davinci_remove,
.driver = {
.name = "davinci_nand",
.of_match_table = of_match_ptr(davinci_nand_of_match),
diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c
index 2f5666511fda..e0dd59bba4bd 100644
--- a/drivers/mtd/nand/raw/denali_dt.c
+++ b/drivers/mtd/nand/raw/denali_dt.c
@@ -225,7 +225,7 @@ static void denali_dt_remove(struct platform_device *pdev)
static struct platform_driver denali_dt_driver = {
.probe = denali_dt_probe,
- .remove_new = denali_dt_remove,
+ .remove = denali_dt_remove,
.driver = {
.name = "denali-nand-dt",
.of_match_table = denali_nand_dt_ids,
diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
index df6a0d5c86bb..03dbe37df021 100644
--- a/drivers/mtd/nand/raw/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
@@ -999,7 +999,7 @@ static struct platform_driver fsl_elbc_nand_driver = {
.of_match_table = fsl_elbc_nand_match,
},
.probe = fsl_elbc_nand_probe,
- .remove_new = fsl_elbc_nand_remove,
+ .remove = fsl_elbc_nand_remove,
};
module_platform_driver(fsl_elbc_nand_driver);
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index f0e2318ce088..7be95d0be248 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -1130,7 +1130,7 @@ static struct platform_driver fsl_ifc_nand_driver = {
.of_match_table = fsl_ifc_nand_match,
},
.probe = fsl_ifc_nand_probe,
- .remove_new = fsl_ifc_nand_remove,
+ .remove = fsl_ifc_nand_remove,
};
module_platform_driver(fsl_ifc_nand_driver);
diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
index 315e9d2b573d..f4dc990a8da1 100644
--- a/drivers/mtd/nand/raw/fsl_upm.c
+++ b/drivers/mtd/nand/raw/fsl_upm.c
@@ -259,7 +259,7 @@ static struct platform_driver of_fun_driver = {
.of_match_table = of_fun_match,
},
.probe = fun_probe,
- .remove_new = fun_remove,
+ .remove = fun_remove,
};
module_platform_driver(of_fun_driver);
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 811982da3557..d579d5dd60d6 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -1221,7 +1221,7 @@ static const struct of_device_id fsmc_nand_id_table[] = {
MODULE_DEVICE_TABLE(of, fsmc_nand_id_table);
static struct platform_driver fsmc_nand_driver = {
- .remove_new = fsmc_nand_remove,
+ .remove = fsmc_nand_remove,
.driver = {
.name = "fsmc-nand",
.of_match_table = fsmc_nand_id_table,
diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c
index d6cc2cb65214..69e5e43532a4 100644
--- a/drivers/mtd/nand/raw/gpio.c
+++ b/drivers/mtd/nand/raw/gpio.c
@@ -392,7 +392,7 @@ out_ce:
static struct platform_driver gpio_nand_driver = {
.probe = gpio_nand_probe,
- .remove_new = gpio_nand_remove,
+ .remove = gpio_nand_remove,
.driver = {
.name = "gpio-nand",
.of_match_table = of_match_ptr(gpio_nand_id_table),
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index e1b515304e3c..d76802944453 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -15,6 +15,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/dma/mxs-dma.h>
#include "gpmi-nand.h"
#include "gpmi-regs.h"
@@ -737,9 +738,8 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
if (ret)
return ret;
- ret = pm_runtime_get_sync(this->dev);
+ ret = pm_runtime_resume_and_get(this->dev);
if (ret < 0) {
- pm_runtime_put_autosuspend(this->dev);
return ret;
}
@@ -2761,15 +2761,9 @@ static int gpmi_nand_probe(struct platform_device *pdev)
if (ret)
goto exit_acquire_resources;
- ret = __gpmi_enable_clk(this, true);
- if (ret)
- goto exit_acquire_resources;
-
+ pm_runtime_enable(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
ret = gpmi_init(this);
if (ret)
@@ -2779,15 +2773,12 @@ static int gpmi_nand_probe(struct platform_device *pdev)
if (ret)
goto exit_nfc_init;
- pm_runtime_mark_last_busy(&pdev->dev);
- pm_runtime_put_autosuspend(&pdev->dev);
-
dev_info(this->dev, "driver registered.\n");
return 0;
exit_nfc_init:
- pm_runtime_put(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
release_resources(this);
exit_acquire_resources:
@@ -2801,23 +2792,23 @@ static void gpmi_nand_remove(struct platform_device *pdev)
struct nand_chip *chip = &this->nand;
int ret;
- pm_runtime_put_sync(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
-
ret = mtd_device_unregister(nand_to_mtd(chip));
WARN_ON(ret);
nand_cleanup(chip);
gpmi_free_dma_buffer(this);
release_resources(this);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
}
-#ifdef CONFIG_PM_SLEEP
static int gpmi_pm_suspend(struct device *dev)
{
- struct gpmi_nand_data *this = dev_get_drvdata(dev);
+ int ret;
- release_dma_channels(this);
- return 0;
+ pinctrl_pm_select_sleep_state(dev);
+ ret = pm_runtime_force_suspend(dev);
+
+ return ret;
}
static int gpmi_pm_resume(struct device *dev)
@@ -2825,9 +2816,13 @@ static int gpmi_pm_resume(struct device *dev)
struct gpmi_nand_data *this = dev_get_drvdata(dev);
int ret;
- ret = acquire_dma_channels(this);
- if (ret < 0)
+ ret = pm_runtime_force_resume(dev);
+ if (ret) {
+ dev_err(this->dev, "Error in resume %d\n", ret);
return ret;
+ }
+
+ pinctrl_pm_select_default_state(dev);
/* re-init the GPMI registers */
ret = gpmi_init(this);
@@ -2849,35 +2844,45 @@ static int gpmi_pm_resume(struct device *dev)
return 0;
}
-#endif /* CONFIG_PM_SLEEP */
-static int __maybe_unused gpmi_runtime_suspend(struct device *dev)
+#define gpmi_enable_clk(x) __gpmi_enable_clk(x, true)
+#define gpmi_disable_clk(x) __gpmi_enable_clk(x, false)
+
+static int gpmi_runtime_suspend(struct device *dev)
{
struct gpmi_nand_data *this = dev_get_drvdata(dev);
- return __gpmi_enable_clk(this, false);
+ gpmi_disable_clk(this);
+
+ return 0;
}
-static int __maybe_unused gpmi_runtime_resume(struct device *dev)
+static int gpmi_runtime_resume(struct device *dev)
{
struct gpmi_nand_data *this = dev_get_drvdata(dev);
+ int ret;
+
+ ret = gpmi_enable_clk(this);
+ if (ret)
+ return ret;
+
+ return 0;
- return __gpmi_enable_clk(this, true);
}
static const struct dev_pm_ops gpmi_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume)
- SET_RUNTIME_PM_OPS(gpmi_runtime_suspend, gpmi_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume)
+ RUNTIME_PM_OPS(gpmi_runtime_suspend, gpmi_runtime_resume, NULL)
};
static struct platform_driver gpmi_nand_driver = {
.driver = {
.name = "gpmi-nand",
- .pm = &gpmi_pm_ops,
+ .pm = pm_ptr(&gpmi_pm_ops),
.of_match_table = gpmi_nand_id_table,
},
- .probe = gpmi_nand_probe,
- .remove_new = gpmi_nand_remove,
+ .probe = gpmi_nand_probe,
+ .remove = gpmi_nand_remove,
};
module_platform_driver(gpmi_nand_driver);
diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c
index fe291a2e5c77..d97270ec1185 100644
--- a/drivers/mtd/nand/raw/hisi504_nand.c
+++ b/drivers/mtd/nand/raw/hisi504_nand.c
@@ -858,7 +858,7 @@ static struct platform_driver hisi_nfc_driver = {
.pm = &hisi_nfc_pm_ops,
},
.probe = hisi_nfc_probe,
- .remove_new = hisi_nfc_remove,
+ .remove = hisi_nfc_remove,
};
module_platform_driver(hisi_nfc_driver);
diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
index 0e7dd9ca4b2b..47dc3efcee92 100644
--- a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
+++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
@@ -549,7 +549,7 @@ MODULE_DEVICE_TABLE(of, ingenic_nand_dt_match);
static struct platform_driver ingenic_nand_driver = {
.probe = ingenic_nand_probe,
- .remove_new = ingenic_nand_remove,
+ .remove = ingenic_nand_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = ingenic_nand_dt_match,
diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c
index f0f0522b2fa2..01cefdaf115d 100644
--- a/drivers/mtd/nand/raw/intel-nand-controller.c
+++ b/drivers/mtd/nand/raw/intel-nand-controller.c
@@ -728,7 +728,7 @@ MODULE_DEVICE_TABLE(of, ebu_nand_match);
static struct platform_driver ebu_nand_driver = {
.probe = ebu_nand_probe,
- .remove_new = ebu_nand_remove,
+ .remove = ebu_nand_remove,
.driver = {
.name = "intel-nand-controller",
.of_match_table = ebu_nand_match,
diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index b9c3adc54c01..19b13ae536d4 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -891,7 +891,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
static struct platform_driver lpc32xx_nand_driver = {
.probe = lpc32xx_nand_probe,
- .remove_new = lpc32xx_nand_remove,
+ .remove = lpc32xx_nand_remove,
.resume = pm_ptr(lpc32xx_nand_resume),
.suspend = pm_ptr(lpc32xx_nand_suspend),
.driver = {
diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index ade971e4cc3b..b54d76547ffb 100644
--- a/drivers/mtd/nand/raw/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
@@ -1010,7 +1010,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
static struct platform_driver lpc32xx_nand_driver = {
.probe = lpc32xx_nand_probe,
- .remove_new = lpc32xx_nand_remove,
+ .remove = lpc32xx_nand_remove,
.resume = pm_ptr(lpc32xx_nand_resume),
.suspend = pm_ptr(lpc32xx_nand_suspend),
.driver = {
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index aa113a5d88c8..303b3016a070 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -3183,7 +3183,7 @@ static struct platform_driver marvell_nfc_driver = {
},
.id_table = marvell_nfc_platform_ids,
.probe = marvell_nfc_probe,
- .remove_new = marvell_nfc_remove,
+ .remove = marvell_nfc_remove,
};
module_platform_driver(marvell_nfc_driver);
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index fbb06aa305cb..b8834aa96e81 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -1621,7 +1621,7 @@ static void meson_nfc_remove(struct platform_device *pdev)
static struct platform_driver meson_nfc_driver = {
.probe = meson_nfc_probe,
- .remove_new = meson_nfc_remove,
+ .remove = meson_nfc_remove,
.driver = {
.name = "meson-nand",
.of_match_table = meson_nfc_id_table,
diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c
index 215610f808f1..97b4e7f3e1bb 100644
--- a/drivers/mtd/nand/raw/mpc5121_nfc.c
+++ b/drivers/mtd/nand/raw/mpc5121_nfc.c
@@ -835,7 +835,7 @@ MODULE_DEVICE_TABLE(of, mpc5121_nfc_match);
static struct platform_driver mpc5121_nfc_driver = {
.probe = mpc5121_nfc_probe,
- .remove_new = mpc5121_nfc_remove,
+ .remove = mpc5121_nfc_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = mpc5121_nfc_match,
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index 586868b4139f..21c7e1102746 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -1640,7 +1640,7 @@ static SIMPLE_DEV_PM_OPS(mtk_nfc_pm_ops, mtk_nfc_suspend, mtk_nfc_resume);
static struct platform_driver mtk_nfc_driver = {
.probe = mtk_nfc_probe,
- .remove_new = mtk_nfc_remove,
+ .remove = mtk_nfc_remove,
.driver = {
.name = MTK_NAME,
.of_match_table = mtk_nfc_id_table,
diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
index 736808150e74..8c56b685bf91 100644
--- a/drivers/mtd/nand/raw/mxc_nand.c
+++ b/drivers/mtd/nand/raw/mxc_nand.c
@@ -1824,7 +1824,7 @@ static struct platform_driver mxcnd_driver = {
.of_match_table = mxcnd_dt_ids,
},
.probe = mxcnd_probe,
- .remove_new = mxcnd_remove,
+ .remove = mxcnd_remove,
};
module_platform_driver(mxcnd_driver);
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
index be8050e84b4f..92de26697359 100644
--- a/drivers/mtd/nand/raw/mxic_nand.c
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -574,7 +574,7 @@ MODULE_DEVICE_TABLE(of, mxic_nfc_of_ids);
static struct platform_driver mxic_nfc_driver = {
.probe = mxic_nfc_probe,
- .remove_new = mxic_nfc_remove,
+ .remove = mxic_nfc_remove,
.driver = {
.name = "mxic-nfc",
.of_match_table = mxic_nfc_of_ids,
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index e229de32ff50..03237310852c 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -113,7 +113,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
rand_otp = of_property_read_bool(dn, "mxic,enable-randomizer-otp");
mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
- /* Subpage write is prohibited in randomizer operatoin */
+ /* Subpage write is prohibited in randomizer operation */
if (rand_otp && chip->options & NAND_NO_SUBPAGE_WRITE &&
mxic->reliability_func & MACRONIX_RANDOMIZER_BIT) {
if (p->supports_set_get_features) {
diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c
index 3bb32a7c6d67..13365128194d 100644
--- a/drivers/mtd/nand/raw/ndfc.c
+++ b/drivers/mtd/nand/raw/ndfc.c
@@ -266,7 +266,7 @@ static struct platform_driver ndfc_driver = {
.of_match_table = ndfc_match,
},
.probe = ndfc_probe,
- .remove_new = ndfc_remove,
+ .remove = ndfc_remove,
};
module_platform_driver(ndfc_driver);
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index cf76afc6c0ed..d9141f3c0dd1 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -2291,7 +2291,7 @@ MODULE_DEVICE_TABLE(of, omap_nand_ids);
static struct platform_driver omap_nand_driver = {
.probe = omap_nand_probe,
- .remove_new = omap_nand_remove,
+ .remove = omap_nand_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = omap_nand_ids,
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c
index 4a97d4a76454..c1d19b8e6715 100644
--- a/drivers/mtd/nand/raw/omap_elm.c
+++ b/drivers/mtd/nand/raw/omap_elm.c
@@ -560,7 +560,7 @@ static struct platform_driver elm_driver = {
.pm = &elm_pm_ops,
},
.probe = elm_probe,
- .remove_new = elm_remove,
+ .remove = elm_remove,
};
module_platform_driver(elm_driver);
diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c
index 2951d81614fd..47e80d5e58c5 100644
--- a/drivers/mtd/nand/raw/orion_nand.c
+++ b/drivers/mtd/nand/raw/orion_nand.c
@@ -214,7 +214,7 @@ MODULE_DEVICE_TABLE(of, orion_nand_of_match_table);
#endif
static struct platform_driver orion_nand_driver = {
- .remove_new = orion_nand_remove,
+ .remove = orion_nand_remove,
.driver = {
.name = "orion_nand",
.of_match_table = of_match_ptr(orion_nand_of_match_table),
diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
index 19b2c9d25863..0b1f7670660e 100644
--- a/drivers/mtd/nand/raw/pasemi_nand.c
+++ b/drivers/mtd/nand/raw/pasemi_nand.c
@@ -237,7 +237,7 @@ static struct platform_driver pasemi_nand_driver =
.of_match_table = pasemi_nand_match,
},
.probe = pasemi_nand_probe,
- .remove_new = pasemi_nand_remove,
+ .remove = pasemi_nand_remove,
};
module_platform_driver(pasemi_nand_driver);
diff --git a/drivers/mtd/nand/raw/pl35x-nand-controller.c b/drivers/mtd/nand/raw/pl35x-nand-controller.c
index 2570fd0beea0..09440ed4652e 100644
--- a/drivers/mtd/nand/raw/pl35x-nand-controller.c
+++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c
@@ -187,7 +187,7 @@ static const struct mtd_ooblayout_ops pl35x_ecc_ooblayout16_ops = {
.free = pl35x_ecc_ooblayout16_free,
};
-/* Generic flash bbt decriptors */
+/* Generic flash bbt descriptors */
static u8 bbt_pattern[] = { 'B', 'b', 't', '0' };
static u8 mirror_pattern[] = { '1', 't', 'b', 'B' };
@@ -1184,7 +1184,7 @@ MODULE_DEVICE_TABLE(of, pl35x_nand_of_match);
static struct platform_driver pl35x_nandc_driver = {
.probe = pl35x_nand_probe,
- .remove_new = pl35x_nand_remove,
+ .remove = pl35x_nand_remove,
.driver = {
.name = PL35X_NANDC_DRIVER_NAME,
.of_match_table = pl35x_nand_of_match,
diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
index b5c374b51ecd..0bcd455328ef 100644
--- a/drivers/mtd/nand/raw/plat_nand.c
+++ b/drivers/mtd/nand/raw/plat_nand.c
@@ -144,7 +144,7 @@ MODULE_DEVICE_TABLE(of, plat_nand_match);
static struct platform_driver plat_nand_driver = {
.probe = plat_nand_probe,
- .remove_new = plat_nand_remove,
+ .remove = plat_nand_remove,
.driver = {
.name = "gen_nand",
.of_match_table = plat_nand_match,
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index b8cff9240b28..636bba2528bf 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -3535,8 +3535,8 @@ static struct platform_driver qcom_nandc_driver = {
.name = "qcom-nandc",
.of_match_table = qcom_nandc_of_match,
},
- .probe = qcom_nandc_probe,
- .remove_new = qcom_nandc_remove,
+ .probe = qcom_nandc_probe,
+ .remove = qcom_nandc_remove,
};
module_platform_driver(qcom_nandc_driver);
diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c
index ed0cf732d20e..b07c2f8b4035 100644
--- a/drivers/mtd/nand/raw/r852.c
+++ b/drivers/mtd/nand/raw/r852.c
@@ -335,7 +335,7 @@ static void r852_cmdctl(struct nand_chip *chip, int dat, unsigned int ctrl)
else
dev->ctlreg &= ~R852_CTL_WRITE;
- /* when write is stareted, enable write access */
+ /* when write is started, enable write access */
if (dat == NAND_CMD_ERASE1)
dev->ctlreg |= R852_CTL_WRITE;
@@ -372,7 +372,7 @@ static int r852_wait(struct nand_chip *chip)
nand_status_op(chip, &status);
- /* Unfortunelly, no way to send detailed error status... */
+ /* Unfortunately, no way to send detailed error status... */
if (dev->dma_error) {
status |= NAND_STATUS_FAIL;
dev->dma_error = 0;
diff --git a/drivers/mtd/nand/raw/renesas-nand-controller.c b/drivers/mtd/nand/raw/renesas-nand-controller.c
index 0e92d50c5249..44f6603736d1 100644
--- a/drivers/mtd/nand/raw/renesas-nand-controller.c
+++ b/drivers/mtd/nand/raw/renesas-nand-controller.c
@@ -1402,7 +1402,7 @@ static struct platform_driver rnandc_driver = {
.of_match_table = rnandc_id_table,
},
.probe = rnandc_probe,
- .remove_new = rnandc_remove,
+ .remove = rnandc_remove,
};
module_platform_driver(rnandc_driver);
diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c
index 51c9cf9013dc..63e7b9e39a5a 100644
--- a/drivers/mtd/nand/raw/rockchip-nand-controller.c
+++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c
@@ -1477,7 +1477,7 @@ static const struct dev_pm_ops rk_nfc_pm_ops = {
static struct platform_driver rk_nfc_driver = {
.probe = rk_nfc_probe,
- .remove_new = rk_nfc_remove,
+ .remove = rk_nfc_remove,
.driver = {
.name = "rockchip-nfc",
.of_match_table = rk_nfc_id_table,
diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index 48c1d0eb66ca..229f2e87d56e 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -1213,7 +1213,7 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
static struct platform_driver s3c24xx_nand_driver = {
.probe = s3c24xx_nand_probe,
- .remove_new = s3c24xx_nand_remove,
+ .remove = s3c24xx_nand_remove,
.suspend = s3c24xx_nand_suspend,
.resume = s3c24xx_nand_resume,
.id_table = s3c24xx_driver_ids,
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index 2a8164efb273..97f733e481ff 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -1216,7 +1216,7 @@ static void flctl_remove(struct platform_device *pdev)
static struct platform_driver flctl_driver = {
.probe = flctl_probe,
- .remove_new = flctl_remove,
+ .remove = flctl_remove,
.driver = {
.name = "sh_flctl",
.of_match_table = of_flctl_match,
diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
index 2402dc5465d5..142e93b200a3 100644
--- a/drivers/mtd/nand/raw/sharpsl.c
+++ b/drivers/mtd/nand/raw/sharpsl.c
@@ -234,7 +234,7 @@ static struct platform_driver sharpsl_nand_driver = {
.name = "sharpsl-nand",
},
.probe = sharpsl_nand_probe,
- .remove_new = sharpsl_nand_remove,
+ .remove = sharpsl_nand_remove,
};
module_platform_driver(sharpsl_nand_driver);
diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
index 24f52a30fb13..e238784c8c3e 100644
--- a/drivers/mtd/nand/raw/sm_common.c
+++ b/drivers/mtd/nand/raw/sm_common.c
@@ -52,8 +52,8 @@ static const struct mtd_ooblayout_ops oob_sm_ops = {
.free = oob_sm_ooblayout_free,
};
-/* NOTE: This layout is not compatabable with SmartMedia, */
-/* because the 256 byte devices have page depenent oob layout */
+/* NOTE: This layout is not compatible with SmartMedia, */
+/* because the 256 byte devices have page dependent oob layout */
/* However it does preserve the bad block markers */
/* If you use smftl, it will bypass this and work correctly */
/* If you not, then you break SmartMedia compliance anyway */
diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c
index 76d50eb9f1db..668584683ce5 100644
--- a/drivers/mtd/nand/raw/socrates_nand.c
+++ b/drivers/mtd/nand/raw/socrates_nand.c
@@ -231,7 +231,7 @@ static struct platform_driver socrates_nand_driver = {
.of_match_table = socrates_nand_match,
},
.probe = socrates_nand_probe,
- .remove_new = socrates_nand_remove,
+ .remove = socrates_nand_remove,
};
module_platform_driver(socrates_nand_driver);
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 0f67e96cc240..a960403081f1 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -2147,7 +2147,7 @@ MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match);
static struct platform_driver stm32_fmc2_nfc_driver = {
.probe = stm32_fmc2_nfc_probe,
- .remove_new = stm32_fmc2_nfc_remove,
+ .remove = stm32_fmc2_nfc_remove,
.driver = {
.name = "stm32_fmc2_nfc",
.of_match_table = stm32_fmc2_nfc_match,
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index c28634e20abf..fab371e3e9b7 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -2196,7 +2196,7 @@ static struct platform_driver sunxi_nfc_driver = {
.of_match_table = sunxi_nfc_ids,
},
.probe = sunxi_nfc_probe,
- .remove_new = sunxi_nfc_remove,
+ .remove = sunxi_nfc_remove,
};
module_platform_driver(sunxi_nfc_driver);
diff --git a/drivers/mtd/nand/raw/technologic-nand-controller.c b/drivers/mtd/nand/raw/technologic-nand-controller.c
index 0e45a6fd91dd..a3294aaf43bd 100644
--- a/drivers/mtd/nand/raw/technologic-nand-controller.c
+++ b/drivers/mtd/nand/raw/technologic-nand-controller.c
@@ -213,7 +213,7 @@ static struct platform_driver ts72xx_nand_driver = {
.of_match_table = ts72xx_id_table,
},
.probe = ts72xx_nand_probe,
- .remove_new = ts72xx_nand_remove,
+ .remove = ts72xx_nand_remove,
};
module_platform_driver(ts72xx_nand_driver);
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c
index a553e3ac8ff4..7f9eb5f042a7 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -1279,7 +1279,7 @@ static struct platform_driver tegra_nand_driver = {
.pm = &tegra_nand_pm,
},
.probe = tegra_nand_probe,
- .remove_new = tegra_nand_remove,
+ .remove = tegra_nand_remove,
};
module_platform_driver(tegra_nand_driver);
diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index 37f79c019a72..907fb5de4269 100644
--- a/drivers/mtd/nand/raw/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
@@ -405,7 +405,7 @@ static int txx9ndfmc_resume(struct platform_device *dev)
static struct platform_driver txx9ndfmc_driver = {
.probe = txx9ndfmc_probe,
- .remove_new = txx9ndfmc_remove,
+ .remove = txx9ndfmc_remove,
.resume = txx9ndfmc_resume,
.driver = {
.name = "txx9ndfmc",
diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
index f31d23219f91..4b5ba3187853 100644
--- a/drivers/mtd/nand/raw/vf610_nfc.c
+++ b/drivers/mtd/nand/raw/vf610_nfc.c
@@ -941,7 +941,7 @@ static struct platform_driver vf610_nfc_driver = {
.pm = &vf610_nfc_pm_ops,
},
.probe = vf610_nfc_probe,
- .remove_new = vf610_nfc_remove,
+ .remove = vf610_nfc_remove,
};
module_platform_driver(vf610_nfc_driver);
diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
index 008549011fb9..af84395dc66e 100644
--- a/drivers/mtd/nand/raw/xway_nand.c
+++ b/drivers/mtd/nand/raw/xway_nand.c
@@ -256,7 +256,7 @@ static const struct of_device_id xway_nand_match[] = {
static struct platform_driver xway_nand_driver = {
.probe = xway_nand_probe,
- .remove_new = xway_nand_remove,
+ .remove = xway_nand_remove,
.driver = {
.name = "lantiq,nand-xway",
.of_match_table = xway_nand_match,
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 4d76f9f71a0e..b1df7f627161 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -337,7 +337,7 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
return ret;
}
-static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
+static const struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
.init_ctx = spinand_ondie_ecc_init_ctx,
.cleanup_ctx = spinand_ondie_ecc_cleanup_ctx,
.prepare_io_req = spinand_ondie_ecc_prepare_io_req,
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index f3bb81d7e460..7180e615ac97 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -161,17 +161,18 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
}
static const struct spinand_info winbond_spinand_table[] = {
- SPINAND_INFO("W25M02GV",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
- NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
+ /* 512M-bit densities */
+ SPINAND_INFO("W25N512GW", /* 1.8V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x20),
+ NAND_MEMORG(1, 2048, 64, 64, 512, 10, 1, 1, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
- SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
- SPINAND_SELECT_TARGET(w25m02gv_select_target)),
- SPINAND_INFO("W25N01GV",
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+ /* 1G-bit densities */
+ SPINAND_INFO("W25N01GV", /* 3.3V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(1, 512),
@@ -180,52 +181,63 @@ static const struct spinand_info winbond_spinand_table[] = {
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
- SPINAND_INFO("W25N01KV",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
- NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1),
- NAND_ECCREQ(4, 512),
+ SPINAND_INFO("W25N01GW", /* 1.8V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x21),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
- SPINAND_ECCINFO(&w25n01kv_ooblayout, w25n02kv_ecc_get_status)),
- SPINAND_INFO("W25N02KV",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
- NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
- NAND_ECCREQ(8, 512),
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+ SPINAND_INFO("W25N01JW", /* high-speed 1.8V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbc, 0x21),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
- SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
- SPINAND_INFO("W25N01JW",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbc, 0x21),
- NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+ SPINAND_INFO("W25N01KV", /* 3.3V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
+ NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
- SPINAND_ECCINFO(&w25m02gv_ooblayout, w25n02kv_ecc_get_status)),
- SPINAND_INFO("W25N02JWZEIF",
+ SPINAND_ECCINFO(&w25n01kv_ooblayout, w25n02kv_ecc_get_status)),
+ /* 2G-bit densities */
+ SPINAND_INFO("W25M02GV", /* 2x1G-bit 3.3V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
+ SPINAND_SELECT_TARGET(w25m02gv_select_target)),
+ SPINAND_INFO("W25N02JW", /* high-speed 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbf, 0x22),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 2, 1),
- NAND_ECCREQ(4, 512),
+ NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
- SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
- SPINAND_INFO("W25N512GW",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x20),
- NAND_MEMORG(1, 2048, 64, 64, 512, 10, 1, 1, 1),
- NAND_ECCREQ(4, 512),
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+ SPINAND_INFO("W25N02KV", /* 3.3V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
- SPINAND_INFO("W25N02KWZEIR",
+ SPINAND_INFO("W25N02KW", /* 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x22),
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
NAND_ECCREQ(8, 512),
@@ -234,18 +246,19 @@ static const struct spinand_info winbond_spinand_table[] = {
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
- SPINAND_INFO("W25N01GWZEIG",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x21),
- NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
- NAND_ECCREQ(4, 512),
+ /* 4G-bit densities */
+ SPINAND_INFO("W25N04KV", /* 3.3V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
+ NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
+ NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
- SPINAND_ECCINFO(&w25m02gv_ooblayout, w25n02kv_ecc_get_status)),
- SPINAND_INFO("W25N04KV",
- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
- NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
+ SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
+ SPINAND_INFO("W25N04KW", /* 1.8V */
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x23),
+ NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
diff --git a/drivers/mtd/spi-nor/controllers/hisi-sfc.c b/drivers/mtd/spi-nor/controllers/hisi-sfc.c
index 89a7f0bbc4b3..db948da2c4c5 100644
--- a/drivers/mtd/spi-nor/controllers/hisi-sfc.c
+++ b/drivers/mtd/spi-nor/controllers/hisi-sfc.c
@@ -488,7 +488,7 @@ static struct platform_driver hisi_spi_nor_driver = {
.of_match_table = hisi_spi_nor_dt_ids,
},
.probe = hisi_spi_nor_probe,
- .remove_new = hisi_spi_nor_remove,
+ .remove = hisi_spi_nor_remove,
};
module_platform_driver(hisi_spi_nor_driver);
diff --git a/drivers/mtd/spi-nor/controllers/nxp-spifi.c b/drivers/mtd/spi-nor/controllers/nxp-spifi.c
index 5aee62f51031..1a92d71755db 100644
--- a/drivers/mtd/spi-nor/controllers/nxp-spifi.c
+++ b/drivers/mtd/spi-nor/controllers/nxp-spifi.c
@@ -446,7 +446,7 @@ MODULE_DEVICE_TABLE(of, nxp_spifi_match);
static struct platform_driver nxp_spifi_driver = {
.probe = nxp_spifi_probe,
- .remove_new = nxp_spifi_remove,
+ .remove = nxp_spifi_remove,
.driver = {
.name = "nxp-spifi",
.of_match_table = nxp_spifi_match,
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 9d6e85bf227b..66949d9f0cc5 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -89,7 +89,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto);
if (op->dummy.nbytes)
- op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto);
+ op->dummy.buswidth = spi_nor_get_protocol_data_nbits(proto);
if (op->data.nbytes)
op->data.buswidth = spi_nor_get_protocol_data_nbits(proto);
@@ -113,6 +113,9 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
op->cmd.opcode = (op->cmd.opcode << 8) | ext;
op->cmd.nbytes = 2;
}
+
+ if (proto == SNOR_PROTO_8_8_8_DTR && nor->flags & SNOR_F_SWAP16)
+ op->data.swap16 = true;
}
/**
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 1516b6d0dc37..5c33740ed7f5 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -140,6 +140,7 @@ enum spi_nor_option_flags {
SNOR_F_RWW = BIT(14),
SNOR_F_ECC = BIT(15),
SNOR_F_NO_WP = BIT(16),
+ SNOR_F_SWAP16 = BIT(17),
};
struct spi_nor_read_command {
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index ea6be95e75a5..830da21eea08 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -8,6 +8,23 @@
#include "core.h"
+#define MXIC_NOR_OP_RD_CR2 0x71 /* Read configuration register 2 opcode */
+#define MXIC_NOR_OP_WR_CR2 0x72 /* Write configuration register 2 opcode */
+#define MXIC_NOR_ADDR_CR2_MODE 0x00000000 /* CR2 address for setting spi/sopi/dopi mode */
+#define MXIC_NOR_ADDR_CR2_DC 0x00000300 /* CR2 address for setting dummy cycles */
+#define MXIC_NOR_REG_DOPI_EN 0x2 /* Enable Octal DTR */
+#define MXIC_NOR_REG_SPI_EN 0x0 /* Enable SPI */
+
+/* Convert dummy cycles to bit pattern */
+#define MXIC_NOR_REG_DC(p) \
+ ((20 - (p)) >> 1)
+
+#define MXIC_NOR_WR_CR2(addr, ndata, buf) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(MXIC_NOR_OP_WR_CR2, 0), \
+ SPI_MEM_OP_ADDR(4, addr, 0), \
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
+
static int
mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
@@ -182,9 +199,88 @@ static const struct flash_info macronix_nor_parts[] = {
.name = "mx25l3255e",
.size = SZ_4M,
.no_sfdp_flags = SECT_4K,
- }
+ },
+ /*
+ * This spares us of adding new flash entries for flashes that can be
+ * initialized solely based on the SFDP data, but still need the
+ * manufacturer hooks to set parameters that can't be discovered at SFDP
+ * parsing time.
+ */
+ { .id = SNOR_ID(0xc2) }
};
+static int macronix_nor_octal_dtr_en(struct spi_nor *nor)
+{
+ struct spi_mem_op op;
+ u8 *buf = nor->bouncebuf, i;
+ int ret;
+
+ /* Use dummy cycles which is parse by SFDP and convert to bit pattern. */
+ buf[0] = MXIC_NOR_REG_DC(nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].num_wait_states);
+ op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_DC, 1, buf);
+ ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
+ if (ret)
+ return ret;
+
+ /* Set the octal and DTR enable bits. */
+ buf[0] = MXIC_NOR_REG_DOPI_EN;
+ op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 1, buf);
+ ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
+ if (ret)
+ return ret;
+
+ /* Read flash ID to make sure the switch was successful. */
+ ret = spi_nor_read_id(nor, 4, 4, buf, SNOR_PROTO_8_8_8_DTR);
+ if (ret) {
+ dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
+ return ret;
+ }
+
+ /* Macronix SPI-NOR flash 8D-8D-8D read ID would get 6 bytes data A-A-B-B-C-C */
+ for (i = 0; i < nor->info->id->len; i++)
+ if (buf[i * 2] != buf[(i * 2) + 1] || buf[i * 2] != nor->info->id->bytes[i])
+ return -EINVAL;
+
+ return 0;
+}
+
+static int macronix_nor_octal_dtr_dis(struct spi_nor *nor)
+{
+ struct spi_mem_op op;
+ u8 *buf = nor->bouncebuf;
+ int ret;
+
+ /*
+ * The register is 1-byte wide, but 1-byte transactions are not
+ * allowed in 8D-8D-8D mode. Since there is no register at the
+ * next location, just initialize the value to 0 and let the
+ * transaction go on.
+ */
+ buf[0] = MXIC_NOR_REG_SPI_EN;
+ buf[1] = 0x0;
+ op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 2, buf);
+ ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
+ if (ret)
+ return ret;
+
+ /* Read flash ID to make sure the switch was successful. */
+ ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
+ if (ret) {
+ dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
+ return ret;
+ }
+
+ if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int macronix_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
+{
+ return enable ? macronix_nor_octal_dtr_en(nor) : macronix_nor_octal_dtr_dis(nor);
+}
+
static void macronix_nor_default_init(struct spi_nor *nor)
{
nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
@@ -194,6 +290,7 @@ static int macronix_nor_late_init(struct spi_nor *nor)
{
if (!nor->params->set_4byte_addr_mode)
nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
+ nor->params->set_octal_dtr = macronix_nor_set_octal_dtr;
return 0;
}
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 5b1117265bd2..21727f9a4ac6 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -671,6 +671,10 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return -EOPNOTSUPP;
}
+ /* Byte order in 8D-8D-8D mode */
+ if (bfpt.dwords[SFDP_DWORD(18)] & BFPT_DWORD18_BYTE_ORDER_SWAPPED)
+ nor->flags |= SNOR_F_SWAP16;
+
return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt);
}
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
index da0fe5aa9bb0..f74a0eb339ea 100644
--- a/drivers/mtd/spi-nor/sfdp.h
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -130,6 +130,7 @@ struct sfdp_bfpt {
#define BFPT_DWORD18_CMD_EXT_INV (0x1UL << 29) /* Invert */
#define BFPT_DWORD18_CMD_EXT_RES (0x2UL << 29) /* Reserved */
#define BFPT_DWORD18_CMD_EXT_16B (0x3UL << 29) /* 16-bit opcode */
+#define BFPT_DWORD18_BYTE_ORDER_SWAPPED BIT(31) /* Byte order swapped in 8D-8D-8D mode */
struct sfdp_parameter_header {
u8 id_lsb;
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index d6c92595f6bc..5a88a6096ca8 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -106,6 +106,7 @@ static int cypress_nor_sr_ready_and_clear_reg(struct spi_nor *nor, u64 addr)
int ret;
if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
+ op.addr.nbytes = nor->addr_nbytes;
op.dummy.nbytes = params->rdsr_dummy;
op.data.nbytes = 2;
}
diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c
index 96064e4babf0..5e9eb268073d 100644
--- a/drivers/mtd/spi-nor/sysfs.c
+++ b/drivers/mtd/spi-nor/sysfs.c
@@ -87,7 +87,7 @@ static umode_t spi_nor_sysfs_is_visible(struct kobject *kobj,
}
static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj,
- struct bin_attribute *attr, int n)
+ const struct bin_attribute *attr, int n)
{
struct spi_device *spi = to_spi_device(kobj_to_dev(kobj));
struct spi_mem *spimem = spi_get_drvdata(spi);
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index 9f7ce5763e71..8d0a00d69e12 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -129,6 +129,7 @@ static const struct flash_info winbond_nor_parts[] = {
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
}, {
.id = SNOR_ID(0xef, 0x40, 0x18),
+ /* Flavors w/ and w/o SFDP. */
.name = "w25q128",
.size = SZ_16M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
diff --git a/drivers/mtd/tests/oobtest.c b/drivers/mtd/tests/oobtest.c
index 13fed398937e..e1ee68f8b8f8 100644
--- a/drivers/mtd/tests/oobtest.c
+++ b/drivers/mtd/tests/oobtest.c
@@ -17,7 +17,7 @@
#include <linux/mtd/mtd.h>
#include <linux/slab.h>
#include <linux/sched.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include "mtd_test.h"
diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c
index 8eb40b6e6dfa..6878700d2fc0 100644
--- a/drivers/mtd/tests/pagetest.c
+++ b/drivers/mtd/tests/pagetest.c
@@ -17,7 +17,7 @@
#include <linux/mtd/mtd.h>
#include <linux/slab.h>
#include <linux/sched.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include "mtd_test.h"
diff --git a/drivers/mtd/tests/subpagetest.c b/drivers/mtd/tests/subpagetest.c
index 05250a080139..f34bbf033c4d 100644
--- a/drivers/mtd/tests/subpagetest.c
+++ b/drivers/mtd/tests/subpagetest.c
@@ -15,7 +15,7 @@
#include <linux/mtd/mtd.h>
#include <linux/slab.h>
#include <linux/sched.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include "mtd_test.h"
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index ae5abe492b52..adc47b87b38a 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1447,7 +1447,7 @@ out_ech:
return err;
}
-static struct ubi_attach_info *alloc_ai(void)
+static struct ubi_attach_info *alloc_ai(const char *slab_name)
{
struct ubi_attach_info *ai;
@@ -1461,7 +1461,7 @@ static struct ubi_attach_info *alloc_ai(void)
INIT_LIST_HEAD(&ai->alien);
INIT_LIST_HEAD(&ai->fastmap);
ai->volumes = RB_ROOT;
- ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
+ ai->aeb_slab_cache = kmem_cache_create(slab_name,
sizeof(struct ubi_ainf_peb),
0, 0, NULL);
if (!ai->aeb_slab_cache) {
@@ -1491,7 +1491,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
err = -ENOMEM;
- scan_ai = alloc_ai();
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_fastmap");
if (!scan_ai)
goto out;
@@ -1557,7 +1557,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
int err;
struct ubi_attach_info *ai;
- ai = alloc_ai();
+ ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
@@ -1575,7 +1575,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (err > 0 || mtd_is_eccerr(err)) {
if (err != UBI_NO_FASTMAP) {
destroy_ai(ai);
- ai = alloc_ai();
+ ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
@@ -1614,7 +1614,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) {
struct ubi_attach_info *scan_ai;
- scan_ai = alloc_ai();
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_dbg_chk_fastmap");
if (!scan_ai) {
err = -ENOMEM;
goto out_wl;
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
index 2a9cc9413c42..9bdb6525f128 100644
--- a/drivers/mtd/ubi/fastmap-wl.c
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -346,14 +346,27 @@ out:
* WL sub-system.
*
* @ubi: UBI device description object
+ * @need_fill: whether to fill wear-leveling pool when no PEBs are found
*/
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
+ bool need_fill)
{
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
int pnum;
- if (pool->used == pool->size)
+ if (pool->used == pool->size) {
+ if (need_fill && !ubi->fm_work_scheduled) {
+ /*
+ * We cannot update the fastmap here because this
+ * function is called in atomic context.
+ * Let's fail here and refill/update it as soon as
+ * possible.
+ */
+ ubi->fm_work_scheduled = 1;
+ schedule_work(&ubi->fm_work);
+ }
return NULL;
+ }
pnum = pool->pebs[pool->used];
return ubi->lookuptbl[pnum];
@@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
if (!ubi->used.rb_node)
return false;
- e = next_peb_for_wl(ubi);
+ e = next_peb_for_wl(ubi, false);
if (!e) {
if (!ubi->free.rb_node)
return false;
diff --git a/drivers/mtd/ubi/nvmem.c b/drivers/mtd/ubi/nvmem.c
index a94a1a9aaec1..34f8c1d3cdee 100644
--- a/drivers/mtd/ubi/nvmem.c
+++ b/drivers/mtd/ubi/nvmem.c
@@ -55,7 +55,7 @@ static int ubi_nvmem_reg_read(void *priv, unsigned int from,
if (err)
return err;
- return bytes_left == 0 ? 0 : -EIO;
+ return 0;
}
static int ubi_nvmem_add(struct ubi_volume_info *vi)
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 1c9e874e8ede..26cc53ad34ec 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -549,6 +549,7 @@ struct ubi_debug_info {
* @peb_buf: a buffer of PEB size used for different purposes
* @buf_mutex: protects @peb_buf
* @ckvol_mutex: serializes static volume checking when opening
+ * @wl_reboot_notifier: close all wear-leveling work before reboot
*
* @dbg: debugging information for this UBI device
*/
@@ -651,6 +652,7 @@ struct ubi_device {
void *peb_buf;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
+ struct notifier_block wl_reboot_notifier;
struct ubi_debug_info dbg;
};
@@ -831,7 +833,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
struct ubi_attach_info *ai);
int ubi_attach(struct ubi_device *ubi, int force_scan);
-void ubi_destroy_ai(struct ubi_attach_info *ai);
/* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 5a3558bbb903..e5cf3bdca3b0 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -143,8 +143,10 @@ static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol)
vol->vol_id != volid)
continue;
+ fwnode_handle_put(fw_vols);
return fw_vol;
}
+ fwnode_handle_put(fw_vols);
return NULL;
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a357f3d27f2f..4f6f339d8fb8 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -89,6 +89,7 @@
#include <linux/crc32.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
+#include <linux/reboot.h>
#include "ubi.h"
#include "wl.h"
@@ -127,6 +128,8 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
struct ubi_wl_entry *e, struct rb_root *root);
static int self_check_in_pq(const struct ubi_device *ubi,
struct ubi_wl_entry *e);
+static int ubi_wl_reboot_notifier(struct notifier_block *n,
+ unsigned long state, void *cmd);
/**
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -683,7 +686,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi_assert(!ubi->move_to_put);
#ifdef CONFIG_MTD_UBI_FASTMAP
- if (!next_peb_for_wl(ubi) ||
+ if (!next_peb_for_wl(ubi, true) ||
#else
if (!ubi->free.rb_node ||
#endif
@@ -846,7 +849,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
goto out_not_moved;
}
if (err == MOVE_RETRY) {
- scrubbing = 1;
+ /*
+ * For source PEB:
+ * 1. The scrubbing is set for scrub type PEB, it will
+ * be put back into ubi->scrub list.
+ * 2. Non-scrub type PEB will be put back into ubi->used
+ * list.
+ */
+ keep = 1;
dst_leb_clean = 1;
goto out_not_moved;
}
@@ -1943,6 +1953,13 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (!ubi->ro_mode && !ubi->fm_disabled)
ubi_ensure_anchor_pebs(ubi);
#endif
+
+ if (!ubi->wl_reboot_notifier.notifier_call) {
+ ubi->wl_reboot_notifier.notifier_call = ubi_wl_reboot_notifier;
+ ubi->wl_reboot_notifier.priority = 1; /* Higher than MTD */
+ register_reboot_notifier(&ubi->wl_reboot_notifier);
+ }
+
return 0;
out_free:
@@ -1988,6 +2005,17 @@ void ubi_wl_close(struct ubi_device *ubi)
kfree(ubi->lookuptbl);
}
+static int ubi_wl_reboot_notifier(struct notifier_block *n,
+ unsigned long state, void *cmd)
+{
+ struct ubi_device *ubi;
+
+ ubi = container_of(n, struct ubi_device, wl_reboot_notifier);
+ ubi_wl_close(ubi);
+
+ return NOTIFY_DONE;
+}
+
/**
* self_check_ec - make sure that the erase counter of a PEB is correct.
* @ubi: UBI device description object
diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h
index 7b6715ef6d4a..a69169c35e31 100644
--- a/drivers/mtd/ubi/wl.h
+++ b/drivers/mtd/ubi/wl.h
@@ -5,7 +5,8 @@
static void update_fastmap_work_fn(struct work_struct *wrk);
static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi);
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
+ bool need_fill);
static bool need_wear_leveling(struct ubi_device *ubi);
static void ubi_fastmap_close(struct ubi_device *ubi);
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9920b3a68ed1..1fd5acdc73c6 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -641,6 +641,7 @@ config NETDEVSIM
depends on PTP_1588_CLOCK_MOCK || PTP_1588_CLOCK_MOCK=n
select NET_DEVLINK
select PAGE_POOL
+ select NET_SHAPER
help
This driver is a developer testing tool and software model that can
be used to test various control path networking APIs, especially
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index 0433a0f36d1b..98c6205ed19f 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -3206,15 +3206,11 @@ static int amt_newlink(struct net *net, struct net_device *dev,
goto err;
}
- if (data[IFLA_AMT_RELAY_PORT])
- amt->relay_port = nla_get_be16(data[IFLA_AMT_RELAY_PORT]);
- else
- amt->relay_port = htons(IANA_AMT_UDP_PORT);
+ amt->relay_port = nla_get_be16_default(data[IFLA_AMT_RELAY_PORT],
+ htons(IANA_AMT_UDP_PORT));
- if (data[IFLA_AMT_GATEWAY_PORT])
- amt->gw_port = nla_get_be16(data[IFLA_AMT_GATEWAY_PORT]);
- else
- amt->gw_port = htons(IANA_AMT_UDP_PORT);
+ amt->gw_port = nla_get_be16_default(data[IFLA_AMT_GATEWAY_PORT],
+ htons(IANA_AMT_UDP_PORT));
if (!amt->relay_port) {
NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_DISCOVERY_IP],
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index e057526448d7..a2abfade82dd 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -84,7 +84,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
if (skb_copy_bits(skb, BAREUDP_BASE_HLEN, &ipversion,
sizeof(ipversion))) {
- DEV_STATS_INC(bareudp->dev, rx_dropped);
+ dev_core_stats_rx_dropped_inc(bareudp->dev);
goto drop;
}
ipversion >>= 4;
@@ -94,7 +94,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
} else if (ipversion == 6 && bareudp->multi_proto_mode) {
proto = htons(ETH_P_IPV6);
} else {
- DEV_STATS_INC(bareudp->dev, rx_dropped);
+ dev_core_stats_rx_dropped_inc(bareudp->dev);
goto drop;
}
} else if (bareudp->ethertype == htons(ETH_P_MPLS_UC)) {
@@ -108,7 +108,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
ipv4_is_multicast(tunnel_hdr->daddr)) {
proto = htons(ETH_P_MPLS_MC);
} else {
- DEV_STATS_INC(bareudp->dev, rx_dropped);
+ dev_core_stats_rx_dropped_inc(bareudp->dev);
goto drop;
}
} else {
@@ -124,7 +124,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
(addr_type & IPV6_ADDR_MULTICAST)) {
proto = htons(ETH_P_MPLS_MC);
} else {
- DEV_STATS_INC(bareudp->dev, rx_dropped);
+ dev_core_stats_rx_dropped_inc(bareudp->dev);
goto drop;
}
}
@@ -136,7 +136,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
proto,
!net_eq(bareudp->net,
dev_net(bareudp->dev)))) {
- DEV_STATS_INC(bareudp->dev, rx_dropped);
+ dev_core_stats_rx_dropped_inc(bareudp->dev);
goto drop;
}
@@ -144,7 +144,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
tun_dst = udp_tun_rx_dst(skb, family, key, 0, 0);
if (!tun_dst) {
- DEV_STATS_INC(bareudp->dev, rx_dropped);
+ dev_core_stats_rx_dropped_inc(bareudp->dev);
goto drop;
}
skb_dst_set(skb, &tun_dst->dst);
@@ -317,7 +317,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,
__be32 saddr;
int err;
- if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
+ if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
return -EINVAL;
if (!sock)
@@ -387,7 +387,7 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
__be16 sport;
int err;
- if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
+ if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
return -EINVAL;
if (!sock)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b1bffd8e9a95..49dd4fe195e5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1008,6 +1008,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
if (bond->dev->flags & IFF_UP)
bond_hw_addr_flush(bond->dev, old_active->dev);
+
+ bond_slave_ns_maddrs_add(bond, old_active);
}
if (new_active) {
@@ -1024,6 +1026,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
dev_mc_sync(new_active->dev, bond->dev);
netif_addr_unlock_bh(bond->dev);
}
+
+ bond_slave_ns_maddrs_del(bond, new_active);
}
}
@@ -1476,7 +1480,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
slave_disable_netpoll(slave);
}
-static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
+static int bond_netpoll_setup(struct net_device *dev)
{
struct bonding *bond = netdev_priv(dev);
struct list_head *iter;
@@ -1545,6 +1549,7 @@ static void bond_compute_features(struct bonding *bond)
{
unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
IFF_XMIT_DST_RELEASE_PERM;
+ netdev_features_t gso_partial_features = NETIF_F_GSO_ESP;
netdev_features_t vlan_features = BOND_VLAN_FEATURES;
netdev_features_t enc_features = BOND_ENC_FEATURES;
#ifdef CONFIG_XFRM_OFFLOAD
@@ -1577,6 +1582,9 @@ static void bond_compute_features(struct bonding *bond)
BOND_XFRM_FEATURES);
#endif /* CONFIG_XFRM_OFFLOAD */
+ if (slave->dev->hw_enc_features & NETIF_F_GSO_PARTIAL)
+ gso_partial_features &= slave->dev->gso_partial_features;
+
mpls_features = netdev_increment_features(mpls_features,
slave->dev->mpls_features,
BOND_MPLS_FEATURES);
@@ -1590,6 +1598,11 @@ static void bond_compute_features(struct bonding *bond)
}
bond_dev->hard_header_len = max_hard_header_len;
+ if (gso_partial_features & NETIF_F_GSO_ESP)
+ bond_dev->gso_partial_features |= NETIF_F_GSO_ESP;
+ else
+ bond_dev->gso_partial_features &= ~NETIF_F_GSO_ESP;
+
done:
bond_dev->vlan_features = vlan_features;
bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
@@ -2341,6 +2354,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
bond_compute_features(bond);
bond_set_carrier(bond);
+ /* Needs to be called before bond_select_active_slave(), which will
+ * remove the maddrs if the slave is selected as active slave.
+ */
+ bond_slave_ns_maddrs_add(bond, new_slave);
+
if (bond_uses_primary(bond)) {
block_netpoll_tx();
bond_select_active_slave(bond);
@@ -2350,7 +2368,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
if (bond_mode_can_use_xmit_hash(bond))
bond_update_slave_arr(bond, NULL);
-
if (!slave_dev->netdev_ops->ndo_bpf ||
!slave_dev->netdev_ops->ndo_xdp_xmit) {
if (bond->xdp_prog) {
@@ -2548,6 +2565,12 @@ static int __bond_release_one(struct net_device *bond_dev,
if (oldcurrent == slave)
bond_change_active_slave(bond, NULL);
+ /* Must be called after bond_change_active_slave () as the slave
+ * might change from an active slave to a backup slave. Then it is
+ * necessary to clear the maddrs on the backup slave.
+ */
+ bond_slave_ns_maddrs_del(bond, slave);
+
if (bond_is_lb(bond)) {
/* Must be called only after the slave has been
* detached from the list and the curr_active_slave
@@ -5676,8 +5699,11 @@ static int bond_xdp_set(struct net_device *dev, struct bpf_prog *prog,
ASSERT_RTNL();
- if (!bond_xdp_check(bond))
+ if (!bond_xdp_check(bond)) {
+ BOND_NL_ERR(dev, extack,
+ "No native XDP support for the current bonding mode");
return -EOPNOTSUPP;
+ }
old_prog = bond->xdp_prog;
bond->xdp_prog = prog;
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 95d59a18c022..327b6ecdc77e 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -15,6 +15,7 @@
#include <linux/sched/signal.h>
#include <net/bonding.h>
+#include <net/ndisc.h>
static int bond_option_active_slave_set(struct bonding *bond,
const struct bond_opt_value *newval);
@@ -1234,6 +1235,68 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond,
}
#if IS_ENABLED(CONFIG_IPV6)
+static bool slave_can_set_ns_maddr(const struct bonding *bond, struct slave *slave)
+{
+ return BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP &&
+ !bond_is_active_slave(slave) &&
+ slave->dev->flags & IFF_MULTICAST;
+}
+
+static void slave_set_ns_maddrs(struct bonding *bond, struct slave *slave, bool add)
+{
+ struct in6_addr *targets = bond->params.ns_targets;
+ char slot_maddr[MAX_ADDR_LEN];
+ int i;
+
+ if (!slave_can_set_ns_maddr(bond, slave))
+ return;
+
+ for (i = 0; i < BOND_MAX_NS_TARGETS; i++) {
+ if (ipv6_addr_any(&targets[i]))
+ break;
+
+ if (!ndisc_mc_map(&targets[i], slot_maddr, slave->dev, 0)) {
+ if (add)
+ dev_mc_add(slave->dev, slot_maddr);
+ else
+ dev_mc_del(slave->dev, slot_maddr);
+ }
+ }
+}
+
+void bond_slave_ns_maddrs_add(struct bonding *bond, struct slave *slave)
+{
+ if (!bond->params.arp_validate)
+ return;
+ slave_set_ns_maddrs(bond, slave, true);
+}
+
+void bond_slave_ns_maddrs_del(struct bonding *bond, struct slave *slave)
+{
+ if (!bond->params.arp_validate)
+ return;
+ slave_set_ns_maddrs(bond, slave, false);
+}
+
+static void slave_set_ns_maddr(struct bonding *bond, struct slave *slave,
+ struct in6_addr *target, struct in6_addr *slot)
+{
+ char target_maddr[MAX_ADDR_LEN], slot_maddr[MAX_ADDR_LEN];
+
+ if (!bond->params.arp_validate || !slave_can_set_ns_maddr(bond, slave))
+ return;
+
+ /* remove the previous maddr from slave */
+ if (!ipv6_addr_any(slot) &&
+ !ndisc_mc_map(slot, slot_maddr, slave->dev, 0))
+ dev_mc_del(slave->dev, slot_maddr);
+
+ /* add new maddr on slave if target is set */
+ if (!ipv6_addr_any(target) &&
+ !ndisc_mc_map(target, target_maddr, slave->dev, 0))
+ dev_mc_add(slave->dev, target_maddr);
+}
+
static void _bond_options_ns_ip6_target_set(struct bonding *bond, int slot,
struct in6_addr *target,
unsigned long last_rx)
@@ -1243,8 +1306,10 @@ static void _bond_options_ns_ip6_target_set(struct bonding *bond, int slot,
struct slave *slave;
if (slot >= 0 && slot < BOND_MAX_NS_TARGETS) {
- bond_for_each_slave(bond, slave, iter)
+ bond_for_each_slave(bond, slave, iter) {
slave->target_last_arp_rx[slot] = last_rx;
+ slave_set_ns_maddr(bond, slave, target, &targets[slot]);
+ }
targets[slot] = *target;
}
}
@@ -1296,15 +1361,30 @@ static int bond_option_ns_ip6_targets_set(struct bonding *bond,
{
return -EPERM;
}
+
+static void slave_set_ns_maddrs(struct bonding *bond, struct slave *slave, bool add) {}
+
+void bond_slave_ns_maddrs_add(struct bonding *bond, struct slave *slave) {}
+
+void bond_slave_ns_maddrs_del(struct bonding *bond, struct slave *slave) {}
#endif
static int bond_option_arp_validate_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
+ bool changed = !!bond->params.arp_validate != !!newval->value;
+ struct list_head *iter;
+ struct slave *slave;
+
netdev_dbg(bond->dev, "Setting arp_validate to %s (%llu)\n",
newval->string, newval->value);
bond->params.arp_validate = newval->value;
+ if (changed) {
+ bond_for_each_slave(bond, slave, iter)
+ slave_set_ns_maddrs(bond, slave, !!bond->params.arp_validate);
+ }
+
return 0;
}
diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c
index c63f7fc1e691..511615dc3341 100644
--- a/drivers/net/can/c_can/c_can_main.c
+++ b/drivers/net/can/c_can/c_can_main.c
@@ -1011,7 +1011,6 @@ static int c_can_handle_bus_err(struct net_device *dev,
/* common for all type of bus errors */
priv->can.can_stats.bus_error++;
- stats->rx_errors++;
/* propagate the error condition to the CAN stack */
skb = alloc_can_err_skb(dev, &cf);
@@ -1027,26 +1026,32 @@ static int c_can_handle_bus_err(struct net_device *dev,
case LEC_STUFF_ERROR:
netdev_dbg(dev, "stuff error\n");
cf->data[2] |= CAN_ERR_PROT_STUFF;
+ stats->rx_errors++;
break;
case LEC_FORM_ERROR:
netdev_dbg(dev, "form error\n");
cf->data[2] |= CAN_ERR_PROT_FORM;
+ stats->rx_errors++;
break;
case LEC_ACK_ERROR:
netdev_dbg(dev, "ack error\n");
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+ stats->tx_errors++;
break;
case LEC_BIT1_ERROR:
netdev_dbg(dev, "bit1 error\n");
cf->data[2] |= CAN_ERR_PROT_BIT1;
+ stats->tx_errors++;
break;
case LEC_BIT0_ERROR:
netdev_dbg(dev, "bit0 error\n");
cf->data[2] |= CAN_ERR_PROT_BIT0;
+ stats->tx_errors++;
break;
case LEC_CRC_ERROR:
netdev_dbg(dev, "CRC error\n");
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+ stats->rx_errors++;
break;
default:
break;
diff --git a/drivers/net/can/cc770/Kconfig b/drivers/net/can/cc770/Kconfig
index 467ef19de1c1..aae25c2f849e 100644
--- a/drivers/net/can/cc770/Kconfig
+++ b/drivers/net/can/cc770/Kconfig
@@ -7,7 +7,7 @@ if CAN_CC770
config CAN_CC770_ISA
tristate "ISA Bus based legacy CC770 driver"
- depends on ISA
+ depends on HAS_IOPORT
help
This driver adds legacy support for CC770 and AN82527 chips
connected to the ISA bus using I/O port, memory mapped or
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index a978b960f1f1..16e9e7d7527d 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1765,7 +1765,8 @@ static int m_can_close(struct net_device *dev)
netif_stop_queue(dev);
m_can_stop(dev);
- free_irq(dev->irq, dev);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
m_can_clean(dev);
diff --git a/drivers/net/can/rockchip/Kconfig b/drivers/net/can/rockchip/Kconfig
index e029e2a3ca4b..d203c530551f 100644
--- a/drivers/net/can/rockchip/Kconfig
+++ b/drivers/net/can/rockchip/Kconfig
@@ -2,7 +2,8 @@
config CAN_ROCKCHIP_CANFD
tristate "Rockchip CAN-FD controller"
- depends on OF || COMPILE_TEST
+ depends on OF
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
select CAN_RX_OFFLOAD
help
Say Y here if you want to use CAN-FD controller found on
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 01168db4c106..2f516cc6d22c 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -87,7 +87,7 @@ config CAN_PLX_PCI
config CAN_SJA1000_ISA
tristate "ISA Bus based legacy SJA1000 driver"
- depends on ISA
+ depends on HAS_IOPORT
help
This driver adds legacy support for SJA1000 chips connected to
the ISA bus using I/O port, memory mapped or indirect access.
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index e684991fa391..7209a831f0f2 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -2,7 +2,7 @@
//
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
-// Copyright (c) 2019, 2020, 2021 Pengutronix,
+// Copyright (c) 2019, 2020, 2021, 2024 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
//
// Based on:
@@ -483,9 +483,11 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
};
const struct ethtool_coalesce ec = {
.rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq,
- .rx_max_coalesced_frames_irq = priv->rx_obj_num_coalesce_irq,
+ .rx_max_coalesced_frames_irq = priv->rx_obj_num_coalesce_irq == 0 ?
+ 1 : priv->rx_obj_num_coalesce_irq,
.tx_coalesce_usecs_irq = priv->tx_coalesce_usecs_irq,
- .tx_max_coalesced_frames_irq = priv->tx_obj_num_coalesce_irq,
+ .tx_max_coalesced_frames_irq = priv->tx_obj_num_coalesce_irq == 0 ?
+ 1 : priv->tx_obj_num_coalesce_irq,
};
struct can_ram_layout layout;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
index f732556d233a..d3ac865933fd 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
@@ -16,9 +16,9 @@
#include "mcp251xfd.h"
-static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta)
+static inline bool mcp251xfd_tx_fifo_sta_empty(u32 fifo_sta)
{
- return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
+ return fifo_sta & MCP251XFD_REG_FIFOSTA_TFERFFIF;
}
static inline int
@@ -122,7 +122,11 @@ mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
if (err)
return err;
- if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) {
+ /* If the chip says the TX-FIFO is empty, but there are no TX
+ * buffers free in the ring, we assume all have been sent.
+ */
+ if (mcp251xfd_tx_fifo_sta_empty(fifo_sta) &&
+ mcp251xfd_get_tx_free(tx_ring) == 0) {
*len_p = tx_ring->obj_num;
return 0;
}
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index 9e1b7d41005f..da7c72105fb6 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -188,14 +188,10 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
/* register peer device */
if (data && data[VXCAN_INFO_PEER]) {
- struct nlattr *nla_peer;
+ struct nlattr *nla_peer = data[VXCAN_INFO_PEER];
- nla_peer = data[VXCAN_INFO_PEER];
ifmp = nla_data(nla_peer);
- err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
- if (err < 0)
- return err;
-
+ rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
tbp = peer_tb;
}
@@ -208,9 +204,6 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
}
peer_net = rtnl_link_get_net(net, tbp);
- if (IS_ERR(peer_net))
- return PTR_ERR(peer_net);
-
peer = rtnl_create_link(peer_net, ifname, name_assign_type,
&vxcan_link_ops, tbp, extack);
if (IS_ERR(peer)) {
@@ -302,6 +295,7 @@ static struct rtnl_link_ops vxcan_link_ops = {
.newlink = vxcan_newlink,
.dellink = vxcan_dellink,
.policy = vxcan_policy,
+ .peer_type = VXCAN_INFO_PEER,
.maxtype = VXCAN_INFO_MAX,
.get_link_net = vxcan_get_link_net,
};
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index c39cb119e760..285785c942b0 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -989,8 +989,7 @@ void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
if (stringset == ETH_SS_STATS) {
for (i = 0; i < mib_size; i++)
- strscpy(data + i * ETH_GSTRING_LEN,
- mibs[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, mibs[i].name);
} else if (stringset == ETH_SS_PHY_STATS) {
phydev = b53_get_phy_device(ds, port);
if (!phydev)
diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c
index 3a89349dc918..c687360a5b7f 100644
--- a/drivers/net/dsa/b53/b53_mmap.c
+++ b/drivers/net/dsa/b53/b53_mmap.c
@@ -370,7 +370,7 @@ MODULE_DEVICE_TABLE(of, b53_mmap_of_table);
static struct platform_driver b53_mmap_driver = {
.probe = b53_mmap_probe,
- .remove_new = b53_mmap_remove,
+ .remove = b53_mmap_remove,
.shutdown = b53_mmap_shutdown,
.driver = {
.name = "b53-switch",
diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
index f3f95332ff17..b9939bbd2cd5 100644
--- a/drivers/net/dsa/b53/b53_srab.c
+++ b/drivers/net/dsa/b53/b53_srab.c
@@ -682,7 +682,7 @@ static void b53_srab_shutdown(struct platform_device *pdev)
static struct platform_driver b53_srab_driver = {
.probe = b53_srab_probe,
- .remove_new = b53_srab_remove,
+ .remove = b53_srab_remove,
.shutdown = b53_srab_shutdown,
.driver = {
.name = "b53-srab-switch",
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 0e663ec0c12a..43bde1f583ff 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -513,12 +513,12 @@ static void bcm_sf2_crossbar_setup(struct bcm_sf2_priv *priv)
u32 reg;
int i;
- mask = BIT(priv->num_crossbar_int_ports) - 1;
+ mask = BIT(priv->num_crossbar_ext_bits) - 1;
reg = reg_readl(priv, REG_CROSSBAR);
switch (priv->type) {
case BCM4908_DEVICE_ID:
- shift = CROSSBAR_BCM4908_INT_P7 * priv->num_crossbar_int_ports;
+ shift = CROSSBAR_BCM4908_INT_P7 * priv->num_crossbar_ext_bits;
reg &= ~(mask << shift);
if (0) /* FIXME */
reg |= CROSSBAR_BCM4908_EXT_SERDES << shift;
@@ -536,7 +536,7 @@ static void bcm_sf2_crossbar_setup(struct bcm_sf2_priv *priv)
reg = reg_readl(priv, REG_CROSSBAR);
for (i = 0; i < priv->num_crossbar_int_ports; i++) {
- shift = i * priv->num_crossbar_int_ports;
+ shift = i * priv->num_crossbar_ext_bits;
dev_dbg(dev, "crossbar int port #%d - ext port #%d\n", i,
(reg >> shift) & mask);
@@ -1183,8 +1183,8 @@ static void bcm_sf2_sw_get_strings(struct dsa_switch *ds, int port,
int cnt = b53_get_sset_count(ds, port, stringset);
b53_get_strings(ds, port, stringset, data);
- bcm_sf2_cfp_get_strings(ds, port, stringset,
- data + cnt * ETH_GSTRING_LEN);
+ data += cnt * ETH_GSTRING_LEN;
+ bcm_sf2_cfp_get_strings(ds, port, stringset, &data);
}
static void bcm_sf2_sw_get_ethtool_stats(struct dsa_switch *ds, int port,
@@ -1260,6 +1260,7 @@ struct bcm_sf2_of_data {
unsigned int core_reg_align;
unsigned int num_cfp_rules;
unsigned int num_crossbar_int_ports;
+ unsigned int num_crossbar_ext_bits;
};
static const u16 bcm_sf2_4908_reg_offsets[] = {
@@ -1288,6 +1289,7 @@ static const struct bcm_sf2_of_data bcm_sf2_4908_data = {
.reg_offsets = bcm_sf2_4908_reg_offsets,
.num_cfp_rules = 256,
.num_crossbar_int_ports = 2,
+ .num_crossbar_ext_bits = 2,
};
/* Register offsets for the SWITCH_REG_* block */
@@ -1399,6 +1401,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
priv->core_reg_align = data->core_reg_align;
priv->num_cfp_rules = data->num_cfp_rules;
priv->num_crossbar_int_ports = data->num_crossbar_int_ports;
+ priv->num_crossbar_ext_bits = data->num_crossbar_ext_bits;
priv->rcdev = devm_reset_control_get_optional_exclusive(&pdev->dev,
"switch");
@@ -1620,7 +1623,7 @@ static SIMPLE_DEV_PM_OPS(bcm_sf2_pm_ops,
static struct platform_driver bcm_sf2_driver = {
.probe = bcm_sf2_sw_probe,
- .remove_new = bcm_sf2_sw_remove,
+ .remove = bcm_sf2_sw_remove,
.shutdown = bcm_sf2_sw_shutdown,
.driver = {
.name = "brcm-sf2",
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index f95f4880b69e..be9f3b29019f 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -75,6 +75,7 @@ struct bcm_sf2_priv {
unsigned int core_reg_align;
unsigned int num_cfp_rules;
unsigned int num_crossbar_int_ports;
+ unsigned int num_crossbar_ext_bits;
/* spinlock protecting access to the indirect registers */
spinlock_t indir_lock;
@@ -227,8 +228,8 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv);
void bcm_sf2_cfp_exit(struct dsa_switch *ds);
int bcm_sf2_cfp_resume(struct dsa_switch *ds);
-void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,
- u32 stringset, uint8_t *data);
+void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ uint8_t **data);
void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data);
int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset);
diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
index c88ee3dd4299..e22362e6f0cd 100644
--- a/drivers/net/dsa/bcm_sf2_cfp.c
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
@@ -1279,27 +1279,19 @@ static const struct bcm_sf2_cfp_stat {
},
};
-void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,
- u32 stringset, uint8_t *data)
+void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ uint8_t **data)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
- unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats);
- char buf[ETH_GSTRING_LEN];
- unsigned int i, j, iter;
+ unsigned int i, j;
if (stringset != ETH_SS_STATS)
return;
- for (i = 1; i < priv->num_cfp_rules; i++) {
- for (j = 0; j < s; j++) {
- snprintf(buf, sizeof(buf),
- "CFP%03d_%sCntr",
- i, bcm_sf2_cfp_stats[j].name);
- iter = (i - 1) * s + j;
- strscpy(data + iter * ETH_GSTRING_LEN,
- buf, ETH_GSTRING_LEN);
- }
- }
+ for (i = 1; i < priv->num_cfp_rules; i++)
+ for (j = 0; j < ARRAY_SIZE(bcm_sf2_cfp_stats); j++)
+ ethtool_sprintf(data, "CFP%03d_%sCntr", i,
+ bcm_sf2_cfp_stats[j].name);
}
void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c
index c70ed67cc188..adbab544c60f 100644
--- a/drivers/net/dsa/dsa_loop.c
+++ b/drivers/net/dsa/dsa_loop.c
@@ -121,8 +121,7 @@ static void dsa_loop_get_strings(struct dsa_switch *ds, int port,
return;
for (i = 0; i < __DSA_LOOP_CNT_MAX; i++)
- memcpy(data + i * ETH_GSTRING_LEN,
- ps->ports[port].mib[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, ps->ports[port].mib[i].name);
}
static void dsa_loop_get_ethtool_stats(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c
index beda1e9d350f..283ec5a6e23c 100644
--- a/drivers/net/dsa/hirschmann/hellcreek.c
+++ b/drivers/net/dsa/hirschmann/hellcreek.c
@@ -294,12 +294,8 @@ static void hellcreek_get_strings(struct dsa_switch *ds, int port,
{
int i;
- for (i = 0; i < ARRAY_SIZE(hellcreek_counter); ++i) {
- const struct hellcreek_counter *counter = &hellcreek_counter[i];
-
- strscpy(data + i * ETH_GSTRING_LEN,
- counter->name, ETH_GSTRING_LEN);
- }
+ for (i = 0; i < ARRAY_SIZE(hellcreek_counter); ++i)
+ ethtool_puts(&data, hellcreek_counter[i].name);
}
static int hellcreek_get_sset_count(struct dsa_switch *ds, int port, int sset)
@@ -2105,7 +2101,7 @@ MODULE_DEVICE_TABLE(of, hellcreek_of_match);
static struct platform_driver hellcreek_driver = {
.probe = hellcreek_probe,
- .remove_new = hellcreek_remove,
+ .remove = hellcreek_remove,
.shutdown = hellcreek_shutdown,
.driver = {
.name = "hellcreek",
diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
index fcd4505f4925..6eb3140d4044 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -2249,7 +2249,7 @@ MODULE_DEVICE_TABLE(of, gswip_of_match);
static struct platform_driver gswip_driver = {
.probe = gswip_probe,
- .remove_new = gswip_remove,
+ .remove = gswip_remove,
.shutdown = gswip_shutdown,
.driver = {
.name = "gswip",
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 0ba658a72d8f..d16817e0476f 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1131,6 +1131,10 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds)
if (i == dev->cpu_port)
continue;
ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED);
+
+ /* Power down the internal PHY if port is unused. */
+ if (dsa_is_unused_port(ds, i) && dev->info->internal_phy[i])
+ ksz_pwrite16(dev, i, 0x100, BMCR_PDOWN);
}
}
diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c
index 7d7560f23a73..1c6d7fc16772 100644
--- a/drivers/net/dsa/microchip/ksz9477_i2c.c
+++ b/drivers/net/dsa/microchip/ksz9477_i2c.c
@@ -2,7 +2,7 @@
/*
* Microchip KSZ9477 series register access through I2C
*
- * Copyright (C) 2018-2019 Microchip Technology Inc.
+ * Copyright (C) 2018-2024 Microchip Technology Inc.
*/
#include <linux/i2c.h>
@@ -16,6 +16,8 @@ KSZ_REGMAP_TABLE(ksz9477, not_used, 16, 0, 0);
static int ksz9477_i2c_probe(struct i2c_client *i2c)
{
+ const struct ksz_chip_data *chip;
+ struct device *ddev = &i2c->dev;
struct regmap_config rc;
struct ksz_device *dev;
int i, ret;
@@ -24,6 +26,12 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c)
if (!dev)
return -ENOMEM;
+ chip = device_get_match_data(ddev);
+ if (!chip)
+ return -EINVAL;
+
+ /* Save chip id to do special initialization when probing. */
+ dev->chip_id = chip->chip_id;
for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = ksz9477_regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
@@ -111,6 +119,10 @@ static const struct of_device_id ksz9477_dt_ids[] = {
.compatible = "microchip,ksz9567",
.data = &ksz_switch_chips[KSZ9567]
},
+ {
+ .compatible = "microchip,lan9646",
+ .data = &ksz_switch_chips[LAN9646]
+ },
{},
};
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 5290f5ad98f3..920443ee8ffd 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -411,6 +411,8 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
.port_setup = lan937x_port_setup,
.set_ageing_time = lan937x_set_ageing_time,
+ .mdio_bus_preinit = lan937x_mdio_bus_preinit,
+ .create_phy_addr_map = lan937x_create_phy_addr_map,
.r_phy = lan937x_r_phy,
.w_phy = lan937x_w_phy,
.r_mib_cnt = ksz9477_r_mib_cnt,
@@ -1762,6 +1764,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 8,
.num_ipms = 8,
.tc_cbs_supported = true,
+ .phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
@@ -1790,6 +1793,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 8,
.num_ipms = 8,
.tc_cbs_supported = true,
+ .phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
@@ -1818,6 +1822,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 8,
.num_ipms = 8,
.tc_cbs_supported = true,
+ .phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
@@ -1850,6 +1855,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 8,
.num_ipms = 8,
.tc_cbs_supported = true,
+ .phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
@@ -1882,6 +1888,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_tx_queues = 8,
.num_ipms = 8,
.tc_cbs_supported = true,
+ .phy_side_mdio_supported = true,
.ops = &lan937x_dev_ops,
.phylink_mac_ops = &lan937x_phylink_mac_ops,
.mib_names = ksz9477_mib_names,
@@ -1901,6 +1908,41 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.internal_phy = {true, true, true, true,
false, false, true, true},
},
+
+ [LAN9646] = {
+ .chip_id = LAN9646_CHIP_ID,
+ .dev_name = "LAN9646",
+ .num_vlans = 4096,
+ .num_alus = 4096,
+ .num_statics = 16,
+ .cpu_ports = 0x7F, /* can be configured as cpu port */
+ .port_cnt = 7, /* total physical port count */
+ .port_nirqs = 4,
+ .num_tx_queues = 4,
+ .num_ipms = 8,
+ .ops = &ksz9477_dev_ops,
+ .phylink_mac_ops = &ksz9477_phylink_mac_ops,
+ .phy_errata_9477 = true,
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .regs = ksz9477_regs,
+ .masks = ksz9477_masks,
+ .shifts = ksz9477_shifts,
+ .xmii_ctrl0 = ksz9477_xmii_ctrl0,
+ .xmii_ctrl1 = ksz9477_xmii_ctrl1,
+ .supports_mii = {false, false, false, false,
+ false, true, true},
+ .supports_rmii = {false, false, false, false,
+ false, true, true},
+ .supports_rgmii = {false, false, false, false,
+ false, true, true},
+ .internal_phy = {true, true, true, true,
+ true, false, false},
+ .gbit_capable = {true, true, true, true, true, true, true},
+ .wr_table = &ksz9477_register_set,
+ .rd_table = &ksz9477_register_set,
+ },
};
EXPORT_SYMBOL_GPL(ksz_switch_chips);
@@ -2112,10 +2154,8 @@ static void ksz_get_strings(struct dsa_switch *ds, int port,
if (stringset != ETH_SS_STATS)
return;
- for (i = 0; i < dev->info->mib_cnt; i++) {
- memcpy(buf + i * ETH_GSTRING_LEN,
- dev->info->mib_names[i].string, ETH_GSTRING_LEN);
- }
+ for (i = 0; i < dev->info->mib_cnt; i++)
+ ethtool_puts(&buf, dev->info->mib_names[i].string);
}
/**
@@ -2238,16 +2278,100 @@ static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
return dev->dev_ops->w_phy(dev, addr, regnum, val);
}
+/**
+ * ksz_parent_mdio_read - Read data from a PHY register on the parent MDIO bus.
+ * @bus: MDIO bus structure.
+ * @addr: PHY address on the parent MDIO bus.
+ * @regnum: Register number to read.
+ *
+ * This function provides a direct read operation on the parent MDIO bus for
+ * accessing PHY registers. By bypassing SPI or I2C, it uses the parent MDIO bus
+ * to retrieve data from the PHY registers at the specified address and register
+ * number.
+ *
+ * Return: Value of the PHY register, or a negative error code on failure.
+ */
+static int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+ struct ksz_device *dev = bus->priv;
+
+ return mdiobus_read_nested(dev->parent_mdio_bus, addr, regnum);
+}
+
+/**
+ * ksz_parent_mdio_write - Write data to a PHY register on the parent MDIO bus.
+ * @bus: MDIO bus structure.
+ * @addr: PHY address on the parent MDIO bus.
+ * @regnum: Register number to write to.
+ * @val: Value to write to the PHY register.
+ *
+ * This function provides a direct write operation on the parent MDIO bus for
+ * accessing PHY registers. Bypassing SPI or I2C, it uses the parent MDIO bus
+ * to modify the PHY register values at the specified address.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+static int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum,
+ u16 val)
+{
+ struct ksz_device *dev = bus->priv;
+
+ return mdiobus_write_nested(dev->parent_mdio_bus, addr, regnum, val);
+}
+
+/**
+ * ksz_phy_addr_to_port - Map a PHY address to the corresponding switch port.
+ * @dev: Pointer to device structure.
+ * @addr: PHY address to map to a port.
+ *
+ * This function finds the corresponding switch port for a given PHY address by
+ * iterating over all user ports on the device. It checks if a port's PHY
+ * address in `phy_addr_map` matches the specified address and if the port
+ * contains an internal PHY. If a match is found, the index of the port is
+ * returned.
+ *
+ * Return: Port index on success, or -EINVAL if no matching port is found.
+ */
+static int ksz_phy_addr_to_port(struct ksz_device *dev, int addr)
+{
+ struct dsa_switch *ds = dev->ds;
+ struct dsa_port *dp;
+
+ dsa_switch_for_each_user_port(dp, ds) {
+ if (dev->info->internal_phy[dp->index] &&
+ dev->phy_addr_map[dp->index] == addr)
+ return dp->index;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * ksz_irq_phy_setup - Configure IRQs for PHYs in the KSZ device.
+ * @dev: Pointer to the KSZ device structure.
+ *
+ * Sets up IRQs for each active PHY connected to the KSZ switch by mapping the
+ * appropriate IRQs for each PHY and assigning them to the `user_mii_bus` in
+ * the DSA switch structure. Each IRQ is mapped based on the port's IRQ domain.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
static int ksz_irq_phy_setup(struct ksz_device *dev)
{
struct dsa_switch *ds = dev->ds;
- int phy;
+ int phy, port;
int irq;
int ret;
- for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) {
+ for (phy = 0; phy < PHY_MAX_ADDR; phy++) {
if (BIT(phy) & ds->phys_mii_mask) {
- irq = irq_find_mapping(dev->ports[phy].pirq.domain,
+ port = ksz_phy_addr_to_port(dev, phy);
+ if (port < 0) {
+ ret = port;
+ goto out;
+ }
+
+ irq = irq_find_mapping(dev->ports[port].pirq.domain,
PORT_SRC_PHY_INT);
if (irq < 0) {
ret = irq;
@@ -2265,49 +2389,183 @@ out:
return ret;
}
+/**
+ * ksz_irq_phy_free - Release IRQ mappings for PHYs in the KSZ device.
+ * @dev: Pointer to the KSZ device structure.
+ *
+ * Releases any IRQ mappings previously assigned to active PHYs in the KSZ
+ * switch by disposing of each mapped IRQ in the `user_mii_bus` structure.
+ */
static void ksz_irq_phy_free(struct ksz_device *dev)
{
struct dsa_switch *ds = dev->ds;
int phy;
- for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++)
+ for (phy = 0; phy < PHY_MAX_ADDR; phy++)
if (BIT(phy) & ds->phys_mii_mask)
irq_dispose_mapping(ds->user_mii_bus->irq[phy]);
}
+/**
+ * ksz_parse_dt_phy_config - Parse and validate PHY configuration from DT
+ * @dev: pointer to the KSZ device structure
+ * @bus: pointer to the MII bus structure
+ * @mdio_np: pointer to the MDIO node in the device tree
+ *
+ * This function parses and validates PHY configurations for each user port
+ * defined in the device tree for a KSZ switch device. It verifies that the
+ * `phy-handle` properties are correctly set and that the internal PHYs match
+ * expected addresses and parent nodes. Sets up the PHY mask in the MII bus if
+ * all validations pass. Logs error messages for any mismatches or missing data.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+static int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
+ struct device_node *mdio_np)
+{
+ struct device_node *phy_node, *phy_parent_node;
+ bool phys_are_valid = true;
+ struct dsa_port *dp;
+ u32 phy_addr;
+ int ret;
+
+ dsa_switch_for_each_user_port(dp, dev->ds) {
+ if (!dev->info->internal_phy[dp->index])
+ continue;
+
+ phy_node = of_parse_phandle(dp->dn, "phy-handle", 0);
+ if (!phy_node) {
+ dev_err(dev->dev, "failed to parse phy-handle for port %d.\n",
+ dp->index);
+ phys_are_valid = false;
+ continue;
+ }
+
+ phy_parent_node = of_get_parent(phy_node);
+ if (!phy_parent_node) {
+ dev_err(dev->dev, "failed to get PHY-parent node for port %d\n",
+ dp->index);
+ phys_are_valid = false;
+ } else if (phy_parent_node != mdio_np) {
+ dev_err(dev->dev, "PHY-parent node mismatch for port %d, expected %pOF, got %pOF\n",
+ dp->index, mdio_np, phy_parent_node);
+ phys_are_valid = false;
+ } else {
+ ret = of_property_read_u32(phy_node, "reg", &phy_addr);
+ if (ret < 0) {
+ dev_err(dev->dev, "failed to read PHY address for port %d. Error %d\n",
+ dp->index, ret);
+ phys_are_valid = false;
+ } else if (phy_addr != dev->phy_addr_map[dp->index]) {
+ dev_err(dev->dev, "PHY address mismatch for port %d, expected 0x%x, got 0x%x\n",
+ dp->index, dev->phy_addr_map[dp->index],
+ phy_addr);
+ phys_are_valid = false;
+ } else {
+ bus->phy_mask |= BIT(phy_addr);
+ }
+ }
+
+ of_node_put(phy_node);
+ of_node_put(phy_parent_node);
+ }
+
+ if (!phys_are_valid)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * ksz_mdio_register - Register and configure the MDIO bus for the KSZ device.
+ * @dev: Pointer to the KSZ device structure.
+ *
+ * This function sets up and registers an MDIO bus for the KSZ switch device,
+ * allowing access to its internal PHYs. If the device supports side MDIO,
+ * the function will configure the external MDIO controller specified by the
+ * "mdio-parent-bus" device tree property to directly manage internal PHYs.
+ * Otherwise, SPI or I2C access is set up for PHY access.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
static int ksz_mdio_register(struct ksz_device *dev)
{
+ struct device_node *parent_bus_node;
+ struct mii_bus *parent_bus = NULL;
struct dsa_switch *ds = dev->ds;
struct device_node *mdio_np;
struct mii_bus *bus;
- int ret;
+ int ret, i;
mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio");
if (!mdio_np)
return 0;
+ parent_bus_node = of_parse_phandle(mdio_np, "mdio-parent-bus", 0);
+ if (parent_bus_node && !dev->info->phy_side_mdio_supported) {
+ dev_err(dev->dev, "Side MDIO bus is not supported for this HW, ignoring 'mdio-parent-bus' property.\n");
+ ret = -EINVAL;
+
+ goto put_mdio_node;
+ } else if (parent_bus_node) {
+ parent_bus = of_mdio_find_bus(parent_bus_node);
+ if (!parent_bus) {
+ ret = -EPROBE_DEFER;
+
+ goto put_mdio_node;
+ }
+
+ dev->parent_mdio_bus = parent_bus;
+ }
+
bus = devm_mdiobus_alloc(ds->dev);
if (!bus) {
- of_node_put(mdio_np);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto put_mdio_node;
+ }
+
+ if (dev->dev_ops->mdio_bus_preinit) {
+ ret = dev->dev_ops->mdio_bus_preinit(dev, !!parent_bus);
+ if (ret)
+ goto put_mdio_node;
+ }
+
+ if (dev->dev_ops->create_phy_addr_map) {
+ ret = dev->dev_ops->create_phy_addr_map(dev, !!parent_bus);
+ if (ret)
+ goto put_mdio_node;
+ } else {
+ for (i = 0; i < dev->info->port_cnt; i++)
+ dev->phy_addr_map[i] = i;
}
bus->priv = dev;
- bus->read = ksz_sw_mdio_read;
- bus->write = ksz_sw_mdio_write;
- bus->name = "ksz user smi";
- snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
+ if (parent_bus) {
+ bus->read = ksz_parent_mdio_read;
+ bus->write = ksz_parent_mdio_write;
+ bus->name = "KSZ side MDIO";
+ snprintf(bus->id, MII_BUS_ID_SIZE, "ksz-side-mdio-%d",
+ ds->index);
+ } else {
+ bus->read = ksz_sw_mdio_read;
+ bus->write = ksz_sw_mdio_write;
+ bus->name = "ksz user smi";
+ snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
+ }
+
+ ret = ksz_parse_dt_phy_config(dev, bus, mdio_np);
+ if (ret)
+ goto put_mdio_node;
+
+ ds->phys_mii_mask = bus->phy_mask;
bus->parent = ds->dev;
- bus->phy_mask = ~ds->phys_mii_mask;
ds->user_mii_bus = bus;
if (dev->irq > 0) {
ret = ksz_irq_phy_setup(dev);
- if (ret) {
- of_node_put(mdio_np);
- return ret;
- }
+ if (ret)
+ goto put_mdio_node;
}
ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np);
@@ -2318,7 +2576,9 @@ static int ksz_mdio_register(struct ksz_device *dev)
ksz_irq_phy_free(dev);
}
+put_mdio_node:
of_node_put(mdio_np);
+ of_node_put(parent_bus_node);
return ret;
}
@@ -2745,6 +3005,7 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
case KSZ9896_CHIP_ID:
/* KSZ9896C Errata DS80000757A Module 3 */
case KSZ9897_CHIP_ID:
+ case LAN9646_CHIP_ID:
/* KSZ9897R Errata DS80000758C Module 4 */
/* Energy Efficient Ethernet (EEE) feature select must be manually disabled
* The EEE feature is enabled by default, but it is not fully
@@ -3005,6 +3266,7 @@ static void ksz_port_teardown(struct dsa_switch *ds, int port)
case KSZ9893_CHIP_ID:
case KSZ9896_CHIP_ID:
case KSZ9897_CHIP_ID:
+ case LAN9646_CHIP_ID:
if (dsa_is_user_port(ds, port))
ksz9477_port_acl_free(dev, port);
}
@@ -3061,7 +3323,8 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
dev->chip_id == KSZ9477_CHIP_ID ||
dev->chip_id == KSZ9896_CHIP_ID ||
dev->chip_id == KSZ9897_CHIP_ID ||
- dev->chip_id == KSZ9567_CHIP_ID)
+ dev->chip_id == KSZ9567_CHIP_ID ||
+ dev->chip_id == LAN9646_CHIP_ID)
proto = DSA_TAG_PROTO_KSZ9477;
if (is_lan937x(dev))
@@ -3180,6 +3443,7 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
case LAN9372_CHIP_ID:
case LAN9373_CHIP_ID:
case LAN9374_CHIP_ID:
+ case LAN9646_CHIP_ID:
return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
}
@@ -3202,6 +3466,7 @@ static int ksz_validate_eee(struct dsa_switch *ds, int port)
case KSZ9893_CHIP_ID:
case KSZ9896_CHIP_ID:
case KSZ9897_CHIP_ID:
+ case LAN9646_CHIP_ID:
return 0;
}
@@ -3554,7 +3819,10 @@ static int ksz_switch_detect(struct ksz_device *dev)
case LAN9372_CHIP_ID:
case LAN9373_CHIP_ID:
case LAN9374_CHIP_ID:
- dev->chip_id = id32;
+
+ /* LAN9646 does not have its own chip id. */
+ if (dev->chip_id != LAN9646_CHIP_ID)
+ dev->chip_id = id32;
break;
case KSZ9893_CHIP_ID:
ret = ksz_read8(dev, REG_CHIP_ID4,
@@ -3593,6 +3861,7 @@ static int ksz_cls_flower_add(struct dsa_switch *ds, int port,
case KSZ9893_CHIP_ID:
case KSZ9896_CHIP_ID:
case KSZ9897_CHIP_ID:
+ case LAN9646_CHIP_ID:
return ksz9477_cls_flower_add(ds, port, cls, ingress);
}
@@ -3613,6 +3882,7 @@ static int ksz_cls_flower_del(struct dsa_switch *ds, int port,
case KSZ9893_CHIP_ID:
case KSZ9896_CHIP_ID:
case KSZ9897_CHIP_ID:
+ case LAN9646_CHIP_ID:
return ksz9477_cls_flower_del(ds, port, cls, ingress);
}
@@ -4700,6 +4970,7 @@ static int ksz_parse_drive_strength(struct ksz_device *dev)
case KSZ9893_CHIP_ID:
case KSZ9896_CHIP_ID:
case KSZ9897_CHIP_ID:
+ case LAN9646_CHIP_ID:
return ksz9477_drive_strength_write(dev, of_props,
ARRAY_SIZE(of_props));
default:
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index bec846e20682..b3bb75ca0796 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -65,6 +65,12 @@ struct ksz_chip_data {
u8 num_tx_queues;
u8 num_ipms; /* number of Internal Priority Maps */
bool tc_cbs_supported;
+
+ /**
+ * @phy_side_mdio_supported: Indicates if the chip supports an additional
+ * side MDIO channel for accessing integrated PHYs.
+ */
+ bool phy_side_mdio_supported;
const struct ksz_dev_ops *ops;
const struct phylink_mac_ops *phylink_mac_ops;
bool phy_errata_9477;
@@ -191,6 +197,22 @@ struct ksz_device {
struct ksz_switch_macaddr *switch_macaddr;
struct net_device *hsr_dev; /* HSR */
u8 hsr_ports;
+
+ /**
+ * @phy_addr_map: Array mapping switch ports to their corresponding PHY
+ * addresses.
+ */
+ u8 phy_addr_map[KSZ_MAX_NUM_PORTS];
+
+ /**
+ * @parent_mdio_bus: Pointer to the external MDIO bus controller.
+ *
+ * This points to an external MDIO bus controller that is used to access
+ * the PHYs integrated within the switch. Unlike an integrated MDIO
+ * bus, this external controller provides a direct path for managing
+ * the switch’s internal PHYs, bypassing the main SPI interface.
+ */
+ struct mii_bus *parent_mdio_bus;
};
/* List of supported models */
@@ -214,6 +236,7 @@ enum ksz_model {
LAN9372,
LAN9373,
LAN9374,
+ LAN9646,
};
enum ksz_regs {
@@ -326,6 +349,43 @@ struct ksz_dev_ops {
void (*port_cleanup)(struct ksz_device *dev, int port);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
int (*set_ageing_time)(struct ksz_device *dev, unsigned int msecs);
+
+ /**
+ * @mdio_bus_preinit: Function pointer to pre-initialize the MDIO bus
+ * for accessing PHYs.
+ * @dev: Pointer to device structure.
+ * @side_mdio: Boolean indicating if the PHYs are accessed over a side
+ * MDIO bus.
+ *
+ * This function pointer is used to configure the MDIO bus for PHY
+ * access before initiating regular PHY operations. It enables either
+ * SPI/I2C or side MDIO access modes by unlocking necessary registers
+ * and setting up access permissions for the selected mode.
+ *
+ * Return:
+ * - 0 on success.
+ * - Negative error code on failure.
+ */
+ int (*mdio_bus_preinit)(struct ksz_device *dev, bool side_mdio);
+
+ /**
+ * @create_phy_addr_map: Function pointer to create a port-to-PHY
+ * address map.
+ * @dev: Pointer to device structure.
+ * @side_mdio: Boolean indicating if the PHYs are accessed over a side
+ * MDIO bus.
+ *
+ * This function pointer is responsible for mapping switch ports to PHY
+ * addresses according to the configured access mode (SPI or side MDIO)
+ * and the device’s strap configuration. The mapping setup may vary
+ * depending on the chip variant and configuration. Ensures the correct
+ * address mapping for PHY communication.
+ *
+ * Return:
+ * - 0 on success.
+ * - Negative error code on failure (e.g., invalid configuration).
+ */
+ int (*create_phy_addr_map)(struct ksz_device *dev, bool side_mdio);
int (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
int (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c
index 050f17c43ef6..22fb9ef4645c 100644
--- a/drivers/net/dsa/microchip/ksz_ptp.c
+++ b/drivers/net/dsa/microchip/ksz_ptp.c
@@ -1106,7 +1106,7 @@ static int ksz_ptp_msg_irq_setup(struct ksz_port *port, u8 n)
ptpmsg_irq->port = port;
ptpmsg_irq->ts_reg = ops->get_port_addr(port->num, ts_reg[n]);
- snprintf(ptpmsg_irq->name, sizeof(ptpmsg_irq->name), name[n]);
+ strscpy(ptpmsg_irq->name, name[n]);
ptpmsg_irq->num = irq_find_mapping(port->ptpirq.domain, n);
if (ptpmsg_irq->num < 0)
diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c
index 1c6652f2b9fe..108a958dc356 100644
--- a/drivers/net/dsa/microchip/ksz_spi.c
+++ b/drivers/net/dsa/microchip/ksz_spi.c
@@ -54,6 +54,8 @@ static int ksz_spi_probe(struct spi_device *spi)
if (!chip)
return -EINVAL;
+ /* Save chip id to do special initialization when probing. */
+ dev->chip_id = chip->chip_id;
if (chip->chip_id == KSZ88X3_CHIP_ID)
regmap_config = ksz8863_regmap_config;
else if (chip->chip_id == KSZ8795_CHIP_ID ||
@@ -203,6 +205,10 @@ static const struct of_device_id ksz_dt_ids[] = {
.compatible = "microchip,lan9374",
.data = &ksz_switch_chips[LAN9374]
},
+ {
+ .compatible = "microchip,lan9646",
+ .data = &ksz_switch_chips[LAN9646]
+ },
{},
};
MODULE_DEVICE_TABLE(of, ksz_dt_ids);
@@ -228,6 +234,7 @@ static const struct spi_device_id ksz_spi_ids[] = {
{ "lan9372" },
{ "lan9373" },
{ "lan9374" },
+ { "lan9646" },
{ },
};
MODULE_DEVICE_TABLE(spi, ksz_spi_ids);
diff --git a/drivers/net/dsa/microchip/lan937x.h b/drivers/net/dsa/microchip/lan937x.h
index 3388d91dbc44..df13ebbd356f 100644
--- a/drivers/net/dsa/microchip/lan937x.h
+++ b/drivers/net/dsa/microchip/lan937x.h
@@ -13,6 +13,8 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port);
void lan937x_config_cpu_port(struct dsa_switch *ds);
int lan937x_switch_init(struct ksz_device *dev);
void lan937x_switch_exit(struct ksz_device *dev);
+int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio);
+int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio);
int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 824d9309a3d3..b7652efd632e 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -18,6 +18,87 @@
#include "ksz9477.h"
#include "lan937x.h"
+/* marker for ports without built-in PHY */
+#define LAN937X_NO_PHY U8_MAX
+
+/*
+ * lan9370_phy_addr - Mapping of LAN9370 switch ports to PHY addresses.
+ *
+ * Each entry corresponds to a specific port on the LAN9370 switch,
+ * where ports 1-4 are connected to integrated 100BASE-T1 PHYs, and
+ * Port 5 is connected to an RGMII interface without a PHY. The values
+ * are based on the documentation (DS00003108E, section 3.3).
+ */
+static const u8 lan9370_phy_addr[] = {
+ [0] = 2, /* Port 1, T1 AFE0 */
+ [1] = 3, /* Port 2, T1 AFE1 */
+ [2] = 5, /* Port 3, T1 AFE3 */
+ [3] = 6, /* Port 4, T1 AFE4 */
+ [4] = LAN937X_NO_PHY, /* Port 5, RGMII 2 */
+};
+
+/*
+ * lan9371_phy_addr - Mapping of LAN9371 switch ports to PHY addresses.
+ *
+ * The values are based on the documentation (DS00003109E, section 3.3).
+ */
+static const u8 lan9371_phy_addr[] = {
+ [0] = 2, /* Port 1, T1 AFE0 */
+ [1] = 3, /* Port 2, T1 AFE1 */
+ [2] = 5, /* Port 3, T1 AFE3 */
+ [3] = 8, /* Port 4, TX PHY */
+ [4] = LAN937X_NO_PHY, /* Port 5, RGMII 2 */
+ [5] = LAN937X_NO_PHY, /* Port 6, RGMII 1 */
+};
+
+/*
+ * lan9372_phy_addr - Mapping of LAN9372 switch ports to PHY addresses.
+ *
+ * The values are based on the documentation (DS00003110F, section 3.3).
+ */
+static const u8 lan9372_phy_addr[] = {
+ [0] = 2, /* Port 1, T1 AFE0 */
+ [1] = 3, /* Port 2, T1 AFE1 */
+ [2] = 5, /* Port 3, T1 AFE3 */
+ [3] = 8, /* Port 4, TX PHY */
+ [4] = LAN937X_NO_PHY, /* Port 5, RGMII 2 */
+ [5] = LAN937X_NO_PHY, /* Port 6, RGMII 1 */
+ [6] = 6, /* Port 7, T1 AFE4 */
+ [7] = 4, /* Port 8, T1 AFE2 */
+};
+
+/*
+ * lan9373_phy_addr - Mapping of LAN9373 switch ports to PHY addresses.
+ *
+ * The values are based on the documentation (DS00003110F, section 3.3).
+ */
+static const u8 lan9373_phy_addr[] = {
+ [0] = 2, /* Port 1, T1 AFE0 */
+ [1] = 3, /* Port 2, T1 AFE1 */
+ [2] = 5, /* Port 3, T1 AFE3 */
+ [3] = LAN937X_NO_PHY, /* Port 4, SGMII */
+ [4] = LAN937X_NO_PHY, /* Port 5, RGMII 2 */
+ [5] = LAN937X_NO_PHY, /* Port 6, RGMII 1 */
+ [6] = 6, /* Port 7, T1 AFE4 */
+ [7] = 4, /* Port 8, T1 AFE2 */
+};
+
+/*
+ * lan9374_phy_addr - Mapping of LAN9374 switch ports to PHY addresses.
+ *
+ * The values are based on the documentation (DS00003110F, section 3.3).
+ */
+static const u8 lan9374_phy_addr[] = {
+ [0] = 2, /* Port 1, T1 AFE0 */
+ [1] = 3, /* Port 2, T1 AFE1 */
+ [2] = 5, /* Port 3, T1 AFE3 */
+ [3] = 7, /* Port 4, T1 AFE5 */
+ [4] = LAN937X_NO_PHY, /* Port 5, RGMII 2 */
+ [5] = LAN937X_NO_PHY, /* Port 6, RGMII 1 */
+ [6] = 6, /* Port 7, T1 AFE4 */
+ [7] = 4, /* Port 8, T1 AFE2 */
+};
+
static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
return regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0);
@@ -30,24 +111,144 @@ static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset,
bits, set ? bits : 0);
}
-static int lan937x_enable_spi_indirect_access(struct ksz_device *dev)
+/**
+ * lan937x_create_phy_addr_map - Create port-to-PHY address map for MDIO bus.
+ * @dev: Pointer to device structure.
+ * @side_mdio: Boolean indicating if the PHYs are accessed over a side MDIO bus.
+ *
+ * This function sets up the PHY address mapping for the LAN937x switches,
+ * which support two access modes for internal PHYs:
+ * 1. **SPI Access**: A straightforward one-to-one port-to-PHY address
+ * mapping is applied.
+ * 2. **MDIO Access**: The PHY address mapping varies based on chip variant
+ * and strap configuration. An offset is calculated based on strap settings
+ * to ensure correct PHY addresses are assigned. The offset calculation logic
+ * is based on Microchip's Article Number 000015828, available at:
+ * https://microchip.my.site.com/s/article/LAN9374-Virtual-PHY-PHY-Address-Mapping
+ *
+ * The function first checks if side MDIO access is disabled, in which case a
+ * simple direct mapping (port number = PHY address) is applied. If side MDIO
+ * access is enabled, it reads the strap configuration to determine the correct
+ * offset for PHY addresses.
+ *
+ * The appropriate mapping table is selected based on the chip ID, and the
+ * `phy_addr_map` is populated with the correct addresses for each port. Any
+ * port with no PHY is assigned a `LAN937X_NO_PHY` marker.
+ *
+ * Return: 0 on success, error code on failure.
+ */
+int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio)
+{
+ static const u8 *phy_addr_map;
+ u32 strap_val;
+ u8 offset = 0;
+ size_t size;
+ int ret, i;
+
+ if (!side_mdio) {
+ /* simple direct mapping */
+ for (i = 0; i < dev->info->port_cnt; i++)
+ dev->phy_addr_map[i] = i;
+
+ return 0;
+ }
+
+ ret = ksz_read32(dev, REG_SW_CFG_STRAP_VAL, &strap_val);
+ if (ret < 0)
+ return ret;
+
+ if (!(strap_val & SW_CASCADE_ID_CFG) && !(strap_val & SW_VPHY_ADD_CFG))
+ offset = 0;
+ else if (!(strap_val & SW_CASCADE_ID_CFG) && (strap_val & SW_VPHY_ADD_CFG))
+ offset = 7;
+ else if ((strap_val & SW_CASCADE_ID_CFG) && !(strap_val & SW_VPHY_ADD_CFG))
+ offset = 15;
+ else
+ offset = 22;
+
+ switch (dev->info->chip_id) {
+ case LAN9370_CHIP_ID:
+ phy_addr_map = lan9370_phy_addr;
+ size = ARRAY_SIZE(lan9370_phy_addr);
+ break;
+ case LAN9371_CHIP_ID:
+ phy_addr_map = lan9371_phy_addr;
+ size = ARRAY_SIZE(lan9371_phy_addr);
+ break;
+ case LAN9372_CHIP_ID:
+ phy_addr_map = lan9372_phy_addr;
+ size = ARRAY_SIZE(lan9372_phy_addr);
+ break;
+ case LAN9373_CHIP_ID:
+ phy_addr_map = lan9373_phy_addr;
+ size = ARRAY_SIZE(lan9373_phy_addr);
+ break;
+ case LAN9374_CHIP_ID:
+ phy_addr_map = lan9374_phy_addr;
+ size = ARRAY_SIZE(lan9374_phy_addr);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (size < dev->info->port_cnt)
+ return -EINVAL;
+
+ for (i = 0; i < dev->info->port_cnt; i++) {
+ if (phy_addr_map[i] == LAN937X_NO_PHY)
+ dev->phy_addr_map[i] = phy_addr_map[i];
+ else
+ dev->phy_addr_map[i] = phy_addr_map[i] + offset;
+ }
+
+ return 0;
+}
+
+/**
+ * lan937x_mdio_bus_preinit - Pre-initialize MDIO bus for accessing PHYs.
+ * @dev: Pointer to device structure.
+ * @side_mdio: Boolean indicating if the PHYs are accessed over a side MDIO bus.
+ *
+ * This function configures the LAN937x switch for PHY access either through
+ * SPI or the side MDIO bus, unlocking the necessary registers for each access
+ * mode.
+ *
+ * Operation Modes:
+ * 1. **SPI Access**: Enables SPI indirect access to address clock domain
+ * crossing issues when SPI is used for PHY access.
+ * 2. **MDIO Access**: Grants access to internal PHYs over the side MDIO bus,
+ * required when using the MDIO bus for PHY management.
+ *
+ * Return: 0 on success, error code on failure.
+ */
+int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio)
{
u16 data16;
int ret;
- /* Enable Phy access through SPI */
+ /* Unlock access to the PHYs, needed for SPI and side MDIO access */
ret = lan937x_cfg(dev, REG_GLOBAL_CTRL_0, SW_PHY_REG_BLOCK, false);
if (ret < 0)
- return ret;
+ goto print_error;
- ret = ksz_read16(dev, REG_VPHY_SPECIAL_CTRL__2, &data16);
- if (ret < 0)
- return ret;
+ if (side_mdio)
+ /* Allow access to internal PHYs over MDIO bus */
+ data16 = VPHY_MDIO_INTERNAL_ENABLE;
+ else
+ /* Enable SPI indirect access to address clock domain crossing
+ * issue
+ */
+ data16 = VPHY_SPI_INDIRECT_ENABLE;
- /* Allow SPI access */
- data16 |= VPHY_SPI_INDIRECT_ENABLE;
+ ret = ksz_rmw16(dev, REG_VPHY_SPECIAL_CTRL__2,
+ VPHY_SPI_INDIRECT_ENABLE | VPHY_MDIO_INTERNAL_ENABLE,
+ data16);
+
+print_error:
+ if (ret < 0)
+ dev_err(dev->dev, "failed to preinit the MDIO bus\n");
- return ksz_write16(dev, REG_VPHY_SPECIAL_CTRL__2, data16);
+ return ret;
}
static int lan937x_vphy_ind_addr_wr(struct ksz_device *dev, int addr, int reg)
@@ -363,13 +564,6 @@ int lan937x_setup(struct dsa_switch *ds)
struct ksz_device *dev = ds->priv;
int ret;
- /* enable Indirect Access from SPI to the VPHY registers */
- ret = lan937x_enable_spi_indirect_access(dev);
- if (ret < 0) {
- dev_err(dev->dev, "failed to enable spi indirect access");
- return ret;
- }
-
/* The VLAN aware is a global setting. Mixed vlan
* filterings are not supported.
*/
diff --git a/drivers/net/dsa/microchip/lan937x_reg.h b/drivers/net/dsa/microchip/lan937x_reg.h
index 2f22a9d01de3..4ec93e421da4 100644
--- a/drivers/net/dsa/microchip/lan937x_reg.h
+++ b/drivers/net/dsa/microchip/lan937x_reg.h
@@ -37,6 +37,10 @@
#define SW_CLK125_ENB BIT(1)
#define SW_CLK25_ENB BIT(0)
+#define REG_SW_CFG_STRAP_VAL 0x0200
+#define SW_CASCADE_ID_CFG BIT(15)
+#define SW_VPHY_ADD_CFG BIT(0)
+
/* 2 - PHY Control */
#define REG_SW_CFG_STRAP_OVR 0x0214
#define SW_VPHY_DISABLE BIT(31)
diff --git a/drivers/net/dsa/mt7530-mmio.c b/drivers/net/dsa/mt7530-mmio.c
index 10dc49961f15..5f2db4317dd3 100644
--- a/drivers/net/dsa/mt7530-mmio.c
+++ b/drivers/net/dsa/mt7530-mmio.c
@@ -86,7 +86,7 @@ static void mt7988_shutdown(struct platform_device *pdev)
static struct platform_driver mt7988_platform_driver = {
.probe = mt7988_probe,
- .remove_new = mt7988_remove,
+ .remove = mt7988_remove,
.shutdown = mt7988_shutdown,
.driver = {
.name = "mt7530-mmio",
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index d84ee1b419a6..086b8b3d5b40 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -21,6 +21,7 @@
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <net/dsa.h>
+#include <net/pkt_cls.h>
#include "mt7530.h"
@@ -3146,6 +3147,53 @@ mt753x_conduit_state_change(struct dsa_switch *ds,
mt7530_rmw(priv, MT753X_MFC, MT7530_CPU_EN | MT7530_CPU_PORT_MASK, val);
}
+static int mt753x_tc_setup_qdisc_tbf(struct dsa_switch *ds, int port,
+ struct tc_tbf_qopt_offload *qopt)
+{
+ struct tc_tbf_qopt_offload_replace_params *p = &qopt->replace_params;
+ struct mt7530_priv *priv = ds->priv;
+ u32 rate = 0;
+
+ switch (qopt->command) {
+ case TC_TBF_REPLACE:
+ rate = div_u64(p->rate.rate_bytes_ps, 1000) << 3; /* kbps */
+ fallthrough;
+ case TC_TBF_DESTROY: {
+ u32 val, tick;
+
+ mt7530_rmw(priv, MT753X_GERLCR, EGR_BC_MASK,
+ EGR_BC_CRC_IPG_PREAMBLE);
+
+ /* if rate is greater than 10Mbps tick is 1/32 ms,
+ * 1ms otherwise
+ */
+ tick = rate > 10000 ? 2 : 7;
+ val = FIELD_PREP(ERLCR_CIR_MASK, (rate >> 5)) |
+ FIELD_PREP(ERLCR_EN_MASK, !!rate) |
+ FIELD_PREP(ERLCR_EXP_MASK, tick) |
+ ERLCR_TBF_MODE_MASK |
+ FIELD_PREP(ERLCR_MANT_MASK, 0xf);
+ mt7530_write(priv, MT753X_ERLCR_P(port), val);
+ break;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int mt753x_setup_tc(struct dsa_switch *ds, int port,
+ enum tc_setup_type type, void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_QDISC_TBF:
+ return mt753x_tc_setup_qdisc_tbf(ds, port, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int mt7988_setup(struct dsa_switch *ds)
{
struct mt7530_priv *priv = ds->priv;
@@ -3193,6 +3241,7 @@ const struct dsa_switch_ops mt7530_switch_ops = {
.get_mac_eee = mt753x_get_mac_eee,
.set_mac_eee = mt753x_set_mac_eee,
.conduit_state_change = mt753x_conduit_state_change,
+ .port_setup_tc = mt753x_setup_tc,
};
EXPORT_SYMBOL_GPL(mt7530_switch_ops);
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index 6ad33a9f6b1d..448200689f49 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -248,6 +248,18 @@ enum mt7530_vlan_egress_attr {
#define AGE_UNIT_MAX 0xfff
#define AGE_UNIT(x) (AGE_UNIT_MASK & (x))
+#define MT753X_ERLCR_P(x) (0x1040 + ((x) * 0x100))
+#define ERLCR_CIR_MASK GENMASK(31, 16)
+#define ERLCR_EN_MASK BIT(15)
+#define ERLCR_EXP_MASK GENMASK(11, 8)
+#define ERLCR_TBF_MODE_MASK BIT(7)
+#define ERLCR_MANT_MASK GENMASK(6, 0)
+
+#define MT753X_GERLCR 0x10e0
+#define EGR_BC_MASK GENMASK(7, 0)
+#define EGR_BC_CRC 0x4 /* crc */
+#define EGR_BC_CRC_IPG_PREAMBLE 0x18 /* crc + ipg + preamble */
+
/* Register for port STP state control */
#define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100))
#define FID_PST(fid, state) (((state) & 0x3) << ((fid) * 2))
diff --git a/drivers/net/dsa/mv88e6xxx/Kconfig b/drivers/net/dsa/mv88e6xxx/Kconfig
index e3181d5471df..64ae3882d17c 100644
--- a/drivers/net/dsa/mv88e6xxx/Kconfig
+++ b/drivers/net/dsa/mv88e6xxx/Kconfig
@@ -17,3 +17,13 @@ config NET_DSA_MV88E6XXX_PTP
help
Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch
chips that support it.
+
+config NET_DSA_MV88E6XXX_LEDS
+ bool "LED support for Marvell 88E6xxx"
+ default y
+ depends on NET_DSA_MV88E6XXX
+ depends on LEDS_CLASS=y || LEDS_CLASS=NET_DSA_MV88E6XXX
+ depends on LEDS_TRIGGERS
+ help
+ This enabled support for controlling the LEDs attached to the
+ Marvell 88E6xxx switch chips.
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
index a9a9651187db..dd961081d631 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -9,6 +9,7 @@ mv88e6xxx-objs += global2.o
mv88e6xxx-objs += global2_avb.o
mv88e6xxx-objs += global2_scratch.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o
+mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_LEDS) += leds.o
mv88e6xxx-objs += pcs-6185.o
mv88e6xxx-objs += pcs-6352.o
mv88e6xxx-objs += pcs-639x.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 284270a4ade1..3a792f79270d 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -27,6 +27,7 @@
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/platform_data/mv88e6xxx.h>
+#include <linux/property.h>
#include <linux/netdevice.h>
#include <linux/gpio/consumer.h>
#include <linux/phylink.h>
@@ -867,7 +868,7 @@ mv88e6xxx_mac_select_pcs(struct phylink_config *config,
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct mv88e6xxx_chip *chip = dp->ds->priv;
- struct phylink_pcs *pcs = ERR_PTR(-EOPNOTSUPP);
+ struct phylink_pcs *pcs = NULL;
if (chip->info->ops->pcs_ops)
pcs = chip->info->ops->pcs_ops->pcs_select(chip, dp->index,
@@ -1152,42 +1153,37 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
return value;
}
-static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
- uint8_t *data, int types)
+static void mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t **data, int types)
{
const struct mv88e6xxx_hw_stat *stat;
- int i, j;
+ int i;
- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
+ for (i = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (stat->type & types) {
- memcpy(data + j * ETH_GSTRING_LEN, stat->string,
- ETH_GSTRING_LEN);
- j++;
- }
+ if (stat->type & types)
+ ethtool_puts(data, stat->string);
}
-
- return j;
}
-static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
- uint8_t *data)
+static void mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t **data)
{
- return mv88e6xxx_stats_get_strings(chip, data,
- STATS_TYPE_BANK0 | STATS_TYPE_PORT);
+ mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_PORT);
}
-static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip,
- uint8_t *data)
+static void mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t **data)
{
- return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0);
+ mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0);
}
-static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
- uint8_t *data)
+static void mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t **data)
{
- return mv88e6xxx_stats_get_strings(chip, data,
- STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
+ mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
}
static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = {
@@ -1198,21 +1194,18 @@ static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = {
"vtu_miss_violation",
};
-static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data)
+static void mv88e6xxx_atu_vtu_get_strings(uint8_t **data)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++)
- strscpy(data + i * ETH_GSTRING_LEN,
- mv88e6xxx_atu_vtu_stats_strings[i],
- ETH_GSTRING_LEN);
+ ethtool_puts(data, mv88e6xxx_atu_vtu_stats_strings[i]);
}
static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
u32 stringset, uint8_t *data)
{
struct mv88e6xxx_chip *chip = ds->priv;
- int count = 0;
if (stringset != ETH_SS_STATS)
return;
@@ -1220,15 +1213,12 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
mv88e6xxx_reg_lock(chip);
if (chip->info->ops->stats_get_strings)
- count = chip->info->ops->stats_get_strings(chip, data);
+ chip->info->ops->stats_get_strings(chip, &data);
- if (chip->info->ops->serdes_get_strings) {
- data += count * ETH_GSTRING_LEN;
- count = chip->info->ops->serdes_get_strings(chip, port, data);
- }
+ if (chip->info->ops->serdes_get_strings)
+ chip->info->ops->serdes_get_strings(chip, port, &data);
- data += count * ETH_GSTRING_LEN;
- mv88e6xxx_atu_vtu_get_strings(data);
+ mv88e6xxx_atu_vtu_get_strings(&data);
mv88e6xxx_reg_unlock(chip);
}
@@ -1929,36 +1919,9 @@ static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
return chip->info->ops->vtu_loadpurge(chip, entry);
}
-static int mv88e6xxx_fid_map_vlan(struct mv88e6xxx_chip *chip,
- const struct mv88e6xxx_vtu_entry *entry,
- void *_fid_bitmap)
-{
- unsigned long *fid_bitmap = _fid_bitmap;
-
- set_bit(entry->fid, fid_bitmap);
- return 0;
-}
-
-int mv88e6xxx_fid_map(struct mv88e6xxx_chip *chip, unsigned long *fid_bitmap)
-{
- bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
-
- /* Every FID has an associated VID, so walking the VTU
- * will discover the full set of FIDs in use.
- */
- return mv88e6xxx_vtu_walk(chip, mv88e6xxx_fid_map_vlan, fid_bitmap);
-}
-
static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
{
- DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
- int err;
-
- err = mv88e6xxx_fid_map(chip, fid_bitmap);
- if (err)
- return err;
-
- *fid = find_first_zero_bit(fid_bitmap, MV88E6XXX_N_FID);
+ *fid = find_first_zero_bit(chip->fid_bitmap, MV88E6XXX_N_FID);
if (unlikely(*fid >= mv88e6xxx_num_databases(chip)))
return -ENOSPC;
@@ -2665,6 +2628,9 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
port, vid);
}
+ /* Record FID used in SW FID map */
+ bitmap_set(chip->fid_bitmap, vlan.fid, 1);
+
return 0;
}
@@ -2770,6 +2736,9 @@ static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip,
err = mv88e6xxx_mst_put(chip, vlan.sid);
if (err)
return err;
+
+ /* Record FID freed in SW FID map */
+ bitmap_clear(chip->fid_bitmap, vlan.fid, 1);
}
return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
@@ -3371,14 +3340,44 @@ static int mv88e6xxx_setup_upstream_port(struct mv88e6xxx_chip *chip, int port)
static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
{
struct device_node *phy_handle = NULL;
+ struct fwnode_handle *ports_fwnode;
+ struct fwnode_handle *port_fwnode;
struct dsa_switch *ds = chip->ds;
+ struct mv88e6xxx_port *p;
struct dsa_port *dp;
int tx_amp;
int err;
u16 reg;
+ u32 val;
+
+ p = &chip->ports[port];
+ p->chip = chip;
+ p->port = port;
+
+ /* Look up corresponding fwnode if any */
+ ports_fwnode = device_get_named_child_node(chip->dev, "ethernet-ports");
+ if (!ports_fwnode)
+ ports_fwnode = device_get_named_child_node(chip->dev, "ports");
+ if (ports_fwnode) {
+ fwnode_for_each_child_node(ports_fwnode, port_fwnode) {
+ if (fwnode_property_read_u32(port_fwnode, "reg", &val))
+ continue;
+ if (val == port) {
+ p->fwnode = port_fwnode;
+ p->fiber = fwnode_property_present(port_fwnode, "sfp");
+ break;
+ }
+ }
+ fwnode_handle_put(ports_fwnode);
+ } else {
+ dev_dbg(chip->dev, "no ethernet ports node defined for the device\n");
+ }
- chip->ports[port].chip = chip;
- chip->ports[port].port = port;
+ if (chip->info->ops->port_setup_leds) {
+ err = chip->info->ops->port_setup_leds(chip, port);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+ }
err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
SPEED_UNFORCED, DUPLEX_UNFORCED,
@@ -4597,6 +4596,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_leds = mv88e6xxx_port_setup_leds,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
@@ -4699,6 +4699,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_leds = mv88e6xxx_port_setup_leds,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
@@ -4974,6 +4975,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_leds = mv88e6xxx_port_setup_leds,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
@@ -5396,6 +5398,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_leds = mv88e6xxx_port_setup_leds,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index a54682240839..9fe8e8a7856b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -13,7 +13,9 @@
#include <linux/irq.h>
#include <linux/gpio/consumer.h>
#include <linux/kthread.h>
+#include <linux/leds.h>
#include <linux/phy.h>
+#include <linux/property.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#include <net/dsa.h>
@@ -276,6 +278,7 @@ struct mv88e6xxx_vlan {
struct mv88e6xxx_port {
struct mv88e6xxx_chip *chip;
int port;
+ struct fwnode_handle *fwnode;
struct mv88e6xxx_vlan bridge_pvid;
u64 serdes_stats[2];
u64 atu_member_violation;
@@ -290,6 +293,11 @@ struct mv88e6xxx_port {
struct devlink_region *region;
void *pcs_private;
+ /* LED related information */
+ bool fiber;
+ struct led_classdev led0;
+ struct led_classdev led1;
+
/* MacAuth Bypass control flag */
bool mab;
};
@@ -434,6 +442,9 @@ struct mv88e6xxx_chip {
/* Bridge MST to SID mappings */
struct list_head msts;
+
+ /* FID map */
+ DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
};
struct mv88e6xxx_bus_ops {
@@ -574,6 +585,9 @@ struct mv88e6xxx_ops {
phy_interface_t mode);
int (*port_get_cmode)(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
+ /* LED control */
+ int (*port_setup_leds)(struct mv88e6xxx_chip *chip, int port);
+
/* Some devices have a per port register indicating what is
* the upstream port this port should forward to.
*/
@@ -592,7 +606,7 @@ struct mv88e6xxx_ops {
/* Return the number of strings describing statistics */
int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
- int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
+ void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t **data);
size_t (*stats_get_stat)(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data);
@@ -619,8 +633,8 @@ struct mv88e6xxx_ops {
/* Statistics from the SERDES interface */
int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
- int (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port,
- uint8_t *data);
+ int (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port,
+ uint8_t **data);
size_t (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
@@ -830,6 +844,4 @@ int mv88e6xxx_vtu_walk(struct mv88e6xxx_chip *chip,
void *priv),
void *priv);
-int mv88e6xxx_fid_map(struct mv88e6xxx_chip *chip, unsigned long *bitmap);
-
#endif /* _MV88E6XXX_CHIP_H */
diff --git a/drivers/net/dsa/mv88e6xxx/devlink.c b/drivers/net/dsa/mv88e6xxx/devlink.c
index a08dab75e0c0..795c8df7b6a7 100644
--- a/drivers/net/dsa/mv88e6xxx/devlink.c
+++ b/drivers/net/dsa/mv88e6xxx/devlink.c
@@ -374,10 +374,9 @@ static int mv88e6xxx_region_atu_snapshot(struct devlink *dl,
u8 **data)
{
struct dsa_switch *ds = dsa_devlink_to_ds(dl);
- DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
struct mv88e6xxx_devlink_atu_entry *table;
struct mv88e6xxx_chip *chip = ds->priv;
- int fid = -1, count, err;
+ int fid = -1, err = 0, count;
table = kmalloc_array(mv88e6xxx_num_databases(chip),
sizeof(struct mv88e6xxx_devlink_atu_entry),
@@ -392,14 +391,8 @@ static int mv88e6xxx_region_atu_snapshot(struct devlink *dl,
mv88e6xxx_reg_lock(chip);
- err = mv88e6xxx_fid_map(chip, fid_bitmap);
- if (err) {
- kfree(table);
- goto out;
- }
-
while (1) {
- fid = find_next_bit(fid_bitmap, MV88E6XXX_N_FID, fid + 1);
+ fid = find_next_bit(chip->fid_bitmap, MV88E6XXX_N_FID, fid + 1);
if (fid == MV88E6XXX_N_FID)
break;
diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88e6xxx/global1_vtu.c
index bcfb4a812055..b524f27a2f0d 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c
@@ -471,6 +471,9 @@ int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
{
int err;
+ /* As part of the VTU flush, refresh FID map */
+ bitmap_zero(chip->fid_bitmap, MV88E6XXX_N_FID);
+
err = mv88e6xxx_g1_vtu_op_wait(chip);
if (err)
return err;
diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c
new file mode 100644
index 000000000000..1c88bfaea46b
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/leds.c
@@ -0,0 +1,839 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/bitfield.h>
+#include <linux/leds.h>
+#include <linux/property.h>
+
+#include "chip.h"
+#include "global2.h"
+#include "port.h"
+
+/* Offset 0x16: LED control */
+
+static int mv88e6xxx_port_led_write(struct mv88e6xxx_chip *chip, int port, u16 reg)
+{
+ reg |= MV88E6XXX_PORT_LED_CONTROL_UPDATE;
+
+ return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL, reg);
+}
+
+static int mv88e6xxx_port_led_read(struct mv88e6xxx_chip *chip, int port,
+ u16 ptr, u16 *val)
+{
+ int err;
+
+ err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL, ptr);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_LED_CONTROL, val);
+ *val &= 0x3ff;
+
+ return err;
+}
+
+static int mv88e6xxx_led_brightness_set(struct mv88e6xxx_port *p, int led,
+ int brightness)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_led_read(p->chip, p->port,
+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL,
+ &reg);
+ if (err)
+ return err;
+
+ if (led == 1)
+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
+ else
+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
+
+ if (brightness) {
+ /* Selector 0x0f == Force LED ON */
+ if (led == 1)
+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELF;
+ else
+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELF;
+ } else {
+ /* Selector 0x0e == Force LED OFF */
+ if (led == 1)
+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE;
+ else
+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE;
+ }
+
+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL;
+
+ return mv88e6xxx_port_led_write(p->chip, p->port, reg);
+}
+
+static int mv88e6xxx_led0_brightness_set_blocking(struct led_classdev *ldev,
+ enum led_brightness brightness)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
+ int err;
+
+ mv88e6xxx_reg_lock(p->chip);
+ err = mv88e6xxx_led_brightness_set(p, 0, brightness);
+ mv88e6xxx_reg_unlock(p->chip);
+
+ return err;
+}
+
+static int mv88e6xxx_led1_brightness_set_blocking(struct led_classdev *ldev,
+ enum led_brightness brightness)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
+ int err;
+
+ mv88e6xxx_reg_lock(p->chip);
+ err = mv88e6xxx_led_brightness_set(p, 1, brightness);
+ mv88e6xxx_reg_unlock(p->chip);
+
+ return err;
+}
+
+struct mv88e6xxx_led_hwconfig {
+ int led;
+ u8 portmask;
+ unsigned long rules;
+ bool fiber;
+ bool blink_activity;
+ u16 selector;
+};
+
+/* The following is a lookup table to check what rules we can support on a
+ * certain LED given restrictions such as that some rules only work with fiber
+ * (SFP) connections and some blink on activity by default.
+ */
+#define MV88E6XXX_PORTS_0_3 (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define MV88E6XXX_PORTS_4_5 (BIT(4) | BIT(5))
+#define MV88E6XXX_PORT_4 BIT(4)
+#define MV88E6XXX_PORT_5 BIT(5)
+
+/* Entries are listed in selector order.
+ *
+ * These configurations vary across different switch families, list
+ * different tables per-family here.
+ */
+static const struct mv88e6xxx_led_hwconfig mv88e6352_led_hwconfigs[] = {
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORT_4,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL0,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORT_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL0,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_4_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK_100),
+ .blink_activity = true,
+ .fiber = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_4_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .fiber = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_4_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .fiber = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_4_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK_100),
+ .blink_activity = true,
+ .fiber = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL3,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_1000),
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_4_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .fiber = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORT_4,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL4,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORT_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL5,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORT_4,
+ .rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORT_5,
+ .rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL7,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000),
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL7,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL8,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORT_5,
+ .rules = BIT(TRIGGER_NETDEV_LINK),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_10),
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL9,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_100),
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL9,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_10),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SELA,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_100),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SELA,
+ },
+ {
+ .led = 0,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000),
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SELB,
+ },
+ {
+ .led = 1,
+ .portmask = MV88E6XXX_PORTS_0_3,
+ .rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000),
+ .blink_activity = true,
+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SELB,
+ },
+};
+
+/* mv88e6xxx_led_match_selector() - look up the appropriate LED mode selector
+ * @p: port state container
+ * @led: LED number, 0 or 1
+ * @blink_activity: blink the LED (usually blink on indicated activity)
+ * @fiber: the link is connected to fiber such as SFP
+ * @rules: LED status flags from the LED classdev core
+ * @selector: fill in the selector in this parameter with an OR operation
+ */
+static int mv88e6xxx_led_match_selector(struct mv88e6xxx_port *p, int led, bool blink_activity,
+ bool fiber, unsigned long rules, u16 *selector)
+{
+ const struct mv88e6xxx_led_hwconfig *conf;
+ int i;
+
+ /* No rules means we turn the LED off */
+ if (!rules) {
+ if (led == 1)
+ *selector |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE;
+ else
+ *selector |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE;
+ return 0;
+ }
+
+ /* TODO: these rules are for MV88E6352, when adding other families,
+ * think about making sure you select the table that match the
+ * specific switch family.
+ */
+ for (i = 0; i < ARRAY_SIZE(mv88e6352_led_hwconfigs); i++) {
+ conf = &mv88e6352_led_hwconfigs[i];
+
+ if (conf->led != led)
+ continue;
+
+ if (!(conf->portmask & BIT(p->port)))
+ continue;
+
+ if (conf->blink_activity != blink_activity)
+ continue;
+
+ if (conf->fiber != fiber)
+ continue;
+
+ if (conf->rules == rules) {
+ dev_dbg(p->chip->dev, "port%d LED %d set selector %04x for rules %08lx\n",
+ p->port, led, conf->selector, rules);
+ *selector |= conf->selector;
+ return 0;
+ }
+ }
+
+ return -EOPNOTSUPP;
+}
+
+/* mv88e6xxx_led_match_selector() - find Linux netdev rules from a selector value
+ * @p: port state container
+ * @selector: the selector value from the LED actity register
+ * @led: LED number, 0 or 1
+ * @rules: Linux netdev activity rules found from selector
+ */
+static int
+mv88e6xxx_led_match_rule(struct mv88e6xxx_port *p, u16 selector, int led, unsigned long *rules)
+{
+ const struct mv88e6xxx_led_hwconfig *conf;
+ int i;
+
+ /* Find the selector in the table, we just look for the right selector
+ * and ignore if the activity has special properties such as blinking
+ * or is fiber-only.
+ */
+ for (i = 0; i < ARRAY_SIZE(mv88e6352_led_hwconfigs); i++) {
+ conf = &mv88e6352_led_hwconfigs[i];
+
+ if (conf->led != led)
+ continue;
+
+ if (!(conf->portmask & BIT(p->port)))
+ continue;
+
+ if (conf->selector == selector) {
+ dev_dbg(p->chip->dev, "port%d LED %d has selector %04x, rules %08lx\n",
+ p->port, led, selector, conf->rules);
+ *rules = conf->rules;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/* mv88e6xxx_led_get_selector() - get the appropriate LED mode selector
+ * @p: port state container
+ * @led: LED number, 0 or 1
+ * @fiber: the link is connected to fiber such as SFP
+ * @rules: LED status flags from the LED classdev core
+ * @selector: fill in the selector in this parameter with an OR operation
+ */
+static int mv88e6xxx_led_get_selector(struct mv88e6xxx_port *p, int led,
+ bool fiber, unsigned long rules, u16 *selector)
+{
+ int err;
+
+ /* What happens here is that we first try to locate a trigger with solid
+ * indicator (such as LED is on for a 1000 link) else we try a second
+ * sweep to find something suitable with a trigger that will blink on
+ * activity.
+ */
+ err = mv88e6xxx_led_match_selector(p, led, false, fiber, rules, selector);
+ if (err)
+ return mv88e6xxx_led_match_selector(p, led, true, fiber, rules, selector);
+
+ return 0;
+}
+
+/* Sets up the hardware blinking period */
+static int mv88e6xxx_led_set_blinking_period(struct mv88e6xxx_port *p, int led,
+ unsigned long delay_on, unsigned long delay_off)
+{
+ unsigned long period;
+ u16 reg;
+
+ period = delay_on + delay_off;
+
+ reg = 0;
+
+ switch (period) {
+ case 21:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_21MS;
+ break;
+ case 42:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_42MS;
+ break;
+ case 84:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_84MS;
+ break;
+ case 168:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_168MS;
+ break;
+ case 336:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_336MS;
+ break;
+ case 672:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_672MS;
+ break;
+ default:
+ /* Fall back to software blinking */
+ return -EINVAL;
+ }
+
+ /* This is essentially PWM duty cycle: how long time of the period
+ * will the LED be on. Zero isn't great in most cases.
+ */
+ switch (delay_on) {
+ case 0:
+ /* This is usually pretty useless and will make the LED look OFF */
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_NONE;
+ break;
+ case 21:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS;
+ break;
+ case 42:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_42MS;
+ break;
+ case 84:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_84MS;
+ break;
+ case 168:
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_168MS;
+ break;
+ default:
+ /* Just use something non-zero */
+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS;
+ break;
+ }
+
+ /* Set up blink rate */
+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_STRETCH_BLINK;
+
+ return mv88e6xxx_port_led_write(p->chip, p->port, reg);
+}
+
+static int mv88e6xxx_led_blink_set(struct mv88e6xxx_port *p, int led,
+ unsigned long *delay_on, unsigned long *delay_off)
+{
+ u16 reg;
+ int err;
+
+ /* Choose a sensible default 336 ms (~3 Hz) */
+ if ((*delay_on == 0) && (*delay_off == 0)) {
+ *delay_on = 168;
+ *delay_off = 168;
+ }
+
+ /* No off delay is just on */
+ if (*delay_off == 0)
+ return mv88e6xxx_led_brightness_set(p, led, 1);
+
+ err = mv88e6xxx_led_set_blinking_period(p, led, *delay_on, *delay_off);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_led_read(p->chip, p->port,
+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL,
+ &reg);
+ if (err)
+ return err;
+
+ if (led == 1)
+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
+ else
+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
+
+ /* This will select the forced blinking status */
+ if (led == 1)
+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELD;
+ else
+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELD;
+
+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL;
+
+ return mv88e6xxx_port_led_write(p->chip, p->port, reg);
+}
+
+static int mv88e6xxx_led0_blink_set(struct led_classdev *ldev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
+ int err;
+
+ mv88e6xxx_reg_lock(p->chip);
+ err = mv88e6xxx_led_blink_set(p, 0, delay_on, delay_off);
+ mv88e6xxx_reg_unlock(p->chip);
+
+ return err;
+}
+
+static int mv88e6xxx_led1_blink_set(struct led_classdev *ldev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
+ int err;
+
+ mv88e6xxx_reg_lock(p->chip);
+ err = mv88e6xxx_led_blink_set(p, 1, delay_on, delay_off);
+ mv88e6xxx_reg_unlock(p->chip);
+
+ return err;
+}
+
+static int
+mv88e6xxx_led0_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
+ u16 selector = 0;
+
+ return mv88e6xxx_led_get_selector(p, 0, p->fiber, rules, &selector);
+}
+
+static int
+mv88e6xxx_led1_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
+ u16 selector = 0;
+
+ return mv88e6xxx_led_get_selector(p, 1, p->fiber, rules, &selector);
+}
+
+static int mv88e6xxx_led_hw_control_set(struct mv88e6xxx_port *p,
+ int led, unsigned long rules)
+{
+ u16 reg;
+ int err;
+
+ err = mv88e6xxx_port_led_read(p->chip, p->port,
+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL,
+ &reg);
+ if (err)
+ return err;
+
+ if (led == 1)
+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
+ else
+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
+
+ err = mv88e6xxx_led_get_selector(p, led, p->fiber, rules, &reg);
+ if (err)
+ return err;
+
+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL;
+
+ if (led == 0)
+ dev_dbg(p->chip->dev, "LED 0 hw control on port %d trigger selector 0x%02x\n",
+ p->port,
+ (unsigned int)(reg & MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK));
+ else
+ dev_dbg(p->chip->dev, "LED 1 hw control on port %d trigger selector 0x%02x\n",
+ p->port,
+ (unsigned int)(reg & MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK) >> 4);
+
+ return mv88e6xxx_port_led_write(p->chip, p->port, reg);
+}
+
+static int
+mv88e6xxx_led_hw_control_get(struct mv88e6xxx_port *p, int led, unsigned long *rules)
+{
+ u16 val;
+ int err;
+
+ mv88e6xxx_reg_lock(p->chip);
+ err = mv88e6xxx_port_led_read(p->chip, p->port,
+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL, &val);
+ mv88e6xxx_reg_unlock(p->chip);
+ if (err)
+ return err;
+
+ /* Mask out the selector bits for this port */
+ if (led == 1) {
+ val &= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
+ /* It's forced blinking/OFF/ON */
+ if (val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELD ||
+ val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELE ||
+ val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELF) {
+ *rules = 0;
+ return 0;
+ }
+ } else {
+ val &= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
+ /* It's forced blinking/OFF/ON */
+ if (val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELD ||
+ val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELE ||
+ val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELF) {
+ *rules = 0;
+ return 0;
+ }
+ }
+
+ err = mv88e6xxx_led_match_rule(p, val, led, rules);
+ if (!err)
+ return 0;
+
+ dev_dbg(p->chip->dev, "couldn't find matching selector for %04x\n", val);
+ *rules = 0;
+ return 0;
+}
+
+static int
+mv88e6xxx_led0_hw_control_set(struct led_classdev *ldev, unsigned long rules)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
+ int err;
+
+ mv88e6xxx_reg_lock(p->chip);
+ err = mv88e6xxx_led_hw_control_set(p, 0, rules);
+ mv88e6xxx_reg_unlock(p->chip);
+
+ return err;
+}
+
+static int
+mv88e6xxx_led1_hw_control_set(struct led_classdev *ldev, unsigned long rules)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
+ int err;
+
+ mv88e6xxx_reg_lock(p->chip);
+ err = mv88e6xxx_led_hw_control_set(p, 1, rules);
+ mv88e6xxx_reg_unlock(p->chip);
+
+ return err;
+}
+
+static int
+mv88e6xxx_led0_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
+
+ return mv88e6xxx_led_hw_control_get(p, 0, rules);
+}
+
+static int
+mv88e6xxx_led1_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
+
+ return mv88e6xxx_led_hw_control_get(p, 1, rules);
+}
+
+static struct device *mv88e6xxx_led_hw_control_get_device(struct mv88e6xxx_port *p)
+{
+ struct dsa_port *dp;
+
+ dp = dsa_to_port(p->chip->ds, p->port);
+ if (!dp)
+ return NULL;
+ if (dp->user)
+ return &dp->user->dev;
+ return NULL;
+}
+
+static struct device *
+mv88e6xxx_led0_hw_control_get_device(struct led_classdev *ldev)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
+
+ return mv88e6xxx_led_hw_control_get_device(p);
+}
+
+static struct device *
+mv88e6xxx_led1_hw_control_get_device(struct led_classdev *ldev)
+{
+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
+
+ return mv88e6xxx_led_hw_control_get_device(p);
+}
+
+int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, int port)
+{
+ struct fwnode_handle *led = NULL, *leds = NULL;
+ struct led_init_data init_data = { };
+ enum led_default_state state;
+ struct mv88e6xxx_port *p;
+ struct led_classdev *l;
+ struct device *dev;
+ u32 led_num;
+ int ret;
+
+ /* LEDs are on ports 1,2,3,4, 5 and 6 (index 0..5), no more */
+ if (port > 5)
+ return -EOPNOTSUPP;
+
+ p = &chip->ports[port];
+ if (!p->fwnode)
+ return 0;
+
+ dev = chip->dev;
+
+ leds = fwnode_get_named_child_node(p->fwnode, "leds");
+ if (!leds) {
+ dev_dbg(dev, "No Leds node specified in device tree for port %d!\n",
+ port);
+ return 0;
+ }
+
+ fwnode_for_each_child_node(leds, led) {
+ /* Reg represent the led number of the port, max 2
+ * LEDs can be connected to each port, in some designs
+ * only one LED is connected.
+ */
+ if (fwnode_property_read_u32(led, "reg", &led_num))
+ continue;
+ if (led_num > 1) {
+ dev_err(dev, "invalid LED specified port %d\n", port);
+ return -EINVAL;
+ }
+
+ if (led_num == 0)
+ l = &p->led0;
+ else
+ l = &p->led1;
+
+ state = led_init_default_state_get(led);
+ switch (state) {
+ case LEDS_DEFSTATE_ON:
+ l->brightness = 1;
+ mv88e6xxx_led_brightness_set(p, led_num, 1);
+ break;
+ case LEDS_DEFSTATE_KEEP:
+ break;
+ default:
+ l->brightness = 0;
+ mv88e6xxx_led_brightness_set(p, led_num, 0);
+ }
+
+ l->max_brightness = 1;
+ if (led_num == 0) {
+ l->brightness_set_blocking = mv88e6xxx_led0_brightness_set_blocking;
+ l->blink_set = mv88e6xxx_led0_blink_set;
+ l->hw_control_is_supported = mv88e6xxx_led0_hw_control_is_supported;
+ l->hw_control_set = mv88e6xxx_led0_hw_control_set;
+ l->hw_control_get = mv88e6xxx_led0_hw_control_get;
+ l->hw_control_get_device = mv88e6xxx_led0_hw_control_get_device;
+ } else {
+ l->brightness_set_blocking = mv88e6xxx_led1_brightness_set_blocking;
+ l->blink_set = mv88e6xxx_led1_blink_set;
+ l->hw_control_is_supported = mv88e6xxx_led1_hw_control_is_supported;
+ l->hw_control_set = mv88e6xxx_led1_hw_control_set;
+ l->hw_control_get = mv88e6xxx_led1_hw_control_get;
+ l->hw_control_get_device = mv88e6xxx_led1_hw_control_get_device;
+ }
+ l->hw_control_trigger = "netdev";
+
+ init_data.default_label = ":port";
+ init_data.fwnode = led;
+ init_data.devname_mandatory = true;
+ init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d:0%d", chip->info->name,
+ port, led_num);
+ if (!init_data.devicename)
+ return -ENOMEM;
+
+ ret = devm_led_classdev_register_ext(dev, l, &init_data);
+ kfree(init_data.devicename);
+
+ if (ret) {
+ dev_err(dev, "Failed to init LED %d for port %d", led_num, port);
+ return ret;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 04053fdc6489..dc777ddce1f3 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -12,6 +12,7 @@
#include <linux/if_bridge.h>
#include <linux/phy.h>
#include <linux/phylink.h>
+#include <linux/property.h>
#include "chip.h"
#include "global2.h"
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index ddadeb9bfdae..c1d2f99efb1c 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -309,6 +309,130 @@
/* Offset 0x13: OutFiltered Counter */
#define MV88E6XXX_PORT_OUT_FILTERED 0x13
+/* Offset 0x16: LED Control */
+#define MV88E6XXX_PORT_LED_CONTROL 0x16
+#define MV88E6XXX_PORT_LED_CONTROL_UPDATE BIT(15)
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_MASK GENMASK(14, 12)
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL (0x00 << 12) /* Control for LED 0 and 1 */
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_STRETCH_BLINK (0x06 << 12) /* Stetch and Blink Rate */
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_CNTL_SPECIAL (0x07 << 12) /* Control for the Port's Special LED */
+#define MV88E6XXX_PORT_LED_CONTROL_DATA_MASK GENMASK(10, 0)
+/* Selection masks valid for either port 1,2,3,4 or 5 */
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK GENMASK(3, 0)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK GENMASK(7, 4)
+/* Selection control for LED 0 and 1, ports 5 and 6 only has LED 0
+ * Bits Function
+ * 0..3 LED 0 control selector on ports 1-5
+ * 4..7 LED 1 control selector on ports 1-4 on port 5 this controls LED 0 of port 6
+ *
+ * Sel Port LED Function for the 6352 family:
+ * 0 1-4 0 Link/Act/Speed by Blink Rate (off=no link, on=link, blink=activity, blink speed=link speed)
+ * 1-4 1 Port 2's Special LED
+ * 5-6 0 Port 5 Link/Act (off=no link, on=link, blink=activity)
+ * 5-6 1 Port 6 Link/Act (off=no link, on=link 1000, blink=activity)
+ * 1 1-4 0 100/1000 Link/Act (off=no link, on=100 or 1000 link, blink=activity)
+ * 1-4 1 10/100 Link Act (off=no link, on=10 or 100 link, blink=activity)
+ * 5-6 0 Fiber 100 Link/Act (off=no link, on=link 100, blink=activity)
+ * 5-6 1 Fiber 1000 Link/Act (off=no link, on=link 1000, blink=activity)
+ * 2 1-4 0 1000 Link/Act (off=no link, on=link 1000, blink=activity)
+ * 1-4 1 10/100 Link/Act (off=no link, on=10 or 100 link, blink=activity)
+ * 5-6 0 Fiber 1000 Link/Act (off=no link, on=link 1000, blink=activity)
+ * 5-6 1 Fiber 100 Link/Act (off=no link, on=link 100, blink=activity)
+ * 3 1-4 0 Link/Act (off=no link, on=link, blink=activity)
+ * 1-4 1 1000 Link (off=no link, on=1000 link)
+ * 5-6 0 Port 0's Special LED
+ * 5-6 1 Fiber Link (off=no link, on=link)
+ * 4 1-4 0 Port 0's Special LED
+ * 1-4 1 Port 1's Special LED
+ * 5-6 0 Port 1's Special LED
+ * 5-6 1 Port 5 Link/Act (off=no link, on=link, blink=activity)
+ * 5 1-4 0 Reserved
+ * 1-4 1 Reserved
+ * 5-6 0 Port 2's Special LED
+ * 5-6 1 Port 6 Link (off=no link, on=link)
+ * 6 1-4 0 Duplex/Collision (off=half-duplex,on=full-duplex,blink=collision)
+ * 1-4 1 10/1000 Link/Act (off=no link, on=10 or 1000 link, blink=activity)
+ * 5-6 0 Port 5 Duplex/Collision (off=half-duplex, on=full-duplex, blink=col)
+ * 5-6 1 Port 6 Duplex/Collision (off=half-duplex, on=full-duplex, blink=col)
+ * 7 1-4 0 10/1000 Link/Act (off=no link, on=10 or 1000 link, blink=activity)
+ * 1-4 1 10/1000 Link (off=no link, on=10 or 1000 link)
+ * 5-6 0 Port 5 Link/Act/Speed by Blink rate (off=no link, on=link, blink=activity, blink speed=link speed)
+ * 5-6 1 Port 6 Link/Act/Speed by Blink rate (off=no link, on=link, blink=activity, blink speed=link speed)
+ * 8 1-4 0 Link (off=no link, on=link)
+ * 1-4 1 Activity (off=no link, blink on=activity)
+ * 5-6 0 Port 6 Link/Act (off=no link, on=link, blink=activity)
+ * 5-6 1 Port 0's Special LED
+ * 9 1-4 0 10 Link (off=no link, on=10 link)
+ * 1-4 1 100 Link (off=no link, on=100 link)
+ * 5-6 0 Reserved
+ * 5-6 1 Port 1's Special LED
+ * a 1-4 0 10 Link/Act (off=no link, on=10 link, blink=activity)
+ * 1-4 1 100 Link/Act (off=no link, on=100 link, blink=activity)
+ * 5-6 0 Reserved
+ * 5-6 1 Port 2's Special LED
+ * b 1-4 0 100/1000 Link (off=no link, on=100 or 1000 link)
+ * 1-4 1 10/100 Link (off=no link, on=100 link, blink=activity)
+ * 5-6 0 Reserved
+ * 5-6 1 Reserved
+ * c * * PTP Act (blink on=PTP activity)
+ * d * * Force Blink
+ * e * * Force Off
+ * f * * Force On
+ */
+/* Select LED0 output */
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL0 0x0
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1 0x1
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2 0x2
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL3 0x3
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL4 0x4
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL5 0x5
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6 0x6
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL7 0x7
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8 0x8
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL9 0x9
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELA 0xa
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELB 0xb
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELC 0xc
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELD 0xd
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELE 0xe
+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELF 0xf
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL0 (0x0 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1 (0x1 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2 (0x2 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3 (0x3 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL4 (0x4 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL5 (0x5 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6 (0x6 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL7 (0x7 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL8 (0x8 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL9 (0x9 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELA (0xa << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELB (0xb << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELC (0xc << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELD (0xd << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELE (0xe << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELF (0xf << 4)
+/* Stretch and Blink Rate Control (Index 0x06 of LED Control) */
+/* Pulse Stretch Selection for all LED's on this port */
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_NONE (0 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS (1 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_42MS (2 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_84MS (3 << 4)
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_168MS (4 << 4)
+/* Blink Rate Selection for all LEDs on this port */
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_21MS 0
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_42MS 1
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_84MS 2
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_168MS 3
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_336MS 4
+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_672MS 5
+ /* Control for Special LED (Index 0x7 of LED Control on Port0) */
+#define MV88E6XXX_PORT_LED_CONTROL_0x07_P0_LAN_LINKACT_SHIFT 0 /* bits 6:0 LAN Link Activity LED */
+/* Control for Special LED (Index 0x7 of LED Control on Port 1) */
+#define MV88E6XXX_PORT_LED_CONTROL_0x07_P1_WAN_LINKACT_SHIFT 0 /* bits 6:0 WAN Link Activity LED */
+/* Control for Special LED (Index 0x7 of LED Control on Port 2) */
+#define MV88E6XXX_PORT_LED_CONTROL_0x07_P2_PTP_ACT 0 /* bits 6:0 PTP Activity */
+
/* Offset 0x18: IEEE Priority Mapping Table */
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
@@ -457,6 +581,15 @@ int mv88e6393x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode);
int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
+#ifdef CONFIG_NET_DSA_MV88E6XXX_LEDS
+int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, int port);
+#else
+static inline int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip,
+ int port)
+{
+ return 0;
+}
+#endif
int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port,
bool drop_untagged);
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port, bool map);
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 01ea53940786..b3330211edbc 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -132,8 +132,8 @@ int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
}
-int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
- int port, uint8_t *data)
+int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
+ uint8_t **data)
{
struct mv88e6352_serdes_hw_stat *stat;
int err, i;
@@ -144,8 +144,7 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
stat = &mv88e6352_serdes_hw_stats[i];
- memcpy(data + i * ETH_GSTRING_LEN, stat->string,
- ETH_GSTRING_LEN);
+ ethtool_puts(data, stat->string);
}
return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
}
@@ -394,8 +393,8 @@ int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
}
-int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
- int port, uint8_t *data)
+int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
+ uint8_t **data)
{
struct mv88e6390_serdes_hw_stat *stat;
int i;
@@ -405,8 +404,7 @@ int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
stat = &mv88e6390_serdes_hw_stats[i];
- memcpy(data + i * ETH_GSTRING_LEN, stat->string,
- ETH_GSTRING_LEN);
+ ethtool_puts(data, stat->string);
}
return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
}
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index ff5c3ab31e15..ad887d8601bc 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -125,13 +125,13 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
int port);
int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
-int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
- int port, uint8_t *data);
+int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
+ uint8_t **data);
size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
-int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
- int port, uint8_t *data);
+int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip, int port,
+ uint8_t **data);
size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
diff --git a/drivers/net/dsa/ocelot/ocelot_ext.c b/drivers/net/dsa/ocelot/ocelot_ext.c
index 5632a7248cd4..450bda18ef37 100644
--- a/drivers/net/dsa/ocelot/ocelot_ext.c
+++ b/drivers/net/dsa/ocelot/ocelot_ext.c
@@ -102,7 +102,7 @@ static struct platform_driver ocelot_ext_switch_driver = {
.of_match_table = ocelot_ext_switch_of_match,
},
.probe = ocelot_ext_probe,
- .remove_new = ocelot_ext_remove,
+ .remove = ocelot_ext_remove,
.shutdown = ocelot_ext_shutdown,
};
module_platform_driver(ocelot_ext_switch_driver);
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 70782649c395..eb3944ba2a72 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -1014,7 +1014,7 @@ MODULE_DEVICE_TABLE(of, seville_of_match);
static struct platform_driver seville_vsc9953_driver = {
.probe = seville_probe,
- .remove_new = seville_remove,
+ .remove = seville_remove,
.shutdown = seville_shutdown,
.driver = {
.name = "mscc_seville",
diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index f8d8c70642c4..59b4a7240b58 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -673,7 +673,7 @@ qca8k_phy_eth_command(struct qca8k_priv *priv, bool read, int phy,
* We therefore need to lock the MDIO bus onto which the switch is
* connected.
*/
- mutex_lock(&priv->bus->mdio_lock);
+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
/* Actually start the request:
* 1. Send mdio master packet
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index 04b758e5a680..5f545dda702b 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -146,7 +146,7 @@ EXPORT_SYMBOL_NS_GPL(realtek_mdio_probe, REALTEK_DSA);
* realtek_mdio_remove() - Remove the driver of an MDIO-connected switch
* @mdiodev: mdio_device to be removed.
*
- * This function should be used as the .remove_new in an mdio_driver. First
+ * This function should be used as the .remove in an mdio_driver. First
* it unregisters the DSA switch and then it calls the common remove function.
*
* Context: Can sleep.
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 88590ae95a75..d750bddf27b4 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -367,7 +367,7 @@ EXPORT_SYMBOL_NS_GPL(realtek_smi_probe, REALTEK_DSA);
* realtek_smi_remove() - Remove the driver of a SMI-connected switch
* @pdev: platform_device to be removed.
*
- * This function should be used as the .remove_new in a platform_driver. First
+ * This function should be used as the .remove in a platform_driver. First
* it unregisters the DSA switch and then it calls the common remove function.
*
* Context: Can sleep.
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index ad7044b295ec..6b9dbdb00941 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -2164,7 +2164,7 @@ static struct platform_driver rtl8365mb_smi_driver = {
.of_match_table = rtl8365mb_of_match,
},
.probe = realtek_smi_probe,
- .remove_new = realtek_smi_remove,
+ .remove = realtek_smi_remove,
.shutdown = realtek_smi_shutdown,
};
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index c7a8cd060587..6ba03f81c882 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -2102,7 +2102,7 @@ static struct platform_driver rtl8366rb_smi_driver = {
.of_match_table = rtl8366rb_of_match,
},
.probe = realtek_smi_probe,
- .remove_new = realtek_smi_remove,
+ .remove = realtek_smi_remove,
.shutdown = realtek_smi_shutdown,
};
diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c
index 92e032972b34..66974379334a 100644
--- a/drivers/net/dsa/rzn1_a5psw.c
+++ b/drivers/net/dsa/rzn1_a5psw.c
@@ -802,10 +802,8 @@ static void a5psw_get_strings(struct dsa_switch *ds, int port, u32 stringset,
if (stringset != ETH_SS_STATS)
return;
- for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++) {
- memcpy(data + u * ETH_GSTRING_LEN, a5psw_stats[u].name,
- ETH_GSTRING_LEN);
- }
+ for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++)
+ ethtool_puts(&data, a5psw_stats[u].name);
}
static void a5psw_get_ethtool_stats(struct dsa_switch *ds, int port,
@@ -1324,7 +1322,7 @@ static struct platform_driver a5psw_driver = {
.of_match_table = a5psw_of_mtable,
},
.probe = a5psw_probe,
- .remove_new = a5psw_remove,
+ .remove = a5psw_remove,
.shutdown = a5psw_shutdown,
};
module_platform_driver(a5psw_driver);
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index 8c66d3bf61f0..dceb96ae9c83 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -278,7 +278,7 @@ struct sja1105_private {
struct mii_bus *mdio_base_t1;
struct mii_bus *mdio_base_tx;
struct mii_bus *mdio_pcs;
- struct dw_xpcs *xpcs[SJA1105_MAX_NUM_PORTS];
+ struct phylink_pcs *pcs[SJA1105_MAX_NUM_PORTS];
struct sja1105_ptp_data ptp_data;
struct sja1105_tas_data tas_data;
};
diff --git a/drivers/net/dsa/sja1105/sja1105_ethtool.c b/drivers/net/dsa/sja1105/sja1105_ethtool.c
index decc6c931dc1..2ea64b1d026d 100644
--- a/drivers/net/dsa/sja1105/sja1105_ethtool.c
+++ b/drivers/net/dsa/sja1105/sja1105_ethtool.c
@@ -586,7 +586,6 @@ void sja1105_get_strings(struct dsa_switch *ds, int port,
{
struct sja1105_private *priv = ds->priv;
enum sja1105_counter_index max_ctr, i;
- char *p = data;
if (stringset != ETH_SS_STATS)
return;
@@ -597,10 +596,8 @@ void sja1105_get_strings(struct dsa_switch *ds, int port,
else
max_ctr = __MAX_SJA1105PQRS_PORT_COUNTER;
- for (i = 0; i < max_ctr; i++) {
- strscpy(p, sja1105_port_counters[i].name, ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < max_ctr; i++)
+ ethtool_puts(&data, sja1105_port_counters[i].name);
}
int sja1105_get_sset_count(struct dsa_switch *ds, int port, int sset)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index d0563ef59acf..f8454f3b6f9c 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -15,7 +15,6 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/of_mdio.h>
-#include <linux/pcs/pcs-xpcs.h>
#include <linux/netdev_features.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
@@ -1257,29 +1256,11 @@ static int sja1105_parse_dt(struct sja1105_private *priv)
return rc;
}
-/* Convert link speed from SJA1105 to ethtool encoding */
-static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv,
- u64 speed)
-{
- if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS])
- return SPEED_10;
- if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS])
- return SPEED_100;
- if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS])
- return SPEED_1000;
- if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS])
- return SPEED_2500;
- return SPEED_UNKNOWN;
-}
-
-/* Set link speed in the MAC configuration for a specific port. */
-static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
- int speed_mbps)
+static int sja1105_set_port_speed(struct sja1105_private *priv, int port,
+ int speed_mbps)
{
struct sja1105_mac_config_entry *mac;
- struct device *dev = priv->ds->dev;
u64 speed;
- int rc;
/* On P/Q/R/S, one can read from the device via the MAC reconfiguration
* tables. On E/T, MAC reconfig tables are not readable, only writable.
@@ -1313,7 +1294,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS];
break;
default:
- dev_err(dev, "Invalid speed %iMbps\n", speed_mbps);
+ dev_err(priv->ds->dev, "Invalid speed %iMbps\n", speed_mbps);
return -EINVAL;
}
@@ -1325,11 +1306,31 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
* we need to configure the PCS only (if even that).
*/
if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII)
- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
+ speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX)
- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS];
- else
- mac[port].speed = speed;
+ speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS];
+
+ mac[port].speed = speed;
+
+ return 0;
+}
+
+/* Write the MAC Configuration Table entry and, if necessary, the CGU settings,
+ * after a link speedchange for this port.
+ */
+static int sja1105_set_port_config(struct sja1105_private *priv, int port)
+{
+ struct sja1105_mac_config_entry *mac;
+ struct device *dev = priv->ds->dev;
+ int rc;
+
+ /* On P/Q/R/S, one can read from the device via the MAC reconfiguration
+ * tables. On E/T, MAC reconfig tables are not readable, only writable.
+ * We have to *know* what the MAC looks like. For the sake of keeping
+ * the code common, we'll use the static configuration tables as a
+ * reasonable approximation for both E/T and P/Q/R/S.
+ */
+ mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
/* Write to the dynamic reconfiguration tables */
rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port,
@@ -1356,12 +1357,8 @@ sja1105_mac_select_pcs(struct phylink_config *config, phy_interface_t iface)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct sja1105_private *priv = dp->ds->priv;
- struct dw_xpcs *xpcs = priv->xpcs[dp->index];
-
- if (xpcs)
- return &xpcs->pcs;
- return NULL;
+ return priv->pcs[dp->index];
}
static void sja1105_mac_config(struct phylink_config *config,
@@ -1390,7 +1387,8 @@ static void sja1105_mac_link_up(struct phylink_config *config,
struct sja1105_private *priv = dp->ds->priv;
int port = dp->index;
- sja1105_adjust_port_config(priv, port, speed);
+ if (!sja1105_set_port_speed(priv, port, speed))
+ sja1105_set_port_config(priv, port);
sja1105_inhibit_tx(priv, BIT(port), false);
}
@@ -2293,8 +2291,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
{
struct ptp_system_timestamp ptp_sts_before;
struct ptp_system_timestamp ptp_sts_after;
- int speed_mbps[SJA1105_MAX_NUM_PORTS];
u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0};
+ u64 mac_speed[SJA1105_MAX_NUM_PORTS];
struct sja1105_mac_config_entry *mac;
struct dsa_switch *ds = priv->ds;
s64 t1, t2, t3, t4;
@@ -2307,17 +2305,16 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
- /* Back up the dynamic link speed changed by sja1105_adjust_port_config
+ /* Back up the dynamic link speed changed by sja1105_set_port_speed()
* in order to temporarily restore it to SJA1105_SPEED_AUTO - which the
* switch wants to see in the static config in order to allow us to
* change it through the dynamic interface later.
*/
for (i = 0; i < ds->num_ports; i++) {
- speed_mbps[i] = sja1105_port_speed_to_ethtool(priv,
- mac[i].speed);
+ mac_speed[i] = mac[i].speed;
mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO];
- if (priv->xpcs[i])
+ if (priv->pcs[i])
bmcr[i] = mdiobus_c45_read(priv->mdio_pcs, i,
MDIO_MMD_VEND2, MDIO_CTRL1);
}
@@ -2374,14 +2371,15 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
}
for (i = 0; i < ds->num_ports; i++) {
- struct dw_xpcs *xpcs = priv->xpcs[i];
+ struct phylink_pcs *pcs = priv->pcs[i];
unsigned int neg_mode;
- rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]);
+ mac[i].speed = mac_speed[i];
+ rc = sja1105_set_port_config(priv, i);
if (rc < 0)
goto out;
- if (!xpcs)
+ if (!pcs)
continue;
if (bmcr[i] & BMCR_ANENABLE)
@@ -2389,7 +2387,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
else
neg_mode = PHYLINK_PCS_NEG_OUTBAND;
- rc = xpcs_do_config(xpcs, priv->phy_mode[i], NULL, neg_mode);
+ rc = pcs->ops->pcs_config(pcs, neg_mode, priv->phy_mode[i],
+ NULL, true);
if (rc < 0)
goto out;
@@ -2405,8 +2404,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
else
speed = SPEED_10;
- xpcs_link_up(&xpcs->pcs, neg_mode, priv->phy_mode[i],
- speed, DUPLEX_FULL);
+ pcs->ops->pcs_link_up(pcs, neg_mode, priv->phy_mode[i],
+ speed, DUPLEX_FULL);
}
}
diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c
index 52ddb4ef259e..84b7169f2974 100644
--- a/drivers/net/dsa/sja1105/sja1105_mdio.c
+++ b/drivers/net/dsa/sja1105/sja1105_mdio.c
@@ -400,7 +400,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
}
for (port = 0; port < ds->num_ports; port++) {
- struct dw_xpcs *xpcs;
+ struct phylink_pcs *pcs;
if (dsa_is_unused_port(ds, port))
continue;
@@ -409,13 +409,13 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
continue;
- xpcs = xpcs_create_mdiodev(bus, port, priv->phy_mode[port]);
- if (IS_ERR(xpcs)) {
- rc = PTR_ERR(xpcs);
+ pcs = xpcs_create_pcs_mdiodev(bus, port);
+ if (IS_ERR(pcs)) {
+ rc = PTR_ERR(pcs);
goto out_pcs_free;
}
- priv->xpcs[port] = xpcs;
+ priv->pcs[port] = pcs;
}
priv->mdio_pcs = bus;
@@ -424,11 +424,10 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
out_pcs_free:
for (port = 0; port < ds->num_ports; port++) {
- if (!priv->xpcs[port])
- continue;
-
- xpcs_destroy(priv->xpcs[port]);
- priv->xpcs[port] = NULL;
+ if (priv->pcs[port]) {
+ xpcs_destroy_pcs(priv->pcs[port]);
+ priv->pcs[port] = NULL;
+ }
}
mdiobus_unregister(bus);
@@ -446,11 +445,10 @@ static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
return;
for (port = 0; port < ds->num_ports; port++) {
- if (!priv->xpcs[port])
- continue;
-
- xpcs_destroy(priv->xpcs[port]);
- priv->xpcs[port] = NULL;
+ if (priv->pcs[port]) {
+ xpcs_destroy_pcs(priv->pcs[port]);
+ priv->pcs[port] = NULL;
+ }
}
mdiobus_unregister(priv->mdio_pcs);
diff --git a/drivers/net/dsa/vitesse-vsc73xx-platform.c b/drivers/net/dsa/vitesse-vsc73xx-platform.c
index 755b7895a15a..7a2e0a619b85 100644
--- a/drivers/net/dsa/vitesse-vsc73xx-platform.c
+++ b/drivers/net/dsa/vitesse-vsc73xx-platform.c
@@ -158,7 +158,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match);
static struct platform_driver vsc73xx_platform_driver = {
.probe = vsc73xx_platform_probe,
- .remove_new = vsc73xx_platform_remove,
+ .remove = vsc73xx_platform_remove,
.shutdown = vsc73xx_platform_shutdown,
.driver = {
.name = "vsc73xx-platform",
diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c
index de3b768f2ff9..4dbcc49a9e52 100644
--- a/drivers/net/dsa/xrs700x/xrs700x.c
+++ b/drivers/net/dsa/xrs700x/xrs700x.c
@@ -91,10 +91,8 @@ static void xrs700x_get_strings(struct dsa_switch *ds, int port,
if (stringset != ETH_SS_STATS)
return;
- for (i = 0; i < ARRAY_SIZE(xrs700x_mibs); i++) {
- strscpy(data, xrs700x_mibs[i].name, ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < ARRAY_SIZE(xrs700x_mibs); i++)
+ ethtool_puts(&data, xrs700x_mibs[i].name);
}
static int xrs700x_get_sset_count(struct dsa_switch *ds, int port, int sset)
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index e9c5e1e11fa0..005d79975f3b 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -168,22 +168,21 @@ static int __init dummy_init_module(void)
{
int i, err = 0;
- down_write(&pernet_ops_rwsem);
- rtnl_lock();
- err = __rtnl_link_register(&dummy_link_ops);
+ err = rtnl_link_register(&dummy_link_ops);
if (err < 0)
- goto out;
+ return err;
+
+ rtnl_net_lock(&init_net);
for (i = 0; i < numdummies && !err; i++) {
err = dummy_init_one();
cond_resched();
}
- if (err < 0)
- __rtnl_link_unregister(&dummy_link_ops);
-out:
- rtnl_unlock();
- up_write(&pernet_ops_rwsem);
+ rtnl_net_unlock(&init_net);
+
+ if (err < 0)
+ rtnl_link_unregister(&dummy_link_ops);
return err;
}
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 082388bb6169..790270912913 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1302,7 +1302,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
if (print_info)
pr_cont(", IRQ %d\n", dev->irq);
/* Tell them about an invalid IRQ. */
- if (dev->irq <= 0 || dev->irq >= nr_irqs)
+ if (dev->irq <= 0 || dev->irq >= irq_get_nr_irqs())
pr_warn(" *** Warning: IRQ %d is unlikely to work! ***\n",
dev->irq);
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 2874680ef24d..e1695d0fbd8b 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -1009,7 +1009,7 @@ static struct platform_driver axdrv = {
.name = "ax88796",
},
.probe = ax_probe,
- .remove_new = ax_remove,
+ .remove = ax_remove,
.suspend = ax_suspend,
.resume = ax_resume,
};
diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c
index 5a0fa995e643..94ff8364cdf0 100644
--- a/drivers/net/ethernet/8390/mcf8390.c
+++ b/drivers/net/ethernet/8390/mcf8390.c
@@ -457,7 +457,7 @@ static struct platform_driver mcf8390_drv = {
.name = "mcf8390",
},
.probe = mcf8390_probe,
- .remove_new = mcf8390_remove,
+ .remove = mcf8390_remove,
};
module_platform_driver(mcf8390_drv);
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
index 350683a09d2e..961019c32842 100644
--- a/drivers/net/ethernet/8390/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
@@ -894,7 +894,7 @@ static int ne_drv_resume(struct platform_device *pdev)
#endif
static struct platform_driver ne_driver = {
- .remove_new = ne_drv_remove,
+ .remove = ne_drv_remove,
.suspend = ne_drv_suspend,
.resume = ne_drv_resume,
.driver = {
diff --git a/drivers/net/ethernet/actions/owl-emac.c b/drivers/net/ethernet/actions/owl-emac.c
index e03193da5874..115f48b3342c 100644
--- a/drivers/net/ethernet/actions/owl-emac.c
+++ b/drivers/net/ethernet/actions/owl-emac.c
@@ -1607,7 +1607,7 @@ static struct platform_driver owl_emac_driver = {
.pm = &owl_emac_pm_ops,
},
.probe = owl_emac_probe,
- .remove_new = owl_emac_remove,
+ .remove = owl_emac_remove,
};
module_platform_driver(owl_emac_driver);
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index adf6f67c5fcb..a593adc16c78 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1565,7 +1565,7 @@ static struct platform_driver greth_of_driver = {
.of_match_table = greth_of_match,
},
.probe = greth_of_probe,
- .remove_new = greth_of_remove,
+ .remove = greth_of_remove,
};
module_platform_driver(greth_of_driver);
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index d761c08fe5c1..2f516b950f4e 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -1142,7 +1142,7 @@ static struct platform_driver emac_driver = {
.of_match_table = emac_of_match,
},
.probe = emac_probe,
- .remove_new = emac_remove,
+ .remove = emac_remove,
.suspend = emac_suspend,
.resume = emac_resume,
};
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 3c112c18ae6a..3f6204de9e6b 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -1519,7 +1519,7 @@ MODULE_DEVICE_TABLE(of, altera_tse_ids);
static struct platform_driver altera_tse_driver = {
.probe = altera_tse_probe,
- .remove_new = altera_tse_remove,
+ .remove = altera_tse_remove,
.suspend = NULL,
.resume = NULL,
.driver = {
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
index d958cda9e58b..66445617fbfb 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.c
+++ b/drivers/net/ethernet/amazon/ena/ena_com.c
@@ -763,25 +763,16 @@ static int ena_com_wait_and_process_admin_cq_interrupts(struct ena_comp_ctx *com
if (comp_ctx->status == ENA_CMD_COMPLETED) {
netdev_err(admin_queue->ena_dev->net_device,
- "The ena device sent a completion but the driver didn't receive a MSI-X interrupt (cmd %d), autopolling mode is %s\n",
- comp_ctx->cmd_opcode, admin_queue->auto_polling ? "ON" : "OFF");
- /* Check if fallback to polling is enabled */
- if (admin_queue->auto_polling)
- admin_queue->polling = true;
+ "The ena device sent a completion but the driver didn't receive a MSI-X interrupt (cmd %d)\n",
+ comp_ctx->cmd_opcode);
} else {
netdev_err(admin_queue->ena_dev->net_device,
"The ena device didn't send a completion for the admin cmd %d status %d\n",
comp_ctx->cmd_opcode, comp_ctx->status);
}
- /* Check if shifted to polling mode.
- * This will happen if there is a completion without an interrupt
- * and autopolling mode is enabled. Continuing normal execution in such case
- */
- if (!admin_queue->polling) {
- admin_queue->running_state = false;
- ret = -ETIME;
- goto err;
- }
+ admin_queue->running_state = false;
+ ret = -ETIME;
+ goto err;
}
ret = ena_com_comp_status_to_errno(admin_queue, comp_ctx->comp_status);
@@ -1650,12 +1641,6 @@ void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling)
ena_dev->admin_queue.polling = polling;
}
-void ena_com_set_admin_auto_polling_mode(struct ena_com_dev *ena_dev,
- bool polling)
-{
- ena_dev->admin_queue.auto_polling = polling;
-}
-
int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev)
{
struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read;
@@ -2198,21 +2183,6 @@ int ena_com_get_ena_srd_info(struct ena_com_dev *ena_dev,
return ret;
}
-int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
- struct ena_admin_basic_stats *stats)
-{
- struct ena_com_stats_ctx ctx;
- int ret;
-
- memset(&ctx, 0x0, sizeof(ctx));
- ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_BASIC);
- if (likely(ret == 0))
- memcpy(stats, &ctx.get_resp.u.basic_stats,
- sizeof(ctx.get_resp.u.basic_stats));
-
- return ret;
-}
-
int ena_com_get_customer_metrics(struct ena_com_dev *ena_dev, char *buffer, u32 len)
{
struct ena_admin_aq_get_stats_cmd *get_cmd;
@@ -2289,24 +2259,6 @@ int ena_com_set_dev_mtu(struct ena_com_dev *ena_dev, u32 mtu)
return ret;
}
-int ena_com_get_offload_settings(struct ena_com_dev *ena_dev,
- struct ena_admin_feature_offload_desc *offload)
-{
- int ret;
- struct ena_admin_get_feat_resp resp;
-
- ret = ena_com_get_feature(ena_dev, &resp,
- ENA_ADMIN_STATELESS_OFFLOAD_CONFIG, 0);
- if (unlikely(ret)) {
- netdev_err(ena_dev->net_device, "Failed to get offload capabilities %d\n", ret);
- return ret;
- }
-
- memcpy(offload, &resp.u.offload, sizeof(resp.u.offload));
-
- return 0;
-}
-
int ena_com_set_hash_function(struct ena_com_dev *ena_dev)
{
struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue;
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h b/drivers/net/ethernet/amazon/ena/ena_com.h
index a372c5e768a7..9414e93d107b 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.h
+++ b/drivers/net/ethernet/amazon/ena/ena_com.h
@@ -224,9 +224,6 @@ struct ena_com_admin_queue {
/* Indicate if the admin queue should poll for completion */
bool polling;
- /* Define if fallback to polling mode should occur */
- bool auto_polling;
-
u16 curr_cmd_id;
/* Indicate that the ena was initialized and can
@@ -493,17 +490,6 @@ bool ena_com_get_admin_running_state(struct ena_com_dev *ena_dev);
*/
void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling);
-/* ena_com_set_admin_auto_polling_mode - Enable autoswitch to polling mode
- * @ena_dev: ENA communication layer struct
- * @polling: Enable/Disable polling mode
- *
- * Set the autopolling mode.
- * If autopolling is on:
- * In case of missing interrupt when data is available switch to polling.
- */
-void ena_com_set_admin_auto_polling_mode(struct ena_com_dev *ena_dev,
- bool polling);
-
/* ena_com_admin_q_comp_intr_handler - admin queue interrupt handler
* @ena_dev: ENA communication layer struct
*
@@ -591,15 +577,6 @@ int ena_com_set_aenq_config(struct ena_com_dev *ena_dev, u32 groups_flag);
int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
struct ena_com_dev_get_features_ctx *get_feat_ctx);
-/* ena_com_get_dev_basic_stats - Get device basic statistics
- * @ena_dev: ENA communication layer struct
- * @stats: stats return value
- *
- * @return: 0 on Success and negative value otherwise.
- */
-int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
- struct ena_admin_basic_stats *stats);
-
/* ena_com_get_eni_stats - Get extended network interface statistics
* @ena_dev: ENA communication layer struct
* @stats: stats return value
@@ -635,15 +612,6 @@ int ena_com_get_customer_metrics(struct ena_com_dev *ena_dev, char *buffer, u32
*/
int ena_com_set_dev_mtu(struct ena_com_dev *ena_dev, u32 mtu);
-/* ena_com_get_offload_settings - Retrieve the device offloads capabilities
- * @ena_dev: ENA communication layer struct
- * @offlad: offload return value
- *
- * @return: 0 on Success and negative value otherwise.
- */
-int ena_com_get_offload_settings(struct ena_com_dev *ena_dev,
- struct ena_admin_feature_offload_desc *offload);
-
/* ena_com_rss_init - Init RSS
* @ena_dev: ENA communication layer struct
* @log_size: indirection log size
diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
index 60fb35ec4b15..a3c934c3de71 100644
--- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c
+++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
@@ -1129,22 +1129,18 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf)
return;
}
- strings_buf = devm_kcalloc(&adapter->pdev->dev,
- ETH_GSTRING_LEN, strings_num,
- GFP_ATOMIC);
+ strings_buf = kcalloc(strings_num, ETH_GSTRING_LEN, GFP_ATOMIC);
if (!strings_buf) {
netif_err(adapter, drv, netdev,
"Failed to allocate strings_buf\n");
return;
}
- data_buf = devm_kcalloc(&adapter->pdev->dev,
- strings_num, sizeof(u64),
- GFP_ATOMIC);
+ data_buf = kcalloc(strings_num, sizeof(u64), GFP_ATOMIC);
if (!data_buf) {
netif_err(adapter, drv, netdev,
"Failed to allocate data buf\n");
- devm_kfree(&adapter->pdev->dev, strings_buf);
+ kfree(strings_buf);
return;
}
@@ -1166,8 +1162,8 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf)
strings_buf + i * ETH_GSTRING_LEN,
data_buf[i]);
- devm_kfree(&adapter->pdev->dev, strings_buf);
- devm_kfree(&adapter->pdev->dev, data_buf);
+ kfree(strings_buf);
+ kfree(data_buf);
}
void ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf)
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index c5b50cfa935a..63c8a2328142 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -1383,7 +1383,7 @@ static void ena_adjust_adaptive_rx_intr_moderation(struct ena_napi *ena_napi)
rx_ring->rx_stats.bytes,
&dim_sample);
- net_dim(&ena_napi->dim, dim_sample);
+ net_dim(&ena_napi->dim, &dim_sample);
rx_ring->per_napi_packets = 0;
}
@@ -1677,9 +1677,9 @@ static int ena_request_mgmnt_irq(struct ena_adapter *adapter)
static int ena_request_io_irq(struct ena_adapter *adapter)
{
u32 io_queue_count = adapter->num_io_queues + adapter->xdp_num_queues;
+ int rc = 0, i, k, irq_idx;
unsigned long flags = 0;
struct ena_irq *irq;
- int rc = 0, i, k;
if (!test_bit(ENA_FLAG_MSIX_ENABLED, &adapter->flags)) {
netif_err(adapter, ifup, adapter->netdev,
@@ -1705,6 +1705,16 @@ static int ena_request_io_irq(struct ena_adapter *adapter)
irq_set_affinity_hint(irq->vector, &irq->affinity_hint_mask);
}
+ /* Now that IO IRQs have been successfully allocated map them to the
+ * corresponding IO NAPI instance. Note that the mgmnt IRQ does not
+ * have a NAPI, so care must be taken to correctly map IRQs to NAPIs.
+ */
+ for (i = 0; i < io_queue_count; i++) {
+ irq_idx = ENA_IO_IRQ_IDX(i);
+ irq = &adapter->irq_tbl[irq_idx];
+ netif_napi_set_irq(&adapter->ena_napi[i].napi, irq->vector);
+ }
+
return rc;
err:
@@ -1811,20 +1821,40 @@ static void ena_napi_disable_in_range(struct ena_adapter *adapter,
int first_index,
int count)
{
+ struct napi_struct *napi;
int i;
- for (i = first_index; i < first_index + count; i++)
- napi_disable(&adapter->ena_napi[i].napi);
+ for (i = first_index; i < first_index + count; i++) {
+ napi = &adapter->ena_napi[i].napi;
+ if (!ENA_IS_XDP_INDEX(adapter, i)) {
+ /* This API is supported for non-XDP queues only */
+ netif_queue_set_napi(adapter->netdev, i,
+ NETDEV_QUEUE_TYPE_TX, NULL);
+ netif_queue_set_napi(adapter->netdev, i,
+ NETDEV_QUEUE_TYPE_RX, NULL);
+ }
+ napi_disable(napi);
+ }
}
static void ena_napi_enable_in_range(struct ena_adapter *adapter,
int first_index,
int count)
{
+ struct napi_struct *napi;
int i;
- for (i = first_index; i < first_index + count; i++)
- napi_enable(&adapter->ena_napi[i].napi);
+ for (i = first_index; i < first_index + count; i++) {
+ napi = &adapter->ena_napi[i].napi;
+ napi_enable(napi);
+ if (!ENA_IS_XDP_INDEX(adapter, i)) {
+ /* This API is supported for non-XDP queues only */
+ netif_queue_set_napi(adapter->netdev, i,
+ NETDEV_QUEUE_TYPE_RX, napi);
+ netif_queue_set_napi(adapter->netdev, i,
+ NETDEV_QUEUE_TYPE_TX, napi);
+ }
+ }
}
/* Configure the Rx forwarding */
diff --git a/drivers/net/ethernet/amd/amd8111e.h b/drivers/net/ethernet/amd/amd8111e.h
index 305232f5476d..e4ee4c28800c 100644
--- a/drivers/net/ethernet/amd/amd8111e.h
+++ b/drivers/net/ethernet/amd/amd8111e.h
@@ -550,7 +550,6 @@ typedef enum {
/* Driver definitions */
-#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_DEVICE_ID_AMD8111E_7462 0x7462
#define MAX_UNITS 8 /* Maximum number of devices possible */
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index 85c978149bf6..0671a066913b 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -1363,7 +1363,7 @@ static void au1000_remove(struct platform_device *pdev)
static struct platform_driver au1000_eth_driver = {
.probe = au1000_probe,
- .remove_new = au1000_remove,
+ .remove = au1000_remove,
.driver = {
.name = "au1000-eth",
},
diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
index c78706d21a6a..0f98b92408ed 100644
--- a/drivers/net/ethernet/amd/sunlance.c
+++ b/drivers/net/ethernet/amd/sunlance.c
@@ -1514,7 +1514,7 @@ static struct platform_driver sunlance_sbus_driver = {
.of_match_table = sunlance_sbus_match,
},
.probe = sunlance_sbus_probe,
- .remove_new = sunlance_sbus_remove,
+ .remove = sunlance_sbus_remove,
};
module_platform_driver(sunlance_sbus_driver);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 5fc94c2f638e..4431ab1c18b3 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -195,23 +195,19 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0; i < XGBE_STATS_COUNT; i++) {
- memcpy(data, xgbe_gstring_stats[i].stat_string,
- ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < XGBE_STATS_COUNT; i++)
+ ethtool_puts(&data, xgbe_gstring_stats[i].stat_string);
+
for (i = 0; i < pdata->tx_ring_count; i++) {
- sprintf(data, "txq_%u_packets", i);
- data += ETH_GSTRING_LEN;
- sprintf(data, "txq_%u_bytes", i);
- data += ETH_GSTRING_LEN;
+ ethtool_sprintf(&data, "txq_%u_packets", i);
+ ethtool_sprintf(&data, "txq_%u_bytes", i);
}
+
for (i = 0; i < pdata->rx_ring_count; i++) {
- sprintf(data, "rxq_%u_packets", i);
- data += ETH_GSTRING_LEN;
- sprintf(data, "rxq_%u_bytes", i);
- data += ETH_GSTRING_LEN;
+ ethtool_sprintf(&data, "rxq_%u_packets", i);
+ ethtool_sprintf(&data, "rxq_%u_bytes", i);
}
+
break;
}
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
index 7912b3b45148..4365bd62942c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
@@ -565,7 +565,7 @@ static struct platform_driver xgbe_driver = {
.pm = &xgbe_platform_pm_ops,
},
.probe = xgbe_platform_probe,
- .remove_new = xgbe_platform_remove,
+ .remove = xgbe_platform_remove,
};
int xgbe_platform_init(void)
diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c
index 9e90c2381491..2a91c84aebdb 100644
--- a/drivers/net/ethernet/apm/xgene-v2/main.c
+++ b/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -734,7 +734,7 @@ static struct platform_driver xge_driver = {
.acpi_match_table = ACPI_PTR(xge_acpi_match),
},
.probe = xge_probe,
- .remove_new = xge_remove,
+ .remove = xge_remove,
.shutdown = xge_shutdown,
};
module_platform_driver(xge_driver);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 4af9d89d5f88..3b2951030a38 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -2159,7 +2159,7 @@ static struct platform_driver xgene_enet_driver = {
.acpi_match_table = ACPI_PTR(xgene_enet_acpi_match),
},
.probe = xgene_enet_probe,
- .remove_new = xgene_enet_remove,
+ .remove = xgene_enet_remove,
.shutdown = xgene_enet_shutdown,
};
diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
index 766ab78256fe..8989506e6248 100644
--- a/drivers/net/ethernet/apple/macmace.c
+++ b/drivers/net/ethernet/apple/macmace.c
@@ -759,7 +759,7 @@ static void mac_mace_device_remove(struct platform_device *pdev)
static struct platform_driver mac_mace_driver = {
.probe = mace_probe,
- .remove_new = mac_mace_device_remove,
+ .remove = mac_mace_device_remove,
.driver = {
.name = mac_mace_string,
},
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index 440ff4616fec..6fef47ba0a59 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -15,6 +15,7 @@
#include "aq_macsec.h"
#include "aq_main.h"
+#include <linux/ethtool.h>
#include <linux/linkmode.h>
#include <linux/ptp_clock_kernel.h>
@@ -977,6 +978,76 @@ static int aq_ethtool_set_phy_tunable(struct net_device *ndev,
return err;
}
+static int aq_ethtool_get_module_info(struct net_device *ndev,
+ struct ethtool_modinfo *modinfo)
+{
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ u8 compliance_val, dom_type;
+ int err;
+
+ /* Module EEPROM is only supported for controllers with external PHY */
+ if (aq_nic->aq_nic_cfg.aq_hw_caps->media_type != AQ_HW_MEDIA_TYPE_FIBRE ||
+ !aq_nic->aq_hw_ops->hw_read_module_eeprom)
+ return -EOPNOTSUPP;
+
+ err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
+ SFF_8472_ID_ADDR, SFF_8472_COMP_ADDR, 1, &compliance_val);
+ if (err)
+ return err;
+
+ err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
+ SFF_8472_ID_ADDR, SFF_8472_DOM_TYPE_ADDR, 1, &dom_type);
+ if (err)
+ return err;
+
+ if (dom_type & SFF_8472_ADDRESS_CHANGE_REQ_MASK || compliance_val == 0x00) {
+ modinfo->type = ETH_MODULE_SFF_8079;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+ } else {
+ modinfo->type = ETH_MODULE_SFF_8472;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+ }
+ return 0;
+}
+
+static int aq_ethtool_get_module_eeprom(struct net_device *ndev,
+ struct ethtool_eeprom *ee, unsigned char *data)
+{
+ struct aq_nic_s *aq_nic = netdev_priv(ndev);
+ unsigned int first, last, len;
+ int err;
+
+ if (!aq_nic->aq_hw_ops->hw_read_module_eeprom)
+ return -EOPNOTSUPP;
+
+ first = ee->offset;
+ last = ee->offset + ee->len;
+
+ if (first < ETH_MODULE_SFF_8079_LEN) {
+ len = min(last, ETH_MODULE_SFF_8079_LEN);
+ len -= first;
+
+ err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
+ SFF_8472_ID_ADDR, first, len, data);
+ if (err)
+ return err;
+
+ first += len;
+ data += len;
+ }
+ if (first < ETH_MODULE_SFF_8472_LEN && last > ETH_MODULE_SFF_8079_LEN) {
+ len = min(last, ETH_MODULE_SFF_8472_LEN);
+ len -= first;
+ first -= ETH_MODULE_SFF_8079_LEN;
+
+ err = aq_nic->aq_hw_ops->hw_read_module_eeprom(aq_nic->aq_hw,
+ SFF_8472_DIAGNOSTICS_ADDR, first, len, data);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
const struct ethtool_ops aq_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES,
@@ -1014,4 +1085,6 @@ const struct ethtool_ops aq_ethtool_ops = {
.get_ts_info = aq_ethtool_get_ts_info,
.get_phy_tunable = aq_ethtool_get_phy_tunable,
.set_phy_tunable = aq_ethtool_set_phy_tunable,
+ .get_module_info = aq_ethtool_get_module_info,
+ .get_module_eeprom = aq_ethtool_get_module_eeprom,
};
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
index 6d5be5ebeb13..f26fe1a75539 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
@@ -14,4 +14,12 @@
extern const struct ethtool_ops aq_ethtool_ops;
#define AQ_PRIV_FLAGS_MASK (AQ_HW_LOOPBACK_MASK)
+#define SFF_8472_ID_ADDR 0x50
+#define SFF_8472_DIAGNOSTICS_ADDR 0x51
+
+#define SFF_8472_COMP_ADDR 0x5e
+#define SFF_8472_DOM_TYPE_ADDR 0x5c
+
+#define SFF_8472_ADDRESS_CHANGE_REQ_MASK 0x4
+
#endif /* AQ_ETHTOOL_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
index f010bda61c96..42c0efc1b455 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -340,6 +340,9 @@ struct aq_hw_ops {
int (*hw_set_loopback)(struct aq_hw_s *self, u32 mode, bool enable);
int (*hw_get_mac_temp)(struct aq_hw_s *self, u32 *temp);
+
+ int (*hw_read_module_eeprom)(struct aq_hw_s *self, u8 dev_addr,
+ u8 reg_start_addr, int len, u8 *data);
};
struct aq_fw_ops {
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index 43c71f6b314f..08630ee94251 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -162,8 +162,8 @@ int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i,
self->msix_entry_mask |= (1 << i);
if (pdev->msix_enabled && affinity_mask)
- irq_set_affinity_hint(pci_irq_vector(pdev, i),
- affinity_mask);
+ irq_update_affinity_hint(pci_irq_vector(pdev, i),
+ affinity_mask);
}
return err;
@@ -187,7 +187,7 @@ void aq_pci_func_free_irqs(struct aq_nic_s *self)
continue;
if (pdev->msix_enabled)
- irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL);
+ irq_update_affinity_hint(pci_irq_vector(pdev, i), NULL);
free_irq(pci_irq_vector(pdev, i), irq_data);
self->msix_entry_mask &= ~(1U << i);
}
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
index 56c46266bb0a..493432d036b9 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -1654,6 +1654,137 @@ static int hw_atl_b0_get_mac_temp(struct aq_hw_s *self, u32 *temp)
return 0;
}
+#define START_TRANSMIT 0x5001
+#define START_READ_TRANSMIT 0x5101
+#define STOP_TRANSMIT 0x3001
+#define REPEAT_TRANSMIT 0x1001
+#define REPEAT_NACK_TRANSMIT 0x1011
+
+static int hw_atl_b0_smb0_wait_result(struct aq_hw_s *self, bool expect_ack)
+{
+ int err;
+ u32 val;
+
+ err = readx_poll_timeout(hw_atl_smb0_byte_transfer_complete_get,
+ self, val, val == 1, 100U, 10000U);
+ if (err)
+ return err;
+ if (hw_atl_smb0_receive_acknowledged_get(self) != expect_ack)
+ return -EIO;
+ return 0;
+}
+
+/* Starts an I2C/SMBUS write to a given address. addr is in 7-bit format,
+ * the read/write bit is not part of it.
+ */
+static int hw_atl_b0_smb0_start_write(struct aq_hw_s *self, u32 addr)
+{
+ hw_atl_smb0_tx_data_set(self, (addr << 1) | 0);
+ hw_atl_smb0_provisioning2_set(self, START_TRANSMIT);
+ return hw_atl_b0_smb0_wait_result(self, 0);
+}
+
+/* Writes a single byte as part of an ongoing write started by start_write. */
+static int hw_atl_b0_smb0_write_byte(struct aq_hw_s *self, u32 data)
+{
+ hw_atl_smb0_tx_data_set(self, data);
+ hw_atl_smb0_provisioning2_set(self, REPEAT_TRANSMIT);
+ return hw_atl_b0_smb0_wait_result(self, 0);
+}
+
+/* Starts an I2C/SMBUS read to a given address. addr is in 7-bit format,
+ * the read/write bit is not part of it.
+ */
+static int hw_atl_b0_smb0_start_read(struct aq_hw_s *self, u32 addr)
+{
+ int err;
+
+ hw_atl_smb0_tx_data_set(self, (addr << 1) | 1);
+ hw_atl_smb0_provisioning2_set(self, START_READ_TRANSMIT);
+ err = hw_atl_b0_smb0_wait_result(self, 0);
+ if (err)
+ return err;
+ if (hw_atl_smb0_repeated_start_detect_get(self) == 0)
+ return -EIO;
+ return 0;
+}
+
+/* Reads a single byte as part of an ongoing read started by start_read. */
+static int hw_atl_b0_smb0_read_byte(struct aq_hw_s *self)
+{
+ int err;
+
+ hw_atl_smb0_provisioning2_set(self, REPEAT_TRANSMIT);
+ err = hw_atl_b0_smb0_wait_result(self, 0);
+ if (err)
+ return err;
+ return hw_atl_smb0_rx_data_get(self);
+}
+
+/* Reads the last byte of an ongoing read. */
+static int hw_atl_b0_smb0_read_byte_nack(struct aq_hw_s *self)
+{
+ int err;
+
+ hw_atl_smb0_provisioning2_set(self, REPEAT_NACK_TRANSMIT);
+ err = hw_atl_b0_smb0_wait_result(self, 1);
+ if (err)
+ return err;
+ return hw_atl_smb0_rx_data_get(self);
+}
+
+/* Sends a stop condition and ends a transfer. */
+static void hw_atl_b0_smb0_stop(struct aq_hw_s *self)
+{
+ hw_atl_smb0_provisioning2_set(self, STOP_TRANSMIT);
+}
+
+static int hw_atl_b0_read_module_eeprom(struct aq_hw_s *self, u8 dev_addr,
+ u8 reg_start_addr, int len, u8 *data)
+{
+ int i, b;
+ int err;
+ u32 val;
+
+ /* Wait for SMBUS0 to be idle */
+ err = readx_poll_timeout(hw_atl_smb0_bus_busy_get, self,
+ val, val == 0, 100U, 10000U);
+ if (err)
+ return err;
+
+ err = hw_atl_b0_smb0_start_write(self, dev_addr);
+ if (err)
+ goto out;
+
+ err = hw_atl_b0_smb0_write_byte(self, reg_start_addr);
+ if (err)
+ goto out;
+
+ err = hw_atl_b0_smb0_start_read(self, dev_addr);
+ if (err)
+ goto out;
+
+ for (i = 0; i < len - 1; i++) {
+ b = hw_atl_b0_smb0_read_byte(self);
+ if (b < 0) {
+ err = b;
+ goto out;
+ }
+ data[i] = (u8)b;
+ }
+
+ b = hw_atl_b0_smb0_read_byte_nack(self);
+ if (b < 0) {
+ err = b;
+ goto out;
+ }
+ data[i] = (u8)b;
+
+out:
+ hw_atl_b0_smb0_stop(self);
+ return err;
+}
+
const struct aq_hw_ops hw_atl_ops_b0 = {
.hw_soft_reset = hw_atl_utils_soft_reset,
.hw_prepare = hw_atl_utils_initfw,
@@ -1712,4 +1843,5 @@ const struct aq_hw_ops hw_atl_ops_b0 = {
.hw_set_fc = hw_atl_b0_set_fc,
.hw_get_mac_temp = hw_atl_b0_get_mac_temp,
+ .hw_read_module_eeprom = hw_atl_b0_read_module_eeprom,
};
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
index 7b67bdd8a258..d07af1271d59 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
@@ -57,6 +57,49 @@ u32 hw_atl_ts_data_get(struct aq_hw_s *aq_hw)
HW_ATL_TS_DATA_OUT_SHIFT);
}
+u32 hw_atl_smb0_bus_busy_get(struct aq_hw_s *aq_hw)
+{
+ return aq_hw_read_reg_bit(aq_hw, HW_ATL_SMB0_BUS_BUSY_ADR,
+ HW_ATL_SMB0_BUS_BUSY_MSK,
+ HW_ATL_SMB0_BUS_BUSY_SHIFT);
+}
+
+u32 hw_atl_smb0_byte_transfer_complete_get(struct aq_hw_s *aq_hw)
+{
+ return aq_hw_read_reg_bit(aq_hw, HW_ATL_SMB0_BYTE_TRANSFER_COMPLETE_ADR,
+ HW_ATL_SMB0_BYTE_TRANSFER_COMPLETE_MSK,
+ HW_ATL_SMB0_BYTE_TRANSFER_COMPLETE_SHIFT);
+}
+
+u32 hw_atl_smb0_receive_acknowledged_get(struct aq_hw_s *aq_hw)
+{
+ return aq_hw_read_reg_bit(aq_hw, HW_ATL_SMB0_RX_ACKNOWLEDGED_ADR,
+ HW_ATL_SMB0_RX_ACKNOWLEDGED_MSK,
+ HW_ATL_SMB0_RX_ACKNOWLEDGED_SHIFT);
+}
+
+u32 hw_atl_smb0_repeated_start_detect_get(struct aq_hw_s *aq_hw)
+{
+ return aq_hw_read_reg_bit(aq_hw, HW_ATL_SMB0_REPEATED_START_DETECT_ADR,
+ HW_ATL_SMB0_REPEATED_START_DETECT_MSK,
+ HW_ATL_SMB0_REPEATED_START_DETECT_SHIFT);
+}
+
+u32 hw_atl_smb0_rx_data_get(struct aq_hw_s *aq_hw)
+{
+ return aq_hw_read_reg(aq_hw, HW_ATL_SMB0_RECEIVED_DATA_ADR);
+}
+
+void hw_atl_smb0_tx_data_set(struct aq_hw_s *aq_hw, u32 data)
+{
+ return aq_hw_write_reg(aq_hw, HW_ATL_SMB0_TRANSMITTED_DATA_ADR, data);
+}
+
+void hw_atl_smb0_provisioning2_set(struct aq_hw_s *aq_hw, u32 data)
+{
+ return aq_hw_write_reg(aq_hw, HW_ATL_SMB0_PROVISIONING2_ADR, data);
+}
+
/* global */
void hw_atl_reg_glb_cpu_sem_set(struct aq_hw_s *aq_hw, u32 glb_cpu_sem,
u32 semaphore)
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
index 58f5ee0a6214..5fd506acacb5 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
@@ -34,6 +34,27 @@ u32 hw_atl_ts_ready_latch_high_get(struct aq_hw_s *aq_hw);
/* get temperature sense data */
u32 hw_atl_ts_data_get(struct aq_hw_s *aq_hw);
+/* SMBUS0 bus busy */
+u32 hw_atl_smb0_bus_busy_get(struct aq_hw_s *aq_hw);
+
+/* SMBUS0 byte transfer complete */
+u32 hw_atl_smb0_byte_transfer_complete_get(struct aq_hw_s *aq_hw);
+
+/* SMBUS0 receive acknowledged */
+u32 hw_atl_smb0_receive_acknowledged_get(struct aq_hw_s *aq_hw);
+
+/* SMBUS0 set transmitted data (only leftmost byte of data valid) */
+void hw_atl_smb0_tx_data_set(struct aq_hw_s *aq_hw, u32 data);
+
+/* SMBUS0 provisioning2 command register */
+void hw_atl_smb0_provisioning2_set(struct aq_hw_s *aq_hw, u32 data);
+
+/* SMBUS0 repeated start detect */
+u32 hw_atl_smb0_repeated_start_detect_get(struct aq_hw_s *aq_hw);
+
+/* SMBUS0 received data register */
+u32 hw_atl_smb0_rx_data_get(struct aq_hw_s *aq_hw);
+
/* global */
/* set global microprocessor semaphore */
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
index 4a6467031b9e..fce30d90b6cb 100644
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
@@ -42,6 +42,38 @@
#define HW_ATL_TS_DATA_OUT_SHIFT 0
#define HW_ATL_TS_DATA_OUT_WIDTH 12
+/* SMBUS0 Received Data register */
+#define HW_ATL_SMB0_RECEIVED_DATA_ADR 0x00000748
+/* SMBUS0 Transmitted Data register */
+#define HW_ATL_SMB0_TRANSMITTED_DATA_ADR 0x00000608
+
+/* SMBUS0 Global Provisioning 2 register */
+#define HW_ATL_SMB0_PROVISIONING2_ADR 0x00000604
+
+/* SMBUS0 Bus Busy Bitfield Definitions */
+#define HW_ATL_SMB0_BUS_BUSY_ADR 0x00000744
+#define HW_ATL_SMB0_BUS_BUSY_MSK 0x00000080
+#define HW_ATL_SMB0_BUS_BUSY_SHIFT 7
+#define HW_ATL_SMB0_BUS_BUSY_WIDTH 1
+
+/* SMBUS0 Byte Transfer Complete Bitfield Definitions */
+#define HW_ATL_SMB0_BYTE_TRANSFER_COMPLETE_ADR 0x00000744
+#define HW_ATL_SMB0_BYTE_TRANSFER_COMPLETE_MSK 0x00000002
+#define HW_ATL_SMB0_BYTE_TRANSFER_COMPLETE_SHIFT 1
+#define HW_ATL_SMB0_BYTE_TRANSFER_COMPLETE_WIDTH 1
+
+/* SMBUS0 Receive Acknowledge Bitfield Definitions */
+#define HW_ATL_SMB0_RX_ACKNOWLEDGED_ADR 0x00000744
+#define HW_ATL_SMB0_RX_ACKNOWLEDGED_MSK 0x00000100
+#define HW_ATL_SMB0_RX_ACKNOWLEDGED_SHIFT 8
+#define HW_ATL_SMB0_RX_ACKNOWLEDGED_WIDTH 1
+
+/* SMBUS0 Repeated Start Detect Bitfield Definitions */
+#define HW_ATL_SMB0_REPEATED_START_DETECT_ADR 0x00000744
+#define HW_ATL_SMB0_REPEATED_START_DETECT_MSK 0x00000004
+#define HW_ATL_SMB0_REPEATED_START_DETECT_SHIFT 2
+#define HW_ATL_SMB0_REPEATED_START_DETECT_WIDTH 1
+
/* global microprocessor semaphore definitions
* base address: 0x000003a0
* parameter: semaphore {s} | stride size 0x4 | range [0, 15]
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index 31ee477dd131..8283aeee35fb 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -111,6 +111,7 @@ static void arc_emac_tx_clean(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats;
+ struct device *dev = ndev->dev.parent;
unsigned int i;
for (i = 0; i < TX_BD_NUM; i++) {
@@ -140,7 +141,7 @@ static void arc_emac_tx_clean(struct net_device *ndev)
stats->tx_bytes += skb->len;
}
- dma_unmap_single(&ndev->dev, dma_unmap_addr(tx_buff, addr),
+ dma_unmap_single(dev, dma_unmap_addr(tx_buff, addr),
dma_unmap_len(tx_buff, len), DMA_TO_DEVICE);
/* return the sk_buff to system */
@@ -174,6 +175,7 @@ static void arc_emac_tx_clean(struct net_device *ndev)
static int arc_emac_rx(struct net_device *ndev, int budget)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
+ struct device *dev = ndev->dev.parent;
unsigned int work_done;
for (work_done = 0; work_done < budget; work_done++) {
@@ -223,9 +225,9 @@ static int arc_emac_rx(struct net_device *ndev, int budget)
continue;
}
- addr = dma_map_single(&ndev->dev, (void *)skb->data,
+ addr = dma_map_single(dev, (void *)skb->data,
EMAC_BUFFER_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(&ndev->dev, addr)) {
+ if (dma_mapping_error(dev, addr)) {
if (net_ratelimit())
netdev_err(ndev, "cannot map dma buffer\n");
dev_kfree_skb(skb);
@@ -237,7 +239,7 @@ static int arc_emac_rx(struct net_device *ndev, int budget)
}
/* unmap previosly mapped skb */
- dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr),
+ dma_unmap_single(dev, dma_unmap_addr(rx_buff, addr),
dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE);
pktlen = info & LEN_MASK;
@@ -423,6 +425,7 @@ static int arc_emac_open(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
struct phy_device *phy_dev = ndev->phydev;
+ struct device *dev = ndev->dev.parent;
int i;
phy_dev->autoneg = AUTONEG_ENABLE;
@@ -445,9 +448,9 @@ static int arc_emac_open(struct net_device *ndev)
if (unlikely(!rx_buff->skb))
return -ENOMEM;
- addr = dma_map_single(&ndev->dev, (void *)rx_buff->skb->data,
+ addr = dma_map_single(dev, (void *)rx_buff->skb->data,
EMAC_BUFFER_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(&ndev->dev, addr)) {
+ if (dma_mapping_error(dev, addr)) {
netdev_err(ndev, "cannot dma map\n");
dev_kfree_skb(rx_buff->skb);
return -ENOMEM;
@@ -548,6 +551,7 @@ static void arc_emac_set_rx_mode(struct net_device *ndev)
static void arc_free_tx_queue(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
+ struct device *dev = ndev->dev.parent;
unsigned int i;
for (i = 0; i < TX_BD_NUM; i++) {
@@ -555,7 +559,7 @@ static void arc_free_tx_queue(struct net_device *ndev)
struct buffer_state *tx_buff = &priv->tx_buff[i];
if (tx_buff->skb) {
- dma_unmap_single(&ndev->dev,
+ dma_unmap_single(dev,
dma_unmap_addr(tx_buff, addr),
dma_unmap_len(tx_buff, len),
DMA_TO_DEVICE);
@@ -579,6 +583,7 @@ static void arc_free_tx_queue(struct net_device *ndev)
static void arc_free_rx_queue(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
+ struct device *dev = ndev->dev.parent;
unsigned int i;
for (i = 0; i < RX_BD_NUM; i++) {
@@ -586,7 +591,7 @@ static void arc_free_rx_queue(struct net_device *ndev)
struct buffer_state *rx_buff = &priv->rx_buff[i];
if (rx_buff->skb) {
- dma_unmap_single(&ndev->dev,
+ dma_unmap_single(dev,
dma_unmap_addr(rx_buff, addr),
dma_unmap_len(rx_buff, len),
DMA_FROM_DEVICE);
@@ -679,6 +684,7 @@ static netdev_tx_t arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
unsigned int len, *txbd_curr = &priv->txbd_curr;
struct net_device_stats *stats = &ndev->stats;
__le32 *info = &priv->txbd[*txbd_curr].info;
+ struct device *dev = ndev->dev.parent;
dma_addr_t addr;
if (skb_padto(skb, ETH_ZLEN))
@@ -692,10 +698,9 @@ static netdev_tx_t arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
return NETDEV_TX_BUSY;
}
- addr = dma_map_single(&ndev->dev, (void *)skb->data, len,
- DMA_TO_DEVICE);
+ addr = dma_map_single(dev, (void *)skb->data, len, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(&ndev->dev, addr))) {
+ if (unlikely(dma_mapping_error(dev, addr))) {
stats->tx_dropped++;
stats->tx_errors++;
dev_kfree_skb_any(skb);
diff --git a/drivers/net/ethernet/arc/emac_mdio.c b/drivers/net/ethernet/arc/emac_mdio.c
index 87f40c2ba904..078b1a72c161 100644
--- a/drivers/net/ethernet/arc/emac_mdio.c
+++ b/drivers/net/ethernet/arc/emac_mdio.c
@@ -133,6 +133,7 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
struct arc_emac_mdio_bus_data *data = &priv->bus_data;
struct device_node *np = priv->dev->of_node;
const char *name = "Synopsys MII Bus";
+ struct device_node *mdio_node;
struct mii_bus *bus;
int error;
@@ -164,7 +165,13 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name);
- error = of_mdiobus_register(bus, priv->dev->of_node);
+ /* Backwards compatibility for EMAC nodes without MDIO subnode. */
+ mdio_node = of_get_child_by_name(np, "mdio");
+ if (!mdio_node)
+ mdio_node = of_node_get(np);
+
+ error = of_mdiobus_register(bus, mdio_node);
+ of_node_put(mdio_node);
if (error) {
mdiobus_free(bus);
return dev_err_probe(priv->dev, error,
diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
index 493d6356c8ca..780e70ea1c22 100644
--- a/drivers/net/ethernet/arc/emac_rockchip.c
+++ b/drivers/net/ethernet/arc/emac_rockchip.c
@@ -264,7 +264,7 @@ static void emac_rockchip_remove(struct platform_device *pdev)
static struct platform_driver emac_rockchip_driver = {
.probe = emac_rockchip_probe,
- .remove_new = emac_rockchip_remove,
+ .remove = emac_rockchip_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = emac_rockchip_dt_ids,
diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c
index 9586b6894f7e..3d4c3d8698e2 100644
--- a/drivers/net/ethernet/atheros/ag71xx.c
+++ b/drivers/net/ethernet/atheros/ag71xx.c
@@ -1598,8 +1598,8 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit)
int ring_mask, ring_size, done = 0;
unsigned int pktlen_mask, offset;
struct ag71xx_ring *ring;
- struct list_head rx_list;
struct sk_buff *skb;
+ LIST_HEAD(rx_list);
ring = &ag->rx_ring;
pktlen_mask = ag->dcfg->desc_pktlen_mask;
@@ -1610,8 +1610,6 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit)
netif_dbg(ag, rx_status, ndev, "rx packets, limit=%d, curr=%u, dirty=%u\n",
limit, ring->curr, ring->dirty);
- INIT_LIST_HEAD(&rx_list);
-
while (done < limit) {
unsigned int i = ring->curr & ring_mask;
struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i);
@@ -1648,6 +1646,7 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit)
skb->dev = ndev;
skb->ip_summed = CHECKSUM_NONE;
+ skb->protocol = eth_type_trans(skb, ndev);
list_add_tail(&skb->list, &rx_list);
next:
@@ -1659,8 +1658,6 @@ next:
ag71xx_ring_rx_refill(ag);
- list_for_each_entry(skb, &rx_list, list)
- skb->protocol = eth_type_trans(skb, ndev);
netif_receive_skb_list(&rx_list);
netif_dbg(ag, rx_status, ndev, "rx finish, curr=%u, dirty=%u, done=%d\n",
@@ -1822,10 +1819,9 @@ static int ag71xx_probe(struct platform_device *pdev)
}
clk_eth = devm_clk_get_enabled(&pdev->dev, "eth");
- if (IS_ERR(clk_eth)) {
- netif_err(ag, probe, ndev, "Failed to get eth clk.\n");
- return PTR_ERR(clk_eth);
- }
+ if (IS_ERR(clk_eth))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk_eth),
+ "Failed to get eth clk.");
SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -1836,14 +1832,13 @@ static int ag71xx_probe(struct platform_device *pdev)
memcpy(ag->fifodata, dcfg->fifodata, sizeof(ag->fifodata));
ag->mac_reset = devm_reset_control_get(&pdev->dev, "mac");
- if (IS_ERR(ag->mac_reset)) {
- netif_err(ag, probe, ndev, "missing mac reset\n");
- return PTR_ERR(ag->mac_reset);
- }
+ if (IS_ERR(ag->mac_reset))
+ return dev_err_probe(&pdev->dev, PTR_ERR(ag->mac_reset),
+ "missing mac reset");
- ag->mac_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!ag->mac_base)
- return -ENOMEM;
+ ag->mac_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ag->mac_base))
+ return PTR_ERR(ag->mac_base);
/* ensure that HW is in manual polling mode before interrupts are
* activated. Otherwise ag71xx_interrupt might call napi_schedule
@@ -1917,18 +1912,14 @@ static int ag71xx_probe(struct platform_device *pdev)
if (err)
return err;
- platform_set_drvdata(pdev, ndev);
-
err = ag71xx_phylink_setup(ag);
- if (err) {
- netif_err(ag, probe, ndev, "failed to setup phylink (%d)\n", err);
- return err;
- }
+ if (err)
+ return dev_err_probe(&pdev->dev, err,
+ "failed to setup phylink");
err = devm_register_netdev(&pdev->dev, ndev);
if (err) {
netif_err(ag, probe, ndev, "unable to register net device\n");
- platform_set_drvdata(pdev, NULL);
return err;
}
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 75ca3ddda1f5..eeec8bf17cf4 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -72,7 +72,6 @@ config BCMGENET
tristate "Broadcom GENET internal MAC support"
depends on HAS_IOMEM
depends on PTP_1588_CLOCK_OPTIONAL || !ARCH_BCM2835
- select MII
select PHYLIB
select FIXED_PHY
select BCM7XXX_PHY
@@ -195,7 +194,6 @@ config SYSTEMPORT
tristate "Broadcom SYSTEMPORT internal MAC support"
depends on HAS_IOMEM
depends on NET_DSA || !NET_DSA
- select MII
select PHYLIB
select FIXED_PHY
select DIMLIB
@@ -260,7 +258,6 @@ config BCMASP
depends on ARCH_BRCMSTB || COMPILE_TEST
default ARCH_BRCMSTB
depends on OF
- select MII
select PHYLIB
select MDIO_BCM_UNIMAC
help
diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c
index 297c2682a9cf..a68fab1b05f0 100644
--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c
+++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c
@@ -1500,7 +1500,7 @@ static SIMPLE_DEV_PM_OPS(bcmasp_pm_ops,
static struct platform_driver bcmasp_driver = {
.probe = bcmasp_probe,
- .remove_new = bcmasp_remove,
+ .remove = bcmasp_remove,
.shutdown = bcmasp_shutdown,
.driver = {
.name = "brcm,asp-v2",
diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c
index ca163c8e3729..9da5ae29a105 100644
--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c
+++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c
@@ -101,14 +101,14 @@ static int bcmasp_get_sset_count(struct net_device *dev, int string_set)
static void bcmasp_get_strings(struct net_device *dev, u32 stringset,
u8 *data)
{
+ const char *str;
unsigned int i;
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < BCMASP_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- bcmasp_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ str = bcmasp_gstrings_stats[i].stat_string;
+ ethtool_puts(&data, str);
}
break;
default:
@@ -496,4 +496,5 @@ const struct ethtool_ops bcmasp_ethtool_ops = {
.get_strings = bcmasp_get_strings,
.get_ethtool_stats = bcmasp_get_ethtool_stats,
.get_sset_count = bcmasp_get_sset_count,
+ .get_ts_info = ethtool_op_get_ts_info,
};
diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
index 9ea16ef4139d..cfd50efbdbc0 100644
--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
+++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
@@ -365,6 +365,9 @@ static netdev_tx_t bcmasp_xmit(struct sk_buff *skb, struct net_device *dev)
intf->tx_spb_index = spb_index;
intf->tx_spb_dma_valid = valid;
+
+ skb_tx_timestamp(skb);
+
bcmasp_intf_tx_write(intf, intf->tx_spb_dma_valid);
if (tx_spb_ring_full(intf, MAX_SKB_FRAGS + 1))
diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c
index 72df1bb10172..203e8d0dd04b 100644
--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
@@ -789,7 +789,7 @@ static struct platform_driver bcm4908_enet_driver = {
.of_match_table = bcm4908_enet_of_match,
},
.probe = bcm4908_enet_probe,
- .remove_new = bcm4908_enet_remove,
+ .remove = bcm4908_enet_remove,
};
module_platform_driver(bcm4908_enet_driver);
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 3c0e3b9828be..65e3a0656a4c 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1339,14 +1339,14 @@ static int bcm_enet_get_sset_count(struct net_device *netdev,
static void bcm_enet_get_strings(struct net_device *netdev,
u32 stringset, u8 *data)
{
+ const char *str;
int i;
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < BCM_ENET_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- bcm_enet_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ str = bcm_enet_gstrings_stats[i].stat_string;
+ ethtool_puts(&data, str);
}
break;
}
@@ -1936,7 +1936,7 @@ static void bcm_enet_remove(struct platform_device *pdev)
static struct platform_driver bcm63xx_enet_driver = {
.probe = bcm_enet_probe,
- .remove_new = bcm_enet_remove,
+ .remove = bcm_enet_remove,
.driver = {
.name = "bcm63xx_enet",
},
@@ -2503,14 +2503,14 @@ static const struct bcm_enet_stats bcm_enetsw_gstrings_stats[] = {
static void bcm_enetsw_get_strings(struct net_device *netdev,
u32 stringset, u8 *data)
{
+ const char *str;
int i;
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- bcm_enetsw_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ str = bcm_enetsw_gstrings_stats[i].stat_string;
+ ethtool_puts(&data, str);
}
break;
}
@@ -2755,7 +2755,7 @@ static void bcm_enetsw_remove(struct platform_device *pdev)
static struct platform_driver bcm63xx_enetsw_driver = {
.probe = bcm_enetsw_probe,
- .remove_new = bcm_enetsw_remove,
+ .remove = bcm_enetsw_remove,
.driver = {
.name = "bcm63xx_enetsw",
},
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 0a68b526e4a8..42672c63f108 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -27,30 +27,6 @@
#include "bcmsysport.h"
-/* I/O accessors register helpers */
-#define BCM_SYSPORT_IO_MACRO(name, offset) \
-static inline u32 name##_readl(struct bcm_sysport_priv *priv, u32 off) \
-{ \
- u32 reg = readl_relaxed(priv->base + offset + off); \
- return reg; \
-} \
-static inline void name##_writel(struct bcm_sysport_priv *priv, \
- u32 val, u32 off) \
-{ \
- writel_relaxed(val, priv->base + offset + off); \
-} \
-
-BCM_SYSPORT_IO_MACRO(intrl2_0, SYS_PORT_INTRL2_0_OFFSET);
-BCM_SYSPORT_IO_MACRO(intrl2_1, SYS_PORT_INTRL2_1_OFFSET);
-BCM_SYSPORT_IO_MACRO(umac, SYS_PORT_UMAC_OFFSET);
-BCM_SYSPORT_IO_MACRO(gib, SYS_PORT_GIB_OFFSET);
-BCM_SYSPORT_IO_MACRO(tdma, SYS_PORT_TDMA_OFFSET);
-BCM_SYSPORT_IO_MACRO(rxchk, SYS_PORT_RXCHK_OFFSET);
-BCM_SYSPORT_IO_MACRO(txchk, SYS_PORT_TXCHK_OFFSET);
-BCM_SYSPORT_IO_MACRO(rbuf, SYS_PORT_RBUF_OFFSET);
-BCM_SYSPORT_IO_MACRO(tbuf, SYS_PORT_TBUF_OFFSET);
-BCM_SYSPORT_IO_MACRO(topctrl, SYS_PORT_TOPCTRL_OFFSET);
-
/* On SYSTEMPORT Lite, any register after RDMA_STATUS has the exact
* same layout, except it has been moved by 4 bytes up, *sigh*
*/
@@ -370,32 +346,22 @@ static void bcm_sysport_get_strings(struct net_device *dev,
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
const struct bcm_sysport_stats *s;
- char buf[128];
- int i, j;
+ int i;
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0, j = 0; i < BCM_SYSPORT_STATS_LEN; i++) {
+ for (i = 0; i < BCM_SYSPORT_STATS_LEN; i++) {
s = &bcm_sysport_gstrings_stats[i];
if (priv->is_lite &&
!bcm_sysport_lite_stat_valid(s->type))
continue;
- memcpy(data + j * ETH_GSTRING_LEN, s->stat_string,
- ETH_GSTRING_LEN);
- j++;
+ ethtool_puts(&data, s->stat_string);
}
for (i = 0; i < dev->num_tx_queues; i++) {
- snprintf(buf, sizeof(buf), "txq%d_packets", i);
- memcpy(data + j * ETH_GSTRING_LEN, buf,
- ETH_GSTRING_LEN);
- j++;
-
- snprintf(buf, sizeof(buf), "txq%d_bytes", i);
- memcpy(data + j * ETH_GSTRING_LEN, buf,
- ETH_GSTRING_LEN);
- j++;
+ ethtool_sprintf(&data, "txq%d_packets", i);
+ ethtool_sprintf(&data, "txq%d_bytes", i);
}
break;
default:
@@ -1053,7 +1019,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
if (priv->dim.use_dim) {
dim_update_sample(priv->dim.event_ctr, priv->dim.packets,
priv->dim.bytes, &dim_sample);
- net_dim(&priv->dim.dim, dim_sample);
+ net_dim(&priv->dim.dim, &dim_sample);
}
return work_done;
@@ -2900,7 +2866,7 @@ static SIMPLE_DEV_PM_OPS(bcm_sysport_pm_ops,
static struct platform_driver bcm_sysport_driver = {
.probe = bcm_sysport_probe,
- .remove_new = bcm_sysport_remove,
+ .remove = bcm_sysport_remove,
.driver = {
.name = "brcm-systemport",
.of_match_table = bcm_sysport_of_match,
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index 335cf6631db5..a34296f989f1 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -773,4 +773,27 @@ struct bcm_sysport_priv {
struct bcm_sysport_tx_ring *ring_map[DSA_MAX_PORTS * 8];
};
+
+/* I/O accessors register helpers */
+#define BCM_SYSPORT_IO_MACRO(name, offset) \
+static inline u32 name##_readl(struct bcm_sysport_priv *priv, u32 off) \
+{ \
+ u32 reg = readl_relaxed(priv->base + (offset) + off); \
+ return reg; \
+} \
+static inline void name##_writel(struct bcm_sysport_priv *priv, \
+ u32 val, u32 off) \
+{ \
+ writel_relaxed(val, priv->base + (offset) + off); \
+} \
+
+BCM_SYSPORT_IO_MACRO(intrl2_0, SYS_PORT_INTRL2_0_OFFSET);
+BCM_SYSPORT_IO_MACRO(intrl2_1, SYS_PORT_INTRL2_1_OFFSET);
+BCM_SYSPORT_IO_MACRO(umac, SYS_PORT_UMAC_OFFSET);
+BCM_SYSPORT_IO_MACRO(gib, SYS_PORT_GIB_OFFSET);
+BCM_SYSPORT_IO_MACRO(tdma, SYS_PORT_TDMA_OFFSET);
+BCM_SYSPORT_IO_MACRO(rxchk, SYS_PORT_RXCHK_OFFSET);
+BCM_SYSPORT_IO_MACRO(rbuf, SYS_PORT_RBUF_OFFSET);
+BCM_SYSPORT_IO_MACRO(topctrl, SYS_PORT_TOPCTRL_OFFSET);
+
#endif /* __BCM_SYSPORT_H */
diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c
index 77425c7a32db..ecce23cecbea 100644
--- a/drivers/net/ethernet/broadcom/bgmac-platform.c
+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
@@ -294,7 +294,7 @@ static struct platform_driver bgmac_enet_driver = {
.pm = BGMAC_PM_OPS
},
.probe = bgmac_probe,
- .remove_new = bgmac_remove,
+ .remove = bgmac_remove,
};
module_platform_driver(bgmac_enet_driver);
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 6ffdc4229407..a461ec612e95 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1367,8 +1367,7 @@ static void bgmac_get_strings(struct net_device *dev, u32 stringset,
return;
for (i = 0; i < BGMAC_STATS_LEN; i++)
- strscpy(data + i * ETH_GSTRING_LEN,
- bgmac_get_strings_stats[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, bgmac_get_strings_stats[i].name);
}
static void bgmac_get_ethtool_stats(struct net_device *dev,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index adf7b6b94941..44199855ebfb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -39,34 +39,34 @@ static const struct {
int size;
char string[ETH_GSTRING_LEN];
} bnx2x_q_stats_arr[] = {
-/* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%s]: rx_bytes" },
+/* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%d]: rx_bytes" },
{ Q_STATS_OFFSET32(total_unicast_packets_received_hi),
- 8, "[%s]: rx_ucast_packets" },
+ 8, "[%d]: rx_ucast_packets" },
{ Q_STATS_OFFSET32(total_multicast_packets_received_hi),
- 8, "[%s]: rx_mcast_packets" },
+ 8, "[%d]: rx_mcast_packets" },
{ Q_STATS_OFFSET32(total_broadcast_packets_received_hi),
- 8, "[%s]: rx_bcast_packets" },
- { Q_STATS_OFFSET32(no_buff_discard_hi), 8, "[%s]: rx_discards" },
+ 8, "[%d]: rx_bcast_packets" },
+ { Q_STATS_OFFSET32(no_buff_discard_hi), 8, "[%d]: rx_discards" },
{ Q_STATS_OFFSET32(rx_err_discard_pkt),
- 4, "[%s]: rx_phy_ip_err_discards"},
+ 4, "[%d]: rx_phy_ip_err_discards"},
{ Q_STATS_OFFSET32(rx_skb_alloc_failed),
- 4, "[%s]: rx_skb_alloc_discard" },
- { Q_STATS_OFFSET32(hw_csum_err), 4, "[%s]: rx_csum_offload_errors" },
- { Q_STATS_OFFSET32(driver_xoff), 4, "[%s]: tx_exhaustion_events" },
- { Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%s]: tx_bytes" },
+ 4, "[%d]: rx_skb_alloc_discard" },
+ { Q_STATS_OFFSET32(hw_csum_err), 4, "[%d]: rx_csum_offload_errors" },
+ { Q_STATS_OFFSET32(driver_xoff), 4, "[%d]: tx_exhaustion_events" },
+ { Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%d]: tx_bytes" },
/* 10 */{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
- 8, "[%s]: tx_ucast_packets" },
+ 8, "[%d]: tx_ucast_packets" },
{ Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi),
- 8, "[%s]: tx_mcast_packets" },
+ 8, "[%d]: tx_mcast_packets" },
{ Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
- 8, "[%s]: tx_bcast_packets" },
+ 8, "[%d]: tx_bcast_packets" },
{ Q_STATS_OFFSET32(total_tpa_aggregations_hi),
- 8, "[%s]: tpa_aggregations" },
+ 8, "[%d]: tpa_aggregations" },
{ Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi),
- 8, "[%s]: tpa_aggregated_frames"},
- { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"},
+ 8, "[%d]: tpa_aggregated_frames"},
+ { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%d]: tpa_bytes"},
{ Q_STATS_OFFSET32(driver_filtered_tx_pkt),
- 4, "[%s]: driver_filtered_tx_pkt" }
+ 4, "[%d]: driver_filtered_tx_pkt" }
};
#define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
@@ -3184,49 +3184,43 @@ static u32 bnx2x_get_private_flags(struct net_device *dev)
static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
{
struct bnx2x *bp = netdev_priv(dev);
- int i, j, k, start;
- char queue_name[MAX_QUEUE_NAME_LEN+1];
+ const char *str;
+ int i, j, start;
switch (stringset) {
case ETH_SS_STATS:
- k = 0;
if (is_multi(bp)) {
for_each_eth_queue(bp, i) {
- memset(queue_name, 0, sizeof(queue_name));
- snprintf(queue_name, sizeof(queue_name),
- "%d", i);
- for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
- snprintf(buf + (k + j)*ETH_GSTRING_LEN,
- ETH_GSTRING_LEN,
- bnx2x_q_stats_arr[j].string,
- queue_name);
- k += BNX2X_NUM_Q_STATS;
+ for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
+ str = bnx2x_q_stats_arr[j].string;
+ ethtool_sprintf(&buf, str, i);
+ }
}
}
- for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
+ for (i = 0; i < BNX2X_NUM_STATS; i++) {
if (HIDE_PORT_STAT(bp) && IS_PORT_STAT(i))
continue;
- strcpy(buf + (k + j)*ETH_GSTRING_LEN,
- bnx2x_stats_arr[i].string);
- j++;
+ ethtool_puts(&buf, bnx2x_stats_arr[i].string);
}
break;
case ETH_SS_TEST:
+ if (IS_VF(bp))
+ break;
/* First 4 tests cannot be done in MF mode */
if (!IS_MF(bp))
start = 0;
else
start = 4;
- memcpy(buf, bnx2x_tests_str_arr + start,
- ETH_GSTRING_LEN * BNX2X_NUM_TESTS(bp));
+ for (i = start; i < BNX2X_NUM_TESTS_SF; i++)
+ ethtool_puts(&buf, bnx2x_tests_str_arr[i]);
break;
case ETH_SS_PRIV_FLAGS:
- memcpy(buf, bnx2x_private_arr,
- ETH_GSTRING_LEN * BNX2X_PRI_FLAG_LEN);
+ for (i = 0; i < BNX2X_PRI_FLAG_LEN; i++)
+ ethtool_puts(&buf, bnx2x_private_arr[i]);
break;
}
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 99d025b69079..4ec4934a4edd 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -245,6 +245,21 @@ static const u16 bnxt_async_events_arr[] = {
ASYNC_EVENT_CMPL_EVENT_ID_PPS_TIMESTAMP,
ASYNC_EVENT_CMPL_EVENT_ID_ERROR_REPORT,
ASYNC_EVENT_CMPL_EVENT_ID_PHC_UPDATE,
+ ASYNC_EVENT_CMPL_EVENT_ID_DBG_BUF_PRODUCER,
+};
+
+const u16 bnxt_bstore_to_trace[] = {
+ [BNXT_CTX_SRT] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT_TRACE,
+ [BNXT_CTX_SRT2] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT2_TRACE,
+ [BNXT_CTX_CRT] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT_TRACE,
+ [BNXT_CTX_CRT2] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT2_TRACE,
+ [BNXT_CTX_RIGP0] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP0_TRACE,
+ [BNXT_CTX_L2HWRM] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_L2_HWRM_TRACE,
+ [BNXT_CTX_REHWRM] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ROCE_HWRM_TRACE,
+ [BNXT_CTX_CA0] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA0_TRACE,
+ [BNXT_CTX_CA1] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA1_TRACE,
+ [BNXT_CTX_CA2] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA2_TRACE,
+ [BNXT_CTX_RIGP1] = DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP1_TRACE,
};
static struct workqueue_struct *bnxt_pf_wq;
@@ -864,6 +879,11 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
bnapi->events &= ~BNXT_TX_CMP_EVENT;
}
+static bool bnxt_separate_head_pool(void)
+{
+ return PAGE_SIZE > BNXT_RX_PAGE_SIZE;
+}
+
static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
struct bnxt_rx_ring_info *rxr,
unsigned int *offset,
@@ -886,27 +906,19 @@ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
}
static inline u8 *__bnxt_alloc_rx_frag(struct bnxt *bp, dma_addr_t *mapping,
+ struct bnxt_rx_ring_info *rxr,
gfp_t gfp)
{
- u8 *data;
- struct pci_dev *pdev = bp->pdev;
+ unsigned int offset;
+ struct page *page;
- if (gfp == GFP_ATOMIC)
- data = napi_alloc_frag(bp->rx_buf_size);
- else
- data = netdev_alloc_frag(bp->rx_buf_size);
- if (!data)
+ page = page_pool_alloc_frag(rxr->head_pool, &offset,
+ bp->rx_buf_size, gfp);
+ if (!page)
return NULL;
- *mapping = dma_map_single_attrs(&pdev->dev, data + bp->rx_dma_offset,
- bp->rx_buf_use_size, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
-
- if (dma_mapping_error(&pdev->dev, *mapping)) {
- skb_free_frag(data);
- data = NULL;
- }
- return data;
+ *mapping = page_pool_get_dma_addr(page) + bp->rx_dma_offset + offset;
+ return page_address(page) + offset;
}
int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
@@ -928,7 +940,7 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
rx_buf->data = page;
rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset;
} else {
- u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp);
+ u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, rxr, gfp);
if (!data)
return -ENOMEM;
@@ -1179,13 +1191,14 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp,
}
skb = napi_build_skb(data, bp->rx_buf_size);
- dma_unmap_single_attrs(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
- bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
+ dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
+ bp->rx_dir);
if (!skb) {
- skb_free_frag(data);
+ page_pool_free_va(rxr->head_pool, data, true);
return NULL;
}
+ skb_mark_for_recycle(skb);
skb_reserve(skb, bp->rx_offset);
skb_put(skb, offset_and_len & 0xffff);
return skb;
@@ -1840,7 +1853,8 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
u8 *new_data;
dma_addr_t new_mapping;
- new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC);
+ new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, rxr,
+ GFP_ATOMIC);
if (!new_data) {
bnxt_abort_tpa(cpr, idx, agg_bufs);
cpr->sw_stats->rx.rx_oom_discards += 1;
@@ -1852,16 +1866,16 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
tpa_info->mapping = new_mapping;
skb = napi_build_skb(data, bp->rx_buf_size);
- dma_unmap_single_attrs(&bp->pdev->dev, mapping,
- bp->rx_buf_use_size, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
+ dma_sync_single_for_cpu(&bp->pdev->dev, mapping,
+ bp->rx_buf_use_size, bp->rx_dir);
if (!skb) {
- skb_free_frag(data);
+ page_pool_free_va(rxr->head_pool, data, true);
bnxt_abort_tpa(cpr, idx, agg_bufs);
cpr->sw_stats->rx.rx_oom_discards += 1;
return NULL;
}
+ skb_mark_for_recycle(skb);
skb_reserve(skb, bp->rx_offset);
skb_put(skb, len);
}
@@ -2254,11 +2268,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
if (!bnxt_get_rx_ts_p5(bp, &ts, cmpl_ts)) {
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
- unsigned long flags;
- spin_lock_irqsave(&ptp->ptp_lock, flags);
- ns = timecounter_cyc2time(&ptp->tc, ts);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ ns = bnxt_timecounter_cyc2time(ptp, ts);
memset(skb_hwtstamps(skb), 0,
sizeof(*skb_hwtstamps(skb)));
skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
@@ -2465,6 +2476,59 @@ static bool bnxt_auto_speed_updated(struct bnxt_link_info *link_info)
return false;
}
+bool bnxt_bs_trace_avail(struct bnxt *bp, u16 type)
+{
+ u32 flags = bp->ctx->ctx_arr[type].flags;
+
+ return (flags & BNXT_CTX_MEM_TYPE_VALID) &&
+ ((flags & BNXT_CTX_MEM_FW_TRACE) ||
+ (flags & BNXT_CTX_MEM_FW_BIN_TRACE));
+}
+
+static void bnxt_bs_trace_init(struct bnxt *bp, struct bnxt_ctx_mem_type *ctxm)
+{
+ u32 mem_size, pages, rem_bytes, magic_byte_offset;
+ u16 trace_type = bnxt_bstore_to_trace[ctxm->type];
+ struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info;
+ struct bnxt_ring_mem_info *rmem, *rmem_pg_tbl;
+ struct bnxt_bs_trace_info *bs_trace;
+ int last_pg;
+
+ if (ctxm->instance_bmap && ctxm->instance_bmap > 1)
+ return;
+
+ mem_size = ctxm->max_entries * ctxm->entry_size;
+ rem_bytes = mem_size % BNXT_PAGE_SIZE;
+ pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE);
+
+ last_pg = (pages - 1) & (MAX_CTX_PAGES - 1);
+ magic_byte_offset = (rem_bytes ? rem_bytes : BNXT_PAGE_SIZE) - 1;
+
+ rmem = &ctx_pg[0].ring_mem;
+ bs_trace = &bp->bs_trace[trace_type];
+ bs_trace->ctx_type = ctxm->type;
+ bs_trace->trace_type = trace_type;
+ if (pages > MAX_CTX_PAGES) {
+ int last_pg_dir = rmem->nr_pages - 1;
+
+ rmem_pg_tbl = &ctx_pg[0].ctx_pg_tbl[last_pg_dir]->ring_mem;
+ bs_trace->magic_byte = rmem_pg_tbl->pg_arr[last_pg];
+ } else {
+ bs_trace->magic_byte = rmem->pg_arr[last_pg];
+ }
+ bs_trace->magic_byte += magic_byte_offset;
+ *bs_trace->magic_byte = BNXT_TRACE_BUF_MAGIC_BYTE;
+}
+
+#define BNXT_EVENT_BUF_PRODUCER_TYPE(data1) \
+ (((data1) & ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_MASK) >>\
+ ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SFT)
+
+#define BNXT_EVENT_BUF_PRODUCER_OFFSET(data2) \
+ (((data2) & \
+ ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_MASK) >>\
+ ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_SFT)
+
#define BNXT_EVENT_THERMAL_CURRENT_TEMP(data2) \
((data2) & \
ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK)
@@ -2764,12 +2828,12 @@ static int bnxt_async_event_process(struct bnxt *bp,
if (!ptp)
goto async_event_process_exit;
- spin_lock_irqsave(&ptp->ptp_lock, flags);
bnxt_ptp_update_current_time(bp);
ns = (((u64)BNXT_EVENT_PHC_RTC_UPDATE(data1) <<
BNXT_PHC_BITS) | ptp->current_time);
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
bnxt_ptp_rtc_timecounter_init(ptp, ns);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
}
break;
}
@@ -2781,6 +2845,13 @@ static int bnxt_async_event_process(struct bnxt *bp,
hwrm_update_token(bp, seq_id, BNXT_HWRM_DEFERRED);
goto async_event_process_exit;
}
+ case ASYNC_EVENT_CMPL_EVENT_ID_DBG_BUF_PRODUCER: {
+ u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1);
+ u32 offset = BNXT_EVENT_BUF_PRODUCER_OFFSET(data2);
+
+ bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset);
+ goto async_event_process_exit;
+ }
default:
goto async_event_process_exit;
}
@@ -3102,7 +3173,7 @@ static int bnxt_poll(struct napi_struct *napi, int budget)
cpr->rx_packets,
cpr->rx_bytes,
&dim_sample);
- net_dim(&cpr->dim, dim_sample);
+ net_dim(&cpr->dim, &dim_sample);
}
return work_done;
}
@@ -3233,7 +3304,7 @@ poll_done:
cpr_rx->rx_packets,
cpr_rx->rx_bytes,
&dim_sample);
- net_dim(&cpr->dim, dim_sample);
+ net_dim(&cpr->dim, &dim_sample);
}
return work_done;
}
@@ -3311,28 +3382,22 @@ static void bnxt_free_tx_skbs(struct bnxt *bp)
static void bnxt_free_one_rx_ring(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
{
- struct pci_dev *pdev = bp->pdev;
int i, max_idx;
max_idx = bp->rx_nr_pages * RX_DESC_CNT;
for (i = 0; i < max_idx; i++) {
struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[i];
- dma_addr_t mapping = rx_buf->mapping;
void *data = rx_buf->data;
if (!data)
continue;
rx_buf->data = NULL;
- if (BNXT_RX_PAGE_MODE(bp)) {
+ if (BNXT_RX_PAGE_MODE(bp))
page_pool_recycle_direct(rxr->page_pool, data);
- } else {
- dma_unmap_single_attrs(&pdev->dev, mapping,
- bp->rx_buf_use_size, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
- skb_free_frag(data);
- }
+ else
+ page_pool_free_va(rxr->head_pool, data, true);
}
}
@@ -3359,7 +3424,6 @@ static void bnxt_free_one_rx_agg_ring(struct bnxt *bp, struct bnxt_rx_ring_info
static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
{
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[ring_nr];
- struct pci_dev *pdev = bp->pdev;
struct bnxt_tpa_idx_map *map;
int i;
@@ -3373,13 +3437,8 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
if (!data)
continue;
- dma_unmap_single_attrs(&pdev->dev, tpa_info->mapping,
- bp->rx_buf_use_size, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
-
tpa_info->data = NULL;
-
- skb_free_frag(data);
+ page_pool_free_va(rxr->head_pool, data, false);
}
skip_rx_tpa_free:
@@ -3434,6 +3493,35 @@ static void bnxt_init_ctx_mem(struct bnxt_ctx_mem_type *ctxm, void *p, int len)
*(p2 + i + offset) = init_val;
}
+static size_t __bnxt_copy_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem,
+ void *buf, size_t offset, size_t head,
+ size_t tail)
+{
+ int i, head_page, start_idx, source_offset;
+ size_t len, rem_len, total_len, max_bytes;
+
+ head_page = head / rmem->page_size;
+ source_offset = head % rmem->page_size;
+ total_len = (tail - head) & MAX_CTX_BYTES_MASK;
+ if (!total_len)
+ total_len = MAX_CTX_BYTES;
+ start_idx = head_page % MAX_CTX_PAGES;
+ max_bytes = (rmem->nr_pages - start_idx) * rmem->page_size -
+ source_offset;
+ total_len = min(total_len, max_bytes);
+ rem_len = total_len;
+
+ for (i = start_idx; rem_len; i++, source_offset = 0) {
+ len = min((size_t)(rmem->page_size - source_offset), rem_len);
+ if (buf)
+ memcpy(buf + offset, rmem->pg_arr[i] + source_offset,
+ len);
+ offset += len;
+ rem_len -= len;
+ }
+ return total_len;
+}
+
static void bnxt_free_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem)
{
struct pci_dev *pdev = bp->pdev;
@@ -3595,7 +3683,9 @@ static void bnxt_free_rx_rings(struct bnxt *bp)
xdp_rxq_info_unreg(&rxr->xdp_rxq);
page_pool_destroy(rxr->page_pool);
- rxr->page_pool = NULL;
+ if (rxr->page_pool != rxr->head_pool)
+ page_pool_destroy(rxr->head_pool);
+ rxr->page_pool = rxr->head_pool = NULL;
kfree(rxr->rx_agg_bmap);
rxr->rx_agg_bmap = NULL;
@@ -3613,6 +3703,7 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
int numa_node)
{
struct page_pool_params pp = { 0 };
+ struct page_pool *pool;
pp.pool_size = bp->rx_agg_ring_size;
if (BNXT_RX_PAGE_MODE(bp))
@@ -3625,14 +3716,25 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
pp.max_len = PAGE_SIZE;
pp.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
- rxr->page_pool = page_pool_create(&pp);
- if (IS_ERR(rxr->page_pool)) {
- int err = PTR_ERR(rxr->page_pool);
+ pool = page_pool_create(&pp);
+ if (IS_ERR(pool))
+ return PTR_ERR(pool);
+ rxr->page_pool = pool;
- rxr->page_pool = NULL;
- return err;
+ if (bnxt_separate_head_pool()) {
+ pp.pool_size = max(bp->rx_ring_size, 1024);
+ pool = page_pool_create(&pp);
+ if (IS_ERR(pool))
+ goto err_destroy_pp;
}
+ rxr->head_pool = pool;
+
return 0;
+
+err_destroy_pp:
+ page_pool_destroy(rxr->page_pool);
+ rxr->page_pool = NULL;
+ return PTR_ERR(pool);
}
static int bnxt_alloc_rx_rings(struct bnxt *bp)
@@ -4183,7 +4285,8 @@ static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr)
u8 *data;
for (i = 0; i < bp->max_tpa; i++) {
- data = __bnxt_alloc_rx_frag(bp, &mapping, GFP_KERNEL);
+ data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
+ GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -4558,7 +4661,7 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
struct net_device *dev = bp->dev;
if (page_mode) {
- bp->flags &= ~BNXT_FLAG_AGG_RINGS;
+ bp->flags &= ~(BNXT_FLAG_AGG_RINGS | BNXT_FLAG_NO_AGG_RINGS);
bp->flags |= BNXT_FLAG_RX_PAGE_MODE;
if (bp->xdp_prog->aux->xdp_has_frags)
@@ -8153,6 +8256,9 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
if (flags & FUNC_QCFG_RESP_FLAGS_RING_MONITOR_ENABLED)
bp->fw_cap |= BNXT_FW_CAP_RING_MONITOR;
+ if (flags & FUNC_QCFG_RESP_FLAGS_ENABLE_RDMA_SRIOV)
+ bp->fw_cap |= BNXT_FW_CAP_ENABLE_RDMA_SRIOV;
+
switch (resp->port_partition_type) {
case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_0:
case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_5:
@@ -8226,6 +8332,9 @@ static int bnxt_alloc_all_ctx_pg_info(struct bnxt *bp, int ctx_max)
return 0;
}
+static void bnxt_free_one_ctx_mem(struct bnxt *bp,
+ struct bnxt_ctx_mem_type *ctxm, bool force);
+
#define BNXT_CTX_INIT_VALID(flags) \
(!!((flags) & \
FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_ENABLE_CTX_KIND_INIT))
@@ -8234,7 +8343,7 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp)
{
struct hwrm_func_backing_store_qcaps_v2_output *resp;
struct hwrm_func_backing_store_qcaps_v2_input *req;
- struct bnxt_ctx_mem_info *ctx;
+ struct bnxt_ctx_mem_info *ctx = bp->ctx;
u16 type;
int rc;
@@ -8242,16 +8351,20 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp)
if (rc)
return rc;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
- bp->ctx = ctx;
+ if (!ctx) {
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ bp->ctx = ctx;
+ }
resp = hwrm_req_hold(bp, req);
for (type = 0; type < BNXT_CTX_V2_MAX; ) {
struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
u8 init_val, init_off, i;
+ u32 max_entries;
+ u16 entry_size;
__le32 *p;
u32 flags;
@@ -8261,15 +8374,26 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp)
goto ctx_done;
flags = le32_to_cpu(resp->flags);
type = le16_to_cpu(resp->next_valid_type);
- if (!(flags & FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_TYPE_VALID))
+ if (!(flags & BNXT_CTX_MEM_TYPE_VALID)) {
+ bnxt_free_one_ctx_mem(bp, ctxm, true);
continue;
-
+ }
+ entry_size = le16_to_cpu(resp->entry_size);
+ max_entries = le32_to_cpu(resp->max_num_entries);
+ if (ctxm->mem_valid) {
+ if (!(flags & BNXT_CTX_MEM_PERSIST) ||
+ ctxm->entry_size != entry_size ||
+ ctxm->max_entries != max_entries)
+ bnxt_free_one_ctx_mem(bp, ctxm, true);
+ else
+ continue;
+ }
ctxm->type = le16_to_cpu(resp->type);
- ctxm->entry_size = le16_to_cpu(resp->entry_size);
+ ctxm->entry_size = entry_size;
ctxm->flags = flags;
ctxm->instance_bmap = le32_to_cpu(resp->instance_bit_map);
ctxm->entry_multiple = resp->entry_multiple;
- ctxm->max_entries = le32_to_cpu(resp->max_num_entries);
+ ctxm->max_entries = max_entries;
ctxm->min_entries = le32_to_cpu(resp->min_num_entries);
init_val = resp->ctx_init_value;
init_off = resp->ctx_init_offset;
@@ -8294,7 +8418,8 @@ static int bnxt_hwrm_func_backing_store_qcaps(struct bnxt *bp)
struct hwrm_func_backing_store_qcaps_input *req;
int rc;
- if (bp->hwrm_spec_code < 0x10902 || BNXT_VF(bp) || bp->ctx)
+ if (bp->hwrm_spec_code < 0x10902 || BNXT_VF(bp) ||
+ (bp->ctx && bp->ctx->flags & BNXT_CTX_FLAG_INITED))
return 0;
if (bp->fw_cap & BNXT_FW_CAP_BACKING_STORE_V2)
@@ -8635,6 +8760,36 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp,
return rc;
}
+static size_t bnxt_copy_ctx_pg_tbls(struct bnxt *bp,
+ struct bnxt_ctx_pg_info *ctx_pg,
+ void *buf, size_t offset, size_t head,
+ size_t tail)
+{
+ struct bnxt_ring_mem_info *rmem = &ctx_pg->ring_mem;
+ size_t nr_pages = ctx_pg->nr_pages;
+ int page_size = rmem->page_size;
+ size_t len = 0, total_len = 0;
+ u16 depth = rmem->depth;
+
+ tail %= nr_pages * page_size;
+ do {
+ if (depth > 1) {
+ int i = head / (page_size * MAX_CTX_PAGES);
+ struct bnxt_ctx_pg_info *pg_tbl;
+
+ pg_tbl = ctx_pg->ctx_pg_tbl[i];
+ rmem = &pg_tbl->ring_mem;
+ }
+ len = __bnxt_copy_ring(bp, rmem, buf, offset, head, tail);
+ head += len;
+ offset += len;
+ total_len += len;
+ if (head >= nr_pages * page_size)
+ head = 0;
+ } while (head != tail);
+ return total_len;
+}
+
static void bnxt_free_ctx_pg_tbls(struct bnxt *bp,
struct bnxt_ctx_pg_info *ctx_pg)
{
@@ -8685,6 +8840,8 @@ static int bnxt_setup_ctxm_pg_tbls(struct bnxt *bp,
rc = bnxt_alloc_ctx_pg_tbls(bp, &ctx_pg[i], mem_size, pg_lvl,
ctxm->init_value ? ctxm : NULL);
}
+ if (!rc)
+ ctxm->mem_valid = 1;
return rc;
}
@@ -8711,6 +8868,16 @@ static int bnxt_hwrm_func_backing_store_cfg_v2(struct bnxt *bp,
hwrm_req_hold(bp, req);
req->type = cpu_to_le16(ctxm->type);
req->entry_size = cpu_to_le16(ctxm->entry_size);
+ if ((ctxm->flags & BNXT_CTX_MEM_PERSIST) &&
+ bnxt_bs_trace_avail(bp, ctxm->type)) {
+ struct bnxt_bs_trace_info *bs_trace;
+ u32 enables;
+
+ enables = FUNC_BACKING_STORE_CFG_V2_REQ_ENABLES_NEXT_BS_OFFSET;
+ req->enables = cpu_to_le32(enables);
+ bs_trace = &bp->bs_trace[bnxt_bstore_to_trace[ctxm->type]];
+ req->next_bs_offset = cpu_to_le32(bs_trace->last_offset);
+ }
req->subtype_valid_cnt = ctxm->split_entry_cnt;
for (i = 0, p = &req->split_entry_0; i < ctxm->split_entry_cnt; i++)
p[i] = cpu_to_le32(ctxm->split[i]);
@@ -8740,21 +8907,42 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena)
{
struct bnxt_ctx_mem_info *ctx = bp->ctx;
struct bnxt_ctx_mem_type *ctxm;
- u16 last_type;
+ u16 last_type = BNXT_CTX_INV;
int rc = 0;
u16 type;
- if (!ena)
- return 0;
- else if (ena & FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM)
- last_type = BNXT_CTX_MAX - 1;
- else
- last_type = BNXT_CTX_L2_MAX - 1;
+ for (type = BNXT_CTX_SRT; type <= BNXT_CTX_RIGP1; type++) {
+ ctxm = &ctx->ctx_arr[type];
+ if (!bnxt_bs_trace_avail(bp, type))
+ continue;
+ if (!ctxm->mem_valid) {
+ rc = bnxt_setup_ctxm_pg_tbls(bp, ctxm,
+ ctxm->max_entries, 1);
+ if (rc) {
+ netdev_warn(bp->dev, "Unable to setup ctx page for type:0x%x.\n",
+ type);
+ continue;
+ }
+ bnxt_bs_trace_init(bp, ctxm);
+ last_type = type;
+ }
+ }
+
+ if (last_type == BNXT_CTX_INV) {
+ if (!ena)
+ return 0;
+ else if (ena & FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM)
+ last_type = BNXT_CTX_MAX - 1;
+ else
+ last_type = BNXT_CTX_L2_MAX - 1;
+ }
ctx->ctx_arr[last_type].last = 1;
for (type = 0 ; type < BNXT_CTX_V2_MAX; type++) {
ctxm = &ctx->ctx_arr[type];
+ if (!ctxm->mem_valid)
+ continue;
rc = bnxt_hwrm_func_backing_store_cfg_v2(bp, ctxm, ctxm->last);
if (rc)
return rc;
@@ -8762,21 +8950,63 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena)
return 0;
}
-void bnxt_free_ctx_mem(struct bnxt *bp)
+/**
+ * __bnxt_copy_ctx_mem - copy host context memory
+ * @bp: The driver context
+ * @ctxm: The pointer to the context memory type
+ * @buf: The destination buffer or NULL to just obtain the length
+ * @offset: The buffer offset to copy the data to
+ * @head: The head offset of context memory to copy from
+ * @tail: The tail offset (last byte + 1) of context memory to end the copy
+ *
+ * This function is called for debugging purposes to dump the host context
+ * used by the chip.
+ *
+ * Return: Length of memory copied
+ */
+static size_t __bnxt_copy_ctx_mem(struct bnxt *bp,
+ struct bnxt_ctx_mem_type *ctxm, void *buf,
+ size_t offset, size_t head, size_t tail)
{
- struct bnxt_ctx_mem_info *ctx = bp->ctx;
- u16 type;
+ struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info;
+ size_t len = 0, total_len = 0;
+ int i, n = 1;
- if (!ctx)
- return;
+ if (!ctx_pg)
+ return 0;
- for (type = 0; type < BNXT_CTX_V2_MAX; type++) {
- struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
- struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info;
- int i, n = 1;
+ if (ctxm->instance_bmap)
+ n = hweight32(ctxm->instance_bmap);
+ for (i = 0; i < n; i++) {
+ len = bnxt_copy_ctx_pg_tbls(bp, &ctx_pg[i], buf, offset, head,
+ tail);
+ offset += len;
+ total_len += len;
+ }
+ return total_len;
+}
- if (!ctx_pg)
- continue;
+size_t bnxt_copy_ctx_mem(struct bnxt *bp, struct bnxt_ctx_mem_type *ctxm,
+ void *buf, size_t offset)
+{
+ size_t tail = ctxm->max_entries * ctxm->entry_size;
+
+ return __bnxt_copy_ctx_mem(bp, ctxm, buf, offset, 0, tail);
+}
+
+static void bnxt_free_one_ctx_mem(struct bnxt *bp,
+ struct bnxt_ctx_mem_type *ctxm, bool force)
+{
+ struct bnxt_ctx_pg_info *ctx_pg;
+ int i, n = 1;
+
+ ctxm->last = 0;
+
+ if (ctxm->mem_valid && !force && (ctxm->flags & BNXT_CTX_MEM_PERSIST))
+ return;
+
+ ctx_pg = ctxm->pg_info;
+ if (ctx_pg) {
if (ctxm->instance_bmap)
n = hweight32(ctxm->instance_bmap);
for (i = 0; i < n; i++)
@@ -8784,11 +9014,27 @@ void bnxt_free_ctx_mem(struct bnxt *bp)
kfree(ctx_pg);
ctxm->pg_info = NULL;
+ ctxm->mem_valid = 0;
}
+ memset(ctxm, 0, sizeof(*ctxm));
+}
+
+void bnxt_free_ctx_mem(struct bnxt *bp, bool force)
+{
+ struct bnxt_ctx_mem_info *ctx = bp->ctx;
+ u16 type;
+
+ if (!ctx)
+ return;
+
+ for (type = 0; type < BNXT_CTX_V2_MAX; type++)
+ bnxt_free_one_ctx_mem(bp, &ctx->ctx_arr[type], force);
ctx->flags &= ~BNXT_CTX_FLAG_INITED;
- kfree(ctx);
- bp->ctx = NULL;
+ if (force) {
+ kfree(ctx);
+ bp->ctx = NULL;
+ }
}
static int bnxt_alloc_ctx_mem(struct bnxt *bp)
@@ -9053,7 +9299,6 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
struct hwrm_port_mac_ptp_qcfg_output *resp;
struct hwrm_port_mac_ptp_qcfg_input *req;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
- bool phc_cfg;
u8 flags;
int rc;
@@ -9100,8 +9345,9 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
rc = -ENODEV;
goto exit;
}
- phc_cfg = (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0;
- rc = bnxt_ptp_init(bp, phc_cfg);
+ ptp->rtc_configured =
+ (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0;
+ rc = bnxt_ptp_init(bp);
if (rc)
netdev_warn(bp->dev, "PTP initialization failed.\n");
exit:
@@ -9179,6 +9425,9 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->flags |= BNXT_FLAG_UDP_GSO_CAP;
if (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_TX_PKT_TS_CMPL_SUPPORTED)
bp->fw_cap |= BNXT_FW_CAP_TX_TS_CMP;
+ if (BNXT_PF(bp) &&
+ (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_ROCE_VF_RESOURCE_MGMT_SUPPORTED))
+ bp->fw_cap |= BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED;
bp->tx_push_thresh = 0;
if ((flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) &&
@@ -10885,7 +11134,7 @@ static void bnxt_free_irq(struct bnxt *bp)
irq = &bp->irq_tbl[map_idx];
if (irq->requested) {
if (irq->have_cpumask) {
- irq_set_affinity_hint(irq->vector, NULL);
+ irq_update_affinity_hint(irq->vector, NULL);
free_cpumask_var(irq->cpu_mask);
irq->have_cpumask = 0;
}
@@ -10940,10 +11189,10 @@ static int bnxt_request_irq(struct bnxt *bp)
irq->have_cpumask = 1;
cpumask_set_cpu(cpumask_local_spread(i, numa_node),
irq->cpu_mask);
- rc = irq_set_affinity_hint(irq->vector, irq->cpu_mask);
+ rc = irq_update_affinity_hint(irq->vector, irq->cpu_mask);
if (rc) {
netdev_warn(bp->dev,
- "Set affinity failed, IRQ = %d\n",
+ "Update affinity hint failed, IRQ = %d\n",
irq->vector);
break;
}
@@ -10988,7 +11237,8 @@ static void bnxt_init_napi(struct bnxt *bp)
cp_nr_rings--;
for (i = 0; i < cp_nr_rings; i++) {
bnapi = bp->bnapi[i];
- netif_napi_add(bp->dev, &bnapi->napi, poll_fn);
+ netif_napi_add_config(bp->dev, &bnapi->napi, poll_fn,
+ bnapi->index);
}
if (BNXT_CHIP_TYPE_NITRO_A0(bp)) {
bnapi = bp->bnapi[cp_nr_rings];
@@ -11748,7 +11998,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
set_bit(BNXT_STATE_FW_RESET_DET, &bp->state);
if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
bnxt_ulp_irq_stop(bp);
- bnxt_free_ctx_mem(bp);
+ bnxt_free_ctx_mem(bp, false);
bnxt_dcb_free(bp);
rc = bnxt_fw_init_one(bp);
if (rc) {
@@ -12882,7 +13132,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
if (features & NETIF_F_GRO_HW)
features &= ~NETIF_F_LRO;
- /* Both CTAG and STAG VLAN accelaration on the RX side have to be
+ /* Both CTAG and STAG VLAN acceleration on the RX side have to be
* turned on or off together.
*/
vlan_features = features & BNXT_HW_FEATURE_VLAN_ALL_RX;
@@ -13461,7 +13711,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
bnxt_hwrm_func_drv_unrgtr(bp);
if (pci_is_enabled(bp->pdev))
pci_disable_device(bp->pdev);
- bnxt_free_ctx_mem(bp);
+ bnxt_free_ctx_mem(bp, false);
}
static bool is_bnxt_fw_ok(struct bnxt *bp)
@@ -13495,12 +13745,13 @@ static void bnxt_force_fw_reset(struct bnxt *bp)
test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
return;
+ /* we have to serialize with bnxt_refclk_read()*/
if (ptp) {
unsigned long flags;
- spin_lock_irqsave(&ptp->ptp_lock, flags);
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
} else {
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
}
@@ -13564,12 +13815,13 @@ void bnxt_fw_reset(struct bnxt *bp)
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
int n = 0, tmo;
+ /* we have to serialize with bnxt_refclk_read()*/
if (ptp) {
unsigned long flags;
- spin_lock_irqsave(&ptp->ptp_lock, flags);
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
} else {
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
}
@@ -14494,6 +14746,14 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
bnxt_close_nic(bp, true, false);
WRITE_ONCE(dev->mtu, new_mtu);
+
+ /* MTU change may change the AGG ring settings if an XDP multi-buffer
+ * program is attached. We need to set the AGG rings settings and
+ * rx_skb_func accordingly.
+ */
+ if (READ_ONCE(bp->xdp_prog))
+ bnxt_set_rx_skb_mode(bp, true);
+
bnxt_set_ring_params(bp);
if (netif_running(dev))
@@ -15231,6 +15491,13 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
for (i = 0; i <= BNXT_VNIC_NTUPLE; i++) {
vnic = &bp->vnic_info[i];
+
+ rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true);
+ if (rc) {
+ netdev_err(bp->dev, "hwrm vnic %d set rss failure rc: %d\n",
+ vnic->vnic_id, rc);
+ return rc;
+ }
vnic->mru = bp->dev->mtu + ETH_HLEN + VLAN_HLEN;
bnxt_hwrm_vnic_update(bp, vnic,
VNIC_UPDATE_REQ_ENABLES_MRU_VALID);
@@ -15316,7 +15583,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
kfree(bp->fw_health);
bp->fw_health = NULL;
bnxt_cleanup_pci(bp);
- bnxt_free_ctx_mem(bp);
+ bnxt_free_ctx_mem(bp, true);
bnxt_free_crash_dump_mem(bp);
kfree(bp->rss_indir_tbl);
bp->rss_indir_tbl = NULL;
@@ -15958,7 +16225,7 @@ init_err_pci_clean:
kfree(bp->fw_health);
bp->fw_health = NULL;
bnxt_cleanup_pci(bp);
- bnxt_free_ctx_mem(bp);
+ bnxt_free_ctx_mem(bp, true);
bnxt_free_crash_dump_mem(bp);
kfree(bp->rss_indir_tbl);
bp->rss_indir_tbl = NULL;
@@ -15984,6 +16251,7 @@ static void bnxt_shutdown(struct pci_dev *pdev)
if (netif_running(dev))
dev_close(dev);
+ bnxt_ptp_clear(bp);
bnxt_clear_int_mode(bp);
pci_disable_device(pdev);
@@ -16011,8 +16279,9 @@ static int bnxt_suspend(struct device *device)
rc = bnxt_close(dev);
}
bnxt_hwrm_func_drv_unrgtr(bp);
+ bnxt_ptp_clear(bp);
pci_disable_device(bp->pdev);
- bnxt_free_ctx_mem(bp);
+ bnxt_free_ctx_mem(bp, false);
rtnl_unlock();
return rc;
}
@@ -16054,6 +16323,10 @@ static int bnxt_resume(struct device *device)
if (bp->fw_crash_mem)
bnxt_hwrm_crash_dump_mem_cfg(bp);
+ if (bnxt_ptp_init(bp)) {
+ kfree(bp->ptp_cfg);
+ bp->ptp_cfg = NULL;
+ }
bnxt_get_wol_settings(bp);
if (netif_running(dev)) {
rc = bnxt_open(dev);
@@ -16124,7 +16397,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
if (pci_is_enabled(pdev))
pci_disable_device(pdev);
- bnxt_free_ctx_mem(bp);
+ bnxt_free_ctx_mem(bp, false);
rtnl_unlock();
/* Request a slot slot reset. */
@@ -16136,7 +16409,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot.
- * At this point, the card has exprienced a hard reset,
+ * At this point, the card has experienced a hard reset,
* followed by fixups by BIOS, and has its config space
* set up identically to what it was at cold boot.
*/
@@ -16164,7 +16437,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
pci_set_master(pdev);
/* Upon fatal error, our device internal logic that latches to
* BAR value is getting reset and will restore only upon
- * rewritting the BARs.
+ * rewriting the BARs.
*
* As pci_restore_state() does not re-write the BARs if the
* value is same as saved value earlier, driver needs to
@@ -16232,8 +16505,12 @@ static void bnxt_io_resume(struct pci_dev *pdev)
rtnl_lock();
err = bnxt_hwrm_func_qcaps(bp);
- if (!err && netif_running(netdev))
- err = bnxt_open(netdev);
+ if (!err) {
+ if (netif_running(netdev))
+ err = bnxt_open(netdev);
+ else
+ err = bnxt_reserve_rings(bp, true);
+ }
if (!err)
netif_device_attach(netdev);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 69231e85140b..23f1aff214b4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1105,6 +1105,7 @@ struct bnxt_rx_ring_info {
struct bnxt_ring_struct rx_agg_ring_struct;
struct xdp_rxq_info xdp_rxq;
struct page_pool *page_pool;
+ struct page_pool *head_pool;
};
struct bnxt_rx_sw_stats {
@@ -1848,6 +1849,8 @@ struct bnxt_vf_rep {
#define MAX_CTX_PAGES (BNXT_PAGE_SIZE / 8)
#define MAX_CTX_TOTAL_PAGES (MAX_CTX_PAGES * MAX_CTX_PAGES)
+#define MAX_CTX_BYTES ((size_t)MAX_CTX_TOTAL_PAGES * BNXT_PAGE_SIZE)
+#define MAX_CTX_BYTES_MASK (MAX_CTX_BYTES - 1)
struct bnxt_ctx_pg_info {
u32 entries;
@@ -1880,6 +1883,13 @@ struct bnxt_ctx_mem_type {
u16 entry_size;
u32 flags;
#define BNXT_CTX_MEM_TYPE_VALID FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_TYPE_VALID
+#define BNXT_CTX_MEM_FW_TRACE \
+ FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_DBG_TRACE
+#define BNXT_CTX_MEM_FW_BIN_TRACE \
+ FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_BIN_DBG_TRACE
+#define BNXT_CTX_MEM_PERSIST \
+ FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_NEXT_BS_OFFSET
+
u32 instance_bmap;
u8 init_value;
u8 entry_multiple;
@@ -1888,6 +1898,7 @@ struct bnxt_ctx_mem_type {
u32 max_entries;
u32 min_entries;
u8 last:1;
+ u8 mem_valid:1;
u8 split_entry_cnt;
#define BNXT_MAX_SPLIT_ENTRY 4
union {
@@ -1919,21 +1930,30 @@ struct bnxt_ctx_mem_type {
#define BNXT_CTX_FTQM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_FP_TQM_RING
#define BNXT_CTX_MRAV FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_MRAV
#define BNXT_CTX_TIM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TIM
-#define BNXT_CTX_TKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TKC
-#define BNXT_CTX_RKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RKC
+#define BNXT_CTX_TCK FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TX_CK
+#define BNXT_CTX_RCK FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RX_CK
#define BNXT_CTX_MTQM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_MP_TQM_RING
#define BNXT_CTX_SQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SQ_DB_SHADOW
#define BNXT_CTX_RQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RQ_DB_SHADOW
#define BNXT_CTX_SRQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRQ_DB_SHADOW
#define BNXT_CTX_CQDBS FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CQ_DB_SHADOW
-#define BNXT_CTX_QTKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_QUIC_TKC
-#define BNXT_CTX_QRKC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_QUIC_RKC
#define BNXT_CTX_TBLSC FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_TBL_SCOPE
#define BNXT_CTX_XPAR FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_XID_PARTITION
+#define BNXT_CTX_SRT FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRT_TRACE
+#define BNXT_CTX_SRT2 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_SRT2_TRACE
+#define BNXT_CTX_CRT FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CRT_TRACE
+#define BNXT_CTX_CRT2 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CRT2_TRACE
+#define BNXT_CTX_RIGP0 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RIGP0_TRACE
+#define BNXT_CTX_L2HWRM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_L2_HWRM_TRACE
+#define BNXT_CTX_REHWRM FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_ROCE_HWRM_TRACE
+#define BNXT_CTX_CA0 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA0_TRACE
+#define BNXT_CTX_CA1 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA1_TRACE
+#define BNXT_CTX_CA2 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA2_TRACE
+#define BNXT_CTX_RIGP1 FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RIGP1_TRACE
#define BNXT_CTX_MAX (BNXT_CTX_TIM + 1)
#define BNXT_CTX_L2_MAX (BNXT_CTX_FTQM + 1)
-#define BNXT_CTX_V2_MAX (BNXT_CTX_XPAR + 1)
+#define BNXT_CTX_V2_MAX (BNXT_CTX_RIGP1 + 1)
#define BNXT_CTX_INV ((u16)-1)
struct bnxt_ctx_mem_info {
@@ -2094,6 +2114,26 @@ enum board_idx {
NETXTREME_E_P7_VF,
};
+#define BNXT_TRACE_BUF_MAGIC_BYTE ((u8)0xbc)
+#define BNXT_TRACE_MAX 11
+
+struct bnxt_bs_trace_info {
+ u8 *magic_byte;
+ u32 last_offset;
+ u8 wrapped:1;
+ u16 ctx_type;
+ u16 trace_type;
+};
+
+static inline void bnxt_bs_trace_check_wrap(struct bnxt_bs_trace_info *bs_trace,
+ u32 offset)
+{
+ if (!bs_trace->wrapped &&
+ *bs_trace->magic_byte != BNXT_TRACE_BUF_MAGIC_BYTE)
+ bs_trace->wrapped = 1;
+ bs_trace->last_offset = offset;
+}
+
struct bnxt {
void __iomem *bar0;
void __iomem *bar1;
@@ -2406,6 +2446,8 @@ struct bnxt {
#define BNXT_FW_CAP_DCBX_AGENT BIT_ULL(2)
#define BNXT_FW_CAP_NEW_RM BIT_ULL(3)
#define BNXT_FW_CAP_IF_CHANGE BIT_ULL(4)
+ #define BNXT_FW_CAP_ENABLE_RDMA_SRIOV BIT_ULL(5)
+ #define BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED BIT_ULL(6)
#define BNXT_FW_CAP_KONG_MB_CHNL BIT_ULL(7)
#define BNXT_FW_CAP_OVS_64BIT_HANDLE BIT_ULL(10)
#define BNXT_FW_CAP_TRUSTED_VF BIT_ULL(11)
@@ -2452,6 +2494,10 @@ struct bnxt {
#define BNXT_SUPPORTS_QUEUE_API(bp) \
(BNXT_PF(bp) && BNXT_SUPPORTS_NTUPLE_VNIC(bp) && \
((bp)->fw_cap & BNXT_FW_CAP_VNIC_RE_FLUSH))
+#define BNXT_RDMA_SRIOV_EN(bp) \
+ ((bp)->fw_cap & BNXT_FW_CAP_ENABLE_RDMA_SRIOV)
+#define BNXT_ROCE_VF_RESC_CAP(bp) \
+ ((bp)->fw_cap & BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED)
u32 hwrm_spec_code;
u16 hwrm_cmd_seq;
@@ -2622,6 +2668,7 @@ struct bnxt {
u16 dump_flag;
#define BNXT_DUMP_LIVE 0
#define BNXT_DUMP_CRASH 1
+#define BNXT_DUMP_DRIVER 2
struct bpf_prog *xdp_prog;
@@ -2650,6 +2697,7 @@ struct bnxt {
struct bnxt_ctx_pg_info *fw_crash_mem;
u32 fw_crash_len;
+ struct bnxt_bs_trace_info bs_trace[BNXT_TRACE_MAX];
};
#define BNXT_NUM_RX_RING_STATS 8
@@ -2785,12 +2833,14 @@ static inline bool bnxt_sriov_cfg(struct bnxt *bp)
#endif
}
+extern const u16 bnxt_bstore_to_trace[];
extern const u16 bnxt_lhint_arr[];
int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
u16 prod, gfp_t gfp);
void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data);
u32 bnxt_fw_health_readl(struct bnxt *bp, int reg_idx);
+bool bnxt_bs_trace_avail(struct bnxt *bp, u16 type);
void bnxt_set_tpa_flags(struct bnxt *bp);
void bnxt_set_ring_params(struct bnxt *);
int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
@@ -2822,7 +2872,9 @@ int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic,
int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings);
int bnxt_nq_rings_in_use(struct bnxt *bp);
int bnxt_hwrm_set_coal(struct bnxt *);
-void bnxt_free_ctx_mem(struct bnxt *bp);
+size_t bnxt_copy_ctx_mem(struct bnxt *bp, struct bnxt_ctx_mem_type *ctxm,
+ void *buf, size_t offset);
+void bnxt_free_ctx_mem(struct bnxt *bp, bool force);
int bnxt_num_tx_to_cp(struct bnxt *bp, int tx);
unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp);
unsigned int bnxt_get_avail_stat_ctxs_for_en(struct bnxt *bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c
index 4e2b938ed1f7..7236d8e548ab 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c
@@ -15,6 +15,50 @@
#include "bnxt_hwrm.h"
#include "bnxt_coredump.h"
+static const u16 bnxt_bstore_to_seg_id[] = {
+ [BNXT_CTX_QP] = BNXT_CTX_MEM_SEG_QP,
+ [BNXT_CTX_SRQ] = BNXT_CTX_MEM_SEG_SRQ,
+ [BNXT_CTX_CQ] = BNXT_CTX_MEM_SEG_CQ,
+ [BNXT_CTX_VNIC] = BNXT_CTX_MEM_SEG_VNIC,
+ [BNXT_CTX_STAT] = BNXT_CTX_MEM_SEG_STAT,
+ [BNXT_CTX_STQM] = BNXT_CTX_MEM_SEG_STQM,
+ [BNXT_CTX_FTQM] = BNXT_CTX_MEM_SEG_FTQM,
+ [BNXT_CTX_MRAV] = BNXT_CTX_MEM_SEG_MRAV,
+ [BNXT_CTX_TIM] = BNXT_CTX_MEM_SEG_TIM,
+ [BNXT_CTX_SRT] = BNXT_CTX_MEM_SEG_SRT,
+ [BNXT_CTX_SRT2] = BNXT_CTX_MEM_SEG_SRT2,
+ [BNXT_CTX_CRT] = BNXT_CTX_MEM_SEG_CRT,
+ [BNXT_CTX_CRT2] = BNXT_CTX_MEM_SEG_CRT2,
+ [BNXT_CTX_RIGP0] = BNXT_CTX_MEM_SEG_RIGP0,
+ [BNXT_CTX_L2HWRM] = BNXT_CTX_MEM_SEG_L2HWRM,
+ [BNXT_CTX_REHWRM] = BNXT_CTX_MEM_SEG_REHWRM,
+ [BNXT_CTX_CA0] = BNXT_CTX_MEM_SEG_CA0,
+ [BNXT_CTX_CA1] = BNXT_CTX_MEM_SEG_CA1,
+ [BNXT_CTX_CA2] = BNXT_CTX_MEM_SEG_CA2,
+ [BNXT_CTX_RIGP1] = BNXT_CTX_MEM_SEG_RIGP1,
+};
+
+static int bnxt_dbg_hwrm_log_buffer_flush(struct bnxt *bp, u16 type, u32 flags,
+ u32 *offset)
+{
+ struct hwrm_dbg_log_buffer_flush_output *resp;
+ struct hwrm_dbg_log_buffer_flush_input *req;
+ int rc;
+
+ rc = hwrm_req_init(bp, req, HWRM_DBG_LOG_BUFFER_FLUSH);
+ if (rc)
+ return rc;
+
+ req->flags = cpu_to_le32(flags);
+ req->type = cpu_to_le16(type);
+ resp = hwrm_req_hold(bp, req);
+ rc = hwrm_req_send(bp, req);
+ if (!rc)
+ *offset = le32_to_cpu(resp->current_buffer_offset);
+ hwrm_req_drop(bp, req);
+ return rc;
+}
+
static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg,
struct bnxt_hwrm_dbg_dma_info *info)
{
@@ -165,11 +209,12 @@ static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id,
return rc;
}
-static void
+void
bnxt_fill_coredump_seg_hdr(struct bnxt *bp,
struct bnxt_coredump_segment_hdr *seg_hdr,
struct coredump_segment_record *seg_rec, u32 seg_len,
- int status, u32 duration, u32 instance)
+ int status, u32 duration, u32 instance, u32 comp_id,
+ u32 seg_id)
{
memset(seg_hdr, 0, sizeof(*seg_hdr));
memcpy(seg_hdr->signature, "sEgM", 4);
@@ -180,11 +225,8 @@ bnxt_fill_coredump_seg_hdr(struct bnxt *bp,
seg_hdr->high_version = seg_rec->version_hi;
seg_hdr->flags = cpu_to_le32(seg_rec->compress_flags);
} else {
- /* For hwrm_ver_get response Component id = 2
- * and Segment id = 0
- */
- seg_hdr->component_id = cpu_to_le32(2);
- seg_hdr->segment_id = 0;
+ seg_hdr->component_id = cpu_to_le32(comp_id);
+ seg_hdr->segment_id = cpu_to_le32(seg_id);
}
seg_hdr->function_id = cpu_to_le16(bp->pdev->devfn);
seg_hdr->length = cpu_to_le32(seg_len);
@@ -269,7 +311,78 @@ bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record,
record->ioctl_high_version = 0;
}
-static int __bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
+static void bnxt_fill_drv_seg_record(struct bnxt *bp,
+ struct bnxt_driver_segment_record *record,
+ struct bnxt_ctx_mem_type *ctxm, u16 type)
+{
+ struct bnxt_bs_trace_info *bs_trace = &bp->bs_trace[type];
+ u32 offset = 0;
+ int rc = 0;
+
+ rc = bnxt_dbg_hwrm_log_buffer_flush(bp, type, 0, &offset);
+ if (rc)
+ return;
+
+ bnxt_bs_trace_check_wrap(bs_trace, offset);
+ record->max_entries = cpu_to_le32(ctxm->max_entries);
+ record->entry_size = cpu_to_le32(ctxm->entry_size);
+ record->offset = cpu_to_le32(bs_trace->last_offset);
+ record->wrapped = bs_trace->wrapped;
+}
+
+static u32 bnxt_get_ctx_coredump(struct bnxt *bp, void *buf, u32 offset,
+ u32 *segs)
+{
+ struct bnxt_driver_segment_record record = {};
+ struct bnxt_coredump_segment_hdr seg_hdr;
+ struct bnxt_ctx_mem_info *ctx = bp->ctx;
+ u32 comp_id = BNXT_DRV_COMP_ID;
+ void *data = NULL;
+ size_t len = 0;
+ u16 type;
+
+ *segs = 0;
+ if (!ctx)
+ return 0;
+
+ if (buf)
+ buf += offset;
+ for (type = 0 ; type <= BNXT_CTX_RIGP1; type++) {
+ struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
+ bool trace = bnxt_bs_trace_avail(bp, type);
+ u32 seg_id = bnxt_bstore_to_seg_id[type];
+ size_t seg_len, extra_hlen = 0;
+
+ if (!ctxm->mem_valid || !seg_id)
+ continue;
+
+ if (trace)
+ extra_hlen = BNXT_SEG_RCD_LEN;
+ if (buf)
+ data = buf + BNXT_SEG_HDR_LEN + extra_hlen;
+ seg_len = bnxt_copy_ctx_mem(bp, ctxm, data, 0) + extra_hlen;
+ if (buf) {
+ bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, seg_len,
+ 0, 0, 0, comp_id, seg_id);
+ memcpy(buf, &seg_hdr, BNXT_SEG_HDR_LEN);
+ buf += BNXT_SEG_HDR_LEN;
+ if (trace) {
+ u16 trace_type = bnxt_bstore_to_trace[type];
+
+ bnxt_fill_drv_seg_record(bp, &record, ctxm,
+ trace_type);
+ memcpy(buf, &record, BNXT_SEG_RCD_LEN);
+ }
+ buf += seg_len;
+ }
+ len += BNXT_SEG_HDR_LEN + seg_len;
+ *segs += 1;
+ }
+ return len;
+}
+
+static int __bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf,
+ u32 *dump_len)
{
u32 ver_get_resp_len = sizeof(struct hwrm_ver_get_output);
u32 offset = 0, seg_hdr_len, seg_record_len, buf_len = 0;
@@ -287,17 +400,31 @@ static int __bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
start_utc = sys_tz.tz_minuteswest * 60;
seg_hdr_len = sizeof(seg_hdr);
- /* First segment should be hwrm_ver_get response */
+ /* First segment should be hwrm_ver_get response.
+ * For hwrm_ver_get response Component id = 2 and Segment id = 0.
+ */
*dump_len = seg_hdr_len + ver_get_resp_len;
if (buf) {
bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, ver_get_resp_len,
- 0, 0, 0);
+ 0, 0, 0, BNXT_VER_GET_COMP_ID, 0);
memcpy(buf + offset, &seg_hdr, seg_hdr_len);
offset += seg_hdr_len;
memcpy(buf + offset, &bp->ver_resp, ver_get_resp_len);
offset += ver_get_resp_len;
}
+ if (dump_type == BNXT_DUMP_DRIVER) {
+ u32 drv_len, segs = 0;
+
+ drv_len = bnxt_get_ctx_coredump(bp, buf, offset, &segs);
+ *dump_len += drv_len;
+ offset += drv_len;
+ if (buf)
+ coredump.total_segs += segs;
+ goto err;
+ }
+
+ seg_record_len = sizeof(*seg_record);
rc = bnxt_hwrm_dbg_coredump_list(bp, &coredump);
if (rc) {
netdev_err(bp->dev, "Failed to get coredump segment list\n");
@@ -346,7 +473,7 @@ next_seg:
end = jiffies;
duration = jiffies_to_msecs(end - start);
bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, seg_record, seg_len,
- rc, duration, 0);
+ rc, duration, 0, 0, 0);
if (buf) {
/* Write segment header into the buffer */
@@ -442,7 +569,7 @@ int bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, u32 *dump_len)
else
return -EOPNOTSUPP;
} else {
- return __bnxt_get_coredump(bp, buf, dump_len);
+ return __bnxt_get_coredump(bp, dump_type, buf, dump_len);
}
}
@@ -512,9 +639,12 @@ u32 bnxt_get_coredump_length(struct bnxt *bp, u16 dump_type)
return bp->fw_crash_len;
}
- if (bnxt_hwrm_get_dump_len(bp, dump_type, &len)) {
- if (dump_type != BNXT_DUMP_CRASH)
- __bnxt_get_coredump(bp, NULL, &len);
+ if (dump_type != BNXT_DUMP_DRIVER) {
+ if (!bnxt_hwrm_get_dump_len(bp, dump_type, &len))
+ return len;
}
+ if (dump_type != BNXT_DUMP_CRASH)
+ __bnxt_get_coredump(bp, dump_type, NULL, &len);
+
return len;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h
index a76d5c281413..d1cd6387f3ab 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h
@@ -68,11 +68,49 @@ struct bnxt_coredump_record {
__le16 rsvd3[313];
};
+struct bnxt_driver_segment_record {
+ __le32 max_entries;
+ __le32 entry_size;
+ __le32 offset;
+ __u8 wrapped:1;
+ __u8 unused[3];
+};
+
+#define BNXT_VER_GET_COMP_ID 2
+#define BNXT_DRV_COMP_ID 0xd
+
+#define BNXT_CTX_MEM_SEG_ID_START 0x200
+
+#define BNXT_CTX_MEM_SEG_QP (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_QP)
+#define BNXT_CTX_MEM_SEG_SRQ (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_SRQ)
+#define BNXT_CTX_MEM_SEG_CQ (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_CQ)
+#define BNXT_CTX_MEM_SEG_VNIC (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_VNIC)
+#define BNXT_CTX_MEM_SEG_STAT (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_STAT)
+#define BNXT_CTX_MEM_SEG_STQM (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_STQM)
+#define BNXT_CTX_MEM_SEG_FTQM (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_FTQM)
+#define BNXT_CTX_MEM_SEG_MRAV (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_MRAV)
+#define BNXT_CTX_MEM_SEG_TIM (BNXT_CTX_MEM_SEG_ID_START + BNXT_CTX_TIM)
+
+#define BNXT_CTX_MEM_SEG_SRT 0x1
+#define BNXT_CTX_MEM_SEG_SRT2 0x2
+#define BNXT_CTX_MEM_SEG_CRT 0x3
+#define BNXT_CTX_MEM_SEG_CRT2 0x4
+#define BNXT_CTX_MEM_SEG_RIGP0 0x5
+#define BNXT_CTX_MEM_SEG_L2HWRM 0x6
+#define BNXT_CTX_MEM_SEG_REHWRM 0x7
+#define BNXT_CTX_MEM_SEG_CA0 0x8
+#define BNXT_CTX_MEM_SEG_CA1 0x9
+#define BNXT_CTX_MEM_SEG_CA2 0xa
+#define BNXT_CTX_MEM_SEG_RIGP1 0xb
+
#define BNXT_CRASH_DUMP_LEN (8 << 20)
#define COREDUMP_LIST_BUF_LEN 2048
#define COREDUMP_RETRIEVE_BUF_LEN 4096
+#define BNXT_SEG_HDR_LEN sizeof(struct bnxt_coredump_segment_hdr)
+#define BNXT_SEG_RCD_LEN sizeof(struct bnxt_driver_segment_record)
+
struct bnxt_coredump {
void *data;
int data_size;
@@ -118,6 +156,11 @@ struct hwrm_dbg_cmn_output {
#define BNXT_DBG_CR_DUMP_MDM_CFG_DDR \
DBG_CRASHDUMP_MEDIUM_CFG_REQ_TYPE_DDR
+void bnxt_fill_coredump_seg_hdr(struct bnxt *bp,
+ struct bnxt_coredump_segment_hdr *seg_hdr,
+ struct coredump_segment_record *seg_rec,
+ u32 seg_len, int status, u32 duration,
+ u32 instance, u32 comp_id, u32 seg_id);
int bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, u32 *dump_len);
int bnxt_hwrm_get_dump_len(struct bnxt *bp, u16 dump_type, u32 *dump_len);
u32 bnxt_get_coredump_length(struct bnxt *bp, u16 dump_type);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index 4cb0fabf977e..ef8288fd68f4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -463,7 +463,7 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
break;
}
bnxt_cancel_reservations(bp, false);
- bnxt_free_ctx_mem(bp);
+ bnxt_free_ctx_mem(bp, false);
break;
}
case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index f71cc8188b4e..f1f6bb328a55 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -705,112 +705,105 @@ skip_ring_stats:
static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
{
struct bnxt *bp = netdev_priv(dev);
- static const char * const *str;
u32 i, j, num_str;
+ const char *str;
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < bp->cp_nr_rings; i++) {
- if (is_rx_ring(bp, i)) {
- num_str = NUM_RING_RX_HW_STATS;
- for (j = 0; j < num_str; j++) {
- sprintf(buf, "[%d]: %s", i,
- bnxt_ring_rx_stats_str[j]);
- buf += ETH_GSTRING_LEN;
+ if (is_rx_ring(bp, i))
+ for (j = 0; j < NUM_RING_RX_HW_STATS; j++) {
+ str = bnxt_ring_rx_stats_str[j];
+ ethtool_sprintf(&buf, "[%d]: %s", i,
+ str);
}
- }
- if (is_tx_ring(bp, i)) {
- num_str = NUM_RING_TX_HW_STATS;
- for (j = 0; j < num_str; j++) {
- sprintf(buf, "[%d]: %s", i,
- bnxt_ring_tx_stats_str[j]);
- buf += ETH_GSTRING_LEN;
+ if (is_tx_ring(bp, i))
+ for (j = 0; j < NUM_RING_TX_HW_STATS; j++) {
+ str = bnxt_ring_tx_stats_str[j];
+ ethtool_sprintf(&buf, "[%d]: %s", i,
+ str);
}
- }
num_str = bnxt_get_num_tpa_ring_stats(bp);
if (!num_str || !is_rx_ring(bp, i))
goto skip_tpa_stats;
if (bp->max_tpa_v2)
- str = bnxt_ring_tpa2_stats_str;
+ for (j = 0; j < num_str; j++) {
+ str = bnxt_ring_tpa2_stats_str[j];
+ ethtool_sprintf(&buf, "[%d]: %s", i,
+ str);
+ }
else
- str = bnxt_ring_tpa_stats_str;
-
- for (j = 0; j < num_str; j++) {
- sprintf(buf, "[%d]: %s", i, str[j]);
- buf += ETH_GSTRING_LEN;
- }
-skip_tpa_stats:
- if (is_rx_ring(bp, i)) {
- num_str = NUM_RING_RX_SW_STATS;
for (j = 0; j < num_str; j++) {
- sprintf(buf, "[%d]: %s", i,
- bnxt_rx_sw_stats_str[j]);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_ring_tpa_stats_str[j];
+ ethtool_sprintf(&buf, "[%d]: %s", i,
+ str);
}
- }
- num_str = NUM_RING_CMN_SW_STATS;
- for (j = 0; j < num_str; j++) {
- sprintf(buf, "[%d]: %s", i,
- bnxt_cmn_sw_stats_str[j]);
- buf += ETH_GSTRING_LEN;
+skip_tpa_stats:
+ if (is_rx_ring(bp, i))
+ for (j = 0; j < NUM_RING_RX_SW_STATS; j++) {
+ str = bnxt_rx_sw_stats_str[j];
+ ethtool_sprintf(&buf, "[%d]: %s", i,
+ str);
+ }
+ for (j = 0; j < NUM_RING_CMN_SW_STATS; j++) {
+ str = bnxt_cmn_sw_stats_str[j];
+ ethtool_sprintf(&buf, "[%d]: %s", i, str);
}
}
- for (i = 0; i < BNXT_NUM_RING_ERR_STATS; i++) {
- strscpy(buf, bnxt_ring_err_stats_arr[i], ETH_GSTRING_LEN);
- buf += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < BNXT_NUM_RING_ERR_STATS; i++)
+ ethtool_puts(&buf, bnxt_ring_err_stats_arr[i]);
- if (bp->flags & BNXT_FLAG_PORT_STATS) {
+ if (bp->flags & BNXT_FLAG_PORT_STATS)
for (i = 0; i < BNXT_NUM_PORT_STATS; i++) {
- strcpy(buf, bnxt_port_stats_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_port_stats_arr[i].string;
+ ethtool_puts(&buf, str);
}
- }
+
if (bp->flags & BNXT_FLAG_PORT_STATS_EXT) {
u32 len;
len = min_t(u32, bp->fw_rx_stats_ext_size,
ARRAY_SIZE(bnxt_port_stats_ext_arr));
for (i = 0; i < len; i++) {
- strcpy(buf, bnxt_port_stats_ext_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_port_stats_ext_arr[i].string;
+ ethtool_puts(&buf, str);
}
+
len = min_t(u32, bp->fw_tx_stats_ext_size,
ARRAY_SIZE(bnxt_tx_port_stats_ext_arr));
for (i = 0; i < len; i++) {
- strcpy(buf,
- bnxt_tx_port_stats_ext_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_tx_port_stats_ext_arr[i].string;
+ ethtool_puts(&buf, str);
}
+
if (bp->pri2cos_valid) {
for (i = 0; i < 8; i++) {
- strcpy(buf,
- bnxt_rx_bytes_pri_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_rx_bytes_pri_arr[i].string;
+ ethtool_puts(&buf, str);
}
+
for (i = 0; i < 8; i++) {
- strcpy(buf,
- bnxt_rx_pkts_pri_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_rx_pkts_pri_arr[i].string;
+ ethtool_puts(&buf, str);
}
+
for (i = 0; i < 8; i++) {
- strcpy(buf,
- bnxt_tx_bytes_pri_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_tx_bytes_pri_arr[i].string;
+ ethtool_puts(&buf, str);
}
+
for (i = 0; i < 8; i++) {
- strcpy(buf,
- bnxt_tx_pkts_pri_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ str = bnxt_tx_pkts_pri_arr[i].string;
+ ethtool_puts(&buf, str);
}
}
}
break;
case ETH_SS_TEST:
if (bp->num_tests)
- memcpy(buf, bp->test_info->string,
- bp->num_tests * ETH_GSTRING_LEN);
+ for (i = 0; i < bp->num_tests; i++)
+ ethtool_puts(&buf, bp->test_info->string[i]);
break;
default:
netdev_err(bp->dev, "bnxt_get_strings invalid request %x\n",
@@ -1131,14 +1124,15 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
fkeys = &fltr->fkeys;
fmasks = &fltr->fmasks;
if (fkeys->basic.n_proto == htons(ETH_P_IP)) {
- if (fkeys->basic.ip_proto == IPPROTO_ICMP ||
- fkeys->basic.ip_proto == IPPROTO_RAW) {
+ if (fkeys->basic.ip_proto == BNXT_IP_PROTO_WILDCARD) {
fs->flow_type = IP_USER_FLOW;
fs->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
- if (fkeys->basic.ip_proto == IPPROTO_ICMP)
- fs->h_u.usr_ip4_spec.proto = IPPROTO_ICMP;
- else
- fs->h_u.usr_ip4_spec.proto = IPPROTO_RAW;
+ fs->h_u.usr_ip4_spec.proto = BNXT_IP_PROTO_WILDCARD;
+ fs->m_u.usr_ip4_spec.proto = 0;
+ } else if (fkeys->basic.ip_proto == IPPROTO_ICMP) {
+ fs->flow_type = IP_USER_FLOW;
+ fs->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
+ fs->h_u.usr_ip4_spec.proto = IPPROTO_ICMP;
fs->m_u.usr_ip4_spec.proto = BNXT_IP_PROTO_FULL_MASK;
} else if (fkeys->basic.ip_proto == IPPROTO_TCP) {
fs->flow_type = TCP_V4_FLOW;
@@ -1160,13 +1154,13 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
fs->m_u.tcp_ip4_spec.pdst = fmasks->ports.dst;
}
} else {
- if (fkeys->basic.ip_proto == IPPROTO_ICMPV6 ||
- fkeys->basic.ip_proto == IPPROTO_RAW) {
+ if (fkeys->basic.ip_proto == BNXT_IP_PROTO_WILDCARD) {
fs->flow_type = IPV6_USER_FLOW;
- if (fkeys->basic.ip_proto == IPPROTO_ICMPV6)
- fs->h_u.usr_ip6_spec.l4_proto = IPPROTO_ICMPV6;
- else
- fs->h_u.usr_ip6_spec.l4_proto = IPPROTO_RAW;
+ fs->h_u.usr_ip6_spec.l4_proto = BNXT_IP_PROTO_WILDCARD;
+ fs->m_u.usr_ip6_spec.l4_proto = 0;
+ } else if (fkeys->basic.ip_proto == IPPROTO_ICMPV6) {
+ fs->flow_type = IPV6_USER_FLOW;
+ fs->h_u.usr_ip6_spec.l4_proto = IPPROTO_ICMPV6;
fs->m_u.usr_ip6_spec.l4_proto = BNXT_IP_PROTO_FULL_MASK;
} else if (fkeys->basic.ip_proto == IPPROTO_TCP) {
fs->flow_type = TCP_V6_FLOW;
@@ -1289,10 +1283,12 @@ static int bnxt_add_l2_cls_rule(struct bnxt *bp,
static bool bnxt_verify_ntuple_ip4_flow(struct ethtool_usrip4_spec *ip_spec,
struct ethtool_usrip4_spec *ip_mask)
{
+ u8 mproto = ip_mask->proto;
+ u8 sproto = ip_spec->proto;
+
if (ip_mask->l4_4_bytes || ip_mask->tos ||
ip_spec->ip_ver != ETH_RX_NFC_IP4 ||
- ip_mask->proto != BNXT_IP_PROTO_FULL_MASK ||
- (ip_spec->proto != IPPROTO_RAW && ip_spec->proto != IPPROTO_ICMP))
+ (mproto && (mproto != BNXT_IP_PROTO_FULL_MASK || sproto != IPPROTO_ICMP)))
return false;
return true;
}
@@ -1300,10 +1296,11 @@ static bool bnxt_verify_ntuple_ip4_flow(struct ethtool_usrip4_spec *ip_spec,
static bool bnxt_verify_ntuple_ip6_flow(struct ethtool_usrip6_spec *ip_spec,
struct ethtool_usrip6_spec *ip_mask)
{
+ u8 mproto = ip_mask->l4_proto;
+ u8 sproto = ip_spec->l4_proto;
+
if (ip_mask->l4_4_bytes || ip_mask->tclass ||
- ip_mask->l4_proto != BNXT_IP_PROTO_FULL_MASK ||
- (ip_spec->l4_proto != IPPROTO_RAW &&
- ip_spec->l4_proto != IPPROTO_ICMPV6))
+ (mproto && (mproto != BNXT_IP_PROTO_FULL_MASK || sproto != IPPROTO_ICMPV6)))
return false;
return true;
}
@@ -1357,7 +1354,8 @@ static int bnxt_add_ntuple_cls_rule(struct bnxt *bp,
struct ethtool_usrip4_spec *ip_spec = &fs->h_u.usr_ip4_spec;
struct ethtool_usrip4_spec *ip_mask = &fs->m_u.usr_ip4_spec;
- fkeys->basic.ip_proto = ip_spec->proto;
+ fkeys->basic.ip_proto = ip_mask->proto ? ip_spec->proto
+ : BNXT_IP_PROTO_WILDCARD;
fkeys->basic.n_proto = htons(ETH_P_IP);
fkeys->addrs.v4addrs.src = ip_spec->ip4src;
fmasks->addrs.v4addrs.src = ip_mask->ip4src;
@@ -1388,7 +1386,8 @@ static int bnxt_add_ntuple_cls_rule(struct bnxt *bp,
struct ethtool_usrip6_spec *ip_spec = &fs->h_u.usr_ip6_spec;
struct ethtool_usrip6_spec *ip_mask = &fs->m_u.usr_ip6_spec;
- fkeys->basic.ip_proto = ip_spec->l4_proto;
+ fkeys->basic.ip_proto = ip_mask->l4_proto ? ip_spec->l4_proto
+ : BNXT_IP_PROTO_WILDCARD;
fkeys->basic.n_proto = htons(ETH_P_IPV6);
fkeys->addrs.v6addrs.src = *(struct in6_addr *)&ip_spec->ip6src;
fmasks->addrs.v6addrs.src = *(struct in6_addr *)&ip_mask->ip6src;
@@ -2838,19 +2837,24 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
}
base->port = PORT_NONE;
- if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
+ if (media == BNXT_MEDIA_TP) {
base->port = PORT_TP;
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
lk_ksettings->link_modes.supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT,
lk_ksettings->link_modes.advertising);
+ } else if (media == BNXT_MEDIA_KR) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Backplane_BIT,
+ lk_ksettings->link_modes.supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Backplane_BIT,
+ lk_ksettings->link_modes.advertising);
} else {
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
lk_ksettings->link_modes.supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
lk_ksettings->link_modes.advertising);
- if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC)
+ if (media == BNXT_MEDIA_CR)
base->port = PORT_DA;
else
base->port = PORT_FIBRE;
@@ -4985,8 +4989,8 @@ static int bnxt_set_dump(struct net_device *dev, struct ethtool_dump *dump)
{
struct bnxt *bp = netdev_priv(dev);
- if (dump->flag > BNXT_DUMP_CRASH) {
- netdev_info(dev, "Supports only Live(0) and Crash(1) dumps.\n");
+ if (dump->flag > BNXT_DUMP_DRIVER) {
+ netdev_info(dev, "Supports only Live(0), Crash(1), Driver(2) dumps.\n");
return -EINVAL;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
index e2ee030237d4..33b86ede1ce5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
@@ -44,6 +44,7 @@ struct bnxt_led_cfg {
#define BNXT_PXP_REG_LEN 0x3110
#define BNXT_IP_PROTO_FULL_MASK 0xFF
+#define BNXT_IP_PROTO_WILDCARD 0x0
extern const struct ethtool_ops bnxt_ethtool_ops;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
index f8ef6f1a1964..5f8de1634378 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
@@ -42,6 +42,10 @@ struct hwrm_resp_hdr {
#define TLV_TYPE_MODIFY_ROCE_CC_GEN1 0x5UL
#define TLV_TYPE_QUERY_ROCE_CC_GEN2 0x6UL
#define TLV_TYPE_MODIFY_ROCE_CC_GEN2 0x7UL
+#define TLV_TYPE_QUERY_ROCE_CC_GEN1_EXT 0x8UL
+#define TLV_TYPE_MODIFY_ROCE_CC_GEN1_EXT 0x9UL
+#define TLV_TYPE_QUERY_ROCE_CC_GEN2_EXT 0xaUL
+#define TLV_TYPE_MODIFY_ROCE_CC_GEN2_EXT 0xbUL
#define TLV_TYPE_ENGINE_CKV_ALIAS_ECC_PUBLIC_KEY 0x8001UL
#define TLV_TYPE_ENGINE_CKV_IV 0x8003UL
#define TLV_TYPE_ENGINE_CKV_AUTH_TAG 0x8004UL
@@ -509,6 +513,7 @@ struct cmd_nums {
#define HWRM_TFC_IF_TBL_GET 0x399UL
#define HWRM_TFC_TBL_SCOPE_CONFIG_GET 0x39aUL
#define HWRM_TFC_RESC_USAGE_QUERY 0x39bUL
+ #define HWRM_TFC_GLOBAL_ID_FREE 0x39cUL
#define HWRM_SV 0x400UL
#define HWRM_DBG_SERDES_TEST 0xff0eUL
#define HWRM_DBG_LOG_BUFFER_FLUSH 0xff0fUL
@@ -624,8 +629,8 @@ struct hwrm_err_output {
#define HWRM_VERSION_MAJOR 1
#define HWRM_VERSION_MINOR 10
#define HWRM_VERSION_UPDATE 3
-#define HWRM_VERSION_RSVD 68
-#define HWRM_VERSION_STR "1.10.3.68"
+#define HWRM_VERSION_RSVD 85
+#define HWRM_VERSION_STR "1.10.3.85"
/* hwrm_ver_get_input (size:192b/24B) */
struct hwrm_ver_get_input {
@@ -1302,6 +1307,43 @@ struct hwrm_async_event_cmpl_error_report {
#define ASYNC_EVENT_CMPL_ERROR_REPORT_EVENT_DATA1_ERROR_TYPE_SFT 0
};
+/* hwrm_async_event_cmpl_dbg_buf_producer (size:128b/16B) */
+struct hwrm_async_event_cmpl_dbg_buf_producer {
+ __le16 type;
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_MASK 0x3fUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_LAST ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_TYPE_HWRM_ASYNC_EVENT
+ __le16 event_id;
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_DBG_BUF_PRODUCER 0x4cUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_LAST ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_ID_DBG_BUF_PRODUCER
+ __le32 event_data2;
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_MASK 0xffffffffUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA2_CURR_OFF_SFT 0
+ u8 opaque_v;
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_V 0x1UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_OPAQUE_MASK 0xfeUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_OPAQUE_SFT 1
+ u8 timestamp_lo;
+ __le16 timestamp_hi;
+ __le32 event_data1;
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_MASK 0xffffUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SFT 0
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SRT_TRACE 0x0UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_SRT2_TRACE 0x1UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CRT_TRACE 0x2UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CRT2_TRACE 0x3UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_RIGP0_TRACE 0x4UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_L2_HWRM_TRACE 0x5UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_ROCE_HWRM_TRACE 0x6UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA0_TRACE 0x7UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA1_TRACE 0x8UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_CA2_TRACE 0x9UL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_RIGP1_TRACE 0xaUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_AFM_KONG_HWRM_TRACE 0xbUL
+ #define ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_LAST ASYNC_EVENT_CMPL_DBG_BUF_PRODUCER_EVENT_DATA1_TYPE_AFM_KONG_HWRM_TRACE
+};
+
/* hwrm_async_event_cmpl_hwrm_error (size:128b/16B) */
struct hwrm_async_event_cmpl_hwrm_error {
__le16 type;
@@ -1864,7 +1906,10 @@ struct hwrm_func_qcaps_output {
__le32 roce_vf_max_gid;
__le32 flags_ext3;
#define FUNC_QCAPS_RESP_FLAGS_EXT3_RM_RSV_WHILE_ALLOC_CAP 0x1UL
- u8 unused_3[7];
+ #define FUNC_QCAPS_RESP_FLAGS_EXT3_REQUIRE_L2_FILTER 0x2UL
+ #define FUNC_QCAPS_RESP_FLAGS_EXT3_MAX_ROCE_VFS_SUPPORTED 0x4UL
+ __le16 max_roce_vfs;
+ u8 unused_3[5];
u8 valid;
};
@@ -2253,17 +2298,18 @@ struct hwrm_func_cfg_input {
#define FUNC_CFG_REQ_FLAGS2_KTLS_KEY_CTX_ASSETS_TEST 0x1UL
#define FUNC_CFG_REQ_FLAGS2_QUIC_KEY_CTX_ASSETS_TEST 0x2UL
__le32 enables2;
- #define FUNC_CFG_REQ_ENABLES2_KDNET 0x1UL
- #define FUNC_CFG_REQ_ENABLES2_DB_PAGE_SIZE 0x2UL
- #define FUNC_CFG_REQ_ENABLES2_QUIC_TX_KEY_CTXS 0x4UL
- #define FUNC_CFG_REQ_ENABLES2_QUIC_RX_KEY_CTXS 0x8UL
- #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_AV_PER_VF 0x10UL
- #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_CQ_PER_VF 0x20UL
- #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_MRW_PER_VF 0x40UL
- #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_QP_PER_VF 0x80UL
- #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_SRQ_PER_VF 0x100UL
- #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_GID_PER_VF 0x200UL
- #define FUNC_CFG_REQ_ENABLES2_XID_PARTITION_CFG 0x400UL
+ #define FUNC_CFG_REQ_ENABLES2_KDNET 0x1UL
+ #define FUNC_CFG_REQ_ENABLES2_DB_PAGE_SIZE 0x2UL
+ #define FUNC_CFG_REQ_ENABLES2_QUIC_TX_KEY_CTXS 0x4UL
+ #define FUNC_CFG_REQ_ENABLES2_QUIC_RX_KEY_CTXS 0x8UL
+ #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_AV_PER_VF 0x10UL
+ #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_CQ_PER_VF 0x20UL
+ #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_MRW_PER_VF 0x40UL
+ #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_QP_PER_VF 0x80UL
+ #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_SRQ_PER_VF 0x100UL
+ #define FUNC_CFG_REQ_ENABLES2_ROCE_MAX_GID_PER_VF 0x200UL
+ #define FUNC_CFG_REQ_ENABLES2_XID_PARTITION_CFG 0x400UL
+ #define FUNC_CFG_REQ_ENABLES2_PHYSICAL_SLOT_NUMBER 0x800UL
u8 port_kdnet_mode;
#define FUNC_CFG_REQ_PORT_KDNET_MODE_DISABLED 0x0UL
#define FUNC_CFG_REQ_PORT_KDNET_MODE_ENABLED 0x1UL
@@ -2281,7 +2327,7 @@ struct hwrm_func_cfg_input {
#define FUNC_CFG_REQ_DB_PAGE_SIZE_2MB 0x9UL
#define FUNC_CFG_REQ_DB_PAGE_SIZE_4MB 0xaUL
#define FUNC_CFG_REQ_DB_PAGE_SIZE_LAST FUNC_CFG_REQ_DB_PAGE_SIZE_4MB
- u8 unused_1[2];
+ __le16 physical_slot_number;
__le32 num_ktls_tx_key_ctxs;
__le32 num_ktls_rx_key_ctxs;
__le32 num_quic_tx_key_ctxs;
@@ -3683,7 +3729,7 @@ struct hwrm_func_ptp_ext_qcfg_output {
u8 valid;
};
-/* hwrm_func_backing_store_cfg_v2_input (size:448b/56B) */
+/* hwrm_func_backing_store_cfg_v2_input (size:512b/64B) */
struct hwrm_func_backing_store_cfg_v2_input {
__le16 req_type;
__le16 cmpl_ring;
@@ -3721,6 +3767,7 @@ struct hwrm_func_backing_store_cfg_v2_input {
#define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_CA1_TRACE 0x27UL
#define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_CA2_TRACE 0x28UL
#define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_RIGP1_TRACE 0x29UL
+ #define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL
#define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_INVALID 0xffffUL
#define FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_LAST FUNC_BACKING_STORE_CFG_V2_REQ_TYPE_INVALID
__le16 instance;
@@ -3752,6 +3799,9 @@ struct hwrm_func_backing_store_cfg_v2_input {
__le32 split_entry_1;
__le32 split_entry_2;
__le32 split_entry_3;
+ __le32 enables;
+ #define FUNC_BACKING_STORE_CFG_V2_REQ_ENABLES_NEXT_BS_OFFSET 0x1UL
+ __le32 next_bs_offset;
};
/* hwrm_func_backing_store_cfg_v2_output (size:128b/16B) */
@@ -3802,6 +3852,7 @@ struct hwrm_func_backing_store_qcfg_v2_input {
#define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_CA1_TRACE 0x27UL
#define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_CA2_TRACE 0x28UL
#define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_RIGP1_TRACE 0x29UL
+ #define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL
#define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_INVALID 0xffffUL
#define FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_LAST FUNC_BACKING_STORE_QCFG_V2_REQ_TYPE_INVALID
__le16 instance;
@@ -3963,6 +4014,7 @@ struct hwrm_func_backing_store_qcaps_v2_input {
#define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA1_TRACE 0x27UL
#define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_CA2_TRACE 0x28UL
#define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_RIGP1_TRACE 0x29UL
+ #define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL
#define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_INVALID 0xffffUL
#define FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_LAST FUNC_BACKING_STORE_QCAPS_V2_REQ_TYPE_INVALID
u8 rsvd[6];
@@ -4005,6 +4057,7 @@ struct hwrm_func_backing_store_qcaps_v2_output {
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_CA1_TRACE 0x27UL
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_CA2_TRACE 0x28UL
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_RIGP1_TRACE 0x29UL
+ #define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_AFM_KONG_HWRM_TRACE 0x2aUL
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_INVALID 0xffffUL
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_LAST FUNC_BACKING_STORE_QCAPS_V2_RESP_TYPE_INVALID
__le16 entry_size;
@@ -4014,6 +4067,8 @@ struct hwrm_func_backing_store_qcaps_v2_output {
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_DRIVER_MANAGED_MEMORY 0x4UL
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_ROCE_QP_PSEUDO_STATIC_ALLOC 0x8UL
#define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_DBG_TRACE 0x10UL
+ #define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_FW_BIN_DBG_TRACE 0x20UL
+ #define FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_NEXT_BS_OFFSET 0x40UL
__le32 instance_bit_map;
u8 ctx_init_value;
u8 ctx_init_offset;
@@ -4034,7 +4089,8 @@ struct hwrm_func_backing_store_qcaps_v2_output {
__le32 split_entry_1;
__le32 split_entry_2;
__le32 split_entry_3;
- u8 rsvd3[3];
+ __le16 max_instance_count;
+ u8 rsvd3;
u8 valid;
};
@@ -4535,11 +4591,12 @@ struct hwrm_port_phy_qcfg_output {
#define PORT_PHY_QCFG_RESP_PHY_TYPE_800G_BASEDR8 0x3dUL
#define PORT_PHY_QCFG_RESP_PHY_TYPE_LAST PORT_PHY_QCFG_RESP_PHY_TYPE_800G_BASEDR8
u8 media_type;
- #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_UNKNOWN 0x0UL
- #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP 0x1UL
- #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC 0x2UL
- #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE 0x3UL
- #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_LAST PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_UNKNOWN 0x0UL
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP 0x1UL
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC 0x2UL
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE 0x3UL
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_BACKPLANE 0x4UL
+ #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_LAST PORT_PHY_QCFG_RESP_MEDIA_TYPE_BACKPLANE
u8 xcvr_pkg_type;
#define PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL 0x1UL
#define PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_EXTERNAL 0x2UL
@@ -4654,7 +4711,8 @@ struct hwrm_port_phy_qcfg_output {
#define PORT_PHY_QCFG_RESP_LINK_PARTNER_PAM4_ADV_SPEEDS_100GB 0x2UL
#define PORT_PHY_QCFG_RESP_LINK_PARTNER_PAM4_ADV_SPEEDS_200GB 0x4UL
u8 link_down_reason;
- #define PORT_PHY_QCFG_RESP_LINK_DOWN_REASON_RF 0x1UL
+ #define PORT_PHY_QCFG_RESP_LINK_DOWN_REASON_RF 0x1UL
+ #define PORT_PHY_QCFG_RESP_LINK_DOWN_REASON_OTP_SPEED_VIOLATION 0x2UL
__le16 support_speeds2;
#define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_1GB 0x1UL
#define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_10GB 0x2UL
@@ -9241,20 +9299,22 @@ struct hwrm_fw_set_time_output {
/* hwrm_struct_hdr (size:128b/16B) */
struct hwrm_struct_hdr {
__le16 struct_id;
- #define STRUCT_HDR_STRUCT_ID_LLDP_CFG 0x41bUL
- #define STRUCT_HDR_STRUCT_ID_DCBX_ETS 0x41dUL
- #define STRUCT_HDR_STRUCT_ID_DCBX_PFC 0x41fUL
- #define STRUCT_HDR_STRUCT_ID_DCBX_APP 0x421UL
- #define STRUCT_HDR_STRUCT_ID_DCBX_FEATURE_STATE 0x422UL
- #define STRUCT_HDR_STRUCT_ID_LLDP_GENERIC 0x424UL
- #define STRUCT_HDR_STRUCT_ID_LLDP_DEVICE 0x426UL
- #define STRUCT_HDR_STRUCT_ID_POWER_BKUP 0x427UL
- #define STRUCT_HDR_STRUCT_ID_PEER_MMAP 0x429UL
- #define STRUCT_HDR_STRUCT_ID_AFM_OPAQUE 0x1UL
- #define STRUCT_HDR_STRUCT_ID_PORT_DESCRIPTION 0xaUL
- #define STRUCT_HDR_STRUCT_ID_RSS_V2 0x64UL
- #define STRUCT_HDR_STRUCT_ID_MSIX_PER_VF 0xc8UL
- #define STRUCT_HDR_STRUCT_ID_LAST STRUCT_HDR_STRUCT_ID_MSIX_PER_VF
+ #define STRUCT_HDR_STRUCT_ID_LLDP_CFG 0x41bUL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_ETS 0x41dUL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_PFC 0x41fUL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_APP 0x421UL
+ #define STRUCT_HDR_STRUCT_ID_DCBX_FEATURE_STATE 0x422UL
+ #define STRUCT_HDR_STRUCT_ID_LLDP_GENERIC 0x424UL
+ #define STRUCT_HDR_STRUCT_ID_LLDP_DEVICE 0x426UL
+ #define STRUCT_HDR_STRUCT_ID_POWER_BKUP 0x427UL
+ #define STRUCT_HDR_STRUCT_ID_PEER_MMAP 0x429UL
+ #define STRUCT_HDR_STRUCT_ID_AFM_OPAQUE 0x1UL
+ #define STRUCT_HDR_STRUCT_ID_PORT_DESCRIPTION 0xaUL
+ #define STRUCT_HDR_STRUCT_ID_RSS_V2 0x64UL
+ #define STRUCT_HDR_STRUCT_ID_MSIX_PER_VF 0xc8UL
+ #define STRUCT_HDR_STRUCT_ID_UDCC_RTT_BUCKET_COUNT 0x12cUL
+ #define STRUCT_HDR_STRUCT_ID_UDCC_RTT_BUCKET_BOUND 0x12dUL
+ #define STRUCT_HDR_STRUCT_ID_LAST STRUCT_HDR_STRUCT_ID_UDCC_RTT_BUCKET_BOUND
__le16 len;
u8 version;
u8 count;
@@ -9756,6 +9816,7 @@ struct hwrm_dbg_qcaps_output {
#define DBG_QCAPS_RESP_FLAGS_COREDUMP_HOST_DDR 0x10UL
#define DBG_QCAPS_RESP_FLAGS_COREDUMP_HOST_CAPTURE 0x20UL
#define DBG_QCAPS_RESP_FLAGS_PTRACE 0x40UL
+ #define DBG_QCAPS_RESP_FLAGS_REG_ACCESS_RESTRICTED 0x80UL
u8 unused_1[3];
u8 valid;
};
@@ -9996,6 +10057,43 @@ struct hwrm_dbg_ring_info_get_output {
u8 valid;
};
+/* hwrm_dbg_log_buffer_flush_input (size:192b/24B) */
+struct hwrm_dbg_log_buffer_flush_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+ __le16 type;
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT_TRACE 0x0UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_SRT2_TRACE 0x1UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT_TRACE 0x2UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CRT2_TRACE 0x3UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP0_TRACE 0x4UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_L2_HWRM_TRACE 0x5UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ROCE_HWRM_TRACE 0x6UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA0_TRACE 0x7UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA1_TRACE 0x8UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_CA2_TRACE 0x9UL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_RIGP1_TRACE 0xaUL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_AFM_KONG_HWRM_TRACE 0xbUL
+ #define DBG_LOG_BUFFER_FLUSH_REQ_TYPE_LAST DBG_LOG_BUFFER_FLUSH_REQ_TYPE_AFM_KONG_HWRM_TRACE
+ u8 unused_1[2];
+ __le32 flags;
+ #define DBG_LOG_BUFFER_FLUSH_REQ_FLAGS_FLUSH_ALL_BUFFERS 0x1UL
+};
+
+/* hwrm_dbg_log_buffer_flush_output (size:128b/16B) */
+struct hwrm_dbg_log_buffer_flush_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ __le32 current_buffer_offset;
+ u8 unused_1[3];
+ u8 valid;
+};
+
/* hwrm_nvm_read_input (size:320b/40B) */
struct hwrm_nvm_read_input {
__le16 req_type;
@@ -10080,6 +10178,7 @@ struct hwrm_nvm_write_input {
#define NVM_WRITE_REQ_FLAGS_KEEP_ORIG_ACTIVE_IMG 0x1UL
#define NVM_WRITE_REQ_FLAGS_BATCH_MODE 0x2UL
#define NVM_WRITE_REQ_FLAGS_BATCH_LAST 0x4UL
+ #define NVM_WRITE_REQ_FLAGS_SKIP_CRID_CHECK 0x8UL
__le32 dir_item_length;
__le32 offset;
__le32 len;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
index fa514be87650..2d4e19b96ee7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
@@ -67,15 +67,15 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
if (BNXT_PTP_USE_RTC(ptp->bp))
return bnxt_ptp_cfg_settime(ptp->bp, ns);
- spin_lock_irqsave(&ptp->ptp_lock, flags);
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
timecounter_init(&ptp->tc, &ptp->cc, ns);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
return 0;
}
/* Caller holds ptp_lock */
-static int bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
- u64 *ns)
+static int __bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
+ u64 *ns)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
u32 high_before, high_now, low;
@@ -98,17 +98,50 @@ static int bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
return 0;
}
-static void bnxt_ptp_get_current_time(struct bnxt *bp)
+static int bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
+ u64 *ns)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
unsigned long flags;
+ int rc;
+
+ /* We have to serialize reg access and FW reset */
+ read_seqlock_excl_irqsave(&ptp->ptp_lock, flags);
+ rc = __bnxt_refclk_read(bp, sts, ns);
+ read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
+ return rc;
+}
+
+static int bnxt_refclk_read_low(struct bnxt *bp, struct ptp_system_timestamp *sts,
+ u32 *low)
+{
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ unsigned long flags;
+
+ /* We have to serialize reg access and FW reset */
+ read_seqlock_excl_irqsave(&ptp->ptp_lock, flags);
+
+ if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+ read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
+ return -EIO;
+ }
+
+ ptp_read_system_prets(sts);
+ *low = readl(bp->bar0 + ptp->refclk_mapped_regs[0]);
+ ptp_read_system_postts(sts);
+
+ read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
+ return 0;
+}
+
+static void bnxt_ptp_get_current_time(struct bnxt *bp)
+{
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
if (!ptp)
return;
- spin_lock_irqsave(&ptp->ptp_lock, flags);
- WRITE_ONCE(ptp->old_time, ptp->current_time);
+ WRITE_ONCE(ptp->old_time, ptp->current_time >> BNXT_HI_TIMER_SHIFT);
bnxt_refclk_read(bp, NULL, &ptp->current_time);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
}
static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts,
@@ -151,36 +184,32 @@ static int bnxt_ptp_gettimex(struct ptp_clock_info *ptp_info,
{
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
ptp_info);
- unsigned long flags;
u64 ns, cycles;
+ u32 low;
int rc;
- spin_lock_irqsave(&ptp->ptp_lock, flags);
- rc = bnxt_refclk_read(ptp->bp, sts, &cycles);
- if (rc) {
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ rc = bnxt_refclk_read_low(ptp->bp, sts, &low);
+ if (rc)
return rc;
- }
- ns = timecounter_cyc2time(&ptp->tc, cycles);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+
+ cycles = bnxt_extend_cycles_32b_to_48b(ptp, low);
+ ns = bnxt_timecounter_cyc2time(ptp, cycles);
*ts = ns_to_timespec64(ns);
return 0;
}
-/* Caller holds ptp_lock */
void bnxt_ptp_update_current_time(struct bnxt *bp)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
bnxt_refclk_read(ptp->bp, NULL, &ptp->current_time);
- WRITE_ONCE(ptp->old_time, ptp->current_time);
+ WRITE_ONCE(ptp->old_time, ptp->current_time >> BNXT_HI_TIMER_SHIFT);
}
static int bnxt_ptp_adjphc(struct bnxt_ptp_cfg *ptp, s64 delta)
{
struct hwrm_port_mac_cfg_input *req;
- unsigned long flags;
int rc;
rc = hwrm_req_init(ptp->bp, req, HWRM_PORT_MAC_CFG);
@@ -194,9 +223,7 @@ static int bnxt_ptp_adjphc(struct bnxt_ptp_cfg *ptp, s64 delta)
if (rc) {
netdev_err(ptp->bp->dev, "ptp adjphc failed. rc = %x\n", rc);
} else {
- spin_lock_irqsave(&ptp->ptp_lock, flags);
bnxt_ptp_update_current_time(ptp->bp);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
}
return rc;
@@ -211,9 +238,9 @@ static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
if (BNXT_PTP_USE_RTC(ptp->bp))
return bnxt_ptp_adjphc(ptp, delta);
- spin_lock_irqsave(&ptp->ptp_lock, flags);
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
timecounter_adjtime(&ptp->tc, delta);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
return 0;
}
@@ -246,10 +273,10 @@ static int bnxt_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
if (!BNXT_MH(bp))
return bnxt_ptp_adjfine_rtc(bp, scaled_ppm);
- spin_lock_irqsave(&ptp->ptp_lock, flags);
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
timecounter_read(&ptp->tc);
ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
return 0;
}
@@ -257,13 +284,10 @@ void bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
struct ptp_clock_event event;
- unsigned long flags;
u64 ns, pps_ts;
pps_ts = EVENT_PPS_TS(data2, data1);
- spin_lock_irqsave(&ptp->ptp_lock, flags);
- ns = timecounter_cyc2time(&ptp->tc, pps_ts);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ ns = bnxt_timecounter_cyc2time(ptp, pps_ts);
switch (EVENT_DATA2_PPS_EVENT_TYPE(data2)) {
case ASYNC_EVENT_CMPL_PPS_TIMESTAMP_EVENT_DATA2_EVENT_TYPE_INTERNAL:
@@ -400,17 +424,13 @@ static int bnxt_get_target_cycles(struct bnxt_ptp_cfg *ptp, u64 target_ns,
{
u64 cycles_now;
u64 nsec_now, nsec_delta;
- unsigned long flags;
int rc;
- spin_lock_irqsave(&ptp->ptp_lock, flags);
rc = bnxt_refclk_read(ptp->bp, NULL, &cycles_now);
- if (rc) {
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ if (rc)
return rc;
- }
- nsec_now = timecounter_cyc2time(&ptp->tc, cycles_now);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+
+ nsec_now = bnxt_timecounter_cyc2time(ptp, cycles_now);
nsec_delta = target_ns - nsec_now;
*cycles_delta = div64_u64(nsec_delta << ptp->cc.shift, ptp->cc.mult);
@@ -687,7 +707,7 @@ static u64 bnxt_cc_read(const struct cyclecounter *cc)
struct bnxt_ptp_cfg *ptp = container_of(cc, struct bnxt_ptp_cfg, cc);
u64 ns = 0;
- bnxt_refclk_read(ptp->bp, NULL, &ns);
+ __bnxt_refclk_read(ptp->bp, NULL, &ns);
return ns;
}
@@ -697,7 +717,6 @@ static int bnxt_stamp_tx_skb(struct bnxt *bp, int slot)
struct skb_shared_hwtstamps timestamp;
struct bnxt_ptp_tx_req *txts_req;
unsigned long now = jiffies;
- unsigned long flags;
u64 ts = 0, ns = 0;
u32 tmo = 0;
int rc;
@@ -711,9 +730,7 @@ static int bnxt_stamp_tx_skb(struct bnxt *bp, int slot)
tmo, slot);
if (!rc) {
memset(&timestamp, 0, sizeof(timestamp));
- spin_lock_irqsave(&ptp->ptp_lock, flags);
- ns = timecounter_cyc2time(&ptp->tc, ts);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ ns = bnxt_timecounter_cyc2time(ptp, ts);
timestamp.hwtstamp = ns_to_ktime(ns);
skb_tstamp_tx(txts_req->tx_skb, &timestamp);
ptp->stats.ts_pkts++;
@@ -767,9 +784,9 @@ next_slot:
bnxt_ptp_get_current_time(bp);
ptp->next_period = now + HZ;
if (time_after_eq(now, ptp->next_overflow_check)) {
- spin_lock_irqsave(&ptp->ptp_lock, flags);
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
timecounter_read(&ptp->tc);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
ptp->next_overflow_check = now + BNXT_PHC_OVERFLOW_PERIOD;
}
if (rc == -EAGAIN)
@@ -808,15 +825,11 @@ void bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb, u16 prod)
int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
- u64 time;
if (!ptp)
return -ENODEV;
- BNXT_READ_TIME64(ptp, time, ptp->old_time);
- *ts = (time & BNXT_HI_TIMER_MASK) | pkt_ts;
- if (pkt_ts < (time & BNXT_LO_TIMER_MASK))
- *ts += BNXT_LO_TIMER_MASK + 1;
+ *ts = bnxt_extend_cycles_32b_to_48b(ptp, pkt_ts);
return 0;
}
@@ -829,7 +842,6 @@ void bnxt_tx_ts_cmp(struct bnxt *bp, struct bnxt_napi *bnapi,
u32 opaque = tscmp->tx_ts_cmp_opaque;
struct bnxt_tx_ring_info *txr;
struct bnxt_sw_tx_bd *tx_buf;
- unsigned long flags;
u64 ts, ns;
u16 cons;
@@ -844,9 +856,7 @@ void bnxt_tx_ts_cmp(struct bnxt *bp, struct bnxt_napi *bnapi,
le32_to_cpu(tscmp->tx_ts_cmp_flags_type),
le32_to_cpu(tscmp->tx_ts_cmp_errors_v));
} else {
- spin_lock_irqsave(&ptp->ptp_lock, flags);
- ns = timecounter_cyc2time(&ptp->tc, ts);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ ns = bnxt_timecounter_cyc2time(ptp, ts);
timestamp.hwtstamp = ns_to_ktime(ns);
skb_tstamp_tx(tx_buf->skb, &timestamp);
}
@@ -955,6 +965,7 @@ static bool bnxt_pps_config_ok(struct bnxt *bp)
static void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ unsigned long flags;
if (!ptp->ptp_clock) {
memset(&ptp->cc, 0, sizeof(ptp->cc));
@@ -971,8 +982,11 @@ static void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc)
}
ptp->next_overflow_check = jiffies + BNXT_PHC_OVERFLOW_PERIOD;
}
- if (init_tc)
+ if (init_tc) {
+ write_seqlock_irqsave(&ptp->ptp_lock, flags);
timecounter_init(&ptp->tc, &ptp->cc, ktime_to_ns(ktime_get_real()));
+ write_sequnlock_irqrestore(&ptp->ptp_lock, flags);
+ }
}
/* Caller holds ptp_lock */
@@ -1005,9 +1019,9 @@ int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg)
if (rc)
return rc;
}
- spin_lock_irqsave(&bp->ptp_cfg->ptp_lock, flags);
+ write_seqlock_irqsave(&bp->ptp_cfg->ptp_lock, flags);
bnxt_ptp_rtc_timecounter_init(bp->ptp_cfg, ns);
- spin_unlock_irqrestore(&bp->ptp_cfg->ptp_lock, flags);
+ write_sequnlock_irqrestore(&bp->ptp_cfg->ptp_lock, flags);
return 0;
}
@@ -1024,7 +1038,7 @@ static void bnxt_ptp_free(struct bnxt *bp)
}
}
-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
+int bnxt_ptp_init(struct bnxt *bp)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
int rc;
@@ -1042,12 +1056,12 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
bnxt_ptp_free(bp);
WRITE_ONCE(ptp->tx_avail, BNXT_MAX_TX_TS);
- spin_lock_init(&ptp->ptp_lock);
+ seqlock_init(&ptp->ptp_lock);
spin_lock_init(&ptp->ptp_tx_lock);
if (BNXT_PTP_USE_RTC(bp)) {
bnxt_ptp_timecounter_init(bp, false);
- rc = bnxt_ptp_init_rtc(bp, phc_cfg);
+ rc = bnxt_ptp_init_rtc(bp, ptp->rtc_configured);
if (rc)
goto out;
} else {
@@ -1075,12 +1089,8 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
atomic64_set(&ptp->stats.ts_err, 0);
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
- unsigned long flags;
-
- spin_lock_irqsave(&ptp->ptp_lock, flags);
bnxt_refclk_read(bp, NULL, &ptp->current_time);
- WRITE_ONCE(ptp->old_time, ptp->current_time);
- spin_unlock_irqrestore(&ptp->ptp_lock, flags);
+ WRITE_ONCE(ptp->old_time, ptp->current_time >> BNXT_HI_TIMER_SHIFT);
ptp_schedule_worker(ptp->ptp_clock, 0);
}
ptp->txts_tmo = BNXT_PTP_DFLT_TX_TMO;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
index f322466ecad3..a95f05e9c579 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
@@ -21,6 +21,7 @@
#define BNXT_DEVCLK_FREQ 1000000
#define BNXT_LO_TIMER_MASK 0x0000ffffffffUL
#define BNXT_HI_TIMER_MASK 0xffff00000000UL
+#define BNXT_HI_TIMER_SHIFT 24
#define BNXT_PTP_DFLT_TX_TMO 1000 /* ms */
#define BNXT_PTP_QTS_TIMEOUT 1000
@@ -102,14 +103,15 @@ struct bnxt_ptp_cfg {
struct timecounter tc;
struct bnxt_pps pps_info;
/* serialize timecounter access */
- spinlock_t ptp_lock;
+ seqlock_t ptp_lock;
/* serialize ts tx request queuing */
spinlock_t ptp_tx_lock;
u64 current_time;
- u64 old_time;
unsigned long next_period;
unsigned long next_overflow_check;
u32 cmult;
+ /* cache of upper 24 bits of cyclecoutner. 8 bits are used to check for roll-over */
+ u32 old_time;
/* a 23b shift cyclecounter will overflow in ~36 mins. Check overflow every 18 mins. */
#define BNXT_PHC_OVERFLOW_PERIOD (18 * 60 * HZ)
@@ -133,6 +135,7 @@ struct bnxt_ptp_cfg {
BNXT_PTP_MSG_PDELAY_REQ | \
BNXT_PTP_MSG_PDELAY_RESP)
u8 tx_tstamp_en:1;
+ u8 rtc_configured:1;
int rx_filter;
u32 tstamp_filters;
@@ -145,20 +148,6 @@ struct bnxt_ptp_cfg {
struct bnxt_ptp_stats stats;
};
-#if BITS_PER_LONG == 32
-#define BNXT_READ_TIME64(ptp, dst, src) \
-do { \
- unsigned long flags; \
- \
- spin_lock_irqsave(&(ptp)->ptp_lock, flags); \
- (dst) = (src); \
- spin_unlock_irqrestore(&(ptp)->ptp_lock, flags); \
-} while (0)
-#else
-#define BNXT_READ_TIME64(ptp, dst, src) \
- ((dst) = READ_ONCE(src))
-#endif
-
#define BNXT_PTP_INC_TX_AVAIL(ptp) \
do { \
spin_lock_bh(&(ptp)->ptp_tx_lock); \
@@ -180,6 +169,29 @@ void bnxt_tx_ts_cmp(struct bnxt *bp, struct bnxt_napi *bnapi,
struct tx_ts_cmp *tscmp);
void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns);
int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg);
-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg);
+int bnxt_ptp_init(struct bnxt *bp);
void bnxt_ptp_clear(struct bnxt *bp);
+static inline u64 bnxt_timecounter_cyc2time(struct bnxt_ptp_cfg *ptp, u64 ts)
+{
+ unsigned int seq;
+ u64 ns;
+
+ do {
+ seq = read_seqbegin(&ptp->ptp_lock);
+ ns = timecounter_cyc2time(&ptp->tc, ts);
+ } while (read_seqretry(&ptp->ptp_lock, seq));
+
+ return ns;
+}
+
+static inline u64 bnxt_extend_cycles_32b_to_48b(struct bnxt_ptp_cfg *ptp, u32 ts)
+{
+ u64 time, cycles;
+
+ time = (u64)READ_ONCE(ptp->old_time) << BNXT_HI_TIMER_SHIFT;
+ cycles = (time & BNXT_HI_TIMER_MASK) | ts;
+ if (ts < (time & BNXT_LO_TIMER_MASK))
+ cycles += BNXT_LO_TIMER_MASK + 1;
+ return cycles;
+}
#endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
index 7bb8a5d74430..12b6ed51fd88 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
@@ -520,6 +520,56 @@ static int __bnxt_set_vf_params(struct bnxt *bp, int vf_id)
return hwrm_req_send(bp, req);
}
+static void bnxt_hwrm_roce_sriov_cfg(struct bnxt *bp, int num_vfs)
+{
+ struct hwrm_func_qcaps_output *resp;
+ struct hwrm_func_cfg_input *cfg_req;
+ struct hwrm_func_qcaps_input *req;
+ int rc;
+
+ rc = hwrm_req_init(bp, req, HWRM_FUNC_QCAPS);
+ if (rc)
+ return;
+
+ req->fid = cpu_to_le16(0xffff);
+ resp = hwrm_req_hold(bp, req);
+ rc = hwrm_req_send(bp, req);
+ if (rc)
+ goto err;
+
+ rc = hwrm_req_init(bp, cfg_req, HWRM_FUNC_CFG);
+ if (rc)
+ goto err;
+
+ cfg_req->fid = cpu_to_le16(0xffff);
+ cfg_req->enables2 =
+ cpu_to_le32(FUNC_CFG_REQ_ENABLES2_ROCE_MAX_AV_PER_VF |
+ FUNC_CFG_REQ_ENABLES2_ROCE_MAX_CQ_PER_VF |
+ FUNC_CFG_REQ_ENABLES2_ROCE_MAX_MRW_PER_VF |
+ FUNC_CFG_REQ_ENABLES2_ROCE_MAX_QP_PER_VF |
+ FUNC_CFG_REQ_ENABLES2_ROCE_MAX_SRQ_PER_VF |
+ FUNC_CFG_REQ_ENABLES2_ROCE_MAX_GID_PER_VF);
+ cfg_req->roce_max_av_per_vf =
+ cpu_to_le32(le32_to_cpu(resp->roce_vf_max_av) / num_vfs);
+ cfg_req->roce_max_cq_per_vf =
+ cpu_to_le32(le32_to_cpu(resp->roce_vf_max_cq) / num_vfs);
+ cfg_req->roce_max_mrw_per_vf =
+ cpu_to_le32(le32_to_cpu(resp->roce_vf_max_mrw) / num_vfs);
+ cfg_req->roce_max_qp_per_vf =
+ cpu_to_le32(le32_to_cpu(resp->roce_vf_max_qp) / num_vfs);
+ cfg_req->roce_max_srq_per_vf =
+ cpu_to_le32(le32_to_cpu(resp->roce_vf_max_srq) / num_vfs);
+ cfg_req->roce_max_gid_per_vf =
+ cpu_to_le32(le32_to_cpu(resp->roce_vf_max_gid) / num_vfs);
+
+ rc = hwrm_req_send(bp, cfg_req);
+
+err:
+ hwrm_req_drop(bp, req);
+ if (rc)
+ netdev_err(bp->dev, "RoCE sriov configuration failed\n");
+}
+
/* Only called by PF to reserve resources for VFs, returns actual number of
* VFs configured, or < 0 on error.
*/
@@ -759,6 +809,9 @@ int bnxt_cfg_hw_sriov(struct bnxt *bp, int *num_vfs, bool reset)
*num_vfs = rc;
}
+ if (BNXT_RDMA_SRIOV_EN(bp) && BNXT_ROCE_VF_RESC_CAP(bp))
+ bnxt_hwrm_roce_sriov_cfg(bp, *num_vfs);
+
return 0;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
index fdd6356f21ef..b771c84cdd89 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
@@ -414,6 +414,8 @@ static void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt *bp)
edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP;
if (bp->flags & BNXT_FLAG_VF)
edev->flags |= BNXT_EN_FLAG_VF;
+ if (BNXT_ROCE_VF_RESC_CAP(bp))
+ edev->flags |= BNXT_EN_FLAG_ROCE_VF_RES_MGMT;
edev->chip_num = bp->chip_num;
edev->hw_ring_stats_size = bp->hw_ring_stats_size;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
index 4f4914f5c84c..5d6aac60f236 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
@@ -64,6 +64,7 @@ struct bnxt_en_dev {
#define BNXT_EN_FLAG_ULP_STOPPED 0x8
#define BNXT_EN_FLAG_VF 0x10
#define BNXT_EN_VF(edev) ((edev)->flags & BNXT_EN_FLAG_VF)
+ #define BNXT_EN_FLAG_ROCE_VF_RES_MGMT 0x20
struct bnxt_ulp *ulp_tbl;
int l2_db_size; /* Doorbell BAR size in
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index f7be886570d8..3e93f957430b 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1144,14 +1144,14 @@ static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
static void bcmgenet_get_strings(struct net_device *dev, u32 stringset,
u8 *data)
{
+ const char *str;
int i;
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < BCMGENET_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- bcmgenet_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ str = bcmgenet_gstrings_stats[i].stat_string;
+ ethtool_puts(&data, str);
}
break;
}
@@ -2405,7 +2405,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
if (ring->dim.use_dim) {
dim_update_sample(ring->dim.event_ctr, ring->dim.packets,
ring->dim.bytes, &dim_sample);
- net_dim(&ring->dim.dim, dim_sample);
+ net_dim(&ring->dim.dim, &dim_sample);
}
return work_done;
@@ -4350,7 +4350,7 @@ MODULE_DEVICE_TABLE(acpi, genet_acpi_match);
static struct platform_driver bcmgenet_driver = {
.probe = bcmgenet_probe,
- .remove_new = bcmgenet_remove,
+ .remove = bcmgenet_remove,
.shutdown = bcmgenet_shutdown,
.driver = {
.name = "bcmgenet",
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index fcf8485f3446..30865fe03eeb 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -2608,7 +2608,7 @@ static void sbmac_remove(struct platform_device *pldev)
static struct platform_driver sbmac_driver = {
.probe = sbmac_probe,
- .remove_new = sbmac_remove,
+ .remove = sbmac_remove,
.driver = {
.name = sbmac_string,
},
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 378815917741..9cc8db10a8d6 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -3737,7 +3737,7 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
}
do {
- u32 *fw_data = (u32 *)(fw_hdr + 1);
+ __be32 *fw_data = (__be32 *)(fw_hdr + 1);
for (i = 0; i < tg3_fw_data_len(tp, fw_hdr); i++)
write_op(tp, cpu_scratch_base +
(be32_to_cpu(fw_hdr->base_addr) & 0xffff) +
@@ -7395,27 +7395,60 @@ tx_recovery:
static void tg3_napi_disable(struct tg3 *tp)
{
+ int txq_idx = tp->txq_cnt - 1;
+ int rxq_idx = tp->rxq_cnt - 1;
+ struct tg3_napi *tnapi;
int i;
- for (i = tp->irq_cnt - 1; i >= 0; i--)
- napi_disable(&tp->napi[i].napi);
+ for (i = tp->irq_cnt - 1; i >= 0; i--) {
+ tnapi = &tp->napi[i];
+ if (tnapi->tx_buffers) {
+ netif_queue_set_napi(tp->dev, txq_idx,
+ NETDEV_QUEUE_TYPE_TX, NULL);
+ txq_idx--;
+ }
+ if (tnapi->rx_rcb) {
+ netif_queue_set_napi(tp->dev, rxq_idx,
+ NETDEV_QUEUE_TYPE_RX, NULL);
+ rxq_idx--;
+ }
+ napi_disable(&tnapi->napi);
+ }
}
static void tg3_napi_enable(struct tg3 *tp)
{
+ int txq_idx = 0, rxq_idx = 0;
+ struct tg3_napi *tnapi;
int i;
- for (i = 0; i < tp->irq_cnt; i++)
- napi_enable(&tp->napi[i].napi);
+ for (i = 0; i < tp->irq_cnt; i++) {
+ tnapi = &tp->napi[i];
+ napi_enable(&tnapi->napi);
+ if (tnapi->tx_buffers) {
+ netif_queue_set_napi(tp->dev, txq_idx,
+ NETDEV_QUEUE_TYPE_TX,
+ &tnapi->napi);
+ txq_idx++;
+ }
+ if (tnapi->rx_rcb) {
+ netif_queue_set_napi(tp->dev, rxq_idx,
+ NETDEV_QUEUE_TYPE_RX,
+ &tnapi->napi);
+ rxq_idx++;
+ }
+ }
}
static void tg3_napi_init(struct tg3 *tp)
{
int i;
- netif_napi_add(tp->dev, &tp->napi[0].napi, tg3_poll);
- for (i = 1; i < tp->irq_cnt; i++)
- netif_napi_add(tp->dev, &tp->napi[i].napi, tg3_poll_msix);
+ for (i = 0; i < tp->irq_cnt; i++) {
+ netif_napi_add(tp->dev, &tp->napi[i].napi,
+ i ? tg3_poll_msix : tg3_poll);
+ netif_napi_set_irq(&tp->napi[i].napi, tp->napi[i].irq_vec);
+ }
}
static void tg3_napi_fini(struct tg3 *tp)
@@ -11309,18 +11342,17 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num)
else {
name = &tnapi->irq_lbl[0];
if (tnapi->tx_buffers && tnapi->rx_rcb)
- snprintf(name, IFNAMSIZ,
+ snprintf(name, sizeof(tnapi->irq_lbl),
"%s-txrx-%d", tp->dev->name, irq_num);
else if (tnapi->tx_buffers)
- snprintf(name, IFNAMSIZ,
+ snprintf(name, sizeof(tnapi->irq_lbl),
"%s-tx-%d", tp->dev->name, irq_num);
else if (tnapi->rx_rcb)
- snprintf(name, IFNAMSIZ,
+ snprintf(name, sizeof(tnapi->irq_lbl),
"%s-rx-%d", tp->dev->name, irq_num);
else
- snprintf(name, IFNAMSIZ,
+ snprintf(name, sizeof(tnapi->irq_lbl),
"%s-%d", tp->dev->name, irq_num);
- name[IFNAMSIZ-1] = 0;
}
if (tg3_flag(tp, USING_MSI) || tg3_flag(tp, USING_MSIX)) {
@@ -13093,12 +13125,16 @@ static int tg3_test_nvram(struct tg3 *tp)
/* Bootstrap checksum at offset 0x10 */
csum = calc_crc((unsigned char *) buf, 0x10);
- if (csum != le32_to_cpu(buf[0x10/4]))
+
+ /* The type of buf is __be32 *, but this value is __le32 */
+ if (csum != le32_to_cpu((__force __le32)buf[0x10 / 4]))
goto out;
/* Manufacturing block starts at offset 0x74, checksum at 0xfc */
- csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88);
- if (csum != le32_to_cpu(buf[0xfc/4]))
+ csum = calc_crc((unsigned char *)&buf[0x74 / 4], 0x88);
+
+ /* The type of buf is __be32 *, but this value is __le32 */
+ if (csum != le32_to_cpu((__force __le32)buf[0xfc / 4]))
goto out;
kfree(buf);
@@ -17065,12 +17101,14 @@ static int tg3_get_device_address(struct tg3 *tp, u8 *addr)
addr_ok = is_valid_ether_addr(addr);
}
if (!addr_ok) {
+ __be32 be_hi, be_lo;
+
/* Next, try NVRAM. */
if (!tg3_flag(tp, NO_NVRAM) &&
- !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) &&
- !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) {
- memcpy(&addr[0], ((char *)&hi) + 2, 2);
- memcpy(&addr[2], (char *)&lo, sizeof(lo));
+ !tg3_nvram_read_be32(tp, mac_offset + 0, &be_hi) &&
+ !tg3_nvram_read_be32(tp, mac_offset + 4, &be_lo)) {
+ memcpy(&addr[0], ((char *)&be_hi) + 2, 2);
+ memcpy(&addr[2], (char *)&be_lo, sizeof(be_lo));
}
/* Finally just fetch it out of the MAC control regs. */
else {
@@ -17801,6 +17839,9 @@ static int tg3_init_one(struct pci_dev *pdev,
} else
persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
+ if (tg3_asic_rev(tp) == ASIC_REV_57766)
+ persist_dma_mask = DMA_BIT_MASK(31);
+
/* Configure DMA attributes. */
if (dma_mask > DMA_BIT_MASK(32)) {
err = dma_set_mask(&pdev->dev, dma_mask);
@@ -18237,7 +18278,7 @@ done:
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot.
- * At this point, the card has exprienced a hard reset,
+ * At this point, the card has experienced a hard reset,
* followed by fixups by BIOS, and has its config space
* set up identically to what it was at cold boot.
*/
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index cf1b2b123c7e..b473f8014d9c 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -3033,7 +3033,7 @@ struct tg3_napi {
dma_addr_t rx_rcb_mapping;
dma_addr_t tx_desc_mapping;
- char irq_lbl[IFNAMSIZ];
+ char irq_lbl[IFNAMSIZ + 6 + 10]; /* name + "-txrx-" + %d */
unsigned int irq_vec;
};
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index 10b1e534030e..4396997c59d0 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -351,7 +351,6 @@ struct bnad {
/* debugfs specific data */
char *regdata;
u32 reglen;
- struct dentry *bnad_dentry_files[5];
struct dentry *port_debugfs_root;
};
diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
index 97291bfbeea5..8f0972e6737c 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
@@ -500,11 +500,6 @@ bnad_debugfs_init(struct bnad *bnad)
if (!bna_debugfs_root) {
bna_debugfs_root = debugfs_create_dir("bna", NULL);
atomic_set(&bna_debugfs_port_count, 0);
- if (!bna_debugfs_root) {
- netdev_warn(bnad->netdev,
- "debugfs root dir creation failed\n");
- return;
- }
}
/* Setup the pci_dev debugfs directory for the port */
@@ -517,18 +512,11 @@ bnad_debugfs_init(struct bnad *bnad)
for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) {
file = &bnad_debugfs_files[i];
- bnad->bnad_dentry_files[i] =
- debugfs_create_file(file->name,
- file->mode,
- bnad->port_debugfs_root,
- bnad,
- file->fops);
- if (!bnad->bnad_dentry_files[i]) {
- netdev_warn(bnad->netdev,
- "create %s entry failed\n",
- file->name);
- return;
- }
+ debugfs_create_file(file->name,
+ file->mode,
+ bnad->port_debugfs_root,
+ bnad,
+ file->fops);
}
}
}
@@ -537,15 +525,6 @@ bnad_debugfs_init(struct bnad *bnad)
void
bnad_debugfs_uninit(struct bnad *bnad)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bnad_debugfs_files); i++) {
- if (bnad->bnad_dentry_files[i]) {
- debugfs_remove(bnad->bnad_dentry_files[i]);
- bnad->bnad_dentry_files[i] = NULL;
- }
- }
-
/* Remove the pci_dev debugfs directory for the port */
if (bnad->port_debugfs_root) {
debugfs_remove(bnad->port_debugfs_root);
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 56901280ba04..daa416fb1724 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -915,20 +915,15 @@ static int macb_mii_probe(struct net_device *dev)
return 0;
}
-static int macb_mdiobus_register(struct macb *bp)
+static int macb_mdiobus_register(struct macb *bp, struct device_node *mdio_np)
{
struct device_node *child, *np = bp->pdev->dev.of_node;
/* If we have a child named mdio, probe it instead of looking for PHYs
* directly under the MAC node
*/
- child = of_get_child_by_name(np, "mdio");
- if (child) {
- int ret = of_mdiobus_register(bp->mii_bus, child);
-
- of_node_put(child);
- return ret;
- }
+ if (mdio_np)
+ return of_mdiobus_register(bp->mii_bus, mdio_np);
/* Only create the PHY from the device tree if at least one PHY is
* described. Otherwise scan the entire MDIO bus. We do this to support
@@ -950,17 +945,15 @@ static int macb_mdiobus_register(struct macb *bp)
static int macb_mii_init(struct macb *bp)
{
- struct device_node *child, *np = bp->pdev->dev.of_node;
+ struct device_node *mdio_np, *np = bp->pdev->dev.of_node;
int err = -ENXIO;
/* With fixed-link, we don't need to register the MDIO bus,
* except if we have a child named "mdio" in the device tree.
* In that case, some devices may be attached to the MACB's MDIO bus.
*/
- child = of_get_child_by_name(np, "mdio");
- if (child)
- of_node_put(child);
- else if (of_phy_is_fixed_link(np))
+ mdio_np = of_get_child_by_name(np, "mdio");
+ if (!mdio_np && of_phy_is_fixed_link(np))
return macb_mii_probe(bp->dev);
/* Enable management port */
@@ -984,7 +977,7 @@ static int macb_mii_init(struct macb *bp)
dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
- err = macb_mdiobus_register(bp);
+ err = macb_mdiobus_register(bp, mdio_np);
if (err)
goto err_out_free_mdiobus;
@@ -999,6 +992,8 @@ err_out_unregister_bus:
err_out_free_mdiobus:
mdiobus_free(bp->mii_bus);
err_out:
+ of_node_put(mdio_np);
+
return err;
}
@@ -4849,10 +4844,11 @@ static const struct macb_config pc302gem_config = {
};
static const struct macb_config sama5d2_config = {
- .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
+ .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_JUMBO,
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
+ .jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
};
@@ -5490,7 +5486,7 @@ static const struct dev_pm_ops macb_pm_ops = {
static struct platform_driver macb_driver = {
.probe = macb_probe,
- .remove_new = macb_remove,
+ .remove = macb_remove,
.driver = {
.name = "macb",
.of_match_table = of_match_ptr(macb_dt_ids),
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index a71b320fd030..331ac6a3dc38 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1919,7 +1919,7 @@ static struct platform_driver xgmac_driver = {
.pm = &xgmac_pm_ops,
},
.probe = xgmac_probe,
- .remove_new = xgmac_remove,
+ .remove = xgmac_remove,
};
module_platform_driver(xgmac_driver);
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c
index 9fd717b9cf69..984f0dd7b62e 100644
--- a/drivers/net/ethernet/cavium/common/cavium_ptp.c
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c
@@ -239,12 +239,11 @@ static int cavium_ptp_probe(struct pci_dev *pdev,
if (err)
goto error_free;
- err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
+ clock->reg_base = pcim_iomap_region(pdev, PCI_PTP_BAR_NO, pci_name(pdev));
+ err = PTR_ERR_OR_ZERO(clock->reg_base);
if (err)
goto error_free;
- clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
-
spin_lock_init(&clock->spin_lock);
cc = &clock->cycle_counter;
@@ -292,7 +291,7 @@ error_stop:
clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
- pcim_iounmap_regions(pdev, 1 << PCI_PTP_BAR_NO);
+ pcim_iounmap_region(pdev, PCI_PTP_BAR_NO);
error_free:
devm_kfree(dev, clock);
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
index b3c81a2e9d46..9ad49aea2673 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
@@ -36,175 +36,6 @@
*/
#define CN23XX_INPUT_JABBER 64600
-void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct)
-{
- int i = 0;
- u32 regval = 0;
- struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
-
- /*In cn23xx_soft_reset*/
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%llx\n",
- "CN23XX_WIN_WR_MASK_REG", CVM_CAST64(CN23XX_WIN_WR_MASK_REG),
- CVM_CAST64(octeon_read_csr64(oct, CN23XX_WIN_WR_MASK_REG)));
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_SLI_SCRATCH1", CVM_CAST64(CN23XX_SLI_SCRATCH1),
- CVM_CAST64(octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1)));
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_RST_SOFT_RST", CN23XX_RST_SOFT_RST,
- lio_pci_readq(oct, CN23XX_RST_SOFT_RST));
-
- /*In cn23xx_set_dpi_regs*/
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_DPI_DMA_CONTROL", CN23XX_DPI_DMA_CONTROL,
- lio_pci_readq(oct, CN23XX_DPI_DMA_CONTROL));
-
- for (i = 0; i < 6; i++) {
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_DPI_DMA_ENG_ENB", i,
- CN23XX_DPI_DMA_ENG_ENB(i),
- lio_pci_readq(oct, CN23XX_DPI_DMA_ENG_ENB(i)));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_DPI_DMA_ENG_BUF", i,
- CN23XX_DPI_DMA_ENG_BUF(i),
- lio_pci_readq(oct, CN23XX_DPI_DMA_ENG_BUF(i)));
- }
-
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n", "CN23XX_DPI_CTL",
- CN23XX_DPI_CTL, lio_pci_readq(oct, CN23XX_DPI_CTL));
-
- /*In cn23xx_setup_pcie_mps and cn23xx_setup_pcie_mrrs */
- pci_read_config_dword(oct->pci_dev, CN23XX_CONFIG_PCIE_DEVCTL, &regval);
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_CONFIG_PCIE_DEVCTL",
- CVM_CAST64(CN23XX_CONFIG_PCIE_DEVCTL), CVM_CAST64(regval));
-
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_DPI_SLI_PRTX_CFG", oct->pcie_port,
- CN23XX_DPI_SLI_PRTX_CFG(oct->pcie_port),
- lio_pci_readq(oct, CN23XX_DPI_SLI_PRTX_CFG(oct->pcie_port)));
-
- /*In cn23xx_specific_regs_setup */
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_S2M_PORTX_CTL", oct->pcie_port,
- CVM_CAST64(CN23XX_SLI_S2M_PORTX_CTL(oct->pcie_port)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_S2M_PORTX_CTL(oct->pcie_port))));
-
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_SLI_RING_RST", CVM_CAST64(CN23XX_SLI_PKT_IOQ_RING_RST),
- (u64)octeon_read_csr64(oct, CN23XX_SLI_PKT_IOQ_RING_RST));
-
- /*In cn23xx_setup_global_mac_regs*/
- for (i = 0; i < CN23XX_MAX_MACS; i++) {
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_PKT_MAC_RINFO64", i,
- CVM_CAST64(CN23XX_SLI_PKT_MAC_RINFO64(i, oct->pf_num)),
- CVM_CAST64(octeon_read_csr64
- (oct, CN23XX_SLI_PKT_MAC_RINFO64
- (i, oct->pf_num))));
- }
-
- /*In cn23xx_setup_global_input_regs*/
- for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_IQ_PKT_CONTROL64", i,
- CVM_CAST64(CN23XX_SLI_IQ_PKT_CONTROL64(i)),
- CVM_CAST64(octeon_read_csr64
- (oct, CN23XX_SLI_IQ_PKT_CONTROL64(i))));
- }
-
- /*In cn23xx_setup_global_output_regs*/
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_WMARK", CVM_CAST64(CN23XX_SLI_OQ_WMARK),
- CVM_CAST64(octeon_read_csr64(oct, CN23XX_SLI_OQ_WMARK)));
-
- for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_PKT_CONTROL", i,
- CVM_CAST64(CN23XX_SLI_OQ_PKT_CONTROL(i)),
- CVM_CAST64(octeon_read_csr(
- oct, CN23XX_SLI_OQ_PKT_CONTROL(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_PKT_INT_LEVELS", i,
- CVM_CAST64(CN23XX_SLI_OQ_PKT_INT_LEVELS(i)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(i))));
- }
-
- /*In cn23xx_enable_interrupt and cn23xx_disable_interrupt*/
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "cn23xx->intr_enb_reg64",
- CVM_CAST64((long)(cn23xx->intr_enb_reg64)),
- CVM_CAST64(readq(cn23xx->intr_enb_reg64)));
-
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "cn23xx->intr_sum_reg64",
- CVM_CAST64((long)(cn23xx->intr_sum_reg64)),
- CVM_CAST64(readq(cn23xx->intr_sum_reg64)));
-
- /*In cn23xx_setup_iq_regs*/
- for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_IQ_BASE_ADDR64", i,
- CVM_CAST64(CN23XX_SLI_IQ_BASE_ADDR64(i)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_IQ_BASE_ADDR64(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_IQ_SIZE", i,
- CVM_CAST64(CN23XX_SLI_IQ_SIZE(i)),
- CVM_CAST64(octeon_read_csr
- (oct, CN23XX_SLI_IQ_SIZE(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_IQ_DOORBELL", i,
- CVM_CAST64(CN23XX_SLI_IQ_DOORBELL(i)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_IQ_DOORBELL(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_IQ_INSTR_COUNT64", i,
- CVM_CAST64(CN23XX_SLI_IQ_INSTR_COUNT64(i)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_IQ_INSTR_COUNT64(i))));
- }
-
- /*In cn23xx_setup_oq_regs*/
- for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_BASE_ADDR64", i,
- CVM_CAST64(CN23XX_SLI_OQ_BASE_ADDR64(i)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_OQ_BASE_ADDR64(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_SIZE", i,
- CVM_CAST64(CN23XX_SLI_OQ_SIZE(i)),
- CVM_CAST64(octeon_read_csr
- (oct, CN23XX_SLI_OQ_SIZE(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_BUFF_INFO_SIZE", i,
- CVM_CAST64(CN23XX_SLI_OQ_BUFF_INFO_SIZE(i)),
- CVM_CAST64(octeon_read_csr(
- oct, CN23XX_SLI_OQ_BUFF_INFO_SIZE(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_PKTS_SENT", i,
- CVM_CAST64(CN23XX_SLI_OQ_PKTS_SENT(i)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_OQ_PKTS_SENT(i))));
- dev_dbg(&oct->pci_dev->dev, "%s(%d)[%llx] : 0x%016llx\n",
- "CN23XX_SLI_OQ_PKTS_CREDIT", i,
- CVM_CAST64(CN23XX_SLI_OQ_PKTS_CREDIT(i)),
- CVM_CAST64(octeon_read_csr64(
- oct, CN23XX_SLI_OQ_PKTS_CREDIT(i))));
- }
-
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_SLI_PKT_TIME_INT",
- CVM_CAST64(CN23XX_SLI_PKT_TIME_INT),
- CVM_CAST64(octeon_read_csr64(oct, CN23XX_SLI_PKT_TIME_INT)));
- dev_dbg(&oct->pci_dev->dev, "%s[%llx] : 0x%016llx\n",
- "CN23XX_SLI_PKT_CNT_INT",
- CVM_CAST64(CN23XX_SLI_PKT_CNT_INT),
- CVM_CAST64(octeon_read_csr64(oct, CN23XX_SLI_PKT_CNT_INT)));
-}
-
static int cn23xx_pf_soft_reset(struct octeon_device *oct)
{
octeon_write_csr64(oct, CN23XX_WIN_WR_MASK_REG, 0xFF);
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
index e6f31d0d5c0b..234b96b4f488 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
@@ -59,8 +59,6 @@ int validate_cn23xx_pf_config_info(struct octeon_device *oct,
u32 cn23xx_pf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us);
-void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct);
-
int cn23xx_sriov_config(struct octeon_device *oct);
int cn23xx_fw_loaded(struct octeon_device *oct);
diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
index 744f2434f7fa..393b9951490a 100644
--- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
@@ -1545,7 +1545,7 @@ static struct platform_driver octeon_mgmt_driver = {
.of_match_table = octeon_mgmt_match,
},
.probe = octeon_mgmt_probe,
- .remove_new = octeon_mgmt_remove,
+ .remove = octeon_mgmt_remove,
};
module_platform_driver(octeon_mgmt_driver);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
index 89256b866840..5a9f6925e1fa 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
@@ -515,23 +515,6 @@ void *cxgb3_free_atid(struct t3cdev *tdev, int atid)
EXPORT_SYMBOL(cxgb3_free_atid);
-/*
- * Free a server TID and return it to the free pool.
- */
-void cxgb3_free_stid(struct t3cdev *tdev, int stid)
-{
- struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
- union listen_entry *p = stid2entry(t, stid);
-
- spin_lock_bh(&t->stid_lock);
- p->next = t->sfree;
- t->sfree = p;
- t->stids_in_use--;
- spin_unlock_bh(&t->stid_lock);
-}
-
-EXPORT_SYMBOL(cxgb3_free_stid);
-
void cxgb3_insert_tid(struct t3cdev *tdev, struct cxgb3_client *client,
void *ctx, unsigned int tid)
{
@@ -671,28 +654,6 @@ int cxgb3_alloc_atid(struct t3cdev *tdev, struct cxgb3_client *client,
EXPORT_SYMBOL(cxgb3_alloc_atid);
-int cxgb3_alloc_stid(struct t3cdev *tdev, struct cxgb3_client *client,
- void *ctx)
-{
- int stid = -1;
- struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
-
- spin_lock_bh(&t->stid_lock);
- if (t->sfree) {
- union listen_entry *p = t->sfree;
-
- stid = (p - t->stid_tab) + t->stid_base;
- t->sfree = p->next;
- p->t3c_tid.ctx = ctx;
- p->t3c_tid.client = client;
- t->stids_in_use++;
- }
- spin_unlock_bh(&t->stid_lock);
- return stid;
-}
-
-EXPORT_SYMBOL(cxgb3_alloc_stid);
-
/* Get the t3cdev associated with a net_device */
struct t3cdev *dev2t3cdev(struct net_device *dev)
{
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h
index 929c298115ca..7419824f9926 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.h
@@ -95,10 +95,7 @@ struct cxgb3_client {
*/
int cxgb3_alloc_atid(struct t3cdev *dev, struct cxgb3_client *client,
void *ctx);
-int cxgb3_alloc_stid(struct t3cdev *dev, struct cxgb3_client *client,
- void *ctx);
void *cxgb3_free_atid(struct t3cdev *dev, int atid);
-void cxgb3_free_stid(struct t3cdev *dev, int stid);
void cxgb3_insert_tid(struct t3cdev *dev, struct cxgb3_client *client,
void *ctx, unsigned int tid);
void cxgb3_queue_tid_release(struct t3cdev *dev, unsigned int tid);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
index 163efab27e9b..5060d3998889 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
@@ -120,7 +120,7 @@ int cxgb4_clip_get(const struct net_device *dev, const u32 *lip, u8 v6)
write_unlock_bh(&ctbl->lock);
dev_err(adap->pdev_dev,
"CLIP FW cmd failed with error %d, "
- "Connections using %pI6c wont be "
+ "Connections using %pI6c won't be "
"offloaded",
ret, ce->addr6.sin6_addr.s6_addr);
return ret;
@@ -133,7 +133,7 @@ int cxgb4_clip_get(const struct net_device *dev, const u32 *lip, u8 v6)
} else {
write_unlock_bh(&ctbl->lock);
dev_info(adap->pdev_dev, "CLIP table overflow, "
- "Connections using %pI6c wont be offloaded",
+ "Connections using %pI6c won't be offloaded",
(void *)lip);
return -ENOMEM;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index bbf7641a0fc7..75bd69ff61a8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -1608,7 +1608,6 @@ void t4_os_portmod_changed(struct adapter *adap, int port_id);
void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
void t4_free_sge_resources(struct adapter *adap);
-void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q);
irq_handler_t t4_intr_handler(struct adapter *adap);
netdev_tx_t t4_start_xmit(struct sk_buff *skb, struct net_device *dev);
int cxgb4_selftest_lb_pkt(struct net_device *netdev);
@@ -2141,28 +2140,6 @@ int cxgb4_free_mac_filt(struct adapter *adap, unsigned int viid,
unsigned int naddr, const u8 **addr, bool sleep_ok);
int cxgb4_init_mps_ref_entries(struct adapter *adap);
void cxgb4_free_mps_ref_entries(struct adapter *adap);
-int cxgb4_alloc_encap_mac_filt(struct adapter *adap, unsigned int viid,
- const u8 *addr, const u8 *mask,
- unsigned int vni, unsigned int vni_mask,
- u8 dip_hit, u8 lookup_type, bool sleep_ok);
-int cxgb4_free_encap_mac_filt(struct adapter *adap, unsigned int viid,
- int idx, bool sleep_ok);
-int cxgb4_free_raw_mac_filt(struct adapter *adap,
- unsigned int viid,
- const u8 *addr,
- const u8 *mask,
- unsigned int idx,
- u8 lookup_type,
- u8 port_id,
- bool sleep_ok);
-int cxgb4_alloc_raw_mac_filt(struct adapter *adap,
- unsigned int viid,
- const u8 *addr,
- const u8 *mask,
- unsigned int idx,
- u8 lookup_type,
- u8 port_id,
- bool sleep_ok);
int cxgb4_update_mac_filt(struct port_info *pi, unsigned int viid,
int *tcam_idx, const u8 *addr,
bool persistent, u8 *smt_idx);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 2418645c8823..97a261d5357e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2188,18 +2188,6 @@ void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
}
EXPORT_SYMBOL(cxgb4_get_tcp_stats);
-void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
- const unsigned int *pgsz_order)
-{
- struct adapter *adap = netdev2adap(dev);
-
- t4_write_reg(adap, ULP_RX_ISCSI_TAGMASK_A, tag_mask);
- t4_write_reg(adap, ULP_RX_ISCSI_PSZ_A, HPZ0_V(pgsz_order[0]) |
- HPZ1_V(pgsz_order[1]) | HPZ2_V(pgsz_order[2]) |
- HPZ3_V(pgsz_order[3]));
-}
-EXPORT_SYMBOL(cxgb4_iscsi_init);
-
int cxgb4_flush_eq_cache(struct net_device *dev)
{
struct adapter *adap = netdev2adap(dev);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c
index a020e8490681..60f4d5b5eb3a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c
@@ -28,28 +28,6 @@ static int cxgb4_mps_ref_dec_by_mac(struct adapter *adap,
return ret;
}
-static int cxgb4_mps_ref_dec(struct adapter *adap, u16 idx)
-{
- struct mps_entries_ref *mps_entry, *tmp;
- int ret = -EINVAL;
-
- spin_lock(&adap->mps_ref_lock);
- list_for_each_entry_safe(mps_entry, tmp, &adap->mps_ref, list) {
- if (mps_entry->idx == idx) {
- if (!refcount_dec_and_test(&mps_entry->refcnt)) {
- spin_unlock(&adap->mps_ref_lock);
- return -EBUSY;
- }
- list_del(&mps_entry->list);
- kfree(mps_entry);
- ret = 0;
- break;
- }
- }
- spin_unlock(&adap->mps_ref_lock);
- return ret;
-}
-
static int cxgb4_mps_ref_inc(struct adapter *adap, const u8 *mac_addr,
u16 idx, const u8 *mask)
{
@@ -141,82 +119,6 @@ int cxgb4_update_mac_filt(struct port_info *pi, unsigned int viid,
return ret;
}
-int cxgb4_free_raw_mac_filt(struct adapter *adap,
- unsigned int viid,
- const u8 *addr,
- const u8 *mask,
- unsigned int idx,
- u8 lookup_type,
- u8 port_id,
- bool sleep_ok)
-{
- int ret = 0;
-
- if (!cxgb4_mps_ref_dec(adap, idx))
- ret = t4_free_raw_mac_filt(adap, viid, addr,
- mask, idx, lookup_type,
- port_id, sleep_ok);
-
- return ret;
-}
-
-int cxgb4_alloc_raw_mac_filt(struct adapter *adap,
- unsigned int viid,
- const u8 *addr,
- const u8 *mask,
- unsigned int idx,
- u8 lookup_type,
- u8 port_id,
- bool sleep_ok)
-{
- int ret;
-
- ret = t4_alloc_raw_mac_filt(adap, viid, addr,
- mask, idx, lookup_type,
- port_id, sleep_ok);
- if (ret < 0)
- return ret;
-
- if (cxgb4_mps_ref_inc(adap, addr, ret, mask)) {
- ret = -ENOMEM;
- t4_free_raw_mac_filt(adap, viid, addr,
- mask, idx, lookup_type,
- port_id, sleep_ok);
- }
-
- return ret;
-}
-
-int cxgb4_free_encap_mac_filt(struct adapter *adap, unsigned int viid,
- int idx, bool sleep_ok)
-{
- int ret = 0;
-
- if (!cxgb4_mps_ref_dec(adap, idx))
- ret = t4_free_encap_mac_filt(adap, viid, idx, sleep_ok);
-
- return ret;
-}
-
-int cxgb4_alloc_encap_mac_filt(struct adapter *adap, unsigned int viid,
- const u8 *addr, const u8 *mask,
- unsigned int vni, unsigned int vni_mask,
- u8 dip_hit, u8 lookup_type, bool sleep_ok)
-{
- int ret;
-
- ret = t4_alloc_encap_mac_filt(adap, viid, addr, mask, vni, vni_mask,
- dip_hit, lookup_type, sleep_ok);
- if (ret < 0)
- return ret;
-
- if (cxgb4_mps_ref_inc(adap, addr, ret, mask)) {
- ret = -ENOMEM;
- t4_free_encap_mac_filt(adap, viid, ret, sleep_ok);
- }
- return ret;
-}
-
int cxgb4_init_mps_ref_entries(struct adapter *adap)
{
spin_lock_init(&adap->mps_ref_lock);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index d8cafaa7ddb4..d7713038386c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -518,8 +518,6 @@ unsigned int cxgb4_best_aligned_mtu(const unsigned short *mtus,
unsigned int *mtu_idxp);
void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
struct tp_tcp_stats *v6);
-void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
- const unsigned int *pgsz_order);
struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
unsigned int skb_len, unsigned int pull_len);
int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index 1e5f5b1a22a6..c02b4e9c06b2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -608,25 +608,6 @@ struct l2t_entry *t4_l2t_alloc_switching(struct adapter *adap, u16 vlan,
return e;
}
-/**
- * cxgb4_l2t_alloc_switching - Allocates an L2T entry for switch filters
- * @dev: net_device pointer
- * @vlan: VLAN Id
- * @port: Associated port
- * @dmac: Destination MAC address to add to L2T
- * Returns pointer to the allocated l2t entry
- *
- * Allocates an L2T entry for use by switching rule of a filter
- */
-struct l2t_entry *cxgb4_l2t_alloc_switching(struct net_device *dev, u16 vlan,
- u8 port, u8 *dmac)
-{
- struct adapter *adap = netdev2adap(dev);
-
- return t4_l2t_alloc_switching(adap, vlan, port, dmac);
-}
-EXPORT_SYMBOL(cxgb4_l2t_alloc_switching);
-
struct l2t_data *t4_init_l2t(unsigned int l2t_start, unsigned int l2t_end)
{
unsigned int l2t_size;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
index 340fecb28a13..8aad7e9dee6d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
@@ -115,8 +115,6 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
unsigned int priority);
u64 cxgb4_select_ntuple(struct net_device *dev,
const struct l2t_entry *l2t);
-struct l2t_entry *cxgb4_l2t_alloc_switching(struct net_device *dev, u16 vlan,
- u8 port, u8 *dmac);
void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
struct l2t_entry *t4_l2t_alloc_switching(struct adapter *adap, u16 vlan,
u8 port, u8 *dmac);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index de52bcb884c4..a7d76a8ed050 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -4874,22 +4874,6 @@ void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
}
}
-/**
- * t4_free_ofld_rxqs - free a block of consecutive Rx queues
- * @adap: the adapter
- * @n: number of queues
- * @q: pointer to first queue
- *
- * Release the resources of a consecutive block of offload Rx queues.
- */
-void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q)
-{
- for ( ; n; n--, q++)
- if (q->rspq.desc)
- free_rspq_fl(adap, &q->rspq,
- q->fl.size ? &q->fl : NULL);
-}
-
void t4_sge_free_ethofld_txq(struct adapter *adap, struct sge_eohw_txq *txq)
{
if (txq->q.desc) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/srq.c b/drivers/net/ethernet/chelsio/cxgb4/srq.c
index 9a54302bb046..a77d6ac1ee8c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/srq.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/srq.c
@@ -51,64 +51,6 @@ struct srq_data *t4_init_srq(int srq_size)
return s;
}
-/* cxgb4_get_srq_entry: read the SRQ table entry
- * @dev: Pointer to the net_device
- * @idx: Index to the srq
- * @entryp: pointer to the srq entry
- *
- * Sends CPL_SRQ_TABLE_REQ message for the given index.
- * Contents will be returned in CPL_SRQ_TABLE_RPL message.
- *
- * Returns zero if the read is successful, else a error
- * number will be returned. Caller should not use the srq
- * entry if the return value is non-zero.
- *
- *
- */
-int cxgb4_get_srq_entry(struct net_device *dev,
- int srq_idx, struct srq_entry *entryp)
-{
- struct cpl_srq_table_req *req;
- struct adapter *adap;
- struct sk_buff *skb;
- struct srq_data *s;
- int rc = -ENODEV;
-
- adap = netdev2adap(dev);
- s = adap->srq;
-
- if (!(adap->flags & CXGB4_FULL_INIT_DONE) || !s)
- goto out;
-
- skb = alloc_skb(sizeof(*req), GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
- req = (struct cpl_srq_table_req *)
- __skb_put_zero(skb, sizeof(*req));
- INIT_TP_WR(req, 0);
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SRQ_TABLE_REQ,
- TID_TID_V(srq_idx) |
- TID_QID_V(adap->sge.fw_evtq.abs_id)));
- req->idx = srq_idx;
-
- mutex_lock(&s->lock);
-
- s->entryp = entryp;
- t4_mgmt_tx(adap, skb);
-
- rc = wait_for_completion_timeout(&s->comp, SRQ_WAIT_TO);
- if (rc)
- rc = 0;
- else /* !rc means we timed out */
- rc = -ETIMEDOUT;
-
- WARN_ON_ONCE(entryp->idx != srq_idx);
- mutex_unlock(&s->lock);
-out:
- return rc;
-}
-EXPORT_SYMBOL(cxgb4_get_srq_entry);
-
void do_srq_table_rpl(struct adapter *adap,
const struct cpl_srq_table_rpl *rpl)
{
diff --git a/drivers/net/ethernet/chelsio/cxgb4/srq.h b/drivers/net/ethernet/chelsio/cxgb4/srq.h
index ec85cf93865a..d9f04bd5ffa3 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/srq.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/srq.h
@@ -58,8 +58,6 @@ struct srq_data {
};
struct srq_data *t4_init_srq(int srq_size);
-int cxgb4_get_srq_entry(struct net_device *dev,
- int srq_idx, struct srq_entry *entryp);
void do_srq_table_rpl(struct adapter *adap,
const struct cpl_srq_table_rpl *rpl);
#endif /* __CXGB4_SRQ_H */
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
index 7ff82b6778ba..21e0dfeff158 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
@@ -573,7 +573,6 @@ int send_tx_flowc_wr(struct sock *sk, int compl,
u32 snd_nxt, u32 rcv_nxt);
void chtls_tcp_push(struct sock *sk, int flags);
int chtls_push_frames(struct chtls_sock *csk, int comp);
-int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val);
void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
u64 mask, u64 val, u8 cookie,
int through_l2t);
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c
index 1e67140b0f80..fab6df21f01c 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c
@@ -106,15 +106,6 @@ void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
send_or_defer(sk, tcp_sk(sk), skb, through_l2t);
}
-/*
- * Set one of the t_flags bits in the TCB.
- */
-int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val)
-{
- return chtls_set_tcb_field(sk, 1, 1ULL << bit_pos,
- (u64)val << bit_pos);
-}
-
static int chtls_set_tcb_keyid(struct sock *sk, int keyid)
{
return chtls_set_tcb_field(sk, 31, 0xFFFFFFFFULL, keyid);
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
index 455a54708be4..96fd31d75dfd 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
@@ -342,8 +342,8 @@ static struct sk_buff *copy_gl_to_skb_pkt(const struct pkt_gl *gl,
{
struct sk_buff *skb;
- /* Allocate space for cpl_pass_accpet_req which will be synthesized by
- * driver. Once driver synthesizes cpl_pass_accpet_req the skb will go
+ /* Allocate space for cpl_pass_accept_req which will be synthesized by
+ * driver. Once driver synthesizes cpl_pass_accept_req the skb will go
* through the regular cpl_pass_accept_req processing in TOM.
*/
skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req)
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index 0a21a10a791c..fa5857923db4 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -1903,7 +1903,7 @@ static struct platform_driver cs89x0_driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(cs89x0_match),
},
- .remove_new = cs89x0_platform_remove,
+ .remove = cs89x0_platform_remove,
};
module_platform_driver_probe(cs89x0_driver, cs89x0_platform_probe);
diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c
index c2007cd86416..a4972457edd9 100644
--- a/drivers/net/ethernet/cirrus/ep93xx_eth.c
+++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c
@@ -862,7 +862,7 @@ MODULE_DEVICE_TABLE(of, ep93xx_eth_of_ids);
static struct platform_driver ep93xx_eth_driver = {
.probe = ep93xx_eth_probe,
- .remove_new = ep93xx_eth_remove,
+ .remove = ep93xx_eth_remove,
.driver = {
.name = "ep93xx-eth",
.of_match_table = ep93xx_eth_of_ids,
diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c
index 84b300fee2bb..6723df9b65d9 100644
--- a/drivers/net/ethernet/cirrus/mac89x0.c
+++ b/drivers/net/ethernet/cirrus/mac89x0.c
@@ -568,7 +568,7 @@ static void mac89x0_device_remove(struct platform_device *pdev)
static struct platform_driver mac89x0_platform_driver = {
.probe = mac89x0_device_probe,
- .remove_new = mac89x0_device_remove,
+ .remove = mac89x0_device_remove,
.driver = {
.name = "mac89x0",
},
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 0cc3644ee855..10b7e02ba4d0 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -23,10 +23,8 @@
#define ENIC_BARS_MAX 6
-#define ENIC_WQ_MAX 8
-#define ENIC_RQ_MAX 8
-#define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX)
-#define ENIC_INTR_MAX (ENIC_CQ_MAX + 2)
+#define ENIC_WQ_MAX 256
+#define ENIC_RQ_MAX 256
#define ENIC_WQ_NAPI_BUDGET 256
@@ -162,6 +160,17 @@ struct enic_rq_stats {
u64 desc_skip; /* Rx pkt went into later buffer */
};
+struct enic_wq {
+ spinlock_t lock; /* spinlock for wq */
+ struct vnic_wq vwq;
+ struct enic_wq_stats stats;
+} ____cacheline_aligned;
+
+struct enic_rq {
+ struct vnic_rq vrq;
+ struct enic_rq_stats stats;
+} ____cacheline_aligned;
+
/* Per-instance private data structure */
struct enic {
struct net_device *netdev;
@@ -173,8 +182,8 @@ struct enic {
struct work_struct reset;
struct work_struct tx_hang_reset;
struct work_struct change_mtu_work;
- struct msix_entry msix_entry[ENIC_INTR_MAX];
- struct enic_msix_entry msix[ENIC_INTR_MAX];
+ struct msix_entry *msix_entry;
+ struct enic_msix_entry *msix;
u32 msg_enable;
spinlock_t devcmd_lock;
u8 mac_addr[ETH_ALEN];
@@ -193,28 +202,25 @@ struct enic {
bool enic_api_busy;
struct enic_port_profile *pp;
- /* work queue cache line section */
- ____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX];
- spinlock_t wq_lock[ENIC_WQ_MAX];
- struct enic_wq_stats wq_stats[ENIC_WQ_MAX];
+ struct enic_wq *wq;
+ unsigned int wq_avail;
unsigned int wq_count;
u16 loop_enable;
u16 loop_tag;
- /* receive queue cache line section */
- ____cacheline_aligned struct vnic_rq rq[ENIC_RQ_MAX];
- struct enic_rq_stats rq_stats[ENIC_RQ_MAX];
+ struct enic_rq *rq;
+ unsigned int rq_avail;
unsigned int rq_count;
struct vxlan_offload vxlan;
- struct napi_struct napi[ENIC_RQ_MAX + ENIC_WQ_MAX];
+ struct napi_struct *napi;
- /* interrupt resource cache line section */
- ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
+ struct vnic_intr *intr;
+ unsigned int intr_avail;
unsigned int intr_count;
u32 __iomem *legacy_pba; /* memory-mapped */
- /* completion queue cache line section */
- ____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX];
+ struct vnic_cq *cq;
+ unsigned int cq_avail;
unsigned int cq_count;
struct enic_rfs_flw_tbl rfs_h;
u32 rx_copybreak;
@@ -272,18 +278,28 @@ static inline unsigned int enic_msix_wq_intr(struct enic *enic,
return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset;
}
-static inline unsigned int enic_msix_err_intr(struct enic *enic)
-{
- return enic->rq_count + enic->wq_count;
-}
+/* MSIX interrupts are organized as the error interrupt, then the notify
+ * interrupt followed by all the I/O interrupts. The error interrupt needs
+ * to fit in 7 bits due to hardware constraints
+ */
+#define ENIC_MSIX_RESERVED_INTR 2
+#define ENIC_MSIX_ERR_INTR 0
+#define ENIC_MSIX_NOTIFY_INTR 1
+#define ENIC_MSIX_IO_INTR_BASE ENIC_MSIX_RESERVED_INTR
+#define ENIC_MSIX_MIN_INTR (ENIC_MSIX_RESERVED_INTR + 2)
#define ENIC_LEGACY_IO_INTR 0
#define ENIC_LEGACY_ERR_INTR 1
#define ENIC_LEGACY_NOTIFY_INTR 2
+static inline unsigned int enic_msix_err_intr(struct enic *enic)
+{
+ return ENIC_MSIX_ERR_INTR;
+}
+
static inline unsigned int enic_msix_notify_intr(struct enic *enic)
{
- return enic->rq_count + enic->wq_count + 1;
+ return ENIC_MSIX_NOTIFY_INTR;
}
static inline bool enic_is_err_intr(struct enic *enic, int intr)
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
index f7986f2b6a17..d607b4f0542c 100644
--- a/drivers/net/ethernet/cisco/enic/enic_ethtool.c
+++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
@@ -337,7 +337,7 @@ static void enic_get_ethtool_stats(struct net_device *netdev,
for (i = 0; i < NUM_ENIC_GEN_STATS; i++)
*(data++) = ((u64 *)&enic->gen_stats)[enic_gen_stats[i].index];
for (i = 0; i < enic->rq_count; i++) {
- struct enic_rq_stats *rqstats = &enic->rq_stats[i];
+ struct enic_rq_stats *rqstats = &enic->rq[i].stats;
int index;
for (j = 0; j < NUM_ENIC_PER_RQ_STATS; j++) {
@@ -346,7 +346,7 @@ static void enic_get_ethtool_stats(struct net_device *netdev,
}
}
for (i = 0; i < enic->wq_count; i++) {
- struct enic_wq_stats *wqstats = &enic->wq_stats[i];
+ struct enic_wq_stats *wqstats = &enic->wq[i].stats;
int index;
for (j = 0; j < NUM_ENIC_PER_WQ_STATS; j++) {
@@ -695,8 +695,8 @@ static void enic_get_channels(struct net_device *netdev,
switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_MSIX:
- channels->max_rx = ENIC_RQ_MAX;
- channels->max_tx = ENIC_WQ_MAX;
+ channels->max_rx = min(enic->rq_avail, ENIC_RQ_MAX);
+ channels->max_tx = min(enic->wq_avail, ENIC_WQ_MAX);
channels->rx_count = enic->rq_count;
channels->tx_count = enic->wq_count;
break;
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index ffed14b63d41..9913952ccb42 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -342,8 +342,8 @@ static void enic_wq_free_buf(struct vnic_wq *wq,
{
struct enic *enic = vnic_dev_priv(wq->vdev);
- enic->wq_stats[wq->index].cq_work++;
- enic->wq_stats[wq->index].cq_bytes += buf->len;
+ enic->wq[wq->index].stats.cq_work++;
+ enic->wq[wq->index].stats.cq_bytes += buf->len;
enic_free_wq_buf(wq, buf);
}
@@ -352,20 +352,20 @@ static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
{
struct enic *enic = vnic_dev_priv(vdev);
- spin_lock(&enic->wq_lock[q_number]);
+ spin_lock(&enic->wq[q_number].lock);
- vnic_wq_service(&enic->wq[q_number], cq_desc,
+ vnic_wq_service(&enic->wq[q_number].vwq, cq_desc,
completed_index, enic_wq_free_buf,
opaque);
if (netif_tx_queue_stopped(netdev_get_tx_queue(enic->netdev, q_number)) &&
- vnic_wq_desc_avail(&enic->wq[q_number]) >=
+ vnic_wq_desc_avail(&enic->wq[q_number].vwq) >=
(MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)) {
netif_wake_subqueue(enic->netdev, q_number);
- enic->wq_stats[q_number].wake++;
+ enic->wq[q_number].stats.wake++;
}
- spin_unlock(&enic->wq_lock[q_number]);
+ spin_unlock(&enic->wq[q_number].lock);
return 0;
}
@@ -377,7 +377,7 @@ static bool enic_log_q_error(struct enic *enic)
bool err = false;
for (i = 0; i < enic->wq_count; i++) {
- error_status = vnic_wq_error_status(&enic->wq[i]);
+ error_status = vnic_wq_error_status(&enic->wq[i].vwq);
err |= error_status;
if (error_status)
netdev_err(enic->netdev, "WQ[%d] error_status %d\n",
@@ -385,7 +385,7 @@ static bool enic_log_q_error(struct enic *enic)
}
for (i = 0; i < enic->rq_count; i++) {
- error_status = vnic_rq_error_status(&enic->rq[i]);
+ error_status = vnic_rq_error_status(&enic->rq[i].vrq);
err |= error_status;
if (error_status)
netdev_err(enic->netdev, "RQ[%d] error_status %d\n",
@@ -598,9 +598,9 @@ static int enic_queue_wq_skb_vlan(struct enic *enic, struct vnic_wq *wq,
err = enic_queue_wq_skb_cont(enic, wq, skb, len_left, loopback);
/* The enic_queue_wq_desc() above does not do HW checksum */
- enic->wq_stats[wq->index].csum_none++;
- enic->wq_stats[wq->index].packets++;
- enic->wq_stats[wq->index].bytes += skb->len;
+ enic->wq[wq->index].stats.csum_none++;
+ enic->wq[wq->index].stats.packets++;
+ enic->wq[wq->index].stats.bytes += skb->len;
return err;
}
@@ -634,9 +634,9 @@ static int enic_queue_wq_skb_csum_l4(struct enic *enic, struct vnic_wq *wq,
if (!eop)
err = enic_queue_wq_skb_cont(enic, wq, skb, len_left, loopback);
- enic->wq_stats[wq->index].csum_partial++;
- enic->wq_stats[wq->index].packets++;
- enic->wq_stats[wq->index].bytes += skb->len;
+ enic->wq[wq->index].stats.csum_partial++;
+ enic->wq[wq->index].stats.packets++;
+ enic->wq[wq->index].stats.bytes += skb->len;
return err;
}
@@ -699,11 +699,11 @@ static int enic_queue_wq_skb_tso(struct enic *enic, struct vnic_wq *wq,
if (skb->encapsulation) {
hdr_len = skb_inner_tcp_all_headers(skb);
enic_preload_tcp_csum_encap(skb);
- enic->wq_stats[wq->index].encap_tso++;
+ enic->wq[wq->index].stats.encap_tso++;
} else {
hdr_len = skb_tcp_all_headers(skb);
enic_preload_tcp_csum(skb);
- enic->wq_stats[wq->index].tso++;
+ enic->wq[wq->index].stats.tso++;
}
/* Queue WQ_ENET_MAX_DESC_LEN length descriptors
@@ -757,8 +757,8 @@ tso_out_stats:
pkts = len / mss;
if ((len % mss) > 0)
pkts++;
- enic->wq_stats[wq->index].packets += pkts;
- enic->wq_stats[wq->index].bytes += (len + (pkts * hdr_len));
+ enic->wq[wq->index].stats.packets += pkts;
+ enic->wq[wq->index].stats.bytes += (len + (pkts * hdr_len));
return 0;
}
@@ -792,9 +792,9 @@ static inline int enic_queue_wq_skb_encap(struct enic *enic, struct vnic_wq *wq,
if (!eop)
err = enic_queue_wq_skb_cont(enic, wq, skb, len_left, loopback);
- enic->wq_stats[wq->index].encap_csum++;
- enic->wq_stats[wq->index].packets++;
- enic->wq_stats[wq->index].bytes += skb->len;
+ enic->wq[wq->index].stats.encap_csum++;
+ enic->wq[wq->index].stats.packets++;
+ enic->wq[wq->index].stats.bytes += skb->len;
return err;
}
@@ -812,7 +812,7 @@ static inline int enic_queue_wq_skb(struct enic *enic,
/* VLAN tag from trunking driver */
vlan_tag_insert = 1;
vlan_tag = skb_vlan_tag_get(skb);
- enic->wq_stats[wq->index].add_vlan++;
+ enic->wq[wq->index].stats.add_vlan++;
} else if (enic->loop_enable) {
vlan_tag = enic->loop_tag;
loopback = 1;
@@ -859,11 +859,11 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
struct netdev_queue *txq;
txq_map = skb_get_queue_mapping(skb) % enic->wq_count;
- wq = &enic->wq[txq_map];
+ wq = &enic->wq[txq_map].vwq;
if (skb->len <= 0) {
dev_kfree_skb_any(skb);
- enic->wq_stats[wq->index].null_pkt++;
+ enic->wq[wq->index].stats.null_pkt++;
return NETDEV_TX_OK;
}
@@ -878,19 +878,19 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
skb_shinfo(skb)->nr_frags + 1 > ENIC_NON_TSO_MAX_DESC &&
skb_linearize(skb)) {
dev_kfree_skb_any(skb);
- enic->wq_stats[wq->index].skb_linear_fail++;
+ enic->wq[wq->index].stats.skb_linear_fail++;
return NETDEV_TX_OK;
}
- spin_lock(&enic->wq_lock[txq_map]);
+ spin_lock(&enic->wq[txq_map].lock);
if (vnic_wq_desc_avail(wq) <
skb_shinfo(skb)->nr_frags + ENIC_DESC_MAX_SPLITS) {
netif_tx_stop_queue(txq);
/* This is a hard error, log it */
netdev_err(netdev, "BUG! Tx ring full when queue awake!\n");
- spin_unlock(&enic->wq_lock[txq_map]);
- enic->wq_stats[wq->index].desc_full_awake++;
+ spin_unlock(&enic->wq[txq_map].lock);
+ enic->wq[wq->index].stats.desc_full_awake++;
return NETDEV_TX_BUSY;
}
@@ -899,14 +899,14 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS) {
netif_tx_stop_queue(txq);
- enic->wq_stats[wq->index].stopped++;
+ enic->wq[wq->index].stats.stopped++;
}
skb_tx_timestamp(skb);
if (!netdev_xmit_more() || netif_xmit_stopped(txq))
vnic_wq_doorbell(wq);
error:
- spin_unlock(&enic->wq_lock[txq_map]);
+ spin_unlock(&enic->wq[txq_map].lock);
return NETDEV_TX_OK;
}
@@ -940,10 +940,10 @@ static void enic_get_stats(struct net_device *netdev,
net_stats->rx_errors = stats->rx.rx_errors;
net_stats->multicast = stats->rx.rx_multicast_frames_ok;
- for (i = 0; i < ENIC_RQ_MAX; i++) {
- struct enic_rq_stats *rqs = &enic->rq_stats[i];
+ for (i = 0; i < enic->rq_count; i++) {
+ struct enic_rq_stats *rqs = &enic->rq[i].stats;
- if (!enic->rq->ctrl)
+ if (!enic->rq[i].vrq.ctrl)
break;
pkt_truncated += rqs->pkt_truncated;
bad_fcs += rqs->bad_fcs;
@@ -1313,7 +1313,7 @@ static int enic_rq_alloc_buf(struct vnic_rq *rq)
}
skb = netdev_alloc_skb_ip_align(netdev, len);
if (!skb) {
- enic->rq_stats[rq->index].no_skb++;
+ enic->rq[rq->index].stats.no_skb++;
return -ENOMEM;
}
@@ -1366,7 +1366,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
struct net_device *netdev = enic->netdev;
struct sk_buff *skb;
struct vnic_cq *cq = &enic->cq[enic_cq_rq(enic, rq->index)];
- struct enic_rq_stats *rqstats = &enic->rq_stats[rq->index];
+ struct enic_rq_stats *rqstats = &enic->rq[rq->index].stats;
u8 type, color, eop, sop, ingress_port, vlan_stripped;
u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof;
@@ -1512,7 +1512,7 @@ static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
{
struct enic *enic = vnic_dev_priv(vdev);
- vnic_rq_service(&enic->rq[q_number], cq_desc,
+ vnic_rq_service(&enic->rq[q_number].vrq, cq_desc,
completed_index, VNIC_RQ_RETURN_DESC,
enic_rq_indicate_buf, opaque);
@@ -1609,7 +1609,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
0 /* don't unmask intr */,
0 /* don't reset intr timer */);
- err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
+ err = vnic_rq_fill(&enic->rq[0].vrq, enic_rq_alloc_buf);
/* Buffer allocation failed. Stay in polling
* mode so we can try to fill the ring again.
@@ -1621,7 +1621,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
/* Call the function which refreshes the intr coalescing timer
* value based on the traffic.
*/
- enic_calc_int_moderation(enic, &enic->rq[0]);
+ enic_calc_int_moderation(enic, &enic->rq[0].vrq);
if ((rq_work_done < budget) && napi_complete_done(napi, rq_work_done)) {
@@ -1630,11 +1630,11 @@ static int enic_poll(struct napi_struct *napi, int budget)
*/
if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
- enic_set_int_moderation(enic, &enic->rq[0]);
+ enic_set_int_moderation(enic, &enic->rq[0].vrq);
vnic_intr_unmask(&enic->intr[intr]);
- enic->rq_stats[0].napi_complete++;
+ enic->rq[0].stats.napi_complete++;
} else {
- enic->rq_stats[0].napi_repoll++;
+ enic->rq[0].stats.napi_repoll++;
}
return rq_work_done;
@@ -1683,7 +1683,7 @@ static int enic_poll_msix_wq(struct napi_struct *napi, int budget)
struct net_device *netdev = napi->dev;
struct enic *enic = netdev_priv(netdev);
unsigned int wq_index = (napi - &enic->napi[0]) - enic->rq_count;
- struct vnic_wq *wq = &enic->wq[wq_index];
+ struct vnic_wq *wq = &enic->wq[wq_index].vwq;
unsigned int cq;
unsigned int intr;
unsigned int wq_work_to_do = ENIC_WQ_NAPI_BUDGET;
@@ -1737,7 +1737,7 @@ static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
0 /* don't unmask intr */,
0 /* don't reset intr timer */);
- err = vnic_rq_fill(&enic->rq[rq], enic_rq_alloc_buf);
+ err = vnic_rq_fill(&enic->rq[rq].vrq, enic_rq_alloc_buf);
/* Buffer allocation failed. Stay in polling mode
* so we can try to fill the ring again.
@@ -1749,7 +1749,7 @@ static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
/* Call the function which refreshes the intr coalescing timer
* value based on the traffic.
*/
- enic_calc_int_moderation(enic, &enic->rq[rq]);
+ enic_calc_int_moderation(enic, &enic->rq[rq].vrq);
if ((work_done < budget) && napi_complete_done(napi, work_done)) {
@@ -1758,11 +1758,11 @@ static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
*/
if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
- enic_set_int_moderation(enic, &enic->rq[rq]);
+ enic_set_int_moderation(enic, &enic->rq[rq].vrq);
vnic_intr_unmask(&enic->intr[intr]);
- enic->rq_stats[rq].napi_complete++;
+ enic->rq[rq].stats.napi_complete++;
} else {
- enic->rq_stats[rq].napi_repoll++;
+ enic->rq[rq].stats.napi_repoll++;
}
return work_done;
@@ -1792,7 +1792,7 @@ static void enic_free_intr(struct enic *enic)
free_irq(enic->pdev->irq, enic);
break;
case VNIC_DEV_INTR_MODE_MSIX:
- for (i = 0; i < ARRAY_SIZE(enic->msix); i++)
+ for (i = 0; i < enic->intr_count; i++)
if (enic->msix[i].requested)
free_irq(enic->msix_entry[i].vector,
enic->msix[i].devid);
@@ -1859,7 +1859,7 @@ static int enic_request_intr(struct enic *enic)
enic->msix[intr].isr = enic_isr_msix_notify;
enic->msix[intr].devid = enic;
- for (i = 0; i < ARRAY_SIZE(enic->msix); i++)
+ for (i = 0; i < enic->intr_count; i++)
enic->msix[i].requested = 0;
for (i = 0; i < enic->intr_count; i++) {
@@ -1989,10 +1989,10 @@ static int enic_open(struct net_device *netdev)
for (i = 0; i < enic->rq_count; i++) {
/* enable rq before updating rq desc */
- vnic_rq_enable(&enic->rq[i]);
- vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf);
+ vnic_rq_enable(&enic->rq[i].vrq);
+ vnic_rq_fill(&enic->rq[i].vrq, enic_rq_alloc_buf);
/* Need at least one buffer on ring to get going */
- if (vnic_rq_desc_used(&enic->rq[i]) == 0) {
+ if (vnic_rq_desc_used(&enic->rq[i].vrq) == 0) {
netdev_err(netdev, "Unable to alloc receive buffers\n");
err = -ENOMEM;
goto err_out_free_rq;
@@ -2000,7 +2000,7 @@ static int enic_open(struct net_device *netdev)
}
for (i = 0; i < enic->wq_count; i++)
- vnic_wq_enable(&enic->wq[i]);
+ vnic_wq_enable(&enic->wq[i].vwq);
if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
enic_dev_add_station_addr(enic);
@@ -2027,9 +2027,9 @@ static int enic_open(struct net_device *netdev)
err_out_free_rq:
for (i = 0; i < enic->rq_count; i++) {
- ret = vnic_rq_disable(&enic->rq[i]);
+ ret = vnic_rq_disable(&enic->rq[i].vrq);
if (!ret)
- vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
+ vnic_rq_clean(&enic->rq[i].vrq, enic_free_rq_buf);
}
enic_dev_notify_unset(enic);
err_out_free_intr:
@@ -2071,12 +2071,12 @@ static int enic_stop(struct net_device *netdev)
enic_dev_del_station_addr(enic);
for (i = 0; i < enic->wq_count; i++) {
- err = vnic_wq_disable(&enic->wq[i]);
+ err = vnic_wq_disable(&enic->wq[i].vwq);
if (err)
return err;
}
for (i = 0; i < enic->rq_count; i++) {
- err = vnic_rq_disable(&enic->rq[i]);
+ err = vnic_rq_disable(&enic->rq[i].vrq);
if (err)
return err;
}
@@ -2086,9 +2086,9 @@ static int enic_stop(struct net_device *netdev)
enic_free_intr(enic);
for (i = 0; i < enic->wq_count; i++)
- vnic_wq_clean(&enic->wq[i], enic_free_wq_buf);
+ vnic_wq_clean(&enic->wq[i].vwq, enic_free_wq_buf);
for (i = 0; i < enic->rq_count; i++)
- vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
+ vnic_rq_clean(&enic->rq[i].vrq, enic_free_rq_buf);
for (i = 0; i < enic->cq_count; i++)
vnic_cq_clean(&enic->cq[i]);
for (i = 0; i < enic->intr_count; i++)
@@ -2442,112 +2442,56 @@ static void enic_tx_hang_reset(struct work_struct *work)
static int enic_set_intr_mode(struct enic *enic)
{
- unsigned int n = min_t(unsigned int, enic->rq_count, ENIC_RQ_MAX);
- unsigned int m = min_t(unsigned int, enic->wq_count, ENIC_WQ_MAX);
unsigned int i;
+ int num_intr;
/* Set interrupt mode (INTx, MSI, MSI-X) depending
* on system capabilities.
*
* Try MSI-X first
- *
- * We need n RQs, m WQs, n+m CQs, and n+m+2 INTRs
- * (the second to last INTR is used for WQ/RQ errors)
- * (the last INTR is used for notifications)
- */
-
- BUG_ON(ARRAY_SIZE(enic->msix_entry) < n + m + 2);
- for (i = 0; i < n + m + 2; i++)
- enic->msix_entry[i].entry = i;
-
- /* Use multiple RQs if RSS is enabled
*/
- if (ENIC_SETTING(enic, RSS) &&
- enic->config.intr_mode < 1 &&
- enic->rq_count >= n &&
- enic->wq_count >= m &&
- enic->cq_count >= n + m &&
- enic->intr_count >= n + m + 2) {
-
- if (pci_enable_msix_range(enic->pdev, enic->msix_entry,
- n + m + 2, n + m + 2) > 0) {
-
- enic->rq_count = n;
- enic->wq_count = m;
- enic->cq_count = n + m;
- enic->intr_count = n + m + 2;
-
- vnic_dev_set_intr_mode(enic->vdev,
- VNIC_DEV_INTR_MODE_MSIX);
-
- return 0;
- }
- }
-
if (enic->config.intr_mode < 1 &&
- enic->rq_count >= 1 &&
- enic->wq_count >= m &&
- enic->cq_count >= 1 + m &&
- enic->intr_count >= 1 + m + 2) {
- if (pci_enable_msix_range(enic->pdev, enic->msix_entry,
- 1 + m + 2, 1 + m + 2) > 0) {
-
- enic->rq_count = 1;
- enic->wq_count = m;
- enic->cq_count = 1 + m;
- enic->intr_count = 1 + m + 2;
-
+ enic->intr_avail >= ENIC_MSIX_MIN_INTR) {
+ for (i = 0; i < enic->intr_avail; i++)
+ enic->msix_entry[i].entry = i;
+
+ num_intr = pci_enable_msix_range(enic->pdev, enic->msix_entry,
+ ENIC_MSIX_MIN_INTR,
+ enic->intr_avail);
+ if (num_intr > 0) {
vnic_dev_set_intr_mode(enic->vdev,
- VNIC_DEV_INTR_MODE_MSIX);
-
+ VNIC_DEV_INTR_MODE_MSIX);
+ enic->intr_avail = num_intr;
return 0;
}
}
/* Next try MSI
*
- * We need 1 RQ, 1 WQ, 2 CQs, and 1 INTR
+ * We need 1 INTR
*/
if (enic->config.intr_mode < 2 &&
- enic->rq_count >= 1 &&
- enic->wq_count >= 1 &&
- enic->cq_count >= 2 &&
- enic->intr_count >= 1 &&
+ enic->intr_avail >= 1 &&
!pci_enable_msi(enic->pdev)) {
-
- enic->rq_count = 1;
- enic->wq_count = 1;
- enic->cq_count = 2;
- enic->intr_count = 1;
-
+ enic->intr_avail = 1;
vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSI);
-
return 0;
}
/* Next try INTx
*
- * We need 1 RQ, 1 WQ, 2 CQs, and 3 INTRs
+ * We need 3 INTRs
* (the first INTR is used for WQ/RQ)
* (the second INTR is used for WQ/RQ errors)
* (the last INTR is used for notifications)
*/
if (enic->config.intr_mode < 3 &&
- enic->rq_count >= 1 &&
- enic->wq_count >= 1 &&
- enic->cq_count >= 2 &&
- enic->intr_count >= 3) {
-
- enic->rq_count = 1;
- enic->wq_count = 1;
- enic->cq_count = 2;
- enic->intr_count = 3;
-
+ enic->intr_avail >= 3) {
+ enic->intr_avail = 3;
vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_INTX);
-
return 0;
}
@@ -2572,11 +2516,81 @@ static void enic_clear_intr_mode(struct enic *enic)
vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);
}
+static int enic_adjust_resources(struct enic *enic)
+{
+ unsigned int max_queues;
+ unsigned int rq_default;
+ unsigned int rq_avail;
+ unsigned int wq_avail;
+
+ if (enic->rq_avail < 1 || enic->wq_avail < 1 || enic->cq_avail < 2) {
+ dev_err(enic_get_dev(enic),
+ "Not enough resources available rq: %d wq: %d cq: %d\n",
+ enic->rq_avail, enic->wq_avail,
+ enic->cq_avail);
+ return -ENOSPC;
+ }
+
+ if (is_kdump_kernel()) {
+ dev_info(enic_get_dev(enic), "Running from within kdump kernel. Using minimal resources\n");
+ enic->rq_avail = 1;
+ enic->wq_avail = 1;
+ enic->config.rq_desc_count = ENIC_MIN_RQ_DESCS;
+ enic->config.wq_desc_count = ENIC_MIN_WQ_DESCS;
+ enic->config.mtu = min_t(u16, 1500, enic->config.mtu);
+ }
+
+ /* if RSS isn't set, then we can only use one RQ */
+ if (!ENIC_SETTING(enic, RSS))
+ enic->rq_avail = 1;
+
+ switch (vnic_dev_get_intr_mode(enic->vdev)) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ case VNIC_DEV_INTR_MODE_MSI:
+ enic->rq_count = 1;
+ enic->wq_count = 1;
+ enic->cq_count = 2;
+ enic->intr_count = enic->intr_avail;
+ break;
+ case VNIC_DEV_INTR_MODE_MSIX:
+ /* Adjust the number of wqs/rqs/cqs/interrupts that will be
+ * used based on which resource is the most constrained
+ */
+ wq_avail = min(enic->wq_avail, ENIC_WQ_MAX);
+ rq_default = netif_get_num_default_rss_queues();
+ rq_avail = min3(enic->rq_avail, ENIC_RQ_MAX, rq_default);
+ max_queues = min(enic->cq_avail,
+ enic->intr_avail - ENIC_MSIX_RESERVED_INTR);
+ if (wq_avail + rq_avail <= max_queues) {
+ enic->rq_count = rq_avail;
+ enic->wq_count = wq_avail;
+ } else {
+ /* recalculate wq/rq count */
+ if (rq_avail < wq_avail) {
+ enic->rq_count = min(rq_avail, max_queues / 2);
+ enic->wq_count = max_queues - enic->rq_count;
+ } else {
+ enic->wq_count = min(wq_avail, max_queues / 2);
+ enic->rq_count = max_queues - enic->wq_count;
+ }
+ }
+ enic->cq_count = enic->rq_count + enic->wq_count;
+ enic->intr_count = enic->cq_count + ENIC_MSIX_RESERVED_INTR;
+
+ break;
+ default:
+ dev_err(enic_get_dev(enic), "Unknown interrupt mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static void enic_get_queue_stats_rx(struct net_device *dev, int idx,
struct netdev_queue_stats_rx *rxs)
{
struct enic *enic = netdev_priv(dev);
- struct enic_rq_stats *rqstats = &enic->rq_stats[idx];
+ struct enic_rq_stats *rqstats = &enic->rq[idx].stats;
rxs->bytes = rqstats->bytes;
rxs->packets = rqstats->packets;
@@ -2590,7 +2604,7 @@ static void enic_get_queue_stats_tx(struct net_device *dev, int idx,
struct netdev_queue_stats_tx *txs)
{
struct enic *enic = netdev_priv(dev);
- struct enic_wq_stats *wqstats = &enic->wq_stats[idx];
+ struct enic_wq_stats *wqstats = &enic->wq[idx].stats;
txs->bytes = wqstats->bytes;
txs->packets = wqstats->packets;
@@ -2674,6 +2688,71 @@ static const struct netdev_stat_ops enic_netdev_stat_ops = {
.get_base_stats = enic_get_base_stats,
};
+static void enic_free_enic_resources(struct enic *enic)
+{
+ kfree(enic->wq);
+ enic->wq = NULL;
+
+ kfree(enic->rq);
+ enic->rq = NULL;
+
+ kfree(enic->cq);
+ enic->cq = NULL;
+
+ kfree(enic->napi);
+ enic->napi = NULL;
+
+ kfree(enic->msix_entry);
+ enic->msix_entry = NULL;
+
+ kfree(enic->msix);
+ enic->msix = NULL;
+
+ kfree(enic->intr);
+ enic->intr = NULL;
+}
+
+static int enic_alloc_enic_resources(struct enic *enic)
+{
+ enic->wq = kcalloc(enic->wq_avail, sizeof(struct enic_wq), GFP_KERNEL);
+ if (!enic->wq)
+ goto free_queues;
+
+ enic->rq = kcalloc(enic->rq_avail, sizeof(struct enic_rq), GFP_KERNEL);
+ if (!enic->rq)
+ goto free_queues;
+
+ enic->cq = kcalloc(enic->cq_avail, sizeof(struct vnic_cq), GFP_KERNEL);
+ if (!enic->cq)
+ goto free_queues;
+
+ enic->napi = kcalloc(enic->wq_avail + enic->rq_avail,
+ sizeof(struct napi_struct), GFP_KERNEL);
+ if (!enic->napi)
+ goto free_queues;
+
+ enic->msix_entry = kcalloc(enic->intr_avail, sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (!enic->msix_entry)
+ goto free_queues;
+
+ enic->msix = kcalloc(enic->intr_avail, sizeof(struct enic_msix_entry),
+ GFP_KERNEL);
+ if (!enic->msix)
+ goto free_queues;
+
+ enic->intr = kcalloc(enic->intr_avail, sizeof(struct vnic_intr),
+ GFP_KERNEL);
+ if (!enic->intr)
+ goto free_queues;
+
+ return 0;
+
+free_queues:
+ enic_free_enic_resources(enic);
+ return -ENOMEM;
+}
+
static void enic_dev_deinit(struct enic *enic)
{
unsigned int i;
@@ -2691,18 +2770,7 @@ static void enic_dev_deinit(struct enic *enic)
enic_free_vnic_resources(enic);
enic_clear_intr_mode(enic);
enic_free_affinity_hint(enic);
-}
-
-static void enic_kdump_kernel_config(struct enic *enic)
-{
- if (is_kdump_kernel()) {
- dev_info(enic_get_dev(enic), "Running from within kdump kernel. Using minimal resources\n");
- enic->rq_count = 1;
- enic->wq_count = 1;
- enic->config.rq_desc_count = ENIC_MIN_RQ_DESCS;
- enic->config.wq_desc_count = ENIC_MIN_WQ_DESCS;
- enic->config.mtu = min_t(u16, 1500, enic->config.mtu);
- }
+ enic_free_enic_resources(enic);
}
static int enic_dev_init(struct enic *enic)
@@ -2734,19 +2802,26 @@ static int enic_dev_init(struct enic *enic)
enic_get_res_counts(enic);
- /* modify resource count if we are in kdump_kernel
- */
- enic_kdump_kernel_config(enic);
+ err = enic_alloc_enic_resources(enic);
+ if (err) {
+ dev_err(dev, "Failed to allocate enic resources\n");
+ return err;
+ }
- /* Set interrupt mode based on resource counts and system
- * capabilities
- */
+ /* Set interrupt mode based on system capabilities */
err = enic_set_intr_mode(enic);
if (err) {
dev_err(dev, "Failed to set intr mode based on resource "
"counts and system capabilities, aborting\n");
- return err;
+ goto err_out_free_vnic_resources;
+ }
+
+ /* Adjust resource counts based on most constrained resources */
+ err = enic_adjust_resources(enic);
+ if (err) {
+ dev_err(dev, "Failed to adjust resources\n");
+ goto err_out_free_vnic_resources;
}
/* Allocate and configure vNIC resources
@@ -2788,6 +2863,7 @@ err_out_free_vnic_resources:
enic_free_affinity_hint(enic);
enic_clear_intr_mode(enic);
enic_free_vnic_resources(enic);
+ enic_free_enic_resources(enic);
return err;
}
@@ -2993,7 +3069,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
for (i = 0; i < enic->wq_count; i++)
- spin_lock_init(&enic->wq_lock[i]);
+ spin_lock_init(&enic->wq[i].lock);
/* Register net device
*/
diff --git a/drivers/net/ethernet/cisco/enic/enic_res.c b/drivers/net/ethernet/cisco/enic/enic_res.c
index 1c48aebdbab0..126125199833 100644
--- a/drivers/net/ethernet/cisco/enic/enic_res.c
+++ b/drivers/net/ethernet/cisco/enic/enic_res.c
@@ -176,9 +176,9 @@ void enic_free_vnic_resources(struct enic *enic)
unsigned int i;
for (i = 0; i < enic->wq_count; i++)
- vnic_wq_free(&enic->wq[i]);
+ vnic_wq_free(&enic->wq[i].vwq);
for (i = 0; i < enic->rq_count; i++)
- vnic_rq_free(&enic->rq[i]);
+ vnic_rq_free(&enic->rq[i].vrq);
for (i = 0; i < enic->cq_count; i++)
vnic_cq_free(&enic->cq[i]);
for (i = 0; i < enic->intr_count; i++)
@@ -187,16 +187,21 @@ void enic_free_vnic_resources(struct enic *enic)
void enic_get_res_counts(struct enic *enic)
{
- enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
- enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
- enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
- enic->intr_count = vnic_dev_get_res_count(enic->vdev,
- RES_TYPE_INTR_CTRL);
+ enic->wq_avail = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
+ enic->rq_avail = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
+ enic->cq_avail = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
+ enic->intr_avail = vnic_dev_get_res_count(enic->vdev,
+ RES_TYPE_INTR_CTRL);
+
+ enic->wq_count = enic->wq_avail;
+ enic->rq_count = enic->rq_avail;
+ enic->cq_count = enic->cq_avail;
+ enic->intr_count = enic->intr_avail;
dev_info(enic_get_dev(enic),
"vNIC resources avail: wq %d rq %d cq %d intr %d\n",
- enic->wq_count, enic->rq_count,
- enic->cq_count, enic->intr_count);
+ enic->wq_avail, enic->rq_avail,
+ enic->cq_avail, enic->intr_avail);
}
void enic_init_vnic_resources(struct enic *enic)
@@ -221,9 +226,12 @@ void enic_init_vnic_resources(struct enic *enic)
switch (intr_mode) {
case VNIC_DEV_INTR_MODE_INTX:
+ error_interrupt_enable = 1;
+ error_interrupt_offset = ENIC_LEGACY_ERR_INTR;
+ break;
case VNIC_DEV_INTR_MODE_MSIX:
error_interrupt_enable = 1;
- error_interrupt_offset = enic->intr_count - 2;
+ error_interrupt_offset = enic_msix_err_intr(enic);
break;
default:
error_interrupt_enable = 0;
@@ -233,7 +241,7 @@ void enic_init_vnic_resources(struct enic *enic)
for (i = 0; i < enic->rq_count; i++) {
cq_index = i;
- vnic_rq_init(&enic->rq[i],
+ vnic_rq_init(&enic->rq[i].vrq,
cq_index,
error_interrupt_enable,
error_interrupt_offset);
@@ -241,7 +249,7 @@ void enic_init_vnic_resources(struct enic *enic)
for (i = 0; i < enic->wq_count; i++) {
cq_index = enic->rq_count + i;
- vnic_wq_init(&enic->wq[i],
+ vnic_wq_init(&enic->wq[i].vwq,
cq_index,
error_interrupt_enable,
error_interrupt_offset);
@@ -249,15 +257,15 @@ void enic_init_vnic_resources(struct enic *enic)
/* Init CQ resources
*
- * CQ[0 - n+m-1] point to INTR[0] for INTx, MSI
- * CQ[0 - n+m-1] point to INTR[0 - n+m-1] for MSI-X
+ * All CQs point to INTR[0] for INTx, MSI
+ * CQ[i] point to INTR[ENIC_MSIX_IO_INTR_BASE + i] for MSI-X
*/
for (i = 0; i < enic->cq_count; i++) {
switch (intr_mode) {
case VNIC_DEV_INTR_MODE_MSIX:
- interrupt_offset = i;
+ interrupt_offset = ENIC_MSIX_IO_INTR_BASE + i;
break;
default:
interrupt_offset = 0;
@@ -322,7 +330,7 @@ int enic_alloc_vnic_resources(struct enic *enic)
*/
for (i = 0; i < enic->wq_count; i++) {
- err = vnic_wq_alloc(enic->vdev, &enic->wq[i], i,
+ err = vnic_wq_alloc(enic->vdev, &enic->wq[i].vwq, i,
enic->config.wq_desc_count,
sizeof(struct wq_enet_desc));
if (err)
@@ -330,7 +338,7 @@ int enic_alloc_vnic_resources(struct enic *enic)
}
for (i = 0; i < enic->rq_count; i++) {
- err = vnic_rq_alloc(enic->vdev, &enic->rq[i], i,
+ err = vnic_rq_alloc(enic->vdev, &enic->rq[i].vrq, i,
enic->config.rq_desc_count,
sizeof(struct rq_enet_desc));
if (err)
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 73e1c71c5092..991e3839858b 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2573,7 +2573,7 @@ static struct platform_driver gemini_ethernet_port_driver = {
.of_match_table = gemini_ethernet_port_of_match,
},
.probe = gemini_ethernet_port_probe,
- .remove_new = gemini_ethernet_port_remove,
+ .remove = gemini_ethernet_port_remove,
};
static int gemini_ethernet_probe(struct platform_device *pdev)
@@ -2637,7 +2637,7 @@ static struct platform_driver gemini_ethernet_driver = {
.of_match_table = gemini_ethernet_of_match,
},
.probe = gemini_ethernet_probe,
- .remove_new = gemini_ethernet_remove,
+ .remove = gemini_ethernet_remove,
};
static int __init gemini_ethernet_module_init(void)
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 150cc94ae9f8..8735e333034c 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1799,7 +1799,7 @@ static struct platform_driver dm9000_driver = {
.of_match_table = of_match_ptr(dm9000_of_matches),
},
.probe = dm9000_probe,
- .remove_new = dm9000_drv_remove,
+ .remove = dm9000_drv_remove,
};
module_platform_driver(dm9000_driver);
diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig
index 0d77f84c8e7b..e9e13654812c 100644
--- a/drivers/net/ethernet/dlink/Kconfig
+++ b/drivers/net/ethernet/dlink/Kconfig
@@ -32,24 +32,4 @@ config DL2K
To compile this driver as a module, choose M here: the
module will be called dl2k.
-config SUNDANCE
- tristate "Sundance Alta support"
- depends on PCI
- select CRC32
- select MII
- help
- This driver is for the Sundance "Alta" chip.
- More specific information and updates are available from
- <http://www.scyld.com/network/sundance.html>.
-
-config SUNDANCE_MMIO
- bool "Use MMIO instead of PIO"
- depends on SUNDANCE
- help
- Enable memory-mapped I/O for interaction with Sundance NIC registers.
- Do NOT enable this by default, PIO (enabled when MMIO is disabled)
- is known to solve bugs on certain chips.
-
- If unsure, say N.
-
endif # NET_VENDOR_DLINK
diff --git a/drivers/net/ethernet/dlink/Makefile b/drivers/net/ethernet/dlink/Makefile
index 3ff503c747db..38c236eb6007 100644
--- a/drivers/net/ethernet/dlink/Makefile
+++ b/drivers/net/ethernet/dlink/Makefile
@@ -4,4 +4,3 @@
#
obj-$(CONFIG_DL2K) += dl2k.o
-obj-$(CONFIG_SUNDANCE) += sundance.o
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
deleted file mode 100644
index 8af5ecec7d61..000000000000
--- a/drivers/net/ethernet/dlink/sundance.c
+++ /dev/null
@@ -1,1985 +0,0 @@
-/* sundance.c: A Linux device driver for the Sundance ST201 "Alta". */
-/*
- Written 1999-2000 by Donald Becker.
-
- This software may be used and distributed according to the terms of
- the GNU General Public License (GPL), incorporated herein by reference.
- Drivers based on or derived from this code fall under the GPL and must
- retain the authorship, copyright and license notice. This file is not
- a complete program and may only be used when the entire operating
- system is licensed under the GPL.
-
- The author may be reached as becker@scyld.com, or C/O
- Scyld Computing Corporation
- 410 Severn Ave., Suite 210
- Annapolis MD 21403
-
- Support and updates available at
- http://www.scyld.com/network/sundance.html
- [link no longer provides useful info -jgarzik]
- Archives of the mailing list are still available at
- https://www.beowulf.org/pipermail/netdrivers/
-
-*/
-
-#define DRV_NAME "sundance"
-
-/* The user-configurable values.
- These may be modified when a driver module is loaded.*/
-static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
-/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
- Typical is a 64 element hash table based on the Ethernet CRC. */
-static const int multicast_filter_limit = 32;
-
-/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
- Setting to > 1518 effectively disables this feature.
- This chip can receive into offset buffers, so the Alpha does not
- need a copy-align. */
-static int rx_copybreak;
-static int flowctrl=1;
-
-/* media[] specifies the media type the NIC operates at.
- autosense Autosensing active media.
- 10mbps_hd 10Mbps half duplex.
- 10mbps_fd 10Mbps full duplex.
- 100mbps_hd 100Mbps half duplex.
- 100mbps_fd 100Mbps full duplex.
- 0 Autosensing active media.
- 1 10Mbps half duplex.
- 2 10Mbps full duplex.
- 3 100Mbps half duplex.
- 4 100Mbps full duplex.
-*/
-#define MAX_UNITS 8
-static char *media[MAX_UNITS];
-
-
-/* Operational parameters that are set at compile time. */
-
-/* Keep the ring sizes a power of two for compile efficiency.
- The compiler will convert <unsigned>'%'<2^N> into a bit mask.
- Making the Tx ring too large decreases the effectiveness of channel
- bonding and packet priority, and more than 128 requires modifying the
- Tx error recovery.
- Large receive rings merely waste memory. */
-#define TX_RING_SIZE 32
-#define TX_QUEUE_LEN (TX_RING_SIZE - 1) /* Limit ring entries actually used. */
-#define RX_RING_SIZE 64
-#define RX_BUDGET 32
-#define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct netdev_desc)
-#define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct netdev_desc)
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (4*HZ)
-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/uaccess.h>
-#include <asm/processor.h> /* Processor type for cache alignment. */
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/dma-mapping.h>
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("Sundance Alta Ethernet driver");
-MODULE_LICENSE("GPL");
-
-module_param(debug, int, 0);
-module_param(rx_copybreak, int, 0);
-module_param_array(media, charp, NULL, 0);
-module_param(flowctrl, int, 0);
-MODULE_PARM_DESC(debug, "Sundance Alta debug level (0-5)");
-MODULE_PARM_DESC(rx_copybreak, "Sundance Alta copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(flowctrl, "Sundance Alta flow control [0|1]");
-
-/*
- Theory of Operation
-
-I. Board Compatibility
-
-This driver is designed for the Sundance Technologies "Alta" ST201 chip.
-
-II. Board-specific settings
-
-III. Driver operation
-
-IIIa. Ring buffers
-
-This driver uses two statically allocated fixed-size descriptor lists
-formed into rings by a branch from the final descriptor to the beginning of
-the list. The ring sizes are set at compile time by RX/TX_RING_SIZE.
-Some chips explicitly use only 2^N sized rings, while others use a
-'next descriptor' pointer that the driver forms into rings.
-
-IIIb/c. Transmit/Receive Structure
-
-This driver uses a zero-copy receive and transmit scheme.
-The driver allocates full frame size skbuffs for the Rx ring buffers at
-open() time and passes the skb->data field to the chip as receive data
-buffers. When an incoming frame is less than RX_COPYBREAK bytes long,
-a fresh skbuff is allocated and the frame is copied to the new skbuff.
-When the incoming frame is larger, the skbuff is passed directly up the
-protocol stack. Buffers consumed this way are replaced by newly allocated
-skbuffs in a later phase of receives.
-
-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
-using a full-sized skbuff for small frames vs. the copying costs of larger
-frames. New boards are typically used in generously configured machines
-and the underfilled buffers have negligible impact compared to the benefit of
-a single allocation size, so the default value of zero results in never
-copying packets. When copying is done, the cost is usually mitigated by using
-a combined copy/checksum routine. Copying also preloads the cache, which is
-most useful with small frames.
-
-A subtle aspect of the operation is that the IP header at offset 14 in an
-ethernet frame isn't longword aligned for further processing.
-Unaligned buffers are permitted by the Sundance hardware, so
-frames are received into the skbuff at an offset of "+2", 16-byte aligning
-the IP header.
-
-IIId. Synchronization
-
-The driver runs as two independent, single-threaded flows of control. One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag. The other thread is the interrupt handler, which is single
-threaded by the hardware and interrupt handling software.
-
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'lp->tx_full' flag.
-
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring. After reaping the stats, it marks the Tx queue entry as
-empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it
-clears both the tx_full and tbusy flags.
-
-IV. Notes
-
-IVb. References
-
-The Sundance ST201 datasheet, preliminary version.
-The Kendin KS8723 datasheet, preliminary version.
-The ICplus IP100 datasheet, preliminary version.
-http://www.scyld.com/expert/100mbps.html
-http://www.scyld.com/expert/NWay.html
-
-IVc. Errata
-
-*/
-
-/* Work-around for Kendin chip bugs. */
-#ifndef CONFIG_SUNDANCE_MMIO
-#define USE_IO_OPS 1
-#endif
-
-static const struct pci_device_id sundance_pci_tbl[] = {
- { 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 },
- { 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 },
- { 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 },
- { 0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3 },
- { 0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
- { 0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
- { 0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
- { }
-};
-MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
-
-enum {
- netdev_io_size = 128
-};
-
-struct pci_id_info {
- const char *name;
-};
-static const struct pci_id_info pci_id_tbl[] = {
- {"D-Link DFE-550TX FAST Ethernet Adapter"},
- {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
- {"D-Link DFE-580TX 4 port Server Adapter"},
- {"D-Link DFE-530TXS FAST Ethernet Adapter"},
- {"D-Link DL10050-based FAST Ethernet Adapter"},
- {"Sundance Technology Alta"},
- {"IC Plus Corporation IP100A FAST Ethernet Adapter"},
- { } /* terminate list. */
-};
-
-/* This driver was written to use PCI memory space, however x86-oriented
- hardware often uses I/O space accesses. */
-
-/* Offsets to the device registers.
- Unlike software-only systems, device drivers interact with complex hardware.
- It's not useful to define symbolic names for every register bit in the
- device. The name can only partially document the semantics and make
- the driver longer and more difficult to read.
- In general, only the important configuration values or bits changed
- multiple times should be defined symbolically.
-*/
-enum alta_offsets {
- DMACtrl = 0x00,
- TxListPtr = 0x04,
- TxDMABurstThresh = 0x08,
- TxDMAUrgentThresh = 0x09,
- TxDMAPollPeriod = 0x0a,
- RxDMAStatus = 0x0c,
- RxListPtr = 0x10,
- DebugCtrl0 = 0x1a,
- DebugCtrl1 = 0x1c,
- RxDMABurstThresh = 0x14,
- RxDMAUrgentThresh = 0x15,
- RxDMAPollPeriod = 0x16,
- LEDCtrl = 0x1a,
- ASICCtrl = 0x30,
- EEData = 0x34,
- EECtrl = 0x36,
- FlashAddr = 0x40,
- FlashData = 0x44,
- WakeEvent = 0x45,
- TxStatus = 0x46,
- TxFrameId = 0x47,
- DownCounter = 0x18,
- IntrClear = 0x4a,
- IntrEnable = 0x4c,
- IntrStatus = 0x4e,
- MACCtrl0 = 0x50,
- MACCtrl1 = 0x52,
- StationAddr = 0x54,
- MaxFrameSize = 0x5A,
- RxMode = 0x5c,
- MIICtrl = 0x5e,
- MulticastFilter0 = 0x60,
- MulticastFilter1 = 0x64,
- RxOctetsLow = 0x68,
- RxOctetsHigh = 0x6a,
- TxOctetsLow = 0x6c,
- TxOctetsHigh = 0x6e,
- TxFramesOK = 0x70,
- RxFramesOK = 0x72,
- StatsCarrierError = 0x74,
- StatsLateColl = 0x75,
- StatsMultiColl = 0x76,
- StatsOneColl = 0x77,
- StatsTxDefer = 0x78,
- RxMissed = 0x79,
- StatsTxXSDefer = 0x7a,
- StatsTxAbort = 0x7b,
- StatsBcastTx = 0x7c,
- StatsBcastRx = 0x7d,
- StatsMcastTx = 0x7e,
- StatsMcastRx = 0x7f,
- /* Aliased and bogus values! */
- RxStatus = 0x0c,
-};
-
-#define ASIC_HI_WORD(x) ((x) + 2)
-
-enum ASICCtrl_HiWord_bit {
- GlobalReset = 0x0001,
- RxReset = 0x0002,
- TxReset = 0x0004,
- DMAReset = 0x0008,
- FIFOReset = 0x0010,
- NetworkReset = 0x0020,
- HostReset = 0x0040,
- ResetBusy = 0x0400,
-};
-
-/* Bits in the interrupt status/mask registers. */
-enum intr_status_bits {
- IntrSummary=0x0001, IntrPCIErr=0x0002, IntrMACCtrl=0x0008,
- IntrTxDone=0x0004, IntrRxDone=0x0010, IntrRxStart=0x0020,
- IntrDrvRqst=0x0040,
- StatsMax=0x0080, LinkChange=0x0100,
- IntrTxDMADone=0x0200, IntrRxDMADone=0x0400,
-};
-
-/* Bits in the RxMode register. */
-enum rx_mode_bits {
- AcceptAllIPMulti=0x20, AcceptMultiHash=0x10, AcceptAll=0x08,
- AcceptBroadcast=0x04, AcceptMulticast=0x02, AcceptMyPhys=0x01,
-};
-/* Bits in MACCtrl. */
-enum mac_ctrl0_bits {
- EnbFullDuplex=0x20, EnbRcvLargeFrame=0x40,
- EnbFlowCtrl=0x100, EnbPassRxCRC=0x200,
-};
-enum mac_ctrl1_bits {
- StatsEnable=0x0020, StatsDisable=0x0040, StatsEnabled=0x0080,
- TxEnable=0x0100, TxDisable=0x0200, TxEnabled=0x0400,
- RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000,
-};
-
-/* Bits in WakeEvent register. */
-enum wake_event_bits {
- WakePktEnable = 0x01,
- MagicPktEnable = 0x02,
- LinkEventEnable = 0x04,
- WolEnable = 0x80,
-};
-
-/* The Rx and Tx buffer descriptors. */
-/* Note that using only 32 bit fields simplifies conversion to big-endian
- architectures. */
-struct netdev_desc {
- __le32 next_desc;
- __le32 status;
- struct desc_frag { __le32 addr, length; } frag;
-};
-
-/* Bits in netdev_desc.status */
-enum desc_status_bits {
- DescOwn=0x8000,
- DescEndPacket=0x4000,
- DescEndRing=0x2000,
- LastFrag=0x80000000,
- DescIntrOnTx=0x8000,
- DescIntrOnDMADone=0x80000000,
- DisableAlign = 0x00000001,
-};
-
-#define PRIV_ALIGN 15 /* Required alignment mask */
-/* Use __attribute__((aligned (L1_CACHE_BYTES))) to maintain alignment
- within the structure. */
-#define MII_CNT 4
-struct netdev_private {
- /* Descriptor rings first for alignment. */
- struct netdev_desc *rx_ring;
- struct netdev_desc *tx_ring;
- struct sk_buff* rx_skbuff[RX_RING_SIZE];
- struct sk_buff* tx_skbuff[TX_RING_SIZE];
- dma_addr_t tx_ring_dma;
- dma_addr_t rx_ring_dma;
- struct timer_list timer; /* Media monitoring timer. */
- struct net_device *ndev; /* backpointer */
- /* ethtool extra stats */
- struct {
- u64 tx_multiple_collisions;
- u64 tx_single_collisions;
- u64 tx_late_collisions;
- u64 tx_deferred;
- u64 tx_deferred_excessive;
- u64 tx_aborted;
- u64 tx_bcasts;
- u64 rx_bcasts;
- u64 tx_mcasts;
- u64 rx_mcasts;
- } xstats;
- /* Frequently used values: keep some adjacent for cache effect. */
- spinlock_t lock;
- int msg_enable;
- int chip_id;
- unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
- unsigned int rx_buf_sz; /* Based on MTU+slack. */
- struct netdev_desc *last_tx; /* Last Tx descriptor used. */
- unsigned int cur_tx, dirty_tx;
- /* These values are keep track of the transceiver/media in use. */
- unsigned int flowctrl:1;
- unsigned int default_port:4; /* Last dev->if_port value. */
- unsigned int an_enable:1;
- unsigned int speed;
- unsigned int wol_enabled:1; /* Wake on LAN enabled */
- struct tasklet_struct rx_tasklet;
- struct tasklet_struct tx_tasklet;
- int budget;
- int cur_task;
- /* Multicast and receive mode. */
- spinlock_t mcastlock; /* SMP lock multicast updates. */
- u16 mcast_filter[4];
- /* MII transceiver section. */
- struct mii_if_info mii_if;
- int mii_preamble_required;
- unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */
- struct pci_dev *pci_dev;
- void __iomem *base;
- spinlock_t statlock;
-};
-
-/* The station address location in the EEPROM. */
-#define EEPROM_SA_OFFSET 0x10
-#define DEFAULT_INTR (IntrRxDMADone | IntrPCIErr | \
- IntrDrvRqst | IntrTxDone | StatsMax | \
- LinkChange)
-
-static int change_mtu(struct net_device *dev, int new_mtu);
-static int eeprom_read(void __iomem *ioaddr, int location);
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static int mdio_wait_link(struct net_device *dev, int wait);
-static int netdev_open(struct net_device *dev);
-static void check_duplex(struct net_device *dev);
-static void netdev_timer(struct timer_list *t);
-static void tx_timeout(struct net_device *dev, unsigned int txqueue);
-static void init_ring(struct net_device *dev);
-static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev);
-static int reset_tx (struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance);
-static void rx_poll(struct tasklet_struct *t);
-static void tx_poll(struct tasklet_struct *t);
-static void refill_rx (struct net_device *dev);
-static void netdev_error(struct net_device *dev, int intr_status);
-static void netdev_error(struct net_device *dev, int intr_status);
-static void set_rx_mode(struct net_device *dev);
-static int __set_mac_addr(struct net_device *dev);
-static int sundance_set_mac_addr(struct net_device *dev, void *data);
-static struct net_device_stats *get_stats(struct net_device *dev);
-static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int netdev_close(struct net_device *dev);
-static const struct ethtool_ops ethtool_ops;
-
-static void sundance_reset(struct net_device *dev, unsigned long reset_cmd)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base + ASICCtrl;
- int countdown;
-
- /* ST201 documentation states ASICCtrl is a 32bit register */
- iowrite32 (reset_cmd | ioread32 (ioaddr), ioaddr);
- /* ST201 documentation states reset can take up to 1 ms */
- countdown = 10 + 1;
- while (ioread32 (ioaddr) & (ResetBusy << 16)) {
- if (--countdown == 0) {
- printk(KERN_WARNING "%s : reset not completed !!\n", dev->name);
- break;
- }
- udelay(100);
- }
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void sundance_poll_controller(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
-
- disable_irq(np->pci_dev->irq);
- intr_handler(np->pci_dev->irq, dev);
- enable_irq(np->pci_dev->irq);
-}
-#endif
-
-static const struct net_device_ops netdev_ops = {
- .ndo_open = netdev_open,
- .ndo_stop = netdev_close,
- .ndo_start_xmit = start_tx,
- .ndo_get_stats = get_stats,
- .ndo_set_rx_mode = set_rx_mode,
- .ndo_eth_ioctl = netdev_ioctl,
- .ndo_tx_timeout = tx_timeout,
- .ndo_change_mtu = change_mtu,
- .ndo_set_mac_address = sundance_set_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = sundance_poll_controller,
-#endif
-};
-
-static int sundance_probe1(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct net_device *dev;
- struct netdev_private *np;
- static int card_idx;
- int chip_idx = ent->driver_data;
- int irq;
- int i;
- void __iomem *ioaddr;
- u16 mii_ctl;
- void *ring_space;
- dma_addr_t ring_dma;
-#ifdef USE_IO_OPS
- int bar = 0;
-#else
- int bar = 1;
-#endif
- int phy, phy_end, phy_idx = 0;
- __le16 addr[ETH_ALEN / 2];
-
- if (pci_enable_device(pdev))
- return -EIO;
- pci_set_master(pdev);
-
- irq = pdev->irq;
-
- dev = alloc_etherdev(sizeof(*np));
- if (!dev)
- return -ENOMEM;
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- if (pci_request_regions(pdev, DRV_NAME))
- goto err_out_netdev;
-
- ioaddr = pci_iomap(pdev, bar, netdev_io_size);
- if (!ioaddr)
- goto err_out_res;
-
- for (i = 0; i < 3; i++)
- addr[i] =
- cpu_to_le16(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
- eth_hw_addr_set(dev, (u8 *)addr);
-
- np = netdev_priv(dev);
- np->ndev = dev;
- np->base = ioaddr;
- np->pci_dev = pdev;
- np->chip_id = chip_idx;
- np->msg_enable = (1 << debug) - 1;
- spin_lock_init(&np->lock);
- spin_lock_init(&np->statlock);
- tasklet_setup(&np->rx_tasklet, rx_poll);
- tasklet_setup(&np->tx_tasklet, tx_poll);
-
- ring_space = dma_alloc_coherent(&pdev->dev, TX_TOTAL_SIZE,
- &ring_dma, GFP_KERNEL);
- if (!ring_space)
- goto err_out_cleardev;
- np->tx_ring = (struct netdev_desc *)ring_space;
- np->tx_ring_dma = ring_dma;
-
- ring_space = dma_alloc_coherent(&pdev->dev, RX_TOTAL_SIZE,
- &ring_dma, GFP_KERNEL);
- if (!ring_space)
- goto err_out_unmap_tx;
- np->rx_ring = (struct netdev_desc *)ring_space;
- np->rx_ring_dma = ring_dma;
-
- np->mii_if.dev = dev;
- np->mii_if.mdio_read = mdio_read;
- np->mii_if.mdio_write = mdio_write;
- np->mii_if.phy_id_mask = 0x1f;
- np->mii_if.reg_num_mask = 0x1f;
-
- /* The chip-specific entries in the device structure. */
- dev->netdev_ops = &netdev_ops;
- dev->ethtool_ops = &ethtool_ops;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /* MTU range: 68 - 8191 */
- dev->min_mtu = ETH_MIN_MTU;
- dev->max_mtu = 8191;
-
- pci_set_drvdata(pdev, dev);
-
- i = register_netdev(dev);
- if (i)
- goto err_out_unmap_rx;
-
- printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
- dev->name, pci_id_tbl[chip_idx].name, ioaddr,
- dev->dev_addr, irq);
-
- np->phys[0] = 1; /* Default setting */
- np->mii_preamble_required++;
-
- /*
- * It seems some phys doesn't deal well with address 0 being accessed
- * first
- */
- if (sundance_pci_tbl[np->chip_id].device == 0x0200) {
- phy = 0;
- phy_end = 31;
- } else {
- phy = 1;
- phy_end = 32; /* wraps to zero, due to 'phy & 0x1f' */
- }
- for (; phy <= phy_end && phy_idx < MII_CNT; phy++) {
- int phyx = phy & 0x1f;
- int mii_status = mdio_read(dev, phyx, MII_BMSR);
- if (mii_status != 0xffff && mii_status != 0x0000) {
- np->phys[phy_idx++] = phyx;
- np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
- if ((mii_status & 0x0040) == 0)
- np->mii_preamble_required++;
- printk(KERN_INFO "%s: MII PHY found at address %d, status "
- "0x%4.4x advertising %4.4x.\n",
- dev->name, phyx, mii_status, np->mii_if.advertising);
- }
- }
- np->mii_preamble_required--;
-
- if (phy_idx == 0) {
- printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n",
- dev->name, ioread32(ioaddr + ASICCtrl));
- goto err_out_unregister;
- }
-
- np->mii_if.phy_id = np->phys[0];
-
- /* Parse override configuration */
- np->an_enable = 1;
- if (card_idx < MAX_UNITS) {
- if (media[card_idx] != NULL) {
- np->an_enable = 0;
- if (strcmp (media[card_idx], "100mbps_fd") == 0 ||
- strcmp (media[card_idx], "4") == 0) {
- np->speed = 100;
- np->mii_if.full_duplex = 1;
- } else if (strcmp (media[card_idx], "100mbps_hd") == 0 ||
- strcmp (media[card_idx], "3") == 0) {
- np->speed = 100;
- np->mii_if.full_duplex = 0;
- } else if (strcmp (media[card_idx], "10mbps_fd") == 0 ||
- strcmp (media[card_idx], "2") == 0) {
- np->speed = 10;
- np->mii_if.full_duplex = 1;
- } else if (strcmp (media[card_idx], "10mbps_hd") == 0 ||
- strcmp (media[card_idx], "1") == 0) {
- np->speed = 10;
- np->mii_if.full_duplex = 0;
- } else {
- np->an_enable = 1;
- }
- }
- if (flowctrl == 1)
- np->flowctrl = 1;
- }
-
- /* Fibre PHY? */
- if (ioread32 (ioaddr + ASICCtrl) & 0x80) {
- /* Default 100Mbps Full */
- if (np->an_enable) {
- np->speed = 100;
- np->mii_if.full_duplex = 1;
- np->an_enable = 0;
- }
- }
- /* Reset PHY */
- mdio_write (dev, np->phys[0], MII_BMCR, BMCR_RESET);
- mdelay (300);
- /* If flow control enabled, we need to advertise it.*/
- if (np->flowctrl)
- mdio_write (dev, np->phys[0], MII_ADVERTISE, np->mii_if.advertising | 0x0400);
- mdio_write (dev, np->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
- /* Force media type */
- if (!np->an_enable) {
- mii_ctl = 0;
- mii_ctl |= (np->speed == 100) ? BMCR_SPEED100 : 0;
- mii_ctl |= (np->mii_if.full_duplex) ? BMCR_FULLDPLX : 0;
- mdio_write (dev, np->phys[0], MII_BMCR, mii_ctl);
- printk (KERN_INFO "Override speed=%d, %s duplex\n",
- np->speed, np->mii_if.full_duplex ? "Full" : "Half");
-
- }
-
- /* Perhaps move the reset here? */
- /* Reset the chip to erase previous misconfiguration. */
- if (netif_msg_hw(np))
- printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
- sundance_reset(dev, 0x00ff << 16);
- if (netif_msg_hw(np))
- printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
-
- card_idx++;
- return 0;
-
-err_out_unregister:
- unregister_netdev(dev);
-err_out_unmap_rx:
- dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE,
- np->rx_ring, np->rx_ring_dma);
-err_out_unmap_tx:
- dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE,
- np->tx_ring, np->tx_ring_dma);
-err_out_cleardev:
- pci_iounmap(pdev, ioaddr);
-err_out_res:
- pci_release_regions(pdev);
-err_out_netdev:
- free_netdev (dev);
- return -ENODEV;
-}
-
-static int change_mtu(struct net_device *dev, int new_mtu)
-{
- if (netif_running(dev))
- return -EBUSY;
- WRITE_ONCE(dev->mtu, new_mtu);
- return 0;
-}
-
-#define eeprom_delay(ee_addr) ioread32(ee_addr)
-/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
-static int eeprom_read(void __iomem *ioaddr, int location)
-{
- int boguscnt = 10000; /* Typical 1900 ticks. */
- iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl);
- do {
- eeprom_delay(ioaddr + EECtrl);
- if (! (ioread16(ioaddr + EECtrl) & 0x8000)) {
- return ioread16(ioaddr + EEData);
- }
- } while (--boguscnt > 0);
- return 0;
-}
-
-/* MII transceiver control section.
- Read and write the MII registers using software-generated serial
- MDIO protocol. See the MII specifications or DP83840A data sheet
- for details.
-
- The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
- met by back-to-back 33Mhz PCI cycles. */
-#define mdio_delay() ioread8(mdio_addr)
-
-enum mii_reg_bits {
- MDIO_ShiftClk=0x0001, MDIO_Data=0x0002, MDIO_EnbOutput=0x0004,
-};
-#define MDIO_EnbIn (0)
-#define MDIO_WRITE0 (MDIO_EnbOutput)
-#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput)
-
-/* Generate the preamble required for initial synchronization and
- a few older transceivers. */
-static void mdio_sync(void __iomem *mdio_addr)
-{
- int bits = 32;
-
- /* Establish sync by sending at least 32 logic ones. */
- while (--bits >= 0) {
- iowrite8(MDIO_WRITE1, mdio_addr);
- mdio_delay();
- iowrite8(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
- mdio_delay();
- }
-}
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *mdio_addr = np->base + MIICtrl;
- int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
- int i, retval = 0;
-
- if (np->mii_preamble_required)
- mdio_sync(mdio_addr);
-
- /* Shift the read command bits out. */
- for (i = 15; i >= 0; i--) {
- int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
-
- iowrite8(dataval, mdio_addr);
- mdio_delay();
- iowrite8(dataval | MDIO_ShiftClk, mdio_addr);
- mdio_delay();
- }
- /* Read the two transition, 16 data, and wire-idle bits. */
- for (i = 19; i > 0; i--) {
- iowrite8(MDIO_EnbIn, mdio_addr);
- mdio_delay();
- retval = (retval << 1) | ((ioread8(mdio_addr) & MDIO_Data) ? 1 : 0);
- iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
- mdio_delay();
- }
- return (retval>>1) & 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *mdio_addr = np->base + MIICtrl;
- int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
- int i;
-
- if (np->mii_preamble_required)
- mdio_sync(mdio_addr);
-
- /* Shift the command bits out. */
- for (i = 31; i >= 0; i--) {
- int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
-
- iowrite8(dataval, mdio_addr);
- mdio_delay();
- iowrite8(dataval | MDIO_ShiftClk, mdio_addr);
- mdio_delay();
- }
- /* Clear out extra bits. */
- for (i = 2; i > 0; i--) {
- iowrite8(MDIO_EnbIn, mdio_addr);
- mdio_delay();
- iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
- mdio_delay();
- }
-}
-
-static int mdio_wait_link(struct net_device *dev, int wait)
-{
- int bmsr;
- int phy_id;
- struct netdev_private *np;
-
- np = netdev_priv(dev);
- phy_id = np->phys[0];
-
- do {
- bmsr = mdio_read(dev, phy_id, MII_BMSR);
- if (bmsr & 0x0004)
- return 0;
- mdelay(1);
- } while (--wait > 0);
- return -1;
-}
-
-static int netdev_open(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- const int irq = np->pci_dev->irq;
- unsigned long flags;
- int i;
-
- sundance_reset(dev, 0x00ff << 16);
-
- i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
- if (i)
- return i;
-
- if (netif_msg_ifup(np))
- printk(KERN_DEBUG "%s: netdev_open() irq %d\n", dev->name, irq);
-
- init_ring(dev);
-
- iowrite32(np->rx_ring_dma, ioaddr + RxListPtr);
- /* The Tx list pointer is written as packets are queued. */
-
- /* Initialize other registers. */
- __set_mac_addr(dev);
-#if IS_ENABLED(CONFIG_VLAN_8021Q)
- iowrite16(dev->mtu + 18, ioaddr + MaxFrameSize);
-#else
- iowrite16(dev->mtu + 14, ioaddr + MaxFrameSize);
-#endif
- if (dev->mtu > 2047)
- iowrite32(ioread32(ioaddr + ASICCtrl) | 0x0C, ioaddr + ASICCtrl);
-
- /* Configure the PCI bus bursts and FIFO thresholds. */
-
- if (dev->if_port == 0)
- dev->if_port = np->default_port;
-
- spin_lock_init(&np->mcastlock);
-
- set_rx_mode(dev);
- iowrite16(0, ioaddr + IntrEnable);
- iowrite16(0, ioaddr + DownCounter);
- /* Set the chip to poll every N*320nsec. */
- iowrite8(100, ioaddr + RxDMAPollPeriod);
- iowrite8(127, ioaddr + TxDMAPollPeriod);
- /* Fix DFE-580TX packet drop issue */
- if (np->pci_dev->revision >= 0x14)
- iowrite8(0x01, ioaddr + DebugCtrl1);
- netif_start_queue(dev);
-
- spin_lock_irqsave(&np->lock, flags);
- reset_tx(dev);
- spin_unlock_irqrestore(&np->lock, flags);
-
- iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
-
- /* Disable Wol */
- iowrite8(ioread8(ioaddr + WakeEvent) | 0x00, ioaddr + WakeEvent);
- np->wol_enabled = 0;
-
- if (netif_msg_ifup(np))
- printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x "
- "MAC Control %x, %4.4x %4.4x.\n",
- dev->name, ioread32(ioaddr + RxStatus), ioread8(ioaddr + TxStatus),
- ioread32(ioaddr + MACCtrl0),
- ioread16(ioaddr + MACCtrl1), ioread16(ioaddr + MACCtrl0));
-
- /* Set the timer to check for link beat. */
- timer_setup(&np->timer, netdev_timer, 0);
- np->timer.expires = jiffies + 3*HZ;
- add_timer(&np->timer);
-
- /* Enable interrupts by setting the interrupt mask. */
- iowrite16(DEFAULT_INTR, ioaddr + IntrEnable);
-
- return 0;
-}
-
-static void check_duplex(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
- int negotiated = mii_lpa & np->mii_if.advertising;
- int duplex;
-
- /* Force media */
- if (!np->an_enable || mii_lpa == 0xffff) {
- if (np->mii_if.full_duplex)
- iowrite16 (ioread16 (ioaddr + MACCtrl0) | EnbFullDuplex,
- ioaddr + MACCtrl0);
- return;
- }
-
- /* Autonegotiation */
- duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
- if (np->mii_if.full_duplex != duplex) {
- np->mii_if.full_duplex = duplex;
- if (netif_msg_link(np))
- printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d "
- "negotiated capability %4.4x.\n", dev->name,
- duplex ? "full" : "half", np->phys[0], negotiated);
- iowrite16(ioread16(ioaddr + MACCtrl0) | (duplex ? 0x20 : 0), ioaddr + MACCtrl0);
- }
-}
-
-static void netdev_timer(struct timer_list *t)
-{
- struct netdev_private *np = from_timer(np, t, timer);
- struct net_device *dev = np->mii_if.dev;
- void __iomem *ioaddr = np->base;
- int next_tick = 10*HZ;
-
- if (netif_msg_timer(np)) {
- printk(KERN_DEBUG "%s: Media selection timer tick, intr status %4.4x, "
- "Tx %x Rx %x.\n",
- dev->name, ioread16(ioaddr + IntrEnable),
- ioread8(ioaddr + TxStatus), ioread32(ioaddr + RxStatus));
- }
- check_duplex(dev);
- np->timer.expires = jiffies + next_tick;
- add_timer(&np->timer);
-}
-
-static void tx_timeout(struct net_device *dev, unsigned int txqueue)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- unsigned long flag;
-
- netif_stop_queue(dev);
- tasklet_disable_in_atomic(&np->tx_tasklet);
- iowrite16(0, ioaddr + IntrEnable);
- printk(KERN_WARNING "%s: Transmit timed out, TxStatus %2.2x "
- "TxFrameId %2.2x,"
- " resetting...\n", dev->name, ioread8(ioaddr + TxStatus),
- ioread8(ioaddr + TxFrameId));
-
- {
- int i;
- for (i=0; i<TX_RING_SIZE; i++) {
- printk(KERN_DEBUG "%02x %08llx %08x %08x(%02x) %08x %08x\n", i,
- (unsigned long long)(np->tx_ring_dma + i*sizeof(*np->tx_ring)),
- le32_to_cpu(np->tx_ring[i].next_desc),
- le32_to_cpu(np->tx_ring[i].status),
- (le32_to_cpu(np->tx_ring[i].status) >> 2) & 0xff,
- le32_to_cpu(np->tx_ring[i].frag.addr),
- le32_to_cpu(np->tx_ring[i].frag.length));
- }
- printk(KERN_DEBUG "TxListPtr=%08x netif_queue_stopped=%d\n",
- ioread32(np->base + TxListPtr),
- netif_queue_stopped(dev));
- printk(KERN_DEBUG "cur_tx=%d(%02x) dirty_tx=%d(%02x)\n",
- np->cur_tx, np->cur_tx % TX_RING_SIZE,
- np->dirty_tx, np->dirty_tx % TX_RING_SIZE);
- printk(KERN_DEBUG "cur_rx=%d dirty_rx=%d\n", np->cur_rx, np->dirty_rx);
- printk(KERN_DEBUG "cur_task=%d\n", np->cur_task);
- }
- spin_lock_irqsave(&np->lock, flag);
-
- /* Stop and restart the chip's Tx processes . */
- reset_tx(dev);
- spin_unlock_irqrestore(&np->lock, flag);
-
- dev->if_port = 0;
-
- netif_trans_update(dev); /* prevent tx timeout */
- dev->stats.tx_errors++;
- if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
- netif_wake_queue(dev);
- }
- iowrite16(DEFAULT_INTR, ioaddr + IntrEnable);
- tasklet_enable(&np->tx_tasklet);
-}
-
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void init_ring(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- int i;
-
- np->cur_rx = np->cur_tx = 0;
- np->dirty_rx = np->dirty_tx = 0;
- np->cur_task = 0;
-
- np->rx_buf_sz = (dev->mtu <= 1520 ? PKT_BUF_SZ : dev->mtu + 16);
-
- /* Initialize all Rx descriptors. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- np->rx_ring[i].next_desc = cpu_to_le32(np->rx_ring_dma +
- ((i+1)%RX_RING_SIZE)*sizeof(*np->rx_ring));
- np->rx_ring[i].status = 0;
- np->rx_ring[i].frag.length = 0;
- np->rx_skbuff[i] = NULL;
- }
-
- /* Fill in the Rx buffers. Handle allocation failure gracefully. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb =
- netdev_alloc_skb(dev, np->rx_buf_sz + 2);
- np->rx_skbuff[i] = skb;
- if (skb == NULL)
- break;
- skb_reserve(skb, 2); /* 16 byte align the IP header. */
- np->rx_ring[i].frag.addr = cpu_to_le32(
- dma_map_single(&np->pci_dev->dev, skb->data,
- np->rx_buf_sz, DMA_FROM_DEVICE));
- if (dma_mapping_error(&np->pci_dev->dev,
- np->rx_ring[i].frag.addr)) {
- dev_kfree_skb(skb);
- np->rx_skbuff[i] = NULL;
- break;
- }
- np->rx_ring[i].frag.length = cpu_to_le32(np->rx_buf_sz | LastFrag);
- }
- np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-
- for (i = 0; i < TX_RING_SIZE; i++) {
- np->tx_skbuff[i] = NULL;
- np->tx_ring[i].status = 0;
- }
-}
-
-static void tx_poll(struct tasklet_struct *t)
-{
- struct netdev_private *np = from_tasklet(np, t, tx_tasklet);
- unsigned head = np->cur_task % TX_RING_SIZE;
- struct netdev_desc *txdesc =
- &np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE];
-
- /* Chain the next pointer */
- for (; np->cur_tx - np->cur_task > 0; np->cur_task++) {
- int entry = np->cur_task % TX_RING_SIZE;
- txdesc = &np->tx_ring[entry];
- if (np->last_tx) {
- np->last_tx->next_desc = cpu_to_le32(np->tx_ring_dma +
- entry*sizeof(struct netdev_desc));
- }
- np->last_tx = txdesc;
- }
- /* Indicate the latest descriptor of tx ring */
- txdesc->status |= cpu_to_le32(DescIntrOnTx);
-
- if (ioread32 (np->base + TxListPtr) == 0)
- iowrite32 (np->tx_ring_dma + head * sizeof(struct netdev_desc),
- np->base + TxListPtr);
-}
-
-static netdev_tx_t
-start_tx (struct sk_buff *skb, struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- struct netdev_desc *txdesc;
- unsigned entry;
-
- /* Calculate the next Tx descriptor entry. */
- entry = np->cur_tx % TX_RING_SIZE;
- np->tx_skbuff[entry] = skb;
- txdesc = &np->tx_ring[entry];
-
- txdesc->next_desc = 0;
- txdesc->status = cpu_to_le32 ((entry << 2) | DisableAlign);
- txdesc->frag.addr = cpu_to_le32(dma_map_single(&np->pci_dev->dev,
- skb->data, skb->len, DMA_TO_DEVICE));
- if (dma_mapping_error(&np->pci_dev->dev,
- txdesc->frag.addr))
- goto drop_frame;
- txdesc->frag.length = cpu_to_le32 (skb->len | LastFrag);
-
- /* Increment cur_tx before tasklet_schedule() */
- np->cur_tx++;
- mb();
- /* Schedule a tx_poll() task */
- tasklet_schedule(&np->tx_tasklet);
-
- /* On some architectures: explicitly flush cache lines here. */
- if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 1 &&
- !netif_queue_stopped(dev)) {
- /* do nothing */
- } else {
- netif_stop_queue (dev);
- }
- if (netif_msg_tx_queued(np)) {
- printk (KERN_DEBUG
- "%s: Transmit frame #%d queued in slot %d.\n",
- dev->name, np->cur_tx, entry);
- }
- return NETDEV_TX_OK;
-
-drop_frame:
- dev_kfree_skb_any(skb);
- np->tx_skbuff[entry] = NULL;
- dev->stats.tx_dropped++;
- return NETDEV_TX_OK;
-}
-
-/* Reset hardware tx and free all of tx buffers */
-static int
-reset_tx (struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- struct sk_buff *skb;
- int i;
-
- /* Reset tx logic, TxListPtr will be cleaned */
- iowrite16 (TxDisable, ioaddr + MACCtrl1);
- sundance_reset(dev, (NetworkReset|FIFOReset|DMAReset|TxReset) << 16);
-
- /* free all tx skbuff */
- for (i = 0; i < TX_RING_SIZE; i++) {
- np->tx_ring[i].next_desc = 0;
-
- skb = np->tx_skbuff[i];
- if (skb) {
- dma_unmap_single(&np->pci_dev->dev,
- le32_to_cpu(np->tx_ring[i].frag.addr),
- skb->len, DMA_TO_DEVICE);
- dev_kfree_skb_any(skb);
- np->tx_skbuff[i] = NULL;
- dev->stats.tx_dropped++;
- }
- }
- np->cur_tx = np->dirty_tx = 0;
- np->cur_task = 0;
-
- np->last_tx = NULL;
- iowrite8(127, ioaddr + TxDMAPollPeriod);
-
- iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
- return 0;
-}
-
-/* The interrupt handler cleans up after the Tx thread,
- and schedule a Rx thread work */
-static irqreturn_t intr_handler(int irq, void *dev_instance)
-{
- struct net_device *dev = (struct net_device *)dev_instance;
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- int hw_frame_id;
- int tx_cnt;
- int tx_status;
- int handled = 0;
- int i;
-
- do {
- int intr_status = ioread16(ioaddr + IntrStatus);
- iowrite16(intr_status, ioaddr + IntrStatus);
-
- if (netif_msg_intr(np))
- printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n",
- dev->name, intr_status);
-
- if (!(intr_status & DEFAULT_INTR))
- break;
-
- handled = 1;
-
- if (intr_status & (IntrRxDMADone)) {
- iowrite16(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone),
- ioaddr + IntrEnable);
- if (np->budget < 0)
- np->budget = RX_BUDGET;
- tasklet_schedule(&np->rx_tasklet);
- }
- if (intr_status & (IntrTxDone | IntrDrvRqst)) {
- tx_status = ioread16 (ioaddr + TxStatus);
- for (tx_cnt=32; tx_status & 0x80; --tx_cnt) {
- if (netif_msg_tx_done(np))
- printk
- ("%s: Transmit status is %2.2x.\n",
- dev->name, tx_status);
- if (tx_status & 0x1e) {
- if (netif_msg_tx_err(np))
- printk("%s: Transmit error status %4.4x.\n",
- dev->name, tx_status);
- dev->stats.tx_errors++;
- if (tx_status & 0x10)
- dev->stats.tx_fifo_errors++;
- if (tx_status & 0x08)
- dev->stats.collisions++;
- if (tx_status & 0x04)
- dev->stats.tx_fifo_errors++;
- if (tx_status & 0x02)
- dev->stats.tx_window_errors++;
-
- /*
- ** This reset has been verified on
- ** DFE-580TX boards ! phdm@macqel.be.
- */
- if (tx_status & 0x10) { /* TxUnderrun */
- /* Restart Tx FIFO and transmitter */
- sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16);
- /* No need to reset the Tx pointer here */
- }
- /* Restart the Tx. Need to make sure tx enabled */
- i = 10;
- do {
- iowrite16(ioread16(ioaddr + MACCtrl1) | TxEnable, ioaddr + MACCtrl1);
- if (ioread16(ioaddr + MACCtrl1) & TxEnabled)
- break;
- mdelay(1);
- } while (--i);
- }
- /* Yup, this is a documentation bug. It cost me *hours*. */
- iowrite16 (0, ioaddr + TxStatus);
- if (tx_cnt < 0) {
- iowrite32(5000, ioaddr + DownCounter);
- break;
- }
- tx_status = ioread16 (ioaddr + TxStatus);
- }
- hw_frame_id = (tx_status >> 8) & 0xff;
- } else {
- hw_frame_id = ioread8(ioaddr + TxFrameId);
- }
-
- if (np->pci_dev->revision >= 0x14) {
- spin_lock(&np->lock);
- for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
- int entry = np->dirty_tx % TX_RING_SIZE;
- struct sk_buff *skb;
- int sw_frame_id;
- sw_frame_id = (le32_to_cpu(
- np->tx_ring[entry].status) >> 2) & 0xff;
- if (sw_frame_id == hw_frame_id &&
- !(le32_to_cpu(np->tx_ring[entry].status)
- & 0x00010000))
- break;
- if (sw_frame_id == (hw_frame_id + 1) %
- TX_RING_SIZE)
- break;
- skb = np->tx_skbuff[entry];
- /* Free the original skb. */
- dma_unmap_single(&np->pci_dev->dev,
- le32_to_cpu(np->tx_ring[entry].frag.addr),
- skb->len, DMA_TO_DEVICE);
- dev_consume_skb_irq(np->tx_skbuff[entry]);
- np->tx_skbuff[entry] = NULL;
- np->tx_ring[entry].frag.addr = 0;
- np->tx_ring[entry].frag.length = 0;
- }
- spin_unlock(&np->lock);
- } else {
- spin_lock(&np->lock);
- for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
- int entry = np->dirty_tx % TX_RING_SIZE;
- struct sk_buff *skb;
- if (!(le32_to_cpu(np->tx_ring[entry].status)
- & 0x00010000))
- break;
- skb = np->tx_skbuff[entry];
- /* Free the original skb. */
- dma_unmap_single(&np->pci_dev->dev,
- le32_to_cpu(np->tx_ring[entry].frag.addr),
- skb->len, DMA_TO_DEVICE);
- dev_consume_skb_irq(np->tx_skbuff[entry]);
- np->tx_skbuff[entry] = NULL;
- np->tx_ring[entry].frag.addr = 0;
- np->tx_ring[entry].frag.length = 0;
- }
- spin_unlock(&np->lock);
- }
-
- if (netif_queue_stopped(dev) &&
- np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
- /* The ring is no longer full, clear busy flag. */
- netif_wake_queue (dev);
- }
- /* Abnormal error summary/uncommon events handlers. */
- if (intr_status & (IntrPCIErr | LinkChange | StatsMax))
- netdev_error(dev, intr_status);
- } while (0);
- if (netif_msg_intr(np))
- printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
- dev->name, ioread16(ioaddr + IntrStatus));
- return IRQ_RETVAL(handled);
-}
-
-static void rx_poll(struct tasklet_struct *t)
-{
- struct netdev_private *np = from_tasklet(np, t, rx_tasklet);
- struct net_device *dev = np->ndev;
- int entry = np->cur_rx % RX_RING_SIZE;
- int boguscnt = np->budget;
- void __iomem *ioaddr = np->base;
- int received = 0;
-
- /* If EOP is set on the next entry, it's a new packet. Send it up. */
- while (1) {
- struct netdev_desc *desc = &(np->rx_ring[entry]);
- u32 frame_status = le32_to_cpu(desc->status);
- int pkt_len;
-
- if (--boguscnt < 0) {
- goto not_done;
- }
- if (!(frame_status & DescOwn))
- break;
- pkt_len = frame_status & 0x1fff; /* Chip omits the CRC. */
- if (netif_msg_rx_status(np))
- printk(KERN_DEBUG " netdev_rx() status was %8.8x.\n",
- frame_status);
- if (frame_status & 0x001f4000) {
- /* There was a error. */
- if (netif_msg_rx_err(np))
- printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n",
- frame_status);
- dev->stats.rx_errors++;
- if (frame_status & 0x00100000)
- dev->stats.rx_length_errors++;
- if (frame_status & 0x00010000)
- dev->stats.rx_fifo_errors++;
- if (frame_status & 0x00060000)
- dev->stats.rx_frame_errors++;
- if (frame_status & 0x00080000)
- dev->stats.rx_crc_errors++;
- if (frame_status & 0x00100000) {
- printk(KERN_WARNING "%s: Oversized Ethernet frame,"
- " status %8.8x.\n",
- dev->name, frame_status);
- }
- } else {
- struct sk_buff *skb;
-#ifndef final_version
- if (netif_msg_rx_status(np))
- printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d"
- ", bogus_cnt %d.\n",
- pkt_len, boguscnt);
-#endif
- /* Check if the packet is long enough to accept without copying
- to a minimally-sized skbuff. */
- if (pkt_len < rx_copybreak &&
- (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
- skb_reserve(skb, 2); /* 16 byte align the IP header */
- dma_sync_single_for_cpu(&np->pci_dev->dev,
- le32_to_cpu(desc->frag.addr),
- np->rx_buf_sz, DMA_FROM_DEVICE);
- skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
- dma_sync_single_for_device(&np->pci_dev->dev,
- le32_to_cpu(desc->frag.addr),
- np->rx_buf_sz, DMA_FROM_DEVICE);
- skb_put(skb, pkt_len);
- } else {
- dma_unmap_single(&np->pci_dev->dev,
- le32_to_cpu(desc->frag.addr),
- np->rx_buf_sz, DMA_FROM_DEVICE);
- skb_put(skb = np->rx_skbuff[entry], pkt_len);
- np->rx_skbuff[entry] = NULL;
- }
- skb->protocol = eth_type_trans(skb, dev);
- /* Note: checksum -> skb->ip_summed = CHECKSUM_UNNECESSARY; */
- netif_rx(skb);
- }
- entry = (entry + 1) % RX_RING_SIZE;
- received++;
- }
- np->cur_rx = entry;
- refill_rx (dev);
- np->budget -= received;
- iowrite16(DEFAULT_INTR, ioaddr + IntrEnable);
- return;
-
-not_done:
- np->cur_rx = entry;
- refill_rx (dev);
- if (!received)
- received = 1;
- np->budget -= received;
- if (np->budget <= 0)
- np->budget = RX_BUDGET;
- tasklet_schedule(&np->rx_tasklet);
-}
-
-static void refill_rx (struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- int entry;
-
- /* Refill the Rx ring buffers. */
- for (;(np->cur_rx - np->dirty_rx + RX_RING_SIZE) % RX_RING_SIZE > 0;
- np->dirty_rx = (np->dirty_rx + 1) % RX_RING_SIZE) {
- struct sk_buff *skb;
- entry = np->dirty_rx % RX_RING_SIZE;
- if (np->rx_skbuff[entry] == NULL) {
- skb = netdev_alloc_skb(dev, np->rx_buf_sz + 2);
- np->rx_skbuff[entry] = skb;
- if (skb == NULL)
- break; /* Better luck next round. */
- skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- np->rx_ring[entry].frag.addr = cpu_to_le32(
- dma_map_single(&np->pci_dev->dev, skb->data,
- np->rx_buf_sz, DMA_FROM_DEVICE));
- if (dma_mapping_error(&np->pci_dev->dev,
- np->rx_ring[entry].frag.addr)) {
- dev_kfree_skb_irq(skb);
- np->rx_skbuff[entry] = NULL;
- break;
- }
- }
- /* Perhaps we need not reset this field. */
- np->rx_ring[entry].frag.length =
- cpu_to_le32(np->rx_buf_sz | LastFrag);
- np->rx_ring[entry].status = 0;
- }
-}
-static void netdev_error(struct net_device *dev, int intr_status)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- u16 mii_ctl, mii_advertise, mii_lpa;
- int speed;
-
- if (intr_status & LinkChange) {
- if (mdio_wait_link(dev, 10) == 0) {
- printk(KERN_INFO "%s: Link up\n", dev->name);
- if (np->an_enable) {
- mii_advertise = mdio_read(dev, np->phys[0],
- MII_ADVERTISE);
- mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
- mii_advertise &= mii_lpa;
- printk(KERN_INFO "%s: Link changed: ",
- dev->name);
- if (mii_advertise & ADVERTISE_100FULL) {
- np->speed = 100;
- printk("100Mbps, full duplex\n");
- } else if (mii_advertise & ADVERTISE_100HALF) {
- np->speed = 100;
- printk("100Mbps, half duplex\n");
- } else if (mii_advertise & ADVERTISE_10FULL) {
- np->speed = 10;
- printk("10Mbps, full duplex\n");
- } else if (mii_advertise & ADVERTISE_10HALF) {
- np->speed = 10;
- printk("10Mbps, half duplex\n");
- } else
- printk("\n");
-
- } else {
- mii_ctl = mdio_read(dev, np->phys[0], MII_BMCR);
- speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
- np->speed = speed;
- printk(KERN_INFO "%s: Link changed: %dMbps ,",
- dev->name, speed);
- printk("%s duplex.\n",
- (mii_ctl & BMCR_FULLDPLX) ?
- "full" : "half");
- }
- check_duplex(dev);
- if (np->flowctrl && np->mii_if.full_duplex) {
- iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
- ioaddr + MulticastFilter1+2);
- iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
- ioaddr + MACCtrl0);
- }
- netif_carrier_on(dev);
- } else {
- printk(KERN_INFO "%s: Link down\n", dev->name);
- netif_carrier_off(dev);
- }
- }
- if (intr_status & StatsMax) {
- get_stats(dev);
- }
- if (intr_status & IntrPCIErr) {
- printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
- dev->name, intr_status);
- /* We must do a global reset of DMA to continue. */
- }
-}
-
-static struct net_device_stats *get_stats(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- unsigned long flags;
- u8 late_coll, single_coll, mult_coll;
-
- spin_lock_irqsave(&np->statlock, flags);
- /* The chip only need report frame silently dropped. */
- dev->stats.rx_missed_errors += ioread8(ioaddr + RxMissed);
- dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK);
- dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK);
- dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError);
-
- mult_coll = ioread8(ioaddr + StatsMultiColl);
- np->xstats.tx_multiple_collisions += mult_coll;
- single_coll = ioread8(ioaddr + StatsOneColl);
- np->xstats.tx_single_collisions += single_coll;
- late_coll = ioread8(ioaddr + StatsLateColl);
- np->xstats.tx_late_collisions += late_coll;
- dev->stats.collisions += mult_coll
- + single_coll
- + late_coll;
-
- np->xstats.tx_deferred += ioread8(ioaddr + StatsTxDefer);
- np->xstats.tx_deferred_excessive += ioread8(ioaddr + StatsTxXSDefer);
- np->xstats.tx_aborted += ioread8(ioaddr + StatsTxAbort);
- np->xstats.tx_bcasts += ioread8(ioaddr + StatsBcastTx);
- np->xstats.rx_bcasts += ioread8(ioaddr + StatsBcastRx);
- np->xstats.tx_mcasts += ioread8(ioaddr + StatsMcastTx);
- np->xstats.rx_mcasts += ioread8(ioaddr + StatsMcastRx);
-
- dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow);
- dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16;
- dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow);
- dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16;
-
- spin_unlock_irqrestore(&np->statlock, flags);
-
- return &dev->stats;
-}
-
-static void set_rx_mode(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- u16 mc_filter[4]; /* Multicast hash filter */
- u32 rx_mode;
- int i;
-
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- memset(mc_filter, 0xff, sizeof(mc_filter));
- rx_mode = AcceptBroadcast | AcceptMulticast | AcceptAll | AcceptMyPhys;
- } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
- (dev->flags & IFF_ALLMULTI)) {
- /* Too many to match, or accept all multicasts. */
- memset(mc_filter, 0xff, sizeof(mc_filter));
- rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
- } else if (!netdev_mc_empty(dev)) {
- struct netdev_hw_addr *ha;
- int bit;
- int index;
- int crc;
- memset (mc_filter, 0, sizeof (mc_filter));
- netdev_for_each_mc_addr(ha, dev) {
- crc = ether_crc_le(ETH_ALEN, ha->addr);
- for (index=0, bit=0; bit < 6; bit++, crc <<= 1)
- if (crc & 0x80000000) index |= 1 << bit;
- mc_filter[index/16] |= (1 << (index % 16));
- }
- rx_mode = AcceptBroadcast | AcceptMultiHash | AcceptMyPhys;
- } else {
- iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode);
- return;
- }
- if (np->mii_if.full_duplex && np->flowctrl)
- mc_filter[3] |= 0x0200;
-
- for (i = 0; i < 4; i++)
- iowrite16(mc_filter[i], ioaddr + MulticastFilter0 + i*2);
- iowrite8(rx_mode, ioaddr + RxMode);
-}
-
-static int __set_mac_addr(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- u16 addr16;
-
- addr16 = (dev->dev_addr[0] | (dev->dev_addr[1] << 8));
- iowrite16(addr16, np->base + StationAddr);
- addr16 = (dev->dev_addr[2] | (dev->dev_addr[3] << 8));
- iowrite16(addr16, np->base + StationAddr+2);
- addr16 = (dev->dev_addr[4] | (dev->dev_addr[5] << 8));
- iowrite16(addr16, np->base + StationAddr+4);
- return 0;
-}
-
-/* Invoked with rtnl_lock held */
-static int sundance_set_mac_addr(struct net_device *dev, void *data)
-{
- const struct sockaddr *addr = data;
-
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
- eth_hw_addr_set(dev, addr->sa_data);
- __set_mac_addr(dev);
-
- return 0;
-}
-
-static const struct {
- const char name[ETH_GSTRING_LEN];
-} sundance_stats[] = {
- { "tx_multiple_collisions" },
- { "tx_single_collisions" },
- { "tx_late_collisions" },
- { "tx_deferred" },
- { "tx_deferred_excessive" },
- { "tx_aborted" },
- { "tx_bcasts" },
- { "rx_bcasts" },
- { "tx_mcasts" },
- { "rx_mcasts" },
-};
-
-static int check_if_running(struct net_device *dev)
-{
- if (!netif_running(dev))
- return -EINVAL;
- return 0;
-}
-
-static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- struct netdev_private *np = netdev_priv(dev);
- strscpy(info->driver, DRV_NAME, sizeof(info->driver));
- strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
-}
-
-static int get_link_ksettings(struct net_device *dev,
- struct ethtool_link_ksettings *cmd)
-{
- struct netdev_private *np = netdev_priv(dev);
- spin_lock_irq(&np->lock);
- mii_ethtool_get_link_ksettings(&np->mii_if, cmd);
- spin_unlock_irq(&np->lock);
- return 0;
-}
-
-static int set_link_ksettings(struct net_device *dev,
- const struct ethtool_link_ksettings *cmd)
-{
- struct netdev_private *np = netdev_priv(dev);
- int res;
- spin_lock_irq(&np->lock);
- res = mii_ethtool_set_link_ksettings(&np->mii_if, cmd);
- spin_unlock_irq(&np->lock);
- return res;
-}
-
-static int nway_reset(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- return mii_nway_restart(&np->mii_if);
-}
-
-static u32 get_link(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- return mii_link_ok(&np->mii_if);
-}
-
-static u32 get_msglevel(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- return np->msg_enable;
-}
-
-static void set_msglevel(struct net_device *dev, u32 val)
-{
- struct netdev_private *np = netdev_priv(dev);
- np->msg_enable = val;
-}
-
-static void get_strings(struct net_device *dev, u32 stringset,
- u8 *data)
-{
- if (stringset == ETH_SS_STATS)
- memcpy(data, sundance_stats, sizeof(sundance_stats));
-}
-
-static int get_sset_count(struct net_device *dev, int sset)
-{
- switch (sset) {
- case ETH_SS_STATS:
- return ARRAY_SIZE(sundance_stats);
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static void get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
-{
- struct netdev_private *np = netdev_priv(dev);
- int i = 0;
-
- get_stats(dev);
- data[i++] = np->xstats.tx_multiple_collisions;
- data[i++] = np->xstats.tx_single_collisions;
- data[i++] = np->xstats.tx_late_collisions;
- data[i++] = np->xstats.tx_deferred;
- data[i++] = np->xstats.tx_deferred_excessive;
- data[i++] = np->xstats.tx_aborted;
- data[i++] = np->xstats.tx_bcasts;
- data[i++] = np->xstats.rx_bcasts;
- data[i++] = np->xstats.tx_mcasts;
- data[i++] = np->xstats.rx_mcasts;
-}
-
-#ifdef CONFIG_PM
-
-static void sundance_get_wol(struct net_device *dev,
- struct ethtool_wolinfo *wol)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- u8 wol_bits;
-
- wol->wolopts = 0;
-
- wol->supported = (WAKE_PHY | WAKE_MAGIC);
- if (!np->wol_enabled)
- return;
-
- wol_bits = ioread8(ioaddr + WakeEvent);
- if (wol_bits & MagicPktEnable)
- wol->wolopts |= WAKE_MAGIC;
- if (wol_bits & LinkEventEnable)
- wol->wolopts |= WAKE_PHY;
-}
-
-static int sundance_set_wol(struct net_device *dev,
- struct ethtool_wolinfo *wol)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- u8 wol_bits;
-
- if (!device_can_wakeup(&np->pci_dev->dev))
- return -EOPNOTSUPP;
-
- np->wol_enabled = !!(wol->wolopts);
- wol_bits = ioread8(ioaddr + WakeEvent);
- wol_bits &= ~(WakePktEnable | MagicPktEnable |
- LinkEventEnable | WolEnable);
-
- if (np->wol_enabled) {
- if (wol->wolopts & WAKE_MAGIC)
- wol_bits |= (MagicPktEnable | WolEnable);
- if (wol->wolopts & WAKE_PHY)
- wol_bits |= (LinkEventEnable | WolEnable);
- }
- iowrite8(wol_bits, ioaddr + WakeEvent);
-
- device_set_wakeup_enable(&np->pci_dev->dev, np->wol_enabled);
-
- return 0;
-}
-#else
-#define sundance_get_wol NULL
-#define sundance_set_wol NULL
-#endif /* CONFIG_PM */
-
-static const struct ethtool_ops ethtool_ops = {
- .begin = check_if_running,
- .get_drvinfo = get_drvinfo,
- .nway_reset = nway_reset,
- .get_link = get_link,
- .get_wol = sundance_get_wol,
- .set_wol = sundance_set_wol,
- .get_msglevel = get_msglevel,
- .set_msglevel = set_msglevel,
- .get_strings = get_strings,
- .get_sset_count = get_sset_count,
- .get_ethtool_stats = get_ethtool_stats,
- .get_link_ksettings = get_link_ksettings,
- .set_link_ksettings = set_link_ksettings,
-};
-
-static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct netdev_private *np = netdev_priv(dev);
- int rc;
-
- if (!netif_running(dev))
- return -EINVAL;
-
- spin_lock_irq(&np->lock);
- rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL);
- spin_unlock_irq(&np->lock);
-
- return rc;
-}
-
-static int netdev_close(struct net_device *dev)
-{
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
- struct sk_buff *skb;
- int i;
-
- /* Wait and kill tasklet */
- tasklet_kill(&np->rx_tasklet);
- tasklet_kill(&np->tx_tasklet);
- np->cur_tx = 0;
- np->dirty_tx = 0;
- np->cur_task = 0;
- np->last_tx = NULL;
-
- netif_stop_queue(dev);
-
- if (netif_msg_ifdown(np)) {
- printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %2.2x "
- "Rx %4.4x Int %2.2x.\n",
- dev->name, ioread8(ioaddr + TxStatus),
- ioread32(ioaddr + RxStatus), ioread16(ioaddr + IntrStatus));
- printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n",
- dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx);
- }
-
- /* Disable interrupts by clearing the interrupt mask. */
- iowrite16(0x0000, ioaddr + IntrEnable);
-
- /* Disable Rx and Tx DMA for safely release resource */
- iowrite32(0x500, ioaddr + DMACtrl);
-
- /* Stop the chip's Tx and Rx processes. */
- iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1);
-
- for (i = 2000; i > 0; i--) {
- if ((ioread32(ioaddr + DMACtrl) & 0xc000) == 0)
- break;
- mdelay(1);
- }
-
- iowrite16(GlobalReset | DMAReset | FIFOReset | NetworkReset,
- ioaddr + ASIC_HI_WORD(ASICCtrl));
-
- for (i = 2000; i > 0; i--) {
- if ((ioread16(ioaddr + ASIC_HI_WORD(ASICCtrl)) & ResetBusy) == 0)
- break;
- mdelay(1);
- }
-
-#ifdef __i386__
- if (netif_msg_hw(np)) {
- printk(KERN_DEBUG " Tx ring at %8.8x:\n",
- (int)(np->tx_ring_dma));
- for (i = 0; i < TX_RING_SIZE; i++)
- printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n",
- i, np->tx_ring[i].status, np->tx_ring[i].frag.addr,
- np->tx_ring[i].frag.length);
- printk(KERN_DEBUG " Rx ring %8.8x:\n",
- (int)(np->rx_ring_dma));
- for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) {
- printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
- i, np->rx_ring[i].status, np->rx_ring[i].frag.addr,
- np->rx_ring[i].frag.length);
- }
- }
-#endif /* __i386__ debugging only */
-
- free_irq(np->pci_dev->irq, dev);
-
- del_timer_sync(&np->timer);
-
- /* Free all the skbuffs in the Rx queue. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- np->rx_ring[i].status = 0;
- skb = np->rx_skbuff[i];
- if (skb) {
- dma_unmap_single(&np->pci_dev->dev,
- le32_to_cpu(np->rx_ring[i].frag.addr),
- np->rx_buf_sz, DMA_FROM_DEVICE);
- dev_kfree_skb(skb);
- np->rx_skbuff[i] = NULL;
- }
- np->rx_ring[i].frag.addr = cpu_to_le32(0xBADF00D0); /* poison */
- }
- for (i = 0; i < TX_RING_SIZE; i++) {
- np->tx_ring[i].next_desc = 0;
- skb = np->tx_skbuff[i];
- if (skb) {
- dma_unmap_single(&np->pci_dev->dev,
- le32_to_cpu(np->tx_ring[i].frag.addr),
- skb->len, DMA_TO_DEVICE);
- dev_kfree_skb(skb);
- np->tx_skbuff[i] = NULL;
- }
- }
-
- return 0;
-}
-
-static void sundance_remove1(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
-
- if (dev) {
- struct netdev_private *np = netdev_priv(dev);
- unregister_netdev(dev);
- dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE,
- np->rx_ring, np->rx_ring_dma);
- dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE,
- np->tx_ring, np->tx_ring_dma);
- pci_iounmap(pdev, np->base);
- pci_release_regions(pdev);
- free_netdev(dev);
- }
-}
-
-static int __maybe_unused sundance_suspend(struct device *dev_d)
-{
- struct net_device *dev = dev_get_drvdata(dev_d);
- struct netdev_private *np = netdev_priv(dev);
- void __iomem *ioaddr = np->base;
-
- if (!netif_running(dev))
- return 0;
-
- netdev_close(dev);
- netif_device_detach(dev);
-
- if (np->wol_enabled) {
- iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode);
- iowrite16(RxEnable, ioaddr + MACCtrl1);
- }
-
- device_set_wakeup_enable(dev_d, np->wol_enabled);
-
- return 0;
-}
-
-static int __maybe_unused sundance_resume(struct device *dev_d)
-{
- struct net_device *dev = dev_get_drvdata(dev_d);
- int err = 0;
-
- if (!netif_running(dev))
- return 0;
-
- err = netdev_open(dev);
- if (err) {
- printk(KERN_ERR "%s: Can't resume interface!\n",
- dev->name);
- goto out;
- }
-
- netif_device_attach(dev);
-
-out:
- return err;
-}
-
-static SIMPLE_DEV_PM_OPS(sundance_pm_ops, sundance_suspend, sundance_resume);
-
-static struct pci_driver sundance_driver = {
- .name = DRV_NAME,
- .id_table = sundance_pci_tbl,
- .probe = sundance_probe1,
- .remove = sundance_remove1,
- .driver.pm = &sundance_pm_ops,
-};
-
-module_pci_driver(sundance_driver);
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 2a18df3605f1..0de3cd660ec8 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -863,7 +863,7 @@ static void dnet_remove(struct platform_device *pdev)
static struct platform_driver dnet_driver = {
.probe = dnet_probe,
- .remove_new = dnet_remove,
+ .remove = dnet_remove,
.driver = {
.name = "dnet",
},
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 44da335d66bd..95a5295d0361 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -2689,7 +2689,7 @@ static struct platform_driver tsnep_driver = {
.of_match_table = tsnep_of_match,
},
.probe = tsnep_probe,
- .remove_new = tsnep_remove,
+ .remove = tsnep_remove,
};
module_platform_driver(tsnep_driver);
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index ad41c9019018..0c418557264c 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -1296,7 +1296,7 @@ MODULE_DEVICE_TABLE(of, ethoc_match);
static struct platform_driver ethoc_driver = {
.probe = ethoc_probe,
- .remove_new = ethoc_remove,
+ .remove = ethoc_remove,
.suspend = ethoc_suspend,
.resume = ethoc_resume,
.driver = {
diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c
index 9ebe751c1df0..5cb478e98697 100644
--- a/drivers/net/ethernet/ezchip/nps_enet.c
+++ b/drivers/net/ethernet/ezchip/nps_enet.c
@@ -651,7 +651,7 @@ MODULE_DEVICE_TABLE(of, nps_enet_dt_ids);
static struct platform_driver nps_enet_driver = {
.probe = nps_enet_probe,
- .remove_new = nps_enet_remove,
+ .remove = nps_enet_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = nps_enet_dt_ids,
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 0b61f548fd18..17ec35e75a65 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1913,40 +1913,22 @@ static int ftgmac100_probe(struct platform_device *pdev)
goto err_phy_connect;
}
err = phy_connect_direct(netdev, phydev, ftgmac100_adjust_link,
- PHY_INTERFACE_MODE_MII);
+ PHY_INTERFACE_MODE_RMII);
if (err) {
dev_err(&pdev->dev, "Connecting PHY failed\n");
goto err_phy_connect;
}
- } else if (np && of_phy_is_fixed_link(np)) {
- struct phy_device *phy;
-
- err = of_phy_register_fixed_link(np);
- if (err) {
- dev_err(&pdev->dev, "Failed to register fixed PHY\n");
- goto err_phy_connect;
- }
-
- phy = of_phy_get_and_connect(priv->netdev, np,
- &ftgmac100_adjust_link);
- if (!phy) {
- dev_err(&pdev->dev, "Failed to connect to fixed PHY\n");
- of_phy_deregister_fixed_link(np);
- err = -EINVAL;
- goto err_phy_connect;
- }
-
- /* Display what we found */
- phy_attached_info(phy);
- } else if (np && of_get_property(np, "phy-handle", NULL)) {
+ } else if (np && (of_phy_is_fixed_link(np) ||
+ of_get_property(np, "phy-handle", NULL))) {
struct phy_device *phy;
/* Support "mdio"/"phy" child nodes for ast2400/2500 with
* an embedded MDIO controller. Automatically scan the DTS for
* available PHYs and register them.
*/
- if (of_device_is_compatible(np, "aspeed,ast2400-mac") ||
- of_device_is_compatible(np, "aspeed,ast2500-mac")) {
+ if (of_get_property(np, "phy-handle", NULL) &&
+ (of_device_is_compatible(np, "aspeed,ast2400-mac") ||
+ of_device_is_compatible(np, "aspeed,ast2500-mac"))) {
err = ftgmac100_setup_mdio(netdev);
if (err)
goto err_setup_mdio;
@@ -2089,7 +2071,7 @@ MODULE_DEVICE_TABLE(of, ftgmac100_of_match);
static struct platform_driver ftgmac100_driver = {
.probe = ftgmac100_probe,
- .remove_new = ftgmac100_remove,
+ .remove = ftgmac100_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = ftgmac100_of_match,
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index 1047c805054e..5803a382f0ba 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -1243,7 +1243,7 @@ static const struct of_device_id ftmac100_of_ids[] = {
static struct platform_driver ftmac100_driver = {
.probe = ftmac100_probe,
- .remove_new = ftmac100_remove,
+ .remove = ftmac100_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = ftmac100_of_ids
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index e15dd3d858df..bf5baef5c3e0 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -463,6 +463,22 @@ static int dpaa_set_mac_address(struct net_device *net_dev, void *addr)
return 0;
}
+static int dpaa_addr_sync(struct net_device *net_dev, const u8 *addr)
+{
+ const struct dpaa_priv *priv = netdev_priv(net_dev);
+
+ return priv->mac_dev->add_hash_mac_addr(priv->mac_dev->fman_mac,
+ (enet_addr_t *)addr);
+}
+
+static int dpaa_addr_unsync(struct net_device *net_dev, const u8 *addr)
+{
+ const struct dpaa_priv *priv = netdev_priv(net_dev);
+
+ return priv->mac_dev->remove_hash_mac_addr(priv->mac_dev->fman_mac,
+ (enet_addr_t *)addr);
+}
+
static void dpaa_set_rx_mode(struct net_device *net_dev)
{
const struct dpaa_priv *priv;
@@ -490,9 +506,9 @@ static void dpaa_set_rx_mode(struct net_device *net_dev)
err);
}
- err = priv->mac_dev->set_multi(net_dev, priv->mac_dev);
+ err = __dev_mc_sync(net_dev, dpaa_addr_sync, dpaa_addr_unsync);
if (err < 0)
- netif_err(priv, drv, net_dev, "mac_dev->set_multi() = %d\n",
+ netif_err(priv, drv, net_dev, "dpaa_addr_sync() = %d\n",
err);
}
@@ -1804,7 +1820,6 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
struct page *page, *head_page;
struct dpaa_bp *dpaa_bp;
void *vaddr, *sg_vaddr;
- int frag_off, frag_len;
struct sk_buff *skb;
dma_addr_t sg_addr;
int page_offset;
@@ -1847,6 +1862,11 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
* on Tx, if extra headers are added.
*/
WARN_ON(fd_off != priv->rx_headroom);
+ /* The offset to data start within the buffer holding
+ * the SGT should always be equal to the offset to data
+ * start within the first buffer holding the frame.
+ */
+ WARN_ON_ONCE(fd_off != qm_sg_entry_get_off(&sgt[i]));
skb_reserve(skb, fd_off);
skb_put(skb, qm_sg_entry_get_len(&sgt[i]));
} else {
@@ -1860,21 +1880,23 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
page = virt_to_page(sg_vaddr);
head_page = virt_to_head_page(sg_vaddr);
- /* Compute offset in (possibly tail) page */
+ /* Compute offset of sg_vaddr in (possibly tail) page */
page_offset = ((unsigned long)sg_vaddr &
(PAGE_SIZE - 1)) +
(page_address(page) - page_address(head_page));
- /* page_offset only refers to the beginning of sgt[i];
- * but the buffer itself may have an internal offset.
+
+ /* Non-initial SGT entries should not have a buffer
+ * offset.
*/
- frag_off = qm_sg_entry_get_off(&sgt[i]) + page_offset;
- frag_len = qm_sg_entry_get_len(&sgt[i]);
+ WARN_ON_ONCE(qm_sg_entry_get_off(&sgt[i]));
+
/* skb_add_rx_frag() does no checking on the page; if
* we pass it a tail page, we'll end up with
- * bad page accounting and eventually with segafults.
+ * bad page accounting and eventually with segfaults.
*/
- skb_add_rx_frag(skb, i - 1, head_page, frag_off,
- frag_len, dpaa_bp->size);
+ skb_add_rx_frag(skb, i - 1, head_page, page_offset,
+ qm_sg_entry_get_len(&sgt[i]),
+ dpaa_bp->size);
}
/* Update the pool count for the current {cpu x bpool} */
@@ -2750,7 +2772,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use &&
!fman_port_get_hash_result_offset(priv->mac_dev->port[RX],
&hash_offset)) {
- hash = be32_to_cpu(*(u32 *)(vaddr + hash_offset));
+ hash = be32_to_cpu(*(__be32 *)(vaddr + hash_offset));
hash_valid = true;
}
@@ -3571,7 +3593,7 @@ static struct platform_driver dpaa_driver = {
},
.id_table = dpaa_devtype,
.probe = dpaa_eth_probe,
- .remove_new = dpaa_remove
+ .remove = dpaa_remove
};
static int __init dpaa_load(void)
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h
index 6f0e58a2a58a..9e1d44ae92cc 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h
@@ -56,7 +56,7 @@ DECLARE_EVENT_CLASS(dpaa_eth_fd,
__entry->fd_format = qm_fd_get_format(fd);
__entry->fd_offset = qm_fd_get_offset(fd);
__entry->fd_length = qm_fd_get_length(fd);
- __entry->fd_status = fd->status;
+ __entry->fd_status = __be32_to_cpu(fd->status);
__assign_str(name);
),
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
index b0060cf96090..9986f6e1f587 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -243,38 +243,24 @@ static void dpaa_get_ethtool_stats(struct net_device *net_dev,
static void dpaa_get_strings(struct net_device *net_dev, u32 stringset,
u8 *data)
{
- unsigned int i, j, num_cpus, size;
- char string_cpu[ETH_GSTRING_LEN];
- u8 *strings;
+ unsigned int i, j, num_cpus;
- memset(string_cpu, 0, sizeof(string_cpu));
- strings = data;
- num_cpus = num_online_cpus();
- size = DPAA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN;
+ num_cpus = num_online_cpus();
for (i = 0; i < DPAA_STATS_PERCPU_LEN; i++) {
- for (j = 0; j < num_cpus; j++) {
- snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]",
- dpaa_stats_percpu[i], j);
- memcpy(strings, string_cpu, ETH_GSTRING_LEN);
- strings += ETH_GSTRING_LEN;
- }
- snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]",
- dpaa_stats_percpu[i]);
- memcpy(strings, string_cpu, ETH_GSTRING_LEN);
- strings += ETH_GSTRING_LEN;
- }
- for (j = 0; j < num_cpus; j++) {
- snprintf(string_cpu, ETH_GSTRING_LEN,
- "bpool [CPU %d]", j);
- memcpy(strings, string_cpu, ETH_GSTRING_LEN);
- strings += ETH_GSTRING_LEN;
+ for (j = 0; j < num_cpus; j++)
+ ethtool_sprintf(&data, "%s [CPU %d]",
+ dpaa_stats_percpu[i], j);
+
+ ethtool_sprintf(&data, "%s [TOTAL]", dpaa_stats_percpu[i]);
}
- snprintf(string_cpu, ETH_GSTRING_LEN, "bpool [TOTAL]");
- memcpy(strings, string_cpu, ETH_GSTRING_LEN);
- strings += ETH_GSTRING_LEN;
+ for (i = 0; i < num_cpus; i++)
+ ethtool_sprintf(&data, "bpool [CPU %d]", i);
+
+ ethtool_puts(&data, "bpool [TOTAL]");
- memcpy(strings, dpaa_stats_global, size);
+ for (i = 0; i < DPAA_STATS_GLOBAL_LEN; i++)
+ ethtool_puts(&data, dpaa_stats_global[i]);
}
static int dpaa_get_hash_opts(struct net_device *dev,
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
index 7f476519b7ad..74ef77cb7078 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
@@ -217,20 +217,15 @@ static int dpaa2_eth_set_pauseparam(struct net_device *net_dev,
static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset,
u8 *data)
{
- u8 *p = data;
int i;
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0; i < DPAA2_ETH_NUM_STATS; i++) {
- strscpy(p, dpaa2_ethtool_stats[i], ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
- for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++) {
- strscpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
- dpaa2_mac_get_strings(p);
+ for (i = 0; i < DPAA2_ETH_NUM_STATS; i++)
+ ethtool_puts(&data, dpaa2_ethtool_stats[i]);
+ for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++)
+ ethtool_puts(&data, dpaa2_ethtool_extras[i]);
+ dpaa2_mac_get_strings(&data);
break;
}
}
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index a69bb22c37ea..422ce13a7c94 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -558,15 +558,12 @@ int dpaa2_mac_get_sset_count(void)
return DPAA2_MAC_NUM_STATS;
}
-void dpaa2_mac_get_strings(u8 *data)
+void dpaa2_mac_get_strings(u8 **data)
{
- u8 *p = data;
int i;
- for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
- strscpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < DPAA2_MAC_NUM_STATS; i++)
+ ethtool_puts(data, dpaa2_mac_ethtool_stats[i]);
}
void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data)
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
index c1ec9efd413a..53f8d106d11e 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
@@ -49,7 +49,7 @@ void dpaa2_mac_disconnect(struct dpaa2_mac *mac);
int dpaa2_mac_get_sset_count(void);
-void dpaa2_mac_get_strings(u8 *data);
+void dpaa2_mac_get_strings(u8 **data);
void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
index 6bc1988be311..a888f6e6e9b0 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
@@ -170,17 +170,16 @@ dpaa2_switch_ethtool_get_sset_count(struct net_device *netdev, int sset)
static void dpaa2_switch_ethtool_get_strings(struct net_device *netdev,
u32 stringset, u8 *data)
{
- u8 *p = data;
+ const char *str;
int i;
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < DPAA2_SWITCH_NUM_COUNTERS; i++) {
- memcpy(p, dpaa2_switch_ethtool_counters[i].name,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
+ str = dpaa2_switch_ethtool_counters[i].name;
+ ethtool_puts(&data, str);
}
- dpaa2_mac_get_strings(p);
+ dpaa2_mac_get_strings(&data);
break;
}
}
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index 4d75e6807e92..6c2779047dcd 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -7,6 +7,14 @@ config FSL_ENETC_CORE
If compiled as module (M), the module name is fsl-enetc-core.
+config NXP_ENETC_PF_COMMON
+ tristate
+ help
+ This module supports common functionality between drivers of
+ different versions of NXP ENETC PF controllers.
+
+ If compiled as module (M), the module name is nxp-enetc-pf-common.
+
config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI_MSI
@@ -14,6 +22,7 @@ config FSL_ENETC
select FSL_ENETC_CORE
select FSL_ENETC_IERB
select FSL_ENETC_MDIO
+ select NXP_ENETC_PF_COMMON
select PHYLINK
select PCS_LYNX
select DIMLIB
@@ -24,6 +33,23 @@ config FSL_ENETC
If compiled as module (M), the module name is fsl-enetc.
+config NXP_ENETC4
+ tristate "ENETC4 PF driver"
+ depends on PCI_MSI
+ select MDIO_DEVRES
+ select FSL_ENETC_CORE
+ select FSL_ENETC_MDIO
+ select NXP_ENETC_PF_COMMON
+ select PHYLINK
+ select DIMLIB
+ help
+ This driver supports NXP ENETC devices with major revision 4. ENETC is
+ as the NIC functionality in NETC, it supports virtualization/isolation
+ based on PCIe Single Root IO Virtualization (SR-IOV) and a full range
+ of TSN standards and NIC offload capabilities.
+
+ If compiled as module (M), the module name is nxp-enetc4.
+
config FSL_ENETC_VF
tristate "ENETC VF driver"
depends on PCI_MSI
@@ -75,3 +101,17 @@ config FSL_ENETC_QOS
enable/disable from user space via Qos commands(tc). In the kernel
side, it can be loaded by Qos driver. Currently, it is only support
taprio(802.1Qbv) and Credit Based Shaper(802.1Qbu).
+
+config NXP_NETC_BLK_CTRL
+ tristate "NETC blocks control driver"
+ help
+ This driver configures Integrated Endpoint Register Block (IERB) and
+ Privileged Register Block (PRB) of NETC. For i.MX platforms, it also
+ includes the configuration of NETCMIX block.
+ The IERB contains registers that are used for pre-boot initialization,
+ debug, and non-customer configuration. The PRB controls global reset
+ and global error handling for NETC. The NETCMIX block is mainly used
+ to set MII protocol and PCS protocol of the links, it also contains
+ settings for some other functions.
+
+ If compiled as module (M), the module name is nxp-netc-blk-ctrl.
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile
index b13cbbabb2ea..6fd27ee4fcd1 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -3,11 +3,17 @@
obj-$(CONFIG_FSL_ENETC_CORE) += fsl-enetc-core.o
fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
+obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
+nxp-enetc-pf-common-y := enetc_pf_common.o
+
obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
fsl-enetc-y := enetc_pf.o
fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
+obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
+nxp-enetc4-y := enetc4_pf.o
+
obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
fsl-enetc-vf-y := enetc_vf.o
@@ -19,3 +25,6 @@ fsl-enetc-mdio-y := enetc_pci_mdio.o enetc_mdio.o
obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o
fsl-enetc-ptp-y := enetc_ptp.o
+
+obj-$(CONFIG_NXP_NETC_BLK_CTRL) += nxp-netc-blk-ctrl.o
+nxp-netc-blk-ctrl-y := netc_blk_ctrl.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index c09370eab319..35634c516e26 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -3,6 +3,7 @@
#include "enetc.h"
#include <linux/bpf_trace.h>
+#include <linux/clk.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/vmalloc.h>
@@ -21,7 +22,7 @@ void enetc_port_mac_wr(struct enetc_si *si, u32 reg, u32 val)
{
enetc_port_wr(&si->hw, reg, val);
if (si->hw_features & ENETC_SI_F_QBU)
- enetc_port_wr(&si->hw, reg + ENETC_PMAC_OFFSET, val);
+ enetc_port_wr(&si->hw, reg + si->drvdata->pmac_offset, val);
}
EXPORT_SYMBOL_GPL(enetc_port_mac_wr);
@@ -700,8 +701,9 @@ static void enetc_rx_dim_work(struct work_struct *w)
net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
struct enetc_int_vector *v =
container_of(dim, struct enetc_int_vector, rx_dim);
+ struct enetc_ndev_priv *priv = netdev_priv(v->rx_ring.ndev);
- v->rx_ictt = enetc_usecs_to_cycles(moder.usec);
+ v->rx_ictt = enetc_usecs_to_cycles(moder.usec, priv->sysclk_freq);
dim->state = DIM_START_MEASURE;
}
@@ -718,7 +720,7 @@ static void enetc_rx_net_dim(struct enetc_int_vector *v)
v->rx_ring.stats.packets,
v->rx_ring.stats.bytes,
&dim_sample);
- net_dim(&v->rx_dim, dim_sample);
+ net_dim(&v->rx_dim, &dim_sample);
}
static int enetc_bd_ready_count(struct enetc_bdr *tx_ring, int ci)
@@ -1736,9 +1738,15 @@ void enetc_get_si_caps(struct enetc_si *si)
si->num_rx_rings = (val >> 16) & 0xff;
si->num_tx_rings = val & 0xff;
- val = enetc_rd(hw, ENETC_SIRFSCAPR);
- si->num_fs_entries = ENETC_SIRFSCAPR_GET_NUM_RFS(val);
- si->num_fs_entries = min(si->num_fs_entries, ENETC_MAX_RFS_SIZE);
+ val = enetc_rd(hw, ENETC_SIPCAPR0);
+ if (val & ENETC_SIPCAPR0_RFS) {
+ val = enetc_rd(hw, ENETC_SIRFSCAPR);
+ si->num_fs_entries = ENETC_SIRFSCAPR_GET_NUM_RFS(val);
+ si->num_fs_entries = min(si->num_fs_entries, ENETC_MAX_RFS_SIZE);
+ } else {
+ /* ENETC which not supports RFS */
+ si->num_fs_entries = 0;
+ }
si->num_rss = 0;
val = enetc_rd(hw, ENETC_SIPCAPR0);
@@ -2066,7 +2074,10 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
/* enable SI */
enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN);
- if (si->num_rss) {
+ /* TODO: RSS support for i.MX95 will be supported later, and the
+ * is_enetc_rev1() condition will be removed
+ */
+ if (si->num_rss && is_enetc_rev1(si)) {
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
@@ -2090,9 +2101,9 @@ void enetc_init_si_rings_params(struct enetc_ndev_priv *priv)
*/
priv->num_rx_rings = min_t(int, cpus, si->num_rx_rings);
priv->num_tx_rings = si->num_tx_rings;
- priv->bdr_int_num = cpus;
+ priv->bdr_int_num = priv->num_rx_rings;
priv->ic_mode = ENETC_IC_RX_ADAPTIVE | ENETC_IC_TX_MANUAL;
- priv->tx_ictt = ENETC_TXIC_TIMETHR;
+ priv->tx_ictt = enetc_usecs_to_cycles(600, priv->sysclk_freq);
}
EXPORT_SYMBOL_GPL(enetc_init_si_rings_params);
@@ -2501,10 +2512,14 @@ int enetc_open(struct net_device *ndev)
extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP);
- err = enetc_setup_irqs(priv);
+ err = clk_prepare_enable(priv->ref_clk);
if (err)
return err;
+ err = enetc_setup_irqs(priv);
+ if (err)
+ goto err_setup_irqs;
+
err = enetc_phylink_connect(ndev);
if (err)
goto err_phy_connect;
@@ -2536,6 +2551,8 @@ err_alloc_tx:
phylink_disconnect_phy(priv->phylink);
err_phy_connect:
enetc_free_irqs(priv);
+err_setup_irqs:
+ clk_disable_unprepare(priv->ref_clk);
return err;
}
@@ -2589,6 +2606,7 @@ int enetc_close(struct net_device *ndev)
enetc_assign_tx_resources(priv, NULL);
enetc_free_irqs(priv);
+ clk_disable_unprepare(priv->ref_clk);
return 0;
}
@@ -2995,13 +3013,99 @@ int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
}
EXPORT_SYMBOL_GPL(enetc_ioctl);
+static int enetc_int_vector_init(struct enetc_ndev_priv *priv, int i,
+ int v_tx_rings)
+{
+ struct enetc_int_vector *v;
+ struct enetc_bdr *bdr;
+ int j, err;
+
+ v = kzalloc(struct_size(v, tx_ring, v_tx_rings), GFP_KERNEL);
+ if (!v)
+ return -ENOMEM;
+
+ priv->int_vector[i] = v;
+ bdr = &v->rx_ring;
+ bdr->index = i;
+ bdr->ndev = priv->ndev;
+ bdr->dev = priv->dev;
+ bdr->bd_count = priv->rx_bd_count;
+ bdr->buffer_offset = ENETC_RXB_PAD;
+ priv->rx_ring[i] = bdr;
+
+ err = xdp_rxq_info_reg(&bdr->xdp.rxq, priv->ndev, i, 0);
+ if (err)
+ goto free_vector;
+
+ err = xdp_rxq_info_reg_mem_model(&bdr->xdp.rxq, MEM_TYPE_PAGE_SHARED,
+ NULL);
+ if (err) {
+ xdp_rxq_info_unreg(&bdr->xdp.rxq);
+ goto free_vector;
+ }
+
+ /* init defaults for adaptive IC */
+ if (priv->ic_mode & ENETC_IC_RX_ADAPTIVE) {
+ v->rx_ictt = 0x1;
+ v->rx_dim_en = true;
+ }
+
+ INIT_WORK(&v->rx_dim.work, enetc_rx_dim_work);
+ netif_napi_add(priv->ndev, &v->napi, enetc_poll);
+ v->count_tx_rings = v_tx_rings;
+
+ for (j = 0; j < v_tx_rings; j++) {
+ int idx;
+
+ /* default tx ring mapping policy */
+ idx = priv->bdr_int_num * j + i;
+ __set_bit(idx, &v->tx_rings_map);
+ bdr = &v->tx_ring[j];
+ bdr->index = idx;
+ bdr->ndev = priv->ndev;
+ bdr->dev = priv->dev;
+ bdr->bd_count = priv->tx_bd_count;
+ priv->tx_ring[idx] = bdr;
+ }
+
+ return 0;
+
+free_vector:
+ priv->rx_ring[i] = NULL;
+ priv->int_vector[i] = NULL;
+ kfree(v);
+
+ return err;
+}
+
+static void enetc_int_vector_destroy(struct enetc_ndev_priv *priv, int i)
+{
+ struct enetc_int_vector *v = priv->int_vector[i];
+ struct enetc_bdr *rx_ring = &v->rx_ring;
+ int j, tx_ring_index;
+
+ xdp_rxq_info_unreg_mem_model(&rx_ring->xdp.rxq);
+ xdp_rxq_info_unreg(&rx_ring->xdp.rxq);
+ netif_napi_del(&v->napi);
+ cancel_work_sync(&v->rx_dim.work);
+
+ for (j = 0; j < v->count_tx_rings; j++) {
+ tx_ring_index = priv->bdr_int_num * j + i;
+ priv->tx_ring[tx_ring_index] = NULL;
+ }
+
+ priv->rx_ring[i] = NULL;
+ priv->int_vector[i] = NULL;
+ kfree(v);
+}
+
int enetc_alloc_msix(struct enetc_ndev_priv *priv)
{
struct pci_dev *pdev = priv->si->pdev;
+ int v_tx_rings, v_remainder;
int num_stack_tx_queues;
int first_xdp_tx_ring;
int i, n, err, nvec;
- int v_tx_rings;
nvec = ENETC_BDR_INT_BASE_IDX + priv->bdr_int_num;
/* allocate MSIX for both messaging and Rx/Tx interrupts */
@@ -3015,64 +3119,17 @@ int enetc_alloc_msix(struct enetc_ndev_priv *priv)
/* # of tx rings per int vector */
v_tx_rings = priv->num_tx_rings / priv->bdr_int_num;
+ v_remainder = priv->num_tx_rings % priv->bdr_int_num;
for (i = 0; i < priv->bdr_int_num; i++) {
- struct enetc_int_vector *v;
- struct enetc_bdr *bdr;
- int j;
-
- v = kzalloc(struct_size(v, tx_ring, v_tx_rings), GFP_KERNEL);
- if (!v) {
- err = -ENOMEM;
- goto fail;
- }
-
- priv->int_vector[i] = v;
-
- bdr = &v->rx_ring;
- bdr->index = i;
- bdr->ndev = priv->ndev;
- bdr->dev = priv->dev;
- bdr->bd_count = priv->rx_bd_count;
- bdr->buffer_offset = ENETC_RXB_PAD;
- priv->rx_ring[i] = bdr;
-
- err = xdp_rxq_info_reg(&bdr->xdp.rxq, priv->ndev, i, 0);
- if (err) {
- kfree(v);
- goto fail;
- }
+ /* Distribute the remaining TX rings to the first v_remainder
+ * interrupt vectors
+ */
+ int num_tx_rings = i < v_remainder ? v_tx_rings + 1 : v_tx_rings;
- err = xdp_rxq_info_reg_mem_model(&bdr->xdp.rxq,
- MEM_TYPE_PAGE_SHARED, NULL);
- if (err) {
- xdp_rxq_info_unreg(&bdr->xdp.rxq);
- kfree(v);
+ err = enetc_int_vector_init(priv, i, num_tx_rings);
+ if (err)
goto fail;
- }
-
- /* init defaults for adaptive IC */
- if (priv->ic_mode & ENETC_IC_RX_ADAPTIVE) {
- v->rx_ictt = 0x1;
- v->rx_dim_en = true;
- }
- INIT_WORK(&v->rx_dim.work, enetc_rx_dim_work);
- netif_napi_add(priv->ndev, &v->napi, enetc_poll);
- v->count_tx_rings = v_tx_rings;
-
- for (j = 0; j < v_tx_rings; j++) {
- int idx;
-
- /* default tx ring mapping policy */
- idx = priv->bdr_int_num * j + i;
- __set_bit(idx, &v->tx_rings_map);
- bdr = &v->tx_ring[j];
- bdr->index = idx;
- bdr->ndev = priv->ndev;
- bdr->dev = priv->dev;
- bdr->bd_count = priv->tx_bd_count;
- priv->tx_ring[idx] = bdr;
- }
}
num_stack_tx_queues = enetc_num_stack_tx_queues(priv);
@@ -3092,16 +3149,8 @@ int enetc_alloc_msix(struct enetc_ndev_priv *priv)
return 0;
fail:
- while (i--) {
- struct enetc_int_vector *v = priv->int_vector[i];
- struct enetc_bdr *rx_ring = &v->rx_ring;
-
- xdp_rxq_info_unreg_mem_model(&rx_ring->xdp.rxq);
- xdp_rxq_info_unreg(&rx_ring->xdp.rxq);
- netif_napi_del(&v->napi);
- cancel_work_sync(&v->rx_dim.work);
- kfree(v);
- }
+ while (i--)
+ enetc_int_vector_destroy(priv, i);
pci_free_irq_vectors(pdev);
@@ -3113,26 +3162,8 @@ void enetc_free_msix(struct enetc_ndev_priv *priv)
{
int i;
- for (i = 0; i < priv->bdr_int_num; i++) {
- struct enetc_int_vector *v = priv->int_vector[i];
- struct enetc_bdr *rx_ring = &v->rx_ring;
-
- xdp_rxq_info_unreg_mem_model(&rx_ring->xdp.rxq);
- xdp_rxq_info_unreg(&rx_ring->xdp.rxq);
- netif_napi_del(&v->napi);
- cancel_work_sync(&v->rx_dim.work);
- }
-
- for (i = 0; i < priv->num_rx_rings; i++)
- priv->rx_ring[i] = NULL;
-
- for (i = 0; i < priv->num_tx_rings; i++)
- priv->tx_ring[i] = NULL;
-
- for (i = 0; i < priv->bdr_int_num; i++) {
- kfree(priv->int_vector[i]);
- priv->int_vector[i] = NULL;
- }
+ for (i = 0; i < priv->bdr_int_num; i++)
+ enetc_int_vector_destroy(priv, i);
/* disable all MSIX for this device */
pci_free_irq_vectors(priv->si->pdev);
@@ -3241,5 +3272,55 @@ void enetc_pci_remove(struct pci_dev *pdev)
}
EXPORT_SYMBOL_GPL(enetc_pci_remove);
+static const struct enetc_drvdata enetc_pf_data = {
+ .sysclk_freq = ENETC_CLK_400M,
+ .pmac_offset = ENETC_PMAC_OFFSET,
+ .eth_ops = &enetc_pf_ethtool_ops,
+};
+
+static const struct enetc_drvdata enetc4_pf_data = {
+ .sysclk_freq = ENETC_CLK_333M,
+ .pmac_offset = ENETC4_PMAC_OFFSET,
+ .eth_ops = &enetc4_pf_ethtool_ops,
+};
+
+static const struct enetc_drvdata enetc_vf_data = {
+ .sysclk_freq = ENETC_CLK_400M,
+ .eth_ops = &enetc_vf_ethtool_ops,
+};
+
+static const struct enetc_platform_info enetc_info[] = {
+ { .revision = ENETC_REV_1_0,
+ .dev_id = ENETC_DEV_ID_PF,
+ .data = &enetc_pf_data,
+ },
+ { .revision = ENETC_REV_4_1,
+ .dev_id = NXP_ENETC_PF_DEV_ID,
+ .data = &enetc4_pf_data,
+ },
+ { .revision = ENETC_REV_1_0,
+ .dev_id = ENETC_DEV_ID_VF,
+ .data = &enetc_vf_data,
+ },
+};
+
+int enetc_get_driver_data(struct enetc_si *si)
+{
+ u16 dev_id = si->pdev->device;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_info); i++) {
+ if (si->revision == enetc_info[i].revision &&
+ dev_id == enetc_info[i].dev_id) {
+ si->drvdata = enetc_info[i].data;
+
+ return 0;
+ }
+ }
+
+ return -ERANGE;
+}
+EXPORT_SYMBOL_GPL(enetc_get_driver_data);
+
MODULE_DESCRIPTION("NXP ENETC Ethernet driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index fb7d98d57783..72fa03dbc2dd 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -14,6 +14,7 @@
#include <net/xdp.h>
#include "enetc_hw.h"
+#include "enetc4_hw.h"
#define ENETC_MAC_MAXFRM_SIZE 9600
#define ENETC_MAX_MTU (ENETC_MAC_MAXFRM_SIZE - \
@@ -231,6 +232,18 @@ enum enetc_errata {
#define ENETC_SI_F_QBV BIT(1)
#define ENETC_SI_F_QBU BIT(2)
+struct enetc_drvdata {
+ u32 pmac_offset; /* Only valid for PSI which supports 802.1Qbu */
+ u64 sysclk_freq;
+ const struct ethtool_ops *eth_ops;
+};
+
+struct enetc_platform_info {
+ u16 revision;
+ u16 dev_id;
+ const struct enetc_drvdata *data;
+};
+
/* PCI IEP device data */
struct enetc_si {
struct pci_dev *pdev;
@@ -246,11 +259,18 @@ struct enetc_si {
int num_fs_entries;
int num_rss; /* number of RSS buckets */
unsigned short pad;
+ u16 revision;
int hw_features;
+ const struct enetc_drvdata *drvdata;
};
#define ENETC_SI_ALIGN 32
+static inline bool is_enetc_rev1(struct enetc_si *si)
+{
+ return si->pdev->revision == ENETC_REV1;
+}
+
static inline void *enetc_si_priv(const struct enetc_si *si)
{
return (char *)si + ALIGN(sizeof(struct enetc_si), ENETC_SI_ALIGN);
@@ -302,7 +322,7 @@ struct enetc_cls_rule {
int used;
};
-#define ENETC_MAX_BDR_INT 2 /* fixed to max # of available cpus */
+#define ENETC_MAX_BDR_INT 6 /* fixed to max # of available cpus */
struct psfp_cap {
u32 max_streamid;
u32 max_psfp_filter;
@@ -341,7 +361,6 @@ enum enetc_ic_mode {
#define ENETC_RXIC_PKTTHR min_t(u32, 256, ENETC_RX_RING_DEFAULT_SIZE / 2)
#define ENETC_TXIC_PKTTHR min_t(u32, 128, ENETC_TX_RING_DEFAULT_SIZE / 2)
-#define ENETC_TXIC_TIMETHR enetc_usecs_to_cycles(600)
struct enetc_ndev_priv {
struct net_device *ndev;
@@ -389,6 +408,9 @@ struct enetc_ndev_priv {
* and link state updates
*/
struct mutex mm_lock;
+
+ struct clk *ref_clk; /* RGMII/RMII reference clock */
+ u64 sysclk_freq; /* NETC system clock frequency */
};
/* Messaging */
@@ -418,6 +440,7 @@ void enetc_init_si_rings_params(struct enetc_ndev_priv *priv);
int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
void enetc_free_si_resources(struct enetc_ndev_priv *priv);
int enetc_configure_si(struct enetc_ndev_priv *priv);
+int enetc_get_driver_data(struct enetc_si *si);
int enetc_open(struct net_device *ndev);
int enetc_close(struct net_device *ndev);
@@ -434,6 +457,9 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
struct xdp_frame **frames, u32 flags);
/* ethtool */
+extern const struct ethtool_ops enetc_pf_ethtool_ops;
+extern const struct ethtool_ops enetc4_pf_ethtool_ops;
+extern const struct ethtool_ops enetc_vf_ethtool_ops;
void enetc_set_ethtool_ops(struct net_device *ndev);
void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link);
void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
new file mode 100644
index 000000000000..26b220677448
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * This header file defines the register offsets and bit fields
+ * of ENETC4 PF and VFs. Note that the same registers as ENETC
+ * version 1.0 are defined in the enetc_hw.h file.
+ *
+ * Copyright 2024 NXP
+ */
+#ifndef __ENETC4_HW_H_
+#define __ENETC4_HW_H_
+
+#define NXP_ENETC_VENDOR_ID 0x1131
+#define NXP_ENETC_PF_DEV_ID 0xe101
+
+/***************************ENETC port registers**************************/
+#define ENETC4_ECAPR0 0x0
+#define ECAPR0_RFS BIT(2)
+#define ECAPR0_TSD BIT(5)
+#define ECAPR0_RSS BIT(8)
+#define ECAPR0_RSC BIT(9)
+#define ECAPR0_LSO BIT(10)
+#define ECAPR0_WO BIT(13)
+
+#define ENETC4_ECAPR1 0x4
+#define ECAPR1_NUM_TCS GENMASK(6, 4)
+#define ECAPR1_NUM_MCH GENMASK(9, 8)
+#define ECAPR1_NUM_UCH GENMASK(11, 10)
+#define ECAPR1_NUM_MSIX GENMASK(22, 12)
+#define ECAPR1_NUM_VSI GENMASK(27, 24)
+#define ECAPR1_NUM_IPV BIT(31)
+
+#define ENETC4_ECAPR2 0x8
+#define ECAPR2_NUM_TX_BDR GENMASK(9, 0)
+#define ECAPR2_NUM_RX_BDR GENMASK(25, 16)
+
+#define ENETC4_PMR 0x10
+#define PMR_SI_EN(a) BIT((16 + (a)))
+
+/* Port Pause ON/OFF threshold register */
+#define ENETC4_PPAUONTR 0x108
+#define ENETC4_PPAUOFFTR 0x10c
+
+/* Port Station interface promiscuous MAC mode register */
+#define ENETC4_PSIPMMR 0x200
+#define PSIPMMR_SI_MAC_UP(a) BIT(a) /* a = SI index */
+#define PSIPMMR_SI_MAC_MP(a) BIT((a) + 16)
+
+/* Port Station interface promiscuous VLAN mode register */
+#define ENETC4_PSIPVMR 0x204
+
+/* Port RSS key register n. n = 0,1,2,...,9 */
+#define ENETC4_PRSSKR(n) ((n) * 0x4 + 0x250)
+
+/* Port station interface MAC address filtering capability register */
+#define ENETC4_PSIMAFCAPR 0x280
+#define PSIMAFCAPR_NUM_MAC_AFTE GENMASK(11, 0)
+
+/* Port station interface VLAN filtering capability register */
+#define ENETC4_PSIVLANFCAPR 0x2c0
+#define PSIVLANFCAPR_NUM_VLAN_FTE GENMASK(11, 0)
+
+/* Port station interface VLAN filtering mode register */
+#define ENETC4_PSIVLANFMR 0x2c4
+#define PSIVLANFMR_VS BIT(0)
+
+/* Port Station interface a primary MAC address registers */
+#define ENETC4_PSIPMAR0(a) ((a) * 0x80 + 0x2000)
+#define ENETC4_PSIPMAR1(a) ((a) * 0x80 + 0x2004)
+
+/* Port station interface a configuration register 0/2 */
+#define ENETC4_PSICFGR0(a) ((a) * 0x80 + 0x2010)
+#define PSICFGR0_VASE BIT(13)
+#define PSICFGR0_ASE BIT(15)
+#define PSICFGR0_ANTI_SPOOFING (PSICFGR0_VASE | PSICFGR0_ASE)
+
+#define ENETC4_PSICFGR2(a) ((a) * 0x80 + 0x2018)
+#define PSICFGR2_NUM_MSIX GENMASK(5, 0)
+
+#define ENETC4_PMCAPR 0x4004
+#define PMCAPR_HD BIT(8)
+#define PMCAPR_FP GENMASK(10, 9)
+
+/* Port configuration register */
+#define ENETC4_PCR 0x4010
+#define PCR_HDR_FMT BIT(0)
+#define PCR_L2DOSE BIT(4)
+#define PCR_TIMER_CS BIT(8)
+#define PCR_PSPEED GENMASK(29, 16)
+#define PCR_PSPEED_VAL(speed) (((speed) / 10 - 1) << 16)
+
+/* Port MAC address register 0/1 */
+#define ENETC4_PMAR0 0x4020
+#define ENETC4_PMAR1 0x4024
+
+/* Port operational register */
+#define ENETC4_POR 0x4100
+
+/* Port traffic class a transmit maximum SDU register */
+#define ENETC4_PTCTMSDUR(a) ((a) * 0x20 + 0x4208)
+#define PTCTMSDUR_MAXSDU GENMASK(15, 0)
+#define PTCTMSDUR_SDU_TYPE GENMASK(17, 16)
+#define SDU_TYPE_PPDU 0
+#define SDU_TYPE_MPDU 1
+#define SDU_TYPE_MSDU 2
+
+#define ENETC4_PMAC_OFFSET 0x400
+#define ENETC4_PM_CMD_CFG(mac) (0x5008 + (mac) * 0x400)
+#define PM_CMD_CFG_TX_EN BIT(0)
+#define PM_CMD_CFG_RX_EN BIT(1)
+#define PM_CMD_CFG_PAUSE_FWD BIT(7)
+#define PM_CMD_CFG_PAUSE_IGN BIT(8)
+#define PM_CMD_CFG_TX_ADDR_INS BIT(9)
+#define PM_CMD_CFG_LOOP_EN BIT(10)
+#define PM_CMD_CFG_LPBK_MODE GENMASK(12, 11)
+#define LPBCK_MODE_EXT_TX_CLK 0
+#define LPBCK_MODE_MAC_LEVEL 1
+#define LPBCK_MODE_INT_TX_CLK 2
+#define PM_CMD_CFG_CNT_FRM_EN BIT(13)
+#define PM_CMD_CFG_TXP BIT(15)
+#define PM_CMD_CFG_SEND_IDLE BIT(16)
+#define PM_CMD_CFG_HD_FCEN BIT(18)
+#define PM_CMD_CFG_SFD BIT(21)
+#define PM_CMD_CFG_TX_FLUSH BIT(22)
+#define PM_CMD_CFG_TX_LOWP_EN BIT(23)
+#define PM_CMD_CFG_RX_LOWP_EMPTY BIT(24)
+#define PM_CMD_CFG_SWR BIT(26)
+#define PM_CMD_CFG_TS_MODE BIT(30)
+#define PM_CMD_CFG_MG BIT(31)
+
+/* Port MAC 0/1 Maximum Frame Length Register */
+#define ENETC4_PM_MAXFRM(mac) (0x5014 + (mac) * 0x400)
+
+/* Port MAC 0/1 Pause Quanta Register */
+#define ENETC4_PM_PAUSE_QUANTA(mac) (0x5054 + (mac) * 0x400)
+
+/* Port MAC 0/1 Pause Quanta Threshold Register */
+#define ENETC4_PM_PAUSE_THRESH(mac) (0x5064 + (mac) * 0x400)
+
+/* Port MAC 0 Interface Mode Control Register */
+#define ENETC4_PM_IF_MODE(mac) (0x5300 + (mac) * 0x400)
+#define PM_IF_MODE_IFMODE GENMASK(2, 0)
+#define IFMODE_XGMII 0
+#define IFMODE_RMII 3
+#define IFMODE_RGMII 4
+#define IFMODE_SGMII 5
+#define PM_IF_MODE_REVMII BIT(3)
+#define PM_IF_MODE_M10 BIT(4)
+#define PM_IF_MODE_HD BIT(6)
+#define PM_IF_MODE_SSP GENMASK(14, 13)
+#define SSP_100M 0
+#define SSP_10M 1
+#define SSP_1G 2
+#define PM_IF_MODE_ENA BIT(15)
+
+#endif
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
new file mode 100644
index 000000000000..fc41078c4f5d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -0,0 +1,756 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2024 NXP */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/unaligned.h>
+
+#include "enetc_pf_common.h"
+
+#define ENETC_SI_MAX_RING_NUM 8
+
+static void enetc4_get_port_caps(struct enetc_pf *pf)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+ u32 val;
+
+ val = enetc_port_rd(hw, ENETC4_ECAPR1);
+ pf->caps.num_vsi = (val & ECAPR1_NUM_VSI) >> 24;
+ pf->caps.num_msix = ((val & ECAPR1_NUM_MSIX) >> 12) + 1;
+
+ val = enetc_port_rd(hw, ENETC4_ECAPR2);
+ pf->caps.num_rx_bdr = (val & ECAPR2_NUM_RX_BDR) >> 16;
+ pf->caps.num_tx_bdr = val & ECAPR2_NUM_TX_BDR;
+
+ val = enetc_port_rd(hw, ENETC4_PMCAPR);
+ pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+}
+
+static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
+ const u8 *addr)
+{
+ u16 lower = get_unaligned_le16(addr + 4);
+ u32 upper = get_unaligned_le32(addr);
+
+ if (si != 0) {
+ __raw_writel(upper, hw->port + ENETC4_PSIPMAR0(si));
+ __raw_writew(lower, hw->port + ENETC4_PSIPMAR1(si));
+ } else {
+ __raw_writel(upper, hw->port + ENETC4_PMAR0);
+ __raw_writew(lower, hw->port + ENETC4_PMAR1);
+ }
+}
+
+static void enetc4_pf_get_si_primary_mac(struct enetc_hw *hw, int si,
+ u8 *addr)
+{
+ u32 upper;
+ u16 lower;
+
+ upper = __raw_readl(hw->port + ENETC4_PSIPMAR0(si));
+ lower = __raw_readw(hw->port + ENETC4_PSIPMAR1(si));
+
+ put_unaligned_le32(upper, addr);
+ put_unaligned_le16(lower, addr + 4);
+}
+
+static const struct enetc_pf_ops enetc4_pf_ops = {
+ .set_si_primary_mac = enetc4_pf_set_si_primary_mac,
+ .get_si_primary_mac = enetc4_pf_get_si_primary_mac,
+};
+
+static int enetc4_pf_struct_init(struct enetc_si *si)
+{
+ struct enetc_pf *pf = enetc_si_priv(si);
+
+ pf->si = si;
+ pf->total_vfs = pci_sriov_get_totalvfs(si->pdev);
+ pf->ops = &enetc4_pf_ops;
+
+ enetc4_get_port_caps(pf);
+
+ return 0;
+}
+
+static u32 enetc4_psicfgr0_val_construct(bool is_vf, u32 num_tx_bdr, u32 num_rx_bdr)
+{
+ u32 val;
+
+ val = ENETC_PSICFGR0_SET_TXBDR(num_tx_bdr);
+ val |= ENETC_PSICFGR0_SET_RXBDR(num_rx_bdr);
+ val |= ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S);
+
+ if (is_vf)
+ val |= ENETC_PSICFGR0_VTE | ENETC_PSICFGR0_SIVIE;
+
+ return val;
+}
+
+static void enetc4_default_rings_allocation(struct enetc_pf *pf)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+ u32 num_rx_bdr, num_tx_bdr, val;
+ u32 vf_tx_bdr, vf_rx_bdr;
+ int i, rx_rem, tx_rem;
+
+ if (pf->caps.num_rx_bdr < ENETC_SI_MAX_RING_NUM + pf->caps.num_vsi)
+ num_rx_bdr = pf->caps.num_rx_bdr - pf->caps.num_vsi;
+ else
+ num_rx_bdr = ENETC_SI_MAX_RING_NUM;
+
+ if (pf->caps.num_tx_bdr < ENETC_SI_MAX_RING_NUM + pf->caps.num_vsi)
+ num_tx_bdr = pf->caps.num_tx_bdr - pf->caps.num_vsi;
+ else
+ num_tx_bdr = ENETC_SI_MAX_RING_NUM;
+
+ val = enetc4_psicfgr0_val_construct(false, num_tx_bdr, num_rx_bdr);
+ enetc_port_wr(hw, ENETC4_PSICFGR0(0), val);
+
+ num_rx_bdr = pf->caps.num_rx_bdr - num_rx_bdr;
+ rx_rem = num_rx_bdr % pf->caps.num_vsi;
+ num_rx_bdr = num_rx_bdr / pf->caps.num_vsi;
+
+ num_tx_bdr = pf->caps.num_tx_bdr - num_tx_bdr;
+ tx_rem = num_tx_bdr % pf->caps.num_vsi;
+ num_tx_bdr = num_tx_bdr / pf->caps.num_vsi;
+
+ for (i = 0; i < pf->caps.num_vsi; i++) {
+ vf_tx_bdr = (i < tx_rem) ? num_tx_bdr + 1 : num_tx_bdr;
+ vf_rx_bdr = (i < rx_rem) ? num_rx_bdr + 1 : num_rx_bdr;
+ val = enetc4_psicfgr0_val_construct(true, vf_tx_bdr, vf_rx_bdr);
+ enetc_port_wr(hw, ENETC4_PSICFGR0(i + 1), val);
+ }
+}
+
+static void enetc4_allocate_si_rings(struct enetc_pf *pf)
+{
+ enetc4_default_rings_allocation(pf);
+}
+
+static void enetc4_pf_set_si_vlan_promisc(struct enetc_hw *hw, int si, bool en)
+{
+ u32 val = enetc_port_rd(hw, ENETC4_PSIPVMR);
+
+ if (en)
+ val |= BIT(si);
+ else
+ val &= ~BIT(si);
+
+ enetc_port_wr(hw, ENETC4_PSIPVMR, val);
+}
+
+static void enetc4_set_default_si_vlan_promisc(struct enetc_pf *pf)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+ int num_si = pf->caps.num_vsi + 1;
+ int i;
+
+ /* enforce VLAN promiscuous mode for all SIs */
+ for (i = 0; i < num_si; i++)
+ enetc4_pf_set_si_vlan_promisc(hw, i, true);
+}
+
+/* Allocate the number of MSI-X vectors for per SI. */
+static void enetc4_set_si_msix_num(struct enetc_pf *pf)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+ int i, num_msix, total_si;
+ u32 val;
+
+ total_si = pf->caps.num_vsi + 1;
+
+ num_msix = pf->caps.num_msix / total_si +
+ pf->caps.num_msix % total_si - 1;
+ val = num_msix & PSICFGR2_NUM_MSIX;
+ enetc_port_wr(hw, ENETC4_PSICFGR2(0), val);
+
+ num_msix = pf->caps.num_msix / total_si - 1;
+ val = num_msix & PSICFGR2_NUM_MSIX;
+ for (i = 0; i < pf->caps.num_vsi; i++)
+ enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), val);
+}
+
+static void enetc4_enable_all_si(struct enetc_pf *pf)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+ int num_si = pf->caps.num_vsi + 1;
+ u32 si_bitmap = 0;
+ int i;
+
+ /* Master enable for all SIs */
+ for (i = 0; i < num_si; i++)
+ si_bitmap |= PMR_SI_EN(i);
+
+ enetc_port_wr(hw, ENETC4_PMR, si_bitmap);
+}
+
+static void enetc4_configure_port_si(struct enetc_pf *pf)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+
+ enetc4_allocate_si_rings(pf);
+
+ /* Outer VLAN tag will be used for VLAN filtering */
+ enetc_port_wr(hw, ENETC4_PSIVLANFMR, PSIVLANFMR_VS);
+
+ enetc4_set_default_si_vlan_promisc(pf);
+
+ /* Disable SI MAC multicast & unicast promiscuous */
+ enetc_port_wr(hw, ENETC4_PSIPMMR, 0);
+
+ enetc4_set_si_msix_num(pf);
+
+ enetc4_enable_all_si(pf);
+}
+
+static void enetc4_pf_reset_tc_msdu(struct enetc_hw *hw)
+{
+ u32 val = ENETC_MAC_MAXFRM_SIZE;
+ int tc;
+
+ val = u32_replace_bits(val, SDU_TYPE_MPDU, PTCTMSDUR_SDU_TYPE);
+
+ for (tc = 0; tc < ENETC_NUM_TC; tc++)
+ enetc_port_wr(hw, ENETC4_PTCTMSDUR(tc), val);
+}
+
+static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
+{
+ struct enetc_si *si = pf->si;
+
+ enetc_port_mac_wr(si, ENETC4_PM_MAXFRM(0),
+ ENETC_SET_MAXFRM(ENETC_MAC_MAXFRM_SIZE));
+
+ enetc4_pf_reset_tc_msdu(&si->hw);
+}
+
+static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
+{
+ int i;
+
+ for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+ enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
+}
+
+static void enetc4_set_default_rss_key(struct enetc_pf *pf)
+{
+ u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
+ struct enetc_hw *hw = &pf->si->hw;
+
+ /* set up hash key */
+ get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
+ enetc4_set_rss_key(hw, hash_key);
+}
+
+static void enetc4_enable_trx(struct enetc_pf *pf)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+
+ /* Enable port transmit/receive */
+ enetc_port_wr(hw, ENETC4_POR, 0);
+}
+
+static void enetc4_configure_port(struct enetc_pf *pf)
+{
+ enetc4_configure_port_si(pf);
+ enetc4_set_trx_frame_size(pf);
+ enetc4_set_default_rss_key(pf);
+ enetc4_enable_trx(pf);
+}
+
+static int enetc4_pf_init(struct enetc_pf *pf)
+{
+ struct device *dev = &pf->si->pdev->dev;
+ int err;
+
+ /* Initialize the MAC address for PF and VFs */
+ err = enetc_setup_mac_addresses(dev->of_node, pf);
+ if (err) {
+ dev_err(dev, "Failed to set MAC addresses\n");
+ return err;
+ }
+
+ enetc4_configure_port(pf);
+
+ return 0;
+}
+
+static const struct net_device_ops enetc4_ndev_ops = {
+ .ndo_open = enetc_open,
+ .ndo_stop = enetc_close,
+ .ndo_start_xmit = enetc_xmit,
+ .ndo_get_stats = enetc_get_stats,
+ .ndo_set_mac_address = enetc_pf_set_mac_addr,
+};
+
+static struct phylink_pcs *
+enetc4_pl_mac_select_pcs(struct phylink_config *config, phy_interface_t iface)
+{
+ struct enetc_pf *pf = phylink_to_enetc_pf(config);
+
+ return pf->pcs;
+}
+
+static void enetc4_mac_config(struct enetc_pf *pf, unsigned int mode,
+ phy_interface_t phy_mode)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(pf->si->ndev);
+ struct enetc_si *si = pf->si;
+ u32 val;
+
+ val = enetc_port_mac_rd(si, ENETC4_PM_IF_MODE(0));
+ val &= ~(PM_IF_MODE_IFMODE | PM_IF_MODE_ENA);
+
+ switch (phy_mode) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ val |= IFMODE_RGMII;
+ /* We need to enable auto-negotiation for the MAC
+ * if its RGMII interface support In-Band status.
+ */
+ if (phylink_autoneg_inband(mode))
+ val |= PM_IF_MODE_ENA;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ val |= IFMODE_RMII;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ val |= IFMODE_SGMII;
+ break;
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_XGMII:
+ case PHY_INTERFACE_MODE_USXGMII:
+ val |= IFMODE_XGMII;
+ break;
+ default:
+ dev_err(priv->dev,
+ "Unsupported PHY mode:%d\n", phy_mode);
+ return;
+ }
+
+ enetc_port_mac_wr(si, ENETC4_PM_IF_MODE(0), val);
+}
+
+static void enetc4_pl_mac_config(struct phylink_config *config, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct enetc_pf *pf = phylink_to_enetc_pf(config);
+
+ enetc4_mac_config(pf, mode, state->interface);
+}
+
+static void enetc4_set_port_speed(struct enetc_ndev_priv *priv, int speed)
+{
+ u32 old_speed = priv->speed;
+ u32 val;
+
+ if (speed == old_speed)
+ return;
+
+ val = enetc_port_rd(&priv->si->hw, ENETC4_PCR);
+ val &= ~PCR_PSPEED;
+
+ switch (speed) {
+ case SPEED_100:
+ case SPEED_1000:
+ case SPEED_2500:
+ case SPEED_10000:
+ val |= (PCR_PSPEED & PCR_PSPEED_VAL(speed));
+ break;
+ case SPEED_10:
+ default:
+ val |= (PCR_PSPEED & PCR_PSPEED_VAL(SPEED_10));
+ }
+
+ priv->speed = speed;
+ enetc_port_wr(&priv->si->hw, ENETC4_PCR, val);
+}
+
+static void enetc4_set_rgmii_mac(struct enetc_pf *pf, int speed, int duplex)
+{
+ struct enetc_si *si = pf->si;
+ u32 old_val, val;
+
+ old_val = enetc_port_mac_rd(si, ENETC4_PM_IF_MODE(0));
+ val = old_val & ~(PM_IF_MODE_ENA | PM_IF_MODE_M10 | PM_IF_MODE_REVMII);
+
+ switch (speed) {
+ case SPEED_1000:
+ val = u32_replace_bits(val, SSP_1G, PM_IF_MODE_SSP);
+ break;
+ case SPEED_100:
+ val = u32_replace_bits(val, SSP_100M, PM_IF_MODE_SSP);
+ break;
+ case SPEED_10:
+ val = u32_replace_bits(val, SSP_10M, PM_IF_MODE_SSP);
+ }
+
+ val = u32_replace_bits(val, duplex == DUPLEX_FULL ? 0 : 1,
+ PM_IF_MODE_HD);
+
+ if (val == old_val)
+ return;
+
+ enetc_port_mac_wr(si, ENETC4_PM_IF_MODE(0), val);
+}
+
+static void enetc4_set_rmii_mac(struct enetc_pf *pf, int speed, int duplex)
+{
+ struct enetc_si *si = pf->si;
+ u32 old_val, val;
+
+ old_val = enetc_port_mac_rd(si, ENETC4_PM_IF_MODE(0));
+ val = old_val & ~(PM_IF_MODE_ENA | PM_IF_MODE_SSP);
+
+ switch (speed) {
+ case SPEED_100:
+ val &= ~PM_IF_MODE_M10;
+ break;
+ case SPEED_10:
+ val |= PM_IF_MODE_M10;
+ }
+
+ val = u32_replace_bits(val, duplex == DUPLEX_FULL ? 0 : 1,
+ PM_IF_MODE_HD);
+
+ if (val == old_val)
+ return;
+
+ enetc_port_mac_wr(si, ENETC4_PM_IF_MODE(0), val);
+}
+
+static void enetc4_set_hd_flow_control(struct enetc_pf *pf, bool enable)
+{
+ struct enetc_si *si = pf->si;
+ u32 old_val, val;
+
+ if (!pf->caps.half_duplex)
+ return;
+
+ old_val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+ val = u32_replace_bits(old_val, enable ? 1 : 0, PM_CMD_CFG_HD_FCEN);
+ if (val == old_val)
+ return;
+
+ enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
+static void enetc4_set_rx_pause(struct enetc_pf *pf, bool rx_pause)
+{
+ struct enetc_si *si = pf->si;
+ u32 old_val, val;
+
+ old_val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+ val = u32_replace_bits(old_val, rx_pause ? 0 : 1, PM_CMD_CFG_PAUSE_IGN);
+ if (val == old_val)
+ return;
+
+ enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
+static void enetc4_set_tx_pause(struct enetc_pf *pf, int num_rxbdr, bool tx_pause)
+{
+ u32 pause_off_thresh = 0, pause_on_thresh = 0;
+ u32 init_quanta = 0, refresh_quanta = 0;
+ struct enetc_hw *hw = &pf->si->hw;
+ u32 rbmr, old_rbmr;
+ int i;
+
+ for (i = 0; i < num_rxbdr; i++) {
+ old_rbmr = enetc_rxbdr_rd(hw, i, ENETC_RBMR);
+ rbmr = u32_replace_bits(old_rbmr, tx_pause ? 1 : 0, ENETC_RBMR_CM);
+ if (rbmr == old_rbmr)
+ continue;
+
+ enetc_rxbdr_wr(hw, i, ENETC_RBMR, rbmr);
+ }
+
+ if (tx_pause) {
+ /* When the port first enters congestion, send a PAUSE request
+ * with the maximum number of quanta. When the port exits
+ * congestion, it will automatically send a PAUSE frame with
+ * zero quanta.
+ */
+ init_quanta = 0xffff;
+
+ /* Also, set up the refresh timer to send follow-up PAUSE
+ * frames at half the quanta value, in case the congestion
+ * condition persists.
+ */
+ refresh_quanta = 0xffff / 2;
+
+ /* Start emitting PAUSE frames when 3 large frames (or more
+ * smaller frames) have accumulated in the FIFO waiting to be
+ * DMAed to the RX ring.
+ */
+ pause_on_thresh = 3 * ENETC_MAC_MAXFRM_SIZE;
+ pause_off_thresh = 1 * ENETC_MAC_MAXFRM_SIZE;
+ }
+
+ enetc_port_mac_wr(pf->si, ENETC4_PM_PAUSE_QUANTA(0), init_quanta);
+ enetc_port_mac_wr(pf->si, ENETC4_PM_PAUSE_THRESH(0), refresh_quanta);
+ enetc_port_wr(hw, ENETC4_PPAUONTR, pause_on_thresh);
+ enetc_port_wr(hw, ENETC4_PPAUOFFTR, pause_off_thresh);
+}
+
+static void enetc4_enable_mac(struct enetc_pf *pf, bool en)
+{
+ struct enetc_si *si = pf->si;
+ u32 val;
+
+ val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+ val &= ~(PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN);
+ val |= en ? (PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN) : 0;
+
+ enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
+static void enetc4_pl_mac_link_up(struct phylink_config *config,
+ struct phy_device *phy, unsigned int mode,
+ phy_interface_t interface, int speed,
+ int duplex, bool tx_pause, bool rx_pause)
+{
+ struct enetc_pf *pf = phylink_to_enetc_pf(config);
+ struct enetc_si *si = pf->si;
+ struct enetc_ndev_priv *priv;
+ bool hd_fc = false;
+
+ priv = netdev_priv(si->ndev);
+ enetc4_set_port_speed(priv, speed);
+
+ if (!phylink_autoneg_inband(mode) &&
+ phy_interface_mode_is_rgmii(interface))
+ enetc4_set_rgmii_mac(pf, speed, duplex);
+
+ if (interface == PHY_INTERFACE_MODE_RMII)
+ enetc4_set_rmii_mac(pf, speed, duplex);
+
+ if (duplex == DUPLEX_FULL) {
+ /* When preemption is enabled, generation of PAUSE frames
+ * must be disabled, as stated in the IEEE 802.3 standard.
+ */
+ if (priv->active_offloads & ENETC_F_QBU)
+ tx_pause = false;
+ } else { /* DUPLEX_HALF */
+ if (tx_pause || rx_pause)
+ hd_fc = true;
+
+ /* As per 802.3 annex 31B, PAUSE frames are only supported
+ * when the link is configured for full duplex operation.
+ */
+ tx_pause = false;
+ rx_pause = false;
+ }
+
+ enetc4_set_hd_flow_control(pf, hd_fc);
+ enetc4_set_tx_pause(pf, priv->num_rx_rings, tx_pause);
+ enetc4_set_rx_pause(pf, rx_pause);
+ enetc4_enable_mac(pf, true);
+}
+
+static void enetc4_pl_mac_link_down(struct phylink_config *config,
+ unsigned int mode,
+ phy_interface_t interface)
+{
+ struct enetc_pf *pf = phylink_to_enetc_pf(config);
+
+ enetc4_enable_mac(pf, false);
+}
+
+static const struct phylink_mac_ops enetc_pl_mac_ops = {
+ .mac_select_pcs = enetc4_pl_mac_select_pcs,
+ .mac_config = enetc4_pl_mac_config,
+ .mac_link_up = enetc4_pl_mac_link_up,
+ .mac_link_down = enetc4_pl_mac_link_down,
+};
+
+static void enetc4_pci_remove(void *data)
+{
+ struct pci_dev *pdev = data;
+
+ enetc_pci_remove(pdev);
+}
+
+static int enetc4_link_init(struct enetc_ndev_priv *priv,
+ struct device_node *node)
+{
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct device *dev = priv->dev;
+ int err;
+
+ err = of_get_phy_mode(node, &pf->if_mode);
+ if (err) {
+ dev_err(dev, "Failed to get PHY mode\n");
+ return err;
+ }
+
+ err = enetc_mdiobus_create(pf, node);
+ if (err) {
+ dev_err(dev, "Failed to create MDIO bus\n");
+ return err;
+ }
+
+ err = enetc_phylink_create(priv, node, &enetc_pl_mac_ops);
+ if (err) {
+ dev_err(dev, "Failed to create phylink\n");
+ goto err_phylink_create;
+ }
+
+ return 0;
+
+err_phylink_create:
+ enetc_mdiobus_destroy(pf);
+
+ return err;
+}
+
+static void enetc4_link_deinit(struct enetc_ndev_priv *priv)
+{
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+
+ enetc_phylink_destroy(priv);
+ enetc_mdiobus_destroy(pf);
+}
+
+static int enetc4_pf_netdev_create(struct enetc_si *si)
+{
+ struct device *dev = &si->pdev->dev;
+ struct enetc_ndev_priv *priv;
+ struct net_device *ndev;
+ int err;
+
+ ndev = alloc_etherdev_mqs(sizeof(struct enetc_ndev_priv),
+ si->num_tx_rings, si->num_rx_rings);
+ if (!ndev)
+ return -ENOMEM;
+
+ priv = netdev_priv(ndev);
+ priv->ref_clk = devm_clk_get_optional(dev, "ref");
+ if (IS_ERR(priv->ref_clk)) {
+ dev_err(dev, "Get reference clock failed\n");
+ err = PTR_ERR(priv->ref_clk);
+ goto err_clk_get;
+ }
+
+ enetc_pf_netdev_setup(si, ndev, &enetc4_ndev_ops);
+
+ enetc_init_si_rings_params(priv);
+
+ err = enetc_configure_si(priv);
+ if (err) {
+ dev_err(dev, "Failed to configure SI\n");
+ goto err_config_si;
+ }
+
+ err = enetc_alloc_msix(priv);
+ if (err) {
+ dev_err(dev, "Failed to alloc MSI-X\n");
+ goto err_alloc_msix;
+ }
+
+ err = enetc4_link_init(priv, dev->of_node);
+ if (err)
+ goto err_link_init;
+
+ err = register_netdev(ndev);
+ if (err) {
+ dev_err(dev, "Failed to register netdev\n");
+ goto err_reg_netdev;
+ }
+
+ return 0;
+
+err_reg_netdev:
+ enetc4_link_deinit(priv);
+err_link_init:
+ enetc_free_msix(priv);
+err_alloc_msix:
+err_config_si:
+err_clk_get:
+ mutex_destroy(&priv->mm_lock);
+ free_netdev(ndev);
+
+ return err;
+}
+
+static void enetc4_pf_netdev_destroy(struct enetc_si *si)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(si->ndev);
+ struct net_device *ndev = si->ndev;
+
+ unregister_netdev(ndev);
+ enetc_free_msix(priv);
+ free_netdev(ndev);
+}
+
+static int enetc4_pf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ struct enetc_si *si;
+ struct enetc_pf *pf;
+ int err;
+
+ err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
+ if (err)
+ return dev_err_probe(dev, err, "PCIe probing failed\n");
+
+ err = devm_add_action_or_reset(dev, enetc4_pci_remove, pdev);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Add enetc4_pci_remove() action failed\n");
+
+ /* si is the private data. */
+ si = pci_get_drvdata(pdev);
+ if (!si->hw.port || !si->hw.global)
+ return dev_err_probe(dev, -ENODEV,
+ "Couldn't map PF only space\n");
+
+ si->revision = enetc_get_ip_revision(&si->hw);
+ err = enetc_get_driver_data(si);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Could not get VF driver data\n");
+
+ err = enetc4_pf_struct_init(si);
+ if (err)
+ return err;
+
+ pf = enetc_si_priv(si);
+ err = enetc4_pf_init(pf);
+ if (err)
+ return err;
+
+ enetc_get_si_caps(si);
+
+ return enetc4_pf_netdev_create(si);
+}
+
+static void enetc4_pf_remove(struct pci_dev *pdev)
+{
+ struct enetc_si *si = pci_get_drvdata(pdev);
+
+ enetc4_pf_netdev_destroy(si);
+}
+
+static const struct pci_device_id enetc4_pf_id_table[] = {
+ { PCI_DEVICE(NXP_ENETC_VENDOR_ID, NXP_ENETC_PF_DEV_ID) },
+ { 0, } /* End of table. */
+};
+MODULE_DEVICE_TABLE(pci, enetc4_pf_id_table);
+
+static struct pci_driver enetc4_pf_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = enetc4_pf_id_table,
+ .probe = enetc4_pf_probe,
+ .remove = enetc4_pf_remove,
+};
+module_pci_driver(enetc4_pf_driver);
+
+MODULE_DESCRIPTION("ENETC4 PF Driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 2563eb8ac7b6..bf34b5bb1e35 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -247,38 +247,25 @@ static int enetc_get_sset_count(struct net_device *ndev, int sset)
static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- u8 *p = data;
int i, j;
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++) {
- strscpy(p, enetc_si_counters[i].name, ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
- for (i = 0; i < priv->num_tx_rings; i++) {
- for (j = 0; j < ARRAY_SIZE(tx_ring_stats); j++) {
- snprintf(p, ETH_GSTRING_LEN, tx_ring_stats[j],
- i);
- p += ETH_GSTRING_LEN;
- }
- }
- for (i = 0; i < priv->num_rx_rings; i++) {
- for (j = 0; j < ARRAY_SIZE(rx_ring_stats); j++) {
- snprintf(p, ETH_GSTRING_LEN, rx_ring_stats[j],
- i);
- p += ETH_GSTRING_LEN;
- }
- }
+ for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++)
+ ethtool_puts(&data, enetc_si_counters[i].name);
+ for (i = 0; i < priv->num_tx_rings; i++)
+ for (j = 0; j < ARRAY_SIZE(tx_ring_stats); j++)
+ ethtool_sprintf(&data, tx_ring_stats[j], i);
+ for (i = 0; i < priv->num_rx_rings; i++)
+ for (j = 0; j < ARRAY_SIZE(rx_ring_stats); j++)
+ ethtool_sprintf(&data, rx_ring_stats[j], i);
if (!enetc_si_is_pf(priv->si))
break;
- for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) {
- strscpy(p, enetc_port_counters[i].name,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
+ ethtool_puts(&data, enetc_port_counters[i].name);
+
break;
}
}
@@ -775,9 +762,10 @@ static int enetc_get_coalesce(struct net_device *ndev,
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_int_vector *v = priv->int_vector[0];
+ u64 clk_freq = priv->sysclk_freq;
- ic->tx_coalesce_usecs = enetc_cycles_to_usecs(priv->tx_ictt);
- ic->rx_coalesce_usecs = enetc_cycles_to_usecs(v->rx_ictt);
+ ic->tx_coalesce_usecs = enetc_cycles_to_usecs(priv->tx_ictt, clk_freq);
+ ic->rx_coalesce_usecs = enetc_cycles_to_usecs(v->rx_ictt, clk_freq);
ic->tx_max_coalesced_frames = ENETC_TXIC_PKTTHR;
ic->rx_max_coalesced_frames = ENETC_RXIC_PKTTHR;
@@ -793,12 +781,13 @@ static int enetc_set_coalesce(struct net_device *ndev,
struct netlink_ext_ack *extack)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ u64 clk_freq = priv->sysclk_freq;
u32 rx_ictt, tx_ictt;
int i, ic_mode;
bool changed;
- tx_ictt = enetc_usecs_to_cycles(ic->tx_coalesce_usecs);
- rx_ictt = enetc_usecs_to_cycles(ic->rx_coalesce_usecs);
+ tx_ictt = enetc_usecs_to_cycles(ic->tx_coalesce_usecs, clk_freq);
+ rx_ictt = enetc_usecs_to_cycles(ic->rx_coalesce_usecs, clk_freq);
if (ic->rx_max_coalesced_frames != ENETC_RXIC_PKTTHR)
return -EOPNOTSUPP;
@@ -1178,7 +1167,7 @@ void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link)
}
EXPORT_SYMBOL_GPL(enetc_mm_link_state_update);
-static const struct ethtool_ops enetc_pf_ethtool_ops = {
+const struct ethtool_ops enetc_pf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
@@ -1213,7 +1202,7 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = {
.get_mm_stats = enetc_get_mm_stats,
};
-static const struct ethtool_ops enetc_vf_ethtool_ops = {
+const struct ethtool_ops enetc_vf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
@@ -1234,13 +1223,26 @@ static const struct ethtool_ops enetc_vf_ethtool_ops = {
.get_ts_info = enetc_get_ts_info,
};
+const struct ethtool_ops enetc4_pf_ethtool_ops = {
+ .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
+ ETHTOOL_COALESCE_MAX_FRAMES |
+ ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
+ .get_ringparam = enetc_get_ringparam,
+ .get_coalesce = enetc_get_coalesce,
+ .set_coalesce = enetc_set_coalesce,
+ .get_link_ksettings = enetc_get_link_ksettings,
+ .set_link_ksettings = enetc_set_link_ksettings,
+ .get_link = ethtool_op_get_link,
+ .get_wol = enetc_get_wol,
+ .set_wol = enetc_set_wol,
+ .get_pauseparam = enetc_get_pauseparam,
+ .set_pauseparam = enetc_set_pauseparam,
+};
+
void enetc_set_ethtool_ops(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- if (enetc_si_is_pf(priv->si))
- ndev->ethtool_ops = &enetc_pf_ethtool_ops;
- else
- ndev->ethtool_ops = &enetc_vf_ethtool_ops;
+ ndev->ethtool_ops = priv->si->drvdata->eth_ops;
}
EXPORT_SYMBOL_GPL(enetc_set_ethtool_ops);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 1619943fb263..7c3285584f8a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -6,6 +6,8 @@
#define ENETC_MM_VERIFY_SLEEP_US USEC_PER_MSEC
#define ENETC_MM_VERIFY_RETRIES 3
+#define ENETC_NUM_TC 8
+
/* ENETC device IDs */
#define ENETC_DEV_ID_PF 0xe100
#define ENETC_DEV_ID_VF 0xef00
@@ -25,6 +27,7 @@
#define ENETC_SIPCAPR0_RSS BIT(8)
#define ENETC_SIPCAPR0_QBV BIT(4)
#define ENETC_SIPCAPR0_QBU BIT(3)
+#define ENETC_SIPCAPR0_RFS BIT(2)
#define ENETC_SIPCAPR1 0x24
#define ENETC_SITGTGR 0x30
#define ENETC_SIRBGCR 0x38
@@ -368,6 +371,10 @@ enum enetc_bdr_type {TX, RX};
/** Global regs, offset: 2_0000h */
#define ENETC_GLOBAL_BASE 0x20000
#define ENETC_G_EIPBRR0 0x0bf8
+#define EIPBRR0_REVISION GENMASK(15, 0)
+#define ENETC_REV_1_0 0x0100
+#define ENETC_REV_4_1 0X0401
+
#define ENETC_G_EIPBRR1 0x0bfc
#define ENETC_G_EPFBLPR(n) (0xd00 + 4 * (n))
#define ENETC_G_EPFBLPR1_XGMII 0x80000000
@@ -396,18 +403,22 @@ struct enetc_hw {
*/
extern rwlock_t enetc_mdio_lock;
+DECLARE_STATIC_KEY_FALSE(enetc_has_err050089);
+
/* use this locking primitive only on the fast datapath to
* group together multiple non-MDIO register accesses to
* minimize the overhead of the lock
*/
static inline void enetc_lock_mdio(void)
{
- read_lock(&enetc_mdio_lock);
+ if (static_branch_unlikely(&enetc_has_err050089))
+ read_lock(&enetc_mdio_lock);
}
static inline void enetc_unlock_mdio(void)
{
- read_unlock(&enetc_mdio_lock);
+ if (static_branch_unlikely(&enetc_has_err050089))
+ read_unlock(&enetc_mdio_lock);
}
/* use these accessors only on the fast datapath under
@@ -416,14 +427,16 @@ static inline void enetc_unlock_mdio(void)
*/
static inline u32 enetc_rd_reg_hot(void __iomem *reg)
{
- lockdep_assert_held(&enetc_mdio_lock);
+ if (static_branch_unlikely(&enetc_has_err050089))
+ lockdep_assert_held(&enetc_mdio_lock);
return ioread32(reg);
}
static inline void enetc_wr_reg_hot(void __iomem *reg, u32 val)
{
- lockdep_assert_held(&enetc_mdio_lock);
+ if (static_branch_unlikely(&enetc_has_err050089))
+ lockdep_assert_held(&enetc_mdio_lock);
iowrite32(val, reg);
}
@@ -452,9 +465,13 @@ static inline u32 _enetc_rd_mdio_reg_wa(void __iomem *reg)
unsigned long flags;
u32 val;
- write_lock_irqsave(&enetc_mdio_lock, flags);
- val = ioread32(reg);
- write_unlock_irqrestore(&enetc_mdio_lock, flags);
+ if (static_branch_unlikely(&enetc_has_err050089)) {
+ write_lock_irqsave(&enetc_mdio_lock, flags);
+ val = ioread32(reg);
+ write_unlock_irqrestore(&enetc_mdio_lock, flags);
+ } else {
+ val = ioread32(reg);
+ }
return val;
}
@@ -463,9 +480,13 @@ static inline void _enetc_wr_mdio_reg_wa(void __iomem *reg, u32 val)
{
unsigned long flags;
- write_lock_irqsave(&enetc_mdio_lock, flags);
- iowrite32(val, reg);
- write_unlock_irqrestore(&enetc_mdio_lock, flags);
+ if (static_branch_unlikely(&enetc_has_err050089)) {
+ write_lock_irqsave(&enetc_mdio_lock, flags);
+ iowrite32(val, reg);
+ write_unlock_irqrestore(&enetc_mdio_lock, flags);
+ } else {
+ iowrite32(val, reg);
+ }
}
#ifdef ioread64
@@ -957,15 +978,17 @@ struct enetc_cbd {
u8 status_flags;
};
-#define ENETC_CLK 400000000ULL
-static inline u32 enetc_cycles_to_usecs(u32 cycles)
+#define ENETC_CLK_400M 400000000ULL
+#define ENETC_CLK_333M 333000000ULL
+
+static inline u32 enetc_cycles_to_usecs(u32 cycles, u64 clk_freq)
{
- return (u32)div_u64(cycles * 1000000ULL, ENETC_CLK);
+ return (u32)div_u64(cycles * 1000000ULL, clk_freq);
}
-static inline u32 enetc_usecs_to_cycles(u32 usecs)
+static inline u32 enetc_usecs_to_cycles(u32 usecs, u64 clk_freq)
{
- return (u32)div_u64(usecs * ENETC_CLK, 1000000ULL);
+ return (u32)div_u64(usecs * clk_freq, 1000000ULL);
}
/* Port traffic class frame preemption register */
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
index a1b595bd7993..e108cac8288d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
@@ -4,11 +4,35 @@
#include <linux/of_mdio.h>
#include "enetc_pf.h"
+#define NETC_EMDIO_VEN_ID 0x1131
+#define NETC_EMDIO_DEV_ID 0xee00
#define ENETC_MDIO_DEV_ID 0xee01
#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO"
#define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus"
#define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver"
+DEFINE_STATIC_KEY_FALSE(enetc_has_err050089);
+EXPORT_SYMBOL_GPL(enetc_has_err050089);
+
+static void enetc_emdio_enable_err050089(struct pci_dev *pdev)
+{
+ if (pdev->vendor == PCI_VENDOR_ID_FREESCALE &&
+ pdev->device == ENETC_MDIO_DEV_ID) {
+ static_branch_inc(&enetc_has_err050089);
+ dev_info(&pdev->dev, "Enabled ERR050089 workaround\n");
+ }
+}
+
+static void enetc_emdio_disable_err050089(struct pci_dev *pdev)
+{
+ if (pdev->vendor == PCI_VENDOR_ID_FREESCALE &&
+ pdev->device == ENETC_MDIO_DEV_ID) {
+ static_branch_dec(&enetc_has_err050089);
+ if (!static_key_enabled(&enetc_has_err050089.key))
+ dev_info(&pdev->dev, "Disabled ERR050089 workaround\n");
+ }
+}
+
static int enetc_pci_mdio_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -62,6 +86,8 @@ static int enetc_pci_mdio_probe(struct pci_dev *pdev,
goto err_pci_mem_reg;
}
+ enetc_emdio_enable_err050089(pdev);
+
err = of_mdiobus_register(bus, dev->of_node);
if (err)
goto err_mdiobus_reg;
@@ -71,6 +97,7 @@ static int enetc_pci_mdio_probe(struct pci_dev *pdev,
return 0;
err_mdiobus_reg:
+ enetc_emdio_disable_err050089(pdev);
pci_release_region(pdev, 0);
err_pci_mem_reg:
pci_disable_device(pdev);
@@ -88,6 +115,9 @@ static void enetc_pci_mdio_remove(struct pci_dev *pdev)
struct enetc_mdio_priv *mdio_priv;
mdiobus_unregister(bus);
+
+ enetc_emdio_disable_err050089(pdev);
+
mdio_priv = bus->priv;
iounmap(mdio_priv->hw->port);
pci_release_region(pdev, 0);
@@ -96,6 +126,7 @@ static void enetc_pci_mdio_remove(struct pci_dev *pdev)
static const struct pci_device_id enetc_pci_mdio_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
+ { PCI_DEVICE(NETC_EMDIO_VEN_ID, NETC_EMDIO_DEV_ID) },
{ 0, } /* End of table. */
};
MODULE_DEVICE_TABLE(pci, enetc_pci_mdio_id_table);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8f6b0bf48139..c47b4a743d93 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -2,15 +2,13 @@
/* Copyright 2017-2019 NXP */
#include <linux/unaligned.h>
-#include <linux/mdio.h>
#include <linux/module.h>
-#include <linux/fsl/enetc_mdio.h>
+#include <linux/of.h>
#include <linux/of_platform.h>
-#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/pcs-lynx.h>
#include "enetc_ierb.h"
-#include "enetc_pf.h"
+#include "enetc_pf_common.h"
#define ENETC_DRV_NAME_STR "ENETC PF driver"
@@ -33,18 +31,15 @@ static void enetc_pf_set_primary_mac_addr(struct enetc_hw *hw, int si,
__raw_writew(lower, hw->port + ENETC_PSIPMAR1(si));
}
-static int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr)
+static struct phylink_pcs *enetc_pf_create_pcs(struct enetc_pf *pf,
+ struct mii_bus *bus)
{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct sockaddr *saddr = addr;
-
- if (!is_valid_ether_addr(saddr->sa_data))
- return -EADDRNOTAVAIL;
-
- eth_hw_addr_set(ndev, saddr->sa_data);
- enetc_pf_set_primary_mac_addr(&priv->si->hw, 0, saddr->sa_data);
+ return lynx_pcs_create_mdiodev(bus, 0);
+}
- return 0;
+static void enetc_pf_destroy_pcs(struct phylink_pcs *pcs)
+{
+ lynx_pcs_destroy(pcs);
}
static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map)
@@ -393,56 +388,6 @@ static int enetc_pf_set_vf_spoofchk(struct net_device *ndev, int vf, bool en)
return 0;
}
-static int enetc_setup_mac_address(struct device_node *np, struct enetc_pf *pf,
- int si)
-{
- struct device *dev = &pf->si->pdev->dev;
- struct enetc_hw *hw = &pf->si->hw;
- u8 mac_addr[ETH_ALEN] = { 0 };
- int err;
-
- /* (1) try to get the MAC address from the device tree */
- if (np) {
- err = of_get_mac_address(np, mac_addr);
- if (err == -EPROBE_DEFER)
- return err;
- }
-
- /* (2) bootloader supplied MAC address */
- if (is_zero_ether_addr(mac_addr))
- enetc_pf_get_primary_mac_addr(hw, si, mac_addr);
-
- /* (3) choose a random one */
- if (is_zero_ether_addr(mac_addr)) {
- eth_random_addr(mac_addr);
- dev_info(dev, "no MAC address specified for SI%d, using %pM\n",
- si, mac_addr);
- }
-
- enetc_pf_set_primary_mac_addr(hw, si, mac_addr);
-
- return 0;
-}
-
-static int enetc_setup_mac_addresses(struct device_node *np,
- struct enetc_pf *pf)
-{
- int err, i;
-
- /* The PF might take its MAC from the device tree */
- err = enetc_setup_mac_address(np, pf, 0);
- if (err)
- return err;
-
- for (i = 0; i < pf->total_vfs; i++) {
- err = enetc_setup_mac_address(NULL, pf, i + 1);
- if (err)
- return err;
- }
-
- return 0;
-}
-
static void enetc_port_assign_rfs_entries(struct enetc_si *si)
{
struct enetc_pf *pf = enetc_si_priv(si);
@@ -665,19 +610,11 @@ static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (!num_vfs) {
enetc_msg_psi_free(pf);
- kfree(pf->vf_state);
pf->num_vfs = 0;
pci_disable_sriov(pdev);
} else {
pf->num_vfs = num_vfs;
- pf->vf_state = kcalloc(num_vfs, sizeof(struct enetc_vf_state),
- GFP_KERNEL);
- if (!pf->vf_state) {
- pf->num_vfs = 0;
- return -ENOMEM;
- }
-
err = enetc_msg_psi_init(pf);
if (err) {
dev_err(&pdev->dev, "enetc_msg_psi_init (%d)\n", err);
@@ -696,7 +633,6 @@ static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs)
err_en_sriov:
enetc_msg_psi_free(pf);
err_msg_psi:
- kfree(pf->vf_state);
pf->num_vfs = 0;
return err;
@@ -775,187 +711,6 @@ static const struct net_device_ops enetc_ndev_ops = {
.ndo_xdp_xmit = enetc_xdp_xmit,
};
-static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
- const struct net_device_ops *ndev_ops)
-{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
-
- SET_NETDEV_DEV(ndev, &si->pdev->dev);
- priv->ndev = ndev;
- priv->si = si;
- priv->dev = &si->pdev->dev;
- si->ndev = ndev;
-
- priv->msg_enable = (NETIF_MSG_WOL << 1) - 1;
- ndev->netdev_ops = ndev_ops;
- enetc_set_ethtool_ops(ndev);
- ndev->watchdog_timeo = 5 * HZ;
- ndev->max_mtu = ENETC_MAX_MTU;
-
- ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
- NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK |
- NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
- ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
- NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
- ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
- NETIF_F_TSO | NETIF_F_TSO6;
-
- if (si->num_rss)
- ndev->hw_features |= NETIF_F_RXHASH;
-
- ndev->priv_flags |= IFF_UNICAST_FLT;
- ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
- NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
- NETDEV_XDP_ACT_NDO_XMIT_SG;
-
- if (si->hw_features & ENETC_SI_F_PSFP && !enetc_psfp_enable(priv)) {
- priv->active_offloads |= ENETC_F_QCI;
- ndev->features |= NETIF_F_HW_TC;
- ndev->hw_features |= NETIF_F_HW_TC;
- }
-
- /* pick up primary MAC address from SI */
- enetc_load_primary_mac_addr(&si->hw, ndev);
-}
-
-static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np)
-{
- struct device *dev = &pf->si->pdev->dev;
- struct enetc_mdio_priv *mdio_priv;
- struct mii_bus *bus;
- int err;
-
- bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
- if (!bus)
- return -ENOMEM;
-
- bus->name = "Freescale ENETC MDIO Bus";
- bus->read = enetc_mdio_read_c22;
- bus->write = enetc_mdio_write_c22;
- bus->read_c45 = enetc_mdio_read_c45;
- bus->write_c45 = enetc_mdio_write_c45;
- bus->parent = dev;
- mdio_priv = bus->priv;
- mdio_priv->hw = &pf->si->hw;
- mdio_priv->mdio_base = ENETC_EMDIO_BASE;
- snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
-
- err = of_mdiobus_register(bus, np);
- if (err)
- return dev_err_probe(dev, err, "cannot register MDIO bus\n");
-
- pf->mdio = bus;
-
- return 0;
-}
-
-static void enetc_mdio_remove(struct enetc_pf *pf)
-{
- if (pf->mdio)
- mdiobus_unregister(pf->mdio);
-}
-
-static int enetc_imdio_create(struct enetc_pf *pf)
-{
- struct device *dev = &pf->si->pdev->dev;
- struct enetc_mdio_priv *mdio_priv;
- struct phylink_pcs *phylink_pcs;
- struct mii_bus *bus;
- int err;
-
- bus = mdiobus_alloc_size(sizeof(*mdio_priv));
- if (!bus)
- return -ENOMEM;
-
- bus->name = "Freescale ENETC internal MDIO Bus";
- bus->read = enetc_mdio_read_c22;
- bus->write = enetc_mdio_write_c22;
- bus->read_c45 = enetc_mdio_read_c45;
- bus->write_c45 = enetc_mdio_write_c45;
- bus->parent = dev;
- bus->phy_mask = ~0;
- mdio_priv = bus->priv;
- mdio_priv->hw = &pf->si->hw;
- mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE;
- snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
-
- err = mdiobus_register(bus);
- if (err) {
- dev_err(dev, "cannot register internal MDIO bus (%d)\n", err);
- goto free_mdio_bus;
- }
-
- phylink_pcs = lynx_pcs_create_mdiodev(bus, 0);
- if (IS_ERR(phylink_pcs)) {
- err = PTR_ERR(phylink_pcs);
- dev_err(dev, "cannot create lynx pcs (%d)\n", err);
- goto unregister_mdiobus;
- }
-
- pf->imdio = bus;
- pf->pcs = phylink_pcs;
-
- return 0;
-
-unregister_mdiobus:
- mdiobus_unregister(bus);
-free_mdio_bus:
- mdiobus_free(bus);
- return err;
-}
-
-static void enetc_imdio_remove(struct enetc_pf *pf)
-{
- if (pf->pcs)
- lynx_pcs_destroy(pf->pcs);
- if (pf->imdio) {
- mdiobus_unregister(pf->imdio);
- mdiobus_free(pf->imdio);
- }
-}
-
-static bool enetc_port_has_pcs(struct enetc_pf *pf)
-{
- return (pf->if_mode == PHY_INTERFACE_MODE_SGMII ||
- pf->if_mode == PHY_INTERFACE_MODE_1000BASEX ||
- pf->if_mode == PHY_INTERFACE_MODE_2500BASEX ||
- pf->if_mode == PHY_INTERFACE_MODE_USXGMII);
-}
-
-static int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node)
-{
- struct device_node *mdio_np;
- int err;
-
- mdio_np = of_get_child_by_name(node, "mdio");
- if (mdio_np) {
- err = enetc_mdio_probe(pf, mdio_np);
-
- of_node_put(mdio_np);
- if (err)
- return err;
- }
-
- if (enetc_port_has_pcs(pf)) {
- err = enetc_imdio_create(pf);
- if (err) {
- enetc_mdio_remove(pf);
- return err;
- }
- }
-
- return 0;
-}
-
-static void enetc_mdiobus_destroy(struct enetc_pf *pf)
-{
- enetc_mdio_remove(pf);
- enetc_imdio_remove(pf);
-}
-
static struct phylink_pcs *
enetc_pl_mac_select_pcs(struct phylink_config *config, phy_interface_t iface)
{
@@ -1101,47 +856,6 @@ static const struct phylink_mac_ops enetc_mac_phylink_ops = {
.mac_link_down = enetc_pl_mac_link_down,
};
-static int enetc_phylink_create(struct enetc_ndev_priv *priv,
- struct device_node *node)
-{
- struct enetc_pf *pf = enetc_si_priv(priv->si);
- struct phylink *phylink;
- int err;
-
- pf->phylink_config.dev = &priv->ndev->dev;
- pf->phylink_config.type = PHYLINK_NETDEV;
- pf->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
- MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
-
- __set_bit(PHY_INTERFACE_MODE_INTERNAL,
- pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_SGMII,
- pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_1000BASEX,
- pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_2500BASEX,
- pf->phylink_config.supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_USXGMII,
- pf->phylink_config.supported_interfaces);
- phy_interface_set_rgmii(pf->phylink_config.supported_interfaces);
-
- phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node),
- pf->if_mode, &enetc_mac_phylink_ops);
- if (IS_ERR(phylink)) {
- err = PTR_ERR(phylink);
- return err;
- }
-
- priv->phylink = phylink;
-
- return 0;
-}
-
-static void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
-{
- phylink_destroy(priv->phylink);
-}
-
/* Initialize the entire shared memory for the flow steering entries
* of this port (PF + VFs)
*/
@@ -1224,6 +938,13 @@ static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
goto out_pci_remove;
}
+ si->revision = enetc_get_ip_revision(&si->hw);
+ err = enetc_get_driver_data(si);
+ if (err) {
+ dev_err(&pdev->dev, "Could not get PF driver data\n");
+ goto out_pci_remove;
+ }
+
err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
&si->cbd_ring);
if (err)
@@ -1259,6 +980,14 @@ static void enetc_psi_destroy(struct pci_dev *pdev)
enetc_pci_remove(pdev);
}
+static const struct enetc_pf_ops enetc_pf_ops = {
+ .set_si_primary_mac = enetc_pf_set_primary_mac_addr,
+ .get_si_primary_mac = enetc_pf_get_primary_mac_addr,
+ .create_pcs = enetc_pf_create_pcs,
+ .destroy_pcs = enetc_pf_destroy_pcs,
+ .enable_psfp = enetc_psfp_enable,
+};
+
static int enetc_pf_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1285,7 +1014,15 @@ static int enetc_pf_probe(struct pci_dev *pdev,
pf = enetc_si_priv(si);
pf->si = si;
+ pf->ops = &enetc_pf_ops;
+
pf->total_vfs = pci_sriov_get_totalvfs(pdev);
+ if (pf->total_vfs) {
+ pf->vf_state = kcalloc(pf->total_vfs, sizeof(struct enetc_vf_state),
+ GFP_KERNEL);
+ if (!pf->vf_state)
+ goto err_alloc_vf_state;
+ }
err = enetc_setup_mac_addresses(node, pf);
if (err)
@@ -1338,7 +1075,7 @@ static int enetc_pf_probe(struct pci_dev *pdev,
if (err)
goto err_mdiobus_create;
- err = enetc_phylink_create(priv, node);
+ err = enetc_phylink_create(priv, node, &enetc_mac_phylink_ops);
if (err)
goto err_phylink_create;
@@ -1363,6 +1100,8 @@ err_alloc_si_res:
free_netdev(ndev);
err_alloc_netdev:
err_setup_mac_addresses:
+ kfree(pf->vf_state);
+err_alloc_vf_state:
enetc_psi_destroy(pdev);
err_psi_create:
return err;
@@ -1389,6 +1128,7 @@ static void enetc_pf_remove(struct pci_dev *pdev)
enetc_free_si_resources(priv);
free_netdev(si->ndev);
+ kfree(pf->vf_state);
enetc_psi_destroy(pdev);
}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index c26bd66e4597..a26a12863855 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -28,6 +28,24 @@ struct enetc_vf_state {
enum enetc_vf_flags flags;
};
+struct enetc_port_caps {
+ u32 half_duplex:1;
+ int num_vsi;
+ int num_msix;
+ int num_rx_bdr;
+ int num_tx_bdr;
+};
+
+struct enetc_pf;
+
+struct enetc_pf_ops {
+ void (*set_si_primary_mac)(struct enetc_hw *hw, int si, const u8 *addr);
+ void (*get_si_primary_mac)(struct enetc_hw *hw, int si, u8 *addr);
+ struct phylink_pcs *(*create_pcs)(struct enetc_pf *pf, struct mii_bus *bus);
+ void (*destroy_pcs)(struct phylink_pcs *pcs);
+ int (*enable_psfp)(struct enetc_ndev_priv *priv);
+};
+
struct enetc_pf {
struct enetc_si *si;
int num_vfs; /* number of active VFs, after sriov_init */
@@ -50,6 +68,9 @@ struct enetc_pf {
phy_interface_t if_mode;
struct phylink_config phylink_config;
+
+ struct enetc_port_caps caps;
+ const struct enetc_pf_ops *ops;
};
#define phylink_to_enetc_pf(config) \
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
new file mode 100644
index 000000000000..0eecfc833164
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/* Copyright 2024 NXP */
+
+#include <linux/fsl/enetc_mdio.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+
+#include "enetc_pf_common.h"
+
+static void enetc_set_si_hw_addr(struct enetc_pf *pf, int si,
+ const u8 *mac_addr)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+
+ pf->ops->set_si_primary_mac(hw, si, mac_addr);
+}
+
+static void enetc_get_si_hw_addr(struct enetc_pf *pf, int si, u8 *mac_addr)
+{
+ struct enetc_hw *hw = &pf->si->hw;
+
+ pf->ops->get_si_primary_mac(hw, si, mac_addr);
+}
+
+int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct sockaddr *saddr = addr;
+
+ if (!is_valid_ether_addr(saddr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ eth_hw_addr_set(ndev, saddr->sa_data);
+ enetc_set_si_hw_addr(pf, 0, saddr->sa_data);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_pf_set_mac_addr);
+
+static int enetc_setup_mac_address(struct device_node *np, struct enetc_pf *pf,
+ int si)
+{
+ struct device *dev = &pf->si->pdev->dev;
+ u8 mac_addr[ETH_ALEN] = { 0 };
+ int err;
+
+ /* (1) try to get the MAC address from the device tree */
+ if (np) {
+ err = of_get_mac_address(np, mac_addr);
+ if (err == -EPROBE_DEFER)
+ return err;
+ }
+
+ /* (2) bootloader supplied MAC address */
+ if (is_zero_ether_addr(mac_addr))
+ enetc_get_si_hw_addr(pf, si, mac_addr);
+
+ /* (3) choose a random one */
+ if (is_zero_ether_addr(mac_addr)) {
+ eth_random_addr(mac_addr);
+ dev_info(dev, "no MAC address specified for SI%d, using %pM\n",
+ si, mac_addr);
+ }
+
+ enetc_set_si_hw_addr(pf, si, mac_addr);
+
+ return 0;
+}
+
+int enetc_setup_mac_addresses(struct device_node *np, struct enetc_pf *pf)
+{
+ int err, i;
+
+ /* The PF might take its MAC from the device tree */
+ err = enetc_setup_mac_address(np, pf, 0);
+ if (err)
+ return err;
+
+ for (i = 0; i < pf->total_vfs; i++) {
+ err = enetc_setup_mac_address(NULL, pf, i + 1);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_setup_mac_addresses);
+
+void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
+ const struct net_device_ops *ndev_ops)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_pf *pf = enetc_si_priv(si);
+
+ SET_NETDEV_DEV(ndev, &si->pdev->dev);
+ priv->ndev = ndev;
+ priv->si = si;
+ priv->dev = &si->pdev->dev;
+ si->ndev = ndev;
+
+ priv->msg_enable = (NETIF_MSG_WOL << 1) - 1;
+ priv->sysclk_freq = si->drvdata->sysclk_freq;
+ ndev->netdev_ops = ndev_ops;
+ enetc_set_ethtool_ops(ndev);
+ ndev->watchdog_timeo = 5 * HZ;
+ ndev->max_mtu = ENETC_MAX_MTU;
+
+ ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
+ NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK |
+ NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+ ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+ ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
+ NETIF_F_TSO | NETIF_F_TSO6;
+
+ ndev->priv_flags |= IFF_UNICAST_FLT;
+
+ /* TODO: currently, i.MX95 ENETC driver does not support advanced features */
+ if (!is_enetc_rev1(si)) {
+ ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
+ goto end;
+ }
+
+ if (si->num_rss)
+ ndev->hw_features |= NETIF_F_RXHASH;
+
+ ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+ NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
+ NETDEV_XDP_ACT_NDO_XMIT_SG;
+
+ if (si->hw_features & ENETC_SI_F_PSFP && pf->ops->enable_psfp &&
+ !pf->ops->enable_psfp(priv)) {
+ priv->active_offloads |= ENETC_F_QCI;
+ ndev->features |= NETIF_F_HW_TC;
+ ndev->hw_features |= NETIF_F_HW_TC;
+ }
+
+end:
+ /* pick up primary MAC address from SI */
+ enetc_load_primary_mac_addr(&si->hw, ndev);
+}
+EXPORT_SYMBOL_GPL(enetc_pf_netdev_setup);
+
+static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np)
+{
+ struct device *dev = &pf->si->pdev->dev;
+ struct enetc_mdio_priv *mdio_priv;
+ struct mii_bus *bus;
+ int err;
+
+ bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = "Freescale ENETC MDIO Bus";
+ bus->read = enetc_mdio_read_c22;
+ bus->write = enetc_mdio_write_c22;
+ bus->read_c45 = enetc_mdio_read_c45;
+ bus->write_c45 = enetc_mdio_write_c45;
+ bus->parent = dev;
+ mdio_priv = bus->priv;
+ mdio_priv->hw = &pf->si->hw;
+ mdio_priv->mdio_base = ENETC_EMDIO_BASE;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
+
+ err = of_mdiobus_register(bus, np);
+ if (err)
+ return dev_err_probe(dev, err, "cannot register MDIO bus\n");
+
+ pf->mdio = bus;
+
+ return 0;
+}
+
+static void enetc_mdio_remove(struct enetc_pf *pf)
+{
+ if (pf->mdio)
+ mdiobus_unregister(pf->mdio);
+}
+
+static int enetc_imdio_create(struct enetc_pf *pf)
+{
+ struct device *dev = &pf->si->pdev->dev;
+ struct enetc_mdio_priv *mdio_priv;
+ struct phylink_pcs *phylink_pcs;
+ struct mii_bus *bus;
+ int err;
+
+ if (!pf->ops->create_pcs) {
+ dev_err(dev, "Creating PCS is not supported\n");
+
+ return -EOPNOTSUPP;
+ }
+
+ bus = mdiobus_alloc_size(sizeof(*mdio_priv));
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = "Freescale ENETC internal MDIO Bus";
+ bus->read = enetc_mdio_read_c22;
+ bus->write = enetc_mdio_write_c22;
+ bus->read_c45 = enetc_mdio_read_c45;
+ bus->write_c45 = enetc_mdio_write_c45;
+ bus->parent = dev;
+ bus->phy_mask = ~0;
+ mdio_priv = bus->priv;
+ mdio_priv->hw = &pf->si->hw;
+ mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
+
+ err = mdiobus_register(bus);
+ if (err) {
+ dev_err(dev, "cannot register internal MDIO bus (%d)\n", err);
+ goto free_mdio_bus;
+ }
+
+ phylink_pcs = pf->ops->create_pcs(pf, bus);
+ if (IS_ERR(phylink_pcs)) {
+ err = PTR_ERR(phylink_pcs);
+ dev_err(dev, "cannot create lynx pcs (%d)\n", err);
+ goto unregister_mdiobus;
+ }
+
+ pf->imdio = bus;
+ pf->pcs = phylink_pcs;
+
+ return 0;
+
+unregister_mdiobus:
+ mdiobus_unregister(bus);
+free_mdio_bus:
+ mdiobus_free(bus);
+ return err;
+}
+
+static void enetc_imdio_remove(struct enetc_pf *pf)
+{
+ if (pf->pcs && pf->ops->destroy_pcs)
+ pf->ops->destroy_pcs(pf->pcs);
+
+ if (pf->imdio) {
+ mdiobus_unregister(pf->imdio);
+ mdiobus_free(pf->imdio);
+ }
+}
+
+static bool enetc_port_has_pcs(struct enetc_pf *pf)
+{
+ return (pf->if_mode == PHY_INTERFACE_MODE_SGMII ||
+ pf->if_mode == PHY_INTERFACE_MODE_1000BASEX ||
+ pf->if_mode == PHY_INTERFACE_MODE_2500BASEX ||
+ pf->if_mode == PHY_INTERFACE_MODE_USXGMII);
+}
+
+int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node)
+{
+ struct device_node *mdio_np;
+ int err;
+
+ mdio_np = of_get_child_by_name(node, "mdio");
+ if (mdio_np) {
+ err = enetc_mdio_probe(pf, mdio_np);
+
+ of_node_put(mdio_np);
+ if (err)
+ return err;
+ }
+
+ if (enetc_port_has_pcs(pf)) {
+ err = enetc_imdio_create(pf);
+ if (err) {
+ enetc_mdio_remove(pf);
+ return err;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_mdiobus_create);
+
+void enetc_mdiobus_destroy(struct enetc_pf *pf)
+{
+ enetc_mdio_remove(pf);
+ enetc_imdio_remove(pf);
+}
+EXPORT_SYMBOL_GPL(enetc_mdiobus_destroy);
+
+int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
+ const struct phylink_mac_ops *ops)
+{
+ struct enetc_pf *pf = enetc_si_priv(priv->si);
+ struct phylink *phylink;
+ int err;
+
+ pf->phylink_config.dev = &priv->ndev->dev;
+ pf->phylink_config.type = PHYLINK_NETDEV;
+ pf->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
+
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ pf->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_SGMII,
+ pf->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX,
+ pf->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX,
+ pf->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_USXGMII,
+ pf->phylink_config.supported_interfaces);
+ phy_interface_set_rgmii(pf->phylink_config.supported_interfaces);
+
+ phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node),
+ pf->if_mode, ops);
+ if (IS_ERR(phylink)) {
+ err = PTR_ERR(phylink);
+ return err;
+ }
+
+ priv->phylink = phylink;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_phylink_create);
+
+void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
+{
+ phylink_destroy(priv->phylink);
+}
+EXPORT_SYMBOL_GPL(enetc_phylink_destroy);
+
+MODULE_DESCRIPTION("NXP ENETC PF common functionality driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
new file mode 100644
index 000000000000..48f55ee743ad
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright 2024 NXP */
+
+#include "enetc_pf.h"
+
+int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr);
+int enetc_setup_mac_addresses(struct device_node *np, struct enetc_pf *pf);
+void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
+ const struct net_device_ops *ndev_ops);
+int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node);
+void enetc_mdiobus_destroy(struct enetc_pf *pf);
+int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node,
+ const struct phylink_mac_ops *ops);
+void enetc_phylink_destroy(struct enetc_ndev_priv *priv);
+
+static inline u16 enetc_get_ip_revision(struct enetc_hw *hw)
+{
+ return enetc_global_rd(hw, ENETC_G_EIPBRR0) & EIPBRR0_REVISION;
+}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
index b65da49dd926..ccf86651455c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
@@ -336,7 +336,7 @@ int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data)
*
* (enetClockFrequency / portTransmitRate) * 100
*/
- hi_credit_reg = (u32)div_u64((ENETC_CLK * 100ULL) * hi_credit_bit,
+ hi_credit_reg = (u32)div_u64((priv->sysclk_freq * 100ULL) * hi_credit_bit,
port_transmit_rate * 1000000ULL);
enetc_port_wr(hw, ENETC_PTCCBSR1(tc), hi_credit_reg);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index dfcaac302e24..a5f8ce576b6e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -78,11 +78,18 @@ static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct sockaddr *saddr = addr;
+ int err;
if (!is_valid_ether_addr(saddr->sa_data))
return -EADDRNOTAVAIL;
- return enetc_msg_vsi_set_primary_mac_addr(priv, saddr);
+ err = enetc_msg_vsi_set_primary_mac_addr(priv, saddr);
+ if (err)
+ return err;
+
+ eth_hw_addr_set(ndev, saddr->sa_data);
+
+ return 0;
}
static int enetc_vf_set_features(struct net_device *ndev,
@@ -128,6 +135,7 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
si->ndev = ndev;
priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
+ priv->sysclk_freq = si->drvdata->sysclk_freq;
ndev->netdev_ops = ndev_ops;
enetc_set_ethtool_ops(ndev);
ndev->watchdog_timeo = 5 * HZ;
@@ -164,6 +172,13 @@ static int enetc_vf_probe(struct pci_dev *pdev,
return dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
si = pci_get_drvdata(pdev);
+ si->revision = ENETC_REV_1_0;
+ err = enetc_get_driver_data(si);
+ if (err) {
+ dev_err_probe(&pdev->dev, err,
+ "Could not get VF driver data\n");
+ goto err_alloc_netdev;
+ }
enetc_get_si_caps(si);
diff --git a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
new file mode 100644
index 000000000000..bcb8eefeb93c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
@@ -0,0 +1,445 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NXP NETC Blocks Control Driver
+ *
+ * Copyright 2024 NXP
+ *
+ * This driver is used for pre-initialization of NETC, such as PCS and MII
+ * protocols, LDID, warm reset, etc. Therefore, all NETC device drivers can
+ * only be probed after the netc-blk-crtl driver has completed initialization.
+ * In addition, when the system enters suspend mode, IERB, PRB, and NETCMIX
+ * will be powered off, except for WOL. Therefore, when the system resumes,
+ * these blocks need to be reinitialized.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/fsl/netc_global.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+/* NETCMIX registers */
+#define IMX95_CFG_LINK_IO_VAR 0x0
+#define IO_VAR_16FF_16G_SERDES 0x1
+#define IO_VAR(port, var) (((var) & 0xf) << ((port) << 2))
+
+#define IMX95_CFG_LINK_MII_PROT 0x4
+#define CFG_LINK_MII_PORT_0 GENMASK(3, 0)
+#define CFG_LINK_MII_PORT_1 GENMASK(7, 4)
+#define MII_PROT_MII 0x0
+#define MII_PROT_RMII 0x1
+#define MII_PROT_RGMII 0x2
+#define MII_PROT_SERIAL 0x3
+#define MII_PROT(port, prot) (((prot) & 0xf) << ((port) << 2))
+
+#define IMX95_CFG_LINK_PCS_PROT(a) (0x8 + (a) * 4)
+#define PCS_PROT_1G_SGMII BIT(0)
+#define PCS_PROT_2500M_SGMII BIT(1)
+#define PCS_PROT_XFI BIT(3)
+#define PCS_PROT_SFI BIT(4)
+#define PCS_PROT_10G_SXGMII BIT(6)
+
+/* NETC privileged register block register */
+#define PRB_NETCRR 0x100
+#define NETCRR_SR BIT(0)
+#define NETCRR_LOCK BIT(1)
+
+#define PRB_NETCSR 0x104
+#define NETCSR_ERROR BIT(0)
+#define NETCSR_STATE BIT(1)
+
+/* NETC integrated endpoint register block register */
+#define IERB_EMDIOFAUXR 0x344
+#define IERB_T0FAUXR 0x444
+#define IERB_EFAUXR(a) (0x3044 + 0x100 * (a))
+#define IERB_VFAUXR(a) (0x4004 + 0x40 * (a))
+#define FAUXR_LDID GENMASK(3, 0)
+
+/* Platform information */
+#define IMX95_ENETC0_BUS_DEVFN 0x0
+#define IMX95_ENETC1_BUS_DEVFN 0x40
+#define IMX95_ENETC2_BUS_DEVFN 0x80
+
+/* Flags for different platforms */
+#define NETC_HAS_NETCMIX BIT(0)
+
+struct netc_devinfo {
+ u32 flags;
+ int (*netcmix_init)(struct platform_device *pdev);
+ int (*ierb_init)(struct platform_device *pdev);
+};
+
+struct netc_blk_ctrl {
+ void __iomem *prb;
+ void __iomem *ierb;
+ void __iomem *netcmix;
+
+ const struct netc_devinfo *devinfo;
+ struct platform_device *pdev;
+ struct dentry *debugfs_root;
+};
+
+static void netc_reg_write(void __iomem *base, u32 offset, u32 val)
+{
+ netc_write(base + offset, val);
+}
+
+static u32 netc_reg_read(void __iomem *base, u32 offset)
+{
+ return netc_read(base + offset);
+}
+
+static int netc_of_pci_get_bus_devfn(struct device_node *np)
+{
+ u32 reg[5];
+ int error;
+
+ error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
+ if (error)
+ return error;
+
+ return (reg[0] >> 8) & 0xffff;
+}
+
+static int netc_get_link_mii_protocol(phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_MII:
+ return MII_PROT_MII;
+ case PHY_INTERFACE_MODE_RMII:
+ return MII_PROT_RMII;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ return MII_PROT_RGMII;
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_XGMII:
+ case PHY_INTERFACE_MODE_USXGMII:
+ return MII_PROT_SERIAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int imx95_netcmix_init(struct platform_device *pdev)
+{
+ struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+ struct device_node *np = pdev->dev.of_node;
+ phy_interface_t interface;
+ int bus_devfn, mii_proto;
+ u32 val;
+ int err;
+
+ /* Default setting of MII protocol */
+ val = MII_PROT(0, MII_PROT_RGMII) | MII_PROT(1, MII_PROT_RGMII) |
+ MII_PROT(2, MII_PROT_SERIAL);
+
+ /* Update the link MII protocol through parsing phy-mode */
+ for_each_available_child_of_node_scoped(np, child) {
+ for_each_available_child_of_node_scoped(child, gchild) {
+ if (!of_device_is_compatible(gchild, "pci1131,e101"))
+ continue;
+
+ bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+ if (bus_devfn < 0)
+ return -EINVAL;
+
+ if (bus_devfn == IMX95_ENETC2_BUS_DEVFN)
+ continue;
+
+ err = of_get_phy_mode(gchild, &interface);
+ if (err)
+ continue;
+
+ mii_proto = netc_get_link_mii_protocol(interface);
+ if (mii_proto < 0)
+ return -EINVAL;
+
+ switch (bus_devfn) {
+ case IMX95_ENETC0_BUS_DEVFN:
+ val = u32_replace_bits(val, mii_proto,
+ CFG_LINK_MII_PORT_0);
+ break;
+ case IMX95_ENETC1_BUS_DEVFN:
+ val = u32_replace_bits(val, mii_proto,
+ CFG_LINK_MII_PORT_1);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ }
+
+ /* Configure Link I/O variant */
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_IO_VAR,
+ IO_VAR(2, IO_VAR_16FF_16G_SERDES));
+ /* Configure Link 2 PCS protocol */
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_PCS_PROT(2),
+ PCS_PROT_10G_SXGMII);
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_MII_PROT, val);
+
+ return 0;
+}
+
+static bool netc_ierb_is_locked(struct netc_blk_ctrl *priv)
+{
+ return !!(netc_reg_read(priv->prb, PRB_NETCRR) & NETCRR_LOCK);
+}
+
+static int netc_lock_ierb(struct netc_blk_ctrl *priv)
+{
+ u32 val;
+
+ netc_reg_write(priv->prb, PRB_NETCRR, NETCRR_LOCK);
+
+ return read_poll_timeout(netc_reg_read, val, !(val & NETCSR_STATE),
+ 100, 2000, false, priv->prb, PRB_NETCSR);
+}
+
+static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv)
+{
+ u32 val;
+
+ netc_reg_write(priv->prb, PRB_NETCRR, 0);
+
+ return read_poll_timeout(netc_reg_read, val, !(val & NETCRR_LOCK),
+ 1000, 100000, true, priv->prb, PRB_NETCRR);
+}
+
+static int imx95_ierb_init(struct platform_device *pdev)
+{
+ struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+
+ /* EMDIO : No MSI-X intterupt */
+ netc_reg_write(priv->ierb, IERB_EMDIOFAUXR, 0);
+ /* ENETC0 PF */
+ netc_reg_write(priv->ierb, IERB_EFAUXR(0), 0);
+ /* ENETC0 VF0 */
+ netc_reg_write(priv->ierb, IERB_VFAUXR(0), 1);
+ /* ENETC0 VF1 */
+ netc_reg_write(priv->ierb, IERB_VFAUXR(1), 2);
+ /* ENETC1 PF */
+ netc_reg_write(priv->ierb, IERB_EFAUXR(1), 3);
+ /* ENETC1 VF0 */
+ netc_reg_write(priv->ierb, IERB_VFAUXR(2), 5);
+ /* ENETC1 VF1 */
+ netc_reg_write(priv->ierb, IERB_VFAUXR(3), 6);
+ /* ENETC2 PF */
+ netc_reg_write(priv->ierb, IERB_EFAUXR(2), 4);
+ /* ENETC2 VF0 */
+ netc_reg_write(priv->ierb, IERB_VFAUXR(4), 5);
+ /* ENETC2 VF1 */
+ netc_reg_write(priv->ierb, IERB_VFAUXR(5), 6);
+ /* NETC TIMER */
+ netc_reg_write(priv->ierb, IERB_T0FAUXR, 7);
+
+ return 0;
+}
+
+static int netc_ierb_init(struct platform_device *pdev)
+{
+ struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+ const struct netc_devinfo *devinfo = priv->devinfo;
+ int err;
+
+ if (netc_ierb_is_locked(priv)) {
+ err = netc_unlock_ierb_with_warm_reset(priv);
+ if (err) {
+ dev_err(&pdev->dev, "Unlock IERB failed.\n");
+ return err;
+ }
+ }
+
+ if (devinfo->ierb_init) {
+ err = devinfo->ierb_init(pdev);
+ if (err)
+ return err;
+ }
+
+ err = netc_lock_ierb(priv);
+ if (err) {
+ dev_err(&pdev->dev, "Lock IERB failed.\n");
+ return err;
+ }
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+static int netc_prb_show(struct seq_file *s, void *data)
+{
+ struct netc_blk_ctrl *priv = s->private;
+ u32 val;
+
+ val = netc_reg_read(priv->prb, PRB_NETCRR);
+ seq_printf(s, "[PRB NETCRR] Lock:%d SR:%d\n",
+ (val & NETCRR_LOCK) ? 1 : 0,
+ (val & NETCRR_SR) ? 1 : 0);
+
+ val = netc_reg_read(priv->prb, PRB_NETCSR);
+ seq_printf(s, "[PRB NETCSR] State:%d Error:%d\n",
+ (val & NETCSR_STATE) ? 1 : 0,
+ (val & NETCSR_ERROR) ? 1 : 0);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(netc_prb);
+
+static void netc_blk_ctrl_create_debugfs(struct netc_blk_ctrl *priv)
+{
+ struct dentry *root;
+
+ root = debugfs_create_dir("netc_blk_ctrl", NULL);
+ if (IS_ERR(root))
+ return;
+
+ priv->debugfs_root = root;
+
+ debugfs_create_file("prb", 0444, root, priv, &netc_prb_fops);
+}
+
+static void netc_blk_ctrl_remove_debugfs(struct netc_blk_ctrl *priv)
+{
+ debugfs_remove_recursive(priv->debugfs_root);
+ priv->debugfs_root = NULL;
+}
+
+#else
+
+static void netc_blk_ctrl_create_debugfs(struct netc_blk_ctrl *priv)
+{
+}
+
+static void netc_blk_ctrl_remove_debugfs(struct netc_blk_ctrl *priv)
+{
+}
+#endif
+
+static int netc_prb_check_error(struct netc_blk_ctrl *priv)
+{
+ if (netc_reg_read(priv->prb, PRB_NETCSR) & NETCSR_ERROR)
+ return -1;
+
+ return 0;
+}
+
+static const struct netc_devinfo imx95_devinfo = {
+ .flags = NETC_HAS_NETCMIX,
+ .netcmix_init = imx95_netcmix_init,
+ .ierb_init = imx95_ierb_init,
+};
+
+static const struct of_device_id netc_blk_ctrl_match[] = {
+ { .compatible = "nxp,imx95-netc-blk-ctrl", .data = &imx95_devinfo },
+ {},
+};
+MODULE_DEVICE_TABLE(of, netc_blk_ctrl_match);
+
+static int netc_blk_ctrl_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ const struct netc_devinfo *devinfo;
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *id;
+ struct netc_blk_ctrl *priv;
+ struct clk *ipg_clk;
+ void __iomem *regs;
+ int err;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->pdev = pdev;
+ ipg_clk = devm_clk_get_optional_enabled(dev, "ipg");
+ if (IS_ERR(ipg_clk))
+ return dev_err_probe(dev, PTR_ERR(ipg_clk),
+ "Set ipg clock failed\n");
+
+ id = of_match_device(netc_blk_ctrl_match, dev);
+ if (!id)
+ return dev_err_probe(dev, -EINVAL, "Cannot match device\n");
+
+ devinfo = (struct netc_devinfo *)id->data;
+ if (!devinfo)
+ return dev_err_probe(dev, -EINVAL, "No device information\n");
+
+ priv->devinfo = devinfo;
+ regs = devm_platform_ioremap_resource_byname(pdev, "ierb");
+ if (IS_ERR(regs))
+ return dev_err_probe(dev, PTR_ERR(regs),
+ "Missing IERB resource\n");
+
+ priv->ierb = regs;
+ regs = devm_platform_ioremap_resource_byname(pdev, "prb");
+ if (IS_ERR(regs))
+ return dev_err_probe(dev, PTR_ERR(regs),
+ "Missing PRB resource\n");
+
+ priv->prb = regs;
+ if (devinfo->flags & NETC_HAS_NETCMIX) {
+ regs = devm_platform_ioremap_resource_byname(pdev, "netcmix");
+ if (IS_ERR(regs))
+ return dev_err_probe(dev, PTR_ERR(regs),
+ "Missing NETCMIX resource\n");
+ priv->netcmix = regs;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ if (devinfo->netcmix_init) {
+ err = devinfo->netcmix_init(pdev);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Initializing NETCMIX failed\n");
+ }
+
+ err = netc_ierb_init(pdev);
+ if (err)
+ return dev_err_probe(dev, err, "Initializing IERB failed\n");
+
+ if (netc_prb_check_error(priv) < 0)
+ dev_warn(dev, "The current IERB configuration is invalid\n");
+
+ netc_blk_ctrl_create_debugfs(priv);
+
+ err = of_platform_populate(node, NULL, NULL, dev);
+ if (err) {
+ netc_blk_ctrl_remove_debugfs(priv);
+ return dev_err_probe(dev, err, "of_platform_populate failed\n");
+ }
+
+ return 0;
+}
+
+static void netc_blk_ctrl_remove(struct platform_device *pdev)
+{
+ struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
+
+ of_platform_depopulate(&pdev->dev);
+ netc_blk_ctrl_remove_debugfs(priv);
+}
+
+static struct platform_driver netc_blk_ctrl_driver = {
+ .driver = {
+ .name = "nxp-netc-blk-ctrl",
+ .of_match_table = netc_blk_ctrl_match,
+ },
+ .probe = netc_blk_ctrl_probe,
+ .remove = netc_blk_ctrl_remove,
+};
+
+module_platform_driver(netc_blk_ctrl_driver);
+
+MODULE_DESCRIPTION("NXP NETC Blocks Control Driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9d9fcec41488..1b55047c0237 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -4766,7 +4766,7 @@ static struct platform_driver fec_driver = {
},
.id_table = fec_devtype,
.probe = fec_probe,
- .remove_new = fec_drv_remove,
+ .remove = fec_drv_remove,
};
module_platform_driver(fec_driver);
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index ebae71ec26c6..2bfaf14f65c8 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -1040,7 +1040,7 @@ static struct platform_driver mpc52xx_fec_driver = {
.of_match_table = mpc52xx_fec_match,
},
.probe = mpc52xx_fec_probe,
- .remove_new = mpc52xx_fec_remove,
+ .remove = mpc52xx_fec_remove,
#ifdef CONFIG_PM
.suspend = mpc52xx_fec_of_suspend,
.resume = mpc52xx_fec_of_resume,
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c
index 39689826cc8f..3d073f0fae63 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c
@@ -94,7 +94,7 @@ static int mpc52xx_fec_mdio_probe(struct platform_device *of)
goto out_free;
}
- snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res.start);
bus->priv = priv;
bus->parent = dev;
@@ -144,7 +144,7 @@ struct platform_driver mpc52xx_fec_mdio_driver = {
.of_match_table = mpc52xx_fec_mdio_match,
},
.probe = mpc52xx_fec_mdio_probe,
- .remove_new = mpc52xx_fec_mdio_remove,
+ .remove = mpc52xx_fec_mdio_remove,
};
/* let fec driver call it, since this has to be registered before it */
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index a4eb6edb850a..7f6b57432071 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -84,8 +84,7 @@
#define FEC_CC_MULT (1 << 31)
#define FEC_COUNTER_PERIOD (1 << 31)
#define PPS_OUPUT_RELOAD_PERIOD NSEC_PER_SEC
-#define FEC_CHANNLE_0 0
-#define DEFAULT_PPS_CHANNEL FEC_CHANNLE_0
+#define DEFAULT_PPS_CHANNEL 0
#define FEC_PTP_MAX_NSEC_PERIOD 4000000000ULL
#define FEC_PTP_MAX_NSEC_COUNTER 0x80000000ULL
@@ -525,7 +524,6 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
int ret = 0;
if (rq->type == PTP_CLK_REQ_PPS) {
- fep->pps_channel = DEFAULT_PPS_CHANNEL;
fep->reload_period = PPS_OUPUT_RELOAD_PERIOD;
ret = fec_ptp_enable_pps(fep, on);
@@ -536,10 +534,9 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
if (rq->perout.flags)
return -EOPNOTSUPP;
- if (rq->perout.index != DEFAULT_PPS_CHANNEL)
+ if (rq->perout.index != fep->pps_channel)
return -EOPNOTSUPP;
- fep->pps_channel = DEFAULT_PPS_CHANNEL;
period.tv_sec = rq->perout.period.sec;
period.tv_nsec = rq->perout.period.nsec;
period_ns = timespec64_to_ns(&period);
@@ -707,12 +704,16 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(ndev);
+ struct device_node *np = fep->pdev->dev.of_node;
int irq;
int ret;
fep->ptp_caps.owner = THIS_MODULE;
strscpy(fep->ptp_caps.name, "fec ptp", sizeof(fep->ptp_caps.name));
+ fep->pps_channel = DEFAULT_PPS_CHANNEL;
+ of_property_read_u32(np, "fsl,pps-channel", &fep->pps_channel);
+
fep->ptp_caps.max_adj = 250000000;
fep->ptp_caps.n_alarm = 0;
fep->ptp_caps.n_ext_ts = 0;
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
index d96028f01770..fb416d60dcd7 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -24,7 +24,6 @@
/* General defines */
#define FMAN_LIODN_TBL 64 /* size of LIODN table */
-#define MAX_NUM_OF_MACS 10
#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4
#define BASE_RX_PORTID 0x08
#define BASE_TX_PORTID 0x28
diff --git a/drivers/net/ethernet/freescale/fman/fman.h b/drivers/net/ethernet/freescale/fman/fman.h
index 2ea575a46675..74eb62eba0d7 100644
--- a/drivers/net/ethernet/freescale/fman/fman.h
+++ b/drivers/net/ethernet/freescale/fman/fman.h
@@ -74,6 +74,9 @@
#define BM_MAX_NUM_OF_POOLS 64 /* Buffers pools */
#define FMAN_PORT_MAX_EXT_POOLS_NUM 8 /* External BM pools per Rx port */
+/* General defines */
+#define MAX_NUM_OF_MACS 10
+
struct fman; /* FMan data */
/* Enum for defining port types */
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 3088da7adf0f..85617bb94959 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1415,7 +1415,6 @@ int dtsec_initialization(struct mac_device *mac_dev,
mac_dev->set_exception = dtsec_set_exception;
mac_dev->set_allmulti = dtsec_set_allmulti;
mac_dev->set_tstamp = dtsec_set_tstamp;
- mac_dev->set_multi = fman_set_multi;
mac_dev->enable = dtsec_enable;
mac_dev->disable = dtsec_disable;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 796e6f4e583d..3925441143fa 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -1087,7 +1087,6 @@ int memac_initialization(struct mac_device *mac_dev,
mac_dev->set_exception = memac_set_exception;
mac_dev->set_allmulti = memac_set_allmulti;
mac_dev->set_tstamp = memac_set_tstamp;
- mac_dev->set_multi = fman_set_multi;
mac_dev->enable = memac_enable;
mac_dev->disable = memac_disable;
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c
index f17a4e511510..e977389f7088 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
+++ b/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -987,7 +987,7 @@ static int init_low_level_driver(struct fman_port *port)
return -ENODEV;
}
- /* The code bellow is a trick so the FM will not release the buffer
+ /* The code below is a trick so the FM will not release the buffer
* to BM nor will try to enqueue the frame to QM
*/
if (port->port_type == FMAN_PORT_TYPE_TX) {
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index c2261d26db5b..fecfca6eba03 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -771,7 +771,6 @@ int tgec_initialization(struct mac_device *mac_dev,
mac_dev->set_exception = tgec_set_exception;
mac_dev->set_allmulti = tgec_set_allmulti;
mac_dev->set_tstamp = tgec_set_tstamp;
- mac_dev->set_multi = fman_set_multi;
mac_dev->enable = tgec_enable;
mac_dev->disable = tgec_disable;
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 11da139082e1..a39fcea6a77a 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -32,8 +32,6 @@ MODULE_DESCRIPTION("FSL FMan MAC API based driver");
struct mac_priv_s {
u8 cell_index;
struct fman *fman;
- /* List of multicast addresses */
- struct list_head mc_addr_list;
struct platform_device *eth_dev;
u16 speed;
};
@@ -57,44 +55,6 @@ static void mac_exception(struct mac_device *mac_dev,
__func__, ex);
}
-int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
-{
- struct mac_priv_s *priv;
- struct mac_address *old_addr, *tmp;
- struct netdev_hw_addr *ha;
- int err;
- enet_addr_t *addr;
-
- priv = mac_dev->priv;
-
- /* Clear previous address list */
- list_for_each_entry_safe(old_addr, tmp, &priv->mc_addr_list, list) {
- addr = (enet_addr_t *)old_addr->addr;
- err = mac_dev->remove_hash_mac_addr(mac_dev->fman_mac, addr);
- if (err < 0)
- return err;
-
- list_del(&old_addr->list);
- kfree(old_addr);
- }
-
- /* Add all the addresses from the new list */
- netdev_for_each_mc_addr(ha, net_dev) {
- addr = (enet_addr_t *)ha->addr;
- err = mac_dev->add_hash_mac_addr(mac_dev->fman_mac, addr);
- if (err < 0)
- return err;
-
- tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
- if (!tmp)
- return -ENOMEM;
-
- ether_addr_copy(tmp->addr, ha->addr);
- list_add(&tmp->list, &priv->mc_addr_list);
- }
- return 0;
-}
-
static DEFINE_MUTEX(eth_lock);
static struct platform_device *dpaa_eth_add_device(int fman_id,
@@ -181,8 +141,6 @@ static int mac_probe(struct platform_device *_of_dev)
mac_dev->priv = priv;
mac_dev->dev = dev;
- INIT_LIST_HEAD(&priv->mc_addr_list);
-
/* Get the FM node */
dev_node = of_get_parent(mac_node);
if (!dev_node) {
@@ -259,6 +217,11 @@ static int mac_probe(struct platform_device *_of_dev)
err = -EINVAL;
goto _return_dev_put;
}
+ if (val >= MAX_NUM_OF_MACS) {
+ dev_err(dev, "cell-index value is too big for %pOF\n", mac_node);
+ err = -EINVAL;
+ goto _return_dev_put;
+ }
priv->cell_index = (u8)val;
/* Get the MAC address */
@@ -379,7 +342,7 @@ static struct platform_driver mac_driver = {
.of_match_table = mac_match,
},
.probe = mac_probe,
- .remove_new = mac_remove,
+ .remove = mac_remove,
};
builtin_platform_driver(mac_driver);
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index 8b5b43d50f8e..955ace338965 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -40,8 +40,6 @@ struct mac_device {
int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr);
int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
int (*set_tstamp)(struct fman_mac *mac_dev, bool enable);
- int (*set_multi)(struct net_device *net_dev,
- struct mac_device *mac_dev);
int (*set_exception)(struct fman_mac *mac_dev,
enum fman_mac_exceptions exception, bool enable);
int (*add_hash_mac_addr)(struct fman_mac *mac_dev,
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 3425c4a6abcb..f563692a4a00 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1052,7 +1052,7 @@ static struct platform_driver fs_enet_driver = {
.of_match_table = fs_enet_match,
},
.probe = fs_enet_probe,
- .remove_new = fs_enet_remove,
+ .remove = fs_enet_remove,
};
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
index 2e210a003558..66038e2a4ae3 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
@@ -123,7 +123,7 @@ static int fs_mii_bitbang_init(struct mii_bus *bus, struct device_node *np)
* we get is an int, and the odds of multiple bitbang mdio buses
* is low enough that it's not worth going too crazy.
*/
- snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res.start);
data = of_get_property(np, "fsl,mdio-pin", &len);
if (!data || len != 4)
@@ -214,7 +214,7 @@ static struct platform_driver fs_enet_bb_mdio_driver = {
.of_match_table = fs_enet_mdio_bb_match,
},
.probe = fs_enet_mdio_probe,
- .remove_new = fs_enet_mdio_remove,
+ .remove = fs_enet_mdio_remove,
};
module_platform_driver(fs_enet_bb_mdio_driver);
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
index 93d91e8ad0de..dec31b638941 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
@@ -212,7 +212,7 @@ static struct platform_driver fs_enet_fec_mdio_driver = {
.of_match_table = fs_enet_mdio_fec_match,
},
.probe = fs_enet_mdio_probe,
- .remove_new = fs_enet_mdio_remove,
+ .remove = fs_enet_mdio_remove,
};
module_platform_driver(fs_enet_fec_mdio_driver);
diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 026f7270a54d..56d2f79fb7e3 100644
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@ -526,7 +526,7 @@ static struct platform_driver fsl_pq_mdio_driver = {
.of_match_table = fsl_pq_mdio_match,
},
.probe = fsl_pq_mdio_probe,
- .remove_new = fsl_pq_mdio_remove,
+ .remove = fsl_pq_mdio_remove,
};
module_platform_driver(fsl_pq_mdio_driver);
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index ecb1703ea150..435138f4699d 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2207,8 +2207,9 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
if (unlikely(do_tstamp)) {
struct skb_shared_hwtstamps shhwtstamps;
- u64 *ns = (u64 *)(((uintptr_t)skb->data + 0x10) &
- ~0x7UL);
+ __be64 *ns;
+
+ ns = (__be64 *)(((uintptr_t)skb->data + 0x10) & ~0x7UL);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(be64_to_cpu(*ns));
@@ -2471,7 +2472,7 @@ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb)
/* Get receive timestamp from the skb */
if (priv->hwts_rx_en) {
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
- u64 *ns = (u64 *) skb->data;
+ __be64 *ns = (__be64 *)skb->data;
memset(shhwtstamps, 0, sizeof(*shhwtstamps));
shhwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(*ns));
@@ -3642,7 +3643,7 @@ static struct platform_driver gfar_driver = {
.of_match_table = gfar_match,
},
.probe = gfar_probe,
- .remove_new = gfar_remove,
+ .remove = gfar_remove,
};
module_platform_driver(gfar_driver);
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index a99b95c4bcfb..781d92e703cb 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -115,12 +115,14 @@ static const char stat_gstrings[][ETH_GSTRING_LEN] = {
static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
{
struct gfar_private *priv = netdev_priv(dev);
+ int i;
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
- memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
+ for (i = 0; i < GFAR_STATS_LEN; i++)
+ ethtool_puts(&buf, stat_gstrings[i]);
else
- memcpy(buf, stat_gstrings,
- GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN);
+ for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
+ ethtool_puts(&buf, stat_gstrings[i]);
}
/* Fill in an array of 64-bit statistics from various sources.
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index ab421243a419..6663c1768089 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -3591,22 +3591,23 @@ static int ucc_geth_probe(struct platform_device* ofdev)
if ((ucc_num < 0) || (ucc_num > 7))
return -ENODEV;
- ug_info = kmemdup(&ugeth_primary_info, sizeof(*ug_info), GFP_KERNEL);
- if (ug_info == NULL)
+ ug_info = devm_kmemdup(&ofdev->dev, &ugeth_primary_info,
+ sizeof(*ug_info), GFP_KERNEL);
+ if (!ug_info)
return -ENOMEM;
ug_info->uf_info.ucc_num = ucc_num;
err = ucc_geth_parse_clock(np, "rx", &ug_info->uf_info.rx_clock);
if (err)
- goto err_free_info;
+ return err;
err = ucc_geth_parse_clock(np, "tx", &ug_info->uf_info.tx_clock);
if (err)
- goto err_free_info;
+ return err;
err = of_address_to_resource(np, 0, &res);
if (err)
- goto err_free_info;
+ return err;
ug_info->uf_info.regs = res.start;
ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
@@ -3619,7 +3620,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
*/
err = of_phy_register_fixed_link(np);
if (err)
- goto err_free_info;
+ return err;
ug_info->phy_node = of_node_get(np);
}
@@ -3687,9 +3688,8 @@ static int ucc_geth_probe(struct platform_device* ofdev)
ug_info->uf_info.irq);
/* Create an ethernet device instance */
- dev = alloc_etherdev(sizeof(*ugeth));
-
- if (dev == NULL) {
+ dev = devm_alloc_etherdev(&ofdev->dev, sizeof(*ugeth));
+ if (!dev) {
err = -ENOMEM;
goto err_deregister_fixed_link;
}
@@ -3724,15 +3724,17 @@ static int ucc_geth_probe(struct platform_device* ofdev)
/* Carrier starts down, phylib will bring it up */
netif_carrier_off(dev);
- err = register_netdev(dev);
+ err = devm_register_netdev(&ofdev->dev, dev);
if (err) {
if (netif_msg_probe(ugeth))
pr_err("%s: Cannot register net device, aborting\n",
dev->name);
- goto err_free_netdev;
+ goto err_deregister_fixed_link;
}
- of_get_ethdev_address(np, dev);
+ err = of_get_ethdev_address(np, dev);
+ if (err == -EPROBE_DEFER)
+ goto err_deregister_fixed_link;
ugeth->ug_info = ug_info;
ugeth->dev = device;
@@ -3741,16 +3743,11 @@ static int ucc_geth_probe(struct platform_device* ofdev)
return 0;
-err_free_netdev:
- free_netdev(dev);
err_deregister_fixed_link:
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(ug_info->tbi_node);
of_node_put(ug_info->phy_node);
-err_free_info:
- kfree(ug_info);
-
return err;
}
@@ -3760,14 +3757,11 @@ static void ucc_geth_remove(struct platform_device* ofdev)
struct ucc_geth_private *ugeth = netdev_priv(dev);
struct device_node *np = ofdev->dev.of_node;
- unregister_netdev(dev);
ucc_geth_memclean(ugeth);
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(ugeth->ug_info->tbi_node);
of_node_put(ugeth->ug_info->phy_node);
- kfree(ugeth->ug_info);
- free_netdev(dev);
}
static const struct of_device_id ucc_geth_match[] = {
@@ -3786,7 +3780,7 @@ static struct platform_driver ucc_geth_driver = {
.of_match_table = ucc_geth_match,
},
.probe = ucc_geth_probe,
- .remove_new = ucc_geth_remove,
+ .remove = ucc_geth_remove,
.suspend = ucc_geth_suspend,
.resume = ucc_geth_resume,
};
diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index 601beb93d3b3..699f346faf5c 100644
--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
@@ -287,20 +287,17 @@ static void uec_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
u32 stats_mode = ugeth->ug_info->statisticsMode;
+ int i;
- if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) {
- memcpy(buf, hw_stat_gstrings, UEC_HW_STATS_LEN *
- ETH_GSTRING_LEN);
- buf += UEC_HW_STATS_LEN * ETH_GSTRING_LEN;
- }
- if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
- memcpy(buf, tx_fw_stat_gstrings, UEC_TX_FW_STATS_LEN *
- ETH_GSTRING_LEN);
- buf += UEC_TX_FW_STATS_LEN * ETH_GSTRING_LEN;
- }
+ if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE)
+ for (i = 0; i < UEC_HW_STATS_LEN; i++)
+ ethtool_puts(&buf, hw_stat_gstrings[i]);
+ if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX)
+ for (i = 0; i < UEC_TX_FW_STATS_LEN; i++)
+ ethtool_puts(&buf, tx_fw_stat_gstrings[i]);
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX)
- memcpy(buf, rx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN *
- ETH_GSTRING_LEN);
+ for (i = 0; i < UEC_RX_FW_STATS_LEN; i++)
+ ethtool_puts(&buf, rx_fw_stat_gstrings[i]);
}
static void uec_get_ethtool_stats(struct net_device *netdev,
diff --git a/drivers/net/ethernet/fungible/funcore/fun_queue.c b/drivers/net/ethernet/fungible/funcore/fun_queue.c
index 8ab9f68434f5..d07ee3e4f52a 100644
--- a/drivers/net/ethernet/fungible/funcore/fun_queue.c
+++ b/drivers/net/ethernet/fungible/funcore/fun_queue.c
@@ -482,43 +482,6 @@ free_funq:
return NULL;
}
-/* Create a funq's CQ on the device. */
-static int fun_create_cq(struct fun_queue *funq)
-{
- struct fun_dev *fdev = funq->fdev;
- unsigned int rqid;
- int rc;
-
- rqid = funq->cq_flags & FUN_ADMIN_EPCQ_CREATE_FLAG_RQ ?
- funq->rqid : FUN_HCI_ID_INVALID;
- rc = fun_cq_create(fdev, funq->cq_flags, funq->cqid, rqid,
- funq->cqe_size_log2, funq->cq_depth,
- funq->cq_dma_addr, 0, 0, funq->cq_intcoal_nentries,
- funq->cq_intcoal_usec, funq->cq_vector, 0, 0,
- &funq->cqid, &funq->cq_db);
- if (!rc)
- dev_dbg(fdev->dev, "created CQ %u\n", funq->cqid);
-
- return rc;
-}
-
-/* Create a funq's SQ on the device. */
-static int fun_create_sq(struct fun_queue *funq)
-{
- struct fun_dev *fdev = funq->fdev;
- int rc;
-
- rc = fun_sq_create(fdev, funq->sq_flags, funq->sqid, funq->cqid,
- funq->sqe_size_log2, funq->sq_depth,
- funq->sq_dma_addr, funq->sq_intcoal_nentries,
- funq->sq_intcoal_usec, funq->cq_vector, 0, 0,
- 0, &funq->sqid, &funq->sq_db);
- if (!rc)
- dev_dbg(fdev->dev, "created SQ %u\n", funq->sqid);
-
- return rc;
-}
-
/* Create a funq's RQ on the device. */
int fun_create_rq(struct fun_queue *funq)
{
@@ -561,34 +524,6 @@ int fun_request_irq(struct fun_queue *funq, const char *devname,
return rc;
}
-/* Create all component queues of a funq on the device. */
-int fun_create_queue(struct fun_queue *funq)
-{
- int rc;
-
- rc = fun_create_cq(funq);
- if (rc)
- return rc;
-
- if (funq->rq_depth) {
- rc = fun_create_rq(funq);
- if (rc)
- goto release_cq;
- }
-
- rc = fun_create_sq(funq);
- if (rc)
- goto release_rq;
-
- return 0;
-
-release_rq:
- fun_destroy_sq(funq->fdev, funq->rqid);
-release_cq:
- fun_destroy_cq(funq->fdev, funq->cqid);
- return rc;
-}
-
void fun_free_irq(struct fun_queue *funq)
{
if (funq->irq_handler) {
diff --git a/drivers/net/ethernet/fungible/funcore/fun_queue.h b/drivers/net/ethernet/fungible/funcore/fun_queue.h
index 7fb53d0ae8b0..2d966afb187a 100644
--- a/drivers/net/ethernet/fungible/funcore/fun_queue.h
+++ b/drivers/net/ethernet/fungible/funcore/fun_queue.h
@@ -163,7 +163,6 @@ static inline void fun_set_cq_callback(struct fun_queue *funq, cq_callback_t cb,
}
int fun_create_rq(struct fun_queue *funq);
-int fun_create_queue(struct fun_queue *funq);
void fun_free_irq(struct fun_queue *funq);
int fun_request_irq(struct fun_queue *funq, const char *devname,
diff --git a/drivers/net/ethernet/google/Kconfig b/drivers/net/ethernet/google/Kconfig
index 8641a00f8e63..564862a57124 100644
--- a/drivers/net/ethernet/google/Kconfig
+++ b/drivers/net/ethernet/google/Kconfig
@@ -18,6 +18,7 @@ if NET_VENDOR_GOOGLE
config GVE
tristate "Google Virtual NIC (gVNIC) support"
depends on (PCI_MSI && (X86 || CPU_LITTLE_ENDIAN))
+ select PAGE_POOL
help
This driver supports Google Virtual NIC (gVNIC)"
diff --git a/drivers/net/ethernet/google/gve/Makefile b/drivers/net/ethernet/google/gve/Makefile
index 9ed07080b38a..4520f1c07a63 100644
--- a/drivers/net/ethernet/google/gve/Makefile
+++ b/drivers/net/ethernet/google/gve/Makefile
@@ -1,4 +1,5 @@
# Makefile for the Google virtual Ethernet (gve) driver
obj-$(CONFIG_GVE) += gve.o
-gve-objs := gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_ethtool.o gve_adminq.o gve_utils.o gve_flow_rule.o
+gve-objs := gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_ethtool.o gve_adminq.o gve_utils.o gve_flow_rule.o \
+ gve_buffer_mgmt_dqo.o
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 301fa1ea4f51..dd92949bb214 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -13,6 +13,7 @@
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/u64_stats_sync.h>
+#include <net/page_pool/helpers.h>
#include <net/xdp.h>
#include "gve_desc.h"
@@ -60,6 +61,8 @@
#define GVE_DEFAULT_RX_BUFFER_OFFSET 2048
+#define GVE_PAGE_POOL_SIZE_MULTIPLIER 4
+
#define GVE_FLOW_RULES_CACHE_SIZE \
(GVE_ADMINQ_BUFFER_SIZE / sizeof(struct gve_adminq_queried_flow_rule))
#define GVE_FLOW_RULE_IDS_CACHE_SIZE \
@@ -102,6 +105,7 @@ struct gve_rx_slot_page_info {
struct page *page;
void *page_address;
u32 page_offset; /* offset to write to in page */
+ unsigned int buf_size;
int pagecnt_bias; /* expected pagecnt if only the driver has a ref */
u16 pad; /* adjustment for rx padding */
u8 can_flip; /* tracks if the networking stack is using the page */
@@ -273,6 +277,8 @@ struct gve_rx_ring {
/* Address info of the buffers for header-split */
struct gve_header_buf hdr_bufs;
+
+ struct page_pool *page_pool;
} dqo;
};
@@ -1162,6 +1168,36 @@ void gve_rx_stop_ring_gqi(struct gve_priv *priv, int idx);
u16 gve_get_pkt_buf_size(const struct gve_priv *priv, bool enable_hplit);
bool gve_header_split_supported(const struct gve_priv *priv);
int gve_set_hsplit_config(struct gve_priv *priv, u8 tcp_data_split);
+/* rx buffer handling */
+int gve_buf_ref_cnt(struct gve_rx_buf_state_dqo *bs);
+void gve_free_page_dqo(struct gve_priv *priv, struct gve_rx_buf_state_dqo *bs,
+ bool free_page);
+struct gve_rx_buf_state_dqo *gve_alloc_buf_state(struct gve_rx_ring *rx);
+bool gve_buf_state_is_allocated(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state);
+void gve_free_buf_state(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state);
+struct gve_rx_buf_state_dqo *gve_dequeue_buf_state(struct gve_rx_ring *rx,
+ struct gve_index_list *list);
+void gve_enqueue_buf_state(struct gve_rx_ring *rx, struct gve_index_list *list,
+ struct gve_rx_buf_state_dqo *buf_state);
+struct gve_rx_buf_state_dqo *gve_get_recycled_buf_state(struct gve_rx_ring *rx);
+void gve_try_recycle_buf(struct gve_priv *priv, struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state);
+void gve_free_to_page_pool(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state,
+ bool allow_direct);
+int gve_alloc_qpl_page_dqo(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state);
+void gve_free_qpl_page_dqo(struct gve_rx_buf_state_dqo *buf_state);
+void gve_reuse_buffer(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state);
+void gve_free_buffer(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state);
+int gve_alloc_buffer(struct gve_rx_ring *rx, struct gve_rx_desc_dqo *desc);
+struct page_pool *gve_rx_create_page_pool(struct gve_priv *priv,
+ struct gve_rx_ring *rx);
+
/* Reset */
void gve_schedule_reset(struct gve_priv *priv);
int gve_reset(struct gve_priv *priv, bool attempt_teardown);
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index e44e8b139633..060e0e674938 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -1248,10 +1248,10 @@ gve_adminq_configure_flow_rule(struct gve_priv *priv,
sizeof(struct gve_adminq_configure_flow_rule),
flow_rule_cmd);
- if (err) {
+ if (err == -ETIME) {
dev_err(&priv->pdev->dev, "Timeout to configure the flow rule, trigger reset");
gve_reset(priv, true);
- } else {
+ } else if (!err) {
priv->flow_rules_cache.rules_cache_synced = false;
}
diff --git a/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c b/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
new file mode 100644
index 000000000000..403f0f335ba6
--- /dev/null
+++ b/drivers/net/ethernet/google/gve/gve_buffer_mgmt_dqo.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Google virtual Ethernet (gve) driver
+ *
+ * Copyright (C) 2015-2024 Google, Inc.
+ */
+
+#include "gve.h"
+#include "gve_utils.h"
+
+int gve_buf_ref_cnt(struct gve_rx_buf_state_dqo *bs)
+{
+ return page_count(bs->page_info.page) - bs->page_info.pagecnt_bias;
+}
+
+struct gve_rx_buf_state_dqo *gve_alloc_buf_state(struct gve_rx_ring *rx)
+{
+ struct gve_rx_buf_state_dqo *buf_state;
+ s16 buffer_id;
+
+ buffer_id = rx->dqo.free_buf_states;
+ if (unlikely(buffer_id == -1))
+ return NULL;
+
+ buf_state = &rx->dqo.buf_states[buffer_id];
+
+ /* Remove buf_state from free list */
+ rx->dqo.free_buf_states = buf_state->next;
+
+ /* Point buf_state to itself to mark it as allocated */
+ buf_state->next = buffer_id;
+
+ return buf_state;
+}
+
+bool gve_buf_state_is_allocated(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ s16 buffer_id = buf_state - rx->dqo.buf_states;
+
+ return buf_state->next == buffer_id;
+}
+
+void gve_free_buf_state(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ s16 buffer_id = buf_state - rx->dqo.buf_states;
+
+ buf_state->next = rx->dqo.free_buf_states;
+ rx->dqo.free_buf_states = buffer_id;
+}
+
+struct gve_rx_buf_state_dqo *gve_dequeue_buf_state(struct gve_rx_ring *rx,
+ struct gve_index_list *list)
+{
+ struct gve_rx_buf_state_dqo *buf_state;
+ s16 buffer_id;
+
+ buffer_id = list->head;
+ if (unlikely(buffer_id == -1))
+ return NULL;
+
+ buf_state = &rx->dqo.buf_states[buffer_id];
+
+ /* Remove buf_state from list */
+ list->head = buf_state->next;
+ if (buf_state->next == -1)
+ list->tail = -1;
+
+ /* Point buf_state to itself to mark it as allocated */
+ buf_state->next = buffer_id;
+
+ return buf_state;
+}
+
+void gve_enqueue_buf_state(struct gve_rx_ring *rx, struct gve_index_list *list,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ s16 buffer_id = buf_state - rx->dqo.buf_states;
+
+ buf_state->next = -1;
+
+ if (list->head == -1) {
+ list->head = buffer_id;
+ list->tail = buffer_id;
+ } else {
+ int tail = list->tail;
+
+ rx->dqo.buf_states[tail].next = buffer_id;
+ list->tail = buffer_id;
+ }
+}
+
+struct gve_rx_buf_state_dqo *gve_get_recycled_buf_state(struct gve_rx_ring *rx)
+{
+ struct gve_rx_buf_state_dqo *buf_state;
+ int i;
+
+ /* Recycled buf states are immediately usable. */
+ buf_state = gve_dequeue_buf_state(rx, &rx->dqo.recycled_buf_states);
+ if (likely(buf_state))
+ return buf_state;
+
+ if (unlikely(rx->dqo.used_buf_states.head == -1))
+ return NULL;
+
+ /* Used buf states are only usable when ref count reaches 0, which means
+ * no SKBs refer to them.
+ *
+ * Search a limited number before giving up.
+ */
+ for (i = 0; i < 5; i++) {
+ buf_state = gve_dequeue_buf_state(rx, &rx->dqo.used_buf_states);
+ if (gve_buf_ref_cnt(buf_state) == 0) {
+ rx->dqo.used_buf_states_cnt--;
+ return buf_state;
+ }
+
+ gve_enqueue_buf_state(rx, &rx->dqo.used_buf_states, buf_state);
+ }
+
+ return NULL;
+}
+
+int gve_alloc_qpl_page_dqo(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ struct gve_priv *priv = rx->gve;
+ u32 idx;
+
+ idx = rx->dqo.next_qpl_page_idx;
+ if (idx >= gve_get_rx_pages_per_qpl_dqo(priv->rx_desc_cnt)) {
+ net_err_ratelimited("%s: Out of QPL pages\n",
+ priv->dev->name);
+ return -ENOMEM;
+ }
+ buf_state->page_info.page = rx->dqo.qpl->pages[idx];
+ buf_state->addr = rx->dqo.qpl->page_buses[idx];
+ rx->dqo.next_qpl_page_idx++;
+ buf_state->page_info.page_offset = 0;
+ buf_state->page_info.page_address =
+ page_address(buf_state->page_info.page);
+ buf_state->page_info.buf_size = priv->data_buffer_size_dqo;
+ buf_state->last_single_ref_offset = 0;
+
+ /* The page already has 1 ref. */
+ page_ref_add(buf_state->page_info.page, INT_MAX - 1);
+ buf_state->page_info.pagecnt_bias = INT_MAX;
+
+ return 0;
+}
+
+void gve_free_qpl_page_dqo(struct gve_rx_buf_state_dqo *buf_state)
+{
+ if (!buf_state->page_info.page)
+ return;
+
+ page_ref_sub(buf_state->page_info.page,
+ buf_state->page_info.pagecnt_bias - 1);
+ buf_state->page_info.page = NULL;
+}
+
+void gve_try_recycle_buf(struct gve_priv *priv, struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ const u16 data_buffer_size = priv->data_buffer_size_dqo;
+ int pagecount;
+
+ /* Can't reuse if we only fit one buffer per page */
+ if (data_buffer_size * 2 > PAGE_SIZE)
+ goto mark_used;
+
+ pagecount = gve_buf_ref_cnt(buf_state);
+
+ /* Record the offset when we have a single remaining reference.
+ *
+ * When this happens, we know all of the other offsets of the page are
+ * usable.
+ */
+ if (pagecount == 1) {
+ buf_state->last_single_ref_offset =
+ buf_state->page_info.page_offset;
+ }
+
+ /* Use the next buffer sized chunk in the page. */
+ buf_state->page_info.page_offset += data_buffer_size;
+ buf_state->page_info.page_offset &= (PAGE_SIZE - 1);
+
+ /* If we wrap around to the same offset without ever dropping to 1
+ * reference, then we don't know if this offset was ever freed.
+ */
+ if (buf_state->page_info.page_offset ==
+ buf_state->last_single_ref_offset) {
+ goto mark_used;
+ }
+
+ gve_enqueue_buf_state(rx, &rx->dqo.recycled_buf_states, buf_state);
+ return;
+
+mark_used:
+ gve_enqueue_buf_state(rx, &rx->dqo.used_buf_states, buf_state);
+ rx->dqo.used_buf_states_cnt++;
+}
+
+void gve_free_to_page_pool(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state,
+ bool allow_direct)
+{
+ struct page *page = buf_state->page_info.page;
+
+ if (!page)
+ return;
+
+ page_pool_put_full_page(page->pp, page, allow_direct);
+ buf_state->page_info.page = NULL;
+}
+
+static int gve_alloc_from_page_pool(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ struct gve_priv *priv = rx->gve;
+ struct page *page;
+
+ buf_state->page_info.buf_size = priv->data_buffer_size_dqo;
+ page = page_pool_alloc(rx->dqo.page_pool,
+ &buf_state->page_info.page_offset,
+ &buf_state->page_info.buf_size, GFP_ATOMIC);
+
+ if (!page)
+ return -ENOMEM;
+
+ buf_state->page_info.page = page;
+ buf_state->page_info.page_address = page_address(page);
+ buf_state->addr = page_pool_get_dma_addr(page);
+
+ return 0;
+}
+
+struct page_pool *gve_rx_create_page_pool(struct gve_priv *priv,
+ struct gve_rx_ring *rx)
+{
+ u32 ntfy_id = gve_rx_idx_to_ntfy(priv, rx->q_num);
+ struct page_pool_params pp = {
+ .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
+ .order = 0,
+ .pool_size = GVE_PAGE_POOL_SIZE_MULTIPLIER * priv->rx_desc_cnt,
+ .dev = &priv->pdev->dev,
+ .netdev = priv->dev,
+ .napi = &priv->ntfy_blocks[ntfy_id].napi,
+ .max_len = PAGE_SIZE,
+ .dma_dir = DMA_FROM_DEVICE,
+ };
+
+ return page_pool_create(&pp);
+}
+
+void gve_free_buffer(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ if (rx->dqo.page_pool) {
+ gve_free_to_page_pool(rx, buf_state, true);
+ gve_free_buf_state(rx, buf_state);
+ } else {
+ gve_enqueue_buf_state(rx, &rx->dqo.recycled_buf_states,
+ buf_state);
+ }
+}
+
+void gve_reuse_buffer(struct gve_rx_ring *rx,
+ struct gve_rx_buf_state_dqo *buf_state)
+{
+ if (rx->dqo.page_pool) {
+ buf_state->page_info.page = NULL;
+ gve_free_buf_state(rx, buf_state);
+ } else {
+ gve_dec_pagecnt_bias(&buf_state->page_info);
+ gve_try_recycle_buf(rx->gve, rx, buf_state);
+ }
+}
+
+int gve_alloc_buffer(struct gve_rx_ring *rx, struct gve_rx_desc_dqo *desc)
+{
+ struct gve_rx_buf_state_dqo *buf_state;
+
+ if (rx->dqo.page_pool) {
+ buf_state = gve_alloc_buf_state(rx);
+ if (WARN_ON_ONCE(!buf_state))
+ return -ENOMEM;
+
+ if (gve_alloc_from_page_pool(rx, buf_state))
+ goto free_buf_state;
+ } else {
+ buf_state = gve_get_recycled_buf_state(rx);
+ if (unlikely(!buf_state)) {
+ buf_state = gve_alloc_buf_state(rx);
+ if (unlikely(!buf_state))
+ return -ENOMEM;
+
+ if (unlikely(gve_alloc_qpl_page_dqo(rx, buf_state)))
+ goto free_buf_state;
+ }
+ }
+ desc->buf_id = cpu_to_le16(buf_state - rx->dqo.buf_states);
+ desc->buf_addr = cpu_to_le64(buf_state->addr +
+ buf_state->page_info.page_offset);
+
+ return 0;
+
+free_buf_state:
+ gve_free_buf_state(rx, buf_state);
+ return -ENOMEM;
+}
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 661566db68c8..e171ca248f9a 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1875,6 +1875,11 @@ static void gve_turndown(struct gve_priv *priv)
if (!gve_tx_was_added_to_block(priv, idx))
continue;
+
+ if (idx < priv->tx_cfg.num_queues)
+ netif_queue_set_napi(priv->dev, idx,
+ NETDEV_QUEUE_TYPE_TX, NULL);
+
napi_disable(&block->napi);
}
for (idx = 0; idx < priv->rx_cfg.num_queues; idx++) {
@@ -1883,6 +1888,9 @@ static void gve_turndown(struct gve_priv *priv)
if (!gve_rx_was_added_to_block(priv, idx))
continue;
+
+ netif_queue_set_napi(priv->dev, idx, NETDEV_QUEUE_TYPE_RX,
+ NULL);
napi_disable(&block->napi);
}
@@ -1909,6 +1917,12 @@ static void gve_turnup(struct gve_priv *priv)
continue;
napi_enable(&block->napi);
+
+ if (idx < priv->tx_cfg.num_queues)
+ netif_queue_set_napi(priv->dev, idx,
+ NETDEV_QUEUE_TYPE_TX,
+ &block->napi);
+
if (gve_is_gqi(priv)) {
iowrite32be(0, gve_irq_doorbell(priv, block));
} else {
@@ -1931,6 +1945,9 @@ static void gve_turnup(struct gve_priv *priv)
continue;
napi_enable(&block->napi);
+ netif_queue_set_napi(priv->dev, idx, NETDEV_QUEUE_TYPE_RX,
+ &block->napi);
+
if (gve_is_gqi(priv)) {
iowrite32be(0, gve_irq_doorbell(priv, block));
} else {
@@ -2544,6 +2561,54 @@ static const struct netdev_queue_mgmt_ops gve_queue_mgmt_ops = {
.ndo_queue_stop = gve_rx_queue_stop,
};
+static void gve_get_rx_queue_stats(struct net_device *dev, int idx,
+ struct netdev_queue_stats_rx *rx_stats)
+{
+ struct gve_priv *priv = netdev_priv(dev);
+ struct gve_rx_ring *rx = &priv->rx[idx];
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin(&rx->statss);
+ rx_stats->packets = rx->rpackets;
+ rx_stats->bytes = rx->rbytes;
+ rx_stats->alloc_fail = rx->rx_skb_alloc_fail +
+ rx->rx_buf_alloc_fail;
+ } while (u64_stats_fetch_retry(&rx->statss, start));
+}
+
+static void gve_get_tx_queue_stats(struct net_device *dev, int idx,
+ struct netdev_queue_stats_tx *tx_stats)
+{
+ struct gve_priv *priv = netdev_priv(dev);
+ struct gve_tx_ring *tx = &priv->tx[idx];
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin(&tx->statss);
+ tx_stats->packets = tx->pkt_done;
+ tx_stats->bytes = tx->bytes_done;
+ } while (u64_stats_fetch_retry(&tx->statss, start));
+}
+
+static void gve_get_base_stats(struct net_device *dev,
+ struct netdev_queue_stats_rx *rx,
+ struct netdev_queue_stats_tx *tx)
+{
+ rx->packets = 0;
+ rx->bytes = 0;
+ rx->alloc_fail = 0;
+
+ tx->packets = 0;
+ tx->bytes = 0;
+}
+
+static const struct netdev_stat_ops gve_stat_ops = {
+ .get_queue_stats_rx = gve_get_rx_queue_stats,
+ .get_queue_stats_tx = gve_get_tx_queue_stats,
+ .get_base_stats = gve_get_base_stats,
+};
+
static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int max_tx_queues, max_rx_queues;
@@ -2599,6 +2664,7 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->ethtool_ops = &gve_ethtool_ops;
dev->netdev_ops = &gve_netdev_ops;
dev->queue_mgmt_ops = &gve_queue_mgmt_ops;
+ dev->stat_ops = &gve_stat_ops;
/* Set default and supported features.
*
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index 1154c1d8f66f..8ac0047f1ada 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -16,189 +16,6 @@
#include <net/ipv6.h>
#include <net/tcp.h>
-static int gve_buf_ref_cnt(struct gve_rx_buf_state_dqo *bs)
-{
- return page_count(bs->page_info.page) - bs->page_info.pagecnt_bias;
-}
-
-static void gve_free_page_dqo(struct gve_priv *priv,
- struct gve_rx_buf_state_dqo *bs,
- bool free_page)
-{
- page_ref_sub(bs->page_info.page, bs->page_info.pagecnt_bias - 1);
- if (free_page)
- gve_free_page(&priv->pdev->dev, bs->page_info.page, bs->addr,
- DMA_FROM_DEVICE);
- bs->page_info.page = NULL;
-}
-
-static struct gve_rx_buf_state_dqo *gve_alloc_buf_state(struct gve_rx_ring *rx)
-{
- struct gve_rx_buf_state_dqo *buf_state;
- s16 buffer_id;
-
- buffer_id = rx->dqo.free_buf_states;
- if (unlikely(buffer_id == -1))
- return NULL;
-
- buf_state = &rx->dqo.buf_states[buffer_id];
-
- /* Remove buf_state from free list */
- rx->dqo.free_buf_states = buf_state->next;
-
- /* Point buf_state to itself to mark it as allocated */
- buf_state->next = buffer_id;
-
- return buf_state;
-}
-
-static bool gve_buf_state_is_allocated(struct gve_rx_ring *rx,
- struct gve_rx_buf_state_dqo *buf_state)
-{
- s16 buffer_id = buf_state - rx->dqo.buf_states;
-
- return buf_state->next == buffer_id;
-}
-
-static void gve_free_buf_state(struct gve_rx_ring *rx,
- struct gve_rx_buf_state_dqo *buf_state)
-{
- s16 buffer_id = buf_state - rx->dqo.buf_states;
-
- buf_state->next = rx->dqo.free_buf_states;
- rx->dqo.free_buf_states = buffer_id;
-}
-
-static struct gve_rx_buf_state_dqo *
-gve_dequeue_buf_state(struct gve_rx_ring *rx, struct gve_index_list *list)
-{
- struct gve_rx_buf_state_dqo *buf_state;
- s16 buffer_id;
-
- buffer_id = list->head;
- if (unlikely(buffer_id == -1))
- return NULL;
-
- buf_state = &rx->dqo.buf_states[buffer_id];
-
- /* Remove buf_state from list */
- list->head = buf_state->next;
- if (buf_state->next == -1)
- list->tail = -1;
-
- /* Point buf_state to itself to mark it as allocated */
- buf_state->next = buffer_id;
-
- return buf_state;
-}
-
-static void gve_enqueue_buf_state(struct gve_rx_ring *rx,
- struct gve_index_list *list,
- struct gve_rx_buf_state_dqo *buf_state)
-{
- s16 buffer_id = buf_state - rx->dqo.buf_states;
-
- buf_state->next = -1;
-
- if (list->head == -1) {
- list->head = buffer_id;
- list->tail = buffer_id;
- } else {
- int tail = list->tail;
-
- rx->dqo.buf_states[tail].next = buffer_id;
- list->tail = buffer_id;
- }
-}
-
-static struct gve_rx_buf_state_dqo *
-gve_get_recycled_buf_state(struct gve_rx_ring *rx)
-{
- struct gve_rx_buf_state_dqo *buf_state;
- int i;
-
- /* Recycled buf states are immediately usable. */
- buf_state = gve_dequeue_buf_state(rx, &rx->dqo.recycled_buf_states);
- if (likely(buf_state))
- return buf_state;
-
- if (unlikely(rx->dqo.used_buf_states.head == -1))
- return NULL;
-
- /* Used buf states are only usable when ref count reaches 0, which means
- * no SKBs refer to them.
- *
- * Search a limited number before giving up.
- */
- for (i = 0; i < 5; i++) {
- buf_state = gve_dequeue_buf_state(rx, &rx->dqo.used_buf_states);
- if (gve_buf_ref_cnt(buf_state) == 0) {
- rx->dqo.used_buf_states_cnt--;
- return buf_state;
- }
-
- gve_enqueue_buf_state(rx, &rx->dqo.used_buf_states, buf_state);
- }
-
- /* For QPL, we cannot allocate any new buffers and must
- * wait for the existing ones to be available.
- */
- if (rx->dqo.qpl)
- return NULL;
-
- /* If there are no free buf states discard an entry from
- * `used_buf_states` so it can be used.
- */
- if (unlikely(rx->dqo.free_buf_states == -1)) {
- buf_state = gve_dequeue_buf_state(rx, &rx->dqo.used_buf_states);
- if (gve_buf_ref_cnt(buf_state) == 0)
- return buf_state;
-
- gve_free_page_dqo(rx->gve, buf_state, true);
- gve_free_buf_state(rx, buf_state);
- }
-
- return NULL;
-}
-
-static int gve_alloc_page_dqo(struct gve_rx_ring *rx,
- struct gve_rx_buf_state_dqo *buf_state)
-{
- struct gve_priv *priv = rx->gve;
- u32 idx;
-
- if (!rx->dqo.qpl) {
- int err;
-
- err = gve_alloc_page(priv, &priv->pdev->dev,
- &buf_state->page_info.page,
- &buf_state->addr,
- DMA_FROM_DEVICE, GFP_ATOMIC);
- if (err)
- return err;
- } else {
- idx = rx->dqo.next_qpl_page_idx;
- if (idx >= gve_get_rx_pages_per_qpl_dqo(priv->rx_desc_cnt)) {
- net_err_ratelimited("%s: Out of QPL pages\n",
- priv->dev->name);
- return -ENOMEM;
- }
- buf_state->page_info.page = rx->dqo.qpl->pages[idx];
- buf_state->addr = rx->dqo.qpl->page_buses[idx];
- rx->dqo.next_qpl_page_idx++;
- }
- buf_state->page_info.page_offset = 0;
- buf_state->page_info.page_address =
- page_address(buf_state->page_info.page);
- buf_state->last_single_ref_offset = 0;
-
- /* The page already has 1 ref. */
- page_ref_add(buf_state->page_info.page, INT_MAX - 1);
- buf_state->page_info.pagecnt_bias = INT_MAX;
-
- return 0;
-}
-
static void gve_rx_free_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx)
{
struct device *hdev = &priv->pdev->dev;
@@ -278,8 +95,10 @@ static void gve_rx_reset_ring_dqo(struct gve_priv *priv, int idx)
for (i = 0; i < rx->dqo.num_buf_states; i++) {
struct gve_rx_buf_state_dqo *bs = &rx->dqo.buf_states[i];
- if (bs->page_info.page)
- gve_free_page_dqo(priv, bs, !rx->dqo.qpl);
+ if (rx->dqo.page_pool)
+ gve_free_to_page_pool(rx, bs, false);
+ else
+ gve_free_qpl_page_dqo(bs);
}
}
@@ -321,9 +140,11 @@ void gve_rx_free_ring_dqo(struct gve_priv *priv, struct gve_rx_ring *rx,
for (i = 0; i < rx->dqo.num_buf_states; i++) {
struct gve_rx_buf_state_dqo *bs = &rx->dqo.buf_states[i];
- /* Only free page for RDA. QPL pages are freed in gve_main. */
- if (bs->page_info.page)
- gve_free_page_dqo(priv, bs, !rx->dqo.qpl);
+
+ if (rx->dqo.page_pool)
+ gve_free_to_page_pool(rx, bs, false);
+ else
+ gve_free_qpl_page_dqo(bs);
}
if (rx->dqo.qpl) {
@@ -350,6 +171,11 @@ void gve_rx_free_ring_dqo(struct gve_priv *priv, struct gve_rx_ring *rx,
kvfree(rx->dqo.buf_states);
rx->dqo.buf_states = NULL;
+ if (rx->dqo.page_pool) {
+ page_pool_destroy(rx->dqo.page_pool);
+ rx->dqo.page_pool = NULL;
+ }
+
gve_rx_free_hdr_bufs(priv, rx);
netif_dbg(priv, drv, priv->dev, "freed rx ring %d\n", idx);
@@ -382,6 +208,7 @@ int gve_rx_alloc_ring_dqo(struct gve_priv *priv,
int idx)
{
struct device *hdev = &priv->pdev->dev;
+ struct page_pool *pool;
int qpl_page_cnt;
size_t size;
u32 qpl_id;
@@ -395,8 +222,7 @@ int gve_rx_alloc_ring_dqo(struct gve_priv *priv,
rx->gve = priv;
rx->q_num = idx;
- rx->dqo.num_buf_states = cfg->raw_addressing ?
- min_t(s16, S16_MAX, buffer_queue_slots * 4) :
+ rx->dqo.num_buf_states = cfg->raw_addressing ? buffer_queue_slots :
gve_get_rx_pages_per_qpl_dqo(cfg->ring_size);
rx->dqo.buf_states = kvcalloc(rx->dqo.num_buf_states,
sizeof(rx->dqo.buf_states[0]),
@@ -424,7 +250,13 @@ int gve_rx_alloc_ring_dqo(struct gve_priv *priv,
if (!rx->dqo.bufq.desc_ring)
goto err;
- if (!cfg->raw_addressing) {
+ if (cfg->raw_addressing) {
+ pool = gve_rx_create_page_pool(priv, rx);
+ if (IS_ERR(pool))
+ goto err;
+
+ rx->dqo.page_pool = pool;
+ } else {
qpl_id = gve_get_rx_qpl_id(cfg->qcfg_tx, rx->q_num);
qpl_page_cnt = gve_get_rx_pages_per_qpl_dqo(cfg->ring_size);
@@ -521,26 +353,14 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
num_avail_slots = min_t(u32, num_avail_slots, complq->num_free_slots);
while (num_posted < num_avail_slots) {
struct gve_rx_desc_dqo *desc = &bufq->desc_ring[bufq->tail];
- struct gve_rx_buf_state_dqo *buf_state;
-
- buf_state = gve_get_recycled_buf_state(rx);
- if (unlikely(!buf_state)) {
- buf_state = gve_alloc_buf_state(rx);
- if (unlikely(!buf_state))
- break;
-
- if (unlikely(gve_alloc_page_dqo(rx, buf_state))) {
- u64_stats_update_begin(&rx->statss);
- rx->rx_buf_alloc_fail++;
- u64_stats_update_end(&rx->statss);
- gve_free_buf_state(rx, buf_state);
- break;
- }
+
+ if (unlikely(gve_alloc_buffer(rx, desc))) {
+ u64_stats_update_begin(&rx->statss);
+ rx->rx_buf_alloc_fail++;
+ u64_stats_update_end(&rx->statss);
+ break;
}
- desc->buf_id = cpu_to_le16(buf_state - rx->dqo.buf_states);
- desc->buf_addr = cpu_to_le64(buf_state->addr +
- buf_state->page_info.page_offset);
if (rx->dqo.hdr_bufs.data)
desc->header_buf_addr =
cpu_to_le64(rx->dqo.hdr_bufs.addr +
@@ -557,48 +377,6 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
rx->fill_cnt += num_posted;
}
-static void gve_try_recycle_buf(struct gve_priv *priv, struct gve_rx_ring *rx,
- struct gve_rx_buf_state_dqo *buf_state)
-{
- const u16 data_buffer_size = priv->data_buffer_size_dqo;
- int pagecount;
-
- /* Can't reuse if we only fit one buffer per page */
- if (data_buffer_size * 2 > PAGE_SIZE)
- goto mark_used;
-
- pagecount = gve_buf_ref_cnt(buf_state);
-
- /* Record the offset when we have a single remaining reference.
- *
- * When this happens, we know all of the other offsets of the page are
- * usable.
- */
- if (pagecount == 1) {
- buf_state->last_single_ref_offset =
- buf_state->page_info.page_offset;
- }
-
- /* Use the next buffer sized chunk in the page. */
- buf_state->page_info.page_offset += data_buffer_size;
- buf_state->page_info.page_offset &= (PAGE_SIZE - 1);
-
- /* If we wrap around to the same offset without ever dropping to 1
- * reference, then we don't know if this offset was ever freed.
- */
- if (buf_state->page_info.page_offset ==
- buf_state->last_single_ref_offset) {
- goto mark_used;
- }
-
- gve_enqueue_buf_state(rx, &rx->dqo.recycled_buf_states, buf_state);
- return;
-
-mark_used:
- gve_enqueue_buf_state(rx, &rx->dqo.used_buf_states, buf_state);
- rx->dqo.used_buf_states_cnt++;
-}
-
static void gve_rx_skb_csum(struct sk_buff *skb,
const struct gve_rx_compl_desc_dqo *desc,
struct gve_ptype ptype)
@@ -713,6 +491,9 @@ static int gve_rx_append_frags(struct napi_struct *napi,
if (!skb)
return -1;
+ if (rx->dqo.page_pool)
+ skb_mark_for_recycle(skb);
+
if (rx->ctx.skb_tail == rx->ctx.skb_head)
skb_shinfo(rx->ctx.skb_head)->frag_list = skb;
else
@@ -723,7 +504,7 @@ static int gve_rx_append_frags(struct napi_struct *napi,
if (rx->ctx.skb_tail != rx->ctx.skb_head) {
rx->ctx.skb_head->len += buf_len;
rx->ctx.skb_head->data_len += buf_len;
- rx->ctx.skb_head->truesize += priv->data_buffer_size_dqo;
+ rx->ctx.skb_head->truesize += buf_state->page_info.buf_size;
}
/* Trigger ondemand page allocation if we are running low on buffers */
@@ -733,13 +514,8 @@ static int gve_rx_append_frags(struct napi_struct *napi,
skb_add_rx_frag(rx->ctx.skb_tail, num_frags,
buf_state->page_info.page,
buf_state->page_info.page_offset,
- buf_len, priv->data_buffer_size_dqo);
- gve_dec_pagecnt_bias(&buf_state->page_info);
-
- /* Advances buffer page-offset if page is partially used.
- * Marks buffer as used if page is full.
- */
- gve_try_recycle_buf(priv, rx, buf_state);
+ buf_len, buf_state->page_info.buf_size);
+ gve_reuse_buffer(rx, buf_state);
return 0;
}
@@ -773,8 +549,7 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx,
}
if (unlikely(compl_desc->rx_error)) {
- gve_enqueue_buf_state(rx, &rx->dqo.recycled_buf_states,
- buf_state);
+ gve_free_buffer(rx, buf_state);
return -EINVAL;
}
@@ -798,6 +573,9 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx,
if (unlikely(!rx->ctx.skb_head))
goto error;
rx->ctx.skb_tail = rx->ctx.skb_head;
+
+ if (rx->dqo.page_pool)
+ skb_mark_for_recycle(rx->ctx.skb_head);
} else {
unsplit = 1;
}
@@ -834,8 +612,7 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx,
rx->rx_copybreak_pkt++;
u64_stats_update_end(&rx->statss);
- gve_enqueue_buf_state(rx, &rx->dqo.recycled_buf_states,
- buf_state);
+ gve_free_buffer(rx, buf_state);
return 0;
}
@@ -850,16 +627,17 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx,
return 0;
}
+ if (rx->dqo.page_pool)
+ skb_mark_for_recycle(rx->ctx.skb_head);
+
skb_add_rx_frag(rx->ctx.skb_head, 0, buf_state->page_info.page,
buf_state->page_info.page_offset, buf_len,
- priv->data_buffer_size_dqo);
- gve_dec_pagecnt_bias(&buf_state->page_info);
-
- gve_try_recycle_buf(priv, rx, buf_state);
+ buf_state->page_info.buf_size);
+ gve_reuse_buffer(rx, buf_state);
return 0;
error:
- gve_enqueue_buf_state(rx, &rx->dqo.recycled_buf_states, buf_state);
+ gve_free_buffer(rx, buf_state);
return -ENOMEM;
}
diff --git a/drivers/net/ethernet/google/gve/gve_utils.c b/drivers/net/ethernet/google/gve/gve_utils.c
index 2349750075a5..30fef100257e 100644
--- a/drivers/net/ethernet/google/gve/gve_utils.c
+++ b/drivers/net/ethernet/google/gve/gve_utils.c
@@ -111,6 +111,7 @@ void gve_add_napi(struct gve_priv *priv, int ntfy_idx,
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
netif_napi_add(priv->dev, &block->napi, gve_poll);
+ netif_napi_set_irq(&block->napi, block->irq);
}
void gve_remove_napi(struct gve_priv *priv, int ntfy_idx)
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index 3312e1d93c3b..65302c41bfb1 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -7,7 +7,6 @@ config NET_VENDOR_HISILICON
bool "Hisilicon devices"
default y
depends on OF || ACPI
- depends on ARM || ARM64 || COMPILE_TEST
help
If you have a network (Ethernet) card belonging to this class, say Y.
@@ -18,6 +17,8 @@ config NET_VENDOR_HISILICON
if NET_VENDOR_HISILICON
+if ARM || ARM64 || COMPILE_TEST
+
config HIX5HD2_GMAC
tristate "Hisilicon HIX5HD2 Family Network Device Support"
select PHYLIB
@@ -141,4 +142,19 @@ config HNS3_ENET
endif #HNS3
+endif # ARM || ARM64 || COMPILE_TEST
+
+config HIBMCGE
+ tristate "Hisilicon BMC Gigabit Ethernet Device Support"
+ depends on PCI && PCI_MSI
+ select PHYLIB
+ select MOTORCOMM_PHY
+ select REALTEK_PHY
+ help
+ If you wish to compile a kernel for a BMC with HIBMC-xx_gmac
+ then you should answer Y to this. This makes this driver suitable for use
+ on certain boards such as the HIBMC-210.
+
+ If you are unsure, say N.
+
endif # NET_VENDOR_HISILICON
diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile
index 7f76d412047a..0e2cadfea8ff 100644
--- a/drivers/net/ethernet/hisilicon/Makefile
+++ b/drivers/net/ethernet/hisilicon/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_HNS_MDIO) += hns_mdio.o
obj-$(CONFIG_HNS) += hns/
obj-$(CONFIG_HNS3) += hns3/
obj-$(CONFIG_HISI_FEMAC) += hisi_femac.o
+obj-$(CONFIG_HIBMCGE) += hibmcge/
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/Makefile b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
new file mode 100644
index 000000000000..ae58ac38c206
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Makefile for the HISILICON BMC GE network device drivers.
+#
+
+obj-$(CONFIG_HIBMCGE) += hibmcge.o
+
+hibmcge-objs = hbg_main.o hbg_hw.o hbg_mdio.o hbg_irq.o hbg_txrx.o hbg_ethtool.o
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
new file mode 100644
index 000000000000..96daf058d387
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_COMMON_H
+#define __HBG_COMMON_H
+
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include "hbg_reg.h"
+
+#define HBG_STATUS_DISABLE 0x0
+#define HBG_STATUS_ENABLE 0x1
+#define HBG_RX_SKIP1 0x00
+#define HBG_RX_SKIP2 0x01
+#define HBG_VECTOR_NUM 4
+#define HBG_PCU_CACHE_LINE_SIZE 32
+#define HBG_TX_TIMEOUT_BUF_LEN 1024
+#define HBG_RX_DESCR 0x01
+
+#define HBG_PACKET_HEAD_SIZE ((HBG_RX_SKIP1 + HBG_RX_SKIP2 + \
+ HBG_RX_DESCR) * HBG_PCU_CACHE_LINE_SIZE)
+
+enum hbg_dir {
+ HBG_DIR_TX = 1 << 0,
+ HBG_DIR_RX = 1 << 1,
+ HBG_DIR_TX_RX = HBG_DIR_TX | HBG_DIR_RX,
+};
+
+enum hbg_tx_state {
+ HBG_TX_STATE_COMPLETE = 0, /* clear state, must fix to 0 */
+ HBG_TX_STATE_START,
+};
+
+enum hbg_nic_state {
+ HBG_NIC_STATE_EVENT_HANDLING = 0,
+};
+
+struct hbg_buffer {
+ u32 state;
+ dma_addr_t state_dma;
+
+ struct sk_buff *skb;
+ dma_addr_t skb_dma;
+ u32 skb_len;
+
+ enum hbg_dir dir;
+ struct hbg_ring *ring;
+ struct hbg_priv *priv;
+};
+
+struct hbg_ring {
+ struct hbg_buffer *queue;
+ dma_addr_t queue_dma;
+
+ union {
+ u32 head;
+ u32 ntc;
+ };
+ union {
+ u32 tail;
+ u32 ntu;
+ };
+ u32 len;
+
+ enum hbg_dir dir;
+ struct hbg_priv *priv;
+ struct napi_struct napi;
+ char *tout_log_buf; /* tx timeout log buffer */
+};
+
+enum hbg_hw_event_type {
+ HBG_HW_EVENT_NONE = 0,
+ HBG_HW_EVENT_INIT, /* driver is loading */
+ HBG_HW_EVENT_RESET,
+};
+
+struct hbg_dev_specs {
+ u32 mac_id;
+ struct sockaddr mac_addr;
+ u32 phy_addr;
+ u32 mdio_frequency;
+ u32 rx_fifo_num;
+ u32 tx_fifo_num;
+ u32 vlan_layers;
+ u32 max_mtu;
+ u32 min_mtu;
+
+ u32 max_frame_len;
+ u32 rx_buf_size;
+};
+
+struct hbg_irq_info {
+ const char *name;
+ u32 mask;
+ bool re_enable;
+ bool need_print;
+ u64 count;
+
+ void (*irq_handle)(struct hbg_priv *priv, struct hbg_irq_info *info);
+};
+
+struct hbg_vector {
+ char name[HBG_VECTOR_NUM][32];
+ struct hbg_irq_info *info_array;
+ u32 info_array_len;
+};
+
+struct hbg_mac {
+ struct mii_bus *mdio_bus;
+ struct phy_device *phydev;
+ u8 phy_addr;
+
+ u32 speed;
+ u32 duplex;
+ u32 autoneg;
+ u32 link_status;
+};
+
+struct hbg_priv {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ u8 __iomem *io_base;
+ struct hbg_dev_specs dev_specs;
+ unsigned long state;
+ struct hbg_mac mac;
+ struct hbg_vector vectors;
+ struct hbg_ring tx_ring;
+ struct hbg_ring rx_ring;
+};
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
new file mode 100644
index 000000000000..c3370114aef3
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include "hbg_ethtool.h"
+
+static const struct ethtool_ops hbg_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_link_ksettings = phy_ethtool_get_link_ksettings,
+ .set_link_ksettings = phy_ethtool_set_link_ksettings,
+};
+
+void hbg_ethtool_set_ops(struct net_device *netdev)
+{
+ netdev->ethtool_ops = &hbg_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h
new file mode 100644
index 000000000000..628707ec2686
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_ETHTOOL_H
+#define __HBG_ETHTOOL_H
+
+#include <linux/netdevice.h>
+
+void hbg_ethtool_set_ops(struct net_device *netdev);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
new file mode 100644
index 000000000000..05295c2ad439
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/iopoll.h>
+#include <linux/minmax.h>
+#include "hbg_common.h"
+#include "hbg_hw.h"
+#include "hbg_reg.h"
+
+#define HBG_HW_EVENT_WAIT_TIMEOUT_US (2 * 1000 * 1000)
+#define HBG_HW_EVENT_WAIT_INTERVAL_US (10 * 1000)
+/* little endian or big endian.
+ * ctrl means packet description, data means skb packet data
+ */
+#define HBG_ENDIAN_CTRL_LE_DATA_BE 0x0
+#define HBG_PCU_FRAME_LEN_PLUS 4
+
+static bool hbg_hw_spec_is_valid(struct hbg_priv *priv)
+{
+ return hbg_reg_read(priv, HBG_REG_SPEC_VALID_ADDR) &&
+ !hbg_reg_read(priv, HBG_REG_EVENT_REQ_ADDR);
+}
+
+int hbg_hw_event_notify(struct hbg_priv *priv,
+ enum hbg_hw_event_type event_type)
+{
+ bool is_valid;
+ int ret;
+
+ if (test_and_set_bit(HBG_NIC_STATE_EVENT_HANDLING, &priv->state))
+ return -EBUSY;
+
+ /* notify */
+ hbg_reg_write(priv, HBG_REG_EVENT_REQ_ADDR, event_type);
+
+ ret = read_poll_timeout(hbg_hw_spec_is_valid, is_valid, is_valid,
+ HBG_HW_EVENT_WAIT_INTERVAL_US,
+ HBG_HW_EVENT_WAIT_TIMEOUT_US,
+ HBG_HW_EVENT_WAIT_INTERVAL_US, priv);
+
+ clear_bit(HBG_NIC_STATE_EVENT_HANDLING, &priv->state);
+
+ if (ret)
+ dev_err(&priv->pdev->dev,
+ "event %d wait timeout\n", event_type);
+
+ return ret;
+}
+
+static int hbg_hw_dev_specs_init(struct hbg_priv *priv)
+{
+ struct hbg_dev_specs *specs = &priv->dev_specs;
+ u64 mac_addr;
+
+ if (!hbg_hw_spec_is_valid(priv)) {
+ dev_err(&priv->pdev->dev, "dev_specs not init\n");
+ return -EINVAL;
+ }
+
+ specs->mac_id = hbg_reg_read(priv, HBG_REG_MAC_ID_ADDR);
+ specs->phy_addr = hbg_reg_read(priv, HBG_REG_PHY_ID_ADDR);
+ specs->mdio_frequency = hbg_reg_read(priv, HBG_REG_MDIO_FREQ_ADDR);
+ specs->max_mtu = hbg_reg_read(priv, HBG_REG_MAX_MTU_ADDR);
+ specs->min_mtu = hbg_reg_read(priv, HBG_REG_MIN_MTU_ADDR);
+ specs->vlan_layers = hbg_reg_read(priv, HBG_REG_VLAN_LAYERS_ADDR);
+ specs->rx_fifo_num = hbg_reg_read(priv, HBG_REG_RX_FIFO_NUM_ADDR);
+ specs->tx_fifo_num = hbg_reg_read(priv, HBG_REG_TX_FIFO_NUM_ADDR);
+ mac_addr = hbg_reg_read64(priv, HBG_REG_MAC_ADDR_ADDR);
+ u64_to_ether_addr(mac_addr, (u8 *)specs->mac_addr.sa_data);
+
+ if (!is_valid_ether_addr((u8 *)specs->mac_addr.sa_data))
+ return -EADDRNOTAVAIL;
+
+ specs->max_frame_len = HBG_PCU_CACHE_LINE_SIZE + specs->max_mtu;
+ specs->rx_buf_size = HBG_PACKET_HEAD_SIZE + specs->max_frame_len;
+ return 0;
+}
+
+u32 hbg_hw_get_irq_status(struct hbg_priv *priv)
+{
+ u32 status;
+
+ status = hbg_reg_read(priv, HBG_REG_CF_INTRPT_STAT_ADDR);
+
+ hbg_field_modify(status, HBG_INT_MSK_TX_B,
+ hbg_reg_read(priv, HBG_REG_CF_IND_TXINT_STAT_ADDR));
+ hbg_field_modify(status, HBG_INT_MSK_RX_B,
+ hbg_reg_read(priv, HBG_REG_CF_IND_RXINT_STAT_ADDR));
+
+ return status;
+}
+
+void hbg_hw_irq_clear(struct hbg_priv *priv, u32 mask)
+{
+ if (FIELD_GET(HBG_INT_MSK_TX_B, mask))
+ return hbg_reg_write(priv, HBG_REG_CF_IND_TXINT_CLR_ADDR, 0x1);
+
+ if (FIELD_GET(HBG_INT_MSK_RX_B, mask))
+ return hbg_reg_write(priv, HBG_REG_CF_IND_RXINT_CLR_ADDR, 0x1);
+
+ return hbg_reg_write(priv, HBG_REG_CF_INTRPT_CLR_ADDR, mask);
+}
+
+bool hbg_hw_irq_is_enabled(struct hbg_priv *priv, u32 mask)
+{
+ if (FIELD_GET(HBG_INT_MSK_TX_B, mask))
+ return hbg_reg_read(priv, HBG_REG_CF_IND_TXINT_MSK_ADDR);
+
+ if (FIELD_GET(HBG_INT_MSK_RX_B, mask))
+ return hbg_reg_read(priv, HBG_REG_CF_IND_RXINT_MSK_ADDR);
+
+ return hbg_reg_read(priv, HBG_REG_CF_INTRPT_MSK_ADDR) & mask;
+}
+
+void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable)
+{
+ u32 value;
+
+ if (FIELD_GET(HBG_INT_MSK_TX_B, mask))
+ return hbg_reg_write(priv,
+ HBG_REG_CF_IND_TXINT_MSK_ADDR, enable);
+
+ if (FIELD_GET(HBG_INT_MSK_RX_B, mask))
+ return hbg_reg_write(priv,
+ HBG_REG_CF_IND_RXINT_MSK_ADDR, enable);
+
+ value = hbg_reg_read(priv, HBG_REG_CF_INTRPT_MSK_ADDR);
+ if (enable)
+ value |= mask;
+ else
+ value &= ~mask;
+
+ hbg_reg_write(priv, HBG_REG_CF_INTRPT_MSK_ADDR, value);
+}
+
+void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr)
+{
+ hbg_reg_write64(priv, HBG_REG_STATION_ADDR_LOW_2_ADDR, mac_addr);
+}
+
+static void hbg_hw_set_pcu_max_frame_len(struct hbg_priv *priv,
+ u16 max_frame_len)
+{
+ max_frame_len = max_t(u32, max_frame_len, ETH_DATA_LEN);
+
+ /* lower two bits of value must be set to 0 */
+ max_frame_len = round_up(max_frame_len, HBG_PCU_FRAME_LEN_PLUS);
+
+ hbg_reg_write_field(priv, HBG_REG_MAX_FRAME_LEN_ADDR,
+ HBG_REG_MAX_FRAME_LEN_M, max_frame_len);
+}
+
+static void hbg_hw_set_mac_max_frame_len(struct hbg_priv *priv,
+ u16 max_frame_size)
+{
+ hbg_reg_write_field(priv, HBG_REG_MAX_FRAME_SIZE_ADDR,
+ HBG_REG_MAX_FRAME_LEN_M, max_frame_size);
+}
+
+void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu)
+{
+ hbg_hw_set_pcu_max_frame_len(priv, mtu);
+ hbg_hw_set_mac_max_frame_len(priv, mtu);
+}
+
+void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable)
+{
+ hbg_reg_write_field(priv, HBG_REG_PORT_ENABLE_ADDR,
+ HBG_REG_PORT_ENABLE_TX_B, enable);
+ hbg_reg_write_field(priv, HBG_REG_PORT_ENABLE_ADDR,
+ HBG_REG_PORT_ENABLE_RX_B, enable);
+}
+
+u32 hbg_hw_get_fifo_used_num(struct hbg_priv *priv, enum hbg_dir dir)
+{
+ if (dir & HBG_DIR_TX)
+ return hbg_reg_read_field(priv, HBG_REG_CF_CFF_DATA_NUM_ADDR,
+ HBG_REG_CF_CFF_DATA_NUM_ADDR_TX_M);
+
+ if (dir & HBG_DIR_RX)
+ return hbg_reg_read_field(priv, HBG_REG_CF_CFF_DATA_NUM_ADDR,
+ HBG_REG_CF_CFF_DATA_NUM_ADDR_RX_M);
+
+ return 0;
+}
+
+void hbg_hw_set_tx_desc(struct hbg_priv *priv, struct hbg_tx_desc *tx_desc)
+{
+ hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_0_ADDR, tx_desc->word0);
+ hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_1_ADDR, tx_desc->word1);
+ hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_2_ADDR, tx_desc->word2);
+ hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_3_ADDR, tx_desc->word3);
+}
+
+void hbg_hw_fill_buffer(struct hbg_priv *priv, u32 buffer_dma_addr)
+{
+ hbg_reg_write(priv, HBG_REG_RX_CFF_ADDR_ADDR, buffer_dma_addr);
+}
+
+void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex)
+{
+ hbg_reg_write_field(priv, HBG_REG_PORT_MODE_ADDR,
+ HBG_REG_PORT_MODE_M, speed);
+ hbg_reg_write_field(priv, HBG_REG_DUPLEX_TYPE_ADDR,
+ HBG_REG_DUPLEX_B, duplex);
+}
+
+static void hbg_hw_init_transmit_ctrl(struct hbg_priv *priv)
+{
+ u32 ctrl = 0;
+
+ ctrl |= FIELD_PREP(HBG_REG_TRANSMIT_CTRL_AN_EN_B, HBG_STATUS_ENABLE);
+ ctrl |= FIELD_PREP(HBG_REG_TRANSMIT_CTRL_CRC_ADD_B, HBG_STATUS_ENABLE);
+ ctrl |= FIELD_PREP(HBG_REG_TRANSMIT_CTRL_PAD_EN_B, HBG_STATUS_ENABLE);
+
+ hbg_reg_write(priv, HBG_REG_TRANSMIT_CTRL_ADDR, ctrl);
+}
+
+static void hbg_hw_init_rx_ctrl(struct hbg_priv *priv)
+{
+ u32 ctrl = 0;
+
+ ctrl |= FIELD_PREP(HBG_REG_RX_CTRL_RX_GET_ADDR_MODE_B,
+ HBG_STATUS_ENABLE);
+ ctrl |= FIELD_PREP(HBG_REG_RX_CTRL_TIME_INF_EN_B, HBG_STATUS_DISABLE);
+ ctrl |= FIELD_PREP(HBG_REG_RX_CTRL_RXBUF_1ST_SKIP_SIZE_M, HBG_RX_SKIP1);
+ ctrl |= FIELD_PREP(HBG_REG_RX_CTRL_RXBUF_1ST_SKIP_SIZE2_M,
+ HBG_RX_SKIP2);
+ ctrl |= FIELD_PREP(HBG_REG_RX_CTRL_RX_ALIGN_NUM_M, NET_IP_ALIGN);
+ ctrl |= FIELD_PREP(HBG_REG_RX_CTRL_PORT_NUM, priv->dev_specs.mac_id);
+
+ hbg_reg_write(priv, HBG_REG_RX_CTRL_ADDR, ctrl);
+}
+
+static void hbg_hw_init_rx_control(struct hbg_priv *priv)
+{
+ hbg_hw_init_rx_ctrl(priv);
+
+ /* parse from L2 layer */
+ hbg_reg_write_field(priv, HBG_REG_RX_PKT_MODE_ADDR,
+ HBG_REG_RX_PKT_MODE_PARSE_MODE_M, 0x1);
+
+ hbg_reg_write_field(priv, HBG_REG_RECV_CTRL_ADDR,
+ HBG_REG_RECV_CTRL_STRIP_PAD_EN_B,
+ HBG_STATUS_ENABLE);
+ hbg_reg_write_field(priv, HBG_REG_RX_BUF_SIZE_ADDR,
+ HBG_REG_RX_BUF_SIZE_M, priv->dev_specs.rx_buf_size);
+ hbg_reg_write_field(priv, HBG_REG_CF_CRC_STRIP_ADDR,
+ HBG_REG_CF_CRC_STRIP_B, HBG_STATUS_DISABLE);
+}
+
+int hbg_hw_init(struct hbg_priv *priv)
+{
+ int ret;
+
+ ret = hbg_hw_dev_specs_init(priv);
+ if (ret)
+ return ret;
+
+ hbg_reg_write_field(priv, HBG_REG_BUS_CTRL_ADDR,
+ HBG_REG_BUS_CTRL_ENDIAN_M,
+ HBG_ENDIAN_CTRL_LE_DATA_BE);
+ hbg_reg_write_field(priv, HBG_REG_MODE_CHANGE_EN_ADDR,
+ HBG_REG_MODE_CHANGE_EN_B, HBG_STATUS_ENABLE);
+
+ hbg_hw_init_rx_control(priv);
+ hbg_hw_init_transmit_ctrl(priv);
+ return 0;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
new file mode 100644
index 000000000000..14fb39241c93
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_HW_H
+#define __HBG_HW_H
+
+#include <linux/bitfield.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+
+static inline u32 hbg_reg_read(struct hbg_priv *priv, u32 addr)
+{
+ return readl(priv->io_base + addr);
+}
+
+static inline void hbg_reg_write(struct hbg_priv *priv, u32 addr, u32 value)
+{
+ writel(value, priv->io_base + addr);
+}
+
+static inline u64 hbg_reg_read64(struct hbg_priv *priv, u32 addr)
+{
+ return lo_hi_readq(priv->io_base + addr);
+}
+
+static inline void hbg_reg_write64(struct hbg_priv *priv, u32 addr, u64 value)
+{
+ lo_hi_writeq(value, priv->io_base + addr);
+}
+
+#define hbg_reg_read_field(priv, addr, mask) \
+ FIELD_GET(mask, hbg_reg_read(priv, addr))
+
+#define hbg_field_modify(reg_value, mask, value) ({ \
+ (reg_value) &= ~(mask); \
+ (reg_value) |= FIELD_PREP(mask, value); })
+
+#define hbg_reg_write_field(priv, addr, mask, val) ({ \
+ typeof(priv) _priv = (priv); \
+ typeof(addr) _addr = (addr); \
+ u32 _value = hbg_reg_read(_priv, _addr); \
+ hbg_field_modify(_value, mask, val); \
+ hbg_reg_write(_priv, _addr, _value); })
+
+int hbg_hw_event_notify(struct hbg_priv *priv,
+ enum hbg_hw_event_type event_type);
+int hbg_hw_init(struct hbg_priv *priv);
+void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex);
+u32 hbg_hw_get_irq_status(struct hbg_priv *priv);
+void hbg_hw_irq_clear(struct hbg_priv *priv, u32 mask);
+bool hbg_hw_irq_is_enabled(struct hbg_priv *priv, u32 mask);
+void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable);
+void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu);
+void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable);
+void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr);
+u32 hbg_hw_get_fifo_used_num(struct hbg_priv *priv, enum hbg_dir dir);
+void hbg_hw_set_tx_desc(struct hbg_priv *priv, struct hbg_tx_desc *tx_desc);
+void hbg_hw_fill_buffer(struct hbg_priv *priv, u32 buffer_dma_addr);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c
new file mode 100644
index 000000000000..25dd25f096fe
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/interrupt.h>
+#include "hbg_irq.h"
+#include "hbg_hw.h"
+
+static void hbg_irq_handle_err(struct hbg_priv *priv,
+ struct hbg_irq_info *irq_info)
+{
+ if (irq_info->need_print)
+ dev_err(&priv->pdev->dev,
+ "receive error interrupt: %s\n", irq_info->name);
+}
+
+static void hbg_irq_handle_tx(struct hbg_priv *priv,
+ struct hbg_irq_info *irq_info)
+{
+ napi_schedule(&priv->tx_ring.napi);
+}
+
+static void hbg_irq_handle_rx(struct hbg_priv *priv,
+ struct hbg_irq_info *irq_info)
+{
+ napi_schedule(&priv->rx_ring.napi);
+}
+
+#define HBG_TXRX_IRQ_I(name, handle) \
+ {#name, HBG_INT_MSK_##name##_B, false, false, 0, handle}
+#define HBG_ERR_IRQ_I(name, need_print) \
+ {#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err}
+
+static struct hbg_irq_info hbg_irqs[] = {
+ HBG_TXRX_IRQ_I(RX, hbg_irq_handle_rx),
+ HBG_TXRX_IRQ_I(TX, hbg_irq_handle_tx),
+ HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true),
+ HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true),
+ HBG_ERR_IRQ_I(TX_AHB_ERR, true),
+ HBG_ERR_IRQ_I(RX_BUF_AVL, false),
+ HBG_ERR_IRQ_I(REL_BUF_ERR, true),
+ HBG_ERR_IRQ_I(TXCFG_AVL, false),
+ HBG_ERR_IRQ_I(TX_DROP, false),
+ HBG_ERR_IRQ_I(RX_DROP, false),
+ HBG_ERR_IRQ_I(RX_AHB_ERR, true),
+ HBG_ERR_IRQ_I(MAC_FIFO_ERR, false),
+ HBG_ERR_IRQ_I(RBREQ_ERR, false),
+ HBG_ERR_IRQ_I(WE_ERR, false),
+};
+
+static irqreturn_t hbg_irq_handle(int irq_num, void *p)
+{
+ struct hbg_irq_info *info;
+ struct hbg_priv *priv = p;
+ u32 status;
+ u32 i;
+
+ status = hbg_hw_get_irq_status(priv);
+ for (i = 0; i < priv->vectors.info_array_len; i++) {
+ info = &priv->vectors.info_array[i];
+ if (status & info->mask) {
+ if (!hbg_hw_irq_is_enabled(priv, info->mask))
+ continue;
+
+ hbg_hw_irq_enable(priv, info->mask, false);
+ hbg_hw_irq_clear(priv, info->mask);
+
+ info->count++;
+ if (info->irq_handle)
+ info->irq_handle(priv, info);
+
+ if (info->re_enable)
+ hbg_hw_irq_enable(priv, info->mask, true);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static const char *irq_names_map[HBG_VECTOR_NUM] = { "tx", "rx",
+ "err", "mdio" };
+
+int hbg_irq_init(struct hbg_priv *priv)
+{
+ struct hbg_vector *vectors = &priv->vectors;
+ struct device *dev = &priv->pdev->dev;
+ int ret, id;
+ u32 i;
+
+ /* used pcim_enable_device(), so the vectors become device managed */
+ ret = pci_alloc_irq_vectors(priv->pdev, HBG_VECTOR_NUM, HBG_VECTOR_NUM,
+ PCI_IRQ_MSI | PCI_IRQ_MSIX);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to allocate vectors\n");
+
+ if (ret != HBG_VECTOR_NUM)
+ return dev_err_probe(dev, -EINVAL,
+ "requested %u MSI, but allocated %d MSI\n",
+ HBG_VECTOR_NUM, ret);
+
+ /* mdio irq not requested, so the number of requested interrupts
+ * is HBG_VECTOR_NUM - 1.
+ */
+ for (i = 0; i < HBG_VECTOR_NUM - 1; i++) {
+ id = pci_irq_vector(priv->pdev, i);
+ if (id < 0)
+ return dev_err_probe(dev, id, "failed to get irq id\n");
+
+ snprintf(vectors->name[i], sizeof(vectors->name[i]), "%s-%s-%s",
+ dev_driver_string(dev), pci_name(priv->pdev),
+ irq_names_map[i]);
+
+ ret = devm_request_irq(dev, id, hbg_irq_handle, 0,
+ vectors->name[i], priv);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to request irq: %s\n",
+ irq_names_map[i]);
+ }
+
+ vectors->info_array = hbg_irqs;
+ vectors->info_array_len = ARRAY_SIZE(hbg_irqs);
+ return 0;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h
new file mode 100644
index 000000000000..5c5323cfc751
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_IRQ_H
+#define __HBG_IRQ_H
+
+#include "hbg_common.h"
+
+int hbg_irq_init(struct hbg_priv *priv);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
new file mode 100644
index 000000000000..75505fb5cc4a
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include "hbg_common.h"
+#include "hbg_ethtool.h"
+#include "hbg_hw.h"
+#include "hbg_irq.h"
+#include "hbg_mdio.h"
+#include "hbg_txrx.h"
+
+static void hbg_change_mtu(struct hbg_priv *priv, int new_mtu);
+
+static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled)
+{
+ struct hbg_irq_info *info;
+ u32 i;
+
+ for (i = 0; i < priv->vectors.info_array_len; i++) {
+ info = &priv->vectors.info_array[i];
+ hbg_hw_irq_enable(priv, info->mask, enabled);
+ }
+}
+
+static int hbg_net_open(struct net_device *netdev)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+ int ret;
+
+ ret = hbg_txrx_init(priv);
+ if (ret)
+ return ret;
+
+ hbg_all_irq_enable(priv, true);
+ hbg_hw_mac_enable(priv, HBG_STATUS_ENABLE);
+ netif_start_queue(netdev);
+ hbg_phy_start(priv);
+
+ return 0;
+}
+
+/* This function only can be called after hbg_txrx_uninit() */
+static int hbg_hw_txrx_clear(struct hbg_priv *priv)
+{
+ int ret;
+
+ /* After ring buffers have been released,
+ * do a reset to release hw fifo rx ring buffer
+ */
+ ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_RESET);
+ if (ret)
+ return ret;
+
+ /* After reset, regs need to be reconfigured */
+ hbg_hw_init(priv);
+ hbg_hw_set_uc_addr(priv, ether_addr_to_u64(priv->netdev->dev_addr));
+ hbg_change_mtu(priv, priv->netdev->mtu);
+
+ return 0;
+}
+
+static int hbg_net_stop(struct net_device *netdev)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ hbg_phy_stop(priv);
+ netif_stop_queue(netdev);
+ hbg_hw_mac_enable(priv, HBG_STATUS_DISABLE);
+ hbg_all_irq_enable(priv, false);
+ hbg_txrx_uninit(priv);
+ return hbg_hw_txrx_clear(priv);
+}
+
+static int hbg_net_set_mac_address(struct net_device *netdev, void *addr)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+ u8 *mac_addr;
+
+ mac_addr = ((struct sockaddr *)addr)->sa_data;
+
+ if (!is_valid_ether_addr(mac_addr))
+ return -EADDRNOTAVAIL;
+
+ hbg_hw_set_uc_addr(priv, ether_addr_to_u64(mac_addr));
+ dev_addr_set(netdev, mac_addr);
+
+ return 0;
+}
+
+static void hbg_change_mtu(struct hbg_priv *priv, int new_mtu)
+{
+ u32 frame_len;
+
+ frame_len = new_mtu + VLAN_HLEN * priv->dev_specs.vlan_layers +
+ ETH_HLEN + ETH_FCS_LEN;
+ hbg_hw_set_mtu(priv, frame_len);
+}
+
+static int hbg_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ hbg_change_mtu(priv, new_mtu);
+ WRITE_ONCE(netdev->mtu, new_mtu);
+
+ dev_dbg(&priv->pdev->dev,
+ "change mtu from %u to %u\n", netdev->mtu, new_mtu);
+
+ return 0;
+}
+
+static void hbg_net_tx_timeout(struct net_device *netdev, unsigned int txqueue)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+ struct hbg_ring *ring = &priv->tx_ring;
+ char *buf = ring->tout_log_buf;
+ u32 pos = 0;
+
+ pos += scnprintf(buf + pos, HBG_TX_TIMEOUT_BUF_LEN - pos,
+ "ring used num: %u, fifo used num: %u\n",
+ hbg_get_queue_used_num(ring),
+ hbg_hw_get_fifo_used_num(priv, HBG_DIR_TX));
+ pos += scnprintf(buf + pos, HBG_TX_TIMEOUT_BUF_LEN - pos,
+ "ntc: %u, ntu: %u, irq enabled: %u\n",
+ ring->ntc, ring->ntu,
+ hbg_hw_irq_is_enabled(priv, HBG_INT_MSK_TX_B));
+
+ netdev_info(netdev, "%s", buf);
+}
+
+static const struct net_device_ops hbg_netdev_ops = {
+ .ndo_open = hbg_net_open,
+ .ndo_stop = hbg_net_stop,
+ .ndo_start_xmit = hbg_net_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = hbg_net_set_mac_address,
+ .ndo_change_mtu = hbg_net_change_mtu,
+ .ndo_tx_timeout = hbg_net_tx_timeout,
+};
+
+static int hbg_init(struct hbg_priv *priv)
+{
+ int ret;
+
+ ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_INIT);
+ if (ret)
+ return ret;
+
+ ret = hbg_hw_init(priv);
+ if (ret)
+ return ret;
+
+ ret = hbg_irq_init(priv);
+ if (ret)
+ return ret;
+
+ return hbg_mdio_init(priv);
+}
+
+static int hbg_pci_init(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct hbg_priv *priv = netdev_priv(netdev);
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable PCI device\n");
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set PCI DMA mask\n");
+
+ ret = pcim_iomap_regions(pdev, BIT(0), dev_driver_string(dev));
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to map PCI bar space\n");
+
+ priv->io_base = pcim_iomap_table(pdev)[0];
+ if (!priv->io_base)
+ return dev_err_probe(dev, -ENOMEM, "failed to get io base\n");
+
+ pci_set_master(pdev);
+ return 0;
+}
+
+static int hbg_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ struct net_device *netdev;
+ struct hbg_priv *priv;
+ int ret;
+
+ netdev = devm_alloc_etherdev(dev, sizeof(struct hbg_priv));
+ if (!netdev)
+ return -ENOMEM;
+
+ pci_set_drvdata(pdev, netdev);
+ SET_NETDEV_DEV(netdev, dev);
+
+ priv = netdev_priv(netdev);
+ priv->netdev = netdev;
+ priv->pdev = pdev;
+
+ ret = hbg_pci_init(pdev);
+ if (ret)
+ return ret;
+
+ ret = hbg_init(priv);
+ if (ret)
+ return ret;
+
+ netdev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
+ netdev->max_mtu = priv->dev_specs.max_mtu;
+ netdev->min_mtu = priv->dev_specs.min_mtu;
+ netdev->netdev_ops = &hbg_netdev_ops;
+ netdev->watchdog_timeo = 5 * HZ;
+
+ hbg_change_mtu(priv, ETH_DATA_LEN);
+ hbg_net_set_mac_address(priv->netdev, &priv->dev_specs.mac_addr);
+ hbg_ethtool_set_ops(netdev);
+
+ ret = devm_register_netdev(dev, netdev);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register netdev\n");
+
+ netif_carrier_off(netdev);
+ return 0;
+}
+
+static const struct pci_device_id hbg_pci_tbl[] = {
+ {PCI_VDEVICE(HUAWEI, 0x3730), 0},
+ { }
+};
+MODULE_DEVICE_TABLE(pci, hbg_pci_tbl);
+
+static struct pci_driver hbg_driver = {
+ .name = "hibmcge",
+ .id_table = hbg_pci_tbl,
+ .probe = hbg_probe,
+};
+module_pci_driver(hbg_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
+MODULE_DESCRIPTION("hibmcge driver");
+MODULE_VERSION("1.0");
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c
new file mode 100644
index 000000000000..a3479fba8501
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/phy.h>
+#include "hbg_common.h"
+#include "hbg_hw.h"
+#include "hbg_mdio.h"
+#include "hbg_reg.h"
+
+#define HBG_MAC_GET_PRIV(mac) ((struct hbg_priv *)(mac)->mdio_bus->priv)
+#define HBG_MII_BUS_GET_MAC(bus) (&((struct hbg_priv *)(bus)->priv)->mac)
+
+#define HBG_MDIO_C22_MODE 0x1
+#define HBG_MDIO_C22_REG_WRITE 0x1
+#define HBG_MDIO_C22_REG_READ 0x2
+
+#define HBG_MDIO_OP_TIMEOUT_US (1 * 1000 * 1000)
+#define HBG_MDIO_OP_INTERVAL_US (5 * 1000)
+
+static void hbg_mdio_set_command(struct hbg_mac *mac, u32 cmd)
+{
+ hbg_reg_write(HBG_MAC_GET_PRIV(mac), HBG_REG_MDIO_COMMAND_ADDR, cmd);
+}
+
+static void hbg_mdio_get_command(struct hbg_mac *mac, u32 *cmd)
+{
+ *cmd = hbg_reg_read(HBG_MAC_GET_PRIV(mac), HBG_REG_MDIO_COMMAND_ADDR);
+}
+
+static void hbg_mdio_set_wdata_reg(struct hbg_mac *mac, u16 wdata_value)
+{
+ hbg_reg_write_field(HBG_MAC_GET_PRIV(mac), HBG_REG_MDIO_WDATA_ADDR,
+ HBG_REG_MDIO_WDATA_M, wdata_value);
+}
+
+static u32 hbg_mdio_get_rdata_reg(struct hbg_mac *mac)
+{
+ return hbg_reg_read_field(HBG_MAC_GET_PRIV(mac),
+ HBG_REG_MDIO_RDATA_ADDR,
+ HBG_REG_MDIO_WDATA_M);
+}
+
+static int hbg_mdio_wait_ready(struct hbg_mac *mac)
+{
+ struct hbg_priv *priv = HBG_MAC_GET_PRIV(mac);
+ u32 cmd = 0;
+ int ret;
+
+ ret = readl_poll_timeout(priv->io_base + HBG_REG_MDIO_COMMAND_ADDR, cmd,
+ !FIELD_GET(HBG_REG_MDIO_COMMAND_START_B, cmd),
+ HBG_MDIO_OP_INTERVAL_US,
+ HBG_MDIO_OP_TIMEOUT_US);
+
+ return ret ? -ETIMEDOUT : 0;
+}
+
+static int hbg_mdio_cmd_send(struct hbg_mac *mac, u32 prt_addr, u32 dev_addr,
+ u32 type, u32 op_code)
+{
+ u32 cmd = 0;
+
+ hbg_mdio_get_command(mac, &cmd);
+ hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_ST_M, type);
+ hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_OP_M, op_code);
+ hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_PRTAD_M, prt_addr);
+ hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_DEVAD_M, dev_addr);
+
+ /* if auto scan enabled, this value need fix to 0 */
+ hbg_field_modify(cmd, HBG_REG_MDIO_COMMAND_START_B, 0x1);
+
+ hbg_mdio_set_command(mac, cmd);
+
+ /* wait operation complete and check the result */
+ return hbg_mdio_wait_ready(mac);
+}
+
+static int hbg_mdio_read22(struct mii_bus *bus, int phy_addr, int regnum)
+{
+ struct hbg_mac *mac = HBG_MII_BUS_GET_MAC(bus);
+ int ret;
+
+ ret = hbg_mdio_cmd_send(mac, phy_addr, regnum, HBG_MDIO_C22_MODE,
+ HBG_MDIO_C22_REG_READ);
+ if (ret)
+ return ret;
+
+ return hbg_mdio_get_rdata_reg(mac);
+}
+
+static int hbg_mdio_write22(struct mii_bus *bus, int phy_addr, int regnum,
+ u16 val)
+{
+ struct hbg_mac *mac = HBG_MII_BUS_GET_MAC(bus);
+
+ hbg_mdio_set_wdata_reg(mac, val);
+ return hbg_mdio_cmd_send(mac, phy_addr, regnum, HBG_MDIO_C22_MODE,
+ HBG_MDIO_C22_REG_WRITE);
+}
+
+static void hbg_mdio_init_hw(struct hbg_priv *priv)
+{
+ u32 freq = priv->dev_specs.mdio_frequency;
+ struct hbg_mac *mac = &priv->mac;
+ u32 cmd = 0;
+
+ cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_ST_M, HBG_MDIO_C22_MODE);
+ cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_AUTO_SCAN_B, HBG_STATUS_DISABLE);
+
+ /* freq use two bits, which are stored in clk_sel and clk_sel_exp */
+ cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_CLK_SEL_B, freq & 0x1);
+ cmd |= FIELD_PREP(HBG_REG_MDIO_COMMAND_CLK_SEL_EXP_B,
+ (freq >> 1) & 0x1);
+
+ hbg_mdio_set_command(mac, cmd);
+}
+
+static void hbg_phy_adjust_link(struct net_device *netdev)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+ struct phy_device *phydev = netdev->phydev;
+ u32 speed;
+
+ if (phydev->link != priv->mac.link_status) {
+ if (phydev->link) {
+ switch (phydev->speed) {
+ case SPEED_10:
+ speed = HBG_PORT_MODE_SGMII_10M;
+ break;
+ case SPEED_100:
+ speed = HBG_PORT_MODE_SGMII_100M;
+ break;
+ case SPEED_1000:
+ speed = HBG_PORT_MODE_SGMII_1000M;
+ break;
+ default:
+ return;
+ }
+
+ priv->mac.speed = speed;
+ priv->mac.duplex = phydev->duplex;
+ priv->mac.autoneg = phydev->autoneg;
+ hbg_hw_adjust_link(priv, speed, phydev->duplex);
+ }
+
+ priv->mac.link_status = phydev->link;
+ phy_print_status(phydev);
+ }
+}
+
+static void hbg_phy_disconnect(void *data)
+{
+ phy_disconnect((struct phy_device *)data);
+}
+
+static int hbg_phy_connect(struct hbg_priv *priv)
+{
+ struct phy_device *phydev = priv->mac.phydev;
+ struct device *dev = &priv->pdev->dev;
+ int ret;
+
+ ret = phy_connect_direct(priv->netdev, phydev, hbg_phy_adjust_link,
+ PHY_INTERFACE_MODE_SGMII);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to connect phy\n");
+
+ ret = devm_add_action_or_reset(dev, hbg_phy_disconnect, phydev);
+ if (ret)
+ return ret;
+
+ phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+ phy_attached_info(phydev);
+
+ return 0;
+}
+
+void hbg_phy_start(struct hbg_priv *priv)
+{
+ phy_start(priv->mac.phydev);
+}
+
+void hbg_phy_stop(struct hbg_priv *priv)
+{
+ phy_stop(priv->mac.phydev);
+}
+
+int hbg_mdio_init(struct hbg_priv *priv)
+{
+ struct device *dev = &priv->pdev->dev;
+ struct hbg_mac *mac = &priv->mac;
+ struct phy_device *phydev;
+ struct mii_bus *mdio_bus;
+ int ret;
+
+ mac->phy_addr = priv->dev_specs.phy_addr;
+ mdio_bus = devm_mdiobus_alloc(dev);
+ if (!mdio_bus)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to alloc MDIO bus\n");
+
+ mdio_bus->parent = dev;
+ mdio_bus->priv = priv;
+ mdio_bus->phy_mask = ~(1 << mac->phy_addr);
+ mdio_bus->name = "hibmcge mii bus";
+ mac->mdio_bus = mdio_bus;
+
+ mdio_bus->read = hbg_mdio_read22;
+ mdio_bus->write = hbg_mdio_write22;
+ snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii", dev_name(dev));
+
+ ret = devm_mdiobus_register(dev, mdio_bus);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register MDIO bus\n");
+
+ phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr);
+ if (!phydev)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get phy device\n");
+
+ mac->phydev = phydev;
+ hbg_mdio_init_hw(priv);
+ return hbg_phy_connect(priv);
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h
new file mode 100644
index 000000000000..febd02a309c7
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_MDIO_H
+#define __HBG_MDIO_H
+
+#include "hbg_common.h"
+
+int hbg_mdio_init(struct hbg_priv *priv);
+void hbg_phy_start(struct hbg_priv *priv);
+void hbg_phy_stop(struct hbg_priv *priv);
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
new file mode 100644
index 000000000000..57d81c6d7633
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_REG_H
+#define __HBG_REG_H
+
+/* DEV SPEC */
+#define HBG_REG_SPEC_VALID_ADDR 0x0000
+#define HBG_REG_EVENT_REQ_ADDR 0x0004
+#define HBG_REG_MAC_ID_ADDR 0x0008
+#define HBG_REG_PHY_ID_ADDR 0x000C
+#define HBG_REG_MAC_ADDR_ADDR 0x0010
+#define HBG_REG_MDIO_FREQ_ADDR 0x0024
+#define HBG_REG_MAX_MTU_ADDR 0x0028
+#define HBG_REG_MIN_MTU_ADDR 0x002C
+#define HBG_REG_TX_FIFO_NUM_ADDR 0x0030
+#define HBG_REG_RX_FIFO_NUM_ADDR 0x0034
+#define HBG_REG_VLAN_LAYERS_ADDR 0x0038
+
+/* MDIO */
+#define HBG_REG_MDIO_BASE 0x8000
+#define HBG_REG_MDIO_COMMAND_ADDR (HBG_REG_MDIO_BASE + 0x0000)
+#define HBG_REG_MDIO_COMMAND_CLK_SEL_EXP_B BIT(17)
+#define HBG_REG_MDIO_COMMAND_AUTO_SCAN_B BIT(16)
+#define HBG_REG_MDIO_COMMAND_CLK_SEL_B BIT(15)
+#define HBG_REG_MDIO_COMMAND_START_B BIT(14)
+#define HBG_REG_MDIO_COMMAND_ST_M GENMASK(13, 12)
+#define HBG_REG_MDIO_COMMAND_OP_M GENMASK(11, 10)
+#define HBG_REG_MDIO_COMMAND_PRTAD_M GENMASK(9, 5)
+#define HBG_REG_MDIO_COMMAND_DEVAD_M GENMASK(4, 0)
+#define HBG_REG_MDIO_WDATA_ADDR (HBG_REG_MDIO_BASE + 0x0008)
+#define HBG_REG_MDIO_WDATA_M GENMASK(15, 0)
+#define HBG_REG_MDIO_RDATA_ADDR (HBG_REG_MDIO_BASE + 0x000C)
+#define HBG_REG_MDIO_STA_ADDR (HBG_REG_MDIO_BASE + 0x0010)
+
+/* GMAC */
+#define HBG_REG_SGMII_BASE 0x10000
+#define HBG_REG_DUPLEX_TYPE_ADDR (HBG_REG_SGMII_BASE + 0x0008)
+#define HBG_REG_DUPLEX_B BIT(0)
+#define HBG_REG_MAX_FRAME_SIZE_ADDR (HBG_REG_SGMII_BASE + 0x003C)
+#define HBG_REG_PORT_MODE_ADDR (HBG_REG_SGMII_BASE + 0x0040)
+#define HBG_REG_PORT_MODE_M GENMASK(3, 0)
+#define HBG_REG_PORT_ENABLE_ADDR (HBG_REG_SGMII_BASE + 0x0044)
+#define HBG_REG_PORT_ENABLE_RX_B BIT(1)
+#define HBG_REG_PORT_ENABLE_TX_B BIT(2)
+#define HBG_REG_TRANSMIT_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x0060)
+#define HBG_REG_TRANSMIT_CTRL_PAD_EN_B BIT(7)
+#define HBG_REG_TRANSMIT_CTRL_CRC_ADD_B BIT(6)
+#define HBG_REG_TRANSMIT_CTRL_AN_EN_B BIT(5)
+#define HBG_REG_CF_CRC_STRIP_ADDR (HBG_REG_SGMII_BASE + 0x01B0)
+#define HBG_REG_CF_CRC_STRIP_B BIT(0)
+#define HBG_REG_MODE_CHANGE_EN_ADDR (HBG_REG_SGMII_BASE + 0x01B4)
+#define HBG_REG_MODE_CHANGE_EN_B BIT(0)
+#define HBG_REG_RECV_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x01E0)
+#define HBG_REG_RECV_CTRL_STRIP_PAD_EN_B BIT(3)
+#define HBG_REG_STATION_ADDR_LOW_2_ADDR (HBG_REG_SGMII_BASE + 0x0210)
+#define HBG_REG_STATION_ADDR_HIGH_2_ADDR (HBG_REG_SGMII_BASE + 0x0214)
+
+/* PCU */
+#define HBG_REG_CF_INTRPT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x042C)
+#define HBG_INT_MSK_WE_ERR_B BIT(31)
+#define HBG_INT_MSK_RBREQ_ERR_B BIT(30)
+#define HBG_INT_MSK_MAC_FIFO_ERR_B BIT(29)
+#define HBG_INT_MSK_RX_AHB_ERR_B BIT(28)
+#define HBG_INT_MSK_RX_DROP_B BIT(26)
+#define HBG_INT_MSK_TX_DROP_B BIT(25)
+#define HBG_INT_MSK_TXCFG_AVL_B BIT(24)
+#define HBG_INT_MSK_REL_BUF_ERR_B BIT(23)
+#define HBG_INT_MSK_RX_BUF_AVL_B BIT(22)
+#define HBG_INT_MSK_TX_AHB_ERR_B BIT(21)
+#define HBG_INT_MSK_SRAM_PARITY_ERR_B BIT(20)
+#define HBG_INT_MSK_MAC_APP_TX_FIFO_ERR_B BIT(19)
+#define HBG_INT_MSK_MAC_APP_RX_FIFO_ERR_B BIT(18)
+#define HBG_INT_MSK_MAC_PCS_TX_FIFO_ERR_B BIT(17)
+#define HBG_INT_MSK_MAC_PCS_RX_FIFO_ERR_B BIT(16)
+#define HBG_INT_MSK_MAC_MII_FIFO_ERR_B BIT(15)
+#define HBG_INT_MSK_TX_B BIT(1) /* just used in driver */
+#define HBG_INT_MSK_RX_B BIT(0) /* just used in driver */
+#define HBG_REG_CF_INTRPT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0434)
+#define HBG_REG_CF_INTRPT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x0438)
+#define HBG_REG_MAX_FRAME_LEN_ADDR (HBG_REG_SGMII_BASE + 0x0444)
+#define HBG_REG_MAX_FRAME_LEN_M GENMASK(15, 0)
+#define HBG_REG_CF_CFF_DATA_NUM_ADDR (HBG_REG_SGMII_BASE + 0x045C)
+#define HBG_REG_CF_CFF_DATA_NUM_ADDR_TX_M GENMASK(8, 0)
+#define HBG_REG_CF_CFF_DATA_NUM_ADDR_RX_M GENMASK(24, 16)
+#define HBG_REG_TX_CFF_ADDR_0_ADDR (HBG_REG_SGMII_BASE + 0x0488)
+#define HBG_REG_TX_CFF_ADDR_1_ADDR (HBG_REG_SGMII_BASE + 0x048C)
+#define HBG_REG_TX_CFF_ADDR_2_ADDR (HBG_REG_SGMII_BASE + 0x0490)
+#define HBG_REG_TX_CFF_ADDR_3_ADDR (HBG_REG_SGMII_BASE + 0x0494)
+#define HBG_REG_RX_CFF_ADDR_ADDR (HBG_REG_SGMII_BASE + 0x04A0)
+#define HBG_REG_RX_BUF_SIZE_ADDR (HBG_REG_SGMII_BASE + 0x04E4)
+#define HBG_REG_RX_BUF_SIZE_M GENMASK(15, 0)
+#define HBG_REG_BUS_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x04E8)
+#define HBG_REG_BUS_CTRL_ENDIAN_M GENMASK(2, 1)
+#define HBG_REG_RX_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x04F0)
+#define HBG_REG_RX_CTRL_RXBUF_1ST_SKIP_SIZE_M GENMASK(31, 28)
+#define HBG_REG_RX_CTRL_TIME_INF_EN_B BIT(23)
+#define HBG_REG_RX_CTRL_RX_ALIGN_NUM_M GENMASK(18, 17)
+#define HBG_REG_RX_CTRL_PORT_NUM GENMASK(16, 13)
+#define HBG_REG_RX_CTRL_RX_GET_ADDR_MODE_B BIT(12)
+#define HBG_REG_RX_CTRL_RXBUF_1ST_SKIP_SIZE2_M GENMASK(3, 0)
+#define HBG_REG_RX_PKT_MODE_ADDR (HBG_REG_SGMII_BASE + 0x04F4)
+#define HBG_REG_RX_PKT_MODE_PARSE_MODE_M GENMASK(22, 21)
+#define HBG_REG_CF_IND_TXINT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x0694)
+#define HBG_REG_IND_INTR_MASK_B BIT(0)
+#define HBG_REG_CF_IND_TXINT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0698)
+#define HBG_REG_CF_IND_TXINT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x069C)
+#define HBG_REG_CF_IND_RXINT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x06a0)
+#define HBG_REG_CF_IND_RXINT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x06a4)
+#define HBG_REG_CF_IND_RXINT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x06a8)
+
+enum hbg_port_mode {
+ /* 0x0 ~ 0x5 are reserved */
+ HBG_PORT_MODE_SGMII_10M = 0x6,
+ HBG_PORT_MODE_SGMII_100M = 0x7,
+ HBG_PORT_MODE_SGMII_1000M = 0x8,
+};
+
+struct hbg_tx_desc {
+ u32 word0;
+ u32 word1;
+ u32 word2; /* pkt_addr */
+ u32 word3; /* clear_addr */
+};
+
+#define HBG_TX_DESC_W0_IP_OFF_M GENMASK(30, 26)
+#define HBG_TX_DESC_W0_l3_CS_B BIT(2)
+#define HBG_TX_DESC_W0_WB_B BIT(1)
+#define HBG_TX_DESC_W0_l4_CS_B BIT(0)
+#define HBG_TX_DESC_W1_SEND_LEN_M GENMASK(19, 4)
+
+struct hbg_rx_desc {
+ u32 word0;
+ u32 word1; /* tag */
+ u32 word2;
+ u32 word3;
+ u32 word4;
+ u32 word5;
+};
+
+#define HBG_RX_DESC_W2_PKT_LEN_M GENMASK(31, 16)
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
new file mode 100644
index 000000000000..f4f256a0dfea
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <net/netdev_queues.h>
+#include "hbg_common.h"
+#include "hbg_irq.h"
+#include "hbg_reg.h"
+#include "hbg_txrx.h"
+
+#define netdev_get_tx_ring(netdev) \
+ (&(((struct hbg_priv *)netdev_priv(netdev))->tx_ring))
+
+#define buffer_to_dma_dir(buffer) (((buffer)->dir == HBG_DIR_RX) ? \
+ DMA_FROM_DEVICE : DMA_TO_DEVICE)
+
+#define hbg_queue_used_num(head, tail, ring) ({ \
+ typeof(ring) _ring = (ring); \
+ ((tail) + _ring->len - (head)) % _ring->len; })
+#define hbg_queue_left_num(head, tail, ring) ({ \
+ typeof(ring) _r = (ring); \
+ _r->len - hbg_queue_used_num((head), (tail), _r) - 1; })
+#define hbg_queue_is_empty(head, tail, ring) \
+ (hbg_queue_used_num((head), (tail), (ring)) == 0)
+#define hbg_queue_is_full(head, tail, ring) \
+ (hbg_queue_left_num((head), (tail), (ring)) == 0)
+#define hbg_queue_next_prt(p, ring) (((p) + 1) % (ring)->len)
+#define hbg_queue_move_next(p, ring) ({ \
+ typeof(ring) _ring = (ring); \
+ _ring->p = hbg_queue_next_prt(_ring->p, _ring); })
+
+#define HBG_TX_STOP_THRS 2
+#define HBG_TX_START_THRS (2 * HBG_TX_STOP_THRS)
+
+static int hbg_dma_map(struct hbg_buffer *buffer)
+{
+ struct hbg_priv *priv = buffer->priv;
+
+ buffer->skb_dma = dma_map_single(&priv->pdev->dev,
+ buffer->skb->data, buffer->skb_len,
+ buffer_to_dma_dir(buffer));
+ if (unlikely(dma_mapping_error(&priv->pdev->dev, buffer->skb_dma)))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void hbg_dma_unmap(struct hbg_buffer *buffer)
+{
+ struct hbg_priv *priv = buffer->priv;
+
+ if (unlikely(!buffer->skb_dma))
+ return;
+
+ dma_unmap_single(&priv->pdev->dev, buffer->skb_dma, buffer->skb_len,
+ buffer_to_dma_dir(buffer));
+ buffer->skb_dma = 0;
+}
+
+static void hbg_init_tx_desc(struct hbg_buffer *buffer,
+ struct hbg_tx_desc *tx_desc)
+{
+ u32 ip_offset = buffer->skb->network_header - buffer->skb->mac_header;
+ u32 word0 = 0;
+
+ word0 |= FIELD_PREP(HBG_TX_DESC_W0_WB_B, HBG_STATUS_ENABLE);
+ word0 |= FIELD_PREP(HBG_TX_DESC_W0_IP_OFF_M, ip_offset);
+ if (likely(buffer->skb->ip_summed == CHECKSUM_PARTIAL)) {
+ word0 |= FIELD_PREP(HBG_TX_DESC_W0_l3_CS_B, HBG_STATUS_ENABLE);
+ word0 |= FIELD_PREP(HBG_TX_DESC_W0_l4_CS_B, HBG_STATUS_ENABLE);
+ }
+
+ tx_desc->word0 = word0;
+ tx_desc->word1 = FIELD_PREP(HBG_TX_DESC_W1_SEND_LEN_M,
+ buffer->skb->len);
+ tx_desc->word2 = buffer->skb_dma;
+ tx_desc->word3 = buffer->state_dma;
+}
+
+netdev_tx_t hbg_net_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct hbg_ring *ring = netdev_get_tx_ring(netdev);
+ struct hbg_priv *priv = netdev_priv(netdev);
+ /* This smp_load_acquire() pairs with smp_store_release() in
+ * hbg_napi_tx_recycle() called in tx interrupt handle process.
+ */
+ u32 ntc = smp_load_acquire(&ring->ntc);
+ struct hbg_buffer *buffer;
+ struct hbg_tx_desc tx_desc;
+ u32 ntu = ring->ntu;
+
+ if (unlikely(!skb->len ||
+ skb->len > hbg_spec_max_frame_len(priv, HBG_DIR_TX))) {
+ dev_kfree_skb_any(skb);
+ netdev->stats.tx_errors++;
+ return NETDEV_TX_OK;
+ }
+
+ if (!netif_subqueue_maybe_stop(netdev, 0,
+ hbg_queue_left_num(ntc, ntu, ring),
+ HBG_TX_STOP_THRS, HBG_TX_START_THRS))
+ return NETDEV_TX_BUSY;
+
+ buffer = &ring->queue[ntu];
+ buffer->skb = skb;
+ buffer->skb_len = skb->len;
+ if (unlikely(hbg_dma_map(buffer))) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ buffer->state = HBG_TX_STATE_START;
+ hbg_init_tx_desc(buffer, &tx_desc);
+ hbg_hw_set_tx_desc(priv, &tx_desc);
+
+ /* This smp_store_release() pairs with smp_load_acquire() in
+ * hbg_napi_tx_recycle() called in tx interrupt handle process.
+ */
+ smp_store_release(&ring->ntu, hbg_queue_next_prt(ntu, ring));
+ dev_sw_netstats_tx_add(netdev, 1, skb->len);
+ return NETDEV_TX_OK;
+}
+
+static void hbg_buffer_free_skb(struct hbg_buffer *buffer)
+{
+ if (unlikely(!buffer->skb))
+ return;
+
+ dev_kfree_skb_any(buffer->skb);
+ buffer->skb = NULL;
+}
+
+static int hbg_buffer_alloc_skb(struct hbg_buffer *buffer)
+{
+ u32 len = hbg_spec_max_frame_len(buffer->priv, buffer->dir);
+ struct hbg_priv *priv = buffer->priv;
+
+ buffer->skb = netdev_alloc_skb(priv->netdev, len);
+ if (unlikely(!buffer->skb))
+ return -ENOMEM;
+
+ buffer->skb_len = len;
+ memset(buffer->skb->data, 0, HBG_PACKET_HEAD_SIZE);
+ return 0;
+}
+
+static void hbg_buffer_free(struct hbg_buffer *buffer)
+{
+ hbg_dma_unmap(buffer);
+ hbg_buffer_free_skb(buffer);
+}
+
+static int hbg_napi_tx_recycle(struct napi_struct *napi, int budget)
+{
+ struct hbg_ring *ring = container_of(napi, struct hbg_ring, napi);
+ /* This smp_load_acquire() pairs with smp_store_release() in
+ * hbg_net_start_xmit() called in xmit process.
+ */
+ u32 ntu = smp_load_acquire(&ring->ntu);
+ struct hbg_priv *priv = ring->priv;
+ struct hbg_buffer *buffer;
+ u32 ntc = ring->ntc;
+ int packet_done = 0;
+
+ /* We need do cleanup even if budget is 0.
+ * Per NAPI documentation budget is for Rx.
+ * So We hardcode the amount of work Tx NAPI does to 128.
+ */
+ budget = 128;
+ while (packet_done < budget) {
+ if (unlikely(hbg_queue_is_empty(ntc, ntu, ring)))
+ break;
+
+ /* make sure HW write desc complete */
+ dma_rmb();
+
+ buffer = &ring->queue[ntc];
+ if (buffer->state != HBG_TX_STATE_COMPLETE)
+ break;
+
+ hbg_buffer_free(buffer);
+ ntc = hbg_queue_next_prt(ntc, ring);
+ packet_done++;
+ }
+
+ /* This smp_store_release() pairs with smp_load_acquire() in
+ * hbg_net_start_xmit() called in xmit process.
+ */
+ smp_store_release(&ring->ntc, ntc);
+ netif_wake_queue(priv->netdev);
+
+ if (likely(packet_done < budget &&
+ napi_complete_done(napi, packet_done)))
+ hbg_hw_irq_enable(priv, HBG_INT_MSK_TX_B, true);
+
+ return packet_done;
+}
+
+static int hbg_rx_fill_one_buffer(struct hbg_priv *priv)
+{
+ struct hbg_ring *ring = &priv->rx_ring;
+ struct hbg_buffer *buffer;
+ int ret;
+
+ if (hbg_queue_is_full(ring->ntc, ring->ntu, ring))
+ return 0;
+
+ buffer = &ring->queue[ring->ntu];
+ ret = hbg_buffer_alloc_skb(buffer);
+ if (unlikely(ret))
+ return ret;
+
+ ret = hbg_dma_map(buffer);
+ if (unlikely(ret)) {
+ hbg_buffer_free_skb(buffer);
+ return ret;
+ }
+
+ hbg_hw_fill_buffer(priv, buffer->skb_dma);
+ hbg_queue_move_next(ntu, ring);
+ return 0;
+}
+
+static bool hbg_sync_data_from_hw(struct hbg_priv *priv,
+ struct hbg_buffer *buffer)
+{
+ struct hbg_rx_desc *rx_desc;
+
+ /* make sure HW write desc complete */
+ dma_rmb();
+
+ dma_sync_single_for_cpu(&priv->pdev->dev, buffer->skb_dma,
+ buffer->skb_len, DMA_FROM_DEVICE);
+
+ rx_desc = (struct hbg_rx_desc *)buffer->skb->data;
+ return FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2) != 0;
+}
+
+static int hbg_napi_rx_poll(struct napi_struct *napi, int budget)
+{
+ struct hbg_ring *ring = container_of(napi, struct hbg_ring, napi);
+ struct hbg_priv *priv = ring->priv;
+ struct hbg_rx_desc *rx_desc;
+ struct hbg_buffer *buffer;
+ u32 packet_done = 0;
+ u32 pkt_len;
+
+ while (packet_done < budget) {
+ if (unlikely(hbg_queue_is_empty(ring->ntc, ring->ntu, ring)))
+ break;
+
+ buffer = &ring->queue[ring->ntc];
+ if (unlikely(!buffer->skb))
+ goto next_buffer;
+
+ if (unlikely(!hbg_sync_data_from_hw(priv, buffer)))
+ break;
+ rx_desc = (struct hbg_rx_desc *)buffer->skb->data;
+ pkt_len = FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2);
+
+ hbg_dma_unmap(buffer);
+
+ skb_reserve(buffer->skb, HBG_PACKET_HEAD_SIZE + NET_IP_ALIGN);
+ skb_put(buffer->skb, pkt_len);
+ buffer->skb->protocol = eth_type_trans(buffer->skb,
+ priv->netdev);
+
+ dev_sw_netstats_rx_add(priv->netdev, pkt_len);
+ napi_gro_receive(napi, buffer->skb);
+ buffer->skb = NULL;
+
+next_buffer:
+ hbg_rx_fill_one_buffer(priv);
+ hbg_queue_move_next(ntc, ring);
+ packet_done++;
+ }
+
+ if (likely(packet_done < budget &&
+ napi_complete_done(napi, packet_done)))
+ hbg_hw_irq_enable(priv, HBG_INT_MSK_RX_B, true);
+
+ return packet_done;
+}
+
+static void hbg_ring_uninit(struct hbg_ring *ring)
+{
+ struct hbg_buffer *buffer;
+ u32 i;
+
+ if (!ring->queue)
+ return;
+
+ napi_disable(&ring->napi);
+ netif_napi_del(&ring->napi);
+
+ for (i = 0; i < ring->len; i++) {
+ buffer = &ring->queue[i];
+ hbg_buffer_free(buffer);
+ buffer->ring = NULL;
+ buffer->priv = NULL;
+ }
+
+ dma_free_coherent(&ring->priv->pdev->dev,
+ ring->len * sizeof(*ring->queue),
+ ring->queue, ring->queue_dma);
+ ring->queue = NULL;
+ ring->queue_dma = 0;
+ ring->len = 0;
+ ring->priv = NULL;
+}
+
+static int hbg_ring_init(struct hbg_priv *priv, struct hbg_ring *ring,
+ int (*napi_poll)(struct napi_struct *, int),
+ enum hbg_dir dir)
+{
+ struct hbg_buffer *buffer;
+ u32 i, len;
+
+ len = hbg_get_spec_fifo_max_num(priv, dir) + 1;
+ ring->queue = dma_alloc_coherent(&priv->pdev->dev,
+ len * sizeof(*ring->queue),
+ &ring->queue_dma, GFP_KERNEL);
+ if (!ring->queue)
+ return -ENOMEM;
+
+ for (i = 0; i < len; i++) {
+ buffer = &ring->queue[i];
+ buffer->skb_len = 0;
+ buffer->dir = dir;
+ buffer->ring = ring;
+ buffer->priv = priv;
+ buffer->state_dma = ring->queue_dma + (i * sizeof(*buffer));
+ }
+
+ ring->dir = dir;
+ ring->priv = priv;
+ ring->ntc = 0;
+ ring->ntu = 0;
+ ring->len = len;
+
+ if (dir == HBG_DIR_TX)
+ netif_napi_add_tx(priv->netdev, &ring->napi, napi_poll);
+ else
+ netif_napi_add(priv->netdev, &ring->napi, napi_poll);
+
+ napi_enable(&ring->napi);
+ return 0;
+}
+
+static int hbg_tx_ring_init(struct hbg_priv *priv)
+{
+ struct hbg_ring *tx_ring = &priv->tx_ring;
+
+ if (!tx_ring->tout_log_buf)
+ tx_ring->tout_log_buf = devm_kmalloc(&priv->pdev->dev,
+ HBG_TX_TIMEOUT_BUF_LEN,
+ GFP_KERNEL);
+
+ if (!tx_ring->tout_log_buf)
+ return -ENOMEM;
+
+ return hbg_ring_init(priv, tx_ring, hbg_napi_tx_recycle, HBG_DIR_TX);
+}
+
+static int hbg_rx_ring_init(struct hbg_priv *priv)
+{
+ int ret;
+ u32 i;
+
+ ret = hbg_ring_init(priv, &priv->rx_ring, hbg_napi_rx_poll, HBG_DIR_RX);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < priv->rx_ring.len - 1; i++) {
+ ret = hbg_rx_fill_one_buffer(priv);
+ if (ret) {
+ hbg_ring_uninit(&priv->rx_ring);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int hbg_txrx_init(struct hbg_priv *priv)
+{
+ int ret;
+
+ ret = hbg_tx_ring_init(priv);
+ if (ret) {
+ dev_err(&priv->pdev->dev,
+ "failed to init tx ring, ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = hbg_rx_ring_init(priv);
+ if (ret) {
+ dev_err(&priv->pdev->dev,
+ "failed to init rx ring, ret = %d\n", ret);
+ hbg_ring_uninit(&priv->tx_ring);
+ }
+
+ return ret;
+}
+
+void hbg_txrx_uninit(struct hbg_priv *priv)
+{
+ hbg_ring_uninit(&priv->tx_ring);
+ hbg_ring_uninit(&priv->rx_ring);
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h
new file mode 100644
index 000000000000..2883a5899ae2
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_TXRX_H
+#define __HBG_TXRX_H
+
+#include <linux/etherdevice.h>
+#include "hbg_hw.h"
+
+static inline u32 hbg_spec_max_frame_len(struct hbg_priv *priv,
+ enum hbg_dir dir)
+{
+ return (dir == HBG_DIR_TX) ? priv->dev_specs.max_frame_len :
+ priv->dev_specs.rx_buf_size;
+}
+
+static inline u32 hbg_get_spec_fifo_max_num(struct hbg_priv *priv,
+ enum hbg_dir dir)
+{
+ return (dir == HBG_DIR_TX) ? priv->dev_specs.tx_fifo_num :
+ priv->dev_specs.rx_fifo_num;
+}
+
+static inline bool hbg_fifo_is_full(struct hbg_priv *priv, enum hbg_dir dir)
+{
+ return hbg_hw_get_fifo_used_num(priv, dir) >=
+ hbg_get_spec_fifo_max_num(priv, dir);
+}
+
+static inline u32 hbg_get_queue_used_num(struct hbg_ring *ring)
+{
+ return (ring->ntu + ring->len - ring->ntc) % ring->len;
+}
+
+netdev_tx_t hbg_net_start_xmit(struct sk_buff *skb, struct net_device *netdev);
+int hbg_txrx_init(struct hbg_priv *priv);
+void hbg_txrx_uninit(struct hbg_priv *priv);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index beb815e5289b..a376d4bdf281 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -1047,7 +1047,7 @@ MODULE_DEVICE_TABLE(of, hip04_mac_match);
static struct platform_driver hip04_mac_driver = {
.probe = hip04_mac_probe,
- .remove_new = hip04_remove,
+ .remove = hip04_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = hip04_mac_match,
diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c
index 2406263c9dd3..d244a40df430 100644
--- a/drivers/net/ethernet/hisilicon/hisi_femac.c
+++ b/drivers/net/ethernet/hisilicon/hisi_femac.c
@@ -959,7 +959,7 @@ static struct platform_driver hisi_femac_driver = {
.of_match_table = hisi_femac_match,
},
.probe = hisi_femac_drv_probe,
- .remove_new = hisi_femac_drv_remove,
+ .remove = hisi_femac_drv_remove,
#ifdef CONFIG_PM
.suspend = hisi_femac_drv_suspend,
.resume = hisi_femac_drv_resume,
diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
index 1a972b093a42..e3e7f2270560 100644
--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -1312,7 +1312,7 @@ static struct platform_driver hix5hd2_dev_driver = {
.of_match_table = hix5hd2_of_match,
},
.probe = hix5hd2_dev_probe,
- .remove_new = hix5hd2_dev_remove,
+ .remove = hix5hd2_dev_remove,
};
module_platform_driver(hix5hd2_dev_driver);
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h
index d72657444ef3..2ae34d01fd36 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -512,7 +512,7 @@ struct hnae_ae_ops {
struct net_device_stats *net_stats);
void (*get_stats)(struct hnae_handle *handle, u64 *data);
void (*get_strings)(struct hnae_handle *handle,
- u32 stringset, u8 *data);
+ u32 stringset, u8 **data);
int (*get_sset_count)(struct hnae_handle *handle, int stringset);
void (*update_led_status)(struct hnae_handle *handle);
int (*set_led_id)(struct hnae_handle *handle,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index bc3e406f0139..8ce910f8d0cc 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -730,15 +730,14 @@ static void hns_ae_get_stats(struct hnae_handle *handle, u64 *data)
hns_dsaf_get_stats(vf_cb->dsaf_dev, p, vf_cb->port_index);
}
-static void hns_ae_get_strings(struct hnae_handle *handle,
- u32 stringset, u8 *data)
+static void hns_ae_get_strings(struct hnae_handle *handle, u32 stringset,
+ u8 **data)
{
int port;
int idx;
struct hns_mac_cb *mac_cb;
struct hns_ppe_cb *ppe_cb;
struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
- u8 *p = data;
struct hnae_vf_cb *vf_cb;
assert(handle);
@@ -748,19 +747,14 @@ static void hns_ae_get_strings(struct hnae_handle *handle,
mac_cb = hns_get_mac_cb(handle);
ppe_cb = hns_get_ppe_cb(handle);
- for (idx = 0; idx < handle->q_num; idx++) {
- hns_rcb_get_strings(stringset, p, idx);
- p += ETH_GSTRING_LEN * hns_rcb_get_ring_sset_count(stringset);
- }
-
- hns_ppe_get_strings(ppe_cb, stringset, p);
- p += ETH_GSTRING_LEN * hns_ppe_get_sset_count(stringset);
+ for (idx = 0; idx < handle->q_num; idx++)
+ hns_rcb_get_strings(stringset, data, idx);
- hns_mac_get_strings(mac_cb, stringset, p);
- p += ETH_GSTRING_LEN * hns_mac_get_sset_count(mac_cb, stringset);
+ hns_ppe_get_strings(ppe_cb, stringset, data);
+ hns_mac_get_strings(mac_cb, stringset, data);
if (mac_cb->mac_type == HNAE_PORT_SERVICE)
- hns_dsaf_get_strings(stringset, p, port, dsaf_dev);
+ hns_dsaf_get_strings(stringset, data, port, dsaf_dev);
}
static int hns_ae_get_sset_count(struct hnae_handle *handle, int stringset)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index bdb7afaabdd0..400933ca1a29 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -669,16 +669,15 @@ static void hns_gmac_get_stats(void *mac_drv, u64 *data)
}
}
-static void hns_gmac_get_strings(u32 stringset, u8 *data)
+static void hns_gmac_get_strings(u32 stringset, u8 **data)
{
- u8 *buff = data;
u32 i;
if (stringset != ETH_SS_STATS)
return;
for (i = 0; i < ARRAY_SIZE(g_gmac_stats_string); i++)
- ethtool_puts(&buff, g_gmac_stats_string[i].desc);
+ ethtool_puts(data, g_gmac_stats_string[i].desc);
}
static int hns_gmac_get_sset_count(int stringset)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index 58baac7103b3..bc6b269be299 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -1090,28 +1090,24 @@ int hns_mac_init(struct dsaf_device *dsaf_dev)
u32 port_id;
int max_port_num = hns_mac_get_max_port_num(dsaf_dev);
struct hns_mac_cb *mac_cb;
- struct fwnode_handle *child;
- device_for_each_child_node(dsaf_dev->dev, child) {
+ device_for_each_child_node_scoped(dsaf_dev->dev, child) {
ret = fwnode_property_read_u32(child, "reg", &port_id);
if (ret) {
- fwnode_handle_put(child);
dev_err(dsaf_dev->dev,
"get reg fail, ret=%d!\n", ret);
return ret;
}
if (port_id >= max_port_num) {
- fwnode_handle_put(child);
dev_err(dsaf_dev->dev,
"reg(%u) out of range!\n", port_id);
return -EINVAL;
}
mac_cb = devm_kzalloc(dsaf_dev->dev, sizeof(*mac_cb),
GFP_KERNEL);
- if (!mac_cb) {
- fwnode_handle_put(child);
+ if (!mac_cb)
return -ENOMEM;
- }
+
mac_cb->fw_port = child;
mac_cb->mac_id = (u8)port_id;
dsaf_dev->mac_cb[port_id] = mac_cb;
@@ -1194,8 +1190,7 @@ void hns_mac_get_stats(struct hns_mac_cb *mac_cb, u64 *data)
mac_ctrl_drv->get_ethtool_stats(mac_ctrl_drv, data);
}
-void hns_mac_get_strings(struct hns_mac_cb *mac_cb,
- int stringset, u8 *data)
+void hns_mac_get_strings(struct hns_mac_cb *mac_cb, int stringset, u8 **data)
{
struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
index edf0bcf76ac9..630f01cf7a71 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
@@ -378,7 +378,7 @@ struct mac_driver {
void (*get_regs)(void *mac_drv, void *data);
int (*get_regs_count)(void);
/* get strings name for ethtool statistic */
- void (*get_strings)(u32 stringset, u8 *data);
+ void (*get_strings)(u32 stringset, u8 **data);
/* get the number of strings*/
int (*get_sset_count)(int stringset);
@@ -445,7 +445,7 @@ int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb,
enum hnae_loop loop, int en);
void hns_mac_update_stats(struct hns_mac_cb *mac_cb);
void hns_mac_get_stats(struct hns_mac_cb *mac_cb, u64 *data);
-void hns_mac_get_strings(struct hns_mac_cb *mac_cb, int stringset, u8 *data);
+void hns_mac_get_strings(struct hns_mac_cb *mac_cb, int stringset, u8 **data);
int hns_mac_get_sset_count(struct hns_mac_cb *mac_cb, int stringset);
void hns_mac_get_regs(struct hns_mac_cb *mac_cb, void *data);
int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 1b67da1f6fa8..851490346261 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -2590,55 +2590,34 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data)
p[i] = 0xdddddddd;
}
-static char *hns_dsaf_get_node_stats_strings(char *data, int node,
- struct dsaf_device *dsaf_dev)
+static void hns_dsaf_get_node_stats_strings(u8 **data, int node,
+ struct dsaf_device *dsaf_dev)
{
- char *buff = data;
- int i;
bool is_ver1 = AE_IS_VER1(dsaf_dev->dsaf_ver);
+ int i;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_pad_drop_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_manage_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pkt_id", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pause_frame", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_release_buf_num", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_sbm_drop_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_crc_false_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_bp_drop_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_lookup_rslt_drop_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_local_rslt_fail_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_vlan_drop_pkts", node);
- buff += ETH_GSTRING_LEN;
- snprintf(buff, ETH_GSTRING_LEN, "innod%d_stp_drop_pkts", node);
- buff += ETH_GSTRING_LEN;
+ ethtool_sprintf(data, "innod%d_pad_drop_pkts", node);
+ ethtool_sprintf(data, "innod%d_manage_pkts", node);
+ ethtool_sprintf(data, "innod%d_rx_pkts", node);
+ ethtool_sprintf(data, "innod%d_rx_pkt_id", node);
+ ethtool_sprintf(data, "innod%d_rx_pause_frame", node);
+ ethtool_sprintf(data, "innod%d_release_buf_num", node);
+ ethtool_sprintf(data, "innod%d_sbm_drop_pkts", node);
+ ethtool_sprintf(data, "innod%d_crc_false_pkts", node);
+ ethtool_sprintf(data, "innod%d_bp_drop_pkts", node);
+ ethtool_sprintf(data, "innod%d_lookup_rslt_drop_pkts", node);
+ ethtool_sprintf(data, "innod%d_local_rslt_fail_pkts", node);
+ ethtool_sprintf(data, "innod%d_vlan_drop_pkts", node);
+ ethtool_sprintf(data, "innod%d_stp_drop_pkts", node);
if (node < DSAF_SERVICE_NW_NUM && !is_ver1) {
for (i = 0; i < DSAF_PRIO_NR; i++) {
- snprintf(buff + 0 * ETH_GSTRING_LEN * DSAF_PRIO_NR,
- ETH_GSTRING_LEN, "inod%d_pfc_prio%d_pkts",
- node, i);
- snprintf(buff + 1 * ETH_GSTRING_LEN * DSAF_PRIO_NR,
- ETH_GSTRING_LEN, "onod%d_pfc_prio%d_pkts",
- node, i);
- buff += ETH_GSTRING_LEN;
+ ethtool_sprintf(data, "inod%d_pfc_prio%d_pkts", node,
+ i);
+ ethtool_sprintf(data, "onod%d_pfc_prio%d_pkts", node,
+ i);
}
- buff += 1 * DSAF_PRIO_NR * ETH_GSTRING_LEN;
}
- snprintf(buff, ETH_GSTRING_LEN, "onnod%d_tx_pkts", node);
- buff += ETH_GSTRING_LEN;
-
- return buff;
+ ethtool_sprintf(data, "onnod%d_tx_pkts", node);
}
static u64 *hns_dsaf_get_node_stats(struct dsaf_device *ddev, u64 *data,
@@ -2720,21 +2699,20 @@ int hns_dsaf_get_sset_count(struct dsaf_device *dsaf_dev, int stringset)
*@port:port index
*@dsaf_dev: dsaf device
*/
-void hns_dsaf_get_strings(int stringset, u8 *data, int port,
+void hns_dsaf_get_strings(int stringset, u8 **data, int port,
struct dsaf_device *dsaf_dev)
{
- char *buff = (char *)data;
int node = port;
if (stringset != ETH_SS_STATS)
return;
/* for ge/xge node info */
- buff = hns_dsaf_get_node_stats_strings(buff, node, dsaf_dev);
+ hns_dsaf_get_node_stats_strings(data, node, dsaf_dev);
/* for ppe node info */
node = port + DSAF_PPE_INODE_BASE;
- (void)hns_dsaf_get_node_stats_strings(buff, node, dsaf_dev);
+ hns_dsaf_get_node_stats_strings(data, node, dsaf_dev);
}
/**
@@ -3031,7 +3009,7 @@ MODULE_DEVICE_TABLE(of, g_dsaf_match);
static struct platform_driver g_dsaf_driver = {
.probe = hns_dsaf_probe,
- .remove_new = hns_dsaf_remove,
+ .remove = hns_dsaf_remove,
.driver = {
.name = DSAF_DRV_NAME,
.of_match_table = g_dsaf_match,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
index 5526a10caac5..0eb03dff1a8b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -442,7 +442,7 @@ void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 inode_num);
int hns_dsaf_get_sset_count(struct dsaf_device *dsaf_dev, int stringset);
void hns_dsaf_get_stats(struct dsaf_device *ddev, u64 *data, int port);
-void hns_dsaf_get_strings(int stringset, u8 *data, int port,
+void hns_dsaf_get_strings(int stringset, u8 **data, int port,
struct dsaf_device *dsaf_dev);
void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
index a08d1f0a5a16..5013beb4d282 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
@@ -457,24 +457,23 @@ int hns_ppe_get_regs_count(void)
* @stringset: string set type
* @data: output string
*/
-void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 *data)
+void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 **data)
{
int index = ppe_cb->index;
- u8 *buff = data;
-
- ethtool_sprintf(&buff, "ppe%d_rx_sw_pkt", index);
- ethtool_sprintf(&buff, "ppe%d_rx_pkt_ok", index);
- ethtool_sprintf(&buff, "ppe%d_rx_drop_pkt_no_bd", index);
- ethtool_sprintf(&buff, "ppe%d_rx_alloc_buf_fail", index);
- ethtool_sprintf(&buff, "ppe%d_rx_alloc_buf_wait", index);
- ethtool_sprintf(&buff, "ppe%d_rx_pkt_drop_no_buf", index);
- ethtool_sprintf(&buff, "ppe%d_rx_pkt_err_fifo_full", index);
-
- ethtool_sprintf(&buff, "ppe%d_tx_bd", index);
- ethtool_sprintf(&buff, "ppe%d_tx_pkt", index);
- ethtool_sprintf(&buff, "ppe%d_tx_pkt_ok", index);
- ethtool_sprintf(&buff, "ppe%d_tx_pkt_err_fifo_empty", index);
- ethtool_sprintf(&buff, "ppe%d_tx_pkt_err_csum_fail", index);
+
+ ethtool_sprintf(data, "ppe%d_rx_sw_pkt", index);
+ ethtool_sprintf(data, "ppe%d_rx_pkt_ok", index);
+ ethtool_sprintf(data, "ppe%d_rx_drop_pkt_no_bd", index);
+ ethtool_sprintf(data, "ppe%d_rx_alloc_buf_fail", index);
+ ethtool_sprintf(data, "ppe%d_rx_alloc_buf_wait", index);
+ ethtool_sprintf(data, "ppe%d_rx_pkt_drop_no_buf", index);
+ ethtool_sprintf(data, "ppe%d_rx_pkt_err_fifo_full", index);
+
+ ethtool_sprintf(data, "ppe%d_tx_bd", index);
+ ethtool_sprintf(data, "ppe%d_tx_pkt", index);
+ ethtool_sprintf(data, "ppe%d_tx_pkt_ok", index);
+ ethtool_sprintf(data, "ppe%d_tx_pkt_err_fifo_empty", index);
+ ethtool_sprintf(data, "ppe%d_tx_pkt_err_csum_fail", index);
}
void hns_ppe_get_stats(struct hns_ppe_cb *ppe_cb, u64 *data)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
index 7e00231c1acf..602c8e971fe4 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
@@ -109,7 +109,7 @@ int hns_ppe_get_sset_count(int stringset);
int hns_ppe_get_regs_count(void);
void hns_ppe_get_regs(struct hns_ppe_cb *ppe_cb, void *data);
-void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 *data);
+void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 **data);
void hns_ppe_get_stats(struct hns_ppe_cb *ppe_cb, u64 *data);
void hns_ppe_set_tso_enable(struct hns_ppe_cb *ppe_cb, u32 value);
void hns_ppe_set_rss_key(struct hns_ppe_cb *ppe_cb,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
index 93344563a259..46af467aa596 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -923,44 +923,42 @@ int hns_rcb_get_ring_regs_count(void)
*@data:strings name value
*@index:queue index
*/
-void hns_rcb_get_strings(int stringset, u8 *data, int index)
+void hns_rcb_get_strings(int stringset, u8 **data, int index)
{
- u8 *buff = data;
-
if (stringset != ETH_SS_STATS)
return;
- ethtool_sprintf(&buff, "tx_ring%d_rcb_pkt_num", index);
- ethtool_sprintf(&buff, "tx_ring%d_ppe_tx_pkt_num", index);
- ethtool_sprintf(&buff, "tx_ring%d_ppe_drop_pkt_num", index);
- ethtool_sprintf(&buff, "tx_ring%d_fbd_num", index);
-
- ethtool_sprintf(&buff, "tx_ring%d_pkt_num", index);
- ethtool_sprintf(&buff, "tx_ring%d_bytes", index);
- ethtool_sprintf(&buff, "tx_ring%d_err_cnt", index);
- ethtool_sprintf(&buff, "tx_ring%d_io_err", index);
- ethtool_sprintf(&buff, "tx_ring%d_sw_err", index);
- ethtool_sprintf(&buff, "tx_ring%d_seg_pkt", index);
- ethtool_sprintf(&buff, "tx_ring%d_restart_queue", index);
- ethtool_sprintf(&buff, "tx_ring%d_tx_busy", index);
-
- ethtool_sprintf(&buff, "rx_ring%d_rcb_pkt_num", index);
- ethtool_sprintf(&buff, "rx_ring%d_ppe_pkt_num", index);
- ethtool_sprintf(&buff, "rx_ring%d_ppe_drop_pkt_num", index);
- ethtool_sprintf(&buff, "rx_ring%d_fbd_num", index);
-
- ethtool_sprintf(&buff, "rx_ring%d_pkt_num", index);
- ethtool_sprintf(&buff, "rx_ring%d_bytes", index);
- ethtool_sprintf(&buff, "rx_ring%d_err_cnt", index);
- ethtool_sprintf(&buff, "rx_ring%d_io_err", index);
- ethtool_sprintf(&buff, "rx_ring%d_sw_err", index);
- ethtool_sprintf(&buff, "rx_ring%d_seg_pkt", index);
- ethtool_sprintf(&buff, "rx_ring%d_reuse_pg", index);
- ethtool_sprintf(&buff, "rx_ring%d_len_err", index);
- ethtool_sprintf(&buff, "rx_ring%d_non_vld_desc_err", index);
- ethtool_sprintf(&buff, "rx_ring%d_bd_num_err", index);
- ethtool_sprintf(&buff, "rx_ring%d_l2_err", index);
- ethtool_sprintf(&buff, "rx_ring%d_l3l4csum_err", index);
+ ethtool_sprintf(data, "tx_ring%d_rcb_pkt_num", index);
+ ethtool_sprintf(data, "tx_ring%d_ppe_tx_pkt_num", index);
+ ethtool_sprintf(data, "tx_ring%d_ppe_drop_pkt_num", index);
+ ethtool_sprintf(data, "tx_ring%d_fbd_num", index);
+
+ ethtool_sprintf(data, "tx_ring%d_pkt_num", index);
+ ethtool_sprintf(data, "tx_ring%d_bytes", index);
+ ethtool_sprintf(data, "tx_ring%d_err_cnt", index);
+ ethtool_sprintf(data, "tx_ring%d_io_err", index);
+ ethtool_sprintf(data, "tx_ring%d_sw_err", index);
+ ethtool_sprintf(data, "tx_ring%d_seg_pkt", index);
+ ethtool_sprintf(data, "tx_ring%d_restart_queue", index);
+ ethtool_sprintf(data, "tx_ring%d_tx_busy", index);
+
+ ethtool_sprintf(data, "rx_ring%d_rcb_pkt_num", index);
+ ethtool_sprintf(data, "rx_ring%d_ppe_pkt_num", index);
+ ethtool_sprintf(data, "rx_ring%d_ppe_drop_pkt_num", index);
+ ethtool_sprintf(data, "rx_ring%d_fbd_num", index);
+
+ ethtool_sprintf(data, "rx_ring%d_pkt_num", index);
+ ethtool_sprintf(data, "rx_ring%d_bytes", index);
+ ethtool_sprintf(data, "rx_ring%d_err_cnt", index);
+ ethtool_sprintf(data, "rx_ring%d_io_err", index);
+ ethtool_sprintf(data, "rx_ring%d_sw_err", index);
+ ethtool_sprintf(data, "rx_ring%d_seg_pkt", index);
+ ethtool_sprintf(data, "rx_ring%d_reuse_pg", index);
+ ethtool_sprintf(data, "rx_ring%d_len_err", index);
+ ethtool_sprintf(data, "rx_ring%d_non_vld_desc_err", index);
+ ethtool_sprintf(data, "rx_ring%d_bd_num_err", index);
+ ethtool_sprintf(data, "rx_ring%d_l2_err", index);
+ ethtool_sprintf(data, "rx_ring%d_l3l4csum_err", index);
}
void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
index c1e9b6997853..0f4cc184ef39 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
@@ -157,7 +157,7 @@ int hns_rcb_get_ring_regs_count(void);
void hns_rcb_get_ring_regs(struct hnae_queue *queue, void *data);
-void hns_rcb_get_strings(int stringset, u8 *data, int index);
+void hns_rcb_get_strings(int stringset, u8 **data, int index);
void hns_rcb_set_rx_ring_bs(struct hnae_queue *q, u32 buf_size);
void hns_rcb_set_tx_ring_bs(struct hnae_queue *q, u32 buf_size);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
index c58833eb4830..dbc44c2c26c2 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
@@ -743,16 +743,15 @@ static void hns_xgmac_get_stats(void *mac_drv, u64 *data)
*@stringset: type of values in data
*@data:data for value of string name
*/
-static void hns_xgmac_get_strings(u32 stringset, u8 *data)
+static void hns_xgmac_get_strings(u32 stringset, u8 **data)
{
- u8 *buff = data;
u32 i;
if (stringset != ETH_SS_STATS)
return;
for (i = 0; i < ARRAY_SIZE(g_xgmac_stats_string); i++)
- ethtool_puts(&buff, g_xgmac_stats_string[i].desc);
+ ethtool_puts(data, g_xgmac_stats_string[i].desc);
}
/**
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index fd32e15cadcb..42bb341fd80b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -2439,7 +2439,7 @@ static struct platform_driver hns_nic_dev_driver = {
.acpi_match_table = ACPI_PTR(hns_enet_acpi_match),
},
.probe = hns_nic_dev_probe,
- .remove_new = hns_nic_dev_remove,
+ .remove = hns_nic_dev_remove,
};
module_platform_driver(hns_nic_dev_driver);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index a5bb306b2cf1..6c458f037262 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -903,7 +903,6 @@ static void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
struct hns_nic_priv *priv = netdev_priv(netdev);
struct hnae_handle *h = priv->ae_handle;
- u8 *buff = data;
if (!h->dev->ops->get_strings) {
netdev_err(netdev, "h->dev->ops->get_strings is null!\n");
@@ -912,43 +911,43 @@ static void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
if (stringset == ETH_SS_TEST) {
if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)
- ethtool_puts(&buff,
+ ethtool_puts(&data,
hns_nic_test_strs[MAC_INTERNALLOOP_MAC]);
- ethtool_puts(&buff, hns_nic_test_strs[MAC_INTERNALLOOP_SERDES]);
+ ethtool_puts(&data, hns_nic_test_strs[MAC_INTERNALLOOP_SERDES]);
if ((netdev->phydev) && (!netdev->phydev->is_c45))
- ethtool_puts(&buff,
+ ethtool_puts(&data,
hns_nic_test_strs[MAC_INTERNALLOOP_PHY]);
} else {
- ethtool_puts(&buff, "rx_packets");
- ethtool_puts(&buff, "tx_packets");
- ethtool_puts(&buff, "rx_bytes");
- ethtool_puts(&buff, "tx_bytes");
- ethtool_puts(&buff, "rx_errors");
- ethtool_puts(&buff, "tx_errors");
- ethtool_puts(&buff, "rx_dropped");
- ethtool_puts(&buff, "tx_dropped");
- ethtool_puts(&buff, "multicast");
- ethtool_puts(&buff, "collisions");
- ethtool_puts(&buff, "rx_over_errors");
- ethtool_puts(&buff, "rx_crc_errors");
- ethtool_puts(&buff, "rx_frame_errors");
- ethtool_puts(&buff, "rx_fifo_errors");
- ethtool_puts(&buff, "rx_missed_errors");
- ethtool_puts(&buff, "tx_aborted_errors");
- ethtool_puts(&buff, "tx_carrier_errors");
- ethtool_puts(&buff, "tx_fifo_errors");
- ethtool_puts(&buff, "tx_heartbeat_errors");
- ethtool_puts(&buff, "rx_length_errors");
- ethtool_puts(&buff, "tx_window_errors");
- ethtool_puts(&buff, "rx_compressed");
- ethtool_puts(&buff, "tx_compressed");
- ethtool_puts(&buff, "netdev_rx_dropped");
- ethtool_puts(&buff, "netdev_tx_dropped");
-
- ethtool_puts(&buff, "netdev_tx_timeout");
-
- h->dev->ops->get_strings(h, stringset, buff);
+ ethtool_puts(&data, "rx_packets");
+ ethtool_puts(&data, "tx_packets");
+ ethtool_puts(&data, "rx_bytes");
+ ethtool_puts(&data, "tx_bytes");
+ ethtool_puts(&data, "rx_errors");
+ ethtool_puts(&data, "tx_errors");
+ ethtool_puts(&data, "rx_dropped");
+ ethtool_puts(&data, "tx_dropped");
+ ethtool_puts(&data, "multicast");
+ ethtool_puts(&data, "collisions");
+ ethtool_puts(&data, "rx_over_errors");
+ ethtool_puts(&data, "rx_crc_errors");
+ ethtool_puts(&data, "rx_frame_errors");
+ ethtool_puts(&data, "rx_fifo_errors");
+ ethtool_puts(&data, "rx_missed_errors");
+ ethtool_puts(&data, "tx_aborted_errors");
+ ethtool_puts(&data, "tx_carrier_errors");
+ ethtool_puts(&data, "tx_fifo_errors");
+ ethtool_puts(&data, "tx_heartbeat_errors");
+ ethtool_puts(&data, "rx_length_errors");
+ ethtool_puts(&data, "tx_window_errors");
+ ethtool_puts(&data, "rx_compressed");
+ ethtool_puts(&data, "tx_compressed");
+ ethtool_puts(&data, "netdev_rx_dropped");
+ ethtool_puts(&data, "netdev_tx_dropped");
+
+ ethtool_puts(&data, "netdev_tx_timeout");
+
+ h->dev->ops->get_strings(h, stringset, &data);
}
}
@@ -970,7 +969,7 @@ static int hns_get_sset_count(struct net_device *netdev, int stringset)
return -EOPNOTSUPP;
}
if (stringset == ETH_SS_TEST) {
- u32 cnt = (sizeof(hns_nic_test_strs) / ETH_GSTRING_LEN);
+ u32 cnt = ARRAY_SIZE(hns_nic_test_strs);
if (priv->ae_handle->phy_if == PHY_INTERFACE_MODE_XGMII)
cnt--;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
index 67b0bf310daa..9a63fbc69408 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
@@ -25,8 +25,11 @@ void hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo *ae_algo)
pci_id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
if (!pci_id)
continue;
- if (IS_ENABLED(CONFIG_PCI_IOV))
+ if (IS_ENABLED(CONFIG_PCI_IOV)) {
+ device_lock(&ae_dev->pdev->dev);
pci_disable_sriov(ae_dev->pdev);
+ device_unlock(&ae_dev->pdev->dev);
+ }
}
}
EXPORT_SYMBOL(hnae3_unregister_ae_algo_prepare);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 27dbe367f3d3..710a8f9f2248 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -677,7 +677,7 @@ struct hnae3_ae_ops {
void (*get_mac_stats)(struct hnae3_handle *handle,
struct hns3_mac_stats *mac_stats);
void (*get_strings)(struct hnae3_handle *handle,
- u32 stringset, u8 *data);
+ u32 stringset, u8 **data);
int (*get_sset_count)(struct hnae3_handle *handle, int stringset);
void (*get_regs)(struct hnae3_handle *handle, u32 *version,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c
index 2b31188ff555..f9a3d6fc4416 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c
@@ -36,27 +36,22 @@ int hclge_comm_tqps_get_sset_count(struct hnae3_handle *handle)
}
EXPORT_SYMBOL_GPL(hclge_comm_tqps_get_sset_count);
-u8 *hclge_comm_tqps_get_strings(struct hnae3_handle *handle, u8 *data)
+void hclge_comm_tqps_get_strings(struct hnae3_handle *handle, u8 **data)
{
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
- u8 *buff = data;
u16 i;
for (i = 0; i < kinfo->num_tqps; i++) {
struct hclge_comm_tqp *tqp =
container_of(kinfo->tqp[i], struct hclge_comm_tqp, q);
- snprintf(buff, ETH_GSTRING_LEN, "txq%u_pktnum_rcd", tqp->index);
- buff += ETH_GSTRING_LEN;
+ ethtool_sprintf(data, "txq%u_pktnum_rcd", tqp->index);
}
for (i = 0; i < kinfo->num_tqps; i++) {
struct hclge_comm_tqp *tqp =
container_of(kinfo->tqp[i], struct hclge_comm_tqp, q);
- snprintf(buff, ETH_GSTRING_LEN, "rxq%u_pktnum_rcd", tqp->index);
- buff += ETH_GSTRING_LEN;
+ ethtool_sprintf(data, "rxq%u_pktnum_rcd", tqp->index);
}
-
- return buff;
}
EXPORT_SYMBOL_GPL(hclge_comm_tqps_get_strings);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.h
index a46350162ee8..b9ff424c0bc2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.h
@@ -32,7 +32,7 @@ struct hclge_comm_tqp {
u64 *hclge_comm_tqps_get_stats(struct hnae3_handle *handle, u64 *data);
int hclge_comm_tqps_get_sset_count(struct hnae3_handle *handle);
-u8 *hclge_comm_tqps_get_strings(struct hnae3_handle *handle, u8 *data);
+void hclge_comm_tqps_get_strings(struct hnae3_handle *handle, u8 **data);
void hclge_comm_reset_tqp_stats(struct hnae3_handle *handle);
int hclge_comm_tqps_update_stats(struct hnae3_handle *handle,
struct hclge_comm_hw *hw);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 841e5af7b2be..807eb3bbb11c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -1293,10 +1293,8 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
/* save the buffer addr until the last read operation */
*save_buf = read_buf;
- }
- /* get data ready for the first time to read */
- if (!*ppos) {
+ /* get data ready for the first time to read */
ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd,
read_buf, hns3_dbg_cmd[index].buf_len);
if (ret)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index b09f0cca34dc..43377a7b2426 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -11,7 +11,6 @@
#include <linux/irq.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
-#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/skbuff.h>
@@ -381,24 +380,6 @@ static const struct hns3_rx_ptype hns3_rx_ptype_tbl[] = {
#define HNS3_INVALID_PTYPE \
ARRAY_SIZE(hns3_rx_ptype_tbl)
-static void hns3_dma_map_sync(struct device *dev, unsigned long iova)
-{
- struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
- struct iommu_iotlb_gather iotlb_gather;
- size_t granule;
-
- if (!domain || !iommu_is_dma_domain(domain))
- return;
-
- granule = 1 << __ffs(domain->pgsize_bitmap);
- iova = ALIGN_DOWN(iova, granule);
- iotlb_gather.start = iova;
- iotlb_gather.end = iova + granule - 1;
- iotlb_gather.pgsize = granule;
-
- iommu_iotlb_sync(domain, &iotlb_gather);
-}
-
static irqreturn_t hns3_irq_handle(int irq, void *vector)
{
struct hns3_enet_tqp_vector *tqp_vector = vector;
@@ -1051,8 +1032,6 @@ static bool hns3_can_use_tx_sgl(struct hns3_enet_ring *ring,
static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring)
{
u32 alloc_size = ring->tqp->handle->kinfo.tx_spare_buf_size;
- struct net_device *netdev = ring_to_netdev(ring);
- struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hns3_tx_spare *tx_spare;
struct page *page;
dma_addr_t dma;
@@ -1094,7 +1073,6 @@ static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring)
tx_spare->buf = page_address(page);
tx_spare->len = PAGE_SIZE << order;
ring->tx_spare = tx_spare;
- ring->tx_copybreak = priv->tx_copybreak;
return;
dma_mapping_error:
@@ -1746,9 +1724,7 @@ static int hns3_map_and_fill_desc(struct hns3_enet_ring *ring, void *priv,
unsigned int type)
{
struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
- struct hnae3_handle *handle = ring->tqp->handle;
struct device *dev = ring_to_dev(ring);
- struct hnae3_ae_dev *ae_dev;
unsigned int size;
dma_addr_t dma;
@@ -1780,13 +1756,6 @@ static int hns3_map_and_fill_desc(struct hns3_enet_ring *ring, void *priv,
return -ENOMEM;
}
- /* Add a SYNC command to sync io-pgtale to avoid errors in pgtable
- * prefetch
- */
- ae_dev = hns3_get_ae_dev(handle);
- if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3)
- hns3_dma_map_sync(dev, dma);
-
desc_cb->priv = priv;
desc_cb->length = size;
desc_cb->dma = dma;
@@ -2483,6 +2452,7 @@ static int hns3_nic_set_features(struct net_device *netdev,
return ret;
}
+ netdev->features = features;
return 0;
}
@@ -4478,7 +4448,7 @@ static void hns3_update_rx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector)
dim_update_sample(tqp_vector->event_cnt, rx_group->total_packets,
rx_group->total_bytes, &sample);
- net_dim(&rx_group->dim, sample);
+ net_dim(&rx_group->dim, &sample);
}
static void hns3_update_tx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector)
@@ -4491,7 +4461,7 @@ static void hns3_update_tx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector)
dim_update_sample(tqp_vector->event_cnt, tx_group->total_packets,
tx_group->total_bytes, &sample);
- net_dim(&tx_group->dim, sample);
+ net_dim(&tx_group->dim, &sample);
}
static int hns3_nic_common_poll(struct napi_struct *napi, int budget)
@@ -4898,30 +4868,6 @@ static void hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv)
devm_kfree(&pdev->dev, priv->tqp_vector);
}
-static void hns3_update_tx_spare_buf_config(struct hns3_nic_priv *priv)
-{
-#define HNS3_MIN_SPARE_BUF_SIZE (2 * 1024 * 1024)
-#define HNS3_MAX_PACKET_SIZE (64 * 1024)
-
- struct iommu_domain *domain = iommu_get_domain_for_dev(priv->dev);
- struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(priv->ae_handle);
- struct hnae3_handle *handle = priv->ae_handle;
-
- if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3)
- return;
-
- if (!(domain && iommu_is_dma_domain(domain)))
- return;
-
- priv->min_tx_copybreak = HNS3_MAX_PACKET_SIZE;
- priv->min_tx_spare_buf_size = HNS3_MIN_SPARE_BUF_SIZE;
-
- if (priv->tx_copybreak < priv->min_tx_copybreak)
- priv->tx_copybreak = priv->min_tx_copybreak;
- if (handle->kinfo.tx_spare_buf_size < priv->min_tx_spare_buf_size)
- handle->kinfo.tx_spare_buf_size = priv->min_tx_spare_buf_size;
-}
-
static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
unsigned int ring_type)
{
@@ -5155,7 +5101,6 @@ int hns3_init_all_ring(struct hns3_nic_priv *priv)
int i, j;
int ret;
- hns3_update_tx_spare_buf_config(priv);
for (i = 0; i < ring_num; i++) {
ret = hns3_alloc_ring_memory(&priv->ring[i]);
if (ret) {
@@ -5360,8 +5305,6 @@ static int hns3_client_init(struct hnae3_handle *handle)
priv->ae_handle = handle;
priv->tx_timeout_count = 0;
priv->max_non_tso_bd_num = ae_dev->dev_specs.max_non_tso_bd_num;
- priv->min_tx_copybreak = 0;
- priv->min_tx_spare_buf_size = 0;
set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
handle->msg_enable = netif_msg_init(debug, DEFAULT_MSG_LEVEL);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
index caf7a4df8585..d36c4ed16d8d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -596,8 +596,6 @@ struct hns3_nic_priv {
struct hns3_enet_coalesce rx_coal;
u32 tx_copybreak;
u32 rx_copybreak;
- u32 min_tx_copybreak;
- u32 min_tx_spare_buf_size;
};
union l3_hdr_info {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 97eaeec1952b..b771a2daba43 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -509,54 +509,37 @@ static int hns3_get_sset_count(struct net_device *netdev, int stringset)
}
}
-static void *hns3_update_strings(u8 *data, const struct hns3_stats *stats,
- u32 stat_count, u32 num_tqps, const char *prefix)
+static void hns3_update_strings(u8 **data, const struct hns3_stats *stats,
+ u32 stat_count, u32 num_tqps,
+ const char *prefix)
{
-#define MAX_PREFIX_SIZE (6 + 4)
- u32 size_left;
u32 i, j;
- u32 n1;
- for (i = 0; i < num_tqps; i++) {
- for (j = 0; j < stat_count; j++) {
- data[ETH_GSTRING_LEN - 1] = '\0';
-
- /* first, prepend the prefix string */
- n1 = scnprintf(data, MAX_PREFIX_SIZE, "%s%u_",
- prefix, i);
- size_left = (ETH_GSTRING_LEN - 1) - n1;
-
- /* now, concatenate the stats string to it */
- strncat(data, stats[j].stats_string, size_left);
- data += ETH_GSTRING_LEN;
- }
- }
-
- return data;
+ for (i = 0; i < num_tqps; i++)
+ for (j = 0; j < stat_count; j++)
+ ethtool_sprintf(data, "%s%u_%s", prefix, i,
+ stats[j].stats_string);
}
-static u8 *hns3_get_strings_tqps(struct hnae3_handle *handle, u8 *data)
+static void hns3_get_strings_tqps(struct hnae3_handle *handle, u8 **data)
{
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
const char tx_prefix[] = "txq";
const char rx_prefix[] = "rxq";
/* get strings for Tx */
- data = hns3_update_strings(data, hns3_txq_stats, HNS3_TXQ_STATS_COUNT,
- kinfo->num_tqps, tx_prefix);
+ hns3_update_strings(data, hns3_txq_stats, HNS3_TXQ_STATS_COUNT,
+ kinfo->num_tqps, tx_prefix);
/* get strings for Rx */
- data = hns3_update_strings(data, hns3_rxq_stats, HNS3_RXQ_STATS_COUNT,
- kinfo->num_tqps, rx_prefix);
-
- return data;
+ hns3_update_strings(data, hns3_rxq_stats, HNS3_RXQ_STATS_COUNT,
+ kinfo->num_tqps, rx_prefix);
}
static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
struct hnae3_handle *h = hns3_get_handle(netdev);
const struct hnae3_ae_ops *ops = h->ae_algo->ops;
- char *buff = (char *)data;
int i;
if (!ops->get_strings)
@@ -564,18 +547,15 @@ static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
switch (stringset) {
case ETH_SS_STATS:
- buff = hns3_get_strings_tqps(h, buff);
- ops->get_strings(h, stringset, (u8 *)buff);
+ hns3_get_strings_tqps(h, &data);
+ ops->get_strings(h, stringset, &data);
break;
case ETH_SS_TEST:
- ops->get_strings(h, stringset, data);
+ ops->get_strings(h, stringset, &data);
break;
case ETH_SS_PRIV_FLAGS:
- for (i = 0; i < HNS3_PRIV_FLAGS_LEN; i++) {
- snprintf(buff, ETH_GSTRING_LEN, "%s",
- hns3_priv_flags[i].name);
- buff += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < HNS3_PRIV_FLAGS_LEN; i++)
+ ethtool_puts(&data, hns3_priv_flags[i].name);
break;
default:
break;
@@ -1933,31 +1913,6 @@ static int hns3_set_tx_spare_buf_size(struct net_device *netdev,
return ret;
}
-static int hns3_check_tx_copybreak(struct net_device *netdev, u32 copybreak)
-{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
-
- if (copybreak < priv->min_tx_copybreak) {
- netdev_err(netdev, "tx copybreak %u should be no less than %u!\n",
- copybreak, priv->min_tx_copybreak);
- return -EINVAL;
- }
- return 0;
-}
-
-static int hns3_check_tx_spare_buf_size(struct net_device *netdev, u32 buf_size)
-{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
-
- if (buf_size < priv->min_tx_spare_buf_size) {
- netdev_err(netdev,
- "tx spare buf size %u should be no less than %u!\n",
- buf_size, priv->min_tx_spare_buf_size);
- return -EINVAL;
- }
- return 0;
-}
-
static int hns3_set_tunable(struct net_device *netdev,
const struct ethtool_tunable *tuna,
const void *data)
@@ -1974,10 +1929,6 @@ static int hns3_set_tunable(struct net_device *netdev,
switch (tuna->id) {
case ETHTOOL_TX_COPYBREAK:
- ret = hns3_check_tx_copybreak(netdev, *(u32 *)data);
- if (ret)
- return ret;
-
priv->tx_copybreak = *(u32 *)data;
for (i = 0; i < h->kinfo.num_tqps; i++)
@@ -1992,10 +1943,6 @@ static int hns3_set_tunable(struct net_device *netdev,
break;
case ETHTOOL_TX_COPYBREAK_BUF_SIZE:
- ret = hns3_check_tx_spare_buf_size(netdev, *(u32 *)data);
- if (ret)
- return ret;
-
old_tx_spare_buf_size = h->kinfo.tx_spare_buf_size;
new_tx_spare_buf_size = *(u32 *)data;
netdev_info(netdev, "request to set tx spare buf size from %u to %u\n",
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 728f4777e51f..05942fa78b11 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -6,7 +6,6 @@
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -595,25 +594,21 @@ static u64 *hclge_comm_get_stats(struct hclge_dev *hdev,
return buf;
}
-static u8 *hclge_comm_get_strings(struct hclge_dev *hdev, u32 stringset,
- const struct hclge_comm_stats_str strs[],
- int size, u8 *data)
+static void hclge_comm_get_strings(struct hclge_dev *hdev, u32 stringset,
+ const struct hclge_comm_stats_str strs[],
+ int size, u8 **data)
{
- char *buff = (char *)data;
u32 i;
if (stringset != ETH_SS_STATS)
- return buff;
+ return;
for (i = 0; i < size; i++) {
if (strs[i].stats_num > hdev->ae_dev->dev_specs.mac_stats_num)
continue;
- snprintf(buff, ETH_GSTRING_LEN, "%s", strs[i].desc);
- buff = buff + ETH_GSTRING_LEN;
+ ethtool_puts(data, strs[i].desc);
}
-
- return (u8 *)buff;
}
static void hclge_update_stats_for_all(struct hclge_dev *hdev)
@@ -718,44 +713,38 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
}
static void hclge_get_strings(struct hnae3_handle *handle, u32 stringset,
- u8 *data)
+ u8 **data)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- u8 *p = (char *)data;
+ const char *str;
int size;
if (stringset == ETH_SS_STATS) {
size = ARRAY_SIZE(g_mac_stats_string);
- p = hclge_comm_get_strings(hdev, stringset, g_mac_stats_string,
- size, p);
- p = hclge_comm_tqps_get_strings(handle, p);
+ hclge_comm_get_strings(hdev, stringset, g_mac_stats_string,
+ size, data);
+ hclge_comm_tqps_get_strings(handle, data);
} else if (stringset == ETH_SS_TEST) {
if (handle->flags & HNAE3_SUPPORT_EXTERNAL_LOOPBACK) {
- memcpy(p, hns3_nic_test_strs[HNAE3_LOOP_EXTERNAL],
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
+ str = hns3_nic_test_strs[HNAE3_LOOP_EXTERNAL];
+ ethtool_puts(data, str);
}
if (handle->flags & HNAE3_SUPPORT_APP_LOOPBACK) {
- memcpy(p, hns3_nic_test_strs[HNAE3_LOOP_APP],
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
+ str = hns3_nic_test_strs[HNAE3_LOOP_APP];
+ ethtool_puts(data, str);
}
if (handle->flags & HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK) {
- memcpy(p, hns3_nic_test_strs[HNAE3_LOOP_SERIAL_SERDES],
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
+ str = hns3_nic_test_strs[HNAE3_LOOP_SERIAL_SERDES];
+ ethtool_puts(data, str);
}
if (handle->flags & HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK) {
- memcpy(p,
- hns3_nic_test_strs[HNAE3_LOOP_PARALLEL_SERDES],
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
+ str = hns3_nic_test_strs[HNAE3_LOOP_PARALLEL_SERDES];
+ ethtool_puts(data, str);
}
if (handle->flags & HNAE3_SUPPORT_PHY_LOOPBACK) {
- memcpy(p, hns3_nic_test_strs[HNAE3_LOOP_PHY],
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
+ str = hns3_nic_test_strs[HNAE3_LOOP_PHY];
+ ethtool_puts(data, str);
}
}
}
@@ -3585,17 +3574,6 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf,
return ret;
}
-static void hclge_set_reset_pending(struct hclge_dev *hdev,
- enum hnae3_reset_type reset_type)
-{
- /* When an incorrect reset type is executed, the get_reset_level
- * function generates the HNAE3_NONE_RESET flag. As a result, this
- * type do not need to pending.
- */
- if (reset_type != HNAE3_NONE_RESET)
- set_bit(reset_type, &hdev->reset_pending);
-}
-
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
{
u32 cmdq_src_reg, msix_src_reg, hw_err_src_reg;
@@ -3616,7 +3594,7 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
*/
if (BIT(HCLGE_VECTOR0_IMPRESET_INT_B) & msix_src_reg) {
dev_info(&hdev->pdev->dev, "IMP reset interrupt\n");
- hclge_set_reset_pending(hdev, HNAE3_IMP_RESET);
+ set_bit(HNAE3_IMP_RESET, &hdev->reset_pending);
set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
*clearval = BIT(HCLGE_VECTOR0_IMPRESET_INT_B);
hdev->rst_stats.imp_rst_cnt++;
@@ -3626,7 +3604,7 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
if (BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B) & msix_src_reg) {
dev_info(&hdev->pdev->dev, "global reset interrupt\n");
set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
- hclge_set_reset_pending(hdev, HNAE3_GLOBAL_RESET);
+ set_bit(HNAE3_GLOBAL_RESET, &hdev->reset_pending);
*clearval = BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B);
hdev->rst_stats.global_rst_cnt++;
return HCLGE_VECTOR0_EVENT_RST;
@@ -3781,7 +3759,7 @@ static int hclge_misc_irq_init(struct hclge_dev *hdev)
snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s",
HCLGE_NAME, pci_name(hdev->pdev));
ret = request_irq(hdev->misc_vector.vector_irq, hclge_misc_irq_handle,
- IRQ_NOAUTOEN, hdev->misc_vector.name, hdev);
+ 0, hdev->misc_vector.name, hdev);
if (ret) {
hclge_free_vector(hdev, 0);
dev_err(&hdev->pdev->dev, "request misc irq(%d) fail\n",
@@ -4074,7 +4052,7 @@ static void hclge_do_reset(struct hclge_dev *hdev)
case HNAE3_FUNC_RESET:
dev_info(&pdev->dev, "PF reset requested\n");
/* schedule again to check later */
- hclge_set_reset_pending(hdev, HNAE3_FUNC_RESET);
+ set_bit(HNAE3_FUNC_RESET, &hdev->reset_pending);
hclge_reset_task_schedule(hdev);
break;
default:
@@ -4108,8 +4086,6 @@ static enum hnae3_reset_type hclge_get_reset_level(struct hnae3_ae_dev *ae_dev,
clear_bit(HNAE3_FLR_RESET, addr);
}
- clear_bit(HNAE3_NONE_RESET, addr);
-
if (hdev->reset_type != HNAE3_NONE_RESET &&
rst_level < hdev->reset_type)
return HNAE3_NONE_RESET;
@@ -4251,7 +4227,7 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev)
return false;
} else if (hdev->rst_stats.reset_fail_cnt < MAX_RESET_FAIL_CNT) {
hdev->rst_stats.reset_fail_cnt++;
- hclge_set_reset_pending(hdev, hdev->reset_type);
+ set_bit(hdev->reset_type, &hdev->reset_pending);
dev_info(&hdev->pdev->dev,
"re-schedule reset task(%u)\n",
hdev->rst_stats.reset_fail_cnt);
@@ -4494,20 +4470,8 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle)
static void hclge_set_def_reset_request(struct hnae3_ae_dev *ae_dev,
enum hnae3_reset_type rst_type)
{
-#define HCLGE_SUPPORT_RESET_TYPE \
- (BIT(HNAE3_FLR_RESET) | BIT(HNAE3_FUNC_RESET) | \
- BIT(HNAE3_GLOBAL_RESET) | BIT(HNAE3_IMP_RESET))
-
struct hclge_dev *hdev = ae_dev->priv;
- if (!(BIT(rst_type) & HCLGE_SUPPORT_RESET_TYPE)) {
- /* To prevent reset triggered by hclge_reset_event */
- set_bit(HNAE3_NONE_RESET, &hdev->default_reset_request);
- dev_warn(&hdev->pdev->dev, "unsupported reset type %d\n",
- rst_type);
- return;
- }
-
set_bit(rst_type, &hdev->default_reset_request);
}
@@ -11917,6 +11881,9 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
hclge_init_rxd_adv_layout(hdev);
+ /* Enable MISC vector(vector0) */
+ hclge_enable_vector(&hdev->misc_vector, true);
+
ret = hclge_init_wol(hdev);
if (ret)
dev_warn(&pdev->dev,
@@ -11929,10 +11896,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
hclge_state_init(hdev);
hdev->last_reset_time = jiffies;
- /* Enable MISC vector(vector0) */
- enable_irq(hdev->misc_vector.vector_irq);
- hclge_enable_vector(&hdev->misc_vector, true);
-
dev_info(&hdev->pdev->dev, "%s driver initialization finished.\n",
HCLGE_DRIVER_NAME);
@@ -12338,7 +12301,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
/* Disable MISC vector(vector0) */
hclge_enable_vector(&hdev->misc_vector, false);
- disable_irq(hdev->misc_vector.vector_irq);
+ synchronize_irq(hdev->misc_vector.vector_irq);
/* Disable all hw interrupts */
hclge_config_mac_tnl_int(hdev, false);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
index bab16c2191b2..5505caea88e9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
@@ -58,9 +58,6 @@ bool hclge_ptp_set_tx_info(struct hnae3_handle *handle, struct sk_buff *skb)
struct hclge_dev *hdev = vport->back;
struct hclge_ptp *ptp = hdev->ptp;
- if (!ptp)
- return false;
-
if (!test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) ||
test_and_set_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state)) {
ptp->tx_skipped++;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
index 8c057192aae6..43c1c18fa81f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
@@ -510,9 +510,9 @@ out:
static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data,
struct hnae3_knic_private_info *kinfo)
{
+#define HCLGE_RING_REG_OFFSET 0x200
#define HCLGE_RING_INT_REG_OFFSET 0x4
- struct hnae3_queue *tqp;
int i, j, reg_num;
int data_num_sum;
u32 *reg = data;
@@ -533,11 +533,10 @@ static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data,
reg_num = ARRAY_SIZE(ring_reg_addr_list);
for (j = 0; j < kinfo->num_tqps; j++) {
reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RING, reg_num, reg);
- tqp = kinfo->tqp[j];
for (i = 0; i < reg_num; i++)
- *reg++ = readl_relaxed(tqp->io_base -
- HCLGE_TQP_REG_OFFSET +
- ring_reg_addr_list[i]);
+ *reg++ = hclge_read_dev(&hdev->hw,
+ ring_reg_addr_list[i] +
+ HCLGE_RING_REG_OFFSET * j);
}
data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * kinfo->num_tqps;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index 896f1eb172d3..2f6ffb88e700 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -130,12 +130,10 @@ static int hclgevf_get_sset_count(struct hnae3_handle *handle, int strset)
}
static void hclgevf_get_strings(struct hnae3_handle *handle, u32 strset,
- u8 *data)
+ u8 **data)
{
- u8 *p = (char *)data;
-
if (strset == ETH_SS_STATS)
- p = hclge_comm_tqps_get_strings(handle, p);
+ hclge_comm_tqps_get_strings(handle, data);
}
static void hclgevf_get_stats(struct hnae3_handle *handle, u64 *data)
@@ -1395,17 +1393,6 @@ static int hclgevf_notify_roce_client(struct hclgevf_dev *hdev,
return ret;
}
-static void hclgevf_set_reset_pending(struct hclgevf_dev *hdev,
- enum hnae3_reset_type reset_type)
-{
- /* When an incorrect reset type is executed, the get_reset_level
- * function generates the HNAE3_NONE_RESET flag. As a result, this
- * type do not need to pending.
- */
- if (reset_type != HNAE3_NONE_RESET)
- set_bit(reset_type, &hdev->reset_pending);
-}
-
static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
{
#define HCLGEVF_RESET_WAIT_US 20000
@@ -1555,7 +1542,7 @@ static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev)
hdev->rst_stats.rst_fail_cnt);
if (hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT)
- hclgevf_set_reset_pending(hdev, hdev->reset_type);
+ set_bit(hdev->reset_type, &hdev->reset_pending);
if (hclgevf_is_reset_pending(hdev)) {
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
@@ -1675,8 +1662,6 @@ static enum hnae3_reset_type hclgevf_get_reset_level(unsigned long *addr)
clear_bit(HNAE3_FLR_RESET, addr);
}
- clear_bit(HNAE3_NONE_RESET, addr);
-
return rst_level;
}
@@ -1686,15 +1671,14 @@ static void hclgevf_reset_event(struct pci_dev *pdev,
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
struct hclgevf_dev *hdev = ae_dev->priv;
+ dev_info(&hdev->pdev->dev, "received reset request from VF enet\n");
+
if (hdev->default_reset_request)
hdev->reset_level =
hclgevf_get_reset_level(&hdev->default_reset_request);
else
hdev->reset_level = HNAE3_VF_FUNC_RESET;
- dev_info(&hdev->pdev->dev, "received reset request from VF enet, reset level is %d\n",
- hdev->reset_level);
-
/* reset of this VF requested */
set_bit(HCLGEVF_RESET_REQUESTED, &hdev->reset_state);
hclgevf_reset_task_schedule(hdev);
@@ -1705,20 +1689,8 @@ static void hclgevf_reset_event(struct pci_dev *pdev,
static void hclgevf_set_def_reset_request(struct hnae3_ae_dev *ae_dev,
enum hnae3_reset_type rst_type)
{
-#define HCLGEVF_SUPPORT_RESET_TYPE \
- (BIT(HNAE3_VF_RESET) | BIT(HNAE3_VF_FUNC_RESET) | \
- BIT(HNAE3_VF_PF_FUNC_RESET) | BIT(HNAE3_VF_FULL_RESET) | \
- BIT(HNAE3_FLR_RESET) | BIT(HNAE3_VF_EXP_RESET))
-
struct hclgevf_dev *hdev = ae_dev->priv;
- if (!(BIT(rst_type) & HCLGEVF_SUPPORT_RESET_TYPE)) {
- /* To prevent reset triggered by hclge_reset_event */
- set_bit(HNAE3_NONE_RESET, &hdev->default_reset_request);
- dev_info(&hdev->pdev->dev, "unsupported reset type %d\n",
- rst_type);
- return;
- }
set_bit(rst_type, &hdev->default_reset_request);
}
@@ -1875,14 +1847,14 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
*/
if (hdev->reset_attempts > HCLGEVF_MAX_RESET_ATTEMPTS_CNT) {
/* prepare for full reset of stack + pcie interface */
- hclgevf_set_reset_pending(hdev, HNAE3_VF_FULL_RESET);
+ set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending);
/* "defer" schedule the reset task again */
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
} else {
hdev->reset_attempts++;
- hclgevf_set_reset_pending(hdev, hdev->reset_level);
+ set_bit(hdev->reset_level, &hdev->reset_pending);
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
}
hclgevf_reset_task_schedule(hdev);
@@ -2005,7 +1977,7 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
dev_info(&hdev->pdev->dev,
"receive reset interrupt 0x%x!\n", rst_ing_reg);
- hclgevf_set_reset_pending(hdev, HNAE3_VF_RESET);
+ set_bit(HNAE3_VF_RESET, &hdev->reset_pending);
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
*clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B);
@@ -2315,7 +2287,6 @@ static void hclgevf_state_init(struct hclgevf_dev *hdev)
clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
INIT_DELAYED_WORK(&hdev->service_task, hclgevf_service_task);
- timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0);
mutex_init(&hdev->mbx_resp.mbx_mutex);
sema_init(&hdev->reset_sem, 1);
@@ -3015,6 +2986,7 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
HCLGEVF_DRIVER_NAME);
hclgevf_task_schedule(hdev, round_jiffies_relative(HZ));
+ timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0);
return 0;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
index 7d9d9dbc7560..6db415d8b917 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
@@ -123,10 +123,10 @@ int hclgevf_get_regs_len(struct hnae3_handle *handle)
void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
void *data)
{
+#define HCLGEVF_RING_REG_OFFSET 0x200
#define HCLGEVF_RING_INT_REG_OFFSET 0x4
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
- struct hnae3_queue *tqp;
int i, j, reg_um;
u32 *reg = data;
@@ -147,11 +147,10 @@ void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
reg_um = ARRAY_SIZE(ring_reg_addr_list);
for (j = 0; j < hdev->num_tqps; j++) {
reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_RING, reg_um, reg);
- tqp = &hdev->htqp[j].q;
for (i = 0; i < reg_um; i++)
- *reg++ = readl_relaxed(tqp->io_base -
- HCLGEVF_TQP_REG_OFFSET +
- ring_reg_addr_list[i]);
+ *reg++ = hclgevf_read_dev(&hdev->hw,
+ ring_reg_addr_list[i] +
+ HCLGEVF_RING_REG_OFFSET * j);
}
reg_um = ARRAY_SIZE(tqp_intr_reg_addr_list);
diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c
index 8a047145f0c5..a1aa6c1f966e 100644
--- a/drivers/net/ethernet/hisilicon/hns_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns_mdio.c
@@ -636,7 +636,7 @@ MODULE_DEVICE_TABLE(acpi, hns_mdio_acpi_match);
static struct platform_driver hns_mdio_driver = {
.probe = hns_mdio_probe,
- .remove_new = hns_mdio_remove,
+ .remove = hns_mdio_remove,
.driver = {
.name = MDIO_DRV_NAME,
.of_match_table = hns_mdio_match,
diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c
index 813403c2628f..baa598988f47 100644
--- a/drivers/net/ethernet/i825xx/sni_82596.c
+++ b/drivers/net/ethernet/i825xx/sni_82596.c
@@ -168,7 +168,7 @@ static void sni_82596_driver_remove(struct platform_device *pdev)
static struct platform_driver sni_82596_driver = {
.probe = sni_82596_probe,
- .remove_new = sni_82596_driver_remove,
+ .remove = sni_82596_driver_remove,
.driver = {
.name = sni_82596_string,
},
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index c41c3f1cc506..9b006bc353a1 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -121,7 +121,7 @@ static struct platform_driver ehea_driver = {
.of_match_table = ehea_device_table,
},
.probe = ehea_probe_adapter,
- .remove_new = ehea_remove,
+ .remove = ehea_remove,
};
void ehea_dump(void *adr, int len, char *msg)
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index dac570f3c110..25b8a3556004 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -1727,6 +1727,7 @@ static inline int emac_rx_sg_append(struct emac_instance *dev, int slot)
/* NAPI poll context */
static int emac_poll_rx(void *param, int budget)
{
+ LIST_HEAD(rx_list);
struct emac_instance *dev = param;
int slot = dev->rx_slot, received = 0;
@@ -1783,8 +1784,7 @@ static int emac_poll_rx(void *param, int budget)
skb->protocol = eth_type_trans(skb, dev->ndev);
emac_rx_csum(dev, skb, ctrl);
- if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
- ++dev->estats.rx_dropped_stack;
+ list_add_tail(&skb->list, &rx_list);
next:
++dev->stats.rx_packets;
skip:
@@ -1828,6 +1828,8 @@ static int emac_poll_rx(void *param, int budget)
goto next;
}
+ netif_receive_skb_list(&rx_list);
+
if (received) {
DBG2(dev, "rx %d BDs" NL, received);
dev->rx_slot = slot;
@@ -2935,9 +2937,12 @@ static int emac_init_config(struct emac_instance *dev)
/* Read MAC-address */
err = of_get_ethdev_address(np, dev->ndev);
- if (err)
- return dev_err_probe(&dev->ofdev->dev, err,
- "Can't get valid [local-]mac-address from OF !\n");
+ if (err == -EPROBE_DEFER)
+ return err;
+ if (err) {
+ dev_warn(&dev->ofdev->dev, "Can't get valid mac-address. Generating random.");
+ eth_hw_addr_random(dev->ndev);
+ }
/* IAHT and GAHT filter parameterization */
if (emac_has_feature(dev, EMAC_FTR_EMAC4SYNC)) {
@@ -3019,8 +3024,14 @@ static int emac_probe(struct platform_device *ofdev)
SET_NETDEV_DEV(ndev, &ofdev->dev);
/* Initialize some embedded data structures */
- mutex_init(&dev->mdio_lock);
- mutex_init(&dev->link_lock);
+ err = devm_mutex_init(&ofdev->dev, &dev->mdio_lock);
+ if (err)
+ goto err_gone;
+
+ err = devm_mutex_init(&ofdev->dev, &dev->link_lock);
+ if (err)
+ goto err_gone;
+
spin_lock_init(&dev->lock);
INIT_WORK(&dev->reset_work, emac_reset_work);
@@ -3029,15 +3040,8 @@ static int emac_probe(struct platform_device *ofdev)
if (err)
goto err_gone;
- /* Get interrupts. EMAC irq is mandatory */
- dev->emac_irq = irq_of_parse_and_map(np, 0);
- if (!dev->emac_irq) {
- printk(KERN_ERR "%pOF: Can't map main interrupt\n", np);
- err = -ENODEV;
- goto err_gone;
- }
-
/* Setup error IRQ handler */
+ dev->emac_irq = platform_get_irq(ofdev, 0);
err = devm_request_irq(&ofdev->dev, dev->emac_irq, emac_irq, 0, "EMAC",
dev);
if (err) {
@@ -3048,12 +3052,10 @@ static int emac_probe(struct platform_device *ofdev)
ndev->irq = dev->emac_irq;
- /* Map EMAC regs */
- // TODO : platform_get_resource() and devm_ioremap_resource()
- dev->emacp = devm_of_iomap(&ofdev->dev, np, 0, NULL);
- if (!dev->emacp) {
+ dev->emacp = devm_platform_ioremap_resource(ofdev, 0);
+ if (IS_ERR(dev->emacp)) {
dev_err(&ofdev->dev, "can't map device registers");
- err = -ENOMEM;
+ err = PTR_ERR(dev->emacp);
goto err_gone;
}
@@ -3241,7 +3243,7 @@ static struct platform_driver emac_driver = {
.of_match_table = emac_match,
},
.probe = emac_probe,
- .remove_new = emac_remove,
+ .remove = emac_remove,
};
static void __init emac_make_bootlist(void)
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index 99d5f83f7c60..7d70056e9008 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -524,7 +524,8 @@ static int mal_probe(struct platform_device *ofdev)
unsigned long irqflags;
irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
- mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
+ mal = devm_kzalloc(&ofdev->dev, sizeof(struct mal_instance),
+ GFP_KERNEL);
if (!mal)
return -ENOMEM;
@@ -539,8 +540,7 @@ static int mal_probe(struct platform_device *ofdev)
printk(KERN_ERR
"mal%d: can't find MAL num-tx-chans property!\n",
index);
- err = -ENODEV;
- goto fail;
+ return -ENODEV;
}
mal->num_tx_chans = prop[0];
@@ -549,8 +549,7 @@ static int mal_probe(struct platform_device *ofdev)
printk(KERN_ERR
"mal%d: can't find MAL num-rx-chans property!\n",
index);
- err = -ENODEV;
- goto fail;
+ return -ENODEV;
}
mal->num_rx_chans = prop[0];
@@ -558,15 +557,13 @@ static int mal_probe(struct platform_device *ofdev)
if (dcr_base == 0) {
printk(KERN_ERR
"mal%d: can't find DCR resource!\n", index);
- err = -ENODEV;
- goto fail;
+ return -ENODEV;
}
mal->dcr_host = dcr_map(ofdev->dev.of_node, dcr_base, 0x100);
if (!DCR_MAP_OK(mal->dcr_host)) {
printk(KERN_ERR
"mal%d: failed to map DCRs !\n", index);
- err = -ENODEV;
- goto fail;
+ return -ENODEV;
}
if (of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal-405ez")) {
@@ -582,25 +579,6 @@ static int mal_probe(struct platform_device *ofdev)
#endif
}
- mal->txeob_irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
- mal->rxeob_irq = irq_of_parse_and_map(ofdev->dev.of_node, 1);
- mal->serr_irq = irq_of_parse_and_map(ofdev->dev.of_node, 2);
-
- if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
- mal->txde_irq = mal->rxde_irq = mal->serr_irq;
- } else {
- mal->txde_irq = irq_of_parse_and_map(ofdev->dev.of_node, 3);
- mal->rxde_irq = irq_of_parse_and_map(ofdev->dev.of_node, 4);
- }
-
- if (!mal->txeob_irq || !mal->rxeob_irq || !mal->serr_irq ||
- !mal->txde_irq || !mal->rxde_irq) {
- printk(KERN_ERR
- "mal%d: failed to map interrupts !\n", index);
- err = -ENODEV;
- goto fail_unmap;
- }
-
INIT_LIST_HEAD(&mal->poll_list);
INIT_LIST_HEAD(&mal->list);
spin_lock_init(&mal->lock);
@@ -654,31 +632,43 @@ static int mal_probe(struct platform_device *ofdev)
sizeof(struct mal_descriptor) *
mal_rx_bd_offset(mal, i));
+ mal->txeob_irq = platform_get_irq(ofdev, 0);
+ mal->rxeob_irq = platform_get_irq(ofdev, 1);
+ mal->serr_irq = platform_get_irq(ofdev, 2);
+
if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
+ mal->txde_irq = mal->rxde_irq = mal->serr_irq;
irqflags = IRQF_SHARED;
hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
} else {
+ mal->txde_irq = platform_get_irq(ofdev, 3);
+ mal->rxde_irq = platform_get_irq(ofdev, 4);
irqflags = 0;
hdlr_serr = mal_serr;
hdlr_txde = mal_txde;
hdlr_rxde = mal_rxde;
}
- err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
+ err = devm_request_irq(&ofdev->dev, mal->serr_irq, hdlr_serr, irqflags,
+ "MAL SERR", mal);
if (err)
goto fail2;
- err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
+ err = devm_request_irq(&ofdev->dev, mal->txde_irq, hdlr_txde, irqflags,
+ "MAL TX DE", mal);
if (err)
- goto fail3;
- err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
+ goto fail2;
+ err = devm_request_irq(&ofdev->dev, mal->txeob_irq, mal_txeob, 0,
+ "MAL TX EOB", mal);
if (err)
- goto fail4;
- err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
+ goto fail2;
+ err = devm_request_irq(&ofdev->dev, mal->rxde_irq, hdlr_rxde, irqflags,
+ "MAL RX DE", mal);
if (err)
- goto fail5;
- err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
+ goto fail2;
+ err = devm_request_irq(&ofdev->dev, mal->rxeob_irq, mal_rxeob, 0,
+ "MAL RX EOB", mal);
if (err)
- goto fail6;
+ goto fail2;
/* Enable all MAL SERR interrupt sources */
set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS);
@@ -697,23 +687,12 @@ static int mal_probe(struct platform_device *ofdev)
return 0;
- fail6:
- free_irq(mal->rxde_irq, mal);
- fail5:
- free_irq(mal->txeob_irq, mal);
- fail4:
- free_irq(mal->txde_irq, mal);
- fail3:
- free_irq(mal->serr_irq, mal);
fail2:
dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
fail_dummy:
free_netdev(mal->dummy_dev);
fail_unmap:
dcr_unmap(mal->dcr_host, 0x100);
- fail:
- kfree(mal);
-
return err;
}
@@ -732,12 +711,6 @@ static void mal_remove(struct platform_device *ofdev)
"mal%d: commac list is not empty on remove!\n",
mal->index);
- free_irq(mal->serr_irq, mal);
- free_irq(mal->txde_irq, mal);
- free_irq(mal->txeob_irq, mal);
- free_irq(mal->rxde_irq, mal);
- free_irq(mal->rxeob_irq, mal);
-
mal_reset(mal);
free_netdev(mal->dummy_dev);
@@ -746,10 +719,9 @@ static void mal_remove(struct platform_device *ofdev)
dma_free_coherent(&ofdev->dev,
sizeof(struct mal_descriptor) *
- (NUM_TX_BUFF * mal->num_tx_chans +
- NUM_RX_BUFF * mal->num_rx_chans), mal->bd_virt,
- mal->bd_dma);
- kfree(mal);
+ (NUM_TX_BUFF * mal->num_tx_chans +
+ NUM_RX_BUFF * mal->num_rx_chans),
+ mal->bd_virt, mal->bd_dma);
}
static const struct of_device_id mal_platform_match[] =
@@ -778,7 +750,7 @@ static struct platform_driver mal_of_driver = {
.of_match_table = mal_platform_match,
},
.probe = mal_probe,
- .remove_new = mal_remove,
+ .remove = mal_remove,
};
int __init mal_init(void)
diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c
index e1712fdc3c31..b544dd8633b7 100644
--- a/drivers/net/ethernet/ibm/emac/rgmii.c
+++ b/drivers/net/ethernet/ibm/emac/rgmii.c
@@ -216,31 +216,24 @@ void *rgmii_dump_regs(struct platform_device *ofdev, void *buf)
static int rgmii_probe(struct platform_device *ofdev)
{
- struct device_node *np = ofdev->dev.of_node;
struct rgmii_instance *dev;
- struct resource regs;
- int rc;
+ int err;
- rc = -ENOMEM;
- dev = kzalloc(sizeof(struct rgmii_instance), GFP_KERNEL);
- if (dev == NULL)
- goto err_gone;
+ dev = devm_kzalloc(&ofdev->dev, sizeof(struct rgmii_instance),
+ GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
- mutex_init(&dev->lock);
- dev->ofdev = ofdev;
+ err = devm_mutex_init(&ofdev->dev, &dev->lock);
+ if (err)
+ return err;
- rc = -ENXIO;
- if (of_address_to_resource(np, 0, &regs)) {
- printk(KERN_ERR "%pOF: Can't get registers address\n", np);
- goto err_free;
- }
+ dev->ofdev = ofdev;
- rc = -ENOMEM;
- dev->base = (struct rgmii_regs __iomem *)ioremap(regs.start,
- sizeof(struct rgmii_regs));
- if (dev->base == NULL) {
- printk(KERN_ERR "%pOF: Can't map device registers!\n", np);
- goto err_free;
+ dev->base = devm_platform_ioremap_resource(ofdev, 0);
+ if (IS_ERR(dev->base)) {
+ dev_err(&ofdev->dev, "can't map device registers");
+ return PTR_ERR(dev->base);
}
/* Check for RGMII flags */
@@ -266,21 +259,6 @@ static int rgmii_probe(struct platform_device *ofdev)
platform_set_drvdata(ofdev, dev);
return 0;
-
- err_free:
- kfree(dev);
- err_gone:
- return rc;
-}
-
-static void rgmii_remove(struct platform_device *ofdev)
-{
- struct rgmii_instance *dev = platform_get_drvdata(ofdev);
-
- WARN_ON(dev->users != 0);
-
- iounmap(dev->base);
- kfree(dev);
}
static const struct of_device_id rgmii_match[] =
@@ -300,7 +278,6 @@ static struct platform_driver rgmii_driver = {
.of_match_table = rgmii_match,
},
.probe = rgmii_probe,
- .remove_new = rgmii_remove,
};
int __init rgmii_init(void)
diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c
index fa3488258ca2..09f6373ed2f9 100644
--- a/drivers/net/ethernet/ibm/emac/tah.c
+++ b/drivers/net/ethernet/ibm/emac/tah.c
@@ -87,31 +87,24 @@ void *tah_dump_regs(struct platform_device *ofdev, void *buf)
static int tah_probe(struct platform_device *ofdev)
{
- struct device_node *np = ofdev->dev.of_node;
struct tah_instance *dev;
- struct resource regs;
- int rc;
+ int err;
- rc = -ENOMEM;
- dev = kzalloc(sizeof(struct tah_instance), GFP_KERNEL);
- if (dev == NULL)
- goto err_gone;
+ dev = devm_kzalloc(&ofdev->dev, sizeof(struct tah_instance),
+ GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
- mutex_init(&dev->lock);
- dev->ofdev = ofdev;
+ err = devm_mutex_init(&ofdev->dev, &dev->lock);
+ if (err)
+ return err;
- rc = -ENXIO;
- if (of_address_to_resource(np, 0, &regs)) {
- printk(KERN_ERR "%pOF: Can't get registers address\n", np);
- goto err_free;
- }
+ dev->ofdev = ofdev;
- rc = -ENOMEM;
- dev->base = (struct tah_regs __iomem *)ioremap(regs.start,
- sizeof(struct tah_regs));
- if (dev->base == NULL) {
- printk(KERN_ERR "%pOF: Can't map device registers!\n", np);
- goto err_free;
+ dev->base = devm_platform_ioremap_resource(ofdev, 0);
+ if (IS_ERR(dev->base)) {
+ dev_err(&ofdev->dev, "can't map device registers");
+ return PTR_ERR(dev->base);
}
platform_set_drvdata(ofdev, dev);
@@ -123,21 +116,6 @@ static int tah_probe(struct platform_device *ofdev)
wmb();
return 0;
-
- err_free:
- kfree(dev);
- err_gone:
- return rc;
-}
-
-static void tah_remove(struct platform_device *ofdev)
-{
- struct tah_instance *dev = platform_get_drvdata(ofdev);
-
- WARN_ON(dev->users != 0);
-
- iounmap(dev->base);
- kfree(dev);
}
static const struct of_device_id tah_match[] =
@@ -158,7 +136,6 @@ static struct platform_driver tah_driver = {
.of_match_table = tah_match,
},
.probe = tah_probe,
- .remove_new = tah_remove,
};
int __init tah_init(void)
diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c
index 26e86cdee2f6..69ca6065de1c 100644
--- a/drivers/net/ethernet/ibm/emac/zmii.c
+++ b/drivers/net/ethernet/ibm/emac/zmii.c
@@ -232,32 +232,25 @@ void *zmii_dump_regs(struct platform_device *ofdev, void *buf)
static int zmii_probe(struct platform_device *ofdev)
{
- struct device_node *np = ofdev->dev.of_node;
struct zmii_instance *dev;
- struct resource regs;
- int rc;
+ int err;
- rc = -ENOMEM;
- dev = kzalloc(sizeof(struct zmii_instance), GFP_KERNEL);
- if (dev == NULL)
- goto err_gone;
+ dev = devm_kzalloc(&ofdev->dev, sizeof(struct zmii_instance),
+ GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ err = devm_mutex_init(&ofdev->dev, &dev->lock);
+ if (err)
+ return err;
- mutex_init(&dev->lock);
dev->ofdev = ofdev;
dev->mode = PHY_INTERFACE_MODE_NA;
- rc = -ENXIO;
- if (of_address_to_resource(np, 0, &regs)) {
- printk(KERN_ERR "%pOF: Can't get registers address\n", np);
- goto err_free;
- }
-
- rc = -ENOMEM;
- dev->base = (struct zmii_regs __iomem *)ioremap(regs.start,
- sizeof(struct zmii_regs));
- if (dev->base == NULL) {
- printk(KERN_ERR "%pOF: Can't map device registers!\n", np);
- goto err_free;
+ dev->base = devm_platform_ioremap_resource(ofdev, 0);
+ if (IS_ERR(dev->base)) {
+ dev_err(&ofdev->dev, "can't map device registers");
+ return PTR_ERR(dev->base);
}
/* We may need FER value for autodetection later */
@@ -271,21 +264,6 @@ static int zmii_probe(struct platform_device *ofdev)
platform_set_drvdata(ofdev, dev);
return 0;
-
- err_free:
- kfree(dev);
- err_gone:
- return rc;
-}
-
-static void zmii_remove(struct platform_device *ofdev)
-{
- struct zmii_instance *dev = platform_get_drvdata(ofdev);
-
- WARN_ON(dev->users != 0);
-
- iounmap(dev->base);
- kfree(dev);
}
static const struct of_device_id zmii_match[] =
@@ -306,7 +284,6 @@ static struct platform_driver zmii_driver = {
.of_match_table = zmii_match,
},
.probe = zmii_probe,
- .remove_new = zmii_remove,
};
int __init zmii_init(void)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 97425c06e1ed..e95ae0d39948 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -2310,7 +2310,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
tx_buff = &tx_pool->tx_buff[index];
adapter->netdev->stats.tx_packets--;
adapter->netdev->stats.tx_bytes -= tx_buff->skb->len;
- adapter->tx_stats_buffers[queue_num].packets--;
+ adapter->tx_stats_buffers[queue_num].batched_packets--;
adapter->tx_stats_buffers[queue_num].bytes -=
tx_buff->skb->len;
dev_kfree_skb_any(tx_buff->skb);
@@ -2402,7 +2402,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
unsigned int tx_map_failed = 0;
union sub_crq indir_arr[16];
unsigned int tx_dropped = 0;
- unsigned int tx_packets = 0;
+ unsigned int tx_dpackets = 0;
+ unsigned int tx_bpackets = 0;
unsigned int tx_bytes = 0;
dma_addr_t data_dma_addr;
struct netdev_queue *txq;
@@ -2575,6 +2576,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
if (lpar_rc != H_SUCCESS)
goto tx_err;
+ tx_dpackets++;
goto early_exit;
}
@@ -2603,6 +2605,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
goto tx_err;
}
+ tx_bpackets++;
+
early_exit:
if (atomic_add_return(num_entries, &tx_scrq->used)
>= adapter->req_tx_entries_per_subcrq) {
@@ -2610,7 +2614,6 @@ early_exit:
netif_stop_subqueue(netdev, queue_num);
}
- tx_packets++;
tx_bytes += skb->len;
txq_trans_cond_update(txq);
ret = NETDEV_TX_OK;
@@ -2640,10 +2643,11 @@ out:
rcu_read_unlock();
netdev->stats.tx_dropped += tx_dropped;
netdev->stats.tx_bytes += tx_bytes;
- netdev->stats.tx_packets += tx_packets;
+ netdev->stats.tx_packets += tx_bpackets + tx_dpackets;
adapter->tx_send_failed += tx_send_failed;
adapter->tx_map_failed += tx_map_failed;
- adapter->tx_stats_buffers[queue_num].packets += tx_packets;
+ adapter->tx_stats_buffers[queue_num].batched_packets += tx_bpackets;
+ adapter->tx_stats_buffers[queue_num].direct_packets += tx_dpackets;
adapter->tx_stats_buffers[queue_num].bytes += tx_bytes;
adapter->tx_stats_buffers[queue_num].dropped_packets += tx_dropped;
@@ -3804,29 +3808,20 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
if (stringset != ETH_SS_STATS)
return;
- for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++, data += ETH_GSTRING_LEN)
- memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN);
+ for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
+ ethtool_puts(&data, ibmvnic_stats[i].name);
for (i = 0; i < adapter->req_tx_queues; i++) {
- snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i);
- data += ETH_GSTRING_LEN;
-
- snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i);
- data += ETH_GSTRING_LEN;
-
- snprintf(data, ETH_GSTRING_LEN, "tx%d_dropped_packets", i);
- data += ETH_GSTRING_LEN;
+ ethtool_sprintf(&data, "tx%d_batched_packets", i);
+ ethtool_sprintf(&data, "tx%d_direct_packets", i);
+ ethtool_sprintf(&data, "tx%d_bytes", i);
+ ethtool_sprintf(&data, "tx%d_dropped_packets", i);
}
for (i = 0; i < adapter->req_rx_queues; i++) {
- snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i);
- data += ETH_GSTRING_LEN;
-
- snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i);
- data += ETH_GSTRING_LEN;
-
- snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i);
- data += ETH_GSTRING_LEN;
+ ethtool_sprintf(&data, "rx%d_packets", i);
+ ethtool_sprintf(&data, "rx%d_bytes", i);
+ ethtool_sprintf(&data, "rx%d_interrupts", i);
}
}
@@ -3873,7 +3868,9 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
(adapter, ibmvnic_stats[i].offset));
for (j = 0; j < adapter->req_tx_queues; j++) {
- data[i] = adapter->tx_stats_buffers[j].packets;
+ data[i] = adapter->tx_stats_buffers[j].batched_packets;
+ i++;
+ data[i] = adapter->tx_stats_buffers[j].direct_packets;
i++;
data[i] = adapter->tx_stats_buffers[j].bytes;
i++;
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
index 94ac36b1408b..a189038d88df 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.h
+++ b/drivers/net/ethernet/ibm/ibmvnic.h
@@ -213,7 +213,8 @@ struct ibmvnic_statistics {
#define NUM_TX_STATS 3
struct ibmvnic_tx_queue_stats {
- u64 packets;
+ u64 batched_packets;
+ u64 direct_packets;
u64 bytes;
u64 dropped_packets;
};
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 0375c7448a57..20bc40eec487 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -258,6 +258,7 @@ config I40E_DCB
config IAVF
tristate
select LIBIE
+ select NET_SHAPER
config I40EVF
tristate "Intel(R) Ethernet Adaptive Virtual Function support"
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index ab7ae418d294..3f089c3d47b2 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -513,6 +513,8 @@ void e1000_down(struct e1000_adapter *adapter)
*/
netif_carrier_off(netdev);
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_RX, NULL);
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_TX, NULL);
napi_disable(&adapter->napi);
e1000_irq_disable(adapter);
@@ -1392,7 +1394,10 @@ int e1000_open(struct net_device *netdev)
/* From here on the code is the same as e1000_up() */
clear_bit(__E1000_DOWN, &adapter->flags);
+ netif_napi_set_irq(&adapter->napi, adapter->pdev->irq);
napi_enable(&adapter->napi);
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_RX, &adapter->napi);
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_TX, &adapter->napi);
e1000_irq_enable(adapter);
@@ -3504,7 +3509,9 @@ static void e1000_reset_task(struct work_struct *work)
container_of(work, struct e1000_adapter, reset_task);
e_err(drv, "Reset adapter\n");
+ rtnl_lock();
e1000_reinit_locked(adapter);
+ rtnl_unlock();
}
/**
@@ -5069,7 +5076,9 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
usleep_range(10000, 20000);
WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
+ rtnl_lock();
e1000_down(adapter);
+ rtnl_unlock();
}
status = er32(STATUS);
@@ -5230,16 +5239,20 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ rtnl_lock();
netif_device_detach(netdev);
- if (state == pci_channel_io_perm_failure)
+ if (state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
return PCI_ERS_RESULT_DISCONNECT;
+ }
if (netif_running(netdev))
e1000_down(adapter);
if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags))
pci_disable_device(pdev);
+ rtnl_unlock();
/* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index ce227b56cf72..2f9655cf5dd9 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -1205,12 +1205,10 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
if (ret_val)
goto out;
- if (hw->mac.type != e1000_pch_mtp) {
- ret_val = e1000e_force_smbus(hw);
- if (ret_val) {
- e_dbg("Failed to force SMBUS: %d\n", ret_val);
- goto release;
- }
+ ret_val = e1000e_force_smbus(hw);
+ if (ret_val) {
+ e_dbg("Failed to force SMBUS: %d\n", ret_val);
+ goto release;
}
/* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
@@ -1273,13 +1271,6 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
}
release:
- if (hw->mac.type == e1000_pch_mtp) {
- ret_val = e1000e_force_smbus(hw);
- if (ret_val)
- e_dbg("Failed to force SMBUS over MTL system: %d\n",
- ret_val);
- }
-
hw->phy.ops.release(hw);
out:
if (ret_val)
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 07e903346358..286155efcedf 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -2928,11 +2928,8 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
tx_ring->head = adapter->hw.hw_addr + E1000_TDH(0);
tx_ring->tail = adapter->hw.hw_addr + E1000_TDT(0);
- writel(0, tx_ring->head);
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
e1000e_update_tdt_wa(tx_ring, 0);
- else
- writel(0, tx_ring->tail);
/* Set the Tx Interrupt Delay register */
ew32(TIDV, adapter->tx_int_delay);
@@ -3253,11 +3250,8 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
rx_ring->head = adapter->hw.hw_addr + E1000_RDH(0);
rx_ring->tail = adapter->hw.hw_addr + E1000_RDT(0);
- writel(0, rx_ring->head);
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
e1000e_update_rdt_wa(rx_ring, 0);
- else
- writel(0, rx_ring->tail);
/* Enable Receive Checksum Offload for TCP and UDP */
rxcsum = er32(RXCSUM);
@@ -4613,6 +4607,7 @@ int e1000e_open(struct net_device *netdev)
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
int err;
+ int irq;
/* disallow open during test */
if (test_bit(__E1000_TESTING, &adapter->state))
@@ -4676,7 +4671,15 @@ int e1000e_open(struct net_device *netdev)
/* From here on the code is the same as e1000e_up() */
clear_bit(__E1000_DOWN, &adapter->state);
+ if (adapter->int_mode == E1000E_INT_MODE_MSIX)
+ irq = adapter->msix_entries[0].vector;
+ else
+ irq = adapter->pdev->irq;
+
+ netif_napi_set_irq(&adapter->napi, irq);
napi_enable(&adapter->napi);
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_RX, &adapter->napi);
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_TX, &adapter->napi);
e1000_irq_enable(adapter);
@@ -4735,6 +4738,8 @@ int e1000e_close(struct net_device *netdev)
netdev_info(netdev, "NIC Link is Down\n");
}
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_RX, NULL);
+ netif_queue_set_napi(netdev, 0, NETDEV_QUEUE_TYPE_TX, NULL);
napi_disable(&adapter->napi);
e1000e_free_tx_resources(adapter->tx_ring);
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 2089a0e172bf..d4255c2706fa 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -755,6 +755,7 @@ enum i40e_filter_state {
I40E_FILTER_ACTIVE, /* Added to switch by FW */
I40E_FILTER_FAILED, /* Rejected by FW */
I40E_FILTER_REMOVE, /* To be removed */
+ I40E_FILTER_NEW_SYNC, /* New, not sent yet, is in i40e_sync_vsi_filters() */
/* There is no 'removed' state; the filter struct is freed */
};
struct i40e_mac_filter {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index abf624d770e6..208c2f0857b6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -89,6 +89,7 @@ static char *i40e_filter_state_string[] = {
"ACTIVE",
"FAILED",
"REMOVE",
+ "NEW_SYNC",
};
/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index f2506511bbff..bce5b76f1e7a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -5299,7 +5299,7 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
}
flags_complete:
- bitmap_xor(changed_flags, pf->flags, orig_flags, I40E_PF_FLAGS_NBITS);
+ bitmap_xor(changed_flags, new_flags, orig_flags, I40E_PF_FLAGS_NBITS);
if (test_bit(I40E_FLAG_FW_LLDP_DIS, changed_flags))
reset_needed = I40E_PF_RESET_AND_REBUILD_FLAG;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 25295ae370b2..ab5febf83ec3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1255,6 +1255,7 @@ int i40e_count_filters(struct i40e_vsi *vsi)
hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
if (f->state == I40E_FILTER_NEW ||
+ f->state == I40E_FILTER_NEW_SYNC ||
f->state == I40E_FILTER_ACTIVE)
++cnt;
}
@@ -1441,6 +1442,8 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
new->f = add_head;
new->state = add_head->state;
+ if (add_head->state == I40E_FILTER_NEW)
+ add_head->state = I40E_FILTER_NEW_SYNC;
/* Add the new filter to the tmp list */
hlist_add_head(&new->hlist, tmp_add_list);
@@ -1550,6 +1553,8 @@ static int i40e_correct_vf_mac_vlan_filters(struct i40e_vsi *vsi,
return -ENOMEM;
new_mac->f = add_head;
new_mac->state = add_head->state;
+ if (add_head->state == I40E_FILTER_NEW)
+ add_head->state = I40E_FILTER_NEW_SYNC;
/* Add the new filter to the tmp list */
hlist_add_head(&new_mac->hlist, tmp_add_list);
@@ -2437,7 +2442,8 @@ static int
i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
struct i40e_mac_filter *f)
{
- bool enable = f->state == I40E_FILTER_NEW;
+ bool enable = f->state == I40E_FILTER_NEW ||
+ f->state == I40E_FILTER_NEW_SYNC;
struct i40e_hw *hw = &vsi->back->hw;
int aq_ret;
@@ -2611,6 +2617,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
/* Add it to the hash list */
hlist_add_head(&new->hlist, &tmp_add_list);
+ f->state = I40E_FILTER_NEW_SYNC;
}
/* Count the number of active (current and new) VLAN
@@ -2762,7 +2769,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
spin_lock_bh(&vsi->mac_filter_hash_lock);
hlist_for_each_entry_safe(new, h, &tmp_add_list, hlist) {
/* Only update the state if we're still NEW */
- if (new->f->state == I40E_FILTER_NEW)
+ if (new->f->state == I40E_FILTER_NEW ||
+ new->f->state == I40E_FILTER_NEW_SYNC)
new->f->state = new->state;
hlist_del(&new->hlist);
netdev_hw_addr_refcnt(new->f, vsi->netdev, -1);
@@ -13087,12 +13095,13 @@ static int i40e_get_phys_port_id(struct net_device *netdev,
* @addr: the MAC address entry being added
* @vid: VLAN ID
* @flags: instructions from stack about fdb operation
+ * @notified: whether notification was emitted
* @extack: netlink extended ack, unused currently
*/
static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags,
+ u16 flags, bool *notified,
struct netlink_ext_ack *extack)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 48cd1d06761c..532a0a595fe8 100644
--- a/drivers/net/ethernet/intel/iavf/iavf.h
+++ b/drivers/net/ethernet/intel/iavf/iavf.h
@@ -34,6 +34,7 @@
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_mirred.h>
#include <net/tc_act/tc_skbedit.h>
+#include <net/net_shaper.h>
#include "iavf_type.h"
#include <linux/avf/virtchnl.h>
@@ -250,6 +251,9 @@ struct iavf_cloud_filter {
#define IAVF_RESET_WAIT_DETECTED_COUNT 500
#define IAVF_RESET_WAIT_COMPLETE_COUNT 2000
+#define IAVF_MAX_QOS_TC_NUM 8
+#define IAVF_DEFAULT_QUANTA_SIZE 1024
+
/* board specific private data structure */
struct iavf_adapter {
struct workqueue_struct *wq;
@@ -336,6 +340,9 @@ struct iavf_adapter {
#define IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_INSERTION BIT_ULL(36)
#define IAVF_FLAG_AQ_ENABLE_STAG_VLAN_INSERTION BIT_ULL(37)
#define IAVF_FLAG_AQ_DISABLE_STAG_VLAN_INSERTION BIT_ULL(38)
+#define IAVF_FLAG_AQ_CONFIGURE_QUEUES_BW BIT_ULL(39)
+#define IAVF_FLAG_AQ_CFG_QUEUES_QUANTA_SIZE BIT_ULL(40)
+#define IAVF_FLAG_AQ_GET_QOS_CAPS BIT_ULL(41)
/* flags for processing extended capability messages during
* __IAVF_INIT_EXTENDED_CAPS. Each capability exchange requires
@@ -408,6 +415,8 @@ struct iavf_adapter {
VIRTCHNL_VF_OFFLOAD_FDIR_PF)
#define ADV_RSS_SUPPORT(_a) ((_a)->vf_res->vf_cap_flags & \
VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF)
+#define QOS_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
+ VIRTCHNL_VF_OFFLOAD_QOS)
struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */
struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
struct virtchnl_version_info pf_version;
@@ -416,6 +425,7 @@ struct iavf_adapter {
struct virtchnl_vlan_caps vlan_v2_caps;
u16 msg_enable;
struct iavf_eth_stats current_stats;
+ struct virtchnl_qos_cap_list *qos_caps;
struct iavf_vsi vsi;
u32 aq_wait_count;
/* RSS stuff */
@@ -529,22 +539,16 @@ static inline void iavf_change_state(struct iavf_adapter *adapter,
iavf_state_str(adapter->state));
}
-int iavf_up(struct iavf_adapter *adapter);
void iavf_down(struct iavf_adapter *adapter);
int iavf_process_config(struct iavf_adapter *adapter);
int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
void iavf_schedule_aq_request(struct iavf_adapter *adapter, u64 flags);
void iavf_schedule_finish_config(struct iavf_adapter *adapter);
-void iavf_reset(struct iavf_adapter *adapter);
void iavf_set_ethtool_ops(struct net_device *netdev);
-void iavf_update_stats(struct iavf_adapter *adapter);
void iavf_free_all_tx_resources(struct iavf_adapter *adapter);
void iavf_free_all_rx_resources(struct iavf_adapter *adapter);
-void iavf_napi_add_all(struct iavf_adapter *adapter);
-void iavf_napi_del_all(struct iavf_adapter *adapter);
-
int iavf_send_api_ver(struct iavf_adapter *adapter);
int iavf_verify_api_ver(struct iavf_adapter *adapter);
int iavf_send_vf_config_msg(struct iavf_adapter *adapter);
@@ -555,11 +559,9 @@ void iavf_set_queue_vlan_tag_loc(struct iavf_adapter *adapter);
u16 iavf_get_num_vlans_added(struct iavf_adapter *adapter);
void iavf_irq_enable(struct iavf_adapter *adapter, bool flush);
void iavf_configure_queues(struct iavf_adapter *adapter);
-void iavf_deconfigure_queues(struct iavf_adapter *adapter);
void iavf_enable_queues(struct iavf_adapter *adapter);
void iavf_disable_queues(struct iavf_adapter *adapter);
void iavf_map_queues(struct iavf_adapter *adapter);
-int iavf_request_queues(struct iavf_adapter *adapter, int num);
void iavf_add_ether_addrs(struct iavf_adapter *adapter);
void iavf_del_ether_addrs(struct iavf_adapter *adapter);
void iavf_add_vlans(struct iavf_adapter *adapter);
@@ -579,8 +581,9 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
enum virtchnl_ops v_opcode,
enum iavf_status v_retval, u8 *msg, u16 msglen);
int iavf_config_rss(struct iavf_adapter *adapter);
-int iavf_lan_add_device(struct iavf_adapter *adapter);
-int iavf_lan_del_device(struct iavf_adapter *adapter);
+void iavf_cfg_queues_bw(struct iavf_adapter *adapter);
+void iavf_cfg_queues_quanta_size(struct iavf_adapter *adapter);
+void iavf_get_qos_caps(struct iavf_adapter *adapter);
void iavf_enable_channels(struct iavf_adapter *adapter);
void iavf_disable_channels(struct iavf_adapter *adapter);
void iavf_add_cloud_filter(struct iavf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index f782402cd789..12ef160425aa 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -1972,8 +1972,11 @@ static void iavf_finish_config(struct work_struct *work)
adapter = container_of(work, struct iavf_adapter, finish_config);
- /* Always take RTNL first to prevent circular lock dependency */
+ /* Always take RTNL first to prevent circular lock dependency;
+ * The dev->lock is needed to update the queue number
+ */
rtnl_lock();
+ mutex_lock(&adapter->netdev->lock);
mutex_lock(&adapter->crit_lock);
if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
@@ -2017,6 +2020,7 @@ static void iavf_finish_config(struct work_struct *work)
out:
mutex_unlock(&adapter->crit_lock);
+ mutex_unlock(&adapter->netdev->lock);
rtnl_unlock();
}
@@ -2085,6 +2089,21 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
return 0;
}
+ if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_QUEUES_BW) {
+ iavf_cfg_queues_bw(adapter);
+ return 0;
+ }
+
+ if (adapter->aq_required & IAVF_FLAG_AQ_GET_QOS_CAPS) {
+ iavf_get_qos_caps(adapter);
+ return 0;
+ }
+
+ if (adapter->aq_required & IAVF_FLAG_AQ_CFG_QUEUES_QUANTA_SIZE) {
+ iavf_cfg_queues_quanta_size(adapter);
+ return 0;
+ }
+
if (adapter->aq_required & IAVF_FLAG_AQ_CONFIGURE_QUEUES) {
iavf_configure_queues(adapter);
return 0;
@@ -2670,6 +2689,9 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
/* request initial VLAN offload settings */
iavf_set_vlan_offload_features(adapter, 0, netdev->features);
+ if (QOS_ALLOWED(adapter))
+ adapter->aq_required |= IAVF_FLAG_AQ_GET_QOS_CAPS;
+
iavf_schedule_finish_config(adapter);
return;
@@ -2919,6 +2941,30 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
}
/**
+ * iavf_reconfig_qs_bw - Call-back task to handle hardware reset
+ * @adapter: board private structure
+ *
+ * After a reset, the shaper parameters of queues need to be replayed again.
+ * Since the net_shaper object inside TX rings persists across reset,
+ * set the update flag for all queues so that the virtchnl message is triggered
+ * for all queues.
+ **/
+static void iavf_reconfig_qs_bw(struct iavf_adapter *adapter)
+{
+ int i, num = 0;
+
+ for (i = 0; i < adapter->num_active_queues; i++)
+ if (adapter->tx_rings[i].q_shaper.bw_min ||
+ adapter->tx_rings[i].q_shaper.bw_max) {
+ adapter->tx_rings[i].q_shaper_update = true;
+ num++;
+ }
+
+ if (num)
+ adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_QUEUES_BW;
+}
+
+/**
* iavf_reset_task - Call-back task to handle hardware reset
* @work: pointer to work_struct
*
@@ -2944,10 +2990,12 @@ static void iavf_reset_task(struct work_struct *work)
/* When device is being removed it doesn't make sense to run the reset
* task, just return in such a case.
*/
+ mutex_lock(&netdev->lock);
if (!mutex_trylock(&adapter->crit_lock)) {
if (adapter->state != __IAVF_REMOVE)
queue_work(adapter->wq, &adapter->reset_task);
+ mutex_unlock(&netdev->lock);
return;
}
@@ -2995,6 +3043,7 @@ static void iavf_reset_task(struct work_struct *work)
reg_val);
iavf_disable_vf(adapter);
mutex_unlock(&adapter->crit_lock);
+ mutex_unlock(&netdev->lock);
return; /* Do not attempt to reinit. It's dead, Jim. */
}
@@ -3124,6 +3173,8 @@ continue_reset:
iavf_up_complete(adapter);
iavf_irq_enable(adapter, true);
+
+ iavf_reconfig_qs_bw(adapter);
} else {
iavf_change_state(adapter, __IAVF_DOWN);
wake_up(&adapter->down_waitqueue);
@@ -3133,6 +3184,7 @@ continue_reset:
wake_up(&adapter->reset_waitqueue);
mutex_unlock(&adapter->crit_lock);
+ mutex_unlock(&netdev->lock);
return;
reset_err:
@@ -3143,6 +3195,7 @@ reset_err:
iavf_disable_vf(adapter);
mutex_unlock(&adapter->crit_lock);
+ mutex_unlock(&netdev->lock);
dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
}
@@ -3614,8 +3667,10 @@ exit:
if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
return 0;
+ mutex_lock(&netdev->lock);
netif_set_real_num_rx_queues(netdev, total_qps);
netif_set_real_num_tx_queues(netdev, total_qps);
+ mutex_unlock(&netdev->lock);
return ret;
}
@@ -4893,6 +4948,98 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
return iavf_fix_strip_features(adapter, features);
}
+static int
+iavf_verify_shaper(struct net_shaper_binding *binding,
+ const struct net_shaper *shaper,
+ struct netlink_ext_ack *extack)
+{
+ struct iavf_adapter *adapter = netdev_priv(binding->netdev);
+ u64 vf_max;
+
+ if (shaper->handle.scope == NET_SHAPER_SCOPE_QUEUE) {
+ vf_max = adapter->qos_caps->cap[0].shaper.peak;
+ if (vf_max && shaper->bw_max > vf_max) {
+ NL_SET_ERR_MSG_FMT(extack, "Max rate (%llu) of queue %d can't exceed max TX rate of VF (%llu kbps)",
+ shaper->bw_max, shaper->handle.id,
+ vf_max);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int
+iavf_shaper_set(struct net_shaper_binding *binding,
+ const struct net_shaper *shaper,
+ struct netlink_ext_ack *extack)
+{
+ struct iavf_adapter *adapter = netdev_priv(binding->netdev);
+ const struct net_shaper_handle *handle = &shaper->handle;
+ struct iavf_ring *tx_ring;
+ int ret = 0;
+
+ mutex_lock(&adapter->crit_lock);
+ if (handle->id >= adapter->num_active_queues)
+ goto unlock;
+
+ ret = iavf_verify_shaper(binding, shaper, extack);
+ if (ret)
+ goto unlock;
+
+ tx_ring = &adapter->tx_rings[handle->id];
+
+ tx_ring->q_shaper.bw_min = div_u64(shaper->bw_min, 1000);
+ tx_ring->q_shaper.bw_max = div_u64(shaper->bw_max, 1000);
+ tx_ring->q_shaper_update = true;
+
+ adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_QUEUES_BW;
+
+unlock:
+ mutex_unlock(&adapter->crit_lock);
+ return ret;
+}
+
+static int iavf_shaper_del(struct net_shaper_binding *binding,
+ const struct net_shaper_handle *handle,
+ struct netlink_ext_ack *extack)
+{
+ struct iavf_adapter *adapter = netdev_priv(binding->netdev);
+ struct iavf_ring *tx_ring;
+
+ mutex_lock(&adapter->crit_lock);
+ if (handle->id >= adapter->num_active_queues)
+ goto unlock;
+
+ tx_ring = &adapter->tx_rings[handle->id];
+ tx_ring->q_shaper.bw_min = 0;
+ tx_ring->q_shaper.bw_max = 0;
+ tx_ring->q_shaper_update = true;
+
+ adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_QUEUES_BW;
+
+unlock:
+ mutex_unlock(&adapter->crit_lock);
+ return 0;
+}
+
+static void iavf_shaper_cap(struct net_shaper_binding *binding,
+ enum net_shaper_scope scope,
+ unsigned long *flags)
+{
+ if (scope != NET_SHAPER_SCOPE_QUEUE)
+ return;
+
+ *flags = BIT(NET_SHAPER_A_CAPS_SUPPORT_BW_MIN) |
+ BIT(NET_SHAPER_A_CAPS_SUPPORT_BW_MAX) |
+ BIT(NET_SHAPER_A_CAPS_SUPPORT_METRIC_BPS);
+}
+
+static const struct net_shaper_ops iavf_shaper_ops = {
+ .set = iavf_shaper_set,
+ .delete = iavf_shaper_del,
+ .capabilities = iavf_shaper_cap,
+};
+
static const struct net_device_ops iavf_netdev_ops = {
.ndo_open = iavf_open,
.ndo_stop = iavf_close,
@@ -4908,6 +5055,7 @@ static const struct net_device_ops iavf_netdev_ops = {
.ndo_fix_features = iavf_fix_features,
.ndo_set_features = iavf_set_features,
.ndo_setup_tc = iavf_setup_tc,
+ .net_shaper_ops = &iavf_shaper_ops,
};
/**
@@ -5054,7 +5202,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct net_device *netdev;
struct iavf_adapter *adapter = NULL;
struct iavf_hw *hw = NULL;
- int err;
+ int err, len;
err = pci_enable_device(pdev);
if (err)
@@ -5122,6 +5270,13 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->bus.func = PCI_FUNC(pdev->devfn);
hw->bus.bus_id = pdev->bus->number;
+ len = struct_size(adapter->qos_caps, cap, IAVF_MAX_QOS_TC_NUM);
+ adapter->qos_caps = kzalloc(len, GFP_KERNEL);
+ if (!adapter->qos_caps) {
+ err = -ENOMEM;
+ goto err_alloc_qos_cap;
+ }
+
/* set up the locks for the AQ, do this only once in probe
* and destroy them only once in remove
*/
@@ -5160,6 +5315,8 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Initialization goes on in the work. Do not add more of it below. */
return 0;
+err_alloc_qos_cap:
+ iounmap(hw->hw_addr);
err_ioremap:
destroy_workqueue(adapter->wq);
err_alloc_wq:
diff --git a/drivers/net/ethernet/intel/iavf/iavf_prototype.h b/drivers/net/ethernet/intel/iavf/iavf_prototype.h
index 48c3901381b4..cac9d1a35a52 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_prototype.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_prototype.h
@@ -18,7 +18,6 @@
/* adminq functions */
enum iavf_status iavf_init_adminq(struct iavf_hw *hw);
enum iavf_status iavf_shutdown_adminq(struct iavf_hw *hw);
-void iavf_adminq_init_ring_data(struct iavf_hw *hw);
enum iavf_status iavf_clean_arq_element(struct iavf_hw *hw,
struct iavf_arq_event_info *e,
u16 *events_pending);
@@ -33,8 +32,6 @@ bool iavf_asq_done(struct iavf_hw *hw);
void iavf_debug_aq(struct iavf_hw *hw, enum iavf_debug_mask mask,
void *desc, void *buffer, u16 buf_len);
-void iavf_idle_aq(struct iavf_hw *hw);
-void iavf_resume_aq(struct iavf_hw *hw);
bool iavf_check_asq_alive(struct iavf_hw *hw);
enum iavf_status iavf_aq_queue_shutdown(struct iavf_hw *hw, bool unloading);
const char *iavf_aq_str(struct iavf_hw *hw, enum iavf_admin_queue_err aq_err);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.h b/drivers/net/ethernet/intel/iavf/iavf_txrx.h
index d7b5587aeb8e..f97c702c0802 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.h
@@ -296,6 +296,8 @@ struct iavf_ring {
*/
u32 rx_buf_len;
+ struct net_shaper q_shaper;
+ bool q_shaper_update;
} ____cacheline_internodealigned_in_smp;
#define IAVF_ITR_ADAPTIVE_MIN_INC 0x0002
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index 7e810b65380c..15d388b431c5 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -151,7 +151,8 @@ int iavf_send_vf_config_msg(struct iavf_adapter *adapter)
VIRTCHNL_VF_OFFLOAD_USO |
VIRTCHNL_VF_OFFLOAD_FDIR_PF |
VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF |
- VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
+ VIRTCHNL_VF_CAP_ADV_LINK_SPEED |
+ VIRTCHNL_VF_OFFLOAD_QOS;
adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
adapter->aq_required &= ~IAVF_FLAG_AQ_GET_CONFIG;
@@ -1508,6 +1509,130 @@ iavf_set_adapter_link_speed_from_vpe(struct iavf_adapter *adapter,
}
/**
+ * iavf_get_qos_caps - get qos caps support
+ * @adapter: iavf adapter struct instance
+ *
+ * This function requests PF for Supported QoS Caps.
+ */
+void iavf_get_qos_caps(struct iavf_adapter *adapter)
+{
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev,
+ "Cannot get qos caps, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ adapter->current_op = VIRTCHNL_OP_GET_QOS_CAPS;
+ adapter->aq_required &= ~IAVF_FLAG_AQ_GET_QOS_CAPS;
+ iavf_send_pf_msg(adapter, VIRTCHNL_OP_GET_QOS_CAPS, NULL, 0);
+}
+
+/**
+ * iavf_set_quanta_size - set quanta size of queue chunk
+ * @adapter: iavf adapter struct instance
+ * @quanta_size: quanta size in bytes
+ * @queue_index: starting index of queue chunk
+ * @num_queues: number of queues in the queue chunk
+ *
+ * This function requests PF to set quanta size of queue chunk
+ * starting at queue_index.
+ */
+static void
+iavf_set_quanta_size(struct iavf_adapter *adapter, u16 quanta_size,
+ u16 queue_index, u16 num_queues)
+{
+ struct virtchnl_quanta_cfg quanta_cfg;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev,
+ "Cannot set queue quanta size, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ adapter->current_op = VIRTCHNL_OP_CONFIG_QUANTA;
+ quanta_cfg.quanta_size = quanta_size;
+ quanta_cfg.queue_select.type = VIRTCHNL_QUEUE_TYPE_TX;
+ quanta_cfg.queue_select.start_queue_id = queue_index;
+ quanta_cfg.queue_select.num_queues = num_queues;
+ adapter->aq_required &= ~IAVF_FLAG_AQ_CFG_QUEUES_QUANTA_SIZE;
+ iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_QUANTA,
+ (u8 *)&quanta_cfg, sizeof(quanta_cfg));
+}
+
+/**
+ * iavf_cfg_queues_quanta_size - configure quanta size of queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF configure quanta size of allocated queues.
+ **/
+void iavf_cfg_queues_quanta_size(struct iavf_adapter *adapter)
+{
+ int quanta_size = IAVF_DEFAULT_QUANTA_SIZE;
+
+ /* Set Queue Quanta Size to default */
+ iavf_set_quanta_size(adapter, quanta_size, 0,
+ adapter->num_active_queues);
+}
+
+/**
+ * iavf_cfg_queues_bw - configure bandwidth of allocated queues
+ * @adapter: iavf adapter structure instance
+ *
+ * This function requests PF to configure queue bandwidth of allocated queues
+ */
+void iavf_cfg_queues_bw(struct iavf_adapter *adapter)
+{
+ struct virtchnl_queues_bw_cfg *qs_bw_cfg;
+ struct net_shaper *q_shaper;
+ int qs_to_update = 0;
+ int i, inx = 0;
+ size_t len;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev,
+ "Cannot set tc queue bw, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ if (adapter->tx_rings[i].q_shaper_update)
+ qs_to_update++;
+ }
+ len = struct_size(qs_bw_cfg, cfg, qs_to_update);
+ qs_bw_cfg = kzalloc(len, GFP_KERNEL);
+ if (!qs_bw_cfg)
+ return;
+
+ qs_bw_cfg->vsi_id = adapter->vsi.id;
+ qs_bw_cfg->num_queues = qs_to_update;
+
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ struct iavf_ring *tx_ring = &adapter->tx_rings[i];
+
+ q_shaper = &tx_ring->q_shaper;
+ if (tx_ring->q_shaper_update) {
+ qs_bw_cfg->cfg[inx].queue_id = i;
+ qs_bw_cfg->cfg[inx].shaper.peak = q_shaper->bw_max;
+ qs_bw_cfg->cfg[inx].shaper.committed = q_shaper->bw_min;
+ qs_bw_cfg->cfg[inx].tc = 0;
+ inx++;
+ }
+ }
+
+ adapter->current_op = VIRTCHNL_OP_CONFIG_QUEUE_BW;
+ adapter->aq_required &= ~IAVF_FLAG_AQ_CONFIGURE_QUEUES_BW;
+ iavf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_QUEUE_BW,
+ (u8 *)qs_bw_cfg, len);
+ kfree(qs_bw_cfg);
+}
+
+/**
* iavf_enable_channels
* @adapter: adapter structure
*
@@ -2227,6 +2352,18 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
break;
+ case VIRTCHNL_OP_GET_QOS_CAPS:
+ dev_warn(&adapter->pdev->dev, "Failed to Get Qos CAPs, error %s\n",
+ iavf_stat_str(&adapter->hw, v_retval));
+ break;
+ case VIRTCHNL_OP_CONFIG_QUANTA:
+ dev_warn(&adapter->pdev->dev, "Failed to Config Quanta, error %s\n",
+ iavf_stat_str(&adapter->hw, v_retval));
+ break;
+ case VIRTCHNL_OP_CONFIG_QUEUE_BW:
+ dev_warn(&adapter->pdev->dev, "Failed to Config Queue BW, error %s\n",
+ iavf_stat_str(&adapter->hw, v_retval));
+ break;
default:
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
v_retval, iavf_stat_str(&adapter->hw, v_retval),
@@ -2569,6 +2706,24 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
if (!v_retval)
iavf_netdev_features_vlan_strip_set(netdev, false);
break;
+ case VIRTCHNL_OP_GET_QOS_CAPS: {
+ u16 len = struct_size(adapter->qos_caps, cap,
+ IAVF_MAX_QOS_TC_NUM);
+
+ memcpy(adapter->qos_caps, msg, min(msglen, len));
+
+ adapter->aq_required |= IAVF_FLAG_AQ_CFG_QUEUES_QUANTA_SIZE;
+ }
+ break;
+ case VIRTCHNL_OP_CONFIG_QUANTA:
+ break;
+ case VIRTCHNL_OP_CONFIG_QUEUE_BW: {
+ int i;
+ /* shaper configuration is successful for all queues */
+ for (i = 0; i < adapter->num_active_queues; i++)
+ adapter->tx_rings[i].q_shaper_update = false;
+ }
+ break;
default:
if (adapter->current_op && (v_opcode != adapter->current_op))
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index d6f80da30dec..2f5d6f974185 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -181,11 +181,9 @@
#define ice_for_each_chnl_tc(i) \
for ((i) = ICE_CHNL_START_TC; (i) < ICE_CHNL_MAX_TC; (i)++)
-#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_UCAST_RX)
+#define ICE_UCAST_PROMISC_BITS ICE_PROMISC_UCAST_RX
-#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \
- ICE_PROMISC_UCAST_RX | \
- ICE_PROMISC_VLAN_TX | \
+#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_RX | \
ICE_PROMISC_VLAN_RX)
#define ICE_MCAST_PROMISC_BITS (ICE_PROMISC_MCAST_TX | ICE_PROMISC_MCAST_RX)
@@ -207,6 +205,7 @@ enum ice_feature {
ICE_F_GNSS,
ICE_F_ROCE_LAG,
ICE_F_SRIOV_LAG,
+ ICE_F_MBX_LIMIT,
ICE_F_MAX
};
@@ -371,9 +370,6 @@ struct ice_vsi {
spinlock_t arfs_lock; /* protects aRFS hash table and filter state */
atomic_t *arfs_last_fltr_id;
- u16 max_frame;
- u16 rx_buf_len;
-
struct ice_aqc_vsi_props info; /* VSI properties */
struct ice_vsi_vlan_info vlan_info; /* vlan config to be restored */
@@ -669,6 +665,8 @@ struct ice_pf {
struct ice_agg_node vf_agg_node[ICE_MAX_VF_AGG_NODES];
struct ice_dplls dplls;
struct device *hwmon_dev;
+
+ u8 num_quanta_prof_used;
};
extern struct workqueue_struct *ice_lag_wq;
@@ -1047,5 +1045,10 @@ static inline void ice_clear_rdma_cap(struct ice_pf *pf)
clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
}
+static inline enum ice_phy_model ice_get_phy_model(const struct ice_hw *hw)
+{
+ return hw->ptp.phy_model;
+}
+
extern const struct xdp_metadata_ops ice_xdp_md_ops;
#endif /* _ICE_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c
index ad84d8ad49a6..01a08cfd0090 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.c
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.c
@@ -9,12 +9,14 @@
#include <linux/spinlock.h>
#include <linux/xarray.h>
#include "ice_adapter.h"
+#include "ice.h"
static DEFINE_XARRAY(ice_adapters);
static DEFINE_MUTEX(ice_adapters_mutex);
/* PCI bus number is 8 bits. Slot is 5 bits. Domain can have the rest. */
#define INDEX_FIELD_DOMAIN GENMASK(BITS_PER_LONG - 1, 13)
+#define INDEX_FIELD_DEV GENMASK(31, 16)
#define INDEX_FIELD_BUS GENMASK(12, 5)
#define INDEX_FIELD_SLOT GENMASK(4, 0)
@@ -24,9 +26,17 @@ static unsigned long ice_adapter_index(const struct pci_dev *pdev)
WARN_ON(domain > FIELD_MAX(INDEX_FIELD_DOMAIN));
- return FIELD_PREP(INDEX_FIELD_DOMAIN, domain) |
- FIELD_PREP(INDEX_FIELD_BUS, pdev->bus->number) |
- FIELD_PREP(INDEX_FIELD_SLOT, PCI_SLOT(pdev->devfn));
+ switch (pdev->device) {
+ case ICE_DEV_ID_E825C_BACKPLANE:
+ case ICE_DEV_ID_E825C_QSFP:
+ case ICE_DEV_ID_E825C_SFP:
+ case ICE_DEV_ID_E825C_SGMII:
+ return FIELD_PREP(INDEX_FIELD_DEV, pdev->device);
+ default:
+ return FIELD_PREP(INDEX_FIELD_DOMAIN, domain) |
+ FIELD_PREP(INDEX_FIELD_BUS, pdev->bus->number) |
+ FIELD_PREP(INDEX_FIELD_SLOT, PCI_SLOT(pdev->devfn));
+ }
}
static struct ice_adapter *ice_adapter_new(void)
@@ -40,11 +50,17 @@ static struct ice_adapter *ice_adapter_new(void)
spin_lock_init(&adapter->ptp_gltsyn_time_lock);
refcount_set(&adapter->refcount, 1);
+ mutex_init(&adapter->ports.lock);
+ INIT_LIST_HEAD(&adapter->ports.ports);
+
return adapter;
}
static void ice_adapter_free(struct ice_adapter *adapter)
{
+ WARN_ON(!list_empty(&adapter->ports.ports));
+ mutex_destroy(&adapter->ports.lock);
+
kfree(adapter);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h
index 9d11014ec02f..e233225848b3 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.h
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.h
@@ -4,22 +4,42 @@
#ifndef _ICE_ADAPTER_H_
#define _ICE_ADAPTER_H_
+#include <linux/types.h>
#include <linux/spinlock_types.h>
#include <linux/refcount_types.h>
struct pci_dev;
+struct ice_pf;
+
+/**
+ * struct ice_port_list - data used to store the list of adapter ports
+ *
+ * This structure contains data used to maintain a list of adapter ports
+ *
+ * @ports: list of ports
+ * @lock: protect access to the ports list
+ */
+struct ice_port_list {
+ struct list_head ports;
+ /* To synchronize the ports list operations */
+ struct mutex lock;
+};
/**
* struct ice_adapter - PCI adapter resources shared across PFs
* @ptp_gltsyn_time_lock: Spinlock protecting access to the GLTSYN_TIME
* register of the PTP clock.
* @refcount: Reference count. struct ice_pf objects hold the references.
+ * @ctrl_pf: Control PF of the adapter
+ * @ports: Ports list
*/
struct ice_adapter {
+ refcount_t refcount;
/* For access to the GLTSYN_TIME register */
spinlock_t ptp_gltsyn_time_lock;
- refcount_t refcount;
+ struct ice_pf *ctrl_pf;
+ struct ice_port_list ports;
};
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev);
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 0be1a98d7cc1..1489a8ceec51 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -1492,6 +1492,23 @@ struct ice_aqc_dnl_equa_param {
#define ICE_AQC_RX_EQU_BFLF (0x13 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_BFHF (0x14 << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_RX_EQU_DRATE (0x15 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_CTLE_GAINHF (0x20 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_CTLE_GAINLF (0x21 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_CTLE_GAINDC (0x22 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_CTLE_BW (0x23 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_GAIN (0x30 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_GAIN2 (0x31 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_2 (0x32 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_3 (0x33 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_4 (0x34 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_5 (0x35 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_6 (0x36 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_7 (0x37 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_8 (0x38 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_9 (0x39 << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_10 (0x3A << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_11 (0x3B << ICE_AQC_RX_EQU_SHIFT)
+#define ICE_AQC_RX_EQU_DFE_12 (0x3C << ICE_AQC_RX_EQU_SHIFT)
#define ICE_AQC_TX_EQU_PRE1 0x0
#define ICE_AQC_TX_EQU_PRE3 0x3
#define ICE_AQC_TX_EQU_ATTEN 0x4
@@ -1742,6 +1759,15 @@ struct ice_aqc_nvm {
};
#define ICE_AQC_NVM_START_POINT 0
+#define ICE_AQC_NVM_SECTOR_UNIT 4096
+#define ICE_AQC_NVM_SDP_AC_PTR_OFFSET 0xD8
+#define ICE_AQC_NVM_SDP_AC_PTR_M GENMASK(14, 0)
+#define ICE_AQC_NVM_SDP_AC_PTR_INVAL 0x7FFF
+#define ICE_AQC_NVM_SDP_AC_PTR_TYPE_M BIT(15)
+#define ICE_AQC_NVM_SDP_AC_SDP_NUM_M GENMASK(2, 0)
+#define ICE_AQC_NVM_SDP_AC_DIR_M BIT(3)
+#define ICE_AQC_NVM_SDP_AC_PIN_M GENMASK(15, 6)
+#define ICE_AQC_NVM_SDP_AC_MAX_SIZE 7
#define ICE_AQC_NVM_TX_TOPO_MOD_ID 0x14B
diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
index 4a9a6899fc45..82a9cd4ec7ae 100644
--- a/drivers/net/ethernet/intel/ice/ice_base.c
+++ b/drivers/net/ethernet/intel/ice/ice_base.c
@@ -156,7 +156,8 @@ skip_alloc:
* handler here (i.e. resume, reset/rebuild, etc.)
*/
if (vsi->netdev)
- netif_napi_add(vsi->netdev, &q_vector->napi, ice_napi_poll);
+ netif_napi_add_config(vsi->netdev, &q_vector->napi,
+ ice_napi_poll, v_idx);
out:
/* tie q_vector and VSI together */
@@ -347,6 +348,8 @@ ice_setup_tx_ctx(struct ice_tx_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf
break;
}
+ tlan_ctx->quanta_prof_idx = ring->quanta_prof_id;
+
tlan_ctx->tso_ena = ICE_TX_LEGACY;
tlan_ctx->tso_qnum = pf_q;
@@ -445,7 +448,7 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
/* Max packet size for this queue - must not be set to a larger value
* than 5 x DBUF
*/
- rlan_ctx.rxmax = min_t(u32, vsi->max_frame,
+ rlan_ctx.rxmax = min_t(u32, ring->max_frame,
ICE_MAX_CHAINED_RX_BUFS * ring->rx_buf_len);
/* Rx queue threshold in units of 64 */
@@ -541,8 +544,6 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
u32 num_bufs = ICE_RX_DESC_UNUSED(ring);
int err;
- ring->rx_buf_len = ring->vsi->rx_buf_len;
-
if (ring->vsi->type == ICE_VSI_PF || ring->vsi->type == ICE_VSI_SF) {
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
@@ -641,21 +642,25 @@ int ice_vsi_cfg_single_rxq(struct ice_vsi *vsi, u16 q_idx)
/**
* ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
* @vsi: VSI
+ * @ring: Rx ring to configure
+ *
+ * Determine the maximum frame size and Rx buffer length to use for a PF VSI.
+ * Set these in the associated Rx ring structure.
*/
-static void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
+static void ice_vsi_cfg_frame_size(struct ice_vsi *vsi, struct ice_rx_ring *ring)
{
if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
- vsi->max_frame = ICE_MAX_FRAME_LEGACY_RX;
- vsi->rx_buf_len = ICE_RXBUF_1664;
+ ring->max_frame = ICE_MAX_FRAME_LEGACY_RX;
+ ring->rx_buf_len = ICE_RXBUF_1664;
#if (PAGE_SIZE < 8192)
} else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
(vsi->netdev->mtu <= ETH_DATA_LEN)) {
- vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
- vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
+ ring->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
+ ring->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
#endif
} else {
- vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
- vsi->rx_buf_len = ICE_RXBUF_3072;
+ ring->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
+ ring->rx_buf_len = ICE_RXBUF_3072;
}
}
@@ -670,15 +675,15 @@ int ice_vsi_cfg_rxqs(struct ice_vsi *vsi)
{
u16 i;
- if (vsi->type == ICE_VSI_VF)
- goto setup_rings;
-
- ice_vsi_cfg_frame_size(vsi);
-setup_rings:
/* set up individual rings */
ice_for_each_rxq(vsi, i) {
- int err = ice_vsi_cfg_rxq(vsi->rx_rings[i]);
+ struct ice_rx_ring *ring = vsi->rx_rings[i];
+ int err;
+
+ if (vsi->type != ICE_VSI_VF)
+ ice_vsi_cfg_frame_size(vsi, ring);
+ err = ice_vsi_cfg_rxq(ring);
if (err)
return err;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 009716a12a26..b22e71dc59d4 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -2437,6 +2437,25 @@ ice_parse_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
}
/**
+ * ice_func_id_to_logical_id - map from function id to logical pf id
+ * @active_function_bitmap: active function bitmap
+ * @pf_id: function number of device
+ *
+ * Return: logical PF ID.
+ */
+static int ice_func_id_to_logical_id(u32 active_function_bitmap, u8 pf_id)
+{
+ u8 logical_id = 0;
+ u8 i;
+
+ for (i = 0; i < pf_id; i++)
+ if (active_function_bitmap & BIT(i))
+ logical_id++;
+
+ return logical_id;
+}
+
+/**
* ice_parse_valid_functions_cap - Parse ICE_AQC_CAPS_VALID_FUNCTIONS caps
* @hw: pointer to the HW struct
* @dev_p: pointer to device capabilities structure
@@ -2453,6 +2472,8 @@ ice_parse_valid_functions_cap(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
dev_p->num_funcs = hweight32(number);
ice_debug(hw, ICE_DBG_INIT, "dev caps: num_funcs = %d\n",
dev_p->num_funcs);
+
+ hw->logical_pf_id = ice_func_id_to_logical_id(number, hw->pf_id);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.c b/drivers/net/ethernet/intel/ice/ice_ddp.c
index 272fd823a825..03988be03729 100644
--- a/drivers/net/ethernet/intel/ice/ice_ddp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ddp.c
@@ -1211,6 +1211,131 @@ ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
}
/**
+ * ice_is_buffer_metadata - determine if package buffer is a metadata buffer
+ * @buf: pointer to buffer header
+ * Return: whether given @buf is a metadata one.
+ */
+static bool ice_is_buffer_metadata(struct ice_buf_hdr *buf)
+{
+ return le32_to_cpu(buf->section_entry[0].type) & ICE_METADATA_BUF;
+}
+
+/**
+ * struct ice_ddp_send_ctx - sending context of current DDP segment
+ * @hw: pointer to the hardware struct
+ *
+ * Keeps current sending state (header, error) for the purpose of proper "last"
+ * bit setting in ice_aq_download_pkg(). Use via calls to ice_ddp_send_hunk().
+ */
+struct ice_ddp_send_ctx {
+ struct ice_hw *hw;
+/* private: only for ice_ddp_send_hunk() */
+ struct ice_buf_hdr *hdr;
+ int err;
+};
+
+static void ice_ddp_send_ctx_set_err(struct ice_ddp_send_ctx *ctx, int err)
+{
+ ctx->err = err;
+}
+
+/**
+ * ice_ddp_send_hunk - send one hunk of data to FW
+ * @ctx: current segment sending context
+ * @hunk: next hunk to send, size is always ICE_PKG_BUF_SIZE
+ *
+ * Send the next hunk of data to FW, retrying if needed.
+ *
+ * Notice: must be called once more with a NULL @hunk to finish up; such call
+ * will set up the "last" bit of an AQ request. After such call @ctx.hdr is
+ * cleared, @hw is still valid.
+ *
+ * Return: %ICE_DDP_PKG_SUCCESS if there were no problems; a sticky @err
+ * otherwise.
+ */
+static enum ice_ddp_state ice_ddp_send_hunk(struct ice_ddp_send_ctx *ctx,
+ struct ice_buf_hdr *hunk)
+{
+ struct ice_buf_hdr *prev_hunk = ctx->hdr;
+ struct ice_hw *hw = ctx->hw;
+ bool prev_was_last = !hunk;
+ enum ice_aq_err aq_err;
+ u32 offset, info;
+ int attempt, err;
+
+ if (ctx->err)
+ return ctx->err;
+
+ ctx->hdr = hunk;
+ if (!prev_hunk)
+ return ICE_DDP_PKG_SUCCESS; /* no problem so far */
+
+ for (attempt = 0; attempt < 5; attempt++) {
+ if (attempt)
+ msleep(20);
+
+ err = ice_aq_download_pkg(hw, prev_hunk, ICE_PKG_BUF_SIZE,
+ prev_was_last, &offset, &info, NULL);
+
+ aq_err = hw->adminq.sq_last_status;
+ if (aq_err != ICE_AQ_RC_ENOSEC && aq_err != ICE_AQ_RC_EBADSIG)
+ break;
+ }
+
+ if (err) {
+ ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n",
+ err, offset, info);
+ ctx->err = ice_map_aq_err_to_ddp_state(aq_err);
+ } else if (attempt) {
+ dev_dbg(ice_hw_to_dev(hw),
+ "ice_aq_download_pkg number of retries: %d\n", attempt);
+ }
+
+ return ctx->err;
+}
+
+/**
+ * ice_dwnld_cfg_bufs_no_lock
+ * @ctx: context of the current buffers section to send
+ * @bufs: pointer to an array of buffers
+ * @start: buffer index of first buffer to download
+ * @count: the number of buffers to download
+ *
+ * Downloads package configuration buffers to the firmware. Metadata buffers
+ * are skipped, and the first metadata buffer found indicates that the rest
+ * of the buffers are all metadata buffers.
+ */
+static enum ice_ddp_state
+ice_dwnld_cfg_bufs_no_lock(struct ice_ddp_send_ctx *ctx, struct ice_buf *bufs,
+ u32 start, u32 count)
+{
+ struct ice_buf_hdr *bh;
+ enum ice_ddp_state err;
+
+ if (!bufs || !count) {
+ ice_ddp_send_ctx_set_err(ctx, ICE_DDP_PKG_ERR);
+ return ICE_DDP_PKG_ERR;
+ }
+
+ bufs += start;
+
+ for (int i = 0; i < count; i++, bufs++) {
+ bh = (struct ice_buf_hdr *)bufs;
+ /* Metadata buffers should not be sent to FW,
+ * their presence means "we are done here".
+ */
+ if (ice_is_buffer_metadata(bh))
+ break;
+
+ err = ice_ddp_send_hunk(ctx, bh);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/**
* ice_get_pkg_seg_by_idx
* @pkg_hdr: pointer to the package header to be searched
* @idx: index of segment
@@ -1270,136 +1395,20 @@ ice_is_signing_seg_type_at_idx(struct ice_pkg_hdr *pkg_hdr, u32 idx,
}
/**
- * ice_is_buffer_metadata - determine if package buffer is a metadata buffer
- * @buf: pointer to buffer header
- */
-static bool ice_is_buffer_metadata(struct ice_buf_hdr *buf)
-{
- if (le32_to_cpu(buf->section_entry[0].type) & ICE_METADATA_BUF)
- return true;
-
- return false;
-}
-
-/**
- * ice_is_last_download_buffer
- * @buf: pointer to current buffer header
- * @idx: index of the buffer in the current sequence
- * @count: the buffer count in the current sequence
- *
- * Note: this routine should only be called if the buffer is not the last buffer
- */
-static bool
-ice_is_last_download_buffer(struct ice_buf_hdr *buf, u32 idx, u32 count)
-{
- struct ice_buf *next_buf;
-
- if ((idx + 1) == count)
- return true;
-
- /* A set metadata flag in the next buffer will signal that the current
- * buffer will be the last buffer downloaded
- */
- next_buf = ((struct ice_buf *)buf) + 1;
-
- return ice_is_buffer_metadata((struct ice_buf_hdr *)next_buf);
-}
-
-/**
- * ice_dwnld_cfg_bufs_no_lock
- * @hw: pointer to the hardware structure
- * @bufs: pointer to an array of buffers
- * @start: buffer index of first buffer to download
- * @count: the number of buffers to download
- * @indicate_last: if true, then set last buffer flag on last buffer download
- *
- * Downloads package configuration buffers to the firmware. Metadata buffers
- * are skipped, and the first metadata buffer found indicates that the rest
- * of the buffers are all metadata buffers.
- */
-static enum ice_ddp_state
-ice_dwnld_cfg_bufs_no_lock(struct ice_hw *hw, struct ice_buf *bufs, u32 start,
- u32 count, bool indicate_last)
-{
- enum ice_ddp_state state = ICE_DDP_PKG_SUCCESS;
- struct ice_buf_hdr *bh;
- enum ice_aq_err err;
- u32 offset, info, i;
-
- if (!bufs || !count)
- return ICE_DDP_PKG_ERR;
-
- /* If the first buffer's first section has its metadata bit set
- * then there are no buffers to be downloaded, and the operation is
- * considered a success.
- */
- bh = (struct ice_buf_hdr *)(bufs + start);
- if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF)
- return ICE_DDP_PKG_SUCCESS;
-
- for (i = 0; i < count; i++) {
- bool last = false;
- int try_cnt = 0;
- int status;
-
- bh = (struct ice_buf_hdr *)(bufs + start + i);
-
- if (indicate_last)
- last = ice_is_last_download_buffer(bh, i, count);
-
- while (1) {
- status = ice_aq_download_pkg(hw, bh, ICE_PKG_BUF_SIZE,
- last, &offset, &info,
- NULL);
- if (hw->adminq.sq_last_status != ICE_AQ_RC_ENOSEC &&
- hw->adminq.sq_last_status != ICE_AQ_RC_EBADSIG)
- break;
-
- try_cnt++;
-
- if (try_cnt == 5)
- break;
-
- msleep(20);
- }
-
- if (try_cnt)
- dev_dbg(ice_hw_to_dev(hw),
- "ice_aq_download_pkg number of retries: %d\n",
- try_cnt);
-
- /* Save AQ status from download package */
- if (status) {
- ice_debug(hw, ICE_DBG_PKG, "Pkg download failed: err %d off %d inf %d\n",
- status, offset, info);
- err = hw->adminq.sq_last_status;
- state = ice_map_aq_err_to_ddp_state(err);
- break;
- }
-
- if (last)
- break;
- }
-
- return state;
-}
-
-/**
* ice_download_pkg_sig_seg - download a signature segment
- * @hw: pointer to the hardware structure
+ * @ctx: context of the current buffers section to send
* @seg: pointer to signature segment
*/
static enum ice_ddp_state
-ice_download_pkg_sig_seg(struct ice_hw *hw, struct ice_sign_seg *seg)
+ice_download_pkg_sig_seg(struct ice_ddp_send_ctx *ctx, struct ice_sign_seg *seg)
{
- return ice_dwnld_cfg_bufs_no_lock(hw, seg->buf_tbl.buf_array, 0,
- le32_to_cpu(seg->buf_tbl.buf_count),
- false);
+ return ice_dwnld_cfg_bufs_no_lock(ctx, seg->buf_tbl.buf_array, 0,
+ le32_to_cpu(seg->buf_tbl.buf_count));
}
/**
* ice_download_pkg_config_seg - download a config segment
- * @hw: pointer to the hardware structure
+ * @ctx: context of the current buffers section to send
* @pkg_hdr: pointer to package header
* @idx: segment index
* @start: starting buffer
@@ -1408,8 +1417,9 @@ ice_download_pkg_sig_seg(struct ice_hw *hw, struct ice_sign_seg *seg)
* Note: idx must reference a ICE segment
*/
static enum ice_ddp_state
-ice_download_pkg_config_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
- u32 idx, u32 start, u32 count)
+ice_download_pkg_config_seg(struct ice_ddp_send_ctx *ctx,
+ struct ice_pkg_hdr *pkg_hdr, u32 idx, u32 start,
+ u32 count)
{
struct ice_buf_table *bufs;
struct ice_seg *seg;
@@ -1425,46 +1435,56 @@ ice_download_pkg_config_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
if (start >= buf_count || start + count > buf_count)
return ICE_DDP_PKG_ERR;
- return ice_dwnld_cfg_bufs_no_lock(hw, bufs->buf_array, start, count,
- true);
+ return ice_dwnld_cfg_bufs_no_lock(ctx, bufs->buf_array, start, count);
+}
+
+static bool ice_is_last_sign_seg(u32 flags)
+{
+ return !(flags & ICE_SIGN_SEG_FLAGS_VALID) || /* behavior prior to valid */
+ (flags & ICE_SIGN_SEG_FLAGS_LAST);
}
/**
* ice_dwnld_sign_and_cfg_segs - download a signing segment and config segment
- * @hw: pointer to the hardware structure
+ * @ctx: context of the current buffers section to send
* @pkg_hdr: pointer to package header
* @idx: segment index (must be a signature segment)
*
* Note: idx must reference a signature segment
*/
static enum ice_ddp_state
-ice_dwnld_sign_and_cfg_segs(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
- u32 idx)
+ice_dwnld_sign_and_cfg_segs(struct ice_ddp_send_ctx *ctx,
+ struct ice_pkg_hdr *pkg_hdr, u32 idx)
{
+ u32 conf_idx, start, count, flags;
enum ice_ddp_state state;
struct ice_sign_seg *seg;
- u32 conf_idx;
- u32 start;
- u32 count;
seg = (struct ice_sign_seg *)ice_get_pkg_seg_by_idx(pkg_hdr, idx);
if (!seg) {
state = ICE_DDP_PKG_ERR;
- goto exit;
+ ice_ddp_send_ctx_set_err(ctx, state);
+ return state;
}
count = le32_to_cpu(seg->signed_buf_count);
- state = ice_download_pkg_sig_seg(hw, seg);
+ state = ice_download_pkg_sig_seg(ctx, seg);
if (state || !count)
- goto exit;
+ return state;
conf_idx = le32_to_cpu(seg->signed_seg_idx);
start = le32_to_cpu(seg->signed_buf_start);
- state = ice_download_pkg_config_seg(hw, pkg_hdr, conf_idx, start,
+ state = ice_download_pkg_config_seg(ctx, pkg_hdr, conf_idx, start,
count);
-exit:
+ /* finish up by sending last hunk with "last" flag set if requested by
+ * DDP content
+ */
+ flags = le32_to_cpu(seg->flags);
+ if (ice_is_last_sign_seg(flags))
+ state = ice_ddp_send_hunk(ctx, NULL);
+
return state;
}
@@ -1519,6 +1539,7 @@ ice_download_pkg_with_sig_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
{
enum ice_aq_err aq_err = hw->adminq.sq_last_status;
enum ice_ddp_state state = ICE_DDP_PKG_ERR;
+ struct ice_ddp_send_ctx ctx = { .hw = hw };
int status;
u32 i;
@@ -1539,7 +1560,7 @@ ice_download_pkg_with_sig_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
hw->pkg_sign_type))
continue;
- state = ice_dwnld_sign_and_cfg_segs(hw, pkg_hdr, i);
+ state = ice_dwnld_sign_and_cfg_segs(&ctx, pkg_hdr, i);
if (state)
break;
}
@@ -1564,6 +1585,7 @@ ice_download_pkg_with_sig_seg(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr)
static enum ice_ddp_state
ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
{
+ struct ice_ddp_send_ctx ctx = { .hw = hw };
enum ice_ddp_state state;
struct ice_buf_hdr *bh;
int status;
@@ -1576,7 +1598,7 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
* considered a success.
*/
bh = (struct ice_buf_hdr *)bufs;
- if (le32_to_cpu(bh->section_entry[0].type) & ICE_METADATA_BUF)
+ if (ice_is_buffer_metadata(bh))
return ICE_DDP_PKG_SUCCESS;
status = ice_acquire_global_cfg_lock(hw, ICE_RES_WRITE);
@@ -1586,7 +1608,9 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
return ice_map_aq_err_to_ddp_state(hw->adminq.sq_last_status);
}
- state = ice_dwnld_cfg_bufs_no_lock(hw, bufs, 0, count, true);
+ ice_dwnld_cfg_bufs_no_lock(&ctx, bufs, 0, count);
+ /* finish up by sending last hunk with "last" flag set */
+ state = ice_ddp_send_hunk(&ctx, NULL);
if (!state)
state = ice_post_dwnld_pkg_actions(hw);
diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.h b/drivers/net/ethernet/intel/ice/ice_ddp.h
index 79551da2a4b0..8a2d57fc5dae 100644
--- a/drivers/net/ethernet/intel/ice/ice_ddp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ddp.h
@@ -181,7 +181,10 @@ struct ice_sign_seg {
__le32 signed_seg_idx;
__le32 signed_buf_start;
__le32 signed_buf_count;
-#define ICE_SIGN_SEG_RESERVED_COUNT 44
+#define ICE_SIGN_SEG_FLAGS_VALID 0x80000000
+#define ICE_SIGN_SEG_FLAGS_LAST 0x00000001
+ __le32 flags;
+#define ICE_SIGN_SEG_RESERVED_COUNT 40
u8 reserved[ICE_SIGN_SEG_RESERVED_COUNT];
struct ice_buf_table buf_tbl;
};
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index c0b3e70a7ea3..fb527434b58b 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -552,13 +552,14 @@ int ice_eswitch_attach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)
static void ice_eswitch_detach(struct ice_pf *pf, struct ice_repr *repr)
{
ice_eswitch_stop_reprs(pf);
+ repr->ops.rem(repr);
+
xa_erase(&pf->eswitch.reprs, repr->id);
if (xa_empty(&pf->eswitch.reprs))
ice_eswitch_disable_switchdev(pf);
ice_eswitch_release_repr(pf, repr);
- repr->ops.rem(repr);
ice_repr_destroy(repr);
if (xa_empty(&pf->eswitch.reprs)) {
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h
index 20ce32dda69c..ac7db100e2cd 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.h
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h
@@ -60,11 +60,6 @@ ice_eswitch_set_target_vsi(struct sk_buff *skb,
static inline void
ice_eswitch_update_repr(unsigned long *repr_id, struct ice_vsi *vsi) { }
-static inline int ice_eswitch_configure(struct ice_pf *pf)
-{
- return 0;
-}
-
static inline int ice_eswitch_mode_get(struct devlink *devlink, u16 *mode)
{
return DEVLINK_ESWITCH_MODE_LEGACY;
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index d5cc934d1359..3072634bf049 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -693,75 +693,53 @@ static int ice_get_port_topology(struct ice_hw *hw, u8 lport,
static int ice_get_tx_rx_equa(struct ice_hw *hw, u8 serdes_num,
struct ice_serdes_equalization_to_ethtool *ptr)
{
+ static const int tx = ICE_AQC_OP_CODE_TX_EQU;
+ static const int rx = ICE_AQC_OP_CODE_RX_EQU;
+ struct {
+ int data_in;
+ int opcode;
+ int *out;
+ } aq_params[] = {
+ { ICE_AQC_TX_EQU_PRE1, tx, &ptr->tx_equ_pre1 },
+ { ICE_AQC_TX_EQU_PRE3, tx, &ptr->tx_equ_pre3 },
+ { ICE_AQC_TX_EQU_ATTEN, tx, &ptr->tx_equ_atten },
+ { ICE_AQC_TX_EQU_POST1, tx, &ptr->tx_equ_post1 },
+ { ICE_AQC_TX_EQU_PRE2, tx, &ptr->tx_equ_pre2 },
+ { ICE_AQC_RX_EQU_PRE2, rx, &ptr->rx_equ_pre2 },
+ { ICE_AQC_RX_EQU_PRE1, rx, &ptr->rx_equ_pre1 },
+ { ICE_AQC_RX_EQU_POST1, rx, &ptr->rx_equ_post1 },
+ { ICE_AQC_RX_EQU_BFLF, rx, &ptr->rx_equ_bflf },
+ { ICE_AQC_RX_EQU_BFHF, rx, &ptr->rx_equ_bfhf },
+ { ICE_AQC_RX_EQU_DRATE, rx, &ptr->rx_equ_drate },
+ { ICE_AQC_RX_EQU_CTLE_GAINHF, rx, &ptr->rx_equ_ctle_gainhf },
+ { ICE_AQC_RX_EQU_CTLE_GAINLF, rx, &ptr->rx_equ_ctle_gainlf },
+ { ICE_AQC_RX_EQU_CTLE_GAINDC, rx, &ptr->rx_equ_ctle_gaindc },
+ { ICE_AQC_RX_EQU_CTLE_BW, rx, &ptr->rx_equ_ctle_bw },
+ { ICE_AQC_RX_EQU_DFE_GAIN, rx, &ptr->rx_equ_dfe_gain },
+ { ICE_AQC_RX_EQU_DFE_GAIN2, rx, &ptr->rx_equ_dfe_gain_2 },
+ { ICE_AQC_RX_EQU_DFE_2, rx, &ptr->rx_equ_dfe_2 },
+ { ICE_AQC_RX_EQU_DFE_3, rx, &ptr->rx_equ_dfe_3 },
+ { ICE_AQC_RX_EQU_DFE_4, rx, &ptr->rx_equ_dfe_4 },
+ { ICE_AQC_RX_EQU_DFE_5, rx, &ptr->rx_equ_dfe_5 },
+ { ICE_AQC_RX_EQU_DFE_6, rx, &ptr->rx_equ_dfe_6 },
+ { ICE_AQC_RX_EQU_DFE_7, rx, &ptr->rx_equ_dfe_7 },
+ { ICE_AQC_RX_EQU_DFE_8, rx, &ptr->rx_equ_dfe_8 },
+ { ICE_AQC_RX_EQU_DFE_9, rx, &ptr->rx_equ_dfe_9 },
+ { ICE_AQC_RX_EQU_DFE_10, rx, &ptr->rx_equ_dfe_10 },
+ { ICE_AQC_RX_EQU_DFE_11, rx, &ptr->rx_equ_dfe_11 },
+ { ICE_AQC_RX_EQU_DFE_12, rx, &ptr->rx_equ_dfe_12 },
+ };
int err;
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_TX_EQU_PRE1,
- ICE_AQC_OP_CODE_TX_EQU, serdes_num,
- &ptr->tx_equalization_pre1);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_TX_EQU_PRE3,
- ICE_AQC_OP_CODE_TX_EQU, serdes_num,
- &ptr->tx_equalization_pre3);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_TX_EQU_ATTEN,
- ICE_AQC_OP_CODE_TX_EQU, serdes_num,
- &ptr->tx_equalization_atten);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_TX_EQU_POST1,
- ICE_AQC_OP_CODE_TX_EQU, serdes_num,
- &ptr->tx_equalization_post1);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_TX_EQU_PRE2,
- ICE_AQC_OP_CODE_TX_EQU, serdes_num,
- &ptr->tx_equalization_pre2);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_RX_EQU_PRE2,
- ICE_AQC_OP_CODE_RX_EQU, serdes_num,
- &ptr->rx_equalization_pre2);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_RX_EQU_PRE1,
- ICE_AQC_OP_CODE_RX_EQU, serdes_num,
- &ptr->rx_equalization_pre1);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_RX_EQU_POST1,
- ICE_AQC_OP_CODE_RX_EQU, serdes_num,
- &ptr->rx_equalization_post1);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_RX_EQU_BFLF,
- ICE_AQC_OP_CODE_RX_EQU, serdes_num,
- &ptr->rx_equalization_bflf);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_RX_EQU_BFHF,
- ICE_AQC_OP_CODE_RX_EQU, serdes_num,
- &ptr->rx_equalization_bfhf);
- if (err)
- return err;
-
- err = ice_aq_get_phy_equalization(hw, ICE_AQC_RX_EQU_DRATE,
- ICE_AQC_OP_CODE_RX_EQU, serdes_num,
- &ptr->rx_equalization_drate);
- if (err)
- return err;
+ for (int i = 0; i < ARRAY_SIZE(aq_params); i++) {
+ err = ice_aq_get_phy_equalization(hw, aq_params[i].data_in,
+ aq_params[i].opcode,
+ serdes_num, aq_params[i].out);
+ if (err)
+ break;
+ }
- return 0;
+ return err;
}
/**
@@ -4716,6 +4694,81 @@ static void ice_get_fec_stats(struct net_device *netdev,
pi->lport, err);
}
+#define ICE_ETHTOOL_PFR (ETH_RESET_IRQ | ETH_RESET_DMA | \
+ ETH_RESET_FILTER | ETH_RESET_OFFLOAD)
+
+#define ICE_ETHTOOL_CORER ((ICE_ETHTOOL_PFR | ETH_RESET_RAM) << \
+ ETH_RESET_SHARED_SHIFT)
+
+#define ICE_ETHTOOL_GLOBR (ICE_ETHTOOL_CORER | \
+ (ETH_RESET_MAC << ETH_RESET_SHARED_SHIFT) | \
+ (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))
+
+#define ICE_ETHTOOL_VFR ICE_ETHTOOL_PFR
+
+/**
+ * ice_ethtool_reset - triggers a given type of reset
+ * @dev: network interface device structure
+ * @flags: set of reset flags
+ *
+ * Return: 0 on success, -EOPNOTSUPP when using unsupported set of flags.
+ */
+static int ice_ethtool_reset(struct net_device *dev, u32 *flags)
+{
+ struct ice_netdev_priv *np = netdev_priv(dev);
+ struct ice_pf *pf = np->vsi->back;
+ enum ice_reset_req reset;
+
+ switch (*flags) {
+ case ICE_ETHTOOL_CORER:
+ reset = ICE_RESET_CORER;
+ break;
+ case ICE_ETHTOOL_GLOBR:
+ reset = ICE_RESET_GLOBR;
+ break;
+ case ICE_ETHTOOL_PFR:
+ reset = ICE_RESET_PFR;
+ break;
+ default:
+ netdev_info(dev, "Unsupported set of ethtool flags");
+ return -EOPNOTSUPP;
+ }
+
+ ice_schedule_reset(pf, reset);
+
+ *flags = 0;
+
+ return 0;
+}
+
+/**
+ * ice_repr_ethtool_reset - triggers a VF reset
+ * @dev: network interface device structure
+ * @flags: set of reset flags
+ *
+ * Return: 0 on success,
+ * -EOPNOTSUPP when using unsupported set of flags
+ * -EBUSY when VF is not ready for reset.
+ */
+static int ice_repr_ethtool_reset(struct net_device *dev, u32 *flags)
+{
+ struct ice_repr *repr = ice_netdev_to_repr(dev);
+ struct ice_vf *vf;
+
+ if (repr->type != ICE_REPR_TYPE_VF ||
+ *flags != ICE_ETHTOOL_VFR)
+ return -EOPNOTSUPP;
+
+ vf = repr->vf;
+
+ if (ice_check_vf_ready_for_cfg(vf))
+ return -EBUSY;
+
+ *flags = 0;
+
+ return ice_reset_vf(vf, ICE_VF_RESET_VFLR | ICE_VF_RESET_LOCK);
+}
+
static const struct ethtool_ops ice_ethtool_ops = {
.cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
@@ -4752,6 +4805,7 @@ static const struct ethtool_ops ice_ethtool_ops = {
.nway_reset = ice_nway_reset,
.get_pauseparam = ice_get_pauseparam,
.set_pauseparam = ice_set_pauseparam,
+ .reset = ice_ethtool_reset,
.get_rxfh_key_size = ice_get_rxfh_key_size,
.get_rxfh_indir_size = ice_get_rxfh_indir_size,
.get_rxfh = ice_get_rxfh,
@@ -4804,6 +4858,7 @@ static const struct ethtool_ops ice_ethtool_repr_ops = {
.get_strings = ice_repr_get_strings,
.get_ethtool_stats = ice_repr_get_ethtool_stats,
.get_sset_count = ice_repr_get_sset_count,
+ .reset = ice_repr_ethtool_reset,
};
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.h b/drivers/net/ethernet/intel/ice/ice_ethtool.h
index 9acccae38625..8f2ad1c172c0 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.h
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.h
@@ -10,17 +10,34 @@ struct ice_phy_type_to_ethtool {
};
struct ice_serdes_equalization_to_ethtool {
- int rx_equalization_pre2;
- int rx_equalization_pre1;
- int rx_equalization_post1;
- int rx_equalization_bflf;
- int rx_equalization_bfhf;
- int rx_equalization_drate;
- int tx_equalization_pre1;
- int tx_equalization_pre3;
- int tx_equalization_atten;
- int tx_equalization_post1;
- int tx_equalization_pre2;
+ int rx_equ_pre2;
+ int rx_equ_pre1;
+ int rx_equ_post1;
+ int rx_equ_bflf;
+ int rx_equ_bfhf;
+ int rx_equ_drate;
+ int rx_equ_ctle_gainhf;
+ int rx_equ_ctle_gainlf;
+ int rx_equ_ctle_gaindc;
+ int rx_equ_ctle_bw;
+ int rx_equ_dfe_gain;
+ int rx_equ_dfe_gain_2;
+ int rx_equ_dfe_2;
+ int rx_equ_dfe_3;
+ int rx_equ_dfe_4;
+ int rx_equ_dfe_5;
+ int rx_equ_dfe_6;
+ int rx_equ_dfe_7;
+ int rx_equ_dfe_8;
+ int rx_equ_dfe_9;
+ int rx_equ_dfe_10;
+ int rx_equ_dfe_11;
+ int rx_equ_dfe_12;
+ int tx_equ_pre1;
+ int tx_equ_pre3;
+ int tx_equ_atten;
+ int tx_equ_post1;
+ int tx_equ_pre2;
};
struct ice_regdump_to_ethtool {
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
index 5412eff8ef23..ee9862ddfe15 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
@@ -1830,11 +1830,12 @@ static int
ice_set_fdir_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,
struct ice_fdir_fltr *input)
{
- u16 dest_vsi, q_index = 0;
+ s16 q_index = ICE_FDIR_NO_QUEUE_IDX;
u16 orig_q_index = 0;
struct ice_pf *pf;
struct ice_hw *hw;
int flow_type;
+ u16 dest_vsi;
u8 dest_ctl;
if (!vsi || !fsp || !input)
diff --git a/drivers/net/ethernet/intel/ice/ice_fdir.h b/drivers/net/ethernet/intel/ice/ice_fdir.h
index ab5b118daa2d..820023c0271f 100644
--- a/drivers/net/ethernet/intel/ice/ice_fdir.h
+++ b/drivers/net/ethernet/intel/ice/ice_fdir.h
@@ -53,6 +53,8 @@
*/
#define ICE_FDIR_IPV4_PKT_FLAG_MF 0x20
+#define ICE_FDIR_NO_QUEUE_IDX -1
+
enum ice_fltr_prgm_desc_dest {
ICE_FLTR_PRGM_DESC_DEST_DROP_PKT,
ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX,
@@ -186,7 +188,7 @@ struct ice_fdir_fltr {
u16 flex_fltr;
/* filter control */
- u16 q_index;
+ s16 q_index;
u16 orig_q_index;
u16 dest_vsi;
u8 dest_ctl;
diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
index 90b9b0993122..28b0897adf32 100644
--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
@@ -23,9 +23,6 @@ int
ice_get_sw_fv_list(struct ice_hw *hw, struct ice_prot_lkup_ext *lkups,
unsigned long *bm, struct list_head *fv_list);
int
-ice_pkg_buf_unreserve_section(struct ice_buf_build *bld, u16 count);
-u16 ice_pkg_buf_get_free_space(struct ice_buf_build *bld);
-int
ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
u16 buf_size, struct ice_sq_cd *cd);
bool
diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.c b/drivers/net/ethernet/intel/ice/ice_gnss.c
index c8ea1af51ad3..f02e8ca55375 100644
--- a/drivers/net/ethernet/intel/ice/ice_gnss.c
+++ b/drivers/net/ethernet/intel/ice/ice_gnss.c
@@ -397,8 +397,8 @@ bool ice_gnss_is_gps_present(struct ice_hw *hw)
int err;
u8 data;
- err = ice_read_pca9575_reg_e810t(hw, ICE_PCA9575_P0_IN, &data);
- if (err || !!(data & ICE_E810T_P0_GNSS_PRSNT_N))
+ err = ice_read_pca9575_reg(hw, ICE_PCA9575_P0_IN, &data);
+ if (err || !!(data & ICE_P0_GNSS_PRSNT_N))
return false;
} else {
return false;
diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
index 91cbae1eec89..dc88aea9f473 100644
--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
@@ -6,6 +6,14 @@
#ifndef _ICE_HW_AUTOGEN_H_
#define _ICE_HW_AUTOGEN_H_
+#define GLCOMM_QUANTA_PROF(_i) (0x002D2D68 + ((_i) * 4))
+#define GLCOMM_QUANTA_PROF_MAX_INDEX 15
+#define GLCOMM_QUANTA_PROF_QUANTA_SIZE_S 0
+#define GLCOMM_QUANTA_PROF_QUANTA_SIZE_M ICE_M(0x3FFF, 0)
+#define GLCOMM_QUANTA_PROF_MAX_CMD_S 16
+#define GLCOMM_QUANTA_PROF_MAX_CMD_M ICE_M(0xFF, 16)
+#define GLCOMM_QUANTA_PROF_MAX_DESC_S 24
+#define GLCOMM_QUANTA_PROF_MAX_DESC_M ICE_M(0x3F, 24)
#define QTX_COMM_DBELL(_DBQM) (0x002C0000 + ((_DBQM) * 4))
#define QTX_COMM_HEAD(_DBQM) (0x000E0000 + ((_DBQM) * 4))
#define QTX_COMM_HEAD_HEAD_S 0
@@ -539,5 +547,8 @@
#define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0)
#define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
#define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
+#define E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH 0x00234000
+#define E830_MBX_VF_DEC_TRIG(_VF) (0x00233800 + (_VF) * 4)
+#define E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(_VF) (0x00233000 + (_VF) * 4)
#endif /* _ICE_HW_AUTOGEN_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 06e712cdc3d9..a7d45a8ce7ac 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -2777,8 +2777,10 @@ void ice_napi_add(struct ice_vsi *vsi)
return;
ice_for_each_q_vector(vsi, v_idx)
- netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi,
- ice_napi_poll);
+ netif_napi_add_config(vsi->netdev,
+ &vsi->q_vectors[v_idx]->napi,
+ ice_napi_poll,
+ v_idx);
}
/**
@@ -3880,6 +3882,9 @@ void ice_init_feature_support(struct ice_pf *pf)
default:
break;
}
+
+ if (pf->hw.mac_type == ICE_MAC_E830)
+ ice_set_feature_support(pf, ICE_F_MBX_LIMIT);
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index 1a6cfc8693ce..10d6fc479a32 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -88,8 +88,6 @@ void ice_write_intrl(struct ice_q_vector *q_vector, u8 intrl);
void ice_write_itr(struct ice_ring_container *rc, u16 itr);
void ice_set_q_vector_intrl(struct ice_q_vector *q_vector);
-int ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set);
-
bool ice_is_safe_mode(struct ice_pf *pf);
bool ice_is_rdma_ena(struct ice_pf *pf);
bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index b1e7727b8677..1eaa4428fd24 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -1546,12 +1546,20 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type)
ice_vf_lan_overflow_event(pf, &event);
break;
case ice_mbx_opc_send_msg_to_pf:
- data.num_msg_proc = i;
- data.num_pending_arq = pending;
- data.max_num_msgs_mbx = hw->mailboxq.num_rq_entries;
- data.async_watermark_val = ICE_MBX_OVERFLOW_WATERMARK;
+ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) {
+ ice_vc_process_vf_msg(pf, &event, NULL);
+ ice_mbx_vf_dec_trig_e830(hw, &event);
+ } else {
+ u16 val = hw->mailboxq.num_rq_entries;
+
+ data.max_num_msgs_mbx = val;
+ val = ICE_MBX_OVERFLOW_WATERMARK;
+ data.async_watermark_val = val;
+ data.num_msg_proc = i;
+ data.num_pending_arq = pending;
- ice_vc_process_vf_msg(pf, &event, &data);
+ ice_vc_process_vf_msg(pf, &event, &data);
+ }
break;
case ice_aqc_opc_fw_logs_event:
ice_get_fwlog_data(pf, &event);
@@ -4082,7 +4090,11 @@ static int ice_init_pf(struct ice_pf *pf)
mutex_init(&pf->vfs.table_lock);
hash_init(pf->vfs.table);
- ice_mbx_init_snapshot(&pf->hw);
+ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
+ wr32(&pf->hw, E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH,
+ ICE_MBX_OVERFLOW_WATERMARK);
+ else
+ ice_mbx_init_snapshot(&pf->hw);
xa_init(&pf->dyn_ports);
xa_init(&pf->sf_nums);
@@ -4543,6 +4555,34 @@ ice_init_tx_topology(struct ice_hw *hw, const struct firmware *firmware)
}
/**
+ * ice_init_supported_rxdids - Initialize supported Rx descriptor IDs
+ * @hw: pointer to the hardware structure
+ * @pf: pointer to pf structure
+ *
+ * The pf->supported_rxdids bitmap is used to indicate to VFs which descriptor
+ * formats the PF hardware supports. The exact list of supported RXDIDs
+ * depends on the loaded DDP package. The IDs can be determined by reading the
+ * GLFLXP_RXDID_FLAGS register after the DDP package is loaded.
+ *
+ * Note that the legacy 32-byte RXDID 0 is always supported but is not listed
+ * in the DDP package. The 16-byte legacy descriptor is never supported by
+ * VFs.
+ */
+static void ice_init_supported_rxdids(struct ice_hw *hw, struct ice_pf *pf)
+{
+ pf->supported_rxdids = BIT(ICE_RXDID_LEGACY_1);
+
+ for (int i = ICE_RXDID_FLEX_NIC; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) {
+ u32 regval;
+
+ regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0));
+ if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S)
+ & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M)
+ pf->supported_rxdids |= BIT(i);
+ }
+}
+
+/**
* ice_init_ddp_config - DDP related configuration
* @hw: pointer to the hardware structure
* @pf: pointer to pf structure
@@ -4576,6 +4616,9 @@ static int ice_init_ddp_config(struct ice_hw *hw, struct ice_pf *pf)
ice_load_pkg(firmware, pf);
release_firmware(firmware);
+ /* Initialize the supported Rx descriptor IDs after loading DDP */
+ ice_init_supported_rxdids(hw, pf);
+
return 0;
}
@@ -5888,7 +5931,7 @@ static int __init ice_module_init(void)
ice_adv_lnk_speed_maps_init();
- ice_wq = alloc_workqueue("%s", 0, 0, KBUILD_MODNAME);
+ ice_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, KBUILD_MODNAME);
if (!ice_wq) {
pr_err("Failed to create workqueue\n");
return status;
@@ -6113,12 +6156,14 @@ ice_set_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate)
* @addr: the MAC address entry being added
* @vid: VLAN ID
* @flags: instructions from stack about fdb operation
+ * @notified: whether notification was emitted
* @extack: netlink extended ack
*/
static int
ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
struct net_device *dev, const unsigned char *addr, u16 vid,
- u16 flags, struct netlink_ext_ack __always_unused *extack)
+ u16 flags, bool *notified,
+ struct netlink_ext_ack __always_unused *extack)
{
int err;
@@ -6152,12 +6197,14 @@ ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
* @dev: the net device pointer
* @addr: the MAC address entry being added
* @vid: VLAN ID
+ * @notified: whether notification was emitted
* @extack: netlink extended ack
*/
static int
ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
struct net_device *dev, const unsigned char *addr,
- __always_unused u16 vid, struct netlink_ext_ack *extack)
+ __always_unused u16 vid, bool *notified,
+ struct netlink_ext_ack *extack)
{
int err;
@@ -6512,8 +6559,7 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
if (changed & NETIF_F_HW_TC) {
bool ena = !!(features & NETIF_F_HW_TC);
- ena ? set_bit(ICE_FLAG_CLS_FLOWER, pf->flags) :
- clear_bit(ICE_FLAG_CLS_FLOWER, pf->flags);
+ assign_bit(ICE_FLAG_CLS_FLOWER, pf->flags, ena);
}
if (changed & NETIF_F_LOOPBACK)
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index ef2e858f49bb..a999fface272 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -4,253 +4,187 @@
#include "ice.h"
#include "ice_lib.h"
#include "ice_trace.h"
+#include "ice_cgu_regs.h"
+
+static const char ice_pin_names[][64] = {
+ "SDP0",
+ "SDP1",
+ "SDP2",
+ "SDP3",
+ "TIME_SYNC",
+ "1PPS"
+};
-#define E810_OUT_PROP_DELAY_NS 1
+static const struct ice_ptp_pin_desc ice_pin_desc_e82x[] = {
+ /* name, gpio */
+ { TIME_SYNC, { 4, -1 }},
+ { ONE_PPS, { -1, 5 }},
+};
-static const struct ptp_pin_desc ice_pin_desc_e810t[] = {
- /* name idx func chan */
- { "GNSS", GNSS, PTP_PF_EXTTS, 0, { 0, } },
- { "SMA1", SMA1, PTP_PF_NONE, 1, { 0, } },
- { "U.FL1", UFL1, PTP_PF_NONE, 1, { 0, } },
- { "SMA2", SMA2, PTP_PF_NONE, 2, { 0, } },
- { "U.FL2", UFL2, PTP_PF_NONE, 2, { 0, } },
+static const struct ice_ptp_pin_desc ice_pin_desc_e825c[] = {
+ /* name, gpio */
+ { SDP0, { 0, 0 }},
+ { SDP1, { 1, 1 }},
+ { SDP2, { 2, 2 }},
+ { SDP3, { 3, 3 }},
+ { TIME_SYNC, { 4, -1 }},
+ { ONE_PPS, { -1, 5 }},
};
-/**
- * ice_get_sma_config_e810t
- * @hw: pointer to the hw struct
- * @ptp_pins: pointer to the ptp_pin_desc struture
- *
- * Read the configuration of the SMA control logic and put it into the
- * ptp_pin_desc structure
- */
-static int
-ice_get_sma_config_e810t(struct ice_hw *hw, struct ptp_pin_desc *ptp_pins)
-{
- u8 data, i;
- int status;
+static const struct ice_ptp_pin_desc ice_pin_desc_e810[] = {
+ /* name, gpio */
+ { SDP0, { 0, 0 }},
+ { SDP1, { 1, 1 }},
+ { SDP2, { 2, 2 }},
+ { SDP3, { 3, 3 }},
+ { ONE_PPS, { -1, 5 }},
+};
- /* Read initial pin state */
- status = ice_read_sma_ctrl_e810t(hw, &data);
- if (status)
- return status;
+static const char ice_pin_names_nvm[][64] = {
+ "GNSS",
+ "SMA1",
+ "U.FL1",
+ "SMA2",
+ "U.FL2",
+};
- /* initialize with defaults */
- for (i = 0; i < NUM_PTP_PINS_E810T; i++) {
- strscpy(ptp_pins[i].name, ice_pin_desc_e810t[i].name,
- sizeof(ptp_pins[i].name));
- ptp_pins[i].index = ice_pin_desc_e810t[i].index;
- ptp_pins[i].func = ice_pin_desc_e810t[i].func;
- ptp_pins[i].chan = ice_pin_desc_e810t[i].chan;
- }
+static const struct ice_ptp_pin_desc ice_pin_desc_e810_sma[] = {
+ /* name, gpio */
+ { GNSS, { 1, -1 }},
+ { SMA1, { 1, 0 }},
+ { UFL1, { -1, 0 }},
+ { SMA2, { 3, 2 }},
+ { UFL2, { 3, -1 }},
+};
- /* Parse SMA1/UFL1 */
- switch (data & ICE_SMA1_MASK_E810T) {
- case ICE_SMA1_MASK_E810T:
- default:
- ptp_pins[SMA1].func = PTP_PF_NONE;
- ptp_pins[UFL1].func = PTP_PF_NONE;
- break;
- case ICE_SMA1_DIR_EN_E810T:
- ptp_pins[SMA1].func = PTP_PF_PEROUT;
- ptp_pins[UFL1].func = PTP_PF_NONE;
- break;
- case ICE_SMA1_TX_EN_E810T:
- ptp_pins[SMA1].func = PTP_PF_EXTTS;
- ptp_pins[UFL1].func = PTP_PF_NONE;
- break;
- case 0:
- ptp_pins[SMA1].func = PTP_PF_EXTTS;
- ptp_pins[UFL1].func = PTP_PF_PEROUT;
- break;
- }
+static struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf)
+{
+ return !pf->adapter ? NULL : pf->adapter->ctrl_pf;
+}
- /* Parse SMA2/UFL2 */
- switch (data & ICE_SMA2_MASK_E810T) {
- case ICE_SMA2_MASK_E810T:
- default:
- ptp_pins[SMA2].func = PTP_PF_NONE;
- ptp_pins[UFL2].func = PTP_PF_NONE;
- break;
- case (ICE_SMA2_TX_EN_E810T | ICE_SMA2_UFL2_RX_DIS_E810T):
- ptp_pins[SMA2].func = PTP_PF_EXTTS;
- ptp_pins[UFL2].func = PTP_PF_NONE;
- break;
- case (ICE_SMA2_DIR_EN_E810T | ICE_SMA2_UFL2_RX_DIS_E810T):
- ptp_pins[SMA2].func = PTP_PF_PEROUT;
- ptp_pins[UFL2].func = PTP_PF_NONE;
- break;
- case (ICE_SMA2_DIR_EN_E810T | ICE_SMA2_TX_EN_E810T):
- ptp_pins[SMA2].func = PTP_PF_NONE;
- ptp_pins[UFL2].func = PTP_PF_EXTTS;
- break;
- case ICE_SMA2_DIR_EN_E810T:
- ptp_pins[SMA2].func = PTP_PF_PEROUT;
- ptp_pins[UFL2].func = PTP_PF_EXTTS;
- break;
- }
+static struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf)
+{
+ struct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);
- return 0;
+ return !ctrl_pf ? NULL : &ctrl_pf->ptp;
}
/**
- * ice_ptp_set_sma_config_e810t
- * @hw: pointer to the hw struct
- * @ptp_pins: pointer to the ptp_pin_desc struture
+ * ice_ptp_find_pin_idx - Find pin index in ptp_pin_desc
+ * @pf: Board private structure
+ * @func: Pin function
+ * @chan: GPIO channel
*
- * Set the configuration of the SMA control logic based on the configuration in
- * num_pins parameter
+ * Return: positive pin number when pin is present, -1 otherwise
*/
-static int
-ice_ptp_set_sma_config_e810t(struct ice_hw *hw,
- const struct ptp_pin_desc *ptp_pins)
+static int ice_ptp_find_pin_idx(struct ice_pf *pf, enum ptp_pin_function func,
+ unsigned int chan)
{
- int status;
- u8 data;
+ const struct ptp_clock_info *info = &pf->ptp.info;
+ int i;
- /* SMA1 and UFL1 cannot be set to TX at the same time */
- if (ptp_pins[SMA1].func == PTP_PF_PEROUT &&
- ptp_pins[UFL1].func == PTP_PF_PEROUT)
- return -EINVAL;
+ for (i = 0; i < info->n_pins; i++) {
+ if (info->pin_config[i].func == func &&
+ info->pin_config[i].chan == chan)
+ return i;
+ }
- /* SMA2 and UFL2 cannot be set to RX at the same time */
- if (ptp_pins[SMA2].func == PTP_PF_EXTTS &&
- ptp_pins[UFL2].func == PTP_PF_EXTTS)
- return -EINVAL;
+ return -1;
+}
- /* Read initial pin state value */
- status = ice_read_sma_ctrl_e810t(hw, &data);
- if (status)
- return status;
-
- /* Set the right sate based on the desired configuration */
- data &= ~ICE_SMA1_MASK_E810T;
- if (ptp_pins[SMA1].func == PTP_PF_NONE &&
- ptp_pins[UFL1].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA1 + U.FL1 disabled");
- data |= ICE_SMA1_MASK_E810T;
- } else if (ptp_pins[SMA1].func == PTP_PF_EXTTS &&
- ptp_pins[UFL1].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA1 RX");
- data |= ICE_SMA1_TX_EN_E810T;
- } else if (ptp_pins[SMA1].func == PTP_PF_NONE &&
- ptp_pins[UFL1].func == PTP_PF_PEROUT) {
- /* U.FL 1 TX will always enable SMA 1 RX */
- dev_info(ice_hw_to_dev(hw), "SMA1 RX + U.FL1 TX");
- } else if (ptp_pins[SMA1].func == PTP_PF_EXTTS &&
- ptp_pins[UFL1].func == PTP_PF_PEROUT) {
- dev_info(ice_hw_to_dev(hw), "SMA1 RX + U.FL1 TX");
- } else if (ptp_pins[SMA1].func == PTP_PF_PEROUT &&
- ptp_pins[UFL1].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA1 TX");
- data |= ICE_SMA1_DIR_EN_E810T;
- }
-
- data &= ~ICE_SMA2_MASK_E810T;
- if (ptp_pins[SMA2].func == PTP_PF_NONE &&
- ptp_pins[UFL2].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA2 + U.FL2 disabled");
- data |= ICE_SMA2_MASK_E810T;
- } else if (ptp_pins[SMA2].func == PTP_PF_EXTTS &&
- ptp_pins[UFL2].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA2 RX");
- data |= (ICE_SMA2_TX_EN_E810T |
- ICE_SMA2_UFL2_RX_DIS_E810T);
- } else if (ptp_pins[SMA2].func == PTP_PF_NONE &&
- ptp_pins[UFL2].func == PTP_PF_EXTTS) {
- dev_info(ice_hw_to_dev(hw), "UFL2 RX");
- data |= (ICE_SMA2_DIR_EN_E810T | ICE_SMA2_TX_EN_E810T);
- } else if (ptp_pins[SMA2].func == PTP_PF_PEROUT &&
- ptp_pins[UFL2].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA2 TX");
- data |= (ICE_SMA2_DIR_EN_E810T |
- ICE_SMA2_UFL2_RX_DIS_E810T);
- } else if (ptp_pins[SMA2].func == PTP_PF_PEROUT &&
- ptp_pins[UFL2].func == PTP_PF_EXTTS) {
- dev_info(ice_hw_to_dev(hw), "SMA2 TX + U.FL2 RX");
- data |= ICE_SMA2_DIR_EN_E810T;
- }
-
- return ice_write_sma_ctrl_e810t(hw, data);
-}
-
-/**
- * ice_ptp_set_sma_e810t
- * @info: the driver's PTP info structure
- * @pin: pin index in kernel structure
- * @func: Pin function to be set (PTP_PF_NONE, PTP_PF_EXTTS or PTP_PF_PEROUT)
- *
- * Set the configuration of a single SMA pin
+/**
+ * ice_ptp_update_sma_data - update SMA pins data according to pins setup
+ * @pf: Board private structure
+ * @sma_pins: parsed SMA pins status
+ * @data: SMA data to update
*/
-static int
-ice_ptp_set_sma_e810t(struct ptp_clock_info *info, unsigned int pin,
- enum ptp_pin_function func)
+static void ice_ptp_update_sma_data(struct ice_pf *pf, unsigned int sma_pins[],
+ u8 *data)
{
- struct ptp_pin_desc ptp_pins[NUM_PTP_PINS_E810T];
- struct ice_pf *pf = ptp_info_to_pf(info);
- struct ice_hw *hw = &pf->hw;
- int err;
+ const char *state1, *state2;
- if (pin < SMA1 || func > PTP_PF_PEROUT)
- return -EOPNOTSUPP;
-
- err = ice_get_sma_config_e810t(hw, ptp_pins);
- if (err)
- return err;
-
- /* Disable the same function on the other pin sharing the channel */
- if (pin == SMA1 && ptp_pins[UFL1].func == func)
- ptp_pins[UFL1].func = PTP_PF_NONE;
- if (pin == UFL1 && ptp_pins[SMA1].func == func)
- ptp_pins[SMA1].func = PTP_PF_NONE;
-
- if (pin == SMA2 && ptp_pins[UFL2].func == func)
- ptp_pins[UFL2].func = PTP_PF_NONE;
- if (pin == UFL2 && ptp_pins[SMA2].func == func)
- ptp_pins[SMA2].func = PTP_PF_NONE;
+ /* Set the right state based on the desired configuration.
+ * When bit is set, functionality is disabled.
+ */
+ *data &= ~ICE_ALL_SMA_MASK;
+ if (!sma_pins[UFL1 - 1]) {
+ if (sma_pins[SMA1 - 1] == PTP_PF_EXTTS) {
+ state1 = "SMA1 Rx, U.FL1 disabled";
+ *data |= ICE_SMA1_TX_EN;
+ } else if (sma_pins[SMA1 - 1] == PTP_PF_PEROUT) {
+ state1 = "SMA1 Tx U.FL1 disabled";
+ *data |= ICE_SMA1_DIR_EN;
+ } else {
+ state1 = "SMA1 disabled, U.FL1 disabled";
+ *data |= ICE_SMA1_MASK;
+ }
+ } else {
+ /* U.FL1 Tx will always enable SMA1 Rx */
+ state1 = "SMA1 Rx, U.FL1 Tx";
+ }
- /* Set up new pin function in the temp table */
- ptp_pins[pin].func = func;
+ if (!sma_pins[UFL2 - 1]) {
+ if (sma_pins[SMA2 - 1] == PTP_PF_EXTTS) {
+ state2 = "SMA2 Rx, U.FL2 disabled";
+ *data |= ICE_SMA2_TX_EN | ICE_SMA2_UFL2_RX_DIS;
+ } else if (sma_pins[SMA2 - 1] == PTP_PF_PEROUT) {
+ state2 = "SMA2 Tx, U.FL2 disabled";
+ *data |= ICE_SMA2_DIR_EN | ICE_SMA2_UFL2_RX_DIS;
+ } else {
+ state2 = "SMA2 disabled, U.FL2 disabled";
+ *data |= ICE_SMA2_MASK;
+ }
+ } else {
+ if (!sma_pins[SMA2 - 1]) {
+ state2 = "SMA2 disabled, U.FL2 Rx";
+ *data |= ICE_SMA2_DIR_EN | ICE_SMA2_TX_EN;
+ } else {
+ state2 = "SMA2 Tx, U.FL2 Rx";
+ *data |= ICE_SMA2_DIR_EN;
+ }
+ }
- return ice_ptp_set_sma_config_e810t(hw, ptp_pins);
+ dev_dbg(ice_pf_to_dev(pf), "%s, %s\n", state1, state2);
}
/**
- * ice_verify_pin_e810t
- * @info: the driver's PTP info structure
- * @pin: Pin index
- * @func: Assigned function
- * @chan: Assigned channel
+ * ice_ptp_set_sma_cfg - set the configuration of the SMA control logic
+ * @pf: Board private structure
*
- * Verify if pin supports requested pin function. If the Check pins consistency.
- * Reconfigure the SMA logic attached to the given pin to enable its
- * desired functionality
+ * Return: 0 on success, negative error code otherwise
*/
-static int
-ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin,
- enum ptp_pin_function func, unsigned int chan)
+static int ice_ptp_set_sma_cfg(struct ice_pf *pf)
{
- /* Don't allow channel reassignment */
- if (chan != ice_pin_desc_e810t[pin].chan)
- return -EOPNOTSUPP;
+ const struct ice_ptp_pin_desc *ice_pins = pf->ptp.ice_pin_desc;
+ struct ptp_pin_desc *pins = pf->ptp.pin_desc;
+ unsigned int sma_pins[ICE_SMA_PINS_NUM] = {};
+ int err;
+ u8 data;
- /* Check if functions are properly assigned */
- switch (func) {
- case PTP_PF_NONE:
- break;
- case PTP_PF_EXTTS:
- if (pin == UFL1)
- return -EOPNOTSUPP;
- break;
- case PTP_PF_PEROUT:
- if (pin == UFL2 || pin == GNSS)
- return -EOPNOTSUPP;
- break;
- case PTP_PF_PHYSYNC:
- return -EOPNOTSUPP;
- }
+ /* Read initial pin state value */
+ err = ice_read_sma_ctrl(&pf->hw, &data);
+ if (err)
+ return err;
- return ice_ptp_set_sma_e810t(info, pin, func);
+ /* Get SMA/U.FL pins states */
+ for (int i = 0; i < pf->ptp.info.n_pins; i++)
+ if (pins[i].func) {
+ int name_idx = ice_pins[i].name_idx;
+
+ switch (name_idx) {
+ case SMA1:
+ case UFL1:
+ case SMA2:
+ case UFL2:
+ sma_pins[name_idx - 1] = pins[i].func;
+ break;
+ default:
+ continue;
+ }
+ }
+
+ ice_ptp_update_sma_data(pf, sma_pins, &data);
+ return ice_write_sma_ctrl(&pf->hw, data);
}
/**
@@ -800,8 +734,8 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
struct ice_ptp_port *port;
unsigned int i;
- mutex_lock(&pf->ptp.ports_owner.lock);
- list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) {
+ mutex_lock(&pf->adapter->ports.lock);
+ list_for_each_entry(port, &pf->adapter->ports.ports, list_node) {
struct ice_ptp_tx *tx = &port->tx;
if (!tx || !tx->init)
@@ -809,7 +743,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
ice_ptp_process_tx_tstamp(tx);
}
- mutex_unlock(&pf->ptp.ports_owner.lock);
+ mutex_unlock(&pf->adapter->ports.lock);
for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) {
u64 tstamp_ready;
@@ -974,7 +908,7 @@ ice_ptp_flush_all_tx_tracker(struct ice_pf *pf)
{
struct ice_ptp_port *port;
- list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member)
+ list_for_each_entry(port, &pf->adapter->ports.ports, list_node)
ice_ptp_flush_tx_tracker(ptp_port_to_pf(port), &port->tx);
}
@@ -1363,7 +1297,7 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
mutex_lock(&ptp_port->ps_lock);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_stop_phy_timer_eth56g(hw, port, true);
break;
@@ -1409,7 +1343,7 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
mutex_lock(&ptp_port->ps_lock);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_start_phy_timer_eth56g(hw, port);
break;
@@ -1480,8 +1414,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
/* Skip HW writes if reset is in progress */
if (pf->hw.reset_ongoing)
return;
-
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_E810:
/* Do not reconfigure E810 PHY */
return;
@@ -1514,7 +1447,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
ice_ptp_reset_ts_memory(hw);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G: {
int port;
@@ -1553,7 +1486,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
case ICE_PHY_UNSUP:
default:
dev_warn(dev, "%s: Unexpected PHY model %d\n", __func__,
- hw->ptp.phy_model);
+ ice_get_phy_model(hw));
return -EOPNOTSUPP;
}
}
@@ -1575,10 +1508,10 @@ static void ice_ptp_restart_all_phy(struct ice_pf *pf)
{
struct list_head *entry;
- list_for_each(entry, &pf->ptp.ports_owner.ports) {
+ list_for_each(entry, &pf->adapter->ports.ports) {
struct ice_ptp_port *port = list_entry(entry,
struct ice_ptp_port,
- list_member);
+ list_node);
if (port->link_up)
ice_ptp_port_phy_restart(port);
@@ -1651,33 +1584,41 @@ void ice_ptp_extts_event(struct ice_pf *pf)
/**
* ice_ptp_cfg_extts - Configure EXTTS pin and channel
* @pf: Board private structure
- * @chan: GPIO channel (0-3)
- * @config: desired EXTTS configuration.
- * @store: If set to true, the values will be stored
+ * @rq: External timestamp request
+ * @on: Enable/disable flag
*
* Configure an external timestamp event on the requested channel.
*
- * Return: 0 on success, -EOPNOTUSPP on unsupported flags
+ * Return: 0 on success, negative error code otherwise
*/
-static int ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
- struct ice_extts_channel *config, bool store)
+static int ice_ptp_cfg_extts(struct ice_pf *pf, struct ptp_extts_request *rq,
+ int on)
{
- u32 func, aux_reg, gpio_reg, irq_reg;
+ u32 aux_reg, gpio_reg, irq_reg;
struct ice_hw *hw = &pf->hw;
+ unsigned int chan, gpio_pin;
+ int pin_desc_idx;
u8 tmr_idx;
/* Reject requests with unsupported flags */
- if (config->flags & ~(PTP_ENABLE_FEATURE |
- PTP_RISING_EDGE |
- PTP_FALLING_EDGE |
- PTP_STRICT_FLAGS))
+
+ if (rq->flags & ~(PTP_ENABLE_FEATURE |
+ PTP_RISING_EDGE |
+ PTP_FALLING_EDGE |
+ PTP_STRICT_FLAGS))
return -EOPNOTSUPP;
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ chan = rq->index;
+ pin_desc_idx = ice_ptp_find_pin_idx(pf, PTP_PF_EXTTS, chan);
+ if (pin_desc_idx < 0)
+ return -EIO;
+
+ gpio_pin = pf->ptp.ice_pin_desc[pin_desc_idx].gpio[0];
irq_reg = rd32(hw, PFINT_OICR_ENA);
- if (config->ena) {
+ if (on) {
/* Enable the interrupt */
irq_reg |= PFINT_OICR_TSYN_EVNT_M;
aux_reg = GLTSYN_AUX_IN_0_INT_ENA_M;
@@ -1686,33 +1627,38 @@ static int ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
#define GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE BIT(1)
/* set event level to requested edge */
- if (config->flags & PTP_FALLING_EDGE)
+ if (rq->flags & PTP_FALLING_EDGE)
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE;
- if (config->flags & PTP_RISING_EDGE)
+ if (rq->flags & PTP_RISING_EDGE)
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_RISING_EDGE;
/* Write GPIO CTL reg.
* 0x1 is input sampled by EVENT register(channel)
* + num_in_channels * tmr_idx
*/
- func = 1 + chan + (tmr_idx * 3);
- gpio_reg = FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M, func);
- pf->ptp.ext_ts_chan |= (1 << chan);
+ gpio_reg = FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M,
+ 1 + chan + (tmr_idx * 3));
} else {
+ bool last_enabled = true;
+
/* clear the values we set to reset defaults */
aux_reg = 0;
gpio_reg = 0;
- pf->ptp.ext_ts_chan &= ~(1 << chan);
- if (!pf->ptp.ext_ts_chan)
+
+ for (unsigned int i = 0; i < pf->ptp.info.n_ext_ts; i++)
+ if ((pf->ptp.extts_rqs[i].flags &
+ PTP_ENABLE_FEATURE) &&
+ i != chan) {
+ last_enabled = false;
+ }
+
+ if (last_enabled)
irq_reg &= ~PFINT_OICR_TSYN_EVNT_M;
}
wr32(hw, PFINT_OICR_ENA, irq_reg);
wr32(hw, GLTSYN_AUX_IN(chan, tmr_idx), aux_reg);
- wr32(hw, GLGEN_GPIO_CTL(config->gpio_pin), gpio_reg);
-
- if (store)
- memcpy(&pf->ptp.extts_channels[chan], config, sizeof(*config));
+ wr32(hw, GLGEN_GPIO_CTL(gpio_pin), gpio_reg);
return 0;
}
@@ -1723,16 +1669,10 @@ static int ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
*/
static void ice_ptp_disable_all_extts(struct ice_pf *pf)
{
- struct ice_extts_channel extts_cfg = {};
- int i;
-
- for (i = 0; i < pf->ptp.info.n_ext_ts; i++) {
- if (pf->ptp.extts_channels[i].ena) {
- extts_cfg.gpio_pin = pf->ptp.extts_channels[i].gpio_pin;
- extts_cfg.ena = false;
- ice_ptp_cfg_extts(pf, i, &extts_cfg, false);
- }
- }
+ for (unsigned int i = 0; i < pf->ptp.info.n_ext_ts ; i++)
+ if (pf->ptp.extts_rqs[i].flags & PTP_ENABLE_FEATURE)
+ ice_ptp_cfg_extts(pf, &pf->ptp.extts_rqs[i],
+ false);
synchronize_irq(pf->oicr_irq.virq);
}
@@ -1745,273 +1685,322 @@ static void ice_ptp_disable_all_extts(struct ice_pf *pf)
*/
static void ice_ptp_enable_all_extts(struct ice_pf *pf)
{
- int i;
-
- for (i = 0; i < pf->ptp.info.n_ext_ts; i++) {
- if (pf->ptp.extts_channels[i].ena)
- ice_ptp_cfg_extts(pf, i, &pf->ptp.extts_channels[i],
- false);
- }
+ for (unsigned int i = 0; i < pf->ptp.info.n_ext_ts ; i++)
+ if (pf->ptp.extts_rqs[i].flags & PTP_ENABLE_FEATURE)
+ ice_ptp_cfg_extts(pf, &pf->ptp.extts_rqs[i],
+ true);
}
/**
- * ice_ptp_cfg_clkout - Configure clock to generate periodic wave
- * @pf: Board private structure
- * @chan: GPIO channel (0-3)
- * @config: desired periodic clk configuration. NULL will disable channel
- * @store: If set to true the values will be stored
+ * ice_ptp_write_perout - Write periodic wave parameters to HW
+ * @hw: pointer to the HW struct
+ * @chan: target channel
+ * @gpio_pin: target GPIO pin
+ * @start: target time to start periodic output
+ * @period: target period
*
- * Configure the internal clock generator modules to generate the clock wave of
- * specified period.
+ * Return: 0 on success, negative error code otherwise
*/
-static int ice_ptp_cfg_clkout(struct ice_pf *pf, unsigned int chan,
- struct ice_perout_channel *config, bool store)
+static int ice_ptp_write_perout(struct ice_hw *hw, unsigned int chan,
+ unsigned int gpio_pin, u64 start, u64 period)
{
- u64 current_time, period, start_time, phase;
- struct ice_hw *hw = &pf->hw;
- u32 func, val, gpio_pin;
- u8 tmr_idx;
- if (config && config->flags & ~PTP_PEROUT_PHASE)
- return -EOPNOTSUPP;
-
- tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ u32 val = 0;
/* 0. Reset mode & out_en in AUX_OUT */
wr32(hw, GLTSYN_AUX_OUT(chan, tmr_idx), 0);
- /* If we're disabling the output, clear out CLKO and TGT and keep
- * output level low
- */
- if (!config || !config->ena) {
- wr32(hw, GLTSYN_CLKO(chan, tmr_idx), 0);
- wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), 0);
- wr32(hw, GLTSYN_TGT_H(chan, tmr_idx), 0);
-
- val = GLGEN_GPIO_CTL_PIN_DIR_M;
- gpio_pin = pf->ptp.perout_channels[chan].gpio_pin;
- wr32(hw, GLGEN_GPIO_CTL(gpio_pin), val);
-
- /* Store the value if requested */
- if (store)
- memset(&pf->ptp.perout_channels[chan], 0,
- sizeof(struct ice_perout_channel));
-
- return 0;
- }
- period = config->period;
- start_time = config->start_time;
- div64_u64_rem(start_time, period, &phase);
- gpio_pin = config->gpio_pin;
+ if (ice_is_e825c(hw)) {
+ int err;
- /* 1. Write clkout with half of required period value */
- if (period & 0x1) {
- dev_err(ice_pf_to_dev(pf), "CLK Period must be an even value\n");
- goto err;
+ /* Enable/disable CGU 1PPS output for E825C */
+ err = ice_cgu_cfg_pps_out(hw, !!period);
+ if (err)
+ return err;
}
+ /* 1. Write perout with half of required period value.
+ * HW toggles output when source clock hits the TGT and then adds
+ * GLTSYN_CLKO value to the target, so it ends up with 50% duty cycle.
+ */
period >>= 1;
- /* For proper operation, the GLTSYN_CLKO must be larger than clock tick
+ /* For proper operation, GLTSYN_CLKO must be larger than clock tick and
+ * period has to fit in 32 bit register.
*/
#define MIN_PULSE 3
- if (period <= MIN_PULSE || period > U32_MAX) {
- dev_err(ice_pf_to_dev(pf), "CLK Period must be > %d && < 2^33",
- MIN_PULSE * 2);
- goto err;
+ if (!!period && (period <= MIN_PULSE || period > U32_MAX)) {
+ dev_err(ice_hw_to_dev(hw), "CLK period ticks must be >= %d && <= 2^32",
+ MIN_PULSE);
+ return -EIO;
}
wr32(hw, GLTSYN_CLKO(chan, tmr_idx), lower_32_bits(period));
- /* Allow time for programming before start_time is hit */
- current_time = ice_ptp_read_src_clk_reg(pf, NULL);
-
- /* if start time is in the past start the timer at the nearest second
- * maintaining phase
- */
- if (start_time < current_time)
- start_time = roundup_u64(current_time, NSEC_PER_SEC) + phase;
-
- if (ice_is_e810(hw))
- start_time -= E810_OUT_PROP_DELAY_NS;
- else
- start_time -= ice_e82x_pps_delay(ice_e82x_time_ref(hw));
-
/* 2. Write TARGET time */
- wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), lower_32_bits(start_time));
- wr32(hw, GLTSYN_TGT_H(chan, tmr_idx), upper_32_bits(start_time));
+ wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), lower_32_bits(start));
+ wr32(hw, GLTSYN_TGT_H(chan, tmr_idx), upper_32_bits(start));
/* 3. Write AUX_OUT register */
- val = GLTSYN_AUX_OUT_0_OUT_ENA_M | GLTSYN_AUX_OUT_0_OUTMOD_M;
+ if (!!period)
+ val = GLTSYN_AUX_OUT_0_OUT_ENA_M | GLTSYN_AUX_OUT_0_OUTMOD_M;
wr32(hw, GLTSYN_AUX_OUT(chan, tmr_idx), val);
/* 4. write GPIO CTL reg */
- func = 8 + chan + (tmr_idx * 4);
- val = GLGEN_GPIO_CTL_PIN_DIR_M |
- FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M, func);
+ val = GLGEN_GPIO_CTL_PIN_DIR_M;
+ if (!!period)
+ val |= FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M,
+ 8 + chan + (tmr_idx * 4));
+
wr32(hw, GLGEN_GPIO_CTL(gpio_pin), val);
- /* Store the value if requested */
- if (store) {
- memcpy(&pf->ptp.perout_channels[chan], config,
- sizeof(struct ice_perout_channel));
- pf->ptp.perout_channels[chan].start_time = phase;
+ return 0;
+}
+
+/**
+ * ice_ptp_cfg_perout - Configure clock to generate periodic wave
+ * @pf: Board private structure
+ * @rq: Periodic output request
+ * @on: Enable/disable flag
+ *
+ * Configure the internal clock generator modules to generate the clock wave of
+ * specified period.
+ *
+ * Return: 0 on success, negative error code otherwise
+ */
+static int ice_ptp_cfg_perout(struct ice_pf *pf, struct ptp_perout_request *rq,
+ int on)
+{
+ u64 clk, period, start, phase;
+ struct ice_hw *hw = &pf->hw;
+ unsigned int gpio_pin;
+ int pin_desc_idx;
+
+ if (rq->flags & ~PTP_PEROUT_PHASE)
+ return -EOPNOTSUPP;
+
+ pin_desc_idx = ice_ptp_find_pin_idx(pf, PTP_PF_PEROUT, rq->index);
+ if (pin_desc_idx < 0)
+ return -EIO;
+
+ gpio_pin = pf->ptp.ice_pin_desc[pin_desc_idx].gpio[1];
+ period = rq->period.sec * NSEC_PER_SEC + rq->period.nsec;
+
+ /* If we're disabling the output or period is 0, clear out CLKO and TGT
+ * and keep output level low.
+ */
+ if (!on || !period)
+ return ice_ptp_write_perout(hw, rq->index, gpio_pin, 0, 0);
+
+ if (strncmp(pf->ptp.pin_desc[pin_desc_idx].name, "1PPS", 64) == 0 &&
+ period != NSEC_PER_SEC && hw->ptp.phy_model == ICE_PHY_E82X) {
+ dev_err(ice_pf_to_dev(pf), "1PPS pin supports only 1 s period\n");
+ return -EOPNOTSUPP;
}
- return 0;
-err:
- dev_err(ice_pf_to_dev(pf), "PTP failed to cfg per_clk\n");
- return -EFAULT;
+ if (period & 0x1) {
+ dev_err(ice_pf_to_dev(pf), "CLK Period must be an even value\n");
+ return -EIO;
+ }
+
+ start = rq->start.sec * NSEC_PER_SEC + rq->start.nsec;
+
+ /* If PTP_PEROUT_PHASE is set, rq has phase instead of start time */
+ if (rq->flags & PTP_PEROUT_PHASE)
+ phase = start;
+ else
+ div64_u64_rem(start, period, &phase);
+
+ /* If we have only phase or start time is in the past, start the timer
+ * at the next multiple of period, maintaining phase.
+ */
+ clk = ice_ptp_read_src_clk_reg(pf, NULL);
+ if (rq->flags & PTP_PEROUT_PHASE || start <= clk - ice_prop_delay(hw))
+ start = div64_u64(clk + period - 1, period) * period + phase;
+
+ /* Compensate for propagation delay from the generator to the pin. */
+ start -= ice_prop_delay(hw);
+
+ return ice_ptp_write_perout(hw, rq->index, gpio_pin, start, period);
}
/**
- * ice_ptp_disable_all_clkout - Disable all currently configured outputs
- * @pf: pointer to the PF structure
+ * ice_ptp_disable_all_perout - Disable all currently configured outputs
+ * @pf: Board private structure
*
* Disable all currently configured clock outputs. This is necessary before
- * certain changes to the PTP hardware clock. Use ice_ptp_enable_all_clkout to
+ * certain changes to the PTP hardware clock. Use ice_ptp_enable_all_perout to
* re-enable the clocks again.
*/
-static void ice_ptp_disable_all_clkout(struct ice_pf *pf)
+static void ice_ptp_disable_all_perout(struct ice_pf *pf)
{
- uint i;
-
- for (i = 0; i < pf->ptp.info.n_per_out; i++)
- if (pf->ptp.perout_channels[i].ena)
- ice_ptp_cfg_clkout(pf, i, NULL, false);
+ for (unsigned int i = 0; i < pf->ptp.info.n_per_out; i++)
+ if (pf->ptp.perout_rqs[i].period.sec ||
+ pf->ptp.perout_rqs[i].period.nsec)
+ ice_ptp_cfg_perout(pf, &pf->ptp.perout_rqs[i],
+ false);
}
/**
- * ice_ptp_enable_all_clkout - Enable all configured periodic clock outputs
- * @pf: pointer to the PF structure
+ * ice_ptp_enable_all_perout - Enable all configured periodic clock outputs
+ * @pf: Board private structure
*
* Enable all currently configured clock outputs. Use this after
- * ice_ptp_disable_all_clkout to reconfigure the output signals according to
+ * ice_ptp_disable_all_perout to reconfigure the output signals according to
* their configuration.
*/
-static void ice_ptp_enable_all_clkout(struct ice_pf *pf)
+static void ice_ptp_enable_all_perout(struct ice_pf *pf)
{
- uint i;
-
- for (i = 0; i < pf->ptp.info.n_per_out; i++)
- if (pf->ptp.perout_channels[i].ena)
- ice_ptp_cfg_clkout(pf, i, &pf->ptp.perout_channels[i],
- false);
+ for (unsigned int i = 0; i < pf->ptp.info.n_per_out; i++)
+ if (pf->ptp.perout_rqs[i].period.sec ||
+ pf->ptp.perout_rqs[i].period.nsec)
+ ice_ptp_cfg_perout(pf, &pf->ptp.perout_rqs[i],
+ true);
}
/**
- * ice_ptp_gpio_enable_e810 - Enable/disable ancillary features of PHC
- * @info: the driver's PTP info structure
- * @rq: The requested feature to change
- * @on: Enable/disable flag
+ * ice_ptp_disable_shared_pin - Disable enabled pin that shares GPIO
+ * @pf: Board private structure
+ * @pin: Pin index
+ * @func: Assigned function
+ *
+ * Return: 0 on success, negative error code otherwise
*/
-static int
-ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
- struct ptp_clock_request *rq, int on)
+static int ice_ptp_disable_shared_pin(struct ice_pf *pf, unsigned int pin,
+ enum ptp_pin_function func)
{
- struct ice_pf *pf = ptp_info_to_pf(info);
- bool sma_pres = false;
- unsigned int chan;
- u32 gpio_pin;
+ unsigned int gpio_pin;
- if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL))
- sma_pres = true;
+ switch (func) {
+ case PTP_PF_PEROUT:
+ gpio_pin = pf->ptp.ice_pin_desc[pin].gpio[1];
+ break;
+ case PTP_PF_EXTTS:
+ gpio_pin = pf->ptp.ice_pin_desc[pin].gpio[0];
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
- switch (rq->type) {
- case PTP_CLK_REQ_PEROUT:
- {
- struct ice_perout_channel clk_cfg = {};
-
- chan = rq->perout.index;
- if (sma_pres) {
- if (chan == ice_pin_desc_e810t[SMA1].chan)
- clk_cfg.gpio_pin = GPIO_20;
- else if (chan == ice_pin_desc_e810t[SMA2].chan)
- clk_cfg.gpio_pin = GPIO_22;
- else
- return -1;
- } else if (ice_is_e810t(&pf->hw)) {
- if (chan == 0)
- clk_cfg.gpio_pin = GPIO_20;
- else
- clk_cfg.gpio_pin = GPIO_22;
- } else if (chan == PPS_CLK_GEN_CHAN) {
- clk_cfg.gpio_pin = PPS_PIN_INDEX;
- } else {
- clk_cfg.gpio_pin = chan;
- }
+ for (unsigned int i = 0; i < pf->ptp.info.n_pins; i++) {
+ struct ptp_pin_desc *pin_desc = &pf->ptp.pin_desc[i];
+ unsigned int chan = pin_desc->chan;
- clk_cfg.flags = rq->perout.flags;
- clk_cfg.period = ((rq->perout.period.sec * NSEC_PER_SEC) +
- rq->perout.period.nsec);
- clk_cfg.start_time = ((rq->perout.start.sec * NSEC_PER_SEC) +
- rq->perout.start.nsec);
- clk_cfg.ena = !!on;
+ /* Skip pin idx from the request */
+ if (i == pin)
+ continue;
- return ice_ptp_cfg_clkout(pf, chan, &clk_cfg, true);
- }
- case PTP_CLK_REQ_EXTTS:
- {
- struct ice_extts_channel extts_cfg = {};
-
- chan = rq->extts.index;
- if (sma_pres) {
- if (chan < ice_pin_desc_e810t[SMA2].chan)
- gpio_pin = GPIO_21;
- else
- gpio_pin = GPIO_23;
- } else if (ice_is_e810t(&pf->hw)) {
- if (chan == 0)
- gpio_pin = GPIO_21;
- else
- gpio_pin = GPIO_23;
- } else {
- gpio_pin = chan;
+ if (pin_desc->func == PTP_PF_PEROUT &&
+ pf->ptp.ice_pin_desc[i].gpio[1] == gpio_pin) {
+ pf->ptp.perout_rqs[chan].period.sec = 0;
+ pf->ptp.perout_rqs[chan].period.nsec = 0;
+ pin_desc->func = PTP_PF_NONE;
+ pin_desc->chan = 0;
+ dev_dbg(ice_pf_to_dev(pf), "Disabling pin %u with shared output GPIO pin %u\n",
+ i, gpio_pin);
+ return ice_ptp_cfg_perout(pf, &pf->ptp.perout_rqs[chan],
+ false);
+ } else if (pf->ptp.pin_desc->func == PTP_PF_EXTTS &&
+ pf->ptp.ice_pin_desc[i].gpio[0] == gpio_pin) {
+ pf->ptp.extts_rqs[chan].flags &= ~PTP_ENABLE_FEATURE;
+ pin_desc->func = PTP_PF_NONE;
+ pin_desc->chan = 0;
+ dev_dbg(ice_pf_to_dev(pf), "Disabling pin %u with shared input GPIO pin %u\n",
+ i, gpio_pin);
+ return ice_ptp_cfg_extts(pf, &pf->ptp.extts_rqs[chan],
+ false);
}
+ }
- extts_cfg.flags = rq->extts.flags;
- extts_cfg.gpio_pin = gpio_pin;
- extts_cfg.ena = !!on;
+ return 0;
+}
- return ice_ptp_cfg_extts(pf, chan, &extts_cfg, true);
- }
+/**
+ * ice_verify_pin - verify if pin supports requested pin function
+ * @info: the driver's PTP info structure
+ * @pin: Pin index
+ * @func: Assigned function
+ * @chan: Assigned channel
+ *
+ * Return: 0 on success, -EOPNOTSUPP when function is not supported.
+ */
+static int ice_verify_pin(struct ptp_clock_info *info, unsigned int pin,
+ enum ptp_pin_function func, unsigned int chan)
+{
+ struct ice_pf *pf = ptp_info_to_pf(info);
+ const struct ice_ptp_pin_desc *pin_desc;
+
+ pin_desc = &pf->ptp.ice_pin_desc[pin];
+
+ /* Is assigned function allowed? */
+ switch (func) {
+ case PTP_PF_EXTTS:
+ if (pin_desc->gpio[0] < 0)
+ return -EOPNOTSUPP;
+ break;
+ case PTP_PF_PEROUT:
+ if (pin_desc->gpio[1] < 0)
+ return -EOPNOTSUPP;
+ break;
+ case PTP_PF_NONE:
+ break;
+ case PTP_PF_PHYSYNC:
default:
return -EOPNOTSUPP;
}
+
+ /* On adapters with SMA_CTRL disable other pins that share same GPIO */
+ if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL)) {
+ ice_ptp_disable_shared_pin(pf, pin, func);
+ pf->ptp.pin_desc[pin].func = func;
+ pf->ptp.pin_desc[pin].chan = chan;
+ return ice_ptp_set_sma_cfg(pf);
+ }
+
+ return 0;
}
/**
- * ice_ptp_gpio_enable_e823 - Enable/disable ancillary features of PHC
- * @info: the driver's PTP info structure
+ * ice_ptp_gpio_enable - Enable/disable ancillary features of PHC
+ * @info: The driver's PTP info structure
* @rq: The requested feature to change
* @on: Enable/disable flag
+ *
+ * Return: 0 on success, negative error code otherwise
*/
-static int ice_ptp_gpio_enable_e823(struct ptp_clock_info *info,
- struct ptp_clock_request *rq, int on)
+static int ice_ptp_gpio_enable(struct ptp_clock_info *info,
+ struct ptp_clock_request *rq, int on)
{
struct ice_pf *pf = ptp_info_to_pf(info);
+ int err;
switch (rq->type) {
- case PTP_CLK_REQ_PPS:
+ case PTP_CLK_REQ_PEROUT:
{
- struct ice_perout_channel clk_cfg = {};
+ struct ptp_perout_request *cached =
+ &pf->ptp.perout_rqs[rq->perout.index];
- clk_cfg.flags = rq->perout.flags;
- clk_cfg.gpio_pin = PPS_PIN_INDEX;
- clk_cfg.period = NSEC_PER_SEC;
- clk_cfg.ena = !!on;
-
- return ice_ptp_cfg_clkout(pf, PPS_CLK_GEN_CHAN, &clk_cfg, true);
+ err = ice_ptp_cfg_perout(pf, &rq->perout, on);
+ if (!err) {
+ *cached = rq->perout;
+ } else {
+ cached->period.sec = 0;
+ cached->period.nsec = 0;
+ }
+ return err;
}
case PTP_CLK_REQ_EXTTS:
{
- struct ice_extts_channel extts_cfg = {};
-
- extts_cfg.flags = rq->extts.flags;
- extts_cfg.gpio_pin = TIME_SYNC_PIN_INDEX;
- extts_cfg.ena = !!on;
+ struct ptp_extts_request *cached =
+ &pf->ptp.extts_rqs[rq->extts.index];
- return ice_ptp_cfg_extts(pf, rq->extts.index, &extts_cfg, true);
+ err = ice_ptp_cfg_extts(pf, &rq->extts, on);
+ if (!err)
+ *cached = rq->extts;
+ else
+ cached->flags &= ~PTP_ENABLE_FEATURE;
+ return err;
}
default:
return -EOPNOTSUPP;
@@ -2059,7 +2048,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
/* For Vernier mode on E82X, we need to recalibrate after new settime.
* Start with marking timestamps as invalid.
*/
- if (hw->ptp.phy_model == ICE_PHY_E82X) {
+ if (ice_get_phy_model(hw) == ICE_PHY_E82X) {
err = ice_ptp_clear_phy_offset_ready_e82x(hw);
if (err)
dev_warn(ice_pf_to_dev(pf), "Failed to mark timestamps as invalid before settime\n");
@@ -2071,7 +2060,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
}
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
err = ice_ptp_write_init(pf, &ts64);
ice_ptp_unlock(hw);
@@ -2080,10 +2069,10 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
ice_ptp_reset_cached_phctime(pf);
/* Reenable periodic outputs */
- ice_ptp_enable_all_clkout(pf);
+ ice_ptp_enable_all_perout(pf);
/* Recalibrate and re-enable timestamp blocks for E822/E823 */
- if (hw->ptp.phy_model == ICE_PHY_E82X)
+ if (ice_get_phy_model(hw) == ICE_PHY_E82X)
ice_ptp_restart_all_phy(pf);
exit:
if (err) {
@@ -2142,12 +2131,12 @@ static int ice_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
}
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
err = ice_ptp_write_adj(pf, delta);
/* Reenable periodic outputs */
- ice_ptp_enable_all_clkout(pf);
+ ice_ptp_enable_all_perout(pf);
ice_ptp_unlock(hw);
@@ -2405,20 +2394,41 @@ u64 ice_ptp_get_rx_hwts(const union ice_32b_rx_flex_desc *rx_desc,
}
/**
- * ice_ptp_disable_sma_pins_e810t - Disable E810-T SMA pins
+ * ice_ptp_setup_pin_cfg - setup PTP pin_config structure
+ * @pf: Board private structure
+ */
+static void ice_ptp_setup_pin_cfg(struct ice_pf *pf)
+{
+ for (unsigned int i = 0; i < pf->ptp.info.n_pins; i++) {
+ const struct ice_ptp_pin_desc *desc = &pf->ptp.ice_pin_desc[i];
+ struct ptp_pin_desc *pin = &pf->ptp.pin_desc[i];
+ const char *name = NULL;
+
+ if (!ice_is_feature_supported(pf, ICE_F_SMA_CTRL))
+ name = ice_pin_names[desc->name_idx];
+ else if (desc->name_idx != GPIO_NA)
+ name = ice_pin_names_nvm[desc->name_idx];
+ if (name)
+ strscpy(pin->name, name, sizeof(pin->name));
+
+ pin->index = i;
+ }
+
+ pf->ptp.info.pin_config = pf->ptp.pin_desc;
+}
+
+/**
+ * ice_ptp_disable_pins - Disable PTP pins
* @pf: pointer to the PF structure
- * @info: PTP clock info structure
*
* Disable the OS access to the SMA pins. Called to clear out the OS
- * indications of pin support when we fail to setup the E810-T SMA control
- * register.
+ * indications of pin support when we fail to setup the SMA control register.
*/
-static void
-ice_ptp_disable_sma_pins_e810t(struct ice_pf *pf, struct ptp_clock_info *info)
+static void ice_ptp_disable_pins(struct ice_pf *pf)
{
- struct device *dev = ice_pf_to_dev(pf);
+ struct ptp_clock_info *info = &pf->ptp.info;
- dev_warn(dev, "Failed to configure E810-T SMA pin control\n");
+ dev_warn(ice_pf_to_dev(pf), "Failed to configure PTP pin control\n");
info->enable = NULL;
info->verify = NULL;
@@ -2428,126 +2438,158 @@ ice_ptp_disable_sma_pins_e810t(struct ice_pf *pf, struct ptp_clock_info *info)
}
/**
- * ice_ptp_setup_sma_pins_e810t - Setup the SMA pins
+ * ice_ptp_parse_sdp_entries - update ice_ptp_pin_desc structure from NVM
* @pf: pointer to the PF structure
- * @info: PTP clock info structure
+ * @entries: SDP connection section from NVM
+ * @num_entries: number of valid entries in sdp_entries
+ * @pins: PTP pins array to update
*
- * Finish setting up the SMA pins by allocating pin_config, and setting it up
- * according to the current status of the SMA. On failure, disable all of the
- * extended SMA pin support.
+ * Return: 0 on success, negative error code otherwise.
*/
-static void
-ice_ptp_setup_sma_pins_e810t(struct ice_pf *pf, struct ptp_clock_info *info)
+static int ice_ptp_parse_sdp_entries(struct ice_pf *pf, __le16 *entries,
+ unsigned int num_entries,
+ struct ice_ptp_pin_desc *pins)
{
- struct device *dev = ice_pf_to_dev(pf);
- int err;
+ unsigned int n_pins = 0;
+ unsigned int i;
- /* Allocate memory for kernel pins interface */
- info->pin_config = devm_kcalloc(dev, info->n_pins,
- sizeof(*info->pin_config), GFP_KERNEL);
- if (!info->pin_config) {
- ice_ptp_disable_sma_pins_e810t(pf, info);
- return;
- }
+ /* Setup ice_pin_desc array */
+ for (i = 0; i < ICE_N_PINS_MAX; i++) {
+ pins[i].name_idx = -1;
+ pins[i].gpio[0] = -1;
+ pins[i].gpio[1] = -1;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ u16 entry = le16_to_cpu(entries[i]);
+ DECLARE_BITMAP(bitmap, GPIO_NA);
+ unsigned int bitmap_idx;
+ bool dir;
+ u16 gpio;
+
+ *bitmap = FIELD_GET(ICE_AQC_NVM_SDP_AC_PIN_M, entry);
+ dir = !!FIELD_GET(ICE_AQC_NVM_SDP_AC_DIR_M, entry);
+ gpio = FIELD_GET(ICE_AQC_NVM_SDP_AC_SDP_NUM_M, entry);
+ for_each_set_bit(bitmap_idx, bitmap, GPIO_NA + 1) {
+ unsigned int idx;
+
+ /* Check if entry's pin bit is valid */
+ if (bitmap_idx >= NUM_PTP_PINS_NVM &&
+ bitmap_idx != GPIO_NA)
+ continue;
- /* Read current SMA status */
- err = ice_get_sma_config_e810t(&pf->hw, info->pin_config);
- if (err)
- ice_ptp_disable_sma_pins_e810t(pf, info);
-}
+ /* Check if pin already exists */
+ for (idx = 0; idx < ICE_N_PINS_MAX; idx++)
+ if (pins[idx].name_idx == bitmap_idx)
+ break;
+
+ if (idx == ICE_N_PINS_MAX) {
+ /* Pin not found, setup its entry and name */
+ idx = n_pins++;
+ pins[idx].name_idx = bitmap_idx;
+ if (bitmap_idx == GPIO_NA)
+ strscpy(pf->ptp.pin_desc[idx].name,
+ ice_pin_names[gpio],
+ sizeof(pf->ptp.pin_desc[idx]
+ .name));
+ }
-/**
- * ice_ptp_setup_pins_e810 - Setup PTP pins in sysfs
- * @pf: pointer to the PF instance
- * @info: PTP clock capabilities
- */
-static void
-ice_ptp_setup_pins_e810(struct ice_pf *pf, struct ptp_clock_info *info)
-{
- if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL)) {
- info->n_ext_ts = N_EXT_TS_E810;
- info->n_per_out = N_PER_OUT_E810T;
- info->n_pins = NUM_PTP_PINS_E810T;
- info->verify = ice_verify_pin_e810t;
-
- /* Complete setup of the SMA pins */
- ice_ptp_setup_sma_pins_e810t(pf, info);
- } else if (ice_is_e810t(&pf->hw)) {
- info->n_ext_ts = N_EXT_TS_NO_SMA_E810T;
- info->n_per_out = N_PER_OUT_NO_SMA_E810T;
- } else {
- info->n_per_out = N_PER_OUT_E810;
- info->n_ext_ts = N_EXT_TS_E810;
+ /* Setup in/out GPIO number */
+ pins[idx].gpio[dir] = gpio;
+ }
}
-}
-/**
- * ice_ptp_setup_pins_e823 - Setup PTP pins in sysfs
- * @pf: pointer to the PF instance
- * @info: PTP clock capabilities
- */
-static void
-ice_ptp_setup_pins_e823(struct ice_pf *pf, struct ptp_clock_info *info)
-{
- info->pps = 1;
- info->n_per_out = 0;
- info->n_ext_ts = 1;
+ for (i = 0; i < n_pins; i++) {
+ dev_dbg(ice_pf_to_dev(pf),
+ "NVM pin entry[%d] : name_idx %d gpio_out %d gpio_in %d\n",
+ i, pins[i].name_idx, pins[i].gpio[1], pins[i].gpio[0]);
+ }
+
+ pf->ptp.info.n_pins = n_pins;
+ return 0;
}
/**
- * ice_ptp_set_funcs_e82x - Set specialized functions for E82x support
+ * ice_ptp_set_funcs_e82x - Set specialized functions for E82X support
* @pf: Board private structure
- * @info: PTP info to fill
*
- * Assign functions to the PTP capabiltiies structure for E82x devices.
+ * Assign functions to the PTP capabilities structure for E82X devices.
* Functions which operate across all device families should be set directly
- * in ice_ptp_set_caps. Only add functions here which are distinct for E82x
+ * in ice_ptp_set_caps. Only add functions here which are distinct for E82X
* devices.
*/
-static void
-ice_ptp_set_funcs_e82x(struct ice_pf *pf, struct ptp_clock_info *info)
+static void ice_ptp_set_funcs_e82x(struct ice_pf *pf)
{
#ifdef CONFIG_ICE_HWTS
if (boot_cpu_has(X86_FEATURE_ART) &&
boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
- info->getcrosststamp = ice_ptp_getcrosststamp_e82x;
+ pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp_e82x;
+
#endif /* CONFIG_ICE_HWTS */
+ if (ice_is_e825c(&pf->hw)) {
+ pf->ptp.ice_pin_desc = ice_pin_desc_e825c;
+ pf->ptp.info.n_pins = ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e825c);
+ } else {
+ pf->ptp.ice_pin_desc = ice_pin_desc_e82x;
+ pf->ptp.info.n_pins = ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e82x);
+ }
+ ice_ptp_setup_pin_cfg(pf);
}
/**
* ice_ptp_set_funcs_e810 - Set specialized functions for E810 support
* @pf: Board private structure
- * @info: PTP info to fill
*
* Assign functions to the PTP capabiltiies structure for E810 devices.
* Functions which operate across all device families should be set directly
- * in ice_ptp_set_caps. Only add functions here which are distinct for e810
+ * in ice_ptp_set_caps. Only add functions here which are distinct for E810
* devices.
*/
-static void
-ice_ptp_set_funcs_e810(struct ice_pf *pf, struct ptp_clock_info *info)
+static void ice_ptp_set_funcs_e810(struct ice_pf *pf)
{
- info->enable = ice_ptp_gpio_enable_e810;
- ice_ptp_setup_pins_e810(pf, info);
-}
+ __le16 entries[ICE_AQC_NVM_SDP_AC_MAX_SIZE];
+ struct ice_ptp_pin_desc *desc = NULL;
+ struct ice_ptp *ptp = &pf->ptp;
+ unsigned int num_entries;
+ int err;
-/**
- * ice_ptp_set_funcs_e823 - Set specialized functions for E823 support
- * @pf: Board private structure
- * @info: PTP info to fill
- *
- * Assign functions to the PTP capabiltiies structure for E823 devices.
- * Functions which operate across all device families should be set directly
- * in ice_ptp_set_caps. Only add functions here which are distinct for e823
- * devices.
- */
-static void
-ice_ptp_set_funcs_e823(struct ice_pf *pf, struct ptp_clock_info *info)
-{
- ice_ptp_set_funcs_e82x(pf, info);
+ err = ice_ptp_read_sdp_ac(&pf->hw, entries, &num_entries);
+ if (err) {
+ /* SDP section does not exist in NVM or is corrupted */
+ if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL)) {
+ ptp->ice_pin_desc = ice_pin_desc_e810_sma;
+ ptp->info.n_pins =
+ ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e810_sma);
+ } else {
+ pf->ptp.ice_pin_desc = ice_pin_desc_e810;
+ pf->ptp.info.n_pins =
+ ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e810);
+ err = 0;
+ }
+ } else {
+ desc = devm_kcalloc(ice_pf_to_dev(pf), ICE_N_PINS_MAX,
+ sizeof(struct ice_ptp_pin_desc),
+ GFP_KERNEL);
+ if (!desc)
+ goto err;
- info->enable = ice_ptp_gpio_enable_e823;
- ice_ptp_setup_pins_e823(pf, info);
+ err = ice_ptp_parse_sdp_entries(pf, entries, num_entries, desc);
+ if (err)
+ goto err;
+
+ ptp->ice_pin_desc = (const struct ice_ptp_pin_desc *)desc;
+ }
+
+ ptp->info.pin_config = ptp->pin_desc;
+ ice_ptp_setup_pin_cfg(pf);
+
+ if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL))
+ err = ice_ptp_set_sma_cfg(pf);
+err:
+ if (err) {
+ devm_kfree(ice_pf_to_dev(pf), desc);
+ ice_ptp_disable_pins(pf);
+ }
}
/**
@@ -2567,13 +2609,15 @@ static void ice_ptp_set_caps(struct ice_pf *pf)
info->adjfine = ice_ptp_adjfine;
info->gettimex64 = ice_ptp_gettimex64;
info->settime64 = ice_ptp_settime64;
+ info->n_per_out = GLTSYN_TGT_H_IDX_MAX;
+ info->n_ext_ts = GLTSYN_EVNT_H_IDX_MAX;
+ info->enable = ice_ptp_gpio_enable;
+ info->verify = ice_verify_pin;
if (ice_is_e810(&pf->hw))
- ice_ptp_set_funcs_e810(pf, info);
- else if (ice_is_e823(&pf->hw))
- ice_ptp_set_funcs_e823(pf, info);
+ ice_ptp_set_funcs_e810(pf);
else
- ice_ptp_set_funcs_e82x(pf, info);
+ ice_ptp_set_funcs_e82x(pf);
}
/**
@@ -2775,7 +2819,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
src_tmr = ice_get_ptp_src_clock_index(&pf->hw);
@@ -2813,10 +2857,8 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf)
/* Write the increment time value to PHY and LAN */
err = ice_ptp_write_incval(hw, ice_base_incval(pf));
- if (err) {
- ice_ptp_unlock(hw);
- return err;
- }
+ if (err)
+ goto err_unlock;
/* Write the initial Time value to PHY and LAN using the cached PHC
* time before the reset and time difference between stopping and
@@ -2829,10 +2871,8 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf)
ts = ktime_to_timespec64(ktime_get_real());
}
err = ice_ptp_write_init(pf, &ts);
- if (err) {
- ice_ptp_unlock(hw);
- return err;
- }
+ if (err)
+ goto err_unlock;
/* Release the global hardware lock */
ice_ptp_unlock(hw);
@@ -2852,10 +2892,14 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf)
}
/* Re-enable all periodic outputs and external timestamp events */
- ice_ptp_enable_all_clkout(pf);
+ ice_ptp_enable_all_perout(pf);
ice_ptp_enable_all_extts(pf);
return 0;
+
+err_unlock:
+ ice_ptp_unlock(hw);
+ return err;
}
/**
@@ -2895,187 +2939,49 @@ err:
dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
}
-/**
- * ice_ptp_aux_dev_to_aux_pf - Get auxiliary PF handle for the auxiliary device
- * @aux_dev: auxiliary device to get the auxiliary PF for
- */
-static struct ice_pf *
-ice_ptp_aux_dev_to_aux_pf(struct auxiliary_device *aux_dev)
-{
- struct ice_ptp_port *aux_port;
- struct ice_ptp *aux_ptp;
-
- aux_port = container_of(aux_dev, struct ice_ptp_port, aux_dev);
- aux_ptp = container_of(aux_port, struct ice_ptp, port);
-
- return container_of(aux_ptp, struct ice_pf, ptp);
-}
-
-/**
- * ice_ptp_aux_dev_to_owner_pf - Get PF handle for the auxiliary device
- * @aux_dev: auxiliary device to get the PF for
- */
-static struct ice_pf *
-ice_ptp_aux_dev_to_owner_pf(struct auxiliary_device *aux_dev)
+static bool ice_is_primary(struct ice_hw *hw)
{
- struct ice_ptp_port_owner *ports_owner;
- const struct auxiliary_driver *aux_drv;
- struct ice_ptp *owner_ptp;
-
- if (!aux_dev->dev.driver)
- return NULL;
-
- aux_drv = to_auxiliary_drv(aux_dev->dev.driver);
- ports_owner = container_of(aux_drv, struct ice_ptp_port_owner,
- aux_driver);
- owner_ptp = container_of(ports_owner, struct ice_ptp, ports_owner);
- return container_of(owner_ptp, struct ice_pf, ptp);
+ return ice_is_e825c(hw) && ice_is_dual(hw) ?
+ !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M) : true;
}
-/**
- * ice_ptp_auxbus_probe - Probe auxiliary devices
- * @aux_dev: PF's auxiliary device
- * @id: Auxiliary device ID
- */
-static int ice_ptp_auxbus_probe(struct auxiliary_device *aux_dev,
- const struct auxiliary_device_id *id)
+static int ice_ptp_setup_adapter(struct ice_pf *pf)
{
- struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev);
- struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev);
-
- if (WARN_ON(!owner_pf))
- return -ENODEV;
+ if (!ice_pf_src_tmr_owned(pf) || !ice_is_primary(&pf->hw))
+ return -EPERM;
- INIT_LIST_HEAD(&aux_pf->ptp.port.list_member);
- mutex_lock(&owner_pf->ptp.ports_owner.lock);
- list_add(&aux_pf->ptp.port.list_member,
- &owner_pf->ptp.ports_owner.ports);
- mutex_unlock(&owner_pf->ptp.ports_owner.lock);
+ pf->adapter->ctrl_pf = pf;
return 0;
}
-/**
- * ice_ptp_auxbus_remove - Remove auxiliary devices from the bus
- * @aux_dev: PF's auxiliary device
- */
-static void ice_ptp_auxbus_remove(struct auxiliary_device *aux_dev)
+static int ice_ptp_setup_pf(struct ice_pf *pf)
{
- struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev);
- struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev);
+ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
+ struct ice_ptp *ptp = &pf->ptp;
- mutex_lock(&owner_pf->ptp.ports_owner.lock);
- list_del(&aux_pf->ptp.port.list_member);
- mutex_unlock(&owner_pf->ptp.ports_owner.lock);
-}
+ if (WARN_ON(!ctrl_ptp) || ice_get_phy_model(&pf->hw) == ICE_PHY_UNSUP)
+ return -ENODEV;
-/**
- * ice_ptp_auxbus_shutdown
- * @aux_dev: PF's auxiliary device
- */
-static void ice_ptp_auxbus_shutdown(struct auxiliary_device *aux_dev)
-{
- /* Doing nothing here, but handle to auxbus driver must be satisfied */
-}
+ INIT_LIST_HEAD(&ptp->port.list_node);
+ mutex_lock(&pf->adapter->ports.lock);
-/**
- * ice_ptp_auxbus_suspend
- * @aux_dev: PF's auxiliary device
- * @state: power management state indicator
- */
-static int
-ice_ptp_auxbus_suspend(struct auxiliary_device *aux_dev, pm_message_t state)
-{
- /* Doing nothing here, but handle to auxbus driver must be satisfied */
- return 0;
-}
+ list_add(&ptp->port.list_node,
+ &pf->adapter->ports.ports);
+ mutex_unlock(&pf->adapter->ports.lock);
-/**
- * ice_ptp_auxbus_resume
- * @aux_dev: PF's auxiliary device
- */
-static int ice_ptp_auxbus_resume(struct auxiliary_device *aux_dev)
-{
- /* Doing nothing here, but handle to auxbus driver must be satisfied */
return 0;
}
-/**
- * ice_ptp_auxbus_create_id_table - Create auxiliary device ID table
- * @pf: Board private structure
- * @name: auxiliary bus driver name
- */
-static struct auxiliary_device_id *
-ice_ptp_auxbus_create_id_table(struct ice_pf *pf, const char *name)
-{
- struct auxiliary_device_id *ids;
-
- /* Second id left empty to terminate the array */
- ids = devm_kcalloc(ice_pf_to_dev(pf), 2,
- sizeof(struct auxiliary_device_id), GFP_KERNEL);
- if (!ids)
- return NULL;
-
- snprintf(ids[0].name, sizeof(ids[0].name), "ice.%s", name);
-
- return ids;
-}
-
-/**
- * ice_ptp_register_auxbus_driver - Register PTP auxiliary bus driver
- * @pf: Board private structure
- */
-static int ice_ptp_register_auxbus_driver(struct ice_pf *pf)
+static void ice_ptp_cleanup_pf(struct ice_pf *pf)
{
- struct auxiliary_driver *aux_driver;
- struct ice_ptp *ptp;
- struct device *dev;
- char *name;
- int err;
-
- ptp = &pf->ptp;
- dev = ice_pf_to_dev(pf);
- aux_driver = &ptp->ports_owner.aux_driver;
- INIT_LIST_HEAD(&ptp->ports_owner.ports);
- mutex_init(&ptp->ports_owner.lock);
- name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u",
- pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn),
- ice_get_ptp_src_clock_index(&pf->hw));
- if (!name)
- return -ENOMEM;
-
- aux_driver->name = name;
- aux_driver->shutdown = ice_ptp_auxbus_shutdown;
- aux_driver->suspend = ice_ptp_auxbus_suspend;
- aux_driver->remove = ice_ptp_auxbus_remove;
- aux_driver->resume = ice_ptp_auxbus_resume;
- aux_driver->probe = ice_ptp_auxbus_probe;
- aux_driver->id_table = ice_ptp_auxbus_create_id_table(pf, name);
- if (!aux_driver->id_table)
- return -ENOMEM;
+ struct ice_ptp *ptp = &pf->ptp;
- err = auxiliary_driver_register(aux_driver);
- if (err) {
- devm_kfree(dev, aux_driver->id_table);
- dev_err(dev, "Failed registering aux_driver, name <%s>\n",
- name);
+ if (ice_get_phy_model(&pf->hw) != ICE_PHY_UNSUP) {
+ mutex_lock(&pf->adapter->ports.lock);
+ list_del(&ptp->port.list_node);
+ mutex_unlock(&pf->adapter->ports.lock);
}
-
- return err;
-}
-
-/**
- * ice_ptp_unregister_auxbus_driver - Unregister PTP auxiliary bus driver
- * @pf: Board private structure
- */
-static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
-{
- struct auxiliary_driver *aux_driver = &pf->ptp.ports_owner.aux_driver;
-
- auxiliary_driver_unregister(aux_driver);
- devm_kfree(ice_pf_to_dev(pf), aux_driver->id_table);
-
- mutex_destroy(&pf->ptp.ports_owner.lock);
}
/**
@@ -3087,15 +2993,12 @@ static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
*/
int ice_ptp_clock_index(struct ice_pf *pf)
{
- struct auxiliary_device *aux_dev;
- struct ice_pf *owner_pf;
+ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
struct ptp_clock *clock;
- aux_dev = &pf->ptp.port.aux_dev;
- owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev);
- if (!owner_pf)
+ if (!ctrl_ptp)
return -1;
- clock = owner_pf->ptp.clock;
+ clock = ctrl_ptp->clock;
return clock ? ptp_clock_index(clock) : -1;
}
@@ -3129,18 +3032,14 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
/* Write the increment time value to PHY and LAN */
err = ice_ptp_write_incval(hw, ice_base_incval(pf));
- if (err) {
- ice_ptp_unlock(hw);
- goto err_exit;
- }
+ if (err)
+ goto err_unlock;
ts = ktime_to_timespec64(ktime_get_real());
/* Write the initial Time value to PHY and LAN */
err = ice_ptp_write_init(pf, &ts);
- if (err) {
- ice_ptp_unlock(hw);
- goto err_exit;
- }
+ if (err)
+ goto err_unlock;
/* Release the global hardware lock */
ice_ptp_unlock(hw);
@@ -3155,19 +3054,15 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
if (err)
goto err_clk;
- err = ice_ptp_register_auxbus_driver(pf);
- if (err) {
- dev_err(ice_pf_to_dev(pf), "Failed to register PTP auxbus driver");
- goto err_aux;
- }
-
return 0;
-err_aux:
- ptp_clock_unregister(pf->ptp.clock);
err_clk:
pf->ptp.clock = NULL;
err_exit:
return err;
+
+err_unlock:
+ ice_ptp_unlock(hw);
+ return err;
}
/**
@@ -3209,7 +3104,7 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
mutex_init(&ptp_port->ps_lock);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_ptp_init_tx_eth56g(pf, &ptp_port->tx,
ptp_port->port_num);
@@ -3227,76 +3122,6 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
}
/**
- * ice_ptp_release_auxbus_device
- * @dev: device that utilizes the auxbus
- */
-static void ice_ptp_release_auxbus_device(struct device *dev)
-{
- /* Doing nothing here, but handle to auxbux device must be satisfied */
-}
-
-/**
- * ice_ptp_create_auxbus_device - Create PTP auxiliary bus device
- * @pf: Board private structure
- */
-static int ice_ptp_create_auxbus_device(struct ice_pf *pf)
-{
- struct auxiliary_device *aux_dev;
- struct ice_ptp *ptp;
- struct device *dev;
- char *name;
- int err;
- u32 id;
-
- ptp = &pf->ptp;
- id = ptp->port.port_num;
- dev = ice_pf_to_dev(pf);
-
- aux_dev = &ptp->port.aux_dev;
-
- name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u",
- pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn),
- ice_get_ptp_src_clock_index(&pf->hw));
- if (!name)
- return -ENOMEM;
-
- aux_dev->name = name;
- aux_dev->id = id;
- aux_dev->dev.release = ice_ptp_release_auxbus_device;
- aux_dev->dev.parent = dev;
-
- err = auxiliary_device_init(aux_dev);
- if (err)
- goto aux_err;
-
- err = auxiliary_device_add(aux_dev);
- if (err) {
- auxiliary_device_uninit(aux_dev);
- goto aux_err;
- }
-
- return 0;
-aux_err:
- dev_err(dev, "Failed to create PTP auxiliary bus device <%s>\n", name);
- devm_kfree(dev, name);
- return err;
-}
-
-/**
- * ice_ptp_remove_auxbus_device - Remove PTP auxiliary bus device
- * @pf: Board private structure
- */
-static void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
-{
- struct auxiliary_device *aux_dev = &pf->ptp.port.aux_dev;
-
- auxiliary_device_delete(aux_dev);
- auxiliary_device_uninit(aux_dev);
-
- memset(aux_dev, 0, sizeof(*aux_dev));
-}
-
-/**
* ice_ptp_init_tx_interrupt_mode - Initialize device Tx interrupt mode
* @pf: Board private structure
*
@@ -3307,7 +3132,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
*/
static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf)
{
- switch (pf->hw.ptp.phy_model) {
+ switch (ice_get_phy_model(&pf->hw)) {
case ICE_PHY_E82X:
/* E822 based PHY has the clock owner process the interrupt
* for all ports.
@@ -3350,19 +3175,26 @@ void ice_ptp_init(struct ice_pf *pf)
/* If this function owns the clock hardware, it must allocate and
* configure the PTP clock device to represent it.
*/
- if (ice_pf_src_tmr_owned(pf)) {
+ if (ice_pf_src_tmr_owned(pf) && ice_is_primary(hw)) {
+ err = ice_ptp_setup_adapter(pf);
+ if (err)
+ goto err_exit;
err = ice_ptp_init_owner(pf);
if (err)
- goto err;
+ goto err_exit;
}
+ err = ice_ptp_setup_pf(pf);
+ if (err)
+ goto err_exit;
+
ptp->port.port_num = hw->pf_id;
if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
ptp->port.port_num = hw->pf_id * 2;
err = ice_ptp_init_port(pf, &ptp->port);
if (err)
- goto err;
+ goto err_exit;
/* Start the PHY timestamping block */
ice_ptp_reset_phy_timestamping(pf);
@@ -3370,20 +3202,16 @@ void ice_ptp_init(struct ice_pf *pf)
/* Configure initial Tx interrupt settings */
ice_ptp_cfg_tx_interrupt(pf);
- err = ice_ptp_create_auxbus_device(pf);
- if (err)
- goto err;
-
ptp->state = ICE_PTP_READY;
err = ice_ptp_init_work(pf, ptp);
if (err)
- goto err;
+ goto err_exit;
dev_info(ice_pf_to_dev(pf), "PTP init successful\n");
return;
-err:
+err_exit:
/* If we registered a PTP clock, release it */
if (pf->ptp.clock) {
ptp_clock_unregister(ptp->clock);
@@ -3410,7 +3238,7 @@ void ice_ptp_release(struct ice_pf *pf)
/* Disable timestamping for both Tx and Rx */
ice_ptp_disable_timestamp_mode(pf);
- ice_ptp_remove_auxbus_device(pf);
+ ice_ptp_cleanup_pf(pf);
ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
@@ -3425,14 +3253,11 @@ void ice_ptp_release(struct ice_pf *pf)
pf->ptp.kworker = NULL;
}
- if (ice_pf_src_tmr_owned(pf))
- ice_ptp_unregister_auxbus_driver(pf);
-
if (!pf->ptp.clock)
return;
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
ptp_clock_unregister(pf->ptp.clock);
pf->ptp.clock = NULL;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 2db2257a0fb2..824e73b677a4 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -9,37 +9,6 @@
#include "ice_ptp_hw.h"
-enum ice_ptp_pin_e810 {
- GPIO_20 = 0,
- GPIO_21,
- GPIO_22,
- GPIO_23,
- NUM_PTP_PIN_E810
-};
-
-enum ice_ptp_pin_e810t {
- GNSS = 0,
- SMA1,
- UFL1,
- SMA2,
- UFL2,
- NUM_PTP_PINS_E810T
-};
-
-struct ice_perout_channel {
- bool ena;
- u32 gpio_pin;
- u32 flags;
- u64 period;
- u64 start_time;
-};
-
-struct ice_extts_channel {
- bool ena;
- u32 gpio_pin;
- u32 flags;
-};
-
/* The ice hardware captures Tx hardware timestamps in the PHY. The timestamp
* is stored in a buffer of registers. Depending on the specific hardware,
* this buffer might be shared across multiple PHY ports.
@@ -169,9 +138,8 @@ struct ice_ptp_tx {
* ready for PTP functionality. It is used to track the port initialization
* and determine when the port's PHY offset is valid.
*
- * @list_member: list member structure of auxiliary device
+ * @list_node: list member structure
* @tx: Tx timestamp tracking for this port
- * @aux_dev: auxiliary device associated with this port
* @ov_work: delayed work task for tracking when PHY offset is valid
* @ps_lock: mutex used to protect the overall PTP PHY start procedure
* @link_up: indicates whether the link is up
@@ -179,9 +147,8 @@ struct ice_ptp_tx {
* @port_num: the port number this structure represents
*/
struct ice_ptp_port {
- struct list_head list_member;
+ struct list_head list_node;
struct ice_ptp_tx tx;
- struct auxiliary_device aux_dev;
struct kthread_delayed_work ov_work;
struct mutex ps_lock; /* protects overall PTP PHY start procedure */
bool link_up;
@@ -195,22 +162,6 @@ enum ice_ptp_tx_interrupt {
ICE_PTP_TX_INTERRUPT_ALL,
};
-/**
- * struct ice_ptp_port_owner - data used to handle the PTP clock owner info
- *
- * This structure contains data necessary for the PTP clock owner to correctly
- * handle the timestamping feature for all attached ports.
- *
- * @aux_driver: the structure carring the auxiliary driver information
- * @ports: list of porst handled by this port owner
- * @lock: protect access to ports list
- */
-struct ice_ptp_port_owner {
- struct auxiliary_driver aux_driver;
- struct list_head ports;
- struct mutex lock;
-};
-
#define GLTSYN_TGT_H_IDX_MAX 4
enum ice_ptp_state {
@@ -221,20 +172,69 @@ enum ice_ptp_state {
ICE_PTP_ERROR,
};
+enum ice_ptp_pin {
+ SDP0 = 0,
+ SDP1,
+ SDP2,
+ SDP3,
+ TIME_SYNC,
+ ONE_PPS
+};
+
+enum ice_ptp_pin_nvm {
+ GNSS = 0,
+ SMA1,
+ UFL1,
+ SMA2,
+ UFL2,
+ NUM_PTP_PINS_NVM,
+ GPIO_NA = 9
+};
+
+/* Per-channel register definitions */
+#define GLTSYN_AUX_OUT(_chan, _idx) (GLTSYN_AUX_OUT_0(_idx) + ((_chan) * 8))
+#define GLTSYN_AUX_IN(_chan, _idx) (GLTSYN_AUX_IN_0(_idx) + ((_chan) * 8))
+#define GLTSYN_CLKO(_chan, _idx) (GLTSYN_CLKO_0(_idx) + ((_chan) * 8))
+#define GLTSYN_TGT_L(_chan, _idx) (GLTSYN_TGT_L_0(_idx) + ((_chan) * 16))
+#define GLTSYN_TGT_H(_chan, _idx) (GLTSYN_TGT_H_0(_idx) + ((_chan) * 16))
+#define GLTSYN_EVNT_L(_chan, _idx) (GLTSYN_EVNT_L_0(_idx) + ((_chan) * 16))
+#define GLTSYN_EVNT_H(_chan, _idx) (GLTSYN_EVNT_H_0(_idx) + ((_chan) * 16))
+#define GLTSYN_EVNT_H_IDX_MAX 3
+
+/* Pin definitions for PTP */
+#define ICE_N_PINS_MAX 6
+#define ICE_SMA_PINS_NUM 4
+#define ICE_PIN_DESC_ARR_LEN(_arr) (sizeof(_arr) / \
+ sizeof(struct ice_ptp_pin_desc))
+
+/**
+ * struct ice_ptp_pin_desc - hardware pin description data
+ * @name_idx: index of the name of pin in ice_pin_names
+ * @gpio: the associated GPIO input and output pins
+ *
+ * Structure describing a PTP-capable GPIO pin that extends ptp_pin_desc array
+ * for the device. Device families have separate sets of available pins with
+ * varying restrictions.
+ */
+struct ice_ptp_pin_desc {
+ int name_idx;
+ int gpio[2];
+};
+
/**
* struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK
* @state: current state of PTP state machine
* @tx_interrupt_mode: the TX interrupt mode for the PTP clock
* @port: data for the PHY port initialization procedure
- * @ports_owner: data for the auxiliary driver owner
* @work: delayed work function for periodic tasks
* @cached_phc_time: a cached copy of the PHC time for timestamp extension
* @cached_phc_jiffies: jiffies when cached_phc_time was last updated
- * @ext_ts_chan: the external timestamp channel in use
- * @ext_ts_irq: the external timestamp IRQ in use
* @kworker: kwork thread for handling periodic work
- * @perout_channels: periodic output data
- * @extts_channels: channels for external timestamps
+ * @ext_ts_irq: the external timestamp IRQ in use
+ * @pin_desc: structure defining pins
+ * @ice_pin_desc: internal structure describing pin relations
+ * @perout_rqs: cached periodic output requests
+ * @extts_rqs: cached external timestamp requests
* @info: structure defining PTP hardware capabilities
* @clock: pointer to registered PTP clock device
* @tstamp_config: hardware timestamping configuration
@@ -250,15 +250,15 @@ struct ice_ptp {
enum ice_ptp_state state;
enum ice_ptp_tx_interrupt tx_interrupt_mode;
struct ice_ptp_port port;
- struct ice_ptp_port_owner ports_owner;
struct kthread_delayed_work work;
u64 cached_phc_time;
unsigned long cached_phc_jiffies;
- u8 ext_ts_chan;
- u8 ext_ts_irq;
struct kthread_worker *kworker;
- struct ice_perout_channel perout_channels[GLTSYN_TGT_H_IDX_MAX];
- struct ice_extts_channel extts_channels[GLTSYN_TGT_H_IDX_MAX];
+ u8 ext_ts_irq;
+ struct ptp_pin_desc pin_desc[ICE_N_PINS_MAX];
+ const struct ice_ptp_pin_desc *ice_pin_desc;
+ struct ptp_perout_request perout_rqs[GLTSYN_TGT_H_IDX_MAX];
+ struct ptp_extts_request extts_rqs[GLTSYN_EVNT_H_IDX_MAX];
struct ptp_clock_info info;
struct ptp_clock *clock;
struct hwtstamp_config tstamp_config;
@@ -289,27 +289,6 @@ struct ice_ptp {
#define FIFO_EMPTY BIT(2)
#define FIFO_OK 0xFF
#define ICE_PTP_FIFO_NUM_CHECKS 5
-/* Per-channel register definitions */
-#define GLTSYN_AUX_OUT(_chan, _idx) (GLTSYN_AUX_OUT_0(_idx) + ((_chan) * 8))
-#define GLTSYN_AUX_IN(_chan, _idx) (GLTSYN_AUX_IN_0(_idx) + ((_chan) * 8))
-#define GLTSYN_CLKO(_chan, _idx) (GLTSYN_CLKO_0(_idx) + ((_chan) * 8))
-#define GLTSYN_TGT_L(_chan, _idx) (GLTSYN_TGT_L_0(_idx) + ((_chan) * 16))
-#define GLTSYN_TGT_H(_chan, _idx) (GLTSYN_TGT_H_0(_idx) + ((_chan) * 16))
-#define GLTSYN_EVNT_L(_chan, _idx) (GLTSYN_EVNT_L_0(_idx) + ((_chan) * 16))
-#define GLTSYN_EVNT_H(_chan, _idx) (GLTSYN_EVNT_H_0(_idx) + ((_chan) * 16))
-#define GLTSYN_EVNT_H_IDX_MAX 3
-
-/* Pin definitions for PTP PPS out */
-#define PPS_CLK_GEN_CHAN 3
-#define PPS_CLK_SRC_CHAN 2
-#define PPS_PIN_INDEX 5
-#define TIME_SYNC_PIN_INDEX 4
-#define N_EXT_TS_E810 3
-#define N_PER_OUT_E810 4
-#define N_PER_OUT_E810T 3
-#define N_PER_OUT_NO_SMA_E810T 2
-#define N_EXT_TS_NO_SMA_E810T 2
-#define ETH_GLTSYN_ENA(_i) (0x03000348 + ((_i) * 4))
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
int ice_ptp_clock_index(struct ice_pf *pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
index e6980b94a6c1..585ce200c60f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
@@ -334,7 +334,7 @@ struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD] = {
* reference. See the struct ice_time_ref_info_e82x for information about the
* meaning of each constant.
*/
-const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ] = {
+const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
/* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */
{
/* pll_freq */
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
index ec8db830ac73..dfd49732bd5b 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
@@ -659,6 +659,29 @@ static int ice_cfg_cgu_pll_e825c(struct ice_hw *hw,
return 0;
}
+#define ICE_ONE_PPS_OUT_AMP_MAX 3
+
+/**
+ * ice_cgu_cfg_pps_out - Configure 1PPS output from CGU
+ * @hw: pointer to the HW struct
+ * @enable: true to enable 1PPS output, false to disable it
+ *
+ * Return: 0 on success, other negative error code when CGU read/write failed
+ */
+int ice_cgu_cfg_pps_out(struct ice_hw *hw, bool enable)
+{
+ union nac_cgu_dword9 dw9;
+ int err;
+
+ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD9, &dw9.val);
+ if (err)
+ return err;
+
+ dw9.one_pps_out_en = enable;
+ dw9.one_pps_out_amp = enable * ICE_ONE_PPS_OUT_AMP_MAX;
+ return ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD9, dw9.val);
+}
+
/**
* ice_cfg_cgu_pll_dis_sticky_bits_e82x - disable TS PLL sticky bits
* @hw: pointer to the HW struct
@@ -804,7 +827,7 @@ static u32 ice_ptp_tmr_cmd_to_port_reg(struct ice_hw *hw,
/* Certain hardware families share the same register values for the
* port register and source timer register.
*/
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_E810:
return ice_ptp_tmr_cmd_to_src_reg(hw, cmd) & TS_CMD_MASK_E810;
default:
@@ -5148,9 +5171,9 @@ ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready)
return 0;
}
-/* E810T SMA functions
+/* E810 SMA functions
*
- * The following functions operate specifically on E810T hardware and are used
+ * The following functions operate specifically on E810 hardware and are used
* to access the extended GPIOs available.
*/
@@ -5217,14 +5240,14 @@ ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle)
}
/**
- * ice_read_sma_ctrl_e810t
+ * ice_read_sma_ctrl
* @hw: pointer to the hw struct
* @data: pointer to data to be read from the GPIO controller
*
* Read the SMA controller state. It is connected to pins 3-7 of Port 1 of the
* PCA9575 expander, so only bits 3-7 in data are valid.
*/
-int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data)
+int ice_read_sma_ctrl(struct ice_hw *hw, u8 *data)
{
int status;
u16 handle;
@@ -5236,7 +5259,7 @@ int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data)
*data = 0;
- for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) {
+ for (i = ICE_SMA_MIN_BIT; i <= ICE_SMA_MAX_BIT; i++) {
bool pin;
status = ice_aq_get_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET,
@@ -5250,14 +5273,14 @@ int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data)
}
/**
- * ice_write_sma_ctrl_e810t
+ * ice_write_sma_ctrl
* @hw: pointer to the hw struct
* @data: data to be written to the GPIO controller
*
* Write the data to the SMA controller. It is connected to pins 3-7 of Port 1
* of the PCA9575 expander, so only bits 3-7 in data are valid.
*/
-int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data)
+int ice_write_sma_ctrl(struct ice_hw *hw, u8 data)
{
int status;
u16 handle;
@@ -5267,7 +5290,7 @@ int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data)
if (status)
return status;
- for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) {
+ for (i = ICE_SMA_MIN_BIT; i <= ICE_SMA_MAX_BIT; i++) {
bool pin;
pin = !(data & (1 << i));
@@ -5281,14 +5304,14 @@ int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data)
}
/**
- * ice_read_pca9575_reg_e810t
+ * ice_read_pca9575_reg
* @hw: pointer to the hw struct
* @offset: GPIO controller register offset
* @data: pointer to data to be read from the GPIO controller
*
* Read the register from the GPIO controller
*/
-int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data)
+int ice_read_pca9575_reg(struct ice_hw *hw, u8 offset, u8 *data)
{
struct ice_aqc_link_topo_addr link_topo;
__le16 addr;
@@ -5312,6 +5335,66 @@ int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data)
}
/**
+ * ice_ptp_read_sdp_ac - read SDP available connections section from NVM
+ * @hw: pointer to the HW struct
+ * @entries: returns the SDP available connections section from NVM
+ * @num_entries: returns the number of valid entries
+ *
+ * Return: 0 on success, negative error code if NVM read failed or section does
+ * not exist or is corrupted
+ */
+int ice_ptp_read_sdp_ac(struct ice_hw *hw, __le16 *entries, uint *num_entries)
+{
+ __le16 data;
+ u32 offset;
+ int err;
+
+ err = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (err)
+ goto exit;
+
+ /* Read the offset of SDP_AC */
+ offset = ICE_AQC_NVM_SDP_AC_PTR_OFFSET;
+ err = ice_aq_read_nvm(hw, 0, offset, sizeof(data), &data, false, true,
+ NULL);
+ if (err)
+ goto exit;
+
+ /* Check if section exist */
+ offset = FIELD_GET(ICE_AQC_NVM_SDP_AC_PTR_M, le16_to_cpu(data));
+ if (offset == ICE_AQC_NVM_SDP_AC_PTR_INVAL) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ if (offset & ICE_AQC_NVM_SDP_AC_PTR_TYPE_M) {
+ offset &= ICE_AQC_NVM_SDP_AC_PTR_M;
+ offset *= ICE_AQC_NVM_SECTOR_UNIT;
+ } else {
+ offset *= sizeof(data);
+ }
+
+ /* Skip reading section length and read the number of valid entries */
+ offset += sizeof(data);
+ err = ice_aq_read_nvm(hw, 0, offset, sizeof(data), &data, false, true,
+ NULL);
+ if (err)
+ goto exit;
+ *num_entries = le16_to_cpu(data);
+
+ /* Read SDP configuration section */
+ offset += sizeof(data);
+ err = ice_aq_read_nvm(hw, 0, offset, *num_entries * sizeof(data),
+ entries, false, true, NULL);
+
+exit:
+ if (err)
+ dev_dbg(ice_hw_to_dev(hw), "Failed to configure SDP connection section\n");
+ ice_release_nvm(hw);
+ return err;
+}
+
+/**
* ice_ptp_init_phy_e810 - initialize PHY parameters
* @ptp: pointer to the PTP HW struct
*/
@@ -5417,7 +5500,7 @@ void ice_ptp_init_hw(struct ice_hw *hw)
static int ice_ptp_write_port_cmd(struct ice_hw *hw, u8 port,
enum ice_ptp_tmr_cmd cmd)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_ptp_write_port_cmd_eth56g(hw, port, cmd);
case ICE_PHY_E82X:
@@ -5482,7 +5565,7 @@ static int ice_ptp_port_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
u32 port;
/* PHY models which can program all ports simultaneously */
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_E810:
return ice_ptp_port_cmd_e810(hw, cmd);
default:
@@ -5561,7 +5644,7 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
/* PHY timers */
/* Fill Rx and Tx ports and send msg to PHY */
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_ptp_prep_phy_time_eth56g(hw,
(u32)(time & 0xFFFFFFFF));
@@ -5607,7 +5690,7 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval));
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval));
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_ptp_prep_phy_incval_eth56g(hw, incval);
break;
@@ -5676,7 +5759,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0);
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_ptp_prep_phy_adj_eth56g(hw, adj);
break;
@@ -5709,7 +5792,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
*/
int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_read_ptp_tstamp_eth56g(hw, block, idx, tstamp);
case ICE_PHY_E810:
@@ -5739,7 +5822,7 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
*/
int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_clear_ptp_tstamp_eth56g(hw, block, idx);
case ICE_PHY_E810:
@@ -5802,7 +5885,7 @@ static int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx)
*/
void ice_ptp_reset_ts_memory(struct ice_hw *hw)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
ice_ptp_reset_ts_memory_eth56g(hw);
break;
@@ -5831,7 +5914,7 @@ int ice_ptp_init_phc(struct ice_hw *hw)
/* Clear event err indications for auxiliary pins */
(void)rd32(hw, GLTSYN_STAT(src_idx));
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_ptp_init_phc_eth56g(hw);
case ICE_PHY_E810:
@@ -5856,7 +5939,7 @@ int ice_ptp_init_phc(struct ice_hw *hw)
*/
int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_get_phy_tx_tstamp_ready_eth56g(hw, block,
tstamp_ready);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
index 6cedc1a906af..47af7c5c79b8 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
@@ -316,7 +316,7 @@ ice_cgu_pll_params_e825c e825c_cgu_params[NUM_ICE_TIME_REF_FREQ];
extern const struct ice_phy_reg_info_eth56g eth56g_phy_res[NUM_ETH56G_PHY_RES];
/* Table of constants related to possible TIME_REF sources */
-extern const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ];
+extern const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ];
/* Table of constants for Vernier calibration on E822 */
extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
@@ -326,10 +326,12 @@ extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
*/
#define ICE_E810_PLL_FREQ 812500000
#define ICE_PTP_NOMINAL_INCVAL_E810 0x13b13b13bULL
-#define E810_OUT_PROP_DELAY_NS 1
+#define ICE_E810_OUT_PROP_DELAY_NS 1
+#define ICE_E825C_OUT_PROP_DELAY_NS 11
/* Device agnostic functions */
u8 ice_get_ptp_src_clock_index(struct ice_hw *hw);
+int ice_cgu_cfg_pps_out(struct ice_hw *hw, bool enable);
bool ice_ptp_lock(struct ice_hw *hw);
void ice_ptp_unlock(struct ice_hw *hw);
void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd);
@@ -358,7 +360,7 @@ void ice_ptp_reset_ts_memory_quad_e82x(struct ice_hw *hw, u8 quad);
*
* Returns the current TIME_REF from the capabilities structure.
*/
-static inline enum ice_time_ref_freq ice_e82x_time_ref(struct ice_hw *hw)
+static inline enum ice_time_ref_freq ice_e82x_time_ref(const struct ice_hw *hw)
{
return hw->func_caps.ts_func_info.time_ref;
}
@@ -379,17 +381,17 @@ ice_set_e82x_time_ref(struct ice_hw *hw, enum ice_time_ref_freq time_ref)
static inline u64 ice_e82x_pll_freq(enum ice_time_ref_freq time_ref)
{
- return e822_time_ref[time_ref].pll_freq;
+ return e82x_time_ref[time_ref].pll_freq;
}
static inline u64 ice_e82x_nominal_incval(enum ice_time_ref_freq time_ref)
{
- return e822_time_ref[time_ref].nominal_incval;
+ return e82x_time_ref[time_ref].nominal_incval;
}
static inline u64 ice_e82x_pps_delay(enum ice_time_ref_freq time_ref)
{
- return e822_time_ref[time_ref].pps_delay;
+ return e82x_time_ref[time_ref].pps_delay;
}
/* E822 Vernier calibration functions */
@@ -400,10 +402,10 @@ int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port);
int ice_phy_cfg_intr_e82x(struct ice_hw *hw, u8 quad, bool ena, u8 threshold);
/* E810 family functions */
-int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data);
-int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data);
-int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data);
-bool ice_is_pca9575_present(struct ice_hw *hw);
+int ice_read_sma_ctrl(struct ice_hw *hw, u8 *data);
+int ice_write_sma_ctrl(struct ice_hw *hw, u8 data);
+int ice_read_pca9575_reg(struct ice_hw *hw, u8 offset, u8 *data);
+int ice_ptp_read_sdp_ac(struct ice_hw *hw, __le16 *entries, uint *num_entries);
int ice_cgu_get_num_pins(struct ice_hw *hw, bool input);
enum dpll_pin_type ice_cgu_get_pin_type(struct ice_hw *hw, u8 pin, bool input);
struct dpll_pin_frequency *
@@ -421,8 +423,6 @@ int ice_cgu_get_output_pin_state_caps(struct ice_hw *hw, u8 pin_id,
int ice_ptp_read_tx_hwtstamp_status_eth56g(struct ice_hw *hw, u32 *ts_status);
int ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset);
int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port);
-int ice_phy_cfg_tx_offset_eth56g(struct ice_hw *hw, u8 port);
-int ice_phy_cfg_rx_offset_eth56g(struct ice_hw *hw, u8 port);
int ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold);
int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port);
@@ -432,6 +432,20 @@ int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port);
#define ICE_ETH56G_NOMINAL_THRESH4 0x7777
#define ICE_ETH56G_NOMINAL_TX_THRESH 0x6
+static inline u64 ice_prop_delay(const struct ice_hw *hw)
+{
+ switch (hw->ptp.phy_model) {
+ case ICE_PHY_ETH56G:
+ return ICE_E825C_OUT_PROP_DELAY_NS;
+ case ICE_PHY_E810:
+ return ICE_E810_OUT_PROP_DELAY_NS;
+ case ICE_PHY_E82X:
+ return ice_e82x_pps_delay(ice_e82x_time_ref(hw));
+ default:
+ return 0;
+ }
+}
+
/**
* ice_get_base_incval - Get base clock increment value
* @hw: pointer to the HW struct
@@ -452,6 +466,11 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
}
}
+static inline bool ice_is_dual(struct ice_hw *hw)
+{
+ return !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_DUAL_M);
+}
+
#define PFTSYN_SEM_BYTES 4
#define ICE_PTP_CLOCK_INDEX_0 0x00
@@ -689,30 +708,27 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
#define LOW_TX_MEMORY_BANK_START 0x03090000
#define HIGH_TX_MEMORY_BANK_START 0x03090004
-/* E810T SMA controller pin control */
-#define ICE_SMA1_DIR_EN_E810T BIT(4)
-#define ICE_SMA1_TX_EN_E810T BIT(5)
-#define ICE_SMA2_UFL2_RX_DIS_E810T BIT(3)
-#define ICE_SMA2_DIR_EN_E810T BIT(6)
-#define ICE_SMA2_TX_EN_E810T BIT(7)
-
-#define ICE_SMA1_MASK_E810T (ICE_SMA1_DIR_EN_E810T | \
- ICE_SMA1_TX_EN_E810T)
-#define ICE_SMA2_MASK_E810T (ICE_SMA2_UFL2_RX_DIS_E810T | \
- ICE_SMA2_DIR_EN_E810T | \
- ICE_SMA2_TX_EN_E810T)
-#define ICE_ALL_SMA_MASK_E810T (ICE_SMA1_MASK_E810T | \
- ICE_SMA2_MASK_E810T)
-
-#define ICE_SMA_MIN_BIT_E810T 3
-#define ICE_SMA_MAX_BIT_E810T 7
+/* SMA controller pin control */
+#define ICE_SMA1_DIR_EN BIT(4)
+#define ICE_SMA1_TX_EN BIT(5)
+#define ICE_SMA2_UFL2_RX_DIS BIT(3)
+#define ICE_SMA2_DIR_EN BIT(6)
+#define ICE_SMA2_TX_EN BIT(7)
+
+#define ICE_SMA1_MASK (ICE_SMA1_DIR_EN | ICE_SMA1_TX_EN)
+#define ICE_SMA2_MASK (ICE_SMA2_UFL2_RX_DIS | ICE_SMA2_DIR_EN | \
+ ICE_SMA2_TX_EN)
+#define ICE_ALL_SMA_MASK (ICE_SMA1_MASK | ICE_SMA2_MASK)
+
+#define ICE_SMA_MIN_BIT 3
+#define ICE_SMA_MAX_BIT 7
#define ICE_PCA9575_P1_OFFSET 8
-/* E810T PCA9575 IO controller registers */
+/* PCA9575 IO controller registers */
#define ICE_PCA9575_P0_IN 0x0
-/* E810T PCA9575 IO controller pin control */
-#define ICE_E810T_P0_GNSS_PRSNT_N BIT(4)
+/* PCA9575 IO controller pin control */
+#define ICE_P0_GNSS_PRSNT_N BIT(4)
/* ETH56G PHY register addresses */
/* Timestamp PHY incval registers */
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 91cb393f616f..b83f99c01d91 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -194,7 +194,8 @@ void ice_free_vfs(struct ice_pf *pf)
}
/* clear malicious info since the VF is getting released */
- list_del(&vf->mbx_info.list_entry);
+ if (!ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
+ list_del(&vf->mbx_info.list_entry);
mutex_unlock(&vf->cfg_lock);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index 8208055d6e7f..5d2d7736fd5f 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -1352,14 +1352,14 @@ static void ice_net_dim(struct ice_q_vector *q_vector)
struct dim_sample dim_sample;
__ice_update_sample(q_vector, tx, &dim_sample, true);
- net_dim(&tx->dim, dim_sample);
+ net_dim(&tx->dim, &dim_sample);
}
if (ITR_IS_DYNAMIC(rx)) {
struct dim_sample dim_sample;
__ice_update_sample(q_vector, rx, &dim_sample, false);
- net_dim(&rx->dim, dim_sample);
+ net_dim(&rx->dim, &dim_sample);
}
}
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
index feba314a3fe4..cb347c852ba9 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
@@ -359,8 +359,9 @@ struct ice_rx_ring {
struct ice_rx_ring *next; /* pointer to next ring in q_vector */
struct xsk_buff_pool *xsk_pool;
u32 nr_frags;
- dma_addr_t dma; /* physical address of ring */
+ u16 max_frame;
u16 rx_buf_len;
+ dma_addr_t dma; /* physical address of ring */
u8 dcb_tc; /* Traffic class of ring */
u8 ptp_rx;
#define ICE_RX_FLAGS_RING_BUILD_SKB BIT(1)
@@ -406,6 +407,7 @@ struct ice_tx_ring {
#define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2)
u8 flags;
u8 dcb_tc; /* Traffic class of ring */
+ u16 quanta_prof_id;
} ____cacheline_internodealigned_in_smp;
static inline bool ice_ring_uses_build_skb(struct ice_rx_ring *ring)
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h
index afcead4baef4..79f960c6680d 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h
@@ -154,7 +154,6 @@ static inline u32 ice_set_rs_bit(const struct ice_tx_ring *xdp_ring)
}
void ice_finalize_xdp_rx(struct ice_tx_ring *xdp_ring, unsigned int xdp_res, u32 first_idx);
-int ice_xmit_xdp_buff(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring);
int __ice_xmit_xdp_ring(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring,
bool frame);
void ice_release_rx_desc(struct ice_rx_ring *rx_ring, u16 val);
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index 45768796691f..adb168860711 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -905,6 +905,7 @@ struct ice_hw {
u8 revision_id;
u8 pf_id; /* device profile info */
+ u8 logical_pf_id;
u16 max_burst_size; /* driver sets this value */
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
index 8c434689e3f7..c7c0c2f50c26 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
@@ -717,6 +717,23 @@ ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m)
}
/**
+ * ice_reset_vf_mbx_cnt - reset VF mailbox message count
+ * @vf: pointer to the VF structure
+ *
+ * This function clears the VF mailbox message count, and should be called on
+ * VF reset.
+ */
+static void ice_reset_vf_mbx_cnt(struct ice_vf *vf)
+{
+ struct ice_pf *pf = vf->pf;
+
+ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
+ ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
+ else
+ ice_mbx_clear_malvf(&vf->mbx_info);
+}
+
+/**
* ice_reset_all_vfs - reset all allocated VFs in one go
* @pf: pointer to the PF structure
*
@@ -742,7 +759,7 @@ void ice_reset_all_vfs(struct ice_pf *pf)
/* clear all malicious info if the VFs are getting reset */
ice_for_each_vf(pf, bkt, vf)
- ice_mbx_clear_malvf(&vf->mbx_info);
+ ice_reset_vf_mbx_cnt(vf);
/* If VFs have been disabled, there is no need to reset */
if (test_and_set_bit(ICE_VF_DIS, pf->state)) {
@@ -958,7 +975,7 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
ice_eswitch_update_repr(&vf->repr_id, vsi);
/* if the VF has been reset allow it to come up again */
- ice_mbx_clear_malvf(&vf->mbx_info);
+ ice_reset_vf_mbx_cnt(vf);
out_unlock:
if (lag && lag->bonded && lag->primary &&
@@ -1011,7 +1028,10 @@ void ice_initialize_vf_entry(struct ice_vf *vf)
ice_vf_fdir_init(vf);
/* Initialize mailbox info for this VF */
- ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
+ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
+ ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
+ else
+ ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
mutex_init(&vf->cfg_lock);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
index be4266899690..4261fe1c2bcd 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
@@ -59,6 +59,13 @@ struct ice_fdir_prof_info {
u64 fdir_active_cnt;
};
+struct ice_vf_qs_bw {
+ u32 committed;
+ u32 peak;
+ u16 queue_id;
+ u8 tc;
+};
+
/* VF operations */
struct ice_vf_ops {
enum ice_disq_rst_src reset_type;
@@ -140,6 +147,7 @@ struct ice_vf {
struct devlink_port devlink_port;
u16 num_msix; /* num of MSI-X configured on this VF */
+ struct ice_vf_qs_bw qs_bw[ICE_MAX_RSS_QS_PER_VF];
};
/* Flags for controlling behavior of ice_reset_vf */
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_mbx.c b/drivers/net/ethernet/intel/ice/ice_vf_mbx.c
index 40cb4ba0789c..75c8113e58ee 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_mbx.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_mbx.c
@@ -211,6 +211,38 @@ ice_mbx_detect_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info,
}
/**
+ * ice_mbx_vf_dec_trig_e830 - Decrements the VF mailbox queue counter
+ * @hw: pointer to the HW struct
+ * @event: pointer to the control queue receive event
+ *
+ * This function triggers to decrement the counter
+ * MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT when the driver replenishes
+ * the buffers at the PF mailbox queue.
+ */
+void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
+ const struct ice_rq_event_info *event)
+{
+ u16 vfid = le16_to_cpu(event->desc.retval);
+
+ wr32(hw, E830_MBX_VF_DEC_TRIG(vfid), 1);
+}
+
+/**
+ * ice_mbx_vf_clear_cnt_e830 - Clear the VF mailbox queue count
+ * @hw: pointer to the HW struct
+ * @vf_id: VF ID in the PF space
+ *
+ * This function clears the counter MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT, and should
+ * be called when a VF is created and on VF reset.
+ */
+void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id)
+{
+ u32 reg = rd32(hw, E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(vf_id));
+
+ wr32(hw, E830_MBX_VF_DEC_TRIG(vf_id), reg);
+}
+
+/**
* ice_mbx_vf_state_handler - Handle states of the overflow algorithm
* @hw: pointer to the HW struct
* @mbx_data: pointer to structure containing mailbox data
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_mbx.h b/drivers/net/ethernet/intel/ice/ice_vf_mbx.h
index 44bc030d17e0..684de89e5c5e 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_mbx.h
+++ b/drivers/net/ethernet/intel/ice/ice_vf_mbx.h
@@ -19,6 +19,9 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
u8 *msg, u16 msglen, struct ice_sq_cd *cd);
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed);
+void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
+ const struct ice_rq_event_info *event);
+void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id);
int
ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data,
struct ice_mbx_vf_info *vf_info, bool *report_malvf);
@@ -47,5 +50,11 @@ static inline void ice_mbx_init_snapshot(struct ice_hw *hw)
{
}
+static inline void
+ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
+ const struct ice_rq_event_info *event)
+{
+}
+
#endif /* CONFIG_PCI_IOV */
#endif /* _ICE_VF_MBX_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
index 59f62306b9cb..f445e33b2028 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
@@ -495,6 +495,9 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_USO)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_USO;
+ if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_QOS)
+ vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_QOS;
+
vfres->num_vsis = 1;
/* Tx and Rx queue are equal for VF */
vfres->num_queue_pairs = vsi->num_txq;
@@ -1035,6 +1038,191 @@ error_param:
}
/**
+ * ice_vc_get_qos_caps - Get current QoS caps from PF
+ * @vf: pointer to the VF info
+ *
+ * Get VF's QoS capabilities, such as TC number, arbiter and
+ * bandwidth from PF.
+ *
+ * Return: 0 on success or negative error value.
+ */
+static int ice_vc_get_qos_caps(struct ice_vf *vf)
+{
+ enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
+ struct virtchnl_qos_cap_list *cap_list = NULL;
+ u8 tc_prio[ICE_MAX_TRAFFIC_CLASS] = { 0 };
+ struct virtchnl_qos_cap_elem *cfg = NULL;
+ struct ice_vsi_ctx *vsi_ctx;
+ struct ice_pf *pf = vf->pf;
+ struct ice_port_info *pi;
+ struct ice_vsi *vsi;
+ u8 numtc, tc;
+ u16 len = 0;
+ int ret, i;
+
+ if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ vsi = ice_get_vf_vsi(vf);
+ if (!vsi) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ pi = pf->hw.port_info;
+ numtc = vsi->tc_cfg.numtc;
+
+ vsi_ctx = ice_get_vsi_ctx(pi->hw, vf->lan_vsi_idx);
+ if (!vsi_ctx) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ len = struct_size(cap_list, cap, numtc);
+ cap_list = kzalloc(len, GFP_KERNEL);
+ if (!cap_list) {
+ v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
+ len = 0;
+ goto err;
+ }
+
+ cap_list->vsi_id = vsi->vsi_num;
+ cap_list->num_elem = numtc;
+
+ /* Store the UP2TC configuration from DCB to a user priority bitmap
+ * of each TC. Each element of prio_of_tc represents one TC. Each
+ * bitmap indicates the user priorities belong to this TC.
+ */
+ for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) {
+ tc = pi->qos_cfg.local_dcbx_cfg.etscfg.prio_table[i];
+ tc_prio[tc] |= BIT(i);
+ }
+
+ for (i = 0; i < numtc; i++) {
+ cfg = &cap_list->cap[i];
+ cfg->tc_num = i;
+ cfg->tc_prio = tc_prio[i];
+ cfg->arbiter = pi->qos_cfg.local_dcbx_cfg.etscfg.tsatable[i];
+ cfg->weight = VIRTCHNL_STRICT_WEIGHT;
+ cfg->type = VIRTCHNL_BW_SHAPER;
+ cfg->shaper.committed = vsi_ctx->sched.bw_t_info[i].cir_bw.bw;
+ cfg->shaper.peak = vsi_ctx->sched.bw_t_info[i].eir_bw.bw;
+ }
+
+err:
+ ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_QOS_CAPS, v_ret,
+ (u8 *)cap_list, len);
+ kfree(cap_list);
+ return ret;
+}
+
+/**
+ * ice_vf_cfg_qs_bw - Configure per queue bandwidth
+ * @vf: pointer to the VF info
+ * @num_queues: number of queues to be configured
+ *
+ * Configure per queue bandwidth.
+ *
+ * Return: 0 on success or negative error value.
+ */
+static int ice_vf_cfg_qs_bw(struct ice_vf *vf, u16 num_queues)
+{
+ struct ice_hw *hw = &vf->pf->hw;
+ struct ice_vsi *vsi;
+ int ret;
+ u16 i;
+
+ vsi = ice_get_vf_vsi(vf);
+ if (!vsi)
+ return -EINVAL;
+
+ for (i = 0; i < num_queues; i++) {
+ u32 p_rate, min_rate;
+ u8 tc;
+
+ p_rate = vf->qs_bw[i].peak;
+ min_rate = vf->qs_bw[i].committed;
+ tc = vf->qs_bw[i].tc;
+ if (p_rate)
+ ret = ice_cfg_q_bw_lmt(hw->port_info, vsi->idx, tc,
+ vf->qs_bw[i].queue_id,
+ ICE_MAX_BW, p_rate);
+ else
+ ret = ice_cfg_q_bw_dflt_lmt(hw->port_info, vsi->idx, tc,
+ vf->qs_bw[i].queue_id,
+ ICE_MAX_BW);
+ if (ret)
+ return ret;
+
+ if (min_rate)
+ ret = ice_cfg_q_bw_lmt(hw->port_info, vsi->idx, tc,
+ vf->qs_bw[i].queue_id,
+ ICE_MIN_BW, min_rate);
+ else
+ ret = ice_cfg_q_bw_dflt_lmt(hw->port_info, vsi->idx, tc,
+ vf->qs_bw[i].queue_id,
+ ICE_MIN_BW);
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ice_vf_cfg_q_quanta_profile - Configure quanta profile
+ * @vf: pointer to the VF info
+ * @quanta_prof_idx: pointer to the quanta profile index
+ * @quanta_size: quanta size to be set
+ *
+ * This function chooses available quanta profile and configures the register.
+ * The quanta profile is evenly divided by the number of device ports, and then
+ * available to the specific PF and VFs. The first profile for each PF is a
+ * reserved default profile. Only quanta size of the rest unused profile can be
+ * modified.
+ *
+ * Return: 0 on success or negative error value.
+ */
+static int ice_vf_cfg_q_quanta_profile(struct ice_vf *vf, u16 quanta_size,
+ u16 *quanta_prof_idx)
+{
+ const u16 n_desc = calc_quanta_desc(quanta_size);
+ struct ice_hw *hw = &vf->pf->hw;
+ const u16 n_cmd = 2 * n_desc;
+ struct ice_pf *pf = vf->pf;
+ u16 per_pf, begin_id;
+ u8 n_used;
+ u32 reg;
+
+ begin_id = (GLCOMM_QUANTA_PROF_MAX_INDEX + 1) / hw->dev_caps.num_funcs *
+ hw->logical_pf_id;
+
+ if (quanta_size == ICE_DFLT_QUANTA) {
+ *quanta_prof_idx = begin_id;
+ } else {
+ per_pf = (GLCOMM_QUANTA_PROF_MAX_INDEX + 1) /
+ hw->dev_caps.num_funcs;
+ n_used = pf->num_quanta_prof_used;
+ if (n_used < per_pf) {
+ *quanta_prof_idx = begin_id + 1 + n_used;
+ pf->num_quanta_prof_used++;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ reg = FIELD_PREP(GLCOMM_QUANTA_PROF_QUANTA_SIZE_M, quanta_size) |
+ FIELD_PREP(GLCOMM_QUANTA_PROF_MAX_CMD_M, n_cmd) |
+ FIELD_PREP(GLCOMM_QUANTA_PROF_MAX_DESC_M, n_desc);
+ wr32(hw, GLCOMM_QUANTA_PROF(*quanta_prof_idx), reg);
+
+ return 0;
+}
+
+/**
* ice_vc_cfg_promiscuous_mode_msg
* @vf: pointer to the VF info
* @msg: pointer to the msg buffer
@@ -1636,6 +1824,141 @@ error_param:
}
/**
+ * ice_vc_cfg_q_bw - Configure per queue bandwidth
+ * @vf: pointer to the VF info
+ * @msg: pointer to the msg buffer which holds the command descriptor
+ *
+ * Configure VF queues bandwidth.
+ *
+ * Return: 0 on success or negative error value.
+ */
+static int ice_vc_cfg_q_bw(struct ice_vf *vf, u8 *msg)
+{
+ enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
+ struct virtchnl_queues_bw_cfg *qbw =
+ (struct virtchnl_queues_bw_cfg *)msg;
+ struct ice_vsi *vsi;
+ u16 i;
+
+ if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
+ !ice_vc_isvalid_vsi_id(vf, qbw->vsi_id)) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ vsi = ice_get_vf_vsi(vf);
+ if (!vsi) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ if (qbw->num_queues > ICE_MAX_RSS_QS_PER_VF ||
+ qbw->num_queues > min_t(u16, vsi->alloc_txq, vsi->alloc_rxq)) {
+ dev_err(ice_pf_to_dev(vf->pf), "VF-%d trying to configure more than allocated number of queues: %d\n",
+ vf->vf_id, min_t(u16, vsi->alloc_txq, vsi->alloc_rxq));
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ for (i = 0; i < qbw->num_queues; i++) {
+ if (qbw->cfg[i].shaper.peak != 0 && vf->max_tx_rate != 0 &&
+ qbw->cfg[i].shaper.peak > vf->max_tx_rate)
+ dev_warn(ice_pf_to_dev(vf->pf), "The maximum queue %d rate limit configuration may not take effect because the maximum TX rate for VF-%d is %d\n",
+ qbw->cfg[i].queue_id, vf->vf_id,
+ vf->max_tx_rate);
+ if (qbw->cfg[i].shaper.committed != 0 && vf->min_tx_rate != 0 &&
+ qbw->cfg[i].shaper.committed < vf->min_tx_rate)
+ dev_warn(ice_pf_to_dev(vf->pf), "The minimum queue %d rate limit configuration may not take effect because the minimum TX rate for VF-%d is %d\n",
+ qbw->cfg[i].queue_id, vf->vf_id,
+ vf->max_tx_rate);
+ }
+
+ for (i = 0; i < qbw->num_queues; i++) {
+ vf->qs_bw[i].queue_id = qbw->cfg[i].queue_id;
+ vf->qs_bw[i].peak = qbw->cfg[i].shaper.peak;
+ vf->qs_bw[i].committed = qbw->cfg[i].shaper.committed;
+ vf->qs_bw[i].tc = qbw->cfg[i].tc;
+ }
+
+ if (ice_vf_cfg_qs_bw(vf, qbw->num_queues))
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+
+err:
+ /* send the response to the VF */
+ return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_QUEUE_BW,
+ v_ret, NULL, 0);
+}
+
+/**
+ * ice_vc_cfg_q_quanta - Configure per queue quanta
+ * @vf: pointer to the VF info
+ * @msg: pointer to the msg buffer which holds the command descriptor
+ *
+ * Configure VF queues quanta.
+ *
+ * Return: 0 on success or negative error value.
+ */
+static int ice_vc_cfg_q_quanta(struct ice_vf *vf, u8 *msg)
+{
+ enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
+ u16 quanta_prof_id, quanta_size, start_qid, end_qid, i;
+ struct virtchnl_quanta_cfg *qquanta =
+ (struct virtchnl_quanta_cfg *)msg;
+ struct ice_vsi *vsi;
+ int ret;
+
+ if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ vsi = ice_get_vf_vsi(vf);
+ if (!vsi) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ end_qid = qquanta->queue_select.start_queue_id +
+ qquanta->queue_select.num_queues;
+ if (end_qid > ICE_MAX_RSS_QS_PER_VF ||
+ end_qid > min_t(u16, vsi->alloc_txq, vsi->alloc_rxq)) {
+ dev_err(ice_pf_to_dev(vf->pf), "VF-%d trying to configure more than allocated number of queues: %d\n",
+ vf->vf_id, min_t(u16, vsi->alloc_txq, vsi->alloc_rxq));
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ quanta_size = qquanta->quanta_size;
+ if (quanta_size > ICE_MAX_QUANTA_SIZE ||
+ quanta_size < ICE_MIN_QUANTA_SIZE) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ if (quanta_size % 64) {
+ dev_err(ice_pf_to_dev(vf->pf), "quanta size should be the product of 64\n");
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto err;
+ }
+
+ ret = ice_vf_cfg_q_quanta_profile(vf, quanta_size,
+ &quanta_prof_id);
+ if (ret) {
+ v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
+ goto err;
+ }
+
+ start_qid = qquanta->queue_select.start_queue_id;
+ for (i = start_qid; i < end_qid; i++)
+ vsi->tx_rings[i]->quanta_prof_id = quanta_prof_id;
+
+err:
+ /* send the response to the VF */
+ return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_QUANTA,
+ v_ret, NULL, 0);
+}
+
+/**
* ice_vc_cfg_qs_msg
* @vf: pointer to the VF info
* @msg: pointer to the msg buffer
@@ -1715,8 +2038,8 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
/* copy Tx queue info from VF into VSI */
if (qpi->txq.ring_len > 0) {
- vsi->tx_rings[i]->dma = qpi->txq.dma_ring_addr;
- vsi->tx_rings[i]->count = qpi->txq.ring_len;
+ vsi->tx_rings[q_idx]->dma = qpi->txq.dma_ring_addr;
+ vsi->tx_rings[q_idx]->count = qpi->txq.ring_len;
/* Disable any existing queue first */
if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx))
@@ -1725,7 +2048,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
/* Configure a queue with the requested settings */
if (ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx)) {
dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure TX queue %d\n",
- vf->vf_id, i);
+ vf->vf_id, q_idx);
goto error_param;
}
}
@@ -1733,39 +2056,37 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
/* copy Rx queue info from VF into VSI */
if (qpi->rxq.ring_len > 0) {
u16 max_frame_size = ice_vc_get_max_frame_size(vf);
+ struct ice_rx_ring *ring = vsi->rx_rings[q_idx];
u32 rxdid;
- vsi->rx_rings[i]->dma = qpi->rxq.dma_ring_addr;
- vsi->rx_rings[i]->count = qpi->rxq.ring_len;
+ ring->dma = qpi->rxq.dma_ring_addr;
+ ring->count = qpi->rxq.ring_len;
if (qpi->rxq.crc_disable)
- vsi->rx_rings[q_idx]->flags |=
- ICE_RX_FLAGS_CRC_STRIP_DIS;
+ ring->flags |= ICE_RX_FLAGS_CRC_STRIP_DIS;
else
- vsi->rx_rings[q_idx]->flags &=
- ~ICE_RX_FLAGS_CRC_STRIP_DIS;
+ ring->flags &= ~ICE_RX_FLAGS_CRC_STRIP_DIS;
if (qpi->rxq.databuffer_size != 0 &&
(qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
qpi->rxq.databuffer_size < 1024))
goto error_param;
- vsi->rx_buf_len = qpi->rxq.databuffer_size;
- vsi->rx_rings[i]->rx_buf_len = vsi->rx_buf_len;
+ ring->rx_buf_len = qpi->rxq.databuffer_size;
if (qpi->rxq.max_pkt_size > max_frame_size ||
qpi->rxq.max_pkt_size < 64)
goto error_param;
- vsi->max_frame = qpi->rxq.max_pkt_size;
+ ring->max_frame = qpi->rxq.max_pkt_size;
/* add space for the port VLAN since the VF driver is
* not expected to account for it in the MTU
* calculation
*/
if (ice_vf_is_port_vlan_ena(vf))
- vsi->max_frame += VLAN_HLEN;
+ ring->max_frame += VLAN_HLEN;
if (ice_vsi_cfg_single_rxq(vsi, q_idx)) {
dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure RX queue %d\n",
- vf->vf_id, i);
+ vf->vf_id, q_idx);
goto error_param;
}
@@ -2233,17 +2554,27 @@ static bool ice_is_vlan_promisc_allowed(struct ice_vf *vf)
/**
* ice_vf_ena_vlan_promisc - Enable Tx/Rx VLAN promiscuous for the VLAN
+ * @vf: VF to enable VLAN promisc on
* @vsi: VF's VSI used to enable VLAN promiscuous mode
* @vlan: VLAN used to enable VLAN promiscuous
*
* This function should only be called if VLAN promiscuous mode is allowed,
* which can be determined via ice_is_vlan_promisc_allowed().
*/
-static int ice_vf_ena_vlan_promisc(struct ice_vsi *vsi, struct ice_vlan *vlan)
+static int ice_vf_ena_vlan_promisc(struct ice_vf *vf, struct ice_vsi *vsi,
+ struct ice_vlan *vlan)
{
- u8 promisc_m = ICE_PROMISC_VLAN_TX | ICE_PROMISC_VLAN_RX;
+ u8 promisc_m = 0;
int status;
+ if (test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states))
+ promisc_m |= ICE_UCAST_VLAN_PROMISC_BITS;
+ if (test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
+ promisc_m |= ICE_MCAST_VLAN_PROMISC_BITS;
+
+ if (!promisc_m)
+ return 0;
+
status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m,
vlan->vid);
if (status && status != -EEXIST)
@@ -2262,7 +2593,7 @@ static int ice_vf_ena_vlan_promisc(struct ice_vsi *vsi, struct ice_vlan *vlan)
*/
static int ice_vf_dis_vlan_promisc(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
- u8 promisc_m = ICE_PROMISC_VLAN_TX | ICE_PROMISC_VLAN_RX;
+ u8 promisc_m = ICE_UCAST_VLAN_PROMISC_BITS | ICE_MCAST_VLAN_PROMISC_BITS;
int status;
status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m,
@@ -2417,7 +2748,7 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
goto error_param;
}
} else if (vlan_promisc) {
- status = ice_vf_ena_vlan_promisc(vsi, &vlan);
+ status = ice_vf_ena_vlan_promisc(vf, vsi, &vlan);
if (status) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
dev_err(dev, "Enable Unicast/multicast promiscuous mode on VLAN ID:%d failed error-%d\n",
@@ -2700,12 +3031,8 @@ err:
static int ice_vc_query_rxdid(struct ice_vf *vf)
{
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
- struct virtchnl_supported_rxdids *rxdid = NULL;
- struct ice_hw *hw = &vf->pf->hw;
+ struct virtchnl_supported_rxdids rxdid = {};
struct ice_pf *pf = vf->pf;
- int len = 0;
- int ret, i;
- u32 regval;
if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
@@ -2717,35 +3044,11 @@ static int ice_vc_query_rxdid(struct ice_vf *vf)
goto err;
}
- len = sizeof(struct virtchnl_supported_rxdids);
- rxdid = kzalloc(len, GFP_KERNEL);
- if (!rxdid) {
- v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
- len = 0;
- goto err;
- }
-
- /* RXDIDs supported by DDP package can be read from the register
- * to get the supported RXDID bitmap. But the legacy 32byte RXDID
- * is not listed in DDP package, add it in the bitmap manually.
- * Legacy 16byte descriptor is not supported.
- */
- rxdid->supported_rxdids |= BIT(ICE_RXDID_LEGACY_1);
-
- for (i = ICE_RXDID_FLEX_NIC; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) {
- regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0));
- if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S)
- & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M)
- rxdid->supported_rxdids |= BIT(i);
- }
-
- pf->supported_rxdids = rxdid->supported_rxdids;
+ rxdid.supported_rxdids = pf->supported_rxdids;
err:
- ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS,
- v_ret, (u8 *)rxdid, len);
- kfree(rxdid);
- return ret;
+ return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS,
+ v_ret, (u8 *)&rxdid, sizeof(rxdid));
}
/**
@@ -3254,7 +3557,7 @@ ice_vc_add_vlans(struct ice_vf *vf, struct ice_vsi *vsi,
return err;
if (vlan_promisc) {
- err = ice_vf_ena_vlan_promisc(vsi, &vlan);
+ err = ice_vf_ena_vlan_promisc(vf, vsi, &vlan);
if (err)
return err;
}
@@ -3282,7 +3585,8 @@ ice_vc_add_vlans(struct ice_vf *vf, struct ice_vsi *vsi,
*/
if (!ice_is_dvm_ena(&vsi->back->hw)) {
if (vlan_promisc) {
- err = ice_vf_ena_vlan_promisc(vsi, &vlan);
+ err = ice_vf_ena_vlan_promisc(vf, vsi,
+ &vlan);
if (err)
return err;
}
@@ -3821,6 +4125,9 @@ static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
.dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg,
.ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg,
.dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg,
+ .get_qos_caps = ice_vc_get_qos_caps,
+ .cfg_q_bw = ice_vc_cfg_q_bw,
+ .cfg_q_quanta = ice_vc_cfg_q_quanta,
};
/**
@@ -4009,8 +4316,10 @@ ice_is_malicious_vf(struct ice_vf *vf, struct ice_mbx_data *mbxdata)
* @event: pointer to the AQ event
* @mbxdata: information used to detect VF attempting mailbox overflow
*
- * called from the common asq/arq handler to
- * process request from VF
+ * Called from the common asq/arq handler to process request from VF. When this
+ * flow is used for devices with hardware VF to PF message queue overflow
+ * support (ICE_F_MBX_LIMIT) mbxdata is set to NULL and ice_is_malicious_vf
+ * check is skipped.
*/
void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
struct ice_mbx_data *mbxdata)
@@ -4036,7 +4345,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
mutex_lock(&vf->cfg_lock);
/* Check if the VF is trying to overflow the mailbox */
- if (ice_is_malicious_vf(vf, mbxdata))
+ if (mbxdata && ice_is_malicious_vf(vf, mbxdata))
goto finish;
/* Check if VF is disabled. */
@@ -4177,6 +4486,15 @@ error_handler:
case VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2:
err = ops->dis_vlan_insertion_v2_msg(vf, msg);
break;
+ case VIRTCHNL_OP_GET_QOS_CAPS:
+ err = ops->get_qos_caps(vf);
+ break;
+ case VIRTCHNL_OP_CONFIG_QUEUE_BW:
+ err = ops->cfg_q_bw(vf, msg);
+ break;
+ case VIRTCHNL_OP_CONFIG_QUANTA:
+ err = ops->cfg_q_quanta(vf, msg);
+ break;
case VIRTCHNL_OP_UNKNOWN:
default:
dev_err(dev, "Unsupported opcode %d from VF %d\n", v_opcode,
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.h b/drivers/net/ethernet/intel/ice/ice_virtchnl.h
index 3a4115869153..0c629aef9baf 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.h
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.h
@@ -13,6 +13,13 @@
/* Restrict number of MAC Addr and VLAN that non-trusted VF can programmed */
#define ICE_MAX_VLAN_PER_VF 8
+#define ICE_DFLT_QUANTA 1024
+#define ICE_MAX_QUANTA_SIZE 4096
+#define ICE_MIN_QUANTA_SIZE 256
+
+#define calc_quanta_desc(x) \
+ max_t(u16, 12, min_t(u16, 63, (((x) + 66) / 132) * 2 + 4))
+
/* MAC filters: 1 is reserved for the VF's default/perm_addr/LAA MAC, 1 for
* broadcast, and 16 for additional unicast/multicast filters
*/
@@ -61,6 +68,10 @@ struct ice_virtchnl_ops {
int (*dis_vlan_stripping_v2_msg)(struct ice_vf *vf, u8 *msg);
int (*ena_vlan_insertion_v2_msg)(struct ice_vf *vf, u8 *msg);
int (*dis_vlan_insertion_v2_msg)(struct ice_vf *vf, u8 *msg);
+ int (*get_qos_caps)(struct ice_vf *vf);
+ int (*cfg_q_tc_map)(struct ice_vf *vf, u8 *msg);
+ int (*cfg_q_bw)(struct ice_vf *vf, u8 *msg);
+ int (*cfg_q_quanta)(struct ice_vf *vf, u8 *msg);
};
#ifdef CONFIG_PCI_IOV
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c
index d796dbd2a440..c105a82ee136 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_allowlist.c
@@ -84,6 +84,11 @@ static const u32 fdir_pf_allowlist_opcodes[] = {
VIRTCHNL_OP_ADD_FDIR_FILTER, VIRTCHNL_OP_DEL_FDIR_FILTER,
};
+static const u32 tc_allowlist_opcodes[] = {
+ VIRTCHNL_OP_GET_QOS_CAPS, VIRTCHNL_OP_CONFIG_QUEUE_BW,
+ VIRTCHNL_OP_CONFIG_QUANTA,
+};
+
struct allowlist_opcode_info {
const u32 *opcodes;
size_t size;
@@ -104,6 +109,7 @@ static const struct allowlist_opcode_info allowlist_opcodes[] = {
ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF, adv_rss_pf_allowlist_opcodes),
ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_FDIR_PF, fdir_pf_allowlist_opcodes),
ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_VLAN_V2, vlan_v2_allowlist_opcodes),
+ ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_QOS, tc_allowlist_opcodes),
};
/**
diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index 2c31ad87587a..66544faab710 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -141,6 +141,7 @@ enum idpf_vport_state {
* @adapter: Adapter back pointer
* @vport: Vport back pointer
* @vport_id: Vport identifier
+ * @link_speed_mbps: Link speed in mbps
* @vport_idx: Relative vport index
* @state: See enum idpf_vport_state
* @netstats: Packet and byte stats
@@ -150,6 +151,7 @@ struct idpf_netdev_priv {
struct idpf_adapter *adapter;
struct idpf_vport *vport;
u32 vport_id;
+ u32 link_speed_mbps;
u16 vport_idx;
enum idpf_vport_state state;
struct rtnl_link_stats64 netstats;
@@ -287,7 +289,6 @@ struct idpf_port_stats {
* @tx_itr_profile: TX profiles for Dynamic Interrupt Moderation
* @port_stats: per port csum, header split, and other offload stats
* @link_up: True if link is up
- * @link_speed_mbps: Link speed in mbps
* @sw_marker_wq: workqueue for marker packets
*/
struct idpf_vport {
@@ -331,7 +332,6 @@ struct idpf_vport {
struct idpf_port_stats port_stats;
bool link_up;
- u32 link_speed_mbps;
wait_queue_head_t sw_marker_wq;
};
diff --git a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
index 3806ddd3ce4a..59b1a1a09996 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
@@ -1296,24 +1296,19 @@ static void idpf_set_msglevel(struct net_device *netdev, u32 data)
static int idpf_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
- struct idpf_vport *vport;
-
- idpf_vport_ctrl_lock(netdev);
- vport = idpf_netdev_to_vport(netdev);
+ struct idpf_netdev_priv *np = netdev_priv(netdev);
ethtool_link_ksettings_zero_link_mode(cmd, supported);
cmd->base.autoneg = AUTONEG_DISABLE;
cmd->base.port = PORT_NONE;
- if (vport->link_up) {
+ if (netif_carrier_ok(netdev)) {
cmd->base.duplex = DUPLEX_FULL;
- cmd->base.speed = vport->link_speed_mbps;
+ cmd->base.speed = np->link_speed_mbps;
} else {
cmd->base.duplex = DUPLEX_UNKNOWN;
cmd->base.speed = SPEED_UNKNOWN;
}
- idpf_vport_ctrl_unlock(netdev);
-
return 0;
}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 4f20343e49a9..b4fbb99bfad2 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1786,6 +1786,7 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter)
*/
err = idpf_vc_core_init(adapter);
if (err) {
+ cancel_delayed_work_sync(&adapter->mbx_task);
idpf_deinit_dflt_mbx(adapter);
goto unlock_mutex;
}
@@ -1860,7 +1861,7 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
* mess with. Nothing below should use those variables from new_vport
* and should instead always refer to them in vport if they need to.
*/
- memcpy(new_vport, vport, offsetof(struct idpf_vport, link_speed_mbps));
+ memcpy(new_vport, vport, offsetof(struct idpf_vport, link_up));
/* Adjust resource parameters prior to reallocating resources */
switch (reset_cause) {
@@ -1906,7 +1907,7 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
/* Same comment as above regarding avoiding copying the wait_queues and
* mutexes applies here. We do not want to mess with those if possible.
*/
- memcpy(vport, new_vport, offsetof(struct idpf_vport, link_speed_mbps));
+ memcpy(vport, new_vport, offsetof(struct idpf_vport, link_up));
if (reset_cause == IDPF_SR_Q_CHANGE)
idpf_vport_alloc_vec_indexes(vport);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index d4e6f0e10487..da2a5becf62f 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -3679,7 +3679,7 @@ static void idpf_net_dim(struct idpf_q_vector *q_vector)
idpf_update_dim_sample(q_vector, &dim_sample, &q_vector->tx_dim,
packets, bytes);
- net_dim(&q_vector->tx_dim, dim_sample);
+ net_dim(&q_vector->tx_dim, &dim_sample);
check_rx_itr:
if (!IDPF_ITR_IS_DYNAMIC(q_vector->rx_intr_mode))
@@ -3698,7 +3698,7 @@ check_rx_itr:
idpf_update_dim_sample(q_vector, &dim_sample, &q_vector->rx_dim,
packets, bytes);
- net_dim(&q_vector->rx_dim, dim_sample);
+ net_dim(&q_vector->rx_dim, &dim_sample);
}
/**
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
index f0537826f840..9c1fe84108ed 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
@@ -438,7 +438,8 @@ struct idpf_q_vector {
__cacheline_group_end_aligned(cold);
};
libeth_cacheline_set_assert(struct idpf_q_vector, 112,
- 424 + 2 * sizeof(struct dim),
+ 24 + sizeof(struct napi_struct) +
+ 2 * sizeof(struct dim),
8 + sizeof(cpumask_var_t));
struct idpf_rx_queue_stats {
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index 15c00a01f1c0..d46c95f91b0d 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -141,7 +141,7 @@ static void idpf_handle_event_link(struct idpf_adapter *adapter,
}
np = netdev_priv(vport->netdev);
- vport->link_speed_mbps = le32_to_cpu(v2e->link_speed);
+ np->link_speed_mbps = le32_to_cpu(v2e->link_speed);
if (vport->link_up == v2e->link_status)
return;
@@ -3063,7 +3063,6 @@ init_failed:
adapter->state = __IDPF_VER_CHECK;
if (adapter->vcxn_mngr)
idpf_vc_xn_shutdown(adapter->vcxn_mngr);
- idpf_deinit_dflt_mbx(adapter);
set_bit(IDPF_HR_DRV_LOAD, adapter->flags);
queue_delayed_work(adapter->vc_event_wq, &adapter->vc_event_task,
msecs_to_jiffies(task_delay));
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index 6e110f28f922..529b7d18b662 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -63,6 +63,5 @@ enum e1000_mng_mode {
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
-void e1000_init_function_pointers_82575(struct e1000_hw *hw);
#endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h
index 091cddf4ada8..4f652ab713b3 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.h
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h
@@ -7,7 +7,6 @@
s32 igb_acquire_nvm(struct e1000_hw *hw);
void igb_release_nvm(struct e1000_hw *hw);
s32 igb_read_mac_addr(struct e1000_hw *hw);
-s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num);
s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num,
u32 part_num_size);
s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index b83df5f94b1f..08578980b651 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -907,7 +907,7 @@ static int igb_request_msix(struct igb_adapter *adapter)
int i, err = 0, vector = 0, free_vector = 0;
err = request_irq(adapter->msix_entries[vector].vector,
- igb_msix_other, IRQF_NO_THREAD, netdev->name, adapter);
+ igb_msix_other, 0, netdev->name, adapter);
if (err)
goto err_out;
@@ -1204,7 +1204,7 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
/* initialize pointer to rings */
ring = q_vector->ring;
- /* intialize ITR */
+ /* initialize ITR */
if (rxr_count) {
/* rx or rx/tx vector */
if (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3)
@@ -2486,7 +2486,7 @@ static int igb_set_features(struct net_device *netdev,
static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags,
+ u16 flags, bool *notified,
struct netlink_ext_ack *extack)
{
/* guarantee we can provide a unique filter for the unicast address */
@@ -3906,7 +3906,7 @@ static void igb_remove(struct pci_dev *pdev)
*
* This function initializes the vf specific data storage and then attempts to
* allocate the VFs. The reason for ordering it this way is because it is much
- * mor expensive time wise to disable SR-IOV than it is to allocate and free
+ * more expensive time wise to disable SR-IOV than it is to allocate and free
* the memory for the VFs.
**/
static void igb_probe_vfs(struct igb_adapter *adapter)
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index 6ad35a00a287..ca6e44245a7b 100644
--- a/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -169,8 +169,6 @@ struct igbvf_adapter {
u16 link_speed;
u16 link_duplex;
- spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
-
/* track device up/down/testing state */
unsigned long state;
@@ -220,7 +218,6 @@ struct igbvf_adapter {
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
- spinlock_t stats_lock; /* prevent concurrent stats updates */
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 925d7286a8ee..02044aa2181b 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1656,12 +1656,9 @@ static int igbvf_sw_init(struct igbvf_adapter *adapter)
if (igbvf_alloc_queues(adapter))
return -ENOMEM;
- spin_lock_init(&adapter->tx_queue_lock);
-
/* Explicitly disable IRQ since the NIC can be in any state. */
igbvf_irq_disable(adapter);
- spin_lock_init(&adapter->stats_lock);
spin_lock_init(&adapter->hw.mbx_lock);
set_bit(__IGBVF_DOWN, &adapter->state);
diff --git a/drivers/net/ethernet/intel/igc/igc_diag.c b/drivers/net/ethernet/intel/igc/igc_diag.c
index cc621970c0cd..a43d7244ee70 100644
--- a/drivers/net/ethernet/intel/igc/igc_diag.c
+++ b/drivers/net/ethernet/intel/igc/igc_diag.c
@@ -173,8 +173,7 @@ bool igc_link_test(struct igc_adapter *adapter, u64 *data)
*data = 0;
/* add delay to give enough time for autonegotioation to finish */
- if (adapter->hw.mac.autoneg)
- ssleep(5);
+ ssleep(5);
link_up = igc_has_link(adapter);
if (!link_up) {
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 5b0c6f433767..817838677817 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1821,11 +1821,8 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
ethtool_link_ksettings_add_link_mode(cmd, advertising, 2500baseT_Full);
/* set autoneg settings */
- if (hw->mac.autoneg == 1) {
- ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
- ethtool_link_ksettings_add_link_mode(cmd, advertising,
- Autoneg);
- }
+ ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
/* Set pause flow control settings */
ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
@@ -1878,10 +1875,7 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
cmd->base.duplex = DUPLEX_UNKNOWN;
}
cmd->base.speed = speed;
- if (hw->mac.autoneg)
- cmd->base.autoneg = AUTONEG_ENABLE;
- else
- cmd->base.autoneg = AUTONEG_DISABLE;
+ cmd->base.autoneg = AUTONEG_ENABLE;
/* MDI-X => 2; MDI =>1; Invalid =>0 */
if (hw->phy.media_type == igc_media_type_copper)
@@ -1955,7 +1949,6 @@ igc_ethtool_set_link_ksettings(struct net_device *netdev,
advertised |= ADVERTISE_10_HALF;
if (cmd->base.autoneg == AUTONEG_ENABLE) {
- hw->mac.autoneg = 1;
hw->phy.autoneg_advertised = advertised;
if (adapter->fc_autoneg)
hw->fc.requested_mode = igc_fc_default;
diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h
index e1c572e0d4ef..d9d1a1a11daf 100644
--- a/drivers/net/ethernet/intel/igc/igc_hw.h
+++ b/drivers/net/ethernet/intel/igc/igc_hw.h
@@ -92,7 +92,6 @@ struct igc_mac_info {
bool asf_firmware_present;
bool arc_subsystem_valid;
- bool autoneg;
bool autoneg_failed;
bool get_link_status;
};
diff --git a/drivers/net/ethernet/intel/igc/igc_mac.c b/drivers/net/ethernet/intel/igc/igc_mac.c
index a5c4b19d71a2..d344e0a1cd5e 100644
--- a/drivers/net/ethernet/intel/igc/igc_mac.c
+++ b/drivers/net/ethernet/intel/igc/igc_mac.c
@@ -386,14 +386,6 @@ s32 igc_check_for_copper_link(struct igc_hw *hw)
*/
igc_check_downshift(hw);
- /* If we are forcing speed/duplex, then we simply return since
- * we have already determined whether we have link or not.
- */
- if (!mac->autoneg) {
- ret_val = -IGC_ERR_CONFIG;
- goto out;
- }
-
/* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to
* configure Collision Distance in the MAC.
@@ -468,173 +460,171 @@ s32 igc_config_fc_after_link_up(struct igc_hw *hw)
goto out;
}
- /* Check for the case where we have copper media and auto-neg is
- * enabled. In this case, we need to check and see if Auto-Neg
- * has completed, and if so, how the PHY and link partner has
- * flow control configured.
+ /* In auto-neg, we need to check and see if Auto-Neg has completed,
+ * and if so, how the PHY and link partner has flow control
+ * configured.
*/
- if (mac->autoneg) {
- /* Read the MII Status Register and check to see if AutoNeg
- * has completed. We read this twice because this reg has
- * some "sticky" (latched) bits.
- */
- ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
- &mii_status_reg);
- if (ret_val)
- goto out;
- ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
- &mii_status_reg);
- if (ret_val)
- goto out;
- if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
- hw_dbg("Copper PHY and Auto Neg has not completed.\n");
- goto out;
- }
+ /* Read the MII Status Register and check to see if AutoNeg
+ * has completed. We read this twice because this reg has
+ * some "sticky" (latched) bits.
+ */
+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
+ &mii_status_reg);
+ if (ret_val)
+ goto out;
+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
+ &mii_status_reg);
+ if (ret_val)
+ goto out;
- /* The AutoNeg process has completed, so we now need to
- * read both the Auto Negotiation Advertisement
- * Register (Address 4) and the Auto_Negotiation Base
- * Page Ability Register (Address 5) to determine how
- * flow control was negotiated.
- */
- ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
- &mii_nway_adv_reg);
- if (ret_val)
- goto out;
- ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
- &mii_nway_lp_ability_reg);
- if (ret_val)
- goto out;
- /* Two bits in the Auto Negotiation Advertisement Register
- * (Address 4) and two bits in the Auto Negotiation Base
- * Page Ability Register (Address 5) determine flow control
- * for both the PHY and the link partner. The following
- * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
- * 1999, describes these PAUSE resolution bits and how flow
- * control is determined based upon these settings.
- * NOTE: DC = Don't Care
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
- *-------|---------|-------|---------|--------------------
- * 0 | 0 | DC | DC | igc_fc_none
- * 0 | 1 | 0 | DC | igc_fc_none
- * 0 | 1 | 1 | 0 | igc_fc_none
- * 0 | 1 | 1 | 1 | igc_fc_tx_pause
- * 1 | 0 | 0 | DC | igc_fc_none
- * 1 | DC | 1 | DC | igc_fc_full
- * 1 | 1 | 0 | 0 | igc_fc_none
- * 1 | 1 | 0 | 1 | igc_fc_rx_pause
- *
- * Are both PAUSE bits set to 1? If so, this implies
- * Symmetric Flow Control is enabled at both ends. The
- * ASM_DIR bits are irrelevant per the spec.
- *
- * For Symmetric Flow Control:
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
- *-------|---------|-------|---------|--------------------
- * 1 | DC | 1 | DC | IGC_fc_full
- *
- */
- if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
- /* Now we need to check if the user selected RX ONLY
- * of pause frames. In this case, we had to advertise
- * FULL flow control because we could not advertise RX
- * ONLY. Hence, we must now check to see if we need to
- * turn OFF the TRANSMISSION of PAUSE frames.
- */
- if (hw->fc.requested_mode == igc_fc_full) {
- hw->fc.current_mode = igc_fc_full;
- hw_dbg("Flow Control = FULL.\n");
- } else {
- hw->fc.current_mode = igc_fc_rx_pause;
- hw_dbg("Flow Control = RX PAUSE frames only.\n");
- }
- }
+ if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
+ hw_dbg("Copper PHY and Auto Neg has not completed.\n");
+ goto out;
+ }
- /* For receiving PAUSE frames ONLY.
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
- *-------|---------|-------|---------|--------------------
- * 0 | 1 | 1 | 1 | igc_fc_tx_pause
- */
- else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc.current_mode = igc_fc_tx_pause;
- hw_dbg("Flow Control = TX PAUSE frames only.\n");
- }
- /* For transmitting PAUSE frames ONLY.
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
- *-------|---------|-------|---------|--------------------
- * 1 | 1 | 0 | 1 | igc_fc_rx_pause
- */
- else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
- !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc.current_mode = igc_fc_rx_pause;
- hw_dbg("Flow Control = RX PAUSE frames only.\n");
- }
- /* Per the IEEE spec, at this point flow control should be
- * disabled. However, we want to consider that we could
- * be connected to a legacy switch that doesn't advertise
- * desired flow control, but can be forced on the link
- * partner. So if we advertised no flow control, that is
- * what we will resolve to. If we advertised some kind of
- * receive capability (Rx Pause Only or Full Flow Control)
- * and the link partner advertised none, we will configure
- * ourselves to enable Rx Flow Control only. We can do
- * this safely for two reasons: If the link partner really
- * didn't want flow control enabled, and we enable Rx, no
- * harm done since we won't be receiving any PAUSE frames
- * anyway. If the intent on the link partner was to have
- * flow control enabled, then by us enabling RX only, we
- * can at least receive pause frames and process them.
- * This is a good idea because in most cases, since we are
- * predominantly a server NIC, more times than not we will
- * be asked to delay transmission of packets than asking
- * our link partner to pause transmission of frames.
+ /* The AutoNeg process has completed, so we now need to
+ * read both the Auto Negotiation Advertisement
+ * Register (Address 4) and the Auto_Negotiation Base
+ * Page Ability Register (Address 5) to determine how
+ * flow control was negotiated.
+ */
+ ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
+ &mii_nway_adv_reg);
+ if (ret_val)
+ goto out;
+ ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
+ &mii_nway_lp_ability_reg);
+ if (ret_val)
+ goto out;
+ /* Two bits in the Auto Negotiation Advertisement Register
+ * (Address 4) and two bits in the Auto Negotiation Base
+ * Page Ability Register (Address 5) determine flow control
+ * for both the PHY and the link partner. The following
+ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+ * 1999, describes these PAUSE resolution bits and how flow
+ * control is determined based upon these settings.
+ * NOTE: DC = Don't Care
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+ *-------|---------|-------|---------|--------------------
+ * 0 | 0 | DC | DC | igc_fc_none
+ * 0 | 1 | 0 | DC | igc_fc_none
+ * 0 | 1 | 1 | 0 | igc_fc_none
+ * 0 | 1 | 1 | 1 | igc_fc_tx_pause
+ * 1 | 0 | 0 | DC | igc_fc_none
+ * 1 | DC | 1 | DC | igc_fc_full
+ * 1 | 1 | 0 | 0 | igc_fc_none
+ * 1 | 1 | 0 | 1 | igc_fc_rx_pause
+ *
+ * Are both PAUSE bits set to 1? If so, this implies
+ * Symmetric Flow Control is enabled at both ends. The
+ * ASM_DIR bits are irrelevant per the spec.
+ *
+ * For Symmetric Flow Control:
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | DC | 1 | DC | IGC_fc_full
+ *
+ */
+ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+ /* Now we need to check if the user selected RX ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
*/
- else if ((hw->fc.requested_mode == igc_fc_none) ||
- (hw->fc.requested_mode == igc_fc_tx_pause) ||
- (hw->fc.strict_ieee)) {
- hw->fc.current_mode = igc_fc_none;
- hw_dbg("Flow Control = NONE.\n");
+ if (hw->fc.requested_mode == igc_fc_full) {
+ hw->fc.current_mode = igc_fc_full;
+ hw_dbg("Flow Control = FULL.\n");
} else {
hw->fc.current_mode = igc_fc_rx_pause;
hw_dbg("Flow Control = RX PAUSE frames only.\n");
}
+ }
- /* Now we need to do one last check... If we auto-
- * negotiated to HALF DUPLEX, flow control should not be
- * enabled per IEEE 802.3 spec.
- */
- ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
- if (ret_val) {
- hw_dbg("Error getting link speed and duplex\n");
- goto out;
- }
+ /* For receiving PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 0 | 1 | 1 | 1 | igc_fc_tx_pause
+ */
+ else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+ hw->fc.current_mode = igc_fc_tx_pause;
+ hw_dbg("Flow Control = TX PAUSE frames only.\n");
+ }
+ /* For transmitting PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | 1 | 0 | 1 | igc_fc_rx_pause
+ */
+ else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+ hw->fc.current_mode = igc_fc_rx_pause;
+ hw_dbg("Flow Control = RX PAUSE frames only.\n");
+ }
+ /* Per the IEEE spec, at this point flow control should be
+ * disabled. However, we want to consider that we could
+ * be connected to a legacy switch that doesn't advertise
+ * desired flow control, but can be forced on the link
+ * partner. So if we advertised no flow control, that is
+ * what we will resolve to. If we advertised some kind of
+ * receive capability (Rx Pause Only or Full Flow Control)
+ * and the link partner advertised none, we will configure
+ * ourselves to enable Rx Flow Control only. We can do
+ * this safely for two reasons: If the link partner really
+ * didn't want flow control enabled, and we enable Rx, no
+ * harm done since we won't be receiving any PAUSE frames
+ * anyway. If the intent on the link partner was to have
+ * flow control enabled, then by us enabling RX only, we
+ * can at least receive pause frames and process them.
+ * This is a good idea because in most cases, since we are
+ * predominantly a server NIC, more times than not we will
+ * be asked to delay transmission of packets than asking
+ * our link partner to pause transmission of frames.
+ */
+ else if ((hw->fc.requested_mode == igc_fc_none) ||
+ (hw->fc.requested_mode == igc_fc_tx_pause) ||
+ (hw->fc.strict_ieee)) {
+ hw->fc.current_mode = igc_fc_none;
+ hw_dbg("Flow Control = NONE.\n");
+ } else {
+ hw->fc.current_mode = igc_fc_rx_pause;
+ hw_dbg("Flow Control = RX PAUSE frames only.\n");
+ }
- if (duplex == HALF_DUPLEX)
- hw->fc.current_mode = igc_fc_none;
+ /* Now we need to do one last check... If we auto-
+ * negotiated to HALF DUPLEX, flow control should not be
+ * enabled per IEEE 802.3 spec.
+ */
+ ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ hw_dbg("Error getting link speed and duplex\n");
+ goto out;
+ }
- /* Now we call a subroutine to actually force the MAC
- * controller to use the correct flow control settings.
- */
- ret_val = igc_force_mac_fc(hw);
- if (ret_val) {
- hw_dbg("Error forcing flow control settings\n");
- goto out;
- }
+ if (duplex == HALF_DUPLEX)
+ hw->fc.current_mode = igc_fc_none;
+
+ /* Now we call a subroutine to actually force the MAC
+ * controller to use the correct flow control settings.
+ */
+ ret_val = igc_force_mac_fc(hw);
+ if (ret_val) {
+ hw_dbg("Error forcing flow control settings\n");
+ goto out;
}
out:
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 6e70bca15db1..27872bdea9bd 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -7108,7 +7108,6 @@ static int igc_probe(struct pci_dev *pdev,
/* Initialize link properties that are user-changeable */
adapter->fc_autoneg = true;
- hw->mac.autoneg = true;
hw->phy.autoneg_advertised = 0xaf;
hw->fc.requested_mode = igc_fc_default;
diff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c
index 2801e5f24df9..6c4d204aecfa 100644
--- a/drivers/net/ethernet/intel/igc/igc_phy.c
+++ b/drivers/net/ethernet/intel/igc/igc_phy.c
@@ -494,24 +494,12 @@ s32 igc_setup_copper_link(struct igc_hw *hw)
s32 ret_val = 0;
bool link;
- if (hw->mac.autoneg) {
- /* Setup autoneg and flow control advertisement and perform
- * autonegotiation.
- */
- ret_val = igc_copper_link_autoneg(hw);
- if (ret_val)
- goto out;
- } else {
- /* PHY will be set to 10H, 10F, 100H or 100F
- * depending on user settings.
- */
- hw_dbg("Forcing Speed and Duplex\n");
- ret_val = hw->phy.ops.force_speed_duplex(hw);
- if (ret_val) {
- hw_dbg("Error Forcing Speed and Duplex\n");
- goto out;
- }
- }
+ /* Setup autoneg and flow control advertisement and perform
+ * autonegotiation.
+ */
+ ret_val = igc_copper_link_autoneg(hw);
+ if (ret_val)
+ goto out;
/* Check link status. Wait up to 100 microseconds for link to become
* valid.
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index 283a23150a4d..4aaaea3b5f8f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include "ixgbe.h"
+#include "ixgbe_mbx.h"
#include "ixgbe_phy.h"
#define IXGBE_82598_MAX_TX_QUEUES 32
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 8b8404d8c946..2e38e8f6fac1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -43,6 +43,7 @@
#include "ixgbe.h"
#include "ixgbe_common.h"
#include "ixgbe_dcb_82599.h"
+#include "ixgbe_mbx.h"
#include "ixgbe_phy.h"
#include "ixgbe_sriov.h"
#include "ixgbe_model.h"
@@ -9954,7 +9955,7 @@ static int ixgbe_set_features(struct net_device *netdev,
static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags,
+ u16 flags, bool *notified,
struct netlink_ext_ack *extack)
{
/* guarantee we can provide a unique filter for the unicast address */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index bd205306934b..bf65e82b4c61 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -4,7 +4,7 @@
#ifndef _IXGBE_MBX_H_
#define _IXGBE_MBX_H_
-#include "ixgbe_type.h"
+#include <linux/types.h>
#define IXGBE_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
@@ -96,6 +96,8 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
#define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */
+struct ixgbe_hw;
+
int ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16);
int ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16);
int ixgbe_check_for_msg(struct ixgbe_hw *, u16);
@@ -105,6 +107,18 @@ int ixgbe_check_for_rst(struct ixgbe_hw *, u16);
void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
#endif /* CONFIG_PCI_IOV */
+struct ixgbe_mbx_operations {
+ int (*init_params)(struct ixgbe_hw *hw);
+ int (*read)(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 vf_number);
+ int (*write)(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 vf_number);
+ int (*read_posted)(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+ int (*write_posted)(struct ixgbe_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id);
+ int (*check_for_msg)(struct ixgbe_hw *hw, u16 vf_number);
+ int (*check_for_ack)(struct ixgbe_hw *hw, u16 vf_number);
+ int (*check_for_rst)(struct ixgbe_hw *hw, u16 vf_number);
+};
+
extern const struct ixgbe_mbx_operations mbx_ops_generic;
#endif /* _IXGBE_MBX_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index e71715f5da22..9631559a5aea 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -18,6 +18,7 @@
#include "ixgbe.h"
#include "ixgbe_type.h"
+#include "ixgbe_mbx.h"
#include "ixgbe_sriov.h"
#ifdef CONFIG_PCI_IOV
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 346e3d9114a8..9baccacd02a1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -3601,19 +3601,6 @@ struct ixgbe_phy_info {
u32 nw_mng_if_sel;
};
-#include "ixgbe_mbx.h"
-
-struct ixgbe_mbx_operations {
- int (*init_params)(struct ixgbe_hw *hw);
- int (*read)(struct ixgbe_hw *, u32 *, u16, u16);
- int (*write)(struct ixgbe_hw *, u32 *, u16, u16);
- int (*read_posted)(struct ixgbe_hw *, u32 *, u16, u16);
- int (*write_posted)(struct ixgbe_hw *, u32 *, u16, u16);
- int (*check_for_msg)(struct ixgbe_hw *, u16);
- int (*check_for_ack)(struct ixgbe_hw *, u16);
- int (*check_for_rst)(struct ixgbe_hw *, u16);
-};
-
struct ixgbe_mbx_stats {
u32 msgs_tx;
u32 msgs_rx;
@@ -3623,6 +3610,8 @@ struct ixgbe_mbx_stats {
u32 rsts;
};
+struct ixgbe_mbx_operations;
+
struct ixgbe_mbx_info {
const struct ixgbe_mbx_operations *ops;
struct ixgbe_mbx_stats stats;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index f1ffa398f6df..81e1df83f136 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include "ixgbe.h"
+#include "ixgbe_mbx.h"
#include "ixgbe_phy.h"
#include "ixgbe_x540.h"
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
index a5f644934445..d9a8cf018d3b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
@@ -4,6 +4,7 @@
#include "ixgbe_x540.h"
#include "ixgbe_type.h"
#include "ixgbe_common.h"
+#include "ixgbe_mbx.h"
#include "ixgbe_phy.h"
static int ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 81cf3361a1e5..87c7e6251a4f 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -1403,7 +1403,7 @@ static struct platform_driver korina_driver = {
.of_match_table = of_match_ptr(korina_match),
},
.probe = korina_probe,
- .remove_new = korina_remove,
+ .remove = korina_remove,
};
module_platform_driver(korina_driver);
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 7179271f63b6..660dff5426e7 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -734,7 +734,7 @@ static void ltq_etop_remove(struct platform_device *pdev)
}
static struct platform_driver ltq_mii_driver = {
- .remove_new = ltq_etop_remove,
+ .remove = ltq_etop_remove,
.driver = {
.name = "ltq_etop",
},
diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c
index 07904a528f21..b8766fb7a844 100644
--- a/drivers/net/ethernet/lantiq_xrx200.c
+++ b/drivers/net/ethernet/lantiq_xrx200.c
@@ -669,7 +669,7 @@ MODULE_DEVICE_TABLE(of, xrx200_match);
static struct platform_driver xrx200_driver = {
.probe = xrx200_probe,
- .remove_new = xrx200_remove,
+ .remove = xrx200_remove,
.driver = {
.name = "lantiq,xrx200-net",
.of_match_table = xrx200_match,
diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c
index ff54fbe41bcc..829a4b828f8e 100644
--- a/drivers/net/ethernet/litex/litex_liteeth.c
+++ b/drivers/net/ethernet/litex/litex_liteeth.c
@@ -309,7 +309,7 @@ MODULE_DEVICE_TABLE(of, liteeth_of_match);
static struct platform_driver liteeth_driver = {
.probe = liteeth_probe,
- .remove_new = liteeth_remove,
+ .remove = liteeth_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = liteeth_of_match,
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 9e80899546d9..a06048719e84 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -1698,13 +1698,9 @@ static void mv643xx_eth_get_strings(struct net_device *dev,
{
int i;
- if (stringset == ETH_SS_STATS) {
- for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- mv643xx_eth_stats[i].stat_string,
- ETH_GSTRING_LEN);
- }
- }
+ if (stringset == ETH_SS_STATS)
+ for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++)
+ ethtool_puts(&data, mv643xx_eth_stats[i].stat_string);
}
static void mv643xx_eth_get_ethtool_stats(struct net_device *dev,
@@ -2843,29 +2839,24 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
struct mv643xx_eth_shared_platform_data *pd;
struct mv643xx_eth_shared_private *msp;
const struct mbus_dram_target_info *dram;
- struct resource *res;
int ret;
if (!mv643xx_eth_version_printed++)
pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n",
mv643xx_eth_driver_version);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL)
- return -EINVAL;
-
msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
if (msp == NULL)
return -ENOMEM;
platform_set_drvdata(pdev, msp);
- msp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (msp->base == NULL)
- return -ENOMEM;
+ msp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(msp->base))
+ return PTR_ERR(msp->base);
- msp->clk = devm_clk_get(&pdev->dev, NULL);
- if (!IS_ERR(msp->clk))
- clk_prepare_enable(msp->clk);
+ msp->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+ if (IS_ERR(msp->clk))
+ return PTR_ERR(msp->clk);
/*
* (Re-)program MBUS remapping windows if we are asked to.
@@ -2876,7 +2867,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
ret = mv643xx_eth_shared_of_probe(pdev);
if (ret)
- goto err_put_clk;
+ return ret;
pd = dev_get_platdata(&pdev->dev);
msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
@@ -2884,25 +2875,16 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
infer_hw_params(msp);
return 0;
-
-err_put_clk:
- if (!IS_ERR(msp->clk))
- clk_disable_unprepare(msp->clk);
- return ret;
}
static void mv643xx_eth_shared_remove(struct platform_device *pdev)
{
- struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
-
mv643xx_eth_shared_of_remove();
- if (!IS_ERR(msp->clk))
- clk_disable_unprepare(msp->clk);
}
static struct platform_driver mv643xx_eth_shared_driver = {
.probe = mv643xx_eth_shared_probe,
- .remove_new = mv643xx_eth_shared_remove,
+ .remove = mv643xx_eth_shared_remove,
.driver = {
.name = MV643XX_ETH_SHARED_NAME,
.of_match_table = of_match_ptr(mv643xx_eth_shared_ids),
@@ -3307,7 +3289,7 @@ static void mv643xx_eth_shutdown(struct platform_device *pdev)
static struct platform_driver mv643xx_eth_driver = {
.probe = mv643xx_eth_probe,
- .remove_new = mv643xx_eth_remove,
+ .remove = mv643xx_eth_remove,
.shutdown = mv643xx_eth_shutdown,
.driver = {
.name = MV643XX_ETH_NAME,
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index e1d003fdbc2e..3f4447e68888 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -348,13 +348,12 @@ static int orion_mdio_probe(struct platform_device *pdev)
if (type == BUS_TYPE_XSMI)
orion_mdio_xsmi_set_mdc_freq(bus);
} else {
- dev->clk[0] = clk_get(&pdev->dev, NULL);
- if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
+ dev->clk[0] = clk_get_optional(&pdev->dev, NULL);
+ if (IS_ERR(dev->clk[0])) {
+ ret = PTR_ERR(dev->clk[0]);
goto out_clk;
}
- if (!IS_ERR(dev->clk[0]))
- clk_prepare_enable(dev->clk[0]);
+ clk_prepare_enable(dev->clk[0]);
}
@@ -422,8 +421,6 @@ static void orion_mdio_remove(struct platform_device *pdev)
mdiobus_unregister(bus);
for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
- if (IS_ERR(dev->clk[i]))
- break;
clk_disable_unprepare(dev->clk[i]);
clk_put(dev->clk[i]);
}
@@ -447,7 +444,7 @@ MODULE_DEVICE_TABLE(acpi, orion_mdio_acpi_match);
static struct platform_driver orion_mdio_driver = {
.probe = orion_mdio_probe,
- .remove_new = orion_mdio_remove,
+ .remove = orion_mdio_remove,
.driver = {
.name = "orion-mdio",
.of_match_table = orion_mdio_match,
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index d72b2d5f96db..1fb285fa0bdb 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -4795,11 +4795,9 @@ static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
int i;
for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
- memcpy(data + i * ETH_GSTRING_LEN,
- mvneta_statistics[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, mvneta_statistics[i].name);
if (!pp->bm_priv) {
- data += ETH_GSTRING_LEN * ARRAY_SIZE(mvneta_statistics);
page_pool_ethtool_stats_get_strings(data);
}
}
@@ -5883,7 +5881,7 @@ MODULE_DEVICE_TABLE(of, mvneta_match);
static struct platform_driver mvneta_driver = {
.probe = mvneta_probe,
- .remove_new = mvneta_remove,
+ .remove = mvneta_remove,
.driver = {
.name = MVNETA_DRIVER_NAME,
.of_match_table = mvneta_match,
diff --git a/drivers/net/ethernet/marvell/mvneta_bm.c b/drivers/net/ethernet/marvell/mvneta_bm.c
index 3f46a0fed048..6bb380494919 100644
--- a/drivers/net/ethernet/marvell/mvneta_bm.c
+++ b/drivers/net/ethernet/marvell/mvneta_bm.c
@@ -485,7 +485,7 @@ MODULE_DEVICE_TABLE(of, mvneta_bm_match);
static struct platform_driver mvneta_bm_driver = {
.probe = mvneta_bm_probe,
- .remove_new = mvneta_bm_remove,
+ .remove = mvneta_bm_remove,
.driver = {
.name = MVNETA_BM_DRIVER_NAME,
.of_match_table = mvneta_bm_match,
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 3880dcc0418b..571631a30320 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1985,45 +1985,32 @@ static void mvpp2_ethtool_get_strings(struct net_device *netdev, u32 sset,
u8 *data)
{
struct mvpp2_port *port = netdev_priv(netdev);
+ const char *str;
int i, q;
if (sset != ETH_SS_STATS)
return;
- for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_mib_regs); i++) {
- strscpy(data, mvpp2_ethtool_mib_regs[i].string,
- ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_mib_regs); i++)
+ ethtool_puts(&data, mvpp2_ethtool_mib_regs[i].string);
- for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_port_regs); i++) {
- strscpy(data, mvpp2_ethtool_port_regs[i].string,
- ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_port_regs); i++)
+ ethtool_puts(&data, mvpp2_ethtool_port_regs[i].string);
- for (q = 0; q < port->ntxqs; q++) {
+ for (q = 0; q < port->ntxqs; q++)
for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_txq_regs); i++) {
- snprintf(data, ETH_GSTRING_LEN,
- mvpp2_ethtool_txq_regs[i].string, q);
- data += ETH_GSTRING_LEN;
+ str = mvpp2_ethtool_txq_regs[i].string;
+ ethtool_sprintf(&data, str, q);
}
- }
- for (q = 0; q < port->nrxqs; q++) {
+ for (q = 0; q < port->nrxqs; q++)
for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_rxq_regs); i++) {
- snprintf(data, ETH_GSTRING_LEN,
- mvpp2_ethtool_rxq_regs[i].string,
- q);
- data += ETH_GSTRING_LEN;
+ str = mvpp2_ethtool_rxq_regs[i].string;
+ ethtool_sprintf(&data, str, q);
}
- }
- for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_xdp); i++) {
- strscpy(data, mvpp2_ethtool_xdp[i].string,
- ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_xdp); i++)
+ ethtool_puts(&data, mvpp2_ethtool_xdp[i].string);
}
static void
@@ -7774,7 +7761,7 @@ MODULE_DEVICE_TABLE(acpi, mvpp2_acpi_match);
static struct platform_driver mvpp2_driver = {
.probe = mvpp2_probe,
- .remove_new = mvpp2_remove,
+ .remove = mvpp2_remove,
.driver = {
.name = MVPP2_DRIVER_NAME,
.of_match_table = mvpp2_match,
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c
index 7d0124b283da..4f4d58189118 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c
@@ -47,7 +47,7 @@ static const char octep_gstrings_global_stats[][ETH_GSTRING_LEN] = {
"rx_err_pkts",
};
-#define OCTEP_GLOBAL_STATS_CNT (sizeof(octep_gstrings_global_stats) / ETH_GSTRING_LEN)
+#define OCTEP_GLOBAL_STATS_CNT ARRAY_SIZE(octep_gstrings_global_stats)
static const char octep_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
"tx_packets_posted[Q-%u]",
@@ -56,7 +56,7 @@ static const char octep_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
"tx_busy[Q-%u]",
};
-#define OCTEP_TX_Q_STATS_CNT (sizeof(octep_gstrings_tx_q_stats) / ETH_GSTRING_LEN)
+#define OCTEP_TX_Q_STATS_CNT ARRAY_SIZE(octep_gstrings_tx_q_stats)
static const char octep_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
"rx_packets[Q-%u]",
@@ -64,7 +64,7 @@ static const char octep_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
"rx_alloc_errors[Q-%u]",
};
-#define OCTEP_RX_Q_STATS_CNT (sizeof(octep_gstrings_rx_q_stats) / ETH_GSTRING_LEN)
+#define OCTEP_RX_Q_STATS_CNT ARRAY_SIZE(octep_gstrings_rx_q_stats)
static void octep_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
@@ -80,32 +80,25 @@ static void octep_get_strings(struct net_device *netdev,
{
struct octep_device *oct = netdev_priv(netdev);
u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
- char *strings = (char *)data;
+ const char *str;
int i, j;
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0; i < OCTEP_GLOBAL_STATS_CNT; i++) {
- snprintf(strings, ETH_GSTRING_LEN,
- octep_gstrings_global_stats[i]);
- strings += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < OCTEP_GLOBAL_STATS_CNT; i++)
+ ethtool_puts(&data, octep_gstrings_global_stats[i]);
- for (i = 0; i < num_queues; i++) {
+ for (i = 0; i < num_queues; i++)
for (j = 0; j < OCTEP_TX_Q_STATS_CNT; j++) {
- snprintf(strings, ETH_GSTRING_LEN,
- octep_gstrings_tx_q_stats[j], i);
- strings += ETH_GSTRING_LEN;
+ str = octep_gstrings_tx_q_stats[j];
+ ethtool_sprintf(&data, str, i);
}
- }
- for (i = 0; i < num_queues; i++) {
+ for (i = 0; i < num_queues; i++)
for (j = 0; j < OCTEP_RX_Q_STATS_CNT; j++) {
- snprintf(strings, ETH_GSTRING_LEN,
- octep_gstrings_rx_q_stats[j], i);
- strings += ETH_GSTRING_LEN;
+ str = octep_gstrings_rx_q_stats[j];
+ ethtool_sprintf(&data, str, i);
}
- }
break;
default:
break;
diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c
index a1979b45e355..7b21439a315f 100644
--- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_ethtool.c
@@ -25,7 +25,7 @@ static const char octep_vf_gstrings_global_stats[][ETH_GSTRING_LEN] = {
"rx_dropped_bytes_fifo_full",
};
-#define OCTEP_VF_GLOBAL_STATS_CNT (sizeof(octep_vf_gstrings_global_stats) / ETH_GSTRING_LEN)
+#define OCTEP_VF_GLOBAL_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_global_stats)
static const char octep_vf_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
"tx_packets_posted[Q-%u]",
@@ -34,7 +34,7 @@ static const char octep_vf_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = {
"tx_busy[Q-%u]",
};
-#define OCTEP_VF_TX_Q_STATS_CNT (sizeof(octep_vf_gstrings_tx_q_stats) / ETH_GSTRING_LEN)
+#define OCTEP_VF_TX_Q_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_tx_q_stats)
static const char octep_vf_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
"rx_packets[Q-%u]",
@@ -42,7 +42,7 @@ static const char octep_vf_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = {
"rx_alloc_errors[Q-%u]",
};
-#define OCTEP_VF_RX_Q_STATS_CNT (sizeof(octep_vf_gstrings_rx_q_stats) / ETH_GSTRING_LEN)
+#define OCTEP_VF_RX_Q_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_rx_q_stats)
static void octep_vf_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info)
@@ -58,32 +58,25 @@ static void octep_vf_get_strings(struct net_device *netdev,
{
struct octep_vf_device *oct = netdev_priv(netdev);
u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
- char *strings = (char *)data;
+ const char *str;
int i, j;
switch (stringset) {
case ETH_SS_STATS:
- for (i = 0; i < OCTEP_VF_GLOBAL_STATS_CNT; i++) {
- snprintf(strings, ETH_GSTRING_LEN,
- octep_vf_gstrings_global_stats[i]);
- strings += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < OCTEP_VF_GLOBAL_STATS_CNT; i++)
+ ethtool_puts(&data, octep_vf_gstrings_global_stats[i]);
- for (i = 0; i < num_queues; i++) {
+ for (i = 0; i < num_queues; i++)
for (j = 0; j < OCTEP_VF_TX_Q_STATS_CNT; j++) {
- snprintf(strings, ETH_GSTRING_LEN,
- octep_vf_gstrings_tx_q_stats[j], i);
- strings += ETH_GSTRING_LEN;
+ str = octep_vf_gstrings_tx_q_stats[j];
+ ethtool_sprintf(&data, str, i);
}
- }
- for (i = 0; i < num_queues; i++) {
+ for (i = 0; i < num_queues; i++)
for (j = 0; j < OCTEP_VF_RX_Q_STATS_CNT; j++) {
- snprintf(strings, ETH_GSTRING_LEN,
- octep_vf_gstrings_rx_q_stats[j], i);
- strings += ETH_GSTRING_LEN;
+ str = octep_vf_gstrings_rx_q_stats[j];
+ ethtool_sprintf(&data, str, i);
}
- }
break;
default:
break;
diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig
index a32d85d6f599..35c4f5f64f58 100644
--- a/drivers/net/ethernet/marvell/octeontx2/Kconfig
+++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig
@@ -46,3 +46,11 @@ config OCTEONTX2_VF
depends on OCTEONTX2_PF
help
This driver supports Marvell's OcteonTX2 NIC virtual function.
+
+config RVU_ESWITCH
+ tristate "Marvell RVU E-Switch support"
+ depends on OCTEONTX2_PF
+ default m
+ help
+ This driver supports Marvell's RVU E-Switch that
+ provides internal SRIOV packet steering and switching.
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/Makefile b/drivers/net/ethernet/marvell/octeontx2/af/Makefile
index 3cf4c8285c90..ccea37847df8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/af/Makefile
@@ -11,4 +11,5 @@ rvu_mbox-y := mbox.o rvu_trace.o
rvu_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \
rvu_reg.o rvu_npc.o rvu_debugfs.o ptp.o rvu_npc_fs.o \
rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o rvu_switch.o \
- rvu_sdp.o rvu_npc_hash.o mcs.o mcs_rvu_if.o mcs_cnf10kb.o
+ rvu_sdp.o rvu_npc_hash.o mcs.o mcs_rvu_if.o mcs_cnf10kb.o \
+ rvu_rep.o
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index 27935c54b91b..8216f843a7cd 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -112,6 +112,11 @@ struct mac_ops *get_mac_ops(void *cgxd)
return ((struct cgx *)cgxd)->mac_ops;
}
+u32 cgx_get_fifo_len(void *cgxd)
+{
+ return ((struct cgx *)cgxd)->fifo_len;
+}
+
void cgx_write(struct cgx *cgx, u64 lmac, u64 offset, u64 val)
{
writeq(val, cgx->reg_base + (lmac << cgx->mac_ops->lmac_offset) +
@@ -209,6 +214,24 @@ u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id)
return (cfg & CMR_P2X_SEL_MASK) >> CMR_P2X_SEL_SHIFT;
}
+static u8 cgx_get_nix_resetbit(struct cgx *cgx)
+{
+ int first_lmac;
+ u8 p2x;
+
+ /* non 98XX silicons supports only NIX0 block */
+ if (cgx->pdev->subsystem_device != PCI_SUBSYS_DEVID_98XX)
+ return CGX_NIX0_RESET;
+
+ first_lmac = find_first_bit(&cgx->lmac_bmap, cgx->max_lmac_per_mac);
+ p2x = cgx_lmac_get_p2x(cgx->cgx_id, first_lmac);
+
+ if (p2x == CMR_P2X_SEL_NIX1)
+ return CGX_NIX1_RESET;
+ else
+ return CGX_NIX0_RESET;
+}
+
/* Ensure the required lock for event queue(where asynchronous events are
* posted) is acquired before calling this API. Else an asynchronous event(with
* latest link status) can reach the destination before this function returns
@@ -501,7 +524,7 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id)
u8 num_lmacs;
u32 fifo_len;
- fifo_len = cgx->mac_ops->fifo_len;
+ fifo_len = cgx->fifo_len;
num_lmacs = cgx->mac_ops->get_nr_lmacs(cgx);
switch (num_lmacs) {
@@ -1719,6 +1742,8 @@ static int cgx_lmac_init(struct cgx *cgx)
lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id);
}
+ /* Start X2P reset on given MAC block */
+ cgx->mac_ops->mac_x2p_reset(cgx, true);
return cgx_lmac_verify_fwi_version(cgx);
err_bitmap_free:
@@ -1764,7 +1789,7 @@ static void cgx_populate_features(struct cgx *cgx)
u64 cfg;
cfg = cgx_read(cgx, 0, CGX_CONST);
- cgx->mac_ops->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
+ cgx->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
cgx->max_lmac_per_mac = FIELD_GET(CGX_CONST_MAX_LMACS, cfg);
if (is_dev_rpm(cgx))
@@ -1784,6 +1809,45 @@ static u8 cgx_get_rxid_mapoffset(struct cgx *cgx)
return 0x60;
}
+static void cgx_x2p_reset(void *cgxd, bool enable)
+{
+ struct cgx *cgx = cgxd;
+ int lmac_id;
+ u64 cfg;
+
+ if (enable) {
+ for_each_set_bit(lmac_id, &cgx->lmac_bmap, cgx->max_lmac_per_mac)
+ cgx->mac_ops->mac_enadis_rx(cgx, lmac_id, false);
+
+ usleep_range(1000, 2000);
+
+ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
+ cfg |= cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP;
+ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
+ } else {
+ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
+ cfg &= ~(cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP);
+ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
+ }
+}
+
+static int cgx_enadis_rx(void *cgxd, int lmac_id, bool enable)
+{
+ struct cgx *cgx = cgxd;
+ u64 cfg;
+
+ if (!is_lmac_valid(cgx, lmac_id))
+ return -ENODEV;
+
+ cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
+ if (enable)
+ cfg |= DATA_PKT_RX_EN;
+ else
+ cfg &= ~DATA_PKT_RX_EN;
+ cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg);
+ return 0;
+}
+
static struct mac_ops cgx_mac_ops = {
.name = "cgx",
.csr_offset = 0,
@@ -1815,6 +1879,8 @@ static struct mac_ops cgx_mac_ops = {
.mac_get_pfc_frm_cfg = cgx_lmac_get_pfc_frm_cfg,
.mac_reset = cgx_lmac_reset,
.mac_stats_reset = cgx_stats_reset,
+ .mac_x2p_reset = cgx_x2p_reset,
+ .mac_enadis_rx = cgx_enadis_rx,
};
static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
index dc9ace30554a..1cf12e5c7da8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
@@ -32,6 +32,10 @@
#define CGX_LMAC_TYPE_MASK 0xF
#define CGXX_CMRX_INT 0x040
#define FW_CGX_INT BIT_ULL(1)
+#define CGXX_CMR_GLOBAL_CONFIG 0x08
+#define CGX_NIX0_RESET BIT_ULL(2)
+#define CGX_NIX1_RESET BIT_ULL(3)
+#define CGX_NSCI_DROP BIT_ULL(9)
#define CGXX_CMRX_INT_ENA_W1S 0x058
#define CGXX_CMRX_RX_ID_MAP 0x060
#define CGXX_CMRX_RX_STAT0 0x070
@@ -185,4 +189,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause,
int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause,
int pfvf_idx);
int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr);
+u32 cgx_get_fifo_len(void *cgxd);
#endif /* CGX_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h
index 2436c1ff9ba4..5d84386ed22d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h
@@ -156,6 +156,7 @@ enum nix_scheduler {
#define NIC_HW_MIN_FRS 40
#define NIC_HW_MAX_FRS 9212
#define SDP_HW_MAX_FRS 65535
+#define SDP_HW_MIN_FRS 16
#define CN10K_LMAC_LINK_MAX_FRS 16380 /* 16k - FCS */
#define CN10K_LBK_LINK_MAX_FRS 65535 /* 64k */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
index 9ffc6790c513..6180e68e1765 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
@@ -72,7 +72,6 @@ struct mac_ops {
u8 irq_offset;
u8 int_ena_bit;
u8 lmac_fwi;
- u32 fifo_len;
bool non_contiguous_serdes_lane;
/* RPM & CGX differs in number of Receive/transmit stats */
u8 rx_stats_cnt;
@@ -133,6 +132,8 @@ struct mac_ops {
int (*get_fec_stats)(void *cgxd, int lmac_id,
struct cgx_fec_stats_rsp *rsp);
int (*mac_stats_reset)(void *cgxd, int lmac_id);
+ void (*mac_x2p_reset)(void *cgxd, bool enable);
+ int (*mac_enadis_rx)(void *cgxd, int lmac_id, bool enable);
};
struct cgx {
@@ -142,6 +143,10 @@ struct cgx {
u8 lmac_count;
/* number of LMACs per MAC could be 4 or 8 */
u8 max_lmac_per_mac;
+ /* length of fifo varies depending on the number
+ * of LMACS
+ */
+ u32 fifo_len;
#define MAX_LMAC_COUNT 8
struct lmac *lmac_idmap[MAX_LMAC_COUNT];
struct work_struct cgx_cmd_work;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index 6ea2f3071fe8..62c07407eb94 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -144,6 +144,9 @@ M(LMTST_TBL_SETUP, 0x00a, lmtst_tbl_setup, lmtst_tbl_setup_req, \
msg_rsp) \
M(SET_VF_PERM, 0x00b, set_vf_perm, set_vf_perm, msg_rsp) \
M(PTP_GET_CAP, 0x00c, ptp_get_cap, msg_req, ptp_get_cap_rsp) \
+M(GET_REP_CNT, 0x00d, get_rep_cnt, msg_req, get_rep_cnt_rsp) \
+M(ESW_CFG, 0x00e, esw_cfg, esw_cfg_req, msg_rsp) \
+M(REP_EVENT_NOTIFY, 0x00f, rep_event_notify, rep_event, msg_rsp) \
/* CGX mbox IDs (range 0x200 - 0x3FF) */ \
M(CGX_START_RXTX, 0x200, cgx_start_rxtx, msg_req, msg_rsp) \
M(CGX_STOP_RXTX, 0x201, cgx_stop_rxtx, msg_req, msg_rsp) \
@@ -319,6 +322,7 @@ M(NIX_MCAST_GRP_DESTROY, 0x802c, nix_mcast_grp_destroy, nix_mcast_grp_destroy_re
M(NIX_MCAST_GRP_UPDATE, 0x802d, nix_mcast_grp_update, \
nix_mcast_grp_update_req, \
nix_mcast_grp_update_rsp) \
+M(NIX_LF_STATS, 0x802e, nix_lf_stats, nix_stats_req, nix_stats_rsp) \
/* MCS mbox IDs (range 0xA000 - 0xBFFF) */ \
M(MCS_ALLOC_RESOURCES, 0xa000, mcs_alloc_resources, mcs_alloc_rsrc_req, \
mcs_alloc_rsrc_rsp) \
@@ -380,12 +384,16 @@ M(CPT_INST_LMTST, 0xD00, cpt_inst_lmtst, cpt_inst_lmtst_req, msg_rsp)
#define MBOX_UP_MCS_MESSAGES \
M(MCS_INTR_NOTIFY, 0xE00, mcs_intr_notify, mcs_intr_info, msg_rsp)
+#define MBOX_UP_REP_MESSAGES \
+M(REP_EVENT_UP_NOTIFY, 0xEF0, rep_event_up_notify, rep_event, msg_rsp) \
+
enum {
#define M(_name, _id, _1, _2, _3) MBOX_MSG_ ## _name = _id,
MBOX_MESSAGES
MBOX_UP_CGX_MESSAGES
MBOX_UP_CPT_MESSAGES
MBOX_UP_MCS_MESSAGES
+MBOX_UP_REP_MESSAGES
#undef M
};
@@ -1364,6 +1372,37 @@ struct nix_bandprof_get_hwinfo_rsp {
u32 policer_timeunit;
};
+struct nix_stats_req {
+ struct mbox_msghdr hdr;
+ u8 reset;
+ u16 pcifunc;
+ u64 rsvd;
+};
+
+struct nix_stats_rsp {
+ struct mbox_msghdr hdr;
+ u16 pcifunc;
+ struct {
+ u64 octs;
+ u64 ucast;
+ u64 bcast;
+ u64 mcast;
+ u64 drop;
+ u64 drop_octs;
+ u64 drop_mcast;
+ u64 drop_bcast;
+ u64 err;
+ u64 rsvd[5];
+ } rx;
+ struct {
+ u64 ucast;
+ u64 bcast;
+ u64 mcast;
+ u64 drop;
+ u64 octs;
+ } tx;
+};
+
/* NPC mbox message structs */
#define NPC_MCAM_ENTRY_INVALID 0xFFFF
@@ -1525,6 +1564,41 @@ struct ptp_get_cap_rsp {
u64 cap;
};
+struct get_rep_cnt_rsp {
+ struct mbox_msghdr hdr;
+ u16 rep_cnt;
+ u16 rep_pf_map[64];
+ u64 rsvd;
+};
+
+struct esw_cfg_req {
+ struct mbox_msghdr hdr;
+ u8 ena;
+ u64 rsvd;
+};
+
+struct rep_evt_data {
+ u8 port_state;
+ u8 vf_state;
+ u16 rx_mode;
+ u16 rx_flags;
+ u16 mtu;
+ u8 mac[ETH_ALEN];
+ u64 rsvd[5];
+};
+
+struct rep_event {
+ struct mbox_msghdr hdr;
+ u16 pcifunc;
+#define RVU_EVENT_PORT_STATE BIT_ULL(0)
+#define RVU_EVENT_PFVF_STATE BIT_ULL(1)
+#define RVU_EVENT_MTU_CHANGE BIT_ULL(2)
+#define RVU_EVENT_RX_MODE_CHANGE BIT_ULL(3)
+#define RVU_EVENT_MAC_ADDR_CHANGE BIT_ULL(4)
+ u16 event;
+ struct rep_evt_data evt_data;
+};
+
struct flow_msg {
unsigned char dmac[6];
unsigned char smac[6];
@@ -1563,6 +1637,7 @@ struct flow_msg {
u8 icmp_type;
u8 icmp_code;
__be16 tcp_flags;
+ u16 sq_id;
};
struct npc_install_flow_req {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
index 1b34cf9c9703..2e9945446199 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
@@ -39,6 +39,8 @@ static struct mac_ops rpm_mac_ops = {
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
.mac_reset = rpm_lmac_reset,
.mac_stats_reset = rpm_stats_reset,
+ .mac_x2p_reset = rpm_x2p_reset,
+ .mac_enadis_rx = rpm_enadis_rx,
};
static struct mac_ops rpm2_mac_ops = {
@@ -72,6 +74,8 @@ static struct mac_ops rpm2_mac_ops = {
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
.mac_reset = rpm_lmac_reset,
.mac_stats_reset = rpm_stats_reset,
+ .mac_x2p_reset = rpm_x2p_reset,
+ .mac_enadis_rx = rpm_enadis_rx,
};
bool is_dev_rpm2(void *rpmd)
@@ -467,7 +471,7 @@ u8 rpm_get_lmac_type(void *rpmd, int lmac_id)
int err;
req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req);
- err = cgx_fwi_cmd_generic(req, &resp, rpm, 0);
+ err = cgx_fwi_cmd_generic(req, &resp, rpm, lmac_id);
if (!err)
return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp);
return err;
@@ -480,7 +484,7 @@ u32 rpm_get_lmac_fifo_len(void *rpmd, int lmac_id)
u8 num_lmacs;
u32 fifo_len;
- fifo_len = rpm->mac_ops->fifo_len;
+ fifo_len = rpm->fifo_len;
num_lmacs = rpm->mac_ops->get_nr_lmacs(rpm);
switch (num_lmacs) {
@@ -533,9 +537,9 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
*/
max_lmac = (rpm_read(rpm, 0, CGX_CONST) >> 24) & 0xFF;
if (max_lmac > 4)
- fifo_len = rpm->mac_ops->fifo_len / 2;
+ fifo_len = rpm->fifo_len / 2;
else
- fifo_len = rpm->mac_ops->fifo_len;
+ fifo_len = rpm->fifo_len;
if (lmac_id < 4) {
num_lmacs = hweight8(lmac_info & 0xF);
@@ -699,46 +703,51 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp)
if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE)
return 0;
+ /* latched registers FCFECX_CW_HI/RSFEC_STAT_FAST_DATA_HI_CDC are common
+ * for all counters. Acquire lock to ensure serialized reads
+ */
+ mutex_lock(&rpm->lock);
if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_BASER) {
- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_CCW_LO);
- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_CCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_corr_blks = (val_hi << 16 | val_lo);
- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_NCCW_LO);
- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_NCCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_uncorr_blks = (val_hi << 16 | val_lo);
/* 50G uses 2 Physical serdes lines */
if (rpm->lmac_idmap[lmac_id]->link_info.lmac_type_id ==
LMAC_MODE_50G_R) {
- val_lo = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_VL1_CCW_LO);
- val_hi = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_VL1_CCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_corr_blks += (val_hi << 16 | val_lo);
- val_lo = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_VL1_NCCW_LO);
- val_hi = rpm_read(rpm, lmac_id,
- RPMX_MTI_FCFECX_CW_HI);
+ val_lo = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_VL1_NCCW_LO(lmac_id));
+ val_hi = rpm_read(rpm, 0,
+ RPMX_MTI_FCFECX_CW_HI(lmac_id));
rsp->fec_uncorr_blks += (val_hi << 16 | val_lo);
}
} else {
/* enable RS-FEC capture */
- cfg = rpm_read(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL);
+ cfg = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL);
cfg |= RPMX_RSFEC_RX_CAPTURE | BIT(lmac_id);
- rpm_write(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL, cfg);
+ rpm_write(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL, cfg);
val_lo = rpm_read(rpm, 0,
RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2);
- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
rsp->fec_corr_blks = (val_hi << 32 | val_lo);
val_lo = rpm_read(rpm, 0,
RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3);
- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
rsp->fec_uncorr_blks = (val_hi << 32 | val_lo);
}
+ mutex_unlock(&rpm->lock);
return 0;
}
@@ -763,3 +772,41 @@ int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr)
return 0;
}
+
+void rpm_x2p_reset(void *rpmd, bool enable)
+{
+ rpm_t *rpm = rpmd;
+ int lmac_id;
+ u64 cfg;
+
+ if (enable) {
+ for_each_set_bit(lmac_id, &rpm->lmac_bmap, rpm->max_lmac_per_mac)
+ rpm->mac_ops->mac_enadis_rx(rpm, lmac_id, false);
+
+ usleep_range(1000, 2000);
+
+ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
+ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg | RPM_NIX0_RESET);
+ } else {
+ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
+ cfg &= ~RPM_NIX0_RESET;
+ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg);
+ }
+}
+
+int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable)
+{
+ rpm_t *rpm = rpmd;
+ u64 cfg;
+
+ if (!is_lmac_valid(rpm, lmac_id))
+ return -ENODEV;
+
+ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
+ if (enable)
+ cfg |= RPM_RX_EN;
+ else
+ cfg &= ~RPM_RX_EN;
+ rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
+ return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
index 34b11deb0f3c..b8d3972e096a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
@@ -17,6 +17,8 @@
/* Registers */
#define RPMX_CMRX_CFG 0x00
+#define RPMX_CMR_GLOBAL_CFG 0x08
+#define RPM_NIX0_RESET BIT_ULL(3)
#define RPMX_RX_TS_PREPEND BIT_ULL(22)
#define RPMX_TX_PTP_1S_SUPPORT BIT_ULL(17)
#define RPMX_CMRX_RX_ID_MAP 0x80
@@ -84,16 +86,18 @@
/* FEC stats */
#define RPMX_MTI_STAT_STATN_CONTROL 0x10018
#define RPMX_MTI_STAT_DATA_HI_CDC 0x10038
-#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(27)
+#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(28)
#define RPMX_CMD_CLEAR_RX BIT_ULL(30)
#define RPMX_CMD_CLEAR_TX BIT_ULL(31)
+#define RPMX_MTI_RSFEC_STAT_STATN_CONTROL 0x40018
+#define RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC 0x40000
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2 0x40050
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3 0x40058
-#define RPMX_MTI_FCFECX_VL0_CCW_LO 0x38618
-#define RPMX_MTI_FCFECX_VL0_NCCW_LO 0x38620
-#define RPMX_MTI_FCFECX_VL1_CCW_LO 0x38628
-#define RPMX_MTI_FCFECX_VL1_NCCW_LO 0x38630
-#define RPMX_MTI_FCFECX_CW_HI 0x38638
+#define RPMX_MTI_FCFECX_VL0_CCW_LO(a) (0x38618 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_VL0_NCCW_LO(a) (0x38620 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_VL1_CCW_LO(a) (0x38628 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_VL1_NCCW_LO(a) (0x38630 + ((a) * 0x40))
+#define RPMX_MTI_FCFECX_CW_HI(a) (0x38638 + ((a) * 0x40))
/* CN10KB CSR Declaration */
#define RPM2_CMRX_SW_INT 0x1b0
@@ -137,4 +141,6 @@ bool is_dev_rpm2(void *rpmd);
int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr);
int rpm_stats_reset(void *rpmd, int lmac_id);
+void rpm_x2p_reset(void *rpmd, bool enable);
+int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable);
#endif /* RPM_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 1a97fb9032fa..cd0d7b7774f1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -1162,6 +1162,7 @@ cpt:
}
rvu_program_channels(rvu);
+ cgx_start_linkup(rvu);
err = rvu_mcs_init(rvu);
if (err) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index 5016ba82e142..a383b5ef5b2d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -513,6 +513,11 @@ struct rvu_switch {
u16 start_entry;
};
+struct rep_evtq_ent {
+ struct list_head node;
+ struct rep_event event;
+};
+
struct rvu {
void __iomem *afreg_base;
void __iomem *pfreg_base;
@@ -525,6 +530,7 @@ struct rvu {
struct mutex alias_lock; /* Serialize bar2 alias access */
int vfs; /* Number of VFs attached to RVU */
u16 vf_devid; /* VF devices id */
+ bool def_rule_cntr_en;
int nix_blkaddr[MAX_NIX_BLKS];
/* Mbox */
@@ -594,6 +600,15 @@ struct rvu {
spinlock_t cpt_intr_lock;
struct mutex mbox_lock; /* Serialize mbox up and down msgs */
+ u16 rep_pcifunc;
+ int rep_cnt;
+ u16 *rep2pfvf_map;
+ u8 rep_mode;
+ struct work_struct rep_evt_work;
+ struct workqueue_struct *rep_evt_wq;
+ struct list_head rep_evtq_head;
+ /* Representor event lock */
+ spinlock_t rep_evtq_lock;
};
static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
@@ -852,6 +867,14 @@ bool is_sdp_pfvf(u16 pcifunc);
bool is_sdp_pf(u16 pcifunc);
bool is_sdp_vf(struct rvu *rvu, u16 pcifunc);
+static inline bool is_rep_dev(struct rvu *rvu, u16 pcifunc)
+{
+ if (rvu->rep_pcifunc && rvu->rep_pcifunc == pcifunc)
+ return true;
+
+ return false;
+}
+
/* CGX APIs */
static inline bool is_pf_cgxmapped(struct rvu *rvu, u8 pf)
{
@@ -960,7 +983,11 @@ void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
int group, int alg_idx, int mcam_index);
-
+void __rvu_mcam_remove_counter_from_rule(struct rvu *rvu, u16 pcifunc,
+ struct rvu_npc_mcam_rule *rule);
+void __rvu_mcam_add_counter_to_rule(struct rvu *rvu, u16 pcifunc,
+ struct rvu_npc_mcam_rule *rule,
+ struct npc_install_flow_rsp *rsp);
void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc,
int blkaddr, int *alloc_cnt,
int *enable_cnt);
@@ -985,6 +1012,7 @@ void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 src, struct mcam_entry *entry,
u8 *intf, u8 *ena);
+int npc_config_cntr_default_entries(struct rvu *rvu, bool enable);
bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc);
bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature);
u32 rvu_cgx_get_fifolen(struct rvu *rvu);
@@ -997,6 +1025,7 @@ int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_
int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause);
void rvu_mac_reset(struct rvu *rvu, u16 pcifunc);
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac);
+void cgx_start_linkup(struct rvu *rvu);
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
int type);
bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
@@ -1045,7 +1074,8 @@ int rvu_ndc_fix_locked_cacheline(struct rvu *rvu, int blkaddr);
/* RVU Switch */
void rvu_switch_enable(struct rvu *rvu);
void rvu_switch_disable(struct rvu *rvu);
-void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc);
+void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc, bool ena);
+void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool ena);
int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
u64 pkind, u8 var_len_off, u8 var_len_off_mask,
@@ -1058,4 +1088,9 @@ int rvu_mcs_flr_handler(struct rvu *rvu, u16 pcifunc);
void rvu_mcs_ptp_cfg(struct rvu *rvu, u8 rpm_id, u8 lmac_id, bool ena);
void rvu_mcs_exit(struct rvu *rvu);
+/* Representor APIs */
+int rvu_rep_pf_init(struct rvu *rvu);
+int rvu_rep_install_mcam_rules(struct rvu *rvu);
+void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena);
+int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable);
#endif /* RVU_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
index 266ecbc1b97a..992fa0b82e8d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
@@ -349,6 +349,7 @@ static void rvu_cgx_wq_destroy(struct rvu *rvu)
int rvu_cgx_init(struct rvu *rvu)
{
+ struct mac_ops *mac_ops;
int cgx, err;
void *cgxd;
@@ -375,6 +376,15 @@ int rvu_cgx_init(struct rvu *rvu)
if (err)
return err;
+ /* Clear X2P reset on all MAC blocks */
+ for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) {
+ cgxd = rvu_cgx_pdata(cgx, rvu);
+ if (!cgxd)
+ continue;
+ mac_ops = get_mac_ops(cgxd);
+ mac_ops->mac_x2p_reset(cgxd, false);
+ }
+
/* Register for CGX events */
err = cgx_lmac_event_handler_init(rvu);
if (err)
@@ -382,10 +392,26 @@ int rvu_cgx_init(struct rvu *rvu)
mutex_init(&rvu->cgx_cfg_lock);
- /* Ensure event handler registration is completed, before
- * we turn on the links
- */
- mb();
+ return 0;
+}
+
+void cgx_start_linkup(struct rvu *rvu)
+{
+ unsigned long lmac_bmap;
+ struct mac_ops *mac_ops;
+ int cgx, lmac, err;
+ void *cgxd;
+
+ /* Enable receive on all LMACS */
+ for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
+ cgxd = rvu_cgx_pdata(cgx, rvu);
+ if (!cgxd)
+ continue;
+ mac_ops = get_mac_ops(cgxd);
+ lmac_bmap = cgx_get_lmac_bmap(cgxd);
+ for_each_set_bit(lmac, &lmac_bmap, rvu->hw->lmac_per_cgx)
+ mac_ops->mac_enadis_rx(cgxd, lmac, true);
+ }
/* Do link up for all CGX ports */
for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
@@ -398,8 +424,6 @@ int rvu_cgx_init(struct rvu *rvu)
"Link up process failed to start on cgx %d\n",
cgx);
}
-
- return 0;
}
int rvu_cgx_exit(struct rvu *rvu)
@@ -923,13 +947,12 @@ int rvu_mbox_handler_cgx_features_get(struct rvu *rvu,
u32 rvu_cgx_get_fifolen(struct rvu *rvu)
{
- struct mac_ops *mac_ops;
- u32 fifo_len;
+ void *cgxd = rvu_first_cgx_pdata(rvu);
- mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu));
- fifo_len = mac_ops ? mac_ops->fifo_len : 0;
+ if (!cgxd)
+ return 0;
- return fifo_len;
+ return cgx_get_fifo_len(cgxd);
}
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 87ba77e5026a..148144f5b61d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -45,33 +45,6 @@ enum {
CGX_STAT18,
};
-/* NIX TX stats */
-enum nix_stat_lf_tx {
- TX_UCAST = 0x0,
- TX_BCAST = 0x1,
- TX_MCAST = 0x2,
- TX_DROP = 0x3,
- TX_OCTS = 0x4,
- TX_STATS_ENUM_LAST,
-};
-
-/* NIX RX stats */
-enum nix_stat_lf_rx {
- RX_OCTS = 0x0,
- RX_UCAST = 0x1,
- RX_BCAST = 0x2,
- RX_MCAST = 0x3,
- RX_DROP = 0x4,
- RX_DROP_OCTS = 0x5,
- RX_FCS = 0x6,
- RX_ERR = 0x7,
- RX_DRP_BCAST = 0x8,
- RX_DRP_MCAST = 0x9,
- RX_DRP_L3BCAST = 0xa,
- RX_DRP_L3MCAST = 0xb,
- RX_STATS_ENUM_LAST,
-};
-
static char *cgx_rx_stats_fields[] = {
[CGX_STAT0] = "Received packets",
[CGX_STAT1] = "Octets of received packets",
@@ -663,16 +636,16 @@ static ssize_t rvu_dbg_lmtst_map_table_display(struct file *filp,
RVU_DEBUG_FOPS(lmtst_map_table, lmtst_map_table_display, NULL);
-static void get_lf_str_list(struct rvu_block block, int pcifunc,
+static void get_lf_str_list(const struct rvu_block *block, int pcifunc,
char *lfs)
{
- int lf = 0, seq = 0, len = 0, prev_lf = block.lf.max;
+ int lf = 0, seq = 0, len = 0, prev_lf = block->lf.max;
- for_each_set_bit(lf, block.lf.bmap, block.lf.max) {
- if (lf >= block.lf.max)
+ for_each_set_bit(lf, block->lf.bmap, block->lf.max) {
+ if (lf >= block->lf.max)
break;
- if (block.fn_map[lf] != pcifunc)
+ if (block->fn_map[lf] != pcifunc)
continue;
if (lf == prev_lf + 1) {
@@ -719,7 +692,7 @@ static int get_max_column_width(struct rvu *rvu)
if (!strlen(block.name))
continue;
- get_lf_str_list(block, pcifunc, buf);
+ get_lf_str_list(&block, pcifunc, buf);
if (lf_str_size <= strlen(buf))
lf_str_size = strlen(buf) + 1;
}
@@ -803,7 +776,7 @@ static ssize_t rvu_dbg_rsrc_attach_status(struct file *filp,
continue;
len = 0;
lfs[len] = '\0';
- get_lf_str_list(block, pcifunc, lfs);
+ get_lf_str_list(&block, pcifunc, lfs);
if (strlen(lfs))
flag = 1;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
index 7498ab429963..dab4deca893f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
@@ -1238,6 +1238,7 @@ enum rvu_af_dl_param_id {
RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
+ RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
};
@@ -1358,6 +1359,32 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink
return 0;
}
+static int rvu_af_dl_npc_def_rule_cntr_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+
+ ctx->val.vbool = rvu->def_rule_cntr_en;
+
+ return 0;
+}
+
+static int rvu_af_dl_npc_def_rule_cntr_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx,
+ struct netlink_ext_ack *extack)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+ int err;
+
+ err = npc_config_cntr_default_entries(rvu, ctx->val.vbool);
+ if (!err)
+ rvu->def_rule_cntr_en = ctx->val.vbool;
+
+ return err;
+}
+
static int rvu_af_dl_nix_maxlf_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
@@ -1444,6 +1471,11 @@ static const struct devlink_param rvu_af_dl_params[] = {
rvu_af_dl_npc_mcam_high_zone_percent_get,
rvu_af_dl_npc_mcam_high_zone_percent_set,
rvu_af_dl_npc_mcam_high_zone_percent_validate),
+ DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
+ "npc_def_rule_cntr", DEVLINK_PARAM_TYPE_BOOL,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ rvu_af_dl_npc_def_rule_cntr_get,
+ rvu_af_dl_npc_def_rule_cntr_set, NULL),
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
"nix_maxlf", DEVLINK_PARAM_TYPE_U16,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
@@ -1468,6 +1500,9 @@ static int rvu_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
struct rvu *rvu = rvu_dl->rvu;
struct rvu_switch *rswitch;
+ if (rvu->rep_mode)
+ return -EOPNOTSUPP;
+
rswitch = &rvu->rswitch;
*mode = rswitch->mode;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index da69350c6f76..5d5a01dbbca1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -31,6 +31,7 @@ static int nix_free_all_bandprof(struct rvu *rvu, u16 pcifunc);
static void nix_clear_ratelimit_aggr(struct rvu *rvu, struct nix_hw *nix_hw,
u32 leaf_prof);
static const char *nix_get_ctx_name(int ctype);
+static int nix_get_tx_link(struct rvu *rvu, u16 pcifunc);
enum mc_tbl_sz {
MC_TBL_SZ_256,
@@ -312,7 +313,9 @@ static bool is_valid_txschq(struct rvu *rvu, int blkaddr,
/* TLs aggegating traffic are shared across PF and VFs */
if (lvl >= hw->cap.nix_tx_aggr_lvl) {
- if (rvu_get_pf(map_func) != rvu_get_pf(pcifunc))
+ if ((nix_get_tx_link(rvu, map_func) !=
+ nix_get_tx_link(rvu, pcifunc)) &&
+ (rvu_get_pf(map_func) != rvu_get_pf(pcifunc)))
return false;
else
return true;
@@ -360,7 +363,6 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf,
cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id, pkind);
rvu_npc_set_pkind(rvu, pkind, pfvf);
-
break;
case NIX_INTF_TYPE_LBK:
vf = (pcifunc & RVU_PFVF_FUNC_MASK) - 1;
@@ -584,6 +586,9 @@ int rvu_mbox_handler_nix_bp_disable(struct rvu *rvu,
if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK)
return 0;
+ if (is_sdp_pfvf(pcifunc))
+ type = NIX_INTF_TYPE_SDP;
+
pfvf = rvu_get_pfvf(rvu, pcifunc);
err = nix_get_struct_ptrs(rvu, pcifunc, &nix_hw, &blkaddr);
if (err)
@@ -1614,6 +1619,12 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
cfg = NPC_TX_DEF_PKIND;
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf), cfg);
+ if (is_rep_dev(rvu, pcifunc)) {
+ pfvf->tx_chan_base = RVU_SWITCH_LBK_CHAN;
+ pfvf->tx_chan_cnt = 1;
+ goto exit;
+ }
+
intf = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX;
if (is_sdp_pfvf(pcifunc))
intf = NIX_INTF_TYPE_SDP;
@@ -1684,6 +1695,9 @@ int rvu_mbox_handler_nix_lf_free(struct rvu *rvu, struct nix_lf_free_req *req,
if (nixlf < 0)
return NIX_AF_ERR_AF_LF_INVALID;
+ if (is_rep_dev(rvu, pcifunc))
+ goto free_lf;
+
if (req->flags & NIX_LF_DISABLE_FLOWS)
rvu_npc_disable_mcam_entries(rvu, pcifunc, nixlf);
else
@@ -1695,6 +1709,7 @@ int rvu_mbox_handler_nix_lf_free(struct rvu *rvu, struct nix_lf_free_req *req,
nix_interface_deinit(rvu, pcifunc, nixlf);
+free_lf:
/* Reset this NIX LF */
err = rvu_lf_reset(rvu, block, nixlf);
if (err) {
@@ -2007,7 +2022,8 @@ static void nix_get_txschq_range(struct rvu *rvu, u16 pcifunc,
struct rvu_hwinfo *hw = rvu->hw;
int pf = rvu_get_pf(pcifunc);
- if (is_lbk_vf(rvu, pcifunc)) { /* LBK links */
+ /* LBK links */
+ if (is_lbk_vf(rvu, pcifunc) || is_rep_dev(rvu, pcifunc)) {
*start = hw->cap.nix_txsch_per_cgx_lmac * link;
*end = *start + hw->cap.nix_txsch_per_lbk_lmac;
} else if (is_pf_cgxmapped(rvu, pf)) { /* CGX links */
@@ -2760,7 +2776,7 @@ void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc,
int schq;
u64 cfg;
- if (!is_pf_cgxmapped(rvu, pf))
+ if (!is_pf_cgxmapped(rvu, pf) && !is_rep_dev(rvu, pcifunc))
return;
cfg = enable ? (BIT_ULL(12) | RVU_SWITCH_LBK_CHAN) : 0;
@@ -4393,8 +4409,6 @@ int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu,
if (test_bit(PF_SET_VF_TRUSTED, &pfvf->flags) && from_vf)
ether_addr_copy(pfvf->default_mac, req->mac_addr);
- rvu_switch_update_rules(rvu, pcifunc);
-
return 0;
}
@@ -4555,7 +4569,7 @@ int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req,
if (!nix_hw)
return NIX_AF_ERR_INVALID_NIXBLK;
- if (is_lbk_vf(rvu, pcifunc))
+ if (is_lbk_vf(rvu, pcifunc) || is_rep_dev(rvu, pcifunc))
rvu_get_lbk_link_max_frs(rvu, &max_mtu);
else
rvu_get_lmac_link_max_frs(rvu, &max_mtu);
@@ -4583,6 +4597,8 @@ int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req,
/* For VFs of PF0 ingress is LBK port, so config LBK link */
pfvf = rvu_get_pfvf(rvu, pcifunc);
link = hw->cgx_links + pfvf->lbkid;
+ } else if (is_rep_dev(rvu, pcifunc)) {
+ link = hw->cgx_links + 0;
}
if (link < 0)
@@ -4674,7 +4690,7 @@ static void nix_link_config(struct rvu *rvu, int blkaddr,
if (hw->sdp_links) {
link = hw->cgx_links + hw->lbk_links;
rvu_write64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link),
- SDP_HW_MAX_FRS << 16 | NIC_HW_MIN_FRS);
+ SDP_HW_MAX_FRS << 16 | SDP_HW_MIN_FRS);
}
/* Get MCS external bypass status for CN10K-B */
@@ -5166,7 +5182,7 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
{
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
- int nixlf, err;
+ int nixlf, err, pf;
err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
if (err)
@@ -5182,7 +5198,11 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
pfvf = rvu_get_pfvf(rvu, pcifunc);
set_bit(NIXLF_INITIALIZED, &pfvf->flags);
- rvu_switch_update_rules(rvu, pcifunc);
+ rvu_switch_update_rules(rvu, pcifunc, true);
+
+ pf = rvu_get_pf(pcifunc);
+ if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode)
+ rvu_rep_notify_pfvf_state(rvu, pcifunc, true);
return rvu_cgx_start_stop_io(rvu, pcifunc, true);
}
@@ -5192,7 +5212,7 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
{
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
- int nixlf, err;
+ int nixlf, err, pf;
err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
if (err)
@@ -5210,8 +5230,12 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
if (err)
return err;
+ rvu_switch_update_rules(rvu, pcifunc, false);
rvu_cgx_tx_enable(rvu, pcifunc, true);
+ pf = rvu_get_pf(pcifunc);
+ if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode)
+ rvu_rep_notify_pfvf_state(rvu, pcifunc, false);
return 0;
}
@@ -5239,6 +5263,9 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
clear_bit(NIXLF_INITIALIZED, &pfvf->flags);
+ if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode)
+ rvu_rep_notify_pfvf_state(rvu, pcifunc, false);
+
rvu_cgx_start_stop_io(rvu, pcifunc, false);
if (pfvf->sq_ctx) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
index 97722ce8c4cb..821fe242f821 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -2691,6 +2691,49 @@ void npc_mcam_rsrcs_reserve(struct rvu *rvu, int blkaddr, int entry_idx)
npc_mcam_set_bit(mcam, entry_idx);
}
+int npc_config_cntr_default_entries(struct rvu *rvu, bool enable)
+{
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ struct npc_install_flow_rsp rsp;
+ struct rvu_npc_mcam_rule *rule;
+ int blkaddr;
+
+ blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+ if (blkaddr < 0)
+ return -EINVAL;
+
+ mutex_lock(&mcam->lock);
+ list_for_each_entry(rule, &mcam->mcam_rules, list) {
+ if (!is_mcam_entry_enabled(rvu, mcam, blkaddr, rule->entry))
+ continue;
+ if (!rule->default_rule)
+ continue;
+ if (enable && !rule->has_cntr) { /* Alloc and map new counter */
+ __rvu_mcam_add_counter_to_rule(rvu, rule->owner,
+ rule, &rsp);
+ if (rsp.counter < 0) {
+ dev_err(rvu->dev,
+ "%s: Failed to allocate cntr for default rule (err=%d)\n",
+ __func__, rsp.counter);
+ break;
+ }
+ npc_map_mcam_entry_and_cntr(rvu, mcam, blkaddr,
+ rule->entry, rsp.counter);
+ /* Reset counter before use */
+ rvu_write64(rvu, blkaddr,
+ NPC_AF_MATCH_STATX(rule->cntr), 0x0);
+ }
+
+ /* Free and unmap counter */
+ if (!enable && rule->has_cntr)
+ __rvu_mcam_remove_counter_from_rule(rvu, rule->owner,
+ rule);
+ }
+ mutex_unlock(&mcam->lock);
+
+ return 0;
+}
+
int rvu_mbox_handler_npc_mcam_alloc_entry(struct rvu *rvu,
struct npc_mcam_alloc_entry_req *req,
struct npc_mcam_alloc_entry_rsp *rsp)
@@ -2975,9 +3018,9 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
return rc;
}
-int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
- struct npc_mcam_alloc_counter_req *req,
- struct npc_mcam_alloc_counter_rsp *rsp)
+static int __npc_mcam_alloc_counter(struct rvu *rvu,
+ struct npc_mcam_alloc_counter_req *req,
+ struct npc_mcam_alloc_counter_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 pcifunc = req->hdr.pcifunc;
@@ -2998,11 +3041,9 @@ int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
if (!req->contig && req->count > NPC_MAX_NONCONTIG_COUNTERS)
return NPC_MCAM_INVALID_REQ;
- mutex_lock(&mcam->lock);
/* Check if unused counters are available or not */
if (!rvu_rsrc_free_count(&mcam->counters)) {
- mutex_unlock(&mcam->lock);
return NPC_MCAM_ALLOC_FAILED;
}
@@ -3035,12 +3076,27 @@ int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
}
}
- mutex_unlock(&mcam->lock);
return 0;
}
-int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
- struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
+int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
+ struct npc_mcam_alloc_counter_req *req,
+ struct npc_mcam_alloc_counter_rsp *rsp)
+{
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ int err;
+
+ mutex_lock(&mcam->lock);
+
+ err = __npc_mcam_alloc_counter(rvu, req, rsp);
+
+ mutex_unlock(&mcam->lock);
+ return err;
+}
+
+static int __npc_mcam_free_counter(struct rvu *rvu,
+ struct npc_mcam_oper_counter_req *req,
+ struct msg_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 index, entry = 0;
@@ -3050,10 +3106,8 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
if (blkaddr < 0)
return NPC_MCAM_INVALID_REQ;
- mutex_lock(&mcam->lock);
err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
if (err) {
- mutex_unlock(&mcam->lock);
return err;
}
@@ -3077,10 +3131,66 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
index, req->cntr);
}
- mutex_unlock(&mcam->lock);
return 0;
}
+int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
+ struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
+{
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ int err;
+
+ mutex_lock(&mcam->lock);
+
+ err = __npc_mcam_free_counter(rvu, req, rsp);
+
+ mutex_unlock(&mcam->lock);
+
+ return err;
+}
+
+void __rvu_mcam_remove_counter_from_rule(struct rvu *rvu, u16 pcifunc,
+ struct rvu_npc_mcam_rule *rule)
+{
+ struct npc_mcam_oper_counter_req free_req = { 0 };
+ struct msg_rsp free_rsp;
+
+ if (!rule->has_cntr)
+ return;
+
+ free_req.hdr.pcifunc = pcifunc;
+ free_req.cntr = rule->cntr;
+
+ __npc_mcam_free_counter(rvu, &free_req, &free_rsp);
+ rule->has_cntr = false;
+}
+
+void __rvu_mcam_add_counter_to_rule(struct rvu *rvu, u16 pcifunc,
+ struct rvu_npc_mcam_rule *rule,
+ struct npc_install_flow_rsp *rsp)
+{
+ struct npc_mcam_alloc_counter_req cntr_req = { 0 };
+ struct npc_mcam_alloc_counter_rsp cntr_rsp = { 0 };
+ int err;
+
+ cntr_req.hdr.pcifunc = pcifunc;
+ cntr_req.contig = true;
+ cntr_req.count = 1;
+
+ /* we try to allocate a counter to track the stats of this
+ * rule. If counter could not be allocated then proceed
+ * without counter because counters are limited than entries.
+ */
+ err = __npc_mcam_alloc_counter(rvu, &cntr_req, &cntr_rsp);
+ if (!err && cntr_rsp.count) {
+ rule->cntr = cntr_rsp.cntr;
+ rule->has_cntr = true;
+ rsp->counter = rule->cntr;
+ } else {
+ rsp->counter = err;
+ }
+}
+
int rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu *rvu,
struct npc_mcam_unmap_counter_req *req, struct msg_rsp *rsp)
{
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
index 150635de2bd5..da69e454662a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
@@ -1081,44 +1081,26 @@ static void rvu_mcam_add_rule(struct npc_mcam *mcam,
static void rvu_mcam_remove_counter_from_rule(struct rvu *rvu, u16 pcifunc,
struct rvu_npc_mcam_rule *rule)
{
- struct npc_mcam_oper_counter_req free_req = { 0 };
- struct msg_rsp free_rsp;
+ struct npc_mcam *mcam = &rvu->hw->mcam;
- if (!rule->has_cntr)
- return;
+ mutex_lock(&mcam->lock);
- free_req.hdr.pcifunc = pcifunc;
- free_req.cntr = rule->cntr;
+ __rvu_mcam_remove_counter_from_rule(rvu, pcifunc, rule);
- rvu_mbox_handler_npc_mcam_free_counter(rvu, &free_req, &free_rsp);
- rule->has_cntr = false;
+ mutex_unlock(&mcam->lock);
}
static void rvu_mcam_add_counter_to_rule(struct rvu *rvu, u16 pcifunc,
struct rvu_npc_mcam_rule *rule,
struct npc_install_flow_rsp *rsp)
{
- struct npc_mcam_alloc_counter_req cntr_req = { 0 };
- struct npc_mcam_alloc_counter_rsp cntr_rsp = { 0 };
- int err;
+ struct npc_mcam *mcam = &rvu->hw->mcam;
- cntr_req.hdr.pcifunc = pcifunc;
- cntr_req.contig = true;
- cntr_req.count = 1;
+ mutex_lock(&mcam->lock);
- /* we try to allocate a counter to track the stats of this
- * rule. If counter could not be allocated then proceed
- * without counter because counters are limited than entries.
- */
- err = rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req,
- &cntr_rsp);
- if (!err && cntr_rsp.count) {
- rule->cntr = cntr_rsp.cntr;
- rule->has_cntr = true;
- rsp->counter = rule->cntr;
- } else {
- rsp->counter = err;
- }
+ __rvu_mcam_add_counter_to_rule(rvu, pcifunc, rule, rsp);
+
+ mutex_unlock(&mcam->lock);
}
static int npc_mcast_update_action_index(struct rvu *rvu, struct npc_install_flow_req *req,
@@ -1416,6 +1398,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
struct npc_install_flow_rsp *rsp)
{
bool from_vf = !!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK);
+ bool from_rep_dev = !!is_rep_dev(rvu, req->hdr.pcifunc);
struct rvu_switch *rswitch = &rvu->rswitch;
int blkaddr, nixlf, err;
struct rvu_pfvf *pfvf;
@@ -1472,14 +1455,19 @@ process_flow:
/* AF installing for a PF/VF */
if (!req->hdr.pcifunc)
target = req->vf;
+
/* PF installing for its VF */
- else if (!from_vf && req->vf) {
+ if (!from_vf && req->vf && !from_rep_dev) {
target = (req->hdr.pcifunc & ~RVU_PFVF_FUNC_MASK) | req->vf;
pf_set_vfs_mac = req->default_rule &&
(req->features & BIT_ULL(NPC_DMAC));
}
- /* msg received from PF/VF */
+
+ /* Representor device installing for a representee */
+ if (from_rep_dev && req->vf)
+ target = req->vf;
else
+ /* msg received from PF/VF */
target = req->hdr.pcifunc;
/* ignore chan_mask in case pf func is not AF, revisit later */
@@ -1492,8 +1480,10 @@ process_flow:
pfvf = rvu_get_pfvf(rvu, target);
+ if (from_rep_dev)
+ req->channel = pfvf->rx_chan_base;
/* PF installing for its VF */
- if (req->hdr.pcifunc && !from_vf && req->vf)
+ if (req->hdr.pcifunc && !from_vf && req->vf && !from_rep_dev)
set_bit(PF_SET_VF_CFG, &pfvf->flags);
/* update req destination mac addr */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
index 2b299fa85159..62cdc714ba57 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
@@ -445,6 +445,7 @@
#define NIX_CONST_MAX_BPIDS GENMASK_ULL(23, 12)
#define NIX_CONST_SDP_CHANS GENMASK_ULL(11, 0)
+#define NIX_VLAN_ETYPE_MASK GENMASK_ULL(63, 48)
#define NIX_AF_MDQ_PARENT_MASK GENMASK_ULL(24, 16)
#define NIX_AF_TL4_PARENT_MASK GENMASK_ULL(23, 16)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c
new file mode 100644
index 000000000000..052ae5923e3a
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell RVU Admin Function driver
+ *
+ * Copyright (C) 2024 Marvell.
+ *
+ */
+
+#include <linux/bitfield.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "rvu.h"
+#include "rvu_reg.h"
+
+#define M(_name, _id, _fn_name, _req_type, _rsp_type) \
+static struct _req_type __maybe_unused \
+*otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid) \
+{ \
+ struct _req_type *req; \
+ \
+ req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \
+ &rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \
+ sizeof(struct _rsp_type)); \
+ if (!req) \
+ return NULL; \
+ req->hdr.sig = OTX2_MBOX_REQ_SIG; \
+ req->hdr.id = _id; \
+ return req; \
+}
+
+MBOX_UP_REP_MESSAGES
+#undef M
+
+static int rvu_rep_up_notify(struct rvu *rvu, struct rep_event *event)
+{
+ struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, event->pcifunc);
+ struct rep_event *msg;
+ int pf;
+
+ pf = rvu_get_pf(event->pcifunc);
+
+ if (event->event & RVU_EVENT_MAC_ADDR_CHANGE)
+ ether_addr_copy(pfvf->mac_addr, event->evt_data.mac);
+
+ mutex_lock(&rvu->mbox_lock);
+ msg = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf);
+ if (!msg) {
+ mutex_unlock(&rvu->mbox_lock);
+ return -ENOMEM;
+ }
+
+ msg->hdr.pcifunc = event->pcifunc;
+ msg->event = event->event;
+
+ memcpy(&msg->evt_data, &event->evt_data, sizeof(struct rep_evt_data));
+
+ otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);
+
+ otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);
+
+ mutex_unlock(&rvu->mbox_lock);
+ return 0;
+}
+
+static void rvu_rep_wq_handler(struct work_struct *work)
+{
+ struct rvu *rvu = container_of(work, struct rvu, rep_evt_work);
+ struct rep_evtq_ent *qentry;
+ struct rep_event *event;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&rvu->rep_evtq_lock, flags);
+ qentry = list_first_entry_or_null(&rvu->rep_evtq_head,
+ struct rep_evtq_ent,
+ node);
+ if (qentry)
+ list_del(&qentry->node);
+
+ spin_unlock_irqrestore(&rvu->rep_evtq_lock, flags);
+ if (!qentry)
+ break; /* nothing more to process */
+
+ event = &qentry->event;
+
+ rvu_rep_up_notify(rvu, event);
+ kfree(qentry);
+ } while (1);
+}
+
+int rvu_mbox_handler_rep_event_notify(struct rvu *rvu, struct rep_event *req,
+ struct msg_rsp *rsp)
+{
+ struct rep_evtq_ent *qentry;
+
+ qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC);
+ if (!qentry)
+ return -ENOMEM;
+
+ qentry->event = *req;
+ spin_lock(&rvu->rep_evtq_lock);
+ list_add_tail(&qentry->node, &rvu->rep_evtq_head);
+ spin_unlock(&rvu->rep_evtq_lock);
+ queue_work(rvu->rep_evt_wq, &rvu->rep_evt_work);
+ return 0;
+}
+
+int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable)
+{
+ struct rep_event *req;
+ int pf;
+
+ if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)))
+ return 0;
+
+ pf = rvu_get_pf(rvu->rep_pcifunc);
+
+ mutex_lock(&rvu->mbox_lock);
+ req = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf);
+ if (!req) {
+ mutex_unlock(&rvu->mbox_lock);
+ return -ENOMEM;
+ }
+
+ req->hdr.pcifunc = rvu->rep_pcifunc;
+ req->event |= RVU_EVENT_PFVF_STATE;
+ req->pcifunc = pcifunc;
+ req->evt_data.vf_state = enable;
+
+ otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);
+ otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);
+
+ mutex_unlock(&rvu->mbox_lock);
+ return 0;
+}
+
+#define RVU_LF_RX_STATS(reg) \
+ rvu_read64(rvu, blkaddr, NIX_AF_LFX_RX_STATX(nixlf, reg))
+
+#define RVU_LF_TX_STATS(reg) \
+ rvu_read64(rvu, blkaddr, NIX_AF_LFX_TX_STATX(nixlf, reg))
+
+int rvu_mbox_handler_nix_lf_stats(struct rvu *rvu,
+ struct nix_stats_req *req,
+ struct nix_stats_rsp *rsp)
+{
+ u16 pcifunc = req->pcifunc;
+ int nixlf, blkaddr, err;
+ struct msg_req rst_req;
+ struct msg_rsp rst_rsp;
+
+ err = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr);
+ if (err)
+ return 0;
+
+ if (req->reset) {
+ rst_req.hdr.pcifunc = pcifunc;
+ return rvu_mbox_handler_nix_stats_rst(rvu, &rst_req, &rst_rsp);
+ }
+ rsp->rx.octs = RVU_LF_RX_STATS(RX_OCTS);
+ rsp->rx.ucast = RVU_LF_RX_STATS(RX_UCAST);
+ rsp->rx.bcast = RVU_LF_RX_STATS(RX_BCAST);
+ rsp->rx.mcast = RVU_LF_RX_STATS(RX_MCAST);
+ rsp->rx.drop = RVU_LF_RX_STATS(RX_DROP);
+ rsp->rx.err = RVU_LF_RX_STATS(RX_ERR);
+ rsp->rx.drop_octs = RVU_LF_RX_STATS(RX_DROP_OCTS);
+ rsp->rx.drop_mcast = RVU_LF_RX_STATS(RX_DRP_MCAST);
+ rsp->rx.drop_bcast = RVU_LF_RX_STATS(RX_DRP_BCAST);
+
+ rsp->tx.octs = RVU_LF_TX_STATS(TX_OCTS);
+ rsp->tx.ucast = RVU_LF_TX_STATS(TX_UCAST);
+ rsp->tx.bcast = RVU_LF_TX_STATS(TX_BCAST);
+ rsp->tx.mcast = RVU_LF_TX_STATS(TX_MCAST);
+ rsp->tx.drop = RVU_LF_TX_STATS(TX_DROP);
+
+ rsp->pcifunc = req->pcifunc;
+ return 0;
+}
+
+static u16 rvu_rep_get_vlan_id(struct rvu *rvu, u16 pcifunc)
+{
+ int id;
+
+ for (id = 0; id < rvu->rep_cnt; id++)
+ if (rvu->rep2pfvf_map[id] == pcifunc)
+ return id;
+ return 0;
+}
+
+static int rvu_rep_tx_vlan_cfg(struct rvu *rvu, u16 pcifunc,
+ u16 vlan_tci, int *vidx)
+{
+ struct nix_vtag_config_rsp rsp = {};
+ struct nix_vtag_config req = {};
+ u64 etype = ETH_P_8021Q;
+ int err;
+
+ /* Insert vlan tag */
+ req.hdr.pcifunc = pcifunc;
+ req.vtag_size = VTAGSIZE_T4;
+ req.cfg_type = 0; /* tx vlan cfg */
+ req.tx.cfg_vtag0 = true;
+ req.tx.vtag0 = FIELD_PREP(NIX_VLAN_ETYPE_MASK, etype) | vlan_tci;
+
+ err = rvu_mbox_handler_nix_vtag_cfg(rvu, &req, &rsp);
+ if (err) {
+ dev_err(rvu->dev, "Tx vlan config failed\n");
+ return err;
+ }
+ *vidx = rsp.vtag0_idx;
+ return 0;
+}
+
+static int rvu_rep_rx_vlan_cfg(struct rvu *rvu, u16 pcifunc)
+{
+ struct nix_vtag_config req = {};
+ struct nix_vtag_config_rsp rsp;
+
+ /* config strip, capture and size */
+ req.hdr.pcifunc = pcifunc;
+ req.vtag_size = VTAGSIZE_T4;
+ req.cfg_type = 1; /* rx vlan cfg */
+ req.rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0;
+ req.rx.strip_vtag = true;
+ req.rx.capture_vtag = false;
+
+ return rvu_mbox_handler_nix_vtag_cfg(rvu, &req, &rsp);
+}
+
+static int rvu_rep_install_rx_rule(struct rvu *rvu, u16 pcifunc,
+ u16 entry, bool rte)
+{
+ struct npc_install_flow_req req = {};
+ struct npc_install_flow_rsp rsp = {};
+ struct rvu_pfvf *pfvf;
+ u16 vlan_tci, rep_id;
+
+ pfvf = rvu_get_pfvf(rvu, pcifunc);
+
+ /* To steer the traffic from Representee to Representor */
+ rep_id = rvu_rep_get_vlan_id(rvu, pcifunc);
+ if (rte) {
+ vlan_tci = rep_id | BIT_ULL(8);
+ req.vf = rvu->rep_pcifunc;
+ req.op = NIX_RX_ACTIONOP_UCAST;
+ req.index = rep_id;
+ } else {
+ vlan_tci = rep_id;
+ req.vf = pcifunc;
+ req.op = NIX_RX_ACTION_DEFAULT;
+ }
+
+ rvu_rep_rx_vlan_cfg(rvu, req.vf);
+ req.entry = entry;
+ req.hdr.pcifunc = 0; /* AF is requester */
+ req.features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_VLAN_ETYPE_CTAG);
+ req.vtag0_valid = true;
+ req.vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0;
+ req.packet.vlan_etype = cpu_to_be16(ETH_P_8021Q);
+ req.mask.vlan_etype = cpu_to_be16(ETH_P_8021Q);
+ req.packet.vlan_tci = cpu_to_be16(vlan_tci);
+ req.mask.vlan_tci = cpu_to_be16(0xffff);
+
+ req.channel = RVU_SWITCH_LBK_CHAN;
+ req.chan_mask = 0xffff;
+ req.intf = pfvf->nix_rx_intf;
+
+ return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
+}
+
+static int rvu_rep_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry,
+ bool rte)
+{
+ struct npc_install_flow_req req = {};
+ struct npc_install_flow_rsp rsp = {};
+ struct rvu_pfvf *pfvf;
+ int vidx, err;
+ u16 vlan_tci;
+ u8 lbkid;
+
+ pfvf = rvu_get_pfvf(rvu, pcifunc);
+ vlan_tci = rvu_rep_get_vlan_id(rvu, pcifunc);
+ if (rte)
+ vlan_tci |= BIT_ULL(8);
+
+ err = rvu_rep_tx_vlan_cfg(rvu, pcifunc, vlan_tci, &vidx);
+ if (err)
+ return err;
+
+ lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
+ req.hdr.pcifunc = 0; /* AF is requester */
+ if (rte) {
+ req.vf = pcifunc;
+ } else {
+ req.vf = rvu->rep_pcifunc;
+ req.packet.sq_id = vlan_tci;
+ req.mask.sq_id = 0xffff;
+ }
+
+ req.entry = entry;
+ req.intf = pfvf->nix_tx_intf;
+ req.op = NIX_TX_ACTIONOP_UCAST_CHAN;
+ req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN;
+ req.set_cntr = 1;
+ req.vtag0_def = vidx;
+ req.vtag0_op = 1;
+ return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
+}
+
+int rvu_rep_install_mcam_rules(struct rvu *rvu)
+{
+ struct rvu_switch *rswitch = &rvu->rswitch;
+ u16 start = rswitch->start_entry;
+ struct rvu_hwinfo *hw = rvu->hw;
+ u16 pcifunc, entry = 0;
+ int pf, vf, numvfs;
+ int err, nixlf, i;
+ u8 rep;
+
+ for (pf = 1; pf < hw->total_pfs; pf++) {
+ if (!is_pf_cgxmapped(rvu, pf))
+ continue;
+
+ pcifunc = pf << RVU_PFVF_PF_SHIFT;
+ rvu_get_nix_blkaddr(rvu, pcifunc);
+ rep = true;
+ for (i = 0; i < 2; i++) {
+ err = rvu_rep_install_rx_rule(rvu, pcifunc,
+ start + entry, rep);
+ if (err)
+ return err;
+ rswitch->entry2pcifunc[entry++] = pcifunc;
+
+ err = rvu_rep_install_tx_rule(rvu, pcifunc,
+ start + entry, rep);
+ if (err)
+ return err;
+ rswitch->entry2pcifunc[entry++] = pcifunc;
+ rep = false;
+ }
+
+ rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
+ for (vf = 0; vf < numvfs; vf++) {
+ pcifunc = pf << RVU_PFVF_PF_SHIFT |
+ ((vf + 1) & RVU_PFVF_FUNC_MASK);
+ rvu_get_nix_blkaddr(rvu, pcifunc);
+
+ /* Skip installimg rules if nixlf is not attached */
+ err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
+ if (err)
+ continue;
+ rep = true;
+ for (i = 0; i < 2; i++) {
+ err = rvu_rep_install_rx_rule(rvu, pcifunc,
+ start + entry,
+ rep);
+ if (err)
+ return err;
+ rswitch->entry2pcifunc[entry++] = pcifunc;
+
+ err = rvu_rep_install_tx_rule(rvu, pcifunc,
+ start + entry,
+ rep);
+ if (err)
+ return err;
+ rswitch->entry2pcifunc[entry++] = pcifunc;
+ rep = false;
+ }
+ }
+ }
+
+ /* Initialize the wq for handling REP events */
+ spin_lock_init(&rvu->rep_evtq_lock);
+ INIT_LIST_HEAD(&rvu->rep_evtq_head);
+ INIT_WORK(&rvu->rep_evt_work, rvu_rep_wq_handler);
+ rvu->rep_evt_wq = alloc_workqueue("rep_evt_wq", 0, 0);
+ if (!rvu->rep_evt_wq) {
+ dev_err(rvu->dev, "REP workqueue allocation failed\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena)
+{
+ struct rvu_switch *rswitch = &rvu->rswitch;
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ u32 max = rswitch->used_entries;
+ int blkaddr;
+ u16 entry;
+
+ if (!rswitch->used_entries)
+ return;
+
+ blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+
+ if (blkaddr < 0)
+ return;
+
+ rvu_switch_enable_lbk_link(rvu, pcifunc, ena);
+ mutex_lock(&mcam->lock);
+ for (entry = 0; entry < max; entry++) {
+ if (rswitch->entry2pcifunc[entry] == pcifunc)
+ npc_enable_mcam_entry(rvu, mcam, blkaddr, entry, ena);
+ }
+ mutex_unlock(&mcam->lock);
+}
+
+int rvu_rep_pf_init(struct rvu *rvu)
+{
+ u16 pcifunc = rvu->rep_pcifunc;
+ struct rvu_pfvf *pfvf;
+
+ pfvf = rvu_get_pfvf(rvu, pcifunc);
+ set_bit(NIXLF_INITIALIZED, &pfvf->flags);
+ rvu_switch_enable_lbk_link(rvu, pcifunc, true);
+ rvu_rep_rx_vlan_cfg(rvu, pcifunc);
+ return 0;
+}
+
+int rvu_mbox_handler_esw_cfg(struct rvu *rvu, struct esw_cfg_req *req,
+ struct msg_rsp *rsp)
+{
+ if (req->hdr.pcifunc != rvu->rep_pcifunc)
+ return 0;
+
+ rvu->rep_mode = req->ena;
+
+ if (!rvu->rep_mode)
+ rvu_npc_free_mcam_entries(rvu, req->hdr.pcifunc, -1);
+
+ return 0;
+}
+
+int rvu_mbox_handler_get_rep_cnt(struct rvu *rvu, struct msg_req *req,
+ struct get_rep_cnt_rsp *rsp)
+{
+ int pf, vf, numvfs, hwvf, rep = 0;
+ u16 pcifunc;
+
+ rvu->rep_pcifunc = req->hdr.pcifunc;
+ rsp->rep_cnt = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;
+ rvu->rep_cnt = rsp->rep_cnt;
+
+ rvu->rep2pfvf_map = devm_kzalloc(rvu->dev, rvu->rep_cnt *
+ sizeof(u16), GFP_KERNEL);
+ if (!rvu->rep2pfvf_map)
+ return -ENOMEM;
+
+ for (pf = 0; pf < rvu->hw->total_pfs; pf++) {
+ if (!is_pf_cgxmapped(rvu, pf))
+ continue;
+ pcifunc = pf << RVU_PFVF_PF_SHIFT;
+ rvu->rep2pfvf_map[rep] = pcifunc;
+ rsp->rep_pf_map[rep] = pcifunc;
+ rep++;
+ rvu_get_pf_numvfs(rvu, pf, &numvfs, &hwvf);
+ for (vf = 0; vf < numvfs; vf++) {
+ rvu->rep2pfvf_map[rep] = pcifunc |
+ ((vf + 1) & RVU_PFVF_FUNC_MASK);
+ rsp->rep_pf_map[rep] = rvu->rep2pfvf_map[rep];
+ rep++;
+ }
+ }
+ return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h
index fc8da2090657..77ac94cb2ec4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h
@@ -823,4 +823,30 @@ enum nix_tx_vtag_op {
#define VTAG_STRIP BIT_ULL(4)
#define VTAG_CAPTURE BIT_ULL(5)
+/* NIX TX stats */
+enum nix_stat_lf_tx {
+ TX_UCAST = 0x0,
+ TX_BCAST = 0x1,
+ TX_MCAST = 0x2,
+ TX_DROP = 0x3,
+ TX_OCTS = 0x4,
+ TX_STATS_ENUM_LAST,
+};
+
+/* NIX RX stats */
+enum nix_stat_lf_rx {
+ RX_OCTS = 0x0,
+ RX_UCAST = 0x1,
+ RX_BCAST = 0x2,
+ RX_MCAST = 0x3,
+ RX_DROP = 0x4,
+ RX_DROP_OCTS = 0x5,
+ RX_FCS = 0x6,
+ RX_ERR = 0x7,
+ RX_DRP_BCAST = 0x8,
+ RX_DRP_MCAST = 0x9,
+ RX_DRP_L3BCAST = 0xa,
+ RX_DRP_L3MCAST = 0xb,
+ RX_STATS_ENUM_LAST,
+};
#endif /* RVU_STRUCT_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
index 854045ed3b06..268efb7c1c15 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
@@ -8,7 +8,7 @@
#include <linux/bitfield.h>
#include "rvu.h"
-static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)
+void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct nix_hw *nix_hw;
@@ -166,6 +166,8 @@ void rvu_switch_enable(struct rvu *rvu)
alloc_req.contig = true;
alloc_req.count = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;
+ if (rvu->rep_mode)
+ alloc_req.count = alloc_req.count * 4;
ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &alloc_req,
&alloc_rsp);
if (ret) {
@@ -189,7 +191,12 @@ void rvu_switch_enable(struct rvu *rvu)
rswitch->used_entries = alloc_rsp.count;
rswitch->start_entry = alloc_rsp.entry;
- ret = rvu_switch_install_rules(rvu);
+ if (rvu->rep_mode) {
+ rvu_rep_pf_init(rvu);
+ ret = rvu_rep_install_mcam_rules(rvu);
+ } else {
+ ret = rvu_switch_install_rules(rvu);
+ }
if (ret)
goto uninstall_rules;
@@ -222,6 +229,9 @@ void rvu_switch_disable(struct rvu *rvu)
if (!rswitch->used_entries)
return;
+ if (rvu->rep_mode)
+ goto free_ents;
+
for (pf = 1; pf < hw->total_pfs; pf++) {
if (!is_pf_cgxmapped(rvu, pf))
continue;
@@ -249,6 +259,7 @@ void rvu_switch_disable(struct rvu *rvu)
}
}
+free_ents:
uninstall_req.start = rswitch->start_entry;
uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1;
free_req.all = 1;
@@ -258,12 +269,15 @@ void rvu_switch_disable(struct rvu *rvu)
kfree(rswitch->entry2pcifunc);
}
-void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc)
+void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc, bool ena)
{
struct rvu_switch *rswitch = &rvu->rswitch;
u32 max = rswitch->used_entries;
u16 entry;
+ if (rvu->rep_mode)
+ return rvu_rep_update_rules(rvu, pcifunc, ena);
+
if (!rswitch->used_entries)
return;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
index 64a97a0a10ed..dbc971266865 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
@@ -5,11 +5,13 @@
obj-$(CONFIG_OCTEONTX2_PF) += rvu_nicpf.o otx2_ptp.o
obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.o
+obj-$(CONFIG_RVU_ESWITCH) += rvu_rep.o
rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o \
otx2_devlink.o qos_sq.o qos.o
rvu_nicvf-y := otx2_vf.o
+rvu_rep-y := rep.o
rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o
rvu_nicpf-$(CONFIG_MACSEC) += cn10k_macsec.o
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
index c1c99d7054f8..a15cc86635d6 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
@@ -72,7 +72,7 @@ int cn10k_lmtst_init(struct otx2_nic *pfvf)
}
EXPORT_SYMBOL(cn10k_lmtst_init);
-int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
+int cn10k_sq_aq_init(void *dev, u16 qidx, u8 chan_offset, u16 sqb_aura)
{
struct nix_cn10k_aq_enq_req *aq;
struct otx2_nic *pfvf = dev;
@@ -88,7 +88,7 @@ int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
aq->sq.ena = 1;
aq->sq.smq = otx2_get_smq_idx(pfvf, qidx);
aq->sq.smq_rr_weight = mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
- aq->sq.default_chan = pfvf->hw.tx_chan_base;
+ aq->sq.default_chan = pfvf->hw.tx_chan_base + chan_offset;
aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */
aq->sq.sqb_aura = sqb_aura;
aq->sq.sq_int_ena = NIX_SQINT_BITS;
@@ -203,6 +203,11 @@ int cn10k_alloc_leaf_profile(struct otx2_nic *pfvf, u16 *leaf)
rsp = (struct nix_bandprof_alloc_rsp *)
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ rc = PTR_ERR(rsp);
+ goto out;
+ }
+
if (!rsp->prof_count[BAND_PROF_LEAF_LAYER]) {
rc = -EIO;
goto out;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
index c1861f7de254..e3f0bce9908f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
@@ -26,7 +26,7 @@ static inline int mtu_to_dwrr_weight(struct otx2_nic *pfvf, int mtu)
int cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx);
-int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
+int cn10k_sq_aq_init(void *dev, u16 qidx, u8 chan_offset, u16 sqb_aura);
int cn10k_lmtst_init(struct otx2_nic *pfvf);
int cn10k_free_all_ipolicers(struct otx2_nic *pfvf);
int cn10k_alloc_matchall_ipolicer(struct otx2_nic *pfvf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index 87d5776e3b88..523ecb798a7a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -83,6 +83,7 @@ int otx2_update_rq_stats(struct otx2_nic *pfvf, int qidx)
otx2_nix_rq_op_stats(&rq->stats, pfvf, qidx);
return 1;
}
+EXPORT_SYMBOL(otx2_update_rq_stats);
int otx2_update_sq_stats(struct otx2_nic *pfvf, int qidx)
{
@@ -99,6 +100,7 @@ int otx2_update_sq_stats(struct otx2_nic *pfvf, int qidx)
otx2_nix_sq_op_stats(&sq->stats, pfvf, qidx);
return 1;
}
+EXPORT_SYMBOL(otx2_update_sq_stats);
void otx2_get_dev_stats(struct otx2_nic *pfvf)
{
@@ -227,7 +229,7 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
u16 maxlen;
int err;
- maxlen = otx2_get_max_mtu(pfvf) + OTX2_ETH_HLEN + OTX2_HW_TIMESTAMP_LEN;
+ maxlen = pfvf->hw.max_mtu + OTX2_ETH_HLEN + OTX2_HW_TIMESTAMP_LEN;
mutex_lock(&pfvf->mbox.lock);
req = otx2_mbox_alloc_msg_nix_set_hw_frs(&pfvf->mbox);
@@ -236,7 +238,7 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
return -ENOMEM;
}
- req->maxlen = pfvf->netdev->mtu + OTX2_ETH_HLEN + OTX2_HW_TIMESTAMP_LEN;
+ req->maxlen = mtu + OTX2_ETH_HLEN + OTX2_HW_TIMESTAMP_LEN;
/* Use max receive length supported by hardware for loopback devices */
if (is_otx2_lbkvf(pfvf->pdev))
@@ -246,13 +248,14 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
mutex_unlock(&pfvf->mbox.lock);
return err;
}
+EXPORT_SYMBOL(otx2_hw_set_mtu);
int otx2_config_pause_frm(struct otx2_nic *pfvf)
{
struct cgx_pause_frm_cfg *req;
int err;
- if (is_otx2_lbkvf(pfvf->pdev))
+ if (is_otx2_lbkvf(pfvf->pdev) || is_otx2_sdp_rep(pfvf->pdev))
return 0;
mutex_lock(&pfvf->mbox.lock);
@@ -646,12 +649,22 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for
req->reg[2] = NIX_AF_MDQX_SCHEDULE(schq);
req->regval[2] = dwrr_val;
} else if (lvl == NIX_TXSCH_LVL_TL4) {
+ int sdp_chan = hw->tx_chan_base + prio;
+
+ if (is_otx2_sdp_rep(pfvf->pdev))
+ prio = 0;
parent = schq_list[NIX_TXSCH_LVL_TL3][prio];
req->reg[0] = NIX_AF_TL4X_PARENT(schq);
req->regval[0] = (u64)parent << 16;
req->num_regs++;
req->reg[1] = NIX_AF_TL4X_SCHEDULE(schq);
req->regval[1] = dwrr_val;
+ if (is_otx2_sdp_rep(pfvf->pdev)) {
+ req->num_regs++;
+ req->reg[2] = NIX_AF_TL4X_SDP_LINK_CFG(schq);
+ req->regval[2] = BIT_ULL(12) | BIT_ULL(13) |
+ (sdp_chan & 0xff);
+ }
} else if (lvl == NIX_TXSCH_LVL_TL3) {
parent = schq_list[NIX_TXSCH_LVL_TL2][prio];
req->reg[0] = NIX_AF_TL3X_PARENT(schq);
@@ -659,7 +672,8 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for
req->num_regs++;
req->reg[1] = NIX_AF_TL3X_SCHEDULE(schq);
req->regval[1] = dwrr_val;
- if (lvl == hw->txschq_link_cfg_lvl) {
+ if (lvl == hw->txschq_link_cfg_lvl &&
+ !is_otx2_sdp_rep(pfvf->pdev)) {
req->num_regs++;
req->reg[2] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, hw->tx_link);
/* Enable this queue and backpressure
@@ -676,7 +690,8 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for
req->reg[1] = NIX_AF_TL2X_SCHEDULE(schq);
req->regval[1] = (u64)hw->txschq_aggr_lvl_rr_prio << 24 | dwrr_val;
- if (lvl == hw->txschq_link_cfg_lvl) {
+ if (lvl == hw->txschq_link_cfg_lvl &&
+ !is_otx2_sdp_rep(pfvf->pdev)) {
req->num_regs++;
req->reg[2] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, hw->tx_link);
/* Enable this queue and backpressure
@@ -735,6 +750,7 @@ EXPORT_SYMBOL(otx2_smq_flush);
int otx2_txsch_alloc(struct otx2_nic *pfvf)
{
+ int chan_cnt = pfvf->hw.tx_chan_cnt;
struct nix_txsch_alloc_req *req;
struct nix_txsch_alloc_rsp *rsp;
int lvl, schq, rc;
@@ -747,6 +763,12 @@ int otx2_txsch_alloc(struct otx2_nic *pfvf)
/* Request one schq per level */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
req->schq[lvl] = 1;
+
+ if (is_otx2_sdp_rep(pfvf->pdev) && chan_cnt > 1) {
+ req->schq[NIX_TXSCH_LVL_SMQ] = chan_cnt;
+ req->schq[NIX_TXSCH_LVL_TL4] = chan_cnt;
+ }
+
rc = otx2_sync_mbox_msg(&pfvf->mbox);
if (rc)
return rc;
@@ -757,10 +779,12 @@ int otx2_txsch_alloc(struct otx2_nic *pfvf)
return PTR_ERR(rsp);
/* Setup transmit scheduler list */
- for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ pfvf->hw.txschq_cnt[lvl] = rsp->schq[lvl];
for (schq = 0; schq < rsp->schq[lvl]; schq++)
pfvf->hw.txschq_list[lvl][schq] =
rsp->schq_list[lvl][schq];
+ }
pfvf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl;
pfvf->hw.txschq_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio;
@@ -798,12 +822,15 @@ EXPORT_SYMBOL(otx2_txschq_free_one);
void otx2_txschq_stop(struct otx2_nic *pfvf)
{
- int lvl, schq;
+ int lvl, schq, idx;
/* free non QOS TLx nodes */
- for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
- otx2_txschq_free_one(pfvf, lvl,
- pfvf->hw.txschq_list[lvl][0]);
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (idx = 0; idx < pfvf->hw.txschq_cnt[lvl]; idx++) {
+ otx2_txschq_free_one(pfvf, lvl,
+ pfvf->hw.txschq_list[lvl][idx]);
+ }
+ }
/* Clear the txschq list */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
@@ -883,7 +910,7 @@ static int otx2_rq_init(struct otx2_nic *pfvf, u16 qidx, u16 lpb_aura)
return otx2_sync_mbox_msg(&pfvf->mbox);
}
-int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
+int otx2_sq_aq_init(void *dev, u16 qidx, u8 chan_offset, u16 sqb_aura)
{
struct otx2_nic *pfvf = dev;
struct otx2_snd_queue *sq;
@@ -902,7 +929,7 @@ int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
aq->sq.ena = 1;
aq->sq.smq = otx2_get_smq_idx(pfvf, qidx);
aq->sq.smq_rr_quantum = mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
- aq->sq.default_chan = pfvf->hw.tx_chan_base;
+ aq->sq.default_chan = pfvf->hw.tx_chan_base + chan_offset;
aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */
aq->sq.sqb_aura = sqb_aura;
aq->sq.sq_int_ena = NIX_SQINT_BITS;
@@ -925,6 +952,7 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
struct otx2_qset *qset = &pfvf->qset;
struct otx2_snd_queue *sq;
struct otx2_pool *pool;
+ u8 chan_offset;
int err;
pool = &pfvf->qset.pool[sqb_aura];
@@ -971,7 +999,8 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
sq->stats.bytes = 0;
sq->stats.pkts = 0;
- err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura);
+ chan_offset = qidx % pfvf->hw.tx_chan_cnt;
+ err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, chan_offset, sqb_aura);
if (err) {
kfree(sq->sg);
sq->sg = NULL;
@@ -1738,6 +1767,8 @@ void mbox_handler_nix_lf_alloc(struct otx2_nic *pfvf,
pfvf->hw.sqb_size = rsp->sqb_size;
pfvf->hw.rx_chan_base = rsp->rx_chan_base;
pfvf->hw.tx_chan_base = rsp->tx_chan_base;
+ pfvf->hw.rx_chan_cnt = rsp->rx_chan_cnt;
+ pfvf->hw.tx_chan_cnt = rsp->tx_chan_cnt;
pfvf->hw.lso_tsov4_idx = rsp->lso_tsov4_idx;
pfvf->hw.lso_tsov6_idx = rsp->lso_tsov6_idx;
pfvf->hw.cgx_links = rsp->cgx_links;
@@ -1782,6 +1813,7 @@ void otx2_free_cints(struct otx2_nic *pfvf, int n)
free_irq(vector, &qset->napi[qidx]);
}
}
+EXPORT_SYMBOL(otx2_free_cints);
void otx2_set_cints_affinity(struct otx2_nic *pfvf)
{
@@ -1837,6 +1869,10 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
if (!rc) {
rsp = (struct nix_hw_info *)
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ rc = PTR_ERR(rsp);
+ goto out;
+ }
/* HW counts VLAN insertion bytes (8 for double tag)
* irrespective of whether SQE is requesting to insert VLAN
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index f27a3456ae64..566848663fea 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -29,6 +29,7 @@
#include "otx2_devlink.h"
#include <rvu_trace.h>
#include "qos.h"
+#include "rep.h"
/* IPv4 flag more fragment bit */
#define IPV4_FLAG_MORE 0x20
@@ -41,6 +42,8 @@
#define PCI_SUBSYS_DEVID_96XX_RVU_PFVF 0xB200
#define PCI_SUBSYS_DEVID_CN10K_B_RVU_PFVF 0xBD00
+#define PCI_DEVID_OCTEONTX2_SDP_REP 0xA0F7
+
/* PCI BAR nos */
#define PCI_CFG_REG_BAR_NUM 2
#define PCI_MBOX_BAR_NUM 4
@@ -120,33 +123,6 @@ enum otx2_errcodes_re {
ERRCODE_IL4_CSUM = 0x22,
};
-/* NIX TX stats */
-enum nix_stat_lf_tx {
- TX_UCAST = 0x0,
- TX_BCAST = 0x1,
- TX_MCAST = 0x2,
- TX_DROP = 0x3,
- TX_OCTS = 0x4,
- TX_STATS_ENUM_LAST,
-};
-
-/* NIX RX stats */
-enum nix_stat_lf_rx {
- RX_OCTS = 0x0,
- RX_UCAST = 0x1,
- RX_BCAST = 0x2,
- RX_MCAST = 0x3,
- RX_DROP = 0x4,
- RX_DROP_OCTS = 0x5,
- RX_FCS = 0x6,
- RX_ERR = 0x7,
- RX_DRP_BCAST = 0x8,
- RX_DRP_MCAST = 0x9,
- RX_DRP_L3BCAST = 0xa,
- RX_DRP_L3MCAST = 0xb,
- RX_STATS_ENUM_LAST,
-};
-
struct otx2_dev_stats {
u64 rx_bytes;
u64 rx_frames;
@@ -224,15 +200,19 @@ struct otx2_hw {
/* NIX */
u8 txschq_link_cfg_lvl;
+ u8 txschq_cnt[NIX_TXSCH_LVL_CNT];
u8 txschq_aggr_lvl_rr_prio;
u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
u16 matchall_ipolicer;
u32 dwrr_mtu;
+ u32 max_mtu;
u8 smq_link_type;
/* HW settings, coalescing etc */
u16 rx_chan_base;
u16 tx_chan_base;
+ u8 rx_chan_cnt;
+ u8 tx_chan_cnt;
u16 cq_qcount_wait;
u16 cq_ecount_wait;
u16 rq_skid;
@@ -367,7 +347,8 @@ struct otx2_flow_config {
};
struct dev_hw_ops {
- int (*sq_aq_init)(void *dev, u16 qidx, u16 sqb_aura);
+ int (*sq_aq_init)(void *dev, u16 qidx, u8 chan_offset,
+ u16 sqb_aura);
void (*sqe_flush)(void *dev, struct otx2_snd_queue *sq,
int size, int qidx);
int (*refill_pool_ptrs)(void *dev, struct otx2_cq_queue *cq);
@@ -465,6 +446,8 @@ struct otx2_nic {
#define OTX2_FLAG_PTP_ONESTEP_SYNC BIT_ULL(15)
#define OTX2_FLAG_ADPTV_INT_COAL_ENABLED BIT_ULL(16)
#define OTX2_FLAG_TC_MARK_ENABLED BIT_ULL(17)
+#define OTX2_FLAG_REP_MODE_ENABLED BIT_ULL(18)
+#define OTX2_FLAG_PORT_UP BIT_ULL(19)
u64 flags;
u64 *cq_op_addr;
@@ -532,11 +515,19 @@ struct otx2_nic {
#if IS_ENABLED(CONFIG_MACSEC)
struct cn10k_mcs_cfg *macsec_cfg;
#endif
+
+#if IS_ENABLED(CONFIG_RVU_ESWITCH)
+ struct rep_dev **reps;
+ int rep_cnt;
+ u16 rep_pf_map[RVU_MAX_REP];
+ u16 esw_mode;
+#endif
};
static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
{
- return pdev->device == PCI_DEVID_OCTEONTX2_RVU_AFVF;
+ return (pdev->device == PCI_DEVID_OCTEONTX2_RVU_AFVF) ||
+ (pdev->device == PCI_DEVID_RVU_REP);
}
static inline bool is_96xx_A0(struct pci_dev *pdev)
@@ -551,6 +542,11 @@ static inline bool is_96xx_B0(struct pci_dev *pdev)
(pdev->subsystem_device == PCI_SUBSYS_DEVID_96XX_RVU_PFVF);
}
+static inline bool is_otx2_sdp_rep(struct pci_dev *pdev)
+{
+ return pdev->device == PCI_DEVID_OCTEONTX2_SDP_REP;
+}
+
/* REVID for PCIe devices.
* Bits 0..1: minor pass, bit 3..2: major pass
* bits 7..4: midr id
@@ -913,15 +909,19 @@ static inline void otx2_dma_unmap_page(struct otx2_nic *pfvf,
static inline u16 otx2_get_smq_idx(struct otx2_nic *pfvf, u16 qidx)
{
u16 smq;
+ int idx;
+
#ifdef CONFIG_DCB
if (qidx < NIX_PF_PFC_PRIO_MAX && pfvf->pfc_alloc_status[qidx])
return pfvf->pfc_schq_list[NIX_TXSCH_LVL_SMQ][qidx];
#endif
/* check if qidx falls under QOS queues */
- if (qidx >= pfvf->hw.non_qos_queues)
+ if (qidx >= pfvf->hw.non_qos_queues) {
smq = pfvf->qos.qid_to_sqmap[qidx - pfvf->hw.non_qos_queues];
- else
- smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+ } else {
+ idx = qidx % pfvf->hw.txschq_cnt[NIX_TXSCH_LVL_SMQ];
+ smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][idx];
+ }
return smq;
}
@@ -988,14 +988,28 @@ int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable);
void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx);
void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura);
-int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
-int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
+int otx2_sq_aq_init(void *dev, u16 qidx, u8 chan_offset, u16 sqb_aura);
+int cn10k_sq_aq_init(void *dev, u16 qidx, u8 chan_offset, u16 sqb_aura);
int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq,
dma_addr_t *dma);
int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
int stack_pages, int numptrs, int buf_size, int type);
int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
int pool_id, int numptrs);
+int otx2_init_rsrc(struct pci_dev *pdev, struct otx2_nic *pf);
+void otx2_free_queue_mem(struct otx2_qset *qset);
+int otx2_alloc_queue_mem(struct otx2_nic *pf);
+int otx2_init_hw_resources(struct otx2_nic *pfvf);
+void otx2_free_hw_resources(struct otx2_nic *pf);
+int otx2_wq_init(struct otx2_nic *pf);
+int otx2_check_pf_usable(struct otx2_nic *pf);
+int otx2_pfaf_mbox_init(struct otx2_nic *pf);
+int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af);
+int otx2_realloc_msix_vectors(struct otx2_nic *pf);
+void otx2_pfaf_mbox_destroy(struct otx2_nic *pf);
+void otx2_disable_mbox_intr(struct otx2_nic *pf);
+void otx2_disable_napi(struct otx2_nic *pf);
+irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq);
/* RSS configuration APIs*/
int otx2_rss_init(struct otx2_nic *pfvf);
@@ -1127,4 +1141,12 @@ u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid);
void otx2_qos_config_txschq(struct otx2_nic *pfvf);
void otx2_clean_qos_queues(struct otx2_nic *pfvf);
+int rvu_event_up_notify(struct otx2_nic *pf, struct rep_event *info);
+int otx2_setup_tc_cls_flower(struct otx2_nic *nic,
+ struct flow_cls_offload *cls_flower);
+
+static inline int mcam_entry_cmp(const void *a, const void *b)
+{
+ return *(u16 *)a - *(u16 *)b;
+}
#endif /* OTX2_COMMON_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
index aa01110f04a3..294fba58b670 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
@@ -315,6 +315,11 @@ int otx2_config_priority_flow_ctrl(struct otx2_nic *pfvf)
if (!otx2_sync_mbox_msg(&pfvf->mbox)) {
rsp = (struct cgx_pfc_rsp *)
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ err = PTR_ERR(rsp);
+ goto unlock;
+ }
+
if (req->rx_pause != rsp->rx_pause || req->tx_pause != rsp->tx_pause) {
dev_warn(pfvf->dev,
"Failed to config PFC\n");
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
index 53f14aa944bd..33ec9a7f7c03 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
@@ -141,7 +141,56 @@ static const struct devlink_param otx2_dl_params[] = {
otx2_dl_ucast_flt_cnt_validate),
};
+#ifdef CONFIG_RVU_ESWITCH
+static int otx2_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
+{
+ struct otx2_devlink *otx2_dl = devlink_priv(devlink);
+ struct otx2_nic *pfvf = otx2_dl->pfvf;
+
+ if (!otx2_rep_dev(pfvf->pdev))
+ return -EOPNOTSUPP;
+
+ *mode = pfvf->esw_mode;
+
+ return 0;
+}
+
+static int otx2_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_devlink *otx2_dl = devlink_priv(devlink);
+ struct otx2_nic *pfvf = otx2_dl->pfvf;
+ int ret = 0;
+
+ if (!otx2_rep_dev(pfvf->pdev))
+ return -EOPNOTSUPP;
+
+ if (pfvf->esw_mode == mode)
+ return 0;
+
+ switch (mode) {
+ case DEVLINK_ESWITCH_MODE_LEGACY:
+ rvu_rep_destroy(pfvf);
+ break;
+ case DEVLINK_ESWITCH_MODE_SWITCHDEV:
+ ret = rvu_rep_create(pfvf, extack);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!ret)
+ pfvf->esw_mode = mode;
+
+ return ret;
+}
+#endif
+
static const struct devlink_ops otx2_devlink_ops = {
+#ifdef CONFIG_RVU_ESWITCH
+ .eswitch_mode_get = otx2_devlink_eswitch_mode_get,
+ .eswitch_mode_set = otx2_devlink_eswitch_mode_set,
+#endif
};
int otx2_register_dl(struct otx2_nic *pfvf)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c
index 80d853b343f9..2046dd0da00d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c
@@ -28,6 +28,11 @@ static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
if (!err) {
rsp = (struct cgx_mac_addr_add_rsp *)
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ mutex_unlock(&pf->mbox.lock);
+ return PTR_ERR(rsp);
+ }
+
*dmac_index = rsp->index;
}
@@ -200,6 +205,10 @@ int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos)
rsp = (struct cgx_mac_addr_update_rsp *)
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ rc = PTR_ERR(rsp);
+ goto out;
+ }
pf->flow_cfg->bmap_to_dmacindex[bit_pos] = rsp->index;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 32468c663605..2d53dc77ef1e 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -85,26 +85,22 @@ static void otx2_get_qset_strings(struct otx2_nic *pfvf, u8 **data, int qset)
int start_qidx = qset * pfvf->hw.rx_queues;
int qidx, stats;
- for (qidx = 0; qidx < pfvf->hw.rx_queues; qidx++) {
- for (stats = 0; stats < otx2_n_queue_stats; stats++) {
- sprintf(*data, "rxq%d: %s", qidx + start_qidx,
- otx2_queue_stats[stats].name);
- *data += ETH_GSTRING_LEN;
- }
- }
+ for (qidx = 0; qidx < pfvf->hw.rx_queues; qidx++)
+ for (stats = 0; stats < otx2_n_queue_stats; stats++)
+ ethtool_sprintf(data, "rxq%d: %s", qidx + start_qidx,
+ otx2_queue_stats[stats].name);
- for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
- for (stats = 0; stats < otx2_n_queue_stats; stats++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++)
+ for (stats = 0; stats < otx2_n_queue_stats; stats++)
if (qidx >= pfvf->hw.non_qos_queues)
- sprintf(*data, "txq_qos%d: %s",
- qidx + start_qidx - pfvf->hw.non_qos_queues,
- otx2_queue_stats[stats].name);
+ ethtool_sprintf(data, "txq_qos%d: %s",
+ qidx + start_qidx -
+ pfvf->hw.non_qos_queues,
+ otx2_queue_stats[stats].name);
else
- sprintf(*data, "txq%d: %s", qidx + start_qidx,
- otx2_queue_stats[stats].name);
- *data += ETH_GSTRING_LEN;
- }
- }
+ ethtool_sprintf(data, "txq%d: %s",
+ qidx + start_qidx,
+ otx2_queue_stats[stats].name);
}
static void otx2_get_strings(struct net_device *netdev, u32 sset, u8 *data)
@@ -115,36 +111,25 @@ static void otx2_get_strings(struct net_device *netdev, u32 sset, u8 *data)
if (sset != ETH_SS_STATS)
return;
- for (stats = 0; stats < otx2_n_dev_stats; stats++) {
- memcpy(data, otx2_dev_stats[stats].name, ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (stats = 0; stats < otx2_n_dev_stats; stats++)
+ ethtool_puts(&data, otx2_dev_stats[stats].name);
- for (stats = 0; stats < otx2_n_drv_stats; stats++) {
- memcpy(data, otx2_drv_stats[stats].name, ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (stats = 0; stats < otx2_n_drv_stats; stats++)
+ ethtool_puts(&data, otx2_drv_stats[stats].name);
otx2_get_qset_strings(pfvf, &data, 0);
if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag)) {
- for (stats = 0; stats < CGX_RX_STATS_COUNT; stats++) {
- sprintf(data, "cgx_rxstat%d: ", stats);
- data += ETH_GSTRING_LEN;
- }
+ for (stats = 0; stats < CGX_RX_STATS_COUNT; stats++)
+ ethtool_sprintf(&data, "cgx_rxstat%d: ", stats);
- for (stats = 0; stats < CGX_TX_STATS_COUNT; stats++) {
- sprintf(data, "cgx_txstat%d: ", stats);
- data += ETH_GSTRING_LEN;
- }
+ for (stats = 0; stats < CGX_TX_STATS_COUNT; stats++)
+ ethtool_sprintf(&data, "cgx_txstat%d: ", stats);
}
- strcpy(data, "reset_count");
- data += ETH_GSTRING_LEN;
- sprintf(data, "Fec Corrected Errors: ");
- data += ETH_GSTRING_LEN;
- sprintf(data, "Fec Uncorrected Errors: ");
- data += ETH_GSTRING_LEN;
+ ethtool_puts(&data, "reset_count");
+ ethtool_puts(&data, "Fec Corrected Errors: ");
+ ethtool_puts(&data, "Fec Uncorrected Errors: ");
}
static void otx2_get_qset_stats(struct otx2_nic *pfvf,
@@ -343,6 +328,11 @@ static void otx2_get_pauseparam(struct net_device *netdev,
if (!otx2_sync_mbox_msg(&pfvf->mbox)) {
rsp = (struct cgx_pause_frm_cfg *)
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return;
+ }
+
pause->rx_pause = rsp->rx_pause;
pause->tx_pause = rsp->tx_pause;
}
@@ -1072,6 +1062,11 @@ static int otx2_set_fecparam(struct net_device *netdev,
rsp = (struct fec_mode *)otx2_mbox_get_rsp(&pfvf->mbox.mbox,
0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ err = PTR_ERR(rsp);
+ goto end;
+ }
+
if (rsp->fec >= 0)
pfvf->linfo.fec = rsp->fec;
else
@@ -1365,20 +1360,15 @@ static void otx2vf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
if (sset != ETH_SS_STATS)
return;
- for (stats = 0; stats < otx2_n_dev_stats; stats++) {
- memcpy(data, otx2_dev_stats[stats].name, ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (stats = 0; stats < otx2_n_dev_stats; stats++)
+ ethtool_puts(&data, otx2_dev_stats[stats].name);
- for (stats = 0; stats < otx2_n_drv_stats; stats++) {
- memcpy(data, otx2_drv_stats[stats].name, ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (stats = 0; stats < otx2_n_drv_stats; stats++)
+ ethtool_puts(&data, otx2_drv_stats[stats].name);
otx2_get_qset_strings(vf, &data, 0);
- strcpy(data, "reset_count");
- data += ETH_GSTRING_LEN;
+ ethtool_puts(&data, "reset_count");
}
static void otx2vf_get_ethtool_stats(struct net_device *netdev,
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 98c31a16c70b..47bfd1fb37d4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -64,11 +64,6 @@ static int otx2_free_ntuple_mcam_entries(struct otx2_nic *pfvf)
return 0;
}
-static int mcam_entry_cmp(const void *a, const void *b)
-{
- return *(u16 *)a - *(u16 *)b;
-}
-
int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
{
struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
@@ -119,6 +114,8 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp))
+ goto exit;
for (ent = 0; ent < rsp->count; ent++)
flow_cfg->flow_ent[ent + allocated] = rsp->entry_list[ent];
@@ -197,6 +194,10 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf)
rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp)) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return PTR_ERR(rsp);
+ }
if (rsp->count != req->count) {
netdev_info(pfvf->netdev,
@@ -232,6 +233,10 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf)
frsp = (struct npc_get_field_status_rsp *)otx2_mbox_get_rsp
(&pfvf->mbox.mbox, 0, &freq->hdr);
+ if (IS_ERR(frsp)) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return PTR_ERR(frsp);
+ }
if (frsp->enable) {
pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 5492dea547a1..e310f99b1736 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -519,6 +519,7 @@ static void otx2_pfvf_mbox_up_handler(struct work_struct *work)
switch (msg->id) {
case MBOX_MSG_CGX_LINK_EVENT:
+ case MBOX_MSG_REP_EVENT_UP_NOTIFY:
break;
default:
if (msg->rc)
@@ -832,6 +833,9 @@ static void otx2_handle_link_event(struct otx2_nic *pf)
struct cgx_link_user_info *linfo = &pf->linfo;
struct net_device *netdev = pf->netdev;
+ if (pf->flags & OTX2_FLAG_PORT_UP)
+ return;
+
pr_info("%s NIC Link is %s %d Mbps %s duplex\n", netdev->name,
linfo->link_up ? "UP" : "DOWN", linfo->speed,
linfo->full_duplex ? "Full" : "Half");
@@ -844,6 +848,35 @@ static void otx2_handle_link_event(struct otx2_nic *pf)
}
}
+static int otx2_mbox_up_handler_rep_event_up_notify(struct otx2_nic *pf,
+ struct rep_event *info,
+ struct msg_rsp *rsp)
+{
+ struct net_device *netdev = pf->netdev;
+
+ if (info->event == RVU_EVENT_MTU_CHANGE) {
+ netdev->mtu = info->evt_data.mtu;
+ return 0;
+ }
+
+ if (info->event == RVU_EVENT_PORT_STATE) {
+ if (info->evt_data.port_state) {
+ pf->flags |= OTX2_FLAG_PORT_UP;
+ netif_carrier_on(netdev);
+ netif_tx_start_all_queues(netdev);
+ } else {
+ pf->flags &= ~OTX2_FLAG_PORT_UP;
+ netif_tx_stop_all_queues(netdev);
+ netif_carrier_off(netdev);
+ }
+ return 0;
+ }
+#ifdef CONFIG_RVU_ESWITCH
+ rvu_event_up_notify(pf, info);
+#endif
+ return 0;
+}
+
int otx2_mbox_up_handler_mcs_intr_notify(struct otx2_nic *pf,
struct mcs_intr_info *event,
struct msg_rsp *rsp)
@@ -913,6 +946,7 @@ static int otx2_process_mbox_msg_up(struct otx2_nic *pf,
}
MBOX_UP_CGX_MESSAGES
MBOX_UP_MCS_MESSAGES
+MBOX_UP_REP_MESSAGES
#undef M
break;
default:
@@ -1008,7 +1042,7 @@ static irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
return IRQ_HANDLED;
}
-static void otx2_disable_mbox_intr(struct otx2_nic *pf)
+void otx2_disable_mbox_intr(struct otx2_nic *pf)
{
int vector = pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_AFPF_MBOX);
@@ -1016,8 +1050,9 @@ static void otx2_disable_mbox_intr(struct otx2_nic *pf)
otx2_write64(pf, RVU_PF_INT_ENA_W1C, BIT_ULL(0));
free_irq(vector, pf);
}
+EXPORT_SYMBOL(otx2_disable_mbox_intr);
-static int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af)
+int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af)
{
struct otx2_hw *hw = &pf->hw;
struct msg_req *req;
@@ -1061,7 +1096,7 @@ static int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af)
return 0;
}
-static void otx2_pfaf_mbox_destroy(struct otx2_nic *pf)
+void otx2_pfaf_mbox_destroy(struct otx2_nic *pf)
{
struct mbox *mbox = &pf->mbox;
@@ -1076,8 +1111,9 @@ static void otx2_pfaf_mbox_destroy(struct otx2_nic *pf)
otx2_mbox_destroy(&mbox->mbox);
otx2_mbox_destroy(&mbox->mbox_up);
}
+EXPORT_SYMBOL(otx2_pfaf_mbox_destroy);
-static int otx2_pfaf_mbox_init(struct otx2_nic *pf)
+int otx2_pfaf_mbox_init(struct otx2_nic *pf)
{
struct mbox *mbox = &pf->mbox;
void __iomem *hwbase;
@@ -1379,7 +1415,7 @@ done:
return IRQ_HANDLED;
}
-static irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq)
+irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq)
{
struct otx2_cq_poll *cq_poll = (struct otx2_cq_poll *)cq_irq;
struct otx2_nic *pf = (struct otx2_nic *)cq_poll->dev;
@@ -1398,20 +1434,25 @@ static irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq)
return IRQ_HANDLED;
}
+EXPORT_SYMBOL(otx2_cq_intr_handler);
-static void otx2_disable_napi(struct otx2_nic *pf)
+void otx2_disable_napi(struct otx2_nic *pf)
{
struct otx2_qset *qset = &pf->qset;
struct otx2_cq_poll *cq_poll;
+ struct work_struct *work;
int qidx;
for (qidx = 0; qidx < pf->hw.cint_cnt; qidx++) {
cq_poll = &qset->napi[qidx];
- cancel_work_sync(&cq_poll->dim.work);
+ work = &cq_poll->dim.work;
+ if (work->func)
+ cancel_work_sync(work);
napi_disable(&cq_poll->napi);
netif_napi_del(&cq_poll->napi);
}
}
+EXPORT_SYMBOL(otx2_disable_napi);
static void otx2_free_cq_res(struct otx2_nic *pf)
{
@@ -1477,7 +1518,7 @@ static int otx2_get_rbuf_size(struct otx2_nic *pf, int mtu)
return ALIGN(rbuf_size, 2048);
}
-static int otx2_init_hw_resources(struct otx2_nic *pf)
+int otx2_init_hw_resources(struct otx2_nic *pf)
{
struct nix_lf_free_req *free_req;
struct mbox *mbox = &pf->mbox;
@@ -1493,10 +1534,11 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
hw->sqpool_cnt = otx2_get_total_tx_queues(pf);
hw->pool_cnt = hw->rqpool_cnt + hw->sqpool_cnt;
- /* Maximum hardware supported transmit length */
- pf->tx_max_pktlen = pf->netdev->max_mtu + OTX2_ETH_HLEN;
-
- pf->rbsize = otx2_get_rbuf_size(pf, pf->netdev->mtu);
+ if (!otx2_rep_dev(pf->pdev)) {
+ /* Maximum hardware supported transmit length */
+ pf->tx_max_pktlen = pf->netdev->max_mtu + OTX2_ETH_HLEN;
+ pf->rbsize = otx2_get_rbuf_size(pf, pf->netdev->mtu);
+ }
mutex_lock(&mbox->lock);
/* NPA init */
@@ -1549,10 +1591,15 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
}
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
- err = otx2_txschq_config(pf, lvl, 0, false);
- if (err) {
- mutex_unlock(&mbox->lock);
- goto err_free_nix_queues;
+ int idx;
+
+ for (idx = 0; idx < pf->hw.txschq_cnt[lvl]; idx++) {
+ err = otx2_txschq_config(pf, lvl, idx, false);
+ if (err) {
+ dev_err(pf->dev, "Failed to config TXSCH\n");
+ mutex_unlock(&mbox->lock);
+ goto err_free_nix_queues;
+ }
}
}
@@ -1601,8 +1648,9 @@ exit:
mutex_unlock(&mbox->lock);
return err;
}
+EXPORT_SYMBOL(otx2_init_hw_resources);
-static void otx2_free_hw_resources(struct otx2_nic *pf)
+void otx2_free_hw_resources(struct otx2_nic *pf)
{
struct otx2_qset *qset = &pf->qset;
struct nix_lf_free_req *free_req;
@@ -1624,11 +1672,12 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
otx2_pfc_txschq_stop(pf);
#endif
- otx2_clean_qos_queues(pf);
+ if (!otx2_rep_dev(pf->pdev))
+ otx2_clean_qos_queues(pf);
mutex_lock(&mbox->lock);
/* Disable backpressure */
- if (!(pf->pcifunc & RVU_PFVF_FUNC_MASK))
+ if (!is_otx2_lbkvf(pf->pdev))
otx2_nix_config_bp(pf, false);
mutex_unlock(&mbox->lock);
@@ -1660,7 +1709,8 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
otx2_free_cq_res(pf);
/* Free all ingress bandwidth profiles allocated */
- cn10k_free_all_ipolicers(pf);
+ if (!otx2_rep_dev(pf->pdev))
+ cn10k_free_all_ipolicers(pf);
mutex_lock(&mbox->lock);
/* Reset NIX LF */
@@ -1688,6 +1738,7 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
}
mutex_unlock(&mbox->lock);
}
+EXPORT_SYMBOL(otx2_free_hw_resources);
static bool otx2_promisc_use_mce_list(struct otx2_nic *pfvf)
{
@@ -1770,15 +1821,24 @@ static void otx2_dim_work(struct work_struct *w)
dim->state = DIM_START_MEASURE;
}
-int otx2_open(struct net_device *netdev)
+void otx2_free_queue_mem(struct otx2_qset *qset)
+{
+ kfree(qset->sq);
+ qset->sq = NULL;
+ kfree(qset->cq);
+ qset->cq = NULL;
+ kfree(qset->rq);
+ qset->rq = NULL;
+ kfree(qset->napi);
+ qset->napi = NULL;
+}
+EXPORT_SYMBOL(otx2_free_queue_mem);
+
+int otx2_alloc_queue_mem(struct otx2_nic *pf)
{
- struct otx2_nic *pf = netdev_priv(netdev);
- struct otx2_cq_poll *cq_poll = NULL;
struct otx2_qset *qset = &pf->qset;
- int err = 0, qidx, vec;
- char *irq_name;
+ struct otx2_cq_poll *cq_poll;
- netif_carrier_off(netdev);
/* RQ and SQs are mapped to different CQs,
* so find out max CQ IRQs (i.e CINTs) needed.
@@ -1798,7 +1858,6 @@ int otx2_open(struct net_device *netdev)
/* CQ size of SQ */
qset->sqe_cnt = qset->sqe_cnt ? qset->sqe_cnt : Q_COUNT(Q_SIZE_4K);
- err = -ENOMEM;
qset->cq = kcalloc(pf->qset.cq_cnt,
sizeof(struct otx2_cq_queue), GFP_KERNEL);
if (!qset->cq)
@@ -1814,6 +1873,28 @@ int otx2_open(struct net_device *netdev)
if (!qset->rq)
goto err_free_mem;
+ return 0;
+
+err_free_mem:
+ otx2_free_queue_mem(qset);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL(otx2_alloc_queue_mem);
+
+int otx2_open(struct net_device *netdev)
+{
+ struct otx2_nic *pf = netdev_priv(netdev);
+ struct otx2_cq_poll *cq_poll = NULL;
+ struct otx2_qset *qset = &pf->qset;
+ int err = 0, qidx, vec;
+ char *irq_name;
+
+ netif_carrier_off(netdev);
+
+ err = otx2_alloc_queue_mem(pf);
+ if (err)
+ return err;
+
err = otx2_init_hw_resources(pf);
if (err)
goto err_free_mem;
@@ -1932,6 +2013,7 @@ int otx2_open(struct net_device *netdev)
}
pf->flags &= ~OTX2_FLAG_INTF_DOWN;
+ pf->flags &= ~OTX2_FLAG_PORT_UP;
/* 'intf_down' may be checked on any cpu */
smp_wmb();
@@ -1979,10 +2061,7 @@ err_disable_napi:
otx2_disable_napi(pf);
otx2_free_hw_resources(pf);
err_free_mem:
- kfree(qset->sq);
- kfree(qset->cq);
- kfree(qset->rq);
- kfree(qset->napi);
+ otx2_free_queue_mem(qset);
return err;
}
EXPORT_SYMBOL(otx2_open);
@@ -2047,11 +2126,7 @@ int otx2_stop(struct net_device *netdev)
for (qidx = 0; qidx < netdev->num_tx_queues; qidx++)
netdev_tx_reset_queue(netdev_get_tx_queue(netdev, qidx));
-
- kfree(qset->sq);
- kfree(qset->cq);
- kfree(qset->rq);
- kfree(qset->napi);
+ otx2_free_queue_mem(qset);
/* Do not clear RQ/SQ ringsize settings */
memset_startat(qset, 0, sqe_cnt);
return 0;
@@ -2081,7 +2156,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
sq = &pf->qset.sq[sq_idx];
txq = netdev_get_tx_queue(netdev, qidx);
- if (!otx2_sq_append_skb(netdev, sq, skb, qidx)) {
+ if (!otx2_sq_append_skb(pf, txq, sq, skb, qidx)) {
netif_tx_stop_queue(txq);
/* Check again, incase SQBs got freed up */
@@ -2786,7 +2861,7 @@ static const struct net_device_ops otx2_netdev_ops = {
.ndo_set_vf_trust = otx2_ndo_set_vf_trust,
};
-static int otx2_wq_init(struct otx2_nic *pf)
+int otx2_wq_init(struct otx2_nic *pf)
{
pf->otx2_wq = create_singlethread_workqueue("otx2_wq");
if (!pf->otx2_wq)
@@ -2797,7 +2872,7 @@ static int otx2_wq_init(struct otx2_nic *pf)
return 0;
}
-static int otx2_check_pf_usable(struct otx2_nic *nic)
+int otx2_check_pf_usable(struct otx2_nic *nic)
{
u64 rev;
@@ -2815,7 +2890,7 @@ static int otx2_check_pf_usable(struct otx2_nic *nic)
return 0;
}
-static int otx2_realloc_msix_vectors(struct otx2_nic *pf)
+int otx2_realloc_msix_vectors(struct otx2_nic *pf)
{
struct otx2_hw *hw = &pf->hw;
int num_vec, err;
@@ -2837,6 +2912,7 @@ static int otx2_realloc_msix_vectors(struct otx2_nic *pf)
return otx2_register_mbox_intr(pf, false);
}
+EXPORT_SYMBOL(otx2_realloc_msix_vectors);
static int otx2_sriov_vfcfg_init(struct otx2_nic *pf)
{
@@ -2872,6 +2948,88 @@ static void otx2_sriov_vfcfg_cleanup(struct otx2_nic *pf)
}
}
+int otx2_init_rsrc(struct pci_dev *pdev, struct otx2_nic *pf)
+{
+ struct device *dev = &pdev->dev;
+ struct otx2_hw *hw = &pf->hw;
+ int num_vec, err;
+
+ num_vec = pci_msix_vec_count(pdev);
+ hw->irq_name = devm_kmalloc_array(&hw->pdev->dev, num_vec, NAME_SIZE,
+ GFP_KERNEL);
+ if (!hw->irq_name)
+ return -ENOMEM;
+
+ hw->affinity_mask = devm_kcalloc(&hw->pdev->dev, num_vec,
+ sizeof(cpumask_var_t), GFP_KERNEL);
+ if (!hw->affinity_mask)
+ return -ENOMEM;
+
+ /* Map CSRs */
+ pf->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
+ if (!pf->reg_base) {
+ dev_err(dev, "Unable to map physical function CSRs, aborting\n");
+ return -ENOMEM;
+ }
+
+ err = otx2_check_pf_usable(pf);
+ if (err)
+ return err;
+
+ err = pci_alloc_irq_vectors(hw->pdev, RVU_PF_INT_VEC_CNT,
+ RVU_PF_INT_VEC_CNT, PCI_IRQ_MSIX);
+ if (err < 0) {
+ dev_err(dev, "%s: Failed to alloc %d IRQ vectors\n",
+ __func__, num_vec);
+ return err;
+ }
+
+ otx2_setup_dev_hw_settings(pf);
+
+ /* Init PF <=> AF mailbox stuff */
+ err = otx2_pfaf_mbox_init(pf);
+ if (err)
+ goto err_free_irq_vectors;
+
+ /* Register mailbox interrupt */
+ err = otx2_register_mbox_intr(pf, true);
+ if (err)
+ goto err_mbox_destroy;
+
+ /* Request AF to attach NPA and NIX LFs to this PF.
+ * NIX and NPA LFs are needed for this PF to function as a NIC.
+ */
+ err = otx2_attach_npa_nix(pf);
+ if (err)
+ goto err_disable_mbox_intr;
+
+ err = otx2_realloc_msix_vectors(pf);
+ if (err)
+ goto err_detach_rsrc;
+
+ err = cn10k_lmtst_init(pf);
+ if (err)
+ goto err_detach_rsrc;
+
+ return 0;
+
+err_detach_rsrc:
+ if (pf->hw.lmt_info)
+ free_percpu(pf->hw.lmt_info);
+ if (test_bit(CN10K_LMTST, &pf->hw.cap_flag))
+ qmem_free(pf->dev, pf->dync_lmt);
+ otx2_detach_resources(&pf->mbox);
+err_disable_mbox_intr:
+ otx2_disable_mbox_intr(pf);
+err_mbox_destroy:
+ otx2_pfaf_mbox_destroy(pf);
+err_free_irq_vectors:
+ pci_free_irq_vectors(hw->pdev);
+
+ return err;
+}
+EXPORT_SYMBOL(otx2_init_rsrc);
+
static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
@@ -2879,7 +3037,6 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct net_device *netdev;
struct otx2_nic *pf;
struct otx2_hw *hw;
- int num_vec;
err = pcim_enable_device(pdev);
if (err) {
@@ -2930,72 +3087,14 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Use CQE of 128 byte descriptor size by default */
hw->xqe_size = 128;
- num_vec = pci_msix_vec_count(pdev);
- hw->irq_name = devm_kmalloc_array(&hw->pdev->dev, num_vec, NAME_SIZE,
- GFP_KERNEL);
- if (!hw->irq_name) {
- err = -ENOMEM;
- goto err_free_netdev;
- }
-
- hw->affinity_mask = devm_kcalloc(&hw->pdev->dev, num_vec,
- sizeof(cpumask_var_t), GFP_KERNEL);
- if (!hw->affinity_mask) {
- err = -ENOMEM;
- goto err_free_netdev;
- }
-
- /* Map CSRs */
- pf->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
- if (!pf->reg_base) {
- dev_err(dev, "Unable to map physical function CSRs, aborting\n");
- err = -ENOMEM;
- goto err_free_netdev;
- }
-
- err = otx2_check_pf_usable(pf);
+ err = otx2_init_rsrc(pdev, pf);
if (err)
goto err_free_netdev;
- err = pci_alloc_irq_vectors(hw->pdev, RVU_PF_INT_VEC_CNT,
- RVU_PF_INT_VEC_CNT, PCI_IRQ_MSIX);
- if (err < 0) {
- dev_err(dev, "%s: Failed to alloc %d IRQ vectors\n",
- __func__, num_vec);
- goto err_free_netdev;
- }
-
- otx2_setup_dev_hw_settings(pf);
-
- /* Init PF <=> AF mailbox stuff */
- err = otx2_pfaf_mbox_init(pf);
- if (err)
- goto err_free_irq_vectors;
-
- /* Register mailbox interrupt */
- err = otx2_register_mbox_intr(pf, true);
- if (err)
- goto err_mbox_destroy;
-
- /* Request AF to attach NPA and NIX LFs to this PF.
- * NIX and NPA LFs are needed for this PF to function as a NIC.
- */
- err = otx2_attach_npa_nix(pf);
- if (err)
- goto err_disable_mbox_intr;
-
- err = otx2_realloc_msix_vectors(pf);
- if (err)
- goto err_detach_rsrc;
-
err = otx2_set_real_num_queues(netdev, hw->tx_queues, hw->rx_queues);
if (err)
goto err_detach_rsrc;
- err = cn10k_lmtst_init(pf);
- if (err)
- goto err_detach_rsrc;
-
/* Assign default mac address */
otx2_get_mac_from_af(netdev);
@@ -3058,6 +3157,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
netdev->min_mtu = OTX2_MIN_MTU;
netdev->max_mtu = otx2_get_max_mtu(pf);
+ hw->max_mtu = netdev->max_mtu;
/* reset CGX/RPM MAC stats */
otx2_reset_mac_stats(pf);
@@ -3118,11 +3218,8 @@ err_detach_rsrc:
if (test_bit(CN10K_LMTST, &pf->hw.cap_flag))
qmem_free(pf->dev, pf->dync_lmt);
otx2_detach_resources(&pf->mbox);
-err_disable_mbox_intr:
otx2_disable_mbox_intr(pf);
-err_mbox_destroy:
otx2_pfaf_mbox_destroy(pf);
-err_free_irq_vectors:
pci_free_irq_vectors(hw->pdev);
err_free_netdev:
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
index e63cc1eb6d89..9a226ca74425 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
@@ -443,6 +443,7 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
struct flow_action_entry *act;
struct net_device *target;
struct otx2_nic *priv;
+ struct rep_dev *rdev;
u32 burst, mark = 0;
u8 nr_police = 0;
u8 num_intf = 1;
@@ -464,14 +465,18 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
return 0;
case FLOW_ACTION_REDIRECT_INGRESS:
target = act->dev;
- priv = netdev_priv(target);
- /* npc_install_flow_req doesn't support passing a target pcifunc */
- if (rvu_get_pf(nic->pcifunc) != rvu_get_pf(priv->pcifunc)) {
- NL_SET_ERR_MSG_MOD(extack,
- "can't redirect to other pf/vf");
- return -EOPNOTSUPP;
+ if (target->dev.parent) {
+ priv = netdev_priv(target);
+ if (rvu_get_pf(nic->pcifunc) != rvu_get_pf(priv->pcifunc)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "can't redirect to other pf/vf");
+ return -EOPNOTSUPP;
+ }
+ req->vf = priv->pcifunc & RVU_PFVF_FUNC_MASK;
+ } else {
+ rdev = netdev_priv(target);
+ req->vf = rdev->pcifunc & RVU_PFVF_FUNC_MASK;
}
- req->vf = priv->pcifunc & RVU_PFVF_FUNC_MASK;
/* if op is already set; avoid overwriting the same */
if (!req->op)
@@ -1300,6 +1305,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
req->channel = nic->hw.rx_chan_base;
req->entry = flow_cfg->flow_ent[mcam_idx];
req->intf = NIX_INTF_RX;
+ req->vf = nic->pcifunc;
req->set_cntr = 1;
new_node->entry = req->entry;
@@ -1400,8 +1406,8 @@ static int otx2_tc_get_flow_stats(struct otx2_nic *nic,
return 0;
}
-static int otx2_setup_tc_cls_flower(struct otx2_nic *nic,
- struct flow_cls_offload *cls_flower)
+int otx2_setup_tc_cls_flower(struct otx2_nic *nic,
+ struct flow_cls_offload *cls_flower)
{
switch (cls_flower->command) {
case FLOW_CLS_REPLACE:
@@ -1414,6 +1420,7 @@ static int otx2_setup_tc_cls_flower(struct otx2_nic *nic,
return -EOPNOTSUPP;
}
}
+EXPORT_SYMBOL(otx2_setup_tc_cls_flower);
static int otx2_tc_ingress_matchall_install(struct otx2_nic *nic,
struct tc_cls_matchall_offload *cls)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 933e18ba2fb2..04bc06a80e23 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -376,9 +376,11 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
}
otx2_set_rxhash(pfvf, cqe, skb);
- skb_record_rx_queue(skb, cq->cq_idx);
- if (pfvf->netdev->features & NETIF_F_RXCSUM)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ if (!(pfvf->flags & OTX2_FLAG_REP_MODE_ENABLED)) {
+ skb_record_rx_queue(skb, cq->cq_idx);
+ if (pfvf->netdev->features & NETIF_F_RXCSUM)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
if (pfvf->flags & OTX2_FLAG_TC_MARK_ENABLED)
skb->mark = parse->match_id;
@@ -453,6 +455,7 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
int tx_pkts = 0, tx_bytes = 0, qidx;
struct otx2_snd_queue *sq;
struct nix_cqe_tx_s *cqe;
+ struct net_device *ndev;
int processed_cqe = 0;
if (cq->pend_cqe >= budget)
@@ -493,6 +496,13 @@ process_cqe:
otx2_write64(pfvf, NIX_LF_CQ_OP_DOOR,
((u64)cq->cq_idx << 32) | processed_cqe);
+#if IS_ENABLED(CONFIG_RVU_ESWITCH)
+ if (pfvf->flags & OTX2_FLAG_REP_MODE_ENABLED)
+ ndev = pfvf->reps[qidx]->netdev;
+ else
+#endif
+ ndev = pfvf->netdev;
+
if (likely(tx_pkts)) {
struct netdev_queue *txq;
@@ -500,12 +510,14 @@ process_cqe:
if (qidx >= pfvf->hw.tx_queues)
qidx -= pfvf->hw.xdp_queues;
- txq = netdev_get_tx_queue(pfvf->netdev, qidx);
+ if (pfvf->flags & OTX2_FLAG_REP_MODE_ENABLED)
+ qidx = 0;
+ txq = netdev_get_tx_queue(ndev, qidx);
netdev_tx_completed_queue(txq, tx_pkts, tx_bytes);
/* Check if queue was stopped earlier due to ring full */
smp_mb();
if (netif_tx_queue_stopped(txq) &&
- netif_carrier_ok(pfvf->netdev))
+ netif_carrier_ok(ndev))
netif_tx_wake_queue(txq);
}
return 0;
@@ -527,7 +539,7 @@ static void otx2_adjust_adaptive_coalese(struct otx2_nic *pfvf, struct otx2_cq_p
rx_frames + tx_frames,
rx_bytes + tx_bytes,
&dim_sample);
- net_dim(&cq_poll->dim, dim_sample);
+ net_dim(&cq_poll->dim, &dim_sample);
}
int otx2_napi_handler(struct napi_struct *napi, int budget)
@@ -594,6 +606,7 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
}
return workdone;
}
+EXPORT_SYMBOL(otx2_napi_handler);
void otx2_sqe_flush(void *dev, struct otx2_snd_queue *sq,
int size, int qidx)
@@ -1141,13 +1154,13 @@ static void otx2_set_txtstamp(struct otx2_nic *pfvf, struct sk_buff *skb,
}
}
-bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
+bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq,
+ struct otx2_snd_queue *sq,
struct sk_buff *skb, u16 qidx)
{
- struct netdev_queue *txq = netdev_get_tx_queue(netdev, qidx);
- struct otx2_nic *pfvf = netdev_priv(netdev);
int offset, num_segs, free_desc;
struct nix_sqe_hdr_s *sqe_hdr;
+ struct otx2_nic *pfvf = dev;
/* Check if there is enough room between producer
* and consumer index.
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
index 3f1d2655ff77..e1db5f961877 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
@@ -167,7 +167,8 @@ static inline u64 otx2_iova_to_phys(void *iommu_domain, dma_addr_t dma_addr)
}
int otx2_napi_handler(struct napi_struct *napi, int budget);
-bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
+bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq,
+ struct otx2_snd_queue *sq,
struct sk_buff *skb, u16 qidx);
void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq,
int size, int qidx);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 99fcc5661674..839fc77c11b2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -21,6 +21,7 @@
static const struct pci_device_id otx2_vf_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_RVU_AFVF) },
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_RVU_VF) },
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_SDP_REP) },
{ }
};
@@ -371,7 +372,7 @@ static int otx2vf_open(struct net_device *netdev)
/* LBKs do not receive link events so tell everyone we are up here */
vf = netdev_priv(netdev);
- if (is_otx2_lbkvf(vf->pdev)) {
+ if (is_otx2_lbkvf(vf->pdev) || is_otx2_sdp_rep(vf->pdev)) {
pr_info("%s NIC Link is UP\n", netdev->name);
netif_carrier_on(netdev);
netif_tx_start_all_queues(netdev);
@@ -395,7 +396,7 @@ static netdev_tx_t otx2vf_xmit(struct sk_buff *skb, struct net_device *netdev)
sq = &vf->qset.sq[qidx];
txq = netdev_get_tx_queue(netdev, qidx);
- if (!otx2_sq_append_skb(netdev, sq, skb, qidx)) {
+ if (!otx2_sq_append_skb(vf, txq, sq, skb, qidx)) {
netif_tx_stop_queue(txq);
/* Check again, incase SQBs got freed up */
@@ -500,7 +501,7 @@ static const struct net_device_ops otx2vf_netdev_ops = {
.ndo_setup_tc = otx2_setup_tc,
};
-static int otx2_wq_init(struct otx2_nic *vf)
+static int otx2_vf_wq_init(struct otx2_nic *vf)
{
vf->otx2_wq = create_singlethread_workqueue("otx2vf_wq");
if (!vf->otx2_wq)
@@ -671,6 +672,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
netdev->min_mtu = OTX2_MIN_MTU;
netdev->max_mtu = otx2_get_max_mtu(vf);
+ hw->max_mtu = netdev->max_mtu;
/* To distinguish, for LBK VFs set netdev name explicitly */
if (is_otx2_lbkvf(vf->pdev)) {
@@ -682,13 +684,22 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
snprintf(netdev->name, sizeof(netdev->name), "lbk%d", n);
}
+ if (is_otx2_sdp_rep(vf->pdev)) {
+ int n;
+
+ n = vf->pcifunc & RVU_PFVF_FUNC_MASK;
+ n -= 1;
+ snprintf(netdev->name, sizeof(netdev->name), "sdp%d-%d",
+ pdev->bus->number, n);
+ }
+
err = register_netdev(netdev);
if (err) {
dev_err(dev, "Failed to register netdevice\n");
goto err_ptp_destroy;
}
- err = otx2_wq_init(vf);
+ err = otx2_vf_wq_init(vf);
if (err)
goto err_unreg_netdev;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
new file mode 100644
index 000000000000..232b10740c13
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
@@ -0,0 +1,864 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell RVU representor driver
+ *
+ * Copyright (C) 2024 Marvell.
+ *
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/net_tstamp.h>
+#include <linux/sort.h>
+
+#include "otx2_common.h"
+#include "cn10k.h"
+#include "otx2_reg.h"
+#include "rep.h"
+
+#define DRV_NAME "rvu_rep"
+#define DRV_STRING "Marvell RVU Representor Driver"
+
+static const struct pci_device_id rvu_rep_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_RVU_REP) },
+ { }
+};
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION(DRV_STRING);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, rvu_rep_id_table);
+
+static int rvu_rep_notify_pfvf(struct otx2_nic *priv, u16 event,
+ struct rep_event *data);
+
+static int rvu_rep_mcam_flow_init(struct rep_dev *rep)
+{
+ struct npc_mcam_alloc_entry_req *req;
+ struct npc_mcam_alloc_entry_rsp *rsp;
+ struct otx2_nic *priv = rep->mdev;
+ int ent, allocated = 0;
+ int count;
+
+ rep->flow_cfg = kcalloc(1, sizeof(struct otx2_flow_config), GFP_KERNEL);
+
+ if (!rep->flow_cfg)
+ return -ENOMEM;
+
+ count = OTX2_DEFAULT_FLOWCOUNT;
+
+ rep->flow_cfg->flow_ent = kcalloc(count, sizeof(u16), GFP_KERNEL);
+ if (!rep->flow_cfg->flow_ent)
+ return -ENOMEM;
+
+ while (allocated < count) {
+ req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(&priv->mbox);
+ if (!req)
+ goto exit;
+
+ req->hdr.pcifunc = rep->pcifunc;
+ req->contig = false;
+ req->ref_entry = 0;
+ req->count = (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ?
+ NPC_MAX_NONCONTIG_ENTRIES : count - allocated;
+
+ if (otx2_sync_mbox_msg(&priv->mbox))
+ goto exit;
+
+ rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
+ (&priv->mbox.mbox, 0, &req->hdr);
+
+ for (ent = 0; ent < rsp->count; ent++)
+ rep->flow_cfg->flow_ent[ent + allocated] = rsp->entry_list[ent];
+
+ allocated += rsp->count;
+
+ if (rsp->count != req->count)
+ break;
+ }
+exit:
+ /* Multiple MCAM entry alloc requests could result in non-sequential
+ * MCAM entries in the flow_ent[] array. Sort them in an ascending
+ * order, otherwise user installed ntuple filter index and MCAM entry
+ * index will not be in sync.
+ */
+ if (allocated)
+ sort(&rep->flow_cfg->flow_ent[0], allocated,
+ sizeof(rep->flow_cfg->flow_ent[0]), mcam_entry_cmp, NULL);
+
+ mutex_unlock(&priv->mbox.lock);
+
+ rep->flow_cfg->max_flows = allocated;
+
+ if (allocated) {
+ rep->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
+ rep->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
+ rep->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
+ }
+
+ INIT_LIST_HEAD(&rep->flow_cfg->flow_list);
+ INIT_LIST_HEAD(&rep->flow_cfg->flow_list_tc);
+ return 0;
+}
+
+static int rvu_rep_setup_tc_cb(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ struct rep_dev *rep = cb_priv;
+ struct otx2_nic *priv = rep->mdev;
+
+ if (!(rep->flags & RVU_REP_VF_INITIALIZED))
+ return -EINVAL;
+
+ if (!(rep->flags & OTX2_FLAG_TC_FLOWER_SUPPORT))
+ rvu_rep_mcam_flow_init(rep);
+
+ priv->netdev = rep->netdev;
+ priv->flags = rep->flags;
+ priv->pcifunc = rep->pcifunc;
+ priv->flow_cfg = rep->flow_cfg;
+
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return otx2_setup_tc_cls_flower(priv, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static LIST_HEAD(rvu_rep_block_cb_list);
+static int rvu_rep_setup_tc(struct net_device *netdev, enum tc_setup_type type,
+ void *type_data)
+{
+ struct rvu_rep *rep = netdev_priv(netdev);
+
+ switch (type) {
+ case TC_SETUP_BLOCK:
+ return flow_block_cb_setup_simple(type_data,
+ &rvu_rep_block_cb_list,
+ rvu_rep_setup_tc_cb,
+ rep, rep, true);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int
+rvu_rep_sp_stats64(const struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct rep_dev *rep = netdev_priv(dev);
+ struct otx2_nic *priv = rep->mdev;
+ struct otx2_rcv_queue *rq;
+ struct otx2_snd_queue *sq;
+ u16 qidx = rep->rep_id;
+
+ otx2_update_rq_stats(priv, qidx);
+ rq = &priv->qset.rq[qidx];
+
+ otx2_update_sq_stats(priv, qidx);
+ sq = &priv->qset.sq[qidx];
+
+ stats->tx_bytes = sq->stats.bytes;
+ stats->tx_packets = sq->stats.pkts;
+ stats->rx_bytes = rq->stats.bytes;
+ stats->rx_packets = rq->stats.pkts;
+ return 0;
+}
+
+static bool
+rvu_rep_has_offload_stats(const struct net_device *dev, int attr_id)
+{
+ return attr_id == IFLA_OFFLOAD_XSTATS_CPU_HIT;
+}
+
+static int
+rvu_rep_get_offload_stats(int attr_id, const struct net_device *dev,
+ void *sp)
+{
+ if (attr_id == IFLA_OFFLOAD_XSTATS_CPU_HIT)
+ return rvu_rep_sp_stats64(dev, (struct rtnl_link_stats64 *)sp);
+
+ return -EINVAL;
+}
+
+static int rvu_rep_dl_port_fn_hw_addr_get(struct devlink_port *port,
+ u8 *hw_addr, int *hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct rep_dev *rep = container_of(port, struct rep_dev, dl_port);
+
+ ether_addr_copy(hw_addr, rep->mac);
+ *hw_addr_len = ETH_ALEN;
+ return 0;
+}
+
+static int rvu_rep_dl_port_fn_hw_addr_set(struct devlink_port *port,
+ const u8 *hw_addr, int hw_addr_len,
+ struct netlink_ext_ack *extack)
+{
+ struct rep_dev *rep = container_of(port, struct rep_dev, dl_port);
+ struct otx2_nic *priv = rep->mdev;
+ struct rep_event evt = {0};
+
+ eth_hw_addr_set(rep->netdev, hw_addr);
+ ether_addr_copy(rep->mac, hw_addr);
+
+ ether_addr_copy(evt.evt_data.mac, hw_addr);
+ evt.pcifunc = rep->pcifunc;
+ rvu_rep_notify_pfvf(priv, RVU_EVENT_MAC_ADDR_CHANGE, &evt);
+ return 0;
+}
+
+static const struct devlink_port_ops rvu_rep_dl_port_ops = {
+ .port_fn_hw_addr_get = rvu_rep_dl_port_fn_hw_addr_get,
+ .port_fn_hw_addr_set = rvu_rep_dl_port_fn_hw_addr_set,
+};
+
+static void
+rvu_rep_devlink_set_switch_id(struct otx2_nic *priv,
+ struct netdev_phys_item_id *ppid)
+{
+ struct pci_dev *pdev = priv->pdev;
+ u64 id;
+
+ id = pci_get_dsn(pdev);
+
+ ppid->id_len = sizeof(id);
+ put_unaligned_be64(id, &ppid->id);
+}
+
+static void rvu_rep_devlink_port_unregister(struct rep_dev *rep)
+{
+ devlink_port_unregister(&rep->dl_port);
+}
+
+static int rvu_rep_devlink_port_register(struct rep_dev *rep)
+{
+ struct devlink_port_attrs attrs = {};
+ struct otx2_nic *priv = rep->mdev;
+ struct devlink *dl = priv->dl->dl;
+ int err;
+
+ if (!(rep->pcifunc & RVU_PFVF_FUNC_MASK)) {
+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
+ attrs.phys.port_number = rvu_get_pf(rep->pcifunc);
+ } else {
+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
+ attrs.pci_vf.pf = rvu_get_pf(rep->pcifunc);
+ attrs.pci_vf.vf = rep->pcifunc & RVU_PFVF_FUNC_MASK;
+ }
+
+ rvu_rep_devlink_set_switch_id(priv, &attrs.switch_id);
+ devlink_port_attrs_set(&rep->dl_port, &attrs);
+
+ err = devl_port_register_with_ops(dl, &rep->dl_port, rep->rep_id,
+ &rvu_rep_dl_port_ops);
+ if (err) {
+ dev_err(rep->mdev->dev, "devlink_port_register failed: %d\n",
+ err);
+ return err;
+ }
+ return 0;
+}
+
+static int rvu_rep_get_repid(struct otx2_nic *priv, u16 pcifunc)
+{
+ int rep_id;
+
+ for (rep_id = 0; rep_id < priv->rep_cnt; rep_id++)
+ if (priv->rep_pf_map[rep_id] == pcifunc)
+ return rep_id;
+ return -EINVAL;
+}
+
+static int rvu_rep_notify_pfvf(struct otx2_nic *priv, u16 event,
+ struct rep_event *data)
+{
+ struct rep_event *req;
+
+ mutex_lock(&priv->mbox.lock);
+ req = otx2_mbox_alloc_msg_rep_event_notify(&priv->mbox);
+ if (!req) {
+ mutex_unlock(&priv->mbox.lock);
+ return -ENOMEM;
+ }
+ req->event = event;
+ req->pcifunc = data->pcifunc;
+
+ memcpy(&req->evt_data, &data->evt_data, sizeof(struct rep_evt_data));
+ otx2_sync_mbox_msg(&priv->mbox);
+ mutex_unlock(&priv->mbox.lock);
+ return 0;
+}
+
+static void rvu_rep_state_evt_handler(struct otx2_nic *priv,
+ struct rep_event *info)
+{
+ struct rep_dev *rep;
+ int rep_id;
+
+ rep_id = rvu_rep_get_repid(priv, info->pcifunc);
+ rep = priv->reps[rep_id];
+ if (info->evt_data.vf_state)
+ rep->flags |= RVU_REP_VF_INITIALIZED;
+ else
+ rep->flags &= ~RVU_REP_VF_INITIALIZED;
+}
+
+int rvu_event_up_notify(struct otx2_nic *pf, struct rep_event *info)
+{
+ if (info->event & RVU_EVENT_PFVF_STATE)
+ rvu_rep_state_evt_handler(pf, info);
+ return 0;
+}
+
+static int rvu_rep_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct rep_dev *rep = netdev_priv(dev);
+ struct otx2_nic *priv = rep->mdev;
+ struct rep_event evt = {0};
+
+ netdev_info(dev, "Changing MTU from %d to %d\n",
+ dev->mtu, new_mtu);
+ dev->mtu = new_mtu;
+
+ evt.evt_data.mtu = new_mtu;
+ evt.pcifunc = rep->pcifunc;
+ rvu_rep_notify_pfvf(priv, RVU_EVENT_MTU_CHANGE, &evt);
+ return 0;
+}
+
+static void rvu_rep_get_stats(struct work_struct *work)
+{
+ struct delayed_work *del_work = to_delayed_work(work);
+ struct nix_stats_req *req;
+ struct nix_stats_rsp *rsp;
+ struct rep_stats *stats;
+ struct otx2_nic *priv;
+ struct rep_dev *rep;
+ int err;
+
+ rep = container_of(del_work, struct rep_dev, stats_wrk);
+ priv = rep->mdev;
+
+ mutex_lock(&priv->mbox.lock);
+ req = otx2_mbox_alloc_msg_nix_lf_stats(&priv->mbox);
+ if (!req) {
+ mutex_unlock(&priv->mbox.lock);
+ return;
+ }
+ req->pcifunc = rep->pcifunc;
+ err = otx2_sync_mbox_msg_busy_poll(&priv->mbox);
+ if (err)
+ goto exit;
+
+ rsp = (struct nix_stats_rsp *)
+ otx2_mbox_get_rsp(&priv->mbox.mbox, 0, &req->hdr);
+
+ if (IS_ERR(rsp)) {
+ err = PTR_ERR(rsp);
+ goto exit;
+ }
+
+ stats = &rep->stats;
+ stats->rx_bytes = rsp->rx.octs;
+ stats->rx_frames = rsp->rx.ucast + rsp->rx.bcast +
+ rsp->rx.mcast;
+ stats->rx_drops = rsp->rx.drop;
+ stats->rx_mcast_frames = rsp->rx.mcast;
+ stats->tx_bytes = rsp->tx.octs;
+ stats->tx_frames = rsp->tx.ucast + rsp->tx.bcast + rsp->tx.mcast;
+ stats->tx_drops = rsp->tx.drop;
+exit:
+ mutex_unlock(&priv->mbox.lock);
+}
+
+static void rvu_rep_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct rep_dev *rep = netdev_priv(dev);
+
+ if (!(rep->flags & RVU_REP_VF_INITIALIZED))
+ return;
+
+ stats->rx_packets = rep->stats.rx_frames;
+ stats->rx_bytes = rep->stats.rx_bytes;
+ stats->rx_dropped = rep->stats.rx_drops;
+ stats->multicast = rep->stats.rx_mcast_frames;
+
+ stats->tx_packets = rep->stats.tx_frames;
+ stats->tx_bytes = rep->stats.tx_bytes;
+ stats->tx_dropped = rep->stats.tx_drops;
+
+ schedule_delayed_work(&rep->stats_wrk, msecs_to_jiffies(100));
+}
+
+static int rvu_eswitch_config(struct otx2_nic *priv, u8 ena)
+{
+ struct esw_cfg_req *req;
+
+ mutex_lock(&priv->mbox.lock);
+ req = otx2_mbox_alloc_msg_esw_cfg(&priv->mbox);
+ if (!req) {
+ mutex_unlock(&priv->mbox.lock);
+ return -ENOMEM;
+ }
+ req->ena = ena;
+ otx2_sync_mbox_msg(&priv->mbox);
+ mutex_unlock(&priv->mbox.lock);
+ return 0;
+}
+
+static netdev_tx_t rvu_rep_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct rep_dev *rep = netdev_priv(dev);
+ struct otx2_nic *pf = rep->mdev;
+ struct otx2_snd_queue *sq;
+ struct netdev_queue *txq;
+
+ sq = &pf->qset.sq[rep->rep_id];
+ txq = netdev_get_tx_queue(dev, 0);
+
+ if (!otx2_sq_append_skb(pf, txq, sq, skb, rep->rep_id)) {
+ netif_tx_stop_queue(txq);
+
+ /* Check again, in case SQBs got freed up */
+ smp_mb();
+ if (((sq->num_sqbs - *sq->aura_fc_addr) * sq->sqe_per_sqb)
+ > sq->sqe_thresh)
+ netif_tx_wake_queue(txq);
+
+ return NETDEV_TX_BUSY;
+ }
+ return NETDEV_TX_OK;
+}
+
+static int rvu_rep_open(struct net_device *dev)
+{
+ struct rep_dev *rep = netdev_priv(dev);
+ struct otx2_nic *priv = rep->mdev;
+ struct rep_event evt = {0};
+
+ if (!(rep->flags & RVU_REP_VF_INITIALIZED))
+ return 0;
+
+ netif_carrier_on(dev);
+ netif_tx_start_all_queues(dev);
+
+ evt.event = RVU_EVENT_PORT_STATE;
+ evt.evt_data.port_state = 1;
+ evt.pcifunc = rep->pcifunc;
+ rvu_rep_notify_pfvf(priv, RVU_EVENT_PORT_STATE, &evt);
+ return 0;
+}
+
+static int rvu_rep_stop(struct net_device *dev)
+{
+ struct rep_dev *rep = netdev_priv(dev);
+ struct otx2_nic *priv = rep->mdev;
+ struct rep_event evt = {0};
+
+ if (!(rep->flags & RVU_REP_VF_INITIALIZED))
+ return 0;
+
+ netif_carrier_off(dev);
+ netif_tx_disable(dev);
+
+ evt.event = RVU_EVENT_PORT_STATE;
+ evt.pcifunc = rep->pcifunc;
+ rvu_rep_notify_pfvf(priv, RVU_EVENT_PORT_STATE, &evt);
+ return 0;
+}
+
+static const struct net_device_ops rvu_rep_netdev_ops = {
+ .ndo_open = rvu_rep_open,
+ .ndo_stop = rvu_rep_stop,
+ .ndo_start_xmit = rvu_rep_xmit,
+ .ndo_get_stats64 = rvu_rep_get_stats64,
+ .ndo_change_mtu = rvu_rep_change_mtu,
+ .ndo_has_offload_stats = rvu_rep_has_offload_stats,
+ .ndo_get_offload_stats = rvu_rep_get_offload_stats,
+ .ndo_setup_tc = rvu_rep_setup_tc,
+};
+
+static int rvu_rep_napi_init(struct otx2_nic *priv,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qset *qset = &priv->qset;
+ struct otx2_cq_poll *cq_poll = NULL;
+ struct otx2_hw *hw = &priv->hw;
+ int err = 0, qidx, vec;
+ char *irq_name;
+
+ qset->napi = kcalloc(hw->cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
+ if (!qset->napi)
+ return -ENOMEM;
+
+ /* Register NAPI handler */
+ for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
+ cq_poll = &qset->napi[qidx];
+ cq_poll->cint_idx = qidx;
+ cq_poll->cq_ids[CQ_RX] =
+ (qidx < hw->rx_queues) ? qidx : CINT_INVALID_CQ;
+ cq_poll->cq_ids[CQ_TX] = (qidx < hw->tx_queues) ?
+ qidx + hw->rx_queues :
+ CINT_INVALID_CQ;
+ cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
+ cq_poll->cq_ids[CQ_QOS] = CINT_INVALID_CQ;
+
+ cq_poll->dev = (void *)priv;
+ netif_napi_add(priv->reps[qidx]->netdev, &cq_poll->napi,
+ otx2_napi_handler);
+ napi_enable(&cq_poll->napi);
+ }
+ /* Register CQ IRQ handlers */
+ vec = hw->nix_msixoff + NIX_LF_CINT_VEC_START;
+ for (qidx = 0; qidx < hw->cint_cnt; qidx++) {
+ irq_name = &hw->irq_name[vec * NAME_SIZE];
+
+ snprintf(irq_name, NAME_SIZE, "rep%d-rxtx-%d", qidx, qidx);
+
+ err = request_irq(pci_irq_vector(priv->pdev, vec),
+ otx2_cq_intr_handler, 0, irq_name,
+ &qset->napi[qidx]);
+ if (err) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "RVU REP IRQ registration failed for CQ%d",
+ qidx);
+ goto err_free_cints;
+ }
+ vec++;
+
+ /* Enable CQ IRQ */
+ otx2_write64(priv, NIX_LF_CINTX_INT(qidx), BIT_ULL(0));
+ otx2_write64(priv, NIX_LF_CINTX_ENA_W1S(qidx), BIT_ULL(0));
+ }
+ priv->flags &= ~OTX2_FLAG_INTF_DOWN;
+ return 0;
+
+err_free_cints:
+ otx2_free_cints(priv, qidx);
+ otx2_disable_napi(priv);
+ return err;
+}
+
+static void rvu_rep_free_cq_rsrc(struct otx2_nic *priv)
+{
+ struct otx2_qset *qset = &priv->qset;
+ struct otx2_cq_poll *cq_poll = NULL;
+ int qidx, vec;
+
+ /* Cleanup CQ NAPI and IRQ */
+ vec = priv->hw.nix_msixoff + NIX_LF_CINT_VEC_START;
+ for (qidx = 0; qidx < priv->hw.cint_cnt; qidx++) {
+ /* Disable interrupt */
+ otx2_write64(priv, NIX_LF_CINTX_ENA_W1C(qidx), BIT_ULL(0));
+
+ synchronize_irq(pci_irq_vector(priv->pdev, vec));
+
+ cq_poll = &qset->napi[qidx];
+ napi_synchronize(&cq_poll->napi);
+ vec++;
+ }
+ otx2_free_cints(priv, priv->hw.cint_cnt);
+ otx2_disable_napi(priv);
+}
+
+static void rvu_rep_rsrc_free(struct otx2_nic *priv)
+{
+ struct otx2_qset *qset = &priv->qset;
+ struct delayed_work *work;
+ int wrk;
+
+ for (wrk = 0; wrk < priv->qset.cq_cnt; wrk++) {
+ work = &priv->refill_wrk[wrk].pool_refill_work;
+ cancel_delayed_work_sync(work);
+ }
+ devm_kfree(priv->dev, priv->refill_wrk);
+
+ otx2_free_hw_resources(priv);
+ otx2_free_queue_mem(qset);
+}
+
+static int rvu_rep_rsrc_init(struct otx2_nic *priv)
+{
+ struct otx2_qset *qset = &priv->qset;
+ int err;
+
+ err = otx2_alloc_queue_mem(priv);
+ if (err)
+ return err;
+
+ priv->hw.max_mtu = otx2_get_max_mtu(priv);
+ priv->tx_max_pktlen = priv->hw.max_mtu + OTX2_ETH_HLEN;
+ priv->rbsize = ALIGN(priv->hw.rbuf_len, OTX2_ALIGN) + OTX2_HEAD_ROOM;
+
+ err = otx2_init_hw_resources(priv);
+ if (err)
+ goto err_free_rsrc;
+
+ /* Set maximum frame size allowed in HW */
+ err = otx2_hw_set_mtu(priv, priv->hw.max_mtu);
+ if (err) {
+ dev_err(priv->dev, "Failed to set HW MTU\n");
+ goto err_free_rsrc;
+ }
+ return 0;
+
+err_free_rsrc:
+ otx2_free_hw_resources(priv);
+ otx2_free_queue_mem(qset);
+ return err;
+}
+
+void rvu_rep_destroy(struct otx2_nic *priv)
+{
+ struct rep_dev *rep;
+ int rep_id;
+
+ rvu_eswitch_config(priv, false);
+ priv->flags |= OTX2_FLAG_INTF_DOWN;
+ rvu_rep_free_cq_rsrc(priv);
+ for (rep_id = 0; rep_id < priv->rep_cnt; rep_id++) {
+ rep = priv->reps[rep_id];
+ unregister_netdev(rep->netdev);
+ rvu_rep_devlink_port_unregister(rep);
+ free_netdev(rep->netdev);
+ kfree(rep->flow_cfg);
+ }
+ kfree(priv->reps);
+ rvu_rep_rsrc_free(priv);
+}
+
+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack)
+{
+ int rep_cnt = priv->rep_cnt;
+ struct net_device *ndev;
+ struct rep_dev *rep;
+ int rep_id, err;
+ u16 pcifunc;
+
+ err = rvu_rep_rsrc_init(priv);
+ if (err)
+ return -ENOMEM;
+
+ priv->reps = kcalloc(rep_cnt, sizeof(struct rep_dev *), GFP_KERNEL);
+ if (!priv->reps)
+ return -ENOMEM;
+
+ for (rep_id = 0; rep_id < rep_cnt; rep_id++) {
+ ndev = alloc_etherdev(sizeof(*rep));
+ if (!ndev) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "PFVF representor:%d creation failed",
+ rep_id);
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ rep = netdev_priv(ndev);
+ priv->reps[rep_id] = rep;
+ rep->mdev = priv;
+ rep->netdev = ndev;
+ rep->rep_id = rep_id;
+
+ ndev->min_mtu = OTX2_MIN_MTU;
+ ndev->max_mtu = priv->hw.max_mtu;
+ ndev->netdev_ops = &rvu_rep_netdev_ops;
+ pcifunc = priv->rep_pf_map[rep_id];
+ rep->pcifunc = pcifunc;
+
+ snprintf(ndev->name, sizeof(ndev->name), "Rpf%dvf%d",
+ rvu_get_pf(pcifunc), (pcifunc & RVU_PFVF_FUNC_MASK));
+
+ ndev->hw_features = (NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM | NETIF_F_RXHASH |
+ NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6);
+
+ ndev->hw_features |= NETIF_F_HW_TC;
+ ndev->features |= ndev->hw_features;
+ eth_hw_addr_random(ndev);
+ err = rvu_rep_devlink_port_register(rep);
+ if (err)
+ goto exit;
+
+ SET_NETDEV_DEVLINK_PORT(ndev, &rep->dl_port);
+ err = register_netdev(ndev);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "PFVF representor registration failed");
+ free_netdev(ndev);
+ goto exit;
+ }
+
+ INIT_DELAYED_WORK(&rep->stats_wrk, rvu_rep_get_stats);
+ }
+ err = rvu_rep_napi_init(priv, extack);
+ if (err)
+ goto exit;
+
+ rvu_eswitch_config(priv, true);
+ return 0;
+exit:
+ while (--rep_id >= 0) {
+ rep = priv->reps[rep_id];
+ unregister_netdev(rep->netdev);
+ rvu_rep_devlink_port_unregister(rep);
+ free_netdev(rep->netdev);
+ }
+ kfree(priv->reps);
+ rvu_rep_rsrc_free(priv);
+ return err;
+}
+
+static int rvu_get_rep_cnt(struct otx2_nic *priv)
+{
+ struct get_rep_cnt_rsp *rsp;
+ struct mbox_msghdr *msghdr;
+ struct msg_req *req;
+ int err, rep;
+
+ mutex_lock(&priv->mbox.lock);
+ req = otx2_mbox_alloc_msg_get_rep_cnt(&priv->mbox);
+ if (!req) {
+ mutex_unlock(&priv->mbox.lock);
+ return -ENOMEM;
+ }
+ err = otx2_sync_mbox_msg(&priv->mbox);
+ if (err)
+ goto exit;
+
+ msghdr = otx2_mbox_get_rsp(&priv->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(msghdr)) {
+ err = PTR_ERR(msghdr);
+ goto exit;
+ }
+
+ rsp = (struct get_rep_cnt_rsp *)msghdr;
+ priv->hw.tx_queues = rsp->rep_cnt;
+ priv->hw.rx_queues = rsp->rep_cnt;
+ priv->rep_cnt = rsp->rep_cnt;
+ for (rep = 0; rep < priv->rep_cnt; rep++)
+ priv->rep_pf_map[rep] = rsp->rep_pf_map[rep];
+
+exit:
+ mutex_unlock(&priv->mbox.lock);
+ return err;
+}
+
+static int rvu_rep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct device *dev = &pdev->dev;
+ struct otx2_nic *priv;
+ struct otx2_hw *hw;
+ int err;
+
+ err = pcim_enable_device(pdev);
+ if (err) {
+ dev_err(dev, "Failed to enable PCI device\n");
+ return err;
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ dev_err(dev, "PCI request regions failed 0x%x\n", err);
+ return err;
+ }
+
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+ if (err) {
+ dev_err(dev, "DMA mask config failed, abort\n");
+ goto err_release_regions;
+ }
+
+ pci_set_master(pdev);
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ err = -ENOMEM;
+ goto err_release_regions;
+ }
+
+ pci_set_drvdata(pdev, priv);
+ priv->pdev = pdev;
+ priv->dev = dev;
+ priv->flags |= OTX2_FLAG_INTF_DOWN;
+ priv->flags |= OTX2_FLAG_REP_MODE_ENABLED;
+
+ hw = &priv->hw;
+ hw->pdev = pdev;
+ hw->max_queues = OTX2_MAX_CQ_CNT;
+ hw->rbuf_len = OTX2_DEFAULT_RBUF_LEN;
+ hw->xqe_size = 128;
+
+ err = otx2_init_rsrc(pdev, priv);
+ if (err)
+ goto err_release_regions;
+
+ priv->iommu_domain = iommu_get_domain_for_dev(dev);
+
+ err = rvu_get_rep_cnt(priv);
+ if (err)
+ goto err_detach_rsrc;
+
+ err = otx2_register_dl(priv);
+ if (err)
+ goto err_detach_rsrc;
+
+ return 0;
+
+err_detach_rsrc:
+ if (priv->hw.lmt_info)
+ free_percpu(priv->hw.lmt_info);
+ if (test_bit(CN10K_LMTST, &priv->hw.cap_flag))
+ qmem_free(priv->dev, priv->dync_lmt);
+ otx2_detach_resources(&priv->mbox);
+ otx2_disable_mbox_intr(priv);
+ otx2_pfaf_mbox_destroy(priv);
+ pci_free_irq_vectors(pdev);
+err_release_regions:
+ pci_set_drvdata(pdev, NULL);
+ pci_release_regions(pdev);
+ return err;
+}
+
+static void rvu_rep_remove(struct pci_dev *pdev)
+{
+ struct otx2_nic *priv = pci_get_drvdata(pdev);
+
+ otx2_unregister_dl(priv);
+ if (!(priv->flags & OTX2_FLAG_INTF_DOWN))
+ rvu_rep_destroy(priv);
+ otx2_detach_resources(&priv->mbox);
+ if (priv->hw.lmt_info)
+ free_percpu(priv->hw.lmt_info);
+ if (test_bit(CN10K_LMTST, &priv->hw.cap_flag))
+ qmem_free(priv->dev, priv->dync_lmt);
+ otx2_disable_mbox_intr(priv);
+ otx2_pfaf_mbox_destroy(priv);
+ pci_free_irq_vectors(priv->pdev);
+ pci_set_drvdata(pdev, NULL);
+ pci_release_regions(pdev);
+}
+
+static struct pci_driver rvu_rep_driver = {
+ .name = DRV_NAME,
+ .id_table = rvu_rep_id_table,
+ .probe = rvu_rep_probe,
+ .remove = rvu_rep_remove,
+ .shutdown = rvu_rep_remove,
+};
+
+static int __init rvu_rep_init_module(void)
+{
+ return pci_register_driver(&rvu_rep_driver);
+}
+
+static void __exit rvu_rep_cleanup_module(void)
+{
+ pci_unregister_driver(&rvu_rep_driver);
+}
+
+module_init(rvu_rep_init_module);
+module_exit(rvu_rep_cleanup_module);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.h b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
new file mode 100644
index 000000000000..38446b3e4f13
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Marvell RVU REPRESENTOR driver
+ *
+ * Copyright (C) 2024 Marvell.
+ *
+ */
+
+#ifndef REP_H
+#define REP_H
+
+#include <linux/pci.h>
+
+#include "otx2_reg.h"
+#include "otx2_txrx.h"
+#include "otx2_common.h"
+
+#define PCI_DEVID_RVU_REP 0xA0E0
+
+#define RVU_MAX_REP OTX2_MAX_CQ_CNT
+
+struct rep_stats {
+ u64 rx_bytes;
+ u64 rx_frames;
+ u64 rx_drops;
+ u64 rx_mcast_frames;
+
+ u64 tx_bytes;
+ u64 tx_frames;
+ u64 tx_drops;
+};
+
+struct rep_dev {
+ struct otx2_nic *mdev;
+ struct net_device *netdev;
+ struct rep_stats stats;
+ struct delayed_work stats_wrk;
+ struct devlink_port dl_port;
+ struct otx2_flow_config *flow_cfg;
+#define RVU_REP_VF_INITIALIZED BIT_ULL(0)
+ u64 flags;
+ u16 rep_id;
+ u16 pcifunc;
+ u8 mac[ETH_ALEN];
+};
+
+static inline bool otx2_rep_dev(struct pci_dev *pdev)
+{
+ return pdev->device == PCI_DEVID_RVU_REP;
+}
+
+int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack);
+void rvu_rep_destroy(struct otx2_nic *priv);
+int rvu_event_up_notify(struct otx2_nic *pf, struct rep_event *info);
+#endif /* REP_H */
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 1a59c952aa01..2bf426cea6dd 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1394,18 +1394,15 @@ static int pxa168_eth_probe(struct platform_device *pdev)
printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n");
- clk = devm_clk_get(&pdev->dev, NULL);
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "Fast Ethernet failed to get clock\n");
+ dev_err(&pdev->dev, "Fast Ethernet failed to get and enable clock\n");
return -ENODEV;
}
- clk_prepare_enable(clk);
dev = alloc_etherdev(sizeof(struct pxa168_eth_private));
- if (!dev) {
- err = -ENOMEM;
- goto err_clk;
- }
+ if (!dev)
+ return -ENOMEM;
platform_set_drvdata(pdev, dev);
pep = netdev_priv(dev);
@@ -1523,8 +1520,6 @@ err_free_mdio:
mdiobus_free(pep->smi_bus);
err_netdev:
free_netdev(dev);
-err_clk:
- clk_disable_unprepare(clk);
return err;
}
@@ -1542,7 +1537,6 @@ static void pxa168_eth_remove(struct platform_device *pdev)
if (dev->phydev)
phy_disconnect(dev->phydev);
- clk_disable_unprepare(pep->clk);
mdiobus_unregister(pep->smi_bus);
mdiobus_free(pep->smi_bus);
unregister_netdev(dev);
@@ -1579,7 +1573,7 @@ MODULE_DEVICE_TABLE(of, pxa168_eth_of_match);
static struct platform_driver pxa168_eth_driver = {
.probe = pxa168_eth_probe,
- .remove_new = pxa168_eth_remove,
+ .remove = pxa168_eth_remove,
.shutdown = pxa168_eth_shutdown,
.resume = pxa168_eth_resume,
.suspend = pxa168_eth_suspend,
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index fcfb34561882..25bf6ec44289 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -484,8 +484,7 @@ static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < ARRAY_SIZE(skge_stats); i++)
- memcpy(data + i * ETH_GSTRING_LEN,
- skge_stats[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, skge_stats[i].name);
break;
}
}
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index a7a16eac1891..3914cd9210d4 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -3800,8 +3800,7 @@ static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data)
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < ARRAY_SIZE(sky2_stats); i++)
- memcpy(data + i * ETH_GSTRING_LEN,
- sky2_stats[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, sky2_stats[i].name);
break;
}
}
diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/mediatek/airoha_eth.c
index 2c26eb185283..6c683a12d5aa 100644
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
@@ -554,7 +554,7 @@
#define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0)
#define REG_EGRESS_RATE_METER_CFG 0x100c
-#define EGRESS_RATE_METER_EN_MASK BIT(29)
+#define EGRESS_RATE_METER_EN_MASK BIT(31)
#define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17)
#define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12)
#define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0)
@@ -752,11 +752,9 @@ struct airoha_tx_irq_queue {
struct airoha_qdma *qdma;
struct napi_struct napi;
- u32 *q;
int size;
- int queued;
- u16 head;
+ u32 *q;
};
struct airoha_hw_stats {
@@ -1116,17 +1114,23 @@ static void airoha_fe_set_pse_queue_rsv_pages(struct airoha_eth *eth,
PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK);
}
+static u32 airoha_fe_get_pse_all_rsv(struct airoha_eth *eth)
+{
+ u32 val = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET);
+
+ return FIELD_GET(PSE_ALLRSV_MASK, val);
+}
+
static int airoha_fe_set_pse_oq_rsv(struct airoha_eth *eth,
u32 port, u32 queue, u32 val)
{
- u32 orig_val, tmp, all_rsv, fq_limit;
+ u32 orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue);
+ u32 tmp, all_rsv, fq_limit;
airoha_fe_set_pse_queue_rsv_pages(eth, port, queue, val);
/* modify all rsv */
- orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue);
- tmp = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET);
- all_rsv = FIELD_GET(PSE_ALLRSV_MASK, tmp);
+ all_rsv = airoha_fe_get_pse_all_rsv(eth);
all_rsv += (val - orig_val);
airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, PSE_ALLRSV_MASK,
FIELD_PREP(PSE_ALLRSV_MASK, all_rsv));
@@ -1166,11 +1170,13 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth)
[FE_PSE_PORT_GDM4] = 2,
[FE_PSE_PORT_CDM5] = 2,
};
+ u32 all_rsv;
int q;
+ all_rsv = airoha_fe_get_pse_all_rsv(eth);
/* hw misses PPE2 oq rsv */
- airoha_fe_set(eth, REG_FE_PSE_BUF_SET,
- PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]);
+ all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2];
+ airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv);
/* CMD1 */
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++)
@@ -1363,7 +1369,8 @@ static int airoha_fe_init(struct airoha_eth *eth)
airoha_fe_set(eth, REG_GDM_MISC_CFG,
GDM2_RDM_ACK_WAIT_PREF_MASK |
GDM2_CHN_VLD_MODE_MASK);
- airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK, 15);
+ airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK,
+ FIELD_PREP(CDM2_OAM_QSEL_MASK, 15));
/* init fragment and assemble Force Port */
/* NPU Core-3, NPU Bridge Channel-3 */
@@ -1647,30 +1654,38 @@ static int airoha_qdma_init_rx(struct airoha_qdma *qdma)
static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
{
struct airoha_tx_irq_queue *irq_q;
+ int id, done = 0, irq_queued;
struct airoha_qdma *qdma;
struct airoha_eth *eth;
- int id, done = 0;
+ u32 status, head;
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
qdma = irq_q->qdma;
id = irq_q - &qdma->q_tx_irq[0];
eth = qdma->eth;
- while (irq_q->queued > 0 && done < budget) {
- u32 qid, last, val = irq_q->q[irq_q->head];
+ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(id));
+ head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
+ head = head % irq_q->size;
+ irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
+
+ while (irq_queued > 0 && done < budget) {
+ u32 qid, val = irq_q->q[head];
+ struct airoha_qdma_desc *desc;
+ struct airoha_queue_entry *e;
struct airoha_queue *q;
+ u32 index, desc_ctrl;
+ struct sk_buff *skb;
if (val == 0xff)
break;
- irq_q->q[irq_q->head] = 0xff; /* mark as done */
- irq_q->head = (irq_q->head + 1) % irq_q->size;
- irq_q->queued--;
+ irq_q->q[head] = 0xff; /* mark as done */
+ head = (head + 1) % irq_q->size;
+ irq_queued--;
done++;
- last = FIELD_GET(IRQ_DESC_IDX_MASK, val);
qid = FIELD_GET(IRQ_RING_IDX_MASK, val);
-
if (qid >= ARRAY_SIZE(qdma->q_tx))
continue;
@@ -1678,44 +1693,53 @@ static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
if (!q->ndesc)
continue;
+ index = FIELD_GET(IRQ_DESC_IDX_MASK, val);
+ if (index >= q->ndesc)
+ continue;
+
spin_lock_bh(&q->lock);
- while (q->queued > 0) {
- struct airoha_qdma_desc *desc = &q->desc[q->tail];
- struct airoha_queue_entry *e = &q->entry[q->tail];
- u32 desc_ctrl = le32_to_cpu(desc->ctrl);
- struct sk_buff *skb = e->skb;
- u16 index = q->tail;
+ if (!q->queued)
+ goto unlock;
- if (!(desc_ctrl & QDMA_DESC_DONE_MASK) &&
- !(desc_ctrl & QDMA_DESC_DROP_MASK))
- break;
+ desc = &q->desc[index];
+ desc_ctrl = le32_to_cpu(desc->ctrl);
- q->tail = (q->tail + 1) % q->ndesc;
- q->queued--;
+ if (!(desc_ctrl & QDMA_DESC_DONE_MASK) &&
+ !(desc_ctrl & QDMA_DESC_DROP_MASK))
+ goto unlock;
- dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
- DMA_TO_DEVICE);
+ e = &q->entry[index];
+ skb = e->skb;
- WRITE_ONCE(desc->msg0, 0);
- WRITE_ONCE(desc->msg1, 0);
+ dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
+ DMA_TO_DEVICE);
+ memset(e, 0, sizeof(*e));
+ WRITE_ONCE(desc->msg0, 0);
+ WRITE_ONCE(desc->msg1, 0);
+ q->queued--;
- if (skb) {
- struct netdev_queue *txq;
+ /* completion ring can report out-of-order indexes if hw QoS
+ * is enabled and packets with different priority are queued
+ * to same DMA ring. Take into account possible out-of-order
+ * reports incrementing DMA ring tail pointer
+ */
+ while (q->tail != q->head && !q->entry[q->tail].dma_addr)
+ q->tail = (q->tail + 1) % q->ndesc;
- txq = netdev_get_tx_queue(skb->dev, qid);
- if (netif_tx_queue_stopped(txq) &&
- q->ndesc - q->queued >= q->free_thr)
- netif_tx_wake_queue(txq);
+ if (skb) {
+ u16 queue = skb_get_queue_mapping(skb);
+ struct netdev_queue *txq;
- dev_kfree_skb_any(skb);
- e->skb = NULL;
- }
+ txq = netdev_get_tx_queue(skb->dev, queue);
+ netdev_tx_completed_queue(txq, 1, skb->len);
+ if (netif_tx_queue_stopped(txq) &&
+ q->ndesc - q->queued >= q->free_thr)
+ netif_tx_wake_queue(txq);
- if (index == last)
- break;
+ dev_kfree_skb_any(skb);
}
-
+unlock:
spin_unlock_bh(&q->lock);
}
@@ -2015,20 +2039,11 @@ static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
if (intr[0] & INT_TX_MASK) {
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
- struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i];
- u32 status, head;
-
if (!(intr[0] & TX_DONE_INT_MASK(i)))
continue;
airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0,
TX_DONE_INT_MASK(i));
-
- status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
- head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
- irq_q->head = head % irq_q->size;
- irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
-
napi_schedule(&qdma->q_tx_irq[i].napi);
}
}
@@ -2331,7 +2346,7 @@ static int airoha_dev_stop(struct net_device *dev)
{
struct airoha_gdm_port *port = netdev_priv(dev);
struct airoha_qdma *qdma = port->qdma;
- int err;
+ int i, err;
netif_tx_disable(dev);
err = airoha_set_gdm_ports(qdma->eth, false);
@@ -2342,6 +2357,14 @@ static int airoha_dev_stop(struct net_device *dev)
GLOBAL_CFG_TX_DMA_EN_MASK |
GLOBAL_CFG_RX_DMA_EN_MASK);
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
+ if (!qdma->q_tx[i].ndesc)
+ continue;
+
+ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
+ netdev_tx_reset_subqueue(dev, i);
+ }
+
return 0;
}
@@ -2479,7 +2502,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
q->queued += i;
skb_tx_timestamp(skb);
- if (!netdev_xmit_more())
+ netdev_tx_sent_queue(txq, skb->len);
+
+ if (netif_xmit_stopped(txq) || !netdev_xmit_more())
airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
TX_RING_CPU_IDX_MASK,
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
@@ -2780,7 +2805,7 @@ MODULE_DEVICE_TABLE(of, of_airoha_match);
static struct platform_driver airoha_driver = {
.probe = airoha_probe,
- .remove_new = airoha_remove,
+ .remove = airoha_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_airoha_match,
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ed7313c10a05..53485142938c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2227,7 +2227,7 @@ rx_done:
eth->rx_bytes += bytes;
dim_update_sample(eth->rx_events, eth->rx_packets, eth->rx_bytes,
&dim_sample);
- net_dim(&eth->rx_dim, dim_sample);
+ net_dim(&eth->rx_dim, &dim_sample);
if (xdp_flush)
xdp_do_flush();
@@ -2377,7 +2377,7 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes,
&dim_sample);
- net_dim(&eth->tx_dim, dim_sample);
+ net_dim(&eth->tx_dim, &dim_sample);
if (mtk_queue_stopped(eth) &&
(atomic_read(&ring->free_count) > ring->thresh))
@@ -4329,10 +4329,8 @@ static void mtk_get_strings(struct net_device *dev, u32 stringset, u8 *data)
case ETH_SS_STATS: {
struct mtk_mac *mac = netdev_priv(dev);
- for (i = 0; i < ARRAY_SIZE(mtk_ethtool_stats); i++) {
- memcpy(data, mtk_ethtool_stats[i].str, ETH_GSTRING_LEN);
- data += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < ARRAY_SIZE(mtk_ethtool_stats); i++)
+ ethtool_puts(&data, mtk_ethtool_stats[i].str);
if (mtk_page_pool_enabled(mac->hw))
page_pool_ethtool_stats_get_strings(data);
break;
@@ -5358,7 +5356,7 @@ MODULE_DEVICE_TABLE(of, of_mtk_match);
static struct platform_driver mtk_driver = {
.probe = mtk_probe,
- .remove_new = mtk_remove,
+ .remove = mtk_remove,
.driver = {
.name = "mtk_soc_eth",
.of_match_table = of_mtk_match,
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index 461cc2c79c71..0e92956e84cf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -156,7 +156,8 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
break;
case RX:
cq->mcq.comp = mlx4_en_rx_irq;
- netif_napi_add(cq->dev, &cq->napi, mlx4_en_poll_rx_cq);
+ netif_napi_add_config(cq->dev, &cq->napi, mlx4_en_poll_rx_cq,
+ cq_idx);
netif_napi_set_irq(&cq->napi, irq);
napi_enable(&cq->napi);
netif_queue_set_napi(cq->dev, cq_idx, NETDEV_QUEUE_TYPE_RX, &cq->napi);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 5912f7e614f9..be3d0876c521 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -109,35 +109,48 @@ mlx5_core-$(CONFIG_MLX5_EN_TLS) += en_accel/ktls_stats.o \
en_accel/fs_tcp.o en_accel/ktls.o en_accel/ktls_txrx.o \
en_accel/ktls_tx.o en_accel/ktls_rx.o
-mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/dr_domain.o steering/dr_table.o \
- steering/dr_matcher.o steering/dr_rule.o \
- steering/dr_icm_pool.o steering/dr_buddy.o \
- steering/dr_ste.o steering/dr_send.o \
- steering/dr_ste_v0.o steering/dr_ste_v1.o \
- steering/dr_ste_v2.o \
- steering/dr_cmd.o steering/dr_fw.o \
- steering/dr_action.o steering/fs_dr.o \
- steering/dr_definer.o steering/dr_ptrn.o \
- steering/dr_arg.o steering/dr_dbg.o lib/smfs.o
+#
+# SW Steering
+#
+mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/sws/dr_domain.o \
+ steering/sws/dr_table.o \
+ steering/sws/dr_matcher.o \
+ steering/sws/dr_rule.o \
+ steering/sws/dr_icm_pool.o \
+ steering/sws/dr_buddy.o \
+ steering/sws/dr_ste.o \
+ steering/sws/dr_send.o \
+ steering/sws/dr_ste_v0.o \
+ steering/sws/dr_ste_v1.o \
+ steering/sws/dr_ste_v2.o \
+ steering/sws/dr_cmd.o \
+ steering/sws/dr_fw.o \
+ steering/sws/dr_action.o \
+ steering/sws/dr_definer.o \
+ steering/sws/dr_ptrn.o \
+ steering/sws/dr_arg.o \
+ steering/sws/dr_dbg.o \
+ steering/sws/fs_dr.o \
+ lib/smfs.o
#
# HW Steering
#
-mlx5_core-$(CONFIG_MLX5_HW_STEERING) += steering/hws/mlx5hws_cmd.o \
- steering/hws/mlx5hws_context.o \
- steering/hws/mlx5hws_pat_arg.o \
- steering/hws/mlx5hws_buddy.o \
- steering/hws/mlx5hws_pool.o \
- steering/hws/mlx5hws_table.o \
- steering/hws/mlx5hws_action.o \
- steering/hws/mlx5hws_rule.o \
- steering/hws/mlx5hws_matcher.o \
- steering/hws/mlx5hws_send.o \
- steering/hws/mlx5hws_definer.o \
- steering/hws/mlx5hws_bwc.o \
- steering/hws/mlx5hws_debug.o \
- steering/hws/mlx5hws_vport.o \
- steering/hws/mlx5hws_bwc_complex.o
+mlx5_core-$(CONFIG_MLX5_HW_STEERING) += steering/hws/cmd.o \
+ steering/hws/context.o \
+ steering/hws/pat_arg.o \
+ steering/hws/buddy.o \
+ steering/hws/pool.o \
+ steering/hws/table.o \
+ steering/hws/action.o \
+ steering/hws/rule.o \
+ steering/hws/matcher.o \
+ steering/hws/send.o \
+ steering/hws/definer.o \
+ steering/hws/bwc.o \
+ steering/hws/debug.o \
+ steering/hws/vport.o \
+ steering/hws/bwc_complex.o
#
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
index 4caa1b6f40ba..1fd403713baf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
@@ -71,6 +71,7 @@ static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq,
{
unsigned long flags;
struct mlx5_eq_tasklet *tasklet_ctx = cq->tasklet_ctx.priv;
+ bool schedule_tasklet = false;
spin_lock_irqsave(&tasklet_ctx->lock, flags);
/* When migrating CQs between EQs will be implemented, please note
@@ -80,9 +81,19 @@ static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq,
*/
if (list_empty_careful(&cq->tasklet_ctx.list)) {
mlx5_cq_hold(cq);
+ /* If the tasklet CQ work list isn't empty, mlx5_cq_tasklet_cb()
+ * is scheduled/running and hasn't processed the list yet, so it
+ * will see this added CQ when it runs. If the list is empty,
+ * the tasklet needs to be scheduled to pick up the CQ. The
+ * spinlock avoids any race with the tasklet accessing the list.
+ */
+ schedule_tasklet = list_empty(&tasklet_ctx->list);
list_add_tail(&cq->tasklet_ctx.list, &tasklet_ctx->list);
}
spin_unlock_irqrestore(&tasklet_ctx->lock, flags);
+
+ if (schedule_tasklet)
+ tasklet_schedule(&tasklet_ctx->task);
}
/* Callers must verify outbox status in case of err */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
index 904e08de852e..31142f6cc372 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
@@ -166,9 +166,90 @@ static int mlx5_dpll_device_mode_get(const struct dpll_device *dpll,
return 0;
}
+enum {
+ MLX5_DPLL_SSM_CODE_PRC = 0b0010,
+ MLX5_DPLL_SSM_CODE_SSU_A = 0b0100,
+ MLX5_DPLL_SSM_CODE_SSU_B = 0b1000,
+ MLX5_DPLL_SSM_CODE_EEC1 = 0b1011,
+ MLX5_DPLL_SSM_CODE_PRTC = 0b0010,
+ MLX5_DPLL_SSM_CODE_EPRTC = 0b0010,
+ MLX5_DPLL_SSM_CODE_EEEC = 0b1011,
+ MLX5_DPLL_SSM_CODE_EPRC = 0b0010,
+};
+
+enum {
+ MLX5_DPLL_ENHANCED_SSM_CODE_PRC = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_SSU_A = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_SSU_B = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EEC1 = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_PRTC = 0x20,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EPRTC = 0x21,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EEEC = 0x22,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EPRC = 0x23,
+};
+
+#define __MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code) \
+ ((ssm_code) | ((enhanced_ssm_code) << 8))
+
+#define MLX5_DPLL_SSM_COMBINED_CODE(type) \
+ __MLX5_DPLL_SSM_COMBINED_CODE(MLX5_DPLL_SSM_CODE_##type, \
+ MLX5_DPLL_ENHANCED_SSM_CODE_##type)
+
+static int mlx5_dpll_clock_quality_level_get(const struct dpll_device *dpll,
+ void *priv, unsigned long *qls,
+ struct netlink_ext_ack *extack)
+{
+ u8 network_option, ssm_code, enhanced_ssm_code;
+ u32 out[MLX5_ST_SZ_DW(msecq_reg)] = {};
+ u32 in[MLX5_ST_SZ_DW(msecq_reg)] = {};
+ struct mlx5_dpll *mdpll = priv;
+ int err;
+
+ err = mlx5_core_access_reg(mdpll->mdev, in, sizeof(in),
+ out, sizeof(out), MLX5_REG_MSECQ, 0, 0);
+ if (err)
+ return err;
+ network_option = MLX5_GET(msecq_reg, out, network_option);
+ if (network_option != 1)
+ goto errout;
+ ssm_code = MLX5_GET(msecq_reg, out, local_ssm_code);
+ enhanced_ssm_code = MLX5_GET(msecq_reg, out, local_enhanced_ssm_code);
+
+ switch (__MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code)) {
+ case MLX5_DPLL_SSM_COMBINED_CODE(PRC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(SSU_A):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_A, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(SSU_B):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_B, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EEC1):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEC1, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(PRTC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRTC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EPRTC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRTC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EEEC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEEC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EPRC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC, qls);
+ return 0;
+ }
+errout:
+ NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware\n");
+ return -EINVAL;
+}
+
static const struct dpll_device_ops mlx5_dpll_device_ops = {
.lock_status_get = mlx5_dpll_device_lock_status_get,
.mode_get = mlx5_dpll_device_mode_get,
+ .clock_quality_level_get = mlx5_dpll_clock_quality_level_get,
};
static int mlx5_dpll_pin_direction_get(const struct dpll_pin *pin,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 57b7298a0e79..979fc56205e1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -83,6 +83,7 @@ struct page_pool;
#define MLX5E_SHAMPO_LOG_HEADER_ENTRY_SIZE (8)
#define MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE (9)
#define MLX5E_SHAMPO_WQ_HEADER_PER_PAGE (PAGE_SIZE >> MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE)
+#define MLX5E_SHAMPO_LOG_WQ_HEADER_PER_PAGE (PAGE_SHIFT - MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE)
#define MLX5E_SHAMPO_WQ_BASE_HEAD_ENTRY_SIZE (64)
#define MLX5E_SHAMPO_WQ_RESRV_SIZE (64 * 1024)
#define MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE (4096)
@@ -624,16 +625,14 @@ struct mlx5e_dma_info {
struct mlx5e_shampo_hd {
u32 mkey;
- struct mlx5e_dma_info *info;
struct mlx5e_frag_page *pages;
- u16 curr_page_index;
u32 hd_per_wq;
u16 hd_per_wqe;
+ u16 pages_per_wq;
unsigned long *bitmap;
u16 pi;
u16 ci;
__be32 key;
- u64 last_addr;
};
struct mlx5e_hw_gro_data {
@@ -755,7 +754,7 @@ struct mlx5e_channel {
u8 lag_port;
/* XDP_REDIRECT */
- struct mlx5e_xdpsq xdpsq;
+ struct mlx5e_xdpsq *xdpsq;
/* AF_XDP zero-copy */
struct mlx5e_rq xskrq;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
index 1c062a2e8996..45737d039252 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
@@ -318,7 +318,7 @@ mlx5_ct_fs_smfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
}
actions[num_actions++] = smfs_rule->count_action;
- actions[num_actions++] = attr->modify_hdr->action.dr_action;
+ actions[num_actions++] = attr->modify_hdr->fs_dr_action.dr_action;
actions[num_actions++] = fs_smfs->fwd_action;
nat = (attr->ft == fs_smfs->ct_nat);
@@ -379,7 +379,7 @@ static int mlx5_ct_fs_smfs_ct_rule_update(struct mlx5_ct_fs *fs, struct mlx5_ct_
struct mlx5dr_rule *rule;
actions[0] = smfs_rule->count_action;
- actions[1] = attr->modify_hdr->action.dr_action;
+ actions[1] = attr->modify_hdr->fs_dr_action.dr_action;
actions[2] = fs_smfs->fwd_action;
rule = mlx5_smfs_rule_create(smfs_rule->smfs_matcher->dr_matcher, spec,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
index dcfccaaa8d91..a84ebac2f011 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
@@ -866,7 +866,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
return 0;
err_rule:
- mlx5_tc_ct_entry_destroy_mod_hdr(ct_priv, zone_rule->attr, zone_rule->mh);
+ mlx5_tc_ct_entry_destroy_mod_hdr(ct_priv, attr, zone_rule->mh);
mlx5_put_label_mapping(ct_priv, attr->ct_attr.ct_labels_id);
err_mod_hdr:
kfree(attr);
@@ -1026,7 +1026,7 @@ mlx5_tc_ct_counter_create(struct mlx5_tc_ct_priv *ct_priv)
return ERR_PTR(-ENOMEM);
counter->is_shared = false;
- counter->counter = mlx5_fc_create_ex(ct_priv->dev, true);
+ counter->counter = mlx5_fc_create(ct_priv->dev, true);
if (IS_ERR(counter->counter)) {
ct_dbg("Failed to create counter for ct entry");
ret = PTR_ERR(counter->counter);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index 4610621a340e..94b291662087 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -865,7 +865,7 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
if (unlikely(sq_num >= priv->channels.num))
return -ENXIO;
- sq = &priv->channels.c[sq_num]->xdpsq;
+ sq = priv->channels.c[sq_num]->xdpsq;
for (i = 0; i < n; i++) {
struct mlx5e_xmit_data_frags xdptxdf = {};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
index d61be26a4df1..3db31cc10719 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
@@ -660,7 +660,7 @@ tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
while (remaining > 0) {
skb_frag_t *frag = &record->frags[i];
- get_page(skb_frag_page(frag));
+ page_ref_inc(skb_frag_page(frag));
remaining -= skb_frag_size(frag);
info->frags[i++] = *frag;
}
@@ -763,7 +763,7 @@ void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
stats = sq->stats;
mlx5e_tx_dma_unmap(sq->pdev, dma);
- put_page(wi->resync_dump_frag_page);
+ page_ref_dec(wi->resync_dump_frag_page);
stats->tls_dump_packets++;
stats->tls_dump_bytes += wi->num_bytes;
}
@@ -816,12 +816,12 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx,
err_out:
for (; i < info.nr_frags; i++)
- /* The put_page() here undoes the page ref obtained in tx_sync_info_get().
+ /* The page_ref_dec() here undoes the page ref obtained in tx_sync_info_get().
* Page refs obtained for the DUMP WQEs above (by page_ref_add) will be
* released only upon their completions (or in mlx5e_free_txqsq_descs,
* if channel closes).
*/
- put_page(skb_frag_page(&info.frags[i]));
+ page_ref_dec(skb_frag_page(&info.frags[i]));
return MLX5E_KTLS_SYNC_FAIL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 1966736f98b4..cae39198b4db 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -406,6 +406,9 @@ int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv,
unlock:
mutex_unlock(&priv->state_lock);
+ if (!err)
+ netdev_update_features(priv->netdev);
+
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index e601324a690a..d0b80b520397 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -350,19 +350,15 @@ static int mlx5e_rq_shampo_hd_info_alloc(struct mlx5e_rq *rq, int node)
shampo->bitmap = bitmap_zalloc_node(shampo->hd_per_wq, GFP_KERNEL,
node);
- shampo->info = kvzalloc_node(array_size(shampo->hd_per_wq,
- sizeof(*shampo->info)),
- GFP_KERNEL, node);
shampo->pages = kvzalloc_node(array_size(shampo->hd_per_wq,
sizeof(*shampo->pages)),
GFP_KERNEL, node);
- if (!shampo->bitmap || !shampo->info || !shampo->pages)
+ if (!shampo->bitmap || !shampo->pages)
goto err_nomem;
return 0;
err_nomem:
- kvfree(shampo->info);
kvfree(shampo->bitmap);
kvfree(shampo->pages);
@@ -372,7 +368,6 @@ err_nomem:
static void mlx5e_rq_shampo_hd_info_free(struct mlx5e_rq *rq)
{
kvfree(rq->mpwqe.shampo->bitmap);
- kvfree(rq->mpwqe.shampo->info);
kvfree(rq->mpwqe.shampo->pages);
}
@@ -767,8 +762,6 @@ static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev,
u32 *pool_size,
int node)
{
- void *wqc = MLX5_ADDR_OF(rqc, rqp->rqc, wq);
- int wq_size;
int err;
if (!test_bit(MLX5E_RQ_STATE_SHAMPO, &rq->state))
@@ -793,9 +786,9 @@ static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev,
cpu_to_be32(rq->mpwqe.shampo->mkey);
rq->mpwqe.shampo->hd_per_wqe =
mlx5e_shampo_hd_per_wqe(mdev, params, rqp);
- wq_size = BIT(MLX5_GET(wq, wqc, log_wq_sz));
- *pool_size += (rq->mpwqe.shampo->hd_per_wqe * wq_size) /
- MLX5E_SHAMPO_WQ_HEADER_PER_PAGE;
+ rq->mpwqe.shampo->pages_per_wq =
+ rq->mpwqe.shampo->hd_per_wq / MLX5E_SHAMPO_WQ_HEADER_PER_PAGE;
+ *pool_size += rq->mpwqe.shampo->pages_per_wq;
return 0;
err_hw_gro_data:
@@ -1126,7 +1119,7 @@ static void mlx5e_flush_rq_cq(struct mlx5e_rq *rq)
struct mlx5_cqe64 *cqe;
if (test_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state)) {
- while ((cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq)))
+ while ((cqe = mlx5_cqwq_get_cqe_enhanced_comp(cqwq)))
mlx5_cqwq_pop(cqwq);
} else {
while ((cqe = mlx5_cqwq_get_cqe(cqwq)))
@@ -2086,6 +2079,44 @@ void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq)
mlx5e_free_xdpsq(sq);
}
+static struct mlx5e_xdpsq *mlx5e_open_xdpredirect_sq(struct mlx5e_channel *c,
+ struct mlx5e_params *params,
+ struct mlx5e_channel_param *cparam,
+ struct mlx5e_create_cq_param *ccp)
+{
+ struct mlx5e_xdpsq *xdpsq;
+ int err;
+
+ xdpsq = kvzalloc_node(sizeof(*xdpsq), GFP_KERNEL, c->cpu);
+ if (!xdpsq)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlx5e_open_cq(c->mdev, params->tx_cq_moderation,
+ &cparam->xdp_sq.cqp, ccp, &xdpsq->cq);
+ if (err)
+ goto err_free_xdpsq;
+
+ err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, NULL, xdpsq, true);
+ if (err)
+ goto err_close_xdpsq_cq;
+
+ return xdpsq;
+
+err_close_xdpsq_cq:
+ mlx5e_close_cq(&xdpsq->cq);
+err_free_xdpsq:
+ kvfree(xdpsq);
+
+ return ERR_PTR(err);
+}
+
+static void mlx5e_close_xdpredirect_sq(struct mlx5e_xdpsq *xdpsq)
+{
+ mlx5e_close_xdpsq(xdpsq);
+ mlx5e_close_cq(&xdpsq->cq);
+ kvfree(xdpsq);
+}
+
static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,
struct net_device *netdev,
struct workqueue_struct *workqueue,
@@ -2476,6 +2507,7 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
struct mlx5e_params *params,
struct mlx5e_channel_param *cparam)
{
+ const struct net_device_ops *netdev_ops = c->netdev->netdev_ops;
struct dim_cq_moder icocq_moder = {0, 0};
struct mlx5e_create_cq_param ccp;
int err;
@@ -2496,15 +2528,18 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
if (err)
goto err_close_icosq_cq;
- err = mlx5e_open_cq(c->mdev, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp,
- &c->xdpsq.cq);
- if (err)
- goto err_close_tx_cqs;
+ if (netdev_ops->ndo_xdp_xmit) {
+ c->xdpsq = mlx5e_open_xdpredirect_sq(c, params, cparam, &ccp);
+ if (IS_ERR(c->xdpsq)) {
+ err = PTR_ERR(c->xdpsq);
+ goto err_close_tx_cqs;
+ }
+ }
err = mlx5e_open_cq(c->mdev, params->rx_cq_moderation, &cparam->rq.cqp, &ccp,
&c->rq.cq);
if (err)
- goto err_close_xdp_tx_cqs;
+ goto err_close_xdpredirect_sq;
err = c->xdp ? mlx5e_open_cq(c->mdev, params->tx_cq_moderation, &cparam->xdp_sq.cqp,
&ccp, &c->rq_xdpsq.cq) : 0;
@@ -2516,7 +2551,7 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
err = mlx5e_open_icosq(c, params, &cparam->async_icosq, &c->async_icosq,
mlx5e_async_icosq_err_cqe_work);
if (err)
- goto err_close_xdpsq_cq;
+ goto err_close_rq_xdpsq_cq;
mutex_init(&c->icosq_recovery_lock);
@@ -2540,16 +2575,8 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
goto err_close_rq;
}
- err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, NULL, &c->xdpsq, true);
- if (err)
- goto err_close_xdp_sq;
-
return 0;
-err_close_xdp_sq:
- if (c->xdp)
- mlx5e_close_xdpsq(&c->rq_xdpsq);
-
err_close_rq:
mlx5e_close_rq(&c->rq);
@@ -2562,15 +2589,16 @@ err_close_icosq:
err_close_async_icosq:
mlx5e_close_icosq(&c->async_icosq);
-err_close_xdpsq_cq:
+err_close_rq_xdpsq_cq:
if (c->xdp)
mlx5e_close_cq(&c->rq_xdpsq.cq);
err_close_rx_cq:
mlx5e_close_cq(&c->rq.cq);
-err_close_xdp_tx_cqs:
- mlx5e_close_cq(&c->xdpsq.cq);
+err_close_xdpredirect_sq:
+ if (c->xdpsq)
+ mlx5e_close_xdpredirect_sq(c->xdpsq);
err_close_tx_cqs:
mlx5e_close_tx_cqs(c);
@@ -2586,7 +2614,6 @@ err_close_async_icosq_cq:
static void mlx5e_close_queues(struct mlx5e_channel *c)
{
- mlx5e_close_xdpsq(&c->xdpsq);
if (c->xdp)
mlx5e_close_xdpsq(&c->rq_xdpsq);
/* The same ICOSQ is used for UMRs for both RQ and XSKRQ. */
@@ -2599,7 +2626,8 @@ static void mlx5e_close_queues(struct mlx5e_channel *c)
if (c->xdp)
mlx5e_close_cq(&c->rq_xdpsq.cq);
mlx5e_close_cq(&c->rq.cq);
- mlx5e_close_cq(&c->xdpsq.cq);
+ if (c->xdpsq)
+ mlx5e_close_xdpredirect_sq(c->xdpsq);
mlx5e_close_tx_cqs(c);
mlx5e_close_cq(&c->icosq.cq);
mlx5e_close_cq(&c->async_icosq.cq);
@@ -2697,7 +2725,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
c->aff_mask = irq_get_effective_affinity_mask(irq);
c->lag_port = mlx5e_enumerate_lag_port(mdev, ix);
- netif_napi_add(netdev, &c->napi, mlx5e_napi_poll);
+ netif_napi_add_config(netdev, &c->napi, mlx5e_napi_poll, ix);
netif_napi_set_irq(&c->napi, irq);
err = mlx5e_open_queues(c, params, cparam);
@@ -4267,7 +4295,8 @@ void mlx5e_set_xdp_feature(struct net_device *netdev)
struct mlx5e_params *params = &priv->channels.params;
xdp_features_t val;
- if (params->packet_merge.type != MLX5E_PACKET_MERGE_NONE) {
+ if (!netdev->netdev_ops->ndo_bpf ||
+ params->packet_merge.type != MLX5E_PACKET_MERGE_NONE) {
xdp_clear_features_flag(netdev);
return;
}
@@ -4557,6 +4586,10 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
out:
WRITE_ONCE(netdev->mtu, params->sw_mtu);
mutex_unlock(&priv->state_lock);
+
+ if (!err)
+ netdev_update_features(netdev);
+
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 92094bf60d59..554f9cb5b53f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -600,7 +600,8 @@ mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
if (c->xdp)
sqs[num_sqs++] = c->rq_xdpsq.sqn;
- sqs[num_sqs++] = c->xdpsq.sqn;
+ if (c->xdpsq)
+ sqs[num_sqs++] = c->xdpsq->sqn;
}
}
if (ptp_sq) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 8e24ba96c779..1963bc5adb18 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -643,83 +643,82 @@ static void build_ksm_umr(struct mlx5e_icosq *sq, struct mlx5e_umr_wqe *umr_wqe,
umr_wqe->uctrl.mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE);
}
+static struct mlx5e_frag_page *mlx5e_shampo_hd_to_frag_page(struct mlx5e_rq *rq, int header_index)
+{
+ BUILD_BUG_ON(MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE > PAGE_SHIFT);
+
+ return &rq->mpwqe.shampo->pages[header_index >> MLX5E_SHAMPO_LOG_WQ_HEADER_PER_PAGE];
+}
+
+static u64 mlx5e_shampo_hd_offset(int header_index)
+{
+ return (header_index & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) <<
+ MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE;
+}
+
+static void mlx5e_free_rx_shampo_hd_entry(struct mlx5e_rq *rq, u16 header_index);
+
static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq,
struct mlx5e_icosq *sq,
u16 ksm_entries, u16 index)
{
struct mlx5e_shampo_hd *shampo = rq->mpwqe.shampo;
- u16 entries, pi, header_offset, err, wqe_bbs, new_entries;
+ u16 pi, header_offset, err, wqe_bbs;
u32 lkey = rq->mdev->mlx5e_res.hw_objs.mkey;
- u16 page_index = shampo->curr_page_index;
- struct mlx5e_frag_page *frag_page;
- u64 addr = shampo->last_addr;
- struct mlx5e_dma_info *dma_info;
struct mlx5e_umr_wqe *umr_wqe;
- int headroom, i;
+ int headroom, i = 0;
headroom = rq->buff.headroom;
- new_entries = ksm_entries - (shampo->pi & (MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT - 1));
- entries = ALIGN(ksm_entries, MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT);
- wqe_bbs = MLX5E_KSM_UMR_WQEBBS(entries);
+ wqe_bbs = MLX5E_KSM_UMR_WQEBBS(ksm_entries);
pi = mlx5e_icosq_get_next_pi(sq, wqe_bbs);
umr_wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
- build_ksm_umr(sq, umr_wqe, shampo->key, index, entries);
+ build_ksm_umr(sq, umr_wqe, shampo->key, index, ksm_entries);
- frag_page = &shampo->pages[page_index];
+ WARN_ON_ONCE(ksm_entries & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1));
+ while (i < ksm_entries) {
+ struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
+ u64 addr;
- for (i = 0; i < entries; i++, index++) {
- dma_info = &shampo->info[index];
- if (i >= ksm_entries || (index < shampo->pi && shampo->pi - index <
- MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT))
- goto update_ksm;
- header_offset = (index & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) <<
- MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE;
- if (!(header_offset & (PAGE_SIZE - 1))) {
- page_index = (page_index + 1) & (shampo->hd_per_wq - 1);
- frag_page = &shampo->pages[page_index];
+ err = mlx5e_page_alloc_fragmented(rq, frag_page);
+ if (unlikely(err))
+ goto err_unmap;
- err = mlx5e_page_alloc_fragmented(rq, frag_page);
- if (unlikely(err))
- goto err_unmap;
- addr = page_pool_get_dma_addr(frag_page->page);
+ addr = page_pool_get_dma_addr(frag_page->page);
- dma_info->addr = addr;
- dma_info->frag_page = frag_page;
- } else {
- dma_info->addr = addr + header_offset;
- dma_info->frag_page = frag_page;
- }
+ for (int j = 0; j < MLX5E_SHAMPO_WQ_HEADER_PER_PAGE; j++) {
+ header_offset = mlx5e_shampo_hd_offset(index++);
-update_ksm:
- umr_wqe->inline_ksms[i] = (struct mlx5_ksm) {
- .key = cpu_to_be32(lkey),
- .va = cpu_to_be64(dma_info->addr + headroom),
- };
+ umr_wqe->inline_ksms[i++] = (struct mlx5_ksm) {
+ .key = cpu_to_be32(lkey),
+ .va = cpu_to_be64(addr + header_offset + headroom),
+ };
+ }
}
sq->db.wqe_info[pi] = (struct mlx5e_icosq_wqe_info) {
.wqe_type = MLX5E_ICOSQ_WQE_SHAMPO_HD_UMR,
.num_wqebbs = wqe_bbs,
- .shampo.len = new_entries,
+ .shampo.len = ksm_entries,
};
- shampo->pi = (shampo->pi + new_entries) & (shampo->hd_per_wq - 1);
- shampo->curr_page_index = page_index;
- shampo->last_addr = addr;
+ shampo->pi = (shampo->pi + ksm_entries) & (shampo->hd_per_wq - 1);
sq->pc += wqe_bbs;
sq->doorbell_cseg = &umr_wqe->ctrl;
return 0;
err_unmap:
- while (--i >= 0) {
- dma_info = &shampo->info[--index];
- if (!(i & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1))) {
- dma_info->addr = ALIGN_DOWN(dma_info->addr, PAGE_SIZE);
- mlx5e_page_release_fragmented(rq, dma_info->frag_page);
+ while (--i) {
+ --index;
+ header_offset = mlx5e_shampo_hd_offset(index);
+ if (!header_offset) {
+ struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index);
+
+ mlx5e_page_release_fragmented(rq, frag_page);
}
}
+
rq->stats->buff_alloc_err++;
return err;
}
@@ -731,7 +730,8 @@ static int mlx5e_alloc_rx_hd_mpwqe(struct mlx5e_rq *rq)
struct mlx5e_icosq *sq = rq->icosq;
int i, err, max_ksm_entries, len;
- max_ksm_entries = MLX5E_MAX_KSM_PER_WQE(rq->mdev);
+ max_ksm_entries = ALIGN_DOWN(MLX5E_MAX_KSM_PER_WQE(rq->mdev),
+ MLX5E_SHAMPO_WQ_HEADER_PER_PAGE);
ksm_entries = bitmap_find_window(shampo->bitmap,
shampo->hd_per_wqe,
shampo->hd_per_wq, shampo->pi);
@@ -739,8 +739,8 @@ static int mlx5e_alloc_rx_hd_mpwqe(struct mlx5e_rq *rq)
if (!ksm_entries)
return 0;
- ksm_entries += (shampo->pi & (MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT - 1));
- index = ALIGN_DOWN(shampo->pi, MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT);
+ /* pi is aligned to MLX5E_SHAMPO_WQ_HEADER_PER_PAGE */
+ index = shampo->pi;
entries_before = shampo->hd_per_wq - index;
if (unlikely(entries_before < ksm_entries))
@@ -851,13 +851,11 @@ static void
mlx5e_free_rx_shampo_hd_entry(struct mlx5e_rq *rq, u16 header_index)
{
struct mlx5e_shampo_hd *shampo = rq->mpwqe.shampo;
- u64 addr = shampo->info[header_index].addr;
if (((header_index + 1) & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) == 0) {
- struct mlx5e_dma_info *dma_info = &shampo->info[header_index];
+ struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, header_index);
- dma_info->addr = ALIGN_DOWN(addr, PAGE_SIZE);
- mlx5e_page_release_fragmented(rq, dma_info->frag_page);
+ mlx5e_page_release_fragmented(rq, frag_page);
}
clear_bit(header_index, shampo->bitmap);
}
@@ -1211,10 +1209,10 @@ static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe,
static void *mlx5e_shampo_get_packet_hd(struct mlx5e_rq *rq, u16 header_index)
{
- struct mlx5e_dma_info *last_head = &rq->mpwqe.shampo->info[header_index];
- u16 head_offset = (last_head->addr & (PAGE_SIZE - 1)) + rq->buff.headroom;
+ struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, header_index);
+ u16 head_offset = mlx5e_shampo_hd_offset(header_index) + rq->buff.headroom;
- return page_address(last_head->frag_page->page) + head_offset;
+ return page_address(frag_page->page) + head_offset;
}
static void mlx5e_shampo_update_ipv4_udp_hdr(struct mlx5e_rq *rq, struct iphdr *ipv4)
@@ -2185,29 +2183,30 @@ static struct sk_buff *
mlx5e_skb_from_cqe_shampo(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
struct mlx5_cqe64 *cqe, u16 header_index)
{
- struct mlx5e_dma_info *head = &rq->mpwqe.shampo->info[header_index];
- u16 head_offset = head->addr & (PAGE_SIZE - 1);
+ struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, header_index);
+ dma_addr_t page_dma_addr = page_pool_get_dma_addr(frag_page->page);
+ u16 head_offset = mlx5e_shampo_hd_offset(header_index);
+ dma_addr_t dma_addr = page_dma_addr + head_offset;
u16 head_size = cqe->shampo.header_size;
u16 rx_headroom = rq->buff.headroom;
struct sk_buff *skb = NULL;
void *hdr, *data;
u32 frag_size;
- hdr = page_address(head->frag_page->page) + head_offset;
+ hdr = page_address(frag_page->page) + head_offset;
data = hdr + rx_headroom;
frag_size = MLX5_SKB_FRAG_SZ(rx_headroom + head_size);
if (likely(frag_size <= BIT(MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE))) {
/* build SKB around header */
- dma_sync_single_range_for_cpu(rq->pdev, head->addr, 0, frag_size, rq->buff.map_dir);
+ dma_sync_single_range_for_cpu(rq->pdev, dma_addr, 0, frag_size, rq->buff.map_dir);
net_prefetchw(hdr);
net_prefetch(data);
skb = mlx5e_build_linear_skb(rq, hdr, frag_size, rx_headroom, head_size, 0);
-
if (unlikely(!skb))
return NULL;
- head->frag_page->frags++;
+ frag_page->frags++;
} else {
/* allocate SKB and copy header for large header */
rq->stats->gro_large_hds++;
@@ -2219,7 +2218,7 @@ mlx5e_skb_from_cqe_shampo(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
}
net_prefetchw(skb->data);
- mlx5e_copy_skb_header(rq, skb, head->frag_page->page, head->addr,
+ mlx5e_copy_skb_header(rq, skb, frag_page->page, dma_addr,
head_offset + rx_headroom,
rx_headroom, head_size);
/* skb linear part was allocated with headlen and aligned to long */
@@ -2436,7 +2435,7 @@ static int mlx5e_rx_cq_process_enhanced_cqe_comp(struct mlx5e_rq *rq,
struct mlx5e_cq_decomp *cqd = &rq->cqd;
int work_done = 0;
- cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq);
+ cqe = mlx5_cqwq_get_cqe_enhanced_comp(cqwq);
if (!cqe)
return work_done;
@@ -2466,7 +2465,7 @@ static int mlx5e_rx_cq_process_enhanced_cqe_comp(struct mlx5e_rq *rq,
rq, cqe);
work_done++;
} while (work_done < budget_rem &&
- (cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq)));
+ (cqe = mlx5_cqwq_get_cqe_enhanced_comp(cqwq)));
/* last cqe might be title on next poll bulk */
if (title_cqe) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
index 5bf8318cc48b..1d60465cc2ca 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
@@ -36,6 +36,7 @@
#include "en.h"
#include "en/port.h"
#include "eswitch.h"
+#include "lib/mlx5.h"
static int mlx5e_test_health_info(struct mlx5e_priv *priv)
{
@@ -247,6 +248,9 @@ static int mlx5e_cond_loopback(struct mlx5e_priv *priv)
if (is_mdev_switchdev_mode(priv->mdev))
return -EOPNOTSUPP;
+ if (mlx5_get_sd(priv->mdev))
+ return -EOPNOTSUPP;
+
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
index 5873fde65c2e..76108299ea57 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
@@ -55,7 +55,7 @@ static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
return;
dim_update_sample(sq->cq.event_ctr, stats->packets, stats->bytes, &dim_sample);
- net_dim(sq->dim, dim_sample);
+ net_dim(sq->dim, &dim_sample);
}
static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq)
@@ -67,7 +67,7 @@ static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq)
return;
dim_update_sample(rq->cq.event_ctr, stats->packets, stats->bytes, &dim_sample);
- net_dim(rq->dim, dim_sample);
+ net_dim(rq->dim, &dim_sample);
}
void mlx5e_trigger_irq(struct mlx5e_icosq *sq)
@@ -165,7 +165,8 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
if (unlikely(!budget))
goto out;
- busy |= mlx5e_poll_xdpsq_cq(&c->xdpsq.cq);
+ if (c->xdpsq)
+ busy |= mlx5e_poll_xdpsq_cq(&c->xdpsq->cq);
if (c->xdp)
busy |= mlx5e_poll_xdpsq_cq(&c->rq_xdpsq.cq);
@@ -236,7 +237,8 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
mlx5e_cq_arm(&rq->cq);
mlx5e_cq_arm(&c->icosq.cq);
mlx5e_cq_arm(&c->async_icosq.cq);
- mlx5e_cq_arm(&c->xdpsq.cq);
+ if (c->xdpsq)
+ mlx5e_cq_arm(&c->xdpsq->cq);
if (xsk_open) {
mlx5e_handle_rx_dim(xskrq);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index 68cb86b37e56..2b229b6226c6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -114,14 +114,10 @@ static int mlx5_eq_comp_int(struct notifier_block *nb,
struct mlx5_eq *eq = &eq_comp->core;
struct mlx5_eqe *eqe;
int num_eqes = 0;
- u32 cqn = -1;
- eqe = next_eqe_sw(eq);
- if (!eqe)
- goto out;
-
- do {
+ while ((eqe = next_eqe_sw(eq))) {
struct mlx5_core_cq *cq;
+ u32 cqn;
/* Make sure we read EQ entry contents after we've
* checked the ownership bit.
@@ -142,14 +138,12 @@ static int mlx5_eq_comp_int(struct notifier_block *nb,
++eq->cons_index;
- } while ((++num_eqes < MLX5_EQ_POLLING_BUDGET) && (eqe = next_eqe_sw(eq)));
+ if (++num_eqes >= MLX5_EQ_POLLING_BUDGET)
+ break;
+ }
-out:
eq_update_ci(eq, 1);
- if (cqn != -1)
- tasklet_schedule(&eq_comp->tasklet_ctx.task);
-
return 0;
}
@@ -215,11 +209,7 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
recovery = action == ASYNC_EQ_RECOVER;
mlx5_eq_async_int_lock(eq_async, recovery, &flags);
- eqe = next_eqe_sw(eq);
- if (!eqe)
- goto out;
-
- do {
+ while ((eqe = next_eqe_sw(eq))) {
/*
* Make sure we read EQ entry contents after we've
* checked the ownership bit.
@@ -231,9 +221,10 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
++eq->cons_index;
- } while ((++num_eqes < MLX5_EQ_POLLING_BUDGET) && (eqe = next_eqe_sw(eq)));
+ if (++num_eqes >= MLX5_EQ_POLLING_BUDGET)
+ break;
+ }
-out:
eq_update_ci(eq, 1);
mlx5_eq_async_int_unlock(eq_async, recovery, &flags);
@@ -810,15 +801,8 @@ EXPORT_SYMBOL(mlx5_eq_get_eqe);
void mlx5_eq_update_ci(struct mlx5_eq *eq, u32 cc, bool arm)
{
- __be32 __iomem *addr = eq->doorbell + (arm ? 0 : 2);
- u32 val;
-
eq->cons_index += cc;
- val = (eq->cons_index & 0xffffff) | (eq->eqn << 24);
-
- __raw_writel((__force u32)cpu_to_be32(val), addr);
- /* We still want ordering, just not swabbing, so add a barrier */
- wmb();
+ eq_update_ci(eq, arm);
}
EXPORT_SYMBOL(mlx5_eq_update_ci);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
index f8869c9b6802..982fe3714683 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
@@ -187,7 +187,7 @@ rate_err:
return err;
}
-void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
+void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport)
{
struct mlx5_devlink_port *dl_port;
@@ -195,7 +195,7 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, struct
return;
dl_port = vport->dl_port;
- mlx5_esw_qos_vport_update_group(esw, vport, NULL, NULL);
+ mlx5_esw_qos_vport_update_parent(vport, NULL, NULL);
devl_rate_leaf_destroy(&dl_port->dl_port);
devl_port_unregister(&dl_port->dl_port);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/qos_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/qos_tracepoint.h
index 1ce332f21ebe..43550a416a6f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/qos_tracepoint.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/qos_tracepoint.h
@@ -9,107 +9,111 @@
#include <linux/tracepoint.h>
#include "eswitch.h"
+#include "qos.h"
TRACE_EVENT(mlx5_esw_vport_qos_destroy,
- TP_PROTO(const struct mlx5_vport *vport),
- TP_ARGS(vport),
- TP_STRUCT__entry(__string(devname, dev_name(vport->dev->device))
+ TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport),
+ TP_ARGS(dev, vport),
+ TP_STRUCT__entry(__string(devname, dev_name(dev->device))
__field(unsigned short, vport_id)
- __field(unsigned int, tsar_ix)
+ __field(unsigned int, sched_elem_ix)
),
TP_fast_assign(__assign_str(devname);
__entry->vport_id = vport->vport;
- __entry->tsar_ix = vport->qos.esw_tsar_ix;
+ __entry->sched_elem_ix = mlx5_esw_qos_vport_get_sched_elem_ix(vport);
),
- TP_printk("(%s) vport=%hu tsar_ix=%u\n",
- __get_str(devname), __entry->vport_id, __entry->tsar_ix
+ TP_printk("(%s) vport=%hu sched_elem_ix=%u\n",
+ __get_str(devname), __entry->vport_id, __entry->sched_elem_ix
)
);
DECLARE_EVENT_CLASS(mlx5_esw_vport_qos_template,
- TP_PROTO(const struct mlx5_vport *vport, u32 bw_share, u32 max_rate),
- TP_ARGS(vport, bw_share, max_rate),
- TP_STRUCT__entry(__string(devname, dev_name(vport->dev->device))
+ TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport,
+ u32 bw_share, u32 max_rate),
+ TP_ARGS(dev, vport, bw_share, max_rate),
+ TP_STRUCT__entry(__string(devname, dev_name(dev->device))
__field(unsigned short, vport_id)
- __field(unsigned int, tsar_ix)
+ __field(unsigned int, sched_elem_ix)
__field(unsigned int, bw_share)
__field(unsigned int, max_rate)
- __field(void *, group)
+ __field(void *, parent)
),
TP_fast_assign(__assign_str(devname);
__entry->vport_id = vport->vport;
- __entry->tsar_ix = vport->qos.esw_tsar_ix;
+ __entry->sched_elem_ix = mlx5_esw_qos_vport_get_sched_elem_ix(vport);
__entry->bw_share = bw_share;
__entry->max_rate = max_rate;
- __entry->group = vport->qos.group;
+ __entry->parent = mlx5_esw_qos_vport_get_parent(vport);
),
- TP_printk("(%s) vport=%hu tsar_ix=%u bw_share=%u, max_rate=%u group=%p\n",
- __get_str(devname), __entry->vport_id, __entry->tsar_ix,
- __entry->bw_share, __entry->max_rate, __entry->group
+ TP_printk("(%s) vport=%hu sched_elem_ix=%u bw_share=%u, max_rate=%u parent=%p\n",
+ __get_str(devname), __entry->vport_id, __entry->sched_elem_ix,
+ __entry->bw_share, __entry->max_rate, __entry->parent
)
);
DEFINE_EVENT(mlx5_esw_vport_qos_template, mlx5_esw_vport_qos_create,
- TP_PROTO(const struct mlx5_vport *vport, u32 bw_share, u32 max_rate),
- TP_ARGS(vport, bw_share, max_rate)
+ TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport,
+ u32 bw_share, u32 max_rate),
+ TP_ARGS(dev, vport, bw_share, max_rate)
);
DEFINE_EVENT(mlx5_esw_vport_qos_template, mlx5_esw_vport_qos_config,
- TP_PROTO(const struct mlx5_vport *vport, u32 bw_share, u32 max_rate),
- TP_ARGS(vport, bw_share, max_rate)
+ TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport,
+ u32 bw_share, u32 max_rate),
+ TP_ARGS(dev, vport, bw_share, max_rate)
);
-DECLARE_EVENT_CLASS(mlx5_esw_group_qos_template,
+DECLARE_EVENT_CLASS(mlx5_esw_node_qos_template,
TP_PROTO(const struct mlx5_core_dev *dev,
- const struct mlx5_esw_rate_group *group,
+ const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix),
- TP_ARGS(dev, group, tsar_ix),
+ TP_ARGS(dev, node, tsar_ix),
TP_STRUCT__entry(__string(devname, dev_name(dev->device))
- __field(const void *, group)
+ __field(const void *, node)
__field(unsigned int, tsar_ix)
),
TP_fast_assign(__assign_str(devname);
- __entry->group = group;
+ __entry->node = node;
__entry->tsar_ix = tsar_ix;
),
- TP_printk("(%s) group=%p tsar_ix=%u\n",
- __get_str(devname), __entry->group, __entry->tsar_ix
+ TP_printk("(%s) node=%p tsar_ix=%u\n",
+ __get_str(devname), __entry->node, __entry->tsar_ix
)
);
-DEFINE_EVENT(mlx5_esw_group_qos_template, mlx5_esw_group_qos_create,
+DEFINE_EVENT(mlx5_esw_node_qos_template, mlx5_esw_node_qos_create,
TP_PROTO(const struct mlx5_core_dev *dev,
- const struct mlx5_esw_rate_group *group,
+ const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix),
- TP_ARGS(dev, group, tsar_ix)
+ TP_ARGS(dev, node, tsar_ix)
);
-DEFINE_EVENT(mlx5_esw_group_qos_template, mlx5_esw_group_qos_destroy,
+DEFINE_EVENT(mlx5_esw_node_qos_template, mlx5_esw_node_qos_destroy,
TP_PROTO(const struct mlx5_core_dev *dev,
- const struct mlx5_esw_rate_group *group,
+ const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix),
- TP_ARGS(dev, group, tsar_ix)
+ TP_ARGS(dev, node, tsar_ix)
);
-TRACE_EVENT(mlx5_esw_group_qos_config,
+TRACE_EVENT(mlx5_esw_node_qos_config,
TP_PROTO(const struct mlx5_core_dev *dev,
- const struct mlx5_esw_rate_group *group,
+ const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix, u32 bw_share, u32 max_rate),
- TP_ARGS(dev, group, tsar_ix, bw_share, max_rate),
+ TP_ARGS(dev, node, tsar_ix, bw_share, max_rate),
TP_STRUCT__entry(__string(devname, dev_name(dev->device))
- __field(const void *, group)
+ __field(const void *, node)
__field(unsigned int, tsar_ix)
__field(unsigned int, bw_share)
__field(unsigned int, max_rate)
),
TP_fast_assign(__assign_str(devname);
- __entry->group = group;
+ __entry->node = node;
__entry->tsar_ix = tsar_ix;
__entry->bw_share = bw_share;
__entry->max_rate = max_rate;
),
- TP_printk("(%s) group=%p tsar_ix=%u bw_share=%u max_rate=%u\n",
- __get_str(devname), __entry->group, __entry->tsar_ix,
+ TP_printk("(%s) node=%p tsar_ix=%u bw_share=%u max_rate=%u\n",
+ __get_str(devname), __entry->node, __entry->tsar_ix,
__entry->bw_share, __entry->max_rate
)
);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
index 8587cd572da5..45183de424f3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
@@ -176,20 +176,10 @@ static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
static int esw_create_legacy_table(struct mlx5_eswitch *esw)
{
- int err;
-
memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
atomic64_set(&esw->user_count, 0);
- err = esw_create_legacy_vepa_table(esw);
- if (err)
- return err;
-
- err = esw_create_legacy_fdb_table(esw);
- if (err)
- esw_destroy_legacy_vepa_table(esw);
-
- return err;
+ return esw_create_legacy_fdb_table(esw);
}
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
@@ -259,15 +249,22 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
if (!setting) {
esw_cleanup_vepa_rules(esw);
+ esw_destroy_legacy_vepa_table(esw);
return 0;
}
if (esw->fdb_table.legacy.vepa_uplink_rule)
return 0;
+ err = esw_create_legacy_vepa_table(esw);
+ if (err)
+ return err;
+
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
+ if (!spec) {
+ err = -ENOMEM;
+ goto out;
+ }
/* Uplink rule forward uplink traffic to FDB */
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
@@ -303,8 +300,10 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
out:
kvfree(spec);
- if (err)
+ if (err) {
esw_cleanup_vepa_rules(esw);
+ esw_destroy_legacy_vepa_table(esw);
+ }
return err;
}
@@ -513,15 +512,11 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
u32 max_rate, u32 min_rate)
{
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
- int err;
if (!mlx5_esw_allowed(esw))
return -EPERM;
if (IS_ERR(evport))
return PTR_ERR(evport);
- mutex_lock(&esw->state_lock);
- err = mlx5_esw_qos_set_vport_rate(esw, evport, max_rate, min_rate);
- mutex_unlock(&esw->state_lock);
- return err;
+ return mlx5_esw_qos_set_vport_rate(evport, max_rate, min_rate);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
index 02a3563f51ad..8b7c843446e1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
@@ -11,497 +11,427 @@
/* Minimum supported BW share value by the HW is 1 Mbit/sec */
#define MLX5_MIN_BW_SHARE 1
-#define MLX5_RATE_TO_BW_SHARE(rate, divider, limit) \
- min_t(u32, max_t(u32, DIV_ROUND_UP(rate, divider), MLX5_MIN_BW_SHARE), limit)
-
-struct mlx5_esw_rate_group {
- u32 tsar_ix;
- u32 max_rate;
- u32 min_rate;
- u32 bw_share;
- struct list_head list;
+/* Holds rate nodes associated with an E-Switch. */
+struct mlx5_qos_domain {
+ /* Serializes access to all qos changes in the qos domain. */
+ struct mutex lock;
+ /* List of all mlx5_esw_sched_nodes. */
+ struct list_head nodes;
};
-static int esw_qos_tsar_config(struct mlx5_core_dev *dev, u32 *sched_ctx,
- u32 tsar_ix, u32 max_rate, u32 bw_share)
+static void esw_qos_lock(struct mlx5_eswitch *esw)
{
- u32 bitmask = 0;
-
- if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
- return -EOPNOTSUPP;
+ mutex_lock(&esw->qos.domain->lock);
+}
- MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate);
- MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
- bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
- bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
+static void esw_qos_unlock(struct mlx5_eswitch *esw)
+{
+ mutex_unlock(&esw->qos.domain->lock);
+}
- return mlx5_modify_scheduling_element_cmd(dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- sched_ctx,
- tsar_ix,
- bitmask);
+static void esw_assert_qos_lock_held(struct mlx5_eswitch *esw)
+{
+ lockdep_assert_held(&esw->qos.domain->lock);
}
-static int esw_qos_group_config(struct mlx5_eswitch *esw, struct mlx5_esw_rate_group *group,
- u32 max_rate, u32 bw_share, struct netlink_ext_ack *extack)
+static struct mlx5_qos_domain *esw_qos_domain_alloc(void)
{
- u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
- struct mlx5_core_dev *dev = esw->dev;
- int err;
+ struct mlx5_qos_domain *qos_domain;
- err = esw_qos_tsar_config(dev, sched_ctx,
- group->tsar_ix,
- max_rate, bw_share);
- if (err)
- NL_SET_ERR_MSG_MOD(extack, "E-Switch modify group TSAR element failed");
+ qos_domain = kzalloc(sizeof(*qos_domain), GFP_KERNEL);
+ if (!qos_domain)
+ return NULL;
- trace_mlx5_esw_group_qos_config(dev, group, group->tsar_ix, bw_share, max_rate);
+ mutex_init(&qos_domain->lock);
+ INIT_LIST_HEAD(&qos_domain->nodes);
- return err;
+ return qos_domain;
}
-static int esw_qos_vport_config(struct mlx5_eswitch *esw,
- struct mlx5_vport *vport,
- u32 max_rate, u32 bw_share,
- struct netlink_ext_ack *extack)
+static int esw_qos_domain_init(struct mlx5_eswitch *esw)
{
- u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
- struct mlx5_core_dev *dev = esw->dev;
- int err;
-
- if (!vport->qos.enabled)
- return -EIO;
-
- err = esw_qos_tsar_config(dev, sched_ctx, vport->qos.esw_tsar_ix,
- max_rate, bw_share);
- if (err) {
- esw_warn(esw->dev,
- "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
- vport->vport, err);
- NL_SET_ERR_MSG_MOD(extack, "E-Switch modify TSAR vport element failed");
- return err;
- }
+ esw->qos.domain = esw_qos_domain_alloc();
- trace_mlx5_esw_vport_qos_config(vport, bw_share, max_rate);
-
- return 0;
+ return esw->qos.domain ? 0 : -ENOMEM;
}
-static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw,
- struct mlx5_esw_rate_group *group,
- bool group_level)
+static void esw_qos_domain_release(struct mlx5_eswitch *esw)
{
- u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
- struct mlx5_vport *evport;
- u32 max_guarantee = 0;
- unsigned long i;
+ kfree(esw->qos.domain);
+ esw->qos.domain = NULL;
+}
- if (group_level) {
- struct mlx5_esw_rate_group *group;
+enum sched_node_type {
+ SCHED_NODE_TYPE_VPORTS_TSAR,
+ SCHED_NODE_TYPE_VPORT,
+};
- list_for_each_entry(group, &esw->qos.groups, list) {
- if (group->min_rate < max_guarantee)
- continue;
- max_guarantee = group->min_rate;
- }
- } else {
- mlx5_esw_for_each_vport(esw, i, evport) {
- if (!evport->enabled || !evport->qos.enabled ||
- evport->qos.group != group || evport->qos.min_rate < max_guarantee)
- continue;
- max_guarantee = evport->qos.min_rate;
- }
- }
+static const char * const sched_node_type_str[] = {
+ [SCHED_NODE_TYPE_VPORTS_TSAR] = "vports TSAR",
+ [SCHED_NODE_TYPE_VPORT] = "vport",
+};
- if (max_guarantee)
- return max_t(u32, max_guarantee / fw_max_bw_share, 1);
+struct mlx5_esw_sched_node {
+ u32 ix;
+ /* Bandwidth parameters. */
+ u32 max_rate;
+ u32 min_rate;
+ /* A computed value indicating relative min_rate between node's children. */
+ u32 bw_share;
+ /* The parent node in the rate hierarchy. */
+ struct mlx5_esw_sched_node *parent;
+ /* Entry in the parent node's children list. */
+ struct list_head entry;
+ /* The type of this node in the rate hierarchy. */
+ enum sched_node_type type;
+ /* The eswitch this node belongs to. */
+ struct mlx5_eswitch *esw;
+ /* The children nodes of this node, empty list for leaf nodes. */
+ struct list_head children;
+ /* Valid only if this node is associated with a vport. */
+ struct mlx5_vport *vport;
+};
- /* If vports min rate divider is 0 but their group has bw_share configured, then
- * need to set bw_share for vports to minimal value.
- */
- if (!group_level && !max_guarantee && group && group->bw_share)
- return 1;
- return 0;
+static void
+esw_qos_node_set_parent(struct mlx5_esw_sched_node *node, struct mlx5_esw_sched_node *parent)
+{
+ list_del_init(&node->entry);
+ node->parent = parent;
+ list_add_tail(&node->entry, &parent->children);
+ node->esw = parent->esw;
}
-static u32 esw_qos_calc_bw_share(u32 min_rate, u32 divider, u32 fw_max)
+void mlx5_esw_qos_vport_qos_free(struct mlx5_vport *vport)
{
- if (divider)
- return MLX5_RATE_TO_BW_SHARE(min_rate, divider, fw_max);
-
- return 0;
+ kfree(vport->qos.sched_node);
+ memset(&vport->qos, 0, sizeof(vport->qos));
}
-static int esw_qos_normalize_vports_min_rate(struct mlx5_eswitch *esw,
- struct mlx5_esw_rate_group *group,
- struct netlink_ext_ack *extack)
+u32 mlx5_esw_qos_vport_get_sched_elem_ix(const struct mlx5_vport *vport)
{
- u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
- u32 divider = esw_qos_calculate_min_rate_divider(esw, group, false);
- struct mlx5_vport *evport;
- unsigned long i;
- u32 bw_share;
- int err;
+ if (!vport->qos.sched_node)
+ return 0;
- mlx5_esw_for_each_vport(esw, i, evport) {
- if (!evport->enabled || !evport->qos.enabled || evport->qos.group != group)
- continue;
- bw_share = esw_qos_calc_bw_share(evport->qos.min_rate, divider, fw_max_bw_share);
+ return vport->qos.sched_node->ix;
+}
- if (bw_share == evport->qos.bw_share)
- continue;
+struct mlx5_esw_sched_node *
+mlx5_esw_qos_vport_get_parent(const struct mlx5_vport *vport)
+{
+ if (!vport->qos.sched_node)
+ return NULL;
- err = esw_qos_vport_config(esw, evport, evport->qos.max_rate, bw_share, extack);
- if (err)
- return err;
+ return vport->qos.sched_node->parent;
+}
- evport->qos.bw_share = bw_share;
+static void esw_qos_sched_elem_warn(struct mlx5_esw_sched_node *node, int err, const char *op)
+{
+ if (node->vport) {
+ esw_warn(node->esw->dev,
+ "E-Switch %s %s scheduling element failed (vport=%d,err=%d)\n",
+ op, sched_node_type_str[node->type], node->vport->vport, err);
+ return;
}
- return 0;
+ esw_warn(node->esw->dev,
+ "E-Switch %s %s scheduling element failed (err=%d)\n",
+ op, sched_node_type_str[node->type], err);
}
-static int esw_qos_normalize_groups_min_rate(struct mlx5_eswitch *esw, u32 divider,
+static int esw_qos_node_create_sched_element(struct mlx5_esw_sched_node *node, void *ctx,
struct netlink_ext_ack *extack)
{
- u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
- struct mlx5_esw_rate_group *group;
- u32 bw_share;
int err;
- list_for_each_entry(group, &esw->qos.groups, list) {
- bw_share = esw_qos_calc_bw_share(group->min_rate, divider, fw_max_bw_share);
-
- if (bw_share == group->bw_share)
- continue;
-
- err = esw_qos_group_config(esw, group, group->max_rate, bw_share, extack);
- if (err)
- return err;
-
- group->bw_share = bw_share;
-
- /* All the group's vports need to be set with default bw_share
- * to enable them with QOS
- */
- err = esw_qos_normalize_vports_min_rate(esw, group, extack);
-
- if (err)
- return err;
+ err = mlx5_create_scheduling_element_cmd(node->esw->dev, SCHEDULING_HIERARCHY_E_SWITCH, ctx,
+ &node->ix);
+ if (err) {
+ esw_qos_sched_elem_warn(node, err, "create");
+ NL_SET_ERR_MSG_MOD(extack, "E-Switch create scheduling element failed");
}
- return 0;
+ return err;
}
-static int esw_qos_set_vport_min_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport,
- u32 min_rate, struct netlink_ext_ack *extack)
+static int esw_qos_node_destroy_sched_element(struct mlx5_esw_sched_node *node,
+ struct netlink_ext_ack *extack)
{
- u32 fw_max_bw_share, previous_min_rate;
- bool min_rate_supported;
int err;
- lockdep_assert_held(&esw->state_lock);
- fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
- min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
- fw_max_bw_share >= MLX5_MIN_BW_SHARE;
- if (min_rate && !min_rate_supported)
- return -EOPNOTSUPP;
- if (min_rate == evport->qos.min_rate)
- return 0;
-
- previous_min_rate = evport->qos.min_rate;
- evport->qos.min_rate = min_rate;
- err = esw_qos_normalize_vports_min_rate(esw, evport->qos.group, extack);
- if (err)
- evport->qos.min_rate = previous_min_rate;
+ err = mlx5_destroy_scheduling_element_cmd(node->esw->dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ node->ix);
+ if (err) {
+ esw_qos_sched_elem_warn(node, err, "destroy");
+ NL_SET_ERR_MSG_MOD(extack, "E-Switch destroying scheduling element failed.");
+ }
return err;
}
-static int esw_qos_set_vport_max_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport,
- u32 max_rate, struct netlink_ext_ack *extack)
+static int esw_qos_sched_elem_config(struct mlx5_esw_sched_node *node, u32 max_rate, u32 bw_share,
+ struct netlink_ext_ack *extack)
{
- u32 act_max_rate = max_rate;
- bool max_rate_supported;
+ u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
+ struct mlx5_core_dev *dev = node->esw->dev;
+ u32 bitmask = 0;
int err;
- lockdep_assert_held(&esw->state_lock);
- max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
+ if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
+ return -EOPNOTSUPP;
- if (max_rate && !max_rate_supported)
+ if (bw_share && (!MLX5_CAP_QOS(dev, esw_bw_share) ||
+ MLX5_CAP_QOS(dev, max_tsar_bw_share) < MLX5_MIN_BW_SHARE))
return -EOPNOTSUPP;
- if (max_rate == evport->qos.max_rate)
+
+ if (node->max_rate == max_rate && node->bw_share == bw_share)
return 0;
- /* If parent group has rate limit need to set to group
- * value when new max rate is 0.
- */
- if (evport->qos.group && !max_rate)
- act_max_rate = evport->qos.group->max_rate;
+ if (node->max_rate != max_rate) {
+ MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate);
+ bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
+ }
+ if (node->bw_share != bw_share) {
+ MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
+ bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
+ }
+
+ err = mlx5_modify_scheduling_element_cmd(dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ sched_ctx,
+ node->ix,
+ bitmask);
+ if (err) {
+ esw_qos_sched_elem_warn(node, err, "modify");
+ NL_SET_ERR_MSG_MOD(extack, "E-Switch modify scheduling element failed");
- err = esw_qos_vport_config(esw, evport, act_max_rate, evport->qos.bw_share, extack);
+ return err;
+ }
- if (!err)
- evport->qos.max_rate = max_rate;
+ node->max_rate = max_rate;
+ node->bw_share = bw_share;
+ if (node->type == SCHED_NODE_TYPE_VPORTS_TSAR)
+ trace_mlx5_esw_node_qos_config(dev, node, node->ix, bw_share, max_rate);
+ else if (node->type == SCHED_NODE_TYPE_VPORT)
+ trace_mlx5_esw_vport_qos_config(dev, node->vport, bw_share, max_rate);
- return err;
+ return 0;
}
-static int esw_qos_set_group_min_rate(struct mlx5_eswitch *esw, struct mlx5_esw_rate_group *group,
- u32 min_rate, struct netlink_ext_ack *extack)
+static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw,
+ struct mlx5_esw_sched_node *parent)
{
+ struct list_head *nodes = parent ? &parent->children : &esw->qos.domain->nodes;
u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
- struct mlx5_core_dev *dev = esw->dev;
- u32 previous_min_rate, divider;
- int err;
+ struct mlx5_esw_sched_node *node;
+ u32 max_guarantee = 0;
- if (!(MLX5_CAP_QOS(dev, esw_bw_share) && fw_max_bw_share >= MLX5_MIN_BW_SHARE))
- return -EOPNOTSUPP;
+ /* Find max min_rate across all nodes.
+ * This will correspond to fw_max_bw_share in the final bw_share calculation.
+ */
+ list_for_each_entry(node, nodes, entry) {
+ if (node->esw == esw && node->ix != esw->qos.root_tsar_ix &&
+ node->min_rate > max_guarantee)
+ max_guarantee = node->min_rate;
+ }
- if (min_rate == group->min_rate)
- return 0;
+ if (max_guarantee)
+ return max_t(u32, max_guarantee / fw_max_bw_share, 1);
- previous_min_rate = group->min_rate;
- group->min_rate = min_rate;
- divider = esw_qos_calculate_min_rate_divider(esw, group, true);
- err = esw_qos_normalize_groups_min_rate(esw, divider, extack);
- if (err) {
- group->min_rate = previous_min_rate;
- NL_SET_ERR_MSG_MOD(extack, "E-Switch group min rate setting failed");
+ /* If nodes max min_rate divider is 0 but their parent has bw_share
+ * configured, then set bw_share for nodes to minimal value.
+ */
- /* Attempt restoring previous configuration */
- divider = esw_qos_calculate_min_rate_divider(esw, group, true);
- if (esw_qos_normalize_groups_min_rate(esw, divider, extack))
- NL_SET_ERR_MSG_MOD(extack, "E-Switch BW share restore failed");
- }
+ if (parent && parent->bw_share)
+ return 1;
- return err;
+ /* If the node nodes has min_rate configured, a divider of 0 sets all
+ * nodes' bw_share to 0, effectively disabling min guarantees.
+ */
+ return 0;
}
-static int esw_qos_set_group_max_rate(struct mlx5_eswitch *esw,
- struct mlx5_esw_rate_group *group,
- u32 max_rate, struct netlink_ext_ack *extack)
+static u32 esw_qos_calc_bw_share(u32 min_rate, u32 divider, u32 fw_max)
{
- struct mlx5_vport *vport;
- unsigned long i;
- int err;
-
- if (group->max_rate == max_rate)
+ if (!divider)
return 0;
+ return min_t(u32, max_t(u32, DIV_ROUND_UP(min_rate, divider), MLX5_MIN_BW_SHARE), fw_max);
+}
- err = esw_qos_group_config(esw, group, max_rate, group->bw_share, extack);
- if (err)
- return err;
+static void esw_qos_update_sched_node_bw_share(struct mlx5_esw_sched_node *node,
+ u32 divider,
+ struct netlink_ext_ack *extack)
+{
+ u32 fw_max_bw_share = MLX5_CAP_QOS(node->esw->dev, max_tsar_bw_share);
+ u32 bw_share;
- group->max_rate = max_rate;
+ bw_share = esw_qos_calc_bw_share(node->min_rate, divider, fw_max_bw_share);
- /* Any unlimited vports in the group should be set
- * with the value of the group.
- */
- mlx5_esw_for_each_vport(esw, i, vport) {
- if (!vport->enabled || !vport->qos.enabled ||
- vport->qos.group != group || vport->qos.max_rate)
+ esw_qos_sched_elem_config(node, node->max_rate, bw_share, extack);
+}
+
+static void esw_qos_normalize_min_rate(struct mlx5_eswitch *esw,
+ struct mlx5_esw_sched_node *parent,
+ struct netlink_ext_ack *extack)
+{
+ struct list_head *nodes = parent ? &parent->children : &esw->qos.domain->nodes;
+ u32 divider = esw_qos_calculate_min_rate_divider(esw, parent);
+ struct mlx5_esw_sched_node *node;
+
+ list_for_each_entry(node, nodes, entry) {
+ if (node->esw != esw || node->ix == esw->qos.root_tsar_ix)
continue;
- err = esw_qos_vport_config(esw, vport, max_rate, vport->qos.bw_share, extack);
- if (err)
- NL_SET_ERR_MSG_MOD(extack,
- "E-Switch vport implicit rate limit setting failed");
- }
+ esw_qos_update_sched_node_bw_share(node, divider, extack);
- return err;
-}
+ if (list_empty(&node->children))
+ continue;
-static bool esw_qos_element_type_supported(struct mlx5_core_dev *dev, int type)
-{
- switch (type) {
- case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR:
- return MLX5_CAP_QOS(dev, esw_element_type) &
- ELEMENT_TYPE_CAP_MASK_TSAR;
- case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT:
- return MLX5_CAP_QOS(dev, esw_element_type) &
- ELEMENT_TYPE_CAP_MASK_VPORT;
- case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC:
- return MLX5_CAP_QOS(dev, esw_element_type) &
- ELEMENT_TYPE_CAP_MASK_VPORT_TC;
- case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC:
- return MLX5_CAP_QOS(dev, esw_element_type) &
- ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC;
+ esw_qos_normalize_min_rate(node->esw, node, extack);
}
- return false;
}
-static int esw_qos_vport_create_sched_element(struct mlx5_eswitch *esw,
- struct mlx5_vport *vport,
- u32 max_rate, u32 bw_share)
+static int esw_qos_set_node_min_rate(struct mlx5_esw_sched_node *node,
+ u32 min_rate, struct netlink_ext_ack *extack)
{
- u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
- struct mlx5_esw_rate_group *group = vport->qos.group;
- struct mlx5_core_dev *dev = esw->dev;
- u32 parent_tsar_ix;
- void *vport_elem;
- int err;
+ struct mlx5_eswitch *esw = node->esw;
- if (!esw_qos_element_type_supported(dev, SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT))
- return -EOPNOTSUPP;
+ if (min_rate == node->min_rate)
+ return 0;
- parent_tsar_ix = group ? group->tsar_ix : esw->qos.root_tsar_ix;
- MLX5_SET(scheduling_context, sched_ctx, element_type,
- SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
- vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes);
- MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
- MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_tsar_ix);
- MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate);
- MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
-
- err = mlx5_create_scheduling_element_cmd(dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- sched_ctx,
- &vport->qos.esw_tsar_ix);
- if (err) {
- esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
- vport->vport, err);
- return err;
- }
+ node->min_rate = min_rate;
+ esw_qos_normalize_min_rate(esw, node->parent, extack);
return 0;
}
-static int esw_qos_update_group_scheduling_element(struct mlx5_eswitch *esw,
- struct mlx5_vport *vport,
- struct mlx5_esw_rate_group *curr_group,
- struct mlx5_esw_rate_group *new_group,
- struct netlink_ext_ack *extack)
+static int esw_qos_create_node_sched_elem(struct mlx5_core_dev *dev, u32 parent_element_id,
+ u32 *tsar_ix)
{
- u32 max_rate;
- int err;
+ u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
+ void *attr;
+
+ if (!mlx5_qos_element_type_supported(dev,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR,
+ SCHEDULING_HIERARCHY_E_SWITCH) ||
+ !mlx5_qos_tsar_type_supported(dev,
+ TSAR_ELEMENT_TSAR_TYPE_DWRR,
+ SCHEDULING_HIERARCHY_E_SWITCH))
+ return -EOPNOTSUPP;
- err = mlx5_destroy_scheduling_element_cmd(esw->dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- vport->qos.esw_tsar_ix);
- if (err) {
- NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR vport element failed");
- return err;
- }
+ MLX5_SET(scheduling_context, tsar_ctx, element_type,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR);
+ MLX5_SET(scheduling_context, tsar_ctx, parent_element_id,
+ parent_element_id);
+ attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes);
+ MLX5_SET(tsar_element, attr, tsar_type, TSAR_ELEMENT_TSAR_TYPE_DWRR);
- vport->qos.group = new_group;
- max_rate = vport->qos.max_rate ? vport->qos.max_rate : new_group->max_rate;
+ return mlx5_create_scheduling_element_cmd(dev,
+ SCHEDULING_HIERARCHY_E_SWITCH,
+ tsar_ctx,
+ tsar_ix);
+}
- /* If vport is unlimited, we set the group's value.
- * Therefore, if the group is limited it will apply to
- * the vport as well and if not, vport will remain unlimited.
- */
- err = esw_qos_vport_create_sched_element(esw, vport, max_rate, vport->qos.bw_share);
- if (err) {
- NL_SET_ERR_MSG_MOD(extack, "E-Switch vport group set failed.");
- goto err_sched;
- }
+static int esw_qos_vport_create_sched_element(struct mlx5_esw_sched_node *vport_node,
+ struct netlink_ext_ack *extack)
+{
+ u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
+ struct mlx5_core_dev *dev = vport_node->esw->dev;
+ void *attr;
- return 0;
+ if (!mlx5_qos_element_type_supported(dev,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT,
+ SCHEDULING_HIERARCHY_E_SWITCH))
+ return -EOPNOTSUPP;
-err_sched:
- vport->qos.group = curr_group;
- max_rate = vport->qos.max_rate ? vport->qos.max_rate : curr_group->max_rate;
- if (esw_qos_vport_create_sched_element(esw, vport, max_rate, vport->qos.bw_share))
- esw_warn(esw->dev, "E-Switch vport group restore failed (vport=%d)\n",
- vport->vport);
+ MLX5_SET(scheduling_context, sched_ctx, element_type,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
+ attr = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes);
+ MLX5_SET(vport_element, attr, vport_number, vport_node->vport->vport);
+ MLX5_SET(scheduling_context, sched_ctx, parent_element_id, vport_node->parent->ix);
+ MLX5_SET(scheduling_context, sched_ctx, max_average_bw, vport_node->max_rate);
- return err;
+ return esw_qos_node_create_sched_element(vport_node, sched_ctx, extack);
}
-static int esw_qos_vport_update_group(struct mlx5_eswitch *esw,
- struct mlx5_vport *vport,
- struct mlx5_esw_rate_group *group,
- struct netlink_ext_ack *extack)
+static struct mlx5_esw_sched_node *
+__esw_qos_alloc_node(struct mlx5_eswitch *esw, u32 tsar_ix, enum sched_node_type type,
+ struct mlx5_esw_sched_node *parent)
{
- struct mlx5_esw_rate_group *new_group, *curr_group;
- int err;
+ struct list_head *parent_children;
+ struct mlx5_esw_sched_node *node;
- if (!vport->enabled)
- return -EINVAL;
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return NULL;
- curr_group = vport->qos.group;
- new_group = group ?: esw->qos.group0;
- if (curr_group == new_group)
- return 0;
+ node->esw = esw;
+ node->ix = tsar_ix;
+ node->type = type;
+ node->parent = parent;
+ INIT_LIST_HEAD(&node->children);
+ parent_children = parent ? &parent->children : &esw->qos.domain->nodes;
+ list_add_tail(&node->entry, parent_children);
- err = esw_qos_update_group_scheduling_element(esw, vport, curr_group, new_group, extack);
- if (err)
- return err;
+ return node;
+}
- /* Recalculate bw share weights of old and new groups */
- if (vport->qos.bw_share || new_group->bw_share) {
- esw_qos_normalize_vports_min_rate(esw, curr_group, extack);
- esw_qos_normalize_vports_min_rate(esw, new_group, extack);
- }
+static void __esw_qos_free_node(struct mlx5_esw_sched_node *node)
+{
+ list_del(&node->entry);
+ kfree(node);
+}
- return 0;
+static void esw_qos_destroy_node(struct mlx5_esw_sched_node *node, struct netlink_ext_ack *extack)
+{
+ esw_qos_node_destroy_sched_element(node, extack);
+ __esw_qos_free_node(node);
}
-static struct mlx5_esw_rate_group *
-__esw_qos_create_rate_group(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
+static struct mlx5_esw_sched_node *
+__esw_qos_create_vports_sched_node(struct mlx5_eswitch *esw, struct mlx5_esw_sched_node *parent,
+ struct netlink_ext_ack *extack)
{
- u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
- struct mlx5_esw_rate_group *group;
- __be32 *attr;
- u32 divider;
+ struct mlx5_esw_sched_node *node;
+ u32 tsar_ix;
int err;
- group = kzalloc(sizeof(*group), GFP_KERNEL);
- if (!group)
- return ERR_PTR(-ENOMEM);
-
- MLX5_SET(scheduling_context, tsar_ctx, element_type,
- SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR);
-
- attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes);
- *attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16);
-
- MLX5_SET(scheduling_context, tsar_ctx, parent_element_id,
- esw->qos.root_tsar_ix);
- err = mlx5_create_scheduling_element_cmd(esw->dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- tsar_ctx,
- &group->tsar_ix);
+ err = esw_qos_create_node_sched_elem(esw->dev, esw->qos.root_tsar_ix, &tsar_ix);
if (err) {
- NL_SET_ERR_MSG_MOD(extack, "E-Switch create TSAR for group failed");
- goto err_sched_elem;
+ NL_SET_ERR_MSG_MOD(extack, "E-Switch create TSAR for node failed");
+ return ERR_PTR(err);
}
- list_add_tail(&group->list, &esw->qos.groups);
-
- divider = esw_qos_calculate_min_rate_divider(esw, group, true);
- if (divider) {
- err = esw_qos_normalize_groups_min_rate(esw, divider, extack);
- if (err) {
- NL_SET_ERR_MSG_MOD(extack, "E-Switch groups normalization failed");
- goto err_min_rate;
- }
+ node = __esw_qos_alloc_node(esw, tsar_ix, SCHED_NODE_TYPE_VPORTS_TSAR, parent);
+ if (!node) {
+ NL_SET_ERR_MSG_MOD(extack, "E-Switch alloc node failed");
+ err = -ENOMEM;
+ goto err_alloc_node;
}
- trace_mlx5_esw_group_qos_create(esw->dev, group, group->tsar_ix);
- return group;
+ esw_qos_normalize_min_rate(esw, NULL, extack);
+ trace_mlx5_esw_node_qos_create(esw->dev, node, node->ix);
+
+ return node;
-err_min_rate:
- list_del(&group->list);
+err_alloc_node:
if (mlx5_destroy_scheduling_element_cmd(esw->dev,
SCHEDULING_HIERARCHY_E_SWITCH,
- group->tsar_ix))
- NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR for group failed");
-err_sched_elem:
- kfree(group);
+ tsar_ix))
+ NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR for node failed");
return ERR_PTR(err);
}
static int esw_qos_get(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack);
static void esw_qos_put(struct mlx5_eswitch *esw);
-static struct mlx5_esw_rate_group *
-esw_qos_create_rate_group(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
+static struct mlx5_esw_sched_node *
+esw_qos_create_vports_sched_node(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
{
- struct mlx5_esw_rate_group *group;
+ struct mlx5_esw_sched_node *node;
int err;
+ esw_assert_qos_lock_held(esw);
if (!MLX5_CAP_QOS(esw->dev, log_esw_max_sched_depth))
return ERR_PTR(-EOPNOTSUPP);
@@ -509,96 +439,58 @@ esw_qos_create_rate_group(struct mlx5_eswitch *esw, struct netlink_ext_ack *exta
if (err)
return ERR_PTR(err);
- group = __esw_qos_create_rate_group(esw, extack);
- if (IS_ERR(group))
+ node = __esw_qos_create_vports_sched_node(esw, NULL, extack);
+ if (IS_ERR(node))
esw_qos_put(esw);
- return group;
+ return node;
}
-static int __esw_qos_destroy_rate_group(struct mlx5_eswitch *esw,
- struct mlx5_esw_rate_group *group,
- struct netlink_ext_ack *extack)
+static void __esw_qos_destroy_node(struct mlx5_esw_sched_node *node, struct netlink_ext_ack *extack)
{
- u32 divider;
- int err;
-
- list_del(&group->list);
-
- divider = esw_qos_calculate_min_rate_divider(esw, NULL, true);
- err = esw_qos_normalize_groups_min_rate(esw, divider, extack);
- if (err)
- NL_SET_ERR_MSG_MOD(extack, "E-Switch groups' normalization failed");
+ struct mlx5_eswitch *esw = node->esw;
- err = mlx5_destroy_scheduling_element_cmd(esw->dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- group->tsar_ix);
- if (err)
- NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR_ID failed");
-
- trace_mlx5_esw_group_qos_destroy(esw->dev, group, group->tsar_ix);
-
- kfree(group);
-
- return err;
-}
-
-static int esw_qos_destroy_rate_group(struct mlx5_eswitch *esw,
- struct mlx5_esw_rate_group *group,
- struct netlink_ext_ack *extack)
-{
- int err;
-
- err = __esw_qos_destroy_rate_group(esw, group, extack);
- esw_qos_put(esw);
-
- return err;
+ trace_mlx5_esw_node_qos_destroy(esw->dev, node, node->ix);
+ esw_qos_destroy_node(node, extack);
+ esw_qos_normalize_min_rate(esw, NULL, extack);
}
static int esw_qos_create(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
{
- u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
struct mlx5_core_dev *dev = esw->dev;
- __be32 *attr;
int err;
if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
return -EOPNOTSUPP;
- if (!esw_qos_element_type_supported(dev, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR) ||
- !(MLX5_CAP_QOS(dev, esw_tsar_type) & TSAR_TYPE_CAP_MASK_DWRR))
- return -EOPNOTSUPP;
-
- MLX5_SET(scheduling_context, tsar_ctx, element_type,
- SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR);
-
- attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes);
- *attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16);
-
- err = mlx5_create_scheduling_element_cmd(dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- tsar_ctx,
- &esw->qos.root_tsar_ix);
+ err = esw_qos_create_node_sched_elem(esw->dev, 0, &esw->qos.root_tsar_ix);
if (err) {
esw_warn(dev, "E-Switch create root TSAR failed (%d)\n", err);
return err;
}
- INIT_LIST_HEAD(&esw->qos.groups);
if (MLX5_CAP_QOS(dev, log_esw_max_sched_depth)) {
- esw->qos.group0 = __esw_qos_create_rate_group(esw, extack);
- if (IS_ERR(esw->qos.group0)) {
- esw_warn(dev, "E-Switch create rate group 0 failed (%ld)\n",
- PTR_ERR(esw->qos.group0));
- err = PTR_ERR(esw->qos.group0);
- goto err_group0;
- }
+ esw->qos.node0 = __esw_qos_create_vports_sched_node(esw, NULL, extack);
+ } else {
+ /* The eswitch doesn't support scheduling nodes.
+ * Create a software-only node0 using the root TSAR to attach vport QoS to.
+ */
+ if (!__esw_qos_alloc_node(esw,
+ esw->qos.root_tsar_ix,
+ SCHED_NODE_TYPE_VPORTS_TSAR,
+ NULL))
+ esw->qos.node0 = ERR_PTR(-ENOMEM);
+ }
+ if (IS_ERR(esw->qos.node0)) {
+ err = PTR_ERR(esw->qos.node0);
+ esw_warn(dev, "E-Switch create rate node 0 failed (%d)\n", err);
+ goto err_node0;
}
refcount_set(&esw->qos.refcnt, 1);
return 0;
-err_group0:
+err_node0:
if (mlx5_destroy_scheduling_element_cmd(esw->dev, SCHEDULING_HIERARCHY_E_SWITCH,
esw->qos.root_tsar_ix))
esw_warn(esw->dev, "E-Switch destroy root TSAR failed.\n");
@@ -610,8 +502,11 @@ static void esw_qos_destroy(struct mlx5_eswitch *esw)
{
int err;
- if (esw->qos.group0)
- __esw_qos_destroy_rate_group(esw, esw->qos.group0, NULL);
+ if (esw->qos.node0->ix != esw->qos.root_tsar_ix)
+ __esw_qos_destroy_node(esw->qos.node0, NULL);
+ else
+ __esw_qos_free_node(esw->qos.node0);
+ esw->qos.node0 = NULL;
err = mlx5_destroy_scheduling_element_cmd(esw->dev,
SCHEDULING_HIERARCHY_E_SWITCH,
@@ -624,8 +519,7 @@ static int esw_qos_get(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
{
int err = 0;
- lockdep_assert_held(&esw->state_lock);
-
+ esw_assert_qos_lock_held(esw);
if (!refcount_inc_not_zero(&esw->qos.refcnt)) {
/* esw_qos_create() set refcount to 1 only on success.
* No need to decrement on failure.
@@ -638,77 +532,169 @@ static int esw_qos_get(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
static void esw_qos_put(struct mlx5_eswitch *esw)
{
- lockdep_assert_held(&esw->state_lock);
+ esw_assert_qos_lock_held(esw);
if (refcount_dec_and_test(&esw->qos.refcnt))
esw_qos_destroy(esw);
}
-static int esw_qos_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
- u32 max_rate, u32 bw_share, struct netlink_ext_ack *extack)
+static void esw_qos_vport_disable(struct mlx5_vport *vport, struct netlink_ext_ack *extack)
+{
+ struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
+ struct mlx5_esw_sched_node *parent = vport_node->parent;
+
+ esw_qos_node_destroy_sched_element(vport_node, extack);
+
+ vport_node->bw_share = 0;
+ list_del_init(&vport_node->entry);
+ esw_qos_normalize_min_rate(parent->esw, parent, extack);
+
+ trace_mlx5_esw_vport_qos_destroy(vport_node->esw->dev, vport);
+}
+
+static int esw_qos_vport_enable(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent,
+ struct netlink_ext_ack *extack)
{
int err;
- lockdep_assert_held(&esw->state_lock);
- if (vport->qos.enabled)
- return 0;
+ esw_assert_qos_lock_held(vport->dev->priv.eswitch);
+
+ esw_qos_node_set_parent(vport->qos.sched_node, parent);
+ err = esw_qos_vport_create_sched_element(vport->qos.sched_node, extack);
+ if (err)
+ return err;
+
+ esw_qos_normalize_min_rate(parent->esw, parent, extack);
+
+ return 0;
+}
+
+static int mlx5_esw_qos_vport_enable(struct mlx5_vport *vport, enum sched_node_type type,
+ struct mlx5_esw_sched_node *parent, u32 max_rate,
+ u32 min_rate, struct netlink_ext_ack *extack)
+{
+ struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
+ struct mlx5_esw_sched_node *sched_node;
+ int err;
+ esw_assert_qos_lock_held(esw);
err = esw_qos_get(esw, extack);
if (err)
return err;
- vport->qos.group = esw->qos.group0;
+ parent = parent ?: esw->qos.node0;
+ sched_node = __esw_qos_alloc_node(parent->esw, 0, type, parent);
+ if (!sched_node)
+ return -ENOMEM;
- err = esw_qos_vport_create_sched_element(esw, vport, max_rate, bw_share);
+ sched_node->max_rate = max_rate;
+ sched_node->min_rate = min_rate;
+ sched_node->vport = vport;
+ vport->qos.sched_node = sched_node;
+ err = esw_qos_vport_enable(vport, parent, extack);
if (err)
- goto err_out;
+ esw_qos_put(esw);
- vport->qos.enabled = true;
- trace_mlx5_esw_vport_qos_create(vport, bw_share, max_rate);
+ return err;
+}
- return 0;
+void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport)
+{
+ struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
+ struct mlx5_esw_sched_node *parent;
-err_out:
+ lockdep_assert_held(&esw->state_lock);
+ esw_qos_lock(esw);
+ if (!vport->qos.sched_node)
+ goto unlock;
+
+ parent = vport->qos.sched_node->parent;
+ WARN(parent != esw->qos.node0, "Disabling QoS on port before detaching it from node");
+
+ esw_qos_vport_disable(vport, NULL);
+ mlx5_esw_qos_vport_qos_free(vport);
esw_qos_put(esw);
+unlock:
+ esw_qos_unlock(esw);
+}
- return err;
+static int mlx5_esw_qos_set_vport_max_rate(struct mlx5_vport *vport, u32 max_rate,
+ struct netlink_ext_ack *extack)
+{
+ struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
+
+ esw_assert_qos_lock_held(vport->dev->priv.eswitch);
+
+ if (!vport_node)
+ return mlx5_esw_qos_vport_enable(vport, SCHED_NODE_TYPE_VPORT, NULL, max_rate, 0,
+ extack);
+ else
+ return esw_qos_sched_elem_config(vport_node, max_rate, vport_node->bw_share,
+ extack);
}
-void mlx5_esw_qos_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
+static int mlx5_esw_qos_set_vport_min_rate(struct mlx5_vport *vport, u32 min_rate,
+ struct netlink_ext_ack *extack)
{
- int err;
+ struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
- lockdep_assert_held(&esw->state_lock);
- if (!vport->qos.enabled)
- return;
- WARN(vport->qos.group && vport->qos.group != esw->qos.group0,
- "Disabling QoS on port before detaching it from group");
+ esw_assert_qos_lock_held(vport->dev->priv.eswitch);
- err = mlx5_destroy_scheduling_element_cmd(esw->dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- vport->qos.esw_tsar_ix);
- if (err)
- esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
- vport->vport, err);
+ if (!vport_node)
+ return mlx5_esw_qos_vport_enable(vport, SCHED_NODE_TYPE_VPORT, NULL, 0, min_rate,
+ extack);
+ else
+ return esw_qos_set_node_min_rate(vport_node, min_rate, extack);
+}
- memset(&vport->qos, 0, sizeof(vport->qos));
- trace_mlx5_esw_vport_qos_destroy(vport);
+int mlx5_esw_qos_set_vport_rate(struct mlx5_vport *vport, u32 max_rate, u32 min_rate)
+{
+ struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
+ int err;
- esw_qos_put(esw);
+ esw_qos_lock(esw);
+ err = mlx5_esw_qos_set_vport_min_rate(vport, min_rate, NULL);
+ if (!err)
+ err = mlx5_esw_qos_set_vport_max_rate(vport, max_rate, NULL);
+ esw_qos_unlock(esw);
+ return err;
+}
+
+bool mlx5_esw_qos_get_vport_rate(struct mlx5_vport *vport, u32 *max_rate, u32 *min_rate)
+{
+ struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
+ bool enabled;
+
+ esw_qos_lock(esw);
+ enabled = !!vport->qos.sched_node;
+ if (enabled) {
+ *max_rate = vport->qos.sched_node->max_rate;
+ *min_rate = vport->qos.sched_node->min_rate;
+ }
+ esw_qos_unlock(esw);
+ return enabled;
}
-int mlx5_esw_qos_set_vport_rate(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
- u32 max_rate, u32 min_rate)
+static int esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent,
+ struct netlink_ext_ack *extack)
{
+ struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
+ struct mlx5_esw_sched_node *curr_parent;
int err;
- lockdep_assert_held(&esw->state_lock);
- err = esw_qos_vport_enable(esw, vport, 0, 0, NULL);
- if (err)
- return err;
+ esw_assert_qos_lock_held(esw);
+ curr_parent = vport->qos.sched_node->parent;
+ parent = parent ?: esw->qos.node0;
+ if (curr_parent == parent)
+ return 0;
- err = esw_qos_set_vport_min_rate(esw, vport, min_rate, NULL);
- if (!err)
- err = esw_qos_set_vport_max_rate(esw, vport, max_rate, NULL);
+ esw_qos_vport_disable(vport, extack);
+
+ err = esw_qos_vport_enable(vport, parent, extack);
+ if (err) {
+ if (esw_qos_vport_enable(vport, curr_parent, NULL))
+ esw_warn(parent->esw->dev, "vport restore QoS failed (vport=%d)\n",
+ vport->vport);
+ }
return err;
}
@@ -779,10 +765,8 @@ static int mlx5_esw_qos_link_speed_verify(struct mlx5_core_dev *mdev,
int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32 rate_mbps)
{
- u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
struct mlx5_vport *vport;
u32 link_speed_max;
- u32 bitmask;
int err;
vport = mlx5_eswitch_get_vport(esw, vport_num);
@@ -800,21 +784,9 @@ int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32
return err;
}
- mutex_lock(&esw->state_lock);
- if (!vport->qos.enabled) {
- /* Eswitch QoS wasn't enabled yet. Enable it and vport QoS. */
- err = esw_qos_vport_enable(esw, vport, rate_mbps, vport->qos.bw_share, NULL);
- } else {
- MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps);
-
- bitmask = MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
- err = mlx5_modify_scheduling_element_cmd(esw->dev,
- SCHEDULING_HIERARCHY_E_SWITCH,
- ctx,
- vport->qos.esw_tsar_ix,
- bitmask);
- }
- mutex_unlock(&esw->state_lock);
+ esw_qos_lock(esw);
+ err = mlx5_esw_qos_set_vport_max_rate(vport, rate_mbps, NULL);
+ esw_qos_unlock(esw);
return err;
}
@@ -852,6 +824,20 @@ static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char *
return 0;
}
+int mlx5_esw_qos_init(struct mlx5_eswitch *esw)
+{
+ if (esw->qos.domain)
+ return 0; /* Nothing to change. */
+
+ return esw_qos_domain_init(esw);
+}
+
+void mlx5_esw_qos_cleanup(struct mlx5_eswitch *esw)
+{
+ if (esw->qos.domain)
+ esw_qos_domain_release(esw);
+}
+
/* Eswitch devlink rate API */
int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv,
@@ -869,14 +855,9 @@ int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void
if (err)
return err;
- mutex_lock(&esw->state_lock);
- err = esw_qos_vport_enable(esw, vport, 0, 0, extack);
- if (err)
- goto unlock;
-
- err = esw_qos_set_vport_min_rate(esw, vport, tx_share, extack);
-unlock:
- mutex_unlock(&esw->state_lock);
+ esw_qos_lock(esw);
+ err = mlx5_esw_qos_set_vport_min_rate(vport, tx_share, extack);
+ esw_qos_unlock(esw);
return err;
}
@@ -895,57 +876,50 @@ int mlx5_esw_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *
if (err)
return err;
- mutex_lock(&esw->state_lock);
- err = esw_qos_vport_enable(esw, vport, 0, 0, extack);
- if (err)
- goto unlock;
-
- err = esw_qos_set_vport_max_rate(esw, vport, tx_max, extack);
-unlock:
- mutex_unlock(&esw->state_lock);
+ esw_qos_lock(esw);
+ err = mlx5_esw_qos_set_vport_max_rate(vport, tx_max, extack);
+ esw_qos_unlock(esw);
return err;
}
int mlx5_esw_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv,
u64 tx_share, struct netlink_ext_ack *extack)
{
- struct mlx5_core_dev *dev = devlink_priv(rate_node->devlink);
- struct mlx5_eswitch *esw = dev->priv.eswitch;
- struct mlx5_esw_rate_group *group = priv;
+ struct mlx5_esw_sched_node *node = priv;
+ struct mlx5_eswitch *esw = node->esw;
int err;
- err = esw_qos_devlink_rate_to_mbps(dev, "tx_share", &tx_share, extack);
+ err = esw_qos_devlink_rate_to_mbps(esw->dev, "tx_share", &tx_share, extack);
if (err)
return err;
- mutex_lock(&esw->state_lock);
- err = esw_qos_set_group_min_rate(esw, group, tx_share, extack);
- mutex_unlock(&esw->state_lock);
+ esw_qos_lock(esw);
+ err = esw_qos_set_node_min_rate(node, tx_share, extack);
+ esw_qos_unlock(esw);
return err;
}
int mlx5_esw_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv,
u64 tx_max, struct netlink_ext_ack *extack)
{
- struct mlx5_core_dev *dev = devlink_priv(rate_node->devlink);
- struct mlx5_eswitch *esw = dev->priv.eswitch;
- struct mlx5_esw_rate_group *group = priv;
+ struct mlx5_esw_sched_node *node = priv;
+ struct mlx5_eswitch *esw = node->esw;
int err;
- err = esw_qos_devlink_rate_to_mbps(dev, "tx_max", &tx_max, extack);
+ err = esw_qos_devlink_rate_to_mbps(esw->dev, "tx_max", &tx_max, extack);
if (err)
return err;
- mutex_lock(&esw->state_lock);
- err = esw_qos_set_group_max_rate(esw, group, tx_max, extack);
- mutex_unlock(&esw->state_lock);
+ esw_qos_lock(esw);
+ err = esw_qos_sched_elem_config(node, tx_max, node->bw_share, extack);
+ esw_qos_unlock(esw);
return err;
}
int mlx5_esw_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
struct netlink_ext_ack *extack)
{
- struct mlx5_esw_rate_group *group;
+ struct mlx5_esw_sched_node *node;
struct mlx5_eswitch *esw;
int err = 0;
@@ -953,7 +927,7 @@ int mlx5_esw_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
if (IS_ERR(esw))
return PTR_ERR(esw);
- mutex_lock(&esw->state_lock);
+ esw_qos_lock(esw);
if (esw->mode != MLX5_ESWITCH_OFFLOADS) {
NL_SET_ERR_MSG_MOD(extack,
"Rate node creation supported only in switchdev mode");
@@ -961,51 +935,48 @@ int mlx5_esw_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
goto unlock;
}
- group = esw_qos_create_rate_group(esw, extack);
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
+ node = esw_qos_create_vports_sched_node(esw, extack);
+ if (IS_ERR(node)) {
+ err = PTR_ERR(node);
goto unlock;
}
- *priv = group;
+ *priv = node;
unlock:
- mutex_unlock(&esw->state_lock);
+ esw_qos_unlock(esw);
return err;
}
int mlx5_esw_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv,
struct netlink_ext_ack *extack)
{
- struct mlx5_esw_rate_group *group = priv;
- struct mlx5_eswitch *esw;
- int err;
+ struct mlx5_esw_sched_node *node = priv;
+ struct mlx5_eswitch *esw = node->esw;
- esw = mlx5_devlink_eswitch_get(rate_node->devlink);
- if (IS_ERR(esw))
- return PTR_ERR(esw);
-
- mutex_lock(&esw->state_lock);
- err = esw_qos_destroy_rate_group(esw, group, extack);
- mutex_unlock(&esw->state_lock);
- return err;
+ esw_qos_lock(esw);
+ __esw_qos_destroy_node(node, extack);
+ esw_qos_put(esw);
+ esw_qos_unlock(esw);
+ return 0;
}
-int mlx5_esw_qos_vport_update_group(struct mlx5_eswitch *esw,
- struct mlx5_vport *vport,
- struct mlx5_esw_rate_group *group,
- struct netlink_ext_ack *extack)
+int mlx5_esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent,
+ struct netlink_ext_ack *extack)
{
+ struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
int err = 0;
- mutex_lock(&esw->state_lock);
- if (!vport->qos.enabled && !group)
- goto unlock;
+ if (parent && parent->esw != esw) {
+ NL_SET_ERR_MSG_MOD(extack, "Cross E-Switch scheduling is not supported");
+ return -EOPNOTSUPP;
+ }
- err = esw_qos_vport_enable(esw, vport, 0, 0, extack);
- if (!err)
- err = esw_qos_vport_update_group(esw, vport, group, extack);
-unlock:
- mutex_unlock(&esw->state_lock);
+ esw_qos_lock(esw);
+ if (!vport->qos.sched_node && parent)
+ err = mlx5_esw_qos_vport_enable(vport, SCHED_NODE_TYPE_VPORT, parent, 0, 0, extack);
+ else if (vport->qos.sched_node)
+ err = esw_qos_vport_update_parent(vport, parent, extack);
+ esw_qos_unlock(esw);
return err;
}
@@ -1014,13 +985,12 @@ int mlx5_esw_devlink_rate_parent_set(struct devlink_rate *devlink_rate,
void *priv, void *parent_priv,
struct netlink_ext_ack *extack)
{
- struct mlx5_esw_rate_group *group;
+ struct mlx5_esw_sched_node *node;
struct mlx5_vport *vport = priv;
if (!parent)
- return mlx5_esw_qos_vport_update_group(vport->dev->priv.eswitch,
- vport, NULL, extack);
+ return mlx5_esw_qos_vport_update_parent(vport, NULL, extack);
- group = parent_priv;
- return mlx5_esw_qos_vport_update_group(vport->dev->priv.eswitch, vport, group, extack);
+ node = parent_priv;
+ return mlx5_esw_qos_vport_update_parent(vport, node, extack);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h
index 0141e9d52037..6eb8f6a648c8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h
@@ -6,9 +6,16 @@
#ifdef CONFIG_MLX5_ESWITCH
-int mlx5_esw_qos_set_vport_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport,
- u32 max_rate, u32 min_rate);
-void mlx5_esw_qos_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
+int mlx5_esw_qos_init(struct mlx5_eswitch *esw);
+void mlx5_esw_qos_cleanup(struct mlx5_eswitch *esw);
+
+int mlx5_esw_qos_set_vport_rate(struct mlx5_vport *evport, u32 max_rate, u32 min_rate);
+bool mlx5_esw_qos_get_vport_rate(struct mlx5_vport *vport, u32 *max_rate, u32 *min_rate);
+void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport);
+
+void mlx5_esw_qos_vport_qos_free(struct mlx5_vport *vport);
+u32 mlx5_esw_qos_vport_get_sched_elem_ix(const struct mlx5_vport *vport);
+struct mlx5_esw_sched_node *mlx5_esw_qos_vport_get_parent(const struct mlx5_vport *vport);
int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv,
u64 tx_share, struct netlink_ext_ack *extack);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index 7aef30dbd82d..7fb8a3381f84 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -894,7 +894,7 @@ static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport
vport_num, 1,
MLX5_VPORT_ADMIN_STATE_DOWN);
- mlx5_esw_qos_vport_disable(esw, vport);
+ mlx5_esw_qos_vport_disable(vport);
esw_vport_cleanup_acl(esw, vport);
}
@@ -1061,7 +1061,7 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
unsigned long i;
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
- memset(&vport->qos, 0, sizeof(vport->qos));
+ mlx5_esw_qos_vport_qos_free(vport);
memset(&vport->info, 0, sizeof(vport->info));
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
}
@@ -1073,7 +1073,7 @@ static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw)
unsigned long i;
mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
- memset(&vport->qos, 0, sizeof(vport->qos));
+ mlx5_esw_qos_vport_qos_free(vport);
memset(&vport->info, 0, sizeof(vport->info));
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
}
@@ -1481,15 +1481,18 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
mlx5_eq_notifier_register(esw->dev, &esw->nb);
+ err = mlx5_esw_qos_init(esw);
+ if (err)
+ goto err_esw_init;
+
if (esw->mode == MLX5_ESWITCH_LEGACY) {
err = esw_legacy_enable(esw);
} else {
- mlx5_rescan_drivers(esw->dev);
err = esw_offloads_enable(esw);
}
if (err)
- goto err_esw_enable;
+ goto err_esw_init;
esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED;
@@ -1503,7 +1506,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
return 0;
-err_esw_enable:
+err_esw_init:
mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
mlx5_esw_acls_ns_cleanup(esw);
return err;
@@ -1875,6 +1878,11 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
if (err)
goto reps_err;
+ esw->mode = MLX5_ESWITCH_LEGACY;
+ err = mlx5_esw_qos_init(esw);
+ if (err)
+ goto reps_err;
+
mutex_init(&esw->offloads.encap_tbl_lock);
hash_init(esw->offloads.encap_tbl);
mutex_init(&esw->offloads.decap_tbl_lock);
@@ -1888,7 +1896,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
refcount_set(&esw->qos.refcnt, 0);
esw->enabled_vports = 0;
- esw->mode = MLX5_ESWITCH_LEGACY;
esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
@@ -1925,6 +1932,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
esw_info(esw->dev, "cleanup\n");
+ mlx5_esw_qos_cleanup(esw);
destroy_workqueue(esw->work_queue);
WARN_ON(refcount_read(&esw->qos.refcnt));
mutex_destroy(&esw->state_lock);
@@ -2061,6 +2069,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
u16 vport, struct ifla_vf_info *ivi)
{
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
+ u32 max_rate, min_rate;
if (IS_ERR(evport))
return PTR_ERR(evport);
@@ -2075,9 +2084,10 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
ivi->qos = evport->info.qos;
ivi->spoofchk = evport->info.spoofchk;
ivi->trusted = evport->info.trusted;
- if (evport->qos.enabled) {
- ivi->min_tx_rate = evport->qos.min_rate;
- ivi->max_tx_rate = evport->qos.max_rate;
+
+ if (mlx5_esw_qos_get_vport_rate(evport, &max_rate, &min_rate)) {
+ ivi->max_tx_rate = max_rate;
+ ivi->min_tx_rate = min_rate;
}
mutex_unlock(&esw->state_lock);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index f44b4c7ebcfd..a83d41121db6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -212,13 +212,10 @@ struct mlx5_vport {
struct mlx5_vport_info info;
+ /* Protected with the E-Switch qos domain lock. */
struct {
- bool enabled;
- u32 esw_tsar_ix;
- u32 bw_share;
- u32 min_rate;
- u32 max_rate;
- struct mlx5_esw_rate_group *group;
+ /* Vport scheduling element node. */
+ struct mlx5_esw_sched_node *sched_node;
} qos;
u16 vport;
@@ -333,6 +330,7 @@ enum {
};
struct dentry;
+struct mlx5_qos_domain;
struct mlx5_eswitch {
struct mlx5_core_dev *dev;
@@ -359,15 +357,17 @@ struct mlx5_eswitch {
struct rw_semaphore mode_lock;
atomic64_t user_count;
+ /* Protected with the E-Switch qos domain lock. */
struct {
- u32 root_tsar_ix;
- struct mlx5_esw_rate_group *group0;
- struct list_head groups; /* Protected by esw->state_lock */
-
- /* Protected by esw->state_lock.
- * Initially 0, meaning no QoS users and QoS is disabled.
- */
+ /* Initially 0, meaning no QoS users and QoS is disabled. */
refcount_t refcnt;
+ u32 root_tsar_ix;
+ struct mlx5_qos_domain *domain;
+ /* Contains all vports with QoS enabled but no explicit node.
+ * Cannot be NULL if QoS is enabled, but may be a fake node
+ * referencing the root TSAR if the esw doesn't support nodes.
+ */
+ struct mlx5_esw_sched_node *node0;
} qos;
struct mlx5_esw_bridge_offloads *br_offloads;
@@ -427,10 +427,8 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
u16 vport_num, bool setting);
int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
u32 max_rate, u32 min_rate);
-int mlx5_esw_qos_vport_update_group(struct mlx5_eswitch *esw,
- struct mlx5_vport *vport,
- struct mlx5_esw_rate_group *group,
- struct netlink_ext_ack *extack);
+int mlx5_esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *node,
+ struct netlink_ext_ack *extack);
int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting);
int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting);
int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
@@ -806,7 +804,7 @@ int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, struct mlx5
void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
-void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
+void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport);
struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num);
int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index f24f91d213f2..d6ff2dc4c19e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -2332,18 +2332,35 @@ out_free:
return err;
}
+static void esw_mode_change(struct mlx5_eswitch *esw, u16 mode)
+{
+ mlx5_devcom_comp_lock(esw->dev->priv.hca_devcom_comp);
+
+ if (esw->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_IB_ADEV) {
+ esw->mode = mode;
+ mlx5_devcom_comp_unlock(esw->dev->priv.hca_devcom_comp);
+ return;
+ }
+
+ esw->dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
+ mlx5_rescan_drivers_locked(esw->dev);
+ esw->mode = mode;
+ esw->dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
+ mlx5_rescan_drivers_locked(esw->dev);
+ mlx5_devcom_comp_unlock(esw->dev->priv.hca_devcom_comp);
+}
+
static int esw_offloads_start(struct mlx5_eswitch *esw,
struct netlink_ext_ack *extack)
{
int err;
- esw->mode = MLX5_ESWITCH_OFFLOADS;
+ esw_mode_change(esw, MLX5_ESWITCH_OFFLOADS);
err = mlx5_eswitch_enable_locked(esw, esw->dev->priv.sriov.num_vfs);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed setting eswitch to offloads");
- esw->mode = MLX5_ESWITCH_LEGACY;
- mlx5_rescan_drivers(esw->dev);
+ esw_mode_change(esw, MLX5_ESWITCH_LEGACY);
return err;
}
if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
@@ -2527,8 +2544,11 @@ static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep, u8 rep_type)
{
if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
- REP_LOADED, REP_REGISTERED) == REP_LOADED)
+ REP_LOADED, REP_REGISTERED) == REP_LOADED) {
+ if (rep_type == REP_ETH)
+ __esw_offloads_unload_rep(esw, rep, REP_IB);
esw->offloads.rep_ops[rep_type]->unload(rep);
+ }
}
static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type)
@@ -2617,7 +2637,7 @@ int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, struct mlx5_vport *vpor
return err;
load_err:
- mlx5_esw_offloads_devlink_port_unregister(esw, vport);
+ mlx5_esw_offloads_devlink_port_unregister(vport);
return err;
}
@@ -2628,7 +2648,7 @@ void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, struct mlx5_vport *v
mlx5_esw_offloads_rep_unload(esw, vport->vport);
- mlx5_esw_offloads_devlink_port_unregister(esw, vport);
+ mlx5_esw_offloads_devlink_port_unregister(vport);
}
static int esw_set_slave_root_fdb(struct mlx5_core_dev *master,
@@ -3584,7 +3604,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
{
int err;
- esw->mode = MLX5_ESWITCH_LEGACY;
+ esw_mode_change(esw, MLX5_ESWITCH_LEGACY);
/* If changing from switchdev to legacy mode without sriov enabled,
* no need to create legacy fdb.
@@ -3770,7 +3790,6 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
err = esw_offloads_start(esw, extack);
} else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
err = esw_offloads_stop(esw, extack);
- mlx5_rescan_drivers(esw->dev);
} else {
err = -EINVAL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 8505d5e241e1..2eabfcc247c6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -2105,13 +2105,22 @@ lookup_fte_locked(struct mlx5_flow_group *g,
fte_tmp = NULL;
goto out;
}
+
+ nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
+
if (!fte_tmp->node.active) {
+ up_write_ref_node(&fte_tmp->node, false);
+
+ if (take_write)
+ up_write_ref_node(&g->node, false);
+ else
+ up_read_ref_node(&g->node);
+
tree_put_node(&fte_tmp->node, false);
- fte_tmp = NULL;
- goto out;
+
+ return NULL;
}
- nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
out:
if (take_write)
up_write_ref_node(&g->node, false);
@@ -3689,6 +3698,7 @@ void mlx5_fs_core_free(struct mlx5_core_dev *dev)
int mlx5_fs_core_alloc(struct mlx5_core_dev *dev)
{
struct mlx5_flow_steering *steering;
+ char name[80];
int err = 0;
err = mlx5_init_fc_stats(dev);
@@ -3713,10 +3723,12 @@ int mlx5_fs_core_alloc(struct mlx5_core_dev *dev)
else
steering->mode = MLX5_FLOW_STEERING_MODE_DMFS;
- steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
+ snprintf(name, sizeof(name), "%s-mlx5_fs_fgs", dev_name(dev->device));
+ steering->fgs_cache = kmem_cache_create(name,
sizeof(struct mlx5_flow_group), 0,
0, NULL);
- steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
+ snprintf(name, sizeof(name), "%s-mlx5_fs_ftes", dev_name(dev->device));
+ steering->ftes_cache = kmem_cache_create(name, sizeof(struct fs_fte), 0,
0, NULL);
if (!steering->ftes_cache || !steering->fgs_cache) {
err = -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index 964937f17cf5..bad2df0715ec 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -37,7 +37,7 @@
#include <linux/mlx5/fs.h>
#include <linux/rhashtable.h>
#include <linux/llist.h>
-#include <steering/fs_dr.h>
+#include <steering/sws/fs_dr.h>
#define FDB_TC_MAX_CHAIN 3
#define FDB_FT_CHAIN (FDB_TC_MAX_CHAIN + 1)
@@ -63,7 +63,7 @@ struct mlx5_modify_hdr {
enum mlx5_flow_namespace_type ns_type;
enum mlx5_flow_resource_owner owner;
union {
- struct mlx5_fs_dr_action action;
+ struct mlx5_fs_dr_action fs_dr_action;
u32 id;
};
};
@@ -73,7 +73,7 @@ struct mlx5_pkt_reformat {
int reformat_type; /* from mlx5_ifc */
enum mlx5_flow_resource_owner owner;
union {
- struct mlx5_fs_dr_action action;
+ struct mlx5_fs_dr_action fs_dr_action;
u32 id;
};
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
index 0c26d707eed2..62d0c689796b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
@@ -32,13 +32,11 @@
#include <linux/mlx5/driver.h>
#include <linux/mlx5/fs.h>
-#include <linux/rbtree.h>
#include "mlx5_core.h"
#include "fs_core.h"
#include "fs_cmd.h"
#define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000)
-#define MLX5_FC_BULK_QUERY_ALLOC_PERIOD msecs_to_jiffies(180 * 1000)
/* Max number of counters to query in bulk read is 32K */
#define MLX5_SW_MAX_COUNTERS_BULK BIT(15)
#define MLX5_INIT_COUNTERS_BULK 8
@@ -52,21 +50,37 @@ struct mlx5_fc_cache {
};
struct mlx5_fc {
- struct list_head list;
- struct llist_node addlist;
- struct llist_node dellist;
-
- /* last{packets,bytes} members are used when calculating the delta since
- * last reading
- */
+ u32 id;
+ bool aging;
+ struct mlx5_fc_bulk *bulk;
+ struct mlx5_fc_cache cache;
+ /* last{packets,bytes} are used for calculating deltas since last reading. */
u64 lastpackets;
u64 lastbytes;
+};
- struct mlx5_fc_bulk *bulk;
- u32 id;
- bool aging;
+struct mlx5_fc_pool {
+ struct mlx5_core_dev *dev;
+ struct mutex pool_lock; /* protects pool lists */
+ struct list_head fully_used;
+ struct list_head partially_used;
+ struct list_head unused;
+ int available_fcs;
+ int used_fcs;
+ int threshold;
+};
- struct mlx5_fc_cache cache ____cacheline_aligned_in_smp;
+struct mlx5_fc_stats {
+ struct xarray counters;
+
+ struct workqueue_struct *wq;
+ struct delayed_work work;
+ unsigned long sampling_interval; /* jiffies */
+ u32 *bulk_query_out;
+ int bulk_query_len;
+ bool bulk_query_alloc_failed;
+ unsigned long next_bulk_query_alloc;
+ struct mlx5_fc_pool fc_pool;
};
static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev);
@@ -74,78 +88,6 @@ static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool);
static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool);
static void mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc);
-/* locking scheme:
- *
- * It is the responsibility of the user to prevent concurrent calls or bad
- * ordering to mlx5_fc_create(), mlx5_fc_destroy() and accessing a reference
- * to struct mlx5_fc.
- * e.g en_tc.c is protected by RTNL lock of its caller, and will never call a
- * dump (access to struct mlx5_fc) after a counter is destroyed.
- *
- * access to counter list:
- * - create (user context)
- * - mlx5_fc_create() only adds to an addlist to be used by
- * mlx5_fc_stats_work(). addlist is a lockless single linked list
- * that doesn't require any additional synchronization when adding single
- * node.
- * - spawn thread to do the actual destroy
- *
- * - destroy (user context)
- * - add a counter to lockless dellist
- * - spawn thread to do the actual del
- *
- * - dump (user context)
- * user should not call dump after destroy
- *
- * - query (single thread workqueue context)
- * destroy/dump - no conflict (see destroy)
- * query/dump - packets and bytes might be inconsistent (since update is not
- * atomic)
- * query/create - no conflict (see create)
- * since every create/destroy spawn the work, only after necessary time has
- * elapsed, the thread will actually query the hardware.
- */
-
-static struct list_head *mlx5_fc_counters_lookup_next(struct mlx5_core_dev *dev,
- u32 id)
-{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
- unsigned long next_id = (unsigned long)id + 1;
- struct mlx5_fc *counter;
- unsigned long tmp;
-
- rcu_read_lock();
- /* skip counters that are in idr, but not yet in counters list */
- idr_for_each_entry_continue_ul(&fc_stats->counters_idr,
- counter, tmp, next_id) {
- if (!list_empty(&counter->list))
- break;
- }
- rcu_read_unlock();
-
- return counter ? &counter->list : &fc_stats->counters;
-}
-
-static void mlx5_fc_stats_insert(struct mlx5_core_dev *dev,
- struct mlx5_fc *counter)
-{
- struct list_head *next = mlx5_fc_counters_lookup_next(dev, counter->id);
-
- list_add_tail(&counter->list, next);
-}
-
-static void mlx5_fc_stats_remove(struct mlx5_core_dev *dev,
- struct mlx5_fc *counter)
-{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
-
- list_del(&counter->list);
-
- spin_lock(&fc_stats->counters_idr_lock);
- WARN_ON(!idr_remove(&fc_stats->counters_idr, counter->id));
- spin_unlock(&fc_stats->counters_idr_lock);
-}
-
static int get_init_bulk_query_len(struct mlx5_core_dev *dev)
{
return min_t(int, MLX5_INIT_COUNTERS_BULK,
@@ -174,47 +116,64 @@ static void update_counter_cache(int index, u32 *bulk_raw_data,
cache->lastuse = jiffies;
}
-static void mlx5_fc_stats_query_counter_range(struct mlx5_core_dev *dev,
- struct mlx5_fc *first,
- u32 last_id)
+/* Synchronization notes
+ *
+ * Access to counter array:
+ * - create - mlx5_fc_create() (user context)
+ * - inserts the counter into the xarray.
+ *
+ * - destroy - mlx5_fc_destroy() (user context)
+ * - erases the counter from the xarray and releases it.
+ *
+ * - query mlx5_fc_query(), mlx5_fc_query_cached{,_raw}() (user context)
+ * - user should not access a counter after destroy.
+ *
+ * - bulk query (single thread workqueue context)
+ * - create: query relies on 'lastuse' to avoid updating counters added
+ * around the same time as the current bulk cmd.
+ * - destroy: destroyed counters will not be accessed, even if they are
+ * destroyed during a bulk query command.
+ */
+static void mlx5_fc_stats_query_all_counters(struct mlx5_core_dev *dev)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
- bool query_more_counters = (first->id <= last_id);
- int cur_bulk_len = fc_stats->bulk_query_len;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
+ u32 bulk_len = fc_stats->bulk_query_len;
+ XA_STATE(xas, &fc_stats->counters, 0);
u32 *data = fc_stats->bulk_query_out;
- struct mlx5_fc *counter = first;
+ struct mlx5_fc *counter;
+ u32 last_bulk_id = 0;
+ u64 bulk_query_time;
u32 bulk_base_id;
- int bulk_len;
int err;
- while (query_more_counters) {
- /* first id must be aligned to 4 when using bulk query */
- bulk_base_id = counter->id & ~0x3;
-
- /* number of counters to query inc. the last counter */
- bulk_len = min_t(int, cur_bulk_len,
- ALIGN(last_id - bulk_base_id + 1, 4));
-
- err = mlx5_cmd_fc_bulk_query(dev, bulk_base_id, bulk_len,
- data);
- if (err) {
- mlx5_core_err(dev, "Error doing bulk query: %d\n", err);
- return;
- }
- query_more_counters = false;
-
- list_for_each_entry_from(counter, &fc_stats->counters, list) {
- int counter_index = counter->id - bulk_base_id;
- struct mlx5_fc_cache *cache = &counter->cache;
-
- if (counter->id >= bulk_base_id + bulk_len) {
- query_more_counters = true;
- break;
+ xas_lock(&xas);
+ xas_for_each(&xas, counter, U32_MAX) {
+ if (xas_retry(&xas, counter))
+ continue;
+ if (unlikely(counter->id >= last_bulk_id)) {
+ /* Start new bulk query. */
+ /* First id must be aligned to 4 when using bulk query. */
+ bulk_base_id = counter->id & ~0x3;
+ last_bulk_id = bulk_base_id + bulk_len;
+ /* The lock is released while querying the hw and reacquired after. */
+ xas_unlock(&xas);
+ /* The same id needs to be processed again in the next loop iteration. */
+ xas_reset(&xas);
+ bulk_query_time = jiffies;
+ err = mlx5_cmd_fc_bulk_query(dev, bulk_base_id, bulk_len, data);
+ if (err) {
+ mlx5_core_err(dev, "Error doing bulk query: %d\n", err);
+ return;
}
-
- update_counter_cache(counter_index, data, cache);
+ xas_lock(&xas);
+ continue;
}
+ /* Do not update counters added after bulk query was started. */
+ if (time_after64(bulk_query_time, counter->cache.lastuse))
+ update_counter_cache(counter->id - bulk_base_id, data,
+ &counter->cache);
}
+ xas_unlock(&xas);
}
static void mlx5_fc_free(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
@@ -225,7 +184,7 @@ static void mlx5_fc_free(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
static void mlx5_fc_release(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
if (counter->bulk)
mlx5_fc_pool_release_counter(&fc_stats->fc_pool, counter);
@@ -233,85 +192,55 @@ static void mlx5_fc_release(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
mlx5_fc_free(dev, counter);
}
-static void mlx5_fc_stats_bulk_query_size_increase(struct mlx5_core_dev *dev)
+static void mlx5_fc_stats_bulk_query_buf_realloc(struct mlx5_core_dev *dev,
+ int bulk_query_len)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
- int max_bulk_len = get_max_bulk_query_len(dev);
- unsigned long now = jiffies;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
u32 *bulk_query_out_tmp;
- int max_out_len;
-
- if (fc_stats->bulk_query_alloc_failed &&
- time_before(now, fc_stats->next_bulk_query_alloc))
- return;
+ int out_len;
- max_out_len = mlx5_cmd_fc_get_bulk_query_out_len(max_bulk_len);
- bulk_query_out_tmp = kzalloc(max_out_len, GFP_KERNEL);
+ out_len = mlx5_cmd_fc_get_bulk_query_out_len(bulk_query_len);
+ bulk_query_out_tmp = kvzalloc(out_len, GFP_KERNEL);
if (!bulk_query_out_tmp) {
mlx5_core_warn_once(dev,
- "Can't increase flow counters bulk query buffer size, insufficient memory, bulk_size(%d)\n",
- max_bulk_len);
- fc_stats->bulk_query_alloc_failed = true;
- fc_stats->next_bulk_query_alloc =
- now + MLX5_FC_BULK_QUERY_ALLOC_PERIOD;
+ "Can't increase flow counters bulk query buffer size, alloc failed, bulk_query_len(%d)\n",
+ bulk_query_len);
return;
}
- kfree(fc_stats->bulk_query_out);
+ kvfree(fc_stats->bulk_query_out);
fc_stats->bulk_query_out = bulk_query_out_tmp;
- fc_stats->bulk_query_len = max_bulk_len;
- if (fc_stats->bulk_query_alloc_failed) {
- mlx5_core_info(dev,
- "Flow counters bulk query buffer size increased, bulk_size(%d)\n",
- max_bulk_len);
- fc_stats->bulk_query_alloc_failed = false;
- }
+ fc_stats->bulk_query_len = bulk_query_len;
+ mlx5_core_info(dev,
+ "Flow counters bulk query buffer size increased, bulk_query_len(%d)\n",
+ bulk_query_len);
}
-static void mlx5_fc_stats_work(struct work_struct *work)
+static int mlx5_fc_num_counters(struct mlx5_fc_stats *fc_stats)
{
- struct mlx5_core_dev *dev = container_of(work, struct mlx5_core_dev,
- priv.fc_stats.work.work);
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
- /* Take dellist first to ensure that counters cannot be deleted before
- * they are inserted.
- */
- struct llist_node *dellist = llist_del_all(&fc_stats->dellist);
- struct llist_node *addlist = llist_del_all(&fc_stats->addlist);
- struct mlx5_fc *counter = NULL, *last = NULL, *tmp;
- unsigned long now = jiffies;
-
- if (addlist || !list_empty(&fc_stats->counters))
- queue_delayed_work(fc_stats->wq, &fc_stats->work,
- fc_stats->sampling_interval);
-
- llist_for_each_entry(counter, addlist, addlist) {
- mlx5_fc_stats_insert(dev, counter);
- fc_stats->num_counters++;
- }
-
- llist_for_each_entry_safe(counter, tmp, dellist, dellist) {
- mlx5_fc_stats_remove(dev, counter);
+ struct mlx5_fc *counter;
+ int num_counters = 0;
+ unsigned long id;
- mlx5_fc_release(dev, counter);
- fc_stats->num_counters--;
- }
+ xa_for_each(&fc_stats->counters, id, counter)
+ num_counters++;
+ return num_counters;
+}
- if (fc_stats->bulk_query_len < get_max_bulk_query_len(dev) &&
- fc_stats->num_counters > get_init_bulk_query_len(dev))
- mlx5_fc_stats_bulk_query_size_increase(dev);
+static void mlx5_fc_stats_work(struct work_struct *work)
+{
+ struct mlx5_fc_stats *fc_stats = container_of(work, struct mlx5_fc_stats,
+ work.work);
+ struct mlx5_core_dev *dev = fc_stats->fc_pool.dev;
- if (time_before(now, fc_stats->next_query) ||
- list_empty(&fc_stats->counters))
- return;
- last = list_last_entry(&fc_stats->counters, struct mlx5_fc, list);
+ queue_delayed_work(fc_stats->wq, &fc_stats->work, fc_stats->sampling_interval);
- counter = list_first_entry(&fc_stats->counters, struct mlx5_fc,
- list);
- if (counter)
- mlx5_fc_stats_query_counter_range(dev, counter, last->id);
+ /* Grow the bulk query buffer to max if not maxed and enough counters are present. */
+ if (unlikely(fc_stats->bulk_query_len < get_max_bulk_query_len(dev) &&
+ mlx5_fc_num_counters(fc_stats) > get_init_bulk_query_len(dev)))
+ mlx5_fc_stats_bulk_query_buf_realloc(dev, get_max_bulk_query_len(dev));
- fc_stats->next_query = now + fc_stats->sampling_interval;
+ mlx5_fc_stats_query_all_counters(dev);
}
static struct mlx5_fc *mlx5_fc_single_alloc(struct mlx5_core_dev *dev)
@@ -334,7 +263,7 @@ static struct mlx5_fc *mlx5_fc_single_alloc(struct mlx5_core_dev *dev)
static struct mlx5_fc *mlx5_fc_acquire(struct mlx5_core_dev *dev, bool aging)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
struct mlx5_fc *counter;
if (aging && MLX5_CAP_GEN(dev, flow_counter_bulk_alloc) != 0) {
@@ -346,16 +275,15 @@ static struct mlx5_fc *mlx5_fc_acquire(struct mlx5_core_dev *dev, bool aging)
return mlx5_fc_single_alloc(dev);
}
-struct mlx5_fc *mlx5_fc_create_ex(struct mlx5_core_dev *dev, bool aging)
+struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging)
{
struct mlx5_fc *counter = mlx5_fc_acquire(dev, aging);
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
int err;
if (IS_ERR(counter))
return counter;
- INIT_LIST_HEAD(&counter->list);
counter->aging = aging;
if (aging) {
@@ -365,18 +293,9 @@ struct mlx5_fc *mlx5_fc_create_ex(struct mlx5_core_dev *dev, bool aging)
counter->lastbytes = counter->cache.bytes;
counter->lastpackets = counter->cache.packets;
- idr_preload(GFP_KERNEL);
- spin_lock(&fc_stats->counters_idr_lock);
-
- err = idr_alloc_u32(&fc_stats->counters_idr, counter, &id, id,
- GFP_NOWAIT);
-
- spin_unlock(&fc_stats->counters_idr_lock);
- idr_preload_end();
- if (err)
+ err = xa_err(xa_store(&fc_stats->counters, id, counter, GFP_KERNEL));
+ if (err != 0)
goto err_out_alloc;
-
- llist_add(&counter->addlist, &fc_stats->addlist);
}
return counter;
@@ -385,16 +304,6 @@ err_out_alloc:
mlx5_fc_release(dev, counter);
return ERR_PTR(err);
}
-
-struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging)
-{
- struct mlx5_fc *counter = mlx5_fc_create_ex(dev, aging);
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
-
- if (aging)
- mod_delayed_work(fc_stats->wq, &fc_stats->work, 0);
- return counter;
-}
EXPORT_SYMBOL(mlx5_fc_create);
u32 mlx5_fc_id(struct mlx5_fc *counter)
@@ -405,39 +314,32 @@ EXPORT_SYMBOL(mlx5_fc_id);
void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
if (!counter)
return;
- if (counter->aging) {
- llist_add(&counter->dellist, &fc_stats->dellist);
- mod_delayed_work(fc_stats->wq, &fc_stats->work, 0);
- return;
- }
-
+ if (counter->aging)
+ xa_erase(&fc_stats->counters, counter->id);
mlx5_fc_release(dev, counter);
}
EXPORT_SYMBOL(mlx5_fc_destroy);
int mlx5_init_fc_stats(struct mlx5_core_dev *dev)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
- int init_bulk_len;
- int init_out_len;
+ struct mlx5_fc_stats *fc_stats;
+
+ fc_stats = kzalloc(sizeof(*fc_stats), GFP_KERNEL);
+ if (!fc_stats)
+ return -ENOMEM;
+ dev->priv.fc_stats = fc_stats;
- spin_lock_init(&fc_stats->counters_idr_lock);
- idr_init(&fc_stats->counters_idr);
- INIT_LIST_HEAD(&fc_stats->counters);
- init_llist_head(&fc_stats->addlist);
- init_llist_head(&fc_stats->dellist);
+ xa_init(&fc_stats->counters);
- init_bulk_len = get_init_bulk_query_len(dev);
- init_out_len = mlx5_cmd_fc_get_bulk_query_out_len(init_bulk_len);
- fc_stats->bulk_query_out = kzalloc(init_out_len, GFP_KERNEL);
+ /* Allocate initial (small) bulk query buffer. */
+ mlx5_fc_stats_bulk_query_buf_realloc(dev, get_init_bulk_query_len(dev));
if (!fc_stats->bulk_query_out)
- return -ENOMEM;
- fc_stats->bulk_query_len = init_bulk_len;
+ goto err_bulk;
fc_stats->wq = create_singlethread_workqueue("mlx5_fc");
if (!fc_stats->wq)
@@ -447,34 +349,35 @@ int mlx5_init_fc_stats(struct mlx5_core_dev *dev)
INIT_DELAYED_WORK(&fc_stats->work, mlx5_fc_stats_work);
mlx5_fc_pool_init(&fc_stats->fc_pool, dev);
+ queue_delayed_work(fc_stats->wq, &fc_stats->work, MLX5_FC_STATS_PERIOD);
return 0;
err_wq_create:
- kfree(fc_stats->bulk_query_out);
+ kvfree(fc_stats->bulk_query_out);
+err_bulk:
+ kfree(fc_stats);
return -ENOMEM;
}
void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
- struct llist_node *tmplist;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
struct mlx5_fc *counter;
- struct mlx5_fc *tmp;
-
- cancel_delayed_work_sync(&dev->priv.fc_stats.work);
- destroy_workqueue(dev->priv.fc_stats.wq);
- dev->priv.fc_stats.wq = NULL;
+ unsigned long id;
- tmplist = llist_del_all(&fc_stats->addlist);
- llist_for_each_entry_safe(counter, tmp, tmplist, addlist)
- mlx5_fc_release(dev, counter);
+ cancel_delayed_work_sync(&fc_stats->work);
+ destroy_workqueue(fc_stats->wq);
+ fc_stats->wq = NULL;
- list_for_each_entry_safe(counter, tmp, &fc_stats->counters, list)
+ xa_for_each(&fc_stats->counters, id, counter) {
+ xa_erase(&fc_stats->counters, id);
mlx5_fc_release(dev, counter);
+ }
+ xa_destroy(&fc_stats->counters);
mlx5_fc_pool_cleanup(&fc_stats->fc_pool);
- idr_destroy(&fc_stats->counters_idr);
- kfree(fc_stats->bulk_query_out);
+ kvfree(fc_stats->bulk_query_out);
+ kfree(fc_stats);
}
int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
@@ -518,7 +421,7 @@ void mlx5_fc_queue_stats_work(struct mlx5_core_dev *dev,
struct delayed_work *dwork,
unsigned long delay)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
queue_delayed_work(fc_stats->wq, dwork, delay);
}
@@ -526,7 +429,7 @@ void mlx5_fc_queue_stats_work(struct mlx5_core_dev *dev,
void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
unsigned long interval)
{
- struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
+ struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
fc_stats->sampling_interval = min_t(unsigned long, interval,
fc_stats->sampling_interval);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
index 4f55e55ecb55..566710d34a7b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -35,6 +35,7 @@ struct mlx5_fw_reset {
enum {
MLX5_FW_RST_STATE_IDLE = 0,
MLX5_FW_RST_STATE_TOGGLE_REQ = 4,
+ MLX5_FW_RST_STATE_DROP_MODE = 5,
};
enum {
@@ -616,6 +617,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work)
struct mlx5_fw_reset *fw_reset;
struct mlx5_core_dev *dev;
unsigned long timeout;
+ int poll_freq = 20;
bool reset_action;
u8 rst_state;
int err;
@@ -651,7 +653,12 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work)
reset_action = true;
break;
}
- msleep(20);
+ if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) {
+ mlx5_core_info(dev, "Sync Reset Drop mode ack\n");
+ mlx5_set_fw_rst_ack(dev);
+ poll_freq = 1000;
+ }
+ msleep(poll_freq);
} while (!time_after(jiffies, timeout));
if (!reset_action) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 8577db3308cc..7f68468c2e75 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -516,6 +516,7 @@ void mlx5_modify_lag(struct mlx5_lag *ldev,
blocking_notifier_call_chain(&dev0->priv.lag_nh,
MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE,
ndev);
+ dev_put(ndev);
}
}
@@ -918,6 +919,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
struct lag_tracker tracker = { };
+ struct net_device *ndev;
bool do_bond, roce_lag;
int err;
int i;
@@ -981,6 +983,16 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
return;
}
}
+ if (tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
+ ndev = mlx5_lag_active_backup_get_netdev(dev0);
+ /** Only sriov and roce lag should have tracker->TX_type
+ * set so no need to check the mode
+ */
+ blocking_notifier_call_chain(&dev0->priv.lag_nh,
+ MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE,
+ ndev);
+ dev_put(ndev);
+ }
} else if (mlx5_lag_should_modify_lag(ldev, do_bond)) {
mlx5_modify_lag(ldev, &tracker);
} else if (mlx5_lag_should_disable_lag(ldev, do_bond)) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index b306ae79bf97..4822d01123b4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -402,9 +402,7 @@ static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
struct ptp_system_timestamp *sts)
{
struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
- struct mlx5_timer *timer = &clock->timer;
struct mlx5_core_dev *mdev;
- unsigned long flags;
u64 cycles, ns;
mdev = container_of(clock, struct mlx5_core_dev, clock);
@@ -413,10 +411,8 @@ static int mlx5_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
goto out;
}
- write_seqlock_irqsave(&clock->lock, flags);
cycles = mlx5_read_time(mdev, sts, false);
- ns = timecounter_cyc2time(&timer->tc, cycles);
- write_sequnlock_irqrestore(&clock->lock, flags);
+ ns = mlx5_timecounter_cyc2time(clock, cycles);
*ts = ns_to_timespec64(ns);
out:
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
index 4b7f7131c560..b1edc71ffc6d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
@@ -72,7 +72,7 @@ static inline void eq_update_ci(struct mlx5_eq *eq, int arm)
__raw_writel((__force u32)cpu_to_be32(val), addr);
/* We still want ordering, just not swabbing, so add a barrier */
- mb();
+ wmb();
}
int mlx5_eq_table_init(struct mlx5_core_dev *dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/smfs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/smfs.h
index 452d0df339ac..404f3d4b6380 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/smfs.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/smfs.h
@@ -4,8 +4,8 @@
#ifndef __MLX5_LIB_SMFS_H__
#define __MLX5_LIB_SMFS_H__
-#include "steering/mlx5dr.h"
-#include "steering/dr_types.h"
+#include "steering/sws/mlx5dr.h"
+#include "steering/sws/dr_types.h"
struct mlx5dr_matcher *
mlx5_smfs_matcher_create(struct mlx5dr_table *table, u32 priority, struct mlx5_flow_spec *spec);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 62c770b0eaa8..99de67c3aa74 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -224,6 +224,8 @@ void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change);
int mlx5_core_sriov_set_msix_vec_count(struct pci_dev *vf, int msix_vec_count);
int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id);
int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id);
+bool mlx5_qos_element_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy);
+bool mlx5_qos_tsar_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy);
int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
void *context, u32 *element_id);
int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
index 81a9232a03e1..7db9cab9bedf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
@@ -593,9 +593,11 @@ static void irq_pool_free(struct mlx5_irq_pool *pool)
kvfree(pool);
}
-static int irq_pools_init(struct mlx5_core_dev *dev, int sf_vec, int pcif_vec)
+static int irq_pools_init(struct mlx5_core_dev *dev, int sf_vec, int pcif_vec,
+ bool dynamic_vec)
{
struct mlx5_irq_table *table = dev->priv.irq_table;
+ int sf_vec_available = sf_vec;
int num_sf_ctrl;
int err;
@@ -616,6 +618,13 @@ static int irq_pools_init(struct mlx5_core_dev *dev, int sf_vec, int pcif_vec)
num_sf_ctrl = DIV_ROUND_UP(mlx5_sf_max_functions(dev),
MLX5_SFS_PER_CTRL_IRQ);
num_sf_ctrl = min_t(int, MLX5_IRQ_CTRL_SF_MAX, num_sf_ctrl);
+ if (!dynamic_vec && (num_sf_ctrl + 1) > sf_vec_available) {
+ mlx5_core_dbg(dev,
+ "Not enough IRQs for SFs control and completion pool, required=%d avail=%d\n",
+ num_sf_ctrl + 1, sf_vec_available);
+ return 0;
+ }
+
table->sf_ctrl_pool = irq_pool_alloc(dev, pcif_vec, num_sf_ctrl,
"mlx5_sf_ctrl",
MLX5_EQ_SHARE_IRQ_MIN_CTRL,
@@ -624,9 +633,11 @@ static int irq_pools_init(struct mlx5_core_dev *dev, int sf_vec, int pcif_vec)
err = PTR_ERR(table->sf_ctrl_pool);
goto err_pf;
}
- /* init sf_comp_pool */
+ sf_vec_available -= num_sf_ctrl;
+
+ /* init sf_comp_pool, remaining vectors are for the SF completions */
table->sf_comp_pool = irq_pool_alloc(dev, pcif_vec + num_sf_ctrl,
- sf_vec - num_sf_ctrl, "mlx5_sf_comp",
+ sf_vec_available, "mlx5_sf_comp",
MLX5_EQ_SHARE_IRQ_MIN_COMP,
MLX5_EQ_SHARE_IRQ_MAX_COMP);
if (IS_ERR(table->sf_comp_pool)) {
@@ -715,6 +726,7 @@ int mlx5_irq_table_get_num_comp(struct mlx5_irq_table *table)
int mlx5_irq_table_create(struct mlx5_core_dev *dev)
{
int num_eqs = mlx5_max_eq_cap_get(dev);
+ bool dynamic_vec;
int total_vec;
int pcif_vec;
int req_vec;
@@ -724,21 +736,31 @@ int mlx5_irq_table_create(struct mlx5_core_dev *dev)
if (mlx5_core_is_sf(dev))
return 0;
+ /* PCI PF vectors usage is limited by online cpus, device EQs and
+ * PCI MSI-X capability.
+ */
pcif_vec = MLX5_CAP_GEN(dev, num_ports) * num_online_cpus() + 1;
pcif_vec = min_t(int, pcif_vec, num_eqs);
+ pcif_vec = min_t(int, pcif_vec, pci_msix_vec_count(dev->pdev));
total_vec = pcif_vec;
if (mlx5_sf_max_functions(dev))
total_vec += MLX5_MAX_MSIX_PER_SF * mlx5_sf_max_functions(dev);
total_vec = min_t(int, total_vec, pci_msix_vec_count(dev->pdev));
- pcif_vec = min_t(int, pcif_vec, pci_msix_vec_count(dev->pdev));
req_vec = pci_msix_can_alloc_dyn(dev->pdev) ? 1 : total_vec;
n = pci_alloc_irq_vectors(dev->pdev, 1, req_vec, PCI_IRQ_MSIX);
if (n < 0)
return n;
- err = irq_pools_init(dev, total_vec - pcif_vec, pcif_vec);
+ /* Further limit vectors of the pools based on platform for non dynamic case */
+ dynamic_vec = pci_msix_can_alloc_dyn(dev->pdev);
+ if (!dynamic_vec) {
+ pcif_vec = min_t(int, n, pcif_vec);
+ total_vec = min_t(int, n, total_vec);
+ }
+
+ err = irq_pools_init(dev, total_vec - pcif_vec, pcif_vec, dynamic_vec);
if (err)
pci_free_irq_vectors(dev->pdev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/qos.c
index db2bd3ad63ba..6be9981bb6b1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/qos.c
@@ -28,7 +28,9 @@ int mlx5_qos_create_leaf_node(struct mlx5_core_dev *mdev, u32 parent_id,
{
u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
- if (!(MLX5_CAP_QOS(mdev, nic_element_type) & ELEMENT_TYPE_CAP_MASK_QUEUE_GROUP))
+ if (!mlx5_qos_element_type_supported(mdev,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_QUEUE_GROUP,
+ SCHEDULING_HIERARCHY_NIC))
return -EOPNOTSUPP;
MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_id);
@@ -47,8 +49,12 @@ int mlx5_qos_create_inner_node(struct mlx5_core_dev *mdev, u32 parent_id,
u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
void *attr;
- if (!(MLX5_CAP_QOS(mdev, nic_element_type) & ELEMENT_TYPE_CAP_MASK_TSAR) ||
- !(MLX5_CAP_QOS(mdev, nic_tsar_type) & TSAR_TYPE_CAP_MASK_DWRR))
+ if (!mlx5_qos_element_type_supported(mdev,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR,
+ SCHEDULING_HIERARCHY_NIC) ||
+ !mlx5_qos_tsar_type_supported(mdev,
+ TSAR_ELEMENT_TSAR_TYPE_DWRR,
+ SCHEDULING_HIERARCHY_NIC))
return -EOPNOTSUPP;
MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_id);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rl.c b/drivers/net/ethernet/mellanox/mlx5/core/rl.c
index 9f8b4005f4bd..e393391966e0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/rl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/rl.c
@@ -34,6 +34,64 @@
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
+bool mlx5_qos_tsar_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy)
+{
+ int cap;
+
+ switch (hierarchy) {
+ case SCHEDULING_HIERARCHY_E_SWITCH:
+ cap = MLX5_CAP_QOS(dev, esw_tsar_type);
+ break;
+ case SCHEDULING_HIERARCHY_NIC:
+ cap = MLX5_CAP_QOS(dev, nic_tsar_type);
+ break;
+ default:
+ return false;
+ }
+
+ switch (type) {
+ case TSAR_ELEMENT_TSAR_TYPE_DWRR:
+ return cap & TSAR_TYPE_CAP_MASK_DWRR;
+ case TSAR_ELEMENT_TSAR_TYPE_ROUND_ROBIN:
+ return cap & TSAR_TYPE_CAP_MASK_ROUND_ROBIN;
+ case TSAR_ELEMENT_TSAR_TYPE_ETS:
+ return cap & TSAR_TYPE_CAP_MASK_ETS;
+ }
+
+ return false;
+}
+
+bool mlx5_qos_element_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy)
+{
+ int cap;
+
+ switch (hierarchy) {
+ case SCHEDULING_HIERARCHY_E_SWITCH:
+ cap = MLX5_CAP_QOS(dev, esw_element_type);
+ break;
+ case SCHEDULING_HIERARCHY_NIC:
+ cap = MLX5_CAP_QOS(dev, nic_element_type);
+ break;
+ default:
+ return false;
+ }
+
+ switch (type) {
+ case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR:
+ return cap & ELEMENT_TYPE_CAP_MASK_TSAR;
+ case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT:
+ return cap & ELEMENT_TYPE_CAP_MASK_VPORT;
+ case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC:
+ return cap & ELEMENT_TYPE_CAP_MASK_VPORT_TC;
+ case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC:
+ return cap & ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC;
+ case SCHEDULING_CONTEXT_ELEMENT_TYPE_QUEUE_GROUP:
+ return cap & ELEMENT_TYPE_CAP_MASK_QUEUE_GROUP;
+ }
+
+ return false;
+}
+
/* Scheduling element fw management */
int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
void *ctx, u32 *element_id)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c
index b27bb4106532..a897cdc60fdb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
#define MLX5HWS_ACTION_METER_INIT_COLOR_OFFSET 1
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_action.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h
index bf5c1b241006..e8f562c31826 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_action.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_ACTION_H_
-#define MLX5HWS_ACTION_H_
+#ifndef HWS_ACTION_H_
+#define HWS_ACTION_H_
/* Max number of STEs needed for a rule (including match) */
#define MLX5HWS_ACTION_MAX_STE 20
@@ -304,4 +304,4 @@ mlx5hws_action_apply_setter(struct mlx5hws_actions_apply_data *apply,
htonl(num_of_actions << 29);
}
-#endif /* MLX5HWS_ACTION_H_ */
+#endif /* HWS_ACTION_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_buddy.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.c
index e6ed66202a40..b9aef80ba094 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_buddy.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
-#include "mlx5hws_buddy.h"
+#include "internal.h"
+#include "buddy.h"
static int hws_buddy_init(struct mlx5hws_buddy_mem *buddy, u32 max_order)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_buddy.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.h
index 338c44bbedaf..ef6b223677aa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_buddy.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_BUDDY_H_
-#define MLX5HWS_BUDDY_H_
+#ifndef HWS_BUDDY_H_
+#define HWS_BUDDY_H_
struct mlx5hws_buddy_mem {
unsigned long **bitmap;
@@ -18,4 +18,4 @@ int mlx5hws_buddy_alloc_mem(struct mlx5hws_buddy_mem *buddy, u32 order);
void mlx5hws_buddy_free_mem(struct mlx5hws_buddy_mem *buddy, u32 seg, u32 order);
-#endif /* MLX5HWS_BUDDY_H_ */
+#endif /* HWS_BUDDY_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c
index 8f3a6f9d703d..baacf662c0ab 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
static u16 hws_bwc_gen_queue_idx(struct mlx5hws_context *ctx)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h
index 4fe8c32d8fbe..0b745968e21e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_BWC_H_
-#define MLX5HWS_BWC_H_
+#ifndef HWS_BWC_H_
+#define HWS_BWC_H_
#define MLX5HWS_BWC_MATCHER_INIT_SIZE_LOG 1
#define MLX5HWS_BWC_MATCHER_SIZE_LOG_STEP 1
@@ -70,4 +70,4 @@ static inline u16 mlx5hws_bwc_get_queue_id(struct mlx5hws_context *ctx, u16 idx)
return idx + mlx5hws_bwc_queues(ctx);
}
-#endif /* MLX5HWS_BWC_H_ */
+#endif /* HWS_BWC_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c
index 601fad5fc54a..c00010ca86bd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
bool mlx5hws_bwc_match_params_is_complex(struct mlx5hws_context *ctx,
u8 match_criteria_enable,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.h
index 068ee8118609..340f0688e394 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_BWC_COMPLEX_H_
-#define MLX5HWS_BWC_COMPLEX_H_
+#ifndef HWS_BWC_COMPLEX_H_
+#define HWS_BWC_COMPLEX_H_
bool mlx5hws_bwc_match_params_is_complex(struct mlx5hws_context *ctx,
u8 match_criteria_enable,
@@ -26,4 +26,4 @@ int mlx5hws_bwc_rule_create_complex(struct mlx5hws_bwc_rule *bwc_rule,
int mlx5hws_bwc_rule_destroy_complex(struct mlx5hws_bwc_rule *bwc_rule);
-#endif /* MLX5HWS_BWC_COMPLEX_H_ */
+#endif /* HWS_BWC_COMPLEX_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c
index 2c7b14172049..c00c138c3366 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
static enum mlx5_ifc_flow_destination_type
hws_cmd_dest_type_to_ifc_dest_type(enum mlx5_flow_destination_type type)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h
index 2fbcf4ff571a..434f62b0904e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_cmd.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_CMD_H_
-#define MLX5HWS_CMD_H_
+#ifndef HWS_CMD_H_
+#define HWS_CMD_H_
#define WIRE_PORT 0xFFFF
@@ -358,4 +358,4 @@ int mlx5hws_cmd_allow_other_vhca_access(struct mlx5_core_dev *mdev,
int mlx5hws_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_function,
u16 vport_number, u16 *gvmi);
-#endif /* MLX5HWS_CMD_H_ */
+#endif /* HWS_CMD_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_context.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c
index 00e4fdf4a558..fd48b05e91e0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_context.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. */
-#include "mlx5hws_internal.h"
+#include "internal.h"
bool mlx5hws_context_cap_dynamic_reparse(struct mlx5hws_context *ctx)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_context.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h
index 8ab548aa402b..47f5cc8de73f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_context.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_CONTEXT_H_
-#define MLX5HWS_CONTEXT_H_
+#ifndef HWS_CONTEXT_H_
+#define HWS_CONTEXT_H_
enum mlx5hws_context_flags {
MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT = 1 << 0,
@@ -62,4 +62,4 @@ bool mlx5hws_context_cap_dynamic_reparse(struct mlx5hws_context *ctx);
u8 mlx5hws_context_get_reparse_mode(struct mlx5hws_context *ctx);
-#endif /* MLX5HWS_CONTEXT_H_ */
+#endif /* HWS_CONTEXT_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_debug.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c
index 2b8c5a4e1c4c..5b200b4bc1a8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_debug.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c
@@ -5,7 +5,7 @@
#include <linux/kernel.h>
#include <linux/seq_file.h>
#include <linux/version.h>
-#include "mlx5hws_internal.h"
+#include "internal.h"
static int
hws_debug_dump_matcher_template_definer(struct seq_file *f,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_debug.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.h
index b93a536035d9..e44e7ae28f93 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_debug.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_DEBUG_H_
-#define MLX5HWS_DEBUG_H_
+#ifndef HWS_DEBUG_H_
+#define HWS_DEBUG_H_
#define HWS_DEBUG_FORMAT_VERSION "1.0"
@@ -37,4 +37,4 @@ mlx5hws_debug_icm_to_idx(u64 icm_addr)
void mlx5hws_debug_init_dump(struct mlx5hws_context *ctx);
void mlx5hws_debug_uninit_dump(struct mlx5hws_context *ctx);
-#endif /* MLX5HWS_DEBUG_H_ */
+#endif /* HWS_DEBUG_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c
index 3f4c58bada37..8fe96eb76baf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
/* Pattern tunnel Layer bits. */
#define MLX5_FLOW_LAYER_VXLAN BIT(12)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h
index 2f6a7df4021c..9432d5084def 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_DEFINER_H_
-#define MLX5HWS_DEFINER_H_
+#ifndef HWS_DEFINER_H_
+#define HWS_DEFINER_H_
/* Max available selecotrs */
#define DW_SELECTORS 9
@@ -831,4 +831,4 @@ mlx5hws_definer_conv_match_params_to_compressed_fc(struct mlx5hws_context *ctx,
u32 *match_param,
int *fc_sz);
-#endif /* MLX5HWS_DEFINER_H_ */
+#endif /* HWS_DEFINER_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_internal.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/internal.h
index 5643be1cd5bf..3c8635f286ce 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_internal.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/internal.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_INTERNAL_H_
-#define MLX5HWS_INTERNAL_H_
+#ifndef HWS_INTERNAL_H_
+#define HWS_INTERNAL_H_
#include <linux/mlx5/transobj.h>
#include <linux/mlx5/vport.h>
@@ -10,22 +10,22 @@
#include "wq.h"
#include "lib/mlx5.h"
-#include "mlx5hws_prm.h"
+#include "prm.h"
#include "mlx5hws.h"
-#include "mlx5hws_pool.h"
-#include "mlx5hws_vport.h"
-#include "mlx5hws_context.h"
-#include "mlx5hws_table.h"
-#include "mlx5hws_send.h"
-#include "mlx5hws_rule.h"
-#include "mlx5hws_cmd.h"
-#include "mlx5hws_action.h"
-#include "mlx5hws_definer.h"
-#include "mlx5hws_matcher.h"
-#include "mlx5hws_debug.h"
-#include "mlx5hws_pat_arg.h"
-#include "mlx5hws_bwc.h"
-#include "mlx5hws_bwc_complex.h"
+#include "pool.h"
+#include "vport.h"
+#include "context.h"
+#include "table.h"
+#include "send.h"
+#include "rule.h"
+#include "cmd.h"
+#include "action.h"
+#include "definer.h"
+#include "matcher.h"
+#include "debug.h"
+#include "pat_arg.h"
+#include "bwc.h"
+#include "bwc_complex.h"
#define W_SIZE 2
#define DW_SIZE 4
@@ -56,4 +56,4 @@ static inline unsigned long align(unsigned long val, unsigned long align)
return (val + align - 1) & ~(align - 1);
}
-#endif /* MLX5HWS_INTERNAL_H_ */
+#endif /* HWS_INTERNAL_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_matcher.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c
index 61a1155d4b4f..1bb3a6f8c3cd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_matcher.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
enum mlx5hws_matcher_rtc_type {
HWS_MATCHER_RTC_TYPE_MATCH,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_matcher.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.h
index 125391d1a114..81ff487f57be 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_matcher.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.h
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#ifndef MLX5HWS_MATCHER_H_
-#define MLX5HWS_MATCHER_H_
+#ifndef HWS_MATCHER_H_
+#define HWS_MATCHER_H_
/* We calculated that concatenating a collision table to the main table with
* 3% of the main table rows will be enough resources for high insertion
@@ -104,4 +104,4 @@ static inline bool mlx5hws_matcher_is_insert_by_idx(struct mlx5hws_matcher *matc
return matcher->attr.insert_mode == MLX5HWS_MATCHER_INSERT_BY_INDEX;
}
-#endif /* MLX5HWS_MATCHER_H_ */
+#endif /* HWS_MATCHER_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pat_arg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c
index e084a5cbf81f..06db5e4726ae 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pat_arg.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
enum mlx5hws_arg_chunk_size
mlx5hws_arg_data_size_to_arg_log_size(u16 data_size)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pat_arg.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h
index 27ca93385b08..27ca93385b08 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pat_arg.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c
index a8a63e3278be..fed2d913f3b8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
-#include "mlx5hws_buddy.h"
+#include "internal.h"
+#include "buddy.h"
static void hws_pool_free_one_resource(struct mlx5hws_pool_resource *resource)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pool.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.h
index 621298b352b2..621298b352b2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_pool.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_prm.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h
index de92cecbeb92..de92cecbeb92 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_prm.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_rule.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c
index 8a011b958b43..e20c67a04203 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_rule.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
static void hws_rule_skip(struct mlx5hws_matcher *matcher,
struct mlx5hws_match_template *mt,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_rule.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.h
index 495cdd17e9f3..495cdd17e9f3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_rule.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c
index 6d443e6ee8d9..424797b6d802 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
#include "lib/clock.h"
enum { CQ_OK = 0, CQ_EMPTY = -1, CQ_POLL_ERR = -2 };
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h
index b50825d6dc53..b50825d6dc53 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_table.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c
index 8c063a8d87d7..9576e02d00c3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_table.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
u32 mlx5hws_table_get_id(struct mlx5hws_table *tbl)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_table.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h
index dd50420eec9e..dd50420eec9e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_table.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_vport.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/vport.c
index faf42421c43f..d8e382b9fa61 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/vport.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
-#include "mlx5hws_internal.h"
+#include "internal.h"
int mlx5hws_vport_init_vports(struct mlx5hws_context *ctx)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_vport.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/vport.h
index 0912fc166b3a..0912fc166b3a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_vport.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/vport.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_action.c
index 2ebb61ef3ea9..2ebb61ef3ea9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_action.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_arg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_arg.c
index 01ed6442095d..01ed6442095d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_arg.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_arg.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_buddy.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_buddy.c
index fe228d948b47..fe228d948b47 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_buddy.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_buddy.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_cmd.c
index baefb9a3fa05..baefb9a3fa05 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_cmd.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c
index 030a5776c937..030a5776c937 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.h
index 57c6b363b870..57c6b363b870 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_definer.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_definer.c
index d5ea97751945..d5ea97751945 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_definer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_definer.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c
index 3d74109f8230..3d74109f8230 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_fw.c
index f05ef0cd54ba..f05ef0cd54ba 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_fw.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c
index 0b5af9f3f605..0b5af9f3f605 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_matcher.c
index 0726848eb3ff..0726848eb3ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_matcher.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ptrn.c
index 8ca534ef5d03..8ca534ef5d03 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ptrn.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_rule.c
index d1db04baa1fa..d1db04baa1fa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_rule.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c
index 6fa06ba2d346..6fa06ba2d346 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c
index e94fbb015efa..e94fbb015efa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h
index 54a6619c3ecb..54a6619c3ecb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c
index e9f6c7ed7a7b..e9f6c7ed7a7b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c
index 1d49704b9542..1d49704b9542 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h
index e2fc69867088..e2fc69867088 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v2.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c
index 808b013cf48c..808b013cf48c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v2.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_table.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_table.c
index 69294a66fd7f..69294a66fd7f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_table.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_table.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_types.h
index 7618c6147f86..7618c6147f86 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_types.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c
index 833cb68c744f..4b349d4005e4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c
@@ -256,6 +256,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
{
struct mlx5dr_domain *domain = ns->fs_dr_domain.dr_domain;
struct mlx5dr_action_dest *term_actions;
+ struct mlx5_pkt_reformat *pkt_reformat;
struct mlx5dr_match_parameters params;
struct mlx5_core_dev *dev = ns->dev;
struct mlx5dr_action **fs_dr_actions;
@@ -332,18 +333,19 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
bool is_decap;
- if (fte->act_dests.action.pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) {
+ pkt_reformat = fte->act_dests.action.pkt_reformat;
+ if (pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) {
err = -EINVAL;
mlx5dr_err(domain, "FW-owned reformat can't be used in SW rule\n");
goto free_actions;
}
- is_decap = fte->act_dests.action.pkt_reformat->reformat_type ==
+ is_decap = pkt_reformat->reformat_type ==
MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
if (is_decap)
actions[num_actions++] =
- fte->act_dests.action.pkt_reformat->action.dr_action;
+ pkt_reformat->fs_dr_action.dr_action;
else
delay_encap_set = true;
}
@@ -370,9 +372,11 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
actions[num_actions++] = tmp_action;
}
- if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
- actions[num_actions++] =
- fte->act_dests.action.modify_hdr->action.dr_action;
+ if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
+ struct mlx5_modify_hdr *modify_hdr = fte->act_dests.action.modify_hdr;
+
+ actions[num_actions++] = modify_hdr->fs_dr_action.dr_action;
+ }
if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
tmp_action = create_action_push_vlan(domain, &fte->act_dests.action.vlan[0]);
@@ -395,8 +399,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
}
if (delay_encap_set)
- actions[num_actions++] =
- fte->act_dests.action.pkt_reformat->action.dr_action;
+ actions[num_actions++] = pkt_reformat->fs_dr_action.dr_action;
/* The order of the actions below is not important */
@@ -458,9 +461,11 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
term_actions[num_term_actions].dest = tmp_action;
if (dst->dest_attr.vport.flags &
- MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
+ MLX5_FLOW_DEST_VPORT_REFORMAT_ID) {
+ pkt_reformat = dst->dest_attr.vport.pkt_reformat;
term_actions[num_term_actions].reformat =
- dst->dest_attr.vport.pkt_reformat->action.dr_action;
+ pkt_reformat->fs_dr_action.dr_action;
+ }
num_term_actions++;
break;
@@ -671,7 +676,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
}
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
- pkt_reformat->action.dr_action = action;
+ pkt_reformat->fs_dr_action.dr_action = action;
return 0;
}
@@ -679,7 +684,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
static void mlx5_cmd_dr_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns,
struct mlx5_pkt_reformat *pkt_reformat)
{
- mlx5dr_action_destroy(pkt_reformat->action.dr_action);
+ mlx5dr_action_destroy(pkt_reformat->fs_dr_action.dr_action);
}
static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
@@ -702,7 +707,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
}
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
- modify_hdr->action.dr_action = action;
+ modify_hdr->fs_dr_action.dr_action = action;
return 0;
}
@@ -710,7 +715,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
static void mlx5_cmd_dr_modify_header_dealloc(struct mlx5_flow_root_namespace *ns,
struct mlx5_modify_hdr *modify_hdr)
{
- mlx5dr_action_destroy(modify_hdr->action.dr_action);
+ mlx5dr_action_destroy(modify_hdr->fs_dr_action.dr_action);
}
static int
@@ -836,7 +841,7 @@ int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat
case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
case MLX5_REFORMAT_TYPE_INSERT_HDR:
- return mlx5dr_action_get_pkt_reformat_id(pkt_reformat->action.dr_action);
+ return mlx5dr_action_get_pkt_reformat_id(pkt_reformat->fs_dr_action.dr_action);
}
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.h
index 99a3b2eff6b8..99a3b2eff6b8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h
index fb078fa0f0cc..fb078fa0f0cc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr_ste_v1.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr_ste_v1.h
index ca3b0f1453a7..ca3b0f1453a7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5_ifc_dr_ste_v1.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr_ste_v1.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h
index 3ac7dc67509f..3ac7dc67509f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/wq.h b/drivers/net/ethernet/mellanox/mlx5/core/wq.h
index e4ef1d24a3ad..6debb8fd33ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/wq.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/wq.h
@@ -244,7 +244,7 @@ static inline struct mlx5_cqe64 *mlx5_cqwq_get_cqe(struct mlx5_cqwq *wq)
}
static inline
-struct mlx5_cqe64 *mlx5_cqwq_get_cqe_enahnced_comp(struct mlx5_cqwq *wq)
+struct mlx5_cqe64 *mlx5_cqwq_get_cqe_enhanced_comp(struct mlx5_cqwq *wq)
{
u8 sw_validity_iteration_count = mlx5_cqwq_get_wrap_cnt(wq) & 0xff;
u32 ci = mlx5_cqwq_get_ci(wq);
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
index 385a56ac7348..fb2e5b844c15 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(acpi, mlxbf_gige_acpi_match);
static struct platform_driver mlxbf_gige_driver = {
.probe = mlxbf_gige_probe,
- .remove_new = mlxbf_gige_remove,
+ .remove = mlxbf_gige_remove,
.shutdown = mlxbf_gige_shutdown,
.driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
index 947500f8ed71..7aa1a462a103 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
@@ -67,7 +67,7 @@ static bool mlxsw_afk_blocks_check(struct mlxsw_afk *mlxsw_afk)
for (j = 0; j < block->instances_count; j++) {
const struct mlxsw_afk_element_info *elinfo;
- struct mlxsw_afk_element_inst *elinst;
+ const struct mlxsw_afk_element_inst *elinst;
elinst = &block->instances[j];
elinfo = &mlxsw_afk_element_infos[elinst->element];
@@ -154,7 +154,7 @@ static void mlxsw_afk_picker_count_hits(struct mlxsw_afk *mlxsw_afk,
const struct mlxsw_afk_block *block = &mlxsw_afk->blocks[i];
for (j = 0; j < block->instances_count; j++) {
- struct mlxsw_afk_element_inst *elinst;
+ const struct mlxsw_afk_element_inst *elinst;
elinst = &block->instances[j];
if (elinst->element == element) {
@@ -386,7 +386,7 @@ mlxsw_afk_block_elinst_get(const struct mlxsw_afk_block *block,
int i;
for (i = 0; i < block->instances_count; i++) {
- struct mlxsw_afk_element_inst *elinst;
+ const struct mlxsw_afk_element_inst *elinst;
elinst = &block->instances[i];
if (elinst->element == element)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
index 98a05598178b..5aa1afb3f2ca 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
@@ -117,7 +117,7 @@ struct mlxsw_afk_element_inst { /* element instance in actual block */
struct mlxsw_afk_block {
u16 encoding; /* block ID */
- struct mlxsw_afk_element_inst *instances;
+ const struct mlxsw_afk_element_inst *instances;
unsigned int instances_count;
bool high_entropy;
};
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
index eaad78605602..6fe185ea6732 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
@@ -7,7 +7,7 @@
#include "item.h"
#include "core_acl_flex_keys.h"
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x00, 2),
MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x02, 4),
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
@@ -15,7 +15,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x00, 2),
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x02, 4),
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
@@ -23,27 +23,27 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x02, 2),
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x0C, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 16, 16),
MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4),
MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 16, 16),
MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2),
MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8),
@@ -51,35 +51,35 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12),
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3),
MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16),
MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x00, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x00, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x00, 4),
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x00, 4),
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16),
};
@@ -124,90 +124,90 @@ const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
.clear_block = mlxsw_sp1_afk_clear_block,
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2),
MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 8, -1, true), /* RX_ACL_SYSTEM_PORT */
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6),
MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2),
MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8),
MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5[] = {
MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER, 0x04, 20, 11, 0, true),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_0_3, 0x00, 0, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_4_7, 0x00, 0, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x00, 0, 3, 0, true),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16),
MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */
MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 0, 16),
};
@@ -319,16 +319,16 @@ const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
.clear_block = mlxsw_sp2_afk_clear_block,
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 18, 12),
MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 9, -1, true), /* RX_ACL_SYSTEM_PORT */
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER, 0x04, 20, 12),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x00, 0, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
};
diff --git a/drivers/net/ethernet/meta/Kconfig b/drivers/net/ethernet/meta/Kconfig
index 85519690b837..831921b9d4d5 100644
--- a/drivers/net/ethernet/meta/Kconfig
+++ b/drivers/net/ethernet/meta/Kconfig
@@ -23,6 +23,7 @@ config FBNIC
depends on !S390
depends on MAX_SKB_FRAGS < 22
depends on PCI_MSI
+ depends on PTP_1588_CLOCK_OPTIONAL
select NET_DEVLINK
select PAGE_POOL
select PHYLINK
diff --git a/drivers/net/ethernet/meta/fbnic/Makefile b/drivers/net/ethernet/meta/fbnic/Makefile
index ed4533a73c57..239b2258ec65 100644
--- a/drivers/net/ethernet/meta/fbnic/Makefile
+++ b/drivers/net/ethernet/meta/fbnic/Makefile
@@ -7,10 +7,13 @@
obj-$(CONFIG_FBNIC) += fbnic.o
-fbnic-y := fbnic_devlink.o \
+fbnic-y := fbnic_csr.o \
+ fbnic_debugfs.o \
+ fbnic_devlink.o \
fbnic_ethtool.o \
fbnic_fw.o \
fbnic_hw_stats.o \
+ fbnic_hwmon.o \
fbnic_irq.o \
fbnic_mac.o \
fbnic_netdev.o \
@@ -18,4 +21,5 @@ fbnic-y := fbnic_devlink.o \
fbnic_phylink.o \
fbnic_rpc.o \
fbnic_tlv.o \
- fbnic_txrx.o
+ fbnic_txrx.o \
+ fbnic_time.o
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h
index 0f9e8d79461c..706ae6104c8e 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic.h
@@ -6,6 +6,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/ptp_clock_kernel.h>
#include <linux/types.h>
#include <linux/workqueue.h>
@@ -18,6 +19,8 @@
struct fbnic_dev {
struct device *dev;
struct net_device *netdev;
+ struct dentry *dbg_fbd;
+ struct device *hwmon;
u32 __iomem *uc_addr0;
u32 __iomem *uc_addr4;
@@ -30,6 +33,7 @@ struct fbnic_dev {
struct fbnic_fw_mbx mbx[FBNIC_IPC_MBX_INDICES];
struct fbnic_fw_cap fw_cap;
+ struct fbnic_fw_completion *cmpl_data;
/* Lock protecting Tx Mailbox queue to prevent possible races */
spinlock_t fw_tx_lock;
@@ -45,10 +49,21 @@ struct fbnic_dev {
struct fbnic_act_tcam act_tcam[FBNIC_RPC_TCAM_ACT_NUM_ENTRIES];
struct fbnic_mac_addr mac_addr[FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES];
u8 mac_addr_boundary;
+ u8 tce_tcam_last;
/* Number of TCQs/RCQs available on hardware */
u16 max_num_queues;
+ /* Lock protecting writes to @time_high, @time_offset of fbnic_netdev,
+ * and the HW time CSR machinery.
+ */
+ spinlock_t time_lock;
+ /* Externally accessible PTP clock, may be NULL */
+ struct ptp_clock *ptp;
+ struct ptp_clock_info ptp_info;
+ /* Last @time_high refresh time in jiffies (to catch stalls) */
+ unsigned long last_read;
+
/* Local copy of hardware statistics */
struct fbnic_hw_stats hw_stats;
};
@@ -127,6 +142,9 @@ void fbnic_devlink_unregister(struct fbnic_dev *fbd);
int fbnic_fw_enable_mbx(struct fbnic_dev *fbd);
void fbnic_fw_disable_mbx(struct fbnic_dev *fbd);
+void fbnic_hwmon_register(struct fbnic_dev *fbd);
+void fbnic_hwmon_unregister(struct fbnic_dev *fbd);
+
int fbnic_pcs_irq_enable(struct fbnic_dev *fbd);
void fbnic_pcs_irq_disable(struct fbnic_dev *fbd);
@@ -139,6 +157,14 @@ int fbnic_alloc_irqs(struct fbnic_dev *fbd);
void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version,
const size_t str_sz);
+void fbnic_dbg_fbd_init(struct fbnic_dev *fbd);
+void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd);
+void fbnic_dbg_init(void);
+void fbnic_dbg_exit(void);
+
+void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version);
+int fbnic_csr_regs_len(struct fbnic_dev *fbd);
+
enum fbnic_boards {
fbnic_board_asic
};
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.c b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c
new file mode 100644
index 000000000000..2118901b25e9
--- /dev/null
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#include "fbnic.h"
+
+#define FBNIC_BOUNDS(section) { \
+ .start = FBNIC_CSR_START_##section, \
+ .end = FBNIC_CSR_END_##section + 1, \
+}
+
+struct fbnic_csr_bounds {
+ u32 start;
+ u32 end;
+};
+
+static const struct fbnic_csr_bounds fbnic_csr_sects[] = {
+ FBNIC_BOUNDS(INTR),
+ FBNIC_BOUNDS(INTR_CQ),
+ FBNIC_BOUNDS(QM_TX),
+ FBNIC_BOUNDS(QM_RX),
+ FBNIC_BOUNDS(TCE),
+ FBNIC_BOUNDS(TCE_RAM),
+ FBNIC_BOUNDS(TMI),
+ FBNIC_BOUNDS(PTP),
+ FBNIC_BOUNDS(RXB),
+ FBNIC_BOUNDS(RPC),
+ FBNIC_BOUNDS(FAB),
+ FBNIC_BOUNDS(MASTER),
+ FBNIC_BOUNDS(PCS),
+ FBNIC_BOUNDS(RSFEC),
+ FBNIC_BOUNDS(MAC_MAC),
+ FBNIC_BOUNDS(SIG),
+ FBNIC_BOUNDS(PUL_USER),
+ FBNIC_BOUNDS(QUEUE),
+ FBNIC_BOUNDS(RPC_RAM),
+};
+
+#define FBNIC_RPC_TCAM_ACT_DW_PER_ENTRY 14
+#define FBNIC_RPC_TCAM_ACT_NUM_ENTRIES 64
+
+#define FBNIC_RPC_TCAM_MACDA_DW_PER_ENTRY 4
+#define FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES 32
+
+#define FBNIC_RPC_TCAM_OUTER_IPSRC_DW_PER_ENTRY 9
+#define FBNIC_RPC_TCAM_OUTER_IPSRC_NUM_ENTRIES 8
+
+#define FBNIC_RPC_TCAM_OUTER_IPDST_DW_PER_ENTRY 9
+#define FBNIC_RPC_TCAM_OUTER_IPDST_NUM_ENTRIES 8
+
+#define FBNIC_RPC_TCAM_IPSRC_DW_PER_ENTRY 9
+#define FBNIC_RPC_TCAM_IPSRC_NUM_ENTRIES 8
+
+#define FBNIC_RPC_TCAM_IPDST_DW_PER_ENTRY 9
+#define FBNIC_RPC_TCAM_IPDST_NUM_ENTRIES 8
+
+#define FBNIC_RPC_RSS_TBL_DW_PER_ENTRY 2
+#define FBNIC_RPC_RSS_TBL_NUM_ENTRIES 256
+
+static void fbnic_csr_get_regs_rpc_ram(struct fbnic_dev *fbd, u32 **data_p)
+{
+ u32 start = FBNIC_CSR_START_RPC_RAM;
+ u32 end = FBNIC_CSR_END_RPC_RAM;
+ u32 *data = *data_p;
+ u32 i, j;
+
+ *(data++) = start;
+ *(data++) = end - 1;
+
+ /* FBNIC_RPC_TCAM_ACT */
+ for (i = 0; i < FBNIC_RPC_TCAM_ACT_NUM_ENTRIES; i++) {
+ for (j = 0; j < FBNIC_RPC_TCAM_ACT_DW_PER_ENTRY; j++)
+ *(data++) = rd32(fbd, FBNIC_RPC_TCAM_ACT(i, j));
+ }
+
+ /* FBNIC_RPC_TCAM_MACDA */
+ for (i = 0; i < FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES; i++) {
+ for (j = 0; j < FBNIC_RPC_TCAM_MACDA_DW_PER_ENTRY; j++)
+ *(data++) = rd32(fbd, FBNIC_RPC_TCAM_MACDA(i, j));
+ }
+
+ /* FBNIC_RPC_TCAM_OUTER_IPSRC */
+ for (i = 0; i < FBNIC_RPC_TCAM_OUTER_IPSRC_NUM_ENTRIES; i++) {
+ for (j = 0; j < FBNIC_RPC_TCAM_OUTER_IPSRC_DW_PER_ENTRY; j++)
+ *(data++) = rd32(fbd, FBNIC_RPC_TCAM_OUTER_IPSRC(i, j));
+ }
+
+ /* FBNIC_RPC_TCAM_OUTER_IPDST */
+ for (i = 0; i < FBNIC_RPC_TCAM_OUTER_IPDST_NUM_ENTRIES; i++) {
+ for (j = 0; j < FBNIC_RPC_TCAM_OUTER_IPDST_DW_PER_ENTRY; j++)
+ *(data++) = rd32(fbd, FBNIC_RPC_TCAM_OUTER_IPDST(i, j));
+ }
+
+ /* FBNIC_RPC_TCAM_IPSRC */
+ for (i = 0; i < FBNIC_RPC_TCAM_IPSRC_NUM_ENTRIES; i++) {
+ for (j = 0; j < FBNIC_RPC_TCAM_IPSRC_DW_PER_ENTRY; j++)
+ *(data++) = rd32(fbd, FBNIC_RPC_TCAM_IPSRC(i, j));
+ }
+
+ /* FBNIC_RPC_TCAM_IPDST */
+ for (i = 0; i < FBNIC_RPC_TCAM_IPDST_NUM_ENTRIES; i++) {
+ for (j = 0; j < FBNIC_RPC_TCAM_IPDST_DW_PER_ENTRY; j++)
+ *(data++) = rd32(fbd, FBNIC_RPC_TCAM_IPDST(i, j));
+ }
+
+ /* FBNIC_RPC_RSS_TBL */
+ for (i = 0; i < FBNIC_RPC_RSS_TBL_NUM_ENTRIES; i++) {
+ for (j = 0; j < FBNIC_RPC_RSS_TBL_DW_PER_ENTRY; j++)
+ *(data++) = rd32(fbd, FBNIC_RPC_RSS_TBL(i, j));
+ }
+
+ *data_p = data;
+}
+
+void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version)
+{
+ const struct fbnic_csr_bounds *bound;
+ u32 *start = data;
+ int i, j;
+
+ *regs_version = 1u;
+
+ /* Skip RPC_RAM section which cannot be dumped linearly */
+ for (i = 0, bound = fbnic_csr_sects;
+ i < ARRAY_SIZE(fbnic_csr_sects) - 1; i++, ++bound) {
+ *(data++) = bound->start;
+ *(data++) = bound->end - 1;
+ for (j = bound->start; j < bound->end; j++)
+ *(data++) = rd32(fbd, j);
+ }
+
+ /* Dump the RPC_RAM as special case registers */
+ fbnic_csr_get_regs_rpc_ram(fbd, &data);
+
+ WARN_ON(data - start != fbnic_csr_regs_len(fbd));
+}
+
+int fbnic_csr_regs_len(struct fbnic_dev *fbd)
+{
+ int i, len = 0;
+
+ /* Dump includes start and end information of each section
+ * which results in an offset of 2
+ */
+ for (i = 0; i < ARRAY_SIZE(fbnic_csr_sects); i++)
+ len += fbnic_csr_sects[i].end - fbnic_csr_sects[i].start + 2;
+
+ return len;
+}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h
index 21db509acbc1..02bb81b3c506 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h
@@ -397,6 +397,14 @@ enum {
#define FBNIC_TCE_DROP_CTRL_TTI_FRM_DROP_EN CSR_BIT(1)
#define FBNIC_TCE_DROP_CTRL_TTI_TBI_DROP_EN CSR_BIT(2)
+#define FBNIC_TCE_TCAM_IDX2DEST_MAP 0x0404A /* 0x10128 */
+#define FBNIC_TCE_TCAM_IDX2DEST_MAP_DEST_ID_0 CSR_GENMASK(3, 0)
+enum {
+ FBNIC_TCE_TCAM_DEST_MAC = 1,
+ FBNIC_TCE_TCAM_DEST_BMC = 2,
+ FBNIC_TCE_TCAM_DEST_FW = 4,
+};
+
#define FBNIC_TCE_TXB_TX_BMC_Q_CTRL 0x0404B /* 0x1012c */
#define FBNIC_TCE_TXB_BMC_DWRR_CTRL 0x0404C /* 0x10130 */
#define FBNIC_TCE_TXB_BMC_DWRR_CTRL_QUANTUM0 CSR_GENMASK(7, 0)
@@ -407,12 +415,62 @@ enum {
#define FBNIC_TCE_TXB_BMC_DWRR_CTRL_EXT 0x0404F /* 0x1013c */
#define FBNIC_CSR_END_TCE 0x04050 /* CSR section delimiter */
+/* TCE RAM registers */
+#define FBNIC_CSR_START_TCE_RAM 0x04200 /* CSR section delimiter */
+#define FBNIC_TCE_RAM_TCAM(m, n) \
+ (0x04200 + 0x8 * (n) + (m)) /* 0x10800 + 32*n + 4*m */
+#define FBNIC_TCE_RAM_TCAM_MASK CSR_GENMASK(15, 0)
+#define FBNIC_TCE_RAM_TCAM_VALUE CSR_GENMASK(31, 16)
+#define FBNIC_TCE_RAM_TCAM3(n) (0x04218 + (n)) /* 0x010860 + 4*n */
+#define FBNIC_TCE_RAM_TCAM3_DEST_MASK CSR_GENMASK(5, 3)
+#define FBNIC_TCE_RAM_TCAM3_MCQ_MASK CSR_BIT(7)
+#define FBNIC_TCE_RAM_TCAM3_VALIDATE CSR_BIT(31)
+#define FBNIC_CSR_END_TCE_RAM 0x0421F /* CSR section delimiter */
+
/* TMI registers */
#define FBNIC_CSR_START_TMI 0x04400 /* CSR section delimiter */
#define FBNIC_TMI_SOP_PROT_CTRL 0x04400 /* 0x11000 */
#define FBNIC_TMI_DROP_CTRL 0x04401 /* 0x11004 */
#define FBNIC_TMI_DROP_CTRL_EN CSR_BIT(0)
#define FBNIC_CSR_END_TMI 0x0443f /* CSR section delimiter */
+
+/* Precision Time Protocol Registers */
+#define FBNIC_CSR_START_PTP 0x04800 /* CSR section delimiter */
+#define FBNIC_PTP_REG_BASE 0x04800 /* 0x12000 */
+
+#define FBNIC_PTP_CTRL 0x04800 /* 0x12000 */
+#define FBNIC_PTP_CTRL_EN CSR_BIT(0)
+#define FBNIC_PTP_CTRL_MONO_EN CSR_BIT(4)
+#define FBNIC_PTP_CTRL_TQS_OUT_EN CSR_BIT(8)
+#define FBNIC_PTP_CTRL_MAC_OUT_IVAL CSR_GENMASK(16, 12)
+#define FBNIC_PTP_CTRL_TICK_IVAL CSR_GENMASK(23, 20)
+
+#define FBNIC_PTP_ADJUST 0x04801 /* 0x12004 */
+#define FBNIC_PTP_ADJUST_INIT CSR_BIT(0)
+#define FBNIC_PTP_ADJUST_SUB_NUDGE CSR_BIT(8)
+#define FBNIC_PTP_ADJUST_ADD_NUDGE CSR_BIT(16)
+#define FBNIC_PTP_ADJUST_ADDEND_SET CSR_BIT(24)
+
+#define FBNIC_PTP_INIT_HI 0x04802 /* 0x12008 */
+#define FBNIC_PTP_INIT_LO 0x04803 /* 0x1200c */
+
+#define FBNIC_PTP_NUDGE_NS 0x04804 /* 0x12010 */
+#define FBNIC_PTP_NUDGE_SUBNS 0x04805 /* 0x12014 */
+
+#define FBNIC_PTP_ADD_VAL_NS 0x04806 /* 0x12018 */
+#define FBNIC_PTP_ADD_VAL_NS_MASK CSR_GENMASK(15, 0)
+#define FBNIC_PTP_ADD_VAL_SUBNS 0x04807 /* 0x1201c */
+
+#define FBNIC_PTP_CTR_VAL_HI 0x04808 /* 0x12020 */
+#define FBNIC_PTP_CTR_VAL_LO 0x04809 /* 0x12024 */
+
+#define FBNIC_PTP_MONO_PTP_CTR_HI 0x0480a /* 0x12028 */
+#define FBNIC_PTP_MONO_PTP_CTR_LO 0x0480b /* 0x1202c */
+
+#define FBNIC_PTP_CDC_FIFO_STATUS 0x0480c /* 0x12030 */
+#define FBNIC_PTP_SPARE 0x0480d /* 0x12034 */
+#define FBNIC_CSR_END_PTP 0x0480d /* CSR section delimiter */
+
/* Rx Buffer Registers */
#define FBNIC_CSR_START_RXB 0x08000 /* CSR section delimiter */
enum {
@@ -548,6 +606,7 @@ enum {
};
#define FBNIC_RPC_ACT_TBL0_DMA_HINT CSR_GENMASK(24, 16)
+#define FBNIC_RPC_ACT_TBL0_TS_ENA CSR_BIT(28)
#define FBNIC_RPC_ACT_TBL0_RSS_CTXT_ID CSR_BIT(30)
#define FBNIC_RPC_ACT_TBL1_DEFAULT 0x0840b /* 0x2102c */
@@ -579,6 +638,16 @@ enum {
FBNIC_RPC_RSS_KEY_DWORD_LEN * 32 - \
FBNIC_RPC_RSS_KEY_BIT_LEN)
+#define FBNIC_RPC_CNTR_TCP_OPT_ERR 0x0849e /* 0x21278 */
+#define FBNIC_RPC_CNTR_UNKN_ETYPE 0x0849f /* 0x2127c */
+#define FBNIC_RPC_CNTR_IPV4_FRAG 0x084a0 /* 0x21280 */
+#define FBNIC_RPC_CNTR_IPV6_FRAG 0x084a1 /* 0x21284 */
+#define FBNIC_RPC_CNTR_IPV4_ESP 0x084a2 /* 0x21288 */
+#define FBNIC_RPC_CNTR_IPV6_ESP 0x084a3 /* 0x2128c */
+#define FBNIC_RPC_CNTR_UNKN_EXT_HDR 0x084a4 /* 0x21290 */
+#define FBNIC_RPC_CNTR_OUT_OF_HDR_ERR 0x084a5 /* 0x21294 */
+#define FBNIC_RPC_CNTR_OVR_SIZE_ERR 0x084a6 /* 0x21298 */
+
#define FBNIC_RPC_TCAM_MACDA_VALIDATE 0x0852d /* 0x214b4 */
#define FBNIC_CSR_END_RPC 0x0856b /* CSR section delimiter */
@@ -606,6 +675,15 @@ enum {
#define FBNIC_RPC_TCAM_MACDA_VALUE CSR_GENMASK(15, 0)
#define FBNIC_RPC_TCAM_MACDA_MASK CSR_GENMASK(31, 16)
+#define FBNIC_RPC_TCAM_OUTER_IPSRC(m, n)\
+ (0x08c00 + 0x08 * (n) + (m)) /* 0x023000 + 32*n + 4*m */
+#define FBNIC_RPC_TCAM_OUTER_IPDST(m, n)\
+ (0x08c48 + 0x08 * (n) + (m)) /* 0x023120 + 32*n + 4*m */
+#define FBNIC_RPC_TCAM_IPSRC(m, n)\
+ (0x08c90 + 0x08 * (n) + (m)) /* 0x023240 + 32*n + 4*m */
+#define FBNIC_RPC_TCAM_IPDST(m, n)\
+ (0x08cd8 + 0x08 * (n) + (m)) /* 0x023360 + 32*n + 4*m */
+
#define FBNIC_RPC_RSS_TBL(n, m) \
(0x08d20 + 0x100 * (n) + (m)) /* 0x023480 + 1024*n + 4*m */
#define FBNIC_RPC_RSS_TBL_COUNT 2
@@ -624,6 +702,13 @@ enum {
#define FBNIC_MASTER_SPARE_0 0x0C41B /* 0x3106c */
#define FBNIC_CSR_END_MASTER 0x0C452 /* CSR section delimiter */
+/* MAC PCS registers */
+#define FBNIC_CSR_START_PCS 0x10000 /* CSR section delimiter */
+#define FBNIC_CSR_END_PCS 0x10668 /* CSR section delimiter */
+
+#define FBNIC_CSR_START_RSFEC 0x10800 /* CSR section delimiter */
+#define FBNIC_CSR_END_RSFEC 0x108c8 /* CSR section delimiter */
+
/* MAC MAC registers (ASIC only) */
#define FBNIC_CSR_START_MAC_MAC 0x11000 /* CSR section delimiter */
#define FBNIC_MAC_COMMAND_CONFIG 0x11002 /* 0x44008 */
@@ -843,6 +928,43 @@ enum {
#define FBNIC_MAX_QUEUES 128
#define FBNIC_CSR_END_QUEUE (0x40000 + 0x400 * FBNIC_MAX_QUEUES - 1)
+/* PUL User Registers*/
+#define FBNIC_PUL_USER_OB_RD_TLP_CNT_31_0 \
+ 0x3106e /* 0xc41b8 */
+#define FBNIC_PUL_USER_OB_RD_DWORD_CNT_31_0 \
+ 0x31070 /* 0xc41c0 */
+#define FBNIC_PUL_USER_OB_RD_DWORD_CNT_63_32 \
+ 0x31071 /* 0xc41c4 */
+#define FBNIC_PUL_USER_OB_WR_TLP_CNT_31_0 \
+ 0x31072 /* 0xc41c8 */
+#define FBNIC_PUL_USER_OB_WR_TLP_CNT_63_32 \
+ 0x31073 /* 0xc41cc */
+#define FBNIC_PUL_USER_OB_WR_DWORD_CNT_31_0 \
+ 0x31074 /* 0xc41d0 */
+#define FBNIC_PUL_USER_OB_WR_DWORD_CNT_63_32 \
+ 0x31075 /* 0xc41d4 */
+#define FBNIC_PUL_USER_OB_CPL_TLP_CNT_31_0 \
+ 0x31076 /* 0xc41d8 */
+#define FBNIC_PUL_USER_OB_CPL_TLP_CNT_63_32 \
+ 0x31077 /* 0xc41dc */
+#define FBNIC_PUL_USER_OB_CPL_DWORD_CNT_31_0 \
+ 0x31078 /* 0xc41e0 */
+#define FBNIC_PUL_USER_OB_CPL_DWORD_CNT_63_32 \
+ 0x31079 /* 0xc41e4 */
+#define FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_31_0 \
+ 0x3107a /* 0xc41e8 */
+#define FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_63_32 \
+ 0x3107b /* 0xc41ec */
+#define FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_31_0 \
+ 0x3107c /* 0xc41f0 */
+#define FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_63_32 \
+ 0x3107d /* 0xc41f4 */
+#define FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_31_0 \
+ 0x3107e /* 0xc41f8 */
+#define FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_63_32 \
+ 0x3107f /* 0xc41fc */
+#define FBNIC_CSR_END_PUL_USER 0x31080 /* CSR section delimiter */
+
/* BAR 4 CSRs */
/* The IPC mailbox consists of 32 mailboxes, with each mailbox consisting
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c b/drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c
new file mode 100644
index 000000000000..59951b5abdb7
--- /dev/null
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <linux/rtnetlink.h>
+#include <linux/seq_file.h>
+
+#include "fbnic.h"
+
+static struct dentry *fbnic_dbg_root;
+
+static int fbnic_dbg_pcie_stats_show(struct seq_file *s, void *v)
+{
+ struct fbnic_dev *fbd = s->private;
+
+ rtnl_lock();
+ fbnic_get_hw_stats(fbd);
+
+ seq_printf(s, "ob_rd_tlp: %llu\n", fbd->hw_stats.pcie.ob_rd_tlp.value);
+ seq_printf(s, "ob_rd_dword: %llu\n",
+ fbd->hw_stats.pcie.ob_rd_dword.value);
+ seq_printf(s, "ob_wr_tlp: %llu\n", fbd->hw_stats.pcie.ob_wr_tlp.value);
+ seq_printf(s, "ob_wr_dword: %llu\n",
+ fbd->hw_stats.pcie.ob_wr_dword.value);
+ seq_printf(s, "ob_cpl_tlp: %llu\n",
+ fbd->hw_stats.pcie.ob_cpl_tlp.value);
+ seq_printf(s, "ob_cpl_dword: %llu\n",
+ fbd->hw_stats.pcie.ob_cpl_dword.value);
+ seq_printf(s, "ob_rd_no_tag: %llu\n",
+ fbd->hw_stats.pcie.ob_rd_no_tag.value);
+ seq_printf(s, "ob_rd_no_cpl_cred: %llu\n",
+ fbd->hw_stats.pcie.ob_rd_no_cpl_cred.value);
+ seq_printf(s, "ob_rd_no_np_cred: %llu\n",
+ fbd->hw_stats.pcie.ob_rd_no_np_cred.value);
+ rtnl_unlock();
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_pcie_stats);
+
+void fbnic_dbg_fbd_init(struct fbnic_dev *fbd)
+{
+ struct pci_dev *pdev = to_pci_dev(fbd->dev);
+ const char *name = pci_name(pdev);
+
+ fbd->dbg_fbd = debugfs_create_dir(name, fbnic_dbg_root);
+ debugfs_create_file("pcie_stats", 0400, fbd->dbg_fbd, fbd,
+ &fbnic_dbg_pcie_stats_fops);
+}
+
+void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd)
+{
+ debugfs_remove_recursive(fbd->dbg_fbd);
+ fbd->dbg_fbd = NULL;
+}
+
+void fbnic_dbg_init(void)
+{
+ fbnic_dbg_root = debugfs_create_dir(fbnic_driver_name, NULL);
+}
+
+void fbnic_dbg_exit(void)
+{
+ debugfs_remove_recursive(fbnic_dbg_root);
+ fbnic_dbg_root = NULL;
+}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
index 5d980e178941..cc8ca94529ca 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
@@ -6,6 +9,66 @@
#include "fbnic_netdev.h"
#include "fbnic_tlv.h"
+struct fbnic_stat {
+ u8 string[ETH_GSTRING_LEN];
+ unsigned int size;
+ unsigned int offset;
+};
+
+#define FBNIC_STAT_FIELDS(type, name, stat) { \
+ .string = name, \
+ .size = sizeof_field(struct type, stat), \
+ .offset = offsetof(struct type, stat), \
+}
+
+/* Hardware statistics not captured in rtnl_link_stats */
+#define FBNIC_HW_STAT(name, stat) \
+ FBNIC_STAT_FIELDS(fbnic_hw_stats, name, stat)
+
+static const struct fbnic_stat fbnic_gstrings_hw_stats[] = {
+ /* RPC */
+ FBNIC_HW_STAT("rpc_unkn_etype", rpc.unkn_etype),
+ FBNIC_HW_STAT("rpc_unkn_ext_hdr", rpc.unkn_ext_hdr),
+ FBNIC_HW_STAT("rpc_ipv4_frag", rpc.ipv4_frag),
+ FBNIC_HW_STAT("rpc_ipv6_frag", rpc.ipv6_frag),
+ FBNIC_HW_STAT("rpc_ipv4_esp", rpc.ipv4_esp),
+ FBNIC_HW_STAT("rpc_ipv6_esp", rpc.ipv6_esp),
+ FBNIC_HW_STAT("rpc_tcp_opt_err", rpc.tcp_opt_err),
+ FBNIC_HW_STAT("rpc_out_of_hdr_err", rpc.out_of_hdr_err),
+};
+
+#define FBNIC_HW_FIXED_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_stats)
+#define FBNIC_HW_STATS_LEN FBNIC_HW_FIXED_STATS_LEN
+
+static int
+fbnic_get_ts_info(struct net_device *netdev,
+ struct kernel_ethtool_ts_info *tsinfo)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+
+ tsinfo->phc_index = ptp_clock_index(fbn->fbd->ptp);
+
+ tsinfo->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ tsinfo->tx_types =
+ BIT(HWTSTAMP_TX_OFF) |
+ BIT(HWTSTAMP_TX_ON);
+
+ tsinfo->rx_filters =
+ BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
+ BIT(HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
static void
fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
{
@@ -22,6 +85,43 @@ static void fbnic_set_counter(u64 *stat, struct fbnic_stat_counter *counter)
*stat = counter->value;
}
+static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
+{
+ int i;
+
+ switch (sset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < FBNIC_HW_STATS_LEN; i++)
+ ethtool_puts(&data, fbnic_gstrings_hw_stats[i].string);
+ break;
+ }
+}
+
+static int fbnic_get_sset_count(struct net_device *dev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return FBNIC_HW_STATS_LEN;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void fbnic_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct fbnic_net *fbn = netdev_priv(dev);
+ const struct fbnic_stat *stat;
+ int i;
+
+ fbnic_get_hw_stats(fbn->fbd);
+
+ for (i = 0; i < FBNIC_HW_STATS_LEN; i++) {
+ stat = &fbnic_gstrings_hw_stats[i];
+ data[i] = *(u64 *)((u8 *)&fbn->fbd->hw_stats + stat->offset);
+ }
+}
+
static void
fbnic_get_eth_mac_stats(struct net_device *netdev,
struct ethtool_eth_mac_stats *eth_mac_stats)
@@ -64,8 +164,53 @@ fbnic_get_eth_mac_stats(struct net_device *netdev,
&mac_stats->eth_mac.FrameTooLongErrors);
}
+static void fbnic_get_ts_stats(struct net_device *netdev,
+ struct ethtool_ts_stats *ts_stats)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ u64 ts_packets, ts_lost;
+ struct fbnic_ring *ring;
+ unsigned int start;
+ int i;
+
+ ts_stats->pkts = fbn->tx_stats.ts_packets;
+ ts_stats->lost = fbn->tx_stats.ts_lost;
+ for (i = 0; i < fbn->num_tx_queues; i++) {
+ ring = fbn->tx[i];
+ do {
+ start = u64_stats_fetch_begin(&ring->stats.syncp);
+ ts_packets = ring->stats.ts_packets;
+ ts_lost = ring->stats.ts_lost;
+ } while (u64_stats_fetch_retry(&ring->stats.syncp, start));
+ ts_stats->pkts += ts_packets;
+ ts_stats->lost += ts_lost;
+ }
+}
+
+static void fbnic_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *data)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+
+ fbnic_csr_get_regs(fbn->fbd, data, &regs->version);
+}
+
+static int fbnic_get_regs_len(struct net_device *netdev)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+
+ return fbnic_csr_regs_len(fbn->fbd) * sizeof(u32);
+}
+
static const struct ethtool_ops fbnic_ethtool_ops = {
.get_drvinfo = fbnic_get_drvinfo,
+ .get_regs_len = fbnic_get_regs_len,
+ .get_regs = fbnic_get_regs,
+ .get_strings = fbnic_get_strings,
+ .get_ethtool_stats = fbnic_get_ethtool_stats,
+ .get_sset_count = fbnic_get_sset_count,
+ .get_ts_info = fbnic_get_ts_info,
+ .get_ts_stats = fbnic_get_ts_stats,
.get_eth_mac_stats = fbnic_get_eth_mac_stats,
};
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
index 221faf8c6756..7cd8841920e4 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
@@ -44,6 +44,13 @@ struct fbnic_fw_cap {
u8 link_fec;
};
+struct fbnic_fw_completion {
+ struct {
+ s32 millivolts;
+ s32 millidegrees;
+ } tsene;
+};
+
void fbnic_mbx_init(struct fbnic_dev *fbd);
void fbnic_mbx_clean(struct fbnic_dev *fbd);
void fbnic_mbx_poll(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c b/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c
index a0acc7606aa1..89ac6bc8c7fc 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c
@@ -1,5 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
#include "fbnic.h"
+static void fbnic_hw_stat_rst32(struct fbnic_dev *fbd, u32 reg,
+ struct fbnic_stat_counter *stat)
+{
+ /* We do not touch the "value" field here.
+ * It gets zeroed out on fbd structure allocation.
+ * After that we want it to grow continuously
+ * through device resets and power state changes.
+ */
+ stat->u.old_reg_value_32 = rd32(fbd, reg);
+}
+
+static void fbnic_hw_stat_rd32(struct fbnic_dev *fbd, u32 reg,
+ struct fbnic_stat_counter *stat)
+{
+ u32 new_reg_value;
+
+ new_reg_value = rd32(fbd, reg);
+ stat->value += new_reg_value - stat->u.old_reg_value_32;
+ stat->u.old_reg_value_32 = new_reg_value;
+}
+
u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset)
{
u32 prev_upper, upper, lower, diff;
@@ -25,3 +49,172 @@ u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset)
*/
return ((u64)upper << 32);
}
+
+static void fbnic_hw_stat_rst64(struct fbnic_dev *fbd, u32 reg, s32 offset,
+ struct fbnic_stat_counter *stat)
+{
+ /* Record initial counter values and compute deltas from there to ensure
+ * stats start at 0 after reboot/reset. This avoids exposing absolute
+ * hardware counter values to userspace.
+ */
+ stat->u.old_reg_value_64 = fbnic_stat_rd64(fbd, reg, offset);
+}
+
+static void fbnic_hw_stat_rd64(struct fbnic_dev *fbd, u32 reg, s32 offset,
+ struct fbnic_stat_counter *stat)
+{
+ u64 new_reg_value;
+
+ new_reg_value = fbnic_stat_rd64(fbd, reg, offset);
+ stat->value += new_reg_value - stat->u.old_reg_value_64;
+ stat->u.old_reg_value_64 = new_reg_value;
+}
+
+static void fbnic_reset_rpc_stats(struct fbnic_dev *fbd,
+ struct fbnic_rpc_stats *rpc)
+{
+ fbnic_hw_stat_rst32(fbd,
+ FBNIC_RPC_CNTR_UNKN_ETYPE,
+ &rpc->unkn_etype);
+ fbnic_hw_stat_rst32(fbd,
+ FBNIC_RPC_CNTR_UNKN_EXT_HDR,
+ &rpc->unkn_ext_hdr);
+ fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV4_FRAG, &rpc->ipv4_frag);
+ fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV6_FRAG, &rpc->ipv6_frag);
+ fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV4_ESP, &rpc->ipv4_esp);
+ fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV6_ESP, &rpc->ipv6_esp);
+ fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_TCP_OPT_ERR, &rpc->tcp_opt_err);
+ fbnic_hw_stat_rst32(fbd,
+ FBNIC_RPC_CNTR_OUT_OF_HDR_ERR,
+ &rpc->out_of_hdr_err);
+ fbnic_hw_stat_rst32(fbd,
+ FBNIC_RPC_CNTR_OVR_SIZE_ERR,
+ &rpc->ovr_size_err);
+}
+
+static void fbnic_get_rpc_stats32(struct fbnic_dev *fbd,
+ struct fbnic_rpc_stats *rpc)
+{
+ fbnic_hw_stat_rd32(fbd,
+ FBNIC_RPC_CNTR_UNKN_ETYPE,
+ &rpc->unkn_etype);
+ fbnic_hw_stat_rd32(fbd,
+ FBNIC_RPC_CNTR_UNKN_EXT_HDR,
+ &rpc->unkn_ext_hdr);
+
+ fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV4_FRAG, &rpc->ipv4_frag);
+ fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV6_FRAG, &rpc->ipv6_frag);
+
+ fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV4_ESP, &rpc->ipv4_esp);
+ fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV6_ESP, &rpc->ipv6_esp);
+
+ fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_TCP_OPT_ERR, &rpc->tcp_opt_err);
+ fbnic_hw_stat_rd32(fbd,
+ FBNIC_RPC_CNTR_OUT_OF_HDR_ERR,
+ &rpc->out_of_hdr_err);
+ fbnic_hw_stat_rd32(fbd,
+ FBNIC_RPC_CNTR_OVR_SIZE_ERR,
+ &rpc->ovr_size_err);
+}
+
+static void fbnic_reset_pcie_stats_asic(struct fbnic_dev *fbd,
+ struct fbnic_pcie_stats *pcie)
+{
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_RD_TLP_CNT_31_0,
+ 1,
+ &pcie->ob_rd_tlp);
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_RD_DWORD_CNT_31_0,
+ 1,
+ &pcie->ob_rd_dword);
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_CPL_TLP_CNT_31_0,
+ 1,
+ &pcie->ob_cpl_tlp);
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_CPL_DWORD_CNT_31_0,
+ 1,
+ &pcie->ob_cpl_dword);
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_WR_TLP_CNT_31_0,
+ 1,
+ &pcie->ob_wr_tlp);
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_WR_DWORD_CNT_31_0,
+ 1,
+ &pcie->ob_wr_dword);
+
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_31_0,
+ 1,
+ &pcie->ob_rd_no_tag);
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_31_0,
+ 1,
+ &pcie->ob_rd_no_cpl_cred);
+ fbnic_hw_stat_rst64(fbd,
+ FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_31_0,
+ 1,
+ &pcie->ob_rd_no_np_cred);
+}
+
+static void fbnic_get_pcie_stats_asic64(struct fbnic_dev *fbd,
+ struct fbnic_pcie_stats *pcie)
+{
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_RD_TLP_CNT_31_0,
+ 1,
+ &pcie->ob_rd_tlp);
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_RD_DWORD_CNT_31_0,
+ 1,
+ &pcie->ob_rd_dword);
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_WR_TLP_CNT_31_0,
+ 1,
+ &pcie->ob_wr_tlp);
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_WR_DWORD_CNT_31_0,
+ 1,
+ &pcie->ob_wr_dword);
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_CPL_TLP_CNT_31_0,
+ 1,
+ &pcie->ob_cpl_tlp);
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_CPL_DWORD_CNT_31_0,
+ 1,
+ &pcie->ob_cpl_dword);
+
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_31_0,
+ 1,
+ &pcie->ob_rd_no_tag);
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_31_0,
+ 1,
+ &pcie->ob_rd_no_cpl_cred);
+ fbnic_hw_stat_rd64(fbd,
+ FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_31_0,
+ 1,
+ &pcie->ob_rd_no_np_cred);
+}
+
+void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
+{
+ fbnic_reset_rpc_stats(fbd, &fbd->hw_stats.rpc);
+ fbnic_reset_pcie_stats_asic(fbd, &fbd->hw_stats.pcie);
+}
+
+void fbnic_get_hw_stats32(struct fbnic_dev *fbd)
+{
+ fbnic_get_rpc_stats32(fbd, &fbd->hw_stats.rpc);
+}
+
+void fbnic_get_hw_stats(struct fbnic_dev *fbd)
+{
+ fbnic_get_hw_stats32(fbd);
+
+ fbnic_get_pcie_stats_asic64(fbd, &fbd->hw_stats.pcie);
+}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h b/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h
index 30348904b510..78df56b87745 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.h
@@ -1,3 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#ifndef _FBNIC_HW_STATS_H_
+#define _FBNIC_HW_STATS_H_
+
#include <linux/ethtool.h>
#include "fbnic_csr.h"
@@ -31,10 +37,32 @@ struct fbnic_mac_stats {
struct fbnic_eth_mac_stats eth_mac;
};
+struct fbnic_rpc_stats {
+ struct fbnic_stat_counter unkn_etype, unkn_ext_hdr;
+ struct fbnic_stat_counter ipv4_frag, ipv6_frag, ipv4_esp, ipv6_esp;
+ struct fbnic_stat_counter tcp_opt_err, out_of_hdr_err, ovr_size_err;
+};
+
+struct fbnic_pcie_stats {
+ struct fbnic_stat_counter ob_rd_tlp, ob_rd_dword;
+ struct fbnic_stat_counter ob_wr_tlp, ob_wr_dword;
+ struct fbnic_stat_counter ob_cpl_tlp, ob_cpl_dword;
+
+ struct fbnic_stat_counter ob_rd_no_tag;
+ struct fbnic_stat_counter ob_rd_no_cpl_cred;
+ struct fbnic_stat_counter ob_rd_no_np_cred;
+};
+
struct fbnic_hw_stats {
struct fbnic_mac_stats mac;
+ struct fbnic_rpc_stats rpc;
+ struct fbnic_pcie_stats pcie;
};
u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset);
+void fbnic_reset_hw_stats(struct fbnic_dev *fbd);
+void fbnic_get_hw_stats32(struct fbnic_dev *fbd);
void fbnic_get_hw_stats(struct fbnic_dev *fbd);
+
+#endif /* _FBNIC_HW_STATS_H_ */
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
new file mode 100644
index 000000000000..bcd1086e3768
--- /dev/null
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#include <linux/hwmon.h>
+
+#include "fbnic.h"
+#include "fbnic_mac.h"
+
+static int fbnic_hwmon_sensor_id(enum hwmon_sensor_types type)
+{
+ if (type == hwmon_temp)
+ return FBNIC_SENSOR_TEMP;
+ if (type == hwmon_in)
+ return FBNIC_SENSOR_VOLTAGE;
+
+ return -EOPNOTSUPP;
+}
+
+static umode_t fbnic_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type == hwmon_temp && attr == hwmon_temp_input)
+ return 0444;
+ if (type == hwmon_in && attr == hwmon_in_input)
+ return 0444;
+
+ return 0;
+}
+
+static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct fbnic_dev *fbd = dev_get_drvdata(dev);
+ const struct fbnic_mac *mac = fbd->mac;
+ int id;
+
+ id = fbnic_hwmon_sensor_id(type);
+ return id < 0 ? id : mac->get_sensor(fbd, id, val);
+}
+
+static const struct hwmon_ops fbnic_hwmon_ops = {
+ .is_visible = fbnic_hwmon_is_visible,
+ .read = fbnic_hwmon_read,
+};
+
+static const struct hwmon_channel_info *fbnic_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
+ NULL
+};
+
+static const struct hwmon_chip_info fbnic_chip_info = {
+ .ops = &fbnic_hwmon_ops,
+ .info = fbnic_hwmon_info,
+};
+
+void fbnic_hwmon_register(struct fbnic_dev *fbd)
+{
+ if (!IS_REACHABLE(CONFIG_HWMON))
+ return;
+
+ fbd->hwmon = hwmon_device_register_with_info(fbd->dev, "fbnic",
+ fbd, &fbnic_chip_info,
+ NULL);
+ if (IS_ERR(fbd->hwmon)) {
+ dev_notice(fbd->dev,
+ "Failed to register hwmon device %pe\n",
+ fbd->hwmon);
+ fbd->hwmon = NULL;
+ }
+}
+
+void fbnic_hwmon_unregister(struct fbnic_dev *fbd)
+{
+ if (!IS_REACHABLE(CONFIG_HWMON) || !fbd->hwmon)
+ return;
+
+ hwmon_device_unregister(fbd->hwmon);
+ fbd->hwmon = NULL;
+}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
index 7b654d0a6dac..80b82ff12c4d 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
@@ -686,6 +686,27 @@ fbnic_mac_get_eth_mac_stats(struct fbnic_dev *fbd, bool reset,
MAC_STAT_TX_BROADCAST);
}
+static int fbnic_mac_get_sensor_asic(struct fbnic_dev *fbd, int id, long *val)
+{
+ struct fbnic_fw_completion fw_cmpl;
+ s32 *sensor;
+
+ switch (id) {
+ case FBNIC_SENSOR_TEMP:
+ sensor = &fw_cmpl.tsene.millidegrees;
+ break;
+ case FBNIC_SENSOR_VOLTAGE:
+ sensor = &fw_cmpl.tsene.millivolts;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = *sensor;
+
+ return 0;
+}
+
static const struct fbnic_mac fbnic_mac_asic = {
.init_regs = fbnic_mac_init_regs,
.pcs_enable = fbnic_pcs_enable_asic,
@@ -695,6 +716,7 @@ static const struct fbnic_mac fbnic_mac_asic = {
.get_eth_mac_stats = fbnic_mac_get_eth_mac_stats,
.link_down = fbnic_mac_link_down_asic,
.link_up = fbnic_mac_link_up_asic,
+ .get_sensor = fbnic_mac_get_sensor_asic,
};
/**
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
index 476239a9d381..05a591653e09 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
@@ -47,6 +47,11 @@ enum {
#define FBNIC_LINK_MODE_PAM4 (FBNIC_LINK_50R1)
#define FBNIC_LINK_MODE_MASK (FBNIC_LINK_AUTO - 1)
+enum fbnic_sensor_id {
+ FBNIC_SENSOR_TEMP, /* Temp in millidegrees Centigrade */
+ FBNIC_SENSOR_VOLTAGE, /* Voltage in millivolts */
+};
+
/* This structure defines the interface hooks for the MAC. The MAC hooks
* will be configured as a const struct provided with a set of function
* pointers.
@@ -83,6 +88,8 @@ struct fbnic_mac {
void (*link_down)(struct fbnic_dev *fbd);
void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);
+
+ int (*get_sensor)(struct fbnic_dev *fbd, int id, long *val);
};
int fbnic_mac_init(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
index a400616a24d4..fc7d80db5fa6 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
@@ -42,18 +42,24 @@ int __fbnic_open(struct fbnic_net *fbn)
goto free_resources;
}
- err = fbnic_fw_init_heartbeat(fbd, false);
+ err = fbnic_time_start(fbn);
if (err)
goto release_ownership;
+ err = fbnic_fw_init_heartbeat(fbd, false);
+ if (err)
+ goto time_stop;
+
err = fbnic_pcs_irq_enable(fbd);
if (err)
- goto release_ownership;
+ goto time_stop;
/* Pull the BMC config and initialize the RPC */
fbnic_bmc_rpc_init(fbd);
fbnic_rss_reinit(fbd, fbn);
return 0;
+time_stop:
+ fbnic_time_stop(fbn);
release_ownership:
fbnic_fw_xmit_ownership_msg(fbn->fbd, false);
free_resources:
@@ -82,6 +88,7 @@ static int fbnic_stop(struct net_device *netdev)
fbnic_down(fbn);
fbnic_pcs_irq_disable(fbn->fbd);
+ fbnic_time_stop(fbn);
fbnic_fw_xmit_ownership_msg(fbn->fbd, false);
fbnic_free_resources(fbn);
@@ -266,6 +273,7 @@ void __fbnic_set_rx_mode(struct net_device *netdev)
/* Write updates to hardware */
fbnic_write_rules(fbd);
fbnic_write_macda(fbd);
+ fbnic_write_tce_tcam(fbd);
}
static void fbnic_set_rx_mode(struct net_device *netdev)
@@ -317,6 +325,84 @@ void fbnic_clear_rx_mode(struct net_device *netdev)
__dev_mc_unsync(netdev, NULL);
}
+static int fbnic_hwtstamp_get(struct net_device *netdev,
+ struct kernel_hwtstamp_config *config)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+
+ *config = fbn->hwtstamp_config;
+
+ return 0;
+}
+
+static int fbnic_hwtstamp_set(struct net_device *netdev,
+ struct kernel_hwtstamp_config *config,
+ struct netlink_ext_ack *extack)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ int old_rx_filter;
+
+ if (config->source != HWTSTAMP_SOURCE_NETDEV)
+ return -EOPNOTSUPP;
+
+ if (!kernel_hwtstamp_config_changed(config, &fbn->hwtstamp_config))
+ return 0;
+
+ /* Upscale the filters */
+ switch (config->rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ break;
+ case HWTSTAMP_FILTER_NTP_ALL:
+ config->rx_filter = HWTSTAMP_FILTER_ALL;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ /* Configure */
+ old_rx_filter = fbn->hwtstamp_config.rx_filter;
+ memcpy(&fbn->hwtstamp_config, config, sizeof(*config));
+
+ if (old_rx_filter != config->rx_filter && netif_running(fbn->netdev)) {
+ fbnic_rss_reinit(fbn->fbd, fbn);
+ fbnic_write_rules(fbn->fbd);
+ }
+
+ /* Save / report back filter configuration
+ * Note that our filter configuration is inexact. Instead of
+ * filtering for a specific UDP port or L2 Ethertype we are
+ * filtering in all UDP or all non-IP packets for timestamping. So
+ * if anything other than FILTER_ALL is requested we report
+ * FILTER_SOME indicating that we will be timestamping a few
+ * additional packets.
+ */
+ if (config->rx_filter > HWTSTAMP_FILTER_ALL)
+ config->rx_filter = HWTSTAMP_FILTER_SOME;
+
+ return 0;
+}
+
static void fbnic_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats64)
{
@@ -394,6 +480,8 @@ static const struct net_device_ops fbnic_netdev_ops = {
.ndo_set_mac_address = fbnic_set_mac,
.ndo_set_rx_mode = fbnic_set_rx_mode,
.ndo_get_stats64 = fbnic_get_stats64,
+ .ndo_hwtstamp_get = fbnic_hwtstamp_get,
+ .ndo_hwtstamp_set = fbnic_hwtstamp_set,
};
static void fbnic_get_queue_stats_rx(struct net_device *dev, int idx,
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
index 6c27da09a612..b8417b300778 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
@@ -33,6 +33,15 @@ struct fbnic_net {
u8 fec;
u8 link_mode;
+ /* Cached top bits of the HW time counter for 40b -> 64b conversion */
+ u32 time_high;
+ /* Protect readers of @time_offset, writers take @time_lock. */
+ struct u64_stats_sync time_seq;
+ /* Offset in ns between free running NIC PHC and time set via PTP
+ * clock callbacks
+ */
+ s64 time_offset;
+
u16 num_tx_queues;
u16 num_rx_queues;
@@ -45,6 +54,9 @@ struct fbnic_net {
struct fbnic_queue_stats rx_stats;
u64 link_down_events;
+ /* Time stampinn filter config */
+ struct kernel_hwtstamp_config hwtstamp_config;
+
struct list_head napis;
};
@@ -60,6 +72,12 @@ void fbnic_reset_queues(struct fbnic_net *fbn,
unsigned int tx, unsigned int rx);
void fbnic_set_ethtool_ops(struct net_device *dev);
+int fbnic_ptp_setup(struct fbnic_dev *fbd);
+void fbnic_ptp_destroy(struct fbnic_dev *fbd);
+void fbnic_time_init(struct fbnic_net *fbn);
+int fbnic_time_start(struct fbnic_net *fbn);
+void fbnic_time_stop(struct fbnic_net *fbn);
+
void __fbnic_set_rx_mode(struct net_device *netdev);
void fbnic_clear_rx_mode(struct net_device *netdev);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
index a4809fe0fc24..32702dc4a066 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
@@ -9,6 +9,7 @@
#include "fbnic.h"
#include "fbnic_drvinfo.h"
+#include "fbnic_hw_stats.h"
#include "fbnic_netdev.h"
char fbnic_driver_name[] = DRV_NAME;
@@ -198,6 +199,8 @@ static void fbnic_service_task(struct work_struct *work)
rtnl_lock();
+ fbnic_get_hw_stats32(fbd);
+
fbnic_fw_check_heartbeat(fbd);
fbnic_health_check(fbd);
@@ -288,6 +291,12 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
fbnic_devlink_register(fbd);
+ fbnic_dbg_fbd_init(fbd);
+
+ /* Capture snapshot of hardware stats so netdev can calculate delta */
+ fbnic_reset_hw_stats(fbd);
+
+ fbnic_hwmon_register(fbd);
if (!fbd->dsn) {
dev_warn(&pdev->dev, "Reading serial number failed\n");
@@ -300,14 +309,20 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto init_failure_mode;
}
+ err = fbnic_ptp_setup(fbd);
+ if (err)
+ goto ifm_free_netdev;
+
err = fbnic_netdev_register(netdev);
if (err) {
dev_err(&pdev->dev, "Netdev registration failed: %d\n", err);
- goto ifm_free_netdev;
+ goto ifm_destroy_ptp;
}
return 0;
+ifm_destroy_ptp:
+ fbnic_ptp_destroy(fbd);
ifm_free_netdev:
fbnic_netdev_free(fbd);
init_failure_mode:
@@ -319,7 +334,6 @@ init_failure_mode:
free_irqs:
fbnic_free_irqs(fbd);
free_fbd:
- pci_disable_device(pdev);
fbnic_devlink_free(fbd);
return err;
@@ -342,14 +356,16 @@ static void fbnic_remove(struct pci_dev *pdev)
fbnic_netdev_unregister(netdev);
cancel_delayed_work_sync(&fbd->service_task);
+ fbnic_ptp_destroy(fbd);
fbnic_netdev_free(fbd);
}
+ fbnic_hwmon_unregister(fbd);
+ fbnic_dbg_fbd_exit(fbd);
fbnic_devlink_unregister(fbd);
fbnic_fw_disable_mbx(fbd);
fbnic_free_irqs(fbd);
- pci_disable_device(pdev);
fbnic_devlink_free(fbd);
}
@@ -542,9 +558,13 @@ static int __init fbnic_init_module(void)
{
int err;
+ fbnic_dbg_init();
+
err = pci_register_driver(&fbnic_driver);
- if (err)
+ if (err) {
+ fbnic_dbg_exit();
goto out;
+ }
pr_info(DRV_SUMMARY " (%s)", fbnic_driver.name);
out:
@@ -560,5 +580,7 @@ module_init(fbnic_init_module);
static void __exit fbnic_exit_module(void)
{
pci_unregister_driver(&fbnic_driver);
+
+ fbnic_dbg_exit();
}
module_exit(fbnic_exit_module);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
index c8aa29fc052b..908c098cd59e 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
@@ -244,6 +244,12 @@ void fbnic_bmc_rpc_init(struct fbnic_dev *fbd)
((_ip) ? FBNIC_RPC_TCAM_ACT1_IP_VALID : 0) | \
((_v6) ? FBNIC_RPC_TCAM_ACT1_IP_IS_V6 : 0))
+#define FBNIC_TSTAMP_MASK(_all, _udp, _ether) \
+ (((_all) ? ((1u << FBNIC_NUM_HASH_OPT) - 1) : 0) | \
+ ((_udp) ? (1u << FBNIC_UDP6_HASH_OPT) | \
+ (1u << FBNIC_UDP4_HASH_OPT) : 0) | \
+ ((_ether) ? (1u << FBNIC_ETHER_HASH_OPT) : 0))
+
void fbnic_rss_reinit(struct fbnic_dev *fbd, struct fbnic_net *fbn)
{
static const u32 act1_value[FBNIC_NUM_HASH_OPT] = {
@@ -255,6 +261,7 @@ void fbnic_rss_reinit(struct fbnic_dev *fbd, struct fbnic_net *fbn)
FBNIC_ACT1_INIT(0, 0, 1, 0), /* IP4 */
0 /* Ether */
};
+ u32 tstamp_mask = 0;
unsigned int i;
/* To support scenarios where a BMC is present we must write the
@@ -264,6 +271,28 @@ void fbnic_rss_reinit(struct fbnic_dev *fbd, struct fbnic_net *fbn)
BUILD_BUG_ON(FBNIC_RSS_EN_NUM_UNICAST * 2 != FBNIC_RSS_EN_NUM_ENTRIES);
BUILD_BUG_ON(ARRAY_SIZE(act1_value) != FBNIC_NUM_HASH_OPT);
+ /* Set timestamp mask with 1b per flow type */
+ if (fbn->hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) {
+ switch (fbn->hwtstamp_config.rx_filter) {
+ case HWTSTAMP_FILTER_ALL:
+ tstamp_mask = FBNIC_TSTAMP_MASK(1, 1, 1);
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ tstamp_mask = FBNIC_TSTAMP_MASK(0, 1, 1);
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ tstamp_mask = FBNIC_TSTAMP_MASK(0, 1, 0);
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ tstamp_mask = FBNIC_TSTAMP_MASK(0, 0, 1);
+ break;
+ default:
+ netdev_warn(fbn->netdev, "Unsupported hwtstamp_rx_filter\n");
+ break;
+ }
+ }
+
/* Program RSS hash enable mask for host in action TCAM/table. */
for (i = fbnic_bmc_present(fbd) ? 0 : FBNIC_RSS_EN_NUM_UNICAST;
i < FBNIC_RSS_EN_NUM_ENTRIES; i++) {
@@ -287,6 +316,8 @@ void fbnic_rss_reinit(struct fbnic_dev *fbd, struct fbnic_net *fbn)
if (!dest)
dest = FBNIC_RPC_ACT_TBL0_DROP;
+ else if (tstamp_mask & (1u << flow_type))
+ dest |= FBNIC_RPC_ACT_TBL0_TS_ENA;
if (act1_value[flow_type] & FBNIC_RPC_TCAM_ACT1_L4_VALID)
dest |= FIELD_PREP(FBNIC_RPC_ACT_TBL0_DMA_HINT,
@@ -556,6 +587,116 @@ static void fbnic_clear_act_tcam(struct fbnic_dev *fbd, unsigned int idx)
wr32(fbd, FBNIC_RPC_TCAM_ACT(idx, i), 0);
}
+static void fbnic_clear_tce_tcam_entry(struct fbnic_dev *fbd, unsigned int idx)
+{
+ int i;
+
+ /* Invalidate entry and clear addr state info */
+ for (i = 0; i <= FBNIC_TCE_TCAM_WORD_LEN; i++)
+ wr32(fbd, FBNIC_TCE_RAM_TCAM(idx, i), 0);
+}
+
+static void fbnic_write_tce_tcam_dest(struct fbnic_dev *fbd, unsigned int idx,
+ struct fbnic_mac_addr *mac_addr)
+{
+ u32 dest = FBNIC_TCE_TCAM_DEST_BMC;
+ u32 idx2dest_map;
+
+ if (is_multicast_ether_addr(mac_addr->value.addr8))
+ dest |= FBNIC_TCE_TCAM_DEST_MAC;
+
+ idx2dest_map = rd32(fbd, FBNIC_TCE_TCAM_IDX2DEST_MAP);
+ idx2dest_map &= ~(FBNIC_TCE_TCAM_IDX2DEST_MAP_DEST_ID_0 << (4 * idx));
+ idx2dest_map |= dest << (4 * idx);
+
+ wr32(fbd, FBNIC_TCE_TCAM_IDX2DEST_MAP, idx2dest_map);
+}
+
+static void fbnic_write_tce_tcam_entry(struct fbnic_dev *fbd, unsigned int idx,
+ struct fbnic_mac_addr *mac_addr)
+{
+ __be16 *mask, *value;
+ int i;
+
+ mask = &mac_addr->mask.addr16[FBNIC_TCE_TCAM_WORD_LEN - 1];
+ value = &mac_addr->value.addr16[FBNIC_TCE_TCAM_WORD_LEN - 1];
+
+ for (i = 0; i < FBNIC_TCE_TCAM_WORD_LEN; i++)
+ wr32(fbd, FBNIC_TCE_RAM_TCAM(idx, i),
+ FIELD_PREP(FBNIC_TCE_RAM_TCAM_MASK, ntohs(*mask--)) |
+ FIELD_PREP(FBNIC_TCE_RAM_TCAM_VALUE, ntohs(*value--)));
+
+ wrfl(fbd);
+
+ wr32(fbd, FBNIC_TCE_RAM_TCAM3(idx), FBNIC_TCE_RAM_TCAM3_MCQ_MASK |
+ FBNIC_TCE_RAM_TCAM3_DEST_MASK |
+ FBNIC_TCE_RAM_TCAM3_VALIDATE);
+}
+
+static void __fbnic_write_tce_tcam_rev(struct fbnic_dev *fbd)
+{
+ int tcam_idx = FBNIC_TCE_TCAM_NUM_ENTRIES;
+ int mac_idx;
+
+ for (mac_idx = ARRAY_SIZE(fbd->mac_addr); mac_idx--;) {
+ struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[mac_idx];
+
+ /* Verify BMC bit is set */
+ if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam))
+ continue;
+
+ if (!tcam_idx) {
+ dev_err(fbd->dev, "TCE TCAM overflow\n");
+ return;
+ }
+
+ tcam_idx--;
+ fbnic_write_tce_tcam_dest(fbd, tcam_idx, mac_addr);
+ fbnic_write_tce_tcam_entry(fbd, tcam_idx, mac_addr);
+ }
+
+ while (tcam_idx)
+ fbnic_clear_tce_tcam_entry(fbd, --tcam_idx);
+
+ fbd->tce_tcam_last = tcam_idx;
+}
+
+static void __fbnic_write_tce_tcam(struct fbnic_dev *fbd)
+{
+ int tcam_idx = 0;
+ int mac_idx;
+
+ for (mac_idx = 0; mac_idx < ARRAY_SIZE(fbd->mac_addr); mac_idx++) {
+ struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[mac_idx];
+
+ /* Verify BMC bit is set */
+ if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam))
+ continue;
+
+ if (tcam_idx == FBNIC_TCE_TCAM_NUM_ENTRIES) {
+ dev_err(fbd->dev, "TCE TCAM overflow\n");
+ return;
+ }
+
+ fbnic_write_tce_tcam_dest(fbd, tcam_idx, mac_addr);
+ fbnic_write_tce_tcam_entry(fbd, tcam_idx, mac_addr);
+ tcam_idx++;
+ }
+
+ while (tcam_idx < FBNIC_TCE_TCAM_NUM_ENTRIES)
+ fbnic_clear_tce_tcam_entry(fbd, tcam_idx++);
+
+ fbd->tce_tcam_last = tcam_idx;
+}
+
+void fbnic_write_tce_tcam(struct fbnic_dev *fbd)
+{
+ if (fbd->tce_tcam_last)
+ __fbnic_write_tce_tcam_rev(fbd);
+ else
+ __fbnic_write_tce_tcam(fbd);
+}
+
void fbnic_clear_rules(struct fbnic_dev *fbd)
{
u32 dest = FIELD_PREP(FBNIC_RPC_ACT_TBL0_DEST_MASK,
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h
index d62935f722a2..0d8285fa5b45 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.h
@@ -35,6 +35,9 @@ enum {
#define FBNIC_RPC_TCAM_ACT_WORD_LEN 11
#define FBNIC_RPC_TCAM_ACT_NUM_ENTRIES 64
+#define FBNIC_TCE_TCAM_WORD_LEN 3
+#define FBNIC_TCE_TCAM_NUM_ENTRIES 8
+
struct fbnic_mac_addr {
union {
unsigned char addr8[ETH_ALEN];
@@ -186,4 +189,5 @@ static inline int __fbnic_mc_unsync(struct fbnic_mac_addr *mac_addr)
void fbnic_clear_rules(struct fbnic_dev *fbd);
void fbnic_write_rules(struct fbnic_dev *fbd);
+void fbnic_write_tce_tcam(struct fbnic_dev *fbd);
#endif /* _FBNIC_RPC_H_ */
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_time.c b/drivers/net/ethernet/meta/fbnic/fbnic_time.c
new file mode 100644
index 000000000000..39d99677b71e
--- /dev/null
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_time.c
@@ -0,0 +1,303 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#include <linux/bitfield.h>
+#include <linux/jiffies.h>
+#include <linux/limits.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/timer.h>
+
+#include "fbnic.h"
+#include "fbnic_csr.h"
+#include "fbnic_netdev.h"
+
+/* FBNIC timing & PTP implementation
+ * Datapath uses truncated 40b timestamps for scheduling and event reporting.
+ * We need to promote those to full 64b, hence we periodically cache the top
+ * 32bit of the HW time counter. Since this makes our time reporting non-atomic
+ * we leave the HW clock free running and adjust time offsets in SW as needed.
+ * Time offset is 64bit - we need a seq counter for 32bit machines.
+ * Time offset and the cache of top bits are independent so we don't need
+ * a coherent snapshot of both - READ_ONCE()/WRITE_ONCE() + writer side lock
+ * are enough.
+ */
+
+/* Period of refresh of top bits of timestamp, give ourselves a 8x margin.
+ * This should translate to once a minute.
+ * The use of nsecs_to_jiffies() should be safe for a <=40b nsec value.
+ */
+#define FBNIC_TS_HIGH_REFRESH_JIF nsecs_to_jiffies((1ULL << 40) / 16)
+
+static struct fbnic_dev *fbnic_from_ptp_info(struct ptp_clock_info *ptp)
+{
+ return container_of(ptp, struct fbnic_dev, ptp_info);
+}
+
+/* This function is "slow" because we could try guessing which high part
+ * is correct based on low instead of re-reading, and skip reading @hi
+ * twice altogether if @lo is far enough from 0.
+ */
+static u64 __fbnic_time_get_slow(struct fbnic_dev *fbd)
+{
+ u32 hi, lo;
+
+ lockdep_assert_held(&fbd->time_lock);
+
+ do {
+ hi = fbnic_rd32(fbd, FBNIC_PTP_CTR_VAL_HI);
+ lo = fbnic_rd32(fbd, FBNIC_PTP_CTR_VAL_LO);
+ } while (hi != fbnic_rd32(fbd, FBNIC_PTP_CTR_VAL_HI));
+
+ return (u64)hi << 32 | lo;
+}
+
+static void __fbnic_time_set_addend(struct fbnic_dev *fbd, u64 addend)
+{
+ lockdep_assert_held(&fbd->time_lock);
+
+ fbnic_wr32(fbd, FBNIC_PTP_ADD_VAL_NS,
+ FIELD_PREP(FBNIC_PTP_ADD_VAL_NS_MASK, addend >> 32));
+ fbnic_wr32(fbd, FBNIC_PTP_ADD_VAL_SUBNS, (u32)addend);
+}
+
+static void fbnic_ptp_fresh_check(struct fbnic_dev *fbd)
+{
+ if (time_is_after_jiffies(fbd->last_read +
+ FBNIC_TS_HIGH_REFRESH_JIF * 3 / 2))
+ return;
+
+ dev_warn(fbd->dev, "NIC timestamp refresh stall, delayed by %lu sec\n",
+ (jiffies - fbd->last_read - FBNIC_TS_HIGH_REFRESH_JIF) / HZ);
+}
+
+static void fbnic_ptp_refresh_time(struct fbnic_dev *fbd, struct fbnic_net *fbn)
+{
+ unsigned long flags;
+ u32 hi;
+
+ spin_lock_irqsave(&fbd->time_lock, flags);
+ hi = fbnic_rd32(fbn->fbd, FBNIC_PTP_CTR_VAL_HI);
+ if (!fbnic_present(fbd))
+ goto out; /* Don't bother handling, reset is pending */
+ /* Let's keep high cached value a bit lower to avoid race with
+ * incoming timestamps. The logic in fbnic_ts40_to_ns() will
+ * take care of overflow in this case. It will make cached time
+ * ~1 minute lower and incoming timestamp will always be later
+ * then cached time.
+ */
+ WRITE_ONCE(fbn->time_high, hi - 16);
+ fbd->last_read = jiffies;
+ out:
+ spin_unlock_irqrestore(&fbd->time_lock, flags);
+}
+
+static long fbnic_ptp_do_aux_work(struct ptp_clock_info *ptp)
+{
+ struct fbnic_dev *fbd = fbnic_from_ptp_info(ptp);
+ struct fbnic_net *fbn;
+
+ fbn = netdev_priv(fbd->netdev);
+
+ fbnic_ptp_fresh_check(fbd);
+ fbnic_ptp_refresh_time(fbd, fbn);
+
+ return FBNIC_TS_HIGH_REFRESH_JIF;
+}
+
+static int fbnic_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+ struct fbnic_dev *fbd = fbnic_from_ptp_info(ptp);
+ u64 addend, dclk_period;
+ unsigned long flags;
+
+ /* d_clock is 600 MHz; which in Q16.32 fixed point ns is: */
+ dclk_period = (((u64)1000000000) << 32) / FBNIC_CLOCK_FREQ;
+ addend = adjust_by_scaled_ppm(dclk_period, scaled_ppm);
+
+ spin_lock_irqsave(&fbd->time_lock, flags);
+ __fbnic_time_set_addend(fbd, addend);
+ fbnic_wr32(fbd, FBNIC_PTP_ADJUST, FBNIC_PTP_ADJUST_ADDEND_SET);
+
+ /* Flush, make sure FBNIC_PTP_ADD_VAL_* is stable for at least 4 clks */
+ fbnic_rd32(fbd, FBNIC_PTP_SPARE);
+ spin_unlock_irqrestore(&fbd->time_lock, flags);
+
+ return fbnic_present(fbd) ? 0 : -EIO;
+}
+
+static int fbnic_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct fbnic_dev *fbd = fbnic_from_ptp_info(ptp);
+ struct fbnic_net *fbn;
+ unsigned long flags;
+
+ fbn = netdev_priv(fbd->netdev);
+
+ spin_lock_irqsave(&fbd->time_lock, flags);
+ u64_stats_update_begin(&fbn->time_seq);
+ WRITE_ONCE(fbn->time_offset, READ_ONCE(fbn->time_offset) + delta);
+ u64_stats_update_end(&fbn->time_seq);
+ spin_unlock_irqrestore(&fbd->time_lock, flags);
+
+ return 0;
+}
+
+static int
+fbnic_ptp_gettimex64(struct ptp_clock_info *ptp, struct timespec64 *ts,
+ struct ptp_system_timestamp *sts)
+{
+ struct fbnic_dev *fbd = fbnic_from_ptp_info(ptp);
+ struct fbnic_net *fbn;
+ unsigned long flags;
+ u64 time_ns;
+ u32 hi, lo;
+
+ fbn = netdev_priv(fbd->netdev);
+
+ spin_lock_irqsave(&fbd->time_lock, flags);
+
+ do {
+ hi = fbnic_rd32(fbd, FBNIC_PTP_CTR_VAL_HI);
+ ptp_read_system_prets(sts);
+ lo = fbnic_rd32(fbd, FBNIC_PTP_CTR_VAL_LO);
+ ptp_read_system_postts(sts);
+ /* Similarly to comment above __fbnic_time_get_slow()
+ * - this can be optimized if needed.
+ */
+ } while (hi != fbnic_rd32(fbd, FBNIC_PTP_CTR_VAL_HI));
+
+ time_ns = ((u64)hi << 32 | lo) + fbn->time_offset;
+ spin_unlock_irqrestore(&fbd->time_lock, flags);
+
+ if (!fbnic_present(fbd))
+ return -EIO;
+
+ *ts = ns_to_timespec64(time_ns);
+
+ return 0;
+}
+
+static int
+fbnic_ptp_settime64(struct ptp_clock_info *ptp, const struct timespec64 *ts)
+{
+ struct fbnic_dev *fbd = fbnic_from_ptp_info(ptp);
+ struct fbnic_net *fbn;
+ unsigned long flags;
+ u64 dev_ns, host_ns;
+ int ret;
+
+ fbn = netdev_priv(fbd->netdev);
+
+ host_ns = timespec64_to_ns(ts);
+
+ spin_lock_irqsave(&fbd->time_lock, flags);
+
+ dev_ns = __fbnic_time_get_slow(fbd);
+
+ if (fbnic_present(fbd)) {
+ u64_stats_update_begin(&fbn->time_seq);
+ WRITE_ONCE(fbn->time_offset, host_ns - dev_ns);
+ u64_stats_update_end(&fbn->time_seq);
+ ret = 0;
+ } else {
+ ret = -EIO;
+ }
+ spin_unlock_irqrestore(&fbd->time_lock, flags);
+
+ return ret;
+}
+
+static const struct ptp_clock_info fbnic_ptp_info = {
+ .owner = THIS_MODULE,
+ /* 1,000,000,000 - 1 PPB to ensure increment is positive
+ * after max negative adjustment.
+ */
+ .max_adj = 999999999,
+ .do_aux_work = fbnic_ptp_do_aux_work,
+ .adjfine = fbnic_ptp_adjfine,
+ .adjtime = fbnic_ptp_adjtime,
+ .gettimex64 = fbnic_ptp_gettimex64,
+ .settime64 = fbnic_ptp_settime64,
+};
+
+static void fbnic_ptp_reset(struct fbnic_dev *fbd)
+{
+ struct fbnic_net *fbn = netdev_priv(fbd->netdev);
+ u64 dclk_period;
+
+ fbnic_wr32(fbd, FBNIC_PTP_CTRL,
+ FBNIC_PTP_CTRL_EN |
+ FIELD_PREP(FBNIC_PTP_CTRL_TICK_IVAL, 1));
+
+ /* d_clock is 600 MHz; which in Q16.32 fixed point ns is: */
+ dclk_period = (((u64)1000000000) << 32) / FBNIC_CLOCK_FREQ;
+
+ __fbnic_time_set_addend(fbd, dclk_period);
+
+ fbnic_wr32(fbd, FBNIC_PTP_INIT_HI, 0);
+ fbnic_wr32(fbd, FBNIC_PTP_INIT_LO, 0);
+
+ fbnic_wr32(fbd, FBNIC_PTP_ADJUST, FBNIC_PTP_ADJUST_INIT);
+
+ fbnic_wr32(fbd, FBNIC_PTP_CTRL,
+ FBNIC_PTP_CTRL_EN |
+ FBNIC_PTP_CTRL_TQS_OUT_EN |
+ FIELD_PREP(FBNIC_PTP_CTRL_MAC_OUT_IVAL, 3) |
+ FIELD_PREP(FBNIC_PTP_CTRL_TICK_IVAL, 1));
+
+ fbnic_rd32(fbd, FBNIC_PTP_SPARE);
+
+ fbn->time_offset = 0;
+ fbn->time_high = 0;
+}
+
+void fbnic_time_init(struct fbnic_net *fbn)
+{
+ /* This is not really a statistic, but the lockng primitive fits
+ * our usecase perfectly, we need an atomic 8 bytes READ_ONCE() /
+ * WRITE_ONCE() behavior.
+ */
+ u64_stats_init(&fbn->time_seq);
+}
+
+int fbnic_time_start(struct fbnic_net *fbn)
+{
+ fbnic_ptp_refresh_time(fbn->fbd, fbn);
+ /* Assume that fbnic_ptp_do_aux_work() will never be called if not
+ * scheduled here
+ */
+ return ptp_schedule_worker(fbn->fbd->ptp, FBNIC_TS_HIGH_REFRESH_JIF);
+}
+
+void fbnic_time_stop(struct fbnic_net *fbn)
+{
+ ptp_cancel_worker_sync(fbn->fbd->ptp);
+ fbnic_ptp_fresh_check(fbn->fbd);
+}
+
+int fbnic_ptp_setup(struct fbnic_dev *fbd)
+{
+ struct device *dev = fbd->dev;
+ unsigned long flags;
+
+ spin_lock_init(&fbd->time_lock);
+
+ spin_lock_irqsave(&fbd->time_lock, flags); /* Appease lockdep */
+ fbnic_ptp_reset(fbd);
+ spin_unlock_irqrestore(&fbd->time_lock, flags);
+
+ memcpy(&fbd->ptp_info, &fbnic_ptp_info, sizeof(fbnic_ptp_info));
+
+ fbd->ptp = ptp_clock_register(&fbd->ptp_info, dev);
+ if (IS_ERR(fbd->ptp))
+ dev_err(dev, "Failed to register PTP: %pe\n", fbd->ptp);
+
+ return PTR_ERR_OR_ZERO(fbd->ptp);
+}
+
+void fbnic_ptp_destroy(struct fbnic_dev *fbd)
+{
+ if (!fbd->ptp)
+ return;
+ ptp_clock_unregister(fbd->ptp);
+}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
index 6a6d7e22f1a7..b5050fabe8fe 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
@@ -12,9 +12,14 @@
#include "fbnic_netdev.h"
#include "fbnic_txrx.h"
+enum {
+ FBNIC_XMIT_CB_TS = 0x01,
+};
+
struct fbnic_xmit_cb {
u32 bytecount;
u8 desc_count;
+ u8 flags;
int hw_head;
};
@@ -43,6 +48,46 @@ static void fbnic_ring_wr32(struct fbnic_ring *ring, unsigned int csr, u32 val)
writel(val, csr_base + csr);
}
+/**
+ * fbnic_ts40_to_ns() - convert descriptor timestamp to PHC time
+ * @fbn: netdev priv of the FB NIC
+ * @ts40: timestamp read from a descriptor
+ *
+ * Return: u64 value of PHC time in nanoseconds
+ *
+ * Convert truncated 40 bit device timestamp as read from a descriptor
+ * to the full PHC time in nanoseconds.
+ */
+static __maybe_unused u64 fbnic_ts40_to_ns(struct fbnic_net *fbn, u64 ts40)
+{
+ unsigned int s;
+ u64 time_ns;
+ s64 offset;
+ u8 ts_top;
+ u32 high;
+
+ do {
+ s = u64_stats_fetch_begin(&fbn->time_seq);
+ offset = READ_ONCE(fbn->time_offset);
+ } while (u64_stats_fetch_retry(&fbn->time_seq, s));
+
+ high = READ_ONCE(fbn->time_high);
+
+ /* Bits 63..40 from periodic clock reads, 39..0 from ts40 */
+ time_ns = (u64)(high >> 8) << 40 | ts40;
+
+ /* Compare bits 32-39 between periodic reads and ts40,
+ * see if HW clock may have wrapped since last read. We are sure
+ * that periodic reads are always at least ~1 minute behind, so
+ * this logic works perfectly fine.
+ */
+ ts_top = ts40 >> 32;
+ if (ts_top < (u8)high && (u8)high - ts_top > U8_MAX / 2)
+ time_ns += 1ULL << 40;
+
+ return time_ns + offset;
+}
+
static unsigned int fbnic_desc_unused(struct fbnic_ring *ring)
{
return (ring->head - ring->tail - 1) & ring->size_mask;
@@ -110,11 +155,32 @@ static void fbnic_unmap_page_twd(struct device *dev, __le64 *twd)
#define FBNIC_TWD_TYPE(_type) \
cpu_to_le64(FIELD_PREP(FBNIC_TWD_TYPE_MASK, FBNIC_TWD_TYPE_##_type))
+static bool fbnic_tx_tstamp(struct sk_buff *skb)
+{
+ struct fbnic_net *fbn;
+
+ if (!unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
+ return false;
+
+ fbn = netdev_priv(skb->dev);
+ if (fbn->hwtstamp_config.tx_type == HWTSTAMP_TX_OFF)
+ return false;
+
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ FBNIC_XMIT_CB(skb)->flags |= FBNIC_XMIT_CB_TS;
+ FBNIC_XMIT_CB(skb)->hw_head = -1;
+
+ return true;
+}
+
static bool
fbnic_tx_offloads(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
{
unsigned int l2len, i3len;
+ if (fbnic_tx_tstamp(skb))
+ *meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_TS);
+
if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL))
return false;
@@ -205,6 +271,9 @@ fbnic_tx_map(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
ring->tail = tail;
+ /* Record SW timestamp */
+ skb_tx_timestamp(skb);
+
/* Verify there is room for another packet */
fbnic_maybe_stop_tx(skb->dev, ring, FBNIC_MAX_SKB_DESC);
@@ -316,7 +385,7 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget,
struct fbnic_ring *ring, bool discard,
unsigned int hw_head)
{
- u64 total_bytes = 0, total_packets = 0;
+ u64 total_bytes = 0, total_packets = 0, ts_lost = 0;
unsigned int head = ring->head;
struct netdev_queue *txq;
unsigned int clean_desc;
@@ -331,6 +400,13 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget,
if (desc_cnt > clean_desc)
break;
+ if (unlikely(FBNIC_XMIT_CB(skb)->flags & FBNIC_XMIT_CB_TS)) {
+ FBNIC_XMIT_CB(skb)->hw_head = hw_head;
+ if (likely(!discard))
+ break;
+ ts_lost++;
+ }
+
ring->tx_buf[head] = NULL;
clean_desc -= desc_cnt;
@@ -368,6 +444,7 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget,
if (unlikely(discard)) {
u64_stats_update_begin(&ring->stats.syncp);
ring->stats.dropped += total_packets;
+ ring->stats.ts_lost += ts_lost;
u64_stats_update_end(&ring->stats.syncp);
netdev_tx_completed_queue(txq, total_packets, total_bytes);
@@ -384,6 +461,56 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget,
FBNIC_TX_DESC_WAKEUP);
}
+static void fbnic_clean_tsq(struct fbnic_napi_vector *nv,
+ struct fbnic_ring *ring,
+ u64 tcd, int *ts_head, int *head0)
+{
+ struct skb_shared_hwtstamps hwtstamp;
+ struct fbnic_net *fbn;
+ struct sk_buff *skb;
+ int head;
+ u64 ns;
+
+ head = (*ts_head < 0) ? ring->head : *ts_head;
+
+ do {
+ unsigned int desc_cnt;
+
+ if (head == ring->tail) {
+ if (unlikely(net_ratelimit()))
+ netdev_err(nv->napi.dev,
+ "Tx timestamp without matching packet\n");
+ return;
+ }
+
+ skb = ring->tx_buf[head];
+ desc_cnt = FBNIC_XMIT_CB(skb)->desc_count;
+
+ head += desc_cnt;
+ head &= ring->size_mask;
+ } while (!(FBNIC_XMIT_CB(skb)->flags & FBNIC_XMIT_CB_TS));
+
+ fbn = netdev_priv(nv->napi.dev);
+ ns = fbnic_ts40_to_ns(fbn, FIELD_GET(FBNIC_TCD_TYPE1_TS_MASK, tcd));
+
+ memset(&hwtstamp, 0, sizeof(hwtstamp));
+ hwtstamp.hwtstamp = ns_to_ktime(ns);
+
+ *ts_head = head;
+
+ FBNIC_XMIT_CB(skb)->flags &= ~FBNIC_XMIT_CB_TS;
+ if (*head0 < 0) {
+ head = FBNIC_XMIT_CB(skb)->hw_head;
+ if (head >= 0)
+ *head0 = head;
+ }
+
+ skb_tstamp_tx(skb, &hwtstamp);
+ u64_stats_update_begin(&ring->stats.syncp);
+ ring->stats.ts_packets++;
+ u64_stats_update_end(&ring->stats.syncp);
+}
+
static void fbnic_page_pool_init(struct fbnic_ring *ring, unsigned int idx,
struct page *page)
{
@@ -417,10 +544,12 @@ static void fbnic_page_pool_drain(struct fbnic_ring *ring, unsigned int idx,
}
static void fbnic_clean_twq(struct fbnic_napi_vector *nv, int napi_budget,
- struct fbnic_q_triad *qt, s32 head0)
+ struct fbnic_q_triad *qt, s32 ts_head, s32 head0)
{
if (head0 >= 0)
fbnic_clean_twq0(nv, napi_budget, &qt->sub0, false, head0);
+ else if (ts_head >= 0)
+ fbnic_clean_twq0(nv, napi_budget, &qt->sub0, false, ts_head);
}
static void
@@ -428,9 +557,9 @@ fbnic_clean_tcq(struct fbnic_napi_vector *nv, struct fbnic_q_triad *qt,
int napi_budget)
{
struct fbnic_ring *cmpl = &qt->cmpl;
+ s32 head0 = -1, ts_head = -1;
__le64 *raw_tcd, done;
u32 head = cmpl->head;
- s32 head0 = -1;
done = (head & (cmpl->size_mask + 1)) ? 0 : cpu_to_le64(FBNIC_TCD_DONE);
raw_tcd = &cmpl->desc[head & cmpl->size_mask];
@@ -453,6 +582,12 @@ fbnic_clean_tcq(struct fbnic_napi_vector *nv, struct fbnic_q_triad *qt,
* they are skipped for now.
*/
break;
+ case FBNIC_TCD_TYPE_1:
+ if (WARN_ON_ONCE(tcd & FBNIC_TCD_TWQ1))
+ break;
+
+ fbnic_clean_tsq(nv, &qt->sub0, tcd, &ts_head, &head0);
+ break;
default:
break;
}
@@ -472,7 +607,7 @@ fbnic_clean_tcq(struct fbnic_napi_vector *nv, struct fbnic_q_triad *qt,
}
/* Unmap and free processed buffers */
- fbnic_clean_twq(nv, napi_budget, qt, head0);
+ fbnic_clean_twq(nv, napi_budget, qt, ts_head, head0);
}
static void fbnic_clean_bdq(struct fbnic_napi_vector *nv, int napi_budget,
@@ -707,6 +842,10 @@ static struct sk_buff *fbnic_build_skb(struct fbnic_napi_vector *nv,
/* Set MAC header specific fields */
skb->protocol = eth_type_trans(skb, nv->napi.dev);
+ /* Add timestamp if present */
+ if (pkt->hwtstamp)
+ skb_hwtstamps(skb)->hwtstamp = pkt->hwtstamp;
+
return skb;
}
@@ -717,6 +856,23 @@ static enum pkt_hash_types fbnic_skb_hash_type(u64 rcd)
PKT_HASH_TYPE_L2;
}
+static void fbnic_rx_tstamp(struct fbnic_napi_vector *nv, u64 rcd,
+ struct fbnic_pkt_buff *pkt)
+{
+ struct fbnic_net *fbn;
+ u64 ns, ts;
+
+ if (!FIELD_GET(FBNIC_RCD_OPT_META_TS, rcd))
+ return;
+
+ fbn = netdev_priv(nv->napi.dev);
+ ts = FIELD_GET(FBNIC_RCD_OPT_META_TS_MASK, rcd);
+ ns = fbnic_ts40_to_ns(fbn, ts);
+
+ /* Add timestamp to shared info */
+ pkt->hwtstamp = ns_to_ktime(ns);
+}
+
static void fbnic_populate_skb_fields(struct fbnic_napi_vector *nv,
u64 rcd, struct sk_buff *skb,
struct fbnic_q_triad *qt)
@@ -781,6 +937,8 @@ static int fbnic_clean_rcq(struct fbnic_napi_vector *nv,
if (FIELD_GET(FBNIC_RCD_OPT_META_TYPE_MASK, rcd))
break;
+ fbnic_rx_tstamp(nv, rcd, pkt);
+
/* We currently ignore the action table index */
break;
case FBNIC_RCD_TYPE_META:
@@ -907,6 +1065,8 @@ static void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn,
fbn->tx_stats.bytes += stats->bytes;
fbn->tx_stats.packets += stats->packets;
fbn->tx_stats.dropped += stats->dropped;
+ fbn->tx_stats.ts_lost += stats->ts_lost;
+ fbn->tx_stats.ts_packets += stats->ts_packets;
}
static void fbnic_remove_tx_ring(struct fbnic_net *fbn,
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
index 2f91f68d11d5..8d626287c3f4 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
@@ -47,6 +47,7 @@ struct fbnic_net;
struct fbnic_pkt_buff {
struct xdp_buff buff;
+ ktime_t hwtstamp;
u32 data_truesize;
u16 data_len;
u16 nr_frags;
@@ -56,6 +57,8 @@ struct fbnic_queue_stats {
u64 packets;
u64 bytes;
u64 dropped;
+ u64 ts_packets;
+ u64 ts_lost;
struct u64_stats_sync syncp;
};
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index ddd87ef71caf..c7b0b09c2b09 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -1247,7 +1247,7 @@ static struct platform_driver ks8842_platform_driver = {
.name = DRV_NAME,
},
.probe = ks8842_probe,
- .remove_new = ks8842_remove,
+ .remove = ks8842_remove,
};
module_platform_driver(ks8842_platform_driver);
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
index 7fa1820db9cc..bb5138806c3f 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -216,22 +216,6 @@ static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np)
}
/**
- * ks8851_dbg_dumpkkt - dump initial packet contents to debug
- * @ks: The device state
- * @rxpkt: The data for the received packet
- *
- * Dump the initial data from the packet to dev_dbg().
- */
-static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
-{
- netdev_dbg(ks->netdev,
- "pkt %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",
- rxpkt[4], rxpkt[5], rxpkt[6], rxpkt[7],
- rxpkt[8], rxpkt[9], rxpkt[10], rxpkt[11],
- rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]);
-}
-
-/**
* ks8851_rx_pkts - receive packets from the host
* @ks: The device information.
* @rxq: Queue of packets received in this function.
@@ -296,8 +280,8 @@ static void ks8851_rx_pkts(struct ks8851_net *ks, struct sk_buff_head *rxq)
ks->rdfifo(ks, rxpkt, rxalign + 8);
- if (netif_msg_pktdata(ks))
- ks8851_dbg_dumpkkt(ks, rxpkt);
+ netif_dbg(ks, pktdata, ks->netdev,
+ "pkt %12ph\n", &rxpkt[4]);
skb->protocol = eth_type_trans(skb, ks->netdev);
__skb_queue_tail(rxq, skb);
diff --git a/drivers/net/ethernet/micrel/ks8851_par.c b/drivers/net/ethernet/micrel/ks8851_par.c
index 381b9cd285eb..78695be2570b 100644
--- a/drivers/net/ethernet/micrel/ks8851_par.c
+++ b/drivers/net/ethernet/micrel/ks8851_par.c
@@ -334,7 +334,7 @@ static struct platform_driver ks8851_driver = {
.pm = &ks8851_pm_ops,
},
.probe = ks8851_probe_par,
- .remove_new = ks8851_remove_par,
+ .remove = ks8851_remove_par,
};
module_platform_driver(ks8851_driver);
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index ee046468652c..73832fb2bc32 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -59,6 +59,7 @@ config LAN743X
source "drivers/net/ethernet/microchip/lan865x/Kconfig"
source "drivers/net/ethernet/microchip/lan966x/Kconfig"
+source "drivers/net/ethernet/microchip/lan969x/Kconfig"
source "drivers/net/ethernet/microchip/sparx5/Kconfig"
source "drivers/net/ethernet/microchip/vcap/Kconfig"
source "drivers/net/ethernet/microchip/fdma/Kconfig"
diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
index 3c65baed9fd8..7770df82200f 100644
--- a/drivers/net/ethernet/microchip/Makefile
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -11,6 +11,7 @@ lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
obj-$(CONFIG_LAN865X) += lan865x/
obj-$(CONFIG_LAN966X_SWITCH) += lan966x/
+obj-$(CONFIG_LAN969X_SWITCH) += lan969x/
obj-$(CONFIG_SPARX5_SWITCH) += sparx5/
obj-$(CONFIG_VCAP) += vcap/
obj-$(CONFIG_FDMA) += fdma/
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index 534d4716d5f7..3234a960fcc3 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -1285,7 +1285,7 @@ static void lan966x_remove(struct platform_device *pdev)
static struct platform_driver lan966x_driver = {
.probe = lan966x_probe,
- .remove_new = lan966x_remove,
+ .remove = lan966x_remove,
.driver = {
.name = "lan966x-switch",
.of_match_table = lan966x_match,
diff --git a/drivers/net/ethernet/microchip/lan969x/Kconfig b/drivers/net/ethernet/microchip/lan969x/Kconfig
new file mode 100644
index 000000000000..c5c6122ae2ec
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/Kconfig
@@ -0,0 +1,5 @@
+config LAN969X_SWITCH
+ bool "Lan969x switch driver"
+ depends on SPARX5_SWITCH
+ help
+ This driver supports the lan969x family of network switch devices.
diff --git a/drivers/net/ethernet/microchip/lan969x/Makefile b/drivers/net/ethernet/microchip/lan969x/Makefile
new file mode 100644
index 000000000000..316405cbbc71
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for the Microchip lan969x network device drivers.
+#
+
+obj-$(CONFIG_SPARX5_SWITCH) += lan969x-switch.o
+
+lan969x-switch-y := lan969x_regs.o lan969x.o lan969x_calendar.o \
+ lan969x_vcap_ag_api.o lan969x_vcap_impl.o
+
+# Provide include files
+ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/fdma
+ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/vcap
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x.c b/drivers/net/ethernet/microchip/lan969x/lan969x.c
new file mode 100644
index 000000000000..ac37d0f74ee3
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/lan969x.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip lan969x Switch driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include "lan969x.h"
+
+#define LAN969X_SDLB_GRP_CNT 5
+#define LAN969X_HSCH_LEAK_GRP_CNT 4
+
+static const struct sparx5_main_io_resource lan969x_main_iomap[] = {
+ { TARGET_CPU, 0xc0000, 0 }, /* 0xe00c0000 */
+ { TARGET_FDMA, 0xc0400, 0 }, /* 0xe00c0400 */
+ { TARGET_GCB, 0x2010000, 1 }, /* 0xe2010000 */
+ { TARGET_QS, 0x2030000, 1 }, /* 0xe2030000 */
+ { TARGET_PTP, 0x2040000, 1 }, /* 0xe2040000 */
+ { TARGET_ANA_ACL, 0x2050000, 1 }, /* 0xe2050000 */
+ { TARGET_LRN, 0x2060000, 1 }, /* 0xe2060000 */
+ { TARGET_VCAP_SUPER, 0x2080000, 1 }, /* 0xe2080000 */
+ { TARGET_QSYS, 0x20a0000, 1 }, /* 0xe20a0000 */
+ { TARGET_QFWD, 0x20b0000, 1 }, /* 0xe20b0000 */
+ { TARGET_XQS, 0x20c0000, 1 }, /* 0xe20c0000 */
+ { TARGET_VCAP_ES2, 0x20d0000, 1 }, /* 0xe20d0000 */
+ { TARGET_VCAP_ES0, 0x20e0000, 1 }, /* 0xe20e0000 */
+ { TARGET_ANA_AC_POL, 0x2200000, 1 }, /* 0xe2200000 */
+ { TARGET_QRES, 0x2280000, 1 }, /* 0xe2280000 */
+ { TARGET_EACL, 0x22c0000, 1 }, /* 0xe22c0000 */
+ { TARGET_ANA_CL, 0x2400000, 1 }, /* 0xe2400000 */
+ { TARGET_ANA_L3, 0x2480000, 1 }, /* 0xe2480000 */
+ { TARGET_ANA_AC_SDLB, 0x2500000, 1 }, /* 0xe2500000 */
+ { TARGET_HSCH, 0x2580000, 1 }, /* 0xe2580000 */
+ { TARGET_REW, 0x2600000, 1 }, /* 0xe2600000 */
+ { TARGET_ANA_L2, 0x2800000, 1 }, /* 0xe2800000 */
+ { TARGET_ANA_AC, 0x2900000, 1 }, /* 0xe2900000 */
+ { TARGET_VOP, 0x2a00000, 1 }, /* 0xe2a00000 */
+ { TARGET_DEV2G5, 0x3004000, 1 }, /* 0xe3004000 */
+ { TARGET_DEV10G, 0x3008000, 1 }, /* 0xe3008000 */
+ { TARGET_PCS10G_BR, 0x300c000, 1 }, /* 0xe300c000 */
+ { TARGET_DEV2G5 + 1, 0x3010000, 1 }, /* 0xe3010000 */
+ { TARGET_DEV2G5 + 2, 0x3014000, 1 }, /* 0xe3014000 */
+ { TARGET_DEV2G5 + 3, 0x3018000, 1 }, /* 0xe3018000 */
+ { TARGET_DEV2G5 + 4, 0x301c000, 1 }, /* 0xe301c000 */
+ { TARGET_DEV10G + 1, 0x3020000, 1 }, /* 0xe3020000 */
+ { TARGET_PCS10G_BR + 1, 0x3024000, 1 }, /* 0xe3024000 */
+ { TARGET_DEV2G5 + 5, 0x3028000, 1 }, /* 0xe3028000 */
+ { TARGET_DEV2G5 + 6, 0x302c000, 1 }, /* 0xe302c000 */
+ { TARGET_DEV2G5 + 7, 0x3030000, 1 }, /* 0xe3030000 */
+ { TARGET_DEV2G5 + 8, 0x3034000, 1 }, /* 0xe3034000 */
+ { TARGET_DEV10G + 2, 0x3038000, 1 }, /* 0xe3038000 */
+ { TARGET_PCS10G_BR + 2, 0x303c000, 1 }, /* 0xe303c000 */
+ { TARGET_DEV2G5 + 9, 0x3040000, 1 }, /* 0xe3040000 */
+ { TARGET_DEV5G, 0x3044000, 1 }, /* 0xe3044000 */
+ { TARGET_PCS5G_BR, 0x3048000, 1 }, /* 0xe3048000 */
+ { TARGET_DEV2G5 + 10, 0x304c000, 1 }, /* 0xe304c000 */
+ { TARGET_DEV2G5 + 11, 0x3050000, 1 }, /* 0xe3050000 */
+ { TARGET_DEV2G5 + 12, 0x3054000, 1 }, /* 0xe3054000 */
+ { TARGET_DEV10G + 3, 0x3058000, 1 }, /* 0xe3058000 */
+ { TARGET_PCS10G_BR + 3, 0x305c000, 1 }, /* 0xe305c000 */
+ { TARGET_DEV2G5 + 13, 0x3060000, 1 }, /* 0xe3060000 */
+ { TARGET_DEV5G + 1, 0x3064000, 1 }, /* 0xe3064000 */
+ { TARGET_PCS5G_BR + 1, 0x3068000, 1 }, /* 0xe3068000 */
+ { TARGET_DEV2G5 + 14, 0x306c000, 1 }, /* 0xe306c000 */
+ { TARGET_DEV2G5 + 15, 0x3070000, 1 }, /* 0xe3070000 */
+ { TARGET_DEV2G5 + 16, 0x3074000, 1 }, /* 0xe3074000 */
+ { TARGET_DEV10G + 4, 0x3078000, 1 }, /* 0xe3078000 */
+ { TARGET_PCS10G_BR + 4, 0x307c000, 1 }, /* 0xe307c000 */
+ { TARGET_DEV2G5 + 17, 0x3080000, 1 }, /* 0xe3080000 */
+ { TARGET_DEV5G + 2, 0x3084000, 1 }, /* 0xe3084000 */
+ { TARGET_PCS5G_BR + 2, 0x3088000, 1 }, /* 0xe3088000 */
+ { TARGET_DEV2G5 + 18, 0x308c000, 1 }, /* 0xe308c000 */
+ { TARGET_DEV2G5 + 19, 0x3090000, 1 }, /* 0xe3090000 */
+ { TARGET_DEV2G5 + 20, 0x3094000, 1 }, /* 0xe3094000 */
+ { TARGET_DEV10G + 5, 0x3098000, 1 }, /* 0xe3098000 */
+ { TARGET_PCS10G_BR + 5, 0x309c000, 1 }, /* 0xe309c000 */
+ { TARGET_DEV2G5 + 21, 0x30a0000, 1 }, /* 0xe30a0000 */
+ { TARGET_DEV5G + 3, 0x30a4000, 1 }, /* 0xe30a4000 */
+ { TARGET_PCS5G_BR + 3, 0x30a8000, 1 }, /* 0xe30a8000 */
+ { TARGET_DEV2G5 + 22, 0x30ac000, 1 }, /* 0xe30ac000 */
+ { TARGET_DEV2G5 + 23, 0x30b0000, 1 }, /* 0xe30b0000 */
+ { TARGET_DEV2G5 + 24, 0x30b4000, 1 }, /* 0xe30b4000 */
+ { TARGET_DEV10G + 6, 0x30b8000, 1 }, /* 0xe30b8000 */
+ { TARGET_PCS10G_BR + 6, 0x30bc000, 1 }, /* 0xe30bc000 */
+ { TARGET_DEV2G5 + 25, 0x30c0000, 1 }, /* 0xe30c0000 */
+ { TARGET_DEV10G + 7, 0x30c4000, 1 }, /* 0xe30c4000 */
+ { TARGET_PCS10G_BR + 7, 0x30c8000, 1 }, /* 0xe30c8000 */
+ { TARGET_DEV2G5 + 26, 0x30cc000, 1 }, /* 0xe30cc000 */
+ { TARGET_DEV10G + 8, 0x30d0000, 1 }, /* 0xe30d0000 */
+ { TARGET_PCS10G_BR + 8, 0x30d4000, 1 }, /* 0xe30d4000 */
+ { TARGET_DEV2G5 + 27, 0x30d8000, 1 }, /* 0xe30d8000 */
+ { TARGET_DEV10G + 9, 0x30dc000, 1 }, /* 0xe30dc000 */
+ { TARGET_PCS10G_BR + 9, 0x30e0000, 1 }, /* 0xe30e0000 */
+ { TARGET_DSM, 0x30ec000, 1 }, /* 0xe30ec000 */
+ { TARGET_PORT_CONF, 0x30f0000, 1 }, /* 0xe30f0000 */
+ { TARGET_ASM, 0x3200000, 1 }, /* 0xe3200000 */
+};
+
+static struct sparx5_sdlb_group lan969x_sdlb_groups[LAN969X_SDLB_GRP_CNT] = {
+ { 1000000000, 8192 / 2, 64 }, /* 1 G */
+ { 500000000, 8192 / 2, 64 }, /* 500 M */
+ { 100000000, 8192 / 4, 64 }, /* 100 M */
+ { 50000000, 8192 / 4, 64 }, /* 50 M */
+ { 5000000, 8192 / 8, 64 }, /* 10 M */
+};
+
+static u32 lan969x_hsch_max_group_rate[LAN969X_HSCH_LEAK_GRP_CNT] = {
+ 655355, 1048568, 6553550, 10485680
+};
+
+static struct sparx5_sdlb_group *lan969x_get_sdlb_group(int idx)
+{
+ return &lan969x_sdlb_groups[idx];
+}
+
+static u32 lan969x_get_hsch_max_group_rate(int grp)
+{
+ return lan969x_hsch_max_group_rate[grp];
+}
+
+static u32 lan969x_get_dev_mode_bit(struct sparx5 *sparx5, int port)
+{
+ if (lan969x_port_is_2g5(port) || lan969x_port_is_5g(port))
+ return port;
+
+ /* 10G */
+ switch (port) {
+ case 0:
+ return 12;
+ case 4:
+ return 13;
+ case 8:
+ return 14;
+ case 12:
+ return 0;
+ default:
+ return port;
+ }
+}
+
+static u32 lan969x_port_dev_mapping(struct sparx5 *sparx5, int port)
+{
+ if (lan969x_port_is_5g(port)) {
+ switch (port) {
+ case 9:
+ return 0;
+ case 13:
+ return 1;
+ case 17:
+ return 2;
+ case 21:
+ return 3;
+ }
+ }
+
+ if (lan969x_port_is_10g(port)) {
+ switch (port) {
+ case 0:
+ return 0;
+ case 4:
+ return 1;
+ case 8:
+ return 2;
+ case 12:
+ return 3;
+ case 16:
+ return 4;
+ case 20:
+ return 5;
+ case 24:
+ return 6;
+ case 25:
+ return 7;
+ case 26:
+ return 8;
+ case 27:
+ return 9;
+ }
+ }
+
+ /* 2g5 port */
+ return port;
+}
+
+static int lan969x_port_mux_set(struct sparx5 *sparx5, struct sparx5_port *port,
+ struct sparx5_port_config *conf)
+{
+ u32 portno = port->portno;
+ u32 inst;
+
+ if (port->conf.portmode == conf->portmode)
+ return 0; /* Nothing to do */
+
+ switch (conf->portmode) {
+ case PHY_INTERFACE_MODE_QSGMII: /* QSGMII: 4x2G5 devices. Mode Q' */
+ inst = (portno - portno % 4) / 4;
+ spx5_rmw(BIT(inst), BIT(inst), sparx5, PORT_CONF_QSGMII_ENA);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static irqreturn_t lan969x_ptp_irq_handler(int irq, void *args)
+{
+ int budget = SPARX5_MAX_PTP_ID;
+ struct sparx5 *sparx5 = args;
+
+ while (budget--) {
+ struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct sparx5_port *port;
+ struct timespec64 ts;
+ unsigned long flags;
+ u32 val, id, txport;
+ u32 delay;
+
+ val = spx5_rd(sparx5, PTP_TWOSTEP_CTRL);
+
+ /* Check if a timestamp can be retrieved */
+ if (!(val & PTP_TWOSTEP_CTRL_PTP_VLD))
+ break;
+
+ WARN_ON(val & PTP_TWOSTEP_CTRL_PTP_OVFL);
+
+ if (!(val & PTP_TWOSTEP_CTRL_STAMP_TX))
+ continue;
+
+ /* Retrieve the ts Tx port */
+ txport = PTP_TWOSTEP_CTRL_STAMP_PORT_GET(val);
+
+ /* Retrieve its associated skb */
+ port = sparx5->ports[txport];
+
+ /* Retrieve the delay */
+ delay = spx5_rd(sparx5, PTP_TWOSTEP_STAMP_NSEC);
+ delay = PTP_TWOSTEP_STAMP_NSEC_NS_GET(delay);
+
+ /* Get next timestamp from fifo, which needs to be the
+ * rx timestamp which represents the id of the frame
+ */
+ spx5_rmw(PTP_TWOSTEP_CTRL_PTP_NXT_SET(1),
+ PTP_TWOSTEP_CTRL_PTP_NXT,
+ sparx5, PTP_TWOSTEP_CTRL);
+
+ val = spx5_rd(sparx5, PTP_TWOSTEP_CTRL);
+
+ /* Check if a timestamp can be retrieved */
+ if (!(val & PTP_TWOSTEP_CTRL_PTP_VLD))
+ break;
+
+ /* Read RX timestamping to get the ID */
+ id = spx5_rd(sparx5, PTP_TWOSTEP_STAMP_NSEC);
+ id <<= 8;
+ id |= spx5_rd(sparx5, PTP_TWOSTEP_STAMP_SUBNS);
+
+ spin_lock_irqsave(&port->tx_skbs.lock, flags);
+ skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
+ if (SPARX5_SKB_CB(skb)->ts_id != id)
+ continue;
+
+ __skb_unlink(skb, &port->tx_skbs);
+ skb_match = skb;
+ break;
+ }
+ spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
+
+ /* Next ts */
+ spx5_rmw(PTP_TWOSTEP_CTRL_PTP_NXT_SET(1),
+ PTP_TWOSTEP_CTRL_PTP_NXT,
+ sparx5, PTP_TWOSTEP_CTRL);
+
+ if (WARN_ON(!skb_match))
+ continue;
+
+ spin_lock(&sparx5->ptp_ts_id_lock);
+ sparx5->ptp_skbs--;
+ spin_unlock(&sparx5->ptp_ts_id_lock);
+
+ /* Get the h/w timestamp */
+ sparx5_get_hwtimestamp(sparx5, &ts, delay);
+
+ /* Set the timestamp in the skb */
+ shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+ skb_tstamp_tx(skb_match, &shhwtstamps);
+
+ dev_kfree_skb_any(skb_match);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static const struct sparx5_regs lan969x_regs = {
+ .tsize = lan969x_tsize,
+ .gaddr = lan969x_gaddr,
+ .gcnt = lan969x_gcnt,
+ .gsize = lan969x_gsize,
+ .raddr = lan969x_raddr,
+ .rcnt = lan969x_rcnt,
+ .fpos = lan969x_fpos,
+ .fsize = lan969x_fsize,
+};
+
+static const struct sparx5_consts lan969x_consts = {
+ .n_ports = 30,
+ .n_ports_all = 35,
+ .n_hsch_l1_elems = 32,
+ .n_hsch_queues = 4,
+ .n_lb_groups = 5,
+ .n_pgids = 1054, /* (1024 + n_ports) */
+ .n_sio_clks = 1,
+ .n_own_upsids = 1,
+ .n_auto_cals = 4,
+ .n_filters = 256,
+ .n_gates = 256,
+ .n_sdlbs = 496,
+ .n_dsm_cal_taxis = 5,
+ .buf_size = 1572864,
+ .qres_max_prio_idx = 315,
+ .qres_max_colour_idx = 323,
+ .tod_pin = 4,
+ .vcaps = lan969x_vcaps,
+ .vcap_stats = &lan969x_vcap_stats,
+ .vcaps_cfg = lan969x_vcap_inst_cfg,
+};
+
+static const struct sparx5_ops lan969x_ops = {
+ .is_port_2g5 = &lan969x_port_is_2g5,
+ .is_port_5g = &lan969x_port_is_5g,
+ .is_port_10g = &lan969x_port_is_10g,
+ .is_port_25g = &lan969x_port_is_25g,
+ .get_port_dev_index = &lan969x_port_dev_mapping,
+ .get_port_dev_bit = &lan969x_get_dev_mode_bit,
+ .get_hsch_max_group_rate = &lan969x_get_hsch_max_group_rate,
+ .get_sdlb_group = &lan969x_get_sdlb_group,
+ .set_port_mux = &lan969x_port_mux_set,
+ .ptp_irq_handler = &lan969x_ptp_irq_handler,
+ .dsm_calendar_calc = &lan969x_dsm_calendar_calc,
+};
+
+const struct sparx5_match_data lan969x_desc = {
+ .iomap = lan969x_main_iomap,
+ .iomap_size = ARRAY_SIZE(lan969x_main_iomap),
+ .ioranges = 2,
+ .regs = &lan969x_regs,
+ .consts = &lan969x_consts,
+ .ops = &lan969x_ops,
+};
+EXPORT_SYMBOL_GPL(lan969x_desc);
+
+MODULE_DESCRIPTION("Microchip lan969x switch driver");
+MODULE_AUTHOR("Daniel Machon <daniel.machon@microchip.com>");
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x.h b/drivers/net/ethernet/microchip/lan969x/lan969x.h
new file mode 100644
index 000000000000..2489d0d32dfd
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/lan969x.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Microchip lan969x Switch driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#ifndef __LAN969X_H__
+#define __LAN969X_H__
+
+#include "../sparx5/sparx5_main.h"
+#include "../sparx5/sparx5_regs.h"
+#include "../sparx5/sparx5_vcap_impl.h"
+
+/* lan969x.c */
+extern const struct sparx5_match_data lan969x_desc;
+
+/* lan969x_vcap_ag_api.c */
+extern const struct vcap_statistics lan969x_vcap_stats;
+extern const struct vcap_info lan969x_vcaps[];
+
+/* lan969x_vcap_impl.c */
+extern const struct sparx5_vcap_inst lan969x_vcap_inst_cfg[];
+
+/* lan969x_regs.c */
+extern const unsigned int lan969x_tsize[TSIZE_LAST];
+extern const unsigned int lan969x_raddr[RADDR_LAST];
+extern const unsigned int lan969x_rcnt[RCNT_LAST];
+extern const unsigned int lan969x_gaddr[GADDR_LAST];
+extern const unsigned int lan969x_gcnt[GCNT_LAST];
+extern const unsigned int lan969x_gsize[GSIZE_LAST];
+extern const unsigned int lan969x_fpos[FPOS_LAST];
+extern const unsigned int lan969x_fsize[FSIZE_LAST];
+
+static inline bool lan969x_port_is_2g5(int portno)
+{
+ return portno == 1 || portno == 2 || portno == 3 ||
+ portno == 5 || portno == 6 || portno == 7 ||
+ portno == 10 || portno == 11 || portno == 14 ||
+ portno == 15 || portno == 18 || portno == 19 ||
+ portno == 22 || portno == 23;
+}
+
+static inline bool lan969x_port_is_5g(int portno)
+{
+ return portno == 9 || portno == 13 || portno == 17 ||
+ portno == 21;
+}
+
+static inline bool lan969x_port_is_10g(int portno)
+{
+ return portno == 0 || portno == 4 || portno == 8 ||
+ portno == 12 || portno == 16 || portno == 20 ||
+ portno == 24 || portno == 25 || portno == 26 ||
+ portno == 27;
+}
+
+static inline bool lan969x_port_is_25g(int portno)
+{
+ return false;
+}
+
+/* lan969x_calendar.c */
+int lan969x_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
+ struct sparx5_calendar_data *data);
+#endif
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_calendar.c b/drivers/net/ethernet/microchip/lan969x/lan969x_calendar.c
new file mode 100644
index 000000000000..e857640df185
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/lan969x_calendar.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip lan969x Switch driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include "lan969x.h"
+
+#define LAN969X_DSM_CAL_DEVS_PER_TAXI 10
+#define LAN969X_DSM_CAL_TAXIS 5
+
+enum lan969x_dsm_cal_dev {
+ DSM_CAL_DEV_2G5,
+ DSM_CAL_DEV_5G,
+ DSM_CAL_DEV_10G,
+ DSM_CAL_DEV_OTHER, /* 1G or less */
+ DSM_CAL_DEV_MAX
+};
+
+/* Each entry in the following struct defines properties for a given speed
+ * (10G, 5G, 2.5G, or 1G or less).
+ */
+struct lan969x_dsm_cal_dev_speed {
+ /* Number of devices that requires this speed. */
+ u32 n_devs;
+
+ /* Array of devices that requires this speed. */
+ u32 devs[LAN969X_DSM_CAL_DEVS_PER_TAXI];
+
+ /* Number of slots required for one device running this speed. */
+ u32 n_slots;
+
+ /* Gap between two slots for one device running this speed. */
+ u32 gap;
+};
+
+static u32
+lan969x_taxi_ports[LAN969X_DSM_CAL_TAXIS][LAN969X_DSM_CAL_DEVS_PER_TAXI] = {
+ { 0, 4, 1, 2, 3, 5, 6, 7, 28, 29 },
+ { 8, 12, 9, 13, 10, 11, 14, 15, 99, 99 },
+ { 16, 20, 17, 21, 18, 19, 22, 23, 99, 99 },
+ { 24, 25, 99, 99, 99, 99, 99, 99, 99, 99 },
+ { 26, 27, 99, 99, 99, 99, 99, 99, 99, 99 }
+};
+
+static int lan969x_dsm_cal_idx_get(u32 *calendar, u32 cal_len, u32 *cal_idx)
+{
+ if (*cal_idx >= cal_len)
+ return -EINVAL;
+
+ do {
+ if (calendar[*cal_idx] == SPX5_DSM_CAL_EMPTY)
+ return 0;
+
+ (*cal_idx)++;
+ } while (*cal_idx < cal_len);
+
+ return -ENOENT;
+}
+
+static enum lan969x_dsm_cal_dev lan969x_dsm_cal_get_dev(int speed)
+{
+ return (speed == 10000 ? DSM_CAL_DEV_10G :
+ speed == 5000 ? DSM_CAL_DEV_5G :
+ speed == 2500 ? DSM_CAL_DEV_2G5 :
+ DSM_CAL_DEV_OTHER);
+}
+
+static int lan969x_dsm_cal_get_speed(enum lan969x_dsm_cal_dev dev)
+{
+ return (dev == DSM_CAL_DEV_10G ? 10000 :
+ dev == DSM_CAL_DEV_5G ? 5000 :
+ dev == DSM_CAL_DEV_2G5 ? 2500 :
+ 1000);
+}
+
+int lan969x_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
+ struct sparx5_calendar_data *data)
+{
+ struct lan969x_dsm_cal_dev_speed dev_speeds[DSM_CAL_DEV_MAX] = {};
+ u32 cal_len, n_slots, taxi_bw, n_devs = 0, required_bw = 0;
+ struct lan969x_dsm_cal_dev_speed *speed;
+ int err;
+
+ /* Maximum bandwidth for this taxi */
+ taxi_bw = (128 * 1000000) / sparx5_clk_period(sparx5->coreclock);
+
+ memcpy(data->taxi_ports, &lan969x_taxi_ports[taxi],
+ LAN969X_DSM_CAL_DEVS_PER_TAXI * sizeof(u32));
+
+ for (int i = 0; i < LAN969X_DSM_CAL_DEVS_PER_TAXI; i++) {
+ u32 portno = data->taxi_ports[i];
+ enum sparx5_cal_bw bw;
+
+ bw = sparx5_get_port_cal_speed(sparx5, portno);
+
+ if (portno < sparx5->data->consts->n_ports_all)
+ data->taxi_speeds[i] = sparx5_cal_speed_to_value(bw);
+ else
+ data->taxi_speeds[i] = 0;
+ }
+
+ /* Determine the different port types (10G, 5G, 2.5G, <= 1G) in the
+ * this taxi map.
+ */
+ for (int i = 0; i < LAN969X_DSM_CAL_DEVS_PER_TAXI; i++) {
+ u32 taxi_speed = data->taxi_speeds[i];
+ enum lan969x_dsm_cal_dev dev;
+
+ if (taxi_speed == 0)
+ continue;
+
+ required_bw += taxi_speed;
+
+ dev = lan969x_dsm_cal_get_dev(taxi_speed);
+ speed = &dev_speeds[dev];
+ speed->devs[speed->n_devs++] = i;
+ n_devs++;
+ }
+
+ if (required_bw > taxi_bw) {
+ pr_err("Required bandwidth: %u is higher than total taxi bandwidth: %u",
+ required_bw, taxi_bw);
+ return -EINVAL;
+ }
+
+ if (n_devs == 0) {
+ data->schedule[0] = SPX5_DSM_CAL_EMPTY;
+ return 0;
+ }
+
+ cal_len = n_devs;
+
+ /* Search for a calendar length that fits all active devices. */
+ while (cal_len < SPX5_DSM_CAL_LEN) {
+ u32 bw_per_slot = taxi_bw / cal_len;
+
+ n_slots = 0;
+
+ for (int i = 0; i < DSM_CAL_DEV_MAX; i++) {
+ speed = &dev_speeds[i];
+
+ if (speed->n_devs == 0)
+ continue;
+
+ required_bw = lan969x_dsm_cal_get_speed(i);
+ speed->n_slots = DIV_ROUND_UP(required_bw, bw_per_slot);
+
+ if (speed->n_slots)
+ speed->gap = DIV_ROUND_UP(cal_len,
+ speed->n_slots);
+ else
+ speed->gap = 0;
+
+ n_slots += speed->n_slots * speed->n_devs;
+ }
+
+ if (n_slots <= cal_len)
+ break; /* Found a suitable calendar length. */
+
+ /* Not good enough yet. */
+ cal_len = n_slots;
+ }
+
+ if (cal_len > SPX5_DSM_CAL_LEN) {
+ pr_err("Invalid length: %u for taxi: %u", cal_len, taxi);
+ return -EINVAL;
+ }
+
+ for (u32 i = 0; i < SPX5_DSM_CAL_LEN; i++)
+ data->schedule[i] = SPX5_DSM_CAL_EMPTY;
+
+ /* Place the remaining devices */
+ for (u32 i = 0; i < DSM_CAL_DEV_MAX; i++) {
+ speed = &dev_speeds[i];
+ for (u32 dev = 0; dev < speed->n_devs; dev++) {
+ u32 idx = 0;
+
+ for (n_slots = 0; n_slots < speed->n_slots; n_slots++) {
+ err = lan969x_dsm_cal_idx_get(data->schedule,
+ cal_len, &idx);
+ if (err)
+ return err;
+ data->schedule[idx] = speed->devs[dev];
+ idx += speed->gap;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_regs.c b/drivers/net/ethernet/microchip/lan969x/lan969x_regs.c
new file mode 100644
index 000000000000..ace4ba21eec4
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/lan969x_regs.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip lan969x Switch driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc.
+ */
+
+/* This file is autogenerated by cml-utils 2024-09-30 11:48:29 +0200.
+ * Commit ID: 9d07b8d19363f3cd3590ddb3f7a2e2768e16524b
+ */
+
+#include "lan969x.h"
+
+const unsigned int lan969x_tsize[TSIZE_LAST] = {
+ [TC_DEV10G] = 10,
+ [TC_DEV2G5] = 28,
+ [TC_DEV5G] = 4,
+ [TC_PCS10G_BR] = 10,
+ [TC_PCS5G_BR] = 4,
+};
+
+const unsigned int lan969x_raddr[RADDR_LAST] = {
+ [RA_CPU_PROC_CTRL] = 160,
+ [RA_GCB_SOFT_RST] = 12,
+ [RA_GCB_HW_SGPIO_TO_SD_MAP_CFG] = 20,
+};
+
+const unsigned int lan969x_rcnt[RCNT_LAST] = {
+ [RC_ANA_AC_OWN_UPSID] = 1,
+ [RC_ANA_ACL_VCAP_S2_CFG] = 35,
+ [RC_ANA_ACL_OWN_UPSID] = 1,
+ [RC_ANA_CL_OWN_UPSID] = 1,
+ [RC_ANA_L2_OWN_UPSID] = 1,
+ [RC_ASM_PORT_CFG] = 32,
+ [RC_DSM_BUF_CFG] = 32,
+ [RC_DSM_DEV_TX_STOP_WM_CFG] = 32,
+ [RC_DSM_RX_PAUSE_CFG] = 32,
+ [RC_DSM_MAC_CFG] = 32,
+ [RC_DSM_MAC_ADDR_BASE_HIGH_CFG] = 30,
+ [RC_DSM_MAC_ADDR_BASE_LOW_CFG] = 30,
+ [RC_DSM_TAXI_CAL_CFG] = 6,
+ [RC_GCB_HW_SGPIO_TO_SD_MAP_CFG] = 30,
+ [RC_HSCH_PORT_MODE] = 35,
+ [RC_QFWD_SWITCH_PORT_MODE] = 35,
+ [RC_QSYS_PAUSE_CFG] = 35,
+ [RC_QSYS_ATOP] = 35,
+ [RC_QSYS_FWD_PRESSURE] = 35,
+ [RC_QSYS_CAL_AUTO] = 4,
+ [RC_REW_OWN_UPSID] = 1,
+ [RC_REW_RTAG_ETAG_CTRL] = 35,
+};
+
+const unsigned int lan969x_gaddr[GADDR_LAST] = {
+ [GA_ANA_AC_RAM_CTRL] = 202000,
+ [GA_ANA_AC_PS_COMMON] = 202880,
+ [GA_ANA_AC_MIRROR_PROBE] = 203232,
+ [GA_ANA_AC_SRC] = 201728,
+ [GA_ANA_AC_PGID] = 131072,
+ [GA_ANA_AC_TSN_SF] = 202028,
+ [GA_ANA_AC_TSN_SF_CFG] = 148480,
+ [GA_ANA_AC_TSN_SF_STATUS] = 147936,
+ [GA_ANA_AC_SG_ACCESS] = 202032,
+ [GA_ANA_AC_SG_CONFIG] = 202752,
+ [GA_ANA_AC_SG_STATUS] = 147952,
+ [GA_ANA_AC_SG_STATUS_STICKY] = 202044,
+ [GA_ANA_AC_STAT_GLOBAL_CFG_PORT] = 202048,
+ [GA_ANA_AC_STAT_CNT_CFG_PORT] = 204800,
+ [GA_ANA_AC_STAT_GLOBAL_CFG_ACL] = 202068,
+ [GA_ANA_ACL_COMMON] = 8192,
+ [GA_ANA_ACL_KEY_SEL] = 9204,
+ [GA_ANA_ACL_CNT_B] = 4096,
+ [GA_ANA_ACL_STICKY] = 10852,
+ [GA_ANA_AC_POL_POL_ALL_CFG] = 17504,
+ [GA_ANA_AC_POL_COMMON_BDLB] = 19464,
+ [GA_ANA_AC_POL_COMMON_BUM_SLB] = 19472,
+ [GA_ANA_AC_SDLB_LBGRP_TBL] = 31788,
+ [GA_ANA_CL_PORT] = 65536,
+ [GA_ANA_CL_COMMON] = 87040,
+ [GA_ANA_L2_COMMON] = 561928,
+ [GA_ANA_L3_COMMON] = 370752,
+ [GA_ANA_L3_VLAN_ARP_L3MC_STICKY] = 368580,
+ [GA_ASM_CFG] = 18304,
+ [GA_ASM_PFC_TIMER_CFG] = 15568,
+ [GA_ASM_LBK_WM_CFG] = 15596,
+ [GA_ASM_LBK_MISC_CFG] = 15608,
+ [GA_ASM_RAM_CTRL] = 15684,
+ [GA_EACL_ES2_KEY_SELECT_PROFILE] = 36864,
+ [GA_EACL_CNT_TBL] = 30720,
+ [GA_EACL_POL_CFG] = 38400,
+ [GA_EACL_ES2_STICKY] = 29072,
+ [GA_EACL_RAM_CTRL] = 29112,
+ [GA_GCB_SIO_CTRL] = 560,
+ [GA_HSCH_HSCH_DWRR] = 36480,
+ [GA_HSCH_HSCH_MISC] = 36608,
+ [GA_HSCH_HSCH_LEAK_LISTS] = 37256,
+ [GA_HSCH_SYSTEM] = 37384,
+ [GA_HSCH_MMGT] = 36260,
+ [GA_HSCH_TAS_CONFIG] = 37696,
+ [GA_PTP_PTP_CFG] = 512,
+ [GA_PTP_PTP_TOD_DOMAINS] = 528,
+ [GA_PTP_PHASE_DETECTOR_CTRL] = 628,
+ [GA_QSYS_CALCFG] = 2164,
+ [GA_QSYS_RAM_CTRL] = 2204,
+ [GA_REW_COMMON] = 98304,
+ [GA_REW_PORT] = 49152,
+ [GA_REW_VOE_PORT_LM_CNT] = 90112,
+ [GA_REW_RAM_CTRL] = 93992,
+ [GA_VOP_RAM_CTRL] = 16368,
+ [GA_XQS_SYSTEM] = 5744,
+ [GA_XQS_QLIMIT_SHR] = 6912,
+};
+
+const unsigned int lan969x_gcnt[GCNT_LAST] = {
+ [GC_ANA_AC_SRC] = 67,
+ [GC_ANA_AC_PGID] = 1054,
+ [GC_ANA_AC_TSN_SF_CFG] = 256,
+ [GC_ANA_AC_STAT_CNT_CFG_PORT] = 35,
+ [GC_ANA_ACL_KEY_SEL] = 99,
+ [GC_ANA_ACL_CNT_A] = 1024,
+ [GC_ANA_ACL_CNT_B] = 1024,
+ [GC_ANA_AC_SDLB_LBGRP_TBL] = 5,
+ [GC_ANA_AC_SDLB_LBSET_TBL] = 496,
+ [GC_ANA_CL_PORT] = 35,
+ [GC_ANA_L2_ISDX_LIMIT] = 256,
+ [GC_ANA_L2_ISDX] = 1024,
+ [GC_ANA_L3_VLAN] = 4608,
+ [GC_ASM_DEV_STATISTICS] = 30,
+ [GC_EACL_ES2_KEY_SELECT_PROFILE] = 68,
+ [GC_EACL_CNT_TBL] = 512,
+ [GC_GCB_SIO_CTRL] = 1,
+ [GC_HSCH_HSCH_CFG] = 1120,
+ [GC_HSCH_HSCH_DWRR] = 32,
+ [GC_PTP_PTP_PINS] = 8,
+ [GC_PTP_PHASE_DETECTOR_CTRL] = 8,
+ [GC_REW_PORT] = 35,
+ [GC_REW_VOE_PORT_LM_CNT] = 240,
+};
+
+const unsigned int lan969x_gsize[GSIZE_LAST] = {
+ [GW_ANA_AC_SRC] = 4,
+ [GW_ANA_L2_COMMON] = 712,
+ [GW_ASM_CFG] = 1092,
+ [GW_CPU_CPU_REGS] = 180,
+ [GW_DEV2G5_PHASE_DETECTOR_CTRL] = 12,
+ [GW_FDMA_FDMA] = 448,
+ [GW_GCB_CHIP_REGS] = 180,
+ [GW_HSCH_TAS_CONFIG] = 16,
+ [GW_PTP_PHASE_DETECTOR_CTRL] = 12,
+ [GW_QSYS_PAUSE_CFG] = 988,
+};
+
+const unsigned int lan969x_fpos[FPOS_LAST] = {
+ [FP_CPU_PROC_CTRL_AARCH64_MODE_ENA] = 7,
+ [FP_CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS] = 6,
+ [FP_CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS] = 5,
+ [FP_CPU_PROC_CTRL_BE_EXCEP_MODE] = 4,
+ [FP_CPU_PROC_CTRL_VINITHI] = 3,
+ [FP_CPU_PROC_CTRL_CFGTE] = 2,
+ [FP_CPU_PROC_CTRL_CP15S_DISABLE] = 1,
+ [FP_CPU_PROC_CTRL_PROC_CRYPTO_DISABLE] = 0,
+ [FP_CPU_PROC_CTRL_L2_FLUSH_REQ] = 8,
+ [FP_DEV2G5_PHAD_CTRL_PHAD_ENA] = 5,
+ [FP_DEV2G5_PHAD_CTRL_PHAD_FAILED] = 3,
+ [FP_FDMA_CH_CFG_CH_XTR_STATUS_MODE] = 5,
+ [FP_FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY] = 4,
+ [FP_FDMA_CH_CFG_CH_INJ_PORT] = 3,
+ [FP_PTP_PTP_PIN_CFG_PTP_PIN_ACTION] = 27,
+ [FP_PTP_PTP_PIN_CFG_PTP_PIN_SYNC] = 25,
+ [FP_PTP_PTP_PIN_CFG_PTP_PIN_INV_POL] = 24,
+ [FP_PTP_PHAD_CTRL_PHAD_ENA] = 5,
+ [FP_PTP_PHAD_CTRL_PHAD_FAILED] = 3,
+};
+
+const unsigned int lan969x_fsize[FSIZE_LAST] = {
+ [FW_ANA_AC_PROBE_PORT_CFG_PROBE_PORT_MASK] = 30,
+ [FW_ANA_AC_SRC_CFG_PORT_MASK] = 30,
+ [FW_ANA_AC_PGID_CFG_PORT_MASK] = 30,
+ [FW_ANA_AC_TSN_SF_PORT_NUM] = 7,
+ [FW_ANA_AC_TSN_SF_CFG_TSN_SGID] = 8,
+ [FW_ANA_AC_TSN_SF_STATUS_TSN_SFID] = 8,
+ [FW_ANA_AC_SG_ACCESS_CTRL_SGID] = 8,
+ [FW_ANA_AC_PORT_SGE_CFG_MASK] = 17,
+ [FW_ANA_AC_SDLB_XLB_START_LBSET_START] = 9,
+ [FW_ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT] = 3,
+ [FW_ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT] = 9,
+ [FW_ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT] = 9,
+ [FW_ANA_AC_SDLB_XLB_NEXT_LBGRP] = 3,
+ [FW_ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR] = 9,
+ [FW_ANA_L2_AUTO_LRN_CFG_AUTO_LRN_ENA] = 30,
+ [FW_ANA_L2_DLB_CFG_DLB_IDX] = 9,
+ [FW_ANA_L2_TSN_CFG_TSN_SFID] = 8,
+ [FW_ANA_L3_VLAN_MASK_CFG_VLAN_PORT_MASK] = 30,
+ [FW_FDMA_CH_CFG_CH_DCB_DB_CNT] = 2,
+ [FW_GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL] = 7,
+ [FW_HSCH_SE_CFG_SE_DWRR_CNT] = 5,
+ [FW_HSCH_SE_CONNECT_SE_LEAK_LINK] = 14,
+ [FW_HSCH_SE_DLB_SENSE_SE_DLB_DPORT] = 6,
+ [FW_HSCH_HSCH_CFG_CFG_CFG_SE_IDX] = 11,
+ [FW_HSCH_HSCH_LEAK_CFG_LEAK_FIRST] = 14,
+ [FW_HSCH_FLUSH_CTRL_FLUSH_PORT] = 6,
+ [FW_HSCH_FLUSH_CTRL_FLUSH_HIER] = 14,
+ [FW_LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW] = 13,
+ [FW_LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX] = 8,
+ [FW_LRN_AUTOAGE_CFG_2_NEXT_ROW] = 13,
+ [FW_PTP_PTP_PIN_INTR_INTR_PTP] = 8,
+ [FW_PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA] = 8,
+ [FW_PTP_PTP_INTR_IDENT_INTR_PTP_IDENT] = 8,
+ [FW_PTP_PTP_PIN_CFG_PTP_PIN_SELECT] = 3,
+ [FW_QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL] = 6,
+ [FW_QRES_RES_CFG_WM_HIGH] = 11,
+ [FW_QRES_RES_STAT_MAXUSE] = 19,
+ [FW_QRES_RES_STAT_CUR_INUSE] = 19,
+ [FW_QSYS_PAUSE_CFG_PAUSE_START] = 11,
+ [FW_QSYS_PAUSE_CFG_PAUSE_STOP] = 11,
+ [FW_QSYS_ATOP_ATOP] = 11,
+ [FW_QSYS_ATOP_TOT_CFG_ATOP_TOT] = 11,
+ [FW_REW_RTAG_ETAG_CTRL_IPE_TBL] = 6,
+ [FW_XQS_STAT_CFG_STAT_VIEW] = 10,
+ [FW_XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP] = 14,
+ [FW_XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP] = 14,
+ [FW_XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP] = 14,
+ [FW_XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM] = 14,
+};
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_ag_api.c b/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_ag_api.c
new file mode 100644
index 000000000000..7acc5bcf337a
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_ag_api.c
@@ -0,0 +1,3843 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries.
+ * Microchip VCAP API
+ */
+
+/* This file is autogenerated by cml-utils 2024-10-07 11:10:56 +0200.
+ * Commit ID: b5ddc8e244eb2481a9524f1ddc630a8b41e7c391
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include "lan969x.h"
+
+/* keyfields */
+static const struct vcap_field is0_normal_7tuple_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 0,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 1,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_GEN_IDX_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 2,
+ .width = 2,
+ },
+ [VCAP_KF_LOOKUP_GEN_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 4,
+ .width = 10,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U72,
+ .offset = 16,
+ .width = 65,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 81,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 82,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 83,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_TPID0] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 86,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_PCP0] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 89,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 92,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID0] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 93,
+ .width = 12,
+ },
+ [VCAP_KF_8021Q_TPID1] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 105,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_PCP1] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 108,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI1] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 111,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID1] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 112,
+ .width = 12,
+ },
+ [VCAP_KF_8021Q_TPID2] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 124,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_PCP2] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 127,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI2] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 130,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID2] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 131,
+ .width = 12,
+ },
+ [VCAP_KF_L2_DMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 144,
+ .width = 48,
+ },
+ [VCAP_KF_L2_SMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 192,
+ .width = 48,
+ },
+ [VCAP_KF_IP_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 240,
+ .width = 1,
+ },
+ [VCAP_KF_ETYPE_LEN_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 241,
+ .width = 1,
+ },
+ [VCAP_KF_ETYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 242,
+ .width = 16,
+ },
+ [VCAP_KF_IP_SNAP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 258,
+ .width = 1,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 259,
+ .width = 1,
+ },
+ [VCAP_KF_L3_FRAGMENT_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 260,
+ .width = 2,
+ },
+ [VCAP_KF_L3_FRAG_INVLD_L4_LEN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 262,
+ .width = 1,
+ },
+ [VCAP_KF_L3_OPTIONS_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 263,
+ .width = 1,
+ },
+ [VCAP_KF_L3_DSCP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 264,
+ .width = 6,
+ },
+ [VCAP_KF_L3_IP6_DIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 270,
+ .width = 128,
+ },
+ [VCAP_KF_L3_IP6_SIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 398,
+ .width = 128,
+ },
+ [VCAP_KF_TCP_UDP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 526,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 527,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 528,
+ .width = 16,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 544,
+ .width = 8,
+ },
+};
+
+static const struct vcap_field is0_normal_5tuple_ip4_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 2,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 2,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_GEN_IDX_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 3,
+ .width = 2,
+ },
+ [VCAP_KF_LOOKUP_GEN_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 5,
+ .width = 10,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 15,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U72,
+ .offset = 17,
+ .width = 65,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 82,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 83,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 84,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_TPID0] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 87,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_PCP0] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 90,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 93,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID0] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 94,
+ .width = 12,
+ },
+ [VCAP_KF_8021Q_TPID1] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 106,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_PCP1] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 109,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI1] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 112,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID1] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 113,
+ .width = 12,
+ },
+ [VCAP_KF_8021Q_TPID2] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 125,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_PCP2] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 128,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI2] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 131,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID2] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 132,
+ .width = 12,
+ },
+ [VCAP_KF_IP_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 145,
+ .width = 1,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 146,
+ .width = 1,
+ },
+ [VCAP_KF_L3_FRAGMENT_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 147,
+ .width = 2,
+ },
+ [VCAP_KF_L3_FRAG_INVLD_L4_LEN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 149,
+ .width = 1,
+ },
+ [VCAP_KF_L3_OPTIONS_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 150,
+ .width = 1,
+ },
+ [VCAP_KF_L3_DSCP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 151,
+ .width = 6,
+ },
+ [VCAP_KF_L3_IP4_DIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 157,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP4_SIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 189,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP_PROTO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 221,
+ .width = 8,
+ },
+ [VCAP_KF_TCP_UDP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 229,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 230,
+ .width = 1,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 231,
+ .width = 8,
+ },
+ [VCAP_KF_IP_PAYLOAD_5TUPLE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 239,
+ .width = 32,
+ },
+};
+
+static const struct vcap_field is2_mac_etype_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 4,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 4,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_PAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 5,
+ .width = 8,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_L3] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 18,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 20,
+ .width = 32,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 52,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 53,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 54,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 56,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 57,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 67,
+ .width = 13,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 80,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 81,
+ .width = 3,
+ },
+ [VCAP_KF_L2_FWD_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_L3_DST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 88,
+ .width = 1,
+ },
+ [VCAP_KF_L2_DMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 89,
+ .width = 48,
+ },
+ [VCAP_KF_L2_SMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 137,
+ .width = 48,
+ },
+ [VCAP_KF_ETYPE_LEN_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 185,
+ .width = 1,
+ },
+ [VCAP_KF_ETYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 186,
+ .width = 16,
+ },
+ [VCAP_KF_L2_PAYLOAD_ETYPE] = {
+ .type = VCAP_FIELD_U64,
+ .offset = 202,
+ .width = 64,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 266,
+ .width = 16,
+ },
+ [VCAP_KF_OAM_CCM_CNTS_EQ0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 282,
+ .width = 1,
+ },
+ [VCAP_KF_OAM_Y1731_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 283,
+ .width = 1,
+ },
+};
+
+static const struct vcap_field is2_arp_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 4,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 4,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_PAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 5,
+ .width = 8,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_L3] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 18,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 20,
+ .width = 32,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 52,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 53,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 54,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 56,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 57,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 67,
+ .width = 13,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 80,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 81,
+ .width = 3,
+ },
+ [VCAP_KF_L2_FWD_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_KF_L2_SMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 85,
+ .width = 48,
+ },
+ [VCAP_KF_ARP_ADDR_SPACE_OK_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 133,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_PROTO_SPACE_OK_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 134,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_LEN_OK_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 135,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_TGT_MATCH_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 136,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_SENDER_MATCH_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 137,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_OPCODE_UNKNOWN_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 138,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_OPCODE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 139,
+ .width = 2,
+ },
+ [VCAP_KF_L3_IP4_DIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 141,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP4_SIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 173,
+ .width = 32,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 205,
+ .width = 1,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 206,
+ .width = 16,
+ },
+};
+
+static const struct vcap_field is2_ip4_tcp_udp_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 4,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 4,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_PAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 5,
+ .width = 8,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_L3] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 18,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 20,
+ .width = 32,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 52,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 53,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 54,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 56,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 57,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 67,
+ .width = 13,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 80,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 81,
+ .width = 3,
+ },
+ [VCAP_KF_L2_FWD_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_L3_DST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 88,
+ .width = 1,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 89,
+ .width = 1,
+ },
+ [VCAP_KF_L3_FRAGMENT_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 90,
+ .width = 2,
+ },
+ [VCAP_KF_L3_FRAG_INVLD_L4_LEN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 92,
+ .width = 1,
+ },
+ [VCAP_KF_L3_OPTIONS_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 93,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 94,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TOS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 95,
+ .width = 8,
+ },
+ [VCAP_KF_L3_IP4_DIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 103,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP4_SIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 135,
+ .width = 32,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 167,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 168,
+ .width = 1,
+ },
+ [VCAP_KF_L4_DPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 169,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 185,
+ .width = 16,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 201,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT_EQ_DPORT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 217,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SEQUENCE_EQ0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 218,
+ .width = 1,
+ },
+ [VCAP_KF_L4_FIN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 219,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SYN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 220,
+ .width = 1,
+ },
+ [VCAP_KF_L4_RST] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 221,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PSH] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 222,
+ .width = 1,
+ },
+ [VCAP_KF_L4_ACK] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 223,
+ .width = 1,
+ },
+ [VCAP_KF_L4_URG] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 224,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PAYLOAD] = {
+ .type = VCAP_FIELD_U64,
+ .offset = 225,
+ .width = 64,
+ },
+};
+
+static const struct vcap_field is2_ip4_other_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 4,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 4,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_PAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 5,
+ .width = 8,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_L3] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 18,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 20,
+ .width = 32,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 52,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 53,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 54,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 56,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 57,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 67,
+ .width = 13,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 80,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 81,
+ .width = 3,
+ },
+ [VCAP_KF_L2_FWD_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_L3_DST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 88,
+ .width = 1,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 89,
+ .width = 1,
+ },
+ [VCAP_KF_L3_FRAGMENT_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 90,
+ .width = 2,
+ },
+ [VCAP_KF_L3_FRAG_INVLD_L4_LEN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 92,
+ .width = 1,
+ },
+ [VCAP_KF_L3_OPTIONS_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 93,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 94,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TOS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 95,
+ .width = 8,
+ },
+ [VCAP_KF_L3_IP4_DIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 103,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP4_SIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 135,
+ .width = 32,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 167,
+ .width = 1,
+ },
+ [VCAP_KF_L3_IP_PROTO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 168,
+ .width = 8,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 176,
+ .width = 16,
+ },
+ [VCAP_KF_L3_PAYLOAD] = {
+ .type = VCAP_FIELD_U112,
+ .offset = 192,
+ .width = 96,
+ },
+};
+
+static const struct vcap_field is2_ip6_std_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 4,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 4,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_PAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 5,
+ .width = 8,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_L3] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 18,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 20,
+ .width = 32,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 52,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 53,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 54,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 56,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 57,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 67,
+ .width = 13,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 80,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 81,
+ .width = 3,
+ },
+ [VCAP_KF_L2_FWD_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 89,
+ .width = 1,
+ },
+ [VCAP_KF_L3_IP6_SIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 90,
+ .width = 128,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 218,
+ .width = 1,
+ },
+ [VCAP_KF_L3_IP_PROTO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 219,
+ .width = 8,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 227,
+ .width = 16,
+ },
+ [VCAP_KF_L3_PAYLOAD] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 243,
+ .width = 40,
+ },
+};
+
+static const struct vcap_field is2_ip_7tuple_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 2,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 2,
+ .width = 1,
+ },
+ [VCAP_KF_LOOKUP_PAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 3,
+ .width = 8,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_L3] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 11,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 12,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 16,
+ .width = 2,
+ },
+ [VCAP_KF_IF_IGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U72,
+ .offset = 18,
+ .width = 65,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 83,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 85,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 88,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 98,
+ .width = 13,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 111,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 112,
+ .width = 3,
+ },
+ [VCAP_KF_L2_FWD_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 115,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 118,
+ .width = 1,
+ },
+ [VCAP_KF_L3_DST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 119,
+ .width = 1,
+ },
+ [VCAP_KF_L2_DMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 120,
+ .width = 48,
+ },
+ [VCAP_KF_L2_SMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 168,
+ .width = 48,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 218,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 219,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TOS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 220,
+ .width = 8,
+ },
+ [VCAP_KF_L3_IP6_DIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 228,
+ .width = 128,
+ },
+ [VCAP_KF_L3_IP6_SIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 356,
+ .width = 128,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 484,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_UDP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 485,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 486,
+ .width = 1,
+ },
+ [VCAP_KF_L4_DPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 487,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 503,
+ .width = 16,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 519,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT_EQ_DPORT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 535,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SEQUENCE_EQ0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 536,
+ .width = 1,
+ },
+ [VCAP_KF_L4_FIN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 537,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SYN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 538,
+ .width = 1,
+ },
+ [VCAP_KF_L4_RST] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 539,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PSH] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 540,
+ .width = 1,
+ },
+ [VCAP_KF_L4_ACK] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 541,
+ .width = 1,
+ },
+ [VCAP_KF_L4_URG] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 542,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PAYLOAD] = {
+ .type = VCAP_FIELD_U64,
+ .offset = 543,
+ .width = 64,
+ },
+};
+
+static const struct vcap_field es0_isdx_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 0,
+ .width = 1,
+ },
+ [VCAP_KF_IF_EGR_PORT_NO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 1,
+ .width = 6,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 7,
+ .width = 13,
+ },
+ [VCAP_KF_COSID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 20,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_TPID] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 23,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 26,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 27,
+ .width = 1,
+ },
+ [VCAP_KF_PROT_ACTIVE] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 28,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 38,
+ .width = 10,
+ },
+};
+
+static const struct vcap_field es2_mac_etype_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 3,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 3,
+ .width = 1,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 14,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 15,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 16,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 26,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 28,
+ .width = 13,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 41,
+ .width = 3,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 44,
+ .width = 32,
+ },
+ [VCAP_KF_IF_IGR_PORT_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 76,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 77,
+ .width = 7,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 84,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_COSID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 88,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 91,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 92,
+ .width = 1,
+ },
+ [VCAP_KF_L2_DMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 96,
+ .width = 48,
+ },
+ [VCAP_KF_L2_SMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 144,
+ .width = 48,
+ },
+ [VCAP_KF_ETYPE_LEN_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 192,
+ .width = 1,
+ },
+ [VCAP_KF_ETYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 193,
+ .width = 16,
+ },
+ [VCAP_KF_L2_PAYLOAD_ETYPE] = {
+ .type = VCAP_FIELD_U64,
+ .offset = 209,
+ .width = 64,
+ },
+ [VCAP_KF_OAM_CCM_CNTS_EQ0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 273,
+ .width = 1,
+ },
+ [VCAP_KF_OAM_Y1731_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 274,
+ .width = 1,
+ },
+};
+
+static const struct vcap_field es2_arp_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 3,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 3,
+ .width = 1,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 14,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 15,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 16,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 26,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 28,
+ .width = 13,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 41,
+ .width = 3,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 44,
+ .width = 32,
+ },
+ [VCAP_KF_IF_IGR_PORT_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 76,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 77,
+ .width = 7,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 84,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_COSID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 88,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 91,
+ .width = 1,
+ },
+ [VCAP_KF_L2_SMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 95,
+ .width = 48,
+ },
+ [VCAP_KF_ARP_ADDR_SPACE_OK_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 143,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_PROTO_SPACE_OK_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 144,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_LEN_OK_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 145,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_TGT_MATCH_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 146,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_SENDER_MATCH_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 147,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_OPCODE_UNKNOWN_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 148,
+ .width = 1,
+ },
+ [VCAP_KF_ARP_OPCODE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 149,
+ .width = 2,
+ },
+ [VCAP_KF_L3_IP4_DIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 151,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP4_SIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 183,
+ .width = 32,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 215,
+ .width = 1,
+ },
+};
+
+static const struct vcap_field es2_ip4_tcp_udp_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 3,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 3,
+ .width = 1,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 14,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 15,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 16,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 26,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 28,
+ .width = 13,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 41,
+ .width = 3,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 44,
+ .width = 32,
+ },
+ [VCAP_KF_IF_IGR_PORT_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 76,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 77,
+ .width = 7,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 84,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_COSID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 88,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 91,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 92,
+ .width = 1,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 96,
+ .width = 1,
+ },
+ [VCAP_KF_L3_FRAGMENT_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 97,
+ .width = 2,
+ },
+ [VCAP_KF_L3_OPTIONS_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 99,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 100,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TOS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 101,
+ .width = 8,
+ },
+ [VCAP_KF_L3_IP4_DIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 109,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP4_SIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 141,
+ .width = 32,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 173,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 174,
+ .width = 1,
+ },
+ [VCAP_KF_L4_DPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 175,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 191,
+ .width = 16,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 207,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT_EQ_DPORT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 223,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SEQUENCE_EQ0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 224,
+ .width = 1,
+ },
+ [VCAP_KF_L4_FIN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 225,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SYN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 226,
+ .width = 1,
+ },
+ [VCAP_KF_L4_RST] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 227,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PSH] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 228,
+ .width = 1,
+ },
+ [VCAP_KF_L4_ACK] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 229,
+ .width = 1,
+ },
+ [VCAP_KF_L4_URG] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 230,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PAYLOAD] = {
+ .type = VCAP_FIELD_U64,
+ .offset = 231,
+ .width = 64,
+ },
+};
+
+static const struct vcap_field es2_ip4_other_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 3,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 3,
+ .width = 1,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 14,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 15,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 16,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 26,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 28,
+ .width = 13,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 41,
+ .width = 3,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 44,
+ .width = 32,
+ },
+ [VCAP_KF_IF_IGR_PORT_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 76,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 77,
+ .width = 7,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 84,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_COSID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 88,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 91,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 92,
+ .width = 1,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 96,
+ .width = 1,
+ },
+ [VCAP_KF_L3_FRAGMENT_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 97,
+ .width = 2,
+ },
+ [VCAP_KF_L3_OPTIONS_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 99,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 100,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TOS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 101,
+ .width = 8,
+ },
+ [VCAP_KF_L3_IP4_DIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 109,
+ .width = 32,
+ },
+ [VCAP_KF_L3_IP4_SIP] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 141,
+ .width = 32,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 173,
+ .width = 1,
+ },
+ [VCAP_KF_L3_IP_PROTO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 174,
+ .width = 8,
+ },
+ [VCAP_KF_L3_PAYLOAD] = {
+ .type = VCAP_FIELD_U112,
+ .offset = 182,
+ .width = 96,
+ },
+};
+
+static const struct vcap_field es2_ip_7tuple_keyfield[] = {
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 0,
+ .width = 1,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 10,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 11,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 12,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 13,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 23,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 25,
+ .width = 13,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 38,
+ .width = 3,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 41,
+ .width = 32,
+ },
+ [VCAP_KF_IF_IGR_PORT_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 73,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 74,
+ .width = 7,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 81,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_KF_COSID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 85,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 88,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 89,
+ .width = 1,
+ },
+ [VCAP_KF_L2_DMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 93,
+ .width = 48,
+ },
+ [VCAP_KF_L2_SMAC] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 141,
+ .width = 48,
+ },
+ [VCAP_KF_IP4_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 191,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 192,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TOS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 193,
+ .width = 8,
+ },
+ [VCAP_KF_L3_IP6_DIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 201,
+ .width = 128,
+ },
+ [VCAP_KF_L3_IP6_SIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 329,
+ .width = 128,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 457,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_UDP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 458,
+ .width = 1,
+ },
+ [VCAP_KF_TCP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 459,
+ .width = 1,
+ },
+ [VCAP_KF_L4_DPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 460,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 476,
+ .width = 16,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 492,
+ .width = 16,
+ },
+ [VCAP_KF_L4_SPORT_EQ_DPORT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 508,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SEQUENCE_EQ0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 509,
+ .width = 1,
+ },
+ [VCAP_KF_L4_FIN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 510,
+ .width = 1,
+ },
+ [VCAP_KF_L4_SYN] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 511,
+ .width = 1,
+ },
+ [VCAP_KF_L4_RST] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 512,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PSH] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 513,
+ .width = 1,
+ },
+ [VCAP_KF_L4_ACK] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 514,
+ .width = 1,
+ },
+ [VCAP_KF_L4_URG] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 515,
+ .width = 1,
+ },
+ [VCAP_KF_L4_PAYLOAD] = {
+ .type = VCAP_FIELD_U64,
+ .offset = 516,
+ .width = 64,
+ },
+};
+
+static const struct vcap_field es2_ip6_std_keyfield[] = {
+ [VCAP_KF_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 3,
+ },
+ [VCAP_KF_LOOKUP_FIRST_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 3,
+ .width = 1,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 13,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 14,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 15,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 16,
+ .width = 10,
+ },
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 26,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 28,
+ .width = 13,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 41,
+ .width = 3,
+ },
+ [VCAP_KF_IF_EGR_PORT_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 44,
+ .width = 32,
+ },
+ [VCAP_KF_IF_IGR_PORT_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 76,
+ .width = 1,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 77,
+ .width = 7,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 84,
+ .width = 3,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 87,
+ .width = 1,
+ },
+ [VCAP_KF_COSID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 88,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 91,
+ .width = 1,
+ },
+ [VCAP_KF_L3_RT_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 92,
+ .width = 1,
+ },
+ [VCAP_KF_L3_TTL_GT0] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 96,
+ .width = 1,
+ },
+ [VCAP_KF_L3_IP6_SIP] = {
+ .type = VCAP_FIELD_U128,
+ .offset = 97,
+ .width = 128,
+ },
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 225,
+ .width = 1,
+ },
+ [VCAP_KF_L3_IP_PROTO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 226,
+ .width = 8,
+ },
+ [VCAP_KF_L4_RNG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 234,
+ .width = 16,
+ },
+ [VCAP_KF_L3_PAYLOAD] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 250,
+ .width = 40,
+ },
+};
+
+/* keyfield_set */
+static const struct vcap_set is0_keyfield_set[] = {
+ [VCAP_KFS_NORMAL_7TUPLE] = {
+ .type_id = 0,
+ .sw_per_item = 12,
+ .sw_cnt = 1,
+ },
+ [VCAP_KFS_NORMAL_5TUPLE_IP4] = {
+ .type_id = 2,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+};
+
+static const struct vcap_set is2_keyfield_set[] = {
+ [VCAP_KFS_MAC_ETYPE] = {
+ .type_id = 0,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_ARP] = {
+ .type_id = 3,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_IP4_TCP_UDP] = {
+ .type_id = 4,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_IP4_OTHER] = {
+ .type_id = 5,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_IP6_STD] = {
+ .type_id = 6,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_IP_7TUPLE] = {
+ .type_id = 1,
+ .sw_per_item = 12,
+ .sw_cnt = 1,
+ },
+};
+
+static const struct vcap_set es0_keyfield_set[] = {
+ [VCAP_KFS_ISDX] = {
+ .type_id = 0,
+ .sw_per_item = 1,
+ .sw_cnt = 1,
+ },
+};
+
+static const struct vcap_set es2_keyfield_set[] = {
+ [VCAP_KFS_MAC_ETYPE] = {
+ .type_id = 0,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_ARP] = {
+ .type_id = 1,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_IP4_TCP_UDP] = {
+ .type_id = 2,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_IP4_OTHER] = {
+ .type_id = 3,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+ [VCAP_KFS_IP_7TUPLE] = {
+ .type_id = -1,
+ .sw_per_item = 12,
+ .sw_cnt = 1,
+ },
+ [VCAP_KFS_IP6_STD] = {
+ .type_id = 4,
+ .sw_per_item = 6,
+ .sw_cnt = 2,
+ },
+};
+
+/* keyfield_set map */
+static const struct vcap_field *is0_keyfield_set_map[] = {
+ [VCAP_KFS_NORMAL_7TUPLE] = is0_normal_7tuple_keyfield,
+ [VCAP_KFS_NORMAL_5TUPLE_IP4] = is0_normal_5tuple_ip4_keyfield,
+};
+
+static const struct vcap_field *is2_keyfield_set_map[] = {
+ [VCAP_KFS_MAC_ETYPE] = is2_mac_etype_keyfield,
+ [VCAP_KFS_ARP] = is2_arp_keyfield,
+ [VCAP_KFS_IP4_TCP_UDP] = is2_ip4_tcp_udp_keyfield,
+ [VCAP_KFS_IP4_OTHER] = is2_ip4_other_keyfield,
+ [VCAP_KFS_IP6_STD] = is2_ip6_std_keyfield,
+ [VCAP_KFS_IP_7TUPLE] = is2_ip_7tuple_keyfield,
+};
+
+static const struct vcap_field *es0_keyfield_set_map[] = {
+ [VCAP_KFS_ISDX] = es0_isdx_keyfield,
+};
+
+static const struct vcap_field *es2_keyfield_set_map[] = {
+ [VCAP_KFS_MAC_ETYPE] = es2_mac_etype_keyfield,
+ [VCAP_KFS_ARP] = es2_arp_keyfield,
+ [VCAP_KFS_IP4_TCP_UDP] = es2_ip4_tcp_udp_keyfield,
+ [VCAP_KFS_IP4_OTHER] = es2_ip4_other_keyfield,
+ [VCAP_KFS_IP_7TUPLE] = es2_ip_7tuple_keyfield,
+ [VCAP_KFS_IP6_STD] = es2_ip6_std_keyfield,
+};
+
+/* keyfield_set map sizes */
+static int is0_keyfield_set_map_size[] = {
+ [VCAP_KFS_NORMAL_7TUPLE] = ARRAY_SIZE(is0_normal_7tuple_keyfield),
+ [VCAP_KFS_NORMAL_5TUPLE_IP4] = ARRAY_SIZE(is0_normal_5tuple_ip4_keyfield),
+};
+
+static int is2_keyfield_set_map_size[] = {
+ [VCAP_KFS_MAC_ETYPE] = ARRAY_SIZE(is2_mac_etype_keyfield),
+ [VCAP_KFS_ARP] = ARRAY_SIZE(is2_arp_keyfield),
+ [VCAP_KFS_IP4_TCP_UDP] = ARRAY_SIZE(is2_ip4_tcp_udp_keyfield),
+ [VCAP_KFS_IP4_OTHER] = ARRAY_SIZE(is2_ip4_other_keyfield),
+ [VCAP_KFS_IP6_STD] = ARRAY_SIZE(is2_ip6_std_keyfield),
+ [VCAP_KFS_IP_7TUPLE] = ARRAY_SIZE(is2_ip_7tuple_keyfield),
+};
+
+static int es0_keyfield_set_map_size[] = {
+ [VCAP_KFS_ISDX] = ARRAY_SIZE(es0_isdx_keyfield),
+};
+
+static int es2_keyfield_set_map_size[] = {
+ [VCAP_KFS_MAC_ETYPE] = ARRAY_SIZE(es2_mac_etype_keyfield),
+ [VCAP_KFS_ARP] = ARRAY_SIZE(es2_arp_keyfield),
+ [VCAP_KFS_IP4_TCP_UDP] = ARRAY_SIZE(es2_ip4_tcp_udp_keyfield),
+ [VCAP_KFS_IP4_OTHER] = ARRAY_SIZE(es2_ip4_other_keyfield),
+ [VCAP_KFS_IP_7TUPLE] = ARRAY_SIZE(es2_ip_7tuple_keyfield),
+ [VCAP_KFS_IP6_STD] = ARRAY_SIZE(es2_ip6_std_keyfield),
+};
+
+/* actionfields */
+static const struct vcap_field is0_classification_actionfield[] = {
+ [VCAP_AF_TYPE] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 0,
+ .width = 1,
+ },
+ [VCAP_AF_DSCP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 1,
+ .width = 1,
+ },
+ [VCAP_AF_DSCP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 2,
+ .width = 6,
+ },
+ [VCAP_AF_QOS_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 12,
+ .width = 1,
+ },
+ [VCAP_AF_QOS_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 13,
+ .width = 3,
+ },
+ [VCAP_AF_DP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 16,
+ .width = 1,
+ },
+ [VCAP_AF_DP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 17,
+ .width = 2,
+ },
+ [VCAP_AF_DEI_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 19,
+ .width = 1,
+ },
+ [VCAP_AF_DEI_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 20,
+ .width = 1,
+ },
+ [VCAP_AF_PCP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 21,
+ .width = 1,
+ },
+ [VCAP_AF_PCP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 22,
+ .width = 3,
+ },
+ [VCAP_AF_MAP_LOOKUP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 25,
+ .width = 2,
+ },
+ [VCAP_AF_MAP_KEY] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 27,
+ .width = 3,
+ },
+ [VCAP_AF_MAP_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 30,
+ .width = 7,
+ },
+ [VCAP_AF_CLS_VID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 37,
+ .width = 3,
+ },
+ [VCAP_AF_VID_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 43,
+ .width = 13,
+ },
+ [VCAP_AF_ISDX_ADD_REPLACE_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 66,
+ .width = 1,
+ },
+ [VCAP_AF_ISDX_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 67,
+ .width = 10,
+ },
+ [VCAP_AF_PAG_OVERRIDE_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 107,
+ .width = 8,
+ },
+ [VCAP_AF_PAG_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 115,
+ .width = 8,
+ },
+ [VCAP_AF_NXT_IDX_CTRL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 167,
+ .width = 3,
+ },
+ [VCAP_AF_NXT_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 170,
+ .width = 10,
+ },
+};
+
+static const struct vcap_field is0_full_actionfield[] = {
+ [VCAP_AF_DSCP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 0,
+ .width = 1,
+ },
+ [VCAP_AF_DSCP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 1,
+ .width = 6,
+ },
+ [VCAP_AF_QOS_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 11,
+ .width = 1,
+ },
+ [VCAP_AF_QOS_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 12,
+ .width = 3,
+ },
+ [VCAP_AF_DP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 15,
+ .width = 1,
+ },
+ [VCAP_AF_DP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 16,
+ .width = 2,
+ },
+ [VCAP_AF_DEI_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 18,
+ .width = 1,
+ },
+ [VCAP_AF_DEI_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 19,
+ .width = 1,
+ },
+ [VCAP_AF_PCP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 20,
+ .width = 1,
+ },
+ [VCAP_AF_PCP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 21,
+ .width = 3,
+ },
+ [VCAP_AF_MAP_LOOKUP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 24,
+ .width = 2,
+ },
+ [VCAP_AF_MAP_KEY] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 26,
+ .width = 3,
+ },
+ [VCAP_AF_MAP_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 29,
+ .width = 7,
+ },
+ [VCAP_AF_CLS_VID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 36,
+ .width = 3,
+ },
+ [VCAP_AF_VID_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 42,
+ .width = 13,
+ },
+ [VCAP_AF_ISDX_ADD_REPLACE_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 65,
+ .width = 1,
+ },
+ [VCAP_AF_ISDX_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 66,
+ .width = 10,
+ },
+ [VCAP_AF_MASK_MODE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 76,
+ .width = 3,
+ },
+ [VCAP_AF_PORT_MASK] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 79,
+ .width = 37,
+ },
+ [VCAP_AF_PAG_OVERRIDE_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 174,
+ .width = 8,
+ },
+ [VCAP_AF_PAG_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 182,
+ .width = 8,
+ },
+ [VCAP_AF_NXT_IDX_CTRL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 266,
+ .width = 3,
+ },
+ [VCAP_AF_NXT_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 269,
+ .width = 10,
+ },
+};
+
+static const struct vcap_field is0_class_reduced_actionfield[] = {
+ [VCAP_AF_TYPE] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 0,
+ .width = 1,
+ },
+ [VCAP_AF_QOS_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 5,
+ .width = 1,
+ },
+ [VCAP_AF_QOS_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 6,
+ .width = 3,
+ },
+ [VCAP_AF_DP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 9,
+ .width = 1,
+ },
+ [VCAP_AF_DP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 10,
+ .width = 2,
+ },
+ [VCAP_AF_MAP_LOOKUP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 12,
+ .width = 2,
+ },
+ [VCAP_AF_MAP_KEY] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 3,
+ },
+ [VCAP_AF_CLS_VID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 17,
+ .width = 3,
+ },
+ [VCAP_AF_VID_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 23,
+ .width = 13,
+ },
+ [VCAP_AF_ISDX_ADD_REPLACE_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 46,
+ .width = 1,
+ },
+ [VCAP_AF_ISDX_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 47,
+ .width = 10,
+ },
+ [VCAP_AF_NXT_IDX_CTRL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 89,
+ .width = 3,
+ },
+ [VCAP_AF_NXT_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 92,
+ .width = 10,
+ },
+};
+
+static const struct vcap_field is2_base_type_actionfield[] = {
+ [VCAP_AF_PIPELINE_FORCE_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 1,
+ .width = 1,
+ },
+ [VCAP_AF_PIPELINE_PT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 2,
+ .width = 5,
+ },
+ [VCAP_AF_HIT_ME_ONCE] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 7,
+ .width = 1,
+ },
+ [VCAP_AF_INTR_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 8,
+ .width = 1,
+ },
+ [VCAP_AF_CPU_COPY_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 9,
+ .width = 1,
+ },
+ [VCAP_AF_CPU_QUEUE_NUM] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 10,
+ .width = 3,
+ },
+ [VCAP_AF_LRN_DIS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 15,
+ .width = 1,
+ },
+ [VCAP_AF_RT_DIS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 16,
+ .width = 1,
+ },
+ [VCAP_AF_POLICE_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 17,
+ .width = 1,
+ },
+ [VCAP_AF_POLICE_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 18,
+ .width = 5,
+ },
+ [VCAP_AF_IGNORE_PIPELINE_CTRL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 23,
+ .width = 1,
+ },
+ [VCAP_AF_MASK_MODE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 27,
+ .width = 3,
+ },
+ [VCAP_AF_PORT_MASK] = {
+ .type = VCAP_FIELD_U48,
+ .offset = 30,
+ .width = 37,
+ },
+ [VCAP_AF_MIRROR_PROBE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 78,
+ .width = 2,
+ },
+ [VCAP_AF_MATCH_ID] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 131,
+ .width = 16,
+ },
+ [VCAP_AF_MATCH_ID_MASK] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 147,
+ .width = 16,
+ },
+ [VCAP_AF_CNT_ID] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 163,
+ .width = 10,
+ },
+};
+
+static const struct vcap_field es0_es0_actionfield[] = {
+ [VCAP_AF_PUSH_OUTER_TAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 2,
+ },
+ [VCAP_AF_PUSH_INNER_TAG] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 2,
+ .width = 1,
+ },
+ [VCAP_AF_TAG_A_TPID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 3,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_A_VID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 6,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_A_PCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 8,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_A_DEI_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 11,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_B_TPID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 14,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_B_VID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 17,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_B_PCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 19,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_B_DEI_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 22,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_C_TPID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 25,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_C_PCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 28,
+ .width = 3,
+ },
+ [VCAP_AF_TAG_C_DEI_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 31,
+ .width = 3,
+ },
+ [VCAP_AF_VID_A_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 34,
+ .width = 12,
+ },
+ [VCAP_AF_PCP_A_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 46,
+ .width = 3,
+ },
+ [VCAP_AF_DEI_A_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 49,
+ .width = 1,
+ },
+ [VCAP_AF_VID_B_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 50,
+ .width = 12,
+ },
+ [VCAP_AF_PCP_B_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 62,
+ .width = 3,
+ },
+ [VCAP_AF_DEI_B_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 65,
+ .width = 1,
+ },
+ [VCAP_AF_VID_C_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 66,
+ .width = 12,
+ },
+ [VCAP_AF_PCP_C_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 78,
+ .width = 3,
+ },
+ [VCAP_AF_DEI_C_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 81,
+ .width = 1,
+ },
+ [VCAP_AF_POP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 82,
+ .width = 2,
+ },
+ [VCAP_AF_UNTAG_VID_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 84,
+ .width = 1,
+ },
+ [VCAP_AF_PUSH_CUSTOMER_TAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 85,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_C_VID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 87,
+ .width = 2,
+ },
+ [VCAP_AF_DSCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 127,
+ .width = 3,
+ },
+ [VCAP_AF_DSCP_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 130,
+ .width = 6,
+ },
+ [VCAP_AF_ESDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 319,
+ .width = 10,
+ },
+ [VCAP_AF_FWD_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 438,
+ .width = 2,
+ },
+ [VCAP_AF_CPU_QU] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 440,
+ .width = 3,
+ },
+ [VCAP_AF_PIPELINE_PT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 443,
+ .width = 2,
+ },
+ [VCAP_AF_PIPELINE_ACT] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 445,
+ .width = 1,
+ },
+ [VCAP_AF_SWAP_MACS_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 454,
+ .width = 1,
+ },
+ [VCAP_AF_LOOP_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 455,
+ .width = 1,
+ },
+};
+
+static const struct vcap_field es2_base_type_actionfield[] = {
+ [VCAP_AF_HIT_ME_ONCE] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 0,
+ .width = 1,
+ },
+ [VCAP_AF_INTR_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 1,
+ .width = 1,
+ },
+ [VCAP_AF_FWD_MODE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 2,
+ .width = 2,
+ },
+ [VCAP_AF_COPY_QUEUE_NUM] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 4,
+ .width = 14,
+ },
+ [VCAP_AF_COPY_PORT_NUM] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 18,
+ .width = 6,
+ },
+ [VCAP_AF_MIRROR_PROBE_ID] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 24,
+ .width = 2,
+ },
+ [VCAP_AF_CPU_COPY_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 26,
+ .width = 1,
+ },
+ [VCAP_AF_CPU_QUEUE_NUM] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 27,
+ .width = 3,
+ },
+ [VCAP_AF_POLICE_ENA] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 30,
+ .width = 1,
+ },
+ [VCAP_AF_POLICE_REMARK] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 31,
+ .width = 1,
+ },
+ [VCAP_AF_POLICE_IDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 32,
+ .width = 5,
+ },
+ [VCAP_AF_ES2_REW_CMD] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 37,
+ .width = 3,
+ },
+ [VCAP_AF_CNT_ID] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 40,
+ .width = 9,
+ },
+ [VCAP_AF_IGNORE_PIPELINE_CTRL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 49,
+ .width = 1,
+ },
+};
+
+/* actionfield_set */
+static const struct vcap_set is0_actionfield_set[] = {
+ [VCAP_AFS_CLASSIFICATION] = {
+ .type_id = 1,
+ .sw_per_item = 2,
+ .sw_cnt = 6,
+ },
+ [VCAP_AFS_FULL] = {
+ .type_id = -1,
+ .sw_per_item = 3,
+ .sw_cnt = 4,
+ },
+ [VCAP_AFS_CLASS_REDUCED] = {
+ .type_id = 1,
+ .sw_per_item = 1,
+ .sw_cnt = 12,
+ },
+};
+
+static const struct vcap_set is2_actionfield_set[] = {
+ [VCAP_AFS_BASE_TYPE] = {
+ .type_id = -1,
+ .sw_per_item = 3,
+ .sw_cnt = 4,
+ },
+};
+
+static const struct vcap_set es0_actionfield_set[] = {
+ [VCAP_AFS_ES0] = {
+ .type_id = -1,
+ .sw_per_item = 1,
+ .sw_cnt = 1,
+ },
+};
+
+static const struct vcap_set es2_actionfield_set[] = {
+ [VCAP_AFS_BASE_TYPE] = {
+ .type_id = -1,
+ .sw_per_item = 3,
+ .sw_cnt = 4,
+ },
+};
+
+/* actionfield_set map */
+static const struct vcap_field *is0_actionfield_set_map[] = {
+ [VCAP_AFS_CLASSIFICATION] = is0_classification_actionfield,
+ [VCAP_AFS_FULL] = is0_full_actionfield,
+ [VCAP_AFS_CLASS_REDUCED] = is0_class_reduced_actionfield,
+};
+
+static const struct vcap_field *is2_actionfield_set_map[] = {
+ [VCAP_AFS_BASE_TYPE] = is2_base_type_actionfield,
+};
+
+static const struct vcap_field *es0_actionfield_set_map[] = {
+ [VCAP_AFS_ES0] = es0_es0_actionfield,
+};
+
+static const struct vcap_field *es2_actionfield_set_map[] = {
+ [VCAP_AFS_BASE_TYPE] = es2_base_type_actionfield,
+};
+
+/* actionfield_set map size */
+static int is0_actionfield_set_map_size[] = {
+ [VCAP_AFS_CLASSIFICATION] = ARRAY_SIZE(is0_classification_actionfield),
+ [VCAP_AFS_FULL] = ARRAY_SIZE(is0_full_actionfield),
+ [VCAP_AFS_CLASS_REDUCED] = ARRAY_SIZE(is0_class_reduced_actionfield),
+};
+
+static int is2_actionfield_set_map_size[] = {
+ [VCAP_AFS_BASE_TYPE] = ARRAY_SIZE(is2_base_type_actionfield),
+};
+
+static int es0_actionfield_set_map_size[] = {
+ [VCAP_AFS_ES0] = ARRAY_SIZE(es0_es0_actionfield),
+};
+
+static int es2_actionfield_set_map_size[] = {
+ [VCAP_AFS_BASE_TYPE] = ARRAY_SIZE(es2_base_type_actionfield),
+};
+
+/* Type Groups */
+static const struct vcap_typegroup is0_x12_keyfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 5,
+ .value = 16,
+ },
+ {
+ .offset = 52,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 104,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 156,
+ .width = 3,
+ .value = 0,
+ },
+ {
+ .offset = 208,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 260,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 312,
+ .width = 4,
+ .value = 0,
+ },
+ {
+ .offset = 364,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 416,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 468,
+ .width = 3,
+ .value = 0,
+ },
+ {
+ .offset = 520,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 572,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is0_x6_keyfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 4,
+ .value = 8,
+ },
+ {
+ .offset = 52,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 104,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 156,
+ .width = 3,
+ .value = 0,
+ },
+ {
+ .offset = 208,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 260,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is0_x3_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup is0_x2_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup is0_x1_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup is2_x12_keyfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 3,
+ .value = 4,
+ },
+ {
+ .offset = 156,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 312,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 468,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is2_x6_keyfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 2,
+ .value = 2,
+ },
+ {
+ .offset = 156,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is2_x3_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup is2_x1_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup es0_x1_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup es2_x12_keyfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 3,
+ .value = 4,
+ },
+ {
+ .offset = 156,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 312,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 468,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup es2_x6_keyfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 2,
+ .value = 2,
+ },
+ {
+ .offset = 156,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup es2_x3_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup es2_x1_keyfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup *is0_keyfield_set_typegroups[] = {
+ [12] = is0_x12_keyfield_set_typegroups,
+ [6] = is0_x6_keyfield_set_typegroups,
+ [3] = is0_x3_keyfield_set_typegroups,
+ [2] = is0_x2_keyfield_set_typegroups,
+ [1] = is0_x1_keyfield_set_typegroups,
+ [13] = NULL,
+};
+
+static const struct vcap_typegroup *is2_keyfield_set_typegroups[] = {
+ [12] = is2_x12_keyfield_set_typegroups,
+ [6] = is2_x6_keyfield_set_typegroups,
+ [3] = is2_x3_keyfield_set_typegroups,
+ [1] = is2_x1_keyfield_set_typegroups,
+ [13] = NULL,
+};
+
+static const struct vcap_typegroup *es0_keyfield_set_typegroups[] = {
+ [1] = es0_x1_keyfield_set_typegroups,
+ [2] = NULL,
+};
+
+static const struct vcap_typegroup *es2_keyfield_set_typegroups[] = {
+ [12] = es2_x12_keyfield_set_typegroups,
+ [6] = es2_x6_keyfield_set_typegroups,
+ [3] = es2_x3_keyfield_set_typegroups,
+ [1] = es2_x1_keyfield_set_typegroups,
+ [13] = NULL,
+};
+
+static const struct vcap_typegroup is0_x3_actionfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 3,
+ .value = 4,
+ },
+ {
+ .offset = 103,
+ .width = 2,
+ .value = 0,
+ },
+ {
+ .offset = 206,
+ .width = 2,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is0_x2_actionfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 2,
+ .value = 2,
+ },
+ {
+ .offset = 103,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is0_x1_actionfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 1,
+ .value = 1,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is2_x3_actionfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 2,
+ .value = 2,
+ },
+ {
+ .offset = 95,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 190,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup is2_x1_actionfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup es0_x1_actionfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup es2_x3_actionfield_set_typegroups[] = {
+ {
+ .offset = 0,
+ .width = 2,
+ .value = 2,
+ },
+ {
+ .offset = 19,
+ .width = 1,
+ .value = 0,
+ },
+ {
+ .offset = 38,
+ .width = 1,
+ .value = 0,
+ },
+ {}
+};
+
+static const struct vcap_typegroup es2_x1_actionfield_set_typegroups[] = {
+ {}
+};
+
+static const struct vcap_typegroup *is0_actionfield_set_typegroups[] = {
+ [3] = is0_x3_actionfield_set_typegroups,
+ [2] = is0_x2_actionfield_set_typegroups,
+ [1] = is0_x1_actionfield_set_typegroups,
+ [13] = NULL,
+};
+
+static const struct vcap_typegroup *is2_actionfield_set_typegroups[] = {
+ [3] = is2_x3_actionfield_set_typegroups,
+ [1] = is2_x1_actionfield_set_typegroups,
+ [13] = NULL,
+};
+
+static const struct vcap_typegroup *es0_actionfield_set_typegroups[] = {
+ [1] = es0_x1_actionfield_set_typegroups,
+ [2] = NULL,
+};
+
+static const struct vcap_typegroup *es2_actionfield_set_typegroups[] = {
+ [3] = es2_x3_actionfield_set_typegroups,
+ [1] = es2_x1_actionfield_set_typegroups,
+ [13] = NULL,
+};
+
+/* Keyfieldset names */
+static const char * const vcap_keyfield_set_names[] = {
+ [VCAP_KFS_NO_VALUE] = "(None)",
+ [VCAP_KFS_ARP] = "VCAP_KFS_ARP",
+ [VCAP_KFS_ETAG] = "VCAP_KFS_ETAG",
+ [VCAP_KFS_IP4_OTHER] = "VCAP_KFS_IP4_OTHER",
+ [VCAP_KFS_IP4_TCP_UDP] = "VCAP_KFS_IP4_TCP_UDP",
+ [VCAP_KFS_IP4_VID] = "VCAP_KFS_IP4_VID",
+ [VCAP_KFS_IP6_OTHER] = "VCAP_KFS_IP6_OTHER",
+ [VCAP_KFS_IP6_STD] = "VCAP_KFS_IP6_STD",
+ [VCAP_KFS_IP6_TCP_UDP] = "VCAP_KFS_IP6_TCP_UDP",
+ [VCAP_KFS_IP6_VID] = "VCAP_KFS_IP6_VID",
+ [VCAP_KFS_IP_7TUPLE] = "VCAP_KFS_IP_7TUPLE",
+ [VCAP_KFS_ISDX] = "VCAP_KFS_ISDX",
+ [VCAP_KFS_LL_FULL] = "VCAP_KFS_LL_FULL",
+ [VCAP_KFS_MAC_ETYPE] = "VCAP_KFS_MAC_ETYPE",
+ [VCAP_KFS_MAC_LLC] = "VCAP_KFS_MAC_LLC",
+ [VCAP_KFS_MAC_SNAP] = "VCAP_KFS_MAC_SNAP",
+ [VCAP_KFS_NORMAL_5TUPLE_IP4] = "VCAP_KFS_NORMAL_5TUPLE_IP4",
+ [VCAP_KFS_NORMAL_7TUPLE] = "VCAP_KFS_NORMAL_7TUPLE",
+ [VCAP_KFS_OAM] = "VCAP_KFS_OAM",
+ [VCAP_KFS_PURE_5TUPLE_IP4] = "VCAP_KFS_PURE_5TUPLE_IP4",
+ [VCAP_KFS_SMAC_SIP4] = "VCAP_KFS_SMAC_SIP4",
+ [VCAP_KFS_SMAC_SIP6] = "VCAP_KFS_SMAC_SIP6",
+};
+
+/* Actionfieldset names */
+static const char * const vcap_actionfield_set_names[] = {
+ [VCAP_AFS_NO_VALUE] = "(None)",
+ [VCAP_AFS_BASE_TYPE] = "VCAP_AFS_BASE_TYPE",
+ [VCAP_AFS_CLASSIFICATION] = "VCAP_AFS_CLASSIFICATION",
+ [VCAP_AFS_CLASS_REDUCED] = "VCAP_AFS_CLASS_REDUCED",
+ [VCAP_AFS_ES0] = "VCAP_AFS_ES0",
+ [VCAP_AFS_FULL] = "VCAP_AFS_FULL",
+ [VCAP_AFS_SMAC_SIP] = "VCAP_AFS_SMAC_SIP",
+};
+
+/* Keyfield names */
+static const char * const vcap_keyfield_names[] = {
+ [VCAP_KF_NO_VALUE] = "(None)",
+ [VCAP_KF_8021BR_ECID_BASE] = "8021BR_ECID_BASE",
+ [VCAP_KF_8021BR_ECID_EXT] = "8021BR_ECID_EXT",
+ [VCAP_KF_8021BR_E_TAGGED] = "8021BR_E_TAGGED",
+ [VCAP_KF_8021BR_GRP] = "8021BR_GRP",
+ [VCAP_KF_8021BR_IGR_ECID_BASE] = "8021BR_IGR_ECID_BASE",
+ [VCAP_KF_8021BR_IGR_ECID_EXT] = "8021BR_IGR_ECID_EXT",
+ [VCAP_KF_8021Q_DEI0] = "8021Q_DEI0",
+ [VCAP_KF_8021Q_DEI1] = "8021Q_DEI1",
+ [VCAP_KF_8021Q_DEI2] = "8021Q_DEI2",
+ [VCAP_KF_8021Q_DEI_CLS] = "8021Q_DEI_CLS",
+ [VCAP_KF_8021Q_PCP0] = "8021Q_PCP0",
+ [VCAP_KF_8021Q_PCP1] = "8021Q_PCP1",
+ [VCAP_KF_8021Q_PCP2] = "8021Q_PCP2",
+ [VCAP_KF_8021Q_PCP_CLS] = "8021Q_PCP_CLS",
+ [VCAP_KF_8021Q_TPID] = "8021Q_TPID",
+ [VCAP_KF_8021Q_TPID0] = "8021Q_TPID0",
+ [VCAP_KF_8021Q_TPID1] = "8021Q_TPID1",
+ [VCAP_KF_8021Q_TPID2] = "8021Q_TPID2",
+ [VCAP_KF_8021Q_VID0] = "8021Q_VID0",
+ [VCAP_KF_8021Q_VID1] = "8021Q_VID1",
+ [VCAP_KF_8021Q_VID2] = "8021Q_VID2",
+ [VCAP_KF_8021Q_VID_CLS] = "8021Q_VID_CLS",
+ [VCAP_KF_8021Q_VLAN_TAGGED_IS] = "8021Q_VLAN_TAGGED_IS",
+ [VCAP_KF_8021Q_VLAN_TAGS] = "8021Q_VLAN_TAGS",
+ [VCAP_KF_ACL_GRP_ID] = "ACL_GRP_ID",
+ [VCAP_KF_ARP_ADDR_SPACE_OK_IS] = "ARP_ADDR_SPACE_OK_IS",
+ [VCAP_KF_ARP_LEN_OK_IS] = "ARP_LEN_OK_IS",
+ [VCAP_KF_ARP_OPCODE] = "ARP_OPCODE",
+ [VCAP_KF_ARP_OPCODE_UNKNOWN_IS] = "ARP_OPCODE_UNKNOWN_IS",
+ [VCAP_KF_ARP_PROTO_SPACE_OK_IS] = "ARP_PROTO_SPACE_OK_IS",
+ [VCAP_KF_ARP_SENDER_MATCH_IS] = "ARP_SENDER_MATCH_IS",
+ [VCAP_KF_ARP_TGT_MATCH_IS] = "ARP_TGT_MATCH_IS",
+ [VCAP_KF_COSID_CLS] = "COSID_CLS",
+ [VCAP_KF_ES0_ISDX_KEY_ENA] = "ES0_ISDX_KEY_ENA",
+ [VCAP_KF_ETYPE] = "ETYPE",
+ [VCAP_KF_ETYPE_LEN_IS] = "ETYPE_LEN_IS",
+ [VCAP_KF_HOST_MATCH] = "HOST_MATCH",
+ [VCAP_KF_IF_EGR_PORT_MASK] = "IF_EGR_PORT_MASK",
+ [VCAP_KF_IF_EGR_PORT_MASK_RNG] = "IF_EGR_PORT_MASK_RNG",
+ [VCAP_KF_IF_EGR_PORT_NO] = "IF_EGR_PORT_NO",
+ [VCAP_KF_IF_IGR_PORT] = "IF_IGR_PORT",
+ [VCAP_KF_IF_IGR_PORT_MASK] = "IF_IGR_PORT_MASK",
+ [VCAP_KF_IF_IGR_PORT_MASK_L3] = "IF_IGR_PORT_MASK_L3",
+ [VCAP_KF_IF_IGR_PORT_MASK_RNG] = "IF_IGR_PORT_MASK_RNG",
+ [VCAP_KF_IF_IGR_PORT_MASK_SEL] = "IF_IGR_PORT_MASK_SEL",
+ [VCAP_KF_IF_IGR_PORT_SEL] = "IF_IGR_PORT_SEL",
+ [VCAP_KF_IP4_IS] = "IP4_IS",
+ [VCAP_KF_IP_MC_IS] = "IP_MC_IS",
+ [VCAP_KF_IP_PAYLOAD_5TUPLE] = "IP_PAYLOAD_5TUPLE",
+ [VCAP_KF_IP_SNAP_IS] = "IP_SNAP_IS",
+ [VCAP_KF_ISDX_CLS] = "ISDX_CLS",
+ [VCAP_KF_ISDX_GT0_IS] = "ISDX_GT0_IS",
+ [VCAP_KF_L2_BC_IS] = "L2_BC_IS",
+ [VCAP_KF_L2_DMAC] = "L2_DMAC",
+ [VCAP_KF_L2_FRM_TYPE] = "L2_FRM_TYPE",
+ [VCAP_KF_L2_FWD_IS] = "L2_FWD_IS",
+ [VCAP_KF_L2_LLC] = "L2_LLC",
+ [VCAP_KF_L2_MC_IS] = "L2_MC_IS",
+ [VCAP_KF_L2_PAYLOAD0] = "L2_PAYLOAD0",
+ [VCAP_KF_L2_PAYLOAD1] = "L2_PAYLOAD1",
+ [VCAP_KF_L2_PAYLOAD2] = "L2_PAYLOAD2",
+ [VCAP_KF_L2_PAYLOAD_ETYPE] = "L2_PAYLOAD_ETYPE",
+ [VCAP_KF_L2_SMAC] = "L2_SMAC",
+ [VCAP_KF_L2_SNAP] = "L2_SNAP",
+ [VCAP_KF_L3_DIP_EQ_SIP_IS] = "L3_DIP_EQ_SIP_IS",
+ [VCAP_KF_L3_DPL_CLS] = "L3_DPL_CLS",
+ [VCAP_KF_L3_DSCP] = "L3_DSCP",
+ [VCAP_KF_L3_DST_IS] = "L3_DST_IS",
+ [VCAP_KF_L3_FRAGMENT] = "L3_FRAGMENT",
+ [VCAP_KF_L3_FRAGMENT_TYPE] = "L3_FRAGMENT_TYPE",
+ [VCAP_KF_L3_FRAG_INVLD_L4_LEN] = "L3_FRAG_INVLD_L4_LEN",
+ [VCAP_KF_L3_FRAG_OFS_GT0] = "L3_FRAG_OFS_GT0",
+ [VCAP_KF_L3_IP4_DIP] = "L3_IP4_DIP",
+ [VCAP_KF_L3_IP4_SIP] = "L3_IP4_SIP",
+ [VCAP_KF_L3_IP6_DIP] = "L3_IP6_DIP",
+ [VCAP_KF_L3_IP6_SIP] = "L3_IP6_SIP",
+ [VCAP_KF_L3_IP_PROTO] = "L3_IP_PROTO",
+ [VCAP_KF_L3_OPTIONS_IS] = "L3_OPTIONS_IS",
+ [VCAP_KF_L3_PAYLOAD] = "L3_PAYLOAD",
+ [VCAP_KF_L3_RT_IS] = "L3_RT_IS",
+ [VCAP_KF_L3_TOS] = "L3_TOS",
+ [VCAP_KF_L3_TTL_GT0] = "L3_TTL_GT0",
+ [VCAP_KF_L4_1588_DOM] = "L4_1588_DOM",
+ [VCAP_KF_L4_1588_VER] = "L4_1588_VER",
+ [VCAP_KF_L4_ACK] = "L4_ACK",
+ [VCAP_KF_L4_DPORT] = "L4_DPORT",
+ [VCAP_KF_L4_FIN] = "L4_FIN",
+ [VCAP_KF_L4_PAYLOAD] = "L4_PAYLOAD",
+ [VCAP_KF_L4_PSH] = "L4_PSH",
+ [VCAP_KF_L4_RNG] = "L4_RNG",
+ [VCAP_KF_L4_RST] = "L4_RST",
+ [VCAP_KF_L4_SEQUENCE_EQ0_IS] = "L4_SEQUENCE_EQ0_IS",
+ [VCAP_KF_L4_SPORT] = "L4_SPORT",
+ [VCAP_KF_L4_SPORT_EQ_DPORT_IS] = "L4_SPORT_EQ_DPORT_IS",
+ [VCAP_KF_L4_SYN] = "L4_SYN",
+ [VCAP_KF_L4_URG] = "L4_URG",
+ [VCAP_KF_LOOKUP_FIRST_IS] = "LOOKUP_FIRST_IS",
+ [VCAP_KF_LOOKUP_GEN_IDX] = "LOOKUP_GEN_IDX",
+ [VCAP_KF_LOOKUP_GEN_IDX_SEL] = "LOOKUP_GEN_IDX_SEL",
+ [VCAP_KF_LOOKUP_PAG] = "LOOKUP_PAG",
+ [VCAP_KF_MIRROR_PROBE] = "MIRROR_PROBE",
+ [VCAP_KF_OAM_CCM_CNTS_EQ0] = "OAM_CCM_CNTS_EQ0",
+ [VCAP_KF_OAM_DETECTED] = "OAM_DETECTED",
+ [VCAP_KF_OAM_FLAGS] = "OAM_FLAGS",
+ [VCAP_KF_OAM_MEL_FLAGS] = "OAM_MEL_FLAGS",
+ [VCAP_KF_OAM_MEPID] = "OAM_MEPID",
+ [VCAP_KF_OAM_OPCODE] = "OAM_OPCODE",
+ [VCAP_KF_OAM_VER] = "OAM_VER",
+ [VCAP_KF_OAM_Y1731_IS] = "OAM_Y1731_IS",
+ [VCAP_KF_PROT_ACTIVE] = "PROT_ACTIVE",
+ [VCAP_KF_TCP_IS] = "TCP_IS",
+ [VCAP_KF_TCP_UDP_IS] = "TCP_UDP_IS",
+ [VCAP_KF_TYPE] = "TYPE",
+};
+
+/* Actionfield names */
+static const char * const vcap_actionfield_names[] = {
+ [VCAP_AF_NO_VALUE] = "(None)",
+ [VCAP_AF_ACL_ID] = "ACL_ID",
+ [VCAP_AF_CLS_VID_SEL] = "CLS_VID_SEL",
+ [VCAP_AF_CNT_ID] = "CNT_ID",
+ [VCAP_AF_COPY_PORT_NUM] = "COPY_PORT_NUM",
+ [VCAP_AF_COPY_QUEUE_NUM] = "COPY_QUEUE_NUM",
+ [VCAP_AF_CPU_COPY_ENA] = "CPU_COPY_ENA",
+ [VCAP_AF_CPU_QU] = "CPU_QU",
+ [VCAP_AF_CPU_QUEUE_NUM] = "CPU_QUEUE_NUM",
+ [VCAP_AF_DEI_A_VAL] = "DEI_A_VAL",
+ [VCAP_AF_DEI_B_VAL] = "DEI_B_VAL",
+ [VCAP_AF_DEI_C_VAL] = "DEI_C_VAL",
+ [VCAP_AF_DEI_ENA] = "DEI_ENA",
+ [VCAP_AF_DEI_VAL] = "DEI_VAL",
+ [VCAP_AF_DP_ENA] = "DP_ENA",
+ [VCAP_AF_DP_VAL] = "DP_VAL",
+ [VCAP_AF_DSCP_ENA] = "DSCP_ENA",
+ [VCAP_AF_DSCP_SEL] = "DSCP_SEL",
+ [VCAP_AF_DSCP_VAL] = "DSCP_VAL",
+ [VCAP_AF_ES2_REW_CMD] = "ES2_REW_CMD",
+ [VCAP_AF_ESDX] = "ESDX",
+ [VCAP_AF_FWD_KILL_ENA] = "FWD_KILL_ENA",
+ [VCAP_AF_FWD_MODE] = "FWD_MODE",
+ [VCAP_AF_FWD_SEL] = "FWD_SEL",
+ [VCAP_AF_HIT_ME_ONCE] = "HIT_ME_ONCE",
+ [VCAP_AF_HOST_MATCH] = "HOST_MATCH",
+ [VCAP_AF_IGNORE_PIPELINE_CTRL] = "IGNORE_PIPELINE_CTRL",
+ [VCAP_AF_INTR_ENA] = "INTR_ENA",
+ [VCAP_AF_ISDX_ADD_REPLACE_SEL] = "ISDX_ADD_REPLACE_SEL",
+ [VCAP_AF_ISDX_ENA] = "ISDX_ENA",
+ [VCAP_AF_ISDX_VAL] = "ISDX_VAL",
+ [VCAP_AF_LOOP_ENA] = "LOOP_ENA",
+ [VCAP_AF_LRN_DIS] = "LRN_DIS",
+ [VCAP_AF_MAP_IDX] = "MAP_IDX",
+ [VCAP_AF_MAP_KEY] = "MAP_KEY",
+ [VCAP_AF_MAP_LOOKUP_SEL] = "MAP_LOOKUP_SEL",
+ [VCAP_AF_MASK_MODE] = "MASK_MODE",
+ [VCAP_AF_MATCH_ID] = "MATCH_ID",
+ [VCAP_AF_MATCH_ID_MASK] = "MATCH_ID_MASK",
+ [VCAP_AF_MIRROR_ENA] = "MIRROR_ENA",
+ [VCAP_AF_MIRROR_PROBE] = "MIRROR_PROBE",
+ [VCAP_AF_MIRROR_PROBE_ID] = "MIRROR_PROBE_ID",
+ [VCAP_AF_NXT_IDX] = "NXT_IDX",
+ [VCAP_AF_NXT_IDX_CTRL] = "NXT_IDX_CTRL",
+ [VCAP_AF_PAG_OVERRIDE_MASK] = "PAG_OVERRIDE_MASK",
+ [VCAP_AF_PAG_VAL] = "PAG_VAL",
+ [VCAP_AF_PCP_A_VAL] = "PCP_A_VAL",
+ [VCAP_AF_PCP_B_VAL] = "PCP_B_VAL",
+ [VCAP_AF_PCP_C_VAL] = "PCP_C_VAL",
+ [VCAP_AF_PCP_ENA] = "PCP_ENA",
+ [VCAP_AF_PCP_VAL] = "PCP_VAL",
+ [VCAP_AF_PIPELINE_ACT] = "PIPELINE_ACT",
+ [VCAP_AF_PIPELINE_FORCE_ENA] = "PIPELINE_FORCE_ENA",
+ [VCAP_AF_PIPELINE_PT] = "PIPELINE_PT",
+ [VCAP_AF_POLICE_ENA] = "POLICE_ENA",
+ [VCAP_AF_POLICE_IDX] = "POLICE_IDX",
+ [VCAP_AF_POLICE_REMARK] = "POLICE_REMARK",
+ [VCAP_AF_POLICE_VCAP_ONLY] = "POLICE_VCAP_ONLY",
+ [VCAP_AF_POP_VAL] = "POP_VAL",
+ [VCAP_AF_PORT_MASK] = "PORT_MASK",
+ [VCAP_AF_PUSH_CUSTOMER_TAG] = "PUSH_CUSTOMER_TAG",
+ [VCAP_AF_PUSH_INNER_TAG] = "PUSH_INNER_TAG",
+ [VCAP_AF_PUSH_OUTER_TAG] = "PUSH_OUTER_TAG",
+ [VCAP_AF_QOS_ENA] = "QOS_ENA",
+ [VCAP_AF_QOS_VAL] = "QOS_VAL",
+ [VCAP_AF_REW_OP] = "REW_OP",
+ [VCAP_AF_RT_DIS] = "RT_DIS",
+ [VCAP_AF_SWAP_MACS_ENA] = "SWAP_MACS_ENA",
+ [VCAP_AF_TAG_A_DEI_SEL] = "TAG_A_DEI_SEL",
+ [VCAP_AF_TAG_A_PCP_SEL] = "TAG_A_PCP_SEL",
+ [VCAP_AF_TAG_A_TPID_SEL] = "TAG_A_TPID_SEL",
+ [VCAP_AF_TAG_A_VID_SEL] = "TAG_A_VID_SEL",
+ [VCAP_AF_TAG_B_DEI_SEL] = "TAG_B_DEI_SEL",
+ [VCAP_AF_TAG_B_PCP_SEL] = "TAG_B_PCP_SEL",
+ [VCAP_AF_TAG_B_TPID_SEL] = "TAG_B_TPID_SEL",
+ [VCAP_AF_TAG_B_VID_SEL] = "TAG_B_VID_SEL",
+ [VCAP_AF_TAG_C_DEI_SEL] = "TAG_C_DEI_SEL",
+ [VCAP_AF_TAG_C_PCP_SEL] = "TAG_C_PCP_SEL",
+ [VCAP_AF_TAG_C_TPID_SEL] = "TAG_C_TPID_SEL",
+ [VCAP_AF_TAG_C_VID_SEL] = "TAG_C_VID_SEL",
+ [VCAP_AF_TYPE] = "TYPE",
+ [VCAP_AF_UNTAG_VID_ENA] = "UNTAG_VID_ENA",
+ [VCAP_AF_VID_A_VAL] = "VID_A_VAL",
+ [VCAP_AF_VID_B_VAL] = "VID_B_VAL",
+ [VCAP_AF_VID_C_VAL] = "VID_C_VAL",
+ [VCAP_AF_VID_VAL] = "VID_VAL",
+};
+
+/* VCAPs */
+const struct vcap_info lan969x_vcaps[] = {
+ [VCAP_TYPE_IS0] = {
+ .name = "is0",
+ .rows = 256,
+ .sw_count = 12,
+ .sw_width = 52,
+ .sticky_width = 1,
+ .act_width = 103,
+ .default_cnt = 70,
+ .require_cnt_dis = 0,
+ .version = 1,
+ .keyfield_set = is0_keyfield_set,
+ .keyfield_set_size = ARRAY_SIZE(is0_keyfield_set),
+ .actionfield_set = is0_actionfield_set,
+ .actionfield_set_size = ARRAY_SIZE(is0_actionfield_set),
+ .keyfield_set_map = is0_keyfield_set_map,
+ .keyfield_set_map_size = is0_keyfield_set_map_size,
+ .actionfield_set_map = is0_actionfield_set_map,
+ .actionfield_set_map_size = is0_actionfield_set_map_size,
+ .keyfield_set_typegroups = is0_keyfield_set_typegroups,
+ .actionfield_set_typegroups = is0_actionfield_set_typegroups,
+ },
+ [VCAP_TYPE_IS2] = {
+ .name = "is2",
+ .rows = 256,
+ .sw_count = 12,
+ .sw_width = 52,
+ .sticky_width = 1,
+ .act_width = 103,
+ .default_cnt = 38,
+ .require_cnt_dis = 0,
+ .version = 1,
+ .keyfield_set = is2_keyfield_set,
+ .keyfield_set_size = ARRAY_SIZE(is2_keyfield_set),
+ .actionfield_set = is2_actionfield_set,
+ .actionfield_set_size = ARRAY_SIZE(is2_actionfield_set),
+ .keyfield_set_map = is2_keyfield_set_map,
+ .keyfield_set_map_size = is2_keyfield_set_map_size,
+ .actionfield_set_map = is2_actionfield_set_map,
+ .actionfield_set_map_size = is2_actionfield_set_map_size,
+ .keyfield_set_typegroups = is2_keyfield_set_typegroups,
+ .actionfield_set_typegroups = is2_actionfield_set_typegroups,
+ },
+ [VCAP_TYPE_ES0] = {
+ .name = "es0",
+ .rows = 1536,
+ .sw_count = 1,
+ .sw_width = 51,
+ .sticky_width = 1,
+ .act_width = 469,
+ .default_cnt = 35,
+ .require_cnt_dis = 0,
+ .version = 1,
+ .keyfield_set = es0_keyfield_set,
+ .keyfield_set_size = ARRAY_SIZE(es0_keyfield_set),
+ .actionfield_set = es0_actionfield_set,
+ .actionfield_set_size = ARRAY_SIZE(es0_actionfield_set),
+ .keyfield_set_map = es0_keyfield_set_map,
+ .keyfield_set_map_size = es0_keyfield_set_map_size,
+ .actionfield_set_map = es0_actionfield_set_map,
+ .actionfield_set_map_size = es0_actionfield_set_map_size,
+ .keyfield_set_typegroups = es0_keyfield_set_typegroups,
+ .actionfield_set_typegroups = es0_actionfield_set_typegroups,
+ },
+ [VCAP_TYPE_ES2] = {
+ .name = "es2",
+ .rows = 256,
+ .sw_count = 12,
+ .sw_width = 52,
+ .sticky_width = 1,
+ .act_width = 19,
+ .default_cnt = 39,
+ .require_cnt_dis = 0,
+ .version = 1,
+ .keyfield_set = es2_keyfield_set,
+ .keyfield_set_size = ARRAY_SIZE(es2_keyfield_set),
+ .actionfield_set = es2_actionfield_set,
+ .actionfield_set_size = ARRAY_SIZE(es2_actionfield_set),
+ .keyfield_set_map = es2_keyfield_set_map,
+ .keyfield_set_map_size = es2_keyfield_set_map_size,
+ .actionfield_set_map = es2_actionfield_set_map,
+ .actionfield_set_map_size = es2_actionfield_set_map_size,
+ .keyfield_set_typegroups = es2_keyfield_set_typegroups,
+ .actionfield_set_typegroups = es2_actionfield_set_typegroups,
+ },
+};
+
+const struct vcap_statistics lan969x_vcap_stats = {
+ .name = "lan969x",
+ .count = 4,
+ .keyfield_set_names = vcap_keyfield_set_names,
+ .actionfield_set_names = vcap_actionfield_set_names,
+ .keyfield_names = vcap_keyfield_names,
+ .actionfield_names = vcap_actionfield_names,
+};
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_impl.c b/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_impl.c
new file mode 100644
index 000000000000..543a1f2bf6bd
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_impl.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "vcap_api.h"
+#include "lan969x.h"
+
+const struct sparx5_vcap_inst lan969x_vcap_inst_cfg[] = {
+ {
+ .vtype = VCAP_TYPE_IS0, /* CLM-0 */
+ .vinst = 0,
+ .map_id = 1,
+ .lookups = SPARX5_IS0_LOOKUPS,
+ .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3,
+ .first_cid = SPARX5_VCAP_CID_IS0_L0,
+ .last_cid = SPARX5_VCAP_CID_IS0_L2 - 1,
+ .blockno = 2,
+ .blocks = 1,
+ .ingress = true,
+ },
+ {
+ .vtype = VCAP_TYPE_IS0, /* CLM-1 */
+ .vinst = 1,
+ .map_id = 2,
+ .lookups = SPARX5_IS0_LOOKUPS,
+ .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3,
+ .first_cid = SPARX5_VCAP_CID_IS0_L2,
+ .last_cid = SPARX5_VCAP_CID_IS0_L4 - 1,
+ .blockno = 3,
+ .blocks = 1,
+ .ingress = true,
+ },
+ {
+ .vtype = VCAP_TYPE_IS0, /* CLM-2 */
+ .vinst = 2,
+ .map_id = 3,
+ .lookups = SPARX5_IS0_LOOKUPS,
+ .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3,
+ .first_cid = SPARX5_VCAP_CID_IS0_L4,
+ .last_cid = SPARX5_VCAP_CID_IS0_MAX,
+ .blockno = 4,
+ .blocks = 1,
+ .ingress = true,
+ },
+ {
+ .vtype = VCAP_TYPE_IS2, /* IS2-0 */
+ .vinst = 0,
+ .map_id = 4,
+ .lookups = SPARX5_IS2_LOOKUPS,
+ .lookups_per_instance = SPARX5_IS2_LOOKUPS / 2,
+ .first_cid = SPARX5_VCAP_CID_IS2_L0,
+ .last_cid = SPARX5_VCAP_CID_IS2_L2 - 1,
+ .blockno = 0,
+ .blocks = 1,
+ .ingress = true,
+ },
+ {
+ .vtype = VCAP_TYPE_IS2, /* IS2-1 */
+ .vinst = 1,
+ .map_id = 5,
+ .lookups = SPARX5_IS2_LOOKUPS,
+ .lookups_per_instance = SPARX5_IS2_LOOKUPS / 2,
+ .first_cid = SPARX5_VCAP_CID_IS2_L2,
+ .last_cid = SPARX5_VCAP_CID_IS2_MAX,
+ .blockno = 1,
+ .blocks = 1,
+ .ingress = true,
+ },
+ {
+ .vtype = VCAP_TYPE_ES0,
+ .lookups = SPARX5_ES0_LOOKUPS,
+ .lookups_per_instance = SPARX5_ES0_LOOKUPS,
+ .first_cid = SPARX5_VCAP_CID_ES0_L0,
+ .last_cid = SPARX5_VCAP_CID_ES0_MAX,
+ .count = 1536,
+ .ingress = false,
+ },
+ {
+ .vtype = VCAP_TYPE_ES2,
+ .lookups = SPARX5_ES2_LOOKUPS,
+ .lookups_per_instance = SPARX5_ES2_LOOKUPS,
+ .first_cid = SPARX5_VCAP_CID_ES2_L0,
+ .last_cid = SPARX5_VCAP_CID_ES2_MAX,
+ .count = 1024,
+ .ingress = false,
+ },
+};
diff --git a/drivers/net/ethernet/microchip/sparx5/Makefile b/drivers/net/ethernet/microchip/sparx5/Makefile
index 288de95add18..3435ca86dd70 100644
--- a/drivers/net/ethernet/microchip/sparx5/Makefile
+++ b/drivers/net/ethernet/microchip/sparx5/Makefile
@@ -11,7 +11,7 @@ sparx5-switch-y := sparx5_main.o sparx5_packet.o \
sparx5_ptp.o sparx5_pgid.o sparx5_tc.o sparx5_qos.o \
sparx5_vcap_impl.o sparx5_vcap_ag_api.o sparx5_tc_flower.o \
sparx5_tc_matchall.o sparx5_pool.o sparx5_sdlb.o sparx5_police.o \
- sparx5_psfp.o sparx5_mirror.o
+ sparx5_psfp.o sparx5_mirror.o sparx5_regs.o
sparx5-switch-$(CONFIG_SPARX5_DCB) += sparx5_dcb.o
sparx5-switch-$(CONFIG_DEBUG_FS) += sparx5_vcap_debugfs.o
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c b/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c
index 76a8bb596aec..5fe941c66c17 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c
@@ -15,9 +15,6 @@
#define SPX5_CALBITS_PER_PORT 3 /* Bit per port in calendar register */
/* DSM calendar information */
-#define SPX5_DSM_CAL_LEN 64
-#define SPX5_DSM_CAL_EMPTY 0xFFFF
-#define SPX5_DSM_CAL_MAX_DEVS_PER_TAXI 13
#define SPX5_DSM_CAL_TAXIS 8
#define SPX5_DSM_CAL_BW_LOSS 553
@@ -37,19 +34,6 @@ static u32 sparx5_taxi_ports[SPX5_DSM_CAL_TAXIS][SPX5_DSM_CAL_MAX_DEVS_PER_TAXI]
{64, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99},
};
-struct sparx5_calendar_data {
- u32 schedule[SPX5_DSM_CAL_LEN];
- u32 avg_dist[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
- u32 taxi_ports[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
- u32 taxi_speeds[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
- u32 dev_slots[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
- u32 new_slots[SPX5_DSM_CAL_LEN];
- u32 temp_sched[SPX5_DSM_CAL_LEN];
- u32 indices[SPX5_DSM_CAL_LEN];
- u32 short_list[SPX5_DSM_CAL_LEN];
- u32 long_list[SPX5_DSM_CAL_LEN];
-};
-
static u32 sparx5_target_bandwidth(struct sparx5 *sparx5)
{
switch (sparx5->target_ct) {
@@ -68,27 +52,32 @@ static u32 sparx5_target_bandwidth(struct sparx5 *sparx5)
case SPX5_TARGET_CT_7558:
case SPX5_TARGET_CT_7558TSN:
return 201000;
+ case SPX5_TARGET_CT_LAN9691VAO:
+ return 46000;
+ case SPX5_TARGET_CT_LAN9694RED:
+ case SPX5_TARGET_CT_LAN9694TSN:
+ case SPX5_TARGET_CT_LAN9694:
+ return 68000;
+ case SPX5_TARGET_CT_LAN9696RED:
+ case SPX5_TARGET_CT_LAN9696TSN:
+ case SPX5_TARGET_CT_LAN9692VAO:
+ case SPX5_TARGET_CT_LAN9696:
+ return 88000;
+ case SPX5_TARGET_CT_LAN9698RED:
+ case SPX5_TARGET_CT_LAN9698TSN:
+ case SPX5_TARGET_CT_LAN9693VAO:
+ case SPX5_TARGET_CT_LAN9698:
+ return 101000;
default:
return 0;
}
}
-/* This is used in calendar configuration */
-enum sparx5_cal_bw {
- SPX5_CAL_SPEED_NONE = 0,
- SPX5_CAL_SPEED_1G = 1,
- SPX5_CAL_SPEED_2G5 = 2,
- SPX5_CAL_SPEED_5G = 3,
- SPX5_CAL_SPEED_10G = 4,
- SPX5_CAL_SPEED_25G = 5,
- SPX5_CAL_SPEED_0G5 = 6,
- SPX5_CAL_SPEED_12G5 = 7
-};
-
static u32 sparx5_clk_to_bandwidth(enum sparx5_core_clockfreq cclock)
{
switch (cclock) {
case SPX5_CORE_CLOCK_250MHZ: return 83000; /* 250000 / 3 */
+ case SPX5_CORE_CLOCK_328MHZ: return 109375; /* 328000 / 3 */
case SPX5_CORE_CLOCK_500MHZ: return 166000; /* 500000 / 3 */
case SPX5_CORE_CLOCK_625MHZ: return 208000; /* 625000 / 3 */
default: return 0;
@@ -96,7 +85,7 @@ static u32 sparx5_clk_to_bandwidth(enum sparx5_core_clockfreq cclock)
return 0;
}
-static u32 sparx5_cal_speed_to_value(enum sparx5_cal_bw speed)
+u32 sparx5_cal_speed_to_value(enum sparx5_cal_bw speed)
{
switch (speed) {
case SPX5_CAL_SPEED_1G: return 1000;
@@ -109,6 +98,7 @@ static u32 sparx5_cal_speed_to_value(enum sparx5_cal_bw speed)
default: return 0;
}
}
+EXPORT_SYMBOL_GPL(sparx5_cal_speed_to_value);
static u32 sparx5_bandwidth_to_calendar(u32 bw)
{
@@ -126,23 +116,28 @@ static u32 sparx5_bandwidth_to_calendar(u32 bw)
}
}
-static enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5,
- u32 portno)
+enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5, u32 portno)
{
struct sparx5_port *port;
- if (portno >= SPX5_PORTS) {
+ if (portno >= sparx5->data->consts->n_ports) {
/* Internal ports */
- if (portno == SPX5_PORT_CPU_0 || portno == SPX5_PORT_CPU_1) {
+ if (portno ==
+ sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0) ||
+ portno ==
+ sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1)) {
/* Equals 1.25G */
return SPX5_CAL_SPEED_2G5;
- } else if (portno == SPX5_PORT_VD0) {
+ } else if (portno ==
+ sparx5_get_internal_port(sparx5, SPX5_PORT_VD0)) {
/* IPMC only idle BW */
return SPX5_CAL_SPEED_NONE;
- } else if (portno == SPX5_PORT_VD1) {
+ } else if (portno ==
+ sparx5_get_internal_port(sparx5, SPX5_PORT_VD1)) {
/* OAM only idle BW */
return SPX5_CAL_SPEED_NONE;
- } else if (portno == SPX5_PORT_VD2) {
+ } else if (portno ==
+ sparx5_get_internal_port(sparx5, SPX5_PORT_VD2)) {
/* IPinIP gets only idle BW */
return SPX5_CAL_SPEED_NONE;
}
@@ -155,10 +150,12 @@ static enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5,
return SPX5_CAL_SPEED_NONE;
return sparx5_bandwidth_to_calendar(port->conf.bandwidth);
}
+EXPORT_SYMBOL_GPL(sparx5_get_port_cal_speed);
/* Auto configure the QSYS calendar based on port configuration */
int sparx5_config_auto_calendar(struct sparx5 *sparx5)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
u32 cal[7], value, idx, portno;
u32 max_core_bw;
u32 total_bw = 0, used_port_bw = 0;
@@ -174,7 +171,7 @@ int sparx5_config_auto_calendar(struct sparx5 *sparx5)
}
/* Setup the calendar with the bandwidth to each port */
- for (portno = 0; portno < SPX5_PORTS_ALL; portno++) {
+ for (portno = 0; portno < consts->n_ports_all; portno++) {
u64 reg, offset, this_bw;
spd = sparx5_get_port_cal_speed(sparx5, portno);
@@ -182,7 +179,7 @@ int sparx5_config_auto_calendar(struct sparx5 *sparx5)
continue;
this_bw = sparx5_cal_speed_to_value(spd);
- if (portno < SPX5_PORTS)
+ if (portno < consts->n_ports)
used_port_bw += this_bw;
else
/* Internal ports are granted half the value */
@@ -208,12 +205,13 @@ int sparx5_config_auto_calendar(struct sparx5 *sparx5)
}
/* Halt the calendar while changing it */
- spx5_rmw(QSYS_CAL_CTRL_CAL_MODE_SET(10),
- QSYS_CAL_CTRL_CAL_MODE,
- sparx5, QSYS_CAL_CTRL);
+ if (is_sparx5(sparx5))
+ spx5_rmw(QSYS_CAL_CTRL_CAL_MODE_SET(10),
+ QSYS_CAL_CTRL_CAL_MODE,
+ sparx5, QSYS_CAL_CTRL);
/* Assign port bandwidth to auto calendar */
- for (idx = 0; idx < ARRAY_SIZE(cal); idx++)
+ for (idx = 0; idx < consts->n_auto_cals; idx++)
spx5_wr(cal[idx], sparx5, QSYS_CAL_AUTO(idx));
/* Increase grant rate of all ports to account for
@@ -278,8 +276,8 @@ static u32 sparx5_dsm_cp_cal(u32 *sched)
return SPX5_DSM_CAL_EMPTY;
}
-static int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
- struct sparx5_calendar_data *data)
+int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
+ struct sparx5_calendar_data *data)
{
bool slow_mode;
u32 gcd, idx, sum, min, factor;
@@ -304,7 +302,7 @@ static int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
for (idx = 0; idx < SPX5_DSM_CAL_MAX_DEVS_PER_TAXI; idx++) {
u32 portno = data->taxi_ports[idx];
- if (portno < SPX5_TAXI_PORT_MAX) {
+ if (portno < sparx5->data->consts->n_ports_all) {
data->taxi_speeds[idx] = sparx5_cal_speed_to_value
(sparx5_get_port_cal_speed(sparx5, portno));
} else {
@@ -533,12 +531,23 @@ check_err:
static int sparx5_dsm_calendar_update(struct sparx5 *sparx5, u32 taxi,
struct sparx5_calendar_data *data)
{
- u32 idx;
- u32 cal_len = sparx5_dsm_cal_len(data->schedule), len;
+ u32 cal_len = sparx5_dsm_cal_len(data->schedule), len, idx;
+
+ if (!is_sparx5(sparx5)) {
+ u32 val, act;
+
+ val = spx5_rd(sparx5, DSM_TAXI_CAL_CFG(taxi));
+ act = DSM_TAXI_CAL_CFG_CAL_SEL_STAT_GET(val);
- spx5_wr(DSM_TAXI_CAL_CFG_CAL_PGM_ENA_SET(1),
- sparx5,
- DSM_TAXI_CAL_CFG(taxi));
+ spx5_rmw(DSM_TAXI_CAL_CFG_CAL_PGM_SEL_SET(!act),
+ DSM_TAXI_CAL_CFG_CAL_PGM_SEL,
+ sparx5, DSM_TAXI_CAL_CFG(taxi));
+ }
+
+ spx5_rmw(DSM_TAXI_CAL_CFG_CAL_PGM_ENA_SET(1),
+ DSM_TAXI_CAL_CFG_CAL_PGM_ENA,
+ sparx5,
+ DSM_TAXI_CAL_CFG(taxi));
for (idx = 0; idx < cal_len; idx++) {
spx5_rmw(DSM_TAXI_CAL_CFG_CAL_IDX_SET(idx),
DSM_TAXI_CAL_CFG_CAL_IDX,
@@ -549,13 +558,21 @@ static int sparx5_dsm_calendar_update(struct sparx5 *sparx5, u32 taxi,
sparx5,
DSM_TAXI_CAL_CFG(taxi));
}
- spx5_wr(DSM_TAXI_CAL_CFG_CAL_PGM_ENA_SET(0),
- sparx5,
- DSM_TAXI_CAL_CFG(taxi));
+ spx5_rmw(DSM_TAXI_CAL_CFG_CAL_PGM_ENA_SET(0),
+ DSM_TAXI_CAL_CFG_CAL_PGM_ENA,
+ sparx5,
+ DSM_TAXI_CAL_CFG(taxi));
len = DSM_TAXI_CAL_CFG_CAL_CUR_LEN_GET(spx5_rd(sparx5,
DSM_TAXI_CAL_CFG(taxi)));
if (len != cal_len - 1)
goto update_err;
+
+ if (!is_sparx5(sparx5)) {
+ spx5_rmw(DSM_TAXI_CAL_CFG_CAL_SWITCH_SET(1),
+ DSM_TAXI_CAL_CFG_CAL_SWITCH,
+ sparx5, DSM_TAXI_CAL_CFG(taxi));
+ }
+
return 0;
update_err:
dev_err(sparx5->dev, "Incorrect calendar length: %u\n", len);
@@ -565,6 +582,7 @@ update_err:
/* Configure the DSM calendar based on port configuration */
int sparx5_config_dsm_calendar(struct sparx5 *sparx5)
{
+ const struct sparx5_ops *ops = sparx5->data->ops;
int taxi;
struct sparx5_calendar_data *data;
int err = 0;
@@ -573,8 +591,8 @@ int sparx5_config_dsm_calendar(struct sparx5 *sparx5)
if (!data)
return -ENOMEM;
- for (taxi = 0; taxi < SPX5_DSM_CAL_TAXIS; ++taxi) {
- err = sparx5_dsm_calendar_calc(sparx5, taxi, data);
+ for (taxi = 0; taxi < sparx5->data->consts->n_dsm_cal_taxis; ++taxi) {
+ err = ops->dsm_calendar_calc(sparx5, taxi, data);
if (err) {
dev_err(sparx5->dev, "DSM calendar calculation failed\n");
goto cal_out;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c b/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c
index 2d763664dcda..10224ad63a78 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c
@@ -234,10 +234,11 @@ static int sparx5_dcb_ieee_dscp_setdel(struct net_device *dev,
struct dcb_app *))
{
struct sparx5_port *port = netdev_priv(dev);
+ struct sparx5 *sparx5 = port->sparx5;
struct sparx5_port *port_itr;
int err, i;
- for (i = 0; i < SPX5_PORTS; i++) {
+ for (i = 0; i < sparx5->data->consts->n_ports; i++) {
port_itr = port->sparx5->ports[i];
if (!port_itr)
continue;
@@ -386,7 +387,7 @@ int sparx5_dcb_init(struct sparx5 *sparx5)
struct sparx5_port *port;
int i;
- for (i = 0; i < SPX5_PORTS; i++) {
+ for (i = 0; i < sparx5->data->consts->n_ports; i++) {
port = sparx5->ports[i];
if (!port)
continue;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c
index d898a7238b48..832f4ae57c83 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c
@@ -505,8 +505,8 @@ static void sparx5_get_dev_misc_stats(u64 *portstats, void __iomem *inst, u32
static void sparx5_get_device_stats(struct sparx5 *sparx5, int portno)
{
u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
- u32 tinst = sparx5_port_dev_index(portno);
- u32 dev = sparx5_to_high_dev(portno);
+ u32 tinst = sparx5_port_dev_index(sparx5, portno);
+ u32 dev = sparx5_to_high_dev(sparx5, portno);
void __iomem *inst;
inst = spx5_inst_get(sparx5, dev, tinst);
@@ -819,8 +819,8 @@ static void sparx5_get_eth_phy_stats(struct net_device *ndev,
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
- u32 tinst = sparx5_port_dev_index(portno);
- u32 dev = sparx5_to_high_dev(portno);
+ u32 tinst = sparx5_port_dev_index(sparx5, portno);
+ u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_phy_stats(portstats, inst, tinst);
@@ -844,8 +844,8 @@ static void sparx5_get_eth_mac_stats(struct net_device *ndev,
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
- u32 tinst = sparx5_port_dev_index(portno);
- u32 dev = sparx5_to_high_dev(portno);
+ u32 tinst = sparx5_port_dev_index(sparx5, portno);
+ u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_mac_stats(portstats, inst, tinst);
@@ -912,8 +912,8 @@ static void sparx5_get_eth_mac_ctrl_stats(struct net_device *ndev,
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
- u32 tinst = sparx5_port_dev_index(portno);
- u32 dev = sparx5_to_high_dev(portno);
+ u32 tinst = sparx5_port_dev_index(sparx5, portno);
+ u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_mac_ctrl_stats(portstats, inst, tinst);
@@ -944,8 +944,8 @@ static void sparx5_get_eth_rmon_stats(struct net_device *ndev,
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
- u32 tinst = sparx5_port_dev_index(portno);
- u32 dev = sparx5_to_high_dev(portno);
+ u32 tinst = sparx5_port_dev_index(sparx5, portno);
+ u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_rmon_stats(portstats, inst, tinst);
@@ -1027,8 +1027,8 @@ static void sparx5_get_sset_data(struct net_device *ndev,
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
- u32 tinst = sparx5_port_dev_index(portno);
- u32 dev = sparx5_to_high_dev(portno);
+ u32 tinst = sparx5_port_dev_index(sparx5, portno);
+ u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_misc_stats(portstats, inst, tinst);
@@ -1122,7 +1122,7 @@ static void sparx5_update_stats(struct sparx5 *sparx5)
{
int idx;
- for (idx = 0; idx < SPX5_PORTS; idx++)
+ for (idx = 0; idx < sparx5->data->consts->n_ports; idx++)
if (sparx5->ports[idx])
sparx5_update_port_stats(sparx5, idx);
}
@@ -1189,7 +1189,7 @@ static int sparx5_get_ts_info(struct net_device *dev,
struct sparx5 *sparx5 = port->sparx5;
struct sparx5_phc *phc;
- if (!sparx5->ptp)
+ if (!sparx5->ptp && is_sparx5(sparx5))
return ethtool_op_get_ts_info(dev, info);
phc = &sparx5->phc[SPARX5_PHC_PORT];
@@ -1228,6 +1228,7 @@ const struct ethtool_ops sparx5_ethtool_ops = {
int sparx_stats_init(struct sparx5 *sparx5)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
char queue_name[32];
int portno;
@@ -1235,14 +1236,15 @@ int sparx_stats_init(struct sparx5 *sparx5)
sparx5->num_stats = spx5_stats_count;
sparx5->num_ethtool_stats = ARRAY_SIZE(sparx5_stats_layout);
sparx5->stats = devm_kcalloc(sparx5->dev,
- SPX5_PORTS_ALL * sparx5->num_stats,
+ consts->n_ports_all *
+ sparx5->num_stats,
sizeof(u64), GFP_KERNEL);
if (!sparx5->stats)
return -ENOMEM;
mutex_init(&sparx5->queue_stats_lock);
sparx5_config_stats(sparx5);
- for (portno = 0; portno < SPX5_PORTS; portno++)
+ for (portno = 0; portno < consts->n_ports; portno++)
if (sparx5->ports[portno])
sparx5_config_port_stats(sparx5, portno);
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
index 61df874b7623..0027144a2af2 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
@@ -154,9 +154,11 @@ static bool sparx5_fdma_rx_get_frame(struct sparx5 *sparx5, struct sparx5_rx *rx
skb = rx->skb[fdma->dcb_index][fdma->db_index];
skb_put(skb, fdma_db_len_get(db_hw));
/* Now do the normal processing of the skb */
- sparx5_ifh_parse((u32 *)skb->data, &fi);
+ sparx5_ifh_parse(sparx5, (u32 *)skb->data, &fi);
/* Map to port netdev */
- port = fi.src_port < SPX5_PORTS ? sparx5->ports[fi.src_port] : NULL;
+ port = fi.src_port < sparx5->data->consts->n_ports ?
+ sparx5->ports[fi.src_port] :
+ NULL;
if (!port || !port->ndev) {
dev_err(sparx5->dev, "Data on inactive port %d\n", fi.src_port);
sparx5_xtr_flush(sparx5, XTR_QUEUE);
@@ -296,7 +298,7 @@ static void sparx5_fdma_rx_init(struct sparx5 *sparx5,
fdma->ops.dataptr_cb = &sparx5_fdma_rx_dataptr_cb;
fdma->ops.nextptr_cb = &fdma_nextptr_cb;
/* Fetch a netdev for SKB and NAPI use, any will do */
- for (idx = 0; idx < SPX5_PORTS; ++idx) {
+ for (idx = 0; idx < sparx5->data->consts->n_ports; ++idx) {
struct sparx5_port *port = sparx5->ports[idx];
if (port && port->ndev) {
@@ -362,7 +364,9 @@ static void sparx5_fdma_injection_mode(struct sparx5 *sparx5)
sparx5, QS_INJ_GRP_CFG(INJ_QUEUE));
/* CPU ports capture setup */
- for (portno = SPX5_PORT_CPU_0; portno <= SPX5_PORT_CPU_1; portno++) {
+ for (portno = sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0);
+ portno <= sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1);
+ portno++) {
/* ASM CPU port: No preamble, IFH, enable padding */
spx5_wr(ASM_PORT_CFG_PAD_ENA_SET(1) |
ASM_PORT_CFG_NO_PREAMBLE_ENA_SET(1) |
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c b/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c
index 75868b3f548e..f5584244612c 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c
@@ -80,15 +80,16 @@ static void sparx5_mact_select(struct sparx5 *sparx5,
int sparx5_mact_learn(struct sparx5 *sparx5, int pgid,
const unsigned char mac[ETH_ALEN], u16 vid)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
int addr, type, ret;
- if (pgid < SPX5_PORTS) {
+ if (pgid < consts->n_ports) {
type = MAC_ENTRY_ADDR_TYPE_UPSID_PN;
addr = pgid % 32;
addr += (pgid / 32) << 5; /* Add upsid */
} else {
type = MAC_ENTRY_ADDR_TYPE_MC_IDX;
- addr = pgid - SPX5_PORTS;
+ addr = pgid - consts->n_ports;
}
mutex_lock(&sparx5->lock);
@@ -128,7 +129,8 @@ int sparx5_mc_sync(struct net_device *dev, const unsigned char *addr)
struct sparx5_port *port = netdev_priv(dev);
struct sparx5 *sparx5 = port->sparx5;
- return sparx5_mact_learn(sparx5, PGID_CPU, addr, port->pvid);
+ return sparx5_mact_learn(sparx5, sparx5_get_pgid(sparx5, PGID_CPU),
+ addr, port->pvid);
}
static int sparx5_mact_get(struct sparx5 *sparx5,
@@ -371,7 +373,7 @@ static void sparx5_mact_handle_entry(struct sparx5 *sparx5,
return;
port = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR_GET(cfg2);
- if (port >= SPX5_PORTS)
+ if (port >= sparx5->data->consts->n_ports)
return;
if (!test_bit(port, sparx5->bridge_mask))
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
index b64c814eac11..2f1013f870fb 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
@@ -24,13 +24,17 @@
#include <linux/types.h>
#include <linux/reset.h>
+#include "../lan969x/lan969x.h" /* for lan969x match data */
+
#include "sparx5_main_regs.h"
#include "sparx5_main.h"
#include "sparx5_port.h"
#include "sparx5_qos.h"
+#include "sparx5_vcap_ag_api.h"
+#include "sparx5_vcap_impl.h"
+
+const struct sparx5_regs *regs;
-#define QLIM_WM(fraction) \
- ((SPX5_BUFFER_MEMORY / SPX5_BUFFER_CELL_SZ - 100) * (fraction) / 100)
#define IO_RANGES 3
struct initial_port_config {
@@ -45,12 +49,6 @@ struct sparx5_ram_config {
u32 init_val;
};
-struct sparx5_main_io_resource {
- enum sparx5_target id;
- phys_addr_t offset;
- int range;
-};
-
static const struct sparx5_main_io_resource sparx5_main_iomap[] = {
{ TARGET_CPU, 0, 0 }, /* 0x600000000 */
{ TARGET_FDMA, 0x80000, 0 }, /* 0x600080000 */
@@ -214,23 +212,79 @@ static const struct sparx5_main_io_resource sparx5_main_iomap[] = {
{ TARGET_VOP, 0x11a00000, 2 }, /* 0x611a00000 */
};
+bool is_sparx5(struct sparx5 *sparx5)
+{
+ switch (sparx5->target_ct) {
+ case SPX5_TARGET_CT_7546:
+ case SPX5_TARGET_CT_7549:
+ case SPX5_TARGET_CT_7552:
+ case SPX5_TARGET_CT_7556:
+ case SPX5_TARGET_CT_7558:
+ case SPX5_TARGET_CT_7546TSN:
+ case SPX5_TARGET_CT_7549TSN:
+ case SPX5_TARGET_CT_7552TSN:
+ case SPX5_TARGET_CT_7556TSN:
+ case SPX5_TARGET_CT_7558TSN:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void sparx5_init_features(struct sparx5 *sparx5)
+{
+ switch (sparx5->target_ct) {
+ case SPX5_TARGET_CT_7546:
+ case SPX5_TARGET_CT_7549:
+ case SPX5_TARGET_CT_7552:
+ case SPX5_TARGET_CT_7556:
+ case SPX5_TARGET_CT_7558:
+ case SPX5_TARGET_CT_7546TSN:
+ case SPX5_TARGET_CT_7549TSN:
+ case SPX5_TARGET_CT_7552TSN:
+ case SPX5_TARGET_CT_7556TSN:
+ case SPX5_TARGET_CT_7558TSN:
+ case SPX5_TARGET_CT_LAN9691VAO:
+ case SPX5_TARGET_CT_LAN9694TSN:
+ case SPX5_TARGET_CT_LAN9694RED:
+ case SPX5_TARGET_CT_LAN9692VAO:
+ case SPX5_TARGET_CT_LAN9696TSN:
+ case SPX5_TARGET_CT_LAN9696RED:
+ case SPX5_TARGET_CT_LAN9693VAO:
+ case SPX5_TARGET_CT_LAN9698TSN:
+ case SPX5_TARGET_CT_LAN9698RED:
+ sparx5->features = (SPX5_FEATURE_PSFP | SPX5_FEATURE_PTP);
+ break;
+ default:
+ break;
+ }
+}
+
+bool sparx5_has_feature(struct sparx5 *sparx5, enum sparx5_feature feature)
+{
+ return sparx5->features & feature;
+}
+
static int sparx5_create_targets(struct sparx5 *sparx5)
{
+ const struct sparx5_main_io_resource *iomap = sparx5->data->iomap;
+ int iomap_size = sparx5->data->iomap_size;
+ int ioranges = sparx5->data->ioranges;
struct resource *iores[IO_RANGES];
void __iomem *iomem[IO_RANGES];
void __iomem *begin[IO_RANGES];
int range_id[IO_RANGES];
int idx, jdx;
- for (idx = 0, jdx = 0; jdx < ARRAY_SIZE(sparx5_main_iomap); jdx++) {
- const struct sparx5_main_io_resource *iomap = &sparx5_main_iomap[jdx];
+ for (idx = 0, jdx = 0; jdx < iomap_size; jdx++) {
+ const struct sparx5_main_io_resource *io = &iomap[jdx];
- if (idx == iomap->range) {
+ if (idx == io->range) {
range_id[idx] = jdx;
idx++;
}
}
- for (idx = 0; idx < IO_RANGES; idx++) {
+ for (idx = 0; idx < ioranges; idx++) {
iores[idx] = platform_get_resource(sparx5->pdev, IORESOURCE_MEM,
idx);
if (!iores[idx]) {
@@ -245,12 +299,12 @@ static int sparx5_create_targets(struct sparx5 *sparx5)
iores[idx]->name);
return -ENOMEM;
}
- begin[idx] = iomem[idx] - sparx5_main_iomap[range_id[idx]].offset;
+ begin[idx] = iomem[idx] - iomap[range_id[idx]].offset;
}
- for (jdx = 0; jdx < ARRAY_SIZE(sparx5_main_iomap); jdx++) {
- const struct sparx5_main_io_resource *iomap = &sparx5_main_iomap[jdx];
+ for (jdx = 0; jdx < iomap_size; jdx++) {
+ const struct sparx5_main_io_resource *io = &iomap[jdx];
- sparx5->regs[iomap->id] = begin[iomap->range] + iomap->offset;
+ sparx5->regs[io->id] = begin[io->range] + io->offset;
}
return 0;
}
@@ -459,56 +513,74 @@ static int sparx5_init_coreclock(struct sparx5 *sparx5)
else if (sparx5->coreclock == SPX5_CORE_CLOCK_250MHZ)
freq = 0; /* Not supported */
break;
+ case SPX5_TARGET_CT_LAN9694:
+ case SPX5_TARGET_CT_LAN9691VAO:
+ case SPX5_TARGET_CT_LAN9694TSN:
+ case SPX5_TARGET_CT_LAN9694RED:
+ case SPX5_TARGET_CT_LAN9696:
+ case SPX5_TARGET_CT_LAN9692VAO:
+ case SPX5_TARGET_CT_LAN9696TSN:
+ case SPX5_TARGET_CT_LAN9696RED:
+ case SPX5_TARGET_CT_LAN9698:
+ case SPX5_TARGET_CT_LAN9693VAO:
+ case SPX5_TARGET_CT_LAN9698TSN:
+ case SPX5_TARGET_CT_LAN9698RED:
+ freq = SPX5_CORE_CLOCK_328MHZ;
+ break;
default:
dev_err(sparx5->dev, "Target (%#04x) not supported\n",
sparx5->target_ct);
return -ENODEV;
}
- switch (freq) {
- case SPX5_CORE_CLOCK_250MHZ:
- clk_div = 10;
- pol_upd_int = 312;
- break;
- case SPX5_CORE_CLOCK_500MHZ:
- clk_div = 5;
- pol_upd_int = 624;
- break;
- case SPX5_CORE_CLOCK_625MHZ:
- clk_div = 4;
- pol_upd_int = 780;
- break;
- default:
- dev_err(sparx5->dev, "%d coreclock not supported on (%#04x)\n",
- sparx5->coreclock, sparx5->target_ct);
- return -EINVAL;
+ if (is_sparx5(sparx5)) {
+ switch (freq) {
+ case SPX5_CORE_CLOCK_250MHZ:
+ clk_div = 10;
+ pol_upd_int = 312;
+ break;
+ case SPX5_CORE_CLOCK_500MHZ:
+ clk_div = 5;
+ pol_upd_int = 624;
+ break;
+ case SPX5_CORE_CLOCK_625MHZ:
+ clk_div = 4;
+ pol_upd_int = 780;
+ break;
+ default:
+ dev_err(sparx5->dev,
+ "%d coreclock not supported on (%#04x)\n",
+ sparx5->coreclock, sparx5->target_ct);
+ return -EINVAL;
+ }
+
+ /* Configure the LCPLL */
+ spx5_rmw(CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_DIV_SET(clk_div) |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_PRE_DIV_SET(0) |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_DIR_SET(0) |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_SEL_SET(0) |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_ENA_SET(0) |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_ENA_SET(1),
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_DIV |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_PRE_DIV |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_DIR |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_SEL |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_ENA |
+ CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_ENA,
+ sparx5, CLKGEN_LCPLL1_CORE_CLK_CFG);
+ } else {
+ pol_upd_int = 820; // SPX5_CORE_CLOCK_328MHZ
}
/* Update state with chosen frequency */
sparx5->coreclock = freq;
-
- /* Configure the LCPLL */
- spx5_rmw(CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_DIV_SET(clk_div) |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_PRE_DIV_SET(0) |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_DIR_SET(0) |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_SEL_SET(0) |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_ENA_SET(0) |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_ENA_SET(1),
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_DIV |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_PRE_DIV |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_DIR |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_SEL |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_ROT_ENA |
- CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_ENA,
- sparx5,
- CLKGEN_LCPLL1_CORE_CLK_CFG);
-
clk_period = sparx5_clk_period(freq);
- spx5_rmw(HSCH_SYS_CLK_PER_100PS_SET(clk_period / 100),
- HSCH_SYS_CLK_PER_100PS,
- sparx5,
- HSCH_SYS_CLK_PER);
+ if (is_sparx5(sparx5))
+ spx5_rmw(HSCH_SYS_CLK_PER_100PS_SET(clk_period / 100),
+ HSCH_SYS_CLK_PER_100PS,
+ sparx5,
+ HSCH_SYS_CLK_PER);
spx5_rmw(ANA_AC_POL_BDLB_DLB_CTRL_CLK_PERIOD_01NS_SET(clk_period / 100),
ANA_AC_POL_BDLB_DLB_CTRL_CLK_PERIOD_01NS,
@@ -525,7 +597,7 @@ static int sparx5_init_coreclock(struct sparx5 *sparx5)
sparx5,
LRN_AUTOAGE_CFG_1);
- for (idx = 0; idx < 3; idx++)
+ for (idx = 0; idx < sparx5->data->consts->n_sio_clks; idx++)
spx5_rmw(GCB_SIO_CLOCK_SYS_CLK_PERIOD_SET(clk_period / 100),
GCB_SIO_CLOCK_SYS_CLK_PERIOD,
sparx5,
@@ -545,25 +617,36 @@ static int sparx5_init_coreclock(struct sparx5 *sparx5)
return 0;
}
+static u32 qlim_wm(struct sparx5 *sparx5, int fraction)
+{
+ return (sparx5->data->consts->buf_size / SPX5_BUFFER_CELL_SZ - 100) *
+ fraction / 100;
+}
+
static int sparx5_qlim_set(struct sparx5 *sparx5)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
u32 res, dp, prio;
for (res = 0; res < 2; res++) {
for (prio = 0; prio < 8; prio++)
spx5_wr(0xFFF, sparx5,
- QRES_RES_CFG(prio + 630 + res * 1024));
+ QRES_RES_CFG(prio +
+ consts->qres_max_prio_idx +
+ res * 1024));
for (dp = 0; dp < 4; dp++)
spx5_wr(0xFFF, sparx5,
- QRES_RES_CFG(dp + 638 + res * 1024));
+ QRES_RES_CFG(dp +
+ consts->qres_max_colour_idx +
+ res * 1024));
}
/* Set 80,90,95,100% of memory size for top watermarks */
- spx5_wr(QLIM_WM(80), sparx5, XQS_QLIMIT_SHR_QLIM_CFG(0));
- spx5_wr(QLIM_WM(90), sparx5, XQS_QLIMIT_SHR_CTOP_CFG(0));
- spx5_wr(QLIM_WM(95), sparx5, XQS_QLIMIT_SHR_ATOP_CFG(0));
- spx5_wr(QLIM_WM(100), sparx5, XQS_QLIMIT_SHR_TOP_CFG(0));
+ spx5_wr(qlim_wm(sparx5, 80), sparx5, XQS_QLIMIT_SHR_QLIM_CFG(0));
+ spx5_wr(qlim_wm(sparx5, 90), sparx5, XQS_QLIMIT_SHR_CTOP_CFG(0));
+ spx5_wr(qlim_wm(sparx5, 95), sparx5, XQS_QLIMIT_SHR_ATOP_CFG(0));
+ spx5_wr(qlim_wm(sparx5, 100), sparx5, XQS_QLIMIT_SHR_TOP_CFG(0));
return 0;
}
@@ -585,7 +668,7 @@ static void sparx5_board_init(struct sparx5 *sparx5)
GCB_HW_SGPIO_SD_CFG);
/* Refer to LOS SGPIO */
- for (idx = 0; idx < SPX5_PORTS; idx++)
+ for (idx = 0; idx < sparx5->data->consts->n_ports; idx++)
if (sparx5->ports[idx])
if (sparx5->ports[idx]->conf.sd_sgpio != ~0)
spx5_wr(sparx5->ports[idx]->conf.sd_sgpio,
@@ -596,12 +679,14 @@ static void sparx5_board_init(struct sparx5 *sparx5)
static int sparx5_start(struct sparx5 *sparx5)
{
u8 broadcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ const struct sparx5_consts *consts = sparx5->data->consts;
+ const struct sparx5_ops *ops = sparx5->data->ops;
char queue_name[32];
u32 idx;
int err;
/* Setup own UPSIDs */
- for (idx = 0; idx < 3; idx++) {
+ for (idx = 0; idx < consts->n_own_upsids; idx++) {
spx5_wr(idx, sparx5, ANA_AC_OWN_UPSID(idx));
spx5_wr(idx, sparx5, ANA_CL_OWN_UPSID(idx));
spx5_wr(idx, sparx5, ANA_L2_OWN_UPSID(idx));
@@ -609,7 +694,7 @@ static int sparx5_start(struct sparx5 *sparx5)
}
/* Enable CPU ports */
- for (idx = SPX5_PORTS; idx < SPX5_PORTS_ALL; idx++)
+ for (idx = consts->n_ports; idx < consts->n_ports_all; idx++)
spx5_rmw(QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(1),
QFWD_SWITCH_PORT_MODE_PORT_ENA,
sparx5,
@@ -619,13 +704,14 @@ static int sparx5_start(struct sparx5 *sparx5)
sparx5_update_fwd(sparx5);
/* CPU copy CPU pgids */
- spx5_wr(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1),
- sparx5, ANA_AC_PGID_MISC_CFG(PGID_CPU));
- spx5_wr(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1),
- sparx5, ANA_AC_PGID_MISC_CFG(PGID_BCAST));
+ spx5_wr(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1), sparx5,
+ ANA_AC_PGID_MISC_CFG(sparx5_get_pgid(sparx5, PGID_CPU)));
+ spx5_wr(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1), sparx5,
+ ANA_AC_PGID_MISC_CFG(sparx5_get_pgid(sparx5, PGID_BCAST)));
/* Recalc injected frame FCS */
- for (idx = SPX5_PORT_CPU_0; idx <= SPX5_PORT_CPU_1; idx++)
+ for (idx = sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0);
+ idx <= sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1); idx++)
spx5_rmw(ANA_CL_FILTER_CTRL_FORCE_FCS_UPDATE_ENA_SET(1),
ANA_CL_FILTER_CTRL_FORCE_FCS_UPDATE_ENA,
sparx5, ANA_CL_FILTER_CTRL(idx));
@@ -640,7 +726,8 @@ static int sparx5_start(struct sparx5 *sparx5)
sparx5_vlan_init(sparx5);
/* Add host mode BC address (points only to CPU) */
- sparx5_mact_learn(sparx5, PGID_CPU, broadcast, NULL_VID);
+ sparx5_mact_learn(sparx5, sparx5_get_pgid(sparx5, PGID_CPU), broadcast,
+ NULL_VID);
/* Enable queue limitation watermarks */
sparx5_qlim_set(sparx5);
@@ -691,7 +778,7 @@ static int sparx5_start(struct sparx5 *sparx5)
/* Start Frame DMA with fallback to register based INJ/XTR */
err = -ENXIO;
- if (sparx5->fdma_irq >= 0) {
+ if (sparx5->fdma_irq >= 0 && is_sparx5(sparx5)) {
if (GCB_CHIP_ID_REV_ID_GET(sparx5->chip_id) > 0)
err = devm_request_threaded_irq(sparx5->dev,
sparx5->fdma_irq,
@@ -718,9 +805,10 @@ static int sparx5_start(struct sparx5 *sparx5)
sparx5->xtr_irq = -ENXIO;
}
- if (sparx5->ptp_irq >= 0) {
+ if (sparx5->ptp_irq >= 0 &&
+ sparx5_has_feature(sparx5, SPX5_FEATURE_PTP)) {
err = devm_request_threaded_irq(sparx5->dev, sparx5->ptp_irq,
- NULL, sparx5_ptp_irq_handler,
+ NULL, ops->ptp_irq_handler,
IRQF_ONESHOT, "sparx5-ptp",
sparx5);
if (err)
@@ -759,6 +847,12 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
sparx5->dev = &pdev->dev;
spin_lock_init(&sparx5->tx_lock);
+ sparx5->data = device_get_match_data(sparx5->dev);
+ if (!sparx5->data)
+ return -EINVAL;
+
+ regs = sparx5->data->regs;
+
/* Do switch core reset if available */
reset = devm_reset_control_get_optional_shared(&pdev->dev, "switch");
if (IS_ERR(reset))
@@ -856,6 +950,9 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
sparx5->target_ct = (enum spx5_target_chiptype)
GCB_CHIP_ID_PART_ID_GET(sparx5->chip_id);
+ /* Initialize the features based on the target */
+ sparx5_init_features(sparx5);
+
/* Initialize Switchcore and internal RAMs */
err = sparx5_init_switchcore(sparx5);
if (err) {
@@ -937,15 +1034,75 @@ static void mchp_sparx5_remove(struct platform_device *pdev)
destroy_workqueue(sparx5->mact_queue);
}
+static const struct sparx5_regs sparx5_regs = {
+ .tsize = sparx5_tsize,
+ .gaddr = sparx5_gaddr,
+ .gcnt = sparx5_gcnt,
+ .gsize = sparx5_gsize,
+ .raddr = sparx5_raddr,
+ .rcnt = sparx5_rcnt,
+ .fpos = sparx5_fpos,
+ .fsize = sparx5_fsize,
+};
+
+static const struct sparx5_consts sparx5_consts = {
+ .n_ports = 65,
+ .n_ports_all = 70,
+ .n_hsch_l1_elems = 64,
+ .n_hsch_queues = 8,
+ .n_lb_groups = 10,
+ .n_pgids = 2113, /* (2048 + n_ports) */
+ .n_sio_clks = 3,
+ .n_own_upsids = 3,
+ .n_auto_cals = 7,
+ .n_filters = 1024,
+ .n_gates = 1024,
+ .n_sdlbs = 4096,
+ .n_dsm_cal_taxis = 8,
+ .buf_size = 4194280,
+ .qres_max_prio_idx = 630,
+ .qres_max_colour_idx = 638,
+ .tod_pin = 4,
+ .vcaps = sparx5_vcaps,
+ .vcaps_cfg = sparx5_vcap_inst_cfg,
+ .vcap_stats = &sparx5_vcap_stats,
+};
+
+static const struct sparx5_ops sparx5_ops = {
+ .is_port_2g5 = &sparx5_port_is_2g5,
+ .is_port_5g = &sparx5_port_is_5g,
+ .is_port_10g = &sparx5_port_is_10g,
+ .is_port_25g = &sparx5_port_is_25g,
+ .get_port_dev_index = &sparx5_port_dev_mapping,
+ .get_port_dev_bit = &sparx5_port_dev_mapping,
+ .get_hsch_max_group_rate = &sparx5_get_hsch_max_group_rate,
+ .get_sdlb_group = &sparx5_get_sdlb_group,
+ .set_port_mux = &sparx5_port_mux_set,
+ .ptp_irq_handler = &sparx5_ptp_irq_handler,
+ .dsm_calendar_calc = &sparx5_dsm_calendar_calc,
+};
+
+static const struct sparx5_match_data sparx5_desc = {
+ .iomap = sparx5_main_iomap,
+ .iomap_size = ARRAY_SIZE(sparx5_main_iomap),
+ .ioranges = 3,
+ .regs = &sparx5_regs,
+ .consts = &sparx5_consts,
+ .ops = &sparx5_ops,
+};
+
static const struct of_device_id mchp_sparx5_match[] = {
- { .compatible = "microchip,sparx5-switch" },
+ { .compatible = "microchip,sparx5-switch", .data = &sparx5_desc },
+#if IS_ENABLED(CONFIG_LAN969X_SWITCH)
+ { .compatible = "microchip,lan9691-switch", .data = &lan969x_desc },
+#endif
{ }
};
MODULE_DEVICE_TABLE(of, mchp_sparx5_match);
static struct platform_driver mchp_sparx5_driver = {
.probe = mchp_sparx5_probe,
- .remove_new = mchp_sparx5_remove,
+ .remove = mchp_sparx5_remove,
.driver = {
.name = "sparx5-switch",
.of_match_table = mchp_sparx5_match,
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
index 3309060b1e4c..d5dd953b0a71 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
@@ -26,16 +26,28 @@
/* Target chip type */
enum spx5_target_chiptype {
- SPX5_TARGET_CT_7546 = 0x7546, /* SparX-5-64 Enterprise */
- SPX5_TARGET_CT_7549 = 0x7549, /* SparX-5-90 Enterprise */
- SPX5_TARGET_CT_7552 = 0x7552, /* SparX-5-128 Enterprise */
- SPX5_TARGET_CT_7556 = 0x7556, /* SparX-5-160 Enterprise */
- SPX5_TARGET_CT_7558 = 0x7558, /* SparX-5-200 Enterprise */
- SPX5_TARGET_CT_7546TSN = 0x47546, /* SparX-5-64i Industrial */
- SPX5_TARGET_CT_7549TSN = 0x47549, /* SparX-5-90i Industrial */
- SPX5_TARGET_CT_7552TSN = 0x47552, /* SparX-5-128i Industrial */
- SPX5_TARGET_CT_7556TSN = 0x47556, /* SparX-5-160i Industrial */
- SPX5_TARGET_CT_7558TSN = 0x47558, /* SparX-5-200i Industrial */
+ SPX5_TARGET_CT_7546 = 0x7546, /* SparX-5-64 Enterprise */
+ SPX5_TARGET_CT_7549 = 0x7549, /* SparX-5-90 Enterprise */
+ SPX5_TARGET_CT_7552 = 0x7552, /* SparX-5-128 Enterprise */
+ SPX5_TARGET_CT_7556 = 0x7556, /* SparX-5-160 Enterprise */
+ SPX5_TARGET_CT_7558 = 0x7558, /* SparX-5-200 Enterprise */
+ SPX5_TARGET_CT_7546TSN = 0x47546, /* SparX-5-64i Industrial */
+ SPX5_TARGET_CT_7549TSN = 0x47549, /* SparX-5-90i Industrial */
+ SPX5_TARGET_CT_7552TSN = 0x47552, /* SparX-5-128i Industrial */
+ SPX5_TARGET_CT_7556TSN = 0x47556, /* SparX-5-160i Industrial */
+ SPX5_TARGET_CT_7558TSN = 0x47558, /* SparX-5-200i Industrial */
+ SPX5_TARGET_CT_LAN9694 = 0x9694, /* lan969x-40 */
+ SPX5_TARGET_CT_LAN9691VAO = 0x9691, /* lan969x-40-VAO */
+ SPX5_TARGET_CT_LAN9694TSN = 0x9695, /* lan969x-40-TSN */
+ SPX5_TARGET_CT_LAN9694RED = 0x969A, /* lan969x-40-RED */
+ SPX5_TARGET_CT_LAN9696 = 0x9696, /* lan969x-60 */
+ SPX5_TARGET_CT_LAN9692VAO = 0x9692, /* lan969x-65-VAO */
+ SPX5_TARGET_CT_LAN9696TSN = 0x9697, /* lan969x-60-TSN */
+ SPX5_TARGET_CT_LAN9696RED = 0x969B, /* lan969x-60-RED */
+ SPX5_TARGET_CT_LAN9698 = 0x9698, /* lan969x-100 */
+ SPX5_TARGET_CT_LAN9693VAO = 0x9693, /* lan969x-100-VAO */
+ SPX5_TARGET_CT_LAN9698TSN = 0x9699, /* lan969x-100-TSN */
+ SPX5_TARGET_CT_LAN9698RED = 0x969C, /* lan969x-100-RED */
};
enum sparx5_port_max_tags {
@@ -51,25 +63,41 @@ enum sparx5_vlan_port_type {
SPX5_VLAN_PORT_TYPE_S_CUSTOM /* S-port using custom type */
};
+/* This is used in calendar configuration */
+enum sparx5_cal_bw {
+ SPX5_CAL_SPEED_NONE = 0,
+ SPX5_CAL_SPEED_1G = 1,
+ SPX5_CAL_SPEED_2G5 = 2,
+ SPX5_CAL_SPEED_5G = 3,
+ SPX5_CAL_SPEED_10G = 4,
+ SPX5_CAL_SPEED_25G = 5,
+ SPX5_CAL_SPEED_0G5 = 6,
+ SPX5_CAL_SPEED_12G5 = 7
+};
+
+enum sparx5_feature {
+ SPX5_FEATURE_PSFP = BIT(0),
+ SPX5_FEATURE_PTP = BIT(1),
+};
+
#define SPX5_PORTS 65
-#define SPX5_PORT_CPU (SPX5_PORTS) /* Next port is CPU port */
-#define SPX5_PORT_CPU_0 (SPX5_PORT_CPU + 0) /* CPU Port 65 */
-#define SPX5_PORT_CPU_1 (SPX5_PORT_CPU + 1) /* CPU Port 66 */
-#define SPX5_PORT_VD0 (SPX5_PORT_CPU + 2) /* VD0/Port 67 used for IPMC */
-#define SPX5_PORT_VD1 (SPX5_PORT_CPU + 3) /* VD1/Port 68 used for AFI/OAM */
-#define SPX5_PORT_VD2 (SPX5_PORT_CPU + 4) /* VD2/Port 69 used for IPinIP*/
-#define SPX5_PORTS_ALL (SPX5_PORT_CPU + 5) /* Total number of ports */
-
-#define PGID_BASE SPX5_PORTS /* Starts after port PGIDs */
-#define PGID_UC_FLOOD (PGID_BASE + 0)
-#define PGID_MC_FLOOD (PGID_BASE + 1)
-#define PGID_IPV4_MC_DATA (PGID_BASE + 2)
-#define PGID_IPV4_MC_CTRL (PGID_BASE + 3)
-#define PGID_IPV6_MC_DATA (PGID_BASE + 4)
-#define PGID_IPV6_MC_CTRL (PGID_BASE + 5)
-#define PGID_BCAST (PGID_BASE + 6)
-#define PGID_CPU (PGID_BASE + 7)
-#define PGID_MCAST_START (PGID_BASE + 8)
+#define SPX5_PORTS_ALL 70 /* Total number of ports */
+
+#define SPX5_PORT_CPU_0 0 /* CPU Port 0 */
+#define SPX5_PORT_CPU_1 1 /* CPU Port 1 */
+#define SPX5_PORT_VD0 2 /* VD0/Port used for IPMC */
+#define SPX5_PORT_VD1 3 /* VD1/Port used for AFI/OAM */
+#define SPX5_PORT_VD2 4 /* VD2/Port used for IPinIP*/
+
+#define PGID_UC_FLOOD 0
+#define PGID_MC_FLOOD 1
+#define PGID_IPV4_MC_DATA 2
+#define PGID_IPV4_MC_CTRL 3
+#define PGID_IPV6_MC_DATA 4
+#define PGID_IPV6_MC_CTRL 5
+#define PGID_BCAST 6
+#define PGID_CPU 7
+#define PGID_MCAST_START 8
#define PGID_TABLE_SIZE 3290
@@ -100,8 +128,27 @@ enum sparx5_vlan_port_type {
#define IFH_PDU_TYPE_IPV4_UDP_PTP 0x6
#define IFH_PDU_TYPE_IPV6_UDP_PTP 0x7
+#define SPX5_DSM_CAL_LEN 64
+#define SPX5_DSM_CAL_MAX_DEVS_PER_TAXI 13
+#define SPX5_DSM_CAL_EMPTY 0xFFFF
+
+#define SPARX5_MAX_PTP_ID 512
+
struct sparx5;
+struct sparx5_calendar_data {
+ u32 schedule[SPX5_DSM_CAL_LEN];
+ u32 avg_dist[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
+ u32 taxi_ports[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
+ u32 taxi_speeds[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
+ u32 dev_slots[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
+ u32 new_slots[SPX5_DSM_CAL_LEN];
+ u32 temp_sched[SPX5_DSM_CAL_LEN];
+ u32 indices[SPX5_DSM_CAL_LEN];
+ u32 short_list[SPX5_DSM_CAL_LEN];
+ u32 long_list[SPX5_DSM_CAL_LEN];
+};
+
/* Frame DMA receive state:
* For each DB, there is a SKB, and the skb data pointer is mapped in
* the DB. Once a frame is received the skb is given to the upper layers
@@ -177,6 +224,7 @@ struct sparx5_port {
enum sparx5_core_clockfreq {
SPX5_CORE_CLOCK_DEFAULT, /* Defaults to the highest supported frequency */
SPX5_CORE_CLOCK_250MHZ, /* 250MHZ core clock frequency */
+ SPX5_CORE_CLOCK_328MHZ, /* 328MHZ core clock frequency */
SPX5_CORE_CLOCK_500MHZ, /* 500MHZ core clock frequency */
SPX5_CORE_CLOCK_625MHZ, /* 625MHZ core clock frequency */
};
@@ -226,11 +274,78 @@ struct sparx5_mall_entry {
#define SPARX5_SKB_CB(skb) \
((struct sparx5_skb_cb *)((skb)->cb))
+struct sparx5_regs {
+ const unsigned int *tsize;
+ const unsigned int *gaddr;
+ const unsigned int *gcnt;
+ const unsigned int *gsize;
+ const unsigned int *raddr;
+ const unsigned int *rcnt;
+ const unsigned int *fpos;
+ const unsigned int *fsize;
+};
+
+struct sparx5_consts {
+ u32 n_ports; /* Number of front ports */
+ u32 n_ports_all; /* Number of front ports + internal ports */
+ u32 n_hsch_l1_elems; /* Number of HSCH layer 1 elements */
+ u32 n_hsch_queues; /* Number of HSCH queues */
+ u32 n_lb_groups; /* Number of leacky bucket groupd */
+ u32 n_pgids; /* Number of PGID's */
+ u32 n_sio_clks; /* Number of serial IO clocks */
+ u32 n_own_upsids; /* Number of own UPSID's */
+ u32 n_auto_cals; /* Number of auto calendars */
+ u32 n_filters; /* Number of PSFP filters */
+ u32 n_gates; /* Number of PSFP gates */
+ u32 n_sdlbs; /* Number of service dual leaky buckets */
+ u32 n_dsm_cal_taxis; /* Number of DSM calendar taxis */
+ u32 buf_size; /* Amount of QLIM watermark memory */
+ u32 qres_max_prio_idx; /* Maximum QRES prio index */
+ u32 qres_max_colour_idx; /* Maximum QRES colour index */
+ u32 tod_pin; /* PTP TOD pin */
+ const struct sparx5_vcap_inst *vcaps_cfg;
+ const struct vcap_info *vcaps;
+ const struct vcap_statistics *vcap_stats;
+};
+
+struct sparx5_ops {
+ bool (*is_port_2g5)(int portno);
+ bool (*is_port_5g)(int portno);
+ bool (*is_port_10g)(int portno);
+ bool (*is_port_25g)(int portno);
+ u32 (*get_port_dev_index)(struct sparx5 *sparx5, int port);
+ u32 (*get_port_dev_bit)(struct sparx5 *sparx5, int port);
+ u32 (*get_hsch_max_group_rate)(int grp);
+ struct sparx5_sdlb_group *(*get_sdlb_group)(int idx);
+ int (*set_port_mux)(struct sparx5 *sparx5, struct sparx5_port *port,
+ struct sparx5_port_config *conf);
+
+ irqreturn_t (*ptp_irq_handler)(int irq, void *args);
+ int (*dsm_calendar_calc)(struct sparx5 *sparx5, u32 taxi,
+ struct sparx5_calendar_data *data);
+};
+
+struct sparx5_main_io_resource {
+ enum sparx5_target id;
+ phys_addr_t offset;
+ int range;
+};
+
+struct sparx5_match_data {
+ const struct sparx5_regs *regs;
+ const struct sparx5_consts *consts;
+ const struct sparx5_ops *ops;
+ const struct sparx5_main_io_resource *iomap;
+ int ioranges;
+ int iomap_size;
+};
+
struct sparx5 {
struct platform_device *pdev;
struct device *dev;
u32 chip_id;
enum spx5_target_chiptype target_ct;
+ u32 features;
void __iomem *regs[NUM_TARGETS];
int port_count;
struct mutex lock; /* MAC reg lock */
@@ -293,8 +408,13 @@ struct sparx5 {
struct list_head mall_entries;
/* Common root for debugfs */
struct dentry *debugfs_root;
+ const struct sparx5_match_data *data;
};
+/* sparx5_main.c */
+bool is_sparx5(struct sparx5 *sparx5);
+bool sparx5_has_feature(struct sparx5 *sparx5, enum sparx5_feature feature);
+
/* sparx5_switchdev.c */
int sparx5_register_notifier_blocks(struct sparx5 *sparx5);
void sparx5_unregister_notifier_blocks(struct sparx5 *sparx5);
@@ -306,7 +426,7 @@ struct frame_info {
};
void sparx5_xtr_flush(struct sparx5 *sparx5, u8 grp);
-void sparx5_ifh_parse(u32 *ifh, struct frame_info *info);
+void sparx5_ifh_parse(struct sparx5 *sparx5, u32 *ifh, struct frame_info *info);
irqreturn_t sparx5_xtr_handler(int irq, void *_priv);
netdev_tx_t sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev);
int sparx5_manual_injection_mode(struct sparx5 *sparx5);
@@ -355,6 +475,11 @@ void sparx5_vlan_port_apply(struct sparx5 *sparx5, struct sparx5_port *port);
/* sparx5_calendar.c */
int sparx5_config_auto_calendar(struct sparx5 *sparx5);
int sparx5_config_dsm_calendar(struct sparx5 *sparx5);
+int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
+ struct sparx5_calendar_data *data);
+u32 sparx5_cal_speed_to_value(enum sparx5_cal_bw speed);
+enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5, u32 portno);
+
/* sparx5_ethtool.c */
void sparx5_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats);
@@ -371,11 +496,14 @@ static inline int sparx5_dcb_init(struct sparx5 *sparx5)
#endif
/* sparx5_netdev.c */
-void sparx5_set_port_ifh_timestamp(void *ifh_hdr, u64 timestamp);
+void sparx5_set_port_ifh_timestamp(struct sparx5 *sparx5, void *ifh_hdr,
+ u64 timestamp);
void sparx5_set_port_ifh_rew_op(void *ifh_hdr, u32 rew_op);
-void sparx5_set_port_ifh_pdu_type(void *ifh_hdr, u32 pdu_type);
-void sparx5_set_port_ifh_pdu_w16_offset(void *ifh_hdr, u32 pdu_w16_offset);
-void sparx5_set_port_ifh(void *ifh_hdr, u16 portno);
+void sparx5_set_port_ifh_pdu_type(struct sparx5 *sparx5, void *ifh_hdr,
+ u32 pdu_type);
+void sparx5_set_port_ifh_pdu_w16_offset(struct sparx5 *sparx5, void *ifh_hdr,
+ u32 pdu_w16_offset);
+void sparx5_set_port_ifh(struct sparx5 *sparx5, void *ifh_hdr, u16 portno);
bool sparx5_netdevice_check(const struct net_device *dev);
struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno);
int sparx5_register_netdevs(struct sparx5 *sparx5);
@@ -398,6 +526,9 @@ void sparx5_ptp_txtstamp_release(struct sparx5_port *port,
struct sk_buff *skb);
irqreturn_t sparx5_ptp_irq_handler(int irq, void *args);
int sparx5_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
+void sparx5_get_hwtimestamp(struct sparx5 *sparx5,
+ struct timespec64 *ts,
+ u32 nsec);
/* sparx5_vcap_impl.c */
int sparx5_vcap_init(struct sparx5 *sparx5);
@@ -413,6 +544,7 @@ enum sparx5_pgid_type {
void sparx5_pgid_init(struct sparx5 *spx5);
int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx);
int sparx5_pgid_free(struct sparx5 *spx5, u16 idx);
+int sparx5_get_pgid(struct sparx5 *sparx5, int pgid);
/* sparx5_pool.c */
struct sparx5_pool_entry {
@@ -426,6 +558,11 @@ int sparx5_pool_get(struct sparx5_pool_entry *pool, int size, u32 *id);
int sparx5_pool_get_with_idx(struct sparx5_pool_entry *pool, int size, u32 idx,
u32 *id);
+/* sparx5_port.c */
+int sparx5_port_mux_set(struct sparx5 *sparx5, struct sparx5_port *port,
+ struct sparx5_port_config *conf);
+int sparx5_get_internal_port(struct sparx5 *sparx5, int port);
+
/* sparx5_sdlb.c */
#define SPX5_SDLB_PUP_TOKEN_DISABLE 0x1FFF
#define SPX5_SDLB_PUP_TOKEN_MAX (SPX5_SDLB_PUP_TOKEN_DISABLE - 1)
@@ -444,10 +581,11 @@ struct sparx5_sdlb_group {
};
extern struct sparx5_sdlb_group sdlb_groups[SPX5_SDLB_GROUP_CNT];
+struct sparx5_sdlb_group *sparx5_get_sdlb_group(int idx);
int sparx5_sdlb_pup_token_get(struct sparx5 *sparx5, u32 pup_interval,
u64 rate);
-int sparx5_sdlb_clk_hz_get(struct sparx5 *sparx5);
+u64 sparx5_sdlb_clk_hz_get(struct sparx5 *sparx5);
int sparx5_sdlb_group_get_by_rate(struct sparx5 *sparx5, u32 rate, u32 burst);
int sparx5_sdlb_group_get_by_index(struct sparx5 *sparx5, u32 idx, u32 *group);
@@ -549,6 +687,8 @@ static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock)
switch (cclock) {
case SPX5_CORE_CLOCK_250MHZ:
return 4000;
+ case SPX5_CORE_CLOCK_328MHZ:
+ return 3048;
case SPX5_CORE_CLOCK_500MHZ:
return 2000;
case SPX5_CORE_CLOCK_625MHZ:
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
index 22acc1f3380c..561344f19062 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+
* Microchip Sparx5 Switch driver
*
- * Copyright (c) 2021 Microchip Technology Inc.
+ * Copyright (c) 2024 Microchip Technology Inc.
*/
-/* This file is autogenerated by cml-utils 2023-02-10 11:18:53 +0100.
- * Commit ID: c30fb4bf0281cd4a7133bdab6682f9e43c872ada
+/* This file is autogenerated by cml-utils 2024-10-04 10:40:40 +0200.
+ * Commit ID: 9d07b8d19363f3cd3590ddb3f7a2e2768e16524b
*/
#ifndef _SPARX5_MAIN_REGS_H_
@@ -15,6 +15,8 @@
#include <linux/types.h>
#include <linux/bug.h>
+#include "sparx5_regs.h"
+
enum sparx5_target {
TARGET_ANA_AC = 1,
TARGET_ANA_ACL = 2,
@@ -52,14 +54,27 @@ enum sparx5_target {
TARGET_VCAP_SUPER = 326,
TARGET_VOP = 327,
TARGET_XQS = 331,
- NUM_TARGETS = 332
+ NUM_TARGETS = 517
};
+/* sparx5_main.c
+ *
+ * This is used by the register macros to access chip differences (if any) in:
+ * target size, register address, register count, group address, group count,
+ * group size, field position and field size.
+ */
+extern const struct sparx5_regs *regs;
+
+/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
+#define spx5_field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+#define spx5_field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
+
#define __REG(...) __VA_ARGS__
-/* ANA_AC:RAM_CTRL:RAM_INIT */
-#define ANA_AC_RAM_INIT __REG(TARGET_ANA_AC,\
- 0, 1, 839108, 0, 1, 4, 0, 0, 1, 4)
+/* ANA_AC:RAM_CTRL:RAM_INIT */
+#define ANA_AC_RAM_INIT \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_RAM_CTRL], 0, 1, 4, 0,\
+ 0, 1, 4)
#define ANA_AC_RAM_INIT_RAM_INIT BIT(1)
#define ANA_AC_RAM_INIT_RAM_INIT_SET(x)\
@@ -73,9 +88,10 @@ enum sparx5_target {
#define ANA_AC_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(ANA_AC_RAM_INIT_RAM_CFG_HOOK, x)
-/* ANA_AC:PS_COMMON:OWN_UPSID */
-#define ANA_AC_OWN_UPSID(r) __REG(TARGET_ANA_AC,\
- 0, 1, 894472, 0, 1, 352, 52, r, 3, 4)
+/* ANA_AC:PS_COMMON:OWN_UPSID */
+#define ANA_AC_OWN_UPSID(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_PS_COMMON], 0, 1, 352,\
+ 52, r, regs->rcnt[RC_ANA_AC_OWN_UPSID], 4)
#define ANA_AC_OWN_UPSID_OWN_UPSID GENMASK(4, 0)
#define ANA_AC_OWN_UPSID_OWN_UPSID_SET(x)\
@@ -83,75 +99,86 @@ enum sparx5_target {
#define ANA_AC_OWN_UPSID_OWN_UPSID_GET(x)\
FIELD_GET(ANA_AC_OWN_UPSID_OWN_UPSID, x)
-/* ANA_AC:MIRROR_PROBE:PROBE_CFG */
-#define ANA_AC_PROBE_CFG(g) \
- __REG(TARGET_ANA_AC, 0, 1, 893696, g, 3, 32, 0, 0, 1, 4)
+/* ANA_AC:MIRROR_PROBE:PROBE_CFG */
+#define ANA_AC_PROBE_CFG(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_MIRROR_PROBE], g, 3, \
+ 32, 0, 0, 1, 4)
-#define ANA_AC_PROBE_CFG_PROBE_RX_CPU_AND_VD GENMASK(31, 27)
+#define ANA_AC_PROBE_CFG_PROBE_RX_CPU_AND_VD GENMASK(31, 27)
#define ANA_AC_PROBE_CFG_PROBE_RX_CPU_AND_VD_SET(x)\
FIELD_PREP(ANA_AC_PROBE_CFG_PROBE_RX_CPU_AND_VD, x)
#define ANA_AC_PROBE_CFG_PROBE_RX_CPU_AND_VD_GET(x)\
FIELD_GET(ANA_AC_PROBE_CFG_PROBE_RX_CPU_AND_VD, x)
-#define ANA_AC_PROBE_CFG_PROBE_CPU_SET GENMASK(26, 19)
+#define ANA_AC_PROBE_CFG_PROBE_CPU_SET GENMASK(26, 19)
#define ANA_AC_PROBE_CFG_PROBE_CPU_SET_SET(x)\
FIELD_PREP(ANA_AC_PROBE_CFG_PROBE_CPU_SET, x)
#define ANA_AC_PROBE_CFG_PROBE_CPU_SET_GET(x)\
FIELD_GET(ANA_AC_PROBE_CFG_PROBE_CPU_SET, x)
-#define ANA_AC_PROBE_CFG_PROBE_VID GENMASK(18, 6)
+#define ANA_AC_PROBE_CFG_PROBE_VID GENMASK(18, 6)
#define ANA_AC_PROBE_CFG_PROBE_VID_SET(x)\
FIELD_PREP(ANA_AC_PROBE_CFG_PROBE_VID, x)
#define ANA_AC_PROBE_CFG_PROBE_VID_GET(x)\
FIELD_GET(ANA_AC_PROBE_CFG_PROBE_VID, x)
-#define ANA_AC_PROBE_CFG_PROBE_VLAN_MODE GENMASK(5, 4)
+#define ANA_AC_PROBE_CFG_PROBE_VLAN_MODE GENMASK(5, 4)
#define ANA_AC_PROBE_CFG_PROBE_VLAN_MODE_SET(x)\
FIELD_PREP(ANA_AC_PROBE_CFG_PROBE_VLAN_MODE, x)
#define ANA_AC_PROBE_CFG_PROBE_VLAN_MODE_GET(x)\
FIELD_GET(ANA_AC_PROBE_CFG_PROBE_VLAN_MODE, x)
-#define ANA_AC_PROBE_CFG_PROBE_MAC_MODE GENMASK(3, 2)
+#define ANA_AC_PROBE_CFG_PROBE_MAC_MODE GENMASK(3, 2)
#define ANA_AC_PROBE_CFG_PROBE_MAC_MODE_SET(x)\
FIELD_PREP(ANA_AC_PROBE_CFG_PROBE_MAC_MODE, x)
#define ANA_AC_PROBE_CFG_PROBE_MAC_MODE_GET(x)\
FIELD_GET(ANA_AC_PROBE_CFG_PROBE_MAC_MODE, x)
-#define ANA_AC_PROBE_CFG_PROBE_DIRECTION GENMASK(1, 0)
+#define ANA_AC_PROBE_CFG_PROBE_DIRECTION GENMASK(1, 0)
#define ANA_AC_PROBE_CFG_PROBE_DIRECTION_SET(x)\
FIELD_PREP(ANA_AC_PROBE_CFG_PROBE_DIRECTION, x)
#define ANA_AC_PROBE_CFG_PROBE_DIRECTION_GET(x)\
FIELD_GET(ANA_AC_PROBE_CFG_PROBE_DIRECTION, x)
-/* ANA_AC:MIRROR_PROBE:PROBE_PORT_CFG */
-#define ANA_AC_PROBE_PORT_CFG(g) \
- __REG(TARGET_ANA_AC, 0, 1, 893696, g, 3, 32, 8, 0, 1, 4)
+/* ANA_AC:MIRROR_PROBE:PROBE_PORT_CFG */
+#define ANA_AC_PROBE_PORT_CFG(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_MIRROR_PROBE], g, 3, \
+ 32, 8, 0, 1, 4)
-/* ANA_AC:MIRROR_PROBE:PROBE_PORT_CFG1 */
-#define ANA_AC_PROBE_PORT_CFG1(g) \
- __REG(TARGET_ANA_AC, 0, 1, 893696, g, 3, 32, 12, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_AC:MIRROR_PROBE:PROBE_PORT_CFG1 */
+#define ANA_AC_PROBE_PORT_CFG1(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_MIRROR_PROBE], g, 3, \
+ 32, 12, 0, 1, 4)
-/* ANA_AC:MIRROR_PROBE:PROBE_PORT_CFG2 */
-#define ANA_AC_PROBE_PORT_CFG2(g) \
- __REG(TARGET_ANA_AC, 0, 1, 893696, g, 3, 32, 16, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_AC:MIRROR_PROBE:PROBE_PORT_CFG2 */
+#define ANA_AC_PROBE_PORT_CFG2(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_MIRROR_PROBE], g, 3, \
+ 32, 16, 0, 1, 4)
-#define ANA_AC_PROBE_PORT_CFG2_PROBE_PORT_MASK2 BIT(0)
+#define ANA_AC_PROBE_PORT_CFG2_PROBE_PORT_MASK2 BIT(0)
#define ANA_AC_PROBE_PORT_CFG2_PROBE_PORT_MASK2_SET(x)\
FIELD_PREP(ANA_AC_PROBE_PORT_CFG2_PROBE_PORT_MASK2, x)
#define ANA_AC_PROBE_PORT_CFG2_PROBE_PORT_MASK2_GET(x)\
FIELD_GET(ANA_AC_PROBE_PORT_CFG2_PROBE_PORT_MASK2, x)
-/* ANA_AC:SRC:SRC_CFG */
-#define ANA_AC_SRC_CFG(g) __REG(TARGET_ANA_AC,\
- 0, 1, 849920, g, 102, 16, 0, 0, 1, 4)
+/* ANA_AC:SRC:SRC_CFG */
+#define ANA_AC_SRC_CFG(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SRC], g, \
+ regs->gcnt[GC_ANA_AC_SRC], regs->gsize[GW_ANA_AC_SRC], 0, 0, 1, 4)
-/* ANA_AC:SRC:SRC_CFG1 */
-#define ANA_AC_SRC_CFG1(g) __REG(TARGET_ANA_AC,\
- 0, 1, 849920, g, 102, 16, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_AC:SRC:SRC_CFG1 */
+#define ANA_AC_SRC_CFG1(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SRC], g, \
+ regs->gcnt[GC_ANA_AC_SRC], regs->gsize[GW_ANA_AC_SRC], 4, 0, 1, 4)
-/* ANA_AC:SRC:SRC_CFG2 */
-#define ANA_AC_SRC_CFG2(g) __REG(TARGET_ANA_AC,\
- 0, 1, 849920, g, 102, 16, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_AC:SRC:SRC_CFG2 */
+#define ANA_AC_SRC_CFG2(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SRC], g, \
+ regs->gcnt[GC_ANA_AC_SRC], regs->gsize[GW_ANA_AC_SRC], 8, 0, 1, 4)
#define ANA_AC_SRC_CFG2_PORT_MASK2 BIT(0)
#define ANA_AC_SRC_CFG2_PORT_MASK2_SET(x)\
@@ -159,17 +186,22 @@ enum sparx5_target {
#define ANA_AC_SRC_CFG2_PORT_MASK2_GET(x)\
FIELD_GET(ANA_AC_SRC_CFG2_PORT_MASK2, x)
-/* ANA_AC:PGID:PGID_CFG */
-#define ANA_AC_PGID_CFG(g) __REG(TARGET_ANA_AC,\
- 0, 1, 786432, g, 3290, 16, 0, 0, 1, 4)
+/* ANA_AC:PGID:PGID_CFG */
+#define ANA_AC_PGID_CFG(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_PGID], g, \
+ regs->gcnt[GC_ANA_AC_PGID], 16, 0, 0, 1, 4)
-/* ANA_AC:PGID:PGID_CFG1 */
-#define ANA_AC_PGID_CFG1(g) __REG(TARGET_ANA_AC,\
- 0, 1, 786432, g, 3290, 16, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_AC:PGID:PGID_CFG1 */
+#define ANA_AC_PGID_CFG1(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_PGID], g, \
+ regs->gcnt[GC_ANA_AC_PGID], 16, 4, 0, 1, 4)
-/* ANA_AC:PGID:PGID_CFG2 */
-#define ANA_AC_PGID_CFG2(g) __REG(TARGET_ANA_AC,\
- 0, 1, 786432, g, 3290, 16, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_AC:PGID:PGID_CFG2 */
+#define ANA_AC_PGID_CFG2(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_PGID], g, \
+ regs->gcnt[GC_ANA_AC_PGID], 16, 8, 0, 1, 4)
#define ANA_AC_PGID_CFG2_PORT_MASK2 BIT(0)
#define ANA_AC_PGID_CFG2_PORT_MASK2_SET(x)\
@@ -177,9 +209,10 @@ enum sparx5_target {
#define ANA_AC_PGID_CFG2_PORT_MASK2_GET(x)\
FIELD_GET(ANA_AC_PGID_CFG2_PORT_MASK2, x)
-/* ANA_AC:PGID:PGID_MISC_CFG */
-#define ANA_AC_PGID_MISC_CFG(g) __REG(TARGET_ANA_AC,\
- 0, 1, 786432, g, 3290, 16, 12, 0, 1, 4)
+/* ANA_AC:PGID:PGID_MISC_CFG */
+#define ANA_AC_PGID_MISC_CFG(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_PGID], g, \
+ regs->gcnt[GC_ANA_AC_PGID], 16, 12, 0, 1, 4)
#define ANA_AC_PGID_MISC_CFG_PGID_CPU_QU GENMASK(6, 4)
#define ANA_AC_PGID_MISC_CFG_PGID_CPU_QU_SET(x)\
@@ -199,9 +232,10 @@ enum sparx5_target {
#define ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_GET(x)\
FIELD_GET(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, x)
-/* ANA_AC:TSN_SF:TSN_SF */
-#define ANA_AC_TSN_SF __REG(TARGET_ANA_AC,\
- 0, 1, 839136, 0, 1, 4, 0, 0, 1, 4)
+/* ANA_AC:TSN_SF:TSN_SF */
+#define ANA_AC_TSN_SF \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_TSN_SF], 0, 1, 4, 0, \
+ 0, 1, 4)
#define ANA_AC_TSN_SF_TSN_STREAM_BLOCK_OVERSIZE_STICKY BIT(9)
#define ANA_AC_TSN_SF_TSN_STREAM_BLOCK_OVERSIZE_STICKY_SET(x)\
@@ -209,21 +243,24 @@ enum sparx5_target {
#define ANA_AC_TSN_SF_TSN_STREAM_BLOCK_OVERSIZE_STICKY_GET(x)\
FIELD_GET(ANA_AC_TSN_SF_TSN_STREAM_BLOCK_OVERSIZE_STICKY, x)
-#define ANA_AC_TSN_SF_PORT_NUM GENMASK(8, 0)
+#define ANA_AC_TSN_SF_PORT_NUM\
+ GENMASK(regs->fsize[FW_ANA_AC_TSN_SF_PORT_NUM] + 0 - 1, 0)
#define ANA_AC_TSN_SF_PORT_NUM_SET(x)\
- FIELD_PREP(ANA_AC_TSN_SF_PORT_NUM, x)
+ spx5_field_prep(ANA_AC_TSN_SF_PORT_NUM, x)
#define ANA_AC_TSN_SF_PORT_NUM_GET(x)\
- FIELD_GET(ANA_AC_TSN_SF_PORT_NUM, x)
+ spx5_field_get(ANA_AC_TSN_SF_PORT_NUM, x)
-/* ANA_AC:TSN_SF_CFG:TSN_SF_CFG */
-#define ANA_AC_TSN_SF_CFG(g) __REG(TARGET_ANA_AC,\
- 0, 1, 839680, g, 1024, 4, 0, 0, 1, 4)
+/* ANA_AC:TSN_SF_CFG:TSN_SF_CFG */
+#define ANA_AC_TSN_SF_CFG(g) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_TSN_SF_CFG], g, \
+ regs->gcnt[GC_ANA_AC_TSN_SF_CFG], 4, 0, 0, 1, 4)
-#define ANA_AC_TSN_SF_CFG_TSN_SGID GENMASK(25, 16)
+#define ANA_AC_TSN_SF_CFG_TSN_SGID\
+ GENMASK(regs->fsize[FW_ANA_AC_TSN_SF_CFG_TSN_SGID] + 16 - 1, 16)
#define ANA_AC_TSN_SF_CFG_TSN_SGID_SET(x)\
- FIELD_PREP(ANA_AC_TSN_SF_CFG_TSN_SGID, x)
+ spx5_field_prep(ANA_AC_TSN_SF_CFG_TSN_SGID, x)
#define ANA_AC_TSN_SF_CFG_TSN_SGID_GET(x)\
- FIELD_GET(ANA_AC_TSN_SF_CFG_TSN_SGID, x)
+ spx5_field_get(ANA_AC_TSN_SF_CFG_TSN_SGID, x)
#define ANA_AC_TSN_SF_CFG_TSN_MAX_SDU GENMASK(15, 2)
#define ANA_AC_TSN_SF_CFG_TSN_MAX_SDU_SET(x)\
@@ -243,9 +280,10 @@ enum sparx5_target {
#define ANA_AC_TSN_SF_CFG_BLOCK_OVERSIZE_STATE_GET(x)\
FIELD_GET(ANA_AC_TSN_SF_CFG_BLOCK_OVERSIZE_STATE, x)
-/* ANA_AC:TSN_SF_STATUS:TSN_SF_STATUS */
-#define ANA_AC_TSN_SF_STATUS __REG(TARGET_ANA_AC,\
- 0, 1, 839072, 0, 1, 16, 0, 0, 1, 4)
+/* ANA_AC:TSN_SF_STATUS:TSN_SF_STATUS */
+#define ANA_AC_TSN_SF_STATUS \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_TSN_SF_STATUS], 0, 1, \
+ 16, 0, 0, 1, 4)
#define ANA_AC_TSN_SF_STATUS_FRM_LEN GENMASK(25, 12)
#define ANA_AC_TSN_SF_STATUS_FRM_LEN_SET(x)\
@@ -259,11 +297,12 @@ enum sparx5_target {
#define ANA_AC_TSN_SF_STATUS_DLB_DROP_GET(x)\
FIELD_GET(ANA_AC_TSN_SF_STATUS_DLB_DROP, x)
-#define ANA_AC_TSN_SF_STATUS_TSN_SFID GENMASK(10, 1)
+#define ANA_AC_TSN_SF_STATUS_TSN_SFID\
+ GENMASK(regs->fsize[FW_ANA_AC_TSN_SF_STATUS_TSN_SFID] + 1 - 1, 1)
#define ANA_AC_TSN_SF_STATUS_TSN_SFID_SET(x)\
- FIELD_PREP(ANA_AC_TSN_SF_STATUS_TSN_SFID, x)
+ spx5_field_prep(ANA_AC_TSN_SF_STATUS_TSN_SFID, x)
#define ANA_AC_TSN_SF_STATUS_TSN_SFID_GET(x)\
- FIELD_GET(ANA_AC_TSN_SF_STATUS_TSN_SFID, x)
+ spx5_field_get(ANA_AC_TSN_SF_STATUS_TSN_SFID, x)
#define ANA_AC_TSN_SF_STATUS_TSTAMP_VLD BIT(0)
#define ANA_AC_TSN_SF_STATUS_TSTAMP_VLD_SET(x)\
@@ -271,15 +310,17 @@ enum sparx5_target {
#define ANA_AC_TSN_SF_STATUS_TSTAMP_VLD_GET(x)\
FIELD_GET(ANA_AC_TSN_SF_STATUS_TSTAMP_VLD, x)
-/* ANA_AC:SG_ACCESS:SG_ACCESS_CTRL */
-#define ANA_AC_SG_ACCESS_CTRL __REG(TARGET_ANA_AC,\
- 0, 1, 839140, 0, 1, 12, 0, 0, 1, 4)
+/* ANA_AC:SG_ACCESS:SG_ACCESS_CTRL */
+#define ANA_AC_SG_ACCESS_CTRL \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_ACCESS], 0, 1, 12, \
+ 0, 0, 1, 4)
-#define ANA_AC_SG_ACCESS_CTRL_SGID GENMASK(9, 0)
+#define ANA_AC_SG_ACCESS_CTRL_SGID\
+ GENMASK(regs->fsize[FW_ANA_AC_SG_ACCESS_CTRL_SGID] + 0 - 1, 0)
#define ANA_AC_SG_ACCESS_CTRL_SGID_SET(x)\
- FIELD_PREP(ANA_AC_SG_ACCESS_CTRL_SGID, x)
+ spx5_field_prep(ANA_AC_SG_ACCESS_CTRL_SGID, x)
#define ANA_AC_SG_ACCESS_CTRL_SGID_GET(x)\
- FIELD_GET(ANA_AC_SG_ACCESS_CTRL_SGID, x)
+ spx5_field_get(ANA_AC_SG_ACCESS_CTRL_SGID, x)
#define ANA_AC_SG_ACCESS_CTRL_CONFIG_CHANGE BIT(28)
#define ANA_AC_SG_ACCESS_CTRL_CONFIG_CHANGE_SET(x)\
@@ -287,9 +328,10 @@ enum sparx5_target {
#define ANA_AC_SG_ACCESS_CTRL_CONFIG_CHANGE_GET(x)\
FIELD_GET(ANA_AC_SG_ACCESS_CTRL_CONFIG_CHANGE, x)
-/* ANA_AC:SG_ACCESS:SG_CYCLETIME_UPDATE_PERIOD */
-#define ANA_AC_SG_CYCLETIME_UPDATE_PERIOD __REG(TARGET_ANA_AC,\
- 0, 1, 839140, 0, 1, 12, 8, 0, 1, 4)
+/* ANA_AC:SG_ACCESS:SG_CYCLETIME_UPDATE_PERIOD */
+#define ANA_AC_SG_CYCLETIME_UPDATE_PERIOD \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_ACCESS], 0, 1, 12, \
+ 8, 0, 1, 4)
#define ANA_AC_SG_CYCLETIME_UPDATE_PERIOD_SG_CT_CLKS GENMASK(15, 0)
#define ANA_AC_SG_CYCLETIME_UPDATE_PERIOD_SG_CT_CLKS_SET(x)\
@@ -303,17 +345,20 @@ enum sparx5_target {
#define ANA_AC_SG_CYCLETIME_UPDATE_PERIOD_SG_CT_UPDATE_ENA_GET(x)\
FIELD_GET(ANA_AC_SG_CYCLETIME_UPDATE_PERIOD_SG_CT_UPDATE_ENA, x)
-/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_1 */
-#define ANA_AC_SG_CONFIG_REG_1 __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 48, 0, 1, 4)
+/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_1 */
+#define ANA_AC_SG_CONFIG_REG_1 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 48, 0, 1, 4)
-/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_2 */
-#define ANA_AC_SG_CONFIG_REG_2 __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 52, 0, 1, 4)
+/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_2 */
+#define ANA_AC_SG_CONFIG_REG_2 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 52, 0, 1, 4)
-/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_3 */
-#define ANA_AC_SG_CONFIG_REG_3 __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 56, 0, 1, 4)
+/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_3 */
+#define ANA_AC_SG_CONFIG_REG_3 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 56, 0, 1, 4)
#define ANA_AC_SG_CONFIG_REG_3_BASE_TIME_SEC_MSB GENMASK(15, 0)
#define ANA_AC_SG_CONFIG_REG_3_BASE_TIME_SEC_MSB_SET(x)\
@@ -369,17 +414,20 @@ enum sparx5_target {
#define ANA_AC_SG_CONFIG_REG_3_OCTETS_EXCEEDED_GET(x)\
FIELD_GET(ANA_AC_SG_CONFIG_REG_3_OCTETS_EXCEEDED, x)
-/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_4 */
-#define ANA_AC_SG_CONFIG_REG_4 __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 60, 0, 1, 4)
+/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_4 */
+#define ANA_AC_SG_CONFIG_REG_4 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 60, 0, 1, 4)
-/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_5 */
-#define ANA_AC_SG_CONFIG_REG_5 __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 64, 0, 1, 4)
+/* ANA_AC:SG_CONFIG:SG_CONFIG_REG_5 */
+#define ANA_AC_SG_CONFIG_REG_5 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 64, 0, 1, 4)
-/* ANA_AC:SG_CONFIG:SG_GCL_GS_CONFIG */
-#define ANA_AC_SG_GCL_GS_CONFIG(r) __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 0, r, 4, 4)
+/* ANA_AC:SG_CONFIG:SG_GCL_GS_CONFIG */
+#define ANA_AC_SG_GCL_GS_CONFIG(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 0, r, 4, 4)
#define ANA_AC_SG_GCL_GS_CONFIG_IPS GENMASK(3, 0)
#define ANA_AC_SG_GCL_GS_CONFIG_IPS_SET(x)\
@@ -393,25 +441,30 @@ enum sparx5_target {
#define ANA_AC_SG_GCL_GS_CONFIG_GATE_STATE_GET(x)\
FIELD_GET(ANA_AC_SG_GCL_GS_CONFIG_GATE_STATE, x)
-/* ANA_AC:SG_CONFIG:SG_GCL_TI_CONFIG */
-#define ANA_AC_SG_GCL_TI_CONFIG(r) __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 16, r, 4, 4)
+/* ANA_AC:SG_CONFIG:SG_GCL_TI_CONFIG */
+#define ANA_AC_SG_GCL_TI_CONFIG(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 16, r, 4, 4)
-/* ANA_AC:SG_CONFIG:SG_GCL_OCT_CONFIG */
-#define ANA_AC_SG_GCL_OCT_CONFIG(r) __REG(TARGET_ANA_AC,\
- 0, 1, 851584, 0, 1, 128, 32, r, 4, 4)
+/* ANA_AC:SG_CONFIG:SG_GCL_OCT_CONFIG */
+#define ANA_AC_SG_GCL_OCT_CONFIG(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_CONFIG], 0, 1, 128,\
+ 32, r, 4, 4)
-/* ANA_AC:SG_STATUS:SG_STATUS_REG_1 */
-#define ANA_AC_SG_STATUS_REG_1 __REG(TARGET_ANA_AC,\
- 0, 1, 839088, 0, 1, 16, 0, 0, 1, 4)
+/* ANA_AC:SG_STATUS:SG_STATUS_REG_1 */
+#define ANA_AC_SG_STATUS_REG_1 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_STATUS], 0, 1, 16, \
+ 0, 0, 1, 4)
-/* ANA_AC:SG_STATUS:SG_STATUS_REG_2 */
-#define ANA_AC_SG_STATUS_REG_2 __REG(TARGET_ANA_AC,\
- 0, 1, 839088, 0, 1, 16, 4, 0, 1, 4)
+/* ANA_AC:SG_STATUS:SG_STATUS_REG_2 */
+#define ANA_AC_SG_STATUS_REG_2 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_STATUS], 0, 1, 16, \
+ 4, 0, 1, 4)
-/* ANA_AC:SG_STATUS:SG_STATUS_REG_3 */
-#define ANA_AC_SG_STATUS_REG_3 __REG(TARGET_ANA_AC,\
- 0, 1, 839088, 0, 1, 16, 8, 0, 1, 4)
+/* ANA_AC:SG_STATUS:SG_STATUS_REG_3 */
+#define ANA_AC_SG_STATUS_REG_3 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_STATUS], 0, 1, 16, \
+ 8, 0, 1, 4)
#define ANA_AC_SG_STATUS_REG_3_CFG_CHG_TIME_SEC_MSB GENMASK(15, 0)
#define ANA_AC_SG_STATUS_REG_3_CFG_CHG_TIME_SEC_MSB_SET(x)\
@@ -443,23 +496,27 @@ enum sparx5_target {
#define ANA_AC_SG_STATUS_REG_3_GCL_OCTET_INDEX_GET(x)\
FIELD_GET(ANA_AC_SG_STATUS_REG_3_GCL_OCTET_INDEX, x)
-/* ANA_AC:SG_STATUS:SG_STATUS_REG_4 */
-#define ANA_AC_SG_STATUS_REG_4 __REG(TARGET_ANA_AC,\
- 0, 1, 839088, 0, 1, 16, 12, 0, 1, 4)
+/* ANA_AC:SG_STATUS:SG_STATUS_REG_4 */
+#define ANA_AC_SG_STATUS_REG_4 \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_SG_STATUS], 0, 1, 16, \
+ 12, 0, 1, 4)
-/* ANA_AC:STAT_GLOBAL_CFG_PORT:STAT_GLOBAL_EVENT_MASK */
-#define ANA_AC_PORT_SGE_CFG(r) __REG(TARGET_ANA_AC,\
- 0, 1, 851552, 0, 1, 20, 0, r, 4, 4)
+/* ANA_AC:STAT_GLOBAL_CFG_PORT:STAT_GLOBAL_EVENT_MASK */
+#define ANA_AC_PORT_SGE_CFG(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_STAT_GLOBAL_CFG_PORT],\
+ 0, 1, 20, 0, r, 4, 4)
-#define ANA_AC_PORT_SGE_CFG_MASK GENMASK(15, 0)
+#define ANA_AC_PORT_SGE_CFG_MASK\
+ GENMASK(regs->fsize[FW_ANA_AC_PORT_SGE_CFG_MASK] + 0 - 1, 0)
#define ANA_AC_PORT_SGE_CFG_MASK_SET(x)\
- FIELD_PREP(ANA_AC_PORT_SGE_CFG_MASK, x)
+ spx5_field_prep(ANA_AC_PORT_SGE_CFG_MASK, x)
#define ANA_AC_PORT_SGE_CFG_MASK_GET(x)\
- FIELD_GET(ANA_AC_PORT_SGE_CFG_MASK, x)
+ spx5_field_get(ANA_AC_PORT_SGE_CFG_MASK, x)
-/* ANA_AC:STAT_GLOBAL_CFG_PORT:STAT_RESET */
-#define ANA_AC_STAT_RESET __REG(TARGET_ANA_AC,\
- 0, 1, 851552, 0, 1, 20, 16, 0, 1, 4)
+/* ANA_AC:STAT_GLOBAL_CFG_PORT:STAT_RESET */
+#define ANA_AC_STAT_RESET \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_STAT_GLOBAL_CFG_PORT],\
+ 0, 1, 20, 16, 0, 1, 4)
#define ANA_AC_STAT_RESET_RESET BIT(0)
#define ANA_AC_STAT_RESET_RESET_SET(x)\
@@ -467,9 +524,10 @@ enum sparx5_target {
#define ANA_AC_STAT_RESET_RESET_GET(x)\
FIELD_GET(ANA_AC_STAT_RESET_RESET, x)
-/* ANA_AC:STAT_CNT_CFG_PORT:STAT_CFG */
-#define ANA_AC_PORT_STAT_CFG(g, r) __REG(TARGET_ANA_AC,\
- 0, 1, 843776, g, 70, 64, 4, r, 4, 4)
+/* ANA_AC:STAT_CNT_CFG_PORT:STAT_CFG */
+#define ANA_AC_PORT_STAT_CFG(g, r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_STAT_CNT_CFG_PORT], g,\
+ regs->gcnt[GC_ANA_AC_STAT_CNT_CFG_PORT], 64, 4, r, 4, 4)
#define ANA_AC_PORT_STAT_CFG_CFG_PRIO_MASK GENMASK(11, 4)
#define ANA_AC_PORT_STAT_CFG_CFG_PRIO_MASK_SET(x)\
@@ -489,13 +547,15 @@ enum sparx5_target {
#define ANA_AC_PORT_STAT_CFG_CFG_CNT_BYTE_GET(x)\
FIELD_GET(ANA_AC_PORT_STAT_CFG_CFG_CNT_BYTE, x)
-/* ANA_AC:STAT_CNT_CFG_PORT:STAT_LSB_CNT */
-#define ANA_AC_PORT_STAT_LSB_CNT(g, r) __REG(TARGET_ANA_AC,\
- 0, 1, 843776, g, 70, 64, 20, r, 4, 4)
+/* ANA_AC:STAT_CNT_CFG_PORT:STAT_LSB_CNT */
+#define ANA_AC_PORT_STAT_LSB_CNT(g, r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_STAT_CNT_CFG_PORT], g,\
+ regs->gcnt[GC_ANA_AC_STAT_CNT_CFG_PORT], 64, 20, r, 4, 4)
-/* ANA_AC:STAT_GLOBAL_CFG_ACL:GLOBAL_CNT_FRM_TYPE_CFG */
-#define ANA_AC_ACL_GLOBAL_CNT_FRM_TYPE_CFG(r) __REG(TARGET_ANA_AC,\
- 0, 1, 893792, 0, 1, 24, 0, r, 2, 4)
+/* ANA_AC:STAT_GLOBAL_CFG_ACL:GLOBAL_CNT_FRM_TYPE_CFG */
+#define ANA_AC_ACL_GLOBAL_CNT_FRM_TYPE_CFG(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_STAT_GLOBAL_CFG_ACL], \
+ 0, 1, 24, 0, r, 2, 4)
#define ANA_AC_ACL_GLOBAL_CNT_FRM_TYPE_CFG_GLOBAL_CFG_CNT_FRM_TYPE GENMASK(2, 0)
#define ANA_AC_ACL_GLOBAL_CNT_FRM_TYPE_CFG_GLOBAL_CFG_CNT_FRM_TYPE_SET(x)\
@@ -503,9 +563,10 @@ enum sparx5_target {
#define ANA_AC_ACL_GLOBAL_CNT_FRM_TYPE_CFG_GLOBAL_CFG_CNT_FRM_TYPE_GET(x)\
FIELD_GET(ANA_AC_ACL_GLOBAL_CNT_FRM_TYPE_CFG_GLOBAL_CFG_CNT_FRM_TYPE, x)
-/* ANA_AC:STAT_GLOBAL_CFG_ACL:STAT_GLOBAL_CFG */
-#define ANA_AC_ACL_STAT_GLOBAL_CFG(r) __REG(TARGET_ANA_AC,\
- 0, 1, 893792, 0, 1, 24, 8, r, 2, 4)
+/* ANA_AC:STAT_GLOBAL_CFG_ACL:STAT_GLOBAL_CFG */
+#define ANA_AC_ACL_STAT_GLOBAL_CFG(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_STAT_GLOBAL_CFG_ACL], \
+ 0, 1, 24, 8, r, 2, 4)
#define ANA_AC_ACL_STAT_GLOBAL_CFG_GLOBAL_CFG_CNT_BYTE BIT(0)
#define ANA_AC_ACL_STAT_GLOBAL_CFG_GLOBAL_CFG_CNT_BYTE_SET(x)\
@@ -513,9 +574,10 @@ enum sparx5_target {
#define ANA_AC_ACL_STAT_GLOBAL_CFG_GLOBAL_CFG_CNT_BYTE_GET(x)\
FIELD_GET(ANA_AC_ACL_STAT_GLOBAL_CFG_GLOBAL_CFG_CNT_BYTE, x)
-/* ANA_AC:STAT_GLOBAL_CFG_ACL:STAT_GLOBAL_EVENT_MASK */
-#define ANA_AC_ACL_STAT_GLOBAL_EVENT_MASK(r) __REG(TARGET_ANA_AC,\
- 0, 1, 893792, 0, 1, 24, 16, r, 2, 4)
+/* ANA_AC:STAT_GLOBAL_CFG_ACL:STAT_GLOBAL_EVENT_MASK */
+#define ANA_AC_ACL_STAT_GLOBAL_EVENT_MASK(r) \
+ __REG(TARGET_ANA_AC, 0, 1, regs->gaddr[GA_ANA_AC_STAT_GLOBAL_CFG_ACL], \
+ 0, 1, 24, 16, r, 2, 4)
#define ANA_AC_ACL_STAT_GLOBAL_EVENT_MASK_GLOBAL_EVENT_MASK GENMASK(3, 0)
#define ANA_AC_ACL_STAT_GLOBAL_EVENT_MASK_GLOBAL_EVENT_MASK_SET(x)\
@@ -523,9 +585,10 @@ enum sparx5_target {
#define ANA_AC_ACL_STAT_GLOBAL_EVENT_MASK_GLOBAL_EVENT_MASK_GET(x)\
FIELD_GET(ANA_AC_ACL_STAT_GLOBAL_EVENT_MASK_GLOBAL_EVENT_MASK, x)
-/* ANA_ACL:COMMON:VCAP_S2_CFG */
-#define ANA_ACL_VCAP_S2_CFG(r) __REG(TARGET_ANA_ACL,\
- 0, 1, 32768, 0, 1, 592, 0, r, 70, 4)
+/* ANA_ACL:COMMON:VCAP_S2_CFG */
+#define ANA_ACL_VCAP_S2_CFG(r) \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_COMMON], 0, 1, 592, \
+ 0, r, regs->rcnt[RC_ANA_ACL_VCAP_S2_CFG], 4)
#define ANA_ACL_VCAP_S2_CFG_SEC_ROUTE_HANDLING_ENA BIT(28)
#define ANA_ACL_VCAP_S2_CFG_SEC_ROUTE_HANDLING_ENA_SET(x)\
@@ -611,9 +674,10 @@ enum sparx5_target {
#define ANA_ACL_VCAP_S2_CFG_SEC_ENA_GET(x)\
FIELD_GET(ANA_ACL_VCAP_S2_CFG_SEC_ENA, x)
-/* ANA_ACL:COMMON:SWAP_IP_CTRL */
-#define ANA_ACL_SWAP_IP_CTRL __REG(TARGET_ANA_ACL,\
- 0, 1, 32768, 0, 1, 592, 412, 0, 1, 4)
+/* ANA_ACL:COMMON:SWAP_IP_CTRL */
+#define ANA_ACL_SWAP_IP_CTRL \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_COMMON], 0, 1, 592, \
+ 412, 0, 1, 4)
#define ANA_ACL_SWAP_IP_CTRL_DMAC_REPL_OFFSET_VAL GENMASK(23, 18)
#define ANA_ACL_SWAP_IP_CTRL_DMAC_REPL_OFFSET_VAL_SET(x)\
@@ -645,9 +709,10 @@ enum sparx5_target {
#define ANA_ACL_SWAP_IP_CTRL_IP_SWAP_IP4_TTL_ENA_GET(x)\
FIELD_GET(ANA_ACL_SWAP_IP_CTRL_IP_SWAP_IP4_TTL_ENA, x)
-/* ANA_ACL:COMMON:VCAP_S2_RLEG_STAT */
-#define ANA_ACL_VCAP_S2_RLEG_STAT(r) __REG(TARGET_ANA_ACL,\
- 0, 1, 32768, 0, 1, 592, 424, r, 4, 4)
+/* ANA_ACL:COMMON:VCAP_S2_RLEG_STAT */
+#define ANA_ACL_VCAP_S2_RLEG_STAT(r) \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_COMMON], 0, 1, 592, \
+ 424, r, 4, 4)
#define ANA_ACL_VCAP_S2_RLEG_STAT_IRLEG_STAT_MASK GENMASK(12, 6)
#define ANA_ACL_VCAP_S2_RLEG_STAT_IRLEG_STAT_MASK_SET(x)\
@@ -661,9 +726,10 @@ enum sparx5_target {
#define ANA_ACL_VCAP_S2_RLEG_STAT_ERLEG_STAT_MASK_GET(x)\
FIELD_GET(ANA_ACL_VCAP_S2_RLEG_STAT_ERLEG_STAT_MASK, x)
-/* ANA_ACL:COMMON:VCAP_S2_FRAGMENT_CFG */
-#define ANA_ACL_VCAP_S2_FRAGMENT_CFG __REG(TARGET_ANA_ACL,\
- 0, 1, 32768, 0, 1, 592, 440, 0, 1, 4)
+/* ANA_ACL:COMMON:VCAP_S2_FRAGMENT_CFG */
+#define ANA_ACL_VCAP_S2_FRAGMENT_CFG \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_COMMON], 0, 1, 592, \
+ 440, 0, 1, 4)
#define ANA_ACL_VCAP_S2_FRAGMENT_CFG_L4_MIN_LEN GENMASK(9, 5)
#define ANA_ACL_VCAP_S2_FRAGMENT_CFG_L4_MIN_LEN_SET(x)\
@@ -683,9 +749,10 @@ enum sparx5_target {
#define ANA_ACL_VCAP_S2_FRAGMENT_CFG_FRAGMENT_OFFSET_THRES_GET(x)\
FIELD_GET(ANA_ACL_VCAP_S2_FRAGMENT_CFG_FRAGMENT_OFFSET_THRES, x)
-/* ANA_ACL:COMMON:OWN_UPSID */
-#define ANA_ACL_OWN_UPSID(r) __REG(TARGET_ANA_ACL,\
- 0, 1, 32768, 0, 1, 592, 580, r, 3, 4)
+/* ANA_ACL:COMMON:OWN_UPSID */
+#define ANA_ACL_OWN_UPSID(r) \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_COMMON], 0, 1, 592, \
+ 580, r, regs->rcnt[RC_ANA_ACL_OWN_UPSID], 4)
#define ANA_ACL_OWN_UPSID_OWN_UPSID GENMASK(4, 0)
#define ANA_ACL_OWN_UPSID_OWN_UPSID_SET(x)\
@@ -693,9 +760,10 @@ enum sparx5_target {
#define ANA_ACL_OWN_UPSID_OWN_UPSID_GET(x)\
FIELD_GET(ANA_ACL_OWN_UPSID_OWN_UPSID, x)
-/* ANA_ACL:KEY_SEL:VCAP_S2_KEY_SEL */
-#define ANA_ACL_VCAP_S2_KEY_SEL(g, r) __REG(TARGET_ANA_ACL,\
- 0, 1, 34200, g, 134, 16, 0, r, 4, 4)
+/* ANA_ACL:KEY_SEL:VCAP_S2_KEY_SEL */
+#define ANA_ACL_VCAP_S2_KEY_SEL(g, r) \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_KEY_SEL], g, \
+ regs->gcnt[GC_ANA_ACL_KEY_SEL], 16, 0, r, 4, 4)
#define ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA BIT(13)
#define ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(x)\
@@ -745,17 +813,20 @@ enum sparx5_target {
#define ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(x)\
FIELD_GET(ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL, x)
-/* ANA_ACL:CNT_A:CNT_A */
-#define ANA_ACL_CNT_A(g) __REG(TARGET_ANA_ACL,\
- 0, 1, 0, g, 4096, 4, 0, 0, 1, 4)
+/* ANA_ACL:CNT_A:CNT_A */
+#define ANA_ACL_CNT_A(g) \
+ __REG(TARGET_ANA_ACL, 0, 1, 0, g, regs->gcnt[GC_ANA_ACL_CNT_A], 4, 0, \
+ 0, 1, 4)
-/* ANA_ACL:CNT_B:CNT_B */
-#define ANA_ACL_CNT_B(g) __REG(TARGET_ANA_ACL,\
- 0, 1, 16384, g, 4096, 4, 0, 0, 1, 4)
+/* ANA_ACL:CNT_B:CNT_B */
+#define ANA_ACL_CNT_B(g) \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_CNT_B], g, \
+ regs->gcnt[GC_ANA_ACL_CNT_B], 4, 0, 0, 1, 4)
-/* ANA_ACL:STICKY:SEC_LOOKUP_STICKY */
-#define ANA_ACL_SEC_LOOKUP_STICKY(r) __REG(TARGET_ANA_ACL,\
- 0, 1, 36408, 0, 1, 16, 0, r, 4, 4)
+/* ANA_ACL:STICKY:SEC_LOOKUP_STICKY */
+#define ANA_ACL_SEC_LOOKUP_STICKY(r) \
+ __REG(TARGET_ANA_ACL, 0, 1, regs->gaddr[GA_ANA_ACL_STICKY], 0, 1, 16, \
+ 0, r, 4, 4)
#define ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_CLM_STICKY BIT(17)
#define ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_CLM_STICKY_SET(x)\
@@ -865,9 +936,10 @@ enum sparx5_target {
#define ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY_GET(x)\
FIELD_GET(ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY, x)
-/* ANA_AC_POL:POL_ALL_CFG:POL_UPD_INT_CFG */
-#define ANA_AC_POL_POL_UPD_INT_CFG __REG(TARGET_ANA_AC_POL,\
- 0, 1, 75968, 0, 1, 1160, 1148, 0, 1, 4)
+/* ANA_AC_POL:POL_ALL_CFG:POL_UPD_INT_CFG */
+#define ANA_AC_POL_POL_UPD_INT_CFG \
+ __REG(TARGET_ANA_AC_POL, 0, 1, regs->gaddr[GA_ANA_AC_POL_POL_ALL_CFG], \
+ 0, 1, 1160, 1148, 0, 1, 4)
#define ANA_AC_POL_POL_UPD_INT_CFG_POL_UPD_INT GENMASK(9, 0)
#define ANA_AC_POL_POL_UPD_INT_CFG_POL_UPD_INT_SET(x)\
@@ -875,9 +947,10 @@ enum sparx5_target {
#define ANA_AC_POL_POL_UPD_INT_CFG_POL_UPD_INT_GET(x)\
FIELD_GET(ANA_AC_POL_POL_UPD_INT_CFG_POL_UPD_INT, x)
-/* ANA_AC_POL:COMMON_BDLB:DLB_CTRL */
-#define ANA_AC_POL_BDLB_DLB_CTRL __REG(TARGET_ANA_AC_POL,\
- 0, 1, 79048, 0, 1, 8, 0, 0, 1, 4)
+/* ANA_AC_POL:COMMON_BDLB:DLB_CTRL */
+#define ANA_AC_POL_BDLB_DLB_CTRL \
+ __REG(TARGET_ANA_AC_POL, 0, 1, regs->gaddr[GA_ANA_AC_POL_COMMON_BDLB], \
+ 0, 1, 8, 0, 0, 1, 4)
#define ANA_AC_POL_BDLB_DLB_CTRL_CLK_PERIOD_01NS GENMASK(26, 19)
#define ANA_AC_POL_BDLB_DLB_CTRL_CLK_PERIOD_01NS_SET(x)\
@@ -903,9 +976,10 @@ enum sparx5_target {
#define ANA_AC_POL_BDLB_DLB_CTRL_DLB_ADD_ENA_GET(x)\
FIELD_GET(ANA_AC_POL_BDLB_DLB_CTRL_DLB_ADD_ENA, x)
-/* ANA_AC_POL:COMMON_BUM_SLB:DLB_CTRL */
-#define ANA_AC_POL_SLB_DLB_CTRL __REG(TARGET_ANA_AC_POL,\
- 0, 1, 79056, 0, 1, 20, 0, 0, 1, 4)
+/* ANA_AC_POL:COMMON_BUM_SLB:DLB_CTRL */
+#define ANA_AC_POL_SLB_DLB_CTRL \
+ __REG(TARGET_ANA_AC_POL, 0, 1, \
+ regs->gaddr[GA_ANA_AC_POL_COMMON_BUM_SLB], 0, 1, 20, 0, 0, 1, 4)
#define ANA_AC_POL_SLB_DLB_CTRL_CLK_PERIOD_01NS GENMASK(26, 19)
#define ANA_AC_POL_SLB_DLB_CTRL_CLK_PERIOD_01NS_SET(x)\
@@ -931,19 +1005,22 @@ enum sparx5_target {
#define ANA_AC_POL_SLB_DLB_CTRL_DLB_ADD_ENA_GET(x)\
FIELD_GET(ANA_AC_POL_SLB_DLB_CTRL_DLB_ADD_ENA, x)
-/* ANA_AC_SDLB:LBGRP_TBL:XLB_START */
-#define ANA_AC_SDLB_XLB_START(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 295468, g, 10, 24, 0, 0, 1, 4)
+/* ANA_AC_SDLB:LBGRP_TBL:XLB_START */
+#define ANA_AC_SDLB_XLB_START(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, regs->gaddr[GA_ANA_AC_SDLB_LBGRP_TBL], \
+ g, regs->gcnt[GC_ANA_AC_SDLB_LBGRP_TBL], 24, 0, 0, 1, 4)
-#define ANA_AC_SDLB_XLB_START_LBSET_START GENMASK(12, 0)
+#define ANA_AC_SDLB_XLB_START_LBSET_START\
+ GENMASK(regs->fsize[FW_ANA_AC_SDLB_XLB_START_LBSET_START] + 0 - 1, 0)
#define ANA_AC_SDLB_XLB_START_LBSET_START_SET(x)\
- FIELD_PREP(ANA_AC_SDLB_XLB_START_LBSET_START, x)
+ spx5_field_prep(ANA_AC_SDLB_XLB_START_LBSET_START, x)
#define ANA_AC_SDLB_XLB_START_LBSET_START_GET(x)\
- FIELD_GET(ANA_AC_SDLB_XLB_START_LBSET_START, x)
+ spx5_field_get(ANA_AC_SDLB_XLB_START_LBSET_START, x)
-/* ANA_AC_SDLB:LBGRP_TBL:PUP_INTERVAL */
-#define ANA_AC_SDLB_PUP_INTERVAL(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 295468, g, 10, 24, 4, 0, 1, 4)
+/* ANA_AC_SDLB:LBGRP_TBL:PUP_INTERVAL */
+#define ANA_AC_SDLB_PUP_INTERVAL(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, regs->gaddr[GA_ANA_AC_SDLB_LBGRP_TBL], \
+ g, regs->gcnt[GC_ANA_AC_SDLB_LBGRP_TBL], 24, 4, 0, 1, 4)
#define ANA_AC_SDLB_PUP_INTERVAL_PUP_INTERVAL GENMASK(19, 0)
#define ANA_AC_SDLB_PUP_INTERVAL_PUP_INTERVAL_SET(x)\
@@ -951,9 +1028,10 @@ enum sparx5_target {
#define ANA_AC_SDLB_PUP_INTERVAL_PUP_INTERVAL_GET(x)\
FIELD_GET(ANA_AC_SDLB_PUP_INTERVAL_PUP_INTERVAL, x)
-/* ANA_AC_SDLB:LBGRP_TBL:PUP_CTRL */
-#define ANA_AC_SDLB_PUP_CTRL(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 295468, g, 10, 24, 8, 0, 1, 4)
+/* ANA_AC_SDLB:LBGRP_TBL:PUP_CTRL */
+#define ANA_AC_SDLB_PUP_CTRL(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, regs->gaddr[GA_ANA_AC_SDLB_LBGRP_TBL], \
+ g, regs->gcnt[GC_ANA_AC_SDLB_LBGRP_TBL], 24, 8, 0, 1, 4)
#define ANA_AC_SDLB_PUP_CTRL_PUP_LB_DT GENMASK(18, 0)
#define ANA_AC_SDLB_PUP_CTRL_PUP_LB_DT_SET(x)\
@@ -967,19 +1045,22 @@ enum sparx5_target {
#define ANA_AC_SDLB_PUP_CTRL_PUP_ENA_GET(x)\
FIELD_GET(ANA_AC_SDLB_PUP_CTRL_PUP_ENA, x)
-/* ANA_AC_SDLB:LBGRP_TBL:LBGRP_MISC */
-#define ANA_AC_SDLB_LBGRP_MISC(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 295468, g, 10, 24, 12, 0, 1, 4)
+/* ANA_AC_SDLB:LBGRP_TBL:LBGRP_MISC */
+#define ANA_AC_SDLB_LBGRP_MISC(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, regs->gaddr[GA_ANA_AC_SDLB_LBGRP_TBL], \
+ g, regs->gcnt[GC_ANA_AC_SDLB_LBGRP_TBL], 24, 12, 0, 1, 4)
-#define ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT GENMASK(12, 8)
+#define ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT\
+ GENMASK(regs->fsize[FW_ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT] + 8 - 1, 8)
#define ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT_SET(x)\
- FIELD_PREP(ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT, x)
+ spx5_field_prep(ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT, x)
#define ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT_GET(x)\
- FIELD_GET(ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT, x)
+ spx5_field_get(ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT, x)
-/* ANA_AC_SDLB:LBGRP_TBL:FRM_RATE_TOKENS */
-#define ANA_AC_SDLB_FRM_RATE_TOKENS(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 295468, g, 10, 24, 16, 0, 1, 4)
+/* ANA_AC_SDLB:LBGRP_TBL:FRM_RATE_TOKENS */
+#define ANA_AC_SDLB_FRM_RATE_TOKENS(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, regs->gaddr[GA_ANA_AC_SDLB_LBGRP_TBL], \
+ g, regs->gcnt[GC_ANA_AC_SDLB_LBGRP_TBL], 24, 16, 0, 1, 4)
#define ANA_AC_SDLB_FRM_RATE_TOKENS_FRM_RATE_TOKENS GENMASK(12, 0)
#define ANA_AC_SDLB_FRM_RATE_TOKENS_FRM_RATE_TOKENS_SET(x)\
@@ -987,9 +1068,10 @@ enum sparx5_target {
#define ANA_AC_SDLB_FRM_RATE_TOKENS_FRM_RATE_TOKENS_GET(x)\
FIELD_GET(ANA_AC_SDLB_FRM_RATE_TOKENS_FRM_RATE_TOKENS, x)
-/* ANA_AC_SDLB:LBGRP_TBL:LBGRP_STATE_TBL */
-#define ANA_AC_SDLB_LBGRP_STATE_TBL(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 295468, g, 10, 24, 20, 0, 1, 4)
+/* ANA_AC_SDLB:LBGRP_TBL:LBGRP_STATE_TBL */
+#define ANA_AC_SDLB_LBGRP_STATE_TBL(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, regs->gaddr[GA_ANA_AC_SDLB_LBGRP_TBL], \
+ g, regs->gcnt[GC_ANA_AC_SDLB_LBGRP_TBL], 24, 20, 0, 1, 4)
#define ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_ONGOING BIT(0)
#define ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_ONGOING_SET(x)\
@@ -1003,15 +1085,17 @@ enum sparx5_target {
#define ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_WAIT_ACK_GET(x)\
FIELD_GET(ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_WAIT_ACK, x)
-#define ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT GENMASK(28, 16)
+#define ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT\
+ GENMASK(regs->fsize[FW_ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT] + 16 - 1, 16)
#define ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT_SET(x)\
- FIELD_PREP(ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT, x)
+ spx5_field_prep(ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT, x)
#define ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT_GET(x)\
- FIELD_GET(ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT, x)
+ spx5_field_get(ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT, x)
-/* ANA_AC_SDLB:LBSET_TBL:PUP_TOKENS */
-#define ANA_AC_SDLB_PUP_TOKENS(g, r) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 0, g, 4616, 64, 0, r, 2, 4)
+/* ANA_AC_SDLB:LBSET_TBL:PUP_TOKENS */
+#define ANA_AC_SDLB_PUP_TOKENS(g, r) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, 0, g, \
+ regs->gcnt[GC_ANA_AC_SDLB_LBSET_TBL], 64, 0, r, 2, 4)
#define ANA_AC_SDLB_PUP_TOKENS_PUP_TOKENS GENMASK(12, 0)
#define ANA_AC_SDLB_PUP_TOKENS_PUP_TOKENS_SET(x)\
@@ -1019,9 +1103,10 @@ enum sparx5_target {
#define ANA_AC_SDLB_PUP_TOKENS_PUP_TOKENS_GET(x)\
FIELD_GET(ANA_AC_SDLB_PUP_TOKENS_PUP_TOKENS, x)
-/* ANA_AC_SDLB:LBSET_TBL:THRES */
-#define ANA_AC_SDLB_THRES(g, r) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 0, g, 4616, 64, 8, r, 2, 4)
+/* ANA_AC_SDLB:LBSET_TBL:THRES */
+#define ANA_AC_SDLB_THRES(g, r) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, 0, g, \
+ regs->gcnt[GC_ANA_AC_SDLB_LBSET_TBL], 64, 8, r, 2, 4)
#define ANA_AC_SDLB_THRES_THRES GENMASK(9, 0)
#define ANA_AC_SDLB_THRES_THRES_SET(x)\
@@ -1035,25 +1120,29 @@ enum sparx5_target {
#define ANA_AC_SDLB_THRES_THRES_HYS_GET(x)\
FIELD_GET(ANA_AC_SDLB_THRES_THRES_HYS, x)
-/* ANA_AC_SDLB:LBSET_TBL:XLB_NEXT */
-#define ANA_AC_SDLB_XLB_NEXT(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 0, g, 4616, 64, 16, 0, 1, 4)
+/* ANA_AC_SDLB:LBSET_TBL:XLB_NEXT */
+#define ANA_AC_SDLB_XLB_NEXT(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, 0, g, \
+ regs->gcnt[GC_ANA_AC_SDLB_LBSET_TBL], 64, 16, 0, 1, 4)
-#define ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT GENMASK(12, 0)
+#define ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT\
+ GENMASK(regs->fsize[FW_ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT] + 0 - 1, 0)
#define ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT_SET(x)\
- FIELD_PREP(ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT, x)
+ spx5_field_prep(ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT, x)
#define ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT_GET(x)\
- FIELD_GET(ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT, x)
+ spx5_field_get(ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT, x)
-#define ANA_AC_SDLB_XLB_NEXT_LBGRP GENMASK(27, 24)
+#define ANA_AC_SDLB_XLB_NEXT_LBGRP\
+ GENMASK(regs->fsize[FW_ANA_AC_SDLB_XLB_NEXT_LBGRP] + 24 - 1, 24)
#define ANA_AC_SDLB_XLB_NEXT_LBGRP_SET(x)\
- FIELD_PREP(ANA_AC_SDLB_XLB_NEXT_LBGRP, x)
+ spx5_field_prep(ANA_AC_SDLB_XLB_NEXT_LBGRP, x)
#define ANA_AC_SDLB_XLB_NEXT_LBGRP_GET(x)\
- FIELD_GET(ANA_AC_SDLB_XLB_NEXT_LBGRP, x)
+ spx5_field_get(ANA_AC_SDLB_XLB_NEXT_LBGRP, x)
-/* ANA_AC_SDLB:LBSET_TBL:INH_CTRL */
-#define ANA_AC_SDLB_INH_CTRL(g, r) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 0, g, 4616, 64, 20, r, 2, 4)
+/* ANA_AC_SDLB:LBSET_TBL:INH_CTRL */
+#define ANA_AC_SDLB_INH_CTRL(g, r) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, 0, g, \
+ regs->gcnt[GC_ANA_AC_SDLB_LBSET_TBL], 64, 20, r, 2, 4)
#define ANA_AC_SDLB_INH_CTRL_PUP_TOKENS_MAX GENMASK(12, 0)
#define ANA_AC_SDLB_INH_CTRL_PUP_TOKENS_MAX_SET(x)\
@@ -1073,19 +1162,22 @@ enum sparx5_target {
#define ANA_AC_SDLB_INH_CTRL_INH_LB_GET(x)\
FIELD_GET(ANA_AC_SDLB_INH_CTRL_INH_LB, x)
-/* ANA_AC_SDLB:LBSET_TBL:INH_LBSET_ADDR */
-#define ANA_AC_SDLB_INH_LBSET_ADDR(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 0, g, 4616, 64, 28, 0, 1, 4)
+/* ANA_AC_SDLB:LBSET_TBL:INH_LBSET_ADDR */
+#define ANA_AC_SDLB_INH_LBSET_ADDR(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, 0, g, \
+ regs->gcnt[GC_ANA_AC_SDLB_LBSET_TBL], 64, 28, 0, 1, 4)
-#define ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR GENMASK(12, 0)
+#define ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR\
+ GENMASK(regs->fsize[FW_ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR] + 0 - 1, 0)
#define ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR_SET(x)\
- FIELD_PREP(ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR, x)
+ spx5_field_prep(ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR, x)
#define ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR_GET(x)\
- FIELD_GET(ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR, x)
+ spx5_field_get(ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR, x)
-/* ANA_AC_SDLB:LBSET_TBL:DLB_MISC */
-#define ANA_AC_SDLB_DLB_MISC(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 0, g, 4616, 64, 32, 0, 1, 4)
+/* ANA_AC_SDLB:LBSET_TBL:DLB_MISC */
+#define ANA_AC_SDLB_DLB_MISC(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, 0, g, \
+ regs->gcnt[GC_ANA_AC_SDLB_LBSET_TBL], 64, 32, 0, 1, 4)
#define ANA_AC_SDLB_DLB_MISC_DLB_FRM_RATE_ENA BIT(0)
#define ANA_AC_SDLB_DLB_MISC_DLB_FRM_RATE_ENA_SET(x)\
@@ -1105,9 +1197,10 @@ enum sparx5_target {
#define ANA_AC_SDLB_DLB_MISC_DLB_FRM_ADJ_GET(x)\
FIELD_GET(ANA_AC_SDLB_DLB_MISC_DLB_FRM_ADJ, x)
-/* ANA_AC_SDLB:LBSET_TBL:DLB_CFG */
-#define ANA_AC_SDLB_DLB_CFG(g) __REG(TARGET_ANA_AC_SDLB,\
- 0, 1, 0, g, 4616, 64, 36, 0, 1, 4)
+/* ANA_AC_SDLB:LBSET_TBL:DLB_CFG */
+#define ANA_AC_SDLB_DLB_CFG(g) \
+ __REG(TARGET_ANA_AC_SDLB, 0, 1, 0, g, \
+ regs->gcnt[GC_ANA_AC_SDLB_LBSET_TBL], 64, 36, 0, 1, 4)
#define ANA_AC_SDLB_DLB_CFG_DROP_ON_YELLOW_ENA BIT(11)
#define ANA_AC_SDLB_DLB_CFG_DROP_ON_YELLOW_ENA_SET(x)\
@@ -1157,9 +1250,10 @@ enum sparx5_target {
#define ANA_AC_SDLB_DLB_CFG_TRAFFIC_TYPE_MASK_GET(x)\
FIELD_GET(ANA_AC_SDLB_DLB_CFG_TRAFFIC_TYPE_MASK, x)
-/* ANA_CL:PORT:FILTER_CTRL */
-#define ANA_CL_FILTER_CTRL(g) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 4, 0, 1, 4)
+/* ANA_CL:PORT:FILTER_CTRL */
+#define ANA_CL_FILTER_CTRL(g) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 4, 0, 1, 4)
#define ANA_CL_FILTER_CTRL_FILTER_SMAC_MC_DIS BIT(2)
#define ANA_CL_FILTER_CTRL_FILTER_SMAC_MC_DIS_SET(x)\
@@ -1179,9 +1273,10 @@ enum sparx5_target {
#define ANA_CL_FILTER_CTRL_FORCE_FCS_UPDATE_ENA_GET(x)\
FIELD_GET(ANA_CL_FILTER_CTRL_FORCE_FCS_UPDATE_ENA, x)
-/* ANA_CL:PORT:VLAN_FILTER_CTRL */
-#define ANA_CL_VLAN_FILTER_CTRL(g, r) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 8, r, 3, 4)
+/* ANA_CL:PORT:VLAN_FILTER_CTRL */
+#define ANA_CL_VLAN_FILTER_CTRL(g, r) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 8, r, 3, 4)
#define ANA_CL_VLAN_FILTER_CTRL_TAG_REQUIRED_ENA BIT(10)
#define ANA_CL_VLAN_FILTER_CTRL_TAG_REQUIRED_ENA_SET(x)\
@@ -1249,9 +1344,10 @@ enum sparx5_target {
#define ANA_CL_VLAN_FILTER_CTRL_CUST3_STAG_DIS_GET(x)\
FIELD_GET(ANA_CL_VLAN_FILTER_CTRL_CUST3_STAG_DIS, x)
-/* ANA_CL:PORT:ETAG_FILTER_CTRL */
-#define ANA_CL_ETAG_FILTER_CTRL(g) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 20, 0, 1, 4)
+/* ANA_CL:PORT:ETAG_FILTER_CTRL */
+#define ANA_CL_ETAG_FILTER_CTRL(g) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 20, 0, 1, 4)
#define ANA_CL_ETAG_FILTER_CTRL_ETAG_REQUIRED_ENA BIT(1)
#define ANA_CL_ETAG_FILTER_CTRL_ETAG_REQUIRED_ENA_SET(x)\
@@ -1265,9 +1361,10 @@ enum sparx5_target {
#define ANA_CL_ETAG_FILTER_CTRL_ETAG_DIS_GET(x)\
FIELD_GET(ANA_CL_ETAG_FILTER_CTRL_ETAG_DIS, x)
-/* ANA_CL:PORT:VLAN_CTRL */
-#define ANA_CL_VLAN_CTRL(g) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 32, 0, 1, 4)
+/* ANA_CL:PORT:VLAN_CTRL */
+#define ANA_CL_VLAN_CTRL(g) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 32, 0, 1, 4)
#define ANA_CL_VLAN_CTRL_PORT_VOE_TPID_AWARE_DIS GENMASK(30, 26)
#define ANA_CL_VLAN_CTRL_PORT_VOE_TPID_AWARE_DIS_SET(x)\
@@ -1335,9 +1432,10 @@ enum sparx5_target {
#define ANA_CL_VLAN_CTRL_PORT_VID_GET(x)\
FIELD_GET(ANA_CL_VLAN_CTRL_PORT_VID, x)
-/* ANA_CL:PORT:VLAN_CTRL_2 */
-#define ANA_CL_VLAN_CTRL_2(g) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 36, 0, 1, 4)
+/* ANA_CL:PORT:VLAN_CTRL_2 */
+#define ANA_CL_VLAN_CTRL_2(g) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 36, 0, 1, 4)
#define ANA_CL_VLAN_CTRL_2_VLAN_PUSH_CNT GENMASK(1, 0)
#define ANA_CL_VLAN_CTRL_2_VLAN_PUSH_CNT_SET(x)\
@@ -1345,9 +1443,10 @@ enum sparx5_target {
#define ANA_CL_VLAN_CTRL_2_VLAN_PUSH_CNT_GET(x)\
FIELD_GET(ANA_CL_VLAN_CTRL_2_VLAN_PUSH_CNT, x)
-/* ANA_CL:PORT:PCP_DEI_MAP_CFG */
-#define ANA_CL_PCP_DEI_MAP_CFG(g, r) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 108, r, 16, 4)
+/* ANA_CL:PORT:PCP_DEI_MAP_CFG */
+#define ANA_CL_PCP_DEI_MAP_CFG(g, r) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 108, r, 16, 4)
#define ANA_CL_PCP_DEI_MAP_CFG_PCP_DEI_DP_VAL GENMASK(4, 3)
#define ANA_CL_PCP_DEI_MAP_CFG_PCP_DEI_DP_VAL_SET(x)\
@@ -1361,9 +1460,10 @@ enum sparx5_target {
#define ANA_CL_PCP_DEI_MAP_CFG_PCP_DEI_QOS_VAL_GET(x)\
FIELD_GET(ANA_CL_PCP_DEI_MAP_CFG_PCP_DEI_QOS_VAL, x)
-/* ANA_CL:PORT:QOS_CFG */
-#define ANA_CL_QOS_CFG(g) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 172, 0, 1, 4)
+/* ANA_CL:PORT:QOS_CFG */
+#define ANA_CL_QOS_CFG(g) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 172, 0, 1, 4)
#define ANA_CL_QOS_CFG_DEFAULT_COSID_ENA BIT(17)
#define ANA_CL_QOS_CFG_DEFAULT_COSID_ENA_SET(x)\
@@ -1437,13 +1537,15 @@ enum sparx5_target {
#define ANA_CL_QOS_CFG_DEFAULT_QOS_VAL_GET(x)\
FIELD_GET(ANA_CL_QOS_CFG_DEFAULT_QOS_VAL, x)
-/* ANA_CL:PORT:CAPTURE_BPDU_CFG */
-#define ANA_CL_CAPTURE_BPDU_CFG(g) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 196, 0, 1, 4)
+/* ANA_CL:PORT:CAPTURE_BPDU_CFG */
+#define ANA_CL_CAPTURE_BPDU_CFG(g) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 196, 0, 1, 4)
-/* ANA_CL:PORT:ADV_CL_CFG_2 */
-#define ANA_CL_ADV_CL_CFG_2(g, r) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 200, r, 6, 4)
+/* ANA_CL:PORT:ADV_CL_CFG_2 */
+#define ANA_CL_ADV_CL_CFG_2(g, r) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 200, r, 6, 4)
#define ANA_CL_ADV_CL_CFG_2_USE_CL_TCI0_ENA BIT(1)
#define ANA_CL_ADV_CL_CFG_2_USE_CL_TCI0_ENA_SET(x)\
@@ -1457,9 +1559,10 @@ enum sparx5_target {
#define ANA_CL_ADV_CL_CFG_2_USE_CL_DSCP_ENA_GET(x)\
FIELD_GET(ANA_CL_ADV_CL_CFG_2_USE_CL_DSCP_ENA, x)
-/* ANA_CL:PORT:ADV_CL_CFG */
-#define ANA_CL_ADV_CL_CFG(g, r) __REG(TARGET_ANA_CL,\
- 0, 1, 131072, g, 70, 512, 224, r, 6, 4)
+/* ANA_CL:PORT:ADV_CL_CFG */
+#define ANA_CL_ADV_CL_CFG(g, r) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_PORT], g, \
+ regs->gcnt[GC_ANA_CL_PORT], 512, 224, r, 6, 4)
#define ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL GENMASK(30, 26)
#define ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(x)\
@@ -1503,9 +1606,10 @@ enum sparx5_target {
#define ANA_CL_ADV_CL_CFG_LOOKUP_ENA_GET(x)\
FIELD_GET(ANA_CL_ADV_CL_CFG_LOOKUP_ENA, x)
-/* ANA_CL:COMMON:OWN_UPSID */
-#define ANA_CL_OWN_UPSID(r) __REG(TARGET_ANA_CL,\
- 0, 1, 166912, 0, 1, 756, 0, r, 3, 4)
+/* ANA_CL:COMMON:OWN_UPSID */
+#define ANA_CL_OWN_UPSID(r) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_COMMON], 0, 1, 756, 0,\
+ r, regs->rcnt[RC_ANA_CL_OWN_UPSID], 4)
#define ANA_CL_OWN_UPSID_OWN_UPSID GENMASK(4, 0)
#define ANA_CL_OWN_UPSID_OWN_UPSID_SET(x)\
@@ -1513,9 +1617,10 @@ enum sparx5_target {
#define ANA_CL_OWN_UPSID_OWN_UPSID_GET(x)\
FIELD_GET(ANA_CL_OWN_UPSID_OWN_UPSID, x)
-/* ANA_CL:COMMON:DSCP_CFG */
-#define ANA_CL_DSCP_CFG(r) __REG(TARGET_ANA_CL,\
- 0, 1, 166912, 0, 1, 756, 256, r, 64, 4)
+/* ANA_CL:COMMON:DSCP_CFG */
+#define ANA_CL_DSCP_CFG(r) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_COMMON], 0, 1, 756, \
+ 256, r, 64, 4)
#define ANA_CL_DSCP_CFG_DSCP_TRANSLATE_VAL GENMASK(12, 7)
#define ANA_CL_DSCP_CFG_DSCP_TRANSLATE_VAL_SET(x)\
@@ -1547,9 +1652,10 @@ enum sparx5_target {
#define ANA_CL_DSCP_CFG_DSCP_TRUST_ENA_GET(x)\
FIELD_GET(ANA_CL_DSCP_CFG_DSCP_TRUST_ENA, x)
-/* ANA_CL:COMMON:QOS_MAP_CFG */
-#define ANA_CL_QOS_MAP_CFG(r) __REG(TARGET_ANA_CL,\
- 0, 1, 166912, 0, 1, 756, 512, r, 32, 4)
+/* ANA_CL:COMMON:QOS_MAP_CFG */
+#define ANA_CL_QOS_MAP_CFG(r) \
+ __REG(TARGET_ANA_CL, 0, 1, regs->gaddr[GA_ANA_CL_COMMON], 0, 1, 756, \
+ 512, r, 32, 4)
#define ANA_CL_QOS_MAP_CFG_DSCP_REWR_VAL GENMASK(9, 4)
#define ANA_CL_QOS_MAP_CFG_DSCP_REWR_VAL_SET(x)\
@@ -1557,9 +1663,10 @@ enum sparx5_target {
#define ANA_CL_QOS_MAP_CFG_DSCP_REWR_VAL_GET(x)\
FIELD_GET(ANA_CL_QOS_MAP_CFG_DSCP_REWR_VAL, x)
-/* ANA_L2:COMMON:FWD_CFG */
-#define ANA_L2_FWD_CFG __REG(TARGET_ANA_L2,\
- 0, 1, 566024, 0, 1, 700, 0, 0, 1, 4)
+/* ANA_L2:COMMON:FWD_CFG */
+#define ANA_L2_FWD_CFG \
+ __REG(TARGET_ANA_L2, 0, 1, regs->gaddr[GA_ANA_L2_COMMON], 0, 1, \
+ regs->gsize[GW_ANA_L2_COMMON], 0, 0, 1, 4)
#define ANA_L2_FWD_CFG_MAC_TBL_SPLIT_SEL GENMASK(21, 20)
#define ANA_L2_FWD_CFG_MAC_TBL_SPLIT_SEL_SET(x)\
@@ -1633,17 +1740,22 @@ enum sparx5_target {
#define ANA_L2_FWD_CFG_FWD_ENA_GET(x)\
FIELD_GET(ANA_L2_FWD_CFG_FWD_ENA, x)
-/* ANA_L2:COMMON:AUTO_LRN_CFG */
-#define ANA_L2_AUTO_LRN_CFG __REG(TARGET_ANA_L2,\
- 0, 1, 566024, 0, 1, 700, 24, 0, 1, 4)
+/* ANA_L2:COMMON:AUTO_LRN_CFG */
+#define ANA_L2_AUTO_LRN_CFG \
+ __REG(TARGET_ANA_L2, 0, 1, regs->gaddr[GA_ANA_L2_COMMON], 0, 1, \
+ regs->gsize[GW_ANA_L2_COMMON], 24, 0, 1, 4)
-/* ANA_L2:COMMON:AUTO_LRN_CFG1 */
-#define ANA_L2_AUTO_LRN_CFG1 __REG(TARGET_ANA_L2,\
- 0, 1, 566024, 0, 1, 700, 28, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_L2:COMMON:AUTO_LRN_CFG1 */
+#define ANA_L2_AUTO_LRN_CFG1 \
+ __REG(TARGET_ANA_L2, 0, 1, regs->gaddr[GA_ANA_L2_COMMON], 0, 1, \
+ regs->gsize[GW_ANA_L2_COMMON], 28, 0, 1, 4)
-/* ANA_L2:COMMON:AUTO_LRN_CFG2 */
-#define ANA_L2_AUTO_LRN_CFG2 __REG(TARGET_ANA_L2,\
- 0, 1, 566024, 0, 1, 700, 32, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_L2:COMMON:AUTO_LRN_CFG2 */
+#define ANA_L2_AUTO_LRN_CFG2 \
+ __REG(TARGET_ANA_L2, 0, 1, regs->gaddr[GA_ANA_L2_COMMON], 0, 1, \
+ regs->gsize[GW_ANA_L2_COMMON], 32, 0, 1, 4)
#define ANA_L2_AUTO_LRN_CFG2_AUTO_LRN_ENA2 BIT(0)
#define ANA_L2_AUTO_LRN_CFG2_AUTO_LRN_ENA2_SET(x)\
@@ -1651,9 +1763,11 @@ enum sparx5_target {
#define ANA_L2_AUTO_LRN_CFG2_AUTO_LRN_ENA2_GET(x)\
FIELD_GET(ANA_L2_AUTO_LRN_CFG2_AUTO_LRN_ENA2, x)
-/* ANA_L2:COMMON:OWN_UPSID */
-#define ANA_L2_OWN_UPSID(r) __REG(TARGET_ANA_L2,\
- 0, 1, 566024, 0, 1, 700, 672, r, 3, 4)
+/* ANA_L2:COMMON:OWN_UPSID */
+#define ANA_L2_OWN_UPSID(r) \
+ __REG(TARGET_ANA_L2, 0, 1, regs->gaddr[GA_ANA_L2_COMMON], 0, 1, \
+ regs->gsize[GW_ANA_L2_COMMON], 672, r, \
+ regs->rcnt[RC_ANA_L2_OWN_UPSID], 4)
#define ANA_L2_OWN_UPSID_OWN_UPSID GENMASK(4, 0)
#define ANA_L2_OWN_UPSID_OWN_UPSID_SET(x)\
@@ -1661,29 +1775,34 @@ enum sparx5_target {
#define ANA_L2_OWN_UPSID_OWN_UPSID_GET(x)\
FIELD_GET(ANA_L2_OWN_UPSID_OWN_UPSID, x)
-/* ANA_L2:ISDX:DLB_CFG */
-#define ANA_L2_DLB_CFG(g) __REG(TARGET_ANA_L2,\
- 0, 1, 0, g, 4096, 128, 56, 0, 1, 4)
+/* ANA_L2:ISDX:DLB_CFG */
+#define ANA_L2_DLB_CFG(g) \
+ __REG(TARGET_ANA_L2, 0, 1, 0, g, regs->gcnt[GC_ANA_L2_ISDX], 128, 56, \
+ 0, 1, 4)
-#define ANA_L2_DLB_CFG_DLB_IDX GENMASK(12, 0)
+#define ANA_L2_DLB_CFG_DLB_IDX\
+ GENMASK(regs->fsize[FW_ANA_L2_DLB_CFG_DLB_IDX] + 0 - 1, 0)
#define ANA_L2_DLB_CFG_DLB_IDX_SET(x)\
- FIELD_PREP(ANA_L2_DLB_CFG_DLB_IDX, x)
+ spx5_field_prep(ANA_L2_DLB_CFG_DLB_IDX, x)
#define ANA_L2_DLB_CFG_DLB_IDX_GET(x)\
- FIELD_GET(ANA_L2_DLB_CFG_DLB_IDX, x)
+ spx5_field_get(ANA_L2_DLB_CFG_DLB_IDX, x)
-/* ANA_L2:ISDX:TSN_CFG */
-#define ANA_L2_TSN_CFG(g) __REG(TARGET_ANA_L2,\
- 0, 1, 0, g, 4096, 128, 100, 0, 1, 4)
+/* ANA_L2:ISDX:TSN_CFG */
+#define ANA_L2_TSN_CFG(g) \
+ __REG(TARGET_ANA_L2, 0, 1, 0, g, regs->gcnt[GC_ANA_L2_ISDX], 128, 100, \
+ 0, 1, 4)
-#define ANA_L2_TSN_CFG_TSN_SFID GENMASK(9, 0)
+#define ANA_L2_TSN_CFG_TSN_SFID\
+ GENMASK(regs->fsize[FW_ANA_L2_TSN_CFG_TSN_SFID] + 0 - 1, 0)
#define ANA_L2_TSN_CFG_TSN_SFID_SET(x)\
- FIELD_PREP(ANA_L2_TSN_CFG_TSN_SFID, x)
+ spx5_field_prep(ANA_L2_TSN_CFG_TSN_SFID, x)
#define ANA_L2_TSN_CFG_TSN_SFID_GET(x)\
- FIELD_GET(ANA_L2_TSN_CFG_TSN_SFID, x)
+ spx5_field_get(ANA_L2_TSN_CFG_TSN_SFID, x)
-/* ANA_L3:COMMON:VLAN_CTRL */
-#define ANA_L3_VLAN_CTRL __REG(TARGET_ANA_L3,\
- 0, 1, 493632, 0, 1, 184, 4, 0, 1, 4)
+/* ANA_L3:COMMON:VLAN_CTRL */
+#define ANA_L3_VLAN_CTRL \
+ __REG(TARGET_ANA_L3, 0, 1, regs->gaddr[GA_ANA_L3_COMMON], 0, 1, 184, 4,\
+ 0, 1, 4)
#define ANA_L3_VLAN_CTRL_VLAN_ENA BIT(0)
#define ANA_L3_VLAN_CTRL_VLAN_ENA_SET(x)\
@@ -1691,9 +1810,10 @@ enum sparx5_target {
#define ANA_L3_VLAN_CTRL_VLAN_ENA_GET(x)\
FIELD_GET(ANA_L3_VLAN_CTRL_VLAN_ENA, x)
-/* ANA_L3:VLAN:VLAN_CFG */
-#define ANA_L3_VLAN_CFG(g) __REG(TARGET_ANA_L3,\
- 0, 1, 0, g, 5120, 64, 8, 0, 1, 4)
+/* ANA_L3:VLAN:VLAN_CFG */
+#define ANA_L3_VLAN_CFG(g) \
+ __REG(TARGET_ANA_L3, 0, 1, 0, g, regs->gcnt[GC_ANA_L3_VLAN], 64, 8, 0, \
+ 1, 4)
#define ANA_L3_VLAN_CFG_VLAN_MSTP_PTR GENMASK(30, 24)
#define ANA_L3_VLAN_CFG_VLAN_MSTP_PTR_SET(x)\
@@ -1749,17 +1869,22 @@ enum sparx5_target {
#define ANA_L3_VLAN_CFG_VLAN_MIRROR_ENA_GET(x)\
FIELD_GET(ANA_L3_VLAN_CFG_VLAN_MIRROR_ENA, x)
-/* ANA_L3:VLAN:VLAN_MASK_CFG */
-#define ANA_L3_VLAN_MASK_CFG(g) __REG(TARGET_ANA_L3,\
- 0, 1, 0, g, 5120, 64, 16, 0, 1, 4)
+/* ANA_L3:VLAN:VLAN_MASK_CFG */
+#define ANA_L3_VLAN_MASK_CFG(g) \
+ __REG(TARGET_ANA_L3, 0, 1, 0, g, regs->gcnt[GC_ANA_L3_VLAN], 64, 16, 0,\
+ 1, 4)
-/* ANA_L3:VLAN:VLAN_MASK_CFG1 */
-#define ANA_L3_VLAN_MASK_CFG1(g) __REG(TARGET_ANA_L3,\
- 0, 1, 0, g, 5120, 64, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_L3:VLAN:VLAN_MASK_CFG1 */
+#define ANA_L3_VLAN_MASK_CFG1(g) \
+ __REG(TARGET_ANA_L3, 0, 1, 0, g, regs->gcnt[GC_ANA_L3_VLAN], 64, 20, 0,\
+ 1, 4)
-/* ANA_L3:VLAN:VLAN_MASK_CFG2 */
-#define ANA_L3_VLAN_MASK_CFG2(g) __REG(TARGET_ANA_L3,\
- 0, 1, 0, g, 5120, 64, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* ANA_L3:VLAN:VLAN_MASK_CFG2 */
+#define ANA_L3_VLAN_MASK_CFG2(g) \
+ __REG(TARGET_ANA_L3, 0, 1, 0, g, regs->gcnt[GC_ANA_L3_VLAN], 64, 24, 0,\
+ 1, 4)
#define ANA_L3_VLAN_MASK_CFG2_VLAN_PORT_MASK2 BIT(0)
#define ANA_L3_VLAN_MASK_CFG2_VLAN_PORT_MASK2_SET(x)\
@@ -1767,365 +1892,455 @@ enum sparx5_target {
#define ANA_L3_VLAN_MASK_CFG2_VLAN_PORT_MASK2_GET(x)\
FIELD_GET(ANA_L3_VLAN_MASK_CFG2_VLAN_PORT_MASK2, x)
-/* ASM:DEV_STATISTICS:RX_IN_BYTES_CNT */
-#define ASM_RX_IN_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 0, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SYMBOL_ERR_CNT */
-#define ASM_RX_SYMBOL_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 4, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_PAUSE_CNT */
-#define ASM_RX_PAUSE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 8, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_UNSUP_OPCODE_CNT */
-#define ASM_RX_UNSUP_OPCODE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 12, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_OK_BYTES_CNT */
-#define ASM_RX_OK_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 16, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_BAD_BYTES_CNT */
-#define ASM_RX_BAD_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 20, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_UC_CNT */
-#define ASM_RX_UC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 24, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_MC_CNT */
-#define ASM_RX_MC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 28, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_BC_CNT */
-#define ASM_RX_BC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 32, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_CRC_ERR_CNT */
-#define ASM_RX_CRC_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 36, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_UNDERSIZE_CNT */
-#define ASM_RX_UNDERSIZE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 40, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_FRAGMENTS_CNT */
-#define ASM_RX_FRAGMENTS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 44, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_IN_RANGE_LEN_ERR_CNT */
-#define ASM_RX_IN_RANGE_LEN_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 48, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_OUT_OF_RANGE_LEN_ERR_CNT */
-#define ASM_RX_OUT_OF_RANGE_LEN_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 52, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_OVERSIZE_CNT */
-#define ASM_RX_OVERSIZE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 56, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_JABBERS_CNT */
-#define ASM_RX_JABBERS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 60, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SIZE64_CNT */
-#define ASM_RX_SIZE64_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 64, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SIZE65TO127_CNT */
-#define ASM_RX_SIZE65TO127_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 68, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SIZE128TO255_CNT */
-#define ASM_RX_SIZE128TO255_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 72, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SIZE256TO511_CNT */
-#define ASM_RX_SIZE256TO511_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 76, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SIZE512TO1023_CNT */
-#define ASM_RX_SIZE512TO1023_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 80, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SIZE1024TO1518_CNT */
-#define ASM_RX_SIZE1024TO1518_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 84, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_SIZE1519TOMAX_CNT */
-#define ASM_RX_SIZE1519TOMAX_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 88, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_IPG_SHRINK_CNT */
-#define ASM_RX_IPG_SHRINK_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 92, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_OUT_BYTES_CNT */
-#define ASM_TX_OUT_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 96, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_PAUSE_CNT */
-#define ASM_TX_PAUSE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 100, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_OK_BYTES_CNT */
-#define ASM_TX_OK_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 104, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_UC_CNT */
-#define ASM_TX_UC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 108, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_MC_CNT */
-#define ASM_TX_MC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 112, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_BC_CNT */
-#define ASM_TX_BC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 116, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_SIZE64_CNT */
-#define ASM_TX_SIZE64_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 120, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_SIZE65TO127_CNT */
-#define ASM_TX_SIZE65TO127_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 124, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_SIZE128TO255_CNT */
-#define ASM_TX_SIZE128TO255_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 128, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_SIZE256TO511_CNT */
-#define ASM_TX_SIZE256TO511_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 132, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_SIZE512TO1023_CNT */
-#define ASM_TX_SIZE512TO1023_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 136, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_SIZE1024TO1518_CNT */
-#define ASM_TX_SIZE1024TO1518_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 140, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_SIZE1519TOMAX_CNT */
-#define ASM_TX_SIZE1519TOMAX_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 144, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_ALIGNMENT_LOST_CNT */
-#define ASM_RX_ALIGNMENT_LOST_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 148, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_TAGGED_FRMS_CNT */
-#define ASM_RX_TAGGED_FRMS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 152, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_UNTAGGED_FRMS_CNT */
-#define ASM_RX_UNTAGGED_FRMS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 156, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_TAGGED_FRMS_CNT */
-#define ASM_TX_TAGGED_FRMS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 160, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_UNTAGGED_FRMS_CNT */
-#define ASM_TX_UNTAGGED_FRMS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 164, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SYMBOL_ERR_CNT */
-#define ASM_PMAC_RX_SYMBOL_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 168, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_PAUSE_CNT */
-#define ASM_PMAC_RX_PAUSE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 172, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_UNSUP_OPCODE_CNT */
-#define ASM_PMAC_RX_UNSUP_OPCODE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 176, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_OK_BYTES_CNT */
-#define ASM_PMAC_RX_OK_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 180, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_BAD_BYTES_CNT */
-#define ASM_PMAC_RX_BAD_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 184, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_UC_CNT */
-#define ASM_PMAC_RX_UC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 188, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_MC_CNT */
-#define ASM_PMAC_RX_MC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 192, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_BC_CNT */
-#define ASM_PMAC_RX_BC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 196, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_CRC_ERR_CNT */
-#define ASM_PMAC_RX_CRC_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 200, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_UNDERSIZE_CNT */
-#define ASM_PMAC_RX_UNDERSIZE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 204, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_FRAGMENTS_CNT */
-#define ASM_PMAC_RX_FRAGMENTS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 208, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_IN_RANGE_LEN_ERR_CNT */
-#define ASM_PMAC_RX_IN_RANGE_LEN_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 212, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT */
-#define ASM_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 216, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_OVERSIZE_CNT */
-#define ASM_PMAC_RX_OVERSIZE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 220, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_JABBERS_CNT */
-#define ASM_PMAC_RX_JABBERS_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 224, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SIZE64_CNT */
-#define ASM_PMAC_RX_SIZE64_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 228, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SIZE65TO127_CNT */
-#define ASM_PMAC_RX_SIZE65TO127_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 232, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SIZE128TO255_CNT */
-#define ASM_PMAC_RX_SIZE128TO255_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 236, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SIZE256TO511_CNT */
-#define ASM_PMAC_RX_SIZE256TO511_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 240, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SIZE512TO1023_CNT */
-#define ASM_PMAC_RX_SIZE512TO1023_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 244, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SIZE1024TO1518_CNT */
-#define ASM_PMAC_RX_SIZE1024TO1518_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 248, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_SIZE1519TOMAX_CNT */
-#define ASM_PMAC_RX_SIZE1519TOMAX_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 252, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_PAUSE_CNT */
-#define ASM_PMAC_TX_PAUSE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 256, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_OK_BYTES_CNT */
-#define ASM_PMAC_TX_OK_BYTES_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 260, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_UC_CNT */
-#define ASM_PMAC_TX_UC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 264, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_MC_CNT */
-#define ASM_PMAC_TX_MC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 268, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_BC_CNT */
-#define ASM_PMAC_TX_BC_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 272, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_SIZE64_CNT */
-#define ASM_PMAC_TX_SIZE64_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 276, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_SIZE65TO127_CNT */
-#define ASM_PMAC_TX_SIZE65TO127_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 280, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_SIZE128TO255_CNT */
-#define ASM_PMAC_TX_SIZE128TO255_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 284, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_SIZE256TO511_CNT */
-#define ASM_PMAC_TX_SIZE256TO511_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 288, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_SIZE512TO1023_CNT */
-#define ASM_PMAC_TX_SIZE512TO1023_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 292, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_SIZE1024TO1518_CNT */
-#define ASM_PMAC_TX_SIZE1024TO1518_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 296, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_TX_SIZE1519TOMAX_CNT */
-#define ASM_PMAC_TX_SIZE1519TOMAX_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 300, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:PMAC_RX_ALIGNMENT_LOST_CNT */
-#define ASM_PMAC_RX_ALIGNMENT_LOST_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 304, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:MM_RX_ASSEMBLY_ERR_CNT */
-#define ASM_MM_RX_ASSEMBLY_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 308, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:MM_RX_SMD_ERR_CNT */
-#define ASM_MM_RX_SMD_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 312, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:MM_RX_ASSEMBLY_OK_CNT */
-#define ASM_MM_RX_ASSEMBLY_OK_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 316, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:MM_RX_MERGE_FRAG_CNT */
-#define ASM_MM_RX_MERGE_FRAG_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 320, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:MM_TX_PFRAGMENT_CNT */
-#define ASM_MM_TX_PFRAGMENT_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 324, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_MULTI_COLL_CNT */
-#define ASM_TX_MULTI_COLL_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 328, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_LATE_COLL_CNT */
-#define ASM_TX_LATE_COLL_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 332, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_XCOLL_CNT */
-#define ASM_TX_XCOLL_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 336, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_DEFER_CNT */
-#define ASM_TX_DEFER_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 340, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_XDEFER_CNT */
-#define ASM_TX_XDEFER_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 344, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_BACKOFF1_CNT */
-#define ASM_TX_BACKOFF1_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 348, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:TX_CSENSE_CNT */
-#define ASM_TX_CSENSE_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 352, 0, 1, 4)
-
-/* ASM:DEV_STATISTICS:RX_IN_BYTES_MSB_CNT */
-#define ASM_RX_IN_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 356, 0, 1, 4)
+/* ASM:DEV_STATISTICS:RX_IN_BYTES_CNT */
+#define ASM_RX_IN_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 0, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SYMBOL_ERR_CNT */
+#define ASM_RX_SYMBOL_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 4, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_PAUSE_CNT */
+#define ASM_RX_PAUSE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 8, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_UNSUP_OPCODE_CNT */
+#define ASM_RX_UNSUP_OPCODE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 12, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_OK_BYTES_CNT */
+#define ASM_RX_OK_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 16, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_BAD_BYTES_CNT */
+#define ASM_RX_BAD_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 20, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_UC_CNT */
+#define ASM_RX_UC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 24, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_MC_CNT */
+#define ASM_RX_MC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 28, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_BC_CNT */
+#define ASM_RX_BC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 32, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_CRC_ERR_CNT */
+#define ASM_RX_CRC_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 36, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_UNDERSIZE_CNT */
+#define ASM_RX_UNDERSIZE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 40, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_FRAGMENTS_CNT */
+#define ASM_RX_FRAGMENTS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 44, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_IN_RANGE_LEN_ERR_CNT */
+#define ASM_RX_IN_RANGE_LEN_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 48, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_OUT_OF_RANGE_LEN_ERR_CNT */
+#define ASM_RX_OUT_OF_RANGE_LEN_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 52, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_OVERSIZE_CNT */
+#define ASM_RX_OVERSIZE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 56, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_JABBERS_CNT */
+#define ASM_RX_JABBERS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 60, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SIZE64_CNT */
+#define ASM_RX_SIZE64_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 64, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SIZE65TO127_CNT */
+#define ASM_RX_SIZE65TO127_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 68, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SIZE128TO255_CNT */
+#define ASM_RX_SIZE128TO255_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 72, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SIZE256TO511_CNT */
+#define ASM_RX_SIZE256TO511_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 76, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SIZE512TO1023_CNT */
+#define ASM_RX_SIZE512TO1023_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 80, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SIZE1024TO1518_CNT */
+#define ASM_RX_SIZE1024TO1518_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 84, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_SIZE1519TOMAX_CNT */
+#define ASM_RX_SIZE1519TOMAX_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 88, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_IPG_SHRINK_CNT */
+#define ASM_RX_IPG_SHRINK_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 92, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_OUT_BYTES_CNT */
+#define ASM_TX_OUT_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 96, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_PAUSE_CNT */
+#define ASM_TX_PAUSE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 100, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_OK_BYTES_CNT */
+#define ASM_TX_OK_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 104, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_UC_CNT */
+#define ASM_TX_UC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 108, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_MC_CNT */
+#define ASM_TX_MC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 112, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_BC_CNT */
+#define ASM_TX_BC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 116, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_SIZE64_CNT */
+#define ASM_TX_SIZE64_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 120, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_SIZE65TO127_CNT */
+#define ASM_TX_SIZE65TO127_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 124, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_SIZE128TO255_CNT */
+#define ASM_TX_SIZE128TO255_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 128, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_SIZE256TO511_CNT */
+#define ASM_TX_SIZE256TO511_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 132, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_SIZE512TO1023_CNT */
+#define ASM_TX_SIZE512TO1023_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 136, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_SIZE1024TO1518_CNT */
+#define ASM_TX_SIZE1024TO1518_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 140, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_SIZE1519TOMAX_CNT */
+#define ASM_TX_SIZE1519TOMAX_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 144, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_ALIGNMENT_LOST_CNT */
+#define ASM_RX_ALIGNMENT_LOST_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 148, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_TAGGED_FRMS_CNT */
+#define ASM_RX_TAGGED_FRMS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 152, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_UNTAGGED_FRMS_CNT */
+#define ASM_RX_UNTAGGED_FRMS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 156, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_TAGGED_FRMS_CNT */
+#define ASM_TX_TAGGED_FRMS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 160, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_UNTAGGED_FRMS_CNT */
+#define ASM_TX_UNTAGGED_FRMS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 164, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SYMBOL_ERR_CNT */
+#define ASM_PMAC_RX_SYMBOL_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 168, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_PAUSE_CNT */
+#define ASM_PMAC_RX_PAUSE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 172, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_UNSUP_OPCODE_CNT */
+#define ASM_PMAC_RX_UNSUP_OPCODE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 176, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_OK_BYTES_CNT */
+#define ASM_PMAC_RX_OK_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 180, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_BAD_BYTES_CNT */
+#define ASM_PMAC_RX_BAD_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 184, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_UC_CNT */
+#define ASM_PMAC_RX_UC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 188, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_MC_CNT */
+#define ASM_PMAC_RX_MC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 192, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_BC_CNT */
+#define ASM_PMAC_RX_BC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 196, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_CRC_ERR_CNT */
+#define ASM_PMAC_RX_CRC_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 200, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_UNDERSIZE_CNT */
+#define ASM_PMAC_RX_UNDERSIZE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 204, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_FRAGMENTS_CNT */
+#define ASM_PMAC_RX_FRAGMENTS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 208, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_IN_RANGE_LEN_ERR_CNT */
+#define ASM_PMAC_RX_IN_RANGE_LEN_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 212, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT */
+#define ASM_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 216, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_OVERSIZE_CNT */
+#define ASM_PMAC_RX_OVERSIZE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 220, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_JABBERS_CNT */
+#define ASM_PMAC_RX_JABBERS_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 224, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SIZE64_CNT */
+#define ASM_PMAC_RX_SIZE64_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 228, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SIZE65TO127_CNT */
+#define ASM_PMAC_RX_SIZE65TO127_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 232, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SIZE128TO255_CNT */
+#define ASM_PMAC_RX_SIZE128TO255_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 236, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SIZE256TO511_CNT */
+#define ASM_PMAC_RX_SIZE256TO511_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 240, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SIZE512TO1023_CNT */
+#define ASM_PMAC_RX_SIZE512TO1023_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 244, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SIZE1024TO1518_CNT */
+#define ASM_PMAC_RX_SIZE1024TO1518_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 248, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_SIZE1519TOMAX_CNT */
+#define ASM_PMAC_RX_SIZE1519TOMAX_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 252, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_PAUSE_CNT */
+#define ASM_PMAC_TX_PAUSE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 256, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_OK_BYTES_CNT */
+#define ASM_PMAC_TX_OK_BYTES_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 260, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_UC_CNT */
+#define ASM_PMAC_TX_UC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 264, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_MC_CNT */
+#define ASM_PMAC_TX_MC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 268, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_BC_CNT */
+#define ASM_PMAC_TX_BC_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 272, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_SIZE64_CNT */
+#define ASM_PMAC_TX_SIZE64_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 276, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_SIZE65TO127_CNT */
+#define ASM_PMAC_TX_SIZE65TO127_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 280, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_SIZE128TO255_CNT */
+#define ASM_PMAC_TX_SIZE128TO255_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 284, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_SIZE256TO511_CNT */
+#define ASM_PMAC_TX_SIZE256TO511_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 288, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_SIZE512TO1023_CNT */
+#define ASM_PMAC_TX_SIZE512TO1023_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 292, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_SIZE1024TO1518_CNT */
+#define ASM_PMAC_TX_SIZE1024TO1518_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 296, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_TX_SIZE1519TOMAX_CNT */
+#define ASM_PMAC_TX_SIZE1519TOMAX_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 300, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:PMAC_RX_ALIGNMENT_LOST_CNT */
+#define ASM_PMAC_RX_ALIGNMENT_LOST_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 304, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:MM_RX_ASSEMBLY_ERR_CNT */
+#define ASM_MM_RX_ASSEMBLY_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 308, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:MM_RX_SMD_ERR_CNT */
+#define ASM_MM_RX_SMD_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 312, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:MM_RX_ASSEMBLY_OK_CNT */
+#define ASM_MM_RX_ASSEMBLY_OK_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 316, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:MM_RX_MERGE_FRAG_CNT */
+#define ASM_MM_RX_MERGE_FRAG_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 320, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:MM_TX_PFRAGMENT_CNT */
+#define ASM_MM_TX_PFRAGMENT_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 324, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_MULTI_COLL_CNT */
+#define ASM_TX_MULTI_COLL_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 328, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_LATE_COLL_CNT */
+#define ASM_TX_LATE_COLL_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 332, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_XCOLL_CNT */
+#define ASM_TX_XCOLL_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 336, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_DEFER_CNT */
+#define ASM_TX_DEFER_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 340, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_XDEFER_CNT */
+#define ASM_TX_XDEFER_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 344, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_BACKOFF1_CNT */
+#define ASM_TX_BACKOFF1_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 348, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:TX_CSENSE_CNT */
+#define ASM_TX_CSENSE_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 352, 0, 1, 4)
+
+/* ASM:DEV_STATISTICS:RX_IN_BYTES_MSB_CNT */
+#define ASM_RX_IN_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 356, 0, 1, 4)
#define ASM_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT_SET(x)\
@@ -2133,9 +2348,10 @@ enum sparx5_target {
#define ASM_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:RX_OK_BYTES_MSB_CNT */
-#define ASM_RX_OK_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 360, 0, 1, 4)
+/* ASM:DEV_STATISTICS:RX_OK_BYTES_MSB_CNT */
+#define ASM_RX_OK_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 360, 0, 1, 4)
#define ASM_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT_SET(x)\
@@ -2143,9 +2359,10 @@ enum sparx5_target {
#define ASM_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:PMAC_RX_OK_BYTES_MSB_CNT */
-#define ASM_PMAC_RX_OK_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 364, 0, 1, 4)
+/* ASM:DEV_STATISTICS:PMAC_RX_OK_BYTES_MSB_CNT */
+#define ASM_PMAC_RX_OK_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 364, 0, 1, 4)
#define ASM_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT_SET(x)\
@@ -2153,9 +2370,10 @@ enum sparx5_target {
#define ASM_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:RX_BAD_BYTES_MSB_CNT */
-#define ASM_RX_BAD_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 368, 0, 1, 4)
+/* ASM:DEV_STATISTICS:RX_BAD_BYTES_MSB_CNT */
+#define ASM_RX_BAD_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 368, 0, 1, 4)
#define ASM_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT_SET(x)\
@@ -2163,9 +2381,10 @@ enum sparx5_target {
#define ASM_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:PMAC_RX_BAD_BYTES_MSB_CNT */
-#define ASM_PMAC_RX_BAD_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 372, 0, 1, 4)
+/* ASM:DEV_STATISTICS:PMAC_RX_BAD_BYTES_MSB_CNT */
+#define ASM_PMAC_RX_BAD_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 372, 0, 1, 4)
#define ASM_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT_SET(x)\
@@ -2173,9 +2392,10 @@ enum sparx5_target {
#define ASM_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:TX_OUT_BYTES_MSB_CNT */
-#define ASM_TX_OUT_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 376, 0, 1, 4)
+/* ASM:DEV_STATISTICS:TX_OUT_BYTES_MSB_CNT */
+#define ASM_TX_OUT_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 376, 0, 1, 4)
#define ASM_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT_SET(x)\
@@ -2183,9 +2403,10 @@ enum sparx5_target {
#define ASM_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:TX_OK_BYTES_MSB_CNT */
-#define ASM_TX_OK_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 380, 0, 1, 4)
+/* ASM:DEV_STATISTICS:TX_OK_BYTES_MSB_CNT */
+#define ASM_TX_OK_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 380, 0, 1, 4)
#define ASM_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT_SET(x)\
@@ -2193,9 +2414,10 @@ enum sparx5_target {
#define ASM_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:PMAC_TX_OK_BYTES_MSB_CNT */
-#define ASM_PMAC_TX_OK_BYTES_MSB_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 384, 0, 1, 4)
+/* ASM:DEV_STATISTICS:PMAC_TX_OK_BYTES_MSB_CNT */
+#define ASM_PMAC_TX_OK_BYTES_MSB_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 384, 0, 1, 4)
#define ASM_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT GENMASK(3, 0)
#define ASM_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT_SET(x)\
@@ -2203,13 +2425,15 @@ enum sparx5_target {
#define ASM_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(ASM_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT, x)
-/* ASM:DEV_STATISTICS:RX_SYNC_LOST_ERR_CNT */
-#define ASM_RX_SYNC_LOST_ERR_CNT(g) __REG(TARGET_ASM,\
- 0, 1, 0, g, 65, 512, 388, 0, 1, 4)
+/* ASM:DEV_STATISTICS:RX_SYNC_LOST_ERR_CNT */
+#define ASM_RX_SYNC_LOST_ERR_CNT(g) \
+ __REG(TARGET_ASM, 0, 1, 0, g, regs->gcnt[GC_ASM_DEV_STATISTICS], 512, \
+ 388, 0, 1, 4)
-/* ASM:CFG:STAT_CFG */
-#define ASM_STAT_CFG __REG(TARGET_ASM,\
- 0, 1, 33280, 0, 1, 1088, 0, 0, 1, 4)
+/* ASM:CFG:STAT_CFG */
+#define ASM_STAT_CFG \
+ __REG(TARGET_ASM, 0, 1, regs->gaddr[GA_ASM_CFG], 0, 1, \
+ regs->gsize[GW_ASM_CFG], 0, 0, 1, 4)
#define ASM_STAT_CFG_STAT_CNT_CLR_SHOT BIT(0)
#define ASM_STAT_CFG_STAT_CNT_CLR_SHOT_SET(x)\
@@ -2217,9 +2441,10 @@ enum sparx5_target {
#define ASM_STAT_CFG_STAT_CNT_CLR_SHOT_GET(x)\
FIELD_GET(ASM_STAT_CFG_STAT_CNT_CLR_SHOT, x)
-/* ASM:CFG:PORT_CFG */
-#define ASM_PORT_CFG(r) __REG(TARGET_ASM,\
- 0, 1, 33280, 0, 1, 1088, 540, r, 67, 4)
+/* ASM:CFG:PORT_CFG */
+#define ASM_PORT_CFG(r) \
+ __REG(TARGET_ASM, 0, 1, regs->gaddr[GA_ASM_CFG], 0, 1, \
+ regs->gsize[GW_ASM_CFG], 540, r, regs->rcnt[RC_ASM_PORT_CFG], 4)
#define ASM_PORT_CFG_CSC_STAT_DIS BIT(12)
#define ASM_PORT_CFG_CSC_STAT_DIS_SET(x)\
@@ -2287,9 +2512,10 @@ enum sparx5_target {
#define ASM_PORT_CFG_PFRM_FLUSH_GET(x)\
FIELD_GET(ASM_PORT_CFG_PFRM_FLUSH, x)
-/* ASM:RAM_CTRL:RAM_INIT */
-#define ASM_RAM_INIT __REG(TARGET_ASM,\
- 0, 1, 34832, 0, 1, 4, 0, 0, 1, 4)
+/* ASM:RAM_CTRL:RAM_INIT */
+#define ASM_RAM_INIT \
+ __REG(TARGET_ASM, 0, 1, regs->gaddr[GA_ASM_RAM_CTRL], 0, 1, 4, 0, 0, 1,\
+ 4)
#define ASM_RAM_INIT_RAM_INIT BIT(1)
#define ASM_RAM_INIT_RAM_INIT_SET(x)\
@@ -2303,9 +2529,10 @@ enum sparx5_target {
#define ASM_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(ASM_RAM_INIT_RAM_CFG_HOOK, x)
-/* CLKGEN:LCPLL1:LCPLL1_CORE_CLK_CFG */
-#define CLKGEN_LCPLL1_CORE_CLK_CFG __REG(TARGET_CLKGEN,\
- 0, 1, 12, 0, 1, 36, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* CLKGEN:LCPLL1:LCPLL1_CORE_CLK_CFG */
+#define CLKGEN_LCPLL1_CORE_CLK_CFG \
+ __REG(TARGET_CLKGEN, 0, 1, 12, 0, 1, 36, 0, 0, 1, 4)
#define CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_DIV GENMASK(7, 0)
#define CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_DIV_SET(x)\
@@ -2343,91 +2570,144 @@ enum sparx5_target {
#define CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_ENA_GET(x)\
FIELD_GET(CLKGEN_LCPLL1_CORE_CLK_CFG_CORE_CLK_ENA, x)
-/* CPU:CPU_REGS:PROC_CTRL */
-#define CPU_PROC_CTRL __REG(TARGET_CPU,\
- 0, 1, 0, 0, 1, 204, 176, 0, 1, 4)
+/* CPU:CPU_REGS:PROC_CTRL */
+#define CPU_PROC_CTRL \
+ __REG(TARGET_CPU, 0, 1, 0, 0, 1, regs->gsize[GW_CPU_CPU_REGS], \
+ regs->raddr[RA_CPU_PROC_CTRL], 0, 1, 4)
-#define CPU_PROC_CTRL_AARCH64_MODE_ENA BIT(12)
+#define CPU_PROC_CTRL_AARCH64_MODE_ENA\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_AARCH64_MODE_ENA])
#define CPU_PROC_CTRL_AARCH64_MODE_ENA_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_AARCH64_MODE_ENA, x)
+ spx5_field_prep(CPU_PROC_CTRL_AARCH64_MODE_ENA, x)
#define CPU_PROC_CTRL_AARCH64_MODE_ENA_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_AARCH64_MODE_ENA, x)
+ spx5_field_get(CPU_PROC_CTRL_AARCH64_MODE_ENA, x)
-#define CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS BIT(11)
+#define CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS])
#define CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS, x)
+ spx5_field_prep(CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS, x)
#define CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS, x)
+ spx5_field_get(CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS, x)
-#define CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS BIT(10)
+#define CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS])
#define CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS, x)
+ spx5_field_prep(CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS, x)
#define CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS, x)
+ spx5_field_get(CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS, x)
-#define CPU_PROC_CTRL_BE_EXCEP_MODE BIT(9)
+#define CPU_PROC_CTRL_BE_EXCEP_MODE\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_BE_EXCEP_MODE])
#define CPU_PROC_CTRL_BE_EXCEP_MODE_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_BE_EXCEP_MODE, x)
+ spx5_field_prep(CPU_PROC_CTRL_BE_EXCEP_MODE, x)
#define CPU_PROC_CTRL_BE_EXCEP_MODE_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_BE_EXCEP_MODE, x)
+ spx5_field_get(CPU_PROC_CTRL_BE_EXCEP_MODE, x)
-#define CPU_PROC_CTRL_VINITHI BIT(8)
+#define CPU_PROC_CTRL_VINITHI\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_VINITHI])
#define CPU_PROC_CTRL_VINITHI_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_VINITHI, x)
+ spx5_field_prep(CPU_PROC_CTRL_VINITHI, x)
#define CPU_PROC_CTRL_VINITHI_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_VINITHI, x)
+ spx5_field_get(CPU_PROC_CTRL_VINITHI, x)
-#define CPU_PROC_CTRL_CFGTE BIT(7)
+#define CPU_PROC_CTRL_CFGTE\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_CFGTE])
#define CPU_PROC_CTRL_CFGTE_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_CFGTE, x)
+ spx5_field_prep(CPU_PROC_CTRL_CFGTE, x)
#define CPU_PROC_CTRL_CFGTE_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_CFGTE, x)
+ spx5_field_get(CPU_PROC_CTRL_CFGTE, x)
-#define CPU_PROC_CTRL_CP15S_DISABLE BIT(6)
+#define CPU_PROC_CTRL_CP15S_DISABLE\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_CP15S_DISABLE])
#define CPU_PROC_CTRL_CP15S_DISABLE_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_CP15S_DISABLE, x)
+ spx5_field_prep(CPU_PROC_CTRL_CP15S_DISABLE, x)
#define CPU_PROC_CTRL_CP15S_DISABLE_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_CP15S_DISABLE, x)
+ spx5_field_get(CPU_PROC_CTRL_CP15S_DISABLE, x)
-#define CPU_PROC_CTRL_PROC_CRYPTO_DISABLE BIT(5)
+#define CPU_PROC_CTRL_PROC_CRYPTO_DISABLE\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_PROC_CRYPTO_DISABLE])
#define CPU_PROC_CTRL_PROC_CRYPTO_DISABLE_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_PROC_CRYPTO_DISABLE, x)
+ spx5_field_prep(CPU_PROC_CTRL_PROC_CRYPTO_DISABLE, x)
#define CPU_PROC_CTRL_PROC_CRYPTO_DISABLE_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_PROC_CRYPTO_DISABLE, x)
+ spx5_field_get(CPU_PROC_CTRL_PROC_CRYPTO_DISABLE, x)
+/* SPARX5 ONLY */
#define CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA BIT(4)
#define CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA_SET(x)\
FIELD_PREP(CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA, x)
#define CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA_GET(x)\
FIELD_GET(CPU_PROC_CTRL_ACP_CACHE_FORCE_ENA, x)
+/* SPARX5 ONLY */
#define CPU_PROC_CTRL_ACP_AWCACHE BIT(3)
#define CPU_PROC_CTRL_ACP_AWCACHE_SET(x)\
FIELD_PREP(CPU_PROC_CTRL_ACP_AWCACHE, x)
#define CPU_PROC_CTRL_ACP_AWCACHE_GET(x)\
FIELD_GET(CPU_PROC_CTRL_ACP_AWCACHE, x)
+/* SPARX5 ONLY */
#define CPU_PROC_CTRL_ACP_ARCACHE BIT(2)
#define CPU_PROC_CTRL_ACP_ARCACHE_SET(x)\
FIELD_PREP(CPU_PROC_CTRL_ACP_ARCACHE, x)
#define CPU_PROC_CTRL_ACP_ARCACHE_GET(x)\
FIELD_GET(CPU_PROC_CTRL_ACP_ARCACHE, x)
-#define CPU_PROC_CTRL_L2_FLUSH_REQ BIT(1)
+#define CPU_PROC_CTRL_L2_FLUSH_REQ\
+ BIT(regs->fpos[FP_CPU_PROC_CTRL_L2_FLUSH_REQ])
#define CPU_PROC_CTRL_L2_FLUSH_REQ_SET(x)\
- FIELD_PREP(CPU_PROC_CTRL_L2_FLUSH_REQ, x)
+ spx5_field_prep(CPU_PROC_CTRL_L2_FLUSH_REQ, x)
#define CPU_PROC_CTRL_L2_FLUSH_REQ_GET(x)\
- FIELD_GET(CPU_PROC_CTRL_L2_FLUSH_REQ, x)
+ spx5_field_get(CPU_PROC_CTRL_L2_FLUSH_REQ, x)
+/* SPARX5 ONLY */
#define CPU_PROC_CTRL_ACP_DISABLE BIT(0)
#define CPU_PROC_CTRL_ACP_DISABLE_SET(x)\
FIELD_PREP(CPU_PROC_CTRL_ACP_DISABLE, x)
#define CPU_PROC_CTRL_ACP_DISABLE_GET(x)\
FIELD_GET(CPU_PROC_CTRL_ACP_DISABLE, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_ENA_CFG */
-#define DEV10G_MAC_ENA_CFG(t) __REG(TARGET_DEV10G,\
- t, 12, 0, 0, 1, 60, 0, 0, 1, 4)
+/* DEV1G:PHASE_DETECTOR_CTRL:PHAD_CTRL */
+#define DEV2G5_PHAD_CTRL(t, g) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 200, g, 2, \
+ regs->gsize[GW_DEV2G5_PHASE_DETECTOR_CTRL], 0, 0, 1, 4)
+
+#define DEV2G5_PHAD_CTRL_PHAD_ENA\
+ BIT(regs->fpos[FP_DEV2G5_PHAD_CTRL_PHAD_ENA])
+#define DEV2G5_PHAD_CTRL_PHAD_ENA_SET(x)\
+ spx5_field_prep(DEV2G5_PHAD_CTRL_PHAD_ENA, x)
+#define DEV2G5_PHAD_CTRL_PHAD_ENA_GET(x)\
+ spx5_field_get(DEV2G5_PHAD_CTRL_PHAD_ENA, x)
+
+/* LAN969X ONLY */
+#define DEV2G5_PHAD_CTRL_DIV_CFG GENMASK(11, 9)
+#define DEV2G5_PHAD_CTRL_DIV_CFG_SET(x)\
+ FIELD_PREP(DEV2G5_PHAD_CTRL_DIV_CFG, x)
+#define DEV2G5_PHAD_CTRL_DIV_CFG_GET(x)\
+ FIELD_GET(DEV2G5_PHAD_CTRL_DIV_CFG, x)
+
+/* DEV1G:PHASE_DETECTOR_CTRL:PHAD_CTRL */
+#define DEV2G5_PHAD_CTRL(t, g) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 200, g, 2, \
+ regs->gsize[GW_DEV2G5_PHASE_DETECTOR_CTRL], 0, 0, 1, 4)
+
+#define DEV2G5_PHAD_CTRL_PHAD_ENA\
+ BIT(regs->fpos[FP_DEV2G5_PHAD_CTRL_PHAD_ENA])
+#define DEV2G5_PHAD_CTRL_PHAD_ENA_SET(x)\
+ spx5_field_prep(DEV2G5_PHAD_CTRL_PHAD_ENA, x)
+#define DEV2G5_PHAD_CTRL_PHAD_ENA_GET(x)\
+ spx5_field_get(DEV2G5_PHAD_CTRL_PHAD_ENA, x)
+
+/* LAN969X ONLY */
+#define DEV2G5_PHAD_CTRL_DIV_CFG GENMASK(11, 9)
+#define DEV2G5_PHAD_CTRL_DIV_CFG_SET(x)\
+ FIELD_PREP(DEV2G5_PHAD_CTRL_DIV_CFG, x)
+#define DEV2G5_PHAD_CTRL_DIV_CFG_GET(x)\
+ FIELD_GET(DEV2G5_PHAD_CTRL_DIV_CFG, x)
+
+/* DEV10G:MAC_CFG_STATUS:MAC_ENA_CFG */
+#define DEV10G_MAC_ENA_CFG(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 0, 0, 1, 60, 0, 0, 1, \
+ 4)
#define DEV10G_MAC_ENA_CFG_RX_ENA BIT(4)
#define DEV10G_MAC_ENA_CFG_RX_ENA_SET(x)\
@@ -2441,9 +2721,10 @@ enum sparx5_target {
#define DEV10G_MAC_ENA_CFG_TX_ENA_GET(x)\
FIELD_GET(DEV10G_MAC_ENA_CFG_TX_ENA, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
-#define DEV10G_MAC_MAXLEN_CFG(t) __REG(TARGET_DEV10G,\
- t, 12, 0, 0, 1, 60, 8, 0, 1, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
+#define DEV10G_MAC_MAXLEN_CFG(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 0, 0, 1, 60, 8, 0, 1, \
+ 4)
#define DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK BIT(16)
#define DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK_SET(x)\
@@ -2457,9 +2738,10 @@ enum sparx5_target {
#define DEV10G_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\
FIELD_GET(DEV10G_MAC_MAXLEN_CFG_MAX_LEN, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_NUM_TAGS_CFG */
-#define DEV10G_MAC_NUM_TAGS_CFG(t) __REG(TARGET_DEV10G,\
- t, 12, 0, 0, 1, 60, 12, 0, 1, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_NUM_TAGS_CFG */
+#define DEV10G_MAC_NUM_TAGS_CFG(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 0, 0, 1, 60, 12, 0, 1, \
+ 4)
#define DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS GENMASK(1, 0)
#define DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS_SET(x)\
@@ -2467,9 +2749,10 @@ enum sparx5_target {
#define DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS_GET(x)\
FIELD_GET(DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_TAGS_CFG */
-#define DEV10G_MAC_TAGS_CFG(t, r) __REG(TARGET_DEV10G,\
- t, 12, 0, 0, 1, 60, 16, r, 3, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_TAGS_CFG */
+#define DEV10G_MAC_TAGS_CFG(t, r) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 0, 0, 1, 60, 16, r, 3, \
+ 4)
#define DEV10G_MAC_TAGS_CFG_TAG_ID GENMASK(31, 16)
#define DEV10G_MAC_TAGS_CFG_TAG_ID_SET(x)\
@@ -2483,9 +2766,10 @@ enum sparx5_target {
#define DEV10G_MAC_TAGS_CFG_TAG_ENA_GET(x)\
FIELD_GET(DEV10G_MAC_TAGS_CFG_TAG_ENA, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
-#define DEV10G_MAC_ADV_CHK_CFG(t) __REG(TARGET_DEV10G,\
- t, 12, 0, 0, 1, 60, 28, 0, 1, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
+#define DEV10G_MAC_ADV_CHK_CFG(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 0, 0, 1, 60, 28, 0, 1, \
+ 4)
#define DEV10G_MAC_ADV_CHK_CFG_EXT_EOP_CHK_ENA BIT(24)
#define DEV10G_MAC_ADV_CHK_CFG_EXT_EOP_CHK_ENA_SET(x)\
@@ -2529,9 +2813,10 @@ enum sparx5_target {
#define DEV10G_MAC_ADV_CHK_CFG_INR_ERR_ENA_GET(x)\
FIELD_GET(DEV10G_MAC_ADV_CHK_CFG_INR_ERR_ENA, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_TX_MONITOR_STICKY */
-#define DEV10G_MAC_TX_MONITOR_STICKY(t) __REG(TARGET_DEV10G,\
- t, 12, 0, 0, 1, 60, 48, 0, 1, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_TX_MONITOR_STICKY */
+#define DEV10G_MAC_TX_MONITOR_STICKY(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 0, 0, 1, 60, 48, 0, 1, \
+ 4)
#define DEV10G_MAC_TX_MONITOR_STICKY_LOCAL_ERR_STATE_STICKY BIT(4)
#define DEV10G_MAC_TX_MONITOR_STICKY_LOCAL_ERR_STATE_STICKY_SET(x)\
@@ -2563,9 +2848,10 @@ enum sparx5_target {
#define DEV10G_MAC_TX_MONITOR_STICKY_DIS_STATE_STICKY_GET(x)\
FIELD_GET(DEV10G_MAC_TX_MONITOR_STICKY_DIS_STATE_STICKY, x)
-/* DEV10G:DEV_CFG_STATUS:DEV_RST_CTRL */
-#define DEV10G_DEV_RST_CTRL(t) __REG(TARGET_DEV10G,\
- t, 12, 436, 0, 1, 52, 0, 0, 1, 4)
+/* DEV10G:DEV_CFG_STATUS:DEV_RST_CTRL */
+#define DEV10G_DEV_RST_CTRL(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 436, 0, 1, 52, 0, 0, 1,\
+ 4)
#define DEV10G_DEV_RST_CTRL_PARDET_MODE_ENA BIT(28)
#define DEV10G_DEV_RST_CTRL_PARDET_MODE_ENA_SET(x)\
@@ -2621,9 +2907,15 @@ enum sparx5_target {
#define DEV10G_DEV_RST_CTRL_MAC_RX_RST_GET(x)\
FIELD_GET(DEV10G_DEV_RST_CTRL_MAC_RX_RST, x)
-/* DEV10G:PCS25G_CFG_STATUS:PCS25G_CFG */
-#define DEV10G_PCS25G_CFG(t) __REG(TARGET_DEV10G,\
- t, 12, 488, 0, 1, 32, 0, 0, 1, 4)
+/* DEV10G:DEV_CFG_STATUS:PTP_STAMPER_CFG */
+#define DEV10G_PTP_STAMPER_CFG(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 436, 0, 1, 52, 20, 0, \
+ 1, 4)
+
+/* DEV10G:PCS25G_CFG_STATUS:PCS25G_CFG */
+#define DEV10G_PCS25G_CFG(t) \
+ __REG(TARGET_DEV10G, t, regs->tsize[TC_DEV10G], 488, 0, 1, 32, 0, 0, 1,\
+ 4)
#define DEV10G_PCS25G_CFG_PCS25G_ENA BIT(0)
#define DEV10G_PCS25G_CFG_PCS25G_ENA_SET(x)\
@@ -2631,9 +2923,10 @@ enum sparx5_target {
#define DEV10G_PCS25G_CFG_PCS25G_ENA_GET(x)\
FIELD_GET(DEV10G_PCS25G_CFG_PCS25G_ENA, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_ENA_CFG */
-#define DEV25G_MAC_ENA_CFG(t) __REG(TARGET_DEV25G,\
- t, 8, 0, 0, 1, 60, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* DEV10G:MAC_CFG_STATUS:MAC_ENA_CFG */
+#define DEV25G_MAC_ENA_CFG(t) \
+ __REG(TARGET_DEV25G, t, 8, 0, 0, 1, 60, 0, 0, 1, 4)
#define DEV25G_MAC_ENA_CFG_RX_ENA BIT(4)
#define DEV25G_MAC_ENA_CFG_RX_ENA_SET(x)\
@@ -2647,9 +2940,10 @@ enum sparx5_target {
#define DEV25G_MAC_ENA_CFG_TX_ENA_GET(x)\
FIELD_GET(DEV25G_MAC_ENA_CFG_TX_ENA, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
-#define DEV25G_MAC_MAXLEN_CFG(t) __REG(TARGET_DEV25G,\
- t, 8, 0, 0, 1, 60, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* DEV10G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
+#define DEV25G_MAC_MAXLEN_CFG(t) \
+ __REG(TARGET_DEV25G, t, 8, 0, 0, 1, 60, 8, 0, 1, 4)
#define DEV25G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK BIT(16)
#define DEV25G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK_SET(x)\
@@ -2663,9 +2957,10 @@ enum sparx5_target {
#define DEV25G_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\
FIELD_GET(DEV25G_MAC_MAXLEN_CFG_MAX_LEN, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
-#define DEV25G_MAC_ADV_CHK_CFG(t) __REG(TARGET_DEV25G,\
- t, 8, 0, 0, 1, 60, 28, 0, 1, 4)
+/* SPARX5 ONLY */
+/* DEV10G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
+#define DEV25G_MAC_ADV_CHK_CFG(t) \
+ __REG(TARGET_DEV25G, t, 8, 0, 0, 1, 60, 28, 0, 1, 4)
#define DEV25G_MAC_ADV_CHK_CFG_EXT_EOP_CHK_ENA BIT(24)
#define DEV25G_MAC_ADV_CHK_CFG_EXT_EOP_CHK_ENA_SET(x)\
@@ -2709,9 +3004,10 @@ enum sparx5_target {
#define DEV25G_MAC_ADV_CHK_CFG_INR_ERR_ENA_GET(x)\
FIELD_GET(DEV25G_MAC_ADV_CHK_CFG_INR_ERR_ENA, x)
-/* DEV10G:DEV_CFG_STATUS:DEV_RST_CTRL */
-#define DEV25G_DEV_RST_CTRL(t) __REG(TARGET_DEV25G,\
- t, 8, 436, 0, 1, 52, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* DEV10G:DEV_CFG_STATUS:DEV_RST_CTRL */
+#define DEV25G_DEV_RST_CTRL(t) \
+ __REG(TARGET_DEV25G, t, 8, 436, 0, 1, 52, 0, 0, 1, 4)
#define DEV25G_DEV_RST_CTRL_PARDET_MODE_ENA BIT(28)
#define DEV25G_DEV_RST_CTRL_PARDET_MODE_ENA_SET(x)\
@@ -2767,9 +3063,10 @@ enum sparx5_target {
#define DEV25G_DEV_RST_CTRL_MAC_RX_RST_GET(x)\
FIELD_GET(DEV25G_DEV_RST_CTRL_MAC_RX_RST, x)
-/* DEV10G:PCS25G_CFG_STATUS:PCS25G_CFG */
-#define DEV25G_PCS25G_CFG(t) __REG(TARGET_DEV25G,\
- t, 8, 488, 0, 1, 32, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* DEV10G:PCS25G_CFG_STATUS:PCS25G_CFG */
+#define DEV25G_PCS25G_CFG(t) \
+ __REG(TARGET_DEV25G, t, 8, 488, 0, 1, 32, 0, 0, 1, 4)
#define DEV25G_PCS25G_CFG_PCS25G_ENA BIT(0)
#define DEV25G_PCS25G_CFG_PCS25G_ENA_SET(x)\
@@ -2777,9 +3074,10 @@ enum sparx5_target {
#define DEV25G_PCS25G_CFG_PCS25G_ENA_GET(x)\
FIELD_GET(DEV25G_PCS25G_CFG_PCS25G_ENA, x)
-/* DEV10G:PCS25G_CFG_STATUS:PCS25G_SD_CFG */
-#define DEV25G_PCS25G_SD_CFG(t) __REG(TARGET_DEV25G,\
- t, 8, 488, 0, 1, 32, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* DEV10G:PCS25G_CFG_STATUS:PCS25G_SD_CFG */
+#define DEV25G_PCS25G_SD_CFG(t) \
+ __REG(TARGET_DEV25G, t, 8, 488, 0, 1, 32, 4, 0, 1, 4)
#define DEV25G_PCS25G_SD_CFG_SD_SEL BIT(8)
#define DEV25G_PCS25G_SD_CFG_SD_SEL_SET(x)\
@@ -2799,9 +3097,10 @@ enum sparx5_target {
#define DEV25G_PCS25G_SD_CFG_SD_ENA_GET(x)\
FIELD_GET(DEV25G_PCS25G_SD_CFG_SD_ENA, x)
-/* DEV1G:DEV_CFG_STATUS:DEV_RST_CTRL */
-#define DEV2G5_DEV_RST_CTRL(t) __REG(TARGET_DEV2G5,\
- t, 65, 0, 0, 1, 36, 0, 0, 1, 4)
+/* DEV1G:DEV_CFG_STATUS:DEV_RST_CTRL */
+#define DEV2G5_DEV_RST_CTRL(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 0, 0, 1, 36, 0, 0, 1, \
+ 4)
#define DEV2G5_DEV_RST_CTRL_USXGMII_OSET_FILTER_DIS BIT(23)
#define DEV2G5_DEV_RST_CTRL_USXGMII_OSET_FILTER_DIS_SET(x)\
@@ -2851,9 +3150,10 @@ enum sparx5_target {
#define DEV2G5_DEV_RST_CTRL_MAC_RX_RST_GET(x)\
FIELD_GET(DEV2G5_DEV_RST_CTRL_MAC_RX_RST, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_ENA_CFG */
-#define DEV2G5_MAC_ENA_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 0, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_ENA_CFG */
+#define DEV2G5_MAC_ENA_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 0, 0, 1, \
+ 4)
#define DEV2G5_MAC_ENA_CFG_RX_ENA BIT(4)
#define DEV2G5_MAC_ENA_CFG_RX_ENA_SET(x)\
@@ -2867,9 +3167,10 @@ enum sparx5_target {
#define DEV2G5_MAC_ENA_CFG_TX_ENA_GET(x)\
FIELD_GET(DEV2G5_MAC_ENA_CFG_TX_ENA, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_MODE_CFG */
-#define DEV2G5_MAC_MODE_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 4, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_MODE_CFG */
+#define DEV2G5_MAC_MODE_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 4, 0, 1, \
+ 4)
#define DEV2G5_MAC_MODE_CFG_FC_WORD_SYNC_ENA BIT(8)
#define DEV2G5_MAC_MODE_CFG_FC_WORD_SYNC_ENA_SET(x)\
@@ -2889,9 +3190,10 @@ enum sparx5_target {
#define DEV2G5_MAC_MODE_CFG_FDX_ENA_GET(x)\
FIELD_GET(DEV2G5_MAC_MODE_CFG_FDX_ENA, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
-#define DEV2G5_MAC_MAXLEN_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 8, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
+#define DEV2G5_MAC_MAXLEN_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 8, 0, 1, \
+ 4)
#define DEV2G5_MAC_MAXLEN_CFG_MAX_LEN GENMASK(15, 0)
#define DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(x)\
@@ -2899,9 +3201,10 @@ enum sparx5_target {
#define DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\
FIELD_GET(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_TAGS_CFG */
-#define DEV2G5_MAC_TAGS_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 12, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_TAGS_CFG */
+#define DEV2G5_MAC_TAGS_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 12, 0, 1,\
+ 4)
#define DEV2G5_MAC_TAGS_CFG_TAG_ID GENMASK(31, 16)
#define DEV2G5_MAC_TAGS_CFG_TAG_ID_SET(x)\
@@ -2927,9 +3230,10 @@ enum sparx5_target {
#define DEV2G5_MAC_TAGS_CFG_VLAN_AWR_ENA_GET(x)\
FIELD_GET(DEV2G5_MAC_TAGS_CFG_VLAN_AWR_ENA, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_TAGS_CFG2 */
-#define DEV2G5_MAC_TAGS_CFG2(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 16, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_TAGS_CFG2 */
+#define DEV2G5_MAC_TAGS_CFG2(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 16, 0, 1,\
+ 4)
#define DEV2G5_MAC_TAGS_CFG2_TAG_ID3 GENMASK(31, 16)
#define DEV2G5_MAC_TAGS_CFG2_TAG_ID3_SET(x)\
@@ -2943,9 +3247,10 @@ enum sparx5_target {
#define DEV2G5_MAC_TAGS_CFG2_TAG_ID2_GET(x)\
FIELD_GET(DEV2G5_MAC_TAGS_CFG2_TAG_ID2, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
-#define DEV2G5_MAC_ADV_CHK_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 20, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
+#define DEV2G5_MAC_ADV_CHK_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 20, 0, 1,\
+ 4)
#define DEV2G5_MAC_ADV_CHK_CFG_LEN_DROP_ENA BIT(0)
#define DEV2G5_MAC_ADV_CHK_CFG_LEN_DROP_ENA_SET(x)\
@@ -2953,9 +3258,10 @@ enum sparx5_target {
#define DEV2G5_MAC_ADV_CHK_CFG_LEN_DROP_ENA_GET(x)\
FIELD_GET(DEV2G5_MAC_ADV_CHK_CFG_LEN_DROP_ENA, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_IFG_CFG */
-#define DEV2G5_MAC_IFG_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 24, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_IFG_CFG */
+#define DEV2G5_MAC_IFG_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 24, 0, 1,\
+ 4)
#define DEV2G5_MAC_IFG_CFG_RESTORE_OLD_IPG_CHECK BIT(17)
#define DEV2G5_MAC_IFG_CFG_RESTORE_OLD_IPG_CHECK_SET(x)\
@@ -2981,9 +3287,10 @@ enum sparx5_target {
#define DEV2G5_MAC_IFG_CFG_RX_IFG1_GET(x)\
FIELD_GET(DEV2G5_MAC_IFG_CFG_RX_IFG1, x)
-/* DEV1G:MAC_CFG_STATUS:MAC_HDX_CFG */
-#define DEV2G5_MAC_HDX_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 52, 0, 1, 36, 28, 0, 1, 4)
+/* DEV1G:MAC_CFG_STATUS:MAC_HDX_CFG */
+#define DEV2G5_MAC_HDX_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 52, 0, 1, 36, 28, 0, 1,\
+ 4)
#define DEV2G5_MAC_HDX_CFG_BYPASS_COL_SYNC BIT(26)
#define DEV2G5_MAC_HDX_CFG_BYPASS_COL_SYNC_SET(x)\
@@ -3015,9 +3322,10 @@ enum sparx5_target {
#define DEV2G5_MAC_HDX_CFG_LATE_COL_POS_GET(x)\
FIELD_GET(DEV2G5_MAC_HDX_CFG_LATE_COL_POS, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_CFG */
-#define DEV2G5_PCS1G_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 0, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_CFG */
+#define DEV2G5_PCS1G_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 0, 0, 1, \
+ 4)
#define DEV2G5_PCS1G_CFG_LINK_STATUS_TYPE BIT(4)
#define DEV2G5_PCS1G_CFG_LINK_STATUS_TYPE_SET(x)\
@@ -3037,9 +3345,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_CFG_PCS_ENA_GET(x)\
FIELD_GET(DEV2G5_PCS1G_CFG_PCS_ENA, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_MODE_CFG */
-#define DEV2G5_PCS1G_MODE_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 4, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_MODE_CFG */
+#define DEV2G5_PCS1G_MODE_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 4, 0, 1, \
+ 4)
#define DEV2G5_PCS1G_MODE_CFG_UNIDIR_MODE_ENA BIT(4)
#define DEV2G5_PCS1G_MODE_CFG_UNIDIR_MODE_ENA_SET(x)\
@@ -3059,9 +3368,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_MODE_CFG_SGMII_MODE_ENA_GET(x)\
FIELD_GET(DEV2G5_PCS1G_MODE_CFG_SGMII_MODE_ENA, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_SD_CFG */
-#define DEV2G5_PCS1G_SD_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 8, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_SD_CFG */
+#define DEV2G5_PCS1G_SD_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 8, 0, 1, \
+ 4)
#define DEV2G5_PCS1G_SD_CFG_SD_SEL BIT(8)
#define DEV2G5_PCS1G_SD_CFG_SD_SEL_SET(x)\
@@ -3081,9 +3391,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_SD_CFG_SD_ENA_GET(x)\
FIELD_GET(DEV2G5_PCS1G_SD_CFG_SD_ENA, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_ANEG_CFG */
-#define DEV2G5_PCS1G_ANEG_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 12, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_ANEG_CFG */
+#define DEV2G5_PCS1G_ANEG_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 12, 0, 1,\
+ 4)
#define DEV2G5_PCS1G_ANEG_CFG_ADV_ABILITY GENMASK(31, 16)
#define DEV2G5_PCS1G_ANEG_CFG_ADV_ABILITY_SET(x)\
@@ -3109,9 +3420,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_ANEG_CFG_ANEG_ENA_GET(x)\
FIELD_GET(DEV2G5_PCS1G_ANEG_CFG_ANEG_ENA, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_LB_CFG */
-#define DEV2G5_PCS1G_LB_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 20, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_LB_CFG */
+#define DEV2G5_PCS1G_LB_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 20, 0, 1,\
+ 4)
#define DEV2G5_PCS1G_LB_CFG_RA_ENA BIT(4)
#define DEV2G5_PCS1G_LB_CFG_RA_ENA_SET(x)\
@@ -3131,9 +3443,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_LB_CFG_TBI_HOST_LB_ENA_GET(x)\
FIELD_GET(DEV2G5_PCS1G_LB_CFG_TBI_HOST_LB_ENA, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_ANEG_STATUS */
-#define DEV2G5_PCS1G_ANEG_STATUS(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 32, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_ANEG_STATUS */
+#define DEV2G5_PCS1G_ANEG_STATUS(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 32, 0, 1,\
+ 4)
#define DEV2G5_PCS1G_ANEG_STATUS_LP_ADV_ABILITY GENMASK(31, 16)
#define DEV2G5_PCS1G_ANEG_STATUS_LP_ADV_ABILITY_SET(x)\
@@ -3159,9 +3472,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_ANEG_STATUS_ANEG_COMPLETE_GET(x)\
FIELD_GET(DEV2G5_PCS1G_ANEG_STATUS_ANEG_COMPLETE, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_LINK_STATUS */
-#define DEV2G5_PCS1G_LINK_STATUS(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 40, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_LINK_STATUS */
+#define DEV2G5_PCS1G_LINK_STATUS(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 40, 0, 1,\
+ 4)
#define DEV2G5_PCS1G_LINK_STATUS_DELAY_VAR GENMASK(15, 12)
#define DEV2G5_PCS1G_LINK_STATUS_DELAY_VAR_SET(x)\
@@ -3187,9 +3501,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_LINK_STATUS_SYNC_STATUS_GET(x)\
FIELD_GET(DEV2G5_PCS1G_LINK_STATUS_SYNC_STATUS, x)
-/* DEV1G:PCS1G_CFG_STATUS:PCS1G_STICKY */
-#define DEV2G5_PCS1G_STICKY(t) __REG(TARGET_DEV2G5,\
- t, 65, 88, 0, 1, 68, 48, 0, 1, 4)
+/* DEV1G:PCS1G_CFG_STATUS:PCS1G_STICKY */
+#define DEV2G5_PCS1G_STICKY(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 88, 0, 1, 68, 48, 0, 1,\
+ 4)
#define DEV2G5_PCS1G_STICKY_LINK_DOWN_STICKY BIT(4)
#define DEV2G5_PCS1G_STICKY_LINK_DOWN_STICKY_SET(x)\
@@ -3203,9 +3518,10 @@ enum sparx5_target {
#define DEV2G5_PCS1G_STICKY_OUT_OF_SYNC_STICKY_GET(x)\
FIELD_GET(DEV2G5_PCS1G_STICKY_OUT_OF_SYNC_STICKY, x)
-/* DEV1G:PCS_FX100_CONFIGURATION:PCS_FX100_CFG */
-#define DEV2G5_PCS_FX100_CFG(t) __REG(TARGET_DEV2G5,\
- t, 65, 164, 0, 1, 4, 0, 0, 1, 4)
+/* DEV1G:PCS_FX100_CONFIGURATION:PCS_FX100_CFG */
+#define DEV2G5_PCS_FX100_CFG(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 164, 0, 1, 4, 0, 0, 1, \
+ 4)
#define DEV2G5_PCS_FX100_CFG_SD_SEL BIT(26)
#define DEV2G5_PCS_FX100_CFG_SD_SEL_SET(x)\
@@ -3285,9 +3601,10 @@ enum sparx5_target {
#define DEV2G5_PCS_FX100_CFG_PCS_ENA_GET(x)\
FIELD_GET(DEV2G5_PCS_FX100_CFG_PCS_ENA, x)
-/* DEV1G:PCS_FX100_STATUS:PCS_FX100_STATUS */
-#define DEV2G5_PCS_FX100_STATUS(t) __REG(TARGET_DEV2G5,\
- t, 65, 168, 0, 1, 4, 0, 0, 1, 4)
+/* DEV1G:PCS_FX100_STATUS:PCS_FX100_STATUS */
+#define DEV2G5_PCS_FX100_STATUS(t) \
+ __REG(TARGET_DEV2G5, t, regs->tsize[TC_DEV2G5], 168, 0, 1, 4, 0, 0, 1, \
+ 4)
#define DEV2G5_PCS_FX100_STATUS_EDGE_POS_PTP GENMASK(11, 8)
#define DEV2G5_PCS_FX100_STATUS_EDGE_POS_PTP_SET(x)\
@@ -3337,9 +3654,9 @@ enum sparx5_target {
#define DEV2G5_PCS_FX100_STATUS_SYNC_STATUS_GET(x)\
FIELD_GET(DEV2G5_PCS_FX100_STATUS_SYNC_STATUS, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_ENA_CFG */
-#define DEV5G_MAC_ENA_CFG(t) __REG(TARGET_DEV5G,\
- t, 13, 0, 0, 1, 60, 0, 0, 1, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_ENA_CFG */
+#define DEV5G_MAC_ENA_CFG(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 0, 0, 1, 60, 0, 0, 1, 4)
#define DEV5G_MAC_ENA_CFG_RX_ENA BIT(4)
#define DEV5G_MAC_ENA_CFG_RX_ENA_SET(x)\
@@ -3353,9 +3670,9 @@ enum sparx5_target {
#define DEV5G_MAC_ENA_CFG_TX_ENA_GET(x)\
FIELD_GET(DEV5G_MAC_ENA_CFG_TX_ENA, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
-#define DEV5G_MAC_MAXLEN_CFG(t) __REG(TARGET_DEV5G,\
- t, 13, 0, 0, 1, 60, 8, 0, 1, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
+#define DEV5G_MAC_MAXLEN_CFG(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 0, 0, 1, 60, 8, 0, 1, 4)
#define DEV5G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK BIT(16)
#define DEV5G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK_SET(x)\
@@ -3369,9 +3686,10 @@ enum sparx5_target {
#define DEV5G_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\
FIELD_GET(DEV5G_MAC_MAXLEN_CFG_MAX_LEN, x)
-/* DEV10G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
-#define DEV5G_MAC_ADV_CHK_CFG(t) __REG(TARGET_DEV5G,\
- t, 13, 0, 0, 1, 60, 28, 0, 1, 4)
+/* DEV10G:MAC_CFG_STATUS:MAC_ADV_CHK_CFG */
+#define DEV5G_MAC_ADV_CHK_CFG(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 0, 0, 1, 60, 28, 0, 1, \
+ 4)
#define DEV5G_MAC_ADV_CHK_CFG_EXT_EOP_CHK_ENA BIT(24)
#define DEV5G_MAC_ADV_CHK_CFG_EXT_EOP_CHK_ENA_SET(x)\
@@ -3415,325 +3733,405 @@ enum sparx5_target {
#define DEV5G_MAC_ADV_CHK_CFG_INR_ERR_ENA_GET(x)\
FIELD_GET(DEV5G_MAC_ADV_CHK_CFG_INR_ERR_ENA, x)
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SYMBOL_ERR_CNT */
-#define DEV5G_RX_SYMBOL_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 0, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_PAUSE_CNT */
-#define DEV5G_RX_PAUSE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 4, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_UNSUP_OPCODE_CNT */
-#define DEV5G_RX_UNSUP_OPCODE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 8, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_UC_CNT */
-#define DEV5G_RX_UC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 12, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_MC_CNT */
-#define DEV5G_RX_MC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 16, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_BC_CNT */
-#define DEV5G_RX_BC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 20, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_CRC_ERR_CNT */
-#define DEV5G_RX_CRC_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 24, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_UNDERSIZE_CNT */
-#define DEV5G_RX_UNDERSIZE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 28, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_FRAGMENTS_CNT */
-#define DEV5G_RX_FRAGMENTS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 32, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_IN_RANGE_LEN_ERR_CNT */
-#define DEV5G_RX_IN_RANGE_LEN_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 36, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_OUT_OF_RANGE_LEN_ERR_CNT */
-#define DEV5G_RX_OUT_OF_RANGE_LEN_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 40, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_OVERSIZE_CNT */
-#define DEV5G_RX_OVERSIZE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 44, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_JABBERS_CNT */
-#define DEV5G_RX_JABBERS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 48, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE64_CNT */
-#define DEV5G_RX_SIZE64_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 52, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE65TO127_CNT */
-#define DEV5G_RX_SIZE65TO127_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 56, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE128TO255_CNT */
-#define DEV5G_RX_SIZE128TO255_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 60, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE256TO511_CNT */
-#define DEV5G_RX_SIZE256TO511_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 64, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE512TO1023_CNT */
-#define DEV5G_RX_SIZE512TO1023_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 68, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE1024TO1518_CNT */
-#define DEV5G_RX_SIZE1024TO1518_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 72, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE1519TOMAX_CNT */
-#define DEV5G_RX_SIZE1519TOMAX_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 76, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_IPG_SHRINK_CNT */
-#define DEV5G_RX_IPG_SHRINK_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 80, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_PAUSE_CNT */
-#define DEV5G_TX_PAUSE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 84, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_UC_CNT */
-#define DEV5G_TX_UC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 88, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_MC_CNT */
-#define DEV5G_TX_MC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 92, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_BC_CNT */
-#define DEV5G_TX_BC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 96, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE64_CNT */
-#define DEV5G_TX_SIZE64_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 100, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE65TO127_CNT */
-#define DEV5G_TX_SIZE65TO127_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 104, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE128TO255_CNT */
-#define DEV5G_TX_SIZE128TO255_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 108, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE256TO511_CNT */
-#define DEV5G_TX_SIZE256TO511_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 112, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE512TO1023_CNT */
-#define DEV5G_TX_SIZE512TO1023_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 116, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE1024TO1518_CNT */
-#define DEV5G_TX_SIZE1024TO1518_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 120, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE1519TOMAX_CNT */
-#define DEV5G_TX_SIZE1519TOMAX_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 124, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_ALIGNMENT_LOST_CNT */
-#define DEV5G_RX_ALIGNMENT_LOST_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 128, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_TAGGED_FRMS_CNT */
-#define DEV5G_RX_TAGGED_FRMS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 132, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_UNTAGGED_FRMS_CNT */
-#define DEV5G_RX_UNTAGGED_FRMS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 136, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_TAGGED_FRMS_CNT */
-#define DEV5G_TX_TAGGED_FRMS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 140, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:TX_UNTAGGED_FRMS_CNT */
-#define DEV5G_TX_UNTAGGED_FRMS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 144, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SYMBOL_ERR_CNT */
-#define DEV5G_PMAC_RX_SYMBOL_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 148, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_PAUSE_CNT */
-#define DEV5G_PMAC_RX_PAUSE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 152, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_UNSUP_OPCODE_CNT */
-#define DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 156, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_UC_CNT */
-#define DEV5G_PMAC_RX_UC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 160, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_MC_CNT */
-#define DEV5G_PMAC_RX_MC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 164, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_BC_CNT */
-#define DEV5G_PMAC_RX_BC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 168, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_CRC_ERR_CNT */
-#define DEV5G_PMAC_RX_CRC_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 172, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_UNDERSIZE_CNT */
-#define DEV5G_PMAC_RX_UNDERSIZE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 176, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_FRAGMENTS_CNT */
-#define DEV5G_PMAC_RX_FRAGMENTS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 180, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_IN_RANGE_LEN_ERR_CNT */
-#define DEV5G_PMAC_RX_IN_RANGE_LEN_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 184, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT */
-#define DEV5G_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 188, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_OVERSIZE_CNT */
-#define DEV5G_PMAC_RX_OVERSIZE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 192, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_JABBERS_CNT */
-#define DEV5G_PMAC_RX_JABBERS_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 196, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE64_CNT */
-#define DEV5G_PMAC_RX_SIZE64_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 200, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE65TO127_CNT */
-#define DEV5G_PMAC_RX_SIZE65TO127_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 204, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE128TO255_CNT */
-#define DEV5G_PMAC_RX_SIZE128TO255_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 208, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE256TO511_CNT */
-#define DEV5G_PMAC_RX_SIZE256TO511_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 212, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE512TO1023_CNT */
-#define DEV5G_PMAC_RX_SIZE512TO1023_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 216, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE1024TO1518_CNT */
-#define DEV5G_PMAC_RX_SIZE1024TO1518_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 220, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE1519TOMAX_CNT */
-#define DEV5G_PMAC_RX_SIZE1519TOMAX_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 224, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_PAUSE_CNT */
-#define DEV5G_PMAC_TX_PAUSE_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 228, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_UC_CNT */
-#define DEV5G_PMAC_TX_UC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 232, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_MC_CNT */
-#define DEV5G_PMAC_TX_MC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 236, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_BC_CNT */
-#define DEV5G_PMAC_TX_BC_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 240, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE64_CNT */
-#define DEV5G_PMAC_TX_SIZE64_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 244, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE65TO127_CNT */
-#define DEV5G_PMAC_TX_SIZE65TO127_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 248, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE128TO255_CNT */
-#define DEV5G_PMAC_TX_SIZE128TO255_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 252, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE256TO511_CNT */
-#define DEV5G_PMAC_TX_SIZE256TO511_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 256, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE512TO1023_CNT */
-#define DEV5G_PMAC_TX_SIZE512TO1023_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 260, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE1024TO1518_CNT */
-#define DEV5G_PMAC_TX_SIZE1024TO1518_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 264, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE1519TOMAX_CNT */
-#define DEV5G_PMAC_TX_SIZE1519TOMAX_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 268, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_ALIGNMENT_LOST_CNT */
-#define DEV5G_PMAC_RX_ALIGNMENT_LOST_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 272, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_ASSEMBLY_ERR_CNT */
-#define DEV5G_MM_RX_ASSEMBLY_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 276, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_SMD_ERR_CNT */
-#define DEV5G_MM_RX_SMD_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 280, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_ASSEMBLY_OK_CNT */
-#define DEV5G_MM_RX_ASSEMBLY_OK_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 284, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_MERGE_FRAG_CNT */
-#define DEV5G_MM_RX_MERGE_FRAG_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 288, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:MM_TX_PFRAGMENT_CNT */
-#define DEV5G_MM_TX_PFRAGMENT_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 292, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_HIH_CKSM_ERR_CNT */
-#define DEV5G_RX_HIH_CKSM_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 296, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:RX_XGMII_PROT_ERR_CNT */
-#define DEV5G_RX_XGMII_PROT_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 300, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_HIH_CKSM_ERR_CNT */
-#define DEV5G_PMAC_RX_HIH_CKSM_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 304, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_XGMII_PROT_ERR_CNT */
-#define DEV5G_PMAC_RX_XGMII_PROT_ERR_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 60, 0, 1, 312, 308, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_40BIT:RX_IN_BYTES_CNT */
-#define DEV5G_RX_IN_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 0, 0, 1, 4)
-
-/* DEV10G:DEV_STATISTICS_40BIT:RX_IN_BYTES_MSB_CNT */
-#define DEV5G_RX_IN_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 4, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SYMBOL_ERR_CNT */
+#define DEV5G_RX_SYMBOL_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 0, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_PAUSE_CNT */
+#define DEV5G_RX_PAUSE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 4, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_UNSUP_OPCODE_CNT */
+#define DEV5G_RX_UNSUP_OPCODE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 8, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_UC_CNT */
+#define DEV5G_RX_UC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 12, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_MC_CNT */
+#define DEV5G_RX_MC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 16, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_BC_CNT */
+#define DEV5G_RX_BC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 20, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_CRC_ERR_CNT */
+#define DEV5G_RX_CRC_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 24, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_UNDERSIZE_CNT */
+#define DEV5G_RX_UNDERSIZE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 28, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_FRAGMENTS_CNT */
+#define DEV5G_RX_FRAGMENTS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 32, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_IN_RANGE_LEN_ERR_CNT */
+#define DEV5G_RX_IN_RANGE_LEN_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 36, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_OUT_OF_RANGE_LEN_ERR_CNT */
+#define DEV5G_RX_OUT_OF_RANGE_LEN_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 40, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_OVERSIZE_CNT */
+#define DEV5G_RX_OVERSIZE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 44, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_JABBERS_CNT */
+#define DEV5G_RX_JABBERS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 48, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE64_CNT */
+#define DEV5G_RX_SIZE64_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 52, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE65TO127_CNT */
+#define DEV5G_RX_SIZE65TO127_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 56, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE128TO255_CNT */
+#define DEV5G_RX_SIZE128TO255_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 60, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE256TO511_CNT */
+#define DEV5G_RX_SIZE256TO511_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 64, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE512TO1023_CNT */
+#define DEV5G_RX_SIZE512TO1023_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 68, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE1024TO1518_CNT */
+#define DEV5G_RX_SIZE1024TO1518_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 72, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_SIZE1519TOMAX_CNT */
+#define DEV5G_RX_SIZE1519TOMAX_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 76, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_IPG_SHRINK_CNT */
+#define DEV5G_RX_IPG_SHRINK_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 80, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_PAUSE_CNT */
+#define DEV5G_TX_PAUSE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 84, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_UC_CNT */
+#define DEV5G_TX_UC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 88, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_MC_CNT */
+#define DEV5G_TX_MC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 92, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_BC_CNT */
+#define DEV5G_TX_BC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 96, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE64_CNT */
+#define DEV5G_TX_SIZE64_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 100, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE65TO127_CNT */
+#define DEV5G_TX_SIZE65TO127_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 104, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE128TO255_CNT */
+#define DEV5G_TX_SIZE128TO255_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 108, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE256TO511_CNT */
+#define DEV5G_TX_SIZE256TO511_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 112, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE512TO1023_CNT */
+#define DEV5G_TX_SIZE512TO1023_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 116, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE1024TO1518_CNT */
+#define DEV5G_TX_SIZE1024TO1518_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 120, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_SIZE1519TOMAX_CNT */
+#define DEV5G_TX_SIZE1519TOMAX_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 124, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_ALIGNMENT_LOST_CNT */
+#define DEV5G_RX_ALIGNMENT_LOST_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 128, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_TAGGED_FRMS_CNT */
+#define DEV5G_RX_TAGGED_FRMS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 132, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_UNTAGGED_FRMS_CNT */
+#define DEV5G_RX_UNTAGGED_FRMS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 136, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_TAGGED_FRMS_CNT */
+#define DEV5G_TX_TAGGED_FRMS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 140, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:TX_UNTAGGED_FRMS_CNT */
+#define DEV5G_TX_UNTAGGED_FRMS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 144, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SYMBOL_ERR_CNT */
+#define DEV5G_PMAC_RX_SYMBOL_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 148, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_PAUSE_CNT */
+#define DEV5G_PMAC_RX_PAUSE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 152, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_UNSUP_OPCODE_CNT */
+#define DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 156, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_UC_CNT */
+#define DEV5G_PMAC_RX_UC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 160, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_MC_CNT */
+#define DEV5G_PMAC_RX_MC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 164, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_BC_CNT */
+#define DEV5G_PMAC_RX_BC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 168, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_CRC_ERR_CNT */
+#define DEV5G_PMAC_RX_CRC_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 172, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_UNDERSIZE_CNT */
+#define DEV5G_PMAC_RX_UNDERSIZE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 176, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_FRAGMENTS_CNT */
+#define DEV5G_PMAC_RX_FRAGMENTS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 180, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_IN_RANGE_LEN_ERR_CNT */
+#define DEV5G_PMAC_RX_IN_RANGE_LEN_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 184, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT */
+#define DEV5G_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 188, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_OVERSIZE_CNT */
+#define DEV5G_PMAC_RX_OVERSIZE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 192, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_JABBERS_CNT */
+#define DEV5G_PMAC_RX_JABBERS_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 196, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE64_CNT */
+#define DEV5G_PMAC_RX_SIZE64_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 200, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE65TO127_CNT */
+#define DEV5G_PMAC_RX_SIZE65TO127_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 204, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE128TO255_CNT */
+#define DEV5G_PMAC_RX_SIZE128TO255_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 208, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE256TO511_CNT */
+#define DEV5G_PMAC_RX_SIZE256TO511_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 212, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE512TO1023_CNT */
+#define DEV5G_PMAC_RX_SIZE512TO1023_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 216, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE1024TO1518_CNT */
+#define DEV5G_PMAC_RX_SIZE1024TO1518_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 220, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_SIZE1519TOMAX_CNT */
+#define DEV5G_PMAC_RX_SIZE1519TOMAX_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 224, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_PAUSE_CNT */
+#define DEV5G_PMAC_TX_PAUSE_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 228, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_UC_CNT */
+#define DEV5G_PMAC_TX_UC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 232, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_MC_CNT */
+#define DEV5G_PMAC_TX_MC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 236, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_BC_CNT */
+#define DEV5G_PMAC_TX_BC_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 240, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE64_CNT */
+#define DEV5G_PMAC_TX_SIZE64_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 244, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE65TO127_CNT */
+#define DEV5G_PMAC_TX_SIZE65TO127_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 248, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE128TO255_CNT */
+#define DEV5G_PMAC_TX_SIZE128TO255_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 252, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE256TO511_CNT */
+#define DEV5G_PMAC_TX_SIZE256TO511_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 256, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE512TO1023_CNT */
+#define DEV5G_PMAC_TX_SIZE512TO1023_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 260, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE1024TO1518_CNT */
+#define DEV5G_PMAC_TX_SIZE1024TO1518_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 264, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_TX_SIZE1519TOMAX_CNT */
+#define DEV5G_PMAC_TX_SIZE1519TOMAX_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 268, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_ALIGNMENT_LOST_CNT */
+#define DEV5G_PMAC_RX_ALIGNMENT_LOST_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 272, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_ASSEMBLY_ERR_CNT */
+#define DEV5G_MM_RX_ASSEMBLY_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 276, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_SMD_ERR_CNT */
+#define DEV5G_MM_RX_SMD_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 280, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_ASSEMBLY_OK_CNT */
+#define DEV5G_MM_RX_ASSEMBLY_OK_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 284, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:MM_RX_MERGE_FRAG_CNT */
+#define DEV5G_MM_RX_MERGE_FRAG_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 288, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:MM_TX_PFRAGMENT_CNT */
+#define DEV5G_MM_TX_PFRAGMENT_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 292, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_HIH_CKSM_ERR_CNT */
+#define DEV5G_RX_HIH_CKSM_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 296, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:RX_XGMII_PROT_ERR_CNT */
+#define DEV5G_RX_XGMII_PROT_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 300, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_HIH_CKSM_ERR_CNT */
+#define DEV5G_PMAC_RX_HIH_CKSM_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 304, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_32BIT:PMAC_RX_XGMII_PROT_ERR_CNT */
+#define DEV5G_PMAC_RX_XGMII_PROT_ERR_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 60, 0, 1, 312, 308, 0, 1,\
+ 4)
+
+/* DEV10G:DEV_STATISTICS_40BIT:RX_IN_BYTES_CNT */
+#define DEV5G_RX_IN_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 0, 0, 1, \
+ 4)
+
+/* DEV10G:DEV_STATISTICS_40BIT:RX_IN_BYTES_MSB_CNT */
+#define DEV5G_RX_IN_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 4, 0, 1, \
+ 4)
#define DEV5G_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT_SET(x)\
@@ -3741,13 +4139,15 @@ enum sparx5_target {
#define DEV5G_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_RX_IN_BYTES_MSB_CNT_RX_IN_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_STATISTICS_40BIT:RX_OK_BYTES_CNT */
-#define DEV5G_RX_OK_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 8, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:RX_OK_BYTES_CNT */
+#define DEV5G_RX_OK_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 8, 0, 1, \
+ 4)
-/* DEV10G:DEV_STATISTICS_40BIT:RX_OK_BYTES_MSB_CNT */
-#define DEV5G_RX_OK_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 12, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:RX_OK_BYTES_MSB_CNT */
+#define DEV5G_RX_OK_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 12, 0, 1, \
+ 4)
#define DEV5G_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT_SET(x)\
@@ -3755,13 +4155,15 @@ enum sparx5_target {
#define DEV5G_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_RX_OK_BYTES_MSB_CNT_RX_OK_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_STATISTICS_40BIT:RX_BAD_BYTES_CNT */
-#define DEV5G_RX_BAD_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 16, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:RX_BAD_BYTES_CNT */
+#define DEV5G_RX_BAD_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 16, 0, 1, \
+ 4)
-/* DEV10G:DEV_STATISTICS_40BIT:RX_BAD_BYTES_MSB_CNT */
-#define DEV5G_RX_BAD_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 20, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:RX_BAD_BYTES_MSB_CNT */
+#define DEV5G_RX_BAD_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 20, 0, 1, \
+ 4)
#define DEV5G_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT_SET(x)\
@@ -3769,13 +4171,15 @@ enum sparx5_target {
#define DEV5G_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_RX_BAD_BYTES_MSB_CNT_RX_BAD_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_STATISTICS_40BIT:TX_OUT_BYTES_CNT */
-#define DEV5G_TX_OUT_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 24, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:TX_OUT_BYTES_CNT */
+#define DEV5G_TX_OUT_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 24, 0, 1, \
+ 4)
-/* DEV10G:DEV_STATISTICS_40BIT:TX_OUT_BYTES_MSB_CNT */
-#define DEV5G_TX_OUT_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 28, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:TX_OUT_BYTES_MSB_CNT */
+#define DEV5G_TX_OUT_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 28, 0, 1, \
+ 4)
#define DEV5G_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT_SET(x)\
@@ -3783,13 +4187,15 @@ enum sparx5_target {
#define DEV5G_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_TX_OUT_BYTES_MSB_CNT_TX_OUT_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_STATISTICS_40BIT:TX_OK_BYTES_CNT */
-#define DEV5G_TX_OK_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 32, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:TX_OK_BYTES_CNT */
+#define DEV5G_TX_OK_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 32, 0, 1, \
+ 4)
-/* DEV10G:DEV_STATISTICS_40BIT:TX_OK_BYTES_MSB_CNT */
-#define DEV5G_TX_OK_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 36, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:TX_OK_BYTES_MSB_CNT */
+#define DEV5G_TX_OK_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 36, 0, 1, \
+ 4)
#define DEV5G_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT_SET(x)\
@@ -3797,13 +4203,15 @@ enum sparx5_target {
#define DEV5G_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_TX_OK_BYTES_MSB_CNT_TX_OK_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_OK_BYTES_CNT */
-#define DEV5G_PMAC_RX_OK_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 40, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_OK_BYTES_CNT */
+#define DEV5G_PMAC_RX_OK_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 40, 0, 1, \
+ 4)
-/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_OK_BYTES_MSB_CNT */
-#define DEV5G_PMAC_RX_OK_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 44, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_OK_BYTES_MSB_CNT */
+#define DEV5G_PMAC_RX_OK_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 44, 0, 1, \
+ 4)
#define DEV5G_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT_SET(x)\
@@ -3811,13 +4219,15 @@ enum sparx5_target {
#define DEV5G_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_PMAC_RX_OK_BYTES_MSB_CNT_PMAC_RX_OK_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_BAD_BYTES_CNT */
-#define DEV5G_PMAC_RX_BAD_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 48, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_BAD_BYTES_CNT */
+#define DEV5G_PMAC_RX_BAD_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 48, 0, 1, \
+ 4)
-/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_BAD_BYTES_MSB_CNT */
-#define DEV5G_PMAC_RX_BAD_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 52, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:PMAC_RX_BAD_BYTES_MSB_CNT */
+#define DEV5G_PMAC_RX_BAD_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 52, 0, 1, \
+ 4)
#define DEV5G_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT_SET(x)\
@@ -3825,13 +4235,15 @@ enum sparx5_target {
#define DEV5G_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_PMAC_RX_BAD_BYTES_MSB_CNT_PMAC_RX_BAD_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_STATISTICS_40BIT:PMAC_TX_OK_BYTES_CNT */
-#define DEV5G_PMAC_TX_OK_BYTES_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 56, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:PMAC_TX_OK_BYTES_CNT */
+#define DEV5G_PMAC_TX_OK_BYTES_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 56, 0, 1, \
+ 4)
-/* DEV10G:DEV_STATISTICS_40BIT:PMAC_TX_OK_BYTES_MSB_CNT */
-#define DEV5G_PMAC_TX_OK_BYTES_MSB_CNT(t) __REG(TARGET_DEV5G,\
- t, 13, 372, 0, 1, 64, 60, 0, 1, 4)
+/* DEV10G:DEV_STATISTICS_40BIT:PMAC_TX_OK_BYTES_MSB_CNT */
+#define DEV5G_PMAC_TX_OK_BYTES_MSB_CNT(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 372, 0, 1, 64, 60, 0, 1, \
+ 4)
#define DEV5G_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT GENMASK(7, 0)
#define DEV5G_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT_SET(x)\
@@ -3839,9 +4251,10 @@ enum sparx5_target {
#define DEV5G_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT_GET(x)\
FIELD_GET(DEV5G_PMAC_TX_OK_BYTES_MSB_CNT_PMAC_TX_OK_BYTES_MSB_CNT, x)
-/* DEV10G:DEV_CFG_STATUS:DEV_RST_CTRL */
-#define DEV5G_DEV_RST_CTRL(t) __REG(TARGET_DEV5G,\
- t, 13, 436, 0, 1, 52, 0, 0, 1, 4)
+/* DEV10G:DEV_CFG_STATUS:DEV_RST_CTRL */
+#define DEV5G_DEV_RST_CTRL(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 436, 0, 1, 52, 0, 0, 1, \
+ 4)
#define DEV5G_DEV_RST_CTRL_PARDET_MODE_ENA BIT(28)
#define DEV5G_DEV_RST_CTRL_PARDET_MODE_ENA_SET(x)\
@@ -3897,9 +4310,14 @@ enum sparx5_target {
#define DEV5G_DEV_RST_CTRL_MAC_RX_RST_GET(x)\
FIELD_GET(DEV5G_DEV_RST_CTRL_MAC_RX_RST, x)
-/* DSM:RAM_CTRL:RAM_INIT */
-#define DSM_RAM_INIT __REG(TARGET_DSM,\
- 0, 1, 0, 0, 1, 4, 0, 0, 1, 4)
+/* DEV10G:DEV_CFG_STATUS:PTP_STAMPER_CFG */
+#define DEV5G_PTP_STAMPER_CFG(t) \
+ __REG(TARGET_DEV5G, t, regs->tsize[TC_DEV5G], 436, 0, 1, 52, 20, 0, 1, \
+ 4)
+
+/* DSM:RAM_CTRL:RAM_INIT */
+#define DSM_RAM_INIT \
+ __REG(TARGET_DSM, 0, 1, 0, 0, 1, 4, 0, 0, 1, 4)
#define DSM_RAM_INIT_RAM_INIT BIT(1)
#define DSM_RAM_INIT_RAM_INIT_SET(x)\
@@ -3913,9 +4331,10 @@ enum sparx5_target {
#define DSM_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(DSM_RAM_INIT_RAM_CFG_HOOK, x)
-/* DSM:CFG:BUF_CFG */
-#define DSM_BUF_CFG(r) __REG(TARGET_DSM,\
- 0, 1, 20, 0, 1, 3528, 0, r, 67, 4)
+/* DSM:CFG:BUF_CFG */
+#define DSM_BUF_CFG(r) \
+ __REG(TARGET_DSM, 0, 1, 20, 0, 1, 3528, 0, r, \
+ regs->rcnt[RC_DSM_BUF_CFG], 4)
#define DSM_BUF_CFG_CSC_STAT_DIS BIT(13)
#define DSM_BUF_CFG_CSC_STAT_DIS_SET(x)\
@@ -3941,9 +4360,10 @@ enum sparx5_target {
#define DSM_BUF_CFG_UNDERFLOW_WATCHDOG_TIMEOUT_GET(x)\
FIELD_GET(DSM_BUF_CFG_UNDERFLOW_WATCHDOG_TIMEOUT, x)
-/* DSM:CFG:DEV_TX_STOP_WM_CFG */
-#define DSM_DEV_TX_STOP_WM_CFG(r) __REG(TARGET_DSM,\
- 0, 1, 20, 0, 1, 3528, 1360, r, 67, 4)
+/* DSM:CFG:DEV_TX_STOP_WM_CFG */
+#define DSM_DEV_TX_STOP_WM_CFG(r) \
+ __REG(TARGET_DSM, 0, 1, 20, 0, 1, 3528, 1360, r, \
+ regs->rcnt[RC_DSM_DEV_TX_STOP_WM_CFG], 4)
#define DSM_DEV_TX_STOP_WM_CFG_FAST_STARTUP_ENA BIT(9)
#define DSM_DEV_TX_STOP_WM_CFG_FAST_STARTUP_ENA_SET(x)\
@@ -3969,9 +4389,10 @@ enum sparx5_target {
#define DSM_DEV_TX_STOP_WM_CFG_DEV_TX_CNT_CLR_GET(x)\
FIELD_GET(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_CNT_CLR, x)
-/* DSM:CFG:RX_PAUSE_CFG */
-#define DSM_RX_PAUSE_CFG(r) __REG(TARGET_DSM,\
- 0, 1, 20, 0, 1, 3528, 1628, r, 67, 4)
+/* DSM:CFG:RX_PAUSE_CFG */
+#define DSM_RX_PAUSE_CFG(r) \
+ __REG(TARGET_DSM, 0, 1, 20, 0, 1, 3528, 1628, r, \
+ regs->rcnt[RC_DSM_RX_PAUSE_CFG], 4)
#define DSM_RX_PAUSE_CFG_RX_PAUSE_EN BIT(1)
#define DSM_RX_PAUSE_CFG_RX_PAUSE_EN_SET(x)\
@@ -3985,9 +4406,10 @@ enum sparx5_target {
#define DSM_RX_PAUSE_CFG_FC_OBEY_LOCAL_GET(x)\
FIELD_GET(DSM_RX_PAUSE_CFG_FC_OBEY_LOCAL, x)
-/* DSM:CFG:MAC_CFG */
-#define DSM_MAC_CFG(r) __REG(TARGET_DSM,\
- 0, 1, 20, 0, 1, 3528, 2432, r, 67, 4)
+/* DSM:CFG:MAC_CFG */
+#define DSM_MAC_CFG(r) \
+ __REG(TARGET_DSM, 0, 1, 20, 0, 1, 3528, 2432, r, \
+ regs->rcnt[RC_DSM_MAC_CFG], 4)
#define DSM_MAC_CFG_TX_PAUSE_VAL GENMASK(31, 16)
#define DSM_MAC_CFG_TX_PAUSE_VAL_SET(x)\
@@ -4013,9 +4435,10 @@ enum sparx5_target {
#define DSM_MAC_CFG_TX_PAUSE_XON_XOFF_GET(x)\
FIELD_GET(DSM_MAC_CFG_TX_PAUSE_XON_XOFF, x)
-/* DSM:CFG:MAC_ADDR_BASE_HIGH_CFG */
-#define DSM_MAC_ADDR_BASE_HIGH_CFG(r) __REG(TARGET_DSM,\
- 0, 1, 20, 0, 1, 3528, 2700, r, 65, 4)
+/* DSM:CFG:MAC_ADDR_BASE_HIGH_CFG */
+#define DSM_MAC_ADDR_BASE_HIGH_CFG(r) \
+ __REG(TARGET_DSM, 0, 1, 20, 0, 1, 3528, 2700, r, \
+ regs->rcnt[RC_DSM_MAC_ADDR_BASE_HIGH_CFG], 4)
#define DSM_MAC_ADDR_BASE_HIGH_CFG_MAC_ADDR_HIGH GENMASK(23, 0)
#define DSM_MAC_ADDR_BASE_HIGH_CFG_MAC_ADDR_HIGH_SET(x)\
@@ -4023,9 +4446,10 @@ enum sparx5_target {
#define DSM_MAC_ADDR_BASE_HIGH_CFG_MAC_ADDR_HIGH_GET(x)\
FIELD_GET(DSM_MAC_ADDR_BASE_HIGH_CFG_MAC_ADDR_HIGH, x)
-/* DSM:CFG:MAC_ADDR_BASE_LOW_CFG */
-#define DSM_MAC_ADDR_BASE_LOW_CFG(r) __REG(TARGET_DSM,\
- 0, 1, 20, 0, 1, 3528, 2960, r, 65, 4)
+/* DSM:CFG:MAC_ADDR_BASE_LOW_CFG */
+#define DSM_MAC_ADDR_BASE_LOW_CFG(r) \
+ __REG(TARGET_DSM, 0, 1, 20, 0, 1, 3528, 2960, r, \
+ regs->rcnt[RC_DSM_MAC_ADDR_BASE_LOW_CFG], 4)
#define DSM_MAC_ADDR_BASE_LOW_CFG_MAC_ADDR_LOW GENMASK(23, 0)
#define DSM_MAC_ADDR_BASE_LOW_CFG_MAC_ADDR_LOW_SET(x)\
@@ -4033,9 +4457,10 @@ enum sparx5_target {
#define DSM_MAC_ADDR_BASE_LOW_CFG_MAC_ADDR_LOW_GET(x)\
FIELD_GET(DSM_MAC_ADDR_BASE_LOW_CFG_MAC_ADDR_LOW, x)
-/* DSM:CFG:TAXI_CAL_CFG */
-#define DSM_TAXI_CAL_CFG(r) __REG(TARGET_DSM,\
- 0, 1, 20, 0, 1, 3528, 3224, r, 9, 4)
+/* DSM:CFG:TAXI_CAL_CFG */
+#define DSM_TAXI_CAL_CFG(r) \
+ __REG(TARGET_DSM, 0, 1, 20, 0, 1, 3528, 3224, r, \
+ regs->rcnt[RC_DSM_TAXI_CAL_CFG], 4)
#define DSM_TAXI_CAL_CFG_CAL_IDX GENMASK(20, 15)
#define DSM_TAXI_CAL_CFG_CAL_IDX_SET(x)\
@@ -4067,9 +4492,31 @@ enum sparx5_target {
#define DSM_TAXI_CAL_CFG_CAL_PGM_ENA_GET(x)\
FIELD_GET(DSM_TAXI_CAL_CFG_CAL_PGM_ENA, x)
-/* EACL:ES2_KEY_SELECT_PROFILE:VCAP_ES2_KEY_SEL */
-#define EACL_VCAP_ES2_KEY_SEL(g, r) __REG(TARGET_EACL,\
- 0, 1, 149504, g, 138, 8, 0, r, 2, 4)
+/* LAN969X ONLY */
+#define DSM_TAXI_CAL_CFG_CAL_SEL_STAT BIT(23)
+#define DSM_TAXI_CAL_CFG_CAL_SEL_STAT_SET(x)\
+ FIELD_PREP(DSM_TAXI_CAL_CFG_CAL_SEL_STAT, x)
+#define DSM_TAXI_CAL_CFG_CAL_SEL_STAT_GET(x)\
+ FIELD_GET(DSM_TAXI_CAL_CFG_CAL_SEL_STAT, x)
+
+/* LAN969X ONLY */
+#define DSM_TAXI_CAL_CFG_CAL_SWITCH BIT(22)
+#define DSM_TAXI_CAL_CFG_CAL_SWITCH_SET(x)\
+ FIELD_PREP(DSM_TAXI_CAL_CFG_CAL_SWITCH, x)
+#define DSM_TAXI_CAL_CFG_CAL_SWITCH_GET(x)\
+ FIELD_GET(DSM_TAXI_CAL_CFG_CAL_SWITCH, x)
+
+/* LAN969X ONLY */
+#define DSM_TAXI_CAL_CFG_CAL_PGM_SEL BIT(21)
+#define DSM_TAXI_CAL_CFG_CAL_PGM_SEL_SET(x)\
+ FIELD_PREP(DSM_TAXI_CAL_CFG_CAL_PGM_SEL, x)
+#define DSM_TAXI_CAL_CFG_CAL_PGM_SEL_GET(x)\
+ FIELD_GET(DSM_TAXI_CAL_CFG_CAL_PGM_SEL, x)
+
+/* EACL:ES2_KEY_SELECT_PROFILE:VCAP_ES2_KEY_SEL */
+#define EACL_VCAP_ES2_KEY_SEL(g, r) \
+ __REG(TARGET_EACL, 0, 1, regs->gaddr[GA_EACL_ES2_KEY_SELECT_PROFILE], \
+ g, regs->gcnt[GC_EACL_ES2_KEY_SELECT_PROFILE], 8, 0, r, 2, 4)
#define EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL GENMASK(7, 5)
#define EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(x)\
@@ -4095,13 +4542,15 @@ enum sparx5_target {
#define EACL_VCAP_ES2_KEY_SEL_KEY_ENA_GET(x)\
FIELD_GET(EACL_VCAP_ES2_KEY_SEL_KEY_ENA, x)
-/* EACL:CNT_TBL:ES2_CNT */
-#define EACL_ES2_CNT(g) __REG(TARGET_EACL,\
- 0, 1, 122880, g, 2048, 4, 0, 0, 1, 4)
+/* EACL:CNT_TBL:ES2_CNT */
+#define EACL_ES2_CNT(g) \
+ __REG(TARGET_EACL, 0, 1, regs->gaddr[GA_EACL_CNT_TBL], g, \
+ regs->gcnt[GC_EACL_CNT_TBL], 4, 0, 0, 1, 4)
-/* EACL:POL_CFG:POL_EACL_CFG */
-#define EACL_POL_EACL_CFG __REG(TARGET_EACL,\
- 0, 1, 150608, 0, 1, 780, 768, 0, 1, 4)
+/* EACL:POL_CFG:POL_EACL_CFG */
+#define EACL_POL_EACL_CFG \
+ __REG(TARGET_EACL, 0, 1, regs->gaddr[GA_EACL_POL_CFG], 0, 1, 780, 768, \
+ 0, 1, 4)
#define EACL_POL_EACL_CFG_EACL_CNT_MARKED_AS_DROPPED BIT(5)
#define EACL_POL_EACL_CFG_EACL_CNT_MARKED_AS_DROPPED_SET(x)\
@@ -4139,9 +4588,10 @@ enum sparx5_target {
#define EACL_POL_EACL_CFG_EACL_FORCE_INIT_GET(x)\
FIELD_GET(EACL_POL_EACL_CFG_EACL_FORCE_INIT, x)
-/* EACL:ES2_STICKY:SEC_LOOKUP_STICKY */
-#define EACL_SEC_LOOKUP_STICKY(r) __REG(TARGET_EACL,\
- 0, 1, 118696, 0, 1, 8, 0, r, 2, 4)
+/* EACL:ES2_STICKY:SEC_LOOKUP_STICKY */
+#define EACL_SEC_LOOKUP_STICKY(r) \
+ __REG(TARGET_EACL, 0, 1, regs->gaddr[GA_EACL_ES2_STICKY], 0, 1, 8, 0, \
+ r, 2, 4)
#define EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP_7TUPLE_STICKY BIT(7)
#define EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP_7TUPLE_STICKY_SET(x)\
@@ -4191,9 +4641,10 @@ enum sparx5_target {
#define EACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY_GET(x)\
FIELD_GET(EACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY, x)
-/* EACL:RAM_CTRL:RAM_INIT */
-#define EACL_RAM_INIT __REG(TARGET_EACL,\
- 0, 1, 118736, 0, 1, 4, 0, 0, 1, 4)
+/* EACL:RAM_CTRL:RAM_INIT */
+#define EACL_RAM_INIT \
+ __REG(TARGET_EACL, 0, 1, regs->gaddr[GA_EACL_RAM_CTRL], 0, 1, 4, 0, 0, \
+ 1, 4)
#define EACL_RAM_INIT_RAM_INIT BIT(1)
#define EACL_RAM_INIT_RAM_INIT_SET(x)\
@@ -4207,9 +4658,10 @@ enum sparx5_target {
#define EACL_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(EACL_RAM_INIT_RAM_CFG_HOOK, x)
-/* FDMA:FDMA:FDMA_CH_ACTIVATE */
-#define FDMA_CH_ACTIVATE __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 0, 0, 1, 4)
+/* FDMA:FDMA:FDMA_CH_ACTIVATE */
+#define FDMA_CH_ACTIVATE \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 0, 0, 1, \
+ 4)
#define FDMA_CH_ACTIVATE_CH_ACTIVATE GENMASK(7, 0)
#define FDMA_CH_ACTIVATE_CH_ACTIVATE_SET(x)\
@@ -4217,9 +4669,10 @@ enum sparx5_target {
#define FDMA_CH_ACTIVATE_CH_ACTIVATE_GET(x)\
FIELD_GET(FDMA_CH_ACTIVATE_CH_ACTIVATE, x)
-/* FDMA:FDMA:FDMA_CH_RELOAD */
-#define FDMA_CH_RELOAD __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 4, 0, 1, 4)
+/* FDMA:FDMA:FDMA_CH_RELOAD */
+#define FDMA_CH_RELOAD \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 4, 0, 1, \
+ 4)
#define FDMA_CH_RELOAD_CH_RELOAD GENMASK(7, 0)
#define FDMA_CH_RELOAD_CH_RELOAD_SET(x)\
@@ -4227,9 +4680,10 @@ enum sparx5_target {
#define FDMA_CH_RELOAD_CH_RELOAD_GET(x)\
FIELD_GET(FDMA_CH_RELOAD_CH_RELOAD, x)
-/* FDMA:FDMA:FDMA_CH_DISABLE */
-#define FDMA_CH_DISABLE __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 8, 0, 1, 4)
+/* FDMA:FDMA:FDMA_CH_DISABLE */
+#define FDMA_CH_DISABLE \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 8, 0, 1, \
+ 4)
#define FDMA_CH_DISABLE_CH_DISABLE GENMASK(7, 0)
#define FDMA_CH_DISABLE_CH_DISABLE_SET(x)\
@@ -4237,49 +4691,58 @@ enum sparx5_target {
#define FDMA_CH_DISABLE_CH_DISABLE_GET(x)\
FIELD_GET(FDMA_CH_DISABLE_CH_DISABLE, x)
-/* FDMA:FDMA:FDMA_DCB_LLP */
-#define FDMA_DCB_LLP(r) __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 52, r, 8, 4)
-
-/* FDMA:FDMA:FDMA_DCB_LLP1 */
-#define FDMA_DCB_LLP1(r) __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 84, r, 8, 4)
-
-/* FDMA:FDMA:FDMA_DCB_LLP_PREV */
-#define FDMA_DCB_LLP_PREV(r) __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 116, r, 8, 4)
-
-/* FDMA:FDMA:FDMA_DCB_LLP_PREV1 */
-#define FDMA_DCB_LLP_PREV1(r) __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 148, r, 8, 4)
-
-/* FDMA:FDMA:FDMA_CH_CFG */
-#define FDMA_CH_CFG(r) __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 224, r, 8, 4)
-
-#define FDMA_CH_CFG_CH_XTR_STATUS_MODE BIT(7)
+/* FDMA:FDMA:FDMA_DCB_LLP */
+#define FDMA_DCB_LLP(r) \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 52, r, 8, \
+ 4)
+
+/* FDMA:FDMA:FDMA_DCB_LLP1 */
+#define FDMA_DCB_LLP1(r) \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 84, r, 8, \
+ 4)
+
+/* FDMA:FDMA:FDMA_DCB_LLP_PREV */
+#define FDMA_DCB_LLP_PREV(r) \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 116, r, 8,\
+ 4)
+
+/* FDMA:FDMA:FDMA_DCB_LLP_PREV1 */
+#define FDMA_DCB_LLP_PREV1(r) \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 148, r, 8,\
+ 4)
+
+/* FDMA:FDMA:FDMA_CH_CFG */
+#define FDMA_CH_CFG(r) \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 224, r, 8,\
+ 4)
+
+#define FDMA_CH_CFG_CH_XTR_STATUS_MODE\
+ BIT(regs->fpos[FP_FDMA_CH_CFG_CH_XTR_STATUS_MODE])
#define FDMA_CH_CFG_CH_XTR_STATUS_MODE_SET(x)\
- FIELD_PREP(FDMA_CH_CFG_CH_XTR_STATUS_MODE, x)
+ spx5_field_prep(FDMA_CH_CFG_CH_XTR_STATUS_MODE, x)
#define FDMA_CH_CFG_CH_XTR_STATUS_MODE_GET(x)\
- FIELD_GET(FDMA_CH_CFG_CH_XTR_STATUS_MODE, x)
+ spx5_field_get(FDMA_CH_CFG_CH_XTR_STATUS_MODE, x)
-#define FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY BIT(6)
+#define FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY\
+ BIT(regs->fpos[FP_FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY])
#define FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(x)\
- FIELD_PREP(FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY, x)
+ spx5_field_prep(FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY, x)
#define FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_GET(x)\
- FIELD_GET(FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY, x)
+ spx5_field_get(FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY, x)
-#define FDMA_CH_CFG_CH_INJ_PORT BIT(5)
+#define FDMA_CH_CFG_CH_INJ_PORT\
+ BIT(regs->fpos[FP_FDMA_CH_CFG_CH_INJ_PORT])
#define FDMA_CH_CFG_CH_INJ_PORT_SET(x)\
- FIELD_PREP(FDMA_CH_CFG_CH_INJ_PORT, x)
+ spx5_field_prep(FDMA_CH_CFG_CH_INJ_PORT, x)
#define FDMA_CH_CFG_CH_INJ_PORT_GET(x)\
- FIELD_GET(FDMA_CH_CFG_CH_INJ_PORT, x)
+ spx5_field_get(FDMA_CH_CFG_CH_INJ_PORT, x)
-#define FDMA_CH_CFG_CH_DCB_DB_CNT GENMASK(4, 1)
+#define FDMA_CH_CFG_CH_DCB_DB_CNT\
+ GENMASK(regs->fsize[FW_FDMA_CH_CFG_CH_DCB_DB_CNT] + 1 - 1, 1)
#define FDMA_CH_CFG_CH_DCB_DB_CNT_SET(x)\
- FIELD_PREP(FDMA_CH_CFG_CH_DCB_DB_CNT, x)
+ spx5_field_prep(FDMA_CH_CFG_CH_DCB_DB_CNT, x)
#define FDMA_CH_CFG_CH_DCB_DB_CNT_GET(x)\
- FIELD_GET(FDMA_CH_CFG_CH_DCB_DB_CNT, x)
+ spx5_field_get(FDMA_CH_CFG_CH_DCB_DB_CNT, x)
#define FDMA_CH_CFG_CH_MEM BIT(0)
#define FDMA_CH_CFG_CH_MEM_SET(x)\
@@ -4287,9 +4750,10 @@ enum sparx5_target {
#define FDMA_CH_CFG_CH_MEM_GET(x)\
FIELD_GET(FDMA_CH_CFG_CH_MEM, x)
-/* FDMA:FDMA:FDMA_CH_TRANSLATE */
-#define FDMA_CH_TRANSLATE(r) __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 256, r, 8, 4)
+/* FDMA:FDMA:FDMA_CH_TRANSLATE */
+#define FDMA_CH_TRANSLATE(r) \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 256, r, 8,\
+ 4)
#define FDMA_CH_TRANSLATE_OFFSET GENMASK(15, 0)
#define FDMA_CH_TRANSLATE_OFFSET_SET(x)\
@@ -4297,9 +4761,10 @@ enum sparx5_target {
#define FDMA_CH_TRANSLATE_OFFSET_GET(x)\
FIELD_GET(FDMA_CH_TRANSLATE_OFFSET, x)
-/* FDMA:FDMA:FDMA_XTR_CFG */
-#define FDMA_XTR_CFG __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 364, 0, 1, 4)
+/* FDMA:FDMA:FDMA_XTR_CFG */
+#define FDMA_XTR_CFG \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 364, 0, 1,\
+ 4)
#define FDMA_XTR_CFG_XTR_FIFO_WM GENMASK(15, 11)
#define FDMA_XTR_CFG_XTR_FIFO_WM_SET(x)\
@@ -4313,9 +4778,10 @@ enum sparx5_target {
#define FDMA_XTR_CFG_XTR_ARB_SAT_GET(x)\
FIELD_GET(FDMA_XTR_CFG_XTR_ARB_SAT, x)
-/* FDMA:FDMA:FDMA_PORT_CTRL */
-#define FDMA_PORT_CTRL(r) __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 376, r, 2, 4)
+/* FDMA:FDMA:FDMA_PORT_CTRL */
+#define FDMA_PORT_CTRL(r) \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 376, r, 2,\
+ 4)
#define FDMA_PORT_CTRL_INJ_STOP BIT(4)
#define FDMA_PORT_CTRL_INJ_STOP_SET(x)\
@@ -4347,9 +4813,10 @@ enum sparx5_target {
#define FDMA_PORT_CTRL_XTR_BUF_RST_GET(x)\
FIELD_GET(FDMA_PORT_CTRL_XTR_BUF_RST, x)
-/* FDMA:FDMA:FDMA_INTR_DCB */
-#define FDMA_INTR_DCB __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 384, 0, 1, 4)
+/* FDMA:FDMA:FDMA_INTR_DCB */
+#define FDMA_INTR_DCB \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 384, 0, 1,\
+ 4)
#define FDMA_INTR_DCB_INTR_DCB GENMASK(7, 0)
#define FDMA_INTR_DCB_INTR_DCB_SET(x)\
@@ -4357,9 +4824,10 @@ enum sparx5_target {
#define FDMA_INTR_DCB_INTR_DCB_GET(x)\
FIELD_GET(FDMA_INTR_DCB_INTR_DCB, x)
-/* FDMA:FDMA:FDMA_INTR_DCB_ENA */
-#define FDMA_INTR_DCB_ENA __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 388, 0, 1, 4)
+/* FDMA:FDMA:FDMA_INTR_DCB_ENA */
+#define FDMA_INTR_DCB_ENA \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 388, 0, 1,\
+ 4)
#define FDMA_INTR_DCB_ENA_INTR_DCB_ENA GENMASK(7, 0)
#define FDMA_INTR_DCB_ENA_INTR_DCB_ENA_SET(x)\
@@ -4367,9 +4835,10 @@ enum sparx5_target {
#define FDMA_INTR_DCB_ENA_INTR_DCB_ENA_GET(x)\
FIELD_GET(FDMA_INTR_DCB_ENA_INTR_DCB_ENA, x)
-/* FDMA:FDMA:FDMA_INTR_DB */
-#define FDMA_INTR_DB __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 392, 0, 1, 4)
+/* FDMA:FDMA:FDMA_INTR_DB */
+#define FDMA_INTR_DB \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 392, 0, 1,\
+ 4)
#define FDMA_INTR_DB_INTR_DB GENMASK(7, 0)
#define FDMA_INTR_DB_INTR_DB_SET(x)\
@@ -4377,9 +4846,10 @@ enum sparx5_target {
#define FDMA_INTR_DB_INTR_DB_GET(x)\
FIELD_GET(FDMA_INTR_DB_INTR_DB, x)
-/* FDMA:FDMA:FDMA_INTR_DB_ENA */
-#define FDMA_INTR_DB_ENA __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 396, 0, 1, 4)
+/* FDMA:FDMA:FDMA_INTR_DB_ENA */
+#define FDMA_INTR_DB_ENA \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 396, 0, 1,\
+ 4)
#define FDMA_INTR_DB_ENA_INTR_DB_ENA GENMASK(7, 0)
#define FDMA_INTR_DB_ENA_INTR_DB_ENA_SET(x)\
@@ -4387,9 +4857,10 @@ enum sparx5_target {
#define FDMA_INTR_DB_ENA_INTR_DB_ENA_GET(x)\
FIELD_GET(FDMA_INTR_DB_ENA_INTR_DB_ENA, x)
-/* FDMA:FDMA:FDMA_INTR_ERR */
-#define FDMA_INTR_ERR __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 400, 0, 1, 4)
+/* FDMA:FDMA:FDMA_INTR_ERR */
+#define FDMA_INTR_ERR \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 400, 0, 1,\
+ 4)
#define FDMA_INTR_ERR_INTR_PORT_ERR GENMASK(9, 8)
#define FDMA_INTR_ERR_INTR_PORT_ERR_SET(x)\
@@ -4403,9 +4874,10 @@ enum sparx5_target {
#define FDMA_INTR_ERR_INTR_CH_ERR_GET(x)\
FIELD_GET(FDMA_INTR_ERR_INTR_CH_ERR, x)
-/* FDMA:FDMA:FDMA_ERRORS */
-#define FDMA_ERRORS __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 412, 0, 1, 4)
+/* FDMA:FDMA:FDMA_ERRORS */
+#define FDMA_ERRORS \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 412, 0, 1,\
+ 4)
#define FDMA_ERRORS_ERR_XTR_WR GENMASK(31, 30)
#define FDMA_ERRORS_ERR_XTR_WR_SET(x)\
@@ -4455,9 +4927,10 @@ enum sparx5_target {
#define FDMA_ERRORS_ERR_CH_WR_GET(x)\
FIELD_GET(FDMA_ERRORS_ERR_CH_WR, x)
-/* FDMA:FDMA:FDMA_ERRORS_2 */
-#define FDMA_ERRORS_2 __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 416, 0, 1, 4)
+/* FDMA:FDMA:FDMA_ERRORS_2 */
+#define FDMA_ERRORS_2 \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 416, 0, 1,\
+ 4)
#define FDMA_ERRORS_2_ERR_XTR_FRAG GENMASK(1, 0)
#define FDMA_ERRORS_2_ERR_XTR_FRAG_SET(x)\
@@ -4465,9 +4938,10 @@ enum sparx5_target {
#define FDMA_ERRORS_2_ERR_XTR_FRAG_GET(x)\
FIELD_GET(FDMA_ERRORS_2_ERR_XTR_FRAG, x)
-/* FDMA:FDMA:FDMA_CTRL */
-#define FDMA_CTRL __REG(TARGET_FDMA,\
- 0, 1, 8, 0, 1, 428, 424, 0, 1, 4)
+/* FDMA:FDMA:FDMA_CTRL */
+#define FDMA_CTRL \
+ __REG(TARGET_FDMA, 0, 1, 8, 0, 1, regs->gsize[GW_FDMA_FDMA], 424, 0, 1,\
+ 4)
#define FDMA_CTRL_NRESET BIT(0)
#define FDMA_CTRL_NRESET_SET(x)\
@@ -4475,9 +4949,10 @@ enum sparx5_target {
#define FDMA_CTRL_NRESET_GET(x)\
FIELD_GET(FDMA_CTRL_NRESET, x)
-/* DEVCPU_GCB:CHIP_REGS:CHIP_ID */
-#define GCB_CHIP_ID __REG(TARGET_GCB,\
- 0, 1, 0, 0, 1, 424, 0, 0, 1, 4)
+/* DEVCPU_GCB:CHIP_REGS:CHIP_ID */
+#define GCB_CHIP_ID \
+ __REG(TARGET_GCB, 0, 1, 0, 0, 1, regs->gsize[GW_GCB_CHIP_REGS], 0, 0, \
+ 1, 4)
#define GCB_CHIP_ID_REV_ID GENMASK(31, 28)
#define GCB_CHIP_ID_REV_ID_SET(x)\
@@ -4503,10 +4978,12 @@ enum sparx5_target {
#define GCB_CHIP_ID_ONE_GET(x)\
FIELD_GET(GCB_CHIP_ID_ONE, x)
-/* DEVCPU_GCB:CHIP_REGS:SOFT_RST */
-#define GCB_SOFT_RST __REG(TARGET_GCB,\
- 0, 1, 0, 0, 1, 424, 8, 0, 1, 4)
+/* DEVCPU_GCB:CHIP_REGS:SOFT_RST */
+#define GCB_SOFT_RST \
+ __REG(TARGET_GCB, 0, 1, 0, 0, 1, regs->gsize[GW_GCB_CHIP_REGS], \
+ regs->raddr[RA_GCB_SOFT_RST], 0, 1, 4)
+/* SPARX5 ONLY */
#define GCB_SOFT_RST_SOFT_NON_CFG_RST BIT(2)
#define GCB_SOFT_RST_SOFT_NON_CFG_RST_SET(x)\
FIELD_PREP(GCB_SOFT_RST_SOFT_NON_CFG_RST, x)
@@ -4525,9 +5002,11 @@ enum sparx5_target {
#define GCB_SOFT_RST_SOFT_CHIP_RST_GET(x)\
FIELD_GET(GCB_SOFT_RST_SOFT_CHIP_RST, x)
-/* DEVCPU_GCB:CHIP_REGS:HW_SGPIO_SD_CFG */
-#define GCB_HW_SGPIO_SD_CFG __REG(TARGET_GCB,\
- 0, 1, 0, 0, 1, 424, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* DEVCPU_GCB:CHIP_REGS:HW_SGPIO_SD_CFG */
+#define GCB_HW_SGPIO_SD_CFG \
+ __REG(TARGET_GCB, 0, 1, 0, 0, 1, regs->gsize[GW_GCB_CHIP_REGS], 20, 0, \
+ 1, 4)
#define GCB_HW_SGPIO_SD_CFG_SD_HIGH_ENA BIT(1)
#define GCB_HW_SGPIO_SD_CFG_SD_HIGH_ENA_SET(x)\
@@ -4541,19 +5020,23 @@ enum sparx5_target {
#define GCB_HW_SGPIO_SD_CFG_SD_MAP_SEL_GET(x)\
FIELD_GET(GCB_HW_SGPIO_SD_CFG_SD_MAP_SEL, x)
-/* DEVCPU_GCB:CHIP_REGS:HW_SGPIO_TO_SD_MAP_CFG */
-#define GCB_HW_SGPIO_TO_SD_MAP_CFG(r) __REG(TARGET_GCB,\
- 0, 1, 0, 0, 1, 424, 24, r, 65, 4)
+/* DEVCPU_GCB:CHIP_REGS:HW_SGPIO_TO_SD_MAP_CFG */
+#define GCB_HW_SGPIO_TO_SD_MAP_CFG(r) \
+ __REG(TARGET_GCB, 0, 1, 0, 0, 1, regs->gsize[GW_GCB_CHIP_REGS], \
+ regs->raddr[RA_GCB_HW_SGPIO_TO_SD_MAP_CFG], r, \
+ regs->rcnt[RC_GCB_HW_SGPIO_TO_SD_MAP_CFG], 4)
-#define GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL GENMASK(8, 0)
+#define GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL\
+ GENMASK(regs->fsize[FW_GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL] + 0 - 1, 0)
#define GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL_SET(x)\
- FIELD_PREP(GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL, x)
+ spx5_field_prep(GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL, x)
#define GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL_GET(x)\
- FIELD_GET(GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL, x)
+ spx5_field_get(GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL, x)
-/* DEVCPU_GCB:SIO_CTRL:SIO_CLOCK */
-#define GCB_SIO_CLOCK(g) __REG(TARGET_GCB,\
- 0, 1, 876, g, 3, 280, 20, 0, 1, 4)
+/* DEVCPU_GCB:SIO_CTRL:SIO_CLOCK */
+#define GCB_SIO_CLOCK(g) \
+ __REG(TARGET_GCB, 0, 1, regs->gaddr[GA_GCB_SIO_CTRL], g, \
+ regs->gcnt[GC_GCB_SIO_CTRL], 280, 20, 0, 1, 4)
#define GCB_SIO_CLOCK_SIO_CLK_FREQ GENMASK(19, 8)
#define GCB_SIO_CLOCK_SIO_CLK_FREQ_SET(x)\
@@ -4567,9 +5050,10 @@ enum sparx5_target {
#define GCB_SIO_CLOCK_SYS_CLK_PERIOD_GET(x)\
FIELD_GET(GCB_SIO_CLOCK_SYS_CLK_PERIOD, x)
-/* HSCH:HSCH_CFG:CIR_CFG */
-#define HSCH_CIR_CFG(g) __REG(TARGET_HSCH,\
- 0, 1, 0, g, 5040, 32, 0, 0, 1, 4)
+/* HSCH:HSCH_CFG:CIR_CFG */
+#define HSCH_CIR_CFG(g) \
+ __REG(TARGET_HSCH, 0, 1, 0, g, regs->gcnt[GC_HSCH_HSCH_CFG], 32, 0, 0, \
+ 1, 4)
#define HSCH_CIR_CFG_CIR_RATE GENMASK(22, 6)
#define HSCH_CIR_CFG_CIR_RATE_SET(x)\
@@ -4583,9 +5067,10 @@ enum sparx5_target {
#define HSCH_CIR_CFG_CIR_BURST_GET(x)\
FIELD_GET(HSCH_CIR_CFG_CIR_BURST, x)
-/* HSCH:HSCH_CFG:EIR_CFG */
-#define HSCH_EIR_CFG(g) __REG(TARGET_HSCH,\
- 0, 1, 0, g, 5040, 32, 4, 0, 1, 4)
+/* HSCH:HSCH_CFG:EIR_CFG */
+#define HSCH_EIR_CFG(g) \
+ __REG(TARGET_HSCH, 0, 1, 0, g, regs->gcnt[GC_HSCH_HSCH_CFG], 32, 4, 0, \
+ 1, 4)
#define HSCH_EIR_CFG_EIR_RATE GENMASK(22, 6)
#define HSCH_EIR_CFG_EIR_RATE_SET(x)\
@@ -4599,15 +5084,17 @@ enum sparx5_target {
#define HSCH_EIR_CFG_EIR_BURST_GET(x)\
FIELD_GET(HSCH_EIR_CFG_EIR_BURST, x)
-/* HSCH:HSCH_CFG:SE_CFG */
-#define HSCH_SE_CFG(g) __REG(TARGET_HSCH,\
- 0, 1, 0, g, 5040, 32, 8, 0, 1, 4)
+/* HSCH:HSCH_CFG:SE_CFG */
+#define HSCH_SE_CFG(g) \
+ __REG(TARGET_HSCH, 0, 1, 0, g, regs->gcnt[GC_HSCH_HSCH_CFG], 32, 8, 0, \
+ 1, 4)
-#define HSCH_SE_CFG_SE_DWRR_CNT GENMASK(12, 6)
+#define HSCH_SE_CFG_SE_DWRR_CNT\
+ GENMASK(regs->fsize[FW_HSCH_SE_CFG_SE_DWRR_CNT] + 6 - 1, 6)
#define HSCH_SE_CFG_SE_DWRR_CNT_SET(x)\
- FIELD_PREP(HSCH_SE_CFG_SE_DWRR_CNT, x)
+ spx5_field_prep(HSCH_SE_CFG_SE_DWRR_CNT, x)
#define HSCH_SE_CFG_SE_DWRR_CNT_GET(x)\
- FIELD_GET(HSCH_SE_CFG_SE_DWRR_CNT, x)
+ spx5_field_get(HSCH_SE_CFG_SE_DWRR_CNT, x)
#define HSCH_SE_CFG_SE_AVB_ENA BIT(5)
#define HSCH_SE_CFG_SE_AVB_ENA_SET(x)\
@@ -4633,19 +5120,22 @@ enum sparx5_target {
#define HSCH_SE_CFG_SE_STOP_GET(x)\
FIELD_GET(HSCH_SE_CFG_SE_STOP, x)
-/* HSCH:HSCH_CFG:SE_CONNECT */
-#define HSCH_SE_CONNECT(g) __REG(TARGET_HSCH,\
- 0, 1, 0, g, 5040, 32, 12, 0, 1, 4)
+/* HSCH:HSCH_CFG:SE_CONNECT */
+#define HSCH_SE_CONNECT(g) \
+ __REG(TARGET_HSCH, 0, 1, 0, g, regs->gcnt[GC_HSCH_HSCH_CFG], 32, 12, 0,\
+ 1, 4)
-#define HSCH_SE_CONNECT_SE_LEAK_LINK GENMASK(15, 0)
+#define HSCH_SE_CONNECT_SE_LEAK_LINK\
+ GENMASK(regs->fsize[FW_HSCH_SE_CONNECT_SE_LEAK_LINK] + 0 - 1, 0)
#define HSCH_SE_CONNECT_SE_LEAK_LINK_SET(x)\
- FIELD_PREP(HSCH_SE_CONNECT_SE_LEAK_LINK, x)
+ spx5_field_prep(HSCH_SE_CONNECT_SE_LEAK_LINK, x)
#define HSCH_SE_CONNECT_SE_LEAK_LINK_GET(x)\
- FIELD_GET(HSCH_SE_CONNECT_SE_LEAK_LINK, x)
+ spx5_field_get(HSCH_SE_CONNECT_SE_LEAK_LINK, x)
-/* HSCH:HSCH_CFG:SE_DLB_SENSE */
-#define HSCH_SE_DLB_SENSE(g) __REG(TARGET_HSCH,\
- 0, 1, 0, g, 5040, 32, 16, 0, 1, 4)
+/* HSCH:HSCH_CFG:SE_DLB_SENSE */
+#define HSCH_SE_DLB_SENSE(g) \
+ __REG(TARGET_HSCH, 0, 1, 0, g, regs->gcnt[GC_HSCH_HSCH_CFG], 32, 16, 0,\
+ 1, 4)
#define HSCH_SE_DLB_SENSE_SE_DLB_PRIO GENMASK(12, 10)
#define HSCH_SE_DLB_SENSE_SE_DLB_PRIO_SET(x)\
@@ -4653,11 +5143,12 @@ enum sparx5_target {
#define HSCH_SE_DLB_SENSE_SE_DLB_PRIO_GET(x)\
FIELD_GET(HSCH_SE_DLB_SENSE_SE_DLB_PRIO, x)
-#define HSCH_SE_DLB_SENSE_SE_DLB_DPORT GENMASK(9, 3)
+#define HSCH_SE_DLB_SENSE_SE_DLB_DPORT\
+ GENMASK(regs->fsize[FW_HSCH_SE_DLB_SENSE_SE_DLB_DPORT] + 3 - 1, 3)
#define HSCH_SE_DLB_SENSE_SE_DLB_DPORT_SET(x)\
- FIELD_PREP(HSCH_SE_DLB_SENSE_SE_DLB_DPORT, x)
+ spx5_field_prep(HSCH_SE_DLB_SENSE_SE_DLB_DPORT, x)
#define HSCH_SE_DLB_SENSE_SE_DLB_DPORT_GET(x)\
- FIELD_GET(HSCH_SE_DLB_SENSE_SE_DLB_DPORT, x)
+ spx5_field_get(HSCH_SE_DLB_SENSE_SE_DLB_DPORT, x)
#define HSCH_SE_DLB_SENSE_SE_DLB_SE_ENA BIT(2)
#define HSCH_SE_DLB_SENSE_SE_DLB_SE_ENA_SET(x)\
@@ -4677,9 +5168,10 @@ enum sparx5_target {
#define HSCH_SE_DLB_SENSE_SE_DLB_DPORT_ENA_GET(x)\
FIELD_GET(HSCH_SE_DLB_SENSE_SE_DLB_DPORT_ENA, x)
-/* HSCH:HSCH_DWRR:DWRR_ENTRY */
-#define HSCH_DWRR_ENTRY(g) __REG(TARGET_HSCH,\
- 0, 1, 162816, g, 72, 4, 0, 0, 1, 4)
+/* HSCH:HSCH_DWRR:DWRR_ENTRY */
+#define HSCH_DWRR_ENTRY(g) \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_HSCH_DWRR], g, \
+ regs->gcnt[GC_HSCH_HSCH_DWRR], 4, 0, 0, 1, 4)
#define HSCH_DWRR_ENTRY_DWRR_COST GENMASK(24, 20)
#define HSCH_DWRR_ENTRY_DWRR_COST_SET(x)\
@@ -4693,15 +5185,17 @@ enum sparx5_target {
#define HSCH_DWRR_ENTRY_DWRR_BALANCE_GET(x)\
FIELD_GET(HSCH_DWRR_ENTRY_DWRR_BALANCE, x)
-/* HSCH:HSCH_MISC:HSCH_CFG_CFG */
-#define HSCH_HSCH_CFG_CFG __REG(TARGET_HSCH,\
- 0, 1, 163104, 0, 1, 648, 284, 0, 1, 4)
+/* HSCH:HSCH_MISC:HSCH_CFG_CFG */
+#define HSCH_HSCH_CFG_CFG \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_HSCH_MISC], 0, 1, 648, \
+ 284, 0, 1, 4)
-#define HSCH_HSCH_CFG_CFG_CFG_SE_IDX GENMASK(26, 14)
+#define HSCH_HSCH_CFG_CFG_CFG_SE_IDX\
+ GENMASK(regs->fsize[FW_HSCH_HSCH_CFG_CFG_CFG_SE_IDX] + 14 - 1, 14)
#define HSCH_HSCH_CFG_CFG_CFG_SE_IDX_SET(x)\
- FIELD_PREP(HSCH_HSCH_CFG_CFG_CFG_SE_IDX, x)
+ spx5_field_prep(HSCH_HSCH_CFG_CFG_CFG_SE_IDX, x)
#define HSCH_HSCH_CFG_CFG_CFG_SE_IDX_GET(x)\
- FIELD_GET(HSCH_HSCH_CFG_CFG_CFG_SE_IDX, x)
+ spx5_field_get(HSCH_HSCH_CFG_CFG_CFG_SE_IDX, x)
#define HSCH_HSCH_CFG_CFG_HSCH_LAYER GENMASK(13, 12)
#define HSCH_HSCH_CFG_CFG_HSCH_LAYER_SET(x)\
@@ -4715,9 +5209,11 @@ enum sparx5_target {
#define HSCH_HSCH_CFG_CFG_CSR_GRANT_GET(x)\
FIELD_GET(HSCH_HSCH_CFG_CFG_CSR_GRANT, x)
-/* HSCH:HSCH_MISC:SYS_CLK_PER */
-#define HSCH_SYS_CLK_PER __REG(TARGET_HSCH,\
- 0, 1, 163104, 0, 1, 648, 640, 0, 1, 4)
+/* SPARX5 ONLY */
+/* HSCH:HSCH_MISC:SYS_CLK_PER */
+#define HSCH_SYS_CLK_PER \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_HSCH_MISC], 0, 1, 648, \
+ 640, 0, 1, 4)
#define HSCH_SYS_CLK_PER_100PS GENMASK(7, 0)
#define HSCH_SYS_CLK_PER_100PS_SET(x)\
@@ -4725,9 +5221,10 @@ enum sparx5_target {
#define HSCH_SYS_CLK_PER_100PS_GET(x)\
FIELD_GET(HSCH_SYS_CLK_PER_100PS, x)
-/* HSCH:HSCH_LEAK_LISTS:HSCH_TIMER_CFG */
-#define HSCH_HSCH_TIMER_CFG(g, r) __REG(TARGET_HSCH,\
- 0, 1, 161664, g, 4, 32, 0, r, 4, 4)
+/* HSCH:HSCH_LEAK_LISTS:HSCH_TIMER_CFG */
+#define HSCH_HSCH_TIMER_CFG(g, r) \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_HSCH_LEAK_LISTS], g, 4, \
+ 32, 0, r, 4, 4)
#define HSCH_HSCH_TIMER_CFG_LEAK_TIME GENMASK(17, 0)
#define HSCH_HSCH_TIMER_CFG_LEAK_TIME_SET(x)\
@@ -4735,15 +5232,17 @@ enum sparx5_target {
#define HSCH_HSCH_TIMER_CFG_LEAK_TIME_GET(x)\
FIELD_GET(HSCH_HSCH_TIMER_CFG_LEAK_TIME, x)
-/* HSCH:HSCH_LEAK_LISTS:HSCH_LEAK_CFG */
-#define HSCH_HSCH_LEAK_CFG(g, r) __REG(TARGET_HSCH,\
- 0, 1, 161664, g, 4, 32, 16, r, 4, 4)
+/* HSCH:HSCH_LEAK_LISTS:HSCH_LEAK_CFG */
+#define HSCH_HSCH_LEAK_CFG(g, r) \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_HSCH_LEAK_LISTS], g, 4, \
+ 32, 16, r, 4, 4)
-#define HSCH_HSCH_LEAK_CFG_LEAK_FIRST GENMASK(16, 1)
+#define HSCH_HSCH_LEAK_CFG_LEAK_FIRST\
+ GENMASK(regs->fsize[FW_HSCH_HSCH_LEAK_CFG_LEAK_FIRST] + 1 - 1, 1)
#define HSCH_HSCH_LEAK_CFG_LEAK_FIRST_SET(x)\
- FIELD_PREP(HSCH_HSCH_LEAK_CFG_LEAK_FIRST, x)
+ spx5_field_prep(HSCH_HSCH_LEAK_CFG_LEAK_FIRST, x)
#define HSCH_HSCH_LEAK_CFG_LEAK_FIRST_GET(x)\
- FIELD_GET(HSCH_HSCH_LEAK_CFG_LEAK_FIRST, x)
+ spx5_field_get(HSCH_HSCH_LEAK_CFG_LEAK_FIRST, x)
#define HSCH_HSCH_LEAK_CFG_LEAK_ERR BIT(0)
#define HSCH_HSCH_LEAK_CFG_LEAK_ERR_SET(x)\
@@ -4751,9 +5250,10 @@ enum sparx5_target {
#define HSCH_HSCH_LEAK_CFG_LEAK_ERR_GET(x)\
FIELD_GET(HSCH_HSCH_LEAK_CFG_LEAK_ERR, x)
-/* HSCH:SYSTEM:FLUSH_CTRL */
-#define HSCH_FLUSH_CTRL __REG(TARGET_HSCH,\
- 0, 1, 184000, 0, 1, 312, 4, 0, 1, 4)
+/* HSCH:SYSTEM:FLUSH_CTRL */
+#define HSCH_FLUSH_CTRL \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_SYSTEM], 0, 1, 312, 4, 0, \
+ 1, 4)
#define HSCH_FLUSH_CTRL_FLUSH_ENA BIT(27)
#define HSCH_FLUSH_CTRL_FLUSH_ENA_SET(x)\
@@ -4773,11 +5273,12 @@ enum sparx5_target {
#define HSCH_FLUSH_CTRL_FLUSH_DST_GET(x)\
FIELD_GET(HSCH_FLUSH_CTRL_FLUSH_DST, x)
-#define HSCH_FLUSH_CTRL_FLUSH_PORT GENMASK(24, 18)
+#define HSCH_FLUSH_CTRL_FLUSH_PORT\
+ GENMASK(regs->fsize[FW_HSCH_FLUSH_CTRL_FLUSH_PORT] + 18 - 1, 18)
#define HSCH_FLUSH_CTRL_FLUSH_PORT_SET(x)\
- FIELD_PREP(HSCH_FLUSH_CTRL_FLUSH_PORT, x)
+ spx5_field_prep(HSCH_FLUSH_CTRL_FLUSH_PORT, x)
#define HSCH_FLUSH_CTRL_FLUSH_PORT_GET(x)\
- FIELD_GET(HSCH_FLUSH_CTRL_FLUSH_PORT, x)
+ spx5_field_get(HSCH_FLUSH_CTRL_FLUSH_PORT, x)
#define HSCH_FLUSH_CTRL_FLUSH_QUEUE BIT(17)
#define HSCH_FLUSH_CTRL_FLUSH_QUEUE_SET(x)\
@@ -4791,15 +5292,17 @@ enum sparx5_target {
#define HSCH_FLUSH_CTRL_FLUSH_SE_GET(x)\
FIELD_GET(HSCH_FLUSH_CTRL_FLUSH_SE, x)
-#define HSCH_FLUSH_CTRL_FLUSH_HIER GENMASK(15, 0)
+#define HSCH_FLUSH_CTRL_FLUSH_HIER\
+ GENMASK(regs->fsize[FW_HSCH_FLUSH_CTRL_FLUSH_HIER] + 0 - 1, 0)
#define HSCH_FLUSH_CTRL_FLUSH_HIER_SET(x)\
- FIELD_PREP(HSCH_FLUSH_CTRL_FLUSH_HIER, x)
+ spx5_field_prep(HSCH_FLUSH_CTRL_FLUSH_HIER, x)
#define HSCH_FLUSH_CTRL_FLUSH_HIER_GET(x)\
- FIELD_GET(HSCH_FLUSH_CTRL_FLUSH_HIER, x)
+ spx5_field_get(HSCH_FLUSH_CTRL_FLUSH_HIER, x)
-/* HSCH:SYSTEM:PORT_MODE */
-#define HSCH_PORT_MODE(r) __REG(TARGET_HSCH,\
- 0, 1, 184000, 0, 1, 312, 8, r, 70, 4)
+/* HSCH:SYSTEM:PORT_MODE */
+#define HSCH_PORT_MODE(r) \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_SYSTEM], 0, 1, 312, 8, r, \
+ regs->rcnt[RC_HSCH_PORT_MODE], 4)
#define HSCH_PORT_MODE_DEQUEUE_DIS BIT(4)
#define HSCH_PORT_MODE_DEQUEUE_DIS_SET(x)\
@@ -4831,9 +5334,10 @@ enum sparx5_target {
#define HSCH_PORT_MODE_CPU_PRIO_MODE_GET(x)\
FIELD_GET(HSCH_PORT_MODE_CPU_PRIO_MODE, x)
-/* HSCH:SYSTEM:OUTB_SHARE_ENA */
-#define HSCH_OUTB_SHARE_ENA(r) __REG(TARGET_HSCH,\
- 0, 1, 184000, 0, 1, 312, 288, r, 5, 4)
+/* HSCH:SYSTEM:OUTB_SHARE_ENA */
+#define HSCH_OUTB_SHARE_ENA(r) \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_SYSTEM], 0, 1, 312, 288, \
+ r, 5, 4)
#define HSCH_OUTB_SHARE_ENA_OUTB_SHARE_ENA GENMASK(7, 0)
#define HSCH_OUTB_SHARE_ENA_OUTB_SHARE_ENA_SET(x)\
@@ -4841,9 +5345,10 @@ enum sparx5_target {
#define HSCH_OUTB_SHARE_ENA_OUTB_SHARE_ENA_GET(x)\
FIELD_GET(HSCH_OUTB_SHARE_ENA_OUTB_SHARE_ENA, x)
-/* HSCH:MMGT:RESET_CFG */
-#define HSCH_RESET_CFG __REG(TARGET_HSCH,\
- 0, 1, 162368, 0, 1, 16, 8, 0, 1, 4)
+/* HSCH:MMGT:RESET_CFG */
+#define HSCH_RESET_CFG \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_MMGT], 0, 1, 16, 8, 0, 1, \
+ 4)
#define HSCH_RESET_CFG_CORE_ENA BIT(0)
#define HSCH_RESET_CFG_CORE_ENA_SET(x)\
@@ -4851,9 +5356,10 @@ enum sparx5_target {
#define HSCH_RESET_CFG_CORE_ENA_GET(x)\
FIELD_GET(HSCH_RESET_CFG_CORE_ENA, x)
-/* HSCH:TAS_CONFIG:TAS_STATEMACHINE_CFG */
-#define HSCH_TAS_STATEMACHINE_CFG __REG(TARGET_HSCH,\
- 0, 1, 162384, 0, 1, 12, 8, 0, 1, 4)
+/* HSCH:TAS_CONFIG:TAS_STATEMACHINE_CFG */
+#define HSCH_TAS_STATEMACHINE_CFG \
+ __REG(TARGET_HSCH, 0, 1, regs->gaddr[GA_HSCH_TAS_CONFIG], 0, 1, \
+ regs->gsize[GW_HSCH_TAS_CONFIG], 8, 0, 1, 4)
#define HSCH_TAS_STATEMACHINE_CFG_REVISIT_DLY GENMASK(7, 0)
#define HSCH_TAS_STATEMACHINE_CFG_REVISIT_DLY_SET(x)\
@@ -4861,9 +5367,9 @@ enum sparx5_target {
#define HSCH_TAS_STATEMACHINE_CFG_REVISIT_DLY_GET(x)\
FIELD_GET(HSCH_TAS_STATEMACHINE_CFG_REVISIT_DLY, x)
-/* LRN:COMMON:COMMON_ACCESS_CTRL */
-#define LRN_COMMON_ACCESS_CTRL __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 0, 0, 1, 4)
+/* LRN:COMMON:COMMON_ACCESS_CTRL */
+#define LRN_COMMON_ACCESS_CTRL \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 0, 0, 1, 4)
#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_COL GENMASK(21, 20)
#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_COL_SET(x)\
@@ -4877,11 +5383,12 @@ enum sparx5_target {
#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_TYPE_GET(x)\
FIELD_GET(LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_TYPE, x)
-#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW GENMASK(18, 5)
+#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW\
+ GENMASK(regs->fsize[FW_LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW] + 5 - 1, 5)
#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW_SET(x)\
- FIELD_PREP(LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW, x)
+ spx5_field_prep(LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW, x)
#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW_GET(x)\
- FIELD_GET(LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW, x)
+ spx5_field_get(LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW, x)
#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_CMD GENMASK(4, 1)
#define LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_CMD_SET(x)\
@@ -4895,9 +5402,9 @@ enum sparx5_target {
#define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT_GET(x)\
FIELD_GET(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT, x)
-/* LRN:COMMON:MAC_ACCESS_CFG_0 */
-#define LRN_MAC_ACCESS_CFG_0 __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 4, 0, 1, 4)
+/* LRN:COMMON:MAC_ACCESS_CFG_0 */
+#define LRN_MAC_ACCESS_CFG_0 \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 4, 0, 1, 4)
#define LRN_MAC_ACCESS_CFG_0_MAC_ENTRY_FID GENMASK(28, 16)
#define LRN_MAC_ACCESS_CFG_0_MAC_ENTRY_FID_SET(x)\
@@ -4911,13 +5418,13 @@ enum sparx5_target {
#define LRN_MAC_ACCESS_CFG_0_MAC_ENTRY_MAC_MSB_GET(x)\
FIELD_GET(LRN_MAC_ACCESS_CFG_0_MAC_ENTRY_MAC_MSB, x)
-/* LRN:COMMON:MAC_ACCESS_CFG_1 */
-#define LRN_MAC_ACCESS_CFG_1 __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 8, 0, 1, 4)
+/* LRN:COMMON:MAC_ACCESS_CFG_1 */
+#define LRN_MAC_ACCESS_CFG_1 \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 8, 0, 1, 4)
-/* LRN:COMMON:MAC_ACCESS_CFG_2 */
-#define LRN_MAC_ACCESS_CFG_2 __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 12, 0, 1, 4)
+/* LRN:COMMON:MAC_ACCESS_CFG_2 */
+#define LRN_MAC_ACCESS_CFG_2 \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 12, 0, 1, 4)
#define LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_SRC_KILL_FWD BIT(28)
#define LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_SRC_KILL_FWD_SET(x)\
@@ -4991,19 +5498,20 @@ enum sparx5_target {
#define LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR_GET(x)\
FIELD_GET(LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR, x)
-/* LRN:COMMON:MAC_ACCESS_CFG_3 */
-#define LRN_MAC_ACCESS_CFG_3 __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 16, 0, 1, 4)
+/* LRN:COMMON:MAC_ACCESS_CFG_3 */
+#define LRN_MAC_ACCESS_CFG_3 \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 16, 0, 1, 4)
-#define LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX GENMASK(10, 0)
+#define LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX\
+ GENMASK(regs->fsize[FW_LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX] + 0 - 1, 0)
#define LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX_SET(x)\
- FIELD_PREP(LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX, x)
+ spx5_field_prep(LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX, x)
#define LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX_GET(x)\
- FIELD_GET(LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX, x)
+ spx5_field_get(LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX, x)
-/* LRN:COMMON:SCAN_NEXT_CFG */
-#define LRN_SCAN_NEXT_CFG __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 20, 0, 1, 4)
+/* LRN:COMMON:SCAN_NEXT_CFG */
+#define LRN_SCAN_NEXT_CFG \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 20, 0, 1, 4)
#define LRN_SCAN_NEXT_CFG_SCAN_AGE_FLAG_UPDATE_SEL GENMASK(21, 19)
#define LRN_SCAN_NEXT_CFG_SCAN_AGE_FLAG_UPDATE_SEL_SET(x)\
@@ -5095,9 +5603,9 @@ enum sparx5_target {
#define LRN_SCAN_NEXT_CFG_ADDR_FILTER_ENA_GET(x)\
FIELD_GET(LRN_SCAN_NEXT_CFG_ADDR_FILTER_ENA, x)
-/* LRN:COMMON:SCAN_NEXT_CFG_1 */
-#define LRN_SCAN_NEXT_CFG_1 __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 24, 0, 1, 4)
+/* LRN:COMMON:SCAN_NEXT_CFG_1 */
+#define LRN_SCAN_NEXT_CFG_1 \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 24, 0, 1, 4)
#define LRN_SCAN_NEXT_CFG_1_PORT_MOVE_NEW_ADDR GENMASK(30, 16)
#define LRN_SCAN_NEXT_CFG_1_PORT_MOVE_NEW_ADDR_SET(x)\
@@ -5111,9 +5619,9 @@ enum sparx5_target {
#define LRN_SCAN_NEXT_CFG_1_SCAN_ENTRY_ADDR_MASK_GET(x)\
FIELD_GET(LRN_SCAN_NEXT_CFG_1_SCAN_ENTRY_ADDR_MASK, x)
-/* LRN:COMMON:AUTOAGE_CFG */
-#define LRN_AUTOAGE_CFG(r) __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 36, r, 4, 4)
+/* LRN:COMMON:AUTOAGE_CFG */
+#define LRN_AUTOAGE_CFG(r) \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 36, r, 4, 4)
#define LRN_AUTOAGE_CFG_UNIT_SIZE GENMASK(29, 28)
#define LRN_AUTOAGE_CFG_UNIT_SIZE_SET(x)\
@@ -5127,9 +5635,9 @@ enum sparx5_target {
#define LRN_AUTOAGE_CFG_PERIOD_VAL_GET(x)\
FIELD_GET(LRN_AUTOAGE_CFG_PERIOD_VAL, x)
-/* LRN:COMMON:AUTOAGE_CFG_1 */
-#define LRN_AUTOAGE_CFG_1 __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 52, 0, 1, 4)
+/* LRN:COMMON:AUTOAGE_CFG_1 */
+#define LRN_AUTOAGE_CFG_1 \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 52, 0, 1, 4)
#define LRN_AUTOAGE_CFG_1_PAUSE_AUTO_AGE_ENA BIT(25)
#define LRN_AUTOAGE_CFG_1_PAUSE_AUTO_AGE_ENA_SET(x)\
@@ -5173,15 +5681,16 @@ enum sparx5_target {
#define LRN_AUTOAGE_CFG_1_FORCE_IDLE_ENA_GET(x)\
FIELD_GET(LRN_AUTOAGE_CFG_1_FORCE_IDLE_ENA, x)
-/* LRN:COMMON:AUTOAGE_CFG_2 */
-#define LRN_AUTOAGE_CFG_2 __REG(TARGET_LRN,\
- 0, 1, 0, 0, 1, 72, 56, 0, 1, 4)
+/* LRN:COMMON:AUTOAGE_CFG_2 */
+#define LRN_AUTOAGE_CFG_2 \
+ __REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 56, 0, 1, 4)
-#define LRN_AUTOAGE_CFG_2_NEXT_ROW GENMASK(17, 4)
+#define LRN_AUTOAGE_CFG_2_NEXT_ROW\
+ GENMASK(regs->fsize[FW_LRN_AUTOAGE_CFG_2_NEXT_ROW] + 4 - 1, 4)
#define LRN_AUTOAGE_CFG_2_NEXT_ROW_SET(x)\
- FIELD_PREP(LRN_AUTOAGE_CFG_2_NEXT_ROW, x)
+ spx5_field_prep(LRN_AUTOAGE_CFG_2_NEXT_ROW, x)
#define LRN_AUTOAGE_CFG_2_NEXT_ROW_GET(x)\
- FIELD_GET(LRN_AUTOAGE_CFG_2_NEXT_ROW, x)
+ spx5_field_get(LRN_AUTOAGE_CFG_2_NEXT_ROW, x)
#define LRN_AUTOAGE_CFG_2_SCAN_ONGOING_STATUS GENMASK(3, 0)
#define LRN_AUTOAGE_CFG_2_SCAN_ONGOING_STATUS_SET(x)\
@@ -5189,9 +5698,10 @@ enum sparx5_target {
#define LRN_AUTOAGE_CFG_2_SCAN_ONGOING_STATUS_GET(x)\
FIELD_GET(LRN_AUTOAGE_CFG_2_SCAN_ONGOING_STATUS, x)
-/* PCIE_DM_EP:PF0_ATU_CAP:IATU_REGION_CTRL_2_OFF_OUTBOUND_0 */
-#define PCEP_RCTRL_2_OUT_0 __REG(TARGET_PCEP,\
- 0, 1, 3145728, 0, 1, 130852, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCIE_DM_EP:PF0_ATU_CAP:IATU_REGION_CTRL_2_OFF_OUTBOUND_0 */
+#define PCEP_RCTRL_2_OUT_0 \
+ __REG(TARGET_PCEP, 0, 1, 3145728, 0, 1, 130852, 4, 0, 1, 4)
#define PCEP_RCTRL_2_OUT_0_MSG_CODE GENMASK(7, 0)
#define PCEP_RCTRL_2_OUT_0_MSG_CODE_SET(x)\
@@ -5253,9 +5763,10 @@ enum sparx5_target {
#define PCEP_RCTRL_2_OUT_0_REGION_EN_GET(x)\
FIELD_GET(PCEP_RCTRL_2_OUT_0_REGION_EN, x)
-/* PCIE_DM_EP:PF0_ATU_CAP:IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0 */
-#define PCEP_ADDR_LWR_OUT_0 __REG(TARGET_PCEP,\
- 0, 1, 3145728, 0, 1, 130852, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCIE_DM_EP:PF0_ATU_CAP:IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0 */
+#define PCEP_ADDR_LWR_OUT_0 \
+ __REG(TARGET_PCEP, 0, 1, 3145728, 0, 1, 130852, 8, 0, 1, 4)
#define PCEP_ADDR_LWR_OUT_0_LWR_BASE_HW GENMASK(15, 0)
#define PCEP_ADDR_LWR_OUT_0_LWR_BASE_HW_SET(x)\
@@ -5269,13 +5780,15 @@ enum sparx5_target {
#define PCEP_ADDR_LWR_OUT_0_LWR_BASE_RW_GET(x)\
FIELD_GET(PCEP_ADDR_LWR_OUT_0_LWR_BASE_RW, x)
-/* PCIE_DM_EP:PF0_ATU_CAP:IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0 */
-#define PCEP_ADDR_UPR_OUT_0 __REG(TARGET_PCEP,\
- 0, 1, 3145728, 0, 1, 130852, 12, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCIE_DM_EP:PF0_ATU_CAP:IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0 */
+#define PCEP_ADDR_UPR_OUT_0 \
+ __REG(TARGET_PCEP, 0, 1, 3145728, 0, 1, 130852, 12, 0, 1, 4)
-/* PCIE_DM_EP:PF0_ATU_CAP:IATU_LIMIT_ADDR_OFF_OUTBOUND_0 */
-#define PCEP_ADDR_LIM_OUT_0 __REG(TARGET_PCEP,\
- 0, 1, 3145728, 0, 1, 130852, 16, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCIE_DM_EP:PF0_ATU_CAP:IATU_LIMIT_ADDR_OFF_OUTBOUND_0 */
+#define PCEP_ADDR_LIM_OUT_0 \
+ __REG(TARGET_PCEP, 0, 1, 3145728, 0, 1, 130852, 16, 0, 1, 4)
#define PCEP_ADDR_LIM_OUT_0_LIMIT_ADDR_HW GENMASK(15, 0)
#define PCEP_ADDR_LIM_OUT_0_LIMIT_ADDR_HW_SET(x)\
@@ -5289,17 +5802,20 @@ enum sparx5_target {
#define PCEP_ADDR_LIM_OUT_0_LIMIT_ADDR_RW_GET(x)\
FIELD_GET(PCEP_ADDR_LIM_OUT_0_LIMIT_ADDR_RW, x)
-/* PCIE_DM_EP:PF0_ATU_CAP:IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0 */
-#define PCEP_ADDR_LWR_TGT_OUT_0 __REG(TARGET_PCEP,\
- 0, 1, 3145728, 0, 1, 130852, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCIE_DM_EP:PF0_ATU_CAP:IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0 */
+#define PCEP_ADDR_LWR_TGT_OUT_0 \
+ __REG(TARGET_PCEP, 0, 1, 3145728, 0, 1, 130852, 20, 0, 1, 4)
-/* PCIE_DM_EP:PF0_ATU_CAP:IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0 */
-#define PCEP_ADDR_UPR_TGT_OUT_0 __REG(TARGET_PCEP,\
- 0, 1, 3145728, 0, 1, 130852, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCIE_DM_EP:PF0_ATU_CAP:IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0 */
+#define PCEP_ADDR_UPR_TGT_OUT_0 \
+ __REG(TARGET_PCEP, 0, 1, 3145728, 0, 1, 130852, 24, 0, 1, 4)
-/* PCIE_DM_EP:PF0_ATU_CAP:IATU_UPPR_LIMIT_ADDR_OFF_OUTBOUND_0 */
-#define PCEP_ADDR_UPR_LIM_OUT_0 __REG(TARGET_PCEP,\
- 0, 1, 3145728, 0, 1, 130852, 32, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCIE_DM_EP:PF0_ATU_CAP:IATU_UPPR_LIMIT_ADDR_OFF_OUTBOUND_0 */
+#define PCEP_ADDR_UPR_LIM_OUT_0 \
+ __REG(TARGET_PCEP, 0, 1, 3145728, 0, 1, 130852, 32, 0, 1, 4)
#define PCEP_ADDR_UPR_LIM_OUT_0_UPPR_LIMIT_ADDR_RW GENMASK(1, 0)
#define PCEP_ADDR_UPR_LIM_OUT_0_UPPR_LIMIT_ADDR_RW_SET(x)\
@@ -5313,9 +5829,10 @@ enum sparx5_target {
#define PCEP_ADDR_UPR_LIM_OUT_0_UPPR_LIMIT_ADDR_HW_GET(x)\
FIELD_GET(PCEP_ADDR_UPR_LIM_OUT_0_UPPR_LIMIT_ADDR_HW, x)
-/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_CFG */
-#define PCS10G_BR_PCS_CFG(t) __REG(TARGET_PCS10G_BR,\
- t, 12, 0, 0, 1, 56, 0, 0, 1, 4)
+/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_CFG */
+#define PCS10G_BR_PCS_CFG(t) \
+ __REG(TARGET_PCS10G_BR, t, regs->tsize[TC_PCS10G_BR], 0, 0, 1, 56, 0, \
+ 0, 1, 4)
#define PCS10G_BR_PCS_CFG_PCS_ENA BIT(31)
#define PCS10G_BR_PCS_CFG_PCS_ENA_SET(x)\
@@ -5389,9 +5906,10 @@ enum sparx5_target {
#define PCS10G_BR_PCS_CFG_TX_SCR_DISABLE_GET(x)\
FIELD_GET(PCS10G_BR_PCS_CFG_TX_SCR_DISABLE, x)
-/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_SD_CFG */
-#define PCS10G_BR_PCS_SD_CFG(t) __REG(TARGET_PCS10G_BR,\
- t, 12, 0, 0, 1, 56, 4, 0, 1, 4)
+/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_SD_CFG */
+#define PCS10G_BR_PCS_SD_CFG(t) \
+ __REG(TARGET_PCS10G_BR, t, regs->tsize[TC_PCS10G_BR], 0, 0, 1, 56, 4, \
+ 0, 1, 4)
#define PCS10G_BR_PCS_SD_CFG_SD_SEL BIT(8)
#define PCS10G_BR_PCS_SD_CFG_SD_SEL_SET(x)\
@@ -5411,9 +5929,10 @@ enum sparx5_target {
#define PCS10G_BR_PCS_SD_CFG_SD_ENA_GET(x)\
FIELD_GET(PCS10G_BR_PCS_SD_CFG_SD_ENA, x)
-/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_CFG */
-#define PCS25G_BR_PCS_CFG(t) __REG(TARGET_PCS25G_BR,\
- t, 8, 0, 0, 1, 56, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_CFG */
+#define PCS25G_BR_PCS_CFG(t) \
+ __REG(TARGET_PCS25G_BR, t, 8, 0, 0, 1, 56, 0, 0, 1, 4)
#define PCS25G_BR_PCS_CFG_PCS_ENA BIT(31)
#define PCS25G_BR_PCS_CFG_PCS_ENA_SET(x)\
@@ -5487,9 +6006,10 @@ enum sparx5_target {
#define PCS25G_BR_PCS_CFG_TX_SCR_DISABLE_GET(x)\
FIELD_GET(PCS25G_BR_PCS_CFG_TX_SCR_DISABLE, x)
-/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_SD_CFG */
-#define PCS25G_BR_PCS_SD_CFG(t) __REG(TARGET_PCS25G_BR,\
- t, 8, 0, 0, 1, 56, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_SD_CFG */
+#define PCS25G_BR_PCS_SD_CFG(t) \
+ __REG(TARGET_PCS25G_BR, t, 8, 0, 0, 1, 56, 4, 0, 1, 4)
#define PCS25G_BR_PCS_SD_CFG_SD_SEL BIT(8)
#define PCS25G_BR_PCS_SD_CFG_SD_SEL_SET(x)\
@@ -5509,9 +6029,10 @@ enum sparx5_target {
#define PCS25G_BR_PCS_SD_CFG_SD_ENA_GET(x)\
FIELD_GET(PCS25G_BR_PCS_SD_CFG_SD_ENA, x)
-/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_CFG */
-#define PCS5G_BR_PCS_CFG(t) __REG(TARGET_PCS5G_BR,\
- t, 13, 0, 0, 1, 56, 0, 0, 1, 4)
+/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_CFG */
+#define PCS5G_BR_PCS_CFG(t) \
+ __REG(TARGET_PCS5G_BR, t, regs->tsize[TC_PCS5G_BR], 0, 0, 1, 56, 0, 0, \
+ 1, 4)
#define PCS5G_BR_PCS_CFG_PCS_ENA BIT(31)
#define PCS5G_BR_PCS_CFG_PCS_ENA_SET(x)\
@@ -5585,9 +6106,10 @@ enum sparx5_target {
#define PCS5G_BR_PCS_CFG_TX_SCR_DISABLE_GET(x)\
FIELD_GET(PCS5G_BR_PCS_CFG_TX_SCR_DISABLE, x)
-/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_SD_CFG */
-#define PCS5G_BR_PCS_SD_CFG(t) __REG(TARGET_PCS5G_BR,\
- t, 13, 0, 0, 1, 56, 4, 0, 1, 4)
+/* PCS_10GBASE_R:PCS_10GBR_CFG:PCS_SD_CFG */
+#define PCS5G_BR_PCS_SD_CFG(t) \
+ __REG(TARGET_PCS5G_BR, t, regs->tsize[TC_PCS5G_BR], 0, 0, 1, 56, 4, 0, \
+ 1, 4)
#define PCS5G_BR_PCS_SD_CFG_SD_SEL BIT(8)
#define PCS5G_BR_PCS_SD_CFG_SD_SEL_SET(x)\
@@ -5607,58 +6129,67 @@ enum sparx5_target {
#define PCS5G_BR_PCS_SD_CFG_SD_ENA_GET(x)\
FIELD_GET(PCS5G_BR_PCS_SD_CFG_SD_ENA, x)
-/* PORT_CONF:HW_CFG:DEV5G_MODES */
-#define PORT_CONF_DEV5G_MODES __REG(TARGET_PORT_CONF,\
- 0, 1, 0, 0, 1, 24, 0, 0, 1, 4)
+/* PORT_CONF:HW_CFG:DEV5G_MODES */
+#define PORT_CONF_DEV5G_MODES \
+ __REG(TARGET_PORT_CONF, 0, 1, 0, 0, 1, 24, 0, 0, 1, 4)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D0_MODE BIT(0)
#define PORT_CONF_DEV5G_MODES_DEV5G_D0_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D0_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D0_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D0_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D1_MODE BIT(1)
#define PORT_CONF_DEV5G_MODES_DEV5G_D1_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D1_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D1_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D1_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D2_MODE BIT(2)
#define PORT_CONF_DEV5G_MODES_DEV5G_D2_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D2_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D2_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D2_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D3_MODE BIT(3)
#define PORT_CONF_DEV5G_MODES_DEV5G_D3_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D3_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D3_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D3_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D4_MODE BIT(4)
#define PORT_CONF_DEV5G_MODES_DEV5G_D4_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D4_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D4_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D4_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D5_MODE BIT(5)
#define PORT_CONF_DEV5G_MODES_DEV5G_D5_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D5_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D5_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D5_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D6_MODE BIT(6)
#define PORT_CONF_DEV5G_MODES_DEV5G_D6_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D6_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D6_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D6_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D7_MODE BIT(7)
#define PORT_CONF_DEV5G_MODES_DEV5G_D7_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D7_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D7_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D7_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D8_MODE BIT(8)
#define PORT_CONF_DEV5G_MODES_DEV5G_D8_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D8_MODE, x)
@@ -5671,27 +6202,30 @@ enum sparx5_target {
#define PORT_CONF_DEV5G_MODES_DEV5G_D9_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D9_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D10_MODE BIT(10)
#define PORT_CONF_DEV5G_MODES_DEV5G_D10_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D10_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D10_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D10_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D11_MODE BIT(11)
#define PORT_CONF_DEV5G_MODES_DEV5G_D11_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D11_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D11_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D11_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV5G_MODES_DEV5G_D64_MODE BIT(12)
#define PORT_CONF_DEV5G_MODES_DEV5G_D64_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV5G_MODES_DEV5G_D64_MODE, x)
#define PORT_CONF_DEV5G_MODES_DEV5G_D64_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV5G_MODES_DEV5G_D64_MODE, x)
-/* PORT_CONF:HW_CFG:DEV10G_MODES */
-#define PORT_CONF_DEV10G_MODES __REG(TARGET_PORT_CONF,\
- 0, 1, 0, 0, 1, 24, 4, 0, 1, 4)
+/* PORT_CONF:HW_CFG:DEV10G_MODES */
+#define PORT_CONF_DEV10G_MODES \
+ __REG(TARGET_PORT_CONF, 0, 1, 0, 0, 1, 24, 4, 0, 1, 4)
#define PORT_CONF_DEV10G_MODES_DEV10G_D12_MODE BIT(0)
#define PORT_CONF_DEV10G_MODES_DEV10G_D12_MODE_SET(x)\
@@ -5699,75 +6233,87 @@ enum sparx5_target {
#define PORT_CONF_DEV10G_MODES_DEV10G_D12_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D12_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D13_MODE BIT(1)
#define PORT_CONF_DEV10G_MODES_DEV10G_D13_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D13_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D13_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D13_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D14_MODE BIT(2)
#define PORT_CONF_DEV10G_MODES_DEV10G_D14_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D14_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D14_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D14_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D15_MODE BIT(3)
#define PORT_CONF_DEV10G_MODES_DEV10G_D15_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D15_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D15_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D15_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D48_MODE BIT(4)
#define PORT_CONF_DEV10G_MODES_DEV10G_D48_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D48_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D48_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D48_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D49_MODE BIT(5)
#define PORT_CONF_DEV10G_MODES_DEV10G_D49_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D49_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D49_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D49_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D50_MODE BIT(6)
#define PORT_CONF_DEV10G_MODES_DEV10G_D50_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D50_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D50_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D50_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D51_MODE BIT(7)
#define PORT_CONF_DEV10G_MODES_DEV10G_D51_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D51_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D51_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D51_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D52_MODE BIT(8)
#define PORT_CONF_DEV10G_MODES_DEV10G_D52_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D52_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D52_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D52_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D53_MODE BIT(9)
#define PORT_CONF_DEV10G_MODES_DEV10G_D53_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D53_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D53_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D53_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D54_MODE BIT(10)
#define PORT_CONF_DEV10G_MODES_DEV10G_D54_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D54_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D54_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D54_MODE, x)
+/* SPARX5 ONLY */
#define PORT_CONF_DEV10G_MODES_DEV10G_D55_MODE BIT(11)
#define PORT_CONF_DEV10G_MODES_DEV10G_D55_MODE_SET(x)\
FIELD_PREP(PORT_CONF_DEV10G_MODES_DEV10G_D55_MODE, x)
#define PORT_CONF_DEV10G_MODES_DEV10G_D55_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV10G_MODES_DEV10G_D55_MODE, x)
-/* PORT_CONF:HW_CFG:DEV25G_MODES */
-#define PORT_CONF_DEV25G_MODES __REG(TARGET_PORT_CONF,\
- 0, 1, 0, 0, 1, 24, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PORT_CONF:HW_CFG:DEV25G_MODES */
+#define PORT_CONF_DEV25G_MODES \
+ __REG(TARGET_PORT_CONF, 0, 1, 0, 0, 1, 24, 8, 0, 1, 4)
#define PORT_CONF_DEV25G_MODES_DEV25G_D56_MODE BIT(0)
#define PORT_CONF_DEV25G_MODES_DEV25G_D56_MODE_SET(x)\
@@ -5817,9 +6363,9 @@ enum sparx5_target {
#define PORT_CONF_DEV25G_MODES_DEV25G_D63_MODE_GET(x)\
FIELD_GET(PORT_CONF_DEV25G_MODES_DEV25G_D63_MODE, x)
-/* PORT_CONF:HW_CFG:QSGMII_ENA */
-#define PORT_CONF_QSGMII_ENA __REG(TARGET_PORT_CONF,\
- 0, 1, 0, 0, 1, 24, 12, 0, 1, 4)
+/* PORT_CONF:HW_CFG:QSGMII_ENA */
+#define PORT_CONF_QSGMII_ENA \
+ __REG(TARGET_PORT_CONF, 0, 1, 0, 0, 1, 24, 12, 0, 1, 4)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_0 BIT(0)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_0_SET(x)\
@@ -5857,45 +6403,52 @@ enum sparx5_target {
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_5_GET(x)\
FIELD_GET(PORT_CONF_QSGMII_ENA_QSGMII_ENA_5, x)
+/* SPARX5 ONLY */
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_6 BIT(6)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_6_SET(x)\
FIELD_PREP(PORT_CONF_QSGMII_ENA_QSGMII_ENA_6, x)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_6_GET(x)\
FIELD_GET(PORT_CONF_QSGMII_ENA_QSGMII_ENA_6, x)
+/* SPARX5 ONLY */
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_7 BIT(7)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_7_SET(x)\
FIELD_PREP(PORT_CONF_QSGMII_ENA_QSGMII_ENA_7, x)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_7_GET(x)\
FIELD_GET(PORT_CONF_QSGMII_ENA_QSGMII_ENA_7, x)
+/* SPARX5 ONLY */
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_8 BIT(8)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_8_SET(x)\
FIELD_PREP(PORT_CONF_QSGMII_ENA_QSGMII_ENA_8, x)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_8_GET(x)\
FIELD_GET(PORT_CONF_QSGMII_ENA_QSGMII_ENA_8, x)
+/* SPARX5 ONLY */
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_9 BIT(9)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_9_SET(x)\
FIELD_PREP(PORT_CONF_QSGMII_ENA_QSGMII_ENA_9, x)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_9_GET(x)\
FIELD_GET(PORT_CONF_QSGMII_ENA_QSGMII_ENA_9, x)
+/* SPARX5 ONLY */
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_10 BIT(10)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_10_SET(x)\
FIELD_PREP(PORT_CONF_QSGMII_ENA_QSGMII_ENA_10, x)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_10_GET(x)\
FIELD_GET(PORT_CONF_QSGMII_ENA_QSGMII_ENA_10, x)
+/* SPARX5 ONLY */
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_11 BIT(11)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_11_SET(x)\
FIELD_PREP(PORT_CONF_QSGMII_ENA_QSGMII_ENA_11, x)
#define PORT_CONF_QSGMII_ENA_QSGMII_ENA_11_GET(x)\
FIELD_GET(PORT_CONF_QSGMII_ENA_QSGMII_ENA_11, x)
-/* PORT_CONF:USGMII_CFG_STAT:USGMII_CFG */
-#define PORT_CONF_USGMII_CFG(g) __REG(TARGET_PORT_CONF,\
- 0, 1, 72, g, 6, 8, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* PORT_CONF:USGMII_CFG_STAT:USGMII_CFG */
+#define PORT_CONF_USGMII_CFG(g) \
+ __REG(TARGET_PORT_CONF, 0, 1, 72, g, 6, 8, 0, 0, 1, 4)
#define PORT_CONF_USGMII_CFG_BYPASS_SCRAM BIT(9)
#define PORT_CONF_USGMII_CFG_BYPASS_SCRAM_SET(x)\
@@ -5939,39 +6492,46 @@ enum sparx5_target {
#define PORT_CONF_USGMII_CFG_QUAD_MODE_GET(x)\
FIELD_GET(PORT_CONF_USGMII_CFG_QUAD_MODE, x)
-/* DEVCPU_PTP:PTP_CFG:PTP_PIN_INTR */
-#define PTP_PTP_PIN_INTR __REG(TARGET_PTP,\
- 0, 1, 320, 0, 1, 16, 0, 0, 1, 4)
+/* DEVCPU_PTP:PTP_CFG:PTP_PIN_INTR */
+#define PTP_PTP_PIN_INTR \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_CFG], 0, 1, 16, 0, 0, 1,\
+ 4)
-#define PTP_PTP_PIN_INTR_INTR_PTP GENMASK(4, 0)
+#define PTP_PTP_PIN_INTR_INTR_PTP\
+ GENMASK(regs->fsize[FW_PTP_PTP_PIN_INTR_INTR_PTP] + 0 - 1, 0)
#define PTP_PTP_PIN_INTR_INTR_PTP_SET(x)\
- FIELD_PREP(PTP_PTP_PIN_INTR_INTR_PTP, x)
+ spx5_field_prep(PTP_PTP_PIN_INTR_INTR_PTP, x)
#define PTP_PTP_PIN_INTR_INTR_PTP_GET(x)\
- FIELD_GET(PTP_PTP_PIN_INTR_INTR_PTP, x)
+ spx5_field_get(PTP_PTP_PIN_INTR_INTR_PTP, x)
-/* DEVCPU_PTP:PTP_CFG:PTP_PIN_INTR_ENA */
-#define PTP_PTP_PIN_INTR_ENA __REG(TARGET_PTP,\
- 0, 1, 320, 0, 1, 16, 4, 0, 1, 4)
+/* DEVCPU_PTP:PTP_CFG:PTP_PIN_INTR_ENA */
+#define PTP_PTP_PIN_INTR_ENA \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_CFG], 0, 1, 16, 4, 0, 1,\
+ 4)
-#define PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA GENMASK(4, 0)
+#define PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA\
+ GENMASK(regs->fsize[FW_PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA] + 0 - 1, 0)
#define PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA_SET(x)\
- FIELD_PREP(PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA, x)
+ spx5_field_prep(PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA, x)
#define PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA_GET(x)\
- FIELD_GET(PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA, x)
+ spx5_field_get(PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA, x)
-/* DEVCPU_PTP:PTP_CFG:PTP_INTR_IDENT */
-#define PTP_PTP_INTR_IDENT __REG(TARGET_PTP,\
- 0, 1, 320, 0, 1, 16, 8, 0, 1, 4)
+/* DEVCPU_PTP:PTP_CFG:PTP_INTR_IDENT */
+#define PTP_PTP_INTR_IDENT \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_CFG], 0, 1, 16, 8, 0, 1,\
+ 4)
-#define PTP_PTP_INTR_IDENT_INTR_PTP_IDENT GENMASK(4, 0)
+#define PTP_PTP_INTR_IDENT_INTR_PTP_IDENT\
+ GENMASK(regs->fsize[FW_PTP_PTP_INTR_IDENT_INTR_PTP_IDENT] + 0 - 1, 0)
#define PTP_PTP_INTR_IDENT_INTR_PTP_IDENT_SET(x)\
- FIELD_PREP(PTP_PTP_INTR_IDENT_INTR_PTP_IDENT, x)
+ spx5_field_prep(PTP_PTP_INTR_IDENT_INTR_PTP_IDENT, x)
#define PTP_PTP_INTR_IDENT_INTR_PTP_IDENT_GET(x)\
- FIELD_GET(PTP_PTP_INTR_IDENT_INTR_PTP_IDENT, x)
+ spx5_field_get(PTP_PTP_INTR_IDENT_INTR_PTP_IDENT, x)
-/* DEVCPU_PTP:PTP_CFG:PTP_DOM_CFG */
-#define PTP_PTP_DOM_CFG __REG(TARGET_PTP,\
- 0, 1, 320, 0, 1, 16, 12, 0, 1, 4)
+/* DEVCPU_PTP:PTP_CFG:PTP_DOM_CFG */
+#define PTP_PTP_DOM_CFG \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_CFG], 0, 1, 16, 12, 0, \
+ 1, 4)
#define PTP_PTP_DOM_CFG_PTP_ENA GENMASK(11, 9)
#define PTP_PTP_DOM_CFG_PTP_ENA_SET(x)\
@@ -5997,13 +6557,15 @@ enum sparx5_target {
#define PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS_GET(x)\
FIELD_GET(PTP_PTP_DOM_CFG_PTP_CLKCFG_DIS, x)
-/* DEVCPU_PTP:PTP_TOD_DOMAINS:CLK_PER_CFG */
-#define PTP_CLK_PER_CFG(g, r) __REG(TARGET_PTP,\
- 0, 1, 336, g, 3, 28, 0, r, 2, 4)
+/* DEVCPU_PTP:PTP_TOD_DOMAINS:CLK_PER_CFG */
+#define PTP_CLK_PER_CFG(g, r) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_TOD_DOMAINS], g, 3, 28, \
+ 0, r, 2, 4)
-/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_NSEC */
-#define PTP_PTP_CUR_NSEC(g) __REG(TARGET_PTP,\
- 0, 1, 336, g, 3, 28, 8, 0, 1, 4)
+/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_NSEC */
+#define PTP_PTP_CUR_NSEC(g) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_TOD_DOMAINS], g, 3, 28, \
+ 8, 0, 1, 4)
#define PTP_PTP_CUR_NSEC_PTP_CUR_NSEC GENMASK(29, 0)
#define PTP_PTP_CUR_NSEC_PTP_CUR_NSEC_SET(x)\
@@ -6011,9 +6573,10 @@ enum sparx5_target {
#define PTP_PTP_CUR_NSEC_PTP_CUR_NSEC_GET(x)\
FIELD_GET(PTP_PTP_CUR_NSEC_PTP_CUR_NSEC, x)
-/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_NSEC_FRAC */
-#define PTP_PTP_CUR_NSEC_FRAC(g) __REG(TARGET_PTP,\
- 0, 1, 336, g, 3, 28, 12, 0, 1, 4)
+/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_NSEC_FRAC */
+#define PTP_PTP_CUR_NSEC_FRAC(g) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_TOD_DOMAINS], g, 3, 28, \
+ 12, 0, 1, 4)
#define PTP_PTP_CUR_NSEC_FRAC_PTP_CUR_NSEC_FRAC GENMASK(7, 0)
#define PTP_PTP_CUR_NSEC_FRAC_PTP_CUR_NSEC_FRAC_SET(x)\
@@ -6021,13 +6584,15 @@ enum sparx5_target {
#define PTP_PTP_CUR_NSEC_FRAC_PTP_CUR_NSEC_FRAC_GET(x)\
FIELD_GET(PTP_PTP_CUR_NSEC_FRAC_PTP_CUR_NSEC_FRAC, x)
-/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_SEC_LSB */
-#define PTP_PTP_CUR_SEC_LSB(g) __REG(TARGET_PTP,\
- 0, 1, 336, g, 3, 28, 16, 0, 1, 4)
+/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_SEC_LSB */
+#define PTP_PTP_CUR_SEC_LSB(g) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_TOD_DOMAINS], g, 3, 28, \
+ 16, 0, 1, 4)
-/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_SEC_MSB */
-#define PTP_PTP_CUR_SEC_MSB(g) __REG(TARGET_PTP,\
- 0, 1, 336, g, 3, 28, 20, 0, 1, 4)
+/* DEVCPU_PTP:PTP_TOD_DOMAINS:PTP_CUR_SEC_MSB */
+#define PTP_PTP_CUR_SEC_MSB(g) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_TOD_DOMAINS], g, 3, 28, \
+ 20, 0, 1, 4)
#define PTP_PTP_CUR_SEC_MSB_PTP_CUR_SEC_MSB GENMASK(15, 0)
#define PTP_PTP_CUR_SEC_MSB_PTP_CUR_SEC_MSB_SET(x)\
@@ -6035,37 +6600,43 @@ enum sparx5_target {
#define PTP_PTP_CUR_SEC_MSB_PTP_CUR_SEC_MSB_GET(x)\
FIELD_GET(PTP_PTP_CUR_SEC_MSB_PTP_CUR_SEC_MSB, x)
-/* DEVCPU_PTP:PTP_TOD_DOMAINS:NTP_CUR_NSEC */
-#define PTP_NTP_CUR_NSEC(g) __REG(TARGET_PTP,\
- 0, 1, 336, g, 3, 28, 24, 0, 1, 4)
+/* DEVCPU_PTP:PTP_TOD_DOMAINS:NTP_CUR_NSEC */
+#define PTP_NTP_CUR_NSEC(g) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PTP_TOD_DOMAINS], g, 3, 28, \
+ 24, 0, 1, 4)
-/* DEVCPU_PTP:PTP_PINS:PTP_PIN_CFG */
-#define PTP_PTP_PIN_CFG(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 0, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PTP_PIN_CFG */
+#define PTP_PTP_PIN_CFG(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 0, 0, 1,\
+ 4)
-#define PTP_PTP_PIN_CFG_PTP_PIN_ACTION GENMASK(28, 26)
+#define PTP_PTP_PIN_CFG_PTP_PIN_ACTION\
+ GENMASK(regs->fpos[FP_PTP_PTP_PIN_CFG_PTP_PIN_ACTION] + 2, regs->fpos[FP_PTP_PTP_PIN_CFG_PTP_PIN_ACTION])
#define PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(x)\
- FIELD_PREP(PTP_PTP_PIN_CFG_PTP_PIN_ACTION, x)
+ spx5_field_prep(PTP_PTP_PIN_CFG_PTP_PIN_ACTION, x)
#define PTP_PTP_PIN_CFG_PTP_PIN_ACTION_GET(x)\
- FIELD_GET(PTP_PTP_PIN_CFG_PTP_PIN_ACTION, x)
+ spx5_field_get(PTP_PTP_PIN_CFG_PTP_PIN_ACTION, x)
-#define PTP_PTP_PIN_CFG_PTP_PIN_SYNC GENMASK(25, 24)
+#define PTP_PTP_PIN_CFG_PTP_PIN_SYNC\
+ GENMASK(regs->fpos[FP_PTP_PTP_PIN_CFG_PTP_PIN_SYNC] + 1, regs->fpos[FP_PTP_PTP_PIN_CFG_PTP_PIN_SYNC])
#define PTP_PTP_PIN_CFG_PTP_PIN_SYNC_SET(x)\
- FIELD_PREP(PTP_PTP_PIN_CFG_PTP_PIN_SYNC, x)
+ spx5_field_prep(PTP_PTP_PIN_CFG_PTP_PIN_SYNC, x)
#define PTP_PTP_PIN_CFG_PTP_PIN_SYNC_GET(x)\
- FIELD_GET(PTP_PTP_PIN_CFG_PTP_PIN_SYNC, x)
+ spx5_field_get(PTP_PTP_PIN_CFG_PTP_PIN_SYNC, x)
-#define PTP_PTP_PIN_CFG_PTP_PIN_INV_POL BIT(23)
+#define PTP_PTP_PIN_CFG_PTP_PIN_INV_POL\
+ BIT(regs->fpos[FP_PTP_PTP_PIN_CFG_PTP_PIN_INV_POL])
#define PTP_PTP_PIN_CFG_PTP_PIN_INV_POL_SET(x)\
- FIELD_PREP(PTP_PTP_PIN_CFG_PTP_PIN_INV_POL, x)
+ spx5_field_prep(PTP_PTP_PIN_CFG_PTP_PIN_INV_POL, x)
#define PTP_PTP_PIN_CFG_PTP_PIN_INV_POL_GET(x)\
- FIELD_GET(PTP_PTP_PIN_CFG_PTP_PIN_INV_POL, x)
+ spx5_field_get(PTP_PTP_PIN_CFG_PTP_PIN_INV_POL, x)
-#define PTP_PTP_PIN_CFG_PTP_PIN_SELECT GENMASK(22, 21)
+#define PTP_PTP_PIN_CFG_PTP_PIN_SELECT\
+ GENMASK(regs->fsize[FW_PTP_PTP_PIN_CFG_PTP_PIN_SELECT] + 21 - 1, 21)
#define PTP_PTP_PIN_CFG_PTP_PIN_SELECT_SET(x)\
- FIELD_PREP(PTP_PTP_PIN_CFG_PTP_PIN_SELECT, x)
+ spx5_field_prep(PTP_PTP_PIN_CFG_PTP_PIN_SELECT, x)
#define PTP_PTP_PIN_CFG_PTP_PIN_SELECT_GET(x)\
- FIELD_GET(PTP_PTP_PIN_CFG_PTP_PIN_SELECT, x)
+ spx5_field_get(PTP_PTP_PIN_CFG_PTP_PIN_SELECT, x)
#define PTP_PTP_PIN_CFG_PTP_CLK_SELECT GENMASK(20, 18)
#define PTP_PTP_PIN_CFG_PTP_CLK_SELECT_SET(x)\
@@ -6097,9 +6668,10 @@ enum sparx5_target {
#define PTP_PTP_PIN_CFG_PTP_PIN_OUTP_OFS_GET(x)\
FIELD_GET(PTP_PTP_PIN_CFG_PTP_PIN_OUTP_OFS, x)
-/* DEVCPU_PTP:PTP_PINS:PTP_TOD_SEC_MSB */
-#define PTP_PTP_TOD_SEC_MSB(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 4, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PTP_TOD_SEC_MSB */
+#define PTP_PTP_TOD_SEC_MSB(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 4, 0, 1,\
+ 4)
#define PTP_PTP_TOD_SEC_MSB_PTP_TOD_SEC_MSB GENMASK(15, 0)
#define PTP_PTP_TOD_SEC_MSB_PTP_TOD_SEC_MSB_SET(x)\
@@ -6107,13 +6679,15 @@ enum sparx5_target {
#define PTP_PTP_TOD_SEC_MSB_PTP_TOD_SEC_MSB_GET(x)\
FIELD_GET(PTP_PTP_TOD_SEC_MSB_PTP_TOD_SEC_MSB, x)
-/* DEVCPU_PTP:PTP_PINS:PTP_TOD_SEC_LSB */
-#define PTP_PTP_TOD_SEC_LSB(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 8, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PTP_TOD_SEC_LSB */
+#define PTP_PTP_TOD_SEC_LSB(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 8, 0, 1,\
+ 4)
-/* DEVCPU_PTP:PTP_PINS:PTP_TOD_NSEC */
-#define PTP_PTP_TOD_NSEC(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 12, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PTP_TOD_NSEC */
+#define PTP_PTP_TOD_NSEC(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 12, 0, \
+ 1, 4)
#define PTP_PTP_TOD_NSEC_PTP_TOD_NSEC GENMASK(29, 0)
#define PTP_PTP_TOD_NSEC_PTP_TOD_NSEC_SET(x)\
@@ -6121,9 +6695,10 @@ enum sparx5_target {
#define PTP_PTP_TOD_NSEC_PTP_TOD_NSEC_GET(x)\
FIELD_GET(PTP_PTP_TOD_NSEC_PTP_TOD_NSEC, x)
-/* DEVCPU_PTP:PTP_PINS:PTP_TOD_NSEC_FRAC */
-#define PTP_PTP_TOD_NSEC_FRAC(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 16, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PTP_TOD_NSEC_FRAC */
+#define PTP_PTP_TOD_NSEC_FRAC(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 16, 0, \
+ 1, 4)
#define PTP_PTP_TOD_NSEC_FRAC_PTP_TOD_NSEC_FRAC GENMASK(7, 0)
#define PTP_PTP_TOD_NSEC_FRAC_PTP_TOD_NSEC_FRAC_SET(x)\
@@ -6131,13 +6706,15 @@ enum sparx5_target {
#define PTP_PTP_TOD_NSEC_FRAC_PTP_TOD_NSEC_FRAC_GET(x)\
FIELD_GET(PTP_PTP_TOD_NSEC_FRAC_PTP_TOD_NSEC_FRAC, x)
-/* DEVCPU_PTP:PTP_PINS:NTP_NSEC */
-#define PTP_NTP_NSEC(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 20, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:NTP_NSEC */
+#define PTP_NTP_NSEC(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 20, 0, \
+ 1, 4)
-/* DEVCPU_PTP:PTP_PINS:PIN_WF_HIGH_PERIOD */
-#define PTP_PIN_WF_HIGH_PERIOD(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 24, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PIN_WF_HIGH_PERIOD */
+#define PTP_PIN_WF_HIGH_PERIOD(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 24, 0, \
+ 1, 4)
#define PTP_PIN_WF_HIGH_PERIOD_PIN_WFH GENMASK(29, 0)
#define PTP_PIN_WF_HIGH_PERIOD_PIN_WFH_SET(x)\
@@ -6145,9 +6722,10 @@ enum sparx5_target {
#define PTP_PIN_WF_HIGH_PERIOD_PIN_WFH_GET(x)\
FIELD_GET(PTP_PIN_WF_HIGH_PERIOD_PIN_WFH, x)
-/* DEVCPU_PTP:PTP_PINS:PIN_WF_LOW_PERIOD */
-#define PTP_PIN_WF_LOW_PERIOD(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 28, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PIN_WF_LOW_PERIOD */
+#define PTP_PIN_WF_LOW_PERIOD(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 28, 0, \
+ 1, 4)
#define PTP_PIN_WF_LOW_PERIOD_PIN_WFL GENMASK(29, 0)
#define PTP_PIN_WF_LOW_PERIOD_PIN_WFL_SET(x)\
@@ -6155,9 +6733,10 @@ enum sparx5_target {
#define PTP_PIN_WF_LOW_PERIOD_PIN_WFL_GET(x)\
FIELD_GET(PTP_PIN_WF_LOW_PERIOD_PIN_WFL, x)
-/* DEVCPU_PTP:PTP_PINS:PIN_IOBOUNCH_DELAY */
-#define PTP_PIN_IOBOUNCH_DELAY(g) __REG(TARGET_PTP,\
- 0, 1, 0, g, 5, 64, 32, 0, 1, 4)
+/* DEVCPU_PTP:PTP_PINS:PIN_IOBOUNCH_DELAY */
+#define PTP_PIN_IOBOUNCH_DELAY(g) \
+ __REG(TARGET_PTP, 0, 1, 0, g, regs->gcnt[GC_PTP_PTP_PINS], 64, 32, 0, \
+ 1, 4)
#define PTP_PIN_IOBOUNCH_DELAY_PIN_IOBOUNCH_VAL GENMASK(18, 3)
#define PTP_PIN_IOBOUNCH_DELAY_PIN_IOBOUNCH_VAL_SET(x)\
@@ -6171,22 +6750,27 @@ enum sparx5_target {
#define PTP_PIN_IOBOUNCH_DELAY_PIN_IOBOUNCH_CFG_GET(x)\
FIELD_GET(PTP_PIN_IOBOUNCH_DELAY_PIN_IOBOUNCH_CFG, x)
-/* DEVCPU_PTP:PHASE_DETECTOR_CTRL:PHAD_CTRL */
-#define PTP_PHAD_CTRL(g) __REG(TARGET_PTP,\
- 0, 1, 420, g, 5, 8, 0, 0, 1, 4)
+/* DEVCPU_PTP:PHASE_DETECTOR_CTRL:PHAD_CTRL */
+#define PTP_PHAD_CTRL(g) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PHASE_DETECTOR_CTRL], g, \
+ regs->gcnt[GC_PTP_PHASE_DETECTOR_CTRL], \
+ regs->gsize[GW_PTP_PHASE_DETECTOR_CTRL], 0, 0, 1, 4)
-#define PTP_PHAD_CTRL_PHAD_ENA BIT(7)
+#define PTP_PHAD_CTRL_PHAD_ENA\
+ BIT(regs->fpos[FP_PTP_PHAD_CTRL_PHAD_ENA])
#define PTP_PHAD_CTRL_PHAD_ENA_SET(x)\
- FIELD_PREP(PTP_PHAD_CTRL_PHAD_ENA, x)
+ spx5_field_prep(PTP_PHAD_CTRL_PHAD_ENA, x)
#define PTP_PHAD_CTRL_PHAD_ENA_GET(x)\
- FIELD_GET(PTP_PHAD_CTRL_PHAD_ENA, x)
+ spx5_field_get(PTP_PHAD_CTRL_PHAD_ENA, x)
-#define PTP_PHAD_CTRL_PHAD_FAILED BIT(6)
+#define PTP_PHAD_CTRL_PHAD_FAILED\
+ BIT(regs->fpos[FP_PTP_PHAD_CTRL_PHAD_FAILED])
#define PTP_PHAD_CTRL_PHAD_FAILED_SET(x)\
- FIELD_PREP(PTP_PHAD_CTRL_PHAD_FAILED, x)
+ spx5_field_prep(PTP_PHAD_CTRL_PHAD_FAILED, x)
#define PTP_PHAD_CTRL_PHAD_FAILED_GET(x)\
- FIELD_GET(PTP_PHAD_CTRL_PHAD_FAILED, x)
+ spx5_field_get(PTP_PHAD_CTRL_PHAD_FAILED, x)
+/* SPARX5 ONLY */
#define PTP_PHAD_CTRL_REDUCED_RES GENMASK(5, 3)
#define PTP_PHAD_CTRL_REDUCED_RES_SET(x)\
FIELD_PREP(PTP_PHAD_CTRL_REDUCED_RES, x)
@@ -6199,13 +6783,79 @@ enum sparx5_target {
#define PTP_PHAD_CTRL_LOCK_ACC_GET(x)\
FIELD_GET(PTP_PHAD_CTRL_LOCK_ACC, x)
-/* DEVCPU_PTP:PHASE_DETECTOR_CTRL:PHAD_CYC_STAT */
-#define PTP_PHAD_CYC_STAT(g) __REG(TARGET_PTP,\
- 0, 1, 420, g, 5, 8, 4, 0, 1, 4)
-
-/* QFWD:SYSTEM:SWITCH_PORT_MODE */
-#define QFWD_SWITCH_PORT_MODE(r) __REG(TARGET_QFWD,\
- 0, 1, 0, 0, 1, 340, 0, r, 70, 4)
+/* DEVCPU_PTP:PHASE_DETECTOR_CTRL:PHAD_CYC_STAT */
+#define PTP_PHAD_CYC_STAT(g) \
+ __REG(TARGET_PTP, 0, 1, regs->gaddr[GA_PTP_PHASE_DETECTOR_CTRL], g, \
+ regs->gcnt[GC_PTP_PHASE_DETECTOR_CTRL], \
+ regs->gsize[GW_PTP_PHASE_DETECTOR_CTRL], 4, 0, 1, 4)
+
+/* LAN969X ONLY */
+/* DEVCPU_PTP:PTP_TS_FIFO:PTP_TWOSTEP_CTRL */
+#define PTP_TWOSTEP_CTRL \
+ __REG(TARGET_PTP, 0, 1, 612, 0, 1, 16, 0, 0, 1, 4)
+
+#define PTP_TWOSTEP_CTRL_PTP_OVWR_ENA BIT(12)
+#define PTP_TWOSTEP_CTRL_PTP_OVWR_ENA_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_CTRL_PTP_OVWR_ENA, x)
+#define PTP_TWOSTEP_CTRL_PTP_OVWR_ENA_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_CTRL_PTP_OVWR_ENA, x)
+
+#define PTP_TWOSTEP_CTRL_PTP_NXT BIT(11)
+#define PTP_TWOSTEP_CTRL_PTP_NXT_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_CTRL_PTP_NXT, x)
+#define PTP_TWOSTEP_CTRL_PTP_NXT_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_CTRL_PTP_NXT, x)
+
+#define PTP_TWOSTEP_CTRL_PTP_VLD BIT(10)
+#define PTP_TWOSTEP_CTRL_PTP_VLD_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_CTRL_PTP_VLD, x)
+#define PTP_TWOSTEP_CTRL_PTP_VLD_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_CTRL_PTP_VLD, x)
+
+#define PTP_TWOSTEP_CTRL_STAMP_TX BIT(9)
+#define PTP_TWOSTEP_CTRL_STAMP_TX_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_CTRL_STAMP_TX, x)
+#define PTP_TWOSTEP_CTRL_STAMP_TX_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_CTRL_STAMP_TX, x)
+
+#define PTP_TWOSTEP_CTRL_STAMP_PORT GENMASK(8, 1)
+#define PTP_TWOSTEP_CTRL_STAMP_PORT_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_CTRL_STAMP_PORT, x)
+#define PTP_TWOSTEP_CTRL_STAMP_PORT_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_CTRL_STAMP_PORT, x)
+
+#define PTP_TWOSTEP_CTRL_PTP_OVFL BIT(0)
+#define PTP_TWOSTEP_CTRL_PTP_OVFL_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_CTRL_PTP_OVFL, x)
+#define PTP_TWOSTEP_CTRL_PTP_OVFL_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_CTRL_PTP_OVFL, x)
+
+/* LAN969X ONLY */
+/* DEVCPU_PTP:PTP_TS_FIFO:PTP_TWOSTEP_STAMP_NSEC */
+#define PTP_TWOSTEP_STAMP_NSEC \
+ __REG(TARGET_PTP, 0, 1, 612, 0, 1, 16, 4, 0, 1, 4)
+
+#define PTP_TWOSTEP_STAMP_NSEC_NS GENMASK(29, 0)
+#define PTP_TWOSTEP_STAMP_NSEC_NS_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_STAMP_NSEC_NS, x)
+#define PTP_TWOSTEP_STAMP_NSEC_NS_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_STAMP_NSEC_NS, x)
+
+/* LAN969X ONLY */
+/* DEVCPU_PTP:PTP_TS_FIFO:PTP_TWOSTEP_STAMP_SUBNS */
+#define PTP_TWOSTEP_STAMP_SUBNS \
+ __REG(TARGET_PTP, 0, 1, 612, 0, 1, 16, 8, 0, 1, 4)
+
+#define PTP_TWOSTEP_STAMP_SUBNS_NS GENMASK(7, 0)
+#define PTP_TWOSTEP_STAMP_SUBNS_NS_SET(x)\
+ FIELD_PREP(PTP_TWOSTEP_STAMP_SUBNS_NS, x)
+#define PTP_TWOSTEP_STAMP_SUBNS_NS_GET(x)\
+ FIELD_GET(PTP_TWOSTEP_STAMP_SUBNS_NS, x)
+
+/* QFWD:SYSTEM:SWITCH_PORT_MODE */
+#define QFWD_SWITCH_PORT_MODE(r) \
+ __REG(TARGET_QFWD, 0, 1, 0, 0, 1, 340, 0, r, \
+ regs->rcnt[RC_QFWD_SWITCH_PORT_MODE], 4)
#define QFWD_SWITCH_PORT_MODE_PORT_ENA BIT(19)
#define QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(x)\
@@ -6261,49 +6911,53 @@ enum sparx5_target {
#define QFWD_SWITCH_PORT_MODE_LEARNALL_MORE_GET(x)\
FIELD_GET(QFWD_SWITCH_PORT_MODE_LEARNALL_MORE, x)
-/* QFWD:SYSTEM:FRAME_COPY_CFG */
-#define QFWD_FRAME_COPY_CFG(r)\
+/* QFWD:SYSTEM:FRAME_COPY_CFG */
+#define QFWD_FRAME_COPY_CFG(r) \
__REG(TARGET_QFWD, 0, 1, 0, 0, 1, 340, 284, r, 12, 4)
-#define QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL GENMASK(12, 6)
+#define QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL\
+ GENMASK(regs->fsize[FW_QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL] + 6 - 1, 6)
#define QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL_SET(x)\
- FIELD_PREP(QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL, x)
+ spx5_field_prep(QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL, x)
#define QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL_GET(x)\
- FIELD_GET(QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL, x)
+ spx5_field_get(QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL, x)
-/* QRES:RES_CTRL:RES_CFG */
-#define QRES_RES_CFG(g) __REG(TARGET_QRES,\
- 0, 1, 0, g, 5120, 16, 0, 0, 1, 4)
+/* QRES:RES_CTRL:RES_CFG */
+#define QRES_RES_CFG(g) \
+ __REG(TARGET_QRES, 0, 1, 0, g, 5120, 16, 0, 0, 1, 4)
-#define QRES_RES_CFG_WM_HIGH GENMASK(11, 0)
+#define QRES_RES_CFG_WM_HIGH\
+ GENMASK(regs->fsize[FW_QRES_RES_CFG_WM_HIGH] + 0 - 1, 0)
#define QRES_RES_CFG_WM_HIGH_SET(x)\
- FIELD_PREP(QRES_RES_CFG_WM_HIGH, x)
+ spx5_field_prep(QRES_RES_CFG_WM_HIGH, x)
#define QRES_RES_CFG_WM_HIGH_GET(x)\
- FIELD_GET(QRES_RES_CFG_WM_HIGH, x)
+ spx5_field_get(QRES_RES_CFG_WM_HIGH, x)
-/* QRES:RES_CTRL:RES_STAT */
-#define QRES_RES_STAT(g) __REG(TARGET_QRES,\
- 0, 1, 0, g, 5120, 16, 4, 0, 1, 4)
+/* QRES:RES_CTRL:RES_STAT */
+#define QRES_RES_STAT(g) \
+ __REG(TARGET_QRES, 0, 1, 0, g, 5120, 16, 4, 0, 1, 4)
-#define QRES_RES_STAT_MAXUSE GENMASK(20, 0)
+#define QRES_RES_STAT_MAXUSE\
+ GENMASK(regs->fsize[FW_QRES_RES_STAT_MAXUSE] + 0 - 1, 0)
#define QRES_RES_STAT_MAXUSE_SET(x)\
- FIELD_PREP(QRES_RES_STAT_MAXUSE, x)
+ spx5_field_prep(QRES_RES_STAT_MAXUSE, x)
#define QRES_RES_STAT_MAXUSE_GET(x)\
- FIELD_GET(QRES_RES_STAT_MAXUSE, x)
+ spx5_field_get(QRES_RES_STAT_MAXUSE, x)
-/* QRES:RES_CTRL:RES_STAT_CUR */
-#define QRES_RES_STAT_CUR(g) __REG(TARGET_QRES,\
- 0, 1, 0, g, 5120, 16, 8, 0, 1, 4)
+/* QRES:RES_CTRL:RES_STAT_CUR */
+#define QRES_RES_STAT_CUR(g) \
+ __REG(TARGET_QRES, 0, 1, 0, g, 5120, 16, 8, 0, 1, 4)
-#define QRES_RES_STAT_CUR_INUSE GENMASK(20, 0)
+#define QRES_RES_STAT_CUR_INUSE\
+ GENMASK(regs->fsize[FW_QRES_RES_STAT_CUR_INUSE] + 0 - 1, 0)
#define QRES_RES_STAT_CUR_INUSE_SET(x)\
- FIELD_PREP(QRES_RES_STAT_CUR_INUSE, x)
+ spx5_field_prep(QRES_RES_STAT_CUR_INUSE, x)
#define QRES_RES_STAT_CUR_INUSE_GET(x)\
- FIELD_GET(QRES_RES_STAT_CUR_INUSE, x)
+ spx5_field_get(QRES_RES_STAT_CUR_INUSE, x)
-/* DEVCPU_QS:XTR:XTR_GRP_CFG */
-#define QS_XTR_GRP_CFG(r) __REG(TARGET_QS,\
- 0, 1, 0, 0, 1, 36, 0, r, 2, 4)
+/* DEVCPU_QS:XTR:XTR_GRP_CFG */
+#define QS_XTR_GRP_CFG(r) \
+ __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 0, r, 2, 4)
#define QS_XTR_GRP_CFG_MODE GENMASK(3, 2)
#define QS_XTR_GRP_CFG_MODE_SET(x)\
@@ -6323,13 +6977,13 @@ enum sparx5_target {
#define QS_XTR_GRP_CFG_BYTE_SWAP_GET(x)\
FIELD_GET(QS_XTR_GRP_CFG_BYTE_SWAP, x)
-/* DEVCPU_QS:XTR:XTR_RD */
-#define QS_XTR_RD(r) __REG(TARGET_QS,\
- 0, 1, 0, 0, 1, 36, 8, r, 2, 4)
+/* DEVCPU_QS:XTR:XTR_RD */
+#define QS_XTR_RD(r) \
+ __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 8, r, 2, 4)
-/* DEVCPU_QS:XTR:XTR_FLUSH */
-#define QS_XTR_FLUSH __REG(TARGET_QS,\
- 0, 1, 0, 0, 1, 36, 24, 0, 1, 4)
+/* DEVCPU_QS:XTR:XTR_FLUSH */
+#define QS_XTR_FLUSH \
+ __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 24, 0, 1, 4)
#define QS_XTR_FLUSH_FLUSH GENMASK(1, 0)
#define QS_XTR_FLUSH_FLUSH_SET(x)\
@@ -6337,9 +6991,9 @@ enum sparx5_target {
#define QS_XTR_FLUSH_FLUSH_GET(x)\
FIELD_GET(QS_XTR_FLUSH_FLUSH, x)
-/* DEVCPU_QS:XTR:XTR_DATA_PRESENT */
-#define QS_XTR_DATA_PRESENT __REG(TARGET_QS,\
- 0, 1, 0, 0, 1, 36, 28, 0, 1, 4)
+/* DEVCPU_QS:XTR:XTR_DATA_PRESENT */
+#define QS_XTR_DATA_PRESENT \
+ __REG(TARGET_QS, 0, 1, 0, 0, 1, 36, 28, 0, 1, 4)
#define QS_XTR_DATA_PRESENT_DATA_PRESENT GENMASK(1, 0)
#define QS_XTR_DATA_PRESENT_DATA_PRESENT_SET(x)\
@@ -6347,9 +7001,9 @@ enum sparx5_target {
#define QS_XTR_DATA_PRESENT_DATA_PRESENT_GET(x)\
FIELD_GET(QS_XTR_DATA_PRESENT_DATA_PRESENT, x)
-/* DEVCPU_QS:INJ:INJ_GRP_CFG */
-#define QS_INJ_GRP_CFG(r) __REG(TARGET_QS,\
- 0, 1, 36, 0, 1, 40, 0, r, 2, 4)
+/* DEVCPU_QS:INJ:INJ_GRP_CFG */
+#define QS_INJ_GRP_CFG(r) \
+ __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 0, r, 2, 4)
#define QS_INJ_GRP_CFG_MODE GENMASK(3, 2)
#define QS_INJ_GRP_CFG_MODE_SET(x)\
@@ -6363,13 +7017,13 @@ enum sparx5_target {
#define QS_INJ_GRP_CFG_BYTE_SWAP_GET(x)\
FIELD_GET(QS_INJ_GRP_CFG_BYTE_SWAP, x)
-/* DEVCPU_QS:INJ:INJ_WR */
-#define QS_INJ_WR(r) __REG(TARGET_QS,\
- 0, 1, 36, 0, 1, 40, 8, r, 2, 4)
+/* DEVCPU_QS:INJ:INJ_WR */
+#define QS_INJ_WR(r) \
+ __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 8, r, 2, 4)
-/* DEVCPU_QS:INJ:INJ_CTRL */
-#define QS_INJ_CTRL(r) __REG(TARGET_QS,\
- 0, 1, 36, 0, 1, 40, 16, r, 2, 4)
+/* DEVCPU_QS:INJ:INJ_CTRL */
+#define QS_INJ_CTRL(r) \
+ __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 16, r, 2, 4)
#define QS_INJ_CTRL_GAP_SIZE GENMASK(24, 21)
#define QS_INJ_CTRL_GAP_SIZE_SET(x)\
@@ -6401,9 +7055,9 @@ enum sparx5_target {
#define QS_INJ_CTRL_VLD_BYTES_GET(x)\
FIELD_GET(QS_INJ_CTRL_VLD_BYTES, x)
-/* DEVCPU_QS:INJ:INJ_STATUS */
-#define QS_INJ_STATUS __REG(TARGET_QS,\
- 0, 1, 36, 0, 1, 40, 24, 0, 1, 4)
+/* DEVCPU_QS:INJ:INJ_STATUS */
+#define QS_INJ_STATUS \
+ __REG(TARGET_QS, 0, 1, 36, 0, 1, 40, 24, 0, 1, 4)
#define QS_INJ_STATUS_WMARK_REACHED GENMASK(5, 4)
#define QS_INJ_STATUS_WMARK_REACHED_SET(x)\
@@ -6423,21 +7077,24 @@ enum sparx5_target {
#define QS_INJ_STATUS_INJ_IN_PROGRESS_GET(x)\
FIELD_GET(QS_INJ_STATUS_INJ_IN_PROGRESS, x)
-/* QSYS:PAUSE_CFG:PAUSE_CFG */
-#define QSYS_PAUSE_CFG(r) __REG(TARGET_QSYS,\
- 0, 1, 544, 0, 1, 1128, 0, r, 70, 4)
+/* QSYS:PAUSE_CFG:PAUSE_CFG */
+#define QSYS_PAUSE_CFG(r) \
+ __REG(TARGET_QSYS, 0, 1, 544, 0, 1, regs->gsize[GW_QSYS_PAUSE_CFG], 0, \
+ r, regs->rcnt[RC_QSYS_PAUSE_CFG], 4)
-#define QSYS_PAUSE_CFG_PAUSE_START GENMASK(25, 14)
+#define QSYS_PAUSE_CFG_PAUSE_START\
+ GENMASK(regs->fsize[FW_QSYS_PAUSE_CFG_PAUSE_START] + 14 - 1, 14)
#define QSYS_PAUSE_CFG_PAUSE_START_SET(x)\
- FIELD_PREP(QSYS_PAUSE_CFG_PAUSE_START, x)
+ spx5_field_prep(QSYS_PAUSE_CFG_PAUSE_START, x)
#define QSYS_PAUSE_CFG_PAUSE_START_GET(x)\
- FIELD_GET(QSYS_PAUSE_CFG_PAUSE_START, x)
+ spx5_field_get(QSYS_PAUSE_CFG_PAUSE_START, x)
-#define QSYS_PAUSE_CFG_PAUSE_STOP GENMASK(13, 2)
+#define QSYS_PAUSE_CFG_PAUSE_STOP\
+ GENMASK(regs->fsize[FW_QSYS_PAUSE_CFG_PAUSE_STOP] + 2 - 1, 2)
#define QSYS_PAUSE_CFG_PAUSE_STOP_SET(x)\
- FIELD_PREP(QSYS_PAUSE_CFG_PAUSE_STOP, x)
+ spx5_field_prep(QSYS_PAUSE_CFG_PAUSE_STOP, x)
#define QSYS_PAUSE_CFG_PAUSE_STOP_GET(x)\
- FIELD_GET(QSYS_PAUSE_CFG_PAUSE_STOP, x)
+ spx5_field_get(QSYS_PAUSE_CFG_PAUSE_STOP, x)
#define QSYS_PAUSE_CFG_PAUSE_ENA BIT(1)
#define QSYS_PAUSE_CFG_PAUSE_ENA_SET(x)\
@@ -6451,19 +7108,22 @@ enum sparx5_target {
#define QSYS_PAUSE_CFG_AGGRESSIVE_TAILDROP_ENA_GET(x)\
FIELD_GET(QSYS_PAUSE_CFG_AGGRESSIVE_TAILDROP_ENA, x)
-/* QSYS:PAUSE_CFG:ATOP */
-#define QSYS_ATOP(r) __REG(TARGET_QSYS,\
- 0, 1, 544, 0, 1, 1128, 284, r, 70, 4)
+/* QSYS:PAUSE_CFG:ATOP */
+#define QSYS_ATOP(r) \
+ __REG(TARGET_QSYS, 0, 1, 544, 0, 1, regs->gsize[GW_QSYS_PAUSE_CFG], \
+ 284, r, regs->rcnt[RC_QSYS_ATOP], 4)
-#define QSYS_ATOP_ATOP GENMASK(11, 0)
+#define QSYS_ATOP_ATOP\
+ GENMASK(regs->fsize[FW_QSYS_ATOP_ATOP] + 0 - 1, 0)
#define QSYS_ATOP_ATOP_SET(x)\
- FIELD_PREP(QSYS_ATOP_ATOP, x)
+ spx5_field_prep(QSYS_ATOP_ATOP, x)
#define QSYS_ATOP_ATOP_GET(x)\
- FIELD_GET(QSYS_ATOP_ATOP, x)
+ spx5_field_get(QSYS_ATOP_ATOP, x)
-/* QSYS:PAUSE_CFG:FWD_PRESSURE */
-#define QSYS_FWD_PRESSURE(r) __REG(TARGET_QSYS,\
- 0, 1, 544, 0, 1, 1128, 564, r, 70, 4)
+/* QSYS:PAUSE_CFG:FWD_PRESSURE */
+#define QSYS_FWD_PRESSURE(r) \
+ __REG(TARGET_QSYS, 0, 1, 544, 0, 1, regs->gsize[GW_QSYS_PAUSE_CFG], \
+ 564, r, regs->rcnt[RC_QSYS_FWD_PRESSURE], 4)
#define QSYS_FWD_PRESSURE_FWD_PRESSURE GENMASK(11, 1)
#define QSYS_FWD_PRESSURE_FWD_PRESSURE_SET(x)\
@@ -6477,19 +7137,22 @@ enum sparx5_target {
#define QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS_GET(x)\
FIELD_GET(QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS, x)
-/* QSYS:PAUSE_CFG:ATOP_TOT_CFG */
-#define QSYS_ATOP_TOT_CFG __REG(TARGET_QSYS,\
- 0, 1, 544, 0, 1, 1128, 844, 0, 1, 4)
+/* QSYS:PAUSE_CFG:ATOP_TOT_CFG */
+#define QSYS_ATOP_TOT_CFG \
+ __REG(TARGET_QSYS, 0, 1, 544, 0, 1, regs->gsize[GW_QSYS_PAUSE_CFG], \
+ 844, 0, 1, 4)
-#define QSYS_ATOP_TOT_CFG_ATOP_TOT GENMASK(11, 0)
+#define QSYS_ATOP_TOT_CFG_ATOP_TOT\
+ GENMASK(regs->fsize[FW_QSYS_ATOP_TOT_CFG_ATOP_TOT] + 0 - 1, 0)
#define QSYS_ATOP_TOT_CFG_ATOP_TOT_SET(x)\
- FIELD_PREP(QSYS_ATOP_TOT_CFG_ATOP_TOT, x)
+ spx5_field_prep(QSYS_ATOP_TOT_CFG_ATOP_TOT, x)
#define QSYS_ATOP_TOT_CFG_ATOP_TOT_GET(x)\
- FIELD_GET(QSYS_ATOP_TOT_CFG_ATOP_TOT, x)
+ spx5_field_get(QSYS_ATOP_TOT_CFG_ATOP_TOT, x)
-/* QSYS:CALCFG:CAL_AUTO */
-#define QSYS_CAL_AUTO(r) __REG(TARGET_QSYS,\
- 0, 1, 2304, 0, 1, 40, 0, r, 7, 4)
+/* QSYS:CALCFG:CAL_AUTO */
+#define QSYS_CAL_AUTO(r) \
+ __REG(TARGET_QSYS, 0, 1, regs->gaddr[GA_QSYS_CALCFG], 0, 1, 40, 0, r, \
+ regs->rcnt[RC_QSYS_CAL_AUTO], 4)
#define QSYS_CAL_AUTO_CAL_AUTO GENMASK(29, 0)
#define QSYS_CAL_AUTO_CAL_AUTO_SET(x)\
@@ -6497,9 +7160,10 @@ enum sparx5_target {
#define QSYS_CAL_AUTO_CAL_AUTO_GET(x)\
FIELD_GET(QSYS_CAL_AUTO_CAL_AUTO, x)
-/* QSYS:CALCFG:CAL_CTRL */
-#define QSYS_CAL_CTRL __REG(TARGET_QSYS,\
- 0, 1, 2304, 0, 1, 40, 36, 0, 1, 4)
+/* QSYS:CALCFG:CAL_CTRL */
+#define QSYS_CAL_CTRL \
+ __REG(TARGET_QSYS, 0, 1, regs->gaddr[GA_QSYS_CALCFG], 0, 1, 40, 36, 0, \
+ 1, 4)
#define QSYS_CAL_CTRL_CAL_MODE GENMASK(14, 11)
#define QSYS_CAL_CTRL_CAL_MODE_SET(x)\
@@ -6519,9 +7183,10 @@ enum sparx5_target {
#define QSYS_CAL_CTRL_CAL_AUTO_ERROR_GET(x)\
FIELD_GET(QSYS_CAL_CTRL_CAL_AUTO_ERROR, x)
-/* QSYS:RAM_CTRL:RAM_INIT */
-#define QSYS_RAM_INIT __REG(TARGET_QSYS,\
- 0, 1, 2344, 0, 1, 4, 0, 0, 1, 4)
+/* QSYS:RAM_CTRL:RAM_INIT */
+#define QSYS_RAM_INIT \
+ __REG(TARGET_QSYS, 0, 1, regs->gaddr[GA_QSYS_RAM_CTRL], 0, 1, 4, 0, 0, \
+ 1, 4)
#define QSYS_RAM_INIT_RAM_INIT BIT(1)
#define QSYS_RAM_INIT_RAM_INIT_SET(x)\
@@ -6535,9 +7200,10 @@ enum sparx5_target {
#define QSYS_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(QSYS_RAM_INIT_RAM_CFG_HOOK, x)
-/* REW:COMMON:OWN_UPSID */
-#define REW_OWN_UPSID(r) __REG(TARGET_REW,\
- 0, 1, 387264, 0, 1, 1232, 0, r, 3, 4)
+/* REW:COMMON:OWN_UPSID */
+#define REW_OWN_UPSID(r) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_COMMON], 0, 1, 1232, 0, r, \
+ regs->rcnt[RC_REW_OWN_UPSID], 4)
#define REW_OWN_UPSID_OWN_UPSID GENMASK(4, 0)
#define REW_OWN_UPSID_OWN_UPSID_SET(x)\
@@ -6545,15 +7211,17 @@ enum sparx5_target {
#define REW_OWN_UPSID_OWN_UPSID_GET(x)\
FIELD_GET(REW_OWN_UPSID_OWN_UPSID, x)
-/* REW:COMMON:RTAG_ETAG_CTRL */
-#define REW_RTAG_ETAG_CTRL(r) __REG(TARGET_REW,\
- 0, 1, 387264, 0, 1, 1232, 560, r, 70, 4)
+/* REW:COMMON:RTAG_ETAG_CTRL */
+#define REW_RTAG_ETAG_CTRL(r) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_COMMON], 0, 1, 1232, 560, r,\
+ regs->rcnt[RC_REW_RTAG_ETAG_CTRL], 4)
-#define REW_RTAG_ETAG_CTRL_IPE_TBL GENMASK(9, 3)
+#define REW_RTAG_ETAG_CTRL_IPE_TBL\
+ GENMASK(regs->fsize[FW_REW_RTAG_ETAG_CTRL_IPE_TBL] + 3 - 1, 3)
#define REW_RTAG_ETAG_CTRL_IPE_TBL_SET(x)\
- FIELD_PREP(REW_RTAG_ETAG_CTRL_IPE_TBL, x)
+ spx5_field_prep(REW_RTAG_ETAG_CTRL_IPE_TBL, x)
#define REW_RTAG_ETAG_CTRL_IPE_TBL_GET(x)\
- FIELD_GET(REW_RTAG_ETAG_CTRL_IPE_TBL, x)
+ spx5_field_get(REW_RTAG_ETAG_CTRL_IPE_TBL, x)
#define REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA GENMASK(2, 1)
#define REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_SET(x)\
@@ -6567,9 +7235,10 @@ enum sparx5_target {
#define REW_RTAG_ETAG_CTRL_KEEP_ETAG_GET(x)\
FIELD_GET(REW_RTAG_ETAG_CTRL_KEEP_ETAG, x)
-/* REW:COMMON:ES0_CTRL */
-#define REW_ES0_CTRL __REG(TARGET_REW,\
- 0, 1, 387264, 0, 1, 1232, 852, 0, 1, 4)
+/* REW:COMMON:ES0_CTRL */
+#define REW_ES0_CTRL \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_COMMON], 0, 1, 1232, 852, 0,\
+ 1, 4)
#define REW_ES0_CTRL_ES0_BY_RT_FWD BIT(5)
#define REW_ES0_CTRL_ES0_BY_RT_FWD_SET(x)\
@@ -6607,9 +7276,10 @@ enum sparx5_target {
#define REW_ES0_CTRL_ES0_LU_ENA_GET(x)\
FIELD_GET(REW_ES0_CTRL_ES0_LU_ENA, x)
-/* REW:PORT:PORT_VLAN_CFG */
-#define REW_PORT_VLAN_CFG(g) __REG(TARGET_REW,\
- 0, 1, 360448, g, 70, 256, 0, 0, 1, 4)
+/* REW:PORT:PORT_VLAN_CFG */
+#define REW_PORT_VLAN_CFG(g) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_PORT], g, \
+ regs->gcnt[GC_REW_PORT], 256, 0, 0, 1, 4)
#define REW_PORT_VLAN_CFG_PORT_PCP GENMASK(15, 13)
#define REW_PORT_VLAN_CFG_PORT_PCP_SET(x)\
@@ -6629,9 +7299,10 @@ enum sparx5_target {
#define REW_PORT_VLAN_CFG_PORT_VID_GET(x)\
FIELD_GET(REW_PORT_VLAN_CFG_PORT_VID, x)
-/* REW:PORT:PCP_MAP_DE0 */
-#define REW_PCP_MAP_DE0(g, r) __REG(TARGET_REW,\
- 0, 1, 360448, g, 70, 256, 4, r, 8, 4)
+/* REW:PORT:PCP_MAP_DE0 */
+#define REW_PCP_MAP_DE0(g, r) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_PORT], g, \
+ regs->gcnt[GC_REW_PORT], 256, 4, r, 8, 4)
#define REW_PCP_MAP_DE0_PCP_DE0 GENMASK(2, 0)
#define REW_PCP_MAP_DE0_PCP_DE0_SET(x)\
@@ -6639,9 +7310,10 @@ enum sparx5_target {
#define REW_PCP_MAP_DE0_PCP_DE0_GET(x)\
FIELD_GET(REW_PCP_MAP_DE0_PCP_DE0, x)
-/* REW:PORT:PCP_MAP_DE1 */
-#define REW_PCP_MAP_DE1(g, r) __REG(TARGET_REW,\
- 0, 1, 360448, g, 70, 256, 36, r, 8, 4)
+/* REW:PORT:PCP_MAP_DE1 */
+#define REW_PCP_MAP_DE1(g, r) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_PORT], g, \
+ regs->gcnt[GC_REW_PORT], 256, 36, r, 8, 4)
#define REW_PCP_MAP_DE1_PCP_DE1 GENMASK(2, 0)
#define REW_PCP_MAP_DE1_PCP_DE1_SET(x)\
@@ -6649,9 +7321,10 @@ enum sparx5_target {
#define REW_PCP_MAP_DE1_PCP_DE1_GET(x)\
FIELD_GET(REW_PCP_MAP_DE1_PCP_DE1, x)
-/* REW:PORT:DEI_MAP_DE0 */
-#define REW_DEI_MAP_DE0(g, r) __REG(TARGET_REW,\
- 0, 1, 360448, g, 70, 256, 68, r, 8, 4)
+/* REW:PORT:DEI_MAP_DE0 */
+#define REW_DEI_MAP_DE0(g, r) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_PORT], g, \
+ regs->gcnt[GC_REW_PORT], 256, 68, r, 8, 4)
#define REW_DEI_MAP_DE0_DEI_DE0 BIT(0)
#define REW_DEI_MAP_DE0_DEI_DE0_SET(x)\
@@ -6659,9 +7332,10 @@ enum sparx5_target {
#define REW_DEI_MAP_DE0_DEI_DE0_GET(x)\
FIELD_GET(REW_DEI_MAP_DE0_DEI_DE0, x)
-/* REW:PORT:DEI_MAP_DE1 */
-#define REW_DEI_MAP_DE1(g, r) __REG(TARGET_REW,\
- 0, 1, 360448, g, 70, 256, 100, r, 8, 4)
+/* REW:PORT:DEI_MAP_DE1 */
+#define REW_DEI_MAP_DE1(g, r) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_PORT], g, \
+ regs->gcnt[GC_REW_PORT], 256, 100, r, 8, 4)
#define REW_DEI_MAP_DE1_DEI_DE1 BIT(0)
#define REW_DEI_MAP_DE1_DEI_DE1_SET(x)\
@@ -6669,9 +7343,10 @@ enum sparx5_target {
#define REW_DEI_MAP_DE1_DEI_DE1_GET(x)\
FIELD_GET(REW_DEI_MAP_DE1_DEI_DE1, x)
-/* REW:PORT:TAG_CTRL */
-#define REW_TAG_CTRL(g) __REG(TARGET_REW,\
- 0, 1, 360448, g, 70, 256, 132, 0, 1, 4)
+/* REW:PORT:TAG_CTRL */
+#define REW_TAG_CTRL(g) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_PORT], g, \
+ regs->gcnt[GC_REW_PORT], 256, 132, 0, 1, 4)
#define REW_TAG_CTRL_TAG_CFG_OBEY_WAS_TAGGED BIT(13)
#define REW_TAG_CTRL_TAG_CFG_OBEY_WAS_TAGGED_SET(x)\
@@ -6709,9 +7384,10 @@ enum sparx5_target {
#define REW_TAG_CTRL_TAG_DEI_CFG_GET(x)\
FIELD_GET(REW_TAG_CTRL_TAG_DEI_CFG, x)
-/* REW:PORT:DSCP_MAP */
-#define REW_DSCP_MAP(g) __REG(TARGET_REW,\
- 0, 1, 360448, g, 70, 256, 136, 0, 1, 4)
+/* REW:PORT:DSCP_MAP */
+#define REW_DSCP_MAP(g) \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_PORT], g, \
+ regs->gcnt[GC_REW_PORT], 256, 136, 0, 1, 4)
#define REW_DSCP_MAP_DSCP_UPDATE_ENA BIT(1)
#define REW_DSCP_MAP_DSCP_UPDATE_ENA_SET(x)\
@@ -6725,9 +7401,10 @@ enum sparx5_target {
#define REW_DSCP_MAP_DSCP_REMAP_ENA_GET(x)\
FIELD_GET(REW_DSCP_MAP_DSCP_REMAP_ENA, x)
-/* REW:PTP_CTRL:PTP_TWOSTEP_CTRL */
-#define REW_PTP_TWOSTEP_CTRL __REG(TARGET_REW,\
- 0, 1, 378368, 0, 1, 40, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* REW:PTP_CTRL:PTP_TWOSTEP_CTRL */
+#define REW_PTP_TWOSTEP_CTRL \
+ __REG(TARGET_REW, 0, 1, 378368, 0, 1, 40, 0, 0, 1, 4)
#define REW_PTP_TWOSTEP_CTRL_PTP_OVWR_ENA BIT(12)
#define REW_PTP_TWOSTEP_CTRL_PTP_OVWR_ENA_SET(x)\
@@ -6765,9 +7442,10 @@ enum sparx5_target {
#define REW_PTP_TWOSTEP_CTRL_PTP_OVFL_GET(x)\
FIELD_GET(REW_PTP_TWOSTEP_CTRL_PTP_OVFL, x)
-/* REW:PTP_CTRL:PTP_TWOSTEP_STAMP */
-#define REW_PTP_TWOSTEP_STAMP __REG(TARGET_REW,\
- 0, 1, 378368, 0, 1, 40, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* REW:PTP_CTRL:PTP_TWOSTEP_STAMP */
+#define REW_PTP_TWOSTEP_STAMP \
+ __REG(TARGET_REW, 0, 1, 378368, 0, 1, 40, 4, 0, 1, 4)
#define REW_PTP_TWOSTEP_STAMP_STAMP_NSEC GENMASK(29, 0)
#define REW_PTP_TWOSTEP_STAMP_STAMP_NSEC_SET(x)\
@@ -6775,9 +7453,10 @@ enum sparx5_target {
#define REW_PTP_TWOSTEP_STAMP_STAMP_NSEC_GET(x)\
FIELD_GET(REW_PTP_TWOSTEP_STAMP_STAMP_NSEC, x)
-/* REW:PTP_CTRL:PTP_TWOSTEP_STAMP_SUBNS */
-#define REW_PTP_TWOSTEP_STAMP_SUBNS __REG(TARGET_REW,\
- 0, 1, 378368, 0, 1, 40, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* REW:PTP_CTRL:PTP_TWOSTEP_STAMP_SUBNS */
+#define REW_PTP_TWOSTEP_STAMP_SUBNS \
+ __REG(TARGET_REW, 0, 1, 378368, 0, 1, 40, 8, 0, 1, 4)
#define REW_PTP_TWOSTEP_STAMP_SUBNS_STAMP_SUB_NSEC GENMASK(7, 0)
#define REW_PTP_TWOSTEP_STAMP_SUBNS_STAMP_SUB_NSEC_SET(x)\
@@ -6785,17 +7464,20 @@ enum sparx5_target {
#define REW_PTP_TWOSTEP_STAMP_SUBNS_STAMP_SUB_NSEC_GET(x)\
FIELD_GET(REW_PTP_TWOSTEP_STAMP_SUBNS_STAMP_SUB_NSEC, x)
-/* REW:PTP_CTRL:PTP_RSRV_NOT_ZERO */
-#define REW_PTP_RSRV_NOT_ZERO __REG(TARGET_REW,\
- 0, 1, 378368, 0, 1, 40, 12, 0, 1, 4)
+/* SPARX5 ONLY */
+/* REW:PTP_CTRL:PTP_RSRV_NOT_ZERO */
+#define REW_PTP_RSRV_NOT_ZERO \
+ __REG(TARGET_REW, 0, 1, 378368, 0, 1, 40, 12, 0, 1, 4)
-/* REW:PTP_CTRL:PTP_RSRV_NOT_ZERO1 */
-#define REW_PTP_RSRV_NOT_ZERO1 __REG(TARGET_REW,\
- 0, 1, 378368, 0, 1, 40, 16, 0, 1, 4)
+/* SPARX5 ONLY */
+/* REW:PTP_CTRL:PTP_RSRV_NOT_ZERO1 */
+#define REW_PTP_RSRV_NOT_ZERO1 \
+ __REG(TARGET_REW, 0, 1, 378368, 0, 1, 40, 16, 0, 1, 4)
-/* REW:PTP_CTRL:PTP_RSRV_NOT_ZERO2 */
-#define REW_PTP_RSRV_NOT_ZERO2 __REG(TARGET_REW,\
- 0, 1, 378368, 0, 1, 40, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* REW:PTP_CTRL:PTP_RSRV_NOT_ZERO2 */
+#define REW_PTP_RSRV_NOT_ZERO2 \
+ __REG(TARGET_REW, 0, 1, 378368, 0, 1, 40, 20, 0, 1, 4)
#define REW_PTP_RSRV_NOT_ZERO2_PTP_RSRV_NOT_ZERO2 GENMASK(5, 0)
#define REW_PTP_RSRV_NOT_ZERO2_PTP_RSRV_NOT_ZERO2_SET(x)\
@@ -6803,9 +7485,10 @@ enum sparx5_target {
#define REW_PTP_RSRV_NOT_ZERO2_PTP_RSRV_NOT_ZERO2_GET(x)\
FIELD_GET(REW_PTP_RSRV_NOT_ZERO2_PTP_RSRV_NOT_ZERO2, x)
-/* REW:PTP_CTRL:PTP_GEN_STAMP_FMT */
-#define REW_PTP_GEN_STAMP_FMT(r) __REG(TARGET_REW,\
- 0, 1, 378368, 0, 1, 40, 24, r, 4, 4)
+/* SPARX5 ONLY */
+/* REW:PTP_CTRL:PTP_GEN_STAMP_FMT */
+#define REW_PTP_GEN_STAMP_FMT(r) \
+ __REG(TARGET_REW, 0, 1, 378368, 0, 1, 40, 24, r, 4, 4)
#define REW_PTP_GEN_STAMP_FMT_RT_OFS GENMASK(6, 2)
#define REW_PTP_GEN_STAMP_FMT_RT_OFS_SET(x)\
@@ -6819,9 +7502,10 @@ enum sparx5_target {
#define REW_PTP_GEN_STAMP_FMT_RT_FMT_GET(x)\
FIELD_GET(REW_PTP_GEN_STAMP_FMT_RT_FMT, x)
-/* REW:RAM_CTRL:RAM_INIT */
-#define REW_RAM_INIT __REG(TARGET_REW,\
- 0, 1, 378696, 0, 1, 4, 0, 0, 1, 4)
+/* REW:RAM_CTRL:RAM_INIT */
+#define REW_RAM_INIT \
+ __REG(TARGET_REW, 0, 1, regs->gaddr[GA_REW_RAM_CTRL], 0, 1, 4, 0, 0, 1,\
+ 4)
#define REW_RAM_INIT_RAM_INIT BIT(1)
#define REW_RAM_INIT_RAM_INIT_SET(x)\
@@ -6835,9 +7519,9 @@ enum sparx5_target {
#define REW_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(REW_RAM_INIT_RAM_CFG_HOOK, x)
-/* VCAP_ES0:VCAP_CORE_CFG:VCAP_UPDATE_CTRL */
-#define VCAP_ES0_CTRL __REG(TARGET_VCAP_ES0,\
- 0, 1, 0, 0, 1, 8, 0, 0, 1, 4)
+/* VCAP_ES0:VCAP_CORE_CFG:VCAP_UPDATE_CTRL */
+#define VCAP_ES0_CTRL \
+ __REG(TARGET_VCAP_ES0, 0, 1, 0, 0, 1, 8, 0, 0, 1, 4)
#define VCAP_ES0_CTRL_UPDATE_CMD GENMASK(24, 22)
#define VCAP_ES0_CTRL_UPDATE_CMD_SET(x)\
@@ -6887,9 +7571,9 @@ enum sparx5_target {
#define VCAP_ES0_CTRL_MV_TRAFFIC_IGN_GET(x)\
FIELD_GET(VCAP_ES0_CTRL_MV_TRAFFIC_IGN, x)
-/* VCAP_ES0:VCAP_CORE_CFG:VCAP_MV_CFG */
-#define VCAP_ES0_CFG __REG(TARGET_VCAP_ES0,\
- 0, 1, 0, 0, 1, 8, 4, 0, 1, 4)
+/* VCAP_ES0:VCAP_CORE_CFG:VCAP_MV_CFG */
+#define VCAP_ES0_CFG \
+ __REG(TARGET_VCAP_ES0, 0, 1, 0, 0, 1, 8, 4, 0, 1, 4)
#define VCAP_ES0_CFG_MV_NUM_POS GENMASK(31, 16)
#define VCAP_ES0_CFG_MV_NUM_POS_SET(x)\
@@ -6903,33 +7587,33 @@ enum sparx5_target {
#define VCAP_ES0_CFG_MV_SIZE_GET(x)\
FIELD_GET(VCAP_ES0_CFG_MV_SIZE, x)
-/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_ENTRY_DAT */
-#define VCAP_ES0_VCAP_ENTRY_DAT(r) __REG(TARGET_VCAP_ES0,\
- 0, 1, 8, 0, 1, 904, 0, r, 64, 4)
+/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_ENTRY_DAT */
+#define VCAP_ES0_VCAP_ENTRY_DAT(r) \
+ __REG(TARGET_VCAP_ES0, 0, 1, 8, 0, 1, 904, 0, r, 64, 4)
-/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_MASK_DAT */
-#define VCAP_ES0_VCAP_MASK_DAT(r) __REG(TARGET_VCAP_ES0,\
- 0, 1, 8, 0, 1, 904, 256, r, 64, 4)
+/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_MASK_DAT */
+#define VCAP_ES0_VCAP_MASK_DAT(r) \
+ __REG(TARGET_VCAP_ES0, 0, 1, 8, 0, 1, 904, 256, r, 64, 4)
-/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_ACTION_DAT */
-#define VCAP_ES0_VCAP_ACTION_DAT(r) __REG(TARGET_VCAP_ES0,\
- 0, 1, 8, 0, 1, 904, 512, r, 64, 4)
+/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_ACTION_DAT */
+#define VCAP_ES0_VCAP_ACTION_DAT(r) \
+ __REG(TARGET_VCAP_ES0, 0, 1, 8, 0, 1, 904, 512, r, 64, 4)
-/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_CNT_DAT */
-#define VCAP_ES0_VCAP_CNT_DAT(r) __REG(TARGET_VCAP_ES0,\
- 0, 1, 8, 0, 1, 904, 768, r, 32, 4)
+/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_CNT_DAT */
+#define VCAP_ES0_VCAP_CNT_DAT(r) \
+ __REG(TARGET_VCAP_ES0, 0, 1, 8, 0, 1, 904, 768, r, 32, 4)
-/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_CNT_FW_DAT */
-#define VCAP_ES0_VCAP_CNT_FW_DAT __REG(TARGET_VCAP_ES0,\
- 0, 1, 8, 0, 1, 904, 896, 0, 1, 4)
+/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_CNT_FW_DAT */
+#define VCAP_ES0_VCAP_CNT_FW_DAT \
+ __REG(TARGET_VCAP_ES0, 0, 1, 8, 0, 1, 904, 896, 0, 1, 4)
-/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_TG_DAT */
-#define VCAP_ES0_VCAP_TG_DAT __REG(TARGET_VCAP_ES0,\
- 0, 1, 8, 0, 1, 904, 900, 0, 1, 4)
+/* VCAP_ES0:VCAP_CORE_CACHE:VCAP_TG_DAT */
+#define VCAP_ES0_VCAP_TG_DAT \
+ __REG(TARGET_VCAP_ES0, 0, 1, 8, 0, 1, 904, 900, 0, 1, 4)
-/* VCAP_ES0:VCAP_CORE_MAP:VCAP_CORE_IDX */
-#define VCAP_ES0_IDX __REG(TARGET_VCAP_ES0,\
- 0, 1, 912, 0, 1, 8, 0, 0, 1, 4)
+/* VCAP_ES0:VCAP_CORE_MAP:VCAP_CORE_IDX */
+#define VCAP_ES0_IDX \
+ __REG(TARGET_VCAP_ES0, 0, 1, 912, 0, 1, 8, 0, 0, 1, 4)
#define VCAP_ES0_IDX_CORE_IDX GENMASK(3, 0)
#define VCAP_ES0_IDX_CORE_IDX_SET(x)\
@@ -6937,9 +7621,9 @@ enum sparx5_target {
#define VCAP_ES0_IDX_CORE_IDX_GET(x)\
FIELD_GET(VCAP_ES0_IDX_CORE_IDX, x)
-/* VCAP_ES0:VCAP_CORE_MAP:VCAP_CORE_MAP */
-#define VCAP_ES0_MAP __REG(TARGET_VCAP_ES0,\
- 0, 1, 912, 0, 1, 8, 4, 0, 1, 4)
+/* VCAP_ES0:VCAP_CORE_MAP:VCAP_CORE_MAP */
+#define VCAP_ES0_MAP \
+ __REG(TARGET_VCAP_ES0, 0, 1, 912, 0, 1, 8, 4, 0, 1, 4)
#define VCAP_ES0_MAP_CORE_MAP GENMASK(2, 0)
#define VCAP_ES0_MAP_CORE_MAP_SET(x)\
@@ -6947,9 +7631,9 @@ enum sparx5_target {
#define VCAP_ES0_MAP_CORE_MAP_GET(x)\
FIELD_GET(VCAP_ES0_MAP_CORE_MAP, x)
-/* VCAP_ES0:VCAP_CORE_STICKY:VCAP_STICKY */
-#define VCAP_ES0_VCAP_STICKY __REG(TARGET_VCAP_ES0,\
- 0, 1, 920, 0, 1, 4, 0, 0, 1, 4)
+/* VCAP_ES0:VCAP_CORE_STICKY:VCAP_STICKY */
+#define VCAP_ES0_VCAP_STICKY \
+ __REG(TARGET_VCAP_ES0, 0, 1, 920, 0, 1, 4, 0, 0, 1, 4)
#define VCAP_ES0_VCAP_STICKY_VCAP_ROW_DELETED_STICKY BIT(0)
#define VCAP_ES0_VCAP_STICKY_VCAP_ROW_DELETED_STICKY_SET(x)\
@@ -6957,49 +7641,49 @@ enum sparx5_target {
#define VCAP_ES0_VCAP_STICKY_VCAP_ROW_DELETED_STICKY_GET(x)\
FIELD_GET(VCAP_ES0_VCAP_STICKY_VCAP_ROW_DELETED_STICKY, x)
-/* VCAP_ES0:VCAP_CONST:VCAP_VER */
-#define VCAP_ES0_VCAP_VER __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 0, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:VCAP_VER */
+#define VCAP_ES0_VCAP_VER \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 0, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:ENTRY_WIDTH */
-#define VCAP_ES0_ENTRY_WIDTH __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 4, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:ENTRY_WIDTH */
+#define VCAP_ES0_ENTRY_WIDTH \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 4, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:ENTRY_CNT */
-#define VCAP_ES0_ENTRY_CNT __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 8, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:ENTRY_CNT */
+#define VCAP_ES0_ENTRY_CNT \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 8, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:ENTRY_SWCNT */
-#define VCAP_ES0_ENTRY_SWCNT __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 12, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:ENTRY_SWCNT */
+#define VCAP_ES0_ENTRY_SWCNT \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 12, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:ENTRY_TG_WIDTH */
-#define VCAP_ES0_ENTRY_TG_WIDTH __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 16, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:ENTRY_TG_WIDTH */
+#define VCAP_ES0_ENTRY_TG_WIDTH \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 16, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:ACTION_DEF_CNT */
-#define VCAP_ES0_ACTION_DEF_CNT __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 20, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:ACTION_DEF_CNT */
+#define VCAP_ES0_ACTION_DEF_CNT \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 20, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:ACTION_WIDTH */
-#define VCAP_ES0_ACTION_WIDTH __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 24, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:ACTION_WIDTH */
+#define VCAP_ES0_ACTION_WIDTH \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 24, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:CNT_WIDTH */
-#define VCAP_ES0_CNT_WIDTH __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 28, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:CNT_WIDTH */
+#define VCAP_ES0_CNT_WIDTH \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 28, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:CORE_CNT */
-#define VCAP_ES0_CORE_CNT __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 32, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:CORE_CNT */
+#define VCAP_ES0_CORE_CNT \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 32, 0, 1, 4)
-/* VCAP_ES0:VCAP_CONST:IF_CNT */
-#define VCAP_ES0_IF_CNT __REG(TARGET_VCAP_ES0,\
- 0, 1, 924, 0, 1, 40, 36, 0, 1, 4)
+/* VCAP_ES0:VCAP_CONST:IF_CNT */
+#define VCAP_ES0_IF_CNT \
+ __REG(TARGET_VCAP_ES0, 0, 1, 924, 0, 1, 40, 36, 0, 1, 4)
-/* VCAP_ES2:VCAP_CORE_CFG:VCAP_UPDATE_CTRL */
-#define VCAP_ES2_CTRL __REG(TARGET_VCAP_ES2,\
- 0, 1, 0, 0, 1, 8, 0, 0, 1, 4)
+/* VCAP_ES2:VCAP_CORE_CFG:VCAP_UPDATE_CTRL */
+#define VCAP_ES2_CTRL \
+ __REG(TARGET_VCAP_ES2, 0, 1, 0, 0, 1, 8, 0, 0, 1, 4)
#define VCAP_ES2_CTRL_UPDATE_CMD GENMASK(24, 22)
#define VCAP_ES2_CTRL_UPDATE_CMD_SET(x)\
@@ -7049,9 +7733,9 @@ enum sparx5_target {
#define VCAP_ES2_CTRL_MV_TRAFFIC_IGN_GET(x)\
FIELD_GET(VCAP_ES2_CTRL_MV_TRAFFIC_IGN, x)
-/* VCAP_ES2:VCAP_CORE_CFG:VCAP_MV_CFG */
-#define VCAP_ES2_CFG __REG(TARGET_VCAP_ES2,\
- 0, 1, 0, 0, 1, 8, 4, 0, 1, 4)
+/* VCAP_ES2:VCAP_CORE_CFG:VCAP_MV_CFG */
+#define VCAP_ES2_CFG \
+ __REG(TARGET_VCAP_ES2, 0, 1, 0, 0, 1, 8, 4, 0, 1, 4)
#define VCAP_ES2_CFG_MV_NUM_POS GENMASK(31, 16)
#define VCAP_ES2_CFG_MV_NUM_POS_SET(x)\
@@ -7065,33 +7749,33 @@ enum sparx5_target {
#define VCAP_ES2_CFG_MV_SIZE_GET(x)\
FIELD_GET(VCAP_ES2_CFG_MV_SIZE, x)
-/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_ENTRY_DAT */
-#define VCAP_ES2_VCAP_ENTRY_DAT(r) __REG(TARGET_VCAP_ES2,\
- 0, 1, 8, 0, 1, 904, 0, r, 64, 4)
+/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_ENTRY_DAT */
+#define VCAP_ES2_VCAP_ENTRY_DAT(r) \
+ __REG(TARGET_VCAP_ES2, 0, 1, 8, 0, 1, 904, 0, r, 64, 4)
-/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_MASK_DAT */
-#define VCAP_ES2_VCAP_MASK_DAT(r) __REG(TARGET_VCAP_ES2,\
- 0, 1, 8, 0, 1, 904, 256, r, 64, 4)
+/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_MASK_DAT */
+#define VCAP_ES2_VCAP_MASK_DAT(r) \
+ __REG(TARGET_VCAP_ES2, 0, 1, 8, 0, 1, 904, 256, r, 64, 4)
-/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_ACTION_DAT */
-#define VCAP_ES2_VCAP_ACTION_DAT(r) __REG(TARGET_VCAP_ES2,\
- 0, 1, 8, 0, 1, 904, 512, r, 64, 4)
+/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_ACTION_DAT */
+#define VCAP_ES2_VCAP_ACTION_DAT(r) \
+ __REG(TARGET_VCAP_ES2, 0, 1, 8, 0, 1, 904, 512, r, 64, 4)
-/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_CNT_DAT */
-#define VCAP_ES2_VCAP_CNT_DAT(r) __REG(TARGET_VCAP_ES2,\
- 0, 1, 8, 0, 1, 904, 768, r, 32, 4)
+/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_CNT_DAT */
+#define VCAP_ES2_VCAP_CNT_DAT(r) \
+ __REG(TARGET_VCAP_ES2, 0, 1, 8, 0, 1, 904, 768, r, 32, 4)
-/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_CNT_FW_DAT */
-#define VCAP_ES2_VCAP_CNT_FW_DAT __REG(TARGET_VCAP_ES2,\
- 0, 1, 8, 0, 1, 904, 896, 0, 1, 4)
+/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_CNT_FW_DAT */
+#define VCAP_ES2_VCAP_CNT_FW_DAT \
+ __REG(TARGET_VCAP_ES2, 0, 1, 8, 0, 1, 904, 896, 0, 1, 4)
-/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_TG_DAT */
-#define VCAP_ES2_VCAP_TG_DAT __REG(TARGET_VCAP_ES2,\
- 0, 1, 8, 0, 1, 904, 900, 0, 1, 4)
+/* VCAP_ES2:VCAP_CORE_CACHE:VCAP_TG_DAT */
+#define VCAP_ES2_VCAP_TG_DAT \
+ __REG(TARGET_VCAP_ES2, 0, 1, 8, 0, 1, 904, 900, 0, 1, 4)
-/* VCAP_ES2:VCAP_CORE_MAP:VCAP_CORE_IDX */
-#define VCAP_ES2_IDX __REG(TARGET_VCAP_ES2,\
- 0, 1, 912, 0, 1, 8, 0, 0, 1, 4)
+/* VCAP_ES2:VCAP_CORE_MAP:VCAP_CORE_IDX */
+#define VCAP_ES2_IDX \
+ __REG(TARGET_VCAP_ES2, 0, 1, 912, 0, 1, 8, 0, 0, 1, 4)
#define VCAP_ES2_IDX_CORE_IDX GENMASK(3, 0)
#define VCAP_ES2_IDX_CORE_IDX_SET(x)\
@@ -7099,9 +7783,9 @@ enum sparx5_target {
#define VCAP_ES2_IDX_CORE_IDX_GET(x)\
FIELD_GET(VCAP_ES2_IDX_CORE_IDX, x)
-/* VCAP_ES2:VCAP_CORE_MAP:VCAP_CORE_MAP */
-#define VCAP_ES2_MAP __REG(TARGET_VCAP_ES2,\
- 0, 1, 912, 0, 1, 8, 4, 0, 1, 4)
+/* VCAP_ES2:VCAP_CORE_MAP:VCAP_CORE_MAP */
+#define VCAP_ES2_MAP \
+ __REG(TARGET_VCAP_ES2, 0, 1, 912, 0, 1, 8, 4, 0, 1, 4)
#define VCAP_ES2_MAP_CORE_MAP GENMASK(2, 0)
#define VCAP_ES2_MAP_CORE_MAP_SET(x)\
@@ -7109,9 +7793,9 @@ enum sparx5_target {
#define VCAP_ES2_MAP_CORE_MAP_GET(x)\
FIELD_GET(VCAP_ES2_MAP_CORE_MAP, x)
-/* VCAP_ES2:VCAP_CORE_STICKY:VCAP_STICKY */
-#define VCAP_ES2_VCAP_STICKY __REG(TARGET_VCAP_ES2,\
- 0, 1, 920, 0, 1, 4, 0, 0, 1, 4)
+/* VCAP_ES2:VCAP_CORE_STICKY:VCAP_STICKY */
+#define VCAP_ES2_VCAP_STICKY \
+ __REG(TARGET_VCAP_ES2, 0, 1, 920, 0, 1, 4, 0, 0, 1, 4)
#define VCAP_ES2_VCAP_STICKY_VCAP_ROW_DELETED_STICKY BIT(0)
#define VCAP_ES2_VCAP_STICKY_VCAP_ROW_DELETED_STICKY_SET(x)\
@@ -7119,49 +7803,49 @@ enum sparx5_target {
#define VCAP_ES2_VCAP_STICKY_VCAP_ROW_DELETED_STICKY_GET(x)\
FIELD_GET(VCAP_ES2_VCAP_STICKY_VCAP_ROW_DELETED_STICKY, x)
-/* VCAP_ES2:VCAP_CONST:VCAP_VER */
-#define VCAP_ES2_VCAP_VER __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 0, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:VCAP_VER */
+#define VCAP_ES2_VCAP_VER \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 0, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:ENTRY_WIDTH */
-#define VCAP_ES2_ENTRY_WIDTH __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 4, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:ENTRY_WIDTH */
+#define VCAP_ES2_ENTRY_WIDTH \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 4, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:ENTRY_CNT */
-#define VCAP_ES2_ENTRY_CNT __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 8, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:ENTRY_CNT */
+#define VCAP_ES2_ENTRY_CNT \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 8, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:ENTRY_SWCNT */
-#define VCAP_ES2_ENTRY_SWCNT __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 12, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:ENTRY_SWCNT */
+#define VCAP_ES2_ENTRY_SWCNT \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 12, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:ENTRY_TG_WIDTH */
-#define VCAP_ES2_ENTRY_TG_WIDTH __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 16, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:ENTRY_TG_WIDTH */
+#define VCAP_ES2_ENTRY_TG_WIDTH \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 16, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:ACTION_DEF_CNT */
-#define VCAP_ES2_ACTION_DEF_CNT __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 20, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:ACTION_DEF_CNT */
+#define VCAP_ES2_ACTION_DEF_CNT \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 20, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:ACTION_WIDTH */
-#define VCAP_ES2_ACTION_WIDTH __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 24, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:ACTION_WIDTH */
+#define VCAP_ES2_ACTION_WIDTH \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 24, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:CNT_WIDTH */
-#define VCAP_ES2_CNT_WIDTH __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 28, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:CNT_WIDTH */
+#define VCAP_ES2_CNT_WIDTH \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 28, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:CORE_CNT */
-#define VCAP_ES2_CORE_CNT __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 32, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:CORE_CNT */
+#define VCAP_ES2_CORE_CNT \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 32, 0, 1, 4)
-/* VCAP_ES2:VCAP_CONST:IF_CNT */
-#define VCAP_ES2_IF_CNT __REG(TARGET_VCAP_ES2,\
- 0, 1, 924, 0, 1, 40, 36, 0, 1, 4)
+/* VCAP_ES2:VCAP_CONST:IF_CNT */
+#define VCAP_ES2_IF_CNT \
+ __REG(TARGET_VCAP_ES2, 0, 1, 924, 0, 1, 40, 36, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CORE_CFG:VCAP_UPDATE_CTRL */
-#define VCAP_SUPER_CTRL __REG(TARGET_VCAP_SUPER,\
- 0, 1, 0, 0, 1, 8, 0, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CORE_CFG:VCAP_UPDATE_CTRL */
+#define VCAP_SUPER_CTRL \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 0, 0, 1, 8, 0, 0, 1, 4)
#define VCAP_SUPER_CTRL_UPDATE_CMD GENMASK(24, 22)
#define VCAP_SUPER_CTRL_UPDATE_CMD_SET(x)\
@@ -7211,9 +7895,9 @@ enum sparx5_target {
#define VCAP_SUPER_CTRL_MV_TRAFFIC_IGN_GET(x)\
FIELD_GET(VCAP_SUPER_CTRL_MV_TRAFFIC_IGN, x)
-/* VCAP_SUPER:VCAP_CORE_CFG:VCAP_MV_CFG */
-#define VCAP_SUPER_CFG __REG(TARGET_VCAP_SUPER,\
- 0, 1, 0, 0, 1, 8, 4, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CORE_CFG:VCAP_MV_CFG */
+#define VCAP_SUPER_CFG \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 0, 0, 1, 8, 4, 0, 1, 4)
#define VCAP_SUPER_CFG_MV_NUM_POS GENMASK(31, 16)
#define VCAP_SUPER_CFG_MV_NUM_POS_SET(x)\
@@ -7227,33 +7911,33 @@ enum sparx5_target {
#define VCAP_SUPER_CFG_MV_SIZE_GET(x)\
FIELD_GET(VCAP_SUPER_CFG_MV_SIZE, x)
-/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_ENTRY_DAT */
-#define VCAP_SUPER_VCAP_ENTRY_DAT(r) __REG(TARGET_VCAP_SUPER,\
- 0, 1, 8, 0, 1, 904, 0, r, 64, 4)
+/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_ENTRY_DAT */
+#define VCAP_SUPER_VCAP_ENTRY_DAT(r) \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 8, 0, 1, 904, 0, r, 64, 4)
-/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_MASK_DAT */
-#define VCAP_SUPER_VCAP_MASK_DAT(r) __REG(TARGET_VCAP_SUPER,\
- 0, 1, 8, 0, 1, 904, 256, r, 64, 4)
+/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_MASK_DAT */
+#define VCAP_SUPER_VCAP_MASK_DAT(r) \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 8, 0, 1, 904, 256, r, 64, 4)
-/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_ACTION_DAT */
-#define VCAP_SUPER_VCAP_ACTION_DAT(r) __REG(TARGET_VCAP_SUPER,\
- 0, 1, 8, 0, 1, 904, 512, r, 64, 4)
+/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_ACTION_DAT */
+#define VCAP_SUPER_VCAP_ACTION_DAT(r) \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 8, 0, 1, 904, 512, r, 64, 4)
-/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_CNT_DAT */
-#define VCAP_SUPER_VCAP_CNT_DAT(r) __REG(TARGET_VCAP_SUPER,\
- 0, 1, 8, 0, 1, 904, 768, r, 32, 4)
+/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_CNT_DAT */
+#define VCAP_SUPER_VCAP_CNT_DAT(r) \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 8, 0, 1, 904, 768, r, 32, 4)
-/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_CNT_FW_DAT */
-#define VCAP_SUPER_VCAP_CNT_FW_DAT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 8, 0, 1, 904, 896, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_CNT_FW_DAT */
+#define VCAP_SUPER_VCAP_CNT_FW_DAT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 8, 0, 1, 904, 896, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_TG_DAT */
-#define VCAP_SUPER_VCAP_TG_DAT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 8, 0, 1, 904, 900, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CORE_CACHE:VCAP_TG_DAT */
+#define VCAP_SUPER_VCAP_TG_DAT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 8, 0, 1, 904, 900, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CORE_MAP:VCAP_CORE_IDX */
-#define VCAP_SUPER_IDX __REG(TARGET_VCAP_SUPER,\
- 0, 1, 912, 0, 1, 8, 0, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CORE_MAP:VCAP_CORE_IDX */
+#define VCAP_SUPER_IDX \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 912, 0, 1, 8, 0, 0, 1, 4)
#define VCAP_SUPER_IDX_CORE_IDX GENMASK(3, 0)
#define VCAP_SUPER_IDX_CORE_IDX_SET(x)\
@@ -7261,9 +7945,9 @@ enum sparx5_target {
#define VCAP_SUPER_IDX_CORE_IDX_GET(x)\
FIELD_GET(VCAP_SUPER_IDX_CORE_IDX, x)
-/* VCAP_SUPER:VCAP_CORE_MAP:VCAP_CORE_MAP */
-#define VCAP_SUPER_MAP __REG(TARGET_VCAP_SUPER,\
- 0, 1, 912, 0, 1, 8, 4, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CORE_MAP:VCAP_CORE_MAP */
+#define VCAP_SUPER_MAP \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 912, 0, 1, 8, 4, 0, 1, 4)
#define VCAP_SUPER_MAP_CORE_MAP GENMASK(2, 0)
#define VCAP_SUPER_MAP_CORE_MAP_SET(x)\
@@ -7271,49 +7955,49 @@ enum sparx5_target {
#define VCAP_SUPER_MAP_CORE_MAP_GET(x)\
FIELD_GET(VCAP_SUPER_MAP_CORE_MAP, x)
-/* VCAP_SUPER:VCAP_CONST:VCAP_VER */
-#define VCAP_SUPER_VCAP_VER __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 0, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:VCAP_VER */
+#define VCAP_SUPER_VCAP_VER \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 0, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:ENTRY_WIDTH */
-#define VCAP_SUPER_ENTRY_WIDTH __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 4, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:ENTRY_WIDTH */
+#define VCAP_SUPER_ENTRY_WIDTH \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 4, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:ENTRY_CNT */
-#define VCAP_SUPER_ENTRY_CNT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 8, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:ENTRY_CNT */
+#define VCAP_SUPER_ENTRY_CNT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 8, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:ENTRY_SWCNT */
-#define VCAP_SUPER_ENTRY_SWCNT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 12, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:ENTRY_SWCNT */
+#define VCAP_SUPER_ENTRY_SWCNT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 12, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:ENTRY_TG_WIDTH */
-#define VCAP_SUPER_ENTRY_TG_WIDTH __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 16, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:ENTRY_TG_WIDTH */
+#define VCAP_SUPER_ENTRY_TG_WIDTH \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 16, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:ACTION_DEF_CNT */
-#define VCAP_SUPER_ACTION_DEF_CNT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 20, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:ACTION_DEF_CNT */
+#define VCAP_SUPER_ACTION_DEF_CNT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 20, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:ACTION_WIDTH */
-#define VCAP_SUPER_ACTION_WIDTH __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 24, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:ACTION_WIDTH */
+#define VCAP_SUPER_ACTION_WIDTH \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 24, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:CNT_WIDTH */
-#define VCAP_SUPER_CNT_WIDTH __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 28, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:CNT_WIDTH */
+#define VCAP_SUPER_CNT_WIDTH \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 28, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:CORE_CNT */
-#define VCAP_SUPER_CORE_CNT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 32, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:CORE_CNT */
+#define VCAP_SUPER_CORE_CNT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 32, 0, 1, 4)
-/* VCAP_SUPER:VCAP_CONST:IF_CNT */
-#define VCAP_SUPER_IF_CNT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 924, 0, 1, 40, 36, 0, 1, 4)
+/* VCAP_SUPER:VCAP_CONST:IF_CNT */
+#define VCAP_SUPER_IF_CNT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 924, 0, 1, 40, 36, 0, 1, 4)
-/* VCAP_SUPER:RAM_CTRL:RAM_INIT */
-#define VCAP_SUPER_RAM_INIT __REG(TARGET_VCAP_SUPER,\
- 0, 1, 1120, 0, 1, 4, 0, 0, 1, 4)
+/* VCAP_SUPER:RAM_CTRL:RAM_INIT */
+#define VCAP_SUPER_RAM_INIT \
+ __REG(TARGET_VCAP_SUPER, 0, 1, 1120, 0, 1, 4, 0, 0, 1, 4)
#define VCAP_SUPER_RAM_INIT_RAM_INIT BIT(1)
#define VCAP_SUPER_RAM_INIT_RAM_INIT_SET(x)\
@@ -7327,9 +8011,10 @@ enum sparx5_target {
#define VCAP_SUPER_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(VCAP_SUPER_RAM_INIT_RAM_CFG_HOOK, x)
-/* VOP:RAM_CTRL:RAM_INIT */
-#define VOP_RAM_INIT __REG(TARGET_VOP,\
- 0, 1, 279176, 0, 1, 4, 0, 0, 1, 4)
+/* VOP:RAM_CTRL:RAM_INIT */
+#define VOP_RAM_INIT \
+ __REG(TARGET_VOP, 0, 1, regs->gaddr[GA_VOP_RAM_CTRL], 0, 1, 4, 0, 0, 1,\
+ 4)
#define VOP_RAM_INIT_RAM_INIT BIT(1)
#define VOP_RAM_INIT_RAM_INIT_SET(x)\
@@ -7343,9 +8028,10 @@ enum sparx5_target {
#define VOP_RAM_INIT_RAM_CFG_HOOK_GET(x)\
FIELD_GET(VOP_RAM_INIT_RAM_CFG_HOOK, x)
-/* XQS:SYSTEM:STAT_CFG */
-#define XQS_STAT_CFG __REG(TARGET_XQS,\
- 0, 1, 6768, 0, 1, 872, 860, 0, 1, 4)
+/* XQS:SYSTEM:STAT_CFG */
+#define XQS_STAT_CFG \
+ __REG(TARGET_XQS, 0, 1, regs->gaddr[GA_XQS_SYSTEM], 0, 1, 872, 860, 0, \
+ 1, 4)
#define XQS_STAT_CFG_STAT_CLEAR_SHOT GENMASK(21, 18)
#define XQS_STAT_CFG_STAT_CLEAR_SHOT_SET(x)\
@@ -7353,11 +8039,12 @@ enum sparx5_target {
#define XQS_STAT_CFG_STAT_CLEAR_SHOT_GET(x)\
FIELD_GET(XQS_STAT_CFG_STAT_CLEAR_SHOT, x)
-#define XQS_STAT_CFG_STAT_VIEW GENMASK(17, 5)
+#define XQS_STAT_CFG_STAT_VIEW\
+ GENMASK(regs->fsize[FW_XQS_STAT_CFG_STAT_VIEW] + 5 - 1, 5)
#define XQS_STAT_CFG_STAT_VIEW_SET(x)\
- FIELD_PREP(XQS_STAT_CFG_STAT_VIEW, x)
+ spx5_field_prep(XQS_STAT_CFG_STAT_VIEW, x)
#define XQS_STAT_CFG_STAT_VIEW_GET(x)\
- FIELD_GET(XQS_STAT_CFG_STAT_VIEW, x)
+ spx5_field_get(XQS_STAT_CFG_STAT_VIEW, x)
#define XQS_STAT_CFG_STAT_SRV_PKT_ONLY BIT(4)
#define XQS_STAT_CFG_STAT_SRV_PKT_ONLY_SET(x)\
@@ -7371,48 +8058,56 @@ enum sparx5_target {
#define XQS_STAT_CFG_STAT_WRAP_DIS_GET(x)\
FIELD_GET(XQS_STAT_CFG_STAT_WRAP_DIS, x)
-/* XQS:QLIMIT_SHR:QLIMIT_SHR_TOP_CFG */
-#define XQS_QLIMIT_SHR_TOP_CFG(g) __REG(TARGET_XQS,\
- 0, 1, 7936, g, 4, 48, 0, 0, 1, 4)
+/* XQS:QLIMIT_SHR:QLIMIT_SHR_TOP_CFG */
+#define XQS_QLIMIT_SHR_TOP_CFG(g) \
+ __REG(TARGET_XQS, 0, 1, regs->gaddr[GA_XQS_QLIMIT_SHR], g, 4, 48, 0, 0,\
+ 1, 4)
-#define XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP GENMASK(14, 0)
+#define XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP\
+ GENMASK(regs->fsize[FW_XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP] + 0 - 1, 0)
#define XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP_SET(x)\
- FIELD_PREP(XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP, x)
+ spx5_field_prep(XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP, x)
#define XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP_GET(x)\
- FIELD_GET(XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP, x)
+ spx5_field_get(XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP, x)
-/* XQS:QLIMIT_SHR:QLIMIT_SHR_ATOP_CFG */
-#define XQS_QLIMIT_SHR_ATOP_CFG(g) __REG(TARGET_XQS,\
- 0, 1, 7936, g, 4, 48, 4, 0, 1, 4)
+/* XQS:QLIMIT_SHR:QLIMIT_SHR_ATOP_CFG */
+#define XQS_QLIMIT_SHR_ATOP_CFG(g) \
+ __REG(TARGET_XQS, 0, 1, regs->gaddr[GA_XQS_QLIMIT_SHR], g, 4, 48, 4, 0,\
+ 1, 4)
-#define XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP GENMASK(14, 0)
+#define XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP\
+ GENMASK(regs->fsize[FW_XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP] + 0 - 1, 0)
#define XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP_SET(x)\
- FIELD_PREP(XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP, x)
+ spx5_field_prep(XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP, x)
#define XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP_GET(x)\
- FIELD_GET(XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP, x)
+ spx5_field_get(XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP, x)
-/* XQS:QLIMIT_SHR:QLIMIT_SHR_CTOP_CFG */
-#define XQS_QLIMIT_SHR_CTOP_CFG(g) __REG(TARGET_XQS,\
- 0, 1, 7936, g, 4, 48, 8, 0, 1, 4)
+/* XQS:QLIMIT_SHR:QLIMIT_SHR_CTOP_CFG */
+#define XQS_QLIMIT_SHR_CTOP_CFG(g) \
+ __REG(TARGET_XQS, 0, 1, regs->gaddr[GA_XQS_QLIMIT_SHR], g, 4, 48, 8, 0,\
+ 1, 4)
-#define XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP GENMASK(14, 0)
+#define XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP\
+ GENMASK(regs->fsize[FW_XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP] + 0 - 1, 0)
#define XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP_SET(x)\
- FIELD_PREP(XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP, x)
+ spx5_field_prep(XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP, x)
#define XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP_GET(x)\
- FIELD_GET(XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP, x)
+ spx5_field_get(XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP, x)
-/* XQS:QLIMIT_SHR:QLIMIT_SHR_QLIM_CFG */
-#define XQS_QLIMIT_SHR_QLIM_CFG(g) __REG(TARGET_XQS,\
- 0, 1, 7936, g, 4, 48, 12, 0, 1, 4)
+/* XQS:QLIMIT_SHR:QLIMIT_SHR_QLIM_CFG */
+#define XQS_QLIMIT_SHR_QLIM_CFG(g) \
+ __REG(TARGET_XQS, 0, 1, regs->gaddr[GA_XQS_QLIMIT_SHR], g, 4, 48, 12, \
+ 0, 1, 4)
-#define XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM GENMASK(14, 0)
+#define XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM\
+ GENMASK(regs->fsize[FW_XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM] + 0 - 1, 0)
#define XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM_SET(x)\
- FIELD_PREP(XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM, x)
+ spx5_field_prep(XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM, x)
#define XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM_GET(x)\
- FIELD_GET(XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM, x)
+ spx5_field_get(XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM, x)
-/* XQS:STAT:CNT */
-#define XQS_CNT(g) __REG(TARGET_XQS,\
- 0, 1, 0, g, 1024, 4, 0, 0, 1, 4)
+/* XQS:STAT:CNT */
+#define XQS_CNT(g) \
+ __REG(TARGET_XQS, 0, 1, 0, g, 1024, 4, 0, 0, 1, 4)
#endif /* _SPARX5_MAIN_REGS_H_ */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c b/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c
index 459a53676ae9..9806729e9c62 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c
@@ -24,8 +24,14 @@ static u32 sparx5_mirror_to_dir(bool ingress)
/* Get ports belonging to this mirror */
static u64 sparx5_mirror_port_get(struct sparx5 *sparx5, u32 idx)
{
- return (u64)spx5_rd(sparx5, ANA_AC_PROBE_PORT_CFG1(idx)) << 32 |
- spx5_rd(sparx5, ANA_AC_PROBE_PORT_CFG(idx));
+ u64 val;
+
+ val = spx5_rd(sparx5, ANA_AC_PROBE_PORT_CFG(idx));
+
+ if (is_sparx5(sparx5))
+ val |= (u64)spx5_rd(sparx5, ANA_AC_PROBE_PORT_CFG1(idx)) << 32;
+
+ return val;
}
/* Add port to mirror (only front ports) */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
index 705a004b324f..1d34af78166a 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
@@ -55,7 +55,7 @@ static void __ifh_encode_bitfield(void *ifh, u64 value, u32 pos, u32 width)
ifh_hdr[byte - 5] |= (u8)((encode & 0xFF0000000000) >> 40);
}
-void sparx5_set_port_ifh(void *ifh_hdr, u16 portno)
+void sparx5_set_port_ifh(struct sparx5 *sparx5, void *ifh_hdr, u16 portno)
{
/* VSTAX.RSV = 1. MSBit must be 1 */
ifh_encode_bitfield(ifh_hdr, 1, VSTAX + 79, 1);
@@ -64,15 +64,16 @@ void sparx5_set_port_ifh(void *ifh_hdr, u16 portno)
/* MISC.CPU_MASK/DPORT = Destination port */
ifh_encode_bitfield(ifh_hdr, portno, 29, 8);
/* MISC.PIPELINE_PT */
- ifh_encode_bitfield(ifh_hdr, 16, 37, 5);
+ ifh_encode_bitfield(ifh_hdr, is_sparx5(sparx5) ? 16 : 17, 37, 5);
/* MISC.PIPELINE_ACT */
ifh_encode_bitfield(ifh_hdr, 1, 42, 3);
/* FWD.SRC_PORT = CPU */
- ifh_encode_bitfield(ifh_hdr, SPX5_PORT_CPU, 46, 7);
+ ifh_encode_bitfield(ifh_hdr, sparx5_get_pgid(sparx5, SPX5_PORT_CPU_0),
+ 46, is_sparx5(sparx5) ? 7 : 6);
/* FWD.SFLOW_ID (disable SFlow sampling) */
- ifh_encode_bitfield(ifh_hdr, 124, 57, 7);
+ ifh_encode_bitfield(ifh_hdr, 124, is_sparx5(sparx5) ? 57 : 56, 7);
/* FWD.UPDATE_FCS = Enable. Enforce update of FCS. */
- ifh_encode_bitfield(ifh_hdr, 1, 67, 1);
+ ifh_encode_bitfield(ifh_hdr, 1, is_sparx5(sparx5) ? 67 : 66, 1);
}
void sparx5_set_port_ifh_rew_op(void *ifh_hdr, u32 rew_op)
@@ -80,19 +81,25 @@ void sparx5_set_port_ifh_rew_op(void *ifh_hdr, u32 rew_op)
ifh_encode_bitfield(ifh_hdr, rew_op, VSTAX + 32, 10);
}
-void sparx5_set_port_ifh_pdu_type(void *ifh_hdr, u32 pdu_type)
+void sparx5_set_port_ifh_pdu_type(struct sparx5 *sparx5, void *ifh_hdr,
+ u32 pdu_type)
{
- ifh_encode_bitfield(ifh_hdr, pdu_type, 191, 4);
+ ifh_encode_bitfield(ifh_hdr, pdu_type, is_sparx5(sparx5) ? 191 : 190,
+ 4);
}
-void sparx5_set_port_ifh_pdu_w16_offset(void *ifh_hdr, u32 pdu_w16_offset)
+void sparx5_set_port_ifh_pdu_w16_offset(struct sparx5 *sparx5, void *ifh_hdr,
+ u32 pdu_w16_offset)
{
- ifh_encode_bitfield(ifh_hdr, pdu_w16_offset, 195, 6);
+ ifh_encode_bitfield(ifh_hdr, pdu_w16_offset,
+ is_sparx5(sparx5) ? 195 : 194, 6);
}
-void sparx5_set_port_ifh_timestamp(void *ifh_hdr, u64 timestamp)
+void sparx5_set_port_ifh_timestamp(struct sparx5 *sparx5, void *ifh_hdr,
+ u64 timestamp)
{
- ifh_encode_bitfield(ifh_hdr, timestamp, 232, 40);
+ ifh_encode_bitfield(ifh_hdr, timestamp, 232,
+ is_sparx5(sparx5) ? 40 : 38);
}
static int sparx5_port_open(struct net_device *ndev)
@@ -190,7 +197,8 @@ static int sparx5_set_mac_address(struct net_device *dev, void *p)
sparx5_mact_forget(sparx5, dev->dev_addr, port->pvid);
/* Add new */
- sparx5_mact_learn(sparx5, PGID_CPU, addr->sa_data, port->pvid);
+ sparx5_mact_learn(sparx5, sparx5_get_pgid(sparx5, PGID_CPU),
+ addr->sa_data, port->pvid);
/* Record the address */
eth_hw_addr_set(dev, addr->sa_data);
@@ -290,7 +298,7 @@ int sparx5_register_netdevs(struct sparx5 *sparx5)
int portno;
int err;
- for (portno = 0; portno < SPX5_PORTS; portno++)
+ for (portno = 0; portno < sparx5->data->consts->n_ports; portno++)
if (sparx5->ports[portno]) {
err = register_netdev(sparx5->ports[portno]->ndev);
if (err) {
@@ -309,7 +317,7 @@ void sparx5_destroy_netdevs(struct sparx5 *sparx5)
struct sparx5_port *port;
int portno;
- for (portno = 0; portno < SPX5_PORTS; portno++) {
+ for (portno = 0; portno < sparx5->data->consts->n_ports; portno++) {
port = sparx5->ports[portno];
if (port && port->phylink) {
/* Disconnect the phy */
@@ -327,8 +335,7 @@ void sparx5_unregister_netdevs(struct sparx5 *sparx5)
{
int portno;
- for (portno = 0; portno < SPX5_PORTS; portno++)
+ for (portno = 0; portno < sparx5->data->consts->n_ports; portno++)
if (sparx5->ports[portno])
unregister_netdev(sparx5->ports[portno]->ndev);
}
-
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
index 70427643f777..b6f635d85820 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
@@ -32,7 +32,7 @@ void sparx5_xtr_flush(struct sparx5 *sparx5, u8 grp)
spx5_wr(0, sparx5, QS_XTR_FLUSH);
}
-void sparx5_ifh_parse(u32 *ifh, struct frame_info *info)
+void sparx5_ifh_parse(struct sparx5 *sparx5, u32 *ifh, struct frame_info *info)
{
u8 *xtr_hdr = (u8 *)ifh;
@@ -43,7 +43,8 @@ void sparx5_ifh_parse(u32 *ifh, struct frame_info *info)
((u32)xtr_hdr[29] << 8) |
((u32)xtr_hdr[30] << 0);
fwd = (fwd >> 5);
- info->src_port = FIELD_GET(GENMASK(7, 1), fwd);
+ info->src_port = spx5_field_get(GENMASK(is_sparx5(sparx5) ? 7 : 6, 1),
+ fwd);
/*
* Bit 270-271 are occasionally unexpectedly set by the hardware,
@@ -72,10 +73,10 @@ static void sparx5_xtr_grp(struct sparx5 *sparx5, u8 grp, bool byte_swap)
ifh[i] = spx5_rd(sparx5, QS_XTR_RD(grp));
/* Decode IFH (what's needed) */
- sparx5_ifh_parse(ifh, &fi);
+ sparx5_ifh_parse(sparx5, ifh, &fi);
/* Map to port netdev */
- port = fi.src_port < SPX5_PORTS ?
+ port = fi.src_port < sparx5->data->consts->n_ports ?
sparx5->ports[fi.src_port] : NULL;
if (!port || !port->ndev) {
dev_err(sparx5->dev, "Data on inactive port %d\n", fi.src_port);
@@ -235,16 +236,19 @@ netdev_tx_t sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev)
netdev_tx_t ret;
memset(ifh, 0, IFH_LEN * 4);
- sparx5_set_port_ifh(ifh, port->portno);
+ sparx5_set_port_ifh(sparx5, ifh, port->portno);
if (sparx5->ptp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
if (sparx5_ptp_txtstamp_request(port, skb) < 0)
return NETDEV_TX_BUSY;
sparx5_set_port_ifh_rew_op(ifh, SPARX5_SKB_CB(skb)->rew_op);
- sparx5_set_port_ifh_pdu_type(ifh, SPARX5_SKB_CB(skb)->pdu_type);
- sparx5_set_port_ifh_pdu_w16_offset(ifh, SPARX5_SKB_CB(skb)->pdu_w16_offset);
- sparx5_set_port_ifh_timestamp(ifh, SPARX5_SKB_CB(skb)->ts_id);
+ sparx5_set_port_ifh_pdu_type(sparx5, ifh,
+ SPARX5_SKB_CB(skb)->pdu_type);
+ sparx5_set_port_ifh_pdu_w16_offset(sparx5, ifh,
+ SPARX5_SKB_CB(skb)->pdu_w16_offset);
+ sparx5_set_port_ifh_timestamp(sparx5, ifh,
+ SPARX5_SKB_CB(skb)->ts_id);
}
skb_tx_timestamp(skb);
@@ -317,7 +321,9 @@ int sparx5_manual_injection_mode(struct sparx5 *sparx5)
sparx5, QS_INJ_GRP_CFG(INJ_QUEUE));
/* CPU ports capture setup */
- for (portno = SPX5_PORT_CPU_0; portno <= SPX5_PORT_CPU_1; portno++) {
+ for (portno = sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0);
+ portno <= sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1);
+ portno++) {
/* ASM CPU port: No preamble, IFH, enable padding */
spx5_wr(ASM_PORT_CFG_PAD_ENA_SET(1) |
ASM_PORT_CFG_NO_PREAMBLE_ENA_SET(1) |
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_pgid.c b/drivers/net/ethernet/microchip/sparx5/sparx5_pgid.c
index af8b435009f4..eae819fa9486 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_pgid.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_pgid.c
@@ -5,13 +5,13 @@ void sparx5_pgid_init(struct sparx5 *spx5)
{
int i;
- for (i = 0; i < PGID_TABLE_SIZE; i++)
+ for (i = 0; i < spx5->data->consts->n_pgids; i++)
spx5->pgid_map[i] = SPX5_PGID_FREE;
/* Reserved for unicast, flood control, broadcast, and CPU.
* These cannot be freed.
*/
- for (i = 0; i <= PGID_CPU; i++)
+ for (i = 0; i <= sparx5_get_pgid(spx5, PGID_CPU); i++)
spx5->pgid_map[i] = SPX5_PGID_RESERVED;
}
@@ -22,7 +22,8 @@ int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx)
/* The multicast area starts at index 65, but the first 7
* are reserved for flood masks and CPU. Start alloc after that.
*/
- for (i = PGID_MCAST_START; i < PGID_TABLE_SIZE; i++) {
+ for (i = sparx5_get_pgid(spx5, PGID_MCAST_START);
+ i < spx5->data->consts->n_pgids; i++) {
if (spx5->pgid_map[i] == SPX5_PGID_FREE) {
spx5->pgid_map[i] = SPX5_PGID_MULTICAST;
*idx = i;
@@ -35,7 +36,8 @@ int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx)
int sparx5_pgid_free(struct sparx5 *spx5, u16 idx)
{
- if (idx <= PGID_CPU || idx >= PGID_TABLE_SIZE)
+ if (idx <= sparx5_get_pgid(spx5, PGID_CPU) ||
+ idx >= spx5->data->consts->n_pgids)
return -EINVAL;
if (spx5->pgid_map[idx] == SPX5_PGID_FREE)
@@ -44,3 +46,8 @@ int sparx5_pgid_free(struct sparx5 *spx5, u16 idx)
spx5->pgid_map[idx] = SPX5_PGID_FREE;
return 0;
}
+
+int sparx5_get_pgid(struct sparx5 *sparx5, int pgid)
+{
+ return sparx5->data->consts->n_ports + pgid;
+}
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_police.c b/drivers/net/ethernet/microchip/sparx5/sparx5_police.c
index 8ada5cee1342..c88820e83812 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_police.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_police.c
@@ -11,10 +11,11 @@ static int sparx5_policer_service_conf_set(struct sparx5 *sparx5,
struct sparx5_policer *pol)
{
u32 idx, pup_tokens, max_pup_tokens, burst, thres;
+ const struct sparx5_ops *ops = sparx5->data->ops;
struct sparx5_sdlb_group *g;
u64 rate;
- g = &sdlb_groups[pol->group];
+ g = ops->get_sdlb_group(pol->group);
idx = pol->idx;
rate = pol->rate * 1000;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
index 062e486c002c..1401761c6251 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
@@ -132,8 +132,8 @@ static int sparx5_get_sfi_status(struct sparx5 *sparx5,
return -EINVAL;
}
- dev = sparx5_to_high_dev(portno);
- tinst = sparx5_port_dev_index(portno);
+ dev = sparx5_to_high_dev(sparx5, portno);
+ tinst = sparx5_port_dev_index(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
value = spx5_inst_rd(inst, DEV10G_MAC_TX_MONITOR_STICKY(0));
@@ -213,11 +213,13 @@ static int sparx5_port_verify_speed(struct sparx5 *sparx5,
struct sparx5_port *port,
struct sparx5_port_config *conf)
{
- if ((sparx5_port_is_2g5(port->portno) &&
+ const struct sparx5_ops *ops = sparx5->data->ops;
+
+ if ((ops->is_port_2g5(port->portno) &&
conf->speed > SPEED_2500) ||
- (sparx5_port_is_5g(port->portno) &&
+ (ops->is_port_5g(port->portno) &&
conf->speed > SPEED_5000) ||
- (sparx5_port_is_10g(port->portno) &&
+ (ops->is_port_10g(port->portno) &&
conf->speed > SPEED_10000))
return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
@@ -226,14 +228,14 @@ static int sparx5_port_verify_speed(struct sparx5 *sparx5,
return -EINVAL;
case PHY_INTERFACE_MODE_1000BASEX:
if (conf->speed != SPEED_1000 ||
- sparx5_port_is_2g5(port->portno))
+ ops->is_port_2g5(port->portno))
return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
- if (sparx5_port_is_2g5(port->portno))
+ if (ops->is_port_2g5(port->portno))
return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
break;
case PHY_INTERFACE_MODE_2500BASEX:
if (conf->speed != SPEED_2500 ||
- sparx5_port_is_2g5(port->portno))
+ ops->is_port_2g5(port->portno))
return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
break;
case PHY_INTERFACE_MODE_QSGMII:
@@ -316,10 +318,11 @@ static int sparx5_port_flush_poll(struct sparx5 *sparx5, u32 portno)
static int sparx5_port_disable(struct sparx5 *sparx5, struct sparx5_port *port, bool high_spd_dev)
{
u32 tinst = high_spd_dev ?
- sparx5_port_dev_index(port->portno) : port->portno;
+ sparx5_port_dev_index(sparx5, port->portno) : port->portno;
u32 dev = high_spd_dev ?
- sparx5_to_high_dev(port->portno) : TARGET_DEV2G5;
+ sparx5_to_high_dev(sparx5, port->portno) : TARGET_DEV2G5;
void __iomem *devinst = spx5_inst_get(sparx5, dev, tinst);
+ const struct sparx5_ops *ops = sparx5->data->ops;
u32 spd = port->conf.speed;
u32 spd_prm;
int err;
@@ -427,7 +430,7 @@ static int sparx5_port_disable(struct sparx5 *sparx5, struct sparx5_port *port,
HSCH_FLUSH_CTRL);
if (high_spd_dev) {
- u32 pcs = sparx5_to_pcs_dev(port->portno);
+ u32 pcs = sparx5_to_pcs_dev(sparx5, port->portno);
void __iomem *pcsinst = spx5_inst_get(sparx5, pcs, tinst);
/* 12: Disable 5G/10G/25 BaseR PCS */
@@ -436,7 +439,7 @@ static int sparx5_port_disable(struct sparx5 *sparx5, struct sparx5_port *port,
pcsinst,
PCS10G_BR_PCS_CFG(0));
- if (sparx5_port_is_25g(port->portno))
+ if (ops->is_port_25g(port->portno))
/* Disable 25G PCS */
spx5_rmw(DEV25G_PCS25G_CFG_PCS25G_ENA_SET(0),
DEV25G_PCS25G_CFG_PCS25G_ENA,
@@ -473,6 +476,9 @@ static int sparx5_port_fifo_sz(struct sparx5 *sparx5,
u32 mac_width = 8;
u32 addition = 0;
+ if (!is_sparx5(sparx5))
+ return 0;
+
switch (speed) {
case SPEED_25000:
return 0;
@@ -513,9 +519,8 @@ static int sparx5_port_fifo_sz(struct sparx5 *sparx5,
/* Configure port muxing:
* QSGMII: 4x2G5 devices
*/
-static int sparx5_port_mux_set(struct sparx5 *sparx5,
- struct sparx5_port *port,
- struct sparx5_port_config *conf)
+int sparx5_port_mux_set(struct sparx5 *sparx5, struct sparx5_port *port,
+ struct sparx5_port_config *conf)
{
u32 portno = port->portno;
u32 inst;
@@ -558,9 +563,10 @@ static int sparx5_port_max_tags_set(struct sparx5 *sparx5,
bool dtag = max_tags == SPX5_PORT_MAX_TAGS_TWO;
enum sparx5_vlan_port_type vlan_type = port->vlan_type;
bool dotag = max_tags != SPX5_PORT_MAX_TAGS_NONE;
- u32 dev = sparx5_to_high_dev(port->portno);
- u32 tinst = sparx5_port_dev_index(port->portno);
+ u32 dev = sparx5_to_high_dev(sparx5, port->portno);
+ u32 tinst = sparx5_port_dev_index(sparx5, port->portno);
void __iomem *inst = spx5_inst_get(sparx5, dev, tinst);
+ const struct sparx5_ops *ops = sparx5->data->ops;
u32 etype;
etype = (vlan_type == SPX5_VLAN_PORT_TYPE_S_CUSTOM ?
@@ -575,7 +581,7 @@ static int sparx5_port_max_tags_set(struct sparx5 *sparx5,
sparx5,
DEV2G5_MAC_TAGS_CFG(port->portno));
- if (sparx5_port_is_2g5(port->portno))
+ if (ops->is_port_2g5(port->portno))
return 0;
spx5_inst_rmw(DEV10G_MAC_TAGS_CFG_TAG_ID_SET(etype) |
@@ -789,9 +795,9 @@ static int sparx5_port_pcs_high_set(struct sparx5 *sparx5,
struct sparx5_port_config *conf)
{
u32 clk_spd = conf->portmode == PHY_INTERFACE_MODE_5GBASER ? 1 : 0;
- u32 pix = sparx5_port_dev_index(port->portno);
- u32 dev = sparx5_to_high_dev(port->portno);
- u32 pcs = sparx5_to_pcs_dev(port->portno);
+ u32 pix = sparx5_port_dev_index(sparx5, port->portno);
+ u32 dev = sparx5_to_high_dev(sparx5, port->portno);
+ u32 pcs = sparx5_to_pcs_dev(sparx5, port->portno);
void __iomem *devinst;
void __iomem *pcsinst;
int err;
@@ -843,19 +849,22 @@ static int sparx5_port_pcs_high_set(struct sparx5 *sparx5,
/* Switch between 1G/2500 and 5G/10G/25G devices */
static void sparx5_dev_switch(struct sparx5 *sparx5, int port, bool hsd)
{
- int bt_indx = BIT(sparx5_port_dev_index(port));
+ const struct sparx5_ops *ops = sparx5->data->ops;
+ int bt_indx;
+
+ bt_indx = BIT(ops->get_port_dev_bit(sparx5, port));
- if (sparx5_port_is_5g(port)) {
+ if (ops->is_port_5g(port)) {
spx5_rmw(hsd ? 0 : bt_indx,
bt_indx,
sparx5,
PORT_CONF_DEV5G_MODES);
- } else if (sparx5_port_is_10g(port)) {
+ } else if (ops->is_port_10g(port)) {
spx5_rmw(hsd ? 0 : bt_indx,
bt_indx,
sparx5,
PORT_CONF_DEV10G_MODES);
- } else if (sparx5_port_is_25g(port)) {
+ } else if (ops->is_port_25g(port)) {
spx5_rmw(hsd ? 0 : bt_indx,
bt_indx,
sparx5,
@@ -915,6 +924,20 @@ static int sparx5_port_config_low_set(struct sparx5 *sparx5,
sparx5,
DEV2G5_DEV_RST_CTRL(port->portno));
+ /* Enable PHAD_CTRL for better timestamping */
+ if (!is_sparx5(sparx5)) {
+ for (int i = 0; i < 2; ++i) {
+ /* Divide the port clock by three for the two
+ * phase detection registers.
+ */
+ spx5_rmw(DEV2G5_PHAD_CTRL_DIV_CFG_SET(3) |
+ DEV2G5_PHAD_CTRL_PHAD_ENA_SET(1),
+ DEV2G5_PHAD_CTRL_DIV_CFG |
+ DEV2G5_PHAD_CTRL_PHAD_ENA,
+ sparx5, DEV2G5_PHAD_CTRL(port->portno, i));
+ }
+ }
+
return 0;
}
@@ -972,6 +995,7 @@ int sparx5_port_config(struct sparx5 *sparx5,
struct sparx5_port_config *conf)
{
bool high_speed_dev = sparx5_is_baser(conf->portmode);
+ const struct sparx5_ops *ops = sparx5->data->ops;
int err, urgency, stop_wm;
err = sparx5_port_verify_speed(sparx5, port, conf);
@@ -987,6 +1011,13 @@ int sparx5_port_config(struct sparx5 *sparx5,
if (err)
return err;
+ if (!is_sparx5(sparx5) && ops->is_port_10g(port->portno) &&
+ conf->speed < SPEED_10000)
+ spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA_SET(1),
+ DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA,
+ sparx5,
+ DSM_DEV_TX_STOP_WM_CFG(port->portno));
+
/* Set the DSM stop watermark */
stop_wm = sparx5_port_fifo_sz(sparx5, port->portno, conf->speed);
spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM_SET(stop_wm),
@@ -1016,9 +1047,10 @@ int sparx5_port_init(struct sparx5 *sparx5,
{
u32 pause_start = sparx5_wm_enc(6 * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
u32 atop = sparx5_wm_enc(20 * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
- u32 devhigh = sparx5_to_high_dev(port->portno);
- u32 pix = sparx5_port_dev_index(port->portno);
- u32 pcs = sparx5_to_pcs_dev(port->portno);
+ const struct sparx5_ops *ops = sparx5->data->ops;
+ u32 devhigh = sparx5_to_high_dev(sparx5, port->portno);
+ u32 pix = sparx5_port_dev_index(sparx5, port->portno);
+ u32 pcs = sparx5_to_pcs_dev(sparx5, port->portno);
bool sd_pol = port->signd_active_high;
bool sd_sel = !port->signd_internal;
bool sd_ena = port->signd_enable;
@@ -1031,7 +1063,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
pcsinst = spx5_inst_get(sparx5, pcs, pix);
/* Set the mux port mode */
- err = sparx5_port_mux_set(sparx5, port, conf);
+ err = ops->set_port_mux(sparx5, port, conf);
if (err)
return err;
@@ -1082,7 +1114,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
if (err)
return err;
- if (!sparx5_port_is_2g5(port->portno))
+ if (!ops->is_port_2g5(port->portno))
/* Enable shadow device */
spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA_SET(1),
DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA,
@@ -1105,7 +1137,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
sparx5,
DEV2G5_MAC_IFG_CFG(port->portno));
- if (sparx5_port_is_2g5(port->portno))
+ if (ops->is_port_2g5(port->portno))
return 0; /* Low speed device only - return */
/* Now setup the high speed device */
@@ -1128,7 +1160,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
pcsinst,
PCS10G_BR_PCS_SD_CFG(0));
- if (sparx5_port_is_25g(port->portno)) {
+ if (ops->is_port_25g(port->portno)) {
/* Handle Signal Detect in 25G PCS */
spx5_wr(DEV25G_PCS25G_SD_CFG_SD_POL_SET(sd_pol) |
DEV25G_PCS25G_SD_CFG_SD_SEL_SET(sd_sel) |
@@ -1137,6 +1169,27 @@ int sparx5_port_init(struct sparx5 *sparx5,
DEV25G_PCS25G_SD_CFG(pix));
}
+ if (!is_sparx5(sparx5)) {
+ void __iomem *inst;
+ u32 dev, tinst;
+
+ if (ops->is_port_10g(port->portno)) {
+ dev = sparx5_to_high_dev(sparx5, port->portno);
+ tinst = sparx5_port_dev_index(sparx5, port->portno);
+ inst = spx5_inst_get(sparx5, dev, tinst);
+
+ spx5_inst_wr(5, inst,
+ DEV10G_PTP_STAMPER_CFG(port->portno));
+ } else if (ops->is_port_5g(port->portno)) {
+ dev = sparx5_to_high_dev(sparx5, port->portno);
+ tinst = sparx5_port_dev_index(sparx5, port->portno);
+ inst = spx5_inst_get(sparx5, dev, tinst);
+
+ spx5_inst_wr(5, inst,
+ DEV5G_PTP_STAMPER_CFG(port->portno));
+ }
+ }
+
return 0;
}
@@ -1345,3 +1398,8 @@ int sparx5_port_qos_default_set(const struct sparx5_port *port,
return 0;
}
+
+int sparx5_get_internal_port(struct sparx5 *sparx5, int port)
+{
+ return sparx5->data->consts->n_ports + port;
+}
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.h b/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
index 607c4ff1df6b..9b9bcc6834bc 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
@@ -40,25 +40,29 @@ static inline bool sparx5_port_is_25g(int portno)
return portno >= 56 && portno <= 63;
}
-static inline u32 sparx5_to_high_dev(int port)
+static inline u32 sparx5_to_high_dev(struct sparx5 *sparx5, int port)
{
- if (sparx5_port_is_5g(port))
+ const struct sparx5_ops *ops = sparx5->data->ops;
+
+ if (ops->is_port_5g(port))
return TARGET_DEV5G;
- if (sparx5_port_is_10g(port))
+ if (ops->is_port_10g(port))
return TARGET_DEV10G;
return TARGET_DEV25G;
}
-static inline u32 sparx5_to_pcs_dev(int port)
+static inline u32 sparx5_to_pcs_dev(struct sparx5 *sparx5, int port)
{
- if (sparx5_port_is_5g(port))
+ const struct sparx5_ops *ops = sparx5->data->ops;
+
+ if (ops->is_port_5g(port))
return TARGET_PCS5G_BR;
- if (sparx5_port_is_10g(port))
+ if (ops->is_port_10g(port))
return TARGET_PCS10G_BR;
return TARGET_PCS25G_BR;
}
-static inline int sparx5_port_dev_index(int port)
+static inline u32 sparx5_port_dev_mapping(struct sparx5 *sparx5, int port)
{
if (sparx5_port_is_2g5(port))
return port;
@@ -70,6 +74,11 @@ static inline int sparx5_port_dev_index(int port)
return (port - 56);
}
+static inline u32 sparx5_port_dev_index(struct sparx5 *sparx5, int port)
+{
+ return sparx5->data->ops->get_port_dev_index(sparx5, port);
+}
+
int sparx5_port_init(struct sparx5 *sparx5,
struct sparx5_port *spx5_port,
struct sparx5_port_config *conf);
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_psfp.c b/drivers/net/ethernet/microchip/sparx5/sparx5_psfp.c
index 8dee1ab1fa75..cd4f42c3f7eb 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_psfp.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_psfp.c
@@ -20,36 +20,40 @@ static struct sparx5_pool_entry sparx5_psfp_sg_pool[SPX5_PSFP_SG_CNT];
/* Pool of available stream filters */
static struct sparx5_pool_entry sparx5_psfp_sf_pool[SPX5_PSFP_SF_CNT];
-static int sparx5_psfp_sf_get(u32 *id)
+static int sparx5_psfp_sf_get(struct sparx5 *sparx5, u32 *id)
{
- return sparx5_pool_get(sparx5_psfp_sf_pool, SPX5_PSFP_SF_CNT, id);
+ return sparx5_pool_get(sparx5_psfp_sf_pool,
+ sparx5->data->consts->n_filters, id);
}
-static int sparx5_psfp_sf_put(u32 id)
+static int sparx5_psfp_sf_put(struct sparx5 *sparx5, u32 id)
{
- return sparx5_pool_put(sparx5_psfp_sf_pool, SPX5_PSFP_SF_CNT, id);
+ return sparx5_pool_put(sparx5_psfp_sf_pool,
+ sparx5->data->consts->n_filters, id);
}
-static int sparx5_psfp_sg_get(u32 idx, u32 *id)
+static int sparx5_psfp_sg_get(struct sparx5 *sparx5, u32 idx, u32 *id)
{
- return sparx5_pool_get_with_idx(sparx5_psfp_sg_pool, SPX5_PSFP_SG_CNT,
- idx, id);
+ return sparx5_pool_get_with_idx(sparx5_psfp_sg_pool,
+ sparx5->data->consts->n_gates, idx, id);
}
-static int sparx5_psfp_sg_put(u32 id)
+static int sparx5_psfp_sg_put(struct sparx5 *sparx5, u32 id)
{
- return sparx5_pool_put(sparx5_psfp_sg_pool, SPX5_PSFP_SG_CNT, id);
+ return sparx5_pool_put(sparx5_psfp_sg_pool,
+ sparx5->data->consts->n_gates, id);
}
-static int sparx5_psfp_fm_get(u32 idx, u32 *id)
+static int sparx5_psfp_fm_get(struct sparx5 *sparx5, u32 idx, u32 *id)
{
- return sparx5_pool_get_with_idx(sparx5_psfp_fm_pool, SPX5_SDLB_CNT, idx,
- id);
+ return sparx5_pool_get_with_idx(sparx5_psfp_fm_pool,
+ sparx5->data->consts->n_sdlbs, idx, id);
}
-static int sparx5_psfp_fm_put(u32 id)
+static int sparx5_psfp_fm_put(struct sparx5 *sparx5, u32 id)
{
- return sparx5_pool_put(sparx5_psfp_fm_pool, SPX5_SDLB_CNT, id);
+ return sparx5_pool_put(sparx5_psfp_fm_pool,
+ sparx5->data->consts->n_sdlbs, id);
}
u32 sparx5_psfp_isdx_get_sf(struct sparx5 *sparx5, u32 isdx)
@@ -205,7 +209,7 @@ int sparx5_psfp_sf_add(struct sparx5 *sparx5, const struct sparx5_psfp_sf *sf,
{
int ret;
- ret = sparx5_psfp_sf_get(id);
+ ret = sparx5_psfp_sf_get(sparx5, id);
if (ret < 0)
return ret;
@@ -220,7 +224,7 @@ int sparx5_psfp_sf_del(struct sparx5 *sparx5, u32 id)
sparx5_psfp_sf_set(sparx5, id, &sf);
- return sparx5_psfp_sf_put(id);
+ return sparx5_psfp_sf_put(sparx5, id);
}
int sparx5_psfp_sg_add(struct sparx5 *sparx5, u32 uidx,
@@ -229,7 +233,7 @@ int sparx5_psfp_sg_add(struct sparx5 *sparx5, u32 uidx,
ktime_t basetime;
int ret;
- ret = sparx5_psfp_sg_get(uidx, id);
+ ret = sparx5_psfp_sg_get(sparx5, uidx, id);
if (ret < 0)
return ret;
/* Was already in use, no need to reconfigure */
@@ -253,7 +257,7 @@ int sparx5_psfp_sg_del(struct sparx5 *sparx5, u32 id)
const struct sparx5_psfp_sg sg = { 0 };
int ret;
- ret = sparx5_psfp_sg_put(id);
+ ret = sparx5_psfp_sg_put(sparx5, id);
if (ret < 0)
return ret;
/* Stream gate still in use ? */
@@ -270,7 +274,7 @@ int sparx5_psfp_fm_add(struct sparx5 *sparx5, u32 uidx,
int ret;
/* Get flow meter */
- ret = sparx5_psfp_fm_get(uidx, &fm->pol.idx);
+ ret = sparx5_psfp_fm_get(sparx5, uidx, &fm->pol.idx);
if (ret < 0)
return ret;
/* Was already in use, no need to reconfigure */
@@ -303,7 +307,7 @@ int sparx5_psfp_fm_del(struct sparx5 *sparx5, u32 id)
if (ret < 0)
return ret;
- ret = sparx5_psfp_fm_put(id);
+ ret = sparx5_psfp_fm_put(sparx5, id);
if (ret < 0)
return ret;
/* Do not reset flow-meter if still in use. */
@@ -315,11 +319,12 @@ int sparx5_psfp_fm_del(struct sparx5 *sparx5, u32 id)
void sparx5_psfp_init(struct sparx5 *sparx5)
{
+ const struct sparx5_ops *ops = sparx5->data->ops;
const struct sparx5_sdlb_group *group;
int i;
- for (i = 0; i < SPX5_SDLB_GROUP_CNT; i++) {
- group = &sdlb_groups[i];
+ for (i = 0; i < sparx5->data->consts->n_lb_groups; i++) {
+ group = ops->get_sdlb_group(i);
sparx5_sdlb_group_init(sparx5, group->max_rate,
group->min_burst, group->frame_size, i);
}
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
index 5a932460db58..1c2903700a9c 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
@@ -11,8 +11,6 @@
#include "sparx5_main_regs.h"
#include "sparx5_main.h"
-#define SPARX5_MAX_PTP_ID 512
-
#define TOD_ACC_PIN 0x4
enum {
@@ -38,6 +36,9 @@ static u64 sparx5_ptp_get_1ppm(struct sparx5 *sparx5)
case SPX5_CORE_CLOCK_250MHZ:
res = 2301339409586;
break;
+ case SPX5_CORE_CLOCK_328MHZ:
+ res = 1756832768924;
+ break;
case SPX5_CORE_CLOCK_500MHZ:
res = 1150669704793;
break;
@@ -60,6 +61,9 @@ static u64 sparx5_ptp_get_nominal_value(struct sparx5 *sparx5)
case SPX5_CORE_CLOCK_250MHZ:
res = 0x1FF0000000000000;
break;
+ case SPX5_CORE_CLOCK_328MHZ:
+ res = 0x18604697DD0F9B5B;
+ break;
case SPX5_CORE_CLOCK_500MHZ:
res = 0x0FF8000000000000;
break;
@@ -269,11 +273,12 @@ void sparx5_ptp_txtstamp_release(struct sparx5_port *port,
spin_unlock_irqrestore(&sparx5->ptp_ts_id_lock, flags);
}
-static void sparx5_get_hwtimestamp(struct sparx5 *sparx5,
- struct timespec64 *ts,
- u32 nsec)
+void sparx5_get_hwtimestamp(struct sparx5 *sparx5,
+ struct timespec64 *ts,
+ u32 nsec)
{
/* Read current PTP time to get seconds */
+ const struct sparx5_consts *consts = sparx5->data->consts;
unsigned long flags;
u32 curr_nsec;
@@ -285,10 +290,10 @@ static void sparx5_get_hwtimestamp(struct sparx5 *sparx5,
PTP_PTP_PIN_CFG_PTP_PIN_ACTION |
PTP_PTP_PIN_CFG_PTP_PIN_DOM |
PTP_PTP_PIN_CFG_PTP_PIN_SYNC,
- sparx5, PTP_PTP_PIN_CFG(TOD_ACC_PIN));
+ sparx5, PTP_PTP_PIN_CFG(consts->tod_pin));
- ts->tv_sec = spx5_rd(sparx5, PTP_PTP_TOD_SEC_LSB(TOD_ACC_PIN));
- curr_nsec = spx5_rd(sparx5, PTP_PTP_TOD_NSEC(TOD_ACC_PIN));
+ ts->tv_sec = spx5_rd(sparx5, PTP_PTP_TOD_SEC_LSB(consts->tod_pin));
+ curr_nsec = spx5_rd(sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin));
ts->tv_nsec = nsec;
@@ -298,6 +303,7 @@ static void sparx5_get_hwtimestamp(struct sparx5 *sparx5,
spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags);
}
+EXPORT_SYMBOL_GPL(sparx5_get_hwtimestamp);
irqreturn_t sparx5_ptp_irq_handler(int irq, void *args)
{
@@ -440,8 +446,11 @@ static int sparx5_ptp_settime64(struct ptp_clock_info *ptp,
{
struct sparx5_phc *phc = container_of(ptp, struct sparx5_phc, info);
struct sparx5 *sparx5 = phc->sparx5;
+ const struct sparx5_consts *consts;
unsigned long flags;
+ consts = sparx5->data->consts;
+
spin_lock_irqsave(&sparx5->ptp_clock_lock, flags);
/* Must be in IDLE mode before the time can be loaded */
@@ -451,14 +460,14 @@ static int sparx5_ptp_settime64(struct ptp_clock_info *ptp,
PTP_PTP_PIN_CFG_PTP_PIN_ACTION |
PTP_PTP_PIN_CFG_PTP_PIN_DOM |
PTP_PTP_PIN_CFG_PTP_PIN_SYNC,
- sparx5, PTP_PTP_PIN_CFG(TOD_ACC_PIN));
+ sparx5, PTP_PTP_PIN_CFG(consts->tod_pin));
/* Set new value */
spx5_wr(PTP_PTP_TOD_SEC_MSB_PTP_TOD_SEC_MSB_SET(upper_32_bits(ts->tv_sec)),
- sparx5, PTP_PTP_TOD_SEC_MSB(TOD_ACC_PIN));
+ sparx5, PTP_PTP_TOD_SEC_MSB(consts->tod_pin));
spx5_wr(lower_32_bits(ts->tv_sec),
- sparx5, PTP_PTP_TOD_SEC_LSB(TOD_ACC_PIN));
- spx5_wr(ts->tv_nsec, sparx5, PTP_PTP_TOD_NSEC(TOD_ACC_PIN));
+ sparx5, PTP_PTP_TOD_SEC_LSB(consts->tod_pin));
+ spx5_wr(ts->tv_nsec, sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin));
/* Apply new values */
spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_LOAD) |
@@ -467,7 +476,7 @@ static int sparx5_ptp_settime64(struct ptp_clock_info *ptp,
PTP_PTP_PIN_CFG_PTP_PIN_ACTION |
PTP_PTP_PIN_CFG_PTP_PIN_DOM |
PTP_PTP_PIN_CFG_PTP_PIN_SYNC,
- sparx5, PTP_PTP_PIN_CFG(TOD_ACC_PIN));
+ sparx5, PTP_PTP_PIN_CFG(consts->tod_pin));
spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags);
@@ -478,10 +487,13 @@ int sparx5_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
struct sparx5_phc *phc = container_of(ptp, struct sparx5_phc, info);
struct sparx5 *sparx5 = phc->sparx5;
+ const struct sparx5_consts *consts;
unsigned long flags;
time64_t s;
s64 ns;
+ consts = sparx5->data->consts;
+
spin_lock_irqsave(&sparx5->ptp_clock_lock, flags);
spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_SAVE) |
@@ -490,12 +502,12 @@ int sparx5_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
PTP_PTP_PIN_CFG_PTP_PIN_ACTION |
PTP_PTP_PIN_CFG_PTP_PIN_DOM |
PTP_PTP_PIN_CFG_PTP_PIN_SYNC,
- sparx5, PTP_PTP_PIN_CFG(TOD_ACC_PIN));
+ sparx5, PTP_PTP_PIN_CFG(consts->tod_pin));
- s = spx5_rd(sparx5, PTP_PTP_TOD_SEC_MSB(TOD_ACC_PIN));
+ s = spx5_rd(sparx5, PTP_PTP_TOD_SEC_MSB(consts->tod_pin));
s <<= 32;
- s |= spx5_rd(sparx5, PTP_PTP_TOD_SEC_LSB(TOD_ACC_PIN));
- ns = spx5_rd(sparx5, PTP_PTP_TOD_NSEC(TOD_ACC_PIN));
+ s |= spx5_rd(sparx5, PTP_PTP_TOD_SEC_LSB(consts->tod_pin));
+ ns = spx5_rd(sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin));
ns &= PTP_PTP_TOD_NSEC_PTP_TOD_NSEC;
spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags);
@@ -515,6 +527,9 @@ static int sparx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct sparx5_phc *phc = container_of(ptp, struct sparx5_phc, info);
struct sparx5 *sparx5 = phc->sparx5;
+ const struct sparx5_consts *consts;
+
+ consts = sparx5->data->consts;
if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
unsigned long flags;
@@ -528,10 +543,10 @@ static int sparx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
PTP_PTP_PIN_CFG_PTP_PIN_ACTION |
PTP_PTP_PIN_CFG_PTP_PIN_DOM |
PTP_PTP_PIN_CFG_PTP_PIN_SYNC,
- sparx5, PTP_PTP_PIN_CFG(TOD_ACC_PIN));
+ sparx5, PTP_PTP_PIN_CFG(consts->tod_pin));
spx5_wr(PTP_PTP_TOD_NSEC_PTP_TOD_NSEC_SET(delta),
- sparx5, PTP_PTP_TOD_NSEC(TOD_ACC_PIN));
+ sparx5, PTP_PTP_TOD_NSEC(consts->tod_pin));
/* Adjust time with the value of PTP_TOD_NSEC */
spx5_rmw(PTP_PTP_PIN_CFG_PTP_PIN_ACTION_SET(PTP_PIN_ACTION_DELTA) |
@@ -540,7 +555,7 @@ static int sparx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
PTP_PTP_PIN_CFG_PTP_PIN_ACTION |
PTP_PTP_PIN_CFG_PTP_PIN_DOM |
PTP_PTP_PIN_CFG_PTP_PIN_SYNC,
- sparx5, PTP_PTP_PIN_CFG(TOD_ACC_PIN));
+ sparx5, PTP_PTP_PIN_CFG(consts->tod_pin));
spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags);
} else {
@@ -630,7 +645,7 @@ int sparx5_ptp_init(struct sparx5 *sparx5)
/* Enable master counters */
spx5_wr(PTP_PTP_DOM_CFG_PTP_ENA_SET(0x7), sparx5, PTP_PTP_DOM_CFG);
- for (i = 0; i < SPX5_PORTS; i++) {
+ for (i = 0; i < sparx5->data->consts->n_ports; i++) {
port = sparx5->ports[i];
if (!port)
continue;
@@ -646,7 +661,7 @@ void sparx5_ptp_deinit(struct sparx5 *sparx5)
struct sparx5_port *port;
int i;
- for (i = 0; i < SPX5_PORTS; i++) {
+ for (i = 0; i < sparx5->data->consts->n_ports; i++) {
port = sparx5->ports[i];
if (!port)
continue;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.c b/drivers/net/ethernet/microchip/sparx5/sparx5_qos.c
index 5f34febaee6b..e580670f3992 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_qos.c
@@ -74,6 +74,11 @@ static const u32 spx5_hsch_max_group_rate[SPX5_HSCH_LEAK_GRP_CNT] = {
26214200 /* 26.214 Gbps */
};
+u32 sparx5_get_hsch_max_group_rate(int grp)
+{
+ return spx5_hsch_max_group_rate[grp];
+}
+
static struct sparx5_layer layers[SPX5_HSCH_LAYER_CNT];
static u32 sparx5_lg_get_leak_time(struct sparx5 *sparx5, u32 layer, u32 group)
@@ -362,9 +367,10 @@ static u32 sparx5_weight_to_hw_cost(u32 weight_min, u32 weight)
static int sparx5_dwrr_conf_set(struct sparx5_port *port,
struct sparx5_dwrr *dwrr)
{
+ u32 layer = is_sparx5(port->sparx5) ? 2 : 1;
int i;
- spx5_rmw(HSCH_HSCH_CFG_CFG_HSCH_LAYER_SET(2) |
+ spx5_rmw(HSCH_HSCH_CFG_CFG_HSCH_LAYER_SET(layer) |
HSCH_HSCH_CFG_CFG_CFG_SE_IDX_SET(port->portno),
HSCH_HSCH_CFG_CFG_HSCH_LAYER | HSCH_HSCH_CFG_CFG_CFG_SE_IDX,
port->sparx5, HSCH_HSCH_CFG_CFG);
@@ -385,6 +391,7 @@ static int sparx5_dwrr_conf_set(struct sparx5_port *port,
static int sparx5_leak_groups_init(struct sparx5 *sparx5)
{
+ const struct sparx5_ops *ops = sparx5->data->ops;
struct sparx5_layer *layer;
u32 sys_clk_per_100ps;
struct sparx5_lg *lg;
@@ -397,7 +404,7 @@ static int sparx5_leak_groups_init(struct sparx5 *sparx5)
layer = &layers[i];
for (ii = 0; ii < SPX5_HSCH_LEAK_GRP_CNT; ii++) {
lg = &layer->leak_groups[ii];
- lg->max_rate = spx5_hsch_max_group_rate[ii];
+ lg->max_rate = ops->get_hsch_max_group_rate(i);
/* Calculate the leak time in us, to serve a maximum
* rate of 'max_rate' for this group
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h b/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h
index ced35033a6c5..1231a80335d7 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h
@@ -79,4 +79,6 @@ int sparx5_tc_ets_add(struct sparx5_port *port,
int sparx5_tc_ets_del(struct sparx5_port *port);
+u32 sparx5_get_hsch_max_group_rate(int grp);
+
#endif /* __SPARX5_QOS_H__ */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_regs.c b/drivers/net/ethernet/microchip/sparx5/sparx5_regs.c
new file mode 100644
index 000000000000..220e81b714d4
--- /dev/null
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_regs.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip Sparx5 Switch driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc.
+ */
+
+/* This file is autogenerated by cml-utils 2024-09-30 11:48:29 +0200.
+ * Commit ID: 9d07b8d19363f3cd3590ddb3f7a2e2768e16524b
+ */
+
+#include "sparx5_regs.h"
+
+const unsigned int sparx5_tsize[TSIZE_LAST] = {
+ [TC_DEV10G] = 12,
+ [TC_DEV2G5] = 65,
+ [TC_DEV5G] = 13,
+ [TC_PCS10G_BR] = 12,
+ [TC_PCS5G_BR] = 13,
+};
+
+const unsigned int sparx5_raddr[RADDR_LAST] = {
+ [RA_CPU_PROC_CTRL] = 176,
+ [RA_GCB_SOFT_RST] = 8,
+ [RA_GCB_HW_SGPIO_TO_SD_MAP_CFG] = 24,
+};
+
+const unsigned int sparx5_rcnt[RCNT_LAST] = {
+ [RC_ANA_AC_OWN_UPSID] = 3,
+ [RC_ANA_ACL_VCAP_S2_CFG] = 70,
+ [RC_ANA_ACL_OWN_UPSID] = 3,
+ [RC_ANA_CL_OWN_UPSID] = 3,
+ [RC_ANA_L2_OWN_UPSID] = 3,
+ [RC_ASM_PORT_CFG] = 67,
+ [RC_DSM_BUF_CFG] = 67,
+ [RC_DSM_DEV_TX_STOP_WM_CFG] = 67,
+ [RC_DSM_RX_PAUSE_CFG] = 67,
+ [RC_DSM_MAC_CFG] = 67,
+ [RC_DSM_MAC_ADDR_BASE_HIGH_CFG] = 65,
+ [RC_DSM_MAC_ADDR_BASE_LOW_CFG] = 65,
+ [RC_DSM_TAXI_CAL_CFG] = 9,
+ [RC_GCB_HW_SGPIO_TO_SD_MAP_CFG] = 65,
+ [RC_HSCH_PORT_MODE] = 70,
+ [RC_QFWD_SWITCH_PORT_MODE] = 70,
+ [RC_QSYS_PAUSE_CFG] = 70,
+ [RC_QSYS_ATOP] = 70,
+ [RC_QSYS_FWD_PRESSURE] = 70,
+ [RC_QSYS_CAL_AUTO] = 7,
+ [RC_REW_OWN_UPSID] = 3,
+ [RC_REW_RTAG_ETAG_CTRL] = 70,
+};
+
+const unsigned int sparx5_gaddr[GADDR_LAST] = {
+ [GA_ANA_AC_RAM_CTRL] = 839108,
+ [GA_ANA_AC_PS_COMMON] = 894472,
+ [GA_ANA_AC_MIRROR_PROBE] = 893696,
+ [GA_ANA_AC_SRC] = 849920,
+ [GA_ANA_AC_PGID] = 786432,
+ [GA_ANA_AC_TSN_SF] = 839136,
+ [GA_ANA_AC_TSN_SF_CFG] = 839680,
+ [GA_ANA_AC_TSN_SF_STATUS] = 839072,
+ [GA_ANA_AC_SG_ACCESS] = 839140,
+ [GA_ANA_AC_SG_CONFIG] = 851584,
+ [GA_ANA_AC_SG_STATUS] = 839088,
+ [GA_ANA_AC_SG_STATUS_STICKY] = 839152,
+ [GA_ANA_AC_STAT_GLOBAL_CFG_PORT] = 851552,
+ [GA_ANA_AC_STAT_CNT_CFG_PORT] = 843776,
+ [GA_ANA_AC_STAT_GLOBAL_CFG_ACL] = 893792,
+ [GA_ANA_ACL_COMMON] = 32768,
+ [GA_ANA_ACL_KEY_SEL] = 34200,
+ [GA_ANA_ACL_CNT_B] = 16384,
+ [GA_ANA_ACL_STICKY] = 36408,
+ [GA_ANA_AC_POL_POL_ALL_CFG] = 75968,
+ [GA_ANA_AC_POL_COMMON_BDLB] = 79048,
+ [GA_ANA_AC_POL_COMMON_BUM_SLB] = 79056,
+ [GA_ANA_AC_SDLB_LBGRP_TBL] = 295468,
+ [GA_ANA_CL_PORT] = 131072,
+ [GA_ANA_CL_COMMON] = 166912,
+ [GA_ANA_L2_COMMON] = 566024,
+ [GA_ANA_L3_COMMON] = 493632,
+ [GA_ANA_L3_VLAN_ARP_L3MC_STICKY] = 491460,
+ [GA_ASM_CFG] = 33280,
+ [GA_ASM_PFC_TIMER_CFG] = 34716,
+ [GA_ASM_LBK_WM_CFG] = 34744,
+ [GA_ASM_LBK_MISC_CFG] = 34756,
+ [GA_ASM_RAM_CTRL] = 34832,
+ [GA_EACL_ES2_KEY_SELECT_PROFILE] = 149504,
+ [GA_EACL_CNT_TBL] = 122880,
+ [GA_EACL_POL_CFG] = 150608,
+ [GA_EACL_ES2_STICKY] = 118696,
+ [GA_EACL_RAM_CTRL] = 118736,
+ [GA_GCB_SIO_CTRL] = 876,
+ [GA_HSCH_HSCH_DWRR] = 162816,
+ [GA_HSCH_HSCH_MISC] = 163104,
+ [GA_HSCH_HSCH_LEAK_LISTS] = 161664,
+ [GA_HSCH_SYSTEM] = 184000,
+ [GA_HSCH_MMGT] = 162368,
+ [GA_HSCH_TAS_CONFIG] = 162384,
+ [GA_PTP_PTP_CFG] = 320,
+ [GA_PTP_PTP_TOD_DOMAINS] = 336,
+ [GA_PTP_PHASE_DETECTOR_CTRL] = 420,
+ [GA_QSYS_CALCFG] = 2304,
+ [GA_QSYS_RAM_CTRL] = 2344,
+ [GA_REW_COMMON] = 387264,
+ [GA_REW_PORT] = 360448,
+ [GA_REW_VOE_PORT_LM_CNT] = 393216,
+ [GA_REW_RAM_CTRL] = 378696,
+ [GA_VOP_RAM_CTRL] = 279176,
+ [GA_XQS_SYSTEM] = 6768,
+ [GA_XQS_QLIMIT_SHR] = 7936,
+};
+
+const unsigned int sparx5_gcnt[GCNT_LAST] = {
+ [GC_ANA_AC_SRC] = 102,
+ [GC_ANA_AC_PGID] = 3290,
+ [GC_ANA_AC_TSN_SF_CFG] = 1024,
+ [GC_ANA_AC_STAT_CNT_CFG_PORT] = 70,
+ [GC_ANA_ACL_KEY_SEL] = 134,
+ [GC_ANA_ACL_CNT_A] = 4096,
+ [GC_ANA_ACL_CNT_B] = 4096,
+ [GC_ANA_AC_SDLB_LBGRP_TBL] = 10,
+ [GC_ANA_AC_SDLB_LBSET_TBL] = 4616,
+ [GC_ANA_CL_PORT] = 70,
+ [GC_ANA_L2_ISDX_LIMIT] = 1536,
+ [GC_ANA_L2_ISDX] = 4096,
+ [GC_ANA_L3_VLAN] = 5120,
+ [GC_ASM_DEV_STATISTICS] = 65,
+ [GC_EACL_ES2_KEY_SELECT_PROFILE] = 138,
+ [GC_EACL_CNT_TBL] = 2048,
+ [GC_GCB_SIO_CTRL] = 3,
+ [GC_HSCH_HSCH_CFG] = 5040,
+ [GC_HSCH_HSCH_DWRR] = 72,
+ [GC_PTP_PTP_PINS] = 5,
+ [GC_PTP_PHASE_DETECTOR_CTRL] = 5,
+ [GC_REW_PORT] = 70,
+ [GC_REW_VOE_PORT_LM_CNT] = 520,
+};
+
+const unsigned int sparx5_gsize[GSIZE_LAST] = {
+ [GW_ANA_AC_SRC] = 16,
+ [GW_ANA_L2_COMMON] = 700,
+ [GW_ASM_CFG] = 1088,
+ [GW_CPU_CPU_REGS] = 204,
+ [GW_DEV2G5_PHASE_DETECTOR_CTRL] = 8,
+ [GW_FDMA_FDMA] = 428,
+ [GW_GCB_CHIP_REGS] = 424,
+ [GW_HSCH_TAS_CONFIG] = 12,
+ [GW_PTP_PHASE_DETECTOR_CTRL] = 8,
+ [GW_QSYS_PAUSE_CFG] = 1128,
+};
+
+const unsigned int sparx5_fpos[FPOS_LAST] = {
+ [FP_CPU_PROC_CTRL_AARCH64_MODE_ENA] = 12,
+ [FP_CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS] = 11,
+ [FP_CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS] = 10,
+ [FP_CPU_PROC_CTRL_BE_EXCEP_MODE] = 9,
+ [FP_CPU_PROC_CTRL_VINITHI] = 8,
+ [FP_CPU_PROC_CTRL_CFGTE] = 7,
+ [FP_CPU_PROC_CTRL_CP15S_DISABLE] = 6,
+ [FP_CPU_PROC_CTRL_PROC_CRYPTO_DISABLE] = 5,
+ [FP_CPU_PROC_CTRL_L2_FLUSH_REQ] = 1,
+ [FP_DEV2G5_PHAD_CTRL_PHAD_ENA] = 7,
+ [FP_DEV2G5_PHAD_CTRL_PHAD_FAILED] = 6,
+ [FP_FDMA_CH_CFG_CH_XTR_STATUS_MODE] = 7,
+ [FP_FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY] = 6,
+ [FP_FDMA_CH_CFG_CH_INJ_PORT] = 5,
+ [FP_PTP_PTP_PIN_CFG_PTP_PIN_ACTION] = 26,
+ [FP_PTP_PTP_PIN_CFG_PTP_PIN_SYNC] = 24,
+ [FP_PTP_PTP_PIN_CFG_PTP_PIN_INV_POL] = 23,
+ [FP_PTP_PHAD_CTRL_PHAD_ENA] = 7,
+ [FP_PTP_PHAD_CTRL_PHAD_FAILED] = 6,
+};
+
+const unsigned int sparx5_fsize[FSIZE_LAST] = {
+ [FW_ANA_AC_PROBE_PORT_CFG_PROBE_PORT_MASK] = 32,
+ [FW_ANA_AC_SRC_CFG_PORT_MASK] = 32,
+ [FW_ANA_AC_PGID_CFG_PORT_MASK] = 32,
+ [FW_ANA_AC_TSN_SF_PORT_NUM] = 9,
+ [FW_ANA_AC_TSN_SF_CFG_TSN_SGID] = 10,
+ [FW_ANA_AC_TSN_SF_STATUS_TSN_SFID] = 10,
+ [FW_ANA_AC_SG_ACCESS_CTRL_SGID] = 10,
+ [FW_ANA_AC_PORT_SGE_CFG_MASK] = 16,
+ [FW_ANA_AC_SDLB_XLB_START_LBSET_START] = 13,
+ [FW_ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT] = 5,
+ [FW_ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT] = 13,
+ [FW_ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT] = 13,
+ [FW_ANA_AC_SDLB_XLB_NEXT_LBGRP] = 4,
+ [FW_ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR] = 13,
+ [FW_ANA_L2_AUTO_LRN_CFG_AUTO_LRN_ENA] = 32,
+ [FW_ANA_L2_DLB_CFG_DLB_IDX] = 13,
+ [FW_ANA_L2_TSN_CFG_TSN_SFID] = 10,
+ [FW_ANA_L3_VLAN_MASK_CFG_VLAN_PORT_MASK] = 32,
+ [FW_FDMA_CH_CFG_CH_DCB_DB_CNT] = 4,
+ [FW_GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL] = 9,
+ [FW_HSCH_SE_CFG_SE_DWRR_CNT] = 7,
+ [FW_HSCH_SE_CONNECT_SE_LEAK_LINK] = 16,
+ [FW_HSCH_SE_DLB_SENSE_SE_DLB_DPORT] = 7,
+ [FW_HSCH_HSCH_CFG_CFG_CFG_SE_IDX] = 13,
+ [FW_HSCH_HSCH_LEAK_CFG_LEAK_FIRST] = 16,
+ [FW_HSCH_FLUSH_CTRL_FLUSH_PORT] = 7,
+ [FW_HSCH_FLUSH_CTRL_FLUSH_HIER] = 16,
+ [FW_LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW] = 14,
+ [FW_LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX] = 11,
+ [FW_LRN_AUTOAGE_CFG_2_NEXT_ROW] = 14,
+ [FW_PTP_PTP_PIN_INTR_INTR_PTP] = 5,
+ [FW_PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA] = 5,
+ [FW_PTP_PTP_INTR_IDENT_INTR_PTP_IDENT] = 5,
+ [FW_PTP_PTP_PIN_CFG_PTP_PIN_SELECT] = 2,
+ [FW_QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL] = 7,
+ [FW_QRES_RES_CFG_WM_HIGH] = 12,
+ [FW_QRES_RES_STAT_MAXUSE] = 21,
+ [FW_QRES_RES_STAT_CUR_INUSE] = 21,
+ [FW_QSYS_PAUSE_CFG_PAUSE_START] = 12,
+ [FW_QSYS_PAUSE_CFG_PAUSE_STOP] = 12,
+ [FW_QSYS_ATOP_ATOP] = 12,
+ [FW_QSYS_ATOP_TOT_CFG_ATOP_TOT] = 12,
+ [FW_REW_RTAG_ETAG_CTRL_IPE_TBL] = 7,
+ [FW_XQS_STAT_CFG_STAT_VIEW] = 13,
+ [FW_XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP] = 15,
+ [FW_XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP] = 15,
+ [FW_XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP] = 15,
+ [FW_XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM] = 15,
+};
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_regs.h b/drivers/net/ethernet/microchip/sparx5/sparx5_regs.h
new file mode 100644
index 000000000000..ea28130c2341
--- /dev/null
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_regs.h
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Microchip Sparx5 Switch driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc.
+ */
+
+/* This file is autogenerated by cml-utils 2024-09-30 11:48:29 +0200.
+ * Commit ID: 9d07b8d19363f3cd3590ddb3f7a2e2768e16524b
+ */
+
+#ifndef _SPARX5_REGS_H_
+#define _SPARX5_REGS_H_
+
+/* These enumerated values are used to index the platform specific structs
+ * containing the addresses, counts, size and positions, of register groups,
+ * registers and fields.
+ */
+
+enum sparx5_tsize_enum {
+ TC_DEV10G,
+ TC_DEV2G5,
+ TC_DEV5G,
+ TC_PCS10G_BR,
+ TC_PCS5G_BR,
+ TSIZE_LAST,
+};
+
+enum sparx5_raddr_enum {
+ RA_CPU_PROC_CTRL,
+ RA_GCB_SOFT_RST,
+ RA_GCB_HW_SGPIO_TO_SD_MAP_CFG,
+ RADDR_LAST,
+};
+
+enum sparx5_rcnt_enum {
+ RC_ANA_AC_OWN_UPSID,
+ RC_ANA_ACL_VCAP_S2_CFG,
+ RC_ANA_ACL_OWN_UPSID,
+ RC_ANA_CL_OWN_UPSID,
+ RC_ANA_L2_OWN_UPSID,
+ RC_ASM_PORT_CFG,
+ RC_DSM_BUF_CFG,
+ RC_DSM_DEV_TX_STOP_WM_CFG,
+ RC_DSM_RX_PAUSE_CFG,
+ RC_DSM_MAC_CFG,
+ RC_DSM_MAC_ADDR_BASE_HIGH_CFG,
+ RC_DSM_MAC_ADDR_BASE_LOW_CFG,
+ RC_DSM_TAXI_CAL_CFG,
+ RC_GCB_HW_SGPIO_TO_SD_MAP_CFG,
+ RC_HSCH_PORT_MODE,
+ RC_QFWD_SWITCH_PORT_MODE,
+ RC_QSYS_PAUSE_CFG,
+ RC_QSYS_ATOP,
+ RC_QSYS_FWD_PRESSURE,
+ RC_QSYS_CAL_AUTO,
+ RC_REW_OWN_UPSID,
+ RC_REW_RTAG_ETAG_CTRL,
+ RCNT_LAST,
+};
+
+enum sparx5_gaddr_enum {
+ GA_ANA_AC_RAM_CTRL,
+ GA_ANA_AC_PS_COMMON,
+ GA_ANA_AC_MIRROR_PROBE,
+ GA_ANA_AC_SRC,
+ GA_ANA_AC_PGID,
+ GA_ANA_AC_TSN_SF,
+ GA_ANA_AC_TSN_SF_CFG,
+ GA_ANA_AC_TSN_SF_STATUS,
+ GA_ANA_AC_SG_ACCESS,
+ GA_ANA_AC_SG_CONFIG,
+ GA_ANA_AC_SG_STATUS,
+ GA_ANA_AC_SG_STATUS_STICKY,
+ GA_ANA_AC_STAT_GLOBAL_CFG_PORT,
+ GA_ANA_AC_STAT_CNT_CFG_PORT,
+ GA_ANA_AC_STAT_GLOBAL_CFG_ACL,
+ GA_ANA_ACL_COMMON,
+ GA_ANA_ACL_KEY_SEL,
+ GA_ANA_ACL_CNT_B,
+ GA_ANA_ACL_STICKY,
+ GA_ANA_AC_POL_POL_ALL_CFG,
+ GA_ANA_AC_POL_COMMON_BDLB,
+ GA_ANA_AC_POL_COMMON_BUM_SLB,
+ GA_ANA_AC_SDLB_LBGRP_TBL,
+ GA_ANA_CL_PORT,
+ GA_ANA_CL_COMMON,
+ GA_ANA_L2_COMMON,
+ GA_ANA_L3_COMMON,
+ GA_ANA_L3_VLAN_ARP_L3MC_STICKY,
+ GA_ASM_CFG,
+ GA_ASM_PFC_TIMER_CFG,
+ GA_ASM_LBK_WM_CFG,
+ GA_ASM_LBK_MISC_CFG,
+ GA_ASM_RAM_CTRL,
+ GA_EACL_ES2_KEY_SELECT_PROFILE,
+ GA_EACL_CNT_TBL,
+ GA_EACL_POL_CFG,
+ GA_EACL_ES2_STICKY,
+ GA_EACL_RAM_CTRL,
+ GA_GCB_SIO_CTRL,
+ GA_HSCH_HSCH_DWRR,
+ GA_HSCH_HSCH_MISC,
+ GA_HSCH_HSCH_LEAK_LISTS,
+ GA_HSCH_SYSTEM,
+ GA_HSCH_MMGT,
+ GA_HSCH_TAS_CONFIG,
+ GA_PTP_PTP_CFG,
+ GA_PTP_PTP_TOD_DOMAINS,
+ GA_PTP_PHASE_DETECTOR_CTRL,
+ GA_QSYS_CALCFG,
+ GA_QSYS_RAM_CTRL,
+ GA_REW_COMMON,
+ GA_REW_PORT,
+ GA_REW_VOE_PORT_LM_CNT,
+ GA_REW_RAM_CTRL,
+ GA_VOP_RAM_CTRL,
+ GA_XQS_SYSTEM,
+ GA_XQS_QLIMIT_SHR,
+ GADDR_LAST,
+};
+
+enum sparx5_gcnt_enum {
+ GC_ANA_AC_SRC,
+ GC_ANA_AC_PGID,
+ GC_ANA_AC_TSN_SF_CFG,
+ GC_ANA_AC_STAT_CNT_CFG_PORT,
+ GC_ANA_ACL_KEY_SEL,
+ GC_ANA_ACL_CNT_A,
+ GC_ANA_ACL_CNT_B,
+ GC_ANA_AC_SDLB_LBGRP_TBL,
+ GC_ANA_AC_SDLB_LBSET_TBL,
+ GC_ANA_CL_PORT,
+ GC_ANA_L2_ISDX_LIMIT,
+ GC_ANA_L2_ISDX,
+ GC_ANA_L3_VLAN,
+ GC_ASM_DEV_STATISTICS,
+ GC_EACL_ES2_KEY_SELECT_PROFILE,
+ GC_EACL_CNT_TBL,
+ GC_GCB_SIO_CTRL,
+ GC_HSCH_HSCH_CFG,
+ GC_HSCH_HSCH_DWRR,
+ GC_PTP_PTP_PINS,
+ GC_PTP_PHASE_DETECTOR_CTRL,
+ GC_REW_PORT,
+ GC_REW_VOE_PORT_LM_CNT,
+ GCNT_LAST,
+};
+
+enum sparx5_gsize_enum {
+ GW_ANA_AC_SRC,
+ GW_ANA_L2_COMMON,
+ GW_ASM_CFG,
+ GW_CPU_CPU_REGS,
+ GW_DEV2G5_PHASE_DETECTOR_CTRL,
+ GW_FDMA_FDMA,
+ GW_GCB_CHIP_REGS,
+ GW_HSCH_TAS_CONFIG,
+ GW_PTP_PHASE_DETECTOR_CTRL,
+ GW_QSYS_PAUSE_CFG,
+ GSIZE_LAST,
+};
+
+enum sparx5_fpos_enum {
+ FP_CPU_PROC_CTRL_AARCH64_MODE_ENA,
+ FP_CPU_PROC_CTRL_L2_RST_INVALIDATE_DIS,
+ FP_CPU_PROC_CTRL_L1_RST_INVALIDATE_DIS,
+ FP_CPU_PROC_CTRL_BE_EXCEP_MODE,
+ FP_CPU_PROC_CTRL_VINITHI,
+ FP_CPU_PROC_CTRL_CFGTE,
+ FP_CPU_PROC_CTRL_CP15S_DISABLE,
+ FP_CPU_PROC_CTRL_PROC_CRYPTO_DISABLE,
+ FP_CPU_PROC_CTRL_L2_FLUSH_REQ,
+ FP_DEV2G5_PHAD_CTRL_PHAD_ENA,
+ FP_DEV2G5_PHAD_CTRL_PHAD_FAILED,
+ FP_FDMA_CH_CFG_CH_XTR_STATUS_MODE,
+ FP_FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY,
+ FP_FDMA_CH_CFG_CH_INJ_PORT,
+ FP_PTP_PTP_PIN_CFG_PTP_PIN_ACTION,
+ FP_PTP_PTP_PIN_CFG_PTP_PIN_SYNC,
+ FP_PTP_PTP_PIN_CFG_PTP_PIN_INV_POL,
+ FP_PTP_PHAD_CTRL_PHAD_ENA,
+ FP_PTP_PHAD_CTRL_PHAD_FAILED,
+ FPOS_LAST,
+};
+
+enum sparx5_fsize_enum {
+ FW_ANA_AC_PROBE_PORT_CFG_PROBE_PORT_MASK,
+ FW_ANA_AC_SRC_CFG_PORT_MASK,
+ FW_ANA_AC_PGID_CFG_PORT_MASK,
+ FW_ANA_AC_TSN_SF_PORT_NUM,
+ FW_ANA_AC_TSN_SF_CFG_TSN_SGID,
+ FW_ANA_AC_TSN_SF_STATUS_TSN_SFID,
+ FW_ANA_AC_SG_ACCESS_CTRL_SGID,
+ FW_ANA_AC_PORT_SGE_CFG_MASK,
+ FW_ANA_AC_SDLB_XLB_START_LBSET_START,
+ FW_ANA_AC_SDLB_LBGRP_MISC_THRES_SHIFT,
+ FW_ANA_AC_SDLB_LBGRP_STATE_TBL_PUP_LBSET_NEXT,
+ FW_ANA_AC_SDLB_XLB_NEXT_LBSET_NEXT,
+ FW_ANA_AC_SDLB_XLB_NEXT_LBGRP,
+ FW_ANA_AC_SDLB_INH_LBSET_ADDR_INH_LBSET_ADDR,
+ FW_ANA_L2_AUTO_LRN_CFG_AUTO_LRN_ENA,
+ FW_ANA_L2_DLB_CFG_DLB_IDX,
+ FW_ANA_L2_TSN_CFG_TSN_SFID,
+ FW_ANA_L3_VLAN_MASK_CFG_VLAN_PORT_MASK,
+ FW_FDMA_CH_CFG_CH_DCB_DB_CNT,
+ FW_GCB_HW_SGPIO_TO_SD_MAP_CFG_SGPIO_TO_SD_SEL,
+ FW_HSCH_SE_CFG_SE_DWRR_CNT,
+ FW_HSCH_SE_CONNECT_SE_LEAK_LINK,
+ FW_HSCH_SE_DLB_SENSE_SE_DLB_DPORT,
+ FW_HSCH_HSCH_CFG_CFG_CFG_SE_IDX,
+ FW_HSCH_HSCH_LEAK_CFG_LEAK_FIRST,
+ FW_HSCH_FLUSH_CTRL_FLUSH_PORT,
+ FW_HSCH_FLUSH_CTRL_FLUSH_HIER,
+ FW_LRN_COMMON_ACCESS_CTRL_CPU_ACCESS_DIRECT_ROW,
+ FW_LRN_MAC_ACCESS_CFG_3_MAC_ENTRY_ISDX_LIMIT_IDX,
+ FW_LRN_AUTOAGE_CFG_2_NEXT_ROW,
+ FW_PTP_PTP_PIN_INTR_INTR_PTP,
+ FW_PTP_PTP_PIN_INTR_ENA_INTR_PTP_ENA,
+ FW_PTP_PTP_INTR_IDENT_INTR_PTP_IDENT,
+ FW_PTP_PTP_PIN_CFG_PTP_PIN_SELECT,
+ FW_QFWD_FRAME_COPY_CFG_FRMC_PORT_VAL,
+ FW_QRES_RES_CFG_WM_HIGH,
+ FW_QRES_RES_STAT_MAXUSE,
+ FW_QRES_RES_STAT_CUR_INUSE,
+ FW_QSYS_PAUSE_CFG_PAUSE_START,
+ FW_QSYS_PAUSE_CFG_PAUSE_STOP,
+ FW_QSYS_ATOP_ATOP,
+ FW_QSYS_ATOP_TOT_CFG_ATOP_TOT,
+ FW_REW_RTAG_ETAG_CTRL_IPE_TBL,
+ FW_XQS_STAT_CFG_STAT_VIEW,
+ FW_XQS_QLIMIT_SHR_TOP_CFG_QLIMIT_SHR_TOP,
+ FW_XQS_QLIMIT_SHR_ATOP_CFG_QLIMIT_SHR_ATOP,
+ FW_XQS_QLIMIT_SHR_CTOP_CFG_QLIMIT_SHR_CTOP,
+ FW_XQS_QLIMIT_SHR_QLIM_CFG_QLIMIT_SHR_QLIM,
+ FSIZE_LAST,
+};
+
+extern const unsigned int sparx5_tsize[TSIZE_LAST];
+extern const unsigned int sparx5_raddr[RADDR_LAST];
+extern const unsigned int sparx5_rcnt[RCNT_LAST];
+extern const unsigned int sparx5_gaddr[GADDR_LAST];
+extern const unsigned int sparx5_gcnt[GCNT_LAST];
+extern const unsigned int sparx5_gsize[GSIZE_LAST];
+extern const unsigned int sparx5_fpos[FPOS_LAST];
+extern const unsigned int sparx5_fsize[FSIZE_LAST];
+
+#endif /* _SPARX5_REGS_H_ */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_sdlb.c b/drivers/net/ethernet/microchip/sparx5/sparx5_sdlb.c
index f5267218caeb..98a3f44c569c 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_sdlb.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_sdlb.c
@@ -20,17 +20,18 @@ struct sparx5_sdlb_group sdlb_groups[SPX5_SDLB_GROUP_CNT] = {
{ 5000000ULL, 8192 / 8, 64 } /* 5 M */
};
-int sparx5_sdlb_clk_hz_get(struct sparx5 *sparx5)
+struct sparx5_sdlb_group *sparx5_get_sdlb_group(int idx)
+{
+ return &sdlb_groups[idx];
+}
+
+u64 sparx5_sdlb_clk_hz_get(struct sparx5 *sparx5)
{
- u32 clk_per_100ps;
u64 clk_hz;
- clk_per_100ps = HSCH_SYS_CLK_PER_100PS_GET(spx5_rd(sparx5,
- HSCH_SYS_CLK_PER));
- if (!clk_per_100ps)
- clk_per_100ps = SPX5_CLK_PER_100PS_DEFAULT;
+ clk_hz = (10 * 1000 * 1000) /
+ (sparx5_clk_period(sparx5->coreclock) / 100);
- clk_hz = (10 * 1000 * 1000) / clk_per_100ps;
return clk_hz *= 1000;
}
@@ -178,14 +179,15 @@ static int sparx5_sdlb_group_get_count(struct sparx5 *sparx5, u32 group)
int sparx5_sdlb_group_get_by_rate(struct sparx5 *sparx5, u32 rate, u32 burst)
{
+ const struct sparx5_ops *ops = sparx5->data->ops;
const struct sparx5_sdlb_group *group;
u64 rate_bps;
int i, count;
rate_bps = rate * 1000;
- for (i = SPX5_SDLB_GROUP_CNT - 1; i >= 0; i--) {
- group = &sdlb_groups[i];
+ for (i = sparx5->data->consts->n_lb_groups - 1; i >= 0; i--) {
+ group = ops->get_sdlb_group(i);
count = sparx5_sdlb_group_get_count(sparx5, i);
@@ -208,7 +210,7 @@ int sparx5_sdlb_group_get_by_index(struct sparx5 *sparx5, u32 idx, u32 *group)
u32 itr, next;
int i;
- for (i = 0; i < SPX5_SDLB_GROUP_CNT; i++) {
+ for (i = 0; i < sparx5->data->consts->n_lb_groups; i++) {
if (sparx5_sdlb_group_is_empty(sparx5, i))
continue;
@@ -303,11 +305,12 @@ int sparx5_sdlb_group_del(struct sparx5 *sparx5, u32 group, u32 idx)
void sparx5_sdlb_group_init(struct sparx5 *sparx5, u64 max_rate, u32 min_burst,
u32 frame_size, u32 idx)
{
+ const struct sparx5_ops *ops = sparx5->data->ops;
u32 thres_shift, mask = 0x01, power = 0;
struct sparx5_sdlb_group *group;
u64 max_token;
- group = &sdlb_groups[idx];
+ group = ops->get_sdlb_group(idx);
/* Number of positions to right-shift LB's threshold value. */
while ((min_burst & mask) == 0) {
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
index 0b4abc3eb53d..bc9ecb9392cd 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
@@ -32,24 +32,34 @@ static int sparx5_port_attr_pre_bridge_flags(struct sparx5_port *port,
static void sparx5_port_update_mcast_ip_flood(struct sparx5_port *port, bool flood_flag)
{
bool should_flood = flood_flag || port->is_mrouter;
+ struct sparx5 *sparx5 = port->sparx5;
int pgid;
- for (pgid = PGID_IPV4_MC_DATA; pgid <= PGID_IPV6_MC_CTRL; pgid++)
+ for (pgid = sparx5_get_pgid(sparx5, PGID_IPV4_MC_DATA);
+ pgid <= sparx5_get_pgid(sparx5, PGID_IPV6_MC_CTRL); pgid++)
sparx5_pgid_update_mask(port, pgid, should_flood);
}
static void sparx5_port_attr_bridge_flags(struct sparx5_port *port,
struct switchdev_brport_flags flags)
{
+ struct sparx5 *sparx5 = port->sparx5;
+
if (flags.mask & BR_MCAST_FLOOD) {
- sparx5_pgid_update_mask(port, PGID_MC_FLOOD, !!(flags.val & BR_MCAST_FLOOD));
+ sparx5_pgid_update_mask(port,
+ sparx5_get_pgid(sparx5, PGID_MC_FLOOD),
+ !!(flags.val & BR_MCAST_FLOOD));
sparx5_port_update_mcast_ip_flood(port, !!(flags.val & BR_MCAST_FLOOD));
}
if (flags.mask & BR_FLOOD)
- sparx5_pgid_update_mask(port, PGID_UC_FLOOD, !!(flags.val & BR_FLOOD));
+ sparx5_pgid_update_mask(port,
+ sparx5_get_pgid(sparx5, PGID_UC_FLOOD),
+ !!(flags.val & BR_FLOOD));
if (flags.mask & BR_BCAST_FLOOD)
- sparx5_pgid_update_mask(port, PGID_BCAST, !!(flags.val & BR_BCAST_FLOOD));
+ sparx5_pgid_update_mask(port,
+ sparx5_get_pgid(sparx5, PGID_BCAST),
+ !!(flags.val & BR_BCAST_FLOOD));
}
static void sparx5_attr_stp_state_set(struct sparx5_port *port,
@@ -219,7 +229,8 @@ static void sparx5_port_bridge_leave(struct sparx5_port *port,
port->vid = NULL_VID;
/* Forward frames to CPU */
- sparx5_mact_learn(sparx5, PGID_CPU, port->ndev->dev_addr, 0);
+ sparx5_mact_learn(sparx5, sparx5_get_pgid(sparx5, PGID_CPU),
+ port->ndev->dev_addr, 0);
/* Port enters in host more therefore restore mc list */
__dev_mc_sync(port->ndev, sparx5_mc_sync, sparx5_mc_unsync);
@@ -254,7 +265,8 @@ static int sparx5_port_add_addr(struct net_device *dev, bool up)
u16 vid = port->pvid;
if (up)
- sparx5_mact_learn(sparx5, PGID_CPU, port->ndev->dev_addr, vid);
+ sparx5_mact_learn(sparx5, sparx5_get_pgid(sparx5, PGID_CPU),
+ port->ndev->dev_addr, vid);
else
sparx5_mact_forget(sparx5, port->ndev->dev_addr, vid);
@@ -330,7 +342,8 @@ static void sparx5_switchdev_bridge_fdb_event_work(struct work_struct *work)
switch (switchdev_work->event) {
case SWITCHDEV_FDB_ADD_TO_DEVICE:
if (host_addr)
- sparx5_add_mact_entry(sparx5, dev, PGID_CPU,
+ sparx5_add_mact_entry(sparx5, dev,
+ sparx5_get_pgid(sparx5, PGID_CPU),
fdb_info->addr, vid);
else
sparx5_add_mact_entry(sparx5, port->ndev, port->portno,
@@ -418,8 +431,8 @@ static int sparx5_handle_port_vlan_add(struct net_device *dev,
switchdev_blocking_nb);
/* Flood broadcast to CPU */
- sparx5_mact_learn(sparx5, PGID_BCAST, dev->broadcast,
- v->vid);
+ sparx5_mact_learn(sparx5, sparx5_get_pgid(sparx5, PGID_BCAST),
+ dev->broadcast, v->vid);
return 0;
}
@@ -547,7 +560,7 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev,
/* Add any mrouter ports to the new entry */
if (is_new && ether_addr_is_ip_mcast(v->addr))
- for (i = 0; i < SPX5_PORTS; i++)
+ for (i = 0; i < spx5->data->consts->n_ports; i++)
if (spx5->ports[i] && spx5->ports[i]->is_mrouter)
sparx5_pgid_update_mask(spx5->ports[i],
entry->pgid_idx,
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c
index e80f3166db7d..28b2514c8330 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c
@@ -60,8 +60,8 @@ static int sparx5_tc_setup_block(struct net_device *ndev,
cb, ndev, ndev, false);
}
-static void sparx5_tc_get_layer_and_idx(u32 parent, u32 portno, u32 *layer,
- u32 *idx)
+static void sparx5_tc_get_layer_and_idx(struct sparx5 *sparx5, u32 parent,
+ u32 portno, u32 *layer, u32 *idx)
{
if (parent == TC_H_ROOT) {
*layer = 2;
@@ -90,8 +90,8 @@ static int sparx5_tc_setup_qdisc_tbf(struct net_device *ndev,
struct sparx5_port *port = netdev_priv(ndev);
u32 layer, se_idx;
- sparx5_tc_get_layer_and_idx(qopt->parent, port->portno, &layer,
- &se_idx);
+ sparx5_tc_get_layer_and_idx(port->sparx5, qopt->parent, port->portno,
+ &layer, &se_idx);
switch (qopt->command) {
case TC_TBF_REPLACE:
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
index 8d67d9f24c76..4dc1ebd5d510 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
@@ -785,7 +785,9 @@ static int sparx5_tc_flower_psfp_setup(struct sparx5 *sparx5,
* allocate a stream gate that is always open.
*/
if (sg_idx < 0) {
- sg_idx = sparx5_pool_idx_to_id(SPX5_PSFP_SG_OPEN);
+ /* Always-open stream gate is always the last */
+ sg_idx = sparx5_pool_idx_to_id(sparx5->data->consts->n_gates -
+ 1);
sg->ipv = 0; /* Disabled */
sg->cycletime = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT;
sg->num_entries = 1;
@@ -1282,6 +1284,11 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
/* Setup PSFP */
if (tc_sg_idx >= 0 || tc_pol_idx >= 0) {
+ if (!sparx5_has_feature(sparx5, SPX5_FEATURE_PSFP)) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
err = sparx5_tc_flower_psfp_setup(sparx5, vrule, tc_sg_idx,
tc_pol_idx, &sg, &fm, &sf);
if (err)
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_ag_api.h b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_ag_api.h
index 7d106f1276fe..e68f5639a40a 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_ag_api.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_ag_api.h
@@ -10,6 +10,8 @@
#ifndef __SPARX5_VCAP_AG_API_H__
#define __SPARX5_VCAP_AG_API_H__
+#include "vcap_api.h"
+
/* VCAPs */
extern const struct vcap_info sparx5_vcaps[];
extern const struct vcap_statistics sparx5_vcap_stats;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
index 967c8621c250..25066ddb8d4d 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
@@ -17,7 +17,6 @@
#define SUPER_VCAP_BLK_SIZE 3072 /* addresses per Super VCAP block */
#define STREAMSIZE (64 * 4) /* bytes in the VCAP cache area */
-#define SPARX5_IS2_LOOKUPS 4
#define VCAP_IS2_KEYSEL(_ena, _noneth, _v4_mc, _v4_uc, _v6_mc, _v6_uc, _arp) \
(ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(_ena) | \
ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(_noneth) | \
@@ -27,7 +26,6 @@
ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(_v6_uc) | \
ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(_arp))
-#define SPARX5_IS0_LOOKUPS 6
#define VCAP_IS0_KEYSEL(_ena, _etype, _ipv4, _ipv6, _mpls_uc, _mpls_mc, _mlbs) \
(ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(_ena) | \
ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(_etype) | \
@@ -37,31 +35,17 @@
ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_SET(_mpls_mc) | \
ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_SET(_mlbs))
-#define SPARX5_ES0_LOOKUPS 1
#define VCAP_ES0_KEYSEL(_key) (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_SET(_key))
#define SPARX5_STAT_ESDX_GRN_PKTS 0x300
#define SPARX5_STAT_ESDX_YEL_PKTS 0x301
-#define SPARX5_ES2_LOOKUPS 2
#define VCAP_ES2_KEYSEL(_ena, _arp, _ipv4, _ipv6) \
(EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(_ena) | \
EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(_arp) | \
EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(_ipv4) | \
EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(_ipv6))
-static struct sparx5_vcap_inst {
- enum vcap_type vtype; /* type of vcap */
- int vinst; /* instance number within the same type */
- int lookups; /* number of lookups in this vcap type */
- int lookups_per_instance; /* number of lookups in this instance */
- int first_cid; /* first chain id in this vcap */
- int last_cid; /* last chain id in this vcap */
- int count; /* number of available addresses, not in super vcap */
- int map_id; /* id in the super vcap block mapping (if applicable) */
- int blockno; /* starting block in super vcap (if applicable) */
- int blocks; /* number of blocks in super vcap (if applicable) */
- bool ingress; /* is vcap in the ingress path */
-} sparx5_vcap_inst_cfg[] = {
+const struct sparx5_vcap_inst sparx5_vcap_inst_cfg[] = {
{
.vtype = VCAP_TYPE_IS0, /* CLM-0 */
.vinst = 0,
@@ -1793,6 +1777,7 @@ void sparx5_vcap_set_port_keyset(struct net_device *ndev,
static void sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5,
struct vcap_admin *admin)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
int portno, lookup;
u32 keysel;
@@ -1804,7 +1789,7 @@ static void sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5,
VCAP_IS0_PS_MPLS_FOLLOW_ETYPE,
VCAP_IS0_PS_MLBS_FOLLOW_ETYPE);
for (lookup = 0; lookup < admin->lookups; ++lookup) {
- for (portno = 0; portno < SPX5_PORTS; ++portno) {
+ for (portno = 0; portno < consts->n_ports; ++portno) {
spx5_wr(keysel, sparx5,
ANA_CL_ADV_CL_CFG(portno, lookup));
spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA,
@@ -1819,6 +1804,7 @@ static void sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5,
static void sparx5_vcap_is2_port_key_selection(struct sparx5 *sparx5,
struct vcap_admin *admin)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
int portno, lookup;
u32 keysel;
@@ -1829,13 +1815,13 @@ static void sparx5_vcap_is2_port_key_selection(struct sparx5 *sparx5,
VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
VCAP_IS2_PS_ARP_ARP);
for (lookup = 0; lookup < admin->lookups; ++lookup) {
- for (portno = 0; portno < SPX5_PORTS; ++portno) {
+ for (portno = 0; portno < consts->n_ports; ++portno) {
spx5_wr(keysel, sparx5,
ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
}
}
/* IS2 lookups are in bit 0:3 */
- for (portno = 0; portno < SPX5_PORTS; ++portno)
+ for (portno = 0; portno < consts->n_ports; ++portno)
spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0xf),
ANA_ACL_VCAP_S2_CFG_SEC_ENA,
sparx5,
@@ -1846,11 +1832,12 @@ static void sparx5_vcap_is2_port_key_selection(struct sparx5 *sparx5,
static void sparx5_vcap_es0_port_key_selection(struct sparx5 *sparx5,
struct vcap_admin *admin)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
int portno;
u32 keysel;
keysel = VCAP_ES0_KEYSEL(VCAP_ES0_PS_FORCE_ISDX_LOOKUPS);
- for (portno = 0; portno < SPX5_PORTS; ++portno)
+ for (portno = 0; portno < consts->n_ports; ++portno)
spx5_rmw(keysel, REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA,
sparx5, REW_RTAG_ETAG_CTRL(portno));
@@ -1862,6 +1849,7 @@ static void sparx5_vcap_es0_port_key_selection(struct sparx5 *sparx5,
static void sparx5_vcap_es2_port_key_selection(struct sparx5 *sparx5,
struct vcap_admin *admin)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
int portno, lookup;
u32 keysel;
@@ -1869,7 +1857,7 @@ static void sparx5_vcap_es2_port_key_selection(struct sparx5 *sparx5,
VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER,
VCAP_ES2_PS_IPV6_IP_7TUPLE);
for (lookup = 0; lookup < admin->lookups; ++lookup)
- for (portno = 0; portno < SPX5_PORTS; ++portno)
+ for (portno = 0; portno < consts->n_ports; ++portno)
spx5_wr(keysel, sparx5,
EACL_VCAP_ES2_KEY_SEL(portno, lookup));
}
@@ -1901,19 +1889,20 @@ static void sparx5_vcap_port_key_selection(struct sparx5 *sparx5,
static void sparx5_vcap_port_key_deselection(struct sparx5 *sparx5,
struct vcap_admin *admin)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
int portno, lookup;
switch (admin->vtype) {
case VCAP_TYPE_IS0:
for (lookup = 0; lookup < admin->lookups; ++lookup)
- for (portno = 0; portno < SPX5_PORTS; ++portno)
+ for (portno = 0; portno < consts->n_ports; ++portno)
spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(0),
ANA_CL_ADV_CL_CFG_LOOKUP_ENA,
sparx5,
ANA_CL_ADV_CL_CFG(portno, lookup));
break;
case VCAP_TYPE_IS2:
- for (portno = 0; portno < SPX5_PORTS; ++portno)
+ for (portno = 0; portno < consts->n_ports; ++portno)
spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0),
ANA_ACL_VCAP_S2_CFG_SEC_ENA,
sparx5,
@@ -1925,7 +1914,7 @@ static void sparx5_vcap_port_key_deselection(struct sparx5 *sparx5,
break;
case VCAP_TYPE_ES2:
for (lookup = 0; lookup < admin->lookups; ++lookup)
- for (portno = 0; portno < SPX5_PORTS; ++portno)
+ for (portno = 0; portno < consts->n_ports; ++portno)
spx5_rmw(EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(0),
EACL_VCAP_ES2_KEY_SEL_KEY_ENA,
sparx5,
@@ -2042,6 +2031,7 @@ static void sparx5_vcap_block_alloc(struct sparx5 *sparx5,
/* Allocate a vcap control and vcap instances and configure the system */
int sparx5_vcap_init(struct sparx5 *sparx5)
{
+ const struct sparx5_consts *consts = sparx5->data->consts;
const struct sparx5_vcap_inst *cfg;
struct vcap_control *ctrl;
struct vcap_admin *admin;
@@ -2063,14 +2053,14 @@ int sparx5_vcap_init(struct sparx5 *sparx5)
sparx5->vcap_ctrl = ctrl;
/* select the sparx5 VCAP model */
- ctrl->vcaps = sparx5_vcaps;
- ctrl->stats = &sparx5_vcap_stats;
+ ctrl->vcaps = consts->vcaps;
+ ctrl->stats = consts->vcap_stats;
/* Setup callbacks to allow the API to use the VCAP HW */
ctrl->ops = &sparx5_vcap_ops;
INIT_LIST_HEAD(&ctrl->list);
for (idx = 0; idx < ARRAY_SIZE(sparx5_vcap_inst_cfg); ++idx) {
- cfg = &sparx5_vcap_inst_cfg[idx];
+ cfg = &consts->vcaps_cfg[idx];
admin = sparx5_vcap_admin_alloc(sparx5, ctrl, cfg);
if (IS_ERR(admin)) {
err = PTR_ERR(admin);
@@ -2085,7 +2075,7 @@ int sparx5_vcap_init(struct sparx5 *sparx5)
list_add_tail(&admin->list, &ctrl->list);
}
dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl);
- for (idx = 0; idx < SPX5_PORTS; ++idx)
+ for (idx = 0; idx < consts->n_ports; ++idx)
if (sparx5->ports[idx])
vcap_port_debugfs(sparx5->dev, dir, ctrl,
sparx5->ports[idx]->ndev);
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h
index 2684d9199b05..d0a42406bf26 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h
@@ -16,6 +16,11 @@
#include "vcap_api.h"
#include "vcap_api_client.h"
+#define SPARX5_IS2_LOOKUPS 4
+#define SPARX5_IS0_LOOKUPS 6
+#define SPARX5_ES0_LOOKUPS 1
+#define SPARX5_ES2_LOOKUPS 2
+
#define SPARX5_VCAP_CID_IS0_L0 VCAP_CID_INGRESS_L0 /* IS0/CLM lookup 0 */
#define SPARX5_VCAP_CID_IS0_L1 VCAP_CID_INGRESS_L1 /* IS0/CLM lookup 1 */
#define SPARX5_VCAP_CID_IS0_L2 VCAP_CID_INGRESS_L2 /* IS0/CLM lookup 2 */
@@ -40,6 +45,22 @@
#define SPARX5_VCAP_CID_ES2_MAX \
(VCAP_CID_EGRESS_STAGE2_L1 + VCAP_CID_LOOKUP_SIZE - 1) /* ES2 Max */
+struct sparx5_vcap_inst {
+ enum vcap_type vtype; /* type of vcap */
+ int vinst; /* instance number within the same type */
+ int lookups; /* number of lookups in this vcap type */
+ int lookups_per_instance; /* number of lookups in this instance */
+ int first_cid; /* first chain id in this vcap */
+ int last_cid; /* last chain id in this vcap */
+ int count; /* number of available addresses, not in super vcap */
+ int map_id; /* id in the super vcap block mapping (if applicable) */
+ int blockno; /* starting block in super vcap (if applicable) */
+ int blocks; /* number of blocks in super vcap (if applicable) */
+ bool ingress; /* is vcap in the ingress path */
+};
+
+extern const struct sparx5_vcap_inst sparx5_vcap_inst_cfg[];
+
/* IS0 port keyset selection control */
/* IS0 ethernet, IPv4, IPv6 traffic type keyset generation */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
index ac001ae59a38..d42097aa60a0 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
@@ -16,8 +16,10 @@ static int sparx5_vlant_set_mask(struct sparx5 *sparx5, u16 vid)
/* Output mask to respective registers */
spx5_wr(mask[0], sparx5, ANA_L3_VLAN_MASK_CFG(vid));
- spx5_wr(mask[1], sparx5, ANA_L3_VLAN_MASK_CFG1(vid));
- spx5_wr(mask[2], sparx5, ANA_L3_VLAN_MASK_CFG2(vid));
+ if (is_sparx5(sparx5)) {
+ spx5_wr(mask[1], sparx5, ANA_L3_VLAN_MASK_CFG1(vid));
+ spx5_wr(mask[2], sparx5, ANA_L3_VLAN_MASK_CFG2(vid));
+ }
return 0;
}
@@ -141,15 +143,19 @@ void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable)
void sparx5_pgid_clear(struct sparx5 *spx5, int pgid)
{
spx5_wr(0, spx5, ANA_AC_PGID_CFG(pgid));
- spx5_wr(0, spx5, ANA_AC_PGID_CFG1(pgid));
- spx5_wr(0, spx5, ANA_AC_PGID_CFG2(pgid));
+ if (is_sparx5(spx5)) {
+ spx5_wr(0, spx5, ANA_AC_PGID_CFG1(pgid));
+ spx5_wr(0, spx5, ANA_AC_PGID_CFG2(pgid));
+ }
}
void sparx5_pgid_read_mask(struct sparx5 *spx5, int pgid, u32 portmask[3])
{
portmask[0] = spx5_rd(spx5, ANA_AC_PGID_CFG(pgid));
- portmask[1] = spx5_rd(spx5, ANA_AC_PGID_CFG1(pgid));
- portmask[2] = spx5_rd(spx5, ANA_AC_PGID_CFG2(pgid));
+ if (is_sparx5(spx5)) {
+ portmask[1] = spx5_rd(spx5, ANA_AC_PGID_CFG1(pgid));
+ portmask[2] = spx5_rd(spx5, ANA_AC_PGID_CFG2(pgid));
+ }
}
void sparx5_update_fwd(struct sparx5 *sparx5)
@@ -162,26 +168,33 @@ void sparx5_update_fwd(struct sparx5 *sparx5)
bitmap_to_arr32(mask, sparx5->bridge_fwd_mask, SPX5_PORTS);
/* Update flood masks */
- for (port = PGID_UC_FLOOD; port <= PGID_BCAST; port++) {
+ for (port = sparx5_get_pgid(sparx5, PGID_UC_FLOOD);
+ port <= sparx5_get_pgid(sparx5, PGID_BCAST); port++) {
spx5_wr(mask[0], sparx5, ANA_AC_PGID_CFG(port));
- spx5_wr(mask[1], sparx5, ANA_AC_PGID_CFG1(port));
- spx5_wr(mask[2], sparx5, ANA_AC_PGID_CFG2(port));
+ if (is_sparx5(sparx5)) {
+ spx5_wr(mask[1], sparx5, ANA_AC_PGID_CFG1(port));
+ spx5_wr(mask[2], sparx5, ANA_AC_PGID_CFG2(port));
+ }
}
/* Update SRC masks */
- for (port = 0; port < SPX5_PORTS; port++) {
+ for (port = 0; port < sparx5->data->consts->n_ports; port++) {
if (test_bit(port, sparx5->bridge_fwd_mask)) {
/* Allow to send to all bridged but self */
bitmap_copy(workmask, sparx5->bridge_fwd_mask, SPX5_PORTS);
clear_bit(port, workmask);
bitmap_to_arr32(mask, workmask, SPX5_PORTS);
spx5_wr(mask[0], sparx5, ANA_AC_SRC_CFG(port));
- spx5_wr(mask[1], sparx5, ANA_AC_SRC_CFG1(port));
- spx5_wr(mask[2], sparx5, ANA_AC_SRC_CFG2(port));
+ if (is_sparx5(sparx5)) {
+ spx5_wr(mask[1], sparx5, ANA_AC_SRC_CFG1(port));
+ spx5_wr(mask[2], sparx5, ANA_AC_SRC_CFG2(port));
+ }
} else {
spx5_wr(0, sparx5, ANA_AC_SRC_CFG(port));
- spx5_wr(0, sparx5, ANA_AC_SRC_CFG1(port));
- spx5_wr(0, sparx5, ANA_AC_SRC_CFG2(port));
+ if (is_sparx5(sparx5)) {
+ spx5_wr(0, sparx5, ANA_AC_SRC_CFG1(port));
+ spx5_wr(0, sparx5, ANA_AC_SRC_CFG2(port));
+ }
}
}
@@ -192,8 +205,10 @@ void sparx5_update_fwd(struct sparx5 *sparx5)
/* Apply learning mask */
spx5_wr(mask[0], sparx5, ANA_L2_AUTO_LRN_CFG);
- spx5_wr(mask[1], sparx5, ANA_L2_AUTO_LRN_CFG1);
- spx5_wr(mask[2], sparx5, ANA_L2_AUTO_LRN_CFG2);
+ if (is_sparx5(sparx5)) {
+ spx5_wr(mask[1], sparx5, ANA_L2_AUTO_LRN_CFG1);
+ spx5_wr(mask[2], sparx5, ANA_L2_AUTO_LRN_CFG2);
+ }
}
void sparx5_vlan_port_apply(struct sparx5 *sparx5,
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
index 7251121ab196..16eb3de60eb6 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
@@ -366,12 +366,13 @@ static void vcap_api_iterator_init_test(struct kunit *test)
struct vcap_typegroup typegroups[] = {
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 156, .width = 1, .value = 0, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
struct vcap_typegroup typegroups2[] = {
{ .offset = 0, .width = 3, .value = 4, },
{ .offset = 49, .width = 2, .value = 0, },
{ .offset = 98, .width = 2, .value = 0, },
+ { }
};
vcap_iter_init(&iter, 52, typegroups, 86);
@@ -399,6 +400,7 @@ static void vcap_api_iterator_next_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 0, },
{ .offset = 196, .width = 2, .value = 0, },
{ .offset = 245, .width = 1, .value = 0, },
+ { }
};
int idx;
@@ -433,7 +435,7 @@ static void vcap_api_encode_typegroups_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 5, },
{ .offset = 196, .width = 2, .value = 2, },
{ .offset = 245, .width = 5, .value = 27, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
vcap_encode_typegroups(stream, 49, typegroups, false);
@@ -463,6 +465,7 @@ static void vcap_api_encode_bit_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 5, },
{ .offset = 196, .width = 2, .value = 2, },
{ .offset = 245, .width = 1, .value = 0, },
+ { }
};
vcap_iter_init(&iter, 49, typegroups, 44);
@@ -489,7 +492,7 @@ static void vcap_api_encode_field_test(struct kunit *test)
{ .offset = 147, .width = 3, .value = 5, },
{ .offset = 196, .width = 2, .value = 2, },
{ .offset = 245, .width = 5, .value = 27, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
struct vcap_field rf = {
.type = VCAP_FIELD_U32,
@@ -538,7 +541,7 @@ static void vcap_api_encode_short_field_test(struct kunit *test)
{ .offset = 0, .width = 3, .value = 7, },
{ .offset = 21, .width = 2, .value = 3, },
{ .offset = 42, .width = 1, .value = 1, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
struct vcap_field rf = {
.type = VCAP_FIELD_U32,
@@ -608,7 +611,7 @@ static void vcap_api_encode_keyfield_test(struct kunit *test)
struct vcap_typegroup tgt[] = {
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 156, .width = 1, .value = 1, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
vcap_test_api_init(&admin);
@@ -671,7 +674,7 @@ static void vcap_api_encode_max_keyfield_test(struct kunit *test)
struct vcap_typegroup tgt[] = {
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 156, .width = 1, .value = 1, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
u32 keyres[] = {
0x928e8a84,
@@ -732,7 +735,7 @@ static void vcap_api_encode_actionfield_test(struct kunit *test)
{ .offset = 0, .width = 2, .value = 2, },
{ .offset = 21, .width = 1, .value = 1, },
{ .offset = 42, .width = 1, .value = 0, },
- { .offset = 0, .width = 0, .value = 0, },
+ { }
};
vcap_encode_actionfield(&rule, &caf, &rf, tgt);
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index ca4ed58f1206..e97af7ac2bb2 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright (c) 2021, Microsoft Corporation. */
+#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/utsname.h>
@@ -8,6 +9,8 @@
#include <net/mana/mana.h>
+struct dentry *mana_debugfs_root;
+
static u32 mana_gd_r32(struct gdma_context *g, u64 offset)
{
return readl(g->bar0_va + offset);
@@ -1516,6 +1519,12 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
gc->bar0_va = bar0_va;
gc->dev = &pdev->dev;
+ if (gc->is_pf)
+ gc->mana_pci_debugfs = debugfs_create_dir("0", mana_debugfs_root);
+ else
+ gc->mana_pci_debugfs = debugfs_create_dir(pci_slot_name(pdev->slot),
+ mana_debugfs_root);
+
err = mana_gd_setup(pdev);
if (err)
goto unmap_bar;
@@ -1529,6 +1538,13 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
cleanup_gd:
mana_gd_cleanup(pdev);
unmap_bar:
+ /*
+ * at this point we know that the other debugfs child dir/files
+ * are either not yet created or are already cleaned up.
+ * The pci debugfs folder clean-up now, will only be cleaning up
+ * adapter-MTU file and apc->mana_pci_debugfs folder.
+ */
+ debugfs_remove_recursive(gc->mana_pci_debugfs);
pci_iounmap(pdev, bar0_va);
free_gc:
pci_set_drvdata(pdev, NULL);
@@ -1549,6 +1565,8 @@ static void mana_gd_remove(struct pci_dev *pdev)
mana_gd_cleanup(pdev);
+ debugfs_remove_recursive(gc->mana_pci_debugfs);
+
pci_iounmap(pdev, gc->bar0_va);
vfree(gc);
@@ -1600,6 +1618,8 @@ static void mana_gd_shutdown(struct pci_dev *pdev)
mana_gd_cleanup(pdev);
+ debugfs_remove_recursive(gc->mana_pci_debugfs);
+
pci_disable_device(pdev);
}
@@ -1619,7 +1639,28 @@ static struct pci_driver mana_driver = {
.shutdown = mana_gd_shutdown,
};
-module_pci_driver(mana_driver);
+static int __init mana_driver_init(void)
+{
+ int err;
+
+ mana_debugfs_root = debugfs_create_dir("mana", NULL);
+
+ err = pci_register_driver(&mana_driver);
+ if (err)
+ debugfs_remove(mana_debugfs_root);
+
+ return err;
+}
+
+static void __exit mana_driver_exit(void)
+{
+ debugfs_remove(mana_debugfs_root);
+
+ pci_unregister_driver(&mana_driver);
+}
+
+module_init(mana_driver_init);
+module_exit(mana_driver_exit);
MODULE_DEVICE_TABLE(pci, mana_id_table);
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index c47266d1c7c2..57ac732e7707 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3,6 +3,7 @@
#include <uapi/linux/bpf.h>
+#include <linux/debugfs.h>
#include <linux/inetdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -30,6 +31,21 @@ static void mana_adev_idx_free(int idx)
ida_free(&mana_adev_ida, idx);
}
+static ssize_t mana_dbg_q_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *pos)
+{
+ struct gdma_queue *gdma_q = filp->private_data;
+
+ return simple_read_from_buffer(buf, count, pos, gdma_q->queue_mem_ptr,
+ gdma_q->queue_size);
+}
+
+static const struct file_operations mana_dbg_q_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = mana_dbg_q_read,
+};
+
/* Microsoft Azure Network Adapter (MANA) functions */
static int mana_open(struct net_device *ndev)
@@ -721,6 +737,13 @@ static const struct net_device_ops mana_devops = {
static void mana_cleanup_port_context(struct mana_port_context *apc)
{
+ /*
+ * at this point all dir/files under the vport directory
+ * are already cleaned up.
+ * We are sure the apc->mana_port_debugfs remove will not
+ * cause any freed memory access issues
+ */
+ debugfs_remove(apc->mana_port_debugfs);
kfree(apc->rxqs);
apc->rxqs = NULL;
}
@@ -943,6 +966,8 @@ static int mana_query_device_cfg(struct mana_context *ac, u32 proto_major_ver,
else
gc->adapter_mtu = ETH_FRAME_LEN;
+ debugfs_create_u16("adapter-MTU", 0400, gc->mana_pci_debugfs, &gc->adapter_mtu);
+
return 0;
}
@@ -1228,6 +1253,8 @@ static void mana_destroy_eq(struct mana_context *ac)
if (!ac->eqs)
return;
+ debugfs_remove_recursive(ac->mana_eqs_debugfs);
+
for (i = 0; i < gc->max_num_queues; i++) {
eq = ac->eqs[i].eq;
if (!eq)
@@ -1240,6 +1267,18 @@ static void mana_destroy_eq(struct mana_context *ac)
ac->eqs = NULL;
}
+static void mana_create_eq_debugfs(struct mana_context *ac, int i)
+{
+ struct mana_eq eq = ac->eqs[i];
+ char eqnum[32];
+
+ sprintf(eqnum, "eq%d", i);
+ eq.mana_eq_debugfs = debugfs_create_dir(eqnum, ac->mana_eqs_debugfs);
+ debugfs_create_u32("head", 0400, eq.mana_eq_debugfs, &eq.eq->head);
+ debugfs_create_u32("tail", 0400, eq.mana_eq_debugfs, &eq.eq->tail);
+ debugfs_create_file("eq_dump", 0400, eq.mana_eq_debugfs, eq.eq, &mana_dbg_q_fops);
+}
+
static int mana_create_eq(struct mana_context *ac)
{
struct gdma_dev *gd = ac->gdma_dev;
@@ -1260,11 +1299,14 @@ static int mana_create_eq(struct mana_context *ac)
spec.eq.context = ac->eqs;
spec.eq.log2_throttle_limit = LOG2_EQ_THROTTLE;
+ ac->mana_eqs_debugfs = debugfs_create_dir("EQs", gc->mana_pci_debugfs);
+
for (i = 0; i < gc->max_num_queues; i++) {
spec.eq.msix_index = (i + 1) % gc->num_msix_usable;
err = mana_gd_create_mana_eq(gd, &spec, &ac->eqs[i].eq);
if (err)
goto out;
+ mana_create_eq_debugfs(ac, i);
}
return 0;
@@ -1871,6 +1913,8 @@ static void mana_destroy_txq(struct mana_port_context *apc)
return;
for (i = 0; i < apc->num_queues; i++) {
+ debugfs_remove_recursive(apc->tx_qp[i].mana_tx_debugfs);
+
napi = &apc->tx_qp[i].tx_cq.napi;
if (apc->tx_qp[i].txq.napi_initialized) {
napi_synchronize(napi);
@@ -1889,6 +1933,31 @@ static void mana_destroy_txq(struct mana_port_context *apc)
apc->tx_qp = NULL;
}
+static void mana_create_txq_debugfs(struct mana_port_context *apc, int idx)
+{
+ struct mana_tx_qp *tx_qp = &apc->tx_qp[idx];
+ char qnum[32];
+
+ sprintf(qnum, "TX-%d", idx);
+ tx_qp->mana_tx_debugfs = debugfs_create_dir(qnum, apc->mana_port_debugfs);
+ debugfs_create_u32("sq_head", 0400, tx_qp->mana_tx_debugfs,
+ &tx_qp->txq.gdma_sq->head);
+ debugfs_create_u32("sq_tail", 0400, tx_qp->mana_tx_debugfs,
+ &tx_qp->txq.gdma_sq->tail);
+ debugfs_create_u32("sq_pend_skb_qlen", 0400, tx_qp->mana_tx_debugfs,
+ &tx_qp->txq.pending_skbs.qlen);
+ debugfs_create_u32("cq_head", 0400, tx_qp->mana_tx_debugfs,
+ &tx_qp->tx_cq.gdma_cq->head);
+ debugfs_create_u32("cq_tail", 0400, tx_qp->mana_tx_debugfs,
+ &tx_qp->tx_cq.gdma_cq->tail);
+ debugfs_create_u32("cq_budget", 0400, tx_qp->mana_tx_debugfs,
+ &tx_qp->tx_cq.budget);
+ debugfs_create_file("txq_dump", 0400, tx_qp->mana_tx_debugfs,
+ tx_qp->txq.gdma_sq, &mana_dbg_q_fops);
+ debugfs_create_file("cq_dump", 0400, tx_qp->mana_tx_debugfs,
+ tx_qp->tx_cq.gdma_cq, &mana_dbg_q_fops);
+}
+
static int mana_create_txq(struct mana_port_context *apc,
struct net_device *net)
{
@@ -2000,6 +2069,8 @@ static int mana_create_txq(struct mana_port_context *apc,
gc->cq_table[cq->gdma_id] = cq->gdma_cq;
+ mana_create_txq_debugfs(apc, i);
+
netif_napi_add_tx(net, &cq->napi, mana_poll);
napi_enable(&cq->napi);
txq->napi_initialized = true;
@@ -2027,6 +2098,8 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
if (!rxq)
return;
+ debugfs_remove_recursive(rxq->mana_rx_debugfs);
+
napi = &rxq->rx_cq.napi;
if (napi_initialized) {
@@ -2308,6 +2381,28 @@ out:
return NULL;
}
+static void mana_create_rxq_debugfs(struct mana_port_context *apc, int idx)
+{
+ struct mana_rxq *rxq;
+ char qnum[32];
+
+ rxq = apc->rxqs[idx];
+
+ sprintf(qnum, "RX-%d", idx);
+ rxq->mana_rx_debugfs = debugfs_create_dir(qnum, apc->mana_port_debugfs);
+ debugfs_create_u32("rq_head", 0400, rxq->mana_rx_debugfs, &rxq->gdma_rq->head);
+ debugfs_create_u32("rq_tail", 0400, rxq->mana_rx_debugfs, &rxq->gdma_rq->tail);
+ debugfs_create_u32("rq_nbuf", 0400, rxq->mana_rx_debugfs, &rxq->num_rx_buf);
+ debugfs_create_u32("cq_head", 0400, rxq->mana_rx_debugfs,
+ &rxq->rx_cq.gdma_cq->head);
+ debugfs_create_u32("cq_tail", 0400, rxq->mana_rx_debugfs,
+ &rxq->rx_cq.gdma_cq->tail);
+ debugfs_create_u32("cq_budget", 0400, rxq->mana_rx_debugfs, &rxq->rx_cq.budget);
+ debugfs_create_file("rxq_dump", 0400, rxq->mana_rx_debugfs, rxq->gdma_rq, &mana_dbg_q_fops);
+ debugfs_create_file("cq_dump", 0400, rxq->mana_rx_debugfs, rxq->rx_cq.gdma_cq,
+ &mana_dbg_q_fops);
+}
+
static int mana_add_rx_queues(struct mana_port_context *apc,
struct net_device *ndev)
{
@@ -2326,6 +2421,8 @@ static int mana_add_rx_queues(struct mana_port_context *apc,
u64_stats_init(&rxq->stats.syncp);
apc->rxqs[i] = rxq;
+
+ mana_create_rxq_debugfs(apc, i);
}
apc->default_rxobj = apc->rxqs[0]->rxobj;
@@ -2518,14 +2615,19 @@ void mana_query_gf_stats(struct mana_port_context *apc)
static int mana_init_port(struct net_device *ndev)
{
struct mana_port_context *apc = netdev_priv(ndev);
+ struct gdma_dev *gd = apc->ac->gdma_dev;
u32 max_txq, max_rxq, max_queues;
int port_idx = apc->port_idx;
+ struct gdma_context *gc;
+ char vport[32];
int err;
err = mana_init_port_context(apc);
if (err)
return err;
+ gc = gd->gdma_context;
+
err = mana_query_vport_cfg(apc, port_idx, &max_txq, &max_rxq,
&apc->indir_table_sz);
if (err) {
@@ -2542,7 +2644,8 @@ static int mana_init_port(struct net_device *ndev)
apc->num_queues = apc->max_queues;
eth_hw_addr_set(ndev, apc->mac_addr);
-
+ sprintf(vport, "vport%d", port_idx);
+ apc->mana_port_debugfs = debugfs_create_dir(vport, gc->mana_pci_debugfs);
return 0;
reset_apc:
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index dc3864377538..c419626073f5 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -91,53 +91,34 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct mana_port_context *apc = netdev_priv(ndev);
unsigned int num_queues = apc->num_queues;
- u8 *p = data;
int i;
if (stringset != ETH_SS_STATS)
return;
- for (i = 0; i < ARRAY_SIZE(mana_eth_stats); i++) {
- memcpy(p, mana_eth_stats[i].name, ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < ARRAY_SIZE(mana_eth_stats); i++)
+ ethtool_puts(&data, mana_eth_stats[i].name);
for (i = 0; i < num_queues; i++) {
- sprintf(p, "rx_%d_packets", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "rx_%d_bytes", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "rx_%d_xdp_drop", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "rx_%d_xdp_tx", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "rx_%d_xdp_redirect", i);
- p += ETH_GSTRING_LEN;
+ ethtool_sprintf(&data, "rx_%d_packets", i);
+ ethtool_sprintf(&data, "rx_%d_bytes", i);
+ ethtool_sprintf(&data, "rx_%d_xdp_drop", i);
+ ethtool_sprintf(&data, "rx_%d_xdp_tx", i);
+ ethtool_sprintf(&data, "rx_%d_xdp_redirect", i);
}
for (i = 0; i < num_queues; i++) {
- sprintf(p, "tx_%d_packets", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_bytes", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_xdp_xmit", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_tso_packets", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_tso_bytes", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_tso_inner_packets", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_tso_inner_bytes", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_long_pkt_fmt", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_short_pkt_fmt", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_csum_partial", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "tx_%d_mana_map_err", i);
- p += ETH_GSTRING_LEN;
+ ethtool_sprintf(&data, "tx_%d_packets", i);
+ ethtool_sprintf(&data, "tx_%d_bytes", i);
+ ethtool_sprintf(&data, "tx_%d_xdp_xmit", i);
+ ethtool_sprintf(&data, "tx_%d_tso_packets", i);
+ ethtool_sprintf(&data, "tx_%d_tso_bytes", i);
+ ethtool_sprintf(&data, "tx_%d_tso_inner_packets", i);
+ ethtool_sprintf(&data, "tx_%d_tso_inner_bytes", i);
+ ethtool_sprintf(&data, "tx_%d_long_pkt_fmt", i);
+ ethtool_sprintf(&data, "tx_%d_short_pkt_fmt", i);
+ ethtool_sprintf(&data, "tx_%d_csum_partial", i);
+ ethtool_sprintf(&data, "tx_%d_mana_map_err", i);
}
}
@@ -443,6 +424,15 @@ out:
return err;
}
+static int mana_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *cmd)
+{
+ cmd->base.duplex = DUPLEX_FULL;
+ cmd->base.port = PORT_OTHER;
+
+ return 0;
+}
+
const struct ethtool_ops mana_ethtool_ops = {
.get_ethtool_stats = mana_get_ethtool_stats,
.get_sset_count = mana_get_sset_count,
@@ -456,4 +446,6 @@ const struct ethtool_ops mana_ethtool_ops = {
.set_channels = mana_set_channels,
.get_ringparam = mana_get_ringparam,
.set_ringparam = mana_set_ringparam,
+ .get_link_ksettings = mana_get_link_ksettings,
+ .get_link = ethtool_op_get_link,
};
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 96dc69e7141f..8bd60168624a 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -576,7 +576,7 @@ MODULE_DEVICE_TABLE(of, moxart_mac_match);
static struct platform_driver moxart_mac_driver = {
.probe = moxart_mac_probe,
- .remove_new = moxart_remove,
+ .remove = moxart_remove,
.driver = {
.name = "moxart-ethernet",
.of_match_table = moxart_mac_match,
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index a057ec3dab97..986b1f150e3b 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -228,6 +228,32 @@ ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
return 0;
}
+static int
+ocelot_flower_parse_egress_port(struct ocelot *ocelot, struct flow_cls_offload *f,
+ const struct flow_action_entry *a, bool mirror,
+ struct netlink_ext_ack *extack)
+{
+ const char *act_string = mirror ? "mirror" : "redirect";
+ int egress_port = ocelot->ops->netdev_to_port(a->dev);
+ enum flow_action_id offloadable_act_id;
+
+ offloadable_act_id = mirror ? FLOW_ACTION_MIRRED : FLOW_ACTION_REDIRECT;
+
+ /* Mirroring towards foreign interfaces is handled in software */
+ if (egress_port < 0 || a->id != offloadable_act_id) {
+ if (f->common.skip_sw) {
+ NL_SET_ERR_MSG_FMT(extack,
+ "Can only %s to %s if filter also runs in software",
+ act_string, egress_port < 0 ?
+ "CPU" : "ingress of ocelot port");
+ return -EOPNOTSUPP;
+ }
+ egress_port = ocelot->num_phys_ports;
+ }
+
+ return egress_port;
+}
+
static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
bool ingress, struct flow_cls_offload *f,
struct ocelot_vcap_filter *filter)
@@ -356,6 +382,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
break;
case FLOW_ACTION_REDIRECT:
+ case FLOW_ACTION_REDIRECT_INGRESS:
if (filter->block_id != VCAP_IS2) {
NL_SET_ERR_MSG_MOD(extack,
"Redirect action can only be offloaded to VCAP IS2");
@@ -366,17 +393,19 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
"Last action must be GOTO");
return -EOPNOTSUPP;
}
- egress_port = ocelot->ops->netdev_to_port(a->dev);
- if (egress_port < 0) {
- NL_SET_ERR_MSG_MOD(extack,
- "Destination not an ocelot port");
- return -EOPNOTSUPP;
- }
+
+ egress_port = ocelot_flower_parse_egress_port(ocelot, f,
+ a, false,
+ extack);
+ if (egress_port < 0)
+ return egress_port;
+
filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
filter->action.port_mask = BIT(egress_port);
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
break;
case FLOW_ACTION_MIRRED:
+ case FLOW_ACTION_MIRRED_INGRESS:
if (filter->block_id != VCAP_IS2) {
NL_SET_ERR_MSG_MOD(extack,
"Mirror action can only be offloaded to VCAP IS2");
@@ -387,12 +416,13 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
"Last action must be GOTO");
return -EOPNOTSUPP;
}
- egress_port = ocelot->ops->netdev_to_port(a->dev);
- if (egress_port < 0) {
- NL_SET_ERR_MSG_MOD(extack,
- "Destination not an ocelot port");
- return -EOPNOTSUPP;
- }
+
+ egress_port = ocelot_flower_parse_egress_port(ocelot, f,
+ a, true,
+ extack);
+ if (egress_port < 0)
+ return egress_port;
+
filter->egress_port.value = egress_port;
filter->action.mirror_ena = true;
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 7c9540a71725..558e03301aa8 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -730,7 +730,7 @@ static void ocelot_get_stats64(struct net_device *dev,
static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr,
- u16 vid, u16 flags,
+ u16 vid, u16 flags, bool *notified,
struct netlink_ext_ack *extack)
{
struct ocelot_port_private *priv = netdev_priv(dev);
@@ -744,7 +744,7 @@ static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
static int ocelot_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- struct netlink_ext_ack *extack)
+ bool *notified, struct netlink_ext_ack *extack)
{
struct ocelot_port_private *priv = netdev_priv(dev);
struct ocelot_port *ocelot_port = &priv->port;
diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
index c09dd2e3343c..055b55651a49 100644
--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
@@ -416,7 +416,7 @@ static void mscc_ocelot_remove(struct platform_device *pdev)
static struct platform_driver mscc_ocelot_driver = {
.probe = mscc_ocelot_probe,
- .remove_new = mscc_ocelot_remove,
+ .remove = mscc_ocelot_remove,
.driver = {
.name = "ocelot-switch",
.of_match_table = mscc_ocelot_match,
diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
index 2b6e097df28f..6d29d2e1fa7c 100644
--- a/drivers/net/ethernet/natsemi/jazzsonic.c
+++ b/drivers/net/ethernet/natsemi/jazzsonic.c
@@ -241,7 +241,7 @@ static void jazz_sonic_device_remove(struct platform_device *pdev)
static struct platform_driver jazz_sonic_driver = {
.probe = jazz_sonic_probe,
- .remove_new = jazz_sonic_device_remove,
+ .remove = jazz_sonic_device_remove,
.driver = {
.name = jazz_sonic_string,
},
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index 2fc63860dbdb..a740e24a9759 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -545,7 +545,7 @@ static void mac_sonic_platform_remove(struct platform_device *pdev)
static struct platform_driver mac_sonic_platform_driver = {
.probe = mac_sonic_platform_probe,
- .remove_new = mac_sonic_platform_remove,
+ .remove = mac_sonic_platform_remove,
.driver = {
.name = "macsonic",
},
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index 998586872599..bea969dfa536 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -2090,7 +2090,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
*/
/* Ramit : 1024 DMA is not a good idea, it ends up banging
* some DELL and COMPAQ SMP systems
- * Turn on ALP, only we are accpeting Jumbo Packets */
+ * Turn on ALP, only we are accepting Jumbo Packets */
writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD
| RXCFG_STRIPCRC
//| RXCFG_ALP
diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c
index 8943e7244310..c01a4cb5dc0f 100644
--- a/drivers/net/ethernet/natsemi/xtsonic.c
+++ b/drivers/net/ethernet/natsemi/xtsonic.c
@@ -264,7 +264,7 @@ static void xtsonic_device_remove(struct platform_device *pdev)
static struct platform_driver xtsonic_driver = {
.probe = xtsonic_probe,
- .remove_new = xtsonic_device_remove,
+ .remove = xtsonic_device_remove,
.driver = {
.name = xtsonic_string,
},
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index f235e76e4ce9..f8016dc25e0a 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -8523,7 +8523,7 @@ static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot.
- * At this point, the card has exprienced a hard reset,
+ * At this point, the card has experienced a hard reset,
* followed by fixups by BIOS, and has its config space
* set up identically to what it was at cold boot.
*/
diff --git a/drivers/net/ethernet/netronome/nfp/nfd3/dp.c b/drivers/net/ethernet/netronome/nfp/nfd3/dp.c
index d215efc6cad0..f1c6c47564b1 100644
--- a/drivers/net/ethernet/netronome/nfp/nfd3/dp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfd3/dp.c
@@ -1179,7 +1179,7 @@ int nfp_nfd3_poll(struct napi_struct *napi, int budget)
} while (u64_stats_fetch_retry(&r_vec->rx_sync, start));
dim_update_sample(r_vec->event_ctr, pkts, bytes, &dim_sample);
- net_dim(&r_vec->rx_dim, dim_sample);
+ net_dim(&r_vec->rx_dim, &dim_sample);
}
if (r_vec->nfp_net->tx_coalesce_adapt_on && r_vec->tx_ring) {
@@ -1194,7 +1194,7 @@ int nfp_nfd3_poll(struct napi_struct *napi, int budget)
} while (u64_stats_fetch_retry(&r_vec->tx_sync, start));
dim_update_sample(r_vec->event_ctr, pkts, bytes, &dim_sample);
- net_dim(&r_vec->tx_dim, dim_sample);
+ net_dim(&r_vec->tx_dim, &dim_sample);
}
return pkts_polled;
diff --git a/drivers/net/ethernet/netronome/nfp/nfdk/dp.c b/drivers/net/ethernet/netronome/nfp/nfdk/dp.c
index dae5af7d1845..ebeb6ab4465c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfdk/dp.c
+++ b/drivers/net/ethernet/netronome/nfp/nfdk/dp.c
@@ -1289,7 +1289,7 @@ int nfp_nfdk_poll(struct napi_struct *napi, int budget)
} while (u64_stats_fetch_retry(&r_vec->rx_sync, start));
dim_update_sample(r_vec->event_ctr, pkts, bytes, &dim_sample);
- net_dim(&r_vec->rx_dim, dim_sample);
+ net_dim(&r_vec->rx_dim, &dim_sample);
}
if (r_vec->nfp_net->tx_coalesce_adapt_on && r_vec->tx_ring) {
@@ -1304,7 +1304,7 @@ int nfp_nfdk_poll(struct napi_struct *napi, int budget)
} while (u64_stats_fetch_retry(&r_vec->tx_sync, start));
dim_update_sample(r_vec->event_ctr, pkts, bytes, &dim_sample);
- net_dim(&r_vec->tx_dim, dim_sample);
+ net_dim(&r_vec->tx_dim, &dim_sample);
}
return pkts_polled;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 6e0929af0f72..98e098c09c03 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -829,7 +829,7 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
return err;
}
- irq_set_affinity_hint(r_vec->irq_vector, &r_vec->affinity_mask);
+ irq_update_affinity_hint(r_vec->irq_vector, &r_vec->affinity_mask);
nn_dbg(nn, "RV%02d: irq=%03d/%03d\n", idx, r_vec->irq_vector,
r_vec->irq_entry);
@@ -840,7 +840,7 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
static void
nfp_net_cleanup_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec)
{
- irq_set_affinity_hint(r_vec->irq_vector, NULL);
+ irq_update_affinity_hint(r_vec->irq_vector, NULL);
nfp_net_napi_del(&nn->dp, r_vec);
free_irq(r_vec->irq_vector, r_vec);
}
diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c
index 2aa4ad9cf96e..230d5ff99dd7 100644
--- a/drivers/net/ethernet/ni/nixge.c
+++ b/drivers/net/ethernet/ni/nixge.c
@@ -1415,7 +1415,7 @@ static void nixge_remove(struct platform_device *pdev)
static struct platform_driver nixge_driver = {
.probe = nixge_probe,
- .remove_new = nixge_remove,
+ .remove = nixge_remove,
.driver = {
.name = "nixge",
.of_match_table = nixge_dt_ids,
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index dd3e58a1319c..8b9a3e3bba30 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -1503,7 +1503,7 @@ MODULE_DEVICE_TABLE(of, lpc_eth_match);
static struct platform_driver lpc_eth_driver = {
.probe = lpc_eth_drv_probe,
- .remove_new = lpc_eth_drv_remove,
+ .remove = lpc_eth_drv_remove,
#ifdef CONFIG_PM
.suspend = lpc_eth_drv_suspend,
.resume = lpc_eth_drv_resume,
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
index b93791d6b593..f5dc876eb500 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -394,6 +394,7 @@ err_out_free_irqs:
err_out_pci:
ionic_dev_teardown(ionic);
ionic_clear_pci(ionic);
+ ionic_debugfs_del_dev(ionic);
err_out:
mutex_destroy(&ionic->dev_cmd_lock);
ionic_devlink_free(ionic);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
index 0eeda7e502db..2ac59564ded1 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
@@ -928,7 +928,7 @@ static void ionic_dim_update(struct ionic_qcq *qcq, int napi_mode)
dim_update_sample(qcq->cq.bound_intr->rearm_count,
pkts, bytes, &dim_sample);
- net_dim(&qcq->dim, dim_sample);
+ net_dim(&qcq->dim, &dim_sample);
}
int ionic_tx_napi(struct napi_struct *napi, int budget)
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index 8c4cb910e09b..e7d8999049e1 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -648,18 +648,18 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
static void
netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
- int index;
+ const char *str;
+ int i;
switch (stringset) {
case ETH_SS_TEST:
- memcpy(data, *netxen_nic_gstrings_test,
- NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
+ for (i = 0; i < NETXEN_NIC_TEST_LEN; i++)
+ ethtool_puts(&data, netxen_nic_gstrings_test[i]);
break;
case ETH_SS_STATS:
- for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
- memcpy(data + index * ETH_GSTRING_LEN,
- netxen_nic_gstrings_stats[index].stat_string,
- ETH_GSTRING_LEN);
+ for (i = 0; i < NETXEN_NIC_STATS_LEN; i++) {
+ str = netxen_nic_gstrings_stats[i].stat_string;
+ ethtool_puts(&data, str);
}
break;
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c
index f67be4b8ad43..464a72afb758 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c
@@ -2873,6 +2873,7 @@ static u32 qed_grc_dump_ctx_data(struct qed_hwfn *p_hwfn,
false,
SPLIT_TYPE_NONE, 0);
}
+ cond_resched();
}
return offset;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c
index 6263f847b6b9..9e5f0dbc8a07 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hw.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c
@@ -596,6 +596,7 @@ static int qed_dmae_operation_wait(struct qed_hwfn *p_hwfn)
barrier();
while (*p_hwfn->dmae_info.p_completion_word != DMAE_COMPLETION_VAL) {
udelay(DMAE_MIN_WAIT_TIME);
+ cond_resched();
if (++wait_cnt > wait_cnt_limit) {
DP_NOTICE(p_hwfn->cdev,
"Timed-out waiting for operation to complete. Completion word is 0x%08x expected 0x%08x.\n",
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 16e6bd466143..26a714bfad4e 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -459,12 +459,11 @@ static void qed_mcp_print_cpu_info(struct qed_hwfn *p_hwfn,
static int
_qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
- struct qed_mcp_mb_params *p_mb_params,
- u32 max_retries, u32 usecs)
+ struct qed_mcp_mb_params *p_mb_params)
{
- u32 cnt = 0, msecs = DIV_ROUND_UP(usecs, 1000);
struct qed_mcp_cmd_elem *p_cmd_elem;
u16 seq_num;
+ u32 cnt = 0;
int rc = 0;
/* Wait until the mailbox is non-occupied */
@@ -488,12 +487,13 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP))
- msleep(msecs);
+ usleep_range(QED_MCP_RESP_ITER_US,
+ QED_MCP_RESP_ITER_US * 2);
else
- udelay(usecs);
- } while (++cnt < max_retries);
+ udelay(QED_MCP_RESP_ITER_US);
+ } while (++cnt < QED_DRV_MB_MAX_RETRIES);
- if (cnt >= max_retries) {
+ if (cnt >= QED_DRV_MB_MAX_RETRIES) {
DP_NOTICE(p_hwfn,
"The MFW mailbox is occupied by an uncompleted command. Failed to send command 0x%08x [param 0x%08x].\n",
p_mb_params->cmd, p_mb_params->param);
@@ -520,9 +520,10 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
*/
if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP))
- msleep(msecs);
+ usleep_range(QED_MCP_RESP_ITER_US,
+ QED_MCP_RESP_ITER_US * 2);
else
- udelay(usecs);
+ udelay(QED_MCP_RESP_ITER_US);
spin_lock_bh(&p_hwfn->mcp_info->cmd_lock);
@@ -536,9 +537,9 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
goto err;
spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
- } while (++cnt < max_retries);
+ } while (++cnt < QED_DRV_MB_MAX_RETRIES);
- if (cnt >= max_retries) {
+ if (cnt >= QED_DRV_MB_MAX_RETRIES) {
DP_NOTICE(p_hwfn,
"The MFW failed to respond to command 0x%08x [param 0x%08x].\n",
p_mb_params->cmd, p_mb_params->param);
@@ -564,7 +565,8 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
"MFW mailbox: response 0x%08x param 0x%08x [after %d.%03d ms]\n",
p_mb_params->mcp_resp,
p_mb_params->mcp_param,
- (cnt * usecs) / 1000, (cnt * usecs) % 1000);
+ (cnt * QED_MCP_RESP_ITER_US) / 1000,
+ (cnt * QED_MCP_RESP_ITER_US) % 1000);
/* Clear the sequence number from the MFW response */
p_mb_params->mcp_resp &= FW_MSG_CODE_MASK;
@@ -581,8 +583,6 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
struct qed_mcp_mb_params *p_mb_params)
{
size_t union_data_size = sizeof(union drv_union_data);
- u32 max_retries = QED_DRV_MB_MAX_RETRIES;
- u32 usecs = QED_MCP_RESP_ITER_US;
/* MCP not initialized */
if (!qed_mcp_is_init(p_hwfn)) {
@@ -606,13 +606,7 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
return -EINVAL;
}
- if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) {
- max_retries = DIV_ROUND_UP(max_retries, 1000);
- usecs *= 1000;
- }
-
- return _qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries,
- usecs);
+ return _qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params);
}
static int _qed_mcp_cmd(struct qed_hwfn *p_hwfn,
@@ -3085,20 +3079,13 @@ int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len)
DRV_MB_PARAM_NVM_LEN_OFFSET),
&resp, &resp_param,
&read_len,
- (u32 *)(p_buf + offset), false);
+ (u32 *)(p_buf + offset), true);
if (rc || (resp != FW_MSG_CODE_NVM_OK)) {
DP_NOTICE(cdev, "MCP command rc = %d\n", rc);
break;
}
- /* This can be a lengthy process, and it's possible scheduler
- * isn't preemptible. Sleep a bit to prevent CPU hogging.
- */
- if (bytes_left % 0x1000 <
- (bytes_left - read_len) % 0x1000)
- usleep_range(1000, 2000);
-
offset += read_len;
bytes_left -= read_len;
}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 97b059be1041..e50e1df0a433 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -272,16 +272,14 @@ static void qede_get_strings_stats_txq(struct qede_dev *edev,
{
int i;
- for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
+ for (i = 0; i < QEDE_NUM_TQSTATS; i++)
if (txq->is_xdp)
- sprintf(*buf, "%d [XDP]: %s",
- QEDE_TXQ_XDP_TO_IDX(edev, txq),
- qede_tqstats_arr[i].string);
+ ethtool_sprintf(buf, "%d [XDP]: %s",
+ QEDE_TXQ_XDP_TO_IDX(edev, txq),
+ qede_tqstats_arr[i].string);
else
- sprintf(*buf, "%d_%d: %s", txq->index, txq->cos,
- qede_tqstats_arr[i].string);
- *buf += ETH_GSTRING_LEN;
- }
+ ethtool_sprintf(buf, "%d_%d: %s", txq->index, txq->cos,
+ qede_tqstats_arr[i].string);
}
static void qede_get_strings_stats_rxq(struct qede_dev *edev,
@@ -289,11 +287,9 @@ static void qede_get_strings_stats_rxq(struct qede_dev *edev,
{
int i;
- for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
- sprintf(*buf, "%d: %s", rxq->rxq_id,
- qede_rqstats_arr[i].string);
- *buf += ETH_GSTRING_LEN;
- }
+ for (i = 0; i < QEDE_NUM_RQSTATS; i++)
+ ethtool_sprintf(buf, "%d: %s", rxq->rxq_id,
+ qede_rqstats_arr[i].string);
}
static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index)
@@ -331,26 +327,26 @@ static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
for (i = 0; i < QEDE_NUM_STATS; i++) {
if (qede_is_irrelevant_stat(edev, i))
continue;
- strcpy(buf, qede_stats_arr[i].string);
- buf += ETH_GSTRING_LEN;
+ ethtool_puts(&buf, qede_stats_arr[i].string);
}
}
static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
{
struct qede_dev *edev = netdev_priv(dev);
+ int i;
switch (stringset) {
case ETH_SS_STATS:
qede_get_strings_stats(edev, buf);
break;
case ETH_SS_PRIV_FLAGS:
- memcpy(buf, qede_private_arr,
- ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN);
+ for (i = 0; i < QEDE_PRI_FLAG_LEN; i++)
+ ethtool_puts(&buf, qede_private_arr[i]);
break;
case ETH_SS_TEST:
- memcpy(buf, qede_tests_str_arr,
- ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX);
+ for (i = 0; i < QEDE_ETHTOOL_TEST_MAX; i++)
+ ethtool_puts(&buf, qede_tests_str_arr[i]);
break;
default:
DP_VERBOSE(edev, QED_MSG_DEBUG,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index c1436e1554de..17450e05c437 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1196,60 +1196,56 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
int index, i, num_stats;
+ const char *str;
switch (stringset) {
case ETH_SS_TEST:
- memcpy(data, *qlcnic_gstrings_test,
- QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
+ for (i = 0; i < QLCNIC_TEST_LEN; i++)
+ ethtool_puts(&data, qlcnic_gstrings_test[i]);
break;
case ETH_SS_STATS:
num_stats = ARRAY_SIZE(qlcnic_tx_queue_stats_strings);
- for (i = 0; i < adapter->drv_tx_rings; i++) {
+ for (i = 0; i < adapter->drv_tx_rings; i++)
for (index = 0; index < num_stats; index++) {
- sprintf(data, "tx_queue_%d %s", i,
- qlcnic_tx_queue_stats_strings[index]);
- data += ETH_GSTRING_LEN;
+ str = qlcnic_tx_queue_stats_strings[index];
+ ethtool_sprintf(&data, "tx_queue_%d %s", i,
+ str);
}
- }
- for (index = 0; index < QLCNIC_STATS_LEN; index++) {
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_gstrings_stats[index].stat_string,
- ETH_GSTRING_LEN);
+ for (i = 0; i < QLCNIC_STATS_LEN; i++) {
+ str = qlcnic_gstrings_stats[i].stat_string;
+ ethtool_puts(&data, str);
}
if (qlcnic_83xx_check(adapter)) {
num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
- for (i = 0; i < num_stats; i++, index++)
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_83xx_tx_stats_strings[i],
- ETH_GSTRING_LEN);
+ for (i = 0; i < num_stats; i++) {
+ str = qlcnic_83xx_tx_stats_strings[i];
+ ethtool_puts(&data, str);
+ }
num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
- for (i = 0; i < num_stats; i++, index++)
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_83xx_mac_stats_strings[i],
- ETH_GSTRING_LEN);
+ for (i = 0; i < num_stats; i++) {
+ str = qlcnic_83xx_mac_stats_strings[i];
+ ethtool_puts(&data, str);
+ }
num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
- for (i = 0; i < num_stats; i++, index++)
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_83xx_rx_stats_strings[i],
- ETH_GSTRING_LEN);
+ for (i = 0; i < num_stats; i++) {
+ str = qlcnic_83xx_rx_stats_strings[i];
+ ethtool_puts(&data, str);
+ }
return;
} else {
num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
- for (i = 0; i < num_stats; i++, index++)
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_83xx_mac_stats_strings[i],
- ETH_GSTRING_LEN);
+ for (i = 0; i < num_stats; i++) {
+ str = qlcnic_83xx_mac_stats_strings[i];
+ ethtool_puts(&data, str);
+ }
}
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return;
num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats);
- for (i = 0; i < num_stats; index++, i++) {
- memcpy(data + index * ETH_GSTRING_LEN,
- qlcnic_device_gstrings_stats[i],
- ETH_GSTRING_LEN);
- }
+ for (i = 0; i < num_stats; i++)
+ ethtool_puts(&data, qlcnic_device_gstrings_stats[i]);
}
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index b3588a1ebc25..eb69121df726 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -367,7 +367,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *netdev,
- const unsigned char *addr, u16 vid,
+ const unsigned char *addr, u16 vid, bool *notified,
struct netlink_ext_ack *extack)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -394,7 +394,7 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *netdev,
const unsigned char *addr, u16 vid, u16 flags,
- struct netlink_ext_ack *extack)
+ bool *notified, struct netlink_ext_ack *extack)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int err = 0;
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
index e4bc18009d08..a508ebc4b206 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
@@ -293,6 +293,11 @@ static struct sgmii_ops qdf2400_ops = {
};
#endif
+struct emac_match_data {
+ struct sgmii_ops **sgmii_ops;
+ struct device *target_device;
+};
+
static int emac_sgmii_acpi_match(struct device *dev, void *data)
{
#ifdef CONFIG_ACPI
@@ -303,7 +308,7 @@ static int emac_sgmii_acpi_match(struct device *dev, void *data)
{}
};
const struct acpi_device_id *id = acpi_match_device(match_table, dev);
- struct sgmii_ops **ops = data;
+ struct emac_match_data *match_data = data;
if (id) {
acpi_handle handle = ACPI_HANDLE(dev);
@@ -324,10 +329,12 @@ static int emac_sgmii_acpi_match(struct device *dev, void *data)
switch (hrv) {
case 1:
- *ops = &qdf2432_ops;
+ *match_data->sgmii_ops = &qdf2432_ops;
+ match_data->target_device = dev;
return 1;
case 2:
- *ops = &qdf2400_ops;
+ *match_data->sgmii_ops = &qdf2400_ops;
+ match_data->target_device = dev;
return 1;
}
}
@@ -356,16 +363,21 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
int ret;
if (has_acpi_companion(&pdev->dev)) {
+ struct emac_match_data match_data = {
+ .sgmii_ops = &phy->sgmii_ops,
+ .target_device = NULL,
+ };
struct device *dev;
- dev = device_find_child(&pdev->dev, &phy->sgmii_ops,
- emac_sgmii_acpi_match);
+ device_for_each_child(&pdev->dev, &match_data, emac_sgmii_acpi_match);
+ dev = match_data.target_device;
if (!dev) {
dev_warn(&pdev->dev, "cannot find internal phy node\n");
return 0;
}
+ get_device(dev);
sgmii_pdev = to_platform_device(dev);
} else {
const struct of_device_id *match;
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 99d4647bf245..699a8afc214a 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -760,7 +760,7 @@ static void emac_shutdown(struct platform_device *pdev)
static struct platform_driver emac_platform_driver = {
.probe = emac_probe,
- .remove_new = emac_remove,
+ .remove = emac_remove,
.driver = {
.name = "qcom-emac",
.of_match_table = emac_dt_match,
diff --git a/drivers/net/ethernet/qualcomm/qca_debug.c b/drivers/net/ethernet/qualcomm/qca_debug.c
index ad06da0fdaa0..13deb3da4a64 100644
--- a/drivers/net/ethernet/qualcomm/qca_debug.c
+++ b/drivers/net/ethernet/qualcomm/qca_debug.c
@@ -98,8 +98,8 @@ qcaspi_info_show(struct seq_file *s, void *what)
seq_printf(s, "IRQ : %d\n",
qca->spi_dev->irq);
- seq_printf(s, "INTR : %lx\n",
- qca->intr);
+ seq_printf(s, "FLAGS : %lx\n",
+ qca->flags);
seq_printf(s, "SPI max speed : %lu\n",
(unsigned long)qca->spi_dev->max_speed_hz);
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index 8f7ce6b51a1c..ef9c02b000e4 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -35,7 +35,8 @@
#define MAX_DMA_BURST_LEN 5000
-#define SPI_INTR 0
+#define SPI_INTR 0
+#define SPI_RESET 1
/* Modules parameters */
#define QCASPI_CLK_SPEED_MIN 1000000
@@ -495,7 +496,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
if (qca->sync == QCASPI_SYNC_READY)
qca->stats.bad_signature++;
- qca->sync = QCASPI_SYNC_UNKNOWN;
+ set_bit(SPI_RESET, &qca->flags);
netdev_dbg(qca->net_dev, "sync: got CPU on, but signature was invalid, restart\n");
return;
} else {
@@ -505,12 +506,17 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
if (wrbuf_space != QCASPI_HW_BUF_LEN) {
netdev_dbg(qca->net_dev, "sync: got CPU on, but wrbuf not empty. reset!\n");
qca->sync = QCASPI_SYNC_UNKNOWN;
+ qca->stats.buf_avail_err++;
} else {
netdev_dbg(qca->net_dev, "sync: got CPU on, now in sync\n");
qca->sync = QCASPI_SYNC_READY;
return;
}
}
+ } else {
+ /* Handle reset only on QCASPI_EVENT_UPDATE */
+ if (test_and_clear_bit(SPI_RESET, &qca->flags))
+ qca->sync = QCASPI_SYNC_UNKNOWN;
}
switch (qca->sync) {
@@ -521,7 +527,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
qcaspi_read_register(qca, SPI_REG_SIGNATURE, &signature);
if (signature != QCASPI_GOOD_SIGNATURE) {
- qca->sync = QCASPI_SYNC_UNKNOWN;
+ set_bit(SPI_RESET, &qca->flags);
qca->stats.bad_signature++;
netdev_dbg(qca->net_dev, "sync: bad signature, restart\n");
/* don't reset right away */
@@ -552,7 +558,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
qca->reset_count);
if (qca->reset_count >= QCASPI_RESET_TIMEOUT) {
/* reset did not seem to take place, try again */
- qca->sync = QCASPI_SYNC_UNKNOWN;
+ set_bit(SPI_RESET, &qca->flags);
qca->stats.reset_timeout++;
netdev_dbg(qca->net_dev, "sync: reset timeout, restarting process.\n");
}
@@ -581,14 +587,14 @@ qcaspi_spi_thread(void *data)
continue;
}
- if (!test_bit(SPI_INTR, &qca->intr) &&
+ if (!qca->flags &&
!qca->txr.skb[qca->txr.head])
schedule();
set_current_state(TASK_RUNNING);
netdev_dbg(qca->net_dev, "have work to do. int: %lu, tx_skb: %p\n",
- qca->intr,
+ qca->flags,
qca->txr.skb[qca->txr.head]);
qcaspi_qca7k_sync(qca, QCASPI_EVENT_UPDATE);
@@ -602,7 +608,7 @@ qcaspi_spi_thread(void *data)
msleep(QCASPI_QCA7K_REBOOT_TIME_MS);
}
- if (test_and_clear_bit(SPI_INTR, &qca->intr)) {
+ if (test_and_clear_bit(SPI_INTR, &qca->flags)) {
start_spi_intr_handling(qca, &intr_cause);
if (intr_cause & SPI_INT_CPU_ON) {
@@ -627,7 +633,7 @@ qcaspi_spi_thread(void *data)
/* restart sync */
netdev_dbg(qca->net_dev, "===> rdbuf error!\n");
qca->stats.read_buf_err++;
- qca->sync = QCASPI_SYNC_UNKNOWN;
+ set_bit(SPI_RESET, &qca->flags);
continue;
}
@@ -635,7 +641,7 @@ qcaspi_spi_thread(void *data)
/* restart sync */
netdev_dbg(qca->net_dev, "===> wrbuf error!\n");
qca->stats.write_buf_err++;
- qca->sync = QCASPI_SYNC_UNKNOWN;
+ set_bit(SPI_RESET, &qca->flags);
continue;
}
@@ -664,7 +670,7 @@ qcaspi_intr_handler(int irq, void *data)
{
struct qcaspi *qca = data;
- set_bit(SPI_INTR, &qca->intr);
+ set_bit(SPI_INTR, &qca->flags);
if (qca->spi_thread)
wake_up_process(qca->spi_thread);
@@ -680,7 +686,7 @@ qcaspi_netdev_open(struct net_device *dev)
if (!qca)
return -EINVAL;
- set_bit(SPI_INTR, &qca->intr);
+ set_bit(SPI_INTR, &qca->flags);
qca->sync = QCASPI_SYNC_UNKNOWN;
qcafrm_fsm_init_spi(&qca->frm_handle);
@@ -799,7 +805,7 @@ qcaspi_netdev_tx_timeout(struct net_device *dev, unsigned int txqueue)
jiffies, jiffies - dev_trans_start(dev));
qca->net_dev->stats.tx_errors++;
/* Trigger tx queue flush and QCA7000 reset */
- qca->sync = QCASPI_SYNC_UNKNOWN;
+ set_bit(SPI_RESET, &qca->flags);
if (qca->spi_thread)
wake_up_process(qca->spi_thread);
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.h b/drivers/net/ethernet/qualcomm/qca_spi.h
index 8f4808695e82..7ba5c9e2f61c 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.h
+++ b/drivers/net/ethernet/qualcomm/qca_spi.h
@@ -81,7 +81,7 @@ struct qcaspi {
struct qcafrm_handle frm_handle;
struct sk_buff *rx_skb;
- unsigned long intr;
+ unsigned long flags;
u16 reset_count;
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/net/ethernet/realtek/r8169.h b/drivers/net/ethernet/realtek/r8169.h
index e2db944e6fa8..be4c9622618d 100644
--- a/drivers/net/ethernet/realtek/r8169.h
+++ b/drivers/net/ethernet/realtek/r8169.h
@@ -68,6 +68,7 @@ enum mac_version {
/* support for RTL_GIGA_MAC_VER_60 has been removed */
RTL_GIGA_MAC_VER_61,
RTL_GIGA_MAC_VER_63,
+ RTL_GIGA_MAC_VER_64,
RTL_GIGA_MAC_VER_65,
RTL_GIGA_MAC_VER_66,
RTL_GIGA_MAC_NONE
diff --git a/drivers/net/ethernet/realtek/r8169_firmware.c b/drivers/net/ethernet/realtek/r8169_firmware.c
index ed6e721b1555..bf055078a855 100644
--- a/drivers/net/ethernet/realtek/r8169_firmware.c
+++ b/drivers/net/ethernet/realtek/r8169_firmware.c
@@ -215,7 +215,7 @@ int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
{
int rc;
- rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
+ rc = firmware_request_nowarn(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
if (rc < 0)
goto out;
@@ -227,7 +227,7 @@ int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
return 0;
out:
- dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
- rtl_fw->fw_name, rc);
+ dev_warn(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
+ rtl_fw->fw_name, rc);
return rc;
}
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 713a89bb21e9..739707a7b40f 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
+#include <linux/hwmon.h>
#include <linux/phy.h>
#include <linux/if_vlan.h>
#include <linux/in.h>
@@ -55,6 +56,7 @@
#define FIRMWARE_8107E_2 "rtl_nic/rtl8107e-2.fw"
#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw"
#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw"
+#define FIRMWARE_8125D_1 "rtl_nic/rtl8125d-1.fw"
#define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw"
#define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw"
@@ -138,6 +140,7 @@ static const struct {
[RTL_GIGA_MAC_VER_61] = {"RTL8125A", FIRMWARE_8125A_3},
/* reserve 62 for CFG_METHOD_4 in the vendor driver */
[RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2},
+ [RTL_GIGA_MAC_VER_64] = {"RTL8125D", FIRMWARE_8125D_1},
[RTL_GIGA_MAC_VER_65] = {"RTL8126A", FIRMWARE_8126A_2},
[RTL_GIGA_MAC_VER_66] = {"RTL8126A", FIRMWARE_8126A_3},
};
@@ -344,6 +347,8 @@ enum rtl8125_registers {
TxPoll_8125 = 0x90,
LEDSEL3 = 0x96,
MAC0_BKP = 0x19e0,
+ RSS_CTRL_8125 = 0x4500,
+ Q_NUM_CTRL_8125 = 0x4800,
EEE_TXIDLE_TIMER_8125 = 0x6048,
};
@@ -617,7 +622,6 @@ struct rtl8169_tc_offsets {
};
enum rtl_flag {
- RTL_FLAG_TASK_ENABLED = 0,
RTL_FLAG_TASK_RESET_PENDING,
RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE,
RTL_FLAG_TASK_TX_TIMEOUT,
@@ -658,13 +662,9 @@ struct rtl8169_private {
struct work_struct work;
} wk;
- raw_spinlock_t config25_lock;
raw_spinlock_t mac_ocp_lock;
struct mutex led_lock; /* serialize LED ctrl RMW access */
- raw_spinlock_t cfg9346_usage_lock;
- int cfg9346_usage_count;
-
unsigned supports_gmii:1;
unsigned aspm_manageable:1;
unsigned dash_enabled:1;
@@ -707,6 +707,7 @@ MODULE_FIRMWARE(FIRMWARE_8168FP_3);
MODULE_FIRMWARE(FIRMWARE_8107E_2);
MODULE_FIRMWARE(FIRMWARE_8125A_3);
MODULE_FIRMWARE(FIRMWARE_8125B_2);
+MODULE_FIRMWARE(FIRMWARE_8125D_1);
MODULE_FIRMWARE(FIRMWARE_8126A_2);
MODULE_FIRMWARE(FIRMWARE_8126A_3);
@@ -717,22 +718,12 @@ static inline struct device *tp_to_dev(struct rtl8169_private *tp)
static void rtl_lock_config_regs(struct rtl8169_private *tp)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
- if (!--tp->cfg9346_usage_count)
- RTL_W8(tp, Cfg9346, Cfg9346_Lock);
- raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
+ RTL_W8(tp, Cfg9346, Cfg9346_Lock);
}
static void rtl_unlock_config_regs(struct rtl8169_private *tp)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
- if (!tp->cfg9346_usage_count++)
- RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
- raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
+ RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
}
static void rtl_pci_commit(struct rtl8169_private *tp)
@@ -743,24 +734,32 @@ static void rtl_pci_commit(struct rtl8169_private *tp)
static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
{
- unsigned long flags;
u8 val;
- raw_spin_lock_irqsave(&tp->config25_lock, flags);
val = RTL_R8(tp, Config2);
RTL_W8(tp, Config2, (val & ~clear) | set);
- raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
}
static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
{
- unsigned long flags;
u8 val;
- raw_spin_lock_irqsave(&tp->config25_lock, flags);
val = RTL_R8(tp, Config5);
RTL_W8(tp, Config5, (val & ~clear) | set);
- raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
+}
+
+static void r8169_mod_reg8_cond(struct rtl8169_private *tp, int reg,
+ u8 bits, bool cond)
+{
+ u8 val, old_val;
+
+ old_val = RTL_R8(tp, reg);
+ if (cond)
+ val = old_val | bits;
+ else
+ val = old_val & ~bits;
+ if (val != old_val)
+ RTL_W8(tp, reg, val);
}
static bool rtl_is_8125(struct rtl8169_private *tp)
@@ -1346,40 +1345,19 @@ static void rtl8168ep_stop_cmac(struct rtl8169_private *tp)
RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01);
}
-static void rtl_dash_loop_wait(struct rtl8169_private *tp,
- const struct rtl_cond *c,
- unsigned long usecs, int n, bool high)
-{
- if (!tp->dash_enabled)
- return;
- rtl_loop_wait(tp, c, usecs, n, high);
-}
-
-static void rtl_dash_loop_wait_high(struct rtl8169_private *tp,
- const struct rtl_cond *c,
- unsigned long d, int n)
-{
- rtl_dash_loop_wait(tp, c, d, n, true);
-}
-
-static void rtl_dash_loop_wait_low(struct rtl8169_private *tp,
- const struct rtl_cond *c,
- unsigned long d, int n)
-{
- rtl_dash_loop_wait(tp, c, d, n, false);
-}
-
static void rtl8168dp_driver_start(struct rtl8169_private *tp)
{
r8168dp_oob_notify(tp, OOB_CMD_DRIVER_START);
- rtl_dash_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
+ if (tp->dash_enabled)
+ rtl_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
}
static void rtl8168ep_driver_start(struct rtl8169_private *tp)
{
r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
- rtl_dash_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30);
+ if (tp->dash_enabled)
+ rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30);
}
static void rtl8168_driver_start(struct rtl8169_private *tp)
@@ -1393,7 +1371,8 @@ static void rtl8168_driver_start(struct rtl8169_private *tp)
static void rtl8168dp_driver_stop(struct rtl8169_private *tp)
{
r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP);
- rtl_dash_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10);
+ if (tp->dash_enabled)
+ rtl_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10);
}
static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
@@ -1401,7 +1380,8 @@ static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
rtl8168ep_stop_cmac(tp);
r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
- rtl_dash_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
+ if (tp->dash_enabled)
+ rtl_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
}
static void rtl8168_driver_stop(struct rtl8169_private *tp)
@@ -1451,19 +1431,11 @@ static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp)
static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable)
{
- switch (tp->mac_version) {
- case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
- case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
- case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_37:
- case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66:
- if (enable)
- RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~D3_NO_PLL_DOWN);
- else
- RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | D3_NO_PLL_DOWN);
- break;
- default:
- break;
- }
+ if (tp->mac_version >= RTL_GIGA_MAC_VER_25 &&
+ tp->mac_version != RTL_GIGA_MAC_VER_28 &&
+ tp->mac_version != RTL_GIGA_MAC_VER_31 &&
+ tp->mac_version != RTL_GIGA_MAC_VER_38)
+ r8169_mod_reg8_cond(tp, PMCH, D3_NO_PLL_DOWN, !enable);
}
static void rtl_reset_packet_filter(struct rtl8169_private *tp)
@@ -1572,61 +1544,40 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
{
- static const struct {
- u32 opt;
- u16 reg;
- u8 mask;
- } cfg[] = {
- { WAKE_PHY, Config3, LinkUp },
- { WAKE_UCAST, Config5, UWF },
- { WAKE_BCAST, Config5, BWF },
- { WAKE_MCAST, Config5, MWF },
- { WAKE_ANY, Config5, LanWake },
- { WAKE_MAGIC, Config3, MagicPacket }
- };
- unsigned int i, tmp = ARRAY_SIZE(cfg);
- unsigned long flags;
- u8 options;
-
rtl_unlock_config_regs(tp);
if (rtl_is_8168evl_up(tp)) {
- tmp--;
if (wolopts & WAKE_MAGIC)
rtl_eri_set_bits(tp, 0x0dc, MagicPacket_v2);
else
rtl_eri_clear_bits(tp, 0x0dc, MagicPacket_v2);
} else if (rtl_is_8125(tp)) {
- tmp--;
if (wolopts & WAKE_MAGIC)
r8168_mac_ocp_modify(tp, 0xc0b6, 0, BIT(0));
else
r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
+ } else {
+ r8169_mod_reg8_cond(tp, Config3, MagicPacket,
+ wolopts & WAKE_MAGIC);
}
- raw_spin_lock_irqsave(&tp->config25_lock, flags);
- for (i = 0; i < tmp; i++) {
- options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
- if (wolopts & cfg[i].opt)
- options |= cfg[i].mask;
- RTL_W8(tp, cfg[i].reg, options);
- }
- raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
+ r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY);
+ if (rtl_is_8125(tp))
+ r8168_mac_ocp_modify(tp, 0xe0c6, 0x3f,
+ wolopts & WAKE_PHY ? 0x13 : 0);
+ r8169_mod_reg8_cond(tp, Config5, UWF, wolopts & WAKE_UCAST);
+ r8169_mod_reg8_cond(tp, Config5, BWF, wolopts & WAKE_BCAST);
+ r8169_mod_reg8_cond(tp, Config5, MWF, wolopts & WAKE_MCAST);
+ r8169_mod_reg8_cond(tp, Config5, LanWake, wolopts);
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
- options = RTL_R8(tp, Config1) & ~PMEnable;
- if (wolopts)
- options |= PMEnable;
- RTL_W8(tp, Config1, options);
+ r8169_mod_reg8_cond(tp, Config1, PMEnable, wolopts);
break;
case RTL_GIGA_MAC_VER_34:
case RTL_GIGA_MAC_VER_37:
case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66:
- if (wolopts)
- rtl_mod_config2(tp, 0, PME_SIGNAL);
- else
- rtl_mod_config2(tp, PME_SIGNAL, 0);
+ r8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts);
break;
default:
break;
@@ -2098,10 +2049,7 @@ static void rtl_set_eee_txidle_timer(struct rtl8169_private *tp)
tp->tx_lpi_timer = timer_val;
r8168_mac_ocp_write(tp, 0xe048, timer_val);
break;
- case RTL_GIGA_MAC_VER_61:
- case RTL_GIGA_MAC_VER_63:
- case RTL_GIGA_MAC_VER_65:
- case RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66:
tp->tx_lpi_timer = timer_val;
RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val);
break;
@@ -2160,6 +2108,19 @@ static void rtl8169_get_ringparam(struct net_device *dev,
data->tx_pending = NUM_TX_DESC;
}
+static void rtl8169_get_pause_stats(struct net_device *dev,
+ struct ethtool_pause_stats *pause_stats)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (!rtl_is_8125(tp))
+ return;
+
+ rtl8169_update_counters(tp);
+ pause_stats->tx_pause_frames = le32_to_cpu(tp->counters->tx_pause_on);
+ pause_stats->rx_pause_frames = le32_to_cpu(tp->counters->rx_pause_on);
+}
+
static void rtl8169_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *data)
{
@@ -2186,6 +2147,69 @@ static int rtl8169_set_pauseparam(struct net_device *dev,
return 0;
}
+static void rtl8169_get_eth_mac_stats(struct net_device *dev,
+ struct ethtool_eth_mac_stats *mac_stats)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ rtl8169_update_counters(tp);
+
+ mac_stats->FramesTransmittedOK =
+ le64_to_cpu(tp->counters->tx_packets);
+ mac_stats->SingleCollisionFrames =
+ le32_to_cpu(tp->counters->tx_one_collision);
+ mac_stats->MultipleCollisionFrames =
+ le32_to_cpu(tp->counters->tx_multi_collision);
+ mac_stats->FramesReceivedOK =
+ le64_to_cpu(tp->counters->rx_packets);
+ mac_stats->AlignmentErrors =
+ le16_to_cpu(tp->counters->align_errors);
+ mac_stats->FramesLostDueToIntMACXmitError =
+ le64_to_cpu(tp->counters->tx_errors);
+ mac_stats->BroadcastFramesReceivedOK =
+ le64_to_cpu(tp->counters->rx_broadcast);
+ mac_stats->MulticastFramesReceivedOK =
+ le32_to_cpu(tp->counters->rx_multicast);
+
+ if (!rtl_is_8125(tp))
+ return;
+
+ mac_stats->AlignmentErrors =
+ le32_to_cpu(tp->counters->align_errors32);
+ mac_stats->OctetsTransmittedOK =
+ le64_to_cpu(tp->counters->tx_octets);
+ mac_stats->LateCollisions =
+ le32_to_cpu(tp->counters->tx_late_collision);
+ mac_stats->FramesAbortedDueToXSColls =
+ le32_to_cpu(tp->counters->tx_aborted32);
+ mac_stats->OctetsReceivedOK =
+ le64_to_cpu(tp->counters->rx_octets);
+ mac_stats->FramesLostDueToIntMACRcvError =
+ le32_to_cpu(tp->counters->rx_mac_error);
+ mac_stats->MulticastFramesXmittedOK =
+ le64_to_cpu(tp->counters->tx_multicast64);
+ mac_stats->BroadcastFramesXmittedOK =
+ le64_to_cpu(tp->counters->tx_broadcast64);
+ mac_stats->MulticastFramesReceivedOK =
+ le64_to_cpu(tp->counters->rx_multicast64);
+ mac_stats->FrameTooLongErrors =
+ le32_to_cpu(tp->counters->rx_frame_too_long);
+}
+
+static void rtl8169_get_eth_ctrl_stats(struct net_device *dev,
+ struct ethtool_eth_ctrl_stats *ctrl_stats)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (!rtl_is_8125(tp))
+ return;
+
+ rtl8169_update_counters(tp);
+
+ ctrl_stats->UnsupportedOpcodesReceived =
+ le32_to_cpu(tp->counters->rx_unknown_opcode);
+}
+
static const struct ethtool_ops rtl8169_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES,
@@ -2207,8 +2231,11 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
.get_ringparam = rtl8169_get_ringparam,
+ .get_pause_stats = rtl8169_get_pause_stats,
.get_pauseparam = rtl8169_get_pauseparam,
.set_pauseparam = rtl8169_set_pauseparam,
+ .get_eth_mac_stats = rtl8169_get_eth_mac_stats,
+ .get_eth_ctrl_stats = rtl8169_get_eth_ctrl_stats,
};
static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
@@ -2233,6 +2260,9 @@ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
{ 0x7cf, 0x64a, RTL_GIGA_MAC_VER_66 },
{ 0x7cf, 0x649, RTL_GIGA_MAC_VER_65 },
+ /* 8125D family. */
+ { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 },
+
/* 8125B family. */
{ 0x7cf, 0x641, RTL_GIGA_MAC_VER_63 },
@@ -2423,11 +2453,9 @@ u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp)
static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
{
- if (!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
- return;
-
set_bit(flag, tp->wk.flags);
- schedule_work(&tp->wk.work);
+ if (!schedule_work(&tp->wk.work))
+ clear_bit(flag, tp->wk.flags);
}
static void rtl8169_init_phy(struct rtl8169_private *tp)
@@ -2500,9 +2528,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_61:
RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
break;
- case RTL_GIGA_MAC_VER_63:
- case RTL_GIGA_MAC_VER_65:
- case RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_66:
RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
RX_PAUSE_SLOT_ON);
break;
@@ -2517,86 +2543,31 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;
}
-static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
- RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1);
-}
-
-static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
- RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1);
-}
-
-static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
-}
-
-static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
-}
-
-static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, MaxTxPacketSize, 0x24);
- RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
- RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01);
-}
-
-static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, MaxTxPacketSize, 0x3f);
- RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
- RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01);
-}
-
-static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0));
-}
-
-static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
-{
- RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0));
-}
-
static void rtl_jumbo_config(struct rtl8169_private *tp)
{
bool jumbo = tp->dev->mtu > ETH_DATA_LEN;
int readrq = 4096;
+ if (jumbo && tp->mac_version >= RTL_GIGA_MAC_VER_17 &&
+ tp->mac_version <= RTL_GIGA_MAC_VER_26)
+ readrq = 512;
+
rtl_unlock_config_regs(tp);
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_17:
- if (jumbo) {
- readrq = 512;
- r8168b_1_hw_jumbo_enable(tp);
- } else {
- r8168b_1_hw_jumbo_disable(tp);
- }
+ r8169_mod_reg8_cond(tp, Config4, BIT(0), jumbo);
break;
case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_26:
- if (jumbo) {
- readrq = 512;
- r8168c_hw_jumbo_enable(tp);
- } else {
- r8168c_hw_jumbo_disable(tp);
- }
+ r8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo);
+ r8169_mod_reg8_cond(tp, Config4, Jumbo_En1, jumbo);
break;
case RTL_GIGA_MAC_VER_28:
- if (jumbo)
- r8168dp_hw_jumbo_enable(tp);
- else
- r8168dp_hw_jumbo_disable(tp);
+ r8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo);
break;
case RTL_GIGA_MAC_VER_31 ... RTL_GIGA_MAC_VER_33:
- if (jumbo)
- r8168e_hw_jumbo_enable(tp);
- else
- r8168e_hw_jumbo_disable(tp);
+ RTL_W8(tp, MaxTxPacketSize, jumbo ? 0x24 : 0x3f);
+ r8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo);
+ r8169_mod_reg8_cond(tp, Config4, BIT(0), jumbo);
break;
default:
break;
@@ -3707,8 +3678,8 @@ static void rtl_hw_start_8125_common(struct rtl8169_private *tp)
rtl_pcie_state_l2l3_disable(tp);
RTL_W16(tp, 0x382, 0x221b);
- RTL_W8(tp, 0x4500, 0);
- RTL_W16(tp, 0x4800, 0);
+ RTL_W32(tp, RSS_CTRL_8125, 0);
+ RTL_W16(tp, Q_NUM_CTRL_8125, 0);
/* disable UPS */
r8168_mac_ocp_modify(tp, 0xd40a, 0x0010, 0x0000);
@@ -3814,6 +3785,12 @@ static void rtl_hw_start_8125b(struct rtl8169_private *tp)
rtl_hw_start_8125_common(tp);
}
+static void rtl_hw_start_8125d(struct rtl8169_private *tp)
+{
+ rtl_set_def_aspm_entry_latency(tp);
+ rtl_hw_start_8125_common(tp);
+}
+
static void rtl_hw_start_8126a(struct rtl8169_private *tp)
{
rtl_set_def_aspm_entry_latency(tp);
@@ -3862,6 +3839,7 @@ static void rtl_hw_config(struct rtl8169_private *tp)
[RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117,
[RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
[RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
+ [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d,
[RTL_GIGA_MAC_VER_65] = rtl_hw_start_8126a,
[RTL_GIGA_MAC_VER_66] = rtl_hw_start_8126a,
};
@@ -3879,6 +3857,7 @@ static void rtl_hw_start_8125(struct rtl8169_private *tp)
/* disable interrupt coalescing */
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_61:
+ case RTL_GIGA_MAC_VER_64:
for (i = 0xa00; i < 0xb00; i += 4)
RTL_W32(tp, i, 0);
break;
@@ -3893,6 +3872,9 @@ static void rtl_hw_start_8125(struct rtl8169_private *tp)
break;
}
+ /* enable extended tally counter */
+ r8168_mac_ocp_modify(tp, 0xea84, 0, BIT(1) | BIT(0));
+
rtl_hw_config(tp);
}
@@ -4233,8 +4215,8 @@ static unsigned int rtl8125_quirk_udp_padto(struct rtl8169_private *tp,
{
unsigned int padto = 0, len = skb->len;
- if (rtl_is_8125(tp) && len < 128 + RTL_MIN_PATCH_LEN &&
- rtl_skb_is_udp(skb) && skb_transport_header_was_set(skb)) {
+ if (len < 128 + RTL_MIN_PATCH_LEN && rtl_skb_is_udp(skb) &&
+ skb_transport_header_was_set(skb)) {
unsigned int trans_data_len = skb_tail_pointer(skb) -
skb_transport_header(skb);
@@ -4258,9 +4240,15 @@ static unsigned int rtl8125_quirk_udp_padto(struct rtl8169_private *tp,
static unsigned int rtl_quirk_packet_padto(struct rtl8169_private *tp,
struct sk_buff *skb)
{
- unsigned int padto;
+ unsigned int padto = 0;
- padto = rtl8125_quirk_udp_padto(tp, skb);
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
+ padto = rtl8125_quirk_udp_padto(tp, skb);
+ break;
+ default:
+ break;
+ }
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_34:
@@ -4712,11 +4700,6 @@ static void rtl_task(struct work_struct *work)
container_of(work, struct rtl8169_private, wk.work);
int ret;
- rtnl_lock();
-
- if (!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
- goto out_unlock;
-
if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) {
/* if chip isn't accessible, reset bus to revive it */
if (RTL_R32(tp, TxConfig) == ~0) {
@@ -4724,7 +4707,7 @@ static void rtl_task(struct work_struct *work)
if (ret < 0) {
netdev_err(tp->dev, "Can't reset secondary PCI bus, detach NIC\n");
netif_device_detach(tp->dev);
- goto out_unlock;
+ return;
}
}
@@ -4743,8 +4726,6 @@ reset:
} else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) {
rtl_reset_work(tp);
}
-out_unlock:
- rtnl_unlock();
}
static int rtl8169_poll(struct napi_struct *napi, int budget)
@@ -4771,11 +4752,7 @@ static void r8169_phylink_handler(struct net_device *ndev)
if (netif_carrier_ok(ndev)) {
rtl_link_chg_patch(tp);
pm_request_resume(d);
- netif_wake_queue(tp->dev);
} else {
- /* In few cases rx is broken after link-down otherwise */
- if (rtl_is_8125(tp))
- rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE);
pm_runtime_idle(d);
}
@@ -4806,6 +4783,7 @@ static int r8169_phy_connect(struct rtl8169_private *tp)
static void rtl8169_down(struct rtl8169_private *tp)
{
+ disable_work_sync(&tp->wk.work);
/* Clear all task flags */
bitmap_zero(tp->wk.flags, RTL_FLAG_MAX);
@@ -4834,7 +4812,7 @@ static void rtl8169_up(struct rtl8169_private *tp)
phy_resume(tp->phydev);
rtl8169_init_phy(tp);
napi_enable(&tp->napi);
- set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+ enable_work(&tp->wk.work);
rtl_reset_work(tp);
phy_start(tp->phydev);
@@ -4851,8 +4829,6 @@ static int rtl8169_close(struct net_device *dev)
rtl8169_down(tp);
rtl8169_rx_clear(tp);
- cancel_work(&tp->wk.work);
-
free_irq(tp->irq, tp);
phy_disconnect(tp->phydev);
@@ -5085,7 +5061,7 @@ static void rtl_remove_one(struct pci_dev *pdev)
if (pci_dev_run_wake(pdev))
pm_runtime_get_noresume(&pdev->dev);
- cancel_work_sync(&tp->wk.work);
+ disable_work_sync(&tp->wk.work);
if (IS_ENABLED(CONFIG_R8169_LEDS))
r8169_remove_leds(tp->leds);
@@ -5252,6 +5228,12 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
phy_support_eee(tp->phydev);
phy_support_asym_pause(tp->phydev);
+ /* mimic behavior of r8125/r8126 vendor drivers */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_61)
+ phy_set_eee_broken(tp->phydev,
+ ETHTOOL_LINK_MODE_2500baseT_Full_BIT);
+ phy_set_eee_broken(tp->phydev, ETHTOOL_LINK_MODE_5000baseT_Full_BIT);
+
/* PHY will be woken up in rtl_open() */
phy_suspend(tp->phydev);
@@ -5365,6 +5347,43 @@ static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
return false;
}
+static umode_t r8169_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ return 0444;
+}
+
+static int r8169_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct rtl8169_private *tp = dev_get_drvdata(dev);
+ int val_raw;
+
+ val_raw = phy_read_paged(tp->phydev, 0xbd8, 0x12) & 0x3ff;
+ if (val_raw >= 512)
+ val_raw -= 1024;
+
+ *val = 1000 * val_raw / 2;
+
+ return 0;
+}
+
+static const struct hwmon_ops r8169_hwmon_ops = {
+ .is_visible = r8169_hwmon_is_visible,
+ .read = r8169_hwmon_read,
+};
+
+static const struct hwmon_channel_info * const r8169_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ NULL
+};
+
+static const struct hwmon_chip_info r8169_hwmon_chip_info = {
+ .ops = &r8169_hwmon_ops,
+ .info = r8169_hwmon_info,
+};
+
static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct rtl8169_private *tp;
@@ -5386,8 +5405,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1;
tp->ocp_base = OCP_STD_PHY_BASE;
- raw_spin_lock_init(&tp->cfg9346_usage_lock);
- raw_spin_lock_init(&tp->config25_lock);
raw_spin_lock_init(&tp->mac_ocp_lock);
mutex_init(&tp->led_lock);
@@ -5462,6 +5479,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->irq = pci_irq_vector(pdev, 0);
INIT_WORK(&tp->wk.work, rtl_task);
+ disable_work(&tp->wk.work);
rtl_init_mac_address(tp);
@@ -5487,11 +5505,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->features |= dev->hw_features;
- /* There has been a number of reports that using SG/TSO results in
- * tx timeouts. However for a lot of people SG/TSO works fine.
- * Therefore disable both features by default, but allow users to
- * enable them. Use at own risk!
- */
if (rtl_chip_supports_csum_v2(tp)) {
dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6;
netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2);
@@ -5502,6 +5515,17 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1);
}
+ /* There has been a number of reports that using SG/TSO results in
+ * tx timeouts. However for a lot of people SG/TSO works fine.
+ * It's not fully clear which chip versions are affected. Vendor
+ * drivers enable SG/TSO for certain chip versions per default,
+ * let's mimic this here. On other chip versions users can
+ * use ethtool to enable SG/TSO, use at own risk!
+ */
+ if (tp->mac_version >= RTL_GIGA_MAC_VER_46 &&
+ tp->mac_version != RTL_GIGA_MAC_VER_61)
+ dev->features |= dev->hw_features;
+
dev->hw_features |= NETIF_F_RXALL;
dev->hw_features |= NETIF_F_RXFCS;
@@ -5539,6 +5563,12 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
+ /* The temperature sensor is available from RTl8125B */
+ if (IS_REACHABLE(CONFIG_HWMON) && tp->mac_version >= RTL_GIGA_MAC_VER_63)
+ /* ignore errors */
+ devm_hwmon_device_register_with_info(&pdev->dev, "nic_temp", tp,
+ &r8169_hwmon_chip_info,
+ NULL);
rc = register_netdev(dev);
if (rc)
return rc;
diff --git a/drivers/net/ethernet/realtek/r8169_phy_config.c b/drivers/net/ethernet/realtek/r8169_phy_config.c
index cf29b1208482..5307c6ff4e25 100644
--- a/drivers/net/ethernet/realtek/r8169_phy_config.c
+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c
@@ -89,20 +89,17 @@ static void rtl8168h_config_eee_phy(struct phy_device *phydev)
phy_modify_paged(phydev, 0xa42, 0x14, 0x0000, 0x0080);
}
-static void rtl8125a_config_eee_phy(struct phy_device *phydev)
+static void rtl8125_common_config_eee_phy(struct phy_device *phydev)
{
- rtl8168h_config_eee_phy(phydev);
-
- phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000);
phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000);
+ phy_modify_paged(phydev, 0xa42, 0x14, 0x0080, 0x0000);
+ phy_modify_paged(phydev, 0xa4a, 0x11, 0x0200, 0x0000);
}
-static void rtl8125b_config_eee_phy(struct phy_device *phydev)
+static void rtl8125_config_eee_phy(struct phy_device *phydev)
{
- phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000);
- phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000);
- phy_modify_paged(phydev, 0xa42, 0x14, 0x0080, 0x0000);
- phy_modify_paged(phydev, 0xa4a, 0x11, 0x0200, 0x0000);
+ rtl8168g_config_eee_phy(phydev);
+ rtl8125_common_config_eee_phy(phydev);
}
static void rtl8169s_hw_phy_config(struct rtl8169_private *tp,
@@ -1061,15 +1058,15 @@ static void rtl8125a_2_hw_phy_config(struct rtl8169_private *tp,
rtl8168g_enable_gphy_10m(phydev);
rtl8168g_disable_aldps(phydev);
- rtl8125a_config_eee_phy(phydev);
+ rtl8125_config_eee_phy(phydev);
}
static void rtl8125b_hw_phy_config(struct rtl8169_private *tp,
struct phy_device *phydev)
{
r8169_apply_firmware(tp);
+ rtl8168g_enable_gphy_10m(phydev);
- phy_modify_paged(phydev, 0xa44, 0x11, 0x0000, 0x0800);
phy_modify_paged(phydev, 0xac4, 0x13, 0x00f0, 0x0090);
phy_modify_paged(phydev, 0xad3, 0x10, 0x0003, 0x0001);
@@ -1101,13 +1098,27 @@ static void rtl8125b_hw_phy_config(struct rtl8169_private *tp,
rtl8125_legacy_force_mode(phydev);
rtl8168g_disable_aldps(phydev);
- rtl8125b_config_eee_phy(phydev);
+ rtl8125_config_eee_phy(phydev);
+}
+
+static void rtl8125d_hw_phy_config(struct rtl8169_private *tp,
+ struct phy_device *phydev)
+{
+ r8169_apply_firmware(tp);
+ rtl8168g_enable_gphy_10m(phydev);
+ rtl8125_legacy_force_mode(phydev);
+ rtl8168g_disable_aldps(phydev);
+ rtl8125_config_eee_phy(phydev);
}
static void rtl8126a_hw_phy_config(struct rtl8169_private *tp,
struct phy_device *phydev)
{
r8169_apply_firmware(tp);
+ rtl8168g_enable_gphy_10m(phydev);
+ rtl8125_legacy_force_mode(phydev);
+ rtl8168g_disable_aldps(phydev);
+ rtl8125_common_config_eee_phy(phydev);
}
void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
@@ -1160,6 +1171,7 @@ void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
[RTL_GIGA_MAC_VER_53] = rtl8117_hw_phy_config,
[RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config,
[RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config,
+ [RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config,
[RTL_GIGA_MAC_VER_65] = rtl8126a_hw_phy_config,
[RTL_GIGA_MAC_VER_66] = rtl8126a_hw_phy_config,
};
diff --git a/drivers/net/ethernet/realtek/rtase/rtase.h b/drivers/net/ethernet/realtek/rtase/rtase.h
index 583c33930f88..dbc3f92eebc4 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase.h
+++ b/drivers/net/ethernet/realtek/rtase/rtase.h
@@ -9,7 +9,10 @@
#ifndef RTASE_H
#define RTASE_H
-#define RTASE_HW_VER_MASK 0x7C800000
+#define RTASE_HW_VER_MASK 0x7C800000
+#define RTASE_HW_VER_906X_7XA 0x00800000
+#define RTASE_HW_VER_906X_7XC 0x04000000
+#define RTASE_HW_VER_907XD_V1 0x04800000
#define RTASE_RX_DMA_BURST_256 4
#define RTASE_TX_DMA_BURST_UNLIMITED 7
@@ -170,7 +173,7 @@ enum rtase_registers {
RTASE_INT_MITI_TX = 0x0A00,
RTASE_INT_MITI_RX = 0x0A80,
- RTASE_VLAN_ENTRY_0 = 0xAC80,
+ RTASE_VLAN_ENTRY_0 = 0xAC80,
};
enum rtase_desc_status_bit {
@@ -327,6 +330,8 @@ struct rtase_private {
u16 int_nums;
u16 tx_int_mit;
u16 rx_int_mit;
+
+ u32 hw_ver;
};
#define RTASE_LSO_64K 64000
diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c
index f8777b7663d3..de7f11232593 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
+++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
@@ -1714,10 +1714,21 @@ static int rtase_get_settings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
u32 supported = SUPPORTED_MII | SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+ const struct rtase_private *tp = netdev_priv(dev);
ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
supported);
- cmd->base.speed = SPEED_5000;
+
+ switch (tp->hw_ver) {
+ case RTASE_HW_VER_906X_7XA:
+ case RTASE_HW_VER_906X_7XC:
+ cmd->base.speed = SPEED_5000;
+ break;
+ case RTASE_HW_VER_907XD_V1:
+ cmd->base.speed = SPEED_10000;
+ break;
+ }
+
cmd->base.duplex = DUPLEX_FULL;
cmd->base.port = PORT_MII;
cmd->base.autoneg = AUTONEG_DISABLE;
@@ -1972,20 +1983,21 @@ static void rtase_init_software_variable(struct pci_dev *pdev,
tp->dev->max_mtu = RTASE_MAX_JUMBO_SIZE;
}
-static bool rtase_check_mac_version_valid(struct rtase_private *tp)
+static int rtase_check_mac_version_valid(struct rtase_private *tp)
{
- u32 hw_ver = rtase_r32(tp, RTASE_TX_CONFIG_0) & RTASE_HW_VER_MASK;
- bool known_ver = false;
+ int ret = -ENODEV;
+
+ tp->hw_ver = rtase_r32(tp, RTASE_TX_CONFIG_0) & RTASE_HW_VER_MASK;
- switch (hw_ver) {
- case 0x00800000:
- case 0x04000000:
- case 0x04800000:
- known_ver = true;
+ switch (tp->hw_ver) {
+ case RTASE_HW_VER_906X_7XA:
+ case RTASE_HW_VER_906X_7XC:
+ case RTASE_HW_VER_907XD_V1:
+ ret = 0;
break;
}
- return known_ver;
+ return ret;
}
static int rtase_init_board(struct pci_dev *pdev, struct net_device **dev_out,
@@ -2105,9 +2117,13 @@ static int rtase_init_one(struct pci_dev *pdev,
tp->pdev = pdev;
/* identify chip attached to board */
- if (!rtase_check_mac_version_valid(tp))
- return dev_err_probe(&pdev->dev, -ENODEV,
- "unknown chip version, contact rtase maintainers (see MAINTAINERS file)\n");
+ ret = rtase_check_mac_version_valid(tp);
+ if (ret != 0) {
+ dev_err(&pdev->dev,
+ "unknown chip version: 0x%08x, contact rtase maintainers (see MAINTAINERS file)\n",
+ tp->hw_ver);
+ goto err_out_release_board;
+ }
rtase_init_software_variable(pdev, tp);
rtase_init_hardware(tp);
@@ -2115,7 +2131,7 @@ static int rtase_init_one(struct pci_dev *pdev,
ret = rtase_alloc_interrupt(pdev, tp);
if (ret < 0) {
dev_err(&pdev->dev, "unable to alloc MSIX/MSI\n");
- goto err_out_1;
+ goto err_out_del_napi;
}
rtase_init_netdev_ops(dev);
@@ -2148,7 +2164,7 @@ static int rtase_init_one(struct pci_dev *pdev,
GFP_KERNEL);
if (!tp->tally_vaddr) {
ret = -ENOMEM;
- goto err_out;
+ goto err_out_free_dma;
}
rtase_tally_counter_clear(tp);
@@ -2159,13 +2175,13 @@ static int rtase_init_one(struct pci_dev *pdev,
ret = register_netdev(dev);
if (ret != 0)
- goto err_out;
+ goto err_out_free_dma;
netdev_dbg(dev, "%pM, IRQ %d\n", dev->dev_addr, dev->irq);
return 0;
-err_out:
+err_out_free_dma:
if (tp->tally_vaddr) {
dma_free_coherent(&pdev->dev,
sizeof(*tp->tally_vaddr),
@@ -2175,12 +2191,13 @@ err_out:
tp->tally_vaddr = NULL;
}
-err_out_1:
+err_out_del_napi:
for (i = 0; i < tp->int_nums; i++) {
ivec = &tp->int_vector[i];
netif_napi_del(&ivec->napi);
}
+err_out_release_board:
rtase_release_board(pdev, dev, ioaddr);
return ret;
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index a7de5cf6b317..7b48060c250b 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -998,6 +998,8 @@ enum CSR1_BIT {
CSR1_TDHD = 0x08000000,
};
+#define CSR1_CSUM_ENABLE (CSR1_TTCP4 | CSR1_TUDP4 | CSR1_TTCP6 | CSR1_TUDP6)
+
enum CSR2_BIT {
CSR2_RIP4 = 0x00000001,
CSR2_RTCP4 = 0x00000010,
@@ -1012,6 +1014,9 @@ enum CSR2_BIT {
CSR2_RDHD = 0x08000000,
};
+#define CSR2_CSUM_ENABLE (CSR2_RTCP4 | CSR2_RUDP4 | CSR2_RICMP4 | \
+ CSR2_RTCP6 | CSR2_RUDP6 | CSR2_RICMP6)
+
#define DBAT_ENTRY_NUM 22
#define RX_QUEUE_OFFSET 4
#define NUM_RX_QUEUE 2
@@ -1050,6 +1055,7 @@ struct ravb_hw_info {
size_t gstrings_size;
netdev_features_t net_hw_features;
netdev_features_t net_features;
+ netdev_features_t vlan_features;
int stats_len;
u32 tccr_mask;
u32 tx_max_frame_size;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 907af4651c55..ac0f093f647a 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -504,11 +504,10 @@ static void ravb_csum_init_gbeth(struct net_device *ndev)
ndev->features &= ~NETIF_F_RXCSUM;
} else {
if (tx_enable)
- ravb_write(ndev, CSR1_TIP4 | CSR1_TTCP4 | CSR1_TUDP4, CSR1);
+ ravb_write(ndev, CSR1_CSUM_ENABLE, CSR1);
if (rx_enable)
- ravb_write(ndev, CSR2_RIP4 | CSR2_RTCP4 | CSR2_RUDP4 | CSR2_RICMP4,
- CSR2);
+ ravb_write(ndev, CSR2_CSUM_ENABLE, CSR2);
}
done:
@@ -750,38 +749,34 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
static void ravb_rx_csum_gbeth(struct sk_buff *skb)
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
- __wsum csum_ip_hdr, csum_proto;
- skb_frag_t *last_frag;
- u8 *hw_csum;
+ size_t csum_len;
+ u16 *hw_csum;
- /* The hardware checksum status is contained in sizeof(__sum16) * 2 = 4
- * bytes appended to packet data. First 2 bytes is ip header checksum
- * and last 2 bytes is protocol checksum.
+ /* The hardware checksum status is contained in 4 bytes appended to
+ * packet data.
+ *
+ * For ipv4, the first 2 bytes are the ip header checksum status. We can
+ * ignore this as it will always be re-checked in inet_gro_receive().
+ *
+ * The last 2 bytes are the protocol checksum status which will be zero
+ * if the checksum has been validated.
*/
- if (unlikely(skb->len < sizeof(__sum16) * 2))
+ csum_len = sizeof(*hw_csum) * 2;
+ if (unlikely(skb->len < csum_len))
return;
if (skb_is_nonlinear(skb)) {
- last_frag = &shinfo->frags[shinfo->nr_frags - 1];
- hw_csum = skb_frag_address(last_frag) +
- skb_frag_size(last_frag);
+ skb_frag_t *last_frag = &shinfo->frags[shinfo->nr_frags - 1];
+
+ hw_csum = (u16 *)(skb_frag_address(last_frag) +
+ skb_frag_size(last_frag));
+ skb_frag_size_sub(last_frag, csum_len);
} else {
- hw_csum = skb_tail_pointer(skb);
+ hw_csum = (u16 *)skb_tail_pointer(skb);
+ skb_trim(skb, skb->len - csum_len);
}
- hw_csum -= sizeof(__sum16);
- csum_proto = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
-
- hw_csum -= sizeof(__sum16);
- csum_ip_hdr = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
-
- if (skb_is_nonlinear(skb))
- skb_frag_size_sub(last_frag, 2 * sizeof(__sum16));
- else
- skb_trim(skb, skb->len - 2 * sizeof(__sum16));
-
- /* TODO: IPV6 Rx checksum */
- if (skb->protocol == htons(ETH_P_IP) && !csum_ip_hdr && !csum_proto)
+ if (!get_unaligned(--hw_csum))
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
@@ -2067,32 +2062,44 @@ out_unlock:
static bool ravb_can_tx_csum_gbeth(struct sk_buff *skb)
{
- struct iphdr *ip = ip_hdr(skb);
+ u16 net_protocol = ntohs(skb->protocol);
+ u8 inner_protocol;
- /* TODO: Need to add support for VLAN tag 802.1Q */
- if (skb_vlan_tag_present(skb))
- return false;
+ /* GbEth IP can calculate the checksum if:
+ * - there are zero or one VLAN headers with TPID=0x8100
+ * - the network protocol is IPv4 or IPv6
+ * - the transport protocol is TCP, UDP or ICMP
+ * - the packet is not fragmented
+ */
- /* TODO: Need to add hardware checksum for IPv6 */
- if (skb->protocol != htons(ETH_P_IP))
- return false;
+ if (net_protocol == ETH_P_8021Q) {
+ struct vlan_hdr vhdr, *vh;
- switch (ip->protocol) {
- case IPPROTO_TCP:
- break;
- case IPPROTO_UDP:
- /* If the checksum value in the UDP header field is 0, TOE does
- * not calculate checksum for UDP part of this frame as it is
- * optional function as per standards.
- */
- if (udp_hdr(skb)->check == 0)
+ vh = skb_header_pointer(skb, ETH_HLEN, sizeof(vhdr), &vhdr);
+ if (!vh)
return false;
+
+ net_protocol = ntohs(vh->h_vlan_encapsulated_proto);
+ }
+
+ switch (net_protocol) {
+ case ETH_P_IP:
+ inner_protocol = ip_hdr(skb)->protocol;
+ break;
+ case ETH_P_IPV6:
+ inner_protocol = ipv6_hdr(skb)->nexthdr;
break;
default:
return false;
}
- return true;
+ switch (inner_protocol) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ return true;
+ default:
+ return false;
+ }
}
/* Packet transmit function for Ethernet AVB */
@@ -2530,7 +2537,7 @@ static int ravb_set_features_gbeth(struct net_device *ndev,
spin_lock_irqsave(&priv->lock, flags);
if (changed & NETIF_F_RXCSUM) {
if (features & NETIF_F_RXCSUM)
- val = CSR2_RIP4 | CSR2_RTCP4 | CSR2_RUDP4 | CSR2_RICMP4;
+ val = CSR2_CSUM_ENABLE;
else
val = 0;
@@ -2541,7 +2548,7 @@ static int ravb_set_features_gbeth(struct net_device *ndev,
if (changed & NETIF_F_HW_CSUM) {
if (features & NETIF_F_HW_CSUM)
- val = CSR1_TIP4 | CSR1_TTCP4 | CSR1_TUDP4;
+ val = CSR1_CSUM_ENABLE;
else
val = 0;
@@ -2778,6 +2785,7 @@ static const struct ravb_hw_info gbeth_hw_info = {
.gstrings_size = sizeof(ravb_gstrings_stats_gbeth),
.net_hw_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM,
.net_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM,
+ .vlan_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM,
.stats_len = ARRAY_SIZE(ravb_gstrings_stats_gbeth),
.tccr_mask = TCCR_TSRQ0,
.tx_max_frame_size = 1522,
@@ -2920,6 +2928,7 @@ static int ravb_probe(struct platform_device *pdev)
ndev->features = info->net_features;
ndev->hw_features = info->net_hw_features;
+ ndev->vlan_features = info->vlan_features;
error = reset_control_deassert(rstc);
if (error)
@@ -3290,7 +3299,7 @@ static const struct dev_pm_ops ravb_dev_pm_ops = {
static struct platform_driver ravb_driver = {
.probe = ravb_probe,
- .remove_new = ravb_remove,
+ .remove = ravb_remove,
.driver = {
.name = "ravb",
.pm = pm_ptr(&ravb_dev_pm_ops),
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index b80aa27a7214..8d18dae4d8fb 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -2188,7 +2188,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(renesas_eth_sw_pm_ops, renesas_eth_sw_suspend,
static struct platform_driver renesas_eth_sw_driver_platform = {
.probe = renesas_eth_sw_probe,
- .remove_new = renesas_eth_sw_remove,
+ .remove = renesas_eth_sw_remove,
.driver = {
.name = "renesas_eth_sw",
.pm = pm_sleep_ptr(&renesas_eth_sw_pm_ops),
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 7a25903e35c3..8887b8921009 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -3560,7 +3560,7 @@ MODULE_DEVICE_TABLE(platform, sh_eth_id_table);
static struct platform_driver sh_eth_driver = {
.probe = sh_eth_drv_probe,
- .remove_new = sh_eth_drv_remove,
+ .remove = sh_eth_drv_remove,
.id_table = sh_eth_id_table,
.driver = {
.name = CARDNAME,
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 84fa911c78db..fe0bf1d3217a 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2502,7 +2502,7 @@ static void rocker_carrier_init(const struct rocker_port *rocker_port)
u64 link_status = rocker_read64(rocker, PORT_PHYS_LINK_STATUS);
bool link_up;
- link_up = link_status & (1 << rocker_port->pport);
+ link_up = link_status & (1ULL << rocker_port->pport);
if (link_up)
netif_carrier_on(rocker_port->dev);
else
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
index e6e130dbe1de..2eccc7617507 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
@@ -224,7 +224,7 @@ MODULE_DEVICE_TABLE(of, sxgbe_dt_ids);
static struct platform_driver sxgbe_platform_driver = {
.probe = sxgbe_platform_probe,
- .remove_new = sxgbe_platform_remove,
+ .remove = sxgbe_platform_remove,
.driver = {
.name = SXGBE_RESOURCE_NAME,
.pm = &sxgbe_platform_pm_ops,
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index 76356dadf233..7967a0ee320b 100644
--- a/drivers/net/ethernet/seeq/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -832,7 +832,7 @@ static void sgiseeq_remove(struct platform_device *pdev)
static struct platform_driver sgiseeq_driver = {
.probe = sgiseeq_probe,
- .remove_new = sgiseeq_remove,
+ .remove = sgiseeq_remove,
.driver = {
.name = "sgiseeq",
}
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index de131fc5fa0b..452009ed7a43 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1751,7 +1751,7 @@ static void efx_ef10_get_stat_mask(struct efx_nic *efx, unsigned long *mask)
#endif
}
-static size_t efx_ef10_describe_stats(struct efx_nic *efx, u8 *names)
+static size_t efx_ef10_describe_stats(struct efx_nic *efx, u8 **names)
{
DECLARE_BITMAP(mask, EF10_STAT_COUNT);
diff --git a/drivers/net/ethernet/sfc/ef100_ethtool.c b/drivers/net/ethernet/sfc/ef100_ethtool.c
index 5c2551369812..6c3b74000d3b 100644
--- a/drivers/net/ethernet/sfc/ef100_ethtool.c
+++ b/drivers/net/ethernet/sfc/ef100_ethtool.c
@@ -59,6 +59,7 @@ const struct ethtool_ops ef100_ethtool_ops = {
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size,
.rxfh_per_ctx_key = true,
+ .cap_rss_rxnfc_adds = true,
.rxfh_priv_size = sizeof(struct efx_rss_context_priv),
.get_rxfh = efx_ethtool_get_rxfh,
.set_rxfh = efx_ethtool_set_rxfh,
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 6da06931187d..62e674d6ff60 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -583,7 +583,7 @@ static const struct efx_hw_stat_desc ef100_stat_desc[EF100_STAT_COUNT] = {
EFX_GENERIC_SW_STAT(rx_noskb_drops),
};
-static size_t ef100_describe_stats(struct efx_nic *efx, u8 *names)
+static size_t ef100_describe_stats(struct efx_nic *efx, u8 **names)
{
DECLARE_BITMAP(mask, EF100_STAT_COUNT) = {};
diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c
index 83d9db71d7d7..44dc75feb162 100644
--- a/drivers/net/ethernet/sfc/ef100_rx.c
+++ b/drivers/net/ethernet/sfc/ef100_rx.c
@@ -134,6 +134,9 @@ void __ef100_rx_packet(struct efx_channel *channel)
goto free_rx_buffer;
}
+ ++rx_queue->rx_packets;
+ rx_queue->rx_bytes += rx_buf->len;
+
efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh, csum);
goto out;
@@ -149,8 +152,6 @@ static void ef100_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index)
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_nic *efx = rx_queue->efx;
- ++rx_queue->rx_packets;
-
netif_vdbg(efx, rx_status, efx->net_dev,
"RX queue %d received id %x\n",
efx_rx_queue_index(rx_queue), index);
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 36b3b57e2055..650136dfc642 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -22,6 +22,7 @@
#include "net_driver.h"
#include <net/gre.h>
#include <net/udp_tunnel.h>
+#include <net/netdev_queues.h>
#include "efx.h"
#include "efx_common.h"
#include "efx_channels.h"
@@ -417,14 +418,6 @@ unsigned int efx_usecs_to_ticks(struct efx_nic *efx, unsigned int usecs)
return usecs * 1000 / efx->timer_quantum_ns;
}
-unsigned int efx_ticks_to_usecs(struct efx_nic *efx, unsigned int ticks)
-{
- /* We must round up when converting ticks to microseconds
- * because we round down when converting the other way.
- */
- return DIV_ROUND_UP(ticks * efx->timer_quantum_ns, 1000);
-}
-
/* Set interrupt moderation parameters */
int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
unsigned int rx_usecs, bool rx_adaptive,
@@ -626,6 +619,113 @@ static const struct net_device_ops efx_netdev_ops = {
.ndo_bpf = efx_xdp
};
+static void efx_get_queue_stats_rx(struct net_device *net_dev, int idx,
+ struct netdev_queue_stats_rx *stats)
+{
+ struct efx_nic *efx = efx_netdev_priv(net_dev);
+ struct efx_rx_queue *rx_queue;
+ struct efx_channel *channel;
+
+ channel = efx_get_channel(efx, idx);
+ rx_queue = efx_channel_get_rx_queue(channel);
+ /* Count only packets since last time datapath was started */
+ stats->packets = rx_queue->rx_packets - rx_queue->old_rx_packets;
+ stats->bytes = rx_queue->rx_bytes - rx_queue->old_rx_bytes;
+ stats->hw_drops = efx_get_queue_stat_rx_hw_drops(channel) -
+ channel->old_n_rx_hw_drops;
+ stats->hw_drop_overruns = channel->n_rx_nodesc_trunc -
+ channel->old_n_rx_hw_drop_overruns;
+}
+
+static void efx_get_queue_stats_tx(struct net_device *net_dev, int idx,
+ struct netdev_queue_stats_tx *stats)
+{
+ struct efx_nic *efx = efx_netdev_priv(net_dev);
+ struct efx_tx_queue *tx_queue;
+ struct efx_channel *channel;
+
+ channel = efx_get_tx_channel(efx, idx);
+ stats->packets = 0;
+ stats->bytes = 0;
+ stats->hw_gso_packets = 0;
+ stats->hw_gso_wire_packets = 0;
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ stats->packets += tx_queue->complete_packets -
+ tx_queue->old_complete_packets;
+ stats->bytes += tx_queue->complete_bytes -
+ tx_queue->old_complete_bytes;
+ /* Note that, unlike stats->packets and stats->bytes,
+ * these count TXes enqueued, rather than completed,
+ * which may not be what users expect.
+ */
+ stats->hw_gso_packets += tx_queue->tso_bursts -
+ tx_queue->old_tso_bursts;
+ stats->hw_gso_wire_packets += tx_queue->tso_packets -
+ tx_queue->old_tso_packets;
+ }
+}
+
+static void efx_get_base_stats(struct net_device *net_dev,
+ struct netdev_queue_stats_rx *rx,
+ struct netdev_queue_stats_tx *tx)
+{
+ struct efx_nic *efx = efx_netdev_priv(net_dev);
+ struct efx_tx_queue *tx_queue;
+ struct efx_rx_queue *rx_queue;
+ struct efx_channel *channel;
+
+ rx->packets = 0;
+ rx->bytes = 0;
+ rx->hw_drops = 0;
+ rx->hw_drop_overruns = 0;
+ tx->packets = 0;
+ tx->bytes = 0;
+ tx->hw_gso_packets = 0;
+ tx->hw_gso_wire_packets = 0;
+
+ /* Count all packets on non-core queues, and packets before last
+ * datapath start on core queues.
+ */
+ efx_for_each_channel(channel, efx) {
+ rx_queue = efx_channel_get_rx_queue(channel);
+ if (channel->channel >= net_dev->real_num_rx_queues) {
+ rx->packets += rx_queue->rx_packets;
+ rx->bytes += rx_queue->rx_bytes;
+ rx->hw_drops += efx_get_queue_stat_rx_hw_drops(channel);
+ rx->hw_drop_overruns += channel->n_rx_nodesc_trunc;
+ } else {
+ rx->packets += rx_queue->old_rx_packets;
+ rx->bytes += rx_queue->old_rx_bytes;
+ rx->hw_drops += channel->old_n_rx_hw_drops;
+ rx->hw_drop_overruns += channel->old_n_rx_hw_drop_overruns;
+ }
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ if (channel->channel < efx->tx_channel_offset ||
+ channel->channel >= efx->tx_channel_offset +
+ net_dev->real_num_tx_queues) {
+ tx->packets += tx_queue->complete_packets;
+ tx->bytes += tx_queue->complete_bytes;
+ tx->hw_gso_packets += tx_queue->tso_bursts;
+ tx->hw_gso_wire_packets += tx_queue->tso_packets;
+ } else {
+ tx->packets += tx_queue->old_complete_packets;
+ tx->bytes += tx_queue->old_complete_bytes;
+ tx->hw_gso_packets += tx_queue->old_tso_bursts;
+ tx->hw_gso_wire_packets += tx_queue->old_tso_packets;
+ }
+ /* Include XDP TX in device-wide stats */
+ tx->packets += tx_queue->complete_xdp_packets;
+ tx->bytes += tx_queue->complete_xdp_bytes;
+ }
+ }
+}
+
+static const struct netdev_stat_ops efx_stat_ops = {
+ .get_queue_stats_rx = efx_get_queue_stats_rx,
+ .get_queue_stats_tx = efx_get_queue_stats_tx,
+ .get_base_stats = efx_get_base_stats,
+};
+
static int efx_xdp_setup_prog(struct efx_nic *efx, struct bpf_prog *prog)
{
struct bpf_prog *old_prog;
@@ -716,6 +816,7 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->watchdog_timeo = 5 * HZ;
net_dev->irq = efx->pci_dev->irq;
net_dev->netdev_ops = &efx_netdev_ops;
+ net_dev->stat_ops = &efx_stat_ops;
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
net_dev->priv_flags |= IFF_UNICAST_FLT;
net_dev->ethtool_ops = &efx_ethtool_ops;
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index 7a6cab883d66..45e191686625 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -168,7 +168,6 @@ extern const struct ethtool_ops efx_ethtool_ops;
/* Global */
unsigned int efx_usecs_to_ticks(struct efx_nic *efx, unsigned int usecs);
-unsigned int efx_ticks_to_usecs(struct efx_nic *efx, unsigned int ticks);
int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
unsigned int rx_usecs, bool rx_adaptive,
bool rx_may_override_tx);
diff --git a/drivers/net/ethernet/sfc/efx_channels.c b/drivers/net/ethernet/sfc/efx_channels.c
index f1723a6fb082..06b4f52713ef 100644
--- a/drivers/net/ethernet/sfc/efx_channels.c
+++ b/drivers/net/ethernet/sfc/efx_channels.c
@@ -1100,6 +1100,10 @@ void efx_start_channels(struct efx_nic *efx)
atomic_inc(&efx->active_queues);
}
+ /* reset per-queue stats */
+ channel->old_n_rx_hw_drops = efx_get_queue_stat_rx_hw_drops(channel);
+ channel->old_n_rx_hw_drop_overruns = channel->n_rx_nodesc_trunc;
+
efx_for_each_channel_rx_queue(rx_queue, channel) {
efx_init_rx_queue(rx_queue);
atomic_inc(&efx->active_queues);
@@ -1209,6 +1213,8 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
tx_queue->pkts_compl,
tx_queue->bytes_compl);
}
+ tx_queue->complete_packets += tx_queue->pkts_compl;
+ tx_queue->complete_bytes += tx_queue->bytes_compl;
}
/* Receive any packets we queued up */
diff --git a/drivers/net/ethernet/sfc/efx_channels.h b/drivers/net/ethernet/sfc/efx_channels.h
index 46b702648721..547cf94014a3 100644
--- a/drivers/net/ethernet/sfc/efx_channels.h
+++ b/drivers/net/ethernet/sfc/efx_channels.h
@@ -43,6 +43,13 @@ struct efx_channel *efx_copy_channel(const struct efx_channel *old_channel);
void efx_start_channels(struct efx_nic *efx);
void efx_stop_channels(struct efx_nic *efx);
+static inline u64 efx_get_queue_stat_rx_hw_drops(struct efx_channel *channel)
+{
+ return channel->n_rx_eth_crc_err + channel->n_rx_frm_trunc +
+ channel->n_rx_overlength + channel->n_rx_nodesc_trunc +
+ channel->n_rx_mport_bad;
+}
+
void efx_init_napi_channel(struct efx_channel *channel);
void efx_init_napi(struct efx_nic *efx);
void efx_fini_napi_channel(struct efx_channel *channel);
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index 13cf647051af..c88ec3e24836 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -635,22 +635,6 @@ int __efx_reconfigure_port(struct efx_nic *efx)
return rc;
}
-/* Reinitialise the MAC to pick up new PHY settings, even if the port is
- * disabled.
- */
-int efx_reconfigure_port(struct efx_nic *efx)
-{
- int rc;
-
- EFX_ASSERT_RESET_SERIALISED(efx);
-
- mutex_lock(&efx->mac_lock);
- rc = __efx_reconfigure_port(efx);
- mutex_unlock(&efx->mac_lock);
-
- return rc;
-}
-
/**************************************************************************
*
* Device reset and suspend
diff --git a/drivers/net/ethernet/sfc/efx_common.h b/drivers/net/ethernet/sfc/efx_common.h
index 2c54dac3e662..19a8ca530969 100644
--- a/drivers/net/ethernet/sfc/efx_common.h
+++ b/drivers/net/ethernet/sfc/efx_common.h
@@ -40,7 +40,6 @@ void efx_destroy_reset_workqueue(void);
void efx_start_monitor(struct efx_nic *efx);
int __efx_reconfigure_port(struct efx_nic *efx);
-int efx_reconfigure_port(struct efx_nic *efx);
#define EFX_ASSERT_RESET_SERIALISED(efx) \
do { \
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index bb1930818beb..83d715544f7f 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -263,6 +263,7 @@ const struct ethtool_ops efx_ethtool_ops = {
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size,
.rxfh_per_ctx_key = true,
+ .cap_rss_rxnfc_adds = true,
.rxfh_priv_size = sizeof(struct efx_rss_context_priv),
.get_rxfh = efx_ethtool_get_rxfh,
.set_rxfh = efx_ethtool_set_rxfh,
diff --git a/drivers/net/ethernet/sfc/ethtool_common.c b/drivers/net/ethernet/sfc/ethtool_common.c
index 6ded44b86052..2d734496733f 100644
--- a/drivers/net/ethernet/sfc/ethtool_common.c
+++ b/drivers/net/ethernet/sfc/ethtool_common.c
@@ -75,7 +75,6 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
EFX_ETHTOOL_UINT_TXQ_STAT(pio_packets),
EFX_ETHTOOL_UINT_TXQ_STAT(cb_packets),
EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
- EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_inner_ip_hdr_chksum_err),
@@ -83,8 +82,8 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_outer_ip_hdr_chksum_err),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_outer_tcp_udp_chksum_err),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_eth_crc_err),
- EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
+ EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_overlength),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_xdp_drops),
@@ -396,7 +395,7 @@ int efx_ethtool_fill_self_tests(struct efx_nic *efx,
return n;
}
-static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
+static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 **strings)
{
size_t n_stats = 0;
struct efx_channel *channel;
@@ -404,24 +403,22 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
efx_for_each_channel(channel, efx) {
if (efx_channel_has_tx_queues(channel)) {
n_stats++;
- if (strings != NULL) {
- snprintf(strings, ETH_GSTRING_LEN,
- "tx-%u.tx_packets",
- channel->tx_queue[0].queue /
- EFX_MAX_TXQ_PER_CHANNEL);
+ if (!strings)
+ continue;
- strings += ETH_GSTRING_LEN;
- }
+ ethtool_sprintf(strings, "tx-%u.tx_packets",
+ channel->tx_queue[0].queue /
+ EFX_MAX_TXQ_PER_CHANNEL);
}
}
efx_for_each_channel(channel, efx) {
if (efx_channel_has_rx_queue(channel)) {
n_stats++;
- if (strings != NULL) {
- snprintf(strings, ETH_GSTRING_LEN,
- "rx-%d.rx_packets", channel->channel);
- strings += ETH_GSTRING_LEN;
- }
+ if (!strings)
+ continue;
+
+ ethtool_sprintf(strings, "rx-%d.rx_packets",
+ channel->channel);
}
}
if (efx->xdp_tx_queue_count && efx->xdp_tx_queues) {
@@ -429,11 +426,11 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
for (xdp = 0; xdp < efx->xdp_tx_queue_count; xdp++) {
n_stats++;
- if (strings) {
- snprintf(strings, ETH_GSTRING_LEN,
- "tx-xdp-cpu-%hu.tx_packets", xdp);
- strings += ETH_GSTRING_LEN;
- }
+ if (!strings)
+ continue;
+
+ ethtool_sprintf(strings, "tx-xdp-cpu-%hu.tx_packets",
+ xdp);
}
}
@@ -465,15 +462,11 @@ void efx_ethtool_get_strings(struct net_device *net_dev,
switch (string_set) {
case ETH_SS_STATS:
- strings += (efx->type->describe_stats(efx, strings) *
- ETH_GSTRING_LEN);
+ efx->type->describe_stats(efx, &strings);
for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++)
- strscpy(strings + i * ETH_GSTRING_LEN,
- efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
- strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
- strings += (efx_describe_per_queue_stats(efx, strings) *
- ETH_GSTRING_LEN);
- efx_ptp_describe_stats(efx, strings);
+ ethtool_puts(&strings, efx_sw_stat_desc[i].name);
+ efx_describe_per_queue_stats(efx, &strings);
+ efx_ptp_describe_stats(efx, &strings);
break;
case ETH_SS_TEST:
efx_ethtool_fill_self_tests(efx, NULL, strings, NULL);
diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c
index 8925745f1c17..b07f7e4e2877 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.c
+++ b/drivers/net/ethernet/sfc/falcon/efx.c
@@ -1886,14 +1886,6 @@ unsigned int ef4_usecs_to_ticks(struct ef4_nic *efx, unsigned int usecs)
return usecs * 1000 / efx->timer_quantum_ns;
}
-unsigned int ef4_ticks_to_usecs(struct ef4_nic *efx, unsigned int ticks)
-{
- /* We must round up when converting ticks to microseconds
- * because we round down when converting the other way.
- */
- return DIV_ROUND_UP(ticks * efx->timer_quantum_ns, 1000);
-}
-
/* Set interrupt moderation parameters */
int ef4_init_irq_moderation(struct ef4_nic *efx, unsigned int tx_usecs,
unsigned int rx_usecs, bool rx_adaptive,
diff --git a/drivers/net/ethernet/sfc/falcon/efx.h b/drivers/net/ethernet/sfc/falcon/efx.h
index d3b4646545fa..52508f2c8cb2 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.h
+++ b/drivers/net/ethernet/sfc/falcon/efx.h
@@ -198,7 +198,6 @@ int ef4_try_recovery(struct ef4_nic *efx);
/* Global */
void ef4_schedule_reset(struct ef4_nic *efx, enum reset_type type);
unsigned int ef4_usecs_to_ticks(struct ef4_nic *efx, unsigned int usecs);
-unsigned int ef4_ticks_to_usecs(struct ef4_nic *efx, unsigned int ticks);
int ef4_init_irq_moderation(struct ef4_nic *efx, unsigned int tx_usecs,
unsigned int rx_usecs, bool rx_adaptive,
bool rx_may_override_tx);
diff --git a/drivers/net/ethernet/sfc/falcon/ethtool.c b/drivers/net/ethernet/sfc/falcon/ethtool.c
index f4db683b80f7..04766448a545 100644
--- a/drivers/net/ethernet/sfc/falcon/ethtool.c
+++ b/drivers/net/ethernet/sfc/falcon/ethtool.c
@@ -353,7 +353,7 @@ static int ef4_ethtool_fill_self_tests(struct ef4_nic *efx,
return n;
}
-static size_t ef4_describe_per_queue_stats(struct ef4_nic *efx, u8 *strings)
+static size_t ef4_describe_per_queue_stats(struct ef4_nic *efx, u8 **strings)
{
size_t n_stats = 0;
struct ef4_channel *channel;
@@ -361,24 +361,22 @@ static size_t ef4_describe_per_queue_stats(struct ef4_nic *efx, u8 *strings)
ef4_for_each_channel(channel, efx) {
if (ef4_channel_has_tx_queues(channel)) {
n_stats++;
- if (strings != NULL) {
- snprintf(strings, ETH_GSTRING_LEN,
- "tx-%u.tx_packets",
- channel->tx_queue[0].queue /
- EF4_TXQ_TYPES);
+ if (!strings)
+ continue;
- strings += ETH_GSTRING_LEN;
- }
+ ethtool_sprintf(strings, "tx-%u.tx_packets",
+ channel->tx_queue[0].queue /
+ EF4_TXQ_TYPES);
}
}
ef4_for_each_channel(channel, efx) {
if (ef4_channel_has_rx_queue(channel)) {
n_stats++;
- if (strings != NULL) {
- snprintf(strings, ETH_GSTRING_LEN,
- "rx-%d.rx_packets", channel->channel);
- strings += ETH_GSTRING_LEN;
- }
+ if (!strings)
+ continue;
+
+ ethtool_sprintf(strings, "rx-%d.rx_packets",
+ channel->channel);
}
}
return n_stats;
@@ -409,14 +407,10 @@ static void ef4_ethtool_get_strings(struct net_device *net_dev,
switch (string_set) {
case ETH_SS_STATS:
- strings += (efx->type->describe_stats(efx, strings) *
- ETH_GSTRING_LEN);
+ efx->type->describe_stats(efx, &strings);
for (i = 0; i < EF4_ETHTOOL_SW_STAT_COUNT; i++)
- strscpy(strings + i * ETH_GSTRING_LEN,
- ef4_sw_stat_desc[i].name, ETH_GSTRING_LEN);
- strings += EF4_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
- strings += (ef4_describe_per_queue_stats(efx, strings) *
- ETH_GSTRING_LEN);
+ ethtool_puts(&strings, ef4_sw_stat_desc[i].name);
+ ef4_describe_per_queue_stats(efx, &strings);
break;
case ETH_SS_TEST:
ef4_ethtool_fill_self_tests(efx, NULL, strings, NULL);
diff --git a/drivers/net/ethernet/sfc/falcon/falcon.c b/drivers/net/ethernet/sfc/falcon/falcon.c
index 36114ce88034..4af56333ea49 100644
--- a/drivers/net/ethernet/sfc/falcon/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon/falcon.c
@@ -2564,7 +2564,7 @@ static void falcon_remove_nic(struct ef4_nic *efx)
efx->nic_data = NULL;
}
-static size_t falcon_describe_nic_stats(struct ef4_nic *efx, u8 *names)
+static size_t falcon_describe_nic_stats(struct ef4_nic *efx, u8 **names)
{
return ef4_nic_describe_stats(falcon_stat_desc, FALCON_STAT_COUNT,
falcon_stat_mask, names);
diff --git a/drivers/net/ethernet/sfc/falcon/farch.c b/drivers/net/ethernet/sfc/falcon/farch.c
index c64623c2e80c..01017c41338e 100644
--- a/drivers/net/ethernet/sfc/falcon/farch.c
+++ b/drivers/net/ethernet/sfc/falcon/farch.c
@@ -1631,28 +1631,6 @@ void ef4_farch_rx_push_indir_table(struct ef4_nic *efx)
}
}
-/* Looks at available SRAM resources and works out how many queues we
- * can support, and where things like descriptor caches should live.
- *
- * SRAM is split up as follows:
- * 0 buftbl entries for channels
- * efx->vf_buftbl_base buftbl entries for SR-IOV
- * efx->rx_dc_base RX descriptor caches
- * efx->tx_dc_base TX descriptor caches
- */
-void ef4_farch_dimension_resources(struct ef4_nic *efx, unsigned sram_lim_qw)
-{
- unsigned vi_count;
-
- /* Account for the buffer table entries backing the datapath channels
- * and the descriptor caches for those channels.
- */
- vi_count = max(efx->n_channels, efx->n_tx_channels * EF4_TXQ_TYPES);
-
- efx->tx_dc_base = sram_lim_qw - vi_count * TX_DC_ENTRIES;
- efx->rx_dc_base = efx->tx_dc_base - vi_count * RX_DC_ENTRIES;
-}
-
u32 ef4_farch_fpga_ver(struct ef4_nic *efx)
{
ef4_oword_t altera_build;
diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h
index a2c7139f2b32..7ab0db44720d 100644
--- a/drivers/net/ethernet/sfc/falcon/net_driver.h
+++ b/drivers/net/ethernet/sfc/falcon/net_driver.h
@@ -1057,7 +1057,7 @@ struct ef4_nic_type {
void (*finish_flush)(struct ef4_nic *efx);
void (*prepare_flr)(struct ef4_nic *efx);
void (*finish_flr)(struct ef4_nic *efx);
- size_t (*describe_stats)(struct ef4_nic *efx, u8 *names);
+ size_t (*describe_stats)(struct ef4_nic *efx, u8 **names);
size_t (*update_stats)(struct ef4_nic *efx, u64 *full_stats,
struct rtnl_link_stats64 *core_stats);
void (*start_stats)(struct ef4_nic *efx);
diff --git a/drivers/net/ethernet/sfc/falcon/nic.c b/drivers/net/ethernet/sfc/falcon/nic.c
index 78c851b5a56f..a6304686bc90 100644
--- a/drivers/net/ethernet/sfc/falcon/nic.c
+++ b/drivers/net/ethernet/sfc/falcon/nic.c
@@ -444,18 +444,15 @@ void ef4_nic_get_regs(struct ef4_nic *efx, void *buf)
* bits in the first @count bits of @mask for which a name is defined.
*/
size_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count,
- const unsigned long *mask, u8 *names)
+ const unsigned long *mask, u8 **names)
{
size_t visible = 0;
size_t index;
for_each_set_bit(index, mask, count) {
if (desc[index].name) {
- if (names) {
- strscpy(names, desc[index].name,
- ETH_GSTRING_LEN);
- names += ETH_GSTRING_LEN;
- }
+ if (names)
+ ethtool_puts(names, desc[index].name);
++visible;
}
}
@@ -511,14 +508,3 @@ void ef4_nic_update_stats(const struct ef4_hw_stat_desc *desc, size_t count,
}
}
}
-
-void ef4_nic_fix_nodesc_drop_stat(struct ef4_nic *efx, u64 *rx_nodesc_drops)
-{
- /* if down, or this is the first update after coming up */
- if (!(efx->net_dev->flags & IFF_UP) || !efx->rx_nodesc_drops_prev_state)
- efx->rx_nodesc_drops_while_down +=
- *rx_nodesc_drops - efx->rx_nodesc_drops_total;
- efx->rx_nodesc_drops_total = *rx_nodesc_drops;
- efx->rx_nodesc_drops_prev_state = !!(efx->net_dev->flags & IFF_UP);
- *rx_nodesc_drops -= efx->rx_nodesc_drops_while_down;
-}
diff --git a/drivers/net/ethernet/sfc/falcon/nic.h b/drivers/net/ethernet/sfc/falcon/nic.h
index ada6e036fd97..bc6ef937d0fe 100644
--- a/drivers/net/ethernet/sfc/falcon/nic.h
+++ b/drivers/net/ethernet/sfc/falcon/nic.h
@@ -477,7 +477,6 @@ void ef4_farch_finish_flr(struct ef4_nic *efx);
void falcon_start_nic_stats(struct ef4_nic *efx);
void falcon_stop_nic_stats(struct ef4_nic *efx);
int falcon_reset_xaui(struct ef4_nic *efx);
-void ef4_farch_dimension_resources(struct ef4_nic *efx, unsigned sram_lim_qw);
void ef4_farch_init_common(struct ef4_nic *efx);
void ef4_farch_rx_push_indir_table(struct ef4_nic *efx);
@@ -498,14 +497,10 @@ size_t ef4_nic_get_regs_len(struct ef4_nic *efx);
void ef4_nic_get_regs(struct ef4_nic *efx, void *buf);
size_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count,
- const unsigned long *mask, u8 *names);
+ const unsigned long *mask, u8 **names);
void ef4_nic_update_stats(const struct ef4_hw_stat_desc *desc, size_t count,
const unsigned long *mask, u64 *stats,
const void *dma_buf, bool accumulate);
-void ef4_nic_fix_nodesc_drop_stat(struct ef4_nic *efx, u64 *stat);
-
-#define EF4_MAX_FLUSH_TIME 5000
-
void ef4_farch_generate_event(struct ef4_nic *efx, unsigned int evq,
ef4_qword_t *event);
diff --git a/drivers/net/ethernet/sfc/falcon/tx.c b/drivers/net/ethernet/sfc/falcon/tx.c
index b9369483758c..e6e80b039ca2 100644
--- a/drivers/net/ethernet/sfc/falcon/tx.c
+++ b/drivers/net/ethernet/sfc/falcon/tx.c
@@ -40,14 +40,6 @@ static inline u8 *ef4_tx_get_copy_buffer(struct ef4_tx_queue *tx_queue,
return (u8 *)page_buf->addr + offset;
}
-u8 *ef4_tx_get_copy_buffer_limited(struct ef4_tx_queue *tx_queue,
- struct ef4_tx_buffer *buffer, size_t len)
-{
- if (len > EF4_TX_CB_SIZE)
- return NULL;
- return ef4_tx_get_copy_buffer(tx_queue, buffer);
-}
-
static void ef4_dequeue_buffer(struct ef4_tx_queue *tx_queue,
struct ef4_tx_buffer *buffer,
unsigned int *pkts_compl,
diff --git a/drivers/net/ethernet/sfc/falcon/tx.h b/drivers/net/ethernet/sfc/falcon/tx.h
index 2a88c59cbbbe..868ed8a861ab 100644
--- a/drivers/net/ethernet/sfc/falcon/tx.h
+++ b/drivers/net/ethernet/sfc/falcon/tx.h
@@ -15,9 +15,6 @@
unsigned int ef4_tx_limit_len(struct ef4_tx_queue *tx_queue,
dma_addr_t dma_addr, unsigned int len);
-u8 *ef4_tx_get_copy_buffer_limited(struct ef4_tx_queue *tx_queue,
- struct ef4_tx_buffer *buffer, size_t len);
-
int ef4_enqueue_skb_tso(struct ef4_tx_queue *tx_queue, struct sk_buff *skb,
bool *data_mapped);
diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
index 10709d828a63..50f097487b14 100644
--- a/drivers/net/ethernet/sfc/mae.c
+++ b/drivers/net/ethernet/sfc/mae.c
@@ -76,17 +76,6 @@ void efx_mae_mport_uplink(struct efx_nic *efx __always_unused, u32 *out)
*out = EFX_DWORD_VAL(mport);
}
-void efx_mae_mport_vf(struct efx_nic *efx __always_unused, u32 vf_id, u32 *out)
-{
- efx_dword_t mport;
-
- EFX_POPULATE_DWORD_3(mport,
- MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_FUNC,
- MAE_MPORT_SELECTOR_FUNC_PF_ID, MAE_MPORT_SELECTOR_FUNC_PF_ID_CALLER,
- MAE_MPORT_SELECTOR_FUNC_VF_ID, vf_id);
- *out = EFX_DWORD_VAL(mport);
-}
-
/* Constructs an mport selector from an mport ID, because they're not the same */
void efx_mae_mport_mport(struct efx_nic *efx __always_unused, u32 mport_id, u32 *out)
{
diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
index 8df30bc4f3ba..db79912c86d8 100644
--- a/drivers/net/ethernet/sfc/mae.h
+++ b/drivers/net/ethernet/sfc/mae.h
@@ -23,7 +23,6 @@ int efx_mae_free_mport(struct efx_nic *efx, u32 id);
void efx_mae_mport_wire(struct efx_nic *efx, u32 *out);
void efx_mae_mport_uplink(struct efx_nic *efx, u32 *out);
-void efx_mae_mport_vf(struct efx_nic *efx, u32 vf_id, u32 *out);
void efx_mae_mport_mport(struct efx_nic *efx, u32 mport_id, u32 *out);
int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id);
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 76578502226e..d461b1a6ce81 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -1051,15 +1051,6 @@ efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
cookie, false);
}
-int efx_mcdi_rpc_async_quiet(struct efx_nic *efx, unsigned int cmd,
- const efx_dword_t *inbuf, size_t inlen,
- size_t outlen, efx_mcdi_async_completer *complete,
- unsigned long cookie)
-{
- return _efx_mcdi_rpc_async(efx, cmd, inbuf, inlen, outlen, complete,
- cookie, true);
-}
-
int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
efx_dword_t *outbuf, size_t outlen,
size_t *outlen_actual)
@@ -1068,14 +1059,6 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
outlen_actual, false, NULL, NULL);
}
-int efx_mcdi_rpc_finish_quiet(struct efx_nic *efx, unsigned cmd, size_t inlen,
- efx_dword_t *outbuf, size_t outlen,
- size_t *outlen_actual)
-{
- return _efx_mcdi_rpc_finish(efx, cmd, inlen, outbuf, outlen,
- outlen_actual, true, NULL, NULL);
-}
-
void efx_mcdi_display_error(struct efx_nic *efx, unsigned cmd,
size_t inlen, efx_dword_t *outbuf,
size_t outlen, int rc)
@@ -1982,33 +1965,6 @@ efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, const u8 *mac, int *id_out)
}
-int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out)
-{
- MCDI_DECLARE_BUF(outbuf, MC_CMD_WOL_FILTER_GET_OUT_LEN);
- size_t outlen;
- int rc;
-
- rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_GET, NULL, 0,
- outbuf, sizeof(outbuf), &outlen);
- if (rc)
- goto fail;
-
- if (outlen < MC_CMD_WOL_FILTER_GET_OUT_LEN) {
- rc = -EIO;
- goto fail;
- }
-
- *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_GET_OUT_FILTER_ID);
-
- return 0;
-
-fail:
- *id_out = -1;
- netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
- return rc;
-}
-
-
int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_WOL_FILTER_REMOVE_IN_LEN);
@@ -2021,38 +1977,6 @@ int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
return rc;
}
-int efx_mcdi_flush_rxqs(struct efx_nic *efx)
-{
- struct efx_channel *channel;
- struct efx_rx_queue *rx_queue;
- MCDI_DECLARE_BUF(inbuf,
- MC_CMD_FLUSH_RX_QUEUES_IN_LEN(EFX_MAX_CHANNELS));
- int rc, count;
-
- BUILD_BUG_ON(EFX_MAX_CHANNELS >
- MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
-
- count = 0;
- efx_for_each_channel(channel, efx) {
- efx_for_each_channel_rx_queue(rx_queue, channel) {
- if (rx_queue->flush_pending) {
- rx_queue->flush_pending = false;
- atomic_dec(&efx->rxq_flush_pending);
- MCDI_SET_ARRAY_DWORD(
- inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
- count, efx_rx_queue_index(rx_queue));
- count++;
- }
- }
- }
-
- rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, inbuf,
- MC_CMD_FLUSH_RX_QUEUES_IN_LEN(count), NULL, 0, NULL);
- WARN_ON(rc < 0);
-
- return rc;
-}
-
int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
{
int rc;
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index ea612c619874..cdb17d7c147f 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -155,9 +155,6 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
efx_dword_t *outbuf, size_t outlen,
size_t *outlen_actual);
-int efx_mcdi_rpc_finish_quiet(struct efx_nic *efx, unsigned cmd,
- size_t inlen, efx_dword_t *outbuf,
- size_t outlen, size_t *outlen_actual);
typedef void efx_mcdi_async_completer(struct efx_nic *efx,
unsigned long cookie, int rc,
@@ -167,11 +164,6 @@ int efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
const efx_dword_t *inbuf, size_t inlen, size_t outlen,
efx_mcdi_async_completer *complete,
unsigned long cookie);
-int efx_mcdi_rpc_async_quiet(struct efx_nic *efx, unsigned int cmd,
- const efx_dword_t *inbuf, size_t inlen,
- size_t outlen,
- efx_mcdi_async_completer *complete,
- unsigned long cookie);
void efx_mcdi_display_error(struct efx_nic *efx, unsigned cmd,
size_t inlen, efx_dword_t *outbuf,
@@ -410,10 +402,8 @@ int efx_mcdi_handle_assertion(struct efx_nic *efx);
int efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, const u8 *mac,
int *id_out);
-int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
-int efx_mcdi_flush_rxqs(struct efx_nic *efx);
void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
void efx_mcdi_mac_start_stats(struct efx_nic *efx);
void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index b85c51cbe7f9..620ba6ef3514 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -193,6 +193,12 @@ struct efx_tx_buffer {
* @initialised: Has hardware queue been initialised?
* @timestamping: Is timestamping enabled for this channel?
* @xdp_tx: Is this an XDP tx queue?
+ * @old_complete_packets: Value of @complete_packets as of last
+ * efx_init_tx_queue()
+ * @old_complete_bytes: Value of @complete_bytes as of last
+ * efx_init_tx_queue()
+ * @old_tso_bursts: Value of @tso_bursts as of last efx_init_tx_queue()
+ * @old_tso_packets: Value of @tso_packets as of last efx_init_tx_queue()
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
* @old_write_count: The value of @write_count when last checked.
@@ -202,6 +208,20 @@ struct efx_tx_buffer {
* avoid cache-line ping-pong between the xmit path and the
* completion path.
* @merge_events: Number of TX merged completion events
+ * @bytes_compl: Number of bytes completed during this NAPI poll
+ * (efx_process_channel()). For BQL.
+ * @pkts_compl: Number of packets completed during this NAPI poll.
+ * @complete_packets: Number of packets completed since this struct was
+ * created. Only counts SKB packets, not XDP TX (it accumulates
+ * the same values that are reported to BQL).
+ * @complete_bytes: Number of bytes completed since this struct was
+ * created. For TSO, counts the superframe size, not the sizes of
+ * generated frames on the wire (i.e. the headers are only counted
+ * once)
+ * @complete_xdp_packets: Number of XDP TX packets completed since this
+ * struct was created.
+ * @complete_xdp_bytes: Number of XDP TX bytes completed since this
+ * struct was created.
* @completed_timestamp_major: Top part of the most recent tx timestamp.
* @completed_timestamp_minor: Low part of the most recent tx timestamp.
* @insert_count: Current insert pointer
@@ -232,6 +252,7 @@ struct efx_tx_buffer {
* @xmit_pending: Are any packets waiting to be pushed to the NIC
* @cb_packets: Number of times the TX copybreak feature has been used
* @notify_count: Count of notified descriptors to the NIC
+ * @tx_packets: Number of packets sent since this struct was created
* @empty_read_count: If the completion path has seen the queue as empty
* and the transmission path has not yet checked this, the value of
* @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0.
@@ -255,6 +276,10 @@ struct efx_tx_queue {
bool initialised;
bool timestamping;
bool xdp_tx;
+ unsigned long old_complete_packets;
+ unsigned long old_complete_bytes;
+ unsigned int old_tso_bursts;
+ unsigned int old_tso_packets;
/* Members used mainly on the completion path */
unsigned int read_count ____cacheline_aligned_in_smp;
@@ -262,6 +287,10 @@ struct efx_tx_queue {
unsigned int merge_events;
unsigned int bytes_compl;
unsigned int pkts_compl;
+ unsigned long complete_packets;
+ unsigned long complete_bytes;
+ unsigned long complete_xdp_packets;
+ unsigned long complete_xdp_bytes;
u32 completed_timestamp_major;
u32 completed_timestamp_minor;
@@ -370,6 +399,10 @@ struct efx_rx_page_state {
* @recycle_count: RX buffer recycle counter.
* @slow_fill: Timer used to defer efx_nic_generate_fill_event().
* @grant_work: workitem used to grant credits to the MAE if @grant_credits
+ * @rx_packets: Number of packets received since this struct was created
+ * @rx_bytes: Number of bytes received since this struct was created
+ * @old_rx_packets: Value of @rx_packets as of last efx_init_rx_queue()
+ * @old_rx_bytes: Value of @rx_bytes as of last efx_init_rx_queue()
* @xdp_rxq_info: XDP specific RX queue information.
* @xdp_rxq_info_valid: Is xdp_rxq_info valid data?.
*/
@@ -406,6 +439,9 @@ struct efx_rx_queue {
struct work_struct grant_work;
/* Statistics to supplement MAC stats */
unsigned long rx_packets;
+ unsigned long rx_bytes;
+ unsigned long old_rx_packets;
+ unsigned long old_rx_bytes;
struct xdp_rxq_info xdp_rxq_info;
bool xdp_rxq_info_valid;
};
@@ -451,10 +487,8 @@ enum efx_sync_events_state {
* @filter_work: Work item for efx_filter_rfs_expire()
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
* indexed by filter ID
- * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
* @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
* @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
- * @n_rx_mcast_mismatch: Count of unmatched multicast frames
* @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
* @n_rx_overlength: Count of RX_OVERLENGTH errors
* @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
@@ -468,6 +502,10 @@ enum efx_sync_events_state {
* @n_rx_xdp_redirect: Count of RX packets redirected to a different NIC by XDP
* @n_rx_mport_bad: Count of RX packets dropped because their ingress mport was
* not recognised
+ * @old_n_rx_hw_drops: Count of all RX packets dropped for any reason as of last
+ * efx_start_channels()
+ * @old_n_rx_hw_drop_overruns: Value of @n_rx_nodesc_trunc as of last
+ * efx_start_channels()
* @rx_pkt_n_frags: Number of fragments in next packet to be delivered by
* __efx_rx_packet(), or zero if there is none
* @rx_pkt_index: Ring index of first buffer for next packet to be delivered
@@ -511,7 +549,6 @@ struct efx_channel {
u32 *rps_flow_id;
#endif
- unsigned int n_rx_tobe_disc;
unsigned int n_rx_ip_hdr_chksum_err;
unsigned int n_rx_tcp_udp_chksum_err;
unsigned int n_rx_outer_ip_hdr_chksum_err;
@@ -519,7 +556,6 @@ struct efx_channel {
unsigned int n_rx_inner_ip_hdr_chksum_err;
unsigned int n_rx_inner_tcp_udp_chksum_err;
unsigned int n_rx_eth_crc_err;
- unsigned int n_rx_mcast_mismatch;
unsigned int n_rx_frm_trunc;
unsigned int n_rx_overlength;
unsigned int n_skbuff_leaks;
@@ -532,6 +568,9 @@ struct efx_channel {
unsigned int n_rx_xdp_redirect;
unsigned int n_rx_mport_bad;
+ unsigned int old_n_rx_hw_drops;
+ unsigned int old_n_rx_hw_drop_overruns;
+
unsigned int rx_pkt_n_frags;
unsigned int rx_pkt_index;
@@ -1369,7 +1408,7 @@ struct efx_nic_type {
int (*fini_dmaq)(struct efx_nic *efx);
void (*prepare_flr)(struct efx_nic *efx);
void (*finish_flr)(struct efx_nic *efx);
- size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
+ size_t (*describe_stats)(struct efx_nic *efx, u8 **names);
size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
struct rtnl_link_stats64 *core_stats);
size_t (*update_stats_atomic)(struct efx_nic *efx, u64 *full_stats,
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index a33ed473cc8a..80aa5e9c732a 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -299,18 +299,15 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf)
* bits in the first @count bits of @mask for which a name is defined.
*/
size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
- const unsigned long *mask, u8 *names)
+ const unsigned long *mask, u8 **names)
{
size_t visible = 0;
size_t index;
for_each_set_bit(index, mask, count) {
if (desc[index].name) {
- if (names) {
- strscpy(names, desc[index].name,
- ETH_GSTRING_LEN);
- names += ETH_GSTRING_LEN;
- }
+ if (names)
+ ethtool_puts(names, desc[index].name);
++visible;
}
}
diff --git a/drivers/net/ethernet/sfc/nic_common.h b/drivers/net/ethernet/sfc/nic_common.h
index 7ec4ac7b7ff5..821d91efda19 100644
--- a/drivers/net/ethernet/sfc/nic_common.h
+++ b/drivers/net/ethernet/sfc/nic_common.h
@@ -241,7 +241,7 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf);
#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
- const unsigned long *mask, u8 *names);
+ const unsigned long *mask, u8 **names);
int efx_nic_copy_stats(struct efx_nic *efx, __le64 *dest);
void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
const unsigned long *mask, u64 *stats,
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index aaacdcfa54ae..4c7222bf26be 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -399,7 +399,7 @@ static const unsigned long efx_ptp_stat_mask[] = {
[0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL,
};
-size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings)
+size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 **strings)
{
if (!efx->ptp_data)
return 0;
@@ -1800,11 +1800,6 @@ int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
return NETDEV_TX_OK;
}
-int efx_ptp_get_mode(struct efx_nic *efx)
-{
- return efx->ptp_data->mode;
-}
-
int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
unsigned int new_mode)
{
diff --git a/drivers/net/ethernet/sfc/ptp.h b/drivers/net/ethernet/sfc/ptp.h
index 6946203499ef..cb9b077921e8 100644
--- a/drivers/net/ethernet/sfc/ptp.h
+++ b/drivers/net/ethernet/sfc/ptp.h
@@ -26,12 +26,11 @@ int efx_ptp_get_ts_config(struct efx_nic *efx,
void efx_ptp_get_ts_info(struct efx_nic *efx,
struct kernel_ethtool_ts_info *ts_info);
bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
-int efx_ptp_get_mode(struct efx_nic *efx);
int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
unsigned int new_mode);
int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
-size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings);
+size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 **strings);
size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats);
void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev);
void __efx_rx_skb_attach_timestamp(struct efx_channel *channel,
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index f77a2d3ef37e..ffca82207e47 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -125,8 +125,6 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_rx_buffer *rx_buf;
- rx_queue->rx_packets++;
-
rx_buf = efx_rx_buffer(rx_queue, index);
rx_buf->flags |= flags;
@@ -394,6 +392,9 @@ void __efx_rx_packet(struct efx_channel *channel)
goto out;
}
+ rx_queue->rx_packets++;
+ rx_queue->rx_bytes += rx_buf->len;
+
if (!efx_do_xdp(efx, channel, rx_buf, &eh))
goto out;
diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c
index 0b7dc75c40f9..ab358fe13e1d 100644
--- a/drivers/net/ethernet/sfc/rx_common.c
+++ b/drivers/net/ethernet/sfc/rx_common.c
@@ -241,6 +241,9 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
rx_queue->page_recycle_failed = 0;
rx_queue->page_recycle_full = 0;
+ rx_queue->old_rx_packets = rx_queue->rx_packets;
+ rx_queue->old_rx_bytes = rx_queue->rx_bytes;
+
/* Initialise limit fields */
max_fill = efx->rxq_entries - EFX_RXD_HEAD_ROOM;
max_trigger =
diff --git a/drivers/net/ethernet/sfc/siena/ethtool_common.c b/drivers/net/ethernet/sfc/siena/ethtool_common.c
index 075fef64de68..eeee676fdca7 100644
--- a/drivers/net/ethernet/sfc/siena/ethtool_common.c
+++ b/drivers/net/ethernet/sfc/siena/ethtool_common.c
@@ -395,7 +395,7 @@ fail:
test->flags |= ETH_TEST_FL_FAILED;
}
-static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
+static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 **strings)
{
size_t n_stats = 0;
struct efx_channel *channel;
@@ -403,24 +403,22 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
efx_for_each_channel(channel, efx) {
if (efx_channel_has_tx_queues(channel)) {
n_stats++;
- if (strings != NULL) {
- snprintf(strings, ETH_GSTRING_LEN,
- "tx-%u.tx_packets",
- channel->tx_queue[0].queue /
- EFX_MAX_TXQ_PER_CHANNEL);
+ if (!strings)
+ continue;
- strings += ETH_GSTRING_LEN;
- }
+ ethtool_sprintf(strings, "tx-%u.tx_packets",
+ channel->tx_queue[0].queue /
+ EFX_MAX_TXQ_PER_CHANNEL);
}
}
efx_for_each_channel(channel, efx) {
if (efx_channel_has_rx_queue(channel)) {
n_stats++;
- if (strings != NULL) {
- snprintf(strings, ETH_GSTRING_LEN,
- "rx-%d.rx_packets", channel->channel);
- strings += ETH_GSTRING_LEN;
- }
+ if (!strings)
+ continue;
+
+ ethtool_sprintf(strings, "rx-%d.rx_packets",
+ channel->channel);
}
}
if (efx->xdp_tx_queue_count && efx->xdp_tx_queues) {
@@ -428,11 +426,11 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
for (xdp = 0; xdp < efx->xdp_tx_queue_count; xdp++) {
n_stats++;
- if (strings) {
- snprintf(strings, ETH_GSTRING_LEN,
- "tx-xdp-cpu-%hu.tx_packets", xdp);
- strings += ETH_GSTRING_LEN;
- }
+ if (!strings)
+ continue;
+
+ ethtool_sprintf(strings, "tx-xdp-cpu-%hu.tx_packets",
+ xdp);
}
}
@@ -464,15 +462,11 @@ void efx_siena_ethtool_get_strings(struct net_device *net_dev,
switch (string_set) {
case ETH_SS_STATS:
- strings += (efx->type->describe_stats(efx, strings) *
- ETH_GSTRING_LEN);
+ efx->type->describe_stats(efx, &strings);
for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++)
- strscpy(strings + i * ETH_GSTRING_LEN,
- efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
- strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
- strings += (efx_describe_per_queue_stats(efx, strings) *
- ETH_GSTRING_LEN);
- efx_siena_ptp_describe_stats(efx, strings);
+ ethtool_puts(&strings, efx_sw_stat_desc[i].name);
+ efx_describe_per_queue_stats(efx, &strings);
+ efx_siena_ptp_describe_stats(efx, &strings);
break;
case ETH_SS_TEST:
efx_ethtool_fill_self_tests(efx, NULL, strings, NULL);
diff --git a/drivers/net/ethernet/sfc/siena/net_driver.h b/drivers/net/ethernet/sfc/siena/net_driver.h
index 3fa7c652ae9b..9785eff10607 100644
--- a/drivers/net/ethernet/sfc/siena/net_driver.h
+++ b/drivers/net/ethernet/sfc/siena/net_driver.h
@@ -1307,7 +1307,7 @@ struct efx_nic_type {
void (*finish_flush)(struct efx_nic *efx);
void (*prepare_flr)(struct efx_nic *efx);
void (*finish_flr)(struct efx_nic *efx);
- size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
+ size_t (*describe_stats)(struct efx_nic *efx, u8 **names);
size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
struct rtnl_link_stats64 *core_stats);
size_t (*update_stats_atomic)(struct efx_nic *efx, u64 *full_stats,
diff --git a/drivers/net/ethernet/sfc/siena/nic.c b/drivers/net/ethernet/sfc/siena/nic.c
index 0ea0433a6230..32fce70085e3 100644
--- a/drivers/net/ethernet/sfc/siena/nic.c
+++ b/drivers/net/ethernet/sfc/siena/nic.c
@@ -449,20 +449,20 @@ void efx_siena_get_regs(struct efx_nic *efx, void *buf)
* Returns the number of visible statistics, i.e. the number of set
* bits in the first @count bits of @mask for which a name is defined.
*/
-size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
- const unsigned long *mask, u8 *names)
+size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc,
+ size_t count, const unsigned long *mask,
+ u8 **names)
{
size_t visible = 0;
size_t index;
for_each_set_bit(index, mask, count) {
if (desc[index].name) {
- if (names) {
- strscpy(names, desc[index].name,
- ETH_GSTRING_LEN);
- names += ETH_GSTRING_LEN;
- }
++visible;
+ if (!names)
+ continue;
+
+ ethtool_puts(names, desc[index].name);
}
}
diff --git a/drivers/net/ethernet/sfc/siena/nic_common.h b/drivers/net/ethernet/sfc/siena/nic_common.h
index 3af0405eeaa4..b7fbe198008d 100644
--- a/drivers/net/ethernet/sfc/siena/nic_common.h
+++ b/drivers/net/ethernet/sfc/siena/nic_common.h
@@ -239,8 +239,9 @@ void efx_siena_get_regs(struct efx_nic *efx, void *buf);
#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
-size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
- const unsigned long *mask, u8 *names);
+size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc,
+ size_t count, const unsigned long *mask,
+ u8 **names);
void efx_siena_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
const unsigned long *mask, u64 *stats,
const void *dma_buf, bool accumulate);
diff --git a/drivers/net/ethernet/sfc/siena/ptp.c b/drivers/net/ethernet/sfc/siena/ptp.c
index 85005196b4c5..062c77c92077 100644
--- a/drivers/net/ethernet/sfc/siena/ptp.c
+++ b/drivers/net/ethernet/sfc/siena/ptp.c
@@ -393,7 +393,7 @@ static const unsigned long efx_ptp_stat_mask[] = {
[0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL,
};
-size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 *strings)
+size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 **strings)
{
if (!efx->ptp_data)
return 0;
diff --git a/drivers/net/ethernet/sfc/siena/ptp.h b/drivers/net/ethernet/sfc/siena/ptp.h
index b6133e7c5608..54840036ab67 100644
--- a/drivers/net/ethernet/sfc/siena/ptp.h
+++ b/drivers/net/ethernet/sfc/siena/ptp.h
@@ -28,7 +28,7 @@ int efx_siena_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
unsigned int new_mode);
int efx_siena_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
void efx_siena_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
-size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 *strings);
+size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 **strings);
size_t efx_siena_ptp_update_stats(struct efx_nic *efx, u64 *stats);
void efx_siena_time_sync_event(struct efx_channel *channel, efx_qword_t *ev);
void __efx_siena_rx_skb_attach_timestamp(struct efx_channel *channel,
diff --git a/drivers/net/ethernet/sfc/siena/siena.c b/drivers/net/ethernet/sfc/siena/siena.c
index ca33dc08e555..49f0c8a1a90a 100644
--- a/drivers/net/ethernet/sfc/siena/siena.c
+++ b/drivers/net/ethernet/sfc/siena/siena.c
@@ -545,7 +545,7 @@ static const unsigned long siena_stat_mask[] = {
[0 ... BITS_TO_LONGS(SIENA_STAT_COUNT) - 1] = ~0UL,
};
-static size_t siena_describe_nic_stats(struct efx_nic *efx, u8 *names)
+static size_t siena_describe_nic_stats(struct efx_nic *efx, u8 **names)
{
return efx_siena_describe_stats(siena_stat_desc, SIENA_STAT_COUNT,
siena_stat_mask, names);
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index fe2d476028e7..4dff19b6ef17 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -49,14 +49,6 @@ static inline u8 *efx_tx_get_copy_buffer(struct efx_tx_queue *tx_queue,
return (u8 *)page_buf->addr + offset;
}
-u8 *efx_tx_get_copy_buffer_limited(struct efx_tx_queue *tx_queue,
- struct efx_tx_buffer *buffer, size_t len)
-{
- if (len > EFX_TX_CB_SIZE)
- return NULL;
- return efx_tx_get_copy_buffer(tx_queue, buffer);
-}
-
static void efx_tx_maybe_stop_queue(struct efx_tx_queue *txq1)
{
/* We need to consider all queues that the net core sees as one */
@@ -553,6 +545,7 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
void efx_xmit_done_single(struct efx_tx_queue *tx_queue)
{
+ unsigned int xdp_pkts_compl = 0, xdp_bytes_compl = 0;
unsigned int pkts_compl = 0, bytes_compl = 0;
unsigned int efv_pkts_compl = 0;
unsigned int read_ptr;
@@ -577,7 +570,8 @@ void efx_xmit_done_single(struct efx_tx_queue *tx_queue)
if (buffer->flags & EFX_TX_BUF_SKB)
finished = true;
efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl,
- &efv_pkts_compl);
+ &efv_pkts_compl, &xdp_pkts_compl,
+ &xdp_bytes_compl);
++tx_queue->read_count;
read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
@@ -585,6 +579,8 @@ void efx_xmit_done_single(struct efx_tx_queue *tx_queue)
tx_queue->pkts_compl += pkts_compl;
tx_queue->bytes_compl += bytes_compl;
+ tx_queue->complete_xdp_packets += xdp_pkts_compl;
+ tx_queue->complete_xdp_bytes += xdp_bytes_compl;
EFX_WARN_ON_PARANOID(pkts_compl + efv_pkts_compl != 1);
diff --git a/drivers/net/ethernet/sfc/tx.h b/drivers/net/ethernet/sfc/tx.h
index f2c4d2f89919..f882749af8c3 100644
--- a/drivers/net/ethernet/sfc/tx.h
+++ b/drivers/net/ethernet/sfc/tx.h
@@ -15,9 +15,6 @@
unsigned int efx_tx_limit_len(struct efx_tx_queue *tx_queue,
dma_addr_t dma_addr, unsigned int len);
-u8 *efx_tx_get_copy_buffer_limited(struct efx_tx_queue *tx_queue,
- struct efx_tx_buffer *buffer, size_t len);
-
/* What TXQ type will satisfy the checksum offloads required for this skb? */
static inline unsigned int efx_tx_csum_type_skb(struct sk_buff *skb)
{
diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
index 2adb132b2f7e..a22a0d634ffc 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -86,6 +86,11 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
tx_queue->completed_timestamp_major = 0;
tx_queue->completed_timestamp_minor = 0;
+ tx_queue->old_complete_packets = tx_queue->complete_packets;
+ tx_queue->old_complete_bytes = tx_queue->complete_bytes;
+ tx_queue->old_tso_bursts = tx_queue->tso_bursts;
+ tx_queue->old_tso_packets = tx_queue->tso_packets;
+
tx_queue->xdp_tx = efx_channel_is_xdp_tx(tx_queue->channel);
tx_queue->tso_version = 0;
@@ -109,12 +114,14 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
/* Free any buffers left in the ring */
while (tx_queue->read_count != tx_queue->write_count) {
+ unsigned int xdp_pkts_compl = 0, xdp_bytes_compl = 0;
unsigned int pkts_compl = 0, bytes_compl = 0;
unsigned int efv_pkts_compl = 0;
buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask];
efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl,
- &efv_pkts_compl);
+ &efv_pkts_compl, &xdp_pkts_compl,
+ &xdp_bytes_compl);
++tx_queue->read_count;
}
@@ -150,7 +157,9 @@ void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
struct efx_tx_buffer *buffer,
unsigned int *pkts_compl,
unsigned int *bytes_compl,
- unsigned int *efv_pkts_compl)
+ unsigned int *efv_pkts_compl,
+ unsigned int *xdp_pkts,
+ unsigned int *xdp_bytes)
{
if (buffer->unmap_len) {
struct device *dma_dev = &tx_queue->efx->pci_dev->dev;
@@ -195,6 +204,10 @@ void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
tx_queue->queue, tx_queue->read_count);
} else if (buffer->flags & EFX_TX_BUF_XDP) {
xdp_return_frame_rx_napi(buffer->xdpf);
+ if (xdp_pkts)
+ (*xdp_pkts)++;
+ if (xdp_bytes)
+ (*xdp_bytes) += buffer->xdpf->len;
}
buffer->len = 0;
@@ -210,7 +223,9 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
unsigned int index,
unsigned int *pkts_compl,
unsigned int *bytes_compl,
- unsigned int *efv_pkts_compl)
+ unsigned int *efv_pkts_compl,
+ unsigned int *xdp_pkts,
+ unsigned int *xdp_bytes)
{
struct efx_nic *efx = tx_queue->efx;
unsigned int stop_index, read_ptr;
@@ -230,7 +245,7 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
}
efx_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl,
- efv_pkts_compl);
+ efv_pkts_compl, xdp_pkts, xdp_bytes);
++tx_queue->read_count;
read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
@@ -253,15 +268,18 @@ void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue)
int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
{
unsigned int fill_level, pkts_compl = 0, bytes_compl = 0;
+ unsigned int xdp_pkts_compl = 0, xdp_bytes_compl = 0;
unsigned int efv_pkts_compl = 0;
struct efx_nic *efx = tx_queue->efx;
EFX_WARN_ON_ONCE_PARANOID(index > tx_queue->ptr_mask);
efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl,
- &efv_pkts_compl);
+ &efv_pkts_compl, &xdp_pkts_compl, &xdp_bytes_compl);
tx_queue->pkts_compl += pkts_compl;
tx_queue->bytes_compl += bytes_compl;
+ tx_queue->complete_xdp_packets += xdp_pkts_compl;
+ tx_queue->complete_xdp_bytes += xdp_bytes_compl;
if (pkts_compl + efv_pkts_compl > 1)
++tx_queue->merge_events;
@@ -290,6 +308,8 @@ int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
unsigned int insert_count)
{
+ unsigned int xdp_bytes_compl = 0;
+ unsigned int xdp_pkts_compl = 0;
unsigned int efv_pkts_compl = 0;
struct efx_tx_buffer *buffer;
unsigned int bytes_compl = 0;
@@ -300,7 +320,8 @@ void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
--tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl,
- &efv_pkts_compl);
+ &efv_pkts_compl, &xdp_pkts_compl,
+ &xdp_bytes_compl);
}
}
diff --git a/drivers/net/ethernet/sfc/tx_common.h b/drivers/net/ethernet/sfc/tx_common.h
index 1e9f42938aac..039eefafba23 100644
--- a/drivers/net/ethernet/sfc/tx_common.h
+++ b/drivers/net/ethernet/sfc/tx_common.h
@@ -20,7 +20,9 @@ void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
struct efx_tx_buffer *buffer,
unsigned int *pkts_compl,
unsigned int *bytes_compl,
- unsigned int *efv_pkts_compl);
+ unsigned int *efv_pkts_compl,
+ unsigned int *xdp_pkts,
+ unsigned int *xdp_bytes);
static inline bool efx_tx_buffer_in_use(struct efx_tx_buffer *buffer)
{
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index 98d0b561a057..4535579018c9 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -1273,7 +1273,7 @@ static void ioc3_set_multicast_list(struct net_device *dev)
static struct platform_driver ioc3eth_driver = {
.probe = ioc3eth_probe,
- .remove_new = ioc3eth_remove,
+ .remove = ioc3eth_remove,
.driver = {
.name = "ioc3-eth",
}
diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
index 18b6f93d875e..f7c3a5a766b7 100644
--- a/drivers/net/ethernet/sgi/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
@@ -864,7 +864,7 @@ static void meth_remove(struct platform_device *pdev)
static struct platform_driver meth_driver = {
.probe = meth_probe,
- .remove_new = meth_remove,
+ .remove = meth_remove,
.driver = {
.name = "meth",
}
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index a5e23e2da90f..9d1a83a5fa7e 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -2475,7 +2475,7 @@ static const struct dev_pm_ops smc_drv_pm_ops = {
static struct platform_driver smc_driver = {
.probe = smc_drv_probe,
- .remove_new = smc_drv_remove,
+ .remove = smc_drv_remove,
.driver = {
.name = CARDNAME,
.pm = &smc_drv_pm_ops,
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 74f1ccc96459..f539813878f5 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -2667,7 +2667,7 @@ MODULE_DEVICE_TABLE(acpi, smsc911x_acpi_match);
static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe,
- .remove_new = smsc911x_drv_remove,
+ .remove = smsc911x_drv_remove,
.driver = {
.name = SMSC_CHIPNAME,
.pm = SMSC911X_PM_OPS,
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 5ab8b81b84e6..dc99821c6226 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -2211,7 +2211,7 @@ MODULE_DEVICE_TABLE(acpi, netsec_acpi_ids);
static struct platform_driver netsec_driver = {
.probe = netsec_probe,
- .remove_new = netsec_remove,
+ .remove = netsec_remove,
.driver = {
.name = "netsec",
.pm = &netsec_pm_ops,
diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c
index eed24e67c5a6..66b3549636f8 100644
--- a/drivers/net/ethernet/socionext/sni_ave.c
+++ b/drivers/net/ethernet/socionext/sni_ave.c
@@ -1974,7 +1974,7 @@ MODULE_DEVICE_TABLE(of, of_ave_match);
static struct platform_driver ave_driver = {
.probe = ave_probe,
- .remove_new = ave_remove,
+ .remove = ave_remove,
.driver = {
.name = "ave",
.pm = AVE_PM_OPS,
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 05cc07b8f48c..6658536a4e17 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -228,6 +228,16 @@ config DWMAC_SUN8I
stmmac device driver. This driver is used for H3/A83T/A64
EMAC ethernet controller.
+config DWMAC_THEAD
+ tristate "T-HEAD dwmac support"
+ depends on OF && (ARCH_THEAD || COMPILE_TEST)
+ help
+ Support for ethernet controllers on T-HEAD RISC-V SoCs
+
+ This selects the T-HEAD platform specific glue layer support for
+ the stmmac device driver. This driver is used for T-HEAD TH1520
+ ethernet controller.
+
config DWMAC_IMX8
tristate "NXP IMX8 DWMAC support"
default ARCH_MXC
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index c2f0e91f6bf8..2389fd261344 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \
dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
- stmmac_xdp.o stmmac_est.o \
+ stmmac_xdp.o stmmac_est.o stmmac_fpe.o \
$(stmmac-y)
stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
@@ -28,6 +28,7 @@ obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
obj-$(CONFIG_DWMAC_STM32) += dwmac-stm32.o
obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
obj-$(CONFIG_DWMAC_SUN8I) += dwmac-sun8i.o
+obj-$(CONFIG_DWMAC_THEAD) += dwmac-thead.o
obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o
obj-$(CONFIG_DWMAC_INTEL_PLAT) += dwmac-intel-plat.o
obj-$(CONFIG_DWMAC_LOONGSON1) += dwmac-loongson1.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 684489156dce..1367fa5c9b8e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -549,8 +549,12 @@ extern const struct stmmac_desc_ops ndesc_ops;
struct mac_device_info;
extern const struct stmmac_hwtimestamp stmmac_ptp;
+extern const struct stmmac_hwtimestamp dwmac1000_ptp;
extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
+extern const struct ptp_clock_info stmmac_ptp_clock_ops;
+extern const struct ptp_clock_info dwmac1000_ptp_clock_ops;
+
struct mac_link {
u32 caps;
u32 speed_mask;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
index 643ee6d8d4dd..ef99ef3f1ab4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
@@ -135,7 +135,7 @@ MODULE_DEVICE_TABLE(of, anarion_dwmac_match);
static struct platform_driver anarion_dwmac_driver = {
.probe = anarion_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "anarion-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index ec924c6c76c6..83290e707df5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -479,7 +479,7 @@ MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
static struct platform_driver dwc_eth_dwmac_driver = {
.probe = dwc_eth_dwmac_probe,
- .remove_new = dwc_eth_dwmac_remove,
+ .remove = dwc_eth_dwmac_remove,
.driver = {
.name = "dwc-eth-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
index 598eff926815..b9218c07eb6b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -56,6 +56,7 @@ static const struct of_device_id dwmac_generic_match[] = {
{ .compatible = "snps,dwmac-3.610"},
{ .compatible = "snps,dwmac-3.70a"},
{ .compatible = "snps,dwmac-3.710"},
+ { .compatible = "snps,dwmac-3.72a"},
{ .compatible = "snps,dwmac-4.00"},
{ .compatible = "snps,dwmac-4.10a"},
{ .compatible = "snps,dwmac"},
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
index 6b65420e11b5..641f3cd019a3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, imx_dwmac_match);
static struct platform_driver imx_dwmac_driver = {
.probe = imx_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "imx-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
index 19c93b998fb3..066783d66422 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
@@ -370,7 +370,7 @@ MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
static struct platform_driver ingenic_mac_driver = {
.probe = ingenic_mac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "ingenic-mac",
.pm = pm_ptr(&ingenic_mac_pm_ops),
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
index d68f0c4e7835..d94f0a150e93 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
@@ -97,30 +97,38 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
dwmac->dev = &pdev->dev;
dwmac->tx_clk = NULL;
+ /*
+ * This cannot return NULL at this point because the driver’s
+ * compatibility with the device has already been validated in
+ * platform_match().
+ */
dwmac->data = device_get_match_data(&pdev->dev);
- if (dwmac->data) {
- if (dwmac->data->fix_mac_speed)
- plat_dat->fix_mac_speed = dwmac->data->fix_mac_speed;
-
- /* Enable TX clock */
- if (dwmac->data->tx_clk_en) {
- dwmac->tx_clk = devm_clk_get(&pdev->dev, "tx_clk");
- if (IS_ERR(dwmac->tx_clk))
- return PTR_ERR(dwmac->tx_clk);
-
- clk_prepare_enable(dwmac->tx_clk);
-
- /* Check and configure TX clock rate */
- rate = clk_get_rate(dwmac->tx_clk);
- if (dwmac->data->tx_clk_rate &&
- rate != dwmac->data->tx_clk_rate) {
- rate = dwmac->data->tx_clk_rate;
- ret = clk_set_rate(dwmac->tx_clk, rate);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to set tx_clk\n");
- return ret;
- }
+ if (dwmac->data->fix_mac_speed)
+ plat_dat->fix_mac_speed = dwmac->data->fix_mac_speed;
+
+ /* Enable TX clock */
+ if (dwmac->data->tx_clk_en) {
+ dwmac->tx_clk = devm_clk_get(&pdev->dev, "tx_clk");
+ if (IS_ERR(dwmac->tx_clk))
+ return PTR_ERR(dwmac->tx_clk);
+
+ ret = clk_prepare_enable(dwmac->tx_clk);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to enable tx_clk\n");
+ return ret;
+ }
+
+ /* Check and configure TX clock rate */
+ rate = clk_get_rate(dwmac->tx_clk);
+ if (dwmac->data->tx_clk_rate &&
+ rate != dwmac->data->tx_clk_rate) {
+ rate = dwmac->data->tx_clk_rate;
+ ret = clk_set_rate(dwmac->tx_clk, rate);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to set tx_clk\n");
+ goto err_tx_clk_disable;
}
}
@@ -133,7 +141,7 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev,
"Failed to set clk_ptp_ref\n");
- return ret;
+ goto err_tx_clk_disable;
}
}
}
@@ -149,12 +157,15 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
}
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- if (ret) {
- clk_disable_unprepare(dwmac->tx_clk);
- return ret;
- }
+ if (ret)
+ goto err_tx_clk_disable;
return 0;
+
+err_tx_clk_disable:
+ if (dwmac->data->tx_clk_en)
+ clk_disable_unprepare(dwmac->tx_clk);
+ return ret;
}
static void intel_eth_plat_remove(struct platform_device *pdev)
@@ -162,12 +173,13 @@ static void intel_eth_plat_remove(struct platform_device *pdev)
struct intel_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
stmmac_pltfr_remove(pdev);
- clk_disable_unprepare(dwmac->tx_clk);
+ if (dwmac->data->tx_clk_en)
+ clk_disable_unprepare(dwmac->tx_clk);
}
static struct platform_driver intel_eth_plat_driver = {
.probe = intel_eth_plat_probe,
- .remove_new = intel_eth_plat_remove,
+ .remove = intel_eth_plat_remove,
.driver = {
.name = "intel-eth-plat",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 83ad7c7935e3..48acba5eb178 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -451,7 +451,7 @@ static struct phylink_pcs *intel_mgbe_select_pcs(struct stmmac_priv *priv,
* should always be an XPCS. The original code would always
* return this if present.
*/
- return &priv->hw->xpcs->pcs;
+ return xpcs_to_phylink_pcs(priv->hw->xpcs);
}
static int intel_mgbe_common_data(struct pci_dev *pdev,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
index 4ba15873d5b1..61227dcf56dc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -499,7 +499,7 @@ MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match);
static struct platform_driver ipq806x_gmac_dwmac_driver = {
.probe = ipq806x_gmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "ipq806x-gmac-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
index 4c810d8f5bea..22653ffd2a04 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
@@ -72,7 +72,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match);
static struct platform_driver lpc18xx_dwmac_driver = {
.probe = lpc18xx_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "lpc18xx-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
index 2a9132d6d743..c9636832a570 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
@@ -589,9 +589,9 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
plat->mac_interface = priv_plat->phy_mode;
if (priv_plat->mac_wol)
- plat->flags |= STMMAC_FLAG_USE_PHY_WOL;
- else
plat->flags &= ~STMMAC_FLAG_USE_PHY_WOL;
+ else
+ plat->flags |= STMMAC_FLAG_USE_PHY_WOL;
plat->riwt_off = 1;
plat->maxmtu = ETH_DATA_LEN;
plat->host_dma_width = priv_plat->variant->dma_bit_mask;
@@ -699,7 +699,7 @@ MODULE_DEVICE_TABLE(of, mediatek_dwmac_match);
static struct platform_driver mediatek_dwmac_driver = {
.probe = mediatek_dwmac_probe,
- .remove_new = mediatek_dwmac_remove,
+ .remove = mediatek_dwmac_remove,
.driver = {
.name = "dwmac-mediatek",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
index a16bfa9089ea..5469fa1b429e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
@@ -78,7 +78,7 @@ MODULE_DEVICE_TABLE(of, meson6_dwmac_match);
static struct platform_driver meson6_dwmac_driver = {
.probe = meson6_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "meson6-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index b23944aa344e..9c2d62d133ad 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
static struct platform_driver meson8b_dwmac_driver = {
.probe = meson8b_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "meson8b-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 50073bdade46..8cb374668b74 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -2073,7 +2073,7 @@ MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
static struct platform_driver rk_gmac_dwmac_driver = {
.probe = rk_gmac_probe,
- .remove_new = rk_gmac_remove,
+ .remove = rk_gmac_remove,
.driver = {
.name = "rk_gmac-dwmac",
.pm = &rk_gmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c
index 59a7bd560f96..13634965bc19 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c
@@ -80,7 +80,7 @@ MODULE_DEVICE_TABLE(of, rzn1_dwmac_match);
static struct platform_driver rzn1_dwmac_driver = {
.probe = rzn1_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "rzn1-dwmac",
.of_match_table = rzn1_dwmac_match,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index fdb4c773ec98..16020b72dec8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -485,6 +485,9 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
plat_dat->pcs_init = socfpga_dwmac_pcs_init;
plat_dat->pcs_exit = socfpga_dwmac_pcs_exit;
plat_dat->select_pcs = socfpga_dwmac_select_pcs;
+ plat_dat->has_gmac = true;
+
+ plat_dat->riwt_off = 1;
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
@@ -582,7 +585,7 @@ MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
static struct platform_driver socfpga_dwmac_driver = {
.probe = socfpga_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "socfpga-dwmac",
.pm = &socfpga_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
index 4e1076faee0c..421666279dd3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
@@ -176,7 +176,7 @@ MODULE_DEVICE_TABLE(of, starfive_dwmac_match);
static struct platform_driver starfive_dwmac_driver = {
.probe = starfive_dwmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "starfive-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index 4445cddc4cbe..a6ff02d905a9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -358,7 +358,7 @@ MODULE_DEVICE_TABLE(of, sti_dwmac_match);
static struct platform_driver sti_dwmac_driver = {
.probe = sti_dwmac_probe,
- .remove_new = sti_dwmac_remove,
+ .remove = sti_dwmac_remove,
.driver = {
.name = "sti-dwmac",
.pm = &sti_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index c1732955a697..1e8bac665cc9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -675,7 +675,7 @@ MODULE_DEVICE_TABLE(of, stm32_dwmac_match);
static struct platform_driver stm32_dwmac_driver = {
.probe = stm32_dwmac_probe,
- .remove_new = stm32_dwmac_remove,
+ .remove = stm32_dwmac_remove,
.driver = {
.name = "stm32-dwmac",
.pm = &stm32_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 4a0ae92b3055..4b7b2582a120 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1343,7 +1343,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
static struct platform_driver sun8i_dwmac_driver = {
.probe = sun8i_dwmac_probe,
- .remove_new = sun8i_dwmac_remove,
+ .remove = sun8i_dwmac_remove,
.shutdown = sun8i_dwmac_shutdown,
.driver = {
.name = "dwmac-sun8i",
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
index 2653a9f0958c..9ae318436c4a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -172,7 +172,7 @@ MODULE_DEVICE_TABLE(of, sun7i_dwmac_match);
static struct platform_driver sun7i_dwmac_driver = {
.probe = sun7i_gmac_probe,
- .remove_new = stmmac_pltfr_remove,
+ .remove = stmmac_pltfr_remove,
.driver = {
.name = "sun7i-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
index 6fdd94c8919e..3827997d2132 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
@@ -381,7 +381,7 @@ static SIMPLE_DEV_PM_OPS(tegra_mgbe_pm_ops, tegra_mgbe_suspend, tegra_mgbe_resum
static struct platform_driver tegra_mgbe_driver = {
.probe = tegra_mgbe_probe,
- .remove_new = tegra_mgbe_remove,
+ .remove = tegra_mgbe_remove,
.driver = {
.name = "tegra-mgbe",
.pm = &tegra_mgbe_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
new file mode 100644
index 000000000000..dce84ed184e9
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * T-HEAD DWMAC platform driver
+ *
+ * Copyright (C) 2021 Alibaba Group Holding Limited.
+ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
+ *
+ */
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
+#include <linux/platform_device.h>
+
+#include "stmmac_platform.h"
+
+#define GMAC_CLK_EN 0x00
+#define GMAC_TX_CLK_EN BIT(1)
+#define GMAC_TX_CLK_N_EN BIT(2)
+#define GMAC_TX_CLK_OUT_EN BIT(3)
+#define GMAC_RX_CLK_EN BIT(4)
+#define GMAC_RX_CLK_N_EN BIT(5)
+#define GMAC_EPHY_REF_CLK_EN BIT(6)
+#define GMAC_RXCLK_DELAY_CTRL 0x04
+#define GMAC_RXCLK_BYPASS BIT(15)
+#define GMAC_RXCLK_INVERT BIT(14)
+#define GMAC_RXCLK_DELAY GENMASK(4, 0)
+#define GMAC_TXCLK_DELAY_CTRL 0x08
+#define GMAC_TXCLK_BYPASS BIT(15)
+#define GMAC_TXCLK_INVERT BIT(14)
+#define GMAC_TXCLK_DELAY GENMASK(4, 0)
+#define GMAC_PLLCLK_DIV 0x0c
+#define GMAC_PLLCLK_DIV_EN BIT(31)
+#define GMAC_PLLCLK_DIV_NUM GENMASK(7, 0)
+#define GMAC_GTXCLK_SEL 0x18
+#define GMAC_GTXCLK_SEL_PLL BIT(0)
+#define GMAC_INTF_CTRL 0x1c
+#define PHY_INTF_MASK BIT(0)
+#define PHY_INTF_RGMII FIELD_PREP(PHY_INTF_MASK, 1)
+#define PHY_INTF_MII_GMII FIELD_PREP(PHY_INTF_MASK, 0)
+#define GMAC_TXCLK_OEN 0x20
+#define TXCLK_DIR_MASK BIT(0)
+#define TXCLK_DIR_OUTPUT FIELD_PREP(TXCLK_DIR_MASK, 0)
+#define TXCLK_DIR_INPUT FIELD_PREP(TXCLK_DIR_MASK, 1)
+
+#define GMAC_GMII_RGMII_RATE 125000000
+#define GMAC_MII_RATE 25000000
+
+struct thead_dwmac {
+ struct plat_stmmacenet_data *plat;
+ void __iomem *apb_base;
+ struct device *dev;
+};
+
+static int thead_dwmac_set_phy_if(struct plat_stmmacenet_data *plat)
+{
+ struct thead_dwmac *dwmac = plat->bsp_priv;
+ u32 phyif;
+
+ switch (plat->mac_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ phyif = PHY_INTF_MII_GMII;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ phyif = PHY_INTF_RGMII;
+ break;
+ default:
+ dev_err(dwmac->dev, "unsupported phy interface %d\n",
+ plat->mac_interface);
+ return -EINVAL;
+ }
+
+ writel(phyif, dwmac->apb_base + GMAC_INTF_CTRL);
+ return 0;
+}
+
+static int thead_dwmac_set_txclk_dir(struct plat_stmmacenet_data *plat)
+{
+ struct thead_dwmac *dwmac = plat->bsp_priv;
+ u32 txclk_dir;
+
+ switch (plat->mac_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ txclk_dir = TXCLK_DIR_INPUT;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ txclk_dir = TXCLK_DIR_OUTPUT;
+ break;
+ default:
+ dev_err(dwmac->dev, "unsupported phy interface %d\n",
+ plat->mac_interface);
+ return -EINVAL;
+ }
+
+ writel(txclk_dir, dwmac->apb_base + GMAC_TXCLK_OEN);
+ return 0;
+}
+
+static void thead_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mode)
+{
+ struct plat_stmmacenet_data *plat;
+ struct thead_dwmac *dwmac = priv;
+ unsigned long rate;
+ u32 div, reg;
+
+ plat = dwmac->plat;
+
+ switch (plat->mac_interface) {
+ /* For MII, rxc/txc is provided by phy */
+ case PHY_INTERFACE_MODE_MII:
+ return;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ rate = clk_get_rate(plat->stmmac_clk);
+ if (!rate || rate % GMAC_GMII_RGMII_RATE != 0 ||
+ rate % GMAC_MII_RATE != 0) {
+ dev_err(dwmac->dev, "invalid gmac rate %ld\n", rate);
+ return;
+ }
+
+ writel(0, dwmac->apb_base + GMAC_PLLCLK_DIV);
+
+ switch (speed) {
+ case SPEED_1000:
+ div = rate / GMAC_GMII_RGMII_RATE;
+ break;
+ case SPEED_100:
+ div = rate / GMAC_MII_RATE;
+ break;
+ case SPEED_10:
+ div = rate * 10 / GMAC_MII_RATE;
+ break;
+ default:
+ dev_err(dwmac->dev, "invalid speed %u\n", speed);
+ return;
+ }
+
+ reg = FIELD_PREP(GMAC_PLLCLK_DIV_EN, 1) |
+ FIELD_PREP(GMAC_PLLCLK_DIV_NUM, div);
+ writel(reg, dwmac->apb_base + GMAC_PLLCLK_DIV);
+ break;
+ default:
+ dev_err(dwmac->dev, "unsupported phy interface %d\n",
+ plat->mac_interface);
+ return;
+ }
+}
+
+static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat)
+{
+ struct thead_dwmac *dwmac = plat->bsp_priv;
+ u32 reg;
+
+ switch (plat->mac_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ reg = GMAC_RX_CLK_EN | GMAC_TX_CLK_EN;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ /* use pll */
+ writel(GMAC_GTXCLK_SEL_PLL, dwmac->apb_base + GMAC_GTXCLK_SEL);
+ reg = GMAC_TX_CLK_EN | GMAC_TX_CLK_N_EN | GMAC_TX_CLK_OUT_EN |
+ GMAC_RX_CLK_EN | GMAC_RX_CLK_N_EN;
+ break;
+
+ default:
+ dev_err(dwmac->dev, "unsupported phy interface %d\n",
+ plat->mac_interface);
+ return -EINVAL;
+ }
+
+ writel(reg, dwmac->apb_base + GMAC_CLK_EN);
+ return 0;
+}
+
+static int thead_dwmac_init(struct platform_device *pdev, void *priv)
+{
+ struct thead_dwmac *dwmac = priv;
+ unsigned int reg;
+ int ret;
+
+ ret = thead_dwmac_set_phy_if(dwmac->plat);
+ if (ret)
+ return ret;
+
+ ret = thead_dwmac_set_txclk_dir(dwmac->plat);
+ if (ret)
+ return ret;
+
+ reg = readl(dwmac->apb_base + GMAC_RXCLK_DELAY_CTRL);
+ reg &= ~(GMAC_RXCLK_DELAY);
+ reg |= FIELD_PREP(GMAC_RXCLK_DELAY, 0);
+ writel(reg, dwmac->apb_base + GMAC_RXCLK_DELAY_CTRL);
+
+ reg = readl(dwmac->apb_base + GMAC_TXCLK_DELAY_CTRL);
+ reg &= ~(GMAC_TXCLK_DELAY);
+ reg |= FIELD_PREP(GMAC_TXCLK_DELAY, 0);
+ writel(reg, dwmac->apb_base + GMAC_TXCLK_DELAY_CTRL);
+
+ return thead_dwmac_enable_clk(dwmac->plat);
+}
+
+static int thead_dwmac_probe(struct platform_device *pdev)
+{
+ struct stmmac_resources stmmac_res;
+ struct plat_stmmacenet_data *plat;
+ struct thead_dwmac *dwmac;
+ void __iomem *apb;
+ int ret;
+
+ ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to get resources\n");
+
+ plat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
+ if (IS_ERR(plat))
+ return dev_err_probe(&pdev->dev, PTR_ERR(plat),
+ "dt configuration failed\n");
+
+ dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+ if (!dwmac)
+ return -ENOMEM;
+
+ apb = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(apb))
+ return dev_err_probe(&pdev->dev, PTR_ERR(apb),
+ "failed to remap gmac apb registers\n");
+
+ dwmac->dev = &pdev->dev;
+ dwmac->plat = plat;
+ dwmac->apb_base = apb;
+ plat->bsp_priv = dwmac;
+ plat->fix_mac_speed = thead_dwmac_fix_speed;
+ plat->init = thead_dwmac_init;
+
+ return devm_stmmac_pltfr_probe(pdev, plat, &stmmac_res);
+}
+
+static const struct of_device_id thead_dwmac_match[] = {
+ { .compatible = "thead,th1520-gmac" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, thead_dwmac_match);
+
+static struct platform_driver thead_dwmac_driver = {
+ .probe = thead_dwmac_probe,
+ .driver = {
+ .name = "thead-dwmac",
+ .pm = &stmmac_pltfr_pm_ops,
+ .of_match_table = thead_dwmac_match,
+ },
+};
+module_platform_driver(thead_dwmac_driver);
+
+MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
+MODULE_AUTHOR("Drew Fustini <drew@pdp7.com>");
+MODULE_DESCRIPTION("T-HEAD DWMAC platform driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
index a5a5cfa989c6..eccf7f537467 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
@@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(of, visconti_eth_dwmac_match);
static struct platform_driver visconti_eth_dwmac_driver = {
.probe = visconti_eth_dwmac_probe,
- .remove_new = visconti_eth_dwmac_remove,
+ .remove = visconti_eth_dwmac_remove,
.driver = {
.name = "visconti-eth-dwmac",
.of_match_table = visconti_eth_dwmac_match,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 4296ddda8aaa..600fea8f712f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -329,5 +329,17 @@ enum rtc_control {
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
#define GMAC_EXTHASH_BASE 0x500
+/* PTP and timestamping registers */
+
+#define GMAC3_X_ATSNS GENMASK(19, 16)
+#define GMAC3_X_ATSNS_SHIFT 16
+
+#define GMAC_PTP_TCR_ATSFC BIT(24)
+#define GMAC_PTP_TCR_ATSEN0 BIT(25)
+
+#define GMAC3_X_TIMESTAMP_STATUS 0x28
+#define GMAC_PTP_ATNR 0x30
+#define GMAC_PTP_ATSR 0x34
+
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
#endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index d413d76a8936..96bcda0856ec 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -18,6 +18,7 @@
#include <linux/io.h>
#include "stmmac.h"
#include "stmmac_pcs.h"
+#include "stmmac_ptp.h"
#include "dwmac1000.h"
static void dwmac1000_core_init(struct mac_device_info *hw,
@@ -551,3 +552,103 @@ int dwmac1000_setup(struct stmmac_priv *priv)
return 0;
}
+
+/* DWMAC 1000 HW Timestaming ops */
+
+void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
+{
+ u64 ns;
+
+ ns = readl(ptpaddr + GMAC_PTP_ATNR);
+ ns += readl(ptpaddr + GMAC_PTP_ATSR) * NSEC_PER_SEC;
+
+ *ptp_time = ns;
+}
+
+void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv)
+{
+ struct ptp_clock_event event;
+ u32 ts_status, num_snapshot;
+ unsigned long flags;
+ u64 ptp_time;
+ int i;
+
+ /* Clears the timestamp interrupt */
+ ts_status = readl(priv->ptpaddr + GMAC3_X_TIMESTAMP_STATUS);
+
+ if (!(priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN))
+ return;
+
+ num_snapshot = (ts_status & GMAC3_X_ATSNS) >> GMAC3_X_ATSNS_SHIFT;
+
+ for (i = 0; i < num_snapshot; i++) {
+ read_lock_irqsave(&priv->ptp_lock, flags);
+ stmmac_get_ptptime(priv, priv->ptpaddr, &ptp_time);
+ read_unlock_irqrestore(&priv->ptp_lock, flags);
+
+ event.type = PTP_CLOCK_EXTTS;
+ event.index = 0;
+ event.timestamp = ptp_time;
+ ptp_clock_event(priv->ptp_clock, &event);
+ }
+}
+
+/* DWMAC 1000 ptp_clock_info ops */
+
+static void dwmac1000_timestamp_interrupt_cfg(struct stmmac_priv *priv, bool en)
+{
+ void __iomem *ioaddr = priv->ioaddr;
+
+ u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
+
+ if (en)
+ intr_mask &= ~GMAC_INT_DISABLE_TIMESTAMP;
+ else
+ intr_mask |= GMAC_INT_DISABLE_TIMESTAMP;
+
+ writel(intr_mask, ioaddr + GMAC_INT_MASK);
+}
+
+int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ struct stmmac_priv *priv =
+ container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+ void __iomem *ptpaddr = priv->ptpaddr;
+ int ret = -EOPNOTSUPP;
+ u32 tcr_val;
+
+ switch (rq->type) {
+ case PTP_CLK_REQ_EXTTS:
+ mutex_lock(&priv->aux_ts_lock);
+ tcr_val = readl(ptpaddr + PTP_TCR);
+
+ if (on) {
+ tcr_val |= GMAC_PTP_TCR_ATSEN0;
+ tcr_val |= GMAC_PTP_TCR_ATSFC;
+ priv->plat->flags |= STMMAC_FLAG_EXT_SNAPSHOT_EN;
+ } else {
+ tcr_val &= ~GMAC_PTP_TCR_ATSEN0;
+ priv->plat->flags &= ~STMMAC_FLAG_EXT_SNAPSHOT_EN;
+ }
+
+ netdev_dbg(priv->dev, "Auxiliary Snapshot %s.\n",
+ on ? "enabled" : "disabled");
+ writel(tcr_val, ptpaddr + PTP_TCR);
+
+ /* wait for auxts fifo clear to finish */
+ ret = readl_poll_timeout(ptpaddr + PTP_TCR, tcr_val,
+ !(tcr_val & GMAC_PTP_TCR_ATSFC),
+ 10, 10000);
+
+ mutex_unlock(&priv->aux_ts_lock);
+
+ dwmac1000_timestamp_interrupt_cfg(priv, on);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index 93a78fd0737b..184d41a306af 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -44,6 +44,7 @@
#define GMAC_MDIO_DATA 0x00000204
#define GMAC_GPIO_STATUS 0x0000020C
#define GMAC_ARP_ADDR 0x00000210
+#define GMAC_EXT_CFG1 0x00000238
#define GMAC_ADDR_HIGH(reg) (0x300 + reg * 8)
#define GMAC_ADDR_LOW(reg) (0x304 + reg * 8)
#define GMAC_L3L4_CTRL(reg) (0x900 + (reg) * 0x30)
@@ -68,7 +69,6 @@
#define GMAC_RXQCTRL_TACPQE BIT(21)
#define GMAC_RXQCTRL_TACPQE_SHIFT 21
#define GMAC_RXQCTRL_FPRQ GENMASK(26, 24)
-#define GMAC_RXQCTRL_FPRQ_SHIFT 24
/* MAC Packet Filtering */
#define GMAC_PACKET_FILTER_PR BIT(0)
@@ -284,6 +284,10 @@ enum power_event {
#define GMAC_HW_FEAT_DVLAN BIT(5)
#define GMAC_HW_FEAT_NRVF GENMASK(2, 0)
+/* MAC extended config 1 */
+#define GMAC_CONFIG1_SAVE_EN BIT(24)
+#define GMAC_CONFIG1_SPLM(v) FIELD_PREP(GENMASK(9, 8), v)
+
/* GMAC GPIO Status reg */
#define GMAC_GPO0 BIT(16)
#define GMAC_GPO1 BIT(17)
@@ -389,8 +393,8 @@ static inline u32 mtl_chanx_base_addr(const struct dwmac4_addrs *addrs,
#define MTL_OP_MODE_EHFC BIT(7)
-#define MTL_OP_MODE_RTC_MASK 0x18
-#define MTL_OP_MODE_RTC_SHIFT 3
+#define MTL_OP_MODE_RTC_MASK GENMASK(1, 0)
+#define MTL_OP_MODE_RTC_SHIFT 0
#define MTL_OP_MODE_RTC_32 (1 << MTL_OP_MODE_RTC_SHIFT)
#define MTL_OP_MODE_RTC_64 0
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index e65a65666cc1..c25781874aa7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include "stmmac.h"
+#include "stmmac_fpe.h"
#include "stmmac_pcs.h"
#include "dwmac4.h"
#include "dwmac5.h"
@@ -1261,11 +1262,6 @@ const struct stmmac_ops dwmac410_ops = {
.set_arp_offload = dwmac4_set_arp_offload,
.config_l3_filter = dwmac4_config_l3_filter,
.config_l4_filter = dwmac4_config_l4_filter,
- .fpe_configure = dwmac5_fpe_configure,
- .fpe_send_mpacket = dwmac5_fpe_send_mpacket,
- .fpe_irq_status = dwmac5_fpe_irq_status,
- .fpe_get_add_frag_size = dwmac5_fpe_get_add_frag_size,
- .fpe_set_add_frag_size = dwmac5_fpe_set_add_frag_size,
.fpe_map_preemption_class = dwmac5_fpe_map_preemption_class,
.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
@@ -1316,11 +1312,6 @@ const struct stmmac_ops dwmac510_ops = {
.set_arp_offload = dwmac4_set_arp_offload,
.config_l3_filter = dwmac4_config_l3_filter,
.config_l4_filter = dwmac4_config_l4_filter,
- .fpe_configure = dwmac5_fpe_configure,
- .fpe_send_mpacket = dwmac5_fpe_send_mpacket,
- .fpe_irq_status = dwmac5_fpe_irq_status,
- .fpe_get_add_frag_size = dwmac5_fpe_get_add_frag_size,
- .fpe_set_add_frag_size = dwmac5_fpe_set_add_frag_size,
.fpe_map_preemption_class = dwmac5_fpe_map_preemption_class,
.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index e99401bcc1f8..a5fb31eb0192 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -118,6 +118,8 @@ static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x,
x->ipv4_pkt_rcvd++;
if (rdes1 & RDES1_IPV6_HEADER)
x->ipv6_pkt_rcvd++;
+ if (rdes1 & RDES1_IP_PAYLOAD_ERROR)
+ x->ip_payload_err++;
if (message_type == RDES_EXT_NO_PTP)
x->no_ptp_rx_msg_type_ext++;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h
index 6da070ccd737..1ce6f43d545a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h
@@ -95,7 +95,7 @@
#define RDES1_IPV4_HEADER BIT(4)
#define RDES1_IPV6_HEADER BIT(5)
#define RDES1_IP_CSUM_BYPASSED BIT(6)
-#define RDES1_IP_CSUM_ERROR BIT(7)
+#define RDES1_IP_PAYLOAD_ERROR BIT(7)
#define RDES1_PTP_MSG_TYPE_MASK GENMASK(11, 8)
#define RDES1_PTP_PACKET_TYPE BIT(12)
#define RDES1_PTP_VER BIT(13)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 77b35abc6f6f..0cb84a0041a4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -274,7 +274,7 @@ static void dwmac4_dma_rx_chan_op_mode(struct stmmac_priv *priv,
} else {
pr_debug("GMAC: disable RX SF mode (threshold %d)\n", mode);
mtl_rx_op &= ~MTL_OP_MODE_RSF;
- mtl_rx_op &= MTL_OP_MODE_RTC_MASK;
+ mtl_rx_op &= ~MTL_OP_MODE_RTC_MASK;
if (mode <= 32)
mtl_rx_op |= MTL_OP_MODE_RTC_32;
else if (mode <= 64)
@@ -343,7 +343,7 @@ static void dwmac4_dma_tx_chan_op_mode(struct stmmac_priv *priv,
} else {
pr_debug("GMAC: disabling TX SF (threshold %d)\n", mode);
mtl_tx_op &= ~MTL_OP_MODE_TSF;
- mtl_tx_op &= MTL_OP_MODE_TTC_MASK;
+ mtl_tx_op &= ~MTL_OP_MODE_TTC_MASK;
/* Set the transmit threshold */
if (mode <= 32)
mtl_tx_op |= MTL_OP_MODE_TTC_32;
@@ -534,6 +534,11 @@ static void dwmac4_enable_sph(struct stmmac_priv *priv, void __iomem *ioaddr,
value |= GMAC_CONFIG_HDSMS_256; /* Segment max 256 bytes */
writel(value, ioaddr + GMAC_EXT_CONFIG);
+ value = readl(ioaddr + GMAC_EXT_CFG1);
+ value |= GMAC_CONFIG1_SPLM(1); /* Split mode set to L2OFST */
+ value |= GMAC_CONFIG1_SAVE_EN; /* Enable Split AV mode */
+ writel(value, ioaddr + GMAC_EXT_CFG1);
+
value = readl(ioaddr + DMA_CHAN_CONTROL(dwmac4_addrs, chan));
if (en)
value |= DMA_CONTROL_SPH;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
index 0d185e54eb7e..57c03d491774 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -185,8 +185,6 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
x->rx_buf_unav_irq++;
if (unlikely(intr_status & DMA_CHAN_STATUS_RPS))
x->rx_process_stopped_irq++;
- if (unlikely(intr_status & DMA_CHAN_STATUS_RWT))
- x->rx_watchdog_irq++;
if (unlikely(intr_status & DMA_CHAN_STATUS_ETI))
x->tx_early_irq++;
if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) {
@@ -198,6 +196,10 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
ret = tx_hard_error;
}
}
+
+ if (unlikely(intr_status & DMA_CHAN_STATUS_RWT))
+ x->rx_watchdog_irq++;
+
/* TX/RX NORMAL interrupts */
if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
u64_stats_update_begin(&stats->syncp);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
index 08add508db84..1c431b918719 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
@@ -572,153 +572,3 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
writel(val, ioaddr + MAC_PPS_CONTROL);
return 0;
}
-
-void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
- u32 num_txq, u32 num_rxq,
- bool tx_enable, bool pmac_enable)
-{
- u32 value;
-
- if (tx_enable) {
- cfg->fpe_csr = EFPE;
- value = readl(ioaddr + GMAC_RXQ_CTRL1);
- value &= ~GMAC_RXQCTRL_FPRQ;
- value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
- writel(value, ioaddr + GMAC_RXQ_CTRL1);
- } else {
- cfg->fpe_csr = 0;
- }
- writel(cfg->fpe_csr, ioaddr + MAC_FPE_CTRL_STS);
-
- value = readl(ioaddr + GMAC_INT_EN);
-
- if (pmac_enable) {
- if (!(value & GMAC_INT_FPE_EN)) {
- /* Dummy read to clear any pending masked interrupts */
- readl(ioaddr + MAC_FPE_CTRL_STS);
-
- value |= GMAC_INT_FPE_EN;
- }
- } else {
- value &= ~GMAC_INT_FPE_EN;
- }
-
- writel(value, ioaddr + GMAC_INT_EN);
-}
-
-int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev)
-{
- u32 value;
- int status;
-
- status = FPE_EVENT_UNKNOWN;
-
- /* Reads from the MAC_FPE_CTRL_STS register should only be performed
- * here, since the status flags of MAC_FPE_CTRL_STS are "clear on read"
- */
- value = readl(ioaddr + MAC_FPE_CTRL_STS);
-
- if (value & TRSP) {
- status |= FPE_EVENT_TRSP;
- netdev_dbg(dev, "FPE: Respond mPacket is transmitted\n");
- }
-
- if (value & TVER) {
- status |= FPE_EVENT_TVER;
- netdev_dbg(dev, "FPE: Verify mPacket is transmitted\n");
- }
-
- if (value & RRSP) {
- status |= FPE_EVENT_RRSP;
- netdev_dbg(dev, "FPE: Respond mPacket is received\n");
- }
-
- if (value & RVER) {
- status |= FPE_EVENT_RVER;
- netdev_dbg(dev, "FPE: Verify mPacket is received\n");
- }
-
- return status;
-}
-
-void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
- enum stmmac_mpacket_type type)
-{
- u32 value = cfg->fpe_csr;
-
- if (type == MPACKET_VERIFY)
- value |= SVER;
- else if (type == MPACKET_RESPONSE)
- value |= SRSP;
-
- writel(value, ioaddr + MAC_FPE_CTRL_STS);
-}
-
-int dwmac5_fpe_get_add_frag_size(const void __iomem *ioaddr)
-{
- return FIELD_GET(DWMAC5_ADD_FRAG_SZ, readl(ioaddr + MTL_FPE_CTRL_STS));
-}
-
-void dwmac5_fpe_set_add_frag_size(void __iomem *ioaddr, u32 add_frag_size)
-{
- u32 value;
-
- value = readl(ioaddr + MTL_FPE_CTRL_STS);
- writel(u32_replace_bits(value, add_frag_size, DWMAC5_ADD_FRAG_SZ),
- ioaddr + MTL_FPE_CTRL_STS);
-}
-
-#define ALG_ERR_MSG "TX algorithm SP is not suitable for one-to-many mapping"
-#define WEIGHT_ERR_MSG "TXQ weight %u differs across other TXQs in TC: [%u]"
-
-int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
- struct netlink_ext_ack *extack, u32 pclass)
-{
- u32 val, offset, count, queue_weight, preemptible_txqs = 0;
- struct stmmac_priv *priv = netdev_priv(ndev);
- u32 num_tc = ndev->num_tc;
-
- if (!pclass)
- goto update_mapping;
-
- /* DWMAC CORE4+ can not program TC:TXQ mapping to hardware.
- *
- * Synopsys Databook:
- * "The number of Tx DMA channels is equal to the number of Tx queues,
- * and is direct one-to-one mapping."
- */
- for (u32 tc = 0; tc < num_tc; tc++) {
- count = ndev->tc_to_txq[tc].count;
- offset = ndev->tc_to_txq[tc].offset;
-
- if (pclass & BIT(tc))
- preemptible_txqs |= GENMASK(offset + count - 1, offset);
-
- /* This is 1:1 mapping, go to next TC */
- if (count == 1)
- continue;
-
- if (priv->plat->tx_sched_algorithm == MTL_TX_ALGORITHM_SP) {
- NL_SET_ERR_MSG_MOD(extack, ALG_ERR_MSG);
- return -EINVAL;
- }
-
- queue_weight = priv->plat->tx_queues_cfg[offset].weight;
-
- for (u32 i = 1; i < count; i++) {
- if (priv->plat->tx_queues_cfg[offset + i].weight !=
- queue_weight) {
- NL_SET_ERR_MSG_FMT_MOD(extack, WEIGHT_ERR_MSG,
- queue_weight, tc);
- return -EINVAL;
- }
- }
- }
-
-update_mapping:
- val = readl(priv->ioaddr + MTL_FPE_CTRL_STS);
- writel(u32_replace_bits(val, preemptible_txqs, DWMAC5_PREEMPTION_CLASS),
- priv->ioaddr + MTL_FPE_CTRL_STS);
-
- return 0;
-}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.h b/drivers/net/ethernet/stmicro/stmmac/dwmac5.h
index 6c6eb6790e83..00b151b3b688 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.h
@@ -11,15 +11,6 @@
#define PRTYEN BIT(1)
#define TMOUTEN BIT(0)
-#define MAC_FPE_CTRL_STS 0x00000234
-#define TRSP BIT(19)
-#define TVER BIT(18)
-#define RRSP BIT(17)
-#define RVER BIT(16)
-#define SRSP BIT(2)
-#define SVER BIT(1)
-#define EFPE BIT(0)
-
#define MAC_PPS_CONTROL 0x00000b70
#define PPS_MAXIDX(x) ((((x) + 1) * 8) - 1)
#define PPS_MINIDX(x) ((x) * 8)
@@ -39,12 +30,6 @@
#define MAC_PPSx_INTERVAL(x) (0x00000b88 + ((x) * 0x10))
#define MAC_PPSx_WIDTH(x) (0x00000b8c + ((x) * 0x10))
-#define MTL_FPE_CTRL_STS 0x00000c90
-/* Preemption Classification */
-#define DWMAC5_PREEMPTION_CLASS GENMASK(15, 8)
-/* Additional Fragment Size of preempted frames */
-#define DWMAC5_ADD_FRAG_SZ GENMASK(1, 0)
-
#define MTL_RXP_CONTROL_STATUS 0x00000ca0
#define RXPI BIT(31)
#define NPE GENMASK(23, 16)
@@ -108,16 +93,5 @@ int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
struct stmmac_pps_cfg *cfg, bool enable,
u32 sub_second_inc, u32 systime_flags);
-void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
- u32 num_txq, u32 num_rxq,
- bool tx_enable, bool pmac_enable);
-void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,
- struct stmmac_fpe_cfg *cfg,
- enum stmmac_mpacket_type type);
-int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev);
-int dwmac5_fpe_get_add_frag_size(const void __iomem *ioaddr);
-void dwmac5_fpe_set_add_frag_size(void __iomem *ioaddr, u32 add_frag_size);
-int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
- struct netlink_ext_ack *extack, u32 pclass);
#endif /* __DWMAC5_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index 6a2c7d22df1e..a04a79003692 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -84,8 +84,7 @@
#define XGMAC_MCBCQEN BIT(15)
#define XGMAC_MCBCQ GENMASK(11, 8)
#define XGMAC_MCBCQ_SHIFT 8
-#define XGMAC_RQ GENMASK(7, 4)
-#define XGMAC_RQ_SHIFT 4
+#define XGMAC_FPRQ GENMASK(7, 4)
#define XGMAC_UPQ GENMASK(3, 0)
#define XGMAC_UPQ_SHIFT 0
#define XGMAC_RXQ_CTRL2 0x000000a8
@@ -96,6 +95,7 @@
#define XGMAC_LPIIS BIT(5)
#define XGMAC_PMTIS BIT(4)
#define XGMAC_INT_EN 0x000000b4
+#define XGMAC_FPEIE BIT(15)
#define XGMAC_TSIE BIT(12)
#define XGMAC_LPIIE BIT(5)
#define XGMAC_PMTIE BIT(4)
@@ -193,8 +193,6 @@
#define XGMAC_MDIO_ADDR 0x00000200
#define XGMAC_MDIO_DATA 0x00000204
#define XGMAC_MDIO_C22P 0x00000220
-#define XGMAC_FPE_CTRL_STS 0x00000280
-#define XGMAC_EFPE BIT(0)
#define XGMAC_ADDRx_HIGH(x) (0x00000300 + (x) * 0x8)
#define XGMAC_ADDR_MAX 32
#define XGMAC_AE BIT(31)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index f519d43738b0..9a60a6e8f633 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -8,6 +8,7 @@
#include <linux/crc32.h>
#include <linux/iopoll.h>
#include "stmmac.h"
+#include "stmmac_fpe.h"
#include "stmmac_ptp.h"
#include "dwxlgmac2.h"
#include "dwxgmac2.h"
@@ -1504,32 +1505,6 @@ static void dwxgmac2_set_arp_offload(struct mac_device_info *hw, bool en,
writel(value, ioaddr + XGMAC_RX_CONFIG);
}
-static void dwxgmac3_fpe_configure(void __iomem *ioaddr,
- struct stmmac_fpe_cfg *cfg,
- u32 num_txq, u32 num_rxq,
- bool tx_enable, bool pmac_enable)
-{
- u32 value;
-
- if (!tx_enable) {
- value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
-
- value &= ~XGMAC_EFPE;
-
- writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
- return;
- }
-
- value = readl(ioaddr + XGMAC_RXQ_CTRL1);
- value &= ~XGMAC_RQ;
- value |= (num_rxq - 1) << XGMAC_RQ_SHIFT;
- writel(value, ioaddr + XGMAC_RXQ_CTRL1);
-
- value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
- value |= XGMAC_EFPE;
- writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
-}
-
const struct stmmac_ops dwxgmac210_ops = {
.core_init = dwxgmac2_core_init,
.set_mac = dwxgmac2_set_mac,
@@ -1570,7 +1545,7 @@ const struct stmmac_ops dwxgmac210_ops = {
.config_l3_filter = dwxgmac2_config_l3_filter,
.config_l4_filter = dwxgmac2_config_l4_filter,
.set_arp_offload = dwxgmac2_set_arp_offload,
- .fpe_configure = dwxgmac3_fpe_configure,
+ .fpe_map_preemption_class = dwxgmac3_fpe_map_preemption_class,
};
static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
@@ -1627,7 +1602,7 @@ const struct stmmac_ops dwxlgmac2_ops = {
.config_l3_filter = dwxgmac2_config_l3_filter,
.config_l4_filter = dwxgmac2_config_l4_filter,
.set_arp_offload = dwxgmac2_set_arp_offload,
- .fpe_configure = dwxgmac3_fpe_configure,
+ .fpe_map_preemption_class = dwxgmac3_fpe_map_preemption_class,
};
int dwxgmac2_setup(struct stmmac_priv *priv)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 88cce28b2f98..a72d336a8350 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -6,6 +6,7 @@
#include "common.h"
#include "stmmac.h"
+#include "stmmac_fpe.h"
#include "stmmac_ptp.h"
#include "stmmac_est.h"
@@ -112,6 +113,7 @@ static const struct stmmac_hwif_entry {
const void *dma;
const void *mac;
const void *hwtimestamp;
+ const void *ptp;
const void *mode;
const void *tc;
const void *mmc;
@@ -132,7 +134,8 @@ static const struct stmmac_hwif_entry {
.desc = NULL,
.dma = &dwmac100_dma_ops,
.mac = &dwmac100_ops,
- .hwtimestamp = &stmmac_ptp,
+ .hwtimestamp = &dwmac1000_ptp,
+ .ptp = &dwmac1000_ptp_clock_ops,
.mode = NULL,
.tc = NULL,
.mmc = &dwmac_mmc_ops,
@@ -150,7 +153,8 @@ static const struct stmmac_hwif_entry {
.desc = NULL,
.dma = &dwmac1000_dma_ops,
.mac = &dwmac1000_ops,
- .hwtimestamp = &stmmac_ptp,
+ .hwtimestamp = &dwmac1000_ptp,
+ .ptp = &dwmac1000_ptp_clock_ops,
.mode = NULL,
.tc = NULL,
.mmc = &dwmac_mmc_ops,
@@ -170,6 +174,7 @@ static const struct stmmac_hwif_entry {
.dma = &dwmac4_dma_ops,
.mac = &dwmac4_ops,
.hwtimestamp = &stmmac_ptp,
+ .ptp = &stmmac_ptp_clock_ops,
.mode = NULL,
.tc = &dwmac4_tc_ops,
.mmc = &dwmac_mmc_ops,
@@ -185,11 +190,13 @@ static const struct stmmac_hwif_entry {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
.est_off = EST_GMAC4_OFFSET,
+ .fpe_reg = &dwmac5_fpe_reg,
},
.desc = &dwmac4_desc_ops,
.dma = &dwmac4_dma_ops,
.mac = &dwmac410_ops,
.hwtimestamp = &stmmac_ptp,
+ .ptp = &stmmac_ptp_clock_ops,
.mode = &dwmac4_ring_mode_ops,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
@@ -205,11 +212,13 @@ static const struct stmmac_hwif_entry {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
.est_off = EST_GMAC4_OFFSET,
+ .fpe_reg = &dwmac5_fpe_reg,
},
.desc = &dwmac4_desc_ops,
.dma = &dwmac410_dma_ops,
.mac = &dwmac410_ops,
.hwtimestamp = &stmmac_ptp,
+ .ptp = &stmmac_ptp_clock_ops,
.mode = &dwmac4_ring_mode_ops,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
@@ -225,11 +234,13 @@ static const struct stmmac_hwif_entry {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
.est_off = EST_GMAC4_OFFSET,
+ .fpe_reg = &dwmac5_fpe_reg,
},
.desc = &dwmac4_desc_ops,
.dma = &dwmac410_dma_ops,
.mac = &dwmac510_ops,
.hwtimestamp = &stmmac_ptp,
+ .ptp = &stmmac_ptp_clock_ops,
.mode = &dwmac4_ring_mode_ops,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
@@ -246,11 +257,13 @@ static const struct stmmac_hwif_entry {
.ptp_off = PTP_XGMAC_OFFSET,
.mmc_off = MMC_XGMAC_OFFSET,
.est_off = EST_XGMAC_OFFSET,
+ .fpe_reg = &dwxgmac3_fpe_reg,
},
.desc = &dwxgmac210_desc_ops,
.dma = &dwxgmac210_dma_ops,
.mac = &dwxgmac210_ops,
.hwtimestamp = &stmmac_ptp,
+ .ptp = &stmmac_ptp_clock_ops,
.mode = NULL,
.tc = &dwxgmac_tc_ops,
.mmc = &dwxgmac_mmc_ops,
@@ -267,11 +280,13 @@ static const struct stmmac_hwif_entry {
.ptp_off = PTP_XGMAC_OFFSET,
.mmc_off = MMC_XGMAC_OFFSET,
.est_off = EST_XGMAC_OFFSET,
+ .fpe_reg = &dwxgmac3_fpe_reg,
},
.desc = &dwxgmac210_desc_ops,
.dma = &dwxgmac210_dma_ops,
.mac = &dwxlgmac2_ops,
.hwtimestamp = &stmmac_ptp,
+ .ptp = &stmmac_ptp_clock_ops,
.mode = NULL,
.tc = &dwxgmac_tc_ops,
.mmc = &dwxgmac_mmc_ops,
@@ -353,8 +368,11 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
mac->est = mac->est ? : entry->est;
priv->hw = mac;
+ priv->fpe_cfg.reg = entry->regs.fpe_reg;
priv->ptpaddr = priv->ioaddr + entry->regs.ptp_off;
priv->mmcaddr = priv->ioaddr + entry->regs.mmc_off;
+ memcpy(&priv->ptp_clock_ops, entry->ptp,
+ sizeof(struct ptp_clock_info));
if (entry->est)
priv->estaddr = priv->ioaddr + entry->regs.est_off;
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index d5a9f01ecac5..64f8ed67dcc4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -420,15 +420,6 @@ struct stmmac_ops {
bool en, bool udp, bool sa, bool inv,
u32 match);
void (*set_arp_offload)(struct mac_device_info *hw, bool en, u32 addr);
- void (*fpe_configure)(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
- u32 num_txq, u32 num_rxq,
- bool tx_enable, bool pmac_enable);
- void (*fpe_send_mpacket)(void __iomem *ioaddr,
- struct stmmac_fpe_cfg *cfg,
- enum stmmac_mpacket_type type);
- int (*fpe_irq_status)(void __iomem *ioaddr, struct net_device *dev);
- int (*fpe_get_add_frag_size)(const void __iomem *ioaddr);
- void (*fpe_set_add_frag_size)(void __iomem *ioaddr, u32 add_frag_size);
int (*fpe_map_preemption_class)(struct net_device *ndev,
struct netlink_ext_ack *extack,
u32 pclass);
@@ -530,16 +521,6 @@ struct stmmac_ops {
stmmac_do_callback(__priv, mac, config_l4_filter, __args)
#define stmmac_set_arp_offload(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, set_arp_offload, __args)
-#define stmmac_fpe_configure(__priv, __args...) \
- stmmac_do_void_callback(__priv, mac, fpe_configure, __args)
-#define stmmac_fpe_send_mpacket(__priv, __args...) \
- stmmac_do_void_callback(__priv, mac, fpe_send_mpacket, __args)
-#define stmmac_fpe_irq_status(__priv, __args...) \
- stmmac_do_callback(__priv, mac, fpe_irq_status, __args)
-#define stmmac_fpe_get_add_frag_size(__priv, __args...) \
- stmmac_do_callback(__priv, mac, fpe_get_add_frag_size, __args)
-#define stmmac_fpe_set_add_frag_size(__priv, __args...) \
- stmmac_do_void_callback(__priv, mac, fpe_set_add_frag_size, __args)
#define stmmac_fpe_map_preemption_class(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, fpe_map_preemption_class, __args)
@@ -678,6 +659,7 @@ struct stmmac_est_ops {
stmmac_do_void_callback(__priv, est, irq_status, __args)
struct stmmac_regs_off {
+ const struct stmmac_fpe_reg *fpe_reg;
u32 ptp_off;
u32 mmc_off;
u32 est_off;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index ea135203ff2e..1d86439b8a14 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -146,21 +146,13 @@ struct stmmac_channel {
u32 index;
};
-/* FPE link-partner hand-shaking mPacket type */
-enum stmmac_mpacket_type {
- MPACKET_VERIFY = 0,
- MPACKET_RESPONSE = 1,
-};
-
-#define STMMAC_FPE_MM_MAX_VERIFY_RETRIES 3
-#define STMMAC_FPE_MM_MAX_VERIFY_TIME_MS 128
-
struct stmmac_fpe_cfg {
/* Serialize access to MAC Merge state between ethtool requests
* and link state updates.
*/
spinlock_t lock;
+ const struct stmmac_fpe_reg *reg;
u32 fpe_csr; /* MAC_FPE_CTRL_STS reg cache */
enum ethtool_mm_verify_status status;
@@ -420,7 +412,6 @@ bool stmmac_eee_init(struct stmmac_priv *priv);
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt);
int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size);
int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled);
-void stmmac_fpe_apply(struct stmmac_priv *priv);
static inline bool stmmac_xdp_is_enabled(struct stmmac_priv *priv)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 2a37592a6281..1d77389ce953 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -17,9 +17,9 @@
#include <linux/net_tstamp.h>
#include "stmmac.h"
+#include "stmmac_fpe.h"
#include "dwmac_dma.h"
#include "dwxgmac2.h"
-#include "dwmac5.h"
#define REG_SPACE_SIZE 0x1060
#define GMAC4_REG_SPACE_SIZE 0x116C
@@ -1271,7 +1271,7 @@ static int stmmac_get_mm(struct net_device *ndev,
unsigned long flags;
u32 frag_size;
- if (!priv->dma_cap.fpesel)
+ if (!stmmac_fpe_supported(priv))
return -EOPNOTSUPP;
spin_lock_irqsave(&priv->fpe_cfg.lock, flags);
@@ -1294,7 +1294,7 @@ static int stmmac_get_mm(struct net_device *ndev,
else
state->tx_active = false;
- frag_size = stmmac_fpe_get_add_frag_size(priv, priv->ioaddr);
+ frag_size = stmmac_fpe_get_add_frag_size(priv);
state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(frag_size);
spin_unlock_irqrestore(&priv->fpe_cfg.lock, flags);
@@ -1329,7 +1329,7 @@ static int stmmac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
if (!cfg->verify_enabled)
fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
- stmmac_fpe_set_add_frag_size(priv, priv->ioaddr, frag_size);
+ stmmac_fpe_set_add_frag_size(priv, frag_size);
stmmac_fpe_apply(priv);
spin_unlock_irqrestore(&fpe_cfg->lock, flags);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
new file mode 100644
index 000000000000..3a4bee029c7f
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Furong Xu <0x1207@gmail.com>
+ * stmmac FPE(802.3 Qbu) handling
+ */
+#include "stmmac.h"
+#include "stmmac_fpe.h"
+#include "dwmac4.h"
+#include "dwmac5.h"
+#include "dwxgmac2.h"
+
+#define GMAC5_MAC_FPE_CTRL_STS 0x00000234
+#define XGMAC_MAC_FPE_CTRL_STS 0x00000280
+
+#define GMAC5_MTL_FPE_CTRL_STS 0x00000c90
+#define XGMAC_MTL_FPE_CTRL_STS 0x00001090
+/* Preemption Classification */
+#define FPE_MTL_PREEMPTION_CLASS GENMASK(15, 8)
+/* Additional Fragment Size of preempted frames */
+#define FPE_MTL_ADD_FRAG_SZ GENMASK(1, 0)
+
+#define STMMAC_MAC_FPE_CTRL_STS_TRSP BIT(19)
+#define STMMAC_MAC_FPE_CTRL_STS_TVER BIT(18)
+#define STMMAC_MAC_FPE_CTRL_STS_RRSP BIT(17)
+#define STMMAC_MAC_FPE_CTRL_STS_RVER BIT(16)
+#define STMMAC_MAC_FPE_CTRL_STS_SRSP BIT(2)
+#define STMMAC_MAC_FPE_CTRL_STS_SVER BIT(1)
+#define STMMAC_MAC_FPE_CTRL_STS_EFPE BIT(0)
+
+/* FPE link-partner hand-shaking mPacket type */
+enum stmmac_mpacket_type {
+ MPACKET_VERIFY = 0,
+ MPACKET_RESPONSE = 1,
+};
+
+struct stmmac_fpe_reg {
+ const u32 mac_fpe_reg; /* offset of MAC_FPE_CTRL_STS */
+ const u32 mtl_fpe_reg; /* offset of MTL_FPE_CTRL_STS */
+ const u32 rxq_ctrl1_reg; /* offset of MAC_RxQ_Ctrl1 */
+ const u32 fprq_mask; /* Frame Preemption Residue Queue */
+ const u32 int_en_reg; /* offset of MAC_Interrupt_Enable */
+ const u32 int_en_bit; /* Frame Preemption Interrupt Enable */
+};
+
+bool stmmac_fpe_supported(struct stmmac_priv *priv)
+{
+ return priv->dma_cap.fpesel && priv->fpe_cfg.reg &&
+ priv->hw->mac->fpe_map_preemption_class;
+}
+
+static void stmmac_fpe_configure(struct stmmac_priv *priv, bool tx_enable,
+ bool pmac_enable)
+{
+ struct stmmac_fpe_cfg *cfg = &priv->fpe_cfg;
+ const struct stmmac_fpe_reg *reg = cfg->reg;
+ u32 num_rxq = priv->plat->rx_queues_to_use;
+ void __iomem *ioaddr = priv->ioaddr;
+ u32 value;
+
+ if (tx_enable) {
+ cfg->fpe_csr = STMMAC_MAC_FPE_CTRL_STS_EFPE;
+ value = readl(ioaddr + reg->rxq_ctrl1_reg);
+ value &= ~reg->fprq_mask;
+ /* Keep this SHIFT, FIELD_PREP() expects a constant mask :-/ */
+ value |= (num_rxq - 1) << __ffs(reg->fprq_mask);
+ writel(value, ioaddr + reg->rxq_ctrl1_reg);
+ } else {
+ cfg->fpe_csr = 0;
+ }
+ writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg);
+
+ value = readl(ioaddr + reg->int_en_reg);
+
+ if (pmac_enable) {
+ if (!(value & reg->int_en_bit)) {
+ /* Dummy read to clear any pending masked interrupts */
+ readl(ioaddr + reg->mac_fpe_reg);
+
+ value |= reg->int_en_bit;
+ }
+ } else {
+ value &= ~reg->int_en_bit;
+ }
+
+ writel(value, ioaddr + reg->int_en_reg);
+}
+
+static void stmmac_fpe_send_mpacket(struct stmmac_priv *priv,
+ enum stmmac_mpacket_type type)
+{
+ const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+ void __iomem *ioaddr = priv->ioaddr;
+ u32 value = priv->fpe_cfg.fpe_csr;
+
+ if (type == MPACKET_VERIFY)
+ value |= STMMAC_MAC_FPE_CTRL_STS_SVER;
+ else if (type == MPACKET_RESPONSE)
+ value |= STMMAC_MAC_FPE_CTRL_STS_SRSP;
+
+ writel(value, ioaddr + reg->mac_fpe_reg);
+}
+
+static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
+{
+ struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
+
+ /* This is interrupt context, just spin_lock() */
+ spin_lock(&fpe_cfg->lock);
+
+ if (!fpe_cfg->pmac_enabled || status == FPE_EVENT_UNKNOWN)
+ goto unlock_out;
+
+ /* LP has sent verify mPacket */
+ if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER)
+ stmmac_fpe_send_mpacket(priv, MPACKET_RESPONSE);
+
+ /* Local has sent verify mPacket */
+ if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER &&
+ fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
+ fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
+
+ /* LP has sent response mPacket */
+ if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP &&
+ fpe_cfg->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
+ fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
+
+unlock_out:
+ spin_unlock(&fpe_cfg->lock);
+}
+
+void stmmac_fpe_irq_status(struct stmmac_priv *priv)
+{
+ const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+ void __iomem *ioaddr = priv->ioaddr;
+ struct net_device *dev = priv->dev;
+ int status = FPE_EVENT_UNKNOWN;
+ u32 value;
+
+ /* Reads from the MAC_FPE_CTRL_STS register should only be performed
+ * here, since the status flags of MAC_FPE_CTRL_STS are "clear on read"
+ */
+ value = readl(ioaddr + reg->mac_fpe_reg);
+
+ if (value & STMMAC_MAC_FPE_CTRL_STS_TRSP) {
+ status |= FPE_EVENT_TRSP;
+ netdev_dbg(dev, "FPE: Respond mPacket is transmitted\n");
+ }
+
+ if (value & STMMAC_MAC_FPE_CTRL_STS_TVER) {
+ status |= FPE_EVENT_TVER;
+ netdev_dbg(dev, "FPE: Verify mPacket is transmitted\n");
+ }
+
+ if (value & STMMAC_MAC_FPE_CTRL_STS_RRSP) {
+ status |= FPE_EVENT_RRSP;
+ netdev_dbg(dev, "FPE: Respond mPacket is received\n");
+ }
+
+ if (value & STMMAC_MAC_FPE_CTRL_STS_RVER) {
+ status |= FPE_EVENT_RVER;
+ netdev_dbg(dev, "FPE: Verify mPacket is received\n");
+ }
+
+ stmmac_fpe_event_status(priv, status);
+}
+
+/**
+ * stmmac_fpe_verify_timer - Timer for MAC Merge verification
+ * @t: timer_list struct containing private info
+ *
+ * Verify the MAC Merge capability in the local TX direction, by
+ * transmitting Verify mPackets up to 3 times. Wait until link
+ * partner responds with a Response mPacket, otherwise fail.
+ */
+static void stmmac_fpe_verify_timer(struct timer_list *t)
+{
+ struct stmmac_fpe_cfg *fpe_cfg = from_timer(fpe_cfg, t, verify_timer);
+ struct stmmac_priv *priv = container_of(fpe_cfg, struct stmmac_priv,
+ fpe_cfg);
+ unsigned long flags;
+ bool rearm = false;
+
+ spin_lock_irqsave(&fpe_cfg->lock, flags);
+
+ switch (fpe_cfg->status) {
+ case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+ case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+ if (fpe_cfg->verify_retries != 0) {
+ stmmac_fpe_send_mpacket(priv, MPACKET_VERIFY);
+ rearm = true;
+ } else {
+ fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
+ }
+
+ fpe_cfg->verify_retries--;
+ break;
+
+ case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+ stmmac_fpe_configure(priv, true, true);
+ break;
+
+ default:
+ break;
+ }
+
+ if (rearm) {
+ mod_timer(&fpe_cfg->verify_timer,
+ jiffies + msecs_to_jiffies(fpe_cfg->verify_time));
+ }
+
+ spin_unlock_irqrestore(&fpe_cfg->lock, flags);
+}
+
+static void stmmac_fpe_verify_timer_arm(struct stmmac_fpe_cfg *fpe_cfg)
+{
+ if (fpe_cfg->pmac_enabled && fpe_cfg->tx_enabled &&
+ fpe_cfg->verify_enabled &&
+ fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
+ fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
+ timer_setup(&fpe_cfg->verify_timer, stmmac_fpe_verify_timer, 0);
+ mod_timer(&fpe_cfg->verify_timer, jiffies);
+ }
+}
+
+void stmmac_fpe_init(struct stmmac_priv *priv)
+{
+ priv->fpe_cfg.verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
+ priv->fpe_cfg.verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
+ priv->fpe_cfg.status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+ timer_setup(&priv->fpe_cfg.verify_timer, stmmac_fpe_verify_timer, 0);
+ spin_lock_init(&priv->fpe_cfg.lock);
+
+ if ((!priv->fpe_cfg.reg || !priv->hw->mac->fpe_map_preemption_class) &&
+ priv->dma_cap.fpesel)
+ dev_info(priv->device, "FPE is not supported by driver.\n");
+}
+
+void stmmac_fpe_apply(struct stmmac_priv *priv)
+{
+ struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
+
+ /* If verification is disabled, configure FPE right away.
+ * Otherwise let the timer code do it.
+ */
+ if (!fpe_cfg->verify_enabled) {
+ stmmac_fpe_configure(priv, fpe_cfg->tx_enabled,
+ fpe_cfg->pmac_enabled);
+ } else {
+ fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
+ fpe_cfg->verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
+
+ if (netif_running(priv->dev))
+ stmmac_fpe_verify_timer_arm(fpe_cfg);
+ }
+}
+
+void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
+{
+ struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
+ unsigned long flags;
+
+ timer_shutdown_sync(&fpe_cfg->verify_timer);
+
+ spin_lock_irqsave(&fpe_cfg->lock, flags);
+
+ if (is_up && fpe_cfg->pmac_enabled) {
+ /* VERIFY process requires pmac enabled when NIC comes up */
+ stmmac_fpe_configure(priv, false, true);
+
+ /* New link => maybe new partner => new verification process */
+ stmmac_fpe_apply(priv);
+ } else {
+ /* No link => turn off EFPE */
+ stmmac_fpe_configure(priv, false, false);
+ }
+
+ spin_unlock_irqrestore(&fpe_cfg->lock, flags);
+}
+
+int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv)
+{
+ const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+ void __iomem *ioaddr = priv->ioaddr;
+
+ return FIELD_GET(FPE_MTL_ADD_FRAG_SZ, readl(ioaddr + reg->mtl_fpe_reg));
+}
+
+void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size)
+{
+ const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg;
+ void __iomem *ioaddr = priv->ioaddr;
+ u32 value;
+
+ value = readl(ioaddr + reg->mtl_fpe_reg);
+ writel(u32_replace_bits(value, add_frag_size, FPE_MTL_ADD_FRAG_SZ),
+ ioaddr + reg->mtl_fpe_reg);
+}
+
+#define ALG_ERR_MSG "TX algorithm SP is not suitable for one-to-many mapping"
+#define WEIGHT_ERR_MSG "TXQ weight %u differs across other TXQs in TC: [%u]"
+
+int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
+ struct netlink_ext_ack *extack, u32 pclass)
+{
+ u32 val, offset, count, queue_weight, preemptible_txqs = 0;
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int num_tc = netdev_get_num_tc(ndev);
+
+ if (!pclass)
+ goto update_mapping;
+
+ /* DWMAC CORE4+ can not program TC:TXQ mapping to hardware.
+ *
+ * Synopsys Databook:
+ * "The number of Tx DMA channels is equal to the number of Tx queues,
+ * and is direct one-to-one mapping."
+ */
+ for (u32 tc = 0; tc < num_tc; tc++) {
+ count = ndev->tc_to_txq[tc].count;
+ offset = ndev->tc_to_txq[tc].offset;
+
+ if (pclass & BIT(tc))
+ preemptible_txqs |= GENMASK(offset + count - 1, offset);
+
+ /* This is 1:1 mapping, go to next TC */
+ if (count == 1)
+ continue;
+
+ if (priv->plat->tx_sched_algorithm == MTL_TX_ALGORITHM_SP) {
+ NL_SET_ERR_MSG_MOD(extack, ALG_ERR_MSG);
+ return -EINVAL;
+ }
+
+ queue_weight = priv->plat->tx_queues_cfg[offset].weight;
+
+ for (u32 i = 1; i < count; i++) {
+ if (priv->plat->tx_queues_cfg[offset + i].weight !=
+ queue_weight) {
+ NL_SET_ERR_MSG_FMT_MOD(extack, WEIGHT_ERR_MSG,
+ queue_weight, tc);
+ return -EINVAL;
+ }
+ }
+ }
+
+update_mapping:
+ val = readl(priv->ioaddr + GMAC5_MTL_FPE_CTRL_STS);
+ writel(u32_replace_bits(val, preemptible_txqs, FPE_MTL_PREEMPTION_CLASS),
+ priv->ioaddr + GMAC5_MTL_FPE_CTRL_STS);
+
+ return 0;
+}
+
+int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev,
+ struct netlink_ext_ack *extack, u32 pclass)
+{
+ u32 val, offset, count, preemptible_txqs = 0;
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int num_tc = netdev_get_num_tc(ndev);
+
+ if (!num_tc) {
+ /* Restore default TC:Queue mapping */
+ for (u32 i = 0; i < priv->plat->tx_queues_to_use; i++) {
+ val = readl(priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(i));
+ writel(u32_replace_bits(val, i, XGMAC_Q2TCMAP),
+ priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(i));
+ }
+ }
+
+ /* Synopsys Databook:
+ * "All Queues within a traffic class are selected in a round robin
+ * fashion (when packets are available) when the traffic class is
+ * selected by the scheduler for packet transmission. This is true for
+ * any of the scheduling algorithms."
+ */
+ for (u32 tc = 0; tc < num_tc; tc++) {
+ count = ndev->tc_to_txq[tc].count;
+ offset = ndev->tc_to_txq[tc].offset;
+
+ if (pclass & BIT(tc))
+ preemptible_txqs |= GENMASK(offset + count - 1, offset);
+
+ for (u32 i = 0; i < count; i++) {
+ val = readl(priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(offset + i));
+ writel(u32_replace_bits(val, tc, XGMAC_Q2TCMAP),
+ priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(offset + i));
+ }
+ }
+
+ val = readl(priv->ioaddr + XGMAC_MTL_FPE_CTRL_STS);
+ writel(u32_replace_bits(val, preemptible_txqs, FPE_MTL_PREEMPTION_CLASS),
+ priv->ioaddr + XGMAC_MTL_FPE_CTRL_STS);
+
+ return 0;
+}
+
+const struct stmmac_fpe_reg dwmac5_fpe_reg = {
+ .mac_fpe_reg = GMAC5_MAC_FPE_CTRL_STS,
+ .mtl_fpe_reg = GMAC5_MTL_FPE_CTRL_STS,
+ .rxq_ctrl1_reg = GMAC_RXQ_CTRL1,
+ .fprq_mask = GMAC_RXQCTRL_FPRQ,
+ .int_en_reg = GMAC_INT_EN,
+ .int_en_bit = GMAC_INT_FPE_EN,
+};
+
+const struct stmmac_fpe_reg dwxgmac3_fpe_reg = {
+ .mac_fpe_reg = XGMAC_MAC_FPE_CTRL_STS,
+ .mtl_fpe_reg = XGMAC_MTL_FPE_CTRL_STS,
+ .rxq_ctrl1_reg = XGMAC_RXQ_CTRL1,
+ .fprq_mask = XGMAC_FPRQ,
+ .int_en_reg = XGMAC_INT_EN,
+ .int_en_bit = XGMAC_FPEIE,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
new file mode 100644
index 000000000000..b884eac7142d
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Furong Xu <0x1207@gmail.com>
+ * stmmac FPE(802.3 Qbu) handling
+ */
+#ifndef _STMMAC_FPE_H_
+#define _STMMAC_FPE_H_
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#define STMMAC_FPE_MM_MAX_VERIFY_RETRIES 3
+#define STMMAC_FPE_MM_MAX_VERIFY_TIME_MS 128
+
+struct stmmac_priv;
+
+void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up);
+bool stmmac_fpe_supported(struct stmmac_priv *priv);
+void stmmac_fpe_init(struct stmmac_priv *priv);
+void stmmac_fpe_apply(struct stmmac_priv *priv);
+void stmmac_fpe_irq_status(struct stmmac_priv *priv);
+int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv);
+void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size);
+
+int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
+ struct netlink_ext_ack *extack, u32 pclass);
+int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev,
+ struct netlink_ext_ack *extack, u32 pclass);
+
+extern const struct stmmac_fpe_reg dwmac5_fpe_reg;
+extern const struct stmmac_fpe_reg dwxgmac3_fpe_reg;
+
+#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
index 5ef52ef2698f..0f59aa982604 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
@@ -18,9 +18,22 @@
#include "dwmac4.h"
#include "stmmac.h"
+#define STMMAC_HWTS_CFG_MASK (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | \
+ PTP_TCR_TSINIT | PTP_TCR_TSUPDT | \
+ PTP_TCR_TSCTRLSSR | PTP_TCR_SNAPTYPSEL_1 | \
+ PTP_TCR_TSIPV4ENA | PTP_TCR_TSIPV6ENA | \
+ PTP_TCR_TSEVNTENA | PTP_TCR_TSMSTRENA | \
+ PTP_TCR_TSVER2ENA | PTP_TCR_TSIPENA | \
+ PTP_TCR_TSTRIG | PTP_TCR_TSENALL)
+
static void config_hw_tstamping(void __iomem *ioaddr, u32 data)
{
- writel(data, ioaddr + PTP_TCR);
+ u32 regval = readl(ioaddr + PTP_TCR);
+
+ regval &= ~STMMAC_HWTS_CFG_MASK;
+ regval |= data;
+
+ writel(regval, ioaddr + PTP_TCR);
}
static void config_sub_second_increment(void __iomem *ioaddr,
@@ -269,3 +282,14 @@ const struct stmmac_hwtimestamp stmmac_ptp = {
.timestamp_interrupt = timestamp_interrupt,
.hwtstamp_correct_latency = hwtstamp_correct_latency,
};
+
+const struct stmmac_hwtimestamp dwmac1000_ptp = {
+ .config_hw_tstamping = config_hw_tstamping,
+ .init_systime = init_systime,
+ .config_sub_second_increment = config_sub_second_increment,
+ .config_addend = config_addend,
+ .adjust_systime = adjust_systime,
+ .get_systime = get_systime,
+ .get_ptptime = dwmac1000_get_ptptime,
+ .timestamp_interrupt = dwmac1000_timestamp_interrupt,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 208dbc68aaf9..9b262cdad60b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -43,6 +43,7 @@
#include <net/pkt_cls.h>
#include <net/xdp_sock_drv.h>
#include "stmmac_ptp.h"
+#include "stmmac_fpe.h"
#include "stmmac.h"
#include "stmmac_xdp.h"
#include <linux/reset.h>
@@ -966,35 +967,6 @@ static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
/* Nothing to do, xpcs_config() handles everything */
}
-static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
-{
- struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
- unsigned long flags;
-
- timer_shutdown_sync(&fpe_cfg->verify_timer);
-
- spin_lock_irqsave(&fpe_cfg->lock, flags);
-
- if (is_up && fpe_cfg->pmac_enabled) {
- /* VERIFY process requires pmac enabled when NIC comes up */
- stmmac_fpe_configure(priv, priv->ioaddr, fpe_cfg,
- priv->plat->tx_queues_to_use,
- priv->plat->rx_queues_to_use,
- false, true);
-
- /* New link => maybe new partner => new verification process */
- stmmac_fpe_apply(priv);
- } else {
- /* No link => turn off EFPE */
- stmmac_fpe_configure(priv, priv->ioaddr, fpe_cfg,
- priv->plat->tx_queues_to_use,
- priv->plat->rx_queues_to_use,
- false, false);
- }
-
- spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
static void stmmac_mac_link_down(struct phylink_config *config,
unsigned int mode, phy_interface_t interface)
{
@@ -1006,7 +978,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
priv->eee_enabled = stmmac_eee_init(priv);
stmmac_set_eee_pls(priv, priv->hw, false);
- if (priv->dma_cap.fpesel)
+ if (stmmac_fpe_supported(priv))
stmmac_fpe_link_state_handle(priv, false);
}
@@ -1120,7 +1092,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
stmmac_set_eee_pls(priv, priv->hw, true);
}
- if (priv->dma_cap.fpesel)
+ if (stmmac_fpe_supported(priv))
stmmac_fpe_link_state_handle(priv, true);
if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
@@ -1205,6 +1177,9 @@ static int stmmac_init_phy(struct net_device *dev)
return -ENODEV;
}
+ if (priv->dma_cap.eee)
+ phy_support_eee(phydev);
+
ret = phylink_connect_phy(priv->phylink, phydev);
} else {
fwnode_handle_put(phy_fwnode);
@@ -3780,6 +3755,7 @@ static int stmmac_request_irq_single(struct net_device *dev)
/* Request the Wake IRQ in case of another line
* is used for WoL
*/
+ priv->wol_irq_disabled = true;
if (priv->wol_irq > 0 && priv->wol_irq != dev->irq) {
ret = request_irq(priv->wol_irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
@@ -4068,7 +4044,7 @@ static int stmmac_release(struct net_device *dev)
stmmac_release_ptp(priv);
- if (priv->dma_cap.fpesel)
+ if (stmmac_fpe_supported(priv))
timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
pm_runtime_put(priv->device);
@@ -5965,35 +5941,6 @@ static int stmmac_set_features(struct net_device *netdev,
return 0;
}
-static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
-{
- struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-
- /* This is interrupt context, just spin_lock() */
- spin_lock(&fpe_cfg->lock);
-
- if (!fpe_cfg->pmac_enabled || status == FPE_EVENT_UNKNOWN)
- goto unlock_out;
-
- /* LP has sent verify mPacket */
- if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER)
- stmmac_fpe_send_mpacket(priv, priv->ioaddr, fpe_cfg,
- MPACKET_RESPONSE);
-
- /* Local has sent verify mPacket */
- if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER &&
- fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED)
- fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
-
- /* LP has sent response mPacket */
- if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP &&
- fpe_cfg->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING)
- fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
-
-unlock_out:
- spin_unlock(&fpe_cfg->lock);
-}
-
static void stmmac_common_interrupt(struct stmmac_priv *priv)
{
u32 rx_cnt = priv->plat->rx_queues_to_use;
@@ -6012,12 +5959,8 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv)
stmmac_est_irq_status(priv, priv, priv->dev,
&priv->xstats, tx_cnt);
- if (priv->dma_cap.fpesel) {
- int status = stmmac_fpe_irq_status(priv, priv->ioaddr,
- priv->dev);
-
- stmmac_fpe_event_status(priv, status);
- }
+ if (stmmac_fpe_supported(priv))
+ stmmac_fpe_irq_status(priv);
/* To handle GMAC own interrupts */
if ((priv->plat->has_gmac) || xmac) {
@@ -7349,90 +7292,6 @@ int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size)
return ret;
}
-/**
- * stmmac_fpe_verify_timer - Timer for MAC Merge verification
- * @t: timer_list struct containing private info
- *
- * Verify the MAC Merge capability in the local TX direction, by
- * transmitting Verify mPackets up to 3 times. Wait until link
- * partner responds with a Response mPacket, otherwise fail.
- */
-static void stmmac_fpe_verify_timer(struct timer_list *t)
-{
- struct stmmac_fpe_cfg *fpe_cfg = from_timer(fpe_cfg, t, verify_timer);
- struct stmmac_priv *priv = container_of(fpe_cfg, struct stmmac_priv,
- fpe_cfg);
- unsigned long flags;
- bool rearm = false;
-
- spin_lock_irqsave(&fpe_cfg->lock, flags);
-
- switch (fpe_cfg->status) {
- case ETHTOOL_MM_VERIFY_STATUS_INITIAL:
- case ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
- if (fpe_cfg->verify_retries != 0) {
- stmmac_fpe_send_mpacket(priv, priv->ioaddr,
- fpe_cfg, MPACKET_VERIFY);
- rearm = true;
- } else {
- fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
- }
-
- fpe_cfg->verify_retries--;
- break;
-
- case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
- stmmac_fpe_configure(priv, priv->ioaddr, fpe_cfg,
- priv->plat->tx_queues_to_use,
- priv->plat->rx_queues_to_use,
- true, true);
- break;
-
- default:
- break;
- }
-
- if (rearm) {
- mod_timer(&fpe_cfg->verify_timer,
- jiffies + msecs_to_jiffies(fpe_cfg->verify_time));
- }
-
- spin_unlock_irqrestore(&fpe_cfg->lock, flags);
-}
-
-static void stmmac_fpe_verify_timer_arm(struct stmmac_fpe_cfg *fpe_cfg)
-{
- if (fpe_cfg->pmac_enabled && fpe_cfg->tx_enabled &&
- fpe_cfg->verify_enabled &&
- fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_FAILED &&
- fpe_cfg->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) {
- timer_setup(&fpe_cfg->verify_timer, stmmac_fpe_verify_timer, 0);
- mod_timer(&fpe_cfg->verify_timer, jiffies);
- }
-}
-
-void stmmac_fpe_apply(struct stmmac_priv *priv)
-{
- struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;
-
- /* If verification is disabled, configure FPE right away.
- * Otherwise let the timer code do it.
- */
- if (!fpe_cfg->verify_enabled) {
- stmmac_fpe_configure(priv, priv->ioaddr, fpe_cfg,
- priv->plat->tx_queues_to_use,
- priv->plat->rx_queues_to_use,
- fpe_cfg->tx_enabled,
- fpe_cfg->pmac_enabled);
- } else {
- fpe_cfg->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
- fpe_cfg->verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
-
- if (netif_running(priv->dev))
- stmmac_fpe_verify_timer_arm(fpe_cfg);
- }
-}
-
static int stmmac_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp)
{
const struct stmmac_xdp_buff *ctx = (void *)_ctx;
@@ -7711,11 +7570,7 @@ int stmmac_dvr_probe(struct device *device,
mutex_init(&priv->lock);
- priv->fpe_cfg.verify_retries = STMMAC_FPE_MM_MAX_VERIFY_RETRIES;
- priv->fpe_cfg.verify_time = STMMAC_FPE_MM_MAX_VERIFY_TIME_MS;
- priv->fpe_cfg.status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
- timer_setup(&priv->fpe_cfg.verify_timer, stmmac_fpe_verify_timer, 0);
- spin_lock_init(&priv->fpe_cfg.lock);
+ stmmac_fpe_init(priv);
/* If a specific clk_csr value is passed from the platform
* this means that the CSR Clock Range selection cannot be
@@ -7890,7 +7745,7 @@ int stmmac_suspend(struct device *dev)
}
rtnl_unlock();
- if (priv->dma_cap.fpesel)
+ if (stmmac_fpe_supported(priv))
timer_shutdown_sync(&priv->fpe_cfg.verify_timer);
priv->speed = SPEED_UNKNOWN;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 03f90676b3ad..0c7d81ddd440 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -500,23 +500,22 @@ int stmmac_pcs_setup(struct net_device *ndev)
struct fwnode_handle *devnode, *pcsnode;
struct dw_xpcs *xpcs = NULL;
struct stmmac_priv *priv;
- int addr, mode, ret;
+ int addr, ret;
priv = netdev_priv(ndev);
- mode = priv->plat->phy_interface;
devnode = priv->plat->port_node;
if (priv->plat->pcs_init) {
ret = priv->plat->pcs_init(priv);
} else if (fwnode_property_present(devnode, "pcs-handle")) {
pcsnode = fwnode_find_reference(devnode, "pcs-handle", 0);
- xpcs = xpcs_create_fwnode(pcsnode, mode);
+ xpcs = xpcs_create_fwnode(pcsnode);
fwnode_handle_put(pcsnode);
ret = PTR_ERR_OR_ZERO(xpcs);
} else if (priv->plat->mdio_bus_data &&
priv->plat->mdio_bus_data->pcs_mask) {
addr = ffs(priv->plat->mdio_bus_data->pcs_mask) - 1;
- xpcs = xpcs_create_mdiodev(priv->mii, addr, mode);
+ xpcs = xpcs_create_mdiodev(priv->mii, addr);
ret = PTR_ERR_OR_ZERO(xpcs);
} else {
return 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index ad868e8d195d..3ac32444e492 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -522,6 +522,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
if (of_device_is_compatible(np, "st,spear600-gmac") ||
of_device_is_compatible(np, "snps,dwmac-3.50a") ||
of_device_is_compatible(np, "snps,dwmac-3.70a") ||
+ of_device_is_compatible(np, "snps,dwmac-3.72a") ||
of_device_is_compatible(np, "snps,dwmac")) {
/* Note that the max-frame-size parameter as defined in the
* ePAPR v1.1 spec is defined as max-frame-size, it's
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index a6b1de9a251d..429b2d357813 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -9,7 +9,6 @@
*******************************************************************************/
#include "stmmac.h"
#include "stmmac_ptp.h"
-#include "dwmac4.h"
/**
* stmmac_adjust_freq
@@ -265,7 +264,7 @@ static int stmmac_getcrosststamp(struct ptp_clock_info *ptp,
}
/* structure describing a PTP hardware clock */
-static struct ptp_clock_info stmmac_ptp_clock_ops = {
+const struct ptp_clock_info stmmac_ptp_clock_ops = {
.owner = THIS_MODULE,
.name = "stmmac ptp",
.max_adj = 62500000,
@@ -282,6 +281,24 @@ static struct ptp_clock_info stmmac_ptp_clock_ops = {
.getcrosststamp = stmmac_getcrosststamp,
};
+/* structure describing a PTP hardware clock */
+const struct ptp_clock_info dwmac1000_ptp_clock_ops = {
+ .owner = THIS_MODULE,
+ .name = "stmmac ptp",
+ .max_adj = 62500000,
+ .n_alarm = 0,
+ .n_ext_ts = 1,
+ .n_per_out = 0,
+ .n_pins = 0,
+ .pps = 0,
+ .adjfine = stmmac_adjust_freq,
+ .adjtime = stmmac_adjust_time,
+ .gettime64 = stmmac_get_time,
+ .settime64 = stmmac_set_time,
+ .enable = dwmac1000_ptp_enable,
+ .getcrosststamp = stmmac_getcrosststamp,
+};
+
/**
* stmmac_ptp_register
* @priv: driver private structure
@@ -298,20 +315,25 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
priv->pps[i].available = true;
}
- if (priv->plat->ptp_max_adj)
- stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
-
/* Calculate the clock domain crossing (CDC) error if necessary */
priv->plat->cdc_error_adj = 0;
if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
priv->plat->cdc_error_adj = (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
- stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
- stmmac_ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
+ /* Update the ptp clock parameters based on feature discovery, when
+ * available
+ */
+ if (priv->dma_cap.pps_out_num)
+ priv->ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
+
+ if (priv->dma_cap.aux_snapshot_n)
+ priv->ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
+
+ if (priv->plat->ptp_max_adj)
+ priv->ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
rwlock_init(&priv->ptp_lock);
mutex_init(&priv->aux_ts_lock);
- priv->ptp_clock_ops = stmmac_ptp_clock_ops;
priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
priv->device);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
index fce3fba2ffd2..4cc70480ce0f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -94,4 +94,14 @@ enum aux_snapshot {
AUX_SNAPSHOT3 = 0x80,
};
+struct ptp_clock_info;
+struct ptp_clock_request;
+struct stmmac_priv;
+
+int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on);
+
+void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time);
+void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv);
+
#endif /* __STMMAC_PTP_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 75ad2da1a37f..6a79e6a111ed 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -1290,8 +1290,8 @@ const struct stmmac_tc_ops dwxgmac_tc_ops = {
.setup_cls_u32 = tc_setup_cls_u32,
.setup_cbs = tc_setup_cbs,
.setup_cls = tc_setup_cls,
- .setup_taprio = tc_setup_taprio_without_fpe,
+ .setup_taprio = tc_setup_taprio,
.setup_etf = tc_setup_etf,
.query_caps = tc_query_caps,
- .setup_mqprio = tc_setup_mqprio_unimplemented,
+ .setup_mqprio = tc_setup_dwmac510_mqprio,
};
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 41a27ae58ced..df6d35d41b97 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -10182,7 +10182,7 @@ static struct platform_driver niu_of_driver = {
.of_match_table = niu_match,
},
.probe = niu_of_probe,
- .remove_new = niu_of_remove,
+ .remove = niu_of_remove,
};
#endif /* CONFIG_SPARC64 */
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index 16c86b13c185..bbb3a6ca19ed 100644
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -1272,7 +1272,7 @@ static struct platform_driver bigmac_sbus_driver = {
.of_match_table = bigmac_sbus_match,
},
.probe = bigmac_sbus_probe,
- .remove_new = bigmac_sbus_remove,
+ .remove = bigmac_sbus_remove,
};
module_platform_driver(bigmac_sbus_driver);
diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
index aedd13c94225..2920341b14a0 100644
--- a/drivers/net/ethernet/sun/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@ -965,7 +965,7 @@ static struct platform_driver qec_sbus_driver = {
.of_match_table = qec_sbus_match,
},
.probe = qec_sbus_probe,
- .remove_new = qec_sbus_remove,
+ .remove = qec_sbus_remove,
};
static int __init qec_init(void)
diff --git a/drivers/net/ethernet/sunplus/spl2sw_driver.c b/drivers/net/ethernet/sunplus/spl2sw_driver.c
index 391a1bc7f446..721d8ed3f302 100644
--- a/drivers/net/ethernet/sunplus/spl2sw_driver.c
+++ b/drivers/net/ethernet/sunplus/spl2sw_driver.c
@@ -549,7 +549,7 @@ MODULE_DEVICE_TABLE(of, spl2sw_of_match);
static struct platform_driver spl2sw_driver = {
.probe = spl2sw_probe,
- .remove_new = spl2sw_remove,
+ .remove = spl2sw_remove,
.driver = {
.name = "sp7021_emac",
.of_match_table = spl2sw_of_match,
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 0520e9f4bea7..14e1df721f2e 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -71,6 +71,8 @@
#define AM65_CPSW_PORT_REG_RX_PRI_MAP 0x020
#define AM65_CPSW_PORT_REG_RX_MAXLEN 0x024
+#define AM65_CPSW_PORTN_REG_CTL 0x004
+#define AM65_CPSW_PORTN_REG_DSCP_MAP 0x120
#define AM65_CPSW_PORTN_REG_SA_L 0x308
#define AM65_CPSW_PORTN_REG_SA_H 0x30c
#define AM65_CPSW_PORTN_REG_TS_CTL 0x310
@@ -94,6 +96,10 @@
/* AM65_CPSW_PORT_REG_PRI_CTL */
#define AM65_CPSW_PORT_REG_PRI_CTL_RX_PTYPE_RROBIN BIT(8)
+/* AM65_CPSW_PN_REG_CTL */
+#define AM65_CPSW_PN_REG_CTL_DSCP_IPV4_EN BIT(1)
+#define AM65_CPSW_PN_REG_CTL_DSCP_IPV6_EN BIT(2)
+
/* AM65_CPSW_PN_TS_CTL register fields */
#define AM65_CPSW_PN_TS_CTL_TX_ANX_F_EN BIT(4)
#define AM65_CPSW_PN_TS_CTL_TX_VLAN_LT1_EN BIT(5)
@@ -176,6 +182,99 @@ static void am65_cpsw_port_set_sl_mac(struct am65_cpsw_port *slave,
writel(mac_lo, slave->port_base + AM65_CPSW_PORTN_REG_SA_L);
}
+#define AM65_CPSW_DSCP_MAX GENMASK(5, 0)
+#define AM65_CPSW_PRI_MAX GENMASK(2, 0)
+#define AM65_CPSW_DSCP_PRI_PER_REG 8
+#define AM65_CPSW_DSCP_PRI_SIZE 4 /* in bits */
+static int am65_cpsw_port_set_dscp_map(struct am65_cpsw_port *slave, u8 dscp, u8 pri)
+{
+ int reg_ofs;
+ int bit_ofs;
+ u32 val;
+
+ if (dscp > AM65_CPSW_DSCP_MAX)
+ return -EINVAL;
+
+ if (pri > AM65_CPSW_PRI_MAX)
+ return -EINVAL;
+
+ /* 32-bit register offset to this dscp */
+ reg_ofs = (dscp / AM65_CPSW_DSCP_PRI_PER_REG) * 4;
+ /* bit field offset to this dscp */
+ bit_ofs = AM65_CPSW_DSCP_PRI_SIZE * (dscp % AM65_CPSW_DSCP_PRI_PER_REG);
+
+ val = readl(slave->port_base + AM65_CPSW_PORTN_REG_DSCP_MAP + reg_ofs);
+ val &= ~(AM65_CPSW_PRI_MAX << bit_ofs); /* clear */
+ val |= pri << bit_ofs; /* set */
+ writel(val, slave->port_base + AM65_CPSW_PORTN_REG_DSCP_MAP + reg_ofs);
+
+ return 0;
+}
+
+static void am65_cpsw_port_enable_dscp_map(struct am65_cpsw_port *slave)
+{
+ int dscp, pri;
+ u32 val;
+
+ /* Default DSCP to User Priority mapping as per:
+ * https://datatracker.ietf.org/doc/html/rfc8325#section-4.3
+ * and
+ * https://datatracker.ietf.org/doc/html/rfc8622#section-11
+ */
+ for (dscp = 0; dscp <= AM65_CPSW_DSCP_MAX; dscp++) {
+ switch (dscp) {
+ case 56: /* CS7 */
+ case 48: /* CS6 */
+ pri = 7;
+ break;
+ case 46: /* EF */
+ case 44: /* VA */
+ pri = 6;
+ break;
+ case 40: /* CS5 */
+ pri = 5;
+ break;
+ case 34: /* AF41 */
+ case 36: /* AF42 */
+ case 38: /* AF43 */
+ case 32: /* CS4 */
+ case 26: /* AF31 */
+ case 28: /* AF32 */
+ case 30: /* AF33 */
+ case 24: /* CS3 */
+ pri = 4;
+ break;
+ case 18: /* AF21 */
+ case 20: /* AF22 */
+ case 22: /* AF23 */
+ pri = 3;
+ break;
+ case 16: /* CS2 */
+ case 10: /* AF11 */
+ case 12: /* AF12 */
+ case 14: /* AF13 */
+ case 0: /* DF */
+ pri = 0;
+ break;
+ case 8: /* CS1 */
+ case 1: /* LE */
+ pri = 1;
+ break;
+ default:
+ pri = 0;
+ break;
+ }
+
+ am65_cpsw_port_set_dscp_map(slave, dscp, pri);
+ }
+
+ /* enable port IPV4 and IPV6 DSCP for this port */
+ val = readl(slave->port_base + AM65_CPSW_PORTN_REG_CTL);
+ val |= AM65_CPSW_PN_REG_CTL_DSCP_IPV4_EN |
+ AM65_CPSW_PN_REG_CTL_DSCP_IPV6_EN;
+ writel(val, slave->port_base + AM65_CPSW_PORTN_REG_CTL);
+}
+
static void am65_cpsw_sl_ctl_reset(struct am65_cpsw_port *port)
{
cpsw_sl_reset(port->slave.mac_sl, 100);
@@ -337,9 +436,9 @@ static int am65_cpsw_nuss_rx_push(struct am65_cpsw_common *common,
struct am65_cpsw_rx_chn *rx_chn = &common->rx_chns;
struct cppi5_host_desc_t *desc_rx;
struct device *dev = common->dev;
+ struct am65_cpsw_swdata *swdata;
dma_addr_t desc_dma;
dma_addr_t buf_dma;
- void *swdata;
desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
if (!desc_rx) {
@@ -363,7 +462,8 @@ static int am65_cpsw_nuss_rx_push(struct am65_cpsw_common *common,
cppi5_hdesc_attach_buf(desc_rx, buf_dma, AM65_CPSW_MAX_PACKET_SIZE,
buf_dma, AM65_CPSW_MAX_PACKET_SIZE);
swdata = cppi5_hdesc_get_swdata(desc_rx);
- *((void **)swdata) = page_address(page);
+ swdata->page = page;
+ swdata->flow_id = flow_idx;
return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, flow_idx,
desc_rx, desc_dma);
@@ -519,36 +619,31 @@ static enum am65_cpsw_tx_buf_type am65_cpsw_nuss_buf_type(struct am65_cpsw_tx_ch
static inline void am65_cpsw_put_page(struct am65_cpsw_rx_flow *flow,
struct page *page,
- bool allow_direct,
- int desc_idx)
+ bool allow_direct)
{
page_pool_put_full_page(flow->page_pool, page, allow_direct);
- flow->pages[desc_idx] = NULL;
}
static void am65_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma)
{
- struct am65_cpsw_rx_flow *flow = data;
+ struct am65_cpsw_rx_chn *rx_chn = data;
struct cppi5_host_desc_t *desc_rx;
- struct am65_cpsw_rx_chn *rx_chn;
+ struct am65_cpsw_swdata *swdata;
dma_addr_t buf_dma;
+ struct page *page;
u32 buf_dma_len;
- void *page_addr;
- void **swdata;
- int desc_idx;
+ u32 flow_id;
- rx_chn = &flow->common->rx_chns;
desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
swdata = cppi5_hdesc_get_swdata(desc_rx);
- page_addr = *swdata;
+ page = swdata->page;
+ flow_id = swdata->flow_id;
cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
- desc_idx = am65_cpsw_nuss_desc_idx(rx_chn->desc_pool, desc_rx,
- rx_chn->dsize_log2);
- am65_cpsw_put_page(flow, virt_to_page(page_addr), false, desc_idx);
+ am65_cpsw_put_page(&rx_chn->flows[flow_id], page, false);
}
static void am65_cpsw_nuss_xmit_free(struct am65_cpsw_tx_chn *tx_chn,
@@ -703,14 +798,13 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
ret = -ENOMEM;
goto fail_rx;
}
- flow->pages[i] = page;
ret = am65_cpsw_nuss_rx_push(common, page, flow_idx);
if (ret < 0) {
dev_err(common->dev,
"cannot submit page to rx channel flow %d, error %d\n",
flow_idx, ret);
- am65_cpsw_put_page(flow, page, false, i);
+ am65_cpsw_put_page(flow, page, false);
goto fail_rx;
}
}
@@ -764,8 +858,8 @@ fail_tx:
fail_rx:
for (i = 0; i < common->rx_ch_num_flows; i++)
- k3_udma_glue_reset_rx_chn(rx_chn->rx_chn, i, &rx_chn->flows[i],
- am65_cpsw_nuss_rx_cleanup, 0);
+ k3_udma_glue_reset_rx_chn(rx_chn->rx_chn, i, rx_chn,
+ am65_cpsw_nuss_rx_cleanup, !!i);
am65_cpsw_destroy_xdp_rxqs(common);
@@ -817,11 +911,11 @@ static int am65_cpsw_nuss_common_stop(struct am65_cpsw_common *common)
dev_err(common->dev, "rx teardown timeout\n");
}
- for (i = 0; i < common->rx_ch_num_flows; i++) {
+ for (i = common->rx_ch_num_flows - 1; i >= 0; i--) {
napi_disable(&rx_chn->flows[i].napi_rx);
hrtimer_cancel(&rx_chn->flows[i].rx_hrtimer);
- k3_udma_glue_reset_rx_chn(rx_chn->rx_chn, i, &rx_chn->flows[i],
- am65_cpsw_nuss_rx_cleanup, 0);
+ k3_udma_glue_reset_rx_chn(rx_chn->rx_chn, i, rx_chn,
+ am65_cpsw_nuss_rx_cleanup, !!i);
}
k3_udma_glue_disable_rx_chn(rx_chn->rx_chn);
@@ -921,6 +1015,7 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev)
common->usage_count++;
am65_cpsw_port_set_sl_mac(port, ndev->dev_addr);
+ am65_cpsw_port_enable_dscp_map(port);
if (common->is_emac_mode)
am65_cpsw_init_port_emac_ale(port);
@@ -1028,12 +1123,10 @@ pool_free:
static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow,
struct am65_cpsw_port *port,
struct xdp_buff *xdp,
- int desc_idx, int cpu, int *len)
+ int cpu, int *len)
{
struct am65_cpsw_common *common = flow->common;
- struct am65_cpsw_ndev_priv *ndev_priv;
struct net_device *ndev = port->ndev;
- struct am65_cpsw_ndev_stats *stats;
int ret = AM65_CPSW_XDP_CONSUMED;
struct am65_cpsw_tx_chn *tx_chn;
struct netdev_queue *netif_txq;
@@ -1051,9 +1144,6 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow,
/* XDP prog might have changed packet data and boundaries */
*len = xdp->data_end - xdp->data;
- ndev_priv = netdev_priv(ndev);
- stats = this_cpu_ptr(ndev_priv->stats);
-
switch (act) {
case XDP_PASS:
ret = AM65_CPSW_XDP_PASS;
@@ -1073,20 +1163,14 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow,
if (err)
goto drop;
- u64_stats_update_begin(&stats->syncp);
- stats->rx_bytes += *len;
- stats->rx_packets++;
- u64_stats_update_end(&stats->syncp);
+ dev_sw_netstats_tx_add(ndev, 1, *len);
ret = AM65_CPSW_XDP_CONSUMED;
goto out;
case XDP_REDIRECT:
if (unlikely(xdp_do_redirect(ndev, xdp, prog)))
goto drop;
- u64_stats_update_begin(&stats->syncp);
- stats->rx_bytes += *len;
- stats->rx_packets++;
- u64_stats_update_end(&stats->syncp);
+ dev_sw_netstats_rx_add(ndev, *len);
ret = AM65_CPSW_XDP_REDIRECT;
goto out;
default:
@@ -1101,7 +1185,7 @@ drop:
}
page = virt_to_head_page(xdp->data);
- am65_cpsw_put_page(flow, page, true, desc_idx);
+ am65_cpsw_put_page(flow, page, true);
out:
return ret;
@@ -1147,19 +1231,18 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
u32 buf_dma_len, pkt_len, port_id = 0, csum_info;
struct am65_cpsw_common *common = flow->common;
struct am65_cpsw_ndev_priv *ndev_priv;
- struct am65_cpsw_ndev_stats *stats;
struct cppi5_host_desc_t *desc_rx;
struct device *dev = common->dev;
+ struct am65_cpsw_swdata *swdata;
struct page *page, *new_page;
dma_addr_t desc_dma, buf_dma;
struct am65_cpsw_port *port;
- int headroom, desc_idx, ret;
struct net_device *ndev;
u32 flow_idx = flow->id;
struct sk_buff *skb;
struct xdp_buff xdp;
+ int headroom, ret;
void *page_addr;
- void **swdata;
u32 *psdata;
*xdp_state = AM65_CPSW_XDP_PASS;
@@ -1182,8 +1265,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
__func__, flow_idx, &desc_dma);
swdata = cppi5_hdesc_get_swdata(desc_rx);
- page_addr = *swdata;
- page = virt_to_page(page_addr);
+ page = swdata->page;
+ page_addr = page_address(page);
cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
@@ -1199,9 +1282,6 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
- desc_idx = am65_cpsw_nuss_desc_idx(rx_chn->desc_pool, desc_rx,
- rx_chn->dsize_log2);
-
skb = am65_cpsw_build_skb(page_addr, ndev,
AM65_CPSW_MAX_PACKET_SIZE);
if (unlikely(!skb)) {
@@ -1213,7 +1293,7 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
xdp_init_buff(&xdp, PAGE_SIZE, &port->xdp_rxq[flow->id]);
xdp_prepare_buff(&xdp, page_addr, AM65_CPSW_HEADROOM,
pkt_len, false);
- *xdp_state = am65_cpsw_run_xdp(flow, port, &xdp, desc_idx,
+ *xdp_state = am65_cpsw_run_xdp(flow, port, &xdp,
cpu, &pkt_len);
if (*xdp_state != AM65_CPSW_XDP_PASS)
goto allocate;
@@ -1233,12 +1313,7 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
am65_cpsw_nuss_rx_csum(skb, csum_info);
napi_gro_receive(&flow->napi_rx, skb);
- stats = this_cpu_ptr(ndev_priv->stats);
-
- u64_stats_update_begin(&stats->syncp);
- stats->rx_packets++;
- stats->rx_bytes += pkt_len;
- u64_stats_update_end(&stats->syncp);
+ dev_sw_netstats_rx_add(ndev, pkt_len);
allocate:
new_page = page_pool_dev_alloc_pages(flow->page_pool);
@@ -1247,10 +1322,8 @@ allocate:
return -ENOMEM;
}
- flow->pages[desc_idx] = new_page;
-
if (netif_dormant(ndev)) {
- am65_cpsw_put_page(flow, new_page, true, desc_idx);
+ am65_cpsw_put_page(flow, new_page, true);
ndev->stats.rx_dropped++;
return 0;
}
@@ -1258,7 +1331,7 @@ allocate:
requeue:
ret = am65_cpsw_nuss_rx_push(common, new_page, flow_idx);
if (WARN_ON(ret < 0)) {
- am65_cpsw_put_page(flow, new_page, true, desc_idx);
+ am65_cpsw_put_page(flow, new_page, true);
ndev->stats.rx_errors++;
ndev->stats.rx_dropped++;
}
@@ -1321,10 +1394,7 @@ static struct sk_buff *
am65_cpsw_nuss_tx_compl_packet_skb(struct am65_cpsw_tx_chn *tx_chn,
dma_addr_t desc_dma)
{
- struct am65_cpsw_ndev_priv *ndev_priv;
- struct am65_cpsw_ndev_stats *stats;
struct cppi5_host_desc_t *desc_tx;
- struct net_device *ndev;
struct sk_buff *skb;
void **swdata;
@@ -1334,16 +1404,9 @@ am65_cpsw_nuss_tx_compl_packet_skb(struct am65_cpsw_tx_chn *tx_chn,
skb = *(swdata);
am65_cpsw_nuss_xmit_free(tx_chn, desc_tx);
- ndev = skb->dev;
-
am65_cpts_tx_timestamp(tx_chn->common->cpts, skb);
- ndev_priv = netdev_priv(ndev);
- stats = this_cpu_ptr(ndev_priv->stats);
- u64_stats_update_begin(&stats->syncp);
- stats->tx_packets++;
- stats->tx_bytes += skb->len;
- u64_stats_update_end(&stats->syncp);
+ dev_sw_netstats_tx_add(skb->dev, 1, skb->len);
return skb;
}
@@ -1354,8 +1417,6 @@ am65_cpsw_nuss_tx_compl_packet_xdp(struct am65_cpsw_common *common,
dma_addr_t desc_dma,
struct net_device **ndev)
{
- struct am65_cpsw_ndev_priv *ndev_priv;
- struct am65_cpsw_ndev_stats *stats;
struct cppi5_host_desc_t *desc_tx;
struct am65_cpsw_port *port;
struct xdp_frame *xdpf;
@@ -1369,15 +1430,9 @@ am65_cpsw_nuss_tx_compl_packet_xdp(struct am65_cpsw_common *common,
am65_cpsw_nuss_xmit_free(tx_chn, desc_tx);
port = am65_common_get_port(common, port_id);
+ dev_sw_netstats_tx_add(port->ndev, 1, xdpf->len);
*ndev = port->ndev;
- ndev_priv = netdev_priv(*ndev);
- stats = this_cpu_ptr(ndev_priv->stats);
- u64_stats_update_begin(&stats->syncp);
- stats->tx_packets++;
- stats->tx_bytes += xdpf->len;
- u64_stats_update_end(&stats->syncp);
-
return xdpf;
}
@@ -1899,31 +1954,7 @@ static int am65_cpsw_nuss_ndo_slave_ioctl(struct net_device *ndev,
static void am65_cpsw_nuss_ndo_get_stats(struct net_device *dev,
struct rtnl_link_stats64 *stats)
{
- struct am65_cpsw_ndev_priv *ndev_priv = netdev_priv(dev);
- unsigned int start;
- int cpu;
-
- for_each_possible_cpu(cpu) {
- struct am65_cpsw_ndev_stats *cpu_stats;
- u64 rx_packets;
- u64 rx_bytes;
- u64 tx_packets;
- u64 tx_bytes;
-
- cpu_stats = per_cpu_ptr(ndev_priv->stats, cpu);
- do {
- start = u64_stats_fetch_begin(&cpu_stats->syncp);
- rx_packets = cpu_stats->rx_packets;
- rx_bytes = cpu_stats->rx_bytes;
- tx_packets = cpu_stats->tx_packets;
- tx_bytes = cpu_stats->tx_bytes;
- } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
-
- stats->rx_packets += rx_packets;
- stats->rx_bytes += rx_bytes;
- stats->tx_packets += tx_packets;
- stats->tx_bytes += tx_bytes;
- }
+ dev_fetch_sw_netstats(stats, dev->tstats);
stats->rx_errors = dev->stats.rx_errors;
stats->rx_dropped = dev->stats.rx_dropped;
@@ -2402,10 +2433,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
for (i = 0; i < common->rx_ch_num_flows; i++) {
flow = &rx_chn->flows[i];
flow->page_pool = NULL;
- flow->pages = devm_kcalloc(dev, AM65_CPSW_MAX_RX_DESC,
- sizeof(*flow->pages), GFP_KERNEL);
- if (!flow->pages)
- return -ENOMEM;
}
rx_chn->rx_chn = k3_udma_glue_request_rx_chn(dev, "rx", &rx_cfg);
@@ -2455,10 +2482,12 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
flow = &rx_chn->flows[i];
flow->id = i;
flow->common = common;
+ flow->irq = -EINVAL;
rx_flow_cfg.ring_rxfdq0_id = fdqring_id;
rx_flow_cfg.rx_cfg.size = max_desc_num;
- rx_flow_cfg.rxfdq_cfg.size = max_desc_num;
+ /* share same FDQ for all flows */
+ rx_flow_cfg.rxfdq_cfg.size = max_desc_num * rx_cfg.flow_id_num;
rx_flow_cfg.rxfdq_cfg.mode = common->pdata.fdqring_mode;
ret = k3_udma_glue_rx_flow_init(rx_chn->rx_chn,
@@ -2496,6 +2525,7 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
if (ret) {
dev_err(dev, "failure requesting rx %d irq %u, %d\n",
i, flow->irq, ret);
+ flow->irq = -EINVAL;
goto err;
}
}
@@ -2710,13 +2740,6 @@ of_node_put:
return ret;
}
-static void am65_cpsw_pcpu_stats_free(void *data)
-{
- struct am65_cpsw_ndev_stats __percpu *stats = data;
-
- free_percpu(stats);
-}
-
static void am65_cpsw_nuss_phylink_cleanup(struct am65_cpsw_common *common)
{
struct am65_cpsw_port *port;
@@ -2736,7 +2759,6 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
struct device *dev = common->dev;
struct am65_cpsw_port *port;
struct phylink *phylink;
- int ret;
port = &common->ports[port_idx];
@@ -2829,21 +2851,13 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
if (common->pdata.quirks & AM65_CPSW_QUIRK_I2027_NO_TX_CSUM)
port->ndev->features &= ~NETIF_F_HW_CSUM;
- ndev_priv->stats = netdev_alloc_pcpu_stats(struct am65_cpsw_ndev_stats);
- if (!ndev_priv->stats)
- return -ENOMEM;
-
- ret = devm_add_action_or_reset(dev, am65_cpsw_pcpu_stats_free,
- ndev_priv->stats);
- if (ret)
- dev_err(dev, "failed to add percpu stat free action %d\n", ret);
-
+ port->ndev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
port->xdp_prog = NULL;
if (!common->dma_ndev)
common->dma_ndev = port->ndev;
- return ret;
+ return 0;
}
static int am65_cpsw_nuss_init_ndevs(struct am65_cpsw_common *common)
@@ -3349,8 +3363,8 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
for (i = 0; i < common->rx_ch_num_flows; i++)
k3_udma_glue_reset_rx_chn(rx_chan->rx_chn, i,
- &rx_chan->flows[i],
- am65_cpsw_nuss_rx_cleanup, 0);
+ rx_chan,
+ am65_cpsw_nuss_rx_cleanup, !!i);
k3_udma_glue_disable_rx_chn(rx_chan->rx_chn);
@@ -3448,7 +3462,8 @@ static const struct am65_cpsw_pdata j7200_cpswxg_pdata = {
.quirks = 0,
.ale_dev_id = "am64-cpswxg",
.fdqring_mode = K3_RINGACC_RING_MODE_RING,
- .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
+ BIT(PHY_INTERFACE_MODE_USXGMII),
};
static const struct am65_cpsw_pdata j721e_cpswxg_pdata = {
@@ -3500,7 +3515,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
struct resource *res;
struct clk *clk;
int ale_entries;
- u64 id_temp;
+ __be64 id_temp;
int ret, i;
common = devm_kzalloc(dev, sizeof(struct am65_cpsw_common), GFP_KERNEL);
@@ -3773,7 +3788,7 @@ static struct platform_driver am65_cpsw_nuss_driver = {
.pm = &am65_cpsw_nuss_dev_pm_ops,
},
.probe = am65_cpsw_nuss_probe,
- .remove_new = am65_cpsw_nuss_remove,
+ .remove = am65_cpsw_nuss_remove,
};
module_platform_driver(am65_cpsw_nuss_driver);
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index dc8d544230dc..e7832a5cf3cc 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -101,10 +101,14 @@ struct am65_cpsw_rx_flow {
struct hrtimer rx_hrtimer;
unsigned long rx_pace_timeout;
struct page_pool *page_pool;
- struct page **pages;
char name[32];
};
+struct am65_cpsw_swdata {
+ u32 flow_id;
+ struct page *page;
+};
+
struct am65_cpsw_rx_chn {
struct device *dev;
struct device *dma_dev;
@@ -180,18 +184,9 @@ struct am65_cpsw_common {
u32 *ale_context;
};
-struct am65_cpsw_ndev_stats {
- u64 tx_packets;
- u64 tx_bytes;
- u64 rx_packets;
- u64 rx_bytes;
- struct u64_stats_sync syncp;
-};
-
struct am65_cpsw_ndev_priv {
u32 msg_enable;
struct am65_cpsw_port *port;
- struct am65_cpsw_ndev_stats __percpu *stats;
bool offload_fwd_mark;
/* Serialize access to MAC Merge state between ethtool requests
* and link state updates
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index c0a5abd8d9a8..4ef8cf6ea135 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1802,7 +1802,7 @@ static struct platform_driver cpsw_driver = {
.of_match_table = cpsw_of_mtable,
},
.probe = cpsw_probe,
- .remove_new = cpsw_remove,
+ .remove = cpsw_remove,
};
module_platform_driver(cpsw_driver);
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 8d02d2b21429..52e4e350b734 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -162,27 +162,39 @@ static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
ale_entry[idx] |= (value << start);
}
-#define DEFINE_ALE_FIELD(name, start, bits) \
+#define DEFINE_ALE_FIELD_GET(name, start, bits) \
static inline int cpsw_ale_get_##name(u32 *ale_entry) \
{ \
return cpsw_ale_get_field(ale_entry, start, bits); \
-} \
+}
+
+#define DEFINE_ALE_FIELD_SET(name, start, bits) \
static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \
{ \
cpsw_ale_set_field(ale_entry, start, bits, value); \
}
-#define DEFINE_ALE_FIELD1(name, start) \
+#define DEFINE_ALE_FIELD(name, start, bits) \
+DEFINE_ALE_FIELD_GET(name, start, bits) \
+DEFINE_ALE_FIELD_SET(name, start, bits)
+
+#define DEFINE_ALE_FIELD1_GET(name, start) \
static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits) \
{ \
return cpsw_ale_get_field(ale_entry, start, bits); \
-} \
+}
+
+#define DEFINE_ALE_FIELD1_SET(name, start) \
static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value, \
u32 bits) \
{ \
cpsw_ale_set_field(ale_entry, start, bits, value); \
}
+#define DEFINE_ALE_FIELD1(name, start) \
+DEFINE_ALE_FIELD1_GET(name, start) \
+DEFINE_ALE_FIELD1_SET(name, start)
+
enum {
ALE_ENT_VID_MEMBER_LIST = 0,
ALE_ENT_VID_UNREG_MCAST_MSK,
@@ -238,14 +250,14 @@ static const struct ale_entry_fld vlan_entry_k3_cpswxg[] = {
DEFINE_ALE_FIELD(entry_type, 60, 2)
DEFINE_ALE_FIELD(vlan_id, 48, 12)
-DEFINE_ALE_FIELD(mcast_state, 62, 2)
+DEFINE_ALE_FIELD_SET(mcast_state, 62, 2)
DEFINE_ALE_FIELD1(port_mask, 66)
DEFINE_ALE_FIELD(super, 65, 1)
DEFINE_ALE_FIELD(ucast_type, 62, 2)
-DEFINE_ALE_FIELD1(port_num, 66)
-DEFINE_ALE_FIELD(blocked, 65, 1)
-DEFINE_ALE_FIELD(secure, 64, 1)
-DEFINE_ALE_FIELD(mcast, 40, 1)
+DEFINE_ALE_FIELD1_SET(port_num, 66)
+DEFINE_ALE_FIELD_SET(blocked, 65, 1)
+DEFINE_ALE_FIELD_SET(secure, 64, 1)
+DEFINE_ALE_FIELD_GET(mcast, 40, 1)
#define NU_VLAN_UNREG_MCAST_IDX 1
@@ -1692,26 +1704,34 @@ static void cpsw_ale_policer_reset(struct cpsw_ale *ale)
void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch)
{
int pri, idx;
- /* IEEE802.1D-2004, Standard for Local and metropolitan area networks
- * Table G-2 - Traffic type acronyms
- * Table G-3 - Defining traffic types
- * User priority values 1 and 2 effectively communicate a lower
- * priority than 0. In the below table 0 is assigned to higher priority
- * thread than 1 and 2 wherever possible.
- * The below table maps which thread the user priority needs to be
+
+ /* Reference:
+ * IEEE802.1Q-2014, Standard for Local and metropolitan area networks
+ * Table I-2 - Traffic type acronyms
+ * Table I-3 - Defining traffic types
+ * Section I.4 Traffic types and priority values, states:
+ * "0 is thus used both for default priority and for Best Effort, and
+ * Background is associated with a priority value of 1. This means
+ * that the value 1 effectively communicates a lower priority than 0."
+ *
+ * In the table below, Priority Code Point (PCP) 0 is assigned
+ * to a higher priority thread than PCP 1 wherever possible.
+ * The table maps which thread the PCP traffic needs to be
* sent to for a given number of threads (RX channels). Upper threads
* have higher priority.
* e.g. if number of threads is 8 then user priority 0 will map to
- * pri_thread_map[8-1][0] i.e. thread 2
+ * pri_thread_map[8-1][0] i.e. thread 1
*/
- int pri_thread_map[8][8] = { { 0, 0, 0, 0, 0, 0, 0, 0, },
+
+ int pri_thread_map[8][8] = { /* BK,BE,EE,CA,VI,VO,IC,NC */
+ { 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 1, 1, 1, 1, },
{ 0, 0, 0, 0, 1, 1, 2, 2, },
- { 1, 0, 0, 1, 2, 2, 3, 3, },
- { 1, 0, 0, 1, 2, 3, 4, 4, },
- { 1, 0, 0, 2, 3, 4, 5, 5, },
- { 1, 0, 0, 2, 3, 4, 5, 6, },
- { 2, 0, 1, 3, 4, 5, 6, 7, } };
+ { 0, 0, 1, 1, 2, 2, 3, 3, },
+ { 0, 0, 1, 1, 2, 2, 3, 4, },
+ { 1, 0, 2, 2, 3, 3, 4, 5, },
+ { 1, 0, 2, 3, 4, 4, 5, 6, },
+ { 1, 0, 2, 3, 4, 5, 6, 7 } };
cpsw_ale_policer_reset(ale);
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 557cc71b9dd2..a98bcc5eb566 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -2127,7 +2127,7 @@ static struct platform_driver cpsw_driver = {
.of_match_table = cpsw_of_mtable,
},
.probe = cpsw_probe,
- .remove_new = cpsw_remove,
+ .remove = cpsw_remove,
};
module_platform_driver(cpsw_driver);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index b0950a318c42..ed8116fb05e9 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -2070,7 +2070,7 @@ static struct platform_driver davinci_emac_driver = {
.of_match_table = davinci_emac_of_match,
},
.probe = davinci_emac_probe,
- .remove_new = davinci_emac_remove,
+ .remove = davinci_emac_remove,
};
/**
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 8e07d4a1b6ba..68507126be8e 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -760,7 +760,7 @@ static struct platform_driver davinci_mdio_driver = {
.of_match_table = of_match_ptr(davinci_mdio_of_mtable),
},
.probe = davinci_mdio_probe,
- .remove_new = davinci_mdio_remove,
+ .remove = davinci_mdio_remove,
};
static int __init davinci_mdio_init(void)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 5c20ceb164df..c568c84a032b 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -16,6 +16,7 @@
#include <linux/if_hsr.h>
#include <linux/if_vlan.h>
#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
@@ -411,6 +412,8 @@ static int prueth_perout_enable(void *clockops_data,
struct prueth_emac *emac = clockops_data;
u32 reduction_factor = 0, offset = 0;
struct timespec64 ts;
+ u64 current_cycle;
+ u64 start_offset;
u64 ns_period;
if (!on)
@@ -449,8 +452,14 @@ static int prueth_perout_enable(void *clockops_data,
writel(reduction_factor, emac->prueth->shram.va +
TIMESYNC_FW_WC_SYNCOUT_REDUCTION_FACTOR_OFFSET);
- writel(0, emac->prueth->shram.va +
- TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET);
+ current_cycle = icssg_read_time(emac->prueth->shram.va +
+ TIMESYNC_FW_WC_CYCLECOUNT_OFFSET);
+
+ /* Rounding of current_cycle count to next second */
+ start_offset = roundup(current_cycle, MSEC_PER_SEC);
+
+ hi_lo_writeq(start_offset, emac->prueth->shram.va +
+ TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET);
return 0;
}
@@ -808,6 +817,47 @@ static netdev_features_t emac_ndo_fix_features(struct net_device *ndev,
return features;
}
+static int emac_ndo_vlan_rx_add_vid(struct net_device *ndev,
+ __be16 proto, u16 vid)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct prueth *prueth = emac->prueth;
+ int untag_mask = 0;
+ int port_mask;
+
+ if (prueth->is_hsr_offload_mode) {
+ port_mask = BIT(PRUETH_PORT_HOST) | BIT(emac->port_id);
+ untag_mask = 0;
+
+ netdev_dbg(emac->ndev, "VID add vid:%u port_mask:%X untag_mask %X\n",
+ vid, port_mask, untag_mask);
+
+ icssg_vtbl_modify(emac, vid, port_mask, untag_mask, true);
+ icssg_set_pvid(emac->prueth, vid, emac->port_id);
+ }
+ return 0;
+}
+
+static int emac_ndo_vlan_rx_del_vid(struct net_device *ndev,
+ __be16 proto, u16 vid)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct prueth *prueth = emac->prueth;
+ int untag_mask = 0;
+ int port_mask;
+
+ if (prueth->is_hsr_offload_mode) {
+ port_mask = BIT(PRUETH_PORT_HOST);
+ untag_mask = 0;
+
+ netdev_dbg(emac->ndev, "VID del vid:%u port_mask:%X untag_mask %X\n",
+ vid, port_mask, untag_mask);
+
+ icssg_vtbl_modify(emac, vid, port_mask, untag_mask, false);
+ }
+ return 0;
+}
+
static const struct net_device_ops emac_netdev_ops = {
.ndo_open = emac_ndo_open,
.ndo_stop = emac_ndo_stop,
@@ -820,6 +870,8 @@ static const struct net_device_ops emac_netdev_ops = {
.ndo_get_stats64 = icssg_ndo_get_stats64,
.ndo_get_phys_port_name = icssg_ndo_get_phys_port_name,
.ndo_fix_features = emac_ndo_fix_features,
+ .ndo_vlan_rx_add_vid = emac_ndo_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = emac_ndo_vlan_rx_del_vid,
};
static int prueth_netdev_init(struct prueth *prueth,
@@ -947,7 +999,7 @@ static int prueth_netdev_init(struct prueth *prueth,
ndev->netdev_ops = &emac_netdev_ops;
ndev->ethtool_ops = &icssg_ethtool_ops;
ndev->hw_features = NETIF_F_SG;
- ndev->features = ndev->hw_features;
+ ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
ndev->hw_features |= NETIF_PRUETH_HSR_OFFLOAD_FEATURES;
netif_napi_add(ndev, &emac->napi_rx, icssg_napi_rx_poll);
@@ -1646,7 +1698,7 @@ MODULE_DEVICE_TABLE(of, prueth_dt_match);
static struct platform_driver prueth_driver = {
.probe = prueth_probe,
- .remove_new = prueth_remove,
+ .remove = prueth_remove,
.driver = {
.name = "icssg-prueth",
.of_match_table = prueth_dt_match,
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 8722bb4a268a..f5c1d473e9f9 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -330,6 +330,18 @@ static inline int prueth_emac_slice(struct prueth_emac *emac)
extern const struct ethtool_ops icssg_ethtool_ops;
extern const struct dev_pm_ops prueth_dev_pm_ops;
+static inline u64 icssg_read_time(const void __iomem *addr)
+{
+ u32 low, high;
+
+ do {
+ high = readl(addr + 4);
+ low = readl(addr);
+ } while (high != readl(addr + 4));
+
+ return low + ((u64)high << 32);
+}
+
/* Classifier helpers */
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac);
void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
index 292f04d29f4f..5024f0647a0d 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
@@ -1215,7 +1215,7 @@ MODULE_DEVICE_TABLE(of, prueth_dt_match);
static struct platform_driver prueth_driver = {
.probe = prueth_probe,
- .remove_new = prueth_remove,
+ .remove = prueth_remove,
.driver = {
.name = "icssg-prueth-sr1",
.of_match_table = prueth_dt_match,
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index 11b90e1da0c6..857820657bac 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -2270,7 +2270,7 @@ static struct platform_driver netcp_driver = {
.of_match_table = of_match,
},
.probe = netcp_probe,
- .remove_new = netcp_remove,
+ .remove = netcp_remove,
};
module_platform_driver(netcp_driver);
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index 44488c153ea2..4fbe4b7cd12a 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -2566,7 +2566,6 @@ static void gelic_wl_setup_netdev_ops(struct net_device *netdev)
netdev->ethtool_ops = &gelic_wl_ethtool_ops;
netdev->netdev_ops = &gelic_wl_netdevice_ops;
- netdev->wireless_data = &wl->wireless_data;
netdev->wireless_handlers = &gelic_wl_wext_handler_def;
}
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
index 1f203d1ae8db..dbabf538e10a 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
@@ -276,7 +276,6 @@ struct gelic_wl_info {
u8 active_bssid[ETH_ALEN]; /* associated bssid */
unsigned int essid_len;
- struct iw_public_data wireless_data;
struct iw_statistics iwstat;
};
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 554aff7c8f3b..c6957e3b7f0f 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1676,7 +1676,7 @@ static void tsi108_ether_remove(struct platform_device *pdev)
static struct platform_driver tsi_eth_driver = {
.probe = tsi108_init_one,
- .remove_new = tsi108_ether_remove,
+ .remove = tsi108_ether_remove,
.driver = {
.name = "tsi-ethernet",
},
diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c
index a04d4073def9..89dc4c401a8d 100644
--- a/drivers/net/ethernet/vertexcom/mse102x.c
+++ b/drivers/net/ethernet/vertexcom/mse102x.c
@@ -222,7 +222,7 @@ static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp,
struct mse102x_net_spi *mses = to_mse102x_spi(mse);
struct spi_transfer *xfer = &mses->spi_xfer;
struct spi_message *msg = &mses->spi_msg;
- struct sk_buff *tskb;
+ struct sk_buff *tskb = NULL;
int ret;
netif_dbg(mse, tx_queued, mse->ndev, "%s: skb %p, %d@%p\n",
@@ -235,7 +235,6 @@ static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp,
if (!tskb)
return -ENOMEM;
- dev_kfree_skb(txp);
txp = tskb;
}
@@ -257,6 +256,8 @@ static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp,
mse->stats.xfer_err++;
}
+ dev_kfree_skb(tskb);
+
return ret;
}
@@ -436,13 +437,15 @@ static void mse102x_tx_work(struct work_struct *work)
mse = &mses->mse102x;
while ((txb = skb_dequeue(&mse->txq))) {
+ unsigned int len = max_t(unsigned int, txb->len, ETH_ZLEN);
+
mutex_lock(&mses->lock);
ret = mse102x_tx_pkt_spi(mse, txb, work_timeout);
mutex_unlock(&mses->lock);
if (ret) {
mse->ndev->stats.tx_dropped++;
} else {
- mse->ndev->stats.tx_bytes += txb->len;
+ mse->ndev->stats.tx_bytes += len;
mse->ndev->stats.tx_packets++;
}
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index e80c02948801..894911f3d560 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -2570,7 +2570,7 @@ static struct pci_driver rhine_driver_pci = {
static struct platform_driver rhine_driver_platform = {
.probe = rhine_init_one_platform,
- .remove_new = rhine_remove_one_platform,
+ .remove = rhine_remove_one_platform,
.driver = {
.name = DRV_NAME,
.of_match_table = rhine_of_tbl,
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 55fff4d0d380..dd4a07c97eee 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -3247,7 +3247,7 @@ static struct pci_driver velocity_pci_driver = {
static struct platform_driver velocity_platform_driver = {
.probe = velocity_platform_probe,
- .remove_new = velocity_platform_remove,
+ .remove = velocity_platform_remove,
.driver = {
.name = "via-velocity",
.of_match_table = velocity_of_ids,
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
index a4cf682dca65..0ee73a265545 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
@@ -72,14 +72,6 @@ free_queue_irqs:
return err;
}
-static int txgbe_request_gpio_irq(struct txgbe *txgbe)
-{
- txgbe->gpio_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO);
- return request_threaded_irq(txgbe->gpio_irq, NULL,
- txgbe_gpio_irq_handler,
- IRQF_ONESHOT, "txgbe-gpio-irq", txgbe);
-}
-
static int txgbe_request_link_irq(struct txgbe *txgbe)
{
txgbe->link_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK);
@@ -149,11 +141,6 @@ static irqreturn_t txgbe_misc_irq_thread_fn(int irq, void *data)
u32 eicr;
eicr = wx_misc_isb(wx, WX_ISB_MISC);
- if (eicr & TXGBE_PX_MISC_GPIO) {
- sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO);
- handle_nested_irq(sub_irq);
- nhandled++;
- }
if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN |
TXGBE_PX_MISC_ETH_AN)) {
sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK);
@@ -179,7 +166,6 @@ static void txgbe_del_irq_domain(struct txgbe *txgbe)
void txgbe_free_misc_irq(struct txgbe *txgbe)
{
- free_irq(txgbe->gpio_irq, txgbe);
free_irq(txgbe->link_irq, txgbe);
free_irq(txgbe->misc.irq, txgbe);
txgbe_del_irq_domain(txgbe);
@@ -191,7 +177,7 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe)
struct wx *wx = txgbe->wx;
int hwirq, err;
- txgbe->misc.nirqs = 2;
+ txgbe->misc.nirqs = 1;
txgbe->misc.domain = irq_domain_add_simple(NULL, txgbe->misc.nirqs, 0,
&txgbe_misc_irq_domain_ops, txgbe);
if (!txgbe->misc.domain)
@@ -216,20 +202,14 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe)
if (err)
goto del_misc_irq;
- err = txgbe_request_gpio_irq(txgbe);
- if (err)
- goto free_msic_irq;
-
err = txgbe_request_link_irq(txgbe);
if (err)
- goto free_gpio_irq;
+ goto free_msic_irq;
wx->misc_irq_domain = true;
return 0;
-free_gpio_irq:
- free_irq(txgbe->gpio_irq, txgbe);
free_msic_irq:
free_irq(txgbe->misc.irq, txgbe);
del_misc_irq:
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 93180225a6f1..f77450268036 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -82,7 +82,6 @@ static void txgbe_up_complete(struct wx *wx)
{
struct net_device *netdev = wx->netdev;
- txgbe_reinit_gpio_intr(wx);
wx_control_hw(wx, true);
wx_configure_vectors(wx);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
index 67b61afdde96..1ae68f94dd49 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
@@ -122,7 +122,7 @@ static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum
static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
{
struct mii_bus *mii_bus;
- struct dw_xpcs *xpcs;
+ struct phylink_pcs *pcs;
struct pci_dev *pdev;
struct wx *wx;
int ret = 0;
@@ -147,11 +147,11 @@ static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
if (ret)
return ret;
- xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER);
- if (IS_ERR(xpcs))
- return PTR_ERR(xpcs);
+ pcs = xpcs_create_pcs_mdiodev(mii_bus, 0);
+ if (IS_ERR(pcs))
+ return PTR_ERR(pcs);
- txgbe->xpcs = xpcs;
+ txgbe->pcs = pcs;
return 0;
}
@@ -162,8 +162,8 @@ static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *confi
struct wx *wx = phylink_to_wx(config);
struct txgbe *txgbe = wx->priv;
- if (interface == PHY_INTERFACE_MODE_10GBASER)
- return &txgbe->xpcs->pcs;
+ if (wx->media_type != sp_media_copper)
+ return txgbe->pcs;
return NULL;
}
@@ -302,7 +302,7 @@ irqreturn_t txgbe_link_irq_handler(int irq, void *data)
status = rd32(wx, TXGBE_CFG_PORT_ST);
up = !!(status & TXGBE_CFG_PORT_ST_LINK_UP);
- phylink_pcs_change(&txgbe->xpcs->pcs, up);
+ phylink_pcs_change(txgbe->pcs, up);
return IRQ_HANDLED;
}
@@ -358,169 +358,8 @@ static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset,
return 0;
}
-static void txgbe_gpio_irq_ack(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- irq_hw_number_t hwirq = irqd_to_hwirq(d);
- struct wx *wx = gpiochip_get_data(gc);
- unsigned long flags;
-
- raw_spin_lock_irqsave(&wx->gpio_lock, flags);
- wr32(wx, WX_GPIO_EOI, BIT(hwirq));
- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
-}
-
-static void txgbe_gpio_irq_mask(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- irq_hw_number_t hwirq = irqd_to_hwirq(d);
- struct wx *wx = gpiochip_get_data(gc);
- unsigned long flags;
-
- gpiochip_disable_irq(gc, hwirq);
-
- raw_spin_lock_irqsave(&wx->gpio_lock, flags);
- wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq));
- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
-}
-
-static void txgbe_gpio_irq_unmask(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- irq_hw_number_t hwirq = irqd_to_hwirq(d);
- struct wx *wx = gpiochip_get_data(gc);
- unsigned long flags;
-
- gpiochip_enable_irq(gc, hwirq);
-
- raw_spin_lock_irqsave(&wx->gpio_lock, flags);
- wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0);
- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
-}
-
-static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset)
-{
- struct wx *wx = gpiochip_get_data(gc);
- u32 pol, val;
-
- pol = rd32(wx, WX_GPIO_POLARITY);
- val = rd32(wx, WX_GPIO_EXT);
-
- if (val & BIT(offset))
- pol &= ~BIT(offset);
- else
- pol |= BIT(offset);
-
- wr32(wx, WX_GPIO_POLARITY, pol);
-}
-
-static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- irq_hw_number_t hwirq = irqd_to_hwirq(d);
- struct wx *wx = gpiochip_get_data(gc);
- u32 level, polarity, mask;
- unsigned long flags;
-
- mask = BIT(hwirq);
-
- if (type & IRQ_TYPE_LEVEL_MASK) {
- level = 0;
- irq_set_handler_locked(d, handle_level_irq);
- } else {
- level = mask;
- irq_set_handler_locked(d, handle_edge_irq);
- }
-
- if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
- polarity = mask;
- else
- polarity = 0;
-
- raw_spin_lock_irqsave(&wx->gpio_lock, flags);
-
- wr32m(wx, WX_GPIO_INTEN, mask, mask);
- wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level);
- if (type == IRQ_TYPE_EDGE_BOTH)
- txgbe_toggle_trigger(gc, hwirq);
- else
- wr32m(wx, WX_GPIO_POLARITY, mask, polarity);
-
- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
-
- return 0;
-}
-
-static const struct irq_chip txgbe_gpio_irq_chip = {
- .name = "txgbe-gpio-irq",
- .irq_ack = txgbe_gpio_irq_ack,
- .irq_mask = txgbe_gpio_irq_mask,
- .irq_unmask = txgbe_gpio_irq_unmask,
- .irq_set_type = txgbe_gpio_set_type,
- .flags = IRQCHIP_IMMUTABLE,
- GPIOCHIP_IRQ_RESOURCE_HELPERS,
-};
-
-irqreturn_t txgbe_gpio_irq_handler(int irq, void *data)
-{
- struct txgbe *txgbe = data;
- struct wx *wx = txgbe->wx;
- irq_hw_number_t hwirq;
- unsigned long gpioirq;
- struct gpio_chip *gc;
- unsigned long flags;
-
- gpioirq = rd32(wx, WX_GPIO_INTSTATUS);
-
- gc = txgbe->gpio;
- for_each_set_bit(hwirq, &gpioirq, gc->ngpio) {
- int gpio = irq_find_mapping(gc->irq.domain, hwirq);
- struct irq_data *d = irq_get_irq_data(gpio);
- u32 irq_type = irq_get_trigger_type(gpio);
-
- txgbe_gpio_irq_ack(d);
- handle_nested_irq(gpio);
-
- if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
- raw_spin_lock_irqsave(&wx->gpio_lock, flags);
- txgbe_toggle_trigger(gc, hwirq);
- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-void txgbe_reinit_gpio_intr(struct wx *wx)
-{
- struct txgbe *txgbe = wx->priv;
- irq_hw_number_t hwirq;
- unsigned long gpioirq;
- struct gpio_chip *gc;
- unsigned long flags;
-
- /* for gpio interrupt pending before irq enable */
- gpioirq = rd32(wx, WX_GPIO_INTSTATUS);
-
- gc = txgbe->gpio;
- for_each_set_bit(hwirq, &gpioirq, gc->ngpio) {
- int gpio = irq_find_mapping(gc->irq.domain, hwirq);
- struct irq_data *d = irq_get_irq_data(gpio);
- u32 irq_type = irq_get_trigger_type(gpio);
-
- txgbe_gpio_irq_ack(d);
-
- if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
- raw_spin_lock_irqsave(&wx->gpio_lock, flags);
- txgbe_toggle_trigger(gc, hwirq);
- raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
- }
- }
-}
-
static int txgbe_gpio_init(struct txgbe *txgbe)
{
- struct gpio_irq_chip *girq;
struct gpio_chip *gc;
struct device *dev;
struct wx *wx;
@@ -550,11 +389,6 @@ static int txgbe_gpio_init(struct txgbe *txgbe)
gc->direction_input = txgbe_gpio_direction_in;
gc->direction_output = txgbe_gpio_direction_out;
- girq = &gc->irq;
- gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip);
- girq->default_type = IRQ_TYPE_NONE;
- girq->handler = handle_bad_irq;
-
ret = devm_gpiochip_add_data(dev, gc, wx);
if (ret)
return ret;
@@ -578,7 +412,7 @@ static int txgbe_clock_register(struct txgbe *txgbe)
if (IS_ERR(clk))
return PTR_ERR(clk);
- clock = clkdev_create(clk, NULL, clk_name);
+ clock = clkdev_create(clk, NULL, "%s", clk_name);
if (!clock) {
clk_unregister(clk);
return -ENOMEM;
@@ -778,7 +612,7 @@ err_unregister_clk:
err_destroy_phylink:
phylink_destroy(wx->phylink);
err_destroy_xpcs:
- xpcs_destroy(txgbe->xpcs);
+ xpcs_destroy_pcs(txgbe->pcs);
err_unregister_swnode:
software_node_unregister_node_group(txgbe->nodes.group);
@@ -798,6 +632,6 @@ void txgbe_remove_phy(struct txgbe *txgbe)
clkdev_drop(txgbe->clock);
clk_unregister(txgbe->clk);
phylink_destroy(txgbe->wx->phylink);
- xpcs_destroy(txgbe->xpcs);
+ xpcs_destroy_pcs(txgbe->pcs);
software_node_unregister_node_group(txgbe->nodes.group);
}
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
index 8a026d804fe2..3938985355ed 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
@@ -4,8 +4,6 @@
#ifndef _TXGBE_PHY_H_
#define _TXGBE_PHY_H_
-irqreturn_t txgbe_gpio_irq_handler(int irq, void *data);
-void txgbe_reinit_gpio_intr(struct wx *wx);
irqreturn_t txgbe_link_irq_handler(int irq, void *data);
int txgbe_init_phy(struct txgbe *txgbe);
void txgbe_remove_phy(struct txgbe *txgbe);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 959102c4c379..629a13e96b85 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -75,8 +75,7 @@
#define TXGBE_PX_MISC_IEN_MASK \
(TXGBE_PX_MISC_ETH_LKDN | TXGBE_PX_MISC_DEV_RST | \
TXGBE_PX_MISC_ETH_EVENT | TXGBE_PX_MISC_ETH_LK | \
- TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \
- TXGBE_PX_MISC_GPIO)
+ TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR)
/* Port cfg registers */
#define TXGBE_CFG_PORT_ST 0x14404
@@ -313,8 +312,7 @@ struct txgbe_nodes {
};
enum txgbe_misc_irqs {
- TXGBE_IRQ_GPIO = 0,
- TXGBE_IRQ_LINK,
+ TXGBE_IRQ_LINK = 0,
TXGBE_IRQ_MAX
};
@@ -329,13 +327,12 @@ struct txgbe {
struct wx *wx;
struct txgbe_nodes nodes;
struct txgbe_irq misc;
- struct dw_xpcs *xpcs;
+ struct phylink_pcs *pcs;
struct platform_device *sfp_dev;
struct platform_device *i2c_dev;
struct clk_lookup *clock;
struct clk *clk;
struct gpio_chip *gpio;
- unsigned int gpio_irq;
unsigned int link_irq;
/* flow director */
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index b26fd15c25ae..b77f096eaf99 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -1271,6 +1271,6 @@ static struct platform_driver w5100_mmio_driver = {
.pm = &w5100_pm_ops,
},
.probe = w5100_mmio_probe,
- .remove_new = w5100_mmio_remove,
+ .remove = w5100_mmio_remove,
};
module_platform_driver(w5100_mmio_driver);
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index f165616f36fe..3e711dea3b2c 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -681,7 +681,7 @@ static struct platform_driver w5300_driver = {
.pm = &w5300_pm_ops,
},
.probe = w5300_probe,
- .remove_new = w5300_remove,
+ .remove = w5300_remove,
};
module_platform_driver(w5300_driver);
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 1072e2210aed..edb36ff07a0c 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1649,7 +1649,7 @@ MODULE_DEVICE_TABLE(of, temac_of_match);
static struct platform_driver temac_driver = {
.probe = temac_probe,
- .remove_new = temac_remove,
+ .remove = temac_remove,
.driver = {
.name = "xilinx_temac",
.of_match_table = temac_of_match,
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index d940853acc0b..0f4b02fe6f85 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -924,13 +924,13 @@ axienet_start_xmit_dmaengine(struct sk_buff *skb, struct net_device *ndev)
skbuf_dma->sg_len = sg_len;
dma_tx_desc->callback_param = lp;
dma_tx_desc->callback_result = axienet_dma_tx_cb;
- dmaengine_submit(dma_tx_desc);
- dma_async_issue_pending(lp->tx_chan);
txq = skb_get_tx_queue(lp->ndev, skb);
netdev_tx_sent_queue(txq, skb->len);
netif_txq_maybe_stop(txq, CIRC_SPACE(lp->tx_ring_head, lp->tx_ring_tail, TX_BD_NUM_MAX),
MAX_SKB_FRAGS + 1, 2 * MAX_SKB_FRAGS);
+ dmaengine_submit(dma_tx_desc);
+ dma_async_issue_pending(lp->tx_chan);
return NETDEV_TX_OK;
xmit_error_unmap_sg:
@@ -2999,7 +2999,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(axienet_pm_ops,
static struct platform_driver axienet_driver = {
.probe = axienet_probe,
- .remove_new = axienet_remove,
+ .remove = axienet_remove,
.shutdown = axienet_shutdown,
.driver = {
.name = "xilinx_axienet",
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 940452d0a4d2..ecf47107146d 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -7,6 +7,7 @@
* Copyright (c) 2007 - 2013 Xilinx, Inc.
*/
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
@@ -1091,13 +1092,14 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
struct net_device *ndev = NULL;
struct net_local *lp = NULL;
struct device *dev = &ofdev->dev;
+ struct clk *clkin;
int rc = 0;
dev_info(dev, "Device Tree Probing\n");
/* Create an ethernet device instance */
- ndev = alloc_etherdev(sizeof(struct net_local));
+ ndev = devm_alloc_etherdev(dev, sizeof(struct net_local));
if (!ndev)
return -ENOMEM;
@@ -1110,15 +1112,13 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
/* Get IRQ for the device */
rc = platform_get_irq(ofdev, 0);
if (rc < 0)
- goto error;
+ return rc;
ndev->irq = rc;
lp->base_addr = devm_platform_get_and_ioremap_resource(ofdev, 0, &res);
- if (IS_ERR(lp->base_addr)) {
- rc = PTR_ERR(lp->base_addr);
- goto error;
- }
+ if (IS_ERR(lp->base_addr))
+ return PTR_ERR(lp->base_addr);
ndev->mem_start = res->start;
ndev->mem_end = res->end;
@@ -1129,6 +1129,11 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
lp->tx_ping_pong = get_bool(ofdev, "xlnx,tx-ping-pong");
lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong");
+ clkin = devm_clk_get_optional_enabled(&ofdev->dev, NULL);
+ if (IS_ERR(clkin))
+ return dev_err_probe(&ofdev->dev, PTR_ERR(clkin),
+ "Failed to get and enable clock from Device Tree\n");
+
rc = of_get_ethdev_address(ofdev->dev.of_node, ndev);
if (rc) {
dev_warn(dev, "No MAC address found, using random\n");
@@ -1167,8 +1172,6 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
put_node:
of_node_put(lp->phy_node);
-error:
- free_netdev(ndev);
return rc;
}
@@ -1197,8 +1200,6 @@ static void xemaclite_of_remove(struct platform_device *of_dev)
of_node_put(lp->phy_node);
lp->phy_node = NULL;
-
- free_netdev(ndev);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1257,7 +1258,7 @@ static struct platform_driver xemaclite_of_driver = {
.of_match_table = xemaclite_of_match,
},
.probe = xemaclite_of_probe,
- .remove_new = xemaclite_of_remove,
+ .remove = xemaclite_of_remove,
};
module_platform_driver(xemaclite_of_driver);
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index aef316278eb4..a2ab1c150822 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -1619,7 +1619,7 @@ static struct platform_driver ixp4xx_eth_driver = {
.of_match_table = of_match_ptr(ixp4xx_eth_of_match),
},
.probe = ixp4xx_eth_probe,
- .remove_new = ixp4xx_eth_remove,
+ .remove = ixp4xx_eth_remove,
};
module_platform_driver(ixp4xx_eth_driver);
diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 19c99529566b..70c53f33d857 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -87,49 +87,31 @@ static void fjes_get_strings(struct net_device *netdev,
{
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = &adapter->hw;
- u8 *p = data;
int i;
- switch (stringset) {
- case ETH_SS_STATS:
- for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++) {
- memcpy(p, fjes_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
- for (i = 0; i < hw->max_epid; i++) {
- if (i == hw->my_epid)
- continue;
- sprintf(p, "ep%u_com_regist_buf_exec", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_com_unregist_buf_exec", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_send_intr_rx", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_send_intr_unshare", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_send_intr_zoneupdate", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_recv_intr_rx", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_recv_intr_unshare", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_recv_intr_stop", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_recv_intr_zoneupdate", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_tx_buffer_full", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_tx_dropped_not_shared", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_tx_dropped_ver_mismatch", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_tx_dropped_buf_size_mismatch", i);
- p += ETH_GSTRING_LEN;
- sprintf(p, "ep%u_tx_dropped_vlanid_mismatch", i);
- p += ETH_GSTRING_LEN;
- }
- break;
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++)
+ ethtool_puts(&data, fjes_gstrings_stats[i].stat_string);
+
+ for (i = 0; i < hw->max_epid; i++) {
+ if (i == hw->my_epid)
+ continue;
+ ethtool_sprintf(&data, "ep%u_com_regist_buf_exec", i);
+ ethtool_sprintf(&data, "ep%u_com_unregist_buf_exec", i);
+ ethtool_sprintf(&data, "ep%u_send_intr_rx", i);
+ ethtool_sprintf(&data, "ep%u_send_intr_unshare", i);
+ ethtool_sprintf(&data, "ep%u_send_intr_zoneupdate", i);
+ ethtool_sprintf(&data, "ep%u_recv_intr_rx", i);
+ ethtool_sprintf(&data, "ep%u_recv_intr_unshare", i);
+ ethtool_sprintf(&data, "ep%u_recv_intr_stop", i);
+ ethtool_sprintf(&data, "ep%u_recv_intr_zoneupdate", i);
+ ethtool_sprintf(&data, "ep%u_tx_buffer_full", i);
+ ethtool_sprintf(&data, "ep%u_tx_dropped_not_shared", i);
+ ethtool_sprintf(&data, "ep%u_tx_dropped_ver_mismatch", i);
+ ethtool_sprintf(&data, "ep%u_tx_dropped_buf_size_mismatch", i);
+ ethtool_sprintf(&data, "ep%u_tx_dropped_vlanid_mismatch", i);
}
}
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index fad5b6564464..4a4ed2ccf72f 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -1466,7 +1466,7 @@ static struct platform_driver fjes_driver = {
.name = DRV_NAME,
},
.probe = fjes_probe,
- .remove_new = fjes_remove,
+ .remove = fjes_remove,
};
static acpi_status
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 7f611c74eb62..2f29b1386b1c 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -827,7 +827,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
__be16 sport;
int err;
- if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
+ if (skb_vlan_inet_prepare(skb, inner_proto_inherit))
return -EINVAL;
if (!gs4)
@@ -937,7 +937,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
__be16 sport;
int err;
- if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
+ if (skb_vlan_inet_prepare(skb, inner_proto_inherit))
return -EINVAL;
if (!gs6)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 70f981887518..89a996ad8cd0 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -1491,10 +1491,8 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
}
gtp->role = role;
- if (!data[IFLA_GTP_RESTART_COUNT])
- gtp->restart_count = 0;
- else
- gtp->restart_count = nla_get_u8(data[IFLA_GTP_RESTART_COUNT]);
+ gtp->restart_count = nla_get_u8_default(data[IFLA_GTP_RESTART_COUNT],
+ 0);
gtp->net = src_net;
@@ -1829,10 +1827,7 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
version = nla_get_u32(info->attrs[GTPA_VERSION]);
- if (info->attrs[GTPA_FAMILY])
- family = nla_get_u8(info->attrs[GTPA_FAMILY]);
- else
- family = AF_INET;
+ family = nla_get_u8_default(info->attrs[GTPA_FAMILY], AF_INET);
#if !IS_ENABLED(CONFIG_IPV6)
if (family == AF_INET6)
@@ -2069,10 +2064,7 @@ static struct pdp_ctx *gtp_find_pdp_by_link(struct net *net,
struct gtp_dev *gtp;
int family;
- if (nla[GTPA_FAMILY])
- family = nla_get_u8(nla[GTPA_FAMILY]);
- else
- family = AF_INET;
+ family = nla_get_u8_default(nla[GTPA_FAMILY], AF_INET);
gtp = gtp_find_dev(net, nla);
if (!gtp)
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 646f605e358f..799f8ece7824 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -373,6 +373,7 @@ static enum uart ser12_check_uart(unsigned int iobase)
static int ser12_open(struct net_device *dev)
{
+ const unsigned int nr_irqs = irq_get_nr_irqs();
struct baycom_state *bc = netdev_priv(dev);
enum uart u;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index a9184a78650b..c71e52249289 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1460,6 +1460,7 @@ scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern
static void z8530_init(void)
{
+ const unsigned int nr_irqs = irq_get_nr_irqs();
struct scc_channel *scc;
int chip, k;
unsigned long flags;
@@ -1735,7 +1736,7 @@ static int scc_net_siocdevprivate(struct net_device *dev,
if (hwcfg.irq == 2) hwcfg.irq = 9;
- if (hwcfg.irq < 0 || hwcfg.irq >= nr_irqs)
+ if (hwcfg.irq < 0 || hwcfg.irq >= irq_get_nr_irqs())
return -EINVAL;
if (!Ivec[hwcfg.irq].used && hwcfg.irq)
@@ -2117,6 +2118,7 @@ static int __init scc_init_driver (void)
static void __exit scc_cleanup_driver(void)
{
+ const unsigned int nr_irqs = irq_get_nr_irqs();
io_port ctrl;
int k;
struct scc_channel *scc;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 2b6ec979a62f..9afb08dbc350 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -712,8 +712,13 @@ void netvsc_device_remove(struct hv_device *device)
for (i = 0; i < net_device->num_chn; i++) {
/* See also vmbus_reset_channel_cb(). */
/* only disable enabled NAPI channel */
- if (i < ndev->real_num_rx_queues)
+ if (i < ndev->real_num_rx_queues) {
+ netif_queue_set_napi(ndev, i, NETDEV_QUEUE_TYPE_TX,
+ NULL);
+ netif_queue_set_napi(ndev, i, NETDEV_QUEUE_TYPE_RX,
+ NULL);
napi_disable(&net_device->chan_table[i].napi);
+ }
netif_napi_del(&net_device->chan_table[i].napi);
}
@@ -1787,6 +1792,10 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
netdev_dbg(ndev, "hv_netvsc channel opened successfully\n");
napi_enable(&net_device->chan_table[0].napi);
+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX,
+ &net_device->chan_table[0].napi);
+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX,
+ &net_device->chan_table[0].napi);
/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device, net_device, device_info);
@@ -1805,6 +1814,8 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
close:
RCU_INIT_POINTER(net_device_ctx->nvdev, NULL);
+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL);
+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL);
napi_disable(&net_device->chan_table[0].napi);
/* Now, we can close the channel safely */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 23180f7b67b6..d6c4abfc3a28 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1557,7 +1557,7 @@ static void netvsc_get_ethtool_stats(struct net_device *dev,
data[i++] = xdp_tx;
}
- pcpu_sum = kvmalloc_array(num_possible_cpus(),
+ pcpu_sum = kvmalloc_array(nr_cpu_ids,
sizeof(struct netvsc_ethtool_pcpu_stats),
GFP_KERNEL);
if (!pcpu_sum)
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index ecc2128ca9b7..c0ceeef4fcd8 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1269,10 +1269,15 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
ret = vmbus_open(new_sc, netvsc_ring_bytes,
netvsc_ring_bytes, NULL, 0,
netvsc_channel_cb, nvchan);
- if (ret == 0)
+ if (ret == 0) {
napi_enable(&nvchan->napi);
- else
+ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX,
+ &nvchan->napi);
+ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX,
+ &nvchan->napi);
+ } else {
netdev_notice(ndev, "sub channel open failed: %d\n", ret);
+ }
if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn)
wake_up(&nvscdev->subchan_open);
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index 2930141d7dd2..e11d8eda85ea 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -235,7 +235,7 @@ static struct platform_device *ieee802154fake_dev;
static struct platform_driver ieee802154fake_driver = {
.probe = fakelb_probe,
- .remove_new = fakelb_remove,
+ .remove = fakelb_remove,
.driver = {
.name = "ieee802154fakelb",
},
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 2c2483bbe780..1cab20b5a885 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -1047,7 +1047,7 @@ static void hwsim_remove(struct platform_device *pdev)
static struct platform_driver mac802154hwsim_driver = {
.probe = hwsim_probe,
- .remove_new = hwsim_remove,
+ .remove = hwsim_remove,
.driver = {
.name = "mac802154_hwsim",
},
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 2c1b5def4a0b..67424888ff0a 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -426,22 +426,21 @@ static int __init ifb_init_module(void)
{
int i, err;
- down_write(&pernet_ops_rwsem);
- rtnl_lock();
- err = __rtnl_link_register(&ifb_link_ops);
+ err = rtnl_link_register(&ifb_link_ops);
if (err < 0)
- goto out;
+ return err;
+
+ rtnl_net_lock(&init_net);
for (i = 0; i < numifbs && !err; i++) {
err = ifb_init_one(i);
cond_resched();
}
- if (err)
- __rtnl_link_unregister(&ifb_link_ops);
-out:
- rtnl_unlock();
- up_write(&pernet_ops_rwsem);
+ rtnl_net_unlock(&init_net);
+
+ if (err)
+ rtnl_link_unregister(&ifb_link_ops);
return err;
}
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c
index 5f3dd5a2dcf4..f25f6e2cf58c 100644
--- a/drivers/net/ipa/ipa_main.c
+++ b/drivers/net/ipa/ipa_main.c
@@ -1012,7 +1012,7 @@ static const struct attribute_group *ipa_attribute_groups[] = {
static struct platform_driver ipa_driver = {
.probe = ipa_probe,
- .remove_new = ipa_remove,
+ .remove = ipa_remove,
.shutdown = ipa_remove,
.driver = {
.name = "ipa",
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index b1afcb8740de..fd591ddb3884 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -3,6 +3,7 @@
*/
#include <net/inet_dscp.h>
+#include <net/ip.h>
#include "ipvlan.h"
@@ -422,7 +423,7 @@ static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb)
int err, ret = NET_XMIT_DROP;
struct flowi4 fl4 = {
.flowi4_oif = dev->ifindex,
- .flowi4_tos = ip4h->tos & INET_DSCP_MASK,
+ .flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h)),
.flowi4_flags = FLOWI_FLAG_ANYSRC,
.flowi4_mark = skb->mark,
.daddr = ip4h->daddr,
diff --git a/drivers/net/ipvlan/ipvlan_l3s.c b/drivers/net/ipvlan/ipvlan_l3s.c
index d5b05e803219..b4ef386bdb1b 100644
--- a/drivers/net/ipvlan/ipvlan_l3s.c
+++ b/drivers/net/ipvlan/ipvlan_l3s.c
@@ -2,6 +2,8 @@
/* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
*/
+#include <net/ip.h>
+
#include "ipvlan.h"
static unsigned int ipvlan_netid __read_mostly;
@@ -48,11 +50,11 @@ static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev,
switch (proto) {
case AF_INET:
{
- struct iphdr *ip4h = ip_hdr(skb);
+ const struct iphdr *ip4h = ip_hdr(skb);
int err;
err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
- ip4h->tos, sdev);
+ ip4h_dscp(ip4h), sdev);
if (unlikely(err))
goto out;
break;
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index ee2159282573..1bc1e5993f56 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -2621,6 +2621,17 @@ static void macsec_set_head_tail_room(struct net_device *dev)
dev->needed_tailroom = real_dev->needed_tailroom + needed_tailroom;
}
+static void macsec_inherit_tso_max(struct net_device *dev)
+{
+ struct macsec_dev *macsec = macsec_priv(dev);
+
+ /* if macsec is offloaded, we need to follow the lower
+ * device's capabilities. otherwise, we can ignore them.
+ */
+ if (macsec_is_offloaded(macsec))
+ netif_inherit_tso_max(dev, macsec->real_dev);
+}
+
static int macsec_update_offload(struct net_device *dev, enum macsec_offload offload)
{
enum macsec_offload prev_offload;
@@ -2666,6 +2677,10 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload off
macsec_set_head_tail_room(dev);
macsec->insert_tx_tag = macsec_needs_tx_tag(macsec, ops);
+ macsec_inherit_tso_max(dev);
+
+ netdev_update_features(dev);
+
return ret;
}
@@ -3521,6 +3536,10 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
#define MACSEC_FEATURES \
(NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
+#define MACSEC_OFFLOAD_FEATURES \
+ (MACSEC_FEATURES | NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES | \
+ NETIF_F_LRO | NETIF_F_RXHASH | NETIF_F_CSUM_MASK | NETIF_F_RXCSUM)
+
static int macsec_dev_init(struct net_device *dev)
{
struct macsec_dev *macsec = macsec_priv(dev);
@@ -3531,7 +3550,12 @@ static int macsec_dev_init(struct net_device *dev)
if (err)
return err;
- dev->features = real_dev->features & MACSEC_FEATURES;
+ macsec_inherit_tso_max(dev);
+
+ dev->hw_features = real_dev->hw_features & MACSEC_OFFLOAD_FEATURES;
+ dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+
+ dev->features = real_dev->features & MACSEC_OFFLOAD_FEATURES;
dev->features |= NETIF_F_GSO_SOFTWARE;
dev->lltx = true;
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
@@ -3561,8 +3585,12 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
{
struct macsec_dev *macsec = macsec_priv(dev);
struct net_device *real_dev = macsec->real_dev;
+ netdev_features_t mask;
+
+ mask = macsec_is_offloaded(macsec) ? MACSEC_OFFLOAD_FEATURES
+ : MACSEC_FEATURES;
- features &= (real_dev->features & MACSEC_FEATURES) |
+ features &= (real_dev->features & mask) |
NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES;
return features;
@@ -4299,9 +4327,9 @@ static int macsec_validate_attr(struct nlattr *tb[], struct nlattr *data[],
}
}
- es = data[IFLA_MACSEC_ES] ? nla_get_u8(data[IFLA_MACSEC_ES]) : false;
- sci = data[IFLA_MACSEC_INC_SCI] ? nla_get_u8(data[IFLA_MACSEC_INC_SCI]) : false;
- scb = data[IFLA_MACSEC_SCB] ? nla_get_u8(data[IFLA_MACSEC_SCB]) : false;
+ es = nla_get_u8_default(data[IFLA_MACSEC_ES], false);
+ sci = nla_get_u8_default(data[IFLA_MACSEC_INC_SCI], false);
+ scb = nla_get_u8_default(data[IFLA_MACSEC_SCB], false);
if ((sci && (scb || es)) || (scb && es))
return -EINVAL;
@@ -4428,31 +4456,26 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
void *ptr)
{
struct net_device *real_dev = netdev_notifier_info_to_dev(ptr);
+ struct macsec_rxh_data *rxd;
+ struct macsec_dev *m, *n;
LIST_HEAD(head);
if (!is_macsec_master(real_dev))
return NOTIFY_DONE;
+ rxd = macsec_data_rtnl(real_dev);
+
switch (event) {
case NETDEV_DOWN:
case NETDEV_UP:
- case NETDEV_CHANGE: {
- struct macsec_dev *m, *n;
- struct macsec_rxh_data *rxd;
-
- rxd = macsec_data_rtnl(real_dev);
+ case NETDEV_CHANGE:
list_for_each_entry_safe(m, n, &rxd->secys, secys) {
struct net_device *dev = m->secy.netdev;
netif_stacked_transfer_operstate(real_dev, dev);
}
break;
- }
- case NETDEV_UNREGISTER: {
- struct macsec_dev *m, *n;
- struct macsec_rxh_data *rxd;
-
- rxd = macsec_data_rtnl(real_dev);
+ case NETDEV_UNREGISTER:
list_for_each_entry_safe(m, n, &rxd->secys, secys) {
macsec_common_dellink(m->secy.netdev, &head);
}
@@ -4462,12 +4485,7 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
unregister_netdevice_many(&head);
break;
- }
- case NETDEV_CHANGEMTU: {
- struct macsec_dev *m;
- struct macsec_rxh_data *rxd;
-
- rxd = macsec_data_rtnl(real_dev);
+ case NETDEV_CHANGEMTU:
list_for_each_entry(m, &rxd->secys, secys) {
struct net_device *dev = m->secy.netdev;
unsigned int mtu = real_dev->mtu - (m->secy.icv_len +
@@ -4476,7 +4494,13 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
if (dev->mtu > mtu)
dev_set_mtu(dev, mtu);
}
- }
+ break;
+ case NETDEV_FEAT_CHANGE:
+ list_for_each_entry(m, &rxd->secys, secys) {
+ macsec_inherit_tso_max(m->secy.netdev);
+ netdev_update_features(m->secy.netdev);
+ }
+ break;
}
return NOTIFY_OK;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index cf18e66de142..fed4fe2a4748 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1024,7 +1024,7 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid,
- u16 flags,
+ u16 flags, bool *notified,
struct netlink_ext_ack *extack)
{
struct macvlan_dev *vlan = netdev_priv(dev);
@@ -1049,7 +1049,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
- const unsigned char *addr, u16 vid,
+ const unsigned char *addr, u16 vid, bool *notified,
struct netlink_ext_ack *extack)
{
struct macvlan_dev *vlan = netdev_priv(dev);
@@ -1117,7 +1117,7 @@ static void macvlan_dev_poll_controller(struct net_device *dev)
return;
}
-static int macvlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo)
+static int macvlan_dev_netpoll_setup(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *real_dev = vlan->lowerdev;
diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c
index e70fb6687994..d2b3f5a59141 100644
--- a/drivers/net/mctp/mctp-i2c.c
+++ b/drivers/net/mctp/mctp-i2c.c
@@ -880,7 +880,8 @@ static int mctp_i2c_add_netdev(struct mctp_i2c_client *mcli,
goto err;
}
- rc = mctp_register_netdev(ndev, &mctp_i2c_mctp_ops);
+ rc = mctp_register_netdev(ndev, &mctp_i2c_mctp_ops,
+ MCTP_PHYS_BINDING_SMBUS);
if (rc < 0) {
dev_err(&mcli->client->dev,
"register netdev \"%s\" failed %d\n",
diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c
index 1bc87a062686..9adad59b8676 100644
--- a/drivers/net/mctp/mctp-i3c.c
+++ b/drivers/net/mctp/mctp-i3c.c
@@ -607,7 +607,7 @@ __must_hold(&busdevs_lock)
goto err_free_uninit;
}
- rc = mctp_register_netdev(ndev, NULL);
+ rc = mctp_register_netdev(ndev, NULL, MCTP_PHYS_BINDING_I3C);
if (rc < 0) {
dev_warn(&ndev->dev, "netdev register failed: %d\n", rc);
goto err_free_netdev;
diff --git a/drivers/net/mctp/mctp-serial.c b/drivers/net/mctp/mctp-serial.c
index e63720ec3238..26c9a33fd636 100644
--- a/drivers/net/mctp/mctp-serial.c
+++ b/drivers/net/mctp/mctp-serial.c
@@ -23,6 +23,7 @@
#include <linux/mctp.h>
#include <net/mctp.h>
+#include <net/mctpdevice.h>
#include <net/pkt_sched.h>
#define MCTP_SERIAL_MTU 68 /* base mtu (64) + mctp header */
@@ -470,7 +471,7 @@ static int mctp_serial_open(struct tty_struct *tty)
spin_lock_init(&dev->lock);
INIT_WORK(&dev->tx_work, mctp_serial_tx_work);
- rc = register_netdev(ndev);
+ rc = mctp_register_netdev(ndev, NULL, MCTP_PHYS_BINDING_SERIAL);
if (rc)
goto free_netdev;
@@ -492,7 +493,7 @@ static void mctp_serial_close(struct tty_struct *tty)
struct mctp_serial *dev = tty->disc_data;
int idx = dev->idx;
- unregister_netdev(dev->netdev);
+ mctp_unregister_netdev(dev->netdev);
ida_free(&mctp_serial_ida, idx);
}
diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c
index e08c90ac0c6e..f67a4d4005e7 100644
--- a/drivers/net/mdio.c
+++ b/drivers/net/mdio.c
@@ -167,178 +167,6 @@ static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr)
}
/**
- * mdio45_ethtool_gset_npage - get settings for ETHTOOL_GSET
- * @mdio: MDIO interface
- * @ecmd: Ethtool request structure
- * @npage_adv: Modes currently advertised on next pages
- * @npage_lpa: Modes advertised by link partner on next pages
- *
- * The @ecmd parameter is expected to have been cleared before calling
- * mdio45_ethtool_gset_npage().
- *
- * Since the CSRs for auto-negotiation using next pages are not fully
- * standardised, this function does not attempt to decode them. The
- * caller must pass them in.
- */
-void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
- struct ethtool_cmd *ecmd,
- u32 npage_adv, u32 npage_lpa)
-{
- int reg;
- u32 speed;
-
- BUILD_BUG_ON(MDIO_SUPPORTS_C22 != ETH_MDIO_SUPPORTS_C22);
- BUILD_BUG_ON(MDIO_SUPPORTS_C45 != ETH_MDIO_SUPPORTS_C45);
-
- ecmd->transceiver = XCVR_INTERNAL;
- ecmd->phy_address = mdio->prtad;
- ecmd->mdio_support =
- mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22);
-
- reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
- MDIO_CTRL2);
- switch (reg & MDIO_PMA_CTRL2_TYPE) {
- case MDIO_PMA_CTRL2_10GBT:
- case MDIO_PMA_CTRL2_1000BT:
- case MDIO_PMA_CTRL2_100BTX:
- case MDIO_PMA_CTRL2_10BT:
- ecmd->port = PORT_TP;
- ecmd->supported = SUPPORTED_TP;
- reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
- MDIO_SPEED);
- if (reg & MDIO_SPEED_10G)
- ecmd->supported |= SUPPORTED_10000baseT_Full;
- if (reg & MDIO_PMA_SPEED_1000)
- ecmd->supported |= (SUPPORTED_1000baseT_Full |
- SUPPORTED_1000baseT_Half);
- if (reg & MDIO_PMA_SPEED_100)
- ecmd->supported |= (SUPPORTED_100baseT_Full |
- SUPPORTED_100baseT_Half);
- if (reg & MDIO_PMA_SPEED_10)
- ecmd->supported |= (SUPPORTED_10baseT_Full |
- SUPPORTED_10baseT_Half);
- ecmd->advertising = ADVERTISED_TP;
- break;
-
- case MDIO_PMA_CTRL2_10GBCX4:
- ecmd->port = PORT_OTHER;
- ecmd->supported = 0;
- ecmd->advertising = 0;
- break;
-
- case MDIO_PMA_CTRL2_10GBKX4:
- case MDIO_PMA_CTRL2_10GBKR:
- case MDIO_PMA_CTRL2_1000BKX:
- ecmd->port = PORT_OTHER;
- ecmd->supported = SUPPORTED_Backplane;
- reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
- MDIO_PMA_EXTABLE);
- if (reg & MDIO_PMA_EXTABLE_10GBKX4)
- ecmd->supported |= SUPPORTED_10000baseKX4_Full;
- if (reg & MDIO_PMA_EXTABLE_10GBKR)
- ecmd->supported |= SUPPORTED_10000baseKR_Full;
- if (reg & MDIO_PMA_EXTABLE_1000BKX)
- ecmd->supported |= SUPPORTED_1000baseKX_Full;
- reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
- MDIO_PMA_10GBR_FECABLE);
- if (reg & MDIO_PMA_10GBR_FECABLE_ABLE)
- ecmd->supported |= SUPPORTED_10000baseR_FEC;
- ecmd->advertising = ADVERTISED_Backplane;
- break;
-
- /* All the other defined modes are flavours of optical */
- default:
- ecmd->port = PORT_FIBRE;
- ecmd->supported = SUPPORTED_FIBRE;
- ecmd->advertising = ADVERTISED_FIBRE;
- break;
- }
-
- if (mdio->mmds & MDIO_DEVS_AN) {
- ecmd->supported |= SUPPORTED_Autoneg;
- reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
- MDIO_CTRL1);
- if (reg & MDIO_AN_CTRL1_ENABLE) {
- ecmd->autoneg = AUTONEG_ENABLE;
- ecmd->advertising |=
- ADVERTISED_Autoneg |
- mdio45_get_an(mdio, MDIO_AN_ADVERTISE) |
- npage_adv;
- } else {
- ecmd->autoneg = AUTONEG_DISABLE;
- }
- } else {
- ecmd->autoneg = AUTONEG_DISABLE;
- }
-
- if (ecmd->autoneg) {
- u32 modes = 0;
- int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad,
- MDIO_MMD_AN, MDIO_STAT1);
-
- /* If AN is complete and successful, report best common
- * mode, otherwise report best advertised mode. */
- if (an_stat & MDIO_AN_STAT1_COMPLETE) {
- ecmd->lp_advertising =
- mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa;
- if (an_stat & MDIO_AN_STAT1_LPABLE)
- ecmd->lp_advertising |= ADVERTISED_Autoneg;
- modes = ecmd->advertising & ecmd->lp_advertising;
- }
- if ((modes & ~ADVERTISED_Autoneg) == 0)
- modes = ecmd->advertising;
-
- if (modes & (ADVERTISED_10000baseT_Full |
- ADVERTISED_10000baseKX4_Full |
- ADVERTISED_10000baseKR_Full)) {
- speed = SPEED_10000;
- ecmd->duplex = DUPLEX_FULL;
- } else if (modes & (ADVERTISED_1000baseT_Full |
- ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseKX_Full)) {
- speed = SPEED_1000;
- ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half);
- } else if (modes & (ADVERTISED_100baseT_Full |
- ADVERTISED_100baseT_Half)) {
- speed = SPEED_100;
- ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
- } else {
- speed = SPEED_10;
- ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
- }
- } else {
- /* Report forced settings */
- reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
- MDIO_CTRL1);
- speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1)
- * ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10));
- ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX ||
- speed == SPEED_10000);
- }
-
- ethtool_cmd_speed_set(ecmd, speed);
-
- /* 10GBASE-T MDI/MDI-X */
- if (ecmd->port == PORT_TP
- && (ethtool_cmd_speed(ecmd) == SPEED_10000)) {
- switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
- MDIO_PMA_10GBT_SWAPPOL)) {
- case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
- ecmd->eth_tp_mdix = ETH_TP_MDI;
- break;
- case 0:
- ecmd->eth_tp_mdix = ETH_TP_MDI_X;
- break;
- default:
- /* It's complicated... */
- ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
- break;
- }
- }
-}
-EXPORT_SYMBOL(mdio45_ethtool_gset_npage);
-
-/**
* mdio45_ethtool_ksettings_get_npage - get settings for ETHTOOL_GLINKSETTINGS
* @mdio: MDIO interface
* @cmd: Ethtool request structure
diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c
index c2170650415c..e55be6dc9ae7 100644
--- a/drivers/net/mdio/mdio-aspeed.c
+++ b/drivers/net/mdio/mdio-aspeed.c
@@ -198,7 +198,7 @@ static struct platform_driver aspeed_mdio_driver = {
.of_match_table = aspeed_mdio_of_match,
},
.probe = aspeed_mdio_probe,
- .remove_new = aspeed_mdio_remove,
+ .remove = aspeed_mdio_remove,
};
module_platform_driver(aspeed_mdio_driver);
diff --git a/drivers/net/mdio/mdio-bcm-iproc.c b/drivers/net/mdio/mdio-bcm-iproc.c
index 5a2d26c6afdc..91690b496793 100644
--- a/drivers/net/mdio/mdio-bcm-iproc.c
+++ b/drivers/net/mdio/mdio-bcm-iproc.c
@@ -208,7 +208,7 @@ static struct platform_driver iproc_mdio_driver = {
#endif
},
.probe = iproc_mdio_probe,
- .remove_new = iproc_mdio_remove,
+ .remove = iproc_mdio_remove,
};
module_platform_driver(iproc_mdio_driver);
diff --git a/drivers/net/mdio/mdio-bcm-unimac.c b/drivers/net/mdio/mdio-bcm-unimac.c
index b7bc70586ee0..074d96328f41 100644
--- a/drivers/net/mdio/mdio-bcm-unimac.c
+++ b/drivers/net/mdio/mdio-bcm-unimac.c
@@ -355,7 +355,7 @@ static struct platform_driver unimac_mdio_driver = {
.pm = &unimac_mdio_pm_ops,
},
.probe = unimac_mdio_probe,
- .remove_new = unimac_mdio_remove,
+ .remove = unimac_mdio_remove,
};
module_platform_driver(unimac_mdio_driver);
diff --git a/drivers/net/mdio/mdio-gpio.c b/drivers/net/mdio/mdio-gpio.c
index 82088741debd..1cfd538b5105 100644
--- a/drivers/net/mdio/mdio-gpio.c
+++ b/drivers/net/mdio/mdio-gpio.c
@@ -207,7 +207,7 @@ MODULE_DEVICE_TABLE(of, mdio_gpio_of_match);
static struct platform_driver mdio_gpio_driver = {
.probe = mdio_gpio_probe,
- .remove_new = mdio_gpio_remove,
+ .remove = mdio_gpio_remove,
.driver = {
.name = "mdio-gpio",
.of_match_table = mdio_gpio_of_match,
diff --git a/drivers/net/mdio/mdio-hisi-femac.c b/drivers/net/mdio/mdio-hisi-femac.c
index 6703f626ee83..d78a1dc36cfd 100644
--- a/drivers/net/mdio/mdio-hisi-femac.c
+++ b/drivers/net/mdio/mdio-hisi-femac.c
@@ -136,7 +136,7 @@ MODULE_DEVICE_TABLE(of, hisi_femac_mdio_dt_ids);
static struct platform_driver hisi_femac_mdio_driver = {
.probe = hisi_femac_mdio_probe,
- .remove_new = hisi_femac_mdio_remove,
+ .remove = hisi_femac_mdio_remove,
.driver = {
.name = "hisi-femac-mdio",
.of_match_table = hisi_femac_mdio_dt_ids,
diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c
index 9d8f43b28aac..d9a94df482d9 100644
--- a/drivers/net/mdio/mdio-ipq4019.c
+++ b/drivers/net/mdio/mdio-ipq4019.c
@@ -352,8 +352,11 @@ static int ipq4019_mdio_probe(struct platform_device *pdev)
/* The platform resource is provided on the chipset IPQ5018 */
/* This resource is optional */
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
+ if (res) {
priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->eth_ldo_rdy))
+ return PTR_ERR(priv->eth_ldo_rdy);
+ }
bus->name = "ipq4019_mdio";
bus->read = ipq4019_mdio_read_c22;
@@ -391,7 +394,7 @@ MODULE_DEVICE_TABLE(of, ipq4019_mdio_dt_ids);
static struct platform_driver ipq4019_mdio_driver = {
.probe = ipq4019_mdio_probe,
- .remove_new = ipq4019_mdio_remove,
+ .remove = ipq4019_mdio_remove,
.driver = {
.name = "ipq4019-mdio",
.of_match_table = ipq4019_mdio_dt_ids,
diff --git a/drivers/net/mdio/mdio-ipq8064.c b/drivers/net/mdio/mdio-ipq8064.c
index f71b6e1c66e4..6253a9ab8b69 100644
--- a/drivers/net/mdio/mdio-ipq8064.c
+++ b/drivers/net/mdio/mdio-ipq8064.c
@@ -162,7 +162,7 @@ MODULE_DEVICE_TABLE(of, ipq8064_mdio_dt_ids);
static struct platform_driver ipq8064_mdio_driver = {
.probe = ipq8064_mdio_probe,
- .remove_new = ipq8064_mdio_remove,
+ .remove = ipq8064_mdio_remove,
.driver = {
.name = "ipq8064-mdio",
.of_match_table = ipq8064_mdio_dt_ids,
diff --git a/drivers/net/mdio/mdio-moxart.c b/drivers/net/mdio/mdio-moxart.c
index d35af8cd7c4d..9853be6f0f22 100644
--- a/drivers/net/mdio/mdio-moxart.c
+++ b/drivers/net/mdio/mdio-moxart.c
@@ -171,7 +171,7 @@ MODULE_DEVICE_TABLE(of, moxart_mdio_dt_ids);
static struct platform_driver moxart_mdio_driver = {
.probe = moxart_mdio_probe,
- .remove_new = moxart_mdio_remove,
+ .remove = moxart_mdio_remove,
.driver = {
.name = "moxart-mdio",
.of_match_table = moxart_mdio_dt_ids,
diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c
index 62c47e0dd142..944efd33da6d 100644
--- a/drivers/net/mdio/mdio-mscc-miim.c
+++ b/drivers/net/mdio/mdio-mscc-miim.c
@@ -377,7 +377,7 @@ MODULE_DEVICE_TABLE(of, mscc_miim_match);
static struct platform_driver mscc_miim_driver = {
.probe = mscc_miim_probe,
- .remove_new = mscc_miim_remove,
+ .remove = mscc_miim_remove,
.driver = {
.name = "mscc-miim",
.of_match_table = mscc_miim_match,
diff --git a/drivers/net/mdio/mdio-mux-bcm-iproc.c b/drivers/net/mdio/mdio-mux-bcm-iproc.c
index 1ce7d67ba72e..8ba0917a930a 100644
--- a/drivers/net/mdio/mdio-mux-bcm-iproc.c
+++ b/drivers/net/mdio/mdio-mux-bcm-iproc.c
@@ -342,7 +342,7 @@ static struct platform_driver mdiomux_iproc_driver = {
.pm = &mdio_mux_iproc_pm_ops,
},
.probe = mdio_mux_iproc_probe,
- .remove_new = mdio_mux_iproc_remove,
+ .remove = mdio_mux_iproc_remove,
};
module_platform_driver(mdiomux_iproc_driver);
diff --git a/drivers/net/mdio/mdio-mux-bcm6368.c b/drivers/net/mdio/mdio-mux-bcm6368.c
index 1b77e0e3e6e1..476f8b72d020 100644
--- a/drivers/net/mdio/mdio-mux-bcm6368.c
+++ b/drivers/net/mdio/mdio-mux-bcm6368.c
@@ -173,7 +173,7 @@ static struct platform_driver bcm6368_mdiomux_driver = {
.of_match_table = bcm6368_mdiomux_ids,
},
.probe = bcm6368_mdiomux_probe,
- .remove_new = bcm6368_mdiomux_remove,
+ .remove = bcm6368_mdiomux_remove,
};
module_platform_driver(bcm6368_mdiomux_driver);
diff --git a/drivers/net/mdio/mdio-mux-gpio.c b/drivers/net/mdio/mdio-mux-gpio.c
index 38fb031f8979..ef77bd1abae9 100644
--- a/drivers/net/mdio/mdio-mux-gpio.c
+++ b/drivers/net/mdio/mdio-mux-gpio.c
@@ -86,7 +86,7 @@ static struct platform_driver mdio_mux_gpio_driver = {
.of_match_table = mdio_mux_gpio_match,
},
.probe = mdio_mux_gpio_probe,
- .remove_new = mdio_mux_gpio_remove,
+ .remove = mdio_mux_gpio_remove,
};
module_platform_driver(mdio_mux_gpio_driver);
diff --git a/drivers/net/mdio/mdio-mux-meson-g12a.c b/drivers/net/mdio/mdio-mux-meson-g12a.c
index 754b0f2cf15b..08d6a6c93fb8 100644
--- a/drivers/net/mdio/mdio-mux-meson-g12a.c
+++ b/drivers/net/mdio/mdio-mux-meson-g12a.c
@@ -348,7 +348,7 @@ static void g12a_mdio_mux_remove(struct platform_device *pdev)
static struct platform_driver g12a_mdio_mux_driver = {
.probe = g12a_mdio_mux_probe,
- .remove_new = g12a_mdio_mux_remove,
+ .remove = g12a_mdio_mux_remove,
.driver = {
.name = "g12a-mdio_mux",
.of_match_table = g12a_mdio_mux_match,
diff --git a/drivers/net/mdio/mdio-mux-meson-gxl.c b/drivers/net/mdio/mdio-mux-meson-gxl.c
index 89554021b5cc..00c66240136b 100644
--- a/drivers/net/mdio/mdio-mux-meson-gxl.c
+++ b/drivers/net/mdio/mdio-mux-meson-gxl.c
@@ -149,7 +149,7 @@ static void gxl_mdio_mux_remove(struct platform_device *pdev)
static struct platform_driver gxl_mdio_mux_driver = {
.probe = gxl_mdio_mux_probe,
- .remove_new = gxl_mdio_mux_remove,
+ .remove = gxl_mdio_mux_remove,
.driver = {
.name = "gxl-mdio-mux",
.of_match_table = gxl_mdio_mux_match,
diff --git a/drivers/net/mdio/mdio-mux-mmioreg.c b/drivers/net/mdio/mdio-mux-mmioreg.c
index b70e6d1ad429..9c4b1efd0d53 100644
--- a/drivers/net/mdio/mdio-mux-mmioreg.c
+++ b/drivers/net/mdio/mdio-mux-mmioreg.c
@@ -180,7 +180,7 @@ static struct platform_driver mdio_mux_mmioreg_driver = {
.of_match_table = mdio_mux_mmioreg_match,
},
.probe = mdio_mux_mmioreg_probe,
- .remove_new = mdio_mux_mmioreg_remove,
+ .remove = mdio_mux_mmioreg_remove,
};
module_platform_driver(mdio_mux_mmioreg_driver);
diff --git a/drivers/net/mdio/mdio-mux-multiplexer.c b/drivers/net/mdio/mdio-mux-multiplexer.c
index 569b13383191..8e11960fc539 100644
--- a/drivers/net/mdio/mdio-mux-multiplexer.c
+++ b/drivers/net/mdio/mdio-mux-multiplexer.c
@@ -107,7 +107,7 @@ static struct platform_driver mdio_mux_multiplexer_driver = {
.of_match_table = mdio_mux_multiplexer_match,
},
.probe = mdio_mux_multiplexer_probe,
- .remove_new = mdio_mux_multiplexer_remove,
+ .remove = mdio_mux_multiplexer_remove,
};
module_platform_driver(mdio_mux_multiplexer_driver);
diff --git a/drivers/net/mdio/mdio-octeon.c b/drivers/net/mdio/mdio-octeon.c
index 037a38cfed56..2beb83154d39 100644
--- a/drivers/net/mdio/mdio-octeon.c
+++ b/drivers/net/mdio/mdio-octeon.c
@@ -104,7 +104,7 @@ static struct platform_driver octeon_mdiobus_driver = {
.of_match_table = octeon_mdiobus_match,
},
.probe = octeon_mdiobus_probe,
- .remove_new = octeon_mdiobus_remove,
+ .remove = octeon_mdiobus_remove,
};
module_platform_driver(octeon_mdiobus_driver);
diff --git a/drivers/net/mdio/mdio-sun4i.c b/drivers/net/mdio/mdio-sun4i.c
index 4511bcc73b36..ad1edadc5a08 100644
--- a/drivers/net/mdio/mdio-sun4i.c
+++ b/drivers/net/mdio/mdio-sun4i.c
@@ -164,7 +164,7 @@ MODULE_DEVICE_TABLE(of, sun4i_mdio_dt_ids);
static struct platform_driver sun4i_mdio_driver = {
.probe = sun4i_mdio_probe,
- .remove_new = sun4i_mdio_remove,
+ .remove = sun4i_mdio_remove,
.driver = {
.name = "sun4i-mdio",
.of_match_table = sun4i_mdio_dt_ids,
diff --git a/drivers/net/mdio/mdio-thunder.c b/drivers/net/mdio/mdio-thunder.c
index 6067d96b2b7b..1e1aa72b1eff 100644
--- a/drivers/net/mdio/mdio-thunder.c
+++ b/drivers/net/mdio/mdio-thunder.c
@@ -23,7 +23,6 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct device_node *node;
- struct fwnode_handle *fwn;
struct thunder_mdiobus_nexus *nexus;
int err;
int i;
@@ -54,7 +53,7 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
}
i = 0;
- device_for_each_child_node(&pdev->dev, fwn) {
+ device_for_each_child_node_scoped(&pdev->dev, fwn) {
struct resource r;
struct mii_bus *mii_bus;
struct cavium_mdiobus *bus;
@@ -106,7 +105,6 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
if (i >= ARRAY_SIZE(nexus->buses))
break;
}
- fwnode_handle_put(fwn);
return 0;
err_release_regions:
diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c
index 2772a3098543..a8f91a4b7fed 100644
--- a/drivers/net/mdio/mdio-xgene.c
+++ b/drivers/net/mdio/mdio-xgene.c
@@ -441,7 +441,7 @@ static struct platform_driver xgene_mdio_driver = {
.acpi_match_table = ACPI_PTR(xgene_mdio_acpi_match),
},
.probe = xgene_mdio_probe,
- .remove_new = xgene_mdio_remove,
+ .remove = xgene_mdio_remove,
};
module_platform_driver(xgene_mdio_driver);
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index de20928f7402..4ea44a2f48f7 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -1058,102 +1058,105 @@ static struct notifier_block netconsole_netdev_notifier = {
.notifier_call = netconsole_netdev_event,
};
-/**
- * send_ext_msg_udp - send extended log message to target
- * @nt: target to send message to
- * @msg: extended log message to send
- * @msg_len: length of message
- *
- * Transfer extended log @msg to @nt. If @msg is longer than
- * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
- * ncfrag header field added to identify them.
- */
-static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
- int msg_len)
+static void send_msg_no_fragmentation(struct netconsole_target *nt,
+ const char *msg,
+ int msg_len,
+ int release_len)
{
static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */
- const char *header, *body;
- int offset = 0;
- int header_len, body_len;
- const char *msg_ready = msg;
+ const char *userdata = NULL;
const char *release;
- int release_len = 0;
- int userdata_len = 0;
- char *userdata = NULL;
#ifdef CONFIG_NETCONSOLE_DYNAMIC
userdata = nt->userdata_complete;
- userdata_len = nt->userdata_length;
#endif
- if (nt->release) {
+ if (release_len) {
release = init_utsname()->release;
- release_len = strlen(release) + 1;
+
+ scnprintf(buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);
+ msg_len += release_len;
+ } else {
+ memcpy(buf, msg, msg_len);
}
- if (msg_len + release_len + userdata_len <= MAX_PRINT_CHUNK) {
- /* No fragmentation needed */
- if (nt->release) {
- scnprintf(buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);
- msg_len += release_len;
- } else {
- memcpy(buf, msg, msg_len);
- }
+ if (userdata)
+ msg_len += scnprintf(&buf[msg_len],
+ MAX_PRINT_CHUNK - msg_len,
+ "%s", userdata);
- if (userdata)
- msg_len += scnprintf(&buf[msg_len],
- MAX_PRINT_CHUNK - msg_len,
- "%s", userdata);
+ netpoll_send_udp(&nt->np, buf, msg_len);
+}
- msg_ready = buf;
- netpoll_send_udp(&nt->np, msg_ready, msg_len);
- return;
- }
+static void append_release(char *buf)
+{
+ const char *release;
- /* need to insert extra header fields, detect header and body */
- header = msg;
- body = memchr(msg, ';', msg_len);
- if (WARN_ON_ONCE(!body))
- return;
+ release = init_utsname()->release;
+ scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);
+}
- header_len = body - header;
- body_len = msg_len - header_len - 1;
- body++;
+static void send_fragmented_body(struct netconsole_target *nt, char *buf,
+ const char *msgbody, int header_len,
+ int msgbody_len)
+{
+ const char *userdata = NULL;
+ int body_len, offset = 0;
+ int userdata_len = 0;
- /*
- * Transfer multiple chunks with the following extra header.
- * "ncfrag=<byte-offset>/<total-bytes>"
+#ifdef CONFIG_NETCONSOLE_DYNAMIC
+ userdata = nt->userdata_complete;
+ userdata_len = nt->userdata_length;
+#endif
+
+ /* body_len represents the number of bytes that will be sent. This is
+ * bigger than MAX_PRINT_CHUNK, thus, it will be split in multiple
+ * packets
*/
- if (nt->release)
- scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);
- memcpy(buf + release_len, header, header_len);
- header_len += release_len;
+ body_len = msgbody_len + userdata_len;
- while (offset < body_len + userdata_len) {
+ /* In each iteration of the while loop below, we send a packet
+ * containing the header and a portion of the body. The body is
+ * composed of two parts: msgbody and userdata. We keep track of how
+ * many bytes have been sent so far using the offset variable, which
+ * ranges from 0 to the total length of the body.
+ */
+ while (offset < body_len) {
int this_header = header_len;
+ bool msgbody_written = false;
int this_offset = 0;
int this_chunk = 0;
this_header += scnprintf(buf + this_header,
- sizeof(buf) - this_header,
+ MAX_PRINT_CHUNK - this_header,
",ncfrag=%d/%d;", offset,
- body_len + userdata_len);
+ body_len);
- /* Not all body data has been written yet */
- if (offset < body_len) {
- this_chunk = min(body_len - offset,
+ /* Not all msgbody data has been written yet */
+ if (offset < msgbody_len) {
+ this_chunk = min(msgbody_len - offset,
MAX_PRINT_CHUNK - this_header);
if (WARN_ON_ONCE(this_chunk <= 0))
return;
- memcpy(buf + this_header, body + offset, this_chunk);
+ memcpy(buf + this_header, msgbody + offset, this_chunk);
this_offset += this_chunk;
}
- /* Body is fully written and there is pending userdata to write,
- * append userdata in this chunk
+
+ /* msgbody was finally written, either in the previous
+ * messages and/or in the current buf. Time to write
+ * the userdata.
*/
- if (offset + this_offset >= body_len &&
- offset + this_offset < userdata_len + body_len) {
- int sent_userdata = (offset + this_offset) - body_len;
+ msgbody_written |= offset + this_offset >= msgbody_len;
+
+ /* Msg body is fully written and there is pending userdata to
+ * write, append userdata in this chunk
+ */
+ if (msgbody_written && offset + this_offset < body_len) {
+ /* Track how much user data was already sent. First
+ * time here, sent_userdata is zero
+ */
+ int sent_userdata = (offset + this_offset) - msgbody_len;
+ /* offset of bytes used in current buf */
int preceding_bytes = this_chunk + this_header;
if (WARN_ON_ONCE(sent_userdata < 0))
@@ -1180,6 +1183,70 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
}
}
+static void send_msg_fragmented(struct netconsole_target *nt,
+ const char *msg,
+ int msg_len,
+ int release_len)
+{
+ static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */
+ int header_len, msgbody_len;
+ const char *msgbody;
+
+ /* need to insert extra header fields, detect header and msgbody */
+ msgbody = memchr(msg, ';', msg_len);
+ if (WARN_ON_ONCE(!msgbody))
+ return;
+
+ header_len = msgbody - msg;
+ msgbody_len = msg_len - header_len - 1;
+ msgbody++;
+
+ /*
+ * Transfer multiple chunks with the following extra header.
+ * "ncfrag=<byte-offset>/<total-bytes>"
+ */
+ if (release_len)
+ append_release(buf);
+
+ /* Copy the header into the buffer */
+ memcpy(buf + release_len, msg, header_len);
+ header_len += release_len;
+
+ /* for now on, the header will be persisted, and the msgbody
+ * will be replaced
+ */
+ send_fragmented_body(nt, buf, msgbody, header_len, msgbody_len);
+}
+
+/**
+ * send_ext_msg_udp - send extended log message to target
+ * @nt: target to send message to
+ * @msg: extended log message to send
+ * @msg_len: length of message
+ *
+ * Transfer extended log @msg to @nt. If @msg is longer than
+ * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
+ * ncfrag header field added to identify them.
+ */
+static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
+ int msg_len)
+{
+ int userdata_len = 0;
+ int release_len = 0;
+
+#ifdef CONFIG_NETCONSOLE_DYNAMIC
+ userdata_len = nt->userdata_length;
+#endif
+
+ if (nt->release)
+ release_len = strlen(init_utsname()->release) + 1;
+
+ if (msg_len + release_len + userdata_len <= MAX_PRINT_CHUNK)
+ return send_msg_no_fragmentation(nt, msg, msg_len, release_len);
+
+ return send_msg_fragmented(nt, msg, msg_len, release_len);
+}
+
static void write_ext_msg(struct console *con, const char *msg,
unsigned int len)
{
diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index 1436905bc106..5fe1eaef99b5 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -103,8 +103,10 @@ nsim_set_channels(struct net_device *dev, struct ethtool_channels *ch)
struct netdevsim *ns = netdev_priv(dev);
int err;
+ mutex_lock(&dev->lock);
err = netif_set_real_num_queues(dev, ch->combined_count,
ch->combined_count);
+ mutex_unlock(&dev->lock);
if (err)
return err;
diff --git a/drivers/net/netdevsim/ipsec.c b/drivers/net/netdevsim/ipsec.c
index f0d58092e7e9..88187dd4eb2d 100644
--- a/drivers/net/netdevsim/ipsec.c
+++ b/drivers/net/netdevsim/ipsec.c
@@ -39,10 +39,14 @@ static ssize_t nsim_dbg_netdev_ops_read(struct file *filp,
if (!sap->used)
continue;
- p += scnprintf(p, bufsize - (p - buf),
- "sa[%i] %cx ipaddr=0x%08x %08x %08x %08x\n",
- i, (sap->rx ? 'r' : 't'), sap->ipaddr[0],
- sap->ipaddr[1], sap->ipaddr[2], sap->ipaddr[3]);
+ if (sap->xs->props.family == AF_INET6)
+ p += scnprintf(p, bufsize - (p - buf),
+ "sa[%i] %cx ipaddr=%pI6c\n",
+ i, (sap->rx ? 'r' : 't'), &sap->ipaddr);
+ else
+ p += scnprintf(p, bufsize - (p - buf),
+ "sa[%i] %cx ipaddr=%pI4\n",
+ i, (sap->rx ? 'r' : 't'), &sap->ipaddr[3]);
p += scnprintf(p, bufsize - (p - buf),
"sa[%i] spi=0x%08x proto=0x%x salt=0x%08x crypt=%d\n",
i, be32_to_cpu(sap->xs->id.spi),
@@ -176,14 +180,13 @@ static int nsim_ipsec_add_sa(struct xfrm_state *xs,
return ret;
}
- if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) {
+ if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN)
sa.rx = true;
- if (xs->props.family == AF_INET6)
- memcpy(sa.ipaddr, &xs->id.daddr.a6, 16);
- else
- memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4);
- }
+ if (xs->props.family == AF_INET6)
+ memcpy(sa.ipaddr, &xs->id.daddr.a6, 16);
+ else
+ memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4);
/* the preparations worked, so save the info */
memcpy(&ipsec->sa[sa_idx], &sa, sizeof(sa));
diff --git a/drivers/net/netdevsim/macsec.c b/drivers/net/netdevsim/macsec.c
index aa007b1e4b78..bdc8020d588e 100644
--- a/drivers/net/netdevsim/macsec.c
+++ b/drivers/net/netdevsim/macsec.c
@@ -46,7 +46,7 @@ static int nsim_macsec_add_secy(struct macsec_context *ctx)
return -ENOSPC;
}
- netdev_dbg(ctx->netdev, "%s: adding new secy with sci %08llx at index %d\n",
+ netdev_dbg(ctx->netdev, "%s: adding new secy with sci %016llx at index %d\n",
__func__, sci_to_cpu(ctx->secy->sci), idx);
ns->macsec.nsim_secy[idx].used = true;
ns->macsec.nsim_secy[idx].nsim_rxsc_count = 0;
@@ -63,12 +63,12 @@ static int nsim_macsec_upd_secy(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: updating secy with sci %08llx at index %d\n",
+ netdev_dbg(ctx->netdev, "%s: updating secy with sci %016llx at index %d\n",
__func__, sci_to_cpu(ctx->secy->sci), idx);
return 0;
@@ -81,12 +81,12 @@ static int nsim_macsec_del_secy(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: removing SecY with SCI %08llx at index %d\n",
+ netdev_dbg(ctx->netdev, "%s: removing SecY with SCI %016llx at index %d\n",
__func__, sci_to_cpu(ctx->secy->sci), idx);
ns->macsec.nsim_secy[idx].used = false;
@@ -104,7 +104,7 @@ static int nsim_macsec_add_rxsc(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
@@ -122,7 +122,7 @@ static int nsim_macsec_add_rxsc(struct macsec_context *ctx)
netdev_err(ctx->netdev, "%s: nsim_rxsc_count not full but all RXSCs used\n",
__func__);
- netdev_dbg(ctx->netdev, "%s: adding new rxsc with sci %08llx at index %d\n",
+ netdev_dbg(ctx->netdev, "%s: adding new rxsc with sci %016llx at index %d\n",
__func__, sci_to_cpu(ctx->rx_sc->sci), idx);
secy->nsim_rxsc[idx].used = true;
secy->nsim_rxsc[idx].sci = ctx->rx_sc->sci;
@@ -139,7 +139,7 @@ static int nsim_macsec_upd_rxsc(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
@@ -147,12 +147,12 @@ static int nsim_macsec_upd_rxsc(struct macsec_context *ctx)
idx = nsim_macsec_find_rxsc(secy, ctx->rx_sc->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in RXSC table\n",
__func__, sci_to_cpu(ctx->rx_sc->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: updating RXSC with sci %08llx at index %d\n",
+ netdev_dbg(ctx->netdev, "%s: updating RXSC with sci %016llx at index %d\n",
__func__, sci_to_cpu(ctx->rx_sc->sci), idx);
return 0;
@@ -166,7 +166,7 @@ static int nsim_macsec_del_rxsc(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
@@ -174,12 +174,12 @@ static int nsim_macsec_del_rxsc(struct macsec_context *ctx)
idx = nsim_macsec_find_rxsc(secy, ctx->rx_sc->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in RXSC table\n",
__func__, sci_to_cpu(ctx->rx_sc->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: removing RXSC with sci %08llx at index %d\n",
+ netdev_dbg(ctx->netdev, "%s: removing RXSC with sci %016llx at index %d\n",
__func__, sci_to_cpu(ctx->rx_sc->sci), idx);
secy->nsim_rxsc[idx].used = false;
@@ -197,7 +197,7 @@ static int nsim_macsec_add_rxsa(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
@@ -205,12 +205,12 @@ static int nsim_macsec_add_rxsa(struct macsec_context *ctx)
idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in RXSC table\n",
__func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n",
+ netdev_dbg(ctx->netdev, "%s: RXSC with sci %016llx, AN %u\n",
__func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num);
return 0;
@@ -224,7 +224,7 @@ static int nsim_macsec_upd_rxsa(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
@@ -232,12 +232,12 @@ static int nsim_macsec_upd_rxsa(struct macsec_context *ctx)
idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in RXSC table\n",
__func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n",
+ netdev_dbg(ctx->netdev, "%s: RXSC with sci %016llx, AN %u\n",
__func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num);
return 0;
@@ -251,7 +251,7 @@ static int nsim_macsec_del_rxsa(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
@@ -259,12 +259,12 @@ static int nsim_macsec_del_rxsa(struct macsec_context *ctx)
idx = nsim_macsec_find_rxsc(secy, ctx->sa.rx_sa->sc->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in RXSC table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in RXSC table\n",
__func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: RXSC with sci %08llx, AN %u\n",
+ netdev_dbg(ctx->netdev, "%s: RXSC with sci %016llx, AN %u\n",
__func__, sci_to_cpu(ctx->sa.rx_sa->sc->sci), ctx->sa.assoc_num);
return 0;
@@ -277,12 +277,12 @@ static int nsim_macsec_add_txsa(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n",
+ netdev_dbg(ctx->netdev, "%s: SECY with sci %016llx, AN %u\n",
__func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num);
return 0;
@@ -295,12 +295,12 @@ static int nsim_macsec_upd_txsa(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n",
+ netdev_dbg(ctx->netdev, "%s: SECY with sci %016llx, AN %u\n",
__func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num);
return 0;
@@ -313,12 +313,12 @@ static int nsim_macsec_del_txsa(struct macsec_context *ctx)
idx = nsim_macsec_find_secy(ns, ctx->secy->sci);
if (idx < 0) {
- netdev_err(ctx->netdev, "%s: sci %08llx not found in secy table\n",
+ netdev_err(ctx->netdev, "%s: sci %016llx not found in secy table\n",
__func__, sci_to_cpu(ctx->secy->sci));
return -ENOENT;
}
- netdev_dbg(ctx->netdev, "%s: SECY with sci %08llx, AN %u\n",
+ netdev_dbg(ctx->netdev, "%s: SECY with sci %016llx, AN %u\n",
__func__, sci_to_cpu(ctx->secy->sci), ctx->sa.assoc_num);
return 0;
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 017a6102be0a..0be47fed4efc 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -22,6 +22,7 @@
#include <net/netdev_queues.h>
#include <net/page_pool/helpers.h>
#include <net/netlink.h>
+#include <net/net_shaper.h>
#include <net/pkt_cls.h>
#include <net/rtnetlink.h>
#include <net/udp_tunnel.h>
@@ -475,6 +476,43 @@ static int nsim_stop(struct net_device *dev)
return 0;
}
+static int nsim_shaper_set(struct net_shaper_binding *binding,
+ const struct net_shaper *shaper,
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static int nsim_shaper_del(struct net_shaper_binding *binding,
+ const struct net_shaper_handle *handle,
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static int nsim_shaper_group(struct net_shaper_binding *binding,
+ int leaves_count,
+ const struct net_shaper *leaves,
+ const struct net_shaper *root,
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static void nsim_shaper_cap(struct net_shaper_binding *binding,
+ enum net_shaper_scope scope,
+ unsigned long *flags)
+{
+ *flags = ULONG_MAX;
+}
+
+static const struct net_shaper_ops nsim_shaper_ops = {
+ .set = nsim_shaper_set,
+ .delete = nsim_shaper_del,
+ .group = nsim_shaper_group,
+ .capabilities = nsim_shaper_cap,
+};
+
static const struct net_device_ops nsim_netdev_ops = {
.ndo_start_xmit = nsim_start_xmit,
.ndo_set_rx_mode = nsim_set_rx_mode,
@@ -496,6 +534,7 @@ static const struct net_device_ops nsim_netdev_ops = {
.ndo_bpf = nsim_bpf,
.ndo_open = nsim_open,
.ndo_stop = nsim_stop,
+ .net_shaper_ops = &nsim_shaper_ops,
};
static const struct net_device_ops nsim_vf_netdev_ops = {
@@ -624,7 +663,11 @@ static void nsim_setup(struct net_device *dev)
NETIF_F_FRAGLIST |
NETIF_F_HW_CSUM |
NETIF_F_TSO;
- dev->hw_features |= NETIF_F_HW_TC;
+ dev->hw_features |= NETIF_F_HW_TC |
+ NETIF_F_SG |
+ NETIF_F_FRAGLIST |
+ NETIF_F_HW_CSUM |
+ NETIF_F_TSO;
dev->max_mtu = ETH_MAX_MTU;
dev->xdp_features = NETDEV_XDP_ACT_HW_OFFLOAD;
}
diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c
index 059269557d92..bb07725d1c72 100644
--- a/drivers/net/netkit.c
+++ b/drivers/net/netkit.c
@@ -20,6 +20,7 @@ struct netkit {
struct net_device __rcu *peer;
struct bpf_mprog_entry __rcu *active;
enum netkit_action policy;
+ enum netkit_scrub scrub;
struct bpf_mprog_bundle bundle;
/* Needed in slow-path */
@@ -50,12 +51,24 @@ netkit_run(const struct bpf_mprog_entry *entry, struct sk_buff *skb,
return ret;
}
-static void netkit_prep_forward(struct sk_buff *skb, bool xnet)
+static void netkit_xnet(struct sk_buff *skb)
{
- skb_scrub_packet(skb, xnet);
skb->priority = 0;
+ skb->mark = 0;
+}
+
+static void netkit_prep_forward(struct sk_buff *skb,
+ bool xnet, bool xnet_scrub)
+{
+ skb_scrub_packet(skb, false);
nf_skip_egress(skb, true);
skb_reset_mac_header(skb);
+ if (!xnet)
+ return;
+ ipvs_reset(skb);
+ skb_clear_tstamp(skb);
+ if (xnet_scrub)
+ netkit_xnet(skb);
}
static struct netkit *netkit_priv(const struct net_device *dev)
@@ -80,7 +93,8 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev)
!pskb_may_pull(skb, ETH_HLEN) ||
skb_orphan_frags(skb, GFP_ATOMIC)))
goto drop;
- netkit_prep_forward(skb, !net_eq(dev_net(dev), dev_net(peer)));
+ netkit_prep_forward(skb, !net_eq(dev_net(dev), dev_net(peer)),
+ nk->scrub);
eth_skb_pkt_type(skb, peer);
skb->dev = peer;
entry = rcu_dereference(nk->active);
@@ -297,20 +311,6 @@ static int netkit_check_policy(int policy, struct nlattr *tb,
}
}
-static int netkit_check_mode(int mode, struct nlattr *tb,
- struct netlink_ext_ack *extack)
-{
- switch (mode) {
- case NETKIT_L2:
- case NETKIT_L3:
- return 0;
- default:
- NL_SET_ERR_MSG_ATTR(extack, tb,
- "Provided device mode can only be L2 or L3");
- return -EINVAL;
- }
-}
-
static int netkit_validate(struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -332,8 +332,10 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb, *attr;
- enum netkit_action default_prim = NETKIT_PASS;
- enum netkit_action default_peer = NETKIT_PASS;
+ enum netkit_action policy_prim = NETKIT_PASS;
+ enum netkit_action policy_peer = NETKIT_PASS;
+ enum netkit_scrub scrub_prim = NETKIT_SCRUB_DEFAULT;
+ enum netkit_scrub scrub_peer = NETKIT_SCRUB_DEFAULT;
enum netkit_mode mode = NETKIT_L3;
unsigned char ifname_assign_type;
struct ifinfomsg *ifmp = NULL;
@@ -344,35 +346,29 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
int err;
if (data) {
- if (data[IFLA_NETKIT_MODE]) {
- attr = data[IFLA_NETKIT_MODE];
- mode = nla_get_u32(attr);
- err = netkit_check_mode(mode, attr, extack);
- if (err < 0)
- return err;
- }
+ if (data[IFLA_NETKIT_MODE])
+ mode = nla_get_u32(data[IFLA_NETKIT_MODE]);
if (data[IFLA_NETKIT_PEER_INFO]) {
attr = data[IFLA_NETKIT_PEER_INFO];
ifmp = nla_data(attr);
- err = rtnl_nla_parse_ifinfomsg(peer_tb, attr, extack);
- if (err < 0)
- return err;
- err = netkit_validate(peer_tb, NULL, extack);
- if (err < 0)
- return err;
+ rtnl_nla_parse_ifinfomsg(peer_tb, attr, extack);
tbp = peer_tb;
}
+ if (data[IFLA_NETKIT_SCRUB])
+ scrub_prim = nla_get_u32(data[IFLA_NETKIT_SCRUB]);
+ if (data[IFLA_NETKIT_PEER_SCRUB])
+ scrub_peer = nla_get_u32(data[IFLA_NETKIT_PEER_SCRUB]);
if (data[IFLA_NETKIT_POLICY]) {
attr = data[IFLA_NETKIT_POLICY];
- default_prim = nla_get_u32(attr);
- err = netkit_check_policy(default_prim, attr, extack);
+ policy_prim = nla_get_u32(attr);
+ err = netkit_check_policy(policy_prim, attr, extack);
if (err < 0)
return err;
}
if (data[IFLA_NETKIT_PEER_POLICY]) {
attr = data[IFLA_NETKIT_PEER_POLICY];
- default_peer = nla_get_u32(attr);
- err = netkit_check_policy(default_peer, attr, extack);
+ policy_peer = nla_get_u32(attr);
+ err = netkit_check_policy(policy_peer, attr, extack);
if (err < 0)
return err;
}
@@ -390,9 +386,6 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
return -EOPNOTSUPP;
net = rtnl_link_get_net(src_net, tbp);
- if (IS_ERR(net))
- return PTR_ERR(net);
-
peer = rtnl_create_link(net, ifname, ifname_assign_type,
&netkit_link_ops, tbp, extack);
if (IS_ERR(peer)) {
@@ -409,7 +402,8 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
nk = netkit_priv(peer);
nk->primary = false;
- nk->policy = default_peer;
+ nk->policy = policy_peer;
+ nk->scrub = scrub_peer;
nk->mode = mode;
bpf_mprog_bundle_init(&nk->bundle);
@@ -434,7 +428,8 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
nk = netkit_priv(dev);
nk->primary = true;
- nk->policy = default_prim;
+ nk->policy = policy_prim;
+ nk->scrub = scrub_prim;
nk->mode = mode;
bpf_mprog_bundle_init(&nk->bundle);
@@ -874,6 +869,18 @@ static int netkit_change_link(struct net_device *dev, struct nlattr *tb[],
return -EACCES;
}
+ if (data[IFLA_NETKIT_SCRUB]) {
+ NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_SCRUB],
+ "netkit scrubbing cannot be changed after device creation");
+ return -EACCES;
+ }
+
+ if (data[IFLA_NETKIT_PEER_SCRUB]) {
+ NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_PEER_SCRUB],
+ "netkit scrubbing cannot be changed after device creation");
+ return -EACCES;
+ }
+
if (data[IFLA_NETKIT_PEER_INFO]) {
NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_PEER_INFO],
"netkit peer info cannot be changed after device creation");
@@ -908,8 +915,10 @@ static size_t netkit_get_size(const struct net_device *dev)
{
return nla_total_size(sizeof(u32)) + /* IFLA_NETKIT_POLICY */
nla_total_size(sizeof(u32)) + /* IFLA_NETKIT_PEER_POLICY */
- nla_total_size(sizeof(u8)) + /* IFLA_NETKIT_PRIMARY */
+ nla_total_size(sizeof(u32)) + /* IFLA_NETKIT_SCRUB */
+ nla_total_size(sizeof(u32)) + /* IFLA_NETKIT_PEER_SCRUB */
nla_total_size(sizeof(u32)) + /* IFLA_NETKIT_MODE */
+ nla_total_size(sizeof(u8)) + /* IFLA_NETKIT_PRIMARY */
0;
}
@@ -924,11 +933,15 @@ static int netkit_fill_info(struct sk_buff *skb, const struct net_device *dev)
return -EMSGSIZE;
if (nla_put_u32(skb, IFLA_NETKIT_MODE, nk->mode))
return -EMSGSIZE;
+ if (nla_put_u32(skb, IFLA_NETKIT_SCRUB, nk->scrub))
+ return -EMSGSIZE;
if (peer) {
nk = netkit_priv(peer);
if (nla_put_u32(skb, IFLA_NETKIT_PEER_POLICY, nk->policy))
return -EMSGSIZE;
+ if (nla_put_u32(skb, IFLA_NETKIT_PEER_SCRUB, nk->scrub))
+ return -EMSGSIZE;
}
return 0;
@@ -936,9 +949,11 @@ static int netkit_fill_info(struct sk_buff *skb, const struct net_device *dev)
static const struct nla_policy netkit_policy[IFLA_NETKIT_MAX + 1] = {
[IFLA_NETKIT_PEER_INFO] = { .len = sizeof(struct ifinfomsg) },
+ [IFLA_NETKIT_MODE] = NLA_POLICY_MAX(NLA_U32, NETKIT_L3),
[IFLA_NETKIT_POLICY] = { .type = NLA_U32 },
- [IFLA_NETKIT_MODE] = { .type = NLA_U32 },
[IFLA_NETKIT_PEER_POLICY] = { .type = NLA_U32 },
+ [IFLA_NETKIT_SCRUB] = NLA_POLICY_MAX(NLA_U32, NETKIT_SCRUB_DEFAULT),
+ [IFLA_NETKIT_PEER_SCRUB] = NLA_POLICY_MAX(NLA_U32, NETKIT_SCRUB_DEFAULT),
[IFLA_NETKIT_PRIMARY] = { .type = NLA_REJECT,
.reject_message = "Primary attribute is read-only" },
};
@@ -955,6 +970,7 @@ static struct rtnl_link_ops netkit_link_ops = {
.fill_info = netkit_fill_info,
.policy = netkit_policy,
.validate = netkit_validate,
+ .peer_type = IFLA_NETKIT_PEER_INFO,
.maxtype = IFLA_NETKIT_MAX,
};
diff --git a/drivers/net/pcs/pcs-rzn1-miic.c b/drivers/net/pcs/pcs-rzn1-miic.c
index d0a722d43368..61944574d087 100644
--- a/drivers/net/pcs/pcs-rzn1-miic.c
+++ b/drivers/net/pcs/pcs-rzn1-miic.c
@@ -552,7 +552,7 @@ static struct platform_driver miic_driver = {
.of_match_table = miic_of_mtable,
},
.probe = miic_probe,
- .remove_new = miic_remove,
+ .remove = miic_remove,
};
module_platform_driver(miic_driver);
diff --git a/drivers/net/pcs/pcs-xpcs-nxp.c b/drivers/net/pcs/pcs-xpcs-nxp.c
index d16fc58cd48d..e8efe94cf4ec 100644
--- a/drivers/net/pcs/pcs-xpcs-nxp.c
+++ b/drivers/net/pcs/pcs-xpcs-nxp.c
@@ -152,26 +152,18 @@ static int nxp_sja1110_pma_config(struct dw_xpcs *xpcs,
/* Enable TX and RX PLLs and circuits.
* Release reset of PMA to enable data flow to/from PCS.
*/
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE);
- if (ret < 0)
- return ret;
-
- val = ret & ~(SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
- SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
- SJA1110_RESET_SER | SJA1110_RESET_DES);
- val |= SJA1110_RXPKDETEN | SJA1110_RCVEN;
-
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE, val);
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE,
+ SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
+ SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
+ SJA1110_RESET_SER | SJA1110_RESET_DES |
+ SJA1110_RXPKDETEN | SJA1110_RCVEN,
+ SJA1110_RXPKDETEN | SJA1110_RCVEN);
if (ret < 0)
return ret;
/* Program continuous-time linear equalizer (CTLE) settings. */
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE,
- rx_cdr_ctle);
- if (ret < 0)
- return ret;
-
- return 0;
+ return xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE,
+ rx_cdr_ctle);
}
int nxp_sja1110_sgmii_pma_config(struct dw_xpcs *xpcs)
diff --git a/drivers/net/pcs/pcs-xpcs-wx.c b/drivers/net/pcs/pcs-xpcs-wx.c
index 5f5cd3596cb8..fc52f7aa5f59 100644
--- a/drivers/net/pcs/pcs-xpcs-wx.c
+++ b/drivers/net/pcs/pcs-xpcs-wx.c
@@ -46,25 +46,23 @@
#define TXGBE_VCO_CAL_LD0 0x72
#define TXGBE_VCO_CAL_REF0 0x76
-static int txgbe_read_pma(struct dw_xpcs *xpcs, int reg)
+static int txgbe_write_pma(struct dw_xpcs *xpcs, int reg, u16 val)
{
- return xpcs_read(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg);
+ return xpcs_write(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val);
}
-static int txgbe_write_pma(struct dw_xpcs *xpcs, int reg, u16 val)
+static int txgbe_modify_pma(struct dw_xpcs *xpcs, int reg, u16 mask, u16 set)
{
- return xpcs_write(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val);
+ return xpcs_modify(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, mask,
+ set);
}
static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs)
{
- int val;
-
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x21);
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0);
- val = txgbe_read_pma(xpcs, TXGBE_TX_GENCTL1);
- val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTL1_VBOOST_LVL);
- txgbe_write_pma(xpcs, TXGBE_TX_GENCTL1, val);
+ txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1, TXGBE_TX_GENCTL1_VBOOST_LVL,
+ FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x549);
@@ -78,38 +76,29 @@ static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs)
txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_CTLE_POLE(2) |
TXGBE_RX_EQ_CTL0_CTLE_BOOST(5));
- val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL);
- val &= ~TXGBE_RX_EQ_ATTN_LVL0;
- txgbe_write_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, val);
+ txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0xBE);
- val = txgbe_read_pma(xpcs, TXGBE_AFE_DFE_ENABLE);
- val &= ~(TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0);
- txgbe_write_pma(xpcs, TXGBE_AFE_DFE_ENABLE, val);
- val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_CTL4);
- val &= ~TXGBE_RX_EQ_CTL4_CONT_ADAPT0;
- txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL4, val);
+ txgbe_modify_pma(xpcs, TXGBE_AFE_DFE_ENABLE,
+ TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0, 0);
+ txgbe_modify_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_ADAPT0,
+ 0);
}
static void txgbe_pma_config_1g(struct dw_xpcs *xpcs)
{
- int val;
-
- val = txgbe_read_pma(xpcs, TXGBE_TX_GENCTL1);
- val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTL1_VBOOST_LVL);
- val &= ~TXGBE_TX_GENCTL1_VBOOST_EN0;
- txgbe_write_pma(xpcs, TXGBE_TX_GENCTL1, val);
+ txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1,
+ TXGBE_TX_GENCTL1_VBOOST_LVL |
+ TXGBE_TX_GENCTL1_VBOOST_EN0,
+ FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_VGA1_GAIN(7) |
TXGBE_RX_EQ_CTL0_VGA2_GAIN(7) | TXGBE_RX_EQ_CTL0_CTLE_BOOST(6));
- val = txgbe_read_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL);
- val &= ~TXGBE_RX_EQ_ATTN_LVL0;
- txgbe_write_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, val);
+ txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0);
- val = txgbe_read_pma(xpcs, TXGBE_RX_GEN_CTL3);
- val = u16_replace_bits(val, 0x4, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0);
- txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL3, val);
+ txgbe_modify_pma(xpcs, TXGBE_RX_GEN_CTL3, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0,
+ FIELD_PREP(TXGBE_RX_GEN_CTL3_LOS_TRSHLD0, 0x4));
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x20);
txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0x46);
@@ -172,7 +161,7 @@ static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs)
int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
{
- int val, ret;
+ int ret;
switch (interface) {
case PHY_INTERFACE_MODE_10GBASER:
@@ -194,9 +183,8 @@ int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
if (interface == PHY_INTERFACE_MODE_10GBASER) {
xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBR);
- val = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1);
- val |= MDIO_CTRL1_SPEED10G;
- xpcs_write(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1, val);
+ xpcs_modify(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+ MDIO_CTRL1_SPEED10G, MDIO_CTRL1_SPEED10G);
txgbe_pma_config_10gbaser(xpcs);
} else {
xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBX);
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 82463f9d50c8..7246a910728d 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -107,49 +107,9 @@ static const int xpcs_2500basex_features[] = {
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
-static const phy_interface_t xpcs_usxgmii_interfaces[] = {
- PHY_INTERFACE_MODE_USXGMII,
-};
-
-static const phy_interface_t xpcs_10gkr_interfaces[] = {
- PHY_INTERFACE_MODE_10GKR,
-};
-
-static const phy_interface_t xpcs_xlgmii_interfaces[] = {
- PHY_INTERFACE_MODE_XLGMII,
-};
-
-static const phy_interface_t xpcs_10gbaser_interfaces[] = {
- PHY_INTERFACE_MODE_10GBASER,
-};
-
-static const phy_interface_t xpcs_sgmii_interfaces[] = {
- PHY_INTERFACE_MODE_SGMII,
-};
-
-static const phy_interface_t xpcs_1000basex_interfaces[] = {
- PHY_INTERFACE_MODE_1000BASEX,
-};
-
-static const phy_interface_t xpcs_2500basex_interfaces[] = {
- PHY_INTERFACE_MODE_2500BASEX,
-};
-
-enum {
- DW_XPCS_USXGMII,
- DW_XPCS_10GKR,
- DW_XPCS_XLGMII,
- DW_XPCS_10GBASER,
- DW_XPCS_SGMII,
- DW_XPCS_1000BASEX,
- DW_XPCS_2500BASEX,
- DW_XPCS_INTERFACE_MAX,
-};
-
struct dw_xpcs_compat {
+ phy_interface_t interface;
const int *supported;
- const phy_interface_t *interface;
- int num_interfaces;
int an_mode;
int (*pma_config)(struct dw_xpcs *xpcs);
};
@@ -161,26 +121,28 @@ struct dw_xpcs_desc {
};
static const struct dw_xpcs_compat *
-xpcs_find_compat(const struct dw_xpcs_desc *desc, phy_interface_t interface)
+xpcs_find_compat(struct dw_xpcs *xpcs, phy_interface_t interface)
{
- int i, j;
+ const struct dw_xpcs_compat *compat;
- for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
- const struct dw_xpcs_compat *compat = &desc->compat[i];
-
- for (j = 0; j < compat->num_interfaces; j++)
- if (compat->interface[j] == interface)
- return compat;
- }
+ for (compat = xpcs->desc->compat; compat->supported; compat++)
+ if (compat->interface == interface)
+ return compat;
return NULL;
}
+struct phylink_pcs *xpcs_to_phylink_pcs(struct dw_xpcs *xpcs)
+{
+ return &xpcs->pcs;
+}
+EXPORT_SYMBOL_GPL(xpcs_to_phylink_pcs);
+
int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
{
const struct dw_xpcs_compat *compat;
- compat = xpcs_find_compat(xpcs->desc, interface);
+ compat = xpcs_find_compat(xpcs, interface);
if (!compat)
return -ENODEV;
@@ -213,6 +175,11 @@ int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val)
return mdiodev_c45_write(xpcs->mdiodev, dev, reg, val);
}
+int xpcs_modify(struct dw_xpcs *xpcs, int dev, u32 reg, u16 mask, u16 set)
+{
+ return mdiodev_c45_modify(xpcs->mdiodev, dev, reg, mask, set);
+}
+
static int xpcs_modify_changed(struct dw_xpcs *xpcs, int dev, u32 reg,
u16 mask, u16 set)
{
@@ -230,6 +197,12 @@ static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg,
return xpcs_write(xpcs, dev, DW_VENDOR | reg, val);
}
+static int xpcs_modify_vendor(struct dw_xpcs *xpcs, int dev, int reg, u16 mask,
+ u16 set)
+{
+ return xpcs_modify(xpcs, dev, DW_VENDOR | reg, mask, set);
+}
+
int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg)
{
return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg);
@@ -240,20 +213,22 @@ int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val)
return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
}
+static int xpcs_modify_vpcs(struct dw_xpcs *xpcs, int reg, u16 mask, u16 val)
+{
+ return xpcs_modify_vendor(xpcs, MDIO_MMD_PCS, reg, mask, val);
+}
+
static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev)
{
- /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
- unsigned int retries = 12;
- int ret;
+ int ret, val;
- do {
- msleep(50);
- ret = xpcs_read(xpcs, dev, MDIO_CTRL1);
- if (ret < 0)
- return ret;
- } while (ret & MDIO_CTRL1_RESET && --retries);
+ ret = read_poll_timeout(xpcs_read, val,
+ val < 0 || !(val & BMCR_RESET),
+ 50000, 600000, true, xpcs, dev, MII_BMCR);
+ if (val < 0)
+ ret = val;
- return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0;
+ return ret;
}
static int xpcs_soft_reset(struct dw_xpcs *xpcs,
@@ -275,7 +250,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs,
return -EINVAL;
}
- ret = xpcs_write(xpcs, dev, MDIO_CTRL1, MDIO_CTRL1_RESET);
+ ret = xpcs_write(xpcs, dev, MII_BMCR, BMCR_RESET);
if (ret < 0)
return ret;
@@ -336,7 +311,7 @@ static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
return 0;
}
-static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
+static void xpcs_link_up_usxgmii(struct dw_xpcs *xpcs, int speed)
{
int ret, speed_sel;
@@ -364,37 +339,25 @@ static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
return;
}
- ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
- if (ret < 0)
- goto out;
-
- ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_EN);
- if (ret < 0)
- goto out;
-
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
- if (ret < 0)
- goto out;
-
- ret &= ~DW_USXGMII_SS_MASK;
- ret |= speed_sel | DW_USXGMII_FULL;
-
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
+ ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_EN, DW_USXGMII_EN);
if (ret < 0)
goto out;
- ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1);
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, DW_USXGMII_SS_MASK,
+ speed_sel | DW_USXGMII_FULL);
if (ret < 0)
goto out;
- ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_RST);
+ ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_RST,
+ DW_USXGMII_RST);
if (ret < 0)
goto out;
return;
out:
- pr_err("%s: XPCS access returned %pe\n", __func__, ERR_PTR(ret));
+ dev_err(&xpcs->mdiodev->dev, "%s: XPCS access returned %pe\n",
+ __func__, ERR_PTR(ret));
}
static int _xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
@@ -451,13 +414,9 @@ static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
if (ret < 0)
return ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_CTRL1);
- if (ret < 0)
- return ret;
-
- ret |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
-
- return xpcs_write(xpcs, MDIO_MMD_AN, MDIO_CTRL1, ret);
+ return xpcs_modify(xpcs, MDIO_MMD_AN, MDIO_CTRL1,
+ MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART,
+ MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
}
static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
@@ -592,7 +551,7 @@ static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
int i;
xpcs = phylink_pcs_to_xpcs(pcs);
- compat = xpcs_find_compat(xpcs->desc, state->interface);
+ compat = xpcs_find_compat(xpcs, state->interface);
if (!compat)
return -EINVAL;
@@ -610,62 +569,72 @@ static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
{
- int i, j;
-
- for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
- const struct dw_xpcs_compat *compat = &xpcs->desc->compat[i];
+ const struct dw_xpcs_compat *compat;
- for (j = 0; j < compat->num_interfaces; j++)
- __set_bit(compat->interface[j], interfaces);
- }
+ for (compat = xpcs->desc->compat; compat->supported; compat++)
+ __set_bit(compat->interface, interfaces);
}
EXPORT_SYMBOL_GPL(xpcs_get_interfaces);
int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
{
+ u16 mask, val;
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0);
- if (ret < 0)
- return ret;
+ mask = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
+ DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
+ DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
+ DW_VR_MII_EEE_MULT_FACT_100NS;
- if (enable) {
- /* Enable EEE */
- ret = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
+ if (enable)
+ val = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
- mult_fact_100ns << DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT;
- } else {
- ret &= ~(DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN |
- DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN |
- DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL |
- DW_VR_MII_EEE_MULT_FACT_100NS);
- }
+ FIELD_PREP(DW_VR_MII_EEE_MULT_FACT_100NS,
+ mult_fact_100ns);
+ else
+ val = 0;
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, ret);
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, mask,
+ val);
if (ret < 0)
return ret;
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1);
- if (ret < 0)
- return ret;
+ return xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1,
+ DW_VR_MII_EEE_TRN_LPI,
+ enable ? DW_VR_MII_EEE_TRN_LPI : 0);
+}
+EXPORT_SYMBOL_GPL(xpcs_config_eee);
- if (enable)
- ret |= DW_VR_MII_EEE_TRN_LPI;
- else
- ret &= ~DW_VR_MII_EEE_TRN_LPI;
+static void xpcs_pre_config(struct phylink_pcs *pcs, phy_interface_t interface)
+{
+ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
+ const struct dw_xpcs_compat *compat;
+ int ret;
+
+ if (!xpcs->need_reset)
+ return;
- return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1, ret);
+ compat = xpcs_find_compat(xpcs, interface);
+ if (!compat) {
+ dev_err(&xpcs->mdiodev->dev, "unsupported interface %s\n",
+ phy_modes(interface));
+ return;
+ }
+
+ ret = xpcs_soft_reset(xpcs, compat);
+ if (ret)
+ dev_err(&xpcs->mdiodev->dev, "soft reset failed: %pe\n",
+ ERR_PTR(ret));
+
+ xpcs->need_reset = false;
}
-EXPORT_SYMBOL_GPL(xpcs_config_eee);
static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
unsigned int neg_mode)
{
int ret, mdio_ctrl, tx_conf;
-
- if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
- xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_CL37_BP | DW_EN_VSMMD1);
+ u16 mask, val;
/* For AN for C37 SGMII mode, the settings are :-
* 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case
@@ -677,63 +646,60 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
* speed/duplex mode change by HW after SGMII AN complete)
* 5) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 1b (Enable SGMII AN)
*
+ * Note that VR_MII_MMD_CTRL is MII_BMCR.
+ *
* Note: Since it is MAC side SGMII, there is no need to set
* SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config from
* PHY about the link state change after C28 AN is completed
* between PHY and Link Partner. There is also no need to
* trigger AN restart for MAC-side SGMII.
*/
- mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
+ mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
if (mdio_ctrl < 0)
return mdio_ctrl;
- if (mdio_ctrl & AN_CL37_EN) {
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
- mdio_ctrl & ~AN_CL37_EN);
+ if (mdio_ctrl & BMCR_ANENABLE) {
+ ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
+ mdio_ctrl & ~BMCR_ANENABLE);
if (ret < 0)
return ret;
}
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
- if (ret < 0)
- return ret;
+ mask = DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK;
+ val = FIELD_PREP(DW_VR_MII_PCS_MODE_MASK,
+ DW_VR_MII_PCS_MODE_C37_SGMII);
- ret &= ~(DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK);
- ret |= (DW_VR_MII_PCS_MODE_C37_SGMII <<
- DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT &
- DW_VR_MII_PCS_MODE_MASK);
if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
- ret |= DW_VR_MII_AN_CTRL_8BIT;
+ mask |= DW_VR_MII_AN_CTRL_8BIT;
+ val |= DW_VR_MII_AN_CTRL_8BIT;
/* Hardware requires it to be PHY side SGMII */
tx_conf = DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII;
} else {
tx_conf = DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII;
}
- ret |= tx_conf << DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT &
- DW_VR_MII_TX_CONFIG_MASK;
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
- if (ret < 0)
- return ret;
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
+ val |= FIELD_PREP(DW_VR_MII_TX_CONFIG_MASK, tx_conf);
+
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
if (ret < 0)
return ret;
+ mask = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
- ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
- else
- ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
+ val = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
- if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
- ret |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
+ if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
+ mask |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
+ val |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
+ }
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, mask, val);
if (ret < 0)
return ret;
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
- mdio_ctrl | AN_CL37_EN);
+ ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
+ mdio_ctrl | BMCR_ANENABLE);
return ret;
}
@@ -745,34 +711,36 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX;
int ret, mdio_ctrl, adv;
bool changed = 0;
-
- if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
- xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_CL37_BP | DW_EN_VSMMD1);
+ u16 mask, val;
/* According to Chap 7.12, to set 1000BASE-X C37 AN, AN must
* be disabled first:-
* 1) VR_MII_MMD_CTRL Bit(12)[AN_ENABLE] = 0b
* 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 00b (1000BASE-X C37)
+ *
+ * Note that VR_MII_MMD_CTRL is MII_BMCR.
*/
- mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
+ mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
if (mdio_ctrl < 0)
return mdio_ctrl;
- if (mdio_ctrl & AN_CL37_EN) {
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
- mdio_ctrl & ~AN_CL37_EN);
+ if (mdio_ctrl & BMCR_ANENABLE) {
+ ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
+ mdio_ctrl & ~BMCR_ANENABLE);
if (ret < 0)
return ret;
}
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL);
- if (ret < 0)
- return ret;
+ mask = DW_VR_MII_PCS_MODE_MASK;
+ val = FIELD_PREP(DW_VR_MII_PCS_MODE_MASK,
+ DW_VR_MII_PCS_MODE_C37_1000BASEX);
+
+ if (!xpcs->pcs.poll) {
+ mask |= DW_VR_MII_AN_INTR_EN;
+ val |= DW_VR_MII_AN_INTR_EN;
+ }
- ret &= ~DW_VR_MII_PCS_MODE_MASK;
- if (!xpcs->pcs.poll)
- ret |= DW_VR_MII_AN_INTR_EN;
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret);
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
if (ret < 0)
return ret;
@@ -796,8 +764,8 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
return ret;
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
- mdio_ctrl | AN_CL37_EN);
+ ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
+ mdio_ctrl | BMCR_ANENABLE);
if (ret < 0)
return ret;
}
@@ -809,31 +777,26 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1);
- if (ret < 0)
- return ret;
- ret |= DW_VR_MII_DIG_CTRL1_2G5_EN;
- ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret);
+ ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1,
+ DW_VR_MII_DIG_CTRL1_2G5_EN |
+ DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW,
+ DW_VR_MII_DIG_CTRL1_2G5_EN);
if (ret < 0)
return ret;
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL);
- if (ret < 0)
- return ret;
- ret &= ~AN_CL37_EN;
- ret |= SGMII_SPEED_SS6;
- ret &= ~SGMII_SPEED_SS13;
- return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, ret);
+ return xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR,
+ BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_SPEED100,
+ BMCR_SPEED1000);
}
-int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
- const unsigned long *advertising, unsigned int neg_mode)
+static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
+ const unsigned long *advertising,
+ unsigned int neg_mode)
{
const struct dw_xpcs_compat *compat;
int ret;
- compat = xpcs_find_compat(xpcs->desc, interface);
+ compat = xpcs_find_compat(xpcs, interface);
if (!compat)
return -ENODEV;
@@ -841,6 +804,14 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
ret = txgbe_xpcs_switch_mode(xpcs, interface);
if (ret)
return ret;
+
+ /* Wangxun devices need backplane CL37 AN enabled for
+ * SGMII and 1000base-X
+ */
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
+ interface == PHY_INTERFACE_MODE_1000BASEX)
+ xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1,
+ DW_CL37_BP | DW_EN_VSMMD1);
}
switch (compat->an_mode) {
@@ -881,7 +852,6 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
return 0;
}
-EXPORT_SYMBOL_GPL(xpcs_do_config);
static int xpcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
@@ -989,8 +959,7 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
state->link = true;
- speed_value = (ret & DW_VR_MII_AN_STS_C37_ANSGM_SP) >>
- DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT;
+ speed_value = FIELD_GET(DW_VR_MII_AN_STS_C37_ANSGM_SP, ret);
if (speed_value == DW_VR_MII_C37_ANSGM_SP_1000)
state->speed = SPEED_1000;
else if (speed_value == DW_VR_MII_C37_ANSGM_SP_100)
@@ -1007,14 +976,14 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
state->link = true;
- speed = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
+ speed = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
if (speed < 0)
return speed;
- speed &= SGMII_SPEED_SS13 | SGMII_SPEED_SS6;
- if (speed == SGMII_SPEED_SS6)
+ speed &= BMCR_SPEED100 | BMCR_SPEED1000;
+ if (speed == BMCR_SPEED1000)
state->speed = SPEED_1000;
- else if (speed == SGMII_SPEED_SS13)
+ else if (speed == BMCR_SPEED100)
state->speed = SPEED_100;
else if (speed == 0)
state->speed = SPEED_10;
@@ -1023,9 +992,9 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
if (duplex < 0)
return duplex;
- if (duplex & DW_FULL_DUPLEX)
+ if (duplex & ADVERTISE_1000XFULL)
state->duplex = DUPLEX_FULL;
- else if (duplex & DW_HALF_DUPLEX)
+ else if (duplex & ADVERTISE_1000XHALF)
state->duplex = DUPLEX_HALF;
xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
@@ -1074,13 +1043,13 @@ static int xpcs_get_state_2500basex(struct dw_xpcs *xpcs,
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_STS);
+ ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMSR);
if (ret < 0) {
state->link = 0;
return ret;
}
- state->link = !!(ret & DW_VR_MII_MMD_STS_LINK_STS);
+ state->link = !!(ret & BMSR_LSTATUS);
if (!state->link)
return 0;
@@ -1098,7 +1067,7 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
const struct dw_xpcs_compat *compat;
int ret;
- compat = xpcs_find_compat(xpcs->desc, state->interface);
+ compat = xpcs_find_compat(xpcs, state->interface);
if (!compat)
return;
@@ -1108,108 +1077,94 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
break;
case DW_AN_C73:
ret = xpcs_get_state_c73(xpcs, state, compat);
- if (ret) {
- pr_err("xpcs_get_state_c73 returned %pe\n",
- ERR_PTR(ret));
- return;
- }
+ if (ret)
+ dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
+ "xpcs_get_state_c73", ERR_PTR(ret));
break;
case DW_AN_C37_SGMII:
ret = xpcs_get_state_c37_sgmii(xpcs, state);
- if (ret) {
- pr_err("xpcs_get_state_c37_sgmii returned %pe\n",
- ERR_PTR(ret));
- }
+ if (ret)
+ dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
+ "xpcs_get_state_c37_sgmii", ERR_PTR(ret));
break;
case DW_AN_C37_1000BASEX:
ret = xpcs_get_state_c37_1000basex(xpcs, state);
- if (ret) {
- pr_err("xpcs_get_state_c37_1000basex returned %pe\n",
- ERR_PTR(ret));
- }
+ if (ret)
+ dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
+ "xpcs_get_state_c37_1000basex", ERR_PTR(ret));
break;
case DW_2500BASEX:
ret = xpcs_get_state_2500basex(xpcs, state);
- if (ret) {
- pr_err("xpcs_get_state_2500basex returned %pe\n",
- ERR_PTR(ret));
- }
+ if (ret)
+ dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
+ "xpcs_get_state_2500basex", ERR_PTR(ret));
break;
default:
return;
}
}
-static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int neg_mode,
- int speed, int duplex)
+static void xpcs_link_up_sgmii_1000basex(struct dw_xpcs *xpcs,
+ unsigned int neg_mode,
+ phy_interface_t interface,
+ int speed, int duplex)
{
- int val, ret;
+ int ret;
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
return;
- val = mii_bmcr_encode_fixed(speed, duplex);
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
- if (ret)
- pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
-}
-
-static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int neg_mode,
- int speed, int duplex)
-{
- int val, ret;
-
- if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
- return;
+ if (interface == PHY_INTERFACE_MODE_1000BASEX) {
+ if (speed != SPEED_1000) {
+ dev_err(&xpcs->mdiodev->dev,
+ "%s: speed %dMbps not supported\n",
+ __func__, speed);
+ return;
+ }
- switch (speed) {
- case SPEED_1000:
- val = BMCR_SPEED1000;
- break;
- case SPEED_100:
- case SPEED_10:
- default:
- pr_err("%s: speed = %d\n", __func__, speed);
- return;
+ if (duplex != DUPLEX_FULL)
+ dev_err(&xpcs->mdiodev->dev,
+ "%s: half duplex not supported\n",
+ __func__);
}
- if (duplex == DUPLEX_FULL)
- val |= BMCR_FULLDPLX;
- else
- pr_err("%s: half duplex not supported\n", __func__);
-
- ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val);
+ ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
+ mii_bmcr_encode_fixed(speed, duplex));
if (ret)
- pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
+ dev_err(&xpcs->mdiodev->dev, "%s: xpcs_write returned %pe\n",
+ __func__, ERR_PTR(ret));
}
-void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
- phy_interface_t interface, int speed, int duplex)
+static void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface, int speed, int duplex)
{
struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
- if (interface == PHY_INTERFACE_MODE_USXGMII)
- return xpcs_config_usxgmii(xpcs, speed);
- if (interface == PHY_INTERFACE_MODE_SGMII)
- return xpcs_link_up_sgmii(xpcs, neg_mode, speed, duplex);
- if (interface == PHY_INTERFACE_MODE_1000BASEX)
- return xpcs_link_up_1000basex(xpcs, neg_mode, speed, duplex);
+ switch (interface) {
+ case PHY_INTERFACE_MODE_USXGMII:
+ xpcs_link_up_usxgmii(xpcs, speed);
+ break;
+
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ xpcs_link_up_sgmii_1000basex(xpcs, neg_mode, interface, speed,
+ duplex);
+ break;
+
+ default:
+ break;
+ }
}
-EXPORT_SYMBOL_GPL(xpcs_link_up);
static void xpcs_an_restart(struct phylink_pcs *pcs)
{
struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
- int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
- if (ret >= 0) {
- ret |= BMCR_ANRESTART;
- xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret);
- }
+ xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, BMCR_ANRESTART,
+ BMCR_ANRESTART);
}
-static int xpcs_get_id(struct dw_xpcs *xpcs)
+static int xpcs_read_ids(struct dw_xpcs *xpcs)
{
int ret;
u32 id;
@@ -1275,76 +1230,62 @@ static int xpcs_get_id(struct dw_xpcs *xpcs)
return 0;
}
-static const struct dw_xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
- [DW_XPCS_USXGMII] = {
+static const struct dw_xpcs_compat synopsys_xpcs_compat[] = {
+ {
+ .interface = PHY_INTERFACE_MODE_USXGMII,
.supported = xpcs_usxgmii_features,
- .interface = xpcs_usxgmii_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_usxgmii_interfaces),
.an_mode = DW_AN_C73,
- },
- [DW_XPCS_10GKR] = {
+ }, {
+ .interface = PHY_INTERFACE_MODE_10GKR,
.supported = xpcs_10gkr_features,
- .interface = xpcs_10gkr_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_10gkr_interfaces),
.an_mode = DW_AN_C73,
- },
- [DW_XPCS_XLGMII] = {
+ }, {
+ .interface = PHY_INTERFACE_MODE_XLGMII,
.supported = xpcs_xlgmii_features,
- .interface = xpcs_xlgmii_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces),
.an_mode = DW_AN_C73,
- },
- [DW_XPCS_10GBASER] = {
+ }, {
+ .interface = PHY_INTERFACE_MODE_10GBASER,
.supported = xpcs_10gbaser_features,
- .interface = xpcs_10gbaser_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_10gbaser_interfaces),
.an_mode = DW_10GBASER,
- },
- [DW_XPCS_SGMII] = {
+ }, {
+ .interface = PHY_INTERFACE_MODE_SGMII,
.supported = xpcs_sgmii_features,
- .interface = xpcs_sgmii_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
.an_mode = DW_AN_C37_SGMII,
- },
- [DW_XPCS_1000BASEX] = {
+ }, {
+ .interface = PHY_INTERFACE_MODE_1000BASEX,
.supported = xpcs_1000basex_features,
- .interface = xpcs_1000basex_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_1000basex_interfaces),
.an_mode = DW_AN_C37_1000BASEX,
- },
- [DW_XPCS_2500BASEX] = {
+ }, {
+ .interface = PHY_INTERFACE_MODE_2500BASEX,
.supported = xpcs_2500basex_features,
- .interface = xpcs_2500basex_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
.an_mode = DW_2500BASEX,
- },
+ }, {
+ }
};
-static const struct dw_xpcs_compat nxp_sja1105_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
- [DW_XPCS_SGMII] = {
+static const struct dw_xpcs_compat nxp_sja1105_xpcs_compat[] = {
+ {
+ .interface = PHY_INTERFACE_MODE_SGMII,
.supported = xpcs_sgmii_features,
- .interface = xpcs_sgmii_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
.an_mode = DW_AN_C37_SGMII,
.pma_config = nxp_sja1105_sgmii_pma_config,
- },
+ }, {
+ }
};
-static const struct dw_xpcs_compat nxp_sja1110_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
- [DW_XPCS_SGMII] = {
+static const struct dw_xpcs_compat nxp_sja1110_xpcs_compat[] = {
+ {
+ .interface = PHY_INTERFACE_MODE_SGMII,
.supported = xpcs_sgmii_features,
- .interface = xpcs_sgmii_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
.an_mode = DW_AN_C37_SGMII,
.pma_config = nxp_sja1110_sgmii_pma_config,
- },
- [DW_XPCS_2500BASEX] = {
+ }, {
+ .interface = PHY_INTERFACE_MODE_2500BASEX,
.supported = xpcs_2500basex_features,
- .interface = xpcs_2500basex_interfaces,
- .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
.an_mode = DW_2500BASEX,
.pma_config = nxp_sja1110_2500basex_pma_config,
- },
+ }, {
+ }
};
static const struct dw_xpcs_desc xpcs_desc_list[] = {
@@ -1365,12 +1306,33 @@ static const struct dw_xpcs_desc xpcs_desc_list[] = {
static const struct phylink_pcs_ops xpcs_phylink_ops = {
.pcs_validate = xpcs_validate,
+ .pcs_pre_config = xpcs_pre_config,
.pcs_config = xpcs_config,
.pcs_get_state = xpcs_get_state,
.pcs_an_restart = xpcs_an_restart,
.pcs_link_up = xpcs_link_up,
};
+static int xpcs_identify(struct dw_xpcs *xpcs)
+{
+ int i, ret;
+
+ ret = xpcs_read_ids(xpcs);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(xpcs_desc_list); i++) {
+ const struct dw_xpcs_desc *entry = &xpcs_desc_list[i];
+
+ if ((xpcs->info.pcs & entry->mask) == entry->id) {
+ xpcs->desc = entry;
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
static struct dw_xpcs *xpcs_create_data(struct mdio_device *mdiodev)
{
struct dw_xpcs *xpcs;
@@ -1427,7 +1389,6 @@ static void xpcs_clear_clks(struct dw_xpcs *xpcs)
static int xpcs_init_id(struct dw_xpcs *xpcs)
{
const struct dw_xpcs_info *info;
- int i, ret;
info = dev_get_platdata(&xpcs->mdiodev->dev);
if (!info) {
@@ -1437,45 +1398,10 @@ static int xpcs_init_id(struct dw_xpcs *xpcs)
xpcs->info = *info;
}
- ret = xpcs_get_id(xpcs);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < ARRAY_SIZE(xpcs_desc_list); i++) {
- const struct dw_xpcs_desc *desc = &xpcs_desc_list[i];
-
- if ((xpcs->info.pcs & desc->mask) != desc->id)
- continue;
-
- xpcs->desc = desc;
-
- break;
- }
-
- if (!xpcs->desc)
- return -ENODEV;
-
- return 0;
+ return xpcs_identify(xpcs);
}
-static int xpcs_init_iface(struct dw_xpcs *xpcs, phy_interface_t interface)
-{
- const struct dw_xpcs_compat *compat;
-
- compat = xpcs_find_compat(xpcs->desc, interface);
- if (!compat)
- return -EINVAL;
-
- if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
- xpcs->pcs.poll = false;
- return 0;
- }
-
- return xpcs_soft_reset(xpcs, compat);
-}
-
-static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
- phy_interface_t interface)
+static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev)
{
struct dw_xpcs *xpcs;
int ret;
@@ -1492,9 +1418,10 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
if (ret)
goto out_clear_clks;
- ret = xpcs_init_iface(xpcs, interface);
- if (ret)
- goto out_clear_clks;
+ if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
+ xpcs->pcs.poll = false;
+ else
+ xpcs->need_reset = true;
return xpcs;
@@ -1511,14 +1438,12 @@ out_free_data:
* xpcs_create_mdiodev() - create a DW xPCS instance with the MDIO @addr
* @bus: pointer to the MDIO-bus descriptor for the device to be looked at
* @addr: device MDIO-bus ID
- * @interface: requested PHY interface
*
* Return: a pointer to the DW XPCS handle if successful, otherwise -ENODEV if
* the PCS device couldn't be found on the bus and other negative errno related
* to the data allocation and MDIO-bus communications.
*/
-struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
- phy_interface_t interface)
+struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr)
{
struct mdio_device *mdiodev;
struct dw_xpcs *xpcs;
@@ -1527,7 +1452,7 @@ struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
if (IS_ERR(mdiodev))
return ERR_CAST(mdiodev);
- xpcs = xpcs_create(mdiodev, interface);
+ xpcs = xpcs_create(mdiodev);
/* xpcs_create() has taken a refcount on the mdiodev if it was
* successful. If xpcs_create() fails, this will free the mdio
@@ -1541,10 +1466,21 @@ struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
}
EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
+struct phylink_pcs *xpcs_create_pcs_mdiodev(struct mii_bus *bus, int addr)
+{
+ struct dw_xpcs *xpcs;
+
+ xpcs = xpcs_create_mdiodev(bus, addr);
+ if (IS_ERR(xpcs))
+ return ERR_CAST(xpcs);
+
+ return &xpcs->pcs;
+}
+EXPORT_SYMBOL_GPL(xpcs_create_pcs_mdiodev);
+
/**
* xpcs_create_fwnode() - Create a DW xPCS instance from @fwnode
* @fwnode: fwnode handle poining to the DW XPCS device
- * @interface: requested PHY interface
*
* Return: a pointer to the DW XPCS handle if successful, otherwise -ENODEV if
* the fwnode device is unavailable or the PCS device couldn't be found on the
@@ -1552,8 +1488,7 @@ EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
* other negative errno related to the data allocations and MDIO-bus
* communications.
*/
-struct dw_xpcs *xpcs_create_fwnode(struct fwnode_handle *fwnode,
- phy_interface_t interface)
+struct dw_xpcs *xpcs_create_fwnode(struct fwnode_handle *fwnode)
{
struct mdio_device *mdiodev;
struct dw_xpcs *xpcs;
@@ -1565,7 +1500,7 @@ struct dw_xpcs *xpcs_create_fwnode(struct fwnode_handle *fwnode,
if (!mdiodev)
return ERR_PTR(-EPROBE_DEFER);
- xpcs = xpcs_create(mdiodev, interface);
+ xpcs = xpcs_create(mdiodev);
/* xpcs_create() has taken a refcount on the mdiodev if it was
* successful. If xpcs_create() fails, this will free the mdio
@@ -1590,5 +1525,11 @@ void xpcs_destroy(struct dw_xpcs *xpcs)
}
EXPORT_SYMBOL_GPL(xpcs_destroy);
+void xpcs_destroy_pcs(struct phylink_pcs *pcs)
+{
+ xpcs_destroy(phylink_pcs_to_xpcs(pcs));
+}
+EXPORT_SYMBOL_GPL(xpcs_destroy_pcs);
+
MODULE_DESCRIPTION("Synopsys DesignWare XPCS library");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h
index fa05adfae220..adc5a0b3c883 100644
--- a/drivers/net/pcs/pcs-xpcs.h
+++ b/drivers/net/pcs/pcs-xpcs.h
@@ -54,14 +54,9 @@
/* Clause 37 Defines */
/* VR MII MMD registers offsets */
-#define DW_VR_MII_MMD_CTRL 0x0000
-#define DW_VR_MII_MMD_STS 0x0001
-#define DW_VR_MII_MMD_STS_LINK_STS BIT(2)
#define DW_VR_MII_DIG_CTRL1 0x8000
#define DW_VR_MII_AN_CTRL 0x8001
#define DW_VR_MII_AN_INTR_STS 0x8002
-/* Enable 2.5G Mode */
-#define DW_VR_MII_DIG_CTRL1_2G5_EN BIT(2)
/* EEE Mode Control Register */
#define DW_VR_MII_EEE_MCTRL0 0x8006
#define DW_VR_MII_EEE_MCTRL1 0x800b
@@ -69,6 +64,7 @@
/* VR_MII_DIG_CTRL1 */
#define DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW BIT(9)
+#define DW_VR_MII_DIG_CTRL1_2G5_EN BIT(2)
#define DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL BIT(0)
/* VR_MII_DIG_CTRL2 */
@@ -77,11 +73,9 @@
/* VR_MII_AN_CTRL */
#define DW_VR_MII_AN_CTRL_8BIT BIT(8)
-#define DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT 3
#define DW_VR_MII_TX_CONFIG_MASK BIT(3)
#define DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII 0x1
#define DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII 0x0
-#define DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT 1
#define DW_VR_MII_PCS_MODE_MASK GENMASK(2, 1)
#define DW_VR_MII_PCS_MODE_C37_1000BASEX 0x0
#define DW_VR_MII_PCS_MODE_C37_SGMII 0x2
@@ -90,22 +84,12 @@
/* VR_MII_AN_INTR_STS */
#define DW_VR_MII_AN_STS_C37_ANCMPLT_INTR BIT(0)
#define DW_VR_MII_AN_STS_C37_ANSGM_FD BIT(1)
-#define DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT 2
#define DW_VR_MII_AN_STS_C37_ANSGM_SP GENMASK(3, 2)
#define DW_VR_MII_C37_ANSGM_SP_10 0x0
#define DW_VR_MII_C37_ANSGM_SP_100 0x1
#define DW_VR_MII_C37_ANSGM_SP_1000 0x2
#define DW_VR_MII_C37_ANSGM_SP_LNKSTS BIT(4)
-/* SR MII MMD Control defines */
-#define AN_CL37_EN BIT(12) /* Enable Clause 37 auto-nego */
-#define SGMII_SPEED_SS13 BIT(13) /* SGMII speed along with SS6 */
-#define SGMII_SPEED_SS6 BIT(6) /* SGMII speed along with SS13 */
-
-/* SR MII MMD AN Advertisement defines */
-#define DW_HALF_DUPLEX BIT(6)
-#define DW_FULL_DUPLEX BIT(5)
-
/* VR MII EEE Control 0 defines */
#define DW_VR_MII_EEE_LTX_EN BIT(0) /* LPI Tx Enable */
#define DW_VR_MII_EEE_LRX_EN BIT(1) /* LPI Rx Enable */
@@ -114,7 +98,6 @@
#define DW_VR_MII_EEE_TX_EN_CTRL BIT(4) /* Tx Control Enable */
#define DW_VR_MII_EEE_RX_EN_CTRL BIT(7) /* Rx Control Enable */
-#define DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT 8
#define DW_VR_MII_EEE_MULT_FACT_100NS GENMASK(11, 8)
/* VR MII EEE Control 1 defines */
@@ -123,8 +106,27 @@
#define DW_XPCS_INFO_DECLARE(_name, _pcs, _pma) \
static const struct dw_xpcs_info _name = { .pcs = _pcs, .pma = _pma }
+struct dw_xpcs_desc;
+
+enum dw_xpcs_clock {
+ DW_XPCS_CORE_CLK,
+ DW_XPCS_PAD_CLK,
+ DW_XPCS_NUM_CLKS,
+};
+
+struct dw_xpcs {
+ struct dw_xpcs_info info;
+ const struct dw_xpcs_desc *desc;
+ struct mdio_device *mdiodev;
+ struct clk_bulk_data clks[DW_XPCS_NUM_CLKS];
+ struct phylink_pcs pcs;
+ phy_interface_t interface;
+ bool need_reset;
+};
+
int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg);
int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val);
+int xpcs_modify(struct dw_xpcs *xpcs, int dev, u32 reg, u16 mask, u16 set);
int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg);
int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val);
int nxp_sja1105_sgmii_pma_config(struct dw_xpcs *xpcs);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 01b235b3bb7e..15828f4710a9 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -266,22 +266,7 @@ config MAXLINEAR_GPHY
Support for the Maxlinear GPY115, GPY211, GPY212, GPY215,
GPY241, GPY245 PHYs.
-config MEDIATEK_GE_PHY
- tristate "MediaTek Gigabit Ethernet PHYs"
- help
- Supports the MediaTek Gigabit Ethernet PHYs.
-
-config MEDIATEK_GE_SOC_PHY
- tristate "MediaTek SoC Ethernet PHYs"
- depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
- depends on NVMEM_MTK_EFUSE
- help
- Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
-
- Include support for built-in Ethernet PHYs which are present in
- the MT7981 and MT7988 SoCs. These PHYs need calibration data
- present in the SoCs efuse and will dynamically calibrate VCM
- (common-mode voltage) during startup.
+source "drivers/net/phy/mediatek/Kconfig"
config MICREL_PHY
tristate "Micrel PHYs"
@@ -292,8 +277,8 @@ config MICREL_PHY
config MICROCHIP_T1S_PHY
tristate "Microchip 10BASE-T1S Ethernet PHYs"
help
- Currently supports the LAN8670/1/2 Rev.B1 and LAN8650/1 Rev.B0 Internal
- PHYs.
+ Currently supports the LAN8670/1/2 Rev.B1/C1/C2 and
+ LAN8650/1 Rev.B0/B1 Internal PHYs.
config MICROCHIP_PHY
tristate "Microchip PHYs"
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 90f886844381..e6145153e837 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -74,8 +74,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_MARVELL_88Q2XXX_PHY) += marvell-88q2xxx.o
obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o
obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
-obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
-obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
+obj-y += mediatek/
obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index 2e1a46e121d9..a2a862bae2ed 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -801,10 +801,8 @@ static void adin_get_strings(struct phy_device *phydev, u8 *data)
{
int i;
- for (i = 0; i < ARRAY_SIZE(adin_hw_stats); i++) {
- strscpy(&data[i * ETH_GSTRING_LEN],
- adin_hw_stats[i].string, ETH_GSTRING_LEN);
- }
+ for (i = 0; i < ARRAY_SIZE(adin_hw_stats); i++)
+ ethtool_puts(&data, adin_hw_stats[i].string);
}
static int adin_read_mmd_stat_regs(struct phy_device *phydev,
diff --git a/drivers/net/phy/aquantia/aquantia.h b/drivers/net/phy/aquantia/aquantia.h
index 2465345081f8..0c78bfabace5 100644
--- a/drivers/net/phy/aquantia/aquantia.h
+++ b/drivers/net/phy/aquantia/aquantia.h
@@ -177,6 +177,7 @@ static const struct aqr107_hw_stat aqr107_hw_stats[] = {
struct aqr107_priv {
u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
unsigned long leds_active_low;
+ unsigned long leds_active_high;
};
#if IS_REACHABLE(CONFIG_HWMON)
diff --git a/drivers/net/phy/aquantia/aquantia_leds.c b/drivers/net/phy/aquantia/aquantia_leds.c
index 201c8df93fad..00ad2313fed3 100644
--- a/drivers/net/phy/aquantia/aquantia_leds.c
+++ b/drivers/net/phy/aquantia/aquantia_leds.c
@@ -121,13 +121,13 @@ int aqr_phy_led_active_low_set(struct phy_device *phydev, int index, bool enable
{
return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_DRIVE(index),
VEND1_GLOBAL_LED_DRIVE_VDD,
- enable ? VEND1_GLOBAL_LED_DRIVE_VDD : 0);
+ enable ? 0 : VEND1_GLOBAL_LED_DRIVE_VDD);
}
int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long modes)
{
+ bool force_active_low = false, force_active_high = false;
struct aqr107_priv *priv = phydev->priv;
- bool active_low = false;
u32 mode;
if (index >= AQR_MAX_LEDS)
@@ -136,7 +136,10 @@ int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long
for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
switch (mode) {
case PHY_LED_ACTIVE_LOW:
- active_low = true;
+ force_active_low = true;
+ break;
+ case PHY_LED_ACTIVE_HIGH:
+ force_active_high = true;
break;
default:
return -EINVAL;
@@ -144,8 +147,14 @@ int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long
}
/* Save LED driver vdd state to restore on SW reset */
- if (active_low)
+ if (force_active_low)
priv->leds_active_low |= BIT(index);
- return aqr_phy_led_active_low_set(phydev, index, active_low);
+ if (force_active_high)
+ priv->leds_active_high |= BIT(index);
+
+ if (force_active_high || force_active_low)
+ return aqr_phy_led_active_low_set(phydev, index, force_active_low);
+
+ unreachable();
}
diff --git a/drivers/net/phy/aquantia/aquantia_main.c b/drivers/net/phy/aquantia/aquantia_main.c
index c33a5ef34ba0..bb56a66d2a48 100644
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/bitfield.h>
+#include <linux/of.h>
#include <linux/phy.h>
#include "aquantia.h"
@@ -41,6 +42,7 @@
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7
+#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF 9
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10
#define MDIO_AN_VEND_PROV 0xc400
@@ -52,6 +54,12 @@
#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0)
#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4
+#define MDIO_AN_RESVD_VEND_PROV 0xc410
+#define MDIO_AN_RESVD_VEND_PROV_MDIX_AUTO 0
+#define MDIO_AN_RESVD_VEND_PROV_MDIX_MDI 1
+#define MDIO_AN_RESVD_VEND_PROV_MDIX_MDIX 2
+#define MDIO_AN_RESVD_VEND_PROV_MDIX_MASK GENMASK(1, 0)
+
#define MDIO_AN_TX_VEND_STATUS1 0xc800
#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1)
#define MDIO_AN_TX_VEND_STATUS1_10BASET 0
@@ -62,6 +70,9 @@
#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5
#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0)
+#define MDIO_AN_RESVD_VEND_STATUS1 0xc810
+#define MDIO_AN_RESVD_VEND_STATUS1_MDIX BIT(8)
+
#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00
#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1)
@@ -71,6 +82,11 @@
#define MDIO_AN_TX_VEND_INT_MASK2 0xd401
#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0)
+#define PMAPMD_RSVD_VEND_PROV 0xe400
+#define PMAPMD_RSVD_VEND_PROV_MDI_CONF GENMASK(1, 0)
+#define PMAPMD_RSVD_VEND_PROV_MDI_REVERSE BIT(0)
+#define PMAPMD_RSVD_VEND_PROV_MDI_FORCE BIT(1)
+
#define MDIO_AN_RX_LP_STAT1 0xe820
#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15)
#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14)
@@ -148,12 +164,40 @@ static void aqr107_get_stats(struct phy_device *phydev,
}
}
+static int aqr_set_mdix(struct phy_device *phydev, int mdix)
+{
+ u16 val = 0;
+
+ switch (mdix) {
+ case ETH_TP_MDI:
+ val = MDIO_AN_RESVD_VEND_PROV_MDIX_MDI;
+ break;
+ case ETH_TP_MDI_X:
+ val = MDIO_AN_RESVD_VEND_PROV_MDIX_MDIX;
+ break;
+ case ETH_TP_MDI_AUTO:
+ case ETH_TP_MDI_INVALID:
+ default:
+ val = MDIO_AN_RESVD_VEND_PROV_MDIX_AUTO;
+ break;
+ }
+
+ return phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_RESVD_VEND_PROV,
+ MDIO_AN_RESVD_VEND_PROV_MDIX_MASK, val);
+}
+
static int aqr_config_aneg(struct phy_device *phydev)
{
bool changed = false;
u16 reg;
int ret;
+ ret = aqr_set_mdix(phydev, phydev->mdix_ctrl);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
if (phydev->autoneg == AUTONEG_DISABLE)
return genphy_c45_pma_setup_forced(phydev);
@@ -271,6 +315,21 @@ static int aqr_read_status(struct phy_device *phydev)
val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF);
}
+ val = genphy_c45_aneg_done(phydev);
+ if (val < 0)
+ return val;
+ if (val) {
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RESVD_VEND_STATUS1);
+ if (val < 0)
+ return val;
+ if (val & MDIO_AN_RESVD_VEND_STATUS1_MDIX)
+ phydev->mdix = ETH_TP_MDI_X;
+ else
+ phydev->mdix = ETH_TP_MDI;
+ } else {
+ phydev->mdix = ETH_TP_MDI_INVALID;
+ }
+
return genphy_c45_read_status(phydev);
}
@@ -342,9 +401,19 @@ static int aqr107_read_status(struct phy_device *phydev)
if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE)
return 0;
- val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS);
- if (val < 0)
- return val;
+ /**
+ * The status register is not immediately correct on line side link up.
+ * Poll periodically until it reflects the correct ON state.
+ * Only return fail for read error, timeout defaults to OFF state.
+ */
+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PHYXS,
+ MDIO_PHYXS_VEND_IF_STATUS, val,
+ (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val) !=
+ MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF),
+ AQR107_OP_IN_PROG_SLEEP,
+ AQR107_OP_IN_PROG_TIMEOUT, false);
+ if (ret && ret != -ETIMEDOUT)
+ return ret;
switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) {
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR:
@@ -371,7 +440,9 @@ static int aqr107_read_status(struct phy_device *phydev)
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
break;
+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF:
default:
+ phydev->link = false;
phydev->interface = PHY_INTERFACE_MODE_NA;
break;
}
@@ -485,10 +556,33 @@ static void aqr107_chip_info(struct phy_device *phydev)
fw_major, fw_minor, build_id, prov_id);
}
+static int aqr107_config_mdi(struct phy_device *phydev)
+{
+ struct device_node *np = phydev->mdio.dev.of_node;
+ u32 mdi_conf;
+ int ret;
+
+ ret = of_property_read_u32(np, "marvell,mdi-cfg-order", &mdi_conf);
+
+ /* Do nothing in case property "marvell,mdi-cfg-order" is not present */
+ if (ret == -EINVAL || ret == -ENOSYS)
+ return 0;
+
+ if (ret)
+ return ret;
+
+ if (mdi_conf & ~PMAPMD_RSVD_VEND_PROV_MDI_REVERSE)
+ return -EINVAL;
+
+ return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_RSVD_VEND_PROV,
+ PMAPMD_RSVD_VEND_PROV_MDI_CONF,
+ mdi_conf | PMAPMD_RSVD_VEND_PROV_MDI_FORCE);
+}
+
static int aqr107_config_init(struct phy_device *phydev)
{
struct aqr107_priv *priv = phydev->priv;
- u32 led_active_low;
+ u32 led_idx;
int ret;
/* Check that the PHY interface type is compatible */
@@ -514,9 +608,19 @@ static int aqr107_config_init(struct phy_device *phydev)
if (ret)
return ret;
+ ret = aqr107_config_mdi(phydev);
+ if (ret)
+ return ret;
+
/* Restore LED polarity state after reset */
- for_each_set_bit(led_active_low, &priv->leds_active_low, AQR_MAX_LEDS) {
- ret = aqr_phy_led_active_low_set(phydev, led_active_low, true);
+ for_each_set_bit(led_idx, &priv->leds_active_low, AQR_MAX_LEDS) {
+ ret = aqr_phy_led_active_low_set(phydev, led_idx, true);
+ if (ret)
+ return ret;
+ }
+
+ for_each_set_bit(led_idx, &priv->leds_active_high, AQR_MAX_LEDS) {
+ ret = aqr_phy_led_active_low_set(phydev, led_idx, false);
if (ret)
return ret;
}
diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c
index 6c52f7dda514..5198d66dbbc0 100644
--- a/drivers/net/phy/bcm-phy-lib.c
+++ b/drivers/net/phy/bcm-phy-lib.c
@@ -523,8 +523,7 @@ void bcm_phy_get_strings(struct phy_device *phydev, u8 *data)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
- strscpy(data + i * ETH_GSTRING_LEN,
- bcm_phy_hw_stats[i].string, ETH_GSTRING_LEN);
+ ethtool_puts(&data, bcm_phy_hw_stats[i].string);
}
EXPORT_SYMBOL_GPL(bcm_phy_get_strings);
@@ -1137,7 +1136,7 @@ int bcm_config_lre_aneg(struct phy_device *phydev, bool changed)
{
int err;
- if (genphy_config_eee_advert(phydev))
+ if (genphy_c45_an_config_eee_aneg(phydev) > 0)
changed = true;
err = bcm_setup_lre_master_slave(phydev);
diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
index 3ab64e04a01c..cf8b6d0bfaa9 100644
--- a/drivers/net/phy/dp83822.c
+++ b/drivers/net/phy/dp83822.c
@@ -506,7 +506,7 @@ static int dp83822_config_init(struct phy_device *phydev)
return dp83822_config_wol(phydev, &dp83822->wol);
}
-static int dp83826_config_rmii_mode(struct phy_device *phydev)
+static int dp8382x_config_rmii_mode(struct phy_device *phydev)
{
struct device *dev = &phydev->mdio.dev;
const char *of_val;
@@ -544,7 +544,7 @@ static int dp83826_config_init(struct phy_device *phydev)
if (ret)
return ret;
- ret = dp83826_config_rmii_mode(phydev);
+ ret = dp8382x_config_rmii_mode(phydev);
if (ret)
return ret;
} else {
@@ -585,9 +585,14 @@ static int dp83826_config_init(struct phy_device *phydev)
return dp83822_config_wol(phydev, &dp83822->wol);
}
-static int dp8382x_config_init(struct phy_device *phydev)
+static int dp83825_config_init(struct phy_device *phydev)
{
struct dp83822_private *dp83822 = phydev->priv;
+ int ret;
+
+ ret = dp8382x_config_rmii_mode(phydev);
+ if (ret)
+ return ret;
return dp83822_config_wol(phydev, &dp83822->wol);
}
@@ -782,14 +787,14 @@ static int dp83822_resume(struct phy_device *phydev)
.resume = dp83822_resume, \
}
-#define DP83826_PHY_DRIVER(_id, _name) \
+#define DP83825_PHY_DRIVER(_id, _name) \
{ \
PHY_ID_MATCH_MODEL(_id), \
.name = (_name), \
/* PHY_BASIC_FEATURES */ \
- .probe = dp83826_probe, \
+ .probe = dp8382x_probe, \
.soft_reset = dp83822_phy_reset, \
- .config_init = dp83826_config_init, \
+ .config_init = dp83825_config_init, \
.get_wol = dp83822_get_wol, \
.set_wol = dp83822_set_wol, \
.config_intr = dp83822_config_intr, \
@@ -798,14 +803,14 @@ static int dp83822_resume(struct phy_device *phydev)
.resume = dp83822_resume, \
}
-#define DP8382X_PHY_DRIVER(_id, _name) \
+#define DP83826_PHY_DRIVER(_id, _name) \
{ \
PHY_ID_MATCH_MODEL(_id), \
.name = (_name), \
/* PHY_BASIC_FEATURES */ \
- .probe = dp8382x_probe, \
+ .probe = dp83826_probe, \
.soft_reset = dp83822_phy_reset, \
- .config_init = dp8382x_config_init, \
+ .config_init = dp83826_config_init, \
.get_wol = dp83822_get_wol, \
.set_wol = dp83822_set_wol, \
.config_intr = dp83822_config_intr, \
@@ -816,12 +821,12 @@ static int dp83822_resume(struct phy_device *phydev)
static struct phy_driver dp83822_driver[] = {
DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"),
- DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"),
+ DP83825_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"),
+ DP83825_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"),
+ DP83825_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"),
+ DP83825_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"),
DP83826_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"),
DP83826_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"),
- DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"),
- DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"),
- DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"),
};
module_phy_driver(dp83822_driver);
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
index 937061acfc61..351411f0aa6f 100644
--- a/drivers/net/phy/dp83848.c
+++ b/drivers/net/phy/dp83848.c
@@ -147,6 +147,8 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
/* IRQ related */ \
.config_intr = dp83848_config_intr, \
.handle_interrupt = dp83848_handle_interrupt, \
+ \
+ .flags = PHY_RST_AFTER_CLK_EN, \
}
static struct phy_driver dp83848_driver[] = {
diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
index 5f056d7db83e..b6b38caf9c0e 100644
--- a/drivers/net/phy/dp83869.c
+++ b/drivers/net/phy/dp83869.c
@@ -153,19 +153,32 @@ struct dp83869_private {
int mode;
};
+static int dp83869_config_aneg(struct phy_device *phydev)
+{
+ struct dp83869_private *dp83869 = phydev->priv;
+
+ if (dp83869->mode != DP83869_RGMII_1000_BASE)
+ return genphy_config_aneg(phydev);
+
+ return genphy_c37_config_aneg(phydev);
+}
+
static int dp83869_read_status(struct phy_device *phydev)
{
struct dp83869_private *dp83869 = phydev->priv;
+ bool changed;
int ret;
+ if (dp83869->mode == DP83869_RGMII_1000_BASE)
+ return genphy_c37_read_status(phydev, &changed);
+
ret = genphy_read_status(phydev);
if (ret)
return ret;
- if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) {
+ if (dp83869->mode == DP83869_RGMII_100_BASE) {
if (phydev->link) {
- if (dp83869->mode == DP83869_RGMII_100_BASE)
- phydev->speed = SPEED_100;
+ phydev->speed = SPEED_100;
} else {
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
@@ -898,6 +911,7 @@ static int dp83869_phy_reset(struct phy_device *phydev)
.soft_reset = dp83869_phy_reset, \
.config_intr = dp83869_config_intr, \
.handle_interrupt = dp83869_handle_interrupt, \
+ .config_aneg = dp83869_config_aneg, \
.read_status = dp83869_read_status, \
.get_tunable = dp83869_get_tunable, \
.set_tunable = dp83869_set_tunable, \
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index a00a667454a9..ee438b71a0b4 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -540,8 +540,7 @@ static void ip101g_get_strings(struct phy_device *phydev, u8 *data)
int i;
for (i = 0; i < ARRAY_SIZE(ip101g_hw_stats); i++)
- strscpy(data + i * ETH_GSTRING_LEN,
- ip101g_hw_stats[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, ip101g_hw_stats[i].name);
}
static u64 ip101g_get_stat(struct phy_device *phydev, int i)
diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c
index 3c032868ef04..b672c55a7a4e 100644
--- a/drivers/net/phy/intel-xway.c
+++ b/drivers/net/phy/intel-xway.c
@@ -151,6 +151,13 @@
#define XWAY_MMD_LED3H 0x01E8
#define XWAY_MMD_LED3L 0x01E9
+#define XWAY_GPHY_MAX_LEDS 3
+#define XWAY_GPHY_LED_INV(idx) BIT(12 + (idx))
+#define XWAY_GPHY_LED_EN(idx) BIT(8 + (idx))
+#define XWAY_GPHY_LED_DA(idx) BIT(idx)
+#define XWAY_MMD_LEDxH(idx) (XWAY_MMD_LED0H + 2 * (idx))
+#define XWAY_MMD_LEDxL(idx) (XWAY_MMD_LED0L + 2 * (idx))
+
#define PHY_ID_PHY11G_1_3 0x030260D1
#define PHY_ID_PHY22F_1_3 0x030260E1
#define PHY_ID_PHY11G_1_4 0xD565A400
@@ -229,20 +236,12 @@ static int xway_gphy_rgmii_init(struct phy_device *phydev)
XWAY_MDIO_MIICTRL_TXSKEW_MASK, val);
}
-static int xway_gphy_config_init(struct phy_device *phydev)
+static int xway_gphy_init_leds(struct phy_device *phydev)
{
int err;
u32 ledxh;
u32 ledxl;
- /* Mask all interrupts */
- err = phy_write(phydev, XWAY_MDIO_IMASK, 0);
- if (err)
- return err;
-
- /* Clear all pending interrupts */
- phy_read(phydev, XWAY_MDIO_ISTAT);
-
/* Ensure that integrated led function is enabled for all leds */
err = phy_write(phydev, XWAY_MDIO_LED,
XWAY_MDIO_LED_LED0_EN |
@@ -276,6 +275,26 @@ static int xway_gphy_config_init(struct phy_device *phydev)
phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H, ledxh);
phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, ledxl);
+ return 0;
+}
+
+static int xway_gphy_config_init(struct phy_device *phydev)
+{
+ struct device_node *np = phydev->mdio.dev.of_node;
+ int err;
+
+ /* Mask all interrupts */
+ err = phy_write(phydev, XWAY_MDIO_IMASK, 0);
+ if (err)
+ return err;
+
+ /* Use default LED configuration if 'leds' node isn't defined */
+ if (!of_get_child_by_name(np, "leds"))
+ xway_gphy_init_leds(phydev);
+
+ /* Clear all pending interrupts */
+ phy_read(phydev, XWAY_MDIO_ISTAT);
+
err = xway_gphy_rgmii_init(phydev);
if (err)
return err;
@@ -347,6 +366,172 @@ static irqreturn_t xway_gphy_handle_interrupt(struct phy_device *phydev)
return IRQ_HANDLED;
}
+static int xway_gphy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value)
+{
+ int ret;
+
+ if (index >= XWAY_GPHY_MAX_LEDS)
+ return -EINVAL;
+
+ /* clear EN and set manual LED state */
+ ret = phy_modify(phydev, XWAY_MDIO_LED,
+ ((value == LED_OFF) ? XWAY_GPHY_LED_EN(index) : 0) |
+ XWAY_GPHY_LED_DA(index),
+ (value == LED_OFF) ? 0 : XWAY_GPHY_LED_DA(index));
+ if (ret)
+ return ret;
+
+ /* clear HW LED setup */
+ if (value == LED_OFF) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index), 0);
+ if (ret)
+ return ret;
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index), 0);
+ } else {
+ return 0;
+ }
+}
+
+static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) |
+ BIT(TRIGGER_NETDEV_LINK_10) |
+ BIT(TRIGGER_NETDEV_LINK_100) |
+ BIT(TRIGGER_NETDEV_LINK_1000) |
+ BIT(TRIGGER_NETDEV_RX) |
+ BIT(TRIGGER_NETDEV_TX));
+
+static int xway_gphy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ if (index >= XWAY_GPHY_MAX_LEDS)
+ return -EINVAL;
+
+ /* activity triggers are not possible without combination with a link
+ * trigger.
+ */
+ if (rules & (BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX)) &&
+ !(rules & (BIT(TRIGGER_NETDEV_LINK) |
+ BIT(TRIGGER_NETDEV_LINK_10) |
+ BIT(TRIGGER_NETDEV_LINK_100) |
+ BIT(TRIGGER_NETDEV_LINK_1000))))
+ return -EOPNOTSUPP;
+
+ /* All other combinations of the supported triggers are allowed */
+ if (rules & ~supported_triggers)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int xway_gphy_led_hw_control_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules)
+{
+ int lval, hval;
+
+ if (index >= XWAY_GPHY_MAX_LEDS)
+ return -EINVAL;
+
+ hval = phy_read_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index));
+ if (hval < 0)
+ return hval;
+
+ lval = phy_read_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index));
+ if (lval < 0)
+ return lval;
+
+ if (hval & XWAY_MMD_LEDxH_CON_LINK10)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
+
+ if (hval & XWAY_MMD_LEDxH_CON_LINK100)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
+
+ if (hval & XWAY_MMD_LEDxH_CON_LINK1000)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
+
+ if ((hval & XWAY_MMD_LEDxH_CON_LINK10) &&
+ (hval & XWAY_MMD_LEDxH_CON_LINK100) &&
+ (hval & XWAY_MMD_LEDxH_CON_LINK1000))
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
+
+ if (lval & XWAY_MMD_LEDxL_PULSE_TXACT)
+ *rules |= BIT(TRIGGER_NETDEV_TX);
+
+ if (lval & XWAY_MMD_LEDxL_PULSE_RXACT)
+ *rules |= BIT(TRIGGER_NETDEV_RX);
+
+ return 0;
+}
+
+static int xway_gphy_led_hw_control_set(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ u16 hval = 0, lval = 0;
+ int ret;
+
+ if (index >= XWAY_GPHY_MAX_LEDS)
+ return -EINVAL;
+
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
+ rules & BIT(TRIGGER_NETDEV_LINK_10))
+ hval |= XWAY_MMD_LEDxH_CON_LINK10;
+
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
+ rules & BIT(TRIGGER_NETDEV_LINK_100))
+ hval |= XWAY_MMD_LEDxH_CON_LINK100;
+
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
+ rules & BIT(TRIGGER_NETDEV_LINK_1000))
+ hval |= XWAY_MMD_LEDxH_CON_LINK1000;
+
+ if (rules & BIT(TRIGGER_NETDEV_TX))
+ lval |= XWAY_MMD_LEDxL_PULSE_TXACT;
+
+ if (rules & BIT(TRIGGER_NETDEV_RX))
+ lval |= XWAY_MMD_LEDxL_PULSE_RXACT;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index), hval);
+ if (ret)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index), lval);
+ if (ret)
+ return ret;
+
+ return phy_set_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_EN(index));
+}
+
+static int xway_gphy_led_polarity_set(struct phy_device *phydev, int index,
+ unsigned long modes)
+{
+ bool force_active_low = false, force_active_high = false;
+ u32 mode;
+
+ if (index >= XWAY_GPHY_MAX_LEDS)
+ return -EINVAL;
+
+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
+ switch (mode) {
+ case PHY_LED_ACTIVE_LOW:
+ force_active_low = true;
+ break;
+ case PHY_LED_ACTIVE_HIGH:
+ force_active_high = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ if (force_active_low)
+ return phy_set_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index));
+
+ if (force_active_high)
+ return phy_clear_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index));
+
+ unreachable();
+}
+
static struct phy_driver xway_gphy[] = {
{
.phy_id = PHY_ID_PHY11G_1_3,
@@ -359,6 +544,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY22F_1_3,
.phy_id_mask = 0xffffffff,
@@ -370,6 +560,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY11G_1_4,
.phy_id_mask = 0xffffffff,
@@ -381,6 +576,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY22F_1_4,
.phy_id_mask = 0xffffffff,
@@ -392,6 +592,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY11G_1_5,
.phy_id_mask = 0xffffffff,
@@ -402,6 +607,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY22F_1_5,
.phy_id_mask = 0xffffffff,
@@ -412,6 +622,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY11G_VR9_1_1,
.phy_id_mask = 0xffffffff,
@@ -422,6 +637,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY22F_VR9_1_1,
.phy_id_mask = 0xffffffff,
@@ -432,6 +652,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY11G_VR9_1_2,
.phy_id_mask = 0xffffffff,
@@ -442,6 +667,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
}, {
.phy_id = PHY_ID_PHY22F_VR9_1_2,
.phy_id_mask = 0xffffffff,
@@ -452,6 +682,11 @@ static struct phy_driver xway_gphy[] = {
.config_intr = xway_gphy_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .led_brightness_set = xway_gphy_led_brightness_set,
+ .led_hw_is_supported = xway_gphy_led_hw_is_supported,
+ .led_hw_control_get = xway_gphy_led_hw_control_get,
+ .led_hw_control_set = xway_gphy_led_hw_control_set,
+ .led_polarity_set = xway_gphy_led_polarity_set,
},
};
module_phy_driver(xway_gphy);
diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index c812f16eaa3a..5107f58338af 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -101,6 +101,22 @@ struct mmd_val {
u16 val;
};
+static const struct mmd_val mv88q2110_init_seq0[] = {
+ { MDIO_MMD_PCS, 0xffe4, 0x07b5 },
+ { MDIO_MMD_PCS, 0xffe4, 0x06b6 },
+};
+
+static const struct mmd_val mv88q2110_init_seq1[] = {
+ { MDIO_MMD_PCS, 0xffde, 0x402f },
+ { MDIO_MMD_PCS, 0xfe34, 0x4040 },
+ { MDIO_MMD_PCS, 0xfe2a, 0x3c1d },
+ { MDIO_MMD_PCS, 0xfe34, 0x0040 },
+ { MDIO_MMD_AN, 0x8032, 0x0064 },
+ { MDIO_MMD_AN, 0x8031, 0x0a01 },
+ { MDIO_MMD_AN, 0x8031, 0x0c01 },
+ { MDIO_MMD_PCS, 0xffdb, 0x0010 },
+};
+
static const struct mmd_val mv88q222x_revb0_init_seq0[] = {
{ MDIO_MMD_PCS, 0x8033, 0x6801 },
{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
@@ -174,20 +190,54 @@ static const struct mmd_val mv88q222x_revb1_revb2_init_seq1[] = {
{ MDIO_MMD_PCS, 0xfe11, 0x1105 },
};
+static int mv88q2xxx_write_mmd_vals(struct phy_device *phydev,
+ const struct mmd_val *vals, size_t len)
+{
+ int ret;
+
+ for (; len; vals++, len--) {
+ ret = phy_write_mmd(phydev, vals->devad, vals->regnum,
+ vals->val);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int mv88q2xxx_soft_reset(struct phy_device *phydev)
{
int ret;
int val;
- ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
- MDIO_PCS_1000BT1_CTRL, MDIO_PCS_1000BT1_CTRL_RESET);
+ /* Enable RESET of DCL */
+ if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x48);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_CTRL,
+ MDIO_PCS_1000BT1_CTRL_RESET);
if (ret < 0)
return ret;
- return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
- MDIO_PCS_1000BT1_CTRL, val,
- !(val & MDIO_PCS_1000BT1_CTRL_RESET),
- 50000, 600000, true);
+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
+ MDIO_PCS_1000BT1_CTRL, val,
+ !(val & MDIO_PCS_1000BT1_CTRL_RESET),
+ 50000, 600000, true);
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xffe4, 0xc);
+ if (ret < 0)
+ return ret;
+
+ /* Disable RESET of DCL */
+ if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000)
+ return phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x58);
+
+ return 0;
}
static int mv88q2xxx_read_link_gbit(struct phy_device *phydev)
@@ -390,15 +440,6 @@ static int mv88q2xxx_get_features(struct phy_device *phydev)
if (ret)
return ret;
- /* The PHY signalizes it supports autonegotiation. Unfortunately, so
- * far it was not possible to get a link even when following the init
- * sequence provided by Marvell. Disable it for now until a proper
- * workaround is found or a new PHY revision is released.
- */
- if (phydev->drv->phy_id == MARVELL_PHY_ID_88Q2110)
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- phydev->supported);
-
return 0;
}
@@ -705,60 +746,37 @@ static int mv88q2xxx_probe(struct phy_device *phydev)
return mv88q2xxx_hwmon_probe(phydev);
}
-static int mv88q222x_soft_reset(struct phy_device *phydev)
+static int mv88q2110_config_init(struct phy_device *phydev)
{
int ret;
- /* Enable RESET of DCL */
- if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) {
- ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x48);
- if (ret < 0)
- return ret;
- }
-
- ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_CTRL,
- MDIO_PCS_1000BT1_CTRL_RESET);
+ ret = mv88q2xxx_write_mmd_vals(phydev, mv88q2110_init_seq0,
+ ARRAY_SIZE(mv88q2110_init_seq0));
if (ret < 0)
return ret;
- ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xffe4, 0xc);
+ usleep_range(5000, 10000);
+
+ ret = mv88q2xxx_write_mmd_vals(phydev, mv88q2110_init_seq1,
+ ARRAY_SIZE(mv88q2110_init_seq1));
if (ret < 0)
return ret;
- /* Disable RESET of DCL */
- if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000)
- return phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x58);
-
- return 0;
-}
-
-static int mv88q222x_write_mmd_vals(struct phy_device *phydev,
- const struct mmd_val *vals, size_t len)
-{
- int ret;
-
- for (; len; vals++, len--) {
- ret = phy_write_mmd(phydev, vals->devad, vals->regnum,
- vals->val);
- if (ret < 0)
- return ret;
- }
-
- return 0;
+ return mv88q2xxx_config_init(phydev);
}
static int mv88q222x_revb0_config_init(struct phy_device *phydev)
{
int ret;
- ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb0_init_seq0,
+ ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb0_init_seq0,
ARRAY_SIZE(mv88q222x_revb0_init_seq0));
if (ret < 0)
return ret;
usleep_range(5000, 10000);
- ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb0_init_seq1,
+ ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb0_init_seq1,
ARRAY_SIZE(mv88q222x_revb0_init_seq1));
if (ret < 0)
return ret;
@@ -772,17 +790,17 @@ static int mv88q222x_revb1_revb2_config_init(struct phy_device *phydev)
int ret;
if (is_rev_b1)
- ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb1_init_seq0,
+ ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb1_init_seq0,
ARRAY_SIZE(mv88q222x_revb1_init_seq0));
else
- ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb2_init_seq0,
+ ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb2_init_seq0,
ARRAY_SIZE(mv88q222x_revb2_init_seq0));
if (ret < 0)
return ret;
usleep_range(3000, 5000);
- ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb1_revb2_init_seq1,
+ ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb1_revb2_init_seq1,
ARRAY_SIZE(mv88q222x_revb1_revb2_init_seq1));
if (ret < 0)
return ret;
@@ -888,7 +906,7 @@ static struct phy_driver mv88q2xxx_driver[] = {
.name = "mv88q2110",
.get_features = mv88q2xxx_get_features,
.config_aneg = mv88q2xxx_config_aneg,
- .config_init = mv88q2xxx_config_init,
+ .config_init = mv88q2110_config_init,
.read_status = mv88q2xxx_read_status,
.soft_reset = mv88q2xxx_soft_reset,
.set_loopback = genphy_c45_loopback,
@@ -906,7 +924,7 @@ static struct phy_driver mv88q2xxx_driver[] = {
.aneg_done = genphy_c45_aneg_done,
.config_init = mv88q222x_config_init,
.read_status = mv88q2xxx_read_status,
- .soft_reset = mv88q222x_soft_reset,
+ .soft_reset = mv88q2xxx_soft_reset,
.config_intr = mv88q2xxx_config_intr,
.handle_interrupt = mv88q2xxx_handle_interrupt,
.set_loopback = genphy_c45_loopback,
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 9964bf3dea2f..cd50cd6a7f75 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -176,6 +176,7 @@
#define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000
#define MII_M1011_PHY_STATUS_RESOLVED 0x0800
#define MII_M1011_PHY_STATUS_LINK 0x0400
+#define MII_M1011_PHY_STATUS_MDIX BIT(6)
#define MII_88E3016_PHY_SPEC_CTRL 0x10
#define MII_88E3016_DISABLE_SCRAMBLER 0x0200
@@ -1722,6 +1723,19 @@ static int marvell_read_status_page(struct phy_device *phydev, int page)
phydev->duplex = DUPLEX_UNKNOWN;
phydev->port = fiber ? PORT_FIBRE : PORT_TP;
+ if (fiber) {
+ phydev->mdix = ETH_TP_MDI_INVALID;
+ } else {
+ /* The MDI-X state is set regardless of Autoneg being enabled
+ * and reflects forced MDI-X state as well as auto resolution
+ */
+ if (status & MII_M1011_PHY_STATUS_RESOLVED)
+ phydev->mdix = status & MII_M1011_PHY_STATUS_MDIX ?
+ ETH_TP_MDI_X : ETH_TP_MDI;
+ else
+ phydev->mdix = ETH_TP_MDI_INVALID;
+ }
+
if (phydev->autoneg == AUTONEG_ENABLE)
err = marvell_read_status_page_an(phydev, fiber, status);
else
@@ -2006,10 +2020,8 @@ static void marvell_get_strings(struct phy_device *phydev, u8 *data)
int count = marvell_get_sset_count(phydev);
int i;
- for (i = 0; i < count; i++) {
- strscpy(data + i * ETH_GSTRING_LEN,
- marvell_hw_stats[i].string, ETH_GSTRING_LEN);
- }
+ for (i = 0; i < count; i++)
+ ethtool_puts(&data, marvell_hw_stats[i].string);
}
static void marvell_get_strings_simple(struct phy_device *phydev, u8 *data)
@@ -2017,10 +2029,8 @@ static void marvell_get_strings_simple(struct phy_device *phydev, u8 *data)
int count = marvell_get_sset_count_simple(phydev);
int i;
- for (i = 0; i < count; i++) {
- strscpy(data + i * ETH_GSTRING_LEN,
- marvell_hw_stats_simple[i].string, ETH_GSTRING_LEN);
- }
+ for (i = 0; i < count; i++)
+ ethtool_puts(&data, marvell_hw_stats_simple[i].string);
}
static u64 marvell_get_stat(struct phy_device *phydev, int i)
diff --git a/drivers/net/phy/mediatek/Kconfig b/drivers/net/phy/mediatek/Kconfig
new file mode 100644
index 000000000000..2a8ac5aed0f8
--- /dev/null
+++ b/drivers/net/phy/mediatek/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config MTK_NET_PHYLIB
+ tristate
+
+config MEDIATEK_GE_PHY
+ tristate "MediaTek Gigabit Ethernet PHYs"
+ select MTK_NET_PHYLIB
+ help
+ Supports the MediaTek non-built-in Gigabit Ethernet PHYs.
+
+ Non-built-in Gigabit Ethernet PHYs include mt7530/mt7531.
+ You may find mt7530 inside mt7621. This driver shares some
+ common operations with MediaTek SoC built-in Gigabit
+ Ethernet PHYs.
+
+config MEDIATEK_GE_SOC_PHY
+ tristate "MediaTek SoC Ethernet PHYs"
+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+ depends on NVMEM_MTK_EFUSE
+ select MTK_NET_PHYLIB
+ help
+ Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+
+ Include support for built-in Ethernet PHYs which are present in
+ the MT7981 and MT7988 SoCs. These PHYs need calibration data
+ present in the SoCs efuse and will dynamically calibrate VCM
+ (common-mode voltage) during startup.
diff --git a/drivers/net/phy/mediatek/Makefile b/drivers/net/phy/mediatek/Makefile
new file mode 100644
index 000000000000..814879d0abe5
--- /dev/null
+++ b/drivers/net/phy/mediatek/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_MTK_NET_PHYLIB) += mtk-phy-lib.o
+obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o
+obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o
diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek/mtk-ge-soc.c
index f4f9412d0cd7..38dc898eaf7b 100644
--- a/drivers/net/phy/mediatek-ge-soc.c
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
@@ -8,6 +8,8 @@
#include <linux/phy.h>
#include <linux/regmap.h>
+#include "mtk.h"
+
#define MTK_GPHY_ID_MT7981 0x03a29461
#define MTK_GPHY_ID_MT7988 0x03a29481
@@ -110,7 +112,7 @@
#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0)
#define MTK_PHY_RG_AD_CAL_COMP 0x17a
-#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8)
+#define MTK_PHY_AD_CAL_COMP_OUT_MASK GENMASK(8, 8)
#define MTK_PHY_RG_AD_CAL_CLK 0x17b
#define MTK_PHY_DA_CAL_CLK BIT(0)
@@ -210,41 +212,6 @@
#define MTK_PHY_DA_TX_R50_PAIR_D 0x540
/* Registers on MDIO_MMD_VEND2 */
-#define MTK_PHY_LED0_ON_CTRL 0x24
-#define MTK_PHY_LED1_ON_CTRL 0x26
-#define MTK_PHY_LED_ON_MASK GENMASK(6, 0)
-#define MTK_PHY_LED_ON_LINK1000 BIT(0)
-#define MTK_PHY_LED_ON_LINK100 BIT(1)
-#define MTK_PHY_LED_ON_LINK10 BIT(2)
-#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\
- MTK_PHY_LED_ON_LINK100 |\
- MTK_PHY_LED_ON_LINK1000)
-#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
-#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
-#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
-#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
-#define MTK_PHY_LED_ON_POLARITY BIT(14)
-#define MTK_PHY_LED_ON_ENABLE BIT(15)
-
-#define MTK_PHY_LED0_BLINK_CTRL 0x25
-#define MTK_PHY_LED1_BLINK_CTRL 0x27
-#define MTK_PHY_LED_BLINK_1000TX BIT(0)
-#define MTK_PHY_LED_BLINK_1000RX BIT(1)
-#define MTK_PHY_LED_BLINK_100TX BIT(2)
-#define MTK_PHY_LED_BLINK_100RX BIT(3)
-#define MTK_PHY_LED_BLINK_10TX BIT(4)
-#define MTK_PHY_LED_BLINK_10RX BIT(5)
-#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\
- MTK_PHY_LED_BLINK_100RX |\
- MTK_PHY_LED_BLINK_1000RX)
-#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\
- MTK_PHY_LED_BLINK_100TX |\
- MTK_PHY_LED_BLINK_1000TX)
-#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
-#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
-#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
-#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
-
#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1)
#define MTK_PHY_RG_BG_RASEL 0x115
@@ -299,29 +266,11 @@ enum CAL_MODE {
SW_M
};
-#define MTK_PHY_LED_STATE_FORCE_ON 0
-#define MTK_PHY_LED_STATE_FORCE_BLINK 1
-#define MTK_PHY_LED_STATE_NETDEV 2
-
-struct mtk_socphy_priv {
- unsigned long led_state;
-};
-
struct mtk_socphy_shared {
u32 boottrap;
struct mtk_socphy_priv priv[4];
};
-static int mtk_socphy_read_page(struct phy_device *phydev)
-{
- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
-}
-
-static int mtk_socphy_write_page(struct phy_device *phydev, int page)
-{
- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
-}
-
/* One calibration cycle consists of:
* 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
* until AD_CAL_COMP is ready to output calibration result.
@@ -342,7 +291,8 @@ static int cal_cycle(struct phy_device *phydev, int devad,
ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
MTK_PHY_RG_AD_CAL_CLK, reg_val,
reg_val & MTK_PHY_DA_CAL_CLK, 500,
- ANALOG_INTERNAL_OPERATION_MAX_US, false);
+ ANALOG_INTERNAL_OPERATION_MAX_US,
+ false);
if (ret) {
phydev_err(phydev, "Calibration cycle timeout\n");
return ret;
@@ -350,8 +300,10 @@ static int cal_cycle(struct phy_device *phydev, int devad,
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
MTK_PHY_DA_CALIN_FLAG);
- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
- MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP);
+ if (ret < 0)
+ return ret;
+ ret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret);
phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
return ret;
@@ -408,16 +360,17 @@ static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
{
- int i;
- int bias[16] = {};
- const int vals_9461[16] = { 7, 1, 4, 7,
- 7, 1, 4, 7,
- 7, 1, 4, 7,
- 7, 1, 4, 7 };
const int vals_9481[16] = { 10, 6, 6, 10,
10, 6, 6, 10,
10, 6, 6, 10,
10, 6, 6, 10 };
+ const int vals_9461[16] = { 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7 };
+ int bias[16] = {};
+ int i;
+
switch (phydev->drv->phy_id) {
case MTK_GPHY_ID_MT7981:
/* We add some calibration to efuse values
@@ -440,40 +393,72 @@ static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
}
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
- MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
+ buf[0] + bias[0]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
- MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
+ MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TBT_MASK,
+ buf[0] + bias[1]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
- MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
+ buf[0] + bias[2]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
- MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
+ MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TST_MASK,
+ buf[0] + bias[3]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
- MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
+ buf[1] + bias[4]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
- MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
+ MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TBT_MASK,
+ buf[1] + bias[5]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
- MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
+ buf[1] + bias[6]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
- MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
+ MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TST_MASK,
+ buf[1] + bias[7]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
- MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
+ buf[2] + bias[8]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
- MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
+ MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TBT_MASK,
+ buf[2] + bias[9]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
- MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
+ buf[2] + bias[10]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
- MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
+ MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TST_MASK,
+ buf[2] + bias[11]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
- MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
+ buf[3] + bias[12]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
- MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
+ MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TBT_MASK,
+ buf[3] + bias[13]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
- MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
+ buf[3] + bias[14]));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
- MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
+ MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TST_MASK,
+ buf[3] + bias[15]));
return 0;
}
@@ -662,7 +647,8 @@ static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
goto restore;
/* We calibrate TX-VCM in different logic. Check upper index and then
- * lower index. If this calibration is valid, apply lower index's result.
+ * lower index. If this calibration is valid, apply lower index's
+ * result.
*/
ret = upper_ret - lower_ret;
if (ret == 1) {
@@ -691,7 +677,8 @@ static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
} else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
lower_ret == 0) {
ret = 0;
- phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n",
+ phydev_warn(phydev,
+ "TX-VCM SW cal result at high margin 0x%x\n",
upper_idx);
} else {
ret = -EINVAL;
@@ -795,7 +782,8 @@ static void mt7981_phy_finetune(struct phy_device *phydev)
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK |
+ MTK_PHY_LPF_X_AVERAGE_MASK,
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
/* rg_tr_lpf_cnt_val = 512 */
@@ -864,7 +852,8 @@ static void mt7988_phy_finetune(struct phy_device *phydev)
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK |
+ MTK_PHY_LPF_X_AVERAGE_MASK,
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
/* rg_tr_lpf_cnt_val = 1023 */
@@ -976,7 +965,8 @@ static void mt798x_phy_eee(struct phy_device *phydev)
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
- __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
+ __phy_modify(phydev, MTK_PHY_LPI_REG_14,
+ MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
__phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
@@ -986,7 +976,8 @@ static void mt798x_phy_eee(struct phy_device *phydev)
phy_modify_mmd(phydev, MDIO_MMD_VEND1,
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ 0xff));
}
static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
@@ -1069,10 +1060,10 @@ static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
static int mt798x_phy_calibration(struct phy_device *phydev)
{
+ struct nvmem_cell *cell;
int ret = 0;
- u32 *buf;
size_t len;
- struct nvmem_cell *cell;
+ u32 *buf;
cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
if (IS_ERR(cell)) {
@@ -1130,72 +1121,23 @@ static int mt798x_phy_config_init(struct phy_device *phydev)
return mt798x_phy_calibration(phydev);
}
-static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
- bool on)
-{
- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
- struct mtk_socphy_priv *priv = phydev->priv;
- bool changed;
-
- if (on)
- changed = !test_and_set_bit(bit_on, &priv->led_state);
- else
- changed = !!test_and_clear_bit(bit_on, &priv->led_state);
-
- changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
- (index ? 16 : 0), &priv->led_state);
- if (changed)
- return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
- MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
- MTK_PHY_LED_ON_MASK,
- on ? MTK_PHY_LED_ON_FORCE_ON : 0);
- else
- return 0;
-}
-
-static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
- bool blinking)
-{
- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
- struct mtk_socphy_priv *priv = phydev->priv;
- bool changed;
-
- if (blinking)
- changed = !test_and_set_bit(bit_blink, &priv->led_state);
- else
- changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
-
- changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
- (index ? 16 : 0), &priv->led_state);
- if (changed)
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
- MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL,
- blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
- else
- return 0;
-}
-
static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
unsigned long *delay_on,
unsigned long *delay_off)
{
bool blinking = false;
- int err = 0;
-
- if (index > 1)
- return -EINVAL;
+ int err;
- if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
- blinking = true;
- *delay_on = 50;
- *delay_off = 50;
- }
+ err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
+ if (err < 0)
+ return err;
- err = mt798x_phy_hw_led_blink_set(phydev, index, blinking);
+ err = mtk_phy_hw_led_blink_set(phydev, index, blinking);
if (err)
return err;
- return mt798x_phy_hw_led_on_set(phydev, index, false);
+ return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,
+ false);
}
static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
@@ -1203,167 +1145,47 @@ static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
{
int err;
- err = mt798x_phy_hw_led_blink_set(phydev, index, false);
+ err = mtk_phy_hw_led_blink_set(phydev, index, false);
if (err)
return err;
- return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF));
+ return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK,
+ (value != LED_OFF));
}
-static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
- BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
- BIT(TRIGGER_NETDEV_LINK) |
- BIT(TRIGGER_NETDEV_LINK_10) |
- BIT(TRIGGER_NETDEV_LINK_100) |
- BIT(TRIGGER_NETDEV_LINK_1000) |
- BIT(TRIGGER_NETDEV_RX) |
- BIT(TRIGGER_NETDEV_TX));
+static const unsigned long supported_triggers =
+ BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
+ BIT(TRIGGER_NETDEV_LINK) |
+ BIT(TRIGGER_NETDEV_LINK_10) |
+ BIT(TRIGGER_NETDEV_LINK_100) |
+ BIT(TRIGGER_NETDEV_LINK_1000) |
+ BIT(TRIGGER_NETDEV_RX) |
+ BIT(TRIGGER_NETDEV_TX);
static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
unsigned long rules)
{
- if (index > 1)
- return -EINVAL;
-
- /* All combinations of the supported triggers are allowed */
- if (rules & ~supported_triggers)
- return -EOPNOTSUPP;
-
- return 0;
-};
+ return mtk_phy_led_hw_is_supported(phydev, index, rules,
+ supported_triggers);
+}
static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
unsigned long *rules)
{
- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
- struct mtk_socphy_priv *priv = phydev->priv;
- int on, blink;
-
- if (index > 1)
- return -EINVAL;
-
- on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
- index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
-
- if (on < 0)
- return -EIO;
-
- blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
- index ? MTK_PHY_LED1_BLINK_CTRL :
- MTK_PHY_LED0_BLINK_CTRL);
- if (blink < 0)
- return -EIO;
-
- if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
- MTK_PHY_LED_ON_LINKDOWN)) ||
- (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
- set_bit(bit_netdev, &priv->led_state);
- else
- clear_bit(bit_netdev, &priv->led_state);
-
- if (on & MTK_PHY_LED_ON_FORCE_ON)
- set_bit(bit_on, &priv->led_state);
- else
- clear_bit(bit_on, &priv->led_state);
-
- if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
- set_bit(bit_blink, &priv->led_state);
- else
- clear_bit(bit_blink, &priv->led_state);
-
- if (!rules)
- return 0;
-
- if (on & MTK_PHY_LED_ON_LINK)
- *rules |= BIT(TRIGGER_NETDEV_LINK);
-
- if (on & MTK_PHY_LED_ON_LINK10)
- *rules |= BIT(TRIGGER_NETDEV_LINK_10);
-
- if (on & MTK_PHY_LED_ON_LINK100)
- *rules |= BIT(TRIGGER_NETDEV_LINK_100);
-
- if (on & MTK_PHY_LED_ON_LINK1000)
- *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
-
- if (on & MTK_PHY_LED_ON_FDX)
- *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
-
- if (on & MTK_PHY_LED_ON_HDX)
- *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
-
- if (blink & MTK_PHY_LED_BLINK_RX)
- *rules |= BIT(TRIGGER_NETDEV_RX);
-
- if (blink & MTK_PHY_LED_BLINK_TX)
- *rules |= BIT(TRIGGER_NETDEV_TX);
-
- return 0;
+ return mtk_phy_led_hw_ctrl_get(phydev, index, rules,
+ MTK_GPHY_LED_ON_SET,
+ MTK_GPHY_LED_RX_BLINK_SET,
+ MTK_GPHY_LED_TX_BLINK_SET);
};
static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
unsigned long rules)
{
- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
- struct mtk_socphy_priv *priv = phydev->priv;
- u16 on = 0, blink = 0;
- int ret;
-
- if (index > 1)
- return -EINVAL;
-
- if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
- on |= MTK_PHY_LED_ON_FDX;
-
- if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
- on |= MTK_PHY_LED_ON_HDX;
-
- if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
- on |= MTK_PHY_LED_ON_LINK10;
-
- if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
- on |= MTK_PHY_LED_ON_LINK100;
-
- if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
- on |= MTK_PHY_LED_ON_LINK1000;
-
- if (rules & BIT(TRIGGER_NETDEV_RX)) {
- blink |= (on & MTK_PHY_LED_ON_LINK) ?
- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
- MTK_PHY_LED_BLINK_RX;
- }
-
- if (rules & BIT(TRIGGER_NETDEV_TX)) {
- blink |= (on & MTK_PHY_LED_ON_LINK) ?
- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
- MTK_PHY_LED_BLINK_TX;
- }
-
- if (blink || on)
- set_bit(bit_netdev, &priv->led_state);
- else
- clear_bit(bit_netdev, &priv->led_state);
-
- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
- MTK_PHY_LED1_ON_CTRL :
- MTK_PHY_LED0_ON_CTRL,
- MTK_PHY_LED_ON_FDX |
- MTK_PHY_LED_ON_HDX |
- MTK_PHY_LED_ON_LINK,
- on);
-
- if (ret)
- return ret;
-
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
- MTK_PHY_LED1_BLINK_CTRL :
- MTK_PHY_LED0_BLINK_CTRL, blink);
+ return mtk_phy_led_hw_ctrl_set(phydev, index, rules,
+ MTK_GPHY_LED_ON_SET,
+ MTK_GPHY_LED_RX_BLINK_SET,
+ MTK_GPHY_LED_TX_BLINK_SET);
};
static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
@@ -1398,7 +1220,8 @@ static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev)
/* Only now setup pinctrl to avoid bogus blinking */
pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
if (IS_ERR(pinctrl))
- dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED pinctrl\n");
+ dev_err(&phydev->mdio.bus->dev,
+ "Failed to setup PHY LED pinctrl\n");
return 0;
}
@@ -1415,7 +1238,7 @@ static int mt7988_phy_probe_shared(struct phy_device *phydev)
* LED_C and LED_D respectively. At the same time those pins are used to
* bootstrap configuration of the reference clock source (LED_A),
* DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
- * In practise this is done using a LED and a resistor pulling the pin
+ * In practice this is done using a LED and a resistor pulling the pin
* either to GND or to VIO.
* The detected value at boot time is accessible at run-time using the
* TPBANK0 register located in the gpio base of the pinctrl, in order
@@ -1437,14 +1260,6 @@ static int mt7988_phy_probe_shared(struct phy_device *phydev)
return 0;
}
-static void mt798x_phy_leds_state_init(struct phy_device *phydev)
-{
- int i;
-
- for (i = 0; i < 2; ++i)
- mt798x_phy_led_hw_control_get(phydev, i, NULL);
-}
-
static int mt7988_phy_probe(struct phy_device *phydev)
{
struct mtk_socphy_shared *shared;
@@ -1470,7 +1285,7 @@ static int mt7988_phy_probe(struct phy_device *phydev)
phydev->priv = priv;
- mt798x_phy_leds_state_init(phydev);
+ mtk_phy_leds_state_init(phydev);
err = mt7988_phy_fix_leds_polarities(phydev);
if (err)
@@ -1497,7 +1312,7 @@ static int mt7981_phy_probe(struct phy_device *phydev)
phydev->priv = priv;
- mt798x_phy_leds_state_init(phydev);
+ mtk_phy_leds_state_init(phydev);
return mt798x_phy_calibration(phydev);
}
@@ -1512,8 +1327,8 @@ static struct phy_driver mtk_socphy_driver[] = {
.probe = mt7981_phy_probe,
.suspend = genphy_suspend,
.resume = genphy_resume,
- .read_page = mtk_socphy_read_page,
- .write_page = mtk_socphy_write_page,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
.led_blink_set = mt798x_phy_led_blink_set,
.led_brightness_set = mt798x_phy_led_brightness_set,
.led_hw_is_supported = mt798x_phy_led_hw_is_supported,
@@ -1529,8 +1344,8 @@ static struct phy_driver mtk_socphy_driver[] = {
.probe = mt7988_phy_probe,
.suspend = genphy_suspend,
.resume = genphy_resume,
- .read_page = mtk_socphy_read_page,
- .write_page = mtk_socphy_write_page,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
.led_blink_set = mt798x_phy_led_blink_set,
.led_brightness_set = mt798x_phy_led_brightness_set,
.led_hw_is_supported = mt798x_phy_led_hw_is_supported,
diff --git a/drivers/net/phy/mediatek-ge.c b/drivers/net/phy/mediatek/mtk-ge.c
index 54ea64a37ab3..ed2617bc20f4 100644
--- a/drivers/net/phy/mediatek-ge.c
+++ b/drivers/net/phy/mediatek/mtk-ge.c
@@ -3,6 +3,11 @@
#include <linux/module.h>
#include <linux/phy.h>
+#include "mtk.h"
+
+#define MTK_GPHY_ID_MT7530 0x03a29412
+#define MTK_GPHY_ID_MT7531 0x03a29441
+
#define MTK_EXT_PAGE_ACCESS 0x1f
#define MTK_PHY_PAGE_STANDARD 0x0000
#define MTK_PHY_PAGE_EXTENDED 0x0001
@@ -11,16 +16,6 @@
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
-static int mtk_gephy_read_page(struct phy_device *phydev)
-{
- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
-}
-
-static int mtk_gephy_write_page(struct phy_device *phydev, int page)
-{
- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
-}
-
static void mtk_gephy_config_init(struct phy_device *phydev)
{
/* Enable HW auto downshift */
@@ -67,7 +62,7 @@ static int mt7531_phy_config_init(struct phy_device *phydev)
static struct phy_driver mtk_gephy_driver[] = {
{
- PHY_ID_MATCH_EXACT(0x03a29412),
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
.name = "MediaTek MT7530 PHY",
.config_init = mt7530_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
@@ -77,11 +72,11 @@ static struct phy_driver mtk_gephy_driver[] = {
.handle_interrupt = genphy_handle_interrupt_no_ack,
.suspend = genphy_suspend,
.resume = genphy_resume,
- .read_page = mtk_gephy_read_page,
- .write_page = mtk_gephy_write_page,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
},
{
- PHY_ID_MATCH_EXACT(0x03a29441),
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
.name = "MediaTek MT7531 PHY",
.config_init = mt7531_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
@@ -91,16 +86,16 @@ static struct phy_driver mtk_gephy_driver[] = {
.handle_interrupt = genphy_handle_interrupt_no_ack,
.suspend = genphy_suspend,
.resume = genphy_resume,
- .read_page = mtk_gephy_read_page,
- .write_page = mtk_gephy_write_page,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
},
};
module_phy_driver(mtk_gephy_driver);
static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
- { PHY_ID_MATCH_EXACT(0x03a29441) },
- { PHY_ID_MATCH_EXACT(0x03a29412) },
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
{ }
};
diff --git a/drivers/net/phy/mediatek/mtk-phy-lib.c b/drivers/net/phy/mediatek/mtk-phy-lib.c
new file mode 100644
index 000000000000..98a09d670e9c
--- /dev/null
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/phy.h>
+#include <linux/module.h>
+
+#include <linux/netdevice.h>
+
+#include "mtk.h"
+
+int mtk_phy_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_read_page);
+
+int mtk_phy_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_write_page);
+
+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules,
+ unsigned long supported_triggers)
+{
+ if (index > 1)
+ return -EINVAL;
+
+ /* All combinations of the supported triggers are allowed */
+ if (rules & ~supported_triggers)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported);
+
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules, u16 on_set,
+ u16 rx_blink_set, u16 tx_blink_set)
+{
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+ (index ? 16 : 0);
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+ struct mtk_socphy_priv *priv = phydev->priv;
+ int on, blink;
+
+ if (index > 1)
+ return -EINVAL;
+
+ on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
+
+ if (on < 0)
+ return -EIO;
+
+ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ index ? MTK_PHY_LED1_BLINK_CTRL :
+ MTK_PHY_LED0_BLINK_CTRL);
+ if (blink < 0)
+ return -EIO;
+
+ if ((on & (on_set | MTK_PHY_LED_ON_FDX |
+ MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
+ (blink & (rx_blink_set | tx_blink_set)))
+ set_bit(bit_netdev, &priv->led_state);
+ else
+ clear_bit(bit_netdev, &priv->led_state);
+
+ if (on & MTK_PHY_LED_ON_FORCE_ON)
+ set_bit(bit_on, &priv->led_state);
+ else
+ clear_bit(bit_on, &priv->led_state);
+
+ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
+ set_bit(bit_blink, &priv->led_state);
+ else
+ clear_bit(bit_blink, &priv->led_state);
+
+ if (!rules)
+ return 0;
+
+ if (on & on_set)
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
+
+ if (on & MTK_PHY_LED_ON_LINK10)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
+
+ if (on & MTK_PHY_LED_ON_LINK100)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
+
+ if (on & MTK_PHY_LED_ON_LINK1000)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
+
+ if (on & MTK_PHY_LED_ON_LINK2500)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
+
+ if (on & MTK_PHY_LED_ON_FDX)
+ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
+
+ if (on & MTK_PHY_LED_ON_HDX)
+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
+
+ if (blink & rx_blink_set)
+ *rules |= BIT(TRIGGER_NETDEV_RX);
+
+ if (blink & tx_blink_set)
+ *rules |= BIT(TRIGGER_NETDEV_TX);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get);
+
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
+ unsigned long rules, u16 on_set,
+ u16 rx_blink_set, u16 tx_blink_set)
+{
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+ struct mtk_socphy_priv *priv = phydev->priv;
+ u16 on = 0, blink = 0;
+ int ret;
+
+ if (index > 1)
+ return -EINVAL;
+
+ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
+ on |= MTK_PHY_LED_ON_FDX;
+
+ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
+ on |= MTK_PHY_LED_ON_HDX;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK10;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK100;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK1000;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK2500;
+
+ if (rules & BIT(TRIGGER_NETDEV_RX)) {
+ if (on & on_set) {
+ if (on & MTK_PHY_LED_ON_LINK10)
+ blink |= MTK_PHY_LED_BLINK_10RX;
+ if (on & MTK_PHY_LED_ON_LINK100)
+ blink |= MTK_PHY_LED_BLINK_100RX;
+ if (on & MTK_PHY_LED_ON_LINK1000)
+ blink |= MTK_PHY_LED_BLINK_1000RX;
+ if (on & MTK_PHY_LED_ON_LINK2500)
+ blink |= MTK_PHY_LED_BLINK_2500RX;
+ } else {
+ blink |= rx_blink_set;
+ }
+ }
+
+ if (rules & BIT(TRIGGER_NETDEV_TX)) {
+ if (on & on_set) {
+ if (on & MTK_PHY_LED_ON_LINK10)
+ blink |= MTK_PHY_LED_BLINK_10TX;
+ if (on & MTK_PHY_LED_ON_LINK100)
+ blink |= MTK_PHY_LED_BLINK_100TX;
+ if (on & MTK_PHY_LED_ON_LINK1000)
+ blink |= MTK_PHY_LED_BLINK_1000TX;
+ if (on & MTK_PHY_LED_ON_LINK2500)
+ blink |= MTK_PHY_LED_BLINK_2500TX;
+ } else {
+ blink |= tx_blink_set;
+ }
+ }
+
+ if (blink || on)
+ set_bit(bit_netdev, &priv->led_state);
+ else
+ clear_bit(bit_netdev, &priv->led_state);
+
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
+ MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | on_set,
+ on);
+
+ if (ret)
+ return ret;
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_BLINK_CTRL :
+ MTK_PHY_LED0_BLINK_CTRL, blink);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set);
+
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
+ unsigned long *delay_off, bool *blinking)
+{
+ if (index > 1)
+ return -EINVAL;
+
+ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
+ *blinking = true;
+ *delay_on = 50;
+ *delay_off = 50;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg);
+
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
+ u16 led_on_mask, bool on)
+{
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+ struct mtk_socphy_priv *priv = phydev->priv;
+ bool changed;
+
+ if (on)
+ changed = !test_and_set_bit(bit_on, &priv->led_state);
+ else
+ changed = !!test_and_clear_bit(bit_on, &priv->led_state);
+
+ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
+ (index ? 16 : 0), &priv->led_state);
+ if (changed)
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_ON_CTRL :
+ MTK_PHY_LED0_ON_CTRL,
+ led_on_mask,
+ on ? MTK_PHY_LED_ON_FORCE_ON : 0);
+ else
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set);
+
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, bool blinking)
+{
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+ (index ? 16 : 0);
+ struct mtk_socphy_priv *priv = phydev->priv;
+ bool changed;
+
+ if (blinking)
+ changed = !test_and_set_bit(bit_blink, &priv->led_state);
+ else
+ changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
+
+ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
+ (index ? 16 : 0), &priv->led_state);
+ if (changed)
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_BLINK_CTRL :
+ MTK_PHY_LED0_BLINK_CTRL,
+ blinking ?
+ MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
+ else
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set);
+
+void mtk_phy_leds_state_init(struct phy_device *phydev)
+{
+ int i;
+
+ for (i = 0; i < 2; ++i)
+ phydev->drv->led_hw_control_get(phydev, i, NULL);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);
+
+MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
+MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mediatek/mtk.h b/drivers/net/phy/mediatek/mtk.h
new file mode 100644
index 000000000000..63d9fe179b8f
--- /dev/null
+++ b/drivers/net/phy/mediatek/mtk.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Common definition for Mediatek Ethernet PHYs
+ * Author: SkyLake Huang <SkyLake.Huang@mediatek.com>
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef _MTK_EPHY_H_
+#define _MTK_EPHY_H_
+
+#define MTK_EXT_PAGE_ACCESS 0x1f
+
+/* Registers on MDIO_MMD_VEND2 */
+#define MTK_PHY_LED0_ON_CTRL 0x24
+#define MTK_PHY_LED1_ON_CTRL 0x26
+#define MTK_GPHY_LED_ON_MASK GENMASK(6, 0)
+#define MTK_2P5GPHY_LED_ON_MASK GENMASK(7, 0)
+#define MTK_PHY_LED_ON_LINK1000 BIT(0)
+#define MTK_PHY_LED_ON_LINK100 BIT(1)
+#define MTK_PHY_LED_ON_LINK10 BIT(2)
+#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
+#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
+#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
+#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
+#define MTK_PHY_LED_ON_LINK2500 BIT(7)
+#define MTK_PHY_LED_ON_POLARITY BIT(14)
+#define MTK_PHY_LED_ON_ENABLE BIT(15)
+
+#define MTK_PHY_LED0_BLINK_CTRL 0x25
+#define MTK_PHY_LED1_BLINK_CTRL 0x27
+#define MTK_PHY_LED_BLINK_1000TX BIT(0)
+#define MTK_PHY_LED_BLINK_1000RX BIT(1)
+#define MTK_PHY_LED_BLINK_100TX BIT(2)
+#define MTK_PHY_LED_BLINK_100RX BIT(3)
+#define MTK_PHY_LED_BLINK_10TX BIT(4)
+#define MTK_PHY_LED_BLINK_10RX BIT(5)
+#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
+#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
+#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
+#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
+#define MTK_PHY_LED_BLINK_2500TX BIT(10)
+#define MTK_PHY_LED_BLINK_2500RX BIT(11)
+
+#define MTK_GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK1000 | \
+ MTK_PHY_LED_ON_LINK100 | \
+ MTK_PHY_LED_ON_LINK10)
+#define MTK_GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
+ MTK_PHY_LED_BLINK_100RX | \
+ MTK_PHY_LED_BLINK_10RX)
+#define MTK_GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
+ MTK_PHY_LED_BLINK_100RX | \
+ MTK_PHY_LED_BLINK_10RX)
+
+#define MTK_2P5GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK2500 | \
+ MTK_GPHY_LED_ON_SET)
+#define MTK_2P5GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
+ MTK_GPHY_LED_RX_BLINK_SET)
+#define MTK_2P5GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
+ MTK_GPHY_LED_TX_BLINK_SET)
+
+#define MTK_PHY_LED_STATE_FORCE_ON 0
+#define MTK_PHY_LED_STATE_FORCE_BLINK 1
+#define MTK_PHY_LED_STATE_NETDEV 2
+
+struct mtk_socphy_priv {
+ unsigned long led_state;
+};
+
+int mtk_phy_read_page(struct phy_device *phydev);
+int mtk_phy_write_page(struct phy_device *phydev, int page);
+
+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules,
+ unsigned long supported_triggers);
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
+ unsigned long rules, u16 on_set,
+ u16 rx_blink_set, u16 tx_blink_set);
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules, u16 on_set,
+ u16 rx_blink_set, u16 tx_blink_set);
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
+ unsigned long *delay_off, bool *blinking);
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
+ u16 led_on_mask, bool on);
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
+ bool blinking);
+void mtk_phy_leds_state_init(struct phy_device *phydev);
+
+#endif /* _MTK_EPHY_H_ */
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 65b0a3115e14..3ef508840674 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -2004,7 +2004,7 @@ static int ksz9477_config_init(struct phy_device *phydev)
* in this switch shall be regarded as broken.
*/
if (phydev->dev_flags & MICREL_NO_EEE)
- phydev->eee_broken_modes = -1;
+ linkmode_fill(phydev->eee_broken_modes);
return kszphy_config_init(phydev);
}
@@ -2018,10 +2018,8 @@ static void kszphy_get_strings(struct phy_device *phydev, u8 *data)
{
int i;
- for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++) {
- strscpy(data + i * ETH_GSTRING_LEN,
- kszphy_hw_stats[i].string, ETH_GSTRING_LEN);
- }
+ for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++)
+ ethtool_puts(&data, kszphy_hw_stats[i].string);
}
static u64 kszphy_get_stat(struct phy_device *phydev, int i)
diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index a5ef8fe50704..b17bf6708003 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -6,6 +6,7 @@
#include <linux/delay.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <linux/sort.h>
#include <linux/ethtool.h>
#include <linux/ethtool_netlink.h>
#include <linux/bitfield.h>
@@ -226,6 +227,47 @@
#define MICROCHIP_CABLE_MAX_TIME_DIFF \
(MICROCHIP_CABLE_MIN_TIME_DIFF + MICROCHIP_CABLE_TIME_MARGIN)
+#define LAN887X_INT_STS 0xf000
+#define LAN887X_INT_MSK 0xf001
+#define LAN887X_INT_MSK_T1_PHY_INT_MSK BIT(2)
+#define LAN887X_INT_MSK_LINK_UP_MSK BIT(1)
+#define LAN887X_INT_MSK_LINK_DOWN_MSK BIT(0)
+
+#define LAN887X_MX_CHIP_TOP_LINK_MSK (LAN887X_INT_MSK_LINK_UP_MSK |\
+ LAN887X_INT_MSK_LINK_DOWN_MSK)
+
+#define LAN887X_MX_CHIP_TOP_ALL_MSK (LAN887X_INT_MSK_T1_PHY_INT_MSK |\
+ LAN887X_MX_CHIP_TOP_LINK_MSK)
+
+#define LAN887X_COEFF_PWR_DN_CONFIG_100 0x0404
+#define LAN887X_COEFF_PWR_DN_CONFIG_100_V 0x16d6
+#define LAN887X_SQI_CONFIG_100 0x042e
+#define LAN887X_SQI_CONFIG_100_V 0x9572
+#define LAN887X_SQI_MSE_100 0x483
+
+#define LAN887X_POKE_PEEK_100 0x040d
+#define LAN887X_POKE_PEEK_100_EN BIT(0)
+
+#define LAN887X_COEFF_MOD_CONFIG 0x080d
+#define LAN887X_COEFF_MOD_CONFIG_DCQ_COEFF_EN BIT(8)
+
+#define LAN887X_DCQ_SQI_STATUS 0x08b2
+
+/* SQI raw samples count */
+#define SQI_SAMPLES 200
+
+/* Samples percentage considered for SQI calculation */
+#define SQI_INLINERS_PERCENT 60
+
+/* Samples count considered for SQI calculation */
+#define SQI_INLIERS_NUM (SQI_SAMPLES * SQI_INLINERS_PERCENT / 100)
+
+/* Start offset of samples */
+#define SQI_INLIERS_START ((SQI_SAMPLES - SQI_INLIERS_NUM) / 2)
+
+/* End offset of samples */
+#define SQI_INLIERS_END (SQI_INLIERS_START + SQI_INLIERS_NUM)
+
#define DRIVER_AUTHOR "Nisar Sayed <nisar.sayed@microchip.com>"
#define DRIVER_DESC "Microchip LAN87XX/LAN937x/LAN887x T1 PHY driver"
@@ -1474,6 +1516,49 @@ static void lan887x_get_strings(struct phy_device *phydev, u8 *data)
ethtool_puts(&data, lan887x_hw_stats[i].string);
}
+static int lan887x_config_intr(struct phy_device *phydev)
+{
+ int rc;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+ /* Clear the interrupt status before enabling interrupts */
+ rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
+ if (rc < 0)
+ return rc;
+
+ /* Unmask for enabling interrupt */
+ rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_MSK,
+ (u16)~LAN887X_MX_CHIP_TOP_ALL_MSK);
+ } else {
+ rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_MSK,
+ GENMASK(15, 0));
+ if (rc < 0)
+ return rc;
+
+ rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
+ }
+
+ return rc < 0 ? rc : 0;
+}
+
+static irqreturn_t lan887x_handle_interrupt(struct phy_device *phydev)
+{
+ int irq_status;
+
+ irq_status = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
+ if (irq_status < 0) {
+ phy_error(phydev);
+ return IRQ_NONE;
+ }
+
+ if (irq_status & LAN887X_MX_CHIP_TOP_LINK_MSK) {
+ phy_trigger_machine(phydev);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
static int lan887x_cd_reset(struct phy_device *phydev,
enum cable_diag_state cd_done)
{
@@ -1504,6 +1589,10 @@ static int lan887x_cd_reset(struct phy_device *phydev,
if (rc < 0)
return rc;
+ rc = lan887x_config_intr(phydev);
+ if (rc < 0)
+ return rc;
+
rc = lan887x_phy_reconfig(phydev);
if (rc < 0)
return rc;
@@ -1830,6 +1919,145 @@ static int lan887x_cable_test_get_status(struct phy_device *phydev,
return lan887x_cable_test_report(phydev);
}
+/* Compare block to sort in ascending order */
+static int sqi_compare(const void *a, const void *b)
+{
+ return *(u16 *)a - *(u16 *)b;
+}
+
+static int lan887x_get_sqi_100M(struct phy_device *phydev)
+{
+ u16 rawtable[SQI_SAMPLES];
+ u32 sqiavg = 0;
+ u8 sqinum = 0;
+ int rc, i;
+
+ /* Configuration of SQI 100M */
+ rc = phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ LAN887X_COEFF_PWR_DN_CONFIG_100,
+ LAN887X_COEFF_PWR_DN_CONFIG_100_V);
+ if (rc < 0)
+ return rc;
+
+ rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, LAN887X_SQI_CONFIG_100,
+ LAN887X_SQI_CONFIG_100_V);
+ if (rc < 0)
+ return rc;
+
+ rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_SQI_CONFIG_100);
+ if (rc != LAN887X_SQI_CONFIG_100_V)
+ return -EINVAL;
+
+ rc = phy_modify_mmd(phydev, MDIO_MMD_VEND1, LAN887X_POKE_PEEK_100,
+ LAN887X_POKE_PEEK_100_EN,
+ LAN887X_POKE_PEEK_100_EN);
+ if (rc < 0)
+ return rc;
+
+ /* Required before reading register
+ * otherwise it will return high value
+ */
+ msleep(50);
+
+ /* Link check before raw readings */
+ rc = genphy_c45_read_link(phydev);
+ if (rc < 0)
+ return rc;
+
+ if (!phydev->link)
+ return -ENETDOWN;
+
+ /* Get 200 SQI raw readings */
+ for (i = 0; i < SQI_SAMPLES; i++) {
+ rc = phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ LAN887X_POKE_PEEK_100,
+ LAN887X_POKE_PEEK_100_EN);
+ if (rc < 0)
+ return rc;
+
+ rc = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ LAN887X_SQI_MSE_100);
+ if (rc < 0)
+ return rc;
+
+ rawtable[i] = (u16)rc;
+ }
+
+ /* Link check after raw readings */
+ rc = genphy_c45_read_link(phydev);
+ if (rc < 0)
+ return rc;
+
+ if (!phydev->link)
+ return -ENETDOWN;
+
+ /* Sort SQI raw readings in ascending order */
+ sort(rawtable, SQI_SAMPLES, sizeof(u16), sqi_compare, NULL);
+
+ /* Keep inliers and discard outliers */
+ for (i = SQI_INLIERS_START; i < SQI_INLIERS_END; i++)
+ sqiavg += rawtable[i];
+
+ /* Handle invalid samples */
+ if (sqiavg != 0) {
+ /* Get SQI average */
+ sqiavg /= SQI_INLIERS_NUM;
+
+ if (sqiavg < 75)
+ sqinum = 7;
+ else if (sqiavg < 94)
+ sqinum = 6;
+ else if (sqiavg < 119)
+ sqinum = 5;
+ else if (sqiavg < 150)
+ sqinum = 4;
+ else if (sqiavg < 189)
+ sqinum = 3;
+ else if (sqiavg < 237)
+ sqinum = 2;
+ else if (sqiavg < 299)
+ sqinum = 1;
+ else
+ sqinum = 0;
+ }
+
+ return sqinum;
+}
+
+static int lan887x_get_sqi(struct phy_device *phydev)
+{
+ int rc, val;
+
+ if (phydev->speed != SPEED_1000 &&
+ phydev->speed != SPEED_100)
+ return -ENETDOWN;
+
+ if (phydev->speed == SPEED_100)
+ return lan887x_get_sqi_100M(phydev);
+
+ /* Writing DCQ_COEFF_EN to trigger a SQI read */
+ rc = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ LAN887X_COEFF_MOD_CONFIG,
+ LAN887X_COEFF_MOD_CONFIG_DCQ_COEFF_EN);
+ if (rc < 0)
+ return rc;
+
+ /* Wait for DCQ done */
+ rc = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+ LAN887X_COEFF_MOD_CONFIG, val, ((val &
+ LAN887X_COEFF_MOD_CONFIG_DCQ_COEFF_EN) !=
+ LAN887X_COEFF_MOD_CONFIG_DCQ_COEFF_EN),
+ 10, 200, true);
+ if (rc < 0)
+ return rc;
+
+ rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_DCQ_SQI_STATUS);
+ if (rc < 0)
+ return rc;
+
+ return FIELD_GET(T1_DCQ_SQI_MSK, rc);
+}
+
static struct phy_driver microchip_t1_phy_driver[] = {
{
PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX),
@@ -1881,6 +2109,11 @@ static struct phy_driver microchip_t1_phy_driver[] = {
.read_status = genphy_c45_read_status,
.cable_test_start = lan887x_cable_test_start,
.cable_test_get_status = lan887x_cable_test_get_status,
+ .config_intr = lan887x_config_intr,
+ .handle_interrupt = lan887x_handle_interrupt,
+ .get_sqi = lan887x_get_sqi,
+ .get_sqi_max = lan87xx_get_sqi_max,
+ .set_loopback = genphy_c45_loopback,
}
};
diff --git a/drivers/net/phy/microchip_t1s.c b/drivers/net/phy/microchip_t1s.c
index 3614839a8e51..75d291154b4c 100644
--- a/drivers/net/phy/microchip_t1s.c
+++ b/drivers/net/phy/microchip_t1s.c
@@ -3,8 +3,8 @@
* Driver for Microchip 10BASE-T1S PHYs
*
* Support: Microchip Phys:
- * lan8670/1/2 Rev.B1
- * lan8650/1 Rev.B0 Internal PHYs
+ * lan8670/1/2 Rev.B1/C1/C2
+ * lan8650/1 Rev.B0/B1 Internal PHYs
*/
#include <linux/kernel.h>
@@ -12,7 +12,10 @@
#include <linux/phy.h>
#define PHY_ID_LAN867X_REVB1 0x0007C162
-#define PHY_ID_LAN865X_REVB0 0x0007C1B3
+#define PHY_ID_LAN867X_REVC1 0x0007C164
+#define PHY_ID_LAN867X_REVC2 0x0007C165
+/* Both Rev.B0 and B1 clause 22 PHYID's are same due to B1 chip limitation */
+#define PHY_ID_LAN865X_REVB 0x0007C1B3
#define LAN867X_REG_STS2 0x0019
@@ -23,6 +26,12 @@
#define LAN865X_REG_CFGPARAM_CTRL 0x00DA
#define LAN865X_REG_STS2 0x0019
+/* Collision Detector Control 0 Register */
+#define LAN86XX_REG_COL_DET_CTRL0 0x0087
+#define COL_DET_CTRL0_ENABLE_BIT_MASK BIT(15)
+#define COL_DET_ENABLE BIT(15)
+#define COL_DET_DISABLE 0x0000
+
#define LAN865X_CFGPARAM_READ_ENABLE BIT(1)
/* The arrays below are pulled from the following table from AN1699
@@ -59,29 +68,45 @@ static const u16 lan867x_revb1_fixup_masks[12] = {
0x0600, 0x7F00, 0x2000, 0xFFFF,
};
-/* LAN865x Rev.B0 configuration parameters from AN1760 */
-static const u32 lan865x_revb0_fixup_registers[28] = {
- 0x0091, 0x0081, 0x0043, 0x0044,
- 0x0045, 0x0053, 0x0054, 0x0055,
- 0x0040, 0x0050, 0x00D0, 0x00E9,
- 0x00F5, 0x00F4, 0x00F8, 0x00F9,
+/* LAN865x Rev.B0/B1 configuration parameters from AN1760
+ * As per the Configuration Application Note AN1760 published in the below link,
+ * https://www.microchip.com/en-us/application-notes/an1760
+ * Revision F (DS60001760G - June 2024)
+ */
+static const u32 lan865x_revb_fixup_registers[17] = {
+ 0x00D0, 0x00E0, 0x00E9, 0x00F5,
+ 0x00F4, 0x00F8, 0x00F9, 0x0081,
+ 0x0091, 0x0043, 0x0044, 0x0045,
+ 0x0053, 0x0054, 0x0055, 0x0040,
+ 0x0050,
+};
+
+static const u16 lan865x_revb_fixup_values[17] = {
+ 0x3F31, 0xC000, 0x9E50, 0x1CF8,
+ 0xC020, 0xB900, 0x4E53, 0x0080,
+ 0x9660, 0x00FF, 0xFFFF, 0x0000,
+ 0x00FF, 0xFFFF, 0x0000, 0x0002,
+ 0x0002,
+};
+
+static const u16 lan865x_revb_fixup_cfg_regs[2] = {
+ 0x0084, 0x008A,
+};
+
+static const u32 lan865x_revb_sqi_fixup_regs[12] = {
0x00B0, 0x00B1, 0x00B2, 0x00B3,
0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB,
};
-static const u16 lan865x_revb0_fixup_values[28] = {
- 0x9660, 0x00C0, 0x00FF, 0xFFFF,
- 0x0000, 0x00FF, 0xFFFF, 0x0000,
- 0x0002, 0x0002, 0x5F21, 0x9E50,
- 0x1CF8, 0xC020, 0x9B00, 0x4E53,
+static const u16 lan865x_revb_sqi_fixup_values[12] = {
0x0103, 0x0910, 0x1D26, 0x002A,
0x0103, 0x070D, 0x1720, 0x0027,
0x0509, 0x0E13, 0x1C25, 0x002B,
};
-static const u16 lan865x_revb0_fixup_cfg_regs[5] = {
- 0x0084, 0x008A, 0x00AD, 0x00AE, 0x00AF
+static const u16 lan865x_revb_sqi_fixup_cfg_regs[3] = {
+ 0x00AD, 0x00AE, 0x00AF,
};
/* Pulled from AN1760 describing 'indirect read'
@@ -92,7 +117,7 @@ static const u16 lan865x_revb0_fixup_cfg_regs[5] = {
*
* 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VEND2
*/
-static int lan865x_revb0_indirect_read(struct phy_device *phydev, u16 addr)
+static int lan865x_revb_indirect_read(struct phy_device *phydev, u16 addr)
{
int ret;
@@ -112,15 +137,18 @@ static int lan865x_revb0_indirect_read(struct phy_device *phydev, u16 addr)
/* This is pulled straight from AN1760 from 'calculation of offset 1' &
* 'calculation of offset 2'
*/
-static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[2])
+static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[])
{
const u16 fixup_regs[2] = {0x0004, 0x0008};
int ret;
for (int i = 0; i < ARRAY_SIZE(fixup_regs); i++) {
- ret = lan865x_revb0_indirect_read(phydev, fixup_regs[i]);
+ ret = lan865x_revb_indirect_read(phydev, fixup_regs[i]);
if (ret < 0)
return ret;
+
+ /* 5-bit signed value, sign extend */
+ ret &= GENMASK(4, 0);
if (ret & BIT(4))
offsets[i] = ret | 0xE0;
else
@@ -130,13 +158,15 @@ static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[2]
return 0;
}
-static int lan865x_read_cfg_params(struct phy_device *phydev, u16 cfg_params[])
+static int lan865x_read_cfg_params(struct phy_device *phydev,
+ const u16 cfg_regs[], u16 cfg_params[],
+ u8 count)
{
int ret;
- for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
+ for (int i = 0; i < count; i++) {
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
- lan865x_revb0_fixup_cfg_regs[i]);
+ cfg_regs[i]);
if (ret < 0)
return ret;
cfg_params[i] = (u16)ret;
@@ -145,13 +175,14 @@ static int lan865x_read_cfg_params(struct phy_device *phydev, u16 cfg_params[])
return 0;
}
-static int lan865x_write_cfg_params(struct phy_device *phydev, u16 cfg_params[])
+static int lan865x_write_cfg_params(struct phy_device *phydev,
+ const u16 cfg_regs[], u16 cfg_params[],
+ u8 count)
{
int ret;
- for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
- ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
- lan865x_revb0_fixup_cfg_regs[i],
+ for (int i = 0; i < count; i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, cfg_regs[i],
cfg_params[i]);
if (ret)
return ret;
@@ -160,60 +191,90 @@ static int lan865x_write_cfg_params(struct phy_device *phydev, u16 cfg_params[])
return 0;
}
-static int lan865x_setup_cfgparam(struct phy_device *phydev)
+static int lan865x_setup_cfgparam(struct phy_device *phydev, s8 offsets[])
{
- u16 cfg_params[ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs)];
- u16 cfg_results[5];
- s8 offsets[2];
+ u16 cfg_results[ARRAY_SIZE(lan865x_revb_fixup_cfg_regs)];
+ u16 cfg_params[ARRAY_SIZE(lan865x_revb_fixup_cfg_regs)];
int ret;
- ret = lan865x_generate_cfg_offsets(phydev, offsets);
+ ret = lan865x_read_cfg_params(phydev, lan865x_revb_fixup_cfg_regs,
+ cfg_params, ARRAY_SIZE(cfg_params));
if (ret)
return ret;
- ret = lan865x_read_cfg_params(phydev, cfg_params);
+ cfg_results[0] = FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) |
+ FIELD_PREP(GENMASK(9, 4), 14 + offsets[0]) |
+ 0x03;
+ cfg_results[1] = FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]);
+
+ return lan865x_write_cfg_params(phydev, lan865x_revb_fixup_cfg_regs,
+ cfg_results, ARRAY_SIZE(cfg_results));
+}
+
+static int lan865x_setup_sqi_cfgparam(struct phy_device *phydev, s8 offsets[])
+{
+ u16 cfg_results[ARRAY_SIZE(lan865x_revb_sqi_fixup_cfg_regs)];
+ u16 cfg_params[ARRAY_SIZE(lan865x_revb_sqi_fixup_cfg_regs)];
+ int ret;
+
+ ret = lan865x_read_cfg_params(phydev, lan865x_revb_sqi_fixup_cfg_regs,
+ cfg_params, ARRAY_SIZE(cfg_params));
if (ret)
return ret;
- cfg_results[0] = (cfg_params[0] & 0x000F) |
- FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) |
- FIELD_PREP(GENMASK(15, 4), 14 + offsets[0]);
- cfg_results[1] = (cfg_params[1] & 0x03FF) |
- FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]);
- cfg_results[2] = (cfg_params[2] & 0xC0C0) |
- FIELD_PREP(GENMASK(15, 8), 5 + offsets[0]) |
- (9 + offsets[0]);
- cfg_results[3] = (cfg_params[3] & 0xC0C0) |
- FIELD_PREP(GENMASK(15, 8), 9 + offsets[0]) |
- (14 + offsets[0]);
- cfg_results[4] = (cfg_params[4] & 0xC0C0) |
- FIELD_PREP(GENMASK(15, 8), 17 + offsets[0]) |
- (22 + offsets[0]);
-
- return lan865x_write_cfg_params(phydev, cfg_results);
+ cfg_results[0] = FIELD_PREP(GENMASK(13, 8), 5 + offsets[0]) |
+ (9 + offsets[0]);
+ cfg_results[1] = FIELD_PREP(GENMASK(13, 8), 9 + offsets[0]) |
+ (14 + offsets[0]);
+ cfg_results[2] = FIELD_PREP(GENMASK(13, 8), 17 + offsets[0]) |
+ (22 + offsets[0]);
+
+ return lan865x_write_cfg_params(phydev, lan865x_revb_sqi_fixup_cfg_regs,
+ cfg_results, ARRAY_SIZE(cfg_results));
}
-static int lan865x_revb0_config_init(struct phy_device *phydev)
+static int lan865x_revb_config_init(struct phy_device *phydev)
{
+ s8 offsets[2];
int ret;
/* Reference to AN1760
* https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8650-1-Configuration-60001760.pdf
*/
- for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_registers); i++) {
+ ret = lan865x_generate_cfg_offsets(phydev, offsets);
+ if (ret)
+ return ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb_fixup_registers); i++) {
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
- lan865x_revb0_fixup_registers[i],
- lan865x_revb0_fixup_values[i]);
+ lan865x_revb_fixup_registers[i],
+ lan865x_revb_fixup_values[i]);
if (ret)
return ret;
+
+ if (i == 1) {
+ ret = lan865x_setup_cfgparam(phydev, offsets);
+ if (ret)
+ return ret;
+ }
}
- /* Function to calculate and write the configuration parameters in the
- * 0x0084, 0x008A, 0x00AD, 0x00AE and 0x00AF registers (from AN1760)
- */
- return lan865x_setup_cfgparam(phydev);
+
+ ret = lan865x_setup_sqi_cfgparam(phydev, offsets);
+ if (ret)
+ return ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb_sqi_fixup_regs); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb_sqi_fixup_regs[i],
+ lan865x_revb_sqi_fixup_values[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
-static int lan867x_revb1_config_init(struct phy_device *phydev)
+static int lan867x_check_reset_complete(struct phy_device *phydev)
{
int err;
@@ -235,6 +296,69 @@ static int lan867x_revb1_config_init(struct phy_device *phydev)
}
}
+ return 0;
+}
+
+static int lan867x_revc_config_init(struct phy_device *phydev)
+{
+ s8 offsets[2];
+ int ret;
+
+ ret = lan867x_check_reset_complete(phydev);
+ if (ret)
+ return ret;
+
+ ret = lan865x_generate_cfg_offsets(phydev, offsets);
+ if (ret)
+ return ret;
+
+ /* LAN867x Rev.C1/C2 configuration settings are equal to the first 9
+ * configuration settings and all the sqi fixup settings from LAN865x
+ * Rev.B0/B1. So the same fixup registers and values from LAN865x
+ * Rev.B0/B1 are used for LAN867x Rev.C1/C2 to avoid duplication.
+ * Refer the below links for the comparison.
+ * https://www.microchip.com/en-us/application-notes/an1760
+ * Revision F (DS60001760G - June 2024)
+ * https://www.microchip.com/en-us/application-notes/an1699
+ * Revision E (DS60001699F - June 2024)
+ */
+ for (int i = 0; i < 9; i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb_fixup_registers[i],
+ lan865x_revb_fixup_values[i]);
+ if (ret)
+ return ret;
+
+ if (i == 1) {
+ ret = lan865x_setup_cfgparam(phydev, offsets);
+ if (ret)
+ return ret;
+ }
+ }
+
+ ret = lan865x_setup_sqi_cfgparam(phydev, offsets);
+ if (ret)
+ return ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb_sqi_fixup_regs); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb_sqi_fixup_regs[i],
+ lan865x_revb_sqi_fixup_values[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int lan867x_revb1_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ err = lan867x_check_reset_complete(phydev);
+ if (err)
+ return err;
+
/* Reference to AN1699
* https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf
* AN1699 says Read, Modify, Write, but the Write is not required if the
@@ -253,6 +377,36 @@ static int lan867x_revb1_config_init(struct phy_device *phydev)
return 0;
}
+/* As per LAN8650/1 Rev.B0/B1 AN1760 (Revision F (DS60001760G - June 2024)) and
+ * LAN8670/1/2 Rev.C1/C2 AN1699 (Revision E (DS60001699F - June 2024)), under
+ * normal operation, the device should be operated in PLCA mode. Disabling
+ * collision detection is recommended to allow the device to operate in noisy
+ * environments or when reflections and other inherent transmission line
+ * distortion cause poor signal quality. Collision detection must be re-enabled
+ * if the device is configured to operate in CSMA/CD mode.
+ *
+ * AN1760: https://www.microchip.com/en-us/application-notes/an1760
+ * AN1699: https://www.microchip.com/en-us/application-notes/an1699
+ */
+static int lan86xx_plca_set_cfg(struct phy_device *phydev,
+ const struct phy_plca_cfg *plca_cfg)
+{
+ int ret;
+
+ ret = genphy_c45_plca_set_cfg(phydev, plca_cfg);
+ if (ret)
+ return ret;
+
+ if (plca_cfg->enabled)
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2,
+ LAN86XX_REG_COL_DET_CTRL0,
+ COL_DET_CTRL0_ENABLE_BIT_MASK,
+ COL_DET_DISABLE);
+
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LAN86XX_REG_COL_DET_CTRL0,
+ COL_DET_CTRL0_ENABLE_BIT_MASK, COL_DET_ENABLE);
+}
+
static int lan86xx_read_status(struct phy_device *phydev)
{
/* The phy has some limitations, namely:
@@ -308,15 +462,35 @@ static struct phy_driver microchip_t1s_driver[] = {
.get_plca_status = genphy_c45_plca_get_status,
},
{
- PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0),
- .name = "LAN865X Rev.B0 Internal Phy",
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC1),
+ .name = "LAN867X Rev.C1",
.features = PHY_BASIC_T1S_P2MP_FEATURES,
- .config_init = lan865x_revb0_config_init,
+ .config_init = lan867x_revc_config_init,
+ .read_status = lan86xx_read_status,
+ .get_plca_cfg = genphy_c45_plca_get_cfg,
+ .set_plca_cfg = lan86xx_plca_set_cfg,
+ .get_plca_status = genphy_c45_plca_get_status,
+ },
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC2),
+ .name = "LAN867X Rev.C2",
+ .features = PHY_BASIC_T1S_P2MP_FEATURES,
+ .config_init = lan867x_revc_config_init,
+ .read_status = lan86xx_read_status,
+ .get_plca_cfg = genphy_c45_plca_get_cfg,
+ .set_plca_cfg = lan86xx_plca_set_cfg,
+ .get_plca_status = genphy_c45_plca_get_status,
+ },
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB),
+ .name = "LAN865X Rev.B0/B1 Internal Phy",
+ .features = PHY_BASIC_T1S_P2MP_FEATURES,
+ .config_init = lan865x_revb_config_init,
.read_status = lan86xx_read_status,
.read_mmd = lan865x_phy_read_mmd,
.write_mmd = lan865x_phy_write_mmd,
.get_plca_cfg = genphy_c45_plca_get_cfg,
- .set_plca_cfg = genphy_c45_plca_set_cfg,
+ .set_plca_cfg = lan86xx_plca_set_cfg,
.get_plca_status = genphy_c45_plca_get_status,
},
};
@@ -325,7 +499,9 @@ module_phy_driver(microchip_t1s_driver);
static struct mdio_device_id __maybe_unused tbl[] = {
{ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) },
- { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC1) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC2) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB) },
{ }
};
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
index 6f74ce0ab1aa..bee381200ab8 100644
--- a/drivers/net/phy/mscc/mscc_main.c
+++ b/drivers/net/phy/mscc/mscc_main.c
@@ -139,8 +139,7 @@ static void vsc85xx_get_strings(struct phy_device *phydev, u8 *data)
return;
for (i = 0; i < priv->nstats; i++)
- strscpy(data + i * ETH_GSTRING_LEN, priv->hw_stats[i].string,
- ETH_GSTRING_LEN);
+ ethtool_puts(&data, priv->hw_stats[i].string);
}
static u64 vsc85xx_get_stat(struct phy_device *phydev, int i)
diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c
index e5f8ac4b4604..db3c1f72b407 100644
--- a/drivers/net/phy/mxl-gpy.c
+++ b/drivers/net/phy/mxl-gpy.c
@@ -38,6 +38,7 @@
#define PHY_MIISTAT 0x18 /* MII state */
#define PHY_IMASK 0x19 /* interrupt mask */
#define PHY_ISTAT 0x1A /* interrupt status */
+#define PHY_LED 0x1B /* LEDs */
#define PHY_FWV 0x1E /* firmware version */
#define PHY_MIISTAT_SPD_MASK GENMASK(2, 0)
@@ -61,6 +62,11 @@
PHY_IMASK_ADSC | \
PHY_IMASK_ANC)
+#define GPY_MAX_LEDS 4
+#define PHY_LED_POLARITY(idx) BIT(12 + (idx))
+#define PHY_LED_HWCONTROL(idx) BIT(8 + (idx))
+#define PHY_LED_ON(idx) BIT(idx)
+
#define PHY_FWV_REL_MASK BIT(15)
#define PHY_FWV_MAJOR_MASK GENMASK(11, 8)
#define PHY_FWV_MINOR_MASK GENMASK(7, 0)
@@ -72,6 +78,23 @@
#define PHY_MDI_MDI_X_CD 0x1
#define PHY_MDI_MDI_X_CROSS 0x0
+/* LED */
+#define VSPEC1_LED(idx) (1 + (idx))
+#define VSPEC1_LED_BLINKS GENMASK(15, 12)
+#define VSPEC1_LED_PULSE GENMASK(11, 8)
+#define VSPEC1_LED_CON GENMASK(7, 4)
+#define VSPEC1_LED_BLINKF GENMASK(3, 0)
+
+#define VSPEC1_LED_LINK10 BIT(0)
+#define VSPEC1_LED_LINK100 BIT(1)
+#define VSPEC1_LED_LINK1000 BIT(2)
+#define VSPEC1_LED_LINK2500 BIT(3)
+
+#define VSPEC1_LED_TXACT BIT(0)
+#define VSPEC1_LED_RXACT BIT(1)
+#define VSPEC1_LED_COL BIT(2)
+#define VSPEC1_LED_NO_CON BIT(3)
+
/* SGMII */
#define VSPEC1_SGMII_CTRL 0x08
#define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */
@@ -835,6 +858,165 @@ static int gpy115_loopback(struct phy_device *phydev, bool enable)
return genphy_soft_reset(phydev);
}
+static int gpy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value)
+{
+ int ret;
+
+ if (index >= GPY_MAX_LEDS)
+ return -EINVAL;
+
+ /* clear HWCONTROL and set manual LED state */
+ ret = phy_modify(phydev, PHY_LED,
+ ((value == LED_OFF) ? PHY_LED_HWCONTROL(index) : 0) |
+ PHY_LED_ON(index),
+ (value == LED_OFF) ? 0 : PHY_LED_ON(index));
+ if (ret)
+ return ret;
+
+ /* ToDo: set PWM brightness */
+
+ /* clear HW LED setup */
+ if (value == LED_OFF)
+ return phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index), 0);
+ else
+ return 0;
+}
+
+static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) |
+ BIT(TRIGGER_NETDEV_LINK_10) |
+ BIT(TRIGGER_NETDEV_LINK_100) |
+ BIT(TRIGGER_NETDEV_LINK_1000) |
+ BIT(TRIGGER_NETDEV_LINK_2500) |
+ BIT(TRIGGER_NETDEV_RX) |
+ BIT(TRIGGER_NETDEV_TX));
+
+static int gpy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ if (index >= GPY_MAX_LEDS)
+ return -EINVAL;
+
+ /* All combinations of the supported triggers are allowed */
+ if (rules & ~supported_triggers)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int gpy_led_hw_control_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules)
+{
+ int val;
+
+ if (index >= GPY_MAX_LEDS)
+ return -EINVAL;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index));
+ if (val < 0)
+ return val;
+
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK10)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
+
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK100)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
+
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK1000)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
+
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK2500)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
+
+ if (FIELD_GET(VSPEC1_LED_CON, val) == (VSPEC1_LED_LINK10 |
+ VSPEC1_LED_LINK100 |
+ VSPEC1_LED_LINK1000 |
+ VSPEC1_LED_LINK2500))
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
+
+ if (FIELD_GET(VSPEC1_LED_PULSE, val) & VSPEC1_LED_TXACT)
+ *rules |= BIT(TRIGGER_NETDEV_TX);
+
+ if (FIELD_GET(VSPEC1_LED_PULSE, val) & VSPEC1_LED_RXACT)
+ *rules |= BIT(TRIGGER_NETDEV_RX);
+
+ return 0;
+}
+
+static int gpy_led_hw_control_set(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ u16 val = 0;
+ int ret;
+
+ if (index >= GPY_MAX_LEDS)
+ return -EINVAL;
+
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
+ rules & BIT(TRIGGER_NETDEV_LINK_10))
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK10);
+
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
+ rules & BIT(TRIGGER_NETDEV_LINK_100))
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK100);
+
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
+ rules & BIT(TRIGGER_NETDEV_LINK_1000))
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK1000);
+
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
+ rules & BIT(TRIGGER_NETDEV_LINK_2500))
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK2500);
+
+ if (rules & BIT(TRIGGER_NETDEV_TX))
+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_TXACT);
+
+ if (rules & BIT(TRIGGER_NETDEV_RX))
+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_RXACT);
+
+ /* allow RX/TX pulse without link indication */
+ if ((rules & BIT(TRIGGER_NETDEV_TX) || rules & BIT(TRIGGER_NETDEV_RX)) &&
+ !(val & VSPEC1_LED_CON))
+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_NO_CON) | VSPEC1_LED_CON;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index), val);
+ if (ret)
+ return ret;
+
+ return phy_set_bits(phydev, PHY_LED, PHY_LED_HWCONTROL(index));
+}
+
+static int gpy_led_polarity_set(struct phy_device *phydev, int index,
+ unsigned long modes)
+{
+ bool force_active_low = false, force_active_high = false;
+ u32 mode;
+
+ if (index >= GPY_MAX_LEDS)
+ return -EINVAL;
+
+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
+ switch (mode) {
+ case PHY_LED_ACTIVE_LOW:
+ force_active_low = true;
+ break;
+ case PHY_LED_ACTIVE_HIGH:
+ force_active_high = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ if (force_active_low)
+ return phy_set_bits(phydev, PHY_LED, PHY_LED_POLARITY(index));
+
+ if (force_active_high)
+ return phy_clear_bits(phydev, PHY_LED, PHY_LED_POLARITY(index));
+
+ unreachable();
+}
+
static struct phy_driver gpy_drivers[] = {
{
PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx),
@@ -852,6 +1034,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
.phy_id = PHY_ID_GPY115B,
@@ -870,6 +1057,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy115_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
PHY_ID_MATCH_MODEL(PHY_ID_GPY115C),
@@ -887,6 +1079,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy115_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
.phy_id = PHY_ID_GPY211B,
@@ -905,6 +1102,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
PHY_ID_MATCH_MODEL(PHY_ID_GPY211C),
@@ -922,6 +1124,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
.phy_id = PHY_ID_GPY212B,
@@ -940,6 +1147,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
PHY_ID_MATCH_MODEL(PHY_ID_GPY212C),
@@ -957,6 +1169,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
.phy_id = PHY_ID_GPY215B,
@@ -975,6 +1192,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
PHY_ID_MATCH_MODEL(PHY_ID_GPY215C),
@@ -992,6 +1214,11 @@ static struct phy_driver gpy_drivers[] = {
.set_wol = gpy_set_wol,
.get_wol = gpy_get_wol,
.set_loopback = gpy_loopback,
+ .led_brightness_set = gpy_led_brightness_set,
+ .led_hw_is_supported = gpy_led_hw_is_supported,
+ .led_hw_control_get = gpy_led_hw_control_get,
+ .led_hw_control_set = gpy_led_hw_control_set,
+ .led_polarity_set = gpy_led_polarity_set,
},
{
PHY_ID_MATCH_MODEL(PHY_ID_GPY241B),
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index 5af5ade4fc64..ade544bc007d 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/mii.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/phy.h>
#include <linux/processor.h>
#include <linux/property.h>
@@ -185,6 +186,8 @@
#define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb)
+#define TJA11XX_REVERSE_MODE BIT(0)
+
struct nxp_c45_phy;
struct nxp_c45_skb_cb {
@@ -1137,13 +1140,11 @@ static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data)
for (i = 0; i < count; i++) {
if (i < ARRAY_SIZE(common_hw_stats)) {
- strscpy(data + i * ETH_GSTRING_LEN,
- common_hw_stats[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, common_hw_stats[i].name);
continue;
}
idx = i - ARRAY_SIZE(common_hw_stats);
- strscpy(data + i * ETH_GSTRING_LEN,
- phy_data->stats[idx].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, phy_data->stats[idx].name);
}
}
@@ -1510,6 +1511,8 @@ static int nxp_c45_get_delays(struct phy_device *phydev)
static int nxp_c45_set_phy_mode(struct phy_device *phydev)
{
+ struct nxp_c45_phy *priv = phydev->priv;
+ u16 basic_config;
int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES);
@@ -1561,8 +1564,15 @@ static int nxp_c45_set_phy_mode(struct phy_device *phydev)
phydev_err(phydev, "rmii mode not supported\n");
return -EINVAL;
}
+
+ basic_config = MII_BASIC_CONFIG_RMII;
+
+ /* This is not PHY_INTERFACE_MODE_REVRMII */
+ if (priv->flags & TJA11XX_REVERSE_MODE)
+ basic_config |= MII_BASIC_CONFIG_REV;
+
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
- MII_BASIC_CONFIG_RMII);
+ basic_config);
break;
case PHY_INTERFACE_MODE_SGMII:
if (!(ret & SGMII_ABILITY)) {
@@ -1623,6 +1633,20 @@ static int nxp_c45_get_features(struct phy_device *phydev)
return genphy_c45_pma_read_abilities(phydev);
}
+static int nxp_c45_parse_dt(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ struct nxp_c45_phy *priv = phydev->priv;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
+ return 0;
+
+ if (of_property_read_bool(node, "nxp,rmii-refclk-out"))
+ priv->flags |= TJA11XX_REVERSE_MODE;
+
+ return 0;
+}
+
static int nxp_c45_probe(struct phy_device *phydev)
{
struct nxp_c45_phy *priv;
@@ -1642,6 +1666,8 @@ static int nxp_c45_probe(struct phy_device *phydev)
phydev->priv = priv;
+ nxp_c45_parse_dt(phydev);
+
mutex_init(&priv->ptp_lock);
phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1,
diff --git a/drivers/net/phy/nxp-c45-tja11xx.h b/drivers/net/phy/nxp-c45-tja11xx.h
index f364fca68f0b..8b5fc383752b 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.h
+++ b/drivers/net/phy/nxp-c45-tja11xx.h
@@ -28,6 +28,7 @@ struct nxp_c45_phy {
int extts_index;
bool extts;
struct nxp_c45_macsec *macsec;
+ u32 flags;
};
#if IS_ENABLED(CONFIG_MACSEC)
diff --git a/drivers/net/phy/nxp-cbtx.c b/drivers/net/phy/nxp-cbtx.c
index 145703f0a406..3d25491043a3 100644
--- a/drivers/net/phy/nxp-cbtx.c
+++ b/drivers/net/phy/nxp-cbtx.c
@@ -182,7 +182,7 @@ static int cbtx_get_sset_count(struct phy_device *phydev)
static void cbtx_get_strings(struct phy_device *phydev, u8 *data)
{
- strncpy(data, "100btx_rx_err", ETH_GSTRING_LEN);
+ ethtool_puts(&data, "100btx_rx_err");
}
static void cbtx_get_stats(struct phy_device *phydev,
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 5695935fdce9..944ae98ad110 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -680,17 +680,16 @@ EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
* @phydev: target phy_device struct
* @adv: the linkmode advertisement settings
*/
-int genphy_c45_write_eee_adv(struct phy_device *phydev, unsigned long *adv)
+static int genphy_c45_write_eee_adv(struct phy_device *phydev,
+ unsigned long *adv)
{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp);
int val, changed = 0;
- if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP1_FEATURES)) {
- val = linkmode_to_mii_eee_cap1_t(adv);
+ linkmode_andnot(tmp, adv, phydev->eee_broken_modes);
- /* In eee_broken_modes are stored MDIO_AN_EEE_ADV specific raw
- * register values.
- */
- val &= ~phydev->eee_broken_modes;
+ if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP1_FEATURES)) {
+ val = linkmode_to_mii_eee_cap1_t(tmp);
/* IEEE 802.3-2018 45.2.7.13 EEE advertisement 1
* (Register 7.60)
@@ -708,7 +707,7 @@ int genphy_c45_write_eee_adv(struct phy_device *phydev, unsigned long *adv)
}
if (linkmode_intersects(phydev->supported_eee, PHY_EEE_CAP2_FEATURES)) {
- val = linkmode_to_mii_eee_cap2_t(adv);
+ val = linkmode_to_mii_eee_cap2_t(tmp);
/* IEEE 802.3-2022 45.2.7.16 EEE advertisement 2
* (Register 7.62)
@@ -942,7 +941,7 @@ EXPORT_SYMBOL_GPL(genphy_c45_read_eee_abilities);
*/
int genphy_c45_an_config_eee_aneg(struct phy_device *phydev)
{
- if (!phydev->eee_enabled) {
+ if (!phydev->eee_cfg.eee_enabled) {
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
return genphy_c45_write_eee_adv(phydev, adv);
@@ -950,6 +949,7 @@ int genphy_c45_an_config_eee_aneg(struct phy_device *phydev)
return genphy_c45_write_eee_adv(phydev, phydev->advertising_eee);
}
+EXPORT_SYMBOL_GPL(genphy_c45_an_config_eee_aneg);
/**
* genphy_c45_pma_baset1_read_abilities - read supported baset1 link modes from PMA
@@ -1521,20 +1521,17 @@ EXPORT_SYMBOL(genphy_c45_eee_is_active);
int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
struct ethtool_keee *data)
{
- __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
- __ETHTOOL_DECLARE_LINK_MODE_MASK(lp) = {};
bool is_enabled;
int ret;
- ret = genphy_c45_eee_is_active(phydev, adv, lp, &is_enabled);
+ ret = genphy_c45_eee_is_active(phydev, data->advertised,
+ data->lp_advertised, &is_enabled);
if (ret < 0)
return ret;
data->eee_enabled = is_enabled;
- data->eee_active = ret;
+ data->eee_active = phydev->eee_active;
linkmode_copy(data->supported, phydev->supported_eee);
- linkmode_copy(data->advertised, adv);
- linkmode_copy(data->lp_advertised, lp);
return 0;
}
@@ -1568,15 +1565,12 @@ int genphy_c45_ethtool_set_eee(struct phy_device *phydev,
phydev_warn(phydev, "At least some EEE link modes are not supported.\n");
return -EINVAL;
}
- } else {
- adv = phydev->supported_eee;
+ linkmode_copy(phydev->advertising_eee, adv);
+ } else if (linkmode_empty(phydev->advertising_eee)) {
+ phy_advertise_eee_all(phydev);
}
-
- linkmode_copy(phydev->advertising_eee, adv);
}
- phydev->eee_enabled = data->eee_enabled;
-
ret = genphy_c45_an_config_eee_aneg(phydev);
if (ret > 0) {
ret = phy_restart_aneg(phydev);
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 1f98b6a96c15..6bf3ec985f3d 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -388,28 +388,58 @@ void of_set_phy_supported(struct phy_device *phydev)
void of_set_phy_eee_broken(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
- u32 broken = 0;
+ unsigned long *modes = phydev->eee_broken_modes;
- if (!IS_ENABLED(CONFIG_OF_MDIO))
+ if (!IS_ENABLED(CONFIG_OF_MDIO) || !node)
return;
- if (!node)
- return;
+ linkmode_zero(modes);
if (of_property_read_bool(node, "eee-broken-100tx"))
- broken |= MDIO_EEE_100TX;
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, modes);
if (of_property_read_bool(node, "eee-broken-1000t"))
- broken |= MDIO_EEE_1000T;
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, modes);
if (of_property_read_bool(node, "eee-broken-10gt"))
- broken |= MDIO_EEE_10GT;
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, modes);
if (of_property_read_bool(node, "eee-broken-1000kx"))
- broken |= MDIO_EEE_1000KX;
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, modes);
if (of_property_read_bool(node, "eee-broken-10gkx4"))
- broken |= MDIO_EEE_10GKX4;
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, modes);
if (of_property_read_bool(node, "eee-broken-10gkr"))
- broken |= MDIO_EEE_10GKR;
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, modes);
+}
+
+/**
+ * of_set_phy_timing_role - Set the master/slave mode of the PHY
+ *
+ * @phydev: The phy_device struct
+ *
+ * Set master/slave configuration of the PHY based on the device tree.
+ */
+void of_set_phy_timing_role(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ const char *master;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
+ return;
+
+ if (!node)
+ return;
+
+ if (of_property_read_string(node, "timing-role", &master))
+ return;
- phydev->eee_broken_modes = broken;
+ if (strcmp(master, "forced-master") == 0)
+ phydev->master_slave_set = MASTER_SLAVE_CFG_MASTER_FORCE;
+ else if (strcmp(master, "forced-slave") == 0)
+ phydev->master_slave_set = MASTER_SLAVE_CFG_SLAVE_FORCE;
+ else if (strcmp(master, "preferred-master") == 0)
+ phydev->master_slave_set = MASTER_SLAVE_CFG_MASTER_PREFERRED;
+ else if (strcmp(master, "preferred-slave") == 0)
+ phydev->master_slave_set = MASTER_SLAVE_CFG_SLAVE_PREFERRED;
+ else
+ phydev_warn(phydev, "Unknown master-slave mode %s\n", master);
}
/**
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 4f3e742907cb..0d20b534122b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -990,14 +990,14 @@ static int phy_check_link_status(struct phy_device *phydev)
phydev->state = PHY_RUNNING;
err = genphy_c45_eee_is_active(phydev,
NULL, NULL, NULL);
- if (err <= 0)
- phydev->enable_tx_lpi = false;
- else
- phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled;
+ phydev->eee_active = err > 0;
+ phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled &&
+ phydev->eee_active;
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
+ phydev->eee_active = false;
phydev->enable_tx_lpi = false;
phy_link_down(phydev);
}
@@ -1672,7 +1672,7 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
* phy_ethtool_set_eee_noneg - Adjusts MAC LPI configuration without PHY
* renegotiation
* @phydev: pointer to the target PHY device structure
- * @data: pointer to the ethtool_keee structure containing the new EEE settings
+ * @old_cfg: pointer to the eee_config structure containing the old EEE settings
*
* This function updates the Energy Efficient Ethernet (EEE) configuration
* for cases where only the MAC's Low Power Idle (LPI) configuration changes,
@@ -1683,18 +1683,23 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
* configuration.
*/
static void phy_ethtool_set_eee_noneg(struct phy_device *phydev,
- struct ethtool_keee *data)
+ const struct eee_config *old_cfg)
{
- if (phydev->eee_cfg.tx_lpi_enabled != data->tx_lpi_enabled ||
- phydev->eee_cfg.tx_lpi_timer != data->tx_lpi_timer) {
- eee_to_eeecfg(&phydev->eee_cfg, data);
- phydev->enable_tx_lpi = eeecfg_mac_can_tx_lpi(&phydev->eee_cfg);
- if (phydev->link) {
- phydev->link = false;
- phy_link_down(phydev);
- phydev->link = true;
- phy_link_up(phydev);
- }
+ bool enable_tx_lpi;
+
+ if (!phydev->link)
+ return;
+
+ enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled && phydev->eee_active;
+
+ if (phydev->enable_tx_lpi != enable_tx_lpi ||
+ phydev->eee_cfg.tx_lpi_timer != old_cfg->tx_lpi_timer) {
+ phydev->enable_tx_lpi = false;
+ phydev->link = false;
+ phy_link_down(phydev);
+ phydev->enable_tx_lpi = enable_tx_lpi;
+ phydev->link = true;
+ phy_link_up(phydev);
}
}
@@ -1707,18 +1712,23 @@ static void phy_ethtool_set_eee_noneg(struct phy_device *phydev,
*/
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data)
{
+ struct eee_config old_cfg;
int ret;
if (!phydev->drv)
return -EIO;
mutex_lock(&phydev->lock);
+
+ old_cfg = phydev->eee_cfg;
+ eee_to_eeecfg(&phydev->eee_cfg, data);
+
ret = genphy_c45_ethtool_set_eee(phydev, data);
- if (ret >= 0) {
- if (ret == 0)
- phy_ethtool_set_eee_noneg(phydev, data);
- eee_to_eeecfg(&phydev->eee_cfg, data);
- }
+ if (ret == 0)
+ phy_ethtool_set_eee_noneg(phydev, &old_cfg);
+ else if (ret < 0)
+ phydev->eee_cfg = old_cfg;
+
mutex_unlock(&phydev->lock);
return ret < 0 ? ret : 0;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 499797646580..b26bb33cd1d4 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2240,29 +2240,6 @@ static int genphy_c37_config_advert(struct phy_device *phydev)
}
/**
- * genphy_config_eee_advert - disable unwanted eee mode advertisement
- * @phydev: target phy_device struct
- *
- * Description: Writes MDIO_AN_EEE_ADV after disabling unsupported energy
- * efficent ethernet modes. Returns 0 if the PHY's advertisement hasn't
- * changed, and 1 if it has changed.
- */
-int genphy_config_eee_advert(struct phy_device *phydev)
-{
- int err;
-
- /* Nothing to disable */
- if (!phydev->eee_broken_modes)
- return 0;
-
- err = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV,
- phydev->eee_broken_modes, 0);
- /* If the call failed, we assume that EEE is not supported */
- return err < 0 ? 0 : err;
-}
-EXPORT_SYMBOL(genphy_config_eee_advert);
-
-/**
* genphy_setup_forced - configures/forces speed/duplex from @phydev
* @phydev: target phy_device struct
*
@@ -3358,11 +3335,17 @@ static int of_phy_led(struct phy_device *phydev,
if (index > U8_MAX)
return -EINVAL;
+ if (of_property_read_bool(led, "active-high"))
+ set_bit(PHY_LED_ACTIVE_HIGH, &modes);
if (of_property_read_bool(led, "active-low"))
set_bit(PHY_LED_ACTIVE_LOW, &modes);
if (of_property_read_bool(led, "inactive-high-impedance"))
set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes);
+ if (WARN_ON(modes & BIT(PHY_LED_ACTIVE_LOW) &&
+ modes & BIT(PHY_LED_ACTIVE_HIGH)))
+ return -EINVAL;
+
if (modes) {
/* Return error if asked to set polarity modes but not supported */
if (!phydev->drv->led_polarity_set)
@@ -3421,6 +3404,16 @@ static int of_phy_leds(struct phy_device *phydev)
if (!leds)
return 0;
+ /* Check if the PHY driver have at least an OP to
+ * set the LEDs.
+ */
+ if (!(phydev->drv->led_brightness_set ||
+ phydev->drv->led_blink_set ||
+ phydev->drv->led_hw_control_set)) {
+ phydev_dbg(phydev, "ignoring leds node defined with no PHY driver support\n");
+ goto exit;
+ }
+
for_each_available_child_of_node_scoped(leds, led) {
err = of_phy_led(phydev, led);
if (err) {
@@ -3430,6 +3423,7 @@ static int of_phy_leds(struct phy_device *phydev)
}
}
+exit:
of_node_put(leds);
return 0;
}
@@ -3595,12 +3589,12 @@ static int phy_probe(struct device *dev)
/* There is no "enabled" flag. If PHY is advertising, assume it is
* kind of enabled.
*/
- phydev->eee_enabled = !linkmode_empty(phydev->advertising_eee);
+ phydev->eee_cfg.eee_enabled = !linkmode_empty(phydev->advertising_eee);
/* Some PHYs may advertise, by default, not support EEE modes. So,
* we need to clean them.
*/
- if (phydev->eee_enabled)
+ if (phydev->eee_cfg.eee_enabled)
linkmode_and(phydev->advertising_eee, phydev->supported_eee,
phydev->advertising_eee);
@@ -3609,6 +3603,9 @@ static int phy_probe(struct device *dev)
*/
of_set_phy_eee_broken(phydev);
+ /* Get master/slave strap overrides */
+ of_set_phy_timing_role(phydev);
+
/* The Pause Frame bits indicate that the PHY can support passing
* pause frames. During autonegotiation, the PHYs will determine if
* they should allow pause frames to pass. The MAC driver should then
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 4309317de3d1..30a654e98352 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -78,8 +78,7 @@ struct phylink {
unsigned int pcs_neg_mode;
unsigned int pcs_state;
- bool mac_link_dropped;
- bool using_mac_select_pcs;
+ bool link_failed;
struct sfp_bus *sfp_bus;
bool sfp_may_have_phy;
@@ -599,15 +598,8 @@ static unsigned long phylink_get_capabilities(phy_interface_t interface,
* max speed at full duplex.
*/
if (mac_capabilities &
- phylink_cap_from_speed_duplex(max_speed, DUPLEX_FULL)) {
- /* Although a duplex-matching phy might exist, we
- * conservatively remove these modes because the MAC
- * will not be aware of the half-duplex nature of the
- * link.
- */
+ phylink_cap_from_speed_duplex(max_speed, DUPLEX_FULL))
matched_caps = GENMASK(__fls(caps), __fls(MAC_10HD));
- matched_caps &= ~(MAC_1000HD | MAC_100HD | MAC_10HD);
- }
break;
}
case RATE_MATCH_CRS:
@@ -656,17 +648,15 @@ static int phylink_validate_mac_and_pcs(struct phylink *pl,
unsigned long *supported,
struct phylink_link_state *state)
{
+ struct phylink_pcs *pcs = NULL;
unsigned long capabilities;
- struct phylink_pcs *pcs;
int ret;
/* Get the PCS for this interface mode */
- if (pl->using_mac_select_pcs) {
+ if (pl->mac_ops->mac_select_pcs) {
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
if (IS_ERR(pcs))
return PTR_ERR(pcs);
- } else {
- pcs = pl->pcs;
}
if (pcs) {
@@ -774,8 +764,8 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
static int phylink_parse_fixedlink(struct phylink *pl,
const struct fwnode_handle *fwnode)
{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
struct fwnode_handle *fixed_node;
- bool pause, asym_pause, autoneg;
const struct phy_setting *s;
struct gpio_desc *desc;
u32 speed;
@@ -848,22 +838,15 @@ static int phylink_parse_fixedlink(struct phylink *pl,
linkmode_copy(pl->link_config.advertising, pl->supported);
phylink_validate(pl, pl->supported, &pl->link_config);
- pause = phylink_test(pl->supported, Pause);
- asym_pause = phylink_test(pl->supported, Asym_Pause);
- autoneg = phylink_test(pl->supported, Autoneg);
s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
pl->supported, true);
- linkmode_zero(pl->supported);
- phylink_set(pl->supported, MII);
-
- if (pause)
- phylink_set(pl->supported, Pause);
- if (asym_pause)
- phylink_set(pl->supported, Asym_Pause);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mask);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mask);
+ linkmode_and(pl->supported, pl->supported, mask);
- if (autoneg)
- phylink_set(pl->supported, Autoneg);
+ phylink_set(pl->supported, MII);
if (s) {
__set_bit(s->bit, pl->supported);
@@ -1182,7 +1165,7 @@ static void phylink_major_config(struct phylink *pl, bool restart,
state->interface,
state->advertising);
- if (pl->using_mac_select_pcs) {
+ if (pl->mac_ops->mac_select_pcs) {
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
if (IS_ERR(pcs)) {
phylink_err(pl,
@@ -1191,7 +1174,7 @@ static void phylink_major_config(struct phylink *pl, bool restart,
return;
}
- pcs_changed = pcs && pl->pcs != pcs;
+ pcs_changed = pl->pcs != pcs;
}
phylink_pcs_poll_stop(pl);
@@ -1475,81 +1458,71 @@ static void phylink_resolve(struct work_struct *w)
cur_link_state = pl->old_link_state;
if (pl->phylink_disable_state) {
- pl->mac_link_dropped = false;
+ pl->link_failed = false;
link_state.link = false;
- } else if (pl->mac_link_dropped) {
+ } else if (pl->link_failed) {
link_state.link = false;
retrigger = true;
+ } else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
+ phylink_get_fixed_state(pl, &link_state);
+ mac_config = link_state.link;
+ } else if (pl->cur_link_an_mode == MLO_AN_PHY) {
+ link_state = pl->phy_state;
+ mac_config = link_state.link;
} else {
- switch (pl->cur_link_an_mode) {
- case MLO_AN_PHY:
- link_state = pl->phy_state;
- phylink_apply_manual_flow(pl, &link_state);
- mac_config = link_state.link;
- break;
+ phylink_mac_pcs_get_state(pl, &link_state);
- case MLO_AN_FIXED:
- phylink_get_fixed_state(pl, &link_state);
- mac_config = link_state.link;
- break;
+ /* The PCS may have a latching link-fail indicator. If the link
+ * was up, bring the link down and re-trigger the resolve.
+ * Otherwise, re-read the PCS state to get the current status
+ * of the link.
+ */
+ if (!link_state.link) {
+ if (cur_link_state)
+ retrigger = true;
+ else
+ phylink_mac_pcs_get_state(pl, &link_state);
+ }
- case MLO_AN_INBAND:
- phylink_mac_pcs_get_state(pl, &link_state);
+ /* If we have a phy, the "up" state is the union of both the
+ * PHY and the MAC
+ */
+ if (pl->phydev)
+ link_state.link &= pl->phy_state.link;
- /* The PCS may have a latching link-fail indicator.
- * If the link was up, bring the link down and
- * re-trigger the resolve. Otherwise, re-read the
- * PCS state to get the current status of the link.
+ /* Only update if the PHY link is up */
+ if (pl->phydev && pl->phy_state.link) {
+ /* If the interface has changed, force a link down
+ * event if the link isn't already down, and re-resolve.
*/
- if (!link_state.link) {
- if (cur_link_state)
- retrigger = true;
- else
- phylink_mac_pcs_get_state(pl,
- &link_state);
+ if (link_state.interface != pl->phy_state.interface) {
+ retrigger = true;
+ link_state.link = false;
}
- /* If we have a phy, the "up" state is the union of
- * both the PHY and the MAC
+ link_state.interface = pl->phy_state.interface;
+
+ /* If we are doing rate matching, then the link
+ * speed/duplex comes from the PHY
*/
- if (pl->phydev)
- link_state.link &= pl->phy_state.link;
-
- /* Only update if the PHY link is up */
- if (pl->phydev && pl->phy_state.link) {
- /* If the interface has changed, force a
- * link down event if the link isn't already
- * down, and re-resolve.
- */
- if (link_state.interface !=
- pl->phy_state.interface) {
- retrigger = true;
- link_state.link = false;
- }
- link_state.interface = pl->phy_state.interface;
-
- /* If we are doing rate matching, then the
- * link speed/duplex comes from the PHY
- */
- if (pl->phy_state.rate_matching) {
- link_state.rate_matching =
- pl->phy_state.rate_matching;
- link_state.speed = pl->phy_state.speed;
- link_state.duplex =
- pl->phy_state.duplex;
- }
-
- /* If we have a PHY, we need to update with
- * the PHY flow control bits.
- */
- link_state.pause = pl->phy_state.pause;
- mac_config = true;
+ if (pl->phy_state.rate_matching) {
+ link_state.rate_matching =
+ pl->phy_state.rate_matching;
+ link_state.speed = pl->phy_state.speed;
+ link_state.duplex = pl->phy_state.duplex;
}
- phylink_apply_manual_flow(pl, &link_state);
- break;
+
+ /* If we have a PHY, we need to update with the PHY
+ * flow control bits.
+ */
+ link_state.pause = pl->phy_state.pause;
+ mac_config = true;
}
}
+ if (pl->cur_link_an_mode != MLO_AN_FIXED)
+ phylink_apply_manual_flow(pl, &link_state);
+
if (mac_config) {
if (link_state.interface != pl->link_config.interface) {
/* The interface has changed, force the link down and
@@ -1572,7 +1545,7 @@ static void phylink_resolve(struct work_struct *w)
phylink_link_up(pl, link_state);
}
if (!link_state.link && retrigger) {
- pl->mac_link_dropped = false;
+ pl->link_failed = false;
queue_work(system_power_efficient_wq, &pl->resolve);
}
mutex_unlock(&pl->state_mutex);
@@ -1698,7 +1671,6 @@ struct phylink *phylink_create(struct phylink_config *config,
phy_interface_t iface,
const struct phylink_mac_ops *mac_ops)
{
- bool using_mac_select_pcs = false;
struct phylink *pl;
int ret;
@@ -1709,11 +1681,6 @@ struct phylink *phylink_create(struct phylink_config *config,
return ERR_PTR(-EINVAL);
}
- if (mac_ops->mac_select_pcs &&
- mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) !=
- ERR_PTR(-EOPNOTSUPP))
- using_mac_select_pcs = true;
-
pl = kzalloc(sizeof(*pl), GFP_KERNEL);
if (!pl)
return ERR_PTR(-ENOMEM);
@@ -1732,7 +1699,6 @@ struct phylink *phylink_create(struct phylink_config *config,
return ERR_PTR(-EINVAL);
}
- pl->using_mac_select_pcs = using_mac_select_pcs;
pl->phy_state.interface = iface;
pl->link_interface = iface;
if (iface == PHY_INTERFACE_MODE_MOCA)
@@ -1835,6 +1801,8 @@ static void phylink_phy_change(struct phy_device *phydev, bool up)
pl->phy_state.pause |= MLO_PAUSE_RX;
pl->phy_state.interface = phydev->interface;
pl->phy_state.link = up;
+ if (!up)
+ pl->link_failed = true;
mutex_unlock(&pl->state_mutex);
phylink_run_resolve(pl);
@@ -2158,7 +2126,7 @@ EXPORT_SYMBOL_GPL(phylink_disconnect_phy);
static void phylink_link_changed(struct phylink *pl, bool up, const char *what)
{
if (!up)
- pl->mac_link_dropped = true;
+ pl->link_failed = true;
phylink_run_resolve(pl);
phylink_dbg(pl, "%s link %s\n", what, up ? "up" : "down");
}
@@ -2432,6 +2400,32 @@ int phylink_ethtool_set_wol(struct phylink *pl, struct ethtool_wolinfo *wol)
}
EXPORT_SYMBOL_GPL(phylink_ethtool_set_wol);
+static phy_interface_t phylink_sfp_select_interface(struct phylink *pl,
+ const unsigned long *link_modes)
+{
+ phy_interface_t interface;
+
+ interface = sfp_select_interface(pl->sfp_bus, link_modes);
+ if (interface == PHY_INTERFACE_MODE_NA) {
+ phylink_err(pl,
+ "selection of interface failed, advertisement %*pb\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ link_modes);
+ return interface;
+ }
+
+ if (!test_bit(interface, pl->config->supported_interfaces)) {
+ phylink_err(pl,
+ "selection of interface failed, SFP selected %s (%u) but MAC supports %*pbl\n",
+ phy_modes(interface), interface,
+ (int)PHY_INTERFACE_MODE_MAX,
+ pl->config->supported_interfaces);
+ return PHY_INTERFACE_MODE_NA;
+ }
+
+ return interface;
+}
+
static void phylink_merge_link_mode(unsigned long *dst, const unsigned long *b)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask);
@@ -2614,15 +2608,10 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
* link can be configured correctly.
*/
if (pl->sfp_bus) {
- config.interface = sfp_select_interface(pl->sfp_bus,
+ config.interface = phylink_sfp_select_interface(pl,
config.advertising);
- if (config.interface == PHY_INTERFACE_MODE_NA) {
- phylink_err(pl,
- "selection of interface failed, advertisement %*pb\n",
- __ETHTOOL_LINK_MODE_MASK_NBITS,
- config.advertising);
+ if (config.interface == PHY_INTERFACE_MODE_NA)
return -EINVAL;
- }
/* Revalidate with the selected interface */
linkmode_copy(support, pl->supported);
@@ -2792,7 +2781,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
* link will cycle.
*/
if (manual_changed) {
- pl->mac_link_dropped = true;
+ pl->link_failed = true;
phylink_run_resolve(pl);
}
@@ -3227,10 +3216,8 @@ static void phylink_sfp_set_config(struct phylink *pl, u8 mode,
static int phylink_sfp_config_phy(struct phylink *pl, u8 mode,
struct phy_device *phy)
{
- __ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
struct phylink_link_state config;
- phy_interface_t iface;
int ret;
linkmode_copy(support, phy->supported);
@@ -3251,24 +3238,21 @@ static int phylink_sfp_config_phy(struct phylink *pl, u8 mode,
return ret;
}
- iface = sfp_select_interface(pl->sfp_bus, config.advertising);
- if (iface == PHY_INTERFACE_MODE_NA) {
- phylink_err(pl,
- "selection of interface failed, advertisement %*pb\n",
- __ETHTOOL_LINK_MODE_MASK_NBITS, config.advertising);
+ config.interface = phylink_sfp_select_interface(pl, config.advertising);
+ if (config.interface == PHY_INTERFACE_MODE_NA)
return -EINVAL;
- }
- config.interface = iface;
- linkmode_copy(support1, support);
- ret = phylink_validate(pl, support1, &config);
- if (ret) {
- phylink_err(pl,
- "validation of %s/%s with support %*pb failed: %pe\n",
- phylink_an_mode_str(mode),
- phy_modes(config.interface),
- __ETHTOOL_LINK_MODE_MASK_NBITS, support,
- ERR_PTR(ret));
+ /* Attach the PHY so that the PHY is present when we do the major
+ * configuration step.
+ */
+ ret = phylink_attach_phy(pl, phy, config.interface);
+ if (ret < 0)
+ return ret;
+
+ /* This will validate the configuration for us. */
+ ret = phylink_bringup_phy(pl, phy, config.interface);
+ if (ret < 0) {
+ phy_detach(phy);
return ret;
}
@@ -3426,9 +3410,7 @@ static bool phylink_phy_no_inband(struct phy_device *phy)
static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
{
struct phylink *pl = upstream;
- phy_interface_t interface;
u8 mode;
- int ret;
/*
* This is the new way of dealing with flow control for PHYs,
@@ -3449,20 +3431,7 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
pl->config->supported_interfaces);
/* Do the initial configuration */
- ret = phylink_sfp_config_phy(pl, mode, phy);
- if (ret < 0)
- return ret;
-
- interface = pl->link_config.interface;
- ret = phylink_attach_phy(pl, phy, interface);
- if (ret < 0)
- return ret;
-
- ret = phylink_bringup_phy(pl, phy, interface);
- if (ret)
- phy_detach(phy);
-
- return ret;
+ return phylink_sfp_config_phy(pl, mode, phy);
}
static void phylink_sfp_disconnect_phy(void *upstream,
diff --git a/drivers/net/phy/qcom/qca83xx.c b/drivers/net/phy/qcom/qca83xx.c
index a05d0df6fa16..7a5039920b9f 100644
--- a/drivers/net/phy/qcom/qca83xx.c
+++ b/drivers/net/phy/qcom/qca83xx.c
@@ -42,10 +42,8 @@ static void qca83xx_get_strings(struct phy_device *phydev, u8 *data)
{
int i;
- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) {
- strscpy(data + i * ETH_GSTRING_LEN,
- qca83xx_hw_stats[i].string, ETH_GSTRING_LEN);
- }
+ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++)
+ ethtool_puts(&data, qca83xx_hw_stats[i].string);
}
static u64 qca83xx_get_stat(struct phy_device *phydev, int i)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 166f6a728373..f65d7f1f348e 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -80,18 +80,22 @@
#define RTL822X_VND2_GANLPAR 0xa414
-#define RTL822X_VND2_PHYSR 0xa434
-
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
#define RTL9000A_GINMR 0x14
#define RTL9000A_GINMR_LINK_STATUS BIT(4)
-#define RTLGEN_SPEED_MASK 0x0630
+#define RTL_VND2_PHYSR 0xa434
+#define RTL_VND2_PHYSR_DUPLEX BIT(3)
+#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4)
+#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9)
+#define RTL_VND2_PHYSR_MASTER BIT(11)
+#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH)
#define RTL_GENERIC_PHYID 0x001cc800
#define RTL_8211FVD_PHYID 0x001cc878
+#define RTL_8221B 0x001cc840
#define RTL_8221B_VB_CG 0x001cc849
#define RTL_8221B_VN_CG 0x001cc84a
#define RTL_8251B 0x001cc862
@@ -660,9 +664,18 @@ static int rtl8366rb_config_init(struct phy_device *phydev)
}
/* get actual speed to cover the downshift case */
-static void rtlgen_decode_speed(struct phy_device *phydev, int val)
+static void rtlgen_decode_physr(struct phy_device *phydev, int val)
{
- switch (val & RTLGEN_SPEED_MASK) {
+ /* bit 3
+ * 0: Half Duplex
+ * 1: Full Duplex
+ */
+ if (val & RTL_VND2_PHYSR_DUPLEX)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+
+ switch (val & RTL_VND2_PHYSR_SPEED_MASK) {
case 0x0000:
phydev->speed = SPEED_10;
break;
@@ -684,6 +697,19 @@ static void rtlgen_decode_speed(struct phy_device *phydev, int val)
default:
break;
}
+
+ /* bit 11
+ * 0: Slave Mode
+ * 1: Master Mode
+ */
+ if (phydev->speed >= 1000) {
+ if (val & RTL_VND2_PHYSR_MASTER)
+ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
+ else
+ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
+ } else {
+ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED;
+ }
}
static int rtlgen_read_status(struct phy_device *phydev)
@@ -701,7 +727,7 @@ static int rtlgen_read_status(struct phy_device *phydev)
if (val < 0)
return val;
- rtlgen_decode_speed(phydev, val);
+ rtlgen_decode_physr(phydev, val);
return 0;
}
@@ -924,17 +950,25 @@ static void rtl822xb_update_interface(struct phy_device *phydev)
static int rtl822x_read_status(struct phy_device *phydev)
{
- if (phydev->autoneg == AUTONEG_ENABLE) {
- int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
+ int lpadv, ret;
- if (lpadv < 0)
- return lpadv;
+ ret = rtlgen_read_status(phydev);
+ if (ret < 0)
+ return ret;
- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising,
- lpadv);
+ if (phydev->autoneg == AUTONEG_DISABLE ||
+ !phydev->autoneg_complete) {
+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
+ return 0;
}
- return rtlgen_read_status(phydev);
+ lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
+ if (lpadv < 0)
+ return lpadv;
+
+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv);
+
+ return 0;
}
static int rtl822xb_read_status(struct phy_device *phydev)
@@ -993,6 +1027,10 @@ static int rtl822x_c45_read_status(struct phy_device *phydev)
if (ret < 0)
return ret;
+ if (phydev->autoneg == AUTONEG_DISABLE ||
+ !genphy_c45_aneg_done(phydev))
+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
+
/* Vendor register as C45 has no standardized support for 1000BaseT */
if (phydev->autoneg == AUTONEG_ENABLE) {
val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
@@ -1007,11 +1045,11 @@ static int rtl822x_c45_read_status(struct phy_device *phydev)
return 0;
/* Read actual speed from vendor register. */
- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_PHYSR);
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR);
if (val < 0)
return val;
- rtlgen_decode_speed(phydev, val);
+ rtlgen_decode_physr(phydev, val);
return 0;
}
@@ -1040,6 +1078,23 @@ static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
return val >= 0 && val & MDIO_PMA_SPEED_2_5G;
}
+/* On internal PHY's MMD reads over C22 always return 0.
+ * Check a MMD register which is known to be non-zero.
+ */
+static bool rtlgen_supports_mmd(struct phy_device *phydev)
+{
+ int val;
+
+ phy_lock_mdio_bus(phydev);
+ __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS);
+ __phy_write(phydev, MII_MMD_DATA, MDIO_PCS_EEE_ABLE);
+ __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS | MII_MMD_CTRL_NOINCR);
+ val = __phy_read(phydev, MII_MMD_DATA);
+ phy_unlock_mdio_bus(phydev);
+
+ return val > 0;
+}
+
static int rtlgen_match_phy_device(struct phy_device *phydev)
{
return phydev->phy_id == RTL_GENERIC_PHYID &&
@@ -1049,7 +1104,8 @@ static int rtlgen_match_phy_device(struct phy_device *phydev)
static int rtl8226_match_phy_device(struct phy_device *phydev)
{
return phydev->phy_id == RTL_GENERIC_PHYID &&
- rtlgen_supports_2_5gbps(phydev);
+ rtlgen_supports_2_5gbps(phydev) &&
+ rtlgen_supports_mmd(phydev);
}
static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
@@ -1061,6 +1117,11 @@ static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id,
return !is_c45 && (id == phydev->phy_id);
}
+static int rtl8221b_match_phy_device(struct phy_device *phydev)
+{
+ return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev);
+}
+
static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev)
{
return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
@@ -1081,9 +1142,22 @@ static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev)
return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
}
-static int rtl8251b_c22_match_phy_device(struct phy_device *phydev)
+static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev)
{
- return rtlgen_is_c45_match(phydev, RTL_8251B, false);
+ if (phydev->is_c45)
+ return false;
+
+ switch (phydev->phy_id) {
+ case RTL_GENERIC_PHYID:
+ case RTL_8221B:
+ case RTL_8251B:
+ case 0x001cc841:
+ break;
+ default:
+ return false;
+ }
+
+ return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev);
}
static int rtl8251b_c45_match_phy_device(struct phy_device *phydev)
@@ -1345,10 +1419,8 @@ static struct phy_driver realtek_drvs[] = {
.resume = rtlgen_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
- .read_mmd = rtl822x_read_mmd,
- .write_mmd = rtl822x_write_mmd,
}, {
- PHY_ID_MATCH_EXACT(0x001cc840),
+ .match_phy_device = rtl8221b_match_phy_device,
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
@@ -1359,8 +1431,6 @@ static struct phy_driver realtek_drvs[] = {
.resume = rtlgen_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
- .read_mmd = rtl822x_read_mmd,
- .write_mmd = rtl822x_write_mmd,
}, {
PHY_ID_MATCH_EXACT(0x001cc838),
.name = "RTL8226-CG 2.5Gbps PHY",
@@ -1438,8 +1508,9 @@ static struct phy_driver realtek_drvs[] = {
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
- .match_phy_device = rtl8251b_c22_match_phy_device,
- .name = "RTL8126A-internal 5Gbps PHY",
+ .match_phy_device = rtl_internal_nbaset_match_phy_device,
+ .name = "Realtek Internal NBASE-T PHY",
+ .flags = PHY_IS_INTERNAL,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index a5684ef5884b..7dbcbf0a4ee2 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -466,7 +466,8 @@ static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
static const struct sfp_quirk sfp_quirks[] = {
// Alcatel Lucent G-010S-P can operate at 2500base-X, but incorrectly
// report 2500MBd NRZ in their EEPROM
- SFP_QUIRK_M("ALCATELLUCENT", "G010SP", sfp_quirk_2500basex),
+ SFP_QUIRK("ALCATELLUCENT", "G010SP", sfp_quirk_2500basex,
+ sfp_fixup_ignore_tx_fault),
// Alcatel Lucent G-010S-A can operate at 2500base-X, but report 3.2GBd
// NRZ in their EEPROM
@@ -3146,7 +3147,7 @@ static void sfp_shutdown(struct platform_device *pdev)
static struct platform_driver sfp_driver = {
.probe = sfp_probe,
- .remove_new = sfp_remove,
+ .remove = sfp_remove,
.shutdown = sfp_shutdown,
.driver = {
.name = "sfp",
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 150aea7c9c36..e1853599d9ba 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -627,12 +627,13 @@ int smsc_phy_probe(struct phy_device *phydev)
phydev->priv = priv;
/* Make clk optional to keep DTB backward compatibility. */
- refclk = devm_clk_get_optional_enabled(dev, NULL);
+ refclk = devm_clk_get_optional_enabled_with_rate(dev, NULL,
+ 50 * 1000 * 1000);
if (IS_ERR(refclk))
return dev_err_probe(dev, PTR_ERR(refclk),
"Failed to request clock\n");
- return clk_set_rate(refclk, 50 * 1000 * 1000);
+ return 0;
}
EXPORT_SYMBOL_GPL(smsc_phy_probe);
diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index 18191d5a8bd4..a1b27b69f010 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -1946,8 +1946,7 @@ static void team_netpoll_cleanup(struct net_device *dev)
mutex_unlock(&team->lock);
}
-static int team_netpoll_setup(struct net_device *dev,
- struct netpoll_info *npifo)
+static int team_netpoll_setup(struct net_device *dev)
{
struct team *team = netdev_priv(dev);
struct team_port *port;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 9a0f6eb32016..d7a865ef370b 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -71,7 +71,7 @@
#include <linux/bpf_trace.h>
#include <linux/mutex.h>
#include <linux/ieee802154.h>
-#include <linux/if_ltalk.h>
+#include <uapi/linux/if_ltalk.h>
#include <uapi/linux/if_fddi.h>
#include <uapi/linux/if_hippi.h>
#include <uapi/linux/if_fc.h>
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 8adf77e3557e..531b1b6a37d1 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -1652,13 +1652,13 @@ static int lan78xx_set_wol(struct net_device *netdev,
struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
int ret;
+ if (wol->wolopts & ~WAKE_ALL)
+ return -EINVAL;
+
ret = usb_autopm_get_interface(dev->intf);
if (ret < 0)
return ret;
- if (wol->wolopts & ~WAKE_ALL)
- return -EINVAL;
-
pdata->wol = wol->wolopts;
device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
@@ -2380,6 +2380,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
if (dev->chipid == ID_REV_CHIP_ID_7801_) {
if (phy_is_pseudo_fixed_link(phydev)) {
fixed_phy_unregister(phydev);
+ phy_device_free(phydev);
} else {
phy_unregister_fixup_for_uid(PHY_KSZ9031RNX,
0xfffffff0);
@@ -4246,8 +4247,10 @@ static void lan78xx_disconnect(struct usb_interface *intf)
phy_disconnect(net->phydev);
- if (phy_is_pseudo_fixed_link(phydev))
+ if (phy_is_pseudo_fixed_link(phydev)) {
fixed_phy_unregister(phydev);
+ phy_device_free(phydev);
+ }
usb_scuttle_anchored_urbs(&dev->deferred);
@@ -4414,29 +4417,30 @@ static int lan78xx_probe(struct usb_interface *intf,
period = ep_intr->desc.bInterval;
maxp = usb_maxpacket(dev->udev, dev->pipe_intr);
- buf = kmalloc(maxp, GFP_KERNEL);
- if (!buf) {
+
+ dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urb_intr) {
ret = -ENOMEM;
goto out5;
}
- dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
- if (!dev->urb_intr) {
+ buf = kmalloc(maxp, GFP_KERNEL);
+ if (!buf) {
ret = -ENOMEM;
- goto out6;
- } else {
- usb_fill_int_urb(dev->urb_intr, dev->udev,
- dev->pipe_intr, buf, maxp,
- intr_complete, dev, period);
- dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
+ goto free_urbs;
}
+ usb_fill_int_urb(dev->urb_intr, dev->udev,
+ dev->pipe_intr, buf, maxp,
+ intr_complete, dev, period);
+ dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
+
dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out);
/* Reject broken descriptors. */
if (dev->maxpacket == 0) {
ret = -ENODEV;
- goto out6;
+ goto free_urbs;
}
/* driver requires remote-wakeup capability during autosuspend. */
@@ -4444,7 +4448,7 @@ static int lan78xx_probe(struct usb_interface *intf,
ret = lan78xx_phy_init(dev);
if (ret < 0)
- goto out7;
+ goto free_urbs;
ret = register_netdev(netdev);
if (ret != 0) {
@@ -4466,10 +4470,8 @@ static int lan78xx_probe(struct usb_interface *intf,
out8:
phy_disconnect(netdev->phydev);
-out7:
+free_urbs:
usb_free_urb(dev->urb_intr);
-out6:
- kfree(buf);
out5:
lan78xx_unbind(dev, intf);
out4:
diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
index cb7d2f798fb4..091bc2aca7e8 100644
--- a/drivers/net/usb/sr9700.c
+++ b/drivers/net/usb/sr9700.c
@@ -177,9 +177,9 @@ static int sr9700_get_eeprom(struct net_device *netdev,
static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
struct usbnet *dev = netdev_priv(netdev);
- __le16 res;
+ int err, res;
+ __le16 word;
int rc = 0;
- int err;
if (phy_id) {
netdev_dbg(netdev, "Only internal phy supported\n");
@@ -197,14 +197,14 @@ static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc)
if (value & NSR_LINKST)
rc = 1;
}
- err = sr_share_read_word(dev, 1, loc, &res);
+ err = sr_share_read_word(dev, 1, loc, &word);
if (err < 0)
return err;
if (rc == 1)
- res = le16_to_cpu(res) | BMSR_LSTATUS;
+ res = le16_to_cpu(word) | BMSR_LSTATUS;
else
- res = le16_to_cpu(res) & ~BMSR_LSTATUS;
+ res = le16_to_cpu(word) & ~BMSR_LSTATUS;
netdev_dbg(netdev, "sr_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
phy_id, loc, res);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 18148e068aa0..0d6d0d749d44 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1781,19 +1781,11 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
/*
* create and register peer first
*/
- if (data != NULL && data[VETH_INFO_PEER] != NULL) {
- struct nlattr *nla_peer;
+ if (data && data[VETH_INFO_PEER]) {
+ struct nlattr *nla_peer = data[VETH_INFO_PEER];
- nla_peer = data[VETH_INFO_PEER];
ifmp = nla_data(nla_peer);
- err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
- if (err < 0)
- return err;
-
- err = veth_validate(peer_tb, NULL, extack);
- if (err < 0)
- return err;
-
+ rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
tbp = peer_tb;
} else {
ifmp = NULL;
@@ -1809,9 +1801,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
}
net = rtnl_link_get_net(src_net, tbp);
- if (IS_ERR(net))
- return PTR_ERR(net);
-
peer = rtnl_create_link(net, ifname, name_assign_type,
&veth_link_ops, tbp, extack);
if (IS_ERR(peer)) {
@@ -1952,6 +1941,7 @@ static struct rtnl_link_ops veth_link_ops = {
.newlink = veth_newlink,
.dellink = veth_dellink,
.policy = veth_policy,
+ .peer_type = VETH_INFO_PEER,
.maxtype = VETH_INFO_MAX,
.get_link_net = veth_get_link_net,
.get_num_tx_queues = veth_get_num_queues,
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 792e9eadbfc3..64c87bb48a41 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -45,9 +45,6 @@ module_param(napi_tx, bool, 0644);
#define VIRTIO_XDP_TX BIT(0)
#define VIRTIO_XDP_REDIR BIT(1)
-#define VIRTIO_XDP_FLAG BIT(0)
-#define VIRTIO_ORPHAN_FLAG BIT(1)
-
/* RX packet size EWMA. The average packet size is used to determine the packet
* buffer size when refilling RX rings. As the entire RX ring may be refilled
* at once, the weight is chosen so that the EWMA will be insensitive to short-
@@ -86,6 +83,7 @@ struct virtnet_sq_free_stats {
u64 bytes;
u64 napi_packets;
u64 napi_bytes;
+ u64 xsk;
};
struct virtnet_sq_stats {
@@ -298,6 +296,10 @@ struct send_queue {
/* Record whether sq is in reset state. */
bool reset;
+
+ struct xsk_buff_pool *xsk_pool;
+
+ dma_addr_t xsk_hdr_dma_addr;
};
/* Internal representation of a receive virtqueue */
@@ -356,9 +358,6 @@ struct receive_queue {
struct xdp_rxq_info xsk_rxq_info;
struct xdp_buff **xsk_buffs;
-
- /* Do dma by self */
- bool do_dma;
};
/* This structure can contain rss message with maximum settings for indirection table and keysize
@@ -368,15 +367,16 @@ struct receive_queue {
* because table sizes may be differ according to the device configuration.
*/
#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
-#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128
struct virtio_net_ctrl_rss {
u32 hash_types;
u16 indirection_table_mask;
u16 unclassified_queue;
- u16 indirection_table[VIRTIO_NET_RSS_MAX_TABLE_LEN];
+ u16 hash_cfg_reserved; /* for HASH_CONFIG (see virtio_net_hash_config for details) */
u16 max_tx_vq;
u8 hash_key_length;
u8 key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
+
+ u16 *indirection_table;
};
/* Control VQ buffers: protected by the rtnl lock */
@@ -500,6 +500,8 @@ struct virtio_net_common_hdr {
};
};
+static struct virtio_net_common_hdr xsk_hdr;
+
static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp,
struct net_device *dev,
@@ -511,68 +513,127 @@ static struct sk_buff *virtnet_skb_append_frag(struct sk_buff *head_skb,
struct sk_buff *curr_skb,
struct page *page, void *buf,
int len, int truesize);
+static void virtnet_xsk_completed(struct send_queue *sq, int num);
-static bool is_xdp_frame(void *ptr)
+enum virtnet_xmit_type {
+ VIRTNET_XMIT_TYPE_SKB,
+ VIRTNET_XMIT_TYPE_SKB_ORPHAN,
+ VIRTNET_XMIT_TYPE_XDP,
+ VIRTNET_XMIT_TYPE_XSK,
+};
+
+static int rss_indirection_table_alloc(struct virtio_net_ctrl_rss *rss, u16 indir_table_size)
{
- return (unsigned long)ptr & VIRTIO_XDP_FLAG;
+ if (!indir_table_size) {
+ rss->indirection_table = NULL;
+ return 0;
+ }
+
+ rss->indirection_table = kmalloc_array(indir_table_size, sizeof(u16), GFP_KERNEL);
+ if (!rss->indirection_table)
+ return -ENOMEM;
+
+ return 0;
}
-static void *xdp_to_ptr(struct xdp_frame *ptr)
+static void rss_indirection_table_free(struct virtio_net_ctrl_rss *rss)
{
- return (void *)((unsigned long)ptr | VIRTIO_XDP_FLAG);
+ kfree(rss->indirection_table);
}
-static struct xdp_frame *ptr_to_xdp(void *ptr)
+/* We use the last two bits of the pointer to distinguish the xmit type. */
+#define VIRTNET_XMIT_TYPE_MASK (BIT(0) | BIT(1))
+
+#define VIRTIO_XSK_FLAG_OFFSET 2
+
+static enum virtnet_xmit_type virtnet_xmit_ptr_unpack(void **ptr)
+{
+ unsigned long p = (unsigned long)*ptr;
+
+ *ptr = (void *)(p & ~VIRTNET_XMIT_TYPE_MASK);
+
+ return p & VIRTNET_XMIT_TYPE_MASK;
+}
+
+static void *virtnet_xmit_ptr_pack(void *ptr, enum virtnet_xmit_type type)
{
- return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG);
+ return (void *)((unsigned long)ptr | type);
}
-static bool is_orphan_skb(void *ptr)
+static int virtnet_add_outbuf(struct send_queue *sq, int num, void *data,
+ enum virtnet_xmit_type type)
{
- return (unsigned long)ptr & VIRTIO_ORPHAN_FLAG;
+ return virtqueue_add_outbuf(sq->vq, sq->sg, num,
+ virtnet_xmit_ptr_pack(data, type),
+ GFP_ATOMIC);
}
-static void *skb_to_ptr(struct sk_buff *skb, bool orphan)
+static u32 virtnet_ptr_to_xsk_buff_len(void *ptr)
{
- return (void *)((unsigned long)skb | (orphan ? VIRTIO_ORPHAN_FLAG : 0));
+ return ((unsigned long)ptr) >> VIRTIO_XSK_FLAG_OFFSET;
}
-static struct sk_buff *ptr_to_skb(void *ptr)
+static void sg_fill_dma(struct scatterlist *sg, dma_addr_t addr, u32 len)
{
- return (struct sk_buff *)((unsigned long)ptr & ~VIRTIO_ORPHAN_FLAG);
+ sg_dma_address(sg) = addr;
+ sg_dma_len(sg) = len;
}
static void __free_old_xmit(struct send_queue *sq, struct netdev_queue *txq,
bool in_napi, struct virtnet_sq_free_stats *stats)
{
+ struct xdp_frame *frame;
+ struct sk_buff *skb;
unsigned int len;
void *ptr;
while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
- if (!is_xdp_frame(ptr)) {
- struct sk_buff *skb = ptr_to_skb(ptr);
+ switch (virtnet_xmit_ptr_unpack(&ptr)) {
+ case VIRTNET_XMIT_TYPE_SKB:
+ skb = ptr;
pr_debug("Sent skb %p\n", skb);
+ stats->napi_packets++;
+ stats->napi_bytes += skb->len;
+ napi_consume_skb(skb, in_napi);
+ break;
- if (is_orphan_skb(ptr)) {
- stats->packets++;
- stats->bytes += skb->len;
- } else {
- stats->napi_packets++;
- stats->napi_bytes += skb->len;
- }
+ case VIRTNET_XMIT_TYPE_SKB_ORPHAN:
+ skb = ptr;
+
+ stats->packets++;
+ stats->bytes += skb->len;
napi_consume_skb(skb, in_napi);
- } else {
- struct xdp_frame *frame = ptr_to_xdp(ptr);
+ break;
+
+ case VIRTNET_XMIT_TYPE_XDP:
+ frame = ptr;
stats->packets++;
stats->bytes += xdp_get_frame_len(frame);
xdp_return_frame(frame);
+ break;
+
+ case VIRTNET_XMIT_TYPE_XSK:
+ stats->bytes += virtnet_ptr_to_xsk_buff_len(ptr);
+ stats->xsk++;
+ break;
}
}
netdev_tx_completed_queue(txq, stats->napi_packets, stats->napi_bytes);
}
+static void virtnet_free_old_xmit(struct send_queue *sq,
+ struct netdev_queue *txq,
+ bool in_napi,
+ struct virtnet_sq_free_stats *stats)
+{
+ __free_old_xmit(sq, txq, in_napi, stats);
+
+ if (stats->xsk)
+ virtnet_xsk_completed(sq, stats->xsk);
+}
+
/* Converting between virtqueue no. and kernel tx/rx queue no.
* 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
*/
@@ -856,11 +917,14 @@ ok:
static void virtnet_rq_unmap(struct receive_queue *rq, void *buf, u32 len)
{
+ struct virtnet_info *vi = rq->vq->vdev->priv;
struct page *page = virt_to_head_page(buf);
struct virtnet_rq_dma *dma;
void *head;
int offset;
+ BUG_ON(vi->big_packets && !vi->mergeable_rx_bufs);
+
head = page_address(page);
dma = head;
@@ -885,10 +949,13 @@ static void virtnet_rq_unmap(struct receive_queue *rq, void *buf, u32 len)
static void *virtnet_rq_get_buf(struct receive_queue *rq, u32 *len, void **ctx)
{
+ struct virtnet_info *vi = rq->vq->vdev->priv;
void *buf;
+ BUG_ON(vi->big_packets && !vi->mergeable_rx_bufs);
+
buf = virtqueue_get_buf_ctx(rq->vq, len, ctx);
- if (buf && rq->do_dma)
+ if (buf)
virtnet_rq_unmap(rq, buf, *len);
return buf;
@@ -896,15 +963,13 @@ static void *virtnet_rq_get_buf(struct receive_queue *rq, u32 *len, void **ctx)
static void virtnet_rq_init_one_sg(struct receive_queue *rq, void *buf, u32 len)
{
+ struct virtnet_info *vi = rq->vq->vdev->priv;
struct virtnet_rq_dma *dma;
dma_addr_t addr;
u32 offset;
void *head;
- if (!rq->do_dma) {
- sg_init_one(rq->sg, buf, len);
- return;
- }
+ BUG_ON(vi->big_packets && !vi->mergeable_rx_bufs);
head = page_address(rq->alloc_frag.page);
@@ -915,60 +980,57 @@ static void virtnet_rq_init_one_sg(struct receive_queue *rq, void *buf, u32 len)
addr = dma->addr - sizeof(*dma) + offset;
sg_init_table(rq->sg, 1);
- rq->sg[0].dma_address = addr;
- rq->sg[0].length = len;
+ sg_fill_dma(rq->sg, addr, len);
}
static void *virtnet_rq_alloc(struct receive_queue *rq, u32 size, gfp_t gfp)
{
struct page_frag *alloc_frag = &rq->alloc_frag;
+ struct virtnet_info *vi = rq->vq->vdev->priv;
struct virtnet_rq_dma *dma;
void *buf, *head;
dma_addr_t addr;
- if (unlikely(!skb_page_frag_refill(size, alloc_frag, gfp)))
- return NULL;
+ BUG_ON(vi->big_packets && !vi->mergeable_rx_bufs);
head = page_address(alloc_frag->page);
- if (rq->do_dma) {
- dma = head;
-
- /* new pages */
- if (!alloc_frag->offset) {
- if (rq->last_dma) {
- /* Now, the new page is allocated, the last dma
- * will not be used. So the dma can be unmapped
- * if the ref is 0.
- */
- virtnet_rq_unmap(rq, rq->last_dma, 0);
- rq->last_dma = NULL;
- }
+ dma = head;
- dma->len = alloc_frag->size - sizeof(*dma);
+ /* new pages */
+ if (!alloc_frag->offset) {
+ if (rq->last_dma) {
+ /* Now, the new page is allocated, the last dma
+ * will not be used. So the dma can be unmapped
+ * if the ref is 0.
+ */
+ virtnet_rq_unmap(rq, rq->last_dma, 0);
+ rq->last_dma = NULL;
+ }
- addr = virtqueue_dma_map_single_attrs(rq->vq, dma + 1,
- dma->len, DMA_FROM_DEVICE, 0);
- if (virtqueue_dma_mapping_error(rq->vq, addr))
- return NULL;
+ dma->len = alloc_frag->size - sizeof(*dma);
- dma->addr = addr;
- dma->need_sync = virtqueue_dma_need_sync(rq->vq, addr);
+ addr = virtqueue_dma_map_single_attrs(rq->vq, dma + 1,
+ dma->len, DMA_FROM_DEVICE, 0);
+ if (virtqueue_dma_mapping_error(rq->vq, addr))
+ return NULL;
- /* Add a reference to dma to prevent the entire dma from
- * being released during error handling. This reference
- * will be freed after the pages are no longer used.
- */
- get_page(alloc_frag->page);
- dma->ref = 1;
- alloc_frag->offset = sizeof(*dma);
+ dma->addr = addr;
+ dma->need_sync = virtqueue_dma_need_sync(rq->vq, addr);
- rq->last_dma = dma;
- }
+ /* Add a reference to dma to prevent the entire dma from
+ * being released during error handling. This reference
+ * will be freed after the pages are no longer used.
+ */
+ get_page(alloc_frag->page);
+ dma->ref = 1;
+ alloc_frag->offset = sizeof(*dma);
- ++dma->ref;
+ rq->last_dma = dma;
}
+ ++dma->ref;
+
buf = head + alloc_frag->offset;
get_page(alloc_frag->page);
@@ -990,7 +1052,7 @@ static void virtnet_rq_unmap_free_buf(struct virtqueue *vq, void *buf)
return;
}
- if (rq->do_dma)
+ if (!vi->big_packets || vi->mergeable_rx_bufs)
virtnet_rq_unmap(rq, buf, 0);
virtnet_rq_free_buf(vi, rq, buf);
@@ -1001,7 +1063,7 @@ static void free_old_xmit(struct send_queue *sq, struct netdev_queue *txq,
{
struct virtnet_sq_free_stats stats = {0};
- __free_old_xmit(sq, txq, in_napi, &stats);
+ virtnet_free_old_xmit(sq, txq, in_napi, &stats);
/* Avoid overhead when no packets have been processed
* happens when called speculatively from start_xmit.
@@ -1068,12 +1130,6 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
}
}
-static void sg_fill_dma(struct scatterlist *sg, dma_addr_t addr, u32 len)
-{
- sg->dma_address = addr;
- sg->length = len;
-}
-
static struct xdp_buff *buf_to_xdp(struct virtnet_info *vi,
struct receive_queue *rq, void *buf, u32 len)
{
@@ -1354,7 +1410,8 @@ static int virtnet_add_recvbuf_xsk(struct virtnet_info *vi, struct receive_queue
sg_init_table(rq->sg, 1);
sg_fill_dma(rq->sg, addr, len);
- err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, xsk_buffs[i], gfp);
+ err = virtqueue_add_inbuf_premapped(rq->vq, rq->sg, 1,
+ xsk_buffs[i], NULL, gfp);
if (err)
goto err;
}
@@ -1368,6 +1425,120 @@ err:
return err;
}
+static void *virtnet_xsk_to_ptr(u32 len)
+{
+ unsigned long p;
+
+ p = len << VIRTIO_XSK_FLAG_OFFSET;
+
+ return virtnet_xmit_ptr_pack((void *)p, VIRTNET_XMIT_TYPE_XSK);
+}
+
+static int virtnet_xsk_xmit_one(struct send_queue *sq,
+ struct xsk_buff_pool *pool,
+ struct xdp_desc *desc)
+{
+ struct virtnet_info *vi;
+ dma_addr_t addr;
+
+ vi = sq->vq->vdev->priv;
+
+ addr = xsk_buff_raw_get_dma(pool, desc->addr);
+ xsk_buff_raw_dma_sync_for_device(pool, addr, desc->len);
+
+ sg_init_table(sq->sg, 2);
+ sg_fill_dma(sq->sg, sq->xsk_hdr_dma_addr, vi->hdr_len);
+ sg_fill_dma(sq->sg + 1, addr, desc->len);
+
+ return virtqueue_add_outbuf_premapped(sq->vq, sq->sg, 2,
+ virtnet_xsk_to_ptr(desc->len),
+ GFP_ATOMIC);
+}
+
+static int virtnet_xsk_xmit_batch(struct send_queue *sq,
+ struct xsk_buff_pool *pool,
+ unsigned int budget,
+ u64 *kicks)
+{
+ struct xdp_desc *descs = pool->tx_descs;
+ bool kick = false;
+ u32 nb_pkts, i;
+ int err;
+
+ budget = min_t(u32, budget, sq->vq->num_free);
+
+ nb_pkts = xsk_tx_peek_release_desc_batch(pool, budget);
+ if (!nb_pkts)
+ return 0;
+
+ for (i = 0; i < nb_pkts; i++) {
+ err = virtnet_xsk_xmit_one(sq, pool, &descs[i]);
+ if (unlikely(err)) {
+ xsk_tx_completed(sq->xsk_pool, nb_pkts - i);
+ break;
+ }
+
+ kick = true;
+ }
+
+ if (kick && virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq))
+ (*kicks)++;
+
+ return i;
+}
+
+static bool virtnet_xsk_xmit(struct send_queue *sq, struct xsk_buff_pool *pool,
+ int budget)
+{
+ struct virtnet_info *vi = sq->vq->vdev->priv;
+ struct virtnet_sq_free_stats stats = {};
+ struct net_device *dev = vi->dev;
+ u64 kicks = 0;
+ int sent;
+
+ /* Avoid to wakeup napi meanless, so call __free_old_xmit instead of
+ * free_old_xmit().
+ */
+ __free_old_xmit(sq, netdev_get_tx_queue(dev, sq - vi->sq), true, &stats);
+
+ if (stats.xsk)
+ xsk_tx_completed(sq->xsk_pool, stats.xsk);
+
+ sent = virtnet_xsk_xmit_batch(sq, pool, budget, &kicks);
+
+ if (!is_xdp_raw_buffer_queue(vi, sq - vi->sq))
+ check_sq_full_and_disable(vi, vi->dev, sq);
+
+ if (sent) {
+ struct netdev_queue *txq;
+
+ txq = netdev_get_tx_queue(vi->dev, sq - vi->sq);
+ txq_trans_cond_update(txq);
+ }
+
+ u64_stats_update_begin(&sq->stats.syncp);
+ u64_stats_add(&sq->stats.packets, stats.packets);
+ u64_stats_add(&sq->stats.bytes, stats.bytes);
+ u64_stats_add(&sq->stats.kicks, kicks);
+ u64_stats_add(&sq->stats.xdp_tx, sent);
+ u64_stats_update_end(&sq->stats.syncp);
+
+ if (xsk_uses_need_wakeup(pool))
+ xsk_set_tx_need_wakeup(pool);
+
+ return sent;
+}
+
+static void xsk_wakeup(struct send_queue *sq)
+{
+ if (napi_if_scheduled_mark_missed(&sq->napi))
+ return;
+
+ local_bh_disable();
+ virtqueue_napi_schedule(&sq->napi, sq->vq);
+ local_bh_enable();
+}
+
static int virtnet_xsk_wakeup(struct net_device *dev, u32 qid, u32 flag)
{
struct virtnet_info *vi = netdev_priv(dev);
@@ -1381,14 +1552,19 @@ static int virtnet_xsk_wakeup(struct net_device *dev, u32 qid, u32 flag)
sq = &vi->sq[qid];
- if (napi_if_scheduled_mark_missed(&sq->napi))
- return 0;
+ xsk_wakeup(sq);
+ return 0;
+}
- local_bh_disable();
- virtqueue_napi_schedule(&sq->napi, sq->vq);
- local_bh_enable();
+static void virtnet_xsk_completed(struct send_queue *sq, int num)
+{
+ xsk_tx_completed(sq->xsk_pool, num);
- return 0;
+ /* If this is called by rx poll, start_xmit and xdp xmit we should
+ * wakeup the tx napi to consume the xsk tx queue, because the tx
+ * interrupt may not be triggered.
+ */
+ xsk_wakeup(sq);
}
static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
@@ -1431,8 +1607,7 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
skb_frag_size(frag), skb_frag_off(frag));
}
- err = virtqueue_add_outbuf(sq->vq, sq->sg, nr_frags + 1,
- xdp_to_ptr(xdpf), GFP_ATOMIC);
+ err = virtnet_add_outbuf(sq, nr_frags + 1, xdpf, VIRTNET_XMIT_TYPE_XDP);
if (unlikely(err))
return -ENOSPC; /* Caller handle free/refcnt */
@@ -1505,8 +1680,8 @@ static int virtnet_xdp_xmit(struct net_device *dev,
}
/* Free up any pending old buffers before queueing new ones. */
- __free_old_xmit(sq, netdev_get_tx_queue(dev, sq - vi->sq),
- false, &stats);
+ virtnet_free_old_xmit(sq, netdev_get_tx_queue(dev, sq - vi->sq),
+ false, &stats);
for (i = 0; i < n; i++) {
struct xdp_frame *xdpf = frames[i];
@@ -2423,6 +2598,9 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq,
len = SKB_DATA_ALIGN(len) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ if (unlikely(!skb_page_frag_refill(len, &rq->alloc_frag, gfp)))
+ return -ENOMEM;
+
buf = virtnet_rq_alloc(rq, len, gfp);
if (unlikely(!buf))
return -ENOMEM;
@@ -2431,10 +2609,9 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq,
virtnet_rq_init_one_sg(rq, buf, vi->hdr_len + GOOD_PACKET_LEN);
- err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp);
+ err = virtqueue_add_inbuf_premapped(rq->vq, rq->sg, 1, buf, ctx, gfp);
if (err < 0) {
- if (rq->do_dma)
- virtnet_rq_unmap(rq, buf, 0);
+ virtnet_rq_unmap(rq, buf, 0);
put_page(virt_to_head_page(buf));
}
@@ -2525,6 +2702,12 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi,
*/
len = get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len, room);
+ if (unlikely(!skb_page_frag_refill(len + room, alloc_frag, gfp)))
+ return -ENOMEM;
+
+ if (!alloc_frag->offset && len + room + sizeof(struct virtnet_rq_dma) > alloc_frag->size)
+ len -= sizeof(struct virtnet_rq_dma);
+
buf = virtnet_rq_alloc(rq, len + room, gfp);
if (unlikely(!buf))
return -ENOMEM;
@@ -2546,10 +2729,9 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi,
virtnet_rq_init_one_sg(rq, buf, len);
ctx = mergeable_len_to_ctx(len + room, headroom);
- err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp);
+ err = virtqueue_add_inbuf_premapped(rq->vq, rq->sg, 1, buf, ctx, gfp);
if (err < 0) {
- if (rq->do_dma)
- virtnet_rq_unmap(rq, buf, 0);
+ virtnet_rq_unmap(rq, buf, 0);
put_page(virt_to_head_page(buf));
}
@@ -2706,7 +2888,7 @@ static int virtnet_receive_packets(struct virtnet_info *vi,
}
} else {
while (packets < budget &&
- (buf = virtnet_rq_get_buf(rq, &len, NULL)) != NULL) {
+ (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
receive_buf(vi, rq, buf, len, NULL, xdp_xmit, stats);
packets++;
}
@@ -2804,7 +2986,7 @@ static void virtnet_rx_dim_update(struct virtnet_info *vi, struct receive_queue
u64_stats_read(&rq->stats.bytes),
&cur_sample);
- net_dim(&rq->dim, cur_sample);
+ net_dim(&rq->dim, &cur_sample);
rq->packets_in_napi = 0;
}
@@ -2956,7 +3138,7 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
struct virtnet_info *vi = sq->vq->vdev->priv;
unsigned int index = vq2txq(sq->vq);
struct netdev_queue *txq;
- int opaque;
+ int opaque, xsk_done = 0;
bool done;
if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
@@ -2968,7 +3150,11 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
txq = netdev_get_tx_queue(vi->dev, index);
__netif_tx_lock(txq, raw_smp_processor_id());
virtqueue_disable_cb(sq->vq);
- free_old_xmit(sq, txq, !!budget);
+
+ if (sq->xsk_pool)
+ xsk_done = virtnet_xsk_xmit(sq, sq->xsk_pool, budget);
+ else
+ free_old_xmit(sq, txq, !!budget);
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) {
if (netif_tx_queue_stopped(txq)) {
@@ -2979,6 +3165,11 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
netif_tx_wake_queue(txq);
}
+ if (xsk_done >= budget) {
+ __netif_tx_unlock(txq);
+ return budget;
+ }
+
opaque = virtqueue_enable_cb_prepare(sq->vq);
done = napi_complete_done(napi, 0);
@@ -3046,8 +3237,9 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan)
return num_sg;
num_sg++;
}
- return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg,
- skb_to_ptr(skb, orphan), GFP_ATOMIC);
+
+ return virtnet_add_outbuf(sq, num_sg, skb,
+ orphan ? VIRTNET_XMIT_TYPE_SKB_ORPHAN : VIRTNET_XMIT_TYPE_SKB);
}
static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -3374,15 +3566,59 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi)
dev_warn(&vi->dev->dev, "Failed to ack link announce.\n");
}
+static bool virtnet_commit_rss_command(struct virtnet_info *vi);
+
+static void virtnet_rss_update_by_qpairs(struct virtnet_info *vi, u16 queue_pairs)
+{
+ u32 indir_val = 0;
+ int i = 0;
+
+ for (; i < vi->rss_indir_table_size; ++i) {
+ indir_val = ethtool_rxfh_indir_default(i, queue_pairs);
+ vi->rss.indirection_table[i] = indir_val;
+ }
+ vi->rss.max_tx_vq = queue_pairs;
+}
+
static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
{
struct virtio_net_ctrl_mq *mq __free(kfree) = NULL;
- struct scatterlist sg;
+ struct virtio_net_ctrl_rss old_rss;
struct net_device *dev = vi->dev;
+ struct scatterlist sg;
if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ))
return 0;
+ /* Firstly check if we need update rss. Do updating if both (1) rss enabled and
+ * (2) no user configuration.
+ *
+ * During rss command processing, device updates queue_pairs using rss.max_tx_vq. That is,
+ * the device updates queue_pairs together with rss, so we can skip the sperate queue_pairs
+ * update (VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET below) and return directly.
+ */
+ if (vi->has_rss && !netif_is_rxfh_configured(dev)) {
+ memcpy(&old_rss, &vi->rss, sizeof(old_rss));
+ if (rss_indirection_table_alloc(&vi->rss, vi->rss_indir_table_size)) {
+ vi->rss.indirection_table = old_rss.indirection_table;
+ return -ENOMEM;
+ }
+
+ virtnet_rss_update_by_qpairs(vi, queue_pairs);
+
+ if (!virtnet_commit_rss_command(vi)) {
+ /* restore ctrl_rss if commit_rss_command failed */
+ rss_indirection_table_free(&vi->rss);
+ memcpy(&vi->rss, &old_rss, sizeof(old_rss));
+
+ dev_warn(&dev->dev, "Fail to set num of queue pairs to %d, because committing RSS failed\n",
+ queue_pairs);
+ return -EINVAL;
+ }
+ rss_indirection_table_free(&old_rss);
+ goto succ;
+ }
+
mq = kzalloc(sizeof(*mq), GFP_KERNEL);
if (!mq)
return -ENOMEM;
@@ -3395,12 +3631,12 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n",
queue_pairs);
return -EINVAL;
- } else {
- vi->curr_queue_pairs = queue_pairs;
- /* virtnet_open() will refill when device is going to up. */
- if (dev->flags & IFF_UP)
- schedule_delayed_work(&vi->refill, 0);
}
+succ:
+ vi->curr_queue_pairs = queue_pairs;
+ /* virtnet_open() will refill when device is going to up. */
+ if (dev->flags & IFF_UP)
+ schedule_delayed_work(&vi->refill, 0);
return 0;
}
@@ -3828,11 +4064,15 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi)
/* prepare sgs */
sg_init_table(sgs, 4);
- sg_buf_size = offsetof(struct virtio_net_ctrl_rss, indirection_table);
+ sg_buf_size = offsetof(struct virtio_net_ctrl_rss, hash_cfg_reserved);
sg_set_buf(&sgs[0], &vi->rss, sg_buf_size);
- sg_buf_size = sizeof(uint16_t) * (vi->rss.indirection_table_mask + 1);
- sg_set_buf(&sgs[1], vi->rss.indirection_table, sg_buf_size);
+ if (vi->has_rss) {
+ sg_buf_size = sizeof(uint16_t) * vi->rss_indir_table_size;
+ sg_set_buf(&sgs[1], vi->rss.indirection_table, sg_buf_size);
+ } else {
+ sg_set_buf(&sgs[1], &vi->rss.hash_cfg_reserved, sizeof(uint16_t));
+ }
sg_buf_size = offsetof(struct virtio_net_ctrl_rss, key)
- offsetof(struct virtio_net_ctrl_rss, max_tx_vq);
@@ -3856,21 +4096,14 @@ err:
static void virtnet_init_default_rss(struct virtnet_info *vi)
{
- u32 indir_val = 0;
- int i = 0;
-
vi->rss.hash_types = vi->rss_hash_types_supported;
vi->rss_hash_types_saved = vi->rss_hash_types_supported;
vi->rss.indirection_table_mask = vi->rss_indir_table_size
? vi->rss_indir_table_size - 1 : 0;
vi->rss.unclassified_queue = 0;
- for (; i < vi->rss_indir_table_size; ++i) {
- indir_val = ethtool_rxfh_indir_default(i, vi->curr_queue_pairs);
- vi->rss.indirection_table[i] = indir_val;
- }
+ virtnet_rss_update_by_qpairs(vi, vi->curr_queue_pairs);
- vi->rss.max_tx_vq = vi->has_rss ? vi->curr_queue_pairs : 0;
vi->rss.hash_key_length = vi->rss_key_size;
netdev_rss_key_fill(vi->rss.key, vi->rss_key_size);
@@ -5011,7 +5244,7 @@ static int virtnet_set_coalesce(struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct virtnet_info *vi = netdev_priv(dev);
- int ret, queue_number, napi_weight;
+ int ret, queue_number, napi_weight, i;
bool update_napi = false;
/* Can't change NAPI weight if the link is up */
@@ -5040,6 +5273,14 @@ static int virtnet_set_coalesce(struct net_device *dev,
return ret;
if (update_napi) {
+ /* xsk xmit depends on the tx napi. So if xsk is active,
+ * prevent modifications to tx napi.
+ */
+ for (i = queue_number; i < vi->max_queue_pairs; i++) {
+ if (vi->sq[i].xsk_pool)
+ return -EBUSY;
+ }
+
for (; queue_number < vi->max_queue_pairs; queue_number++)
vi->sq[queue_number].napi.weight = napi_weight;
}
@@ -5488,6 +5729,29 @@ unreg:
return err;
}
+static int virtnet_sq_bind_xsk_pool(struct virtnet_info *vi,
+ struct send_queue *sq,
+ struct xsk_buff_pool *pool)
+{
+ int err, qindex;
+
+ qindex = sq - vi->sq;
+
+ virtnet_tx_pause(vi, sq);
+
+ err = virtqueue_reset(sq->vq, virtnet_sq_free_unused_buf);
+ if (err) {
+ netdev_err(vi->dev, "reset tx fail: tx queue index: %d err: %d\n", qindex, err);
+ pool = NULL;
+ }
+
+ sq->xsk_pool = pool;
+
+ virtnet_tx_resume(vi, sq);
+
+ return err;
+}
+
static int virtnet_xsk_pool_enable(struct net_device *dev,
struct xsk_buff_pool *pool,
u16 qid)
@@ -5496,6 +5760,7 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
struct receive_queue *rq;
struct device *dma_dev;
struct send_queue *sq;
+ dma_addr_t hdr_dma;
int err, size;
if (vi->hdr_len > xsk_pool_get_headroom(pool))
@@ -5533,6 +5798,11 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
if (!rq->xsk_buffs)
return -ENOMEM;
+ hdr_dma = virtqueue_dma_map_single_attrs(sq->vq, &xsk_hdr, vi->hdr_len,
+ DMA_TO_DEVICE, 0);
+ if (virtqueue_dma_mapping_error(sq->vq, hdr_dma))
+ return -ENOMEM;
+
err = xsk_pool_dma_map(pool, dma_dev, 0);
if (err)
goto err_xsk_map;
@@ -5541,11 +5811,24 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
if (err)
goto err_rq;
+ err = virtnet_sq_bind_xsk_pool(vi, sq, pool);
+ if (err)
+ goto err_sq;
+
+ /* Now, we do not support tx offload(such as tx csum), so all the tx
+ * virtnet hdr is zero. So all the tx packets can share a single hdr.
+ */
+ sq->xsk_hdr_dma_addr = hdr_dma;
+
return 0;
+err_sq:
+ virtnet_rq_bind_xsk_pool(vi, rq, NULL);
err_rq:
xsk_pool_dma_unmap(pool, 0);
err_xsk_map:
+ virtqueue_dma_unmap_single_attrs(rq->vq, hdr_dma, vi->hdr_len,
+ DMA_TO_DEVICE, 0);
return err;
}
@@ -5554,19 +5837,24 @@ static int virtnet_xsk_pool_disable(struct net_device *dev, u16 qid)
struct virtnet_info *vi = netdev_priv(dev);
struct xsk_buff_pool *pool;
struct receive_queue *rq;
+ struct send_queue *sq;
int err;
if (qid >= vi->curr_queue_pairs)
return -EINVAL;
+ sq = &vi->sq[qid];
rq = &vi->rq[qid];
pool = rq->xsk_pool;
err = virtnet_rq_bind_xsk_pool(vi, rq, NULL);
+ err |= virtnet_sq_bind_xsk_pool(vi, sq, NULL);
xsk_pool_dma_unmap(pool, 0);
+ virtqueue_dma_unmap_single_attrs(sq->vq, sq->xsk_hdr_dma_addr,
+ vi->hdr_len, DMA_TO_DEVICE, 0);
kvfree(rq->xsk_buffs);
return err;
@@ -5916,7 +6204,7 @@ static void free_receive_page_frags(struct virtnet_info *vi)
int i;
for (i = 0; i < vi->max_queue_pairs; i++)
if (vi->rq[i].alloc_frag.page) {
- if (vi->rq[i].do_dma && vi->rq[i].last_dma)
+ if (vi->rq[i].last_dma)
virtnet_rq_unmap(&vi->rq[i], vi->rq[i].last_dma, 0);
put_page(vi->rq[i].alloc_frag.page);
}
@@ -5924,10 +6212,26 @@ static void free_receive_page_frags(struct virtnet_info *vi)
static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
{
- if (!is_xdp_frame(buf))
+ struct virtnet_info *vi = vq->vdev->priv;
+ struct send_queue *sq;
+ int i = vq2rxq(vq);
+
+ sq = &vi->sq[i];
+
+ switch (virtnet_xmit_ptr_unpack(&buf)) {
+ case VIRTNET_XMIT_TYPE_SKB:
+ case VIRTNET_XMIT_TYPE_SKB_ORPHAN:
dev_kfree_skb(buf);
- else
- xdp_return_frame(ptr_to_xdp(buf));
+ break;
+
+ case VIRTNET_XMIT_TYPE_XDP:
+ xdp_return_frame(buf);
+ break;
+
+ case VIRTNET_XMIT_TYPE_XSK:
+ xsk_tx_completed(sq->xsk_pool, 1);
+ break;
+ }
}
static void free_unused_bufs(struct virtnet_info *vi)
@@ -6375,7 +6679,8 @@ static int virtnet_probe(struct virtio_device *vdev)
dev->hw_features |= NETIF_F_GRO_HW;
dev->vlan_features = dev->features;
- dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT;
+ dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+ NETDEV_XDP_ACT_XSK_ZEROCOPY;
/* MTU range: 68 - 65535 */
dev->min_mtu = MIN_MTU;
@@ -6420,10 +6725,19 @@ static int virtnet_probe(struct virtio_device *vdev)
virtio_cread16(vdev, offsetof(struct virtio_net_config,
rss_max_indirection_table_length));
}
+ err = rss_indirection_table_alloc(&vi->rss, vi->rss_indir_table_size);
+ if (err)
+ goto free;
if (vi->has_rss || vi->has_rss_hash_report) {
vi->rss_key_size =
virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size));
+ if (vi->rss_key_size > VIRTIO_NET_RSS_MAX_KEY_SIZE) {
+ dev_err(&vdev->dev, "rss_max_key_size=%u exceeds the limit %u.\n",
+ vi->rss_key_size, VIRTIO_NET_RSS_MAX_KEY_SIZE);
+ err = -EINVAL;
+ goto free;
+ }
vi->rss_hash_types_supported =
virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_hash_types));
@@ -6551,6 +6865,15 @@ static int virtnet_probe(struct virtio_device *vdev)
virtio_device_ready(vdev);
+ if (vi->has_rss || vi->has_rss_hash_report) {
+ if (!virtnet_commit_rss_command(vi)) {
+ dev_warn(&vdev->dev, "RSS disabled because committing failed.\n");
+ dev->hw_features &= ~NETIF_F_RXHASH;
+ vi->has_rss_hash_report = false;
+ vi->has_rss = false;
+ }
+ }
+
virtnet_set_queues(vi, vi->curr_queue_pairs);
/* a random MAC address has been assigned, notify the device.
@@ -6674,6 +6997,8 @@ static void virtnet_remove(struct virtio_device *vdev)
remove_vq_common(vi);
+ rss_indirection_table_free(&vi->rss);
+
free_netdev(vi->dev);
}
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index b70654c7ad34..6793fa09f9d1 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -201,6 +201,14 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)
adapter->link_speed = ret >> 16;
if (ret & 1) { /* Link is up. */
+ /*
+ * From vmxnet3 v9, the hypervisor reports the speed in Gbps.
+ * Convert the speed to Mbps before rporting it to the kernel.
+ * Max link speed supported is 10000G.
+ */
+ if (VMXNET3_VERSION_GE_9(adapter) &&
+ adapter->link_speed < 10000)
+ adapter->link_speed = adapter->link_speed * 1000;
netdev_info(adapter->netdev, "NIC Link is Up %d Mbps\n",
adapter->link_speed);
netif_carrier_on(adapter->netdev);
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 4087f72f0d2b..67d25f4f94ef 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -521,7 +521,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
/* needed to match OIF rule */
fl4.flowi4_l3mdev = vrf_dev->ifindex;
fl4.flowi4_iif = LOOPBACK_IFINDEX;
- fl4.flowi4_tos = ip4h->tos & INET_DSCP_MASK;
+ fl4.flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h));
fl4.flowi4_flags = FLOWI_FLAG_ANYSRC;
fl4.flowi4_proto = ip4h->protocol;
fl4.daddr = ip4h->daddr;
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 6e9a3795846a..9ea63059d52d 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -1232,10 +1232,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
*ifindex = 0;
}
- if (tb[NDA_NH_ID])
- *nhid = nla_get_u32(tb[NDA_NH_ID]);
- else
- *nhid = 0;
+ *nhid = nla_get_u32_default(tb[NDA_NH_ID], 0);
return 0;
}
@@ -1244,7 +1241,7 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr, u16 vid, u16 flags,
- struct netlink_ext_ack *extack)
+ bool *notified, struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
/* struct net *net = dev_net(vxlan->dev); */
@@ -1280,6 +1277,9 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
nhid, true, extack);
spin_unlock_bh(&vxlan->hash_lock[hash_index]);
+ if (!err)
+ *notified = true;
+
return err;
}
@@ -1319,7 +1319,7 @@ out:
/* Delete entry (via netlink) */
static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
- const unsigned char *addr, u16 vid,
+ const unsigned char *addr, u16 vid, bool *notified,
struct netlink_ext_ack *extack)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
@@ -1341,6 +1341,9 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
true);
spin_unlock_bh(&vxlan->hash_lock[hash_index]);
+ if (!err)
+ *notified = true;
+
return err;
}
@@ -1435,11 +1438,11 @@ errout:
/* Watch incoming packets to learn mapping between Ethernet address
* and Tunnel endpoint.
- * Return true if packet is bogus and should be dropped.
*/
-static bool vxlan_snoop(struct net_device *dev,
- union vxlan_addr *src_ip, const u8 *src_mac,
- u32 src_ifindex, __be32 vni)
+static enum skb_drop_reason vxlan_snoop(struct net_device *dev,
+ union vxlan_addr *src_ip,
+ const u8 *src_mac, u32 src_ifindex,
+ __be32 vni)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_fdb *f;
@@ -1447,7 +1450,7 @@ static bool vxlan_snoop(struct net_device *dev,
/* Ignore packets from invalid src-address */
if (!is_valid_ether_addr(src_mac))
- return true;
+ return SKB_DROP_REASON_MAC_INVALID_SOURCE;
#if IS_ENABLED(CONFIG_IPV6)
if (src_ip->sa.sa_family == AF_INET6 &&
@@ -1461,15 +1464,15 @@ static bool vxlan_snoop(struct net_device *dev,
if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) &&
rdst->remote_ifindex == ifindex))
- return false;
+ return SKB_NOT_DROPPED_YET;
/* Don't migrate static entries, drop packets */
if (f->state & (NUD_PERMANENT | NUD_NOARP))
- return true;
+ return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS;
/* Don't override an fdb with nexthop with a learnt entry */
if (rcu_access_pointer(f->nh))
- return true;
+ return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS;
if (net_ratelimit())
netdev_info(dev,
@@ -1497,7 +1500,7 @@ static bool vxlan_snoop(struct net_device *dev,
spin_unlock(&vxlan->hash_lock[hash_index]);
}
- return false;
+ return SKB_NOT_DROPPED_YET;
}
static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
@@ -1551,9 +1554,11 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
#endif
}
-static bool vxlan_remcsum(struct vxlanhdr *unparsed,
- struct sk_buff *skb, u32 vxflags)
+static enum skb_drop_reason vxlan_remcsum(struct vxlanhdr *unparsed,
+ struct sk_buff *skb,
+ u32 vxflags)
{
+ enum skb_drop_reason reason;
size_t start, offset;
if (!(unparsed->vx_flags & VXLAN_HF_RCO) || skb->remcsum_offload)
@@ -1562,15 +1567,17 @@ static bool vxlan_remcsum(struct vxlanhdr *unparsed,
start = vxlan_rco_start(unparsed->vx_vni);
offset = start + vxlan_rco_offset(unparsed->vx_vni);
- if (!pskb_may_pull(skb, offset + sizeof(u16)))
- return false;
+ reason = pskb_may_pull_reason(skb, offset + sizeof(u16));
+ if (reason)
+ return reason;
skb_remcsum_process(skb, (void *)(vxlan_hdr(skb) + 1), start, offset,
!!(vxflags & VXLAN_F_REMCSUM_NOPARTIAL));
out:
unparsed->vx_flags &= ~VXLAN_HF_RCO;
unparsed->vx_vni &= VXLAN_VNI_MASK;
- return true;
+
+ return SKB_NOT_DROPPED_YET;
}
static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed,
@@ -1604,9 +1611,9 @@ out:
unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
}
-static bool vxlan_set_mac(struct vxlan_dev *vxlan,
- struct vxlan_sock *vs,
- struct sk_buff *skb, __be32 vni)
+static enum skb_drop_reason vxlan_set_mac(struct vxlan_dev *vxlan,
+ struct vxlan_sock *vs,
+ struct sk_buff *skb, __be32 vni)
{
union vxlan_addr saddr;
u32 ifindex = skb->dev->ifindex;
@@ -1617,7 +1624,7 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
/* Ignore packet loops (and multicast echo) */
if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
- return false;
+ return SKB_DROP_REASON_LOCAL_MAC;
/* Get address from the outer IP header */
if (vxlan_get_sk_family(vs) == AF_INET) {
@@ -1630,11 +1637,11 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
#endif
}
- if ((vxlan->cfg.flags & VXLAN_F_LEARN) &&
- vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, ifindex, vni))
- return false;
+ if (!(vxlan->cfg.flags & VXLAN_F_LEARN))
+ return SKB_NOT_DROPPED_YET;
- return true;
+ return vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source,
+ ifindex, vni);
}
static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph,
@@ -1671,13 +1678,15 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
struct vxlan_metadata _md;
struct vxlan_metadata *md = &_md;
__be16 protocol = htons(ETH_P_TEB);
+ enum skb_drop_reason reason;
bool raw_proto = false;
void *oiph;
__be32 vni = 0;
int nh;
/* Need UDP and VXLAN header to be present */
- if (!pskb_may_pull(skb, VXLAN_HLEN))
+ reason = pskb_may_pull_reason(skb, VXLAN_HLEN);
+ if (reason)
goto drop;
unparsed = *vxlan_hdr(skb);
@@ -1686,6 +1695,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
ntohl(vxlan_hdr(skb)->vx_flags),
ntohl(vxlan_hdr(skb)->vx_vni));
+ reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
/* Return non vxlan pkt */
goto drop;
}
@@ -1699,8 +1709,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
vni = vxlan_vni(vxlan_hdr(skb)->vx_vni);
vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, &vninode);
- if (!vxlan)
+ if (!vxlan) {
+ reason = SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND;
goto drop;
+ }
/* For backwards compatibility, only allow reserved fields to be
* used by VXLAN extensions if explicitly requested.
@@ -1713,12 +1725,16 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
}
if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto,
- !net_eq(vxlan->net, dev_net(vxlan->dev))))
+ !net_eq(vxlan->net, dev_net(vxlan->dev)))) {
+ reason = SKB_DROP_REASON_NOMEM;
goto drop;
+ }
- if (vs->flags & VXLAN_F_REMCSUM_RX)
- if (unlikely(!vxlan_remcsum(&unparsed, skb, vs->flags)))
+ if (vs->flags & VXLAN_F_REMCSUM_RX) {
+ reason = vxlan_remcsum(&unparsed, skb, vs->flags);
+ if (unlikely(reason))
goto drop;
+ }
if (vxlan_collect_metadata(vs)) {
IP_TUNNEL_DECLARE_FLAGS(flags) = { };
@@ -1728,8 +1744,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
tun_dst = udp_tun_rx_dst(skb, vxlan_get_sk_family(vs), flags,
key32_to_tunnel_id(vni), sizeof(*md));
- if (!tun_dst)
+ if (!tun_dst) {
+ reason = SKB_DROP_REASON_NOMEM;
goto drop;
+ }
md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
@@ -1753,11 +1771,13 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
* is more robust and provides a little more security in
* adding extensions to VXLAN.
*/
+ reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
goto drop;
}
if (!raw_proto) {
- if (!vxlan_set_mac(vxlan, vs, skb, vni))
+ reason = vxlan_set_mac(vxlan, vs, skb, vni);
+ if (reason)
goto drop;
} else {
skb_reset_mac_header(skb);
@@ -1773,7 +1793,8 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
skb_reset_network_header(skb);
- if (!pskb_inet_may_pull(skb)) {
+ reason = pskb_inet_may_pull_reason(skb);
+ if (reason) {
DEV_STATS_INC(vxlan->dev, rx_length_errors);
DEV_STATS_INC(vxlan->dev, rx_errors);
vxlan_vnifilter_count(vxlan, vni, vninode,
@@ -1785,6 +1806,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
oiph = skb->head + nh;
if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
+ reason = SKB_DROP_REASON_IP_TUNNEL_ECN;
DEV_STATS_INC(vxlan->dev, rx_frame_errors);
DEV_STATS_INC(vxlan->dev, rx_errors);
vxlan_vnifilter_count(vxlan, vni, vninode,
@@ -1799,6 +1821,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
dev_core_stats_rx_dropped_inc(vxlan->dev);
vxlan_vnifilter_count(vxlan, vni, vninode,
VXLAN_VNI_STATS_RX_DROPS, 0);
+ reason = SKB_DROP_REASON_DEV_READY;
goto drop;
}
@@ -1811,8 +1834,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
return 0;
drop:
+ reason = reason ?: SKB_DROP_REASON_NOT_SPECIFIED;
/* Consume bad packet */
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
return 0;
}
@@ -2268,7 +2292,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
rcu_read_lock();
dev = skb->dev;
if (unlikely(!(dev->flags & IFF_UP))) {
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);
goto drop;
}
@@ -2319,7 +2343,7 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
DEV_STATS_INC(dev, tx_errors);
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_TX_ERRORS, 0);
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_VNI_NOT_FOUND);
return -ENOENT;
}
@@ -2352,13 +2376,16 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
bool use_cache;
bool udp_sum = false;
bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev));
+ enum skb_drop_reason reason;
bool no_eth_encap;
__be32 vni = 0;
no_eth_encap = flags & VXLAN_F_GPE && skb->protocol != htons(ETH_P_TEB);
- if (!skb_vlan_inet_prepare(skb, no_eth_encap))
+ reason = skb_vlan_inet_prepare(skb, no_eth_encap);
+ if (reason)
goto drop;
+ reason = SKB_DROP_REASON_NOT_SPECIFIED;
old_iph = ip_hdr(skb);
info = skb_tunnel_info(skb);
@@ -2462,6 +2489,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
tos, use_cache ? dst_cache : NULL);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
+ reason = SKB_DROP_REASON_IP_OUTNOROUTES;
goto tx_error;
}
@@ -2513,8 +2541,10 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
vni, md, flags, udp_sum);
- if (err < 0)
+ if (err < 0) {
+ reason = SKB_DROP_REASON_NOMEM;
goto tx_error;
+ }
udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, saddr,
pkey->u.ipv4.dst, tos, ttl, df,
@@ -2534,6 +2564,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
if (IS_ERR(ndst)) {
err = PTR_ERR(ndst);
ndst = NULL;
+ reason = SKB_DROP_REASON_IP_OUTNOROUTES;
goto tx_error;
}
@@ -2574,8 +2605,10 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
skb_scrub_packet(skb, xnet);
err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
vni, md, flags, udp_sum);
- if (err < 0)
+ if (err < 0) {
+ reason = SKB_DROP_REASON_NOMEM;
goto tx_error;
+ }
udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev,
&saddr, &pkey->u.ipv6.dst, tos, ttl,
@@ -2590,7 +2623,7 @@ out_unlock:
drop:
dev_core_stats_tx_dropped_inc(dev);
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
- dev_kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
return;
tx_error:
@@ -2602,7 +2635,7 @@ tx_error:
dst_release(ndst);
DEV_STATS_INC(dev, tx_errors);
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
}
static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
@@ -2708,7 +2741,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
if (info && info->mode & IP_TUNNEL_INFO_TX)
vxlan_xmit_one(skb, dev, vni, NULL, false);
else
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_TUNNEL_TXINFO);
return NETDEV_TX_OK;
}
}
@@ -2771,7 +2804,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
dev_core_stats_tx_dropped_inc(dev);
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_TX_DROPS, 0);
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
return NETDEV_TX_OK;
}
}
@@ -2794,7 +2827,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
if (fdst)
vxlan_xmit_one(skb, dev, vni, fdst, did_rsc);
else
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
}
return NETDEV_TX_OK;
diff --git a/drivers/net/vxlan/vxlan_mdb.c b/drivers/net/vxlan/vxlan_mdb.c
index 60eb95a06d55..8735891ee128 100644
--- a/drivers/net/vxlan/vxlan_mdb.c
+++ b/drivers/net/vxlan/vxlan_mdb.c
@@ -284,7 +284,7 @@ int vxlan_mdb_dump(struct net_device *dev, struct sk_buff *skb,
ASSERT_RTNL();
- NL_ASSERT_DUMP_CTX_FITS(struct vxlan_mdb_dump_ctx);
+ NL_ASSERT_CTX_FITS(struct vxlan_mdb_dump_ctx);
nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, RTM_NEWMDB, sizeof(*bpm),
@@ -1712,7 +1712,7 @@ netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan,
vxlan_xmit_one(skb, vxlan->dev, src_vni,
rcu_dereference(fremote->rd), false);
else
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wan/framer/pef2256/pef2256.c b/drivers/net/wan/framer/pef2256/pef2256.c
index 413a3c1d15bb..1e4c8e85d598 100644
--- a/drivers/net/wan/framer/pef2256/pef2256.c
+++ b/drivers/net/wan/framer/pef2256/pef2256.c
@@ -863,7 +863,7 @@ static struct platform_driver pef2256_driver = {
.of_match_table = pef2256_id_table,
},
.probe = pef2256_probe,
- .remove_new = pef2256_remove,
+ .remove = pef2256_remove,
};
module_platform_driver(pef2256_driver);
diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
index 8fcfbde31a1c..8976dea8e17e 100644
--- a/drivers/net/wan/fsl_qmc_hdlc.c
+++ b/drivers/net/wan/fsl_qmc_hdlc.c
@@ -799,7 +799,7 @@ static struct platform_driver qmc_hdlc_driver = {
.of_match_table = qmc_hdlc_id_table,
},
.probe = qmc_hdlc_probe,
- .remove_new = qmc_hdlc_remove,
+ .remove = qmc_hdlc_remove,
};
module_platform_driver(qmc_hdlc_driver);
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index 605e70f7baac..f999798a5612 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -1290,7 +1290,7 @@ MODULE_DEVICE_TABLE(of, fsl_ucc_hdlc_of_match);
static struct platform_driver ucc_hdlc_driver = {
.probe = ucc_hdlc_probe,
- .remove_new = ucc_hdlc_remove,
+ .remove = ucc_hdlc_remove,
.driver = {
.name = DRV_NAME,
.pm = HDLC_PM_OPS,
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 931c5ca79ea5..720c5dc889ea 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -1534,7 +1534,7 @@ static void ixp4xx_hss_remove(struct platform_device *pdev)
static struct platform_driver ixp4xx_hss_driver = {
.driver.name = DRV_NAME,
.probe = ixp4xx_hss_probe,
- .remove_new = ixp4xx_hss_remove,
+ .remove = ixp4xx_hss_remove,
};
module_platform_driver(ixp4xx_hss_driver);
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index 45e9b908dbfb..6cf173a008e7 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -302,7 +302,8 @@ static void wg_setup(struct net_device *dev)
/* We need to keep the dst around in case of icmp replies. */
netif_keep_dst(dev);
- memset(wg, 0, sizeof(*wg));
+ netif_set_tso_max_size(dev, GSO_MAX_SIZE);
+
wg->dev = dev;
}
diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c
index 3d1f64ff2e12..25de7058701a 100644
--- a/drivers/net/wireguard/selftest/allowedips.c
+++ b/drivers/net/wireguard/selftest/allowedips.c
@@ -383,7 +383,6 @@ static __init bool randomized_test(void)
for (i = 0; i < NUM_QUERIES; ++i) {
get_random_bytes(ip, 4);
if (lookup(t.root4, 32, ip) != horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) {
- horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip);
pr_err("allowedips random v4 self-test: FAIL\n");
goto free;
}
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index f0441b3d7dcb..db9f9ebcb62d 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -837,12 +837,12 @@ static void ath10k_ahb_remove(struct platform_device *pdev)
}
static struct platform_driver ath10k_ahb_driver = {
- .driver = {
- .name = "ath10k_ahb",
+ .driver = {
+ .name = "ath10k_ahb",
.of_match_table = ath10k_ahb_of_match,
},
- .probe = ath10k_ahb_probe,
- .remove_new = ath10k_ahb_remove,
+ .probe = ath10k_ahb_probe,
+ .remove = ath10k_ahb_remove,
};
int ath10k_ahb_init(void)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 646e1737d4c4..c61b95a928da 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6369,7 +6369,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_scan_request *req = &hw_req->req;
- struct wmi_start_scan_arg arg;
+ struct wmi_start_scan_arg *arg = NULL;
int ret = 0;
int i;
u32 scan_timeout;
@@ -6402,56 +6402,61 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
if (ret)
goto exit;
- memset(&arg, 0, sizeof(arg));
- ath10k_wmi_start_scan_init(ar, &arg);
- arg.vdev_id = arvif->vdev_id;
- arg.scan_id = ATH10K_SCAN_ID;
+ arg = kzalloc(sizeof(*arg), GFP_KERNEL);
+ if (!arg) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ath10k_wmi_start_scan_init(ar, arg);
+ arg->vdev_id = arvif->vdev_id;
+ arg->scan_id = ATH10K_SCAN_ID;
if (req->ie_len) {
- arg.ie_len = req->ie_len;
- memcpy(arg.ie, req->ie, arg.ie_len);
+ arg->ie_len = req->ie_len;
+ memcpy(arg->ie, req->ie, arg->ie_len);
}
if (req->n_ssids) {
- arg.n_ssids = req->n_ssids;
- for (i = 0; i < arg.n_ssids; i++) {
- arg.ssids[i].len = req->ssids[i].ssid_len;
- arg.ssids[i].ssid = req->ssids[i].ssid;
+ arg->n_ssids = req->n_ssids;
+ for (i = 0; i < arg->n_ssids; i++) {
+ arg->ssids[i].len = req->ssids[i].ssid_len;
+ arg->ssids[i].ssid = req->ssids[i].ssid;
}
} else {
- arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
+ arg->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
}
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
- arg.scan_ctrl_flags |= WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ;
- ether_addr_copy(arg.mac_addr.addr, req->mac_addr);
- ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask);
+ arg->scan_ctrl_flags |= WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ;
+ ether_addr_copy(arg->mac_addr.addr, req->mac_addr);
+ ether_addr_copy(arg->mac_mask.addr, req->mac_addr_mask);
}
if (req->n_channels) {
- arg.n_channels = req->n_channels;
- for (i = 0; i < arg.n_channels; i++)
- arg.channels[i] = req->channels[i]->center_freq;
+ arg->n_channels = req->n_channels;
+ for (i = 0; i < arg->n_channels; i++)
+ arg->channels[i] = req->channels[i]->center_freq;
}
/* if duration is set, default dwell times will be overwritten */
if (req->duration) {
- arg.dwell_time_active = req->duration;
- arg.dwell_time_passive = req->duration;
- arg.burst_duration_ms = req->duration;
+ arg->dwell_time_active = req->duration;
+ arg->dwell_time_passive = req->duration;
+ arg->burst_duration_ms = req->duration;
- scan_timeout = min_t(u32, arg.max_rest_time *
- (arg.n_channels - 1) + (req->duration +
+ scan_timeout = min_t(u32, arg->max_rest_time *
+ (arg->n_channels - 1) + (req->duration +
ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
- arg.n_channels, arg.max_scan_time);
+ arg->n_channels, arg->max_scan_time);
} else {
- scan_timeout = arg.max_scan_time;
+ scan_timeout = arg->max_scan_time;
}
/* Add a 200ms margin to account for event/command processing */
scan_timeout += 200;
- ret = ath10k_start_scan(ar, &arg);
+ ret = ath10k_start_scan(ar, arg);
if (ret) {
ath10k_warn(ar, "failed to start hw scan: %d\n", ret);
spin_lock_bh(&ar->data_lock);
@@ -6463,6 +6468,8 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
msecs_to_jiffies(scan_timeout));
exit:
+ kfree(arg);
+
mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -7899,7 +7906,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
- struct wmi_start_scan_arg arg;
+ struct wmi_start_scan_arg *arg = NULL;
int ret = 0;
u32 scan_time_msec;
@@ -7936,20 +7943,25 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
- memset(&arg, 0, sizeof(arg));
- ath10k_wmi_start_scan_init(ar, &arg);
- arg.vdev_id = arvif->vdev_id;
- arg.scan_id = ATH10K_SCAN_ID;
- arg.n_channels = 1;
- arg.channels[0] = chan->center_freq;
- arg.dwell_time_active = scan_time_msec;
- arg.dwell_time_passive = scan_time_msec;
- arg.max_scan_time = scan_time_msec;
- arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
- arg.scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
- arg.burst_duration_ms = duration;
-
- ret = ath10k_start_scan(ar, &arg);
+ arg = kzalloc(sizeof(*arg), GFP_KERNEL);
+ if (!arg) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ath10k_wmi_start_scan_init(ar, arg);
+ arg->vdev_id = arvif->vdev_id;
+ arg->scan_id = ATH10K_SCAN_ID;
+ arg->n_channels = 1;
+ arg->channels[0] = chan->center_freq;
+ arg->dwell_time_active = scan_time_msec;
+ arg->dwell_time_passive = scan_time_msec;
+ arg->max_scan_time = scan_time_msec;
+ arg->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE;
+ arg->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ;
+ arg->burst_duration_ms = duration;
+
+ ret = ath10k_start_scan(ar, arg);
if (ret) {
ath10k_warn(ar, "failed to start roc scan: %d\n", ret);
spin_lock_bh(&ar->data_lock);
@@ -7975,6 +7987,8 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
ret = 0;
exit:
+ kfree(arg);
+
mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -8507,9 +8521,10 @@ exit:
static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath10k *ar = hw->priv;
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
@@ -9121,7 +9136,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss1[
{6, {2633, 2925}, {1215, 1350}, {585, 650} },
{7, {2925, 3250}, {1350, 1500}, {650, 722} },
{8, {3510, 3900}, {1620, 1800}, {780, 867} },
- {9, {3900, 4333}, {1800, 2000}, {780, 867} }
+ {9, {3900, 4333}, {1800, 2000}, {865, 960} }
};
/*MCS parameters with Nss = 2 */
@@ -9136,7 +9151,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss2[
{6, {5265, 5850}, {2430, 2700}, {1170, 1300} },
{7, {5850, 6500}, {2700, 3000}, {1300, 1444} },
{8, {7020, 7800}, {3240, 3600}, {1560, 1733} },
- {9, {7800, 8667}, {3600, 4000}, {1560, 1733} }
+ {9, {7800, 8667}, {3600, 4000}, {1730, 1920} }
};
static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs,
@@ -9450,7 +9465,7 @@ static const struct ieee80211_ops ath10k_ops = {
.reconfig_complete = ath10k_reconfig_complete,
.get_survey = ath10k_get_survey,
.set_bitrate_mask = ath10k_mac_op_set_bitrate_mask,
- .sta_rc_update = ath10k_sta_rc_update,
+ .link_sta_rc_update = ath10k_sta_rc_update,
.offset_tsf = ath10k_offset_tsf,
.ampdu_action = ath10k_ampdu_action,
.get_et_sset_count = ath10k_debug_get_et_sset_count,
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 08a6f36a6be9..6805357ee29e 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -3,7 +3,7 @@
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -2648,9 +2648,9 @@ static void ath10k_sdio_remove(struct sdio_func *func)
netif_napi_del(&ar->napi);
- ath10k_core_destroy(ar);
-
destroy_workqueue(ar_sdio->workqueue);
+
+ ath10k_core_destroy(ar);
}
static const struct sdio_device_id ath10k_sdio_devices[] = {
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 0fe47d51013c..d436a874cd5a 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1885,11 +1885,11 @@ static void ath10k_snoc_shutdown(struct platform_device *pdev)
}
static struct platform_driver ath10k_snoc_driver = {
- .probe = ath10k_snoc_probe,
- .remove_new = ath10k_snoc_remove,
+ .probe = ath10k_snoc_probe,
+ .remove = ath10k_snoc_remove,
.shutdown = ath10k_snoc_shutdown,
.driver = {
- .name = "ath10k_snoc",
+ .name = "ath10k_snoc",
.of_match_table = ath10k_snoc_dt_match,
},
};
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 97b12f51ef28..f2fc04596d48 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1000,18 +1000,18 @@ static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
if (!ab->hw_params.fixed_fw_mem)
return 0;
- ret = ath11k_ahb_setup_msa_resources(ab);
- if (ret) {
- ath11k_err(ab, "failed to setup msa resources\n");
- return ret;
- }
-
node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");
if (!node) {
ab_ahb->fw.use_tz = true;
return 0;
}
+ ret = ath11k_ahb_setup_msa_resources(ab);
+ if (ret) {
+ ath11k_err(ab, "failed to setup msa resources\n");
+ return ret;
+ }
+
info.fwnode = &node->fwnode;
info.parent = host_dev;
info.name = node->name;
@@ -1313,12 +1313,12 @@ free_resources:
}
static struct platform_driver ath11k_ahb_driver = {
- .driver = {
- .name = "ath11k",
+ .driver = {
+ .name = "ath11k",
.of_match_table = ath11k_ahb_of_match,
},
- .probe = ath11k_ahb_probe,
- .remove_new = ath11k_ahb_remove,
+ .probe = ath11k_ahb_probe,
+ .remove = ath11k_ahb_remove,
.shutdown = ath11k_ahb_shutdown,
};
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index ccf4ad35fdc3..be67382c00f6 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -616,7 +616,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
.supports_rssi_stats = true,
- .fw_wmi_diag_event = false,
+ .fw_wmi_diag_event = true,
.current_cc_support = true,
.dbr_debug_support = false,
.global_reset = false,
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index f02599bd1c36..61f4b6dd5380 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -1351,6 +1351,7 @@ void ath11k_hal_srng_deinit(struct ath11k_base *ab)
ath11k_hal_free_cont_rdp(ab);
ath11k_hal_free_cont_wrp(ab);
kfree(hal->srng_config);
+ hal->srng_config = NULL;
}
EXPORT_SYMBOL(ath11k_hal_srng_deinit);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index f8068d2e848c..e6acbff06749 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -5079,9 +5079,10 @@ static void ath11k_mac_op_sta_set_4addr(struct ieee80211_hw *hw,
static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath11k *ar = hw->priv;
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
@@ -9708,7 +9709,7 @@ static const struct ieee80211_ops ath11k_ops = {
.sta_state = ath11k_mac_op_sta_state,
.sta_set_4addr = ath11k_mac_op_sta_set_4addr,
.sta_set_txpwr = ath11k_mac_op_sta_set_txpwr,
- .sta_rc_update = ath11k_mac_op_sta_rc_update,
+ .link_sta_rc_update = ath11k_mac_op_sta_rc_update,
.conf_tx = ath11k_mac_op_conf_tx,
.set_antenna = ath11k_mac_op_set_antenna,
.get_antenna = ath11k_mac_op_get_antenna,
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index f477afd325de..7a22483b35cd 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -2180,6 +2180,9 @@ static int ath11k_qmi_request_device_info(struct ath11k_base *ab)
ab->mem = bar_addr_va;
ab->mem_len = resp.bar_size;
+ if (!ab->hw_params.ce_remap)
+ ab->mem_ce = ab->mem;
+
return 0;
out:
return ret;
diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c
index 99d8ba45a75b..827085a926b2 100644
--- a/drivers/net/wireless/ath/ath11k/wow.c
+++ b/drivers/net/wireless/ath/ath11k/wow.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/delay.h>
@@ -155,6 +155,7 @@ static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
u8 hdr_8023_bit_mask[ETH_HLEN] = {};
u8 hdr_80211_pattern[WOW_HDR_LEN] = {};
u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {};
+ u8 bytemask[WOW_MAX_PATTERN_SIZE] = {};
int total_len = old->pkt_offset + old->pattern_len;
int hdr_80211_end_offset;
@@ -172,11 +173,17 @@ static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
struct rfc1042_hdr *new_rfc_mask =
(struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len);
int rfc_len = sizeof(*new_rfc_pattern);
+ int i;
+
+ /* convert bitmask to bytemask */
+ for (i = 0; i < old->pattern_len; i++)
+ if (old->mask[i / 8] & BIT(i % 8))
+ bytemask[i] = 0xff;
memcpy(hdr_8023_pattern + old->pkt_offset,
old->pattern, ETH_HLEN - old->pkt_offset);
memcpy(hdr_8023_bit_mask + old->pkt_offset,
- old->mask, ETH_HLEN - old->pkt_offset);
+ bytemask, ETH_HLEN - old->pkt_offset);
/* Copy destination address */
memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN);
@@ -232,7 +239,7 @@ static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
(void *)old->pattern + ETH_HLEN - old->pkt_offset,
total_len - ETH_HLEN);
memcpy((u8 *)new->mask + new->pattern_len,
- (void *)old->mask + ETH_HLEN - old->pkt_offset,
+ bytemask + ETH_HLEN - old->pkt_offset,
total_len - ETH_HLEN);
new->pattern_len += total_len - ETH_HLEN;
@@ -393,35 +400,31 @@ static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif,
}
for (i = 0; i < wowlan->n_patterns; i++) {
- u8 bitmask[WOW_MAX_PATTERN_SIZE] = {};
u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {};
u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {};
struct cfg80211_pkt_pattern new_pattern = {};
- struct cfg80211_pkt_pattern old_pattern = patterns[i];
- int j;
new_pattern.pattern = ath_pattern;
new_pattern.mask = ath_bitmask;
if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE)
continue;
- /* convert bytemask to bitmask */
- for (j = 0; j < patterns[i].pattern_len; j++)
- if (patterns[i].mask[j / 8] & BIT(j % 8))
- bitmask[j] = 0xff;
- old_pattern.mask = bitmask;
if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
ATH11K_HW_TXRX_NATIVE_WIFI) {
if (patterns[i].pkt_offset < ETH_HLEN) {
- u8 pattern_ext[WOW_MAX_PATTERN_SIZE] = {};
-
- memcpy(pattern_ext, old_pattern.pattern,
- old_pattern.pattern_len);
- old_pattern.pattern = pattern_ext;
ath11k_wow_convert_8023_to_80211(&new_pattern,
- &old_pattern);
+ &patterns[i]);
} else {
- new_pattern = old_pattern;
+ int j;
+
+ new_pattern = patterns[i];
+ new_pattern.mask = ath_bitmask;
+
+ /* convert bitmask to bytemask */
+ for (j = 0; j < patterns[i].pattern_len; j++)
+ if (patterns[i].mask[j / 8] & BIT(j % 8))
+ ath_bitmask[j] = 0xff;
+
new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
}
}
diff --git a/drivers/net/wireless/ath/ath12k/Kconfig b/drivers/net/wireless/ath/ath12k/Kconfig
index f64e7c322216..52a1bb19e3da 100644
--- a/drivers/net/wireless/ath/ath12k/Kconfig
+++ b/drivers/net/wireless/ath/ath12k/Kconfig
@@ -42,3 +42,13 @@ config ATH12K_TRACING
If unsure, say Y to make it easier to debug problems. But if
you want optimal performance choose N.
+
+config ATH12K_COREDUMP
+ bool "ath12k coredump"
+ depends on ATH12K
+ select WANT_DEV_COREDUMP
+ help
+ Enable ath12k coredump collection
+
+ If unsure, say Y to make it easier to debug problems. But if
+ dump collection not required choose N.
diff --git a/drivers/net/wireless/ath/ath12k/Makefile b/drivers/net/wireless/ath/ath12k/Makefile
index 5a1ed20d730e..b5bb3e2599cd 100644
--- a/drivers/net/wireless/ath/ath12k/Makefile
+++ b/drivers/net/wireless/ath/ath12k/Makefile
@@ -27,6 +27,7 @@ ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o
ath12k-$(CONFIG_ACPI) += acpi.o
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
ath12k-$(CONFIG_PM) += wow.o
+ath12k-$(CONFIG_ATH12K_COREDUMP) += coredump.o
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h
index 857bc5f9e946..1a14b9fb86b8 100644
--- a/drivers/net/wireless/ath/ath12k/ce.h
+++ b/drivers/net/wireless/ath/ath12k/ce.h
@@ -148,7 +148,7 @@ struct ath12k_ce_pipe {
void (*send_cb)(struct ath12k_ce_pipe *pipe);
void (*recv_cb)(struct ath12k_base *ab, struct sk_buff *skb);
- struct tasklet_struct intr_tq;
+ struct work_struct intr_wq;
struct ath12k_ce_ring *src_ring;
struct ath12k_ce_ring *dest_ring;
struct ath12k_ce_ring *status_ring;
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 51252e8bc1ae..c57322221e1d 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1004,7 +1004,7 @@ void ath12k_core_halt(struct ath12k *ar)
{
struct ath12k_base *ab = ar->ab;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ar->num_created_vdevs = 0;
ar->allocated_vdev_map = 0;
@@ -1078,6 +1078,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
if (!ah || ah->state == ATH12K_HW_STATE_OFF)
continue;
+ wiphy_lock(ah->hw->wiphy);
mutex_lock(&ah->hw_mutex);
switch (ah->state) {
@@ -1086,10 +1087,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
for (j = 0; j < ah->num_radio; j++) {
ar = &ah->radio[j];
-
- mutex_lock(&ar->conf_mutex);
ath12k_core_halt(ar);
- mutex_unlock(&ar->conf_mutex);
}
break;
@@ -1110,6 +1108,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
}
mutex_unlock(&ah->hw_mutex);
+ wiphy_unlock(ah->hw->wiphy);
}
complete(&ab->driver_recovery);
@@ -1188,6 +1187,7 @@ static void ath12k_core_reset(struct work_struct *work)
ab->is_reset = true;
atomic_set(&ab->recovery_count, 0);
+ ath12k_coredump_collect(ab);
ath12k_core_pre_reconfigure_recovery(ab);
ath12k_core_post_reconfigure_recovery(ab);
@@ -1312,6 +1312,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
INIT_WORK(&ab->restart_work, ath12k_core_restart);
INIT_WORK(&ab->reset_work, ath12k_core_reset);
INIT_WORK(&ab->rfkill_work, ath12k_rfkill_work);
+ INIT_WORK(&ab->dump_work, ath12k_coredump_upload);
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
init_completion(&ab->htc_suspend);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 7f2e9a9b4097..3bf31ee5b9fa 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -30,6 +30,7 @@
#include "acpi.h"
#include "wow.h"
#include "debugfs_htt_stats.h"
+#include "coredump.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -94,6 +95,14 @@ static inline enum wme_ac ath12k_tid_to_ac(u32 tid)
WME_AC_VO);
}
+static inline u64 ath12k_le32hilo_to_u64(__le32 hi, __le32 lo)
+{
+ u64 hi64 = le32_to_cpu(hi);
+ u64 lo64 = le32_to_cpu(lo);
+
+ return (hi64 << 32) | lo64;
+}
+
enum ath12k_skb_flags {
ATH12K_SKB_HW_80211_ENCAP = BIT(0),
ATH12K_SKB_CIPHER_SET = BIT(1),
@@ -220,8 +229,9 @@ struct ath12k_tx_conf {
};
struct ath12k_key_conf {
- bool changed;
enum set_key_cmd cmd;
+ struct list_head list;
+ struct ieee80211_sta *sta;
struct ieee80211_key_conf *key;
};
@@ -238,10 +248,8 @@ struct ath12k_rekey_data {
bool enable_offload;
};
-struct ath12k_vif {
+struct ath12k_link_vif {
u32 vdev_id;
- enum wmi_vdev_type vdev_type;
- enum wmi_vdev_subtype vdev_subtype;
u32 beacon_interval;
u32 dtim_period;
u16 ast_hash;
@@ -251,13 +259,38 @@ struct ath12k_vif {
u8 search_type;
struct ath12k *ar;
- struct ieee80211_vif *vif;
int bank_id;
u8 vdev_id_check_en;
struct wmi_wmm_params_all_arg wmm_params;
struct list_head list;
+
+ bool is_created;
+ bool is_started;
+ bool is_up;
+ u8 bssid[ETH_ALEN];
+ struct cfg80211_bitrate_mask bitrate_mask;
+ struct delayed_work connection_loss_work;
+ int num_legacy_stations;
+ int rtscts_prot_mode;
+ int txpower;
+ bool rsnie_present;
+ bool wpaie_present;
+ struct ieee80211_chanctx_conf chanctx;
+ u8 vdev_stats_id;
+ u32 punct_bitmap;
+ u8 link_id;
+ struct ath12k_vif *ahvif;
+ struct ath12k_rekey_data rekey_data;
+};
+
+struct ath12k_vif {
+ enum wmi_vdev_type vdev_type;
+ enum wmi_vdev_subtype vdev_subtype;
+ struct ieee80211_vif *vif;
+ struct ath12k_hw *ah;
+
union {
struct {
u32 uapsd;
@@ -275,25 +308,16 @@ struct ath12k_vif {
} ap;
} u;
- bool is_created;
- bool is_started;
- bool is_up;
u32 aid;
- u8 bssid[ETH_ALEN];
- struct cfg80211_bitrate_mask bitrate_mask;
- struct delayed_work connection_loss_work;
- int num_legacy_stations;
- int rtscts_prot_mode;
- int txpower;
- bool rsnie_present;
- bool wpaie_present;
u32 key_cipher;
u8 tx_encap_type;
- u8 vdev_stats_id;
- u32 punct_bitmap;
bool ps;
- struct ath12k_vif_cache *cache;
- struct ath12k_rekey_data rekey_data;
+
+ struct ath12k_link_vif deflink;
+ struct ath12k_link_vif __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+ struct ath12k_vif_cache *cache[IEEE80211_MLD_MAX_NUM_LINKS];
+ /* indicates bitmap of link vif created in FW */
+ u16 links_map;
/* Must be last - ends in a flexible-array member.
*
@@ -306,7 +330,7 @@ struct ath12k_vif {
struct ath12k_vif_iter {
u32 vdev_id;
struct ath12k *ar;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
};
#define HAL_AST_IDX_INVALID 0xFFFF
@@ -441,27 +465,36 @@ struct ath12k_wbm_tx_stats {
u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
};
-struct ath12k_sta {
- struct ath12k_vif *arvif;
+struct ath12k_link_sta {
+ struct ath12k_link_vif *arvif;
+ struct ath12k_sta *ahsta;
/* the following are protected by ar->data_lock */
u32 changed; /* IEEE80211_RC_* */
u32 bw;
u32 nss;
u32 smps;
- enum hal_pn_type pn_type;
- struct work_struct update_wk;
+ struct wiphy_work update_wk;
struct rate_info txrate;
struct rate_info last_txrate;
u64 rx_duration;
u64 tx_duration;
u8 rssi_comb;
+ u8 link_id;
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_wbm_tx_stats *wbm_tx_stats;
u32 bw_prev;
};
+struct ath12k_sta {
+ enum hal_pn_type pn_type;
+ struct ath12k_link_sta deflink;
+ struct ath12k_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+ /* indicates bitmap of link sta created in FW */
+ u16 links_map;
+};
+
#define ATH12K_MIN_5G_FREQ 4150
#define ATH12K_MIN_6G_FREQ 5925
#define ATH12K_MAX_6G_FREQ 7115
@@ -561,13 +594,9 @@ struct ath12k {
u32 chan_tx_pwr;
u32 num_stations;
u32 max_num_stations;
- bool monitor_present;
- /* To synchronize concurrent synchronous mac80211 callback operations,
- * concurrent debugfs configuration and concurrent FW statistics events.
- */
- struct mutex conf_mutex;
+
/* protects the radio specific data like debug stats, ppdu_stats_info stats,
- * vdev_stop_status info, scan data, ath12k_sta info, ath12k_vif info,
+ * vdev_stop_status info, scan data, ath12k_sta info, ath12k_link_vif info,
* channel context data, survey info, test mode data.
*/
spinlock_t data_lock;
@@ -666,6 +695,7 @@ struct ath12k_hw {
enum ath12k_hw_state state;
bool regd_updated;
bool use_6ghz_regd;
+
u8 num_radio;
/* Keep last */
@@ -782,6 +812,10 @@ struct ath12k_base {
/* HW channel counters frequency value in hertz common to all MACs */
u32 cc_freq_hz;
+ struct ath12k_dump_file_data *dump_data;
+ size_t ath12k_coredump_len;
+ struct work_struct dump_work;
+
struct ath12k_htc htc;
struct ath12k_dp dp;
@@ -1024,16 +1058,26 @@ static inline struct ath12k_skb_rxcb *ATH12K_SKB_RXCB(struct sk_buff *skb)
return (struct ath12k_skb_rxcb *)skb->cb;
}
-static inline struct ath12k_vif *ath12k_vif_to_arvif(struct ieee80211_vif *vif)
+static inline struct ath12k_vif *ath12k_vif_to_ahvif(struct ieee80211_vif *vif)
{
return (struct ath12k_vif *)vif->drv_priv;
}
-static inline struct ath12k_sta *ath12k_sta_to_arsta(struct ieee80211_sta *sta)
+static inline struct ath12k_sta *ath12k_sta_to_ahsta(struct ieee80211_sta *sta)
{
return (struct ath12k_sta *)sta->drv_priv;
}
+static inline struct ieee80211_sta *ath12k_ahsta_to_sta(struct ath12k_sta *ahsta)
+{
+ return container_of((void *)ahsta, struct ieee80211_sta, drv_priv);
+}
+
+static inline struct ieee80211_vif *ath12k_ahvif_to_vif(struct ath12k_vif *ahvif)
+{
+ return container_of((void *)ahvif, struct ieee80211_vif, drv_priv);
+}
+
static inline struct ath12k *ath12k_ab_to_ar(struct ath12k_base *ab,
int mac_id)
{
diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c
new file mode 100644
index 000000000000..72d675d15e64
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/coredump.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#include <linux/devcoredump.h>
+#include "hif.h"
+#include "coredump.h"
+#include "debug.h"
+
+enum
+ath12k_fw_crash_dump_type ath12k_coredump_get_dump_type(enum ath12k_qmi_target_mem type)
+{
+ enum ath12k_fw_crash_dump_type dump_type;
+
+ switch (type) {
+ case HOST_DDR_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_REMOTE_MEM_DATA;
+ break;
+ case M3_DUMP_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_M3_DUMP;
+ break;
+ case PAGEABLE_MEM_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_PAGEABLE_DATA;
+ break;
+ case BDF_MEM_REGION_TYPE:
+ case CALDB_MEM_REGION_TYPE:
+ dump_type = FW_CRASH_DUMP_NONE;
+ break;
+ default:
+ dump_type = FW_CRASH_DUMP_TYPE_MAX;
+ break;
+ }
+
+ return dump_type;
+}
+
+void ath12k_coredump_upload(struct work_struct *work)
+{
+ struct ath12k_base *ab = container_of(work, struct ath12k_base, dump_work);
+
+ ath12k_info(ab, "Uploading coredump\n");
+ /* dev_coredumpv() takes ownership of the buffer */
+ dev_coredumpv(ab->dev, ab->dump_data, ab->ath12k_coredump_len, GFP_KERNEL);
+ ab->dump_data = NULL;
+}
+
+void ath12k_coredump_collect(struct ath12k_base *ab)
+{
+ ath12k_hif_coredump_download(ab);
+}
diff --git a/drivers/net/wireless/ath/ath12k/coredump.h b/drivers/net/wireless/ath/ath12k/coredump.h
new file mode 100644
index 000000000000..5d6003b1c12d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath12k/coredump.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#ifndef _ATH12K_COREDUMP_H_
+#define _ATH12K_COREDUMP_H_
+
+#define ATH12K_FW_CRASH_DUMP_V2 2
+
+enum ath12k_fw_crash_dump_type {
+ FW_CRASH_DUMP_PAGING_DATA,
+ FW_CRASH_DUMP_RDDM_DATA,
+ FW_CRASH_DUMP_REMOTE_MEM_DATA,
+ FW_CRASH_DUMP_PAGEABLE_DATA,
+ FW_CRASH_DUMP_M3_DUMP,
+ FW_CRASH_DUMP_NONE,
+
+ /* keep last */
+ FW_CRASH_DUMP_TYPE_MAX,
+};
+
+#define COREDUMP_TLV_HDR_SIZE 8
+
+struct ath12k_tlv_dump_data {
+ /* see ath11k_fw_crash_dump_type above */
+ __le32 type;
+
+ /* in bytes */
+ __le32 tlv_len;
+
+ /* pad to 32-bit boundaries as needed */
+ u8 tlv_data[];
+} __packed;
+
+struct ath12k_dump_file_data {
+ /* "ATH12K-FW-DUMP" */
+ char df_magic[16];
+ /* total dump len in bytes */
+ __le32 len;
+ /* file dump version */
+ __le32 version;
+ /* pci device id */
+ __le32 chip_id;
+ /* qrtr instance id */
+ __le32 qrtr_id;
+ /* pci domain id */
+ __le32 bus_id;
+ guid_t guid;
+ /* time-of-day stamp */
+ __le64 tv_sec;
+ /* time-of-day stamp, nano-seconds */
+ __le64 tv_nsec;
+ /* room for growth w/out changing binary format */
+ u8 unused[128];
+ u8 data[];
+} __packed;
+
+#ifdef CONFIG_ATH12K_COREDUMP
+enum ath12k_fw_crash_dump_type ath12k_coredump_get_dump_type
+ (enum ath12k_qmi_target_mem type);
+void ath12k_coredump_upload(struct work_struct *work);
+void ath12k_coredump_collect(struct ath12k_base *ab);
+#else
+static inline enum ath12k_fw_crash_dump_type ath12k_coredump_get_dump_type
+ (enum ath12k_qmi_target_mem type)
+{
+ return FW_CRASH_DUMP_TYPE_MAX;
+}
+
+static inline void ath12k_coredump_upload(struct work_struct *work)
+{
+}
+
+static inline void ath12k_coredump_collect(struct ath12k_base *ab)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index 2a977c36af00..d4b32d1a431c 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -15,14 +15,14 @@ static ssize_t ath12k_write_simulate_radar(struct file *file,
struct ath12k *ar = file->private_data;
int ret;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_simulate_radar(ar);
if (ret)
goto exit;
ret = count;
exit:
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
index f1b7e74aefe4..c9980c0193d1 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
@@ -12,8 +12,8 @@
#include "dp_rx.h"
static u32
-print_array_to_buf(u8 *buf, u32 offset, const char *header,
- const __le32 *array, u32 array_len, const char *footer)
+print_array_to_buf_index(u8 *buf, u32 offset, const char *header, u32 stats_index,
+ const __le32 *array, u32 array_len, const char *footer)
{
int index = 0;
u8 i;
@@ -26,7 +26,7 @@ print_array_to_buf(u8 *buf, u32 offset, const char *header,
for (i = 0; i < array_len; i++) {
index += scnprintf(buf + offset + index,
(ATH12K_HTT_STATS_BUF_SIZE - offset) - index,
- " %u:%u,", i, le32_to_cpu(array[i]));
+ " %u:%u,", stats_index++, le32_to_cpu(array[i]));
}
/* To overwrite the last trailing comma */
index--;
@@ -40,6 +40,54 @@ print_array_to_buf(u8 *buf, u32 offset, const char *header,
return index;
}
+static u32
+print_array_to_buf(u8 *buf, u32 offset, const char *header,
+ const __le32 *array, u32 array_len, const char *footer)
+{
+ return print_array_to_buf_index(buf, offset, header, 0, array, array_len,
+ footer);
+}
+
+static const char *ath12k_htt_be_tx_rx_ru_size_to_str(u8 ru_size)
+{
+ switch (ru_size) {
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_26:
+ return "26";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52:
+ return "52";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52_26:
+ return "52+26";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106:
+ return "106";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106_26:
+ return "106+26";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_242:
+ return "242";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484:
+ return "484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484_242:
+ return "484+242";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996:
+ return "996";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484:
+ return "996+484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484_242:
+ return "996+484+242";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2:
+ return "996x2";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2_484:
+ return "996x2+484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3:
+ return "996x3";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3_484:
+ return "996x3+484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x4:
+ return "996x4";
+ default:
+ return "unknown";
+ }
+}
+
static void
htt_print_tx_pdev_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
struct debug_htt_stats_req *stats_req)
@@ -1447,6 +1495,1207 @@ ath12k_htt_print_tx_de_compl_stats_tlv(const void *tag_buf, u16 tag_len,
stats_req->buf_len = len;
}
+static void
+ath12k_htt_print_tx_selfgen_cmn_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_cmn_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_CMN_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "su_bar = %u\n",
+ le32_to_cpu(htt_stats_buf->su_bar));
+ len += scnprintf(buf + len, buf_len - len, "rts = %u\n",
+ le32_to_cpu(htt_stats_buf->rts));
+ len += scnprintf(buf + len, buf_len - len, "cts2self = %u\n",
+ le32_to_cpu(htt_stats_buf->cts2self));
+ len += scnprintf(buf + len, buf_len - len, "qos_null = %u\n",
+ le32_to_cpu(htt_stats_buf->qos_null));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_1 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_1));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_2 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_2));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_3 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_3));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_4 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_4));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_5 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_5));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_6 = %u\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_6));
+ len += scnprintf(buf + len, buf_len - len, "delayed_bar_7 = %u\n\n",
+ le32_to_cpu(htt_stats_buf->delayed_bar_7));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ac_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ac_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndp));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndp));
+ len += print_array_to_buf_index(buf, len, "ac_mu_mimo_brpollX_tried = ", 1,
+ htt_stats_buf->ac_mu_mimo_brpoll,
+ ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ax_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ax_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndp));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndp));
+ len += print_array_to_buf_index(buf, len, "ax_mu_mimo_brpollX_tried = ", 1,
+ htt_stats_buf->ax_mu_mimo_brpoll,
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_basic_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_basic_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_total_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_ulmumimo_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_bsr_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_bsr_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_bar_trigger));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_rts_trigger = %u\n\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_rts_trigger));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_be_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_be_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_BE_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_queued = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp_queued));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp));
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpollX_queued = ", 1,
+ htt_stats_buf->be_mu_mimo_brpoll_queued,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpollX_tried = ", 1,
+ htt_stats_buf->be_mu_mimo_brpoll,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf(buf, len, "be_ul_mumimo_trigger = ",
+ htt_stats_buf->be_ul_mumimo_trigger,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "be_basic_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_basic_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_ulmumimo_total_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_ulmumimo_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_bsr_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_bsr_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_bar_trigger = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_bar_trigger));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_rts_trigger = %u\n\n",
+ le32_to_cpu(htt_stats_buf->be_mu_rts_trigger));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ac_err_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ac_err_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_ERR_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_su_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_su_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_brp1_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_brp1_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_brp2_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_brp2_err));
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_brp3_err = %u\n\n",
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_brp3_err));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ax_err_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_ax_err_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_ERR_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_su_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_su_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndp_err));
+ len += print_array_to_buf_index(buf, len, "ax_mu_mimo_brpX_err", 1,
+ htt_stats_buf->ax_mu_mimo_brp_err,
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += scnprintf(buf + len, buf_len - len, "ax_basic_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_basic_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_total_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_ulmumimo_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_bsr_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_bsr_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_bar_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_rts_trigger_err = %u\n\n",
+ le32_to_cpu(htt_stats_buf->ax_mu_rts_trigger_err));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_be_err_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_selfgen_be_err_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_BE_ERR_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndp_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndp_flushed));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "be_su_ndpa_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_su_ndpa_flushed));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndpa_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndpa_flushed));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_ndp_flushed = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_ndp_flushed));
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpX_err", 1,
+ htt_stats_buf->be_mu_mimo_brp_err,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf_index(buf, len, "be_mu_mimo_brpollX_flushed", 1,
+ htt_stats_buf->be_mu_mimo_brpoll_flushed,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1,
+ "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_num_cbf_rcvd_on_brp_err",
+ htt_stats_buf->be_mu_mimo_brp_err_num_cbf_rxd,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_ul_mumimo_trigger_err",
+ htt_stats_buf->be_ul_mumimo_trigger_err,
+ ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "be_basic_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_basic_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_ulmumimo_total_trig_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_ulmumimo_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_bsr_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_bsr_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_bar_trigger_err = %u\n",
+ le32_to_cpu(htt_stats_buf->be_mu_bar_trigger_err));
+ len += scnprintf(buf + len, buf_len - len, "be_mu_rts_trigger_err = %u\n\n",
+ le32_to_cpu(htt_stats_buf->be_mu_rts_trigger_err));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ac_sched_status_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats)
+{
+ const struct ath12k_htt_tx_selfgen_ac_sched_status_stats_tlv *htt_stats_buf =
+ tag_buf;
+ u8 *buf = stats->buf;
+ u32 len = stats->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_SELFGEN_AC_SCHED_STATUS_STATS_TLV:\n");
+ len += print_array_to_buf(buf, len, "ac_su_ndpa_sch_status",
+ htt_stats_buf->ac_su_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_su_ndp_sch_status",
+ htt_stats_buf->ac_su_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_ndpa_sch_status",
+ htt_stats_buf->ac_mu_mimo_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_ndp_sch_status",
+ htt_stats_buf->ac_mu_mimo_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_brp_sch_status",
+ htt_stats_buf->ac_mu_mimo_brp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ac_su_ndp_sch_flag_err",
+ htt_stats_buf->ac_su_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_ndp_sch_flag_err",
+ htt_stats_buf->ac_mu_mimo_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ac_mu_mimo_brp_sch_flag_err",
+ htt_stats_buf->ac_mu_mimo_brp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n\n");
+
+ stats->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_ax_sched_status_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats)
+{
+ const struct ath12k_htt_tx_selfgen_ax_sched_status_stats_tlv *htt_stats_buf =
+ tag_buf;
+ u8 *buf = stats->buf;
+ u32 len = stats->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_SELFGEN_AX_SCHED_STATUS_STATS_TLV:\n");
+ len += print_array_to_buf(buf, len, "ax_su_ndpa_sch_status",
+ htt_stats_buf->ax_su_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_su_ndp_sch_status",
+ htt_stats_buf->ax_su_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_mimo_ndpa_sch_status",
+ htt_stats_buf->ax_mu_mimo_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_mimo_ndp_sch_status",
+ htt_stats_buf->ax_mu_mimo_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_brp_sch_status",
+ htt_stats_buf->ax_mu_brp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_bar_sch_status",
+ htt_stats_buf->ax_mu_bar_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_basic_trig_sch_status",
+ htt_stats_buf->ax_basic_trig_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_su_ndp_sch_flag_err",
+ htt_stats_buf->ax_su_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_mimo_ndp_sch_flag_err",
+ htt_stats_buf->ax_mu_mimo_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_brp_sch_flag_err",
+ htt_stats_buf->ax_mu_brp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_mu_bar_sch_flag_err",
+ htt_stats_buf->ax_mu_bar_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_basic_trig_sch_flag_err",
+ htt_stats_buf->ax_basic_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ax_ulmumimo_trig_sch_status",
+ htt_stats_buf->ax_ulmumimo_trig_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "ax_ulmumimo_trig_sch_flag_err",
+ htt_stats_buf->ax_ulmumimo_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n\n");
+
+ stats->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_selfgen_be_sched_status_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats)
+{
+ const struct ath12k_htt_tx_selfgen_be_sched_status_stats_tlv *htt_stats_buf =
+ tag_buf;
+ u8 *buf = stats->buf;
+ u32 len = stats->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_SELFGEN_BE_SCHED_STATUS_STATS_TLV:\n");
+ len += print_array_to_buf(buf, len, "be_su_ndpa_sch_status",
+ htt_stats_buf->be_su_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_su_ndp_sch_status",
+ htt_stats_buf->be_su_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_ndpa_sch_status",
+ htt_stats_buf->be_mu_mimo_ndpa_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_ndp_sch_status",
+ htt_stats_buf->be_mu_mimo_ndp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_brp_sch_status",
+ htt_stats_buf->be_mu_brp_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_bar_sch_status",
+ htt_stats_buf->be_mu_bar_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_basic_trig_sch_status",
+ htt_stats_buf->be_basic_trig_sch_status,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_su_ndp_sch_flag_err",
+ htt_stats_buf->be_su_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_mimo_ndp_sch_flag_err",
+ htt_stats_buf->be_mu_mimo_ndp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_brp_sch_flag_err",
+ htt_stats_buf->be_mu_brp_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_mu_bar_sch_flag_err",
+ htt_stats_buf->be_mu_bar_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_basic_trig_sch_flag_err",
+ htt_stats_buf->be_basic_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n");
+ len += print_array_to_buf(buf, len, "be_basic_trig_sch_flag_err",
+ htt_stats_buf->be_basic_trig_sch_flag_err,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS, "\n");
+ len += print_array_to_buf(buf, len, "be_ulmumimo_trig_sch_flag_err",
+ htt_stats_buf->be_ulmumimo_trig_sch_flag_err,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS, "\n\n");
+
+ stats->buf_len = len;
+}
+
+static void
+ath12k_htt_print_stats_string_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_stats_string_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 i;
+ u16 index = 0;
+ u32 datum;
+ char data[ATH12K_HTT_MAX_STRING_LEN] = {0};
+
+ tag_len = tag_len >> 2;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_STATS_STRING_TLV:\n");
+ for (i = 0; i < tag_len; i++) {
+ datum = __le32_to_cpu(htt_stats_buf->data[i]);
+ index += scnprintf(&data[index], ATH12K_HTT_MAX_STRING_LEN - index,
+ "%.*s", 4, (char *)&datum);
+ if (index >= ATH12K_HTT_MAX_STRING_LEN)
+ break;
+ }
+ len += scnprintf(buf + len, buf_len - len, "data = %s\n\n", data);
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sring_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sring_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+ u32 avail_words;
+ u32 head_tail_ptr;
+ u32 sring_stat;
+ u32 tail_ptr;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__ring_id__arena__ep);
+ avail_words = __le32_to_cpu(htt_stats_buf->num_avail_words__num_valid_words);
+ head_tail_ptr = __le32_to_cpu(htt_stats_buf->head_ptr__tail_ptr);
+ sring_stat = __le32_to_cpu(htt_stats_buf->consumer_empty__producer_full);
+ tail_ptr = __le32_to_cpu(htt_stats_buf->prefetch_count__internal_tail_ptr);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SRING_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "ring_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_RING_ID));
+ len += scnprintf(buf + len, buf_len - len, "arena = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_ARENA));
+ len += scnprintf(buf + len, buf_len - len, "ep = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_SRING_STATS_EP));
+ len += scnprintf(buf + len, buf_len - len, "base_addr_lsb = 0x%x\n",
+ le32_to_cpu(htt_stats_buf->base_addr_lsb));
+ len += scnprintf(buf + len, buf_len - len, "base_addr_msb = 0x%x\n",
+ le32_to_cpu(htt_stats_buf->base_addr_msb));
+ len += scnprintf(buf + len, buf_len - len, "ring_size = %u\n",
+ le32_to_cpu(htt_stats_buf->ring_size));
+ len += scnprintf(buf + len, buf_len - len, "elem_size = %u\n",
+ le32_to_cpu(htt_stats_buf->elem_size));
+ len += scnprintf(buf + len, buf_len - len, "num_avail_words = %u\n",
+ u32_get_bits(avail_words,
+ ATH12K_HTT_SRING_STATS_NUM_AVAIL_WORDS));
+ len += scnprintf(buf + len, buf_len - len, "num_valid_words = %u\n",
+ u32_get_bits(avail_words,
+ ATH12K_HTT_SRING_STATS_NUM_VALID_WORDS));
+ len += scnprintf(buf + len, buf_len - len, "head_ptr = %u\n",
+ u32_get_bits(head_tail_ptr, ATH12K_HTT_SRING_STATS_HEAD_PTR));
+ len += scnprintf(buf + len, buf_len - len, "tail_ptr = %u\n",
+ u32_get_bits(head_tail_ptr, ATH12K_HTT_SRING_STATS_TAIL_PTR));
+ len += scnprintf(buf + len, buf_len - len, "consumer_empty = %u\n",
+ u32_get_bits(sring_stat,
+ ATH12K_HTT_SRING_STATS_CONSUMER_EMPTY));
+ len += scnprintf(buf + len, buf_len - len, "producer_full = %u\n",
+ u32_get_bits(head_tail_ptr,
+ ATH12K_HTT_SRING_STATS_PRODUCER_FULL));
+ len += scnprintf(buf + len, buf_len - len, "prefetch_count = %u\n",
+ u32_get_bits(tail_ptr, ATH12K_HTT_SRING_STATS_PREFETCH_COUNT));
+ len += scnprintf(buf + len, buf_len - len, "internal_tail_ptr = %u\n\n",
+ u32_get_bits(tail_ptr,
+ ATH12K_HTT_SRING_STATS_INTERNAL_TAIL_PTR));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sfm_cmn_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sfm_cmn_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CMN_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "buf_total = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_total));
+ len += scnprintf(buf + len, buf_len - len, "mem_empty = %u\n",
+ le32_to_cpu(htt_stats_buf->mem_empty));
+ len += scnprintf(buf + len, buf_len - len, "deallocate_bufs = %u\n",
+ le32_to_cpu(htt_stats_buf->deallocate_bufs));
+ len += scnprintf(buf + len, buf_len - len, "num_records = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_records));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sfm_client_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sfm_client_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CLIENT_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "client_id = %u\n",
+ le32_to_cpu(htt_stats_buf->client_id));
+ len += scnprintf(buf + len, buf_len - len, "buf_min = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_min));
+ len += scnprintf(buf + len, buf_len - len, "buf_max = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_max));
+ len += scnprintf(buf + len, buf_len - len, "buf_busy = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_busy));
+ len += scnprintf(buf + len, buf_len - len, "buf_alloc = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_alloc));
+ len += scnprintf(buf + len, buf_len - len, "buf_avail = %u\n",
+ le32_to_cpu(htt_stats_buf->buf_avail));
+ len += scnprintf(buf + len, buf_len - len, "num_users = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_users));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_sfm_client_user_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_sfm_client_user_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u16 num_elems = tag_len >> 2;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CLIENT_USER_TLV:\n");
+ len += print_array_to_buf(buf, len, "dwords_used_by_user_n",
+ htt_stats_buf->dwords_used_by_user_n,
+ num_elems, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_mu_mimo_sch_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_mu_mimo_sch_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 i;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mu_mimo_sch_posted = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_mimo_sch_posted));
+ len += scnprintf(buf + len, buf_len - len, "mu_mimo_sch_failed = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_mimo_sch_failed));
+ len += scnprintf(buf + len, buf_len - len, "mu_mimo_ppdu_posted = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_mimo_ppdu_posted));
+ len += scnprintf(buf + len, buf_len - len,
+ "\nac_mu_mimo_sch_posted_per_group_index %u (SU) = %u\n", 0,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_per_grp_sz[0]));
+ for (i = 1; i < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_sch_posted_per_group_index %u ", i);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n", i + 1,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_per_grp_sz[i]));
+ }
+
+ for (i = 0; i < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_sch_posted_per_group_index %u ",
+ i + ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n",
+ i + ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS + 1,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_grp_sz_ext[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len,
+ "\nax_mu_mimo_sch_posted_per_group_index %u (SU) = %u\n", 0,
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_per_grp_sz[0]));
+ for (i = 1; i < ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_sch_posted_per_group_index %u ", i);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n", i + 1,
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_per_grp_sz[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len,
+ "\nbe_mu_mimo_sch_posted_per_group_index %u (SU) = %u\n", 0,
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_per_grp_sz[0]));
+ for (i = 1; i < ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "be_mu_mimo_sch_posted_per_group_index %u ", i);
+ len += scnprintf(buf + len, buf_len - len,
+ "(TOTAL STREAMS = %u) = %u\n", i + 1,
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_per_grp_sz[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11ac MU_MIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len, "ac_mu_mimo_sch_nusers_");
+ len += scnprintf(buf + len, buf_len - len, "%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ac_mu_mimo_sch_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11ax MU_MIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len, "ax_mu_mimo_sch_nusers_");
+ len += scnprintf(buf + len, buf_len - len, "%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_mu_mimo_sch_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11be MU_MIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len, "be_mu_mimo_sch_nusers_");
+ len += scnprintf(buf + len, buf_len - len, "%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->be_mu_mimo_sch_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n11ax OFDMA SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_OFDMA_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ofdma_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ofdma_sch_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_basic_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_bsr_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_bsr_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_bar_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_bar_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_ofdma_brp_sch_nusers_%u = %u\n\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_ofdma_brp_nusers[i]));
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "11ax UL MUMIMO SCH STATS:\n");
+ for (i = 0; i < ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_mumimo_basic_sch_nusers_%u = %u\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_mumimo_nusers[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_ul_mumimo_brp_sch_nusers_%u = %u\n\n", i,
+ le32_to_cpu(htt_stats_buf->ax_ul_mumimo_brp_nusers[i]));
+ }
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_mumimo_grp_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_mumimo_grp_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ int j;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_MUMIMO_GRP_STATS:\n");
+ len += print_array_to_buf(buf, len,
+ "dl_mumimo_grp_tputs_observed (per bin = 300 mbps)",
+ htt_stats_buf->dl_mumimo_grp_tputs,
+ ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS, "\n");
+ len += print_array_to_buf(buf, len, "dl_mumimo_grp eligible",
+ htt_stats_buf->dl_mumimo_grp_eligible,
+ ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ, "\n");
+ len += print_array_to_buf(buf, len, "dl_mumimo_grp_ineligible",
+ htt_stats_buf->dl_mumimo_grp_ineligible,
+ ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ, "\n");
+ len += scnprintf(buf + len, buf_len - len, "dl_mumimo_grp_invalid:\n");
+ for (j = 0; j < ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ; j++) {
+ len += scnprintf(buf + len, buf_len - len, "grp_id = %u", j);
+ len += print_array_to_buf(buf, len, "",
+ htt_stats_buf->dl_mumimo_grp_invalid,
+ ATH12K_HTT_STATS_MAX_INVALID_REASON_CODE,
+ "\n");
+ }
+
+ len += print_array_to_buf(buf, len, "ul_mumimo_grp_best_grp_size",
+ htt_stats_buf->ul_mumimo_grp_best_grp_size,
+ ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ, "\n");
+ len += print_array_to_buf_index(buf, len, "ul_mumimo_grp_best_num_usrs = ", 1,
+ htt_stats_buf->ul_mumimo_grp_best_usrs,
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS, "\n");
+ len += print_array_to_buf(buf, len,
+ "ul_mumimo_grp_tputs_observed (per bin = 300 mbps)",
+ htt_stats_buf->ul_mumimo_grp_tputs,
+ ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_mpdu_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 user_index;
+ u32 tx_sched_mode;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ user_index = __le32_to_cpu(htt_stats_buf->user_index);
+ tx_sched_mode = __le32_to_cpu(htt_stats_buf->tx_sched_mode);
+
+ if (tx_sched_mode == ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC) {
+ if (!user_index)
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_MU_MIMO_AC_MPDU_STATS:\n");
+
+ if (user_index < ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_queued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_queued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_tried_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_tried_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_failed_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_failed_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdus_requeued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_requeued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_err_no_ba_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->err_no_ba_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_mpdu_underrun_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdu_underrun_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ac_mu_mimo_ampdu_underrun_usr_%u = %u\n\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->ampdu_underrun_usr));
+ }
+ }
+
+ if (tx_sched_mode == ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX) {
+ if (!user_index)
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_MU_MIMO_AX_MPDU_STATS:\n");
+
+ if (user_index < ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_queued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_queued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_tried_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_tried_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_failed_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_failed_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdus_requeued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_requeued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_err_no_ba_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->err_no_ba_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_mpdu_underrun_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdu_underrun_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_mimo_ampdu_underrun_usr_%u = %u\n\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->ampdu_underrun_usr));
+ }
+ }
+
+ if (tx_sched_mode == ATH12K_HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX) {
+ if (!user_index)
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_AX_MU_OFDMA_MPDU_STATS:\n");
+
+ if (user_index < ATH12K_HTT_TX_NUM_OFDMA_USER_STATS) {
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_queued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_queued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_tried_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_tried_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_failed_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_failed_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdus_requeued_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdus_requeued_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_err_no_ba_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->err_no_ba_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_mpdu_underrun_usr_%u = %u\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->mpdu_underrun_usr));
+ len += scnprintf(buf + len, buf_len - len,
+ "ax_mu_ofdma_ampdu_underrun_usr_%u = %u\n\n",
+ user_index,
+ le32_to_cpu(htt_stats_buf->ampdu_underrun_usr));
+ }
+ }
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_cca_stats_hist_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_cca_stats_hist_v1_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_CCA_STATS_HIST_TLV :\n");
+ len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n",
+ le32_to_cpu(htt_stats_buf->chan_num));
+ len += scnprintf(buf + len, buf_len - len, "num_records = %u\n",
+ le32_to_cpu(htt_stats_buf->num_records));
+ len += scnprintf(buf + len, buf_len - len, "valid_cca_counters_bitmap = 0x%x\n",
+ le32_to_cpu(htt_stats_buf->valid_cca_counters_bitmap));
+ len += scnprintf(buf + len, buf_len - len, "collection_interval = %u\n\n",
+ le32_to_cpu(htt_stats_buf->collection_interval));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_stats_cca_counters_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_stats_cca_counters_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_PDEV_STATS_CCA_COUNTERS_TLV:(in usec)\n");
+ len += scnprintf(buf + len, buf_len - len, "tx_frame_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->tx_frame_usec));
+ len += scnprintf(buf + len, buf_len - len, "rx_frame_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_frame_usec));
+ len += scnprintf(buf + len, buf_len - len, "rx_clear_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_clear_usec));
+ len += scnprintf(buf + len, buf_len - len, "my_rx_frame_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->my_rx_frame_usec));
+ len += scnprintf(buf + len, buf_len - len, "usec_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->usec_cnt));
+ len += scnprintf(buf + len, buf_len - len, "med_rx_idle_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->med_rx_idle_usec));
+ len += scnprintf(buf + len, buf_len - len, "med_tx_idle_global_usec = %u\n",
+ le32_to_cpu(htt_stats_buf->med_tx_idle_global_usec));
+ len += scnprintf(buf + len, buf_len - len, "cca_obss_usec = %u\n\n",
+ le32_to_cpu(htt_stats_buf->cca_obss_usec));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_obss_pd_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_obss_pd_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 i;
+ static const char *access_cat_names[ATH12K_HTT_NUM_AC_WMM] = {"best effort",
+ "background",
+ "video", "voice"};
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_OBSS_PD_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "num_spatial_reuse_tx = %u\n",
+ le32_to_cpu(htt_stats_buf->num_sr_tx_transmissions));
+ len += scnprintf(buf + len, buf_len - len,
+ "num_spatial_reuse_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_spatial_reuse_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_non_srg_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_non_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_ppdu_tried));
+ len += scnprintf(buf + len, buf_len - len, "num_non_srg_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_ppdu_success));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_ppdu_tried));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_ppdu_success));
+ len += scnprintf(buf + len, buf_len - len, "num_psr_opportunities = %u\n",
+ le32_to_cpu(htt_stats_buf->num_psr_opportunities));
+ len += scnprintf(buf + len, buf_len - len, "num_psr_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_psr_ppdu_tried));
+ len += scnprintf(buf + len, buf_len - len, "num_psr_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_psr_ppdu_success));
+ len += scnprintf(buf + len, buf_len - len, "min_duration_check_flush_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->num_obss_min_dur_check_flush_cnt));
+ len += scnprintf(buf + len, buf_len - len, "sr_ppdu_abort_flush_cnt = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_sr_ppdu_abort_flush_cnt));
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_OBSS_PD_PER_AC_STATS:\n");
+ for (i = 0; i < ATH12K_HTT_NUM_AC_WMM; i++) {
+ len += scnprintf(buf + len, buf_len - len, "Access Category %u (%s)\n",
+ i, access_cat_names[i]);
+ len += scnprintf(buf + len, buf_len - len,
+ "num_non_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_tried_per_ac[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "num_non_srg_ppdu_success = %u\n",
+ le32_to_cpu(htt_stats_buf->num_non_srg_success_ac[i]));
+ len += scnprintf(buf + len, buf_len - len, "num_srg_ppdu_tried = %u\n",
+ le32_to_cpu(htt_stats_buf->num_srg_tried_per_ac[i]));
+ len += scnprintf(buf + len, buf_len - len,
+ "num_srg_ppdu_success = %u\n\n",
+ le32_to_cpu(htt_stats_buf->num_srg_success_per_ac[i]));
+ }
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_dmac_reset_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_dmac_reset_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u64 time;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_DMAC_RESET_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "reset_count = %u\n",
+ le32_to_cpu(htt_stats_buf->reset_count));
+ time = ath12k_le32hilo_to_u64(htt_stats_buf->reset_time_hi_ms,
+ htt_stats_buf->reset_time_lo_ms);
+ len += scnprintf(buf + len, buf_len - len, "reset_time_ms = %llu\n", time);
+
+ time = ath12k_le32hilo_to_u64(htt_stats_buf->disengage_time_hi_ms,
+ htt_stats_buf->disengage_time_lo_ms);
+ len += scnprintf(buf + len, buf_len - len, "disengage_time_ms = %llu\n", time);
+
+ time = ath12k_le32hilo_to_u64(htt_stats_buf->engage_time_hi_ms,
+ htt_stats_buf->engage_time_lo_ms);
+ len += scnprintf(buf + len, buf_len - len, "engage_time_ms = %llu\n", time);
+
+ len += scnprintf(buf + len, buf_len - len, "disengage_count = %u\n",
+ le32_to_cpu(htt_stats_buf->disengage_count));
+ len += scnprintf(buf + len, buf_len - len, "engage_count = %u\n",
+ le32_to_cpu(htt_stats_buf->engage_count));
+ len += scnprintf(buf + len, buf_len - len, "drain_dest_ring_mask = 0x%x\n\n",
+ le32_to_cpu(htt_stats_buf->drain_dest_ring_mask));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_pdev_sched_algo_ofdma_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_sched_algo_ofdma_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_SCHED_ALGO_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_enabled_count",
+ htt_stats_buf->rate_based_dlofdma_enabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_disabled_count",
+ htt_stats_buf->rate_based_dlofdma_disabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_probing_count",
+ htt_stats_buf->rate_based_dlofdma_disabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "rate_based_dlofdma_monitoring_count",
+ htt_stats_buf->rate_based_dlofdma_monitor_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "chan_acc_lat_based_dlofdma_enabled_count",
+ htt_stats_buf->chan_acc_lat_based_dlofdma_enabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "chan_acc_lat_based_dlofdma_disabled_count",
+ htt_stats_buf->chan_acc_lat_based_dlofdma_disabled_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "chan_acc_lat_based_dlofdma_monitoring_count",
+ htt_stats_buf->chan_acc_lat_based_dlofdma_monitor_cnt,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "downgrade_to_dl_su_ru_alloc_fail",
+ htt_stats_buf->downgrade_to_dl_su_ru_alloc_fail,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "candidate_list_single_user_disable_ofdma",
+ htt_stats_buf->candidate_list_single_user_disable_ofdma,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dl_cand_list_dropped_high_ul_qos_weight",
+ htt_stats_buf->dl_cand_list_dropped_high_ul_qos_weight,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "ax_dlofdma_disabled_due_to_pipelining",
+ htt_stats_buf->ax_dlofdma_disabled_due_to_pipelining,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dlofdma_disabled_su_only_eligible",
+ htt_stats_buf->dlofdma_disabled_su_only_eligible,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dlofdma_disabled_consec_no_mpdus_tried",
+ htt_stats_buf->dlofdma_disabled_consec_no_mpdus_tried,
+ ATH12K_HTT_NUM_AC_WMM, "\n");
+ len += print_array_to_buf(buf, len, "dlofdma_disabled_consec_no_mpdus_success",
+ htt_stats_buf->dlofdma_disabled_consec_no_mpdus_success,
+ ATH12K_HTT_NUM_AC_WMM, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_pdev_rate_stats_be_ofdma_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_pdev_rate_stats_be_ofdma_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+ u8 i;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len,
+ "HTT_TX_PDEV_RATE_STATS_BE_OFDMA_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "be_ofdma_tx_ldpc = %u\n",
+ le32_to_cpu(htt_stats_buf->be_ofdma_tx_ldpc));
+ len += print_array_to_buf(buf, len, "be_ofdma_tx_mcs",
+ htt_stats_buf->be_ofdma_tx_mcs,
+ ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS, "\n");
+ len += print_array_to_buf(buf, len, "be_ofdma_eht_sig_mcs",
+ htt_stats_buf->be_ofdma_eht_sig_mcs,
+ ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS, "\n");
+ len += scnprintf(buf + len, buf_len - len, "be_ofdma_tx_ru_size = ");
+ for (i = 0; i < ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %s:%u ",
+ ath12k_htt_be_tx_rx_ru_size_to_str(i),
+ le32_to_cpu(htt_stats_buf->be_ofdma_tx_ru_size[i]));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += print_array_to_buf_index(buf, len, "be_ofdma_tx_nss = ", 1,
+ htt_stats_buf->be_ofdma_tx_nss,
+ ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS,
+ "\n");
+ len += print_array_to_buf(buf, len, "be_ofdma_tx_bw",
+ htt_stats_buf->be_ofdma_tx_bw,
+ ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS, "\n");
+ for (i = 0; i < ATH12K_HTT_TX_PDEV_NUM_GI_CNTRS; i++) {
+ len += scnprintf(buf + len, buf_len - len,
+ "be_ofdma_tx_gi[%u]", i);
+ len += print_array_to_buf(buf, len, "", htt_stats_buf->gi[i],
+ ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS, "\n");
+ }
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ stats_req->buf_len = len;
+}
+
static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
u16 tag, u16 len, const void *tag_buf,
void *user_data)
@@ -1552,6 +2801,83 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
case HTT_STATS_TX_DE_COMPL_STATS_TAG:
ath12k_htt_print_tx_de_compl_stats_tlv(tag_buf, len, stats_req);
break;
+ case HTT_STATS_TX_SELFGEN_CMN_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_cmn_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AC_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ac_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AX_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ax_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_BE_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_be_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AC_ERR_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ac_err_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AX_ERR_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ax_err_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_BE_ERR_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_be_err_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AC_SCHED_STATUS_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ac_sched_status_stats_tlv(tag_buf, len,
+ stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_AX_SCHED_STATUS_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_ax_sched_status_stats_tlv(tag_buf, len,
+ stats_req);
+ break;
+ case HTT_STATS_TX_SELFGEN_BE_SCHED_STATUS_STATS_TAG:
+ ath12k_htt_print_tx_selfgen_be_sched_status_stats_tlv(tag_buf, len,
+ stats_req);
+ break;
+ case HTT_STATS_STRING_TAG:
+ ath12k_htt_print_stats_string_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SRING_STATS_TAG:
+ ath12k_htt_print_sring_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SFM_CMN_TAG:
+ ath12k_htt_print_sfm_cmn_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SFM_CLIENT_TAG:
+ ath12k_htt_print_sfm_client_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SFM_CLIENT_USER_TAG:
+ ath12k_htt_print_sfm_client_user_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG:
+ ath12k_htt_print_tx_pdev_mu_mimo_sch_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_MUMIMO_GRP_STATS_TAG:
+ ath12k_htt_print_tx_pdev_mumimo_grp_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_MPDU_STATS_TAG:
+ ath12k_htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_CCA_1SEC_HIST_TAG:
+ case HTT_STATS_PDEV_CCA_100MSEC_HIST_TAG:
+ case HTT_STATS_PDEV_CCA_STAT_CUMULATIVE_TAG:
+ ath12k_htt_print_pdev_cca_stats_hist_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_CCA_COUNTERS_TAG:
+ ath12k_htt_print_pdev_stats_cca_counters_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_OBSS_PD_TAG:
+ ath12k_htt_print_pdev_obss_pd_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_DMAC_RESET_STATS_TAG:
+ ath12k_htt_print_dmac_reset_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG:
+ ath12k_htt_print_pdev_sched_algo_ofdma_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_TX_PDEV_RATE_STATS_BE_OFDMA_TAG:
+ ath12k_htt_print_tx_pdev_rate_stats_be_ofdma_tlv(tag_buf, len, stats_req);
+ break;
default:
break;
}
@@ -1627,9 +2953,9 @@ static ssize_t ath12k_read_htt_stats_type(struct file *file,
char buf[32];
size_t len;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
type = ar->debug.htt_stats.type;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
len = scnprintf(buf, sizeof(buf), "%u\n", type);
@@ -1662,7 +2988,7 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file,
type >= ATH12K_DBG_HTT_NUM_EXT_STATS)
return -EINVAL;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ar->debug.htt_stats.type = type;
ar->debug.htt_stats.cfg_param[0] = cfg_param[0];
@@ -1670,7 +2996,7 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file,
ar->debug.htt_stats.cfg_param[2] = cfg_param[2];
ar->debug.htt_stats.cfg_param[3] = cfg_param[3];
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return count;
}
@@ -1691,7 +3017,7 @@ static int ath12k_debugfs_htt_stats_req(struct ath12k *ar)
int ret, pdev_id;
struct htt_ext_stats_cfg_params cfg_params = { 0 };
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
init_completion(&stats_req->htt_stats_rcvd);
@@ -1741,7 +3067,7 @@ static int ath12k_open_htt_stats(struct inode *inode,
if (type == ATH12K_DBG_HTT_EXT_STATS_RESET)
return -EPERM;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
if (ah->state != ATH12K_HW_STATE_ON) {
ret = -ENETDOWN;
@@ -1776,14 +3102,14 @@ static int ath12k_open_htt_stats(struct inode *inode,
file->private_data = stats_req;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return 0;
out:
kfree(stats_req);
ar->debug.htt_stats.stats_req = NULL;
err_unlock:
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
@@ -1793,10 +3119,10 @@ static int ath12k_release_htt_stats(struct inode *inode,
{
struct ath12k *ar = inode->i_private;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
kfree(file->private_data);
ar->debug.htt_stats.stats_req = NULL;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return 0;
}
@@ -1840,7 +3166,7 @@ static ssize_t ath12k_write_htt_stats_reset(struct file *file,
type == ATH12K_DBG_HTT_EXT_STATS_RESET)
return -E2BIG;
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
cfg_params.cfg0 = HTT_STAT_DEFAULT_RESET_START_OFFSET;
param_pos = (type >> 5) + 1;
@@ -1866,12 +3192,12 @@ static ssize_t ath12k_write_htt_stats_reset(struct file *file,
0ULL);
if (ret) {
ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
ar->debug.htt_stats.reset = type;
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return count;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
index d52b26b23e65..ac86cab234ec 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
@@ -123,12 +123,21 @@ struct ath12k_htt_extd_stats_msg {
/* htt_dbg_ext_stats_type */
enum ath12k_dbg_htt_ext_stats_type {
- ATH12K_DBG_HTT_EXT_STATS_RESET = 0,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_TX = 1,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5,
- ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM = 6,
- ATH12K_DBG_HTT_EXT_STATS_TX_DE_INFO = 8,
+ ATH12K_DBG_HTT_EXT_STATS_RESET = 0,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX = 1,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM = 6,
+ ATH12K_DBG_HTT_EXT_STATS_TX_DE_INFO = 8,
+ ATH12K_DBG_HTT_EXT_STATS_TX_SELFGEN_INFO = 12,
+ ATH12K_DBG_HTT_EXT_STATS_SRNG_INFO = 15,
+ ATH12K_DBG_HTT_EXT_STATS_SFM_INFO = 16,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_MU = 17,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_CCA_STATS = 19,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23,
+ ATH12K_DBG_HTT_EXT_STATS_SOC_ERROR = 45,
+ ATH12K_DBG_HTT_EXT_STATS_PDEV_SCHED_ALGO = 49,
+ ATH12K_DBG_HTT_EXT_STATS_MANDATORY_MUOFDMA = 51,
/* keep this last */
ATH12K_DBG_HTT_NUM_EXT_STATS,
@@ -139,6 +148,7 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_TX_PDEV_UNDERRUN_TAG = 1,
HTT_STATS_TX_PDEV_SIFS_TAG = 2,
HTT_STATS_TX_PDEV_FLUSH_TAG = 3,
+ HTT_STATS_STRING_TAG = 5,
HTT_STATS_TX_TQM_GEN_MPDU_TAG = 11,
HTT_STATS_TX_TQM_LIST_MPDU_TAG = 12,
HTT_STATS_TX_TQM_LIST_MPDU_CNT_TAG = 13,
@@ -151,22 +161,47 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_TX_DE_ENQUEUE_PACKETS_TAG = 21,
HTT_STATS_TX_DE_ENQUEUE_DISCARD_TAG = 22,
HTT_STATS_TX_DE_CMN_TAG = 23,
+ HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG = 25,
+ HTT_STATS_SFM_CMN_TAG = 26,
+ HTT_STATS_SRING_STATS_TAG = 27,
HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG = 36,
HTT_STATS_TX_SCHED_CMN_TAG = 37,
HTT_STATS_SCHED_TXQ_CMD_POSTED_TAG = 39,
+ HTT_STATS_SFM_CLIENT_USER_TAG = 41,
+ HTT_STATS_SFM_CLIENT_TAG = 42,
HTT_STATS_TX_TQM_ERROR_STATS_TAG = 43,
HTT_STATS_SCHED_TXQ_CMD_REAPED_TAG = 44,
+ HTT_STATS_TX_SELFGEN_AC_ERR_STATS_TAG = 46,
+ HTT_STATS_TX_SELFGEN_CMN_STATS_TAG = 47,
+ HTT_STATS_TX_SELFGEN_AC_STATS_TAG = 48,
+ HTT_STATS_TX_SELFGEN_AX_STATS_TAG = 49,
+ HTT_STATS_TX_SELFGEN_AX_ERR_STATS_TAG = 50,
HTT_STATS_HW_INTR_MISC_TAG = 54,
HTT_STATS_HW_PDEV_ERRS_TAG = 56,
HTT_STATS_TX_DE_COMPL_STATS_TAG = 65,
HTT_STATS_WHAL_TX_TAG = 66,
HTT_STATS_TX_PDEV_SIFS_HIST_TAG = 67,
+ HTT_STATS_PDEV_CCA_1SEC_HIST_TAG = 70,
+ HTT_STATS_PDEV_CCA_100MSEC_HIST_TAG = 71,
+ HTT_STATS_PDEV_CCA_STAT_CUMULATIVE_TAG = 72,
+ HTT_STATS_PDEV_CCA_COUNTERS_TAG = 73,
+ HTT_STATS_TX_PDEV_MPDU_STATS_TAG = 74,
HTT_STATS_SCHED_TXQ_SCHED_ORDER_SU_TAG = 86,
HTT_STATS_SCHED_TXQ_SCHED_INELIGIBILITY_TAG = 87,
+ HTT_STATS_PDEV_OBSS_PD_TAG = 88,
HTT_STATS_HW_WAR_TAG = 89,
HTT_STATS_SCHED_TXQ_SUPERCYCLE_TRIGGER_TAG = 100,
HTT_STATS_PDEV_CTRL_PATH_TX_STATS_TAG = 102,
+ HTT_STATS_TX_SELFGEN_AC_SCHED_STATUS_STATS_TAG = 111,
+ HTT_STATS_TX_SELFGEN_AX_SCHED_STATUS_STATS_TAG = 112,
HTT_STATS_MU_PPDU_DIST_TAG = 129,
+ HTT_STATS_TX_PDEV_MUMIMO_GRP_STATS_TAG = 130,
+ HTT_STATS_TX_PDEV_RATE_STATS_BE_OFDMA_TAG = 135,
+ HTT_STATS_TX_SELFGEN_BE_ERR_STATS_TAG = 137,
+ HTT_STATS_TX_SELFGEN_BE_STATS_TAG = 138,
+ HTT_STATS_TX_SELFGEN_BE_SCHED_STATUS_STATS_TAG = 139,
+ HTT_STATS_DMAC_RESET_STATS_TAG = 155,
+ HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG = 165,
HTT_STATS_MAX_TAG,
};
@@ -690,4 +725,401 @@ struct ath12k_htt_tx_de_compl_stats_tlv {
__le32 tqm_bypass_frame;
} __packed;
+enum ath12k_htt_tx_mumimo_grp_invalid_reason_code_stats {
+ ATH12K_HTT_TX_MUMIMO_GRP_VALID,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_NUM_MU_USERS_EXCEEDED_MU_MAX_USERS,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_SCHED_ALGO_NOT_MU_COMPATIBLE_GID,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_NON_PRIMARY_GRP,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_ZERO_CANDIDATES,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_MORE_CANDIDATES,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_GROUP_SIZE_EXCEED_NSS,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_GROUP_INELIGIBLE,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_GROUP_EFF_MU_TPUT_OMBPS,
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_MAX_REASON_CODE,
+};
+
+#define ATH12K_HTT_NUM_AC_WMM 0x4
+#define ATH12K_HTT_MAX_NUM_SBT_INTR 4
+#define ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS 4
+#define ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS 8
+#define ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS 8
+#define ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS 7
+#define ATH12K_HTT_TX_NUM_OFDMA_USER_STATS 74
+#define ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS 8
+#define ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ 8
+#define ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS 10
+
+#define ATH12K_HTT_STATS_MAX_INVALID_REASON_CODE \
+ ATH12K_HTT_TX_MUMIMO_GRP_INVALID_MAX_REASON_CODE
+#define ATH12K_HTT_TX_NUM_MUMIMO_GRP_INVALID_WORDS \
+ (ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ * ATH12K_HTT_STATS_MAX_INVALID_REASON_CODE)
+
+struct ath12k_htt_tx_selfgen_cmn_stats_tlv {
+ __le32 mac_id__word;
+ __le32 su_bar;
+ __le32 rts;
+ __le32 cts2self;
+ __le32 qos_null;
+ __le32 delayed_bar_1;
+ __le32 delayed_bar_2;
+ __le32 delayed_bar_3;
+ __le32 delayed_bar_4;
+ __le32 delayed_bar_5;
+ __le32 delayed_bar_6;
+ __le32 delayed_bar_7;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ac_stats_tlv {
+ __le32 ac_su_ndpa;
+ __le32 ac_su_ndp;
+ __le32 ac_mu_mimo_ndpa;
+ __le32 ac_mu_mimo_ndp;
+ __le32 ac_mu_mimo_brpoll[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS - 1];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ax_stats_tlv {
+ __le32 ax_su_ndpa;
+ __le32 ax_su_ndp;
+ __le32 ax_mu_mimo_ndpa;
+ __le32 ax_mu_mimo_ndp;
+ __le32 ax_mu_mimo_brpoll[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS - 1];
+ __le32 ax_basic_trigger;
+ __le32 ax_bsr_trigger;
+ __le32 ax_mu_bar_trigger;
+ __le32 ax_mu_rts_trigger;
+ __le32 ax_ulmumimo_trigger;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_be_stats_tlv {
+ __le32 be_su_ndpa;
+ __le32 be_su_ndp;
+ __le32 be_mu_mimo_ndpa;
+ __le32 be_mu_mimo_ndp;
+ __le32 be_mu_mimo_brpoll[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_basic_trigger;
+ __le32 be_bsr_trigger;
+ __le32 be_mu_bar_trigger;
+ __le32 be_mu_rts_trigger;
+ __le32 be_ulmumimo_trigger;
+ __le32 be_su_ndpa_queued;
+ __le32 be_su_ndp_queued;
+ __le32 be_mu_mimo_ndpa_queued;
+ __le32 be_mu_mimo_ndp_queued;
+ __le32 be_mu_mimo_brpoll_queued[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_ul_mumimo_trigger[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ac_err_stats_tlv {
+ __le32 ac_su_ndp_err;
+ __le32 ac_su_ndpa_err;
+ __le32 ac_mu_mimo_ndpa_err;
+ __le32 ac_mu_mimo_ndp_err;
+ __le32 ac_mu_mimo_brp1_err;
+ __le32 ac_mu_mimo_brp2_err;
+ __le32 ac_mu_mimo_brp3_err;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ax_err_stats_tlv {
+ __le32 ax_su_ndp_err;
+ __le32 ax_su_ndpa_err;
+ __le32 ax_mu_mimo_ndpa_err;
+ __le32 ax_mu_mimo_ndp_err;
+ __le32 ax_mu_mimo_brp_err[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS - 1];
+ __le32 ax_basic_trigger_err;
+ __le32 ax_bsr_trigger_err;
+ __le32 ax_mu_bar_trigger_err;
+ __le32 ax_mu_rts_trigger_err;
+ __le32 ax_ulmumimo_trigger_err;
+} __packed;
+
+struct ath12k_htt_tx_selfgen_be_err_stats_tlv {
+ __le32 be_su_ndp_err;
+ __le32 be_su_ndpa_err;
+ __le32 be_mu_mimo_ndpa_err;
+ __le32 be_mu_mimo_ndp_err;
+ __le32 be_mu_mimo_brp_err[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_basic_trigger_err;
+ __le32 be_bsr_trigger_err;
+ __le32 be_mu_bar_trigger_err;
+ __le32 be_mu_rts_trigger_err;
+ __le32 be_ulmumimo_trigger_err;
+ __le32 be_mu_mimo_brp_err_num_cbf_rxd[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+ __le32 be_su_ndpa_flushed;
+ __le32 be_su_ndp_flushed;
+ __le32 be_mu_mimo_ndpa_flushed;
+ __le32 be_mu_mimo_ndp_flushed;
+ __le32 be_mu_mimo_brpoll_flushed[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS - 1];
+ __le32 be_ul_mumimo_trigger_err[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+} __packed;
+
+enum ath12k_htt_tx_selfgen_sch_tsflag_error_stats {
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_FLUSH_RCVD_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_FILT_SCHED_CMD_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_MISMATCH_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_CBF_MIMO_CTRL_MISMATCH_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_CBF_BW_MISMATCH_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RETRY_COUNT_FAIL_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_RESP_TOO_LATE_RECEIVED_ERR,
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_SIFS_STALL_NO_NEXT_CMD_ERR,
+
+ ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS
+};
+
+struct ath12k_htt_tx_selfgen_ac_sched_status_stats_tlv {
+ __le32 ac_su_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_su_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_su_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ac_mu_mimo_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_mu_mimo_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_mu_mimo_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ac_mu_mimo_brp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ac_mu_mimo_brp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_ax_sched_status_stats_tlv {
+ __le32 ax_su_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_su_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_su_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_mu_mimo_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_mimo_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_mimo_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_mu_brp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_brp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_mu_bar_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_mu_bar_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_basic_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_basic_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 ax_ulmumimo_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 ax_ulmumimo_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+} __packed;
+
+struct ath12k_htt_tx_selfgen_be_sched_status_stats_tlv {
+ __le32 be_su_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_su_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_su_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_mu_mimo_ndpa_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_mimo_ndp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_mimo_ndp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_mu_brp_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_brp_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_mu_bar_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_mu_bar_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_basic_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_basic_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+ __le32 be_ulmumimo_trig_sch_status[ATH12K_HTT_TX_PDEV_STATS_NUM_TX_ERR_STATUS];
+ __le32 be_ulmumimo_trig_sch_flag_err[ATH12K_HTT_TX_SELFGEN_SCH_TSFLAG_ERR_STATS];
+} __packed;
+
+struct ath12k_htt_stats_string_tlv {
+ DECLARE_FLEX_ARRAY(__le32, data);
+} __packed;
+
+#define ATH12K_HTT_SRING_STATS_MAC_ID GENMASK(7, 0)
+#define ATH12K_HTT_SRING_STATS_RING_ID GENMASK(15, 8)
+#define ATH12K_HTT_SRING_STATS_ARENA GENMASK(23, 16)
+#define ATH12K_HTT_SRING_STATS_EP BIT(24)
+#define ATH12K_HTT_SRING_STATS_NUM_AVAIL_WORDS GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_NUM_VALID_WORDS GENMASK(31, 16)
+#define ATH12K_HTT_SRING_STATS_HEAD_PTR GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_TAIL_PTR GENMASK(31, 16)
+#define ATH12K_HTT_SRING_STATS_CONSUMER_EMPTY GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_PRODUCER_FULL GENMASK(31, 16)
+#define ATH12K_HTT_SRING_STATS_PREFETCH_COUNT GENMASK(15, 0)
+#define ATH12K_HTT_SRING_STATS_INTERNAL_TAIL_PTR GENMASK(31, 16)
+
+struct ath12k_htt_sring_stats_tlv {
+ __le32 mac_id__ring_id__arena__ep;
+ __le32 base_addr_lsb;
+ __le32 base_addr_msb;
+ __le32 ring_size;
+ __le32 elem_size;
+ __le32 num_avail_words__num_valid_words;
+ __le32 head_ptr__tail_ptr;
+ __le32 consumer_empty__producer_full;
+ __le32 prefetch_count__internal_tail_ptr;
+} __packed;
+
+struct ath12k_htt_sfm_cmn_tlv {
+ __le32 mac_id__word;
+ __le32 buf_total;
+ __le32 mem_empty;
+ __le32 deallocate_bufs;
+ __le32 num_records;
+} __packed;
+
+struct ath12k_htt_sfm_client_tlv {
+ __le32 client_id;
+ __le32 buf_min;
+ __le32 buf_max;
+ __le32 buf_busy;
+ __le32 buf_alloc;
+ __le32 buf_avail;
+ __le32 num_users;
+} __packed;
+
+struct ath12k_htt_sfm_client_user_tlv {
+ DECLARE_FLEX_ARRAY(__le32, dwords_used_by_user_n);
+} __packed;
+
+struct ath12k_htt_tx_pdev_mu_mimo_sch_stats_tlv {
+ __le32 mu_mimo_sch_posted;
+ __le32 mu_mimo_sch_failed;
+ __le32 mu_mimo_ppdu_posted;
+ __le32 ac_mu_mimo_sch_nusers[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS];
+ __le32 ax_mu_mimo_sch_nusers[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 ax_ofdma_sch_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_bsr_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_bar_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_ofdma_brp_nusers[ATH12K_HTT_TX_NUM_OFDMA_USER_STATS];
+ __le32 ax_ul_mumimo_nusers[ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS];
+ __le32 ax_ul_mumimo_brp_nusers[ATH12K_HTT_TX_NUM_UL_MUMIMO_USER_STATS];
+ __le32 ac_mu_mimo_per_grp_sz[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS];
+ __le32 ax_mu_mimo_per_grp_sz[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 be_mu_mimo_sch_nusers[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+ __le32 be_mu_mimo_per_grp_sz[ATH12K_HTT_TX_NUM_BE_MUMIMO_USER_STATS];
+ __le32 ac_mu_mimo_grp_sz_ext[ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS];
+} __packed;
+
+struct ath12k_htt_tx_pdev_mumimo_grp_stats_tlv {
+ __le32 dl_mumimo_grp_best_grp_size[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 dl_mumimo_grp_best_num_usrs[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 dl_mumimo_grp_eligible[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 dl_mumimo_grp_ineligible[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 dl_mumimo_grp_invalid[ATH12K_HTT_TX_NUM_MUMIMO_GRP_INVALID_WORDS];
+ __le32 dl_mumimo_grp_tputs[ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS];
+ __le32 ul_mumimo_grp_best_grp_size[ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ];
+ __le32 ul_mumimo_grp_best_usrs[ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS];
+ __le32 ul_mumimo_grp_tputs[ATH12K_HTT_STATS_MUMIMO_TPUT_NUM_BINS];
+} __packed;
+
+enum ath12k_htt_stats_tx_sched_modes {
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC = 0,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_OFDMA_BE,
+ ATH12K_HTT_STATS_TX_SCHED_MODE_MU_MIMO_BE
+};
+
+struct ath12k_htt_tx_pdev_mpdu_stats_tlv {
+ __le32 mpdus_queued_usr;
+ __le32 mpdus_tried_usr;
+ __le32 mpdus_failed_usr;
+ __le32 mpdus_requeued_usr;
+ __le32 err_no_ba_usr;
+ __le32 mpdu_underrun_usr;
+ __le32 ampdu_underrun_usr;
+ __le32 user_index;
+ __le32 tx_sched_mode;
+} __packed;
+
+struct ath12k_htt_pdev_stats_cca_counters_tlv {
+ __le32 tx_frame_usec;
+ __le32 rx_frame_usec;
+ __le32 rx_clear_usec;
+ __le32 my_rx_frame_usec;
+ __le32 usec_cnt;
+ __le32 med_rx_idle_usec;
+ __le32 med_tx_idle_global_usec;
+ __le32 cca_obss_usec;
+} __packed;
+
+struct ath12k_htt_pdev_cca_stats_hist_v1_tlv {
+ __le32 chan_num;
+ __le32 num_records;
+ __le32 valid_cca_counters_bitmap;
+ __le32 collection_interval;
+} __packed;
+
+struct ath12k_htt_pdev_obss_pd_stats_tlv {
+ __le32 num_obss_tx_ppdu_success;
+ __le32 num_obss_tx_ppdu_failure;
+ __le32 num_sr_tx_transmissions;
+ __le32 num_spatial_reuse_opportunities;
+ __le32 num_non_srg_opportunities;
+ __le32 num_non_srg_ppdu_tried;
+ __le32 num_non_srg_ppdu_success;
+ __le32 num_srg_opportunities;
+ __le32 num_srg_ppdu_tried;
+ __le32 num_srg_ppdu_success;
+ __le32 num_psr_opportunities;
+ __le32 num_psr_ppdu_tried;
+ __le32 num_psr_ppdu_success;
+ __le32 num_non_srg_tried_per_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_non_srg_success_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_srg_tried_per_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_srg_success_per_ac[ATH12K_HTT_NUM_AC_WMM];
+ __le32 num_obss_min_dur_check_flush_cnt;
+ __le32 num_sr_ppdu_abort_flush_cnt;
+} __packed;
+
+struct ath12k_htt_dmac_reset_stats_tlv {
+ __le32 reset_count;
+ __le32 reset_time_lo_ms;
+ __le32 reset_time_hi_ms;
+ __le32 disengage_time_lo_ms;
+ __le32 disengage_time_hi_ms;
+ __le32 engage_time_lo_ms;
+ __le32 engage_time_hi_ms;
+ __le32 disengage_count;
+ __le32 engage_count;
+ __le32 drain_dest_ring_mask;
+} __packed;
+
+struct ath12k_htt_pdev_sched_algo_ofdma_stats_tlv {
+ __le32 mac_id__word;
+ __le32 rate_based_dlofdma_enabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 rate_based_dlofdma_disabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 rate_based_dlofdma_probing_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 rate_based_dlofdma_monitor_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 chan_acc_lat_based_dlofdma_enabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 chan_acc_lat_based_dlofdma_disabled_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 chan_acc_lat_based_dlofdma_monitor_cnt[ATH12K_HTT_NUM_AC_WMM];
+ __le32 downgrade_to_dl_su_ru_alloc_fail[ATH12K_HTT_NUM_AC_WMM];
+ __le32 candidate_list_single_user_disable_ofdma[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dl_cand_list_dropped_high_ul_qos_weight[ATH12K_HTT_NUM_AC_WMM];
+ __le32 ax_dlofdma_disabled_due_to_pipelining[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dlofdma_disabled_su_only_eligible[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dlofdma_disabled_consec_no_mpdus_tried[ATH12K_HTT_NUM_AC_WMM];
+ __le32 dlofdma_disabled_consec_no_mpdus_success[ATH12K_HTT_NUM_AC_WMM];
+} __packed;
+
+enum ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE {
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_26,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52_26,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_106_26,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_242,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_484_242,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996_484_242,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x2_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x3_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_996x4,
+ ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS,
+};
+
+#define ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS 8
+#define ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS 16
+#define ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS 5
+#define ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS 4
+#define ATH12K_HTT_TX_PDEV_NUM_GI_CNTRS 4
+
+struct ath12k_htt_tx_pdev_rate_stats_be_ofdma_tlv {
+ __le32 mac_id__word;
+ __le32 be_ofdma_tx_ldpc;
+ __le32 be_ofdma_tx_mcs[ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS];
+ __le32 be_ofdma_tx_nss[ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS];
+ __le32 be_ofdma_tx_bw[ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS];
+ __le32 gi[ATH12K_HTT_TX_PDEV_NUM_GI_CNTRS][ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS];
+ __le32 be_ofdma_tx_ru_size[ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS];
+ __le32 be_ofdma_eht_sig_mcs[ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS];
+} __packed;
+
#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 61aa78d8bd8c..c99e9ceb1a6e 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -327,20 +327,22 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring,
}
static
-u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif *arvif)
+u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab,
+ struct ath12k_link_vif *arvif)
{
u32 bank_config = 0;
+ struct ath12k_vif *ahvif = arvif->ahvif;
/* Only valid for raw frames with HW crypto enabled.
* With SW crypto, mac80211 sets key per packet
*/
- if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
+ if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags))
bank_config |=
- u32_encode_bits(ath12k_dp_tx_get_encrypt_type(arvif->key_cipher),
+ u32_encode_bits(ath12k_dp_tx_get_encrypt_type(ahvif->key_cipher),
HAL_TX_BANK_CONFIG_ENCRYPT_TYPE);
- bank_config |= u32_encode_bits(arvif->tx_encap_type,
+ bank_config |= u32_encode_bits(ahvif->tx_encap_type,
HAL_TX_BANK_CONFIG_ENCAP_TYPE);
bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_SRC_BUFFER_SWAP) |
u32_encode_bits(0, HAL_TX_BANK_CONFIG_LINK_META_SWAP) |
@@ -355,7 +357,7 @@ u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif
HAL_TX_ADDRY_EN),
HAL_TX_BANK_CONFIG_ADDRY_EN);
- bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(arvif->vif) ? 3 : 0,
+ bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(ahvif->vif) ? 3 : 0,
HAL_TX_BANK_CONFIG_MESH_EN) |
u32_encode_bits(arvif->vdev_id_check_en,
HAL_TX_BANK_CONFIG_VDEV_ID_CHECK_EN);
@@ -365,7 +367,8 @@ u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif
return bank_config;
}
-static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab, struct ath12k_vif *arvif,
+static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab,
+ struct ath12k_link_vif *arvif,
struct ath12k_dp *dp)
{
int bank_id = DP_INVALID_BANK_ID;
@@ -1099,9 +1102,9 @@ int ath12k_dp_htt_connect(struct ath12k_dp *dp)
return 0;
}
-static void ath12k_dp_update_vdev_search(struct ath12k_vif *arvif)
+static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif)
{
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_STA:
/* TODO: Verify the search type and flags since ast hash
* is not part of peer mapv3
@@ -1120,7 +1123,7 @@ static void ath12k_dp_update_vdev_search(struct ath12k_vif *arvif)
}
}
-void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif)
+void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
struct ath12k_base *ab = ar->ab;
@@ -1162,7 +1165,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
spin_lock_bh(&dp->rx_desc_lock);
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
- desc_info = dp->spt_info->rxbaddr[i];
+ desc_info = dp->rxbaddr[i];
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
if (!desc_info[j].in_use) {
@@ -1181,11 +1184,11 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
}
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
- if (!dp->spt_info->rxbaddr[i])
+ if (!dp->rxbaddr[i])
continue;
- kfree(dp->spt_info->rxbaddr[i]);
- dp->spt_info->rxbaddr[i] = NULL;
+ kfree(dp->rxbaddr[i]);
+ dp->rxbaddr[i] = NULL;
}
spin_unlock_bh(&dp->rx_desc_lock);
@@ -1202,10 +1205,16 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
if (!skb)
continue;
- skb_cb = ATH12K_SKB_CB(skb);
- ar = skb_cb->ar;
- if (atomic_dec_and_test(&ar->dp.num_tx_pending))
- wake_up(&ar->dp.tx_empty_waitq);
+ /* if we are unregistering, hw would've been destroyed and
+ * ar is no longer valid.
+ */
+ if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) {
+ skb_cb = ATH12K_SKB_CB(skb);
+ ar = skb_cb->ar;
+
+ if (atomic_dec_and_test(&ar->dp.num_tx_pending))
+ wake_up(&ar->dp.tx_empty_waitq);
+ }
dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr,
skb->len, DMA_TO_DEVICE);
@@ -1220,11 +1229,11 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
for (i = 0; i < ATH12K_TX_SPT_PAGES_PER_POOL; i++) {
tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
- if (!dp->spt_info->txbaddr[tx_spt_page])
+ if (!dp->txbaddr[tx_spt_page])
continue;
- kfree(dp->spt_info->txbaddr[tx_spt_page]);
- dp->spt_info->txbaddr[tx_spt_page] = NULL;
+ kfree(dp->txbaddr[tx_spt_page]);
+ dp->txbaddr[tx_spt_page] = NULL;
}
spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
@@ -1241,6 +1250,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
}
kfree(dp->spt_info);
+ dp->spt_info = NULL;
}
static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
@@ -1276,8 +1286,10 @@ void ath12k_dp_free(struct ath12k_base *ab)
ath12k_dp_rx_reo_cmd_list_cleanup(ab);
- for (i = 0; i < ab->hw_params->max_tx_ring; i++)
+ for (i = 0; i < ab->hw_params->max_tx_ring; i++) {
kfree(dp->tx_ring[i].tx_status);
+ dp->tx_ring[i].tx_status = NULL;
+ }
ath12k_dp_rx_free(ab);
/* Deinit any SOC level resource */
@@ -1415,7 +1427,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
ppt_idx = ATH12K_RX_SPT_PAGE_OFFSET + i;
cookie_ppt_idx = dp->rx_ppt_base + ppt_idx;
- dp->spt_info->rxbaddr[i] = &rx_descs[0];
+ dp->rxbaddr[i] = &rx_descs[0];
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(cookie_ppt_idx, j);
@@ -1445,7 +1457,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
ppt_idx = ATH12K_TX_SPT_PAGE_OFFSET + tx_spt_page;
- dp->spt_info->txbaddr[tx_spt_page] = &tx_descs[0];
+ dp->txbaddr[tx_spt_page] = &tx_descs[0];
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j);
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 2fb18b83b3ee..2e05fc19410e 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -16,6 +16,7 @@ struct ath12k_base;
struct ath12k_peer;
struct ath12k_dp;
struct ath12k_vif;
+struct ath12k_link_vif;
struct hal_tcl_status_ring;
struct ath12k_ext_irq_grp;
@@ -300,8 +301,6 @@ struct ath12k_tx_desc_info {
struct ath12k_spt_info {
dma_addr_t paddr;
u64 *vaddr;
- struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES];
- struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES];
};
struct ath12k_reo_queue_ref {
@@ -352,6 +351,8 @@ struct ath12k_dp {
struct ath12k_spt_info *spt_info;
u32 num_spt_pages;
u32 rx_ppt_base;
+ struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES];
+ struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES];
struct list_head rx_desc_free_list;
/* protects the free desc list */
spinlock_t rx_desc_lock;
@@ -1799,7 +1800,7 @@ int ath12k_dp_service_srng(struct ath12k_base *ab,
struct ath12k_ext_irq_grp *irq_grp,
int budget);
int ath12k_dp_htt_connect(struct ath12k_dp *dp);
-void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif);
+void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif);
void ath12k_dp_free(struct ath12k_base *ab);
int ath12k_dp_alloc(struct ath12k_base *ab);
void ath12k_dp_cc_config(struct ath12k_base *ab);
diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c
index 5c6749bc4039..494984133a91 100644
--- a/drivers/net/wireless/ath/ath12k/dp_mon.c
+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c
@@ -26,15 +26,12 @@ ath12k_dp_mon_rx_populate_byte_count(const struct hal_rx_ppdu_end_user_stats *st
void *ppduinfo,
struct hal_rx_user_status *rx_user_status)
{
- u32 mpdu_ok_byte_count = __le32_to_cpu(stats->mpdu_ok_cnt);
- u32 mpdu_err_byte_count = __le32_to_cpu(stats->mpdu_err_cnt);
-
rx_user_status->mpdu_ok_byte_count =
- u32_get_bits(mpdu_ok_byte_count,
- HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_OK_BYTE_COUNT);
+ le32_get_bits(stats->info7,
+ HAL_RX_PPDU_END_USER_STATS_INFO7_MPDU_OK_BYTE_COUNT);
rx_user_status->mpdu_err_byte_count =
- u32_get_bits(mpdu_err_byte_count,
- HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_ERR_BYTE_COUNT);
+ le32_get_bits(stats->info8,
+ HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT);
}
static void
@@ -593,12 +590,20 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
struct hal_rx_ppdu_start *ppdu_start =
(struct hal_rx_ppdu_start *)tlv_data;
+ u64 ppdu_ts = ath12k_le32hilo_to_u64(ppdu_start->ppdu_start_ts_63_32,
+ ppdu_start->ppdu_start_ts_31_0);
+
info[0] = __le32_to_cpu(ppdu_start->info0);
- ppdu_info->ppdu_id =
- u32_get_bits(info[0], HAL_RX_PPDU_START_INFO0_PPDU_ID);
- ppdu_info->chan_num = __le32_to_cpu(ppdu_start->chan_num);
- ppdu_info->ppdu_ts = __le32_to_cpu(ppdu_start->ppdu_start_ts);
+ ppdu_info->ppdu_id = u32_get_bits(info[0],
+ HAL_RX_PPDU_START_INFO0_PPDU_ID);
+
+ info[1] = __le32_to_cpu(ppdu_start->info1);
+ ppdu_info->chan_num = u32_get_bits(info[1],
+ HAL_RX_PPDU_START_INFO1_CHAN_NUM);
+ ppdu_info->freq = u32_get_bits(info[1],
+ HAL_RX_PPDU_START_INFO1_CHAN_FREQ);
+ ppdu_info->ppdu_ts = ppdu_ts;
if (ppdu_info->ppdu_id != ppdu_info->last_ppdu_id) {
ppdu_info->last_ppdu_id = ppdu_info->ppdu_id;
@@ -726,33 +731,20 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
case HAL_PHYRX_RSSI_LEGACY: {
struct hal_rx_phyrx_rssi_legacy_info *rssi =
(struct hal_rx_phyrx_rssi_legacy_info *)tlv_data;
- u32 reception_type = 0;
- u32 rssi_legacy_info = __le32_to_cpu(rssi->rsvd[0]);
info[0] = __le32_to_cpu(rssi->info0);
+ info[1] = __le32_to_cpu(rssi->info1);
/* TODO: Please note that the combined rssi will not be accurate
* in MU case. Rssi in MU needs to be retrieved from
* PHYRX_OTHER_RECEIVE_INFO TLV.
*/
ppdu_info->rssi_comb =
- u32_get_bits(info[0],
- HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB);
- reception_type =
- u32_get_bits(rssi_legacy_info,
- HAL_RX_PHYRX_RSSI_LEGACY_INFO_RSVD1_RECEPTION);
-
- switch (reception_type) {
- case HAL_RECEPTION_TYPE_ULOFMDA:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA;
- break;
- case HAL_RECEPTION_TYPE_ULMIMO:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO;
- break;
- default:
- ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
- break;
- }
+ u32_get_bits(info[1],
+ HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB);
+
+ ppdu_info->bw = u32_get_bits(info[0],
+ HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RX_BW);
break;
}
case HAL_RXPCU_PPDU_END_INFO: {
@@ -860,27 +852,29 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab,
return HAL_RX_MON_STATUS_PPDU_NOT_DONE;
}
-static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar, struct sk_buff *msdu)
+static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar,
+ struct sk_buff *head_msdu,
+ struct sk_buff *tail_msdu)
{
u32 rx_pkt_offset, l2_hdr_offset;
rx_pkt_offset = ar->ab->hal.hal_desc_sz;
- l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab,
- (struct hal_rx_desc *)msdu->data);
- skb_pull(msdu, rx_pkt_offset + l2_hdr_offset);
+ l2_hdr_offset =
+ ath12k_dp_rx_h_l3pad(ar->ab, (struct hal_rx_desc *)tail_msdu->data);
+ skb_pull(head_msdu, rx_pkt_offset + l2_hdr_offset);
}
static struct sk_buff *
-ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
- u32 mac_id, struct sk_buff *head_msdu,
+ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar, u32 mac_id,
+ struct sk_buff *head_msdu, struct sk_buff *tail_msdu,
struct ieee80211_rx_status *rxs, bool *fcs_err)
{
struct ath12k_base *ab = ar->ab;
- struct sk_buff *msdu, *mpdu_buf, *prev_buf;
- struct hal_rx_desc *rx_desc;
+ struct sk_buff *msdu, *mpdu_buf, *prev_buf, *head_frag_list;
+ struct hal_rx_desc *rx_desc, *tail_rx_desc;
u8 *hdr_desc, *dest, decap_format;
struct ieee80211_hdr_3addr *wh;
- u32 err_bitmap;
+ u32 err_bitmap, frag_list_sum_len = 0;
mpdu_buf = NULL;
@@ -888,24 +882,30 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
goto err_merge_fail;
rx_desc = (struct hal_rx_desc *)head_msdu->data;
- err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
+ tail_rx_desc = (struct hal_rx_desc *)tail_msdu->data;
+ err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, tail_rx_desc);
if (err_bitmap & HAL_RX_MPDU_ERR_FCS)
*fcs_err = true;
- decap_format = ath12k_dp_rx_h_decap_type(ab, rx_desc);
+ decap_format = ath12k_dp_rx_h_decap_type(ab, tail_rx_desc);
- ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs);
+ ath12k_dp_rx_h_ppdu(ar, tail_rx_desc, rxs);
if (decap_format == DP_RX_DECAP_TYPE_RAW) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
prev_buf = head_msdu;
msdu = head_msdu->next;
+ head_frag_list = NULL;
while (msdu) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ar, msdu, tail_msdu);
+
+ if (!head_frag_list)
+ head_frag_list = msdu;
+ frag_list_sum_len += msdu->len;
prev_buf = msdu;
msdu = msdu->next;
}
@@ -913,6 +913,12 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
prev_buf->next = NULL;
skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN);
+ if (head_frag_list) {
+ skb_shinfo(head_msdu)->frag_list = head_frag_list;
+ head_msdu->data_len = frag_list_sum_len;
+ head_msdu->len += head_msdu->data_len;
+ head_msdu->next = NULL;
+ }
} else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) {
u8 qos_pkt = 0;
@@ -929,7 +935,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
msdu = head_msdu;
while (msdu) {
- ath12k_dp_mon_rx_msdus_set_payload(ar, msdu);
+ ath12k_dp_mon_rx_msdus_set_payload(ar, msdu, tail_msdu);
if (qos_pkt) {
dest = skb_push(msdu, sizeof(__le16));
if (!dest)
@@ -1135,7 +1141,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
}
static int ath12k_dp_mon_rx_deliver(struct ath12k *ar, u32 mac_id,
- struct sk_buff *head_msdu,
+ struct sk_buff *head_msdu, struct sk_buff *tail_msdu,
struct hal_rx_mon_ppdu_info *ppduinfo,
struct napi_struct *napi)
{
@@ -1144,7 +1150,8 @@ static int ath12k_dp_mon_rx_deliver(struct ath12k *ar, u32 mac_id,
struct ieee80211_rx_status *rxs = &dp->rx_status;
bool fcs_err = false;
- mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mac_id, head_msdu,
+ mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mac_id,
+ head_msdu, tail_msdu,
rxs, &fcs_err);
if (!mon_skb)
goto mon_deliver_fail;
@@ -1252,7 +1259,7 @@ ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
if (head_msdu && tail_msdu) {
ath12k_dp_mon_rx_deliver(ar, mac_id, head_msdu,
- ppdu_info, napi);
+ tail_msdu, ppdu_info, napi);
}
kfree(mon_mpdu);
@@ -1948,15 +1955,16 @@ ath12k_dp_mon_tx_process_ppdu_info(struct ath12k *ar, int mac_id,
struct dp_mon_tx_ppdu_info *tx_ppdu_info)
{
struct dp_mon_mpdu *tmp, *mon_mpdu;
- struct sk_buff *head_msdu;
+ struct sk_buff *head_msdu, *tail_msdu;
list_for_each_entry_safe(mon_mpdu, tmp,
&tx_ppdu_info->dp_tx_mon_mpdu_list, list) {
list_del(&mon_mpdu->list);
head_msdu = mon_mpdu->head;
+ tail_msdu = mon_mpdu->tail;
if (head_msdu)
- ath12k_dp_mon_rx_deliver(ar, mac_id, head_msdu,
+ ath12k_dp_mon_rx_deliver(ar, mac_id, head_msdu, tail_msdu,
&tx_ppdu_info->rx_status, napi);
kfree(mon_mpdu);
@@ -2165,7 +2173,7 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st
}
static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar,
- struct ath12k_sta *arsta,
+ struct ath12k_link_sta *arsta,
struct hal_rx_mon_ppdu_info *ppdu_info)
{
struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats;
@@ -2321,7 +2329,8 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
struct hal_rx_mon_ppdu_info *ppdu_info,
u32 uid)
{
- struct ath12k_sta *arsta = NULL;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
struct ath12k_rx_peer_stats *rx_stats = NULL;
struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid];
struct ath12k_peer *peer;
@@ -2338,7 +2347,8 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,
return;
}
- arsta = ath12k_sta_to_arsta(peer->sta);
+ ahsta = ath12k_sta_to_ahsta(peer->sta);
+ arsta = &ahsta->deflink;
rx_stats = arsta->rx_stats;
if (!rx_stats)
@@ -2445,7 +2455,8 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
struct dp_srng *mon_dst_ring;
struct hal_srng *srng;
struct dp_rxdma_mon_ring *buf_ring;
- struct ath12k_sta *arsta = NULL;
+ struct ath12k_sta *ahsta = NULL;
+ struct ath12k_link_sta *arsta;
struct ath12k_peer *peer;
u64 cookie;
int num_buffs_reaped = 0, srng_id, buf_id;
@@ -2514,7 +2525,8 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id,
}
if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) {
- arsta = ath12k_sta_to_arsta(peer->sta);
+ ahsta = ath12k_sta_to_ahsta(peer->sta);
+ arsta = &ahsta->deflink;
ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta,
ppdu_info);
} else if ((ppdu_info->fc_valid) &&
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 91e3393f7b5f..9ae579e50557 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -1041,13 +1041,14 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ieee80211_ampdu_params *params)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
int vdev_id = arsta->arvif->vdev_id;
int ret;
ret = ath12k_dp_rx_peer_tid_setup(ar, params->sta->addr, vdev_id,
params->tid, params->buf_size,
- params->ssn, arsta->pn_type);
+ params->ssn, arsta->ahsta->pn_type);
if (ret)
ath12k_warn(ab, "failed to setup rx tid %d\n", ret);
@@ -1059,7 +1060,8 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
{
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(params->sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
int vdev_id = arsta->arvif->vdev_id;
bool active;
int ret;
@@ -1091,7 +1093,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
return ret;
}
-int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif,
+int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
const u8 *peer_addr,
enum set_key_cmd key_cmd,
struct ieee80211_key_conf *key)
@@ -1313,7 +1315,8 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
struct ieee80211_sta *sta;
- struct ath12k_sta *arsta;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
struct htt_ppdu_stats_user_rate *user_rate;
struct ath12k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats;
struct htt_ppdu_user_stats *usr_stats = &ppdu_stats->user_stats[user];
@@ -1394,7 +1397,8 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
}
sta = peer->sta;
- arsta = ath12k_sta_to_arsta(sta);
+ ahsta = ath12k_sta_to_ahsta(sta);
+ arsta = &ahsta->deflink;
memset(&arsta->txrate, 0, sizeof(arsta->txrate));
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index eb1f92559179..bfd4f814553e 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -88,7 +88,7 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ieee80211_ampdu_params *params);
int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
struct ieee80211_ampdu_params *params);
-int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif,
+int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
const u8 *peer_addr,
enum set_key_cmd key_cmd,
struct ieee80211_key_conf *key);
diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c
index 44406e0b4a34..a8d341a6df01 100644
--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
@@ -10,7 +10,7 @@
#include "hw.h"
static enum hal_tcl_encap_type
-ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb)
+ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath12k_base *ab = arvif->ar->ab;
@@ -216,7 +216,7 @@ out:
return ret;
}
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct sk_buff *skb)
{
struct ath12k_base *ab = ar->ab;
@@ -230,6 +230,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
struct sk_buff *skb_ext_desc;
struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ath12k_vif *ahvif = arvif->ahvif;
struct dp_tx_ring *tx_ring;
u8 pool_id;
u8 hal_ring_id;
@@ -274,7 +275,7 @@ tcl_ring_sel:
ti.bank_id = arvif->bank_id;
ti.meta_data_flags = arvif->tcl_metadata;
- if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
+ if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW &&
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) {
if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) {
ti.encrypt_type =
@@ -376,7 +377,7 @@ map:
ti.desc_id = tx_desc->desc_id;
ti.data_len = skb->len;
skb_cb->paddr = ti.paddr;
- skb_cb->vif = arvif->vif;
+ skb_cb->vif = ahvif->vif;
skb_cb->ar = ar;
if (msdu_ext_desc) {
diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.h b/drivers/net/wireless/ath/ath12k/dp_tx.h
index 55ff8cc721e3..46dce23501f3 100644
--- a/drivers/net/wireless/ath/ath12k/dp_tx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.h
@@ -16,7 +16,7 @@ struct ath12k_dp_htt_wbm_tx_status {
};
int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab);
-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct sk_buff *skb);
void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id);
diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index ca04bfae8bdc..fd98fac16dd5 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -385,13 +385,13 @@ static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcn9274.msdu_end.info12,
- RX_MSDU_END_QCN9274_INFO12_MIMO_SS_BITMAP);
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
}
static u8 ath12k_hw_qcn9274_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
{
return le16_get_bits(desc->u.qcn9274.msdu_end.info5,
- RX_MSDU_END_QCN9274_INFO5_TID);
+ RX_MSDU_END_INFO5_TID);
}
static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
@@ -846,13 +846,13 @@ static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_pkt_type(struct hal_rx_desc
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
- RX_MSDU_END_QCN9274_INFO12_MIMO_SS_BITMAP);
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
}
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
{
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
- RX_MSDU_END_QCN9274_INFO5_TID);
+ RX_MSDU_END_INFO5_TID);
}
static u16 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
@@ -1198,7 +1198,7 @@ static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.wcn7850.msdu_end.info12,
- RX_MSDU_END_WCN7850_INFO12_MIMO_SS_BITMAP);
+ RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
}
static u8 ath12k_hw_wcn7850_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
@@ -1216,7 +1216,7 @@ static void ath12k_hw_wcn7850_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc,
struct hal_rx_desc *ldesc)
{
memcpy(&fdesc->u.wcn7850.msdu_end, &ldesc->u.wcn7850.msdu_end,
- sizeof(struct rx_msdu_end_wcn7850));
+ sizeof(struct rx_msdu_end_qcn9274));
}
static u32 ath12k_hw_wcn7850_rx_desc_get_mpdu_start_tag(struct hal_rx_desc *desc)
diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h
index 095216eabc01..2de7b0eba9f2 100644
--- a/drivers/net/wireless/ath/ath12k/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/hal_rx.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_HAL_RX_H
@@ -156,6 +156,7 @@ struct hal_rx_mon_ppdu_info {
u32 preamble_type;
u32 mpdu_len;
u16 chan_num;
+ u16 freq;
u16 tcp_msdu_count;
u16 tcp_ack_msdu_count;
u16 udp_msdu_count;
@@ -232,21 +233,25 @@ struct hal_rx_mon_ppdu_info {
u8 medium_prot_type;
};
-#define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0)
+#define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0)
+#define HAL_RX_PPDU_START_INFO1_CHAN_NUM GENMASK(15, 0)
+#define HAL_RX_PPDU_START_INFO1_CHAN_FREQ GENMASK(31, 16)
struct hal_rx_ppdu_start {
__le32 info0;
- __le32 chan_num;
- __le32 ppdu_start_ts;
+ __le32 info1;
+ __le32 ppdu_start_ts_31_0;
+ __le32 ppdu_start_ts_63_32;
+ __le32 rsvd[2];
} __packed;
-#define HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR GENMASK(25, 16)
+#define HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR GENMASK(26, 16)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_MPDU_CNT_FCS_OK GENMASK(8, 0)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID BIT(9)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_QOS_CTRL_VALID BIT(10)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_HT_CTRL_VALID BIT(11)
-#define HAL_RX_PPDU_END_USER_STATS_INFO1_PKT_TYPE GENMASK(23, 20)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_MPDU_CNT_FCS_OK GENMASK(10, 0)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID BIT(11)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_QOS_CTRL_VALID BIT(12)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_HT_CTRL_VALID BIT(13)
+#define HAL_RX_PPDU_END_USER_STATS_INFO1_PKT_TYPE GENMASK(24, 21)
#define HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX GENMASK(15, 0)
#define HAL_RX_PPDU_END_USER_STATS_INFO2_FRAME_CTRL GENMASK(31, 16)
@@ -262,8 +267,8 @@ struct hal_rx_ppdu_start {
#define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP GENMASK(15, 0)
#define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_EOSP_BITMAP GENMASK(31, 16)
-#define HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_OK_BYTE_COUNT GENMASK(24, 0)
-#define HAL_RX_PPDU_END_USER_STATS_MPDU_DELIM_ERR_BYTE_COUNT GENMASK(24, 0)
+#define HAL_RX_PPDU_END_USER_STATS_INFO7_MPDU_OK_BYTE_COUNT GENMASK(24, 0)
+#define HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT GENMASK(24, 0)
struct hal_rx_ppdu_end_user_stats {
__le32 rsvd0[2];
@@ -278,9 +283,9 @@ struct hal_rx_ppdu_end_user_stats {
__le32 usr_resp_ref;
__le32 info6;
__le32 rsvd3[4];
- __le32 mpdu_ok_cnt;
+ __le32 info7;
__le32 rsvd4;
- __le32 mpdu_err_cnt;
+ __le32 info8;
__le32 rsvd5[2];
__le32 usr_resp_ref_ext;
__le32 rsvd6;
@@ -436,23 +441,27 @@ enum hal_rx_ul_reception_type {
HAL_RECEPTION_TYPE_FRAMELESS
};
-#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8)
-#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_RSVD1_RECEPTION GENMASK(3, 0)
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RECEPTION GENMASK(3, 0)
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RX_BW GENMASK(7, 5)
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8)
struct hal_rx_phyrx_rssi_legacy_info {
- __le32 rsvd[35];
__le32 info0;
+ __le32 rsvd0[39];
+ __le32 info1;
+ __le32 rsvd1;
} __packed;
-#define HAL_RX_MPDU_START_INFO0_PPDU_ID GENMASK(31, 16)
-#define HAL_RX_MPDU_START_INFO1_PEERID GENMASK(31, 16)
-#define HAL_RX_MPDU_START_INFO2_MPDU_LEN GENMASK(13, 0)
+#define HAL_RX_MPDU_START_INFO0_PPDU_ID GENMASK(31, 16)
+#define HAL_RX_MPDU_START_INFO1_PEERID GENMASK(31, 16)
+#define HAL_RX_MPDU_START_INFO2_MPDU_LEN GENMASK(13, 0)
struct hal_rx_mpdu_start {
+ __le32 rsvd0[9];
__le32 info0;
__le32 info1;
- __le32 rsvd1[11];
+ __le32 rsvd1[2];
__le32 info2;
- __le32 rsvd2[9];
+ __le32 rsvd2[16];
} __packed;
#define HAL_RX_PPDU_END_DURATION GENMASK(23, 0)
diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h
index 0e53ec269fa4..e8840fab6061 100644
--- a/drivers/net/wireless/ath/ath12k/hif.h
+++ b/drivers/net/wireless/ath/ath12k/hif.h
@@ -31,6 +31,7 @@ struct ath12k_hif_ops {
void (*ce_irq_disable)(struct ath12k_base *ab);
void (*get_ce_msi_idx)(struct ath12k_base *ab, u32 ce_id, u32 *msi_idx);
int (*panic_handler)(struct ath12k_base *ab);
+ void (*coredump_download)(struct ath12k_base *ab);
};
static inline int ath12k_hif_map_service_to_pipe(struct ath12k_base *ab, u16 service_id,
@@ -156,4 +157,9 @@ static inline int ath12k_hif_panic_handler(struct ath12k_base *ab)
return ab->hif.ops->panic_handler(ab);
}
+static inline void ath12k_hif_coredump_download(struct ath12k_base *ab)
+{
+ if (ab->hif.ops->coredump_download)
+ ab->hif.ops->coredump_download(ab);
+}
#endif /* ATH12K_HIF_H */
diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
index ec1bda95e555..b7b583fadb5a 100644
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ b/drivers/net/wireless/ath/ath12k/hw.c
@@ -913,7 +913,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.rfkill_cfg = 0,
.rfkill_on_level = 0,
- .rddm_size = 0,
+ .rddm_size = 0x600000,
.def_num_link = 0,
.max_mlo_peer = 256,
@@ -1069,7 +1069,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.rfkill_cfg = 0,
.rfkill_on_level = 0,
- .rddm_size = 0,
+ .rddm_size = 0x600000,
.def_num_link = 0,
.max_mlo_peer = 256,
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 137394c36460..d493ec812055 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -250,10 +250,10 @@ static const u32 ath12k_smps_map[] = {
};
static int ath12k_start_vdev_delay(struct ath12k *ar,
- struct ath12k_vif *arvif);
+ struct ath12k_link_vif *arvif);
static void ath12k_mac_stop(struct ath12k *ar);
-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif);
-static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif);
+static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif);
+static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif);
static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode)
{
@@ -476,18 +476,25 @@ static u8 ath12k_parse_mpdudensity(u8 mpdudensity)
}
}
-static int ath12k_mac_vif_chan(struct ieee80211_vif *vif,
- struct cfg80211_chan_def *def)
+static int ath12k_mac_vif_link_chan(struct ieee80211_vif *vif, u8 link_id,
+ struct cfg80211_chan_def *def)
{
+ struct ieee80211_bss_conf *link_conf;
struct ieee80211_chanctx_conf *conf;
rcu_read_lock();
- conf = rcu_dereference(vif->bss_conf.chanctx_conf);
+ link_conf = rcu_dereference(vif->link_conf[link_id]);
+
+ if (!link_conf) {
+ rcu_read_unlock();
+ return -ENOLINK;
+ }
+
+ conf = rcu_dereference(link_conf->chanctx_conf);
if (!conf) {
rcu_read_unlock();
return -ENOENT;
}
-
*def = conf->def;
rcu_read_unlock();
@@ -539,18 +546,33 @@ static void ath12k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath12k_vif_iter *arvif_iter = data;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ unsigned long links_map = ahvif->links_map;
+ struct ath12k_link_vif *arvif;
+ u8 link_id;
+
+ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = rcu_dereference(ahvif->link[link_id]);
+
+ if (WARN_ON(!arvif))
+ continue;
- if (arvif->vdev_id == arvif_iter->vdev_id &&
- arvif->ar == arvif_iter->ar)
- arvif_iter->arvif = arvif;
+ if (arvif->vdev_id == arvif_iter->vdev_id &&
+ arvif->ar == arvif_iter->ar) {
+ arvif_iter->arvif = arvif;
+ break;
+ }
+ }
}
-struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
+struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
{
struct ath12k_vif_iter arvif_iter = {};
u32 flags;
+ /* To use the arvif returned, caller must have held rcu read lock.
+ */
+ WARN_ON(!rcu_read_lock_any_held());
arvif_iter.vdev_id = vdev_id;
arvif_iter.ar = ar;
@@ -567,12 +589,12 @@ struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
return arvif_iter.arvif;
}
-struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
- u32 vdev_id)
+struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
+ u32 vdev_id)
{
int i;
struct ath12k_pdev *pdev;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
for (i = 0; i < ab->num_radios; i++) {
pdev = rcu_dereference(ab->pdevs_active[i]);
@@ -658,7 +680,8 @@ static struct ath12k *ath12k_get_ar_by_ctx(struct ieee80211_hw *hw,
static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
/* If there is one pdev within ah, then we return
@@ -673,11 +696,12 @@ static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
return NULL;
}
-static struct ath12k_vif *ath12k_mac_get_vif_up(struct ath12k *ar)
+static struct ath12k_link_vif *ath12k_mac_get_vif_up(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->is_up)
return arvif;
@@ -705,17 +729,17 @@ static bool ath12k_mac_band_match(enum nl80211_band band1, enum WMI_HOST_WLAN_BA
return false;
}
-static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_vif *arvif)
+static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
- struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
struct cfg80211_chan_def def;
enum nl80211_band band;
u8 pdev_id = ab->fw_pdev[0].pdev_id;
int i;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return pdev_id;
band = def.chan->band;
@@ -730,7 +754,7 @@ static u8 ath12k_mac_get_target_pdev_id_from_vif(struct ath12k_vif *arvif)
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
struct ath12k_base *ab = ar->ab;
if (!ab->hw_params->single_pdev_only)
@@ -770,11 +794,11 @@ static void ath12k_pdev_caps_update(struct ath12k *ar)
static int ath12k_mac_txpower_recalc(struct ath12k *ar)
{
struct ath12k_pdev *pdev = ar->pdev;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret, txpower = -1;
u32 param;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->txpower <= 0)
@@ -824,13 +848,13 @@ fail:
return ret;
}
-static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif)
+static int ath12k_recalc_rtscts_prot(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
u32 vdev_param, rts_cts;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
vdev_param = WMI_VDEV_PARAM_ENABLE_RTSCTS;
@@ -863,7 +887,7 @@ static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif)
return ret;
}
-static int ath12k_mac_set_kickout(struct ath12k_vif *arvif)
+static int ath12k_mac_set_kickout(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
u32 param;
@@ -913,11 +937,14 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
struct ath12k_peer *peer, *tmp;
struct ath12k_base *ab = ar->ab;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
- ath12k_dp_rx_peer_tid_cleanup(ar, peer);
+ /* Skip Rx TID cleanup for self peer */
+ if (peer->sta)
+ ath12k_dp_rx_peer_tid_cleanup(ar, peer);
+
list_del(&peer->list);
kfree(peer);
}
@@ -929,7 +956,7 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
{
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
return -ESHUTDOWN;
@@ -971,7 +998,7 @@ static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id,
struct ath12k_wmi_vdev_up_params params = {};
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
channel = chandef->chan;
arg.vdev_id = vdev_id;
@@ -1034,7 +1061,7 @@ static int ath12k_mac_monitor_vdev_stop(struct ath12k *ar)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->vdev_setup_done);
@@ -1064,9 +1091,8 @@ static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)
struct ath12k_wmi_vdev_create_arg arg = {};
int bit, ret;
u8 tmp_addr[6];
- u16 nss;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ar->monitor_vdev_created)
return 0;
@@ -1104,19 +1130,6 @@ static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)
return ret;
}
- nss = hweight32(ar->cfg_tx_chainmask) ? : 1;
- ret = ath12k_wmi_vdev_set_param_cmd(ar, ar->monitor_vdev_id,
- WMI_VDEV_PARAM_NSS, nss);
- if (ret) {
- ath12k_warn(ar->ab, "failed to set vdev %d chainmask 0x%x, nss %d :%d\n",
- ar->monitor_vdev_id, ar->cfg_tx_chainmask, nss, ret);
- return ret;
- }
-
- ret = ath12k_mac_txpower_recalc(ar);
- if (ret)
- return ret;
-
ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;
ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
ar->num_created_vdevs++;
@@ -1132,7 +1145,7 @@ static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar)
int ret;
unsigned long time_left;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!ar->monitor_vdev_created)
return 0;
@@ -1178,7 +1191,7 @@ static int ath12k_mac_monitor_start(struct ath12k *ar)
struct cfg80211_chan_def *chandef = NULL;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ar->monitor_started)
return 0;
@@ -1208,7 +1221,7 @@ static int ath12k_mac_monitor_stop(struct ath12k *ar)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!ar->monitor_started)
return 0;
@@ -1226,12 +1239,13 @@ static int ath12k_mac_monitor_stop(struct ath12k *ar)
return ret;
}
-static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif)
+static int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif)
{
+ struct ath12k_vif *ahvif = arvif->ahvif;
struct ath12k *ar = arvif->ar;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->vdev_setup_done);
@@ -1253,7 +1267,7 @@ static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif)
ar->num_started_vdevs--;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n",
- arvif->vif->addr, arvif->vdev_id);
+ ahvif->vif->addr, arvif->vdev_id);
if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) {
clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
@@ -1272,36 +1286,33 @@ static int ath12k_mac_config(struct ath12k *ar, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int ret = 0;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
ar->monitor_conf_enabled = conf->flags & IEEE80211_CONF_MONITOR;
if (ar->monitor_conf_enabled) {
if (ar->monitor_vdev_created)
- goto exit;
+ return ret;
ret = ath12k_mac_monitor_vdev_create(ar);
if (ret)
- goto exit;
+ return ret;
ret = ath12k_mac_monitor_start(ar);
if (ret)
goto err_mon_del;
} else {
if (!ar->monitor_vdev_created)
- goto exit;
+ return ret;
ret = ath12k_mac_monitor_stop(ar);
if (ret)
- goto exit;
+ return ret;
ath12k_mac_monitor_vdev_delete(ar);
}
}
-exit:
- mutex_unlock(&ar->conf_mutex);
return ret;
err_mon_del:
ath12k_mac_monitor_vdev_delete(ar);
- mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -1311,6 +1322,8 @@ static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
struct ath12k *ar;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_ah_to_ar(ah, 0);
ret = ath12k_mac_config(ar, changed);
@@ -1321,7 +1334,7 @@ static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
return ret;
}
-static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_vif *arvif,
+static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_link_vif *arvif,
struct sk_buff *bcn)
{
struct ath12k *ar = arvif->ar;
@@ -1378,7 +1391,7 @@ static int ath12k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
return 0;
}
-static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *bcn,
+static void ath12k_mac_set_arvif_ies(struct ath12k_link_vif *arvif, struct sk_buff *bcn,
u8 bssid_index, bool *nontx_profile_found)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn->data;
@@ -1470,19 +1483,22 @@ static void ath12k_mac_set_arvif_ies(struct ath12k_vif *arvif, struct sk_buff *b
}
}
-static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_vif *arvif)
+static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_link_vif *arvif)
{
- struct ieee80211_bss_conf *bss_conf = &arvif->vif->bss_conf;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_bss_conf *bss_conf = &ahvif->vif->bss_conf;
struct ath12k_wmi_bcn_tmpl_ema_arg ema_args;
struct ieee80211_ema_beacons *beacons;
- struct ath12k_vif *tx_arvif;
+ struct ath12k_link_vif *tx_arvif;
bool nontx_profile_found = false;
+ struct ath12k_vif *tx_ahvif;
int ret = 0;
u8 i;
- tx_arvif = ath12k_vif_to_arvif(arvif->vif->mbssid_tx_vif);
+ tx_ahvif = ath12k_vif_to_ahvif(ahvif->vif->mbssid_tx_vif);
+ tx_arvif = &tx_ahvif->deflink;
beacons = ieee80211_beacon_get_template_ema_list(ath12k_ar_to_hw(tx_arvif->ar),
- tx_arvif->vif, 0);
+ tx_ahvif->vif, 0);
if (!beacons || !beacons->cnt) {
ath12k_warn(arvif->ar->ab,
"failed to get ema beacon templates from mac80211\n");
@@ -1520,22 +1536,25 @@ static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_vif *arvif)
return ret;
}
-static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
+static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif)
{
- struct ath12k_vif *tx_arvif = arvif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ath12k_link_vif *tx_arvif = arvif;
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
- struct ieee80211_vif *vif = arvif->vif;
struct ieee80211_mutable_offsets offs = {};
+ struct ath12k_vif *tx_ahvif = ahvif;
bool nontx_profile_found = false;
struct sk_buff *bcn;
int ret;
- if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_AP)
return 0;
if (vif->mbssid_tx_vif) {
- tx_arvif = ath12k_vif_to_arvif(vif->mbssid_tx_vif);
+ tx_ahvif = ath12k_vif_to_ahvif(vif->mbssid_tx_vif);
+ tx_arvif = &tx_ahvif->deflink;
if (tx_arvif != arvif && arvif->is_up)
return 0;
@@ -1543,7 +1562,7 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
return ath12k_mac_setup_bcn_tmpl_ema(arvif);
}
- bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_arvif->vif,
+ bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_ahvif->vif,
&offs, 0);
if (!bcn) {
ath12k_warn(ab, "failed to get beacon template from mac80211\n");
@@ -1554,14 +1573,14 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif)
ath12k_mac_set_arvif_ies(arvif, bcn, 0, NULL);
} else {
ath12k_mac_set_arvif_ies(arvif, bcn,
- arvif->vif->bss_conf.bssid_index,
+ ahvif->vif->bss_conf.bssid_index,
&nontx_profile_found);
if (!nontx_profile_found)
ath12k_warn(ab,
"nontransmitted profile not found in beacon template\n");
}
- if (arvif->vif->type == NL80211_IFTYPE_AP && arvif->vif->p2p) {
+ if (ahvif->vif->type == NL80211_IFTYPE_AP && ahvif->vif->p2p) {
ret = ath12k_mac_setup_bcn_p2p_ie(arvif, bcn);
if (ret) {
ath12k_warn(ab, "failed to setup P2P GO bcn ie: %d\n",
@@ -1595,14 +1614,15 @@ free_bcn_skb:
return ret;
}
-static void ath12k_control_beaconing(struct ath12k_vif *arvif,
+static void ath12k_control_beaconing(struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info)
{
struct ath12k_wmi_vdev_up_params params = {};
+ struct ath12k_vif *ahvif = arvif->ahvif;
struct ath12k *ar = arvif->ar;
int ret;
- lockdep_assert_held(&arvif->ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(arvif->ar)->wiphy);
if (!info->enable_beacon) {
ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id);
@@ -1622,15 +1642,19 @@ static void ath12k_control_beaconing(struct ath12k_vif *arvif,
return;
}
- arvif->aid = 0;
+ ahvif->aid = 0;
ether_addr_copy(arvif->bssid, info->bssid);
params.vdev_id = arvif->vdev_id;
- params.aid = arvif->aid;
+ params.aid = ahvif->aid;
params.bssid = arvif->bssid;
- if (arvif->vif->mbssid_tx_vif) {
- params.tx_bssid = ath12k_vif_to_arvif(arvif->vif->mbssid_tx_vif)->bssid;
+ if (ahvif->vif->mbssid_tx_vif) {
+ struct ath12k_vif *tx_ahvif =
+ ath12k_vif_to_ahvif(ahvif->vif->mbssid_tx_vif);
+ struct ath12k_link_vif *tx_arvif = &tx_ahvif->deflink;
+
+ params.tx_bssid = tx_arvif->bssid;
params.nontx_profile_idx = info->bssid_index;
params.nontx_profile_cnt = 1 << info->bssid_indicator;
}
@@ -1651,7 +1675,8 @@ static void ath12k_mac_handle_beacon_iter(void *data, u8 *mac,
{
struct sk_buff *skb = data;
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
if (vif->type != NL80211_IFTYPE_STATION)
return;
@@ -1674,7 +1699,8 @@ static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
u32 *vdev_id = data;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k *ar = arvif->ar;
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
@@ -1705,9 +1731,9 @@ void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id)
static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work)
{
- struct ath12k_vif *arvif = container_of(work, struct ath12k_vif,
- connection_loss_work.work);
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif,
+ connection_loss_work.work);
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
if (!arvif->is_up)
return;
@@ -1716,15 +1742,16 @@ static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work)
}
static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
u32 aid;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
if (vif->type == NL80211_IFTYPE_STATION)
aid = vif->cfg.aid;
@@ -1742,21 +1769,22 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ieee80211_bss_conf *info = &vif->bss_conf;
struct cfg80211_chan_def def;
struct cfg80211_bss *bss;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
const u8 *rsnie = NULL;
const u8 *wpaie = NULL;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
bss = cfg80211_get_bss(hw->wiphy, def.chan, info->bssid, NULL, 0,
@@ -1804,11 +1832,12 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
struct cfg80211_chan_def def;
const struct ieee80211_supported_band *sband;
@@ -1819,9 +1848,9 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
u8 rate;
int i;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -1867,12 +1896,13 @@ ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
}
static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -1880,9 +1910,9 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
u8 max_nss;
u32 stbc;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
if (!ht_cap->ht_supported)
@@ -2028,12 +2058,13 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
}
static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
enum nl80211_band band;
const u16 *vht_mcs_mask;
@@ -2042,7 +2073,9 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
u8 max_nss, vht_mcs;
int i;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
if (!vht_cap->vht_supported)
@@ -2123,10 +2156,12 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_he(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
int i;
u8 ampdu_factor, max_nss;
@@ -2278,16 +2313,18 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
struct cfg80211_chan_def def;
enum nl80211_band band;
u8 ampdu_factor, mpdu_density;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -2347,9 +2384,10 @@ static int ath12k_get_smps_from_capa(const struct ieee80211_sta_ht_cap *ht_cap,
return 0;
}
-static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
+static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_he_6ghz_capa *he_6ghz_capa = &sta->deflink.he_6ghz_capa;
const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
int smps;
@@ -2376,13 +2414,13 @@ static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta,
}
static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
if (sta->wme) {
/* TODO: Check WME vs QoS */
@@ -2412,15 +2450,16 @@ static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
}
static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,
- struct ath12k_vif *arvif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_ap_ps_arg arg;
u32 max_sp;
u32 uapsd;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
arg.vdev_id = arvif->vdev_id;
@@ -2574,18 +2613,22 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
}
static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
enum wmi_phy_mode phymode = MODE_UNKNOWN;
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
+
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -2719,17 +2762,19 @@ static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,
}
static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
const struct ieee80211_eht_mcs_nss_supp_bw *bw;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
u32 *rx_mcs, *tx_mcs;
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
return;
@@ -2802,34 +2847,34 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
}
static void ath12k_peer_assoc_prepare(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg,
bool reassoc)
{
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
memset(arg, 0, sizeof(*arg));
reinit_completion(&ar->peer_assoc_done);
arg->peer_new_assoc = !reassoc;
- ath12k_peer_assoc_h_basic(ar, vif, sta, arg);
- ath12k_peer_assoc_h_crypto(ar, vif, sta, arg);
- ath12k_peer_assoc_h_rates(ar, vif, sta, arg);
- ath12k_peer_assoc_h_ht(ar, vif, sta, arg);
- ath12k_peer_assoc_h_vht(ar, vif, sta, arg);
- ath12k_peer_assoc_h_he(ar, vif, sta, arg);
- ath12k_peer_assoc_h_he_6ghz(ar, vif, sta, arg);
- ath12k_peer_assoc_h_eht(ar, vif, sta, arg);
- ath12k_peer_assoc_h_qos(ar, vif, sta, arg);
- ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);
- ath12k_peer_assoc_h_smps(sta, arg);
+ ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_rates(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_ht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_vht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_he(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_he_6ghz(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_eht(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_qos(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, arg);
+ ath12k_peer_assoc_h_smps(arsta, arg);
/* TODO: amsdu_disable req? */
}
-static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,
+static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_link_vif *arvif,
const u8 *addr,
const struct ieee80211_sta_ht_cap *ht_cap,
const struct ieee80211_he_6ghz_capa *he_6ghz_capa)
@@ -2849,21 +2894,24 @@ static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif,
}
static void ath12k_bss_assoc(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *bss_conf)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_up_params params = {};
struct ath12k_wmi_peer_assoc_arg peer_arg;
+ struct ath12k_link_sta *arsta;
struct ieee80211_sta *ap_sta;
+ struct ath12k_sta *ahsta;
struct ath12k_peer *peer;
bool is_auth = false;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
- arvif->vdev_id, arvif->bssid, arvif->aid);
+ arvif->vdev_id, arvif->bssid, ahvif->aid);
rcu_read_lock();
@@ -2875,7 +2923,15 @@ static void ath12k_bss_assoc(struct ath12k *ar,
return;
}
- ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false);
+ ahsta = ath12k_sta_to_ahsta(ap_sta);
+ arsta = &ahsta->deflink;
+
+ if (WARN_ON(!arsta)) {
+ rcu_read_unlock();
+ return;
+ }
+
+ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, false);
rcu_read_unlock();
@@ -2903,11 +2959,11 @@ static void ath12k_bss_assoc(struct ath12k *ar,
WARN_ON(arvif->is_up);
- arvif->aid = vif->cfg.aid;
+ ahvif->aid = vif->cfg.aid;
ether_addr_copy(arvif->bssid, bss_conf->bssid);
params.vdev_id = arvif->vdev_id;
- params.aid = arvif->aid;
+ params.aid = ahvif->aid;
params.bssid = arvif->bssid;
ret = ath12k_wmi_vdev_up(ar, &params);
if (ret) {
@@ -2949,11 +3005,11 @@ static void ath12k_bss_assoc(struct ath12k *ar,
}
static void ath12k_bss_disassoc(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
arvif->vdev_id, arvif->bssid);
@@ -2996,10 +3052,10 @@ static u32 ath12k_mac_get_rate_hw_value(int bitrate)
}
static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
- struct ieee80211_vif *vif,
+ struct ath12k_link_vif *arvif,
struct cfg80211_chan_def *def)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
const struct ieee80211_supported_band *sband;
u8 basic_rate_idx;
@@ -3008,7 +3064,7 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
u16 bitrate;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
sband = hw->wiphy->bands[def->chan->band];
basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
@@ -3033,9 +3089,19 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
ath12k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret);
}
-static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
+static int
+ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 old_links, u16 new_links,
+ struct ieee80211_bss_conf *ol[IEEE80211_MLD_MAX_NUM_LINKS])
+{
+ return 0;
+}
+
+static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ath12k *ar = arvif->ar;
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
struct sk_buff *tmpl;
@@ -3046,7 +3112,7 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
if (info->fils_discovery.max_interval) {
interval = info->fils_discovery.max_interval;
- tmpl = ieee80211_get_fils_discovery_tmpl(hw, arvif->vif);
+ tmpl = ieee80211_get_fils_discovery_tmpl(hw, vif);
if (tmpl)
ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id,
tmpl);
@@ -3054,8 +3120,7 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
unsol_bcast_probe_resp_enabled = 1;
interval = info->unsol_bcast_probe_resp_interval;
- tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw,
- arvif->vif);
+ tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
if (tmpl)
ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id,
tmpl);
@@ -3080,10 +3145,44 @@ static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif,
return ret;
}
-static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif)
+static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u64 changed)
+{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ unsigned long links = ahvif->links_map;
+ struct ath12k_link_vif *arvif;
+ struct ath12k *ar;
+ u8 link_id;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (changed & BSS_CHANGED_SSID && vif->type == NL80211_IFTYPE_AP) {
+ ahvif->u.ap.ssid_len = vif->cfg.ssid_len;
+ if (vif->cfg.ssid_len)
+ memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
+ }
+
+ if (changed & BSS_CHANGED_ASSOC) {
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!arvif || !arvif->ar)
+ continue;
+
+ ar = arvif->ar;
+
+ if (vif->cfg.assoc)
+ ath12k_bss_assoc(ar, arvif, &vif->bss_conf);
+ else
+ ath12k_bss_disassoc(ar, arvif);
+ }
+ }
+}
+
+static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
- struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf;
enum wmi_sta_powersave_param param;
enum wmi_sta_ps_mode psmode;
@@ -3091,12 +3190,12 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif)
int timeout;
bool enable_ps;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (vif->type != NL80211_IFTYPE_STATION)
return;
- enable_ps = arvif->ps;
+ enable_ps = arvif->ahvif->ps;
if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
@@ -3128,11 +3227,12 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_vif *arvif)
}
static void ath12k_mac_bss_info_changed(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info,
u64 changed)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ieee80211_vif_cfg *vif_cfg = &vif->cfg;
struct cfg80211_chan_def def;
u32 param_id, param_value;
@@ -3146,7 +3246,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
u8 rateidx;
u32 rate;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (changed & BSS_CHANGED_BEACON_INT) {
arvif->beacon_interval = info->beacon_int;
@@ -3202,10 +3302,10 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
if (changed & BSS_CHANGED_SSID &&
vif->type == NL80211_IFTYPE_AP) {
- arvif->u.ap.ssid_len = vif->cfg.ssid_len;
+ ahvif->u.ap.ssid_len = vif->cfg.ssid_len;
if (vif->cfg.ssid_len)
- memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
- arvif->u.ap.hidden_ssid = info->hidden_ssid;
+ memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len);
+ ahvif->u.ap.hidden_ssid = info->hidden_ssid;
}
if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
@@ -3316,7 +3416,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
}
if (changed & BSS_CHANGED_MCAST_RATE &&
- !ath12k_mac_vif_chan(arvif->vif, &def)) {
+ !ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) {
band = def.chan->band;
mcast_rate = vif->bss_conf.mcast_rate[band];
@@ -3360,8 +3460,8 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
}
if (changed & BSS_CHANGED_BASIC_RATES &&
- !ath12k_mac_vif_chan(arvif->vif, &def))
- ath12k_recalculate_mgmt_rate(ar, vif, &def);
+ !ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))
+ ath12k_recalculate_mgmt_rate(ar, arvif, &def);
if (changed & BSS_CHANGED_TWT) {
if (info->twt_requester || info->twt_responder)
@@ -3406,53 +3506,177 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
if (changed & BSS_CHANGED_PS &&
ar->ab->hw_params->supports_sta_ps) {
- arvif->ps = vif_cfg->ps;
+ ahvif->ps = vif_cfg->ps;
ath12k_mac_vif_setup_ps(arvif);
}
}
-static struct ath12k_vif_cache *ath12k_arvif_get_cache(struct ath12k_vif *arvif)
+static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif,
+ u8 link_id)
+{
+ if (!ahvif->cache[link_id]) {
+ ahvif->cache[link_id] = kzalloc(sizeof(*ahvif->cache[0]), GFP_KERNEL);
+ if (ahvif->cache[link_id])
+ INIT_LIST_HEAD(&ahvif->cache[link_id]->key_conf.list);
+ }
+
+ return ahvif->cache[link_id];
+}
+
+static void ath12k_ahvif_put_link_key_cache(struct ath12k_vif_cache *cache)
{
- if (!arvif->cache)
- arvif->cache = kzalloc(sizeof(*arvif->cache), GFP_KERNEL);
+ struct ath12k_key_conf *key_conf, *tmp;
- return arvif->cache;
+ if (!cache || list_empty(&cache->key_conf.list))
+ return;
+ list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) {
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ }
}
-static void ath12k_arvif_put_cache(struct ath12k_vif *arvif)
+static void ath12k_ahvif_put_link_cache(struct ath12k_vif *ahvif, u8 link_id)
{
- kfree(arvif->cache);
- arvif->cache = NULL;
+ ath12k_ahvif_put_link_key_cache(ahvif->cache[link_id]);
+ kfree(ahvif->cache[link_id]);
+ ahvif->cache[link_id] = NULL;
}
-static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info,
- u64 changed)
+static void ath12k_mac_op_link_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u64 changed)
{
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_vif_cache *cache;
+ struct ath12k_link_vif *arvif;
+ u8 link_id = info->link_id;
- ar = ath12k_get_ar_by_vif(hw, vif);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
/* if the vdev is not created on a certain radio,
* cache the info to be updated later on vdev creation
*/
- if (!ar) {
- cache = ath12k_arvif_get_cache(arvif);
+ if (!arvif || !arvif->is_created) {
+ cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
if (!cache)
return;
- arvif->cache->bss_conf_changed |= changed;
+
+ cache->bss_conf_changed |= changed;
+
return;
}
- mutex_lock(&ar->conf_mutex);
+ ar = arvif->ar;
ath12k_mac_bss_info_changed(ar, arvif, info, changed);
+}
+
+static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah,
+ struct ieee80211_vif *vif,
+ u8 link_id)
+{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ int i;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+ if (arvif)
+ return arvif;
+
+ if (!vif->valid_links) {
+ /* Use deflink for Non-ML VIFs and mark the link id as 0
+ */
+ link_id = 0;
+ arvif = &ahvif->deflink;
+ } else {
+ /* If this is the first link arvif being created for an ML VIF
+ * use the preallocated deflink memory
+ */
+ if (!ahvif->links_map) {
+ arvif = &ahvif->deflink;
+ } else {
+ arvif = (struct ath12k_link_vif *)
+ kzalloc(sizeof(struct ath12k_link_vif), GFP_KERNEL);
+ if (!arvif)
+ return NULL;
+ }
+ }
+
+ arvif->ahvif = ahvif;
+ arvif->link_id = link_id;
+ ahvif->links_map |= BIT(link_id);
+
+ INIT_LIST_HEAD(&arvif->list);
+ INIT_DELAYED_WORK(&arvif->connection_loss_work,
+ ath12k_mac_vif_sta_connection_loss_work);
+
+ for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
+ arvif->bitrate_mask.control[i].legacy = 0xffffffff;
+ memset(arvif->bitrate_mask.control[i].ht_mcs, 0xff,
+ sizeof(arvif->bitrate_mask.control[i].ht_mcs));
+ memset(arvif->bitrate_mask.control[i].vht_mcs, 0xff,
+ sizeof(arvif->bitrate_mask.control[i].vht_mcs));
+ }
+
+ /* Allocate Default Queue now and reassign during actual vdev create */
+ vif->cab_queue = ATH12K_HW_DEFAULT_QUEUE;
+ for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
+ vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE;
- mutex_unlock(&ar->conf_mutex);
+ vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
+
+ rcu_assign_pointer(ahvif->link[arvif->link_id], arvif);
+ ahvif->links_map |= BIT(link_id);
+ synchronize_rcu();
+ return arvif;
+}
+
+static void ath12k_mac_unassign_link_vif(struct ath12k_link_vif *arvif)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_hw *ah = ahvif->ah;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ rcu_assign_pointer(ahvif->link[arvif->link_id], NULL);
+ synchronize_rcu();
+ ahvif->links_map &= ~BIT(arvif->link_id);
+
+ if (arvif != &ahvif->deflink)
+ kfree(arvif);
+ else
+ memset(arvif, 0, sizeof(*arvif));
+}
+
+static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw,
+ struct ath12k_link_vif *arvif)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_hw *ah = hw->priv;
+ struct ath12k *ar = arvif->ar;
+ int ret;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ cancel_delayed_work_sync(&arvif->connection_loss_work);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac remove link interface (vdev %d link id %d)",
+ arvif->vdev_id, arvif->link_id);
+
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ ret = ath12k_peer_delete(ar, arvif->vdev_id, arvif->bssid);
+ if (ret)
+ ath12k_warn(ar->ab, "failed to submit AP self-peer removal on vdev %d link id %d: %d",
+ arvif->vdev_id, arvif->link_id, ret);
+ }
+ ath12k_mac_vdev_delete(ar, arvif);
}
static struct ath12k*
@@ -3541,7 +3765,7 @@ static int ath12k_scan_stop(struct ath12k *ar)
};
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
/* TODO: Fill other STOP Params */
arg.pdev_id = ar->pdev->pdev_id;
@@ -3581,7 +3805,7 @@ static void ath12k_scan_abort(struct ath12k *ar)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ar->data_lock);
@@ -3616,9 +3840,9 @@ static void ath12k_scan_timeout_work(struct work_struct *work)
struct ath12k *ar = container_of(work, struct ath12k,
scan.timeout.work);
- mutex_lock(&ar->conf_mutex);
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ath12k_scan_abort(ar);
- mutex_unlock(&ar->conf_mutex);
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
}
static int ath12k_start_scan(struct ath12k *ar,
@@ -3626,7 +3850,7 @@ static int ath12k_start_scan(struct ath12k *ar,
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_send_scan_start_cmd(ar, arg);
if (ret)
@@ -3655,24 +3879,50 @@ static int ath12k_start_scan(struct ath12k *ar,
return 0;
}
+static u8
+ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
+{
+ struct ath12k_link_vif *arvif;
+ struct ath12k_hw *ah = ahvif->ah;
+ unsigned long links = ahvif->links_map;
+ u8 link_id;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+
+ if (!arvif || !arvif->is_created)
+ continue;
+
+ if (ar == arvif->ar)
+ return link_id;
+ }
+
+ /* input ar is not assigned to any of the links, use link id
+ * 0 for scan vdev creation.
+ */
+ return 0;
+}
+
static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
- struct ath12k *ar, *prev_ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k *ar;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
struct cfg80211_scan_request *req = &hw_req->req;
struct ath12k_wmi_scan_req_arg *arg = NULL;
+ u8 link_id;
int ret;
int i;
bool create = true;
- if (ah->num_radio == 1) {
- WARN_ON(!arvif->is_created);
- ar = ath12k_ah_to_ar(ah, 0);
- goto scan;
- }
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
/* Since the targeted scan device could depend on the frequency
* requested in the hw_req, select the corresponding radio
@@ -3681,6 +3931,13 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
if (!ar)
return -EINVAL;
+ /* check if any of the links of ML VIF is already started on
+ * radio(ar) correpsondig to given scan frequency and use it,
+ * if not use deflink(link 0) for scan purpose.
+ */
+ link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar);
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+
/* If the vif is already assigned to a specific vdev of an ar,
* check whether its already started, vdev which is started
* are not allowed to switch to a new radio.
@@ -3698,31 +3955,24 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
return -EINVAL;
if (ar != arvif->ar) {
- /* backup the previously used ar ptr, since the vdev delete
- * would assign the arvif->ar to NULL after the call
- */
- prev_ar = arvif->ar;
- mutex_lock(&prev_ar->conf_mutex);
- ret = ath12k_mac_vdev_delete(prev_ar, vif);
- mutex_unlock(&prev_ar->conf_mutex);
- if (ret)
- ath12k_warn(prev_ar->ab,
- "unable to delete scan vdev %d\n", ret);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
} else {
create = false;
}
}
if (create) {
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_vdev_create(ar, vif);
- mutex_unlock(&ar->conf_mutex);
+ /* Previous arvif would've been cleared in radio switch block
+ * above, assign arvif again for create.
+ */
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+
+ ret = ath12k_mac_vdev_create(ar, arvif);
if (ret) {
ath12k_warn(ar->ab, "unable to create scan vdev %d\n", ret);
return -EINVAL;
}
}
-scan:
- mutex_lock(&ar->conf_mutex);
spin_lock_bh(&ar->data_lock);
switch (ar->scan.state) {
@@ -3805,30 +4055,31 @@ exit:
kfree(arg);
}
- mutex_unlock(&ar->conf_mutex);
-
return ret;
}
static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
struct ath12k *ar;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+
if (!arvif->is_created)
return;
ar = arvif->ar;
- mutex_lock(&ar->conf_mutex);
ath12k_scan_abort(ar);
- mutex_unlock(&ar->conf_mutex);
cancel_delayed_work_sync(&ar->scan.timeout);
}
-static int ath12k_install_key(struct ath12k_vif *arvif,
+static int ath12k_install_key(struct ath12k_link_vif *arvif,
struct ieee80211_key_conf *key,
enum set_key_cmd cmd,
const u8 *macaddr, u32 flags)
@@ -3843,8 +4094,10 @@ static int ath12k_install_key(struct ath12k_vif *arvif,
.key_flags = flags,
.macaddr = macaddr,
};
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
- lockdep_assert_held(&arvif->ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->install_key_done);
@@ -3895,13 +4148,13 @@ install:
if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ))
return -ETIMEDOUT;
- if (ether_addr_equal(macaddr, arvif->vif->addr))
- arvif->key_cipher = key->cipher;
+ if (ether_addr_equal(macaddr, vif->addr))
+ ahvif->key_cipher = key->cipher;
return ar->install_key_status ? -EINVAL : 0;
}
-static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
+static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif,
const u8 *addr)
{
struct ath12k *ar = arvif->ar;
@@ -3912,7 +4165,7 @@ static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
int i;
u32 flags = 0;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ab->base_lock);
peer = ath12k_peer_find(ab, arvif->vdev_id, addr);
@@ -3944,25 +4197,31 @@ static int ath12k_clear_peer_keys(struct ath12k_vif *arvif,
}
static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
struct ieee80211_key_conf *key)
{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ieee80211_sta *sta = NULL;
struct ath12k_base *ab = ar->ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
struct ath12k_peer *peer;
- struct ath12k_sta *arsta;
+ struct ath12k_sta *ahsta;
const u8 *peer_addr;
- int ret = 0;
+ int ret;
u32 flags = 0;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ if (arsta)
+ sta = ath12k_ahsta_to_sta(arsta->ahsta);
if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags))
return 1;
if (sta)
peer_addr = sta->addr;
- else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
+ else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA)
peer_addr = vif->bss_conf.bssid;
else
peer_addr = vif->addr;
@@ -3970,7 +4229,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
key->hw_key_idx = key->keyidx;
/* the peer should not disappear in mid-way (unless FW goes awry) since
- * we already hold conf_mutex. we just make sure its there now.
+ * we already hold wiphy lock. we just make sure its there now.
*/
spin_lock_bh(&ab->base_lock);
peer = ath12k_peer_find(ab, arvif->vdev_id, peer_addr);
@@ -3980,14 +4239,13 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
if (cmd == SET_KEY) {
ath12k_warn(ab, "cannot install key for non-existent peer %pM\n",
peer_addr);
- ret = -EOPNOTSUPP;
- goto exit;
- } else {
- /* if the peer doesn't exist there is no key to disable
- * anymore
- */
- goto exit;
+ return -EOPNOTSUPP;
}
+
+ /* if the peer doesn't exist there is no key to disable
+ * anymore
+ */
+ return 0;
}
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
@@ -3998,13 +4256,13 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags);
if (ret) {
ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret);
- goto exit;
+ return ret;
}
ret = ath12k_dp_rx_peer_pn_replay_config(arvif, peer_addr, cmd, key);
if (ret) {
ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret);
- goto exit;
+ return ret;
}
spin_lock_bh(&ab->base_lock);
@@ -4029,7 +4287,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr);
if (sta) {
- arsta = ath12k_sta_to_arsta(sta);
+ ahsta = ath12k_sta_to_ahsta(sta);
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
@@ -4038,61 +4296,138 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
if (cmd == SET_KEY)
- arsta->pn_type = HAL_PN_TYPE_WPA;
+ ahsta->pn_type = HAL_PN_TYPE_WPA;
else
- arsta->pn_type = HAL_PN_TYPE_NONE;
+ ahsta->pn_type = HAL_PN_TYPE_NONE;
break;
default:
- arsta->pn_type = HAL_PN_TYPE_NONE;
+ ahsta->pn_type = HAL_PN_TYPE_NONE;
break;
}
}
spin_unlock_bh(&ab->base_lock);
-exit:
- return ret;
+ return 0;
+}
+
+static int ath12k_mac_update_key_cache(struct ath12k_vif_cache *cache,
+ enum set_key_cmd cmd,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct ath12k_key_conf *key_conf = NULL, *tmp;
+
+ if (cmd == SET_KEY) {
+ key_conf = kzalloc(sizeof(*key_conf), GFP_KERNEL);
+
+ if (!key_conf)
+ return -ENOMEM;
+
+ key_conf->cmd = cmd;
+ key_conf->sta = sta;
+ key_conf->key = key;
+ list_add_tail(&key_conf->list,
+ &cache->key_conf.list);
+ }
+ if (list_empty(&cache->key_conf.list))
+ return 0;
+ list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) {
+ if (key_conf->key == key) {
+ /* DEL key for an old SET key which driver hasn't flushed yet.
+ */
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ break;
+ }
+ }
+ return 0;
}
static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta = NULL;
struct ath12k_vif_cache *cache;
- struct ath12k *ar;
+ struct ath12k_sta *ahsta;
+ unsigned long links;
+ u8 link_id;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
/* BIP needs to be done in software */
if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
- key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
+ key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) {
return 1;
+ }
if (key->keyidx > WMI_MAX_KEY_INDEX)
return -ENOSPC;
- ar = ath12k_get_ar_by_vif(hw, vif);
- if (!ar) {
- /* ar is expected to be valid when sta ptr is available */
- if (sta) {
- WARN_ON_ONCE(1);
- return -EINVAL;
+ if (sta) {
+ ahsta = ath12k_sta_to_ahsta(sta);
+ /* For an ML STA Pairwise key is same for all associated link Stations,
+ * hence do set key for all link STAs which are active.
+ */
+ if (sta->mlo) {
+ links = ahsta->links_map;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy,
+ ahvif->link[link_id]);
+ arsta = wiphy_dereference(hw->wiphy,
+ ahsta->link[link_id]);
+
+ if (WARN_ON(!arvif || !arsta))
+ /* arvif and arsta are expected to be valid when
+ * STA is present.
+ */
+ continue;
+
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif,
+ arsta, key);
+ if (ret)
+ break;
+ }
+ } else {
+ arsta = &ahsta->deflink;
+ arvif = arsta->arvif;
+ if (WARN_ON(!arvif)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key);
+ }
+ } else {
+ if (key->link_id >= 0 && key->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ link_id = key->link_id;
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ } else {
+ link_id = 0;
+ arvif = &ahvif->deflink;
}
- cache = ath12k_arvif_get_cache(arvif);
- if (!cache)
- return -ENOSPC;
- cache->key_conf.cmd = cmd;
- cache->key_conf.key = key;
- cache->key_conf.changed = true;
- return 0;
+ if (!arvif || !arvif->is_created) {
+ cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
+ if (!cache)
+ return -ENOSPC;
+
+ ret = ath12k_mac_update_key_cache(cache, cmd, sta, key);
+
+ return ret;
+ }
+
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, NULL, key);
}
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_set_key(ar, cmd, vif, sta, key);
- mutex_unlock(&ar->conf_mutex);
+out:
+
return ret;
}
@@ -4111,17 +4446,18 @@ ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar,
}
static int
-ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,
- struct ieee80211_sta *sta,
+ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
const struct cfg80211_bitrate_mask *mask,
enum nl80211_band band)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
u8 vht_rate, nss;
u32 rate_code;
int ret, i;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
nss = 0;
@@ -4157,11 +4493,12 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif,
}
static int ath12k_station_assoc(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
bool reassoc)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_assoc_arg peer_arg;
int ret;
struct cfg80211_chan_def def;
@@ -4169,15 +4506,15 @@ static int ath12k_station_assoc(struct ath12k *ar,
struct cfg80211_bitrate_mask *mask;
u8 num_vht_rates;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (WARN_ON(ath12k_mac_vif_chan(vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return -EPERM;
band = def.chan->band;
mask = &arvif->bitrate_mask;
- ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc);
+ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, reassoc);
if (peer_arg.peer_nss < 1) {
ath12k_warn(ar->ab,
@@ -4205,7 +4542,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
* Note that all other rates and NSS will be disabled for this peer.
*/
if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
- ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
+ ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
if (ret)
return ret;
@@ -4234,7 +4571,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
}
if (sta->wme && sta->uapsd_queues) {
- ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta);
+ ret = ath12k_peer_assoc_qos_ap(ar, arvif, arsta);
if (ret) {
ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
sta->addr, arvif->vdev_id, ret);
@@ -4246,13 +4583,13 @@ static int ath12k_station_assoc(struct ath12k *ar,
}
static int ath12k_station_disassoc(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!sta->wme) {
arvif->num_legacy_stations--;
@@ -4270,11 +4607,10 @@ static int ath12k_station_disassoc(struct ath12k *ar,
return 0;
}
-static void ath12k_sta_rc_update_wk(struct work_struct *wk)
+static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
{
struct ath12k *ar;
- struct ath12k_vif *arvif;
- struct ath12k_sta *arsta;
+ struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
struct cfg80211_chan_def def;
enum nl80211_band band;
@@ -4285,13 +4621,18 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
const struct cfg80211_bitrate_mask *mask;
struct ath12k_wmi_peer_assoc_arg peer_arg;
enum wmi_phy_mode peer_phymode;
+ struct ath12k_link_sta *arsta;
+ struct ieee80211_vif *vif;
- arsta = container_of(wk, struct ath12k_sta, update_wk);
- sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
+ lockdep_assert_wiphy(wiphy);
+
+ arsta = container_of(wk, struct ath12k_link_sta, update_wk);
+ sta = ath12k_ahsta_to_sta(arsta->ahsta);
arvif = arsta->arvif;
+ vif = ath12k_ahvif_to_vif(arvif->ahvif);
ar = arvif->ar;
- if (WARN_ON(ath12k_mac_vif_chan(arvif->vif, &def)))
+ if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
band = def.chan->band;
@@ -4310,14 +4651,12 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
spin_unlock_bh(&ar->data_lock);
- mutex_lock(&ar->conf_mutex);
-
nss = max_t(u32, 1, nss);
nss = min(nss, max(ath12k_mac_max_ht_nss(ht_mcs_mask),
ath12k_mac_max_vht_nss(vht_mcs_mask)));
if (changed & IEEE80211_RC_BW_CHANGED) {
- ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
+ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, &peer_arg);
peer_phymode = peer_arg.peer_phymode;
if (bw > bw_prev) {
@@ -4334,7 +4673,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
if (err) {
ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
sta->addr, peer_phymode, err);
- goto err_rc_bw_changed;
+ return;
}
err = ath12k_wmi_set_peer_param(ar, sta->addr,
arvif->vdev_id, WMI_PEER_CHWIDTH,
@@ -4355,7 +4694,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
if (err) {
ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",
sta->addr, bw, err);
- goto err_rc_bw_changed;
+ return;
}
err = ath12k_wmi_set_peer_param(ar, sta->addr,
arvif->vdev_id, WMI_PEER_PHYMODE,
@@ -4405,14 +4744,14 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
* across HT/VHT and for multiple VHT MCS support.
*/
if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
- ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
+ ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
} else {
/* If the peer is non-VHT or no fixed VHT rate
* is provided in the new bitrate mask we set the
* other rates using peer_assoc command.
*/
- ath12k_peer_assoc_prepare(ar, arvif->vif, sta,
+ ath12k_peer_assoc_prepare(ar, arvif, arsta,
&peer_arg, true);
err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
@@ -4425,18 +4764,17 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
sta->addr, arvif->vdev_id);
}
}
-err_rc_bw_changed:
- mutex_unlock(&ar->conf_mutex);
}
-static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif,
- struct ieee80211_sta *sta)
+static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
+ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
return 0;
if (ar->num_stations >= ar->max_num_stations)
@@ -4447,38 +4785,38 @@ static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif,
return 0;
}
-static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif,
- struct ieee80211_sta *sta)
+static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
+ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls)
return;
ar->num_stations--;
}
static int ath12k_mac_station_add(struct ath12k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
struct ath12k_base *ab = ar->ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_create_arg peer_param;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- ret = ath12k_mac_inc_num_stations(arvif, sta);
+ ret = ath12k_mac_inc_num_stations(arvif, arsta);
if (ret) {
ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n",
ar->max_num_stations);
goto exit;
}
-
arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
if (!arsta->rx_stats) {
ret = -ENOMEM;
@@ -4519,7 +4857,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
if (ab->hw_params->vdev_start_delay &&
!arvif->is_started &&
- arvif->vdev_type != WMI_VDEV_TYPE_AP) {
+ arvif->ahvif->vdev_type != WMI_VDEV_TYPE_AP) {
ret = ath12k_start_vdev_delay(ar, arvif);
if (ret) {
ath12k_warn(ab, "failed to delay vdev start: %d\n", ret);
@@ -4532,7 +4870,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
free_peer:
ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
dec_num_station:
- ath12k_mac_dec_num_stations(arvif, sta);
+ ath12k_mac_dec_num_stations(arvif, arsta);
exit:
return ret;
}
@@ -4574,16 +4912,18 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta;
struct ath12k_peer *peer;
int ret = 0;
- /* cancel must be done outside the mutex to avoid deadlock */
- if ((old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST))
- cancel_work_sync(&arsta->update_wk);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+ arsta = &ahsta->deflink;
ar = ath12k_get_ar_by_vif(hw, vif);
if (!ar) {
@@ -4591,21 +4931,28 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
return -EINVAL;
}
- mutex_lock(&ar->conf_mutex);
-
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE) {
memset(arsta, 0, sizeof(*arsta));
+ rcu_assign_pointer(ahsta->link[0], arsta);
+ /* TODO use appropriate link id once MLO support is added */
+ arsta->link_id = ATH12K_DEFAULT_LINK_ID;
+ ahsta->links_map = BIT(arsta->link_id);
+ arsta->ahsta = ahsta;
arsta->arvif = arvif;
- INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk);
+ wiphy_work_init(&arsta->update_wk, ath12k_sta_rc_update_wk);
+
+ synchronize_rcu();
- ret = ath12k_mac_station_add(ar, vif, sta);
+ ret = ath12k_mac_station_add(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
sta->addr, arvif->vdev_id);
} else if ((old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)) {
- if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
+ wiphy_work_cancel(hw->wiphy, &arsta->update_wk);
+
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
ath12k_bss_disassoc(ar, arvif);
ret = ath12k_mac_vdev_stop(arvif);
if (ret)
@@ -4622,7 +4969,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
sta->addr, arvif->vdev_id);
- ath12k_mac_dec_num_stations(arvif, sta);
+ ath12k_mac_dec_num_stations(arvif, arsta);
spin_lock_bh(&ar->ab->base_lock);
peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
if (peer && peer->sta == sta) {
@@ -4637,12 +4984,20 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
kfree(arsta->rx_stats);
arsta->rx_stats = NULL;
+
+ if (arsta->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ rcu_assign_pointer(ahsta->link[arsta->link_id], NULL);
+ synchronize_rcu();
+ ahsta->links_map &= ~(BIT(arsta->link_id));
+ arsta->link_id = ATH12K_INVALID_LINK_ID;
+ arsta->ahsta = NULL;
+ }
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_assoc(ar, vif, sta, false);
+ ret = ath12k_station_assoc(ar, arvif, arsta, false);
if (ret)
ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
sta->addr);
@@ -4686,14 +5041,12 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_disassoc(ar, vif, sta);
+ ret = ath12k_station_disassoc(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",
sta->addr);
}
- mutex_unlock(&ar->conf_mutex);
-
return ret;
}
@@ -4703,25 +5056,32 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
int ret;
s16 txpwr;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+
if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
txpwr = 0;
} else {
txpwr = sta->deflink.txpwr.power;
- if (!txpwr)
- return -EINVAL;
+ if (!txpwr) {
+ ret = -EINVAL;
+ goto out;
+ }
}
- if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL)
- return -EINVAL;
+ if (txpwr > ATH12K_TX_POWER_MAX_VAL || txpwr < ATH12K_TX_POWER_MIN_VAL) {
+ ret = -EINVAL;
+ goto out;
+ }
ar = ath12k_ah_to_ar(ah, 0);
- mutex_lock(&ar->conf_mutex);
-
ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
WMI_PEER_USE_FIXED_PWR, txpwr);
if (ret) {
@@ -4731,20 +5091,26 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
}
out:
- mutex_unlock(&ar->conf_mutex);
return ret;
}
static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath12k *ar;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_sta *arsta;
+ struct ath12k_link_vif *arvif;
struct ath12k_peer *peer;
u32 bw, smps;
+ /* TODO: use proper link id once link sta specific rc update support is
+ * available in mac80211.
+ */
+ u8 link_id = ATH12K_DEFAULT_LINK_ID;
ar = ath12k_get_ar_by_vif(hw, vif);
if (!ar) {
@@ -4752,11 +5118,27 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
return;
}
+ rcu_read_lock();
+ arvif = rcu_dereference(ahvif->link[link_id]);
+ if (!arvif) {
+ ath12k_warn(ar->ab, "mac sta rc update failed to fetch link vif on link id %u for peer %pM\n",
+ link_id, sta->addr);
+ rcu_read_unlock();
+ return;
+ }
+ arsta = rcu_dereference(ahsta->link[link_id]);
+ if (!arsta) {
+ rcu_read_unlock();
+ ath12k_warn(ar->ab, "mac sta rc update failed to fetch link sta on link id %u for peer %pM\n",
+ link_id, sta->addr);
+ return;
+ }
spin_lock_bh(&ar->ab->base_lock);
peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
if (!peer) {
spin_unlock_bh(&ar->ab->base_lock);
+ rcu_read_unlock();
ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
sta->addr, arvif->vdev_id);
return;
@@ -4808,17 +5190,20 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->data_lock);
- ieee80211_queue_work(hw, &arsta->update_wk);
+ wiphy_work_queue(hw->wiphy, &arsta->update_wk);
+
+ rcu_read_unlock();
}
-static int ath12k_conf_tx_uapsd(struct ath12k_vif *arvif,
+static int ath12k_conf_tx_uapsd(struct ath12k_link_vif *arvif,
u16 ac, bool enable)
{
struct ath12k *ar = arvif->ar;
+ struct ath12k_vif *ahvif = arvif->ahvif;
u32 value;
int ret;
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_STA)
return 0;
switch (ac) {
@@ -4841,19 +5226,19 @@ static int ath12k_conf_tx_uapsd(struct ath12k_vif *arvif,
}
if (enable)
- arvif->u.sta.uapsd |= value;
+ ahvif->u.sta.uapsd |= value;
else
- arvif->u.sta.uapsd &= ~value;
+ ahvif->u.sta.uapsd &= ~value;
ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
WMI_STA_PS_PARAM_UAPSD,
- arvif->u.sta.uapsd);
+ ahvif->u.sta.uapsd);
if (ret) {
ath12k_warn(ar->ab, "could not set uapsd params %d\n", ret);
goto exit;
}
- if (arvif->u.sta.uapsd)
+ if (ahvif->u.sta.uapsd)
value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
else
value = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
@@ -4868,8 +5253,7 @@ exit:
return ret;
}
-static int ath12k_mac_conf_tx(struct ath12k_vif *arvif,
- unsigned int link_id, u16 ac,
+static int ath12k_mac_conf_tx(struct ath12k_link_vif *arvif, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
struct wmi_wmm_params_arg *p = NULL;
@@ -4877,7 +5261,7 @@ static int ath12k_mac_conf_tx(struct ath12k_vif *arvif,
struct ath12k_base *ab = ar->ab;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
switch (ac) {
case IEEE80211_AC_VO:
@@ -4926,26 +5310,30 @@ static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw,
unsigned int link_id, u16 ac,
const struct ieee80211_tx_queue_params *params)
{
- struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_vif_cache *cache = arvif->cache;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif_cache *cache;
int ret;
- ar = ath12k_get_ar_by_vif(hw, vif);
- if (!ar) {
- /* cache the info and apply after vdev is created */
- cache = ath12k_arvif_get_cache(arvif);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+ return -EINVAL;
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!arvif || !arvif->is_created) {
+ cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
if (!cache)
return -ENOSPC;
+
cache->tx_conf.changed = true;
cache->tx_conf.ac = ac;
cache->tx_conf.tx_queue_params = *params;
+
return 0;
}
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_conf_tx(arvif, link_id, ac, params);
- mutex_unlock(&ar->conf_mutex);
+ ret = ath12k_mac_conf_tx(arvif, ac, params);
return ret;
}
@@ -5016,10 +5404,11 @@ ath12k_create_ht_cap(struct ath12k *ar, u32 ar_ht_cap, u32 rate_cap_rx_chainmask
return ht_cap;
}
-static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
+static int ath12k_mac_set_txbf_conf(struct ath12k_link_vif *arvif)
{
u32 value = 0;
struct ath12k *ar = arvif->ar;
+ struct ath12k_vif *ahvif = arvif->ahvif;
int nsts;
int sound_dim;
u32 vht_cap = ar->pdev->cap.vht_cap;
@@ -5047,7 +5436,7 @@ static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
- arvif->vdev_type == WMI_VDEV_TYPE_AP)
+ ahvif->vdev_type == WMI_VDEV_TYPE_AP)
value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
}
@@ -5055,7 +5444,7 @@ static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif)
value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
- arvif->vdev_type == WMI_VDEV_TYPE_STA)
+ ahvif->vdev_type == WMI_VDEV_TYPE_STA)
value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
}
@@ -5612,7 +6001,7 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ath12k_check_chain_mask(ar, tx_ant, true))
return -EINVAL;
@@ -5716,7 +6105,7 @@ static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
return 0;
}
-static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
+static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct sk_buff *skb)
{
struct ath12k_base *ab = ar->ab;
@@ -5784,7 +6173,8 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
{
struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work);
struct ath12k_skb_cb *skb_cb;
- struct ath12k_vif *arvif;
+ struct ath12k_vif *ahvif;
+ struct ath12k_link_vif *arvif;
struct sk_buff *skb;
int ret;
@@ -5796,8 +6186,8 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
continue;
}
- arvif = ath12k_vif_to_arvif(skb_cb->vif);
-
+ ahvif = ath12k_vif_to_ahvif(skb_cb->vif);
+ arvif = &ahvif->deflink;
if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) {
ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb);
if (ret) {
@@ -5852,18 +6242,18 @@ static void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar,
struct sk_buff *skb,
bool is_prb_rsp)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
if (likely(!is_prb_rsp))
return;
spin_lock_bh(&ar->data_lock);
- if (arvif->u.ap.noa_data &&
- !pskb_expand_head(skb, 0, arvif->u.ap.noa_len,
+ if (ahvif->u.ap.noa_data &&
+ !pskb_expand_head(skb, 0, ahvif->u.ap.noa_len,
GFP_ATOMIC))
- skb_put_data(skb, arvif->u.ap.noa_data,
- arvif->u.ap.noa_len);
+ skb_put_data(skb, ahvif->u.ap.noa_data,
+ ahvif->u.ap.noa_len);
spin_unlock_bh(&ar->data_lock);
}
@@ -5875,7 +6265,8 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k *ar = arvif->ar;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_key_conf *key = info->control.hw_key;
@@ -5939,8 +6330,7 @@ static int ath12k_mac_start(struct ath12k *ar)
int ret;
lockdep_assert_held(&ah->hw_mutex);
-
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
1, pdev->pdev_id);
@@ -6025,14 +6415,11 @@ static int ath12k_mac_start(struct ath12k *ar)
}
}
- mutex_unlock(&ar->conf_mutex);
-
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx],
&ab->pdevs[ar->pdev_idx]);
return 0;
err:
- mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -6052,6 +6439,8 @@ static int ath12k_mac_op_start(struct ieee80211_hw *hw)
struct ath12k *ar;
int ret, i;
+ lockdep_assert_wiphy(hw->wiphy);
+
ath12k_drain_tx(ah);
guard(mutex)(&ah->hw_mutex);
@@ -6158,15 +6547,14 @@ static void ath12k_mac_stop(struct ath12k *ar)
int ret;
lockdep_assert_held(&ah->hw_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- mutex_lock(&ar->conf_mutex);
ret = ath12k_mac_config_mon_status_default(ar, false);
if (ret && (ret != -EOPNOTSUPP))
ath12k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",
ret);
clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
- mutex_unlock(&ar->conf_mutex);
cancel_delayed_work_sync(&ar->scan.timeout);
cancel_work_sync(&ar->regd_update_work);
@@ -6192,6 +6580,8 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
struct ath12k *ar;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
ath12k_drain_tx(ah);
mutex_lock(&ah->hw_mutex);
@@ -6205,7 +6595,7 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
}
static u8
-ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
+ath12k_mac_get_vdev_stats_id(struct ath12k_link_vif *arvif)
{
struct ath12k_base *ab = arvif->ar->ab;
u8 vdev_stats_id = 0;
@@ -6227,19 +6617,22 @@ ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
return vdev_stats_id;
}
-static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_vif *arvif,
+static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif,
u32 *flags, u32 *tx_vdev_id)
{
- struct ieee80211_vif *tx_vif = arvif->vif->mbssid_tx_vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *tx_vif = ahvif->vif->mbssid_tx_vif;
struct ath12k *ar = arvif->ar;
- struct ath12k_vif *tx_arvif;
+ struct ath12k_link_vif *tx_arvif;
+ struct ath12k_vif *tx_ahvif;
if (!tx_vif)
return 0;
- tx_arvif = ath12k_vif_to_arvif(tx_vif);
+ tx_ahvif = ath12k_vif_to_ahvif(tx_vif);
+ tx_arvif = &tx_ahvif->deflink;
- if (arvif->vif->bss_conf.nontransmitted) {
+ if (ahvif->vif->bss_conf.nontransmitted) {
if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
return -EINVAL;
@@ -6251,22 +6644,23 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_vif *arvif,
return -EINVAL;
}
- if (arvif->vif->bss_conf.ema_ap)
+ if (ahvif->vif->bss_conf.ema_ap)
*flags |= WMI_VDEV_MBSSID_FLAGS_EMA_MODE;
return 0;
}
-static int ath12k_mac_setup_vdev_create_arg(struct ath12k_vif *arvif,
+static int ath12k_mac_setup_vdev_create_arg(struct ath12k_link_vif *arvif,
struct ath12k_wmi_vdev_create_arg *arg)
{
struct ath12k *ar = arvif->ar;
struct ath12k_pdev *pdev = ar->pdev;
+ struct ath12k_vif *ahvif = arvif->ahvif;
int ret;
arg->if_id = arvif->vdev_id;
- arg->type = arvif->vdev_type;
- arg->subtype = arvif->vdev_subtype;
+ arg->type = ahvif->vdev_type;
+ arg->subtype = ahvif->vdev_subtype;
arg->pdev_id = pdev->pdev_id;
arg->mbssid_flags = WMI_VDEV_MBSSID_FLAGS_NON_MBSSID_AP;
@@ -6333,14 +6727,15 @@ ath12k_mac_prepare_he_mode(struct ath12k_pdev *pdev, u32 viftype)
}
static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
u32 param_id, param_value;
struct ath12k_base *ab = ar->ab;
+ struct ath12k_vif *ahvif = arvif->ahvif;
int ret;
param_id = WMI_VDEV_PARAM_SET_HEMU_MODE;
- param_value = ath12k_mac_prepare_he_mode(ar->pdev, arvif->vif->type);
+ param_value = ath12k_mac_prepare_he_mode(ar->pdev, ahvif->vif->type);
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
param_id, param_value);
if (ret) {
@@ -6363,9 +6758,10 @@ static int ath12k_set_he_mu_sounding_mode(struct ath12k *ar,
return ret;
}
-static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif)
+static void ath12k_mac_update_vif_offload(struct ath12k_link_vif *arvif)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
u32 param_id, param_value;
@@ -6378,14 +6774,14 @@ static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif)
IEEE80211_OFFLOAD_DECAP_ENABLED);
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
- arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
+ ahvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET;
else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
- arvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
+ ahvif->tx_encap_type = ATH12K_HW_TXRX_RAW;
else
- arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
+ ahvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI;
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
- param_id, arvif->tx_encap_type);
+ param_id, ahvif->tx_encap_type);
if (ret) {
ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n",
arvif->vdev_id, ret);
@@ -6412,57 +6808,86 @@ static void ath12k_mac_update_vif_offload(struct ath12k_vif *arvif)
static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ unsigned long links;
+ int link_id;
- ath12k_mac_update_vif_offload(arvif);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (vif->valid_links) {
+ links = vif->valid_links;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!(arvif && arvif->ar))
+ continue;
+
+ ath12k_mac_update_vif_offload(arvif);
+ }
+
+ return;
+ }
+
+ ath12k_mac_update_vif_offload(&ahvif->deflink);
}
-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
+int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
struct ath12k_hw *ah = ar->ah;
struct ath12k_base *ab = ar->ab;
struct ieee80211_hw *hw = ah->hw;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_create_arg vdev_arg = {0};
struct ath12k_wmi_peer_create_arg peer_param;
+ struct ieee80211_bss_conf *link_conf;
u32 param_id, param_value;
u16 nss;
int i;
int ret, vdev_id;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[arvif->link_id]);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in vdev create for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return -ENOLINK;
+ }
+
+ memcpy(arvif->bssid, link_conf->addr, ETH_ALEN);
arvif->ar = ar;
vdev_id = __ffs64(ab->free_vdev_map);
arvif->vdev_id = vdev_id;
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
switch (vif->type) {
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
- arvif->vdev_type = WMI_VDEV_TYPE_STA;
+ ahvif->vdev_type = WMI_VDEV_TYPE_STA;
if (vif->p2p)
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT;
break;
case NL80211_IFTYPE_MESH_POINT:
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
fallthrough;
case NL80211_IFTYPE_AP:
- arvif->vdev_type = WMI_VDEV_TYPE_AP;
+ ahvif->vdev_type = WMI_VDEV_TYPE_AP;
if (vif->p2p)
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO;
break;
case NL80211_IFTYPE_MONITOR:
- arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
+ ahvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
ar->monitor_vdev_id = vdev_id;
break;
case NL80211_IFTYPE_P2P_DEVICE:
- arvif->vdev_type = WMI_VDEV_TYPE_STA;
- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
+ ahvif->vdev_type = WMI_VDEV_TYPE_STA;
+ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
break;
default:
WARN_ON(1);
@@ -6470,7 +6895,7 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev create id %d type %d subtype %d map %llx\n",
- arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
+ arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype,
ab->free_vdev_map);
vif->cab_queue = arvif->vdev_id % (ATH12K_HW_MAX_QUEUES - 1);
@@ -6484,11 +6909,11 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
goto err;
}
- ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_arg);
+ ret = ath12k_wmi_vdev_create(ar, arvif->bssid, &vdev_arg);
if (ret) {
ath12k_warn(ab, "failed to create WMI vdev %d: %d\n",
arvif->vdev_id, ret);
- goto err;
+ return ret;
}
ar->num_created_vdevs++;
@@ -6513,10 +6938,10 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
goto err_vdev_del;
}
- switch (arvif->vdev_type) {
+ switch (ahvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
peer_param.vdev_id = arvif->vdev_id;
- peer_param.peer_addr = vif->addr;
+ peer_param.peer_addr = arvif->bssid;
peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
ret = ath12k_peer_create(ar, arvif, NULL, &peer_param);
if (ret) {
@@ -6589,29 +7014,28 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
}
ath12k_dp_vdev_tx_attach(ar, arvif);
-
if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled)
ath12k_mac_monitor_vdev_create(ar);
- arvif->ar = ar;
return ret;
err_peer_del:
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
reinit_completion(&ar->peer_delete_done);
- ret = ath12k_wmi_send_peer_delete_cmd(ar, vif->addr,
+ ret = ath12k_wmi_send_peer_delete_cmd(ar, arvif->bssid,
arvif->vdev_id);
if (ret) {
ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
- arvif->vdev_id, vif->addr);
+ arvif->vdev_id, arvif->bssid);
goto err;
}
ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,
- vif->addr);
+ arvif->bssid);
if (ret)
- goto err;
+ /* KVALO: why not goto err? */
+ return ret;
ar->num_peers--;
}
@@ -6633,21 +7057,56 @@ err:
return ret;
}
-static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif)
+static void ath12k_mac_vif_flush_key_cache(struct ath12k_link_vif *arvif)
+{
+ struct ath12k_key_conf *key_conf, *tmp;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ath12k_hw *ah = ahvif->ah;
+ struct ath12k_sta *ahsta;
+ struct ath12k_link_sta *arsta;
+ struct ath12k_vif_cache *cache = ahvif->cache[arvif->link_id];
+ int ret;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) {
+ arsta = NULL;
+ if (key_conf->sta) {
+ ahsta = ath12k_sta_to_ahsta(key_conf->sta);
+ arsta = wiphy_dereference(ah->hw->wiphy,
+ ahsta->link[arvif->link_id]);
+ if (!arsta)
+ goto free_cache;
+ }
+
+ ret = ath12k_mac_set_key(arvif->ar, key_conf->cmd,
+ arvif, arsta,
+ key_conf->key);
+ if (ret)
+ ath12k_warn(arvif->ar->ab, "unable to apply set key param to vdev %d ret %d\n",
+ arvif->vdev_id, ret);
+free_cache:
+ list_del(&key_conf->list);
+ kfree(key_conf);
+ }
+}
+
+static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_vif_cache *cache = arvif->cache;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ath12k_vif_cache *cache = ahvif->cache[arvif->link_id];
struct ath12k_base *ab = ar->ab;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!cache)
return;
if (cache->tx_conf.changed) {
- ret = ath12k_mac_conf_tx(arvif, 0, cache->tx_conf.ac,
+ ret = ath12k_mac_conf_tx(arvif, cache->tx_conf.ac,
&cache->tx_conf.tx_queue_params);
if (ret)
ath12k_warn(ab,
@@ -6660,26 +7119,25 @@ static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif
cache->bss_conf_changed);
}
- if (cache->key_conf.changed) {
- ret = ath12k_mac_set_key(ar, cache->key_conf.cmd, vif, NULL,
- cache->key_conf.key);
- if (ret)
- ath12k_warn(ab, "unable to apply set key param to vdev %d ret %d\n",
- arvif->vdev_id, ret);
- }
- ath12k_arvif_put_cache(arvif);
+ if (!list_empty(&cache->key_conf.list))
+ ath12k_mac_vif_flush_key_cache(arvif);
+
+ ath12k_ahvif_put_link_cache(ahvif, arvif->link_id);
}
static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
+ struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ath12k_hw *ah = hw->priv;
- struct ath12k *ar, *prev_ar;
+ struct ath12k *ar;
struct ath12k_base *ab;
+ u8 link_id = arvif->link_id;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (ah->num_radio == 1)
ar = ah->radio;
else if (ctx)
@@ -6708,27 +7166,20 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
if (WARN_ON(arvif->is_started))
return NULL;
- /* backup the previously used ar ptr since arvif->ar would
- * be set to NULL after vdev delete is done
- */
- prev_ar = arvif->ar;
- mutex_lock(&prev_ar->conf_mutex);
- ret = ath12k_mac_vdev_delete(prev_ar, vif);
-
- if (ret)
- ath12k_warn(prev_ar->ab, "unable to delete vdev %d\n",
- ret);
- mutex_unlock(&prev_ar->conf_mutex);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
}
}
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
if (arvif->is_created)
goto flush;
+ /* Assign arvif again here since previous radio switch block
+ * would've unassigned and cleared it.
+ */
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
if (vif->type == NL80211_IFTYPE_AP &&
ar->num_peers > (ar->max_num_peers - 1)) {
ath12k_warn(ab, "failed to create vdev due to insufficient peer entry resource in firmware\n");
@@ -6741,7 +7192,7 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
goto unlock;
}
- ret = ath12k_mac_vdev_create(ar, vif);
+ ret = ath12k_mac_vdev_create(ar, arvif);
if (ret) {
ath12k_warn(ab, "failed to create vdev %pM ret %d", vif->addr, ret);
goto unlock;
@@ -6752,21 +7203,27 @@ flush:
* add_interface(), Apply any parameters for the vdev which were received
* after add_interface, corresponding to this vif.
*/
- ath12k_mac_vif_cache_flush(ar, vif);
+ ath12k_mac_vif_cache_flush(ar, arvif);
unlock:
- mutex_unlock(&ar->conf_mutex);
return arvif->ar;
}
static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
int i;
- memset(arvif, 0, sizeof(*arvif));
+ lockdep_assert_wiphy(hw->wiphy);
- arvif->vif = vif;
+ memset(ahvif, 0, sizeof(*ahvif));
+
+ ahvif->ah = ah;
+ ahvif->vif = vif;
+ arvif = &ahvif->deflink;
+ arvif->ahvif = ahvif;
INIT_LIST_HEAD(&arvif->list);
INIT_DELAYED_WORK(&arvif->connection_loss_work,
@@ -6786,13 +7243,14 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE;
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
-
- /* For single radio wiphy(i.e ah->num_radio is 1), create the vdev
- * during add_interface itself, for multi radio wiphy, defer the vdev
- * creation until channel_assign to determine the radio on which the
- * vdev needs to be created
+ /* For non-ml vifs, vif->addr is the actual vdev address but for
+ * ML vif link(link BSSID) address is the vdev address and it can be a
+ * different one from vif->addr (i.e ML address).
+ * Defer vdev creation until assign_chanctx or hw_scan is initiated as driver
+ * will not know if this interface is an ML vif at this point.
*/
- ath12k_mac_assign_vif_to_vdev(hw, vif, NULL);
+ ath12k_mac_assign_vif_to_vdev(hw, arvif, NULL);
+
return 0;
}
@@ -6821,14 +7279,16 @@ static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif
}
}
-static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif)
+static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_base *ab = ar->ab;
unsigned long time_left;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
reinit_completion(&ar->vdev_delete_done);
ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
@@ -6849,7 +7309,7 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif)
ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
ar->num_created_vdevs--;
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ar->monitor_vdev_id = -1;
ar->monitor_vdev_created = false;
} else if (ar->monitor_vdev_created && !ar->monitor_started) {
@@ -6865,7 +7325,7 @@ err_vdev_del:
spin_unlock_bh(&ar->data_lock);
ath12k_peer_cleanup(ar, arvif->vdev_id);
- ath12k_arvif_put_cache(arvif);
+ ath12k_ahvif_put_link_cache(ahvif, arvif->link_id);
idr_for_each(&ar->txmgmt_idr,
ath12k_mac_vif_txmgmt_idr_remove, vif);
@@ -6886,39 +7346,24 @@ err_vdev_del:
static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_base *ab;
- struct ath12k *ar;
- int ret;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ u8 link_id;
- if (!arvif->is_created) {
+ lockdep_assert_wiphy(hw->wiphy);
+
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
/* if we cached some config but never received assign chanctx,
* free the allocated cache.
*/
- ath12k_arvif_put_cache(arvif);
- return;
- }
-
- ar = arvif->ar;
- ab = ar->ab;
-
- cancel_delayed_work_sync(&arvif->connection_loss_work);
-
- mutex_lock(&ar->conf_mutex);
-
- ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n",
- arvif->vdev_id);
+ ath12k_ahvif_put_link_cache(ahvif, link_id);
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!arvif || !arvif->is_created)
+ continue;
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
- ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr);
- if (ret)
- ath12k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n",
- arvif->vdev_id, ret);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
}
-
- ath12k_mac_vdev_delete(ar, vif);
-
- mutex_unlock(&ar->conf_mutex);
}
/* FIXME: Has to be verified. */
@@ -6937,7 +7382,7 @@ static void ath12k_mac_configure_filter(struct ath12k *ar,
bool reset_flag;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ar->filter_flags = total_flags;
@@ -6962,14 +7407,12 @@ static void ath12k_mac_op_configure_filter(struct ieee80211_hw *hw,
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
- ar = ath12k_ah_to_ar(ah, 0);
+ lockdep_assert_wiphy(hw->wiphy);
- mutex_lock(&ar->conf_mutex);
+ ar = ath12k_ah_to_ar(ah, 0);
*total_flags &= SUPPORTED_FILTERS;
ath12k_mac_configure_filter(ar, *total_flags);
-
- mutex_unlock(&ar->conf_mutex);
}
static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
@@ -6979,11 +7422,11 @@ static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *
struct ath12k *ar;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
for_each_ar(ah, ar, i) {
- mutex_lock(&ar->conf_mutex);
antennas_rx = max_t(u32, antennas_rx, ar->cfg_rx_chainmask);
antennas_tx = max_t(u32, antennas_tx, ar->cfg_tx_chainmask);
- mutex_unlock(&ar->conf_mutex);
}
*tx_ant = antennas_tx;
@@ -6999,10 +7442,10 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx
int ret = 0;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
for_each_ar(ah, ar, i) {
- mutex_lock(&ar->conf_mutex);
ret = __ath12k_set_antenna(ar, tx_ant, rx_ant);
- mutex_unlock(&ar->conf_mutex);
if (ret)
break;
}
@@ -7010,13 +7453,13 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx
return ret;
}
-static int ath12k_mac_ampdu_action(struct ath12k_vif *arvif,
+static int ath12k_mac_ampdu_action(struct ath12k_link_vif *arvif,
struct ieee80211_ampdu_params *params)
{
struct ath12k *ar = arvif->ar;
int ret = -EINVAL;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
switch (params->action) {
case IEEE80211_AMPDU_RX_START:
@@ -7046,19 +7489,20 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
int ret = -EINVAL;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_vif(hw, vif);
if (!ar)
return -EINVAL;
ar = ath12k_ah_to_ar(ah, 0);
+ arvif = &ahvif->deflink;
- mutex_lock(&ar->conf_mutex);
ret = ath12k_mac_ampdu_action(arvif, params);
- mutex_unlock(&ar->conf_mutex);
-
if (ret)
ath12k_warn(ar->ab, "pdev idx %d unable to perform ampdu action %d ret %d\n",
ar->pdev_idx, params->action, ret);
@@ -7072,6 +7516,8 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
struct ath12k *ar;
struct ath12k_base *ab;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, ctx);
if (!ar)
return -EINVAL;
@@ -7082,8 +7528,6 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
"mac chanctx add freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
- mutex_lock(&ar->conf_mutex);
-
spin_lock_bh(&ar->data_lock);
/* TODO: In case of multiple channel context, populate rx_channel from
* Rx PPDU desc information.
@@ -7091,8 +7535,6 @@ static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
ar->rx_channel = ctx->def.chan;
spin_unlock_bh(&ar->data_lock);
- mutex_unlock(&ar->conf_mutex);
-
return 0;
}
@@ -7102,6 +7544,8 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
struct ath12k *ar;
struct ath12k_base *ab;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, ctx);
if (!ar)
return;
@@ -7112,16 +7556,12 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
"mac chanctx remove freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
- mutex_lock(&ar->conf_mutex);
-
spin_lock_bh(&ar->data_lock);
/* TODO: In case of there is one more channel context left, populate
* rx_channel with the channel of that remaining channel context.
*/
ar->rx_channel = NULL;
spin_unlock_bh(&ar->data_lock);
-
- mutex_unlock(&ar->conf_mutex);
}
static enum wmi_phy_mode
@@ -7188,7 +7628,7 @@ ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
}
static int
-ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
+ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx,
bool restart)
{
@@ -7196,10 +7636,11 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
struct ath12k_base *ab = ar->ab;
struct wmi_vdev_start_req_arg arg = {};
const struct cfg80211_chan_def *chandef = &ctx->def;
- int he_support = arvif->vif->bss_conf.he_support;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ int he_support = ahvif->vif->bss_conf.he_support;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->vdev_setup_done);
@@ -7215,7 +7656,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode,
chandef->chan->band,
- arvif->vif->type);
+ ahvif->vif->type);
arg.min_power = 0;
arg.max_power = chandef->chan->max_power * 2;
arg.max_reg_power = chandef->chan->max_reg_power * 2;
@@ -7235,10 +7676,10 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
return ret;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
- arg.ssid = arvif->u.ap.ssid;
- arg.ssid_len = arvif->u.ap.ssid_len;
- arg.hidden_ssid = arvif->u.ap.hidden_ssid;
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ arg.ssid = ahvif->u.ap.ssid;
+ arg.ssid_len = ahvif->u.ap.ssid_len;
+ arg.hidden_ssid = ahvif->u.ap.hidden_ssid;
/* For now allow DFS for AP mode */
arg.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR);
@@ -7285,7 +7726,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
ar->num_started_vdevs++;
ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
- arvif->vif->addr, arvif->vdev_id);
+ ahvif->vif->addr, arvif->vdev_id);
/* Enable CAC Flag in the driver by checking the channel DFS cac time,
* i.e dfs_cac_ms value which will be valid only for radar channels
@@ -7294,7 +7735,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
* during CAC.
*/
/* TODO: Set the flag for other interface types as required */
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
+ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP &&
chandef->chan->dfs_cac_ms &&
chandef->chan->dfs_state == NL80211_DFS_USABLE) {
set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
@@ -7311,13 +7752,13 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
return 0;
}
-static int ath12k_mac_vdev_start(struct ath12k_vif *arvif,
+static int ath12k_mac_vdev_start(struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
return ath12k_mac_vdev_start_restart(arvif, ctx, false);
}
-static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif,
+static int ath12k_mac_vdev_restart(struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
return ath12k_mac_vdev_start_restart(arvif, ctx, true);
@@ -7335,8 +7776,13 @@ static void
ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_mac_change_chanctx_arg *arg = data;
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
+
+ arvif = &ahvif->deflink;
if (arvif->ar != arg->ar)
return;
@@ -7351,9 +7797,14 @@ static void
ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_mac_change_chanctx_arg *arg = data;
struct ieee80211_chanctx_conf *ctx;
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
+
+ arvif = &ahvif->deflink;
if (arvif->ar != arg->ar)
return;
@@ -7397,13 +7848,13 @@ static u32 ath12k_mac_nlwidth_to_wmiwidth(enum nl80211_chan_width width)
}
static int ath12k_mac_update_peer_puncturing_width(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct cfg80211_chan_def def)
{
u32 param_id, param_value;
int ret;
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
return 0;
param_id = WMI_PEER_CHWIDTH_PUNCTURE_20MHZ_BITMAP;
@@ -7429,17 +7880,19 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
{
struct ath12k_wmi_vdev_up_params params = {};
struct ath12k_base *ab = ar->ab;
+ struct ath12k_link_vif *arvif;
struct ieee80211_vif *vif;
- struct ath12k_vif *arvif;
+ struct ath12k_vif *ahvif;
int ret;
int i;
bool monitor_vif = false;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
for (i = 0; i < n_vifs; i++) {
vif = vifs[i].vif;
- arvif = ath12k_vif_to_arvif(vif);
+ ahvif = ath12k_vif_to_ahvif(vif);
+ arvif = &ahvif->deflink;
if (vif->type == NL80211_IFTYPE_MONITOR)
monitor_vif = true;
@@ -7489,10 +7942,14 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
memset(&params, 0, sizeof(params));
params.vdev_id = arvif->vdev_id;
- params.aid = arvif->aid;
+ params.aid = ahvif->aid;
params.bssid = arvif->bssid;
if (vif->mbssid_tx_vif) {
- params.tx_bssid = ath12k_vif_to_arvif(vif->mbssid_tx_vif)->bssid;
+ struct ath12k_vif *ahvif =
+ ath12k_vif_to_ahvif(vif->mbssid_tx_vif);
+ struct ath12k_link_vif *arvif = &ahvif->deflink;
+
+ params.tx_bssid = arvif->bssid;
params.nontx_profile_idx = vif->bss_conf.bssid_index;
params.nontx_profile_cnt = 1 << vif->bss_conf.bssid_indicator;
}
@@ -7528,7 +7985,7 @@ ath12k_mac_update_active_vif_chan(struct ath12k *ar,
struct ath12k_mac_change_chanctx_arg arg = { .ctx = ctx, .ar = ar };
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ieee80211_iterate_active_interfaces_atomic(hw,
IEEE80211_IFACE_ITER_NORMAL,
@@ -7558,14 +8015,14 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
struct ath12k *ar;
struct ath12k_base *ab;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, ctx);
if (!ar)
return;
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac chanctx change freq %u width %d ptr %p changed %x\n",
ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
@@ -7574,7 +8031,7 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
* switch_vif_chanctx().
*/
if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
- goto unlock;
+ return;
if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH ||
changed & IEEE80211_CHANCTX_CHANGE_RADAR ||
@@ -7582,16 +8039,14 @@ static void ath12k_mac_op_change_chanctx(struct ieee80211_hw *hw,
ath12k_mac_update_active_vif_chan(ar, ctx);
/* TODO: Recalc radar detection */
-
-unlock:
- mutex_unlock(&ar->conf_mutex);
}
static int ath12k_start_vdev_delay(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
struct ath12k_base *ab = ar->ab;
- struct ieee80211_vif *vif = arvif->vif;
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
int ret;
if (WARN_ON(arvif->is_started))
@@ -7605,7 +8060,7 @@ static int ath12k_start_vdev_delay(struct ath12k *ar,
return ret;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath12k_monitor_vdev_up(ar, arvif->vdev_id);
if (ret) {
ath12k_warn(ab, "failed put monitor up: %d\n", ret);
@@ -7625,24 +8080,37 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx)
{
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_base *ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ u8 link_id = link_conf->link_id;
+ struct ath12k_link_vif *arvif;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
/* For multi radio wiphy, the vdev was not created during add_interface
* create now since we have a channel ctx now to assign to a specific ar/fw
*/
- ar = ath12k_mac_assign_vif_to_vdev(hw, vif, ctx);
- if (!ar) {
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+ if (!arvif) {
WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ if (!arvif->is_started) {
+ ar = ath12k_mac_assign_vif_to_vdev(hw, arvif, ctx);
+ if (!ar)
+ return -EINVAL;
+ } else {
+ ath12k_warn(arvif->ar->ab, "failed to assign chanctx for vif %pM link id %u link vif is already started",
+ vif->addr, link_id);
return -EINVAL;
}
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac chanctx assign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
@@ -7651,8 +8119,8 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
/* for some targets bss peer must be created before vdev_start */
if (ab->hw_params->vdev_start_delay &&
- arvif->vdev_type != WMI_VDEV_TYPE_AP &&
- arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
+ ahvif->vdev_type != WMI_VDEV_TYPE_AP &&
+ ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
!ath12k_peer_exist_by_vdev_id(ab, arvif->vdev_id)) {
memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
ret = 0;
@@ -7664,10 +8132,11 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath12k_mac_monitor_start(ar);
if (ret)
goto out;
+
arvif->is_started = true;
goto out;
}
@@ -7680,7 +8149,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out;
}
- if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
ath12k_mac_monitor_start(ar);
arvif->is_started = true;
@@ -7688,8 +8157,6 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
/* TODO: Setup ps and cts/rts protection */
out:
- mutex_unlock(&ar->conf_mutex);
-
return ret;
}
@@ -7701,9 +8168,15 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
{
struct ath12k *ar;
struct ath12k_base *ab;
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
+ u8 link_id = link_conf->link_id;
int ret;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+
/* The vif is expected to be attached to an ar's VDEV.
* We leave the vif/vdev in this function as is
* and not delete the vdev symmetric to assign_vif_chanctx()
@@ -7711,32 +8184,28 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
* remove_interface() or when there is a change in channel
* that moves the vif to a new ar
*/
- if (!arvif->is_created)
+ if (!arvif || !arvif->is_created)
return;
ar = arvif->ar;
ab = ar->ab;
- mutex_lock(&ar->conf_mutex);
-
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac chanctx unassign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
WARN_ON(!arvif->is_started);
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath12k_mac_monitor_stop(ar);
- if (ret) {
- mutex_unlock(&ar->conf_mutex);
+ if (ret)
return;
- }
arvif->is_started = false;
}
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA &&
- arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_STA &&
+ ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
ath12k_bss_disassoc(ar, arvif);
ret = ath12k_mac_vdev_stop(arvif);
if (ret)
@@ -7745,11 +8214,12 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
}
arvif->is_started = false;
- if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
ath12k_mac_monitor_stop(ar);
- mutex_unlock(&ar->conf_mutex);
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
}
static int
@@ -7760,35 +8230,32 @@ ath12k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
{
struct ath12k *ar;
+ lockdep_assert_wiphy(hw->wiphy);
+
ar = ath12k_get_ar_by_ctx(hw, vifs->old_ctx);
if (!ar)
return -EINVAL;
- mutex_lock(&ar->conf_mutex);
-
/* Switching channels across radio is not allowed */
- if (ar != ath12k_get_ar_by_ctx(hw, vifs->new_ctx)) {
- mutex_unlock(&ar->conf_mutex);
+ if (ar != ath12k_get_ar_by_ctx(hw, vifs->new_ctx))
return -EINVAL;
- }
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"mac chanctx switch n_vifs %d mode %d\n",
n_vifs, mode);
ath12k_mac_update_vif_chan(ar, vifs, n_vifs);
- mutex_unlock(&ar->conf_mutex);
-
return 0;
}
static int
ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret = 0;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
list_for_each_entry(arvif, &ar->arvifs, list) {
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "setting mac vdev %d param %d value %d\n",
param, arvif->vdev_id, value);
@@ -7801,7 +8268,7 @@ ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value)
break;
}
}
- mutex_unlock(&ar->conf_mutex);
+
return ret;
}
@@ -7814,6 +8281,8 @@ static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
struct ath12k *ar;
int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD, ret = 0, i;
+ lockdep_assert_wiphy(hw->wiphy);
+
/* Currently we set the rts threshold value to all the vifs across
* all radios of the single wiphy.
* TODO Once support for vif specific RTS threshold in mac80211 is
@@ -7843,6 +8312,9 @@ static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
* supported. This effectively prevents mac80211 from doing frame
* fragmentation in software.
*/
+
+ lockdep_assert_wiphy(hw->wiphy);
+
return -EOPNOTSUPP;
}
@@ -7887,6 +8359,8 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
struct ath12k *ar;
int i;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (drop)
return;
@@ -8020,14 +8494,14 @@ ath12k_mac_get_single_legacy_rate(struct ath12k *ar,
return 0;
}
-static int ath12k_mac_set_fixed_rate_params(struct ath12k_vif *arvif,
+static int ath12k_mac_set_fixed_rate_params(struct ath12k_link_vif *arvif,
u32 rate, u8 nss, u8 sgi, u8 ldpc)
{
struct ath12k *ar = arvif->ar;
u32 vdev_param;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02x nss %u sgi %u\n",
arvif->vdev_id, rate, nss, sgi);
@@ -8099,8 +8573,9 @@ ath12k_mac_vht_mcs_range_present(struct ath12k *ar,
static void ath12k_mac_set_bitrate_mask_iter(void *data,
struct ieee80211_sta *sta)
{
- struct ath12k_vif *arvif = data;
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_link_vif *arvif = data;
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
struct ath12k *ar = arvif->ar;
if (arsta->arvif != arvif)
@@ -8110,14 +8585,15 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data,
arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
spin_unlock_bh(&ar->data_lock);
- ieee80211_queue_work(ath12k_ar_to_hw(ar), &arsta->update_wk);
+ wiphy_work_queue(ath12k_ar_to_hw(ar)->wiphy, &arsta->update_wk);
}
static void ath12k_mac_disable_peer_fixed_rate(void *data,
struct ieee80211_sta *sta)
{
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
- struct ath12k_vif *arvif = data;
+ struct ath12k_link_vif *arvif = data;
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta = &ahsta->deflink;
struct ath12k *ar = arvif->ar;
int ret;
@@ -8139,9 +8615,10 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_link_vif *arvif;
struct cfg80211_chan_def def;
- struct ath12k *ar = arvif->ar;
+ struct ath12k *ar;
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
@@ -8153,8 +8630,15 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
int ret;
int num_rates;
- if (ath12k_mac_vif_chan(vif, &def))
- return -EPERM;
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+
+ ar = arvif->ar;
+ if (ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) {
+ ret = -EPERM;
+ goto out;
+ }
band = def.chan->band;
ht_mcs_mask = mask->control[band].ht_mcs;
@@ -8183,9 +8667,9 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
goto out;
}
- ieee80211_iterate_stations_atomic(hw,
- ath12k_mac_disable_peer_fixed_rate,
- arvif);
+ ieee80211_iterate_stations_mtx(hw,
+ ath12k_mac_disable_peer_fixed_rate,
+ arvif);
} else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
&single_nss)) {
rate = WMI_FIXED_RATE_NONE;
@@ -8226,34 +8710,25 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
*/
ath12k_warn(ar->ab,
"Setting more than one MCS Value in bitrate mask not supported\n");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
- ieee80211_iterate_stations_atomic(hw,
- ath12k_mac_disable_peer_fixed_rate,
- arvif);
-
- mutex_lock(&ar->conf_mutex);
+ ieee80211_iterate_stations_mtx(hw,
+ ath12k_mac_disable_peer_fixed_rate,
+ arvif);
arvif->bitrate_mask = *mask;
- ieee80211_iterate_stations_atomic(hw,
- ath12k_mac_set_bitrate_mask_iter,
- arvif);
-
- mutex_unlock(&ar->conf_mutex);
+ ieee80211_iterate_stations_mtx(hw,
+ ath12k_mac_set_bitrate_mask_iter,
+ arvif);
}
- mutex_lock(&ar->conf_mutex);
-
ret = ath12k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc);
if (ret) {
ath12k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n",
arvif->vdev_id, ret);
}
- mutex_unlock(&ar->conf_mutex);
-
out:
return ret;
}
@@ -8265,9 +8740,12 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar;
struct ath12k_base *ab;
- struct ath12k_vif *arvif;
+ struct ath12k_vif *ahvif;
+ struct ath12k_link_vif *arvif;
int recovery_count, i;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
return;
@@ -8280,8 +8758,6 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
ieee80211_wake_queues(hw);
for_each_ar(ah, ar, i) {
- mutex_lock(&ar->conf_mutex);
-
ab = ar->ab;
ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
@@ -8306,11 +8782,12 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
}
list_for_each_entry(arvif, &ar->arvifs, list) {
+ ahvif = arvif->ahvif;
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"reconfig cipher %d up %d vdev type %d\n",
- arvif->key_cipher,
+ ahvif->key_cipher,
arvif->is_up,
- arvif->vdev_type);
+ ahvif->vdev_type);
/* After trigger disconnect, then upper layer will
* trigger connect again, then the PN number of
@@ -8318,16 +8795,14 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
* side, hence PN number mismatch will not happen.
*/
if (arvif->is_up &&
- arvif->vdev_type == WMI_VDEV_TYPE_STA &&
- arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
- ieee80211_hw_restart_disconnect(arvif->vif);
+ ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
+ ieee80211_hw_restart_disconnect(ahvif->vif);
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"restart disconnect\n");
}
}
-
- mutex_unlock(&ar->conf_mutex);
}
}
@@ -8338,7 +8813,7 @@ ath12k_mac_update_bss_chan_survey(struct ath12k *ar,
int ret;
enum wmi_bss_chan_info_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) ||
ar->rx_channel != channel)
@@ -8370,6 +8845,8 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
struct ieee80211_supported_band *sband;
struct survey_info *ar_survey;
+ lockdep_assert_wiphy(hw->wiphy);
+
if (idx >= ATH12K_NUM_CHANS)
return -ENOENT;
@@ -8403,8 +8880,6 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
ar_survey = &ar->survey[idx];
- mutex_lock(&ar->conf_mutex);
-
ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
spin_lock_bh(&ar->data_lock);
@@ -8416,7 +8891,6 @@ static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
if (ar->rx_channel == survey->channel)
survey->filled |= SURVEY_INFO_IN_USE;
- mutex_unlock(&ar->conf_mutex);
return 0;
}
@@ -8425,7 +8899,12 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
- struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_link_sta *arsta;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arsta = &ahsta->deflink;
sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
@@ -8462,7 +8941,7 @@ static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
ar = ath12k_ah_to_ar(ah, 0);
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
spin_lock_bh(&ar->data_lock);
ar->scan.roc_notify = false;
@@ -8470,8 +8949,6 @@ static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
ath12k_scan_abort(ar);
- mutex_unlock(&ar->conf_mutex);
-
cancel_delayed_work_sync(&ar->scan.timeout);
return 0;
@@ -8483,24 +8960,31 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
int duration,
enum ieee80211_roc_type type)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_wmi_scan_req_arg arg;
- struct ath12k *ar, *prev_ar;
+ struct ath12k_link_vif *arvif;
+ struct ath12k *ar;
u32 scan_time_msec;
bool create = true;
+ u8 link_id;
int ret;
- if (ah->num_radio == 1) {
- WARN_ON(!arvif->is_created);
- ar = ath12k_ah_to_ar(ah, 0);
- goto scan;
- }
+ lockdep_assert_wiphy(hw->wiphy);
ar = ath12k_mac_select_scan_device(hw, vif, chan->center_freq);
- if (!ar)
- return -EINVAL;
+ if (!ar) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ /* check if any of the links of ML VIF is already started on
+ * radio(ar) correpsondig to given scan frequency and use it,
+ * if not use deflink(link 0) for scan purpose.
+ */
+
+ link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar);
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
/* If the vif is already assigned to a specific vdev of an ar,
* check whether its already started, vdev which is started
* are not allowed to switch to a new radio.
@@ -8511,44 +8995,35 @@ static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
* always on the same band for the vif
*/
if (arvif->is_created) {
- if (WARN_ON(!arvif->ar))
- return -EINVAL;
+ if (WARN_ON(!arvif->ar)) {
+ ret = -EINVAL;
+ goto exit;
+ }
- if (ar != arvif->ar && arvif->is_started)
- return -EBUSY;
+ if (ar != arvif->ar && arvif->is_started) {
+ ret = -EBUSY;
+ goto exit;
+ }
if (ar != arvif->ar) {
- /* backup the previously used ar ptr, since the vdev delete
- * would assign the arvif->ar to NULL after the call
- */
- prev_ar = arvif->ar;
- mutex_lock(&prev_ar->conf_mutex);
- ret = ath12k_mac_vdev_delete(prev_ar, vif);
- mutex_unlock(&prev_ar->conf_mutex);
- if (ret) {
- ath12k_warn(prev_ar->ab,
- "unable to delete scan vdev for roc: %d\n",
- ret);
- return ret;
- }
+ ath12k_mac_remove_link_interface(hw, arvif);
+ ath12k_mac_unassign_link_vif(arvif);
} else {
create = false;
}
}
if (create) {
- mutex_lock(&ar->conf_mutex);
- ret = ath12k_mac_vdev_create(ar, vif);
- mutex_unlock(&ar->conf_mutex);
+ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
+
+ ret = ath12k_mac_vdev_create(ar, arvif);
if (ret) {
ath12k_warn(ar->ab, "unable to create scan vdev for roc: %d\n",
ret);
- return -EINVAL;
+ goto exit;
}
}
-scan:
- mutex_lock(&ar->conf_mutex);
spin_lock_bh(&ar->data_lock);
switch (ar->scan.state) {
@@ -8623,9 +9098,8 @@ scan:
free_chan_list:
kfree(arg.chan_list);
-exit:
- mutex_unlock(&ar->conf_mutex);
+exit:
return ret;
}
@@ -8633,16 +9107,20 @@ static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *data)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
- struct ath12k_rekey_data *rekey_data = &arvif->rekey_data;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_rekey_data *rekey_data;
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ arvif = &ahvif->deflink;
+ rekey_data = &arvif->rekey_data;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac set rekey data vdev %d\n",
arvif->vdev_id);
- mutex_lock(&ar->conf_mutex);
-
memcpy(rekey_data->kck, data->kck, NL80211_KCK_LEN);
memcpy(rekey_data->kek, data->kek, NL80211_KEK_LEN);
@@ -8659,8 +9137,6 @@ static void ath12k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
rekey_data->kck, NL80211_KEK_LEN);
ath12k_dbg_dump(ar->ab, ATH12K_DBG_MAC, "replay ctr", NULL,
&rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr));
-
- mutex_unlock(&ar->conf_mutex);
}
static const struct ieee80211_ops ath12k_ops = {
@@ -8673,7 +9149,9 @@ static const struct ieee80211_ops ath12k_ops = {
.remove_interface = ath12k_mac_op_remove_interface,
.update_vif_offload = ath12k_mac_op_update_vif_offload,
.config = ath12k_mac_op_config,
- .bss_info_changed = ath12k_mac_op_bss_info_changed,
+ .link_info_changed = ath12k_mac_op_link_info_changed,
+ .vif_cfg_changed = ath12k_mac_op_vif_cfg_changed,
+ .change_vif_links = ath12k_mac_op_change_vif_links,
.configure_filter = ath12k_mac_op_configure_filter,
.hw_scan = ath12k_mac_op_hw_scan,
.cancel_hw_scan = ath12k_mac_op_cancel_hw_scan,
@@ -8681,7 +9159,7 @@ static const struct ieee80211_ops ath12k_ops = {
.set_rekey_data = ath12k_mac_op_set_rekey_data,
.sta_state = ath12k_mac_op_sta_state,
.sta_set_txpwr = ath12k_mac_op_sta_set_txpwr,
- .sta_rc_update = ath12k_mac_op_sta_rc_update,
+ .link_sta_rc_update = ath12k_mac_op_sta_rc_update,
.conf_tx = ath12k_mac_op_conf_tx,
.set_antenna = ath12k_mac_op_set_antenna,
.get_antenna = ath12k_mac_op_get_antenna,
@@ -9320,7 +9798,7 @@ static void ath12k_mac_setup(struct ath12k *ar)
spin_lock_init(&ar->data_lock);
INIT_LIST_HEAD(&ar->arvifs);
INIT_LIST_HEAD(&ar->ppdu_stats_info);
- mutex_init(&ar->conf_mutex);
+
init_completion(&ar->vdev_setup_done);
init_completion(&ar->vdev_delete_done);
init_completion(&ar->peer_assoc_done);
@@ -9501,7 +9979,7 @@ err:
return ret;
}
-int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
+int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval)
{
@@ -9509,9 +9987,9 @@ int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
struct ath12k *ar = arvif->ar;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
return 0;
if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map))
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index 5efbb6822628..d382337ba649 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -41,6 +41,9 @@ struct ath12k_generic_iter {
#define ATH12K_TX_POWER_MAX_VAL 70
#define ATH12K_TX_POWER_MIN_VAL 0
+#define ATH12K_DEFAULT_LINK_ID 0
+#define ATH12K_INVALID_LINK_ID 255
+
enum ath12k_supported_bw {
ATH12K_BW_20 = 0,
ATH12K_BW_40 = 1,
@@ -65,9 +68,9 @@ u8 ath12k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
void __ath12k_mac_scan_finish(struct ath12k *ar);
void ath12k_mac_scan_finish(struct ath12k *ar);
-struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id);
-struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
- u32 vdev_id);
+struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id);
+struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
+ u32 vdev_id);
struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id);
struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id);
@@ -82,7 +85,7 @@ int ath12k_mac_rfkill_config(struct ath12k *ar);
int ath12k_mac_wait_tx_complete(struct ath12k *ar);
void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb);
void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id);
-int ath12k_mac_vif_set_keepalive(struct ath12k_vif *arvif,
+int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval);
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar);
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index df96b0f91f54..2f6d14382ed7 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -649,3 +649,8 @@ void ath12k_mhi_resume(struct ath12k_pci *ab_pci)
{
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_RESUME);
}
+
+void ath12k_mhi_coredump(struct mhi_controller *mhi_ctrl, bool in_panic)
+{
+ mhi_download_rddm_image(mhi_ctrl, in_panic);
+}
diff --git a/drivers/net/wireless/ath/ath12k/mhi.h b/drivers/net/wireless/ath/ath12k/mhi.h
index 9362ad1958c3..7358b8477536 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.h
+++ b/drivers/net/wireless/ath/ath12k/mhi.h
@@ -43,5 +43,5 @@ void ath12k_mhi_clear_vector(struct ath12k_base *ab);
void ath12k_mhi_suspend(struct ath12k_pci *ar_pci);
void ath12k_mhi_resume(struct ath12k_pci *ar_pci);
-
+void ath12k_mhi_coredump(struct mhi_controller *mhi_ctrl, bool in_panic);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/p2p.c b/drivers/net/wireless/ath/ath12k/p2p.c
index 3a851ee15b2f..84cccf7d91e7 100644
--- a/drivers/net/wireless/ath/ath12k/p2p.c
+++ b/drivers/net/wireless/ath/ath12k/p2p.c
@@ -69,20 +69,20 @@ static size_t ath12k_p2p_noa_ie_len_compute(const struct ath12k_wmi_p2p_noa_info
return len;
}
-static void ath12k_p2p_noa_ie_assign(struct ath12k_vif *arvif, void *ie,
+static void ath12k_p2p_noa_ie_assign(struct ath12k_link_vif *arvif, void *ie,
size_t len)
{
struct ath12k *ar = arvif->ar;
lockdep_assert_held(&ar->data_lock);
- kfree(arvif->u.ap.noa_data);
+ kfree(arvif->ahvif->u.ap.noa_data);
- arvif->u.ap.noa_data = ie;
- arvif->u.ap.noa_len = len;
+ arvif->ahvif->u.ap.noa_data = ie;
+ arvif->ahvif->u.ap.noa_len = len;
}
-static void __ath12k_p2p_noa_update(struct ath12k_vif *arvif,
+static void __ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
const struct ath12k_wmi_p2p_noa_info *noa)
{
struct ath12k *ar = arvif->ar;
@@ -105,7 +105,7 @@ static void __ath12k_p2p_noa_update(struct ath12k_vif *arvif,
ath12k_p2p_noa_ie_assign(arvif, ie, len);
}
-void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
+void ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
const struct ath12k_wmi_p2p_noa_info *noa)
{
struct ath12k *ar = arvif->ar;
@@ -118,9 +118,12 @@ void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_p2p_noa_arg *arg = data;
+ struct ath12k_link_vif *arvif;
+ WARN_ON(!rcu_read_lock_any_held());
+ arvif = &ahvif->deflink;
if (arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
return;
diff --git a/drivers/net/wireless/ath/ath12k/p2p.h b/drivers/net/wireless/ath/ath12k/p2p.h
index b2eec51a9900..03ee877e6d6b 100644
--- a/drivers/net/wireless/ath/ath12k/p2p.h
+++ b/drivers/net/wireless/ath/ath12k/p2p.h
@@ -16,7 +16,7 @@ struct ath12k_p2p_noa_arg {
const struct ath12k_wmi_p2p_noa_info *noa;
};
-void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
+void ath12k_p2p_noa_update(struct ath12k_link_vif *arvif,
const struct ath12k_wmi_p2p_noa_info *noa);
void ath12k_p2p_noa_update_by_vdev_id(struct ath12k *ar, u32 vdev_id,
const struct ath12k_wmi_p2p_noa_info *noa);
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index bd269aa1740b..cf907550e6a4 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -7,6 +7,8 @@
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/vmalloc.h>
#include "pci.h"
#include "core.h"
@@ -425,9 +427,9 @@ static void ath12k_pci_sync_ce_irqs(struct ath12k_base *ab)
}
}
-static void ath12k_pci_ce_tasklet(struct tasklet_struct *t)
+static void ath12k_pci_ce_workqueue(struct work_struct *work)
{
- struct ath12k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
+ struct ath12k_ce_pipe *ce_pipe = from_work(ce_pipe, work, intr_wq);
int irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
ath12k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
@@ -449,7 +451,7 @@ static irqreturn_t ath12k_pci_ce_interrupt_handler(int irq, void *arg)
disable_irq_nosync(ab->irq_num[irq_idx]);
- tasklet_schedule(&ce_pipe->intr_tq);
+ queue_work(system_bh_wq, &ce_pipe->intr_wq);
return IRQ_HANDLED;
}
@@ -675,7 +677,7 @@ static int ath12k_pci_config_irq(struct ath12k_base *ab)
irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + i;
- tasklet_setup(&ce_pipe->intr_tq, ath12k_pci_ce_tasklet);
+ INIT_WORK(&ce_pipe->intr_wq, ath12k_pci_ce_workqueue);
ret = request_irq(irq, ath12k_pci_ce_interrupt_handler,
ab_pci->irq_flags, irq_name[irq_idx],
@@ -962,7 +964,7 @@ static void ath12k_pci_aspm_restore(struct ath12k_pci *ab_pci)
PCI_EXP_LNKCTL_ASPMC);
}
-static void ath12k_pci_kill_tasklets(struct ath12k_base *ab)
+static void ath12k_pci_cancel_workqueue(struct ath12k_base *ab)
{
int i;
@@ -972,7 +974,7 @@ static void ath12k_pci_kill_tasklets(struct ath12k_base *ab)
if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue;
- tasklet_kill(&ce_pipe->intr_tq);
+ cancel_work_sync(&ce_pipe->intr_wq);
}
}
@@ -980,7 +982,7 @@ static void ath12k_pci_ce_irq_disable_sync(struct ath12k_base *ab)
{
ath12k_pci_ce_irqs_disable(ab);
ath12k_pci_sync_ce_irqs(ab);
- ath12k_pci_kill_tasklets(ab);
+ ath12k_pci_cancel_workqueue(ab);
}
int ath12k_pci_map_service_to_pipe(struct ath12k_base *ab, u16 service_id,
@@ -1259,6 +1261,186 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
ab_pci->pci_ops->release(ab);
}
+#ifdef CONFIG_ATH12K_COREDUMP
+static int ath12k_pci_coredump_calculate_size(struct ath12k_base *ab, u32 *dump_seg_sz)
+{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
+ struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
+ struct image_info *rddm_img, *fw_img;
+ struct ath12k_tlv_dump_data *dump_tlv;
+ enum ath12k_fw_crash_dump_type mem_type;
+ u32 len = 0, rddm_tlv_sz = 0, paging_tlv_sz = 0;
+ struct ath12k_dump_file_data *file_data;
+ int i;
+
+ rddm_img = mhi_ctrl->rddm_image;
+ if (!rddm_img) {
+ ath12k_err(ab, "No RDDM dump found\n");
+ return 0;
+ }
+
+ fw_img = mhi_ctrl->fbc_image;
+
+ for (i = 0; i < fw_img->entries ; i++) {
+ if (!fw_img->mhi_buf[i].buf)
+ continue;
+
+ paging_tlv_sz += fw_img->mhi_buf[i].len;
+ }
+ dump_seg_sz[FW_CRASH_DUMP_PAGING_DATA] = paging_tlv_sz;
+
+ for (i = 0; i < rddm_img->entries; i++) {
+ if (!rddm_img->mhi_buf[i].buf)
+ continue;
+
+ rddm_tlv_sz += rddm_img->mhi_buf[i].len;
+ }
+ dump_seg_sz[FW_CRASH_DUMP_RDDM_DATA] = rddm_tlv_sz;
+
+ for (i = 0; i < ab->qmi.mem_seg_count; i++) {
+ mem_type = ath12k_coredump_get_dump_type(ab->qmi.target_mem[i].type);
+
+ if (mem_type == FW_CRASH_DUMP_NONE)
+ continue;
+
+ if (mem_type == FW_CRASH_DUMP_TYPE_MAX) {
+ ath12k_dbg(ab, ATH12K_DBG_PCI,
+ "target mem region type %d not supported",
+ ab->qmi.target_mem[i].type);
+ continue;
+ }
+
+ if (!ab->qmi.target_mem[i].paddr)
+ continue;
+
+ dump_seg_sz[mem_type] += ab->qmi.target_mem[i].size;
+ }
+
+ for (i = 0; i < FW_CRASH_DUMP_TYPE_MAX; i++) {
+ if (!dump_seg_sz[i])
+ continue;
+
+ len += sizeof(*dump_tlv) + dump_seg_sz[i];
+ }
+
+ if (len)
+ len += sizeof(*file_data);
+
+ return len;
+}
+
+static void ath12k_pci_coredump_download(struct ath12k_base *ab)
+{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
+ struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
+ struct image_info *rddm_img, *fw_img;
+ struct timespec64 timestamp;
+ int i, len, mem_idx;
+ enum ath12k_fw_crash_dump_type mem_type;
+ struct ath12k_dump_file_data *file_data;
+ struct ath12k_tlv_dump_data *dump_tlv;
+ size_t hdr_len = sizeof(*file_data);
+ void *buf;
+ u32 dump_seg_sz[FW_CRASH_DUMP_TYPE_MAX] = { 0 };
+
+ ath12k_mhi_coredump(mhi_ctrl, false);
+
+ len = ath12k_pci_coredump_calculate_size(ab, dump_seg_sz);
+ if (!len) {
+ ath12k_warn(ab, "No crash dump data found for devcoredump");
+ return;
+ }
+
+ rddm_img = mhi_ctrl->rddm_image;
+ fw_img = mhi_ctrl->fbc_image;
+
+ /* dev_coredumpv() requires vmalloc data */
+ buf = vzalloc(len);
+ if (!buf)
+ return;
+
+ ab->dump_data = buf;
+ ab->ath12k_coredump_len = len;
+ file_data = ab->dump_data;
+ strscpy(file_data->df_magic, "ATH12K-FW-DUMP", sizeof(file_data->df_magic));
+ file_data->len = cpu_to_le32(len);
+ file_data->version = cpu_to_le32(ATH12K_FW_CRASH_DUMP_V2);
+ file_data->chip_id = cpu_to_le32(ab_pci->dev_id);
+ file_data->qrtr_id = cpu_to_le32(ab_pci->ab->qmi.service_ins_id);
+ file_data->bus_id = cpu_to_le32(pci_domain_nr(ab_pci->pdev->bus));
+ guid_gen(&file_data->guid);
+ ktime_get_real_ts64(&timestamp);
+ file_data->tv_sec = cpu_to_le64(timestamp.tv_sec);
+ file_data->tv_nsec = cpu_to_le64(timestamp.tv_nsec);
+ buf += hdr_len;
+ dump_tlv = buf;
+ dump_tlv->type = cpu_to_le32(FW_CRASH_DUMP_PAGING_DATA);
+ dump_tlv->tlv_len = cpu_to_le32(dump_seg_sz[FW_CRASH_DUMP_PAGING_DATA]);
+ buf += COREDUMP_TLV_HDR_SIZE;
+
+ /* append all segments together as they are all part of a single contiguous
+ * block of memory
+ */
+ for (i = 0; i < fw_img->entries ; i++) {
+ if (!fw_img->mhi_buf[i].buf)
+ continue;
+
+ memcpy_fromio(buf, (void const __iomem *)fw_img->mhi_buf[i].buf,
+ fw_img->mhi_buf[i].len);
+ buf += fw_img->mhi_buf[i].len;
+ }
+
+ dump_tlv = buf;
+ dump_tlv->type = cpu_to_le32(FW_CRASH_DUMP_RDDM_DATA);
+ dump_tlv->tlv_len = cpu_to_le32(dump_seg_sz[FW_CRASH_DUMP_RDDM_DATA]);
+ buf += COREDUMP_TLV_HDR_SIZE;
+
+ /* append all segments together as they are all part of a single contiguous
+ * block of memory
+ */
+ for (i = 0; i < rddm_img->entries; i++) {
+ if (!rddm_img->mhi_buf[i].buf)
+ continue;
+
+ memcpy_fromio(buf, (void const __iomem *)rddm_img->mhi_buf[i].buf,
+ rddm_img->mhi_buf[i].len);
+ buf += rddm_img->mhi_buf[i].len;
+ }
+
+ mem_idx = FW_CRASH_DUMP_REMOTE_MEM_DATA;
+ for (; mem_idx < FW_CRASH_DUMP_TYPE_MAX; mem_idx++) {
+ if (!dump_seg_sz[mem_idx] || mem_idx == FW_CRASH_DUMP_NONE)
+ continue;
+
+ dump_tlv = buf;
+ dump_tlv->type = cpu_to_le32(mem_idx);
+ dump_tlv->tlv_len = cpu_to_le32(dump_seg_sz[mem_idx]);
+ buf += COREDUMP_TLV_HDR_SIZE;
+
+ for (i = 0; i < ab->qmi.mem_seg_count; i++) {
+ mem_type = ath12k_coredump_get_dump_type
+ (ab->qmi.target_mem[i].type);
+
+ if (mem_type != mem_idx)
+ continue;
+
+ if (!ab->qmi.target_mem[i].paddr) {
+ ath12k_dbg(ab, ATH12K_DBG_PCI,
+ "Skipping mem region type %d",
+ ab->qmi.target_mem[i].type);
+ continue;
+ }
+
+ memcpy_fromio(buf, ab->qmi.target_mem[i].v.ioaddr,
+ ab->qmi.target_mem[i].size);
+ buf += ab->qmi.target_mem[i].size;
+ }
+ }
+
+ queue_work(ab->workqueue, &ab->dump_work);
+}
+#endif
+
int ath12k_pci_power_up(struct ath12k_base *ab)
{
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
@@ -1329,6 +1511,9 @@ static const struct ath12k_hif_ops ath12k_pci_hif_ops = {
.ce_irq_disable = ath12k_pci_hif_ce_irq_disable,
.get_ce_msi_idx = ath12k_pci_get_ce_msi_idx,
.panic_handler = ath12k_pci_panic_handler,
+#ifdef CONFIG_ATH12K_COREDUMP
+ .coredump_download = ath12k_pci_coredump_download,
+#endif
};
static
@@ -1538,6 +1723,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
set_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags);
cancel_work_sync(&ab->reset_work);
+ cancel_work_sync(&ab->dump_work);
ath12k_core_deinit(ab);
qmi_fail:
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index 19c0626fbff1..7a62665b8af9 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
@@ -186,7 +186,7 @@ void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id)
struct ath12k_peer *peer, *tmp;
struct ath12k_base *ab = ar->ab;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
@@ -235,7 +235,7 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
{
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->peer_delete_done);
@@ -261,14 +261,15 @@ static int ath12k_wait_for_peer_created(struct ath12k *ar, int vdev_id, const u8
return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, true);
}
-int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ieee80211_sta *sta,
struct ath12k_wmi_peer_create_arg *arg)
{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ath12k_peer *peer;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ar->num_peers > (ar->max_num_peers - 1)) {
ath12k_warn(ar->ab,
@@ -326,7 +327,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
peer->pdev_idx = ar->pdev_idx;
peer->sta = sta;
- if (arvif->vif->type == NL80211_IFTYPE_STATION) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
arvif->ast_hash = peer->ast_hash;
arvif->ast_idx = peer->hw_peer_id;
}
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 7b3500b5c8c2..b955f0cdf598 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_PEER_H
@@ -59,7 +59,7 @@ struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab,
struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id);
void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id);
int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr);
-int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
+int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ieee80211_sta *sta,
struct ath12k_wmi_peer_create_arg *arg);
int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/ath12k/rx_desc.h b/drivers/net/wireless/ath/ath12k/rx_desc.h
index a0db6702a189..10366bbe9999 100644
--- a/drivers/net/wireless/ath/ath12k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath12k/rx_desc.h
@@ -684,18 +684,17 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO5_SA_IDX_TIMEOUT BIT(0)
#define RX_MSDU_END_INFO5_DA_IDX_TIMEOUT BIT(1)
+#define RX_MSDU_END_INFO5_TO_DS BIT(2)
+#define RX_MSDU_END_INFO5_TID GENMASK(6, 3)
#define RX_MSDU_END_INFO5_SA_IS_VALID BIT(7)
#define RX_MSDU_END_INFO5_DA_IS_VALID BIT(8)
#define RX_MSDU_END_INFO5_DA_IS_MCBC BIT(9)
#define RX_MSDU_END_INFO5_L3_HDR_PADDING GENMASK(11, 10)
#define RX_MSDU_END_INFO5_FIRST_MSDU BIT(12)
#define RX_MSDU_END_INFO5_LAST_MSDU BIT(13)
+#define RX_MSDU_END_INFO5_FROM_DS BIT(14)
#define RX_MSDU_END_INFO5_IP_CHKSUM_FAIL_COPY BIT(15)
-#define RX_MSDU_END_QCN9274_INFO5_TO_DS BIT(2)
-#define RX_MSDU_END_QCN9274_INFO5_TID GENMASK(6, 3)
-#define RX_MSDU_END_QCN9274_INFO5_FROM_DS BIT(14)
-
#define RX_MSDU_END_INFO6_MSDU_DROP BIT(0)
#define RX_MSDU_END_INFO6_REO_DEST_IND GENMASK(5, 1)
#define RX_MSDU_END_INFO6_FLOW_IDX GENMASK(25, 6)
@@ -709,14 +708,14 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO7_FLOW_AGGR_CONTN BIT(8)
#define RX_MSDU_END_INFO7_FISA_TIMEOUT BIT(9)
-#define RX_MSDU_END_QCN9274_INFO7_TCPUDP_CSUM_FAIL_CPY BIT(10)
-#define RX_MSDU_END_QCN9274_INFO7_MSDU_LIMIT_ERROR BIT(11)
-#define RX_MSDU_END_QCN9274_INFO7_FLOW_IDX_TIMEOUT BIT(12)
-#define RX_MSDU_END_QCN9274_INFO7_FLOW_IDX_INVALID BIT(13)
-#define RX_MSDU_END_QCN9274_INFO7_CCE_MATCH BIT(14)
-#define RX_MSDU_END_QCN9274_INFO7_AMSDU_PARSER_ERR BIT(15)
+#define RX_MSDU_END_INFO7_TCPUDP_CSUM_FAIL_CPY BIT(10)
+#define RX_MSDU_END_INFO7_MSDU_LIMIT_ERROR BIT(11)
+#define RX_MSDU_END_INFO7_FLOW_IDX_TIMEOUT BIT(12)
+#define RX_MSDU_END_INFO7_FLOW_IDX_INVALID BIT(13)
+#define RX_MSDU_END_INFO7_CCE_MATCH BIT(14)
+#define RX_MSDU_END_INFO7_AMSDU_PARSER_ERR BIT(15)
-#define RX_MSDU_END_QCN9274_INFO8_KEY_ID GENMASK(7, 0)
+#define RX_MSDU_END_INFO8_KEY_ID GENMASK(7, 0)
#define RX_MSDU_END_INFO9_SERVICE_CODE GENMASK(14, 6)
#define RX_MSDU_END_INFO9_PRIORITY_VALID BIT(15)
@@ -758,8 +757,8 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO12_RECV_BW GENMASK(20, 18)
#define RX_MSDU_END_INFO12_RECEPTION_TYPE GENMASK(23, 21)
-#define RX_MSDU_END_QCN9274_INFO12_MIMO_SS_BITMAP GENMASK(30, 24)
-#define RX_MSDU_END_QCN9274_INFO12_MIMO_DONE_COPY BIT(31)
+#define RX_MSDU_END_INFO12_MIMO_SS_BITMAP GENMASK(30, 24)
+#define RX_MSDU_END_INFO12_MIMO_DONE_COPY BIT(31)
#define RX_MSDU_END_INFO13_FIRST_MPDU BIT(0)
#define RX_MSDU_END_INFO13_MCAST_BCAST BIT(2)
@@ -791,7 +790,7 @@ enum rx_msdu_start_reception_type {
#define RX_MSDU_END_INFO13_UNDECRYPT_FRAME_ERR BIT(30)
#define RX_MSDU_END_INFO13_FCS_ERR BIT(31)
-#define RX_MSDU_END_QCN9274_INFO13_WIFI_PARSER_ERR BIT(15)
+#define RX_MSDU_END_INFO13_WIFI_PARSER_ERR BIT(15)
#define RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE GENMASK(12, 10)
#define RX_MSDU_END_INFO14_RX_BITMAP_NOT_UPDED BIT(13)
@@ -889,65 +888,6 @@ struct rx_msdu_end_qcn9274_compact {
__le32 info14;
} __packed;
-/* These macro definitions are only used for WCN7850 */
-#define RX_MSDU_END_WCN7850_INFO2_KEY_ID BIT(7, 0)
-
-#define RX_MSDU_END_WCN7850_INFO5_MSDU_LIMIT_ERR BIT(2)
-#define RX_MSDU_END_WCN7850_INFO5_IDX_TIMEOUT BIT(3)
-#define RX_MSDU_END_WCN7850_INFO5_IDX_INVALID BIT(4)
-#define RX_MSDU_END_WCN7850_INFO5_WIFI_PARSE_ERR BIT(5)
-#define RX_MSDU_END_WCN7850_INFO5_AMSDU_PARSER_ERR BIT(6)
-#define RX_MSDU_END_WCN7850_INFO5_TCPUDP_CSUM_FAIL_CPY BIT(14)
-
-#define RX_MSDU_END_WCN7850_INFO12_MIMO_SS_BITMAP GENMASK(31, 24)
-
-#define RX_MSDU_END_WCN7850_INFO13_FRAGMENT_FLAG BIT(13)
-#define RX_MSDU_END_WCN7850_INFO13_CCE_MATCH BIT(15)
-
-struct rx_msdu_end_wcn7850 {
- __le16 info0;
- __le16 phy_ppdu_id;
- __le16 ip_hdr_cksum;
- __le16 info1;
- __le16 info2;
- __le16 cumulative_l3_checksum;
- __le32 rule_indication0;
- __le32 rule_indication1;
- __le16 info3;
- __le16 l3_type;
- __le32 ipv6_options_crc;
- __le32 tcp_seq_num;
- __le32 tcp_ack_num;
- __le16 info4;
- __le16 window_size;
- __le16 tcp_udp_chksum;
- __le16 info5;
- __le16 sa_idx;
- __le16 da_idx_or_sw_peer_id;
- __le32 info6;
- __le32 fse_metadata;
- __le16 cce_metadata;
- __le16 sa_sw_peer_id;
- __le16 info7;
- __le16 rsvd0;
- __le16 cumulative_l4_checksum;
- __le16 cumulative_ip_length;
- __le32 info9;
- __le32 info10;
- __le32 info11;
- __le32 toeplitz_hash_2_or_4;
- __le32 flow_id_toeplitz;
- __le32 info12;
- __le32 ppdu_start_timestamp_31_0;
- __le32 ppdu_start_timestamp_63_32;
- __le32 phy_meta_data;
- __le16 vlan_ctag_ci;
- __le16 vlan_stag_ci;
- __le32 rsvd[3];
- __le32 info13;
- __le32 info14;
-} __packed;
-
/* rx_msdu_end
*
* rxpcu_mpdu_filter_in_category
@@ -1578,7 +1518,7 @@ struct rx_pkt_hdr_tlv {
struct hal_rx_desc_wcn7850 {
__le64 msdu_end_tag;
- struct rx_msdu_end_wcn7850 msdu_end;
+ struct rx_msdu_end_qcn9274 msdu_end;
u8 rx_padding0[RX_BE_PADDING0_BYTES];
__le64 mpdu_start_tag;
struct rx_mpdu_start_qcn9274 mpdu_start;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 2cd3ff9b0164..dced2aa9ba1a 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -6687,7 +6687,8 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
const u32 *vdev_ids)
{
int i;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif *ahvif;
/* Finish CSA once the switch count becomes NULL */
if (ev->current_switch_count)
@@ -6702,9 +6703,10 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
vdev_ids[i]);
continue;
}
+ ahvif = arvif->ahvif;
- if (arvif->is_up && arvif->vif->bss_conf.csa_active)
- ieee80211_csa_finish(arvif->vif, 0);
+ if (arvif->is_up && ahvif->vif->bss_conf.csa_active)
+ ieee80211_csa_finish(ahvif->vif, 0);
}
rcu_read_unlock();
}
@@ -7098,7 +7100,7 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
struct sk_buff *skb)
{
const struct wmi_gtk_offload_status_event *ev;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
__be64 replay_ctr_be;
u64 replay_ctr;
const void **tb;
@@ -7136,7 +7138,7 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
/* supplicant expects big-endian replay counter */
replay_ctr_be = cpu_to_be64(replay_ctr);
- ieee80211_gtk_rekey_notify(arvif->vif, arvif->bssid,
+ ieee80211_gtk_rekey_notify(arvif->ahvif->vif, arvif->bssid,
(void *)&replay_ctr_be, GFP_ATOMIC);
rcu_read_unlock();
@@ -7284,9 +7286,11 @@ static int ath12k_connect_pdev_htc_service(struct ath12k_base *ab,
u32 pdev_idx)
{
int status;
- u32 svc_id[] = { ATH12K_HTC_SVC_ID_WMI_CONTROL,
- ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1,
- ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2 };
+ static const u32 svc_id[] = {
+ ATH12K_HTC_SVC_ID_WMI_CONTROL,
+ ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1,
+ ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2
+ };
struct ath12k_htc_svc_conn_req conn_req = {};
struct ath12k_htc_svc_conn_resp conn_resp = {};
@@ -7372,13 +7376,13 @@ ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,
int ath12k_wmi_simulate_radar(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
u32 dfs_args[DFS_MAX_TEST_ARGS];
struct wmi_unit_test_cmd wmi_ut;
bool arvif_found = false;
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->is_started && arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ if (arvif->is_started && arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
arvif_found = true;
break;
}
@@ -7940,7 +7944,7 @@ static void ath12k_wmi_fill_arp_offload(struct ath12k *ar,
}
int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload,
bool enable)
{
@@ -7989,7 +7993,7 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
}
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
- struct ath12k_vif *arvif, bool enable)
+ struct ath12k_link_vif *arvif, bool enable)
{
struct ath12k_rekey_data *rekey_data = &arvif->rekey_data;
struct wmi_gtk_rekey_offload_cmd *cmd;
@@ -8026,7 +8030,7 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
}
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
- struct ath12k_vif *arvif)
+ struct ath12k_link_vif *arvif)
{
struct wmi_gtk_rekey_offload_cmd *cmd;
struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 6a913f9b8315..6f55dbdf629d 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -24,7 +24,7 @@
struct ath12k_base;
struct ath12k;
-struct ath12k_vif;
+struct ath12k_link_vif;
/* There is no signed version of __le32, so for a temporary solution come
* up with our own version. The idea is from fs/ntfs/endian.h.
@@ -5627,13 +5627,13 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar,
struct wmi_hw_data_filter_arg *arg);
int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
- struct ath12k_vif *arvif,
+ struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload,
bool enable);
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
- struct ath12k_vif *arvif, bool enable);
+ struct ath12k_link_vif *arvif, bool enable);
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
- struct ath12k_vif *arvif);
+ struct ath12k_link_vif *arvif);
int ath12k_wmi_sta_keepalive(struct ath12k *ar,
const struct wmi_sta_keepalive_arg *arg);
diff --git a/drivers/net/wireless/ath/ath12k/wow.c b/drivers/net/wireless/ath/ath12k/wow.c
index 9b8684abbe40..9e1c0bfd212f 100644
--- a/drivers/net/wireless/ath/ath12k/wow.c
+++ b/drivers/net/wireless/ath/ath12k/wow.c
@@ -29,11 +29,11 @@ static const struct wiphy_wowlan_support ath12k_wowlan_support = {
.max_pkt_offset = WOW_MAX_PKT_OFFSET,
};
-static inline bool ath12k_wow_is_p2p_vdev(struct ath12k_vif *arvif)
+static inline bool ath12k_wow_is_p2p_vdev(struct ath12k_vif *ahvif)
{
- return (arvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_DEVICE ||
- arvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_CLIENT ||
- arvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_GO);
+ return (ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_DEVICE ||
+ ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_CLIENT ||
+ ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_P2P_GO);
}
int ath12k_wow_enable(struct ath12k *ar)
@@ -101,7 +101,7 @@ int ath12k_wow_wakeup(struct ath12k *ar)
return 0;
}
-static int ath12k_wow_vif_cleanup(struct ath12k_vif *arvif)
+static int ath12k_wow_vif_cleanup(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
int i, ret;
@@ -129,10 +129,10 @@ static int ath12k_wow_vif_cleanup(struct ath12k_vif *arvif)
static int ath12k_wow_cleanup(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
ret = ath12k_wow_vif_cleanup(arvif);
@@ -191,7 +191,7 @@ ath12k_wow_convert_8023_to_80211(struct ath12k *ar,
memcpy(bytemask, eth_bytemask, eth_pat_len);
pat_len = eth_pat_len;
- } else if (eth_pkt_ofs + eth_pat_len < prot_ofs) {
+ } else if (size_add(eth_pkt_ofs, eth_pat_len) < prot_ofs) {
memcpy(pat, eth_pat, ETH_ALEN - eth_pkt_ofs);
memcpy(bytemask, eth_bytemask, ETH_ALEN - eth_pkt_ofs);
@@ -354,7 +354,7 @@ ath12k_wow_pno_check_and_convert(struct ath12k *ar, u32 vdev_id,
return 0;
}
-static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif,
+static int ath12k_wow_vif_set_wakeups(struct ath12k_link_vif *arvif,
struct cfg80211_wowlan *wowlan)
{
const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
@@ -364,7 +364,7 @@ static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif,
int ret, i, j;
/* Setup requested WOW features */
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_IBSS:
__set_bit(WOW_BEACON_EVENT, &wow_mask);
fallthrough;
@@ -473,13 +473,13 @@ static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif,
static int ath12k_wow_set_wakeups(struct ath12k *ar,
struct cfg80211_wowlan *wowlan)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (ath12k_wow_is_p2p_vdev(arvif))
+ if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
ret = ath12k_wow_vif_set_wakeups(arvif, wowlan);
if (ret) {
@@ -518,11 +518,11 @@ out:
return ret;
}
-static int ath12k_wow_vif_clean_nlo(struct ath12k_vif *arvif)
+static int ath12k_wow_vif_clean_nlo(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
- switch (arvif->vdev_type) {
+ switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_STA:
return ath12k_wow_vdev_clean_nlo(ar, arvif->vdev_id);
default:
@@ -532,13 +532,13 @@ static int ath12k_wow_vif_clean_nlo(struct ath12k_vif *arvif)
static int ath12k_wow_nlo_cleanup(struct ath12k *ar)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (ath12k_wow_is_p2p_vdev(arvif))
+ if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
ret = ath12k_wow_vif_clean_nlo(arvif);
@@ -555,13 +555,13 @@ static int ath12k_wow_nlo_cleanup(struct ath12k *ar)
static int ath12k_wow_set_hw_filter(struct ath12k *ar)
{
struct wmi_hw_data_filter_arg arg;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
arg.vdev_id = arvif->vdev_id;
@@ -581,13 +581,13 @@ static int ath12k_wow_set_hw_filter(struct ath12k *ar)
static int ath12k_wow_clear_hw_filter(struct ath12k *ar)
{
struct wmi_hw_data_filter_arg arg;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
arg.vdev_id = arvif->vdev_id;
@@ -626,10 +626,10 @@ static void ath12k_wow_generate_ns_mc_addr(struct ath12k_base *ab,
}
}
-static void ath12k_wow_prepare_ns_offload(struct ath12k_vif *arvif,
+static void ath12k_wow_prepare_ns_offload(struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload)
{
- struct net_device *ndev = ieee80211_vif_to_wdev(arvif->vif)->netdev;
+ struct net_device *ndev = ieee80211_vif_to_wdev(arvif->ahvif->vif)->netdev;
struct ath12k_base *ab = arvif->ar->ab;
struct inet6_ifaddr *ifa6;
struct ifacaddr6 *ifaca6;
@@ -710,10 +710,10 @@ unlock:
ath12k_wow_generate_ns_mc_addr(ab, offload);
}
-static void ath12k_wow_prepare_arp_offload(struct ath12k_vif *arvif,
+static void ath12k_wow_prepare_arp_offload(struct ath12k_link_vif *arvif,
struct wmi_arp_ns_offload_arg *offload)
{
- struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
struct ieee80211_vif_cfg vif_cfg = vif->cfg;
struct ath12k_base *ab = arvif->ar->ab;
u32 ipv4_cnt;
@@ -732,22 +732,25 @@ static void ath12k_wow_prepare_arp_offload(struct ath12k_vif *arvif,
static int ath12k_wow_arp_ns_offload(struct ath12k *ar, bool enable)
{
struct wmi_arp_ns_offload_arg *offload;
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif *ahvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
offload = kmalloc(sizeof(*offload), GFP_KERNEL);
if (!offload)
return -ENOMEM;
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ ahvif = arvif->ahvif;
+
+ if (ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
memset(offload, 0, sizeof(*offload));
- memcpy(offload->mac_addr, arvif->vif->addr, ETH_ALEN);
+ memcpy(offload->mac_addr, ahvif->vif->addr, ETH_ALEN);
ath12k_wow_prepare_ns_offload(arvif, offload);
ath12k_wow_prepare_arp_offload(arvif, offload);
@@ -766,13 +769,13 @@ static int ath12k_wow_arp_ns_offload(struct ath12k *ar, bool enable)
static int ath12k_gtk_rekey_offload(struct ath12k *ar, bool enable)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->vdev_type != WMI_VDEV_TYPE_STA ||
+ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA ||
!arvif->is_up ||
!arvif->rekey_data.enable_offload)
continue;
@@ -824,10 +827,10 @@ static int ath12k_wow_set_keepalive(struct ath12k *ar,
enum wmi_sta_keepalive_method method,
u32 interval)
{
- struct ath12k_vif *arvif;
+ struct ath12k_link_vif *arvif;
int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
ret = ath12k_mac_vif_set_keepalive(arvif, method, interval);
@@ -845,7 +848,7 @@ int ath12k_wow_op_suspend(struct ieee80211_hw *hw,
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
int ret;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
ret = ath12k_wow_cleanup(ar);
if (ret) {
@@ -913,7 +916,6 @@ cleanup:
ath12k_wow_cleanup(ar);
exit:
- mutex_unlock(&ar->conf_mutex);
return ret ? 1 : 0;
}
@@ -922,9 +924,9 @@ void ath12k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
+
device_set_wakeup_enable(ar->ab->dev, enabled);
- mutex_unlock(&ar->conf_mutex);
}
int ath12k_wow_op_resume(struct ieee80211_hw *hw)
@@ -933,7 +935,7 @@ int ath12k_wow_op_resume(struct ieee80211_hw *hw)
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
int ret;
- mutex_lock(&ar->conf_mutex);
+ lockdep_assert_wiphy(hw->wiphy);
ret = ath12k_hif_resume(ar->ab);
if (ret) {
@@ -995,7 +997,6 @@ exit:
}
}
- mutex_unlock(&ar->conf_mutex);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index f27308ccb2f1..cb3e891ee1bd 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -218,10 +218,10 @@ static void ath_ahb_remove(struct platform_device *pdev)
}
static struct platform_driver ath_ahb_driver = {
- .probe = ath_ahb_probe,
- .remove_new = ath_ahb_remove,
- .driver = {
- .name = "ar231x-wmac",
+ .probe = ath_ahb_probe,
+ .remove = ath_ahb_remove,
+ .driver = {
+ .name = "ar231x-wmac",
},
};
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index b51fce5ae260..f5ca2fe0d074 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -46,6 +46,8 @@ static const struct pci_device_id ath5k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
{ PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
+ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* Gigaset SX76[23] AR241[34]A */
+ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* Arcadyan ARV45XX AR2417 */
{ PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
{ 0 }
};
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index b4fcfb72991c..68384159870b 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1249,7 +1249,7 @@ struct wmi_rssi_threshold_params_cmd {
/* highest of upper */
a_sle16 thresh_above6_val;
- /* lowest of bellow */
+ /* lowest of below */
a_sle16 thresh_below1_val;
a_sle16 thresh_below2_val;
@@ -1257,7 +1257,7 @@ struct wmi_rssi_threshold_params_cmd {
a_sle16 thresh_below4_val;
a_sle16 thresh_below5_val;
- /* highest of bellow */
+ /* highest of below */
a_sle16 thresh_below6_val;
/* "alpha" */
@@ -1287,13 +1287,13 @@ struct wmi_snr_threshold_params_cmd {
/* highest of upper */
u8 thresh_above4_val;
- /* lowest of bellow */
+ /* lowest of below */
u8 thresh_below1_val;
u8 thresh_below2_val;
u8 thresh_below3_val;
- /* highest of bellow */
+ /* highest of below */
u8 thresh_below4_val;
u8 reserved[3];
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 1a6697b6e3b4..d4805e02b927 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -158,12 +158,12 @@ static void ath_ahb_remove(struct platform_device *pdev)
}
static struct platform_driver ath_ahb_driver = {
- .probe = ath_ahb_probe,
- .remove_new = ath_ahb_remove,
- .driver = {
- .name = "ath9k",
+ .probe = ath_ahb_probe,
+ .remove = ath_ahb_remove,
+ .driver = {
+ .name = "ath9k",
},
- .id_table = ath9k_platform_id_table,
+ .id_table = ath9k_platform_id_table,
};
MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_aic.c b/drivers/net/wireless/ath/ath9k/ar9003_aic.c
index d0f1e8bcc846..45a7ca660f47 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_aic.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_aic.c
@@ -409,13 +409,11 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah)
sram.valid = true;
sram.rot_dir_att_db =
- min(max(rot_dir_path_att_db,
- (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB),
- ATH_AIC_MAX_ROT_DIR_ATT_DB);
+ clamp(rot_dir_path_att_db, (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB,
+ ATH_AIC_MAX_ROT_DIR_ATT_DB);
sram.rot_quad_att_db =
- min(max(rot_quad_path_att_db,
- (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB),
- ATH_AIC_MAX_ROT_QUAD_ATT_DB);
+ clamp(rot_quad_path_att_db, (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB,
+ ATH_AIC_MAX_ROT_QUAD_ATT_DB);
aic->aic_sram[i] = (SM(sram.vga_dir_sign,
AR_PHY_AIC_SRAM_VGA_DIR_SIGN) |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
index 004ca5f536be..fe1013a3a588 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
+++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
@@ -18,7 +18,6 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/ath9k_platform.h>
#include <linux/nvmem-consumer.h>
#include <linux/workqueue.h>
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 9b393a8f7c3a..ad3a3fda1b9c 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -16,7 +16,6 @@
#include <linux/export.h>
#include <linux/types.h>
-#include <linux/ath9k_platform.h>
#include "hw.h"
enum ath_bt_mode {
@@ -115,23 +114,14 @@ static void ath9k_hw_btcoex_pin_init(struct ath_hw *ah, u8 wlanactive_gpio,
u8 btactive_gpio, u8 btpriority_gpio)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
- struct ath9k_platform_data *pdata = ah->dev->platform_data;
if (btcoex_hw->scheme != ATH_BTCOEX_CFG_2WIRE &&
btcoex_hw->scheme != ATH_BTCOEX_CFG_3WIRE)
return;
- /* bt priority GPIO will be ignored by 2 wire scheme */
- if (pdata && (pdata->bt_active_pin || pdata->bt_priority_pin ||
- pdata->wlan_active_pin)) {
- btcoex_hw->btactive_gpio = pdata->bt_active_pin;
- btcoex_hw->wlanactive_gpio = pdata->wlan_active_pin;
- btcoex_hw->btpriority_gpio = pdata->bt_priority_pin;
- } else {
- btcoex_hw->btactive_gpio = btactive_gpio;
- btcoex_hw->wlanactive_gpio = wlanactive_gpio;
- btcoex_hw->btpriority_gpio = btpriority_gpio;
- }
+ btcoex_hw->btactive_gpio = btactive_gpio;
+ btcoex_hw->wlanactive_gpio = wlanactive_gpio;
+ btcoex_hw->btpriority_gpio = btpriority_gpio;
}
void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index efb7889142d4..df58dc02e104 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -15,7 +15,6 @@
*/
#include "hw.h"
-#include <linux/ath9k_platform.h>
void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
{
@@ -119,14 +118,6 @@ static bool ath9k_hw_nvram_read_array(u16 *blob, size_t blob_size,
return true;
}
-static bool ath9k_hw_nvram_read_pdata(struct ath9k_platform_data *pdata,
- off_t offset, u16 *data)
-{
- return ath9k_hw_nvram_read_array(pdata->eeprom_data,
- ARRAY_SIZE(pdata->eeprom_data),
- offset, data);
-}
-
static bool ath9k_hw_nvram_read_firmware(const struct firmware *eeprom_blob,
off_t offset, u16 *data)
{
@@ -146,15 +137,12 @@ static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset,
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_platform_data *pdata = ah->dev->platform_data;
bool ret;
if (ah->nvmem_blob)
ret = ath9k_hw_nvram_read_nvmem(ah, off, data);
else if (ah->eeprom_blob)
ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
- else if (pdata && !pdata->use_eeprom)
- ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
else
ret = common->bus_ops->eeprom_read(common, off, data);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 8a03bcc2789e..57094bd45d98 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1357,8 +1357,10 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u32 changed)
+ struct ieee80211_link_sta *link_sta,
+ u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED))
@@ -1883,7 +1885,7 @@ struct ieee80211_ops ath9k_htc_ops = {
.sta_add = ath9k_htc_sta_add,
.sta_remove = ath9k_htc_sta_remove,
.conf_tx = ath9k_htc_conf_tx,
- .sta_rc_update = ath9k_htc_sta_rc_update,
+ .link_sta_rc_update = ath9k_htc_sta_rc_update,
.bss_info_changed = ath9k_htc_bss_info_changed,
.set_key = ath9k_htc_set_key,
.get_tsf = ath9k_htc_get_tsf,
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index eb631fd3336d..b5257b2b4aa5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -294,6 +294,9 @@ int htc_connect_service(struct htc_target *target,
return -ETIMEDOUT;
}
+ if (target->conn_rsp_epid < 0 || target->conn_rsp_epid >= ENDPOINT_MAX)
+ return -EINVAL;
+
*conn_rsp_epid = target->conn_rsp_epid;
return 0;
err:
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c3a6368bfc68..e2bef099adb3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -490,7 +490,7 @@ static void ath9k_hw_init_macaddr(struct ath_hw *ah)
u16 eeval;
static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
- /* MAC address may already be loaded via ath9k_platform_data */
+ /* MAC address may already be loaded via NVMEM */
if (is_valid_ether_addr(common->macaddr))
return;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 7fad7e75af6a..f9e77c4624d9 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -18,7 +18,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <linux/ath9k_platform.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_net.h>
@@ -583,8 +582,8 @@ static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
/* nvmem cell might not be defined, or the nvmem
* subsystem isn't included. In this case, follow
- * the established "just return 0;" convention of
- * ath9k_init_platform to say:
+ * the established "just return 0;" convention
+ * to say:
* "All good. Nothing to see here. Please go on."
*/
if (err == -ENOENT || err == -EOPNOTSUPP)
@@ -620,49 +619,6 @@ static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
return 0;
}
-static int ath9k_init_platform(struct ath_softc *sc)
-{
- struct ath9k_platform_data *pdata = sc->dev->platform_data;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- int ret;
-
- if (!pdata)
- return 0;
-
- if (!pdata->use_eeprom) {
- ah->ah_flags &= ~AH_USE_EEPROM;
- ah->gpio_mask = pdata->gpio_mask;
- ah->gpio_val = pdata->gpio_val;
- ah->led_pin = pdata->led_pin;
- ah->is_clk_25mhz = pdata->is_clk_25mhz;
- ah->get_mac_revision = pdata->get_mac_revision;
- ah->external_reset = pdata->external_reset;
- ah->disable_2ghz = pdata->disable_2ghz;
- ah->disable_5ghz = pdata->disable_5ghz;
-
- if (!pdata->endian_check)
- ah->ah_flags |= AH_NO_EEP_SWAP;
- }
-
- if (pdata->eeprom_name) {
- ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
- if (ret)
- return ret;
- }
-
- if (pdata->led_active_high)
- ah->config.led_active_high = true;
-
- if (pdata->tx_gain_buffalo)
- ah->config.tx_gain_buffalo = true;
-
- if (pdata->macaddr)
- ether_addr_copy(common->macaddr, pdata->macaddr);
-
- return 0;
-}
-
static int ath9k_of_init(struct ath_softc *sc)
{
struct device_node *np = sc->dev->of_node;
@@ -748,10 +704,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
*/
ath9k_init_pcoem_platform(sc);
- ret = ath9k_init_platform(sc);
- if (ret)
- return ret;
-
ret = ath9k_of_init(sc);
if (ret)
return ret;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 408776562a7e..8557d4826a46 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1679,10 +1679,10 @@ static const struct of_device_id wcn36xx_of_match[] = {
MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
static struct platform_driver wcn36xx_driver = {
- .probe = wcn36xx_probe,
- .remove_new = wcn36xx_remove,
- .driver = {
- .name = "wcn36xx",
+ .probe = wcn36xx_probe,
+ .remove = wcn36xx_remove,
+ .driver = {
+ .name = "wcn36xx",
.of_match_table = wcn36xx_of_match,
},
};
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index bccc27de848d..7ee79593cd23 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -167,7 +167,7 @@ struct wcn36xx_vif {
* @dpu_desc_index: DPU descriptor index is returned from HW after config_sta
* call and is used in TX BD.
* @bss_sta_index: STA index is returned from HW after config_bss call and is
- * used in both SMD channel and TX BD. See table bellow when it is used.
+ * used in both SMD channel and TX BD. See table below when it is used.
* @bss_dpu_desc_index: DPU descriptor index is returned from HW after
* config_bss call and is used in TX BD.
* ______________________________________________
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index e8f1d30a8d73..a1a0a9223e74 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1493,6 +1493,7 @@ out:
}
static int wil_cfg80211_set_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index d35262335eaf..42d991d9f8cb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -770,7 +770,7 @@ void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
sdiodev->settings->bus.sdio.txglomsz);
- nents += (nents >> 4) + 1;
+ nents *= 2;
WARN_ON(nents > sdiodev->max_segment_count);
@@ -947,8 +947,8 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
/* try to attach to the target device */
sdiodev->bus = brcmf_sdio_probe(sdiodev);
- if (!sdiodev->bus) {
- ret = -ENODEV;
+ if (IS_ERR(sdiodev->bus)) {
+ ret = PTR_ERR(sdiodev->bus);
goto out;
}
brcmf_sdiod_host_fixup(sdiodev->func2->card->host);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 349aa3439502..297a7c738c01 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -7820,13 +7820,6 @@ s32 brcmf_cfg80211_down(struct net_device *ndev)
return err;
}
-enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)
-{
- struct wireless_dev *wdev = &ifp->vif->wdev;
-
- return wdev->iftype;
-}
-
bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,
unsigned long state)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index dc3a6a537507..2abae8894614 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -443,7 +443,6 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
s32 brcmf_cfg80211_up(struct net_device *ndev);
s32 brcmf_cfg80211_down(struct net_device *ndev);
struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings);
-enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype type);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index b24faae35873..cfcf01eb0daa 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -561,7 +561,8 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
if (!found) {
/* No platform data for this device, try OF and DMI data */
brcmf_dmi_probe(settings, chip, chiprev);
- brcmf_of_probe(dev, bus_type, settings);
+ if (brcmf_of_probe(dev, bus_type, settings) == -EPROBE_DEFER)
+ return ERR_PTR(-EPROBE_DEFER);
brcmf_acpi_probe(dev, bus_type, settings);
}
return settings;
@@ -593,7 +594,7 @@ static void brcmf_common_pd_remove(struct platform_device *pdev)
}
static struct platform_driver brcmf_pd = {
- .remove_new = brcmf_common_pd_remove,
+ .remove = brcmf_common_pd_remove,
.driver = {
.name = BRCMFMAC_PDATA_NAME,
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
index fe4f65756105..c1f18e2fe540 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
@@ -6,6 +6,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_net.h>
+#include <linux/clk.h>
#include <defs.h>
#include "debug.h"
@@ -65,12 +66,13 @@ static int brcmf_of_get_country_codes(struct device *dev,
return 0;
}
-void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
- struct brcmf_mp_device *settings)
+int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ struct brcmf_mp_device *settings)
{
struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
struct device_node *root, *np = dev->of_node;
struct of_phandle_args oirq;
+ struct clk *clk;
const char *prop;
int irq;
int err;
@@ -106,16 +108,21 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
board_type = devm_kstrdup(dev, tmp, GFP_KERNEL);
if (!board_type) {
of_node_put(root);
- return;
+ return 0;
}
strreplace(board_type, '/', '-');
settings->board_type = board_type;
-
- of_node_put(root);
}
+ of_node_put(root);
+
+ clk = devm_clk_get_optional_enabled_with_rate(dev, "lpo", 32768);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ brcmf_dbg(INFO, "%s LPO clock\n", clk ? "enable" : "no");
if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
- return;
+ return 0;
err = brcmf_of_get_country_codes(dev, settings);
if (err)
@@ -124,23 +131,25 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
of_get_mac_address(np, settings->mac);
if (bus_type != BRCMF_BUSTYPE_SDIO)
- return;
+ return 0;
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
sdio->drive_strength = val;
/* make sure there are interrupts defined in the node */
if (of_irq_parse_one(np, 0, &oirq))
- return;
+ return 0;
irq = irq_create_of_mapping(&oirq);
if (!irq) {
brcmf_err("interrupt could not be mapped\n");
- return;
+ return 0;
}
- irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irqf = irq_get_trigger_type(irq);
sdio->oob_irq_supported = true;
sdio->oob_irq_nr = irq;
sdio->oob_irq_flags = irqf;
+
+ return 0;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
index 10bf52253337..ae124c73fc3b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
@@ -3,11 +3,12 @@
* Copyright (c) 2014 Broadcom Corporation
*/
#ifdef CONFIG_OF
-void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
- struct brcmf_mp_device *settings);
+int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ struct brcmf_mp_device *settings);
#else
-static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
- struct brcmf_mp_device *settings)
+static int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ struct brcmf_mp_device *settings)
{
+ return 0;
}
#endif /* CONFIG_OF */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 5dee54819fbd..e4395b1f8c11 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -66,6 +66,7 @@ BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");
BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
+BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-pcie");
BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");
BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie");
@@ -104,6 +105,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
+ BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),
BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */
@@ -353,6 +355,7 @@ struct brcmf_pciedev_info {
u16 value);
struct brcmf_mp_device *settings;
struct brcmf_otp_params otp;
+ bool fwseed;
#ifdef DEBUG
u32 console_interval;
bool console_active;
@@ -1715,14 +1718,14 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
brcmf_fw_nvram_free(nvram);
- if (devinfo->otp.valid) {
+ if (devinfo->fwseed) {
size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;
struct brcmf_random_seed_footer footer = {
.length = cpu_to_le32(rand_len),
.magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
};
- /* Some Apple chips/firmwares expect a buffer of random
+ /* Some chips/firmwares expect a buffer of random
* data to be present before NVRAM
*/
brcmf_dbg(PCIE, "Download random seed\n");
@@ -2394,6 +2397,37 @@ static void brcmf_pcie_debugfs_create(struct device *dev)
}
#endif
+struct brcmf_pcie_drvdata {
+ enum brcmf_fwvendor vendor;
+ bool fw_seed;
+};
+
+enum {
+ BRCMF_DRVDATA_CYW,
+ BRCMF_DRVDATA_BCA,
+ BRCMF_DRVDATA_WCC,
+ BRCMF_DRVDATA_WCC_SEED,
+};
+
+static const struct brcmf_pcie_drvdata drvdata[] = {
+ [BRCMF_DRVDATA_CYW] = {
+ .vendor = BRCMF_FWVENDOR_CYW,
+ .fw_seed = false,
+ },
+ [BRCMF_DRVDATA_BCA] = {
+ .vendor = BRCMF_FWVENDOR_BCA,
+ .fw_seed = false,
+ },
+ [BRCMF_DRVDATA_WCC] = {
+ .vendor = BRCMF_FWVENDOR_WCC,
+ .fw_seed = false,
+ },
+ [BRCMF_DRVDATA_WCC_SEED] = {
+ .vendor = BRCMF_FWVENDOR_WCC,
+ .fw_seed = true,
+ },
+};
+
/* Forward declaration for pci_match_id() call */
static const struct pci_device_id brcmf_pcie_devid_table[];
@@ -2452,6 +2486,9 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = -ENOMEM;
goto fail;
}
+ ret = PTR_ERR_OR_ZERO(devinfo->settings);
+ if (ret < 0)
+ goto fail;
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (!bus) {
@@ -2472,9 +2509,10 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
bus->bus_priv.pcie = pcie_bus_dev;
bus->ops = &brcmf_pcie_bus_ops;
bus->proto_type = BRCMF_PROTO_MSGBUF;
- bus->fwvid = id->driver_data;
bus->chip = devinfo->coreid;
bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
+ bus->fwvid = drvdata[id->driver_data].vendor;
+ devinfo->fwseed = drvdata[id->driver_data].fw_seed;
dev_set_drvdata(&pdev->dev, bus);
ret = brcmf_alloc(&devinfo->pdev->dev, devinfo->settings);
@@ -2660,14 +2698,14 @@ static const struct dev_pm_ops brcmf_pciedrvr_pm = {
BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \
PCI_ANY_ID, PCI_ANY_ID, \
PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \
- BRCMF_FWVENDOR_ ## fw_vend \
+ BRCMF_DRVDATA_ ## fw_vend \
}
#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev, fw_vend) \
{ \
BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \
(subvend), (subdev), \
PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \
- BRCMF_FWVENDOR_ ## fw_vend \
+ BRCMF_DRVDATA_ ## fw_vend \
}
static const struct pci_device_id brcmf_pcie_devid_table[] = {
@@ -2695,9 +2733,10 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW),
- BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC),
- BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC),
- BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC_SEED),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC_SEED),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC_SEED),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_43752_DEVICE_ID, WCC_SEED),
{ /* end: all zeroes */ }
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 7b936668c1b6..b1727f35217b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3943,7 +3943,7 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
.write32 = brcmf_sdio_buscore_write32,
};
-static bool
+static int
brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
{
struct brcmf_sdio_dev *sdiodev;
@@ -3953,6 +3953,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
u32 reg_val;
u32 drivestrength;
u32 enum_base;
+ int ret = -EBADE;
sdiodev = bus->sdiodev;
sdio_claim_host(sdiodev->func1);
@@ -4001,8 +4002,9 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
BRCMF_BUSTYPE_SDIO,
bus->ci->chip,
bus->ci->chiprev);
- if (!sdiodev->settings) {
+ if (IS_ERR_OR_NULL(sdiodev->settings)) {
brcmf_err("Failed to get device parameters\n");
+ ret = PTR_ERR_OR_ZERO(sdiodev->settings);
goto fail;
}
/* platform specific configuration:
@@ -4071,7 +4073,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
/* allocate header buffer */
bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL);
if (!bus->hdrbuf)
- return false;
+ return -ENOMEM;
/* Locate an appropriately-aligned portion of hdrbuf */
bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
bus->head_align);
@@ -4082,11 +4084,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
if (bus->poll)
bus->pollrate = 1;
- return true;
+ return 0;
fail:
sdio_release_host(sdiodev->func1);
- return false;
+ return ret;
}
static int
@@ -4451,8 +4453,10 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
/* Allocate private bus interface state */
bus = kzalloc(sizeof(*bus), GFP_ATOMIC);
- if (!bus)
+ if (!bus) {
+ ret = -ENOMEM;
goto fail;
+ }
bus->sdiodev = sdiodev;
sdiodev->bus = bus;
@@ -4467,6 +4471,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
dev_name(&sdiodev->func1->dev));
if (!wq) {
brcmf_err("insufficient memory to create txworkqueue\n");
+ ret = -ENOMEM;
goto fail;
}
brcmf_sdiod_freezer_count(sdiodev);
@@ -4474,7 +4479,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
bus->brcmf_wq = wq;
/* attempt to attach to the dongle */
- if (!(brcmf_sdio_probe_attach(bus))) {
+ ret = brcmf_sdio_probe_attach(bus);
+ if (ret < 0) {
brcmf_err("brcmf_sdio_probe_attach failed\n");
goto fail;
}
@@ -4546,7 +4552,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
fail:
brcmf_sdio_remove(bus);
- return NULL;
+ return ERR_PTR(ret);
}
/* Detach and free everything */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 8afbf529c745..2821c27f317e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1272,6 +1272,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
ret = -ENOMEM;
goto fail;
}
+ ret = PTR_ERR_OR_ZERO(devinfo->settings);
+ if (ret < 0)
+ goto fail;
if (!brcmf_usb_dlneeded(devinfo)) {
ret = brcmf_alloc(devinfo->dev, devinfo->settings);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
index 6d776ef6ff54..81df41c7fbb5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
@@ -56,11 +56,6 @@ void brcms_debugfs_detach(struct brcms_pub *drvr)
debugfs_remove_recursive(drvr->dbgfs_dir);
}
-struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr)
-{
- return drvr->dbgfs_dir;
-}
-
static
int brcms_debugfs_hardware_read(struct seq_file *s, void *data)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
index 56898e6d789d..d30a9fa30f1b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
@@ -70,7 +70,6 @@ void brcms_debugfs_init(void);
void brcms_debugfs_exit(void);
void brcms_debugfs_attach(struct brcms_pub *drvr);
void brcms_debugfs_detach(struct brcms_pub *drvr);
-struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr);
void brcms_debugfs_create_files(struct brcms_pub *drvr);
#endif /* _BRCMS_DEBUG_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
index bd480239368a..80c35027787a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
@@ -1426,15 +1426,6 @@ int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
return -ENOSPC;
}
-void dma_txflush(struct dma_pub *pub)
-{
- struct dma_info *di = container_of(pub, struct dma_info, dma);
- struct brcms_ampdu_session *session = &di->ampdu_session;
-
- if (!skb_queue_empty(&session->skb_list))
- ampdu_finalize(di);
-}
-
int dma_txpending(struct dma_pub *pub)
{
struct dma_info *di = container_of(pub, struct dma_info, dma);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h
index ff5b80b09046..7905fd081721 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h
@@ -88,7 +88,6 @@ bool dma_txreset(struct dma_pub *pub);
void dma_txinit(struct dma_pub *pub);
int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
struct sk_buff *p0);
-void dma_txflush(struct dma_pub *pub);
int dma_txpending(struct dma_pub *pub);
void dma_kick_tx(struct dma_pub *pub);
void dma_txsuspend(struct dma_pub *pub);
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index 44684bf1b9ac..c1e22c589d85 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -52,6 +52,7 @@
#define BRCM_CC_43664_CHIP_ID 43664
#define BRCM_CC_43666_CHIP_ID 43666
#define BRCM_CC_4371_CHIP_ID 0x4371
+#define BRCM_CC_43752_CHIP_ID 43752
#define BRCM_CC_4377_CHIP_ID 0x4377
#define BRCM_CC_4378_CHIP_ID 0x4378
#define BRCM_CC_4387_CHIP_ID 0x4387
@@ -94,6 +95,7 @@
#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5
#define BRCM_PCIE_4371_DEVICE_ID 0x440d
#define BRCM_PCIE_43596_DEVICE_ID 0x4415
+#define BRCM_PCIE_43752_DEVICE_ID 0x449d
#define BRCM_PCIE_4377_DEVICE_ID 0x4488
#define BRCM_PCIE_4378_DEVICE_ID 0x4425
#define BRCM_PCIE_4387_DEVICE_ID 0x4433
diff --git a/drivers/net/wireless/intel/ipw2x00/Kconfig b/drivers/net/wireless/intel/ipw2x00/Kconfig
index 1650d5865aa0..b92df91adb3a 100644
--- a/drivers/net/wireless/intel/ipw2x00/Kconfig
+++ b/drivers/net/wireless/intel/ipw2x00/Kconfig
@@ -7,10 +7,8 @@ config IPW2100
tristate "Intel PRO/Wireless 2100 Network Connection"
depends on PCI && CFG80211
select WIRELESS_EXT
- select WEXT_SPY
select WEXT_PRIV
select FW_LOADER
- select LIB80211
select LIBIPW
help
A driver for the Intel PRO/Wireless 2100 Network
@@ -67,12 +65,9 @@ config IPW2100_DEBUG
config IPW2200
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
depends on PCI && CFG80211
- select CFG80211_WEXT_EXPORT
select WIRELESS_EXT
- select WEXT_SPY
select WEXT_PRIV
select FW_LOADER
- select LIB80211
select LIBIPW
help
A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
@@ -158,14 +153,10 @@ config LIBIPW
tristate
depends on PCI && CFG80211
select WIRELESS_EXT
- select WEXT_SPY
select CRYPTO
select CRYPTO_MICHAEL_MIC
+ select CRYPTO_LIB_ARC4
select CRC32
- select LIB80211
- select LIB80211_CRYPT_WEP
- select LIB80211_CRYPT_TKIP
- select LIB80211_CRYPT_CCMP
help
This option enables the hardware independent IEEE 802.11
networking stack. This component is deprecated in favor of the
diff --git a/drivers/net/wireless/intel/ipw2x00/Makefile b/drivers/net/wireless/intel/ipw2x00/Makefile
index e1ec50359dff..91e6091c4ebf 100644
--- a/drivers/net/wireless/intel/ipw2x00/Makefile
+++ b/drivers/net/wireless/intel/ipw2x00/Makefile
@@ -12,4 +12,9 @@ libipw-objs := \
libipw_tx.o \
libipw_rx.o \
libipw_wx.o \
- libipw_geo.o
+ libipw_geo.o \
+ libipw_spy.o \
+ libipw_crypto.o \
+ libipw_crypto_ccmp.o \
+ libipw_crypto_tkip.o \
+ libipw_crypto_wep.o
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index fe75941c584d..215814861cbd 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -148,9 +148,6 @@ that only one external action is invoked at a time.
#include <linux/acpi.h>
#include <linux/ctype.h>
#include <linux/pm_qos.h>
-
-#include <net/lib80211.h>
-
#include "ipw2100.h"
#include "ipw.h"
@@ -6025,8 +6022,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
dev->netdev_ops = &ipw2100_netdev_ops;
dev->ethtool_ops = &ipw2100_ethtool_ops;
dev->wireless_handlers = &ipw2100_wx_handler_def;
- priv->wireless_data.libipw = priv->ieee;
- dev->wireless_data = &priv->wireless_data;
dev->watchdog_timeo = 3 * HZ;
dev->irq = 0;
dev->min_mtu = 68;
@@ -7571,7 +7566,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev,
struct ipw2100_priv *priv = libipw_priv(dev);
struct libipw_device *ieee = priv->ieee;
struct iw_param *param = &wrqu->param;
- struct lib80211_crypt_data *crypt;
+ struct libipw_crypt_data *crypt;
unsigned long flags;
int ret = 0;
@@ -7663,7 +7658,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
{
struct ipw2100_priv *priv = libipw_priv(dev);
struct libipw_device *ieee = priv->ieee;
- struct lib80211_crypt_data *crypt;
+ struct libipw_crypt_data *crypt;
struct iw_param *param = &wrqu->param;
switch (param->flags & IW_AUTH_INDEX) {
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.h b/drivers/net/wireless/intel/ipw2x00/ipw2100.h
index b34085ade3aa..6f81f509b9cb 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.h
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.h
@@ -554,8 +554,6 @@ struct ipw2100_priv {
struct net_device *net_dev;
struct iw_statistics wstats;
- struct iw_public_data wireless_data;
-
struct tasklet_struct irq_tasklet;
struct delayed_work reset_work;
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index eed9ef17bc29..be1d971b3d32 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -6463,6 +6463,14 @@ static int ipw_set_rsn_capa(struct ipw_priv *priv,
* WE-18 support
*/
+static int ipw_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ strcpy(wrqu->name, "IEEE 802.11");
+ return 0;
+}
+
/* SIOCSIWGENIE */
static int ipw_wx_set_genie(struct net_device *dev,
struct iw_request_info *info,
@@ -6549,7 +6557,7 @@ static int ipw_wx_set_auth(struct net_device *dev,
struct ipw_priv *priv = libipw_priv(dev);
struct libipw_device *ieee = priv->ieee;
struct iw_param *param = &wrqu->param;
- struct lib80211_crypt_data *crypt;
+ struct libipw_crypt_data *crypt;
unsigned long flags;
int ret = 0;
@@ -6648,7 +6656,7 @@ static int ipw_wx_get_auth(struct net_device *dev,
{
struct ipw_priv *priv = libipw_priv(dev);
struct libipw_device *ieee = priv->ieee;
- struct lib80211_crypt_data *crypt;
+ struct libipw_crypt_data *crypt;
struct iw_param *param = &wrqu->param;
switch (param->flags & IW_AUTH_INDEX) {
@@ -9826,7 +9834,7 @@ static int ipw_wx_sw_reset(struct net_device *dev,
/* Rebase the WE IOCTLs to zero for the handler array */
static iw_handler ipw_wx_handlers[] = {
- IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname),
+ IW_HANDLER(SIOCGIWNAME, ipw_wx_get_name),
IW_HANDLER(SIOCSIWFREQ, ipw_wx_set_freq),
IW_HANDLER(SIOCGIWFREQ, ipw_wx_get_freq),
IW_HANDLER(SIOCSIWMODE, ipw_wx_set_mode),
@@ -9856,10 +9864,10 @@ static iw_handler ipw_wx_handlers[] = {
IW_HANDLER(SIOCGIWENCODE, ipw_wx_get_encode),
IW_HANDLER(SIOCSIWPOWER, ipw_wx_set_power),
IW_HANDLER(SIOCGIWPOWER, ipw_wx_get_power),
- IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
- IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
- IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
- IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
+ IW_HANDLER(SIOCSIWSPY, ipw_wx_set_spy),
+ IW_HANDLER(SIOCGIWSPY, ipw_wx_get_spy),
+ IW_HANDLER(SIOCSIWTHRSPY, ipw_wx_set_thrspy),
+ IW_HANDLER(SIOCGIWTHRSPY, ipw_wx_get_thrspy),
IW_HANDLER(SIOCSIWGENIE, ipw_wx_set_genie),
IW_HANDLER(SIOCGIWGENIE, ipw_wx_get_genie),
IW_HANDLER(SIOCSIWMLME, ipw_wx_set_mlme),
@@ -11636,8 +11644,7 @@ static int ipw_pci_probe(struct pci_dev *pdev,
priv->ieee->worst_rssi = -85;
net_dev->netdev_ops = &ipw_netdev_ops;
- priv->wireless_data.spy_data = &priv->ieee->spy_data;
- net_dev->wireless_data = &priv->wireless_data;
+ priv->ieee->spy_enabled = true;
net_dev->wireless_handlers = &ipw_wx_handler_def;
net_dev->ethtool_ops = &ipw_ethtool_ops;
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.h b/drivers/net/wireless/intel/ipw2x00/ipw2200.h
index 226286cb7eb8..19310fd0d8eb 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.h
@@ -31,8 +31,6 @@
#include <linux/wireless.h>
#include <linux/jiffies.h>
#include <asm/io.h>
-
-#include <net/lib80211.h>
#include <net/ieee80211_radiotap.h>
#define DRV_NAME "ipw2200"
@@ -1276,8 +1274,6 @@ struct ipw_priv {
struct iw_statistics wstats;
- struct iw_public_data wireless_data;
-
int user_requested_scan;
u8 direct_scan_ssid[IW_ESSID_MAX_SIZE];
u8 direct_scan_ssid_len;
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw.h b/drivers/net/wireless/intel/ipw2x00/libipw.h
index bad080d33c07..3c20353e5a41 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw.h
+++ b/drivers/net/wireless/intel/ipw2x00/libipw.h
@@ -25,8 +25,6 @@
#include <linux/kernel.h> /* ARRAY_SIZE */
#include <linux/wireless.h>
#include <linux/ieee80211.h>
-
-#include <net/lib80211.h>
#include <net/cfg80211.h>
#define LIBIPW_VERSION "git-1.1.13"
@@ -699,6 +697,76 @@ struct libipw_geo {
struct libipw_channel a[LIBIPW_52GHZ_CHANNELS];
};
+#define NUM_WEP_KEYS 4
+
+enum {
+ IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
+};
+
+struct module;
+
+struct libipw_crypto_ops {
+ const char *name;
+ struct list_head list;
+
+ /* init new crypto context (e.g., allocate private data space,
+ * select IV, etc.); returns NULL on failure or pointer to allocated
+ * private data on success */
+ void *(*init) (int keyidx);
+
+ /* deinitialize crypto context and free allocated private data */
+ void (*deinit) (void *priv);
+
+ /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
+ * value from decrypt_mpdu is passed as the keyidx value for
+ * decrypt_msdu. skb must have enough head and tail room for the
+ * encryption; if not, error will be returned; these functions are
+ * called for all MPDUs (i.e., fragments).
+ */
+ int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
+ int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
+
+ /* These functions are called for full MSDUs, i.e. full frames.
+ * These can be NULL if full MSDU operations are not needed. */
+ int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv);
+ int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len,
+ void *priv);
+
+ int (*set_key) (void *key, int len, u8 * seq, void *priv);
+ int (*get_key) (void *key, int len, u8 * seq, void *priv);
+
+ /* procfs handler for printing out key information and possible
+ * statistics */
+ void (*print_stats) (struct seq_file *m, void *priv);
+
+ /* Crypto specific flag get/set for configuration settings */
+ unsigned long (*get_flags) (void *priv);
+ unsigned long (*set_flags) (unsigned long flags, void *priv);
+
+ /* maximum number of bytes added by encryption; encrypt buf is
+ * allocated with extra_prefix_len bytes, copy of in_buf, and
+ * extra_postfix_len; encrypt need not use all this space, but
+ * the result must start at the beginning of the buffer and correct
+ * length must be returned */
+ int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
+ int extra_msdu_prefix_len, extra_msdu_postfix_len;
+
+ struct module *owner;
+};
+
+struct libipw_crypt_info {
+ char *name;
+ /* Most clients will already have a lock,
+ so just point to that. */
+ spinlock_t *lock;
+
+ struct libipw_crypt_data *crypt[NUM_WEP_KEYS];
+ int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+ struct list_head crypt_deinit_list;
+ struct timer_list crypt_deinit_timer;
+ int crypt_quiesced;
+};
+
struct libipw_device {
struct net_device *dev;
struct wireless_dev wdev;
@@ -720,6 +788,7 @@ struct libipw_device {
int iw_mode; /* operating mode (IW_MODE_*) */
struct iw_spy_data spy_data; /* iwspy support */
+ bool spy_enabled;
spinlock_t lock;
@@ -751,7 +820,7 @@ struct libipw_device {
size_t wpa_ie_len;
u8 *wpa_ie;
- struct lib80211_crypt_info crypt_info;
+ struct libipw_crypt_info crypt_info;
int bcrx_sta_key; /* use individual keys to override default keys even
* with RX of broad/multicast frames */
@@ -988,4 +1057,43 @@ static inline int libipw_get_scans(struct libipw_device *ieee)
return ieee->scans;
}
+struct libipw_crypt_data {
+ struct list_head list; /* delayed deletion list */
+ const struct libipw_crypto_ops *ops;
+ void *priv;
+ atomic_t refcnt;
+};
+
+int libipw_crypt_info_init(struct libipw_crypt_info *info, char *name,
+ spinlock_t *lock);
+void libipw_crypt_info_free(struct libipw_crypt_info *info);
+int libipw_register_crypto_ops(const struct libipw_crypto_ops *ops);
+int libipw_unregister_crypto_ops(const struct libipw_crypto_ops *ops);
+const struct libipw_crypto_ops *libipw_get_crypto_ops(const char *name);
+void libipw_crypt_delayed_deinit(struct libipw_crypt_info *info,
+ struct libipw_crypt_data **crypt);
+
+/* must be called in the listed order */
+int libipw_crypto_init(void);
+int libipw_crypto_ccmp_init(void);
+int libipw_crypto_tkip_init(void);
+int libipw_crypto_wep_init(void);
+
+void libipw_crypto_wep_exit(void);
+void libipw_crypto_tkip_exit(void);
+void libipw_crypto_ccmp_exit(void);
+void libipw_crypto_exit(void);
+
+
+int ipw_wx_set_spy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int ipw_wx_get_spy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int ipw_wx_set_thrspy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int ipw_wx_get_thrspy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+void libipw_spy_update(struct net_device *dev, unsigned char *address,
+ struct iw_quality *wstats);
+
#endif /* LIBIPW_H */
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c
new file mode 100644
index 000000000000..32639e0e8430
--- /dev/null
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * libipw -- common bits for IPW drivers
+ *
+ * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com>
+ *
+ * Portions copied from old ieee80211 component, w/ original copyright
+ * notices below:
+ *
+ * Host AP crypto routines
+ *
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
+ * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/ieee80211.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "libipw.h"
+
+struct libipw_crypto_alg {
+ struct list_head list;
+ const struct libipw_crypto_ops *ops;
+};
+
+static LIST_HEAD(libipw_crypto_algs);
+static DEFINE_SPINLOCK(libipw_crypto_lock);
+
+static void libipw_crypt_deinit_entries(struct libipw_crypt_info *info,
+ int force);
+static void libipw_crypt_quiescing(struct libipw_crypt_info *info);
+static void libipw_crypt_deinit_handler(struct timer_list *t);
+
+int libipw_crypt_info_init(struct libipw_crypt_info *info, char *name,
+ spinlock_t *lock)
+{
+ memset(info, 0, sizeof(*info));
+
+ info->name = name;
+ info->lock = lock;
+
+ INIT_LIST_HEAD(&info->crypt_deinit_list);
+ timer_setup(&info->crypt_deinit_timer, libipw_crypt_deinit_handler,
+ 0);
+
+ return 0;
+}
+EXPORT_SYMBOL(libipw_crypt_info_init);
+
+void libipw_crypt_info_free(struct libipw_crypt_info *info)
+{
+ int i;
+
+ libipw_crypt_quiescing(info);
+ del_timer_sync(&info->crypt_deinit_timer);
+ libipw_crypt_deinit_entries(info, 1);
+
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ struct libipw_crypt_data *crypt = info->crypt[i];
+ if (crypt) {
+ if (crypt->ops) {
+ crypt->ops->deinit(crypt->priv);
+ module_put(crypt->ops->owner);
+ }
+ kfree(crypt);
+ info->crypt[i] = NULL;
+ }
+ }
+}
+EXPORT_SYMBOL(libipw_crypt_info_free);
+
+static void libipw_crypt_deinit_entries(struct libipw_crypt_info *info,
+ int force)
+{
+ struct libipw_crypt_data *entry, *next;
+ unsigned long flags;
+
+ spin_lock_irqsave(info->lock, flags);
+ list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) {
+ if (atomic_read(&entry->refcnt) != 0 && !force)
+ continue;
+
+ list_del(&entry->list);
+
+ if (entry->ops) {
+ entry->ops->deinit(entry->priv);
+ module_put(entry->ops->owner);
+ }
+ kfree(entry);
+ }
+ spin_unlock_irqrestore(info->lock, flags);
+}
+
+/* After this, crypt_deinit_list won't accept new members */
+static void libipw_crypt_quiescing(struct libipw_crypt_info *info)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(info->lock, flags);
+ info->crypt_quiesced = 1;
+ spin_unlock_irqrestore(info->lock, flags);
+}
+
+static void libipw_crypt_deinit_handler(struct timer_list *t)
+{
+ struct libipw_crypt_info *info = from_timer(info, t,
+ crypt_deinit_timer);
+ unsigned long flags;
+
+ libipw_crypt_deinit_entries(info, 0);
+
+ spin_lock_irqsave(info->lock, flags);
+ if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) {
+ printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
+ "deletion list\n", info->name);
+ info->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&info->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(info->lock, flags);
+}
+
+void libipw_crypt_delayed_deinit(struct libipw_crypt_info *info,
+ struct libipw_crypt_data **crypt)
+{
+ struct libipw_crypt_data *tmp;
+ unsigned long flags;
+
+ if (*crypt == NULL)
+ return;
+
+ tmp = *crypt;
+ *crypt = NULL;
+
+ /* must not run ops->deinit() while there may be pending encrypt or
+ * decrypt operations. Use a list of delayed deinits to avoid needing
+ * locking. */
+
+ spin_lock_irqsave(info->lock, flags);
+ if (!info->crypt_quiesced) {
+ list_add(&tmp->list, &info->crypt_deinit_list);
+ if (!timer_pending(&info->crypt_deinit_timer)) {
+ info->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&info->crypt_deinit_timer);
+ }
+ }
+ spin_unlock_irqrestore(info->lock, flags);
+}
+EXPORT_SYMBOL(libipw_crypt_delayed_deinit);
+
+int libipw_register_crypto_ops(const struct libipw_crypto_ops *ops)
+{
+ unsigned long flags;
+ struct libipw_crypto_alg *alg;
+
+ alg = kzalloc(sizeof(*alg), GFP_KERNEL);
+ if (alg == NULL)
+ return -ENOMEM;
+
+ alg->ops = ops;
+
+ spin_lock_irqsave(&libipw_crypto_lock, flags);
+ list_add(&alg->list, &libipw_crypto_algs);
+ spin_unlock_irqrestore(&libipw_crypto_lock, flags);
+
+ printk(KERN_DEBUG "libipw_crypt: registered algorithm '%s'\n",
+ ops->name);
+
+ return 0;
+}
+EXPORT_SYMBOL(libipw_register_crypto_ops);
+
+int libipw_unregister_crypto_ops(const struct libipw_crypto_ops *ops)
+{
+ struct libipw_crypto_alg *alg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&libipw_crypto_lock, flags);
+ list_for_each_entry(alg, &libipw_crypto_algs, list) {
+ if (alg->ops == ops)
+ goto found;
+ }
+ spin_unlock_irqrestore(&libipw_crypto_lock, flags);
+ return -EINVAL;
+
+ found:
+ printk(KERN_DEBUG "libipw_crypt: unregistered algorithm '%s'\n",
+ ops->name);
+ list_del(&alg->list);
+ spin_unlock_irqrestore(&libipw_crypto_lock, flags);
+ kfree(alg);
+ return 0;
+}
+EXPORT_SYMBOL(libipw_unregister_crypto_ops);
+
+const struct libipw_crypto_ops *libipw_get_crypto_ops(const char *name)
+{
+ struct libipw_crypto_alg *alg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&libipw_crypto_lock, flags);
+ list_for_each_entry(alg, &libipw_crypto_algs, list) {
+ if (strcmp(alg->ops->name, name) == 0)
+ goto found;
+ }
+ spin_unlock_irqrestore(&libipw_crypto_lock, flags);
+ return NULL;
+
+ found:
+ spin_unlock_irqrestore(&libipw_crypto_lock, flags);
+ return alg->ops;
+}
+EXPORT_SYMBOL(libipw_get_crypto_ops);
+
+static void *libipw_crypt_null_init(int keyidx)
+{
+ return (void *)1;
+}
+
+static void libipw_crypt_null_deinit(void *priv)
+{
+}
+
+static const struct libipw_crypto_ops libipw_crypt_null = {
+ .name = "NULL",
+ .init = libipw_crypt_null_init,
+ .deinit = libipw_crypt_null_deinit,
+ .owner = THIS_MODULE,
+};
+
+int __init libipw_crypto_init(void)
+{
+ return libipw_register_crypto_ops(&libipw_crypt_null);
+}
+
+void libipw_crypto_exit(void)
+{
+ libipw_unregister_crypto_ops(&libipw_crypt_null);
+ BUG_ON(!list_empty(&libipw_crypto_algs));
+}
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c
index 5aad139130e1..bf900d8c8ad3 100644
--- a/net/wireless/lib80211_crypt_ccmp.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * lib80211 crypt: host-based CCMP encryption implementation for lib80211
+ * libipw crypt: host-based CCMP encryption implementation for libipw
*
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
@@ -18,17 +18,10 @@
#include <linux/if_arp.h>
#include <asm/string.h>
#include <linux/wireless.h>
-
#include <linux/ieee80211.h>
-
#include <linux/crypto.h>
#include <crypto/aead.h>
-
-#include <net/lib80211.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("Host AP crypt: CCMP");
-MODULE_LICENSE("GPL");
+#include "libipw.h"
#define AES_BLOCK_LEN 16
#define CCMP_HDR_LEN 8
@@ -36,7 +29,7 @@ MODULE_LICENSE("GPL");
#define CCMP_TK_LEN 16
#define CCMP_PN_LEN 6
-struct lib80211_ccmp_data {
+struct libipw_ccmp_data {
u8 key[CCMP_TK_LEN];
int key_set;
@@ -56,9 +49,9 @@ struct lib80211_ccmp_data {
u8 rx_aad[2 * AES_BLOCK_LEN];
};
-static void *lib80211_ccmp_init(int key_idx)
+static void *libipw_ccmp_init(int key_idx)
{
- struct lib80211_ccmp_data *priv;
+ struct libipw_ccmp_data *priv;
priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
@@ -83,9 +76,9 @@ static void *lib80211_ccmp_init(int key_idx)
return NULL;
}
-static void lib80211_ccmp_deinit(void *priv)
+static void libipw_ccmp_deinit(void *priv)
{
- struct lib80211_ccmp_data *_priv = priv;
+ struct libipw_ccmp_data *_priv = priv;
if (_priv && _priv->tfm)
crypto_free_aead(_priv->tfm);
kfree(priv);
@@ -150,10 +143,10 @@ static int ccmp_init_iv_and_aad(const struct ieee80211_hdr *hdr,
return aad_len;
}
-static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
+static int libipw_ccmp_hdr(struct sk_buff *skb, int hdr_len,
u8 *aeskey, int keylen, void *priv)
{
- struct lib80211_ccmp_data *key = priv;
+ struct libipw_ccmp_data *key = priv;
int i;
u8 *pos;
@@ -187,9 +180,9 @@ static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
return CCMP_HDR_LEN;
}
-static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int libipw_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
- struct lib80211_ccmp_data *key = priv;
+ struct libipw_ccmp_data *key = priv;
struct ieee80211_hdr *hdr;
struct aead_request *req;
struct scatterlist sg[2];
@@ -202,7 +195,7 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
return -1;
data_len = skb->len - hdr_len;
- len = lib80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
+ len = libipw_ccmp_hdr(skb, hdr_len, NULL, 0, priv);
if (len < 0)
return -1;
@@ -251,9 +244,9 @@ static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o)
return 0;
}
-static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int libipw_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
- struct lib80211_ccmp_data *key = priv;
+ struct libipw_ccmp_data *key = priv;
u8 keyidx, *pos;
struct ieee80211_hdr *hdr;
struct aead_request *req;
@@ -299,7 +292,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
pos += 8;
if (ccmp_replay_check(pn, key->rx_pn)) {
-#ifdef CONFIG_LIB80211_DEBUG
+#ifdef CONFIG_LIBIPW_DEBUG
net_dbg_ratelimited("CCMP: replay detected: STA=%pM previous PN %02x%02x%02x%02x%02x%02x received PN %02x%02x%02x%02x%02x%02x\n",
hdr->addr2,
key->rx_pn[0], key->rx_pn[1], key->rx_pn[2],
@@ -344,9 +337,9 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
return keyidx;
}
-static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
+static int libipw_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
{
- struct lib80211_ccmp_data *data = priv;
+ struct libipw_ccmp_data *data = priv;
int keyidx;
struct crypto_aead *tfm = data->tfm;
@@ -376,9 +369,9 @@ static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
return 0;
}
-static int lib80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
+static int libipw_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
{
- struct lib80211_ccmp_data *data = priv;
+ struct libipw_ccmp_data *data = priv;
if (len < CCMP_TK_LEN)
return -1;
@@ -399,9 +392,9 @@ static int lib80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv)
return CCMP_TK_LEN;
}
-static void lib80211_ccmp_print_stats(struct seq_file *m, void *priv)
+static void libipw_ccmp_print_stats(struct seq_file *m, void *priv)
{
- struct lib80211_ccmp_data *ccmp = priv;
+ struct libipw_ccmp_data *ccmp = priv;
seq_printf(m,
"key[%d] alg=CCMP key_set=%d "
@@ -418,31 +411,28 @@ static void lib80211_ccmp_print_stats(struct seq_file *m, void *priv)
ccmp->dot11RSNAStatsCCMPDecryptErrors);
}
-static const struct lib80211_crypto_ops lib80211_crypt_ccmp = {
+static const struct libipw_crypto_ops libipw_crypt_ccmp = {
.name = "CCMP",
- .init = lib80211_ccmp_init,
- .deinit = lib80211_ccmp_deinit,
- .encrypt_mpdu = lib80211_ccmp_encrypt,
- .decrypt_mpdu = lib80211_ccmp_decrypt,
+ .init = libipw_ccmp_init,
+ .deinit = libipw_ccmp_deinit,
+ .encrypt_mpdu = libipw_ccmp_encrypt,
+ .decrypt_mpdu = libipw_ccmp_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
- .set_key = lib80211_ccmp_set_key,
- .get_key = lib80211_ccmp_get_key,
- .print_stats = lib80211_ccmp_print_stats,
+ .set_key = libipw_ccmp_set_key,
+ .get_key = libipw_ccmp_get_key,
+ .print_stats = libipw_ccmp_print_stats,
.extra_mpdu_prefix_len = CCMP_HDR_LEN,
.extra_mpdu_postfix_len = CCMP_MIC_LEN,
.owner = THIS_MODULE,
};
-static int __init lib80211_crypto_ccmp_init(void)
+int __init libipw_crypto_ccmp_init(void)
{
- return lib80211_register_crypto_ops(&lib80211_crypt_ccmp);
+ return libipw_register_crypto_ops(&libipw_crypt_ccmp);
}
-static void __exit lib80211_crypto_ccmp_exit(void)
+void libipw_crypto_ccmp_exit(void)
{
- lib80211_unregister_crypto_ops(&lib80211_crypt_ccmp);
+ libipw_unregister_crypto_ops(&libipw_crypt_ccmp);
}
-
-module_init(lib80211_crypto_ccmp_init);
-module_exit(lib80211_crypto_ccmp_exit);
diff --git a/net/wireless/lib80211_crypt_tkip.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
index 63e68e5e121e..32288697da4f 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * lib80211 crypt: host-based TKIP encryption implementation for lib80211
+ * libipw crypt: host-based TKIP encryption implementation for libipw
*
* Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
@@ -21,25 +21,18 @@
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <asm/string.h>
-
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/iw_handler.h>
-
#include <crypto/arc4.h>
#include <crypto/hash.h>
#include <linux/crypto.h>
#include <linux/crc32.h>
-
-#include <net/lib80211.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("lib80211 crypt: TKIP");
-MODULE_LICENSE("GPL");
+#include "libipw.h"
#define TKIP_HDR_LEN 8
-struct lib80211_tkip_data {
+struct libipw_tkip_data {
#define TKIP_KEY_LEN 32
u8 key[TKIP_KEY_LEN];
int key_set;
@@ -73,23 +66,23 @@ struct lib80211_tkip_data {
unsigned long flags;
};
-static unsigned long lib80211_tkip_set_flags(unsigned long flags, void *priv)
+static unsigned long libipw_tkip_set_flags(unsigned long flags, void *priv)
{
- struct lib80211_tkip_data *_priv = priv;
+ struct libipw_tkip_data *_priv = priv;
unsigned long old_flags = _priv->flags;
_priv->flags = flags;
return old_flags;
}
-static unsigned long lib80211_tkip_get_flags(void *priv)
+static unsigned long libipw_tkip_get_flags(void *priv)
{
- struct lib80211_tkip_data *_priv = priv;
+ struct libipw_tkip_data *_priv = priv;
return _priv->flags;
}
-static void *lib80211_tkip_init(int key_idx)
+static void *libipw_tkip_init(int key_idx)
{
- struct lib80211_tkip_data *priv;
+ struct libipw_tkip_data *priv;
if (fips_enabled)
return NULL;
@@ -124,9 +117,9 @@ static void *lib80211_tkip_init(int key_idx)
return NULL;
}
-static void lib80211_tkip_deinit(void *priv)
+static void libipw_tkip_deinit(void *priv)
{
- struct lib80211_tkip_data *_priv = priv;
+ struct libipw_tkip_data *_priv = priv;
if (_priv) {
crypto_free_shash(_priv->tx_tfm_michael);
crypto_free_shash(_priv->rx_tfm_michael);
@@ -280,10 +273,10 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK,
#endif
}
-static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
+static int libipw_tkip_hdr(struct sk_buff *skb, int hdr_len,
u8 * rc4key, int keylen, void *priv)
{
- struct lib80211_tkip_data *tkey = priv;
+ struct libipw_tkip_data *tkey = priv;
u8 *pos;
struct ieee80211_hdr *hdr;
@@ -324,9 +317,9 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len,
return TKIP_HDR_LEN;
}
-static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int libipw_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
- struct lib80211_tkip_data *tkey = priv;
+ struct libipw_tkip_data *tkey = priv;
int len;
u8 rc4key[16], *pos, *icv;
u32 crc;
@@ -344,7 +337,7 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
len = skb->len - hdr_len;
pos = skb->data + hdr_len;
- if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
+ if ((libipw_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0)
return -1;
crc = ~crc32_le(~0, pos, len);
@@ -373,9 +366,9 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
return 0;
}
-static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int libipw_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
- struct lib80211_tkip_data *tkey = priv;
+ struct libipw_tkip_data *tkey = priv;
u8 rc4key[16];
u8 keyidx, *pos;
u32 iv32;
@@ -419,7 +412,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
pos += TKIP_HDR_LEN;
if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
-#ifdef CONFIG_LIB80211_DEBUG
+#ifdef CONFIG_LIBIPW_DEBUG
net_dbg_ratelimited("TKIP: replay detected: STA=%pM previous TSC %08x%04x received TSC %08x%04x\n",
hdr->addr2, tkey->rx_iv32, tkey->rx_iv16,
iv32, iv16);
@@ -450,7 +443,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
* it needs to be recalculated for the next packet. */
tkey->rx_phase1_done = 0;
}
-#ifdef CONFIG_LIB80211_DEBUG
+#ifdef CONFIG_LIBIPW_DEBUG
net_dbg_ratelimited("TKIP: ICV error detected: STA=%pM\n",
hdr->addr2);
#endif
@@ -538,10 +531,10 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
}
-static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
+static int libipw_michael_mic_add(struct sk_buff *skb, int hdr_len,
void *priv)
{
- struct lib80211_tkip_data *tkey = priv;
+ struct libipw_tkip_data *tkey = priv;
u8 *pos;
if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
@@ -560,7 +553,7 @@ static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
return 0;
}
-static void lib80211_michael_mic_failure(struct net_device *dev,
+static void libipw_michael_mic_failure(struct net_device *dev,
struct ieee80211_hdr *hdr,
int keyidx)
{
@@ -581,10 +574,10 @@ static void lib80211_michael_mic_failure(struct net_device *dev,
wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
}
-static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
+static int libipw_michael_mic_verify(struct sk_buff *skb, int keyidx,
int hdr_len, void *priv)
{
- struct lib80211_tkip_data *tkey = priv;
+ struct libipw_tkip_data *tkey = priv;
u8 mic[8];
if (!tkey->key_set)
@@ -602,7 +595,7 @@ static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
skb->dev ? skb->dev->name : "N/A", hdr->addr2,
keyidx);
if (skb->dev)
- lib80211_michael_mic_failure(skb->dev, hdr, keyidx);
+ libipw_michael_mic_failure(skb->dev, hdr, keyidx);
tkey->dot11RSNAStatsTKIPLocalMICFailures++;
return -1;
}
@@ -617,9 +610,9 @@ static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
return 0;
}
-static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
+static int libipw_tkip_set_key(void *key, int len, u8 * seq, void *priv)
{
- struct lib80211_tkip_data *tkey = priv;
+ struct libipw_tkip_data *tkey = priv;
int keyidx;
struct crypto_shash *tfm = tkey->tx_tfm_michael;
struct arc4_ctx *tfm2 = &tkey->tx_ctx_arc4;
@@ -650,9 +643,9 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
return 0;
}
-static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
+static int libipw_tkip_get_key(void *key, int len, u8 * seq, void *priv)
{
- struct lib80211_tkip_data *tkey = priv;
+ struct libipw_tkip_data *tkey = priv;
if (len < TKIP_KEY_LEN)
return -1;
@@ -679,9 +672,9 @@ static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv)
return TKIP_KEY_LEN;
}
-static void lib80211_tkip_print_stats(struct seq_file *m, void *priv)
+static void libipw_tkip_print_stats(struct seq_file *m, void *priv)
{
- struct lib80211_tkip_data *tkip = priv;
+ struct libipw_tkip_data *tkip = priv;
seq_printf(m,
"key[%d] alg=TKIP key_set=%d "
"tx_pn=%02x%02x%02x%02x%02x%02x "
@@ -705,34 +698,31 @@ static void lib80211_tkip_print_stats(struct seq_file *m, void *priv)
tkip->dot11RSNAStatsTKIPLocalMICFailures);
}
-static const struct lib80211_crypto_ops lib80211_crypt_tkip = {
+static const struct libipw_crypto_ops libipw_crypt_tkip = {
.name = "TKIP",
- .init = lib80211_tkip_init,
- .deinit = lib80211_tkip_deinit,
- .encrypt_mpdu = lib80211_tkip_encrypt,
- .decrypt_mpdu = lib80211_tkip_decrypt,
- .encrypt_msdu = lib80211_michael_mic_add,
- .decrypt_msdu = lib80211_michael_mic_verify,
- .set_key = lib80211_tkip_set_key,
- .get_key = lib80211_tkip_get_key,
- .print_stats = lib80211_tkip_print_stats,
+ .init = libipw_tkip_init,
+ .deinit = libipw_tkip_deinit,
+ .encrypt_mpdu = libipw_tkip_encrypt,
+ .decrypt_mpdu = libipw_tkip_decrypt,
+ .encrypt_msdu = libipw_michael_mic_add,
+ .decrypt_msdu = libipw_michael_mic_verify,
+ .set_key = libipw_tkip_set_key,
+ .get_key = libipw_tkip_get_key,
+ .print_stats = libipw_tkip_print_stats,
.extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
.extra_mpdu_postfix_len = 4, /* ICV */
.extra_msdu_postfix_len = 8, /* MIC */
- .get_flags = lib80211_tkip_get_flags,
- .set_flags = lib80211_tkip_set_flags,
+ .get_flags = libipw_tkip_get_flags,
+ .set_flags = libipw_tkip_set_flags,
.owner = THIS_MODULE,
};
-static int __init lib80211_crypto_tkip_init(void)
+int __init libipw_crypto_tkip_init(void)
{
- return lib80211_register_crypto_ops(&lib80211_crypt_tkip);
+ return libipw_register_crypto_ops(&libipw_crypt_tkip);
}
-static void __exit lib80211_crypto_tkip_exit(void)
+void libipw_crypto_tkip_exit(void)
{
- lib80211_unregister_crypto_ops(&lib80211_crypt_tkip);
+ libipw_unregister_crypto_ops(&libipw_crypt_tkip);
}
-
-module_init(lib80211_crypto_tkip_init);
-module_exit(lib80211_crypto_tkip_exit);
diff --git a/net/wireless/lib80211_crypt_wep.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_wep.c
index 3b148c7bef85..c3a4ccb9de17 100644
--- a/net/wireless/lib80211_crypt_wep.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_wep.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * lib80211 crypt: host-based WEP encryption implementation for lib80211
+ * libipw crypt: host-based WEP encryption implementation for libipw
*
* Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
@@ -16,17 +16,11 @@
#include <linux/skbuff.h>
#include <linux/mm.h>
#include <asm/string.h>
-
-#include <net/lib80211.h>
-
#include <crypto/arc4.h>
#include <linux/crc32.h>
+#include "libipw.h"
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("lib80211 crypt: WEP");
-MODULE_LICENSE("GPL");
-
-struct lib80211_wep_data {
+struct libipw_wep_data {
u32 iv;
#define WEP_KEY_LEN 13
u8 key[WEP_KEY_LEN + 1];
@@ -36,9 +30,9 @@ struct lib80211_wep_data {
struct arc4_ctx rx_ctx;
};
-static void *lib80211_wep_init(int keyidx)
+static void *libipw_wep_init(int keyidx)
{
- struct lib80211_wep_data *priv;
+ struct libipw_wep_data *priv;
if (fips_enabled)
return NULL;
@@ -54,16 +48,16 @@ static void *lib80211_wep_init(int keyidx)
return priv;
}
-static void lib80211_wep_deinit(void *priv)
+static void libipw_wep_deinit(void *priv)
{
kfree_sensitive(priv);
}
/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
-static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len,
+static int libipw_wep_build_iv(struct sk_buff *skb, int hdr_len,
u8 *key, int keylen, void *priv)
{
- struct lib80211_wep_data *wep = priv;
+ struct libipw_wep_data *wep = priv;
u32 klen;
u8 *pos;
@@ -102,19 +96,19 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len,
*
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
*/
-static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int libipw_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
- struct lib80211_wep_data *wep = priv;
+ struct libipw_wep_data *wep = priv;
u32 crc, klen, len;
u8 *pos, *icv;
u8 key[WEP_KEY_LEN + 3];
- /* other checks are in lib80211_wep_build_iv */
+ /* other checks are in libipw_wep_build_iv */
if (skb_tailroom(skb) < 4)
return -1;
/* add the IV to the frame */
- if (lib80211_wep_build_iv(skb, hdr_len, NULL, 0, priv))
+ if (libipw_wep_build_iv(skb, hdr_len, NULL, 0, priv))
return -1;
/* Copy the IV into the first 3 bytes of the key */
@@ -148,9 +142,9 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
* Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
* failure. If frame is OK, IV and ICV will be removed.
*/
-static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int libipw_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
- struct lib80211_wep_data *wep = priv;
+ struct libipw_wep_data *wep = priv;
u32 crc, klen, plen;
u8 key[WEP_KEY_LEN + 3];
u8 keyidx, *pos, icv[4];
@@ -195,9 +189,9 @@ static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
return 0;
}
-static int lib80211_wep_set_key(void *key, int len, u8 * seq, void *priv)
+static int libipw_wep_set_key(void *key, int len, u8 * seq, void *priv)
{
- struct lib80211_wep_data *wep = priv;
+ struct libipw_wep_data *wep = priv;
if (len < 0 || len > WEP_KEY_LEN)
return -1;
@@ -208,9 +202,9 @@ static int lib80211_wep_set_key(void *key, int len, u8 * seq, void *priv)
return 0;
}
-static int lib80211_wep_get_key(void *key, int len, u8 * seq, void *priv)
+static int libipw_wep_get_key(void *key, int len, u8 * seq, void *priv)
{
- struct lib80211_wep_data *wep = priv;
+ struct libipw_wep_data *wep = priv;
if (len < wep->key_len)
return -1;
@@ -220,37 +214,34 @@ static int lib80211_wep_get_key(void *key, int len, u8 * seq, void *priv)
return wep->key_len;
}
-static void lib80211_wep_print_stats(struct seq_file *m, void *priv)
+static void libipw_wep_print_stats(struct seq_file *m, void *priv)
{
- struct lib80211_wep_data *wep = priv;
+ struct libipw_wep_data *wep = priv;
seq_printf(m, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
}
-static const struct lib80211_crypto_ops lib80211_crypt_wep = {
+static const struct libipw_crypto_ops libipw_crypt_wep = {
.name = "WEP",
- .init = lib80211_wep_init,
- .deinit = lib80211_wep_deinit,
- .encrypt_mpdu = lib80211_wep_encrypt,
- .decrypt_mpdu = lib80211_wep_decrypt,
+ .init = libipw_wep_init,
+ .deinit = libipw_wep_deinit,
+ .encrypt_mpdu = libipw_wep_encrypt,
+ .decrypt_mpdu = libipw_wep_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
- .set_key = lib80211_wep_set_key,
- .get_key = lib80211_wep_get_key,
- .print_stats = lib80211_wep_print_stats,
+ .set_key = libipw_wep_set_key,
+ .get_key = libipw_wep_get_key,
+ .print_stats = libipw_wep_print_stats,
.extra_mpdu_prefix_len = 4, /* IV */
.extra_mpdu_postfix_len = 4, /* ICV */
.owner = THIS_MODULE,
};
-static int __init lib80211_crypto_wep_init(void)
+int __init libipw_crypto_wep_init(void)
{
- return lib80211_register_crypto_ops(&lib80211_crypt_wep);
+ return libipw_register_crypto_ops(&libipw_crypt_wep);
}
-static void __exit lib80211_crypto_wep_exit(void)
+void __exit libipw_crypto_wep_exit(void)
{
- lib80211_unregister_crypto_ops(&lib80211_crypt_wep);
+ libipw_unregister_crypto_ops(&libipw_crypt_wep);
}
-
-module_init(lib80211_crypto_wep_init);
-module_exit(lib80211_crypto_wep_exit);
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_module.c b/drivers/net/wireless/intel/ipw2x00/libipw_module.c
index 43bab92a4148..0a16127bfd68 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_module.c
@@ -169,7 +169,7 @@ struct net_device *alloc_libipw(int sizeof_priv, int monitor)
spin_lock_init(&ieee->lock);
- lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
+ libipw_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
ieee->wpa_enabled = 0;
ieee->drop_unencrypted = 0;
@@ -191,7 +191,7 @@ void free_libipw(struct net_device *dev, int monitor)
{
struct libipw_device *ieee = netdev_priv(dev);
- lib80211_crypt_info_free(&ieee->crypt_info);
+ libipw_crypt_info_free(&ieee->crypt_info);
libipw_networks_free(ieee);
@@ -251,6 +251,7 @@ static const struct proc_ops debug_level_proc_ops = {
static int __init libipw_init(void)
{
+ int err;
#ifdef CONFIG_LIBIPW_DEBUG
struct proc_dir_entry *e;
@@ -273,7 +274,33 @@ static int __init libipw_init(void)
printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+ err = libipw_crypto_init();
+ if (err)
+ goto remove_debugfs;
+ err = libipw_crypto_ccmp_init();
+ if (err)
+ goto uninit_crypto;
+ err = libipw_crypto_tkip_init();
+ if (err)
+ goto uninit_crypto_ccmp;
+ err = libipw_crypto_wep_init();
+ if (err)
+ goto uninit_crypto_tkip;
+
return 0;
+uninit_crypto_tkip:
+ libipw_crypto_tkip_exit();
+uninit_crypto_ccmp:
+ libipw_crypto_ccmp_exit();
+uninit_crypto:
+ libipw_crypto_exit();
+remove_debugfs:
+#ifdef CONFIG_LIBIPW_DEBUG
+ remove_proc_entry("debug_level", libipw_proc);
+ remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
+ libipw_proc = NULL;
+#endif
+ return err;
}
static void __exit libipw_exit(void)
@@ -285,6 +312,11 @@ static void __exit libipw_exit(void)
libipw_proc = NULL;
}
#endif /* CONFIG_LIBIPW_DEBUG */
+
+ libipw_crypto_ccmp_exit();
+ libipw_crypto_tkip_exit();
+ libipw_crypto_wep_exit();
+ libipw_crypto_exit();
}
#ifdef CONFIG_LIBIPW_DEBUG
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
index 48d6870bbf4e..dc4e91f58bb4 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
@@ -27,9 +27,6 @@
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
#include <linux/ctype.h>
-
-#include <net/lib80211.h>
-
#include "libipw.h"
static void libipw_monitor_rx(struct libipw_device *ieee,
@@ -266,7 +263,7 @@ static int libipw_is_eapol_frame(struct libipw_device *ieee,
/* Called only as a tasklet (software IRQ), by libipw_rx */
static int
libipw_rx_frame_decrypt(struct libipw_device *ieee, struct sk_buff *skb,
- struct lib80211_crypt_data *crypt)
+ struct libipw_crypt_data *crypt)
{
struct libipw_hdr_3addr *hdr;
int res, hdrlen;
@@ -298,7 +295,7 @@ libipw_rx_frame_decrypt(struct libipw_device *ieee, struct sk_buff *skb,
static int
libipw_rx_frame_decrypt_msdu(struct libipw_device *ieee,
struct sk_buff *skb, int keyidx,
- struct lib80211_crypt_data *crypt)
+ struct libipw_crypt_data *crypt)
{
struct libipw_hdr_3addr *hdr;
int res, hdrlen;
@@ -345,7 +342,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
#endif
u8 dst[ETH_ALEN];
u8 src[ETH_ALEN];
- struct lib80211_crypt_data *crypt = NULL;
+ struct libipw_crypt_data *crypt = NULL;
int keyidx = 0;
int can_be_decrypted = 0;
@@ -396,7 +393,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
wstats.updated |= IW_QUAL_QUAL_INVALID;
/* Update spy records */
- wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
+ libipw_spy_update(ieee->dev, hdr->addr2, &wstats);
}
#endif /* IW_WIRELESS_SPY */
#endif /* CONFIG_WIRELESS_EXT */
@@ -870,8 +867,8 @@ void libipw_rx_any(struct libipw_device *ieee,
switch (ieee->iw_mode) {
case IW_MODE_ADHOC:
/* our BSS and not from/to DS */
- if (ether_addr_equal(hdr->addr3, ieee->bssid))
- if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
+ if (ether_addr_equal(hdr->addr3, ieee->bssid) &&
+ ((fc & (IEEE80211_FCTL_TODS + IEEE80211_FCTL_FROMDS)) == 0)) {
/* promisc: get all */
if (ieee->dev->flags & IFF_PROMISC)
is_packet_for_us = 1;
@@ -885,8 +882,8 @@ void libipw_rx_any(struct libipw_device *ieee,
break;
case IW_MODE_INFRA:
/* our BSS (== from our AP) and from DS */
- if (ether_addr_equal(hdr->addr2, ieee->bssid))
- if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
+ if (ether_addr_equal(hdr->addr2, ieee->bssid) &&
+ ((fc & (IEEE80211_FCTL_TODS + IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS)) {
/* promisc: get all */
if (ieee->dev->flags & IFF_PROMISC)
is_packet_for_us = 1;
diff --git a/net/wireless/wext-spy.c b/drivers/net/wireless/intel/ipw2x00/libipw_spy.c
index b379a0371653..ba876e92f7f6 100644
--- a/net/wireless/wext-spy.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_spy.c
@@ -14,19 +14,21 @@
#include <net/iw_handler.h>
#include <net/arp.h>
#include <net/wext.h>
+#include "libipw.h"
-static inline struct iw_spy_data *get_spydata(struct net_device *dev)
+static struct iw_spy_data *get_spydata(struct net_device *dev)
{
- /* This is the new way */
- if (dev->wireless_data)
- return dev->wireless_data->spy_data;
+ struct libipw_device *ieee = netdev_priv(dev);
+
+ if (ieee->spy_enabled)
+ return &ieee->spy_data;
return NULL;
}
-int iw_handler_set_spy(struct net_device * dev,
- struct iw_request_info * info,
- union iwreq_data * wrqu,
- char * extra)
+int ipw_wx_set_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra)
{
struct iw_spy_data * spydata = get_spydata(dev);
struct sockaddr * address = (struct sockaddr *) extra;
@@ -36,15 +38,15 @@ int iw_handler_set_spy(struct net_device * dev,
return -EOPNOTSUPP;
/* Disable spy collection while we copy the addresses.
- * While we copy addresses, any call to wireless_spy_update()
+ * While we copy addresses, any call to libipw_spy_update()
* will NOP. This is OK, as anyway the addresses are changing. */
spydata->spy_number = 0;
- /* We want to operate without locking, because wireless_spy_update()
+ /* We want to operate without locking, because libipw_spy_update()
* most likely will happen in the interrupt handler, and therefore
* have its own locking constraints and needs performance.
* The rtnl_lock() make sure we don't race with the other iw_handlers.
- * This make sure wireless_spy_update() "see" that the spy list
+ * This make sure libipw_spy_update() "see" that the spy list
* is temporarily disabled. */
smp_wmb();
@@ -69,12 +71,12 @@ int iw_handler_set_spy(struct net_device * dev,
return 0;
}
-EXPORT_SYMBOL(iw_handler_set_spy);
+EXPORT_SYMBOL(ipw_wx_set_spy);
-int iw_handler_get_spy(struct net_device * dev,
- struct iw_request_info * info,
- union iwreq_data * wrqu,
- char * extra)
+int ipw_wx_get_spy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra)
{
struct iw_spy_data * spydata = get_spydata(dev);
struct sockaddr * address = (struct sockaddr *) extra;
@@ -101,16 +103,16 @@ int iw_handler_get_spy(struct net_device * dev,
spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED;
return 0;
}
-EXPORT_SYMBOL(iw_handler_get_spy);
+EXPORT_SYMBOL(ipw_wx_get_spy);
/*------------------------------------------------------------------*/
/*
* Standard Wireless Handler : set spy threshold
*/
-int iw_handler_set_thrspy(struct net_device * dev,
- struct iw_request_info *info,
- union iwreq_data * wrqu,
- char * extra)
+int ipw_wx_set_thrspy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra)
{
struct iw_spy_data * spydata = get_spydata(dev);
struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
@@ -128,16 +130,16 @@ int iw_handler_set_thrspy(struct net_device * dev,
return 0;
}
-EXPORT_SYMBOL(iw_handler_set_thrspy);
+EXPORT_SYMBOL(ipw_wx_set_thrspy);
/*------------------------------------------------------------------*/
/*
* Standard Wireless Handler : get spy threshold
*/
-int iw_handler_get_thrspy(struct net_device * dev,
- struct iw_request_info *info,
- union iwreq_data * wrqu,
- char * extra)
+int ipw_wx_get_thrspy(struct net_device * dev,
+ struct iw_request_info * info,
+ union iwreq_data * wrqu,
+ char * extra)
{
struct iw_spy_data * spydata = get_spydata(dev);
struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
@@ -152,7 +154,7 @@ int iw_handler_get_thrspy(struct net_device * dev,
return 0;
}
-EXPORT_SYMBOL(iw_handler_get_thrspy);
+EXPORT_SYMBOL(ipw_wx_get_thrspy);
/*------------------------------------------------------------------*/
/*
@@ -189,9 +191,9 @@ static void iw_send_thrspy_event(struct net_device * dev,
* small, this is good enough. If we wanted to support larger number of
* spy addresses, we should use something more efficient...
*/
-void wireless_spy_update(struct net_device * dev,
- unsigned char * address,
- struct iw_quality * wstats)
+void libipw_spy_update(struct net_device * dev,
+ unsigned char * address,
+ struct iw_quality * wstats)
{
struct iw_spy_data * spydata = get_spydata(dev);
int i;
@@ -229,4 +231,3 @@ void wireless_spy_update(struct net_device * dev,
}
}
}
-EXPORT_SYMBOL(wireless_spy_update);
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
index e22a6732a4c3..80edaa3dea9c 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
@@ -138,7 +138,7 @@ static int libipw_copy_snap(u8 * data, __be16 h_proto)
static int libipw_encrypt_fragment(struct libipw_device *ieee,
struct sk_buff *frag, int hdr_len)
{
- struct lib80211_crypt_data *crypt =
+ struct libipw_crypt_data *crypt =
ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
int res;
@@ -255,7 +255,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
.qos_ctl = 0
};
u8 dest[ETH_ALEN], src[ETH_ALEN];
- struct lib80211_crypt_data *crypt;
+ struct libipw_crypt_data *crypt;
int priority = skb->priority;
int snapped = 0;
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_wx.c b/drivers/net/wireless/intel/ipw2x00/libipw_wx.c
index dbc7153d0a3d..db71d81b0d4f 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_wx.c
@@ -21,10 +21,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/jiffies.h>
-
-#include <net/lib80211.h>
#include <linux/wireless.h>
-
#include "libipw.h"
static const char *libipw_modes[] = {
@@ -303,7 +300,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
.flags = 0
};
int i, key, key_provided, len;
- struct lib80211_crypt_data **crypt;
+ struct libipw_crypt_data **crypt;
int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
LIBIPW_DEBUG_WX("SET_ENCODE\n");
@@ -328,7 +325,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
if (key_provided && *crypt) {
LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n",
key);
- lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt);
} else
LIBIPW_DEBUG_WX("Disabling encryption.\n");
@@ -338,7 +335,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
if (ieee->crypt_info.crypt[i] != NULL) {
if (key_provided)
break;
- lib80211_crypt_delayed_deinit(&ieee->crypt_info,
+ libipw_crypt_delayed_deinit(&ieee->crypt_info,
&ieee->crypt_info.crypt[i]);
}
}
@@ -361,21 +358,21 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
strcmp((*crypt)->ops->name, "WEP") != 0) {
/* changing to use WEP; deinit previously used algorithm
* on this key */
- lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt);
}
if (*crypt == NULL && host_crypto) {
- struct lib80211_crypt_data *new_crypt;
+ struct libipw_crypt_data *new_crypt;
/* take WEP into use */
- new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
+ new_crypt = kzalloc(sizeof(struct libipw_crypt_data),
GFP_KERNEL);
if (new_crypt == NULL)
return -ENOMEM;
- new_crypt->ops = lib80211_get_crypto_ops("WEP");
+ new_crypt->ops = libipw_get_crypto_ops("WEP");
if (!new_crypt->ops) {
- request_module("lib80211_crypt_wep");
- new_crypt->ops = lib80211_get_crypto_ops("WEP");
+ request_module("libipw_crypt_wep");
+ new_crypt->ops = libipw_get_crypto_ops("WEP");
}
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
@@ -386,7 +383,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
new_crypt = NULL;
printk(KERN_WARNING "%s: could not initialize WEP: "
- "load module lib80211_crypt_wep\n", dev->name);
+ "load module libipw_crypt_wep\n", dev->name);
return -EOPNOTSUPP;
}
*crypt = new_crypt;
@@ -509,8 +506,8 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee,
int i, idx, ret = 0;
int group_key = 0;
const char *alg, *module;
- const struct lib80211_crypto_ops *ops;
- struct lib80211_crypt_data **crypt;
+ const struct libipw_crypto_ops *ops;
+ struct libipw_crypt_data **crypt;
struct libipw_security sec = {
.flags = 0,
@@ -541,7 +538,7 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee,
if ((encoding->flags & IW_ENCODE_DISABLED) ||
ext->alg == IW_ENCODE_ALG_NONE) {
if (*crypt)
- lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt);
for (i = 0; i < WEP_KEYS; i++)
if (ieee->crypt_info.crypt[i] != NULL)
@@ -567,15 +564,15 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee,
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
alg = "WEP";
- module = "lib80211_crypt_wep";
+ module = "libipw_crypt_wep";
break;
case IW_ENCODE_ALG_TKIP:
alg = "TKIP";
- module = "lib80211_crypt_tkip";
+ module = "libipw_crypt_tkip";
break;
case IW_ENCODE_ALG_CCMP:
alg = "CCMP";
- module = "lib80211_crypt_ccmp";
+ module = "libipw_crypt_ccmp";
break;
default:
LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -584,10 +581,10 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee,
goto done;
}
- ops = lib80211_get_crypto_ops(alg);
+ ops = libipw_get_crypto_ops(alg);
if (ops == NULL) {
request_module(module);
- ops = lib80211_get_crypto_ops(alg);
+ ops = libipw_get_crypto_ops(alg);
}
if (ops == NULL) {
LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -597,9 +594,9 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee,
}
if (*crypt == NULL || (*crypt)->ops != ops) {
- struct lib80211_crypt_data *new_crypt;
+ struct libipw_crypt_data *new_crypt;
- lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt);
new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
if (new_crypt == NULL) {
diff --git a/drivers/net/wireless/intel/iwlegacy/3945.c b/drivers/net/wireless/intel/iwlegacy/3945.c
index 14d2331ee6cb..b0656b143f77 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945.c
@@ -566,7 +566,7 @@ il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR) ||
!(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
D_RX("Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
- rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
+ return;
}
/* Convert 3945's rssi indicator to dBm */
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index fcccde7bb659..05c4af41bdb9 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -664,7 +664,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
!(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
D_RX("Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(rx_pkt_status));
- rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
+ return;
}
/* This will be used in several places later */
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index fa1be8c54d3c..cd1fe8490ae5 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -10,10 +10,10 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
-#define IWL_BZ_UCODE_API_MAX 93
+#define IWL_BZ_UCODE_API_MAX 94
/* Lowest firmware API version supported */
-#define IWL_BZ_UCODE_API_MIN 90
+#define IWL_BZ_UCODE_API_MIN 92
/* NVM versions */
#define IWL_BZ_NVM_VERSION 0x0a1d
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
index f1dd1c29f305..fc5e6e44c6aa 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -10,10 +10,10 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
-#define IWL_SC_UCODE_API_MAX 93
+#define IWL_SC_UCODE_API_MAX 94
/* Lowest firmware API version supported */
-#define IWL_SC_UCODE_API_MIN 90
+#define IWL_SC_UCODE_API_MIN 92
/* NVM versions */
#define IWL_SC_NVM_VERSION 0x0a1d
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
index 2397fdc37fc5..9b942c4aabd9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
@@ -56,8 +56,6 @@ struct iwl_binding_cmd {
} __packed; /* BINDING_CMD_API_S_VER_2 */
#define IWL_BINDING_CMD_SIZE_V1 sizeof(struct iwl_binding_cmd_v1)
-#define IWL_LMAC_24G_INDEX 0
-#define IWL_LMAC_5G_INDEX 1
/* The maximal number of fragments in the FW's schedule session */
#define IWL_MVM_MAX_QUOTA 128
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
index 1fa5678c1cd6..a9fa5f054ce0 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
@@ -40,4 +40,7 @@ enum iwl_ctxt_action {
FW_CTXT_ACTION_REMOVE,
}; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */
+#define IWL_LMAC_24G_INDEX 0
+#define IWL_LMAC_5G_INDEX 1
+
#endif /* __iwl_fw_api_context_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index ffee7927cf26..c2362bc786b2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -368,7 +368,7 @@ enum iwl_wowlan_flags {
};
/**
- * struct iwl_wowlan_config_cmd - WoWLAN configuration (versions 5 and 6)
+ * struct iwl_wowlan_config_cmd_v6 - WoWLAN configuration (versions 5 and 6)
* @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters
* @non_qos_seq: non-QoS sequence counter to use next.
* Reserved if the struct has version >= 6.
@@ -380,7 +380,7 @@ enum iwl_wowlan_flags {
* @sta_id: station ID for wowlan.
* @reserved: reserved
*/
-struct iwl_wowlan_config_cmd {
+struct iwl_wowlan_config_cmd_v6 {
__le32 wakeup_filter;
__le16 non_qos_seq;
__le16 qos_seq[8];
@@ -390,7 +390,27 @@ struct iwl_wowlan_config_cmd {
u8 flags;
u8 sta_id;
u8 reserved;
-} __packed; /* WOWLAN_CONFIG_API_S_VER_5 */
+} __packed; /* WOWLAN_CONFIG_API_S_VER_6 */
+
+/**
+ * struct iwl_wowlan_config_cmd - WoWLAN configuration
+ * @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters
+ * @wowlan_ba_teardown_tids: bitmap of BA sessions to tear down
+ * @is_11n_connection: indicates HT connection
+ * @offloading_tid: TID reserved for firmware use
+ * @flags: extra flags, see &enum iwl_wowlan_flags
+ * @sta_id: station ID for wowlan.
+ * @reserved: reserved
+ */
+struct iwl_wowlan_config_cmd {
+ __le32 wakeup_filter;
+ u8 wowlan_ba_teardown_tids;
+ u8 is_11n_connection;
+ u8 offloading_tid;
+ u8 flags;
+ u8 sta_id;
+ u8 reserved[3];
+} __packed; /* WOWLAN_CONFIG_API_S_VER_7 */
#define IWL_NUM_RSC 16
#define WOWLAN_KEY_MAX_SIZE 32
@@ -890,7 +910,7 @@ struct iwl_wowlan_mlo_gtk {
} __packed; /* WOWLAN_MLO_GTK_KEY_API_S_VER_1 */
/**
- * struct iwl_wowlan_info_notif - WoWLAN information notification
+ * struct iwl_wowlan_info_notif_v4 - WoWLAN information notification
* @gtk: GTK data
* @igtk: IGTK data
* @bigtk: BIGTK data
@@ -910,7 +930,7 @@ struct iwl_wowlan_mlo_gtk {
* @reserved2: reserved
* @mlo_gtks: array of GTKs of size num_mlo_link_keys for version >= 4
*/
-struct iwl_wowlan_info_notif {
+struct iwl_wowlan_info_notif_v4 {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
@@ -930,6 +950,45 @@ struct iwl_wowlan_info_notif {
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3, _VER_4 */
/**
+ * struct iwl_wowlan_info_notif - WoWLAN information notification
+ * @gtk: GTK data
+ * @igtk: IGTK data
+ * @bigtk: BIGTK data
+ * @replay_ctr: GTK rekey replay counter
+ * @pattern_number: number of the matched patterns
+ * @qos_seq_ctr: QoS sequence counters to use next
+ * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
+ * @num_of_gtk_rekeys: number of GTK rekeys
+ * @transmitted_ndps: number of transmitted neighbor discovery packets
+ * @received_beacons: number of received beacons
+ * @tid_tear_down: bit mask of tids whose BA sessions were closed
+ * in suspend state
+ * @station_id: station id
+ * @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
+ * following this notif
+ * @tid_offloaded_tx: tid used by the firmware to transmit data packets
+ * while in wowlan
+ * @mlo_gtks: array of GTKs of size num_mlo_link_keys
+ */
+struct iwl_wowlan_info_notif {
+ struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM];
+ __le64 replay_ctr;
+ __le16 pattern_number;
+ __le16 qos_seq_ctr;
+ __le32 wakeup_reasons;
+ __le32 num_of_gtk_rekeys;
+ __le32 transmitted_ndps;
+ __le32 received_beacons;
+ u8 tid_tear_down;
+ u8 station_id;
+ u8 num_mlo_link_keys;
+ u8 tid_offloaded_tx;
+ struct iwl_wowlan_mlo_gtk mlo_gtks[];
+} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */
+
+/**
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
* @wake_packet_length: wakeup packet length
* @station_id: station id
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index 30a54c7fa001..b8dff139aa05 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -616,6 +616,9 @@ struct iwl_tof_range_req_ap_entry_v2 {
* continue with the session and will provide the LMR feedback.
* @IWL_INITIATOR_AP_FLAGS_TEST_INCORRECT_SAC: send an incorrect SAC in the
* first NDP exchange. This is used for testing.
+ * @IWL_INITIATOR_AP_FLAGS_TEST_BAD_SLTF: use incorrect secure LTF tx key. This
+ * is used for testing. Only supported from version 15 of the range request
+ * command.
*/
enum iwl_initiator_ap_flags {
IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1),
@@ -633,6 +636,7 @@ enum iwl_initiator_ap_flags {
IWL_INITIATOR_AP_FLAGS_PMF = BIT(14),
IWL_INITIATOR_AP_FLAGS_TERMINATE_ON_LMR_FEEDBACK = BIT(15),
IWL_INITIATOR_AP_FLAGS_TEST_INCORRECT_SAC = BIT(16),
+ IWL_INITIATOR_AP_FLAGS_TEST_BAD_SLTF = BIT(17),
};
/**
@@ -767,7 +771,7 @@ enum iwl_location_cipher {
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
* the number of measurement iterations (min 2^0 = 1, max 2^14)
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
- * otherwise should be set to &IWL_MVM_INVALID_STA.
+ * otherwise should be set to &IWL_INVALID_STA.
* @cipher: pairwise cipher suite for secured measurement.
* &enum iwl_location_cipher.
* @hltk: HLTK to be used for secured 11az measurement
@@ -814,7 +818,7 @@ struct iwl_tof_range_req_ap_entry_v6 {
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
* the number of measurement iterations (min 2^0 = 1, max 2^14)
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
- * otherwise should be set to &IWL_MVM_INVALID_STA.
+ * otherwise should be set to &IWL_INVALID_STA.
* @cipher: pairwise cipher suite for secured measurement.
* &enum iwl_location_cipher.
* @hltk: HLTK to be used for secured 11az measurement
@@ -827,10 +831,10 @@ struct iwl_tof_range_req_ap_entry_v6 {
* &IWL_INITIATOR_AP_FLAGS_TB is set.
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
*/
struct iwl_tof_range_req_ap_entry_v7 {
__le32 initiator_ap_flags;
@@ -872,7 +876,7 @@ struct iwl_tof_range_req_ap_entry_v7 {
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
* the number of measurement iterations (min 2^0 = 1, max 2^14)
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
- * otherwise should be set to &IWL_MVM_INVALID_STA.
+ * otherwise should be set to &IWL_INVALID_STA.
* @cipher: pairwise cipher suite for secured measurement.
* &enum iwl_location_cipher.
* @hltk: HLTK to be used for secured 11az measurement
@@ -885,10 +889,10 @@ struct iwl_tof_range_req_ap_entry_v7 {
* &IWL_INITIATOR_AP_FLAGS_TB is set.
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
* bits 0 - 2: max LTF repetitions
* bits 3 - 5: max number of spatial streams
@@ -946,7 +950,7 @@ struct iwl_tof_range_req_ap_entry_v8 {
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
* the number of measurement iterations (min 2^0 = 1, max 2^14)
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
- * otherwise should be set to &IWL_MVM_INVALID_STA.
+ * otherwise should be set to &IWL_INVALID_STA.
* @cipher: pairwise cipher suite for secured measurement.
* &enum iwl_location_cipher.
* @hltk: HLTK to be used for secured 11az measurement
@@ -961,10 +965,10 @@ struct iwl_tof_range_req_ap_entry_v8 {
* &IWL_INITIATOR_AP_FLAGS_TB or &IWL_INITIATOR_AP_FLAGS_NON_TB is set.
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
* bits 0 - 2: max LTF repetitions
* bits 3 - 5: max number of spatial streams
@@ -1029,7 +1033,7 @@ struct iwl_tof_range_req_ap_entry_v9 {
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
* the number of measurement iterations (min 2^0 = 1, max 2^14)
* @sta_id: the station id of the AP. Only relevant when associated to the AP,
- * otherwise should be set to &IWL_MVM_INVALID_STA.
+ * otherwise should be set to &IWL_INVALID_STA.
* @cipher: pairwise cipher suite for secured measurement.
* &enum iwl_location_cipher.
* @hltk: HLTK to be used for secured 11az measurement
@@ -1042,10 +1046,10 @@ struct iwl_tof_range_req_ap_entry_v9 {
* &IWL_INITIATOR_AP_FLAGS_TB is set.
* @rx_pn: the next expected PN for protected management frames Rx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
* @tx_pn: the next PN to use for protected management frames Tx. LE byte
* order. Only valid if &IWL_INITIATOR_AP_FLAGS_SECURED is set and sta_id
- * is set to &IWL_MVM_INVALID_STA.
+ * is set to &IWL_INVALID_STA.
* @r2i_ndp_params: parameters for R2I NDP ranging negotiation.
* bits 0 - 2: max LTF repetitions
* bits 3 - 5: max number of spatial streams
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index c46e24fc6a1e..b23d5fc4bbe6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -382,6 +382,8 @@ struct iwl_mac_config_cmd {
* @LINK_CONTEXT_MODIFY_EHT_PARAMS: covers iwl_link_ctx_cfg_cmd::puncture_mask.
* This flag can be set only if the MAC that this link relates to has
* eht_support set to true. No longer used since _VER_3 of this command.
+ * @LINK_CONTEXT_MODIFY_BANDWIDTH: Covers iwl_link_ctx_cfg_cmd::modify_bandwidth.
+ * Request RX OMI to the AP to modify bandwidth of this link.
* @LINK_CONTEXT_MODIFY_ALL: set all above flags
*/
enum iwl_link_ctx_modify_flags {
@@ -393,6 +395,7 @@ enum iwl_link_ctx_modify_flags {
LINK_CONTEXT_MODIFY_HE_PARAMS = BIT(5),
LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE = BIT(6),
LINK_CONTEXT_MODIFY_EHT_PARAMS = BIT(7),
+ LINK_CONTEXT_MODIFY_BANDWIDTH = BIT(8),
LINK_CONTEXT_MODIFY_ALL = 0xff,
}; /* LINK_CONTEXT_MODIFY_MASK_E_VER_1 */
@@ -434,6 +437,22 @@ enum iwl_link_ctx_flags {
}; /* LINK_CONTEXT_FLAG_E_VER_1 */
/**
+ * enum iwl_link_modify_bandwidth - link modify (RX OMI) bandwidth
+ * @IWL_LINK_MODIFY_BW_20: request 20 MHz
+ * @IWL_LINK_MODIFY_BW_40: request 40 MHz
+ * @IWL_LINK_MODIFY_BW_80: request 80 MHz
+ * @IWL_LINK_MODIFY_BW_160: request 160 MHz
+ * @IWL_LINK_MODIFY_BW_320: request 320 MHz
+ */
+enum iwl_link_modify_bandwidth {
+ IWL_LINK_MODIFY_BW_20,
+ IWL_LINK_MODIFY_BW_40,
+ IWL_LINK_MODIFY_BW_80,
+ IWL_LINK_MODIFY_BW_160,
+ IWL_LINK_MODIFY_BW_320,
+};
+
+/**
* struct iwl_link_config_cmd - command structure to configure the LINK context
* in MLD API
* ( LINK_CONFIG_CMD =0x9 )
@@ -457,6 +476,8 @@ enum iwl_link_ctx_flags {
* @block_tx: tell the firmware that this link can't Tx. This should be used
* only when a link is de-activated because of CSA with mode = 1.
* Available since version 5.
+ * @modify_bandwidth: bandwidth request value for RX OMI (see also
+ * %LINK_CONTEXT_MODIFY_BANDWIDTH), from &enum iwl_link_modify_bandwidth.
* @reserved1: in version 2, listen_lmac became reserved
* @cck_rates: basic rates available for CCK
* @ofdm_rates: basic rates available for OFDM
@@ -500,10 +521,11 @@ struct iwl_link_config_cmd {
__le32 modify_mask;
__le32 active;
union {
- __le32 listen_lmac;
+ __le32 listen_lmac; /* only _VER_1 */
struct {
- u8 block_tx;
- u8 reserved1[3];
+ u8 block_tx; /* since _VER_5 */
+ u8 modify_bandwidth; /* since _VER_6 */
+ u8 reserved1[2];
};
};
__le32 cck_rates;
@@ -524,7 +546,7 @@ struct iwl_link_config_cmd {
__le16 puncture_mask; /* removed in _VER_3 */
__le16 frame_time_rts_th;
__le32 flags;
- __le32 flags_mask;
+ __le32 flags_mask; /* removed in _VER_6 */
/* The below fields are for multi-bssid */
u8 ref_bssid_addr[6];
__le16 reserved_for_ref_bssid_addr;
@@ -535,7 +557,7 @@ struct iwl_link_config_cmd {
u8 ibss_bssid_addr[6];
__le16 reserved_for_ibss_bssid_addr;
__le32 reserved3[8];
-} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5 */
+} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6 */
/* Currently FW supports link ids in the range 0-3 and can have
* at most two active links for each vif.
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
index 977ca4ac166d..26301c0b06a1 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
@@ -17,7 +17,7 @@
#define NUM_MAC_INDEX_CDB (NUM_MAC_INDEX_DRIVER + 2)
#define IWL_STATION_COUNT_MAX 16
-#define IWL_MVM_INVALID_STA 0xFF
+#define IWL_INVALID_STA 0xFF
enum iwl_ac {
AC_BK,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 98d56e778d99..f4803b55adb9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2019, 2021-2023 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021-2024 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -327,18 +327,19 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt);
void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
u32 timepoint,
u32 timepoint_data);
+bool iwl_fwrt_read_err_table(struct iwl_trans *trans, u32 base, u32 *err_id);
void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt);
void iwl_fw_dbg_clear_monitor_buf(struct iwl_fw_runtime *fwrt);
-#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \
- IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__)
+#define IWL_FW_CHECK_FAILED(_obj, ...) \
+ IWL_ERR_LIMIT(_obj, __VA_ARGS__)
#define IWL_FW_CHECK(_obj, _cond, _fmt, ...) \
({ \
bool __cond = (_cond); \
\
if (unlikely(__cond)) \
- IWL_FW_CHECK_FAILED(_obj, _fmt, __VA_ARGS__); \
+ IWL_FW_CHECK_FAILED(_obj, _fmt, ##__VA_ARGS__); \
\
unlikely(__cond); \
})
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
index 8f107ceec407..8e0c85a1240d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -530,3 +530,28 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
}
}
IWL_EXPORT_SYMBOL(iwl_fwrt_dump_error_logs);
+
+bool iwl_fwrt_read_err_table(struct iwl_trans *trans, u32 base, u32 *err_id)
+{
+ struct error_table_start {
+ /* cf. struct iwl_error_event_table */
+ u32 valid;
+ __le32 err_id;
+ } err_info = {};
+ int ret;
+
+ if (!base)
+ return false;
+
+ ret = iwl_trans_read_mem_bytes(trans, base,
+ &err_info, sizeof(err_info));
+
+ if (ret)
+ return true;
+
+ if (err_info.valid && err_id)
+ *err_id = le32_to_cpu(err_info.err_id);
+
+ return !!err_info.valid;
+}
+IWL_EXPORT_SYMBOL(iwl_fwrt_read_err_table);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index e95ffe303547..c70da7281551 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -1074,12 +1074,13 @@ int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
void iwl_trans_debugfs_cleanup(struct iwl_trans *trans);
#endif
-#define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \
- do { \
- if (__builtin_constant_p(bufsize)) \
- BUILD_BUG_ON((bufsize) % sizeof(u32)); \
- iwl_trans_read_mem(trans, addr, buf, (bufsize) / sizeof(u32));\
- } while (0)
+#define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \
+ ({ \
+ if (__builtin_constant_p(bufsize)) \
+ BUILD_BUG_ON((bufsize) % sizeof(u32)); \
+ iwl_trans_read_mem(trans, addr, buf, \
+ (bufsize) / sizeof(u32)); \
+ })
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
u64 src_addr, u32 byte_cnt);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index b607961970e9..36726ea4b822 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -689,7 +689,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* Rssi update while not associated - can happen since the statistics
* are handled asynchronously
*/
- if (mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA)
+ if (mvmvif->deflink.ap_sta_id == IWL_INVALID_STA)
return;
/* No BT - reports should be disabled */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index ddf484027d4f..776600ddaea6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -17,7 +17,9 @@
#define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30
#define IWL_MVM_TPT_COUNT_WINDOW_SEC 5
#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5
-#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 11
+#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 15
+#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 11
+#define IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH -72
#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
@@ -57,7 +59,6 @@
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1
#define IWL_MVM_TOF_IS_RESPONDER 0
-#define IWL_MVM_HW_CSUM_DISABLE 0
#define IWL_MVM_ADWELL_ENABLE 1
#define IWL_MVM_ADWELL_MAX_BUDGET 0
#define IWL_MVM_TCM_LOAD_MEDIUM_THRESH 10 /* percentage */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 244ca8cab9d1..f85c01e04ebf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -922,7 +922,7 @@ static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
static int
iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
struct cfg80211_wowlan *wowlan,
- struct iwl_wowlan_config_cmd *wowlan_config_cmd,
+ struct iwl_wowlan_config_cmd_v6 *wowlan_config_cmd,
struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
struct ieee80211_sta *ap_sta)
{
@@ -948,7 +948,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
wowlan_config_cmd->non_qos_seq = cpu_to_le16(ret);
}
- iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, wowlan_config_cmd);
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) < 7)
+ iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, wowlan_config_cmd);
if (wowlan->disconnect)
wowlan_config_cmd->wakeup_filter |=
@@ -1122,7 +1123,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
static int
iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
struct cfg80211_wowlan *wowlan,
- struct iwl_wowlan_config_cmd *wowlan_config_cmd,
+ struct iwl_wowlan_config_cmd_v6 *wowlan_config_cmd_v6,
struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
struct iwl_mvm_vif_link_info *mvm_link,
struct ieee80211_sta *ap_sta)
@@ -1131,7 +1132,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
- mvm->offload_tid = wowlan_config_cmd->offloading_tid;
+ mvm->offload_tid = wowlan_config_cmd_v6->offloading_tid;
if (!unified_image) {
ret = iwl_mvm_switch_to_d3(mvm);
@@ -1147,9 +1148,26 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
if (ret)
return ret;
- ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
- sizeof(*wowlan_config_cmd),
- wowlan_config_cmd);
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) > 6) {
+ struct iwl_wowlan_config_cmd wowlan_config_cmd = {
+ .wakeup_filter = wowlan_config_cmd_v6->wakeup_filter,
+ .wowlan_ba_teardown_tids =
+ wowlan_config_cmd_v6->wowlan_ba_teardown_tids,
+ .is_11n_connection =
+ wowlan_config_cmd_v6->is_11n_connection,
+ .offloading_tid = wowlan_config_cmd_v6->offloading_tid,
+ .flags = wowlan_config_cmd_v6->flags,
+ .sta_id = wowlan_config_cmd_v6->sta_id,
+ };
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
+ sizeof(wowlan_config_cmd),
+ &wowlan_config_cmd);
+ } else {
+ ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
+ sizeof(*wowlan_config_cmd_v6),
+ wowlan_config_cmd_v6);
+ }
if (ret)
return ret;
@@ -1288,7 +1306,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
goto out_noreset;
}
- if (mvm_link->ap_sta_id == IWL_MVM_INVALID_STA) {
+ if (mvm_link->ap_sta_id == IWL_INVALID_STA) {
/* if we're not associated, this must be netdetect */
if (!wowlan->nd_config) {
ret = 1;
@@ -1302,7 +1320,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
mvm->net_detect = true;
} else {
- struct iwl_wowlan_config_cmd wowlan_config_cmd = {
+ struct iwl_wowlan_config_cmd_v6 wowlan_config_cmd = {
.offloading_tid = 0,
};
@@ -1425,6 +1443,7 @@ struct iwl_wowlan_status_data {
u16 non_qos_seq_ctr;
u16 qos_seq_ctr[8];
u8 tid_tear_down;
+ u8 tid_offloaded_tx;
struct {
/* including RX MIC key for TKIP */
@@ -2474,7 +2493,64 @@ static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
struct iwl_wowlan_info_notif *data,
struct iwl_wowlan_status_data *status,
- u32 len, bool has_mlo_keys)
+ u32 len)
+{
+ u32 expected_len = sizeof(*data) +
+ data->num_mlo_link_keys * sizeof(status->mlo_keys[0]);
+
+ if (!data) {
+ IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n");
+ status = NULL;
+ return;
+ }
+
+ if (len < expected_len) {
+ IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
+ status = NULL;
+ return;
+ }
+
+ if (mvm->fast_resume)
+ return;
+
+ iwl_mvm_convert_key_counters_v5(status, &data->gtk[0].sc);
+ iwl_mvm_convert_gtk_v3(status, data->gtk);
+ iwl_mvm_convert_igtk(status, &data->igtk[0]);
+ iwl_mvm_convert_bigtk(status, data->bigtk);
+ status->replay_ctr = le64_to_cpu(data->replay_ctr);
+ status->pattern_number = le16_to_cpu(data->pattern_number);
+ status->tid_offloaded_tx = data->tid_offloaded_tx;
+ if (IWL_FW_CHECK(mvm,
+ data->tid_offloaded_tx >=
+ ARRAY_SIZE(status->qos_seq_ctr),
+ "tid_offloaded_tx is out of bound %d\n",
+ data->tid_offloaded_tx))
+ data->tid_offloaded_tx = 0;
+ status->qos_seq_ctr[data->tid_offloaded_tx] =
+ le16_to_cpu(data->qos_seq_ctr);
+ status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons);
+ status->num_of_gtk_rekeys =
+ le32_to_cpu(data->num_of_gtk_rekeys);
+ status->received_beacons = le32_to_cpu(data->received_beacons);
+ status->tid_tear_down = data->tid_tear_down;
+
+ if (data->num_mlo_link_keys) {
+ status->num_mlo_keys = data->num_mlo_link_keys;
+ if (IWL_FW_CHECK(mvm,
+ status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
+ "Too many mlo keys: %d, max %d\n",
+ status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
+ status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
+ memcpy(status->mlo_keys, data->mlo_gtks,
+ status->num_mlo_keys * sizeof(status->mlo_keys[0]));
+ }
+}
+
+static void
+iwl_mvm_parse_wowlan_info_notif_v4(struct iwl_mvm *mvm,
+ struct iwl_wowlan_info_notif_v4 *data,
+ struct iwl_wowlan_status_data *status,
+ u32 len, bool has_mlo_keys)
{
u32 i;
u32 expected_len = sizeof(*data);
@@ -2746,6 +2822,10 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
+ int wowlan_info_ver = iwl_fw_lookup_notif_ver(mvm->fw,
+ PROT_OFFLOAD_GROUP,
+ WOWLAN_INFO_NOTIFICATION,
+ IWL_FW_CMD_VER_UNKNOWN);
if (WARN_ON(!mvm_link))
goto out_unlock;
@@ -2760,11 +2840,14 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
if (!mvm_ap_sta)
goto out_unlock;
- for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
- u16 seq = status->qos_seq_ctr[i];
- /* firmware stores last-used value, we store next value */
- seq += 0x10;
- mvm_ap_sta->tid_data[i].seq_number = seq;
+ /* firmware stores last-used value, we store next value */
+ if (wowlan_info_ver >= 5) {
+ mvm_ap_sta->tid_data[status->tid_offloaded_tx].seq_number =
+ status->qos_seq_ctr[status->tid_offloaded_tx] + 0x10;
+ } else {
+ for (i = 0; i < IWL_MAX_TID_COUNT; i++)
+ mvm_ap_sta->tid_data[i].seq_number =
+ status->qos_seq_ctr[i] + 0x10;
}
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
@@ -3026,34 +3109,15 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
ieee80211_resume_disconnect(vif);
}
-static bool iwl_mvm_rt_status(struct iwl_trans *trans, u32 base, u32 *err_id)
-{
- struct error_table_start {
- /* cf. struct iwl_error_event_table */
- u32 valid;
- __le32 err_id;
- } err_info;
-
- if (!base)
- return false;
-
- iwl_trans_read_mem_bytes(trans, base,
- &err_info, sizeof(err_info));
- if (err_info.valid && err_id)
- *err_id = le32_to_cpu(err_info.err_id);
-
- return !!err_info.valid;
-}
-
static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
u32 err_id;
/* check for lmac1 error */
- if (iwl_mvm_rt_status(mvm->trans,
- mvm->trans->dbg.lmac_error_event_table[0],
- &err_id)) {
+ if (iwl_fwrt_read_err_table(mvm->trans,
+ mvm->trans->dbg.lmac_error_event_table[0],
+ &err_id)) {
if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) {
struct cfg80211_wowlan_wakeup wakeup = {
.rfkill_release = true,
@@ -3065,13 +3129,15 @@ static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
}
/* check if we have lmac2 set and check for error */
- if (iwl_mvm_rt_status(mvm->trans,
- mvm->trans->dbg.lmac_error_event_table[1], NULL))
+ if (iwl_fwrt_read_err_table(mvm->trans,
+ mvm->trans->dbg.lmac_error_event_table[1],
+ NULL))
return true;
/* check for umac error */
- if (iwl_mvm_rt_status(mvm->trans,
- mvm->trans->dbg.umac_error_event_table, NULL))
+ if (iwl_fwrt_read_err_table(mvm->trans,
+ mvm->trans->dbg.umac_error_event_table,
+ NULL))
return true;
return false;
@@ -3092,7 +3158,7 @@ iwl_mvm_choose_query_wakeup_reasons(struct iwl_mvm *mvm,
/* if FW uses status notification, status shouldn't be NULL here */
if (!d3_data->status) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u8 sta_id = mvm->net_detect ? IWL_MVM_INVALID_STA :
+ u8 sta_id = mvm->net_detect ? IWL_INVALID_STA :
mvmvif->deflink.ap_sta_id;
/* bug - FW with MLO has status notification */
@@ -3264,13 +3330,19 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,
d3_data->status,
len);
+ } else if (wowlan_info_ver < 5) {
+ struct iwl_wowlan_info_notif_v4 *notif =
+ (void *)pkt->data;
+
+ iwl_mvm_parse_wowlan_info_notif_v4(mvm, notif,
+ d3_data->status, len,
+ wowlan_info_ver > 3);
} else {
struct iwl_wowlan_info_notif *notif =
(void *)pkt->data;
iwl_mvm_parse_wowlan_info_notif(mvm, notif,
- d3_data->status, len,
- wowlan_info_ver > 3);
+ d3_data->status, len);
}
d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;
@@ -3612,8 +3684,6 @@ void iwl_mvm_fast_suspend(struct iwl_mvm *mvm)
IWL_ERR(mvm,
"fast suspend: couldn't send D3_CONFIG_CMD %d\n", ret);
- WARN_ON(iwl_mvm_power_update_mac(mvm));
-
ret = iwl_trans_d3_suspend(mvm->trans, false, false);
if (ret)
IWL_ERR(mvm, "fast suspend: trans_d3_suspend failed %d\n", ret);
@@ -3635,22 +3705,31 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
if (iwl_mvm_check_rt_status(mvm, NULL)) {
+ IWL_ERR(mvm,
+ "iwl_mvm_check_rt_status failed, device is gone during suspend\n");
set_bit(STATUS_FW_ERROR, &mvm->trans->status);
iwl_mvm_dump_nic_error_log(mvm);
iwl_dbg_tlv_time_point(&mvm->fwrt,
IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);
iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
false, 0);
- return -ENODEV;
+ mvm->trans->state = IWL_TRANS_NO_FW;
+ ret = -ENODEV;
+
+ goto out;
}
ret = iwl_mvm_d3_notif_wait(mvm, &d3_data);
+
+ if (ret) {
+ IWL_ERR(mvm, "Couldn't get the d3 notif %d\n", ret);
+ mvm->trans->state = IWL_TRANS_NO_FW;
+ }
+
+out:
clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
mvm->fast_resume = false;
- if (ret)
- IWL_ERR(mvm, "Couldn't get the d3 notif %d\n", ret);
-
return ret;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 25f07e00db42..fbe4e4a50852 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -221,7 +221,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
mvmvif->deflink.queue_params[i].uapsd);
if (vif->type == NL80211_IFTYPE_STATION &&
- ap_sta_id != IWL_MVM_INVALID_STA) {
+ ap_sta_id != IWL_INVALID_STA) {
struct iwl_mvm_sta *mvm_sta;
mvm_sta = iwl_mvm_sta_from_staid_protected(mvm, ap_sta_id);
@@ -463,11 +463,13 @@ static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
-static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
- size_t count, loff_t *ppos)
+static ssize_t
+iwl_dbgfs_low_latency_write_handle(struct wiphy *wiphy, struct file *file,
+ char *buf, size_t count, void *data)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *vif = data;
u8 value;
int ret;
@@ -484,12 +486,28 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
return count;
}
-static ssize_t
-iwl_dbgfs_low_latency_force_write(struct ieee80211_vif *vif, char *buf,
- size_t count, loff_t *ppos)
+static ssize_t iwl_dbgfs_low_latency_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
{
+ struct ieee80211_vif *vif = file->private_data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
+ char buf[10] = {};
+
+ return wiphy_locked_debugfs_write(mvm->hw->wiphy, file,
+ buf, sizeof(buf), user_buf, count,
+ iwl_dbgfs_low_latency_write_handle,
+ vif);
+}
+
+static ssize_t
+iwl_dbgfs_low_latency_force_write_handle(struct wiphy *wiphy, struct file *file,
+ char *buf, size_t count, void *data)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *vif = data;
u8 value;
int ret;
@@ -517,6 +535,22 @@ iwl_dbgfs_low_latency_force_write(struct ieee80211_vif *vif, char *buf,
return count;
}
+static ssize_t
+iwl_dbgfs_low_latency_force_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_vif *vif = file->private_data;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = mvmvif->mvm;
+ char buf[10] = {};
+
+ return wiphy_locked_debugfs_write(mvm->hw->wiphy, file,
+ buf, sizeof(buf), user_buf, count,
+ iwl_dbgfs_low_latency_force_write_handle,
+ vif);
+}
+
static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -831,8 +865,20 @@ MVM_DEBUGFS_READ_FILE_OPS(mac_params);
MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
-MVM_DEBUGFS_WRITE_FILE_OPS(low_latency_force, 10);
+
+static const struct file_operations iwl_dbgfs_low_latency_ops = {
+ .write = iwl_dbgfs_low_latency_write,
+ .read = iwl_dbgfs_low_latency_read,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
+static const struct file_operations iwl_dbgfs_low_latency_force_ops = {
+ .write = iwl_dbgfs_low_latency_force_write,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 55245f913286..b26141c30c61 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -559,12 +559,12 @@ static int iwl_mvm_ftm_set_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (mvmvif->ftm_unprotected) {
- *sta_id = IWL_MVM_INVALID_STA;
+ *sta_id = IWL_INVALID_STA;
*flags &= ~cpu_to_le32(IWL_INITIATOR_AP_FLAGS_PMF);
}
#endif
} else {
- *sta_id = IWL_MVM_INVALID_STA;
+ *sta_id = IWL_INVALID_STA;
}
return 0;
@@ -1063,6 +1063,8 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_FW_CMD_VER_UNKNOWN);
switch (cmd_ver) {
+ case 15:
+ /* Version 15 has the same struct as 14 */
case 14:
err = iwl_mvm_ftm_start_v14(mvm, vif, req);
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index e4caa362f597..e6e468e81ab3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -131,7 +131,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- if (cmd_ver == 10) {
+ if (cmd_ver >= 10) {
cmd.band =
iwl_mvm_phy_band_from_nl80211(chandef->chan->band);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index f30b0fc8eca9..5ea684802ad1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1401,6 +1401,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
int ret, i;
struct ieee80211_supported_band *sband = NULL;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
ret = iwl_trans_start_hw(mvm->trans);
@@ -1484,7 +1485,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
for (i = 0; i < IWL_FW_MAX_LINK_ID + 1; i++)
RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL);
- mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA;
/* reset quota debouncing buffer - 0xff will yield invalid data */
memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
@@ -1620,6 +1621,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
{
int ret, i;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
ret = iwl_trans_start_hw(mvm->trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 2b0652168002..272da41567ef 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -12,6 +12,7 @@
HOW(BLOCKED_FW) \
HOW(BLOCKED_NON_BSS) \
HOW(BLOCKED_ROC) \
+ HOW(BLOCKED_TMP_NON_BSS) \
HOW(EXIT_MISSED_BEACON) \
HOW(EXIT_LOW_RSSI) \
HOW(EXIT_COEX) \
@@ -360,7 +361,8 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
send_cmd:
cmd.modify_mask = cpu_to_le32(changes);
cmd.flags = cpu_to_le32(flags);
- cmd.flags_mask = cpu_to_le32(flags_mask);
+ if (cmd_ver < 6)
+ cmd.flags_mask = cpu_to_le32(flags_mask);
cmd.spec_link_id = link_conf->link_id;
if (cmd_ver < 2)
cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
@@ -1165,3 +1167,14 @@ void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (!mvmvif->esr_disable_reason)
iwl_mvm_esr_unblocked(mvm, vif);
}
+
+void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link)
+{
+ link->bcast_sta.sta_id = IWL_INVALID_STA;
+ link->mcast_sta.sta_id = IWL_INVALID_STA;
+ link->ap_sta_id = IWL_INVALID_STA;
+
+ for (int r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
+ link->smps_requests[r] =
+ IEEE80211_SMPS_AUTOMATIC;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index a7a10e716e65..2a13d70da46c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -216,7 +216,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
.preferred_tsf = NUM_TSF_IDS,
.found_vif = false,
};
- int ret, i;
+ int ret;
lockdep_assert_held(&mvm->mutex);
@@ -298,9 +298,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->time_event_data.id = TE_MAX;
mvmvif->roc_activity = ROC_NUM_ACTIVITIES;
- mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
- mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
- mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
+ iwl_mvm_init_link(&mvmvif->deflink);
/* No need to allocate data queues to P2P Device MAC and NAN.*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
@@ -316,9 +314,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
}
- for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
- mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
-
return 0;
exit_fail:
@@ -1605,6 +1600,7 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
0);
u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
MISSED_BEACONS_NOTIF, 0);
+ struct ieee80211_bss_conf *bss_conf;
/* If the firmware uses the new notification (from MAC_CONF_GROUP),
* refer to that notification's version.
@@ -1617,9 +1613,9 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
/* before version four the ID in the notification refers to mac ID */
if (notif_ver < 4) {
vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
+ bss_conf = &vif->bss_conf;
} else {
- struct ieee80211_bss_conf *bss_conf =
- iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false);
+ bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false);
if (!bss_conf)
return;
@@ -1664,6 +1660,8 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
rx_missed_bcon, rx_missed_bcon_since_rx);
}
} else if (link_id >= 0 && hweight16(vif->active_links) > 1) {
+ u32 bss_param_ch_cnt_link_id =
+ bss_conf->bss_param_ch_cnt_link_id;
u32 scnd_lnk_bcn_lost = 0;
if (notif_ver >= 5 &&
@@ -1677,10 +1675,14 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
/* Exit EMLSR if we lost more than
* IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links
* OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH on any link.
+ * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED
+ * and the link's bss_param_ch_count has changed.
*/
if ((rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS &&
scnd_lnk_bcn_lost >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) ||
- rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH)
+ rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH ||
+ (bss_param_ch_cnt_link_id != link_id &&
+ rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED))
iwl_mvm_exit_esr(mvm, vif,
IWL_MVM_ESR_EXIT_MISSED_BEACON,
iwl_mvm_get_primary_link(vif));
@@ -1689,6 +1691,9 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm,
ieee80211_beacon_loss(vif);
else
ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC);
+
+ /* try to switch links, no-op if we don't have MLO */
+ iwl_mvm_int_mlo_scan(mvm, vif);
}
iwl_dbg_tlv_time_point(&mvm->fwrt,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 80b9a115245f..07778d55878b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1109,7 +1109,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
- mvmvif->link[link_id]->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->link[link_id]->ap_sta_id = IWL_INVALID_STA;
mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
mvmvif->link[link_id]->phy_ctxt = NULL;
mvmvif->link[link_id]->active = 0;
@@ -1237,6 +1237,7 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
fast_resume = mvm->fast_resume;
if (fast_resume) {
+ iwl_mvm_mei_device_state(mvm, true);
ret = iwl_mvm_fast_resume(mvm);
if (ret) {
iwl_mvm_stop_device(mvm);
@@ -1344,6 +1345,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
* of packets the FW sent out, so we must reconnect.
*/
iwl_mvm_teardown_tdls_peers(mvm);
+
+ IWL_INFO(mvm, "restart completed\n");
}
void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
@@ -1377,10 +1380,13 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm, bool suspend)
iwl_mvm_rm_aux_sta(mvm);
if (suspend &&
- mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
iwl_mvm_fast_suspend(mvm);
- else
+ /* From this point on, we won't touch the device */
+ iwl_mvm_mei_device_state(mvm, false);
+ } else {
iwl_mvm_stop_device(mvm);
+ }
iwl_mvm_async_handlers_purge(mvm);
/* async_handlers_list is empty and will stay empty: HW is stopped */
@@ -1474,15 +1480,16 @@ struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
return NULL;
}
-int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+int iwl_mvm_set_tx_power(struct iwl_mvm *mvm,
+ struct ieee80211_bss_conf *link_conf,
s16 tx_power)
{
u32 cmd_id = REDUCE_TX_POWER_CMD;
+ u32 mac_id = iwl_mvm_vif_from_mac80211(link_conf->vif)->id;
int len;
struct iwl_dev_tx_power_cmd_v3_v8 cmd = {
.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC),
- .common.mac_context_id =
- cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id),
+ .common.mac_context_id = cpu_to_le32(mac_id),
};
struct iwl_dev_tx_power_cmd cmd_v9_v10;
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3);
@@ -1495,8 +1502,7 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (cmd_ver > 8) {
/* Those fields sit on the same place for v9 and v10 */
cmd_v9_v10.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC);
- cmd_v9_v10.common.mac_context_id =
- cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id);
+ cmd_v9_v10.common.mac_context_id = cpu_to_le32(mac_id);
cmd_v9_v10.common.pwr_restriction = cpu_to_le16(u_tx_power);
cmd_data = &cmd_v9_v10;
}
@@ -1739,6 +1745,21 @@ static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT);
}
+static void iwl_mvm_unblock_esr_tmp_non_bss(struct wiphy *wiphy,
+ struct wiphy_work *wk)
+{
+ struct iwl_mvm_vif *mvmvif =
+ container_of(wk, struct iwl_mvm_vif,
+ unblock_esr_tmp_non_bss_wk.work);
+ struct iwl_mvm *mvm = mvmvif->mvm;
+ struct ieee80211_vif *vif =
+ container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
+
+ mutex_lock(&mvm->mutex);
+ iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
+ mutex_unlock(&mvm->mutex);
+}
+
void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
{
lockdep_assert_held(&mvm->mutex);
@@ -1757,6 +1778,9 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
wiphy_work_init(&mvmvif->unblock_esr_tpt_wk,
iwl_mvm_unblock_esr_tpt);
+
+ wiphy_delayed_work_init(&mvmvif->unblock_esr_tmp_non_bss_wk,
+ iwl_mvm_unblock_esr_tmp_non_bss);
}
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
@@ -1907,6 +1931,8 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
&mvmvif->mlo_int_scan_wk);
wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
+ wiphy_delayed_work_cancel(mvm->hw->wiphy,
+ &mvmvif->unblock_esr_tmp_non_bss_wk);
cancel_delayed_work_sync(&mvmvif->csa_work);
}
@@ -2929,7 +2955,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_MVM_SMPS_REQ_PROT,
IEEE80211_SMPS_DYNAMIC, 0);
}
- } else if (mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ } else if (mvmvif->deflink.ap_sta_id != IWL_INVALID_STA) {
iwl_mvm_mei_host_disassociated(mvm);
/*
* If update fails - SF might be running in associated
@@ -2965,7 +2991,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR(mvm,
"failed to remove AP station\n");
- mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
+ mvmvif->deflink.ap_sta_id = IWL_INVALID_STA;
}
/* remove quota for this interface */
@@ -3311,7 +3337,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_TXPOWER) {
IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
bss_conf->txpower);
- iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
+ iwl_mvm_set_tx_power(mvm, bss_conf, bss_conf->txpower);
}
}
@@ -3422,7 +3448,7 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
*/
break;
case STA_NOTIFY_AWAKE:
- if (WARN_ON(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON(mvmsta->deflink.sta_id == IWL_INVALID_STA))
break;
if (txqs)
@@ -3502,6 +3528,8 @@ void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
unsigned int link_id;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+
/*
* This is called before mac80211 does RCU synchronisation,
* so here we already invalidate our internal RCU-protected
@@ -4083,6 +4111,8 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
&mvmvif->mlo_int_scan_wk);
wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk);
+ wiphy_delayed_work_cancel(mvm->hw->wiphy,
+ &mvmvif->unblock_esr_tmp_non_bss_wk);
/* No need for the periodic statistics anymore */
if (ieee80211_vif_is_mld(vif) && mvmvif->esr_active)
@@ -4244,8 +4274,9 @@ int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
}
void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u32 changed)
+ struct ieee80211_link_sta *link_sta, u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
if (changed & (IEEE80211_RC_BW_CHANGED |
@@ -5075,7 +5106,7 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
(changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
IEEE80211_CHANCTX_CHANGE_RX_CHAINS |
IEEE80211_CHANCTX_CHANGE_RADAR |
- IEEE80211_CHANCTX_CHANGE_MIN_WIDTH)),
+ IEEE80211_CHANCTX_CHANGE_MIN_DEF)),
"Cannot change PHY. Ref=%d, changed=0x%X\n",
phy_ctxt->ref, changed))
return;
@@ -5083,7 +5114,7 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
guard(mvm)(mvm);
/* we are only changing the min_width, may be a noop */
- if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) {
+ if (changed == IEEE80211_CHANCTX_CHANGE_MIN_DEF) {
if (phy_ctxt->width == def->width)
return;
@@ -6570,7 +6601,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
.release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
.set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
- .sta_rc_update = iwl_mvm_sta_rc_update,
+ .link_sta_rc_update = iwl_mvm_sta_rc_update,
.conf_tx = iwl_mvm_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index 455f5f417506..ef0be44207e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -396,7 +396,7 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION ||
- link->ap_sta_id == IWL_MVM_INVALID_STA))
+ link->ap_sta_id == IWL_INVALID_STA))
return;
if (!sec_key_ver)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index e252f0dcea20..b807046144c0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -339,33 +339,20 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
if (ret)
goto out;
- /* Initialize rate control for the AP station, since we might be
- * doing a link switch here - we cannot initialize it before since
- * this needs the phy context assigned (and in FW?), and we cannot
- * do it later because it needs to be initialized as soon as we're
- * able to TX on the link, i.e. when active.
+ /*
+ * if link switching (link not active yet) we'll activate it in
+ * firmware later on link-info change, which mac80211 guarantees
+ * for link switch after the stations are set up
*/
- if (mvmvif->ap_sta) {
- struct ieee80211_link_sta *link_sta;
-
- rcu_read_lock();
- link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]);
-
- if (!WARN_ON_ONCE(!link_sta))
- iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta,
- link_conf, link_sta,
- phy_ctxt->channel->band);
- rcu_read_unlock();
+ if (ieee80211_vif_link_active(vif, link_conf->link_id)) {
+ ret = iwl_mvm_link_changed(mvm, vif, link_conf,
+ LINK_CONTEXT_MODIFY_ACTIVE |
+ LINK_CONTEXT_MODIFY_RATES_INFO,
+ true);
+ if (ret)
+ goto out;
}
- /* then activate */
- ret = iwl_mvm_link_changed(mvm, vif, link_conf,
- LINK_CONTEXT_MODIFY_ACTIVE |
- LINK_CONTEXT_MODIFY_RATES_INFO,
- true);
- if (ret)
- goto out;
-
if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_send_ap_tx_power_constraint_cmd(mvm, vif,
link_conf,
@@ -783,6 +770,11 @@ iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id]))
return;
+ /* not yet marked active in vif means during link switch */
+ if (!ieee80211_vif_link_active(vif, link_conf->link_id) &&
+ vif->cfg.assoc && mvmvif->link[link_conf->link_id]->phy_ctxt)
+ link_changes |= LINK_CONTEXT_MODIFY_ACTIVE;
+
has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax;
has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be;
@@ -832,7 +824,7 @@ static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif *mvmvif)
int i;
for_each_mvm_vif_valid_link(mvmvif, i) {
- if (mvmvif->link[i]->ap_sta_id != IWL_MVM_INVALID_STA)
+ if (mvmvif->link[i]->ap_sta_id != IWL_INVALID_STA)
return true;
}
@@ -859,7 +851,7 @@ static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
if (ret)
IWL_ERR(mvm, "failed to remove AP station\n");
- link->ap_sta_id = IWL_MVM_INVALID_STA;
+ link->ap_sta_id = IWL_INVALID_STA;
}
}
@@ -1046,7 +1038,7 @@ static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_TXPOWER) {
IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n",
link_conf->txpower);
- iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower);
+ iwl_mvm_set_tx_power(mvm, link_conf, link_conf->txpower);
}
}
@@ -1177,8 +1169,6 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
int err, i;
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
- int r;
-
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
break;
@@ -1190,14 +1180,8 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
goto free;
}
- new_link[i]->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
- new_link[i]->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
- new_link[i]->ap_sta_id = IWL_MVM_INVALID_STA;
new_link[i]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
-
- for (r = 0; r < NUM_IWL_MVM_SMPS_REQ; r++)
- new_link[i]->smps_requests[r] =
- IEEE80211_SMPS_AUTOMATIC;
+ iwl_mvm_init_link(new_link[i]);
}
mutex_lock(&mvm->mutex);
@@ -1388,6 +1372,36 @@ iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw,
return ret;
}
+#define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ)
+
+static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw *hw,
+ enum nl80211_iftype type)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
+ struct iwl_mvm_vif *mvmvif;
+ int ret;
+
+ IWL_DEBUG_MAC80211(mvm, "prep_add_interface: type=%u\n",
+ type);
+
+ if (IS_ERR_OR_NULL(bss_vif) ||
+ !(type == NL80211_IFTYPE_AP ||
+ type == NL80211_IFTYPE_P2P_GO ||
+ type == NL80211_IFTYPE_P2P_CLIENT))
+ return;
+
+ mvmvif = iwl_mvm_vif_from_mac80211(bss_vif);
+ ret = iwl_mvm_block_esr_sync(mvm, bss_vif,
+ IWL_MVM_ESR_BLOCKED_TMP_NON_BSS);
+ if (ret)
+ return;
+
+ wiphy_delayed_work_queue(mvmvif->mvm->hw->wiphy,
+ &mvmvif->unblock_esr_tmp_non_bss_wk,
+ IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT);
+}
+
const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.tx = iwl_mvm_mac_tx,
.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
@@ -1413,7 +1427,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
.release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
.set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
- .sta_rc_update = iwl_mvm_sta_rc_update,
+ .link_sta_rc_update = iwl_mvm_sta_rc_update,
.conf_tx = iwl_mvm_mld_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
@@ -1484,4 +1498,5 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.change_sta_links = iwl_mvm_mld_change_sta_links,
.can_activate_links = iwl_mvm_mld_can_activate_links,
.can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm,
+ .prep_add_interface = iwl_mvm_mld_prep_add_interface,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 28a9d90ad1cd..019839604011 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -146,7 +146,7 @@ int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
unsigned int wdg_timeout = _wdg_timeout ? *_wdg_timeout :
mvm->trans->trans_cfg->base_params->wd_timeout;
- if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(sta->sta_id == IWL_INVALID_STA))
return -ENOSPC;
if (sta->type == STATION_TYPE_AUX)
@@ -346,7 +346,7 @@ static int iwl_mvm_mld_rm_int_sta(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(int_sta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(int_sta->sta_id == IWL_INVALID_STA))
return -EINVAL;
if (flush)
@@ -521,6 +521,9 @@ void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm,
unsigned int link_id,
bool is_in_fw)
{
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+ lockdep_assert_held(&mvm->mutex);
+
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta_link->sta_id],
is_in_fw ? ERR_PTR(-EINVAL) : NULL);
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[mvm_sta_link->sta_id], NULL);
@@ -559,7 +562,10 @@ static int iwl_mvm_mld_alloc_sta_link(struct iwl_mvm *mvm,
u32 sta_id = iwl_mvm_find_free_sta_id(mvm,
ieee80211_vif_type_p2p(vif));
- if (sta_id == IWL_MVM_INVALID_STA)
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+ lockdep_assert_held(&mvm->mutex);
+
+ if (sta_id == IWL_INVALID_STA)
return -ENOSPC;
if (rcu_access_pointer(sta->link[link_id]) == &sta->deflink) {
@@ -612,10 +618,10 @@ static void iwl_mvm_mld_set_ap_sta_id(struct ieee80211_sta *sta,
struct iwl_mvm_link_sta *sta_link)
{
if (!sta->tdls) {
- WARN_ON(vif_link->ap_sta_id != IWL_MVM_INVALID_STA);
+ WARN_ON(vif_link->ap_sta_id != IWL_INVALID_STA);
vif_link->ap_sta_id = sta_link->sta_id;
} else {
- WARN_ON(vif_link->ap_sta_id == IWL_MVM_INVALID_STA);
+ WARN_ON(vif_link->ap_sta_id == IWL_INVALID_STA);
}
}
@@ -631,6 +637,9 @@ static int iwl_mvm_alloc_sta_after_restart(struct iwl_mvm *mvm,
int ret = -EINVAL;
int sta_id;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
+ lockdep_assert_held(&mvm->mutex);
+
/* First add an empty station since allocating a queue requires
* a valid station. Since we need a link_id to allocate a station,
* pick up the first valid one.
@@ -686,7 +695,7 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
spin_lock_init(&mvm_sta->lock);
- ret = iwl_mvm_sta_init(mvm, vif, sta, IWL_MVM_INVALID_STA,
+ ret = iwl_mvm_sta_init(mvm, vif, sta, IWL_INVALID_STA,
STATION_TYPE_PEER);
} else {
ret = iwl_mvm_alloc_sta_after_restart(mvm, vif, sta);
@@ -858,9 +867,10 @@ int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id)
{
int ret;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON(sta_id == IWL_INVALID_STA))
return 0;
ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
@@ -1064,6 +1074,7 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
unsigned int link_id;
int ret;
+ lockdep_assert_wiphy(mvm->hw->wiphy);
lockdep_assert_held(&mvm->mutex);
for_each_set_bit(link_id, &old_links_long,
@@ -1109,7 +1120,7 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
goto err;
if (vif->type == NL80211_IFTYPE_STATION)
- mvm_vif_link->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvm_vif_link->ap_sta_id = IWL_INVALID_STA;
iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_sta_link, link_id,
false);
@@ -1182,6 +1193,9 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
link_sta_added_to_fw |= BIT(link_id);
iwl_mvm_rs_add_sta_link(mvm, mvm_sta_link);
+
+ iwl_mvm_rs_rate_init(mvm, vif, sta, link_conf, link_sta,
+ link_conf->chanreq.oper.chan->band);
}
if (sta_mask_added) {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index ef07cff203b0..2ad615293c75 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -361,6 +361,9 @@ struct iwl_mvm_vif_link_info {
* @IWL_MVM_ESR_BLOCKED_NON_BSS: An active non-BSS interface's link is
* preventing EMLSR
* @IWL_MVM_ESR_BLOCKED_ROC: remain-on-channel is preventing EMLSR
+ * @IWL_MVM_ESR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's link
+ * is preventing EMLSR. This is a temporary blocking that is set when there
+ * is an indication that a non-BSS interface is to be added.
* @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons
* @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR
* due to low RSSI.
@@ -379,6 +382,7 @@ enum iwl_mvm_esr_state {
IWL_MVM_ESR_BLOCKED_FW = 0x8,
IWL_MVM_ESR_BLOCKED_NON_BSS = 0x10,
IWL_MVM_ESR_BLOCKED_ROC = 0x20,
+ IWL_MVM_ESR_BLOCKED_TMP_NON_BSS = 0x40,
IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000,
IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000,
IWL_MVM_ESR_EXIT_COEX = 0x40000,
@@ -452,6 +456,8 @@ struct iwl_mvm_esr_exit {
* @prevent_esr_done_wk: work that should be done when esr prevention ends.
* @mlo_int_scan_wk: work for the internal MLO scan.
* @unblock_esr_tpt_wk: work for unblocking EMLSR when tpt is high enough.
+ * @unblock_esr_tmp_non_bss_wk: work for removing the
+ * IWL_MVM_ESR_BLOCKED_TMP_NON_BSS blocking for EMLSR.
* @roc_activity: currently running ROC activity for this vif (or
* ROC_NUM_ACTIVITIES if no activity is running).
* @session_prot_connection_loss: the connection was lost due to session
@@ -588,6 +594,7 @@ struct iwl_mvm_vif {
struct wiphy_delayed_work prevent_esr_done_wk;
struct wiphy_delayed_work mlo_int_scan_wk;
struct wiphy_work unblock_esr_tpt_wk;
+ struct wiphy_delayed_work unblock_esr_tmp_non_bss_wk;
struct iwl_mvm_vif_link_info deflink;
struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
@@ -773,7 +780,6 @@ struct iwl_mvm_tcm {
* @head_sn: reorder window head sn
* @num_stored: number of mpdus stored in the buffer
* @queue: queue of this reorder buffer
- * @last_amsdu: track last ASMDU SN for duplication detection
* @valid: reordering is valid for this queue
* @lock: protect reorder buffer internal state
*/
@@ -781,7 +787,6 @@ struct iwl_mvm_reorder_buffer {
u16 head_sn;
u16 num_stored;
int queue;
- u16 last_amsdu;
bool valid;
spinlock_t lock;
} ____cacheline_aligned_in_smp;
@@ -1077,6 +1082,7 @@ struct iwl_mvm {
/* data related to data path */
struct iwl_rx_phy_info last_phy_info;
struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_STATION_COUNT_MAX];
+ /* note: fw_id_to_link_sta must be protected by wiphy and mvm mutexes */
struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX];
u8 rx_ba_sessions;
@@ -1584,8 +1590,7 @@ static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm)
static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm)
{
return fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_CSUM_SUPPORT) &&
- !IWL_MVM_HW_CSUM_DISABLE;
+ IWL_UCODE_TLV_CAPA_CSUM_SUPPORT);
}
static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm)
@@ -2100,6 +2105,7 @@ int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band);
/* Links */
+void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link);
int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -2327,7 +2333,7 @@ static inline int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
}
#endif
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
- struct iwl_wowlan_config_cmd *cmd);
+ struct iwl_wowlan_config_cmd_v6 *cmd);
int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool disable_offloading,
@@ -2914,7 +2920,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
bool more_data);
int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u32 changed);
+ struct ieee80211_link_sta *link_sta, u32 changed);
void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_prep_tx_info *info);
@@ -2982,7 +2988,8 @@ void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1,
struct iwl_mvm_vif *vif2);
bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif);
-int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+int iwl_mvm_set_tx_power(struct iwl_mvm *mvm,
+ struct ieee80211_bss_conf *bss_conf,
s16 tx_power);
int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
index 1eb21fe861e5..15d4369678a2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
@@ -10,7 +10,7 @@
#include "mvm.h"
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
- struct iwl_wowlan_config_cmd *cmd)
+ struct iwl_wowlan_config_cmd_v6 *cmd)
{
int i;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 4dd4a9d5c71f..e25d7570ffab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1505,8 +1505,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->scan_cmd_size = scan_size;
/* invalidate ids to prevent accidental removal of sta_id 0 */
- mvm->aux_sta.sta_id = IWL_MVM_INVALID_STA;
- mvm->snif_sta.sta_id = IWL_MVM_INVALID_STA;
+ mvm->aux_sta.sta_id = IWL_INVALID_STA;
+ mvm->snif_sta.sta_id = IWL_INVALID_STA;
/* Set EBS as successful as long as not stated otherwise by the FW. */
mvm->last_ebs_successful = true;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index 05715e5af6ab..de5ac000272e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -440,12 +440,6 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (!mvmsta) {
- IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n",
- notif->sta_id);
- goto out;
- }
-
flags = le32_to_cpu(notif->flags);
mvm_link_sta = rcu_dereference(mvmsta->link[link_sta->link_id]);
@@ -615,11 +609,8 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
int cmd_ver;
int ret;
- /* Enable external EHT LTF only for GL device and if there's
- * mutual support by AP and client
- */
- if (CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
- sband_eht_cap &&
+ /* Enable extra EHT LTF if there's mutual support by AP and client */
+ if (sband_eht_cap &&
sband_eht_cap->eht_cap_elem.phy_cap_info[5] &
IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF &&
link_sta->eht_cap.has_eht &&
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 1a0b5f8d4339..9e72db9bab40 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -560,7 +560,8 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
struct iwl_mvm_vif_link_info *link_info,
struct ieee80211_bss_conf *bss_conf)
{
- struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(vif)->mvm;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = mvmvif->mvm;
int thold = bss_conf->cqm_rssi_thold;
int hyst = bss_conf->cqm_rssi_hyst;
int last_event;
@@ -625,6 +626,13 @@ static void iwl_mvm_update_link_sig(struct ieee80211_vif *vif, int sig,
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
return;
+ /* We're not in EMLSR and our signal is bad, try to switch link maybe */
+ if (sig < IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH && !mvmvif->esr_active) {
+ iwl_mvm_int_mlo_scan(mvm, vif);
+ return;
+ }
+
+ /* We are in EMLSR, check if we need to exit */
exit_esr_thresh =
iwl_mvm_get_esr_rssi_thresh(mvm,
&bss_conf->chanreq.oper,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 65f8933c34b4..a2f16bfaec44 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -773,9 +773,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
return false;
}
- rcu_read_lock();
sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
- rcu_read_unlock();
if (IWL_FW_CHECK(mvm,
tid != baid_data->tid ||
@@ -814,7 +812,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
if (!amsdu || last_subframe)
buffer->head_sn = nssn;
- /* No need to update AMSDU last SN - we are moving the head */
+
spin_unlock_bh(&buffer->lock);
return false;
}
@@ -831,7 +829,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
if (!amsdu || last_subframe)
buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
- /* No need to update AMSDU last SN - we are moving the head */
spin_unlock_bh(&buffer->lock);
return false;
}
@@ -841,9 +838,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
__skb_queue_tail(&entries[index].frames, skb);
buffer->num_stored++;
- if (amsdu)
- buffer->last_amsdu = sn;
-
/*
* We cannot trust NSSN for AMSDU sub-frames that are not the last.
* The reason is that NSSN advances on the first sub-frame, and may
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index ddcbd80a49fb..376b9b12fa62 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -3597,7 +3597,8 @@ static int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm,
IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n",
n_channels);
- if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
+ if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif) ||
+ hweight16(vif->valid_links) == 1)
return -EINVAL;
size = struct_size(req, channels, n_channels);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index b6c99cd6d9e5..cd74c181c260 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -47,7 +47,7 @@ int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype)
lockdep_is_held(&mvm->mutex)))
return sta_id;
}
- return IWL_MVM_INVALID_STA;
+ return IWL_INVALID_STA;
}
/* Calculate the ampdu density and max size */
@@ -1216,7 +1216,7 @@ static bool iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm,
* can be unshared and finding one (and only one) that can be
* reused.
* This function is also invoked as a sort of clean-up task,
- * in which case @alloc_for_sta is IWL_MVM_INVALID_STA.
+ * in which case @alloc_for_sta is IWL_INVALID_STA.
*
* Returns the queue number, or -ENOSPC.
*/
@@ -1309,7 +1309,7 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta)
rcu_read_unlock();
- if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) {
+ if (free_queue >= 0 && alloc_for_sta != IWL_INVALID_STA) {
ret = iwl_mvm_free_inactive_queue(mvm, free_queue, queue_owner,
alloc_for_sta);
if (ret)
@@ -1522,7 +1522,7 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
mutex_lock(&mvm->mutex);
- iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA);
+ iwl_mvm_inactivity_check(mvm, IWL_INVALID_STA);
while (!list_empty(&mvm->add_stream_txqs)) {
struct iwl_mvm_txq *mvmtxq;
@@ -1580,7 +1580,7 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
return 0;
/* run the general cleanup/unsharing of queues */
- iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA);
+ iwl_mvm_inactivity_check(mvm, IWL_INVALID_STA);
/* Make sure we have free resources for this STA */
if (vif_type == NL80211_IFTYPE_STATION && !sta->tdls &&
@@ -1756,7 +1756,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* this function
*/
if (!mvm->mld_api_is_used) {
- if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON(sta_id == IWL_INVALID_STA))
return -EINVAL;
mvm_sta->deflink.sta_id = sta_id;
@@ -1865,7 +1865,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
else
sta_id = mvm_sta->deflink.sta_id;
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return -ENOSPC;
spin_lock_init(&mvm_sta->lock);
@@ -1903,10 +1903,10 @@ update_fw:
if (vif->type == NL80211_IFTYPE_STATION) {
if (!sta->tdls) {
- WARN_ON(mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA);
+ WARN_ON(mvmvif->deflink.ap_sta_id != IWL_INVALID_STA);
mvmvif->deflink.ap_sta_id = sta_id;
} else {
- WARN_ON(mvmvif->deflink.ap_sta_id == IWL_MVM_INVALID_STA);
+ WARN_ON(mvmvif->deflink.ap_sta_id == IWL_INVALID_STA);
}
}
@@ -2095,7 +2095,7 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_sec_key_remove_ap(mvm, vif, mvm_link, 0);
/* unassoc - go ahead - remove the AP STA now */
- mvm_link->ap_sta_id = IWL_MVM_INVALID_STA;
+ mvm_link->ap_sta_id = IWL_INVALID_STA;
}
/*
@@ -2103,7 +2103,7 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* before the STA is removed.
*/
if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == sta_id)) {
- mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA;
cancel_delayed_work(&mvm->tdls_cs.dwork);
}
@@ -2170,9 +2170,9 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
u8 type)
{
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
- sta->sta_id == IWL_MVM_INVALID_STA) {
+ sta->sta_id == IWL_INVALID_STA) {
sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
- if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(sta->sta_id == IWL_INVALID_STA))
return -ENOSPC;
}
@@ -2188,7 +2188,7 @@ void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
{
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
memset(sta, 0, sizeof(struct iwl_mvm_int_sta));
- sta->sta_id = IWL_MVM_INVALID_STA;
+ sta->sta_id = IWL_INVALID_STA;
}
static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue,
@@ -2306,7 +2306,7 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(mvm->snif_sta.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvm->snif_sta.sta_id == IWL_INVALID_STA))
return -EINVAL;
iwl_mvm_disable_txq(mvm, NULL, mvm->snif_sta.sta_id,
@@ -2324,7 +2324,7 @@ int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(mvm->aux_sta.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvm->aux_sta.sta_id == IWL_INVALID_STA))
return -EINVAL;
iwl_mvm_disable_txq(mvm, NULL, mvm->aux_sta.sta_id,
@@ -2389,7 +2389,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (vif->type == NL80211_IFTYPE_ADHOC)
baddr = vif->bss_conf.bssid;
- if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(bsta->sta_id == IWL_INVALID_STA))
return -ENOSPC;
ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
@@ -2644,7 +2644,7 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
u32 status;
/* This is a valid situation for GTK removal */
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return 0;
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
@@ -3514,7 +3514,7 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
* station ID, then use AP's station ID.
*/
if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ mvmvif->deflink.ap_sta_id != IWL_INVALID_STA) {
u8 sta_id = mvmvif->deflink.ap_sta_id;
sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
@@ -3569,7 +3569,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
int api_ver = iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA_KEY,
new_api ? 2 : 1);
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return -EINVAL;
keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) &
@@ -3728,7 +3728,7 @@ static int iwl_mvm_send_sta_igtk(struct iwl_mvm *mvm,
if (remove_key) {
/* This is a valid situation for IGTK */
- if (sta_id == IWL_MVM_INVALID_STA)
+ if (sta_id == IWL_INVALID_STA)
return 0;
igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_NOT_VALID);
@@ -3795,7 +3795,7 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
return sta->addr;
if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+ mvmvif->deflink.ap_sta_id != IWL_INVALID_STA) {
u8 sta_id = mvmvif->deflink.ap_sta_id;
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
lockdep_is_held(&mvm->mutex));
@@ -3865,7 +3865,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
{
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
struct iwl_mvm_sta *mvm_sta;
- u8 sta_id = IWL_MVM_INVALID_STA;
+ u8 sta_id = IWL_INVALID_STA;
int ret;
static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0};
@@ -3966,7 +3966,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
{
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
struct iwl_mvm_sta *mvm_sta;
- u8 sta_id = IWL_MVM_INVALID_STA;
+ u8 sta_id = IWL_INVALID_STA;
int ret, i;
lockdep_assert_held(&mvm->mutex);
@@ -4273,7 +4273,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
return;
/* Need to block/unblock also multicast station */
- if (mvmvif->deflink.mcast_sta.sta_id != IWL_MVM_INVALID_STA)
+ if (mvmvif->deflink.mcast_sta.sta_id != IWL_INVALID_STA)
iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
&mvmvif->deflink.mcast_sta,
disable);
@@ -4282,7 +4282,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
* Only unblock the broadcast station (FW blocks it for immediate
* quiet, not the driver)
*/
- if (!disable && mvmvif->deflink.bcast_sta.sta_id != IWL_MVM_INVALID_STA)
+ if (!disable && mvmvif->deflink.bcast_sta.sta_id != IWL_INVALID_STA)
iwl_mvm_int_sta_modify_disable_tx(mvm, mvmvif,
&mvmvif->deflink.bcast_sta,
disable);
@@ -4328,7 +4328,10 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
unsigned int wdg_timeout =
iwl_mvm_get_wd_timeout(mvm, vif);
bool mld = iwl_mvm_has_mld_api(mvm->fw);
- u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK;
+ u32 type = IWL_STA_LINK;
+
+ if (mld)
+ type = STATION_TYPE_PEER;
ret = iwl_mvm_allocate_int_sta(mvm, sta, 0,
NL80211_IFTYPE_UNSPECIFIED, type);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index 3d25ff5cd7e8..65927ebbabb7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -196,7 +196,7 @@ static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm,
mvm->tdls_cs.peer.sent_timestamp = iwl_mvm_get_systime(mvm);
if (state == IWL_MVM_TDLS_SW_IDLE)
- mvm->tdls_cs.cur_sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.cur_sta_id = IWL_INVALID_STA;
}
void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
@@ -250,7 +250,7 @@ iwl_mvm_tdls_check_action(struct iwl_mvm *mvm,
/* get the existing peer if it's there */
if (mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE &&
- mvm->tdls_cs.cur_sta_id != IWL_MVM_INVALID_STA) {
+ mvm->tdls_cs.cur_sta_id != IWL_INVALID_STA) {
struct ieee80211_sta *sta = rcu_dereference_protected(
mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
lockdep_is_held(&mvm->mutex));
@@ -465,7 +465,7 @@ void iwl_mvm_tdls_ch_switch_work(struct work_struct *work)
iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
/* station might be gone, in that case do nothing */
- if (mvm->tdls_cs.peer.sta_id == IWL_MVM_INVALID_STA)
+ if (mvm->tdls_cs.peer.sta_id == IWL_INVALID_STA)
return;
sta = rcu_dereference_protected(
@@ -512,7 +512,7 @@ iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
sta->addr, chandef->chan->center_freq, chandef->width);
/* we only support a single peer for channel switching */
- if (mvm->tdls_cs.peer.sta_id != IWL_MVM_INVALID_STA) {
+ if (mvm->tdls_cs.peer.sta_id != IWL_INVALID_STA) {
IWL_DEBUG_TDLS(mvm,
"Existing peer. Can't start switch with %pM\n",
sta->addr);
@@ -566,7 +566,7 @@ void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_TDLS(mvm, "TDLS cancel channel switch with %pM\n", sta->addr);
/* we only support a single peer for channel switching */
- if (mvm->tdls_cs.peer.sta_id == IWL_MVM_INVALID_STA) {
+ if (mvm->tdls_cs.peer.sta_id == IWL_INVALID_STA) {
IWL_DEBUG_TDLS(mvm, "No ch switch peer - %pM\n", sta->addr);
goto out;
}
@@ -587,7 +587,7 @@ void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE)
wait_for_phy = true;
- mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
+ mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA;
dev_kfree_skb(mvm->tdls_cs.peer.skb);
mvm->tdls_cs.peer.skb = NULL;
@@ -630,7 +630,7 @@ iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw,
if (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE &&
params->status != 0 &&
mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
- mvm->tdls_cs.cur_sta_id != IWL_MVM_INVALID_STA) {
+ mvm->tdls_cs.cur_sta_id != IWL_INVALID_STA) {
struct ieee80211_sta *cur_sta;
/* make sure it's the same peer */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index ca026b5256ce..c9867d26361b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1213,7 +1213,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc))
return -1;
- if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_INVALID_STA))
return -1;
if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->deflink.he_cap.has_he)
@@ -1357,7 +1357,7 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_MVM_INVALID_STA))
+ if (WARN_ON_ONCE(mvmsta->deflink.sta_id == IWL_INVALID_STA))
return -1;
memcpy(&info, skb->cb, sizeof(info));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 1d1364d03f02..dd890dcd1505 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -261,7 +261,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
.data = { lq, },
};
- if (WARN_ON(lq->sta_id == IWL_MVM_INVALID_STA ||
+ if (WARN_ON(lq->sta_id == IWL_INVALID_STA ||
iwl_mvm_has_tlc_offload(mvm)))
return -EINVAL;
@@ -679,10 +679,8 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bss_iface_iterator, &bss_iter_data);
- if (bss_iter_data.error) {
- IWL_ERR(mvm, "More than one managed interface active!\n");
+ if (bss_iter_data.error)
return ERR_PTR(-EINVAL);
- }
return bss_iter_data.vif;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 3b9943eb6934..86f1d87a909c 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1643,6 +1643,8 @@ int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
out:
if (*status == IWL_D3_STATUS_ALIVE)
ret = iwl_pcie_d3_handshake(trans, false);
+ else
+ trans->state = IWL_TRANS_NO_FW;
return ret;
}
@@ -3533,7 +3535,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
struct iwl_trans_pcie *trans_pcie, **priv;
struct iwl_trans *trans;
int ret, addr_size;
- void __iomem * const *table;
u32 bar0;
/* reassign our BAR 0 if invalid due to possible runtime PM races */
@@ -3659,22 +3660,15 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
}
- ret = pcim_iomap_regions_request_all(pdev, BIT(0), DRV_NAME);
+ ret = pcim_request_all_regions(pdev, DRV_NAME);
if (ret) {
- dev_err(&pdev->dev, "pcim_iomap_regions_request_all failed\n");
- goto out_no_pci;
- }
-
- table = pcim_iomap_table(pdev);
- if (!table) {
- dev_err(&pdev->dev, "pcim_iomap_table failed\n");
- ret = -ENOMEM;
+ dev_err(&pdev->dev, "Requesting all PCI BARs failed.\n");
goto out_no_pci;
}
- trans_pcie->hw_base = table[0];
+ trans_pcie->hw_base = pcim_iomap(pdev, 0, 0);
if (!trans_pcie->hw_base) {
- dev_err(&pdev->dev, "couldn't find IO mem in first BAR\n");
+ dev_err(&pdev->dev, "Could not ioremap PCI BAR 0.\n");
ret = -ENODEV;
goto out_no_pci;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 9fe050f0ddc1..1ef14340953c 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -2351,6 +2351,10 @@ void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
txq_write_ptr = txq->write_ptr;
spin_unlock(&txq->lock);
+ /* There is nothing to do if we are flushing an empty queue */
+ if (is_flush && txq_write_ptr == txq_read_ptr)
+ goto out;
+
read_ptr = iwl_txq_get_cmd_index(txq, txq_read_ptr);
if (!test_bit(txq_id, trans_pcie->txqs.queue_used)) {
diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c
index d33a994906a7..27f44a9f0bc1 100644
--- a/drivers/net/wireless/intersil/p54/p54spi.c
+++ b/drivers/net/wireless/intersil/p54/p54spi.c
@@ -624,7 +624,7 @@ static int p54spi_probe(struct spi_device *spi)
gpio_direction_input(p54spi_gpio_irq);
ret = request_irq(gpio_to_irq(p54spi_gpio_irq),
- p54spi_interrupt, 0, "p54spi",
+ p54spi_interrupt, IRQF_NO_AUTOEN, "p54spi",
priv->spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "request_irq() failed");
@@ -633,8 +633,6 @@ static int p54spi_probe(struct spi_device *spi)
irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
- disable_irq(gpio_to_irq(p54spi_gpio_irq));
-
INIT_WORK(&priv->work, p54spi_work);
init_completion(&priv->fw_comp);
INIT_LIST_HEAD(&priv->tx_pending);
diff --git a/drivers/net/wireless/marvell/libertas/Kconfig b/drivers/net/wireless/marvell/libertas/Kconfig
index 36b234bc5be8..caf8bc231b2e 100644
--- a/drivers/net/wireless/marvell/libertas/Kconfig
+++ b/drivers/net/wireless/marvell/libertas/Kconfig
@@ -3,7 +3,6 @@ config LIBERTAS
tristate "Marvell 8xxx Libertas WLAN driver support"
depends on USB || MMC || SPI
depends on CFG80211
- select LIB80211
select FW_LOADER
help
A library for Marvell Libertas 8xxx devices.
diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c
index afe9bcd3ad46..2e2c193716d9 100644
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -486,6 +486,7 @@ static int lbs_add_wps_enrollee_tlv(u8 *tlv, const u8 *ie, size_t ie_len)
*/
static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct lbs_private *priv = wiphy_priv(wiphy);
diff --git a/drivers/net/wireless/marvell/libertas/mesh.h b/drivers/net/wireless/marvell/libertas/mesh.h
index 44c4cd0230a8..e37db10e82a9 100644
--- a/drivers/net/wireless/marvell/libertas/mesh.h
+++ b/drivers/net/wireless/marvell/libertas/mesh.h
@@ -7,7 +7,6 @@
#include <net/iw_handler.h>
-#include <net/lib80211.h>
#include "host.h"
#include "dev.h"
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 1cff001bdc51..b30ed321c625 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -938,8 +938,10 @@ void mwifiex_process_assoc_resp(struct mwifiex_adapter *adapter)
assoc_resp.links[0].bss = priv->req_bss;
assoc_resp.buf = priv->assoc_rsp_buf;
assoc_resp.len = priv->assoc_rsp_size;
+ wiphy_lock(priv->wdev.wiphy);
cfg80211_rx_assoc_resp(priv->netdev,
&assoc_resp);
+ wiphy_unlock(priv->wdev.wiphy);
priv->assoc_rsp_size = 0;
}
}
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index d03129d5d24e..4a96281792cc 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -875,7 +875,7 @@ struct mwifiex_ietypes_chanstats {
struct mwifiex_ie_types_wildcard_ssid_params {
struct mwifiex_ie_types_header header;
u8 max_ssid_length;
- u8 ssid[1];
+ u8 ssid[];
} __packed;
#define TSF_DATA_SIZE 8
diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h
index 516159b721d3..74747d3a379a 100644
--- a/drivers/net/wireless/marvell/mwifiex/ioctl.h
+++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h
@@ -8,7 +8,7 @@
#ifndef _MWIFIEX_IOCTL_H_
#define _MWIFIEX_IOCTL_H_
-#include <net/lib80211.h>
+#define NUM_WEP_KEYS 4
enum {
MWIFIEX_SCAN_TYPE_UNCHANGED = 0,
diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c
index 6d8f1d1d7ca4..5a1a0287c1d5 100644
--- a/drivers/net/wireless/marvell/mwifiex/join.c
+++ b/drivers/net/wireless/marvell/mwifiex/join.c
@@ -663,7 +663,6 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
bool enable_data = true;
u16 cap_info, status_code, aid;
const u8 *ie_ptr;
- struct ieee80211_ht_operation *assoc_resp_ht_oper;
if (!priv->attempted_bss_desc) {
mwifiex_dbg(priv->adapter, ERROR,
@@ -779,14 +778,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
ie_ptr = cfg80211_find_ie(WLAN_EID_HT_OPERATION, assoc_rsp->ie_buffer,
priv->assoc_rsp_size
- sizeof(struct ieee_types_assoc_rsp));
- if (ie_ptr) {
- assoc_resp_ht_oper = (struct ieee80211_ht_operation *)(ie_ptr
- + sizeof(struct ieee_types_header));
- priv->assoc_resp_ht_param = assoc_resp_ht_oper->ht_param;
- priv->ht_param_present = true;
- } else {
- priv->ht_param_present = false;
- }
+
+ priv->ht_param_present = ie_ptr ? true : false;
mwifiex_dbg(priv->adapter, INFO,
"info: ASSOC_RESP: curr_pkt_filter is %#x\n",
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 96d1f6039fbc..855019fe5485 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1679,7 +1679,8 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
}
ret = devm_request_irq(dev, adapter->irq_wakeup,
- mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
+ mwifiex_irq_wakeup_handler,
+ IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN,
"wifi_wake", adapter);
if (ret) {
dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
@@ -1687,7 +1688,6 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
goto err_exit;
}
- disable_irq(adapter->irq_wakeup);
if (device_init_wakeup(dev, true)) {
dev_err(dev, "fail to init wakeup for mwifiex\n");
goto err_exit;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 566adce3413c..0674dcf7a537 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -19,7 +19,6 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <net/sock.h>
-#include <net/lib80211.h>
#include <linux/vmalloc.h>
#include <linux/firmware.h>
#include <linux/ctype.h>
@@ -574,7 +573,6 @@ struct mwifiex_private {
u16 listen_interval;
u16 atim_window;
u8 adhoc_channel;
- u8 adhoc_is_link_sensed;
u8 adhoc_state;
struct mwifiex_802_11_security sec_info;
struct mwifiex_wep_key wep_key[NUM_WEP_KEYS];
@@ -683,7 +681,6 @@ struct mwifiex_private {
struct mwifiex_ds_mem_rw mem_rw;
struct sk_buff_head bypass_txq;
struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
- u8 assoc_resp_ht_param;
bool ht_param_present;
};
@@ -802,7 +799,6 @@ struct mwifiex_auto_tdls_peer {
unsigned long rssi_jiffies;
u8 failure_count;
u8 do_discover;
- u8 do_setup;
};
#define MWIFIEX_TYPE_AGGR_DATA_V2 11
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index b5f3821a6a8f..400348abeee5 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -177,17 +177,14 @@ void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code,
priv->is_data_rate_auto = true;
priv->data_rate = 0;
- priv->assoc_resp_ht_param = 0;
priv->ht_param_present = false;
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data)
mwifiex_hist_data_reset(priv);
- if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
priv->adhoc_state = ADHOC_IDLE;
- priv->adhoc_is_link_sensed = false;
- }
/*
* Memorize the previous SSID and BSSID so
@@ -843,7 +840,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
case EVENT_ADHOC_BCN_LOST:
mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n");
- priv->adhoc_is_link_sensed = false;
mwifiex_clean_txrx(priv);
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
if (netif_carrier_ok(priv->netdev))
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
index d3cba6895f8c..e06a0622973e 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
@@ -351,8 +351,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
goto done;
}
- priv->adhoc_is_link_sensed = false;
-
ret = mwifiex_check_network_compatibility(priv, bss_desc);
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
index 7823e67694e8..0a5f340876c3 100644
--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -1306,7 +1306,6 @@ int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
peer->mac_addr,
NL80211_TDLS_SETUP,
0, GFP_ATOMIC);
- peer->do_setup = false;
priv->check_tdls_tx = false;
} else if (peer->failure_count <
MWIFIEX_TDLS_MAX_FAIL_COUNT &&
@@ -1465,7 +1464,6 @@ void mwifiex_check_auto_tdls(struct timer_list *t)
tdls_peer->failure_count <
MWIFIEX_TDLS_MAX_FAIL_COUNT) {
priv->check_tdls_tx = true;
- tdls_peer->do_setup = true;
mwifiex_dbg(priv->adapter, INFO,
"check TDLS with peer=%pM\t"
"rssi=%d\n", tdls_peer->mac_addr,
diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c
index 42c04bf858da..1f1f6280a0f2 100644
--- a/drivers/net/wireless/marvell/mwifiex/util.c
+++ b/drivers/net/wireless/marvell/mwifiex/util.c
@@ -494,7 +494,9 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
}
}
+ wiphy_lock(priv->wdev.wiphy);
cfg80211_rx_mlme_mgmt(priv->netdev, skb->data, pkt_len);
+ wiphy_unlock(priv->wdev.wiphy);
}
if (priv->adapter->host_mlme_enabled &&
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c
index ec02148a7f1f..08590aa68356 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c
@@ -71,7 +71,7 @@ MODULE_FIRMWARE(MT7628_FIRMWARE_E2);
struct platform_driver mt76_wmac_driver = {
.probe = mt76_wmac_probe,
- .remove_new = mt76_wmac_remove,
+ .remove = mt76_wmac_remove,
.driver = {
.name = "mt76_wmac",
.of_match_table = of_wmac_match,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c
index 12e3e4a91d27..06a0f2a141e8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c
@@ -63,7 +63,7 @@ struct platform_driver mt7622_wmac_driver = {
.of_match_table = mt7622_wmac_of_match,
},
.probe = mt7622_wmac_probe,
- .remove_new = mt7622_wmac_remove,
+ .remove = mt7622_wmac_remove,
};
MODULE_FIRMWARE(MT7622_FIRMWARE_N9);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index d75e8dea1fbd..c6f498fc81ff 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -1163,9 +1163,10 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_dev *dev = phy->dev;
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
@@ -1709,7 +1710,7 @@ const struct ieee80211_ops mt7915_ops = {
.stop_ap = mt7915_stop_ap,
.sta_state = mt76_sta_state,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
- .sta_rc_update = mt7915_sta_rc_update,
+ .link_sta_rc_update = mt7915_sta_rc_update,
.set_key = mt7915_set_key,
.ampdu_action = mt7915_ampdu_action,
.set_rts_threshold = mt7915_set_rts_threshold,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
index 90a6f61d1089..c823a7554a3a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
@@ -1303,7 +1303,7 @@ struct platform_driver mt798x_wmac_driver = {
.of_match_table = mt798x_wmac_of_match,
},
.probe = mt798x_wmac_probe,
- .remove_new = mt798x_wmac_remove,
+ .remove = mt798x_wmac_remove,
};
MODULE_FIRMWARE(MT7986_FIRMWARE_WA);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 39f071ece35e..2b34ae5e0cb5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1060,9 +1060,10 @@ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
static void mt7996_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_dev *dev = phy->dev;
@@ -1472,7 +1473,7 @@ const struct ieee80211_ops mt7996_ops = {
.sta_add = mt7996_sta_add,
.sta_remove = mt7996_sta_remove,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
- .sta_rc_update = mt7996_sta_rc_update,
+ .link_sta_rc_update = mt7996_sta_rc_update,
.set_key = mt7996_set_key,
.ampdu_action = mt7996_ampdu_action,
.set_rts_threshold = mt7996_set_rts_threshold,
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index eb37b228d54e..e96736cc7259 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -231,6 +231,7 @@ struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
}
static int set_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct wilc *wl = wiphy_priv(wiphy);
@@ -1424,7 +1425,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
struct wilc_vif *vif = netdev_priv(dev);
int ret;
- ret = set_channel(wiphy, &settings->chandef);
+ ret = set_channel(wiphy, dev, &settings->chandef);
if (ret != 0)
netdev_err(dev, "Error in setting channel\n");
@@ -1757,57 +1758,10 @@ void wlan_deinit_locks(struct wilc *wilc)
cleanup_srcu_struct(&wilc->srcu);
}
-int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
- const struct wilc_hif_func *ops)
-{
- struct wilc *wl;
- int ret, i;
-
- wl = wilc_create_wiphy(dev);
- if (!wl)
- return -EINVAL;
-
- wlan_init_locks(wl);
-
- ret = wilc_wlan_cfg_init(wl);
- if (ret)
- goto free_wl;
-
- *wilc = wl;
- wl->io_type = io_type;
- wl->hif_func = ops;
-
- for (i = 0; i < NQUEUES; i++)
- INIT_LIST_HEAD(&wl->txq[i].txq_head.list);
-
- INIT_LIST_HEAD(&wl->rxq_head.list);
- INIT_LIST_HEAD(&wl->vif_list);
-
- wl->hif_workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,
- wiphy_name(wl->wiphy));
- if (!wl->hif_workqueue) {
- ret = -ENOMEM;
- goto free_cfg;
- }
-
- return 0;
-
-free_cfg:
- wilc_wlan_cfg_deinit(wl);
-
-free_wl:
- wlan_deinit_locks(wl);
- wiphy_unregister(wl->wiphy);
- wiphy_free(wl->wiphy);
- return ret;
-}
-EXPORT_SYMBOL_GPL(wilc_cfg80211_init);
-
-struct wilc *wilc_create_wiphy(struct device *dev)
+static struct wilc *wilc_create_wiphy(struct device *dev)
{
struct wiphy *wiphy;
struct wilc *wl;
- int ret;
wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(*wl));
if (!wiphy)
@@ -1850,17 +1804,66 @@ struct wilc *wilc_create_wiphy(struct device *dev)
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT);
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- wiphy->features |= NL80211_FEATURE_SAE;
set_wiphy_dev(wiphy, dev);
wl->wiphy = wiphy;
- ret = wiphy_register(wiphy);
- if (ret) {
- wiphy_free(wiphy);
- return NULL;
- }
return wl;
}
+int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
+ const struct wilc_hif_func *ops)
+{
+ struct wilc *wl;
+ int ret, i;
+
+ wl = wilc_create_wiphy(dev);
+ if (!wl)
+ return -EINVAL;
+
+ wlan_init_locks(wl);
+
+ ret = wilc_wlan_cfg_init(wl);
+ if (ret)
+ goto free_wl;
+
+ *wilc = wl;
+ wl->io_type = io_type;
+ wl->hif_func = ops;
+
+ for (i = 0; i < NQUEUES; i++)
+ INIT_LIST_HEAD(&wl->txq[i].txq_head.list);
+
+ INIT_LIST_HEAD(&wl->rxq_head.list);
+ INIT_LIST_HEAD(&wl->vif_list);
+
+ wl->hif_workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,
+ wiphy_name(wl->wiphy));
+ if (!wl->hif_workqueue) {
+ ret = -ENOMEM;
+ goto free_cfg;
+ }
+
+ return 0;
+
+free_cfg:
+ wilc_wlan_cfg_deinit(wl);
+
+free_wl:
+ wlan_deinit_locks(wl);
+ wiphy_free(wl->wiphy);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wilc_cfg80211_init);
+
+int wilc_cfg80211_register(struct wilc *wilc)
+{
+ /* WPA3/SAE supported only on WILC1000 */
+ if (is_wilc1000(wilc->chipid))
+ wilc->wiphy->features |= NL80211_FEATURE_SAE;
+
+ return wiphy_register(wilc->wiphy);
+}
+EXPORT_SYMBOL_GPL(wilc_cfg80211_register);
+
int wilc_init_host_int(struct net_device *net)
{
int ret;
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.h b/drivers/net/wireless/microchip/wilc1000/cfg80211.h
index 8c65951cfaf9..2dc9c1c42d60 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.h
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.h
@@ -10,7 +10,7 @@
int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
const struct wilc_hif_func *ops);
-struct wilc *wilc_create_wiphy(struct device *dev);
+int wilc_cfg80211_register(struct wilc *wilc);
void wilc_deinit_host_int(struct net_device *net);
int wilc_init_host_int(struct net_device *net);
void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size);
diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c
index 9ecf3fb29b55..7e84fc0fd911 100644
--- a/drivers/net/wireless/microchip/wilc1000/netdev.c
+++ b/drivers/net/wireless/microchip/wilc1000/netdev.c
@@ -23,6 +23,12 @@
#define __WILC1000_FW(api) WILC1000_FW_PREFIX #api ".bin"
#define WILC1000_FW(api) __WILC1000_FW(api)
+#define WILC3000_API_VER 1
+
+#define WILC3000_FW_PREFIX "atmel/wilc3000_wifi_firmware-"
+#define __WILC3000_FW(api) WILC3000_FW_PREFIX #api ".bin"
+#define WILC3000_FW(api) __WILC3000_FW(api)
+
static irqreturn_t isr_uh_routine(int irq, void *user_data)
{
struct wilc *wilc = user_data;
@@ -195,20 +201,24 @@ static int wilc_wlan_get_firmware(struct net_device *dev)
{
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc;
- int chip_id;
const struct firmware *wilc_fw;
+ char *firmware;
int ret;
- chip_id = wilc_get_chipid(wilc, false);
+ if (is_wilc1000(wilc->chipid))
+ firmware = WILC1000_FW(WILC1000_API_VER);
+ else if (is_wilc3000(wilc->chipid))
+ firmware = WILC3000_FW(WILC3000_API_VER);
+ else
+ return -EINVAL;
- netdev_info(dev, "ChipID [%x] loading firmware [%s]\n", chip_id,
- WILC1000_FW(WILC1000_API_VER));
+ netdev_info(dev, "WILC%d loading firmware [%s]\n",
+ is_wilc1000(wilc->chipid) ? 1000 : 3000,
+ firmware);
- ret = request_firmware(&wilc_fw, WILC1000_FW(WILC1000_API_VER),
- wilc->dev);
+ ret = request_firmware(&wilc_fw, firmware, wilc->dev);
if (ret != 0) {
- netdev_err(dev, "%s - firmware not available\n",
- WILC1000_FW(WILC1000_API_VER));
+ netdev_err(dev, "%s - firmware not available\n", firmware);
return -EINVAL;
}
wilc->firmware = wilc_fw;
@@ -233,7 +243,7 @@ static int wilc_start_firmware(struct net_device *dev)
return 0;
}
-static int wilc1000_firmware_download(struct net_device *dev)
+static int wilc_firmware_download(struct net_device *dev)
{
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc;
@@ -528,7 +538,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
if (ret)
goto fail_irq_enable;
- ret = wilc1000_firmware_download(dev);
+ ret = wilc_firmware_download(dev);
if (ret)
goto fail_irq_enable;
@@ -608,6 +618,9 @@ static int wilc_mac_open(struct net_device *ndev)
return ret;
}
+ wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype,
+ vif->idx);
+
netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr);
ret = wilc_set_mac_address(vif, ndev->dev_addr);
if (ret) {
@@ -618,9 +631,6 @@ static int wilc_mac_open(struct net_device *ndev)
return ret;
}
- wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype,
- vif->idx);
-
mgmt_regs.interface_stypes = vif->mgmt_reg_stypes;
/* so we detect a change */
vif->mgmt_reg_stypes = 0;
@@ -1014,3 +1024,4 @@ EXPORT_SYMBOL_GPL(wilc_netdev_ifc_init);
MODULE_DESCRIPTION("Atmel WILC1000 core wireless driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER));
+MODULE_FIRMWARE(WILC3000_FW(WILC3000_API_VER));
diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c
index b4da05d5a498..5262c8846c13 100644
--- a/drivers/net/wireless/microchip/wilc1000/sdio.c
+++ b/drivers/net/wireless/microchip/wilc1000/sdio.c
@@ -182,6 +182,14 @@ static int wilc_sdio_probe(struct sdio_func *func,
wilc_sdio_init(wilc, false);
+ ret = wilc_get_chipid(wilc);
+ if (ret)
+ goto dispose_irq;
+
+ ret = wilc_cfg80211_register(wilc);
+ if (ret)
+ goto dispose_irq;
+
ret = wilc_load_mac_from_nv(wilc);
if (ret) {
pr_err("Can not retrieve MAC address from chip\n");
@@ -667,7 +675,6 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume)
struct wilc_sdio *sdio_priv = wilc->bus_data;
struct sdio_cmd52 cmd;
int loop, ret;
- u32 chipid;
/**
* function 0 csa enable
@@ -756,18 +763,6 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume)
return ret;
}
- /**
- * make sure can read back chip id correctly
- **/
- if (!resume) {
- ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
- if (ret) {
- dev_err(&func->dev, "Fail cmd read chip id...\n");
- return ret;
- }
- dev_err(&func->dev, "chipid (%08x)\n", chipid);
- }
-
sdio_priv->isinit = true;
return 0;
}
@@ -815,13 +810,19 @@ static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status)
cmd.address = WILC_SDIO_EXT_IRQ_FLAG_REG;
} else {
cmd.function = 0;
- cmd.address = WILC_SDIO_IRQ_FLAG_REG;
+ cmd.address = is_wilc1000(wilc->chipid) ?
+ WILC1000_SDIO_IRQ_FLAG_REG :
+ WILC3000_SDIO_IRQ_FLAG_REG;
}
cmd.raw = 0;
cmd.read_write = 0;
cmd.data = 0;
wilc_sdio_cmd52(wilc, &cmd);
irq_flags = cmd.data;
+
+ if (sdio_priv->irq_gpio)
+ irq_flags &= is_wilc1000(wilc->chipid) ? 0x1f : 0x0f;
+
tmp |= FIELD_PREP(IRG_FLAGS_MASK, cmd.data);
if (FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags))
@@ -843,22 +844,56 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val)
if (sdio_priv->irq_gpio)
reg = val & (BIT(MAX_NUM_INT) - 1);
- /* select VMM table 0 */
- if (val & SEL_VMM_TBL0)
- reg |= BIT(5);
- /* select VMM table 1 */
- if (val & SEL_VMM_TBL1)
- reg |= BIT(6);
- /* enable VMM */
- if (val & EN_VMM)
- reg |= BIT(7);
+ if (is_wilc1000(wilc->chipid)) {
+ /* select VMM table 0 */
+ if (val & SEL_VMM_TBL0)
+ reg |= BIT(5);
+ /* select VMM table 1 */
+ if (val & SEL_VMM_TBL1)
+ reg |= BIT(6);
+ /* enable VMM */
+ if (val & EN_VMM)
+ reg |= BIT(7);
+ } else {
+ if (sdio_priv->irq_gpio && reg) {
+ struct sdio_cmd52 cmd;
+
+ cmd.read_write = 1;
+ cmd.function = 0;
+ cmd.raw = 0;
+ cmd.address = WILC3000_SDIO_IRQ_FLAG_REG;
+ cmd.data = reg;
+
+ ret = wilc_sdio_cmd52(wilc, &cmd);
+ if (ret) {
+ dev_err(&func->dev,
+ "Failed cmd52, set 0xfe data (%d) ...\n",
+ __LINE__);
+ return ret;
+ }
+ }
+
+ reg = 0;
+ /* select VMM table 0 */
+ if (val & SEL_VMM_TBL0)
+ reg |= BIT(0);
+ /* select VMM table 1 */
+ if (val & SEL_VMM_TBL1)
+ reg |= BIT(1);
+ /* enable VMM */
+ if (val & EN_VMM)
+ reg |= BIT(2);
+ }
+
if (reg) {
struct sdio_cmd52 cmd;
cmd.read_write = 1;
cmd.function = 0;
cmd.raw = 0;
- cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG;
+ cmd.address = is_wilc1000(wilc->chipid) ?
+ WILC1000_SDIO_IRQ_CLEAR_FLAG_REG :
+ WILC3000_SDIO_VMM_TBL_CTRL_REG;
cmd.data = reg;
ret = wilc_sdio_cmd52(wilc, &cmd);
@@ -979,17 +1014,15 @@ static int wilc_sdio_suspend(struct device *dev)
if (!IS_ERR(wilc->rtc_clk))
clk_disable_unprepare(wilc->rtc_clk);
- host_sleep_notify(wilc);
-
- wilc_sdio_disable_interrupt(wilc);
-
- ret = wilc_sdio_reset(wilc);
+ ret = host_sleep_notify(wilc);
if (ret) {
- dev_err(&func->dev, "Fail reset sdio\n");
+ clk_prepare_enable(wilc->rtc_clk);
return ret;
}
- return 0;
+ wilc_sdio_disable_interrupt(wilc);
+
+ return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
}
static int wilc_sdio_resume(struct device *dev)
@@ -1008,9 +1041,7 @@ static int wilc_sdio_resume(struct device *dev)
wilc_sdio_init(wilc, true);
wilc_sdio_enable_interrupt(wilc);
- host_wakeup_notify(wilc);
-
- return 0;
+ return host_wakeup_notify(wilc);
}
static const struct of_device_id wilc_of_match[] = {
diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c
index 05b577b1068e..ce2a9cdd6aa7 100644
--- a/drivers/net/wireless/microchip/wilc1000/spi.c
+++ b/drivers/net/wireless/microchip/wilc1000/spi.c
@@ -245,7 +245,11 @@ static int wilc_bus_probe(struct spi_device *spi)
if (ret)
goto power_down;
- ret = wilc_validate_chipid(wilc);
+ ret = wilc_get_chipid(wilc);
+ if (ret)
+ goto power_down;
+
+ ret = wilc_cfg80211_register(wilc);
if (ret)
goto power_down;
@@ -1229,7 +1233,7 @@ static int wilc_validate_chipid(struct wilc *wilc)
dev_err(&spi->dev, "Fail cmd read chip id...\n");
return ret;
}
- if (!is_wilc1000(chipid)) {
+ if (!is_wilc1000(chipid) && !is_wilc3000(chipid)) {
dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid);
return -ENODEV;
}
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
index 533939e71534..9d80adc45d6b 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
@@ -12,20 +12,6 @@
#define WAKE_UP_TRIAL_RETRY 10000
-static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
-{
- mutex_lock(&wilc->hif_cs);
- if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode)
- chip_wakeup(wilc);
-}
-
-static inline void release_bus(struct wilc *wilc, enum bus_release release)
-{
- if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode)
- chip_allow_sleep(wilc);
- mutex_unlock(&wilc->hif_cs);
-}
-
static void wilc_wlan_txq_remove(struct wilc *wilc, u8 q_num,
struct txq_entry_t *tqe)
{
@@ -555,7 +541,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
return rqe;
}
-void chip_allow_sleep(struct wilc *wilc)
+static int chip_allow_sleep_wilc1000(struct wilc *wilc)
{
u32 reg = 0;
const struct wilc_hif_func *hif_func = wilc->hif_func;
@@ -584,7 +570,7 @@ void chip_allow_sleep(struct wilc *wilc)
while (--trials) {
ret = hif_func->hif_read_reg(wilc, to_host_from_fw_reg, &reg);
if (ret)
- return;
+ return ret;
if ((reg & to_host_from_fw_bit) == 0)
break;
}
@@ -594,28 +580,62 @@ void chip_allow_sleep(struct wilc *wilc)
/* Clear bit 1 */
ret = hif_func->hif_read_reg(wilc, wakeup_reg, &reg);
if (ret)
- return;
+ return ret;
if (reg & wakeup_bit) {
reg &= ~wakeup_bit;
ret = hif_func->hif_write_reg(wilc, wakeup_reg, reg);
if (ret)
- return;
+ return ret;
}
ret = hif_func->hif_read_reg(wilc, from_host_to_fw_reg, &reg);
if (ret)
- return;
+ return ret;
if (reg & from_host_to_fw_bit) {
reg &= ~from_host_to_fw_bit;
ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, reg);
if (ret)
- return;
+ return ret;
+ }
+ return 0;
+}
+
+static int chip_allow_sleep_wilc3000(struct wilc *wilc)
+{
+ u32 reg = 0;
+ int ret;
+ const struct wilc_hif_func *hif_func = wilc->hif_func;
+
+ if (wilc->io_type == WILC_HIF_SDIO) {
+ ret = hif_func->hif_read_reg(wilc, WILC_SDIO_WAKEUP_REG, &reg);
+ if (ret)
+ return ret;
+ ret = hif_func->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG,
+ reg & ~WILC_SDIO_WAKEUP_BIT);
+ if (ret)
+ return ret;
+ } else {
+ ret = hif_func->hif_read_reg(wilc, WILC_SPI_WAKEUP_REG, &reg);
+ if (ret)
+ return ret;
+ ret = hif_func->hif_write_reg(wilc, WILC_SPI_WAKEUP_REG,
+ reg & ~WILC_SPI_WAKEUP_BIT);
+ if (ret)
+ return ret;
}
+ return 0;
+}
+
+static int chip_allow_sleep(struct wilc *wilc)
+{
+ if (is_wilc1000(wilc->chipid))
+ return chip_allow_sleep_wilc1000(wilc);
+ else
+ return chip_allow_sleep_wilc3000(wilc);
}
-EXPORT_SYMBOL_GPL(chip_allow_sleep);
-void chip_wakeup(struct wilc *wilc)
+static int chip_wakeup_wilc1000(struct wilc *wilc)
{
u32 ret = 0;
u32 clk_status_val = 0, trials = 0;
@@ -627,15 +647,15 @@ void chip_wakeup(struct wilc *wilc)
if (wilc->io_type == WILC_HIF_SDIO) {
wakeup_reg = WILC_SDIO_WAKEUP_REG;
wakeup_bit = WILC_SDIO_WAKEUP_BIT;
- clk_status_reg = WILC_SDIO_CLK_STATUS_REG;
- clk_status_bit = WILC_SDIO_CLK_STATUS_BIT;
+ clk_status_reg = WILC1000_SDIO_CLK_STATUS_REG;
+ clk_status_bit = WILC1000_SDIO_CLK_STATUS_BIT;
from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG;
from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT;
} else {
wakeup_reg = WILC_SPI_WAKEUP_REG;
wakeup_bit = WILC_SPI_WAKEUP_BIT;
- clk_status_reg = WILC_SPI_CLK_STATUS_REG;
- clk_status_bit = WILC_SPI_CLK_STATUS_BIT;
+ clk_status_reg = WILC1000_SPI_CLK_STATUS_REG;
+ clk_status_bit = WILC1000_SPI_CLK_STATUS_BIT;
from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG;
from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT;
}
@@ -644,20 +664,20 @@ void chip_wakeup(struct wilc *wilc)
ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,
from_host_to_fw_bit);
if (ret)
- return;
+ return ret;
/* Set wake-up bit */
ret = hif_func->hif_write_reg(wilc, wakeup_reg,
wakeup_bit);
if (ret)
- return;
+ return ret;
while (trials < WAKE_UP_TRIAL_RETRY) {
ret = hif_func->hif_read_reg(wilc, clk_status_reg,
&clk_status_val);
if (ret) {
pr_err("Bus error %d %x\n", ret, clk_status_val);
- return;
+ return ret;
}
if (clk_status_val & clk_status_bit)
break;
@@ -666,29 +686,135 @@ void chip_wakeup(struct wilc *wilc)
}
if (trials >= WAKE_UP_TRIAL_RETRY) {
pr_err("Failed to wake-up the chip\n");
- return;
+ return -ETIMEDOUT;
}
/* Sometimes spi fail to read clock regs after reading
* writing clockless registers
*/
if (wilc->io_type == WILC_HIF_SPI)
wilc->hif_func->hif_reset(wilc);
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(chip_wakeup);
-void host_wakeup_notify(struct wilc *wilc)
+static int chip_wakeup_wilc3000(struct wilc *wilc)
{
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
- wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_2, 1);
- release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ u32 wakeup_reg_val, clk_status_reg_val, trials = 0;
+ u32 wakeup_reg, wakeup_bit;
+ u32 clk_status_reg, clk_status_bit;
+ int wake_seq_trials = 5;
+ const struct wilc_hif_func *hif_func = wilc->hif_func;
+
+ if (wilc->io_type == WILC_HIF_SDIO) {
+ wakeup_reg = WILC_SDIO_WAKEUP_REG;
+ wakeup_bit = WILC_SDIO_WAKEUP_BIT;
+ clk_status_reg = WILC3000_SDIO_CLK_STATUS_REG;
+ clk_status_bit = WILC3000_SDIO_CLK_STATUS_BIT;
+ } else {
+ wakeup_reg = WILC_SPI_WAKEUP_REG;
+ wakeup_bit = WILC_SPI_WAKEUP_BIT;
+ clk_status_reg = WILC3000_SPI_CLK_STATUS_REG;
+ clk_status_bit = WILC3000_SPI_CLK_STATUS_BIT;
+ }
+
+ hif_func->hif_read_reg(wilc, wakeup_reg, &wakeup_reg_val);
+ do {
+ hif_func->hif_write_reg(wilc, wakeup_reg, wakeup_reg_val |
+ wakeup_bit);
+ /* Check the clock status */
+ hif_func->hif_read_reg(wilc, clk_status_reg,
+ &clk_status_reg_val);
+
+ /* In case of clocks off, wait 1ms, and check it again.
+ * if still off, wait for another 1ms, for a total wait of 3ms.
+ * If still off, redo the wake up sequence
+ */
+ while ((clk_status_reg_val & clk_status_bit) == 0 &&
+ (++trials % 4) != 0) {
+ /* Wait for the chip to stabilize*/
+ usleep_range(1000, 1100);
+
+ /* Make sure chip is awake. This is an extra step that
+ * can be removed later to avoid the bus access
+ * overhead
+ */
+ hif_func->hif_read_reg(wilc, clk_status_reg,
+ &clk_status_reg_val);
+ }
+ /* in case of failure, Reset the wakeup bit to introduce a new
+ * edge on the next loop
+ */
+ if ((clk_status_reg_val & clk_status_bit) == 0) {
+ hif_func->hif_write_reg(wilc, wakeup_reg,
+ wakeup_reg_val & (~wakeup_bit));
+ /* added wait before wakeup sequence retry */
+ usleep_range(200, 300);
+ }
+ } while ((clk_status_reg_val & clk_status_bit) == 0 && wake_seq_trials-- > 0);
+ if (!wake_seq_trials)
+ dev_err(wilc->dev, "clocks still OFF. Wake up failed\n");
+
+ return 0;
+}
+
+static int chip_wakeup(struct wilc *wilc)
+{
+ if (is_wilc1000(wilc->chipid))
+ return chip_wakeup_wilc1000(wilc);
+ else
+ return chip_wakeup_wilc3000(wilc);
+}
+
+static inline int acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
+{
+ int ret = 0;
+
+ mutex_lock(&wilc->hif_cs);
+ if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode) {
+ ret = chip_wakeup(wilc);
+ if (ret)
+ mutex_unlock(&wilc->hif_cs);
+ }
+
+ return ret;
+}
+
+static inline int release_bus(struct wilc *wilc, enum bus_release release)
+{
+ int ret = 0;
+
+ if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode)
+ ret = chip_allow_sleep(wilc);
+ mutex_unlock(&wilc->hif_cs);
+
+ return ret;
+}
+
+int host_wakeup_notify(struct wilc *wilc)
+{
+ int ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+
+ if (ret)
+ return ret;
+
+ wilc->hif_func->hif_write_reg(wilc, is_wilc1000(wilc->chipid) ?
+ WILC1000_CORTUS_INTERRUPT_2 :
+ WILC3000_CORTUS_INTERRUPT_2, 1);
+ return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
}
EXPORT_SYMBOL_GPL(host_wakeup_notify);
-void host_sleep_notify(struct wilc *wilc)
+int host_sleep_notify(struct wilc *wilc)
{
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
- wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_1, 1);
- release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ int ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+
+ if (ret)
+ return ret;
+
+ wilc->hif_func->hif_write_reg(wilc, is_wilc1000(wilc->chipid) ?
+ WILC1000_CORTUS_INTERRUPT_1 :
+ WILC3000_CORTUS_INTERRUPT_1, 1);
+ return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
}
EXPORT_SYMBOL_GPL(host_sleep_notify);
@@ -715,6 +841,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
int srcu_idx;
u8 *txb = wilc->tx_buffer;
struct wilc_vif *vif;
+ int rv;
if (wilc->quit)
goto out_update_cnt;
@@ -785,7 +912,10 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
goto out_unlock;
vmm_table[i] = 0x0;
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret)
+ goto out_unlock;
+
counter = 0;
func = wilc->hif_func;
do {
@@ -818,19 +948,45 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
if (ret)
break;
- ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2);
- if (ret)
- break;
+ if (is_wilc1000(wilc->chipid)) {
+ ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2);
+ if (ret)
+ break;
- do {
- ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);
+ do {
+ ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);
+ if (ret)
+ break;
+ if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) {
+ entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);
+ break;
+ }
+ } while (--timeout);
+ } else {
+ ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0);
if (ret)
break;
- if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) {
- entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);
+
+ /* interrupt firmware */
+ ret = func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_BASE, 1);
+ if (ret)
break;
- }
- } while (--timeout);
+
+ do {
+ ret = func->hif_read_reg(wilc, WILC_CORTUS_INTERRUPT_BASE, &reg);
+ if (ret)
+ break;
+ if (reg == 0) {
+ /* Get the entries */
+ ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);
+ if (ret)
+ break;
+
+ entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);
+ break;
+ }
+ } while (--timeout);
+ }
if (timeout <= 0) {
ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0);
break;
@@ -860,7 +1016,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
goto out_release_bus;
}
- release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ ret = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ if (ret)
+ goto out_unlock;
offset = 0;
i = 0;
@@ -922,7 +1080,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
for (i = 0; i < NQUEUES; i++)
wilc->txq[i].fw.count += ac_pkt_num_to_chip[i];
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret)
+ goto out_unlock;
ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM);
if (ret)
@@ -931,7 +1091,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
ret = func->hif_block_tx_ext(wilc, 0, txb, offset);
out_release_bus:
- release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ if (!ret && rv)
+ ret = rv;
out_unlock:
mutex_unlock(&wilc->txq_add_to_head_cs);
@@ -1060,8 +1222,14 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
void wilc_handle_isr(struct wilc *wilc)
{
u32 int_status;
+ int ret;
+
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret) {
+ dev_err_ratelimited(wilc->dev, "Cannot acquire bus\n");
+ return;
+ }
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
wilc->hif_func->hif_read_int(wilc, &int_status);
if (int_status & DATA_INT_EXT)
@@ -1070,7 +1238,9 @@ void wilc_handle_isr(struct wilc *wilc)
if (!(int_status & (ALL_INT_EXT)))
wilc_unknown_isr_ext(wilc);
- release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ ret = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ if (ret)
+ dev_err_ratelimited(wilc->dev, "Cannot release bus\n");
}
EXPORT_SYMBOL_GPL(wilc_handle_isr);
@@ -1082,6 +1252,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
u8 *dma_buffer;
int ret = 0;
u32 reg = 0;
+ int rv;
blksz = BIT(12);
@@ -1092,7 +1263,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
offset = 0;
pr_debug("%s: Downloading firmware size = %d\n", __func__, buffer_size);
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret)
+ return ret;
wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
reg &= ~BIT(10);
@@ -1101,11 +1274,17 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
if (reg & BIT(10))
pr_err("%s: Failed to reset\n", __func__);
- release_bus(wilc, WILC_BUS_RELEASE_ONLY);
+ ret = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
+ if (ret)
+ goto fail;
+
do {
addr = get_unaligned_le32(&buffer[offset]);
size = get_unaligned_le32(&buffer[offset + 4]);
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret)
+ goto fail;
+
offset += 8;
while (((int)size) && (offset < buffer_size)) {
if (size <= blksz)
@@ -1123,7 +1302,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
offset += size2;
size -= size2;
}
- release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ if (!ret && rv)
+ ret = rv;
if (ret) {
pr_err("%s Bus error\n", __func__);
@@ -1142,7 +1323,7 @@ fail:
int wilc_wlan_start(struct wilc *wilc)
{
u32 reg = 0;
- int ret;
+ int ret, rv;
u32 chipid;
if (wilc->io_type == WILC_HIF_SDIO) {
@@ -1151,7 +1332,10 @@ int wilc_wlan_start(struct wilc *wilc)
} else if (wilc->io_type == WILC_HIF_SPI) {
reg = 1;
}
- acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
+ if (ret)
+ return ret;
+
ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);
if (ret)
goto release;
@@ -1160,6 +1344,9 @@ int wilc_wlan_start(struct wilc *wilc)
if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num)
reg |= WILC_HAVE_SDIO_IRQ_GPIO;
+ if (is_wilc3000(wilc->chipid))
+ reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
+
ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);
if (ret)
goto release;
@@ -1182,16 +1369,18 @@ int wilc_wlan_start(struct wilc *wilc)
wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
release:
- release_bus(wilc, WILC_BUS_RELEASE_ONLY);
- return ret;
+ rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
+ return ret ? ret : rv;
}
int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
{
u32 reg = 0;
- int ret;
+ int ret, rv;
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret)
+ return ret;
ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, &reg);
if (ret)
@@ -1227,9 +1416,9 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
ret = 0;
release:
/* host comm is disabled - we can't issue sleep command anymore: */
- release_bus(wilc, WILC_BUS_RELEASE_ONLY);
+ rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
- return ret;
+ return ret ? ret : rv;
}
void wilc_wlan_cleanup(struct net_device *dev)
@@ -1402,19 +1591,56 @@ int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
return ret;
}
+int wilc_get_chipid(struct wilc *wilc)
+{
+ u32 chipid = 0;
+ u32 rfrevid = 0;
+
+ if (wilc->chipid == 0) {
+ wilc->hif_func->hif_read_reg(wilc, WILC3000_CHIP_ID, &chipid);
+ if (!is_wilc3000(chipid)) {
+ wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid);
+ wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID,
+ &rfrevid);
+
+ if (!is_wilc1000(chipid)) {
+ wilc->chipid = 0;
+ return -EINVAL;
+ }
+ if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */
+ if (rfrevid != 0x1)
+ chipid = WILC_1000_BASE_ID_2A_REV1;
+ } else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */
+ if (rfrevid == 0x4)
+ chipid = WILC_1000_BASE_ID_2B_REV1;
+ else if (rfrevid != 0x3)
+ chipid = WILC_1000_BASE_ID_2B_REV2;
+ }
+ }
+
+ wilc->chipid = chipid;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wilc_get_chipid);
+
static int init_chip(struct net_device *dev)
{
- u32 chipid;
u32 reg;
- int ret = 0;
+ int ret, rv;
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc;
- acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret)
+ return ret;
- chipid = wilc_get_chipid(wilc, true);
+ ret = wilc_get_chipid(wilc);
+ if (ret)
+ goto release;
- if ((chipid & 0xfff) != 0xa0) {
+ if ((wilc->chipid & 0xfff) != 0xa0) {
ret = wilc->hif_func->hif_read_reg(wilc,
WILC_CORTUS_RESET_MUX_SEL,
&reg);
@@ -1439,46 +1665,35 @@ static int init_chip(struct net_device *dev)
}
}
-release:
- release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
-
- return ret;
-}
-
-u32 wilc_get_chipid(struct wilc *wilc, bool update)
-{
- u32 chipid = 0;
- u32 rfrevid = 0;
-
- if (wilc->chipid == 0 || update) {
- wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid);
- wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID,
- &rfrevid);
- if (!is_wilc1000(chipid)) {
- wilc->chipid = 0;
- return wilc->chipid;
- }
- if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */
- if (rfrevid != 0x1)
- chipid = WILC_1000_BASE_ID_2A_REV1;
- } else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */
- if (rfrevid == 0x4)
- chipid = WILC_1000_BASE_ID_2B_REV1;
- else if (rfrevid != 0x3)
- chipid = WILC_1000_BASE_ID_2B_REV2;
+ if (is_wilc3000(wilc->chipid)) {
+ ret = wilc->hif_func->hif_read_reg(wilc, WILC3000_BOOTROM_STATUS, &reg);
+ if (ret) {
+ netdev_err(dev, "failed to read WILC3000 BootROM status register\n");
+ goto release;
}
- wilc->chipid = chipid;
+ ret = wilc->hif_func->hif_write_reg(wilc, WILC3000_CORTUS_BOOT_REGISTER_2,
+ WILC_CORTUS_BOOT_FROM_IRAM);
+ if (ret) {
+ netdev_err(dev, "failed to write WILC3000 Boot register\n");
+ goto release;
+ }
}
- return wilc->chipid;
+
+release:
+ rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
+
+ return ret ? ret : rv;
}
int wilc_load_mac_from_nv(struct wilc *wl)
{
- int ret = -EINVAL;
+ int ret, rv;
unsigned int i;
- acquire_bus(wl, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ ret = acquire_bus(wl, WILC_BUS_ACQUIRE_AND_WAKEUP);
+ if (ret)
+ return ret;
for (i = 0; i < WILC_NVMEM_MAX_NUM_BANK; i++) {
int bank_offset = get_bank_offset_from_bank_index(i);
@@ -1517,14 +1732,14 @@ int wilc_load_mac_from_nv(struct wilc *wl)
break;
}
- release_bus(wl, WILC_BUS_RELEASE_ALLOW_SLEEP);
- return ret;
+ rv = release_bus(wl, WILC_BUS_RELEASE_ALLOW_SLEEP);
+ return ret ? ret : rv;
}
EXPORT_SYMBOL_GPL(wilc_load_mac_from_nv);
int wilc_wlan_init(struct net_device *dev)
{
- int ret = 0;
+ int ret = 0, rv;
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc;
@@ -1533,11 +1748,26 @@ int wilc_wlan_init(struct net_device *dev)
wilc->quit = 0;
if (!wilc->hif_func->hif_is_init(wilc)) {
- acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
+ ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
+ if (ret)
+ return ret;
+
ret = wilc->hif_func->hif_init(wilc, false);
- release_bus(wilc, WILC_BUS_RELEASE_ONLY);
+ if (!ret)
+ ret = wilc_get_chipid(wilc);
+ rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
+ if (!ret && rv)
+ ret = rv;
if (ret)
goto fail;
+
+ if (!is_wilc1000(wilc->chipid) && !is_wilc3000(wilc->chipid)) {
+ netdev_err(dev, "Unsupported chipid: %x\n", wilc->chipid);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ netdev_dbg(dev, "chipid (%08x)\n", wilc->chipid);
}
if (!wilc->vmm_table)
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h
index dd2fb3c2f06a..b9e7f9222ead 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.h
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.h
@@ -96,8 +96,14 @@
#define WILC_SPI_WAKEUP_REG 0x1
#define WILC_SPI_WAKEUP_BIT BIT(1)
-#define WILC_SPI_CLK_STATUS_REG 0x0f
-#define WILC_SPI_CLK_STATUS_BIT BIT(2)
+/* WILC1000 specific */
+#define WILC1000_SPI_CLK_STATUS_REG 0x0f
+#define WILC1000_SPI_CLK_STATUS_BIT BIT(2)
+
+/* WILC3000 specific */
+#define WILC3000_SPI_CLK_STATUS_REG 0x13
+#define WILC3000_SPI_CLK_STATUS_BIT BIT(2)
+
#define WILC_SPI_HOST_TO_FW_REG 0x0b
#define WILC_SPI_HOST_TO_FW_BIT BIT(0)
@@ -123,14 +129,24 @@
#define WILC_SDIO_WAKEUP_REG 0xf0
#define WILC_SDIO_WAKEUP_BIT BIT(0)
-#define WILC_SDIO_CLK_STATUS_REG 0xf1
-#define WILC_SDIO_CLK_STATUS_BIT BIT(0)
+/* WILC1000 */
+#define WILC1000_SDIO_CLK_STATUS_REG 0xf1
+#define WILC1000_SDIO_CLK_STATUS_BIT BIT(0)
+
+#define WILC1000_SDIO_IRQ_FLAG_REG 0xf7
+#define WILC1000_SDIO_IRQ_CLEAR_FLAG_REG 0xf8
+
+/* WILC3000 specific */
+#define WILC3000_SDIO_CLK_STATUS_REG 0xf0 /* clk & wakeup are on same reg */
+#define WILC3000_SDIO_CLK_STATUS_BIT BIT(4)
+
+#define WILC3000_SDIO_VMM_TBL_CTRL_REG 0xf1
+#define WILC3000_SDIO_IRQ_FLAG_REG 0xfe
+/* Common vendor specific CCCR register */
#define WILC_SDIO_INTERRUPT_DATA_SZ_REG 0xf2 /* Read size (2 bytes) */
#define WILC_SDIO_VMM_TBL_CTRL_REG 0xf6
-#define WILC_SDIO_IRQ_FLAG_REG 0xf7
-#define WILC_SDIO_IRQ_CLEAR_FLAG_REG 0xf8
#define WILC_SDIO_HOST_TO_FW_REG 0xfa
#define WILC_SDIO_HOST_TO_FW_BIT BIT(0)
@@ -172,8 +188,11 @@
#define WILC_HAVE_USE_IRQ_AS_HOST_WAKE BIT(8)
#define WILC_CORTUS_INTERRUPT_BASE 0x10A8
-#define WILC_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x4)
-#define WILC_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x8)
+#define WILC1000_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x4)
+#define WILC3000_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x14)
+
+#define WILC1000_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x8)
+#define WILC3000_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x18)
/* tx control register 1 to 4 for RX */
#define WILC_REG_4_TO_1_RX 0x1e1c
@@ -183,6 +202,9 @@
#define WILC_CORTUS_RESET_MUX_SEL 0x1118
#define WILC_CORTUS_BOOT_REGISTER 0xc0000
+#define WILC3000_BOOTROM_STATUS 0x207ac
+#define WILC3000_CORTUS_BOOT_REGISTER_2 0x4f0000
+#define WILC3000_CHIP_ID 0x3b0000
#define WILC_CORTUS_BOOT_FROM_IRAM 0x71
@@ -195,6 +217,8 @@
#define WILC_1000_BASE_ID_2B_REV1 (WILC_1000_BASE_ID_2B + 1)
#define WILC_1000_BASE_ID_2B_REV2 (WILC_1000_BASE_ID_2B + 2)
+#define WILC_3000_BASE_ID 0x300000
+
#define WILC_CHIP_REV_FIELD GENMASK(11, 0)
/********************************************
@@ -413,6 +437,11 @@ static inline bool is_wilc1000(u32 id)
return (id & (~WILC_CHIP_REV_FIELD)) == WILC_1000_BASE_ID;
}
+static inline bool is_wilc3000(u32 id)
+{
+ return (id & (~WILC_CHIP_REV_FIELD)) == WILC_3000_BASE_ID;
+}
+
int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
u32 buffer_size);
int wilc_wlan_start(struct wilc *wilc);
@@ -436,13 +465,11 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev);
void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size);
bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size);
-void host_wakeup_notify(struct wilc *wilc);
-void host_sleep_notify(struct wilc *wilc);
-void chip_allow_sleep(struct wilc *wilc);
-void chip_wakeup(struct wilc *wilc);
+int host_wakeup_notify(struct wilc *wilc);
+int host_sleep_notify(struct wilc *wilc);
int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
u32 count);
int wilc_wlan_init(struct net_device *dev);
-u32 wilc_get_chipid(struct wilc *wilc, bool update);
+int wilc_get_chipid(struct wilc *wilc);
int wilc_load_mac_from_nv(struct wilc *wilc);
#endif
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 9540ad6196d7..956c5763662f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -257,7 +257,7 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout);
- cmd->smps_mode = s->smps_mode;
+ cmd->smps_mode = NL80211_SMPS_OFF;
cmd->p2p_ctwindow = s->p2p_ctwindow;
cmd->p2p_opp_ps = s->p2p_opp_ps;
cmd->pbss = s->pbss;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index b204a24074ab..b375a4751580 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -13,7 +13,6 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <net/sock.h>
-#include <net/lib80211.h>
#include <net/cfg80211.h>
#include <linux/vmalloc.h>
#include <linux/firmware.h>
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 3bb81bcff0ac..60c2a12e9d5e 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -3607,7 +3607,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 52, 0x0C);
rt2800_rfcsr_write(rt2x00dev, 54, 0xF8);
if (rf->channel <= 50) {
- rt2800_rfcsr_write(rt2x00dev, 55, 0x06),
+ rt2800_rfcsr_write(rt2x00dev, 55, 0x06);
rt2800_rfcsr_write(rt2x00dev, 56, 0xD3);
} else if (rf->channel >= 52) {
rt2800_rfcsr_write(rt2x00dev, 55, 0x04);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index 8fd22c69855f..a6d50149e0c3 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -823,8 +823,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
- hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c
index 7891c988dd5f..f95898f68d68 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
@@ -5058,10 +5058,12 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
- if (bss_conf->enable_beacon)
+ if (bss_conf->enable_beacon) {
rtl8xxxu_start_tx_beacon(priv);
- else
+ schedule_delayed_work(&priv->update_beacon_work, 0);
+ } else {
rtl8xxxu_stop_tx_beacon(priv);
+ }
}
if (changed & BSS_CHANGED_BEACON)
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
index 039bbedb41c2..379193b24428 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
@@ -3409,17 +3409,6 @@ void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
}
}
-void ex_btc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist)
-{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
-
- rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
- "[BTCoex], *****************Coex DM Reset****************\n");
-
- halbtc8723b1ant_init_hw_config(btcoexist, false, false);
- halbtc8723b1ant_init_coex_dm(btcoexist);
-}
-
void ex_btc8723b1ant_periodical(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
index 9d41e11388ad..a4506d838dc7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h
@@ -197,7 +197,6 @@ void ex_btc8723b1ant_rf_status_notify(struct btc_coexist *btcoexist,
u8 type);
void ex_btc8723b1ant_halt_notify(struct btc_coexist *btcoexist);
void ex_btc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate);
-void ex_btc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist);
void ex_btc8723b1ant_periodical(struct btc_coexist *btcoexist);
void ex_btc8723b1ant_display_coex_info(struct btc_coexist *btcoexist,
struct seq_file *m);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index be4c0e60d44d..478cca33e5e3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -1708,19 +1708,6 @@ void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist,
halbtc_normal_low_power(btcoexist);
}
-void exhalbtc_rf_status_notify(struct btc_coexist *btcoexist, u8 type)
-{
- if (!halbtc_is_bt_coexist_available(btcoexist))
- return;
-
- if (IS_HARDWARE_TYPE_8821(btcoexist->adapter)) {
- } else if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
- if (btcoexist->board_info.btdm_ant_num == 1)
- ex_btc8723b1ant_rf_status_notify(btcoexist, type);
- } else if (IS_HARDWARE_TYPE_8192E(btcoexist->adapter)) {
- }
-}
-
void exhalbtc_halt_notify(struct btc_coexist *btcoexist)
{
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -1768,31 +1755,6 @@ void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state)
}
}
-void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist)
-{
- struct rtl_priv *rtlpriv = btcoexist->adapter;
-
- if (!halbtc_is_bt_coexist_available(btcoexist))
- return;
- btcoexist->statistics.cnt_coex_dm_switch++;
-
- halbtc_leave_low_power(btcoexist);
-
- if (IS_HARDWARE_TYPE_8723B(btcoexist->adapter)) {
- if (btcoexist->board_info.btdm_ant_num == 1) {
- btcoexist->stop_coex_dm = true;
- ex_btc8723b1ant_coex_dm_reset(btcoexist);
- exhalbtc_set_ant_num(rtlpriv,
- BT_COEX_ANT_TYPE_DETECTED, 2);
- ex_btc8723b2ant_init_hwconfig(btcoexist);
- ex_btc8723b2ant_init_coex_dm(btcoexist);
- btcoexist->stop_coex_dm = false;
- }
- }
-
- halbtc_normal_low_power(btcoexist);
-}
-
void exhalbtc_periodical(struct btc_coexist *btcoexist)
{
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -1820,29 +1782,6 @@ void exhalbtc_periodical(struct btc_coexist *btcoexist)
halbtc_normal_low_power(btcoexist);
}
-void exhalbtc_dbg_control(struct btc_coexist *btcoexist,
- u8 code, u8 len, u8 *data)
-{
- if (!halbtc_is_bt_coexist_available(btcoexist))
- return;
- btcoexist->statistics.cnt_dbg_ctrl++;
-
- halbtc_leave_low_power(btcoexist);
-
- halbtc_normal_low_power(btcoexist);
-}
-
-void exhalbtc_antenna_detection(struct btc_coexist *btcoexist, u32 cent_freq,
- u32 offset, u32 span, u32 seconds)
-{
- if (!halbtc_is_bt_coexist_available(btcoexist))
- return;
-}
-
-void exhalbtc_stack_update_profile_info(void)
-{
-}
-
void exhalbtc_update_min_bt_rssi(struct btc_coexist *btcoexist, s8 bt_rssi)
{
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -1851,24 +1790,6 @@ void exhalbtc_update_min_bt_rssi(struct btc_coexist *btcoexist, s8 bt_rssi)
btcoexist->stack_info.min_bt_rssi = bt_rssi;
}
-void exhalbtc_set_hci_version(struct btc_coexist *btcoexist, u16 hci_version)
-{
- if (!halbtc_is_bt_coexist_available(btcoexist))
- return;
-
- btcoexist->stack_info.hci_version = hci_version;
-}
-
-void exhalbtc_set_bt_patch_version(struct btc_coexist *btcoexist,
- u16 bt_hci_version, u16 bt_patch_version)
-{
- if (!halbtc_is_bt_coexist_available(btcoexist))
- return;
-
- btcoexist->bt_info.bt_real_fw_ver = bt_patch_version;
- btcoexist->bt_info.bt_hci_ver = bt_hci_version;
-}
-
void exhalbtc_set_chip_type(struct btc_coexist *btcoexist, u8 chip_type)
{
switch (chip_type) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index a96a995dd850..d8d88a989806 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -763,19 +763,9 @@ void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type);
void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist, u8 *tmp_buf,
u8 length);
-void exhalbtc_rf_status_notify(struct btc_coexist *btcoexist, u8 type);
void exhalbtc_halt_notify(struct btc_coexist *btcoexist);
void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
-void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist);
void exhalbtc_periodical(struct btc_coexist *btcoexist);
-void exhalbtc_dbg_control(struct btc_coexist *btcoexist, u8 code, u8 len,
- u8 *data);
-void exhalbtc_antenna_detection(struct btc_coexist *btcoexist, u32 cent_freq,
- u32 offset, u32 span, u32 seconds);
-void exhalbtc_stack_update_profile_info(void);
-void exhalbtc_set_hci_version(struct btc_coexist *btcoexist, u16 hci_version);
-void exhalbtc_set_bt_patch_version(struct btc_coexist *btcoexist,
- u16 bt_hci_version, u16 bt_patch_version);
void exhalbtc_update_min_bt_rssi(struct btc_coexist *btcoexist, s8 bt_rssi);
void exhalbtc_set_bt_exist(struct btc_coexist *btcoexist, bool bt_exist);
void exhalbtc_set_chip_type(struct btc_coexist *btcoexist, u8 chip_type);
diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c
index 82cf5fb5175f..6518e77b89f5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/efuse.c
+++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c
@@ -162,10 +162,19 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value)
void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u16 max_attempts = 10000;
u32 value32;
u8 readbyte;
u16 retry;
+ /*
+ * In case of USB devices, transfer speeds are limited, hence
+ * efuse I/O reads could be (way) slower. So, decrease (a lot)
+ * the read attempts in case of failures.
+ */
+ if (rtlpriv->rtlhal.interface == INTF_USB)
+ max_attempts = 10;
+
rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
(_offset & 0xff));
readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
@@ -178,7 +187,7 @@ void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf)
retry = 0;
value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
- while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
+ while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < max_attempts)) {
value32 = rtl_read_dword(rtlpriv,
rtlpriv->cfg->maps[EFUSE_CTRL]);
retry++;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
index 1b144fbd4d26..048744166a92 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
@@ -350,7 +350,8 @@ MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8723E 802.11n PCI wireless");
-MODULE_FIRMWARE("rtlwifi/rtl8723efw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723fw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723fw_B.bin");
module_param_named(swenc, rtl8723e_mod_params.sw_crypto, bool, 0444);
module_param_named(debug_level, rtl8723e_mod_params.debug_level, int, 0644);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index 0e77de1baaf8..bcfc53af4c1a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -2040,31 +2040,33 @@ static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- int params[] = {RTL8723BE_EEPROM_ID, EEPROM_VID, EEPROM_DID,
- EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR,
- EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID,
- COUNTRY_CODE_WORLD_WIDE_13};
+ static const int params[] = {
+ RTL8723BE_EEPROM_ID, EEPROM_VID, EEPROM_DID,
+ EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR,
+ EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID,
+ COUNTRY_CODE_WORLD_WIDE_13
+ };
u8 *hwinfo;
int i;
bool is_toshiba_smid1 = false;
bool is_toshiba_smid2 = false;
bool is_samsung_smid = false;
bool is_lenovo_smid = false;
- u16 toshiba_smid1[] = {
+ static const u16 toshiba_smid1[] = {
0x6151, 0x6152, 0x6154, 0x6155, 0x6177, 0x6178, 0x6179, 0x6180,
0x7151, 0x7152, 0x7154, 0x7155, 0x7177, 0x7178, 0x7179, 0x7180,
0x8151, 0x8152, 0x8154, 0x8155, 0x8181, 0x8182, 0x8184, 0x8185,
0x9151, 0x9152, 0x9154, 0x9155, 0x9181, 0x9182, 0x9184, 0x9185
};
- u16 toshiba_smid2[] = {
+ static const u16 toshiba_smid2[] = {
0x6181, 0x6184, 0x6185, 0x7181, 0x7182, 0x7184, 0x7185, 0x8181,
0x8182, 0x8184, 0x8185, 0x9181, 0x9182, 0x9184, 0x9185
};
- u16 samsung_smid[] = {
+ static const u16 samsung_smid[] = {
0x6191, 0x6192, 0x6193, 0x7191, 0x7192, 0x7193, 0x8191, 0x8192,
0x8193, 0x9191, 0x9192, 0x9193
};
- u16 lenovo_smid[] = {
+ static const u16 lenovo_smid[] = {
0x8195, 0x9195, 0x7194, 0x8200, 0x8201, 0x8202, 0x9199, 0x9200
};
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index a65503c5ae5a..b5266e560416 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -407,6 +407,9 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8821ae 802.11ac PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8821aefw.bin");
MODULE_FIRMWARE("rtlwifi/rtl8821aefw_29.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8821aefw_wowlan.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8812aefw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8812aefw_wowlan.bin");
module_param_named(swenc, rtl8821ae_mod_params.sw_crypto, bool, 0444);
module_param_named(debug_level, rtl8821ae_mod_params.debug_level, int, 0644);
diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 02b0d698413b..733b3e58da51 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -43,6 +43,17 @@ config RTW88_8723D
config RTW88_8821C
tristate
+config RTW88_88XXA
+ tristate
+
+config RTW88_8821A
+ tristate
+ select RTW88_88XXA
+
+config RTW88_8812A
+ tristate
+ select RTW88_88XXA
+
config RTW88_8822BE
tristate "Realtek 8822BE PCI wireless network adapter"
depends on PCI
@@ -189,6 +200,28 @@ config RTW88_8821CU
802.11ac USB wireless network adapter
+config RTW88_8821AU
+ tristate "Realtek 8821AU/8811AU USB wireless network adapter"
+ depends on USB
+ select RTW88_CORE
+ select RTW88_USB
+ select RTW88_8821A
+ help
+ Select this option will enable support for 8821AU and 8811AU chipset
+
+ 802.11ac USB wireless network adapter
+
+config RTW88_8812AU
+ tristate "Realtek 8812AU USB wireless network adapter"
+ depends on USB
+ select RTW88_CORE
+ select RTW88_USB
+ select RTW88_8812A
+ help
+ Select this option will enable support for 8812AU chipset
+
+ 802.11ac USB wireless network adapter
+
config RTW88_DEBUG
bool "Realtek rtw88 debug support"
depends on RTW88_CORE
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 8f47359b4380..f0b49f5a8a5a 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -77,6 +77,21 @@ rtw88_8821cs-objs := rtw8821cs.o
obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o
rtw88_8821cu-objs := rtw8821cu.o
+obj-$(CONFIG_RTW88_88XXA) += rtw88_88xxa.o
+rtw88_88xxa-objs := rtw88xxa.o
+
+obj-$(CONFIG_RTW88_8821A) += rtw88_8821a.o
+rtw88_8821a-objs := rtw8821a.o rtw8821a_table.o
+
+obj-$(CONFIG_RTW88_8812A) += rtw88_8812a.o
+rtw88_8812a-objs := rtw8812a.o rtw8812a_table.o
+
+obj-$(CONFIG_RTW88_8821AU) += rtw88_8821au.o
+rtw88_8821au-objs := rtw8821au.o
+
+obj-$(CONFIG_RTW88_8812AU) += rtw88_8812au.o
+rtw88_8812au-objs := rtw8812au.o
+
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
rtw88_pci-objs := pci.o
diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c
index a99776af56c2..c929db1e53ca 100644
--- a/drivers/net/wireless/realtek/rtw88/coex.c
+++ b/drivers/net/wireless/realtek/rtw88/coex.c
@@ -446,7 +446,7 @@ static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
}
}
-static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
+void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
{
struct rtw_coex *coex = &rtwdev->coex;
struct rtw_coex_stat *coex_stat = &coex->stat;
@@ -494,11 +494,29 @@ static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
struct rtw_coex_stat *coex_stat = &coex->stat;
struct rtw_coex_dm *coex_dm = &coex->dm;
bool bt_disabled = false;
+ bool bt_active = true;
u16 score_board;
if (chip->scbd_support) {
score_board = rtw_coex_read_scbd(rtwdev);
bt_disabled = !(score_board & COEX_SCBD_ONOFF);
+ } else {
+ if (coex_stat->hi_pri_tx == 0 && coex_stat->hi_pri_rx == 0 &&
+ coex_stat->lo_pri_tx == 0 && coex_stat->lo_pri_rx == 0)
+ bt_active = false;
+
+ if (coex_stat->hi_pri_tx == 0xffff && coex_stat->hi_pri_rx == 0xffff &&
+ coex_stat->lo_pri_tx == 0xffff && coex_stat->lo_pri_rx == 0xffff)
+ bt_active = false;
+
+ if (bt_active) {
+ coex_stat->bt_disable_cnt = 0;
+ bt_disabled = false;
+ } else {
+ coex_stat->bt_disable_cnt++;
+ if (coex_stat->bt_disable_cnt >= 10)
+ bt_disabled = true;
+ }
}
if (coex_stat->bt_disabled != bt_disabled) {
@@ -950,12 +968,18 @@ static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
{
+ if (!rtwdev->chip->ltecoex_addr)
+ return;
+
rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);
rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);
}
static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
{
+ if (!rtwdev->chip->ltecoex_addr)
+ return;
+
rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);
rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
}
@@ -2747,16 +2771,19 @@ void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
rtw_write8(rtwdev, 0xff1a, 0x0);
rtw_coex_set_gnt_debug(rtwdev);
}
+EXPORT_SYMBOL(rtw_coex_power_on_setting);
void rtw_coex_power_off_setting(struct rtw_dev *rtwdev)
{
rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN);
}
+EXPORT_SYMBOL(rtw_coex_power_off_setting);
void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
{
__rtw_coex_init_hw_config(rtwdev, wifi_only);
}
+EXPORT_SYMBOL(rtw_coex_init_hw_config);
void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
{
@@ -3904,7 +3931,7 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
u8 sys_lte;
u16 score_board_WB, score_board_BW;
u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
- u32 lte_coex, bt_coex;
+ u32 lte_coex = 0, bt_coex = 0;
int i;
score_board_BW = rtw_coex_read_scbd(rtwdev);
@@ -3916,8 +3943,10 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
sys_lte = rtw_read8(rtwdev, 0x73);
- lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
- bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
+ if (rtwdev->chip->ltecoex_addr) {
+ lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
+ bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
+ }
if (!coex_stat->wl_under_ips &&
(!coex_stat->wl_under_lps || coex_stat->wl_force_lps_ctrl) &&
diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h
index 57cf29da9ea4..c398be8391f7 100644
--- a/drivers/net/wireless/realtek/rtw88/coex.h
+++ b/drivers/net/wireless/realtek/rtw88/coex.h
@@ -384,6 +384,7 @@ u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr);
void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
u32 mask, u32 val);
void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set);
+void rtw_coex_query_bt_info(struct rtw_dev *rtwdev);
void rtw_coex_bt_relink_work(struct work_struct *work);
void rtw_coex_bt_reenable_work(struct work_struct *work);
@@ -419,4 +420,14 @@ static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev)
return coex_stat->bt_disabled;
}
+static inline void rtw_coex_active_query_bt_info(struct rtw_dev *rtwdev)
+{
+ /* The RTL8821AU firmware doesn't send C2H_BT_INFO by itself
+ * when bluetooth headphones are disconnected, so we have to
+ * ask for it regularly.
+ */
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A && rtwdev->efuse.btcoex)
+ rtw_coex_query_bt_info(rtwdev);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c
index c26a6905fd15..364ec0436d0f 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.c
+++ b/drivers/net/wireless/realtek/rtw88/debug.c
@@ -308,7 +308,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)
{
struct rtw_debugfs_priv *debugfs_priv = m->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
- u8 page_size = rtwdev->chip->page_size;
+ u16 page_size = rtwdev->chip->page_size;
u32 buf_size = debugfs_priv->rsvd_page.page_num * page_size;
u32 offset = debugfs_priv->rsvd_page.page_offset * page_size;
u8 *buf;
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index b9b0114e253b..e6e9946fbf44 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -139,25 +139,30 @@ static u16 get_max_amsdu_len(u32 bit_rate)
struct rtw_fw_iter_ra_data {
struct rtw_dev *rtwdev;
u8 *payload;
+ u8 length;
};
static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw_fw_iter_ra_data *ra_data = data;
+ struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)ra_data->payload;
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
u8 mac_id, rate, sgi, bw;
u8 mcs, nss;
u32 bit_rate;
- mac_id = GET_RA_REPORT_MACID(ra_data->payload);
+ mac_id = ra_rpt->mac_id;
if (si->mac_id != mac_id)
return;
si->ra_report.txrate.flags = 0;
- rate = GET_RA_REPORT_RATE(ra_data->payload);
- sgi = GET_RA_REPORT_SGI(ra_data->payload);
- bw = GET_RA_REPORT_BW(ra_data->payload);
+ rate = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_RATE);
+ sgi = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_SGI);
+ if (ra_data->length >= offsetofend(typeof(*ra_rpt), bw))
+ bw = ra_rpt->bw;
+ else
+ bw = si->bw_mode;
if (rate < DESC_RATEMCS0) {
si->ra_report.txrate.legacy = rtw_desc_to_bitrate(rate);
@@ -197,14 +202,18 @@ legacy:
static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload,
u8 length)
{
+ struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)payload;
struct rtw_fw_iter_ra_data ra_data;
- if (WARN(length < 7, "invalid ra report c2h length\n"))
+ if (WARN(length < rtwdev->chip->c2h_ra_report_size,
+ "invalid ra report c2h length %d\n", length))
return;
- rtwdev->dm_info.tx_rate = GET_RA_REPORT_RATE(payload);
+ rtwdev->dm_info.tx_rate = u8_get_bits(ra_rpt->rate_sgi,
+ RTW_C2H_RA_RPT_RATE);
ra_data.rtwdev = rtwdev;
ra_data.payload = payload;
+ ra_data.length = length;
rtw_iterate_stas_atomic(rtwdev, rtw_fw_ra_report_iter, &ra_data);
}
@@ -267,7 +276,7 @@ static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload,
static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload,
u8 length)
{
- struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
+ const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload;
rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY,
@@ -1281,16 +1290,16 @@ static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type);
pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
- rtw_tx_fill_tx_desc(&pkt_info, skb);
+ rtw_tx_fill_tx_desc(rtwdev, &pkt_info, skb);
}
-static inline u8 rtw_len_to_page(unsigned int len, u8 page_size)
+static inline u8 rtw_len_to_page(unsigned int len, u16 page_size)
{
return DIV_ROUND_UP(len, page_size);
}
-static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size,
- u8 page_margin, u32 page, u8 *buf,
+static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u16 page_size,
+ u16 page_margin, u32 page, u8 *buf,
struct rtw_rsvd_page *rsvd_pkt)
{
struct sk_buff *skb = rsvd_pkt->skb;
@@ -1592,13 +1601,13 @@ static int __rtw_build_rsvd_page_from_vifs(struct rtw_dev *rtwdev)
static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size)
{
- struct ieee80211_hw *hw = rtwdev->hw;
const struct rtw_chip_info *chip = rtwdev->chip;
- struct sk_buff *iter;
+ struct ieee80211_hw *hw = rtwdev->hw;
struct rtw_rsvd_page *rsvd_pkt;
- u32 page = 0;
+ struct sk_buff *iter;
+ u16 page_size, page_margin, tx_desc_sz;
u8 total_page = 0;
- u8 page_size, page_margin, tx_desc_sz;
+ u32 page = 0;
u8 *buf;
int ret;
@@ -2004,12 +2013,13 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes,
{
const struct rtw_chip_info *chip = rtwdev->chip;
struct sk_buff *skb, *tmp;
- u8 page_offset = 1, *buf, page_size = chip->page_size;
u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc;
- u16 buf_offset = page_size * page_offset;
u8 tx_desc_sz = chip->tx_pkt_desc_sz;
- u8 page_cnt, pages;
+ u16 page_size = chip->page_size;
+ u8 page_offset = 1, *buf;
+ u16 buf_offset = page_size * page_offset;
unsigned int pkt_len;
+ u8 page_cnt, pages;
int ret;
if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM))
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index e999c24e4634..404de1b0c407 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -85,6 +85,19 @@ struct rtw_c2h_adaptivity {
u8 option;
} __packed;
+struct rtw_c2h_ra_rpt {
+ u8 rate_sgi;
+ u8 mac_id;
+ u8 byte2;
+ u8 status;
+ u8 byte4;
+ u8 ra_ratio;
+ u8 bw;
+} __packed;
+
+#define RTW_C2H_RA_RPT_RATE GENMASK(6, 0)
+#define RTW_C2H_RA_RPT_SGI BIT(7)
+
struct rtw_h2c_register {
u32 w0;
u32 w1;
@@ -364,10 +377,6 @@ struct rtw_fw_hdr_legacy {
#define GET_CHAN_SWITCH_CENTRAL_CH(c2h_payload) (c2h_payload[2])
#define GET_CHAN_SWITCH_ID(c2h_payload) (c2h_payload[3])
#define GET_CHAN_SWITCH_STATUS(c2h_payload) (c2h_payload[4])
-#define GET_RA_REPORT_RATE(c2h_payload) (c2h_payload[0] & 0x7f)
-#define GET_RA_REPORT_SGI(c2h_payload) ((c2h_payload[0] & 0x80) >> 7)
-#define GET_RA_REPORT_BW(c2h_payload) (c2h_payload[6])
-#define GET_RA_REPORT_MACID(c2h_payload) (c2h_payload[1])
#define GET_BCN_FILTER_NOTIFY_TYPE(c2h_payload) (c2h_payload[1] & 0xf)
#define GET_BCN_FILTER_NOTIFY_EVENT(c2h_payload) (c2h_payload[1] & 0x10)
diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
index 564f5988ee82..cae9cca6dca3 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.c
+++ b/drivers/net/wireless/realtek/rtw88/mac.c
@@ -227,8 +227,8 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask,
return 0;
}
-static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
- const struct rtw_pwr_seq_cmd **cmd_seq)
+int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
+ const struct rtw_pwr_seq_cmd * const *cmd_seq)
{
u8 cut_mask;
u8 intf_mask;
@@ -267,11 +267,12 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
return 0;
}
+EXPORT_SYMBOL(rtw_pwr_seq_parser);
static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
{
const struct rtw_chip_info *chip = rtwdev->chip;
- const struct rtw_pwr_seq_cmd **pwr_seq;
+ const struct rtw_pwr_seq_cmd * const *pwr_seq;
u32 imr = 0;
u8 rpwm;
bool cur_pwr;
@@ -994,6 +995,7 @@ int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
return 0;
}
+EXPORT_SYMBOL(rtw_download_firmware);
static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
{
@@ -1127,7 +1129,7 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
return 0;
}
-static int set_trx_fifo_info(struct rtw_dev *rtwdev)
+int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev)
{
const struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_fifo_conf *fifo = &rtwdev->fifo;
@@ -1136,7 +1138,7 @@ static int set_trx_fifo_info(struct rtw_dev *rtwdev)
/* config rsvd page num */
fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num;
- fifo->txff_pg_num = chip->txff_size >> 7;
+ fifo->txff_pg_num = chip->txff_size / chip->page_size;
if (rtw_chip_wcpu_11n(rtwdev))
fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num;
else
@@ -1179,6 +1181,7 @@ static int set_trx_fifo_info(struct rtw_dev *rtwdev)
return 0;
}
+EXPORT_SYMBOL(rtw_set_trx_fifo_info);
static int __priority_queue_cfg(struct rtw_dev *rtwdev,
const struct rtw_page_table *pg_tbl,
@@ -1256,7 +1259,7 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev)
u16 pubq_num;
int ret;
- ret = set_trx_fifo_info(rtwdev);
+ ret = rtw_set_trx_fifo_info(rtwdev);
if (ret)
return ret;
diff --git a/drivers/net/wireless/realtek/rtw88/mac.h b/drivers/net/wireless/realtek/rtw88/mac.h
index 58c3dccc14bb..6905e2747372 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.h
+++ b/drivers/net/wireless/realtek/rtw88/mac.h
@@ -30,11 +30,14 @@
void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
u8 primary_ch_idx);
+int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
+ const struct rtw_pwr_seq_cmd * const *cmd_seq);
int rtw_mac_power_on(struct rtw_dev *rtwdev);
void rtw_mac_power_off(struct rtw_dev *rtwdev);
int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw);
int rtw_mac_init(struct rtw_dev *rtwdev);
void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop);
+int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev);
int rtw_ddma_to_fw_fifo(struct rtw_dev *rtwdev, u32 ocp_src, u32 size);
static inline void rtw_mac_flush_all_queues(struct rtw_dev *rtwdev, bool drop)
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index b39e90fb66b4..026fbf4ad9cc 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -928,8 +928,10 @@ static int rtw_ops_set_sar_specs(struct ieee80211_hw *hw,
static void rtw_ops_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u32 changed)
+ struct ieee80211_link_sta *link_sta,
+ u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct rtw_dev *rtwdev = hw->priv;
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
@@ -973,7 +975,7 @@ const struct ieee80211_ops rtw_ops = {
.reconfig_complete = rtw_reconfig_complete,
.hw_scan = rtw_ops_hw_scan,
.cancel_hw_scan = rtw_ops_cancel_hw_scan,
- .sta_rc_update = rtw_ops_sta_rc_update,
+ .link_sta_rc_update = rtw_ops_sta_rc_update,
.set_sar_specs = rtw_ops_set_sar_specs,
#ifdef CONFIG_PM
.suspend = rtw_ops_suspend,
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index bbdef38c7e34..e91530ed05a0 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -202,6 +202,21 @@ static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif)
rtwvif->stats.rx_cnt = 0;
}
+static void rtw_sw_beacon_loss_check(struct rtw_dev *rtwdev,
+ struct rtw_vif *rtwvif, int received_beacons)
+{
+ int watchdog_delay = 2000000 / 1024; /* TU */
+ int beacon_int, expected_beacons;
+
+ if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !rtwvif)
+ return;
+
+ beacon_int = rtwvif_to_vif(rtwvif)->bss_conf.beacon_int;
+ expected_beacons = DIV_ROUND_UP(watchdog_delay, beacon_int);
+
+ rtwdev->beacon_loss = received_beacons < expected_beacons / 2;
+}
+
/* process TX/RX statistics periodically for hardware,
* the information helps hardware to enhance performance
*/
@@ -212,6 +227,7 @@ static void rtw_watch_dog_work(struct work_struct *work)
struct rtw_traffic_stats *stats = &rtwdev->stats;
struct rtw_watch_dog_iter_data data = {};
bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
+ int received_beacons = rtwdev->dm_info.cur_pkt_count.num_bcn_pkt;
u32 tx_unicast_mbps, rx_unicast_mbps;
bool ps_active;
@@ -258,6 +274,7 @@ static void rtw_watch_dog_work(struct work_struct *work)
rtw_leave_lps(rtwdev);
rtw_coex_wl_status_check(rtwdev);
rtw_coex_query_bt_hid_list(rtwdev);
+ rtw_coex_active_query_bt_info(rtwdev);
rtw_phy_dynamic_mechanism(rtwdev);
@@ -270,6 +287,8 @@ static void rtw_watch_dog_work(struct work_struct *work)
*/
rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data);
+ rtw_sw_beacon_loss_check(rtwdev, data.rtwvif, received_beacons);
+
/* fw supports only one station associated to enter lps, if there are
* more than two stations associated to the AP, then we can not enter
* lps, because fw does not handle the overlapped beacon interval
@@ -1309,7 +1328,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
rtw_fw_send_ra_info(rtwdev, si, reset_ra_mask);
}
-static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
+int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
{
const struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_fw_state *fw;
@@ -1329,6 +1348,7 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
return ret;
}
+EXPORT_SYMBOL(rtw_wait_firmware_completion);
static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev,
struct rtw_fw_state *fw)
@@ -1350,7 +1370,7 @@ static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev,
return LPS_DEEP_MODE_NONE;
}
-static int rtw_power_on(struct rtw_dev *rtwdev)
+int rtw_power_on(struct rtw_dev *rtwdev)
{
const struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_fw_state *fw = &rtwdev->fw;
@@ -1413,6 +1433,7 @@ err_off:
err:
return ret;
}
+EXPORT_SYMBOL(rtw_power_on);
void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
{
@@ -1485,7 +1506,7 @@ int rtw_core_start(struct rtw_dev *rtwdev)
{
int ret;
- ret = rtw_power_on(rtwdev);
+ ret = rtwdev->chip->ops->power_on(rtwdev);
if (ret)
return ret;
@@ -1505,12 +1526,13 @@ int rtw_core_start(struct rtw_dev *rtwdev)
return 0;
}
-static void rtw_power_off(struct rtw_dev *rtwdev)
+void rtw_power_off(struct rtw_dev *rtwdev)
{
rtw_hci_stop(rtwdev);
rtw_coex_power_off_setting(rtwdev);
rtw_mac_power_off(rtwdev);
}
+EXPORT_SYMBOL(rtw_power_off);
void rtw_core_stop(struct rtw_dev *rtwdev)
{
@@ -1535,7 +1557,7 @@ void rtw_core_stop(struct rtw_dev *rtwdev)
mutex_lock(&rtwdev->mutex);
- rtw_power_off(rtwdev);
+ rtwdev->chip->ops->power_off(rtwdev);
}
static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
@@ -1917,6 +1939,9 @@ static int rtw_dump_hw_feature(struct rtw_dev *rtwdev)
u8 bw;
int i;
+ if (!rtwdev->chip->hw_feature_report)
+ return 0;
+
id = rtw_read8(rtwdev, REG_C2HEVT);
if (id != C2H_HW_FEATURE_REPORT) {
rtw_err(rtwdev, "failed to read hw feature report\n");
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 945117afe143..cd09fb6f7b8b 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -189,6 +189,8 @@ enum rtw_chip_type {
RTW_CHIP_TYPE_8723D,
RTW_CHIP_TYPE_8821C,
RTW_CHIP_TYPE_8703B,
+ RTW_CHIP_TYPE_8821A,
+ RTW_CHIP_TYPE_8812A,
};
enum rtw_tx_queue_type {
@@ -841,6 +843,8 @@ struct rtw_regd {
};
struct rtw_chip_ops {
+ int (*power_on)(struct rtw_dev *rtwdev);
+ void (*power_off)(struct rtw_dev *rtwdev);
int (*mac_init)(struct rtw_dev *rtwdev);
int (*dump_fw_crash)(struct rtw_dev *rtwdev);
void (*shutdown)(struct rtw_dev *rtwdev);
@@ -848,9 +852,8 @@ struct rtw_chip_ops {
void (*phy_set_param)(struct rtw_dev *rtwdev);
void (*set_channel)(struct rtw_dev *rtwdev, u8 channel,
u8 bandwidth, u8 primary_chan_idx);
- void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_rx_status *rx_status);
+ void (*query_phy_status)(struct rtw_dev *rtwdev, u8 *phy_status,
+ struct rtw_rx_pkt_stat *pkt_stat);
u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
u32 addr, u32 mask);
bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
@@ -1096,17 +1099,20 @@ enum rtw_rfe_fem {
struct rtw_rfe_def {
const struct rtw_table *phy_pg_tbl;
const struct rtw_table *txpwr_lmt_tbl;
+ const struct rtw_pwr_track_tbl *pwr_track_tbl;
const struct rtw_table *agc_btg_tbl;
};
-#define RTW_DEF_RFE(chip, bb_pg, pwrlmt) { \
+#define RTW_DEF_RFE(chip, bb_pg, pwrlmt, track) { \
.phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \
.txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \
+ .pwr_track_tbl = &rtw ## chip ## _pwr_track_type ## track ## _tbl, \
}
-#define RTW_DEF_RFE_EXT(chip, bb_pg, pwrlmt, btg) { \
+#define RTW_DEF_RFE_EXT(chip, bb_pg, pwrlmt, track, btg) { \
.phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \
.txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \
+ .pwr_track_tbl = &rtw ## chip ## _pwr_track_type ## track ## _tbl, \
.agc_btg_tbl = &rtw ## chip ## _agc_btg_type ## btg ## _tbl, \
}
@@ -1167,7 +1173,7 @@ enum rtw_fwcd_item {
/* hardware configuration for each IC */
struct rtw_chip_info {
- struct rtw_chip_ops *ops;
+ const struct rtw_chip_ops *ops;
u8 id;
const char *fw_name;
@@ -1184,7 +1190,7 @@ struct rtw_chip_info {
u32 fw_rxff_size;
u16 rsvd_drv_pg_num;
u8 band;
- u8 page_size;
+ u16 page_size;
u8 csi_buf_pg_num;
u8 dig_max;
u8 dig_min;
@@ -1199,6 +1205,9 @@ struct rtw_chip_info {
const struct rtw_fwcd_segs *fwcd_segs;
u8 usb_tx_agg_desc_num;
+ bool hw_feature_report;
+ u8 c2h_ra_report_size;
+ bool old_datarate_fb_limit;
u8 default_1ss_tx_path;
@@ -1209,8 +1218,8 @@ struct rtw_chip_info {
/* init values */
u8 sys_func_en;
- const struct rtw_pwr_seq_cmd **pwr_on_seq;
- const struct rtw_pwr_seq_cmd **pwr_off_seq;
+ const struct rtw_pwr_seq_cmd * const *pwr_on_seq;
+ const struct rtw_pwr_seq_cmd * const *pwr_off_seq;
const struct rtw_rqpn *rqpn_table;
const struct rtw_prioq_addrs *prioq_addrs;
const struct rtw_page_table *page_table;
@@ -1237,12 +1246,11 @@ struct rtw_chip_info {
u16 dpd_ratemask;
u8 iqk_threshold;
u8 lck_threshold;
- const struct rtw_pwr_track_tbl *pwr_track_tbl;
u8 bfer_su_max_num;
u8 bfer_mu_max_num;
- struct rtw_hw_reg_offset *edcca_th;
+ const struct rtw_hw_reg_offset *edcca_th;
s8 l2h_th_ini_cs;
s8 l2h_th_ini_ad;
@@ -1486,6 +1494,7 @@ struct rtw_coex_stat {
u8 bt_hid_slot;
u8 bt_a2dp_bitpool;
u8 bt_iqk_state;
+ u8 bt_disable_cnt;
u16 wl_beacon_interval;
u8 wl_noisy_level;
@@ -1709,7 +1718,7 @@ struct rtw_dm_info {
bool pwr_trk_init_trigger;
struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX];
s8 txagc_remnant_cck;
- s8 txagc_remnant_ofdm;
+ s8 txagc_remnant_ofdm[RTW_RF_PATH_MAX];
u8 rx_cck_agc_report_type;
/* backup dack results for each path and I/Q */
@@ -1832,6 +1841,20 @@ struct rtw_phy_cond {
#define BRANCH_ENDIF 3
};
+struct rtw_phy_cond2 {
+#ifdef __LITTLE_ENDIAN
+ u8 type_glna;
+ u8 type_gpa;
+ u8 type_alna;
+ u8 type_apa;
+#else
+ u8 type_apa;
+ u8 type_alna;
+ u8 type_gpa;
+ u8 type_glna;
+#endif
+};
+
struct rtw_fifo_conf {
/* tx fifo information */
u16 rsvd_boundary;
@@ -1913,6 +1936,7 @@ struct rtw_hal {
u8 oem_id;
u8 pkg_type;
struct rtw_phy_cond phy_cond;
+ struct rtw_phy_cond2 phy_cond2;
bool rfe_btg;
u8 ps_mode;
@@ -1935,6 +1959,7 @@ struct rtw_hal {
u32 antenna_rx;
u8 bfee_sts_cap;
bool txrx_1ss;
+ bool cck_high_power;
/* protect tx power section */
struct mutex tx_power_mutex;
@@ -2190,6 +2215,7 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool hw_scan);
int rtw_core_start(struct rtw_dev *rtwdev);
+void rtw_power_off(struct rtw_dev *rtwdev);
void rtw_core_stop(struct rtw_dev *rtwdev);
int rtw_chip_info_setup(struct rtw_dev *rtwdev);
int rtw_core_init(struct rtw_dev *rtwdev);
@@ -2204,6 +2230,8 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
bool fw_exist);
void rtw_fw_recovery(struct rtw_dev *rtwdev);
+int rtw_wait_firmware_completion(struct rtw_dev *rtwdev);
+int rtw_power_on(struct rtw_dev *rtwdev);
void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size,
u32 fwcd_item);
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 0b9b8807af2c..0ecaefc4c83d 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -824,7 +824,7 @@ static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev,
pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
memset(pkt_desc, 0, tx_pkt_desc_sz);
pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue);
- rtw_tx_fill_tx_desc(pkt_info, skb);
+ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
dma = dma_map_single(&rtwpci->pdev->dev, skb->data, skb->len,
DMA_TO_DEVICE);
if (dma_mapping_error(&rtwpci->pdev->dev, dma))
@@ -1065,7 +1065,7 @@ static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE,
DMA_FROM_DEVICE);
rx_desc = skb->data;
- chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
+ rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
/* offset from rx_desc to payload */
pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
index 37ef80c9091d..8ed20c89d216 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.c
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
@@ -18,7 +18,10 @@ struct phy_cfg_pair {
};
union phy_table_tile {
- struct rtw_phy_cond cond;
+ struct {
+ struct rtw_phy_cond cond;
+ struct rtw_phy_cond2 cond2;
+ } __packed;
struct phy_cfg_pair cfg;
};
@@ -123,7 +126,7 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev)
void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l)
{
- struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
+ const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
rtw_write32_mask(rtwdev,
edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr,
@@ -527,6 +530,13 @@ static void rtw_phy_dig(struct rtw_dev *rtwdev)
*/
rtw_phy_dig_recorder(dm_info, cur_igi, fa_cnt);
+ /* Mitigate beacon loss and connectivity issues, mainly (only?)
+ * in the 5 GHz band
+ */
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A && rtwdev->beacon_loss &&
+ linked && dm_info->total_fa_cnt < DIG_PERF_FA_TH_EXTRA_HIGH)
+ cur_igi = DIG_CVRG_MIN;
+
if (cur_igi != pre_igi)
rtw_phy_dig_write(rtwdev, cur_igi);
}
@@ -1041,7 +1051,8 @@ void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg)
{
struct rtw_hal *hal = &rtwdev->hal;
struct rtw_efuse *efuse = &rtwdev->efuse;
- struct rtw_phy_cond cond = {0};
+ struct rtw_phy_cond cond = {};
+ struct rtw_phy_cond2 cond2 = {};
cond.cut = hal->cut_version ? hal->cut_version : 15;
cond.pkg = pkg ? pkg : 15;
@@ -1061,15 +1072,34 @@ void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg)
break;
}
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A ||
+ rtwdev->chip->id == RTW_CHIP_TYPE_8821A) {
+ cond.rfe = 0;
+ cond.rfe |= efuse->ext_lna_2g;
+ cond.rfe |= efuse->ext_pa_2g << 1;
+ cond.rfe |= efuse->ext_lna_5g << 2;
+ cond.rfe |= efuse->ext_pa_5g << 3;
+ cond.rfe |= efuse->btcoex << 4;
+
+ cond2.type_alna = efuse->alna_type;
+ cond2.type_glna = efuse->glna_type;
+ cond2.type_apa = efuse->apa_type;
+ cond2.type_gpa = efuse->gpa_type;
+ }
+
hal->phy_cond = cond;
+ hal->phy_cond2 = cond2;
- rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x\n", *((u32 *)&hal->phy_cond));
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x cond2=0x%08x\n",
+ *((u32 *)&hal->phy_cond), *((u32 *)&hal->phy_cond2));
}
-static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond)
+static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond,
+ struct rtw_phy_cond2 cond2)
{
struct rtw_hal *hal = &rtwdev->hal;
struct rtw_phy_cond drv_cond = hal->phy_cond;
+ struct rtw_phy_cond2 drv_cond2 = hal->phy_cond2;
if (cond.cut && cond.cut != drv_cond.cut)
return false;
@@ -1080,8 +1110,29 @@ static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond)
if (cond.intf && cond.intf != drv_cond.intf)
return false;
- if (cond.rfe != drv_cond.rfe)
- return false;
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A ||
+ rtwdev->chip->id == RTW_CHIP_TYPE_8821A) {
+ if (!(cond.rfe & 0x0f))
+ return true;
+
+ if ((cond.rfe & drv_cond.rfe) != cond.rfe)
+ return false;
+
+ if ((cond.rfe & BIT(0)) && cond2.type_glna != drv_cond2.type_glna)
+ return false;
+
+ if ((cond.rfe & BIT(1)) && cond2.type_gpa != drv_cond2.type_gpa)
+ return false;
+
+ if ((cond.rfe & BIT(2)) && cond2.type_alna != drv_cond2.type_alna)
+ return false;
+
+ if ((cond.rfe & BIT(3)) && cond2.type_apa != drv_cond2.type_apa)
+ return false;
+ } else {
+ if (cond.rfe != drv_cond.rfe)
+ return false;
+ }
return true;
}
@@ -1090,7 +1141,8 @@ void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl)
{
const union phy_table_tile *p = tbl->data;
const union phy_table_tile *end = p + tbl->size / 2;
- struct rtw_phy_cond pos_cond = {0};
+ struct rtw_phy_cond pos_cond = {};
+ struct rtw_phy_cond2 pos_cond2 = {};
bool is_matched = true, is_skipped = false;
BUILD_BUG_ON(sizeof(union phy_table_tile) != sizeof(struct phy_cfg_pair));
@@ -1109,11 +1161,12 @@ void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl)
case BRANCH_ELIF:
default:
pos_cond = p->cond;
+ pos_cond2 = p->cond2;
break;
}
} else if (p->cond.neg) {
if (!is_skipped) {
- if (check_positive(rtwdev, pos_cond)) {
+ if (check_positive(rtwdev, pos_cond, pos_cond2)) {
is_matched = true;
is_skipped = true;
} else {
@@ -1470,10 +1523,8 @@ static void rtw_phy_store_tx_power_by_rate(struct rtw_dev *rtwdev,
rate = rates[i];
if (band == PHY_BAND_2G)
hal->tx_pwr_by_rate_offset_2g[rfpath][rate] = offset;
- else if (band == PHY_BAND_5G)
- hal->tx_pwr_by_rate_offset_5g[rfpath][rate] = offset;
else
- continue;
+ hal->tx_pwr_by_rate_offset_5g[rfpath][rate] = offset;
}
}
@@ -2125,8 +2176,8 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw,
*limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path,
rate, ch, regd);
- *remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck :
- dm_info->txagc_remnant_ofdm);
+ *remnant = rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck :
+ dm_info->txagc_remnant_ofdm[path];
*sar = rtw_phy_get_tx_power_sar(rtwdev, hal->sar_band, path, rate);
}
@@ -2340,7 +2391,8 @@ void rtw_phy_init_tx_power(struct rtw_dev *rtwdev)
void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
struct rtw_swing_table *swing_table)
{
- const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
+ const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);
+ const struct rtw_pwr_track_tbl *tbl = rfe_def->pwr_track_tbl;
u8 channel = rtwdev->hal.current_channel;
if (IS_CH_2G_BAND(channel)) {
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 4d9b8668e8b0..e4d506cf9c33 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -9,6 +9,7 @@
#define BIT_FEN_EN_25_1 BIT(13)
#define BIT_FEN_ELDR BIT(12)
#define BIT_FEN_CPUEN BIT(2)
+#define BIT_FEN_USBA BIT(2)
#define BIT_FEN_BB_GLB_RST BIT(1)
#define BIT_FEN_BB_RSTB BIT(0)
#define BIT_R_DIS_PRST BIT(6)
@@ -16,6 +17,10 @@
#define REG_SYS_PW_CTRL 0x0004
#define BIT_PFM_WOWL BIT(3)
#define BIT_APFM_OFFMAC BIT(9)
+#define REG_APS_FSMCO 0x0004
+#define APS_FSMCO_MAC_ENABLE BIT(8)
+#define APS_FSMCO_MAC_OFF BIT(9)
+#define APS_FSMCO_HW_POWERDOWN BIT(15)
#define REG_SYS_CLK_CTRL 0x0008
#define BIT_CPU_CLK_EN BIT(14)
@@ -58,6 +63,8 @@
#define BIT_SHIFT_LDO25_VOLTAGE 4
#define BIT_LDO25_EN BIT(7)
+#define REG_ACLK_MON 0x3e
+
#define REG_GPIO_MUXCFG 0x0040
#define BIT_FSPI_EN BIT(19)
#define BIT_EN_SIC BIT(12)
@@ -90,6 +97,8 @@
#define BIT_USB_SUS_DIS BIT(8)
#define BIT_SDIO_PAD_E5 BIT(18)
+#define REG_RF_B_CTRL 0x76
+
#define REG_AFE_CTRL_4 0x0078
#define BIT_CK320M_AFE_EN BIT(4)
#define BIT_EN_SYN BIT(15)
@@ -134,6 +143,11 @@
#define REG_PMC_DBG_CTRL1 0xa8
#define BITS_PMC_BT_IQK_STS GENMASK(22, 21)
+#define REG_HIMR0 0xb0
+#define REG_HISR0 0xb4
+#define REG_HIMR1 0xb8
+#define REG_HISR1 0xbc
+
#define REG_PAD_CTRL2 0x00C4
#define BIT_RSM_EN_V1 BIT(16)
#define BIT_NO_PDN_CHIPOFF_V1 BIT(17)
@@ -185,6 +199,15 @@
#define MAC_TRX_ENABLE (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | \
BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | \
BIT_MACTXEN | BIT_MACRXEN)
+#define REG_PBP 0x104
+#define PBP_RX_MASK 0x0f
+#define PBP_TX_MASK 0xf0
+#define PBP_64 0x0
+#define PBP_128 0x1
+#define PBP_256 0x2
+#define PBP_512 0x3
+#define PBP_1024 0x4
+
#define BIT_SHIFT_TXDMA_VOQ_MAP 4
#define BIT_MASK_TXDMA_VOQ_MAP 0x3
#define BIT_TXDMA_VOQ_MAP(x) \
@@ -256,6 +279,8 @@
#define REG_HMEBOX1 0x01D4
#define REG_HMEBOX2 0x01D8
#define REG_HMEBOX3 0x01DC
+#define REG_LLT_INIT 0x01E0
+#define BIT_LLT_WRITE_ACCESS BIT(30)
#define REG_HMEBOX0_EX 0x01F0
#define REG_HMEBOX1_EX 0x01F4
#define REG_HMEBOX2_EX 0x01F8
@@ -298,6 +323,7 @@
#define REG_AUTO_LLT 0x0224
#define BIT_AUTO_INIT_LLT BIT(16)
+#define REG_DWBCN1_CTRL 0x0228
#define REG_RQPN_CTRL_1 0x0228
#define REG_RQPN_CTRL_2 0x022C
#define BIT_LD_RQPN BIT(31)
@@ -329,6 +355,7 @@
#define BIT_DMA_BURST_SIZE_1024 0
#define REG_RXPKTNUM 0x02B0
+#define REG_EARLY_MODE_CONTROL 0x02BC
#define REG_INT_MIG 0x0304
#define REG_HCI_MIX_CFG 0x03FC
@@ -336,6 +363,7 @@
#define REG_BCNQ_INFO 0x0418
#define BIT_MGQ_CPU_EMPTY BIT(24)
+#define REG_TXPKT_EMPTY 0x041A
#define REG_FWHW_TXQ_CTRL 0x0420
#define BIT_EN_BCNQ_DL BIT(22)
#define BIT_EN_WR_FREE_TAIL BIT(20)
@@ -362,10 +390,12 @@
#define REG_AMPDU_MAX_TIME_V1 0x0455
#define REG_BCNQ1_BDNY_V1 0x0456
#define REG_AMPDU_MAX_TIME 0x0456
+#define REG_AMPDU_MAX_LENGTH 0x0458
#define REG_WMAC_LBK_BF_HD 0x045D
#define REG_TX_HANG_CTRL 0x045E
#define BIT_EN_GNT_BT_AWAKE BIT(3)
#define BIT_EN_EOF_V1 BIT(2)
+#define REG_FAST_EDCA_CTRL 0x0460
#define REG_DATA_SC 0x0483
#define REG_ARFR2_V1 0x048C
#define REG_ARFRH2_V1 0x0490
@@ -390,6 +420,8 @@
#define REG_PRECNT_CTRL 0x04E5
#define BIT_BTCCA_CTRL (BIT(0) | BIT(1))
#define BIT_EN_PRECNT BIT(11)
+#define REG_TX_RPT_CTRL 0x04EC
+#define REG_TX_RPT_TIME 0x04F0
#define REG_DUMMY_PAGE4_V1 0x04FC
#define REG_EDCA_VO_PARAM 0x0500
@@ -400,6 +432,7 @@
#define BIT_MASK_CWMAX GENMASK(15, 12)
#define BIT_MASK_CWMIN GENMASK(11, 8)
#define BIT_MASK_AIFS GENMASK(7, 0)
+#define REG_BCNTCFG 0x0510
#define REG_PIFS 0x0512
#define REG_SIFS 0x0514
#define BIT_SHIFT_SIFS_OFDM_CTX 8
@@ -526,6 +559,8 @@
#define REG_BT_COEX_V2 0x0762
#define BIT_GNT_BT_POLARITY BIT(12)
#define BIT_LTE_COEX_EN BIT(7)
+#define REG_GNT_BT 0x0765
+#define BIT_PTA_SW_CTL GENMASK(4, 3)
#define REG_BT_COEX_ENH_INTR_CTRL 0x76E
#define BIT_R_GRANTALL_WLMASK BIT(3)
#define BIT_STATIS_BT_EN BIT(2)
@@ -543,14 +578,43 @@
#define REG_FPGA0_RFMOD 0x0800
#define BIT_CCKEN BIT(24)
#define BIT_OFDMEN BIT(25)
+#define REG_CCK_RPT_FORMAT 0x0804
+#define BIT_CCK_RPT_FORMAT BIT(16)
+#define REG_RXPSEL 0x0808
+#define BIT_RX_PSEL_RST (BIT(28) | BIT(29))
+#define REG_TXPSEL 0x080C
#define REG_RX_GAIN_EN 0x081c
+#define REG_CCASEL 0x082C
+#define REG_PDMFTH 0x0830
+#define REG_BWINDICATION 0x0834
+#define REG_CCA2ND 0x0838
+#define REG_L1PKTH 0x0848
+#define REG_CLKTRK 0x0860
+#define REG_ADCCLK 0x08AC
+#define REG_HSSI_READ 0x08B0
+#define REG_FPGA0_XCD_RF_PARA 0x08B4
+#define REG_RX_MCS_LIMIT 0x08BC
+#define REG_ADC160 0x08C4
+#define REG_ANTSEL_SW 0x0900
+#define REG_DAC_RSTB 0x090c
+#define REG_SINGLE_TONE_CONT_TX 0x0914
#define REG_RFE_CTRL_E 0x0974
#define REG_2ND_CCA_CTRL 0x0976
+#define REG_IQK_COM00 0x0978
+#define REG_IQK_COM32 0x097c
+#define REG_IQK_COM64 0x0980
+#define REG_IQK_COM96 0x0984
+
+#define REG_FAS 0x09a4
+#define REG_RXSB 0x0a00
+#define REG_CCK_RX 0x0a04
+#define REG_CCK_PD_TH 0x0a0a
#define REG_CCK0_FAREPORT 0xa2c
#define BIT_CCK0_2RX BIT(18)
#define BIT_CCK0_MRC BIT(22)
+#define REG_FA_CCK 0x0a5c
#define REG_DIS_DPD 0x0a70
#define DIS_DPD_MASK GENMASK(9, 0)
@@ -566,13 +630,109 @@
#define DIS_DPD_RATEVHT2SS_MCS1 BIT(9)
#define DIS_DPD_RATEALL GENMASK(9, 0)
+#define REG_CNTRST 0x0b58
+
+#define REG_3WIRE_SWA 0x0c00
+#define REG_RX_IQC_AB_A 0x0c10
+#define REG_TXSCALE_A 0x0c1c
+#define BB_SWING_MASK GENMASK(31, 21)
+#define REG_TX_AGC_A_CCK_11_CCK_1 0xc20
+#define REG_TX_AGC_A_OFDM18_OFDM6 0xc24
+#define REG_TX_AGC_A_OFDM54_OFDM24 0xc28
+#define REG_TX_AGC_A_MCS3_MCS0 0xc2c
+#define REG_TX_AGC_A_MCS7_MCS4 0xc30
+#define REG_TX_AGC_A_MCS11_MCS8 0xc34
+#define REG_TX_AGC_A_MCS15_MCS12 0xc38
+#define REG_TX_AGC_A_NSS1_INDEX3_NSS1_INDEX0 0xc3c
+#define REG_TX_AGC_A_NSS1_INDEX7_NSS1_INDEX4 0xc40
+#define REG_TX_AGC_A_NSS2_INDEX1_NSS1_INDEX8 0xc44
+#define REG_TX_AGC_A_NSS2_INDEX5_NSS2_INDEX2 0xc48
+#define REG_TX_AGC_A_NSS2_INDEX9_NSS2_INDEX6 0xc4c
+#define REG_RXIGI_A 0x0c50
+#define REG_TX_PWR_TRAINING_A 0x0c54
+#define REG_CK_MONHA 0x0c5c
+#define REG_AFE_PWR1_A 0x0c60
+#define REG_AFE_PWR2_A 0x0c64
+#define REG_RX_WAIT_CCA_TX_CCK_RFON_A 0x0c68
+#define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80
+#define REG_OFDM0_A_TX_AFE 0x0c84
+#define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88
+#define REG_TSSI_TRK_SW 0x0c8c
+#define REG_LSSI_WRITE_A 0x0c90
+#define REG_PREDISTA 0x0c90
+#define REG_TXAGCIDX 0x0c94
+
+#define REG_RFE_PINMUX_A 0x0cb0
+#define REG_RFE_INV_A 0x0cb4
#define REG_RFE_CTRL8 0x0cb4
#define BIT_MASK_RFE_SEL89 GENMASK(7, 0)
+#define PTA_CTRL_PIN 0x66
+#define DPDT_CTRL_PIN 0x77
+#define RFE_INV_MASK 0x3ff00000
+#define REG_RFECTL_A 0x0cb8
#define REG_RFE_INV8 0x0cbd
#define BIT_MASK_RFE_INV89 GENMASK(1, 0)
#define REG_RFE_INV16 0x0cbe
#define BIT_RFE_BUF_EN BIT(3)
+#define REG_IQK_DPD_CFG 0x0cc4
+#define REG_CFG_PMPD 0x0cc8
+#define REG_IQC_Y 0x0ccc
+#define REG_IQC_X 0x0cd4
+#define REG_INTPO_SETA 0x0ce8
+
+#define REG_IQKA_END 0x0d00
+#define REG_PI_READ_A 0x0d04
+#define REG_SI_READ_A 0x0d08
+#define REG_IQKB_END 0x0d40
+#define REG_PI_READ_B 0x0d44
+#define REG_SI_READ_B 0x0d48
+
+#define REG_3WIRE_SWB 0x0e00
+#define REG_RX_IQC_AB_B 0x0e10
+#define REG_TXSCALE_B 0x0e1c
+#define REG_TX_AGC_B_CCK_11_CCK_1 0xe20
+#define REG_TX_AGC_B_OFDM18_OFDM6 0xe24
+#define REG_TX_AGC_B_OFDM54_OFDM24 0xe28
+#define REG_TX_AGC_B_MCS3_MCS0 0xe2c
+#define REG_TX_AGC_B_MCS7_MCS4 0xe30
+#define REG_TX_AGC_B_MCS11_MCS8 0xe34
+#define REG_TX_AGC_B_MCS15_MCS12 0xe38
+#define REG_TX_AGC_B_NSS1_INDEX3_NSS1_INDEX0 0xe3c
+#define REG_TX_AGC_B_NSS1_INDEX7_NSS1_INDEX4 0xe40
+#define REG_TX_AGC_B_NSS2_INDEX1_NSS1_INDEX8 0xe44
+#define REG_TX_AGC_B_NSS2_INDEX5_NSS2_INDEX2 0xe48
+#define REG_TX_AGC_B_NSS2_INDEX9_NSS2_INDEX6 0xe4c
+#define REG_RXIGI_B 0x0e50
+#define REG_TX_PWR_TRAINING_B 0x0e54
+#define REG_CK_MONHB 0x0e5c
+#define REG_AFE_PWR1_B 0x0e60
+#define REG_AFE_PWR2_B 0x0e64
+#define REG_RX_WAIT_CCA_TX_CCK_RFON_B 0x0e68
+#define REG_TXTONEB 0x0e80
+#define REG_RXTONEB 0x0e84
+#define REG_TXPITMB 0x0e88
+#define REG_RXPITMB 0x0e8c
+#define REG_LSSI_WRITE_B 0x0e90
+#define REG_PREDISTB 0x0e90
+#define REG_INIDLYB 0x0e94
+#define REG_RFE_PINMUX_B 0x0eb0
+#define REG_RFE_INV_B 0x0eb4
+#define REG_RFECTL_B 0x0eb8
+#define REG_BPBDB 0x0ec4
+#define REG_PHYTXONB 0x0ec8
+#define REG_IQKYB 0x0ecc
+#define REG_IQKXB 0x0ed4
+#define REG_INTPO_SETB 0x0ee8
+
+#define REG_CRC_CCK 0x0f04
+#define REG_CCA_OFDM 0x0f08
+#define REG_CRC_VHT 0x0f0c
+#define REG_CRC_HT 0x0f10
+#define REG_CRC_OFDM 0x0f14
+#define REG_FA_OFDM 0x0f48
+#define REG_CCA_CCK 0x0fcc
+
#define REG_ANAPARSW_MAC_0 0x1010
#define BIT_CF_L_V2 GENMASK(29, 28)
@@ -709,6 +869,10 @@
#define REG_IGN_GNTBT4 0x4160
+#define REG_USB_MOD 0xf008
+#define REG_USB3_RXITV 0xf050
+#define REG_USB_HRPWM 0xfe58
+
#define RF_MODE 0x00
#define RF_MODOPT 0x01
#define RF_WLINT 0x01
@@ -716,7 +880,13 @@
#define RF_DTXLOK 0x08
#define RF_CFGCH 0x18
#define BIT_BAND GENMASK(18, 16)
+#define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8))
+#define RF18_CHANNEL_MASK (MASKBYTE0)
+#define RF18_RFSI_MASK (BIT(18) | BIT(17))
#define RF_RCK 0x1d
+#define RF_MODE_TABLE_ADDR 0x30
+#define RF_MODE_TABLE_DATA0 0x31
+#define RF_MODE_TABLE_DATA1 0x32
#define RF_LUTWA 0x33
#define RF_LUTWD1 0x3e
#define RF_LUTWD0 0x3f
@@ -725,10 +895,14 @@
#define RF_T_METER 0x42
#define RF_BSPAD 0x54
#define RF_GAINTX 0x56
+#define RF_TXMOD 0x58
#define RF_TXATANK 0x64
+#define RF_TXA_PREPAD 0x65
#define RF_TRXIQ 0x66
#define RF_RXIQGEN 0x8d
+#define RF_RXBB2 0x8f
#define RF_SYN_PFD 0xb0
+#define RF_LCK 0xb4
#define RF_XTALX2 0xb8
#define RF_SYN_CTRL 0xbb
#define RF_MALSEL 0xbe
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
index 222608de33cd..a19b94d022ee 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
@@ -29,9 +29,6 @@
#define TBTT_PROHIBIT_HOLD_TIME 0x80
#define TBTT_PROHIBIT_HOLD_TIME_STOP_BCN 0x64
-/* raw pkt_stat->drv_info_sz is in unit of 8-bytes */
-#define RX_DRV_INFO_SZ_UNIT_8703B 8
-
#define TRANS_SEQ_END \
0xFFFF, \
RTW_PWR_CUT_ALL_MSK, \
@@ -481,14 +478,14 @@ static const struct rtw_pwr_seq_cmd trans_act_to_lps_8703b[] = {
{TRANS_SEQ_END},
};
-static const struct rtw_pwr_seq_cmd *card_enable_flow_8703b[] = {
+static const struct rtw_pwr_seq_cmd * const card_enable_flow_8703b[] = {
trans_pre_enable_8703b,
trans_carddis_to_cardemu_8703b,
trans_cardemu_to_act_8703b,
NULL
};
-static const struct rtw_pwr_seq_cmd *card_disable_flow_8703b[] = {
+static const struct rtw_pwr_seq_cmd * const card_disable_flow_8703b[] = {
trans_act_to_lps_8703b,
trans_act_to_reset_mcu_8703b,
trans_act_to_cardemu_8703b,
@@ -496,11 +493,6 @@ static const struct rtw_pwr_seq_cmd *card_disable_flow_8703b[] = {
NULL
};
-static const struct rtw_rfe_def rtw8703b_rfe_defs[] = {
- [0] = { .phy_pg_tbl = &rtw8703b_bb_pg_tbl,
- .txpwr_lmt_tbl = &rtw8703b_txpwr_lmt_tbl,},
-};
-
static const struct rtw_page_table page_table_8703b[] = {
{12, 2, 2, 0, 1},
{12, 2, 2, 0, 1},
@@ -640,7 +632,7 @@ static void rtw8703b_pwrtrack_init(struct rtw_dev *rtwdev)
dm_info->pwr_trk_init_trigger = true;
dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
dm_info->txagc_remnant_cck = 0;
- dm_info->txagc_remnant_ofdm = 0;
+ dm_info->txagc_remnant_ofdm[RF_PATH_A] = 0;
}
static void rtw8703b_phy_set_param(struct rtw_dev *rtwdev)
@@ -1032,57 +1024,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
query_phy_status_ofdm(rtwdev, phy_status, pkt_stat);
}
-static void rtw8703b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_rx_status *rx_status)
-{
- struct ieee80211_hdr *hdr;
- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
- u8 *phy_status = NULL;
-
- memset(pkt_stat, 0, sizeof(*pkt_stat));
-
- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
- pkt_stat->ppdu_cnt = 0;
- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
-
- pkt_stat->drv_info_sz *= RX_DRV_INFO_SZ_UNIT_8703B;
-
- if (pkt_stat->is_c2h)
- return;
-
- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
- pkt_stat->drv_info_sz);
-
- pkt_stat->bw = GET_RX_DESC_BW(rx_desc);
-
- if (pkt_stat->phy_status) {
- phy_status = rx_desc + desc_sz + pkt_stat->shift;
- query_phy_status(rtwdev, phy_status, pkt_stat);
- }
-
- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
-
- /* Rtl8723cs driver checks for size < 14 or size > 8192 and
- * simply drops the packet. Maybe this should go into
- * rtw_rx_fill_rx_status()?
- */
- if (pkt_stat->pkt_len == 0) {
- rx_status->flag |= RX_FLAG_NO_PSDU;
- rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet");
- }
-}
-
#define ADDA_ON_VAL_8703B 0x03c00014
static
@@ -1643,7 +1584,7 @@ static void rtw8703b_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx,
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
- dm_info->txagc_remnant_ofdm = txagc_idx;
+ dm_info->txagc_remnant_ofdm[RF_PATH_A] = txagc_idx;
/* Only path A is calibrated for rtl8703b */
rtw8703b_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A);
@@ -1872,6 +1813,12 @@ static const struct rtw_pwr_track_tbl rtw8703b_rtw_pwr_track_tbl = {
.pwrtrk_xtal_p = rtw8703b_pwrtrk_xtal_p,
};
+static const struct rtw_rfe_def rtw8703b_rfe_defs[] = {
+ [0] = { .phy_pg_tbl = &rtw8703b_bb_pg_tbl,
+ .txpwr_lmt_tbl = &rtw8703b_txpwr_lmt_tbl,
+ .pwr_track_tbl = &rtw8703b_rtw_pwr_track_tbl, },
+};
+
/* Shared-Antenna Coex Table */
static const struct coex_table_para table_sant_8703b[] = {
{0xffffffff, 0xffffffff}, /* case-0 */
@@ -1941,14 +1888,16 @@ static const struct coex_tdma_para tdma_sant_8703b[] = {
{ {0x61, 0x08, 0x03, 0x11, 0x11} },
};
-static struct rtw_chip_ops rtw8703b_ops = {
+static const struct rtw_chip_ops rtw8703b_ops = {
+ .power_on = rtw_power_on,
+ .power_off = rtw_power_off,
.mac_init = rtw8723x_mac_init,
.dump_fw_crash = NULL,
.shutdown = NULL,
.read_efuse = rtw8703b_read_efuse,
.phy_set_param = rtw8703b_phy_set_param,
.set_channel = rtw8703b_set_channel,
- .query_rx_desc = rtw8703b_query_rx_desc,
+ .query_phy_status = query_phy_status,
.read_rf = rtw_phy_read_rf_sipi,
.write_rf = rtw_phy_write_rf_reg_sipi,
.set_tx_power_index = rtw8723x_set_tx_power_index,
@@ -2014,6 +1963,9 @@ const struct rtw_chip_info rtw8703b_hw_spec = {
.max_power_index = 0x3f,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
.usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */
+ .hw_feature_report = true,
+ .c2h_ra_report_size = 7,
+ .old_datarate_fb_limit = true,
.path_div_supported = false,
.ht_supported = true,
@@ -2046,7 +1998,6 @@ const struct rtw_chip_info rtw8703b_hw_spec = {
.rfe_defs_size = ARRAY_SIZE(rtw8703b_rfe_defs),
.iqk_threshold = 8,
- .pwr_track_tbl = &rtw8703b_rtw_pwr_track_tbl,
/* WOWLAN firmware exists, but not implemented yet */
.wow_fw_name = "rtw88/rtw8703b_wow_fw.bin",
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 3fba4054d45f..eeca31bf71f1 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -79,7 +79,7 @@ static void rtw8723d_pwrtrack_init(struct rtw_dev *rtwdev)
dm_info->pwr_trk_init_trigger = true;
dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
dm_info->txagc_remnant_cck = 0;
- dm_info->txagc_remnant_ofdm = 0;
+ dm_info->txagc_remnant_ofdm[RF_PATH_A] = 0;
}
static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
@@ -227,47 +227,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
}
}
-static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_rx_status *rx_status)
-{
- struct ieee80211_hdr *hdr;
- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
- u8 *phy_status = NULL;
-
- memset(pkt_stat, 0, sizeof(*pkt_stat));
-
- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
- pkt_stat->ppdu_cnt = 0;
- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
-
- /* drv_info_sz is in unit of 8-bytes */
- pkt_stat->drv_info_sz *= 8;
-
- /* c2h cmd pkt's rx/phy status is not interested */
- if (pkt_stat->is_c2h)
- return;
-
- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
- pkt_stat->drv_info_sz);
- if (pkt_stat->phy_status) {
- phy_status = rx_desc + desc_sz + pkt_stat->shift;
- query_phy_status(rtwdev, phy_status, pkt_stat);
- }
-
- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
-}
-
static bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev,
u8 channel, u32 thres)
{
@@ -1306,7 +1265,7 @@ static void rtw8723d_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx,
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
- dm_info->txagc_remnant_ofdm = txagc_idx;
+ dm_info->txagc_remnant_ofdm[RF_PATH_A] = txagc_idx;
rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A);
rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_B);
@@ -1430,10 +1389,12 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev)
dm_info->pwr_trk_triggered = false;
}
-static struct rtw_chip_ops rtw8723d_ops = {
+static const struct rtw_chip_ops rtw8723d_ops = {
+ .power_on = rtw_power_on,
+ .power_off = rtw_power_off,
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723x_read_efuse,
- .query_rx_desc = rtw8723d_query_rx_desc,
+ .query_phy_status = query_phy_status,
.set_channel = rtw8723d_set_channel,
.mac_init = rtw8723x_mac_init,
.shutdown = rtw8723d_shutdown,
@@ -1788,7 +1749,7 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8723d[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static const struct rtw_pwr_seq_cmd *card_enable_flow_8723d[] = {
+static const struct rtw_pwr_seq_cmd * const card_enable_flow_8723d[] = {
trans_carddis_to_cardemu_8723d,
trans_cardemu_to_act_8723d,
NULL
@@ -2004,7 +1965,7 @@ static const struct rtw_pwr_seq_cmd trans_act_to_post_carddis_8723d[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static const struct rtw_pwr_seq_cmd *card_disable_flow_8723d[] = {
+static const struct rtw_pwr_seq_cmd * const card_disable_flow_8723d[] = {
trans_act_to_lps_8723d,
trans_act_to_pre_carddis_8723d,
trans_act_to_cardemu_8723d,
@@ -2059,11 +2020,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8723d = {
.n_gen1_para = ARRAY_SIZE(pcie_gen1_param_8723d),
};
-static const struct rtw_rfe_def rtw8723d_rfe_defs[] = {
- [0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl,
- .txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,},
-};
-
static const u8 rtw8723d_pwrtrk_2gb_n[] = {
0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5,
6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10
@@ -2127,6 +2083,12 @@ static const struct rtw_pwr_track_tbl rtw8723d_rtw_pwr_track_tbl = {
.pwrtrk_xtal_n = rtw8723d_pwrtrk_xtal_n,
};
+static const struct rtw_rfe_def rtw8723d_rfe_defs[] = {
+ [0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl,
+ .txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,
+ .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl, },
+};
+
static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = {
{0x948, MASKDWORD, RTW_REG_DOMAIN_MAC32},
{0x67, BIT(7), RTW_REG_DOMAIN_MAC8},
@@ -2172,6 +2134,9 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
.page_size = TX_PAGE_SIZE,
.dig_min = 0x20,
.usb_tx_agg_desc_num = 1,
+ .hw_feature_report = true,
+ .c2h_ra_report_size = 7,
+ .old_datarate_fb_limit = true,
.ht_supported = true,
.vht_supported = false,
.lps_deep_mode_supported = 0,
@@ -2195,7 +2160,6 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
.rfe_defs = rtw8723d_rfe_defs,
.rfe_defs_size = ARRAY_SIZE(rtw8723d_rfe_defs),
.rx_ldpc = false,
- .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl,
.iqk_threshold = 8,
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
.max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723x.c b/drivers/net/wireless/realtek/rtw88/rtw8723x.c
index 0d0b6c2cb9aa..69f73cb5b4cd 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723x.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723x.c
@@ -595,7 +595,8 @@ void __rtw8723x_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
- const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
+ const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);
+ const struct rtw_pwr_track_tbl *tbl = rfe_def->pwr_track_tbl;
const s8 *pwrtrk_xtal;
s8 xtal_cap;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
new file mode 100644
index 000000000000..482edd31823d
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
@@ -0,0 +1,1102 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#include "main.h"
+#include "coex.h"
+#include "phy.h"
+#include "reg.h"
+#include "rtw88xxa.h"
+#include "rtw8812a.h"
+#include "rtw8812a_table.h"
+#include "tx.h"
+
+static void rtw8812a_power_off(struct rtw_dev *rtwdev)
+{
+ rtw88xxa_power_off(rtwdev, enter_lps_flow_8812a);
+}
+
+static s8 rtw8812a_cck_rx_pwr(u8 lna_idx, u8 vga_idx)
+{
+ s8 rx_pwr_all = 0;
+
+ switch (lna_idx) {
+ case 7:
+ if (vga_idx <= 27)
+ rx_pwr_all = -94 + 2 * (27 - vga_idx);
+ else
+ rx_pwr_all = -94;
+ break;
+ case 6:
+ rx_pwr_all = -42 + 2 * (2 - vga_idx);
+ break;
+ case 5:
+ rx_pwr_all = -36 + 2 * (7 - vga_idx);
+ break;
+ case 4:
+ rx_pwr_all = -30 + 2 * (7 - vga_idx);
+ break;
+ case 3:
+ rx_pwr_all = -18 + 2 * (7 - vga_idx);
+ break;
+ case 2:
+ rx_pwr_all = 2 * (5 - vga_idx);
+ break;
+ case 1:
+ rx_pwr_all = 14 - 2 * vga_idx;
+ break;
+ case 0:
+ rx_pwr_all = 20 - 2 * vga_idx;
+ break;
+ default:
+ break;
+ }
+
+ return rx_pwr_all;
+}
+
+static void rtw8812a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
+ struct rtw_rx_pkt_stat *pkt_stat)
+{
+ rtw88xxa_query_phy_status(rtwdev, phy_status, pkt_stat,
+ rtw8812a_cck_rx_pwr);
+
+ if (pkt_stat->rate >= DESC_RATE6M)
+ return;
+
+ if (rtwdev->hal.cck_high_power)
+ return;
+
+ if (pkt_stat->rssi >= 80)
+ pkt_stat->rssi = ((pkt_stat->rssi - 80) << 1) +
+ ((pkt_stat->rssi - 80) >> 1) + 80;
+ else if (pkt_stat->rssi <= 78 && pkt_stat->rssi >= 20)
+ pkt_stat->rssi += 3;
+}
+
+static void rtw8812a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
+{
+}
+
+static void rtw8812a_do_lck(struct rtw_dev *rtwdev)
+{
+ u32 cont_tx, lc_cal, i;
+
+ cont_tx = rtw_read32_mask(rtwdev, REG_SINGLE_TONE_CONT_TX, 0x70000);
+
+ lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
+
+ if (!cont_tx)
+ rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LCK, BIT(14), 1);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x08000, 1);
+
+ mdelay(150);
+
+ for (i = 0; i < 5; i++) {
+ if (rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x08000) != 1)
+ break;
+
+ mdelay(10);
+ }
+
+ if (i == 5)
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "LCK timed out\n");
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LCK, BIT(14), 0);
+
+ if (!cont_tx)
+ rtw_write8(rtwdev, REG_TXPAUSE, 0);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
+}
+
+static void rtw8812a_iqk_backup_rf(struct rtw_dev *rtwdev, u32 *rfa_backup,
+ u32 *rfb_backup, const u32 *backup_rf_reg,
+ u32 rf_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* Save RF Parameters */
+ for (i = 0; i < rf_num; i++) {
+ rfa_backup[i] = rtw_read_rf(rtwdev, RF_PATH_A,
+ backup_rf_reg[i], MASKDWORD);
+ rfb_backup[i] = rtw_read_rf(rtwdev, RF_PATH_B,
+ backup_rf_reg[i], MASKDWORD);
+ }
+}
+
+static void rtw8812a_iqk_restore_rf(struct rtw_dev *rtwdev,
+ enum rtw_rf_path path,
+ const u32 *backup_rf_reg,
+ u32 *RF_backup, u32 rf_reg_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ for (i = 0; i < rf_reg_num; i++)
+ rtw_write_rf(rtwdev, path, backup_rf_reg[i],
+ RFREG_MASK, RF_backup[i]);
+
+ rtw_write_rf(rtwdev, path, RF_LUTWE, RFREG_MASK, 0);
+}
+
+static void rtw8812a_iqk_restore_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
+ const u32 *backup_afe_reg, u32 afe_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* Reload AFE Parameters */
+ for (i = 0; i < afe_num; i++)
+ rtw_write32(rtwdev, backup_afe_reg[i], afe_backup[i]);
+
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x0);
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x0);
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x0);
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000);
+ rtw_write32_mask(rtwdev, REG_LSSI_WRITE_A, BIT(7), 1);
+ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(18), 1);
+ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(29), 1);
+ rtw_write32_mask(rtwdev, REG_CFG_PMPD, BIT(29), 1);
+
+ rtw_write32(rtwdev, REG_TXTONEB, 0x0);
+ rtw_write32(rtwdev, REG_RXTONEB, 0x0);
+ rtw_write32(rtwdev, REG_TXPITMB, 0x0);
+ rtw_write32(rtwdev, REG_RXPITMB, 0x3c000000);
+ rtw_write32_mask(rtwdev, REG_LSSI_WRITE_B, BIT(7), 1);
+ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(18), 1);
+ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(29), 1);
+ rtw_write32_mask(rtwdev, REG_PHYTXONB, BIT(29), 1);
+}
+
+static void rtw8812a_iqk_rx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path,
+ unsigned int rx_x, unsigned int rx_y)
+{
+ switch (path) {
+ case RF_PATH_A:
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ if (rx_x >> 1 >= 0x112 ||
+ (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) {
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x000003ff, 0x100);
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x03ff0000, 0);
+ } else {
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x000003ff, rx_x >> 1);
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x03ff0000, rx_y >> 1);
+ }
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx_x = %x;;rx_y = %x ====>fill to IQC\n",
+ rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "0xc10 = %x ====>fill to IQC\n",
+ rtw_read32(rtwdev, REG_RX_IQC_AB_A));
+ break;
+ case RF_PATH_B:
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ if (rx_x >> 1 >= 0x112 ||
+ (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) {
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
+ 0x000003ff, 0x100);
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
+ 0x03ff0000, 0);
+ } else {
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
+ 0x000003ff, rx_x >> 1);
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
+ 0x03ff0000, rx_y >> 1);
+ }
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx_x = %x;;rx_y = %x ====>fill to IQC\n",
+ rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "0xe10 = %x====>fill to IQC\n",
+ rtw_read32(rtwdev, REG_RX_IQC_AB_B));
+ break;
+ default:
+ break;
+ }
+}
+
+static void rtw8812a_iqk_tx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path,
+ unsigned int tx_x, unsigned int tx_y)
+{
+ switch (path) {
+ case RF_PATH_A:
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+ rtw_write32_mask(rtwdev, REG_PREDISTA, BIT(7), 0x1);
+ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(18), 0x1);
+ rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(29), 0x1);
+ rtw_write32_mask(rtwdev, REG_CFG_PMPD, BIT(29), 0x1);
+ rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, tx_y);
+ rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, tx_x);
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "tx_x = %x;;tx_y = %x =====> fill to IQC\n",
+ tx_x & 0x000007ff, tx_y & 0x000007ff);
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "0xcd4 = %x;;0xccc = %x ====>fill to IQC\n",
+ rtw_read32_mask(rtwdev, REG_IQC_X, 0x000007ff),
+ rtw_read32_mask(rtwdev, REG_IQC_Y, 0x000007ff));
+ break;
+ case RF_PATH_B:
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+ rtw_write32_mask(rtwdev, REG_PREDISTB, BIT(7), 0x1);
+ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(18), 0x1);
+ rtw_write32_mask(rtwdev, REG_BPBDB, BIT(29), 0x1);
+ rtw_write32_mask(rtwdev, REG_PHYTXONB, BIT(29), 0x1);
+ rtw_write32_mask(rtwdev, REG_IQKYB, 0x000007ff, tx_y);
+ rtw_write32_mask(rtwdev, REG_IQKXB, 0x000007ff, tx_x);
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "tx_x = %x;;tx_y = %x =====> fill to IQC\n",
+ tx_x & 0x000007ff, tx_y & 0x000007ff);
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "0xed4 = %x;;0xecc = %x ====>fill to IQC\n",
+ rtw_read32_mask(rtwdev, REG_IQKXB, 0x000007ff),
+ rtw_read32_mask(rtwdev, REG_IQKYB, 0x000007ff));
+ break;
+ default:
+ break;
+ }
+}
+
+static void rtw8812a_iqk(struct rtw_dev *rtwdev)
+{
+ int tx_x0_temp[10], tx_y0_temp[10], tx_x1_temp[10], tx_y1_temp[10];
+ int rx_x0_temp[10], rx_y0_temp[10], rx_x1_temp[10], rx_y1_temp[10];
+ bool iqk0_ready = false, tx0_finish = false, rx0_finish = false;
+ bool iqk1_ready = false, tx1_finish = false, rx1_finish = false;
+ u8 tx0_avg = 0, tx1_avg = 0, rx0_avg = 0, rx1_avg = 0;
+ int tx_x0 = 0, tx_y0 = 0, tx_x1 = 0, tx_y1 = 0;
+ int rx_x0 = 0, rx_y0 = 0, rx_x1 = 0, rx_y1 = 0;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ bool tx0_fail = true, rx0_fail = true;
+ bool tx1_fail = true, rx1_fail = true;
+ u8 cal0_retry, cal1_retry;
+ u8 delay_count;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* ========path-A AFE all on======== */
+ /* Port 0 DAC/ADC on */
+ rtw_write32(rtwdev, REG_AFE_PWR1_A, 0x77777777);
+ rtw_write32(rtwdev, REG_AFE_PWR2_A, 0x77777777);
+
+ /* Port 1 DAC/ADC on */
+ rtw_write32(rtwdev, REG_AFE_PWR1_B, 0x77777777);
+ rtw_write32(rtwdev, REG_AFE_PWR2_B, 0x77777777);
+
+ rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_A, 0x19791979);
+ rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_B, 0x19791979);
+
+ /* hardware 3-wire off */
+ rtw_write32_mask(rtwdev, REG_3WIRE_SWA, 0xf, 0x4);
+ rtw_write32_mask(rtwdev, REG_3WIRE_SWB, 0xf, 0x4);
+
+ /* DAC/ADC sampling rate (160 MHz) */
+ rtw_write32_mask(rtwdev, REG_CK_MONHA, GENMASK(26, 24), 0x7);
+ rtw_write32_mask(rtwdev, REG_CK_MONHB, GENMASK(26, 24), 0x7);
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ /* ====== path A TX IQK RF setting ====== */
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80002);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d5);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001);
+
+ /* ====== path B TX IQK RF setting ====== */
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x80002);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_TXA_PREPAD, RFREG_MASK, 0x931d5);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RXBB2, RFREG_MASK, 0x8a001);
+
+ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
+ rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1);
+ rtw_write32_mask(rtwdev, REG_INIDLYB, BIT(0), 0x1);
+ rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000); /* TX (X,Y) */
+ rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000); /* RX (X,Y) */
+ rtw_write32(rtwdev, REG_IQK_COM96, 0x00462910); /* [0]:AGC_en, [15]:idac_K_Mask */
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ if (efuse->ext_pa_5g) {
+ if (efuse->rfe_option == 1) {
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403e3);
+ rtw_write32(rtwdev, REG_TXPITMB, 0x821403e3);
+ } else {
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403f7);
+ rtw_write32(rtwdev, REG_TXPITMB, 0x821403f7);
+ }
+ } else {
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403f1);
+ rtw_write32(rtwdev, REG_TXPITMB, 0x821403f1);
+ }
+
+ if (rtwdev->hal.current_band_type == RTW_BAND_5G) {
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x68163e96);
+ rtw_write32(rtwdev, REG_RXPITMB, 0x68163e96);
+ } else {
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28163e96);
+ rtw_write32(rtwdev, REG_RXPITMB, 0x28163e96);
+
+ if (efuse->rfe_option == 3) {
+ if (efuse->ext_pa_2g)
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
+ 0x821403e3);
+ else
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
+ 0x821403f7);
+ }
+ }
+
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10);
+ rtw_write32(rtwdev, REG_INTPO_SETA, 0x00000000);
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_TXTONEB, 0x18008c10);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_RXTONEB, 0x38008c10);
+ rtw_write32(rtwdev, REG_INTPO_SETB, 0x00000000);
+
+ cal0_retry = 0;
+ cal1_retry = 0;
+ while (1) {
+ /* one shot */
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x00100000);
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
+
+ mdelay(10);
+
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x00000000);
+
+ for (delay_count = 0; delay_count < 20; delay_count++) {
+ if (!tx0_finish)
+ iqk0_ready = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ BIT(10));
+ if (!tx1_finish)
+ iqk1_ready = rtw_read32_mask(rtwdev,
+ REG_IQKB_END,
+ BIT(10));
+ if (iqk0_ready && iqk1_ready)
+ break;
+
+ mdelay(1);
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "TX delay_count = %d\n",
+ delay_count);
+
+ if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */
+ /* ============TXIQK Check============== */
+ tx0_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(12));
+ tx1_fail = rtw_read32_mask(rtwdev, REG_IQKB_END, BIT(12));
+
+ if (!(tx0_fail || tx0_finish)) {
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x02000000);
+ tx_x0_temp[tx0_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ 0x07ff0000);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x04000000);
+ tx_y0_temp[tx0_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ 0x07ff0000);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "tx_x0[%d] = %x ;; tx_y0[%d] = %x\n",
+ tx0_avg, tx_x0_temp[tx0_avg],
+ tx0_avg, tx_y0_temp[tx0_avg]);
+
+ tx_x0_temp[tx0_avg] <<= 21;
+ tx_y0_temp[tx0_avg] <<= 21;
+
+ tx0_avg++;
+ } else {
+ cal0_retry++;
+ if (cal0_retry == 10)
+ break;
+ }
+
+ if (!(tx1_fail || tx1_finish)) {
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x02000000);
+ tx_x1_temp[tx1_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKB_END,
+ 0x07ff0000);
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x04000000);
+ tx_y1_temp[tx1_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKB_END,
+ 0x07ff0000);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "tx_x1[%d] = %x ;; tx_y1[%d] = %x\n",
+ tx1_avg, tx_x1_temp[tx1_avg],
+ tx1_avg, tx_y1_temp[tx1_avg]);
+
+ tx_x1_temp[tx1_avg] <<= 21;
+ tx_y1_temp[tx1_avg] <<= 21;
+
+ tx1_avg++;
+ } else {
+ cal1_retry++;
+ if (cal1_retry == 10)
+ break;
+ }
+ } else {
+ cal0_retry++;
+ cal1_retry++;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "delay 20ms TX IQK Not Ready!!!!!\n");
+
+ if (cal0_retry == 10)
+ break;
+ }
+
+ if (tx0_avg >= 2)
+ tx0_finish = rtw88xxa_iqk_finish(tx0_avg, 4,
+ tx_x0_temp, tx_y0_temp, &tx_x0, &tx_y0,
+ false, false);
+
+ if (tx1_avg >= 2)
+ tx1_finish = rtw88xxa_iqk_finish(tx1_avg, 4,
+ tx_x1_temp, tx_y1_temp, &tx_x1, &tx_y1,
+ false, false);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "tx0_average = %d, tx1_average = %d\n",
+ tx0_avg, tx1_avg);
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "tx0_finish = %d, tx1_finish = %d\n",
+ tx0_finish, tx1_finish);
+
+ if (tx0_finish && tx1_finish)
+ break;
+
+ if ((cal0_retry + tx0_avg) >= 10 ||
+ (cal1_retry + tx1_avg) >= 10)
+ break;
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "TXA_cal_retry = %d\n", cal0_retry);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "TXB_cal_retry = %d\n", cal1_retry);
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ /* Load LOK */
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXMOD, 0x7fe00,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_DTXLOK, 0xffc00));
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_TXMOD, 0x7fe00,
+ rtw_read_rf(rtwdev, RF_PATH_B, RF_DTXLOK, 0xffc00));
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ if (tx0_finish) {
+ /* ====== path A RX IQK RF setting====== */
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
+ 0x30000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
+ 0x3f7ff);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
+ 0xfe7bf);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x88001);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d1);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000);
+ }
+ if (tx1_finish) {
+ /* ====== path B RX IQK RF setting====== */
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x80000);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_ADDR, RFREG_MASK,
+ 0x30000);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA0, RFREG_MASK,
+ 0x3f7ff);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA1, RFREG_MASK,
+ 0xfe7bf);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_RXBB2, RFREG_MASK, 0x88001);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_TXA_PREPAD, RFREG_MASK, 0x931d1);
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x00000);
+ }
+
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x1);
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x0);
+ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
+
+ if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE)
+ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a911);
+ else
+ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a890);
+
+ if (efuse->rfe_option == 1) {
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777717);
+ rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777717);
+ rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077);
+ } else {
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777717);
+ rtw_write32(rtwdev, REG_RFE_INV_A, 0x02000077);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777717);
+ rtw_write32(rtwdev, REG_RFE_INV_B, 0x02000077);
+ }
+
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ if (tx0_finish) {
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x38008c10);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x18008c10);
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x82140119);
+ }
+ if (tx1_finish) {
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_TXTONEB, 0x38008c10);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_RXTONEB, 0x18008c10);
+ rtw_write32(rtwdev, REG_TXPITMB, 0x82140119);
+ }
+
+ cal0_retry = 0;
+ cal1_retry = 0;
+ while (1) {
+ /* one shot */
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ if (tx0_finish) {
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000,
+ tx_x0 & 0x000007ff);
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF,
+ tx_y0 & 0x000007ff);
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+ if (efuse->rfe_option == 1)
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28161500);
+ else
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28160cc0);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00300000);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
+ mdelay(5);
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
+ }
+
+ if (tx1_finish) {
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000,
+ tx_x1 & 0x000007ff);
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF,
+ tx_y1 & 0x000007ff);
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+ if (efuse->rfe_option == 1)
+ rtw_write32(rtwdev, REG_RXPITMB, 0x28161500);
+ else
+ rtw_write32(rtwdev, REG_RXPITMB, 0x28160ca0);
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x00300000);
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x00100000);
+ mdelay(5);
+ rtw_write32(rtwdev, REG_RXPITMB, 0x3c000000);
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x00000000);
+ }
+
+ for (delay_count = 0; delay_count < 20; delay_count++) {
+ if (!rx0_finish && tx0_finish)
+ iqk0_ready = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ BIT(10));
+ if (!rx1_finish && tx1_finish)
+ iqk1_ready = rtw_read32_mask(rtwdev,
+ REG_IQKB_END,
+ BIT(10));
+ if (iqk0_ready && iqk1_ready)
+ break;
+
+ mdelay(1);
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "RX delay_count = %d\n",
+ delay_count);
+
+ if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */
+ /* ============RXIQK Check============== */
+ rx0_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(11));
+ rx1_fail = rtw_read32_mask(rtwdev, REG_IQKB_END, BIT(11));
+
+ if (!(rx0_fail || rx0_finish) && tx0_finish) {
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x06000000);
+ rx_x0_temp[rx0_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ 0x07ff0000);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x08000000);
+ rx_y0_temp[rx0_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ 0x07ff0000);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx_x0[%d] = %x ;; rx_y0[%d] = %x\n",
+ rx0_avg, rx_x0_temp[rx0_avg],
+ rx0_avg, rx_y0_temp[rx0_avg]);
+
+ rx_x0_temp[rx0_avg] <<= 21;
+ rx_y0_temp[rx0_avg] <<= 21;
+
+ rx0_avg++;
+ } else {
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "1. RXA_cal_retry = %d\n", cal0_retry);
+
+ cal0_retry++;
+ if (cal0_retry == 10)
+ break;
+ }
+
+ if (!(rx1_fail || rx1_finish) && tx1_finish) {
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x06000000);
+ rx_x1_temp[rx1_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKB_END,
+ 0x07ff0000);
+ rtw_write32(rtwdev, REG_RFECTL_B, 0x08000000);
+ rx_y1_temp[rx1_avg] = rtw_read32_mask(rtwdev,
+ REG_IQKB_END,
+ 0x07ff0000);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx_x1[%d] = %x ;; rx_y1[%d] = %x\n",
+ rx1_avg, rx_x1_temp[rx1_avg],
+ rx1_avg, rx_y1_temp[rx1_avg]);
+
+ rx_x1_temp[rx1_avg] <<= 21;
+ rx_y1_temp[rx1_avg] <<= 21;
+
+ rx1_avg++;
+ } else {
+ cal1_retry++;
+ if (cal1_retry == 10)
+ break;
+ }
+ } else {
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "2. RXA_cal_retry = %d\n", cal0_retry);
+
+ cal0_retry++;
+ cal1_retry++;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "delay 20ms RX IQK Not Ready!!!!!\n");
+
+ if (cal0_retry == 10)
+ break;
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "3. RXA_cal_retry = %d\n",
+ cal0_retry);
+
+ if (rx0_avg >= 2)
+ rx0_finish = rtw88xxa_iqk_finish(rx0_avg, 4,
+ rx_x0_temp, rx_y0_temp,
+ &rx_x0, &rx_y0,
+ true, false);
+
+ if (rx1_avg >= 2)
+ rx1_finish = rtw88xxa_iqk_finish(rx1_avg, 4,
+ rx_x1_temp, rx_y1_temp,
+ &rx_x1, &rx_y1,
+ true, false);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx0_average = %d, rx1_average = %d\n",
+ rx0_avg, rx1_avg);
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx0_finish = %d, rx1_finish = %d\n",
+ rx0_finish, rx1_finish);
+
+ if ((rx0_finish || !tx0_finish) && (rx1_finish || !tx1_finish))
+ break;
+
+ if ((cal0_retry + rx0_avg) >= 10 ||
+ (cal1_retry + rx1_avg) >= 10 ||
+ rx0_avg == 3 || rx1_avg == 3)
+ break;
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "RXA_cal_retry = %d\n", cal0_retry);
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "RXB_cal_retry = %d\n", cal1_retry);
+
+ /* FillIQK Result */
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "========Path_A =======\n");
+
+ if (tx0_finish)
+ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_A, tx_x0, tx_y0);
+ else
+ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_A, 0x200, 0x0);
+
+ if (rx0_finish)
+ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_A, rx_x0, rx_y0);
+ else
+ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_A, 0x200, 0x0);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK, "========Path_B =======\n");
+
+ if (tx1_finish)
+ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_B, tx_x1, tx_y1);
+ else
+ rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_B, 0x200, 0x0);
+
+ if (rx1_finish)
+ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_B, rx_x1, rx_y1);
+ else
+ rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_B, 0x200, 0x0);
+}
+
+#define MACBB_REG_NUM_8812A 9
+#define AFE_REG_NUM_8812A 12
+#define RF_REG_NUM_8812A 3
+
+static void rtw8812a_do_iqk(struct rtw_dev *rtwdev)
+{
+ static const u32 backup_macbb_reg[MACBB_REG_NUM_8812A] = {
+ 0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0xe00, 0x838, 0x82c
+ };
+ static const u32 backup_afe_reg[AFE_REG_NUM_8812A] = {
+ 0xc5c, 0xc60, 0xc64, 0xc68, 0xcb0, 0xcb4,
+ 0xe5c, 0xe60, 0xe64, 0xe68, 0xeb0, 0xeb4
+ };
+ static const u32 backup_rf_reg[RF_REG_NUM_8812A] = {
+ 0x65, 0x8f, 0x0
+ };
+ u32 macbb_backup[MACBB_REG_NUM_8812A] = {};
+ u32 afe_backup[AFE_REG_NUM_8812A] = {};
+ u32 rfa_backup[RF_REG_NUM_8812A] = {};
+ u32 rfb_backup[RF_REG_NUM_8812A] = {};
+ u32 reg_cb8, reg_eb8;
+
+ rtw88xxa_iqk_backup_mac_bb(rtwdev, macbb_backup,
+ backup_macbb_reg, MACBB_REG_NUM_8812A);
+
+ rtw_write32_set(rtwdev, REG_CCASEL, BIT(31));
+ reg_cb8 = rtw_read32(rtwdev, REG_RFECTL_A);
+ reg_eb8 = rtw_read32(rtwdev, REG_RFECTL_B);
+ rtw_write32_clr(rtwdev, REG_CCASEL, BIT(31));
+
+ rtw88xxa_iqk_backup_afe(rtwdev, afe_backup,
+ backup_afe_reg, AFE_REG_NUM_8812A);
+ rtw8812a_iqk_backup_rf(rtwdev, rfa_backup, rfb_backup,
+ backup_rf_reg, RF_REG_NUM_8812A);
+
+ rtw88xxa_iqk_configure_mac(rtwdev);
+
+ rtw8812a_iqk(rtwdev);
+
+ rtw8812a_iqk_restore_rf(rtwdev, RF_PATH_A, backup_rf_reg,
+ rfa_backup, RF_REG_NUM_8812A);
+ rtw8812a_iqk_restore_rf(rtwdev, RF_PATH_B, backup_rf_reg,
+ rfb_backup, RF_REG_NUM_8812A);
+
+ rtw8812a_iqk_restore_afe(rtwdev, afe_backup,
+ backup_afe_reg, AFE_REG_NUM_8812A);
+
+ rtw_write32_set(rtwdev, REG_CCASEL, BIT(31));
+ rtw_write32(rtwdev, REG_RFECTL_A, reg_cb8);
+ rtw_write32(rtwdev, REG_RFECTL_B, reg_eb8);
+ rtw_write32_clr(rtwdev, REG_CCASEL, BIT(31));
+
+ rtw88xxa_iqk_restore_mac_bb(rtwdev, macbb_backup,
+ backup_macbb_reg, MACBB_REG_NUM_8812A);
+}
+
+static void rtw8812a_phy_calibration(struct rtw_dev *rtwdev)
+{
+ u8 channel = rtwdev->hal.current_channel;
+
+ rtw8812a_do_iqk(rtwdev);
+
+ /* The official driver wants to do this after connecting
+ * but before first writing a new igi (phydm_get_new_igi).
+ * Here seems close enough.
+ */
+ if (channel >= 36 && channel <= 64)
+ rtw_load_table(rtwdev, &rtw8812a_agc_diff_lb_tbl);
+ else if (channel >= 100)
+ rtw_load_table(rtwdev, &rtw8812a_agc_diff_hb_tbl);
+}
+
+static void rtw8812a_pwr_track(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+ if (!dm_info->pwr_trk_triggered) {
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER,
+ GENMASK(17, 16), 0x03);
+ dm_info->pwr_trk_triggered = true;
+ return;
+ }
+
+ rtw88xxa_phy_pwrtrack(rtwdev, rtw8812a_do_lck, rtw8812a_do_iqk);
+ dm_info->pwr_trk_triggered = false;
+}
+
+static void rtw8812a_fill_txdesc_checksum(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *txdesc)
+{
+ fill_txdesc_checksum_common(txdesc, 16);
+}
+
+static void rtw8812a_coex_cfg_init(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw8812a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw8821a_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw8821a_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
+{
+}
+
+static void rtw8821a_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
+{
+}
+
+static const struct rtw_chip_ops rtw8812a_ops = {
+ .power_on = rtw88xxa_power_on,
+ .power_off = rtw8812a_power_off,
+ .phy_set_param = NULL,
+ .read_efuse = rtw88xxa_read_efuse,
+ .query_phy_status = rtw8812a_query_phy_status,
+ .set_channel = rtw88xxa_set_channel,
+ .mac_init = NULL,
+ .read_rf = rtw88xxa_phy_read_rf,
+ .write_rf = rtw_phy_write_rf_reg_sipi,
+ .set_antenna = NULL,
+ .set_tx_power_index = rtw88xxa_set_tx_power_index,
+ .cfg_ldo25 = rtw8812a_cfg_ldo25,
+ .efuse_grant = rtw88xxa_efuse_grant,
+ .false_alarm_statistics = rtw88xxa_false_alarm_statistics,
+ .phy_calibration = rtw8812a_phy_calibration,
+ .cck_pd_set = rtw88xxa_phy_cck_pd_set,
+ .pwr_track = rtw8812a_pwr_track,
+ .config_bfee = NULL,
+ .set_gid_table = NULL,
+ .cfg_csi_rate = NULL,
+ .fill_txdesc_checksum = rtw8812a_fill_txdesc_checksum,
+ .coex_set_init = rtw8812a_coex_cfg_init,
+ .coex_set_ant_switch = NULL,
+ .coex_set_gnt_fix = rtw8812a_coex_cfg_gnt_fix,
+ .coex_set_gnt_debug = NULL,
+ .coex_set_rfe_type = rtw8821a_coex_cfg_rfe_type,
+ .coex_set_wl_tx_power = rtw8821a_coex_cfg_wl_tx_power,
+ .coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain,
+};
+
+static const struct rtw_page_table page_table_8812a[] = {
+ /* hq_num, nq_num, lq_num, exq_num, gapq_num */
+ {0, 0, 0, 0, 0}, /* SDIO */
+ {0, 0, 0, 0, 0}, /* PCI */
+ {16, 0, 0, 0, 1}, /* 2 bulk out endpoints */
+ {16, 0, 16, 0, 1}, /* 3 bulk out endpoints */
+ {16, 0, 16, 0, 1}, /* 4 bulk out endpoints */
+};
+
+static const struct rtw_rqpn rqpn_table_8812a[] = {
+ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH,
+ RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+};
+
+static const struct rtw_prioq_addrs prioq_addrs_8812a = {
+ .prio[RTW_DMA_MAPPING_EXTRA] = {
+ .rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
+ },
+ .prio[RTW_DMA_MAPPING_LOW] = {
+ .rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
+ },
+ .prio[RTW_DMA_MAPPING_NORMAL] = {
+ .rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
+ },
+ .prio[RTW_DMA_MAPPING_HIGH] = {
+ .rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
+ },
+ .wsize = false,
+};
+
+static const struct rtw_hw_reg rtw8812a_dig[] = {
+ [0] = { .addr = REG_RXIGI_A, .mask = 0x7f },
+ [1] = { .addr = REG_RXIGI_B, .mask = 0x7f },
+};
+
+static const struct rtw_rfe_def rtw8812a_rfe_defs[] = {
+ [0] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl,
+ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl,
+ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, },
+ [1] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl,
+ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl,
+ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_tbl, },
+ [3] = { .phy_pg_tbl = &rtw8812a_bb_pg_rfe3_tbl,
+ .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl,
+ .pwr_track_tbl = &rtw8812a_rtw_pwr_track_rfe3_tbl, },
+};
+
+static const u8 wl_rssi_step_8812a[] = {101, 45, 101, 40};
+static const u8 bt_rssi_step_8812a[] = {101, 101, 101, 101};
+
+static const struct coex_rf_para rf_para_tx_8812a[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 20, false, 7}, /* for WL-CPT */
+ {8, 17, true, 4},
+ {7, 18, true, 4},
+ {6, 19, true, 4},
+ {5, 20, true, 4}
+};
+
+static const struct coex_rf_para rf_para_rx_8812a[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 20, false, 7}, /* for WL-CPT */
+ {3, 24, true, 5},
+ {2, 26, true, 5},
+ {1, 27, true, 5},
+ {0, 28, true, 5}
+};
+
+static_assert(ARRAY_SIZE(rf_para_tx_8812a) == ARRAY_SIZE(rf_para_rx_8812a));
+
+const struct rtw_chip_info rtw8812a_hw_spec = {
+ .ops = &rtw8812a_ops,
+ .id = RTW_CHIP_TYPE_8812A,
+ .fw_name = "rtw88/rtw8812a_fw.bin",
+ .wlan_cpu = RTW_WCPU_11N,
+ .tx_pkt_desc_sz = 40,
+ .tx_buf_desc_sz = 16,
+ .rx_pkt_desc_sz = 24,
+ .rx_buf_desc_sz = 8,
+ .phy_efuse_size = 512,
+ .log_efuse_size = 512,
+ .ptct_efuse_size = 96 + 1, /* TODO or just 18? */
+ .txff_size = 131072,
+ .rxff_size = 16128,
+ .rsvd_drv_pg_num = 9,
+ .txgi_factor = 1,
+ .is_pwr_by_rate_dec = true,
+ .max_power_index = 0x3f,
+ .csi_buf_pg_num = 0,
+ .band = RTW_BAND_2G | RTW_BAND_5G,
+ .page_size = 512,
+ .dig_min = 0x20,
+ .ht_supported = true,
+ .vht_supported = true,
+ .lps_deep_mode_supported = 0,
+ .sys_func_en = 0xFD,
+ .pwr_on_seq = card_enable_flow_8812a,
+ .pwr_off_seq = card_disable_flow_8812a,
+ .page_table = page_table_8812a,
+ .rqpn_table = rqpn_table_8812a,
+ .prioq_addrs = &prioq_addrs_8812a,
+ .intf_table = NULL,
+ .dig = rtw8812a_dig,
+ .rf_sipi_addr = {REG_LSSI_WRITE_A, REG_LSSI_WRITE_B},
+ .ltecoex_addr = NULL,
+ .mac_tbl = &rtw8812a_mac_tbl,
+ .agc_tbl = &rtw8812a_agc_tbl,
+ .bb_tbl = &rtw8812a_bb_tbl,
+ .rf_tbl = {&rtw8812a_rf_a_tbl, &rtw8812a_rf_b_tbl},
+ .rfe_defs = rtw8812a_rfe_defs,
+ .rfe_defs_size = ARRAY_SIZE(rtw8812a_rfe_defs),
+ .rx_ldpc = false,
+ .hw_feature_report = false,
+ .c2h_ra_report_size = 4,
+ .old_datarate_fb_limit = true,
+ .usb_tx_agg_desc_num = 1,
+ .iqk_threshold = 8,
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+ .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
+
+ .coex_para_ver = 0, /* no coex code in 8812au driver */
+ .bt_desired_ver = 0,
+ .scbd_support = false,
+ .new_scbd10_def = false,
+ .ble_hid_profile_support = false,
+ .wl_mimo_ps_support = false,
+ .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
+ .bt_rssi_type = COEX_BTRSSI_RATIO,
+ .ant_isolation = 15,
+ .rssi_tolerance = 2,
+ .wl_rssi_step = wl_rssi_step_8812a,
+ .bt_rssi_step = bt_rssi_step_8812a,
+ .table_sant_num = 0,
+ .table_sant = NULL,
+ .table_nsant_num = 0,
+ .table_nsant = NULL,
+ .tdma_sant_num = 0,
+ .tdma_sant = NULL,
+ .tdma_nsant_num = 0,
+ .tdma_nsant = NULL,
+ .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8812a),
+ .wl_rf_para_tx = rf_para_tx_8812a,
+ .wl_rf_para_rx = rf_para_rx_8812a,
+ .bt_afh_span_bw20 = 0x20,
+ .bt_afh_span_bw40 = 0x30,
+ .afh_5g_num = 0,
+ .afh_5g = NULL,
+ .coex_info_hw_regs_num = 0,
+ .coex_info_hw_regs = NULL,
+};
+EXPORT_SYMBOL(rtw8812a_hw_spec);
+
+MODULE_FIRMWARE("rtw88/rtw8812a_fw.bin");
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8812a driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.h b/drivers/net/wireless/realtek/rtw88/rtw8812a.h
new file mode 100644
index 000000000000..82dab59e341d
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#ifndef __RTW8812A_H__
+#define __RTW8812A_H__
+
+extern const struct rtw_chip_info rtw8812a_hw_spec;
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a_table.c b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.c
new file mode 100644
index 000000000000..048efbbd49ed
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.c
@@ -0,0 +1,2812 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#include "main.h"
+#include "phy.h"
+#include "rtw8812a_table.h"
+
+static const u32 rtw8812a_mac[] = {
+ 0x010, 0x0000000C,
+ 0x80000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x011, 0x00000066,
+ 0xA0000000, 0x00000000,
+ 0x011, 0x0000005A,
+ 0xB0000000, 0x00000000,
+ 0x025, 0x0000000F,
+ 0x072, 0x00000000,
+ 0x420, 0x00000080,
+ 0x428, 0x0000000A,
+ 0x429, 0x00000010,
+ 0x430, 0x00000000,
+ 0x431, 0x00000000,
+ 0x432, 0x00000000,
+ 0x433, 0x00000001,
+ 0x434, 0x00000002,
+ 0x435, 0x00000003,
+ 0x436, 0x00000005,
+ 0x437, 0x00000007,
+ 0x438, 0x00000000,
+ 0x439, 0x00000000,
+ 0x43A, 0x00000000,
+ 0x43B, 0x00000001,
+ 0x43C, 0x00000002,
+ 0x43D, 0x00000003,
+ 0x43E, 0x00000005,
+ 0x43F, 0x00000007,
+ 0x440, 0x0000005D,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000010,
+ 0x445, 0x00000000,
+ 0x446, 0x00000000,
+ 0x447, 0x00000000,
+ 0x448, 0x00000000,
+ 0x449, 0x000000F0,
+ 0x44A, 0x0000000F,
+ 0x44B, 0x0000003E,
+ 0x44C, 0x00000010,
+ 0x44D, 0x00000000,
+ 0x44E, 0x00000000,
+ 0x44F, 0x00000000,
+ 0x450, 0x00000000,
+ 0x451, 0x000000F0,
+ 0x452, 0x0000000F,
+ 0x453, 0x00000000,
+ 0x45B, 0x00000080,
+ 0x460, 0x00000066,
+ 0x461, 0x00000066,
+ 0x4C8, 0x000000FF,
+ 0x4C9, 0x00000008,
+ 0x4CC, 0x000000FF,
+ 0x4CD, 0x000000FF,
+ 0x4CE, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000A2,
+ 0x502, 0x0000002F,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000A3,
+ 0x506, 0x0000005E,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002B,
+ 0x509, 0x000000A4,
+ 0x50A, 0x0000005E,
+ 0x50B, 0x00000000,
+ 0x50C, 0x0000004F,
+ 0x50D, 0x000000A4,
+ 0x50E, 0x00000000,
+ 0x50F, 0x00000000,
+ 0x512, 0x0000001C,
+ 0x514, 0x0000000A,
+ 0x516, 0x0000000A,
+ 0x525, 0x0000004F,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55C, 0x00000050,
+ 0x55D, 0x000000FF,
+ 0x604, 0x00000009,
+ 0x605, 0x00000030,
+ 0x607, 0x00000003,
+ 0x608, 0x0000000E,
+ 0x609, 0x0000002A,
+ 0x620, 0x000000FF,
+ 0x621, 0x000000FF,
+ 0x622, 0x000000FF,
+ 0x623, 0x000000FF,
+ 0x624, 0x000000FF,
+ 0x625, 0x000000FF,
+ 0x626, 0x000000FF,
+ 0x627, 0x000000FF,
+ 0x638, 0x00000050,
+ 0x63C, 0x0000000A,
+ 0x63D, 0x0000000A,
+ 0x63E, 0x0000000E,
+ 0x63F, 0x0000000E,
+ 0x640, 0x00000080,
+ 0x642, 0x00000040,
+ 0x643, 0x00000000,
+ 0x652, 0x000000C8,
+ 0x66E, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70A, 0x00000065,
+ 0x70B, 0x00000087,
+ 0x718, 0x00000040,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8812a_mac, rtw_phy_cfg_mac);
+
+static const u32 rtw8812a_agc[] = {
+ 0x80000001, 0x00000000, 0x40000000, 0x00000000,
+ 0x81C, 0xFC000001,
+ 0x81C, 0xFB020001,
+ 0x81C, 0xFA040001,
+ 0x81C, 0xF9060001,
+ 0x81C, 0xF8080001,
+ 0x81C, 0xF70A0001,
+ 0x81C, 0xF60C0001,
+ 0x81C, 0xF50E0001,
+ 0x81C, 0xF4100001,
+ 0x81C, 0xF3120001,
+ 0x81C, 0xF2140001,
+ 0x81C, 0xF1160001,
+ 0x81C, 0xF0180001,
+ 0x81C, 0xEF1A0001,
+ 0x81C, 0xEE1C0001,
+ 0x81C, 0xED1E0001,
+ 0x81C, 0xEC200001,
+ 0x81C, 0xEB220001,
+ 0x81C, 0xEA240001,
+ 0x81C, 0xCD260001,
+ 0x81C, 0xCC280001,
+ 0x81C, 0xCB2A0001,
+ 0x81C, 0xCA2C0001,
+ 0x81C, 0xC92E0001,
+ 0x81C, 0xC8300001,
+ 0x81C, 0xA6320001,
+ 0x81C, 0xA5340001,
+ 0x81C, 0xA4360001,
+ 0x81C, 0xA3380001,
+ 0x81C, 0xA23A0001,
+ 0x81C, 0x883C0001,
+ 0x81C, 0x873E0001,
+ 0x81C, 0x86400001,
+ 0x81C, 0x85420001,
+ 0x81C, 0x84440001,
+ 0x81C, 0x83460001,
+ 0x81C, 0x82480001,
+ 0x81C, 0x814A0001,
+ 0x81C, 0x484C0001,
+ 0x81C, 0x474E0001,
+ 0x81C, 0x46500001,
+ 0x81C, 0x45520001,
+ 0x81C, 0x44540001,
+ 0x81C, 0x43560001,
+ 0x81C, 0x42580001,
+ 0x81C, 0x415A0001,
+ 0x81C, 0x255C0001,
+ 0x81C, 0x245E0001,
+ 0x81C, 0x23600001,
+ 0x81C, 0x22620001,
+ 0x81C, 0x21640001,
+ 0x81C, 0x21660001,
+ 0x81C, 0x21680001,
+ 0x81C, 0x216A0001,
+ 0x81C, 0x216C0001,
+ 0x81C, 0x216E0001,
+ 0x81C, 0x21700001,
+ 0x81C, 0x21720001,
+ 0x81C, 0x21740001,
+ 0x81C, 0x21760001,
+ 0x81C, 0x21780001,
+ 0x81C, 0x217A0001,
+ 0x81C, 0x217C0001,
+ 0x81C, 0x217E0001,
+ 0x90000001, 0x00000005, 0x40000000, 0x00000000,
+ 0x81C, 0xF9000001,
+ 0x81C, 0xF8020001,
+ 0x81C, 0xF7040001,
+ 0x81C, 0xF6060001,
+ 0x81C, 0xF5080001,
+ 0x81C, 0xF40A0001,
+ 0x81C, 0xF30C0001,
+ 0x81C, 0xF20E0001,
+ 0x81C, 0xF1100001,
+ 0x81C, 0xF0120001,
+ 0x81C, 0xEF140001,
+ 0x81C, 0xEE160001,
+ 0x81C, 0xED180001,
+ 0x81C, 0xEC1A0001,
+ 0x81C, 0xEB1C0001,
+ 0x81C, 0xEA1E0001,
+ 0x81C, 0xCD200001,
+ 0x81C, 0xCC220001,
+ 0x81C, 0xCB240001,
+ 0x81C, 0xCA260001,
+ 0x81C, 0xC9280001,
+ 0x81C, 0xC82A0001,
+ 0x81C, 0xC72C0001,
+ 0x81C, 0xC62E0001,
+ 0x81C, 0xA5300001,
+ 0x81C, 0xA4320001,
+ 0x81C, 0xA3340001,
+ 0x81C, 0xA2360001,
+ 0x81C, 0x88380001,
+ 0x81C, 0x873A0001,
+ 0x81C, 0x863C0001,
+ 0x81C, 0x853E0001,
+ 0x81C, 0x84400001,
+ 0x81C, 0x83420001,
+ 0x81C, 0x82440001,
+ 0x81C, 0x81460001,
+ 0x81C, 0x48480001,
+ 0x81C, 0x474A0001,
+ 0x81C, 0x464C0001,
+ 0x81C, 0x454E0001,
+ 0x81C, 0x44500001,
+ 0x81C, 0x43520001,
+ 0x81C, 0x42540001,
+ 0x81C, 0x41560001,
+ 0x81C, 0x25580001,
+ 0x81C, 0x245A0001,
+ 0x81C, 0x235C0001,
+ 0x81C, 0x225E0001,
+ 0x81C, 0x21600001,
+ 0x81C, 0x21620001,
+ 0x81C, 0x21640001,
+ 0x81C, 0x21660001,
+ 0x81C, 0x21680001,
+ 0x81C, 0x216A0001,
+ 0x81C, 0x236C0001,
+ 0x81C, 0x226E0001,
+ 0x81C, 0x21700001,
+ 0x81C, 0x21720001,
+ 0x81C, 0x21740001,
+ 0x81C, 0x21760001,
+ 0x81C, 0x21780001,
+ 0x81C, 0x217A0001,
+ 0x81C, 0x217C0001,
+ 0x81C, 0x217E0001,
+ 0xA0000000, 0x00000000,
+ 0x81C, 0xFF000001,
+ 0x81C, 0xFF020001,
+ 0x81C, 0xFF040001,
+ 0x81C, 0xFF060001,
+ 0x81C, 0xFF080001,
+ 0x81C, 0xFE0A0001,
+ 0x81C, 0xFD0C0001,
+ 0x81C, 0xFC0E0001,
+ 0x81C, 0xFB100001,
+ 0x81C, 0xFA120001,
+ 0x81C, 0xF9140001,
+ 0x81C, 0xF8160001,
+ 0x81C, 0xF7180001,
+ 0x81C, 0xF61A0001,
+ 0x81C, 0xF51C0001,
+ 0x81C, 0xF41E0001,
+ 0x81C, 0xF3200001,
+ 0x81C, 0xF2220001,
+ 0x81C, 0xF1240001,
+ 0x81C, 0xF0260001,
+ 0x81C, 0xEF280001,
+ 0x81C, 0xEE2A0001,
+ 0x81C, 0xED2C0001,
+ 0x81C, 0xEC2E0001,
+ 0x81C, 0xEB300001,
+ 0x81C, 0xEA320001,
+ 0x81C, 0xE9340001,
+ 0x81C, 0xE8360001,
+ 0x81C, 0xE7380001,
+ 0x81C, 0xE63A0001,
+ 0x81C, 0xE53C0001,
+ 0x81C, 0xC73E0001,
+ 0x81C, 0xC6400001,
+ 0x81C, 0xC5420001,
+ 0x81C, 0xC4440001,
+ 0x81C, 0xC3460001,
+ 0x81C, 0xC2480001,
+ 0x81C, 0xC14A0001,
+ 0x81C, 0xA74C0001,
+ 0x81C, 0xA64E0001,
+ 0x81C, 0xA5500001,
+ 0x81C, 0xA4520001,
+ 0x81C, 0xA3540001,
+ 0x81C, 0xA2560001,
+ 0x81C, 0xA1580001,
+ 0x81C, 0x675A0001,
+ 0x81C, 0x665C0001,
+ 0x81C, 0x655E0001,
+ 0x81C, 0x64600001,
+ 0x81C, 0x63620001,
+ 0x81C, 0x48640001,
+ 0x81C, 0x47660001,
+ 0x81C, 0x46680001,
+ 0x81C, 0x456A0001,
+ 0x81C, 0x446C0001,
+ 0x81C, 0x436E0001,
+ 0x81C, 0x42700001,
+ 0x81C, 0x41720001,
+ 0x81C, 0x41740001,
+ 0x81C, 0x41760001,
+ 0x81C, 0x41780001,
+ 0x81C, 0x417A0001,
+ 0x81C, 0x417C0001,
+ 0x81C, 0x417E0001,
+ 0xB0000000, 0x00000000,
+ 0x80000004, 0x00000000, 0x40000000, 0x00000000,
+ 0x81C, 0xFC800001,
+ 0x81C, 0xFB820001,
+ 0x81C, 0xFA840001,
+ 0x81C, 0xF9860001,
+ 0x81C, 0xF8880001,
+ 0x81C, 0xF78A0001,
+ 0x81C, 0xF68C0001,
+ 0x81C, 0xF58E0001,
+ 0x81C, 0xF4900001,
+ 0x81C, 0xF3920001,
+ 0x81C, 0xF2940001,
+ 0x81C, 0xF1960001,
+ 0x81C, 0xF0980001,
+ 0x81C, 0xEF9A0001,
+ 0x81C, 0xEE9C0001,
+ 0x81C, 0xED9E0001,
+ 0x81C, 0xECA00001,
+ 0x81C, 0xEBA20001,
+ 0x81C, 0xEAA40001,
+ 0x81C, 0xE9A60001,
+ 0x81C, 0xE8A80001,
+ 0x81C, 0xE7AA0001,
+ 0x81C, 0xE6AC0001,
+ 0x81C, 0xE5AE0001,
+ 0x81C, 0xE4B00001,
+ 0x81C, 0xE3B20001,
+ 0x81C, 0xA8B40001,
+ 0x81C, 0xA7B60001,
+ 0x81C, 0xA6B80001,
+ 0x81C, 0xA5BA0001,
+ 0x81C, 0xA4BC0001,
+ 0x81C, 0xA3BE0001,
+ 0x81C, 0xA2C00001,
+ 0x81C, 0xA1C20001,
+ 0x81C, 0x68C40001,
+ 0x81C, 0x67C60001,
+ 0x81C, 0x66C80001,
+ 0x81C, 0x65CA0001,
+ 0x81C, 0x64CC0001,
+ 0x81C, 0x47CE0001,
+ 0x81C, 0x46D00001,
+ 0x81C, 0x45D20001,
+ 0x81C, 0x44D40001,
+ 0x81C, 0x43D60001,
+ 0x81C, 0x42D80001,
+ 0x81C, 0x08DA0001,
+ 0x81C, 0x07DC0001,
+ 0x81C, 0x06DE0001,
+ 0x81C, 0x05E00001,
+ 0x81C, 0x04E20001,
+ 0x81C, 0x03E40001,
+ 0x81C, 0x02E60001,
+ 0x81C, 0x01E80001,
+ 0x81C, 0x01EA0001,
+ 0x81C, 0x01EC0001,
+ 0x81C, 0x01EE0001,
+ 0x81C, 0x01F00001,
+ 0x81C, 0x01F20001,
+ 0x81C, 0x01F40001,
+ 0x81C, 0x01F60001,
+ 0x81C, 0x01F80001,
+ 0x81C, 0x01FA0001,
+ 0x81C, 0x01FC0001,
+ 0x81C, 0x01FE0001,
+ 0xA0000000, 0x00000000,
+ 0x81C, 0xFF800001,
+ 0x81C, 0xFF820001,
+ 0x81C, 0xFF840001,
+ 0x81C, 0xFE860001,
+ 0x81C, 0xFD880001,
+ 0x81C, 0xFC8A0001,
+ 0x81C, 0xFB8C0001,
+ 0x81C, 0xFA8E0001,
+ 0x81C, 0xF9900001,
+ 0x81C, 0xF8920001,
+ 0x81C, 0xF7940001,
+ 0x81C, 0xF6960001,
+ 0x81C, 0xF5980001,
+ 0x81C, 0xF49A0001,
+ 0x81C, 0xF39C0001,
+ 0x81C, 0xF29E0001,
+ 0x81C, 0xF1A00001,
+ 0x81C, 0xF0A20001,
+ 0x81C, 0xEFA40001,
+ 0x81C, 0xEEA60001,
+ 0x81C, 0xEDA80001,
+ 0x81C, 0xECAA0001,
+ 0x81C, 0xEBAC0001,
+ 0x81C, 0xEAAE0001,
+ 0x81C, 0xE9B00001,
+ 0x81C, 0xE8B20001,
+ 0x81C, 0xE7B40001,
+ 0x81C, 0xE6B60001,
+ 0x81C, 0xE5B80001,
+ 0x81C, 0xE4BA0001,
+ 0x81C, 0xE3BC0001,
+ 0x81C, 0xA8BE0001,
+ 0x81C, 0xA7C00001,
+ 0x81C, 0xA6C20001,
+ 0x81C, 0xA5C40001,
+ 0x81C, 0xA4C60001,
+ 0x81C, 0xA3C80001,
+ 0x81C, 0xA2CA0001,
+ 0x81C, 0xA1CC0001,
+ 0x81C, 0x68CE0001,
+ 0x81C, 0x67D00001,
+ 0x81C, 0x66D20001,
+ 0x81C, 0x65D40001,
+ 0x81C, 0x64D60001,
+ 0x81C, 0x47D80001,
+ 0x81C, 0x46DA0001,
+ 0x81C, 0x45DC0001,
+ 0x81C, 0x44DE0001,
+ 0x81C, 0x43E00001,
+ 0x81C, 0x42E20001,
+ 0x81C, 0x08E40001,
+ 0x81C, 0x07E60001,
+ 0x81C, 0x06E80001,
+ 0x81C, 0x05EA0001,
+ 0x81C, 0x04EC0001,
+ 0x81C, 0x03EE0001,
+ 0x81C, 0x02F00001,
+ 0x81C, 0x01F20001,
+ 0x81C, 0x01F40001,
+ 0x81C, 0x01F60001,
+ 0x81C, 0x01F80001,
+ 0x81C, 0x01FA0001,
+ 0x81C, 0x01FC0001,
+ 0x81C, 0x01FE0001,
+ 0xB0000000, 0x00000000,
+ 0xC50, 0x00000022,
+ 0xC50, 0x00000020,
+ 0xE50, 0x00000022,
+ 0xE50, 0x00000020,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8812a_agc, rtw_phy_cfg_agc);
+
+static const u32 rtw8812a_agc_diff_lb[] = {
+ 0x80000004, 0x00000000, 0x40000000, 0x00000000,
+ 0x81C, 0x47CE0001,
+ 0x81C, 0x46D00001,
+ 0x81C, 0x45D20001,
+ 0x81C, 0x44D40001,
+ 0x81C, 0x43D60001,
+ 0x81C, 0x42D80001,
+ 0x81C, 0x08DA0001,
+ 0x81C, 0x07DC0001,
+ 0x81C, 0x06DE0001,
+ 0x81C, 0x05E00001,
+ 0x81C, 0x04E20001,
+ 0x81C, 0x03E40001,
+ 0x81C, 0x02E60001,
+ 0xA0000000, 0x00000000,
+ 0x81C, 0x47D80001,
+ 0x81C, 0x46DA0001,
+ 0x81C, 0x45DC0001,
+ 0x81C, 0x44DE0001,
+ 0x81C, 0x43E00001,
+ 0x81C, 0x42E20001,
+ 0x81C, 0x08E40001,
+ 0x81C, 0x07E60001,
+ 0x81C, 0x06E80001,
+ 0x81C, 0x05EA0001,
+ 0x81C, 0x04EC0001,
+ 0x81C, 0x03EE0001,
+ 0x81C, 0x02F00001,
+ 0xB0000000, 0x00000000,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8812a_agc_diff_lb, rtw_phy_cfg_agc);
+
+static const u32 rtw8812a_agc_diff_hb[] = {
+ 0x80000004, 0x00000000, 0x40000000, 0x00000000,
+ 0x81C, 0x45CE0001,
+ 0x81C, 0x44D00001,
+ 0x81C, 0x43D20001,
+ 0x81C, 0x42D40001,
+ 0x81C, 0x08D60001,
+ 0x81C, 0x07D80001,
+ 0x81C, 0x06DA0001,
+ 0x81C, 0x05DC0001,
+ 0x81C, 0x04DE0001,
+ 0x81C, 0x03E00001,
+ 0x81C, 0x02E20001,
+ 0x81C, 0x01E40001,
+ 0x81C, 0x01E60001,
+ 0xA0000000, 0x00000000,
+ 0x81C, 0x45D80001,
+ 0x81C, 0x44DA0001,
+ 0x81C, 0x43DC0001,
+ 0x81C, 0x42DE0001,
+ 0x81C, 0x08E00001,
+ 0x81C, 0x07E20001,
+ 0x81C, 0x06E40001,
+ 0x81C, 0x05E60001,
+ 0x81C, 0x04E80001,
+ 0x81C, 0x03EA0001,
+ 0x81C, 0x02EC0001,
+ 0x81C, 0x01EE0001,
+ 0x81C, 0x01F00001,
+ 0xB0000000, 0x00000000,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8812a_agc_diff_hb, rtw_phy_cfg_agc);
+
+static const u32 rtw8812a_bb[] = {
+ 0x800, 0x8020D010,
+ 0x804, 0x080112E0,
+ 0x808, 0x0E028233,
+ 0x80C, 0x12131113,
+ 0x810, 0x20101263,
+ 0x814, 0x020C3D10,
+ 0x818, 0x03A00385,
+ 0x820, 0x00000000,
+ 0x824, 0x00030FE0,
+ 0x828, 0x00000000,
+ 0x82C, 0x002083DD,
+ 0x830, 0x2EAAEEB8,
+ 0x834, 0x0037A706,
+ 0x838, 0x06C89B44,
+ 0x83C, 0x0000095B,
+ 0x840, 0xC0000001,
+ 0x844, 0x40003CDE,
+ 0x848, 0x6210FF8B,
+ 0x84C, 0x6CFDFFB8,
+ 0x850, 0x28874706,
+ 0x854, 0x0001520C,
+ 0x858, 0x8060E000,
+ 0x85C, 0x74210168,
+ 0x860, 0x6929C321,
+ 0x864, 0x79727432,
+ 0x868, 0x8CA7A314,
+ 0x86C, 0x338C2878,
+ 0x870, 0x03333333,
+ 0x874, 0x31602C2E,
+ 0x878, 0x00003152,
+ 0x87C, 0x000FC000,
+ 0x8A0, 0x00000013,
+ 0x8A4, 0x7F7F7F7F,
+ 0x8A8, 0xA202033E,
+ 0x8AC, 0x0FF0FA0A,
+ 0x8B0, 0x00000600,
+ 0x8B4, 0x000FC080,
+ 0x8B8, 0x6C10D7FF,
+ 0x8BC, 0x4CA520A3,
+ 0x8C0, 0x27F00020,
+ 0x8C4, 0x00000000,
+ 0x8C8, 0x00012D69,
+ 0x8CC, 0x08248492,
+ 0x8D0, 0x0000B800,
+ 0x8DC, 0x00000000,
+ 0x8D4, 0x940008A0,
+ 0x8D8, 0x290B5612,
+ 0x8F8, 0x400002C0,
+ 0x8FC, 0x00000000,
+ 0x900, 0x00000701,
+ 0x90C, 0x00000000,
+ 0x910, 0x0000FC00,
+ 0x914, 0x00000404,
+ 0x918, 0x1C1028C0,
+ 0x91C, 0x64B11A1C,
+ 0x920, 0xE0767233,
+ 0x924, 0x055AA500,
+ 0x928, 0x00000004,
+ 0x92C, 0xFFFE0000,
+ 0x930, 0xFFFFFFFE,
+ 0x934, 0x001FFFFF,
+ 0x960, 0x00000000,
+ 0x964, 0x00000000,
+ 0x968, 0x00000000,
+ 0x96C, 0x00000000,
+ 0x970, 0x801FFFFF,
+ 0x978, 0x00000000,
+ 0x97C, 0x00000000,
+ 0x980, 0x00000000,
+ 0x984, 0x00000000,
+ 0x988, 0x00000000,
+ 0x990, 0x27100000,
+ 0x994, 0xFFFF0100,
+ 0x998, 0xFFFFFF5C,
+ 0x99C, 0xFFFFFFFF,
+ 0x9A0, 0x000000FF,
+ 0x9A4, 0x00080080,
+ 0x9A8, 0x00000000,
+ 0x9AC, 0x00000000,
+ 0x9B0, 0x81081008,
+ 0x9B4, 0x00000000,
+ 0x9B8, 0x01081008,
+ 0x9BC, 0x01081008,
+ 0x9D0, 0x00000000,
+ 0x9D4, 0x00000000,
+ 0x9D8, 0x00000000,
+ 0x9DC, 0x00000000,
+ 0x9E4, 0x00000003,
+ 0x9E8, 0x000002D5,
+ 0xA00, 0x00D047C8,
+ 0xA04, 0x01FF000C,
+ 0xA08, 0x8C838300,
+ 0xA0C, 0x2E7F000F,
+ 0xA10, 0x9500BB78,
+ 0xA14, 0x11144028,
+ 0xA18, 0x00881117,
+ 0xA1C, 0x89140F00,
+ 0xA20, 0x1A1B0000,
+ 0xA24, 0x090E1217,
+ 0xA28, 0x00000305,
+ 0xA2C, 0x00900000,
+ 0xA70, 0x101FFF00,
+ 0xA74, 0x00000008,
+ 0xA78, 0x00000900,
+ 0xA7C, 0x225B0606,
+ 0xA80, 0x218075B2,
+ 0xA84, 0x001F8C80,
+ 0xB00, 0x03100000,
+ 0xB04, 0x0000B000,
+ 0xB08, 0xAE0201EB,
+ 0xB0C, 0x01003207,
+ 0xB10, 0x00009807,
+ 0xB14, 0x01000000,
+ 0xB18, 0x00000002,
+ 0xB1C, 0x00000002,
+ 0xB20, 0x0000001F,
+ 0xB24, 0x03020100,
+ 0xB28, 0x07060504,
+ 0xB2C, 0x0B0A0908,
+ 0xB30, 0x0F0E0D0C,
+ 0xB34, 0x13121110,
+ 0xB38, 0x17161514,
+ 0xB3C, 0x0000003A,
+ 0xB40, 0x00000000,
+ 0xB44, 0x00000000,
+ 0xB48, 0x13000032,
+ 0xB4C, 0x48080000,
+ 0xB50, 0x00000000,
+ 0xB54, 0x00000000,
+ 0xB58, 0x00000000,
+ 0xB5C, 0x00000000,
+ 0xC00, 0x00000007,
+ 0xC04, 0x00042020,
+ 0xC08, 0x80410231,
+ 0xC0C, 0x00000000,
+ 0xC10, 0x00000100,
+ 0xC14, 0x01000000,
+ 0xC1C, 0x40000003,
+ 0xC20, 0x12121212,
+ 0xC24, 0x12121212,
+ 0xC28, 0x12121212,
+ 0xC2C, 0x12121212,
+ 0xC30, 0x12121212,
+ 0xC34, 0x12121212,
+ 0xC38, 0x12121212,
+ 0xC3C, 0x12121212,
+ 0xC40, 0x12121212,
+ 0xC44, 0x12121212,
+ 0xC48, 0x12121212,
+ 0xC4C, 0x12121212,
+ 0xC50, 0x00000020,
+ 0xC54, 0x0008121C,
+ 0xC58, 0x30000C1C,
+ 0xC5C, 0x00000058,
+ 0xC60, 0x34344443,
+ 0xC64, 0x07003333,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0xC68, 0x59791979,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0xC68, 0x59791979,
+ 0x90000002, 0x00000000, 0x40000000, 0x00000000,
+ 0xC68, 0x59791979,
+ 0x90000004, 0x00000000, 0x40000000, 0x00000000,
+ 0xC68, 0x59791979,
+ 0x90000001, 0x00000000, 0x40000000, 0x00000000,
+ 0xC68, 0x59791979,
+ 0x90000001, 0x00000005, 0x40000000, 0x00000000,
+ 0xC68, 0x59791979,
+ 0xA0000000, 0x00000000,
+ 0xC68, 0x59799979,
+ 0xB0000000, 0x00000000,
+ 0xC6C, 0x59795979,
+ 0xC70, 0x19795979,
+ 0xC74, 0x19795979,
+ 0xC78, 0x19791979,
+ 0xC7C, 0x19791979,
+ 0xC80, 0x19791979,
+ 0xC84, 0x19791979,
+ 0xC94, 0x0100005C,
+ 0xC98, 0x00000000,
+ 0xC9C, 0x00000000,
+ 0xCA0, 0x00000029,
+ 0xCA4, 0x08040201,
+ 0xCA8, 0x80402010,
+ 0xCB0, 0x77547777,
+ 0xCB4, 0x00000077,
+ 0xCB8, 0x00508242,
+ 0xE00, 0x00000007,
+ 0xE04, 0x00042020,
+ 0xE08, 0x80410231,
+ 0xE0C, 0x00000000,
+ 0xE10, 0x00000100,
+ 0xE14, 0x01000000,
+ 0xE1C, 0x40000003,
+ 0xE20, 0x12121212,
+ 0xE24, 0x12121212,
+ 0xE28, 0x12121212,
+ 0xE2C, 0x12121212,
+ 0xE30, 0x12121212,
+ 0xE34, 0x12121212,
+ 0xE38, 0x12121212,
+ 0xE3C, 0x12121212,
+ 0xE40, 0x12121212,
+ 0xE44, 0x12121212,
+ 0xE48, 0x12121212,
+ 0xE4C, 0x12121212,
+ 0xE50, 0x00000020,
+ 0xE54, 0x0008121C,
+ 0xE58, 0x30000C1C,
+ 0xE5C, 0x00000058,
+ 0xE60, 0x34344443,
+ 0xE64, 0x07003333,
+ 0xE68, 0x59791979,
+ 0xE6C, 0x59795979,
+ 0xE70, 0x19795979,
+ 0xE74, 0x19795979,
+ 0xE78, 0x19791979,
+ 0xE7C, 0x19791979,
+ 0xE80, 0x19791979,
+ 0xE84, 0x19791979,
+ 0xE94, 0x0100005C,
+ 0xE98, 0x00000000,
+ 0xE9C, 0x00000000,
+ 0xEA0, 0x00000029,
+ 0xEA4, 0x08040201,
+ 0xEA8, 0x80402010,
+ 0xEB0, 0x77547777,
+ 0xEB4, 0x00000077,
+ 0xEB8, 0x00508242,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8812a_bb, rtw_phy_cfg_bb);
+
+static const struct rtw_phy_pg_cfg_pair rtw8812a_bb_pg[] = {
+ { 0, 0, 0, 0x00000c20, 0xffffffff, 0x34363840, },
+ { 0, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, },
+ { 0, 0, 0, 0x00000c28, 0xffffffff, 0x30323638, },
+ { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, },
+ { 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, },
+ { 0, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, },
+ { 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, },
+ { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, },
+ { 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, },
+ { 0, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, },
+ { 0, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, },
+ { 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, },
+ { 0, 1, 0, 0x00000e20, 0xffffffff, 0x34363840, },
+ { 0, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, },
+ { 0, 1, 0, 0x00000e28, 0xffffffff, 0x30323638, },
+ { 0, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, },
+ { 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, },
+ { 0, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, },
+ { 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, },
+ { 0, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, },
+ { 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, },
+ { 0, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, },
+ { 0, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, },
+ { 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, },
+ { 1, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, },
+ { 1, 0, 0, 0x00000c28, 0xffffffff, 0x30323640, },
+ { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, },
+ { 1, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, },
+ { 1, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, },
+ { 1, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, },
+ { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, },
+ { 1, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, },
+ { 1, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, },
+ { 1, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, },
+ { 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, },
+ { 1, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, },
+ { 1, 1, 0, 0x00000e28, 0xffffffff, 0x30323640, },
+ { 1, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, },
+ { 1, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, },
+ { 1, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, },
+ { 1, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, },
+ { 1, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, },
+ { 1, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, },
+ { 1, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, },
+ { 1, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, },
+ { 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, },
+};
+
+RTW_DECL_TABLE_BB_PG(rtw8812a_bb_pg);
+
+static const struct rtw_phy_pg_cfg_pair rtw8812a_bb_pg_rfe3[] = {
+ { 0, 0, 0, 0x00000c20, 0xffffffff, 0x34343434, },
+ { 0, 0, 0, 0x00000c24, 0xffffffff, 0x32323232, },
+ { 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303232, },
+ { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x32323232, },
+ { 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303232, },
+ { 0, 0, 1, 0x00000c34, 0xffffffff, 0x32323232, },
+ { 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, },
+ { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32323232, },
+ { 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303232, },
+ { 0, 0, 0, 0x00000c44, 0xffffffff, 0x32322426, },
+ { 0, 0, 1, 0x00000c48, 0xffffffff, 0x32323232, },
+ { 0, 0, 1, 0x00000c4c, 0xffffffff, 0x24262830, },
+ { 0, 1, 0, 0x00000e20, 0xffffffff, 0x34343434, },
+ { 0, 1, 0, 0x00000e24, 0xffffffff, 0x32323232, },
+ { 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303232, },
+ { 0, 1, 0, 0x00000e2c, 0xffffffff, 0x32323232, },
+ { 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303232, },
+ { 0, 1, 1, 0x00000e34, 0xffffffff, 0x32323232, },
+ { 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, },
+ { 0, 1, 0, 0x00000e3c, 0xffffffff, 0x32323232, },
+ { 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303232, },
+ { 0, 1, 0, 0x00000e44, 0xffffffff, 0x32322426, },
+ { 0, 1, 1, 0x00000e48, 0xffffffff, 0x32323232, },
+ { 0, 1, 1, 0x00000e4c, 0xffffffff, 0x24262830, },
+ { 1, 0, 0, 0x00000c24, 0xffffffff, 0x32323232, },
+ { 1, 0, 0, 0x00000c28, 0xffffffff, 0x28303232, },
+ { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32323232, },
+ { 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, },
+ { 1, 0, 1, 0x00000c34, 0xffffffff, 0x32323232, },
+ { 1, 0, 1, 0x00000c38, 0xffffffff, 0x24262830, },
+ { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32323232, },
+ { 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
+ { 1, 0, 0, 0x00000c44, 0xffffffff, 0x32322222, },
+ { 1, 0, 1, 0x00000c48, 0xffffffff, 0x28303232, },
+ { 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22222426, },
+ { 1, 1, 0, 0x00000e24, 0xffffffff, 0x32323232, },
+ { 1, 1, 0, 0x00000e28, 0xffffffff, 0x28303232, },
+ { 1, 1, 0, 0x00000e2c, 0xffffffff, 0x32323232, },
+ { 1, 1, 0, 0x00000e30, 0xffffffff, 0x24262830, },
+ { 1, 1, 1, 0x00000e34, 0xffffffff, 0x32323232, },
+ { 1, 1, 1, 0x00000e38, 0xffffffff, 0x24262830, },
+ { 1, 1, 0, 0x00000e3c, 0xffffffff, 0x32323232, },
+ { 1, 1, 0, 0x00000e40, 0xffffffff, 0x24262830, },
+ { 1, 1, 0, 0x00000e44, 0xffffffff, 0x32322222, },
+ { 1, 1, 1, 0x00000e48, 0xffffffff, 0x28303232, },
+ { 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22222426, },
+};
+
+RTW_DECL_TABLE_BB_PG(rtw8812a_bb_pg_rfe3);
+
+static const u32 rtw8812a_rf_a[] = {
+ 0x000, 0x00010000,
+ 0x018, 0x0001712A,
+ 0x056, 0x00051CF2,
+ 0x066, 0x00040000,
+ 0x01E, 0x00080000,
+ 0x089, 0x00000080,
+ 0x80000001, 0x00000000, 0x40000000, 0x00000000,
+ 0x086, 0x00014B3A,
+ 0x90000001, 0x00000005, 0x40000000, 0x00000000,
+ 0x086, 0x00014B3A,
+ 0xA0000000, 0x00000000,
+ 0x086, 0x00014B38,
+ 0xB0000000, 0x00000000,
+ 0x80000004, 0x00000000, 0x40000000, 0x00000000,
+ 0x08B, 0x00080180,
+ 0xA0000000, 0x00000000,
+ 0x08B, 0x00087180,
+ 0xB0000000, 0x00000000,
+ 0x0B1, 0x0001FC1A,
+ 0x0B3, 0x000F0810,
+ 0x0B4, 0x0001A78D,
+ 0x0BA, 0x00086180,
+ 0x018, 0x00000006,
+ 0x0EF, 0x00002000,
+ 0x80000001, 0x00000000, 0x40000000, 0x00000000,
+ 0x03B, 0x0003F218,
+ 0x03B, 0x00030A58,
+ 0x03B, 0x0002FA58,
+ 0x03B, 0x00022590,
+ 0x03B, 0x0001FA50,
+ 0x03B, 0x00010248,
+ 0x03B, 0x00008240,
+ 0x90000001, 0x00000005, 0x40000000, 0x00000000,
+ 0x03B, 0x0003F218,
+ 0x03B, 0x00030A58,
+ 0x03B, 0x0002FA58,
+ 0x03B, 0x00022590,
+ 0x03B, 0x0001FA50,
+ 0x03B, 0x00010248,
+ 0x03B, 0x00008240,
+ 0xA0000000, 0x00000000,
+ 0x03B, 0x00038A58,
+ 0x03B, 0x00037A58,
+ 0x03B, 0x0002A590,
+ 0x03B, 0x00027A50,
+ 0x03B, 0x00018248,
+ 0x03B, 0x00010240,
+ 0x03B, 0x00008240,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000100,
+ 0x80000002, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A4EE,
+ 0x034, 0x00009076,
+ 0x034, 0x00008073,
+ 0x034, 0x00007070,
+ 0x034, 0x0000606D,
+ 0x034, 0x0000506A,
+ 0x034, 0x00004049,
+ 0x034, 0x00003046,
+ 0x034, 0x00002028,
+ 0x034, 0x00001025,
+ 0x034, 0x00000022,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0000ADF4,
+ 0x034, 0x00009DF1,
+ 0x034, 0x00008DEE,
+ 0x034, 0x00007DEB,
+ 0x034, 0x00006DE8,
+ 0x034, 0x00005DE5,
+ 0x034, 0x00004DE2,
+ 0x034, 0x00003CE6,
+ 0x034, 0x000024E7,
+ 0x034, 0x000014E4,
+ 0x034, 0x000004E1,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x000020A2,
+ 0x0DF, 0x00000080,
+ 0x035, 0x00000192,
+ 0x035, 0x00008192,
+ 0x035, 0x00010192,
+ 0x036, 0x00000024,
+ 0x036, 0x00008024,
+ 0x036, 0x00010024,
+ 0x036, 0x00018024,
+ 0x0EF, 0x00000000,
+ 0x051, 0x00000C21,
+ 0x052, 0x000006D9,
+ 0x053, 0x000FC649,
+ 0x054, 0x0000017E,
+ 0x0EF, 0x00000002,
+ 0x008, 0x00008400,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00001000,
+ 0x03A, 0x00000080,
+ 0x03B, 0x0003A02C,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000400,
+ 0x03B, 0x0003202C,
+ 0x03C, 0x00010000,
+ 0x03A, 0x000000A0,
+ 0x03B, 0x0002B064,
+ 0x03C, 0x00004000,
+ 0x03A, 0x000000D8,
+ 0x03B, 0x00023070,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000468,
+ 0x03B, 0x0001B870,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000098,
+ 0x03B, 0x00012085,
+ 0x03C, 0x000E4000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x0000A080,
+ 0x03C, 0x000F0000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x00002080,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000080,
+ 0x03B, 0x0007A02C,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000400,
+ 0x03B, 0x0007202C,
+ 0x03C, 0x00010000,
+ 0x03A, 0x000000A0,
+ 0x03B, 0x0006B064,
+ 0x03C, 0x00004000,
+ 0x03A, 0x000000D8,
+ 0x03B, 0x00063070,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000468,
+ 0x03B, 0x0005B870,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000098,
+ 0x03B, 0x00052085,
+ 0x03C, 0x000E4000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x0004A080,
+ 0x03C, 0x000F0000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x00042080,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000080,
+ 0x03B, 0x000BA02C,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000400,
+ 0x03B, 0x000B202C,
+ 0x03C, 0x00010000,
+ 0x03A, 0x000000A0,
+ 0x03B, 0x000AB064,
+ 0x03C, 0x00004000,
+ 0x03A, 0x000000D8,
+ 0x03B, 0x000A3070,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000468,
+ 0x03B, 0x0009B870,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000098,
+ 0x03B, 0x00092085,
+ 0x03C, 0x000E4000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x0008A080,
+ 0x03C, 0x000F0000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x00082080,
+ 0x03C, 0x00010000,
+ 0x0EF, 0x00001100,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004A0B2,
+ 0x034, 0x000490AF,
+ 0x034, 0x00048070,
+ 0x034, 0x0004706D,
+ 0x034, 0x00046050,
+ 0x034, 0x0004504D,
+ 0x034, 0x0004404A,
+ 0x034, 0x00043047,
+ 0x034, 0x0004200A,
+ 0x034, 0x00041007,
+ 0x034, 0x00040004,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004A0B2,
+ 0x034, 0x000490AF,
+ 0x034, 0x00048070,
+ 0x034, 0x0004706D,
+ 0x034, 0x0004604D,
+ 0x034, 0x0004504A,
+ 0x034, 0x00044047,
+ 0x034, 0x00043044,
+ 0x034, 0x00042007,
+ 0x034, 0x00041004,
+ 0x034, 0x00040001,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0004ADF5,
+ 0x034, 0x00049DF2,
+ 0x034, 0x00048DEF,
+ 0x034, 0x00047DEC,
+ 0x034, 0x00046DE9,
+ 0x034, 0x00045DE6,
+ 0x034, 0x00044DE3,
+ 0x034, 0x000438C8,
+ 0x034, 0x000428C5,
+ 0x034, 0x000418C2,
+ 0x034, 0x000408C0,
+ 0xB0000000, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002A0B2,
+ 0x034, 0x000290AF,
+ 0x034, 0x00028070,
+ 0x034, 0x0002706D,
+ 0x034, 0x00026050,
+ 0x034, 0x0002504D,
+ 0x034, 0x0002404A,
+ 0x034, 0x00023047,
+ 0x034, 0x0002200A,
+ 0x034, 0x00021007,
+ 0x034, 0x00020004,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002A0B4,
+ 0x034, 0x000290B1,
+ 0x034, 0x00028072,
+ 0x034, 0x0002706F,
+ 0x034, 0x0002604F,
+ 0x034, 0x0002504C,
+ 0x034, 0x00024049,
+ 0x034, 0x00023046,
+ 0x034, 0x00022009,
+ 0x034, 0x00021006,
+ 0x034, 0x00020003,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0002ADF5,
+ 0x034, 0x00029DF2,
+ 0x034, 0x00028DEF,
+ 0x034, 0x00027DEC,
+ 0x034, 0x00026DE9,
+ 0x034, 0x00025DE6,
+ 0x034, 0x00024DE3,
+ 0x034, 0x000238C8,
+ 0x034, 0x000228C5,
+ 0x034, 0x000218C2,
+ 0x034, 0x000208C0,
+ 0xB0000000, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A0B2,
+ 0x034, 0x000090AF,
+ 0x034, 0x00008070,
+ 0x034, 0x0000706D,
+ 0x034, 0x00006050,
+ 0x034, 0x0000504D,
+ 0x034, 0x0000404A,
+ 0x034, 0x00003047,
+ 0x034, 0x0000200A,
+ 0x034, 0x00001007,
+ 0x034, 0x00000004,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A0B2,
+ 0x034, 0x000090AF,
+ 0x034, 0x00008070,
+ 0x034, 0x0000706D,
+ 0x034, 0x0000604D,
+ 0x034, 0x0000504A,
+ 0x034, 0x00004047,
+ 0x034, 0x00003044,
+ 0x034, 0x00002007,
+ 0x034, 0x00001004,
+ 0x034, 0x00000001,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0000AFF7,
+ 0x034, 0x00009DF7,
+ 0x034, 0x00008DF4,
+ 0x034, 0x00007DF1,
+ 0x034, 0x00006DEE,
+ 0x034, 0x00005DEB,
+ 0x034, 0x00004DE8,
+ 0x034, 0x000038CC,
+ 0x034, 0x000028C9,
+ 0x034, 0x000018C6,
+ 0x034, 0x000008C3,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000040,
+ 0x035, 0x000001D4,
+ 0x035, 0x000081D4,
+ 0x035, 0x000101D4,
+ 0x035, 0x000201B4,
+ 0x035, 0x000281B4,
+ 0x035, 0x000301B4,
+ 0x035, 0x000401B4,
+ 0x035, 0x000481B4,
+ 0x035, 0x000501B4,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000040,
+ 0x035, 0x000001D4,
+ 0x035, 0x000081D4,
+ 0x035, 0x000101D4,
+ 0x035, 0x000201B4,
+ 0x035, 0x000281B4,
+ 0x035, 0x000301B4,
+ 0x035, 0x000401B4,
+ 0x035, 0x000481B4,
+ 0x035, 0x000501B4,
+ 0xA0000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000040,
+ 0x035, 0x00000188,
+ 0x035, 0x00008147,
+ 0x035, 0x00010147,
+ 0x035, 0x000201D7,
+ 0x035, 0x000281D7,
+ 0x035, 0x000301D7,
+ 0x035, 0x000401D8,
+ 0x035, 0x000481D8,
+ 0x035, 0x000501D8,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000010,
+ 0x036, 0x00004BFB,
+ 0x036, 0x0000CBFB,
+ 0x036, 0x00014BFB,
+ 0x036, 0x0001CBFB,
+ 0x036, 0x00024F4B,
+ 0x036, 0x0002CF4B,
+ 0x036, 0x00034F4B,
+ 0x036, 0x0003CF4B,
+ 0x036, 0x00044F4B,
+ 0x036, 0x0004CF4B,
+ 0x036, 0x00054F4B,
+ 0x036, 0x0005CF4B,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000010,
+ 0x036, 0x00004BFB,
+ 0x036, 0x0000CBFB,
+ 0x036, 0x00014BFB,
+ 0x036, 0x0001CBFB,
+ 0x036, 0x00024F4B,
+ 0x036, 0x0002CF4B,
+ 0x036, 0x00034F4B,
+ 0x036, 0x0003CF4B,
+ 0x036, 0x00044F4B,
+ 0x036, 0x0004CF4B,
+ 0x036, 0x00054F4B,
+ 0x036, 0x0005CF4B,
+ 0xA0000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000010,
+ 0x036, 0x00084EB4,
+ 0x036, 0x0008CC35,
+ 0x036, 0x00094C35,
+ 0x036, 0x0009CC35,
+ 0x036, 0x000A4C35,
+ 0x036, 0x000ACC35,
+ 0x036, 0x000B4C35,
+ 0x036, 0x000BCC35,
+ 0x036, 0x000C4C34,
+ 0x036, 0x000CCC35,
+ 0x036, 0x000D4C35,
+ 0x036, 0x000DCC35,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x00000008,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000002CC,
+ 0x03C, 0x00000522,
+ 0x03C, 0x00000902,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000002CC,
+ 0x03C, 0x00000522,
+ 0x03C, 0x00000902,
+ 0xA0000000, 0x00000000,
+ 0x03C, 0x000002A8,
+ 0x03C, 0x000005A2,
+ 0x03C, 0x00000880,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000002,
+ 0x0DF, 0x00000080,
+ 0x01F, 0x00000064,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000FDD43,
+ 0x062, 0x00038F4B,
+ 0x063, 0x00032117,
+ 0x064, 0x000194AC,
+ 0x065, 0x000931D1,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x061, 0x000FDD43,
+ 0x062, 0x00038F4B,
+ 0x063, 0x00032117,
+ 0x064, 0x000194AC,
+ 0x065, 0x000931D2,
+ 0xA0000000, 0x00000000,
+ 0x061, 0x000E5D53,
+ 0x062, 0x00038FCD,
+ 0x063, 0x000114EB,
+ 0x064, 0x000196AC,
+ 0x065, 0x000911D7,
+ 0xB0000000, 0x00000000,
+ 0x008, 0x00008400,
+ 0x01C, 0x000739D2,
+ 0x0B4, 0x0001E78D,
+ 0x018, 0x0001F12A,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0x0B4, 0x0001A78D,
+ 0x018, 0x0001712A,
+};
+
+RTW_DECL_TABLE_RF_RADIO(rtw8812a_rf_a, A);
+
+static const u32 rtw8812a_rf_b[] = {
+ 0x056, 0x00051CF2,
+ 0x066, 0x00040000,
+ 0x089, 0x00000080,
+ 0x80000001, 0x00000000, 0x40000000, 0x00000000,
+ 0x086, 0x00014B3A,
+ 0x90000001, 0x00000005, 0x40000000, 0x00000000,
+ 0x086, 0x00014B3A,
+ 0xA0000000, 0x00000000,
+ 0x086, 0x00014B38,
+ 0xB0000000, 0x00000000,
+ 0x80000004, 0x00000000, 0x40000000, 0x00000000,
+ 0x08B, 0x00080180,
+ 0xA0000000, 0x00000000,
+ 0x08B, 0x00087180,
+ 0xB0000000, 0x00000000,
+ 0x018, 0x00000006,
+ 0x0EF, 0x00002000,
+ 0x80000001, 0x00000000, 0x40000000, 0x00000000,
+ 0x03B, 0x0003F218,
+ 0x03B, 0x00030A58,
+ 0x03B, 0x0002FA58,
+ 0x03B, 0x00022590,
+ 0x03B, 0x0001FA50,
+ 0x03B, 0x00010248,
+ 0x03B, 0x00008240,
+ 0x90000001, 0x00000005, 0x40000000, 0x00000000,
+ 0x03B, 0x0003F218,
+ 0x03B, 0x00030A58,
+ 0x03B, 0x0002FA58,
+ 0x03B, 0x00022590,
+ 0x03B, 0x0001FA50,
+ 0x03B, 0x00010248,
+ 0x03B, 0x00008240,
+ 0xA0000000, 0x00000000,
+ 0x03B, 0x00038A58,
+ 0x03B, 0x00037A58,
+ 0x03B, 0x0002A590,
+ 0x03B, 0x00027A50,
+ 0x03B, 0x00018248,
+ 0x03B, 0x00010240,
+ 0x03B, 0x00008240,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000100,
+ 0x80000002, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A4EE,
+ 0x034, 0x00009076,
+ 0x034, 0x00008073,
+ 0x034, 0x00007070,
+ 0x034, 0x0000606D,
+ 0x034, 0x0000506A,
+ 0x034, 0x00004049,
+ 0x034, 0x00003046,
+ 0x034, 0x00002028,
+ 0x034, 0x00001025,
+ 0x034, 0x00000022,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0000ADF4,
+ 0x034, 0x00009DF1,
+ 0x034, 0x00008DEE,
+ 0x034, 0x00007DEB,
+ 0x034, 0x00006DE8,
+ 0x034, 0x00005DE5,
+ 0x034, 0x00004DE2,
+ 0x034, 0x00003CE6,
+ 0x034, 0x000024E7,
+ 0x034, 0x000014E4,
+ 0x034, 0x000004E1,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x000020A2,
+ 0x0DF, 0x00000080,
+ 0x035, 0x00000192,
+ 0x035, 0x00008192,
+ 0x035, 0x00010192,
+ 0x036, 0x00000024,
+ 0x036, 0x00008024,
+ 0x036, 0x00010024,
+ 0x036, 0x00018024,
+ 0x0EF, 0x00000000,
+ 0x051, 0x00000C21,
+ 0x052, 0x000006D9,
+ 0x053, 0x000FC649,
+ 0x054, 0x0000017E,
+ 0x0EF, 0x00000002,
+ 0x008, 0x00008400,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00001000,
+ 0x03A, 0x00000080,
+ 0x03B, 0x0003A02C,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000400,
+ 0x03B, 0x0003202C,
+ 0x03C, 0x00010000,
+ 0x03A, 0x000000A0,
+ 0x03B, 0x0002B064,
+ 0x03C, 0x00004000,
+ 0x03A, 0x000000D8,
+ 0x03B, 0x00023070,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000468,
+ 0x03B, 0x0001B870,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000098,
+ 0x03B, 0x00012085,
+ 0x03C, 0x000E4000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x0000A080,
+ 0x03C, 0x000F0000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x00002080,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000080,
+ 0x03B, 0x0007A02C,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000400,
+ 0x03B, 0x0007202C,
+ 0x03C, 0x00010000,
+ 0x03A, 0x000000A0,
+ 0x03B, 0x0006B064,
+ 0x03C, 0x00004000,
+ 0x03A, 0x000000D8,
+ 0x03B, 0x00063070,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000468,
+ 0x03B, 0x0005B870,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000098,
+ 0x03B, 0x00052085,
+ 0x03C, 0x000E4000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x0004A080,
+ 0x03C, 0x000F0000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x00042080,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000080,
+ 0x03B, 0x000BA02C,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000400,
+ 0x03B, 0x000B202C,
+ 0x03C, 0x00010000,
+ 0x03A, 0x000000A0,
+ 0x03B, 0x000AB064,
+ 0x03C, 0x00004000,
+ 0x03A, 0x000000D8,
+ 0x03B, 0x000A3070,
+ 0x03C, 0x00004000,
+ 0x03A, 0x00000468,
+ 0x03B, 0x0009B870,
+ 0x03C, 0x00010000,
+ 0x03A, 0x00000098,
+ 0x03B, 0x00092085,
+ 0x03C, 0x000E4000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x0008A080,
+ 0x03C, 0x000F0000,
+ 0x03A, 0x00000418,
+ 0x03B, 0x00082080,
+ 0x03C, 0x00010000,
+ 0x0EF, 0x00001100,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004A0B2,
+ 0x034, 0x000490AF,
+ 0x034, 0x00048070,
+ 0x034, 0x0004706D,
+ 0x034, 0x00046050,
+ 0x034, 0x0004504D,
+ 0x034, 0x0004404A,
+ 0x034, 0x00043047,
+ 0x034, 0x0004200A,
+ 0x034, 0x00041007,
+ 0x034, 0x00040004,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004A0B1,
+ 0x034, 0x000490AE,
+ 0x034, 0x0004806F,
+ 0x034, 0x0004706C,
+ 0x034, 0x0004604C,
+ 0x034, 0x00045049,
+ 0x034, 0x00044046,
+ 0x034, 0x00043043,
+ 0x034, 0x00042006,
+ 0x034, 0x00041003,
+ 0x034, 0x00040000,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0004ADF5,
+ 0x034, 0x00049DF2,
+ 0x034, 0x00048DEF,
+ 0x034, 0x00047DEC,
+ 0x034, 0x00046DE9,
+ 0x034, 0x00045DE6,
+ 0x034, 0x00044DE3,
+ 0x034, 0x000438C8,
+ 0x034, 0x000428C5,
+ 0x034, 0x000418C2,
+ 0x034, 0x000408C0,
+ 0xB0000000, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002A0B2,
+ 0x034, 0x000290AF,
+ 0x034, 0x00028070,
+ 0x034, 0x0002706D,
+ 0x034, 0x00026050,
+ 0x034, 0x0002504D,
+ 0x034, 0x0002404A,
+ 0x034, 0x00023047,
+ 0x034, 0x0002200A,
+ 0x034, 0x00021007,
+ 0x034, 0x00020004,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002A0B3,
+ 0x034, 0x000290B0,
+ 0x034, 0x00028071,
+ 0x034, 0x0002706E,
+ 0x034, 0x0002604E,
+ 0x034, 0x0002504B,
+ 0x034, 0x00024048,
+ 0x034, 0x00023045,
+ 0x034, 0x00022008,
+ 0x034, 0x00021005,
+ 0x034, 0x00020002,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0002ADF5,
+ 0x034, 0x00029DF2,
+ 0x034, 0x00028DEF,
+ 0x034, 0x00027DEC,
+ 0x034, 0x00026DE9,
+ 0x034, 0x00025DE6,
+ 0x034, 0x00024DE3,
+ 0x034, 0x000238C8,
+ 0x034, 0x000228C5,
+ 0x034, 0x000218C2,
+ 0x034, 0x000208C0,
+ 0xB0000000, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A0B2,
+ 0x034, 0x000090AF,
+ 0x034, 0x00008070,
+ 0x034, 0x0000706D,
+ 0x034, 0x00006050,
+ 0x034, 0x0000504D,
+ 0x034, 0x0000404A,
+ 0x034, 0x00003047,
+ 0x034, 0x0000200A,
+ 0x034, 0x00001007,
+ 0x034, 0x00000004,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A0B3,
+ 0x034, 0x000090B0,
+ 0x034, 0x00008070,
+ 0x034, 0x0000706D,
+ 0x034, 0x0000604D,
+ 0x034, 0x0000504A,
+ 0x034, 0x00004047,
+ 0x034, 0x00003044,
+ 0x034, 0x00002007,
+ 0x034, 0x00001004,
+ 0x034, 0x00000001,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0000AFF7,
+ 0x034, 0x00009DF7,
+ 0x034, 0x00008DF4,
+ 0x034, 0x00007DF1,
+ 0x034, 0x00006DEE,
+ 0x034, 0x00005DEB,
+ 0x034, 0x00004DE8,
+ 0x034, 0x000038CC,
+ 0x034, 0x000028C9,
+ 0x034, 0x000018C6,
+ 0x034, 0x000008C3,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000040,
+ 0x035, 0x000001C5,
+ 0x035, 0x000081C5,
+ 0x035, 0x000101C5,
+ 0x035, 0x00020174,
+ 0x035, 0x00028174,
+ 0x035, 0x00030174,
+ 0x035, 0x00040185,
+ 0x035, 0x00048185,
+ 0x035, 0x00050185,
+ 0x0EF, 0x00000000,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000040,
+ 0x035, 0x000001C5,
+ 0x035, 0x000081C5,
+ 0x035, 0x000101C5,
+ 0x035, 0x00020174,
+ 0x035, 0x00028174,
+ 0x035, 0x00030174,
+ 0x035, 0x00040185,
+ 0x035, 0x00048185,
+ 0x035, 0x00050185,
+ 0x0EF, 0x00000000,
+ 0xA0000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000040,
+ 0x035, 0x00000188,
+ 0x035, 0x00008147,
+ 0x035, 0x00010147,
+ 0x035, 0x000201D7,
+ 0x035, 0x000281D7,
+ 0x035, 0x000301D7,
+ 0x035, 0x000401D8,
+ 0x035, 0x000481D8,
+ 0x035, 0x000501D8,
+ 0x0EF, 0x00000000,
+ 0xB0000000, 0x00000000,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000010,
+ 0x036, 0x00005B8B,
+ 0x036, 0x0000DB8B,
+ 0x036, 0x00015B8B,
+ 0x036, 0x0001DB8B,
+ 0x036, 0x000262DB,
+ 0x036, 0x0002E2DB,
+ 0x036, 0x000362DB,
+ 0x036, 0x0003E2DB,
+ 0x036, 0x0004553B,
+ 0x036, 0x0004D53B,
+ 0x036, 0x0005553B,
+ 0x036, 0x0005D53B,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000010,
+ 0x036, 0x00005B8B,
+ 0x036, 0x0000DB8B,
+ 0x036, 0x00015B8B,
+ 0x036, 0x0001DB8B,
+ 0x036, 0x000262DB,
+ 0x036, 0x0002E2DB,
+ 0x036, 0x000362DB,
+ 0x036, 0x0003E2DB,
+ 0x036, 0x0004553B,
+ 0x036, 0x0004D53B,
+ 0x036, 0x0005553B,
+ 0x036, 0x0005D53B,
+ 0xA0000000, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000010,
+ 0x036, 0x00084EB4,
+ 0x036, 0x0008CC35,
+ 0x036, 0x00094C35,
+ 0x036, 0x0009CC35,
+ 0x036, 0x000A4C35,
+ 0x036, 0x000ACC35,
+ 0x036, 0x000B4C35,
+ 0x036, 0x000BCC35,
+ 0x036, 0x000C4C34,
+ 0x036, 0x000CCC35,
+ 0x036, 0x000D4C35,
+ 0x036, 0x000DCC35,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x00000008,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000002DC,
+ 0x03C, 0x00000524,
+ 0x03C, 0x00000902,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000002DC,
+ 0x03C, 0x00000524,
+ 0x03C, 0x00000902,
+ 0xA0000000, 0x00000000,
+ 0x03C, 0x000002A8,
+ 0x03C, 0x000005A2,
+ 0x03C, 0x00000880,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000002,
+ 0x0DF, 0x00000080,
+ 0x80000008, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000EAC43,
+ 0x062, 0x00038F47,
+ 0x063, 0x00031157,
+ 0x064, 0x0001C4AC,
+ 0x065, 0x000931D1,
+ 0x90000008, 0x05000000, 0x40000000, 0x00000000,
+ 0x061, 0x000EAC43,
+ 0x062, 0x00038F47,
+ 0x063, 0x00031157,
+ 0x064, 0x0001C4AC,
+ 0x065, 0x000931D2,
+ 0x90000002, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000EAC43,
+ 0x062, 0x00038F47,
+ 0x063, 0x00031157,
+ 0x064, 0x0001C4AC,
+ 0x065, 0x000931D1,
+ 0xA0000000, 0x00000000,
+ 0x061, 0x000E5D53,
+ 0x062, 0x00038FCD,
+ 0x063, 0x000114EB,
+ 0x064, 0x000196AC,
+ 0x065, 0x000911D7,
+ 0xB0000000, 0x00000000,
+ 0x008, 0x00008400,
+};
+
+RTW_DECL_TABLE_RF_RADIO(rtw8812a_rf_b, B);
+
+static const struct rtw_txpwr_lmt_cfg_pair rtw8812a_txpwr_lmt[] = {
+ { 0, 0, 0, 0, 1, 36, },
+ { 2, 0, 0, 0, 1, 32, },
+ { 1, 0, 0, 0, 1, 32, },
+ { 0, 0, 0, 0, 2, 36, },
+ { 2, 0, 0, 0, 2, 32, },
+ { 1, 0, 0, 0, 2, 32, },
+ { 0, 0, 0, 0, 3, 36, },
+ { 2, 0, 0, 0, 3, 32, },
+ { 1, 0, 0, 0, 3, 32, },
+ { 0, 0, 0, 0, 4, 36, },
+ { 2, 0, 0, 0, 4, 32, },
+ { 1, 0, 0, 0, 4, 32, },
+ { 0, 0, 0, 0, 5, 36, },
+ { 2, 0, 0, 0, 5, 32, },
+ { 1, 0, 0, 0, 5, 32, },
+ { 0, 0, 0, 0, 6, 36, },
+ { 2, 0, 0, 0, 6, 32, },
+ { 1, 0, 0, 0, 6, 32, },
+ { 0, 0, 0, 0, 7, 36, },
+ { 2, 0, 0, 0, 7, 32, },
+ { 1, 0, 0, 0, 7, 32, },
+ { 0, 0, 0, 0, 8, 36, },
+ { 2, 0, 0, 0, 8, 32, },
+ { 1, 0, 0, 0, 8, 32, },
+ { 0, 0, 0, 0, 9, 36, },
+ { 2, 0, 0, 0, 9, 32, },
+ { 1, 0, 0, 0, 9, 32, },
+ { 0, 0, 0, 0, 10, 36, },
+ { 2, 0, 0, 0, 10, 32, },
+ { 1, 0, 0, 0, 10, 32, },
+ { 0, 0, 0, 0, 11, 36, },
+ { 2, 0, 0, 0, 11, 32, },
+ { 1, 0, 0, 0, 11, 32, },
+ { 0, 0, 0, 0, 12, 63, },
+ { 2, 0, 0, 0, 12, 32, },
+ { 1, 0, 0, 0, 12, 32, },
+ { 0, 0, 0, 0, 13, 63, },
+ { 2, 0, 0, 0, 13, 32, },
+ { 1, 0, 0, 0, 13, 32, },
+ { 0, 0, 0, 0, 14, 63, },
+ { 2, 0, 0, 0, 14, 63, },
+ { 1, 0, 0, 0, 14, 32, },
+ { 0, 0, 0, 1, 1, 34, },
+ { 2, 0, 0, 1, 1, 32, },
+ { 1, 0, 0, 1, 1, 32, },
+ { 0, 0, 0, 1, 2, 36, },
+ { 2, 0, 0, 1, 2, 32, },
+ { 1, 0, 0, 1, 2, 32, },
+ { 0, 0, 0, 1, 3, 36, },
+ { 2, 0, 0, 1, 3, 32, },
+ { 1, 0, 0, 1, 3, 32, },
+ { 0, 0, 0, 1, 4, 36, },
+ { 2, 0, 0, 1, 4, 32, },
+ { 1, 0, 0, 1, 4, 32, },
+ { 0, 0, 0, 1, 5, 36, },
+ { 2, 0, 0, 1, 5, 32, },
+ { 1, 0, 0, 1, 5, 32, },
+ { 0, 0, 0, 1, 6, 36, },
+ { 2, 0, 0, 1, 6, 32, },
+ { 1, 0, 0, 1, 6, 32, },
+ { 0, 0, 0, 1, 7, 36, },
+ { 2, 0, 0, 1, 7, 32, },
+ { 1, 0, 0, 1, 7, 32, },
+ { 0, 0, 0, 1, 8, 36, },
+ { 2, 0, 0, 1, 8, 32, },
+ { 1, 0, 0, 1, 8, 32, },
+ { 0, 0, 0, 1, 9, 36, },
+ { 2, 0, 0, 1, 9, 32, },
+ { 1, 0, 0, 1, 9, 32, },
+ { 0, 0, 0, 1, 10, 36, },
+ { 2, 0, 0, 1, 10, 32, },
+ { 1, 0, 0, 1, 10, 32, },
+ { 0, 0, 0, 1, 11, 32, },
+ { 2, 0, 0, 1, 11, 32, },
+ { 1, 0, 0, 1, 11, 32, },
+ { 0, 0, 0, 1, 12, 63, },
+ { 2, 0, 0, 1, 12, 32, },
+ { 1, 0, 0, 1, 12, 32, },
+ { 0, 0, 0, 1, 13, 63, },
+ { 2, 0, 0, 1, 13, 32, },
+ { 1, 0, 0, 1, 13, 32, },
+ { 0, 0, 0, 1, 14, 63, },
+ { 2, 0, 0, 1, 14, 63, },
+ { 1, 0, 0, 1, 14, 63, },
+ { 0, 0, 0, 2, 1, 34, },
+ { 2, 0, 0, 2, 1, 32, },
+ { 1, 0, 0, 2, 1, 32, },
+ { 0, 0, 0, 2, 2, 36, },
+ { 2, 0, 0, 2, 2, 32, },
+ { 1, 0, 0, 2, 2, 32, },
+ { 0, 0, 0, 2, 3, 36, },
+ { 2, 0, 0, 2, 3, 32, },
+ { 1, 0, 0, 2, 3, 32, },
+ { 0, 0, 0, 2, 4, 36, },
+ { 2, 0, 0, 2, 4, 32, },
+ { 1, 0, 0, 2, 4, 32, },
+ { 0, 0, 0, 2, 5, 36, },
+ { 2, 0, 0, 2, 5, 32, },
+ { 1, 0, 0, 2, 5, 32, },
+ { 0, 0, 0, 2, 6, 36, },
+ { 2, 0, 0, 2, 6, 32, },
+ { 1, 0, 0, 2, 6, 32, },
+ { 0, 0, 0, 2, 7, 36, },
+ { 2, 0, 0, 2, 7, 32, },
+ { 1, 0, 0, 2, 7, 32, },
+ { 0, 0, 0, 2, 8, 36, },
+ { 2, 0, 0, 2, 8, 32, },
+ { 1, 0, 0, 2, 8, 32, },
+ { 0, 0, 0, 2, 9, 36, },
+ { 2, 0, 0, 2, 9, 32, },
+ { 1, 0, 0, 2, 9, 32, },
+ { 0, 0, 0, 2, 10, 36, },
+ { 2, 0, 0, 2, 10, 32, },
+ { 1, 0, 0, 2, 10, 32, },
+ { 0, 0, 0, 2, 11, 32, },
+ { 2, 0, 0, 2, 11, 32, },
+ { 1, 0, 0, 2, 11, 32, },
+ { 0, 0, 0, 2, 12, 63, },
+ { 2, 0, 0, 2, 12, 32, },
+ { 1, 0, 0, 2, 12, 32, },
+ { 0, 0, 0, 2, 13, 63, },
+ { 2, 0, 0, 2, 13, 32, },
+ { 1, 0, 0, 2, 13, 32, },
+ { 0, 0, 0, 2, 14, 63, },
+ { 2, 0, 0, 2, 14, 63, },
+ { 1, 0, 0, 2, 14, 63, },
+ { 0, 0, 0, 3, 1, 32, },
+ { 2, 0, 0, 3, 1, 32, },
+ { 1, 0, 0, 3, 1, 32, },
+ { 0, 0, 0, 3, 2, 34, },
+ { 2, 0, 0, 3, 2, 32, },
+ { 1, 0, 0, 3, 2, 32, },
+ { 0, 0, 0, 3, 3, 34, },
+ { 2, 0, 0, 3, 3, 32, },
+ { 1, 0, 0, 3, 3, 32, },
+ { 0, 0, 0, 3, 4, 34, },
+ { 2, 0, 0, 3, 4, 32, },
+ { 1, 0, 0, 3, 4, 32, },
+ { 0, 0, 0, 3, 5, 34, },
+ { 2, 0, 0, 3, 5, 32, },
+ { 1, 0, 0, 3, 5, 32, },
+ { 0, 0, 0, 3, 6, 34, },
+ { 2, 0, 0, 3, 6, 32, },
+ { 1, 0, 0, 3, 6, 32, },
+ { 0, 0, 0, 3, 7, 34, },
+ { 2, 0, 0, 3, 7, 32, },
+ { 1, 0, 0, 3, 7, 32, },
+ { 0, 0, 0, 3, 8, 34, },
+ { 2, 0, 0, 3, 8, 32, },
+ { 1, 0, 0, 3, 8, 32, },
+ { 0, 0, 0, 3, 9, 34, },
+ { 2, 0, 0, 3, 9, 32, },
+ { 1, 0, 0, 3, 9, 32, },
+ { 0, 0, 0, 3, 10, 34, },
+ { 2, 0, 0, 3, 10, 32, },
+ { 1, 0, 0, 3, 10, 32, },
+ { 0, 0, 0, 3, 11, 30, },
+ { 2, 0, 0, 3, 11, 32, },
+ { 1, 0, 0, 3, 11, 32, },
+ { 0, 0, 0, 3, 12, 63, },
+ { 2, 0, 0, 3, 12, 32, },
+ { 1, 0, 0, 3, 12, 32, },
+ { 0, 0, 0, 3, 13, 63, },
+ { 2, 0, 0, 3, 13, 32, },
+ { 1, 0, 0, 3, 13, 32, },
+ { 0, 0, 0, 3, 14, 63, },
+ { 2, 0, 0, 3, 14, 63, },
+ { 1, 0, 0, 3, 14, 63, },
+ { 0, 0, 1, 2, 1, 63, },
+ { 2, 0, 1, 2, 1, 63, },
+ { 1, 0, 1, 2, 1, 63, },
+ { 0, 0, 1, 2, 2, 63, },
+ { 2, 0, 1, 2, 2, 63, },
+ { 1, 0, 1, 2, 2, 63, },
+ { 0, 0, 1, 2, 3, 32, },
+ { 2, 0, 1, 2, 3, 32, },
+ { 1, 0, 1, 2, 3, 32, },
+ { 0, 0, 1, 2, 4, 36, },
+ { 2, 0, 1, 2, 4, 32, },
+ { 1, 0, 1, 2, 4, 32, },
+ { 0, 0, 1, 2, 5, 36, },
+ { 2, 0, 1, 2, 5, 32, },
+ { 1, 0, 1, 2, 5, 32, },
+ { 0, 0, 1, 2, 6, 36, },
+ { 2, 0, 1, 2, 6, 32, },
+ { 1, 0, 1, 2, 6, 32, },
+ { 0, 0, 1, 2, 7, 36, },
+ { 2, 0, 1, 2, 7, 32, },
+ { 1, 0, 1, 2, 7, 32, },
+ { 0, 0, 1, 2, 8, 36, },
+ { 2, 0, 1, 2, 8, 32, },
+ { 1, 0, 1, 2, 8, 32, },
+ { 0, 0, 1, 2, 9, 36, },
+ { 2, 0, 1, 2, 9, 32, },
+ { 1, 0, 1, 2, 9, 32, },
+ { 0, 0, 1, 2, 10, 36, },
+ { 2, 0, 1, 2, 10, 32, },
+ { 1, 0, 1, 2, 10, 32, },
+ { 0, 0, 1, 2, 11, 32, },
+ { 2, 0, 1, 2, 11, 32, },
+ { 1, 0, 1, 2, 11, 32, },
+ { 0, 0, 1, 2, 12, 63, },
+ { 2, 0, 1, 2, 12, 32, },
+ { 1, 0, 1, 2, 12, 32, },
+ { 0, 0, 1, 2, 13, 63, },
+ { 2, 0, 1, 2, 13, 32, },
+ { 1, 0, 1, 2, 13, 32, },
+ { 0, 0, 1, 2, 14, 63, },
+ { 2, 0, 1, 2, 14, 63, },
+ { 1, 0, 1, 2, 14, 63, },
+ { 0, 0, 1, 3, 1, 63, },
+ { 2, 0, 1, 3, 1, 63, },
+ { 1, 0, 1, 3, 1, 63, },
+ { 0, 0, 1, 3, 2, 63, },
+ { 2, 0, 1, 3, 2, 63, },
+ { 1, 0, 1, 3, 2, 63, },
+ { 0, 0, 1, 3, 3, 30, },
+ { 2, 0, 1, 3, 3, 30, },
+ { 1, 0, 1, 3, 3, 30, },
+ { 0, 0, 1, 3, 4, 34, },
+ { 2, 0, 1, 3, 4, 30, },
+ { 1, 0, 1, 3, 4, 30, },
+ { 0, 0, 1, 3, 5, 34, },
+ { 2, 0, 1, 3, 5, 30, },
+ { 1, 0, 1, 3, 5, 30, },
+ { 0, 0, 1, 3, 6, 34, },
+ { 2, 0, 1, 3, 6, 30, },
+ { 1, 0, 1, 3, 6, 30, },
+ { 0, 0, 1, 3, 7, 34, },
+ { 2, 0, 1, 3, 7, 30, },
+ { 1, 0, 1, 3, 7, 30, },
+ { 0, 0, 1, 3, 8, 34, },
+ { 2, 0, 1, 3, 8, 30, },
+ { 1, 0, 1, 3, 8, 30, },
+ { 0, 0, 1, 3, 9, 34, },
+ { 2, 0, 1, 3, 9, 30, },
+ { 1, 0, 1, 3, 9, 30, },
+ { 0, 0, 1, 3, 10, 34, },
+ { 2, 0, 1, 3, 10, 30, },
+ { 1, 0, 1, 3, 10, 30, },
+ { 0, 0, 1, 3, 11, 30, },
+ { 2, 0, 1, 3, 11, 30, },
+ { 1, 0, 1, 3, 11, 30, },
+ { 0, 0, 1, 3, 12, 63, },
+ { 2, 0, 1, 3, 12, 32, },
+ { 1, 0, 1, 3, 12, 32, },
+ { 0, 0, 1, 3, 13, 63, },
+ { 2, 0, 1, 3, 13, 32, },
+ { 1, 0, 1, 3, 13, 32, },
+ { 0, 0, 1, 3, 14, 63, },
+ { 2, 0, 1, 3, 14, 63, },
+ { 1, 0, 1, 3, 14, 63, },
+ { 0, 1, 0, 1, 36, 30, },
+ { 2, 1, 0, 1, 36, 32, },
+ { 1, 1, 0, 1, 36, 32, },
+ { 0, 1, 0, 1, 40, 30, },
+ { 2, 1, 0, 1, 40, 32, },
+ { 1, 1, 0, 1, 40, 32, },
+ { 0, 1, 0, 1, 44, 30, },
+ { 2, 1, 0, 1, 44, 32, },
+ { 1, 1, 0, 1, 44, 32, },
+ { 0, 1, 0, 1, 48, 30, },
+ { 2, 1, 0, 1, 48, 32, },
+ { 1, 1, 0, 1, 48, 32, },
+ { 0, 1, 0, 1, 52, 36, },
+ { 2, 1, 0, 1, 52, 32, },
+ { 1, 1, 0, 1, 52, 32, },
+ { 0, 1, 0, 1, 56, 34, },
+ { 2, 1, 0, 1, 56, 32, },
+ { 1, 1, 0, 1, 56, 32, },
+ { 0, 1, 0, 1, 60, 32, },
+ { 2, 1, 0, 1, 60, 32, },
+ { 1, 1, 0, 1, 60, 32, },
+ { 0, 1, 0, 1, 64, 28, },
+ { 2, 1, 0, 1, 64, 32, },
+ { 1, 1, 0, 1, 64, 32, },
+ { 0, 1, 0, 1, 100, 30, },
+ { 2, 1, 0, 1, 100, 32, },
+ { 1, 1, 0, 1, 100, 32, },
+ { 0, 1, 0, 1, 104, 30, },
+ { 2, 1, 0, 1, 104, 32, },
+ { 1, 1, 0, 1, 104, 32, },
+ { 0, 1, 0, 1, 108, 32, },
+ { 2, 1, 0, 1, 108, 32, },
+ { 1, 1, 0, 1, 108, 32, },
+ { 0, 1, 0, 1, 112, 34, },
+ { 2, 1, 0, 1, 112, 32, },
+ { 1, 1, 0, 1, 112, 32, },
+ { 0, 1, 0, 1, 116, 34, },
+ { 2, 1, 0, 1, 116, 32, },
+ { 1, 1, 0, 1, 116, 32, },
+ { 0, 1, 0, 1, 120, 36, },
+ { 2, 1, 0, 1, 120, 32, },
+ { 1, 1, 0, 1, 120, 32, },
+ { 0, 1, 0, 1, 124, 34, },
+ { 2, 1, 0, 1, 124, 32, },
+ { 1, 1, 0, 1, 124, 32, },
+ { 0, 1, 0, 1, 128, 32, },
+ { 2, 1, 0, 1, 128, 32, },
+ { 1, 1, 0, 1, 128, 32, },
+ { 0, 1, 0, 1, 132, 30, },
+ { 2, 1, 0, 1, 132, 32, },
+ { 1, 1, 0, 1, 132, 32, },
+ { 0, 1, 0, 1, 136, 30, },
+ { 2, 1, 0, 1, 136, 32, },
+ { 1, 1, 0, 1, 136, 32, },
+ { 0, 1, 0, 1, 140, 28, },
+ { 2, 1, 0, 1, 140, 32, },
+ { 1, 1, 0, 1, 140, 32, },
+ { 0, 1, 0, 1, 149, 36, },
+ { 2, 1, 0, 1, 149, 32, },
+ { 1, 1, 0, 1, 149, 63, },
+ { 0, 1, 0, 1, 153, 36, },
+ { 2, 1, 0, 1, 153, 32, },
+ { 1, 1, 0, 1, 153, 63, },
+ { 0, 1, 0, 1, 157, 36, },
+ { 2, 1, 0, 1, 157, 32, },
+ { 1, 1, 0, 1, 157, 63, },
+ { 0, 1, 0, 1, 161, 36, },
+ { 2, 1, 0, 1, 161, 32, },
+ { 1, 1, 0, 1, 161, 63, },
+ { 0, 1, 0, 1, 165, 36, },
+ { 2, 1, 0, 1, 165, 32, },
+ { 1, 1, 0, 1, 165, 63, },
+ { 0, 1, 0, 2, 36, 30, },
+ { 2, 1, 0, 2, 36, 32, },
+ { 1, 1, 0, 2, 36, 32, },
+ { 0, 1, 0, 2, 40, 30, },
+ { 2, 1, 0, 2, 40, 32, },
+ { 1, 1, 0, 2, 40, 32, },
+ { 0, 1, 0, 2, 44, 30, },
+ { 2, 1, 0, 2, 44, 32, },
+ { 1, 1, 0, 2, 44, 32, },
+ { 0, 1, 0, 2, 48, 30, },
+ { 2, 1, 0, 2, 48, 32, },
+ { 1, 1, 0, 2, 48, 32, },
+ { 0, 1, 0, 2, 52, 36, },
+ { 2, 1, 0, 2, 52, 32, },
+ { 1, 1, 0, 2, 52, 32, },
+ { 0, 1, 0, 2, 56, 34, },
+ { 2, 1, 0, 2, 56, 32, },
+ { 1, 1, 0, 2, 56, 32, },
+ { 0, 1, 0, 2, 60, 32, },
+ { 2, 1, 0, 2, 60, 32, },
+ { 1, 1, 0, 2, 60, 32, },
+ { 0, 1, 0, 2, 64, 28, },
+ { 2, 1, 0, 2, 64, 32, },
+ { 1, 1, 0, 2, 64, 32, },
+ { 0, 1, 0, 2, 100, 30, },
+ { 2, 1, 0, 2, 100, 32, },
+ { 1, 1, 0, 2, 100, 32, },
+ { 0, 1, 0, 2, 104, 30, },
+ { 2, 1, 0, 2, 104, 32, },
+ { 1, 1, 0, 2, 104, 32, },
+ { 0, 1, 0, 2, 108, 32, },
+ { 2, 1, 0, 2, 108, 32, },
+ { 1, 1, 0, 2, 108, 32, },
+ { 0, 1, 0, 2, 112, 34, },
+ { 2, 1, 0, 2, 112, 32, },
+ { 1, 1, 0, 2, 112, 32, },
+ { 0, 1, 0, 2, 116, 34, },
+ { 2, 1, 0, 2, 116, 32, },
+ { 1, 1, 0, 2, 116, 32, },
+ { 0, 1, 0, 2, 120, 36, },
+ { 2, 1, 0, 2, 120, 32, },
+ { 1, 1, 0, 2, 120, 32, },
+ { 0, 1, 0, 2, 124, 34, },
+ { 2, 1, 0, 2, 124, 32, },
+ { 1, 1, 0, 2, 124, 32, },
+ { 0, 1, 0, 2, 128, 32, },
+ { 2, 1, 0, 2, 128, 32, },
+ { 1, 1, 0, 2, 128, 32, },
+ { 0, 1, 0, 2, 132, 30, },
+ { 2, 1, 0, 2, 132, 32, },
+ { 1, 1, 0, 2, 132, 32, },
+ { 0, 1, 0, 2, 136, 30, },
+ { 2, 1, 0, 2, 136, 32, },
+ { 1, 1, 0, 2, 136, 32, },
+ { 0, 1, 0, 2, 140, 28, },
+ { 2, 1, 0, 2, 140, 32, },
+ { 1, 1, 0, 2, 140, 32, },
+ { 0, 1, 0, 2, 149, 36, },
+ { 2, 1, 0, 2, 149, 32, },
+ { 1, 1, 0, 2, 149, 63, },
+ { 0, 1, 0, 2, 153, 36, },
+ { 2, 1, 0, 2, 153, 32, },
+ { 1, 1, 0, 2, 153, 63, },
+ { 0, 1, 0, 2, 157, 36, },
+ { 2, 1, 0, 2, 157, 32, },
+ { 1, 1, 0, 2, 157, 63, },
+ { 0, 1, 0, 2, 161, 36, },
+ { 2, 1, 0, 2, 161, 32, },
+ { 1, 1, 0, 2, 161, 63, },
+ { 0, 1, 0, 2, 165, 36, },
+ { 2, 1, 0, 2, 165, 32, },
+ { 1, 1, 0, 2, 165, 63, },
+ { 0, 1, 0, 3, 36, 28, },
+ { 2, 1, 0, 3, 36, 30, },
+ { 1, 1, 0, 3, 36, 30, },
+ { 0, 1, 0, 3, 40, 28, },
+ { 2, 1, 0, 3, 40, 30, },
+ { 1, 1, 0, 3, 40, 30, },
+ { 0, 1, 0, 3, 44, 28, },
+ { 2, 1, 0, 3, 44, 30, },
+ { 1, 1, 0, 3, 44, 30, },
+ { 0, 1, 0, 3, 48, 28, },
+ { 2, 1, 0, 3, 48, 30, },
+ { 1, 1, 0, 3, 48, 30, },
+ { 0, 1, 0, 3, 52, 34, },
+ { 2, 1, 0, 3, 52, 30, },
+ { 1, 1, 0, 3, 52, 30, },
+ { 0, 1, 0, 3, 56, 32, },
+ { 2, 1, 0, 3, 56, 30, },
+ { 1, 1, 0, 3, 56, 30, },
+ { 0, 1, 0, 3, 60, 30, },
+ { 2, 1, 0, 3, 60, 30, },
+ { 1, 1, 0, 3, 60, 30, },
+ { 0, 1, 0, 3, 64, 26, },
+ { 2, 1, 0, 3, 64, 30, },
+ { 1, 1, 0, 3, 64, 30, },
+ { 0, 1, 0, 3, 100, 28, },
+ { 2, 1, 0, 3, 100, 30, },
+ { 1, 1, 0, 3, 100, 30, },
+ { 0, 1, 0, 3, 104, 28, },
+ { 2, 1, 0, 3, 104, 30, },
+ { 1, 1, 0, 3, 104, 30, },
+ { 0, 1, 0, 3, 108, 30, },
+ { 2, 1, 0, 3, 108, 30, },
+ { 1, 1, 0, 3, 108, 30, },
+ { 0, 1, 0, 3, 112, 32, },
+ { 2, 1, 0, 3, 112, 30, },
+ { 1, 1, 0, 3, 112, 30, },
+ { 0, 1, 0, 3, 116, 32, },
+ { 2, 1, 0, 3, 116, 30, },
+ { 1, 1, 0, 3, 116, 30, },
+ { 0, 1, 0, 3, 120, 34, },
+ { 2, 1, 0, 3, 120, 30, },
+ { 1, 1, 0, 3, 120, 30, },
+ { 0, 1, 0, 3, 124, 32, },
+ { 2, 1, 0, 3, 124, 30, },
+ { 1, 1, 0, 3, 124, 30, },
+ { 0, 1, 0, 3, 128, 30, },
+ { 2, 1, 0, 3, 128, 30, },
+ { 1, 1, 0, 3, 128, 30, },
+ { 0, 1, 0, 3, 132, 28, },
+ { 2, 1, 0, 3, 132, 30, },
+ { 1, 1, 0, 3, 132, 30, },
+ { 0, 1, 0, 3, 136, 28, },
+ { 2, 1, 0, 3, 136, 30, },
+ { 1, 1, 0, 3, 136, 30, },
+ { 0, 1, 0, 3, 140, 26, },
+ { 2, 1, 0, 3, 140, 30, },
+ { 1, 1, 0, 3, 140, 30, },
+ { 0, 1, 0, 3, 149, 34, },
+ { 2, 1, 0, 3, 149, 30, },
+ { 1, 1, 0, 3, 149, 63, },
+ { 0, 1, 0, 3, 153, 34, },
+ { 2, 1, 0, 3, 153, 30, },
+ { 1, 1, 0, 3, 153, 63, },
+ { 0, 1, 0, 3, 157, 34, },
+ { 2, 1, 0, 3, 157, 30, },
+ { 1, 1, 0, 3, 157, 63, },
+ { 0, 1, 0, 3, 161, 34, },
+ { 2, 1, 0, 3, 161, 30, },
+ { 1, 1, 0, 3, 161, 63, },
+ { 0, 1, 0, 3, 165, 34, },
+ { 2, 1, 0, 3, 165, 30, },
+ { 1, 1, 0, 3, 165, 63, },
+ { 0, 1, 1, 2, 38, 30, },
+ { 2, 1, 1, 2, 38, 32, },
+ { 1, 1, 1, 2, 38, 32, },
+ { 0, 1, 1, 2, 46, 30, },
+ { 2, 1, 1, 2, 46, 32, },
+ { 1, 1, 1, 2, 46, 32, },
+ { 0, 1, 1, 2, 54, 32, },
+ { 2, 1, 1, 2, 54, 32, },
+ { 1, 1, 1, 2, 54, 32, },
+ { 0, 1, 1, 2, 62, 32, },
+ { 2, 1, 1, 2, 62, 32, },
+ { 1, 1, 1, 2, 62, 32, },
+ { 0, 1, 1, 2, 102, 28, },
+ { 2, 1, 1, 2, 102, 32, },
+ { 1, 1, 1, 2, 102, 32, },
+ { 0, 1, 1, 2, 110, 32, },
+ { 2, 1, 1, 2, 110, 32, },
+ { 1, 1, 1, 2, 110, 32, },
+ { 0, 1, 1, 2, 118, 36, },
+ { 2, 1, 1, 2, 118, 32, },
+ { 1, 1, 1, 2, 118, 32, },
+ { 0, 1, 1, 2, 126, 34, },
+ { 2, 1, 1, 2, 126, 32, },
+ { 1, 1, 1, 2, 126, 32, },
+ { 0, 1, 1, 2, 134, 32, },
+ { 2, 1, 1, 2, 134, 32, },
+ { 1, 1, 1, 2, 134, 32, },
+ { 0, 1, 1, 2, 151, 36, },
+ { 2, 1, 1, 2, 151, 32, },
+ { 1, 1, 1, 2, 151, 63, },
+ { 0, 1, 1, 2, 159, 36, },
+ { 2, 1, 1, 2, 159, 32, },
+ { 1, 1, 1, 2, 159, 63, },
+ { 0, 1, 1, 3, 38, 28, },
+ { 2, 1, 1, 3, 38, 30, },
+ { 1, 1, 1, 3, 38, 30, },
+ { 0, 1, 1, 3, 46, 28, },
+ { 2, 1, 1, 3, 46, 30, },
+ { 1, 1, 1, 3, 46, 30, },
+ { 0, 1, 1, 3, 54, 30, },
+ { 2, 1, 1, 3, 54, 30, },
+ { 1, 1, 1, 3, 54, 30, },
+ { 0, 1, 1, 3, 62, 30, },
+ { 2, 1, 1, 3, 62, 30, },
+ { 1, 1, 1, 3, 62, 30, },
+ { 0, 1, 1, 3, 102, 26, },
+ { 2, 1, 1, 3, 102, 30, },
+ { 1, 1, 1, 3, 102, 30, },
+ { 0, 1, 1, 3, 110, 30, },
+ { 2, 1, 1, 3, 110, 30, },
+ { 1, 1, 1, 3, 110, 30, },
+ { 0, 1, 1, 3, 118, 34, },
+ { 2, 1, 1, 3, 118, 30, },
+ { 1, 1, 1, 3, 118, 30, },
+ { 0, 1, 1, 3, 126, 32, },
+ { 2, 1, 1, 3, 126, 30, },
+ { 1, 1, 1, 3, 126, 30, },
+ { 0, 1, 1, 3, 134, 30, },
+ { 2, 1, 1, 3, 134, 30, },
+ { 1, 1, 1, 3, 134, 30, },
+ { 0, 1, 1, 3, 151, 34, },
+ { 2, 1, 1, 3, 151, 30, },
+ { 1, 1, 1, 3, 151, 63, },
+ { 0, 1, 1, 3, 159, 34, },
+ { 2, 1, 1, 3, 159, 30, },
+ { 1, 1, 1, 3, 159, 63, },
+ { 0, 1, 2, 4, 42, 30, },
+ { 2, 1, 2, 4, 42, 32, },
+ { 1, 1, 2, 4, 42, 32, },
+ { 0, 1, 2, 4, 58, 28, },
+ { 2, 1, 2, 4, 58, 32, },
+ { 1, 1, 2, 4, 58, 32, },
+ { 0, 1, 2, 4, 106, 30, },
+ { 2, 1, 2, 4, 106, 32, },
+ { 1, 1, 2, 4, 106, 32, },
+ { 0, 1, 2, 4, 122, 34, },
+ { 2, 1, 2, 4, 122, 32, },
+ { 1, 1, 2, 4, 122, 32, },
+ { 0, 1, 2, 4, 155, 36, },
+ { 2, 1, 2, 4, 155, 32, },
+ { 1, 1, 2, 4, 155, 63, },
+ { 0, 1, 2, 5, 42, 28, },
+ { 2, 1, 2, 5, 42, 30, },
+ { 1, 1, 2, 5, 42, 30, },
+ { 0, 1, 2, 5, 58, 26, },
+ { 2, 1, 2, 5, 58, 30, },
+ { 1, 1, 2, 5, 58, 30, },
+ { 0, 1, 2, 5, 106, 28, },
+ { 2, 1, 2, 5, 106, 30, },
+ { 1, 1, 2, 5, 106, 30, },
+ { 0, 1, 2, 5, 122, 32, },
+ { 2, 1, 2, 5, 122, 30, },
+ { 1, 1, 2, 5, 122, 30, },
+ { 0, 1, 2, 5, 155, 34, },
+ { 2, 1, 2, 5, 155, 30, },
+ { 1, 1, 2, 5, 155, 63, },
+};
+
+RTW_DECL_TABLE_TXPWR_LMT(rtw8812a_txpwr_lmt);
+
+static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8812a[] = {
+ {0x0012,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0014,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x80, 0},
+ {0x0015,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x01, 0},
+ {0x0023,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x10, 0},
+ {0x0046,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+ {0x0043,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(2), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3), 0},
+ {0x0003,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
+ {0x0301,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0},
+ {0x0024,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+ {0x0028,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3), BIT(3)},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8812a[] = {
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(2), 0},
+ {0x0006,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(7), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, BIT(0), 0},
+ {0x0024,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0028,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3), 0},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_act_to_lps_8812a[] = {
+ {0x0301,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
+ {0x0522,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x7F},
+ {0x05F8,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x05F9,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x05FA,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x05FB,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x0c00,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x04},
+ {0x0e00,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x04},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0100,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x03},
+ {0x0101,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0553,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8812a[] = {
+ {0x0c00,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x04},
+ {0x0e00,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x04},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0007,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x2A},
+ {0x0008,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x02, 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, BIT(1), 0},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8812a[] = {
+ {0x0003,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(2), 0},
+ {0x0080,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x05},
+ {0x0042,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xF0, 0xcc},
+ {0x0042,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xF0, 0xEC},
+ {0x0043,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x07},
+ {0x0045,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+ {0x0046,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0xff},
+ {0x0047,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0},
+ {0x0014,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x80, BIT(7)},
+ {0x0015,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x01, BIT(0)},
+ {0x0012,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x01, 0},
+ {0x0023,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x10, BIT(4)},
+ {0x0008,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0x02, 0},
+ {0x0007,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x20},
+ {0x001f,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0076,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3), BIT(3)},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+const struct rtw_pwr_seq_cmd * const card_enable_flow_8812a[] = {
+ trans_carddis_to_cardemu_8812a,
+ trans_cardemu_to_act_8812a,
+ NULL
+};
+
+const struct rtw_pwr_seq_cmd * const enter_lps_flow_8812a[] = {
+ trans_act_to_lps_8812a,
+ NULL
+};
+
+const struct rtw_pwr_seq_cmd * const card_disable_flow_8812a[] = {
+ trans_act_to_cardemu_8812a,
+ trans_cardemu_to_carddis_8812a,
+ NULL
+};
+
+static const u8 rtw8812a_pwrtrk_5gb_n[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13, 14, 14, 14, 14, 14, 14},
+ {0, 1, 1, 2, 2, 3, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13, 14, 14, 14, 14, 14, 14},
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 11, 12, 12, 13,
+ 13, 14, 14, 15, 16, 16, 16, 16, 16},
+};
+
+static const u8 rtw8812a_pwrtrk_5gb_p[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+};
+
+static const u8 rtw8812a_pwrtrk_5ga_n[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13, 14, 15, 15, 15, 15, 15},
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13, 14, 15, 15, 15, 15, 15},
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13, 14, 15, 15, 15, 15, 15},
+};
+
+static const u8 rtw8812a_pwrtrk_5ga_p[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 12, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+};
+
+static const u8 rtw8812a_pwrtrk_2gb_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8812a_pwrtrk_2gb_p[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+static const u8 rtw8812a_pwrtrk_2ga_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 10, 10, 10
+};
+
+static const u8 rtw8812a_pwrtrk_2ga_p[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+static const u8 rtw8812a_pwrtrk_2g_cck_b_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8812a_pwrtrk_2g_cck_b_p[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+static const u8 rtw8812a_pwrtrk_2g_cck_a_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 10, 10, 10
+};
+
+static const u8 rtw8812a_pwrtrk_2g_cck_a_p[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_tbl = {
+ .pwrtrk_5gb_n[0] = rtw8812a_pwrtrk_5gb_n[0],
+ .pwrtrk_5gb_n[1] = rtw8812a_pwrtrk_5gb_n[1],
+ .pwrtrk_5gb_n[2] = rtw8812a_pwrtrk_5gb_n[2],
+ .pwrtrk_5gb_p[0] = rtw8812a_pwrtrk_5gb_p[0],
+ .pwrtrk_5gb_p[1] = rtw8812a_pwrtrk_5gb_p[1],
+ .pwrtrk_5gb_p[2] = rtw8812a_pwrtrk_5gb_p[2],
+ .pwrtrk_5ga_n[0] = rtw8812a_pwrtrk_5ga_n[0],
+ .pwrtrk_5ga_n[1] = rtw8812a_pwrtrk_5ga_n[1],
+ .pwrtrk_5ga_n[2] = rtw8812a_pwrtrk_5ga_n[2],
+ .pwrtrk_5ga_p[0] = rtw8812a_pwrtrk_5ga_p[0],
+ .pwrtrk_5ga_p[1] = rtw8812a_pwrtrk_5ga_p[1],
+ .pwrtrk_5ga_p[2] = rtw8812a_pwrtrk_5ga_p[2],
+ .pwrtrk_2gb_n = rtw8812a_pwrtrk_2gb_n,
+ .pwrtrk_2gb_p = rtw8812a_pwrtrk_2gb_p,
+ .pwrtrk_2ga_n = rtw8812a_pwrtrk_2ga_n,
+ .pwrtrk_2ga_p = rtw8812a_pwrtrk_2ga_p,
+ .pwrtrk_2g_cckb_n = rtw8812a_pwrtrk_2g_cck_b_n,
+ .pwrtrk_2g_cckb_p = rtw8812a_pwrtrk_2g_cck_b_p,
+ .pwrtrk_2g_ccka_n = rtw8812a_pwrtrk_2g_cck_a_n,
+ .pwrtrk_2g_ccka_p = rtw8812a_pwrtrk_2g_cck_a_p,
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_5gb_n[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13,
+ 13, 14, 15, 16, 16, 17, 17, 18, 18},
+ {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
+ 12, 14, 13, 13, 14, 14, 14, 15, 15},
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13, 14, 14, 15, 15, 16, 16},
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_5gb_p[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_5ga_n[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 13, 14, 15, 16, 16, 17, 17, 18, 18},
+ {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13, 14, 15, 16, 16, 17, 17},
+ {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13,
+ 13, 14, 14, 15, 15, 16, 17, 18, 18},
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_5ga_p[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+ {0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11},
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2gb_n[] = {
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7,
+ 7, 7, 8, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 15
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2gb_p[] = {
+ 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
+ 6, 7, 7, 8, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2ga_n[] = {
+ 0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9,
+ 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2ga_p[] = {
+ 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_b_n[] = {
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7,
+ 7, 7, 8, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 15
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_b_p[] = {
+ 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
+ 6, 7, 7, 8, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_a_n[] = {
+ 0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9,
+ 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15
+};
+
+static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_a_p[] = {
+ 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11
+};
+
+const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_rfe3_tbl = {
+ .pwrtrk_5gb_n[0] = rtw8812a_pwrtrk_rfe3_5gb_n[0],
+ .pwrtrk_5gb_n[1] = rtw8812a_pwrtrk_rfe3_5gb_n[1],
+ .pwrtrk_5gb_n[2] = rtw8812a_pwrtrk_rfe3_5gb_n[2],
+ .pwrtrk_5gb_p[0] = rtw8812a_pwrtrk_rfe3_5gb_p[0],
+ .pwrtrk_5gb_p[1] = rtw8812a_pwrtrk_rfe3_5gb_p[1],
+ .pwrtrk_5gb_p[2] = rtw8812a_pwrtrk_rfe3_5gb_p[2],
+ .pwrtrk_5ga_n[0] = rtw8812a_pwrtrk_rfe3_5ga_n[0],
+ .pwrtrk_5ga_n[1] = rtw8812a_pwrtrk_rfe3_5ga_n[1],
+ .pwrtrk_5ga_n[2] = rtw8812a_pwrtrk_rfe3_5ga_n[2],
+ .pwrtrk_5ga_p[0] = rtw8812a_pwrtrk_rfe3_5ga_p[0],
+ .pwrtrk_5ga_p[1] = rtw8812a_pwrtrk_rfe3_5ga_p[1],
+ .pwrtrk_5ga_p[2] = rtw8812a_pwrtrk_rfe3_5ga_p[2],
+ .pwrtrk_2gb_n = rtw8812a_pwrtrk_rfe3_2gb_n,
+ .pwrtrk_2gb_p = rtw8812a_pwrtrk_rfe3_2gb_p,
+ .pwrtrk_2ga_n = rtw8812a_pwrtrk_rfe3_2ga_n,
+ .pwrtrk_2ga_p = rtw8812a_pwrtrk_rfe3_2ga_p,
+ .pwrtrk_2g_cckb_n = rtw8812a_pwrtrk_rfe3_2g_cck_b_n,
+ .pwrtrk_2g_cckb_p = rtw8812a_pwrtrk_rfe3_2g_cck_b_p,
+ .pwrtrk_2g_ccka_n = rtw8812a_pwrtrk_rfe3_2g_cck_a_n,
+ .pwrtrk_2g_ccka_p = rtw8812a_pwrtrk_rfe3_2g_cck_a_p,
+};
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a_table.h b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.h
new file mode 100644
index 000000000000..f7ab5e4cf059
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#ifndef __RTW8812A_TABLE_H__
+#define __RTW8812A_TABLE_H__
+
+extern const struct rtw_table rtw8812a_mac_tbl;
+extern const struct rtw_table rtw8812a_agc_tbl;
+extern const struct rtw_table rtw8812a_agc_diff_lb_tbl;
+extern const struct rtw_table rtw8812a_agc_diff_hb_tbl;
+extern const struct rtw_table rtw8812a_bb_tbl;
+extern const struct rtw_table rtw8812a_bb_pg_tbl;
+extern const struct rtw_table rtw8812a_bb_pg_rfe3_tbl;
+extern const struct rtw_table rtw8812a_rf_a_tbl;
+extern const struct rtw_table rtw8812a_rf_b_tbl;
+extern const struct rtw_table rtw8812a_txpwr_lmt_tbl;
+
+extern const struct rtw_pwr_seq_cmd * const card_enable_flow_8812a[];
+extern const struct rtw_pwr_seq_cmd * const enter_lps_flow_8812a[];
+extern const struct rtw_pwr_seq_cmd * const card_disable_flow_8812a[];
+
+extern const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_tbl;
+extern const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_rfe3_tbl;
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812au.c b/drivers/net/wireless/realtek/rtw88/rtw8812au.c
new file mode 100644
index 000000000000..4da69590a423
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "main.h"
+#include "rtw8812a.h"
+#include "usb.h"
+
+static const struct usb_device_id rtw_8812au_id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
+ {},
+};
+MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table);
+
+static struct usb_driver rtw_8812au_driver = {
+ .name = "rtw_8812au",
+ .id_table = rtw_8812au_id_table,
+ .probe = rtw_usb_probe,
+ .disconnect = rtw_usb_disconnect,
+};
+module_usb_driver(rtw_8812au_driver);
+
+MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8812au driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
new file mode 100644
index 000000000000..db242c9ad68f
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
@@ -0,0 +1,1197 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#include "main.h"
+#include "coex.h"
+#include "phy.h"
+#include "reg.h"
+#include "rtw88xxa.h"
+#include "rtw8821a.h"
+#include "rtw8821a_table.h"
+#include "tx.h"
+
+static void rtw8821a_power_off(struct rtw_dev *rtwdev)
+{
+ rtw88xxa_power_off(rtwdev, enter_lps_flow_8821a);
+}
+
+static s8 rtw8821a_cck_rx_pwr(u8 lna_idx, u8 vga_idx)
+{
+ static const s8 lna_gain_table[] = {15, -1, -17, 0, -30, -38};
+ s8 rx_pwr_all = 0;
+ s8 lna_gain;
+
+ switch (lna_idx) {
+ case 5:
+ case 4:
+ case 2:
+ case 1:
+ case 0:
+ lna_gain = lna_gain_table[lna_idx];
+ rx_pwr_all = lna_gain - 2 * vga_idx;
+ break;
+ default:
+ break;
+ }
+
+ return rx_pwr_all;
+}
+
+static void rtw8821a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
+ struct rtw_rx_pkt_stat *pkt_stat)
+{
+ rtw88xxa_query_phy_status(rtwdev, phy_status, pkt_stat,
+ rtw8821a_cck_rx_pwr);
+}
+
+static void rtw8821a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
+{
+}
+
+#define CAL_NUM_8821A 3
+#define MACBB_REG_NUM_8821A 8
+#define AFE_REG_NUM_8821A 4
+#define RF_REG_NUM_8821A 3
+
+static void rtw8821a_iqk_backup_rf(struct rtw_dev *rtwdev, u32 *rfa_backup,
+ const u32 *backup_rf_reg, u32 rf_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* Save RF Parameters */
+ for (i = 0; i < rf_num; i++)
+ rfa_backup[i] = rtw_read_rf(rtwdev, RF_PATH_A,
+ backup_rf_reg[i], MASKDWORD);
+}
+
+static void rtw8821a_iqk_restore_rf(struct rtw_dev *rtwdev,
+ const u32 *backup_rf_reg,
+ u32 *RF_backup, u32 rf_reg_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ for (i = 0; i < rf_reg_num; i++)
+ rtw_write_rf(rtwdev, RF_PATH_A, backup_rf_reg[i],
+ RFREG_MASK, RF_backup[i]);
+}
+
+static void rtw8821a_iqk_restore_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
+ const u32 *backup_afe_reg, u32 afe_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* Reload AFE Parameters */
+ for (i = 0; i < afe_num; i++)
+ rtw_write32(rtwdev, backup_afe_reg[i], afe_backup[i]);
+
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x0);
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x0);
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x0);
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000);
+ rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080);
+ rtw_write32(rtwdev, REG_TXAGCIDX, 0x00000000);
+ rtw_write32(rtwdev, REG_IQK_DPD_CFG, 0x20040000);
+ rtw_write32(rtwdev, REG_CFG_PMPD, 0x20000000);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x0);
+}
+
+static void rtw8821a_iqk_rx_fill(struct rtw_dev *rtwdev,
+ unsigned int rx_x, unsigned int rx_y)
+{
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x000003ff, rx_x >> 1);
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x03ff0000, (rx_y >> 1) & 0x3ff);
+}
+
+static void rtw8821a_iqk_tx_fill(struct rtw_dev *rtwdev,
+ unsigned int tx_x, unsigned int tx_y)
+{
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080);
+ rtw_write32(rtwdev, REG_IQK_DPD_CFG, 0x20040000);
+ rtw_write32(rtwdev, REG_CFG_PMPD, 0x20000000);
+ rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, tx_y);
+ rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, tx_x);
+}
+
+static void rtw8821a_iqk_tx_vdf_true(struct rtw_dev *rtwdev, u32 cal,
+ bool *tx0iqkok,
+ int tx_x0[CAL_NUM_8821A],
+ int tx_y0[CAL_NUM_8821A])
+{
+ u32 cal_retry, delay_count, iqk_ready, tx_fail;
+ int tx_dt[3], vdf_y[3], vdf_x[3];
+ int k;
+
+ for (k = 0; k < 3; k++) {
+ switch (k) {
+ case 0:
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE,
+ 0x18008c38);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c38);
+ rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x0);
+ break;
+ case 1:
+ rtw_write32_mask(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE,
+ BIT(28), 0x0);
+ rtw_write32_mask(rtwdev, REG_OFDM0_A_TX_AFE,
+ BIT(28), 0x0);
+ rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x0);
+ break;
+ case 2:
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "vdf_y[1] = %x vdf_y[0] = %x\n",
+ vdf_y[1] >> 21 & 0x00007ff,
+ vdf_y[0] >> 21 & 0x00007ff);
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "vdf_x[1] = %x vdf_x[0] = %x\n",
+ vdf_x[1] >> 21 & 0x00007ff,
+ vdf_x[0] >> 21 & 0x00007ff);
+
+ tx_dt[cal] = (vdf_y[1] >> 20) - (vdf_y[0] >> 20);
+ tx_dt[cal] = (16 * tx_dt[cal]) * 10000 / 15708;
+ tx_dt[cal] = (tx_dt[cal] >> 1) + (tx_dt[cal] & BIT(0));
+
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE,
+ 0x18008c20);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c20);
+ rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x1);
+ rtw_write32_mask(rtwdev, REG_INTPO_SETA, 0x3fff0000,
+ tx_dt[cal] & 0x00003fff);
+ break;
+ }
+
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
+
+ for (cal_retry = 0; cal_retry < 10; cal_retry++) {
+ /* one shot */
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
+
+ mdelay(10);
+
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
+
+ for (delay_count = 0; delay_count < 20; delay_count++) {
+ iqk_ready = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ BIT(10));
+
+ /* Originally: if (~iqk_ready || delay_count > 20)
+ * that looks like a typo so make it more explicit
+ */
+ iqk_ready = true;
+
+ if (iqk_ready)
+ break;
+
+ mdelay(1);
+ }
+
+ if (delay_count < 20) {
+ /* ============TXIQK Check============== */
+ tx_fail = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ BIT(12));
+
+ /* Originally: if (~tx_fail) {
+ * It looks like a typo, so make it more explicit.
+ */
+ tx_fail = false;
+
+ if (!tx_fail) {
+ rtw_write32(rtwdev, REG_RFECTL_A,
+ 0x02000000);
+ vdf_x[k] = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ 0x07ff0000);
+ vdf_x[k] <<= 21;
+
+ rtw_write32(rtwdev, REG_RFECTL_A,
+ 0x04000000);
+ vdf_y[k] = rtw_read32_mask(rtwdev,
+ REG_IQKA_END,
+ 0x07ff0000);
+ vdf_y[k] <<= 21;
+
+ *tx0iqkok = true;
+ break;
+ }
+
+ rtw_write32_mask(rtwdev, REG_IQC_Y,
+ 0x000007ff, 0x0);
+ rtw_write32_mask(rtwdev, REG_IQC_X,
+ 0x000007ff, 0x200);
+ }
+
+ *tx0iqkok = false;
+ }
+ }
+
+ if (k == 3) {
+ tx_x0[cal] = vdf_x[k - 1];
+ tx_y0[cal] = vdf_y[k - 1];
+ }
+}
+
+static void rtw8821a_iqk_tx_vdf_false(struct rtw_dev *rtwdev, u32 cal,
+ bool *tx0iqkok,
+ int tx_x0[CAL_NUM_8821A],
+ int tx_y0[CAL_NUM_8821A])
+{
+ u32 cal_retry, delay_count, iqk_ready, tx_fail;
+
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
+
+ for (cal_retry = 0; cal_retry < 10; cal_retry++) {
+ /* one shot */
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
+
+ mdelay(10);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
+
+ for (delay_count = 0; delay_count < 20; delay_count++) {
+ iqk_ready = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(10));
+
+ /* Originally: if (~iqk_ready || delay_count > 20)
+ * that looks like a typo so make it more explicit
+ */
+ iqk_ready = true;
+
+ if (iqk_ready)
+ break;
+
+ mdelay(1);
+ }
+
+ if (delay_count < 20) {
+ /* ============TXIQK Check============== */
+ tx_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(12));
+
+ /* Originally: if (~tx_fail) {
+ * It looks like a typo, so make it more explicit.
+ */
+ tx_fail = false;
+
+ if (!tx_fail) {
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x02000000);
+ tx_x0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
+ 0x07ff0000);
+ tx_x0[cal] <<= 21;
+
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x04000000);
+ tx_y0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
+ 0x07ff0000);
+ tx_y0[cal] <<= 21;
+
+ *tx0iqkok = true;
+ break;
+ }
+
+ rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, 0x0);
+ rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, 0x200);
+ }
+
+ *tx0iqkok = false;
+ }
+}
+
+static void rtw8821a_iqk_rx(struct rtw_dev *rtwdev, u32 cal, bool *rx0iqkok,
+ int rx_x0[CAL_NUM_8821A],
+ int rx_y0[CAL_NUM_8821A])
+{
+ u32 cal_retry, delay_count, iqk_ready, rx_fail;
+
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
+
+ for (cal_retry = 0; cal_retry < 10; cal_retry++) {
+ /* one shot */
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
+
+ mdelay(10);
+
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
+
+ for (delay_count = 0; delay_count < 20; delay_count++) {
+ iqk_ready = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(10));
+
+ /* Originally: if (~iqk_ready || delay_count > 20)
+ * that looks like a typo so make it more explicit
+ */
+ iqk_ready = true;
+
+ if (iqk_ready)
+ break;
+
+ mdelay(1);
+ }
+
+ if (delay_count < 20) {
+ /* ============RXIQK Check============== */
+ rx_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(11));
+ if (!rx_fail) {
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x06000000);
+ rx_x0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
+ 0x07ff0000);
+ rx_x0[cal] <<= 21;
+
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x08000000);
+ rx_y0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
+ 0x07ff0000);
+ rx_y0[cal] <<= 21;
+
+ *rx0iqkok = true;
+ break;
+ }
+
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x000003ff, 0x200 >> 1);
+ rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
+ 0x03ff0000, 0x0 >> 1);
+ }
+
+ *rx0iqkok = false;
+ }
+}
+
+static void rtw8821a_iqk(struct rtw_dev *rtwdev)
+{
+ int tx_average = 0, rx_average = 0, rx_iqk_loop = 0;
+ const struct rtw_efuse *efuse = &rtwdev->efuse;
+ int tx_x = 0, tx_y = 0, rx_x = 0, rx_y = 0;
+ const struct rtw_hal *hal = &rtwdev->hal;
+ bool tx0iqkok = false, rx0iqkok = false;
+ int rx_x_temp = 0, rx_y_temp = 0;
+ int rx_x0[2][CAL_NUM_8821A];
+ int rx_y0[2][CAL_NUM_8821A];
+ int tx_x0[CAL_NUM_8821A];
+ int tx_y0[CAL_NUM_8821A];
+ bool rx_finish1 = false;
+ bool rx_finish2 = false;
+ bool vdf_enable;
+ u32 cal;
+ int i;
+
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "band_width = %d, ext_pa = %d, ext_pa_5g = %d\n",
+ hal->current_band_width, efuse->ext_pa_2g, efuse->ext_pa_5g);
+
+ vdf_enable = hal->current_band_width == RTW_CHANNEL_WIDTH_80;
+
+ for (cal = 0; cal < CAL_NUM_8821A; cal++) {
+ /* path-A LOK */
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* ========path-A AFE all on======== */
+ /* Port 0 DAC/ADC on */
+ rtw_write32(rtwdev, REG_AFE_PWR1_A, 0x77777777);
+ rtw_write32(rtwdev, REG_AFE_PWR2_A, 0x77777777);
+
+ rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_A, 0x19791979);
+
+ /* hardware 3-wire off */
+ rtw_write32_mask(rtwdev, REG_3WIRE_SWA, 0xf, 0x4);
+
+ /* LOK setting */
+
+ /* 1. DAC/ADC sampling rate (160 MHz) */
+ rtw_write32_mask(rtwdev, REG_CK_MONHA, GENMASK(26, 24), 0x7);
+
+ /* 2. LoK RF setting (at BW = 20M) */
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80002);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x00c00, 0x3);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
+ 0x20000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
+ 0x0003f);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
+ 0xf3fc3);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK,
+ 0x931d5);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001);
+ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
+ rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1);
+ /* TX (X,Y) */
+ rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000);
+ /* RX (X,Y) */
+ rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000);
+ /* [0]:AGC_en, [15]:idac_K_Mask */
+ rtw_write32(rtwdev, REG_IQK_COM96, 0x00462910);
+
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ if (efuse->ext_pa_5g)
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
+ 0x821403f7);
+ else
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
+ 0x821403f4);
+
+ if (hal->current_band_type == RTW_BAND_5G)
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x68163e96);
+ else
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28163e96);
+
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
+ rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
+
+ mdelay(10);
+ rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXMOD, 0x7fe00,
+ rtw_read_rf(rtwdev, RF_PATH_A, RF_DTXLOK, 0xffc00));
+
+ if (hal->current_band_width == RTW_CHANNEL_WIDTH_40)
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH,
+ RF18_BW_MASK, 0x1);
+ else if (hal->current_band_width == RTW_CHANNEL_WIDTH_80)
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH,
+ RF18_BW_MASK, 0x0);
+
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ /* 3. TX RF setting */
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
+ 0x20000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
+ 0x0003f);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
+ 0xf3fc3);
+
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d5);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000);
+ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
+ rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1);
+ /* TX (X,Y) */
+ rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000);
+ /* RX (X,Y) */
+ rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000);
+ /* [0]:AGC_en, [15]:idac_K_Mask */
+ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a910);
+
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ if (efuse->ext_pa_5g)
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
+ 0x821403f7);
+ else
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
+ 0x821403e3);
+
+ if (hal->current_band_type == RTW_BAND_5G)
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x40163e96);
+ else
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x00163e96);
+
+ if (vdf_enable)
+ rtw8821a_iqk_tx_vdf_true(rtwdev, cal, &tx0iqkok,
+ tx_x0, tx_y0);
+ else
+ rtw8821a_iqk_tx_vdf_false(rtwdev, cal, &tx0iqkok,
+ tx_x0, tx_y0);
+
+ if (!tx0iqkok)
+ break; /* TXK fail, Don't do RXK */
+
+ /* ====== RX IQK ====== */
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+ /* 1. RX RF setting */
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
+ 0x30000);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
+ 0x0002f);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
+ 0xfffbb);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x88001);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d8);
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000);
+
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000,
+ (tx_x0[cal] >> 21) & 0x000007ff);
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF,
+ (tx_y0[cal] >> 21) & 0x000007ff);
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x1);
+ rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x0);
+ rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
+ rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a911);
+
+ /* [31] = 1 --> Page C1 */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
+
+ /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
+ rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x38008c10);
+ /* RX_Tone_idx[9:0], RxK_Mask[29] */
+ rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x18008c10);
+ rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x02140119);
+
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE)
+ rx_iqk_loop = 2; /* for 2% fail; */
+ else
+ rx_iqk_loop = 1;
+
+ for (i = 0; i < rx_iqk_loop; i++) {
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE && i == 0)
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28161100); /* Good */
+ else
+ rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28160d00);
+
+ rtw8821a_iqk_rx(rtwdev, cal, &rx0iqkok,
+ rx_x0[i], rx_y0[i]);
+ }
+
+ if (tx0iqkok)
+ tx_average++;
+ if (rx0iqkok)
+ rx_average++;
+ }
+
+ /* FillIQK Result */
+
+ if (tx_average == 0)
+ return;
+
+ for (i = 0; i < tx_average; i++)
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "tx_x0[%d] = %x ;; tx_y0[%d] = %x\n",
+ i, (tx_x0[i] >> 21) & 0x000007ff,
+ i, (tx_y0[i] >> 21) & 0x000007ff);
+
+ if (rtw88xxa_iqk_finish(tx_average, 3, tx_x0, tx_y0,
+ &tx_x, &tx_y, true, true))
+ rtw8821a_iqk_tx_fill(rtwdev, tx_x, tx_y);
+ else
+ rtw8821a_iqk_tx_fill(rtwdev, 0x200, 0x0);
+
+ if (rx_average == 0)
+ return;
+
+ for (i = 0; i < rx_average; i++) {
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx_x0[0][%d] = %x ;; rx_y0[0][%d] = %x\n",
+ i, (rx_x0[0][i] >> 21) & 0x000007ff,
+ i, (rx_y0[0][i] >> 21) & 0x000007ff);
+
+ if (rx_iqk_loop == 2)
+ rtw_dbg(rtwdev, RTW_DBG_RFK,
+ "rx_x0[1][%d] = %x ;; rx_y0[1][%d] = %x\n",
+ i, (rx_x0[1][i] >> 21) & 0x000007ff,
+ i, (rx_y0[1][i] >> 21) & 0x000007ff);
+ }
+
+ rx_finish1 = rtw88xxa_iqk_finish(rx_average, 4, rx_x0[0], rx_y0[0],
+ &rx_x_temp, &rx_y_temp, true, true);
+
+ if (rx_finish1) {
+ rx_x = rx_x_temp;
+ rx_y = rx_y_temp;
+ }
+
+ if (rx_iqk_loop == 2) {
+ rx_finish2 = rtw88xxa_iqk_finish(rx_average, 4,
+ rx_x0[1], rx_y0[1],
+ &rx_x, &rx_y, true, true);
+
+ if (rx_finish1 && rx_finish2) {
+ rx_x = (rx_x + rx_x_temp) / 2;
+ rx_y = (rx_y + rx_y_temp) / 2;
+ }
+ }
+
+ if (rx_finish1 || rx_finish2)
+ rtw8821a_iqk_rx_fill(rtwdev, rx_x, rx_y);
+ else
+ rtw8821a_iqk_rx_fill(rtwdev, 0x200, 0x0);
+}
+
+static void rtw8821a_do_iqk(struct rtw_dev *rtwdev)
+{
+ static const u32 backup_macbb_reg[MACBB_REG_NUM_8821A] = {
+ 0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0x838, 0x82c
+ };
+ static const u32 backup_afe_reg[AFE_REG_NUM_8821A] = {
+ 0xc5c, 0xc60, 0xc64, 0xc68
+ };
+ static const u32 backup_rf_reg[RF_REG_NUM_8821A] = {
+ 0x65, 0x8f, 0x0
+ };
+ u32 macbb_backup[MACBB_REG_NUM_8821A];
+ u32 afe_backup[AFE_REG_NUM_8821A];
+ u32 rfa_backup[RF_REG_NUM_8821A];
+
+ rtw88xxa_iqk_backup_mac_bb(rtwdev, macbb_backup,
+ backup_macbb_reg, MACBB_REG_NUM_8821A);
+ rtw88xxa_iqk_backup_afe(rtwdev, afe_backup,
+ backup_afe_reg, AFE_REG_NUM_8821A);
+ rtw8821a_iqk_backup_rf(rtwdev, rfa_backup,
+ backup_rf_reg, RF_REG_NUM_8821A);
+
+ rtw88xxa_iqk_configure_mac(rtwdev);
+
+ rtw8821a_iqk(rtwdev);
+
+ rtw8821a_iqk_restore_rf(rtwdev, backup_rf_reg,
+ rfa_backup, RF_REG_NUM_8821A);
+ rtw8821a_iqk_restore_afe(rtwdev, afe_backup,
+ backup_afe_reg, AFE_REG_NUM_8821A);
+ rtw88xxa_iqk_restore_mac_bb(rtwdev, macbb_backup,
+ backup_macbb_reg, MACBB_REG_NUM_8821A);
+}
+
+static void rtw8821a_phy_calibration(struct rtw_dev *rtwdev)
+{
+ rtw8821a_do_iqk(rtwdev);
+}
+
+static void rtw8821a_pwr_track(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+ if (!dm_info->pwr_trk_triggered) {
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER,
+ GENMASK(17, 16), 0x03);
+ dm_info->pwr_trk_triggered = true;
+ return;
+ }
+
+ rtw88xxa_phy_pwrtrack(rtwdev, NULL, rtw8821a_do_iqk);
+ dm_info->pwr_trk_triggered = false;
+}
+
+static void rtw8821a_fill_txdesc_checksum(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *txdesc)
+{
+ fill_txdesc_checksum_common(txdesc, 16);
+}
+
+static void rtw8821a_coex_cfg_init(struct rtw_dev *rtwdev)
+{
+ u8 val8;
+
+ /* BT report packet sample rate */
+ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
+
+ val8 = BIT_STATIS_BT_EN;
+ if (rtwdev->efuse.share_ant)
+ val8 |= BIT_R_GRANTALL_WLMASK;
+ rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL, val8);
+
+ /* enable BT counter statistics */
+ rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x3);
+
+ /* enable PTA */
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
+}
+
+static void rtw8821a_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type,
+ u8 pos_type)
+{
+ bool share_ant = rtwdev->efuse.share_ant;
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ u32 phase = coex_dm->cur_ant_pos_type;
+
+ if (!rtwdev->efuse.btcoex)
+ return;
+
+ switch (phase) {
+ case COEX_SET_ANT_POWERON:
+ case COEX_SET_ANT_INIT:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
+
+ rtw_write8(rtwdev, REG_RFE_CTRL8,
+ share_ant ? PTA_CTRL_PIN : DPDT_CTRL_PIN);
+ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1);
+ break;
+ case COEX_SET_ANT_WONLY:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ rtw_write8_clr(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
+
+ rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN);
+ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1);
+ break;
+ case COEX_SET_ANT_2G:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ rtw_write8_clr(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
+
+ rtw_write8(rtwdev, REG_RFE_CTRL8,
+ share_ant ? PTA_CTRL_PIN : DPDT_CTRL_PIN);
+ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1);
+ break;
+ case COEX_SET_ANT_5G:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
+
+ rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN);
+ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000,
+ share_ant ? 0x2 : 0x1);
+ break;
+ case COEX_SET_ANT_WOFF:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
+
+ rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN);
+ rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000,
+ share_ant ? 0x2 : 0x1);
+ break;
+ default:
+ rtw_warn(rtwdev, "%s: not handling phase %d\n",
+ __func__, phase);
+ break;
+ }
+}
+
+static void rtw8821a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw8821a_coex_cfg_gnt_debug(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw8821a_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+
+ coex_rfe->ant_switch_exist = true;
+}
+
+static void rtw8821a_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ bool share_ant = efuse->share_ant;
+
+ if (share_ant)
+ return;
+
+ if (wl_pwr == coex_dm->cur_wl_pwr_lvl)
+ return;
+
+ coex_dm->cur_wl_pwr_lvl = wl_pwr;
+}
+
+static void rtw8821a_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
+{
+}
+
+static const struct rtw_chip_ops rtw8821a_ops = {
+ .power_on = rtw88xxa_power_on,
+ .power_off = rtw8821a_power_off,
+ .phy_set_param = NULL,
+ .read_efuse = rtw88xxa_read_efuse,
+ .query_phy_status = rtw8821a_query_phy_status,
+ .set_channel = rtw88xxa_set_channel,
+ .mac_init = NULL,
+ .read_rf = rtw88xxa_phy_read_rf,
+ .write_rf = rtw_phy_write_rf_reg_sipi,
+ .set_antenna = NULL,
+ .set_tx_power_index = rtw88xxa_set_tx_power_index,
+ .cfg_ldo25 = rtw8821a_cfg_ldo25,
+ .efuse_grant = rtw88xxa_efuse_grant,
+ .false_alarm_statistics = rtw88xxa_false_alarm_statistics,
+ .phy_calibration = rtw8821a_phy_calibration,
+ .cck_pd_set = rtw88xxa_phy_cck_pd_set,
+ .pwr_track = rtw8821a_pwr_track,
+ .config_bfee = NULL,
+ .set_gid_table = NULL,
+ .cfg_csi_rate = NULL,
+ .fill_txdesc_checksum = rtw8821a_fill_txdesc_checksum,
+ .coex_set_init = rtw8821a_coex_cfg_init,
+ .coex_set_ant_switch = rtw8821a_coex_cfg_ant_switch,
+ .coex_set_gnt_fix = rtw8821a_coex_cfg_gnt_fix,
+ .coex_set_gnt_debug = rtw8821a_coex_cfg_gnt_debug,
+ .coex_set_rfe_type = rtw8821a_coex_cfg_rfe_type,
+ .coex_set_wl_tx_power = rtw8821a_coex_cfg_wl_tx_power,
+ .coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain,
+};
+
+static const struct rtw_page_table page_table_8821a[] = {
+ /* hq_num, nq_num, lq_num, exq_num, gapq_num */
+ {0, 0, 0, 0, 0}, /* SDIO */
+ {0, 0, 0, 0, 0}, /* PCI */
+ {8, 0, 0, 0, 1}, /* 2 bulk out endpoints */
+ {8, 0, 8, 0, 1}, /* 3 bulk out endpoints */
+ {8, 0, 8, 4, 1}, /* 4 bulk out endpoints */
+};
+
+static const struct rtw_rqpn rqpn_table_8821a[] = {
+ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH,
+ RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
+
+ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+ RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+ RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+};
+
+static const struct rtw_prioq_addrs prioq_addrs_8821a = {
+ .prio[RTW_DMA_MAPPING_EXTRA] = {
+ .rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
+ },
+ .prio[RTW_DMA_MAPPING_LOW] = {
+ .rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
+ },
+ .prio[RTW_DMA_MAPPING_NORMAL] = {
+ .rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
+ },
+ .prio[RTW_DMA_MAPPING_HIGH] = {
+ .rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
+ },
+ .wsize = false,
+};
+
+static const struct rtw_hw_reg rtw8821a_dig[] = {
+ [0] = { .addr = REG_RXIGI_A, .mask = 0x7f },
+};
+
+static const struct rtw_rfe_def rtw8821a_rfe_defs[] = {
+ [0] = { .phy_pg_tbl = &rtw8821a_bb_pg_tbl,
+ .txpwr_lmt_tbl = &rtw8821a_txpwr_lmt_tbl,
+ .pwr_track_tbl = &rtw8821a_rtw_pwr_track_tbl, },
+};
+
+/* TODO */
+/* rssi in percentage % (dbm = % - 100) */
+static const u8 wl_rssi_step_8821a[] = {101, 45, 101, 40};
+static const u8 bt_rssi_step_8821a[] = {101, 101, 101, 101};
+
+/* table_sant_8821a, table_nsant_8821a, tdma_sant_8821a, and tdma_nsant_8821a
+ * are copied from rtw8821c.c because the 8821au driver's tables are not
+ * compatible with the coex code in rtw88.
+ *
+ * tdma case 112 (A2DP) byte 0 had to be modified from 0x61 to 0x51,
+ * otherwise the firmware gets confused after pausing the music:
+ * rtw_8821au 1-2:1.2: [BTCoex], Bt_info[1], len=7, data=[81 00 0a 01 00 00]
+ * - 81 means PAN (personal area network) when it should be 4x (A2DP)
+ * The music is not smooth with the PAN algorithm.
+ */
+
+/* Shared-Antenna Coex Table */
+static const struct coex_table_para table_sant_8821a[] = {
+ {0x55555555, 0x55555555}, /* case-0 */
+ {0x55555555, 0x55555555},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xfafafafa, 0xfafafafa}, /* case-5 */
+ {0x6a5a5555, 0xaaaaaaaa},
+ {0x6a5a56aa, 0x6a5a56aa},
+ {0x6a5a5a5a, 0x6a5a5a5a},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-10 */
+ {0x66555555, 0xaaaaaaaa},
+ {0x66555555, 0x6a5a5aaa},
+ {0x66555555, 0x6aaa6aaa},
+ {0x66555555, 0x6a5a5aaa},
+ {0x66555555, 0xaaaaaaaa}, /* case-15 */
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x6afa5afa},
+ {0xaaffffaa, 0xfafafafa},
+ {0xaa5555aa, 0x5a5a5a5a},
+ {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
+ {0xaa5555aa, 0xaaaaaaaa},
+ {0xffffffff, 0x55555555},
+ {0xffffffff, 0x5a5a5a5a},
+ {0xffffffff, 0x5a5a5a5a},
+ {0xffffffff, 0x5a5a5aaa}, /* case-25 */
+ {0x55555555, 0x5a5a5a5a},
+ {0x55555555, 0xaaaaaaaa},
+ {0x66555555, 0x6a5a6a5a},
+ {0x66556655, 0x66556655},
+ {0x66556aaa, 0x6a5a6aaa}, /* case-30 */
+ {0xffffffff, 0x5aaa5aaa},
+ {0x56555555, 0x5a5a5aaa}
+};
+
+/* Non-Shared-Antenna Coex Table */
+static const struct coex_table_para table_nsant_8821a[] = {
+ {0xffffffff, 0xffffffff}, /* case-100 */
+ {0xffff55ff, 0xfafafafa},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xffffffff, 0xffffffff}, /* case-105 */
+ {0x5afa5afa, 0x5afa5afa},
+ {0x55555555, 0xfafafafa},
+ {0x66555555, 0xfafafafa},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-110 */
+ {0x66555555, 0xaaaaaaaa},
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x5afa5afa},
+ {0xffff55ff, 0xaaaaaaaa},
+ {0xffff55ff, 0xffff55ff}, /* case-115 */
+ {0xaaffffaa, 0x5afa5afa},
+ {0xaaffffaa, 0xaaaaaaaa},
+ {0xffffffff, 0xfafafafa},
+ {0xffff55ff, 0xfafafafa},
+ {0xffffffff, 0xaaaaaaaa}, /* case-120 */
+ {0xffff55ff, 0x5afa5afa},
+ {0xffff55ff, 0x5afa5afa},
+ {0x55ff55ff, 0x55ff55ff}
+};
+
+/* Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_sant_8821a[] = {
+ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} },
+ { {0x61, 0x35, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} }, /* case-5 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x35, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */
+ { {0x61, 0x08, 0x03, 0x11, 0x15} },
+ { {0x61, 0x08, 0x03, 0x10, 0x14} },
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
+ { {0x51, 0x3a, 0x03, 0x11, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x21, 0x03, 0x10, 0x50} },
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */
+ { {0x51, 0x4a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x08, 0x03, 0x30, 0x54} },
+ { {0x55, 0x08, 0x03, 0x10, 0x54} },
+ { {0x65, 0x10, 0x03, 0x11, 0x10} },
+ { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
+ { {0x51, 0x21, 0x03, 0x10, 0x50} },
+ { {0x61, 0x08, 0x03, 0x11, 0x11} }
+};
+
+/* Non-Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_nsant_8821a[] = {
+ { {0x00, 0x00, 0x00, 0x40, 0x00} }, /* case-100 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x25, 0x03, 0x11, 0x11} },
+ { {0x61, 0x35, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */
+ { {0x61, 0x10, 0x03, 0x11, 0x11} },
+ { {0x51, 0x08, 0x03, 0x10, 0x14} }, /* a2dp high rssi */
+ { {0x51, 0x08, 0x03, 0x10, 0x54} }, /* a2dp not high rssi */
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
+ { {0x51, 0x3a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x21, 0x03, 0x10, 0x50} },
+ { {0x51, 0x21, 0x03, 0x10, 0x50} }, /* case-120 */
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }
+};
+
+/* TODO */
+static const struct coex_rf_para rf_para_tx_8821a[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 20, false, 7}, /* for WL-CPT */
+ {8, 17, true, 4},
+ {7, 18, true, 4},
+ {6, 19, true, 4},
+ {5, 20, true, 4}
+};
+
+static const struct coex_rf_para rf_para_rx_8821a[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 20, false, 7}, /* for WL-CPT */
+ {3, 24, true, 5},
+ {2, 26, true, 5},
+ {1, 27, true, 5},
+ {0, 28, true, 5}
+};
+
+static_assert(ARRAY_SIZE(rf_para_tx_8821a) == ARRAY_SIZE(rf_para_rx_8821a));
+
+static const struct coex_5g_afh_map afh_5g_8821a[] = { {0, 0, 0} };
+
+static const struct rtw_reg_domain coex_info_hw_regs_8821a[] = {
+ {0xCB0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0xCB4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0xCBA, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0, 0, RTW_REG_DOMAIN_NL},
+ {0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+ {0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0x45e, BIT(3), RTW_REG_DOMAIN_MAC8},
+ {0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+ {0, 0, RTW_REG_DOMAIN_NL},
+ {0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32},
+ {0x64, BIT(0), RTW_REG_DOMAIN_MAC8},
+ {0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8},
+ {0x40, BIT(5), RTW_REG_DOMAIN_MAC8},
+ {0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_A},
+ {0, 0, RTW_REG_DOMAIN_NL},
+ {0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
+ {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+};
+
+const struct rtw_chip_info rtw8821a_hw_spec = {
+ .ops = &rtw8821a_ops,
+ .id = RTW_CHIP_TYPE_8821A,
+ .fw_name = "rtw88/rtw8821a_fw.bin",
+ .wlan_cpu = RTW_WCPU_11N,
+ .tx_pkt_desc_sz = 40,
+ .tx_buf_desc_sz = 16,
+ .rx_pkt_desc_sz = 24,
+ .rx_buf_desc_sz = 8,
+ .phy_efuse_size = 512,
+ .log_efuse_size = 512,
+ .ptct_efuse_size = 96 + 1, /* TODO or just 18? */
+ .txff_size = 65536,
+ .rxff_size = 16128,
+ .rsvd_drv_pg_num = 8,
+ .txgi_factor = 1,
+ .is_pwr_by_rate_dec = true,
+ .max_power_index = 0x3f,
+ .csi_buf_pg_num = 0,
+ .band = RTW_BAND_2G | RTW_BAND_5G,
+ .page_size = 256,
+ .dig_min = 0x20,
+ .ht_supported = true,
+ .vht_supported = true,
+ .lps_deep_mode_supported = 0,
+ .sys_func_en = 0xFD,
+ .pwr_on_seq = card_enable_flow_8821a,
+ .pwr_off_seq = card_disable_flow_8821a,
+ .page_table = page_table_8821a,
+ .rqpn_table = rqpn_table_8821a,
+ .prioq_addrs = &prioq_addrs_8821a,
+ .intf_table = NULL,
+ .dig = rtw8821a_dig,
+ .rf_sipi_addr = {REG_LSSI_WRITE_A, REG_LSSI_WRITE_B},
+ .ltecoex_addr = NULL,
+ .mac_tbl = &rtw8821a_mac_tbl,
+ .agc_tbl = &rtw8821a_agc_tbl,
+ .bb_tbl = &rtw8821a_bb_tbl,
+ .rf_tbl = {&rtw8821a_rf_a_tbl},
+ .rfe_defs = rtw8821a_rfe_defs,
+ .rfe_defs_size = ARRAY_SIZE(rtw8821a_rfe_defs),
+ .rx_ldpc = false,
+ .hw_feature_report = false,
+ .c2h_ra_report_size = 4,
+ .old_datarate_fb_limit = true,
+ .usb_tx_agg_desc_num = 6,
+ .iqk_threshold = 8,
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+ .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
+
+ .coex_para_ver = 20190509, /* glcoex_ver_date_8821a_1ant */
+ .bt_desired_ver = 0x62, /* But for 2 ant it's 0x5c */
+ .scbd_support = false,
+ .new_scbd10_def = false,
+ .ble_hid_profile_support = false,
+ .wl_mimo_ps_support = false,
+ .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
+ .bt_rssi_type = COEX_BTRSSI_RATIO,
+ .ant_isolation = 10,
+ .rssi_tolerance = 2,
+ .wl_rssi_step = wl_rssi_step_8821a,
+ .bt_rssi_step = bt_rssi_step_8821a,
+ .table_sant_num = ARRAY_SIZE(table_sant_8821a),
+ .table_sant = table_sant_8821a,
+ .table_nsant_num = ARRAY_SIZE(table_nsant_8821a),
+ .table_nsant = table_nsant_8821a,
+ .tdma_sant_num = ARRAY_SIZE(tdma_sant_8821a),
+ .tdma_sant = tdma_sant_8821a,
+ .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8821a),
+ .tdma_nsant = tdma_nsant_8821a,
+ .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8821a),
+ .wl_rf_para_tx = rf_para_tx_8821a,
+ .wl_rf_para_rx = rf_para_rx_8821a,
+ .bt_afh_span_bw20 = 0x20,
+ .bt_afh_span_bw40 = 0x30,
+ .afh_5g_num = ARRAY_SIZE(afh_5g_8821a),
+ .afh_5g = afh_5g_8821a,
+
+ .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8821a),
+ .coex_info_hw_regs = coex_info_hw_regs_8821a,
+};
+EXPORT_SYMBOL(rtw8821a_hw_spec);
+
+MODULE_FIRMWARE("rtw88/rtw8821a_fw.bin");
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.h b/drivers/net/wireless/realtek/rtw88/rtw8821a.h
new file mode 100644
index 000000000000..1b2e548f7234
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#ifndef __RTW8821A_H__
+#define __RTW8821A_H__
+
+extern const struct rtw_chip_info rtw8821a_hw_spec;
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a_table.c b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.c
new file mode 100644
index 000000000000..c8fd8e331f69
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.c
@@ -0,0 +1,2350 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#include "main.h"
+#include "phy.h"
+#include "rtw8821a_table.h"
+
+static const u32 rtw8821a_mac[] = {
+ 0x421, 0x0000000F,
+ 0x428, 0x0000000A,
+ 0x429, 0x00000010,
+ 0x430, 0x00000000,
+ 0x431, 0x00000000,
+ 0x432, 0x00000000,
+ 0x433, 0x00000001,
+ 0x434, 0x00000004,
+ 0x435, 0x00000005,
+ 0x436, 0x00000007,
+ 0x437, 0x00000008,
+ 0x43C, 0x00000004,
+ 0x43D, 0x00000005,
+ 0x43E, 0x00000007,
+ 0x43F, 0x00000008,
+ 0x440, 0x0000005D,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000010,
+ 0x445, 0x00000000,
+ 0x446, 0x00000000,
+ 0x447, 0x00000000,
+ 0x448, 0x00000000,
+ 0x449, 0x000000F0,
+ 0x44A, 0x0000000F,
+ 0x44B, 0x0000003E,
+ 0x44C, 0x00000010,
+ 0x44D, 0x00000000,
+ 0x44E, 0x00000000,
+ 0x44F, 0x00000000,
+ 0x450, 0x00000000,
+ 0x451, 0x000000F0,
+ 0x452, 0x0000000F,
+ 0x453, 0x00000000,
+ 0x456, 0x0000005E,
+ 0x460, 0x00000066,
+ 0x461, 0x00000066,
+ 0x4C8, 0x0000003F,
+ 0x4C9, 0x000000FF,
+ 0x4CC, 0x000000FF,
+ 0x4CD, 0x000000FF,
+ 0x4CE, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000A2,
+ 0x502, 0x0000002F,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000A3,
+ 0x506, 0x0000005E,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002B,
+ 0x509, 0x000000A4,
+ 0x50A, 0x0000005E,
+ 0x50B, 0x00000000,
+ 0x50C, 0x0000004F,
+ 0x50D, 0x000000A4,
+ 0x50E, 0x00000000,
+ 0x50F, 0x00000000,
+ 0x512, 0x0000001C,
+ 0x514, 0x0000000A,
+ 0x516, 0x0000000A,
+ 0x525, 0x0000004F,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55C, 0x00000050,
+ 0x55D, 0x000000FF,
+ 0x605, 0x00000030,
+ 0x607, 0x00000007,
+ 0x608, 0x0000000E,
+ 0x609, 0x0000002A,
+ 0x620, 0x000000FF,
+ 0x621, 0x000000FF,
+ 0x622, 0x000000FF,
+ 0x623, 0x000000FF,
+ 0x624, 0x000000FF,
+ 0x625, 0x000000FF,
+ 0x626, 0x000000FF,
+ 0x627, 0x000000FF,
+ 0x638, 0x00000050,
+ 0x63C, 0x0000000A,
+ 0x63D, 0x0000000A,
+ 0x63E, 0x0000000E,
+ 0x63F, 0x0000000E,
+ 0x640, 0x00000040,
+ 0x642, 0x00000040,
+ 0x643, 0x00000000,
+ 0x652, 0x000000C8,
+ 0x66E, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70A, 0x00000065,
+ 0x70B, 0x00000087,
+ 0x718, 0x00000040,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8821a_mac, rtw_phy_cfg_mac);
+
+static const u32 rtw8821a_agc[] = {
+ 0x81C, 0xBF000001,
+ 0x81C, 0xBF020001,
+ 0x81C, 0xBF040001,
+ 0x81C, 0xBF060001,
+ 0x81C, 0xBE080001,
+ 0x81C, 0xBD0A0001,
+ 0x81C, 0xBC0C0001,
+ 0x81C, 0xBA0E0001,
+ 0x81C, 0xB9100001,
+ 0x81C, 0xB8120001,
+ 0x81C, 0xB7140001,
+ 0x81C, 0xB6160001,
+ 0x81C, 0xB5180001,
+ 0x81C, 0xB41A0001,
+ 0x81C, 0xB31C0001,
+ 0x81C, 0xB21E0001,
+ 0x81C, 0xB1200001,
+ 0x81C, 0xB0220001,
+ 0x81C, 0xAF240001,
+ 0x81C, 0xAE260001,
+ 0x81C, 0xAD280001,
+ 0x81C, 0xAC2A0001,
+ 0x81C, 0xAB2C0001,
+ 0x81C, 0xAA2E0001,
+ 0x81C, 0xA9300001,
+ 0x81C, 0xA8320001,
+ 0x81C, 0xA7340001,
+ 0x81C, 0xA6360001,
+ 0x81C, 0xA5380001,
+ 0x81C, 0xA43A0001,
+ 0x81C, 0x683C0001,
+ 0x81C, 0x673E0001,
+ 0x81C, 0x66400001,
+ 0x81C, 0x65420001,
+ 0x81C, 0x64440001,
+ 0x81C, 0x63460001,
+ 0x81C, 0x62480001,
+ 0x81C, 0x614A0001,
+ 0x81C, 0x474C0001,
+ 0x81C, 0x464E0001,
+ 0x81C, 0x45500001,
+ 0x81C, 0x44520001,
+ 0x81C, 0x43540001,
+ 0x81C, 0x42560001,
+ 0x81C, 0x41580001,
+ 0x81C, 0x285A0001,
+ 0x81C, 0x275C0001,
+ 0x81C, 0x265E0001,
+ 0x81C, 0x25600001,
+ 0x81C, 0x24620001,
+ 0x81C, 0x0A640001,
+ 0x81C, 0x09660001,
+ 0x81C, 0x08680001,
+ 0x81C, 0x076A0001,
+ 0x81C, 0x066C0001,
+ 0x81C, 0x056E0001,
+ 0x81C, 0x04700001,
+ 0x81C, 0x03720001,
+ 0x81C, 0x02740001,
+ 0x81C, 0x01760001,
+ 0x81C, 0x01780001,
+ 0x81C, 0x017A0001,
+ 0x81C, 0x017C0001,
+ 0x81C, 0x017E0001,
+ 0x8000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x81C, 0xFB000101,
+ 0x81C, 0xFA020101,
+ 0x81C, 0xF9040101,
+ 0x81C, 0xF8060101,
+ 0x81C, 0xF7080101,
+ 0x81C, 0xF60A0101,
+ 0x81C, 0xF50C0101,
+ 0x81C, 0xF40E0101,
+ 0x81C, 0xF3100101,
+ 0x81C, 0xF2120101,
+ 0x81C, 0xF1140101,
+ 0x81C, 0xF0160101,
+ 0x81C, 0xEF180101,
+ 0x81C, 0xEE1A0101,
+ 0x81C, 0xED1C0101,
+ 0x81C, 0xEC1E0101,
+ 0x81C, 0xEB200101,
+ 0x81C, 0xEA220101,
+ 0x81C, 0xE9240101,
+ 0x81C, 0xE8260101,
+ 0x81C, 0xE7280101,
+ 0x81C, 0xE62A0101,
+ 0x81C, 0xE52C0101,
+ 0x81C, 0xE42E0101,
+ 0x81C, 0xE3300101,
+ 0x81C, 0xA5320101,
+ 0x81C, 0xA4340101,
+ 0x81C, 0xA3360101,
+ 0x81C, 0x87380101,
+ 0x81C, 0x863A0101,
+ 0x81C, 0x853C0101,
+ 0x81C, 0x843E0101,
+ 0x81C, 0x69400101,
+ 0x81C, 0x68420101,
+ 0x81C, 0x67440101,
+ 0x81C, 0x66460101,
+ 0x81C, 0x49480101,
+ 0x81C, 0x484A0101,
+ 0x81C, 0x474C0101,
+ 0x81C, 0x2A4E0101,
+ 0x81C, 0x29500101,
+ 0x81C, 0x28520101,
+ 0x81C, 0x27540101,
+ 0x81C, 0x26560101,
+ 0x81C, 0x25580101,
+ 0x81C, 0x245A0101,
+ 0x81C, 0x235C0101,
+ 0x81C, 0x055E0101,
+ 0x81C, 0x04600101,
+ 0x81C, 0x03620101,
+ 0x81C, 0x02640101,
+ 0x81C, 0x01660101,
+ 0x81C, 0x01680101,
+ 0x81C, 0x016A0101,
+ 0x81C, 0x016C0101,
+ 0x81C, 0x016E0101,
+ 0x81C, 0x01700101,
+ 0x81C, 0x01720101,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x81C, 0xFB000101,
+ 0x81C, 0xFA020101,
+ 0x81C, 0xF9040101,
+ 0x81C, 0xF8060101,
+ 0x81C, 0xF7080101,
+ 0x81C, 0xF60A0101,
+ 0x81C, 0xF50C0101,
+ 0x81C, 0xF40E0101,
+ 0x81C, 0xF3100101,
+ 0x81C, 0xF2120101,
+ 0x81C, 0xF1140101,
+ 0x81C, 0xF0160101,
+ 0x81C, 0xEF180101,
+ 0x81C, 0xEE1A0101,
+ 0x81C, 0xED1C0101,
+ 0x81C, 0xEC1E0101,
+ 0x81C, 0xEB200101,
+ 0x81C, 0xEA220101,
+ 0x81C, 0xE9240101,
+ 0x81C, 0xE8260101,
+ 0x81C, 0xE7280101,
+ 0x81C, 0xE62A0101,
+ 0x81C, 0xE52C0101,
+ 0x81C, 0xE42E0101,
+ 0x81C, 0xE3300101,
+ 0x81C, 0xA5320101,
+ 0x81C, 0xA4340101,
+ 0x81C, 0xA3360101,
+ 0x81C, 0x87380101,
+ 0x81C, 0x863A0101,
+ 0x81C, 0x853C0101,
+ 0x81C, 0x843E0101,
+ 0x81C, 0x69400101,
+ 0x81C, 0x68420101,
+ 0x81C, 0x67440101,
+ 0x81C, 0x66460101,
+ 0x81C, 0x49480101,
+ 0x81C, 0x484A0101,
+ 0x81C, 0x474C0101,
+ 0x81C, 0x2A4E0101,
+ 0x81C, 0x29500101,
+ 0x81C, 0x28520101,
+ 0x81C, 0x27540101,
+ 0x81C, 0x26560101,
+ 0x81C, 0x25580101,
+ 0x81C, 0x245A0101,
+ 0x81C, 0x235C0101,
+ 0x81C, 0x055E0101,
+ 0x81C, 0x04600101,
+ 0x81C, 0x03620101,
+ 0x81C, 0x02640101,
+ 0x81C, 0x01660101,
+ 0x81C, 0x01680101,
+ 0x81C, 0x016A0101,
+ 0x81C, 0x016C0101,
+ 0x81C, 0x016E0101,
+ 0x81C, 0x01700101,
+ 0x81C, 0x01720101,
+ 0xA0000000, 0x00000000,
+ 0x81C, 0xFF000101,
+ 0x81C, 0xFF020101,
+ 0x81C, 0xFE040101,
+ 0x81C, 0xFD060101,
+ 0x81C, 0xFC080101,
+ 0x81C, 0xFD0A0101,
+ 0x81C, 0xFC0C0101,
+ 0x81C, 0xFB0E0101,
+ 0x81C, 0xFA100101,
+ 0x81C, 0xF9120101,
+ 0x81C, 0xF8140101,
+ 0x81C, 0xF7160101,
+ 0x81C, 0xF6180101,
+ 0x81C, 0xF51A0101,
+ 0x81C, 0xF41C0101,
+ 0x81C, 0xF31E0101,
+ 0x81C, 0xF2200101,
+ 0x81C, 0xF1220101,
+ 0x81C, 0xF0240101,
+ 0x81C, 0xEF260101,
+ 0x81C, 0xEE280101,
+ 0x81C, 0xED2A0101,
+ 0x81C, 0xEC2C0101,
+ 0x81C, 0xEB2E0101,
+ 0x81C, 0xEA300101,
+ 0x81C, 0xE9320101,
+ 0x81C, 0xE8340101,
+ 0x81C, 0xE7360101,
+ 0x81C, 0xE6380101,
+ 0x81C, 0xE53A0101,
+ 0x81C, 0xE43C0101,
+ 0x81C, 0xE33E0101,
+ 0x81C, 0xA5400101,
+ 0x81C, 0xA4420101,
+ 0x81C, 0xA3440101,
+ 0x81C, 0x87460101,
+ 0x81C, 0x86480101,
+ 0x81C, 0x854A0101,
+ 0x81C, 0x844C0101,
+ 0x81C, 0x694E0101,
+ 0x81C, 0x68500101,
+ 0x81C, 0x67520101,
+ 0x81C, 0x66540101,
+ 0x81C, 0x49560101,
+ 0x81C, 0x48580101,
+ 0x81C, 0x475A0101,
+ 0x81C, 0x2A5C0101,
+ 0x81C, 0x295E0101,
+ 0x81C, 0x28600101,
+ 0x81C, 0x27620101,
+ 0x81C, 0x26640101,
+ 0x81C, 0x25660101,
+ 0x81C, 0x24680101,
+ 0x81C, 0x236A0101,
+ 0x81C, 0x056C0101,
+ 0x81C, 0x046E0101,
+ 0x81C, 0x03700101,
+ 0x81C, 0x02720101,
+ 0xB0000000, 0x00000000,
+ 0x81C, 0x01740101,
+ 0x81C, 0x01760101,
+ 0x81C, 0x01780101,
+ 0x81C, 0x017A0101,
+ 0x81C, 0x017C0101,
+ 0x81C, 0x017E0101,
+ 0xC50, 0x00000022,
+ 0xC50, 0x00000020,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8821a_agc, rtw_phy_cfg_agc);
+
+static const u32 rtw8821a_bb[] = {
+ 0x800, 0x0020D090,
+ 0x804, 0x080112E0,
+ 0x808, 0x0E028211,
+ 0x80C, 0x92131111,
+ 0x810, 0x20101261,
+ 0x814, 0x020C3D10,
+ 0x818, 0x03A00385,
+ 0x820, 0x00000000,
+ 0x824, 0x00030FE0,
+ 0x828, 0x00000000,
+ 0x82C, 0x002081DD,
+ 0x830, 0x2AAAEEC8,
+ 0x834, 0x0037A706,
+ 0x838, 0x06489B44,
+ 0x83C, 0x0000095B,
+ 0x840, 0xC0000001,
+ 0x844, 0x40003CDE,
+ 0x848, 0x62103F8B,
+ 0x84C, 0x6CFDFFB8,
+ 0x850, 0x28874706,
+ 0x854, 0x0001520C,
+ 0x858, 0x8060E000,
+ 0x85C, 0x74210168,
+ 0x860, 0x6929C321,
+ 0x864, 0x79727432,
+ 0x868, 0x8CA7A314,
+ 0x86C, 0x888C2878,
+ 0x870, 0x08888888,
+ 0x874, 0x31612C2E,
+ 0x878, 0x00000152,
+ 0x87C, 0x000FD000,
+ 0x8A0, 0x00000013,
+ 0x8A4, 0x7F7F7F7F,
+ 0x8A8, 0xA2000338,
+ 0x8AC, 0x0FF0FA0A,
+ 0x8B4, 0x000FC080,
+ 0x8B8, 0x6C10D7FF,
+ 0x8BC, 0x0CA52090,
+ 0x8C0, 0x1BF00020,
+ 0x8C4, 0x00000000,
+ 0x8C8, 0x00013169,
+ 0x8CC, 0x08248492,
+ 0x8D4, 0x940008A0,
+ 0x8D8, 0x290B5612,
+ 0x8F8, 0x400002C0,
+ 0x8FC, 0x00000000,
+ 0x900, 0x00000700,
+ 0x90C, 0x00000000,
+ 0x910, 0x0000FC00,
+ 0x914, 0x00000404,
+ 0x918, 0x1C1028C0,
+ 0x91C, 0x64B11A1C,
+ 0x920, 0xE0767233,
+ 0x924, 0x055AA500,
+ 0x928, 0x00000004,
+ 0x92C, 0xFFFE0000,
+ 0x930, 0xFFFFFFFE,
+ 0x934, 0x001FFFFF,
+ 0x960, 0x00000000,
+ 0x964, 0x00000000,
+ 0x968, 0x00000000,
+ 0x96C, 0x00000000,
+ 0x970, 0x801FFFFF,
+ 0x974, 0x000003FF,
+ 0x978, 0x00000000,
+ 0x97C, 0x00000000,
+ 0x980, 0x00000000,
+ 0x984, 0x00000000,
+ 0x988, 0x00000000,
+ 0x990, 0x27100000,
+ 0x994, 0xFFFF0100,
+ 0x998, 0xFFFFFF5C,
+ 0x99C, 0xFFFFFFFF,
+ 0x9A0, 0x000000FF,
+ 0x9A4, 0x00480080,
+ 0x9A8, 0x00000000,
+ 0x9AC, 0x00000000,
+ 0x9B0, 0x81081008,
+ 0x9B4, 0x01081008,
+ 0x9B8, 0x01081008,
+ 0x9BC, 0x01081008,
+ 0x9D0, 0x00000000,
+ 0x9D4, 0x00000000,
+ 0x9D8, 0x00000000,
+ 0x9DC, 0x00000000,
+ 0x9E0, 0x00005D00,
+ 0x9E4, 0x00000003,
+ 0x9E8, 0x00000001,
+ 0xA00, 0x00D047C8,
+ 0xA04, 0x01FF800C,
+ 0xA08, 0x8C8A8300,
+ 0xA0C, 0x2E68000F,
+ 0xA10, 0x9500BB78,
+ 0xA14, 0x11144028,
+ 0xA18, 0x00881117,
+ 0xA1C, 0x89140F00,
+ 0xA20, 0x1A1B0000,
+ 0xA24, 0x090E1317,
+ 0xA28, 0x00000204,
+ 0xA2C, 0x00900000,
+ 0xA70, 0x101FFF00,
+ 0xA74, 0x00000008,
+ 0xA78, 0x00000900,
+ 0xA7C, 0x225B0606,
+ 0xA80, 0x21805490,
+ 0xA84, 0x001F0000,
+ 0XB00, 0x03100040,
+ 0XB04, 0x0000B000,
+ 0XB08, 0xAE0201EB,
+ 0XB0C, 0x01003207,
+ 0XB10, 0x00009807,
+ 0XB14, 0x01000000,
+ 0XB18, 0x00000002,
+ 0XB1C, 0x00000002,
+ 0XB20, 0x0000001F,
+ 0XB24, 0x03020100,
+ 0XB28, 0x07060504,
+ 0XB2C, 0x0B0A0908,
+ 0XB30, 0x0F0E0D0C,
+ 0XB34, 0x13121110,
+ 0XB38, 0x17161514,
+ 0XB3C, 0x0000003A,
+ 0XB40, 0x00000000,
+ 0XB44, 0x00000000,
+ 0XB48, 0x13000032,
+ 0XB4C, 0x48080000,
+ 0XB50, 0x00000000,
+ 0XB54, 0x00000000,
+ 0XB58, 0x00000000,
+ 0XB5C, 0x00000000,
+ 0xC00, 0x00000007,
+ 0xC04, 0x00042020,
+ 0xC08, 0x80410231,
+ 0xC0C, 0x00000000,
+ 0xC10, 0x00000100,
+ 0xC14, 0x01000000,
+ 0xC1C, 0x40000003,
+ 0xC20, 0x2C2C2C2C,
+ 0xC24, 0x30303030,
+ 0xC28, 0x30303030,
+ 0xC2C, 0x2C2C2C2C,
+ 0xC30, 0x2C2C2C2C,
+ 0xC34, 0x2C2C2C2C,
+ 0xC38, 0x2C2C2C2C,
+ 0xC3C, 0x2A2A2A2A,
+ 0xC40, 0x2A2A2A2A,
+ 0xC44, 0x2A2A2A2A,
+ 0xC48, 0x2A2A2A2A,
+ 0xC4C, 0x2A2A2A2A,
+ 0xC50, 0x00000020,
+ 0xC54, 0x001C1208,
+ 0xC58, 0x30000C1C,
+ 0xC5C, 0x00000058,
+ 0xC60, 0x34344443,
+ 0xC64, 0x07003333,
+ 0xC68, 0x19791979,
+ 0xC6C, 0x19791979,
+ 0xC70, 0x19791979,
+ 0xC74, 0x19791979,
+ 0xC78, 0x19791979,
+ 0xC7C, 0x19791979,
+ 0xC80, 0x19791979,
+ 0xC84, 0x19791979,
+ 0xC94, 0x0100005C,
+ 0xC98, 0x00000000,
+ 0xC9C, 0x00000000,
+ 0xCA0, 0x00000029,
+ 0xCA4, 0x08040201,
+ 0xCA8, 0x80402010,
+ 0xCB0, 0x77775747,
+ 0xCB4, 0x10000077,
+ 0xCB8, 0x00508240,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8821a_bb, rtw_phy_cfg_bb);
+
+static const struct rtw_phy_pg_cfg_pair rtw8821a_bb_pg[] = {
+ { 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, },
+ { 0, 0, 0, 0x00000c24, 0xffffffff, 0x36363838, },
+ { 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, },
+ { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363838, },
+ { 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, },
+ { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, },
+ { 0, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
+ { 0, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, },
+ { 1, 0, 0, 0x00000c24, 0xffffffff, 0x34343636, },
+ { 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, },
+ { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343636, },
+ { 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, },
+ { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, },
+ { 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
+ { 1, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, },
+};
+
+RTW_DECL_TABLE_BB_PG(rtw8821a_bb_pg);
+
+static const u32 rtw8821a_rf_a[] = {
+ 0x018, 0x0001712A,
+ 0x056, 0x00051CF2,
+ 0x066, 0x00040000,
+ 0x000, 0x00010000,
+ 0x01E, 0x00080000,
+ 0x082, 0x00000830,
+ 0x083, 0x00021800,
+ 0x084, 0x00028000,
+ 0x085, 0x00048000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x086, 0x0009483A,
+ 0xA0000000, 0x00000000,
+ 0x086, 0x00094838,
+ 0xB0000000, 0x00000000,
+ 0x087, 0x00044980,
+ 0x088, 0x00048000,
+ 0x089, 0x0000D480,
+ 0x08A, 0x00042240,
+ 0x08B, 0x000F0380,
+ 0x08C, 0x00090000,
+ 0x08D, 0x00022852,
+ 0x08E, 0x00065540,
+ 0x08F, 0x00088001,
+ 0x0EF, 0x00020000,
+ 0x03E, 0x00000380,
+ 0x03F, 0x00090018,
+ 0x03E, 0x00020380,
+ 0x03F, 0x000A0018,
+ 0x03E, 0x00040308,
+ 0x03F, 0x000A0018,
+ 0x03E, 0x00060018,
+ 0x03F, 0x000A0018,
+ 0x0EF, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x089, 0x00000080,
+ 0x08B, 0x00080180,
+ 0x0EF, 0x00001000,
+ 0x03A, 0x00000244,
+ 0x03B, 0x00038027,
+ 0x03C, 0x00082000,
+ 0x03A, 0x00000244,
+ 0x03B, 0x00030113,
+ 0x03C, 0x00082000,
+ 0x03A, 0x0000014C,
+ 0x03B, 0x00028027,
+ 0x03C, 0x00082000,
+ 0x03A, 0x000000CC,
+ 0x03B, 0x00027027,
+ 0x03C, 0x00042000,
+ 0x03A, 0x0000014C,
+ 0x03B, 0x0001F913,
+ 0x03C, 0x00042000,
+ 0x03A, 0x0000010C,
+ 0x03B, 0x00017F10,
+ 0x03C, 0x00012000,
+ 0x03A, 0x000000D0,
+ 0x03B, 0x00008027,
+ 0x03C, 0x000CA000,
+ 0x03A, 0x00000244,
+ 0x03B, 0x00078027,
+ 0x03C, 0x00082000,
+ 0x03A, 0x00000244,
+ 0x03B, 0x00070113,
+ 0x03C, 0x00082000,
+ 0x03A, 0x0000014C,
+ 0x03B, 0x00068027,
+ 0x03C, 0x00082000,
+ 0x03A, 0x000000CC,
+ 0x03B, 0x00067027,
+ 0x03C, 0x00042000,
+ 0x03A, 0x0000014C,
+ 0x03B, 0x0005F913,
+ 0x03C, 0x00042000,
+ 0x03A, 0x0000010C,
+ 0x03B, 0x00057F10,
+ 0x03C, 0x00012000,
+ 0x03A, 0x000000D0,
+ 0x03B, 0x00048027,
+ 0x03C, 0x000CA000,
+ 0x03A, 0x00000244,
+ 0x03B, 0x000B8027,
+ 0x03C, 0x00082000,
+ 0x03A, 0x00000244,
+ 0x03B, 0x000B0113,
+ 0x03C, 0x00082000,
+ 0x03A, 0x0000014C,
+ 0x03B, 0x000A8027,
+ 0x03C, 0x00082000,
+ 0x03A, 0x000000CC,
+ 0x03B, 0x000A7027,
+ 0x03C, 0x00042000,
+ 0x03A, 0x0000014C,
+ 0x03B, 0x0009F913,
+ 0x03C, 0x00042000,
+ 0x03A, 0x0000010C,
+ 0x03B, 0x00097F10,
+ 0x03C, 0x00012000,
+ 0x03A, 0x000000D0,
+ 0x03B, 0x00088027,
+ 0x03C, 0x000CA000,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x00001100,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004ADF3,
+ 0x034, 0x00049DF0,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004ADF3,
+ 0x034, 0x00049DF0,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004ADF5,
+ 0x034, 0x00049DF2,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004A0F3,
+ 0x034, 0x000490B1,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004A0F3,
+ 0x034, 0x000490B1,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004ADF5,
+ 0x034, 0x00049DF2,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0004ADF3,
+ 0x034, 0x00049DF0,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0004ADF7,
+ 0x034, 0x00049DF3,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00048DED,
+ 0x034, 0x00047DEA,
+ 0x034, 0x00046DE7,
+ 0x034, 0x00045CE9,
+ 0x034, 0x00044CE6,
+ 0x034, 0x000438C6,
+ 0x034, 0x00042886,
+ 0x034, 0x00041486,
+ 0x034, 0x00040447,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00048DED,
+ 0x034, 0x00047DEA,
+ 0x034, 0x00046DE7,
+ 0x034, 0x00045CE9,
+ 0x034, 0x00044CE6,
+ 0x034, 0x000438C6,
+ 0x034, 0x00042886,
+ 0x034, 0x00041486,
+ 0x034, 0x00040447,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x000480AE,
+ 0x034, 0x000470AB,
+ 0x034, 0x0004608B,
+ 0x034, 0x00045069,
+ 0x034, 0x00044048,
+ 0x034, 0x00043045,
+ 0x034, 0x00042026,
+ 0x034, 0x00041023,
+ 0x034, 0x00040002,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x000480AE,
+ 0x034, 0x000470AB,
+ 0x034, 0x0004608B,
+ 0x034, 0x00045069,
+ 0x034, 0x00044048,
+ 0x034, 0x00043045,
+ 0x034, 0x00042026,
+ 0x034, 0x00041023,
+ 0x034, 0x00040002,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00048DED,
+ 0x034, 0x00047DEA,
+ 0x034, 0x00046DE7,
+ 0x034, 0x00045CE9,
+ 0x034, 0x00044CE6,
+ 0x034, 0x000438C6,
+ 0x034, 0x00042886,
+ 0x034, 0x00041486,
+ 0x034, 0x00040447,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x00048DEF,
+ 0x034, 0x00047DEC,
+ 0x034, 0x00046DE9,
+ 0x034, 0x00045CCB,
+ 0x034, 0x0004488D,
+ 0x034, 0x0004348D,
+ 0x034, 0x0004248A,
+ 0x034, 0x0004108D,
+ 0x034, 0x0004008A,
+ 0xB0000000, 0x00000000,
+ 0x80000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002ADF4,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002A0F3,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002A0F3,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0002ADF4,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0002ADF7,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00029DF4,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00029DF4,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00029DF1,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x000290F0,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x000290F0,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00029DF1,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00029DF4,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x00029DF2,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00028DF1,
+ 0x034, 0x00027DEE,
+ 0x034, 0x00026DEB,
+ 0x034, 0x00025CEC,
+ 0x034, 0x00024CE9,
+ 0x034, 0x000238CA,
+ 0x034, 0x00022889,
+ 0x034, 0x00021489,
+ 0x034, 0x0002044A,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00028DF1,
+ 0x034, 0x00027DEE,
+ 0x034, 0x00026DEB,
+ 0x034, 0x00025CEC,
+ 0x034, 0x00024CE9,
+ 0x034, 0x000238CA,
+ 0x034, 0x00022889,
+ 0x034, 0x00021489,
+ 0x034, 0x0002044A,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x000280AF,
+ 0x034, 0x000270AC,
+ 0x034, 0x0002608B,
+ 0x034, 0x00025069,
+ 0x034, 0x00024048,
+ 0x034, 0x00023045,
+ 0x034, 0x00022026,
+ 0x034, 0x00021023,
+ 0x034, 0x00020002,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x000280AF,
+ 0x034, 0x000270AC,
+ 0x034, 0x0002608B,
+ 0x034, 0x00025069,
+ 0x034, 0x00024048,
+ 0x034, 0x00023045,
+ 0x034, 0x00022026,
+ 0x034, 0x00021023,
+ 0x034, 0x00020002,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00028DF1,
+ 0x034, 0x00027DEE,
+ 0x034, 0x00026DEB,
+ 0x034, 0x00025CEC,
+ 0x034, 0x00024CE9,
+ 0x034, 0x000238CA,
+ 0x034, 0x00022889,
+ 0x034, 0x00021489,
+ 0x034, 0x0002044A,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x00028DEE,
+ 0x034, 0x00027DEB,
+ 0x034, 0x00026CCD,
+ 0x034, 0x00025CCA,
+ 0x034, 0x0002488C,
+ 0x034, 0x0002384C,
+ 0x034, 0x00022849,
+ 0x034, 0x00021449,
+ 0x034, 0x0002004D,
+ 0xB0000000, 0x00000000,
+ 0x8000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A0D7,
+ 0x034, 0x000090D3,
+ 0x034, 0x000080B1,
+ 0x034, 0x000070AE,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000A0D7,
+ 0x034, 0x000090D3,
+ 0x034, 0x000080B1,
+ 0x034, 0x000070AE,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x0000ADF7,
+ 0x034, 0x00009DF4,
+ 0x034, 0x00008DF1,
+ 0x034, 0x00007DEE,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00006DEB,
+ 0x034, 0x00005CEC,
+ 0x034, 0x00004CE9,
+ 0x034, 0x000038CA,
+ 0x034, 0x00002889,
+ 0x034, 0x00001489,
+ 0x034, 0x0000044A,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00006DEB,
+ 0x034, 0x00005CEC,
+ 0x034, 0x00004CE9,
+ 0x034, 0x000038CA,
+ 0x034, 0x00002889,
+ 0x034, 0x00001489,
+ 0x034, 0x0000044A,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000608D,
+ 0x034, 0x0000506B,
+ 0x034, 0x0000404A,
+ 0x034, 0x00003047,
+ 0x034, 0x00002044,
+ 0x034, 0x00001025,
+ 0x034, 0x00000004,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x0000608D,
+ 0x034, 0x0000506B,
+ 0x034, 0x0000404A,
+ 0x034, 0x00003047,
+ 0x034, 0x00002044,
+ 0x034, 0x00001025,
+ 0x034, 0x00000004,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x034, 0x00006DEB,
+ 0x034, 0x00005CEC,
+ 0x034, 0x00004CE9,
+ 0x034, 0x000038CA,
+ 0x034, 0x00002889,
+ 0x034, 0x00001489,
+ 0x034, 0x0000044A,
+ 0xA0000000, 0x00000000,
+ 0x034, 0x00006DCD,
+ 0x034, 0x00005CCD,
+ 0x034, 0x00004CCA,
+ 0x034, 0x0000388C,
+ 0x034, 0x00002888,
+ 0x034, 0x00001488,
+ 0x034, 0x00000486,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000040,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x035, 0x00000187,
+ 0x035, 0x00008187,
+ 0x035, 0x00010187,
+ 0x035, 0x00020188,
+ 0x035, 0x00028188,
+ 0x035, 0x00030188,
+ 0x035, 0x00040188,
+ 0x035, 0x00048188,
+ 0x035, 0x00050188,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x035, 0x00000187,
+ 0x035, 0x00008187,
+ 0x035, 0x00010187,
+ 0x035, 0x00020188,
+ 0x035, 0x00028188,
+ 0x035, 0x00030188,
+ 0x035, 0x00040188,
+ 0x035, 0x00048188,
+ 0x035, 0x00050188,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x035, 0x00000128,
+ 0x035, 0x00008128,
+ 0x035, 0x00010128,
+ 0x035, 0x000201C8,
+ 0x035, 0x000281C8,
+ 0x035, 0x000301C8,
+ 0x035, 0x000401C8,
+ 0x035, 0x000481C8,
+ 0x035, 0x000501C8,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x035, 0x00000145,
+ 0x035, 0x00008145,
+ 0x035, 0x00010145,
+ 0x035, 0x00020196,
+ 0x035, 0x00028196,
+ 0x035, 0x00030196,
+ 0x035, 0x000401C7,
+ 0x035, 0x000481C7,
+ 0x035, 0x000501C7,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x035, 0x00000128,
+ 0x035, 0x00008128,
+ 0x035, 0x00010128,
+ 0x035, 0x000201C8,
+ 0x035, 0x000281C8,
+ 0x035, 0x000301C8,
+ 0x035, 0x000401C8,
+ 0x035, 0x000481C8,
+ 0x035, 0x000501C8,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x035, 0x00000187,
+ 0x035, 0x00008187,
+ 0x035, 0x00010187,
+ 0x035, 0x00020188,
+ 0x035, 0x00028188,
+ 0x035, 0x00030188,
+ 0x035, 0x00040188,
+ 0x035, 0x00048188,
+ 0x035, 0x00050188,
+ 0xA0000000, 0x00000000,
+ 0x035, 0x00000145,
+ 0x035, 0x00008145,
+ 0x035, 0x00010145,
+ 0x035, 0x00020196,
+ 0x035, 0x00028196,
+ 0x035, 0x00030196,
+ 0x035, 0x000401C7,
+ 0x035, 0x000481C7,
+ 0x035, 0x000501C7,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000010,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x036, 0x00085733,
+ 0x036, 0x0008D733,
+ 0x036, 0x00095733,
+ 0x036, 0x0009D733,
+ 0x036, 0x000A64B4,
+ 0x036, 0x000AE4B4,
+ 0x036, 0x000B64B4,
+ 0x036, 0x000BE4B4,
+ 0x036, 0x000C64B4,
+ 0x036, 0x000CE4B4,
+ 0x036, 0x000D64B4,
+ 0x036, 0x000DE4B4,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x036, 0x00085733,
+ 0x036, 0x0008D733,
+ 0x036, 0x00095733,
+ 0x036, 0x0009D733,
+ 0x036, 0x000A64B4,
+ 0x036, 0x000AE4B4,
+ 0x036, 0x000B64B4,
+ 0x036, 0x000BE4B4,
+ 0x036, 0x000C64B4,
+ 0x036, 0x000CE4B4,
+ 0x036, 0x000D64B4,
+ 0x036, 0x000DE4B4,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x036, 0x000063B5,
+ 0x036, 0x0000E3B5,
+ 0x036, 0x000163B5,
+ 0x036, 0x0001E3B5,
+ 0x036, 0x000263B5,
+ 0x036, 0x0002E3B5,
+ 0x036, 0x000363B5,
+ 0x036, 0x0003E3B5,
+ 0x036, 0x000463B5,
+ 0x036, 0x0004E3B5,
+ 0x036, 0x000563B5,
+ 0x036, 0x0005E3B5,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x036, 0x000056B3,
+ 0x036, 0x0000D6B3,
+ 0x036, 0x000156B3,
+ 0x036, 0x0001D6B3,
+ 0x036, 0x00026634,
+ 0x036, 0x0002E634,
+ 0x036, 0x00036634,
+ 0x036, 0x0003E634,
+ 0x036, 0x000467B4,
+ 0x036, 0x0004E7B4,
+ 0x036, 0x000567B4,
+ 0x036, 0x0005E7B4,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x036, 0x000063B5,
+ 0x036, 0x0000E3B5,
+ 0x036, 0x000163B5,
+ 0x036, 0x0001E3B5,
+ 0x036, 0x000263B5,
+ 0x036, 0x0002E3B5,
+ 0x036, 0x000363B5,
+ 0x036, 0x0003E3B5,
+ 0x036, 0x000463B5,
+ 0x036, 0x0004E3B5,
+ 0x036, 0x000563B5,
+ 0x036, 0x0005E3B5,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x036, 0x00085733,
+ 0x036, 0x0008D733,
+ 0x036, 0x00095733,
+ 0x036, 0x0009D733,
+ 0x036, 0x000A64B4,
+ 0x036, 0x000AE4B4,
+ 0x036, 0x000B64B4,
+ 0x036, 0x000BE4B4,
+ 0x036, 0x000C64B4,
+ 0x036, 0x000CE4B4,
+ 0x036, 0x000D64B4,
+ 0x036, 0x000DE4B4,
+ 0xA0000000, 0x00000000,
+ 0x036, 0x000056B3,
+ 0x036, 0x0000D6B3,
+ 0x036, 0x000156B3,
+ 0x036, 0x0001D6B3,
+ 0x036, 0x00026634,
+ 0x036, 0x0002E634,
+ 0x036, 0x00036634,
+ 0x036, 0x0003E634,
+ 0x036, 0x000467B4,
+ 0x036, 0x0004E7B4,
+ 0x036, 0x000567B4,
+ 0x036, 0x0005E7B4,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x00000008,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000001C8,
+ 0x03C, 0x00000492,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000001C8,
+ 0x03C, 0x00000492,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000001B6,
+ 0x03C, 0x00000492,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x0000022A,
+ 0x03C, 0x00000594,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000001B6,
+ 0x03C, 0x00000492,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x000001C8,
+ 0x03C, 0x00000492,
+ 0xA0000000, 0x00000000,
+ 0x03C, 0x0000022A,
+ 0x03C, 0x00000594,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x00000800,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x00000800,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x00000800,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x00000820,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x00000820,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x00000800,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x03C, 0x00000800,
+ 0xA0000000, 0x00000000,
+ 0x03C, 0x00000900,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x018, 0x0001712A,
+ 0x0EF, 0x00000002,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x008, 0x0004E400,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x008, 0x0004E400,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x008, 0x00002000,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x008, 0x00002000,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x008, 0x00002000,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x008, 0x00002000,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x008, 0x0004E400,
+ 0xA0000000, 0x00000000,
+ 0x008, 0x00002000,
+ 0xB0000000, 0x00000000,
+ 0x0EF, 0x00000000,
+ 0x0DF, 0x000000C0,
+ 0x01F, 0x00000064,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x058, 0x000A7284,
+ 0x059, 0x000600EC,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x058, 0x000A7284,
+ 0x059, 0x000600EC,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x058, 0x00081184,
+ 0x059, 0x0006016C,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x058, 0x00081184,
+ 0x059, 0x0006016C,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x058, 0x00081184,
+ 0x059, 0x0006016C,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x058, 0x000A7284,
+ 0x059, 0x000600EC,
+ 0xA0000000, 0x00000000,
+ 0x058, 0x00081184,
+ 0x059, 0x0006016C,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000E8D73,
+ 0x062, 0x00093FC5,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000E8D73,
+ 0x062, 0x00093FC5,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000EFD83,
+ 0x062, 0x00093FCC,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000EAD53,
+ 0x062, 0x00093BC4,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000EFD83,
+ 0x062, 0x00093FCC,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x061, 0x000E8D73,
+ 0x062, 0x00093FC5,
+ 0xA0000000, 0x00000000,
+ 0x061, 0x000EAD53,
+ 0x062, 0x00093BC4,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x063, 0x000110E9,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x063, 0x000110E9,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x063, 0x000110EB,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x063, 0x000110E9,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x063, 0x000110E9,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x063, 0x000110EB,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x063, 0x000110E9,
+ 0xA0000000, 0x00000000,
+ 0x063, 0x000714E9,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x064, 0x0001C27C,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x064, 0x0001C27C,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x064, 0x0001C27C,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x064, 0x0001C67C,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x064, 0x0001C27C,
+ 0x90000410, 0x00000000, 0x40000000, 0x00000000,
+ 0x064, 0x0001C27C,
+ 0xA0000000, 0x00000000,
+ 0x064, 0x0001C67C,
+ 0xB0000000, 0x00000000,
+ 0x80000111, 0x00000000, 0x40000000, 0x00000000,
+ 0x065, 0x00091016,
+ 0x90000110, 0x00000000, 0x40000000, 0x00000000,
+ 0x065, 0x00091016,
+ 0x90000210, 0x00000000, 0x40000000, 0x00000000,
+ 0x065, 0x00093016,
+ 0x9000020c, 0x00000000, 0x40000000, 0x00000000,
+ 0x065, 0x00093015,
+ 0x9000040c, 0x00000000, 0x40000000, 0x00000000,
+ 0x065, 0x00093015,
+ 0x90000200, 0x00000000, 0x40000000, 0x00000000,
+ 0x065, 0x00093016,
+ 0xA0000000, 0x00000000,
+ 0x065, 0x00091016,
+ 0xB0000000, 0x00000000,
+ 0x018, 0x00000006,
+ 0x0EF, 0x00002000,
+ 0x03B, 0x0003824B,
+ 0x03B, 0x0003024B,
+ 0x03B, 0x0002844B,
+ 0x03B, 0x00020F4B,
+ 0x03B, 0x00018F4B,
+ 0x03B, 0x000104B2,
+ 0x03B, 0x00008049,
+ 0x03B, 0x00000148,
+ 0x03B, 0x0007824B,
+ 0x03B, 0x0007024B,
+ 0x03B, 0x0006824B,
+ 0x03B, 0x00060F4B,
+ 0x03B, 0x00058F4B,
+ 0x03B, 0x000504B2,
+ 0x03B, 0x00048049,
+ 0x03B, 0x00040148,
+ 0x0EF, 0x00000000,
+ 0x0EF, 0x00000100,
+ 0x034, 0x0000ADF3,
+ 0x034, 0x00009DF0,
+ 0x034, 0x00008D70,
+ 0x034, 0x00007D6D,
+ 0x034, 0x00006CEE,
+ 0x034, 0x00005CCC,
+ 0x034, 0x000044EC,
+ 0x034, 0x000034AC,
+ 0x034, 0x0000246D,
+ 0x034, 0x0000106F,
+ 0x034, 0x0000006C,
+ 0x0EF, 0x00000000,
+ 0x0ED, 0x00000010,
+ 0x044, 0x0000ADF2,
+ 0x044, 0x00009DEF,
+ 0x044, 0x00008DEC,
+ 0x044, 0x00007DE9,
+ 0x044, 0x00006CEC,
+ 0x044, 0x00005CE9,
+ 0x044, 0x000044EC,
+ 0x044, 0x000034E9,
+ 0x044, 0x0000246C,
+ 0x044, 0x00001469,
+ 0x044, 0x0000006C,
+ 0x0ED, 0x00000000,
+ 0x0ED, 0x00000001,
+ 0x040, 0x00038DA7,
+ 0x040, 0x000300C2,
+ 0x040, 0x000288E2,
+ 0x040, 0x000200B8,
+ 0x040, 0x000188A5,
+ 0x040, 0x00010FBC,
+ 0x040, 0x00008F71,
+ 0x040, 0x00000240,
+ 0x0ED, 0x00000000,
+ 0x0EF, 0x000020A2,
+ 0x0DF, 0x00000080,
+ 0x035, 0x00000120,
+ 0x035, 0x00008120,
+ 0x035, 0x00010120,
+ 0x036, 0x00000085,
+ 0x036, 0x00008085,
+ 0x036, 0x00010085,
+ 0x036, 0x00018085,
+ 0x0EF, 0x00000000,
+ 0x051, 0x00000C31,
+ 0x052, 0x00000622,
+ 0x053, 0x000FC70B,
+ 0x054, 0x0000017E,
+ 0x056, 0x00051DF3,
+ 0x051, 0x00000C01,
+ 0x052, 0x000006D6,
+ 0x053, 0x000FC649,
+ 0x070, 0x00049661,
+ 0x071, 0x0007843E,
+ 0x072, 0x00000382,
+ 0x074, 0x00051400,
+ 0x035, 0x00000160,
+ 0x035, 0x00008160,
+ 0x035, 0x00010160,
+ 0x036, 0x00000124,
+ 0x036, 0x00008124,
+ 0x036, 0x00010124,
+ 0x036, 0x00018124,
+ 0x0ED, 0x0000000C,
+ 0x045, 0x00000140,
+ 0x045, 0x00008140,
+ 0x045, 0x00010140,
+ 0x046, 0x00000124,
+ 0x046, 0x00008124,
+ 0x046, 0x00010124,
+ 0x046, 0x00018124,
+ 0x0DF, 0x00000088,
+ 0x0B3, 0x000F0E18,
+ 0x0B4, 0x0001214C,
+ 0x0B7, 0x0003000C,
+ 0x01C, 0x000539D2,
+ 0x0C4, 0x000AFE00,
+ 0x018, 0x0001F12A,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0x018, 0x0001712A,
+};
+
+RTW_DECL_TABLE_RF_RADIO(rtw8821a_rf_a, A);
+
+static const struct rtw_txpwr_lmt_cfg_pair rtw8821a_txpwr_lmt[] = {
+ { 0, 0, 0, 0, 1, 32, },
+ { 2, 0, 0, 0, 1, 28, },
+ { 1, 0, 0, 0, 1, 32, },
+ { 0, 0, 0, 0, 2, 32, },
+ { 2, 0, 0, 0, 2, 28, },
+ { 1, 0, 0, 0, 2, 32, },
+ { 0, 0, 0, 0, 3, 36, },
+ { 2, 0, 0, 0, 3, 28, },
+ { 1, 0, 0, 0, 3, 32, },
+ { 0, 0, 0, 0, 4, 36, },
+ { 2, 0, 0, 0, 4, 28, },
+ { 1, 0, 0, 0, 4, 32, },
+ { 0, 0, 0, 0, 5, 36, },
+ { 2, 0, 0, 0, 5, 28, },
+ { 1, 0, 0, 0, 5, 32, },
+ { 0, 0, 0, 0, 6, 36, },
+ { 2, 0, 0, 0, 6, 28, },
+ { 1, 0, 0, 0, 6, 32, },
+ { 0, 0, 0, 0, 7, 36, },
+ { 2, 0, 0, 0, 7, 28, },
+ { 1, 0, 0, 0, 7, 32, },
+ { 0, 0, 0, 0, 8, 36, },
+ { 2, 0, 0, 0, 8, 28, },
+ { 1, 0, 0, 0, 8, 32, },
+ { 0, 0, 0, 0, 9, 32, },
+ { 2, 0, 0, 0, 9, 28, },
+ { 1, 0, 0, 0, 9, 32, },
+ { 0, 0, 0, 0, 10, 32, },
+ { 2, 0, 0, 0, 10, 28, },
+ { 1, 0, 0, 0, 10, 32, },
+ { 0, 0, 0, 0, 11, 32, },
+ { 2, 0, 0, 0, 11, 28, },
+ { 1, 0, 0, 0, 11, 32, },
+ { 0, 0, 0, 0, 12, 28, },
+ { 2, 0, 0, 0, 12, 28, },
+ { 1, 0, 0, 0, 12, 32, },
+ { 0, 0, 0, 0, 13, 26, },
+ { 2, 0, 0, 0, 13, 28, },
+ { 1, 0, 0, 0, 13, 32, },
+ { 0, 0, 0, 0, 14, 63, },
+ { 2, 0, 0, 0, 14, 63, },
+ { 1, 0, 0, 0, 14, 32, },
+ { 0, 0, 0, 1, 1, 30, },
+ { 2, 0, 0, 1, 1, 30, },
+ { 1, 0, 0, 1, 1, 32, },
+ { 0, 0, 0, 1, 2, 30, },
+ { 2, 0, 0, 1, 2, 32, },
+ { 1, 0, 0, 1, 2, 32, },
+ { 0, 0, 0, 1, 3, 32, },
+ { 2, 0, 0, 1, 3, 32, },
+ { 1, 0, 0, 1, 3, 32, },
+ { 0, 0, 0, 1, 4, 32, },
+ { 2, 0, 0, 1, 4, 32, },
+ { 1, 0, 0, 1, 4, 32, },
+ { 0, 0, 0, 1, 5, 32, },
+ { 2, 0, 0, 1, 5, 32, },
+ { 1, 0, 0, 1, 5, 32, },
+ { 0, 0, 0, 1, 6, 32, },
+ { 2, 0, 0, 1, 6, 32, },
+ { 1, 0, 0, 1, 6, 32, },
+ { 0, 0, 0, 1, 7, 32, },
+ { 2, 0, 0, 1, 7, 32, },
+ { 1, 0, 0, 1, 7, 32, },
+ { 0, 0, 0, 1, 8, 32, },
+ { 2, 0, 0, 1, 8, 32, },
+ { 1, 0, 0, 1, 8, 32, },
+ { 0, 0, 0, 1, 9, 30, },
+ { 2, 0, 0, 1, 9, 32, },
+ { 1, 0, 0, 1, 9, 32, },
+ { 0, 0, 0, 1, 10, 30, },
+ { 2, 0, 0, 1, 10, 32, },
+ { 1, 0, 0, 1, 10, 32, },
+ { 0, 0, 0, 1, 11, 30, },
+ { 2, 0, 0, 1, 11, 32, },
+ { 1, 0, 0, 1, 11, 32, },
+ { 0, 0, 0, 1, 12, 26, },
+ { 2, 0, 0, 1, 12, 32, },
+ { 1, 0, 0, 1, 12, 32, },
+ { 0, 0, 0, 1, 13, 24, },
+ { 2, 0, 0, 1, 13, 30, },
+ { 1, 0, 0, 1, 13, 32, },
+ { 0, 0, 0, 1, 14, 63, },
+ { 2, 0, 0, 1, 14, 63, },
+ { 1, 0, 0, 1, 14, 63, },
+ { 0, 0, 0, 2, 1, 26, },
+ { 2, 0, 0, 2, 1, 26, },
+ { 1, 0, 0, 2, 1, 32, },
+ { 0, 0, 0, 2, 2, 26, },
+ { 2, 0, 0, 2, 2, 32, },
+ { 1, 0, 0, 2, 2, 32, },
+ { 0, 0, 0, 2, 3, 32, },
+ { 2, 0, 0, 2, 3, 32, },
+ { 1, 0, 0, 2, 3, 32, },
+ { 0, 0, 0, 2, 4, 32, },
+ { 2, 0, 0, 2, 4, 32, },
+ { 1, 0, 0, 2, 4, 32, },
+ { 0, 0, 0, 2, 5, 32, },
+ { 2, 0, 0, 2, 5, 32, },
+ { 1, 0, 0, 2, 5, 32, },
+ { 0, 0, 0, 2, 6, 32, },
+ { 2, 0, 0, 2, 6, 32, },
+ { 1, 0, 0, 2, 6, 32, },
+ { 0, 0, 0, 2, 7, 32, },
+ { 2, 0, 0, 2, 7, 32, },
+ { 1, 0, 0, 2, 7, 32, },
+ { 0, 0, 0, 2, 8, 32, },
+ { 2, 0, 0, 2, 8, 32, },
+ { 1, 0, 0, 2, 8, 32, },
+ { 0, 0, 0, 2, 9, 26, },
+ { 2, 0, 0, 2, 9, 32, },
+ { 1, 0, 0, 2, 9, 32, },
+ { 0, 0, 0, 2, 10, 26, },
+ { 2, 0, 0, 2, 10, 32, },
+ { 1, 0, 0, 2, 10, 32, },
+ { 0, 0, 0, 2, 11, 26, },
+ { 2, 0, 0, 2, 11, 32, },
+ { 1, 0, 0, 2, 11, 32, },
+ { 0, 0, 0, 2, 12, 26, },
+ { 2, 0, 0, 2, 12, 32, },
+ { 1, 0, 0, 2, 12, 32, },
+ { 0, 0, 0, 2, 13, 24, },
+ { 2, 0, 0, 2, 13, 26, },
+ { 1, 0, 0, 2, 13, 32, },
+ { 0, 0, 0, 2, 14, 63, },
+ { 2, 0, 0, 2, 14, 63, },
+ { 1, 0, 0, 2, 14, 63, },
+ { 0, 0, 0, 3, 1, 30, },
+ { 2, 0, 0, 3, 1, 32, },
+ { 1, 0, 0, 3, 1, 32, },
+ { 0, 0, 0, 3, 2, 32, },
+ { 2, 0, 0, 3, 2, 32, },
+ { 1, 0, 0, 3, 2, 32, },
+ { 0, 0, 0, 3, 3, 32, },
+ { 2, 0, 0, 3, 3, 32, },
+ { 1, 0, 0, 3, 3, 32, },
+ { 0, 0, 0, 3, 4, 32, },
+ { 2, 0, 0, 3, 4, 32, },
+ { 1, 0, 0, 3, 4, 32, },
+ { 0, 0, 0, 3, 5, 32, },
+ { 2, 0, 0, 3, 5, 32, },
+ { 1, 0, 0, 3, 5, 32, },
+ { 0, 0, 0, 3, 6, 32, },
+ { 2, 0, 0, 3, 6, 32, },
+ { 1, 0, 0, 3, 6, 32, },
+ { 0, 0, 0, 3, 7, 32, },
+ { 2, 0, 0, 3, 7, 32, },
+ { 1, 0, 0, 3, 7, 32, },
+ { 0, 0, 0, 3, 8, 32, },
+ { 2, 0, 0, 3, 8, 32, },
+ { 1, 0, 0, 3, 8, 32, },
+ { 0, 0, 0, 3, 9, 32, },
+ { 2, 0, 0, 3, 9, 32, },
+ { 1, 0, 0, 3, 9, 32, },
+ { 0, 0, 0, 3, 10, 32, },
+ { 2, 0, 0, 3, 10, 32, },
+ { 1, 0, 0, 3, 10, 32, },
+ { 0, 0, 0, 3, 11, 30, },
+ { 2, 0, 0, 3, 11, 32, },
+ { 1, 0, 0, 3, 11, 32, },
+ { 0, 0, 0, 3, 12, 63, },
+ { 2, 0, 0, 3, 12, 32, },
+ { 1, 0, 0, 3, 12, 32, },
+ { 0, 0, 0, 3, 13, 63, },
+ { 2, 0, 0, 3, 13, 32, },
+ { 1, 0, 0, 3, 13, 32, },
+ { 0, 0, 0, 3, 14, 63, },
+ { 2, 0, 0, 3, 14, 63, },
+ { 1, 0, 0, 3, 14, 63, },
+ { 0, 0, 1, 2, 1, 63, },
+ { 2, 0, 1, 2, 1, 63, },
+ { 1, 0, 1, 2, 1, 63, },
+ { 0, 0, 1, 2, 2, 63, },
+ { 2, 0, 1, 2, 2, 63, },
+ { 1, 0, 1, 2, 2, 63, },
+ { 0, 0, 1, 2, 3, 26, },
+ { 2, 0, 1, 2, 3, 26, },
+ { 1, 0, 1, 2, 3, 32, },
+ { 0, 0, 1, 2, 4, 26, },
+ { 2, 0, 1, 2, 4, 32, },
+ { 1, 0, 1, 2, 4, 32, },
+ { 0, 0, 1, 2, 5, 26, },
+ { 2, 0, 1, 2, 5, 32, },
+ { 1, 0, 1, 2, 5, 32, },
+ { 0, 0, 1, 2, 6, 32, },
+ { 2, 0, 1, 2, 6, 32, },
+ { 1, 0, 1, 2, 6, 32, },
+ { 0, 0, 1, 2, 7, 32, },
+ { 2, 0, 1, 2, 7, 32, },
+ { 1, 0, 1, 2, 7, 32, },
+ { 0, 0, 1, 2, 8, 32, },
+ { 2, 0, 1, 2, 8, 32, },
+ { 1, 0, 1, 2, 8, 32, },
+ { 0, 0, 1, 2, 9, 26, },
+ { 2, 0, 1, 2, 9, 32, },
+ { 1, 0, 1, 2, 9, 32, },
+ { 0, 0, 1, 2, 10, 24, },
+ { 2, 0, 1, 2, 10, 32, },
+ { 1, 0, 1, 2, 10, 32, },
+ { 0, 0, 1, 2, 11, 22, },
+ { 2, 0, 1, 2, 11, 26, },
+ { 1, 0, 1, 2, 11, 32, },
+ { 0, 0, 1, 2, 12, 63, },
+ { 2, 0, 1, 2, 12, 63, },
+ { 1, 0, 1, 2, 12, 63, },
+ { 0, 0, 1, 2, 13, 63, },
+ { 2, 0, 1, 2, 13, 63, },
+ { 1, 0, 1, 2, 13, 63, },
+ { 0, 0, 1, 2, 14, 63, },
+ { 2, 0, 1, 2, 14, 63, },
+ { 1, 0, 1, 2, 14, 63, },
+ { 0, 0, 1, 3, 1, 63, },
+ { 2, 0, 1, 3, 1, 63, },
+ { 1, 0, 1, 3, 1, 63, },
+ { 0, 0, 1, 3, 2, 63, },
+ { 2, 0, 1, 3, 2, 63, },
+ { 1, 0, 1, 3, 2, 63, },
+ { 0, 0, 1, 3, 3, 30, },
+ { 2, 0, 1, 3, 3, 30, },
+ { 1, 0, 1, 3, 3, 30, },
+ { 0, 0, 1, 3, 4, 32, },
+ { 2, 0, 1, 3, 4, 30, },
+ { 1, 0, 1, 3, 4, 30, },
+ { 0, 0, 1, 3, 5, 32, },
+ { 2, 0, 1, 3, 5, 30, },
+ { 1, 0, 1, 3, 5, 30, },
+ { 0, 0, 1, 3, 6, 32, },
+ { 2, 0, 1, 3, 6, 30, },
+ { 1, 0, 1, 3, 6, 30, },
+ { 0, 0, 1, 3, 7, 32, },
+ { 2, 0, 1, 3, 7, 30, },
+ { 1, 0, 1, 3, 7, 30, },
+ { 0, 0, 1, 3, 8, 32, },
+ { 2, 0, 1, 3, 8, 30, },
+ { 1, 0, 1, 3, 8, 30, },
+ { 0, 0, 1, 3, 9, 32, },
+ { 2, 0, 1, 3, 9, 30, },
+ { 1, 0, 1, 3, 9, 30, },
+ { 0, 0, 1, 3, 10, 32, },
+ { 2, 0, 1, 3, 10, 30, },
+ { 1, 0, 1, 3, 10, 30, },
+ { 0, 0, 1, 3, 11, 30, },
+ { 2, 0, 1, 3, 11, 30, },
+ { 1, 0, 1, 3, 11, 30, },
+ { 0, 0, 1, 3, 12, 63, },
+ { 2, 0, 1, 3, 12, 32, },
+ { 1, 0, 1, 3, 12, 32, },
+ { 0, 0, 1, 3, 13, 63, },
+ { 2, 0, 1, 3, 13, 32, },
+ { 1, 0, 1, 3, 13, 32, },
+ { 0, 0, 1, 3, 14, 63, },
+ { 2, 0, 1, 3, 14, 63, },
+ { 1, 0, 1, 3, 14, 63, },
+ { 0, 1, 0, 1, 36, 32, },
+ { 2, 1, 0, 1, 36, 30, },
+ { 1, 1, 0, 1, 36, 30, },
+ { 0, 1, 0, 1, 40, 32, },
+ { 2, 1, 0, 1, 40, 30, },
+ { 1, 1, 0, 1, 40, 30, },
+ { 0, 1, 0, 1, 44, 32, },
+ { 2, 1, 0, 1, 44, 30, },
+ { 1, 1, 0, 1, 44, 30, },
+ { 0, 1, 0, 1, 48, 32, },
+ { 2, 1, 0, 1, 48, 30, },
+ { 1, 1, 0, 1, 48, 30, },
+ { 0, 1, 0, 1, 52, 32, },
+ { 2, 1, 0, 1, 52, 30, },
+ { 1, 1, 0, 1, 52, 30, },
+ { 0, 1, 0, 1, 56, 32, },
+ { 2, 1, 0, 1, 56, 30, },
+ { 1, 1, 0, 1, 56, 30, },
+ { 0, 1, 0, 1, 60, 32, },
+ { 2, 1, 0, 1, 60, 30, },
+ { 1, 1, 0, 1, 60, 30, },
+ { 0, 1, 0, 1, 64, 32, },
+ { 2, 1, 0, 1, 64, 30, },
+ { 1, 1, 0, 1, 64, 30, },
+ { 0, 1, 0, 1, 100, 32, },
+ { 2, 1, 0, 1, 100, 30, },
+ { 1, 1, 0, 1, 100, 30, },
+ { 0, 1, 0, 1, 104, 32, },
+ { 2, 1, 0, 1, 104, 30, },
+ { 1, 1, 0, 1, 104, 30, },
+ { 0, 1, 0, 1, 108, 32, },
+ { 2, 1, 0, 1, 108, 30, },
+ { 1, 1, 0, 1, 108, 30, },
+ { 0, 1, 0, 1, 112, 32, },
+ { 2, 1, 0, 1, 112, 30, },
+ { 1, 1, 0, 1, 112, 30, },
+ { 0, 1, 0, 1, 116, 32, },
+ { 2, 1, 0, 1, 116, 30, },
+ { 1, 1, 0, 1, 116, 30, },
+ { 0, 1, 0, 1, 120, 32, },
+ { 2, 1, 0, 1, 120, 30, },
+ { 1, 1, 0, 1, 120, 30, },
+ { 0, 1, 0, 1, 124, 32, },
+ { 2, 1, 0, 1, 124, 30, },
+ { 1, 1, 0, 1, 124, 30, },
+ { 0, 1, 0, 1, 128, 32, },
+ { 2, 1, 0, 1, 128, 30, },
+ { 1, 1, 0, 1, 128, 30, },
+ { 0, 1, 0, 1, 132, 32, },
+ { 2, 1, 0, 1, 132, 30, },
+ { 1, 1, 0, 1, 132, 30, },
+ { 0, 1, 0, 1, 136, 32, },
+ { 2, 1, 0, 1, 136, 30, },
+ { 1, 1, 0, 1, 136, 30, },
+ { 0, 1, 0, 1, 140, 32, },
+ { 2, 1, 0, 1, 140, 30, },
+ { 1, 1, 0, 1, 140, 30, },
+ { 0, 1, 0, 1, 149, 32, },
+ { 2, 1, 0, 1, 149, 30, },
+ { 1, 1, 0, 1, 149, 63, },
+ { 0, 1, 0, 1, 153, 32, },
+ { 2, 1, 0, 1, 153, 30, },
+ { 1, 1, 0, 1, 153, 63, },
+ { 0, 1, 0, 1, 157, 32, },
+ { 2, 1, 0, 1, 157, 30, },
+ { 1, 1, 0, 1, 157, 63, },
+ { 0, 1, 0, 1, 161, 32, },
+ { 2, 1, 0, 1, 161, 30, },
+ { 1, 1, 0, 1, 161, 63, },
+ { 0, 1, 0, 1, 165, 32, },
+ { 2, 1, 0, 1, 165, 30, },
+ { 1, 1, 0, 1, 165, 63, },
+ { 0, 1, 0, 2, 36, 32, },
+ { 2, 1, 0, 2, 36, 30, },
+ { 1, 1, 0, 2, 36, 30, },
+ { 0, 1, 0, 2, 40, 32, },
+ { 2, 1, 0, 2, 40, 30, },
+ { 1, 1, 0, 2, 40, 30, },
+ { 0, 1, 0, 2, 44, 32, },
+ { 2, 1, 0, 2, 44, 30, },
+ { 1, 1, 0, 2, 44, 30, },
+ { 0, 1, 0, 2, 48, 32, },
+ { 2, 1, 0, 2, 48, 30, },
+ { 1, 1, 0, 2, 48, 30, },
+ { 0, 1, 0, 2, 52, 32, },
+ { 2, 1, 0, 2, 52, 30, },
+ { 1, 1, 0, 2, 52, 30, },
+ { 0, 1, 0, 2, 56, 32, },
+ { 2, 1, 0, 2, 56, 30, },
+ { 1, 1, 0, 2, 56, 30, },
+ { 0, 1, 0, 2, 60, 32, },
+ { 2, 1, 0, 2, 60, 30, },
+ { 1, 1, 0, 2, 60, 30, },
+ { 0, 1, 0, 2, 64, 32, },
+ { 2, 1, 0, 2, 64, 30, },
+ { 1, 1, 0, 2, 64, 30, },
+ { 0, 1, 0, 2, 100, 32, },
+ { 2, 1, 0, 2, 100, 30, },
+ { 1, 1, 0, 2, 100, 30, },
+ { 0, 1, 0, 2, 104, 32, },
+ { 2, 1, 0, 2, 104, 30, },
+ { 1, 1, 0, 2, 104, 30, },
+ { 0, 1, 0, 2, 108, 32, },
+ { 2, 1, 0, 2, 108, 30, },
+ { 1, 1, 0, 2, 108, 30, },
+ { 0, 1, 0, 2, 112, 32, },
+ { 2, 1, 0, 2, 112, 30, },
+ { 1, 1, 0, 2, 112, 30, },
+ { 0, 1, 0, 2, 116, 32, },
+ { 2, 1, 0, 2, 116, 30, },
+ { 1, 1, 0, 2, 116, 30, },
+ { 0, 1, 0, 2, 120, 32, },
+ { 2, 1, 0, 2, 120, 30, },
+ { 1, 1, 0, 2, 120, 30, },
+ { 0, 1, 0, 2, 124, 32, },
+ { 2, 1, 0, 2, 124, 30, },
+ { 1, 1, 0, 2, 124, 30, },
+ { 0, 1, 0, 2, 128, 32, },
+ { 2, 1, 0, 2, 128, 30, },
+ { 1, 1, 0, 2, 128, 30, },
+ { 0, 1, 0, 2, 132, 32, },
+ { 2, 1, 0, 2, 132, 30, },
+ { 1, 1, 0, 2, 132, 30, },
+ { 0, 1, 0, 2, 136, 32, },
+ { 2, 1, 0, 2, 136, 30, },
+ { 1, 1, 0, 2, 136, 30, },
+ { 0, 1, 0, 2, 140, 32, },
+ { 2, 1, 0, 2, 140, 30, },
+ { 1, 1, 0, 2, 140, 30, },
+ { 0, 1, 0, 2, 149, 32, },
+ { 2, 1, 0, 2, 149, 30, },
+ { 1, 1, 0, 2, 149, 63, },
+ { 0, 1, 0, 2, 153, 32, },
+ { 2, 1, 0, 2, 153, 30, },
+ { 1, 1, 0, 2, 153, 63, },
+ { 0, 1, 0, 2, 157, 32, },
+ { 2, 1, 0, 2, 157, 30, },
+ { 1, 1, 0, 2, 157, 63, },
+ { 0, 1, 0, 2, 161, 32, },
+ { 2, 1, 0, 2, 161, 30, },
+ { 1, 1, 0, 2, 161, 63, },
+ { 0, 1, 0, 2, 165, 32, },
+ { 2, 1, 0, 2, 165, 30, },
+ { 1, 1, 0, 2, 165, 63, },
+ { 0, 1, 0, 3, 36, 28, },
+ { 2, 1, 0, 3, 36, 30, },
+ { 1, 1, 0, 3, 36, 30, },
+ { 0, 1, 0, 3, 40, 28, },
+ { 2, 1, 0, 3, 40, 30, },
+ { 1, 1, 0, 3, 40, 30, },
+ { 0, 1, 0, 3, 44, 28, },
+ { 2, 1, 0, 3, 44, 30, },
+ { 1, 1, 0, 3, 44, 30, },
+ { 0, 1, 0, 3, 48, 28, },
+ { 2, 1, 0, 3, 48, 30, },
+ { 1, 1, 0, 3, 48, 30, },
+ { 0, 1, 0, 3, 52, 34, },
+ { 2, 1, 0, 3, 52, 30, },
+ { 1, 1, 0, 3, 52, 30, },
+ { 0, 1, 0, 3, 56, 32, },
+ { 2, 1, 0, 3, 56, 30, },
+ { 1, 1, 0, 3, 56, 30, },
+ { 0, 1, 0, 3, 60, 30, },
+ { 2, 1, 0, 3, 60, 30, },
+ { 1, 1, 0, 3, 60, 30, },
+ { 0, 1, 0, 3, 64, 26, },
+ { 2, 1, 0, 3, 64, 30, },
+ { 1, 1, 0, 3, 64, 30, },
+ { 0, 1, 0, 3, 100, 28, },
+ { 2, 1, 0, 3, 100, 30, },
+ { 1, 1, 0, 3, 100, 30, },
+ { 0, 1, 0, 3, 104, 28, },
+ { 2, 1, 0, 3, 104, 30, },
+ { 1, 1, 0, 3, 104, 30, },
+ { 0, 1, 0, 3, 108, 30, },
+ { 2, 1, 0, 3, 108, 30, },
+ { 1, 1, 0, 3, 108, 30, },
+ { 0, 1, 0, 3, 112, 32, },
+ { 2, 1, 0, 3, 112, 30, },
+ { 1, 1, 0, 3, 112, 30, },
+ { 0, 1, 0, 3, 116, 32, },
+ { 2, 1, 0, 3, 116, 30, },
+ { 1, 1, 0, 3, 116, 30, },
+ { 0, 1, 0, 3, 120, 34, },
+ { 2, 1, 0, 3, 120, 30, },
+ { 1, 1, 0, 3, 120, 30, },
+ { 0, 1, 0, 3, 124, 32, },
+ { 2, 1, 0, 3, 124, 30, },
+ { 1, 1, 0, 3, 124, 30, },
+ { 0, 1, 0, 3, 128, 30, },
+ { 2, 1, 0, 3, 128, 30, },
+ { 1, 1, 0, 3, 128, 30, },
+ { 0, 1, 0, 3, 132, 28, },
+ { 2, 1, 0, 3, 132, 30, },
+ { 1, 1, 0, 3, 132, 30, },
+ { 0, 1, 0, 3, 136, 28, },
+ { 2, 1, 0, 3, 136, 30, },
+ { 1, 1, 0, 3, 136, 30, },
+ { 0, 1, 0, 3, 140, 26, },
+ { 2, 1, 0, 3, 140, 30, },
+ { 1, 1, 0, 3, 140, 30, },
+ { 0, 1, 0, 3, 149, 34, },
+ { 2, 1, 0, 3, 149, 30, },
+ { 1, 1, 0, 3, 149, 63, },
+ { 0, 1, 0, 3, 153, 34, },
+ { 2, 1, 0, 3, 153, 30, },
+ { 1, 1, 0, 3, 153, 63, },
+ { 0, 1, 0, 3, 157, 34, },
+ { 2, 1, 0, 3, 157, 30, },
+ { 1, 1, 0, 3, 157, 63, },
+ { 0, 1, 0, 3, 161, 34, },
+ { 2, 1, 0, 3, 161, 30, },
+ { 1, 1, 0, 3, 161, 63, },
+ { 0, 1, 0, 3, 165, 34, },
+ { 2, 1, 0, 3, 165, 30, },
+ { 1, 1, 0, 3, 165, 63, },
+ { 0, 1, 1, 2, 38, 26, },
+ { 2, 1, 1, 2, 38, 30, },
+ { 1, 1, 1, 2, 38, 30, },
+ { 0, 1, 1, 2, 46, 32, },
+ { 2, 1, 1, 2, 46, 30, },
+ { 1, 1, 1, 2, 46, 30, },
+ { 0, 1, 1, 2, 54, 32, },
+ { 2, 1, 1, 2, 54, 30, },
+ { 1, 1, 1, 2, 54, 30, },
+ { 0, 1, 1, 2, 62, 24, },
+ { 2, 1, 1, 2, 62, 30, },
+ { 1, 1, 1, 2, 62, 30, },
+ { 0, 1, 1, 2, 102, 24, },
+ { 2, 1, 1, 2, 102, 30, },
+ { 1, 1, 1, 2, 102, 30, },
+ { 0, 1, 1, 2, 110, 32, },
+ { 2, 1, 1, 2, 110, 30, },
+ { 1, 1, 1, 2, 110, 30, },
+ { 0, 1, 1, 2, 118, 32, },
+ { 2, 1, 1, 2, 118, 30, },
+ { 1, 1, 1, 2, 118, 30, },
+ { 0, 1, 1, 2, 126, 32, },
+ { 2, 1, 1, 2, 126, 30, },
+ { 1, 1, 1, 2, 126, 30, },
+ { 0, 1, 1, 2, 134, 32, },
+ { 2, 1, 1, 2, 134, 30, },
+ { 1, 1, 1, 2, 134, 30, },
+ { 0, 1, 1, 2, 151, 30, },
+ { 2, 1, 1, 2, 151, 30, },
+ { 1, 1, 1, 2, 151, 63, },
+ { 0, 1, 1, 2, 159, 32, },
+ { 2, 1, 1, 2, 159, 30, },
+ { 1, 1, 1, 2, 159, 63, },
+ { 0, 1, 1, 3, 38, 28, },
+ { 2, 1, 1, 3, 38, 30, },
+ { 1, 1, 1, 3, 38, 30, },
+ { 0, 1, 1, 3, 46, 28, },
+ { 2, 1, 1, 3, 46, 30, },
+ { 1, 1, 1, 3, 46, 30, },
+ { 0, 1, 1, 3, 54, 30, },
+ { 2, 1, 1, 3, 54, 30, },
+ { 1, 1, 1, 3, 54, 30, },
+ { 0, 1, 1, 3, 62, 30, },
+ { 2, 1, 1, 3, 62, 30, },
+ { 1, 1, 1, 3, 62, 30, },
+ { 0, 1, 1, 3, 102, 26, },
+ { 2, 1, 1, 3, 102, 30, },
+ { 1, 1, 1, 3, 102, 30, },
+ { 0, 1, 1, 3, 110, 30, },
+ { 2, 1, 1, 3, 110, 30, },
+ { 1, 1, 1, 3, 110, 30, },
+ { 0, 1, 1, 3, 118, 34, },
+ { 2, 1, 1, 3, 118, 30, },
+ { 1, 1, 1, 3, 118, 30, },
+ { 0, 1, 1, 3, 126, 32, },
+ { 2, 1, 1, 3, 126, 30, },
+ { 1, 1, 1, 3, 126, 30, },
+ { 0, 1, 1, 3, 134, 30, },
+ { 2, 1, 1, 3, 134, 30, },
+ { 1, 1, 1, 3, 134, 30, },
+ { 0, 1, 1, 3, 151, 34, },
+ { 2, 1, 1, 3, 151, 30, },
+ { 1, 1, 1, 3, 151, 63, },
+ { 0, 1, 1, 3, 159, 34, },
+ { 2, 1, 1, 3, 159, 30, },
+ { 1, 1, 1, 3, 159, 63, },
+ { 0, 1, 2, 4, 42, 22, },
+ { 2, 1, 2, 4, 42, 30, },
+ { 1, 1, 2, 4, 42, 30, },
+ { 0, 1, 2, 4, 58, 20, },
+ { 2, 1, 2, 4, 58, 30, },
+ { 1, 1, 2, 4, 58, 30, },
+ { 0, 1, 2, 4, 106, 20, },
+ { 2, 1, 2, 4, 106, 30, },
+ { 1, 1, 2, 4, 106, 30, },
+ { 0, 1, 2, 4, 122, 20, },
+ { 2, 1, 2, 4, 122, 30, },
+ { 1, 1, 2, 4, 122, 30, },
+ { 0, 1, 2, 4, 155, 28, },
+ { 2, 1, 2, 4, 155, 30, },
+ { 1, 1, 2, 4, 155, 63, },
+ { 0, 1, 2, 5, 42, 28, },
+ { 2, 1, 2, 5, 42, 30, },
+ { 1, 1, 2, 5, 42, 30, },
+ { 0, 1, 2, 5, 58, 26, },
+ { 2, 1, 2, 5, 58, 30, },
+ { 1, 1, 2, 5, 58, 30, },
+ { 0, 1, 2, 5, 106, 28, },
+ { 2, 1, 2, 5, 106, 30, },
+ { 1, 1, 2, 5, 106, 30, },
+ { 0, 1, 2, 5, 122, 32, },
+ { 2, 1, 2, 5, 122, 30, },
+ { 1, 1, 2, 5, 122, 30, },
+ { 0, 1, 2, 5, 155, 34, },
+ { 2, 1, 2, 5, 155, 30, },
+ { 1, 1, 2, 5, 155, 63, },
+};
+
+RTW_DECL_TABLE_TXPWR_LMT(rtw8821a_txpwr_lmt);
+
+static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821a[] = {
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3) | BIT(7), 0},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
+ {0x004A,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), 0},
+ {0x0023,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), 0},
+ {0x0301,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821a[] = {
+ {0x0020,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0067,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), 0},
+ {0x0001,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_DELAY, 1, RTW_PWR_DELAY_MS},
+ {0x0000,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(5), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4) | BIT(3) | BIT(2), 0},
+ {0x0075,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0006,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
+ {0x0075,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0006,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(7), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4) | BIT(3), 0},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, BIT(0), 0},
+ {0x004F,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0067,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(5) | BIT(4), BIT(5) | BIT(4)},
+ {0x0025,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(6), 0},
+ {0x0049,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+ {0x0063,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+ {0x0062,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0058,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x005A,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+ {0x002E,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x82},
+ {0x0010,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(6), BIT(6)},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_act_to_lps_8821a[] = {
+ {0x0301,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
+ {0x0522,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
+ {0x05F8,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x05F9,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x05FA,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x05FB,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, 0xFF, 0},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US},
+ {0x0002,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0100,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x03},
+ {0x0101,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0093,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+ {0x0553,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821a[] = {
+ {0x001F,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0},
+ {0x004F,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0049,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0006,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_POLLING, BIT(1), 0},
+ {0x0000,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
+ {0x0020,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821a[] = {
+ {0x0007,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x20},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)},
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_PCI_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
+ {0x004A,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_USB_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 1},
+ {0x0023,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), BIT(4)},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), 0},
+ {0xFFFF,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ 0,
+ RTW_PWR_CMD_END, 0, 0},
+};
+
+const struct rtw_pwr_seq_cmd * const card_enable_flow_8821a[] = {
+ trans_carddis_to_cardemu_8821a,
+ trans_cardemu_to_act_8821a,
+ NULL
+};
+
+const struct rtw_pwr_seq_cmd * const enter_lps_flow_8821a[] = {
+ trans_act_to_lps_8821a,
+ NULL
+};
+
+const struct rtw_pwr_seq_cmd * const card_disable_flow_8821a[] = {
+ trans_act_to_cardemu_8821a,
+ trans_cardemu_to_carddis_8821a,
+ NULL
+};
+
+static const u8 rtw8821a_pwrtrk_5gb_n[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+};
+
+static const u8 rtw8821a_pwrtrk_5gb_p[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+};
+
+static const u8 rtw8821a_pwrtrk_5ga_n[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+};
+
+static const u8 rtw8821a_pwrtrk_5ga_p[][RTW_PWR_TRK_TBL_SZ] = {
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+ {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16},
+};
+
+static const u8 rtw8821a_pwrtrk_2gb_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
+};
+
+static const u8 rtw8821a_pwrtrk_2gb_p[] = {
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
+};
+
+static const u8 rtw8821a_pwrtrk_2ga_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
+};
+
+static const u8 rtw8821a_pwrtrk_2ga_p[] = {
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
+};
+
+static const u8 rtw8821a_pwrtrk_2g_cck_b_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
+};
+
+static const u8 rtw8821a_pwrtrk_2g_cck_b_p[] = {
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
+};
+
+static const u8 rtw8821a_pwrtrk_2g_cck_a_n[] = {
+ 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
+};
+
+static const u8 rtw8821a_pwrtrk_2g_cck_a_p[] = {
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
+};
+
+const struct rtw_pwr_track_tbl rtw8821a_rtw_pwr_track_tbl = {
+ .pwrtrk_5gb_n[0] = rtw8821a_pwrtrk_5gb_n[0],
+ .pwrtrk_5gb_n[1] = rtw8821a_pwrtrk_5gb_n[1],
+ .pwrtrk_5gb_n[2] = rtw8821a_pwrtrk_5gb_n[2],
+ .pwrtrk_5gb_p[0] = rtw8821a_pwrtrk_5gb_p[0],
+ .pwrtrk_5gb_p[1] = rtw8821a_pwrtrk_5gb_p[1],
+ .pwrtrk_5gb_p[2] = rtw8821a_pwrtrk_5gb_p[2],
+ .pwrtrk_5ga_n[0] = rtw8821a_pwrtrk_5ga_n[0],
+ .pwrtrk_5ga_n[1] = rtw8821a_pwrtrk_5ga_n[1],
+ .pwrtrk_5ga_n[2] = rtw8821a_pwrtrk_5ga_n[2],
+ .pwrtrk_5ga_p[0] = rtw8821a_pwrtrk_5ga_p[0],
+ .pwrtrk_5ga_p[1] = rtw8821a_pwrtrk_5ga_p[1],
+ .pwrtrk_5ga_p[2] = rtw8821a_pwrtrk_5ga_p[2],
+ .pwrtrk_2gb_n = rtw8821a_pwrtrk_2gb_n,
+ .pwrtrk_2gb_p = rtw8821a_pwrtrk_2gb_p,
+ .pwrtrk_2ga_n = rtw8821a_pwrtrk_2ga_n,
+ .pwrtrk_2ga_p = rtw8821a_pwrtrk_2ga_p,
+ .pwrtrk_2g_cckb_n = rtw8821a_pwrtrk_2g_cck_b_n,
+ .pwrtrk_2g_cckb_p = rtw8821a_pwrtrk_2g_cck_b_p,
+ .pwrtrk_2g_ccka_n = rtw8821a_pwrtrk_2g_cck_a_n,
+ .pwrtrk_2g_ccka_p = rtw8821a_pwrtrk_2g_cck_a_p,
+};
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a_table.h b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.h
new file mode 100644
index 000000000000..90379ac7a817
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#ifndef __RTW8821A_TABLE_H__
+#define __RTW8821A_TABLE_H__
+
+extern const struct rtw_table rtw8821a_mac_tbl;
+extern const struct rtw_table rtw8821a_agc_tbl;
+extern const struct rtw_table rtw8821a_bb_tbl;
+extern const struct rtw_table rtw8821a_bb_pg_tbl;
+extern const struct rtw_table rtw8821a_rf_a_tbl;
+extern const struct rtw_table rtw8821a_txpwr_lmt_tbl;
+
+extern const struct rtw_pwr_seq_cmd * const card_enable_flow_8821a[];
+extern const struct rtw_pwr_seq_cmd * const enter_lps_flow_8821a[];
+extern const struct rtw_pwr_seq_cmd * const card_disable_flow_8821a[];
+
+extern const struct rtw_pwr_track_tbl rtw8821a_rtw_pwr_track_tbl;
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821au.c b/drivers/net/wireless/realtek/rtw88/rtw8821au.c
new file mode 100644
index 000000000000..730018773e1c
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "main.h"
+#include "rtw8821a.h"
+#include "usb.h"
+
+static const struct usb_device_id rtw_8821au_id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
+ {},
+};
+MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table);
+
+static struct usb_driver rtw_8821au_driver = {
+ .name = "rtw_8821au",
+ .id_table = rtw_8821au_id_table,
+ .probe = rtw_usb_probe,
+ .disconnect = rtw_usb_disconnect,
+};
+module_usb_driver(rtw_8821au_driver);
+
+MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821au/8811au driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index 526e8de77b3e..0270225b9c20 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -679,47 +679,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
}
}
-static void rtw8821c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_rx_status *rx_status)
-{
- struct ieee80211_hdr *hdr;
- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
- u8 *phy_status = NULL;
-
- memset(pkt_stat, 0, sizeof(*pkt_stat));
-
- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
- pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc);
- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
-
- /* drv_info_sz is in unit of 8-bytes */
- pkt_stat->drv_info_sz *= 8;
-
- /* c2h cmd pkt's rx/phy status is not interested */
- if (pkt_stat->is_c2h)
- return;
-
- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
- pkt_stat->drv_info_sz);
- if (pkt_stat->phy_status) {
- phy_status = rx_desc + desc_sz + pkt_stat->shift;
- query_phy_status(rtwdev, phy_status, pkt_stat);
- }
-
- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
-}
-
static void
rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
{
@@ -1254,7 +1213,7 @@ static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev,
fill_txdesc_checksum_common(txdesc, 16);
}
-static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
+static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
{0x0086,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_SDIO_MSK,
@@ -1292,7 +1251,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = {
+static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = {
{0x0020,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
@@ -1396,7 +1355,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = {
+static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = {
{0x0093,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
@@ -1454,7 +1413,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = {
+static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = {
{0x0007,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
@@ -1567,13 +1526,13 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static const struct rtw_pwr_seq_cmd *card_enable_flow_8821c[] = {
+static const struct rtw_pwr_seq_cmd * const card_enable_flow_8821c[] = {
trans_carddis_to_cardemu_8821c,
trans_cardemu_to_act_8821c,
NULL
};
-static const struct rtw_pwr_seq_cmd *card_disable_flow_8821c[] = {
+static const struct rtw_pwr_seq_cmd * const card_disable_flow_8821c[] = {
trans_act_to_cardemu_8821c,
trans_cardemu_to_carddis_8821c,
NULL
@@ -1622,14 +1581,7 @@ static const struct rtw_intf_phy_para_table phy_para_table_8821c = {
.n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8821c),
};
-static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
- [0] = RTW_DEF_RFE(8821c, 0, 0),
- [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
- [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
- [6] = RTW_DEF_RFE(8821c, 0, 0),
-};
-
-static struct rtw_hw_reg rtw8821c_dig[] = {
+static const struct rtw_hw_reg rtw8821c_dig[] = {
[0] = { .addr = 0xc50, .mask = 0x7f },
};
@@ -1639,7 +1591,7 @@ static const struct rtw_ltecoex_addr rtw8821c_ltecoex_addr = {
.rdata = LTECOEX_READ_DATA,
};
-static struct rtw_page_table page_table_8821c[] = {
+static const struct rtw_page_table page_table_8821c[] = {
/* not sure what [0] stands for */
{16, 16, 16, 14, 1},
{16, 16, 16, 14, 1},
@@ -1648,7 +1600,7 @@ static struct rtw_page_table page_table_8821c[] = {
{16, 16, 16, 14, 1},
};
-static struct rtw_rqpn rqpn_table_8821c[] = {
+static const struct rtw_rqpn rqpn_table_8821c[] = {
/* not sure what [0] stands for */
{RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
@@ -1667,7 +1619,7 @@ static struct rtw_rqpn rqpn_table_8821c[] = {
RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
};
-static struct rtw_prioq_addrs prioq_addrs_8821c = {
+static const struct rtw_prioq_addrs prioq_addrs_8821c = {
.prio[RTW_DMA_MAPPING_EXTRA] = {
.rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
},
@@ -1683,10 +1635,12 @@ static struct rtw_prioq_addrs prioq_addrs_8821c = {
.wsize = true,
};
-static struct rtw_chip_ops rtw8821c_ops = {
+static const struct rtw_chip_ops rtw8821c_ops = {
+ .power_on = rtw_power_on,
+ .power_off = rtw_power_off,
.phy_set_param = rtw8821c_phy_set_param,
.read_efuse = rtw8821c_read_efuse,
- .query_rx_desc = rtw8821c_query_rx_desc,
+ .query_phy_status = query_phy_status,
.set_channel = rtw8821c_set_channel,
.mac_init = rtw8821c_mac_init,
.read_rf = rtw_phy_read_rf,
@@ -1938,7 +1892,7 @@ static const u8 rtw8821c_pwrtrk_2g_cck_a_p[] = {
5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9
};
-static const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = {
+static const struct rtw_pwr_track_tbl rtw8821c_pwr_track_type0_tbl = {
.pwrtrk_5gb_n[0] = rtw8821c_pwrtrk_5gb_n[0],
.pwrtrk_5gb_n[1] = rtw8821c_pwrtrk_5gb_n[1],
.pwrtrk_5gb_n[2] = rtw8821c_pwrtrk_5gb_n[2],
@@ -1961,6 +1915,13 @@ static const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = {
.pwrtrk_2g_ccka_p = rtw8821c_pwrtrk_2g_cck_a_p,
};
+static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
+ [0] = RTW_DEF_RFE(8821c, 0, 0, 0),
+ [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 0, 2),
+ [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 0, 2),
+ [6] = RTW_DEF_RFE(8821c, 0, 0, 0),
+};
+
static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = {
{0xCB0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
{0xCB4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
@@ -2009,6 +1970,9 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
.page_size = TX_PAGE_SIZE,
.dig_min = 0x1c,
.usb_tx_agg_desc_num = 3,
+ .hw_feature_report = true,
+ .c2h_ra_report_size = 7,
+ .old_datarate_fb_limit = false,
.ht_supported = true,
.vht_supported = true,
.lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
@@ -2030,7 +1994,6 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
.rfe_defs = rtw8821c_rfe_defs,
.rfe_defs_size = ARRAY_SIZE(rtw8821c_rfe_defs),
.rx_ldpc = false,
- .pwr_track_tbl = &rtw8821c_rtw_pwr_track_tbl,
.iqk_threshold = 8,
.bfer_su_max_num = 2,
.bfer_mu_max_num = 1,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
index 91ed921407bb..7a33ebd612ed 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
@@ -214,19 +214,10 @@ extern const struct rtw_chip_info rtw8821c_hw_spec;
#define BIT_FEN_EN BIT(26)
#define REG_INIRTS_RATE_SEL 0x0480
#define REG_HTSTFWT 0x800
-#define REG_RXPSEL 0x808
-#define BIT_RX_PSEL_RST (BIT(28) | BIT(29))
-#define REG_TXPSEL 0x80c
#define REG_RXCCAMSK 0x814
-#define REG_CCASEL 0x82c
-#define REG_PDMFTH 0x830
-#define REG_CCA2ND 0x838
#define REG_L1WT 0x83c
#define REG_L1PKWT 0x840
#define REG_MRC 0x850
-#define REG_CLKTRK 0x860
-#define REG_ADCCLK 0x8ac
-#define REG_ADC160 0x8c4
#define REG_ADC40 0x8c8
#define REG_CHFIR 0x8f0
#define REG_CDDTXP 0x93c
@@ -234,14 +225,11 @@ extern const struct rtw_chip_info rtw8821c_hw_spec;
#define REG_ACBB0 0x948
#define REG_ACBBRXFIR 0x94c
#define REG_ACGG2TBL 0x958
-#define REG_FAS 0x9a4
-#define REG_RXSB 0xa00
#define REG_ADCINI 0xa04
#define REG_PWRTH 0xa08
#define REG_CCA_FLTR 0xa20
#define REG_TXSF2 0xa24
#define REG_TXSF6 0xa28
-#define REG_FA_CCK 0xa5c
#define REG_RXDESC 0xa2c
#define REG_ENTXCCK 0xa80
#define BTG_LNA 0xfc84
@@ -252,12 +240,8 @@ extern const struct rtw_chip_info rtw8821c_hw_spec;
#define REG_PWRTH2 0xaa8
#define REG_CSRATIO 0xaaa
#define REG_TXFILTER 0xaac
-#define REG_CNTRST 0xb58
#define REG_AGCTR_A 0xc08
-#define REG_TXSCALE_A 0xc1c
#define REG_TXDFIR 0xc20
-#define REG_RXIGI_A 0xc50
-#define REG_TXAGCIDX 0xc94
#define REG_TRSW 0xca0
#define REG_RFESEL0 0xcb0
#define REG_RFESEL8 0xcb4
@@ -269,14 +253,6 @@ extern const struct rtw_chip_info rtw8821c_hw_spec;
#define B_WLA_SWITCH BIT(23)
#define REG_RFEINV 0xcbc
#define REG_AGCTR_B 0xe08
-#define REG_RXIGI_B 0xe50
-#define REG_CRC_CCK 0xf04
-#define REG_CRC_OFDM 0xf14
-#define REG_CRC_HT 0xf10
-#define REG_CRC_VHT 0xf0c
-#define REG_CCA_OFDM 0xf08
-#define REG_FA_OFDM 0xf48
-#define REG_CCA_CCK 0xfcc
#define REG_DMEM_CTRL 0x1080
#define BIT_WL_RST BIT(16)
#define REG_ANTWT 0x1904
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index 6edb17aea90e..739809f4cab5 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -934,47 +934,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
}
}
-static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_rx_status *rx_status)
-{
- struct ieee80211_hdr *hdr;
- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
- u8 *phy_status = NULL;
-
- memset(pkt_stat, 0, sizeof(*pkt_stat));
-
- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
- pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc);
- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
-
- /* drv_info_sz is in unit of 8-bytes */
- pkt_stat->drv_info_sz *= 8;
-
- /* c2h cmd pkt's rx/phy status is not interested */
- if (pkt_stat->is_c2h)
- return;
-
- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
- pkt_stat->drv_info_sz);
- if (pkt_stat->phy_status) {
- phy_status = rx_desc + desc_sz + pkt_stat->shift;
- query_phy_status(rtwdev, phy_status, pkt_stat);
- }
-
- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
-}
-
static void
rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
{
@@ -1978,13 +1937,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static const struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = {
+static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822b[] = {
trans_carddis_to_cardemu_8822b,
trans_cardemu_to_act_8822b,
NULL
};
-static const struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = {
+static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822b[] = {
trans_act_to_cardemu_8822b,
trans_cardemu_to_carddis_8822b,
NULL
@@ -2113,12 +2072,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8822b = {
.n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8822b),
};
-static const struct rtw_rfe_def rtw8822b_rfe_defs[] = {
- [2] = RTW_DEF_RFE(8822b, 2, 2),
- [3] = RTW_DEF_RFE(8822b, 3, 0),
- [5] = RTW_DEF_RFE(8822b, 5, 5),
-};
-
static const struct rtw_hw_reg rtw8822b_dig[] = {
[0] = { .addr = 0xc50, .mask = 0x7f },
[1] = { .addr = 0xe50, .mask = 0x7f },
@@ -2156,7 +2109,7 @@ static const struct rtw_rqpn rqpn_table_8822b[] = {
RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
};
-static struct rtw_prioq_addrs prioq_addrs_8822b = {
+static const struct rtw_prioq_addrs prioq_addrs_8822b = {
.prio[RTW_DMA_MAPPING_EXTRA] = {
.rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
},
@@ -2172,10 +2125,12 @@ static struct rtw_prioq_addrs prioq_addrs_8822b = {
.wsize = true,
};
-static struct rtw_chip_ops rtw8822b_ops = {
+static const struct rtw_chip_ops rtw8822b_ops = {
+ .power_on = rtw_power_on,
+ .power_off = rtw_power_off,
.phy_set_param = rtw8822b_phy_set_param,
.read_efuse = rtw8822b_read_efuse,
- .query_rx_desc = rtw8822b_query_rx_desc,
+ .query_phy_status = query_phy_status,
.set_channel = rtw8822b_set_channel,
.mac_init = rtw8822b_mac_init,
.read_rf = rtw_phy_read_rf,
@@ -2471,7 +2426,7 @@ static const u8 rtw8822b_pwrtrk_2g_cck_a_p[RTW_PWR_TRK_TBL_SZ] = {
10, 11, 11, 12, 12, 13, 13, 14, 14, 15
};
-static const struct rtw_pwr_track_tbl rtw8822b_rtw_pwr_track_tbl = {
+static const struct rtw_pwr_track_tbl rtw8822b_pwr_track_type0_tbl = {
.pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1],
.pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2],
.pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3],
@@ -2494,6 +2449,12 @@ static const struct rtw_pwr_track_tbl rtw8822b_rtw_pwr_track_tbl = {
.pwrtrk_2g_ccka_p = rtw8822b_pwrtrk_2g_cck_a_p,
};
+static const struct rtw_rfe_def rtw8822b_rfe_defs[] = {
+ [2] = RTW_DEF_RFE(8822b, 2, 2, 0),
+ [3] = RTW_DEF_RFE(8822b, 3, 0, 0),
+ [5] = RTW_DEF_RFE(8822b, 5, 5, 0),
+};
+
static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = {
{0xcb0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
{0xcb4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
@@ -2521,7 +2482,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = {
{0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
};
-static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
+static const struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
[EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0},
[EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
};
@@ -2550,6 +2511,9 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
.page_size = TX_PAGE_SIZE,
.dig_min = 0x1c,
.usb_tx_agg_desc_num = 3,
+ .hw_feature_report = true,
+ .c2h_ra_report_size = 7,
+ .old_datarate_fb_limit = false,
.ht_supported = true,
.vht_supported = true,
.lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
@@ -2571,7 +2535,6 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
.rf_tbl = {&rtw8822b_rf_a_tbl, &rtw8822b_rf_b_tbl},
.rfe_defs = rtw8822b_rfe_defs,
.rfe_defs_size = ARRAY_SIZE(rtw8822b_rfe_defs),
- .pwr_track_tbl = &rtw8822b_rtw_pwr_track_tbl,
.iqk_threshold = 8,
.bfer_su_max_num = 2,
.bfer_mu_max_num = 1,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.h b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
index cf85e63966a1..0514958fb57c 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
@@ -151,21 +151,12 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
#define RTW8822B_EDCCA_MAX 0x7f
#define RTW8822B_EDCCA_SRC_DEF 1
#define REG_HTSTFWT 0x800
-#define REG_RXPSEL 0x808
-#define BIT_RX_PSEL_RST (BIT(28) | BIT(29))
-#define REG_TXPSEL 0x80c
#define REG_RXCCAMSK 0x814
-#define REG_CCASEL 0x82c
-#define REG_PDMFTH 0x830
-#define REG_CCA2ND 0x838
#define REG_L1WT 0x83c
#define REG_L1PKWT 0x840
#define REG_MRC 0x850
-#define REG_CLKTRK 0x860
#define REG_EDCCA_POW_MA 0x8a0
#define BIT_MA_LEVEL GENMASK(1, 0)
-#define REG_ADCCLK 0x8ac
-#define REG_ADC160 0x8c4
#define REG_ADC40 0x8c8
#define REG_EDCCA_DECISION 0x8dc
#define BIT_EDCCA_OPTION BIT(5)
@@ -176,7 +167,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
#define REG_ACBB0 0x948
#define REG_ACBBRXFIR 0x94c
#define REG_ACGG2TBL 0x958
-#define REG_RXSB 0xa00
#define REG_ADCINI 0xa04
#define REG_TXSF2 0xa24
#define REG_TXSF6 0xa28
@@ -184,14 +174,12 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
#define REG_ENTXCCK 0xa80
#define REG_AGCTR_A 0xc08
#define REG_TXDFIR 0xc20
-#define REG_RXIGI_A 0xc50
#define REG_TRSW 0xca0
#define REG_RFESEL0 0xcb0
#define REG_RFESEL8 0xcb4
#define REG_RFECTL 0xcb8
#define REG_RFEINV 0xcbc
#define REG_AGCTR_B 0xe08
-#define REG_RXIGI_B 0xe50
#define REG_ANTWT 0x1904
#define REG_IQKFAILMSK 0x1bf0
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index 1dbe1cdbc3fd..af6b76937f1d 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -2690,48 +2690,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
}
}
-static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_rx_status *rx_status)
-{
- struct ieee80211_hdr *hdr;
- u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
- u8 *phy_status = NULL;
-
- memset(pkt_stat, 0, sizeof(*pkt_stat));
-
- pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
- pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
- pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
- pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
- GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
- pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
- pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
- pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
- pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
- pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
- pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
- pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc);
- pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
-
- /* drv_info_sz is in unit of 8-bytes */
- pkt_stat->drv_info_sz *= 8;
-
- /* c2h cmd pkt's rx/phy status is not interested */
- if (pkt_stat->is_c2h)
- return;
-
- hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
- pkt_stat->drv_info_sz);
- pkt_stat->hdr = hdr;
- if (pkt_stat->phy_status) {
- phy_status = rx_desc + desc_sz + pkt_stat->shift;
- query_phy_status(rtwdev, phy_status, pkt_stat);
- }
-
- rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
-}
-
static void
rtw8822c_set_write_tx_power_ref(struct rtw_dev *rtwdev, u8 *tx_pwr_ref_cck,
u8 *tx_pwr_ref_ofdm)
@@ -4874,13 +4832,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = {
RTW_PWR_CMD_END, 0, 0},
};
-static const struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = {
+static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822c[] = {
trans_carddis_to_cardemu_8822c,
trans_cardemu_to_act_8822c,
NULL
};
-static const struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = {
+static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822c[] = {
trans_act_to_cardemu_8822c,
trans_cardemu_to_carddis_8822c,
NULL
@@ -4925,16 +4883,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8822c = {
.n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8822c),
};
-static const struct rtw_rfe_def rtw8822c_rfe_defs[] = {
- [0] = RTW_DEF_RFE(8822c, 0, 0),
- [1] = RTW_DEF_RFE(8822c, 0, 0),
- [2] = RTW_DEF_RFE(8822c, 0, 0),
- [3] = RTW_DEF_RFE(8822c, 0, 0),
- [4] = RTW_DEF_RFE(8822c, 0, 0),
- [5] = RTW_DEF_RFE(8822c, 0, 5),
- [6] = RTW_DEF_RFE(8822c, 0, 0),
-};
-
static const struct rtw_hw_reg rtw8822c_dig[] = {
[0] = { .addr = 0x1d70, .mask = 0x7f },
[1] = { .addr = 0x1d70, .mask = 0x7f00 },
@@ -4972,7 +4920,7 @@ static const struct rtw_rqpn rqpn_table_8822c[] = {
RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
};
-static struct rtw_prioq_addrs prioq_addrs_8822c = {
+static const struct rtw_prioq_addrs prioq_addrs_8822c = {
.prio[RTW_DMA_MAPPING_EXTRA] = {
.rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
},
@@ -4988,10 +4936,12 @@ static struct rtw_prioq_addrs prioq_addrs_8822c = {
.wsize = true,
};
-static struct rtw_chip_ops rtw8822c_ops = {
+static const struct rtw_chip_ops rtw8822c_ops = {
+ .power_on = rtw_power_on,
+ .power_off = rtw_power_off,
.phy_set_param = rtw8822c_phy_set_param,
.read_efuse = rtw8822c_read_efuse,
- .query_rx_desc = rtw8822c_query_rx_desc,
+ .query_phy_status = query_phy_status,
.set_channel = rtw8822c_set_channel,
.mac_init = rtw8822c_mac_init,
.dump_fw_crash = rtw8822c_dump_fw_crash,
@@ -5278,7 +5228,7 @@ static const u8 rtw8822c_pwrtrk_2g_cck_a_p[RTW_PWR_TRK_TBL_SZ] = {
18, 18, 19, 20, 21, 22, 23, 24, 24, 25
};
-static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = {
+static const struct rtw_pwr_track_tbl rtw8822c_pwr_track_type0_tbl = {
.pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1],
.pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2],
.pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3],
@@ -5301,7 +5251,17 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = {
.pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p,
};
-static struct rtw_hw_reg_offset rtw8822c_edcca_th[] = {
+static const struct rtw_rfe_def rtw8822c_rfe_defs[] = {
+ [0] = RTW_DEF_RFE(8822c, 0, 0, 0),
+ [1] = RTW_DEF_RFE(8822c, 0, 0, 0),
+ [2] = RTW_DEF_RFE(8822c, 0, 0, 0),
+ [3] = RTW_DEF_RFE(8822c, 0, 0, 0),
+ [4] = RTW_DEF_RFE(8822c, 0, 0, 0),
+ [5] = RTW_DEF_RFE(8822c, 0, 5, 0),
+ [6] = RTW_DEF_RFE(8822c, 0, 0, 0),
+};
+
+static const struct rtw_hw_reg_offset rtw8822c_edcca_th[] = {
[EDCCA_TH_L2H_IDX] = {
{.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80
},
@@ -5371,6 +5331,9 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
.page_size = TX_PAGE_SIZE,
.dig_min = 0x20,
.usb_tx_agg_desc_num = 3,
+ .hw_feature_report = true,
+ .c2h_ra_report_size = 7,
+ .old_datarate_fb_limit = false,
.default_1ss_tx_path = BB_PATH_A,
.path_div_supported = true,
.ht_supported = true,
@@ -5397,7 +5360,6 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
.rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs),
.en_dis_dpd = true,
.dpd_ratemask = DIS_DPD_RATEALL,
- .pwr_track_tbl = &rtw8822c_rtw_pwr_track_tbl,
.iqk_threshold = 8,
.lck_threshold = 8,
.bfer_su_max_num = 2,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
new file mode 100644
index 000000000000..71e61b9c0bec
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
@@ -0,0 +1,1989 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#include <linux/usb.h>
+#include "main.h"
+#include "coex.h"
+#include "phy.h"
+#include "rtw88xxa.h"
+#include "mac.h"
+#include "reg.h"
+#include "sec.h"
+#include "debug.h"
+#include "bf.h"
+#include "efuse.h"
+#include "usb.h"
+
+void rtw88xxa_efuse_grant(struct rtw_dev *rtwdev, bool on)
+{
+ if (on) {
+ rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
+
+ rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
+ rtw_write16_set(rtwdev, REG_SYS_CLKR,
+ BIT_LOADER_CLK_EN | BIT_ANA8M);
+ } else {
+ rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+ }
+}
+EXPORT_SYMBOL(rtw88xxa_efuse_grant);
+
+static void rtw8812a_read_amplifier_type(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ efuse->ext_pa_2g = (efuse->pa_type_2g & BIT(5)) &&
+ (efuse->pa_type_2g & BIT(4));
+ efuse->ext_lna_2g = (efuse->lna_type_2g & BIT(7)) &&
+ (efuse->lna_type_2g & BIT(3));
+
+ efuse->ext_pa_5g = (efuse->pa_type_5g & BIT(1)) &&
+ (efuse->pa_type_5g & BIT(0));
+ efuse->ext_lna_5g = (efuse->lna_type_5g & BIT(7)) &&
+ (efuse->lna_type_5g & BIT(3));
+
+ /* For rtw_phy_cond2: */
+ if (efuse->ext_pa_2g) {
+ u8 ext_type_pa_2g_a = u8_get_bits(efuse->lna_type_2g, BIT(2));
+ u8 ext_type_pa_2g_b = u8_get_bits(efuse->lna_type_2g, BIT(6));
+
+ efuse->gpa_type = (ext_type_pa_2g_b << 2) | ext_type_pa_2g_a;
+ }
+
+ if (efuse->ext_pa_5g) {
+ u8 ext_type_pa_5g_a = u8_get_bits(efuse->lna_type_5g, BIT(2));
+ u8 ext_type_pa_5g_b = u8_get_bits(efuse->lna_type_5g, BIT(6));
+
+ efuse->apa_type = (ext_type_pa_5g_b << 2) | ext_type_pa_5g_a;
+ }
+
+ if (efuse->ext_lna_2g) {
+ u8 ext_type_lna_2g_a = u8_get_bits(efuse->lna_type_2g,
+ BIT(1) | BIT(0));
+ u8 ext_type_lna_2g_b = u8_get_bits(efuse->lna_type_2g,
+ BIT(5) | BIT(4));
+
+ efuse->glna_type = (ext_type_lna_2g_b << 2) | ext_type_lna_2g_a;
+ }
+
+ if (efuse->ext_lna_5g) {
+ u8 ext_type_lna_5g_a = u8_get_bits(efuse->lna_type_5g,
+ BIT(1) | BIT(0));
+ u8 ext_type_lna_5g_b = u8_get_bits(efuse->lna_type_5g,
+ BIT(5) | BIT(4));
+
+ efuse->alna_type = (ext_type_lna_5g_b << 2) | ext_type_lna_5g_a;
+ }
+}
+
+static void rtw8812a_read_rfe_type(struct rtw_dev *rtwdev,
+ struct rtw88xxa_efuse *map)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ if (map->rfe_option == 0xff) {
+ if (rtwdev->hci.type == RTW_HCI_TYPE_USB)
+ efuse->rfe_option = 0;
+ else if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE)
+ efuse->rfe_option = 2;
+ else
+ efuse->rfe_option = 4;
+ } else if (map->rfe_option & BIT(7)) {
+ if (efuse->ext_lna_5g) {
+ if (efuse->ext_pa_5g) {
+ if (efuse->ext_lna_2g && efuse->ext_pa_2g)
+ efuse->rfe_option = 3;
+ else
+ efuse->rfe_option = 0;
+ } else {
+ efuse->rfe_option = 2;
+ }
+ } else {
+ efuse->rfe_option = 4;
+ }
+ } else {
+ efuse->rfe_option = map->rfe_option & 0x3f;
+
+ /* Due to other customer already use incorrect EFUSE map for
+ * their product. We need to add workaround to prevent to
+ * modify spec and notify all customer to revise the IC 0xca
+ * content.
+ */
+ if (efuse->rfe_option == 4 &&
+ (efuse->ext_pa_5g || efuse->ext_pa_2g ||
+ efuse->ext_lna_5g || efuse->ext_lna_2g)) {
+ if (rtwdev->hci.type == RTW_HCI_TYPE_USB)
+ efuse->rfe_option = 0;
+ else if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE)
+ efuse->rfe_option = 2;
+ }
+ }
+}
+
+static void rtw88xxa_read_usb_type(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_hal *hal = &rtwdev->hal;
+ u8 antenna = 0;
+ u8 wmode = 0;
+ u8 val8, i;
+
+ efuse->hw_cap.bw = BIT(RTW_CHANNEL_WIDTH_20) |
+ BIT(RTW_CHANNEL_WIDTH_40) |
+ BIT(RTW_CHANNEL_WIDTH_80);
+ efuse->hw_cap.ptcl = EFUSE_HW_CAP_PTCL_VHT;
+
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A)
+ efuse->hw_cap.nss = 1;
+ else
+ efuse->hw_cap.nss = 2;
+
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A)
+ goto print_hw_cap;
+
+ for (i = 0; i < 2; i++) {
+ rtw_read8_physical_efuse(rtwdev, 1019 - i, &val8);
+
+ antenna = u8_get_bits(val8, GENMASK(7, 5));
+ if (antenna)
+ break;
+ antenna = u8_get_bits(val8, GENMASK(3, 1));
+ if (antenna)
+ break;
+ }
+
+ for (i = 0; i < 2; i++) {
+ rtw_read8_physical_efuse(rtwdev, 1021 - i, &val8);
+
+ wmode = u8_get_bits(val8, GENMASK(3, 2));
+ if (wmode)
+ break;
+ }
+
+ if (antenna == 1) {
+ rtw_info(rtwdev, "This RTL8812AU says it is 1T1R.\n");
+
+ efuse->hw_cap.nss = 1;
+ hal->rf_type = RF_1T1R;
+ hal->rf_path_num = 1;
+ hal->rf_phy_num = 1;
+ hal->antenna_tx = BB_PATH_A;
+ hal->antenna_rx = BB_PATH_A;
+ } else {
+ /* Override rtw_chip_parameter_setup(). It detects 8812au as 1T1R. */
+ efuse->hw_cap.nss = 2;
+ hal->rf_type = RF_2T2R;
+ hal->rf_path_num = 2;
+ hal->rf_phy_num = 2;
+ hal->antenna_tx = BB_PATH_AB;
+ hal->antenna_rx = BB_PATH_AB;
+
+ if (antenna == 2 && wmode == 2) {
+ rtw_info(rtwdev, "This RTL8812AU says it can't do VHT.\n");
+
+ /* Can't be EFUSE_HW_CAP_IGNORE and can't be
+ * EFUSE_HW_CAP_PTCL_VHT, so make it 1.
+ */
+ efuse->hw_cap.ptcl = 1;
+ efuse->hw_cap.bw &= ~BIT(RTW_CHANNEL_WIDTH_80);
+ }
+ }
+
+print_hw_cap:
+ rtw_dbg(rtwdev, RTW_DBG_EFUSE,
+ "hw cap: hci=0x%02x, bw=0x%02x, ptcl=0x%02x, ant_num=%d, nss=%d\n",
+ efuse->hw_cap.hci, efuse->hw_cap.bw, efuse->hw_cap.ptcl,
+ efuse->hw_cap.ant_num, efuse->hw_cap.nss);
+}
+
+int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw88xxa_efuse *map;
+ int i;
+
+ if (chip->id == RTW_CHIP_TYPE_8812A)
+ rtwdev->hal.cut_version += 1;
+
+ if (rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+ log_map, chip->log_efuse_size, true);
+
+ map = (struct rtw88xxa_efuse *)log_map;
+
+ efuse->rf_board_option = map->rf_board_option;
+ efuse->crystal_cap = map->xtal_k;
+ if (efuse->crystal_cap == 0xff)
+ efuse->crystal_cap = 0x20;
+ efuse->pa_type_2g = map->pa_type;
+ efuse->pa_type_5g = map->pa_type;
+ efuse->lna_type_2g = map->lna_type_2g;
+ efuse->lna_type_5g = map->lna_type_5g;
+ if (chip->id == RTW_CHIP_TYPE_8812A) {
+ rtw8812a_read_amplifier_type(rtwdev);
+ rtw8812a_read_rfe_type(rtwdev, map);
+
+ efuse->usb_mode_switch = u8_get_bits(map->usb_mode, BIT(1));
+ }
+ efuse->channel_plan = map->channel_plan;
+ efuse->country_code[0] = map->country_code[0];
+ efuse->country_code[1] = map->country_code[1];
+ efuse->bt_setting = map->rf_bt_setting;
+ efuse->regd = map->rf_board_option & 0x7;
+ efuse->thermal_meter[0] = map->thermal_meter;
+ efuse->thermal_meter[1] = map->thermal_meter;
+ efuse->thermal_meter_k = map->thermal_meter;
+ efuse->tx_bb_swing_setting_2g = map->tx_bb_swing_setting_2g;
+ efuse->tx_bb_swing_setting_5g = map->tx_bb_swing_setting_5g;
+
+ rtw88xxa_read_usb_type(rtwdev);
+
+ if (chip->id == RTW_CHIP_TYPE_8821A)
+ efuse->btcoex = rtw_read32_mask(rtwdev, REG_WL_BT_PWR_CTRL,
+ BIT_BT_FUNC_EN);
+ else
+ efuse->btcoex = (map->rf_board_option & 0xe0) == 0x20;
+ efuse->share_ant = !!(efuse->bt_setting & BIT(0));
+
+ /* No antenna diversity because it's disabled in the vendor driver */
+ efuse->ant_div_cfg = 0;
+
+ efuse->ant_div_type = map->rf_antenna_option;
+ if (efuse->ant_div_type == 0xff)
+ efuse->ant_div_type = 0x3;
+
+ for (i = 0; i < 4; i++)
+ efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
+
+ switch (rtw_hci_type(rtwdev)) {
+ case RTW_HCI_TYPE_USB:
+ if (chip->id == RTW_CHIP_TYPE_8821A)
+ ether_addr_copy(efuse->addr, map->rtw8821au.mac_addr);
+ else
+ ether_addr_copy(efuse->addr, map->rtw8812au.mac_addr);
+ break;
+ case RTW_HCI_TYPE_PCIE:
+ case RTW_HCI_TYPE_SDIO:
+ default:
+ /* unsupported now */
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(rtw88xxa_read_efuse);
+
+static void rtw88xxa_reset_8051(struct rtw_dev *rtwdev)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ u8 val8;
+
+ /* Reset MCU IO Wrapper */
+ rtw_write8_clr(rtwdev, REG_RSV_CTRL, BIT(1));
+ if (chip->id == RTW_CHIP_TYPE_8812A)
+ rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT(3));
+ else
+ rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT(0));
+
+ val8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN + 1);
+ rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, val8 & ~BIT(2));
+
+ /* Enable MCU IO Wrapper */
+ rtw_write8_clr(rtwdev, REG_RSV_CTRL, BIT(1));
+ if (chip->id == RTW_CHIP_TYPE_8812A)
+ rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT(3));
+ else
+ rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT(0));
+
+ rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, val8 | BIT(2));
+}
+
+/* A lightweight deinit function */
+static void rtw88xxau_hw_reset(struct rtw_dev *rtwdev)
+{
+ u8 val8;
+
+ if (!(rtw_read8(rtwdev, REG_MCUFW_CTRL) & BIT_RAM_DL_SEL))
+ return;
+
+ rtw88xxa_reset_8051(rtwdev);
+ rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00);
+
+ /* before BB reset should do clock gated */
+ rtw_write32_set(rtwdev, REG_FPGA0_XCD_RF_PARA, BIT(6));
+
+ /* reset BB */
+ rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
+
+ /* reset RF */
+ rtw_write8(rtwdev, REG_RF_CTRL, 0);
+
+ /* reset TRX path */
+ rtw_write16(rtwdev, REG_CR, 0);
+
+ /* reset MAC, reg0x5[1], auto FSM off */
+ rtw_write8_set(rtwdev, REG_APS_FSMCO + 1, APS_FSMCO_MAC_OFF >> 8);
+
+ /* check if reg0x5[1] auto cleared */
+ if (read_poll_timeout_atomic(rtw_read8, val8,
+ !(val8 & (APS_FSMCO_MAC_OFF >> 8)),
+ 1, 5000, false,
+ rtwdev, REG_APS_FSMCO + 1))
+ rtw_err(rtwdev, "%s: timed out waiting for 0x5[1]\n", __func__);
+
+ /* reg0x5[0], auto FSM on */
+ val8 |= APS_FSMCO_MAC_ENABLE >> 8;
+ rtw_write8(rtwdev, REG_APS_FSMCO + 1, val8);
+
+ rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT(4) | BIT(7));
+ rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT(4) | BIT(7));
+}
+
+static int rtw88xxau_init_power_on(struct rtw_dev *rtwdev)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ u16 val16;
+ int ret;
+
+ ret = rtw_pwr_seq_parser(rtwdev, chip->pwr_on_seq);
+ if (ret) {
+ rtw_err(rtwdev, "power on flow failed\n");
+ return ret;
+ }
+
+ rtw_write16(rtwdev, REG_CR, 0);
+ val16 = BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN |
+ BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN |
+ BIT_MAC_SEC_EN | BIT_32K_CAL_TMR_EN;
+ rtw_write16_set(rtwdev, REG_CR, val16);
+
+ if (chip->id == RTW_CHIP_TYPE_8821A) {
+ if (rtw_read8(rtwdev, REG_SYS_CFG1 + 3) & BIT(0))
+ rtw_write8_set(rtwdev, REG_LDO_SWR_CTRL, BIT(6));
+ }
+
+ return ret;
+}
+
+static int rtw88xxa_llt_write(struct rtw_dev *rtwdev, u32 address, u32 data)
+{
+ u32 value = BIT_LLT_WRITE_ACCESS | (address << 8) | data;
+ int count = 0;
+
+ rtw_write32(rtwdev, REG_LLT_INIT, value);
+
+ do {
+ if (!rtw_read32_mask(rtwdev, REG_LLT_INIT, BIT(31) | BIT(30)))
+ break;
+
+ if (count > 20) {
+ rtw_err(rtwdev, "Failed to poll write LLT done at %d!\n",
+ address);
+ return -EBUSY;
+ }
+ } while (++count);
+
+ return 0;
+}
+
+static int rtw88xxa_llt_init(struct rtw_dev *rtwdev, u32 boundary)
+{
+ u32 last_entry = 255;
+ int status = 0;
+ u32 i;
+
+ for (i = 0; i < boundary - 1; i++) {
+ status = rtw88xxa_llt_write(rtwdev, i, i + 1);
+ if (status)
+ return status;
+ }
+
+ status = rtw88xxa_llt_write(rtwdev, boundary - 1, 0xFF);
+ if (status)
+ return status;
+
+ for (i = boundary; i < last_entry; i++) {
+ status = rtw88xxa_llt_write(rtwdev, i, i + 1);
+ if (status)
+ return status;
+ }
+
+ status = rtw88xxa_llt_write(rtwdev, last_entry, boundary);
+
+ return status;
+}
+
+static void rtw88xxau_init_queue_reserved_page(struct rtw_dev *rtwdev)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+ const struct rtw_page_table *pg_tbl = NULL;
+ u16 pubq_num;
+ u32 val32;
+
+ switch (rtw_hci_type(rtwdev)) {
+ case RTW_HCI_TYPE_PCIE:
+ pg_tbl = &chip->page_table[1];
+ break;
+ case RTW_HCI_TYPE_USB:
+ if (rtwdev->hci.bulkout_num == 2)
+ pg_tbl = &chip->page_table[2];
+ else if (rtwdev->hci.bulkout_num == 3)
+ pg_tbl = &chip->page_table[3];
+ else if (rtwdev->hci.bulkout_num == 4)
+ pg_tbl = &chip->page_table[4];
+ break;
+ case RTW_HCI_TYPE_SDIO:
+ pg_tbl = &chip->page_table[0];
+ break;
+ default:
+ break;
+ }
+
+ pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num -
+ pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num;
+
+ val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num);
+ rtw_write32(rtwdev, REG_RQPN_NPQ, val32);
+
+ val32 = BIT_RQPN_HLP(pg_tbl->hq_num, pg_tbl->lq_num, pubq_num);
+ rtw_write32(rtwdev, REG_RQPN, val32);
+}
+
+static void rtw88xxau_init_tx_buffer_boundary(struct rtw_dev *rtwdev)
+{
+ struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+
+ rtw_write8(rtwdev, REG_BCNQ_BDNY, fifo->rsvd_boundary);
+ rtw_write8(rtwdev, REG_MGQ_BDNY, fifo->rsvd_boundary);
+ rtw_write8(rtwdev, REG_WMAC_LBK_BF_HD, fifo->rsvd_boundary);
+ rtw_write8(rtwdev, REG_TRXFF_BNDY, fifo->rsvd_boundary);
+ rtw_write8(rtwdev, REG_DWBCN0_CTRL + 1, fifo->rsvd_boundary);
+}
+
+static int rtw88xxau_init_queue_priority(struct rtw_dev *rtwdev)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ u8 bulkout_num = rtwdev->hci.bulkout_num;
+ const struct rtw_rqpn *rqpn = NULL;
+ u16 txdma_pq_map;
+
+ switch (rtw_hci_type(rtwdev)) {
+ case RTW_HCI_TYPE_PCIE:
+ rqpn = &chip->rqpn_table[1];
+ break;
+ case RTW_HCI_TYPE_USB:
+ if (bulkout_num == 2)
+ rqpn = &chip->rqpn_table[2];
+ else if (bulkout_num == 3)
+ rqpn = &chip->rqpn_table[3];
+ else if (bulkout_num == 4)
+ rqpn = &chip->rqpn_table[4];
+ else
+ return -EINVAL;
+ break;
+ case RTW_HCI_TYPE_SDIO:
+ rqpn = &chip->rqpn_table[0];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rtwdev->fifo.rqpn = rqpn;
+
+ txdma_pq_map = rtw_read16(rtwdev, REG_TXDMA_PQ_MAP) & 0x7;
+ txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi);
+ txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg);
+ txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk);
+ txdma_pq_map |= BIT_TXDMA_BEQ_MAP(rqpn->dma_map_be);
+ txdma_pq_map |= BIT_TXDMA_VIQ_MAP(rqpn->dma_map_vi);
+ txdma_pq_map |= BIT_TXDMA_VOQ_MAP(rqpn->dma_map_vo);
+ rtw_write16(rtwdev, REG_TXDMA_PQ_MAP, txdma_pq_map);
+
+ /* Packet in Hi Queue Tx immediately (No constraint for ATIM Period). */
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB && bulkout_num == 4)
+ rtw_write8(rtwdev, REG_HIQ_NO_LMT_EN, 0xff);
+
+ return 0;
+}
+
+static void rtw88xxa_init_wmac_setting(struct rtw_dev *rtwdev)
+{
+ rtw_write16(rtwdev, REG_RXFLTMAP0, 0xffff);
+ rtw_write16(rtwdev, REG_RXFLTMAP1, 0x0400);
+ rtw_write16(rtwdev, REG_RXFLTMAP2, 0xffff);
+
+ rtw_write32(rtwdev, REG_MAR, 0xffffffff);
+ rtw_write32(rtwdev, REG_MAR + 4, 0xffffffff);
+}
+
+static void rtw88xxa_init_adaptive_ctrl(struct rtw_dev *rtwdev)
+{
+ rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, 0xffff1);
+ rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x3030);
+}
+
+static void rtw88xxa_init_edca(struct rtw_dev *rtwdev)
+{
+ rtw_write16(rtwdev, REG_SPEC_SIFS, 0x100a);
+ rtw_write16(rtwdev, REG_MAC_SPEC_SIFS, 0x100a);
+
+ rtw_write16(rtwdev, REG_SIFS, 0x100a);
+ rtw_write16(rtwdev, REG_SIFS + 2, 0x100a);
+
+ rtw_write32(rtwdev, REG_EDCA_BE_PARAM, 0x005EA42B);
+ rtw_write32(rtwdev, REG_EDCA_BK_PARAM, 0x0000A44F);
+ rtw_write32(rtwdev, REG_EDCA_VI_PARAM, 0x005EA324);
+ rtw_write32(rtwdev, REG_EDCA_VO_PARAM, 0x002FA226);
+
+ rtw_write8(rtwdev, REG_USTIME_TSF, 0x50);
+ rtw_write8(rtwdev, REG_USTIME_EDCA, 0x50);
+}
+
+static void rtw88xxau_tx_aggregation(struct rtw_dev *rtwdev)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+
+ rtw_write32_mask(rtwdev, REG_DWBCN0_CTRL, 0xf0,
+ chip->usb_tx_agg_desc_num);
+
+ if (chip->id == RTW_CHIP_TYPE_8821A)
+ rtw_write8(rtwdev, REG_DWBCN1_CTRL,
+ chip->usb_tx_agg_desc_num << 1);
+}
+
+static void rtw88xxa_init_beacon_parameters(struct rtw_dev *rtwdev)
+{
+ u16 val16;
+
+ val16 = (BIT_DIS_TSF_UDT << 8) | BIT_DIS_TSF_UDT;
+ if (rtwdev->efuse.btcoex)
+ val16 |= BIT_EN_BCN_FUNCTION;
+ rtw_write16(rtwdev, REG_BCN_CTRL, val16);
+
+ rtw_write32_mask(rtwdev, REG_TBTT_PROHIBIT, 0xfffff, WLAN_TBTT_TIME);
+ rtw_write8(rtwdev, REG_DRVERLYINT, 0x05);
+ rtw_write8(rtwdev, REG_BCNDMATIM, WLAN_BCN_DMA_TIME);
+ rtw_write16(rtwdev, REG_BCNTCFG, 0x4413);
+}
+
+static void rtw88xxa_phy_bb_config(struct rtw_dev *rtwdev)
+{
+ u8 val8, crystal_cap;
+
+ /* power on BB/RF domain */
+ val8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN);
+ val8 |= BIT_FEN_USBA;
+ rtw_write8(rtwdev, REG_SYS_FUNC_EN, val8);
+
+ /* toggle BB reset */
+ val8 |= BIT_FEN_BB_RSTB | BIT_FEN_BB_GLB_RST;
+ rtw_write8(rtwdev, REG_SYS_FUNC_EN, val8);
+
+ rtw_write8(rtwdev, REG_RF_CTRL,
+ BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB);
+ rtw_write8(rtwdev, REG_RF_B_CTRL,
+ BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB);
+
+ rtw_load_table(rtwdev, rtwdev->chip->bb_tbl);
+ rtw_load_table(rtwdev, rtwdev->chip->agc_tbl);
+
+ crystal_cap = rtwdev->efuse.crystal_cap & 0x3F;
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
+ rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x7FF80000,
+ crystal_cap | (crystal_cap << 6));
+ else
+ rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x00FFF000,
+ crystal_cap | (crystal_cap << 6));
+}
+
+static void rtw88xxa_phy_rf_config(struct rtw_dev *rtwdev)
+{
+ u8 rf_path;
+
+ for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++)
+ rtw_load_table(rtwdev, rtwdev->chip->rf_tbl[rf_path]);
+}
+
+static void rtw8812a_config_1t(struct rtw_dev *rtwdev)
+{
+ /* BB OFDM RX Path_A */
+ rtw_write32_mask(rtwdev, REG_RXPSEL, 0xff, 0x11);
+
+ /* BB OFDM TX Path_A */
+ rtw_write32_mask(rtwdev, REG_TXPSEL, MASKLWORD, 0x1111);
+
+ /* BB CCK R/Rx Path_A */
+ rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0c000000, 0x0);
+
+ /* MCS support */
+ rtw_write32_mask(rtwdev, REG_RX_MCS_LIMIT, 0xc0000060, 0x4);
+
+ /* RF Path_B HSSI OFF */
+ rtw_write32_mask(rtwdev, REG_3WIRE_SWB, 0xf, 0x4);
+
+ /* RF Path_B Power Down */
+ rtw_write32_mask(rtwdev, REG_LSSI_WRITE_B, MASKDWORD, 0);
+
+ /* ADDA Path_B OFF */
+ rtw_write32_mask(rtwdev, REG_AFE_PWR1_B, MASKDWORD, 0);
+ rtw_write32_mask(rtwdev, REG_AFE_PWR2_B, MASKDWORD, 0);
+}
+
+static const u32 rtw88xxa_txscale_tbl[] = {
+ 0x081, 0x088, 0x090, 0x099, 0x0a2, 0x0ac, 0x0b6, 0x0c0, 0x0cc, 0x0d8,
+ 0x0e5, 0x0f2, 0x101, 0x110, 0x120, 0x131, 0x143, 0x156, 0x16a, 0x180,
+ 0x197, 0x1af, 0x1c8, 0x1e3, 0x200, 0x21e, 0x23e, 0x261, 0x285, 0x2ab,
+ 0x2d3, 0x2fe, 0x32b, 0x35c, 0x38e, 0x3c4, 0x3fe
+};
+
+static u32 rtw88xxa_get_bb_swing(struct rtw_dev *rtwdev, u8 band, u8 path)
+{
+ static const u32 swing2setting[4] = {0x200, 0x16a, 0x101, 0x0b6};
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ u8 tx_bb_swing;
+
+ if (band == RTW_BAND_2G)
+ tx_bb_swing = efuse->tx_bb_swing_setting_2g;
+ else
+ tx_bb_swing = efuse->tx_bb_swing_setting_5g;
+
+ if (path == RF_PATH_B)
+ tx_bb_swing >>= 2;
+ tx_bb_swing &= 0x3;
+
+ return swing2setting[tx_bb_swing];
+}
+
+static u8 rtw88xxa_get_swing_index(struct rtw_dev *rtwdev)
+{
+ u32 swing, table_value;
+ u8 i;
+
+ swing = rtw88xxa_get_bb_swing(rtwdev, rtwdev->hal.current_band_type,
+ RF_PATH_A);
+
+ for (i = 0; i < ARRAY_SIZE(rtw88xxa_txscale_tbl); i++) {
+ table_value = rtw88xxa_txscale_tbl[i];
+ if (swing == table_value)
+ return i;
+ }
+
+ return 24;
+}
+
+static void rtw88xxa_pwrtrack_init(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u8 path;
+
+ dm_info->default_ofdm_index = rtw88xxa_get_swing_index(rtwdev);
+
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A)
+ dm_info->default_cck_index = 0;
+ else
+ dm_info->default_cck_index = 24;
+
+ for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) {
+ ewma_thermal_init(&dm_info->avg_thermal[path]);
+ dm_info->delta_power_index[path] = 0;
+ dm_info->delta_power_index_last[path] = 0;
+ }
+
+ dm_info->pwr_trk_triggered = false;
+ dm_info->pwr_trk_init_trigger = true;
+ dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
+}
+
+void rtw88xxa_power_off(struct rtw_dev *rtwdev,
+ const struct rtw_pwr_seq_cmd *const *enter_lps_flow)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ enum usb_device_speed speed = rtwusb->udev->speed;
+ u16 ori_fsmc0;
+ u8 reg_cr;
+
+ reg_cr = rtw_read8(rtwdev, REG_CR);
+
+ /* Already powered off */
+ if (reg_cr == 0 || reg_cr == 0xEA)
+ return;
+
+ rtw_hci_stop(rtwdev);
+
+ if (!rtwdev->efuse.btcoex)
+ rtw_write16_clr(rtwdev, REG_GPIO_MUXCFG, BIT_EN_SIC);
+
+ /* set Reg 0xf008[3:4] to 2'11 to enable U1/U2 Mode in USB3.0. */
+ if (speed == USB_SPEED_SUPER)
+ rtw_write8_set(rtwdev, REG_USB_MOD, 0x18);
+
+ rtw_write32(rtwdev, REG_HISR0, 0xffffffff);
+ rtw_write32(rtwdev, REG_HISR1, 0xffffffff);
+ rtw_write32(rtwdev, REG_HIMR0, 0);
+ rtw_write32(rtwdev, REG_HIMR1, 0);
+
+ if (rtwdev->efuse.btcoex)
+ rtw_coex_power_off_setting(rtwdev);
+
+ ori_fsmc0 = rtw_read16(rtwdev, REG_APS_FSMCO);
+ rtw_write16(rtwdev, REG_APS_FSMCO, ori_fsmc0 & ~APS_FSMCO_HW_POWERDOWN);
+
+ /* Stop Tx Report Timer. */
+ rtw_write8_clr(rtwdev, REG_TX_RPT_CTRL, BIT(1));
+
+ /* Stop Rx */
+ rtw_write8(rtwdev, REG_CR, 0);
+
+ rtw_pwr_seq_parser(rtwdev, enter_lps_flow);
+
+ if (rtw_read8(rtwdev, REG_MCUFW_CTRL) & BIT_RAM_DL_SEL)
+ rtw88xxa_reset_8051(rtwdev);
+
+ rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT(2));
+ rtw_write8(rtwdev, REG_MCUFW_CTRL, 0);
+
+ rtw_pwr_seq_parser(rtwdev, rtwdev->chip->pwr_off_seq);
+
+ if (ori_fsmc0 & APS_FSMCO_HW_POWERDOWN)
+ rtw_write16_set(rtwdev, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN);
+
+ clear_bit(RTW_FLAG_POWERON, rtwdev->flags);
+}
+EXPORT_SYMBOL(rtw88xxa_power_off);
+
+static void rtw88xxa_set_channel_bb_swing(struct rtw_dev *rtwdev, u8 band)
+{
+ rtw_write32_mask(rtwdev, REG_TXSCALE_A, BB_SWING_MASK,
+ rtw88xxa_get_bb_swing(rtwdev, band, RF_PATH_A));
+ rtw_write32_mask(rtwdev, REG_TXSCALE_B, BB_SWING_MASK,
+ rtw88xxa_get_bb_swing(rtwdev, band, RF_PATH_B));
+ rtw88xxa_pwrtrack_init(rtwdev);
+}
+
+static void rtw8821a_set_ext_band_switch(struct rtw_dev *rtwdev, u8 band)
+{
+ rtw_write32_mask(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN, 0);
+ rtw_write32_mask(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL, 1);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0xf, 7);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0xf0, 7);
+
+ if (band == RTW_BAND_2G)
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(29) | BIT(28), 1);
+ else
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(29) | BIT(28), 2);
+}
+
+static void rtw8821a_phy_set_rfe_reg_24g(struct rtw_dev *rtwdev)
+{
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ /* Turn off RF PA and LNA */
+
+ /* 0xCB0[15:12] = 0x7 (LNA_On)*/
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF000, 0x7);
+ /* 0xCB0[7:4] = 0x7 (PAPE_A)*/
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF0, 0x7);
+
+ if (efuse->ext_lna_2g) {
+ /* Turn on 2.4G External LNA */
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 1);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0);
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x2);
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x2);
+ } else {
+ /* Bypass 2.4G External LNA */
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 0);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0);
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x7);
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x7);
+ }
+}
+
+static void rtw8821a_phy_set_rfe_reg_5g(struct rtw_dev *rtwdev)
+{
+ /* Turn ON RF PA and LNA */
+
+ /* 0xCB0[15:12] = 0x7 (LNA_On)*/
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF000, 0x5);
+ /* 0xCB0[7:4] = 0x7 (PAPE_A)*/
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF0, 0x4);
+
+ /* Bypass 2.4G External LNA */
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 0);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0);
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x7);
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x7);
+}
+
+static void rtw8812a_phy_set_rfe_reg_24g(struct rtw_dev *rtwdev)
+{
+ switch (rtwdev->efuse.rfe_option) {
+ case 0:
+ case 2:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
+ break;
+ case 1:
+ if (rtwdev->efuse.btcoex) {
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xffffff, 0x777777);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0x33f00000, 0x000);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
+ } else {
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
+ }
+ break;
+ case 3:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x54337770);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x54337770);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
+ rtw_write32_mask(rtwdev, REG_ANTSEL_SW, 0x00000303, 0x1);
+ break;
+ case 4:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x001);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x001);
+ break;
+ case 5:
+ rtw_write8(rtwdev, REG_RFE_PINMUX_A + 2, 0x77);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
+ rtw_write8_clr(rtwdev, REG_RFE_INV_A + 3, BIT(0));
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
+ break;
+ case 6:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x07772770);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x07772770);
+ rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077);
+ rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077);
+ break;
+ default:
+ break;
+ }
+}
+
+static void rtw8812a_phy_set_rfe_reg_5g(struct rtw_dev *rtwdev)
+{
+ switch (rtwdev->efuse.rfe_option) {
+ case 0:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337717);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
+ break;
+ case 1:
+ if (rtwdev->efuse.btcoex) {
+ rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xffffff, 0x337717);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0x33f00000, 0x000);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
+ } else {
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337717);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
+ }
+ break;
+ case 2:
+ case 4:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337777);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337777);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
+ break;
+ case 3:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x54337717);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x54337717);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
+ rtw_write32_mask(rtwdev, REG_ANTSEL_SW, 0x00000303, 0x1);
+ break;
+ case 5:
+ rtw_write8(rtwdev, REG_RFE_PINMUX_A + 2, 0x33);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337777);
+ rtw_write8_set(rtwdev, REG_RFE_INV_A + 3, BIT(0));
+ rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
+ break;
+ case 6:
+ rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x07737717);
+ rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x07737717);
+ rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077);
+ rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077);
+ break;
+ default:
+ break;
+ }
+}
+
+static void rtw88xxa_switch_band(struct rtw_dev *rtwdev, u8 new_band, u8 bw)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ u16 basic_rates, reg_41a;
+
+ /* 8811au one antenna module doesn't support antenna div, so driver must
+ * control antenna band, otherwise one of the band will have issue
+ */
+ if (chip->id == RTW_CHIP_TYPE_8821A && !rtwdev->efuse.btcoex &&
+ rtwdev->efuse.ant_div_cfg == 0)
+ rtw8821a_set_ext_band_switch(rtwdev, new_band);
+
+ if (new_band == RTW_BAND_2G) {
+ rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST);
+
+ if (chip->id == RTW_CHIP_TYPE_8821A) {
+ rtw8821a_phy_set_rfe_reg_24g(rtwdev);
+
+ rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 0);
+ } else {
+ rtw_write32_mask(rtwdev, REG_BWINDICATION, 0x3, 0x1);
+ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(17, 13), 0x17);
+
+ if (bw == RTW_CHANNEL_WIDTH_20 &&
+ rtwdev->hal.rf_type == RF_1T1R &&
+ !rtwdev->efuse.ext_lna_2g)
+ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x02);
+ else
+ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x04);
+
+ rtw_write32_mask(rtwdev, REG_CCASEL, 0x3, 0);
+
+ rtw8812a_phy_set_rfe_reg_24g(rtwdev);
+ }
+
+ rtw_write32_mask(rtwdev, REG_TXPSEL, 0xf0, 0x1);
+ rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0f000000, 0x1);
+
+ basic_rates = BIT(DESC_RATE1M) | BIT(DESC_RATE2M) |
+ BIT(DESC_RATE5_5M) | BIT(DESC_RATE11M) |
+ BIT(DESC_RATE6M) | BIT(DESC_RATE12M) |
+ BIT(DESC_RATE24M);
+ rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, basic_rates);
+
+ rtw_write8_clr(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN);
+ } else { /* RTW_BAND_5G */
+ if (chip->id == RTW_CHIP_TYPE_8821A)
+ rtw8821a_phy_set_rfe_reg_5g(rtwdev);
+
+ rtw_write8_set(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN);
+
+ read_poll_timeout_atomic(rtw_read16, reg_41a, (reg_41a & 0x30) == 0x30,
+ 50, 2500, false, rtwdev, REG_TXPKT_EMPTY);
+
+ rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST);
+
+ if (chip->id == RTW_CHIP_TYPE_8821A) {
+ rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 1);
+ } else {
+ rtw_write32_mask(rtwdev, REG_BWINDICATION, 0x3, 0x2);
+ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(17, 13), 0x15);
+ rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x04);
+
+ rtw_write32_mask(rtwdev, REG_CCASEL, 0x3, 1);
+
+ rtw8812a_phy_set_rfe_reg_5g(rtwdev);
+ }
+
+ rtw_write32_mask(rtwdev, REG_TXPSEL, 0xf0, 0);
+ rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0f000000, 0xf);
+
+ basic_rates = BIT(DESC_RATE6M) | BIT(DESC_RATE12M) |
+ BIT(DESC_RATE24M);
+ rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, basic_rates);
+ }
+
+ rtw88xxa_set_channel_bb_swing(rtwdev, new_band);
+}
+
+int rtw88xxa_power_on(struct rtw_dev *rtwdev)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ struct rtw_hal *hal = &rtwdev->hal;
+ int ret;
+
+ if (test_bit(RTW_FLAG_POWERON, rtwdev->flags))
+ return 0;
+
+ /* Override rtw_chip_efuse_info_setup() */
+ if (chip->id == RTW_CHIP_TYPE_8821A)
+ efuse->btcoex = rtw_read32_mask(rtwdev, REG_WL_BT_PWR_CTRL,
+ BIT_BT_FUNC_EN);
+
+ /* Override rtw_chip_efuse_info_setup() */
+ if (chip->id == RTW_CHIP_TYPE_8812A)
+ rtw8812a_read_amplifier_type(rtwdev);
+
+ ret = rtw_hci_setup(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to setup hci\n");
+ goto err;
+ }
+
+ /* Revise for U2/U3 switch we can not update RF-A/B reset.
+ * Reset after MAC power on to prevent RF R/W error.
+ * Is it a right method?
+ */
+ if (chip->id == RTW_CHIP_TYPE_8812A) {
+ rtw_write8(rtwdev, REG_RF_CTRL, 5);
+ rtw_write8(rtwdev, REG_RF_CTRL, 7);
+ rtw_write8(rtwdev, REG_RF_B_CTRL, 5);
+ rtw_write8(rtwdev, REG_RF_B_CTRL, 7);
+ }
+
+ /* If HW didn't go through a complete de-initial procedure,
+ * it probably occurs some problem for double initial
+ * procedure.
+ */
+ rtw88xxau_hw_reset(rtwdev);
+
+ ret = rtw88xxau_init_power_on(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to power on\n");
+ goto err;
+ }
+
+ ret = rtw_set_trx_fifo_info(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to set trx fifo info\n");
+ goto err;
+ }
+
+ ret = rtw88xxa_llt_init(rtwdev, rtwdev->fifo.rsvd_boundary);
+ if (ret) {
+ rtw_err(rtwdev, "failed to init llt\n");
+ goto err;
+ }
+
+ rtw_write32_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
+
+ ret = rtw_wait_firmware_completion(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to wait firmware completion\n");
+ goto err_off;
+ }
+
+ ret = rtw_download_firmware(rtwdev, &rtwdev->fw);
+ if (ret) {
+ rtw_err(rtwdev, "failed to download firmware\n");
+ goto err_off;
+ }
+
+ rtw_write8(rtwdev, REG_HMETFR, 0xf);
+
+ rtw_load_table(rtwdev, chip->mac_tbl);
+
+ rtw88xxau_init_queue_reserved_page(rtwdev);
+ rtw88xxau_init_tx_buffer_boundary(rtwdev);
+ rtw88xxau_init_queue_priority(rtwdev);
+
+ rtw_write16(rtwdev, REG_TRXFF_BNDY + 2,
+ chip->rxff_size - REPORT_BUF - 1);
+
+ if (chip->id == RTW_CHIP_TYPE_8812A)
+ rtw_write8(rtwdev, REG_PBP,
+ u8_encode_bits(PBP_512, PBP_TX_MASK) |
+ u8_encode_bits(PBP_64, PBP_RX_MASK));
+
+ rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE);
+
+ rtw_write32(rtwdev, REG_HIMR0, 0);
+ rtw_write32(rtwdev, REG_HIMR1, 0);
+
+ rtw_write32_mask(rtwdev, REG_CR, 0x30000, 0x2);
+
+ rtw88xxa_init_wmac_setting(rtwdev);
+ rtw88xxa_init_adaptive_ctrl(rtwdev);
+ rtw88xxa_init_edca(rtwdev);
+
+ rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL, BIT(7));
+ rtw_write8(rtwdev, REG_ACKTO, 0x80);
+
+ rtw88xxau_tx_aggregation(rtwdev);
+
+ rtw88xxa_init_beacon_parameters(rtwdev);
+ rtw_write8(rtwdev, REG_BCN_MAX_ERR, 0xff);
+
+ rtw_hci_interface_cfg(rtwdev);
+
+ /* usb3 rx interval */
+ rtw_write8(rtwdev, REG_USB3_RXITV, 0x01);
+
+ /* burst length=4, set 0x3400 for burst length=2 */
+ rtw_write16(rtwdev, REG_RXDMA_STATUS, 0x7400);
+ rtw_write8(rtwdev, REG_RXDMA_STATUS + 1, 0xf5);
+
+ /* 0x456 = 0x70, sugguested by Zhilin */
+ if (chip->id == RTW_CHIP_TYPE_8821A)
+ rtw_write8(rtwdev, REG_AMPDU_MAX_TIME, 0x5e);
+ else
+ rtw_write8(rtwdev, REG_AMPDU_MAX_TIME, 0x70);
+
+ rtw_write32(rtwdev, REG_AMPDU_MAX_LENGTH, 0xffffffff);
+ rtw_write8(rtwdev, REG_USTIME_TSF, 0x50);
+ rtw_write8(rtwdev, REG_USTIME_EDCA, 0x50);
+
+ if (rtwusb->udev->speed == USB_SPEED_SUPER)
+ /* Disable U1/U2 Mode to avoid 2.5G spur in USB3.0. */
+ rtw_write8_clr(rtwdev, REG_USB_MOD, BIT(4) | BIT(3));
+
+ rtw_write8_set(rtwdev, REG_SINGLE_AMPDU_CTRL, BIT_EN_SINGLE_APMDU);
+
+ /* for VHT packet length 11K */
+ rtw_write8(rtwdev, REG_RX_PKT_LIMIT, 0x18);
+
+ rtw_write8(rtwdev, REG_PIFS, 0x00);
+
+ if (chip->id == RTW_CHIP_TYPE_8821A) {
+ /* 0x0a0a too small, it can't pass AC logo. change to 0x1f1f */
+ rtw_write16(rtwdev, REG_MAX_AGGR_NUM, 0x1f1f);
+ rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL, 0x80);
+ rtw_write32(rtwdev, REG_FAST_EDCA_CTRL, 0x03087777);
+ } else {
+ rtw_write16(rtwdev, REG_MAX_AGGR_NUM, 0x1f1f);
+ rtw_write8_clr(rtwdev, REG_FWHW_TXQ_CTRL, BIT(7));
+ }
+
+ /* to prevent mac is reseted by bus. */
+ rtw_write8_set(rtwdev, REG_RSV_CTRL, BIT(5) | BIT(6));
+
+ /* ARFB table 9 for 11ac 5G 2SS */
+ rtw_write32(rtwdev, REG_ARFR0, 0x00000010);
+ rtw_write32(rtwdev, REG_ARFRH0, 0xfffff000);
+
+ /* ARFB table 10 for 11ac 5G 1SS */
+ rtw_write32(rtwdev, REG_ARFR1_V1, 0x00000010);
+ rtw_write32(rtwdev, REG_ARFRH1_V1, 0x003ff000);
+
+ /* ARFB table 11 for 11ac 24G 1SS */
+ rtw_write32(rtwdev, REG_ARFR2_V1, 0x00000015);
+ rtw_write32(rtwdev, REG_ARFRH2_V1, 0x003ff000);
+
+ /* ARFB table 12 for 11ac 24G 2SS */
+ rtw_write32(rtwdev, REG_ARFR3_V1, 0x00000015);
+ rtw_write32(rtwdev, REG_ARFRH3_V1, 0xffcff000);
+
+ rtw_write8_set(rtwdev, REG_CR, BIT_MACTXEN | BIT_MACRXEN);
+
+ rtw88xxa_phy_bb_config(rtwdev);
+ rtw88xxa_phy_rf_config(rtwdev);
+
+ if (chip->id == RTW_CHIP_TYPE_8812A && hal->rf_path_num == 1)
+ rtw8812a_config_1t(rtwdev);
+
+ rtw88xxa_switch_band(rtwdev, RTW_BAND_2G, RTW_CHANNEL_WIDTH_20);
+
+ rtw_write32(rtwdev, RTW_SEC_CMD_REG, BIT(31) | BIT(30));
+
+ rtw_write8(rtwdev, REG_HWSEQ_CTRL, 0xff);
+ rtw_write32(rtwdev, REG_BAR_MODE_CTRL, 0x0201ffff);
+ rtw_write8(rtwdev, REG_NAV_CTRL + 2, 0);
+
+ rtw_write8_clr(rtwdev, REG_GPIO_MUXCFG, BIT(5));
+
+ rtw_phy_init(rtwdev);
+
+ rtw88xxa_pwrtrack_init(rtwdev);
+
+ /* 0x4c6[3] 1: RTS BW = Data BW
+ * 0: RTS BW depends on CCA / secondary CCA result.
+ */
+ rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT(3));
+
+ /* enable Tx report. */
+ rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, 0x0f);
+
+ /* Pretx_en, for WEP/TKIP SEC */
+ rtw_write8(rtwdev, REG_EARLY_MODE_CONTROL + 3, 0x01);
+
+ rtw_write16(rtwdev, REG_TX_RPT_TIME, 0x3df0);
+
+ /* Reset USB mode switch setting */
+ rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x0);
+ rtw_write8(rtwdev, REG_ACLK_MON, 0x0);
+
+ rtw_write8(rtwdev, REG_USB_HRPWM, 0);
+
+ /* ack for xmit mgmt frames. */
+ rtw_write32_set(rtwdev, REG_FWHW_TXQ_CTRL, BIT(12));
+
+ hal->cck_high_power = rtw_read32_mask(rtwdev, REG_CCK_RPT_FORMAT,
+ BIT_CCK_RPT_FORMAT);
+
+ ret = rtw_hci_start(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to start hci\n");
+ goto err_off;
+ }
+
+ if (efuse->btcoex) {
+ rtw_coex_power_on_setting(rtwdev);
+ rtw_coex_init_hw_config(rtwdev, false);
+ }
+
+ set_bit(RTW_FLAG_POWERON, rtwdev->flags);
+
+ return 0;
+
+err_off:
+ chip->ops->power_off(rtwdev);
+
+err:
+ return ret;
+}
+EXPORT_SYMBOL(rtw88xxa_power_on);
+
+u32 rtw88xxa_phy_read_rf(struct rtw_dev *rtwdev,
+ enum rtw_rf_path rf_path, u32 addr, u32 mask)
+{
+ static const u32 pi_addr[2] = { REG_3WIRE_SWA, REG_3WIRE_SWB };
+ static const u32 read_addr[2][2] = {
+ { REG_SI_READ_A, REG_SI_READ_B },
+ { REG_PI_READ_A, REG_PI_READ_B }
+ };
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ const struct rtw_hal *hal = &rtwdev->hal;
+ bool set_cca, pi_mode;
+ u32 val;
+
+ if (rf_path >= hal->rf_phy_num) {
+ rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
+ return INV_RF_DATA;
+ }
+
+ /* CCA off to avoid reading the wrong value.
+ * Toggling CCA would affect RF 0x0, skip it.
+ */
+ set_cca = addr != 0x0 && chip->id == RTW_CHIP_TYPE_8812A &&
+ hal->cut_version != RTW_CHIP_VER_CUT_C;
+
+ if (set_cca)
+ rtw_write32_set(rtwdev, REG_CCA2ND, BIT(3));
+
+ addr &= 0xff;
+
+ pi_mode = rtw_read32_mask(rtwdev, pi_addr[rf_path], 0x4);
+
+ rtw_write32_mask(rtwdev, REG_HSSI_READ, MASKBYTE0, addr);
+
+ if (chip->id == RTW_CHIP_TYPE_8821A ||
+ hal->cut_version == RTW_CHIP_VER_CUT_C)
+ udelay(20);
+
+ val = rtw_read32_mask(rtwdev, read_addr[pi_mode][rf_path], mask);
+
+ /* CCA on */
+ if (set_cca)
+ rtw_write32_clr(rtwdev, REG_CCA2ND, BIT(3));
+
+ return val;
+}
+EXPORT_SYMBOL(rtw88xxa_phy_read_rf);
+
+static void rtw8812a_phy_fix_spur(struct rtw_dev *rtwdev, u8 channel, u8 bw)
+{
+ /* C cut Item12 ADC FIFO CLOCK */
+ if (rtwdev->hal.cut_version == RTW_CHIP_VER_CUT_C) {
+ if (bw == RTW_CHANNEL_WIDTH_40 && channel == 11)
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0xC00, 0x3);
+ else
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0xC00, 0x2);
+
+ /* A workaround to resolve 2480Mhz spur by setting ADC clock
+ * as 160M.
+ */
+ if (bw == RTW_CHANNEL_WIDTH_20 && (channel == 13 || channel == 14)) {
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x3);
+ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1);
+ } else if (bw == RTW_CHANNEL_WIDTH_40 && channel == 11) {
+ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1);
+ } else if (bw != RTW_CHANNEL_WIDTH_80) {
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x2);
+ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0);
+ }
+ } else {
+ /* A workaround to resolve 2480Mhz spur by setting ADC clock
+ * as 160M.
+ */
+ if (bw == RTW_CHANNEL_WIDTH_20 && (channel == 13 || channel == 14))
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x3);
+ else if (channel <= 14) /* 2.4G only */
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x2);
+ }
+}
+
+static void rtw88xxa_switch_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw)
+{
+ struct rtw_hal *hal = &rtwdev->hal;
+ u32 fc_area, rf_mod_ag;
+ u8 path;
+
+ switch (channel) {
+ case 36 ... 48:
+ fc_area = 0x494;
+ break;
+ case 50 ... 64:
+ fc_area = 0x453;
+ break;
+ case 100 ... 116:
+ fc_area = 0x452;
+ break;
+ default:
+ if (channel >= 118)
+ fc_area = 0x412;
+ else
+ fc_area = 0x96a;
+ break;
+ }
+
+ rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, fc_area);
+
+ for (path = 0; path < hal->rf_path_num; path++) {
+ switch (channel) {
+ case 36 ... 64:
+ rf_mod_ag = 0x101;
+ break;
+ case 100 ... 140:
+ rf_mod_ag = 0x301;
+ break;
+ default:
+ if (channel > 140)
+ rf_mod_ag = 0x501;
+ else
+ rf_mod_ag = 0x000;
+ break;
+ }
+
+ rtw_write_rf(rtwdev, path, RF_CFGCH,
+ RF18_RFSI_MASK | RF18_BAND_MASK, rf_mod_ag);
+
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
+ rtw8812a_phy_fix_spur(rtwdev, channel, bw);
+
+ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_CHANNEL_MASK, channel);
+ }
+}
+
+static void rtw88xxa_set_reg_bw(struct rtw_dev *rtwdev, u8 bw)
+{
+ u16 val16 = rtw_read16(rtwdev, REG_WMAC_TRXPTCL_CTL);
+
+ val16 &= ~BIT_RFMOD;
+ if (bw == RTW_CHANNEL_WIDTH_80)
+ val16 |= BIT_RFMOD_80M;
+ else if (bw == RTW_CHANNEL_WIDTH_40)
+ val16 |= BIT_RFMOD_40M;
+
+ rtw_write16(rtwdev, REG_WMAC_TRXPTCL_CTL, val16);
+}
+
+static void rtw88xxa_post_set_bw_mode(struct rtw_dev *rtwdev, u8 channel,
+ u8 bw, u8 primary_chan_idx)
+{
+ struct rtw_hal *hal = &rtwdev->hal;
+ u8 txsc40 = 0, txsc20, txsc;
+ u8 reg_837, l1pkval;
+
+ rtw88xxa_set_reg_bw(rtwdev, bw);
+
+ txsc20 = primary_chan_idx;
+ if (bw == RTW_CHANNEL_WIDTH_80) {
+ if (txsc20 == RTW_SC_20_UPPER || txsc20 == RTW_SC_20_UPMOST)
+ txsc40 = RTW_SC_40_UPPER;
+ else
+ txsc40 = RTW_SC_40_LOWER;
+ }
+
+ txsc = BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40);
+ rtw_write8(rtwdev, REG_DATA_SC, txsc);
+
+ reg_837 = rtw_read8(rtwdev, REG_BWINDICATION + 3);
+
+ switch (bw) {
+ default:
+ case RTW_CHANNEL_WIDTH_20:
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300200);
+ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0);
+
+ if (hal->rf_type == RF_2T2R)
+ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, 7);
+ else
+ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, 8);
+
+ break;
+ case RTW_CHANNEL_WIDTH_40:
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300201);
+ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0);
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x3C, txsc);
+ rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0000000, txsc);
+
+ if (reg_837 & BIT(2)) {
+ l1pkval = 6;
+ } else {
+ if (hal->rf_type == RF_2T2R)
+ l1pkval = 7;
+ else
+ l1pkval = 8;
+ }
+
+ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, l1pkval);
+
+ if (txsc == RTW_SC_20_UPPER)
+ rtw_write32_set(rtwdev, REG_RXSB, BIT(4));
+ else
+ rtw_write32_clr(rtwdev, REG_RXSB, BIT(4));
+
+ break;
+ case RTW_CHANNEL_WIDTH_80:
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300202);
+ rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1);
+ rtw_write32_mask(rtwdev, REG_ADCCLK, 0x3C, txsc);
+ rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0000000, txsc);
+
+ if (reg_837 & BIT(2)) {
+ l1pkval = 5;
+ } else {
+ if (hal->rf_type == RF_2T2R)
+ l1pkval = 6;
+ else
+ l1pkval = 7;
+ }
+
+ rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, l1pkval);
+
+ break;
+ }
+}
+
+static void rtw88xxa_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
+{
+ u8 path;
+
+ for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) {
+ switch (bw) {
+ case RTW_CHANNEL_WIDTH_5:
+ case RTW_CHANNEL_WIDTH_10:
+ case RTW_CHANNEL_WIDTH_20:
+ default:
+ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 3);
+ break;
+ case RTW_CHANNEL_WIDTH_40:
+ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 1);
+ break;
+ case RTW_CHANNEL_WIDTH_80:
+ rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 0);
+ break;
+ }
+ }
+}
+
+void rtw88xxa_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+ u8 primary_chan_idx)
+{
+ u8 old_band, new_band;
+
+ if (rtw_read8(rtwdev, REG_CCK_CHECK) & BIT_CHECK_CCK_EN)
+ old_band = RTW_BAND_5G;
+ else
+ old_band = RTW_BAND_2G;
+
+ if (channel > 14)
+ new_band = RTW_BAND_5G;
+ else
+ new_band = RTW_BAND_2G;
+
+ if (new_band != old_band)
+ rtw88xxa_switch_band(rtwdev, new_band, bw);
+
+ rtw88xxa_switch_channel(rtwdev, channel, bw);
+
+ rtw88xxa_post_set_bw_mode(rtwdev, channel, bw, primary_chan_idx);
+
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
+ rtw8812a_phy_fix_spur(rtwdev, channel, bw);
+
+ rtw88xxa_set_channel_rf(rtwdev, channel, bw);
+}
+EXPORT_SYMBOL(rtw88xxa_set_channel);
+
+void rtw88xxa_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
+ struct rtw_rx_pkt_stat *pkt_stat,
+ s8 (*cck_rx_pwr)(u8 lna_idx, u8 vga_idx))
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ struct rtw_jaguar_phy_status_rpt *rpt;
+ u8 gain[RTW_RF_PATH_MAX], rssi, i;
+ s8 rx_pwr_db, power_a, power_b;
+ const s8 min_rx_power = -120;
+ u8 lna_idx, vga_idx;
+
+ rpt = (struct rtw_jaguar_phy_status_rpt *)phy_status;
+
+ if (pkt_stat->rate <= DESC_RATE11M) {
+ lna_idx = le32_get_bits(rpt->w1, RTW_JGRPHY_W1_AGC_RPT_LNA_IDX);
+ vga_idx = le32_get_bits(rpt->w1, RTW_JGRPHY_W1_AGC_RPT_VGA_IDX);
+
+ rx_pwr_db = cck_rx_pwr(lna_idx, vga_idx);
+
+ pkt_stat->rx_power[RF_PATH_A] = rx_pwr_db;
+ pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
+ dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
+ pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
+ pkt_stat->signal_power = rx_pwr_db;
+ } else { /* OFDM rate */
+ gain[RF_PATH_A] = le32_get_bits(rpt->w0, RTW_JGRPHY_W0_GAIN_A);
+ gain[RF_PATH_B] = le32_get_bits(rpt->w0, RTW_JGRPHY_W0_GAIN_B);
+
+ for (i = RF_PATH_A; i < rtwdev->hal.rf_path_num; i++) {
+ pkt_stat->rx_power[i] = gain[i] - 110;
+ rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[i], 1);
+ dm_info->rssi[i] = rssi;
+ }
+
+ pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power,
+ rtwdev->hal.rf_path_num);
+
+ power_a = pkt_stat->rx_power[RF_PATH_A];
+ power_b = pkt_stat->rx_power[RF_PATH_B];
+ if (rtwdev->hal.rf_path_num == 1)
+ power_b = power_a;
+
+ pkt_stat->signal_power = max3(power_a, power_b, min_rx_power);
+ }
+}
+EXPORT_SYMBOL(rtw88xxa_query_phy_status);
+
+static void
+rtw88xxa_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path,
+ u8 rs, u32 *phy_pwr_idx)
+{
+ static const u32 offset_txagc[2] = {
+ REG_TX_AGC_A_CCK_11_CCK_1, REG_TX_AGC_B_CCK_11_CCK_1
+ };
+ u8 rate, rate_idx, pwr_index, shift;
+ struct rtw_hal *hal = &rtwdev->hal;
+ bool write_1ss_mcs9;
+ u32 mask;
+ int j;
+
+ for (j = 0; j < rtw_rate_size[rs]; j++) {
+ rate = rtw_rate_section[rs][j];
+
+ pwr_index = hal->tx_pwr_tbl[path][rate];
+
+ shift = rate & 0x3;
+ *phy_pwr_idx |= ((u32)pwr_index << (shift * 8));
+
+ write_1ss_mcs9 = rate == DESC_RATEVHT1SS_MCS9 &&
+ hal->rf_path_num == 1;
+
+ if (write_1ss_mcs9)
+ mask = MASKLWORD;
+ else
+ mask = MASKDWORD;
+
+ if (shift == 0x3 || write_1ss_mcs9) {
+ rate_idx = rate & 0xfc;
+ if (rate >= DESC_RATEVHT1SS_MCS0)
+ rate_idx -= 0x10;
+
+ rtw_write32_mask(rtwdev, offset_txagc[path] + rate_idx,
+ mask, *phy_pwr_idx);
+
+ *phy_pwr_idx = 0;
+ }
+ }
+}
+
+static void rtw88xxa_tx_power_training(struct rtw_dev *rtwdev, u8 bw,
+ u8 channel, u8 path)
+{
+ static const u32 write_offset[] = {
+ REG_TX_PWR_TRAINING_A, REG_TX_PWR_TRAINING_B,
+ };
+ u32 power_level, write_data;
+ u8 i;
+
+ power_level = rtwdev->hal.tx_pwr_tbl[path][DESC_RATEMCS7];
+ write_data = 0;
+
+ for (i = 0; i < 3; i++) {
+ if (i == 0)
+ power_level -= 10;
+ else if (i == 1)
+ power_level -= 8;
+ else
+ power_level -= 6;
+
+ write_data |= max_t(u32, power_level, 2) << (i * 8);
+ }
+
+ rtw_write32_mask(rtwdev, write_offset[path], 0xffffff, write_data);
+}
+
+void rtw88xxa_set_tx_power_index(struct rtw_dev *rtwdev)
+{
+ struct rtw_hal *hal = &rtwdev->hal;
+ u32 phy_pwr_idx = 0;
+ int rs, path;
+
+ for (path = 0; path < hal->rf_path_num; path++) {
+ for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) {
+ if (hal->rf_path_num == 1 &&
+ (rs == RTW_RATE_SECTION_HT_2S ||
+ rs == RTW_RATE_SECTION_VHT_2S))
+ continue;
+
+ if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags) &&
+ rs > RTW_RATE_SECTION_OFDM)
+ continue;
+
+ if (hal->current_band_type == RTW_BAND_5G &&
+ rs == RTW_RATE_SECTION_CCK)
+ continue;
+
+ rtw88xxa_set_tx_power_index_by_rate(rtwdev, path, rs,
+ &phy_pwr_idx);
+ }
+
+ rtw88xxa_tx_power_training(rtwdev, hal->current_band_width,
+ hal->current_channel, path);
+ }
+}
+EXPORT_SYMBOL(rtw88xxa_set_tx_power_index);
+
+void rtw88xxa_false_alarm_statistics(struct rtw_dev *rtwdev)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u32 cck_fa_cnt, ofdm_fa_cnt;
+ u32 crc32_cnt, cca32_cnt;
+ u32 cck_enable;
+
+ cck_enable = rtw_read32(rtwdev, REG_RXPSEL) & BIT(28);
+ cck_fa_cnt = rtw_read16(rtwdev, REG_FA_CCK);
+ ofdm_fa_cnt = rtw_read16(rtwdev, REG_FA_OFDM);
+
+ dm_info->cck_fa_cnt = cck_fa_cnt;
+ dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
+ dm_info->total_fa_cnt = ofdm_fa_cnt;
+ if (cck_enable)
+ dm_info->total_fa_cnt += cck_fa_cnt;
+
+ crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK);
+ dm_info->cck_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
+ dm_info->cck_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
+
+ crc32_cnt = rtw_read32(rtwdev, REG_CRC_OFDM);
+ dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
+ dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
+
+ crc32_cnt = rtw_read32(rtwdev, REG_CRC_HT);
+ dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
+ dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
+
+ crc32_cnt = rtw_read32(rtwdev, REG_CRC_VHT);
+ dm_info->vht_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
+ dm_info->vht_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
+
+ cca32_cnt = rtw_read32(rtwdev, REG_CCA_OFDM);
+ dm_info->ofdm_cca_cnt = u32_get_bits(cca32_cnt, MASKHWORD);
+ dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt;
+ if (cck_enable) {
+ cca32_cnt = rtw_read32(rtwdev, REG_CCA_CCK);
+ dm_info->cck_cca_cnt = u32_get_bits(cca32_cnt, MASKLWORD);
+ dm_info->total_cca_cnt += dm_info->cck_cca_cnt;
+ }
+
+ rtw_write32_set(rtwdev, REG_FAS, BIT(17));
+ rtw_write32_clr(rtwdev, REG_FAS, BIT(17));
+ rtw_write32_clr(rtwdev, REG_CCK0_FAREPORT, BIT(15));
+ rtw_write32_set(rtwdev, REG_CCK0_FAREPORT, BIT(15));
+ rtw_write32_set(rtwdev, REG_CNTRST, BIT(0));
+ rtw_write32_clr(rtwdev, REG_CNTRST, BIT(0));
+}
+EXPORT_SYMBOL(rtw88xxa_false_alarm_statistics);
+
+void rtw88xxa_iqk_backup_mac_bb(struct rtw_dev *rtwdev,
+ u32 *macbb_backup,
+ const u32 *backup_macbb_reg,
+ u32 macbb_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* save MACBB default value */
+ for (i = 0; i < macbb_num; i++)
+ macbb_backup[i] = rtw_read32(rtwdev, backup_macbb_reg[i]);
+}
+EXPORT_SYMBOL(rtw88xxa_iqk_backup_mac_bb);
+
+void rtw88xxa_iqk_backup_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
+ const u32 *backup_afe_reg, u32 afe_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* Save AFE Parameters */
+ for (i = 0; i < afe_num; i++)
+ afe_backup[i] = rtw_read32(rtwdev, backup_afe_reg[i]);
+}
+EXPORT_SYMBOL(rtw88xxa_iqk_backup_afe);
+
+void rtw88xxa_iqk_restore_mac_bb(struct rtw_dev *rtwdev,
+ u32 *macbb_backup,
+ const u32 *backup_macbb_reg,
+ u32 macbb_num)
+{
+ u32 i;
+
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ /* Reload MacBB Parameters */
+ for (i = 0; i < macbb_num; i++)
+ rtw_write32(rtwdev, backup_macbb_reg[i], macbb_backup[i]);
+}
+EXPORT_SYMBOL(rtw88xxa_iqk_restore_mac_bb);
+
+void rtw88xxa_iqk_configure_mac(struct rtw_dev *rtwdev)
+{
+ /* [31] = 0 --> Page C */
+ rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
+
+ rtw_write8(rtwdev, REG_TXPAUSE, 0x3f);
+ rtw_write32_mask(rtwdev, REG_BCN_CTRL,
+ (BIT_EN_BCN_FUNCTION << 8) | BIT_EN_BCN_FUNCTION, 0x0);
+
+ /* RX ante off */
+ rtw_write8(rtwdev, REG_RXPSEL, 0x00);
+
+ /* CCA off */
+ rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf, 0xc);
+
+ /* CCK RX path off */
+ rtw_write8(rtwdev, REG_CCK_RX + 3, 0xf);
+}
+EXPORT_SYMBOL(rtw88xxa_iqk_configure_mac);
+
+bool rtw88xxa_iqk_finish(int average, int threshold,
+ int *x_temp, int *y_temp, int *x, int *y,
+ bool break_inner, bool break_outer)
+{
+ bool finish = false;
+ int i, ii, dx, dy;
+
+ for (i = 0; i < average; i++) {
+ for (ii = i + 1; ii < average; ii++) {
+ dx = abs_diff(x_temp[i] >> 21, x_temp[ii] >> 21);
+ dy = abs_diff(y_temp[i] >> 21, y_temp[ii] >> 21);
+
+ if (dx < threshold && dy < threshold) {
+ *x = ((x_temp[i] >> 21) + (x_temp[ii] >> 21));
+ *y = ((y_temp[i] >> 21) + (y_temp[ii] >> 21));
+
+ *x /= 2;
+ *y /= 2;
+
+ finish = true;
+
+ if (break_inner)
+ break;
+ }
+ }
+
+ if (finish && break_outer)
+ break;
+ }
+
+ return finish;
+}
+EXPORT_SYMBOL(rtw88xxa_iqk_finish);
+
+static void rtw88xxa_pwrtrack_set(struct rtw_dev *rtwdev, u8 tx_rate, u8 path)
+{
+ static const u32 reg_txscale[2] = { REG_TXSCALE_A, REG_TXSCALE_B };
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ u8 cck_swing_idx, ofdm_swing_idx;
+ u8 pwr_tracking_limit;
+
+ switch (tx_rate) {
+ case DESC_RATE1M ... DESC_RATE11M:
+ pwr_tracking_limit = 32;
+ break;
+ case DESC_RATE6M ... DESC_RATE48M:
+ case DESC_RATEMCS3 ... DESC_RATEMCS4:
+ case DESC_RATEMCS11 ... DESC_RATEMCS12:
+ case DESC_RATEVHT1SS_MCS3 ... DESC_RATEVHT1SS_MCS4:
+ case DESC_RATEVHT2SS_MCS3 ... DESC_RATEVHT2SS_MCS4:
+ pwr_tracking_limit = 30;
+ break;
+ case DESC_RATE54M:
+ case DESC_RATEMCS5 ... DESC_RATEMCS7:
+ case DESC_RATEMCS13 ... DESC_RATEMCS15:
+ case DESC_RATEVHT1SS_MCS5 ... DESC_RATEVHT1SS_MCS6:
+ case DESC_RATEVHT2SS_MCS5 ... DESC_RATEVHT2SS_MCS6:
+ pwr_tracking_limit = 28;
+ break;
+ case DESC_RATEMCS0 ... DESC_RATEMCS2:
+ case DESC_RATEMCS8 ... DESC_RATEMCS10:
+ case DESC_RATEVHT1SS_MCS0 ... DESC_RATEVHT1SS_MCS2:
+ case DESC_RATEVHT2SS_MCS0 ... DESC_RATEVHT2SS_MCS2:
+ pwr_tracking_limit = 34;
+ break;
+ case DESC_RATEVHT1SS_MCS7:
+ case DESC_RATEVHT2SS_MCS7:
+ pwr_tracking_limit = 26;
+ break;
+ default:
+ case DESC_RATEVHT1SS_MCS8:
+ case DESC_RATEVHT2SS_MCS8:
+ pwr_tracking_limit = 24;
+ break;
+ case DESC_RATEVHT1SS_MCS9:
+ case DESC_RATEVHT2SS_MCS9:
+ pwr_tracking_limit = 22;
+ break;
+ }
+
+ cck_swing_idx = dm_info->delta_power_index[path] + dm_info->default_cck_index;
+ ofdm_swing_idx = dm_info->delta_power_index[path] + dm_info->default_ofdm_index;
+
+ if (ofdm_swing_idx > pwr_tracking_limit) {
+ if (path == RF_PATH_A)
+ dm_info->txagc_remnant_cck = cck_swing_idx - pwr_tracking_limit;
+ dm_info->txagc_remnant_ofdm[path] = ofdm_swing_idx - pwr_tracking_limit;
+
+ ofdm_swing_idx = pwr_tracking_limit;
+ } else if (ofdm_swing_idx == 0) {
+ if (path == RF_PATH_A)
+ dm_info->txagc_remnant_cck = cck_swing_idx;
+ dm_info->txagc_remnant_ofdm[path] = ofdm_swing_idx;
+ } else {
+ if (path == RF_PATH_A)
+ dm_info->txagc_remnant_cck = 0;
+ dm_info->txagc_remnant_ofdm[path] = 0;
+ }
+
+ rtw_write32_mask(rtwdev, reg_txscale[path], GENMASK(31, 21),
+ rtw88xxa_txscale_tbl[ofdm_swing_idx]);
+}
+
+void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev,
+ void (*do_lck)(struct rtw_dev *rtwdev),
+ void (*do_iqk)(struct rtw_dev *rtwdev))
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+ struct rtw_hal *hal = &rtwdev->hal;
+ struct rtw_swing_table swing_table;
+ s8 remnant_pre[RTW_RF_PATH_MAX];
+ u8 thermal_value, delta, path;
+ bool need_iqk;
+
+ rtw_phy_config_swing_table(rtwdev, &swing_table);
+
+ if (rtwdev->efuse.thermal_meter[0] == 0xff) {
+ pr_err_once("efuse thermal meter is 0xff\n");
+ return;
+ }
+
+ thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00);
+
+ rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A);
+
+ need_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev);
+
+ if (need_iqk && do_lck)
+ do_lck(rtwdev);
+
+ if (dm_info->pwr_trk_init_trigger)
+ dm_info->pwr_trk_init_trigger = false;
+ else if (!rtw_phy_pwrtrack_thermal_changed(rtwdev, thermal_value,
+ RF_PATH_A))
+ goto iqk;
+
+ delta = rtw_phy_pwrtrack_get_delta(rtwdev, RF_PATH_A);
+
+ for (path = RF_PATH_A; path < hal->rf_path_num; path++) {
+ remnant_pre[path] = dm_info->txagc_remnant_ofdm[path];
+
+ dm_info->delta_power_index[path] =
+ rtw_phy_pwrtrack_get_pwridx(rtwdev, &swing_table, path,
+ RF_PATH_A, delta);
+
+ if (dm_info->delta_power_index[path] !=
+ dm_info->delta_power_index_last[path]) {
+ dm_info->delta_power_index_last[path] =
+ dm_info->delta_power_index[path];
+
+ rtw88xxa_pwrtrack_set(rtwdev, dm_info->tx_rate, path);
+ }
+ }
+
+ for (path = RF_PATH_A; path < hal->rf_path_num; path++) {
+ if (remnant_pre[path] != dm_info->txagc_remnant_ofdm[path]) {
+ rtw_phy_set_tx_power_level(rtwdev,
+ hal->current_channel);
+ break;
+ }
+ }
+
+iqk:
+ if (need_iqk)
+ do_iqk(rtwdev);
+}
+EXPORT_SYMBOL(rtw88xxa_phy_pwrtrack);
+
+void rtw88xxa_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
+{
+ static const u8 pd[CCK_PD_LV_MAX] = {0x40, 0x83, 0xcd, 0xdd, 0xed};
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+ /* Override rtw_phy_cck_pd_lv_link(). It implements something
+ * like type 2/3/4. We need type 1 here.
+ */
+ if (rtw_is_assoc(rtwdev)) {
+ if (dm_info->min_rssi > 60) {
+ new_lvl = CCK_PD_LV3;
+ } else if (dm_info->min_rssi > 35) {
+ new_lvl = CCK_PD_LV2;
+ } else if (dm_info->min_rssi > 20) {
+ if (dm_info->cck_fa_avg > 500)
+ new_lvl = CCK_PD_LV2;
+ else if (dm_info->cck_fa_avg < 250)
+ new_lvl = CCK_PD_LV1;
+ else
+ return;
+ } else {
+ new_lvl = CCK_PD_LV1;
+ }
+ }
+
+ rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n",
+ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl);
+
+ if (dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] == new_lvl)
+ return;
+
+ dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
+ dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] = new_lvl;
+
+ rtw_write8(rtwdev, REG_CCK_PD_TH, pd[new_lvl]);
+}
+EXPORT_SYMBOL(rtw88xxa_phy_cck_pd_set);
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a/8812a common code");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.h b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
new file mode 100644
index 000000000000..09a45c1a4129
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2024 Realtek Corporation
+ */
+
+#ifndef __RTW88XXA_H__
+#define __RTW88XXA_H__
+
+#include <asm/byteorder.h>
+#include "reg.h"
+
+struct rtw8821au_efuse {
+ u8 res4[48]; /* 0xd0 */
+ u8 vid[2]; /* 0x100 */
+ u8 pid[2];
+ u8 res8[3];
+ u8 mac_addr[ETH_ALEN]; /* 0x107 */
+ u8 res9[243];
+} __packed;
+
+struct rtw8812au_efuse {
+ u8 vid[2]; /* 0xd0 */
+ u8 pid[2]; /* 0xd2 */
+ u8 res0[3];
+ u8 mac_addr[ETH_ALEN]; /* 0xd7 */
+ u8 res1[291];
+} __packed;
+
+struct rtw88xxa_efuse {
+ __le16 rtl_id;
+ u8 res0[6]; /* 0x02 */
+ u8 usb_mode; /* 0x08 */
+ u8 res1[7]; /* 0x09 */
+
+ /* power index for four RF paths */
+ struct rtw_txpwr_idx txpwr_idx_table[4];
+
+ u8 channel_plan; /* 0xb8 */
+ u8 xtal_k;
+ u8 thermal_meter;
+ u8 iqk_lck;
+ u8 pa_type; /* 0xbc */
+ u8 lna_type_2g; /* 0xbd */
+ u8 res2;
+ u8 lna_type_5g; /* 0xbf */
+ u8 res3;
+ u8 rf_board_option; /* 0xc1 */
+ u8 rf_feature_option;
+ u8 rf_bt_setting;
+ u8 eeprom_version;
+ u8 eeprom_customer_id; /* 0xc5 */
+ u8 tx_bb_swing_setting_2g;
+ u8 tx_bb_swing_setting_5g;
+ u8 tx_pwr_calibrate_rate;
+ u8 rf_antenna_option; /* 0xc9 */
+ u8 rfe_option;
+ u8 country_code[2];
+ u8 res4[3];
+ union {
+ struct rtw8821au_efuse rtw8821au;
+ struct rtw8812au_efuse rtw8812au;
+ };
+} __packed;
+
+static_assert(sizeof(struct rtw88xxa_efuse) == 512);
+
+#define WLAN_BCN_DMA_TIME 0x02
+#define WLAN_TBTT_PROHIBIT 0x04
+#define WLAN_TBTT_HOLD_TIME 0x064
+#define WLAN_TBTT_TIME (WLAN_TBTT_PROHIBIT |\
+ (WLAN_TBTT_HOLD_TIME << BIT_SHIFT_TBTT_HOLD_TIME_AP))
+
+struct rtw_jaguar_phy_status_rpt {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+} __packed;
+
+#define RTW_JGRPHY_W0_GAIN_A GENMASK(6, 0)
+#define RTW_JGRPHY_W0_TRSW_A BIT(7)
+#define RTW_JGRPHY_W0_GAIN_B GENMASK(14, 8)
+#define RTW_JGRPHY_W0_TRSW_B BIT(15)
+#define RTW_JGRPHY_W0_CHL_NUM GENMASK(25, 16)
+#define RTW_JGRPHY_W0_SUB_CHNL GENMASK(29, 26)
+#define RTW_JGRPHY_W0_R_RFMOD GENMASK(31, 30)
+
+/* CCK: */
+#define RTW_JGRPHY_W1_SIG_QUAL GENMASK(7, 0)
+#define RTW_JGRPHY_W1_AGC_RPT_VGA_IDX GENMASK(12, 8)
+#define RTW_JGRPHY_W1_AGC_RPT_LNA_IDX GENMASK(15, 13)
+#define RTW_JGRPHY_W1_BB_POWER GENMASK(23, 16)
+/* OFDM: */
+#define RTW_JGRPHY_W1_PWDB_ALL GENMASK(7, 0)
+#define RTW_JGRPHY_W1_CFO_SHORT_A GENMASK(15, 8) /* s8 */
+#define RTW_JGRPHY_W1_CFO_SHORT_B GENMASK(23, 16) /* s8 */
+#define RTW_JGRPHY_W1_BT_RF_CH_MSB GENMASK(31, 30)
+
+#define RTW_JGRPHY_W2_ANT_DIV_SW_A BIT(0)
+#define RTW_JGRPHY_W2_ANT_DIV_SW_B BIT(1)
+#define RTW_JGRPHY_W2_BT_RF_CH_LSB GENMASK(7, 2)
+#define RTW_JGRPHY_W2_CFO_TAIL_A GENMASK(15, 8) /* s8 */
+#define RTW_JGRPHY_W2_CFO_TAIL_B GENMASK(23, 16) /* s8 */
+#define RTW_JGRPHY_W2_PCTS_MSK_RPT_0 GENMASK(31, 24)
+
+#define RTW_JGRPHY_W3_PCTS_MSK_RPT_1 GENMASK(7, 0)
+/* Stream 1 and 2 RX EVM: */
+#define RTW_JGRPHY_W3_RXEVM_1 GENMASK(15, 8) /* s8 */
+#define RTW_JGRPHY_W3_RXEVM_2 GENMASK(23, 16) /* s8 */
+#define RTW_JGRPHY_W3_RXSNR_A GENMASK(31, 24) /* s8 */
+
+#define RTW_JGRPHY_W4_RXSNR_B GENMASK(7, 0) /* s8 */
+#define RTW_JGRPHY_W4_PCTS_MSK_RPT_2 GENMASK(21, 8)
+#define RTW_JGRPHY_W4_PCTS_RPT_VALID BIT(22)
+#define RTW_JGRPHY_W4_RXEVM_3 GENMASK(31, 24) /* s8 */
+
+#define RTW_JGRPHY_W5_RXEVM_4 GENMASK(7, 0) /* s8 */
+/* 8812a, stream 1 and 2 CSI: */
+#define RTW_JGRPHY_W5_CSI_CURRENT_1 GENMASK(15, 8)
+#define RTW_JGRPHY_W5_CSI_CURRENT_2 GENMASK(23, 16)
+/* 8814a: */
+#define RTW_JGRPHY_W5_RXSNR_C GENMASK(15, 8) /* s8 */
+#define RTW_JGRPHY_W5_RXSNR_D GENMASK(23, 16) /* s8 */
+#define RTW_JGRPHY_W5_GAIN_C GENMASK(30, 24)
+#define RTW_JGRPHY_W5_TRSW_C BIT(31)
+
+#define RTW_JGRPHY_W6_GAIN_D GENMASK(6, 0)
+#define RTW_JGRPHY_W6_TRSW_D BIT(7)
+#define RTW_JGRPHY_W6_SIGEVM GENMASK(15, 8) /* s8 */
+#define RTW_JGRPHY_W6_ANTIDX_ANTC GENMASK(18, 16)
+#define RTW_JGRPHY_W6_ANTIDX_ANTD GENMASK(21, 19)
+#define RTW_JGRPHY_W6_DPDT_CTRL_KEEP BIT(22)
+#define RTW_JGRPHY_W6_GNT_BT_KEEP BIT(23)
+#define RTW_JGRPHY_W6_ANTIDX_ANTA GENMASK(26, 24)
+#define RTW_JGRPHY_W6_ANTIDX_ANTB GENMASK(29, 27)
+#define RTW_JGRPHY_W6_HW_ANTSW_OCCUR GENMASK(31, 30)
+
+#define RF18_BW_MASK (BIT(11) | BIT(10))
+
+void rtw88xxa_efuse_grant(struct rtw_dev *rtwdev, bool on);
+int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map);
+void rtw88xxa_power_off(struct rtw_dev *rtwdev,
+ const struct rtw_pwr_seq_cmd *const *enter_lps_flow);
+int rtw88xxa_power_on(struct rtw_dev *rtwdev);
+u32 rtw88xxa_phy_read_rf(struct rtw_dev *rtwdev,
+ enum rtw_rf_path rf_path, u32 addr, u32 mask);
+void rtw88xxa_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+ u8 primary_chan_idx);
+void rtw88xxa_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
+ struct rtw_rx_pkt_stat *pkt_stat,
+ s8 (*cck_rx_pwr)(u8 lna_idx, u8 vga_idx));
+void rtw88xxa_set_tx_power_index(struct rtw_dev *rtwdev);
+void rtw88xxa_false_alarm_statistics(struct rtw_dev *rtwdev);
+void rtw88xxa_iqk_backup_mac_bb(struct rtw_dev *rtwdev,
+ u32 *macbb_backup,
+ const u32 *backup_macbb_reg,
+ u32 macbb_num);
+void rtw88xxa_iqk_backup_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
+ const u32 *backup_afe_reg, u32 afe_num);
+void rtw88xxa_iqk_restore_mac_bb(struct rtw_dev *rtwdev,
+ u32 *macbb_backup,
+ const u32 *backup_macbb_reg,
+ u32 macbb_num);
+void rtw88xxa_iqk_configure_mac(struct rtw_dev *rtwdev);
+bool rtw88xxa_iqk_finish(int average, int threshold,
+ int *x_temp, int *y_temp, int *x, int *y,
+ bool break_inner, bool break_outer);
+void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev,
+ void (*do_lck)(struct rtw_dev *rtwdev),
+ void (*do_iqk)(struct rtw_dev *rtwdev));
+void rtw88xxa_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl);
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c
index 66f9419588cf..90fc8a5fa89e 100644
--- a/drivers/net/wireless/realtek/rtw88/rx.c
+++ b/drivers/net/wireless/realtek/rtw88/rx.c
@@ -187,11 +187,10 @@ fill_rx_status:
}
EXPORT_SYMBOL(rtw_update_rx_freq_from_ie);
-void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_hdr *hdr,
- struct ieee80211_rx_status *rx_status,
- u8 *phy_status)
+static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
+ struct rtw_rx_pkt_stat *pkt_stat,
+ struct ieee80211_hdr *hdr,
+ struct ieee80211_rx_status *rx_status)
{
struct ieee80211_hw *hw = rtwdev->hw;
u8 path;
@@ -235,12 +234,75 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
else
rx_status->bw = RATE_INFO_BW_20;
- rx_status->signal = pkt_stat->signal_power;
- for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
- rx_status->chains |= BIT(path);
- rx_status->chain_signal[path] = pkt_stat->rx_power[path];
+ if (pkt_stat->phy_status) {
+ rx_status->signal = pkt_stat->signal_power;
+ for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
+ rx_status->chains |= BIT(path);
+ rx_status->chain_signal[path] = pkt_stat->rx_power[path];
+ }
+ } else {
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
}
rtw_rx_addr_match(rtwdev, pkt_stat, hdr);
+
+ /* Rtl8723cs driver checks for size < 14 or size > 8192 and
+ * simply drops the packet.
+ */
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && pkt_stat->pkt_len == 0) {
+ rx_status->flag |= RX_FLAG_NO_PSDU;
+ rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet");
+ }
+}
+
+void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
+ struct rtw_rx_pkt_stat *pkt_stat,
+ struct ieee80211_rx_status *rx_status)
+{
+ u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+ struct rtw_rx_desc *rx_desc = rx_desc8;
+ struct ieee80211_hdr *hdr;
+ u32 enc_type, swdec;
+ void *phy_status;
+
+ memset(pkt_stat, 0, sizeof(*pkt_stat));
+
+ pkt_stat->pkt_len = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PKT_LEN);
+ pkt_stat->crc_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_CRC32);
+ pkt_stat->icv_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ICV_ERR);
+ pkt_stat->drv_info_sz = le32_get_bits(rx_desc->w0,
+ RTW_RX_DESC_W0_DRV_INFO_SIZE);
+ enc_type = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ENC_TYPE);
+ pkt_stat->shift = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SHIFT);
+ pkt_stat->phy_status = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PHYST);
+ swdec = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SWDEC);
+ pkt_stat->decrypted = !swdec && enc_type != RX_DESC_ENC_NONE;
+
+ pkt_stat->cam_id = le32_get_bits(rx_desc->w1, RTW_RX_DESC_W1_MACID);
+
+ pkt_stat->is_c2h = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_C2H);
+ pkt_stat->ppdu_cnt = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_PPDU_CNT);
+
+ pkt_stat->rate = le32_get_bits(rx_desc->w3, RTW_RX_DESC_W3_RX_RATE);
+
+ pkt_stat->bw = le32_get_bits(rx_desc->w4, RTW_RX_DESC_W4_BW);
+
+ pkt_stat->tsf_low = le32_get_bits(rx_desc->w5, RTW_RX_DESC_W5_TSFL);
+
+ /* drv_info_sz is in unit of 8-bytes */
+ pkt_stat->drv_info_sz *= 8;
+
+ /* c2h cmd pkt's rx/phy status is not interested */
+ if (pkt_stat->is_c2h)
+ return;
+
+ phy_status = rx_desc8 + desc_sz + pkt_stat->shift;
+ hdr = phy_status + pkt_stat->drv_info_sz;
+ pkt_stat->hdr = hdr;
+
+ if (pkt_stat->phy_status)
+ rtwdev->chip->ops->query_phy_status(rtwdev, phy_status, pkt_stat);
+
+ rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status);
}
-EXPORT_SYMBOL(rtw_rx_fill_rx_status);
+EXPORT_SYMBOL(rtw_rx_query_rx_desc);
diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h
index 9f0019112987..6b7dee245c0a 100644
--- a/drivers/net/wireless/realtek/rtw88/rx.h
+++ b/drivers/net/wireless/realtek/rtw88/rx.h
@@ -14,42 +14,40 @@ enum rtw_rx_desc_enc {
RX_DESC_ENC_WEP104 = 5,
};
-#define GET_RX_DESC_PHYST(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26))
-#define GET_RX_DESC_ICV_ERR(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(15))
-#define GET_RX_DESC_CRC32(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(14))
-#define GET_RX_DESC_SWDEC(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(27))
-#define GET_RX_DESC_C2H(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x02), BIT(28))
-#define GET_RX_DESC_PKT_LEN(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(13, 0))
-#define GET_RX_DESC_DRV_INFO_SIZE(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16))
-#define GET_RX_DESC_SHIFT(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24))
-#define GET_RX_DESC_ENC_TYPE(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(22, 20))
-#define GET_RX_DESC_RX_RATE(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0))
-#define GET_RX_DESC_MACID(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x01), GENMASK(6, 0))
-#define GET_RX_DESC_PPDU_CNT(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29))
-#define GET_RX_DESC_TSFL(rxdesc) \
- le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0))
-#define GET_RX_DESC_BW(rxdesc) \
- (le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(5, 4)))
+struct rtw_rx_desc {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+} __packed;
+
+#define RTW_RX_DESC_W0_PKT_LEN GENMASK(13, 0)
+#define RTW_RX_DESC_W0_CRC32 BIT(14)
+#define RTW_RX_DESC_W0_ICV_ERR BIT(15)
+#define RTW_RX_DESC_W0_DRV_INFO_SIZE GENMASK(19, 16)
+#define RTW_RX_DESC_W0_ENC_TYPE GENMASK(22, 20)
+#define RTW_RX_DESC_W0_SHIFT GENMASK(25, 24)
+#define RTW_RX_DESC_W0_PHYST BIT(26)
+#define RTW_RX_DESC_W0_SWDEC BIT(27)
+
+#define RTW_RX_DESC_W1_MACID GENMASK(6, 0)
+
+#define RTW_RX_DESC_W2_C2H BIT(28)
+#define RTW_RX_DESC_W2_PPDU_CNT GENMASK(30, 29)
+
+#define RTW_RX_DESC_W3_RX_RATE GENMASK(6, 0)
+
+#define RTW_RX_DESC_W4_BW GENMASK(5, 4)
+
+#define RTW_RX_DESC_W5_TSFL GENMASK(31, 0)
void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct sk_buff *skb);
-void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
- struct rtw_rx_pkt_stat *pkt_stat,
- struct ieee80211_hdr *hdr,
- struct ieee80211_rx_status *rx_status,
- u8 *phy_status);
+void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
+ struct rtw_rx_pkt_stat *pkt_stat,
+ struct ieee80211_rx_status *rx_status);
void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status,
struct rtw_rx_pkt_stat *pkt_stat);
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 21d0754dd7f6..799230eb5f16 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -864,7 +864,7 @@ static void rtw_sdio_tx_skb_prepare(struct rtw_dev *rtwdev,
pkt_info->qsel = rtw_sdio_get_tx_qsel(rtwdev, skb, queue);
- rtw_tx_fill_tx_desc(pkt_info, skb);
+ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, pkt_desc);
}
@@ -981,8 +981,7 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len)
while (true) {
rx_desc = skb->data;
- chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
- &rx_status);
+ rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
pkt_stat.shift;
@@ -1297,12 +1296,12 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev)
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
int i;
- for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
- skb_queue_purge(&rtwsdio->tx_queue[i]);
-
flush_workqueue(rtwsdio->txwq);
destroy_workqueue(rtwsdio->txwq);
kfree(rtwsdio->tx_handler_data);
+
+ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
+ ieee80211_purge_tx_queue(rtwdev->hw, &rtwsdio->tx_queue[i]);
}
int rtw_sdio_probe(struct sdio_func *sdio_func,
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index dae7ca148865..6ed470dd6f22 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -32,7 +32,8 @@ void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
}
}
-void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
+void rtw_tx_fill_tx_desc(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
{
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
bool more_data = false;
@@ -67,6 +68,9 @@ void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE);
+ if (rtwdev->chip->old_datarate_fb_limit)
+ tx_desc->w4 |= le32_encode_bits(0x1f, RTW_TX_DESC_W4_DATARATE_FB_LIMIT);
+
tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) |
le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) |
le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) |
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index 3d544fd7f60f..d34cdeca16f1 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -44,6 +44,7 @@ struct rtw_tx_desc {
#define RTW_TX_DESC_W3_NAVUSEHDR BIT(15)
#define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17)
#define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0)
+#define RTW_TX_DESC_W4_DATARATE_FB_LIMIT GENMASK(12, 8)
#define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24)
#define RTW_TX_DESC_W5_DATA_SHORT BIT(4)
#define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5)
@@ -94,7 +95,8 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct ieee80211_sta *sta,
struct sk_buff *skb);
-void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
+void rtw_tx_fill_tx_desc(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn);
void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src);
void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index b17a429bcd29..8d6db68246f1 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -423,10 +423,11 @@ static void rtw_usb_tx_handler(struct work_struct *work)
static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb)
{
+ struct rtw_dev *rtwdev = rtwusb->rtwdev;
int i;
for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
- skb_queue_purge(&rtwusb->tx_queue[i]);
+ ieee80211_purge_tx_queue(rtwdev->hw, &rtwusb->tx_queue[i]);
}
static void rtw_usb_write_port_complete(struct urb *urb)
@@ -457,7 +458,7 @@ static int rtw_usb_write_data(struct rtw_dev *rtwdev,
skb_put_data(skb, buf, size);
skb_push(skb, chip->tx_pkt_desc_sz);
memset(skb->data, 0, chip->tx_pkt_desc_sz);
- rtw_tx_fill_tx_desc(pkt_info, skb);
+ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
ret = rtw_usb_write_port(rtwdev, qsel, skb,
@@ -477,6 +478,7 @@ static int rtw_usb_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf,
pkt_info.tx_pkt_size = size;
pkt_info.qsel = TX_DESC_QSEL_BEACON;
pkt_info.offset = chip->tx_pkt_desc_sz;
+ pkt_info.ls = true;
return rtw_usb_write_data(rtwdev, &pkt_info, buf);
}
@@ -524,7 +526,7 @@ static int rtw_usb_tx_write(struct rtw_dev *rtwdev,
pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
ep = qsel_to_ep(rtwusb, pkt_info->qsel);
- rtw_tx_fill_tx_desc(pkt_info, skb);
+ rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
tx_data = rtw_usb_get_tx_data(skb);
tx_data->sn = pkt_info->sn;
@@ -570,8 +572,8 @@ static void rtw_usb_rx_handler(struct work_struct *work)
do {
rx_desc = skb->data;
- chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
- &rx_status);
+ rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat,
+ &rx_status);
pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
pkt_stat.shift;
@@ -888,9 +890,9 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev)
{
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
- rtw_usb_tx_queue_purge(rtwusb);
flush_workqueue(rtwusb->txwq);
destroy_workqueue(rtwusb->txwq);
+ rtw_usb_tx_queue_purge(rtwusb);
}
static int rtw_usb_intf_init(struct rtw_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c
index 4476fc7e53db..8ef59994c0db 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.c
+++ b/drivers/net/wireless/realtek/rtw89/cam.c
@@ -211,25 +211,17 @@ static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam,
return 0;
}
-static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- const struct rtw89_sec_cam_entry *sec_cam,
- bool inform_fw)
+static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ const struct rtw89_sec_cam_entry *sec_cam,
+ bool inform_fw)
{
- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
- struct rtw89_vif *rtwvif;
struct rtw89_addr_cam_entry *addr_cam;
unsigned int i;
int ret = 0;
- if (!vif) {
- rtw89_err(rtwdev, "No iface for deleting sec cam\n");
- return -EINVAL;
- }
-
- rtwvif = (struct rtw89_vif *)vif->drv_priv;
- addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
+ addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) {
if (addr_cam->sec_ent[i] != sec_cam->sec_cam_idx)
@@ -239,11 +231,11 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
}
if (inform_fw) {
- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
+ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link);
if (ret)
rtw89_err(rtwdev,
"failed to update dctl cam del key: %d\n", ret);
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
if (ret)
rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret);
}
@@ -251,25 +243,17 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
return ret;
}
-static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key,
- struct rtw89_sec_cam_entry *sec_cam)
+static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ struct ieee80211_key_conf *key,
+ struct rtw89_sec_cam_entry *sec_cam)
{
- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
- struct rtw89_vif *rtwvif;
struct rtw89_addr_cam_entry *addr_cam;
u8 key_idx = 0;
int ret;
- if (!vif) {
- rtw89_err(rtwdev, "No iface for adding sec cam\n");
- return -EINVAL;
- }
-
- rtwvif = (struct rtw89_vif *)vif->drv_priv;
- addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
+ addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
key->cipher == WLAN_CIPHER_SUITE_WEP104)
@@ -285,13 +269,13 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
addr_cam->sec_ent_keyid[key_idx] = key->keyidx;
addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx;
set_bit(key_idx, addr_cam->sec_cam_map);
- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
+ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link);
if (ret) {
rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n",
ret);
return ret;
}
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
if (ret) {
rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n",
ret);
@@ -302,6 +286,92 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
return 0;
}
+static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ const struct rtw89_sec_cam_entry *sec_cam,
+ bool inform_fw)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+ struct rtw89_sta_link *rtwsta_link;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_vif *rtwvif;
+ unsigned int link_id;
+ int ret;
+
+ if (!vif) {
+ rtw89_err(rtwdev, "No iface for deleting sec cam\n");
+ return -EINVAL;
+ }
+
+ rtwvif = vif_to_rtwvif(vif);
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ rtwsta_link = rtwsta ? rtwsta->links[link_id] : NULL;
+ if (rtwsta && !rtwsta_link)
+ continue;
+
+ ret = __rtw89_cam_detach_sec_cam(rtwdev, rtwvif_link, rtwsta_link,
+ sec_cam, inform_fw);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ struct rtw89_sec_cam_entry *sec_cam)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+ struct rtw89_sta_link *rtwsta_link;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_vif *rtwvif;
+ unsigned int link_id;
+ int key_link_id;
+ int ret;
+
+ if (!vif) {
+ rtw89_err(rtwdev, "No iface for adding sec cam\n");
+ return -EINVAL;
+ }
+
+ rtwvif = vif_to_rtwvif(vif);
+
+ key_link_id = ieee80211_vif_is_mld(vif) ? key->link_id : 0;
+ if (key_link_id >= 0) {
+ rtwvif_link = rtwvif->links[key_link_id];
+ rtwsta_link = rtwsta ? rtwsta->links[key_link_id] : NULL;
+
+ if (!rtwvif_link || (rtwsta && !rtwsta_link)) {
+ rtw89_err(rtwdev, "No drv link for adding sec cam\n");
+ return -ENOLINK;
+ }
+
+ return __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link,
+ rtwsta_link, key, sec_cam);
+ }
+
+ /* key_link_id < 0: MLD pairwise key */
+ if (!rtwsta) {
+ rtw89_err(rtwdev, "No sta for adding MLD pairwise sec cam\n");
+ return -EINVAL;
+ }
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ ret = __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link,
+ rtwsta_link, key, sec_cam);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -485,10 +555,10 @@ void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev,
clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map);
}
-void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
+ struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam;
+ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam;
rtw89_cam_deinit_addr_cam(rtwdev, addr_cam);
rtw89_cam_deinit_bssid_cam(rtwdev, bssid_cam);
@@ -593,7 +663,7 @@ static int rtw89_cam_get_avail_bssid_cam(struct rtw89_dev *rtwdev,
}
int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct rtw89_bssid_cam_entry *bssid_cam,
const u8 *bssid)
{
@@ -613,7 +683,7 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev,
}
bssid_cam->bssid_cam_idx = bssid_cam_idx;
- bssid_cam->phy_idx = rtwvif->phy_idx;
+ bssid_cam->phy_idx = rtwvif_link->phy_idx;
bssid_cam->len = BSSID_CAM_ENT_SIZE;
bssid_cam->offset = 0;
bssid_cam->valid = true;
@@ -622,20 +692,21 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev,
return 0;
}
-void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
+ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam;
- ether_addr_copy(bssid_cam->bssid, rtwvif->bssid);
+ ether_addr_copy(bssid_cam->bssid, rtwvif_link->bssid);
}
-int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
+ struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam;
+ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam;
int ret;
- ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, rtwvif->bssid);
+ ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam,
+ rtwvif_link->bssid);
if (ret) {
rtw89_err(rtwdev, "failed to init bssid cam\n");
return ret;
@@ -651,19 +722,27 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
}
int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta, u8 *cmd)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link, u8 *cmd)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta);
- u8 bss_color = vif->bss_conf.he_bss_color.color;
+ struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link,
+ rtwsta_link);
+ struct ieee80211_bss_conf *bss_conf;
+ u8 bss_color;
u8 bss_mask;
- if (vif->bss_conf.nontransmitted)
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
+ bss_color = bss_conf->he_bss_color.color;
+
+ if (bss_conf->nontransmitted)
bss_mask = RTW89_BSSID_MATCH_5_BYTES;
else
bss_mask = RTW89_BSSID_MATCH_ALL;
+ rcu_read_unlock();
+
FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx);
FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset);
FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len);
@@ -694,19 +773,30 @@ static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr)
}
void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
const u8 *scan_mac_addr,
u8 *cmd)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
- struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta);
- const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr;
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct rtw89_addr_cam_entry *addr_cam =
+ rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
+ struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link);
+ struct ieee80211_link_sta *link_sta;
+ const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr;
u8 sma_hash, tma_hash, addr_msk_start;
u8 sma_start = 0;
u8 tma_start = 0;
- u8 *tma = sta ? sta->addr : rtwvif->bssid;
+ const u8 *tma;
+
+ rcu_read_lock();
+
+ if (sta) {
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ tma = link_sta->addr;
+ } else {
+ tma = rtwvif_link->bssid;
+ }
if (addr_cam->addr_mask != 0) {
addr_msk_start = __ffs(addr_cam->addr_mask);
@@ -723,10 +813,10 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
FWCMD_SET_ADDR_LEN(cmd, addr_cam->len);
FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid);
- FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif->net_type);
- FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif->bcn_hit_cond);
- FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif->hit_rule);
- FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif->phy_idx);
+ FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif_link->net_type);
+ FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif_link->bcn_hit_cond);
+ FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif_link->hit_rule);
+ FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif_link->phy_idx);
FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask);
FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel);
FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash);
@@ -748,20 +838,21 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
FWCMD_SET_ADDR_TMA4(cmd, tma[4]);
FWCMD_SET_ADDR_TMA5(cmd, tma[5]);
- FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif->port);
- FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif->port);
- FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif->trigger);
- FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif->lsig_txop);
- FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif->tgt_ind);
- FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif->frm_tgt_ind);
- FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id);
- if (rtwvif->net_type == RTW89_NET_TYPE_INFRA)
+ FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif_link->port);
+ FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif_link->port);
+ FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif_link->trigger);
+ FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif_link->lsig_txop);
+ FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif_link->tgt_ind);
+ FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif_link->frm_tgt_ind);
+ FWCMD_SET_ADDR_MACID(cmd, rtwsta_link ? rtwsta_link->mac_id :
+ rtwvif_link->mac_id);
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA)
FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff);
- else if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
+ else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0);
- FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif->wowlan_pattern);
- FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif->wowlan_uc);
- FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif->wowlan_magic);
+ FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif_link->wowlan_pattern);
+ FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif_link->wowlan_uc);
+ FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif_link->wowlan_magic);
FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi);
FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode);
FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]);
@@ -780,18 +871,22 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]);
FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]);
FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]);
+
+ rcu_read_unlock();
}
void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
struct rtw89_h2c_dctlinfo_ud_v1 *h2c)
{
- struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
+ struct rtw89_addr_cam_entry *addr_cam =
+ rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv;
- h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id,
+ h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id :
+ rtwvif_link->mac_id,
DCTLINFO_V1_C0_MACID) |
le32_encode_bits(1, DCTLINFO_V1_C0_OP);
@@ -862,18 +957,28 @@ void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
}
void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
struct rtw89_h2c_dctlinfo_ud_v2 *h2c)
{
- struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
+ struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link);
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link->rtwvif);
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+ struct rtw89_addr_cam_entry *addr_cam =
+ rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link);
+ bool is_mld = sta ? sta->mlo : ieee80211_vif_is_mld(vif);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv;
+ u8 *mld_sma, *mld_tma, *mld_bssid;
- h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id,
+ h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id :
+ rtwvif_link->mac_id,
DCTLINFO_V2_C0_MACID) |
le32_encode_bits(1, DCTLINFO_V2_C0_OP);
+ h2c->w2 = le32_encode_bits(is_mld, DCTLINFO_V2_W2_IS_MLD);
+ h2c->m2 = cpu_to_le32(DCTLINFO_V2_W2_IS_MLD);
+
h2c->w4 = le32_encode_bits(addr_cam->sec_ent_keyid[0],
DCTLINFO_V2_W4_SEC_ENT0_KEYID) |
le32_encode_bits(addr_cam->sec_ent_keyid[1],
@@ -939,4 +1044,47 @@ void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
DCTLINFO_V2_W4_SEC_KEY_ID);
h2c->m4 |= cpu_to_le32(DCTLINFO_V2_W4_SEC_KEY_ID);
}
+
+ if (!is_mld)
+ return;
+
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) {
+ mld_sma = rtwvif->mac_addr;
+ mld_tma = vif->cfg.ap_addr;
+ mld_bssid = vif->cfg.ap_addr;
+ } else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE && sta) {
+ mld_sma = rtwvif->mac_addr;
+ mld_tma = sta->addr;
+ mld_bssid = rtwvif->mac_addr;
+ } else {
+ return;
+ }
+
+ h2c->w8 = le32_encode_bits(mld_sma[0], DCTLINFO_V2_W8_MLD_SMA_0) |
+ le32_encode_bits(mld_sma[1], DCTLINFO_V2_W8_MLD_SMA_1) |
+ le32_encode_bits(mld_sma[2], DCTLINFO_V2_W8_MLD_SMA_2) |
+ le32_encode_bits(mld_sma[3], DCTLINFO_V2_W8_MLD_SMA_3);
+ h2c->m8 = cpu_to_le32(DCTLINFO_V2_W8_ALL);
+
+ h2c->w9 = le32_encode_bits(mld_sma[4], DCTLINFO_V2_W9_MLD_SMA_4) |
+ le32_encode_bits(mld_sma[5], DCTLINFO_V2_W9_MLD_SMA_5) |
+ le32_encode_bits(mld_tma[0], DCTLINFO_V2_W9_MLD_TMA_0) |
+ le32_encode_bits(mld_tma[1], DCTLINFO_V2_W9_MLD_TMA_1);
+ h2c->m9 = cpu_to_le32(DCTLINFO_V2_W9_ALL);
+
+ h2c->w10 = le32_encode_bits(mld_tma[2], DCTLINFO_V2_W10_MLD_TMA_2) |
+ le32_encode_bits(mld_tma[3], DCTLINFO_V2_W10_MLD_TMA_3) |
+ le32_encode_bits(mld_tma[4], DCTLINFO_V2_W10_MLD_TMA_4) |
+ le32_encode_bits(mld_tma[5], DCTLINFO_V2_W10_MLD_TMA_5);
+ h2c->m10 = cpu_to_le32(DCTLINFO_V2_W10_ALL);
+
+ h2c->w11 = le32_encode_bits(mld_bssid[0], DCTLINFO_V2_W11_MLD_BSSID_0) |
+ le32_encode_bits(mld_bssid[1], DCTLINFO_V2_W11_MLD_BSSID_1) |
+ le32_encode_bits(mld_bssid[2], DCTLINFO_V2_W11_MLD_BSSID_2) |
+ le32_encode_bits(mld_bssid[3], DCTLINFO_V2_W11_MLD_BSSID_3);
+ h2c->m11 = cpu_to_le32(DCTLINFO_V2_W11_ALL);
+
+ h2c->w12 = le32_encode_bits(mld_bssid[4], DCTLINFO_V2_W12_MLD_BSSID_4) |
+ le32_encode_bits(mld_bssid[5], DCTLINFO_V2_W12_MLD_BSSID_5);
+ h2c->m12 = cpu_to_le32(DCTLINFO_V2_W12_ALL);
}
diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h
index 5d7b624c2dd4..3134ebf08825 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.h
+++ b/drivers/net/wireless/realtek/rtw89/cam.h
@@ -514,46 +514,58 @@ struct rtw89_h2c_dctlinfo_ud_v2 {
#define DCTLINFO_V2_W7_SEC_ENT7 GENMASK(23, 16)
#define DCTLINFO_V2_W7_SEC_ENT8 GENMASK(31, 24)
#define DCTLINFO_V2_W7_ALL GENMASK(31, 0)
-#define DCTLINFO_V2_W8_MLD_SMA_L_V1 GENMASK(31, 0)
+#define DCTLINFO_V2_W8_MLD_SMA_0 GENMASK(7, 0)
+#define DCTLINFO_V2_W8_MLD_SMA_1 GENMASK(15, 8)
+#define DCTLINFO_V2_W8_MLD_SMA_2 GENMASK(23, 16)
+#define DCTLINFO_V2_W8_MLD_SMA_3 GENMASK(31, 24)
#define DCTLINFO_V2_W8_ALL GENMASK(31, 0)
-#define DCTLINFO_V2_W9_MLD_SMA_H_V1 GENMASK(15, 0)
-#define DCTLINFO_V2_W9_MLD_TMA_L_V1 GENMASK(31, 16)
+#define DCTLINFO_V2_W9_MLD_SMA_4 GENMASK(7, 0)
+#define DCTLINFO_V2_W9_MLD_SMA_5 GENMASK(15, 8)
+#define DCTLINFO_V2_W9_MLD_TMA_0 GENMASK(23, 16)
+#define DCTLINFO_V2_W9_MLD_TMA_1 GENMASK(31, 24)
#define DCTLINFO_V2_W9_ALL GENMASK(31, 0)
-#define DCTLINFO_V2_W10_MLD_TMA_H_V1 GENMASK(31, 0)
+#define DCTLINFO_V2_W10_MLD_TMA_2 GENMASK(7, 0)
+#define DCTLINFO_V2_W10_MLD_TMA_3 GENMASK(15, 8)
+#define DCTLINFO_V2_W10_MLD_TMA_4 GENMASK(23, 16)
+#define DCTLINFO_V2_W10_MLD_TMA_5 GENMASK(31, 24)
#define DCTLINFO_V2_W10_ALL GENMASK(31, 0)
-#define DCTLINFO_V2_W11_MLD_TA_BSSID_L_V1 GENMASK(31, 0)
+#define DCTLINFO_V2_W11_MLD_BSSID_0 GENMASK(7, 0)
+#define DCTLINFO_V2_W11_MLD_BSSID_1 GENMASK(15, 8)
+#define DCTLINFO_V2_W11_MLD_BSSID_2 GENMASK(23, 16)
+#define DCTLINFO_V2_W11_MLD_BSSID_3 GENMASK(31, 24)
#define DCTLINFO_V2_W11_ALL GENMASK(31, 0)
-#define DCTLINFO_V2_W12_MLD_TA_BSSID_H_V1 GENMASK(15, 0)
+#define DCTLINFO_V2_W12_MLD_BSSID_4 GENMASK(7, 0)
+#define DCTLINFO_V2_W12_MLD_BSSID_5 GENMASK(15, 8)
#define DCTLINFO_V2_W12_ALL GENMASK(15, 0)
-int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
-void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
+int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);
+void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);
int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
struct rtw89_addr_cam_entry *addr_cam,
const struct rtw89_bssid_cam_entry *bssid_cam);
void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev,
struct rtw89_addr_cam_entry *addr_cam);
int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct rtw89_bssid_cam_entry *bssid_cam,
const u8 *bssid);
void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev,
struct rtw89_bssid_cam_entry *bssid_cam);
void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
- struct rtw89_vif *vif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *vif,
+ struct rtw89_sta_link *rtwsta_link,
const u8 *scan_mac_addr, u8 *cmd);
void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
struct rtw89_h2c_dctlinfo_ud_v1 *h2c);
void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
struct rtw89_h2c_dctlinfo_ud_v2 *h2c);
int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta, u8 *cmd);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link, u8 *cmd);
int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -564,6 +576,6 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev,
struct ieee80211_key_conf *key,
bool inform_fw);
void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
+ struct rtw89_vif_link *rtwvif_link);
void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 7070c85e2c28..fb9449930c40 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -10,6 +10,10 @@
#include "ps.h"
#include "util.h"
+static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
+ enum rtw89_chanctx_idx idx1,
+ enum rtw89_chanctx_idx idx2);
+
static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
u8 center_chan)
{
@@ -226,14 +230,30 @@ static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
void rtw89_entity_init(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
hal->entity_pause = false;
bitmap_zero(hal->entity_map, NUM_OF_RTW89_CHANCTX);
bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
atomic_set(&hal->roc_chanctx_idx, RTW89_CHANCTX_IDLE);
+
+ INIT_LIST_HEAD(&mgnt->active_list);
+
rtw89_config_default_chandef(rtwdev);
}
+static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif)
+{
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ if (rtwvif_link->chanctx_assigned)
+ return true;
+
+ return false;
+}
+
static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
struct rtw89_entity_weight *w)
{
@@ -255,11 +275,147 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
}
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
- if (rtwvif->chanctx_assigned)
+ if (rtw89_vif_is_active_role(rtwvif))
w->active_roles++;
}
}
+static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+ struct rtw89_vif_link *cur;
+
+ if (unlikely(!rtwvif_link->chanctx_assigned))
+ return;
+
+ cur = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (!cur || !cur->chanctx_assigned)
+ return;
+
+ if (cur == rtwvif_link)
+ return;
+
+ rtw89_swap_chanctx(rtwdev, rtwvif_link->chanctx_idx, cur->chanctx_idx);
+}
+
+const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
+ const char *caller_message,
+ u8 link_index)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
+ enum rtw89_chanctx_idx chanctx_idx;
+ enum rtw89_chanctx_idx roc_idx;
+ enum rtw89_entity_mode mode;
+ u8 role_index;
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ if (unlikely(link_index >= __RTW89_MLD_MAX_LINK_NUM)) {
+ WARN(1, "link index %u is invalid (max link inst num: %d)\n",
+ link_index, __RTW89_MLD_MAX_LINK_NUM);
+ goto dflt;
+ }
+
+ mode = rtw89_get_entity_mode(rtwdev);
+ switch (mode) {
+ case RTW89_ENTITY_MODE_SCC_OR_SMLD:
+ case RTW89_ENTITY_MODE_MCC:
+ role_index = 0;
+ break;
+ case RTW89_ENTITY_MODE_MCC_PREPARE:
+ role_index = 1;
+ break;
+ default:
+ WARN(1, "Invalid ent mode: %d\n", mode);
+ goto dflt;
+ }
+
+ chanctx_idx = mgnt->chanctx_tbl[role_index][link_index];
+ if (chanctx_idx == RTW89_CHANCTX_IDLE)
+ goto dflt;
+
+ roc_idx = atomic_read(&hal->roc_chanctx_idx);
+ if (roc_idx != RTW89_CHANCTX_IDLE) {
+ /* ROC is ongoing (given ROC runs on RTW89_ROC_BY_LINK_INDEX).
+ * If @link_index is the same as RTW89_ROC_BY_LINK_INDEX, get
+ * the ongoing ROC chanctx.
+ */
+ if (link_index == RTW89_ROC_BY_LINK_INDEX)
+ chanctx_idx = roc_idx;
+ }
+
+ return rtw89_chan_get(rtwdev, chanctx_idx);
+
+dflt:
+ rtw89_debug(rtwdev, RTW89_DBG_CHAN,
+ "%s (%s): prefetch NULL on link index %u\n",
+ __func__, caller_message ?: "", link_index);
+
+ return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
+}
+EXPORT_SYMBOL(__rtw89_mgnt_chan_get);
+
+static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
+ struct rtw89_vif_link *link;
+ struct rtw89_vif *role;
+ u8 pos = 0;
+ int i, j;
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++)
+ mgnt->active_roles[i] = NULL;
+
+ for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) {
+ for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++)
+ mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE;
+ }
+
+ /* To be consistent with legacy behavior, expect the first active role
+ * which uses RTW89_CHANCTX_0 to put at position 0, and make its first
+ * link instance take RTW89_CHANCTX_0. (normalizing)
+ */
+ list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
+ for (i = 0; i < role->links_inst_valid_num; i++) {
+ link = rtw89_vif_get_link_inst(role, i);
+ if (!link || !link->chanctx_assigned)
+ continue;
+
+ if (link->chanctx_idx == RTW89_CHANCTX_0) {
+ rtw89_normalize_link_chanctx(rtwdev, link);
+
+ list_del(&role->mgnt_entry);
+ list_add(&role->mgnt_entry, &mgnt->active_list);
+ break;
+ }
+ }
+ }
+
+ list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
+ if (unlikely(pos >= RTW89_MAX_INTERFACE_NUM)) {
+ rtw89_warn(rtwdev,
+ "%s: active roles are over max iface num\n",
+ __func__);
+ break;
+ }
+
+ for (i = 0; i < role->links_inst_valid_num; i++) {
+ link = rtw89_vif_get_link_inst(role, i);
+ if (!link || !link->chanctx_assigned)
+ continue;
+
+ mgnt->chanctx_tbl[pos][i] = link->chanctx_idx;
+ }
+
+ mgnt->active_roles[pos++] = role;
+ }
+}
+
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
{
DECLARE_BITMAP(recalc_map, NUM_OF_RTW89_CHANCTX) = {};
@@ -286,9 +442,14 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
set_bit(RTW89_CHANCTX_0, recalc_map);
fallthrough;
case 1:
- mode = RTW89_ENTITY_MODE_SCC;
+ mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
break;
case 2 ... NUM_OF_RTW89_CHANCTX:
+ if (w.active_roles == 1) {
+ mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
+ break;
+ }
+
if (w.active_roles != NUM_OF_RTW89_MCC_ROLES) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"unhandled ent: %d chanctxs %d roles\n",
@@ -315,6 +476,8 @@ enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
rtw89_assign_entity_chan(rtwdev, idx, &chan);
}
+ rtw89_entity_recalc_mgnt_roles(rtwdev);
+
if (hal->entity_pause)
return rtw89_get_entity_mode(rtwdev);
@@ -387,9 +550,9 @@ int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev,
static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *role, u64 tsf)
{
- struct rtw89_vif *rtwvif = role->rtwvif;
+ struct rtw89_vif_link *rtwvif_link = role->rtwvif_link;
u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval);
- u64 sync_tsf = READ_ONCE(rtwvif->sync_bcn_tsf);
+ u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
u32 remainder;
if (tsf < sync_tsf) {
@@ -413,8 +576,8 @@ static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux
int ret;
req.group = mcc->group;
- req.macid_x = ref->rtwvif->mac_id;
- req.macid_y = aux->rtwvif->mac_id;
+ req.macid_x = ref->rtwvif_link->mac_id;
+ req.macid_y = aux->rtwvif_link->mac_id;
ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
@@ -440,10 +603,10 @@ static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux
BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES);
arg.num = 2;
- arg.infos[0].band = ref->rtwvif->mac_idx;
- arg.infos[0].port = ref->rtwvif->port;
- arg.infos[1].band = aux->rtwvif->mac_idx;
- arg.infos[1].port = aux->rtwvif->port;
+ arg.infos[0].band = ref->rtwvif_link->mac_idx;
+ arg.infos[0].port = ref->rtwvif_link->port;
+ arg.infos[1].band = aux->rtwvif_link->mac_idx;
+ arg.infos[1].port = aux->rtwvif_link->port;
ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt);
if (ret) {
@@ -522,23 +685,31 @@ out:
static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_mcc_role *mcc_role = data;
- struct rtw89_vif *target = mcc_role->rtwvif;
+ struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_sta_link *rtwsta_link;
if (rtwvif != target)
return;
- rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta->mac_id);
+ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+ if (unlikely(!rtwsta_link)) {
+ rtw89_err(rtwdev, "mcc sta macid: find no link on HW-0\n");
+ return;
+ }
+
+ rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id);
}
static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *mcc_role)
{
- struct rtw89_vif *rtwvif = mcc_role->rtwvif;
+ struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
- rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif->mac_id);
+ rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id);
ieee80211_iterate_stations_atomic(rtwdev->hw,
rtw89_mcc_role_macid_sta_iter,
mcc_role);
@@ -564,8 +735,9 @@ static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev,
static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *mcc_role)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(mcc_role->rtwvif);
+ struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
struct ieee80211_p2p_noa_desc *noa_desc;
+ struct ieee80211_bss_conf *bss_conf;
u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval);
u32 max_toa_us, max_tob_us, max_dur_us;
u32 start_time, interval, duration;
@@ -576,13 +748,18 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
if (!mcc_role->is_go && !mcc_role->is_gc)
return;
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+
/* find the first periodic NoA */
for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) {
- noa_desc = &vif->bss_conf.p2p_noa_attr.desc[i];
+ noa_desc = &bss_conf->p2p_noa_attr.desc[i];
if (noa_desc->count == 255)
goto fill;
}
+ rcu_read_unlock();
return;
fill:
@@ -590,6 +767,8 @@ fill:
interval = le32_to_cpu(noa_desc->interval);
duration = le32_to_cpu(noa_desc->duration);
+ rcu_read_unlock();
+
if (interval != bcn_intvl_us) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC role limit: mismatch interval: %d vs. %d\n",
@@ -597,7 +776,7 @@ fill:
return;
}
- ret = rtw89_mac_port_get_tsf(rtwdev, mcc_role->rtwvif, &tsf);
+ ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
if (ret) {
rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
return;
@@ -632,15 +811,21 @@ fill:
}
static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct rtw89_mcc_role *role)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_bss_conf *bss_conf;
const struct rtw89_chan *chan;
memset(role, 0, sizeof(*role));
- role->rtwvif = rtwvif;
- role->beacon_interval = vif->bss_conf.beacon_int;
+ role->rtwvif_link = rtwvif_link;
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ role->beacon_interval = bss_conf->beacon_int;
+
+ rcu_read_unlock();
if (!role->beacon_interval) {
rtw89_warn(rtwdev,
@@ -650,10 +835,10 @@ static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev,
role->duration = role->beacon_interval / 2;
- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx);
+ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
role->is_2ghz = chan->band_type == RTW89_BAND_2G;
- role->is_go = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_GO;
- role->is_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
+ role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO;
+ role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
rtw89_mcc_fill_role_macid_bitmap(rtwdev, role);
rtw89_mcc_fill_role_policy(rtwdev, role);
@@ -678,10 +863,11 @@ static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev)
}
struct rtw89_mcc_fill_role_selector {
- struct rtw89_vif *bind_vif[NUM_OF_RTW89_CHANCTX];
+ struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX];
};
static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES);
+static_assert(RTW89_MAX_INTERFACE_NUM >= NUM_OF_RTW89_MCC_ROLES);
static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *mcc_role,
@@ -689,7 +875,7 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,
void *data)
{
struct rtw89_mcc_fill_role_selector *sel = data;
- struct rtw89_vif *role_vif = sel->bind_vif[ordered_idx];
+ struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx];
int ret;
if (!role_vif) {
@@ -711,22 +897,26 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,
static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
struct rtw89_mcc_fill_role_selector sel = {};
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
int ret;
+ int i;
- rtw89_for_each_rtwvif(rtwdev, rtwvif) {
- if (!rtwvif->chanctx_assigned)
- continue;
+ for (i = 0; i < NUM_OF_RTW89_MCC_ROLES; i++) {
+ rtwvif = mgnt->active_roles[i];
+ if (!rtwvif)
+ break;
- if (sel.bind_vif[rtwvif->chanctx_idx]) {
- rtw89_warn(rtwdev,
- "MCC skip extra vif <macid %d> on chanctx[%d]\n",
- rtwvif->mac_id, rtwvif->chanctx_idx);
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n");
continue;
}
- sel.bind_vif[rtwvif->chanctx_idx] = rtwvif;
+ sel.bind_vif[i] = rtwvif_link;
}
ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel);
@@ -754,13 +944,13 @@ static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev,
memset(&pattern->courtesy, 0, sizeof(pattern->courtesy));
if (pattern->tob_aux <= 0 || pattern->toa_aux <= 0) {
- pattern->courtesy.macid_tgt = aux->rtwvif->mac_id;
- pattern->courtesy.macid_src = ref->rtwvif->mac_id;
+ pattern->courtesy.macid_tgt = aux->rtwvif_link->mac_id;
+ pattern->courtesy.macid_src = ref->rtwvif_link->mac_id;
pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
pattern->courtesy.enable = true;
} else if (pattern->tob_ref <= 0 || pattern->toa_ref <= 0) {
- pattern->courtesy.macid_tgt = ref->rtwvif->mac_id;
- pattern->courtesy.macid_src = aux->rtwvif->mac_id;
+ pattern->courtesy.macid_tgt = ref->rtwvif_link->mac_id;
+ pattern->courtesy.macid_src = aux->rtwvif_link->mac_id;
pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
pattern->courtesy.enable = true;
}
@@ -1263,7 +1453,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev,
u64 tsf_src;
int ret;
- ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif, &tsf_src);
+ ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif_link, &tsf_src);
if (ret) {
rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
return;
@@ -1280,12 +1470,12 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev,
div_u64_rem(tbtt_tgt, bcn_intvl_src_us, &remainder);
tsf_ofst_tgt = bcn_intvl_src_us - remainder;
- config->sync.macid_tgt = tgt->rtwvif->mac_id;
- config->sync.band_tgt = tgt->rtwvif->mac_idx;
- config->sync.port_tgt = tgt->rtwvif->port;
- config->sync.macid_src = src->rtwvif->mac_id;
- config->sync.band_src = src->rtwvif->mac_idx;
- config->sync.port_src = src->rtwvif->port;
+ config->sync.macid_tgt = tgt->rtwvif_link->mac_id;
+ config->sync.band_tgt = tgt->rtwvif_link->mac_idx;
+ config->sync.port_tgt = tgt->rtwvif_link->port;
+ config->sync.macid_src = src->rtwvif_link->mac_id;
+ config->sync.band_src = src->rtwvif_link->mac_idx;
+ config->sync.port_src = src->rtwvif_link->port;
config->sync.offset = tsf_ofst_tgt / 1024;
config->sync.enable = true;
@@ -1294,7 +1484,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev,
config->sync.macid_tgt, config->sync.macid_src,
config->sync.offset);
- rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif, src->rtwvif,
+ rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif_link, src->rtwvif_link,
config->sync.offset);
}
@@ -1305,13 +1495,13 @@ static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev)
struct rtw89_mcc_config *config = &mcc->config;
u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
u32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref);
- struct rtw89_vif *rtwvif = ref->rtwvif;
+ struct rtw89_vif_link *rtwvif_link = ref->rtwvif_link;
u64 tsf, start_tsf;
u32 cur_tbtt_ofst;
u64 min_time;
int ret;
- ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf);
+ ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
if (ret) {
rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
return ret;
@@ -1390,13 +1580,13 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro
const struct rtw89_chan *chan;
int ret;
- chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx);
+ chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
req.central_ch_seg0 = chan->channel;
req.primary_ch = chan->primary_channel;
req.bandwidth = chan->band_width;
req.ch_band_type = chan->band_type;
- req.macid = role->rtwvif->mac_id;
+ req.macid = role->rtwvif_link->mac_id;
req.group = mcc->group;
req.c2h_rpt = policy->c2h_rpt;
req.tx_null_early = policy->tx_null_early;
@@ -1421,7 +1611,7 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro
}
ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
- role->rtwvif->mac_id,
+ role->rtwvif_link->mac_id,
role->macid_bitmap);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
@@ -1448,7 +1638,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role,
slot_arg->duration = role->duration;
slot_arg->role_num = 1;
- chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx);
+ chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI;
slot_arg->roles[0].is_master = role == ref;
@@ -1458,7 +1648,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role,
slot_arg->roles[0].primary_ch = chan->primary_channel;
slot_arg->roles[0].en_tx_null = !policy->dis_tx_null;
slot_arg->roles[0].null_early = policy->tx_null_early;
- slot_arg->roles[0].macid = role->rtwvif->mac_id;
+ slot_arg->roles[0].macid = role->rtwvif_link->mac_id;
slot_arg->roles[0].macid_main_bitmap =
rtw89_mcc_role_fw_macid_bitmap_to_u32(role);
}
@@ -1569,7 +1759,7 @@ static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace)
}
}
- req.macid = ref->rtwvif->mac_id;
+ req.macid = ref->rtwvif_link->mac_id;
req.tsf_high = config->start_tsf >> 32;
req.tsf_low = config->start_tsf;
@@ -1598,7 +1788,7 @@ static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev,
if (!courtesy->enable)
return;
- if (courtesy->macid_src == ref->rtwvif->mac_id) {
+ if (courtesy->macid_src == ref->rtwvif_link->mac_id) {
slot_arg_src = &arg->slots[ref->slot_idx];
slot_idx_tgt = aux->slot_idx;
} else {
@@ -1717,9 +1907,9 @@ static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_chang
struct rtw89_fw_mcc_duration req = {
.group = mcc->group,
.btc_in_group = false,
- .start_macid = ref->rtwvif->mac_id,
- .macid_x = ref->rtwvif->mac_id,
- .macid_y = aux->rtwvif->mac_id,
+ .start_macid = ref->rtwvif_link->mac_id,
+ .macid_x = ref->rtwvif_link->mac_id,
+ .macid_y = aux->rtwvif_link->mac_id,
.duration_x = ref->duration,
.duration_y = aux->duration,
.start_tsf_high = config->start_tsf >> 32,
@@ -1813,18 +2003,18 @@ static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable)
struct ieee80211_p2p_noa_desc noa_desc = {};
u64 start_time = config->start_tsf;
u32 interval = config->mcc_interval;
- struct rtw89_vif *rtwvif_go;
+ struct rtw89_vif_link *rtwvif_go;
u32 duration;
if (mcc->mode != RTW89_MCC_MODE_GO_STA)
return;
if (ref->is_go) {
- rtwvif_go = ref->rtwvif;
+ rtwvif_go = ref->rtwvif_link;
start_time += ieee80211_tu_to_usec(ref->duration);
duration = config->mcc_interval - ref->duration;
} else if (aux->is_go) {
- rtwvif_go = aux->rtwvif;
+ rtwvif_go = aux->rtwvif_link;
start_time += ieee80211_tu_to_usec(pattern->tob_ref) +
ieee80211_tu_to_usec(config->beacon_offset) +
ieee80211_tu_to_usec(pattern->toa_aux);
@@ -1865,9 +2055,9 @@ static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev)
return;
if (ref->is_go)
- rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, true);
+ rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true);
else if (aux->is_go)
- rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, true);
+ rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true);
rtw89_mcc_handle_beacon_noa(rtwdev, true);
}
@@ -1882,9 +2072,9 @@ static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev)
return;
if (ref->is_go)
- rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, false);
+ rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false);
else if (aux->is_go)
- rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, false);
+ rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false);
rtw89_mcc_handle_beacon_noa(rtwdev, false);
}
@@ -1942,7 +2132,7 @@ struct rtw89_mcc_stop_sel {
static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel,
const struct rtw89_mcc_role *mcc_role)
{
- sel->mac_id = mcc_role->rtwvif->mac_id;
+ sel->mac_id = mcc_role->rtwvif_link->mac_id;
sel->slot_idx = mcc_role->slot_idx;
}
@@ -1953,7 +2143,7 @@ static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev,
{
struct rtw89_mcc_stop_sel *sel = data;
- if (!mcc_role->rtwvif->chanctx_assigned)
+ if (!mcc_role->rtwvif_link->chanctx_assigned)
return 0;
rtw89_mcc_stop_sel_fill(sel, mcc_role);
@@ -2081,7 +2271,7 @@ static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
int ret;
ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
- upd->rtwvif->mac_id,
+ upd->rtwvif_link->mac_id,
upd->macid_bitmap);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
@@ -2106,7 +2296,7 @@ static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
int i;
arg.sch_idx = mcc->group;
- arg.macid = upd->rtwvif->mac_id;
+ arg.macid = upd->rtwvif_link->mac_id;
for (i = 0; i < 32; i++) {
if (add & BIT(i)) {
@@ -2144,7 +2334,7 @@ static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev,
void *data)
{
struct rtw89_mcc_role upd = {
- .rtwvif = mcc_role->rtwvif,
+ .rtwvif_link = mcc_role->rtwvif_link,
};
int ret;
@@ -2370,6 +2560,24 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev)
rtw89_queue_chanctx_work(rtwdev);
}
+static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif,
+ enum rtw89_chanctx_idx idx1,
+ enum rtw89_chanctx_idx idx2)
+{
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ if (!rtwvif_link->chanctx_assigned)
+ continue;
+
+ if (rtwvif_link->chanctx_idx == idx1)
+ rtwvif_link->chanctx_idx = idx2;
+ else if (rtwvif_link->chanctx_idx == idx2)
+ rtwvif_link->chanctx_idx = idx1;
+ }
+}
+
static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_idx idx1,
enum rtw89_chanctx_idx idx2)
@@ -2386,14 +2594,8 @@ static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
swap(hal->chanctx[idx1], hal->chanctx[idx2]);
- rtw89_for_each_rtwvif(rtwdev, rtwvif) {
- if (!rtwvif->chanctx_assigned)
- continue;
- if (rtwvif->chanctx_idx == idx1)
- rtwvif->chanctx_idx = idx2;
- else if (rtwvif->chanctx_idx == idx2)
- rtwvif->chanctx_idx = idx1;
- }
+ rtw89_for_each_rtwvif(rtwdev, rtwvif)
+ __rtw89_swap_chanctx(rtwvif, idx1, idx2);
cur = atomic_read(&hal->roc_chanctx_idx);
if (cur == idx1)
@@ -2444,16 +2646,22 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
}
int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct ieee80211_chanctx_conf *ctx)
{
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
struct rtw89_entity_weight w = {};
- rtwvif->chanctx_idx = cfg->idx;
- rtwvif->chanctx_assigned = true;
+ rtwvif_link->chanctx_idx = cfg->idx;
+ rtwvif_link->chanctx_assigned = true;
cfg->ref_count++;
+ if (list_empty(&rtwvif->mgnt_entry))
+ list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list);
+
if (cfg->idx == RTW89_CHANCTX_0)
goto out;
@@ -2469,20 +2677,24 @@ out:
}
void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct ieee80211_chanctx_conf *ctx)
{
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_hal *hal = &rtwdev->hal;
enum rtw89_chanctx_idx roll;
enum rtw89_entity_mode cur;
enum rtw89_entity_mode new;
int ret;
- rtwvif->chanctx_idx = RTW89_CHANCTX_0;
- rtwvif->chanctx_assigned = false;
+ rtwvif_link->chanctx_idx = RTW89_CHANCTX_0;
+ rtwvif_link->chanctx_assigned = false;
cfg->ref_count--;
+ if (!rtw89_vif_is_active_role(rtwvif))
+ list_del_init(&rtwvif->mgnt_entry);
+
if (cfg->ref_count != 0)
goto out;
diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h
index c6d31984e575..2eb31dff2083 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.h
+++ b/drivers/net/wireless/realtek/rtw89/chan.h
@@ -43,18 +43,21 @@ struct rtw89_entity_weight {
unsigned int active_roles;
};
-static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev)
+static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
{
struct rtw89_hal *hal = &rtwdev->hal;
- return READ_ONCE(hal->entity_active);
+ return READ_ONCE(hal->entity_active[phy_idx]);
}
-static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, bool active)
+static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ bool active)
{
struct rtw89_hal *hal = &rtwdev->hal;
- WRITE_ONCE(hal->entity_active, active);
+ WRITE_ONCE(hal->entity_active[phy_idx], active);
}
static inline
@@ -98,6 +101,14 @@ void rtw89_chanctx_track(struct rtw89_dev *rtwdev);
void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_pause_reasons rsn);
void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev);
+
+const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
+ const char *caller_message,
+ u8 link_index);
+
+#define rtw89_mgnt_chan_get(rtwdev, link_index) \
+ __rtw89_mgnt_chan_get(rtwdev, __func__, link_index)
+
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx);
void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
@@ -106,10 +117,10 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx,
u32 changed);
int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct ieee80211_chanctx_conf *ctx);
void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct ieee80211_chanctx_conf *ctx);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 8d27374db83c..68316d44b204 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -125,6 +125,9 @@ static const u32 cxtbl[] = {
0xfafaaafa, /* 23 */
0xfafffaff, /* 24 */
0xea6a5a5a, /* 25 */
+ 0xfaff5aff, /* 26 */
+ 0xffffdfff, /* 27 */
+ 0xe6555555, /* 28 */
};
static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
@@ -134,77 +137,88 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
.fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
.fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
.fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
- .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6,
+ .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
+ .max_role_num = 6,
},
{RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
.fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
.fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
.fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
.fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
- .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6,
+ .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800,
+ .max_role_num = 6,
},
{RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
.fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
.fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
+ .max_role_num = 6,
},
{RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
.fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
.fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
+ .max_role_num = 5,
},
{RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
.fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
.fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
+ .max_role_num = 5,
},
{RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
.fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
.fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
+ .max_role_num = 5,
},
{RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
.fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
.fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
+ .max_role_num = 6,
},
{RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
.fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
.fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
+ .max_role_num = 6,
},
{RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
.fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
.fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
+ .max_role_num = 5,
},
{RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
.fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
.fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
+ .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280,
+ .max_role_num = 5,
},
{RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
.fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
.fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
.fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5,
+ .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024,
+ .max_role_num = 5,
},
/* keep it to be the last as default entry */
@@ -213,7 +227,8 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
.fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
.fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
.fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
- .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5,
+ .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024,
+ .max_role_num = 5,
},
};
@@ -224,7 +239,7 @@ static const union rtw89_btc_wl_state_map btc_scanning_map = {
.scan = 1,
.connecting = 1,
.roaming = 1,
- .transacting = 1,
+ .dbccing = 1,
._4way = 1,
},
};
@@ -2492,6 +2507,8 @@ static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
if (ver->fcxmreg == 7) {
sz = struct_size(v7, regs, n);
v7 = kmalloc(sz, GFP_KERNEL);
+ if (!v7)
+ return;
v7->type = RPT_EN_MREG;
v7->fver = ver->fcxmreg;
v7->len = n;
@@ -2506,6 +2523,8 @@ static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
} else {
sz = struct_size(v1, regs, n);
v1 = kmalloc(sz, GFP_KERNEL);
+ if (!v1)
+ return;
v1->fver = ver->fcxmreg;
v1->reg_num = n;
memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
@@ -3017,7 +3036,7 @@ static void _update_btc_state_map(struct rtw89_dev *rtwdev)
struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
if (wl->status.map.connecting || wl->status.map._4way ||
- wl->status.map.roaming) {
+ wl->status.map.roaming || wl->status.map.dbccing) {
cx->state_map = BTC_WLINKING;
} else if (wl->status.map.scan) { /* wl scan */
if (bt_linfo->status.map.inq_pag)
@@ -3680,6 +3699,7 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
struct rtw89_btc_dm *dm = &btc->dm;
struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
+ struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
@@ -3721,8 +3741,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
tbl_w1 = cxtbl[16];
}
- btc->bt_req_en = false;
-
switch (type) {
case BTC_CXP_USERDEF0:
btc->update_policy_force = true;
@@ -3744,6 +3762,10 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
case BTC_CXP_OFF_WL:
_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
break;
+ case BTC_CXP_OFF_WL2:
+ _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
+ _slot_set_type(btc, CXST_OFF, SLOT_ISO);
+ break;
case BTC_CXP_OFF_EQ0:
_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
_slot_set_type(btc, CXST_OFF, SLOT_ISO);
@@ -3757,6 +3779,12 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
case BTC_CXP_OFF_EQ3:
_slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
break;
+ case BTC_CXP_OFF_EQ4:
+ _slot_set_tbl(btc, CXST_OFF, cxtbl[26]);
+ break;
+ case BTC_CXP_OFF_EQ5:
+ _slot_set_tbl(btc, CXST_OFF, cxtbl[27]);
+ break;
case BTC_CXP_OFF_BWB0:
_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
break;
@@ -3788,7 +3816,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
}
break;
case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
- btc->bt_req_en = true;
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
*t = t_def[CXTD_OFF_EXT];
@@ -3831,9 +3858,12 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
break;
case BTC_CXP_OFFE_2GBWMIXB:
- _slot_set(btc, CXST_E2G, 0, 0x55555555, SLOT_MIX);
+ if (a2dp->exist)
+ _slot_set(btc, CXST_E2G, 0, cxtbl[2], SLOT_MIX);
+ else
+ _slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_MIX);
_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
- cpu_to_le32(0x55555555), s_def[CXST_EBT].cxtype);
+ s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
break;
case BTC_CXP_OFFE_WL: /* for 4-way */
_slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_MIX);
@@ -3842,6 +3872,8 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
default:
break;
}
+ _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
+ s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
break;
@@ -4246,6 +4278,7 @@ static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
break;
case BTC_ANT_WRFK:
+ case BTC_ANT_WRFK2:
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
@@ -4623,12 +4656,21 @@ static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
static void _action_bt_pan(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
+ struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
+ struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
switch (btc->cx.state_map) {
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
- _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
+ if (a2dp.active || !pan.exist) {
+ btc->dm.slot_dur[CXST_W1] = 80;
+ btc->dm.slot_dur[CXST_B1] = 20;
+ _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
+ } else {
+ _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
+ }
break;
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
@@ -4814,8 +4856,16 @@ static void _action_wl_rfk(struct rtw89_dev *rtwdev)
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
__func__, rfk.band);
- _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
- _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
+ btc->dm.tdma_instant_excute = 1;
+
+ if (rfk.state == BTC_WRFK_ONESHOT_START ||
+ btc->ant_type == BTC_ANT_SHARED) {
+ _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
+ _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
+ } else {
+ _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
+ _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
+ }
}
static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
@@ -4855,6 +4905,8 @@ static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
if (rtwdev->dbcc_en) {
if (ver->fwlrole == 0) {
+ wl_rinfo.dbcc_2g_phy = RTW89_PHY_MAX;
+
for (i = 0; i < RTW89_PHY_MAX; i++) {
if (wl_dinfo->real_band[i] == RTW89_BAND_2G)
wl_rinfo.dbcc_2g_phy = i;
@@ -4989,18 +5041,16 @@ struct rtw89_txtime_data {
bool reenable;
};
-static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
+static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ struct rtw89_txtime_data *iter_data)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_txtime_data *iter_data =
- (struct rtw89_txtime_data *)data;
struct rtw89_dev *rtwdev = iter_data->rtwdev;
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_cx *cx = &btc->cx;
struct rtw89_btc_wl_info *wl = &cx->wl;
struct rtw89_btc_wl_link_info *plink = NULL;
- u8 port = rtwvif->port;
+ u8 port = rtwvif_link->port;
u32 tx_time = iter_data->tx_time;
u8 tx_retry = iter_data->tx_retry;
u16 enable = iter_data->enable;
@@ -5023,8 +5073,8 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
/* backup the original tx time before tx-limit on */
if (reenable) {
- rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time);
- rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry);
+ rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
+ rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
__func__, plink->tx_time, plink->tx_retry);
@@ -5032,22 +5082,37 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
/* restore the original tx time if no tx-limit */
if (!enable) {
- rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time);
- rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true,
+ rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
+ rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
plink->tx_retry);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
__func__, plink->tx_time, plink->tx_retry);
} else {
- rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time);
- rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry);
+ rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
+ rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
__func__, tx_time, tx_retry);
}
}
+static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_txtime_data *iter_data =
+ (struct rtw89_txtime_data *)data;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
+ }
+}
+
static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
@@ -5231,8 +5296,14 @@ static void _action_by_bt(struct rtw89_dev *rtwdev)
struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
+ struct rtw89_btc_dm *dm = &btc->dm;
u8 profile_map = 0;
+ if (dm->freerun_chk) {
+ _action_freerun(rtwdev);
+ return;
+ }
+
if (bt_linfo->hfp_desc.exist)
profile_map |= BTC_BT_HFP;
@@ -5247,30 +5318,20 @@ static void _action_by_bt(struct rtw89_dev *rtwdev)
switch (profile_map) {
case BTC_BT_NOPROFILE:
- if (_check_freerun(rtwdev))
- _action_freerun(rtwdev);
- else if (pan.active)
+ if (pan.active)
_action_bt_pan(rtwdev);
else
_action_bt_idle(rtwdev);
break;
case BTC_BT_HFP:
- if (_check_freerun(rtwdev))
- _action_freerun(rtwdev);
- else
- _action_bt_hfp(rtwdev);
+ _action_bt_hfp(rtwdev);
break;
case BTC_BT_HFP | BTC_BT_HID:
case BTC_BT_HID:
- if (_check_freerun(rtwdev))
- _action_freerun(rtwdev);
- else
- _action_bt_hid(rtwdev);
+ _action_bt_hid(rtwdev);
break;
case BTC_BT_A2DP:
- if (_check_freerun(rtwdev))
- _action_freerun(rtwdev);
- else if (a2dp.sink)
+ if (a2dp.sink)
_action_bt_a2dpsink(rtwdev);
else if (bt_linfo->multi_link.now && !hid.pair_cnt)
_action_bt_a2dp_pan(rtwdev);
@@ -5283,13 +5344,18 @@ static void _action_by_bt(struct rtw89_dev *rtwdev)
case BTC_BT_A2DP | BTC_BT_HFP:
case BTC_BT_A2DP | BTC_BT_HID:
case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
- if (_check_freerun(rtwdev))
- _action_freerun(rtwdev);
+ if (a2dp.sink)
+ _action_bt_a2dpsink(rtwdev);
+ else if (pan.active)
+ _action_bt_a2dp_pan_hid(rtwdev);
else
_action_bt_a2dp_hid(rtwdev);
break;
case BTC_BT_A2DP | BTC_BT_PAN:
- _action_bt_a2dp_pan(rtwdev);
+ if (a2dp.sink)
+ _action_bt_a2dpsink(rtwdev);
+ else
+ _action_bt_a2dp_pan(rtwdev);
break;
case BTC_BT_PAN | BTC_BT_HFP:
case BTC_BT_PAN | BTC_BT_HID:
@@ -5299,7 +5365,10 @@ static void _action_by_bt(struct rtw89_dev *rtwdev)
case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
default:
- _action_bt_a2dp_pan_hid(rtwdev);
+ if (a2dp.sink)
+ _action_bt_a2dpsink(rtwdev);
+ else
+ _action_bt_a2dp_pan_hid(rtwdev);
break;
}
}
@@ -5319,7 +5388,7 @@ static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
policy_type = BTC_CXP_OFFE_WL;
else if (btc->cx.wl.status.val & btc_scanning_map.val)
policy_type = BTC_CXP_OFFE_2GBWMIXB;
- else if (btc->cx.bt.link_info.profile_cnt.now == 0)
+ else if (btc->cx.bt.link_info.status.map.connect == 0)
policy_type = BTC_CXP_OFFE_2GISOB;
else
policy_type = BTC_CXP_OFFE_2GBWISOB;
@@ -6893,6 +6962,8 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
bt->scan_rx_low_pri = false;
igno_bt = false;
+ dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
+
if (always_freerun) {
_action_freerun(rtwdev);
igno_bt = true;
@@ -6931,18 +7002,9 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
goto exit;
}
- if (cx->state_map == BTC_WLINKING) {
- if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
- mode == BTC_WLINK_5G) {
- _action_wl_scan(rtwdev);
- bt->scan_rx_low_pri = false;
- goto exit;
- }
- }
-
- if (wl->status.map.scan) {
+ if (wl->status.val & btc_scanning_map.val) {
_action_wl_scan(rtwdev);
- bt->scan_rx_low_pri = false;
+ bt->scan_rx_low_pri = true;
goto exit;
}
@@ -7178,10 +7240,6 @@ void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
- wl->scan_info.band[phy_idx] = band;
- wl->scan_info.phy_map |= BIT(phy_idx);
- _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
-
if (rtwdev->dbcc_en) {
wl->dbcc_info.scan_band[phy_idx] = band;
_update_dbcc_band(rtwdev, phy_idx);
@@ -7376,13 +7434,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
"[BTC], %s(): bt_info[2]=0x%02x\n",
__func__, bt->raw_info[2]);
- /* reset to mo-connect before update */
- b->status.val = BTC_BLINK_NOCONNECT;
b->profile_cnt.last = b->profile_cnt.now;
- b->relink.last = b->relink.now;
- a2dp->exist_last = a2dp->exist;
- b->multi_link.last = b->multi_link.now;
- bt->inq_pag.last = bt->inq_pag.now;
b->profile_cnt.now = 0;
hid->type = 0;
@@ -7401,7 +7453,8 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
b->profile_cnt.now += (u8)hid->exist;
a2dp->exist = btinfo.lb2.a2dp;
b->profile_cnt.now += (u8)a2dp->exist;
- pan->active = btinfo.lb2.pan;
+ pan->exist = btinfo.lb2.pan;
+ b->profile_cnt.now += (u8)pan->exist;
btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
/* parse raw info low-Byte3 */
@@ -7425,8 +7478,14 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
/* parse raw info high-Byte1 */
btinfo.val = bt->raw_info[BTC_BTINFO_H1];
b->status.map.ble_connect = btinfo.hb1.ble_connect;
- if (btinfo.hb1.ble_connect)
- hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
+ if (btinfo.hb1.ble_connect) {
+ if (hid->exist)
+ hid->type |= BTC_HID_BLE;
+ else if (btinfo.hb1.voice)
+ hid->type |= BTC_HID_RCU_VOICE;
+ else
+ hid->type |= BTC_HID_RCU;
+ }
cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
bt->reinit = btinfo.hb1.reinit;
@@ -7438,7 +7497,6 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
if (bt->igno_wl && !cx->wl.status.map.rf_off)
_set_bt_ignore_wlan_act(rtwdev, false);
- hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
bt->ble_scan_en = btinfo.hb1.ble_scan;
cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
@@ -7448,8 +7506,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
/* parse raw info high-Byte2 */
btinfo.val = bt->raw_info[BTC_BTINFO_H2];
- pan->exist = btinfo.hb2.pan_active;
- b->profile_cnt.now += (u8)pan->exist;
+ pan->active = !!btinfo.hb2.pan_active;
cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
b->afh_update = btinfo.hb2.afh_update;
@@ -7457,8 +7514,9 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
b->slave_role = btinfo.hb2.slave;
hid->slot_info = btinfo.hb2.hid_slot;
hid->pair_cnt = btinfo.hb2.hid_cnt;
- hid->type |= (hid->slot_info == BTC_HID_218 ?
- BTC_HID_218 : BTC_HID_418);
+ if (!b->status.map.ble_connect || hid->pair_cnt > 1)
+ hid->type |= (hid->slot_info == BTC_HID_218 ?
+ BTC_HID_218 : BTC_HID_418);
/* parse raw info high-Byte3 */
btinfo.val = bt->raw_info[BTC_BTINFO_H3];
a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
@@ -7481,13 +7539,16 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
_run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
}
-void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta, enum btc_role_state state)
+void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ enum btc_role_state state)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
+ rtwvif_link->chanctx_idx);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct ieee80211_bss_conf *bss_conf;
+ struct ieee80211_link_sta *link_sta;
struct rtw89_btc *btc = &rtwdev->btc;
const struct rtw89_btc_ver *ver = btc->ver;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
@@ -7495,51 +7556,59 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
struct rtw89_btc_wl_link_info *wlinfo = NULL;
u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
+
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], role is STA=%d\n",
vif->type == NL80211_IFTYPE_STATION);
- rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
+ rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port);
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
chan->band_type, chan->channel, chan->band_width);
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
state == BTC_ROLE_MSTS_STA_CONN_END);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], bcn_period=%d dtim_period=%d\n",
- vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
+ bss_conf->beacon_int, bss_conf->dtim_period);
+
+ if (rtwsta_link) {
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
- if (rtwsta) {
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
- rtwsta->mac_id);
+ rtwsta_link->mac_id);
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], STA support HE=%d VHT=%d HT=%d\n",
- sta->deflink.he_cap.has_he,
- sta->deflink.vht_cap.vht_supported,
- sta->deflink.ht_cap.ht_supported);
- if (sta->deflink.he_cap.has_he)
+ link_sta->he_cap.has_he,
+ link_sta->vht_cap.vht_supported,
+ link_sta->ht_cap.ht_supported);
+ if (link_sta->he_cap.has_he)
mode |= BIT(BTC_WL_MODE_HE);
- if (sta->deflink.vht_cap.vht_supported)
+ if (link_sta->vht_cap.vht_supported)
mode |= BIT(BTC_WL_MODE_VHT);
- if (sta->deflink.ht_cap.ht_supported)
+ if (link_sta->ht_cap.ht_supported)
mode |= BIT(BTC_WL_MODE_HT);
r.mode = mode;
}
- if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
+ if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
+ rcu_read_unlock();
return;
+ }
rtw89_debug(rtwdev, RTW89_DBG_BTC,
- "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
+ "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
- r.role = rtwvif->wifi_role;
- r.phy = rtwvif->phy_idx;
- r.pid = rtwvif->port;
+ r.role = rtwvif_link->wifi_role;
+ r.phy = rtwvif_link->phy_idx;
+ r.pid = rtwvif_link->port;
r.active = true;
r.connected = MLME_LINKED;
- r.bcn_period = vif->bss_conf.beacon_int;
- r.dtim_period = vif->bss_conf.dtim_period;
+ r.bcn_period = bss_conf->beacon_int;
+ r.dtim_period = bss_conf->dtim_period;
r.band = chan->band_type;
r.ch = chan->channel;
r.bw = chan->band_width;
@@ -7547,10 +7616,12 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
r.chdef.center_ch = chan->channel;
r.chdef.bw = chan->band_width;
r.chdef.chan = chan->primary_channel;
- ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
+ ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
- if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
- r.mac_id = rtwsta->mac_id;
+ rcu_read_unlock();
+
+ if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION)
+ r.mac_id = rtwsta_link->mac_id;
btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
@@ -7781,26 +7852,26 @@ struct rtw89_btc_wl_sta_iter_data {
bool is_traffic_change;
};
-static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
+static
+void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ struct rtw89_btc_wl_sta_iter_data *iter_data)
{
- struct rtw89_btc_wl_sta_iter_data *iter_data =
- (struct rtw89_btc_wl_sta_iter_data *)data;
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_dev *rtwdev = iter_data->rtwdev;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
const struct rtw89_btc_ver *ver = btc->ver;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
struct rtw89_btc_wl_link_info *link_info = NULL;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_traffic_stats *link_info_t = NULL;
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_traffic_stats *stats = &rtwvif->stats;
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc_wl_role_info *r;
struct rtw89_btc_wl_role_info_v1 *r1;
u32 last_tx_rate, last_rx_rate;
u16 last_tx_lvl, last_rx_lvl;
- u8 port = rtwvif->port;
+ u8 port = rtwvif_link->port;
u8 rssi;
u8 busy = 0;
u8 dir = 0;
@@ -7808,11 +7879,11 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
u8 i = 0;
bool is_sta_change = false, is_traffic_change = false;
- rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
+ rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
link_info = &wl->link_info[port];
- link_info->stat.traffic = rtwvif->stats;
+ link_info->stat.traffic = *stats;
link_info_t = &link_info->stat.traffic;
if (link_info->connected == MLME_NO_LINK) {
@@ -7860,19 +7931,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
iter_data->busy_all |= busy;
iter_data->dir_all |= BIT(dir);
- if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
+ if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
last_rx_rate > RTW89_HW_RATE_CCK2 &&
link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
link_info->rx_rate_drop_cnt++;
- if (last_tx_rate != rtwsta->ra_report.hw_rate ||
- last_rx_rate != rtwsta->rx_hw_rate ||
+ if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
+ last_rx_rate != rtwsta_link->rx_hw_rate ||
last_tx_lvl != link_info_t->tx_tfc_lv ||
last_rx_lvl != link_info_t->rx_tfc_lv)
is_traffic_change = true;
- link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
- link_info_t->rx_rate = rtwsta->rx_hw_rate;
+ link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
+ link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
if (link_info->role == RTW89_WIFI_ROLE_STATION ||
link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
@@ -7884,19 +7955,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
r = &wl->role_info;
r->active_role[port].tx_lvl = stats->tx_tfc_lv;
r->active_role[port].rx_lvl = stats->rx_tfc_lv;
- r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
- r->active_role[port].rx_rate = rtwsta->rx_hw_rate;
+ r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate;
+ r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate;
} else if (ver->fwlrole == 1) {
r1 = &wl->role_info_v1;
r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
- r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate;
- r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate;
+ r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate;
+ r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate;
} else if (ver->fwlrole == 2) {
dm->trx_info.tx_lvl = stats->tx_tfc_lv;
dm->trx_info.rx_lvl = stats->rx_tfc_lv;
- dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate;
- dm->trx_info.rx_rate = rtwsta->rx_hw_rate;
+ dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
+ dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
}
dm->trx_info.tx_tp = link_info_t->tx_throughput;
@@ -7916,6 +7987,21 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
iter_data->is_traffic_change = true;
}
+static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_btc_wl_sta_iter_data *iter_data =
+ (struct rtw89_btc_wl_sta_iter_data *)data;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
+ }
+}
+
#define BTC_NHM_CHK_INTVL 20
void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
@@ -7965,6 +8051,53 @@ void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
}
}
+static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ const struct rtw89_btc_ver *ver = btc->ver;
+
+ switch (func) {
+ case BTF_EVNT_RPT:
+ case BTF_EVNT_BT_INFO:
+ case BTF_EVNT_BT_SCBD:
+ case BTF_EVNT_BT_REG:
+ case BTF_EVNT_CX_RUNINFO:
+ case BTF_EVNT_BT_PSD:
+ return func;
+ case BTF_EVNT_BT_DEV_INFO:
+ if (ver->fwc2hfunc == 0)
+ return BTF_EVNT_BUF_OVERFLOW;
+ else
+ return BTF_EVNT_BT_DEV_INFO;
+ case BTF_EVNT_BT_LEAUDIO_INFO:
+ if (ver->fwc2hfunc == 0)
+ return BTF_EVNT_C2H_LOOPBACK;
+ else if (ver->fwc2hfunc == 1)
+ return BTF_EVNT_BUF_OVERFLOW;
+ else if (ver->fwc2hfunc == 2)
+ return func;
+ else
+ return BTF_EVNT_MAX;
+ case BTF_EVNT_BUF_OVERFLOW:
+ if (ver->fwc2hfunc == 0)
+ return BTF_EVNT_MAX;
+ else if (ver->fwc2hfunc == 1)
+ return BTF_EVNT_C2H_LOOPBACK;
+ else if (ver->fwc2hfunc == 2)
+ return func;
+ else
+ return BTF_EVNT_MAX;
+ case BTF_EVNT_C2H_LOOPBACK:
+ if (ver->fwc2hfunc == 2)
+ return func;
+ else
+ return BTF_EVNT_MAX;
+ case BTF_EVNT_MAX:
+ default:
+ return BTF_EVNT_MAX;
+ }
+}
+
void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u32 len, u8 class, u8 func)
{
@@ -7981,10 +8114,14 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
if (class != BTFC_FW_EVENT)
return;
+ func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
+
switch (func) {
- case BTF_EVNT_RPT:
case BTF_EVNT_BUF_OVERFLOW:
pfwinfo->event[func]++;
+ break;
+ case BTF_EVNT_RPT:
+ pfwinfo->event[func]++;
/* Don't need rtw89_leave_ps_mode() */
btc_fw_event(rtwdev, func, buf, len);
break;
diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h
index de53b56632f7..dbdb56e063ef 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.h
+++ b/drivers/net/wireless/realtek/rtw89/coex.h
@@ -271,8 +271,10 @@ void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work);
void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work);
void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work);
void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work);
-void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta, enum btc_role_state state);
+void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ enum btc_role_state state);
void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state);
void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
enum btc_wl_rfk_type type,
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 4553810634c6..e5b2968c1431 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -192,13 +192,13 @@ static const struct ieee80211_iface_combination rtw89_iface_combs[] = {
{
.limits = rtw89_iface_limits,
.n_limits = ARRAY_SIZE(rtw89_iface_limits),
- .max_interfaces = 2,
+ .max_interfaces = RTW89_MAX_INTERFACE_NUM,
.num_different_channels = 1,
},
{
.limits = rtw89_iface_limits_mcc,
.n_limits = ARRAY_SIZE(rtw89_iface_limits_mcc),
- .max_interfaces = 2,
+ .max_interfaces = RTW89_MAX_INTERFACE_NUM,
.num_different_channels = 2,
},
};
@@ -341,83 +341,47 @@ void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
rtw89_chan_create(chan, center_chan, channel->hw_value, band, bandwidth);
}
-void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
+static void __rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
{
- struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chip_info *chip = rtwdev->chip;
- const struct rtw89_chan *chan;
- enum rtw89_chanctx_idx chanctx_idx;
- enum rtw89_chanctx_idx roc_idx;
- enum rtw89_phy_idx phy_idx;
- enum rtw89_entity_mode mode;
bool entity_active;
- entity_active = rtw89_get_entity_state(rtwdev);
+ entity_active = rtw89_get_entity_state(rtwdev, phy_idx);
if (!entity_active)
return;
- mode = rtw89_get_entity_mode(rtwdev);
- switch (mode) {
- case RTW89_ENTITY_MODE_SCC:
- case RTW89_ENTITY_MODE_MCC:
- chanctx_idx = RTW89_CHANCTX_0;
- break;
- case RTW89_ENTITY_MODE_MCC_PREPARE:
- chanctx_idx = RTW89_CHANCTX_1;
- break;
- default:
- WARN(1, "Invalid ent mode: %d\n", mode);
- return;
- }
+ chip->ops->set_txpwr(rtwdev, chan, phy_idx);
+}
- roc_idx = atomic_read(&hal->roc_chanctx_idx);
- if (roc_idx != RTW89_CHANCTX_IDLE)
- chanctx_idx = roc_idx;
+void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_chan *chan;
- phy_idx = RTW89_PHY_0;
- chan = rtw89_chan_get(rtwdev, chanctx_idx);
- chip->ops->set_txpwr(rtwdev, chan, phy_idx);
+ chan = rtw89_mgnt_chan_get(rtwdev, 0);
+ __rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_0);
+
+ if (!rtwdev->support_mlo)
+ return;
+
+ chan = rtw89_mgnt_chan_get(rtwdev, 1);
+ __rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_1);
}
-int rtw89_set_channel(struct rtw89_dev *rtwdev)
+static void __rtw89_set_channel(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_mac_idx mac_idx,
+ enum rtw89_phy_idx phy_idx)
{
- struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_chan_rcd *chan_rcd;
- const struct rtw89_chan *chan;
- enum rtw89_chanctx_idx chanctx_idx;
- enum rtw89_chanctx_idx roc_idx;
- enum rtw89_mac_idx mac_idx;
- enum rtw89_phy_idx phy_idx;
struct rtw89_channel_help_params bak;
- enum rtw89_entity_mode mode;
bool entity_active;
- entity_active = rtw89_get_entity_state(rtwdev);
-
- mode = rtw89_entity_recalc(rtwdev);
- switch (mode) {
- case RTW89_ENTITY_MODE_SCC:
- case RTW89_ENTITY_MODE_MCC:
- chanctx_idx = RTW89_CHANCTX_0;
- break;
- case RTW89_ENTITY_MODE_MCC_PREPARE:
- chanctx_idx = RTW89_CHANCTX_1;
- break;
- default:
- WARN(1, "Invalid ent mode: %d\n", mode);
- return -EINVAL;
- }
-
- roc_idx = atomic_read(&hal->roc_chanctx_idx);
- if (roc_idx != RTW89_CHANCTX_IDLE)
- chanctx_idx = roc_idx;
+ entity_active = rtw89_get_entity_state(rtwdev, phy_idx);
- mac_idx = RTW89_MAC_0;
- phy_idx = RTW89_PHY_0;
-
- chan = rtw89_chan_get(rtwdev, chanctx_idx);
- chan_rcd = rtw89_chan_rcd_get(rtwdev, chanctx_idx);
+ chan_rcd = rtw89_chan_rcd_get_by_chan(chan);
rtw89_chip_set_channel_prepare(rtwdev, &bak, chan, mac_idx, phy_idx);
@@ -432,17 +396,30 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev)
rtw89_chip_rfk_band_changed(rtwdev, phy_idx, chan);
}
- rtw89_set_entity_state(rtwdev, true);
- return 0;
+ rtw89_set_entity_state(rtwdev, phy_idx, true);
}
-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_chan *chan)
+int rtw89_set_channel(struct rtw89_dev *rtwdev)
{
- const struct cfg80211_chan_def *chandef;
+ const struct rtw89_chan *chan;
+ enum rtw89_entity_mode mode;
+
+ mode = rtw89_entity_recalc(rtwdev);
+ if (mode < 0 || mode >= NUM_OF_RTW89_ENTITY_MODE) {
+ WARN(1, "Invalid ent mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+ chan = rtw89_mgnt_chan_get(rtwdev, 0);
+ __rtw89_set_channel(rtwdev, chan, RTW89_MAC_0, RTW89_PHY_0);
+
+ if (!rtwdev->support_mlo)
+ return 0;
+
+ chan = rtw89_mgnt_chan_get(rtwdev, 1);
+ __rtw89_set_channel(rtwdev, chan, RTW89_MAC_1, RTW89_PHY_1);
- chandef = rtw89_chandef_get(rtwdev, rtwvif->chanctx_idx);
- rtw89_get_channel_params(chandef, chan);
+ return 0;
}
static enum rtw89_core_tx_type
@@ -463,8 +440,9 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req,
enum btc_pkt_type pkt_type)
{
- struct ieee80211_sta *sta = tx_req->sta;
+ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
+ struct ieee80211_link_sta *link_sta;
struct sk_buff *skb = tx_req->skb;
struct rtw89_sta *rtwsta;
u8 ampdu_num;
@@ -478,21 +456,26 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev,
if (!(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU))
return;
- if (!sta) {
+ if (!rtwsta_link) {
rtw89_warn(rtwdev, "cannot set ampdu info without sta\n");
return;
}
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
- rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ rtwsta = rtwsta_link->rtwsta;
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
ampdu_num = (u8)((rtwsta->ampdu_params[tid].agg_num ?
rtwsta->ampdu_params[tid].agg_num :
- 4 << sta->deflink.ht_cap.ampdu_factor) - 1);
+ 4 << link_sta->ht_cap.ampdu_factor) - 1);
desc_info->agg_en = true;
- desc_info->ampdu_density = sta->deflink.ht_cap.ampdu_density;
+ desc_info->ampdu_density = link_sta->ht_cap.ampdu_density;
desc_info->ampdu_num = ampdu_num;
+
+ rcu_read_unlock();
}
static void
@@ -569,9 +552,13 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan)
{
struct sk_buff *skb = tx_req->skb;
+ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = tx_info->control.vif;
+ struct ieee80211_bss_conf *bss_conf;
u16 lowest_rate;
+ u16 rate;
if (tx_info->flags & IEEE80211_TX_CTL_NO_CCK_RATE ||
(vif && vif->p2p))
@@ -581,25 +568,35 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
else
lowest_rate = RTW89_HW_RATE_OFDM6;
- if (!vif || !vif->bss_conf.basic_rates || !tx_req->sta)
+ if (!rtwvif_link)
return lowest_rate;
- return __ffs(vif->bss_conf.basic_rates) + lowest_rate;
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
+ if (!bss_conf->basic_rates || !rtwsta_link) {
+ rate = lowest_rate;
+ goto out;
+ }
+
+ rate = __ffs(bss_conf->basic_rates) + lowest_rate;
+
+out:
+ rcu_read_unlock();
+
+ return rate;
}
static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
{
- struct ieee80211_vif *vif = tx_req->vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct ieee80211_sta *sta = tx_req->sta;
- struct rtw89_sta *rtwsta;
+ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
- if (!sta)
- return rtwvif->mac_id;
+ if (!rtwsta_link)
+ return rtwvif_link->mac_id;
- rtwsta = (struct rtw89_sta *)sta->drv_priv;
- return rtwsta->mac_id;
+ return rtwsta_link->mac_id;
}
static void rtw89_core_tx_update_llc_hdr(struct rtw89_dev *rtwdev,
@@ -618,11 +615,10 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- struct ieee80211_vif *vif = tx_req->vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
struct sk_buff *skb = tx_req->skb;
u8 qsel, ch_dma;
@@ -631,7 +627,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
desc_info->qsel = qsel;
desc_info->ch_dma = ch_dma;
- desc_info->port = desc_info->hiq ? rtwvif->port : 0;
+ desc_info->port = desc_info->hiq ? rtwvif_link->port : 0;
desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req);
desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL;
desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE;
@@ -701,18 +697,28 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req,
enum btc_pkt_type pkt_type)
{
- struct ieee80211_sta *sta = tx_req->sta;
- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
struct sk_buff *skb = tx_req->skb;
struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ieee80211_link_sta *link_sta;
__le16 fc = hdr->frame_control;
/* AP IOT issue with EAPoL, ARP and DHCP */
if (pkt_type < PACKET_MAX)
return false;
- if (!sta || !sta->deflink.he_cap.has_he)
+ if (!rtwsta_link)
+ return false;
+
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
+ if (!link_sta->he_cap.has_he) {
+ rcu_read_unlock();
return false;
+ }
+
+ rcu_read_unlock();
if (!ieee80211_is_data_qos(fc))
return false;
@@ -720,7 +726,7 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev,
if (skb_headroom(skb) < IEEE80211_HT_CTL_LEN)
return false;
- if (rtwsta && rtwsta->ra_report.might_fallback_legacy)
+ if (rtwsta_link && rtwsta_link->ra_report.might_fallback_legacy)
return false;
return true;
@@ -730,8 +736,7 @@ static void
__rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
{
- struct ieee80211_sta *sta = tx_req->sta;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
struct sk_buff *skb = tx_req->skb;
struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
@@ -747,7 +752,7 @@ __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev,
hdr = data;
htc = data + hdr_len;
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_ORDER);
- *htc = rtwsta->htc_template ? rtwsta->htc_template :
+ *htc = rtwsta_link->htc_template ? rtwsta_link->htc_template :
le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) |
le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_CAS, RTW89_HTC_MASK_CTL_ID);
@@ -761,8 +766,7 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev,
enum btc_pkt_type pkt_type)
{
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
- struct ieee80211_vif *vif = tx_req->vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
if (!__rtw89_core_tx_check_he_qos_htc(rtwdev, tx_req, pkt_type))
goto desc_bk;
@@ -773,23 +777,25 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev,
desc_info->a_ctrl_bsr = true;
desc_bk:
- if (!rtwvif || rtwvif->last_a_ctrl == desc_info->a_ctrl_bsr)
+ if (!rtwvif_link || rtwvif_link->last_a_ctrl == desc_info->a_ctrl_bsr)
return;
- rtwvif->last_a_ctrl = desc_info->a_ctrl_bsr;
+ rtwvif_link->last_a_ctrl = desc_info->a_ctrl_bsr;
desc_info->bk = true;
}
static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
{
- struct ieee80211_vif *vif = tx_req->vif;
- struct ieee80211_sta *sta = tx_req->sta;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
- enum rtw89_chanctx_idx idx = rtwvif->chanctx_idx;
+ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern;
+ enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx);
+ struct ieee80211_link_sta *link_sta;
u16 lowest_rate;
+ u16 rate;
if (rate_pattern->enable)
return rate_pattern->rate;
@@ -801,20 +807,31 @@ static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev,
else
lowest_rate = RTW89_HW_RATE_OFDM6;
- if (!sta || !sta->deflink.supp_rates[chan->band_type])
+ if (!rtwsta_link)
return lowest_rate;
- return __ffs(sta->deflink.supp_rates[chan->band_type]) + lowest_rate;
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
+ if (!link_sta->supp_rates[chan->band_type]) {
+ rate = lowest_rate;
+ goto out;
+ }
+
+ rate = __ffs(link_sta->supp_rates[chan->band_type]) + lowest_rate;
+
+out:
+ rcu_read_unlock();
+
+ return rate;
}
static void
rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
{
- struct ieee80211_vif *vif = tx_req->vif;
- struct ieee80211_sta *sta = tx_req->sta;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+ struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
struct sk_buff *skb = tx_req->skb;
u8 tid, tid_indicate;
@@ -829,10 +846,10 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
desc_info->tid_indicate = tid_indicate;
desc_info->qsel = qsel;
desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req);
- desc_info->port = desc_info->hiq ? rtwvif->port : 0;
- desc_info->er_cap = rtwsta ? rtwsta->er_cap : false;
- desc_info->stbc = rtwsta ? rtwsta->ra.stbc_cap : false;
- desc_info->ldpc = rtwsta ? rtwsta->ra.ldpc_cap : false;
+ desc_info->port = desc_info->hiq ? rtwvif_link->port : 0;
+ desc_info->er_cap = rtwsta_link ? rtwsta_link->er_cap : false;
+ desc_info->stbc = rtwsta_link ? rtwsta_link->ra.stbc_cap : false;
+ desc_info->ldpc = rtwsta_link ? rtwsta_link->ra.ldpc_cap : false;
/* enable wd_info for AMPDU */
desc_info->en_wd_info = true;
@@ -907,8 +924,10 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
struct sk_buff *skb = tx_req->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct rtw89_addr_cam_entry *addr_cam;
enum rtw89_core_tx_type tx_type;
enum btc_pkt_type pkt_type;
+ bool upd_wlan_hdr = false;
bool is_bmc;
u16 seq;
@@ -916,6 +935,11 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
if (tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD) {
tx_type = rtw89_core_get_tx_type(rtwdev, skb);
tx_req->tx_type = tx_type;
+
+ addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link,
+ tx_req->rtwsta_link);
+ if (addr_cam->valid)
+ upd_wlan_hdr = true;
}
is_bmc = (is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1));
@@ -925,6 +949,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
desc_info->is_bmc = is_bmc;
desc_info->wd_page = true;
desc_info->hiq = info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM;
+ desc_info->upd_wlan_hdr = upd_wlan_hdr;
switch (tx_req->tx_type) {
case RTW89_CORE_TX_TYPE_MGMT:
@@ -1027,13 +1052,34 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel)
{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
struct rtw89_core_tx_request tx_req = {0};
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_sta_link *rtwsta_link = NULL;
+ struct rtw89_vif_link *rtwvif_link;
int ret;
+ /* By default, driver writes tx via the link on HW-0. And then,
+ * according to links' status, HW can change tx to another link.
+ */
+
+ if (rtwsta) {
+ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+ if (unlikely(!rtwsta_link)) {
+ rtw89_err(rtwdev, "tx: find no sta link on HW-0\n");
+ return -ENOLINK;
+ }
+ }
+
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "tx: find no vif link on HW-0\n");
+ return -ENOLINK;
+ }
+
tx_req.skb = skb;
- tx_req.sta = sta;
- tx_req.vif = vif;
+ tx_req.rtwvif_link = rtwvif_link;
+ tx_req.rtwsta_link = rtwsta_link;
rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true);
rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true);
@@ -1302,6 +1348,13 @@ static __le32 rtw89_build_txwd_body5_v2(struct rtw89_tx_desc_info *desc_info)
return cpu_to_le32(dword);
}
+static __le32 rtw89_build_txwd_body6_v2(struct rtw89_tx_desc_info *desc_info)
+{
+ u32 dword = FIELD_PREP(BE_TXD_BODY6_UPD_WLAN_HDR, desc_info->upd_wlan_hdr);
+
+ return cpu_to_le32(dword);
+}
+
static __le32 rtw89_build_txwd_body7_v2(struct rtw89_tx_desc_info *desc_info)
{
u32 dword = FIELD_PREP(BE_TXD_BODY7_USERATE_SEL, desc_info->use_rate) |
@@ -1365,6 +1418,7 @@ void rtw89_core_fill_txdesc_v2(struct rtw89_dev *rtwdev,
txwd_body->dword4 = rtw89_build_txwd_body4_v2(desc_info);
txwd_body->dword5 = rtw89_build_txwd_body5_v2(desc_info);
}
+ txwd_body->dword6 = rtw89_build_txwd_body6_v2(desc_info);
txwd_body->dword7 = rtw89_build_txwd_body7_v2(desc_info);
if (!desc_info->en_wd_info)
@@ -1514,16 +1568,24 @@ static u8 rtw89_get_data_rate_nss(struct rtw89_dev *rtwdev, u16 data_rate)
static void rtw89_core_rx_process_phy_ppdu_iter(void *data,
struct ieee80211_sta *sta)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
struct rtw89_hal *hal = &rtwdev->hal;
+ struct rtw89_sta_link *rtwsta_link;
u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
u8 ant_pos = U8_MAX;
u8 evm_pos = 0;
int i;
- if (rtwsta->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self)
+ /* FIXME: For single link, taking link on HW-0 here is okay. But, when
+ * enabling multiple active links, we should determine the right link.
+ */
+ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+ if (unlikely(!rtwsta_link))
+ return;
+
+ if (rtwsta_link->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self)
return;
if (hal->ant_diversity && hal->antenna_rx) {
@@ -1531,22 +1593,24 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data,
evm_pos = ant_pos;
}
- ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg);
+ ewma_rssi_add(&rtwsta_link->avg_rssi, phy_ppdu->rssi_avg);
if (ant_pos < ant_num) {
- ewma_rssi_add(&rtwsta->rssi[ant_pos], phy_ppdu->rssi[0]);
+ ewma_rssi_add(&rtwsta_link->rssi[ant_pos], phy_ppdu->rssi[0]);
} else {
for (i = 0; i < rtwdev->chip->rf_path_num; i++)
- ewma_rssi_add(&rtwsta->rssi[i], phy_ppdu->rssi[i]);
+ ewma_rssi_add(&rtwsta_link->rssi[i], phy_ppdu->rssi[i]);
}
if (phy_ppdu->ofdm.has && (phy_ppdu->has_data || phy_ppdu->has_bcn)) {
- ewma_snr_add(&rtwsta->avg_snr, phy_ppdu->ofdm.avg_snr);
+ ewma_snr_add(&rtwsta_link->avg_snr, phy_ppdu->ofdm.avg_snr);
if (rtw89_get_data_rate_nss(rtwdev, phy_ppdu->rate) == 1) {
- ewma_evm_add(&rtwsta->evm_1ss, phy_ppdu->ofdm.evm_min);
+ ewma_evm_add(&rtwsta_link->evm_1ss, phy_ppdu->ofdm.evm_min);
} else {
- ewma_evm_add(&rtwsta->evm_min[evm_pos], phy_ppdu->ofdm.evm_min);
- ewma_evm_add(&rtwsta->evm_max[evm_pos], phy_ppdu->ofdm.evm_max);
+ ewma_evm_add(&rtwsta_link->evm_min[evm_pos],
+ phy_ppdu->ofdm.evm_min);
+ ewma_evm_add(&rtwsta_link->evm_max[evm_pos],
+ phy_ppdu->ofdm.evm_max);
}
}
}
@@ -1795,32 +1859,58 @@ static void rtw89_core_rx_process_phy_sts(struct rtw89_dev *rtwdev,
phy_ppdu);
}
-static u8 rtw89_rxdesc_to_nl_he_eht_gi(struct rtw89_dev *rtwdev,
- u8 desc_info_gi,
- bool rx_status, bool eht)
+static u8 rtw89_rxdesc_to_nl_he_gi(struct rtw89_dev *rtwdev,
+ u8 desc_info_gi,
+ bool rx_status)
{
switch (desc_info_gi) {
case RTW89_GILTF_SGI_4XHE08:
case RTW89_GILTF_2XHE08:
case RTW89_GILTF_1XHE08:
- return eht ? NL80211_RATE_INFO_EHT_GI_0_8 :
- NL80211_RATE_INFO_HE_GI_0_8;
+ return NL80211_RATE_INFO_HE_GI_0_8;
case RTW89_GILTF_2XHE16:
case RTW89_GILTF_1XHE16:
- return eht ? NL80211_RATE_INFO_EHT_GI_1_6 :
- NL80211_RATE_INFO_HE_GI_1_6;
+ return NL80211_RATE_INFO_HE_GI_1_6;
case RTW89_GILTF_LGI_4XHE32:
- return eht ? NL80211_RATE_INFO_EHT_GI_3_2 :
- NL80211_RATE_INFO_HE_GI_3_2;
+ return NL80211_RATE_INFO_HE_GI_3_2;
default:
rtw89_warn(rtwdev, "invalid gi_ltf=%d", desc_info_gi);
if (rx_status)
- return eht ? NL80211_RATE_INFO_EHT_GI_3_2 :
- NL80211_RATE_INFO_HE_GI_3_2;
+ return NL80211_RATE_INFO_HE_GI_3_2;
return U8_MAX;
}
}
+static u8 rtw89_rxdesc_to_nl_eht_gi(struct rtw89_dev *rtwdev,
+ u8 desc_info_gi,
+ bool rx_status)
+{
+ switch (desc_info_gi) {
+ case RTW89_GILTF_SGI_4XHE08:
+ case RTW89_GILTF_2XHE08:
+ case RTW89_GILTF_1XHE08:
+ return NL80211_RATE_INFO_EHT_GI_0_8;
+ case RTW89_GILTF_2XHE16:
+ case RTW89_GILTF_1XHE16:
+ return NL80211_RATE_INFO_EHT_GI_1_6;
+ case RTW89_GILTF_LGI_4XHE32:
+ return NL80211_RATE_INFO_EHT_GI_3_2;
+ default:
+ rtw89_warn(rtwdev, "invalid gi_ltf=%d", desc_info_gi);
+ if (rx_status)
+ return NL80211_RATE_INFO_EHT_GI_3_2;
+ return U8_MAX;
+ }
+}
+
+static u8 rtw89_rxdesc_to_nl_he_eht_gi(struct rtw89_dev *rtwdev,
+ u8 desc_info_gi,
+ bool rx_status, bool eht)
+{
+ return eht ? rtw89_rxdesc_to_nl_eht_gi(rtwdev, desc_info_gi, rx_status) :
+ rtw89_rxdesc_to_nl_he_gi(rtwdev, desc_info_gi, rx_status);
+}
+
static
bool rtw89_check_rx_statu_gi_match(struct ieee80211_rx_status *status, u8 gi_ltf,
bool eht)
@@ -1876,17 +1966,19 @@ struct rtw89_vif_rx_stats_iter_data {
};
static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf,
struct sk_buff *skb)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data;
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
u8 *pos, *end, type, tf_bw;
u16 aid, tf_rua;
- if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) ||
- rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION ||
- rtwvif->net_type == RTW89_NET_TYPE_NO_LINK)
+ if (!ether_addr_equal(bss_conf->bssid, tf->ta) ||
+ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION ||
+ rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK)
return;
type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK);
@@ -1915,7 +2007,7 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
rtwdev->stats.rx_tf_acc++;
if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ &&
rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106)
- rtwvif->pwr_diff_en = true;
+ rtwvif_link->pwr_diff_en = true;
break;
}
@@ -1986,7 +2078,7 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work);
}
-static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif,
+static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif_link *rtwvif_link,
struct ieee80211_hdr *hdr, size_t len)
{
struct ieee80211_mgmt *mgmt = (typeof(mgmt))hdr;
@@ -1994,20 +2086,22 @@ static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif,
if (len < offsetof(typeof(*mgmt), u.beacon.variable))
return;
- WRITE_ONCE(rtwvif->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp));
+ WRITE_ONCE(rtwvif_link->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp));
}
static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_vif_rx_stats_iter_data *iter_data = data;
struct rtw89_dev *rtwdev = iter_data->rtwdev;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat;
struct rtw89_rx_desc_info *desc_info = iter_data->desc_info;
struct sk_buff *skb = iter_data->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu;
+ struct ieee80211_bss_conf *bss_conf;
+ struct rtw89_vif_link *rtwvif_link;
const u8 *bssid = iter_data->bssid;
if (rtwdev->scanning &&
@@ -2015,33 +2109,49 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
ieee80211_is_probe_resp(hdr->frame_control)))
rtw89_core_cancel_6ghz_probe_tx(rtwdev, skb);
- if (!vif->bss_conf.bssid)
- return;
+ rcu_read_lock();
+
+ /* FIXME: For single link, taking link on HW-0 here is okay. But, when
+ * enabling multiple active links, we should determine the right link.
+ */
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (unlikely(!rtwvif_link))
+ goto out;
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
+ if (!bss_conf->bssid)
+ goto out;
if (ieee80211_is_trigger(hdr->frame_control)) {
- rtw89_stats_trigger_frame(rtwdev, vif, skb);
- return;
+ rtw89_stats_trigger_frame(rtwdev, rtwvif_link, bss_conf, skb);
+ goto out;
}
- if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
- return;
+ if (!ether_addr_equal(bss_conf->bssid, bssid))
+ goto out;
if (ieee80211_is_beacon(hdr->frame_control)) {
if (vif->type == NL80211_IFTYPE_STATION &&
!test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) {
- rtw89_vif_sync_bcn_tsf(rtwvif, hdr, skb->len);
+ rtw89_vif_sync_bcn_tsf(rtwvif_link, hdr, skb->len);
rtw89_fw_h2c_rssi_offload(rtwdev, phy_ppdu);
}
pkt_stat->beacon_nr++;
+
+ if (phy_ppdu)
+ ewma_rssi_add(&rtwdev->phystat.bcn_rssi, phy_ppdu->rssi_avg);
}
- if (!ether_addr_equal(vif->addr, hdr->addr1))
- return;
+ if (!ether_addr_equal(bss_conf->addr, hdr->addr1))
+ goto out;
if (desc_info->data_rate < RTW89_HW_RATE_NR)
pkt_stat->rx_rate_cnt[desc_info->data_rate]++;
rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false);
+
+out:
+ rcu_read_unlock();
}
static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev,
@@ -2432,15 +2542,23 @@ void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta)
struct rtw89_core_iter_rx_status *iter_data =
(struct rtw89_core_iter_rx_status *)data;
struct ieee80211_rx_status *rx_status = iter_data->rx_status;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_rx_desc_info *desc_info = iter_data->desc_info;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_sta_link *rtwsta_link;
u8 mac_id = iter_data->mac_id;
- if (mac_id != rtwsta->mac_id)
+ /* FIXME: For single link, taking link on HW-0 here is okay. But, when
+ * enabling multiple active links, we should determine the right link.
+ */
+ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+ if (unlikely(!rtwsta_link))
return;
- rtwsta->rx_status = *rx_status;
- rtwsta->rx_hw_rate = desc_info->data_rate;
+ if (mac_id != rtwsta_link->mac_id)
+ return;
+
+ rtwsta_link->rx_status = *rx_status;
+ rtwsta_link->rx_hw_rate = desc_info->data_rate;
}
static void rtw89_core_stats_sta_rx_status(struct rtw89_dev *rtwdev,
@@ -2546,6 +2664,10 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
+ /* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */
+ if (rtwdev->support_mlo)
+ return RTW89_PS_MODE_NONE;
+
if (rtw89_disable_ps_mode || !chip->ps_mode_supported ||
RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw))
return RTW89_PS_MODE_NONE;
@@ -2658,7 +2780,7 @@ static void rtw89_core_ba_work(struct work_struct *work)
list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) {
struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq);
struct ieee80211_sta *sta = txq->sta;
- struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
u8 tid = txq->tid;
if (!sta) {
@@ -2686,8 +2808,8 @@ skip_ba_work:
spin_unlock_bh(&rtwdev->ba_lock);
}
-static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta)
+void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta)
{
struct rtw89_txq *rtwtxq, *tmp;
@@ -2701,8 +2823,8 @@ static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev,
spin_unlock_bh(&rtwdev->ba_lock);
}
-static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta)
+void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta)
{
struct rtw89_txq *rtwtxq, *tmp;
@@ -2718,10 +2840,10 @@ static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev,
spin_unlock_bh(&rtwdev->ba_lock);
}
-static void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta)
+void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
struct sk_buff *skb, *tmp;
skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) {
@@ -2762,7 +2884,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
struct ieee80211_hw *hw = rtwdev->hw;
struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq);
struct ieee80211_sta *sta = txq->sta;
- struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags))
return;
@@ -2838,10 +2960,19 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev,
bool *sched_txq, bool *reinvoke)
{
struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv;
- struct ieee80211_sta *sta = txq->sta;
- struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(txq->sta);
+ struct rtw89_sta_link *rtwsta_link;
+
+ if (!rtwsta)
+ return false;
+
+ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+ if (unlikely(!rtwsta_link)) {
+ rtw89_err(rtwdev, "agg wait: find no link on HW-0\n");
+ return false;
+ }
- if (!sta || rtwsta->max_agg_wait <= 0)
+ if (rtwsta_link->max_agg_wait <= 0)
return false;
if (rtwdev->stats.tx_tfc_lv <= RTW89_TFC_MID)
@@ -2855,7 +2986,7 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev,
return false;
}
- if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta->max_agg_wait) {
+ if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta_link->max_agg_wait) {
*reinvoke = true;
rtwtxq->wait_cnt++;
return true;
@@ -2879,7 +3010,7 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv
ieee80211_txq_schedule_start(hw, ac);
while ((txq = ieee80211_next_txq(hw, ac))) {
rtwtxq = (struct rtw89_txq *)txq->drv_priv;
- rtwvif = (struct rtw89_vif *)txq->vif->drv_priv;
+ rtwvif = vif_to_rtwvif(txq->vif);
if (rtwvif->offchan) {
ieee80211_return_txq(hw, txq, true);
@@ -2955,16 +3086,23 @@ static void rtw89_forbid_ba_work(struct work_struct *w)
static void rtw89_core_sta_pending_tx_iter(void *data,
struct ieee80211_sta *sta)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_vif *rtwvif_target = data, *rtwvif = rtwsta->rtwvif;
- struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct rtw89_vif_link *target = data;
+ struct rtw89_vif_link *rtwvif_link;
struct sk_buff *skb, *tmp;
+ unsigned int link_id;
int qsel, ret;
- if (rtwvif->chanctx_idx != rtwvif_target->chanctx_idx)
- return;
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ if (rtwvif_link->chanctx_idx == target->chanctx_idx)
+ goto bottom;
+ return;
+
+bottom:
if (skb_queue_len(&rtwsta->roc_queue) == 0)
return;
@@ -2982,17 +3120,17 @@ static void rtw89_core_sta_pending_tx_iter(void *data,
}
static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
ieee80211_iterate_stations_atomic(rtwdev->hw,
rtw89_core_sta_pending_tx_iter,
- rtwvif);
+ rtwvif_link);
}
static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool qos, bool ps)
+ struct rtw89_vif_link *rtwvif_link, bool qos, bool ps)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
struct ieee80211_sta *sta;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
@@ -3002,7 +3140,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
return 0;
rcu_read_lock();
- sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
+ sta = ieee80211_find_sta(vif, vif->cfg.ap_addr);
if (!sta) {
ret = -EINVAL;
goto out;
@@ -3040,31 +3178,49 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw89_roc *roc = &rtwvif->roc;
+ struct rtw89_vif_link *rtwvif_link;
struct cfg80211_chan_def roc_chan;
- struct rtw89_vif *tmp;
+ struct rtw89_vif *tmp_vif;
+ u32 reg;
int ret;
lockdep_assert_held(&rtwdev->mutex);
rtw89_leave_ips_by_hwflags(rtwdev);
rtw89_leave_lps(rtwdev);
+
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, RTW89_ROC_BY_LINK_INDEX);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "roc start: find no link on HW-%u\n",
+ RTW89_ROC_BY_LINK_INDEX);
+ return;
+ }
+
rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC);
- ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, true);
+ ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true);
if (ret)
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
"roc send null-1 failed: %d\n", ret);
- rtw89_for_each_rtwvif(rtwdev, tmp)
- if (tmp->chanctx_idx == rtwvif->chanctx_idx)
- tmp->offchan = true;
+ rtw89_for_each_rtwvif(rtwdev, tmp_vif) {
+ struct rtw89_vif_link *tmp_link;
+ unsigned int link_id;
+
+ rtw89_vif_for_each_link(tmp_vif, tmp_link, link_id) {
+ if (tmp_link->chanctx_idx == rtwvif_link->chanctx_idx) {
+ tmp_vif->offchan = true;
+ break;
+ }
+ }
+ }
cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT);
- rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, &roc_chan);
+ rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, &roc_chan);
rtw89_set_channel(rtwdev);
- rtw89_write32_clr(rtwdev,
- rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
- B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx);
+ rtw89_write32_clr(rtwdev, reg, B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH);
ieee80211_ready_on_channel(hw);
cancel_delayed_work(&rtwvif->roc.roc_work);
@@ -3077,7 +3233,9 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw89_roc *roc = &rtwvif->roc;
- struct rtw89_vif *tmp;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_vif *tmp_vif;
+ u32 reg;
int ret;
lockdep_assert_held(&rtwdev->mutex);
@@ -3087,24 +3245,28 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
rtw89_leave_ips_by_hwflags(rtwdev);
rtw89_leave_lps(rtwdev);
- rtw89_write32_mask(rtwdev,
- rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
- B_AX_RX_FLTR_CFG_MASK,
- rtwdev->hal.rx_fltr);
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, RTW89_ROC_BY_LINK_INDEX);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "roc end: find no link on HW-%u\n",
+ RTW89_ROC_BY_LINK_INDEX);
+ return;
+ }
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr);
roc->state = RTW89_ROC_IDLE;
- rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, NULL);
+ rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, NULL);
rtw89_chanctx_proceed(rtwdev);
- ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, false);
+ ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false);
if (ret)
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
"roc send null-0 failed: %d\n", ret);
- rtw89_for_each_rtwvif(rtwdev, tmp)
- if (tmp->chanctx_idx == rtwvif->chanctx_idx)
- tmp->offchan = false;
+ rtw89_for_each_rtwvif(rtwdev, tmp_vif)
+ tmp_vif->offchan = false;
- rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif);
+ rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif_link);
queue_work(rtwdev->txq_wq, &rtwdev->txq_work);
if (hw->conf.flags & IEEE80211_CONF_IDLE)
@@ -3188,39 +3350,52 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev,
static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
bool tfc_changed;
tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats);
+
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats);
- rtw89_fw_h2c_tp_offload(rtwdev, rtwvif);
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link);
}
return tfc_changed;
}
-static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- if ((rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION &&
- rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) ||
- rtwvif->tdls_peer)
- return;
-
- if (rtwvif->offchan)
+ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
+ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
return;
- if (rtwvif->stats.tx_tfc_lv == RTW89_TFC_IDLE &&
- rtwvif->stats.rx_tfc_lv == RTW89_TFC_IDLE)
- rtw89_enter_lps(rtwdev, rtwvif, true);
+ rtw89_enter_lps(rtwdev, rtwvif_link, true);
}
static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
- rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_vif_enter_lps(rtwdev, rtwvif);
+ rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+ if (rtwvif->tdls_peer)
+ continue;
+ if (rtwvif->offchan)
+ continue;
+
+ if (rtwvif->stats.tx_tfc_lv != RTW89_TFC_IDLE ||
+ rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE)
+ continue;
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_vif_enter_lps(rtwdev, rtwvif_link);
+ }
}
static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev)
@@ -3234,14 +3409,16 @@ static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev)
rtw89_chip_rfk_track(rtwdev);
}
-void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
+void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf)
{
enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev);
if (mode == RTW89_ENTITY_MODE_MCC)
rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_P2P_PS_CHANGE);
else
- rtw89_process_p2p_ps(rtwdev, vif);
+ rtw89_process_p2p_ps(rtwdev, rtwvif_link, bss_conf);
}
void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev,
@@ -3326,7 +3503,8 @@ void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits)
}
int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
+ struct rtw89_sta_link *rtwsta_link, u8 tid,
+ u8 *cam_idx)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
@@ -3363,7 +3541,7 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
}
entry->tid = tid;
- list_add_tail(&entry->list, &rtwsta->ba_cam_list);
+ list_add_tail(&entry->list, &rtwsta_link->ba_cam_list);
*cam_idx = idx;
@@ -3371,7 +3549,8 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
}
int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
+ struct rtw89_sta_link *rtwsta_link, u8 tid,
+ u8 *cam_idx)
{
struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
struct rtw89_ba_cam_entry *entry = NULL, *tmp;
@@ -3379,7 +3558,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
lockdep_assert_held(&rtwdev->mutex);
- list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) {
+ list_for_each_entry_safe(entry, tmp, &rtwsta_link->ba_cam_list, list) {
if (entry->tid != tid)
continue;
@@ -3396,24 +3575,25 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
#define RTW89_TYPE_MAPPING(_type) \
case NL80211_IFTYPE_ ## _type: \
- rtwvif->wifi_role = RTW89_WIFI_ROLE_ ## _type; \
+ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_ ## _type; \
break
-void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc)
+void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct ieee80211_bss_conf *bss_conf;
switch (vif->type) {
case NL80211_IFTYPE_STATION:
if (vif->p2p)
- rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT;
+ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT;
else
- rtwvif->wifi_role = RTW89_WIFI_ROLE_STATION;
+ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_STATION;
break;
case NL80211_IFTYPE_AP:
if (vif->p2p)
- rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_GO;
+ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_GO;
else
- rtwvif->wifi_role = RTW89_WIFI_ROLE_AP;
+ rtwvif_link->wifi_role = RTW89_WIFI_ROLE_AP;
break;
RTW89_TYPE_MAPPING(ADHOC);
RTW89_TYPE_MAPPING(MONITOR);
@@ -3426,23 +3606,27 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc)
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
- rtwvif->net_type = RTW89_NET_TYPE_AP_MODE;
- rtwvif->self_role = RTW89_SELF_ROLE_AP;
+ rtwvif_link->net_type = RTW89_NET_TYPE_AP_MODE;
+ rtwvif_link->self_role = RTW89_SELF_ROLE_AP;
break;
case NL80211_IFTYPE_ADHOC:
- rtwvif->net_type = RTW89_NET_TYPE_AD_HOC;
- rtwvif->self_role = RTW89_SELF_ROLE_CLIENT;
+ rtwvif_link->net_type = RTW89_NET_TYPE_AD_HOC;
+ rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT;
break;
case NL80211_IFTYPE_STATION:
if (assoc) {
- rtwvif->net_type = RTW89_NET_TYPE_INFRA;
- rtwvif->trigger = vif->bss_conf.he_support;
+ rtwvif_link->net_type = RTW89_NET_TYPE_INFRA;
+
+ rcu_read_lock();
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
+ rtwvif_link->trigger = bss_conf->he_support;
+ rcu_read_unlock();
} else {
- rtwvif->net_type = RTW89_NET_TYPE_NO_LINK;
- rtwvif->trigger = false;
+ rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK;
+ rtwvif_link->trigger = false;
}
- rtwvif->self_role = RTW89_SELF_ROLE_CLIENT;
- rtwvif->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL;
+ rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT;
+ rtwvif_link->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL;
break;
case NL80211_IFTYPE_MONITOR:
break;
@@ -3452,137 +3636,110 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc)
}
}
-int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
struct rtw89_hal *hal = &rtwdev->hal;
u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
int i;
int ret;
- rtwsta->rtwdev = rtwdev;
- rtwsta->rtwvif = rtwvif;
- rtwsta->prev_rssi = 0;
- INIT_LIST_HEAD(&rtwsta->ba_cam_list);
- skb_queue_head_init(&rtwsta->roc_queue);
-
- for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
- rtw89_core_txq_init(rtwdev, sta->txq[i]);
-
- ewma_rssi_init(&rtwsta->avg_rssi);
- ewma_snr_init(&rtwsta->avg_snr);
- ewma_evm_init(&rtwsta->evm_1ss);
+ rtwsta_link->prev_rssi = 0;
+ INIT_LIST_HEAD(&rtwsta_link->ba_cam_list);
+ ewma_rssi_init(&rtwsta_link->avg_rssi);
+ ewma_snr_init(&rtwsta_link->avg_snr);
+ ewma_evm_init(&rtwsta_link->evm_1ss);
for (i = 0; i < ant_num; i++) {
- ewma_rssi_init(&rtwsta->rssi[i]);
- ewma_evm_init(&rtwsta->evm_min[i]);
- ewma_evm_init(&rtwsta->evm_max[i]);
+ ewma_rssi_init(&rtwsta_link->rssi[i]);
+ ewma_evm_init(&rtwsta_link->evm_min[i]);
+ ewma_evm_init(&rtwsta_link->evm_max[i]);
}
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
- /* for station mode, assign the mac_id from itself */
- rtwsta->mac_id = rtwvif->mac_id;
-
/* must do rtw89_reg_6ghz_recalc() before rfk channel */
- ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true);
+ ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true);
if (ret)
return ret;
- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
+ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link,
BTC_ROLE_MSTS_STA_CONN_START);
- rtw89_chip_rfk_channel(rtwdev, rtwvif);
+ rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
} else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
- rtwsta->mac_id = rtw89_acquire_mac_id(rtwdev);
- if (rtwsta->mac_id == RTW89_MAX_MAC_ID_NUM)
- return -ENOSPC;
-
- ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta->mac_id, false);
+ ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false);
if (ret) {
- rtw89_release_mac_id(rtwdev, rtwsta->mac_id);
rtw89_warn(rtwdev, "failed to send h2c macid pause\n");
return ret;
}
- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
+ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link,
RTW89_ROLE_CREATE);
if (ret) {
- rtw89_release_mac_id(rtwdev, rtwsta->mac_id);
rtw89_warn(rtwdev, "failed to send h2c role info\n");
return ret;
}
- ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta);
+ ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
if (ret)
return ret;
- ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta);
+ ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
if (ret)
return ret;
-
- rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE);
}
return 0;
}
-int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
if (vif->type == NL80211_IFTYPE_STATION)
- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, false);
-
- rtwdev->total_sta_assoc--;
- if (sta->tdls)
- rtwvif->tdls_peer--;
- rtwsta->disassoc = true;
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false);
return 0;
}
-int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
int ret;
- rtw89_mac_bf_monitor_calc(rtwdev, sta, true);
- rtw89_mac_bf_disassoc(rtwdev, vif, sta);
- rtw89_core_free_sta_pending_ba(rtwdev, sta);
- rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta);
- rtw89_core_free_sta_pending_roc_tx(rtwdev, sta);
+ rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, true);
+ rtw89_mac_bf_disassoc(rtwdev, rtwvif_link, rtwsta_link);
if (vif->type == NL80211_IFTYPE_AP || sta->tdls)
- rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
+ rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam);
if (sta->tdls)
- rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam);
+ rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam);
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
- rtw89_vif_type_mapping(vif, false);
- rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, true);
+ rtw89_vif_type_mapping(rtwvif_link, false);
+ rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, true);
}
- ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta);
+ ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cmac table\n");
return ret;
}
- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, true);
+ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, true);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c join info\n");
return ret;
}
/* update cam aid mac_id net_type */
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret;
@@ -3591,106 +3748,114 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
return ret;
}
-int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta);
+ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
+ struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link,
+ rtwsta_link);
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
int ret;
if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
if (sta->tdls) {
- ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, sta->addr);
+ struct ieee80211_link_sta *link_sta;
+
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam,
+ link_sta->addr);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c init bssid cam for TDLS\n");
+ rcu_read_unlock();
return ret;
}
+
+ rcu_read_unlock();
}
- ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta->addr_cam, bssid_cam);
+ ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta_link->addr_cam, bssid_cam);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c init addr cam\n");
return ret;
}
}
- ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta);
+ ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cmac table\n");
return ret;
}
- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, false);
+ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, false);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c join info\n");
return ret;
}
/* update cam aid mac_id net_type */
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret;
}
- rtwdev->total_sta_assoc++;
- if (sta->tdls)
- rtwvif->tdls_peer++;
- rtw89_phy_ra_assoc(rtwdev, sta);
- rtw89_mac_bf_assoc(rtwdev, vif, sta);
- rtw89_mac_bf_monitor_calc(rtwdev, sta, false);
+ rtw89_phy_ra_assoc(rtwdev, rtwsta_link);
+ rtw89_mac_bf_assoc(rtwdev, rtwvif_link, rtwsta_link);
+ rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, false);
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ieee80211_bss_conf *bss_conf;
+
+ rcu_read_lock();
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
if (bss_conf->he_support &&
!(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE))
- rtwsta->er_cap = true;
+ rtwsta_link->er_cap = true;
- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
+ rcu_read_unlock();
+
+ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link,
BTC_ROLE_MSTS_STA_CONN_END);
- rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template, chan);
- rtw89_phy_ul_tb_assoc(rtwdev, rtwvif);
+ rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta_link->htc_template, chan);
+ rtw89_phy_ul_tb_assoc(rtwdev, rtwvif_link);
- ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id);
+ ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c general packet\n");
return ret;
}
- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
}
return ret;
}
-int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
int ret;
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
- rtw89_reg_6ghz_recalc(rtwdev, rtwvif, false);
- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
+ rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, false);
+ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link,
BTC_ROLE_MSTS_STA_DIS_CONN);
} else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
- rtw89_release_mac_id(rtwdev, rtwsta->mac_id);
-
- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
+ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link,
RTW89_ROLE_REMOVE);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c role info\n");
return ret;
}
-
- rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE);
}
return 0;
@@ -4152,15 +4317,16 @@ static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev)
void rtw89_core_update_beacon_work(struct work_struct *work)
{
struct rtw89_dev *rtwdev;
- struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif,
- update_beacon_work);
+ struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link,
+ update_beacon_work);
- if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE)
+ if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE)
return;
- rtwdev = rtwvif->rtwdev;
+ rtwdev = rtwvif_link->rtwvif->rtwdev;
+
mutex_lock(&rtwdev->mutex);
- rtw89_chip_h2c_update_beacon(rtwdev, rtwvif);
+ rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link);
mutex_unlock(&rtwdev->mutex);
}
@@ -4266,8 +4432,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
rtw89_phy_dm_init(rtwdev);
- rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
- rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0);
+ rtw89_mac_cfg_ppdu_status_bands(rtwdev, true);
+ rtw89_mac_update_rts_threshold(rtwdev);
rtw89_tas_reset(rtwdev);
@@ -4355,6 +4521,168 @@ void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id)
clear_bit(mac_id, rtwdev->mac_id_map);
}
+void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ u8 mac_id, u8 port)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u8 support_link_num = chip->support_link_num;
+ u8 support_mld_num = 0;
+ unsigned int link_id;
+ u8 index;
+
+ bitmap_zero(rtwvif->links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
+ rtwvif->links[link_id] = NULL;
+
+ rtwvif->rtwdev = rtwdev;
+
+ if (rtwdev->support_mlo) {
+ rtwvif->links_inst_valid_num = support_link_num;
+ support_mld_num = chip->support_macid_num / support_link_num;
+ } else {
+ rtwvif->links_inst_valid_num = 1;
+ }
+
+ for (index = 0; index < rtwvif->links_inst_valid_num; index++) {
+ struct rtw89_vif_link *inst = &rtwvif->links_inst[index];
+
+ inst->rtwvif = rtwvif;
+ inst->mac_id = mac_id + index * support_mld_num;
+ inst->mac_idx = RTW89_MAC_0 + index;
+ inst->phy_idx = RTW89_PHY_0 + index;
+
+ /* multi-link use the same port id on different HW bands */
+ inst->port = port;
+ }
+}
+
+void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_sta *rtwsta, u8 mac_id)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u8 support_link_num = chip->support_link_num;
+ u8 support_mld_num = 0;
+ unsigned int link_id;
+ u8 index;
+
+ bitmap_zero(rtwsta->links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
+ rtwsta->links[link_id] = NULL;
+
+ rtwsta->rtwdev = rtwdev;
+ rtwsta->rtwvif = rtwvif;
+
+ if (rtwdev->support_mlo) {
+ rtwsta->links_inst_valid_num = support_link_num;
+ support_mld_num = chip->support_macid_num / support_link_num;
+ } else {
+ rtwsta->links_inst_valid_num = 1;
+ }
+
+ for (index = 0; index < rtwsta->links_inst_valid_num; index++) {
+ struct rtw89_sta_link *inst = &rtwsta->links_inst[index];
+
+ inst->rtwvif_link = &rtwvif->links_inst[index];
+
+ inst->rtwsta = rtwsta;
+ inst->mac_id = mac_id + index * support_mld_num;
+ }
+}
+
+struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif,
+ unsigned int link_id)
+{
+ struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id];
+ u8 index;
+ int ret;
+
+ if (rtwvif_link)
+ return rtwvif_link;
+
+ index = find_first_zero_bit(rtwvif->links_inst_map,
+ rtwvif->links_inst_valid_num);
+ if (index == rtwvif->links_inst_valid_num) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ rtwvif_link = &rtwvif->links_inst[index];
+ rtwvif_link->link_id = link_id;
+
+ set_bit(index, rtwvif->links_inst_map);
+ rtwvif->links[link_id] = rtwvif_link;
+ return rtwvif_link;
+
+err:
+ rtw89_err(rtwvif->rtwdev, "vif (link_id %u) failed to set link: %d\n",
+ link_id, ret);
+ return NULL;
+}
+
+void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id)
+{
+ struct rtw89_vif_link **container = &rtwvif->links[link_id];
+ struct rtw89_vif_link *link = *container;
+ u8 index;
+
+ if (!link)
+ return;
+
+ index = rtw89_vif_link_inst_get_index(link);
+ clear_bit(index, rtwvif->links_inst_map);
+ *container = NULL;
+}
+
+struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
+ unsigned int link_id)
+{
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id];
+ struct rtw89_sta_link *rtwsta_link = rtwsta->links[link_id];
+ u8 index;
+ int ret;
+
+ if (rtwsta_link)
+ return rtwsta_link;
+
+ if (!rtwvif_link) {
+ ret = -ENOLINK;
+ goto err;
+ }
+
+ index = rtw89_vif_link_inst_get_index(rtwvif_link);
+ if (test_bit(index, rtwsta->links_inst_map)) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ rtwsta_link = &rtwsta->links_inst[index];
+ rtwsta_link->link_id = link_id;
+
+ set_bit(index, rtwsta->links_inst_map);
+ rtwsta->links[link_id] = rtwsta_link;
+ return rtwsta_link;
+
+err:
+ rtw89_err(rtwsta->rtwdev, "sta (link_id %u) failed to set link: %d\n",
+ link_id, ret);
+ return NULL;
+}
+
+void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id)
+{
+ struct rtw89_sta_link **container = &rtwsta->links[link_id];
+ struct rtw89_sta_link *link = *container;
+ u8 index;
+
+ if (!link)
+ return;
+
+ index = rtw89_sta_link_inst_get_index(link);
+ clear_bit(index, rtwsta->links_inst_map);
+ *container = NULL;
+}
+
int rtw89_core_init(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
@@ -4444,39 +4772,45 @@ void rtw89_core_deinit(struct rtw89_dev *rtwdev)
}
EXPORT_SYMBOL(rtw89_core_deinit);
-void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
const u8 *mac_addr, bool hw_scan)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
rtwdev->scanning = true;
rtw89_leave_lps(rtwdev);
if (hw_scan)
rtw89_leave_ips_by_hwflags(rtwdev);
- ether_addr_copy(rtwvif->mac_addr, mac_addr);
- rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type);
- rtw89_chip_rfk_scan(rtwdev, rtwvif, true);
+ ether_addr_copy(rtwvif_link->mac_addr, mac_addr);
+ rtw89_btc_ntfy_scan_start(rtwdev, rtwvif_link->phy_idx, chan->band_type);
+ rtw89_chip_rfk_scan(rtwdev, rtwvif_link, true);
rtw89_hci_recalc_int_mit(rtwdev);
rtw89_phy_config_edcca(rtwdev, true);
- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, mac_addr);
+ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr);
}
void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif, bool hw_scan)
+ struct rtw89_vif_link *rtwvif_link, bool hw_scan)
{
- struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
+ struct ieee80211_bss_conf *bss_conf;
- if (!rtwvif)
+ if (!rtwvif_link)
return;
- ether_addr_copy(rtwvif->mac_addr, vif->addr);
- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr);
+
+ rcu_read_unlock();
+
+ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
- rtw89_chip_rfk_scan(rtwdev, rtwvif, false);
- rtw89_btc_ntfy_scan_finish(rtwdev, RTW89_PHY_0);
+ rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false);
+ rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx);
rtw89_phy_config_edcca(rtwdev, false);
rtwdev->scanning = false;
@@ -4513,11 +4847,20 @@ static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev)
static void rtw89_core_setup_phycap(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
rtwdev->hal.support_cckpd =
!(rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv <= CHIP_CBV) &&
!(rtwdev->chip->chip_id == RTL8852B && rtwdev->hal.cv <= CHIP_CAV);
rtwdev->hal.support_igi =
rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv <= CHIP_CBV;
+
+ if (test_bit(RTW89_QUIRK_THERMAL_PROT_120C, rtwdev->quirks))
+ rtwdev->hal.thermal_prot_th = chip->thermal_th[1];
+ else if (test_bit(RTW89_QUIRK_THERMAL_PROT_110C, rtwdev->quirks))
+ rtwdev->hal.thermal_prot_th = chip->thermal_th[0];
+ else
+ rtwdev->hal.thermal_prot_th = 0;
}
static void rtw89_core_setup_rfe_parms(struct rtw89_dev *rtwdev)
@@ -4688,17 +5031,39 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
}
EXPORT_SYMBOL(rtw89_chip_info_setup);
+void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct ieee80211_bss_conf *bss_conf;
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
+ if (!bss_conf->he_support || !vif->cfg.assoc) {
+ rcu_read_unlock();
+ return;
+ }
+
+ rcu_read_unlock();
+
+ if (chip->ops->set_txpwr_ul_tb_offset)
+ chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif_link->mac_idx);
+}
+
static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
+ u8 n = rtwdev->support_mlo ? chip->support_link_num : 1;
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw89_hal *hal = &rtwdev->hal;
int ret;
int tx_headroom = IEEE80211_HT_CTL_LEN;
- hw->vif_data_size = sizeof(struct rtw89_vif);
- hw->sta_data_size = sizeof(struct rtw89_sta);
+ hw->vif_data_size = struct_size_t(struct rtw89_vif, links_inst, n);
+ hw->sta_data_size = struct_size_t(struct rtw89_sta, links_inst, n);
hw->txq_data_size = sizeof(struct rtw89_txq);
hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 4ed9034fdb46..5ad32eacd0d5 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -829,6 +829,8 @@ enum rtw89_phy_idx {
RTW89_PHY_MAX
};
+#define __RTW89_MLD_MAX_LINK_NUM 2
+
enum rtw89_chanctx_idx {
RTW89_CHANCTX_0 = 0,
RTW89_CHANCTX_1 = 1,
@@ -1160,14 +1162,15 @@ struct rtw89_tx_desc_info {
bool er_cap;
bool stbc;
bool ldpc;
+ bool upd_wlan_hdr;
};
struct rtw89_core_tx_request {
enum rtw89_core_tx_type tx_type;
struct sk_buff *skb;
- struct ieee80211_vif *vif;
- struct ieee80211_sta *sta;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
struct rtw89_tx_desc_info desc_info;
};
@@ -1350,7 +1353,6 @@ struct rtw89_btc_wl_smap {
u32 connecting: 1;
u32 roaming: 1;
u32 dbccing: 1;
- u32 transacting: 1;
u32 _4way: 1;
u32 rf_off: 1;
u32 lps: 2;
@@ -2937,6 +2939,7 @@ struct rtw89_btc_dm {
u8 wl_pre_agc: 2;
u8 wl_lna2: 1;
+ u8 freerun_chk: 1;
u8 wl_pre_agc_rb: 2;
u8 bt_select: 2; /* 0:s0, 1:s1, 2:s0 & s1, refer to enum btc_bt_index */
u8 slot_req_more: 1;
@@ -2975,6 +2978,8 @@ enum rtw89_btc_btf_fw_event {
BTF_EVNT_BT_REG = 3,
BTF_EVNT_CX_RUNINFO = 4,
BTF_EVNT_BT_PSD = 5,
+ BTF_EVNT_BT_DEV_INFO = 6, /* fwc2hfunc > 0 */
+ BTF_EVNT_BT_LEAUDIO_INFO = 7, /* fwc2hfunc > 1 */
BTF_EVNT_BUF_OVERFLOW,
BTF_EVNT_C2H_LOOPBACK,
BTF_EVNT_MAX,
@@ -3141,6 +3146,7 @@ struct rtw89_btc_ver {
u8 fcxinit;
u8 fwevntrptl;
+ u8 fwc2hfunc;
u8 drvinfo_type;
u16 info_buf;
u8 max_role_num;
@@ -3354,12 +3360,13 @@ struct rtw89_sec_cam_entry {
u8 key[32];
};
-struct rtw89_sta {
+struct rtw89_sta_link {
+ struct rtw89_sta *rtwsta;
+ unsigned int link_id;
+
u8 mac_id;
- bool disassoc;
bool er_cap;
- struct rtw89_dev *rtwdev;
- struct rtw89_vif *rtwvif;
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_ra_info ra;
struct rtw89_ra_report ra_report;
int max_agg_wait;
@@ -3370,15 +3377,12 @@ struct rtw89_sta {
struct ewma_evm evm_1ss;
struct ewma_evm evm_min[RF_PATH_MAX];
struct ewma_evm evm_max[RF_PATH_MAX];
- struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
- DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS);
struct ieee80211_rx_status rx_status;
u16 rx_hw_rate;
__le32 htc_template;
struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */
struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */
struct list_head ba_cam_list;
- struct sk_buff_head roc_queue;
bool use_cfg_mask;
struct cfg80211_bitrate_mask mask;
@@ -3424,6 +3428,8 @@ enum rtw89_roc_state {
RTW89_ROC_MGMT,
};
+#define RTW89_ROC_BY_LINK_INDEX 0
+
struct rtw89_roc {
struct ieee80211_channel chan;
struct delayed_work roc_work;
@@ -3460,10 +3466,10 @@ struct rtw89_p2p_noa_setter {
u8 noa_index;
};
-struct rtw89_vif {
- struct list_head list;
- struct rtw89_dev *rtwdev;
- struct rtw89_roc roc;
+struct rtw89_vif_link {
+ struct rtw89_vif *rtwvif;
+ unsigned int link_id;
+
bool chanctx_assigned; /* only valid when running with chanctx_ops */
enum rtw89_chanctx_idx chanctx_idx;
enum rtw89_reg_6ghz_power reg_6ghz_power;
@@ -3473,7 +3479,6 @@ struct rtw89_vif {
u8 port;
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
- __be32 ip_addr;
u8 phy_idx;
u8 mac_idx;
u8 net_type;
@@ -3484,7 +3489,6 @@ struct rtw89_vif {
u8 hit_rule;
u8 last_noa_nr;
u64 sync_bcn_tsf;
- bool offchan;
bool trigger;
bool lsig_txop;
u8 tgt_ind;
@@ -3498,15 +3502,11 @@ struct rtw89_vif {
bool pre_pwr_diff_en;
bool pwr_diff_en;
u8 def_tri_idx;
- u32 tdls_peer;
struct work_struct update_beacon_work;
struct rtw89_addr_cam_entry addr_cam;
struct rtw89_bssid_cam_entry bssid_cam;
struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS];
- struct rtw89_traffic_stats stats;
struct rtw89_phy_rate_pattern rate_pattern;
- struct cfg80211_scan_request *scan_req;
- struct ieee80211_scan_ies *scan_ies;
struct list_head general_pkt_list;
struct rtw89_p2p_noa_setter p2p_noa;
};
@@ -3599,11 +3599,11 @@ struct rtw89_chip_ops {
void (*rfk_hw_init)(struct rtw89_dev *rtwdev);
void (*rfk_init)(struct rtw89_dev *rtwdev);
void (*rfk_init_late)(struct rtw89_dev *rtwdev);
- void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+ void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
void (*rfk_band_changed)(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan);
- void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool start);
void (*rfk_track)(struct rtw89_dev *rtwdev);
void (*power_trim)(struct rtw89_dev *rtwdev);
@@ -3646,23 +3646,25 @@ struct rtw89_chip_ops {
u32 *tx_en, enum rtw89_sch_tx_sel sel);
int (*resume_sch_tx)(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
int (*h2c_dctl_sec_cam)(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int (*h2c_default_cmac_tbl)(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int (*h2c_assoc_cmac_tbl)(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int (*h2c_ampdu_cmac_tbl)(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int (*h2c_update_beacon)(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
- int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link);
+ int (*h2c_ba_cam)(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
bool valid, struct ieee80211_ampdu_params *params);
void (*btc_set_rfe)(struct rtw89_dev *rtwdev);
@@ -4245,6 +4247,7 @@ struct rtw89_chip_info {
u8 wde_qempty_acq_grpnum;
u8 wde_qempty_mgq_grpsel;
u32 rf_base_addr[2];
+ u8 thermal_th[2];
u8 support_macid_num;
u8 support_link_num;
u8 support_chanctx_num;
@@ -4445,6 +4448,8 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_SCAN_OFFLOAD_BE_V0,
RTW89_FW_FEATURE_WOW_REASON_V1,
RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0,
+ RTW89_FW_FEATURE_RFK_RXDCK_V0,
+ RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX,
};
struct rtw89_fw_suit {
@@ -4511,11 +4516,14 @@ enum rtw89_fw_mss_dev_type {
};
struct rtw89_fw_secure {
- bool secure_boot;
+ bool secure_boot: 1;
+ bool can_mss_v1: 1;
+ bool can_mss_v0: 1;
u32 sb_sel_mgn;
u8 mss_dev_type;
u8 mss_cust_idx;
u8 mss_key_num;
+ u8 mss_idx; /* v0 */
};
struct rtw89_fw_info {
@@ -4561,7 +4569,7 @@ enum rtw89_sar_subband {
RTW89_SAR_2GHZ_SUBBAND,
RTW89_SAR_5GHZ_SUBBAND_1_2, /* U-NII-1 and U-NII-2 */
RTW89_SAR_5GHZ_SUBBAND_2_E, /* U-NII-2-Extended */
- RTW89_SAR_5GHZ_SUBBAND_3, /* U-NII-3 */
+ RTW89_SAR_5GHZ_SUBBAND_3_4, /* U-NII-3 and U-NII-4 */
RTW89_SAR_6GHZ_SUBBAND_5_L, /* U-NII-5 lower part */
RTW89_SAR_6GHZ_SUBBAND_5_H, /* U-NII-5 higher part */
RTW89_SAR_6GHZ_SUBBAND_6, /* U-NII-6 */
@@ -4623,7 +4631,7 @@ enum rtw89_chanctx_changes {
};
enum rtw89_entity_mode {
- RTW89_ENTITY_MODE_SCC,
+ RTW89_ENTITY_MODE_SCC_OR_SMLD,
RTW89_ENTITY_MODE_MCC_PREPARE,
RTW89_ENTITY_MODE_MCC,
@@ -4632,6 +4640,16 @@ enum rtw89_entity_mode {
RTW89_ENTITY_MODE_UNHANDLED = -ESRCH,
};
+#define RTW89_MAX_INTERFACE_NUM 2
+
+/* only valid when running with chanctx_ops */
+struct rtw89_entity_mgnt {
+ struct list_head active_list;
+ struct rtw89_vif *active_roles[RTW89_MAX_INTERFACE_NUM];
+ enum rtw89_chanctx_idx chanctx_tbl[RTW89_MAX_INTERFACE_NUM]
+ [__RTW89_MLD_MAX_LINK_NUM];
+};
+
struct rtw89_chanctx {
struct cfg80211_chan_def chandef;
struct rtw89_chan chan;
@@ -4650,8 +4668,12 @@ struct rtw89_edcca_bak {
enum rtw89_dm_type {
RTW89_DM_DYNAMIC_EDCCA,
+ RTW89_DM_THERMAL_PROTECT,
};
+#define RTW89_THERMAL_PROT_LV_MAX 5
+#define RTW89_THERMAL_PROT_STEP 19 /* -19% for each level */
+
struct rtw89_hal {
u32 rx_fltr;
u8 cv;
@@ -4672,12 +4694,16 @@ struct rtw89_hal {
struct rtw89_chanctx chanctx[NUM_OF_RTW89_CHANCTX];
struct cfg80211_chan_def roc_chandef;
- bool entity_active;
+ bool entity_active[RTW89_PHY_MAX];
bool entity_pause;
enum rtw89_entity_mode entity_mode;
+ struct rtw89_entity_mgnt entity_mgnt;
struct rtw89_edcca_bak edcca_bak;
u32 disabled_dm_bitmap; /* bitmap of enum rtw89_dm_type */
+
+ u8 thermal_prot_th;
+ u8 thermal_prot_lv; /* 0 ~ RTW89_THERMAL_PROT_LV_MAX */
};
#define RTW89_MAX_MAC_ID_NUM 128
@@ -4710,10 +4736,22 @@ enum rtw89_flags {
enum rtw89_quirks {
RTW89_QUIRK_PCI_BER,
+ RTW89_QUIRK_THERMAL_PROT_120C,
+ RTW89_QUIRK_THERMAL_PROT_110C,
NUM_OF_RTW89_QUIRKS,
};
+enum rtw89_custid {
+ RTW89_CUSTID_NONE,
+ RTW89_CUSTID_ACER,
+ RTW89_CUSTID_AMD,
+ RTW89_CUSTID_ASUS,
+ RTW89_CUSTID_DELL,
+ RTW89_CUSTID_HP,
+ RTW89_CUSTID_LENOVO,
+};
+
enum rtw89_pkt_drop_sel {
RTW89_PKT_DROP_SEL_MACID_BE_ONCE,
RTW89_PKT_DROP_SEL_MACID_BK_ONCE,
@@ -4750,6 +4788,8 @@ DECLARE_EWMA(thermal, 4, 4);
struct rtw89_phy_stat {
struct ewma_thermal avg_thermal[RF_PATH_MAX];
+ u8 last_thermal_max;
+ struct ewma_rssi bcn_rssi;
struct rtw89_pkt_stat cur_pkt_stat;
struct rtw89_pkt_stat last_pkt_stat;
};
@@ -4791,13 +4831,17 @@ enum rtw89_rfk_chs_nrs {
RTW89_RFK_CHS_NR = __RTW89_RFK_CHS_NR_V1,
};
-struct rtw89_rfk_mcc_info {
+struct rtw89_rfk_mcc_info_data {
u8 ch[RTW89_RFK_CHS_NR];
u8 band[RTW89_RFK_CHS_NR];
u8 bw[RTW89_RFK_CHS_NR];
u8 table_idx;
};
+struct rtw89_rfk_mcc_info {
+ struct rtw89_rfk_mcc_info_data data[2];
+};
+
#define RTW89_IQK_CHS_NR 2
#define RTW89_IQK_PATH_NR 4
@@ -4902,6 +4946,7 @@ struct rtw89_agc_gaincode_set {
#define IGI_RSSI_TH_NUM 5
#define FA_TH_NUM 4
+#define TIA_LNA_OP1DB_NUM 8
#define LNA_GAIN_NUM 7
#define TIA_GAIN_NUM 2
struct rtw89_dig_info {
@@ -5196,7 +5241,7 @@ struct rtw89_early_h2c {
};
struct rtw89_hw_scan_info {
- struct ieee80211_vif *scanning_vif;
+ struct rtw89_vif_link *scanning_vif;
struct list_head pkt_list[NUM_NL80211_BANDS];
struct rtw89_chan op_chan;
bool abort;
@@ -5371,7 +5416,7 @@ struct rtw89_wow_aoac_report {
};
struct rtw89_wow_param {
- struct ieee80211_vif *wow_vif;
+ struct rtw89_vif_link *rtwvif_link;
DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM);
struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM];
struct rtw89_wow_key_info key_info;
@@ -5408,7 +5453,7 @@ struct rtw89_mcc_policy {
};
struct rtw89_mcc_role {
- struct rtw89_vif *rtwvif;
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_mcc_policy policy;
struct rtw89_mcc_limit limit;
@@ -5509,6 +5554,7 @@ struct rtw89_dev {
struct rtw89_efuse efuse;
struct rtw89_traffic_stats stats;
struct rtw89_rfe_data *rfe_data;
+ enum rtw89_custid custid;
/* ensures exclusive access from mac80211 callbacks */
struct mutex mutex;
@@ -5608,6 +5654,122 @@ struct rtw89_dev {
u8 priv[] __aligned(sizeof(void *));
};
+struct rtw89_vif {
+ struct rtw89_dev *rtwdev;
+ struct list_head list;
+ struct list_head mgnt_entry;
+
+ u8 mac_addr[ETH_ALEN];
+ __be32 ip_addr;
+
+ struct rtw89_traffic_stats stats;
+ u32 tdls_peer;
+
+ struct ieee80211_scan_ies *scan_ies;
+ struct cfg80211_scan_request *scan_req;
+
+ struct rtw89_roc roc;
+ bool offchan;
+
+ u8 links_inst_valid_num;
+ DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+ struct rtw89_vif_link *links[IEEE80211_MLD_MAX_NUM_LINKS];
+ struct rtw89_vif_link links_inst[] __counted_by(links_inst_valid_num);
+};
+
+static inline bool rtw89_vif_assign_link_is_valid(struct rtw89_vif_link **rtwvif_link,
+ const struct rtw89_vif *rtwvif,
+ unsigned int link_id)
+{
+ *rtwvif_link = rtwvif->links[link_id];
+ return !!*rtwvif_link;
+}
+
+#define rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) \
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \
+ if (rtw89_vif_assign_link_is_valid(&(rtwvif_link), rtwvif, link_id))
+
+struct rtw89_sta {
+ struct rtw89_dev *rtwdev;
+ struct rtw89_vif *rtwvif;
+
+ bool disassoc;
+
+ struct sk_buff_head roc_queue;
+
+ struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
+ DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS);
+
+ u8 links_inst_valid_num;
+ DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
+ struct rtw89_sta_link *links[IEEE80211_MLD_MAX_NUM_LINKS];
+ struct rtw89_sta_link links_inst[] __counted_by(links_inst_valid_num);
+};
+
+static inline bool rtw89_sta_assign_link_is_valid(struct rtw89_sta_link **rtwsta_link,
+ const struct rtw89_sta *rtwsta,
+ unsigned int link_id)
+{
+ *rtwsta_link = rtwsta->links[link_id];
+ return !!*rtwsta_link;
+}
+
+#define rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) \
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \
+ if (rtw89_sta_assign_link_is_valid(&(rtwsta_link), rtwsta, link_id))
+
+static inline u8 rtw89_vif_get_main_macid(struct rtw89_vif *rtwvif)
+{
+ /* const after init, so no need to check if active first */
+ return rtwvif->links_inst[0].mac_id;
+}
+
+static inline u8 rtw89_vif_get_main_port(struct rtw89_vif *rtwvif)
+{
+ /* const after init, so no need to check if active first */
+ return rtwvif->links_inst[0].port;
+}
+
+static inline struct rtw89_vif_link *
+rtw89_vif_get_link_inst(struct rtw89_vif *rtwvif, u8 index)
+{
+ if (index >= rtwvif->links_inst_valid_num ||
+ !test_bit(index, rtwvif->links_inst_map))
+ return NULL;
+ return &rtwvif->links_inst[index];
+}
+
+static inline
+u8 rtw89_vif_link_inst_get_index(struct rtw89_vif_link *rtwvif_link)
+{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+
+ return rtwvif_link - rtwvif->links_inst;
+}
+
+static inline u8 rtw89_sta_get_main_macid(struct rtw89_sta *rtwsta)
+{
+ /* const after init, so no need to check if active first */
+ return rtwsta->links_inst[0].mac_id;
+}
+
+static inline struct rtw89_sta_link *
+rtw89_sta_get_link_inst(struct rtw89_sta *rtwsta, u8 index)
+{
+ if (index >= rtwsta->links_inst_valid_num ||
+ !test_bit(index, rtwsta->links_inst_map))
+ return NULL;
+ return &rtwsta->links_inst[index];
+}
+
+static inline
+u8 rtw89_sta_link_inst_get_index(struct rtw89_sta_link *rtwsta_link)
+{
+ struct rtw89_sta *rtwsta = rtwsta_link->rtwsta;
+
+ return rtwsta_link - rtwsta->links_inst;
+}
+
static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
{
@@ -5972,9 +6134,26 @@ static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif *rtwvif)
return rtwvif ? rtwvif_to_vif(rtwvif) : NULL;
}
+static inline
+struct ieee80211_vif *rtwvif_link_to_vif(struct rtw89_vif_link *rtwvif_link)
+{
+ return rtwvif_to_vif(rtwvif_link->rtwvif);
+}
+
+static inline
+struct ieee80211_vif *rtwvif_link_to_vif_safe(struct rtw89_vif_link *rtwvif_link)
+{
+ return rtwvif_link ? rtwvif_link_to_vif(rtwvif_link) : NULL;
+}
+
+static inline struct rtw89_vif *vif_to_rtwvif(struct ieee80211_vif *vif)
+{
+ return (struct rtw89_vif *)vif->drv_priv;
+}
+
static inline struct rtw89_vif *vif_to_rtwvif_safe(struct ieee80211_vif *vif)
{
- return vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
+ return vif ? vif_to_rtwvif(vif) : NULL;
}
static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta)
@@ -5989,11 +6168,88 @@ static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta *rtwsta)
return rtwsta ? rtwsta_to_sta(rtwsta) : NULL;
}
+static inline
+struct ieee80211_sta *rtwsta_link_to_sta(struct rtw89_sta_link *rtwsta_link)
+{
+ return rtwsta_to_sta(rtwsta_link->rtwsta);
+}
+
+static inline
+struct ieee80211_sta *rtwsta_link_to_sta_safe(struct rtw89_sta_link *rtwsta_link)
+{
+ return rtwsta_link ? rtwsta_link_to_sta(rtwsta_link) : NULL;
+}
+
+static inline struct rtw89_sta *sta_to_rtwsta(struct ieee80211_sta *sta)
+{
+ return (struct rtw89_sta *)sta->drv_priv;
+}
+
static inline struct rtw89_sta *sta_to_rtwsta_safe(struct ieee80211_sta *sta)
{
- return sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
+ return sta ? sta_to_rtwsta(sta) : NULL;
+}
+
+static inline struct ieee80211_bss_conf *
+__rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink)
+{
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct ieee80211_bss_conf *bss_conf;
+
+ bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]);
+ if (unlikely(!bss_conf)) {
+ *nolink = true;
+ return &vif->bss_conf;
+ }
+
+ *nolink = false;
+ return bss_conf;
+}
+
+#define rtw89_vif_rcu_dereference_link(rtwvif_link, assert) \
+({ \
+ typeof(rtwvif_link) p = rtwvif_link; \
+ struct ieee80211_bss_conf *bss_conf; \
+ bool nolink; \
+ \
+ bss_conf = __rtw89_vif_rcu_dereference_link(p, &nolink); \
+ if (unlikely(nolink) && (assert)) \
+ rtw89_err(p->rtwvif->rtwdev, \
+ "%s: cannot find exact bss_conf for link_id %u\n",\
+ __func__, p->link_id); \
+ bss_conf; \
+})
+
+static inline struct ieee80211_link_sta *
+__rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolink)
+{
+ struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
+ struct ieee80211_link_sta *link_sta;
+
+ link_sta = rcu_dereference(sta->link[rtwsta_link->link_id]);
+ if (unlikely(!link_sta)) {
+ *nolink = true;
+ return &sta->deflink;
+ }
+
+ *nolink = false;
+ return link_sta;
}
+#define rtw89_sta_rcu_dereference_link(rtwsta_link, assert) \
+({ \
+ typeof(rtwsta_link) p = rtwsta_link; \
+ struct ieee80211_link_sta *link_sta; \
+ bool nolink; \
+ \
+ link_sta = __rtw89_sta_rcu_dereference_link(p, &nolink); \
+ if (unlikely(nolink) && (assert)) \
+ rtw89_err(p->rtwsta->rtwdev, \
+ "%s: cannot find exact link_sta for link_id %u\n",\
+ __func__, p->link_id); \
+ link_sta; \
+})
+
static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw)
{
if (hw_bw == RTW89_CHANNEL_WIDTH_160)
@@ -6078,29 +6334,29 @@ enum nl80211_he_ru_alloc rtw89_he_rua_to_ru_alloc(u16 rua)
}
static inline
-struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- if (rtwsta) {
- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
+ if (rtwsta_link) {
+ struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
- return &rtwsta->addr_cam;
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
+ return &rtwsta_link->addr_cam;
}
- return &rtwvif->addr_cam;
+ return &rtwvif_link->addr_cam;
}
static inline
-struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- if (rtwsta) {
- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
+ if (rtwsta_link) {
+ struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link);
if (sta->tdls)
- return &rtwsta->bssid_cam;
+ return &rtwsta_link->bssid_cam;
}
- return &rtwvif->bssid_cam;
+ return &rtwvif_link->bssid_cam;
}
static inline
@@ -6157,13 +6413,21 @@ const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev,
}
static inline
+const struct rtw89_chan_rcd *rtw89_chan_rcd_get_by_chan(const struct rtw89_chan *chan)
+{
+ const struct rtw89_chanctx *chanctx =
+ container_of_const(chan, struct rtw89_chanctx, chan);
+
+ return &chanctx->rcd;
+}
+
+static inline
const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev)
{
- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
+ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
- if (rtwvif)
- return rtw89_chan_get(rtwdev, rtwvif->chanctx_idx);
+ if (rtwvif_link)
+ return rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
else
return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
}
@@ -6240,12 +6504,12 @@ static inline void rtw89_chip_rfk_init_late(struct rtw89_dev *rtwdev)
}
static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
if (chip->ops->rfk_channel)
- chip->ops->rfk_channel(rtwdev, rtwvif);
+ chip->ops->rfk_channel(rtwdev, rtwvif_link);
}
static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev,
@@ -6259,12 +6523,12 @@ static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev,
}
static inline void rtw89_chip_rfk_scan(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool start)
+ struct rtw89_vif_link *rtwvif_link, bool start)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
if (chip->ops->rfk_scan)
- chip->ops->rfk_scan(rtwdev, rtwvif, start);
+ chip->ops->rfk_scan(rtwdev, rtwvif_link, start);
}
static inline void rtw89_chip_rfk_track(struct rtw89_dev *rtwdev)
@@ -6279,8 +6543,12 @@ static inline void rtw89_chip_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- if (chip->ops->set_txpwr_ctrl)
- chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_0);
+ if (!chip->ops->set_txpwr_ctrl)
+ return;
+
+ chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_0);
+ if (rtwdev->dbcc_en)
+ chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_1);
}
static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev)
@@ -6291,8 +6559,8 @@ static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev)
chip->ops->power_trim(rtwdev);
}
-static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx)
+static inline void __rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
@@ -6300,6 +6568,13 @@ static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev,
chip->ops->init_txpwr_unit(rtwdev, phy_idx);
}
+static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev)
+{
+ __rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0);
+ if (rtwdev->dbcc_en)
+ __rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_1);
+}
+
static inline u8 rtw89_chip_get_thermal(struct rtw89_dev *rtwdev,
enum rtw89_rf_path rf_path)
{
@@ -6347,20 +6622,6 @@ static inline void rtw89_chip_cfg_txrx_path(struct rtw89_dev *rtwdev)
chip->ops->cfg_txrx_path(rtwdev);
}
-static inline
-void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif)
-{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- const struct rtw89_chip_info *chip = rtwdev->chip;
-
- if (!vif->bss_conf.he_support || !vif->cfg.assoc)
- return;
-
- if (chip->ops->set_txpwr_ul_tb_offset)
- chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif->mac_idx);
-}
-
static inline void rtw89_chip_digital_pwr_comp(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
@@ -6457,14 +6718,14 @@ int rtw89_chip_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
static inline
int rtw89_chip_h2c_dctl_sec_cam(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
if (!chip->ops->h2c_dctl_sec_cam)
return 0;
- return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
+ return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link);
}
static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
@@ -6479,13 +6740,14 @@ static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
return hdr->addr3;
}
-static inline bool rtw89_sta_has_beamformer_cap(struct ieee80211_sta *sta)
+static inline
+bool rtw89_sta_has_beamformer_cap(struct ieee80211_link_sta *link_sta)
{
- if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) ||
- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) ||
- (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] &
+ if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) ||
+ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) ||
+ (link_sta->he_cap.he_cap_elem.phy_cap_info[3] &
IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) ||
- (sta->deflink.he_cap.he_cap_elem.phy_cap_info[4] &
+ (link_sta->he_cap.he_cap_elem.phy_cap_info[4] &
IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER))
return true;
return false;
@@ -6605,21 +6867,21 @@ void rtw89_core_napi_start(struct rtw89_dev *rtwdev);
void rtw89_core_napi_stop(struct rtw89_dev *rtwdev);
int rtw89_core_napi_init(struct rtw89_dev *rtwdev);
void rtw89_core_napi_deinit(struct rtw89_dev *rtwdev);
-int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
+int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
+int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
+int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
+int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev,
struct ieee80211_sta *sta,
struct cfg80211_tid_config *tid_config);
@@ -6635,22 +6897,40 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev);
u8 rtw89_acquire_mac_id(struct rtw89_dev *rtwdev);
void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id);
+void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ u8 mac_id, u8 port);
+void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_sta *rtwsta, u8 mac_id);
+struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif,
+ unsigned int link_id);
+void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id);
+struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
+ unsigned int link_id);
+void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id);
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
struct rtw89_chan *chan);
int rtw89_set_channel(struct rtw89_dev *rtwdev);
-void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_chan *chan);
u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size);
void rtw89_core_release_bit_map(unsigned long *addr, u8 bit);
void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits);
int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
+ struct rtw89_sta_link *rtwsta_link, u8 tid,
+ u8 *cam_idx);
int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
-void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc);
+ struct rtw89_sta_link *rtwsta_link, u8 tid,
+ u8 *cam_idx);
+void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta);
+void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta);
+void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta);
+void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc);
int rtw89_chip_info_setup(struct rtw89_dev *rtwdev);
+void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link);
bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate);
int rtw89_regd_setup(struct rtw89_dev *rtwdev);
int rtw89_regd_init(struct rtw89_dev *rtwdev,
@@ -6667,13 +6947,15 @@ void rtw89_core_update_beacon_work(struct work_struct *work);
void rtw89_roc_work(struct work_struct *work);
void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
-void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
const u8 *mac_addr, bool hw_scan);
void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif, bool hw_scan);
-int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link, bool hw_scan);
+int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool active);
-void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
+void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf);
void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 29f85210f919..6abd88fa80ba 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -3506,7 +3506,9 @@ out:
return count;
}
-static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
+static void rtw89_sta_link_info_get_iter(struct seq_file *m,
+ struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link)
{
static const char * const he_gi_str[] = {
[NL80211_RATE_INFO_HE_GI_0_8] = "0.8",
@@ -3518,20 +3520,26 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
[NL80211_RATE_INFO_EHT_GI_1_6] = "1.6",
[NL80211_RATE_INFO_EHT_GI_3_2] = "3.2",
};
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rate_info *rate = &rtwsta->ra_report.txrate;
- struct ieee80211_rx_status *status = &rtwsta->rx_status;
- struct seq_file *m = (struct seq_file *)data;
- struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rate_info *rate = &rtwsta_link->ra_report.txrate;
+ struct ieee80211_rx_status *status = &rtwsta_link->rx_status;
struct rtw89_hal *hal = &rtwdev->hal;
u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity;
+ struct ieee80211_link_sta *link_sta;
u8 evm_min, evm_max, evm_1ss;
+ u16 max_rc_amsdu_len;
u8 rssi;
u8 snr;
int i;
- seq_printf(m, "TX rate [%d]: ", rtwsta->mac_id);
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ max_rc_amsdu_len = link_sta->agg.max_rc_amsdu_len;
+
+ rcu_read_unlock();
+
+ seq_printf(m, "TX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id);
if (rate->flags & RATE_INFO_FLAGS_MCS)
seq_printf(m, "HT MCS-%d%s", rate->mcs,
@@ -3549,13 +3557,13 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
eht_gi_str[rate->eht_gi] : "N/A");
else
seq_printf(m, "Legacy %d", rate->legacy);
- seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : "");
+ seq_printf(m, "%s", rtwsta_link->ra_report.might_fallback_legacy ? " FB_G" : "");
seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw));
- seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate);
- seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait,
- sta->deflink.agg.max_rc_amsdu_len);
+ seq_printf(m, " (hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate);
+ seq_printf(m, " ==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait,
+ max_rc_amsdu_len);
- seq_printf(m, "RX rate [%d]: ", rtwsta->mac_id);
+ seq_printf(m, "RX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id);
switch (status->encoding) {
case RX_ENC_LEGACY:
@@ -3582,24 +3590,24 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
break;
}
seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw));
- seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta->rx_hw_rate);
+ seq_printf(m, " (hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate);
- rssi = ewma_rssi_read(&rtwsta->avg_rssi);
+ rssi = ewma_rssi_read(&rtwsta_link->avg_rssi);
seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [",
- RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi);
+ RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta_link->prev_rssi);
for (i = 0; i < ant_num; i++) {
- rssi = ewma_rssi_read(&rtwsta->rssi[i]);
+ rssi = ewma_rssi_read(&rtwsta_link->rssi[i]);
seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi),
ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "",
i + 1 == ant_num ? "" : ", ");
}
seq_puts(m, "]\n");
- evm_1ss = ewma_evm_read(&rtwsta->evm_1ss);
+ evm_1ss = ewma_evm_read(&rtwsta_link->evm_1ss);
seq_printf(m, "EVM: [%2u.%02u, ", evm_1ss >> 2, (evm_1ss & 0x3) * 25);
for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) {
- evm_min = ewma_evm_read(&rtwsta->evm_min[i]);
- evm_max = ewma_evm_read(&rtwsta->evm_max[i]);
+ evm_min = ewma_evm_read(&rtwsta_link->evm_min[i]);
+ evm_max = ewma_evm_read(&rtwsta_link->evm_max[i]);
seq_printf(m, "%s(%2u.%02u, %2u.%02u)", i == 0 ? "" : " ",
evm_min >> 2, (evm_min & 0x3) * 25,
@@ -3607,10 +3615,22 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
}
seq_puts(m, "]\t");
- snr = ewma_snr_read(&rtwsta->avg_snr);
+ snr = ewma_snr_read(&rtwsta_link->avg_snr);
seq_printf(m, "SNR: %u\n", snr);
}
+static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct seq_file *m = (struct seq_file *)data;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
+ rtw89_sta_link_info_get_iter(m, rtwdev, rtwsta_link);
+}
+
static void
rtw89_debug_append_rx_rate(struct seq_file *m, struct rtw89_pkt_stat *pkt_stat,
enum rtw89_hw_rate first_rate, int len)
@@ -3652,14 +3672,22 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v)
struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.last_pkt_stat;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_rx_rate_cnt_info *info;
+ struct rtw89_hal *hal = &rtwdev->hal;
enum rtw89_hw_rate first_rate;
+ u8 rssi;
int i;
- seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n",
- stats->tx_throughput, stats->tx_throughput_raw, stats->tx_tfc_lv,
+ rssi = ewma_rssi_read(&rtwdev->phystat.bcn_rssi);
+
+ seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d",
+ stats->tx_throughput, stats->tx_throughput_raw, stats->tx_tfc_lv);
+ if (hal->thermal_prot_lv)
+ seq_printf(m, ", duty: %d%%",
+ 100 - hal->thermal_prot_lv * RTW89_THERMAL_PROT_STEP);
+ seq_printf(m, "), RX: %u [%u] Mbps (lv: %d)\n",
stats->rx_throughput, stats->rx_throughput_raw, stats->rx_tfc_lv);
- seq_printf(m, "Beacon: %u, TF: %u\n", pkt_stat->beacon_nr,
- stats->rx_tf_periodic);
+ seq_printf(m, "Beacon: %u (%d dBm), TF: %u\n", pkt_stat->beacon_nr,
+ RTW89_RSSI_RAW_TO_DBM(rssi), stats->rx_tf_periodic);
seq_printf(m, "Avg packet length: TX=%u, RX=%u\n", stats->tx_avg_len,
stats->rx_avg_len);
@@ -3737,28 +3765,41 @@ static void rtw89_dump_pkt_offload(struct seq_file *m, struct list_head *pkt_lis
seq_puts(m, "\n");
}
+static void rtw89_vif_link_ids_get(struct seq_file *m, u8 *mac,
+ struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam;
+
+ seq_printf(m, " [%u] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr);
+ seq_printf(m, "\tlink_id=%u\n", rtwvif_link->link_id);
+ seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx);
+ rtw89_dump_addr_cam(m, rtwdev, &rtwvif_link->addr_cam);
+ rtw89_dump_pkt_offload(m, &rtwvif_link->general_pkt_list,
+ "\tpkt_ofld[GENERAL]: ");
+}
+
static
void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_dev *rtwdev = rtwvif->rtwdev;
struct seq_file *m = (struct seq_file *)data;
- struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
- seq_printf(m, "VIF [%d] %pM\n", rtwvif->mac_id, rtwvif->mac_addr);
- seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx);
- rtw89_dump_addr_cam(m, rtwdev, &rtwvif->addr_cam);
- rtw89_dump_pkt_offload(m, &rtwvif->general_pkt_list, "\tpkt_ofld[GENERAL]: ");
+ seq_printf(m, "VIF %pM\n", rtwvif->mac_addr);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_vif_link_ids_get(m, mac, rtwdev, rtwvif_link);
}
-static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta)
+static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
- struct rtw89_dev *rtwdev = rtwvif->rtwdev;
struct rtw89_ba_cam_entry *entry;
bool first = true;
- list_for_each_entry(entry, &rtwsta->ba_cam_list, list) {
+ list_for_each_entry(entry, &rtwsta_link->ba_cam_list, list) {
if (first) {
seq_puts(m, "\tba_cam ");
first = false;
@@ -3771,16 +3812,36 @@ static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta)
seq_puts(m, "\n");
}
+static void rtw89_sta_link_ids_get(struct seq_file *m,
+ struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link)
+{
+ struct ieee80211_link_sta *link_sta;
+
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+
+ seq_printf(m, " [%u] %pM\n", rtwsta_link->mac_id, link_sta->addr);
+
+ rcu_read_unlock();
+
+ seq_printf(m, "\tlink_id=%u\n", rtwsta_link->link_id);
+ rtw89_dump_addr_cam(m, rtwdev, &rtwsta_link->addr_cam);
+ rtw89_dump_ba_cam(m, rtwdev, rtwsta_link);
+}
+
static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_dev *rtwdev = rtwsta->rtwdev;
struct seq_file *m = (struct seq_file *)data;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
- seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr,
- sta->tdls ? "(TDLS)" : "");
- rtw89_dump_addr_cam(m, rtwdev, &rtwsta->addr_cam);
- rtw89_dump_ba_cam(m, rtwsta);
+ seq_printf(m, "STA %pM %s\n", sta->addr, sta->tdls ? "(TDLS)" : "");
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
+ rtw89_sta_link_ids_get(m, rtwdev, rtwsta_link);
}
static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
@@ -3830,6 +3891,7 @@ static const struct rtw89_disabled_dm_info {
const char *name;
} rtw89_disabled_dm_infos[] = {
DM_INFO(DYNAMIC_EDCCA),
+ DM_INFO(THERMAL_PROTECT),
};
static int
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c
index e1236079a84a..6c6c763510af 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse.c
@@ -11,11 +11,38 @@
#define EF_CV_MASK GENMASK(7, 4)
#define EF_CV_INV 15
+#define EFUSE_B1_MSSDEVTYPE_MASK GENMASK(3, 0)
+#define EFUSE_B1_MSSCUSTIDX0_MASK GENMASK(7, 4)
+#define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0)
+#define EFUSE_B2_MSSCUSTIDX1_MASK BIT(6)
+
+#define EFUSE_EXTERNALPN_ADDR_AX 0x5EC
+#define EFUSE_CUSTOMER_ADDR_AX 0x5ED
+#define EFUSE_SERIALNUM_ADDR_AX 0x5ED
+
+#define EFUSE_B1_EXTERNALPN_MASK GENMASK(7, 0)
+#define EFUSE_B2_CUSTOMER_MASK GENMASK(3, 0)
+#define EFUSE_B2_SERIALNUM_MASK GENMASK(6, 4)
+
+#define OTP_KEY_INFO_NUM 2
+
+static const u8 otp_key_info_externalPN[OTP_KEY_INFO_NUM] = {0x0, 0x0};
+static const u8 otp_key_info_customer[OTP_KEY_INFO_NUM] = {0x0, 0x1};
+static const u8 otp_key_info_serialNum[OTP_KEY_INFO_NUM] = {0x0, 0x1};
+
enum rtw89_efuse_bank {
RTW89_EFUSE_BANK_WIFI,
RTW89_EFUSE_BANK_BT,
};
+enum rtw89_efuse_mss_dev_type {
+ MSS_DEV_TYPE_FWSEC_DEF = 0xF,
+ MSS_DEV_TYPE_FWSEC_WINLIN_INBOX = 0xC,
+ MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB = 0xA,
+ MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB = 0x9,
+ MSS_DEV_TYPE_FWSEC_NONWIN_INBOX = 0x6,
+};
+
static int rtw89_switch_efuse_bank(struct rtw89_dev *rtwdev,
enum rtw89_efuse_bank bank)
{
@@ -354,3 +381,126 @@ int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *ecv)
return 0;
}
EXPORT_SYMBOL(rtw89_read_efuse_ver);
+
+static u8 get_mss_dev_type_idx(struct rtw89_dev *rtwdev, u8 mss_dev_type)
+{
+ switch (mss_dev_type) {
+ case MSS_DEV_TYPE_FWSEC_WINLIN_INBOX:
+ mss_dev_type = 0x0;
+ break;
+ case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB:
+ mss_dev_type = 0x1;
+ break;
+ case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB:
+ mss_dev_type = 0x2;
+ break;
+ case MSS_DEV_TYPE_FWSEC_NONWIN_INBOX:
+ mss_dev_type = 0x3;
+ break;
+ case MSS_DEV_TYPE_FWSEC_DEF:
+ mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_DEF;
+ break;
+ default:
+ rtw89_warn(rtwdev, "unknown mss_dev_type %d", mss_dev_type);
+ mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_INV;
+ break;
+ }
+
+ return mss_dev_type;
+}
+
+int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+ u8 mss_dev_type;
+
+ if (chip->chip_id == RTL8852B && b1 == 0xFF && b2 == 0x6E) {
+ mss_dev_type = MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB;
+ sec->mss_cust_idx = 0;
+ sec->mss_key_num = 0;
+
+ goto mss_dev_type;
+ }
+
+ mss_dev_type = u8_get_bits(b1, EFUSE_B1_MSSDEVTYPE_MASK);
+ sec->mss_cust_idx = 0x1F - (u8_get_bits(b1, EFUSE_B1_MSSCUSTIDX0_MASK) |
+ u8_get_bits(b2, EFUSE_B2_MSSCUSTIDX1_MASK) << 4);
+ sec->mss_key_num = 0xF - u8_get_bits(b2, EFUSE_B2_MSSKEYNUM_MASK);
+
+mss_dev_type:
+ sec->mss_dev_type = get_mss_dev_type_idx(rtwdev, mss_dev_type);
+ if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_INV) {
+ rtw89_warn(rtwdev, "invalid mss_dev_type %d\n", mss_dev_type);
+ return -ENOENT;
+ }
+
+ sec->can_mss_v1 = true;
+
+ return 0;
+}
+
+static
+int rtw89_efuse_recognize_mss_index_v0(struct rtw89_dev *rtwdev, u8 b1, u8 b2)
+{
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+ u8 externalPN;
+ u8 serialNum;
+ u8 customer;
+ u8 i;
+
+ externalPN = 0xFF - u8_get_bits(b1, EFUSE_B1_EXTERNALPN_MASK);
+ customer = 0xF - u8_get_bits(b2, EFUSE_B2_CUSTOMER_MASK);
+ serialNum = 0x7 - u8_get_bits(b2, EFUSE_B2_SERIALNUM_MASK);
+
+ for (i = 0; i < OTP_KEY_INFO_NUM; i++) {
+ if (externalPN == otp_key_info_externalPN[i] &&
+ customer == otp_key_info_customer[i] &&
+ serialNum == otp_key_info_serialNum[i]) {
+ sec->mss_idx = i;
+ sec->can_mss_v0 = true;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+ u32 sec_addr = EFUSE_EXTERNALPN_ADDR_AX;
+ u32 sec_size = 2;
+ u8 sec_map[2];
+ u8 b1, b2;
+ int ret;
+
+ ret = rtw89_dump_physical_efuse_map(rtwdev, sec_map,
+ sec_addr, sec_size, false);
+ if (ret) {
+ rtw89_warn(rtwdev, "failed to dump secsel map\n");
+ return ret;
+ }
+
+ b1 = sec_map[0];
+ b2 = sec_map[1];
+
+ if (b1 == 0xFF && b2 == 0xFF)
+ return 0;
+
+ rtw89_efuse_recognize_mss_index_v0(rtwdev, b1, b2);
+ rtw89_efuse_recognize_mss_info_v1(rtwdev, b1, b2);
+ if (!sec->can_mss_v1 && !sec->can_mss_v0)
+ goto out;
+
+ sec->secure_boot = true;
+
+out:
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "MSS secure_boot=%d(%d/%d) dev_type=%d cust_idx=%d key_num=%d mss_index=%d\n",
+ sec->secure_boot, sec->can_mss_v0, sec->can_mss_v1,
+ sec->mss_dev_type, sec->mss_cust_idx,
+ sec->mss_key_num, sec->mss_idx);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h
index 72416f56a071..a96fc1044791 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.h
+++ b/drivers/net/wireless/realtek/rtw89/efuse.h
@@ -23,6 +23,8 @@ int rtw89_parse_efuse_map_be(struct rtw89_dev *rtwdev);
int rtw89_parse_phycap_map_be(struct rtw89_dev *rtwdev);
int rtw89_cnv_efuse_state_be(struct rtw89_dev *rtwdev, bool idle);
int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv);
+int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2);
+int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev);
int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c
index 0be26d5fdf7c..64768923b0f0 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse_be.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c
@@ -8,11 +8,7 @@
#include "reg.h"
#define EFUSE_EXTERNALPN_ADDR_BE 0x1580
-#define EFUSE_B1_MSSDEVTYPE_MASK GENMASK(3, 0)
-#define EFUSE_B1_MSSCUSTIDX0_MASK GENMASK(7, 4)
#define EFUSE_SERIALNUM_ADDR_BE 0x1581
-#define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0)
-#define EFUSE_B2_MSSCUSTIDX1_MASK BIT(6)
#define EFUSE_SB_CRYP_SEL_ADDR 0x1582
#define EFUSE_SB_CRYP_SEL_SIZE 2
#define EFUSE_SB_CRYP_SEL_DEFAULT 0xFFFF
@@ -20,14 +16,6 @@
#define EFUSE_SEC_BE_START 0x1580
#define EFUSE_SEC_BE_SIZE 4
-enum rtw89_efuse_mss_dev_type {
- MSS_DEV_TYPE_FWSEC_DEF = 0xF,
- MSS_DEV_TYPE_FWSEC_WINLIN_INBOX = 0xC,
- MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB = 0xA,
- MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB = 0x9,
- MSS_DEV_TYPE_FWSEC_NONWIN_INBOX = 0x6,
-};
-
static const u32 sb_sel_mgn[SB_SEL_MGN_MAX_SIZE] = {
0x8000100, 0xC000180
};
@@ -477,33 +465,6 @@ static u16 get_sb_cryp_sel_idx(u16 sb_cryp_sel)
return sb_cryp_sel_v + low_bit;
}
-static u8 get_mss_dev_type_idx(struct rtw89_dev *rtwdev, u8 mss_dev_type)
-{
- switch (mss_dev_type) {
- case MSS_DEV_TYPE_FWSEC_WINLIN_INBOX:
- mss_dev_type = 0x0;
- break;
- case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB:
- mss_dev_type = 0x1;
- break;
- case MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_COB:
- mss_dev_type = 0x2;
- break;
- case MSS_DEV_TYPE_FWSEC_NONWIN_INBOX:
- mss_dev_type = 0x3;
- break;
- case MSS_DEV_TYPE_FWSEC_DEF:
- mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_DEF;
- break;
- default:
- rtw89_warn(rtwdev, "unknown mss_dev_type %d", mss_dev_type);
- mss_dev_type = RTW89_FW_MSS_DEV_TYPE_FWSEC_INV;
- break;
- }
-
- return mss_dev_type;
-}
-
int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev)
{
struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
@@ -511,7 +472,6 @@ int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev)
u32 sec_size = EFUSE_SEC_BE_SIZE;
u16 sb_cryp_sel, sb_cryp_sel_idx;
u8 sec_map[EFUSE_SEC_BE_SIZE];
- u8 mss_dev_type;
u8 b1, b2;
int ret;
@@ -538,16 +498,9 @@ int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev)
b1 = sec_map[EFUSE_EXTERNALPN_ADDR_BE - sec_addr];
b2 = sec_map[EFUSE_SERIALNUM_ADDR_BE - sec_addr];
- mss_dev_type = u8_get_bits(b1, EFUSE_B1_MSSDEVTYPE_MASK);
- sec->mss_cust_idx = 0x1F - (u8_get_bits(b1, EFUSE_B1_MSSCUSTIDX0_MASK) |
- u8_get_bits(b2, EFUSE_B2_MSSCUSTIDX1_MASK) << 4);
- sec->mss_key_num = 0xF - u8_get_bits(b2, EFUSE_B2_MSSKEYNUM_MASK);
-
- sec->mss_dev_type = get_mss_dev_type_idx(rtwdev, mss_dev_type);
- if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_INV) {
- rtw89_warn(rtwdev, "invalid mss_dev_type %d\n", mss_dev_type);
+ ret = rtw89_efuse_recognize_mss_info_v1(rtwdev, b1, b2);
+ if (ret)
goto out;
- }
sec->secure_boot = true;
@@ -559,4 +512,3 @@ out:
return 0;
}
-EXPORT_SYMBOL(rtw89_efuse_read_fw_secure_be);
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index d9b0e7ebe619..2191c037d72e 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -56,6 +56,11 @@ static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
struct sk_buff *skb);
static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
struct rtw89_wait_info *wait, unsigned int cond);
+static int __parse_security_section(struct rtw89_dev *rtwdev,
+ struct rtw89_fw_bin_info *info,
+ struct rtw89_fw_hdr_section_info *section_info,
+ const void *content,
+ u32 *mssc_len);
static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len,
bool header)
@@ -124,13 +129,16 @@ static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
struct rtw89_fw_bin_info *info)
{
const struct rtw89_fw_hdr *fw_hdr = (const struct rtw89_fw_hdr *)fw;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_fw_hdr_section_info *section_info;
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
const struct rtw89_fw_dynhdr_hdr *fwdynhdr;
const struct rtw89_fw_hdr_section *section;
const u8 *fw_end = fw + len;
const u8 *bin;
u32 base_hdr_len;
- u32 mssc_len = 0;
+ u32 mssc_len;
+ int ret;
u32 i;
if (!info)
@@ -139,6 +147,7 @@ static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_W6_SEC_NUM);
base_hdr_len = struct_size(fw_hdr, sections, info->section_num);
info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_W7_DYN_HDR);
+ info->idmem_share_mode = le32_get_bits(fw_hdr->w7, FW_HDR_W7_IDMEM_SHARE_MODE);
if (info->dynamic_hdr_en) {
info->hdr_len = le32_get_bits(fw_hdr->w3, FW_HDR_W3_LEN);
@@ -161,26 +170,47 @@ static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
section = &fw_hdr->sections[i];
section_info->type =
le32_get_bits(section->w1, FWSECTION_HDR_W1_SECTIONTYPE);
- if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
- section_info->mssc =
- le32_get_bits(section->w2, FWSECTION_HDR_W2_MSSC);
- mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN;
- } else {
- section_info->mssc = 0;
- }
-
section_info->len = le32_get_bits(section->w1, FWSECTION_HDR_W1_SEC_SIZE);
+
if (le32_get_bits(section->w1, FWSECTION_HDR_W1_CHECKSUM))
section_info->len += FWDL_SECTION_CHKSUM_LEN;
section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_W1_REDL);
section_info->dladdr =
le32_get_bits(section->w0, FWSECTION_HDR_W0_DL_ADDR) & 0x1fffffff;
section_info->addr = bin;
- bin += section_info->len;
+
+ if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
+ section_info->mssc =
+ le32_get_bits(section->w2, FWSECTION_HDR_W2_MSSC);
+
+ ret = __parse_security_section(rtwdev, info, section_info,
+ bin, &mssc_len);
+ if (ret)
+ return ret;
+
+ if (sec->secure_boot && chip->chip_id == RTL8852B)
+ section_info->len_override = 960;
+ } else {
+ section_info->mssc = 0;
+ mssc_len = 0;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d addr=%tx\n",
+ i, section_info->type, section_info->len,
+ section_info->mssc, mssc_len, bin - fw);
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ " ignore=%d key_addr=%p (0x%tx) key_len=%d key_idx=%d\n",
+ section_info->ignore, section_info->key_addr,
+ section_info->key_addr ?
+ section_info->key_addr - section_info->addr : 0,
+ section_info->key_len, section_info->key_idx);
+
+ bin += section_info->len + mssc_len;
section_info++;
}
- if (fw_end != bin + mssc_len) {
+ if (fw_end != bin) {
rtw89_err(rtwdev, "[ERR]fw bin size\n");
return -EINVAL;
}
@@ -235,7 +265,6 @@ static int __get_mssc_key_idx(struct rtw89_dev *rtwdev,
static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
struct rtw89_fw_bin_info *info,
struct rtw89_fw_hdr_section_info *section_info,
- const struct rtw89_fw_hdr_section_v1 *section,
const void *content,
u32 *mssc_len)
{
@@ -318,18 +347,15 @@ ignore:
static int __parse_security_section(struct rtw89_dev *rtwdev,
struct rtw89_fw_bin_info *info,
struct rtw89_fw_hdr_section_info *section_info,
- const struct rtw89_fw_hdr_section_v1 *section,
const void *content,
u32 *mssc_len)
{
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
int ret;
- section_info->mssc =
- le32_get_bits(section->w2, FWSECTION_HDR_V1_W2_MSSC);
-
- if (section_info->mssc == FORMATTED_MSSC) {
+ if ((section_info->mssc & FORMATTED_MSSC_MASK) == FORMATTED_MSSC) {
ret = __parse_formatted_mssc(rtwdev, info, section_info,
- section, content, mssc_len);
+ content, mssc_len);
if (ret)
return -EINVAL;
} else {
@@ -337,6 +363,14 @@ static int __parse_security_section(struct rtw89_dev *rtwdev,
if (info->dsp_checksum)
*mssc_len += section_info->mssc * FWDL_SECURITY_CHKSUM_LEN;
+ if (sec->secure_boot) {
+ if (sec->mss_idx >= section_info->mssc)
+ return -EFAULT;
+ section_info->key_addr = content + section_info->len +
+ sec->mss_idx * FWDL_SECURITY_SIGLEN;
+ section_info->key_len = FWDL_SECURITY_SIGLEN;
+ }
+
info->secure_section_exist = true;
}
@@ -361,6 +395,7 @@ static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
info->dsp_checksum = le32_get_bits(fw_hdr->w6, FW_HDR_V1_W6_DSP_CHKSUM);
base_hdr_len = struct_size(fw_hdr, sections, info->section_num);
info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_DYN_HDR);
+ info->idmem_share_mode = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_IDMEM_SHARE_MODE);
if (info->dynamic_hdr_en) {
info->hdr_len = le32_get_bits(fw_hdr->w5, FW_HDR_V1_W5_HDR_SIZE);
@@ -394,8 +429,11 @@ static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
section_info->addr = bin;
if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
+ section_info->mssc =
+ le32_get_bits(section->w2, FWSECTION_HDR_V1_W2_MSSC);
+
ret = __parse_security_section(rtwdev, info, section_info,
- section, bin, &mssc_len);
+ bin, &mssc_len);
if (ret)
return ret;
} else {
@@ -665,11 +703,13 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER),
+ __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 37, 0, NO_WOW_CPU_IO_RX),
__CFG_FW_FEAT(RTL8852A, lt, 0, 13, 38, 0, NO_PACKET_DROP),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, NO_LPS_PG),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD),
+ __CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER),
@@ -687,6 +727,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0),
+ __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0),
};
static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
@@ -1152,9 +1193,24 @@ static u32 __rtw89_fw_download_tweak_hdr_v0(struct rtw89_dev *rtwdev,
struct rtw89_fw_bin_info *info,
struct rtw89_fw_hdr *fw_hdr)
{
+ struct rtw89_fw_hdr_section_info *section_info;
+ struct rtw89_fw_hdr_section *section;
+ int i;
+
le32p_replace_bits(&fw_hdr->w7, FWDL_SECTION_PER_PKT_LEN,
FW_HDR_W7_PART_SIZE);
+ for (i = 0; i < info->section_num; i++) {
+ section_info = &info->section_info[i];
+
+ if (!section_info->len_override)
+ continue;
+
+ section = &fw_hdr->sections[i];
+ le32p_replace_bits(&section->w1, section_info->len_override,
+ FWSECTION_HDR_W1_SEC_SIZE);
+ }
+
return 0;
}
@@ -1283,10 +1339,20 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev,
if (info->ignore)
return 0;
+ if (info->len_override) {
+ if (info->len_override > info->len)
+ rtw89_warn(rtwdev, "override length %u larger than original %u\n",
+ info->len_override, info->len);
+ else
+ residue_len = info->len_override;
+ }
+
if (info->key_addr && info->key_len) {
- if (info->len > FWDL_SECTION_PER_PKT_LEN || info->len < info->key_len)
- rtw89_warn(rtwdev, "ignore to copy key data because of len %d, %d, %d\n",
- info->len, FWDL_SECTION_PER_PKT_LEN, info->key_len);
+ if (residue_len > FWDL_SECTION_PER_PKT_LEN || info->len < info->key_len)
+ rtw89_warn(rtwdev,
+ "ignore to copy key data because of len %d, %d, %d, %d\n",
+ info->len, FWDL_SECTION_PER_PKT_LEN,
+ info->key_len, residue_len);
else
copy_key = true;
}
@@ -1422,6 +1488,8 @@ static int rtw89_fw_download_suit(struct rtw89_dev *rtwdev,
return ret;
}
+ rtw89_fwdl_secure_idmem_share_mode(rtwdev, info.idmem_share_mode);
+
if (rtwdev->chip->chip_id == RTL8922A &&
(fw_suit->type == RTW89_FW_NORMAL || fw_suit->type == RTW89_FW_WOWLAN))
rtw89_write32(rtwdev, R_BE_SECURE_BOOT_MALLOC_INFO, 0x20248000);
@@ -1741,8 +1809,8 @@ plain_log:
}
#define H2C_CAM_LEN 60
-int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta, const u8 *scan_mac_addr)
+int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr)
{
struct sk_buff *skb;
int ret;
@@ -1753,8 +1821,9 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
return -ENOMEM;
}
skb_put(skb, H2C_CAM_LEN);
- rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif, rtwsta, scan_mac_addr, skb->data);
- rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif, rtwsta, skb->data);
+ rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, scan_mac_addr,
+ skb->data);
+ rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, skb->data);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
@@ -1776,8 +1845,8 @@ fail:
}
int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
struct rtw89_h2c_dctlinfo_ud_v1 *h2c;
u32 len = sizeof(*h2c);
@@ -1792,7 +1861,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
skb_put(skb, len);
h2c = (struct rtw89_h2c_dctlinfo_ud_v1 *)skb->data;
- rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif, rtwsta, h2c);
+ rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif_link, rtwsta_link, h2c);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
@@ -1815,8 +1884,8 @@ fail:
EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1);
int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
struct rtw89_h2c_dctlinfo_ud_v2 *h2c;
u32 len = sizeof(*h2c);
@@ -1831,7 +1900,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev,
skb_put(skb, len);
h2c = (struct rtw89_h2c_dctlinfo_ud_v2 *)skb->data;
- rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif, rtwsta, h2c);
+ rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif_link, rtwsta_link, h2c);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
@@ -1854,10 +1923,10 @@ fail:
EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2);
int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
struct rtw89_h2c_dctlinfo_ud_v2 *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
@@ -1908,21 +1977,24 @@ fail:
}
EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2);
-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
bool valid, struct ieee80211_ampdu_params *params)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_h2c_ba_cam *h2c;
- u8 macid = rtwsta->mac_id;
+ u8 macid = rtwsta_link->mac_id;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
u8 entry_idx;
int ret;
ret = valid ?
- rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) :
- rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx);
+ rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid,
+ &entry_idx) :
+ rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid,
+ &entry_idx);
if (ret) {
/* it still works even if we don't have static BA CAM, because
* hardware can create dynamic BA CAM automatically.
@@ -1960,7 +2032,8 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
if (chip->bacam_ver == RTW89_BACAM_V0_EXT) {
h2c->w1 |= le32_encode_bits(1, RTW89_H2C_BA_CAM_W1_STD_EN) |
- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BA_CAM_W1_BAND);
+ le32_encode_bits(rtwvif_link->mac_idx,
+ RTW89_H2C_BA_CAM_W1_BAND);
}
end:
@@ -2039,13 +2112,14 @@ void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev)
}
}
-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
bool valid, struct ieee80211_ampdu_params *params)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_h2c_ba_cam_v1 *h2c;
- u8 macid = rtwsta->mac_id;
+ u8 macid = rtwsta_link->mac_id;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
u8 entry_idx;
@@ -2053,8 +2127,10 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
int ret;
ret = valid ?
- rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) :
- rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx);
+ rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid,
+ &entry_idx) :
+ rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid,
+ &entry_idx);
if (ret) {
/* it still works even if we don't have static BA CAM, because
* hardware can create dynamic BA CAM automatically.
@@ -2092,7 +2168,8 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
entry_idx += chip->bacam_dynamic_num; /* std entry right after dynamic ones */
h2c->w1 = le32_encode_bits(entry_idx, RTW89_H2C_BA_CAM_V1_W1_ENTRY_IDX_MASK) |
le32_encode_bits(1, RTW89_H2C_BA_CAM_V1_W1_STD_ENTRY_EN) |
- le32_encode_bits(!!rtwvif->mac_idx, RTW89_H2C_BA_CAM_V1_W1_BAND_SEL);
+ le32_encode_bits(!!rtwvif_link->mac_idx,
+ RTW89_H2C_BA_CAM_V1_W1_BAND_SEL);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
@@ -2197,15 +2274,14 @@ fail:
}
static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
static const u8 gtkbody[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88,
0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03};
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_eapol_2_of_2 *eapol_pkt;
+ struct ieee80211_bss_conf *bss_conf;
struct ieee80211_hdr_3addr *hdr;
struct sk_buff *skb;
u8 key_des_ver;
@@ -2227,10 +2303,17 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_FCTL_TODS |
IEEE80211_FCTL_PROTECTED);
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+
ether_addr_copy(hdr->addr1, bss_conf->bssid);
- ether_addr_copy(hdr->addr2, vif->addr);
+ ether_addr_copy(hdr->addr2, bss_conf->addr);
ether_addr_copy(hdr->addr3, bss_conf->bssid);
+ rcu_read_unlock();
+
skb_put_zero(skb, sec_hdr_len);
eapol_pkt = skb_put_zero(skb, sizeof(*eapol_pkt));
@@ -2241,11 +2324,10 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
}
static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
+ struct ieee80211_bss_conf *bss_conf;
struct ieee80211_hdr_3addr *hdr;
struct rtw89_sa_query *sa_query;
struct sk_buff *skb;
@@ -2258,10 +2340,17 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION |
IEEE80211_FCTL_PROTECTED);
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+
ether_addr_copy(hdr->addr1, bss_conf->bssid);
- ether_addr_copy(hdr->addr2, vif->addr);
+ ether_addr_copy(hdr->addr2, bss_conf->addr);
ether_addr_copy(hdr->addr3, bss_conf->bssid);
+ rcu_read_unlock();
+
skb_put_zero(skb, sec_hdr_len);
sa_query = skb_put_zero(skb, sizeof(*sa_query));
@@ -2272,8 +2361,9 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev,
}
static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct ieee80211_hdr_3addr *hdr;
@@ -2295,9 +2385,9 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS);
hdr->frame_control = fc;
- ether_addr_copy(hdr->addr1, rtwvif->bssid);
- ether_addr_copy(hdr->addr2, rtwvif->mac_addr);
- ether_addr_copy(hdr->addr3, rtwvif->bssid);
+ ether_addr_copy(hdr->addr1, rtwvif_link->bssid);
+ ether_addr_copy(hdr->addr2, rtwvif_link->mac_addr);
+ ether_addr_copy(hdr->addr3, rtwvif_link->bssid);
skb_put_zero(skb, sec_hdr_len);
@@ -2312,18 +2402,18 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
arp_hdr->ar_pln = 4;
arp_hdr->ar_op = htons(ARPOP_REPLY);
- ether_addr_copy(arp_skb->sender_hw, rtwvif->mac_addr);
+ ether_addr_copy(arp_skb->sender_hw, rtwvif_link->mac_addr);
arp_skb->sender_ip = rtwvif->ip_addr;
return skb;
}
static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
enum rtw89_fw_pkt_ofld_type type,
u8 *id)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_pktofld_info *info;
struct sk_buff *skb;
int ret;
@@ -2346,13 +2436,13 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true);
break;
case RTW89_PKT_OFLD_TYPE_EAPOL_KEY:
- skb = rtw89_eapol_get(rtwdev, rtwvif);
+ skb = rtw89_eapol_get(rtwdev, rtwvif_link);
break;
case RTW89_PKT_OFLD_TYPE_SA_QUERY:
- skb = rtw89_sa_query_get(rtwdev, rtwvif);
+ skb = rtw89_sa_query_get(rtwdev, rtwvif_link);
break;
case RTW89_PKT_OFLD_TYPE_ARP_RSP:
- skb = rtw89_arp_response_get(rtwdev, rtwvif);
+ skb = rtw89_arp_response_get(rtwdev, rtwvif_link);
break;
default:
goto err;
@@ -2367,7 +2457,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
if (ret)
goto err;
- list_add_tail(&info->list, &rtwvif->general_pkt_list);
+ list_add_tail(&info->list, &rtwvif_link->general_pkt_list);
*id = info->id;
return 0;
@@ -2377,9 +2467,10 @@ err:
}
void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool notify_fw)
+ struct rtw89_vif_link *rtwvif_link,
+ bool notify_fw)
{
- struct list_head *pkt_list = &rtwvif->general_pkt_list;
+ struct list_head *pkt_list = &rtwvif_link->general_pkt_list;
struct rtw89_pktofld_info *info, *tmp;
list_for_each_entry_safe(info, tmp, pkt_list, list) {
@@ -2394,16 +2485,20 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, notify_fw);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link,
+ notify_fw);
}
#define H2C_GENERAL_PKT_LEN 6
#define H2C_GENERAL_PKT_ID_UND 0xff
int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, u8 macid)
+ struct rtw89_vif_link *rtwvif_link, u8 macid)
{
u8 pkt_id_ps_poll = H2C_GENERAL_PKT_ID_UND;
u8 pkt_id_null = H2C_GENERAL_PKT_ID_UND;
@@ -2411,11 +2506,11 @@ int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev,
struct sk_buff *skb;
int ret;
- rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link,
RTW89_PKT_OFLD_TYPE_PS_POLL, &pkt_id_ps_poll);
- rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link,
RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id_null);
- rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link,
RTW89_PKT_OFLD_TYPE_QOS_NULL, &pkt_id_qos_null);
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_GENERAL_PKT_LEN);
@@ -2478,7 +2573,7 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
H2C_CL_MAC_PS,
- H2C_FUNC_MAC_LPS_PARM, 0, 1,
+ H2C_FUNC_MAC_LPS_PARM, 0, !lps_param->psmode,
H2C_LPS_PARM_LEN);
ret = rtw89_h2c_tx(rtwdev, skb, false);
@@ -2494,10 +2589,10 @@ fail:
return ret;
}
-int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_h2c_lps_ch_info *h2c;
u32 len = sizeof(*h2c);
@@ -2546,13 +2641,14 @@ fail:
}
#define H2C_P2P_ACT_LEN 20
-int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf,
struct ieee80211_p2p_noa_desc *desc,
u8 act, u8 noa_id)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- bool p2p_type_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
- u8 ctwindow_oppps = vif->bss_conf.p2p_noa_attr.oppps_ctwindow;
+ bool p2p_type_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
+ u8 ctwindow_oppps = bss_conf->p2p_noa_attr.oppps_ctwindow;
struct sk_buff *skb;
u8 *cmd;
int ret;
@@ -2565,7 +2661,7 @@ int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
skb_put(skb, H2C_P2P_ACT_LEN);
cmd = skb->data;
- RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif->mac_id);
+ RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif_link->mac_id);
RTW89_SET_FWCMD_P2P_P2PID(cmd, 0);
RTW89_SET_FWCMD_P2P_NOAID(cmd, noa_id);
RTW89_SET_FWCMD_P2P_ACT(cmd, act);
@@ -2622,11 +2718,11 @@ static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev,
#define H2C_CMC_TBL_LEN 68
int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- u8 macid = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+ u8 macid = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
struct sk_buff *skb;
int ret;
@@ -2648,7 +2744,7 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
}
SET_CMC_TBL_DOPPLER_CTRL(skb->data, 0);
SET_CMC_TBL_TXPWR_TOLERENCE(skb->data, 0);
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
SET_CMC_TBL_DATA_DCM(skb->data, 0);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
@@ -2671,10 +2767,10 @@ fail:
EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl);
int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
@@ -2755,24 +2851,25 @@ fail:
EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7);
static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta, u8 *pads)
+ struct ieee80211_link_sta *link_sta,
+ u8 *pads)
{
bool ppe_th;
u8 ppe16, ppe8;
- u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
- u8 ppe_thres_hdr = sta->deflink.he_cap.ppe_thres[0];
+ u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1;
+ u8 ppe_thres_hdr = link_sta->he_cap.ppe_thres[0];
u8 ru_bitmap;
u8 n, idx, sh;
u16 ppe;
int i;
ppe_th = FIELD_GET(IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
- sta->deflink.he_cap.he_cap_elem.phy_cap_info[6]);
+ link_sta->he_cap.he_cap_elem.phy_cap_info[6]);
if (!ppe_th) {
u8 pad;
pad = FIELD_GET(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK,
- sta->deflink.he_cap.he_cap_elem.phy_cap_info[9]);
+ link_sta->he_cap.he_cap_elem.phy_cap_info[9]);
for (i = 0; i < RTW89_PPE_BW_NUM; i++)
pads[i] = pad;
@@ -2794,7 +2891,7 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev,
sh = n & 7;
n += IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2;
- ppe = le16_to_cpu(*((__le16 *)&sta->deflink.he_cap.ppe_thres[idx]));
+ ppe = le16_to_cpu(*((__le16 *)&link_sta->he_cap.ppe_thres[idx]));
ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
sh += IEEE80211_PPE_THRES_INFO_PPET_SIZE;
ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
@@ -2809,23 +2906,35 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev,
}
int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
const struct rtw89_chip_info *chip = rtwdev->chip;
- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
+ struct ieee80211_link_sta *link_sta;
struct sk_buff *skb;
u8 pads[RTW89_PPE_BW_NUM];
- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
u16 lowest_rate;
int ret;
memset(pads, 0, sizeof(pads));
- if (sta && sta->deflink.he_cap.has_he)
- __get_sta_he_pkt_padding(rtwdev, sta, pads);
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
+ return -ENOMEM;
+ }
+
+ rcu_read_lock();
+
+ if (rtwsta_link)
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+
+ if (rtwsta_link && link_sta->he_cap.has_he)
+ __get_sta_he_pkt_padding(rtwdev, link_sta, pads);
if (vif->p2p)
lowest_rate = RTW89_HW_RATE_OFDM6;
@@ -2834,11 +2943,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
else
lowest_rate = RTW89_HW_RATE_OFDM6;
- skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
- if (!skb) {
- rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
- return -ENOMEM;
- }
skb_put(skb, H2C_CMC_TBL_LEN);
SET_CTRL_INFO_MACID(skb->data, mac_id);
SET_CTRL_INFO_OPERATION(skb->data, 1);
@@ -2851,7 +2955,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
SET_CMC_TBL_ULDL(skb->data, 1);
else
SET_CMC_TBL_ULDL(skb->data, 0);
- SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif->port);
+ SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif_link->port);
if (chip->h2c_cctl_func_id == H2C_FUNC_MAC_CCTLINFO_UD_V1) {
SET_CMC_TBL_NOMINAL_PKT_PADDING_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_20]);
SET_CMC_TBL_NOMINAL_PKT_PADDING40_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_40]);
@@ -2863,12 +2967,14 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
SET_CMC_TBL_NOMINAL_PKT_PADDING80(skb->data, pads[RTW89_CHANNEL_WIDTH_80]);
SET_CMC_TBL_NOMINAL_PKT_PADDING160(skb->data, pads[RTW89_CHANNEL_WIDTH_160]);
}
- if (sta)
+ if (rtwsta_link)
SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(skb->data,
- sta->deflink.he_cap.has_he);
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
+ link_sta->he_cap.has_he);
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
SET_CMC_TBL_DATA_DCM(skb->data, 0);
+ rcu_read_unlock();
+
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
chip->h2c_cctl_func_id, 0, 1,
@@ -2889,9 +2995,10 @@ fail:
EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl);
static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta, u8 *pads)
+ struct ieee80211_link_sta *link_sta,
+ u8 *pads)
{
- u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
+ u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1;
u16 ppe_thres_hdr;
u8 ppe16, ppe8;
u8 n, idx, sh;
@@ -2900,12 +3007,12 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev,
u16 ppe;
int i;
- ppe_th = !!u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5],
+ ppe_th = !!u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5],
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT);
if (!ppe_th) {
u8 pad;
- pad = u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5],
+ pad = u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5],
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK);
for (i = 0; i < RTW89_PPE_BW_NUM; i++)
@@ -2914,7 +3021,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev,
return;
}
- ppe_thres_hdr = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres);
+ ppe_thres_hdr = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres);
ru_bitmap = u16_get_bits(ppe_thres_hdr,
IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
n = hweight8(ru_bitmap);
@@ -2931,7 +3038,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev,
sh = n & 7;
n += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
- ppe = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres + idx);
+ ppe = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres + idx);
ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
sh += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE;
ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
@@ -2946,14 +3053,15 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev,
}
int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx);
- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
+ struct ieee80211_bss_conf *bss_conf;
+ struct ieee80211_link_sta *link_sta;
u8 pads[RTW89_PPE_BW_NUM];
u32 len = sizeof(*h2c);
struct sk_buff *skb;
@@ -2961,11 +3069,24 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
int ret;
memset(pads, 0, sizeof(pads));
- if (sta) {
- if (sta->deflink.eht_cap.has_eht)
- __get_sta_eht_pkt_padding(rtwdev, sta, pads);
- else if (sta->deflink.he_cap.has_he)
- __get_sta_he_pkt_padding(rtwdev, sta, pads);
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n");
+ return -ENOMEM;
+ }
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+
+ if (rtwsta_link) {
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+
+ if (link_sta->eht_cap.has_eht)
+ __get_sta_eht_pkt_padding(rtwdev, link_sta, pads);
+ else if (link_sta->he_cap.has_he)
+ __get_sta_he_pkt_padding(rtwdev, link_sta, pads);
}
if (vif->p2p)
@@ -2975,11 +3096,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
else
lowest_rate = RTW89_HW_RATE_OFDM6;
- skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
- if (!skb) {
- rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n");
- return -ENOMEM;
- }
skb_put(skb, len);
h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data;
@@ -3000,16 +3116,16 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
h2c->w3 = le32_encode_bits(0, CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL);
h2c->m3 = cpu_to_le32(CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL);
- h2c->w4 = le32_encode_bits(rtwvif->port, CCTLINFO_G7_W4_MULTI_PORT_ID);
+ h2c->w4 = le32_encode_bits(rtwvif_link->port, CCTLINFO_G7_W4_MULTI_PORT_ID);
h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_MULTI_PORT_ID);
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) {
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) {
h2c->w4 |= le32_encode_bits(0, CCTLINFO_G7_W4_DATA_DCM);
h2c->m4 |= cpu_to_le32(CCTLINFO_G7_W4_DATA_DCM);
}
- if (vif->bss_conf.eht_support) {
- u16 punct = vif->bss_conf.chanreq.oper.punctured;
+ if (bss_conf->eht_support) {
+ u16 punct = bss_conf->chanreq.oper.punctured;
h2c->w4 |= le32_encode_bits(~punct,
CCTLINFO_G7_W4_ACT_SUBCH_CBW);
@@ -3036,12 +3152,14 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
CCTLINFO_G7_W6_ULDL);
h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL);
- if (sta) {
- h2c->w8 = le32_encode_bits(sta->deflink.he_cap.has_he,
+ if (rtwsta_link) {
+ h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he,
CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT);
h2c->m8 = cpu_to_le32(CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT);
}
+ rcu_read_unlock();
+
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1,
@@ -3062,10 +3180,10 @@ fail:
EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7);
int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = rtwsta_link->rtwsta;
struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
@@ -3102,7 +3220,7 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
else if (agg_num > 0x200 && agg_num <= 0x400)
ba_bmap = 5;
- h2c->c0 = le32_encode_bits(rtwsta->mac_id, CCTLINFO_G7_C0_MACID) |
+ h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, CCTLINFO_G7_C0_MACID) |
le32_encode_bits(1, CCTLINFO_G7_C0_OP);
h2c->w3 = le32_encode_bits(ba_bmap, CCTLINFO_G7_W3_BA_BMAP);
@@ -3128,7 +3246,7 @@ fail:
EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7);
int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta)
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
@@ -3140,15 +3258,15 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
return -ENOMEM;
}
skb_put(skb, H2C_CMC_TBL_LEN);
- SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id);
+ SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id);
SET_CTRL_INFO_OPERATION(skb->data, 1);
- if (rtwsta->cctl_tx_time) {
+ if (rtwsta_link->cctl_tx_time) {
SET_CMC_TBL_AMPDU_TIME_SEL(skb->data, 1);
- SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta->ampdu_max_time);
+ SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta_link->ampdu_max_time);
}
- if (rtwsta->cctl_tx_retry_limit) {
+ if (rtwsta_link->cctl_tx_retry_limit) {
SET_CMC_TBL_DATA_TXCNT_LMT_SEL(skb->data, 1);
- SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta->data_tx_cnt_lmt);
+ SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta_link->data_tx_cnt_lmt);
}
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
@@ -3170,7 +3288,7 @@ fail:
}
int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta)
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
@@ -3185,7 +3303,7 @@ int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
return -ENOMEM;
}
skb_put(skb, H2C_CMC_TBL_LEN);
- SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id);
+ SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id);
SET_CTRL_INFO_OPERATION(skb->data, 1);
__rtw89_fw_h2c_set_tx_path(rtwdev, skb);
@@ -3209,11 +3327,11 @@ fail:
}
int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ rtwvif_link->chanctx_idx);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_h2c_bcn_upd *h2c;
struct sk_buff *skb_beacon;
struct ieee80211_hdr *hdr;
@@ -3240,7 +3358,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
return -ENOMEM;
}
- noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data);
+ noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data);
if (noa_len &&
(noa_len <= skb_tailroom(skb_beacon) ||
pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) {
@@ -3260,11 +3378,11 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
skb_put(skb, len);
h2c = (struct rtw89_h2c_bcn_upd *)skb->data;
- h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_W0_PORT) |
+ h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_W0_PORT) |
le32_encode_bits(0, RTW89_H2C_BCN_UPD_W0_MBSSID) |
- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) |
+ le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) |
le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_W0_GRP_IE_OFST);
- h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) |
+ h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) |
le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_W1_SSN_SEL) |
le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_W1_SSN_MODE) |
le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_W1_RATE);
@@ -3289,10 +3407,10 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon);
int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx);
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_h2c_bcn_upd_be *h2c;
struct sk_buff *skb_beacon;
struct ieee80211_hdr *hdr;
@@ -3319,7 +3437,7 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev,
return -ENOMEM;
}
- noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data);
+ noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data);
if (noa_len &&
(noa_len <= skb_tailroom(skb_beacon) ||
pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) {
@@ -3339,11 +3457,11 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev,
skb_put(skb, len);
h2c = (struct rtw89_h2c_bcn_upd_be *)skb->data;
- h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) |
+ h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) |
le32_encode_bits(0, RTW89_H2C_BCN_UPD_BE_W0_MBSSID) |
- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) |
+ le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) |
le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_BE_W0_GRP_IE_OFST);
- h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) |
+ h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) |
le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_BE_W1_SSN_SEL) |
le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_BE_W1_SSN_MODE) |
le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_BE_W1_RATE);
@@ -3373,22 +3491,22 @@ EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be);
#define H2C_ROLE_MAINTAIN_LEN 4
int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
enum rtw89_upd_mode upd_mode)
{
struct sk_buff *skb;
- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
u8 self_role;
int ret;
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) {
- if (rtwsta)
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) {
+ if (rtwsta_link)
self_role = RTW89_SELF_ROLE_AP_CLIENT;
else
- self_role = rtwvif->self_role;
+ self_role = rtwvif_link->self_role;
} else {
- self_role = rtwvif->self_role;
+ self_role = rtwvif_link->self_role;
}
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_ROLE_MAINTAIN_LEN);
@@ -3400,7 +3518,7 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
SET_FWROLE_MAINTAIN_MACID(skb->data, mac_id);
SET_FWROLE_MAINTAIN_SELF_ROLE(skb->data, self_role);
SET_FWROLE_MAINTAIN_UPD_MODE(skb->data, upd_mode);
- SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif->wifi_role);
+ SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif_link->wifi_role);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT,
@@ -3421,39 +3539,53 @@ fail:
}
static enum rtw89_fw_sta_type
-rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta);
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_bss_conf *bss_conf;
+ struct ieee80211_link_sta *link_sta;
+ enum rtw89_fw_sta_type type;
- if (!sta)
+ rcu_read_lock();
+
+ if (!rtwsta_link)
goto by_vif;
- if (sta->deflink.eht_cap.has_eht)
- return RTW89_FW_BE_STA;
- else if (sta->deflink.he_cap.has_he)
- return RTW89_FW_AX_STA;
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+
+ if (link_sta->eht_cap.has_eht)
+ type = RTW89_FW_BE_STA;
+ else if (link_sta->he_cap.has_he)
+ type = RTW89_FW_AX_STA;
else
- return RTW89_FW_N_AC_STA;
+ type = RTW89_FW_N_AC_STA;
+
+ goto out;
by_vif:
- if (vif->bss_conf.eht_support)
- return RTW89_FW_BE_STA;
- else if (vif->bss_conf.he_support)
- return RTW89_FW_AX_STA;
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+
+ if (bss_conf->eht_support)
+ type = RTW89_FW_BE_STA;
+ else if (bss_conf->he_support)
+ type = RTW89_FW_AX_STA;
else
- return RTW89_FW_N_AC_STA;
+ type = RTW89_FW_N_AC_STA;
+
+out:
+ rcu_read_unlock();
+
+ return type;
}
-int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta, bool dis_conn)
+int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link, bool dis_conn)
{
struct sk_buff *skb;
- u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
- u8 self_role = rtwvif->self_role;
+ u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
+ u8 self_role = rtwvif_link->self_role;
enum rtw89_fw_sta_type sta_type;
- u8 net_type = rtwvif->net_type;
+ u8 net_type = rtwvif_link->net_type;
struct rtw89_h2c_join_v1 *h2c_v1;
struct rtw89_h2c_join *h2c;
u32 len = sizeof(*h2c);
@@ -3465,7 +3597,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
format_v1 = true;
}
- if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta) {
+ if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta_link) {
self_role = RTW89_SELF_ROLE_AP_CLIENT;
net_type = dis_conn ? RTW89_NET_TYPE_NO_LINK : net_type;
}
@@ -3480,16 +3612,17 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
h2c->w0 = le32_encode_bits(mac_id, RTW89_H2C_JOININFO_W0_MACID) |
le32_encode_bits(dis_conn, RTW89_H2C_JOININFO_W0_OP) |
- le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_JOININFO_W0_BAND) |
- le32_encode_bits(rtwvif->wmm, RTW89_H2C_JOININFO_W0_WMM) |
- le32_encode_bits(rtwvif->trigger, RTW89_H2C_JOININFO_W0_TGR) |
+ le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_JOININFO_W0_BAND) |
+ le32_encode_bits(rtwvif_link->wmm, RTW89_H2C_JOININFO_W0_WMM) |
+ le32_encode_bits(rtwvif_link->trigger, RTW89_H2C_JOININFO_W0_TGR) |
le32_encode_bits(0, RTW89_H2C_JOININFO_W0_ISHESTA) |
le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DLBW) |
le32_encode_bits(0, RTW89_H2C_JOININFO_W0_TF_MAC_PAD) |
le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DL_T_PE) |
- le32_encode_bits(rtwvif->port, RTW89_H2C_JOININFO_W0_PORT_ID) |
+ le32_encode_bits(rtwvif_link->port, RTW89_H2C_JOININFO_W0_PORT_ID) |
le32_encode_bits(net_type, RTW89_H2C_JOININFO_W0_NET_TYPE) |
- le32_encode_bits(rtwvif->wifi_role, RTW89_H2C_JOININFO_W0_WIFI_ROLE) |
+ le32_encode_bits(rtwvif_link->wifi_role,
+ RTW89_H2C_JOININFO_W0_WIFI_ROLE) |
le32_encode_bits(self_role, RTW89_H2C_JOININFO_W0_SELF_ROLE);
if (!format_v1)
@@ -3497,7 +3630,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
h2c_v1 = (struct rtw89_h2c_join_v1 *)skb->data;
- sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif, rtwsta);
+ sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif_link, rtwsta_link);
h2c_v1->w1 = le32_encode_bits(sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE);
h2c_v1->w2 = 0;
@@ -3618,7 +3751,7 @@ fail:
}
#define H2C_EDCA_LEN 12
-int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u8 ac, u32 val)
{
struct sk_buff *skb;
@@ -3631,7 +3764,7 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
}
skb_put(skb, H2C_EDCA_LEN);
RTW89_SET_EDCA_SEL(skb->data, 0);
- RTW89_SET_EDCA_BAND(skb->data, rtwvif->mac_idx);
+ RTW89_SET_EDCA_BAND(skb->data, rtwvif_link->mac_idx);
RTW89_SET_EDCA_WMM(skb->data, 0);
RTW89_SET_EDCA_AC(skb->data, ac);
RTW89_SET_EDCA_PARAM(skb->data, val);
@@ -3655,7 +3788,8 @@ fail:
}
#define H2C_TSF32_TOGL_LEN 4
-int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool en)
{
struct sk_buff *skb;
@@ -3671,9 +3805,9 @@ int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
skb_put(skb, H2C_TSF32_TOGL_LEN);
cmd = skb->data;
- RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif->mac_idx);
+ RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif_link->mac_idx);
RTW89_SET_FWCMD_TSF32_TOGL_EN(cmd, en);
- RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif->port);
+ RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif_link->port);
RTW89_SET_FWCMD_TSF32_TOGL_EARLY(cmd, early_us);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
@@ -3726,12 +3860,57 @@ fail:
return ret;
}
+int rtw89_fw_h2c_tx_duty(struct rtw89_dev *rtwdev, u8 lv)
+{
+ struct rtw89_h2c_tx_duty *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ u16 pause, active;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c tx duty\n");
+ return -ENOMEM;
+ }
+
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_tx_duty *)skb->data;
+
+ static_assert(RTW89_THERMAL_PROT_LV_MAX * RTW89_THERMAL_PROT_STEP < 100);
+
+ if (lv == 0 || lv > RTW89_THERMAL_PROT_LV_MAX) {
+ h2c->w1 = le32_encode_bits(1, RTW89_H2C_TX_DUTY_W1_STOP);
+ } else {
+ active = 100 - lv * RTW89_THERMAL_PROT_STEP;
+ pause = 100 - active;
+
+ h2c->w0 = le32_encode_bits(pause, RTW89_H2C_TX_DUTY_W0_PAUSE_INTVL_MASK) |
+ le32_encode_bits(active, RTW89_H2C_TX_DUTY_W0_TX_INTVL_MASK);
+ }
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
+ H2C_FUNC_TX_DUTY, 0, 0, len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
+ struct rtw89_vif_link *rtwvif_link,
bool connect)
{
- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
- struct ieee80211_bss_conf *bss_conf = vif ? &vif->bss_conf : NULL;
+ struct ieee80211_bss_conf *bss_conf;
s32 thold = RTW89_DEFAULT_CQM_THOLD;
u32 hyst = RTW89_DEFAULT_CQM_HYST;
struct rtw89_h2c_bcnfltr *h2c;
@@ -3742,9 +3921,20 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
return -EINVAL;
- if (!rtwvif || !bss_conf || rtwvif->net_type != RTW89_NET_TYPE_INFRA)
+ if (!rtwvif_link || rtwvif_link->net_type != RTW89_NET_TYPE_INFRA)
return -EINVAL;
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
+
+ if (bss_conf->cqm_rssi_hyst)
+ hyst = bss_conf->cqm_rssi_hyst;
+ if (bss_conf->cqm_rssi_thold)
+ thold = bss_conf->cqm_rssi_thold;
+
+ rcu_read_unlock();
+
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for h2c bcn filter\n");
@@ -3754,11 +3944,6 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
skb_put(skb, len);
h2c = (struct rtw89_h2c_bcnfltr *)skb->data;
- if (bss_conf->cqm_rssi_hyst)
- hyst = bss_conf->cqm_rssi_hyst;
- if (bss_conf->cqm_rssi_thold)
- thold = bss_conf->cqm_rssi_thold;
-
h2c->w0 = le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_RSSI) |
le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_BCN) |
le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_EN) |
@@ -3768,7 +3953,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
le32_encode_bits(hyst, RTW89_H2C_BCNFLTR_W0_RSSI_HYST) |
le32_encode_bits(thold + MAX_RSSI,
RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD) |
- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID);
+ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
@@ -3833,15 +4018,16 @@ fail:
return ret;
}
-int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_traffic_stats *stats = &rtwvif->stats;
struct rtw89_h2c_ofld *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
int ret;
- if (rtwvif->net_type != RTW89_NET_TYPE_INFRA)
+ if (rtwvif_link->net_type != RTW89_NET_TYPE_INFRA)
return -EINVAL;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
@@ -3853,7 +4039,7 @@ int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
skb_put(skb, len);
h2c = (struct rtw89_h2c_ofld *)skb->data;
- h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) |
+ h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) |
le32_encode_bits(stats->tx_throughput, RTW89_H2C_OFLD_W0_TX_TP) |
le32_encode_bits(stats->rx_throughput, RTW89_H2C_OFLD_W0_RX_TP);
@@ -4688,6 +4874,7 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
return 0;
}
+static
int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num,
struct list_head *chan_list)
{
@@ -4759,8 +4946,10 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num,
return 0;
}
+static
int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
- struct list_head *chan_list)
+ struct list_head *chan_list,
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct rtw89_h2c_chinfo_elem_be *elem;
@@ -4785,7 +4974,8 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
h2c->ch_num = ch_num;
h2c->elem_size = sizeof(*elem) / 4; /* in unit of 4 bytes */
- h2c->arg = u8_encode_bits(RTW89_PHY_0, RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK);
+ h2c->arg = u8_encode_bits(rtwvif_link->mac_idx,
+ RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK);
list_for_each_entry(ch_info, chan_list, list) {
elem = (struct rtw89_h2c_chinfo_elem_be *)skb_put(skb, sizeof(*elem));
@@ -4858,7 +5048,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
#define RTW89_SCAN_DELAY_TSF_UNIT 104800
int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *option,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
bool wowlan)
{
struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
@@ -4880,19 +5070,19 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev,
h2c = (struct rtw89_h2c_scanofld *)skb->data;
if (option->delay) {
- ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf);
+ ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
if (ret) {
rtw89_warn(rtwdev, "NLO failed to get port tsf: %d\n", ret);
scan_mode = RTW89_SCAN_IMMEDIATE;
} else {
scan_mode = RTW89_SCAN_DELAY;
- tsf += option->delay * RTW89_SCAN_DELAY_TSF_UNIT;
+ tsf += (u64)option->delay * RTW89_SCAN_DELAY_TSF_UNIT;
}
}
- h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) |
- le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) |
- le32_encode_bits(RTW89_PHY_0, RTW89_H2C_SCANOFLD_W0_BAND) |
+ h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) |
+ le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) |
+ le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_SCANOFLD_W0_BAND) |
le32_encode_bits(option->enable, RTW89_H2C_SCANOFLD_W0_OPERATION);
h2c->w1 = le32_encode_bits(true, RTW89_H2C_SCANOFLD_W1_NOTIFY_END) |
@@ -4963,9 +5153,10 @@ static void rtw89_scan_get_6g_disabled_chan(struct rtw89_dev *rtwdev,
int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *option,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
bool wowlan)
{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct cfg80211_scan_request *req = rtwvif->scan_req;
@@ -5016,8 +5207,8 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
le32_encode_bits(option->repeat, RTW89_H2C_SCANOFLD_BE_W0_REPEAT) |
le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_NOTIFY_END) |
le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_LEARN_CH) |
- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) |
- le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) |
+ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) |
+ le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) |
le32_encode_bits(option->band, RTW89_H2C_SCANOFLD_BE_W0_BAND);
h2c->w1 = le32_encode_bits(option->num_macc_role, RTW89_H2C_SCANOFLD_BE_W1_NUM_MACC_ROLE) |
@@ -5082,11 +5273,11 @@ flex_member:
for (i = 0; i < option->num_opch; i++) {
opch = ptr;
- opch->w0 = le32_encode_bits(rtwvif->mac_id,
+ opch->w0 = le32_encode_bits(rtwvif_link->mac_id,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID) |
le32_encode_bits(option->band,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_BAND) |
- le32_encode_bits(rtwvif->port,
+ le32_encode_bits(rtwvif_link->port,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_PORT) |
le32_encode_bits(RTW89_SCAN_OPMODE_INTV,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY) |
@@ -5180,7 +5371,7 @@ fail:
int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
{
- struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
struct rtw89_fw_h2c_rf_get_mccch *mccch;
struct sk_buff *skb;
int ret;
@@ -5227,7 +5418,7 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
struct rtw89_fw_h2c_rfk_pre_info_v0 *h2c_v0;
struct rtw89_fw_h2c_rfk_pre_info *h2c;
- u8 tbl_sel = rfk_mcc->table_idx;
+ u8 tbl_sel[NUM_OF_RTW89_FW_RFK_PATH];
u32 len = sizeof(*h2c);
struct sk_buff *skb;
u8 ver = U8_MAX;
@@ -5251,19 +5442,24 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
h2c->common.mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
BUILD_BUG_ON(NUM_OF_RTW89_FW_RFK_TBL > RTW89_RFK_CHS_NR);
+ BUILD_BUG_ON(ARRAY_SIZE(rfk_mcc->data) < NUM_OF_RTW89_FW_RFK_PATH);
for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) {
for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
h2c->common.dbcc.ch[path][tbl] =
- cpu_to_le32(rfk_mcc->ch[tbl]);
+ cpu_to_le32(rfk_mcc->data[path].ch[tbl]);
h2c->common.dbcc.band[path][tbl] =
- cpu_to_le32(rfk_mcc->band[tbl]);
+ cpu_to_le32(rfk_mcc->data[path].band[tbl]);
}
}
for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
- h2c->common.tbl.cur_ch[path] = cpu_to_le32(rfk_mcc->ch[tbl_sel]);
- h2c->common.tbl.cur_band[path] = cpu_to_le32(rfk_mcc->band[tbl_sel]);
+ tbl_sel[path] = rfk_mcc->data[path].table_idx;
+
+ h2c->common.tbl.cur_ch[path] =
+ cpu_to_le32(rfk_mcc->data[path].ch[tbl_sel[path]]);
+ h2c->common.tbl.cur_band[path] =
+ cpu_to_le32(rfk_mcc->data[path].band[tbl_sel[path]]);
}
h2c->common.phy_idx = cpu_to_le32(phy_idx);
@@ -5271,9 +5467,9 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
if (ver == 0) { /* RFK_PRE_NOTIFY_V0 */
h2c_v0 = (struct rtw89_fw_h2c_rfk_pre_info_v0 *)skb->data;
- h2c_v0->cur_band = cpu_to_le32(rfk_mcc->band[tbl_sel]);
- h2c_v0->cur_bw = cpu_to_le32(rfk_mcc->bw[tbl_sel]);
- h2c_v0->cur_center_ch = cpu_to_le32(rfk_mcc->ch[tbl_sel]);
+ h2c_v0->cur_band = cpu_to_le32(rfk_mcc->data[0].band[tbl_sel[0]]);
+ h2c_v0->cur_bw = cpu_to_le32(rfk_mcc->data[0].bw[tbl_sel[0]]);
+ h2c_v0->cur_center_ch = cpu_to_le32(rfk_mcc->data[0].ch[tbl_sel[0]]);
val32 = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_IQC_V1);
h2c_v0->ktbl_sel0 = cpu_to_le32(val32);
@@ -5518,30 +5714,44 @@ fail:
}
int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
- const struct rtw89_chan *chan)
+ const struct rtw89_chan *chan, bool is_chl_k)
{
+ struct rtw89_h2c_rf_rxdck_v0 *v0;
struct rtw89_h2c_rf_rxdck *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
+ int ver = -1;
int ret;
+ if (RTW89_CHK_FW_FEATURE(RFK_RXDCK_V0, &rtwdev->fw)) {
+ len = sizeof(*v0);
+ ver = 0;
+ }
+
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for h2c RF RXDCK\n");
return -ENOMEM;
}
skb_put(skb, len);
- h2c = (struct rtw89_h2c_rf_rxdck *)skb->data;
+ v0 = (struct rtw89_h2c_rf_rxdck_v0 *)skb->data;
+
+ v0->len = len;
+ v0->phy = phy_idx;
+ v0->is_afe = false;
+ v0->kpath = RF_AB;
+ v0->cur_band = chan->band_type;
+ v0->cur_bw = chan->band_width;
+ v0->cur_ch = chan->channel;
+ v0->rxdck_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK);
+
+ if (ver == 0)
+ goto hdr;
- h2c->len = len;
- h2c->phy = phy_idx;
- h2c->is_afe = false;
- h2c->kpath = RF_AB;
- h2c->cur_band = chan->band_type;
- h2c->cur_bw = chan->band_width;
- h2c->cur_ch = chan->channel;
- h2c->rxdck_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK);
+ h2c = (struct rtw89_h2c_rf_rxdck *)skb->data;
+ h2c->is_chl_k = is_chl_k;
+hdr:
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
H2C_FUNC_RFK_RXDCK_OFFLOAD, 0, 0, len);
@@ -5871,12 +6081,10 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
}
static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct cfg80211_scan_request *req,
struct rtw89_pktofld_info *info,
enum nl80211_band band, u8 ssid_idx)
{
- struct cfg80211_scan_request *req = rtwvif->scan_req;
-
if (band != NL80211_BAND_6GHZ)
return false;
@@ -5892,11 +6100,13 @@ static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev,
}
static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct sk_buff *skb, u8 ssid_idx)
{
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
+ struct cfg80211_scan_request *req = rtwvif->scan_req;
struct rtw89_pktofld_info *info;
struct sk_buff *new;
int ret = 0;
@@ -5921,8 +6131,7 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
goto out;
}
- rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif, info, band,
- ssid_idx);
+ rtw89_is_6ghz_wildcard_probe_req(rtwdev, req, info, band, ssid_idx);
ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, new);
if (ret) {
@@ -5939,22 +6148,23 @@ out:
}
static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct sk_buff *skb;
u8 num = req->n_ssids, i;
int ret;
for (i = 0; i < num; i++) {
- skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr,
+ skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr,
req->ssids[i].ssid,
req->ssids[i].ssid_len,
req->ie_len);
if (!skb)
return -ENOMEM;
- ret = rtw89_append_probe_req_ie(rtwdev, rtwvif, skb, i);
+ ret = rtw89_append_probe_req_ie(rtwdev, rtwvif_link, skb, i);
kfree_skb(skb);
if (ret)
@@ -5965,13 +6175,12 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
}
static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,
+ struct ieee80211_scan_ies *ies,
struct cfg80211_scan_request *req,
struct rtw89_mac_chinfo *ch_info)
{
- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
- struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
struct cfg80211_scan_6ghz_params *params;
struct rtw89_pktofld_info *info, *tmp;
struct ieee80211_hdr *hdr;
@@ -6000,8 +6209,11 @@ static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,
if (found)
continue;
- skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr,
+ skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr,
NULL, 0, req->ie_len);
+ if (!skb)
+ return -ENOMEM;
+
skb_put_data(skb, ies->ies[NL80211_BAND_6GHZ], ies->len[NL80211_BAND_6GHZ]);
skb_put_data(skb, ies->common_ies, ies->common_ie_len);
hdr = (struct ieee80211_hdr *)skb->data;
@@ -6090,8 +6302,9 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
struct rtw89_mac_chinfo *ch_info)
{
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+ struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
struct rtw89_pktofld_info *info;
@@ -6117,7 +6330,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
}
}
- ret = rtw89_update_6ghz_rnr_chan(rtwdev, req, ch_info);
+ ret = rtw89_update_6ghz_rnr_chan(rtwdev, ies, req, ch_info);
if (ret)
rtw89_warn(rtwdev, "RNR fails: %d\n", ret);
@@ -6155,8 +6368,10 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
ch_info->period = max_t(u8, ch_info->period,
RTW89_DFS_CHAN_TIME);
ch_info->dwell_time = RTW89_DWELL_TIME;
+ ch_info->pause_data = true;
break;
case RTW89_CHAN_ACTIVE:
+ ch_info->pause_data = true;
break;
default:
rtw89_err(rtwdev, "Channel type out of bound\n");
@@ -6207,8 +6422,8 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type,
struct rtw89_mac_chinfo_be *ch_info)
{
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct rtw89_pktofld_info *info;
u8 band, probe_count = 0, i;
@@ -6255,8 +6470,10 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type,
ch_info->period =
max_t(u8, ch_info->period, RTW89_DFS_CHAN_TIME);
ch_info->dwell_time = RTW89_DWELL_TIME;
+ ch_info->pause_data = true;
break;
case RTW89_CHAN_ACTIVE:
+ ch_info->pause_data = true;
break;
default:
rtw89_warn(rtwdev, "Channel type out of bound\n");
@@ -6265,7 +6482,7 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type,
}
int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config;
@@ -6315,8 +6532,9 @@ out:
}
int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool connected)
+ struct rtw89_vif_link *rtwvif_link, bool connected)
{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct rtw89_mac_chinfo *ch_info, *tmp;
struct ieee80211_channel *channel;
@@ -6392,7 +6610,7 @@ out:
}
int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config;
@@ -6432,7 +6650,8 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
list_add_tail(&ch_info->list, &chan_list);
}
- ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list);
+ ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list,
+ rtwvif_link);
out:
list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
@@ -6444,8 +6663,9 @@ out:
}
int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool connected)
+ struct rtw89_vif_link *rtwvif_link, bool connected)
{
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct rtw89_mac_chinfo_be *ch_info, *tmp;
struct ieee80211_channel *channel;
@@ -6491,7 +6711,8 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
}
rtwdev->scan_info.last_chan_idx = idx;
- ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list);
+ ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list,
+ rtwvif_link);
out:
list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
@@ -6503,79 +6724,88 @@ out:
}
static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool connected)
+ struct rtw89_vif_link *rtwvif_link, bool connected)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
int ret;
- ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif);
+ ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif_link);
if (ret) {
rtw89_err(rtwdev, "Update probe request failed\n");
goto out;
}
- ret = mac->add_chan_list(rtwdev, rtwvif, connected);
+ ret = mac->add_chan_list(rtwdev, rtwvif_link, connected);
out:
return ret;
}
-void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
struct ieee80211_scan_request *scan_req)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct cfg80211_scan_request *req = &scan_req->req;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
+ rtwvif_link->chanctx_idx);
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
u32 rx_fltr = rtwdev->hal.rx_fltr;
u8 mac_addr[ETH_ALEN];
+ u32 reg;
+
+ /* clone op and keep it during scan */
+ rtwdev->scan_info.op_chan = *chan;
- rtw89_get_channel(rtwdev, rtwvif, &rtwdev->scan_info.op_chan);
- rtwdev->scan_info.scanning_vif = vif;
+ rtwdev->scan_info.scanning_vif = rtwvif_link;
rtwdev->scan_info.last_chan_idx = 0;
rtwdev->scan_info.abort = false;
rtwvif->scan_ies = &scan_req->ies;
rtwvif->scan_req = req;
ieee80211_stop_queues(rtwdev->hw);
- rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, false);
+ rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false);
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
get_random_mask_addr(mac_addr, req->mac_addr,
req->mac_addr_mask);
else
- ether_addr_copy(mac_addr, vif->addr);
- rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, true);
+ ether_addr_copy(mac_addr, rtwvif_link->mac_addr);
+ rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, true);
rx_fltr &= ~B_AX_A_BCN_CHK_EN;
rx_fltr &= ~B_AX_A_BC;
rx_fltr &= ~B_AX_A_A1_MATCH;
- rtw89_write32_mask(rtwdev,
- rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
- B_AX_RX_FLTR_CFG_MASK,
- rx_fltr);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rx_fltr);
rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN);
}
-void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool aborted)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
struct cfg80211_scan_info info = {
.aborted = aborted,
};
+ struct rtw89_vif *rtwvif;
+ u32 reg;
- if (!vif)
+ if (!rtwvif_link)
return;
- rtw89_write32_mask(rtwdev,
- rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
- B_AX_RX_FLTR_CFG_MASK,
- rtwdev->hal.rx_fltr);
+ rtw89_chanctx_proceed(rtwdev);
+
+ rtwvif = rtwvif_link->rtwvif;
- rtw89_core_scan_complete(rtwdev, vif, true);
+ reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr);
+
+ rtw89_core_scan_complete(rtwdev, rtwvif_link, true);
ieee80211_scan_completed(rtwdev->hw, &info);
ieee80211_wake_queues(rtwdev->hw);
- rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, true);
+ rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true);
rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);
rtw89_release_pkt_list(rtwdev);
@@ -6584,18 +6814,17 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
scan_info->last_chan_idx = 0;
scan_info->scanning_vif = NULL;
scan_info->abort = false;
-
- rtw89_chanctx_proceed(rtwdev);
}
-void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
+void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
int ret;
scan_info->abort = true;
- ret = rtw89_hw_scan_offload(rtwdev, vif, false);
+ ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, false);
if (ret)
rtw89_warn(rtwdev, "rtw89_hw_scan_offload failed ret %d\n", ret);
@@ -6604,40 +6833,43 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
* RTW89_SCAN_END_SCAN_NOTIFY, so that ieee80211_stop() can flush scan
* work properly.
*/
- rtw89_hw_scan_complete(rtwdev, vif, true);
+ rtw89_hw_scan_complete(rtwdev, rtwvif_link, true);
}
static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
- /* This variable implies connected or during attempt to connect */
- if (!is_zero_ether_addr(rtwvif->bssid))
- return true;
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ /* This variable implies connected or during attempt to connect */
+ if (!is_zero_ether_addr(rtwvif_link->bssid))
+ return true;
+ }
}
return false;
}
-int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool enable)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct rtw89_scan_option opt = {0};
- struct rtw89_vif *rtwvif;
bool connected;
int ret = 0;
- rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
- if (!rtwvif)
+ if (!rtwvif_link)
return -EINVAL;
connected = rtw89_is_any_vif_connected_or_connecting(rtwdev);
opt.enable = enable;
opt.target_ch_mode = connected;
if (enable) {
- ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif, connected);
+ ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif_link, connected);
if (ret)
goto out;
}
@@ -6645,14 +6877,14 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) {
opt.operation = enable ? RTW89_SCAN_OP_START : RTW89_SCAN_OP_STOP;
opt.scan_mode = RTW89_SCAN_MODE_SA;
- opt.band = RTW89_PHY_0;
+ opt.band = rtwvif_link->mac_idx;
opt.num_macc_role = 0;
opt.mlo_mode = rtwdev->mlo_dbcc_mode;
opt.num_opch = connected ? 1 : 0;
opt.opch_end = connected ? 0 : RTW89_CHAN_INVALID;
}
- ret = mac->scan_offload(rtwdev, &opt, rtwvif, false);
+ ret = mac->scan_offload(rtwdev, &opt, rtwvif_link, false);
out:
return ret;
}
@@ -6758,7 +6990,7 @@ fail:
}
#define H2C_KEEP_ALIVE_LEN 4
-int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable)
{
struct sk_buff *skb;
@@ -6766,7 +6998,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
int ret;
if (enable) {
- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link,
RTW89_PKT_OFLD_TYPE_NULL_DATA,
&pkt_id);
if (ret)
@@ -6784,7 +7016,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
RTW89_SET_KEEP_ALIVE_ENABLE(skb->data, enable);
RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(skb->data, pkt_id);
RTW89_SET_KEEP_ALIVE_PERIOD(skb->data, 5);
- RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif->mac_id);
+ RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif_link->mac_id);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC,
@@ -6806,7 +7038,7 @@ fail:
return ret;
}
-int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable)
{
struct rtw89_h2c_arp_offload *h2c;
@@ -6816,7 +7048,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
int ret;
if (enable) {
- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link,
RTW89_PKT_OFLD_TYPE_ARP_RSP,
&pkt_id);
if (ret)
@@ -6834,7 +7066,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
h2c->w0 = le32_encode_bits(enable, RTW89_H2C_ARP_OFFLOAD_W0_ENABLE) |
le32_encode_bits(0, RTW89_H2C_ARP_OFFLOAD_W0_ACTION) |
- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) |
+ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) |
le32_encode_bits(pkt_id, RTW89_H2C_ARP_OFFLOAD_W0_PKT_ID);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
@@ -6859,11 +7091,11 @@ fail:
#define H2C_DISCONNECT_DETECT_LEN 8
int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool enable)
+ struct rtw89_vif_link *rtwvif_link, bool enable)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct sk_buff *skb;
- u8 macid = rtwvif->mac_id;
+ u8 macid = rtwvif_link->mac_id;
int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DISCONNECT_DETECT_LEN);
@@ -6902,7 +7134,7 @@ fail:
return ret;
}
-int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
@@ -6923,7 +7155,7 @@ int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
h2c->w0 = le32_encode_bits(enable, RTW89_H2C_NLO_W0_ENABLE) |
le32_encode_bits(enable, RTW89_H2C_NLO_W0_IGNORE_CIPHER) |
- le32_encode_bits(rtwvif->mac_id, RTW89_H2C_NLO_W0_MACID);
+ le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_NLO_W0_MACID);
if (enable) {
h2c->nlo_cnt = nd_config->n_match_sets;
@@ -6953,12 +7185,12 @@ fail:
return ret;
}
-int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_h2c_wow_global *h2c;
- u8 macid = rtwvif->mac_id;
+ u8 macid = rtwvif_link->mac_id;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
int ret;
@@ -7002,12 +7234,12 @@ fail:
#define H2C_WAKEUP_CTRL_LEN 4
int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
bool enable)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct sk_buff *skb;
- u8 macid = rtwvif->mac_id;
+ u8 macid = rtwvif_link->mac_id;
int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WAKEUP_CTRL_LEN);
@@ -7100,13 +7332,13 @@ fail:
}
int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
bool enable)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_gtk_info *gtk_info = &rtw_wow->gtk_info;
struct rtw89_h2c_wow_gtk_ofld *h2c;
- u8 macid = rtwvif->mac_id;
+ u8 macid = rtwvif_link->mac_id;
u32 len = sizeof(*h2c);
u8 pkt_id_sa_query = 0;
struct sk_buff *skb;
@@ -7128,14 +7360,14 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
if (!enable)
goto hdr;
- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link,
RTW89_PKT_OFLD_TYPE_EAPOL_KEY,
&pkt_id_eapol);
if (ret)
goto fail;
if (gtk_info->igtk_keyid) {
- ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
+ ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link,
RTW89_PKT_OFLD_TYPE_SA_QUERY,
&pkt_id_sa_query);
if (ret)
@@ -7173,7 +7405,7 @@ fail:
return ret;
}
-int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable)
{
struct rtw89_wait_info *wait = &rtwdev->mac.ps_wait;
@@ -7189,7 +7421,7 @@ int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
skb_put(skb, len);
h2c = (struct rtw89_h2c_fwips *)skb->data;
- h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_FW_IPS_W0_MACID) |
+ h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_FW_IPS_W0_MACID) |
le32_encode_bits(enable, RTW89_H2C_FW_IPS_W0_ENABLE);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index ad47e77d740b..efa63d444821 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -261,6 +261,7 @@ struct rtw89_fw_hdr_section_info {
u8 redl;
const u8 *addr;
u32 len;
+ u32 len_override;
u32 dladdr;
u32 mssc;
u8 type;
@@ -275,6 +276,7 @@ struct rtw89_fw_bin_info {
u32 hdr_len;
bool dynamic_hdr_en;
u32 dynamic_hdr_len;
+ u8 idmem_share_mode;
bool dsp_checksum;
bool secure_section_exist;
struct rtw89_fw_hdr_section_info section_info[FWDL_SECTION_MAX_NUM];
@@ -563,6 +565,7 @@ struct rtw89_fw_hdr {
#define FW_HDR_W6_SEC_NUM GENMASK(15, 8)
#define FW_HDR_W7_PART_SIZE GENMASK(15, 0)
#define FW_HDR_W7_DYN_HDR BIT(16)
+#define FW_HDR_W7_IDMEM_SHARE_MODE GENMASK(21, 18)
#define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24)
struct rtw89_fw_hdr_section_v1 {
@@ -580,6 +583,7 @@ struct rtw89_fw_hdr_section_v1 {
#define FWSECTION_HDR_V1_W1_REDL BIT(29)
#define FWSECTION_HDR_V1_W2_MSSC GENMASK(7, 0)
#define FORMATTED_MSSC 0xFF
+#define FORMATTED_MSSC_MASK GENMASK(7, 0)
#define FWSECTION_HDR_V1_W2_BBMCU_IDX GENMASK(27, 24)
struct rtw89_fw_hdr_v1 {
@@ -615,6 +619,7 @@ struct rtw89_fw_hdr_v1 {
#define FW_HDR_V1_W6_DSP_CHKSUM BIT(24)
#define FW_HDR_V1_W7_PART_SIZE GENMASK(15, 0)
#define FW_HDR_V1_W7_DYN_HDR BIT(16)
+#define FW_HDR_V1_W7_IDMEM_SHARE_MODE GENMASK(21, 18)
enum rtw89_fw_mss_pool_rmp_tbl_type {
MSS_POOL_RMP_TBL_BITMASK = 0x0,
@@ -3689,6 +3694,13 @@ struct rtw89_c2h_pkt_ofld_rsp {
#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP GENMASK(10, 8)
#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN GENMASK(31, 16)
+struct rtw89_c2h_tx_duty_rpt {
+ struct rtw89_c2h_hdr c2h_hdr;
+ __le32 w2;
+} __packed;
+
+#define RTW89_C2H_TX_DUTY_RPT_W2_TIMER_ERR GENMASK(2, 0)
+
struct rtw89_c2h_wow_aoac_report {
struct rtw89_c2h_hdr c2h_hdr;
u8 rpt_ver;
@@ -3713,6 +3725,15 @@ struct rtw89_c2h_wow_aoac_report {
#define RTW89_C2H_WOW_AOAC_RPT_REKEY_IDX BIT(0)
+struct rtw89_h2c_tx_duty {
+ __le32 w0;
+ __le32 w1;
+} __packed;
+
+#define RTW89_H2C_TX_DUTY_W0_PAUSE_INTVL_MASK GENMASK(15, 0)
+#define RTW89_H2C_TX_DUTY_W0_TX_INTVL_MASK GENMASK(31, 16)
+#define RTW89_H2C_TX_DUTY_W1_STOP BIT(0)
+
struct rtw89_h2c_bcnfltr {
__le32 w0;
} __packed;
@@ -4071,6 +4092,7 @@ enum rtw89_fw_ofld_h2c_func {
H2C_FUNC_OFLD_CFG = 0x14,
H2C_FUNC_ADD_SCANOFLD_CH = 0x16,
H2C_FUNC_SCANOFLD = 0x17,
+ H2C_FUNC_TX_DUTY = 0x18,
H2C_FUNC_PKT_DROP = 0x1b,
H2C_FUNC_CFG_BCNFLTR = 0x1e,
H2C_FUNC_OFLD_RSSI = 0x1f,
@@ -4286,7 +4308,7 @@ struct rtw89_h2c_rf_dack {
__le32 type;
} __packed;
-struct rtw89_h2c_rf_rxdck {
+struct rtw89_h2c_rf_rxdck_v0 {
u8 len;
u8 phy;
u8 is_afe;
@@ -4297,6 +4319,11 @@ struct rtw89_h2c_rf_rxdck {
u8 rxdck_dbg_en;
} __packed;
+struct rtw89_h2c_rf_rxdck {
+ struct rtw89_h2c_rf_rxdck_v0 v0;
+ u8 is_chl_k;
+} __packed;
+
enum rtw89_rf_log_type {
RTW89_RF_RUN_LOG = 0,
RTW89_RF_RPT_LOG = 1,
@@ -4313,6 +4340,42 @@ struct rtw89_c2h_rf_run_log {
__le32 arg[4];
} __packed;
+struct rtw89_c2h_rf_iqk_rpt_log {
+ bool iqk_tx_fail[2];
+ bool iqk_rx_fail[2];
+ bool is_iqk_init;
+ bool is_reload;
+ bool is_wb_txiqk[2];
+ bool is_wb_rxiqk[2];
+ bool is_nbiqk;
+ bool txiqk_en;
+ bool rxiqk_en;
+ bool lok_en;
+ bool iqk_xym_en;
+ bool iqk_sram_en;
+ bool iqk_fft_en;
+ bool is_fw_iqk;
+ bool is_iqk_enable;
+ bool iqk_cfir_en;
+ bool thermal_rek_en;
+ u8 iqk_band[2];
+ u8 iqk_ch[2];
+ u8 iqk_bw[2];
+ u8 iqk_times;
+ u8 version;
+ u8 phy;
+ u8 fwk_status;
+ u8 rsvd;
+ __le32 reload_cnt;
+ __le32 iqk_fail_cnt;
+ __le32 lok_idac[2];
+ __le32 lok_vbuf[2];
+ __le32 rftxgain[2][4];
+ __le32 rfrxgain[2][4];
+ __le32 tx_xym[2][4];
+ __le32 rx_xym[2][4];
+} __packed;
+
struct rtw89_c2h_rf_dpk_rpt_log {
u8 ver;
u8 idx[2];
@@ -4334,19 +4397,25 @@ struct rtw89_c2h_rf_dpk_rpt_log {
struct rtw89_c2h_rf_dack_rpt_log {
u8 fwdack_ver;
- u8 fwdack_rpt_ver;
+ u8 fwdack_info_ver;
u8 msbk_d[2][2][16];
u8 dadck_d[2][2];
u8 cdack_d[2][2][2];
- __le16 addck2_d[2][2][2];
+ u8 addck2_hd[2][2][2];
+ u8 addck2_ld[2][2][2];
u8 adgaink_d[2][2];
- __le16 biask_d[2][2];
+ u8 biask_hd[2][2];
+ u8 biask_ld[2][2];
u8 addck_timeout;
u8 cdack_timeout;
u8 dadck_timeout;
u8 msbk_timeout;
u8 adgaink_timeout;
+ u8 wbadcdck_timeout;
+ u8 drck_timeout;
u8 dack_fail;
+ u8 wbdck_d[2];
+ u8 rck_d;
} __packed;
struct rtw89_c2h_rf_rxdck_rpt_log {
@@ -4357,6 +4426,14 @@ struct rtw89_c2h_rf_rxdck_rpt_log {
u8 timeout[2];
} __packed;
+struct rtw89_c2h_rf_tssi_rpt_log {
+ s8 alignment_power[2][2][4];
+ u8 alignment_power_cw_h[2][2][4];
+ u8 alignment_power_cw_l[2][2][4];
+ u8 tssi_alimk_state[2][2];
+ u8 default_txagc_offset[2][2];
+} __packed;
+
struct rtw89_c2h_rf_txgapk_rpt_log {
__le32 r0x8010[2];
__le32 chk_cnt;
@@ -4404,59 +4481,60 @@ void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u8 type, u8 cat, u8 class, u8 func,
bool rack, bool dack, u32 len);
int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta);
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta);
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
+ struct rtw89_vif_link *rtwvif_link);
int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
-int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *vif,
- struct rtw89_sta *rtwsta, const u8 *scan_mac_addr);
+ struct rtw89_vif_link *rtwvif_link);
+int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif,
+ struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr);
int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta);
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h);
void rtw89_fw_c2h_work(struct work_struct *work);
int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
enum rtw89_upd_mode upd_mode);
-int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta, bool dis_conn);
+int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link, bool dis_conn);
int rtw89_fw_h2c_notify_dbcc(struct rtw89_dev *rtwdev, bool en);
int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
bool pause);
-int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u8 ac, u32 val);
int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev);
+int rtw89_fw_h2c_tx_duty(struct rtw89_dev *rtwdev, u8 lv);
int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
+ struct rtw89_vif_link *rtwvif_link,
bool connect);
int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu);
-int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi);
int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_init_v7(struct rtw89_dev *rtwdev, u8 type);
@@ -4472,17 +4550,13 @@ int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id);
int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
struct sk_buff *skb_ofld);
-int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num,
- struct list_head *chan_list);
-int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
- struct list_head *chan_list);
int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *opt,
- struct rtw89_vif *vif,
+ struct rtw89_vif_link *vif,
bool wowlan);
int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *opt,
- struct rtw89_vif *vif,
+ struct rtw89_vif_link *vif,
bool wowlan);
int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
struct rtw89_fw_h2c_rf_reg_info *info,
@@ -4501,21 +4575,26 @@ int rtw89_fw_h2c_rf_txgapk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan);
int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
- const struct rtw89_chan *chan);
+ const struct rtw89_chan *chan, bool is_chl_k);
int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
u8 h2c_class, u8 h2c_func, u8 *buf, u16 len,
bool rack, bool dack);
int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len);
void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev);
void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev);
-int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u8 macid);
void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool notify_fw);
+ struct rtw89_vif_link *rtwvif_link,
+ bool notify_fw);
void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw);
-int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
bool valid, struct ieee80211_ampdu_params *params);
-int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
bool valid, struct ieee80211_ampdu_params *params);
void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users,
@@ -4524,8 +4603,8 @@ int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users,
int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
struct rtw89_lps_parm *lps_param);
int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
-int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link);
+int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable);
struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len);
struct sk_buff *rtw89_fw_h2c_alloc_skb_no_hdr(struct rtw89_dev *rtwdev, u32 len);
@@ -4534,49 +4613,56 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev,
struct rtw89_mac_c2h_info *c2h_info);
int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable);
void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev);
-void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
- struct ieee80211_scan_request *req);
-void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_scan_request *scan_req);
+void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool aborted);
-int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool enable);
-void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
+void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link);
int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool connected);
+ struct rtw89_vif_link *rtwvif_link, bool connected);
int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
+ struct rtw89_vif_link *rtwvif_link);
int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool connected);
+ struct rtw89_vif_link *rtwvif_link, bool connected);
int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
+ struct rtw89_vif_link *rtwvif_link);
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev,
const struct rtw89_pkt_drop_params *params);
-int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
+int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf,
struct ieee80211_p2p_noa_desc *desc,
u8 act, u8 noa_id);
-int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool en);
-int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable);
int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool enable);
-int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link, bool enable);
+int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable);
-int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable);
int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool enable);
+ struct rtw89_vif_link *rtwvif_link, bool enable);
int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool enable);
-int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link, bool enable);
+int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable);
int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool enable);
+ struct rtw89_vif_link *rtwvif_link, bool enable);
int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev,
struct rtw89_wow_cam_info *cam_info);
int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
bool enable);
int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_add_mcc(struct rtw89_dev *rtwdev,
@@ -4621,51 +4707,73 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
}
static inline int rtw89_chip_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta);
+ return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
}
static inline int rtw89_chip_h2c_default_dmac_tbl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_sta *rtwsta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
if (chip->ops->h2c_default_dmac_tbl)
- return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta);
+ return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
return 0;
}
static inline int rtw89_chip_h2c_update_beacon(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- return chip->ops->h2c_update_beacon(rtwdev, rtwvif);
+ return chip->ops->h2c_update_beacon(rtwdev, rtwvif_link);
}
static inline int rtw89_chip_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- return chip->ops->h2c_assoc_cmac_tbl(rtwdev, vif, sta);
+ return chip->ops->h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
}
-static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+static inline
+int rtw89_chip_h2c_ampdu_link_cmac_tbl(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
if (chip->ops->h2c_ampdu_cmac_tbl)
- return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
+ return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, rtwvif_link,
+ rtwsta_link);
+
+ return 0;
+}
+
+static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif,
+ struct rtw89_sta *rtwsta)
+{
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ int ret;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ ret = rtw89_chip_h2c_ampdu_link_cmac_tbl(rtwdev, rtwvif_link,
+ rtwsta_link);
+ if (ret)
+ return ret;
+ }
return 0;
}
@@ -4675,8 +4783,20 @@ int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
bool valid, struct ieee80211_ampdu_params *params)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ int ret;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ ret = chip->ops->h2c_ba_cam(rtwdev, rtwvif_link, rtwsta_link,
+ valid, params);
+ if (ret)
+ return ret;
+ }
- return chip->ops->h2c_ba_cam(rtwdev, rtwsta, valid, params);
+ return 0;
}
/* must consider compatibility; don't insert new in the mid */
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index c70a23a763b0..7907b84d204b 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1444,6 +1444,7 @@ void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev)
static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
{
#define PWR_ACT 1
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_pwr_cfg * const *cfg_seq;
int (*cfg_func)(struct rtw89_dev *rtwdev);
@@ -1472,6 +1473,9 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
return ret;
if (on) {
+ if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags))
+ mac->efuse_read_fw_secure(rtwdev);
+
set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
@@ -1483,7 +1487,8 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags);
clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR);
- rtw89_set_entity_state(rtwdev, false);
+ rtw89_set_entity_state(rtwdev, RTW89_PHY_0, false);
+ rtw89_set_entity_state(rtwdev, RTW89_PHY_1, false);
}
return 0;
@@ -3995,9 +4000,10 @@ fail:
static void rtw89_mac_dmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid)
{
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
u8 i;
- if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
+ if (rtwdev->chip->chip_gen != RTW89_CHIP_AX || sec->secure_boot)
return;
for (i = 0; i < 4; i++) {
@@ -4009,7 +4015,9 @@ static void rtw89_mac_dmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid)
static void rtw89_mac_cmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid)
{
- if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+
+ if (rtwdev->chip->chip_gen != RTW89_CHIP_AX || sec->secure_boot)
return;
rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR,
@@ -4076,17 +4084,17 @@ static const struct rtw89_port_reg rtw89_port_base_ax = {
};
static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, u8 type)
+ struct rtw89_vif_link *rtwvif_link, u8 type)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif->port);
+ u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif_link->port);
u32 reg_info, reg_ctrl;
u32 val;
int ret;
- reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif->mac_idx);
- reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif->mac_idx);
+ reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif_link->mac_idx);
+ reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg_ctrl, B_AX_PTCL_DBG_SEL_MASK, type);
rtw89_write32_set(rtwdev, reg_ctrl, B_AX_PTCL_DBG_EN);
@@ -4098,26 +4106,32 @@ static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev,
rtw89_warn(rtwdev, "Polling beacon packet empty fail\n");
}
-static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif->port));
- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, 1);
- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, 0);
- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 0);
- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, 2);
- rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK, 1);
- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, 1);
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
-
- rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM0);
- if (rtwvif->port == RTW89_PORT_0)
- rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM1);
-
- rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif->port));
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TBTT_PROHIB_EN);
+ rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port));
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK,
+ 1);
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area, B_AX_BCN_MSK_AREA_MASK,
+ 0);
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK,
+ 0);
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK, 2);
+ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early,
+ B_AX_TBTTERLY_MASK, 1);
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space,
+ B_AX_BCN_SPACE_MASK, 1);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN);
+
+ rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM0);
+ if (rtwvif_link->port == RTW89_PORT_0)
+ rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM1);
+
+ rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port));
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TBTT_PROHIB_EN);
fsleep(2000);
}
@@ -4131,286 +4145,329 @@ static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvi
#define BCN_ERLY_SET_DLY (10 * 2)
static void rtw89_mac_port_cfg_func_sw(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct ieee80211_bss_conf *bss_conf;
bool need_backup = false;
u32 backup_val;
+ u16 beacon_int;
- if (!rtw89_read32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN))
+ if (!rtw89_read32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN))
return;
- if (chip->chip_id == RTL8852A && rtwvif->port != RTW89_PORT_0) {
+ if (chip->chip_id == RTL8852A && rtwvif_link->port != RTW89_PORT_0) {
need_backup = true;
- backup_val = rtw89_read32_port(rtwdev, rtwvif, p->tbtt_prohib);
+ backup_val = rtw89_read32_port(rtwdev, rtwvif_link, p->tbtt_prohib);
}
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
- rtw89_mac_bcn_drop(rtwdev, rtwvif);
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
+ rtw89_mac_bcn_drop(rtwdev, rtwvif_link);
if (chip->chip_id == RTL8852A) {
- rtw89_write32_port_clr(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK);
- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 1);
- rtw89_write16_port_clr(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK);
- rtw89_write16_port_clr(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->tbtt_prohib,
+ B_AX_TBTT_SETUP_MASK);
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib,
+ B_AX_TBTT_HOLD_MASK, 1);
+ rtw89_write16_port_clr(rtwdev, rtwvif_link, p->tbtt_early,
+ B_AX_TBTTERLY_MASK);
+ rtw89_write16_port_clr(rtwdev, rtwvif_link, p->bcn_early,
+ B_AX_BCNERLY_MASK);
}
- msleep(vif->bss_conf.beacon_int + 1);
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN |
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ beacon_int = bss_conf->beacon_int;
+
+ rcu_read_unlock();
+
+ msleep(beacon_int + 1);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN |
B_AX_BRK_SETUP);
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSFTR_RST);
- rtw89_write32_port(rtwdev, rtwvif, p->bcn_cnt_tmr, 0);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSFTR_RST);
+ rtw89_write32_port(rtwdev, rtwvif_link, p->bcn_cnt_tmr, 0);
if (need_backup)
- rtw89_write32_port(rtwdev, rtwvif, p->tbtt_prohib, backup_val);
+ rtw89_write32_port(rtwdev, rtwvif_link, p->tbtt_prohib, backup_val);
}
static void rtw89_mac_port_cfg_tx_rpt(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool en)
+ struct rtw89_vif_link *rtwvif_link, bool en)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
if (en)
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg,
+ B_AX_TXBCN_RPT_EN);
else
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg,
+ B_AX_TXBCN_RPT_EN);
}
static void rtw89_mac_port_cfg_rx_rpt(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool en)
+ struct rtw89_vif_link *rtwvif_link, bool en)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
if (en)
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg,
+ B_AX_RXBCN_RPT_EN);
else
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg,
+ B_AX_RXBCN_RPT_EN);
}
static void rtw89_mac_port_cfg_net_type(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- rtw89_write32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_NET_TYPE_MASK,
- rtwvif->net_type);
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_NET_TYPE_MASK,
+ rtwvif_link->net_type);
}
static void rtw89_mac_port_cfg_bcn_prct(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- bool en = rtwvif->net_type != RTW89_NET_TYPE_NO_LINK;
+ bool en = rtwvif_link->net_type != RTW89_NET_TYPE_NO_LINK;
u32 bits = B_AX_TBTT_PROHIB_EN | B_AX_BRK_SETUP;
if (en)
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bits);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bits);
else
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bits);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bits);
}
static void rtw89_mac_port_cfg_rx_sw(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA ||
- rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;
+ bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA ||
+ rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC;
u32 bit = B_AX_RX_BSSID_FIT_EN;
if (en)
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bit);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bit);
else
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bit);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bit);
}
void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool en)
+ struct rtw89_vif_link *rtwvif_link, bool en)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
if (en)
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN);
else
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN);
}
static void rtw89_mac_port_cfg_rx_sync_by_nettype(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
- bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA ||
- rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;
+ bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA ||
+ rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC;
- rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, en);
+ rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, en);
}
static void rtw89_mac_port_cfg_tx_sw(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool en)
+ struct rtw89_vif_link *rtwvif_link, bool en)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
if (en)
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN);
else
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN);
}
static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
- bool en = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ||
- rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;
+ bool en = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE ||
+ rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC;
- rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en);
+ rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en);
}
void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
- rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
+ rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en);
}
static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- u16 bcn_int = vif->bss_conf.beacon_int ? vif->bss_conf.beacon_int : BCN_INTERVAL;
+ struct ieee80211_bss_conf *bss_conf;
+ u16 bcn_int;
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ if (bss_conf->beacon_int)
+ bcn_int = bss_conf->beacon_int;
+ else
+ bcn_int = BCN_INTERVAL;
- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK,
+ rcu_read_unlock();
+
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, B_AX_BCN_SPACE_MASK,
bcn_int);
}
static void rtw89_mac_port_cfg_hiq_win(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
- u8 win = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0;
+ u8 win = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0;
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- u8 port = rtwvif->port;
+ u8 port = rtwvif_link->port;
u32 reg;
- reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif_link->mac_idx);
rtw89_write8(rtwdev, reg, win);
}
static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_bss_conf *bss_conf;
+ u8 dtim_period;
u32 addr;
- addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif->mac_idx);
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ dtim_period = bss_conf->dtim_period;
+
+ rcu_read_unlock();
+
+ addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif_link->mac_idx);
rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE);
- rtw89_write16_port_mask(rtwdev, rtwvif, p->dtim_ctrl, B_AX_DTIM_NUM_MASK,
- vif->bss_conf.dtim_period);
+ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->dtim_ctrl, B_AX_DTIM_NUM_MASK,
+ dtim_period);
}
static void rtw89_mac_port_cfg_bcn_setup_time(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib,
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib,
B_AX_TBTT_SETUP_MASK, BCN_SETUP_DEF);
}
static void rtw89_mac_port_cfg_bcn_hold_time(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib,
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib,
B_AX_TBTT_HOLD_MASK, BCN_HOLD_DEF);
}
static void rtw89_mac_port_cfg_bcn_mask_area(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area,
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area,
B_AX_BCN_MSK_AREA_MASK, BCN_MASK_DEF);
}
static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early,
+ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early,
B_AX_TBTTERLY_MASK, TBTT_ERLY_DEF);
}
static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
static const u32 masks[RTW89_PORT_NUM] = {
B_AX_BSS_COLOB_AX_PORT_0_MASK, B_AX_BSS_COLOB_AX_PORT_1_MASK,
B_AX_BSS_COLOB_AX_PORT_2_MASK, B_AX_BSS_COLOB_AX_PORT_3_MASK,
B_AX_BSS_COLOB_AX_PORT_4_MASK,
};
- u8 port = rtwvif->port;
+ struct ieee80211_bss_conf *bss_conf;
+ u8 port = rtwvif_link->port;
u32 reg_base;
u32 reg;
u8 bss_color;
- bss_color = vif->bss_conf.he_bss_color.color;
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ bss_color = bss_conf->he_bss_color.color;
+
+ rcu_read_unlock();
+
reg_base = port >= 4 ? p->bss_color + 4 : p->bss_color;
- reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg, masks[port], bss_color);
}
static void rtw89_mac_port_cfg_mbssid(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- u8 port = rtwvif->port;
+ u8 port = rtwvif_link->port;
u32 reg;
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE)
return;
if (port == 0) {
- reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif_link->mac_idx);
rtw89_write32_clr(rtwdev, reg, B_AX_P0MB_ALL_MASK);
}
}
static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- u8 port = rtwvif->port;
+ u8 port = rtwvif_link->port;
u32 reg;
u32 val;
- reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif_link->mac_idx);
val = rtw89_read32(rtwdev, reg);
val &= ~FIELD_PREP(B_AX_PORT_DROP_4_0_MASK, BIT(port));
if (port == 0)
@@ -4419,31 +4476,31 @@ static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev,
}
static void rtw89_mac_port_cfg_func_en(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool enable)
+ struct rtw89_vif_link *rtwvif_link, bool enable)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
if (enable)
- rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg,
+ rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg,
B_AX_PORT_FUNC_EN);
else
- rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg,
+ rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg,
B_AX_PORT_FUNC_EN);
}
static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
- rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK,
+ rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK,
BCN_ERLY_DEF);
}
static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_port_reg *p = mac->port_base;
@@ -4452,20 +4509,20 @@ static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev,
if (rtwdev->chip->chip_id != RTL8852C)
return;
- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT &&
- rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
+ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT &&
+ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION)
return;
val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) |
B_AX_TBTT_SHIFT_OFST_SIGN;
- rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_shift,
+ rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_shift,
B_AX_TBTT_SHIFT_OFST_MASK, val);
}
void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_vif *rtwvif_src,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_vif_link *rtwvif_src,
u16 offset_tu)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
@@ -4473,8 +4530,8 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
u32 val, reg;
val = RTW89_PORT_OFFSET_TU_TO_32US(offset_tu);
- reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif->port * 4,
- rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif_link->port * 4,
+ rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port);
rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_OFFSET_VAL, val);
@@ -4482,16 +4539,16 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
}
static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_vif *rtwvif_src,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_vif_link *rtwvif_src,
u8 offset, int *n_offset)
{
- if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif == rtwvif_src)
+ if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif_link == rtwvif_src)
return;
/* adjust offset randomly to avoid beacon conflict */
offset = offset - offset / 4 + get_random_u32() % (offset / 2);
- rtw89_mac_port_tsf_sync(rtwdev, rtwvif, rtwvif_src,
+ rtw89_mac_port_tsf_sync(rtwdev, rtwvif_link, rtwvif_src,
(*n_offset) * offset);
(*n_offset)++;
@@ -4499,15 +4556,19 @@ static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev,
static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev)
{
- struct rtw89_vif *src = NULL, *tmp;
+ struct rtw89_vif_link *src = NULL, *tmp;
u8 offset = 100, vif_aps = 0;
+ struct rtw89_vif *rtwvif;
+ unsigned int link_id;
int n_offset = 1;
- rtw89_for_each_rtwvif(rtwdev, tmp) {
- if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA)
- src = tmp;
- if (tmp->net_type == RTW89_NET_TYPE_AP_MODE)
- vif_aps++;
+ rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+ rtw89_vif_for_each_link(rtwvif, tmp, link_id) {
+ if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA)
+ src = tmp;
+ if (tmp->net_type == RTW89_NET_TYPE_AP_MODE)
+ vif_aps++;
+ }
}
if (vif_aps == 0)
@@ -4515,104 +4576,106 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev)
offset /= (vif_aps + 1);
- rtw89_for_each_rtwvif(rtwdev, tmp)
- rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, &n_offset);
+ rtw89_for_each_rtwvif(rtwdev, rtwvif)
+ rtw89_vif_for_each_link(rtwvif, tmp, link_id)
+ rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset,
+ &n_offset);
}
-int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
int ret;
- ret = rtw89_mac_port_update(rtwdev, rtwvif);
+ ret = rtw89_mac_port_update(rtwdev, rtwvif_link);
if (ret)
return ret;
- rtw89_mac_dmac_tbl_init(rtwdev, rtwvif->mac_id);
- rtw89_mac_cmac_tbl_init(rtwdev, rtwvif->mac_id);
+ rtw89_mac_dmac_tbl_init(rtwdev, rtwvif_link->mac_id);
+ rtw89_mac_cmac_tbl_init(rtwdev, rtwvif_link->mac_id);
- ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif->mac_id, false);
+ ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif_link->mac_id, false);
if (ret)
return ret;
- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_CREATE);
+ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_CREATE);
if (ret)
return ret;
- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
+ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true);
if (ret)
return ret;
- ret = rtw89_cam_init(rtwdev, rtwvif);
+ ret = rtw89_cam_init(rtwdev, rtwvif_link);
if (ret)
return ret;
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
if (ret)
return ret;
- ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, NULL);
+ ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, NULL);
if (ret)
return ret;
- ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, NULL);
+ ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, NULL);
if (ret)
return ret;
return 0;
}
-int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
int ret;
- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_REMOVE);
+ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_REMOVE);
if (ret)
return ret;
- rtw89_cam_deinit(rtwdev, rtwvif);
+ rtw89_cam_deinit(rtwdev, rtwvif_link);
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
if (ret)
return ret;
return 0;
}
-int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- u8 port = rtwvif->port;
+ u8 port = rtwvif_link->port;
if (port >= RTW89_PORT_NUM)
return -EINVAL;
- rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif);
- rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif, false);
- rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif, false);
- rtw89_mac_port_cfg_net_type(rtwdev, rtwvif);
- rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif);
- rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif);
- rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif);
- rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif);
- rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif);
- rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif);
- rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif);
- rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif);
- rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif);
- rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif);
- rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif);
- rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif);
- rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif);
- rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif);
- rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif);
- rtw89_mac_port_cfg_func_en(rtwdev, rtwvif, true);
+ rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif_link, false);
+ rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif_link, false);
+ rtw89_mac_port_cfg_net_type(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif_link);
+ rtw89_mac_port_cfg_func_en(rtwdev, rtwvif_link, true);
rtw89_mac_port_tsf_resync_all(rtwdev);
fsleep(BCN_ERLY_SET_DLY);
- rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif);
+ rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif_link);
return 0;
}
-int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u64 *tsf)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
@@ -4620,12 +4683,12 @@ int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
u32 tsf_low, tsf_high;
int ret;
- ret = rtw89_mac_check_mac_en(rtwdev, rtwvif->mac_idx, RTW89_CMAC_SEL);
+ ret = rtw89_mac_check_mac_en(rtwdev, rtwvif_link->mac_idx, RTW89_CMAC_SEL);
if (ret)
return ret;
- tsf_low = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_l);
- tsf_high = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_h);
+ tsf_low = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_l);
+ tsf_high = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_h);
*tsf = (u64)tsf_high << 32 | tsf_low;
return 0;
@@ -4651,65 +4714,57 @@ static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
}
void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif)
+ struct rtw89_vif_link *rtwvif_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct ieee80211_hw *hw = rtwdev->hw;
+ struct ieee80211_bss_conf *bss_conf;
+ struct cfg80211_chan_def oper;
bool tolerated = true;
u32 reg;
- if (!vif->bss_conf.he_support || vif->type != NL80211_IFTYPE_STATION)
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ if (!bss_conf->he_support || vif->type != NL80211_IFTYPE_STATION) {
+ rcu_read_unlock();
return;
+ }
- if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR))
+ oper = bss_conf->chanreq.oper;
+ if (!(oper.chan->flags & IEEE80211_CHAN_RADAR)) {
+ rcu_read_unlock();
return;
+ }
- cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper,
+ rcu_read_unlock();
+
+ cfg80211_bss_iter(hw->wiphy, &oper,
rtw89_mac_check_he_obss_narrow_bw_ru_iter,
&tolerated);
reg = rtw89_mac_reg_by_idx(rtwdev, mac->narrow_bw_ru_dis.addr,
- rtwvif->mac_idx);
+ rtwvif_link->mac_idx);
if (tolerated)
rtw89_write32_clr(rtwdev, reg, mac->narrow_bw_ru_dis.mask);
else
rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask);
}
-void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif);
+ rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link);
}
-int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- int ret;
-
- rtwvif->mac_id = rtw89_acquire_mac_id(rtwdev);
- if (rtwvif->mac_id == RTW89_MAX_MAC_ID_NUM)
- return -ENOSPC;
-
- ret = rtw89_mac_vif_init(rtwdev, rtwvif);
- if (ret)
- goto release_mac_id;
-
- return 0;
-
-release_mac_id:
- rtw89_release_mac_id(rtwdev, rtwvif->mac_id);
-
- return ret;
+ return rtw89_mac_vif_init(rtwdev, rtwvif_link);
}
-int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- int ret;
-
- ret = rtw89_mac_vif_deinit(rtwdev, rtwvif);
- rtw89_release_mac_id(rtwdev, rtwvif->mac_id);
-
- return ret;
+ return rtw89_mac_vif_deinit(rtwdev, rtwvif_link);
}
static void
@@ -4730,8 +4785,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
{
const struct rtw89_c2h_scanofld *c2h =
(const struct rtw89_c2h_scanofld *)skb->data;
- struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
+ struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
+ struct rtw89_vif *rtwvif;
struct rtw89_chan new;
u8 reason, status, tx_fail, band, actual_period, expect_period;
u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf;
@@ -4739,9 +4794,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u16 chan;
int ret;
- if (!rtwvif)
+ if (!rtwvif_link)
return;
+ rtwvif = rtwvif_link->rtwvif;
+
tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL);
status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS);
chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH);
@@ -4781,28 +4838,28 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
if (rtwdev->scan_info.abort)
return;
- if (rtwvif && rtwvif->scan_req &&
+ if (rtwvif_link && rtwvif->scan_req &&
last_chan < rtwvif->scan_req->n_channels) {
- ret = rtw89_hw_scan_offload(rtwdev, vif, true);
+ ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true);
if (ret) {
- rtw89_hw_scan_abort(rtwdev, vif);
+ rtw89_hw_scan_abort(rtwdev, rtwvif_link);
rtw89_warn(rtwdev, "HW scan failed: %d\n", ret);
}
} else {
- rtw89_hw_scan_complete(rtwdev, vif, false);
+ rtw89_hw_scan_complete(rtwdev, rtwvif_link, false);
}
break;
case RTW89_SCAN_ENTER_OP_NOTIFY:
case RTW89_SCAN_ENTER_CH_NOTIFY:
if (rtw89_is_op_chan(rtwdev, band, chan)) {
- rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx,
+ rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx,
&rtwdev->scan_info.op_chan);
rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);
ieee80211_wake_queues(rtwdev->hw);
} else {
rtw89_chan_create(&new, chan, chan, band,
RTW89_CHANNEL_WIDTH_20);
- rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx,
+ rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx,
&new);
}
break;
@@ -4812,10 +4869,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
}
static void
-rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
struct sk_buff *skb)
{
- struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
enum nl80211_cqm_rssi_threshold_event nl_event;
const struct rtw89_c2h_mac_bcnfltr_rpt *c2h =
(const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data;
@@ -4827,7 +4885,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
event = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT);
mac_id = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MACID);
- if (mac_id != rtwvif->mac_id)
+ if (mac_id != rtwvif_link->mac_id)
return;
rtw89_debug(rtwdev, RTW89_DBG_FW,
@@ -4839,7 +4897,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
if (!rtwdev->scanning && !rtwvif->offchan)
ieee80211_connection_loss(vif);
else
- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
return;
case RTW89_BCN_FLTR_NOTIFY:
nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
@@ -4863,10 +4921,13 @@ static void
rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
u32 len)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif, c2h);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h);
}
static void
@@ -4975,6 +5036,18 @@ rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h,
}
static void
+rtw89_mac_c2h_tx_duty_rpt(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len)
+{
+ struct rtw89_c2h_tx_duty_rpt *c2h =
+ (struct rtw89_c2h_tx_duty_rpt *)skb_c2h->data;
+ u8 err;
+
+ err = le32_get_bits(c2h->w2, RTW89_C2H_TX_DUTY_RPT_W2_TIMER_ERR);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, "C2H TX duty rpt with err=%d\n", err);
+}
+
+static void
rtw89_mac_c2h_tsf32_toggle_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
u32 len)
{
@@ -5300,6 +5373,7 @@ void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
[RTW89_MAC_C2H_FUNC_BCN_RESEND] = NULL,
[RTW89_MAC_C2H_FUNC_MACID_PAUSE] = rtw89_mac_c2h_macid_pause,
[RTW89_MAC_C2H_FUNC_SCANOFLD_RSP] = rtw89_mac_c2h_scanofld_rsp,
+ [RTW89_MAC_C2H_FUNC_TX_DUTY_RPT] = rtw89_mac_c2h_tx_duty_rpt,
[RTW89_MAC_C2H_FUNC_TSF32_TOGL_RPT] = rtw89_mac_c2h_tsf32_toggle_rpt,
[RTW89_MAC_C2H_FUNC_BCNFLTR_RPT] = rtw89_mac_c2h_bcn_fltr_rpt,
};
@@ -5490,7 +5564,8 @@ int rtw89_mac_cfg_ppdu_status_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool enab
return 0;
}
-void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx)
+static
+void __rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx)
{
#define MAC_AX_TIME_TH_SH 5
#define MAC_AX_LEN_TH_SH 4
@@ -5520,6 +5595,13 @@ void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx)
rtw89_write16_mask(rtwdev, reg, B_AX_RTS_LEN_TH_MASK, len_th);
}
+void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev)
+{
+ __rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0);
+ if (rtwdev->dbcc_en)
+ __rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_1);
+}
+
void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop)
{
bool empty;
@@ -5931,15 +6013,15 @@ static int rtw89_mac_init_bfee_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
}
static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- u8 mac_idx = rtwvif->mac_idx;
u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1;
- u8 port_sel = rtwvif->port;
+ struct ieee80211_link_sta *link_sta;
+ u8 mac_idx = rtwvif_link->mac_idx;
+ u8 port_sel = rtwvif_link->port;
u8 sound_dim = 3, t;
- u8 *phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info;
+ u8 *phy_cap;
u32 reg;
u16 val;
int ret;
@@ -5948,6 +6030,11 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev,
if (ret)
return ret;
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info;
+
if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) ||
(phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) {
ldpc_en &= !!(phy_cap[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD);
@@ -5956,17 +6043,19 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev,
phy_cap[5]);
sound_dim = min(sound_dim, t);
}
- if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) ||
- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
- ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
- stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK);
+ if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) ||
+ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
+ ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
+ stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK);
t = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
- sta->deflink.vht_cap.cap);
+ link_sta->vht_cap.cap);
sound_dim = min(sound_dim, t);
}
nc = min(nc, sound_dim);
nr = min(nr, sound_dim);
+ rcu_read_unlock();
+
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL);
@@ -5989,34 +6078,41 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev,
}
static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M);
+ struct ieee80211_link_sta *link_sta;
+ u8 mac_idx = rtwvif_link->mac_idx;
u32 reg;
- u8 mac_idx = rtwvif->mac_idx;
int ret;
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
if (ret)
return ret;
- if (sta->deflink.he_cap.has_he) {
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+
+ if (link_sta->he_cap.has_he) {
rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) |
BIT(RTW89_MAC_BF_RRSC_HE_MSC3) |
BIT(RTW89_MAC_BF_RRSC_HE_MSC5));
}
- if (sta->deflink.vht_cap.vht_supported) {
+ if (link_sta->vht_cap.vht_supported) {
rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) |
BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) |
BIT(RTW89_MAC_BF_RRSC_VHT_MSC5));
}
- if (sta->deflink.ht_cap.ht_supported) {
+ if (link_sta->ht_cap.ht_supported) {
rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) |
BIT(RTW89_MAC_BF_RRSC_HT_MSC3) |
BIT(RTW89_MAC_BF_RRSC_HT_MSC5));
}
+
+ rcu_read_unlock();
+
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL);
rtw89_write32_clr(rtwdev, reg, B_AX_BFMEE_CSI_FORCE_RETE_EN);
@@ -6028,35 +6124,53 @@ static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev,
}
static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct ieee80211_link_sta *link_sta;
+ bool has_beamformer_cap;
+
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta);
- if (rtw89_sta_has_beamformer_cap(sta)) {
+ rcu_read_unlock();
+
+ if (has_beamformer_cap) {
rtw89_debug(rtwdev, RTW89_DBG_BF,
"initialize bfee for new association\n");
- rtw89_mac_init_bfee_ax(rtwdev, rtwvif->mac_idx);
- rtw89_mac_set_csi_para_reg_ax(rtwdev, vif, sta);
- rtw89_mac_csi_rrsc_ax(rtwdev, vif, sta);
+ rtw89_mac_init_bfee_ax(rtwdev, rtwvif_link->mac_idx);
+ rtw89_mac_set_csi_para_reg_ax(rtwdev, rtwvif_link, rtwsta_link);
+ rtw89_mac_csi_rrsc_ax(rtwdev, rtwvif_link, rtwsta_link);
}
}
-void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
-
- rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, false);
+ rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, false);
}
void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- u8 mac_idx = rtwvif->mac_idx;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
+ u8 mac_idx;
__le32 *p;
+ rtwvif_link = rtwvif->links[conf->link_id];
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, conf->link_id);
+ return;
+ }
+
+ mac_idx = rtwvif_link->mac_idx;
+
rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n");
p = (__le32 *)conf->mu_group.membership;
@@ -6080,7 +6194,7 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *
struct rtw89_mac_bf_monitor_iter_data {
struct rtw89_dev *rtwdev;
- struct ieee80211_sta *down_sta;
+ struct rtw89_sta_link *down_rtwsta_link;
int count;
};
@@ -6089,23 +6203,41 @@ void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw89_mac_bf_monitor_iter_data *iter_data =
(struct rtw89_mac_bf_monitor_iter_data *)data;
- struct ieee80211_sta *down_sta = iter_data->down_sta;
+ struct rtw89_sta_link *down_rtwsta_link = iter_data->down_rtwsta_link;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct ieee80211_link_sta *link_sta;
+ struct rtw89_sta_link *rtwsta_link;
+ bool has_beamformer_cap = false;
int *count = &iter_data->count;
+ unsigned int link_id;
- if (down_sta == sta)
- return;
+ rcu_read_lock();
- if (rtw89_sta_has_beamformer_cap(sta))
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ if (rtwsta_link == down_rtwsta_link)
+ continue;
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
+ if (rtw89_sta_has_beamformer_cap(link_sta)) {
+ has_beamformer_cap = true;
+ break;
+ }
+ }
+
+ if (has_beamformer_cap)
(*count)++;
+
+ rcu_read_unlock();
}
void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta, bool disconnect)
+ struct rtw89_sta_link *rtwsta_link,
+ bool disconnect)
{
struct rtw89_mac_bf_monitor_iter_data data;
data.rtwdev = rtwdev;
- data.down_sta = disconnect ? sta : NULL;
+ data.down_rtwsta_link = disconnect ? rtwsta_link : NULL;
data.count = 0;
ieee80211_iterate_stations_atomic(rtwdev->hw,
rtw89_mac_bf_monitor_calc_iter,
@@ -6121,10 +6253,12 @@ void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev,
void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
{
struct rtw89_traffic_stats *stats = &rtwdev->stats;
- struct rtw89_vif *rtwvif;
+ struct rtw89_vif_link *rtwvif_link;
bool en = stats->tx_tfc_lv <= stats->rx_tfc_lv;
bool old = test_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags);
+ struct rtw89_vif *rtwvif;
bool keep_timer = true;
+ unsigned int link_id;
bool old_keep_timer;
old_keep_timer = test_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags);
@@ -6134,30 +6268,32 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
if (keep_timer != old_keep_timer) {
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_mac_bfee_standby_timer(rtwdev, rtwvif->mac_idx,
- keep_timer);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx,
+ keep_timer);
}
if (en == old)
return;
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, en);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en);
}
static int
-__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
u32 tx_time)
{
#define MAC_AX_DFLT_TX_TIME 5280
- u8 mac_idx = rtwsta->rtwvif->mac_idx;
+ u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx;
u32 max_tx_time = tx_time == 0 ? MAC_AX_DFLT_TX_TIME : tx_time;
u32 reg;
int ret = 0;
- if (rtwsta->cctl_tx_time) {
- rtwsta->ampdu_max_time = (max_tx_time - 512) >> 9;
- ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta);
+ if (rtwsta_link->cctl_tx_time) {
+ rtwsta_link->ampdu_max_time = (max_tx_time - 512) >> 9;
+ ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
} else {
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
if (ret) {
@@ -6173,31 +6309,31 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
return ret;
}
-int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
bool resume, u32 tx_time)
{
int ret = 0;
if (!resume) {
- rtwsta->cctl_tx_time = true;
- ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time);
+ rtwsta_link->cctl_tx_time = true;
+ ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time);
} else {
- ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time);
- rtwsta->cctl_tx_time = false;
+ ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time);
+ rtwsta_link->cctl_tx_time = false;
}
return ret;
}
-int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
u32 *tx_time)
{
- u8 mac_idx = rtwsta->rtwvif->mac_idx;
+ u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx;
u32 reg;
int ret = 0;
- if (rtwsta->cctl_tx_time) {
- *tx_time = (rtwsta->ampdu_max_time + 1) << 9;
+ if (rtwsta_link->cctl_tx_time) {
+ *tx_time = (rtwsta_link->ampdu_max_time + 1) << 9;
} else {
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
if (ret) {
@@ -6213,33 +6349,33 @@ int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
}
int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta,
+ struct rtw89_sta_link *rtwsta_link,
bool resume, u8 tx_retry)
{
int ret = 0;
- rtwsta->data_tx_cnt_lmt = tx_retry;
+ rtwsta_link->data_tx_cnt_lmt = tx_retry;
if (!resume) {
- rtwsta->cctl_tx_retry_limit = true;
- ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta);
+ rtwsta_link->cctl_tx_retry_limit = true;
+ ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
} else {
- ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta);
- rtwsta->cctl_tx_retry_limit = false;
+ ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
+ rtwsta_link->cctl_tx_retry_limit = false;
}
return ret;
}
int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta, u8 *tx_retry)
+ struct rtw89_sta_link *rtwsta_link, u8 *tx_retry)
{
- u8 mac_idx = rtwsta->rtwvif->mac_idx;
+ u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx;
u32 reg;
int ret = 0;
- if (rtwsta->cctl_tx_retry_limit) {
- *tx_retry = rtwsta->data_tx_cnt_lmt;
+ if (rtwsta_link->cctl_tx_retry_limit) {
+ *tx_retry = rtwsta_link->data_tx_cnt_lmt;
} else {
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
if (ret) {
@@ -6255,10 +6391,10 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev,
}
int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool en)
+ struct rtw89_vif_link *rtwvif_link, bool en)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
- u8 mac_idx = rtwvif->mac_idx;
+ u8 mac_idx = rtwvif_link->mac_idx;
u16 set = mac->muedca_ctrl.mask;
u32 reg;
u32 ret;
@@ -6326,7 +6462,9 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
}
static
-void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
+void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
static const enum rtw89_pkt_drop_sel sels[] = {
RTW89_PKT_DROP_SEL_MACID_BE_ONCE,
@@ -6334,15 +6472,14 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
RTW89_PKT_DROP_SEL_MACID_VI_ONCE,
RTW89_PKT_DROP_SEL_MACID_VO_ONCE,
};
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_pkt_drop_params params = {0};
int i;
- params.mac_band = RTW89_MAC_0;
- params.macid = rtwsta->mac_id;
- params.port = rtwvif->port;
+ params.mac_band = rtwvif_link->mac_idx;
+ params.macid = rtwsta_link->mac_id;
+ params.port = rtwvif_link->port;
params.mbssid = 0;
- params.tf_trs = rtwvif->trigger;
+ params.tf_trs = rtwvif_link->trigger;
for (i = 0; i < ARRAY_SIZE(sels); i++) {
params.sel = sels[i];
@@ -6352,15 +6489,21 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
- struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
struct rtw89_vif *target = data;
+ unsigned int link_id;
if (rtwvif != target)
return;
- rtw89_mac_pkt_drop_sta(rtwdev, rtwsta);
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ rtw89_mac_pkt_drop_sta(rtwdev, rtwvif_link, rtwsta_link);
+ }
}
void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
@@ -6398,6 +6541,9 @@ int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable)
struct rtw89_mac_c2h_info c2h_info = {};
u32 ret;
+ if (RTW89_CHK_FW_FEATURE(NO_WOW_CPU_IO_RX, &rtwdev->fw))
+ return 0;
+
h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_WOW_CPUIO_RX_CTRL;
h2c_info.content_len = sizeof(h2c_info.u.hdr);
h2c_info.u.hdr.w0 = u32_encode_bits(wow_enable, RTW89_H2CREG_WOW_CPUIO_RX_CTRL_EN);
@@ -6434,6 +6580,9 @@ static int rtw89_wow_config_mac_ax(struct rtw89_dev *rtwdev, bool enable_wow)
rtw89_write32(rtwdev, R_AX_TF_FWD, 0);
rtw89_write32(rtwdev, R_AX_HW_RPT_FWD, 0);
+ if (RTW89_CHK_FW_FEATURE(NO_WOW_CPU_IO_RX, &rtwdev->fw))
+ return 0;
+
if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
rtw89_write8(rtwdev, R_BE_DBG_WOW_READY, WOWLAN_NOT_READY);
else
@@ -6475,6 +6624,20 @@ int rtw89_fwdl_check_path_ready_ax(struct rtw89_dev *rtwdev,
rtwdev, R_AX_WCPU_FW_CTRL);
}
+static
+void rtw89_fwdl_secure_idmem_share_mode_ax(struct rtw89_dev *rtwdev, u8 mode)
+{
+ struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+
+ if (!sec->secure_boot)
+ return;
+
+ rtw89_write32_mask(rtwdev, R_AX_WCPU_FW_CTRL,
+ B_AX_IDMEM_SHARE_MODE_RECORD_MASK, mode);
+ rtw89_write32_set(rtwdev, R_AX_WCPU_FW_CTRL,
+ B_AX_IDMEM_SHARE_MODE_RECORD_VALID);
+}
+
const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.band1_offset = RTW89_MAC_AX_BAND_REG_OFFSET,
.filter_model_addr = R_AX_FILTER_MODEL_ADDR,
@@ -6528,9 +6691,11 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.fwdl_enable_wcpu = rtw89_mac_enable_cpu_ax,
.fwdl_get_status = rtw89_fw_get_rdy_ax,
.fwdl_check_path_ready = rtw89_fwdl_check_path_ready_ax,
+ .fwdl_secure_idmem_share_mode = rtw89_fwdl_secure_idmem_share_mode_ax,
.parse_efuse_map = rtw89_parse_efuse_map_ax,
.parse_phycap_map = rtw89_parse_phycap_map_ax,
.cnv_efuse_state = rtw89_cnv_efuse_state_ax,
+ .efuse_read_fw_secure = rtw89_efuse_read_fw_secure_ax,
.cfg_plt = rtw89_mac_cfg_plt_ax,
.get_plt_cnt = rtw89_mac_get_plt_cnt_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 67c2a4507124..18579c020548 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -391,6 +391,7 @@ enum rtw89_mac_c2h_ofld_func {
RTW89_MAC_C2H_FUNC_MACID_PAUSE,
RTW89_MAC_C2H_FUNC_TSF32_TOGL_RPT = 0x6,
RTW89_MAC_C2H_FUNC_SCANOFLD_RSP = 0x9,
+ RTW89_MAC_C2H_FUNC_TX_DUTY_RPT = 0xa,
RTW89_MAC_C2H_FUNC_BCNFLTR_RPT = 0xd,
RTW89_MAC_C2H_FUNC_OFLD_MAX,
};
@@ -951,8 +952,9 @@ struct rtw89_mac_gen_def {
void (*dmac_func_pre_en)(struct rtw89_dev *rtwdev);
void (*dle_func_en)(struct rtw89_dev *rtwdev, bool enable);
void (*dle_clk_en)(struct rtw89_dev *rtwdev, bool enable);
- void (*bf_assoc)(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+ void (*bf_assoc)(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
int (*typ_fltr_opt)(struct rtw89_dev *rtwdev,
enum rtw89_machdr_frame_type type,
@@ -983,9 +985,11 @@ struct rtw89_mac_gen_def {
bool dlfw, bool include_bb);
u8 (*fwdl_get_status)(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type);
int (*fwdl_check_path_ready)(struct rtw89_dev *rtwdev, bool h2c_or_fwdl);
+ void (*fwdl_secure_idmem_share_mode)(struct rtw89_dev *rtwdev, u8 mode);
int (*parse_efuse_map)(struct rtw89_dev *rtwdev);
int (*parse_phycap_map)(struct rtw89_dev *rtwdev);
int (*cnv_efuse_state)(struct rtw89_dev *rtwdev, bool idle);
+ int (*efuse_read_fw_secure)(struct rtw89_dev *rtwdev);
int (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band);
@@ -1004,12 +1008,12 @@ struct rtw89_mac_gen_def {
bool (*is_txq_empty)(struct rtw89_dev *rtwdev);
int (*add_chan_list)(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool connected);
+ struct rtw89_vif_link *rtwvif_link, bool connected);
int (*add_chan_list_pno)(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif);
+ struct rtw89_vif_link *rtwvif_link);
int (*scan_offload)(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *option,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
bool wowlan);
int (*wow_config_mac)(struct rtw89_dev *rtwdev, bool enable_wow);
@@ -1033,81 +1037,89 @@ u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_id
}
static inline u32
-rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base)
+rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
return rtw89_read32(rtwdev, reg);
}
static inline u32
-rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u32 base, u32 mask)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
return rtw89_read32_mask(rtwdev, reg, mask);
}
static inline void
-rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base,
+rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base,
u32 data)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
rtw89_write32(rtwdev, reg, data);
}
static inline void
-rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u32 base, u32 mask, u32 data)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg, mask, data);
}
static inline void
-rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u32 base, u32 mask, u16 data)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
rtw89_write16_mask(rtwdev, reg, mask, data);
}
static inline void
-rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u32 base, u32 bit)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
rtw89_write32_clr(rtwdev, reg, bit);
}
static inline void
-rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u32 base, u16 bit)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
rtw89_write16_clr(rtwdev, reg, bit);
}
static inline void
-rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u32 base, u32 bit)
{
u32 reg;
- reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port,
+ rtwvif_link->mac_idx);
rtw89_write32_set(rtwdev, reg, bit);
}
@@ -1139,21 +1151,21 @@ int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev,
struct rtw89_mac_dle_dfi_qempty *qempty);
void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev,
enum mac_ax_err_info err);
-int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
-int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);
+int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
- struct rtw89_vif *rtwvif_src,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_vif_link *rtwvif_src,
u16 offset_tu);
-int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
u64 *tsf);
void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool en);
+ struct rtw89_vif_link *rtwvif_link, bool en);
void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif);
-void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+ struct rtw89_vif_link *rtwvif_link);
+void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en);
-int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
+int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);
int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev);
int rtw89_mac_disable_bb_rf(struct rtw89_dev *rtwdev);
@@ -1213,7 +1225,22 @@ int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
return mac->cfg_ppdu_status(rtwdev, mac_idx, enable);
}
-void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx);
+static inline
+int rtw89_mac_cfg_ppdu_status_bands(struct rtw89_dev *rtwdev, bool enable)
+{
+ int ret;
+
+ ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, enable);
+ if (ret)
+ return ret;
+
+ if (!rtwdev->dbcc_en)
+ return 0;
+
+ return rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_1, enable);
+}
+
+void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev);
void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop);
int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex);
int rtw89_mac_coex_init_v1(struct rtw89_dev *rtwdev,
@@ -1251,27 +1278,30 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter);
void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev);
static inline
-void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
if (mac->bf_assoc)
- mac->bf_assoc(rtwdev, vif, sta);
+ mac->bf_assoc(rtwdev, rtwvif_link, rtwsta_link);
}
-void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
+void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link);
void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf);
void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta, bool disconnect);
+ struct rtw89_sta_link *rtwsta_link,
+ bool disconnect);
void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev);
void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en);
-int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
-int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
+int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool en);
+ struct rtw89_vif_link *rtwvif_link, bool en);
int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause);
static inline void rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
@@ -1376,15 +1406,15 @@ static inline bool rtw89_mac_get_power_state(struct rtw89_dev *rtwdev)
return !!val;
}
-int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
bool resume, u32 tx_time);
-int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
u32 *tx_time);
int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta,
+ struct rtw89_sta_link *rtwsta_link,
bool resume, u8 tx_retry);
int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta, u8 *tx_retry);
+ struct rtw89_sta_link *rtwsta_link, u8 *tx_retry);
enum rtw89_mac_xtal_si_offset {
XTAL0 = 0x0,
@@ -1466,4 +1496,14 @@ int rtw89_mac_get_dle_rsvd_qt_cfg(struct rtw89_dev *rtwdev,
struct rtw89_mac_dle_rsvd_qt_cfg *cfg);
int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable);
+static inline
+void rtw89_fwdl_secure_idmem_share_mode(struct rtw89_dev *rtwdev, u8 mode)
+{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+ if (!mac->fwdl_secure_idmem_share_mode)
+ return;
+
+ return mac->fwdl_secure_idmem_share_mode(rtwdev, mode);
+}
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 48ad0d0f76bf..619d2d3771d5 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -23,13 +23,13 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw,
struct rtw89_dev *rtwdev = hw->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
struct ieee80211_sta *sta = control->sta;
u32 flags = IEEE80211_SKB_CB(skb)->flags;
int ret, qsel;
if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) {
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n");
skb_queue_tail(&rtwsta->roc_queue, skb);
@@ -105,11 +105,61 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed)
return 0;
}
+static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ struct ieee80211_bss_conf *bss_conf;
+ int ret;
+
+ rtw89_leave_ps_mode(rtwdev);
+
+ rtw89_vif_type_mapping(rtwvif_link, false);
+
+ INIT_WORK(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work);
+ INIT_LIST_HEAD(&rtwvif_link->general_pkt_list);
+
+ rtwvif_link->hit_rule = 0;
+ rtwvif_link->bcn_hit_cond = 0;
+ rtwvif_link->chanctx_assigned = false;
+ rtwvif_link->chanctx_idx = RTW89_CHANCTX_0;
+ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr);
+
+ rcu_read_unlock();
+
+ ret = rtw89_mac_add_vif(rtwdev, rtwvif_link);
+ if (ret)
+ return ret;
+
+ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_START);
+ return 0;
+}
+
+static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ mutex_unlock(&rtwdev->mutex);
+ cancel_work_sync(&rtwvif_link->update_beacon_work);
+ mutex_lock(&rtwdev->mutex);
+
+ rtw89_leave_ps_mode(rtwdev);
+
+ rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_STOP);
+
+ rtw89_mac_remove_vif(rtwdev, rtwvif_link);
+}
+
static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
+ u8 mac_id, port;
int ret = 0;
rtw89_debug(rtwdev, RTW89_DBG_STATE, "add vif %pM type %d, p2p %d\n",
@@ -123,49 +173,58 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
- rtwvif->rtwdev = rtwdev;
- rtwvif->roc.state = RTW89_ROC_IDLE;
- rtwvif->offchan = false;
+ mac_id = rtw89_acquire_mac_id(rtwdev);
+ if (mac_id == RTW89_MAX_MAC_ID_NUM) {
+ ret = -ENOSPC;
+ goto err;
+ }
+
+ port = rtw89_core_acquire_bit_map(rtwdev->hw_port, RTW89_PORT_NUM);
+ if (port == RTW89_PORT_NUM) {
+ ret = -ENOSPC;
+ goto release_macid;
+ }
+
+ rtw89_init_vif(rtwdev, rtwvif, mac_id, port);
+
+ rtw89_core_txq_init(rtwdev, vif->txq);
+
if (!rtw89_rtwvif_in_list(rtwdev, rtwvif))
list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
- INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work);
+ INIT_LIST_HEAD(&rtwvif->mgnt_entry);
+
+ ether_addr_copy(rtwvif->mac_addr, vif->addr);
+
+ rtwvif->offchan = false;
+ rtwvif->roc.state = RTW89_ROC_IDLE;
INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work);
- rtw89_leave_ps_mode(rtwdev);
rtw89_traffic_stats_init(rtwdev, &rtwvif->stats);
- rtw89_vif_type_mapping(vif, false);
- rtwvif->port = rtw89_core_acquire_bit_map(rtwdev->hw_port,
- RTW89_PORT_NUM);
- if (rtwvif->port == RTW89_PORT_NUM) {
- ret = -ENOSPC;
- list_del_init(&rtwvif->list);
- goto out;
- }
- rtwvif->bcn_hit_cond = 0;
- rtwvif->mac_idx = RTW89_MAC_0;
- rtwvif->phy_idx = RTW89_PHY_0;
- rtwvif->chanctx_idx = RTW89_CHANCTX_0;
- rtwvif->chanctx_assigned = false;
- rtwvif->hit_rule = 0;
- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
- ether_addr_copy(rtwvif->mac_addr, vif->addr);
- INIT_LIST_HEAD(&rtwvif->general_pkt_list);
-
- ret = rtw89_mac_add_vif(rtwdev, rtwvif);
- if (ret) {
- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
- list_del_init(&rtwvif->list);
- goto out;
+ rtwvif_link = rtw89_vif_set_link(rtwvif, 0);
+ if (!rtwvif_link) {
+ ret = -EINVAL;
+ goto release_port;
}
- rtw89_core_txq_init(rtwdev, vif->txq);
-
- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_START);
+ ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link);
+ if (ret)
+ goto unset_link;
rtw89_recalc_lps(rtwdev);
-out:
+
+ mutex_unlock(&rtwdev->mutex);
+ return 0;
+
+unset_link:
+ rtw89_vif_unset_link(rtwvif, 0);
+release_port:
+ list_del_init(&rtwvif->list);
+ rtw89_core_release_bit_map(rtwdev->hw_port, port);
+release_macid:
+ rtw89_release_mac_id(rtwdev, mac_id);
+err:
mutex_unlock(&rtwdev->mutex);
return ret;
@@ -175,20 +234,35 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ u8 macid = rtw89_vif_get_main_macid(rtwvif);
+ u8 port = rtw89_vif_get_main_port(rtwvif);
+ struct rtw89_vif_link *rtwvif_link;
rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n",
vif->addr, vif->type, vif->p2p);
- cancel_work_sync(&rtwvif->update_beacon_work);
cancel_delayed_work_sync(&rtwvif->roc.roc_work);
mutex_lock(&rtwdev->mutex);
- rtw89_leave_ps_mode(rtwdev);
- rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_STOP);
- rtw89_mac_remove_vif(rtwdev, rtwvif);
- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
+
+ rtwvif_link = rtwvif->links[0];
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, 0);
+ goto bottom;
+ }
+
+ __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link);
+
+ rtw89_vif_unset_link(rtwvif, 0);
+
+bottom:
list_del_init(&rtwvif->list);
+ rtw89_core_release_bit_map(rtwdev->hw_port, port);
+ rtw89_release_mac_id(rtwdev, macid);
+
rtw89_recalc_lps(rtwdev);
rtw89_enter_ips_by_hwflags(rtwdev);
@@ -311,24 +385,30 @@ static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = {
};
static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, u8 aifsn)
+ struct rtw89_vif_link *rtwvif_link, u8 aifsn)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
+ struct ieee80211_bss_conf *bss_conf;
u8 slot_time;
u8 sifs;
- slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ slot_time = bss_conf->use_short_slot ? 9 : 20;
+
+ rcu_read_unlock();
+
sifs = chan->band_type == RTW89_BAND_2G ? 10 : 16;
return aifsn * slot_time + sifs;
}
static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, u16 ac)
+ struct rtw89_vif_link *rtwvif_link, u16 ac)
{
- struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
+ struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac];
u32 val;
u8 ecw_max, ecw_min;
u8 aifs;
@@ -336,12 +416,12 @@ static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev,
/* 2^ecw - 1 = cw; ecw = log2(cw + 1) */
ecw_max = ilog2(params->cw_max + 1);
ecw_min = ilog2(params->cw_min + 1);
- aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif, params->aifs);
+ aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, params->aifs);
val = FIELD_PREP(FW_EDCA_PARAM_TXOPLMT_MSK, params->txop) |
FIELD_PREP(FW_EDCA_PARAM_CWMAX_MSK, ecw_max) |
FIELD_PREP(FW_EDCA_PARAM_CWMIN_MSK, ecw_min) |
FIELD_PREP(FW_EDCA_PARAM_AIFS_MSK, aifs);
- rtw89_fw_h2c_set_edca(rtwdev, rtwvif, ac_to_fw_idx[ac], val);
+ rtw89_fw_h2c_set_edca(rtwdev, rtwvif_link, ac_to_fw_idx[ac], val);
}
#define R_MUEDCA_ACS_PARAM(acs) {R_AX_MUEDCA_ ## acs ## _PARAM_0, \
@@ -355,9 +435,9 @@ static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS][RTW89_CHIP_GEN_NUM] = {
};
static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, u16 ac)
+ struct rtw89_vif_link *rtwvif_link, u16 ac)
{
- struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
+ struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac];
struct ieee80211_he_mu_edca_param_ac_rec *mu_edca;
int gen = rtwdev->chip->chip_gen;
u8 aifs, aifsn;
@@ -370,32 +450,199 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev,
mu_edca = &params->mu_edca_param_rec;
aifsn = FIELD_GET(GENMASK(3, 0), mu_edca->aifsn);
- aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif, aifsn) : 0;
+ aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, aifsn) : 0;
timer_32us = mu_edca->mu_edca_timer << 8;
val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) |
FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) |
FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs);
- reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen],
+ rtwvif_link->mac_idx);
rtw89_write32(rtwdev, reg, val);
- rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true);
+ rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif_link, true);
}
static void __rtw89_conf_tx(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, u16 ac)
+ struct rtw89_vif_link *rtwvif_link, u16 ac)
{
- ____rtw89_conf_tx_edca(rtwdev, rtwvif, ac);
- ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif, ac);
+ ____rtw89_conf_tx_edca(rtwdev, rtwvif_link, ac);
+ ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif_link, ac);
}
static void rtw89_conf_tx(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
u16 ac;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- __rtw89_conf_tx(rtwdev, rtwvif, ac);
+ __rtw89_conf_tx(rtwdev, rtwvif_link, ac);
+}
+
+static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ bool acquire_macid = false;
+ u8 macid;
+ int ret;
+ int i;
+
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
+ /* for station mode, assign the mac_id from itself */
+ macid = rtw89_vif_get_main_macid(rtwvif);
+ } else {
+ macid = rtw89_acquire_mac_id(rtwdev);
+ if (macid == RTW89_MAX_MAC_ID_NUM)
+ return -ENOSPC;
+
+ acquire_macid = true;
+ }
+
+ rtw89_init_sta(rtwdev, rtwvif, rtwsta, macid);
+
+ for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
+ rtw89_core_txq_init(rtwdev, sta->txq[i]);
+
+ skb_queue_head_init(&rtwsta->roc_queue);
+
+ rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id);
+ if (!rtwsta_link) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ rtwvif_link = rtwsta_link->rtwvif_link;
+
+ ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link);
+ if (ret)
+ goto unset_link;
+
+ if (vif->type == NL80211_IFTYPE_AP || sta->tdls)
+ rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE);
+
+ return 0;
+
+unset_link:
+ rtw89_sta_unset_link(rtwsta, sta->deflink.link_id);
+err:
+ if (acquire_macid)
+ rtw89_release_mac_id(rtwdev, macid);
+
+ return ret;
+}
+
+static int __rtw89_ops_sta_assoc(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ bool station_mode)
+{
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ int ret;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+
+ if (station_mode)
+ rtw89_vif_type_mapping(rtwvif_link, true);
+
+ ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link);
+ if (ret)
+ return ret;
+ }
+
+ rtwdev->total_sta_assoc++;
+ if (sta->tdls)
+ rtwvif->tdls_peer++;
+
+ return 0;
+}
+
+static int __rtw89_ops_sta_disassoc(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ int ret;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ ret = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link);
+ if (ret)
+ return ret;
+ }
+
+ rtwsta->disassoc = true;
+
+ rtwdev->total_sta_assoc--;
+ if (sta->tdls)
+ rtwvif->tdls_peer--;
+
+ return 0;
+}
+
+static int __rtw89_ops_sta_disconnect(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ int ret;
+
+ rtw89_core_free_sta_pending_ba(rtwdev, sta);
+ rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta);
+ rtw89_core_free_sta_pending_roc_tx(rtwdev, sta);
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __rtw89_ops_sta_remove(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ u8 macid = rtw89_sta_get_main_macid(rtwsta);
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ int ret;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ ret = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link);
+ if (ret)
+ return ret;
+
+ rtw89_sta_unset_link(rtwsta, link_id);
+ }
+
+ if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
+ rtw89_release_mac_id(rtwdev, macid);
+ rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE);
+ }
+
+ return 0;
}
static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev,
@@ -412,16 +659,34 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev,
return;
}
- rtw89_vif_type_mapping(vif, true);
+ __rtw89_ops_sta_assoc(rtwdev, vif, sta, true);
+}
+
+static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
+{
+ rtw89_phy_set_bss_color(rtwdev, rtwvif_link);
+ rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link);
+ rtw89_mac_port_update(rtwdev, rtwvif_link);
+ rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link);
+}
+
+static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif)
+{
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
- rtw89_core_sta_assoc(rtwdev, vif, sta);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link);
}
static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u64 changed)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
@@ -429,10 +694,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC) {
if (vif->cfg.assoc) {
rtw89_station_mode_sta_assoc(rtwdev, vif);
- rtw89_phy_set_bss_color(rtwdev, vif);
- rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif);
- rtw89_mac_port_update(rtwdev, rtwvif);
- rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif);
+ __rtw89_ops_bss_assoc(rtwdev, vif);
rtw89_queue_chanctx_work(rtwdev);
} else {
@@ -459,39 +721,49 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw,
u64 changed)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
+ rtwvif_link = rtwvif->links[conf->link_id];
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, conf->link_id);
+ goto out;
+ }
+
if (changed & BSS_CHANGED_BSSID) {
- ether_addr_copy(rtwvif->bssid, conf->bssid);
- rtw89_cam_bssid_changed(rtwdev, rtwvif);
- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
- WRITE_ONCE(rtwvif->sync_bcn_tsf, 0);
+ ether_addr_copy(rtwvif_link->bssid, conf->bssid);
+ rtw89_cam_bssid_changed(rtwdev, rtwvif_link);
+ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
+ WRITE_ONCE(rtwvif_link->sync_bcn_tsf, 0);
}
if (changed & BSS_CHANGED_BEACON)
- rtw89_chip_h2c_update_beacon(rtwdev, rtwvif);
+ rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link);
if (changed & BSS_CHANGED_ERP_SLOT)
- rtw89_conf_tx(rtwdev, rtwvif);
+ rtw89_conf_tx(rtwdev, rtwvif_link);
if (changed & BSS_CHANGED_HE_BSS_COLOR)
- rtw89_phy_set_bss_color(rtwdev, vif);
+ rtw89_phy_set_bss_color(rtwdev, rtwvif_link);
if (changed & BSS_CHANGED_MU_GROUPS)
rtw89_mac_bf_set_gid_table(rtwdev, vif, conf);
if (changed & BSS_CHANGED_P2P_PS)
- rtw89_core_update_p2p_ps(rtwdev, vif);
+ rtw89_core_update_p2p_ps(rtwdev, rtwvif_link, conf);
if (changed & BSS_CHANGED_CQM)
- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
if (changed & BSS_CHANGED_TPE)
- rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true);
+ rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true);
+out:
mutex_unlock(&rtwdev->mutex);
}
@@ -500,12 +772,21 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *link_conf)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
const struct rtw89_chan *chan;
mutex_lock(&rtwdev->mutex);
- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx);
+ rtwvif_link = rtwvif->links[link_conf->link_id];
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, link_conf->link_id);
+ goto out;
+ }
+
+ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
if (chan->band_type == RTW89_BAND_6G) {
mutex_unlock(&rtwdev->mutex);
return -EOPNOTSUPP;
@@ -514,16 +795,18 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
- ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid);
- rtw89_cam_bssid_changed(rtwdev, rtwvif);
- rtw89_mac_port_update(rtwdev, rtwvif);
- rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
- rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_TYPE_CHANGE);
- rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
- rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
- rtw89_chip_rfk_channel(rtwdev, rtwvif);
+ ether_addr_copy(rtwvif_link->bssid, link_conf->bssid);
+ rtw89_cam_bssid_changed(rtwdev, rtwvif_link);
+ rtw89_mac_port_update(rtwdev, rtwvif_link);
+ rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL);
+ rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE);
+ rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true);
+ rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
+ rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
rtw89_queue_chanctx_work(rtwdev);
+
+out:
mutex_unlock(&rtwdev->mutex);
return 0;
@@ -534,12 +817,24 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
mutex_lock(&rtwdev->mutex);
- rtw89_mac_stop_ap(rtwdev, rtwvif);
- rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
- rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
+
+ rtwvif_link = rtwvif->links[link_conf->link_id];
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, link_conf->link_id);
+ goto out;
+ }
+
+ rtw89_mac_stop_ap(rtwdev, rtwvif_link);
+ rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL);
+ rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true);
+
+out:
mutex_unlock(&rtwdev->mutex);
}
@@ -547,10 +842,13 @@ static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
bool set)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
- ieee80211_queue_work(rtwdev->hw, &rtwvif->update_beacon_work);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work);
return 0;
}
@@ -561,15 +859,29 @@ static int rtw89_ops_conf_tx(struct ieee80211_hw *hw,
const struct ieee80211_tx_queue_params *params)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
+ int ret = 0;
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
- rtwvif->tx_params[ac] = *params;
- __rtw89_conf_tx(rtwdev, rtwvif, ac);
+
+ rtwvif_link = rtwvif->links[link_id];
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, link_id);
+ ret = -ENOLINK;
+ goto out;
+ }
+
+ rtwvif_link->tx_params[ac] = *params;
+ __rtw89_conf_tx(rtwdev, rtwvif_link, ac);
+
+out:
mutex_unlock(&rtwdev->mutex);
- return 0;
+ return ret;
}
static int __rtw89_ops_sta_state(struct ieee80211_hw *hw,
@@ -582,26 +894,26 @@ static int __rtw89_ops_sta_state(struct ieee80211_hw *hw,
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE)
- return rtw89_core_sta_add(rtwdev, vif, sta);
+ return __rtw89_ops_sta_add(rtwdev, vif, sta);
if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC) {
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
return 0; /* defer to bss_info_changed to have vif info */
- return rtw89_core_sta_assoc(rtwdev, vif, sta);
+ return __rtw89_ops_sta_assoc(rtwdev, vif, sta, false);
}
if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH)
- return rtw89_core_sta_disassoc(rtwdev, vif, sta);
+ return __rtw89_ops_sta_disassoc(rtwdev, vif, sta);
if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_NONE)
- return rtw89_core_sta_disconnect(rtwdev, vif, sta);
+ return __rtw89_ops_sta_disconnect(rtwdev, vif, sta);
if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)
- return rtw89_core_sta_remove(rtwdev, vif, sta);
+ return __rtw89_ops_sta_remove(rtwdev, vif, sta);
return 0;
}
@@ -667,7 +979,8 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
{
struct rtw89_dev *rtwdev = hw->priv;
struct ieee80211_sta *sta = params->sta;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
u16 tid = params->tid;
struct ieee80211_txq *txq = sta->txq[tid];
struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv;
@@ -681,7 +994,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
mutex_lock(&rtwdev->mutex);
clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
clear_bit(tid, rtwsta->ampdu_map);
- rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
+ rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta);
mutex_unlock(&rtwdev->mutex);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
@@ -692,7 +1005,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
rtwsta->ampdu_params[tid].amsdu = params->amsdu;
set_bit(tid, rtwsta->ampdu_map);
rtw89_leave_ps_mode(rtwdev);
- rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta);
+ rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta);
mutex_unlock(&rtwdev->mutex);
break;
case IEEE80211_AMPDU_RX_START:
@@ -720,7 +1033,7 @@ static int rtw89_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
- rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0);
+ rtw89_mac_update_rts_threshold(rtwdev);
mutex_unlock(&rtwdev->mutex);
return 0;
@@ -731,9 +1044,14 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_sta_link *rtwsta_link;
- sinfo->txrate = rtwsta->ra_report.txrate;
+ rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
+ if (unlikely(!rtwsta_link))
+ return;
+
+ sinfo->txrate = rtwsta_link->ra_report.txrate;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
@@ -743,7 +1061,7 @@ void __rtw89_drop_packets(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
struct rtw89_vif *rtwvif;
if (vif) {
- rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ rtwvif = vif_to_rtwvif(vif);
rtw89_mac_pkt_drop_vif(rtwdev, rtwvif);
} else {
rtw89_for_each_rtwvif(rtwdev, rtwvif)
@@ -777,14 +1095,20 @@ struct rtw89_iter_bitrate_mask_data {
static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw89_iter_bitrate_mask_data *br_data = data;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif);
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
if (vif != br_data->vif || vif->p2p)
return;
- rtwsta->use_cfg_mask = true;
- rtwsta->mask = *br_data->mask;
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwsta_link->use_cfg_mask = true;
+ rtwsta_link->mask = *br_data->mask;
+ }
+
rtw89_phy_ra_update_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
}
@@ -854,10 +1178,20 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw,
const u8 *mac_addr)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
mutex_lock(&rtwdev->mutex);
- rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, false);
+
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "sw scan start: find no link on HW-0\n");
+ goto out;
+ }
+
+ rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, false);
+
+out:
mutex_unlock(&rtwdev->mutex);
}
@@ -865,9 +1199,20 @@ static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
mutex_lock(&rtwdev->mutex);
- rtw89_core_scan_complete(rtwdev, vif, false);
+
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "sw scan complete: find no link on HW-0\n");
+ goto out;
+ }
+
+ rtw89_core_scan_complete(rtwdev, rtwvif_link, false);
+
+out:
mutex_unlock(&rtwdev->mutex);
}
@@ -884,22 +1229,35 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
- int ret = 0;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
+ int ret;
if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
return 1;
- if (rtwdev->scanning || rtwvif->offchan)
- return -EBUSY;
-
mutex_lock(&rtwdev->mutex);
- rtw89_hw_scan_start(rtwdev, vif, req);
- ret = rtw89_hw_scan_offload(rtwdev, vif, true);
+
+ if (rtwdev->scanning || rtwvif->offchan) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "hw scan: find no link on HW-0\n");
+ ret = -ENOLINK;
+ goto out;
+ }
+
+ rtw89_hw_scan_start(rtwdev, rtwvif_link, req);
+ ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true);
if (ret) {
- rtw89_hw_scan_abort(rtwdev, vif);
+ rtw89_hw_scan_abort(rtwdev, rtwvif_link);
rtw89_err(rtwdev, "HW scan failed with status: %d\n", ret);
}
+
+out:
mutex_unlock(&rtwdev->mutex);
return ret;
@@ -909,6 +1267,8 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
return;
@@ -917,14 +1277,25 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
return;
mutex_lock(&rtwdev->mutex);
- rtw89_hw_scan_abort(rtwdev, vif);
+
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev, "cancel hw scan: find no link on HW-0\n");
+ goto out;
+ }
+
+ rtw89_hw_scan_abort(rtwdev, rtwvif_link);
+
+out:
mutex_unlock(&rtwdev->mutex);
}
static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u32 changed)
+ struct ieee80211_link_sta *link_sta,
+ u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct rtw89_dev *rtwdev = hw->priv;
rtw89_phy_ra_update_sta(rtwdev, sta, changed);
@@ -970,11 +1341,24 @@ static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
int ret;
mutex_lock(&rtwdev->mutex);
- ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif, ctx);
+
+ rtwvif_link = rtwvif->links[link_conf->link_id];
+ if (unlikely(!rtwvif_link)) {
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, link_conf->link_id);
+ ret = -ENOLINK;
+ goto out;
+ }
+
+ ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, ctx);
+
+out:
mutex_unlock(&rtwdev->mutex);
return ret;
@@ -986,10 +1370,21 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx)
{
struct rtw89_dev *rtwdev = hw->priv;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
mutex_lock(&rtwdev->mutex);
- rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif, ctx);
+
+ rtwvif_link = rtwvif->links[link_conf->link_id];
+ if (unlikely(!rtwvif_link)) {
+ mutex_unlock(&rtwdev->mutex);
+ rtw89_err(rtwdev,
+ "%s: rtwvif link (link_id %u) is not active\n",
+ __func__, link_conf->link_id);
+ return;
+ }
+
+ rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, ctx);
mutex_unlock(&rtwdev->mutex);
}
@@ -1003,7 +1398,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw,
struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
struct rtw89_roc *roc = &rtwvif->roc;
- if (!vif)
+ if (!rtwvif)
return -EINVAL;
mutex_lock(&rtwdev->mutex);
@@ -1053,8 +1448,8 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw,
static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta)
{
struct cfg80211_tid_config *tid_config = data;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_dev *rtwdev = rtwsta->rtwvif->rtwdev;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
rtw89_core_set_tid_config(rtwdev, sta, tid_config);
}
@@ -1203,7 +1598,7 @@ const struct ieee80211_ops rtw89_ops = {
.remain_on_channel = rtw89_ops_remain_on_channel,
.cancel_remain_on_channel = rtw89_ops_cancel_remain_on_channel,
.set_sar_specs = rtw89_ops_set_sar_specs,
- .sta_rc_update = rtw89_ops_sta_rc_update,
+ .link_sta_rc_update = rtw89_ops_sta_rc_update,
.set_tid_config = rtw89_ops_set_tid_config,
#ifdef CONFIG_PM
.suspend = rtw89_ops_suspend,
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index 31f0a5225b11..f7a396c8a3cd 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -773,7 +773,7 @@ static int dmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
return ret;
}
- ret = rtw89_mac_preload_init(rtwdev, RTW89_MAC_0, rtwdev->mac.qta_mode);
+ ret = rtw89_mac_preload_init(rtwdev, mac_idx, rtwdev->mac.qta_mode);
if (ret) {
rtw89_err(rtwdev, "[ERR]preload init %d\n", ret);
return ret;
@@ -2091,13 +2091,13 @@ static int rtw89_mac_init_bfee_be(struct rtw89_dev *rtwdev, u8 mac_idx)
}
static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1;
- u8 mac_idx = rtwvif->mac_idx;
- u8 port_sel = rtwvif->port;
+ struct ieee80211_link_sta *link_sta;
+ u8 mac_idx = rtwvif_link->mac_idx;
+ u8 port_sel = rtwvif_link->port;
u8 sound_dim = 3, t;
u8 *phy_cap;
u32 reg;
@@ -2108,7 +2108,10 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev,
if (ret)
return ret;
- phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info;
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info;
if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) ||
(phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) {
@@ -2119,11 +2122,11 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev,
sound_dim = min(sound_dim, t);
}
- if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) ||
- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
- ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
- stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK);
- t = u32_get_bits(sta->deflink.vht_cap.cap,
+ if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) ||
+ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
+ ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
+ stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK);
+ t = u32_get_bits(link_sta->vht_cap.cap,
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
sound_dim = min(sound_dim, t);
}
@@ -2131,6 +2134,8 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev,
nc = min(nc, sound_dim);
nr = min(nr, sound_dim);
+ rcu_read_unlock();
+
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL);
@@ -2155,12 +2160,12 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev,
}
static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M);
- u8 mac_idx = rtwvif->mac_idx;
+ struct ieee80211_link_sta *link_sta;
+ u8 mac_idx = rtwvif_link->mac_idx;
int ret;
u32 reg;
@@ -2168,22 +2173,28 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev,
if (ret)
return ret;
- if (sta->deflink.he_cap.has_he) {
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+
+ if (link_sta->he_cap.has_he) {
rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) |
BIT(RTW89_MAC_BF_RRSC_HE_MSC3) |
BIT(RTW89_MAC_BF_RRSC_HE_MSC5));
}
- if (sta->deflink.vht_cap.vht_supported) {
+ if (link_sta->vht_cap.vht_supported) {
rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) |
BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) |
BIT(RTW89_MAC_BF_RRSC_VHT_MSC5));
}
- if (sta->deflink.ht_cap.ht_supported) {
+ if (link_sta->ht_cap.ht_supported) {
rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) |
BIT(RTW89_MAC_BF_RRSC_HT_MSC3) |
BIT(RTW89_MAC_BF_RRSC_HT_MSC5));
}
+ rcu_read_unlock();
+
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL);
rtw89_write32_clr(rtwdev, reg, B_BE_BFMEE_CSI_FORCE_RETE_EN);
@@ -2195,17 +2206,25 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev,
}
static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ struct ieee80211_link_sta *link_sta;
+ bool has_beamformer_cap;
+
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta);
+
+ rcu_read_unlock();
- if (rtw89_sta_has_beamformer_cap(sta)) {
+ if (has_beamformer_cap) {
rtw89_debug(rtwdev, RTW89_DBG_BF,
"initialize bfee for new association\n");
- rtw89_mac_init_bfee_be(rtwdev, rtwvif->mac_idx);
- rtw89_mac_set_csi_para_reg_be(rtwdev, vif, sta);
- rtw89_mac_csi_rrsc_be(rtwdev, vif, sta);
+ rtw89_mac_init_bfee_be(rtwdev, rtwvif_link->mac_idx);
+ rtw89_mac_set_csi_para_reg_be(rtwdev, rtwvif_link, rtwsta_link);
+ rtw89_mac_csi_rrsc_be(rtwdev, rtwvif_link, rtwsta_link);
}
}
@@ -2581,9 +2600,11 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.fwdl_enable_wcpu = rtw89_mac_fwdl_enable_wcpu_be,
.fwdl_get_status = fwdl_get_status_be,
.fwdl_check_path_ready = rtw89_fwdl_check_path_ready_be,
+ .fwdl_secure_idmem_share_mode = NULL,
.parse_efuse_map = rtw89_parse_efuse_map_be,
.parse_phycap_map = rtw89_parse_phycap_map_be,
.cnv_efuse_state = rtw89_cnv_efuse_state_be,
+ .efuse_read_fw_secure = rtw89_efuse_read_fw_secure_be,
.cfg_plt = rtw89_mac_cfg_plt_be,
.get_plt_cnt = rtw89_mac_get_plt_cnt_be,
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 5aef7fa37878..f923bec03d41 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -2358,13 +2358,15 @@ static int rtw89_pci_deglitch_setting(struct rtw89_dev *rtwdev)
return 0;
}
-static void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev)
+static void rtw89_pci_disable_eq_ax(struct rtw89_dev *rtwdev)
{
u16 g1_oobs, g2_oobs;
u32 backup_aspm;
u32 phy_offset;
+ u16 offset_cal;
u16 oobs_val;
int ret;
+ u8 gen;
if (rtwdev->chip->chip_id != RTL8852C)
return;
@@ -2400,6 +2402,28 @@ static void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev)
rtw89_write16_set(rtwdev, R_RAC_DIRECT_OFFSET_G2 + RAC_ANA09 * RAC_MULT,
BAC_OOBS_SEL);
+ /* offset K */
+ for (gen = 1; gen <= 2; gen++) {
+ phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_G1 :
+ R_RAC_DIRECT_OFFSET_G2;
+
+ rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT,
+ B_PCIE_BIT_RD_SEL);
+ }
+
+ offset_cal = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_G1 +
+ RAC_ANA1F * RAC_MULT, OFFSET_CAL_MASK);
+
+ for (gen = 1; gen <= 2; gen++) {
+ phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_G1 :
+ R_RAC_DIRECT_OFFSET_G2;
+
+ rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA0B * RAC_MULT,
+ MANUAL_LVL_MASK, offset_cal);
+ rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT,
+ OFFSET_CAL_MODE);
+ }
+
out:
rtw89_write32(rtwdev, R_AX_PCIE_MIX_CFG_V1, backup_aspm);
}
@@ -2647,9 +2671,10 @@ static void rtw89_pci_clr_idx_all_ax(struct rtw89_dev *rtwdev)
static int rtw89_pci_poll_txdma_ch_idle_ax(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
- u32 ret, check, dma_busy;
u32 dma_busy1 = info->dma_busy1.addr;
u32 dma_busy2 = info->dma_busy2_reg;
+ u32 check, dma_busy;
+ int ret;
check = info->dma_busy1.mask;
@@ -2674,8 +2699,9 @@ static int rtw89_pci_poll_txdma_ch_idle_ax(struct rtw89_dev *rtwdev)
static int rtw89_pci_poll_rxdma_ch_idle_ax(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
- u32 ret, check, dma_busy;
u32 dma_busy3 = info->dma_busy3_reg;
+ u32 check, dma_busy;
+ int ret;
check = B_AX_RXQ_BUSY | B_AX_RPQ_BUSY;
@@ -3758,19 +3784,16 @@ static void rtw89_pci_free_irq(struct rtw89_dev *rtwdev,
pci_free_irq_vectors(pdev);
}
-static u16 gray_code_to_bin(u16 gray_code, u32 bit_num)
+static u16 gray_code_to_bin(u16 gray_code)
{
- u16 bin = 0, gray_bit;
- u32 bit_idx;
+ u16 binary = gray_code;
- for (bit_idx = 0; bit_idx < bit_num; bit_idx++) {
- gray_bit = (gray_code >> bit_idx) & 0x1;
- if (bit_num - bit_idx > 1)
- gray_bit ^= (gray_code >> (bit_idx + 1)) & 0x1;
- bin |= (gray_bit << bit_idx);
+ while (gray_code) {
+ gray_code >>= 1;
+ binary ^= gray_code;
}
- return bin;
+ return binary;
}
static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev)
@@ -3806,7 +3829,7 @@ static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev)
val16 = rtw89_read16_mask(rtwdev,
phy_offset + RAC_ANA1F * RAC_MULT,
FILTER_OUT_EQ_MASK);
- val16 = gray_code_to_bin(val16, hweight16(val16));
+ val16 = gray_code_to_bin(val16);
filter_out_val = rtw89_read16(rtwdev, phy_offset + RAC_ANA24 *
RAC_MULT);
filter_out_val &= ~REG_FILTER_OUT_MASK;
@@ -4188,6 +4211,36 @@ static int rtw89_pci_napi_poll(struct napi_struct *napi, int budget)
return work_done;
}
+static
+void rtw89_check_pci_ssid_quirks(struct rtw89_dev *rtwdev,
+ struct pci_dev *pdev,
+ const struct rtw89_pci_ssid_quirk *ssid_quirks)
+{
+ int i;
+
+ if (!ssid_quirks)
+ return;
+
+ for (i = 0; i < 200; i++, ssid_quirks++) {
+ if (ssid_quirks->vendor == 0 && ssid_quirks->device == 0)
+ break;
+
+ if (ssid_quirks->vendor != pdev->vendor ||
+ ssid_quirks->device != pdev->device ||
+ ssid_quirks->subsystem_vendor != pdev->subsystem_vendor ||
+ ssid_quirks->subsystem_device != pdev->subsystem_device)
+ continue;
+
+ bitmap_or(rtwdev->quirks, rtwdev->quirks, &ssid_quirks->bitmap,
+ NUM_OF_RTW89_QUIRKS);
+ rtwdev->custid = ssid_quirks->custid;
+ break;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_HCI, "quirks=%*ph custid=%d\n",
+ (int)sizeof(rtwdev->quirks), rtwdev->quirks, rtwdev->custid);
+}
+
static int __maybe_unused rtw89_pci_suspend(struct device *dev)
{
struct ieee80211_hw *hw = dev_get_drvdata(dev);
@@ -4222,6 +4275,17 @@ static void rtw89_pci_l2_hci_ldo(struct rtw89_dev *rtwdev)
RTW89_PCIE_BIT_CFG_RST_MSTATE);
}
+void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume)
+{
+ if (resume)
+ rtw89_pci_cfg_dac(rtwdev);
+
+ rtw89_pci_disable_eq(rtwdev);
+ rtw89_pci_filter_out(rtwdev);
+ rtw89_pci_link_cfg(rtwdev);
+ rtw89_pci_l1ss_cfg(rtwdev);
+}
+
static int __maybe_unused rtw89_pci_resume(struct device *dev)
{
struct ieee80211_hw *hw = dev_get_drvdata(dev);
@@ -4243,11 +4307,8 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
B_AX_SEL_REQ_ENTR_L1);
}
rtw89_pci_l2_hci_ldo(rtwdev);
- rtw89_pci_disable_eq(rtwdev);
- rtw89_pci_cfg_dac(rtwdev);
- rtw89_pci_filter_out(rtwdev);
- rtw89_pci_link_cfg(rtwdev);
- rtw89_pci_l1ss_cfg(rtwdev);
+
+ rtw89_pci_basic_cfg(rtwdev, true);
return 0;
}
@@ -4280,6 +4341,8 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
.aspm_set = rtw89_pci_aspm_set_ax,
.clkreq_set = rtw89_pci_clkreq_set_ax,
.l1ss_set = rtw89_pci_l1ss_set_ax,
+
+ .disable_eq = rtw89_pci_disable_eq_ax,
};
EXPORT_SYMBOL(rtw89_pci_gen_ax);
@@ -4352,6 +4415,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rtwdev->hci.cpwm_addr = pci_info->cpwm_addr;
rtw89_check_quirks(rtwdev, info->quirks);
+ rtw89_check_pci_ssid_quirks(rtwdev, pdev, pci_info->ssid_quirks);
SET_IEEE80211_DEV(rtwdev->hw, &pdev->dev);
@@ -4379,10 +4443,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_clear_resource;
}
- rtw89_pci_disable_eq(rtwdev);
- rtw89_pci_filter_out(rtwdev);
- rtw89_pci_link_cfg(rtwdev);
- rtw89_pci_l1ss_cfg(rtwdev);
+ rtw89_pci_basic_cfg(rtwdev, false);
ret = rtw89_core_napi_init(rtwdev);
if (ret) {
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index 48c3ab735db2..b68e2d82eea9 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -18,11 +18,16 @@
#define BAC_OOBS_SEL BIT(4)
#define RAC_ANA0A 0x0A
#define B_BAC_EQ_SEL BIT(5)
+#define RAC_ANA0B 0x0B
+#define MANUAL_LVL_MASK GENMASK(8, 5)
#define RAC_ANA0C 0x0C
#define B_PCIE_BIT_PSAVE BIT(15)
#define RAC_ANA0D 0x0D
+#define OFFSET_CAL_MODE BIT(13)
#define BAC_RX_TEST_EN BIT(6)
#define RAC_ANA10 0x10
+#define ADDR_SEL_MASK GENMASK(9, 4)
+#define ADDR_SEL_VAL 0x3C
#define ADDR_SEL_PINOUT_DIS_VAL 0x3C4
#define B_PCIE_BIT_PINOUT_DIS BIT(3)
#define RAC_REG_REV2 0x1B
@@ -38,6 +43,7 @@
#define RAC_ANA1E_G2_VAL 0x6EEA
#define RAC_ANA1F 0x1F
#define OOBS_LEVEL_MASK GENMASK(12, 8)
+#define OFFSET_CAL_MASK GENMASK(7, 4)
#define RAC_ANA24 0x24
#define B_AX_DEGLITCH GENMASK(11, 8)
#define RAC_ANA26 0x26
@@ -134,6 +140,11 @@
#define REG_FILTER_OUT_MASK GENMASK(6, 2)
#define RAC_MULT 2
+#define R_RAC_DIRECT_OFFSET_BE_LANE0_G1 0x3800
+#define R_RAC_DIRECT_OFFSET_BE_LANE1_G1 0x3880
+#define R_RAC_DIRECT_OFFSET_BE_LANE0_G2 0x3900
+#define R_RAC_DIRECT_OFFSET_BE_LANE1_G2 0x3980
+
#define RTW89_PCI_WR_RETRY_CNT 20
/* Interrupts */
@@ -299,6 +310,7 @@
#define B_BE_L1SS_TIMEOUT_CTRL BIT(18)
#define B_BE_ASPM_CTRL_L1 BIT(17)
#define B_BE_ASPM_CTRL_L0 BIT(16)
+#define B_BE_RTK_ASPM_CTRL_MASK GENMASK(17, 16)
#define B_BE_XFER_PENDING_FW BIT(11)
#define B_BE_XFER_PENDING BIT(10)
#define B_BE_REQ_EXIT_L1 BIT(9)
@@ -1276,6 +1288,21 @@ struct rtw89_pci_gen_def {
void (*aspm_set)(struct rtw89_dev *rtwdev, bool enable);
void (*clkreq_set)(struct rtw89_dev *rtwdev, bool enable);
void (*l1ss_set)(struct rtw89_dev *rtwdev, bool enable);
+
+ void (*disable_eq)(struct rtw89_dev *rtwdev);
+};
+
+#define RTW89_PCI_SSID(v, d, ssv, ssd, cust) \
+ .vendor = v, .device = d, .subsystem_vendor = ssv, .subsystem_device = ssd, \
+ .custid = RTW89_CUSTID_ ##cust
+
+struct rtw89_pci_ssid_quirk {
+ unsigned short vendor;
+ unsigned short device;
+ unsigned short subsystem_vendor;
+ unsigned short subsystem_device;
+ enum rtw89_custid custid;
+ unsigned long bitmap; /* bitmap of rtw89_quirks */
};
struct rtw89_pci_info {
@@ -1331,6 +1358,8 @@ struct rtw89_pci_info {
void (*recognize_intrs)(struct rtw89_dev *rtwdev,
struct rtw89_pci *rtwpci,
struct rtw89_pci_isrs *isrs);
+
+ const struct rtw89_pci_ssid_quirk *ssid_quirks;
};
struct rtw89_pci_tx_data {
@@ -1600,6 +1629,7 @@ struct pci_device_id;
int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
void rtw89_pci_remove(struct pci_dev *pdev);
+void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume);
void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev);
int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en);
int rtw89_pci_ltr_set_v1(struct rtw89_dev *rtwdev, bool en);
@@ -1766,4 +1796,13 @@ static inline int rtw89_pci_poll_txdma_ch_idle(struct rtw89_dev *rtwdev)
return gen_def->poll_txdma_ch_idle(rtwdev);
}
+
+static inline void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_pci_info *info = rtwdev->pci_info;
+ const struct rtw89_pci_gen_def *gen_def = info->gen_def;
+
+ gen_def->disable_eq(rtwdev);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c
index 7cc328222965..34154506f5d4 100644
--- a/drivers/net/wireless/realtek/rtw89/pci_be.c
+++ b/drivers/net/wireless/realtek/rtw89/pci_be.c
@@ -550,6 +550,79 @@ static int rtw89_pci_lv1rst_start_dma_be(struct rtw89_dev *rtwdev)
return 0;
}
+static void rtw89_pci_disable_eq_be(struct rtw89_dev *rtwdev)
+{
+ u32 backup_aspm, phy_offset;
+ u16 oobs_val, offset_cal;
+ u16 g1_oobs, g2_oobs;
+ u8 gen;
+
+ if (rtwdev->chip->chip_id != RTL8922A)
+ return;
+
+ g1_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 +
+ RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL);
+ g2_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G2 +
+ RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL);
+ if (g1_oobs && g2_oobs)
+ return;
+
+ backup_aspm = rtw89_read32(rtwdev, R_BE_PCIE_MIX_CFG);
+ rtw89_write32_clr(rtwdev, R_BE_PCIE_MIX_CFG, B_BE_RTK_ASPM_CTRL_MASK);
+
+ /* offset K */
+ for (gen = 1; gen <= 2; gen++) {
+ phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 :
+ R_RAC_DIRECT_OFFSET_BE_LANE0_G2;
+
+ rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT,
+ B_PCIE_BIT_RD_SEL);
+ }
+
+ offset_cal = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 +
+ RAC_ANA1F * RAC_MULT, OFFSET_CAL_MASK);
+
+ for (gen = 1; gen <= 2; gen++) {
+ phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 :
+ R_RAC_DIRECT_OFFSET_BE_LANE0_G2;
+
+ rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA0B * RAC_MULT,
+ MANUAL_LVL_MASK, offset_cal);
+ rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT,
+ OFFSET_CAL_MODE);
+ }
+
+ /* OOBS */
+ for (gen = 1; gen <= 2; gen++) {
+ phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 :
+ R_RAC_DIRECT_OFFSET_BE_LANE0_G2;
+
+ rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT,
+ BAC_RX_TEST_EN);
+ rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT,
+ ADDR_SEL_MASK, ADDR_SEL_VAL);
+ rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT,
+ B_PCIE_BIT_PINOUT_DIS);
+ rtw89_write16_set(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT,
+ B_PCIE_BIT_RD_SEL);
+ }
+
+ oobs_val = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 +
+ RAC_ANA1F * RAC_MULT, OOBS_LEVEL_MASK);
+
+ for (gen = 1; gen <= 2; gen++) {
+ phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 :
+ R_RAC_DIRECT_OFFSET_BE_LANE0_G2;
+
+ rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA03 * RAC_MULT,
+ OOBS_SEN_MASK, oobs_val);
+ rtw89_write16_set(rtwdev, phy_offset + RAC_ANA09 * RAC_MULT,
+ BAC_OOBS_SEL);
+ }
+
+ rtw89_write32(rtwdev, R_BE_PCIE_MIX_CFG, backup_aspm);
+}
+
static int __maybe_unused rtw89_pci_suspend_be(struct device *dev)
{
struct ieee80211_hw *hw = dev_get_drvdata(dev);
@@ -584,6 +657,8 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev)
rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN);
rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR);
+ rtw89_pci_basic_cfg(rtwdev, true);
+
return 0;
}
@@ -614,5 +689,7 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_be = {
.aspm_set = rtw89_pci_aspm_set_be,
.clkreq_set = rtw89_pci_clkreq_set_be,
.l1ss_set = rtw89_pci_l1ss_set_be,
+
+ .disable_eq = rtw89_pci_disable_eq_be,
};
EXPORT_SYMBOL(rtw89_pci_gen_be);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index c7165e757842..f24aca663cf0 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -75,12 +75,12 @@ static u64 get_mcs_ra_mask(u16 mcs_map, u8 highest_mcs, u8 gap)
return ra_mask;
}
-static u64 get_he_ra_mask(struct ieee80211_sta *sta)
+static u64 get_he_ra_mask(struct ieee80211_link_sta *link_sta)
{
- struct ieee80211_sta_he_cap cap = sta->deflink.he_cap;
+ struct ieee80211_sta_he_cap cap = link_sta->he_cap;
u16 mcs_map;
- switch (sta->deflink.bandwidth) {
+ switch (link_sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
if (cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
@@ -118,14 +118,14 @@ static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss)
return mask;
}
-static u64 get_eht_ra_mask(struct ieee80211_sta *sta)
+static u64 get_eht_ra_mask(struct ieee80211_link_sta *link_sta)
{
- struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
+ struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap;
struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz;
struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss;
- u8 *he_phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info;
+ u8 *he_phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info;
- switch (sta->deflink.bandwidth) {
+ switch (link_sta->bandwidth) {
case IEEE80211_STA_RX_BW_320:
mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320;
/* MCS 9, 11, 13 */
@@ -195,15 +195,16 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak)
return ra_mask;
}
-static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link,
+ struct ieee80211_link_sta *link_sta,
const struct rtw89_chan *chan)
{
- struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
- struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
+ struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask;
enum nl80211_band band;
u64 cfg_mask;
- if (!rtwsta->use_cfg_mask)
+ if (!rtwsta_link->use_cfg_mask)
return -1;
switch (chan->band_type) {
@@ -227,17 +228,17 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtw
return -1;
}
- if (sta->deflink.he_cap.has_he) {
+ if (link_sta->he_cap.has_he) {
cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[0],
RA_MASK_HE_1SS_RATES);
cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[1],
RA_MASK_HE_2SS_RATES);
- } else if (sta->deflink.vht_cap.vht_supported) {
+ } else if (link_sta->vht_cap.vht_supported) {
cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0],
RA_MASK_VHT_1SS_RATES);
cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1],
RA_MASK_VHT_2SS_RATES);
- } else if (sta->deflink.ht_cap.ht_supported) {
+ } else if (link_sta->ht_cap.ht_supported) {
cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0],
RA_MASK_HT_1SS_RATES);
cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1],
@@ -261,17 +262,17 @@ rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES,
RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES};
static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
- struct rtw89_sta *rtwsta,
+ struct rtw89_sta_link *rtwsta_link,
const struct rtw89_chan *chan,
bool *fix_giltf_en, u8 *fix_giltf)
{
- struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
+ struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask;
u8 band = chan->band_type;
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
u8 he_gi = mask->control[nl_band].he_gi;
u8 he_ltf = mask->control[nl_band].he_ltf;
- if (!rtwsta->use_cfg_mask)
+ if (!rtwsta_link->use_cfg_mask)
return;
if (he_ltf == 2 && he_gi == 2) {
@@ -295,17 +296,17 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
}
static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
- struct ieee80211_sta *sta, bool csi)
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ struct ieee80211_link_sta *link_sta,
+ bool p2p, bool csi)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
- struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
- struct rtw89_ra_info *ra = &rtwsta->ra;
+ struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern;
+ struct rtw89_ra_info *ra = &rtwsta_link->ra;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif);
+ rtwvif_link->chanctx_idx);
const u64 *high_rate_masks = rtw89_ra_mask_ht_rates;
- u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi);
+ u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi);
u64 ra_mask = 0;
u64 ra_mask_bak;
u8 mode = 0;
@@ -320,65 +321,65 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
memset(ra, 0, sizeof(*ra));
/* Set the ra mask from sta's capability */
- if (sta->deflink.eht_cap.has_eht) {
+ if (link_sta->eht_cap.has_eht) {
mode |= RTW89_RA_MODE_EHT;
- ra_mask |= get_eht_ra_mask(sta);
+ ra_mask |= get_eht_ra_mask(link_sta);
high_rate_masks = rtw89_ra_mask_eht_rates;
- } else if (sta->deflink.he_cap.has_he) {
+ } else if (link_sta->he_cap.has_he) {
mode |= RTW89_RA_MODE_HE;
csi_mode = RTW89_RA_RPT_MODE_HE;
- ra_mask |= get_he_ra_mask(sta);
+ ra_mask |= get_he_ra_mask(link_sta);
high_rate_masks = rtw89_ra_mask_he_rates;
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[2] &
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[2] &
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
stbc_en = 1;
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] &
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
ldpc_en = 1;
- rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, chan, &fix_giltf_en, &fix_giltf);
- } else if (sta->deflink.vht_cap.vht_supported) {
- u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
+ rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, chan, &fix_giltf_en, &fix_giltf);
+ } else if (link_sta->vht_cap.vht_supported) {
+ u16 mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map);
mode |= RTW89_RA_MODE_VHT;
csi_mode = RTW89_RA_RPT_MODE_VHT;
/* MCS9 (non-20MHz), MCS8, MCS7 */
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
ra_mask |= get_mcs_ra_mask(mcs_map, 8, 1);
else
ra_mask |= get_mcs_ra_mask(mcs_map, 9, 1);
high_rate_masks = rtw89_ra_mask_vht_rates;
- if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
+ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
stbc_en = 1;
- if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
+ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
ldpc_en = 1;
- } else if (sta->deflink.ht_cap.ht_supported) {
+ } else if (link_sta->ht_cap.ht_supported) {
mode |= RTW89_RA_MODE_HT;
csi_mode = RTW89_RA_RPT_MODE_HT;
- ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 48) |
- ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 36) |
- ((u64)sta->deflink.ht_cap.mcs.rx_mask[1] << 24) |
- ((u64)sta->deflink.ht_cap.mcs.rx_mask[0] << 12);
+ ra_mask |= ((u64)link_sta->ht_cap.mcs.rx_mask[3] << 48) |
+ ((u64)link_sta->ht_cap.mcs.rx_mask[2] << 36) |
+ ((u64)link_sta->ht_cap.mcs.rx_mask[1] << 24) |
+ ((u64)link_sta->ht_cap.mcs.rx_mask[0] << 12);
high_rate_masks = rtw89_ra_mask_ht_rates;
- if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
+ if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
stbc_en = 1;
- if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
+ if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
ldpc_en = 1;
}
switch (chan->band_type) {
case RTW89_BAND_2G:
- ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ];
- if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xf)
+ ra_mask |= link_sta->supp_rates[NL80211_BAND_2GHZ];
+ if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xf)
mode |= RTW89_RA_MODE_CCK;
- if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xff0)
+ if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xff0)
mode |= RTW89_RA_MODE_OFDM;
break;
case RTW89_BAND_5G:
- ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4;
+ ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_5GHZ] << 4;
mode |= RTW89_RA_MODE_OFDM;
break;
case RTW89_BAND_6G:
- ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_6GHZ] << 4;
+ ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_6GHZ] << 4;
mode |= RTW89_RA_MODE_OFDM;
break;
default:
@@ -405,48 +406,48 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0);
ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak);
- ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan);
+ ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan);
- switch (sta->deflink.bandwidth) {
+ switch (link_sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
bw_mode = RTW89_CHANNEL_WIDTH_160;
- sgi = sta->deflink.vht_cap.vht_supported &&
- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160);
+ sgi = link_sta->vht_cap.vht_supported &&
+ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160);
break;
case IEEE80211_STA_RX_BW_80:
bw_mode = RTW89_CHANNEL_WIDTH_80;
- sgi = sta->deflink.vht_cap.vht_supported &&
- (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
+ sgi = link_sta->vht_cap.vht_supported &&
+ (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
break;
case IEEE80211_STA_RX_BW_40:
bw_mode = RTW89_CHANNEL_WIDTH_40;
- sgi = sta->deflink.ht_cap.ht_supported &&
- (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
+ sgi = link_sta->ht_cap.ht_supported &&
+ (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
break;
default:
bw_mode = RTW89_CHANNEL_WIDTH_20;
- sgi = sta->deflink.ht_cap.ht_supported &&
- (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
+ sgi = link_sta->ht_cap.ht_supported &&
+ (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
break;
}
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] &
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[3] &
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM)
ra->dcm_cap = 1;
- if (rate_pattern->enable && !vif->p2p) {
- ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan);
+ if (rate_pattern->enable && !p2p) {
+ ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan);
ra_mask &= rate_pattern->ra_mask;
mode = rate_pattern->ra_mode;
}
ra->bw_cap = bw_mode;
- ra->er_cap = rtwsta->er_cap;
+ ra->er_cap = rtwsta_link->er_cap;
ra->mode_ctrl = mode;
- ra->macid = rtwsta->mac_id;
+ ra->macid = rtwsta_link->mac_id;
ra->stbc_cap = stbc_en;
ra->ldpc_cap = ldpc_en;
- ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
+ ra->ss_num = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1;
ra->en_sgi = sgi;
ra->ra_mask = ra_mask;
ra->fix_giltf_en = fix_giltf_en;
@@ -458,20 +459,29 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
ra->fixed_csi_rate_en = false;
ra->ra_csi_rate_en = true;
ra->cr_tbl_sel = false;
- ra->band_num = rtwvif->phy_idx;
+ ra->band_num = rtwvif_link->phy_idx;
ra->csi_bw = bw_mode;
ra->csi_gi_ltf = RTW89_GILTF_LGI_4XHE32;
ra->csi_mcs_ss_idx = 5;
ra->csi_mode = csi_mode;
}
-void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
- u32 changed)
+static void __rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ u32 changed)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_ra_info *ra = &rtwsta->ra;
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct rtw89_ra_info *ra = &rtwsta_link->ra;
+ struct ieee80211_link_sta *link_sta;
+
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
+ rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link,
+ link_sta, vif->p2p, false);
- rtw89_phy_ra_sta_update(rtwdev, sta, false);
+ rcu_read_unlock();
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED)
ra->upd_mask = 1;
@@ -489,6 +499,20 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta
rtw89_fw_h2c_ra(rtwdev, ra, false);
}
+void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
+ u32 changed)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ __rtw89_phy_ra_update_sta(rtwdev, rtwvif_link, rtwsta_link, changed);
+ }
+}
+
static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next,
u16 rate_base, u64 ra_mask, u8 ra_mode,
u32 rate_ctrl, u32 ctrl_skip, bool force)
@@ -523,15 +547,15 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next,
[RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \
}
-void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif,
- const struct cfg80211_bitrate_mask *mask)
+static
+void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ const struct cfg80211_bitrate_mask *mask)
{
struct ieee80211_supported_band *sband;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_phy_rate_pattern next_pattern = {0};
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = {
RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0),
RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0),
@@ -600,7 +624,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
if (!next_pattern.enable)
goto out;
- rtwvif->rate_pattern = next_pattern;
+ rtwvif_link->rate_pattern = next_pattern;
rtw89_debug(rtwdev, RTW89_DBG_RA,
"configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n",
next_pattern.rate,
@@ -609,10 +633,22 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
return;
out:
- rtwvif->rate_pattern.enable = false;
+ rtwvif_link->rate_pattern.enable = false;
rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n");
}
+void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ __rtw89_phy_rate_pattern_vif(rtwdev, rtwvif_link, mask);
+}
+
static void rtw89_phy_ra_update_sta_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
@@ -627,14 +663,24 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev)
rtwdev);
}
-void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta)
+void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_ra_info *ra = &rtwsta->ra;
- u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
- bool csi = rtw89_sta_has_beamformer_cap(sta);
+ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct rtw89_ra_info *ra = &rtwsta_link->ra;
+ u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
+ struct ieee80211_link_sta *link_sta;
+ bool csi;
+
+ rcu_read_lock();
+
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ csi = rtw89_sta_has_beamformer_cap(link_sta);
- rtw89_phy_ra_sta_update(rtwdev, sta, csi);
+ rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link,
+ link_sta, vif->p2p, csi);
+
+ rcu_read_unlock();
if (rssi > 40)
ra->init_rate_lv = 1;
@@ -1068,14 +1114,21 @@ static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev)
return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1;
}
-static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx)
+static void __rtw89_phy_bb_reset(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
chip->ops->bb_reset(rtwdev, phy_idx);
}
+static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev)
+{
+ __rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0);
+ if (rtwdev->dbcc_en)
+ __rtw89_phy_bb_reset(rtwdev, RTW89_PHY_1);
+}
+
static void rtw89_phy_config_bb_reg(struct rtw89_dev *rtwdev,
const struct rtw89_reg2_def *reg,
enum rtw89_rf_path rf_path,
@@ -1621,13 +1674,15 @@ void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev)
if (rtwdev->dbcc_en)
rtw89_phy_init_reg(rtwdev, bb_table, rtw89_phy_config_bb_reg,
(void *)RTW89_PHY_1);
- rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0);
+
+ rtw89_chip_init_txpwr_unit(rtwdev);
bb_gain_table = elm_info->bb_gain ? elm_info->bb_gain : chip->bb_gain_table;
if (bb_gain_table)
rtw89_phy_init_reg(rtwdev, bb_gain_table,
chip->phy_def->config_bb_gain, NULL);
- rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0);
+
+ rtw89_phy_bb_reset(rtwdev);
}
static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev)
@@ -1747,6 +1802,24 @@ void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
}
EXPORT_SYMBOL(rtw89_phy_write32_idx);
+void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits,
+ enum rtw89_phy_idx phy_idx)
+{
+ if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
+ addr += rtw89_phy0_phy1_offset(rtwdev, addr);
+ rtw89_phy_write32_set(rtwdev, addr, bits);
+}
+EXPORT_SYMBOL(rtw89_phy_write32_idx_set);
+
+void rtw89_phy_write32_idx_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits,
+ enum rtw89_phy_idx phy_idx)
+{
+ if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
+ addr += rtw89_phy0_phy1_offset(rtwdev, addr);
+ rtw89_phy_write32_clr(rtwdev, addr, bits);
+}
+EXPORT_SYMBOL(rtw89_phy_write32_idx_clr);
+
u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
enum rtw89_phy_idx phy_idx)
{
@@ -2553,14 +2626,14 @@ struct rtw89_phy_iter_ra_data {
struct sk_buff *c2h;
};
-static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
+static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link,
+ struct ieee80211_link_sta *link_sta,
+ struct rtw89_phy_iter_ra_data *ra_data)
{
- struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data;
struct rtw89_dev *rtwdev = ra_data->rtwdev;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
const struct rtw89_c2h_ra_rpt *c2h =
(const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data;
- struct rtw89_ra_report *ra_report = &rtwsta->ra_report;
+ struct rtw89_ra_report *ra_report = &rtwsta_link->ra_report;
const struct rtw89_chip_info *chip = rtwdev->chip;
bool format_v1 = chip->chip_gen == RTW89_CHIP_BE;
u8 mode, rate, bw, giltf, mac_id;
@@ -2570,7 +2643,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
u8 t;
mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID);
- if (mac_id != rtwsta->mac_id)
+ if (mac_id != rtwsta_link->mac_id)
return;
rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS);
@@ -2661,8 +2734,26 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) |
u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL);
ra_report->might_fallback_legacy = mcs <= 2;
- sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
- rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1;
+ link_sta->agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
+ rtwsta_link->max_agg_wait = link_sta->agg.max_rc_amsdu_len / 1500 - 1;
+}
+
+static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_sta_link *rtwsta_link;
+ struct ieee80211_link_sta *link_sta;
+ unsigned int link_id;
+
+ rcu_read_lock();
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
+ __rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data);
+ }
+
+ rcu_read_unlock();
}
static void
@@ -2692,9 +2783,85 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
struct rtw89_c2h_rf_txgapk_rpt_log *txgapk;
struct rtw89_c2h_rf_rxdck_rpt_log *rxdck;
struct rtw89_c2h_rf_dack_rpt_log *dack;
+ struct rtw89_c2h_rf_tssi_rpt_log *tssi;
struct rtw89_c2h_rf_dpk_rpt_log *dpk;
+ struct rtw89_c2h_rf_iqk_rpt_log *iqk;
+ int i, j, k;
switch (func) {
+ case RTW89_PHY_C2H_RFK_LOG_FUNC_IQK:
+ if (len != sizeof(*iqk))
+ goto out;
+
+ iqk = content;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->is_iqk_init = %x\n", iqk->is_iqk_init);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->is_reload = %x\n", iqk->is_reload);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->is_nbiqk = %x\n", iqk->is_nbiqk);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->txiqk_en = %x\n", iqk->txiqk_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->rxiqk_en = %x\n", iqk->rxiqk_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->lok_en = %x\n", iqk->lok_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->iqk_xym_en = %x\n", iqk->iqk_xym_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->iqk_sram_en = %x\n", iqk->iqk_sram_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->iqk_fft_en = %x\n", iqk->iqk_fft_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->is_fw_iqk = %x\n", iqk->is_fw_iqk);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->is_iqk_enable = %x\n", iqk->is_iqk_enable);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->iqk_cfir_en = %x\n", iqk->iqk_cfir_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->thermal_rek_en = %x\n", iqk->thermal_rek_en);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->version = %x\n", iqk->version);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->phy = %x\n", iqk->phy);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->fwk_status = %x\n", iqk->fwk_status);
+
+ for (i = 0; i < 2; i++) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] ======== Path %x ========\n", i);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_band[%d] = %x\n",
+ i, iqk->iqk_band[i]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_ch[%d] = %x\n",
+ i, iqk->iqk_ch[i]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_bw[%d] = %x\n",
+ i, iqk->iqk_bw[i]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_idac[%d] = %x\n",
+ i, le32_to_cpu(iqk->lok_idac[i]));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_vbuf[%d] = %x\n",
+ i, le32_to_cpu(iqk->lok_vbuf[i]));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_tx_fail[%d] = %x\n",
+ i, iqk->iqk_tx_fail[i]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_rx_fail[%d] = %x\n",
+ i, iqk->iqk_rx_fail[i]);
+ for (j = 0; j < 4; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->rftxgain[%d][%d] = %x\n",
+ i, j, le32_to_cpu(iqk->rftxgain[i][j]));
+ for (j = 0; j < 4; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->tx_xym[%d][%d] = %x\n",
+ i, j, le32_to_cpu(iqk->tx_xym[i][j]));
+ for (j = 0; j < 4; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->rfrxgain[%d][%d] = %x\n",
+ i, j, le32_to_cpu(iqk->rfrxgain[i][j]));
+ for (j = 0; j < 4; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK] iqk->rx_xym[%d][%d] = %x\n",
+ i, j, le32_to_cpu(iqk->rx_xym[i][j]));
+ }
+ return;
case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK:
if (len != sizeof(*dpk))
goto out;
@@ -2716,8 +2883,23 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
dack = content;
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ver=0x%x 0x%x\n",
- dack->fwdack_ver, dack->fwdack_rpt_ver);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]FWDACK SUMMARY!!!!!\n");
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]FWDACK ver = 0x%x, FWDACK rpt_ver = 0x%x, driver rpt_ver = 0x%x\n",
+ dack->fwdack_ver, dack->fwdack_info_ver, 0x2);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]timeout code = [0x%x 0x%x 0x%x 0x%x 0x%x]\n",
+ dack->addck_timeout, dack->cdack_timeout, dack->dadck_timeout,
+ dack->adgaink_timeout, dack->msbk_timeout);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]DACK fail = 0x%x\n", dack->dack_fail);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]S0 WBADCK = [0x%x]\n", dack->wbdck_d[0]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]S1 WBADCK = [0x%x]\n", dack->wbdck_d[1]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]DRCK = [0x%x]\n", dack->rck_d);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK ic = [0x%x, 0x%x]\n",
dack->cdack_d[0][0][0], dack->cdack_d[0][0][1]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK qc = [0x%x, 0x%x]\n",
@@ -2728,13 +2910,17 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
dack->cdack_d[1][1][0], dack->cdack_d[1][1][1]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = [0x%x, 0x%x]\n",
- dack->addck2_d[0][0][0], dack->addck2_d[0][0][1]);
+ ((u32)dack->addck2_hd[0][0][0] << 8) | dack->addck2_ld[0][0][0],
+ ((u32)dack->addck2_hd[0][0][1] << 8) | dack->addck2_ld[0][0][1]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK qc = [0x%x, 0x%x]\n",
- dack->addck2_d[0][1][0], dack->addck2_d[0][1][1]);
+ ((u32)dack->addck2_hd[0][1][0] << 8) | dack->addck2_ld[0][1][0],
+ ((u32)dack->addck2_hd[0][1][1] << 8) | dack->addck2_ld[0][1][1]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK ic = [0x%x, 0x%x]\n",
- dack->addck2_d[1][0][0], dack->addck2_d[1][0][1]);
+ ((u32)dack->addck2_hd[1][0][0] << 8) | dack->addck2_ld[1][0][0],
+ ((u32)dack->addck2_hd[1][0][1] << 8) | dack->addck2_ld[1][0][1]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK qc = [0x%x, 0x%x]\n",
- dack->addck2_d[1][1][0], dack->addck2_d[1][1][1]);
+ ((u32)dack->addck2_hd[1][1][0] << 8) | dack->addck2_ld[1][1][0],
+ ((u32)dack->addck2_hd[1][1][1] << 8) | dack->addck2_ld[1][1][1]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_GAINK ic = 0x%x, qc = 0x%x\n",
dack->adgaink_d[0][0], dack->adgaink_d[0][1]);
@@ -2747,18 +2933,29 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
dack->dadck_d[1][0], dack->dadck_d[1][1]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask iqc = 0x%x\n",
- dack->biask_d[0][0]);
+ ((u32)dack->biask_hd[0][0] << 8) | dack->biask_ld[0][0]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 biask iqc = 0x%x\n",
- dack->biask_d[1][0]);
-
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic: %*ph\n",
- (int)sizeof(dack->msbk_d[0][0]), dack->msbk_d[0][0]);
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc: %*ph\n",
- (int)sizeof(dack->msbk_d[0][1]), dack->msbk_d[0][1]);
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic: %*ph\n",
- (int)sizeof(dack->msbk_d[1][0]), dack->msbk_d[1][0]);
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc: %*ph\n",
- (int)sizeof(dack->msbk_d[1][1]), dack->msbk_d[1][1]);
+ ((u32)dack->biask_hd[1][0] << 8) | dack->biask_ld[1][0]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n");
+ for (i = 0; i < 0x10; i++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
+ dack->msbk_d[0][0][i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n");
+ for (i = 0; i < 0x10; i++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
+ dack->msbk_d[0][1][i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic:\n");
+ for (i = 0; i < 0x10; i++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
+ dack->msbk_d[1][0][i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc:\n");
+ for (i = 0; i < 0x10; i++)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
+ dack->msbk_d[1][1][i]);
return;
case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK:
if (len != sizeof(*rxdck))
@@ -2770,6 +2967,39 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
rxdck->ver, rxdck->band, rxdck->bw, rxdck->ch,
rxdck->timeout);
return;
+ case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI:
+ if (len != sizeof(*tssi))
+ goto out;
+
+ tssi = content;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++) {
+ for (k = 0; k < 4; k++) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI] alignment_power_cw_h[%d][%d][%d]=%d\n",
+ i, j, k, tssi->alignment_power_cw_h[i][j][k]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI] alignment_power_cw_l[%d][%d][%d]=%d\n",
+ i, j, k, tssi->alignment_power_cw_l[i][j][k]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI] alignment_power[%d][%d][%d]=%d\n",
+ i, j, k, tssi->alignment_power[i][j][k]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI] alignment_power_cw[%d][%d][%d]=%d\n",
+ i, j, k,
+ (tssi->alignment_power_cw_h[i][j][k] << 8) +
+ tssi->alignment_power_cw_l[i][j][k]);
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI] tssi_alimk_state[%d][%d]=%d\n",
+ i, j, tssi->tssi_alimk_state[i][j]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI] default_txagc_offset[%d]=%d\n",
+ j, tssi->default_txagc_offset[0][j]);
+ }
+ }
+ return;
case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK:
if (len != sizeof(*txgapk))
goto out;
@@ -3171,13 +3401,13 @@ EXPORT_SYMBOL(rtw89_phy_rfk_dack_and_wait);
int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan,
- unsigned int ms)
+ bool is_chl_k, unsigned int ms)
{
int ret;
rtw89_phy_rfk_report_prep(rtwdev);
- ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx, chan);
+ ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx, chan, is_chl_k);
if (ret)
return ret;
@@ -4290,33 +4520,33 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val,
cfo->packet_count++;
}
-void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif->chanctx_idx);
+ rtwvif_link->chanctx_idx);
struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;
if (!chip->ul_tb_waveform_ctrl)
return;
- rtwvif->def_tri_idx =
+ rtwvif_link->def_tri_idx =
rtw89_phy_read32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG);
if (chip->chip_id == RTL8852B && rtwdev->hal.cv > CHIP_CBV)
- rtwvif->dyn_tb_bedge_en = false;
+ rtwvif_link->dyn_tb_bedge_en = false;
else if (chan->band_type >= RTW89_BAND_5G &&
chan->band_width >= RTW89_CHANNEL_WIDTH_40)
- rtwvif->dyn_tb_bedge_en = true;
+ rtwvif_link->dyn_tb_bedge_en = true;
else
- rtwvif->dyn_tb_bedge_en = false;
+ rtwvif_link->dyn_tb_bedge_en = false;
rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
"[ULTB] def_if_bandedge=%d, def_tri_idx=%d\n",
- ul_tb_info->def_if_bandedge, rtwvif->def_tri_idx);
+ ul_tb_info->def_if_bandedge, rtwvif_link->def_tri_idx);
rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
"[ULTB] dyn_tb_begde_en=%d, dyn_tb_tri_en=%d\n",
- rtwvif->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en);
+ rtwvif_link->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en);
}
struct rtw89_phy_ul_tb_check_data {
@@ -4338,7 +4568,7 @@ struct rtw89_phy_power_diff {
};
static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
static const struct rtw89_phy_power_diff table[2] = {
{0x0, 0x0, 0x0, 0x0, 0xf4, 0x3, 0x3},
@@ -4350,13 +4580,13 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev,
if (!rtwdev->chip->ul_tb_pwr_diff)
return;
- if (rtwvif->pwr_diff_en == rtwvif->pre_pwr_diff_en) {
- rtwvif->pwr_diff_en = false;
+ if (rtwvif_link->pwr_diff_en == rtwvif_link->pre_pwr_diff_en) {
+ rtwvif_link->pwr_diff_en = false;
return;
}
- rtwvif->pre_pwr_diff_en = rtwvif->pwr_diff_en;
- param = &table[rtwvif->pwr_diff_en];
+ rtwvif_link->pre_pwr_diff_en = rtwvif_link->pwr_diff_en;
+ param = &table[rtwvif_link->pwr_diff_en];
rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_00, B_Q_MATRIX_00_REAL,
param->q_00);
@@ -4365,32 +4595,32 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev,
rtw89_phy_write32_mask(rtwdev, R_CUSTOMIZE_Q_MATRIX,
B_CUSTOMIZE_Q_MATRIX_EN, param->q_matrix_en);
- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_NORM_BW160,
param->ultb_1t_norm_160);
- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_NORM_BW160,
param->ultb_2t_norm_160);
- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM1_NORM_1STS,
param->com1_norm_1sts);
- reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif->mac_idx);
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif_link->mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM2_RESP_1STS_PATH,
param->com2_resp_1sts_path);
}
static
void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct rtw89_phy_ul_tb_check_data *ul_tb_data)
{
struct rtw89_traffic_stats *stats = &rtwdev->stats;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
+ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION)
return;
if (!vif->cfg.assoc)
@@ -4403,11 +4633,11 @@ void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev,
ul_tb_data->low_tf_client = true;
ul_tb_data->valid = true;
- ul_tb_data->def_tri_idx = rtwvif->def_tri_idx;
- ul_tb_data->dyn_tb_bedge_en = rtwvif->dyn_tb_bedge_en;
+ ul_tb_data->def_tri_idx = rtwvif_link->def_tri_idx;
+ ul_tb_data->dyn_tb_bedge_en = rtwvif_link->dyn_tb_bedge_en;
}
- rtw89_phy_ofdma_power_diff(rtwdev, rtwvif);
+ rtw89_phy_ofdma_power_diff(rtwdev, rtwvif_link);
}
static void rtw89_phy_ul_tb_waveform_ctrl(struct rtw89_dev *rtwdev,
@@ -4453,7 +4683,9 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_phy_ul_tb_check_data ul_tb_data = {};
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff)
return;
@@ -4462,7 +4694,8 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev)
return;
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif, &ul_tb_data);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data);
if (!ul_tb_data.valid)
return;
@@ -4603,11 +4836,36 @@ static void rtw89_phy_antdiv_init(struct rtw89_dev *rtwdev)
rtw89_phy_antdiv_reg_init(rtwdev);
}
+static void rtw89_phy_thermal_protect(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_phy_stat *phystat = &rtwdev->phystat;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 th_max = phystat->last_thermal_max;
+ u8 lv = hal->thermal_prot_lv;
+
+ if (!hal->thermal_prot_th ||
+ (hal->disabled_dm_bitmap & BIT(RTW89_DM_THERMAL_PROTECT)))
+ return;
+
+ if (th_max > hal->thermal_prot_th && lv < RTW89_THERMAL_PROT_LV_MAX)
+ lv++;
+ else if (th_max < hal->thermal_prot_th - 2 && lv > 0)
+ lv--;
+ else
+ return;
+
+ hal->thermal_prot_lv = lv;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, "thermal protection lv=%d\n", lv);
+
+ rtw89_fw_h2c_tx_duty(rtwdev, hal->thermal_prot_lv);
+}
+
static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev)
{
struct rtw89_phy_stat *phystat = &rtwdev->phystat;
+ u8 th, th_max = 0;
int i;
- u8 th;
for (i = 0; i < rtwdev->chip->rf_path_num; i++) {
th = rtw89_chip_get_thermal(rtwdev, i);
@@ -4617,7 +4875,11 @@ static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev)
rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
"path(%d) thermal cur=%u avg=%ld", i, th,
ewma_thermal_read(&phystat->avg_thermal[i]));
+
+ th_max = max(th_max, th);
}
+
+ phystat->last_thermal_max = th_max;
}
struct rtw89_phy_iter_rssi_data {
@@ -4626,30 +4888,42 @@ struct rtw89_phy_iter_rssi_data {
bool rssi_changed;
};
-static void rtw89_phy_stat_rssi_update_iter(void *data,
- struct ieee80211_sta *sta)
+static
+void __rtw89_phy_stat_rssi_update_iter(struct rtw89_sta_link *rtwsta_link,
+ struct rtw89_phy_iter_rssi_data *rssi_data)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_phy_iter_rssi_data *rssi_data =
- (struct rtw89_phy_iter_rssi_data *)data;
struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info;
unsigned long rssi_curr;
- rssi_curr = ewma_rssi_read(&rtwsta->avg_rssi);
+ rssi_curr = ewma_rssi_read(&rtwsta_link->avg_rssi);
if (rssi_curr < ch_info->rssi_min) {
ch_info->rssi_min = rssi_curr;
- ch_info->rssi_min_macid = rtwsta->mac_id;
+ ch_info->rssi_min_macid = rtwsta_link->mac_id;
}
- if (rtwsta->prev_rssi == 0) {
- rtwsta->prev_rssi = rssi_curr;
- } else if (abs((int)rtwsta->prev_rssi - (int)rssi_curr) > (3 << RSSI_FACTOR)) {
- rtwsta->prev_rssi = rssi_curr;
+ if (rtwsta_link->prev_rssi == 0) {
+ rtwsta_link->prev_rssi = rssi_curr;
+ } else if (abs((int)rtwsta_link->prev_rssi - (int)rssi_curr) >
+ (3 << RSSI_FACTOR)) {
+ rtwsta_link->prev_rssi = rssi_curr;
rssi_data->rssi_changed = true;
}
}
+static void rtw89_phy_stat_rssi_update_iter(void *data,
+ struct ieee80211_sta *sta)
+{
+ struct rtw89_phy_iter_rssi_data *rssi_data =
+ (struct rtw89_phy_iter_rssi_data *)data;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
+ __rtw89_phy_stat_rssi_update_iter(rtwsta_link, rssi_data);
+}
+
static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev)
{
struct rtw89_phy_iter_rssi_data rssi_data = {0};
@@ -4676,6 +4950,10 @@ static void rtw89_phy_stat_init(struct rtw89_dev *rtwdev)
memset(&phystat->cur_pkt_stat, 0, sizeof(phystat->cur_pkt_stat));
memset(&phystat->last_pkt_stat, 0, sizeof(phystat->last_pkt_stat));
+
+ ewma_rssi_init(&phystat->bcn_rssi);
+
+ rtwdev->hal.thermal_prot_lv = 0;
}
void rtw89_phy_stat_track(struct rtw89_dev *rtwdev)
@@ -4683,6 +4961,7 @@ void rtw89_phy_stat_track(struct rtw89_dev *rtwdev)
struct rtw89_phy_stat *phystat = &rtwdev->phystat;
rtw89_phy_stat_thermal_update(rtwdev);
+ rtw89_phy_thermal_protect(rtwdev);
rtw89_phy_stat_rssi_update(rtwdev);
phystat->last_pkt_stat = phystat->cur_pkt_stat;
@@ -5188,7 +5467,8 @@ static u32 rtw89_phy_get_ie_bitmap_addr(enum rtw89_phy_status_bitmap ie_page)
}
static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev,
- enum rtw89_phy_status_bitmap ie_page)
+ enum rtw89_phy_status_bitmap ie_page,
+ enum rtw89_phy_idx phy_idx)
{
u32 addr;
@@ -5197,12 +5477,12 @@ static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev,
addr = rtw89_phy_get_ie_bitmap_addr(ie_page);
- return rtw89_phy_read32(rtwdev, addr);
+ return rtw89_phy_read32_idx(rtwdev, addr, MASKDWORD, phy_idx);
}
static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev,
enum rtw89_phy_status_bitmap ie_page,
- u32 val)
+ u32 val, enum rtw89_phy_idx phy_idx)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
u32 addr;
@@ -5214,22 +5494,22 @@ static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev,
val &= B_PHY_STS_BITMAP_MSK_52A;
addr = rtw89_phy_get_ie_bitmap_addr(ie_page);
- rtw89_phy_write32(rtwdev, addr, val);
+ rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx);
}
static void rtw89_physts_enable_ie_bitmap(struct rtw89_dev *rtwdev,
enum rtw89_phy_status_bitmap bitmap,
enum rtw89_phy_status_ie_type ie,
- bool enable)
+ bool enable, enum rtw89_phy_idx phy_idx)
{
- u32 val = rtw89_physts_get_ie_bitmap(rtwdev, bitmap);
+ u32 val = rtw89_physts_get_ie_bitmap(rtwdev, bitmap, phy_idx);
if (enable)
val |= BIT(ie);
else
val &= ~BIT(ie);
- rtw89_physts_set_ie_bitmap(rtwdev, bitmap, val);
+ rtw89_physts_set_ie_bitmap(rtwdev, bitmap, val, phy_idx);
}
static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev,
@@ -5240,44 +5520,52 @@ static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev,
const struct rtw89_physts_regs *physts = phy->physts;
if (enable) {
- rtw89_phy_write32_clr(rtwdev, physts->setting_addr,
- physts->dis_trigger_fail_mask);
- rtw89_phy_write32_clr(rtwdev, physts->setting_addr,
- physts->dis_trigger_brk_mask);
+ rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr,
+ physts->dis_trigger_fail_mask, phy_idx);
+ rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr,
+ physts->dis_trigger_brk_mask, phy_idx);
} else {
- rtw89_phy_write32_set(rtwdev, physts->setting_addr,
- physts->dis_trigger_fail_mask);
- rtw89_phy_write32_set(rtwdev, physts->setting_addr,
- physts->dis_trigger_brk_mask);
+ rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr,
+ physts->dis_trigger_fail_mask, phy_idx);
+ rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr,
+ physts->dis_trigger_brk_mask, phy_idx);
}
}
-static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev)
+static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
{
u8 i;
- rtw89_physts_enable_fail_report(rtwdev, false, RTW89_PHY_0);
+ rtw89_physts_enable_fail_report(rtwdev, false, phy_idx);
for (i = 0; i < RTW89_PHYSTS_BITMAP_NUM; i++) {
if (i >= RTW89_CCK_PKT)
rtw89_physts_enable_ie_bitmap(rtwdev, i,
RTW89_PHYSTS_IE09_FTR_0,
- true);
+ true, phy_idx);
if ((i >= RTW89_CCK_BRK && i <= RTW89_VHT_MU) ||
(i >= RTW89_RSVD_9 && i <= RTW89_CCK_PKT))
continue;
rtw89_physts_enable_ie_bitmap(rtwdev, i,
RTW89_PHYSTS_IE24_OFDM_TD_PATH_A,
- true);
+ true, phy_idx);
}
rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_VHT_PKT,
- RTW89_PHYSTS_IE13_DL_MU_DEF, true);
+ RTW89_PHYSTS_IE13_DL_MU_DEF, true, phy_idx);
rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_HE_PKT,
- RTW89_PHYSTS_IE13_DL_MU_DEF, true);
+ RTW89_PHYSTS_IE13_DL_MU_DEF, true, phy_idx);
/* force IE01 for channel index, only channel field is valid */
rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_CCK_PKT,
- RTW89_PHYSTS_IE01_CMN_OFDM, true);
+ RTW89_PHYSTS_IE01_CMN_OFDM, true, phy_idx);
+}
+
+static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev)
+{
+ __rtw89_physts_parsing_init(rtwdev, RTW89_PHY_0);
+ if (rtwdev->dbcc_en)
+ __rtw89_physts_parsing_init(rtwdev, RTW89_PHY_1);
}
static void rtw89_phy_dig_read_gain_table(struct rtw89_dev *rtwdev, int type)
@@ -5753,26 +6041,15 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev)
rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false);
}
-static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
+static void __rtw89_phy_tx_path_div_sta_iter(struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link)
{
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
- struct rtw89_dev *rtwdev = rtwsta->rtwdev;
- struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_hal *hal = &rtwdev->hal;
- bool *done = data;
u8 rssi_a, rssi_b;
u32 candidate;
- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls)
- return;
-
- if (*done)
- return;
-
- *done = true;
-
- rssi_a = ewma_rssi_read(&rtwsta->rssi[RF_PATH_A]);
- rssi_b = ewma_rssi_read(&rtwsta->rssi[RF_PATH_B]);
+ rssi_a = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_A]);
+ rssi_b = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_B]);
if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH)
candidate = RF_A;
@@ -5785,7 +6062,7 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta
return;
hal->antenna_tx = candidate;
- rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta);
+ rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta_link);
if (hal->antenna_tx == RF_A) {
rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12);
@@ -5796,6 +6073,37 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta
}
}
+static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ bool *done = data;
+
+ if (WARN(ieee80211_vif_is_mld(vif), "MLD mix path_div\n"))
+ return;
+
+ if (sta->tdls)
+ return;
+
+ if (*done)
+ return;
+
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
+ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION)
+ continue;
+
+ *done = true;
+ __rtw89_phy_tx_path_div_sta_iter(rtwdev, rtwsta_link);
+ return;
+ }
+}
+
void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
@@ -6002,17 +6310,27 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev)
rtw89_chip_cfg_txrx_path(rtwdev);
}
-void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
+void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld;
- enum rtw89_phy_idx phy_idx = RTW89_PHY_0;
+ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
+ struct ieee80211_bss_conf *bss_conf;
u8 bss_color;
- if (!vif->bss_conf.he_support || !vif->cfg.assoc)
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ if (!bss_conf->he_support || !vif->cfg.assoc) {
+ rcu_read_unlock();
return;
+ }
+
+ bss_color = bss_conf->he_bss_color.color;
- bss_color = vif->bss_conf.he_bss_color.color;
+ rcu_read_unlock();
rtw89_phy_write32_idx(rtwdev, bss_clr_vld->addr, bss_clr_vld->mask, 0x1,
phy_idx);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 6dd8ec46939a..c683f4d7d29b 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -815,6 +815,10 @@ void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
void rtw89_phy_dm_init(struct rtw89_dev *rtwdev);
void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
u32 data, enum rtw89_phy_idx phy_idx);
+void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits,
+ enum rtw89_phy_idx phy_idx);
+void rtw89_phy_write32_idx_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits,
+ enum rtw89_phy_idx phy_idx);
u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
enum rtw89_phy_idx phy_idx);
s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
@@ -892,7 +896,7 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx);
}
-void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
+void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link);
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev);
void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
u32 changed);
@@ -929,7 +933,7 @@ int rtw89_phy_rfk_dack_and_wait(struct rtw89_dev *rtwdev,
int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx,
const struct rtw89_chan *chan,
- unsigned int ms);
+ bool is_chl_k, unsigned int ms);
void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy,
const struct rtw89_chan *chan,
@@ -953,11 +957,12 @@ void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu);
void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev);
void rtw89_phy_antdiv_work(struct work_struct *work);
-void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
+void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link);
void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
enum rtw89_mac_idx mac_idx,
enum rtw89_tssi_bandedge_cfg bandedge_cfg);
-void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev);
u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band);
void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 72eda9bbd3ae..37d8f254ae32 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -398,10 +398,9 @@ static void rtw89_phy_bb_wrap_ul_pwr(struct rtw89_dev *rtwdev)
}
}
-static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev)
+static void __rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev,
+ enum rtw89_mac_idx mac_idx)
{
- enum rtw89_mac_idx mac_idx = RTW89_MAC_0;
-
rtw89_phy_bb_wrap_pwr_by_macid_init(rtwdev);
rtw89_phy_bb_wrap_tx_path_by_macid_init(rtwdev);
rtw89_phy_bb_wrap_listen_path_en_init(rtwdev);
@@ -411,6 +410,13 @@ static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev)
rtw89_phy_bb_wrap_ul_pwr(rtwdev);
}
+static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev)
+{
+ __rtw89_phy_bb_wrap_init_be(rtwdev, RTW89_MAC_0);
+ if (rtwdev->dbcc_en)
+ __rtw89_phy_bb_wrap_init_be(rtwdev, RTW89_MAC_1);
+}
+
static void rtw89_phy_ch_info_init_be(struct rtw89_dev *rtwdev)
{
rtw89_phy_write32_mask(rtwdev, R_CHINFO_SEG, B_CHINFO_SEG_LEN, 0x0);
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index aebd6404f802..c1c12abc2ea9 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -62,9 +62,9 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
rtw89_mac_power_mode_change(rtwdev, enter);
}
-void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
- if (rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT)
+ if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT)
return;
if (!rtwdev->ps_mode)
@@ -85,23 +85,25 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
rtw89_ps_power_mode_change(rtwdev, false);
}
-static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void __rtw89_enter_lps(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_lps_parm lps_param = {
- .macid = rtwvif->mac_id,
+ .macid = rtwvif_link->mac_id,
.psmode = RTW89_MAC_AX_PS_MODE_LEGACY,
.lastrpwm = RTW89_LAST_RPWM_PS,
};
rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL);
rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
- rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif);
+ rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif_link);
}
-static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void __rtw89_leave_lps(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_lps_parm lps_param = {
- .macid = rtwvif->mac_id,
+ .macid = rtwvif_link->mac_id,
.psmode = RTW89_MAC_AX_PS_MODE_ACTIVE,
.lastrpwm = RTW89_LAST_RPWM_ACTIVE,
};
@@ -109,7 +111,7 @@ static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
rtw89_fw_leave_lps_check(rtwdev, 0);
rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
- rtw89_chip_digital_pwr_comp(rtwdev, rtwvif->phy_idx);
+ rtw89_chip_digital_pwr_comp(rtwdev, rtwvif_link->phy_idx);
}
void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
@@ -119,7 +121,7 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
__rtw89_leave_ps_mode(rtwdev);
}
-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool ps_mode)
{
lockdep_assert_held(&rtwdev->mutex);
@@ -127,23 +129,26 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
return;
- __rtw89_enter_lps(rtwdev, rtwvif);
+ __rtw89_enter_lps(rtwdev, rtwvif_link);
if (ps_mode)
- __rtw89_enter_ps_mode(rtwdev, rtwvif);
+ __rtw89_enter_ps_mode(rtwdev, rtwvif_link);
}
-static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION &&
- rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
+ if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
+ rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
return;
- __rtw89_leave_lps(rtwdev, rtwvif);
+ __rtw89_leave_lps(rtwdev, rtwvif_link);
}
void rtw89_leave_lps(struct rtw89_dev *rtwdev)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
lockdep_assert_held(&rtwdev->mutex);
@@ -153,12 +158,15 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev)
__rtw89_leave_ps_mode(rtwdev);
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_leave_lps_vif(rtwdev, rtwvif);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_leave_lps_vif(rtwdev, rtwvif_link);
}
void rtw89_enter_ips(struct rtw89_dev *rtwdev)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
@@ -166,14 +174,17 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev)
return;
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_mac_vif_deinit(rtwdev, rtwvif);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_mac_vif_deinit(rtwdev, rtwvif_link);
rtw89_core_stop(rtwdev);
}
void rtw89_leave_ips(struct rtw89_dev *rtwdev)
{
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
int ret;
if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
@@ -186,7 +197,8 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev)
rtw89_set_channel(rtwdev);
rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_mac_vif_init(rtwdev, rtwvif);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_mac_vif_init(rtwdev, rtwvif_link);
clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
}
@@ -197,48 +209,50 @@ void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl)
rtw89_leave_lps(rtwdev);
}
-static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
enum rtw89_p2pps_action act)
{
if (act == RTW89_P2P_ACT_UPDATE || act == RTW89_P2P_ACT_REMOVE)
return;
if (act == RTW89_P2P_ACT_INIT)
- rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, true);
+ rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, true);
else if (act == RTW89_P2P_ACT_TERMINATE)
- rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, false);
+ rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, false);
}
static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif)
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
enum rtw89_p2pps_action act;
u8 noa_id;
- if (rtwvif->last_noa_nr == 0)
+ if (rtwvif_link->last_noa_nr == 0)
return;
- for (noa_id = 0; noa_id < rtwvif->last_noa_nr; noa_id++) {
- if (noa_id == rtwvif->last_noa_nr - 1)
+ for (noa_id = 0; noa_id < rtwvif_link->last_noa_nr; noa_id++) {
+ if (noa_id == rtwvif_link->last_noa_nr - 1)
act = RTW89_P2P_ACT_TERMINATE;
else
act = RTW89_P2P_ACT_REMOVE;
- rtw89_tsf32_toggle(rtwdev, rtwvif, act);
- rtw89_fw_h2c_p2p_act(rtwdev, vif, NULL, act, noa_id);
+ rtw89_tsf32_toggle(rtwdev, rtwvif_link, act);
+ rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf,
+ NULL, act, noa_id);
}
}
static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev,
- struct ieee80211_vif *vif)
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf)
{
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct ieee80211_p2p_noa_desc *desc;
enum rtw89_p2pps_action act;
u8 noa_id;
for (noa_id = 0; noa_id < RTW89_P2P_MAX_NOA_NUM; noa_id++) {
- desc = &vif->bss_conf.p2p_noa_attr.desc[noa_id];
+ desc = &bss_conf->p2p_noa_attr.desc[noa_id];
if (!desc->count || !desc->duration)
break;
@@ -246,16 +260,19 @@ static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev,
act = RTW89_P2P_ACT_INIT;
else
act = RTW89_P2P_ACT_UPDATE;
- rtw89_tsf32_toggle(rtwdev, rtwvif, act);
- rtw89_fw_h2c_p2p_act(rtwdev, vif, desc, act, noa_id);
+ rtw89_tsf32_toggle(rtwdev, rtwvif_link, act);
+ rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf,
+ desc, act, noa_id);
}
- rtwvif->last_noa_nr = noa_id;
+ rtwvif_link->last_noa_nr = noa_id;
}
-void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
+void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf)
{
- rtw89_p2p_disable_all_noa(rtwdev, vif);
- rtw89_p2p_update_noa(rtwdev, vif);
+ rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, bss_conf);
+ rtw89_p2p_update_noa(rtwdev, rtwvif_link, bss_conf);
}
void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
@@ -265,6 +282,12 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
enum rtw89_entity_mode mode;
int count = 0;
+ /* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode()
+ * to take MLO cases into account before doing the following.
+ */
+ if (rtwdev->support_mlo)
+ goto disable_lps;
+
mode = rtw89_get_entity_mode(rtwdev);
if (mode == RTW89_ENTITY_MODE_MCC)
goto disable_lps;
@@ -291,9 +314,9 @@ disable_lps:
rtwdev->lps_enabled = false;
}
-void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif)
+void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link)
{
- struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
+ struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa;
struct rtw89_p2p_noa_ie *ie = &setter->ie;
struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
@@ -318,10 +341,10 @@ void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif)
noa_head->oppps_ctwindow = 0;
}
-void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif,
+void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link,
const struct ieee80211_p2p_noa_desc *desc)
{
- struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
+ struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa;
struct rtw89_p2p_noa_ie *ie = &setter->ie;
struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
@@ -338,9 +361,9 @@ void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif,
ie->noa_desc[setter->noa_count++] = *desc;
}
-u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data)
+u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data)
{
- struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
+ struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa;
struct rtw89_p2p_noa_ie *ie = &setter->ie;
void *tail;
diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h
index 54486e4550b6..cdd712966b09 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.h
+++ b/drivers/net/wireless/realtek/rtw89/ps.h
@@ -5,21 +5,23 @@
#ifndef __RTW89_PS_H_
#define __RTW89_PS_H_
-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool ps_mode);
void rtw89_leave_lps(struct rtw89_dev *rtwdev);
void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev);
-void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev);
void rtw89_enter_ips(struct rtw89_dev *rtwdev);
void rtw89_leave_ips(struct rtw89_dev *rtwdev);
void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl);
-void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
+void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct ieee80211_bss_conf *bss_conf);
void rtw89_recalc_lps(struct rtw89_dev *rtwdev);
-void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif);
-void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif,
+void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link);
+void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link,
const struct ieee80211_p2p_noa_desc *desc);
-u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data);
+u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data);
static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev)
{
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 69678eab2309..18ec7c0252fb 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -196,6 +196,8 @@
#define R_AX_HALT_C2H 0x016C
#define R_AX_WCPU_FW_CTRL 0x01E0
+#define B_AX_IDMEM_SHARE_MODE_RECORD_MASK GENMASK(27, 24)
+#define B_AX_IDMEM_SHARE_MODE_RECORD_VALID BIT(23)
#define B_AX_WCPU_FWDL_STS_MASK GENMASK(7, 5)
#define B_AX_FWDL_PATH_RDY BIT(2)
#define B_AX_H2C_PATH_RDY BIT(1)
diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
index a7720a1f17a7..cad5189708e7 100644
--- a/drivers/net/wireless/realtek/rtw89/regd.c
+++ b/drivers/net/wireless/realtek/rtw89/regd.c
@@ -646,22 +646,44 @@ static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
}
-static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
- struct wiphy *wiphy)
+static bool regd_is_6ghz_blocked(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_regd *regd = regulatory->regd;
- struct ieee80211_supported_band *sband;
u8 index;
- int i;
index = rtw89_regd_get_index(regd);
if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
!test_bit(index, regulatory->block_6ghz))
- return;
+ return false;
rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
regd->alpha2[0], regd->alpha2[1]);
+ return true;
+}
+
+static bool regd_is_6ghz_not_applicable(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+ const struct rtw89_regd *regd = regulatory->regd;
+
+ if (regd->txpwr_regd[RTW89_BAND_6G] != RTW89_NA)
+ return false;
+
+ rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is N/A in regd map\n",
+ regd->alpha2[0], regd->alpha2[1]);
+ return true;
+}
+
+static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
+ struct wiphy *wiphy)
+{
+ struct ieee80211_supported_band *sband;
+ int i;
+
+ if (!regd_is_6ghz_blocked(rtwdev) &&
+ !regd_is_6ghz_not_applicable(rtwdev))
+ return;
sband = wiphy->bands[NL80211_BAND_6GHZ];
if (!sband)
@@ -793,22 +815,26 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
struct rtw89_reg_6ghz_tpe new = {};
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
bool changed = false;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
const struct rtw89_reg_6ghz_tpe *tmp;
const struct rtw89_chan *chan;
- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx);
- if (chan->band_type != RTW89_BAND_6G)
- continue;
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+ if (chan->band_type != RTW89_BAND_6G)
+ continue;
- tmp = &rtwvif->reg_6ghz_tpe;
- if (!tmp->valid)
- continue;
+ tmp = &rtwvif_link->reg_6ghz_tpe;
+ if (!tmp->valid)
+ continue;
- tpe_intersect_constraint(&new, tmp->constraint);
+ tpe_intersect_constraint(&new, tmp->constraint);
+ }
}
if (memcmp(&regulatory->reg_6ghz_tpe, &new,
@@ -831,19 +857,24 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
}
static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool active,
+ struct rtw89_vif_link *rtwvif_link, bool active,
unsigned int *changed)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
- struct rtw89_reg_6ghz_tpe *tpe = &rtwvif->reg_6ghz_tpe;
+ struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe;
+ struct ieee80211_bss_conf *bss_conf;
memset(tpe, 0, sizeof(*tpe));
- if (!active || rtwvif->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
+ if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
goto bottom;
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe);
+
+ rcu_read_unlock();
+
if (!tpe->valid)
goto bottom;
@@ -867,20 +898,24 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
const struct rtw89_regd *regd = regulatory->regd;
enum rtw89_reg_6ghz_power sel;
const struct rtw89_chan *chan;
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
+ unsigned int link_id;
int count = 0;
u8 index;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
- chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx);
- if (chan->band_type != RTW89_BAND_6G)
- continue;
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+ if (chan->band_type != RTW89_BAND_6G)
+ continue;
- if (count != 0 && rtwvif->reg_6ghz_power == sel)
- continue;
+ if (count != 0 && rtwvif_link->reg_6ghz_power == sel)
+ continue;
- sel = rtwvif->reg_6ghz_power;
- count++;
+ sel = rtwvif_link->reg_6ghz_power;
+ count++;
+ }
}
if (count != 1)
@@ -908,35 +943,41 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
}
static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif, bool active,
+ struct rtw89_vif_link *rtwvif_link, bool active,
unsigned int *changed)
{
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_bss_conf *bss_conf;
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
if (active) {
- switch (vif->bss_conf.power_type) {
+ switch (bss_conf->power_type) {
case IEEE80211_REG_VLP_AP:
- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
+ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
break;
case IEEE80211_REG_LPI_AP:
- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
+ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
break;
case IEEE80211_REG_SP_AP:
- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
+ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
break;
default:
- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
break;
}
} else {
- rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+ rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
}
+ rcu_read_unlock();
+
*changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
return 0;
}
-int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool active)
{
unsigned int changed = 0;
@@ -948,11 +989,11 @@ int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
* so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
*/
- ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, active, &changed);
+ ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed);
if (ret)
return ret;
- ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif, active, &changed);
+ ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed);
if (ret)
return ret;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 1679bd408ef3..68c67a763f4d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -282,7 +282,7 @@ static int rtw8851b_pwr_on_func(struct rtw89_dev *rtwdev)
{
u32 val32;
u8 val8;
- u32 ret;
+ int ret;
rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN |
B_AX_AFSM_PCIE_SUS_EN);
@@ -401,7 +401,7 @@ static void rtw8851b_patch_swr_pfm2pwm(struct rtw89_dev *rtwdev)
static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev)
{
u32 val32;
- u32 ret;
+ int ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF,
XTAL_SI_RFC2RF);
@@ -1590,10 +1590,11 @@ static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev)
rtw8851b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0);
}
-static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx;
- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx;
+ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
+ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
rtw8851b_rx_dck(rtwdev, phy_idx, chanctx_idx);
rtw8851b_iqk(rtwdev, phy_idx, chanctx_idx);
@@ -1608,10 +1609,12 @@ static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev,
rtw8851b_tssi_scan(rtwdev, phy_idx, chan);
}
-static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool start)
{
- rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx);
+ rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx,
+ rtwvif_link->chanctx_idx);
}
static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev)
@@ -2451,6 +2454,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.wde_qempty_acq_grpnum = 4,
.wde_qempty_mgq_grpsel = 4,
.rf_base_addr = {0xe000},
+ .thermal_th = {0x32, 0x35},
.pwr_on_seq = NULL,
.pwr_off_seq = NULL,
.bb_table = &rtw89_8851b_phy_bb_table,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
index d334924faec8..651cbce1dd7e 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
@@ -60,6 +60,8 @@ static const struct rtw89_pci_info rtw8851b_pci_info = {
.enable_intr = rtw89_pci_enable_intr,
.disable_intr = rtw89_pci_disable_intr,
.recognize_intrs = rtw89_pci_recognize_intrs,
+
+ .ssid_quirks = NULL,
};
static const struct rtw89_driver_info rtw89_8851be_info = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index dde96bd63021..e647759ebd69 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -1350,10 +1350,11 @@ static void rtw8852a_rfk_init(struct rtw89_dev *rtwdev)
rtw8852a_rx_dck(rtwdev, RTW89_PHY_0, true, RTW89_CHANCTX_0);
}
-static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx;
- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx;
+ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
+ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
rtw8852a_rx_dck(rtwdev, phy_idx, true, chanctx_idx);
rtw8852a_iqk(rtwdev, phy_idx, chanctx_idx);
@@ -1368,10 +1369,11 @@ static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev,
rtw8852a_tssi_scan(rtwdev, phy_idx, chan);
}
-static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool start)
{
- rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx);
+ rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx);
}
static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev)
@@ -2168,6 +2170,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.wde_qempty_acq_grpnum = 16,
.wde_qempty_mgq_grpsel = 16,
.rf_base_addr = {0xc000, 0xd000},
+ .thermal_th = {0x32, 0x35},
.pwr_on_seq = pwr_on_seq_8852a,
.pwr_off_seq = pwr_off_seq_8852a,
.bb_table = &rtw89_8852a_phy_bb_table,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
index 9a675e2193bc..701187d69e14 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
@@ -58,6 +58,8 @@ static const struct rtw89_pci_info rtw8852a_pci_info = {
.enable_intr = rtw89_pci_enable_intr,
.disable_intr = rtw89_pci_disable_intr,
.recognize_intrs = rtw89_pci_recognize_intrs,
+
+ .ssid_quirks = NULL,
};
static const struct rtw89_driver_info rtw89_8852ae_info = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index 12be52f76427..49a319128316 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -254,7 +254,7 @@ static void rtw8852b_pwr_sps_ana(struct rtw89_dev *rtwdev)
static int rtw8852b_pwr_on_func(struct rtw89_dev *rtwdev)
{
u32 val32;
- u32 ret;
+ int ret;
rtw8852b_pwr_sps_ana(rtwdev);
@@ -383,7 +383,7 @@ func_en:
static int rtw8852b_pwr_off_func(struct rtw89_dev *rtwdev)
{
u32 val32;
- u32 ret;
+ int ret;
rtw8852b_pwr_sps_ana(rtwdev);
@@ -562,10 +562,11 @@ static void rtw8852b_rfk_init(struct rtw89_dev *rtwdev)
rtw8852b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0);
}
-static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx;
- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx;
+ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
+ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
rtw8852b_rx_dck(rtwdev, phy_idx, chanctx_idx);
rtw8852b_iqk(rtwdev, phy_idx, chanctx_idx);
@@ -580,10 +581,12 @@ static void rtw8852b_rfk_band_changed(struct rtw89_dev *rtwdev,
rtw8852b_tssi_scan(rtwdev, phy_idx, chan);
}
-static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool start)
{
- rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx);
+ rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx,
+ rtwvif_link->chanctx_idx);
}
static void rtw8852b_rfk_track(struct rtw89_dev *rtwdev)
@@ -805,6 +808,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.wde_qempty_acq_grpnum = 4,
.wde_qempty_mgq_grpsel = 4,
.rf_base_addr = {0xe000, 0xf000},
+ .thermal_th = {0x32, 0x35},
.pwr_on_seq = NULL,
.pwr_off_seq = NULL,
.bb_table = &rtw89_8852b_phy_bb_table,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
index ede0ca5426ae..f4aa4437fb75 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
@@ -905,7 +905,6 @@ static void rtw8852bx_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw,
{
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
u32 rx_path_0;
- u32 val;
rx_path_0 = rtw89_phy_read32_idx(rtwdev, R_CHBW_MOD_V1, B_ANT_RX_SEG0, phy_idx);
@@ -985,12 +984,11 @@ static void rtw8852bx_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw,
rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH,
pri_ch, phy_idx);
- /*Set RF mode at A */
- val = chip_id == RTL8852BT ? 0x333 : 0xaaa;
+ /*Set RF mode at 3 */
rtw89_phy_write32_idx(rtwdev, R_P0_RFMODE_ORI_RX,
- B_P0_RFMODE_ORI_RX_ALL, val, phy_idx);
+ B_P0_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
rtw89_phy_write32_idx(rtwdev, R_P1_RFMODE_ORI_RX,
- B_P1_RFMODE_ORI_RX_ALL, val, phy_idx);
+ B_P1_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
break;
default:
rtw89_warn(rtwdev, "Fail to switch bw (bw:%d, pri ch:%d)\n", bw,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852be.c b/drivers/net/wireless/realtek/rtw89/rtw8852be.c
index d8f9d92ca0fb..a13ea1cce4a7 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852be.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852be.c
@@ -60,6 +60,8 @@ static const struct rtw89_pci_info rtw8852b_pci_info = {
.enable_intr = rtw89_pci_enable_intr,
.disable_intr = rtw89_pci_disable_intr,
.recognize_intrs = rtw89_pci_recognize_intrs,
+
+ .ssid_quirks = NULL,
};
static const struct rtw89_driver_info rtw89_8852be_info = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 7dfdcb5964e1..876725133228 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -244,7 +244,7 @@ static const u8 rtw89_btc_8852bt_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {50, 40, 30,
static int rtw8852bt_pwr_on_func(struct rtw89_dev *rtwdev)
{
u32 val32;
- u32 ret;
+ int ret;
rtw89_write32_set(rtwdev, R_AX_LDO_AON_CTRL0, B_AX_PD_REGU_L);
rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN |
@@ -357,7 +357,7 @@ func_en:
static int rtw8852bt_pwr_off_func(struct rtw89_dev *rtwdev)
{
u32 val32;
- u32 ret;
+ int ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF,
XTAL_SI_RFC2RF);
@@ -535,10 +535,11 @@ static void rtw8852bt_rfk_init(struct rtw89_dev *rtwdev)
rtw8852bt_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0);
}
-static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx;
- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx;
+ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
+ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx);
rtw8852bt_iqk(rtwdev, phy_idx, chanctx_idx);
@@ -553,10 +554,12 @@ static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev,
rtw8852bt_tssi_scan(rtwdev, phy_idx, chan);
}
-static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool start)
{
- rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx);
+ rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx,
+ rtwvif_link->chanctx_idx);
}
static void rtw8852bt_rfk_track(struct rtw89_dev *rtwdev)
@@ -739,6 +742,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.wde_qempty_acq_grpnum = 4,
.wde_qempty_mgq_grpsel = 4,
.rf_base_addr = {0xe000, 0xf000},
+ .thermal_th = {0x32, 0x35},
.pwr_on_seq = NULL,
.pwr_off_seq = NULL,
.bb_table = NULL,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c
index 702948119646..e4f40c2e287d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c
@@ -60,6 +60,8 @@ static const struct rtw89_pci_info rtw8852bt_pci_info = {
.enable_intr = rtw89_pci_enable_intr,
.disable_intr = rtw89_pci_disable_intr,
.recognize_intrs = rtw89_pci_recognize_intrs,
+
+ .ssid_quirks = NULL,
};
static const struct rtw89_driver_info rtw89_8852bte_info = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 1c6e89ab0f4b..cde34f8e1e67 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -203,7 +203,7 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path,
static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev)
{
u32 val32;
- u32 ret;
+ int ret;
val32 = rtw89_read32_mask(rtwdev, R_AX_SYS_STATUS1, B_AX_PAD_HCI_SEL_V2_MASK);
if (val32 == MAC_AX_HCI_SEL_PCIE_USB)
@@ -324,7 +324,7 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev)
static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev)
{
u32 val32;
- u32 ret;
+ int ret;
ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF,
XTAL_SI_RFC2RF);
@@ -1846,10 +1846,11 @@ static void rtw8852c_rfk_init(struct rtw89_dev *rtwdev)
rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false);
}
-static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx;
- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx;
+ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
+ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
rtw8852c_mcc_get_ch_info(rtwdev, phy_idx);
rtw8852c_rx_dck(rtwdev, phy_idx, false);
@@ -1866,10 +1867,11 @@ static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev,
rtw8852c_tssi_scan(rtwdev, phy_idx, chan);
}
-static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool start)
{
- rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx);
+ rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx);
}
static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev)
@@ -2945,6 +2947,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.wde_qempty_acq_grpnum = 16,
.wde_qempty_mgq_grpsel = 16,
.rf_base_addr = {0xe000, 0xf000},
+ .thermal_th = {0x32, 0x35},
.pwr_on_seq = NULL,
.pwr_off_seq = NULL,
.bb_table = &rtw89_8852c_phy_bb_table,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
index 211c051c2967..bd17c0a1c684 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
@@ -1065,7 +1065,7 @@ static bool _iqk_nbtxk(struct rtw89_dev *rtwdev,
static bool _lok_finetune_check(struct rtw89_dev *rtwdev, u8 path)
{
- struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
u8 idx = rfk_mcc->table_idx;
bool is_fail1, is_fail2;
@@ -1408,7 +1408,7 @@ static void _iqk_afebb_restore(struct rtw89_dev *rtwdev,
static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path)
{
- struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
u8 idx = 0;
idx = rfk_mcc->table_idx;
@@ -2350,7 +2350,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
if (dgain > 0x5fc || dgain < 0x556) {
_dpk_one_shot(rtwdev, phy, path, D_SYNC);
- dgain = _dpk_dgain_read(rtwdev);
+ _dpk_dgain_read(rtwdev);
}
if (agc_cnt == 0) {
@@ -4105,7 +4105,7 @@ void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
- struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V0] = {};
const struct rtw89_chan *chan;
enum rtw89_entity_mode mode;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
index 8aaad7d58c0d..1a46878be96b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
@@ -67,6 +67,8 @@ static const struct rtw89_pci_info rtw8852c_pci_info = {
.enable_intr = rtw89_pci_enable_intr_v1,
.disable_intr = rtw89_pci_disable_intr_v1,
.recognize_intrs = rtw89_pci_recognize_intrs_v1,
+
+ .ssid_quirks = NULL,
};
static const struct dmi_system_id rtw8852c_pci_quirks[] = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 63b1ff2f98ed..9a4db04a1967 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2023 Realtek Corporation
*/
+#include "chan.h"
#include "coex.h"
#include "debug.h"
#include "efuse.h"
@@ -13,7 +14,7 @@
#include "rtw8922a_rfk.h"
#include "util.h"
-#define RTW8922A_FW_FORMAT_MAX 1
+#define RTW8922A_FW_FORMAT_MAX 2
#define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw"
#define RTW8922A_MODULE_FIRMWARE \
RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin"
@@ -398,9 +399,6 @@ static int rtw8922a_pwr_on_func(struct rtw89_dev *rtwdev)
rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE, B_BE_FEN_BB_IP_RSTN |
B_BE_FEN_BBPLAT_RSTB);
- if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags))
- rtw89_efuse_read_fw_secure_be(rtwdev);
-
return 0;
}
@@ -965,6 +963,42 @@ static const struct rtw8922a_bb_gain bb_gain_tia[TIA_GAIN_NUM] = {
.gain_g_mask = 0x1FF, .gain_a_mask = 0x3FE00 },
};
+static const struct rtw8922a_bb_gain bb_op1db_lna[LNA_GAIN_NUM] = {
+ { .gain_g = {0x40ac, 0x44ac}, .gain_a = {0x4078, 0x4478},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x40ac, 0x44ac}, .gain_a = {0x407c, 0x447c},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x40ac, 0x44ac}, .gain_a = {0x407c, 0x447c},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF00},
+ { .gain_g = {0x40b0, 0x44b0}, .gain_a = {0x407c, 0x447c},
+ .gain_g_mask = 0xFF, .gain_a_mask = 0xFF0000},
+ { .gain_g = {0x40b0, 0x44b0}, .gain_a = {0x407c, 0x447c},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x40b0, 0x44b0}, .gain_a = {0x4080, 0x4480},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x40b0, 0x44b0}, .gain_a = {0x4080, 0x4480},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF00},
+};
+
+static const struct rtw8922a_bb_gain bb_op1db_tia_lna[TIA_LNA_OP1DB_NUM] = {
+ { .gain_g = {0x40b4, 0x44b4}, .gain_a = {0x4080, 0x4480},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x40b4, 0x44b4}, .gain_a = {0x4084, 0x4484},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x40b8, 0x44b8}, .gain_a = {0x4084, 0x4484},
+ .gain_g_mask = 0xFF, .gain_a_mask = 0xFF00},
+ { .gain_g = {0x40b8, 0x44b8}, .gain_a = {0x4084, 0x4484},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF0000},
+ { .gain_g = {0x40b8, 0x44b8}, .gain_a = {0x4084, 0x4484},
+ .gain_g_mask = 0xFF0000, .gain_a_mask = 0xFF000000},
+ { .gain_g = {0x40b8, 0x44b8}, .gain_a = {0x4088, 0x4488},
+ .gain_g_mask = 0xFF000000, .gain_a_mask = 0xFF},
+ { .gain_g = {0x40bc, 0x44bc}, .gain_a = {0x4088, 0x4488},
+ .gain_g_mask = 0xFF, .gain_a_mask = 0xFF00},
+ { .gain_g = {0x40bc, 0x44bc}, .gain_a = {0x4088, 0x4488},
+ .gain_g_mask = 0xFF00, .gain_a_mask = 0xFF0000},
+};
+
struct rtw8922a_bb_gain_bypass {
u32 gain_g[BB_PATH_NUM_8922A];
u32 gain_a[BB_PATH_NUM_8922A];
@@ -1056,6 +1090,30 @@ static void rtw8922a_set_lna_tia_gain(struct rtw89_dev *rtwdev,
val = gain->tia_gain[gain_band][bw_type][path][i];
rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
}
+
+ for (i = 0; i < LNA_GAIN_NUM; i++) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ reg = bb_op1db_lna[i].gain_g[path];
+ mask = bb_op1db_lna[i].gain_g_mask;
+ } else {
+ reg = bb_op1db_lna[i].gain_a[path];
+ mask = bb_op1db_lna[i].gain_a_mask;
+ }
+ val = gain->lna_op1db[gain_band][bw_type][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
+
+ for (i = 0; i < TIA_LNA_OP1DB_NUM; i++) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ reg = bb_op1db_tia_lna[i].gain_g[path];
+ mask = bb_op1db_tia_lna[i].gain_g_mask;
+ } else {
+ reg = bb_op1db_tia_lna[i].gain_a[path];
+ mask = bb_op1db_tia_lna[i].gain_a_mask;
+ }
+ val = gain->tia_lna_op1db[gain_band][bw_type][path][i];
+ rtw89_phy_write32_idx(rtwdev, reg, mask, val, phy_idx);
+ }
}
static void rtw8922a_set_gain(struct rtw89_dev *rtwdev,
@@ -1745,7 +1803,7 @@ static void rtw8922a_digital_pwr_comp(struct rtw89_dev *rtwdev,
static int rtw8922a_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode mode)
{
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
+ const struct rtw89_chan *chan0, *chan1;
if (mode == MLO_1_PLUS_1_1RF || mode == DBCC_LEGACY) {
rtw89_phy_write32_mask(rtwdev, R_DBCC, B_DBCC_EN, 0x1);
@@ -1758,13 +1816,20 @@ static int rtw8922a_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode
return -EOPNOTSUPP;
}
- if (mode == MLO_2_PLUS_0_1RF) {
- rtw8922a_ctrl_afe_dac(rtwdev, chan->band_width, RF_PATH_A);
- rtw8922a_ctrl_afe_dac(rtwdev, chan->band_width, RF_PATH_B);
+ if (mode == MLO_1_PLUS_1_1RF) {
+ chan0 = rtw89_mgnt_chan_get(rtwdev, 0);
+ chan1 = rtw89_mgnt_chan_get(rtwdev, 1);
+ } else if (mode == MLO_0_PLUS_2_1RF) {
+ chan1 = rtw89_mgnt_chan_get(rtwdev, 1);
+ chan0 = chan1;
} else {
- rtw89_warn(rtwdev, "unsupported MLO mode %d\n", mode);
+ chan0 = rtw89_mgnt_chan_get(rtwdev, 0);
+ chan1 = chan0;
}
+ rtw8922a_ctrl_afe_dac(rtwdev, chan0->band_width, RF_PATH_A);
+ rtw8922a_ctrl_afe_dac(rtwdev, chan1->band_width, RF_PATH_B);
+
rtw89_phy_write32_mask(rtwdev, R_EMLSR, B_EMLSR_PARM, 0x6180);
if (mode == MLO_2_PLUS_0_1RF) {
@@ -1991,14 +2056,23 @@ static void rtw8922a_rfk_init(struct rtw89_dev *rtwdev)
memset(rfk_mcc, 0, sizeof(*rfk_mcc));
}
+static void __rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx,
+ const struct rtw89_chan *chan)
+{
+ rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5);
+
+ rtw89_phy_rfk_dack_and_wait(rtwdev, phy_idx, chan, 58);
+ rtw89_phy_rfk_rxdck_and_wait(rtwdev, phy_idx, chan, false, 32);
+}
+
static void rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
- rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, RTW89_PHY_0, 5);
-
- rtw89_phy_rfk_dack_and_wait(rtwdev, RTW89_PHY_0, chan, 58);
- rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, 32);
+ __rtw8922a_rfk_init_late(rtwdev, RTW89_PHY_0, chan);
+ if (rtwdev->dbcc_en)
+ __rtw8922a_rfk_init_late(rtwdev, RTW89_PHY_1, chan);
}
static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath)
@@ -2020,11 +2094,12 @@ static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath)
}
}
-static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
- enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx;
+ enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx);
- enum rtw89_phy_idx phy_idx = rtwvif->phy_idx;
+ enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB, chanctx_idx);
u32 tx_en;
@@ -2035,9 +2110,9 @@ static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtw
rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5);
rtw89_phy_rfk_txgapk_and_wait(rtwdev, phy_idx, chan, 54);
rtw89_phy_rfk_iqk_and_wait(rtwdev, phy_idx, chan, 84);
- rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_NORMAL, 6);
+ rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_NORMAL, 20);
rtw89_phy_rfk_dpk_and_wait(rtwdev, phy_idx, chan, 34);
- rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, 32);
+ rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, true, 32);
rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_CHLK, BTC_WRFK_STOP);
@@ -2050,7 +2125,8 @@ static void rtw8922a_rfk_band_changed(struct rtw89_dev *rtwdev,
rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_SCAN, 6);
}
-static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
bool start)
{
}
@@ -2207,10 +2283,12 @@ static void rtw8922a_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
static u8 rtw8922a_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path)
{
struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ struct rtw89_hal *hal = &rtwdev->hal;
int th;
- /* read thermal only if debugging */
- if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_CFO | RTW89_DBG_RFK_TRACK))
+ /* read thermal only if debugging or thermal protection enabled */
+ if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_CFO | RTW89_DBG_RFK_TRACK) &&
+ !hal->thermal_prot_th)
return 80;
rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1);
@@ -2641,6 +2719,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.wde_qempty_acq_grpnum = 4,
.wde_qempty_mgq_grpsel = 4,
.rf_base_addr = {0xe000, 0xf000},
+ .thermal_th = {0xad, 0xb4},
.pwr_on_seq = NULL,
.pwr_off_seq = NULL,
.bb_table = NULL,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c
index 28907df7407d..c4c93f836a2f 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c
@@ -252,49 +252,58 @@ static void rtw8922a_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx)
}
}
-static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev)
+static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan, u8 path)
{
struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {};
- enum rtw89_chanctx_idx chanctx_idx;
- const struct rtw89_chan *chan;
- enum rtw89_entity_mode mode;
- u8 s0_tbl, s1_tbl;
u8 tbl_sel;
- mode = rtw89_get_entity_mode(rtwdev);
- switch (mode) {
- case RTW89_ENTITY_MODE_MCC_PREPARE:
- chanctx_idx = RTW89_CHANCTX_1;
- break;
- default:
- chanctx_idx = RTW89_CHANCTX_0;
- break;
- }
-
- chan = rtw89_chan_get(rtwdev, chanctx_idx);
-
for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) {
struct rtw89_rfk_chan_desc *p = &desc[tbl_sel];
- p->ch = rfk_mcc->ch[tbl_sel];
+ p->ch = rfk_mcc->data[path].ch[tbl_sel];
p->has_band = true;
- p->band = rfk_mcc->band[tbl_sel];
+ p->band = rfk_mcc->data[path].band[tbl_sel];
p->has_bw = true;
- p->bw = rfk_mcc->bw[tbl_sel];
+ p->bw = rfk_mcc->data[path].bw[tbl_sel];
}
tbl_sel = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan);
- rfk_mcc->ch[tbl_sel] = chan->channel;
- rfk_mcc->band[tbl_sel] = chan->band_type;
- rfk_mcc->bw[tbl_sel] = chan->band_width;
- rfk_mcc->table_idx = tbl_sel;
+ rfk_mcc->data[path].ch[tbl_sel] = chan->channel;
+ rfk_mcc->data[path].band[tbl_sel] = chan->band_type;
+ rfk_mcc->data[path].bw[tbl_sel] = chan->band_width;
+ rfk_mcc->data[path].table_idx = tbl_sel;
+
+ return tbl_sel;
+}
+
+static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_chan *chan0, *chan1;
+ u8 s0_tbl, s1_tbl;
+
+ switch (rtwdev->mlo_dbcc_mode) {
+ default:
+ case MLO_2_PLUS_0_1RF:
+ chan0 = rtw89_mgnt_chan_get(rtwdev, 0);
+ chan1 = chan0;
+ break;
+ case MLO_0_PLUS_2_1RF:
+ chan1 = rtw89_mgnt_chan_get(rtwdev, 1);
+ chan0 = chan1;
+ break;
+ case MLO_1_PLUS_1_1RF:
+ chan0 = rtw89_mgnt_chan_get(rtwdev, 0);
+ chan1 = rtw89_mgnt_chan_get(rtwdev, 1);
+ break;
+ }
- s0_tbl = tbl_sel;
- s1_tbl = tbl_sel;
+ s0_tbl = rtw8922a_chlk_reload_sel_tbl(rtwdev, chan0, 0);
+ s1_tbl = rtw8922a_chlk_reload_sel_tbl(rtwdev, chan1, 1);
rtw8922a_chlk_ktbl_sel(rtwdev, RF_A, s0_tbl);
rtw8922a_chlk_ktbl_sel(rtwdev, RF_B, s1_tbl);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c
index 47f855a7a268..edfb1f220af0 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c
@@ -9,6 +9,12 @@
#include "reg.h"
#include "rtw8922a.h"
+static const struct rtw89_pci_ssid_quirk rtw8922a_pci_ssid_quirks[] = {
+ {RTW89_PCI_SSID(PCI_VENDOR_ID_REALTEK, 0x8922, 0x10EC, 0xA891, DELL),
+ .bitmap = BIT(RTW89_QUIRK_THERMAL_PROT_120C)},
+ {},
+};
+
static const struct rtw89_pci_info rtw8922a_pci_info = {
.gen_def = &rtw89_pci_gen_be,
.txbd_trunc_mode = MAC_AX_BD_TRUNC,
@@ -58,6 +64,8 @@ static const struct rtw89_pci_info rtw8922a_pci_info = {
.enable_intr = rtw89_pci_enable_intr_v2,
.disable_intr = rtw89_pci_disable_intr_v2,
.recognize_intrs = rtw89_pci_recognize_intrs_v2,
+
+ .ssid_quirks = rtw8922a_pci_ssid_quirks,
};
static const struct rtw89_driver_info rtw89_8922ae_info = {
diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c
index 27826d909785..bcc287771b2a 100644
--- a/drivers/net/wireless/realtek/rtw89/sar.c
+++ b/drivers/net/wireless/realtek/rtw89/sar.c
@@ -27,8 +27,8 @@ static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
return RTW89_SAR_5GHZ_SUBBAND_1_2;
case 5500 ... 5720:
return RTW89_SAR_5GHZ_SUBBAND_2_E;
- case 5745 ... 5825:
- return RTW89_SAR_5GHZ_SUBBAND_3;
+ case 5745 ... 5885:
+ return RTW89_SAR_5GHZ_SUBBAND_3_4;
case 5955 ... 6155:
return RTW89_SAR_6GHZ_SUBBAND_5_L;
case 6175 ... 6415:
@@ -295,7 +295,7 @@ static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = {
{ .start_freq = 2412, .end_freq = 2484, },
{ .start_freq = 5180, .end_freq = 5320, },
{ .start_freq = 5500, .end_freq = 5720, },
- { .start_freq = 5745, .end_freq = 5825, },
+ { .start_freq = 5745, .end_freq = 5885, },
{ .start_freq = 5955, .end_freq = 6155, },
{ .start_freq = 6175, .end_freq = 6415, },
{ .start_freq = 6435, .end_freq = 6515, },
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index 5fc2faa9ba5a..7b203bb7f151 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -300,37 +300,54 @@ static void drv_resume_rx(struct rtw89_ser *ser)
static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
- rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
- rtwvif->net_type = RTW89_NET_TYPE_NO_LINK;
- rtwvif->trigger = false;
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
+
rtwvif->tdls_peer = 0;
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port);
+ rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK;
+ rtwvif_link->trigger = false;
+ }
}
static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw89_vif *target_rtwvif = (struct rtw89_vif *)data;
- struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
if (rtwvif != target_rtwvif)
return;
- if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
- rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
- if (sta->tdls)
- rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam);
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
+ rtwvif_link = rtwsta_link->rtwvif_link;
- INIT_LIST_HEAD(&rtwsta->ba_cam_list);
+ if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls)
+ rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam);
+ if (sta->tdls)
+ rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam);
+
+ INIT_LIST_HEAD(&rtwsta_link->ba_cam_list);
+ }
}
static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
+
ieee80211_iterate_stations_atomic(rtwdev->hw,
ser_sta_deinit_cam_iter,
rtwvif);
- rtw89_cam_deinit(rtwdev, rtwvif);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
+ rtw89_cam_deinit(rtwdev, rtwvif_link);
bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM);
}
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 86e24e07780d..3e81fd974ec1 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -421,7 +421,8 @@ static void rtw89_wow_construct_key_info(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_key_info *key_info = &rtw_wow->key_info;
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
bool err = false;
rcu_read_lock();
@@ -596,7 +597,8 @@ static int rtw89_wow_get_aoac_rpt(struct rtw89_dev *rtwdev, bool rx_ready)
static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
u32 cipher, u8 keyidx, u8 *gtk)
{
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
const struct rtw89_cipher_info *cipher_info;
struct ieee80211_key_conf *rekey_conf;
struct ieee80211_key_conf *key;
@@ -632,11 +634,13 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready)
{
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct rtw89_set_key_info_iter_data data = {.error = false,
.rx_ready = rx_ready};
+ struct ieee80211_bss_conf *bss_conf;
struct ieee80211_key_conf *key;
rcu_read_lock();
@@ -669,9 +673,15 @@ static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready)
return;
rtw89_rx_pn_set_pmf(rtwdev, key, aoac_rpt->igtk_ipn);
- ieee80211_gtk_rekey_notify(wow_vif, wow_vif->bss_conf.bssid,
+
+ rcu_read_lock();
+
+ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+ ieee80211_gtk_rekey_notify(wow_vif, bss_conf->bssid,
aoac_rpt->eapol_key_replay_count,
- GFP_KERNEL);
+ GFP_ATOMIC);
+
+ rcu_read_unlock();
}
static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev)
@@ -681,27 +691,24 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev)
static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev)
{
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
- __rtw89_enter_ps_mode(rtwdev, rtwvif);
+ __rtw89_enter_ps_mode(rtwdev, rtwvif_link);
}
static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev)
{
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
if (rtw89_wow_mgd_linked(rtwdev))
- rtw89_enter_lps(rtwdev, rtwvif, false);
+ rtw89_enter_lps(rtwdev, rtwvif_link, false);
else if (rtw89_wow_no_link(rtwdev))
- rtw89_fw_h2c_fwips(rtwdev, rtwvif, true);
+ rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, true);
}
static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow)
{
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
if (rtw89_wow_mgd_linked(rtwdev)) {
rtw89_leave_lps(rtwdev);
@@ -709,7 +716,7 @@ static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow)
if (enable_wow)
rtw89_leave_ips(rtwdev);
else
- rtw89_fw_h2c_fwips(rtwdev, rtwvif, false);
+ rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, false);
}
}
@@ -734,6 +741,8 @@ static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable)
static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
{
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
+ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
struct cfg80211_wowlan_nd_info nd_info;
@@ -780,35 +789,34 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
break;
default:
rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason);
- ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL,
- GFP_KERNEL);
+ ieee80211_report_wowlan_wakeup(wow_vif, NULL, GFP_KERNEL);
return;
}
- ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup,
- GFP_KERNEL);
+ ieee80211_report_wowlan_wakeup(wow_vif, &wakeup, GFP_KERNEL);
}
-static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
/* Current WoWLAN function support setting of only vif in
* infra mode or no link mode. When one suitable vif is found,
* stop the iteration.
*/
- if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION)
+ if (rtw_wow->rtwvif_link || vif->type != NL80211_IFTYPE_STATION)
return;
- switch (rtwvif->net_type) {
+ switch (rtwvif_link->net_type) {
case RTW89_NET_TYPE_INFRA:
if (rtw_wow_has_mgd_features(rtwdev))
- rtw_wow->wow_vif = vif;
+ rtw_wow->rtwvif_link = rtwvif_link;
break;
case RTW89_NET_TYPE_NO_LINK:
if (rtw_wow->pno_inited)
- rtw_wow->wow_vif = vif;
+ rtw_wow->rtwvif_link = rtwvif_link;
break;
default:
break;
@@ -865,7 +873,7 @@ static u16 rtw89_calc_crc(u8 *pdata, int length)
return ~crc;
}
-static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif,
+static int rtw89_wow_pattern_get_type(struct rtw89_vif_link *rtwvif_link,
struct rtw89_wow_cam_info *rtw_pattern,
const u8 *pattern, u8 da_mask)
{
@@ -885,7 +893,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif,
rtw_pattern->bc = true;
else if (is_multicast_ether_addr(da))
rtw_pattern->mc = true;
- else if (ether_addr_equal(da, rtwvif->mac_addr) &&
+ else if (ether_addr_equal(da, rtwvif_link->mac_addr) &&
da_mask == GENMASK(5, 0))
rtw_pattern->uc = true;
else if (!da_mask) /*da_mask == 0 mean wildcard*/
@@ -897,7 +905,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif,
}
static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
const struct cfg80211_pkt_pattern *pkt_pattern,
struct rtw89_wow_cam_info *rtw_pattern)
{
@@ -916,7 +924,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev,
mask_len = DIV_ROUND_UP(len, 8);
memset(rtw_pattern, 0, sizeof(*rtw_pattern));
- ret = rtw89_wow_pattern_get_type(rtwvif, rtw_pattern, pattern,
+ ret = rtw89_wow_pattern_get_type(rtwvif_link, rtw_pattern, pattern,
mask[0] & GENMASK(5, 0));
if (ret)
return ret;
@@ -970,7 +978,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev,
}
static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif,
+ struct rtw89_vif_link *rtwvif_link,
struct cfg80211_wowlan *wowlan)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
@@ -983,7 +991,7 @@ static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev,
for (i = 0; i < wowlan->n_patterns; i++) {
rtw_pattern = &rtw_wow->patterns[i];
- ret = rtw89_wow_pattern_generate(rtwdev, rtwvif,
+ ret = rtw89_wow_pattern_generate(rtwdev, rtwvif_link,
&wowlan->patterns[i],
rtw_pattern);
if (ret) {
@@ -1040,7 +1048,7 @@ static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- rtw_wow->wow_vif = NULL;
+ rtw_wow->rtwvif_link = NULL;
rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM);
rtw_wow->pattern_cnt = 0;
rtw_wow->pno_inited = false;
@@ -1066,6 +1074,7 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev,
struct cfg80211_wowlan *wowlan)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_vif *rtwvif;
if (wowlan->disconnect)
@@ -1078,36 +1087,40 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev,
if (wowlan->nd_config)
rtw89_wow_init_pno(rtwdev, wowlan->nd_config);
- rtw89_for_each_rtwvif(rtwdev, rtwvif)
- rtw89_wow_vif_iter(rtwdev, rtwvif);
+ rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+ /* use the link on HW-0 to do wow flow */
+ rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
+ if (!rtwvif_link)
+ continue;
+
+ rtw89_wow_vif_iter(rtwdev, rtwvif_link);
+ }
- if (!rtw_wow->wow_vif)
+ rtwvif_link = rtw_wow->rtwvif_link;
+ if (!rtwvif_link)
return -EPERM;
- rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv;
- return rtw89_wow_parse_patterns(rtwdev, rtwvif, wowlan);
+ return rtw89_wow_parse_patterns(rtwdev, rtwvif_link, wowlan);
}
static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow)
{
- struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
int ret;
- ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, true);
+ ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, true);
if (ret) {
rtw89_err(rtwdev, "failed to config pno\n");
return ret;
}
- ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow);
+ ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow);
if (ret) {
rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n");
return ret;
}
- ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow);
+ ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow);
if (ret) {
rtw89_err(rtwdev, "failed to fw wow global\n");
return ret;
@@ -1119,34 +1132,39 @@ static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow)
static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
+ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
struct ieee80211_sta *wow_sta;
- struct rtw89_sta *rtwsta = NULL;
+ struct rtw89_sta_link *rtwsta_link = NULL;
+ struct rtw89_sta *rtwsta;
int ret;
- wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid);
- if (wow_sta)
- rtwsta = (struct rtw89_sta *)wow_sta->drv_priv;
+ wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr);
+ if (wow_sta) {
+ rtwsta = sta_to_rtwsta(wow_sta);
+ rtwsta_link = rtwsta->links[rtwvif_link->link_id];
+ if (!rtwsta_link)
+ return -ENOLINK;
+ }
if (wow) {
if (rtw_wow->pattern_cnt)
- rtwvif->wowlan_pattern = true;
+ rtwvif_link->wowlan_pattern = true;
if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags))
- rtwvif->wowlan_magic = true;
+ rtwvif_link->wowlan_magic = true;
} else {
- rtwvif->wowlan_pattern = false;
- rtwvif->wowlan_magic = false;
+ rtwvif_link->wowlan_pattern = false;
+ rtwvif_link->wowlan_magic = false;
}
- ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow);
+ ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow);
if (ret) {
rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n");
return ret;
}
if (wow) {
- ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
+ ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link);
if (ret) {
rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n",
ret);
@@ -1154,13 +1172,13 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow)
}
}
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret;
}
- ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow);
+ ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow);
if (ret) {
rtw89_err(rtwdev, "failed to fw wow global\n");
return ret;
@@ -1190,25 +1208,30 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL;
enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
+ struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link);
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
const struct rtw89_chip_info *chip = rtwdev->chip;
bool include_bb = !!chip->bbmcu_nr;
bool disable_intr_for_dlfw = false;
struct ieee80211_sta *wow_sta;
- struct rtw89_sta *rtwsta = NULL;
+ struct rtw89_sta_link *rtwsta_link = NULL;
+ struct rtw89_sta *rtwsta;
bool is_conn = true;
int ret;
if (chip_id == RTL8852C || chip_id == RTL8922A)
disable_intr_for_dlfw = true;
- wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid);
- if (wow_sta)
- rtwsta = (struct rtw89_sta *)wow_sta->drv_priv;
- else
+ wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr);
+ if (wow_sta) {
+ rtwsta = sta_to_rtwsta(wow_sta);
+ rtwsta_link = rtwsta->links[rtwvif_link->link_id];
+ if (!rtwsta_link)
+ return -ENOLINK;
+ } else {
is_conn = false;
+ }
if (disable_intr_for_dlfw)
rtw89_hci_disable_intr(rtwdev);
@@ -1224,14 +1247,14 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
rtw89_phy_init_rf_reg(rtwdev, true);
- ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
+ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link,
RTW89_ROLE_FW_RESTORE);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c role maintain\n");
return ret;
}
- ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta);
+ ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n");
return ret;
@@ -1240,27 +1263,27 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
if (!is_conn)
rtw89_cam_reset_keys(rtwdev);
- ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn);
+ ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, !is_conn);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c join info\n");
return ret;
}
- ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
+ ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c cam\n");
return ret;
}
if (is_conn) {
- ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id);
+ ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id);
if (ret) {
rtw89_warn(rtwdev, "failed to send h2c general packet\n");
return ret;
}
- rtw89_phy_ra_assoc(rtwdev, wow_sta);
- rtw89_phy_set_bss_color(rtwdev, wow_vif);
- rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif);
+ rtw89_phy_ra_assoc(rtwdev, rtwsta_link);
+ rtw89_phy_set_bss_color(rtwdev, rtwvif_link);
+ rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link);
}
if (chip_gen == RTW89_CHIP_BE)
@@ -1363,21 +1386,20 @@ static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev)
static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev)
{
- struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *vif = rtw_wow->wow_vif;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
int ret;
ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
if (ret)
rtw89_err(rtwdev, "cfg ppdu status\n");
- rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
return ret;
}
static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct list_head *pkt_list = &rtw_wow->pno_pkt_list;
@@ -1391,7 +1413,7 @@ static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev,
}
static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config;
@@ -1401,7 +1423,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev,
int ret;
for (i = 0; i < num; i++) {
- skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr,
+ skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr,
nd_config->match_sets[i].ssid.ssid,
nd_config->match_sets[i].ssid.ssid_len,
nd_config->ie_len);
@@ -1413,7 +1435,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev,
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
kfree_skb(skb);
- rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif);
+ rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link);
return -ENOMEM;
}
@@ -1421,7 +1443,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev,
if (ret) {
kfree_skb(skb);
kfree(info);
- rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif);
+ rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link);
return ret;
}
@@ -1436,20 +1458,19 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
int interval = rtw_wow->nd_config->scan_plans[0].interval;
struct rtw89_scan_option opt = {};
int ret;
if (enable) {
- ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif);
+ ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif_link);
if (ret) {
rtw89_err(rtwdev, "Update probe request failed\n");
return ret;
}
- ret = mac->add_chan_list_pno(rtwdev, rtwvif);
+ ret = mac->add_chan_list_pno(rtwdev, rtwvif_link);
if (ret) {
rtw89_err(rtwdev, "Update channel list failed\n");
return ret;
@@ -1471,7 +1492,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable)
opt.opch_end = RTW89_CHAN_INVALID;
}
- mac->scan_offload(rtwdev, &opt, rtwvif, true);
+ mac->scan_offload(rtwdev, &opt, rtwvif_link, true);
return 0;
}
@@ -1479,8 +1500,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable)
static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
int ret;
if (rtw89_wow_no_link(rtwdev)) {
@@ -1499,25 +1519,25 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
rtw89_wow_pattern_write(rtwdev);
rtw89_wow_construct_key_info(rtwdev);
- ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true);
+ ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, true);
if (ret) {
rtw89_err(rtwdev, "wow: failed to enable keep alive\n");
return ret;
}
- ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, true);
+ ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, true);
if (ret) {
rtw89_err(rtwdev, "wow: failed to enable disconnect detect\n");
return ret;
}
- ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, true);
+ ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, true);
if (ret) {
rtw89_err(rtwdev, "wow: failed to enable GTK offload\n");
return ret;
}
- ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, true);
+ ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, true);
if (ret)
rtw89_warn(rtwdev, "wow: failed to enable arp offload\n");
}
@@ -1548,8 +1568,7 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev)
{
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
- struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link;
int ret;
if (rtw89_wow_no_link(rtwdev)) {
@@ -1559,35 +1578,35 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev)
return ret;
}
- ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, false);
+ ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, false);
if (ret) {
rtw89_err(rtwdev, "wow: failed to disable pno\n");
return ret;
}
- rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif);
+ rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link);
} else {
rtw89_wow_pattern_clear(rtwdev);
- ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, false);
+ ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, false);
if (ret) {
rtw89_err(rtwdev, "wow: failed to disable keep alive\n");
return ret;
}
- ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false);
+ ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, false);
if (ret) {
rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n");
return ret;
}
- ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, false);
+ ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, false);
if (ret) {
rtw89_err(rtwdev, "wow: failed to disable GTK offload\n");
return ret;
}
- ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, false);
+ ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, false);
if (ret)
rtw89_warn(rtwdev, "wow: failed to disable arp offload\n");
diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h
index 3fbc2b87c058..f91991e8f2e3 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.h
+++ b/drivers/net/wireless/realtek/rtw89/wow.h
@@ -97,18 +97,16 @@ static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev)
#ifdef CONFIG_PM
static inline bool rtw89_wow_mgd_linked(struct rtw89_dev *rtwdev)
{
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
- return rtwvif->net_type == RTW89_NET_TYPE_INFRA;
+ return rtwvif_link->net_type == RTW89_NET_TYPE_INFRA;
}
static inline bool rtw89_wow_no_link(struct rtw89_dev *rtwdev)
{
- struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
- struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
- return rtwvif->net_type == RTW89_NET_TYPE_NO_LINK;
+ return rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK;
}
static inline bool rtw_wow_has_mgd_features(struct rtw89_dev *rtwdev)
diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c
index e7198520bdff..64441c8bc460 100644
--- a/drivers/net/wireless/silabs/wfx/main.c
+++ b/drivers/net/wireless/silabs/wfx/main.c
@@ -480,10 +480,23 @@ static int __init wfx_core_init(void)
{
int ret = 0;
- if (IS_ENABLED(CONFIG_SPI))
+ if (IS_ENABLED(CONFIG_SPI)) {
ret = spi_register_driver(&wfx_spi_driver);
- if (IS_ENABLED(CONFIG_MMC) && !ret)
+ if (ret)
+ goto out;
+ }
+ if (IS_ENABLED(CONFIG_MMC)) {
ret = sdio_register_driver(&wfx_sdio_driver);
+ if (ret)
+ goto unregister_spi;
+ }
+
+ return 0;
+
+unregister_spi:
+ if (IS_ENABLED(CONFIG_SPI))
+ spi_unregister_driver(&wfx_spi_driver);
+out:
return ret;
}
module_init(wfx_core_init);
diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c
index 4f346fb977a9..862964a8cc87 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c
@@ -450,7 +450,7 @@ static int __maybe_unused cw1200_spi_suspend(struct device *dev)
{
struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev));
- if (!cw1200_can_suspend(self->core))
+ if (self && !cw1200_can_suspend(self->core))
return -EAGAIN;
/* XXX notify host that we have to keep CW1200 powered on? */
diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c
index 805a3c1bf8fe..259739e53fc1 100644
--- a/drivers/net/wireless/st/cw1200/queue.c
+++ b/drivers/net/wireless/st/cw1200/queue.c
@@ -411,33 +411,6 @@ int cw1200_queue_requeue(struct cw1200_queue *queue, u32 packet_id)
return ret;
}
-int cw1200_queue_requeue_all(struct cw1200_queue *queue)
-{
- struct cw1200_queue_item *item, *tmp;
- struct cw1200_queue_stats *stats = queue->stats;
- spin_lock_bh(&queue->lock);
-
- list_for_each_entry_safe_reverse(item, tmp, &queue->pending, head) {
- --queue->num_pending;
- ++queue->link_map_cache[item->txpriv.link_id];
-
- spin_lock_bh(&stats->lock);
- ++stats->num_queued;
- ++stats->link_map_cache[item->txpriv.link_id];
- spin_unlock_bh(&stats->lock);
-
- ++item->generation;
- item->packet_id = cw1200_queue_mk_packet_id(queue->generation,
- queue->queue_id,
- item->generation,
- item - queue->pool);
- list_move(&item->head, &queue->queue);
- }
- spin_unlock_bh(&queue->lock);
-
- return 0;
-}
-
int cw1200_queue_remove(struct cw1200_queue *queue, u32 packet_id)
{
int ret = 0;
diff --git a/drivers/net/wireless/st/cw1200/queue.h b/drivers/net/wireless/st/cw1200/queue.h
index 96ac69ae97de..d46304b58747 100644
--- a/drivers/net/wireless/st/cw1200/queue.h
+++ b/drivers/net/wireless/st/cw1200/queue.h
@@ -85,7 +85,6 @@ int cw1200_queue_get(struct cw1200_queue *queue,
struct ieee80211_tx_info **tx_info,
const struct cw1200_txpriv **txpriv);
int cw1200_queue_requeue(struct cw1200_queue *queue, u32 packet_id);
-int cw1200_queue_requeue_all(struct cw1200_queue *queue);
int cw1200_queue_remove(struct cw1200_queue *queue,
u32 packet_id);
int cw1200_queue_get_skb(struct cw1200_queue *queue, u32 packet_id,
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c
index c705081249d6..b45050243129 100644
--- a/drivers/net/wireless/ti/wl1251/sdio.c
+++ b/drivers/net/wireless/ti/wl1251/sdio.c
@@ -233,8 +233,8 @@ static int wl1251_sdio_probe(struct sdio_func *func,
}
if (wl->irq) {
- irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
- ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
+ ret = request_irq(wl->irq, wl1251_line_irq, IRQF_NO_AUTOEN,
+ "wl1251", wl);
if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret);
goto disable;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index b26d42b4e3cc..ffbf54776330 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1939,7 +1939,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
static struct platform_driver wl12xx_driver = {
.probe = wl12xx_probe,
- .remove_new = wl12xx_remove,
+ .remove = wl12xx_remove,
.id_table = wl12xx_id_table,
.driver = {
.name = "wl12xx_driver",
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 39d8eebb9b6e..4be1110bac88 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -2097,9 +2097,9 @@ MODULE_DEVICE_TABLE(platform, wl18xx_id_table);
static struct platform_driver wl18xx_driver = {
.probe = wl18xx_probe,
- .remove_new = wlcore_remove,
+ .remove = wlcore_remove,
.id_table = wl18xx_id_table,
- .driver = {
+ .driver = {
.name = "wl18xx_driver",
}
};
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 0c77b8524160..986b07bfa0ee 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5789,9 +5789,10 @@ static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
+ struct ieee80211_sta *sta = link_sta->sta;
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update");
@@ -6052,7 +6053,7 @@ static const struct ieee80211_ops wl1271_ops = {
.assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
.unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
- .sta_rc_update = wlcore_op_sta_rc_update,
+ .link_sta_rc_update = wlcore_op_sta_rc_update,
.sta_statistics = wlcore_op_sta_statistics,
.get_expected_throughput = wlcore_op_get_expected_throughput,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 92fb5b8dcdae..a73207bbe5d7 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -323,17 +323,12 @@ static int wl1271_probe(struct sdio_func *func,
memset(res, 0x00, sizeof(res));
- res[0].start = irq;
- res[0].flags = IORESOURCE_IRQ |
- irqd_get_trigger_type(irq_get_irq_data(irq));
- res[0].name = "irq";
-
+ res[0] = DEFINE_RES_IRQ_NAMED(irq, "irq");
+ res[0].flags |= irq_get_trigger_type(irq);
if (wakeirq > 0) {
- res[1].start = wakeirq;
- res[1].flags = IORESOURCE_IRQ |
- irqd_get_trigger_type(irq_get_irq_data(wakeirq));
- res[1].name = "wakeirq";
+ res[1] = DEFINE_RES_IRQ_NAMED(wakeirq, "wakeirq");
+ res[1].flags |= irq_get_trigger_type(wakeirq);
num_irqs = 2;
} else {
num_irqs = 1;
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 3f424f14de4e..347a15544afe 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -2442,7 +2442,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
if (!data->started || !link_data->beacon_int) {
hrtimer_cancel(&link_data->beacon_timer);
- } else if (!hrtimer_is_queued(&link_data->beacon_timer)) {
+ } else if (!hrtimer_active(&link_data->beacon_timer)) {
u64 tsf = mac80211_hwsim_get_tsf(hw, NULL);
u32 bcn_int = link_data->beacon_int;
u64 until_tbtt = bcn_int - do_div(tsf, bcn_int);
@@ -2537,7 +2537,7 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
info->enable_beacon, info->beacon_int);
vp->bcn_en = info->enable_beacon;
if (data->started &&
- !hrtimer_is_queued(&link_data->beacon_timer) &&
+ !hrtimer_active(&link_data->beacon_timer) &&
info->enable_beacon) {
u64 tsf, until_tbtt;
u32 bcn_int;
@@ -2594,10 +2594,11 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
static void
mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
+ struct ieee80211_link_sta *link_sta,
u32 changed)
{
struct mac80211_hwsim_data *data = hw->priv;
+ struct ieee80211_sta *sta = link_sta->sta;
u32 bw = U32_MAX;
int link_id;
@@ -2607,7 +2608,6 @@ mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw,
link_id++) {
enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT;
struct ieee80211_bss_conf *vif_conf;
- struct ieee80211_link_sta *link_sta;
link_sta = rcu_dereference(sta->link[link_id]);
@@ -2659,7 +2659,7 @@ static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
hwsim_check_magic(vif);
hwsim_set_sta_magic(sta);
- mac80211_hwsim_sta_rc_update(hw, vif, sta, 0);
+ mac80211_hwsim_sta_rc_update(hw, vif, &sta->deflink, 0);
if (sta->valid_links) {
WARN(hweight16(sta->valid_links) > 1,
@@ -3961,7 +3961,7 @@ out:
.link_info_changed = mac80211_hwsim_link_info_changed, \
.tx_last_beacon = mac80211_hwsim_tx_last_beacon, \
.sta_notify = mac80211_hwsim_sta_notify, \
- .sta_rc_update = mac80211_hwsim_sta_rc_update, \
+ .link_sta_rc_update = mac80211_hwsim_sta_rc_update, \
.conf_tx = mac80211_hwsim_conf_tx, \
.get_survey = mac80211_hwsim_get_survey, \
CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) \
diff --git a/drivers/net/wwan/qcom_bam_dmux.c b/drivers/net/wwan/qcom_bam_dmux.c
index 5dcb9a84a12e..64dab8b57611 100644
--- a/drivers/net/wwan/qcom_bam_dmux.c
+++ b/drivers/net/wwan/qcom_bam_dmux.c
@@ -896,7 +896,7 @@ MODULE_DEVICE_TABLE(of, bam_dmux_of_match);
static struct platform_driver bam_dmux_driver = {
.probe = bam_dmux_probe,
- .remove_new = bam_dmux_remove,
+ .remove = bam_dmux_remove,
.driver = {
.name = "bam-dmux",
.pm = &bam_dmux_pm_ops,
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
index 210d84c67ef9..7a9c09cd4fdc 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
@@ -226,7 +226,7 @@ int t7xx_dpmaif_rx_buf_alloc(struct dpmaif_ctrl *dpmaif_ctrl,
return 0;
err_unmap_skbs:
- while (--i > 0)
+ while (i--)
t7xx_unmap_bat_skb(dpmaif_ctrl->dev, bat_req->bat_skb, i);
return ret;
diff --git a/drivers/net/wwan/t7xx/t7xx_modem_ops.c b/drivers/net/wwan/t7xx/t7xx_modem_ops.c
index 79f17100f70b..7968e208dd37 100644
--- a/drivers/net/wwan/t7xx/t7xx_modem_ops.c
+++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.c
@@ -198,6 +198,7 @@ int t7xx_reset_device(struct t7xx_pci_dev *t7xx_dev, enum reset_type type)
pci_save_state(t7xx_dev->pdev);
t7xx_pci_reprobe_early(t7xx_dev);
t7xx_mode_update(t7xx_dev, T7XX_RESET);
+ WRITE_ONCE(t7xx_dev->debug_ports_show, false);
if (type == FLDR) {
ret = t7xx_acpi_reset(t7xx_dev, "_RST");
diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c
index e556e5bd49ab..8381b0dc7acb 100644
--- a/drivers/net/wwan/t7xx/t7xx_pci.c
+++ b/drivers/net/wwan/t7xx/t7xx_pci.c
@@ -41,6 +41,7 @@
#include "t7xx_pcie_mac.h"
#include "t7xx_reg.h"
#include "t7xx_state_monitor.h"
+#include "t7xx_port_proxy.h"
#define T7XX_PCI_IREG_BASE 0
#define T7XX_PCI_EREG_BASE 2
@@ -48,7 +49,7 @@
#define T7XX_INIT_TIMEOUT 20
#define PM_SLEEP_DIS_TIMEOUT_MS 20
#define PM_ACK_TIMEOUT_MS 1500
-#define PM_AUTOSUSPEND_MS 20000
+#define PM_AUTOSUSPEND_MS 5000
#define PM_RESOURCE_POLL_TIMEOUT_US 10000
#define PM_RESOURCE_POLL_STEP_US 100
@@ -120,13 +121,58 @@ static ssize_t t7xx_mode_show(struct device *dev,
static DEVICE_ATTR_RW(t7xx_mode);
-static struct attribute *t7xx_mode_attr[] = {
+static ssize_t t7xx_debug_ports_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct t7xx_pci_dev *t7xx_dev;
+ struct pci_dev *pdev;
+ bool show;
+ int ret;
+
+ pdev = to_pci_dev(dev);
+ t7xx_dev = pci_get_drvdata(pdev);
+ if (!t7xx_dev)
+ return -ENODEV;
+
+ ret = kstrtobool(buf, &show);
+ if (ret < 0)
+ return ret;
+
+ t7xx_proxy_debug_ports_show(t7xx_dev, show);
+ WRITE_ONCE(t7xx_dev->debug_ports_show, show);
+
+ return count;
+};
+
+static ssize_t t7xx_debug_ports_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct t7xx_pci_dev *t7xx_dev;
+ struct pci_dev *pdev;
+ bool show;
+
+ pdev = to_pci_dev(dev);
+ t7xx_dev = pci_get_drvdata(pdev);
+ if (!t7xx_dev)
+ return -ENODEV;
+
+ show = READ_ONCE(t7xx_dev->debug_ports_show);
+
+ return sysfs_emit(buf, "%d\n", show);
+}
+
+static DEVICE_ATTR_RW(t7xx_debug_ports);
+
+static struct attribute *t7xx_attr[] = {
&dev_attr_t7xx_mode.attr,
+ &dev_attr_t7xx_debug_ports.attr,
NULL
};
-static const struct attribute_group t7xx_mode_attribute_group = {
- .attrs = t7xx_mode_attr,
+static const struct attribute_group t7xx_attribute_group = {
+ .attrs = t7xx_attr,
};
void t7xx_mode_update(struct t7xx_pci_dev *t7xx_dev, enum t7xx_mode mode)
@@ -839,7 +885,7 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
t7xx_pcie_mac_interrupts_dis(t7xx_dev);
ret = sysfs_create_group(&t7xx_dev->pdev->dev.kobj,
- &t7xx_mode_attribute_group);
+ &t7xx_attribute_group);
if (ret)
goto err_md_exit;
@@ -855,7 +901,7 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_remove_group:
sysfs_remove_group(&t7xx_dev->pdev->dev.kobj,
- &t7xx_mode_attribute_group);
+ &t7xx_attribute_group);
err_md_exit:
t7xx_md_exit(t7xx_dev);
@@ -870,7 +916,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev)
t7xx_dev = pci_get_drvdata(pdev);
sysfs_remove_group(&t7xx_dev->pdev->dev.kobj,
- &t7xx_mode_attribute_group);
+ &t7xx_attribute_group);
t7xx_md_exit(t7xx_dev);
for (i = 0; i < EXT_INT_NUM; i++) {
diff --git a/drivers/net/wwan/t7xx/t7xx_pci.h b/drivers/net/wwan/t7xx/t7xx_pci.h
index cd8ea17c2644..b25d867e72d2 100644
--- a/drivers/net/wwan/t7xx/t7xx_pci.h
+++ b/drivers/net/wwan/t7xx/t7xx_pci.h
@@ -94,6 +94,7 @@ struct t7xx_pci_dev {
struct dentry *debugfs_dir;
#endif
u32 mode;
+ bool debug_ports_show;
};
enum t7xx_pm_id {
diff --git a/drivers/net/wwan/t7xx/t7xx_port.h b/drivers/net/wwan/t7xx/t7xx_port.h
index f74d3bab810d..9f5d6d288c97 100644
--- a/drivers/net/wwan/t7xx/t7xx_port.h
+++ b/drivers/net/wwan/t7xx/t7xx_port.h
@@ -42,6 +42,8 @@ enum port_ch {
/* to AP */
PORT_CH_AP_CONTROL_RX = 0x1000,
PORT_CH_AP_CONTROL_TX = 0x1001,
+ PORT_CH_AP_ADB_RX = 0x100a,
+ PORT_CH_AP_ADB_TX = 0x100b,
/* to MD */
PORT_CH_CONTROL_RX = 0x2000,
@@ -100,6 +102,7 @@ struct t7xx_port_conf {
struct port_ops *ops;
char *name;
enum wwan_port_type port_type;
+ bool debug;
};
struct t7xx_port {
diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.c b/drivers/net/wwan/t7xx/t7xx_port_proxy.c
index 35743e7de0c3..4fc131f9632f 100644
--- a/drivers/net/wwan/t7xx/t7xx_port_proxy.c
+++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.c
@@ -38,7 +38,8 @@
#include "t7xx_state_monitor.h"
#define Q_IDX_CTRL 0
-#define Q_IDX_MBIM 2
+#define Q_IDX_MBIM_MIPC 2
+#define Q_IDX_ADB 3
#define Q_IDX_AT_CMD 5
#define INVALID_SEQ_NUM GENMASK(15, 0)
@@ -66,8 +67,8 @@ static const struct t7xx_port_conf t7xx_port_conf[] = {
}, {
.tx_ch = PORT_CH_MBIM_TX,
.rx_ch = PORT_CH_MBIM_RX,
- .txq_index = Q_IDX_MBIM,
- .rxq_index = Q_IDX_MBIM,
+ .txq_index = Q_IDX_MBIM_MIPC,
+ .rxq_index = Q_IDX_MBIM_MIPC,
.path_id = CLDMA_ID_MD,
.ops = &wwan_sub_port_ops,
.name = "MBIM",
@@ -100,7 +101,27 @@ static const struct t7xx_port_conf t7xx_port_conf[] = {
.path_id = CLDMA_ID_AP,
.ops = &ctl_port_ops,
.name = "t7xx_ap_ctrl",
- },
+ }, {
+ .tx_ch = PORT_CH_AP_ADB_TX,
+ .rx_ch = PORT_CH_AP_ADB_RX,
+ .txq_index = Q_IDX_ADB,
+ .rxq_index = Q_IDX_ADB,
+ .path_id = CLDMA_ID_AP,
+ .ops = &wwan_sub_port_ops,
+ .name = "adb",
+ .port_type = WWAN_PORT_ADB,
+ .debug = true,
+ }, {
+ .tx_ch = PORT_CH_MIPC_TX,
+ .rx_ch = PORT_CH_MIPC_RX,
+ .txq_index = Q_IDX_MBIM_MIPC,
+ .rxq_index = Q_IDX_MBIM_MIPC,
+ .path_id = CLDMA_ID_MD,
+ .ops = &wwan_sub_port_ops,
+ .name = "mipc",
+ .port_type = WWAN_PORT_MIPC,
+ .debug = true,
+ }
};
static const struct t7xx_port_conf t7xx_early_port_conf[] = {
@@ -505,13 +526,33 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)
spin_lock_init(&port->port_update_lock);
port->chan_enable = false;
- if (port_conf->ops && port_conf->ops->init)
+ if (!port_conf->debug &&
+ port_conf->ops &&
+ port_conf->ops->init)
port_conf->ops->init(port);
}
t7xx_proxy_setup_ch_mapping(port_prox);
}
+void t7xx_proxy_debug_ports_show(struct t7xx_pci_dev *t7xx_dev, bool show)
+{
+ struct port_proxy *port_prox = t7xx_dev->md->port_prox;
+ struct t7xx_port *port;
+ int i;
+
+ for_each_proxy_port(i, port, port_prox) {
+ const struct t7xx_port_conf *port_conf = port->port_conf;
+
+ if (port_conf->debug && port_conf->ops) {
+ if (show && port_conf->ops->init)
+ port_conf->ops->init(port);
+ else if (!show && port_conf->ops->uninit)
+ port_conf->ops->uninit(port);
+ }
+ }
+}
+
void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id)
{
struct port_proxy *port_prox = md->port_prox;
diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.h b/drivers/net/wwan/t7xx/t7xx_port_proxy.h
index 7f5706811445..f0918b36e899 100644
--- a/drivers/net/wwan/t7xx/t7xx_port_proxy.h
+++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.h
@@ -98,6 +98,7 @@ extern struct port_ops ctl_port_ops;
extern struct port_ops t7xx_trace_port_ops;
#endif
+void t7xx_proxy_debug_ports_show(struct t7xx_pci_dev *t7xx_dev, bool show);
void t7xx_port_proxy_reset(struct port_proxy *port_prox);
void t7xx_port_proxy_uninit(struct port_proxy *port_prox);
int t7xx_port_proxy_init(struct t7xx_modem *md);
diff --git a/drivers/net/wwan/t7xx/t7xx_port_wwan.c b/drivers/net/wwan/t7xx/t7xx_port_wwan.c
index 4b23ba693f3f..7fc569565ff9 100644
--- a/drivers/net/wwan/t7xx/t7xx_port_wwan.c
+++ b/drivers/net/wwan/t7xx/t7xx_port_wwan.c
@@ -169,7 +169,9 @@ static int t7xx_port_wwan_init(struct t7xx_port *port)
{
const struct t7xx_port_conf *port_conf = port->port_conf;
- if (port_conf->port_type == WWAN_PORT_FASTBOOT)
+ if (port_conf->port_type == WWAN_PORT_FASTBOOT ||
+ port_conf->port_type == WWAN_PORT_ADB ||
+ port_conf->port_type == WWAN_PORT_MIPC)
t7xx_port_wwan_create(port);
port->rx_length_th = RX_QUEUE_MAXLEN;
@@ -224,7 +226,9 @@ static void t7xx_port_wwan_md_state_notify(struct t7xx_port *port, unsigned int
{
const struct t7xx_port_conf *port_conf = port->port_conf;
- if (port_conf->port_type == WWAN_PORT_FASTBOOT)
+ if (port_conf->port_type == WWAN_PORT_FASTBOOT ||
+ port_conf->port_type == WWAN_PORT_ADB ||
+ port_conf->port_type == WWAN_PORT_MIPC)
return;
if (state != MD_STATE_READY)
diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
index 65a7ed4d6766..a51e2755991a 100644
--- a/drivers/net/wwan/wwan_core.c
+++ b/drivers/net/wwan/wwan_core.c
@@ -334,6 +334,14 @@ static const struct {
.name = "FASTBOOT",
.devsuf = "fastboot",
},
+ [WWAN_PORT_ADB] = {
+ .name = "ADB",
+ .devsuf = "adb",
+ },
+ [WWAN_PORT_MIPC] = {
+ .name = "MIPC",
+ .devsuf = "mipc",
+ },
};
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
@@ -431,7 +439,7 @@ static int __wwan_port_dev_assign_name(struct wwan_port *port, const char *fmt)
return -ENFILE;
}
- return dev_set_name(&port->dev, buf);
+ return dev_set_name(&port->dev, "%s", buf);
}
struct wwan_port *wwan_create_port(struct device *parent,
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c
index 6fc9dfe82474..544d8a4d2af5 100644
--- a/drivers/ntb/hw/idt/ntb_hw_idt.c
+++ b/drivers/ntb/hw/idt/ntb_hw_idt.c
@@ -2671,15 +2671,20 @@ static int idt_init_pci(struct idt_ntb_dev *ndev)
*/
pci_set_master(pdev);
- /* Request all BARs resources and map BAR0 only */
- ret = pcim_iomap_regions_request_all(pdev, 1, NTB_NAME);
+ /* Request all BARs resources */
+ ret = pcim_request_all_regions(pdev, NTB_NAME);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request resources\n");
goto err_clear_master;
}
- /* Retrieve virtual address of BAR0 - PCI configuration space */
- ndev->cfgspc = pcim_iomap_table(pdev)[0];
+ /* ioremap BAR0 - PCI configuration space */
+ ndev->cfgspc = pcim_iomap(pdev, 0, 0);
+ if (!ndev->cfgspc) {
+ dev_err(&pdev->dev, "Failed to ioremap BAR 0\n");
+ ret = -ENOMEM;
+ goto err_clear_master;
+ }
/* Put the IDT driver data pointer to the PCI-device private pointer */
pci_set_drvdata(pdev, ndev);
diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c
index 6b4922de3047..37b743acbb7b 100644
--- a/drivers/nvdimm/dax_devs.c
+++ b/drivers/nvdimm/dax_devs.c
@@ -106,12 +106,12 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns)
nvdimm_bus_lock(&ndns->dev);
nd_dax = nd_dax_alloc(nd_region);
- nd_pfn = &nd_dax->nd_pfn;
- dax_dev = nd_pfn_devinit(nd_pfn, ndns);
+ dax_dev = nd_dax_devinit(nd_dax, ndns);
nvdimm_bus_unlock(&ndns->dev);
if (!dax_dev)
return -ENOMEM;
pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
+ nd_pfn = &nd_dax->nd_pfn;
nd_pfn->pfn_sb = pfn_sb;
rc = nd_pfn_validate(nd_pfn, DAX_SIG);
dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : "<none>");
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 2dbb1dca17b5..5ca06e9a2d29 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -600,6 +600,13 @@ struct nd_dax *to_nd_dax(struct device *dev);
int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns);
bool is_nd_dax(const struct device *dev);
struct device *nd_dax_create(struct nd_region *nd_region);
+static inline struct device *nd_dax_devinit(struct nd_dax *nd_dax,
+ struct nd_namespace_common *ndns)
+{
+ if (!nd_dax)
+ return NULL;
+ return nd_pfn_devinit(&nd_dax->nd_pfn, ndns);
+}
#else
static inline int nd_dax_probe(struct device *dev,
struct nd_namespace_common *ndns)
diff --git a/drivers/nvdimm/nd_virtio.c b/drivers/nvdimm/nd_virtio.c
index f55d60922b87..c3f07be4aa22 100644
--- a/drivers/nvdimm/nd_virtio.c
+++ b/drivers/nvdimm/nd_virtio.c
@@ -97,7 +97,7 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
dev_info(&vdev->dev, "failed to send command to virtio pmem device\n");
err = -EIO;
} else {
- /* A host repsonse results in "host_ack" getting called */
+ /* A host response results in "host_ack" getting called */
wait_event(req_data->host_acked, req_data->done);
err = le32_to_cpu(req_data->resp.ret);
}
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 586348125b61..cfdfe0eaa512 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -539,7 +539,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
if (!nd_pfn->uuid) {
/*
- * When probing a namepace via nd_pfn_probe() the uuid
+ * When probing a namespace via nd_pfn_probe() the uuid
* is NULL (see: nd_pfn_devinit()) we init settings from
* pfn_sb
*/
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 210fb77f51ba..d81faa9d89c9 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -316,7 +316,7 @@ static long pmem_dax_direct_access(struct dax_device *dax_dev,
* range, filesystem turns the normal pwrite to a dax_recovery_write.
*
* The recovery write consists of clearing media poison, clearing page
- * HWPoison bit, reenable page-wide read-write permission, flush the
+ * HWPoison bit, re-enable page-wide read-write permission, flush the
* caches and finally write. A competing pread thread will be held
* off during the recovery process since data read back might not be
* valid, and this is achieved by clearing the badblock records after
diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c
index c9b97aeabf85..2396d19ce549 100644
--- a/drivers/nvdimm/virtio_pmem.c
+++ b/drivers/nvdimm/virtio_pmem.c
@@ -143,6 +143,28 @@ static void virtio_pmem_remove(struct virtio_device *vdev)
virtio_reset_device(vdev);
}
+static int virtio_pmem_freeze(struct virtio_device *vdev)
+{
+ vdev->config->del_vqs(vdev);
+ virtio_reset_device(vdev);
+
+ return 0;
+}
+
+static int virtio_pmem_restore(struct virtio_device *vdev)
+{
+ int ret;
+
+ ret = init_vq(vdev->priv);
+ if (ret) {
+ dev_err(&vdev->dev, "failed to initialize virtio pmem's vq\n");
+ return ret;
+ }
+ virtio_device_ready(vdev);
+
+ return 0;
+}
+
static unsigned int features[] = {
VIRTIO_PMEM_F_SHMEM_REGION,
};
@@ -155,6 +177,8 @@ static struct virtio_driver virtio_pmem_driver = {
.validate = virtio_pmem_validate,
.probe = virtio_pmem_probe,
.remove = virtio_pmem_remove,
+ .freeze = virtio_pmem_freeze,
+ .restore = virtio_pmem_restore,
};
module_virtio_driver(virtio_pmem_driver);
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index b1387dc459a3..7cd1102a8d2c 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -649,7 +649,7 @@ static bool apple_nvme_handle_cq(struct apple_nvme_queue *q, bool force)
found = apple_nvme_poll_cq(q, &iob);
- if (!rq_list_empty(iob.req_list))
+ if (!rq_list_empty(&iob.req_list))
apple_nvme_complete_batch(&iob);
return found;
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index b149b638453f..40e7be3b0339 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -42,6 +42,8 @@ struct nvme_ns_info {
bool is_readonly;
bool is_ready;
bool is_removed;
+ bool is_rotational;
+ bool no_vwc;
};
unsigned int admin_timeout = 60;
@@ -1303,9 +1305,10 @@ static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
}
-static void nvme_keep_alive_finish(struct request *rq,
- blk_status_t status, struct nvme_ctrl *ctrl)
+static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
+ blk_status_t status)
{
+ struct nvme_ctrl *ctrl = rq->end_io_data;
unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
unsigned long delay = nvme_keep_alive_work_period(ctrl);
enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);
@@ -1322,17 +1325,20 @@ static void nvme_keep_alive_finish(struct request *rq,
delay = 0;
}
+ blk_mq_free_request(rq);
+
if (status) {
dev_err(ctrl->device,
"failed nvme_keep_alive_end_io error=%d\n",
status);
- return;
+ return RQ_END_IO_NONE;
}
ctrl->ka_last_check_time = jiffies;
ctrl->comp_seen = false;
if (state == NVME_CTRL_LIVE || state == NVME_CTRL_CONNECTING)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
+ return RQ_END_IO_NONE;
}
static void nvme_keep_alive_work(struct work_struct *work)
@@ -1341,7 +1347,6 @@ static void nvme_keep_alive_work(struct work_struct *work)
struct nvme_ctrl, ka_work);
bool comp_seen = ctrl->comp_seen;
struct request *rq;
- blk_status_t status;
ctrl->ka_last_check_time = jiffies;
@@ -1364,9 +1369,9 @@ static void nvme_keep_alive_work(struct work_struct *work)
nvme_init_request(rq, &ctrl->ka_cmd);
rq->timeout = ctrl->kato * HZ;
- status = blk_execute_rq(rq, false);
- nvme_keep_alive_finish(rq, status, ctrl);
- blk_mq_free_request(rq);
+ rq->end_io = nvme_keep_alive_end_io;
+ rq->end_io_data = ctrl;
+ blk_execute_rq_nowait(rq, false);
}
static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
@@ -1639,6 +1644,8 @@ static int nvme_ns_info_from_id_cs_indep(struct nvme_ctrl *ctrl,
info->is_shared = id->nmic & NVME_NS_NMIC_SHARED;
info->is_readonly = id->nsattr & NVME_NS_ATTR_RO;
info->is_ready = id->nstat & NVME_NSTAT_NRDY;
+ info->is_rotational = id->nsfeat & NVME_NS_ROTATIONAL;
+ info->no_vwc = id->nsfeat & NVME_NS_VWC_NOT_PRESENT;
}
kfree(id);
return ret;
@@ -2185,11 +2192,14 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
ns->head->ids.csi == NVME_CSI_ZNS)
nvme_update_zone_info(ns, &lim, &zi);
- if (ns->ctrl->vwc & NVME_CTRL_VWC_PRESENT)
+ if ((ns->ctrl->vwc & NVME_CTRL_VWC_PRESENT) && !info->no_vwc)
lim.features |= BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA;
else
lim.features &= ~(BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA);
+ if (info->is_rotational)
+ lim.features |= BLK_FEAT_ROTATIONAL;
+
/*
* Register a metadata profile for PI, or the plain non-integrity NVMe
* metadata masquerading as Type 0 if supported, otherwise reject block
@@ -3636,6 +3646,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
head->ns_id = info->nsid;
head->ids = info->ids;
head->shared = info->is_shared;
+ head->rotational = info->is_rotational;
ratelimit_state_init(&head->rs_nuse, 5 * HZ, 1);
ratelimit_set_flags(&head->rs_nuse, RATELIMIT_MSG_ON_RELEASE);
kref_init(&head->ref);
@@ -3795,7 +3806,8 @@ struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
if (ns->head->ns_id == nsid) {
if (!nvme_get_ns(ns))
continue;
@@ -4016,7 +4028,7 @@ static void nvme_scan_ns(struct nvme_ctrl *ctrl, unsigned nsid)
{
struct nvme_ns_info info = { .nsid = nsid };
struct nvme_ns *ns;
- int ret;
+ int ret = 1;
if (nvme_identify_ns_descs(ctrl, &info))
return;
@@ -4033,9 +4045,10 @@ static void nvme_scan_ns(struct nvme_ctrl *ctrl, unsigned nsid)
* set up a namespace. If not fall back to the legacy version.
*/
if ((ctrl->cap & NVME_CAP_CRMS_CRIMS) ||
- (info.ids.csi != NVME_CSI_NVM && info.ids.csi != NVME_CSI_ZNS))
+ (info.ids.csi != NVME_CSI_NVM && info.ids.csi != NVME_CSI_ZNS) ||
+ ctrl->vs >= NVME_VS(2, 0, 0))
ret = nvme_ns_info_from_id_cs_indep(ctrl, &info);
- else
+ if (ret > 0)
ret = nvme_ns_info_from_identify(ctrl, &info);
if (info.is_removed)
@@ -4590,6 +4603,11 @@ EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set);
void nvme_remove_admin_tag_set(struct nvme_ctrl *ctrl)
{
+ /*
+ * As we're about to destroy the queue and free tagset
+ * we can not have keep-alive work running.
+ */
+ nvme_stop_keep_alive(ctrl);
blk_mq_destroy_queue(ctrl->admin_q);
blk_put_queue(ctrl->admin_q);
if (ctrl->ops->flags & NVME_F_FABRICS) {
@@ -4879,7 +4897,8 @@ void nvme_mark_namespaces_dead(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_mark_disk_dead(ns->disk);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
@@ -4891,8 +4910,9 @@ void nvme_unfreeze(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
- blk_mq_unfreeze_queue(ns->queue);
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
+ blk_mq_unfreeze_queue_non_owner(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
clear_bit(NVME_CTRL_FROZEN, &ctrl->flags);
}
@@ -4904,7 +4924,8 @@ int nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
timeout = blk_mq_freeze_queue_wait_timeout(ns->queue, timeout);
if (timeout <= 0)
break;
@@ -4920,7 +4941,8 @@ void nvme_wait_freeze(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_mq_freeze_queue_wait(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
@@ -4933,8 +4955,14 @@ void nvme_start_freeze(struct nvme_ctrl *ctrl)
set_bit(NVME_CTRL_FROZEN, &ctrl->flags);
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
- blk_freeze_queue_start(ns->queue);
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
+ /*
+ * Typical non_owner use case is from pci driver, in which
+ * start_freeze is called from timeout work function, but
+ * unfreeze is done in reset work context
+ */
+ blk_freeze_queue_start_non_owner(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
EXPORT_SYMBOL_GPL(nvme_start_freeze);
@@ -4981,7 +5009,8 @@ void nvme_sync_io_queues(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_sync_queue(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
@@ -5029,6 +5058,8 @@ static inline void _nvme_check_size(void)
BUILD_BUG_ON(sizeof(struct nvme_id_ctrl_nvm) != NVME_IDENTIFY_DATA_SIZE);
BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64);
BUILD_BUG_ON(sizeof(struct nvme_smart_log) != 512);
+ BUILD_BUG_ON(sizeof(struct nvme_endurance_group_log) != 512);
+ BUILD_BUG_ON(sizeof(struct nvme_rotational_media_log) != 512);
BUILD_BUG_ON(sizeof(struct nvme_dbbuf) != 64);
BUILD_BUG_ON(sizeof(struct nvme_directive_cmd) != 64);
BUILD_BUG_ON(sizeof(struct nvme_feat_host_behavior) != 512);
@@ -5037,22 +5068,20 @@ static inline void _nvme_check_size(void)
static int __init nvme_core_init(void)
{
+ unsigned int wq_flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS;
int result = -ENOMEM;
_nvme_check_size();
- nvme_wq = alloc_workqueue("nvme-wq",
- WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+ nvme_wq = alloc_workqueue("nvme-wq", wq_flags, 0);
if (!nvme_wq)
goto out;
- nvme_reset_wq = alloc_workqueue("nvme-reset-wq",
- WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+ nvme_reset_wq = alloc_workqueue("nvme-reset-wq", wq_flags, 0);
if (!nvme_reset_wq)
goto destroy_wq;
- nvme_delete_wq = alloc_workqueue("nvme-delete-wq",
- WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+ nvme_delete_wq = alloc_workqueue("nvme-delete-wq", wq_flags, 0);
if (!nvme_delete_wq)
goto destroy_reset_wq;
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index a96976b22fa7..e8930146847a 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -114,18 +114,26 @@ static struct request *nvme_alloc_user_request(struct request_queue *q,
static int nvme_map_user_request(struct request *req, u64 ubuffer,
unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
- u32 meta_seed, struct io_uring_cmd *ioucmd, unsigned int flags)
+ struct io_uring_cmd *ioucmd, unsigned int flags)
{
struct request_queue *q = req->q;
struct nvme_ns *ns = q->queuedata;
struct block_device *bdev = ns ? ns->disk->part0 : NULL;
bool supports_metadata = bdev && blk_get_integrity(bdev->bd_disk);
+ struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
bool has_metadata = meta_buffer && meta_len;
struct bio *bio = NULL;
int ret;
- if (has_metadata && !supports_metadata)
- return -EINVAL;
+ if (!nvme_ctrl_sgl_supported(ctrl))
+ dev_warn_once(ctrl->device, "using unchecked data buffer\n");
+ if (has_metadata) {
+ if (!supports_metadata)
+ return -EINVAL;
+ if (!nvme_ctrl_meta_sgl_supported(ctrl))
+ dev_warn_once(ctrl->device,
+ "using unchecked metadata buffer\n");
+ }
if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) {
struct iov_iter iter;
@@ -152,8 +160,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
bio_set_dev(bio, bdev);
if (has_metadata) {
- ret = blk_rq_integrity_map_user(req, meta_buffer, meta_len,
- meta_seed);
+ ret = blk_rq_integrity_map_user(req, meta_buffer, meta_len);
if (ret)
goto out_unmap;
}
@@ -170,7 +177,7 @@ out:
static int nvme_submit_user_cmd(struct request_queue *q,
struct nvme_command *cmd, u64 ubuffer, unsigned bufflen,
- void __user *meta_buffer, unsigned meta_len, u32 meta_seed,
+ void __user *meta_buffer, unsigned meta_len,
u64 *result, unsigned timeout, unsigned int flags)
{
struct nvme_ns *ns = q->queuedata;
@@ -187,7 +194,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
req->timeout = timeout;
if (ubuffer && bufflen) {
ret = nvme_map_user_request(req, ubuffer, bufflen, meta_buffer,
- meta_len, meta_seed, NULL, flags);
+ meta_len, NULL, flags);
if (ret)
return ret;
}
@@ -268,7 +275,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
c.rw.lbatm = cpu_to_le16(io.appmask);
return nvme_submit_user_cmd(ns->queue, &c, io.addr, length, metadata,
- meta_len, lower_32_bits(io.slba), NULL, 0, 0);
+ meta_len, NULL, 0, 0);
}
static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl,
@@ -323,7 +330,7 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
cmd.addr, cmd.data_len, nvme_to_user_ptr(cmd.metadata),
- cmd.metadata_len, 0, &result, timeout, 0);
+ cmd.metadata_len, &result, timeout, 0);
if (status >= 0) {
if (put_user(result, &ucmd->result))
@@ -370,7 +377,7 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
cmd.addr, cmd.data_len, nvme_to_user_ptr(cmd.metadata),
- cmd.metadata_len, 0, &cmd.result, timeout, flags);
+ cmd.metadata_len, &cmd.result, timeout, flags);
if (status >= 0) {
if (put_user(cmd.result, &ucmd->result))
@@ -402,7 +409,7 @@ struct nvme_uring_cmd_pdu {
static inline struct nvme_uring_cmd_pdu *nvme_uring_cmd_pdu(
struct io_uring_cmd *ioucmd)
{
- return (struct nvme_uring_cmd_pdu *)&ioucmd->pdu;
+ return io_uring_cmd_to_pdu(ioucmd, struct nvme_uring_cmd_pdu);
}
static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd,
@@ -507,7 +514,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
if (d.addr && d.data_len) {
ret = nvme_map_user_request(req, d.addr,
d.data_len, nvme_to_user_ptr(d.metadata),
- d.metadata_len, 0, ioucmd, vec);
+ d.metadata_len, ioucmd, vec);
if (ret)
return ret;
}
@@ -635,8 +642,6 @@ static int nvme_ns_uring_cmd(struct nvme_ns *ns, struct io_uring_cmd *ioucmd,
struct nvme_ctrl *ctrl = ns->ctrl;
int ret;
- BUILD_BUG_ON(sizeof(struct nvme_uring_cmd_pdu) > sizeof(ioucmd->pdu));
-
ret = nvme_uring_cmd_checks(issue_flags);
if (ret)
return ret;
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 6a15873055b9..a85d190942bd 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -165,7 +165,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
if (!ns->head->disk)
continue;
kblockd_schedule_work(&ns->head->requeue_work);
@@ -209,7 +210,8 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
nvme_mpath_clear_current_path(ns);
kblockd_schedule_work(&ns->head->requeue_work);
}
@@ -224,7 +226,8 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
int srcu_idx;
srcu_idx = srcu_read_lock(&head->srcu);
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (capacity != get_capacity(ns->disk))
clear_bit(NVME_NS_READY, &ns->flags);
}
@@ -257,7 +260,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
int found_distance = INT_MAX, fallback_distance = INT_MAX, distance;
struct nvme_ns *found = NULL, *fallback = NULL, *ns;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;
@@ -356,7 +360,8 @@ static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)
unsigned int min_depth_opt = UINT_MAX, min_depth_nonopt = UINT_MAX;
unsigned int depth;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;
@@ -424,7 +429,8 @@ static bool nvme_available_path(struct nvme_ns_head *head)
if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
return NULL;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags))
continue;
switch (nvme_ctrl_state(ns->ctrl)) {
@@ -635,8 +641,6 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)
lim.features |= BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT | BLK_FEAT_POLL;
if (head->ids.csi == NVME_CSI_ZNS)
lim.features |= BLK_FEAT_ZONED;
- else
- lim.max_zone_append_sectors = 0;
head->disk = blk_alloc_disk(&lim, ctrl->numa_node);
if (IS_ERR(head->disk))
@@ -785,7 +789,8 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
return 0;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
unsigned nsid;
again:
nsid = le32_to_cpu(desc->nsids[n]);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 093cb423f536..611b02c8a8b3 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -474,6 +474,7 @@ struct nvme_ns_head {
struct list_head entry;
struct kref ref;
bool shared;
+ bool rotational;
bool passthru_err_log_enabled;
struct nvme_effects_log *effects;
u64 nuse;
@@ -1122,7 +1123,15 @@ static inline void nvme_start_request(struct request *rq)
static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl)
{
- return ctrl->sgls & ((1 << 0) | (1 << 1));
+ return ctrl->sgls & (NVME_CTRL_SGLS_BYTE_ALIGNED |
+ NVME_CTRL_SGLS_DWORD_ALIGNED);
+}
+
+static inline bool nvme_ctrl_meta_sgl_supported(struct nvme_ctrl *ctrl)
+{
+ if (ctrl->ops->flags & NVME_F_FABRICS)
+ return true;
+ return ctrl->sgls & NVME_CTRL_SGLS_MSDS;
}
#ifdef CONFIG_NVME_HOST_AUTH
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 4b9fda0b1d9a..4c644bb7f069 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -43,6 +43,7 @@
*/
#define NVME_MAX_KB_SZ 8192
#define NVME_MAX_SEGS 128
+#define NVME_MAX_META_SEGS 15
#define NVME_MAX_NR_ALLOCATIONS 5
static int use_threaded_interrupts;
@@ -141,8 +142,10 @@ struct nvme_dev {
struct nvme_ctrl ctrl;
u32 last_ps;
bool hmb;
+ struct sg_table *hmb_sgt;
mempool_t *iod_mempool;
+ mempool_t *iod_meta_mempool;
/* shadow doorbell buffer support: */
__le32 *dbbuf_dbs;
@@ -153,6 +156,7 @@ struct nvme_dev {
/* host memory buffer support: */
u64 host_mem_size;
u32 nr_host_mem_descs;
+ u32 host_mem_descs_size;
dma_addr_t host_mem_descs_dma;
struct nvme_host_mem_buf_desc *host_mem_descs;
void **host_mem_desc_bufs;
@@ -237,6 +241,8 @@ struct nvme_iod {
dma_addr_t first_dma;
dma_addr_t meta_dma;
struct sg_table sgt;
+ struct sg_table meta_sgt;
+ union nvme_descriptor meta_list;
union nvme_descriptor list[NVME_MAX_NR_ALLOCATIONS];
};
@@ -504,6 +510,15 @@ static void nvme_commit_rqs(struct blk_mq_hw_ctx *hctx)
spin_unlock(&nvmeq->sq_lock);
}
+static inline bool nvme_pci_metadata_use_sgls(struct nvme_dev *dev,
+ struct request *req)
+{
+ if (!nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ return false;
+ return req->nr_integrity_segments > 1 ||
+ nvme_req(req)->flags & NVME_REQ_USERCMD;
+}
+
static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
int nseg)
{
@@ -516,8 +531,10 @@ static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
return false;
if (!nvmeq->qid)
return false;
+ if (nvme_pci_metadata_use_sgls(dev, req))
+ return true;
if (!sgl_threshold || avg_seg_size < sgl_threshold)
- return false;
+ return nvme_req(req)->flags & NVME_REQ_USERCMD;
return true;
}
@@ -778,7 +795,8 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
struct bio_vec bv = req_bvec(req);
if (!is_pci_p2pdma_page(bv.bv_page)) {
- if ((bv.bv_offset & (NVME_CTRL_PAGE_SIZE - 1)) +
+ if (!nvme_pci_metadata_use_sgls(dev, req) &&
+ (bv.bv_offset & (NVME_CTRL_PAGE_SIZE - 1)) +
bv.bv_len <= NVME_CTRL_PAGE_SIZE * 2)
return nvme_setup_prp_simple(dev, req,
&cmnd->rw, &bv);
@@ -822,11 +840,69 @@ out_free_sg:
return ret;
}
-static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
- struct nvme_command *cmnd)
+static blk_status_t nvme_pci_setup_meta_sgls(struct nvme_dev *dev,
+ struct request *req)
+{
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+ struct nvme_rw_command *cmnd = &iod->cmd.rw;
+ struct nvme_sgl_desc *sg_list;
+ struct scatterlist *sgl, *sg;
+ unsigned int entries;
+ dma_addr_t sgl_dma;
+ int rc, i;
+
+ iod->meta_sgt.sgl = mempool_alloc(dev->iod_meta_mempool, GFP_ATOMIC);
+ if (!iod->meta_sgt.sgl)
+ return BLK_STS_RESOURCE;
+
+ sg_init_table(iod->meta_sgt.sgl, req->nr_integrity_segments);
+ iod->meta_sgt.orig_nents = blk_rq_map_integrity_sg(req,
+ iod->meta_sgt.sgl);
+ if (!iod->meta_sgt.orig_nents)
+ goto out_free_sg;
+
+ rc = dma_map_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req),
+ DMA_ATTR_NO_WARN);
+ if (rc)
+ goto out_free_sg;
+
+ sg_list = dma_pool_alloc(dev->prp_small_pool, GFP_ATOMIC, &sgl_dma);
+ if (!sg_list)
+ goto out_unmap_sg;
+
+ entries = iod->meta_sgt.nents;
+ iod->meta_list.sg_list = sg_list;
+ iod->meta_dma = sgl_dma;
+
+ cmnd->flags = NVME_CMD_SGL_METASEG;
+ cmnd->metadata = cpu_to_le64(sgl_dma);
+
+ sgl = iod->meta_sgt.sgl;
+ if (entries == 1) {
+ nvme_pci_sgl_set_data(sg_list, sgl);
+ return BLK_STS_OK;
+ }
+
+ sgl_dma += sizeof(*sg_list);
+ nvme_pci_sgl_set_seg(sg_list, sgl_dma, entries);
+ for_each_sg(sgl, sg, entries, i)
+ nvme_pci_sgl_set_data(&sg_list[i + 1], sg);
+
+ return BLK_STS_OK;
+
+out_unmap_sg:
+ dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
+out_free_sg:
+ mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
+ return BLK_STS_RESOURCE;
+}
+
+static blk_status_t nvme_pci_setup_meta_mptr(struct nvme_dev *dev,
+ struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct bio_vec bv = rq_integrity_vec(req);
+ struct nvme_command *cmnd = &iod->cmd;
iod->meta_dma = dma_map_bvec(dev->dev, &bv, rq_dma_dir(req), 0);
if (dma_mapping_error(dev->dev, iod->meta_dma))
@@ -835,6 +911,13 @@ static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
return BLK_STS_OK;
}
+static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req)
+{
+ if (nvme_pci_metadata_use_sgls(dev, req))
+ return nvme_pci_setup_meta_sgls(dev, req);
+ return nvme_pci_setup_meta_mptr(dev, req);
+}
+
static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
@@ -843,6 +926,7 @@ static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
iod->aborted = false;
iod->nr_allocations = -1;
iod->sgt.nents = 0;
+ iod->meta_sgt.nents = 0;
ret = nvme_setup_cmd(req->q->queuedata, req);
if (ret)
@@ -855,7 +939,7 @@ static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
}
if (blk_integrity_rq(req)) {
- ret = nvme_map_metadata(dev, req, &iod->cmd);
+ ret = nvme_map_metadata(dev, req);
if (ret)
goto out_unmap_data;
}
@@ -902,11 +986,12 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_STS_OK;
}
-static void nvme_submit_cmds(struct nvme_queue *nvmeq, struct request **rqlist)
+static void nvme_submit_cmds(struct nvme_queue *nvmeq, struct rq_list *rqlist)
{
+ struct request *req;
+
spin_lock(&nvmeq->sq_lock);
- while (!rq_list_empty(*rqlist)) {
- struct request *req = rq_list_pop(rqlist);
+ while ((req = rq_list_pop(rqlist))) {
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
nvme_sq_copy_cmd(nvmeq, &iod->cmd);
@@ -929,34 +1014,45 @@ static bool nvme_prep_rq_batch(struct nvme_queue *nvmeq, struct request *req)
return nvme_prep_rq(nvmeq->dev, req) == BLK_STS_OK;
}
-static void nvme_queue_rqs(struct request **rqlist)
+static void nvme_queue_rqs(struct rq_list *rqlist)
{
- struct request *req, *next, *prev = NULL;
- struct request *requeue_list = NULL;
+ struct rq_list submit_list = { };
+ struct rq_list requeue_list = { };
+ struct nvme_queue *nvmeq = NULL;
+ struct request *req;
- rq_list_for_each_safe(rqlist, req, next) {
- struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
+ while ((req = rq_list_pop(rqlist))) {
+ if (nvmeq && nvmeq != req->mq_hctx->driver_data)
+ nvme_submit_cmds(nvmeq, &submit_list);
+ nvmeq = req->mq_hctx->driver_data;
- if (!nvme_prep_rq_batch(nvmeq, req)) {
- /* detach 'req' and add to remainder list */
- rq_list_move(rqlist, &requeue_list, req, prev);
+ if (nvme_prep_rq_batch(nvmeq, req))
+ rq_list_add_tail(&submit_list, req);
+ else
+ rq_list_add_tail(&requeue_list, req);
+ }
- req = prev;
- if (!req)
- continue;
- }
+ if (nvmeq)
+ nvme_submit_cmds(nvmeq, &submit_list);
+ *rqlist = requeue_list;
+}
- if (!next || req->mq_hctx != next->mq_hctx) {
- /* detach rest of list, and submit */
- req->rq_next = NULL;
- nvme_submit_cmds(nvmeq, rqlist);
- *rqlist = next;
- prev = NULL;
- } else
- prev = req;
+static __always_inline void nvme_unmap_metadata(struct nvme_dev *dev,
+ struct request *req)
+{
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+
+ if (!iod->meta_sgt.nents) {
+ dma_unmap_page(dev->dev, iod->meta_dma,
+ rq_integrity_vec(req).bv_len,
+ rq_dma_dir(req));
+ return;
}
- *rqlist = requeue_list;
+ dma_pool_free(dev->prp_small_pool, iod->meta_list.sg_list,
+ iod->meta_dma);
+ dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
+ mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
}
static __always_inline void nvme_pci_unmap_rq(struct request *req)
@@ -964,12 +1060,8 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req)
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
struct nvme_dev *dev = nvmeq->dev;
- if (blk_integrity_rq(req)) {
- struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
-
- dma_unmap_page(dev->dev, iod->meta_dma,
- rq_integrity_vec(req).bv_len, rq_dma_dir(req));
- }
+ if (blk_integrity_rq(req))
+ nvme_unmap_metadata(dev, req);
if (blk_rq_nr_phys_segments(req))
nvme_unmap_data(dev, req);
@@ -1083,7 +1175,7 @@ static irqreturn_t nvme_irq(int irq, void *data)
DEFINE_IO_COMP_BATCH(iob);
if (nvme_poll_cq(nvmeq, &iob)) {
- if (!rq_list_empty(iob.req_list))
+ if (!rq_list_empty(&iob.req_list))
nvme_pci_complete_batch(&iob);
return IRQ_HANDLED;
}
@@ -1951,7 +2043,7 @@ static int nvme_set_host_mem(struct nvme_dev *dev, u32 bits)
return ret;
}
-static void nvme_free_host_mem(struct nvme_dev *dev)
+static void nvme_free_host_mem_multi(struct nvme_dev *dev)
{
int i;
@@ -1966,18 +2058,54 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
kfree(dev->host_mem_desc_bufs);
dev->host_mem_desc_bufs = NULL;
- dma_free_coherent(dev->dev,
- dev->nr_host_mem_descs * sizeof(*dev->host_mem_descs),
+}
+
+static void nvme_free_host_mem(struct nvme_dev *dev)
+{
+ if (dev->hmb_sgt)
+ dma_free_noncontiguous(dev->dev, dev->host_mem_size,
+ dev->hmb_sgt, DMA_BIDIRECTIONAL);
+ else
+ nvme_free_host_mem_multi(dev);
+
+ dma_free_coherent(dev->dev, dev->host_mem_descs_size,
dev->host_mem_descs, dev->host_mem_descs_dma);
dev->host_mem_descs = NULL;
+ dev->host_mem_descs_size = 0;
dev->nr_host_mem_descs = 0;
}
-static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
+static int nvme_alloc_host_mem_single(struct nvme_dev *dev, u64 size)
+{
+ dev->hmb_sgt = dma_alloc_noncontiguous(dev->dev, size,
+ DMA_BIDIRECTIONAL, GFP_KERNEL, 0);
+ if (!dev->hmb_sgt)
+ return -ENOMEM;
+
+ dev->host_mem_descs = dma_alloc_coherent(dev->dev,
+ sizeof(*dev->host_mem_descs), &dev->host_mem_descs_dma,
+ GFP_KERNEL);
+ if (!dev->host_mem_descs) {
+ dma_free_noncontiguous(dev->dev, dev->host_mem_size,
+ dev->hmb_sgt, DMA_BIDIRECTIONAL);
+ dev->hmb_sgt = NULL;
+ return -ENOMEM;
+ }
+ dev->host_mem_size = size;
+ dev->host_mem_descs_size = sizeof(*dev->host_mem_descs);
+ dev->nr_host_mem_descs = 1;
+
+ dev->host_mem_descs[0].addr =
+ cpu_to_le64(dev->hmb_sgt->sgl->dma_address);
+ dev->host_mem_descs[0].size = cpu_to_le32(size / NVME_CTRL_PAGE_SIZE);
+ return 0;
+}
+
+static int nvme_alloc_host_mem_multi(struct nvme_dev *dev, u64 preferred,
u32 chunk_size)
{
struct nvme_host_mem_buf_desc *descs;
- u32 max_entries, len;
+ u32 max_entries, len, descs_size;
dma_addr_t descs_dma;
int i = 0;
void **bufs;
@@ -1990,8 +2118,9 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
max_entries = dev->ctrl.hmmaxd;
- descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs),
- &descs_dma, GFP_KERNEL);
+ descs_size = max_entries * sizeof(*descs);
+ descs = dma_alloc_coherent(dev->dev, descs_size, &descs_dma,
+ GFP_KERNEL);
if (!descs)
goto out;
@@ -2020,6 +2149,7 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
dev->host_mem_size = size;
dev->host_mem_descs = descs;
dev->host_mem_descs_dma = descs_dma;
+ dev->host_mem_descs_size = descs_size;
dev->host_mem_desc_bufs = bufs;
return 0;
@@ -2034,8 +2164,7 @@ out_free_bufs:
kfree(bufs);
out_free_descs:
- dma_free_coherent(dev->dev, max_entries * sizeof(*descs), descs,
- descs_dma);
+ dma_free_coherent(dev->dev, descs_size, descs, descs_dma);
out:
dev->host_mem_descs = NULL;
return -ENOMEM;
@@ -2047,9 +2176,18 @@ static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
u64 hmminds = max_t(u32, dev->ctrl.hmminds * 4096, PAGE_SIZE * 2);
u64 chunk_size;
+ /*
+ * If there is an IOMMU that can merge pages, try a virtually
+ * non-contiguous allocation for a single segment first.
+ */
+ if (!(PAGE_SIZE & dma_get_merge_boundary(dev->dev))) {
+ if (!nvme_alloc_host_mem_single(dev, preferred))
+ return 0;
+ }
+
/* start big and work our way down */
for (chunk_size = min_chunk; chunk_size >= hmminds; chunk_size /= 2) {
- if (!__nvme_alloc_host_mem(dev, preferred, chunk_size)) {
+ if (!nvme_alloc_host_mem_multi(dev, preferred, chunk_size)) {
if (!min || dev->host_mem_size >= min)
return 0;
nvme_free_host_mem(dev);
@@ -2097,8 +2235,10 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)
}
dev_info(dev->ctrl.device,
- "allocated %lld MiB host memory buffer.\n",
- dev->host_mem_size >> ilog2(SZ_1M));
+ "allocated %lld MiB host memory buffer (%u segment%s).\n",
+ dev->host_mem_size >> ilog2(SZ_1M),
+ dev->nr_host_mem_descs,
+ str_plural(dev->nr_host_mem_descs));
}
ret = nvme_set_host_mem(dev, enable_bits);
@@ -2717,6 +2857,7 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
{
+ size_t meta_size = sizeof(struct scatterlist) * (NVME_MAX_META_SEGS + 1);
size_t alloc_size = sizeof(struct scatterlist) * NVME_MAX_SEGS;
dev->iod_mempool = mempool_create_node(1,
@@ -2725,7 +2866,18 @@ static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
dev_to_node(dev->dev));
if (!dev->iod_mempool)
return -ENOMEM;
+
+ dev->iod_meta_mempool = mempool_create_node(1,
+ mempool_kmalloc, mempool_kfree,
+ (void *)meta_size, GFP_KERNEL,
+ dev_to_node(dev->dev));
+ if (!dev->iod_meta_mempool)
+ goto free;
+
return 0;
+free:
+ mempool_destroy(dev->iod_mempool);
+ return -ENOMEM;
}
static void nvme_free_tagset(struct nvme_dev *dev)
@@ -2790,6 +2942,11 @@ static void nvme_reset_work(struct work_struct *work)
if (result)
goto out;
+ if (nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ dev->ctrl.max_integrity_segments = NVME_MAX_META_SEGS;
+ else
+ dev->ctrl.max_integrity_segments = 1;
+
nvme_dbbuf_dma_alloc(dev);
result = nvme_setup_host_mem(dev);
@@ -3057,11 +3214,6 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
dev->ctrl.max_hw_sectors = min_t(u32,
NVME_MAX_KB_SZ << 1, dma_opt_mapping_size(&pdev->dev) >> 9);
dev->ctrl.max_segments = NVME_MAX_SEGS;
-
- /*
- * There is no support for SGLs for metadata (yet), so we are limited to
- * a single integrity segment for the separate metadata pointer.
- */
dev->ctrl.max_integrity_segments = 1;
return dev;
@@ -3124,6 +3276,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (result)
goto out_disable;
+ if (nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ dev->ctrl.max_integrity_segments = NVME_MAX_META_SEGS;
+ else
+ dev->ctrl.max_integrity_segments = 1;
+
nvme_dbbuf_dma_alloc(dev);
result = nvme_setup_host_mem(dev);
@@ -3166,6 +3323,7 @@ out_disable:
nvme_free_queues(dev, 0);
out_release_iod_mempool:
mempool_destroy(dev->iod_mempool);
+ mempool_destroy(dev->iod_meta_mempool);
out_release_prp_pools:
nvme_release_prp_pools(dev);
out_dev_unmap:
@@ -3231,6 +3389,7 @@ static void nvme_remove(struct pci_dev *pdev)
nvme_dbbuf_dma_free(dev);
nvme_free_queues(dev, 0);
mempool_destroy(dev->iod_mempool);
+ mempool_destroy(dev->iod_meta_mempool);
nvme_release_prp_pools(dev);
nvme_dev_unmap(dev);
nvme_uninit_ctrl(&dev->ctrl);
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
index dc7922f22600..cf2d2c5039dd 100644
--- a/drivers/nvme/host/pr.c
+++ b/drivers/nvme/host/pr.c
@@ -94,109 +94,137 @@ static int nvme_status_to_pr_err(int status)
}
}
-static int nvme_send_pr_command(struct block_device *bdev,
- struct nvme_command *c, void *data, unsigned int data_len)
+static int __nvme_send_pr_command(struct block_device *bdev, u32 cdw10,
+ u32 cdw11, u8 op, void *data, unsigned int data_len)
{
- if (nvme_disk_is_ns_head(bdev->bd_disk))
- return nvme_send_ns_head_pr_command(bdev, c, data, data_len);
+ struct nvme_command c = { 0 };
- return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c, data,
- data_len);
+ c.common.opcode = op;
+ c.common.cdw10 = cpu_to_le32(cdw10);
+ c.common.cdw11 = cpu_to_le32(cdw11);
+
+ if (nvme_disk_is_ns_head(bdev->bd_disk))
+ return nvme_send_ns_head_pr_command(bdev, &c, data, data_len);
+ return nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c,
+ data, data_len);
}
-static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
- u64 key, u64 sa_key, u8 op)
+static int nvme_send_pr_command(struct block_device *bdev, u32 cdw10, u32 cdw11,
+ u8 op, void *data, unsigned int data_len)
{
- struct nvme_command c = { };
- u8 data[16] = { 0, };
int ret;
- put_unaligned_le64(key, &data[0]);
- put_unaligned_le64(sa_key, &data[8]);
-
- c.common.opcode = op;
- c.common.cdw10 = cpu_to_le32(cdw10);
-
- ret = nvme_send_pr_command(bdev, &c, data, sizeof(data));
- if (ret < 0)
- return ret;
-
- return nvme_status_to_pr_err(ret);
+ ret = __nvme_send_pr_command(bdev, cdw10, cdw11, op, data, data_len);
+ return ret < 0 ? ret : nvme_status_to_pr_err(ret);
}
-static int nvme_pr_register(struct block_device *bdev, u64 old,
- u64 new, unsigned flags)
+static int nvme_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
+ unsigned int flags)
{
+ struct nvmet_pr_register_data data = { 0 };
u32 cdw10;
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- cdw10 = old ? 2 : 0;
- cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0;
- cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register);
+ data.crkey = cpu_to_le64(old_key);
+ data.nrkey = cpu_to_le64(new_key);
+
+ cdw10 = old_key ? NVME_PR_REGISTER_ACT_REPLACE :
+ NVME_PR_REGISTER_ACT_REG;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? NVME_PR_IGNORE_KEY : 0;
+ cdw10 |= NVME_PR_CPTPL_PERSIST;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_register,
+ &data, sizeof(data));
}
static int nvme_pr_reserve(struct block_device *bdev, u64 key,
enum pr_type type, unsigned flags)
{
+ struct nvmet_pr_acquire_data data = { 0 };
u32 cdw10;
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- cdw10 = nvme_pr_type_from_blk(type) << 8;
- cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire);
+ data.crkey = cpu_to_le64(key);
+
+ cdw10 = NVME_PR_ACQUIRE_ACT_ACQUIRE;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? NVME_PR_IGNORE_KEY : 0;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_acquire,
+ &data, sizeof(data));
}
static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
enum pr_type type, bool abort)
{
- u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (abort ? 2 : 1);
+ struct nvmet_pr_acquire_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(old);
+ data.prkey = cpu_to_le64(new);
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
+ cdw10 = abort ? NVME_PR_ACQUIRE_ACT_PREEMPT_AND_ABORT :
+ NVME_PR_ACQUIRE_ACT_PREEMPT;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_acquire,
+ &data, sizeof(data));
}
static int nvme_pr_clear(struct block_device *bdev, u64 key)
{
- u32 cdw10 = 1 | (key ? 0 : 1 << 3);
+ struct nvmet_pr_release_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(key);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ cdw10 = NVME_PR_RELEASE_ACT_CLEAR;
+ cdw10 |= key ? 0 : NVME_PR_IGNORE_KEY;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_release,
+ &data, sizeof(data));
}
static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
{
- u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (key ? 0 : 1 << 3);
+ struct nvmet_pr_release_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(key);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ cdw10 = NVME_PR_RELEASE_ACT_RELEASE;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+ cdw10 |= key ? 0 : NVME_PR_IGNORE_KEY;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_release,
+ &data, sizeof(data));
}
static int nvme_pr_resv_report(struct block_device *bdev, void *data,
u32 data_len, bool *eds)
{
- struct nvme_command c = { };
+ u32 cdw10, cdw11;
int ret;
- c.common.opcode = nvme_cmd_resv_report;
- c.common.cdw10 = cpu_to_le32(nvme_bytes_to_numd(data_len));
- c.common.cdw11 = cpu_to_le32(NVME_EXTENDED_DATA_STRUCT);
+ cdw10 = nvme_bytes_to_numd(data_len);
+ cdw11 = NVME_EXTENDED_DATA_STRUCT;
*eds = true;
retry:
- ret = nvme_send_pr_command(bdev, &c, data, data_len);
+ ret = __nvme_send_pr_command(bdev, cdw10, cdw11, nvme_cmd_resv_report,
+ data, data_len);
if (ret == NVME_SC_HOST_ID_INCONSIST &&
- c.common.cdw11 == cpu_to_le32(NVME_EXTENDED_DATA_STRUCT)) {
- c.common.cdw11 = 0;
+ cdw11 == NVME_EXTENDED_DATA_STRUCT) {
+ cdw11 = 0;
*eds = false;
goto retry;
}
- if (ret < 0)
- return ret;
-
- return nvme_status_to_pr_err(ret);
+ return ret < 0 ? ret : nvme_status_to_pr_err(ret);
}
static int nvme_pr_read_keys(struct block_device *bdev,
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 24a2759798d0..baf7d2490152 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -1019,7 +1019,7 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new)
goto destroy_admin;
}
- if (!(ctrl->ctrl.sgls & (1 << 2))) {
+ if (!(ctrl->ctrl.sgls & NVME_CTRL_SGLS_KSDBDS)) {
ret = -EOPNOTSUPP;
dev_err(ctrl->ctrl.device,
"Mandatory keyed sgls are not supported!\n");
@@ -1051,7 +1051,7 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new)
ctrl->ctrl.sqsize = ctrl->ctrl.maxcmd - 1;
}
- if (ctrl->ctrl.sgls & (1 << 20))
+ if (ctrl->ctrl.sgls & NVME_CTRL_SGLS_SAOS)
ctrl->use_inline_data = true;
if (ctrl->ctrl.queue_count > 1) {
diff --git a/drivers/nvme/host/trace.c b/drivers/nvme/host/trace.c
index 87c437fc070d..ad25ad1e4041 100644
--- a/drivers/nvme/host/trace.c
+++ b/drivers/nvme/host/trace.c
@@ -228,27 +228,61 @@ static const char *nvme_trace_zone_mgmt_recv(struct trace_seq *p, u8 *cdw10)
static const char *nvme_trace_resv_reg(struct trace_seq *p, u8 *cdw10)
{
+ static const char * const rrega_strs[] = {
+ [0x00] = "register",
+ [0x01] = "unregister",
+ [0x02] = "replace",
+ };
const char *ret = trace_seq_buffer_ptr(p);
u8 rrega = cdw10[0] & 0x7;
u8 iekey = (cdw10[0] >> 3) & 0x1;
u8 ptpl = (cdw10[3] >> 6) & 0x3;
+ const char *rrega_str;
+
+ if (rrega < ARRAY_SIZE(rrega_strs) && rrega_strs[rrega])
+ rrega_str = rrega_strs[rrega];
+ else
+ rrega_str = "reserved";
- trace_seq_printf(p, "rrega=%u, iekey=%u, ptpl=%u",
- rrega, iekey, ptpl);
+ trace_seq_printf(p, "rrega=%u:%s, iekey=%u, ptpl=%u",
+ rrega, rrega_str, iekey, ptpl);
trace_seq_putc(p, 0);
return ret;
}
+static const char * const rtype_strs[] = {
+ [0x00] = "reserved",
+ [0x01] = "write exclusive",
+ [0x02] = "exclusive access",
+ [0x03] = "write exclusive registrants only",
+ [0x04] = "exclusive access registrants only",
+ [0x05] = "write exclusive all registrants",
+ [0x06] = "exclusive access all registrants",
+};
+
static const char *nvme_trace_resv_acq(struct trace_seq *p, u8 *cdw10)
{
+ static const char * const racqa_strs[] = {
+ [0x00] = "acquire",
+ [0x01] = "preempt",
+ [0x02] = "preempt and abort",
+ };
const char *ret = trace_seq_buffer_ptr(p);
u8 racqa = cdw10[0] & 0x7;
u8 iekey = (cdw10[0] >> 3) & 0x1;
u8 rtype = cdw10[1];
+ const char *racqa_str = "reserved";
+ const char *rtype_str = "reserved";
- trace_seq_printf(p, "racqa=%u, iekey=%u, rtype=%u",
- racqa, iekey, rtype);
+ if (racqa < ARRAY_SIZE(racqa_strs) && racqa_strs[racqa])
+ racqa_str = racqa_strs[racqa];
+
+ if (rtype < ARRAY_SIZE(rtype_strs) && rtype_strs[rtype])
+ rtype_str = rtype_strs[rtype];
+
+ trace_seq_printf(p, "racqa=%u:%s, iekey=%u, rtype=%u:%s",
+ racqa, racqa_str, iekey, rtype, rtype_str);
trace_seq_putc(p, 0);
return ret;
@@ -256,13 +290,25 @@ static const char *nvme_trace_resv_acq(struct trace_seq *p, u8 *cdw10)
static const char *nvme_trace_resv_rel(struct trace_seq *p, u8 *cdw10)
{
+ static const char * const rrela_strs[] = {
+ [0x00] = "release",
+ [0x01] = "clear",
+ };
const char *ret = trace_seq_buffer_ptr(p);
u8 rrela = cdw10[0] & 0x7;
u8 iekey = (cdw10[0] >> 3) & 0x1;
u8 rtype = cdw10[1];
+ const char *rrela_str = "reserved";
+ const char *rtype_str = "reserved";
+
+ if (rrela < ARRAY_SIZE(rrela_strs) && rrela_strs[rrela])
+ rrela_str = rrela_strs[rrela];
+
+ if (rtype < ARRAY_SIZE(rtype_strs) && rtype_strs[rtype])
+ rtype_str = rtype_strs[rtype];
- trace_seq_printf(p, "rrela=%u, iekey=%u, rtype=%u",
- rrela, iekey, rtype);
+ trace_seq_printf(p, "rrela=%u:%s, iekey=%u, rtype=%u:%s",
+ rrela, rrela_str, iekey, rtype, rtype_str);
trace_seq_putc(p, 0);
return ret;
diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c
index 9a06f9d98cd6..382949e18c6a 100644
--- a/drivers/nvme/host/zns.c
+++ b/drivers/nvme/host/zns.c
@@ -111,7 +111,7 @@ void nvme_update_zone_info(struct nvme_ns *ns, struct queue_limits *lim,
lim->features |= BLK_FEAT_ZONED;
lim->max_open_zones = zi->max_open_zones;
lim->max_active_zones = zi->max_active_zones;
- lim->max_zone_append_sectors = ns->ctrl->max_zone_append;
+ lim->max_hw_zone_append_sectors = ns->ctrl->max_zone_append;
lim->chunk_sectors = ns->head->zsze =
nvme_lba_to_sect(ns->head, zi->zone_size);
}
diff --git a/drivers/nvme/target/Makefile b/drivers/nvme/target/Makefile
index c402c44350b2..f2b025bbe10c 100644
--- a/drivers/nvme/target/Makefile
+++ b/drivers/nvme/target/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_NVME_TARGET_FCLOOP) += nvme-fcloop.o
obj-$(CONFIG_NVME_TARGET_TCP) += nvmet-tcp.o
nvmet-y += core.o configfs.o admin-cmd.o fabrics-cmd.o \
- discovery.o io-cmd-file.o io-cmd-bdev.o
+ discovery.o io-cmd-file.o io-cmd-bdev.o pr.o
nvmet-$(CONFIG_NVME_TARGET_DEBUGFS) += debugfs.o
nvmet-$(CONFIG_NVME_TARGET_PASSTHRU) += passthru.o
nvmet-$(CONFIG_BLK_DEV_ZONED) += zns.o
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 081f0473cd9e..4fa8496a4d96 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -71,6 +71,35 @@ static void nvmet_execute_get_log_page_error(struct nvmet_req *req)
nvmet_req_complete(req, 0);
}
+static void nvmet_execute_get_supported_log_pages(struct nvmet_req *req)
+{
+ struct nvme_supported_log *logs;
+ u16 status;
+
+ logs = kzalloc(sizeof(*logs), GFP_KERNEL);
+ if (!logs) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ logs->lids[NVME_LOG_SUPPORTED] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_ERROR] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_SMART] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_FW_SLOT] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_CHANGED_NS] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_CMD_EFFECTS] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_ENDURANCE_GROUP] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_ANA] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_FEATURES] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_RMI] = cpu_to_le32(NVME_LIDS_LSUPP);
+ logs->lids[NVME_LOG_RESERVATION] = cpu_to_le32(NVME_LIDS_LSUPP);
+
+ status = nvmet_copy_to_sgl(req, 0, logs, sizeof(*logs));
+ kfree(logs);
+out:
+ nvmet_req_complete(req, status);
+}
+
static u16 nvmet_get_smart_log_nsid(struct nvmet_req *req,
struct nvme_smart_log *slog)
{
@@ -130,6 +159,45 @@ static u16 nvmet_get_smart_log_all(struct nvmet_req *req,
return NVME_SC_SUCCESS;
}
+static void nvmet_execute_get_log_page_rmi(struct nvmet_req *req)
+{
+ struct nvme_rotational_media_log *log;
+ struct gendisk *disk;
+ u16 status;
+
+ req->cmd->common.nsid = cpu_to_le32(le16_to_cpu(
+ req->cmd->get_log_page.lsi));
+ status = nvmet_req_find_ns(req);
+ if (status)
+ goto out;
+
+ if (!req->ns->bdev || bdev_nonrot(req->ns->bdev)) {
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+ goto out;
+ }
+
+ if (req->transfer_len != sizeof(*log)) {
+ status = NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR;
+ goto out;
+ }
+
+ log = kzalloc(sizeof(*log), GFP_KERNEL);
+ if (!log)
+ goto out;
+
+ log->endgid = req->cmd->get_log_page.lsi;
+ disk = req->ns->bdev->bd_disk;
+ if (disk && disk->ia_ranges)
+ log->numa = cpu_to_le16(disk->ia_ranges->nr_ia_ranges);
+ else
+ log->numa = cpu_to_le16(1);
+
+ status = nvmet_copy_to_sgl(req, 0, log, sizeof(*log));
+ kfree(log);
+out:
+ nvmet_req_complete(req, status);
+}
+
static void nvmet_execute_get_log_page_smart(struct nvmet_req *req)
{
struct nvme_smart_log *log;
@@ -176,6 +244,10 @@ static void nvmet_get_cmd_effects_nvm(struct nvme_effects_log *log)
log->iocs[nvme_cmd_read] =
log->iocs[nvme_cmd_flush] =
log->iocs[nvme_cmd_dsm] =
+ log->iocs[nvme_cmd_resv_acquire] =
+ log->iocs[nvme_cmd_resv_register] =
+ log->iocs[nvme_cmd_resv_release] =
+ log->iocs[nvme_cmd_resv_report] =
cpu_to_le32(NVME_CMD_EFFECTS_CSUPP);
log->iocs[nvme_cmd_write] =
log->iocs[nvme_cmd_write_zeroes] =
@@ -272,6 +344,49 @@ static u32 nvmet_format_ana_group(struct nvmet_req *req, u32 grpid,
return struct_size(desc, nsids, count);
}
+static void nvmet_execute_get_log_page_endgrp(struct nvmet_req *req)
+{
+ u64 host_reads, host_writes, data_units_read, data_units_written;
+ struct nvme_endurance_group_log *log;
+ u16 status;
+
+ /*
+ * The target driver emulates each endurance group as its own
+ * namespace, reusing the nsid as the endurance group identifier.
+ */
+ req->cmd->common.nsid = cpu_to_le32(le16_to_cpu(
+ req->cmd->get_log_page.lsi));
+ status = nvmet_req_find_ns(req);
+ if (status)
+ goto out;
+
+ log = kzalloc(sizeof(*log), GFP_KERNEL);
+ if (!log) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ if (!req->ns->bdev)
+ goto copy;
+
+ host_reads = part_stat_read(req->ns->bdev, ios[READ]);
+ data_units_read =
+ DIV_ROUND_UP(part_stat_read(req->ns->bdev, sectors[READ]), 1000);
+ host_writes = part_stat_read(req->ns->bdev, ios[WRITE]);
+ data_units_written =
+ DIV_ROUND_UP(part_stat_read(req->ns->bdev, sectors[WRITE]), 1000);
+
+ put_unaligned_le64(host_reads, &log->hrc[0]);
+ put_unaligned_le64(data_units_read, &log->dur[0]);
+ put_unaligned_le64(host_writes, &log->hwc[0]);
+ put_unaligned_le64(data_units_written, &log->duw[0]);
+copy:
+ status = nvmet_copy_to_sgl(req, 0, log, sizeof(*log));
+ kfree(log);
+out:
+ nvmet_req_complete(req, status);
+}
+
static void nvmet_execute_get_log_page_ana(struct nvmet_req *req)
{
struct nvme_ana_rsp_hdr hdr = { 0, };
@@ -317,12 +432,44 @@ out:
nvmet_req_complete(req, status);
}
+static void nvmet_execute_get_log_page_features(struct nvmet_req *req)
+{
+ struct nvme_supported_features_log *features;
+ u16 status;
+
+ features = kzalloc(sizeof(*features), GFP_KERNEL);
+ if (!features) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ features->fis[NVME_FEAT_NUM_QUEUES] =
+ cpu_to_le32(NVME_FIS_FSUPP | NVME_FIS_CSCPE);
+ features->fis[NVME_FEAT_KATO] =
+ cpu_to_le32(NVME_FIS_FSUPP | NVME_FIS_CSCPE);
+ features->fis[NVME_FEAT_ASYNC_EVENT] =
+ cpu_to_le32(NVME_FIS_FSUPP | NVME_FIS_CSCPE);
+ features->fis[NVME_FEAT_HOST_ID] =
+ cpu_to_le32(NVME_FIS_FSUPP | NVME_FIS_CSCPE);
+ features->fis[NVME_FEAT_WRITE_PROTECT] =
+ cpu_to_le32(NVME_FIS_FSUPP | NVME_FIS_NSCPE);
+ features->fis[NVME_FEAT_RESV_MASK] =
+ cpu_to_le32(NVME_FIS_FSUPP | NVME_FIS_NSCPE);
+
+ status = nvmet_copy_to_sgl(req, 0, features, sizeof(*features));
+ kfree(features);
+out:
+ nvmet_req_complete(req, status);
+}
+
static void nvmet_execute_get_log_page(struct nvmet_req *req)
{
if (!nvmet_check_transfer_len(req, nvmet_get_log_page_len(req->cmd)))
return;
switch (req->cmd->get_log_page.lid) {
+ case NVME_LOG_SUPPORTED:
+ return nvmet_execute_get_supported_log_pages(req);
case NVME_LOG_ERROR:
return nvmet_execute_get_log_page_error(req);
case NVME_LOG_SMART:
@@ -338,8 +485,16 @@ static void nvmet_execute_get_log_page(struct nvmet_req *req)
return nvmet_execute_get_log_changed_ns(req);
case NVME_LOG_CMD_EFFECTS:
return nvmet_execute_get_log_cmd_effects_ns(req);
+ case NVME_LOG_ENDURANCE_GROUP:
+ return nvmet_execute_get_log_page_endgrp(req);
case NVME_LOG_ANA:
return nvmet_execute_get_log_page_ana(req);
+ case NVME_LOG_FEATURES:
+ return nvmet_execute_get_log_page_features(req);
+ case NVME_LOG_RMI:
+ return nvmet_execute_get_log_page_rmi(req);
+ case NVME_LOG_RESERVATION:
+ return nvmet_execute_get_log_page_resv(req);
}
pr_debug("unhandled lid %d on qid %d\n",
req->cmd->get_log_page.lid, req->sq->qid);
@@ -433,7 +588,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->nn = cpu_to_le32(NVMET_MAX_NAMESPACES);
id->mnan = cpu_to_le32(NVMET_MAX_NAMESPACES);
id->oncs = cpu_to_le16(NVME_CTRL_ONCS_DSM |
- NVME_CTRL_ONCS_WRITE_ZEROES);
+ NVME_CTRL_ONCS_WRITE_ZEROES |
+ NVME_CTRL_ONCS_RESERVATIONS);
/* XXX: don't report vwc if the underlying device is write through */
id->vwc = NVME_CTRL_VWC_PRESENT;
@@ -445,11 +601,12 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->awun = 0;
id->awupf = 0;
- id->sgls = cpu_to_le32(1 << 0); /* we always support SGLs */
+ /* we always support SGLs */
+ id->sgls = cpu_to_le32(NVME_CTRL_SGLS_BYTE_ALIGNED);
if (ctrl->ops->flags & NVMF_KEYED_SGLS)
- id->sgls |= cpu_to_le32(1 << 2);
+ id->sgls |= cpu_to_le32(NVME_CTRL_SGLS_KSDBDS);
if (req->port->inline_data_size)
- id->sgls |= cpu_to_le32(1 << 20);
+ id->sgls |= cpu_to_le32(NVME_CTRL_SGLS_SAOS);
strscpy(id->subnqn, ctrl->subsys->subsysnqn, sizeof(id->subnqn));
@@ -467,6 +624,13 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->msdbd = ctrl->ops->msdbd;
+ /*
+ * Endurance group identifier is 16 bits, so we can't let namespaces
+ * overflow that since we reuse the nsid
+ */
+ BUILD_BUG_ON(NVMET_MAX_NAMESPACES > USHRT_MAX);
+ id->endgidmax = cpu_to_le16(NVMET_MAX_NAMESPACES);
+
id->anacap = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
id->anatt = 10; /* random value */
id->anagrpmax = cpu_to_le32(NVMET_MAX_ANAGRPS);
@@ -551,6 +715,21 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req)
id->nmic = NVME_NS_NMIC_SHARED;
id->anagrpid = cpu_to_le32(req->ns->anagrpid);
+ if (req->ns->pr.enable)
+ id->rescap = NVME_PR_SUPPORT_WRITE_EXCLUSIVE |
+ NVME_PR_SUPPORT_EXCLUSIVE_ACCESS |
+ NVME_PR_SUPPORT_WRITE_EXCLUSIVE_REG_ONLY |
+ NVME_PR_SUPPORT_EXCLUSIVE_ACCESS_REG_ONLY |
+ NVME_PR_SUPPORT_WRITE_EXCLUSIVE_ALL_REGS |
+ NVME_PR_SUPPORT_EXCLUSIVE_ACCESS_ALL_REGS |
+ NVME_PR_SUPPORT_IEKEY_VER_1_3_DEF;
+
+ /*
+ * Since we don't know any better, every namespace is its own endurance
+ * group.
+ */
+ id->endgid = cpu_to_le16(req->ns->nsid);
+
memcpy(&id->nguid, &req->ns->nguid, sizeof(id->nguid));
id->lbaf[0].ds = req->ns->blksize_shift;
@@ -576,7 +755,40 @@ out:
nvmet_req_complete(req, status);
}
-static void nvmet_execute_identify_nslist(struct nvmet_req *req)
+static void nvmet_execute_identify_endgrp_list(struct nvmet_req *req)
+{
+ u16 min_endgid = le16_to_cpu(req->cmd->identify.cnssid);
+ static const int buf_size = NVME_IDENTIFY_DATA_SIZE;
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_ns *ns;
+ unsigned long idx;
+ __le16 *list;
+ u16 status;
+ int i = 1;
+
+ list = kzalloc(buf_size, GFP_KERNEL);
+ if (!list) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ if (ns->nsid <= min_endgid)
+ continue;
+
+ list[i++] = cpu_to_le16(ns->nsid);
+ if (i == buf_size / sizeof(__le16))
+ break;
+ }
+
+ list[0] = cpu_to_le16(i - 1);
+ status = nvmet_copy_to_sgl(req, 0, list, buf_size);
+ kfree(list);
+out:
+ nvmet_req_complete(req, status);
+}
+
+static void nvmet_execute_identify_nslist(struct nvmet_req *req, bool match_css)
{
static const int buf_size = NVME_IDENTIFY_DATA_SIZE;
struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -606,6 +818,8 @@ static void nvmet_execute_identify_nslist(struct nvmet_req *req)
xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
if (ns->nsid <= min_nsid)
continue;
+ if (match_css && req->ns->csi != req->cmd->identify.csi)
+ continue;
list[i++] = cpu_to_le32(ns->nsid);
if (i == buf_size / sizeof(__le32))
break;
@@ -685,6 +899,56 @@ static void nvmet_execute_identify_ctrl_nvm(struct nvmet_req *req)
nvmet_zero_sgl(req, 0, sizeof(struct nvme_id_ctrl_nvm)));
}
+static void nvme_execute_identify_ns_nvm(struct nvmet_req *req)
+{
+ u16 status;
+
+ status = nvmet_req_find_ns(req);
+ if (status)
+ goto out;
+
+ status = nvmet_copy_to_sgl(req, 0, ZERO_PAGE(0),
+ NVME_IDENTIFY_DATA_SIZE);
+out:
+ nvmet_req_complete(req, status);
+}
+
+static void nvmet_execute_id_cs_indep(struct nvmet_req *req)
+{
+ struct nvme_id_ns_cs_indep *id;
+ u16 status;
+
+ status = nvmet_req_find_ns(req);
+ if (status)
+ goto out;
+
+ id = kzalloc(sizeof(*id), GFP_KERNEL);
+ if (!id) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ id->nstat = NVME_NSTAT_NRDY;
+ id->anagrpid = cpu_to_le32(req->ns->anagrpid);
+ id->nmic = NVME_NS_NMIC_SHARED;
+ if (req->ns->readonly)
+ id->nsattr |= NVME_NS_ATTR_RO;
+ if (req->ns->bdev && !bdev_nonrot(req->ns->bdev))
+ id->nsfeat |= NVME_NS_ROTATIONAL;
+ /*
+ * We need flush command to flush the file's metadata,
+ * so report supporting vwc if backend is file, even
+ * though buffered_io is disable.
+ */
+ if (req->ns->bdev && !bdev_write_cache(req->ns->bdev))
+ id->nsfeat |= NVME_NS_VWC_NOT_PRESENT;
+
+ status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
+ kfree(id);
+out:
+ nvmet_req_complete(req, status);
+}
+
static void nvmet_execute_identify(struct nvmet_req *req)
{
if (!nvmet_check_transfer_len(req, NVME_IDENTIFY_DATA_SIZE))
@@ -698,7 +962,7 @@ static void nvmet_execute_identify(struct nvmet_req *req)
nvmet_execute_identify_ctrl(req);
return;
case NVME_ID_CNS_NS_ACTIVE_LIST:
- nvmet_execute_identify_nslist(req);
+ nvmet_execute_identify_nslist(req, false);
return;
case NVME_ID_CNS_NS_DESC_LIST:
nvmet_execute_identify_desclist(req);
@@ -706,8 +970,8 @@ static void nvmet_execute_identify(struct nvmet_req *req)
case NVME_ID_CNS_CS_NS:
switch (req->cmd->identify.csi) {
case NVME_CSI_NVM:
- /* Not supported */
- break;
+ nvme_execute_identify_ns_nvm(req);
+ return;
case NVME_CSI_ZNS:
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED)) {
nvmet_execute_identify_ns_zns(req);
@@ -729,6 +993,15 @@ static void nvmet_execute_identify(struct nvmet_req *req)
break;
}
break;
+ case NVME_ID_CNS_NS_ACTIVE_LIST_CS:
+ nvmet_execute_identify_nslist(req, true);
+ return;
+ case NVME_ID_CNS_NS_CS_INDEP:
+ nvmet_execute_id_cs_indep(req);
+ return;
+ case NVME_ID_CNS_ENDGRP_LIST:
+ nvmet_execute_identify_endgrp_list(req);
+ return;
}
pr_debug("unhandled identify cns %d on qid %d\n",
@@ -861,6 +1134,9 @@ void nvmet_execute_set_features(struct nvmet_req *req)
case NVME_FEAT_WRITE_PROTECT:
status = nvmet_set_feat_write_protect(req);
break;
+ case NVME_FEAT_RESV_MASK:
+ status = nvmet_set_feat_resv_notif_mask(req, cdw11);
+ break;
default:
req->error_loc = offsetof(struct nvme_common_command, cdw10);
status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
@@ -959,6 +1235,9 @@ void nvmet_execute_get_features(struct nvmet_req *req)
case NVME_FEAT_WRITE_PROTECT:
status = nvmet_get_feat_write_protect(req);
break;
+ case NVME_FEAT_RESV_MASK:
+ status = nvmet_get_feat_resv_notif_mask(req);
+ break;
default:
req->error_loc =
offsetof(struct nvme_common_command, cdw10);
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 685e89b35d33..eeee9e9b854c 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -769,6 +769,32 @@ static ssize_t nvmet_ns_revalidate_size_store(struct config_item *item,
CONFIGFS_ATTR_WO(nvmet_ns_, revalidate_size);
+static ssize_t nvmet_ns_resv_enable_show(struct config_item *item, char *page)
+{
+ return sysfs_emit(page, "%d\n", to_nvmet_ns(item)->pr.enable);
+}
+
+static ssize_t nvmet_ns_resv_enable_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct nvmet_ns *ns = to_nvmet_ns(item);
+ bool val;
+
+ if (kstrtobool(page, &val))
+ return -EINVAL;
+
+ mutex_lock(&ns->subsys->lock);
+ if (ns->enabled) {
+ pr_err("the ns:%d is already enabled.\n", ns->nsid);
+ mutex_unlock(&ns->subsys->lock);
+ return -EINVAL;
+ }
+ ns->pr.enable = val;
+ mutex_unlock(&ns->subsys->lock);
+ return count;
+}
+CONFIGFS_ATTR(nvmet_ns_, resv_enable);
+
static struct configfs_attribute *nvmet_ns_attrs[] = {
&nvmet_ns_attr_device_path,
&nvmet_ns_attr_device_nguid,
@@ -777,6 +803,7 @@ static struct configfs_attribute *nvmet_ns_attrs[] = {
&nvmet_ns_attr_enable,
&nvmet_ns_attr_buffered_io,
&nvmet_ns_attr_revalidate_size,
+ &nvmet_ns_attr_resv_enable,
#ifdef CONFIG_PCI_P2PDMA
&nvmet_ns_attr_p2pmem,
#endif
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index ed2424f8a396..1f4e9989663b 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -611,6 +611,12 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
if (ret)
goto out_restore_subsys_maxnsid;
+ if (ns->pr.enable) {
+ ret = nvmet_pr_init_ns(ns);
+ if (ret)
+ goto out_remove_from_subsys;
+ }
+
subsys->nr_namespaces++;
nvmet_ns_changed(subsys, ns->nsid);
@@ -620,6 +626,8 @@ out_unlock:
mutex_unlock(&subsys->lock);
return ret;
+out_remove_from_subsys:
+ xa_erase(&subsys->namespaces, ns->nsid);
out_restore_subsys_maxnsid:
subsys->max_nsid = nvmet_max_nsid(subsys);
percpu_ref_exit(&ns->ref);
@@ -663,6 +671,9 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
wait_for_completion(&ns->disable_done);
percpu_ref_exit(&ns->ref);
+ if (ns->pr.enable)
+ nvmet_pr_exit_ns(ns);
+
mutex_lock(&subsys->lock);
subsys->nr_namespaces--;
@@ -754,6 +765,7 @@ static void nvmet_set_error(struct nvmet_req *req, u16 status)
static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
{
struct nvmet_ns *ns = req->ns;
+ struct nvmet_pr_per_ctrl_ref *pc_ref = req->pc_ref;
if (!req->sq->sqhd_disabled)
nvmet_update_sq_head(req);
@@ -766,6 +778,9 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
trace_nvmet_req_complete(req);
req->ops->queue_response(req);
+
+ if (pc_ref)
+ nvmet_pr_put_ns_pc_ref(pc_ref);
if (ns)
nvmet_put_namespace(ns);
}
@@ -929,18 +944,39 @@ static u16 nvmet_parse_io_cmd(struct nvmet_req *req)
return ret;
}
+ if (req->ns->pr.enable) {
+ ret = nvmet_parse_pr_cmd(req);
+ if (!ret)
+ return ret;
+ }
+
switch (req->ns->csi) {
case NVME_CSI_NVM:
if (req->ns->file)
- return nvmet_file_parse_io_cmd(req);
- return nvmet_bdev_parse_io_cmd(req);
+ ret = nvmet_file_parse_io_cmd(req);
+ else
+ ret = nvmet_bdev_parse_io_cmd(req);
+ break;
case NVME_CSI_ZNS:
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED))
- return nvmet_bdev_zns_parse_io_cmd(req);
- return NVME_SC_INVALID_IO_CMD_SET;
+ ret = nvmet_bdev_zns_parse_io_cmd(req);
+ else
+ ret = NVME_SC_INVALID_IO_CMD_SET;
+ break;
default:
- return NVME_SC_INVALID_IO_CMD_SET;
+ ret = NVME_SC_INVALID_IO_CMD_SET;
}
+ if (ret)
+ return ret;
+
+ if (req->ns->pr.enable) {
+ ret = nvmet_pr_check_cmd_access(req);
+ if (ret)
+ return ret;
+
+ ret = nvmet_pr_get_ns_pc_ref(req);
+ }
+ return ret;
}
bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
@@ -964,6 +1000,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
req->ns = NULL;
req->error_loc = NVMET_NO_ERROR_LOC;
req->error_slba = 0;
+ req->pc_ref = NULL;
/* no support for fused commands yet */
if (unlikely(flags & (NVME_CMD_FUSE_FIRST | NVME_CMD_FUSE_SECOND))) {
@@ -1015,6 +1052,8 @@ EXPORT_SYMBOL_GPL(nvmet_req_init);
void nvmet_req_uninit(struct nvmet_req *req)
{
percpu_ref_put(&req->sq->ref);
+ if (req->pc_ref)
+ nvmet_pr_put_ns_pc_ref(req->pc_ref);
if (req->ns)
nvmet_put_namespace(req->ns);
}
@@ -1383,7 +1422,8 @@ static void nvmet_fatal_error_handler(struct work_struct *work)
}
u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
- struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp)
+ struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp,
+ uuid_t *hostid)
{
struct nvmet_subsys *subsys;
struct nvmet_ctrl *ctrl;
@@ -1462,6 +1502,8 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
}
ctrl->cntlid = ret;
+ uuid_copy(&ctrl->hostid, hostid);
+
/*
* Discovery controllers may use some arbitrary high value
* in order to cleanup stale discovery sessions
@@ -1478,6 +1520,9 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
nvmet_start_keep_alive_timer(ctrl);
mutex_lock(&subsys->lock);
+ ret = nvmet_ctrl_init_pr(ctrl);
+ if (ret)
+ goto init_pr_fail;
list_add_tail(&ctrl->subsys_entry, &subsys->ctrls);
nvmet_setup_p2p_ns_map(ctrl, req);
nvmet_debugfs_ctrl_setup(ctrl);
@@ -1486,6 +1531,10 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
*ctrlp = ctrl;
return 0;
+init_pr_fail:
+ mutex_unlock(&subsys->lock);
+ nvmet_stop_keep_alive_timer(ctrl);
+ ida_free(&cntlid_ida, ctrl->cntlid);
out_free_sqs:
kfree(ctrl->sqs);
out_free_changed_ns_list:
@@ -1504,6 +1553,7 @@ static void nvmet_ctrl_free(struct kref *ref)
struct nvmet_subsys *subsys = ctrl->subsys;
mutex_lock(&subsys->lock);
+ nvmet_ctrl_destroy_pr(ctrl);
nvmet_release_p2p_ns_map(ctrl);
list_del(&ctrl->subsys_entry);
mutex_unlock(&subsys->lock);
@@ -1717,7 +1767,7 @@ static int __init nvmet_init(void)
goto out_free_zbd_work_queue;
nvmet_wq = alloc_workqueue("nvmet-wq",
- WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
+ WQ_MEM_RECLAIM | WQ_UNBOUND | WQ_SYSFS, 0);
if (!nvmet_wq)
goto out_free_buffered_work_queue;
diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index c4b2eddd5666..c49904ebb6c2 100644
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -64,6 +64,9 @@ static void nvmet_execute_prop_get(struct nvmet_req *req)
case NVME_REG_CSTS:
val = ctrl->csts;
break;
+ case NVME_REG_CRTO:
+ val = NVME_CAP_TIMEOUT(ctrl->csts);
+ break;
default:
status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
break;
@@ -245,12 +248,10 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
status = nvmet_alloc_ctrl(d->subsysnqn, d->hostnqn, req,
- le32_to_cpu(c->kato), &ctrl);
+ le32_to_cpu(c->kato), &ctrl, &d->hostid);
if (status)
goto out;
- uuid_copy(&ctrl->hostid, &d->hostid);
-
dhchap_status = nvmet_setup_auth(ctrl);
if (dhchap_status) {
pr_err("Failed to setup authentication, dhchap status %u\n",
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 190f55e6d753..58328b35dc96 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -20,8 +20,9 @@
#include <linux/blkdev.h>
#include <linux/radix-tree.h>
#include <linux/t10-pi.h>
+#include <linux/kfifo.h>
-#define NVMET_DEFAULT_VS NVME_VS(1, 3, 0)
+#define NVMET_DEFAULT_VS NVME_VS(2, 1, 0)
#define NVMET_ASYNC_EVENTS 4
#define NVMET_ERROR_LOG_SLOTS 128
@@ -30,6 +31,7 @@
#define NVMET_MN_MAX_SIZE 40
#define NVMET_SN_MAX_SIZE 20
#define NVMET_FR_MAX_SIZE 8
+#define NVMET_PR_LOG_QUEUE_SIZE 64
/*
* Supported optional AENs:
@@ -56,6 +58,38 @@
#define IPO_IATTR_CONNECT_SQE(x) \
(cpu_to_le32(offsetof(struct nvmf_connect_command, x)))
+struct nvmet_pr_registrant {
+ u64 rkey;
+ uuid_t hostid;
+ enum nvme_pr_type rtype;
+ struct list_head entry;
+ struct rcu_head rcu;
+};
+
+struct nvmet_pr {
+ bool enable;
+ unsigned long notify_mask;
+ atomic_t generation;
+ struct nvmet_pr_registrant __rcu *holder;
+ /*
+ * During the execution of the reservation command, mutual
+ * exclusion is required throughout the process. However,
+ * while waiting asynchronously for the 'per controller
+ * percpu_ref' to complete before the 'preempt and abort'
+ * command finishes, a semaphore is needed to ensure mutual
+ * exclusion instead of a mutex.
+ */
+ struct semaphore pr_sem;
+ struct list_head registrant_list;
+};
+
+struct nvmet_pr_per_ctrl_ref {
+ struct percpu_ref ref;
+ struct completion free_done;
+ struct completion confirm_done;
+ uuid_t hostid;
+};
+
struct nvmet_ns {
struct percpu_ref ref;
struct file *bdev_file;
@@ -85,6 +119,8 @@ struct nvmet_ns {
int pi_type;
int metadata_size;
u8 csi;
+ struct nvmet_pr pr;
+ struct xarray pr_per_ctrl_refs;
};
static inline struct nvmet_ns *to_nvmet_ns(struct config_item *item)
@@ -191,6 +227,13 @@ static inline bool nvmet_port_secure_channel_required(struct nvmet_port *port)
return nvmet_port_disc_addr_treq_secure_channel(port) == NVMF_TREQ_REQUIRED;
}
+struct nvmet_pr_log_mgr {
+ struct mutex lock;
+ u64 lost_count;
+ u64 counter;
+ DECLARE_KFIFO(log_queue, struct nvme_pr_log, NVMET_PR_LOG_QUEUE_SIZE);
+};
+
struct nvmet_ctrl {
struct nvmet_subsys *subsys;
struct nvmet_sq **sqs;
@@ -246,6 +289,7 @@ struct nvmet_ctrl {
u8 *dh_key;
size_t dh_keysize;
#endif
+ struct nvmet_pr_log_mgr pr_log_mgr;
};
struct nvmet_subsys {
@@ -396,6 +440,9 @@ struct nvmet_req {
struct work_struct zmgmt_work;
} z;
#endif /* CONFIG_BLK_DEV_ZONED */
+ struct {
+ struct work_struct abort_work;
+ } r;
};
int sg_cnt;
int metadata_sg_cnt;
@@ -412,6 +459,7 @@ struct nvmet_req {
struct device *p2p_client;
u16 error_loc;
u64 error_slba;
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
};
#define NVMET_MAX_MPOOL_BVEC 16
@@ -498,7 +546,8 @@ void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl);
void nvmet_update_cc(struct nvmet_ctrl *ctrl, u32 new);
u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
- struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp);
+ struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp,
+ uuid_t *hostid);
struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn,
const char *hostnqn, u16 cntlid,
struct nvmet_req *req);
@@ -761,4 +810,18 @@ static inline bool nvmet_has_auth(struct nvmet_ctrl *ctrl)
static inline const char *nvmet_dhchap_dhgroup_name(u8 dhgid) { return NULL; }
#endif
+int nvmet_pr_init_ns(struct nvmet_ns *ns);
+u16 nvmet_parse_pr_cmd(struct nvmet_req *req);
+u16 nvmet_pr_check_cmd_access(struct nvmet_req *req);
+int nvmet_ctrl_init_pr(struct nvmet_ctrl *ctrl);
+void nvmet_ctrl_destroy_pr(struct nvmet_ctrl *ctrl);
+void nvmet_pr_exit_ns(struct nvmet_ns *ns);
+void nvmet_execute_get_log_page_resv(struct nvmet_req *req);
+u16 nvmet_set_feat_resv_notif_mask(struct nvmet_req *req, u32 mask);
+u16 nvmet_get_feat_resv_notif_mask(struct nvmet_req *req);
+u16 nvmet_pr_get_ns_pc_ref(struct nvmet_req *req);
+static inline void nvmet_pr_put_ns_pc_ref(struct nvmet_pr_per_ctrl_ref *pc_ref)
+{
+ percpu_ref_put(&pc_ref->ref);
+}
#endif /* _NVMET_H */
diff --git a/drivers/nvme/target/pr.c b/drivers/nvme/target/pr.c
new file mode 100644
index 000000000000..25a02b50d9f3
--- /dev/null
+++ b/drivers/nvme/target/pr.c
@@ -0,0 +1,1156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * NVMe over Fabrics Persist Reservation.
+ * Copyright (c) 2024 Guixin Liu, Alibaba Group.
+ * All rights reserved.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/unaligned.h>
+#include "nvmet.h"
+
+#define NVMET_PR_NOTIFI_MASK_ALL \
+ (1 << NVME_PR_NOTIFY_BIT_REG_PREEMPTED | \
+ 1 << NVME_PR_NOTIFY_BIT_RESV_RELEASED | \
+ 1 << NVME_PR_NOTIFY_BIT_RESV_PREEMPTED)
+
+static inline bool nvmet_pr_parse_ignore_key(u32 cdw10)
+{
+ /* Ignore existing key, bit 03. */
+ return (cdw10 >> 3) & 1;
+}
+
+static inline struct nvmet_ns *nvmet_pr_to_ns(struct nvmet_pr *pr)
+{
+ return container_of(pr, struct nvmet_ns, pr);
+}
+
+static struct nvmet_pr_registrant *
+nvmet_pr_find_registrant(struct nvmet_pr *pr, uuid_t *hostid)
+{
+ struct nvmet_pr_registrant *reg;
+
+ list_for_each_entry_rcu(reg, &pr->registrant_list, entry) {
+ if (uuid_equal(&reg->hostid, hostid))
+ return reg;
+ }
+ return NULL;
+}
+
+u16 nvmet_set_feat_resv_notif_mask(struct nvmet_req *req, u32 mask)
+{
+ u32 nsid = le32_to_cpu(req->cmd->common.nsid);
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_ns *ns;
+ unsigned long idx;
+ u16 status;
+
+ if (mask & ~(NVMET_PR_NOTIFI_MASK_ALL)) {
+ req->error_loc = offsetof(struct nvme_common_command, cdw11);
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+ }
+
+ if (nsid != U32_MAX) {
+ status = nvmet_req_find_ns(req);
+ if (status)
+ return status;
+ if (!req->ns->pr.enable)
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+
+ WRITE_ONCE(req->ns->pr.notify_mask, mask);
+ goto success;
+ }
+
+ xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ if (ns->pr.enable)
+ WRITE_ONCE(ns->pr.notify_mask, mask);
+ }
+
+success:
+ nvmet_set_result(req, mask);
+ return NVME_SC_SUCCESS;
+}
+
+u16 nvmet_get_feat_resv_notif_mask(struct nvmet_req *req)
+{
+ u16 status;
+
+ status = nvmet_req_find_ns(req);
+ if (status)
+ return status;
+
+ if (!req->ns->pr.enable)
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+
+ nvmet_set_result(req, READ_ONCE(req->ns->pr.notify_mask));
+ return status;
+}
+
+void nvmet_execute_get_log_page_resv(struct nvmet_req *req)
+{
+ struct nvmet_pr_log_mgr *log_mgr = &req->sq->ctrl->pr_log_mgr;
+ struct nvme_pr_log next_log = {0};
+ struct nvme_pr_log log = {0};
+ u16 status = NVME_SC_SUCCESS;
+ u64 lost_count;
+ u64 cur_count;
+ u64 next_count;
+
+ mutex_lock(&log_mgr->lock);
+ if (!kfifo_get(&log_mgr->log_queue, &log))
+ goto out;
+
+ /*
+ * We can't get the last in kfifo.
+ * Utilize the current count and the count from the next log to
+ * calculate the number of lost logs, while also addressing cases
+ * of overflow. If there is no subsequent log, the number of lost
+ * logs is equal to the lost_count within the nvmet_pr_log_mgr.
+ */
+ cur_count = le64_to_cpu(log.count);
+ if (kfifo_peek(&log_mgr->log_queue, &next_log)) {
+ next_count = le64_to_cpu(next_log.count);
+ if (next_count > cur_count)
+ lost_count = next_count - cur_count - 1;
+ else
+ lost_count = U64_MAX - cur_count + next_count - 1;
+ } else {
+ lost_count = log_mgr->lost_count;
+ }
+
+ log.count = cpu_to_le64((cur_count + lost_count) == 0 ?
+ 1 : (cur_count + lost_count));
+ log_mgr->lost_count -= lost_count;
+
+ log.nr_pages = kfifo_len(&log_mgr->log_queue);
+
+out:
+ status = nvmet_copy_to_sgl(req, 0, &log, sizeof(log));
+ mutex_unlock(&log_mgr->lock);
+ nvmet_req_complete(req, status);
+}
+
+static void nvmet_pr_add_resv_log(struct nvmet_ctrl *ctrl, u8 log_type,
+ u32 nsid)
+{
+ struct nvmet_pr_log_mgr *log_mgr = &ctrl->pr_log_mgr;
+ struct nvme_pr_log log = {0};
+
+ mutex_lock(&log_mgr->lock);
+ log_mgr->counter++;
+ if (log_mgr->counter == 0)
+ log_mgr->counter = 1;
+
+ log.count = cpu_to_le64(log_mgr->counter);
+ log.type = log_type;
+ log.nsid = cpu_to_le32(nsid);
+
+ if (!kfifo_put(&log_mgr->log_queue, log)) {
+ pr_info("a reservation log lost, cntlid:%d, log_type:%d, nsid:%d\n",
+ ctrl->cntlid, log_type, nsid);
+ log_mgr->lost_count++;
+ }
+
+ mutex_unlock(&log_mgr->lock);
+}
+
+static void nvmet_pr_resv_released(struct nvmet_pr *pr, uuid_t *hostid)
+{
+ struct nvmet_ns *ns = nvmet_pr_to_ns(pr);
+ struct nvmet_subsys *subsys = ns->subsys;
+ struct nvmet_ctrl *ctrl;
+
+ if (test_bit(NVME_PR_NOTIFY_BIT_RESV_RELEASED, &pr->notify_mask))
+ return;
+
+ mutex_lock(&subsys->lock);
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
+ if (!uuid_equal(&ctrl->hostid, hostid) &&
+ nvmet_pr_find_registrant(pr, &ctrl->hostid)) {
+ nvmet_pr_add_resv_log(ctrl,
+ NVME_PR_LOG_RESERVATION_RELEASED, ns->nsid);
+ nvmet_add_async_event(ctrl, NVME_AER_CSS,
+ NVME_AEN_RESV_LOG_PAGE_AVALIABLE,
+ NVME_LOG_RESERVATION);
+ }
+ }
+ mutex_unlock(&subsys->lock);
+}
+
+static void nvmet_pr_send_event_to_host(struct nvmet_pr *pr, uuid_t *hostid,
+ u8 log_type)
+{
+ struct nvmet_ns *ns = nvmet_pr_to_ns(pr);
+ struct nvmet_subsys *subsys = ns->subsys;
+ struct nvmet_ctrl *ctrl;
+
+ mutex_lock(&subsys->lock);
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
+ if (uuid_equal(hostid, &ctrl->hostid)) {
+ nvmet_pr_add_resv_log(ctrl, log_type, ns->nsid);
+ nvmet_add_async_event(ctrl, NVME_AER_CSS,
+ NVME_AEN_RESV_LOG_PAGE_AVALIABLE,
+ NVME_LOG_RESERVATION);
+ }
+ }
+ mutex_unlock(&subsys->lock);
+}
+
+static void nvmet_pr_resv_preempted(struct nvmet_pr *pr, uuid_t *hostid)
+{
+ if (test_bit(NVME_PR_NOTIFY_BIT_RESV_PREEMPTED, &pr->notify_mask))
+ return;
+
+ nvmet_pr_send_event_to_host(pr, hostid,
+ NVME_PR_LOG_RESERVATOIN_PREEMPTED);
+}
+
+static void nvmet_pr_registration_preempted(struct nvmet_pr *pr,
+ uuid_t *hostid)
+{
+ if (test_bit(NVME_PR_NOTIFY_BIT_REG_PREEMPTED, &pr->notify_mask))
+ return;
+
+ nvmet_pr_send_event_to_host(pr, hostid,
+ NVME_PR_LOG_REGISTRATION_PREEMPTED);
+}
+
+static inline void nvmet_pr_set_new_holder(struct nvmet_pr *pr, u8 new_rtype,
+ struct nvmet_pr_registrant *reg)
+{
+ reg->rtype = new_rtype;
+ rcu_assign_pointer(pr->holder, reg);
+}
+
+static u16 nvmet_pr_register(struct nvmet_req *req,
+ struct nvmet_pr_register_data *d)
+{
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_pr_registrant *new, *reg;
+ struct nvmet_pr *pr = &req->ns->pr;
+ u16 status = NVME_SC_SUCCESS;
+ u64 nrkey = le64_to_cpu(d->nrkey);
+
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+ if (!new)
+ return NVME_SC_INTERNAL;
+
+ down(&pr->pr_sem);
+ reg = nvmet_pr_find_registrant(pr, &ctrl->hostid);
+ if (reg) {
+ if (reg->rkey != nrkey)
+ status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ kfree(new);
+ goto out;
+ }
+
+ memset(new, 0, sizeof(*new));
+ INIT_LIST_HEAD(&new->entry);
+ new->rkey = nrkey;
+ uuid_copy(&new->hostid, &ctrl->hostid);
+ list_add_tail_rcu(&new->entry, &pr->registrant_list);
+
+out:
+ up(&pr->pr_sem);
+ return status;
+}
+
+static void nvmet_pr_unregister_one(struct nvmet_pr *pr,
+ struct nvmet_pr_registrant *reg)
+{
+ struct nvmet_pr_registrant *first_reg;
+ struct nvmet_pr_registrant *holder;
+ u8 original_rtype;
+
+ list_del_rcu(&reg->entry);
+
+ holder = rcu_dereference_protected(pr->holder, 1);
+ if (reg != holder)
+ goto out;
+
+ original_rtype = holder->rtype;
+ if (original_rtype == NVME_PR_WRITE_EXCLUSIVE_ALL_REGS ||
+ original_rtype == NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS) {
+ first_reg = list_first_or_null_rcu(&pr->registrant_list,
+ struct nvmet_pr_registrant, entry);
+ if (first_reg)
+ first_reg->rtype = original_rtype;
+ rcu_assign_pointer(pr->holder, first_reg);
+ } else {
+ rcu_assign_pointer(pr->holder, NULL);
+
+ if (original_rtype == NVME_PR_WRITE_EXCLUSIVE_REG_ONLY ||
+ original_rtype == NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY)
+ nvmet_pr_resv_released(pr, &reg->hostid);
+ }
+out:
+ kfree_rcu(reg, rcu);
+}
+
+static u16 nvmet_pr_unregister(struct nvmet_req *req,
+ struct nvmet_pr_register_data *d,
+ bool ignore_key)
+{
+ u16 status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_registrant *reg;
+
+ down(&pr->pr_sem);
+ list_for_each_entry_rcu(reg, &pr->registrant_list, entry) {
+ if (uuid_equal(&reg->hostid, &ctrl->hostid)) {
+ if (ignore_key || reg->rkey == le64_to_cpu(d->crkey)) {
+ status = NVME_SC_SUCCESS;
+ nvmet_pr_unregister_one(pr, reg);
+ }
+ break;
+ }
+ }
+ up(&pr->pr_sem);
+
+ return status;
+}
+
+static void nvmet_pr_update_reg_rkey(struct nvmet_pr_registrant *reg,
+ void *attr)
+{
+ reg->rkey = *(u64 *)attr;
+}
+
+static u16 nvmet_pr_update_reg_attr(struct nvmet_pr *pr,
+ struct nvmet_pr_registrant *reg,
+ void (*change_attr)(struct nvmet_pr_registrant *reg,
+ void *attr),
+ void *attr)
+{
+ struct nvmet_pr_registrant *holder;
+ struct nvmet_pr_registrant *new;
+
+ holder = rcu_dereference_protected(pr->holder, 1);
+ if (reg != holder) {
+ change_attr(reg, attr);
+ return NVME_SC_SUCCESS;
+ }
+
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
+ if (!new)
+ return NVME_SC_INTERNAL;
+
+ new->rkey = holder->rkey;
+ new->rtype = holder->rtype;
+ uuid_copy(&new->hostid, &holder->hostid);
+ INIT_LIST_HEAD(&new->entry);
+
+ change_attr(new, attr);
+ list_replace_rcu(&holder->entry, &new->entry);
+ rcu_assign_pointer(pr->holder, new);
+ kfree_rcu(holder, rcu);
+
+ return NVME_SC_SUCCESS;
+}
+
+static u16 nvmet_pr_replace(struct nvmet_req *req,
+ struct nvmet_pr_register_data *d,
+ bool ignore_key)
+{
+ u16 status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_registrant *reg;
+ u64 nrkey = le64_to_cpu(d->nrkey);
+
+ down(&pr->pr_sem);
+ list_for_each_entry_rcu(reg, &pr->registrant_list, entry) {
+ if (uuid_equal(&reg->hostid, &ctrl->hostid)) {
+ if (ignore_key || reg->rkey == le64_to_cpu(d->crkey))
+ status = nvmet_pr_update_reg_attr(pr, reg,
+ nvmet_pr_update_reg_rkey,
+ &nrkey);
+ break;
+ }
+ }
+ up(&pr->pr_sem);
+ return status;
+}
+
+static void nvmet_execute_pr_register(struct nvmet_req *req)
+{
+ u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
+ bool ignore_key = nvmet_pr_parse_ignore_key(cdw10);
+ struct nvmet_pr_register_data *d;
+ u8 reg_act = cdw10 & 0x07; /* Reservation Register Action, bit 02:00 */
+ u16 status;
+
+ d = kmalloc(sizeof(*d), GFP_KERNEL);
+ if (!d) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ status = nvmet_copy_from_sgl(req, 0, d, sizeof(*d));
+ if (status)
+ goto free_data;
+
+ switch (reg_act) {
+ case NVME_PR_REGISTER_ACT_REG:
+ status = nvmet_pr_register(req, d);
+ break;
+ case NVME_PR_REGISTER_ACT_UNREG:
+ status = nvmet_pr_unregister(req, d, ignore_key);
+ break;
+ case NVME_PR_REGISTER_ACT_REPLACE:
+ status = nvmet_pr_replace(req, d, ignore_key);
+ break;
+ default:
+ req->error_loc = offsetof(struct nvme_common_command, cdw10);
+ status = NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
+ break;
+ }
+free_data:
+ kfree(d);
+out:
+ if (!status)
+ atomic_inc(&req->ns->pr.generation);
+ nvmet_req_complete(req, status);
+}
+
+static u16 nvmet_pr_acquire(struct nvmet_req *req,
+ struct nvmet_pr_registrant *reg,
+ u8 rtype)
+{
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_registrant *holder;
+
+ holder = rcu_dereference_protected(pr->holder, 1);
+ if (holder && reg != holder)
+ return NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ if (holder && reg == holder) {
+ if (holder->rtype == rtype)
+ return NVME_SC_SUCCESS;
+ return NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ }
+
+ nvmet_pr_set_new_holder(pr, rtype, reg);
+ return NVME_SC_SUCCESS;
+}
+
+static void nvmet_pr_confirm_ns_pc_ref(struct percpu_ref *ref)
+{
+ struct nvmet_pr_per_ctrl_ref *pc_ref =
+ container_of(ref, struct nvmet_pr_per_ctrl_ref, ref);
+
+ complete(&pc_ref->confirm_done);
+}
+
+static void nvmet_pr_set_ctrl_to_abort(struct nvmet_req *req, uuid_t *hostid)
+{
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+ struct nvmet_ns *ns = req->ns;
+ unsigned long idx;
+
+ xa_for_each(&ns->pr_per_ctrl_refs, idx, pc_ref) {
+ if (uuid_equal(&pc_ref->hostid, hostid)) {
+ percpu_ref_kill_and_confirm(&pc_ref->ref,
+ nvmet_pr_confirm_ns_pc_ref);
+ wait_for_completion(&pc_ref->confirm_done);
+ }
+ }
+}
+
+static u16 nvmet_pr_unreg_all_host_by_prkey(struct nvmet_req *req, u64 prkey,
+ uuid_t *send_hostid,
+ bool abort)
+{
+ u16 status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ struct nvmet_pr_registrant *reg, *tmp;
+ struct nvmet_pr *pr = &req->ns->pr;
+ uuid_t hostid;
+
+ list_for_each_entry_safe(reg, tmp, &pr->registrant_list, entry) {
+ if (reg->rkey == prkey) {
+ status = NVME_SC_SUCCESS;
+ uuid_copy(&hostid, &reg->hostid);
+ if (abort)
+ nvmet_pr_set_ctrl_to_abort(req, &hostid);
+ nvmet_pr_unregister_one(pr, reg);
+ if (!uuid_equal(&hostid, send_hostid))
+ nvmet_pr_registration_preempted(pr, &hostid);
+ }
+ }
+ return status;
+}
+
+static void nvmet_pr_unreg_all_others_by_prkey(struct nvmet_req *req,
+ u64 prkey,
+ uuid_t *send_hostid,
+ bool abort)
+{
+ struct nvmet_pr_registrant *reg, *tmp;
+ struct nvmet_pr *pr = &req->ns->pr;
+ uuid_t hostid;
+
+ list_for_each_entry_safe(reg, tmp, &pr->registrant_list, entry) {
+ if (reg->rkey == prkey &&
+ !uuid_equal(&reg->hostid, send_hostid)) {
+ uuid_copy(&hostid, &reg->hostid);
+ if (abort)
+ nvmet_pr_set_ctrl_to_abort(req, &hostid);
+ nvmet_pr_unregister_one(pr, reg);
+ nvmet_pr_registration_preempted(pr, &hostid);
+ }
+ }
+}
+
+static void nvmet_pr_unreg_all_others(struct nvmet_req *req,
+ uuid_t *send_hostid,
+ bool abort)
+{
+ struct nvmet_pr_registrant *reg, *tmp;
+ struct nvmet_pr *pr = &req->ns->pr;
+ uuid_t hostid;
+
+ list_for_each_entry_safe(reg, tmp, &pr->registrant_list, entry) {
+ if (!uuid_equal(&reg->hostid, send_hostid)) {
+ uuid_copy(&hostid, &reg->hostid);
+ if (abort)
+ nvmet_pr_set_ctrl_to_abort(req, &hostid);
+ nvmet_pr_unregister_one(pr, reg);
+ nvmet_pr_registration_preempted(pr, &hostid);
+ }
+ }
+}
+
+static void nvmet_pr_update_holder_rtype(struct nvmet_pr_registrant *reg,
+ void *attr)
+{
+ u8 new_rtype = *(u8 *)attr;
+
+ reg->rtype = new_rtype;
+}
+
+static u16 nvmet_pr_preempt(struct nvmet_req *req,
+ struct nvmet_pr_registrant *reg,
+ u8 rtype,
+ struct nvmet_pr_acquire_data *d,
+ bool abort)
+{
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_registrant *holder;
+ enum nvme_pr_type original_rtype;
+ u64 prkey = le64_to_cpu(d->prkey);
+ u16 status;
+
+ holder = rcu_dereference_protected(pr->holder, 1);
+ if (!holder)
+ return nvmet_pr_unreg_all_host_by_prkey(req, prkey,
+ &ctrl->hostid, abort);
+
+ original_rtype = holder->rtype;
+ if (original_rtype == NVME_PR_WRITE_EXCLUSIVE_ALL_REGS ||
+ original_rtype == NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS) {
+ if (!prkey) {
+ /*
+ * To prevent possible access from other hosts, and
+ * avoid terminate the holder, set the new holder
+ * first before unregistering.
+ */
+ nvmet_pr_set_new_holder(pr, rtype, reg);
+ nvmet_pr_unreg_all_others(req, &ctrl->hostid, abort);
+ return NVME_SC_SUCCESS;
+ }
+ return nvmet_pr_unreg_all_host_by_prkey(req, prkey,
+ &ctrl->hostid, abort);
+ }
+
+ if (holder == reg) {
+ status = nvmet_pr_update_reg_attr(pr, holder,
+ nvmet_pr_update_holder_rtype, &rtype);
+ if (!status && original_rtype != rtype)
+ nvmet_pr_resv_released(pr, &reg->hostid);
+ return status;
+ }
+
+ if (prkey == holder->rkey) {
+ /*
+ * Same as before, set the new holder first.
+ */
+ nvmet_pr_set_new_holder(pr, rtype, reg);
+ nvmet_pr_unreg_all_others_by_prkey(req, prkey, &ctrl->hostid,
+ abort);
+ if (original_rtype != rtype)
+ nvmet_pr_resv_released(pr, &reg->hostid);
+ return NVME_SC_SUCCESS;
+ }
+
+ if (prkey)
+ return nvmet_pr_unreg_all_host_by_prkey(req, prkey,
+ &ctrl->hostid, abort);
+ return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+}
+
+static void nvmet_pr_do_abort(struct work_struct *w)
+{
+ struct nvmet_req *req = container_of(w, struct nvmet_req, r.abort_work);
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+ struct nvmet_ns *ns = req->ns;
+ unsigned long idx;
+
+ /*
+ * The target does not support abort, just wait per-controller ref to 0.
+ */
+ xa_for_each(&ns->pr_per_ctrl_refs, idx, pc_ref) {
+ if (percpu_ref_is_dying(&pc_ref->ref)) {
+ wait_for_completion(&pc_ref->free_done);
+ reinit_completion(&pc_ref->confirm_done);
+ reinit_completion(&pc_ref->free_done);
+ percpu_ref_resurrect(&pc_ref->ref);
+ }
+ }
+
+ up(&ns->pr.pr_sem);
+ nvmet_req_complete(req, NVME_SC_SUCCESS);
+}
+
+static u16 __nvmet_execute_pr_acquire(struct nvmet_req *req,
+ struct nvmet_pr_registrant *reg,
+ u8 acquire_act,
+ u8 rtype,
+ struct nvmet_pr_acquire_data *d)
+{
+ u16 status;
+
+ switch (acquire_act) {
+ case NVME_PR_ACQUIRE_ACT_ACQUIRE:
+ status = nvmet_pr_acquire(req, reg, rtype);
+ goto out;
+ case NVME_PR_ACQUIRE_ACT_PREEMPT:
+ status = nvmet_pr_preempt(req, reg, rtype, d, false);
+ goto inc_gen;
+ case NVME_PR_ACQUIRE_ACT_PREEMPT_AND_ABORT:
+ status = nvmet_pr_preempt(req, reg, rtype, d, true);
+ goto inc_gen;
+ default:
+ req->error_loc = offsetof(struct nvme_common_command, cdw10);
+ status = NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
+ goto out;
+ }
+inc_gen:
+ if (!status)
+ atomic_inc(&req->ns->pr.generation);
+out:
+ return status;
+}
+
+static void nvmet_execute_pr_acquire(struct nvmet_req *req)
+{
+ u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
+ bool ignore_key = nvmet_pr_parse_ignore_key(cdw10);
+ /* Reservation type, bit 15:08 */
+ u8 rtype = (u8)((cdw10 >> 8) & 0xff);
+ /* Reservation acquire action, bit 02:00 */
+ u8 acquire_act = cdw10 & 0x07;
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_pr_acquire_data *d = NULL;
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_registrant *reg;
+ u16 status = NVME_SC_SUCCESS;
+
+ if (ignore_key ||
+ rtype < NVME_PR_WRITE_EXCLUSIVE ||
+ rtype > NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS) {
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+ goto out;
+ }
+
+ d = kmalloc(sizeof(*d), GFP_KERNEL);
+ if (!d) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ status = nvmet_copy_from_sgl(req, 0, d, sizeof(*d));
+ if (status)
+ goto free_data;
+
+ status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ down(&pr->pr_sem);
+ list_for_each_entry_rcu(reg, &pr->registrant_list, entry) {
+ if (uuid_equal(&reg->hostid, &ctrl->hostid) &&
+ reg->rkey == le64_to_cpu(d->crkey)) {
+ status = __nvmet_execute_pr_acquire(req, reg,
+ acquire_act, rtype, d);
+ break;
+ }
+ }
+
+ if (!status && acquire_act == NVME_PR_ACQUIRE_ACT_PREEMPT_AND_ABORT) {
+ kfree(d);
+ INIT_WORK(&req->r.abort_work, nvmet_pr_do_abort);
+ queue_work(nvmet_wq, &req->r.abort_work);
+ return;
+ }
+
+ up(&pr->pr_sem);
+
+free_data:
+ kfree(d);
+out:
+ nvmet_req_complete(req, status);
+}
+
+static u16 nvmet_pr_release(struct nvmet_req *req,
+ struct nvmet_pr_registrant *reg,
+ u8 rtype)
+{
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_registrant *holder;
+ u8 original_rtype;
+
+ holder = rcu_dereference_protected(pr->holder, 1);
+ if (!holder || reg != holder)
+ return NVME_SC_SUCCESS;
+
+ original_rtype = holder->rtype;
+ if (original_rtype != rtype)
+ return NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+
+ rcu_assign_pointer(pr->holder, NULL);
+
+ if (original_rtype != NVME_PR_WRITE_EXCLUSIVE &&
+ original_rtype != NVME_PR_EXCLUSIVE_ACCESS)
+ nvmet_pr_resv_released(pr, &reg->hostid);
+
+ return NVME_SC_SUCCESS;
+}
+
+static void nvmet_pr_clear(struct nvmet_req *req)
+{
+ struct nvmet_pr_registrant *reg, *tmp;
+ struct nvmet_pr *pr = &req->ns->pr;
+
+ rcu_assign_pointer(pr->holder, NULL);
+
+ list_for_each_entry_safe(reg, tmp, &pr->registrant_list, entry) {
+ list_del_rcu(&reg->entry);
+ if (!uuid_equal(&req->sq->ctrl->hostid, &reg->hostid))
+ nvmet_pr_resv_preempted(pr, &reg->hostid);
+ kfree_rcu(reg, rcu);
+ }
+
+ atomic_inc(&pr->generation);
+}
+
+static u16 __nvmet_execute_pr_release(struct nvmet_req *req,
+ struct nvmet_pr_registrant *reg,
+ u8 release_act, u8 rtype)
+{
+ switch (release_act) {
+ case NVME_PR_RELEASE_ACT_RELEASE:
+ return nvmet_pr_release(req, reg, rtype);
+ case NVME_PR_RELEASE_ACT_CLEAR:
+ nvmet_pr_clear(req);
+ return NVME_SC_SUCCESS;
+ default:
+ req->error_loc = offsetof(struct nvme_common_command, cdw10);
+ return NVME_SC_INVALID_OPCODE | NVME_STATUS_DNR;
+ }
+}
+
+static void nvmet_execute_pr_release(struct nvmet_req *req)
+{
+ u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
+ bool ignore_key = nvmet_pr_parse_ignore_key(cdw10);
+ u8 rtype = (u8)((cdw10 >> 8) & 0xff); /* Reservation type, bit 15:08 */
+ u8 release_act = cdw10 & 0x07; /* Reservation release action, bit 02:00 */
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_release_data *d;
+ struct nvmet_pr_registrant *reg;
+ u16 status;
+
+ if (ignore_key) {
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+ goto out;
+ }
+
+ d = kmalloc(sizeof(*d), GFP_KERNEL);
+ if (!d) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+
+ status = nvmet_copy_from_sgl(req, 0, d, sizeof(*d));
+ if (status)
+ goto free_data;
+
+ status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ down(&pr->pr_sem);
+ list_for_each_entry_rcu(reg, &pr->registrant_list, entry) {
+ if (uuid_equal(&reg->hostid, &ctrl->hostid) &&
+ reg->rkey == le64_to_cpu(d->crkey)) {
+ status = __nvmet_execute_pr_release(req, reg,
+ release_act, rtype);
+ break;
+ }
+ }
+ up(&pr->pr_sem);
+free_data:
+ kfree(d);
+out:
+ nvmet_req_complete(req, status);
+}
+
+static void nvmet_execute_pr_report(struct nvmet_req *req)
+{
+ u32 cdw11 = le32_to_cpu(req->cmd->common.cdw11);
+ u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
+ u32 num_bytes = 4 * (cdw10 + 1); /* cdw10 is number of dwords */
+ u8 eds = cdw11 & 1; /* Extended data structure, bit 00 */
+ struct nvme_registered_ctrl_ext *ctrl_eds;
+ struct nvme_reservation_status_ext *data;
+ struct nvmet_pr *pr = &req->ns->pr;
+ struct nvmet_pr_registrant *holder;
+ struct nvmet_pr_registrant *reg;
+ u16 num_ctrls = 0;
+ u16 status;
+ u8 rtype;
+
+ /* nvmet hostid(uuid_t) is 128 bit. */
+ if (!eds) {
+ req->error_loc = offsetof(struct nvme_common_command, cdw11);
+ status = NVME_SC_HOST_ID_INCONSIST | NVME_STATUS_DNR;
+ goto out;
+ }
+
+ if (num_bytes < sizeof(struct nvme_reservation_status_ext)) {
+ req->error_loc = offsetof(struct nvme_common_command, cdw10);
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+ goto out;
+ }
+
+ data = kmalloc(num_bytes, GFP_KERNEL);
+ if (!data) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+ memset(data, 0, num_bytes);
+ data->gen = cpu_to_le32(atomic_read(&pr->generation));
+ data->ptpls = 0;
+ ctrl_eds = data->regctl_eds;
+
+ rcu_read_lock();
+ holder = rcu_dereference(pr->holder);
+ rtype = holder ? holder->rtype : 0;
+ data->rtype = rtype;
+
+ list_for_each_entry_rcu(reg, &pr->registrant_list, entry) {
+ num_ctrls++;
+ /*
+ * continue to get the number of all registrans.
+ */
+ if (((void *)ctrl_eds + sizeof(*ctrl_eds)) >
+ ((void *)data + num_bytes))
+ continue;
+ /*
+ * Dynamic controller, set cntlid to 0xffff.
+ */
+ ctrl_eds->cntlid = cpu_to_le16(NVME_CNTLID_DYNAMIC);
+ if (rtype == NVME_PR_WRITE_EXCLUSIVE_ALL_REGS ||
+ rtype == NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS)
+ ctrl_eds->rcsts = 1;
+ if (reg == holder)
+ ctrl_eds->rcsts = 1;
+ uuid_copy((uuid_t *)&ctrl_eds->hostid, &reg->hostid);
+ ctrl_eds->rkey = cpu_to_le64(reg->rkey);
+ ctrl_eds++;
+ }
+ rcu_read_unlock();
+
+ put_unaligned_le16(num_ctrls, data->regctl);
+ status = nvmet_copy_to_sgl(req, 0, data, num_bytes);
+ kfree(data);
+out:
+ nvmet_req_complete(req, status);
+}
+
+u16 nvmet_parse_pr_cmd(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+
+ switch (cmd->common.opcode) {
+ case nvme_cmd_resv_register:
+ req->execute = nvmet_execute_pr_register;
+ break;
+ case nvme_cmd_resv_acquire:
+ req->execute = nvmet_execute_pr_acquire;
+ break;
+ case nvme_cmd_resv_release:
+ req->execute = nvmet_execute_pr_release;
+ break;
+ case nvme_cmd_resv_report:
+ req->execute = nvmet_execute_pr_report;
+ break;
+ default:
+ return 1;
+ }
+ return NVME_SC_SUCCESS;
+}
+
+static bool nvmet_is_req_write_cmd_group(struct nvmet_req *req)
+{
+ u8 opcode = req->cmd->common.opcode;
+
+ if (req->sq->qid) {
+ switch (opcode) {
+ case nvme_cmd_flush:
+ case nvme_cmd_write:
+ case nvme_cmd_write_zeroes:
+ case nvme_cmd_dsm:
+ case nvme_cmd_zone_append:
+ case nvme_cmd_zone_mgmt_send:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+static bool nvmet_is_req_read_cmd_group(struct nvmet_req *req)
+{
+ u8 opcode = req->cmd->common.opcode;
+
+ if (req->sq->qid) {
+ switch (opcode) {
+ case nvme_cmd_read:
+ case nvme_cmd_zone_mgmt_recv:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+u16 nvmet_pr_check_cmd_access(struct nvmet_req *req)
+{
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ struct nvmet_pr_registrant *holder;
+ struct nvmet_ns *ns = req->ns;
+ struct nvmet_pr *pr = &ns->pr;
+ u16 status = NVME_SC_SUCCESS;
+
+ rcu_read_lock();
+ holder = rcu_dereference(pr->holder);
+ if (!holder)
+ goto unlock;
+ if (uuid_equal(&ctrl->hostid, &holder->hostid))
+ goto unlock;
+
+ /*
+ * The Reservation command group is checked in executing,
+ * allow it here.
+ */
+ switch (holder->rtype) {
+ case NVME_PR_WRITE_EXCLUSIVE:
+ if (nvmet_is_req_write_cmd_group(req))
+ status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ break;
+ case NVME_PR_EXCLUSIVE_ACCESS:
+ if (nvmet_is_req_read_cmd_group(req) ||
+ nvmet_is_req_write_cmd_group(req))
+ status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ break;
+ case NVME_PR_WRITE_EXCLUSIVE_REG_ONLY:
+ case NVME_PR_WRITE_EXCLUSIVE_ALL_REGS:
+ if ((nvmet_is_req_write_cmd_group(req)) &&
+ !nvmet_pr_find_registrant(pr, &ctrl->hostid))
+ status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ break;
+ case NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY:
+ case NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS:
+ if ((nvmet_is_req_read_cmd_group(req) ||
+ nvmet_is_req_write_cmd_group(req)) &&
+ !nvmet_pr_find_registrant(pr, &ctrl->hostid))
+ status = NVME_SC_RESERVATION_CONFLICT | NVME_STATUS_DNR;
+ break;
+ default:
+ pr_warn("the reservation type is set wrong, type:%d\n",
+ holder->rtype);
+ break;
+ }
+
+unlock:
+ rcu_read_unlock();
+ if (status)
+ req->error_loc = offsetof(struct nvme_common_command, opcode);
+ return status;
+}
+
+u16 nvmet_pr_get_ns_pc_ref(struct nvmet_req *req)
+{
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+
+ pc_ref = xa_load(&req->ns->pr_per_ctrl_refs,
+ req->sq->ctrl->cntlid);
+ if (unlikely(!percpu_ref_tryget_live(&pc_ref->ref)))
+ return NVME_SC_INTERNAL;
+ req->pc_ref = pc_ref;
+ return NVME_SC_SUCCESS;
+}
+
+static void nvmet_pr_ctrl_ns_all_cmds_done(struct percpu_ref *ref)
+{
+ struct nvmet_pr_per_ctrl_ref *pc_ref =
+ container_of(ref, struct nvmet_pr_per_ctrl_ref, ref);
+
+ complete(&pc_ref->free_done);
+}
+
+static int nvmet_pr_alloc_and_insert_pc_ref(struct nvmet_ns *ns,
+ unsigned long idx,
+ uuid_t *hostid)
+{
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+ int ret;
+
+ pc_ref = kmalloc(sizeof(*pc_ref), GFP_ATOMIC);
+ if (!pc_ref)
+ return -ENOMEM;
+
+ ret = percpu_ref_init(&pc_ref->ref, nvmet_pr_ctrl_ns_all_cmds_done,
+ PERCPU_REF_ALLOW_REINIT, GFP_KERNEL);
+ if (ret)
+ goto free;
+
+ init_completion(&pc_ref->free_done);
+ init_completion(&pc_ref->confirm_done);
+ uuid_copy(&pc_ref->hostid, hostid);
+
+ ret = xa_insert(&ns->pr_per_ctrl_refs, idx, pc_ref, GFP_KERNEL);
+ if (ret)
+ goto exit;
+ return ret;
+exit:
+ percpu_ref_exit(&pc_ref->ref);
+free:
+ kfree(pc_ref);
+ return ret;
+}
+
+int nvmet_ctrl_init_pr(struct nvmet_ctrl *ctrl)
+{
+ struct nvmet_subsys *subsys = ctrl->subsys;
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+ struct nvmet_ns *ns = NULL;
+ unsigned long idx;
+ int ret;
+
+ ctrl->pr_log_mgr.counter = 0;
+ ctrl->pr_log_mgr.lost_count = 0;
+ mutex_init(&ctrl->pr_log_mgr.lock);
+ INIT_KFIFO(ctrl->pr_log_mgr.log_queue);
+
+ /*
+ * Here we are under subsys lock, if an ns not in subsys->namespaces,
+ * we can make sure that ns is not enabled, and not call
+ * nvmet_pr_init_ns(), see more details in nvmet_ns_enable().
+ * So just check ns->pr.enable.
+ */
+ xa_for_each(&subsys->namespaces, idx, ns) {
+ if (ns->pr.enable) {
+ ret = nvmet_pr_alloc_and_insert_pc_ref(ns, ctrl->cntlid,
+ &ctrl->hostid);
+ if (ret)
+ goto free_per_ctrl_refs;
+ }
+ }
+ return 0;
+
+free_per_ctrl_refs:
+ xa_for_each(&subsys->namespaces, idx, ns) {
+ if (ns->pr.enable) {
+ pc_ref = xa_erase(&ns->pr_per_ctrl_refs, ctrl->cntlid);
+ if (pc_ref)
+ percpu_ref_exit(&pc_ref->ref);
+ kfree(pc_ref);
+ }
+ }
+ return ret;
+}
+
+void nvmet_ctrl_destroy_pr(struct nvmet_ctrl *ctrl)
+{
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+ struct nvmet_ns *ns;
+ unsigned long idx;
+
+ kfifo_free(&ctrl->pr_log_mgr.log_queue);
+ mutex_destroy(&ctrl->pr_log_mgr.lock);
+
+ xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ if (ns->pr.enable) {
+ pc_ref = xa_erase(&ns->pr_per_ctrl_refs, ctrl->cntlid);
+ if (pc_ref)
+ percpu_ref_exit(&pc_ref->ref);
+ kfree(pc_ref);
+ }
+ }
+}
+
+int nvmet_pr_init_ns(struct nvmet_ns *ns)
+{
+ struct nvmet_subsys *subsys = ns->subsys;
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+ struct nvmet_ctrl *ctrl = NULL;
+ unsigned long idx;
+ int ret;
+
+ ns->pr.holder = NULL;
+ atomic_set(&ns->pr.generation, 0);
+ sema_init(&ns->pr.pr_sem, 1);
+ INIT_LIST_HEAD(&ns->pr.registrant_list);
+ ns->pr.notify_mask = 0;
+
+ xa_init(&ns->pr_per_ctrl_refs);
+
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
+ ret = nvmet_pr_alloc_and_insert_pc_ref(ns, ctrl->cntlid,
+ &ctrl->hostid);
+ if (ret)
+ goto free_per_ctrl_refs;
+ }
+ return 0;
+
+free_per_ctrl_refs:
+ xa_for_each(&ns->pr_per_ctrl_refs, idx, pc_ref) {
+ xa_erase(&ns->pr_per_ctrl_refs, idx);
+ percpu_ref_exit(&pc_ref->ref);
+ kfree(pc_ref);
+ }
+ return ret;
+}
+
+void nvmet_pr_exit_ns(struct nvmet_ns *ns)
+{
+ struct nvmet_pr_registrant *reg, *tmp;
+ struct nvmet_pr_per_ctrl_ref *pc_ref;
+ struct nvmet_pr *pr = &ns->pr;
+ unsigned long idx;
+
+ list_for_each_entry_safe(reg, tmp, &pr->registrant_list, entry) {
+ list_del(&reg->entry);
+ kfree(reg);
+ }
+
+ xa_for_each(&ns->pr_per_ctrl_refs, idx, pc_ref) {
+ /*
+ * No command on ns here, we can safely free pc_ref.
+ */
+ pc_ref = xa_erase(&ns->pr_per_ctrl_refs, idx);
+ percpu_ref_exit(&pc_ref->ref);
+ kfree(pc_ref);
+ }
+
+ xa_destroy(&ns->pr_per_ctrl_refs);
+}
diff --git a/drivers/nvme/target/trace.c b/drivers/nvme/target/trace.c
index 9a3548179a8e..6dbc7036f2e4 100644
--- a/drivers/nvme/target/trace.c
+++ b/drivers/nvme/target/trace.c
@@ -180,6 +180,106 @@ static const char *nvmet_trace_zone_mgmt_recv(struct trace_seq *p, u8 *cdw10)
return ret;
}
+static const char *nvmet_trace_resv_reg(struct trace_seq *p, u8 *cdw10)
+{
+ static const char * const rrega_strs[] = {
+ [0x00] = "register",
+ [0x01] = "unregister",
+ [0x02] = "replace",
+ };
+ const char *ret = trace_seq_buffer_ptr(p);
+ u8 rrega = cdw10[0] & 0x7;
+ u8 iekey = (cdw10[0] >> 3) & 0x1;
+ u8 ptpl = (cdw10[3] >> 6) & 0x3;
+ const char *rrega_str;
+
+ if (rrega < ARRAY_SIZE(rrega_strs) && rrega_strs[rrega])
+ rrega_str = rrega_strs[rrega];
+ else
+ rrega_str = "reserved";
+
+ trace_seq_printf(p, "rrega=%u:%s, iekey=%u, ptpl=%u",
+ rrega, rrega_str, iekey, ptpl);
+ trace_seq_putc(p, 0);
+
+ return ret;
+}
+
+static const char * const rtype_strs[] = {
+ [0x00] = "reserved",
+ [0x01] = "write exclusive",
+ [0x02] = "exclusive access",
+ [0x03] = "write exclusive registrants only",
+ [0x04] = "exclusive access registrants only",
+ [0x05] = "write exclusive all registrants",
+ [0x06] = "exclusive access all registrants",
+};
+
+static const char *nvmet_trace_resv_acq(struct trace_seq *p, u8 *cdw10)
+{
+ static const char * const racqa_strs[] = {
+ [0x00] = "acquire",
+ [0x01] = "preempt",
+ [0x02] = "preempt and abort",
+ };
+ const char *ret = trace_seq_buffer_ptr(p);
+ u8 racqa = cdw10[0] & 0x7;
+ u8 iekey = (cdw10[0] >> 3) & 0x1;
+ u8 rtype = cdw10[1];
+ const char *racqa_str = "reserved";
+ const char *rtype_str = "reserved";
+
+ if (racqa < ARRAY_SIZE(racqa_strs) && racqa_strs[racqa])
+ racqa_str = racqa_strs[racqa];
+
+ if (rtype < ARRAY_SIZE(rtype_strs) && rtype_strs[rtype])
+ rtype_str = rtype_strs[rtype];
+
+ trace_seq_printf(p, "racqa=%u:%s, iekey=%u, rtype=%u:%s",
+ racqa, racqa_str, iekey, rtype, rtype_str);
+ trace_seq_putc(p, 0);
+
+ return ret;
+}
+
+static const char *nvmet_trace_resv_rel(struct trace_seq *p, u8 *cdw10)
+{
+ static const char * const rrela_strs[] = {
+ [0x00] = "release",
+ [0x01] = "clear",
+ };
+ const char *ret = trace_seq_buffer_ptr(p);
+ u8 rrela = cdw10[0] & 0x7;
+ u8 iekey = (cdw10[0] >> 3) & 0x1;
+ u8 rtype = cdw10[1];
+ const char *rrela_str = "reserved";
+ const char *rtype_str = "reserved";
+
+ if (rrela < ARRAY_SIZE(rrela_strs) && rrela_strs[rrela])
+ rrela_str = rrela_strs[rrela];
+
+ if (rtype < ARRAY_SIZE(rtype_strs) && rtype_strs[rtype])
+ rtype_str = rtype_strs[rtype];
+
+ trace_seq_printf(p, "rrela=%u:%s, iekey=%u, rtype=%u:%s",
+ rrela, rrela_str, iekey, rtype, rtype_str);
+ trace_seq_putc(p, 0);
+
+ return ret;
+}
+
+static const char *nvmet_trace_resv_report(struct trace_seq *p, u8 *cdw10)
+{
+ const char *ret = trace_seq_buffer_ptr(p);
+ u32 numd = get_unaligned_le32(cdw10);
+ u8 eds = cdw10[4] & 0x1;
+
+ trace_seq_printf(p, "numd=%u, eds=%u", numd, eds);
+ trace_seq_putc(p, 0);
+
+ return ret;
+}
+
const char *nvmet_trace_parse_nvm_cmd(struct trace_seq *p,
u8 opcode, u8 *cdw10)
{
@@ -195,6 +295,14 @@ const char *nvmet_trace_parse_nvm_cmd(struct trace_seq *p,
return nvmet_trace_zone_mgmt_send(p, cdw10);
case nvme_cmd_zone_mgmt_recv:
return nvmet_trace_zone_mgmt_recv(p, cdw10);
+ case nvme_cmd_resv_register:
+ return nvmet_trace_resv_reg(p, cdw10);
+ case nvme_cmd_resv_acquire:
+ return nvmet_trace_resv_acq(p, cdw10);
+ case nvme_cmd_resv_release:
+ return nvmet_trace_resv_rel(p, cdw10);
+ case nvme_cmd_resv_report:
+ return nvmet_trace_resv_report(p, cdw10);
default:
return nvmet_trace_common(p, cdw10);
}
diff --git a/drivers/nvme/target/zns.c b/drivers/nvme/target/zns.c
index af9e13be7678..3aef35b05111 100644
--- a/drivers/nvme/target/zns.c
+++ b/drivers/nvme/target/zns.c
@@ -537,6 +537,7 @@ void nvmet_bdev_execute_zone_append(struct nvmet_req *req)
u16 status = NVME_SC_SUCCESS;
unsigned int total_len = 0;
struct scatterlist *sg;
+ u32 data_len = nvmet_rw_data_len(req);
struct bio *bio;
int sg_cnt;
@@ -544,6 +545,13 @@ void nvmet_bdev_execute_zone_append(struct nvmet_req *req)
if (!nvmet_check_transfer_len(req, nvmet_rw_data_len(req)))
return;
+ if (data_len >
+ bdev_max_zone_append_sectors(req->ns->bdev) << SECTOR_SHIFT) {
+ req->error_loc = offsetof(struct nvme_rw_command, length);
+ status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
+ goto out;
+ }
+
if (!req->sg_cnt) {
nvmet_req_complete(req, 0);
return;
@@ -576,20 +584,17 @@ void nvmet_bdev_execute_zone_append(struct nvmet_req *req)
bio->bi_opf |= REQ_FUA;
for_each_sg(req->sg, sg, req->sg_cnt, sg_cnt) {
- struct page *p = sg_page(sg);
- unsigned int l = sg->length;
- unsigned int o = sg->offset;
- unsigned int ret;
+ unsigned int len = sg->length;
- ret = bio_add_zone_append_page(bio, p, l, o);
- if (ret != sg->length) {
+ if (bio_add_pc_page(bdev_get_queue(bio->bi_bdev), bio,
+ sg_page(sg), len, sg->offset) != len) {
status = NVME_SC_INTERNAL;
goto out_put_bio;
}
- total_len += sg->length;
+ total_len += len;
}
- if (total_len != nvmet_rw_data_len(req)) {
+ if (total_len != data_len) {
status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
goto out_put_bio;
}
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index d2c384f58028..8671b7c974b9 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -246,6 +246,17 @@ config NVMEM_RAVE_SP_EEPROM
help
Say y here to enable Rave SP EEPROM support.
+config NVMEM_RCAR_EFUSE
+ tristate "Renesas R-Car Gen4 E-FUSE support"
+ depends on (ARCH_RENESAS && ARM64) || COMPILE_TEST
+ depends on NVMEM
+ help
+ Enable support for reading the fuses in the E-FUSE or OTP
+ non-volatile memory block on Renesas R-Car Gen4 SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-rcar-efuse.
+
config NVMEM_RMEM
tristate "Reserved Memory Based Driver Support"
depends on HAS_IOMEM
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index cdd01fbf1313..5b77bbb6488b 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -52,6 +52,8 @@ obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o
nvmem_sec_qfprom-y := sec-qfprom.o
obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
+obj-$(CONFIG_NVMEM_RCAR_EFUSE) += nvmem-rcar-efuse.o
+nvmem-rcar-efuse-y := rcar-efuse.o
obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
nvmem-rmem-y := rmem.o
obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c
index 3d8c87835f4d..b810df727b44 100644
--- a/drivers/nvmem/brcm_nvram.c
+++ b/drivers/nvmem/brcm_nvram.c
@@ -22,7 +22,7 @@
*
* @dev: NVMEM device pointer
* @nvmem_size: Size of the whole space available for NVRAM
- * @data: NVRAM data copy stored to avoid poking underlaying flash controller
+ * @data: NVRAM data copy stored to avoid poking underlying flash controller
* @data_len: NVRAM data size
* @padding_byte: Padding value used to fill remaining space
* @cells: Array of discovered NVMEM cells
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 33ffa2aa4c11..d6494dfc20a7 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -267,7 +267,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size);
- if (!nvmem->reg_write)
+ if (!nvmem->reg_write || nvmem->read_only)
return -EPERM;
rc = nvmem_reg_write(nvmem, pos, buf, count);
@@ -298,16 +298,25 @@ static umode_t nvmem_bin_attr_get_umode(struct nvmem_device *nvmem)
}
static umode_t nvmem_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr,
+ int i)
{
struct device *dev = kobj_to_dev(kobj);
struct nvmem_device *nvmem = to_nvmem_device(dev);
- attr->size = nvmem->size;
-
return nvmem_bin_attr_get_umode(nvmem);
}
+static size_t nvmem_bin_attr_size(struct kobject *kobj,
+ const struct bin_attribute *attr,
+ int i)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+ return nvmem->size;
+}
+
static umode_t nvmem_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
@@ -383,6 +392,7 @@ static const struct attribute_group nvmem_bin_group = {
.bin_attrs = nvmem_bin_attributes,
.attrs = nvmem_attrs,
.is_bin_visible = nvmem_bin_attr_is_visible,
+ .bin_size = nvmem_bin_attr_size,
.is_visible = nvmem_attr_is_visible,
};
@@ -1247,7 +1257,7 @@ static void devm_nvmem_device_release(struct device *dev, void *res)
}
/**
- * devm_nvmem_device_put() - put alredy got nvmem device
+ * devm_nvmem_device_put() - put already got nvmem device
*
* @dev: Device that uses the nvmem device.
* @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
@@ -1265,7 +1275,7 @@ void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
/**
- * nvmem_device_put() - put alredy got nvmem device
+ * nvmem_device_put() - put already got nvmem device
*
* @nvmem: pointer to nvmem device that needs to be released.
*/
diff --git a/drivers/nvmem/imx-iim.c b/drivers/nvmem/imx-iim.c
index f13bbd164086..8cfbe55a56cb 100644
--- a/drivers/nvmem/imx-iim.c
+++ b/drivers/nvmem/imx-iim.c
@@ -115,11 +115,11 @@ static int imx_iim_probe(struct platform_device *pdev)
if (IS_ERR(iim->clk))
return PTR_ERR(iim->clk);
- cfg.name = "imx-iim",
- cfg.read_only = true,
- cfg.word_size = 1,
- cfg.stride = 1,
- cfg.reg_read = imx_iim_read,
+ cfg.name = "imx-iim";
+ cfg.read_only = true;
+ cfg.word_size = 1;
+ cfg.stride = 1;
+ cfg.reg_read = imx_iim_read;
cfg.dev = dev;
cfg.size = drvdata->nregs;
cfg.priv = iim;
diff --git a/drivers/nvmem/lpc18xx_otp.c b/drivers/nvmem/lpc18xx_otp.c
index adc9948e7b2e..c41a0c58bec7 100644
--- a/drivers/nvmem/lpc18xx_otp.c
+++ b/drivers/nvmem/lpc18xx_otp.c
@@ -21,7 +21,7 @@
* LPC18xx OTP memory contains 4 banks with 4 32-bit words. Bank 0 starts
* at offset 0 from the base.
*
- * Bank 0 contains the part ID for Flashless devices and is reseverd for
+ * Bank 0 contains the part ID for Flashless devices and is reserved for
* devices with Flash.
* Bank 1/2 is generale purpose or AES key storage for secure devices.
* Bank 3 contains control data, USB ID and generale purpose words.
diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c
index 7cf81738a3e0..df979e8549fd 100644
--- a/drivers/nvmem/microchip-otpc.c
+++ b/drivers/nvmem/microchip-otpc.c
@@ -156,7 +156,7 @@ static int mchp_otpc_read(void *priv, unsigned int off, void *val,
/*
* We reach this point with off being multiple of stride = 4 to
* be able to cross the subsystem. Inside the driver we use continuous
- * unsigned integer numbers for packet id, thus devide off by 4
+ * unsigned integer numbers for packet id, thus divide off by 4
* before passing it to mchp_otpc_id_to_packet().
*/
packet = mchp_otpc_id_to_packet(otpc, off / 4);
diff --git a/drivers/nvmem/rcar-efuse.c b/drivers/nvmem/rcar-efuse.c
new file mode 100644
index 000000000000..f24bdb9cb5a7
--- /dev/null
+++ b/drivers/nvmem/rcar-efuse.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Renesas R-Car E-FUSE/OTP Driver
+ *
+ * Copyright (C) 2024 Glider bv
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+
+struct rcar_fuse {
+ struct nvmem_keepout keepouts[2];
+ struct nvmem_device *nvmem;
+ struct device *dev;
+ void __iomem *base;
+};
+
+struct rcar_fuse_data {
+ unsigned int bank; /* 0: PFC + E-FUSE, 1: OPT_MEM + E-FUSE */
+ unsigned int start; /* inclusive */
+ unsigned int end; /* exclusive */
+};
+
+static int rcar_fuse_reg_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct rcar_fuse *fuse = priv;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(fuse->dev);
+ if (ret < 0)
+ return ret;
+
+ __ioread32_copy(val, fuse->base + offset, bytes / 4);
+
+ pm_runtime_put(fuse->dev);
+
+ return 0;
+}
+
+static int rcar_fuse_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct rcar_fuse_data *data = device_get_match_data(dev);
+ struct nvmem_config config = {
+ .dev = dev,
+ .name = "rcar-fuse",
+ .id = NVMEM_DEVID_NONE,
+ .owner = THIS_MODULE,
+ .type = NVMEM_TYPE_OTP,
+ .read_only = true,
+ .root_only = true,
+ .reg_read = rcar_fuse_reg_read,
+ .word_size = 4,
+ .stride = 4,
+ };
+ struct rcar_fuse *fuse;
+ struct resource *res;
+ int ret;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret < 0)
+ return ret;
+
+ fuse = devm_kzalloc(dev, sizeof(*fuse), GFP_KERNEL);
+ if (!fuse)
+ return -ENOMEM;
+
+ fuse->base = devm_platform_get_and_ioremap_resource(pdev, data->bank,
+ &res);
+ if (IS_ERR(fuse->base))
+ return PTR_ERR(fuse->base);
+
+ fuse->dev = dev;
+ fuse->keepouts[0].start = 0;
+ fuse->keepouts[0].end = data->start;
+ fuse->keepouts[1].start = data->end;
+ fuse->keepouts[1].end = resource_size(res);
+
+ config.keepout = fuse->keepouts;
+ config.nkeepout = ARRAY_SIZE(fuse->keepouts);
+ config.size = resource_size(res);
+ config.priv = fuse;
+
+ fuse->nvmem = devm_nvmem_register(dev, &config);
+ if (IS_ERR(fuse->nvmem))
+ return dev_err_probe(dev, PTR_ERR(fuse->nvmem),
+ "Failed to register NVMEM device\n");
+
+ return 0;
+}
+
+static const struct rcar_fuse_data rcar_fuse_v3u = {
+ .bank = 0,
+ .start = 0x0c0,
+ .end = 0x0e8,
+};
+
+static const struct rcar_fuse_data rcar_fuse_s4 = {
+ .bank = 0,
+ .start = 0x0c0,
+ .end = 0x14c,
+};
+
+static const struct rcar_fuse_data rcar_fuse_v4h = {
+ .bank = 1,
+ .start = 0x100,
+ .end = 0x1a0,
+};
+
+static const struct rcar_fuse_data rcar_fuse_v4m = {
+ .bank = 1,
+ .start = 0x100,
+ .end = 0x110,
+};
+
+static const struct of_device_id rcar_fuse_match[] = {
+ { .compatible = "renesas,r8a779a0-efuse", .data = &rcar_fuse_v3u },
+ { .compatible = "renesas,r8a779f0-efuse", .data = &rcar_fuse_s4 },
+ { .compatible = "renesas,r8a779g0-otp", .data = &rcar_fuse_v4h },
+ { .compatible = "renesas,r8a779h0-otp", .data = &rcar_fuse_v4m },
+ { /* sentinel */ }
+};
+
+static struct platform_driver rcar_fuse_driver = {
+ .probe = rcar_fuse_probe,
+ .driver = {
+ .name = "rcar_fuse",
+ .of_match_table = rcar_fuse_match,
+ },
+};
+module_platform_driver(rcar_fuse_driver);
+
+MODULE_DESCRIPTION("Renesas R-Car E-FUSE/OTP driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Geert Uytterhoeven");
diff --git a/drivers/of/.kunitconfig b/drivers/of/.kunitconfig
index 4c53d2c7a275..7d570cb922a1 100644
--- a/drivers/of/.kunitconfig
+++ b/drivers/of/.kunitconfig
@@ -1,4 +1,5 @@
CONFIG_KUNIT=y
CONFIG_OF=y
CONFIG_OF_KUNIT_TEST=y
+CONFIG_OF_OVERLAY=y
CONFIG_OF_OVERLAY_KUNIT_TEST=y
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 0e2d608c3e20..50697cc3b07e 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -2,6 +2,12 @@
config DTC
bool
+config GENERIC_BUILTIN_DTB
+ bool
+
+config BUILTIN_DTB_ALL
+ bool
+
menuconfig OF
bool "Device Tree and Open Firmware support"
help
@@ -111,7 +117,7 @@ config OF_OVERLAY_KUNIT_TEST
tristate "Device Tree overlay KUnit tests" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
- select OF_OVERLAY
+ select DTC
help
This option builds KUnit unit tests for the device tree overlay code.
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 286f0c161e33..c5b925ac469f 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -147,7 +147,7 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr)
* PCI bus specific translator
*/
-static bool of_node_is_pcie(struct device_node *np)
+static bool of_node_is_pcie(const struct device_node *np)
{
bool is_pcie = of_node_name_eq(np, "pcie");
@@ -230,8 +230,8 @@ static int __of_address_resource_bounds(struct resource *r, u64 start, u64 size)
* To guard against that we try to register the IO range first.
* If that fails we know that pci_address_to_pio() will do too.
*/
-int of_pci_range_to_resource(struct of_pci_range *range,
- struct device_node *np, struct resource *res)
+int of_pci_range_to_resource(const struct of_pci_range *range,
+ const struct device_node *np, struct resource *res)
{
u64 start;
int err;
@@ -333,14 +333,18 @@ static unsigned int of_bus_isa_get_flags(const __be32 *addr)
static int of_bus_default_flags_match(struct device_node *np)
{
- return of_bus_n_addr_cells(np) == 3;
+ /*
+ * Check for presence first since of_bus_n_addr_cells() will warn when
+ * walking parent nodes.
+ */
+ return of_property_present(np, "#address-cells") && (of_bus_n_addr_cells(np) == 3);
}
/*
* Array of bus specific translators
*/
-static struct of_bus of_busses[] = {
+static const struct of_bus of_busses[] = {
#ifdef CONFIG_PCI
/* PCI */
{
@@ -388,7 +392,7 @@ static struct of_bus of_busses[] = {
},
};
-static struct of_bus *of_match_bus(struct device_node *np)
+static const struct of_bus *of_match_bus(struct device_node *np)
{
int i;
@@ -399,7 +403,7 @@ static struct of_bus *of_match_bus(struct device_node *np)
return NULL;
}
-static int of_empty_ranges_quirk(struct device_node *np)
+static int of_empty_ranges_quirk(const struct device_node *np)
{
if (IS_ENABLED(CONFIG_PPC)) {
/* To save cycles, we cache the result for global "Mac" setting */
@@ -419,8 +423,8 @@ static int of_empty_ranges_quirk(struct device_node *np)
return false;
}
-static int of_translate_one(struct device_node *parent, struct of_bus *bus,
- struct of_bus *pbus, __be32 *addr,
+static int of_translate_one(const struct device_node *parent, const struct of_bus *bus,
+ const struct of_bus *pbus, __be32 *addr,
int na, int ns, int pna, const char *rprop)
{
const __be32 *ranges;
@@ -505,7 +509,7 @@ static u64 __of_translate_address(struct device_node *node,
{
struct device_node *dev __free(device_node) = of_node_get(node);
struct device_node *parent __free(device_node) = get_parent(dev);
- struct of_bus *bus, *pbus;
+ const struct of_bus *bus, *pbus;
__be32 addr[OF_MAX_ADDR_CELLS];
int na, ns, pna, pns;
@@ -690,7 +694,7 @@ const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no,
const __be32 *prop;
unsigned int psize;
struct device_node *parent __free(device_node) = of_get_parent(dev);
- struct of_bus *bus;
+ const struct of_bus *bus;
int onesize, i, na, ns;
if (parent == NULL)
@@ -701,16 +705,16 @@ const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no,
if (strcmp(bus->name, "pci") && (bar_no >= 0))
return NULL;
- bus->count_cells(dev, &na, &ns);
- if (!OF_CHECK_ADDR_COUNT(na))
- return NULL;
-
/* Get "reg" or "assigned-addresses" property */
prop = of_get_property(dev, bus->addresses, &psize);
if (prop == NULL)
return NULL;
psize /= 4;
+ bus->count_cells(dev, &na, &ns);
+ if (!OF_CHECK_ADDR_COUNT(na))
+ return NULL;
+
onesize = na + ns;
for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) {
u32 val = be32_to_cpu(prop[0]);
@@ -1030,7 +1034,7 @@ EXPORT_SYMBOL_GPL(of_dma_is_coherent);
* This is currently only enabled on builds that support Apple ARM devices, as
* an optimization.
*/
-static bool of_mmio_is_nonposted(struct device_node *np)
+static bool of_mmio_is_nonposted(const struct device_node *np)
{
if (!IS_ENABLED(CONFIG_ARCH_APPLE))
return false;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 20603d3c9931..7dc394255a0a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -87,15 +87,25 @@ static bool __of_node_is_type(const struct device_node *np, const char *type)
return np && match && type && !strcmp(match, type);
}
+#define EXCLUDED_DEFAULT_CELLS_PLATFORMS ( \
+ IS_ENABLED(CONFIG_SPARC) \
+)
+
int of_bus_n_addr_cells(struct device_node *np)
{
u32 cells;
- for (; np; np = np->parent)
+ for (; np; np = np->parent) {
if (!of_property_read_u32(np, "#address-cells", &cells))
return cells;
-
- /* No #address-cells property for the root node */
+ /*
+ * Default root value and walking parent nodes for "#address-cells"
+ * is deprecated. Any platforms which hit this warning should
+ * be added to the excluded list.
+ */
+ WARN_ONCE(!EXCLUDED_DEFAULT_CELLS_PLATFORMS,
+ "Missing '#address-cells' in %pOF\n", np);
+ }
return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
}
@@ -112,11 +122,17 @@ int of_bus_n_size_cells(struct device_node *np)
{
u32 cells;
- for (; np; np = np->parent)
+ for (; np; np = np->parent) {
if (!of_property_read_u32(np, "#size-cells", &cells))
return cells;
-
- /* No #size-cells property for the root node */
+ /*
+ * Default root value and walking parent nodes for "#size-cells"
+ * is deprecated. Any platforms which hit this warning should
+ * be added to the excluded list.
+ */
+ WARN_ONCE(!EXCLUDED_DEFAULT_CELLS_PLATFORMS,
+ "Missing '#size-cells' in %pOF\n", np);
+ }
return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
}
@@ -270,7 +286,7 @@ EXPORT_SYMBOL(of_find_all_nodes);
const void *__of_get_property(const struct device_node *np,
const char *name, int *lenp)
{
- struct property *pp = __of_find_property(np, name, lenp);
+ const struct property *pp = __of_find_property(np, name, lenp);
return pp ? pp->value : NULL;
}
@@ -282,7 +298,7 @@ const void *__of_get_property(const struct device_node *np,
const void *of_get_property(const struct device_node *np, const char *name,
int *lenp)
{
- struct property *pp = of_find_property(np, name, lenp);
+ const struct property *pp = of_find_property(np, name, lenp);
return pp ? pp->value : NULL;
}
@@ -321,7 +337,7 @@ EXPORT_SYMBOL(of_get_property);
static int __of_device_is_compatible(const struct device_node *device,
const char *compat, const char *type, const char *name)
{
- struct property *prop;
+ const struct property *prop;
const char *cp;
int index = 0, score = 0;
@@ -628,6 +644,42 @@ struct device_node *of_get_next_child(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_next_child);
+/**
+ * of_get_next_child_with_prefix - Find the next child node with prefix
+ * @node: parent node
+ * @prev: previous child of the parent node, or NULL to get first
+ * @prefix: prefix that the node name should have
+ *
+ * This function is like of_get_next_child(), except that it automatically
+ * skips any nodes whose name doesn't have the given prefix.
+ *
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_get_next_child_with_prefix(const struct device_node *node,
+ struct device_node *prev,
+ const char *prefix)
+{
+ struct device_node *next;
+ unsigned long flags;
+
+ if (!node)
+ return NULL;
+
+ raw_spin_lock_irqsave(&devtree_lock, flags);
+ next = prev ? prev->sibling : node->child;
+ for (; next; next = next->sibling) {
+ if (!of_node_name_prefix(next, prefix))
+ continue;
+ if (of_node_get(next))
+ break;
+ }
+ of_node_put(prev);
+ raw_spin_unlock_irqrestore(&devtree_lock, flags);
+ return next;
+}
+EXPORT_SYMBOL(of_get_next_child_with_prefix);
+
static struct device_node *of_get_next_status_child(const struct device_node *node,
struct device_node *prev,
bool (*checker)(const struct device_node *))
@@ -771,7 +823,7 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_child_by_name);
-struct device_node *__of_find_node_by_path(struct device_node *parent,
+struct device_node *__of_find_node_by_path(const struct device_node *parent,
const char *path)
{
struct device_node *child;
@@ -828,7 +880,7 @@ struct device_node *__of_find_node_by_full_path(struct device_node *node,
struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
{
struct device_node *np = NULL;
- struct property *pp;
+ const struct property *pp;
unsigned long flags;
const char *separator = strchr(path, ':');
@@ -974,7 +1026,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
const char *prop_name)
{
struct device_node *np;
- struct property *pp;
+ const struct property *pp;
unsigned long flags;
raw_spin_lock_irqsave(&devtree_lock, flags);
@@ -1769,7 +1821,7 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np,
*/
void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
{
- struct property *pp;
+ const struct property *pp;
of_aliases = of_find_node_by_path("/aliases");
of_chosen = of_find_node_by_path("/chosen");
@@ -1840,7 +1892,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
*
* Return: The alias id if found.
*/
-int of_alias_get_id(struct device_node *np, const char *stem)
+int of_alias_get_id(const struct device_node *np, const char *stem)
{
struct alias_prop *app;
int id = -ENODEV;
@@ -1898,7 +1950,7 @@ EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
*
* Return: TRUE if console successfully setup. Otherwise return FALSE.
*/
-bool of_console_check(struct device_node *dn, char *name, int index)
+bool of_console_check(const struct device_node *dn, char *name, int index)
{
if (!dn || dn != of_stdout || console_set_on_cmdline)
return false;
@@ -1986,7 +2038,7 @@ int of_find_last_cache_level(unsigned int cpu)
*
* Return: 0 on success or a standard error code on failure.
*/
-int of_map_id(struct device_node *np, u32 id,
+int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
struct device_node **target, u32 *id_out)
{
diff --git a/drivers/of/cpu.c b/drivers/of/cpu.c
index d17b2f851082..5214dc3d05ae 100644
--- a/drivers/of/cpu.c
+++ b/drivers/of/cpu.c
@@ -188,7 +188,7 @@ EXPORT_SYMBOL(of_cpu_node_to_id);
* Return: An idle state node if found at @index. The refcount is incremented
* for it, so call of_node_put() on it when done. Returns NULL if not found.
*/
-struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+struct device_node *of_get_cpu_state_node(const struct device_node *cpu_node,
int index)
{
struct of_phandle_args args;
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 110104a936d9..0aba760f7577 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -536,7 +536,7 @@ static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
kfree(ce);
}
-static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
+static void __of_changeset_entry_invert(const struct of_changeset_entry *ce,
struct of_changeset_entry *rce)
{
memcpy(rce, ce, sizeof(*rce));
@@ -636,7 +636,7 @@ static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
return 0;
}
-static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
+static inline int __of_changeset_entry_revert(const struct of_changeset_entry *ce)
{
struct of_changeset_entry ce_inverted;
@@ -1072,3 +1072,47 @@ int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,
return of_changeset_add_prop_helper(ocs, np, &prop);
}
EXPORT_SYMBOL_GPL(of_changeset_add_prop_bool);
+
+static int of_changeset_update_prop_helper(struct of_changeset *ocs,
+ struct device_node *np,
+ const struct property *pp)
+{
+ struct property *new_pp;
+ int ret;
+
+ new_pp = __of_prop_dup(pp, GFP_KERNEL);
+ if (!new_pp)
+ return -ENOMEM;
+
+ ret = of_changeset_update_property(ocs, np, new_pp);
+ if (ret)
+ __of_prop_free(new_pp);
+
+ return ret;
+}
+
+/**
+ * of_changeset_update_prop_string - Add a string property update to a changeset
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @prop_name: name of the property to be updated
+ * @str: pointer to null terminated string
+ *
+ * Create a string property to be updated and add it to a changeset.
+ *
+ * Return: 0 on success, a negative error value in case of an error.
+ */
+int of_changeset_update_prop_string(struct of_changeset *ocs,
+ struct device_node *np,
+ const char *prop_name, const char *str)
+{
+ struct property prop = {
+ .name = (char *)prop_name,
+ .length = strlen(str) + 1,
+ .value = (void *)str,
+ };
+
+ return of_changeset_update_prop_helper(ocs, np, &prop);
+}
+EXPORT_SYMBOL_GPL(of_changeset_update_prop_string);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 4d528c10df3a..0121100372b4 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -457,6 +457,7 @@ int __initdata dt_root_addr_cells;
int __initdata dt_root_size_cells;
void *initial_boot_params __ro_after_init;
+phys_addr_t initial_boot_params_pa __ro_after_init;
#ifdef CONFIG_OF_EARLY_FLATTREE
@@ -511,8 +512,6 @@ void __init early_init_fdt_scan_reserved_mem(void)
break;
memblock_reserve(base, size);
}
-
- fdt_init_reserved_mem();
}
/**
@@ -938,12 +937,12 @@ int __init early_init_dt_scan_root(void)
dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
- if (prop)
+ if (!WARN(!prop, "No '#size-cells' in root node\n"))
dt_root_size_cells = be32_to_cpup(prop);
pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
- if (prop)
+ if (!WARN(!prop, "No '#address-cells' in root node\n"))
dt_root_addr_cells = be32_to_cpup(prop);
pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
@@ -1136,17 +1135,18 @@ static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
return ptr;
}
-bool __init early_init_dt_verify(void *params)
+bool __init early_init_dt_verify(void *dt_virt, phys_addr_t dt_phys)
{
- if (!params)
+ if (!dt_virt)
return false;
/* check device tree validity */
- if (fdt_check_header(params))
+ if (fdt_check_header(dt_virt))
return false;
/* Setup flat device-tree pointer */
- initial_boot_params = params;
+ initial_boot_params = dt_virt;
+ initial_boot_params_pa = dt_phys;
of_fdt_crc32 = crc32_be(~0, initial_boot_params,
fdt_totalsize(initial_boot_params));
@@ -1173,11 +1173,11 @@ void __init early_init_dt_scan_nodes(void)
early_init_dt_check_for_usable_mem_range();
}
-bool __init early_init_dt_scan(void *params)
+bool __init early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys)
{
bool status;
- status = early_init_dt_verify(params);
+ status = early_init_dt_verify(dt_virt, dt_phys);
if (!status)
return false;
@@ -1212,6 +1212,9 @@ void __init unflatten_device_tree(void)
{
void *fdt = initial_boot_params;
+ /* Save the statically-placed regions in the reserved_mem array */
+ fdt_scan_reserved_mem_reg_nodes();
+
/* Don't use the bootloader provided DTB if ACPI is enabled */
if (!acpi_disabled)
fdt = NULL;
diff --git a/drivers/of/fdt_address.c b/drivers/of/fdt_address.c
index 1dc15ab78b10..9804d7f06705 100644
--- a/drivers/of/fdt_address.c
+++ b/drivers/of/fdt_address.c
@@ -55,7 +55,7 @@ static void __init fdt_bus_default_count_cells(const void *blob, int parentoffse
if (prop)
*addrc = be32_to_cpup(prop);
else
- *addrc = dt_root_addr_cells;
+ *addrc = -1;
}
if (sizec) {
@@ -63,7 +63,7 @@ static void __init fdt_bus_default_count_cells(const void *blob, int parentoffse
if (prop)
*sizec = be32_to_cpup(prop);
else
- *sizec = dt_root_size_cells;
+ *sizec = -1;
}
}
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index a494f56a0d0e..67fc0ceaa5f5 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -720,7 +720,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id,
* Returns: the MSI domain for this device (or NULL on failure).
*/
struct irq_domain *of_msi_get_domain(struct device *dev,
- struct device_node *np,
+ const struct device_node *np,
enum irq_domain_bus_token token)
{
struct of_phandle_iterator it;
@@ -742,7 +742,7 @@ EXPORT_SYMBOL_GPL(of_msi_get_domain);
* @dev: device structure to associate with an MSI irq domain
* @np: device node for that device
*/
-void of_msi_configure(struct device *dev, struct device_node *np)
+void of_msi_configure(struct device *dev, const struct device_node *np)
{
dev_set_msi_domain(dev,
of_msi_get_domain(dev, np, DOMAIN_BUS_PLATFORM_MSI));
diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c
index 9ccde2fd77cb..5b924597a4de 100644
--- a/drivers/of/kexec.c
+++ b/drivers/of/kexec.c
@@ -301,7 +301,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
}
/* Remove memory reservation for the current device tree. */
- ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params),
+ ret = fdt_find_and_del_mem_rsv(fdt, initial_boot_params_pa,
fdt_totalsize(initial_boot_params));
if (ret == -EINVAL) {
pr_err("Error removing memory reservation.\n");
diff --git a/drivers/of/kobj.c b/drivers/of/kobj.c
index 3dbce1e6f184..cab9b169dc67 100644
--- a/drivers/of/kobj.c
+++ b/drivers/of/kobj.c
@@ -37,7 +37,7 @@ static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj,
}
/* always return newly allocated name, caller must free after use */
-static const char *safe_name(struct kobject *kobj, const char *orig_name)
+static const char *safe_name(const struct kobject *kobj, const char *orig_name)
{
const char *name = orig_name;
struct kernfs_node *kn;
@@ -84,7 +84,7 @@ int __of_add_property_sysfs(struct device_node *np, struct property *pp)
return rc;
}
-void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop)
+void __of_sysfs_remove_bin_file(struct device_node *np, const struct property *prop)
{
if (!IS_ENABLED(CONFIG_SYSFS))
return;
@@ -93,7 +93,7 @@ void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop)
kfree(prop->attr.attr.name);
}
-void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
+void __of_remove_property_sysfs(struct device_node *np, const struct property *prop)
{
/* at early boot, bail here and defer setup to of_init() */
if (of_kset && of_node_is_attached(np))
@@ -101,7 +101,7 @@ void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
}
void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
- struct property *oldprop)
+ const struct property *oldprop)
{
/* At early boot, bail out and defer setup to of_init() */
if (!of_kset)
diff --git a/drivers/of/module.c b/drivers/of/module.c
index 780fd82a7ecc..1e735fc130ad 100644
--- a/drivers/of/module.c
+++ b/drivers/of/module.c
@@ -35,12 +35,10 @@ ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
str += csize;
of_property_for_each_string(np, "compatible", p, compat) {
- csize = strlen(compat) + 1;
+ csize = snprintf(str, len, "C%s", compat);
tsize += csize;
if (csize >= len)
continue;
-
- csize = snprintf(str, len, "C%s", compat);
for (c = str; c; ) {
c = strchr(c, ' ');
if (c)
diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index 2ec20886d176..230d5f628c1b 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -14,9 +14,6 @@
#include <asm/numa.h>
-/* define default numa node to 0 */
-#define DEFAULT_NODE 0
-
/*
* Even though we connect cpus to numa domains later in SMP
* init, we need to know the node ids now for all cpus.
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index c235d6c909a1..ea5a0951ec5e 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -9,6 +9,7 @@
*/
#define FDT_ALIGN_SIZE 8
+#define MAX_RESERVED_REGIONS 64
/**
* struct alias_prop - Alias property in 'aliases' node
@@ -72,9 +73,9 @@ static inline void of_platform_register_reconfig_notifier(void) { }
#if defined(CONFIG_OF_KOBJ)
int of_node_is_attached(const struct device_node *node);
int __of_add_property_sysfs(struct device_node *np, struct property *pp);
-void __of_remove_property_sysfs(struct device_node *np, struct property *prop);
+void __of_remove_property_sysfs(struct device_node *np, const struct property *prop);
void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
- struct property *oldprop);
+ const struct property *oldprop);
int __of_attach_node_sysfs(struct device_node *np);
void __of_detach_node_sysfs(struct device_node *np);
#else
@@ -82,9 +83,9 @@ static inline int __of_add_property_sysfs(struct device_node *np, struct propert
{
return 0;
}
-static inline void __of_remove_property_sysfs(struct device_node *np, struct property *prop) {}
+static inline void __of_remove_property_sysfs(struct device_node *np, const struct property *prop) {}
static inline void __of_update_property_sysfs(struct device_node *np,
- struct property *newprop, struct property *oldprop) {}
+ struct property *newprop, const struct property *oldprop) {}
static inline int __of_attach_node_sysfs(struct device_node *np)
{
return 0;
@@ -130,7 +131,7 @@ void __of_prop_free(struct property *prop);
struct device_node *__of_node_dup(const struct device_node *np,
const char *full_name);
-struct device_node *__of_find_node_by_path(struct device_node *parent,
+struct device_node *__of_find_node_by_path(const struct device_node *parent,
const char *path);
struct device_node *__of_find_node_by_full_path(struct device_node *node,
const char *path);
@@ -145,7 +146,7 @@ extern int __of_update_property(struct device_node *np,
extern void __of_detach_node(struct device_node *np);
extern void __of_sysfs_remove_bin_file(struct device_node *np,
- struct property *prop);
+ const struct property *prop);
/* illegal phandle value (set when unresolved) */
#define OF_PHANDLE_ILLEGAL 0xdeadbeef
@@ -183,7 +184,7 @@ static inline struct device_node *__of_get_dma_parent(const struct device_node *
#endif
int fdt_scan_reserved_mem(void);
-void fdt_init_reserved_mem(void);
+void __init fdt_scan_reserved_mem_reg_nodes(void);
bool of_fdt_device_is_available(const void *blob, unsigned long node);
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 46e1c3fbc769..45517b9e57b1 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -27,8 +27,9 @@
#include "of_private.h"
-#define MAX_RESERVED_REGIONS 64
-static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
+static struct reserved_mem reserved_mem_array[MAX_RESERVED_REGIONS] __initdata;
+static struct reserved_mem *reserved_mem __refdata = reserved_mem_array;
+static int total_reserved_mem_cnt = MAX_RESERVED_REGIONS;
static int reserved_mem_count;
static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
@@ -57,6 +58,51 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
}
/*
+ * alloc_reserved_mem_array() - allocate memory for the reserved_mem
+ * array using memblock
+ *
+ * This function is used to allocate memory for the reserved_mem
+ * array according to the total number of reserved memory regions
+ * defined in the DT.
+ * After the new array is allocated, the information stored in
+ * the initial static array is copied over to this new array and
+ * the new array is used from this point on.
+ */
+static void __init alloc_reserved_mem_array(void)
+{
+ struct reserved_mem *new_array;
+ size_t alloc_size, copy_size, memset_size;
+
+ alloc_size = array_size(total_reserved_mem_cnt, sizeof(*new_array));
+ if (alloc_size == SIZE_MAX) {
+ pr_err("Failed to allocate memory for reserved_mem array with err: %d", -EOVERFLOW);
+ return;
+ }
+
+ new_array = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
+ if (!new_array) {
+ pr_err("Failed to allocate memory for reserved_mem array with err: %d", -ENOMEM);
+ return;
+ }
+
+ copy_size = array_size(reserved_mem_count, sizeof(*new_array));
+ if (copy_size == SIZE_MAX) {
+ memblock_free(new_array, alloc_size);
+ total_reserved_mem_cnt = MAX_RESERVED_REGIONS;
+ pr_err("Failed to allocate memory for reserved_mem array with err: %d", -EOVERFLOW);
+ return;
+ }
+
+ memset_size = alloc_size - copy_size;
+
+ memcpy(new_array, reserved_mem, copy_size);
+ memset(new_array + reserved_mem_count, 0, memset_size);
+
+ reserved_mem = new_array;
+}
+
+static void __init fdt_init_reserved_mem_node(struct reserved_mem *rmem);
+/*
* fdt_reserved_mem_save_node() - save fdt node for second pass initialization
*/
static void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
@@ -64,7 +110,7 @@ static void __init fdt_reserved_mem_save_node(unsigned long node, const char *un
{
struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
- if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) {
+ if (reserved_mem_count == total_reserved_mem_cnt) {
pr_err("not enough space for all defined regions.\n");
return;
}
@@ -74,6 +120,9 @@ static void __init fdt_reserved_mem_save_node(unsigned long node, const char *un
rmem->base = base;
rmem->size = size;
+ /* Call the region specific initialization function */
+ fdt_init_reserved_mem_node(rmem);
+
reserved_mem_count++;
return;
}
@@ -106,7 +155,6 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
phys_addr_t base, size;
int len;
const __be32 *prop;
- int first = 1;
bool nomap;
prop = of_get_flat_dt_prop(node, "reg", &len);
@@ -134,10 +182,6 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
uname, &base, (unsigned long)(size / SZ_1M));
len -= t_len;
- if (first) {
- fdt_reserved_mem_save_node(node, uname, base, size);
- first = 0;
- }
}
return 0;
}
@@ -165,12 +209,80 @@ static int __init __reserved_mem_check_root(unsigned long node)
return 0;
}
+static void __init __rmem_check_for_overlap(void);
+
+/**
+ * fdt_scan_reserved_mem_reg_nodes() - Store info for the "reg" defined
+ * reserved memory regions.
+ *
+ * This function is used to scan through the DT and store the
+ * information for the reserved memory regions that are defined using
+ * the "reg" property. The region node number, name, base address, and
+ * size are all stored in the reserved_mem array by calling the
+ * fdt_reserved_mem_save_node() function.
+ */
+void __init fdt_scan_reserved_mem_reg_nodes(void)
+{
+ int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
+ const void *fdt = initial_boot_params;
+ phys_addr_t base, size;
+ const __be32 *prop;
+ int node, child;
+ int len;
+
+ if (!fdt)
+ return;
+
+ node = fdt_path_offset(fdt, "/reserved-memory");
+ if (node < 0) {
+ pr_info("Reserved memory: No reserved-memory node in the DT\n");
+ return;
+ }
+
+ /* Attempt dynamic allocation of a new reserved_mem array */
+ alloc_reserved_mem_array();
+
+ if (__reserved_mem_check_root(node)) {
+ pr_err("Reserved memory: unsupported node format, ignoring\n");
+ return;
+ }
+
+ fdt_for_each_subnode(child, fdt, node) {
+ const char *uname;
+
+ prop = of_get_flat_dt_prop(child, "reg", &len);
+ if (!prop)
+ continue;
+ if (!of_fdt_device_is_available(fdt, child))
+ continue;
+
+ uname = fdt_get_name(fdt, child, NULL);
+ if (len && len % t_len != 0) {
+ pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
+ uname);
+ continue;
+ }
+ base = dt_mem_next_cell(dt_root_addr_cells, &prop);
+ size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+ if (size)
+ fdt_reserved_mem_save_node(child, uname, base, size);
+ }
+
+ /* check for overlapping reserved regions */
+ __rmem_check_for_overlap();
+}
+
+static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname);
+
/*
* fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
*/
int __init fdt_scan_reserved_mem(void)
{
int node, child;
+ int dynamic_nodes_cnt = 0, count = 0;
+ int dynamic_nodes[MAX_RESERVED_REGIONS];
const void *fdt = initial_boot_params;
node = fdt_path_offset(fdt, "/reserved-memory");
@@ -192,9 +304,31 @@ int __init fdt_scan_reserved_mem(void)
uname = fdt_get_name(fdt, child, NULL);
err = __reserved_mem_reserve_reg(child, uname);
- if (err == -ENOENT && of_get_flat_dt_prop(child, "size", NULL))
- fdt_reserved_mem_save_node(child, uname, 0, 0);
+ if (!err)
+ count++;
+ /*
+ * Save the nodes for the dynamically-placed regions
+ * into an array which will be used for allocation right
+ * after all the statically-placed regions are reserved
+ * or marked as no-map. This is done to avoid dynamically
+ * allocating from one of the statically-placed regions.
+ */
+ if (err == -ENOENT && of_get_flat_dt_prop(child, "size", NULL)) {
+ dynamic_nodes[dynamic_nodes_cnt] = child;
+ dynamic_nodes_cnt++;
+ }
}
+ for (int i = 0; i < dynamic_nodes_cnt; i++) {
+ const char *uname;
+ int err;
+
+ child = dynamic_nodes[i];
+ uname = fdt_get_name(fdt, child, NULL);
+ err = __reserved_mem_alloc_size(child, uname);
+ if (!err)
+ count++;
+ }
+ total_reserved_mem_cnt = count;
return 0;
}
@@ -253,8 +387,7 @@ static int __init __reserved_mem_alloc_in_range(phys_addr_t size,
* __reserved_mem_alloc_size() - allocate reserved memory described by
* 'size', 'alignment' and 'alloc-ranges' properties.
*/
-static int __init __reserved_mem_alloc_size(unsigned long node,
- const char *uname, phys_addr_t *res_base, phys_addr_t *res_size)
+static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname)
{
int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
phys_addr_t start = 0, end = 0;
@@ -334,9 +467,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
return -ENOMEM;
}
- *res_base = base;
- *res_size = size;
-
+ /* Save region in the reserved_mem array */
+ fdt_reserved_mem_save_node(node, uname, base, size);
return 0;
}
@@ -425,48 +557,37 @@ static void __init __rmem_check_for_overlap(void)
}
/**
- * fdt_init_reserved_mem() - allocate and init all saved reserved memory regions
+ * fdt_init_reserved_mem_node() - Initialize a reserved memory region
+ * @rmem: reserved_mem struct of the memory region to be initialized.
+ *
+ * This function is used to call the region specific initialization
+ * function for a reserved memory region.
*/
-void __init fdt_init_reserved_mem(void)
+static void __init fdt_init_reserved_mem_node(struct reserved_mem *rmem)
{
- int i;
-
- /* check for overlapping reserved regions */
- __rmem_check_for_overlap();
-
- for (i = 0; i < reserved_mem_count; i++) {
- struct reserved_mem *rmem = &reserved_mem[i];
- unsigned long node = rmem->fdt_node;
- int err = 0;
- bool nomap;
+ unsigned long node = rmem->fdt_node;
+ int err = 0;
+ bool nomap;
- nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
+ nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
- if (rmem->size == 0)
- err = __reserved_mem_alloc_size(node, rmem->name,
- &rmem->base, &rmem->size);
- if (err == 0) {
- err = __reserved_mem_init_node(rmem);
- if (err != 0 && err != -ENOENT) {
- pr_info("node %s compatible matching fail\n",
- rmem->name);
- if (nomap)
- memblock_clear_nomap(rmem->base, rmem->size);
- else
- memblock_phys_free(rmem->base,
- rmem->size);
- } else {
- phys_addr_t end = rmem->base + rmem->size - 1;
- bool reusable =
- (of_get_flat_dt_prop(node, "reusable", NULL)) != NULL;
-
- pr_info("%pa..%pa (%lu KiB) %s %s %s\n",
- &rmem->base, &end, (unsigned long)(rmem->size / SZ_1K),
- nomap ? "nomap" : "map",
- reusable ? "reusable" : "non-reusable",
- rmem->name ? rmem->name : "unknown");
- }
- }
+ err = __reserved_mem_init_node(rmem);
+ if (err != 0 && err != -ENOENT) {
+ pr_info("node %s compatible matching fail\n", rmem->name);
+ if (nomap)
+ memblock_clear_nomap(rmem->base, rmem->size);
+ else
+ memblock_phys_free(rmem->base, rmem->size);
+ } else {
+ phys_addr_t end = rmem->base + rmem->size - 1;
+ bool reusable =
+ (of_get_flat_dt_prop(node, "reusable", NULL)) != NULL;
+
+ pr_info("%pa..%pa (%lu KiB) %s %s %s\n",
+ &rmem->base, &end, (unsigned long)(rmem->size / SZ_1K),
+ nomap ? "nomap" : "map",
+ reusable ? "reusable" : "non-reusable",
+ rmem->name ? rmem->name : "unknown");
}
}
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index cbdecccca097..434f6dd6a86c 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -296,10 +296,11 @@ err_free_target_path:
* invalid @overlay.
*/
static int add_changeset_property(struct overlay_changeset *ovcs,
- struct target *target, struct property *overlay_prop,
+ struct target *target, const struct property *overlay_prop,
bool is_symbols_prop)
{
- struct property *new_prop = NULL, *prop;
+ struct property *new_prop = NULL;
+ const struct property *prop;
int ret = 0;
if (target->in_livetree)
@@ -398,7 +399,7 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
* invalid @overlay.
*/
static int add_changeset_node(struct overlay_changeset *ovcs,
- struct target *target, struct device_node *node)
+ struct target *target, const struct device_node *node)
{
const char *node_kbasename;
const __be32 *phandle;
@@ -675,8 +676,8 @@ static int build_changeset(struct overlay_changeset *ovcs)
* 1) "target" property containing the phandle of the target
* 2) "target-path" property containing the path of the target
*/
-static struct device_node *find_target(struct device_node *info_node,
- struct device_node *target_base)
+static struct device_node *find_target(const struct device_node *info_node,
+ const struct device_node *target_base)
{
struct device_node *node;
char *target_path;
@@ -735,7 +736,7 @@ static struct device_node *find_target(struct device_node *info_node,
* init_overlay_changeset() must call free_overlay_changeset().
*/
static int init_overlay_changeset(struct overlay_changeset *ovcs,
- struct device_node *target_base)
+ const struct device_node *target_base)
{
struct device_node *node, *overlay_node;
struct fragment *fragment;
@@ -910,7 +911,7 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
*/
static int of_overlay_apply(struct overlay_changeset *ovcs,
- struct device_node *base)
+ const struct device_node *base)
{
int ret = 0, ret_revert, ret_tmp;
@@ -978,7 +979,7 @@ out:
*/
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
- int *ret_ovcs_id, struct device_node *base)
+ int *ret_ovcs_id, const struct device_node *base)
{
void *new_fdt;
void *new_fdt_align;
@@ -1074,7 +1075,7 @@ EXPORT_SYMBOL_GPL(of_overlay_fdt_apply);
*
* Returns 1 if @np is @tree or is contained in @tree, else 0
*/
-static int find_node(struct device_node *tree, struct device_node *np)
+static int find_node(const struct device_node *tree, struct device_node *np)
{
if (tree == np)
return 1;
diff --git a/drivers/of/overlay_test.c b/drivers/of/overlay_test.c
index 1f76d50fb16a..c787524c5a88 100644
--- a/drivers/of/overlay_test.c
+++ b/drivers/of/overlay_test.c
@@ -65,6 +65,8 @@ static void of_overlay_apply_kunit_cleanup(struct kunit *test)
struct device_node *np;
of_root_kunit_skip(test);
+ if (!IS_ENABLED(CONFIG_OF_OVERLAY))
+ kunit_skip(test, "requires CONFIG_OF_OVERLAY to apply overlay");
if (!IS_ENABLED(CONFIG_OF_EARLY_FLATTREE))
kunit_skip(test, "requires CONFIG_OF_EARLY_FLATTREE for root node");
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 11b922fde7af..519bf9229e61 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(of_graph_is_present);
int of_property_count_elems_of_size(const struct device_node *np,
const char *propname, int elem_size)
{
- struct property *prop = of_find_property(np, propname, NULL);
+ const struct property *prop = of_find_property(np, propname, NULL);
if (!prop)
return -EINVAL;
@@ -104,7 +104,7 @@ EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
static void *of_find_property_value_of_size(const struct device_node *np,
const char *propname, u32 min, u32 max, size_t *len)
{
- struct property *prop = of_find_property(np, propname, NULL);
+ const struct property *prop = of_find_property(np, propname, NULL);
if (!prop)
return ERR_PTR(-EINVAL);
@@ -530,7 +530,7 @@ int of_property_read_string_helper(const struct device_node *np,
}
EXPORT_SYMBOL_GPL(of_property_read_string_helper);
-const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
+const __be32 *of_prop_next_u32(const struct property *prop, const __be32 *cur,
u32 *pu)
{
const void *curv = cur;
@@ -553,7 +553,7 @@ out_val:
}
EXPORT_SYMBOL_GPL(of_prop_next_u32);
-const char *of_prop_next_string(struct property *prop, const char *cur)
+const char *of_prop_next_string(const struct property *prop, const char *cur)
{
const void *curv = cur;
@@ -631,6 +631,70 @@ struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
EXPORT_SYMBOL(of_graph_get_port_by_id);
/**
+ * of_graph_get_next_port() - get next port node.
+ * @parent: pointer to the parent device node, or parent ports node
+ * @prev: previous port node, or NULL to get first
+ *
+ * Parent device node can be used as @parent whether device node has ports node
+ * or not. It will work same as ports@0 node.
+ *
+ * Return: A 'port' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is decremented.
+ */
+struct device_node *of_graph_get_next_port(const struct device_node *parent,
+ struct device_node *prev)
+{
+ if (!parent)
+ return NULL;
+
+ if (!prev) {
+ struct device_node *node __free(device_node) =
+ of_get_child_by_name(parent, "ports");
+
+ if (node)
+ parent = node;
+
+ return of_get_child_by_name(parent, "port");
+ }
+
+ do {
+ prev = of_get_next_child(parent, prev);
+ if (!prev)
+ break;
+ } while (!of_node_name_eq(prev, "port"));
+
+ return prev;
+}
+EXPORT_SYMBOL(of_graph_get_next_port);
+
+/**
+ * of_graph_get_next_port_endpoint() - get next endpoint node in port.
+ * If it reached to end of the port, it will return NULL.
+ * @port: pointer to the target port node
+ * @prev: previous endpoint node, or NULL to get first
+ *
+ * Return: An 'endpoint' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is decremented.
+ */
+struct device_node *of_graph_get_next_port_endpoint(const struct device_node *port,
+ struct device_node *prev)
+{
+ while (1) {
+ prev = of_get_next_child(port, prev);
+ if (!prev)
+ break;
+ if (WARN(!of_node_name_eq(prev, "endpoint"),
+ "non endpoint node is used (%pOF)", prev))
+ continue;
+
+ break;
+ }
+
+ return prev;
+}
+EXPORT_SYMBOL(of_graph_get_next_port_endpoint);
+
+/**
* of_graph_get_next_endpoint() - get next endpoint node
* @parent: pointer to the parent device node
* @prev: previous endpoint node, or NULL to get first
@@ -653,13 +717,7 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
* parent port node.
*/
if (!prev) {
- struct device_node *node __free(device_node) =
- of_get_child_by_name(parent, "ports");
-
- if (node)
- parent = node;
-
- port = of_get_child_by_name(parent, "port");
+ port = of_graph_get_next_port(parent, NULL);
if (!port) {
pr_debug("graph: no port node found in %pOF\n", parent);
return NULL;
@@ -677,7 +735,7 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
* getting the next child. If the previous endpoint is NULL this
* will return the first child.
*/
- endpoint = of_get_next_child(port, prev);
+ endpoint = of_graph_get_next_port_endpoint(port, prev);
if (endpoint) {
of_node_put(port);
return endpoint;
@@ -686,11 +744,9 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
/* No more endpoints under this port, try the next one. */
prev = NULL;
- do {
- port = of_get_next_child(parent, port);
- if (!port)
- return NULL;
- } while (!of_node_name_eq(port, "port"));
+ port = of_graph_get_next_port(parent, port);
+ if (!port)
+ return NULL;
}
}
EXPORT_SYMBOL(of_graph_get_next_endpoint);
@@ -824,6 +880,23 @@ unsigned int of_graph_get_endpoint_count(const struct device_node *np)
EXPORT_SYMBOL(of_graph_get_endpoint_count);
/**
+ * of_graph_get_port_count() - get the number of port in a device or ports node
+ * @np: pointer to the device or ports node
+ *
+ * Return: count of port of this device or ports node
+ */
+unsigned int of_graph_get_port_count(struct device_node *np)
+{
+ unsigned int num = 0;
+
+ for_each_of_graph_port(np, port)
+ num++;
+
+ return num;
+}
+EXPORT_SYMBOL(of_graph_get_port_count);
+
+/**
* of_graph_get_remote_node() - get remote parent device_node for given port/endpoint
* @node: pointer to parent device_node containing graph port/endpoint
* @port: identifier (value of reg property) of the parent port node
@@ -1466,7 +1539,7 @@ static int of_fwnode_irq_get(const struct fwnode_handle *fwnode,
static int of_fwnode_add_links(struct fwnode_handle *fwnode)
{
- struct property *p;
+ const struct property *p;
struct device_node *con_np = to_of_node(fwnode);
if (IS_ENABLED(CONFIG_X86))
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
index 5cf96776dd7d..779db058c42f 100644
--- a/drivers/of/resolver.c
+++ b/drivers/of/resolver.c
@@ -42,7 +42,7 @@ static void adjust_overlay_phandles(struct device_node *overlay,
int phandle_delta)
{
struct device_node *child;
- struct property *prop;
+ const struct property *prop;
phandle phandle;
/* adjust node's phandle in node */
@@ -71,10 +71,10 @@ static void adjust_overlay_phandles(struct device_node *overlay,
}
static int update_usages_of_a_phandle_reference(struct device_node *overlay,
- struct property *prop_fixup, phandle phandle)
+ const struct property *prop_fixup, phandle phandle)
{
struct device_node *refnode;
- struct property *prop;
+ const struct property *prop;
char *value __free(kfree) = kmemdup(prop_fixup->value, prop_fixup->length, GFP_KERNEL);
char *cur, *end, *node_path, *prop_name, *s;
int offset, len;
@@ -147,11 +147,11 @@ static int node_name_cmp(const struct device_node *dn1,
* of offsets of the phandle reference(s) within the respective property
* value(s). The values at these offsets will be fixed up.
*/
-static int adjust_local_phandle_references(struct device_node *local_fixups,
- struct device_node *overlay, int phandle_delta)
+static int adjust_local_phandle_references(const struct device_node *local_fixups,
+ const struct device_node *overlay, int phandle_delta)
{
struct device_node *overlay_child;
- struct property *prop_fix, *prop;
+ const struct property *prop_fix, *prop;
int err, i, count;
unsigned int off;
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 3aa18737470f..0311b18319a4 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -2360,48 +2360,13 @@ static void _opp_put_config_regulators_helper(struct opp_table *opp_table)
opp_table->config_regulators = NULL;
}
-static void _opp_detach_genpd(struct opp_table *opp_table)
+static int _opp_set_required_dev(struct opp_table *opp_table,
+ struct device *dev,
+ struct device *required_dev,
+ unsigned int index)
{
- int index;
-
- for (index = 0; index < opp_table->required_opp_count; index++) {
- if (!opp_table->required_devs[index])
- continue;
-
- dev_pm_domain_detach(opp_table->required_devs[index], false);
- opp_table->required_devs[index] = NULL;
- }
-}
-
-/*
- * Multiple generic power domains for a device are supported with the help of
- * virtual genpd devices, which are created for each consumer device - genpd
- * pair. These are the device structures which are attached to the power domain
- * and are required by the OPP core to set the performance state of the genpd.
- * The same API also works for the case where single genpd is available and so
- * we don't need to support that separately.
- *
- * This helper will normally be called by the consumer driver of the device
- * "dev", as only that has details of the genpd names.
- *
- * This helper needs to be called once with a list of all genpd to attach.
- * Otherwise the original device structure will be used instead by the OPP core.
- *
- * The order of entries in the names array must match the order in which
- * "required-opps" are added in DT.
- */
-static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
- const char * const *names, struct device ***virt_devs)
-{
- struct device *virt_dev, *gdev;
- struct opp_table *genpd_table;
- int index = 0, ret = -EINVAL;
- const char * const *name = names;
-
- if (!opp_table->required_devs) {
- dev_err(dev, "Required OPPs not available, can't attach genpd\n");
- return -EINVAL;
- }
+ struct opp_table *required_table, *pd_table;
+ struct device *gdev;
/* Genpd core takes care of propagation to parent genpd */
if (opp_table->is_genpd) {
@@ -2409,114 +2374,59 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
return -EOPNOTSUPP;
}
- /* Checking only the first one is enough ? */
- if (opp_table->required_devs[0])
- return 0;
-
- while (*name) {
- if (index >= opp_table->required_opp_count) {
- dev_err(dev, "Index can't be greater than required-opp-count - 1, %s (%d : %d)\n",
- *name, opp_table->required_opp_count, index);
- goto err;
- }
-
- virt_dev = dev_pm_domain_attach_by_name(dev, *name);
- if (IS_ERR_OR_NULL(virt_dev)) {
- ret = virt_dev ? PTR_ERR(virt_dev) : -ENODEV;
- dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret);
- goto err;
- }
-
- /*
- * The required_opp_tables parsing is not perfect, as the OPP
- * core does the parsing solely based on the DT node pointers.
- * The core sets the required_opp_tables entry to the first OPP
- * table in the "opp_tables" list, that matches with the node
- * pointer.
- *
- * If the target DT OPP table is used by multiple devices and
- * they all create separate instances of 'struct opp_table' from
- * it, then it is possible that the required_opp_tables entry
- * may be set to the incorrect sibling device.
- *
- * Cross check it again and fix if required.
- */
- gdev = dev_to_genpd_dev(virt_dev);
- if (IS_ERR(gdev)) {
- ret = PTR_ERR(gdev);
- goto err;
- }
-
- genpd_table = _find_opp_table(gdev);
- if (!IS_ERR(genpd_table)) {
- if (genpd_table != opp_table->required_opp_tables[index]) {
- dev_pm_opp_put_opp_table(opp_table->required_opp_tables[index]);
- opp_table->required_opp_tables[index] = genpd_table;
- } else {
- dev_pm_opp_put_opp_table(genpd_table);
- }
- }
-
- opp_table->required_devs[index] = virt_dev;
- index++;
- name++;
- }
-
- if (virt_devs)
- *virt_devs = opp_table->required_devs;
-
- return 0;
-
-err:
- _opp_detach_genpd(opp_table);
- return ret;
-
-}
-
-static int _opp_set_required_devs(struct opp_table *opp_table,
- struct device *dev,
- struct device **required_devs)
-{
- int i;
-
- if (!opp_table->required_devs) {
+ if (index >= opp_table->required_opp_count) {
dev_err(dev, "Required OPPs not available, can't set required devs\n");
return -EINVAL;
}
- /* Another device that shares the OPP table has set the required devs ? */
- if (opp_table->required_devs[0])
- return 0;
+ required_table = opp_table->required_opp_tables[index];
+ if (IS_ERR(required_table)) {
+ dev_err(dev, "Missing OPP table, unable to set the required devs\n");
+ return -ENODEV;
+ }
- for (i = 0; i < opp_table->required_opp_count; i++) {
- /* Genpd core takes care of propagation to parent genpd */
- if (required_devs[i] && opp_table->is_genpd &&
- opp_table->required_opp_tables[i]->is_genpd) {
- dev_err(dev, "%s: Operation not supported for genpds\n", __func__);
- return -EOPNOTSUPP;
+ /*
+ * The required_opp_tables parsing is not perfect, as the OPP core does
+ * the parsing solely based on the DT node pointers. The core sets the
+ * required_opp_tables entry to the first OPP table in the "opp_tables"
+ * list, that matches with the node pointer.
+ *
+ * If the target DT OPP table is used by multiple devices and they all
+ * create separate instances of 'struct opp_table' from it, then it is
+ * possible that the required_opp_tables entry may be set to the
+ * incorrect sibling device.
+ *
+ * Cross check it again and fix if required.
+ */
+ gdev = dev_to_genpd_dev(required_dev);
+ if (IS_ERR(gdev))
+ return PTR_ERR(gdev);
+
+ pd_table = _find_opp_table(gdev);
+ if (!IS_ERR(pd_table)) {
+ if (pd_table != required_table) {
+ dev_pm_opp_put_opp_table(required_table);
+ opp_table->required_opp_tables[index] = pd_table;
+ } else {
+ dev_pm_opp_put_opp_table(pd_table);
}
-
- opp_table->required_devs[i] = required_devs[i];
}
+ opp_table->required_devs[index] = required_dev;
return 0;
}
-static void _opp_put_required_devs(struct opp_table *opp_table)
+static void _opp_put_required_dev(struct opp_table *opp_table,
+ unsigned int index)
{
- int i;
-
- for (i = 0; i < opp_table->required_opp_count; i++)
- opp_table->required_devs[i] = NULL;
+ opp_table->required_devs[index] = NULL;
}
static void _opp_clear_config(struct opp_config_data *data)
{
- if (data->flags & OPP_CONFIG_REQUIRED_DEVS)
- _opp_put_required_devs(data->opp_table);
- else if (data->flags & OPP_CONFIG_GENPD)
- _opp_detach_genpd(data->opp_table);
-
+ if (data->flags & OPP_CONFIG_REQUIRED_DEV)
+ _opp_put_required_dev(data->opp_table,
+ data->required_dev_index);
if (data->flags & OPP_CONFIG_REGULATOR)
_opp_put_regulators(data->opp_table);
if (data->flags & OPP_CONFIG_SUPPORTED_HW)
@@ -2628,26 +2538,15 @@ int dev_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config)
data->flags |= OPP_CONFIG_REGULATOR;
}
- /* Attach genpds */
- if (config->genpd_names) {
- if (config->required_devs) {
- ret = -EINVAL;
- goto err;
- }
-
- ret = _opp_attach_genpd(opp_table, dev, config->genpd_names,
- config->virt_devs);
- if (ret)
- goto err;
-
- data->flags |= OPP_CONFIG_GENPD;
- } else if (config->required_devs) {
- ret = _opp_set_required_devs(opp_table, dev,
- config->required_devs);
+ if (config->required_dev) {
+ ret = _opp_set_required_dev(opp_table, dev,
+ config->required_dev,
+ config->required_dev_index);
if (ret)
goto err;
- data->flags |= OPP_CONFIG_REQUIRED_DEVS;
+ data->required_dev_index = config->required_dev_index;
+ data->flags |= OPP_CONFIG_REQUIRED_DEV;
}
ret = xa_alloc(&opp_configs, &id, data, XA_LIMIT(1, INT_MAX),
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 55c8cfef97d4..fd5ed2858258 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -295,7 +295,7 @@ void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp)
of_node_put(opp->np);
}
-static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_table,
+static int _link_required_opps(struct dev_pm_opp *opp,
struct opp_table *required_table, int index)
{
struct device_node *np;
@@ -313,39 +313,6 @@ static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_tab
return -ENODEV;
}
- /*
- * There are two genpd (as required-opp) cases that we need to handle,
- * devices with a single genpd and ones with multiple genpds.
- *
- * The single genpd case requires special handling as we need to use the
- * same `dev` structure (instead of a virtual one provided by genpd
- * core) for setting the performance state.
- *
- * It doesn't make sense for a device's DT entry to have both
- * "opp-level" and single "required-opps" entry pointing to a genpd's
- * OPP, as that would make the OPP core call
- * dev_pm_domain_set_performance_state() for two different values for
- * the same device structure. Lets treat single genpd configuration as a
- * case where the OPP's level is directly available without required-opp
- * link in the DT.
- *
- * Just update the `level` with the right value, which
- * dev_pm_opp_set_opp() will take care of in the normal path itself.
- *
- * There is another case though, where a genpd's OPP table has
- * required-opps set to a parent genpd. The OPP core expects the user to
- * set the respective required `struct device` pointer via
- * dev_pm_opp_set_config().
- */
- if (required_table->is_genpd && opp_table->required_opp_count == 1 &&
- !opp_table->required_devs[0]) {
- /* Genpd core takes care of propagation to parent genpd */
- if (!opp_table->is_genpd) {
- if (!WARN_ON(opp->level != OPP_LEVEL_UNSET))
- opp->level = opp->required_opps[0]->level;
- }
- }
-
return 0;
}
@@ -370,7 +337,7 @@ static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
if (IS_ERR_OR_NULL(required_table))
continue;
- ret = _link_required_opps(opp, opp_table, required_table, i);
+ ret = _link_required_opps(opp, required_table, i);
if (ret)
goto free_required_opps;
}
@@ -391,7 +358,7 @@ static int lazy_link_required_opps(struct opp_table *opp_table,
int ret;
list_for_each_entry(opp, &opp_table->opp_list, node) {
- ret = _link_required_opps(opp, opp_table, new_table, index);
+ ret = _link_required_opps(opp, new_table, index);
if (ret)
return ret;
}
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index cff1fabd1ae3..430651e7424a 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -34,13 +34,13 @@ extern struct list_head opp_tables;
#define OPP_CONFIG_REGULATOR_HELPER BIT(2)
#define OPP_CONFIG_PROP_NAME BIT(3)
#define OPP_CONFIG_SUPPORTED_HW BIT(4)
-#define OPP_CONFIG_GENPD BIT(5)
-#define OPP_CONFIG_REQUIRED_DEVS BIT(6)
+#define OPP_CONFIG_REQUIRED_DEV BIT(5)
/**
* struct opp_config_data - data for set config operations
* @opp_table: OPP table
* @flags: OPP config flags
+ * @required_dev_index: The position in the array of required_devs
*
* This structure stores the OPP config information for each OPP table
* configuration by the callers.
@@ -48,6 +48,7 @@ extern struct list_head opp_tables;
struct opp_config_data {
struct opp_table *opp_table;
unsigned int flags;
+ unsigned int required_dev_index;
};
/**
@@ -262,9 +263,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *o
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic);
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
-void _put_opp_list_kref(struct opp_table *opp_table);
void _required_opps_available(struct dev_pm_opp *opp, int count);
-void _update_set_required_opps(struct opp_table *opp_table);
static inline bool lazy_linking_pending(struct opp_table *opp_table)
{
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 0d94e4a967d8..2fbd379923fd 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -173,6 +173,15 @@ config PCI_PASID
If unsure, say N.
+config PCIE_TPH
+ bool "TLP Processing Hints"
+ help
+ This option adds support for PCIe TLP Processing Hints (TPH).
+ TPH allows endpoint devices to provide optimization hints, such as
+ desired caching behavior, for requests that target memory space.
+ These hints, called Steering Tags, can empower the system hardware
+ to optimize the utilization of platform resources.
+
config PCI_P2PDMA
bool "PCI peer-to-peer transfer support"
depends on ZONE_DEVICE
@@ -305,6 +314,6 @@ source "drivers/pci/hotplug/Kconfig"
source "drivers/pci/controller/Kconfig"
source "drivers/pci/endpoint/Kconfig"
source "drivers/pci/switch/Kconfig"
-source "drivers/pci/pwrctl/Kconfig"
+source "drivers/pci/pwrctrl/Kconfig"
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 374c5c06d92f..67647f1880fb 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_PCI) += access.o bus.o probe.o host-bridge.o \
obj-$(CONFIG_PCI) += msi/
obj-$(CONFIG_PCI) += pcie/
-obj-$(CONFIG_PCI) += pwrctl/
+obj-$(CONFIG_PCI) += pwrctrl/
ifdef CONFIG_PCI
obj-$(CONFIG_PROC_FS) += proc.o
@@ -36,6 +36,7 @@ obj-$(CONFIG_VGA_ARB) += vgaarb.o
obj-$(CONFIG_PCI_DOE) += doe.o
obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o
obj-$(CONFIG_PCI_NPEM) += npem.o
+obj-$(CONFIG_PCIE_TPH) += tph.o
# Endpoint library must be initialized before its users
obj-$(CONFIG_PCI_ENDPOINT) += endpoint/
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 55c853686051..98910bc0fcc4 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -13,11 +13,24 @@
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include "pci.h"
+/*
+ * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
+ * to P2P or CardBus bridge windows) go in a table. Additional ones (for
+ * buses below host bridges or subtractive decode bridges) go in the list.
+ * Use pci_bus_for_each_resource() to iterate through all the resources.
+ */
+
+struct pci_bus_resource {
+ struct list_head list;
+ struct resource *res;
+};
+
void pci_add_resource_offset(struct list_head *resources, struct resource *res,
resource_size_t offset)
{
@@ -46,8 +59,7 @@ void pci_free_resource_list(struct list_head *resources)
}
EXPORT_SYMBOL(pci_free_resource_list);
-void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
- unsigned int flags)
+void pci_bus_add_resource(struct pci_bus *bus, struct resource *res)
{
struct pci_bus_resource *bus_res;
@@ -58,7 +70,6 @@ void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
}
bus_res->res = res;
- bus_res->flags = flags;
list_add_tail(&bus_res->list, &bus->resources);
}
@@ -320,6 +331,47 @@ void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
+/*
+ * Create pwrctrl devices (if required) for the PCI devices to handle the power
+ * state.
+ */
+static void pci_pwrctrl_create_devices(struct pci_dev *dev)
+{
+ struct device_node *np = dev_of_node(&dev->dev);
+ struct device *parent = &dev->dev;
+ struct platform_device *pdev;
+
+ /*
+ * First ensure that we are starting from a PCI bridge and it has a
+ * corresponding devicetree node.
+ */
+ if (np && pci_is_bridge(dev)) {
+ /*
+ * Now look for the child PCI device nodes and create pwrctrl
+ * devices for them. The pwrctrl device drivers will manage the
+ * power state of the devices.
+ */
+ for_each_available_child_of_node_scoped(np, child) {
+ /*
+ * First check whether the pwrctrl device really
+ * needs to be created or not. This is decided
+ * based on at least one of the power supplies
+ * being defined in the devicetree node of the
+ * device.
+ */
+ if (!of_pci_supply_present(child)) {
+ pci_dbg(dev, "skipping OF node: %s\n", child->name);
+ return;
+ }
+
+ /* Now create the pwrctrl device */
+ pdev = of_platform_device_create(child, NULL, parent);
+ if (!pdev)
+ pci_err(dev, "failed to create OF node: %s\n", child->name);
+ }
+ }
+}
+
/**
* pci_bus_add_device - start driver for a single device
* @dev: device to add
@@ -329,6 +381,7 @@ void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
void pci_bus_add_device(struct pci_dev *dev)
{
struct device_node *dn = dev->dev.of_node;
+ struct platform_device *pdev;
int retval;
/*
@@ -343,20 +396,28 @@ void pci_bus_add_device(struct pci_dev *dev)
pci_proc_attach_device(dev);
pci_bridge_d3_update(dev);
+ pci_pwrctrl_create_devices(dev);
+
+ /*
+ * If the PCI device is associated with a pwrctrl device with a
+ * power supply, create a device link between the PCI device and
+ * pwrctrl device. This ensures that pwrctrl drivers are probed
+ * before PCI client drivers.
+ */
+ pdev = of_find_device_by_node(dn);
+ if (pdev && of_pci_supply_present(dn)) {
+ if (!device_link_add(&dev->dev, &pdev->dev,
+ DL_FLAG_AUTOREMOVE_CONSUMER))
+ pci_err(dev, "failed to add device link to power control device %s\n",
+ pdev->name);
+ }
+
dev->match_driver = !dn || of_device_is_available(dn);
retval = device_attach(&dev->dev);
if (retval < 0 && retval != -EPROBE_DEFER)
pci_warn(dev, "device attach failed (%d)\n", retval);
- pci_dev_assign_added(dev, true);
-
- if (dev_of_node(&dev->dev) && pci_is_bridge(dev)) {
- retval = of_platform_populate(dev_of_node(&dev->dev), NULL, NULL,
- &dev->dev);
- if (retval)
- pci_err(dev, "failed to populate child OF nodes (%d)\n",
- retval);
- }
+ pci_dev_assign_added(dev);
}
EXPORT_SYMBOL_GPL(pci_bus_add_device);
@@ -389,41 +450,23 @@ void pci_bus_add_devices(const struct pci_bus *bus)
}
EXPORT_SYMBOL(pci_bus_add_devices);
-static void __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
- void *userdata, bool locked)
+static int __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
+ void *userdata)
{
struct pci_dev *dev;
- struct pci_bus *bus;
- struct list_head *next;
- int retval;
+ int ret = 0;
- bus = top;
- if (!locked)
- down_read(&pci_bus_sem);
- next = top->devices.next;
- for (;;) {
- if (next == &bus->devices) {
- /* end of this bus, go up or finish */
- if (bus == top)
+ list_for_each_entry(dev, &top->devices, bus_list) {
+ ret = cb(dev, userdata);
+ if (ret)
+ break;
+ if (dev->subordinate) {
+ ret = __pci_walk_bus(dev->subordinate, cb, userdata);
+ if (ret)
break;
- next = bus->self->bus_list.next;
- bus = bus->self->bus;
- continue;
}
- dev = list_entry(next, struct pci_dev, bus_list);
- if (dev->subordinate) {
- /* this is a pci-pci bridge, do its devices next */
- next = dev->subordinate->devices.next;
- bus = dev->subordinate;
- } else
- next = dev->bus_list.next;
-
- retval = cb(dev, userdata);
- if (retval)
- break;
}
- if (!locked)
- up_read(&pci_bus_sem);
+ return ret;
}
/**
@@ -441,7 +484,9 @@ static void __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void
*/
void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata)
{
- __pci_walk_bus(top, cb, userdata, false);
+ down_read(&pci_bus_sem);
+ __pci_walk_bus(top, cb, userdata);
+ up_read(&pci_bus_sem);
}
EXPORT_SYMBOL_GPL(pci_walk_bus);
@@ -449,9 +494,8 @@ void pci_walk_bus_locked(struct pci_bus *top, int (*cb)(struct pci_dev *, void *
{
lockdep_assert_held(&pci_bus_sem);
- __pci_walk_bus(top, cb, userdata, true);
+ __pci_walk_bus(top, cb, userdata);
}
-EXPORT_SYMBOL_GPL(pci_walk_bus_locked);
struct pci_bus *pci_bus_get(struct pci_bus *bus)
{
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index 284f2e0e4d26..0341d51d6aed 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -386,6 +386,13 @@ static const struct j721e_pcie_data j784s4_pcie_ep_data = {
.max_lanes = 4,
};
+static const struct j721e_pcie_data j722s_pcie_rc_data = {
+ .mode = PCI_MODE_RC,
+ .linkdown_irq_regfield = J7200_LINK_DOWN,
+ .byte_access_allowed = true,
+ .max_lanes = 1,
+};
+
static const struct of_device_id of_j721e_pcie_match[] = {
{
.compatible = "ti,j721e-pcie-host",
@@ -419,6 +426,10 @@ static const struct of_device_id of_j721e_pcie_match[] = {
.compatible = "ti,j784s4-pcie-ep",
.data = &j784s4_pcie_ep_data,
},
+ {
+ .compatible = "ti,j722s-pcie-host",
+ .data = &j722s_pcie_rc_data,
+ },
{},
};
@@ -572,15 +583,14 @@ static int j721e_pcie_probe(struct platform_device *pdev)
pcie->refclk = clk;
/*
- * The "Power Sequencing and Reset Signal Timings" table of the
- * PCI Express Card Electromechanical Specification, Revision
- * 5.1, Section 2.9.2, Symbol "T_PERST-CLK", indicates PERST#
- * should be deasserted after minimum of 100us once REFCLK is
- * stable. The REFCLK to the connector in RC mode is selected
- * while enabling the PHY. So deassert PERST# after 100 us.
+ * Section 2.2 of the PCI Express Card Electromechanical
+ * Specification (Revision 5.1) mandates that the deassertion
+ * of the PERST# signal should be delayed by 100 ms (TPVPERL).
+ * This shall ensure that the power and the reference clock
+ * are stable.
*/
if (gpiod) {
- fsleep(PCIE_T_PERST_CLK_US);
+ msleep(PCIE_T_PVPERL_MS);
gpiod_set_value_cansleep(gpiod, 1);
}
@@ -671,15 +681,14 @@ static int j721e_pcie_resume_noirq(struct device *dev)
return ret;
/*
- * The "Power Sequencing and Reset Signal Timings" table of the
- * PCI Express Card Electromechanical Specification, Revision
- * 5.1, Section 2.9.2, Symbol "T_PERST-CLK", indicates PERST#
- * should be deasserted after minimum of 100us once REFCLK is
- * stable. The REFCLK to the connector in RC mode is selected
- * while enabling the PHY. So deassert PERST# after 100 us.
+ * Section 2.2 of the PCI Express Card Electromechanical
+ * Specification (Revision 5.1) mandates that the deassertion
+ * of the PERST# signal should be delayed by 100 ms (TPVPERL).
+ * This shall ensure that the power and the reference clock
+ * are stable.
*/
if (pcie->reset_gpio) {
- fsleep(PCIE_T_PERST_CLK_US);
+ msleep(PCIE_T_PVPERL_MS);
gpiod_set_value_cansleep(pcie->reset_gpio, 1);
}
@@ -712,7 +721,7 @@ static DEFINE_NOIRQ_DEV_PM_OPS(j721e_pcie_pm_ops,
static struct platform_driver j721e_pcie_driver = {
.probe = j721e_pcie_probe,
- .remove_new = j721e_pcie_remove,
+ .remove = j721e_pcie_remove,
.driver = {
.name = "j721e-pcie",
.of_match_table = of_j721e_pcie_match,
diff --git a/drivers/pci/controller/cadence/pcie-cadence.c b/drivers/pci/controller/cadence/pcie-cadence.c
index 4251fac5e310..204e045aed8c 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.c
+++ b/drivers/pci/controller/cadence/pcie-cadence.c
@@ -197,7 +197,7 @@ int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie)
phy_count = of_property_count_strings(np, "phy-names");
if (phy_count < 1) {
- dev_err(dev, "no phy-names. PHY will not be initialized\n");
+ dev_info(dev, "no \"phy-names\" property found; PHY will not be initialized\n");
pcie->phy_count = 0;
return 0;
}
@@ -260,7 +260,7 @@ static int cdns_pcie_resume_noirq(struct device *dev)
ret = cdns_pcie_enable_phy(pcie);
if (ret) {
- dev_err(dev, "failed to enable phy\n");
+ dev_err(dev, "failed to enable PHY\n");
return ret;
}
diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c
index fa45da28a218..6a830166d37f 100644
--- a/drivers/pci/controller/dwc/pci-exynos.c
+++ b/drivers/pci/controller/dwc/pci-exynos.c
@@ -383,7 +383,7 @@ static const struct of_device_id exynos_pcie_of_match[] = {
static struct platform_driver exynos_pcie_driver = {
.probe = exynos_pcie_probe,
- .remove_new = exynos_pcie_remove,
+ .remove = exynos_pcie_remove,
.driver = {
.name = "exynos-pcie",
.of_match_table = exynos_pcie_of_match,
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 808d1f105417..c8d5c90aa4d4 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -82,6 +82,11 @@ enum imx_pcie_variants {
#define IMX_PCIE_FLAG_HAS_SERDES BIT(6)
#define IMX_PCIE_FLAG_SUPPORT_64BIT BIT(7)
#define IMX_PCIE_FLAG_CPU_ADDR_FIXUP BIT(8)
+/*
+ * Because of ERR005723 (PCIe does not support L2 power down) we need to
+ * workaround suspend resume on some devices which are affected by this errata.
+ */
+#define IMX_PCIE_FLAG_BROKEN_SUSPEND BIT(9)
#define imx_check_flag(pci, val) (pci->drvdata->flags & val)
@@ -1237,9 +1242,19 @@ static int imx_pcie_suspend_noirq(struct device *dev)
return 0;
imx_pcie_msi_save_restore(imx_pcie, true);
- imx_pcie_pm_turnoff(imx_pcie);
- imx_pcie_stop_link(imx_pcie->pci);
- imx_pcie_host_exit(pp);
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
+ /*
+ * The minimum for a workaround would be to set PERST# and to
+ * set the PCIE_TEST_PD flag. However, we can also disable the
+ * clock which saves some power.
+ */
+ imx_pcie_assert_core_reset(imx_pcie);
+ imx_pcie->drvdata->enable_ref_clk(imx_pcie, false);
+ } else {
+ imx_pcie_pm_turnoff(imx_pcie);
+ imx_pcie_stop_link(imx_pcie->pci);
+ imx_pcie_host_exit(pp);
+ }
return 0;
}
@@ -1253,14 +1268,32 @@ static int imx_pcie_resume_noirq(struct device *dev)
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
return 0;
- ret = imx_pcie_host_init(pp);
- if (ret)
- return ret;
- imx_pcie_msi_save_restore(imx_pcie, false);
- dw_pcie_setup_rc(pp);
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
+ ret = imx_pcie->drvdata->enable_ref_clk(imx_pcie, true);
+ if (ret)
+ return ret;
+ ret = imx_pcie_deassert_core_reset(imx_pcie);
+ if (ret)
+ return ret;
+ /*
+ * Using PCIE_TEST_PD seems to disable MSI and powers down the
+ * root complex. This is why we have to setup the rc again and
+ * why we have to restore the MSI register.
+ */
+ ret = dw_pcie_setup_rc(&imx_pcie->pci->pp);
+ if (ret)
+ return ret;
+ imx_pcie_msi_save_restore(imx_pcie, false);
+ } else {
+ ret = imx_pcie_host_init(pp);
+ if (ret)
+ return ret;
+ imx_pcie_msi_save_restore(imx_pcie, false);
+ dw_pcie_setup_rc(pp);
- if (imx_pcie->link_is_up)
- imx_pcie_start_link(imx_pcie->pci);
+ if (imx_pcie->link_is_up)
+ imx_pcie_start_link(imx_pcie->pci);
+ }
return 0;
}
@@ -1485,7 +1518,9 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX6Q] = {
.variant = IMX6Q,
.flags = IMX_PCIE_FLAG_IMX_PHY |
- IMX_PCIE_FLAG_IMX_SPEED_CHANGE,
+ IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
+ IMX_PCIE_FLAG_BROKEN_SUSPEND |
+ IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.dbi_length = 0x200,
.gpr = "fsl,imx6q-iomuxc-gpr",
.clk_names = imx6q_clks,
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 2219b1a866fa..63bd5003da45 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -455,6 +455,17 @@ static void __iomem *ks_pcie_other_map_bus(struct pci_bus *bus,
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
u32 reg;
+ /*
+ * Checking whether the link is up here is a last line of defense
+ * against platforms that forward errors on the system bus as
+ * SError upon PCI configuration transactions issued when the link
+ * is down. This check is racy by definition and does not stop
+ * the system from triggering an SError if the link goes down
+ * after this check is performed.
+ */
+ if (!dw_pcie_link_up(pci))
+ return NULL;
+
reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
CFG_FUNC(PCI_FUNC(devfn));
if (!pci_is_root_bus(bus->parent))
@@ -1093,6 +1104,7 @@ static int ks_pcie_am654_set_mode(struct device *dev,
static const struct ks_pcie_of_data ks_pcie_rc_of_data = {
.host_ops = &ks_pcie_host_ops,
+ .mode = DW_PCIE_RC_TYPE,
.version = DW_PCIE_VER_365A,
};
@@ -1363,7 +1375,7 @@ static void ks_pcie_remove(struct platform_device *pdev)
static struct platform_driver ks_pcie_driver = {
.probe = ks_pcie_probe,
- .remove_new = ks_pcie_remove,
+ .remove = ks_pcie_remove,
.driver = {
.name = "keystone-pcie",
.of_match_table = ks_pcie_of_match,
diff --git a/drivers/pci/controller/dwc/pcie-bt1.c b/drivers/pci/controller/dwc/pcie-bt1.c
index 76d0ddea8007..1340edc18d12 100644
--- a/drivers/pci/controller/dwc/pcie-bt1.c
+++ b/drivers/pci/controller/dwc/pcie-bt1.c
@@ -632,7 +632,7 @@ MODULE_DEVICE_TABLE(of, bt1_pcie_of_match);
static struct platform_driver bt1_pcie_driver = {
.probe = bt1_pcie_probe,
- .remove_new = bt1_pcie_remove,
+ .remove = bt1_pcie_remove,
.driver = {
.name = "bt1-pcie",
.of_match_table = bt1_pcie_of_match,
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 43ba5c6738df..f3ac7d46a855 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -268,6 +268,20 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
return -EINVAL;
}
+static u64 dw_pcie_ep_align_addr(struct pci_epc *epc, u64 pci_addr,
+ size_t *pci_size, size_t *offset)
+{
+ struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ u64 mask = pci->region_align - 1;
+ size_t ofst = pci_addr & mask;
+
+ *pci_size = ALIGN(ofst + *pci_size, epc->mem->window.page_size);
+ *offset = ofst;
+
+ return pci_addr & ~mask;
+}
+
static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
phys_addr_t addr)
{
@@ -280,6 +294,7 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
if (ret < 0)
return;
+ ep->outbound_addr[atu_index] = 0;
dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_OB, atu_index);
clear_bit(atu_index, ep->ob_window_map);
}
@@ -444,6 +459,7 @@ static const struct pci_epc_ops epc_ops = {
.write_header = dw_pcie_ep_write_header,
.set_bar = dw_pcie_ep_set_bar,
.clear_bar = dw_pcie_ep_clear_bar,
+ .align_addr = dw_pcie_ep_align_addr,
.map_addr = dw_pcie_ep_map_addr,
.unmap_addr = dw_pcie_ep_unmap_addr,
.set_msi = dw_pcie_ep_set_msi,
@@ -488,7 +504,8 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
u32 msg_addr_lower, msg_addr_upper, reg;
struct dw_pcie_ep_func *ep_func;
struct pci_epc *epc = ep->epc;
- unsigned int aligned_offset;
+ size_t map_size = sizeof(u32);
+ size_t offset;
u16 msg_ctrl, msg_data;
bool has_upper;
u64 msg_addr;
@@ -516,14 +533,13 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
}
msg_addr = ((u64)msg_addr_upper) << 32 | msg_addr_lower;
- aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
- msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size);
+ msg_addr = dw_pcie_ep_align_addr(epc, msg_addr, &map_size, &offset);
ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr,
- epc->mem->window.page_size);
+ map_size);
if (ret)
return ret;
- writel(msg_data | (interrupt_num - 1), ep->msi_mem + aligned_offset);
+ writel(msg_data | (interrupt_num - 1), ep->msi_mem + offset);
dw_pcie_ep_unmap_addr(epc, func_no, 0, ep->msi_mem_phys);
@@ -574,8 +590,9 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
struct pci_epf_msix_tbl *msix_tbl;
struct dw_pcie_ep_func *ep_func;
struct pci_epc *epc = ep->epc;
+ size_t map_size = sizeof(u32);
+ size_t offset;
u32 reg, msg_data, vec_ctrl;
- unsigned int aligned_offset;
u32 tbl_offset;
u64 msg_addr;
int ret;
@@ -600,14 +617,13 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
return -EPERM;
}
- aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
- msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size);
+ msg_addr = dw_pcie_ep_align_addr(epc, msg_addr, &map_size, &offset);
ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr,
- epc->mem->window.page_size);
+ map_size);
if (ret)
return ret;
- writel(msg_data, ep->msi_mem + aligned_offset);
+ writel(msg_data, ep->msi_mem + offset);
dw_pcie_ep_unmap_addr(epc, func_no, 0, ep->msi_mem_phys);
@@ -689,7 +705,7 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
* for 1 MB BAR size only.
*/
for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
- dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
+ dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, BIT(4));
}
dw_pcie_setup(pci);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 3e41865c7290..d2291c3ceb8b 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -474,8 +474,8 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
if (pci_msi_enabled()) {
pp->has_msi_ctrl = !(pp->ops->msi_init ||
- of_property_read_bool(np, "msi-parent") ||
- of_property_read_bool(np, "msi-map"));
+ of_property_present(np, "msi-parent") ||
+ of_property_present(np, "msi-map"));
/*
* For the has_msi_ctrl case the default assignment is handled
diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c
index 7a11c618b9d9..615a0e3e6d7e 100644
--- a/drivers/pci/controller/dwc/pcie-histb.c
+++ b/drivers/pci/controller/dwc/pcie-histb.c
@@ -439,7 +439,7 @@ MODULE_DEVICE_TABLE(of, histb_pcie_of_match);
static struct platform_driver histb_pcie_platform_driver = {
.probe = histb_pcie_probe,
- .remove_new = histb_pcie_remove,
+ .remove = histb_pcie_remove,
.driver = {
.name = "histb-pcie",
.of_match_table = histb_pcie_of_match,
diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c
index 676d2aba4fbd..9b53b8f6f268 100644
--- a/drivers/pci/controller/dwc/pcie-intel-gw.c
+++ b/drivers/pci/controller/dwc/pcie-intel-gw.c
@@ -443,7 +443,7 @@ static const struct of_device_id of_intel_pcie_match[] = {
static struct platform_driver intel_pcie_driver = {
.probe = intel_pcie_probe,
- .remove_new = intel_pcie_remove,
+ .remove = intel_pcie_remove,
.driver = {
.name = "intel-gw-pcie",
.of_match_table = of_intel_pcie_match,
diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c
index 85a2c77b1835..1b2088acb538 100644
--- a/drivers/pci/controller/dwc/pcie-kirin.c
+++ b/drivers/pci/controller/dwc/pcie-kirin.c
@@ -769,7 +769,7 @@ static int kirin_pcie_probe(struct platform_device *pdev)
static struct platform_driver kirin_pcie_driver = {
.probe = kirin_pcie_probe,
- .remove_new = kirin_pcie_remove,
+ .remove = kirin_pcie_remove,
.driver = {
.name = "kirin-pcie",
.of_match_table = kirin_pcie_match,
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
index e588fcc54589..c08f64d7a825 100644
--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
+++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
@@ -396,6 +396,10 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
return ret;
}
+ /* Perform cleanup that requires refclk */
+ pci_epc_deinit_notify(pci->ep.epc);
+ dw_pcie_ep_cleanup(&pci->ep);
+
/* Assert WAKE# to RC to indicate device is ready */
gpiod_set_value_cansleep(pcie_ep->wake, 1);
usleep_range(WAKE_DELAY_US, WAKE_DELAY_US + 500);
@@ -540,8 +544,6 @@ static void qcom_pcie_perst_assert(struct dw_pcie *pci)
{
struct qcom_pcie_ep *pcie_ep = to_pcie_ep(pci);
- pci_epc_deinit_notify(pci->ep.epc);
- dw_pcie_ep_cleanup(&pci->ep);
qcom_pcie_disable_resources(pcie_ep);
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DISABLED;
}
@@ -937,7 +939,7 @@ MODULE_DEVICE_TABLE(of, qcom_pcie_ep_match);
static struct platform_driver qcom_pcie_ep_driver = {
.probe = qcom_pcie_ep_probe,
- .remove_new = qcom_pcie_ep_remove,
+ .remove = qcom_pcie_ep_remove,
.driver = {
.name = "qcom-pcie-ep",
.of_match_table = qcom_pcie_ep_match,
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index ef44a82be058..dc102d8bd58c 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -133,6 +133,7 @@
/* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */
#define PARF_INT_ALL_LINK_UP BIT(13)
+#define PARF_INT_MSI_DEV_0_7 GENMASK(30, 23)
/* PARF_NO_SNOOP_OVERIDE register fields */
#define WR_NO_SNOOP_OVERIDE_EN BIT(1)
@@ -1364,6 +1365,16 @@ static const struct qcom_pcie_ops ops_1_9_0 = {
.config_sid = qcom_pcie_config_sid_1_9_0,
};
+/* Qcom IP rev.: 1.21.0 Synopsys IP rev.: 5.60a */
+static const struct qcom_pcie_ops ops_1_21_0 = {
+ .get_resources = qcom_pcie_get_resources_2_7_0,
+ .init = qcom_pcie_init_2_7_0,
+ .post_init = qcom_pcie_post_init_2_7_0,
+ .host_post_init = qcom_pcie_host_post_init_2_7_0,
+ .deinit = qcom_pcie_deinit_2_7_0,
+ .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
+};
+
/* Qcom IP rev.: 2.9.0 Synopsys IP rev.: 5.00a */
static const struct qcom_pcie_ops ops_2_9_0 = {
.get_resources = qcom_pcie_get_resources_2_9_0,
@@ -1411,7 +1422,7 @@ static const struct qcom_pcie_cfg cfg_2_9_0 = {
};
static const struct qcom_pcie_cfg cfg_sc8280xp = {
- .ops = &ops_1_9_0,
+ .ops = &ops_1_21_0,
.no_l0s = true,
};
@@ -1716,7 +1727,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
goto err_host_deinit;
}
- writel_relaxed(PARF_INT_ALL_LINK_UP, pcie->parf + PARF_INT_ALL_MASK);
+ writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_MSI_DEV_0_7,
+ pcie->parf + PARF_INT_ALL_MASK);
}
qcom_pcie_icc_opp_update(pcie);
@@ -1828,6 +1840,7 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },
{ .compatible = "qcom,pcie-ipq8074", .data = &cfg_2_3_3 },
{ .compatible = "qcom,pcie-ipq8074-gen3", .data = &cfg_2_9_0 },
+ { .compatible = "qcom,pcie-ipq9574", .data = &cfg_2_9_0 },
{ .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 },
{ .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 },
{ .compatible = "qcom,pcie-sa8540p", .data = &cfg_sc8280xp },
@@ -1843,7 +1856,7 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &cfg_1_9_0 },
{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 },
{ .compatible = "qcom,pcie-sm8550", .data = &cfg_1_9_0 },
- { .compatible = "qcom,pcie-x1e80100", .data = &cfg_1_9_0 },
+ { .compatible = "qcom,pcie-x1e80100", .data = &cfg_sc8280xp },
{ }
};
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index 3a5511c3f7d9..fc872dd35029 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -775,7 +775,7 @@ static struct platform_driver rcar_gen4_pcie_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = rcar_gen4_pcie_probe,
- .remove_new = rcar_gen4_pcie_remove,
+ .remove = rcar_gen4_pcie_remove,
};
module_platform_driver(rcar_gen4_pcie_driver);
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index c1394f2ab63f..5103995cd6c7 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1704,9 +1704,6 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie)
if (ret)
dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret);
- pci_epc_deinit_notify(pcie->pci.ep.epc);
- dw_pcie_ep_cleanup(&pcie->pci.ep);
-
reset_control_assert(pcie->core_rst);
tegra_pcie_disable_phy(pcie);
@@ -1785,6 +1782,10 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
goto fail_phy;
}
+ /* Perform cleanup that requires refclk */
+ pci_epc_deinit_notify(pcie->pci.ep.epc);
+ dw_pcie_ep_cleanup(&pcie->pci.ep);
+
/* Clear any stale interrupt statuses */
appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L0);
appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_0_0);
@@ -2493,7 +2494,7 @@ static const struct dev_pm_ops tegra_pcie_dw_pm_ops = {
static struct platform_driver tegra_pcie_dw_driver = {
.probe = tegra_pcie_dw_probe,
- .remove_new = tegra_pcie_dw_remove,
+ .remove = tegra_pcie_dw_remove,
.shutdown = tegra_pcie_dw_shutdown,
.driver = {
.name = "tegra194-pcie",
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index a598a98247ce..a29796cce420 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -1996,7 +1996,7 @@ static struct platform_driver advk_pcie_driver = {
.of_match_table = advk_pcie_of_match_table,
},
.probe = advk_pcie_probe,
- .remove_new = advk_pcie_remove,
+ .remove = advk_pcie_remove,
};
module_platform_driver(advk_pcie_driver);
diff --git a/drivers/pci/controller/pci-host-generic.c b/drivers/pci/controller/pci-host-generic.c
index 5f06f94db7b1..4051b9b61dac 100644
--- a/drivers/pci/controller/pci-host-generic.c
+++ b/drivers/pci/controller/pci-host-generic.c
@@ -82,7 +82,7 @@ static struct platform_driver gen_pci_driver = {
.of_match_table = gen_pci_of_match,
},
.probe = pci_host_common_probe,
- .remove_new = pci_host_common_remove,
+ .remove = pci_host_common_remove,
};
module_platform_driver(gen_pci_driver);
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 29fe09c99e7d..46d3afe1d308 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -1727,7 +1727,7 @@ static struct platform_driver mvebu_pcie_driver = {
.pm = &mvebu_pcie_pm_ops,
},
.probe = mvebu_pcie_probe,
- .remove_new = mvebu_pcie_remove,
+ .remove = mvebu_pcie_remove,
};
module_platform_driver(mvebu_pcie_driver);
diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
index d7517c3976e7..b3cdbc5927de 100644
--- a/drivers/pci/controller/pci-tegra.c
+++ b/drivers/pci/controller/pci-tegra.c
@@ -1460,7 +1460,7 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
pcie->cs = *res;
/* constrain configuration space to 4 KiB */
- pcie->cs.end = pcie->cs.start + SZ_4K - 1;
+ resource_set_size(&pcie->cs, SZ_4K);
pcie->cfg = devm_ioremap_resource(dev, &pcie->cs);
if (IS_ERR(pcie->cfg)) {
@@ -2800,6 +2800,6 @@ static struct platform_driver tegra_pcie_driver = {
.pm = &tegra_pcie_pm_ops,
},
.probe = tegra_pcie_probe,
- .remove_new = tegra_pcie_remove,
+ .remove = tegra_pcie_remove,
};
module_platform_driver(tegra_pcie_driver);
diff --git a/drivers/pci/controller/pci-thunder-pem.c b/drivers/pci/controller/pci-thunder-pem.c
index 06a9855cb431..f1bd5de67997 100644
--- a/drivers/pci/controller/pci-thunder-pem.c
+++ b/drivers/pci/controller/pci-thunder-pem.c
@@ -400,9 +400,9 @@ static int thunder_pem_acpi_init(struct pci_config_window *cfg)
* Reserve 64K size PEM specific resources. The full 16M range
* size is required for thunder_pem_init() call.
*/
- res_pem->end = res_pem->start + SZ_64K - 1;
+ resource_set_size(res_pem, SZ_64K);
thunder_pem_reserve_range(dev, root->segment, res_pem);
- res_pem->end = res_pem->start + SZ_16M - 1;
+ resource_set_size(res_pem, SZ_16M);
/* Reserve PCI configuration space as well. */
thunder_pem_reserve_range(dev, root->segment, &cfg->res);
diff --git a/drivers/pci/controller/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c
index 3ce38dfd0d29..88c0977bc41a 100644
--- a/drivers/pci/controller/pci-xgene-msi.c
+++ b/drivers/pci/controller/pci-xgene-msi.c
@@ -518,7 +518,7 @@ static struct platform_driver xgene_msi_driver = {
.of_match_table = xgene_msi_match_table,
},
.probe = xgene_msi_probe,
- .remove_new = xgene_msi_remove,
+ .remove = xgene_msi_remove,
};
static int __init xgene_pcie_msi_init(void)
diff --git a/drivers/pci/controller/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c
index e36a6e158d23..e1cee3c0575f 100644
--- a/drivers/pci/controller/pcie-altera-msi.c
+++ b/drivers/pci/controller/pcie-altera-msi.c
@@ -267,7 +267,7 @@ static struct platform_driver altera_msi_driver = {
.of_match_table = altera_msi_of_match,
},
.probe = altera_msi_probe,
- .remove_new = altera_msi_remove,
+ .remove = altera_msi_remove,
};
static int __init altera_msi_init(void)
diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
index 650b2dd81c48..eb55a7f8573a 100644
--- a/drivers/pci/controller/pcie-altera.c
+++ b/drivers/pci/controller/pcie-altera.c
@@ -815,10 +815,10 @@ static void altera_pcie_remove(struct platform_device *pdev)
}
static struct platform_driver altera_pcie_driver = {
- .probe = altera_pcie_probe,
- .remove_new = altera_pcie_remove,
+ .probe = altera_pcie_probe,
+ .remove = altera_pcie_remove,
.driver = {
- .name = "altera-pcie",
+ .name = "altera-pcie",
.of_match_table = altera_pcie_of_match,
},
};
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index 9321280f6edb..e733a27dc8df 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -1928,7 +1928,7 @@ static const struct dev_pm_ops brcm_pcie_pm_ops = {
static struct platform_driver brcm_pcie_driver = {
.probe = brcm_pcie_probe,
- .remove_new = brcm_pcie_remove,
+ .remove = brcm_pcie_remove,
.driver = {
.name = "brcm-pcie",
.of_match_table = brcm_pcie_match,
diff --git a/drivers/pci/controller/pcie-hisi-error.c b/drivers/pci/controller/pcie-hisi-error.c
index ad9d5ffcd9e3..aaf1ed2b6e59 100644
--- a/drivers/pci/controller/pcie-hisi-error.c
+++ b/drivers/pci/controller/pcie-hisi-error.c
@@ -317,7 +317,7 @@ static struct platform_driver hisi_pcie_error_handler_driver = {
.acpi_match_table = hisi_pcie_acpi_match,
},
.probe = hisi_pcie_error_handler_probe,
- .remove_new = hisi_pcie_error_handler_remove,
+ .remove = hisi_pcie_error_handler_remove,
};
module_platform_driver(hisi_pcie_error_handler_driver);
diff --git a/drivers/pci/controller/pcie-iproc-platform.c b/drivers/pci/controller/pcie-iproc-platform.c
index 4e6aa882a567..0cb78c583c7e 100644
--- a/drivers/pci/controller/pcie-iproc-platform.c
+++ b/drivers/pci/controller/pcie-iproc-platform.c
@@ -134,7 +134,7 @@ static struct platform_driver iproc_pltfm_pcie_driver = {
.of_match_table = of_match_ptr(iproc_pcie_of_match_table),
},
.probe = iproc_pltfm_pcie_probe,
- .remove_new = iproc_pltfm_pcie_remove,
+ .remove = iproc_pltfm_pcie_remove,
.shutdown = iproc_pltfm_pcie_shutdown,
};
module_platform_driver(iproc_pltfm_pcie_driver);
diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
index 66ce4b5d309b..be52e3a123ab 100644
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -28,7 +28,12 @@
#include "../pci.h"
+#define PCIE_BASE_CFG_REG 0x14
+#define PCIE_BASE_CFG_SPEED GENMASK(15, 8)
+
#define PCIE_SETTING_REG 0x80
+#define PCIE_SETTING_LINK_WIDTH GENMASK(11, 8)
+#define PCIE_SETTING_GEN_SUPPORT GENMASK(14, 12)
#define PCIE_PCI_IDS_1 0x9c
#define PCI_CLASS(class) (class << 8)
#define PCIE_RC_MODE BIT(0)
@@ -125,6 +130,9 @@
struct mtk_gen3_pcie;
+#define PCIE_CONF_LINK2_CTL_STS (PCIE_CFG_OFFSET_ADDR + 0xb0)
+#define PCIE_CONF_LINK2_LCR2_LINK_SPEED GENMASK(3, 0)
+
/**
* struct mtk_gen3_pcie_pdata - differentiate between host generations
* @power_up: pcie power_up callback
@@ -160,6 +168,8 @@ struct mtk_msi_set {
* @phy: PHY controller block
* @clks: PCIe clocks
* @num_clks: PCIe clocks count for this port
+ * @max_link_speed: Maximum link speed (PCIe Gen) for this port
+ * @num_lanes: Number of PCIe lanes for this port
* @irq: PCIe controller interrupt number
* @saved_irq_state: IRQ enable state saved at suspend time
* @irq_lock: lock protecting IRQ register access
@@ -180,6 +190,8 @@ struct mtk_gen3_pcie {
struct phy *phy;
struct clk_bulk_data *clks;
int num_clks;
+ u8 max_link_speed;
+ u8 num_lanes;
int irq;
u32 saved_irq_state;
@@ -381,11 +393,35 @@ static int mtk_pcie_startup_port(struct mtk_gen3_pcie *pcie)
int err;
u32 val;
- /* Set as RC mode */
+ /* Set as RC mode and set controller PCIe Gen speed restriction, if any */
val = readl_relaxed(pcie->base + PCIE_SETTING_REG);
val |= PCIE_RC_MODE;
+ if (pcie->max_link_speed) {
+ val &= ~PCIE_SETTING_GEN_SUPPORT;
+
+ /* Can enable link speed support only from Gen2 onwards */
+ if (pcie->max_link_speed >= 2)
+ val |= FIELD_PREP(PCIE_SETTING_GEN_SUPPORT,
+ GENMASK(pcie->max_link_speed - 2, 0));
+ }
+ if (pcie->num_lanes) {
+ val &= ~PCIE_SETTING_LINK_WIDTH;
+
+ /* Zero means one lane, each bit activates x2/x4/x8/x16 */
+ if (pcie->num_lanes > 1)
+ val |= FIELD_PREP(PCIE_SETTING_LINK_WIDTH,
+ GENMASK(fls(pcie->num_lanes >> 2), 0));
+ }
writel_relaxed(val, pcie->base + PCIE_SETTING_REG);
+ /* Set Link Control 2 (LNKCTL2) speed restriction, if any */
+ if (pcie->max_link_speed) {
+ val = readl_relaxed(pcie->base + PCIE_CONF_LINK2_CTL_STS);
+ val &= ~PCIE_CONF_LINK2_LCR2_LINK_SPEED;
+ val |= FIELD_PREP(PCIE_CONF_LINK2_LCR2_LINK_SPEED, pcie->max_link_speed);
+ writel_relaxed(val, pcie->base + PCIE_CONF_LINK2_CTL_STS);
+ }
+
/* Set class code */
val = readl_relaxed(pcie->base + PCIE_PCI_IDS_1);
val &= ~GENMASK(31, 8);
@@ -813,6 +849,7 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
struct device *dev = pcie->dev;
struct platform_device *pdev = to_platform_device(dev);
struct resource *regs;
+ u32 num_lanes;
regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie-mac");
if (!regs)
@@ -858,6 +895,14 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
return pcie->num_clks;
}
+ ret = of_property_read_u32(dev->of_node, "num-lanes", &num_lanes);
+ if (ret == 0) {
+ if (num_lanes == 0 || num_lanes > 16 || (num_lanes != 1 && num_lanes % 2))
+ dev_warn(dev, "invalid num-lanes, using controller defaults\n");
+ else
+ pcie->num_lanes = num_lanes;
+ }
+
return 0;
}
@@ -1004,9 +1049,21 @@ static void mtk_pcie_power_down(struct mtk_gen3_pcie *pcie)
reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
}
+static int mtk_pcie_get_controller_max_link_speed(struct mtk_gen3_pcie *pcie)
+{
+ u32 val;
+ int ret;
+
+ val = readl_relaxed(pcie->base + PCIE_BASE_CFG_REG);
+ val = FIELD_GET(PCIE_BASE_CFG_SPEED, val);
+ ret = fls(val);
+
+ return ret > 0 ? ret : -EINVAL;
+}
+
static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
{
- int err;
+ int err, max_speed;
err = mtk_pcie_parse_port(pcie);
if (err)
@@ -1031,6 +1088,20 @@ static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
if (err)
return err;
+ err = of_pci_get_max_link_speed(pcie->dev->of_node);
+ if (err) {
+ /* Get the maximum speed supported by the controller */
+ max_speed = mtk_pcie_get_controller_max_link_speed(pcie);
+
+ /* Set max_link_speed only if the controller supports it */
+ if (max_speed >= 0 && max_speed <= err) {
+ pcie->max_link_speed = err;
+ dev_info(pcie->dev,
+ "maximum controller link speed Gen%d, overriding to Gen%u",
+ max_speed, pcie->max_link_speed);
+ }
+ }
+
/* Try link up */
err = mtk_pcie_startup_port(pcie);
if (err)
@@ -1225,7 +1296,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_of_match);
static struct platform_driver mtk_pcie_driver = {
.probe = mtk_pcie_probe,
- .remove_new = mtk_pcie_remove,
+ .remove = mtk_pcie_remove,
.driver = {
.name = "mtk-pcie-gen3",
.of_match_table = mtk_pcie_of_match,
diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 7f7d04c2ea57..3bcfc4e58ba2 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -1235,7 +1235,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
static struct platform_driver mtk_pcie_driver = {
.probe = mtk_pcie_probe,
- .remove_new = mtk_pcie_remove,
+ .remove = mtk_pcie_remove,
.driver = {
.name = "mtk-pcie",
.of_match_table = mtk_pcie_ids,
diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c
index 9b4754a45515..776caa0b1011 100644
--- a/drivers/pci/controller/pcie-mt7621.c
+++ b/drivers/pci/controller/pcie-mt7621.c
@@ -541,7 +541,7 @@ MODULE_DEVICE_TABLE(of, mt7621_pcie_ids);
static struct platform_driver mt7621_pcie_driver = {
.probe = mt7621_pcie_probe,
- .remove_new = mt7621_pcie_remove,
+ .remove = mt7621_pcie_remove,
.driver = {
.name = "mt7621-pci",
.of_match_table = mt7621_pcie_ids,
diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
index 3dd653f3d784..7c92eada04af 100644
--- a/drivers/pci/controller/pcie-rcar-host.c
+++ b/drivers/pci/controller/pcie-rcar-host.c
@@ -796,8 +796,8 @@ static int rcar_pcie_enable_msi(struct rcar_pcie_host *host)
rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
/*
- * Setup MSI data target using RC base address address, which
- * is guaranteed to be in the low 32bit range on any R-Car HW.
+ * Setup MSI data target using RC base address, which is guaranteed
+ * to be in the low 32bit range on any R-Car HW.
*/
rcar_pci_write_reg(pcie, lower_32_bits(res.start) | MSIFE, PCIEMSIALR);
rcar_pci_write_reg(pcie, upper_32_bits(res.start), PCIEMSIAUR);
diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
index 136274533656..1064b7b06cef 100644
--- a/drivers/pci/controller/pcie-rockchip-ep.c
+++ b/drivers/pci/controller/pcie-rockchip-ep.c
@@ -10,12 +10,16 @@
#include <linux/configfs.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
+#include <linux/irq.h>
#include <linux/of.h>
#include <linux/pci-epc.h>
#include <linux/platform_device.h>
#include <linux/pci-epf.h>
#include <linux/sizes.h>
+#include <linux/workqueue.h>
#include "pcie-rockchip.h"
@@ -48,6 +52,10 @@ struct rockchip_pcie_ep {
u64 irq_pci_addr;
u8 irq_pci_fn;
u8 irq_pending;
+ int perst_irq;
+ bool perst_asserted;
+ bool link_up;
+ struct delayed_work link_training;
};
static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip,
@@ -63,15 +71,25 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip,
ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region));
}
+static int rockchip_pcie_ep_ob_atu_num_bits(struct rockchip_pcie *rockchip,
+ u64 pci_addr, size_t size)
+{
+ int num_pass_bits = fls64(pci_addr ^ (pci_addr + size - 1));
+
+ return clamp(num_pass_bits,
+ ROCKCHIP_PCIE_AT_MIN_NUM_BITS,
+ ROCKCHIP_PCIE_AT_MAX_NUM_BITS);
+}
+
static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn,
u32 r, u64 cpu_addr, u64 pci_addr,
size_t size)
{
- int num_pass_bits = fls64(size - 1);
+ int num_pass_bits;
u32 addr0, addr1, desc0;
- if (num_pass_bits < 8)
- num_pass_bits = 8;
+ num_pass_bits = rockchip_pcie_ep_ob_atu_num_bits(rockchip,
+ pci_addr, size);
addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
(lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
@@ -228,6 +246,28 @@ static inline u32 rockchip_ob_region(phys_addr_t addr)
return (addr >> ilog2(SZ_1M)) & 0x1f;
}
+static u64 rockchip_pcie_ep_align_addr(struct pci_epc *epc, u64 pci_addr,
+ size_t *pci_size, size_t *addr_offset)
+{
+ struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
+ size_t size = *pci_size;
+ u64 offset, mask;
+ int num_bits;
+
+ num_bits = rockchip_pcie_ep_ob_atu_num_bits(&ep->rockchip,
+ pci_addr, size);
+ mask = (1ULL << num_bits) - 1;
+
+ offset = pci_addr & mask;
+ if (size + offset > SZ_1M)
+ size = SZ_1M - offset;
+
+ *pci_size = ALIGN(offset + size, ROCKCHIP_PCIE_AT_SIZE_ALIGN);
+ *addr_offset = offset;
+
+ return pci_addr & ~mask;
+}
+
static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn,
phys_addr_t addr, u64 pci_addr,
size_t size)
@@ -236,6 +276,9 @@ static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn,
struct rockchip_pcie *pcie = &ep->rockchip;
u32 r = rockchip_ob_region(addr);
+ if (test_bit(r, &ep->ob_region_map))
+ return -EBUSY;
+
rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size);
set_bit(r, &ep->ob_region_map);
@@ -249,13 +292,9 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
{
struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
struct rockchip_pcie *rockchip = &ep->rockchip;
- u32 r;
-
- for (r = 0; r < ep->max_regions; r++)
- if (ep->ob_addr[r] == addr)
- break;
+ u32 r = rockchip_ob_region(addr);
- if (r == ep->max_regions)
+ if (addr != ep->ob_addr[r] || !test_bit(r, &ep->ob_region_map))
return;
rockchip_pcie_clear_ep_ob_atu(rockchip, r);
@@ -351,9 +390,10 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn,
{
struct rockchip_pcie *rockchip = &ep->rockchip;
u32 flags, mme, data, data_mask;
+ size_t irq_pci_size, offset;
+ u64 irq_pci_addr;
u8 msi_count;
u64 pci_addr;
- u32 r;
/* Check MSI enable bit */
flags = rockchip_pcie_read(&ep->rockchip,
@@ -389,18 +429,21 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn,
PCI_MSI_ADDRESS_LO);
/* Set the outbound region if needed. */
- if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) ||
+ irq_pci_size = ~PCIE_ADDR_MASK + 1;
+ irq_pci_addr = rockchip_pcie_ep_align_addr(ep->epc,
+ pci_addr & PCIE_ADDR_MASK,
+ &irq_pci_size, &offset);
+ if (unlikely(ep->irq_pci_addr != irq_pci_addr ||
ep->irq_pci_fn != fn)) {
- r = rockchip_ob_region(ep->irq_phys_addr);
- rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r,
- ep->irq_phys_addr,
- pci_addr & PCIE_ADDR_MASK,
- ~PCIE_ADDR_MASK + 1);
- ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK);
+ rockchip_pcie_prog_ep_ob_atu(rockchip, fn,
+ rockchip_ob_region(ep->irq_phys_addr),
+ ep->irq_phys_addr,
+ irq_pci_addr, irq_pci_size);
+ ep->irq_pci_addr = irq_pci_addr;
ep->irq_pci_fn = fn;
}
- writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK));
+ writew(data, ep->irq_cpu_addr + offset + (pci_addr & ~PCIE_ADDR_MASK));
return 0;
}
@@ -432,14 +475,222 @@ static int rockchip_pcie_ep_start(struct pci_epc *epc)
rockchip_pcie_write(rockchip, cfg, PCIE_CORE_PHY_FUNC_CFG);
+ if (rockchip->perst_gpio)
+ enable_irq(ep->perst_irq);
+
+ /* Enable configuration and start link training */
+ rockchip_pcie_write(rockchip,
+ PCIE_CLIENT_LINK_TRAIN_ENABLE |
+ PCIE_CLIENT_CONF_ENABLE,
+ PCIE_CLIENT_CONFIG);
+
+ if (!rockchip->perst_gpio)
+ schedule_delayed_work(&ep->link_training, 0);
+
+ return 0;
+}
+
+static void rockchip_pcie_ep_stop(struct pci_epc *epc)
+{
+ struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+
+ if (rockchip->perst_gpio) {
+ ep->perst_asserted = true;
+ disable_irq(ep->perst_irq);
+ }
+
+ cancel_delayed_work_sync(&ep->link_training);
+
+ /* Stop link training and disable configuration */
+ rockchip_pcie_write(rockchip,
+ PCIE_CLIENT_CONF_DISABLE |
+ PCIE_CLIENT_LINK_TRAIN_DISABLE,
+ PCIE_CLIENT_CONFIG);
+}
+
+static void rockchip_pcie_ep_retrain_link(struct rockchip_pcie *rockchip)
+{
+ u32 status;
+
+ status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_LCS);
+ status |= PCI_EXP_LNKCTL_RL;
+ rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_LCS);
+}
+
+static bool rockchip_pcie_ep_link_up(struct rockchip_pcie *rockchip)
+{
+ u32 val = rockchip_pcie_read(rockchip, PCIE_CLIENT_BASIC_STATUS1);
+
+ return PCIE_LINK_UP(val);
+}
+
+static void rockchip_pcie_ep_link_training(struct work_struct *work)
+{
+ struct rockchip_pcie_ep *ep =
+ container_of(work, struct rockchip_pcie_ep, link_training.work);
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+ struct device *dev = rockchip->dev;
+ u32 val;
+ int ret;
+
+ /* Enable Gen1 training and wait for its completion */
+ ret = readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL,
+ val, PCIE_LINK_TRAINING_DONE(val), 50,
+ LINK_TRAIN_TIMEOUT);
+ if (ret)
+ goto again;
+
+ /* Make sure that the link is up */
+ ret = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1,
+ val, PCIE_LINK_UP(val), 50,
+ LINK_TRAIN_TIMEOUT);
+ if (ret)
+ goto again;
+
+ /*
+ * Check the current speed: if gen2 speed was requested and we are not
+ * at gen2 speed yet, retrain again for gen2.
+ */
+ val = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
+ if (!PCIE_LINK_IS_GEN2(val) && rockchip->link_gen == 2) {
+ /* Enable retrain for gen2 */
+ rockchip_pcie_ep_retrain_link(rockchip);
+ readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL,
+ val, PCIE_LINK_IS_GEN2(val), 50,
+ LINK_TRAIN_TIMEOUT);
+ }
+
+ /* Check again that the link is up */
+ if (!rockchip_pcie_ep_link_up(rockchip))
+ goto again;
+
+ /*
+ * If PERST# was asserted while polling the link, do not notify
+ * the function.
+ */
+ if (ep->perst_asserted)
+ return;
+
+ val = rockchip_pcie_read(rockchip, PCIE_CLIENT_BASIC_STATUS0);
+ dev_info(dev,
+ "link up (negotiated speed: %sGT/s, width: x%lu)\n",
+ (val & PCIE_CLIENT_NEG_LINK_SPEED) ? "5" : "2.5",
+ ((val & PCIE_CLIENT_NEG_LINK_WIDTH_MASK) >>
+ PCIE_CLIENT_NEG_LINK_WIDTH_SHIFT) << 1);
+
+ /* Notify the function */
+ pci_epc_linkup(ep->epc);
+ ep->link_up = true;
+
+ return;
+
+again:
+ schedule_delayed_work(&ep->link_training, msecs_to_jiffies(5));
+}
+
+static void rockchip_pcie_ep_perst_assert(struct rockchip_pcie_ep *ep)
+{
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+
+ dev_dbg(rockchip->dev, "PERST# asserted, link down\n");
+
+ if (ep->perst_asserted)
+ return;
+
+ ep->perst_asserted = true;
+
+ cancel_delayed_work_sync(&ep->link_training);
+
+ if (ep->link_up) {
+ pci_epc_linkdown(ep->epc);
+ ep->link_up = false;
+ }
+}
+
+static void rockchip_pcie_ep_perst_deassert(struct rockchip_pcie_ep *ep)
+{
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+
+ dev_dbg(rockchip->dev, "PERST# de-asserted, starting link training\n");
+
+ if (!ep->perst_asserted)
+ return;
+
+ ep->perst_asserted = false;
+
+ /* Enable link re-training */
+ rockchip_pcie_ep_retrain_link(rockchip);
+
+ /* Start link training */
+ schedule_delayed_work(&ep->link_training, 0);
+}
+
+static irqreturn_t rockchip_pcie_ep_perst_irq_thread(int irq, void *data)
+{
+ struct pci_epc *epc = data;
+ struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+ u32 perst = gpiod_get_value(rockchip->perst_gpio);
+
+ if (perst)
+ rockchip_pcie_ep_perst_assert(ep);
+ else
+ rockchip_pcie_ep_perst_deassert(ep);
+
+ irq_set_irq_type(ep->perst_irq,
+ (perst ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW));
+
+ return IRQ_HANDLED;
+}
+
+static int rockchip_pcie_ep_setup_irq(struct pci_epc *epc)
+{
+ struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+ struct device *dev = rockchip->dev;
+ int ret;
+
+ if (!rockchip->perst_gpio)
+ return 0;
+
+ /* PCIe reset interrupt */
+ ep->perst_irq = gpiod_to_irq(rockchip->perst_gpio);
+ if (ep->perst_irq < 0) {
+ dev_err(dev,
+ "failed to get IRQ for PERST# GPIO: %d\n",
+ ep->perst_irq);
+
+ return ep->perst_irq;
+ }
+
+ /*
+ * The perst_gpio is active low, so when it is inactive on start, it
+ * is high and will trigger the perst_irq handler. So treat this initial
+ * IRQ as a dummy one by faking the host asserting PERST#.
+ */
+ ep->perst_asserted = true;
+ irq_set_status_flags(ep->perst_irq, IRQ_NOAUTOEN);
+ ret = devm_request_threaded_irq(dev, ep->perst_irq, NULL,
+ rockchip_pcie_ep_perst_irq_thread,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "pcie-ep-perst", epc);
+ if (ret) {
+ dev_err(dev,
+ "failed to request IRQ for PERST# GPIO: %d\n",
+ ret);
+
+ return ret;
+ }
+
return 0;
}
static const struct pci_epc_features rockchip_pcie_epc_features = {
- .linkup_notifier = false,
+ .linkup_notifier = true,
.msi_capable = true,
.msix_capable = false,
- .align = 256,
+ .align = ROCKCHIP_PCIE_AT_SIZE_ALIGN,
};
static const struct pci_epc_features*
@@ -452,17 +703,19 @@ static const struct pci_epc_ops rockchip_pcie_epc_ops = {
.write_header = rockchip_pcie_ep_write_header,
.set_bar = rockchip_pcie_ep_set_bar,
.clear_bar = rockchip_pcie_ep_clear_bar,
+ .align_addr = rockchip_pcie_ep_align_addr,
.map_addr = rockchip_pcie_ep_map_addr,
.unmap_addr = rockchip_pcie_ep_unmap_addr,
.set_msi = rockchip_pcie_ep_set_msi,
.get_msi = rockchip_pcie_ep_get_msi,
.raise_irq = rockchip_pcie_ep_raise_irq,
.start = rockchip_pcie_ep_start,
+ .stop = rockchip_pcie_ep_stop,
.get_features = rockchip_pcie_ep_get_features,
};
-static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip,
- struct rockchip_pcie_ep *ep)
+static int rockchip_pcie_ep_get_resources(struct rockchip_pcie *rockchip,
+ struct rockchip_pcie_ep *ep)
{
struct device *dev = rockchip->dev;
int err;
@@ -496,91 +749,63 @@ static const struct of_device_id rockchip_pcie_ep_of_match[] = {
{},
};
-static int rockchip_pcie_ep_probe(struct platform_device *pdev)
+static int rockchip_pcie_ep_init_ob_mem(struct rockchip_pcie_ep *ep)
{
- struct device *dev = &pdev->dev;
- struct rockchip_pcie_ep *ep;
- struct rockchip_pcie *rockchip;
- struct pci_epc *epc;
- size_t max_regions;
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+ struct device *dev = rockchip->dev;
struct pci_epc_mem_window *windows = NULL;
int err, i;
- u32 cfg_msi, cfg_msix_cp;
-
- ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
- if (!ep)
- return -ENOMEM;
- rockchip = &ep->rockchip;
- rockchip->is_rc = false;
- rockchip->dev = dev;
-
- epc = devm_pci_epc_create(dev, &rockchip_pcie_epc_ops);
- if (IS_ERR(epc)) {
- dev_err(dev, "failed to create epc device\n");
- return PTR_ERR(epc);
- }
-
- ep->epc = epc;
- epc_set_drvdata(epc, ep);
-
- err = rockchip_pcie_parse_ep_dt(rockchip, ep);
- if (err)
- return err;
-
- err = rockchip_pcie_enable_clocks(rockchip);
- if (err)
- return err;
-
- err = rockchip_pcie_init_port(rockchip);
- if (err)
- goto err_disable_clocks;
-
- /* Establish the link automatically */
- rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE,
- PCIE_CLIENT_CONFIG);
-
- max_regions = ep->max_regions;
- ep->ob_addr = devm_kcalloc(dev, max_regions, sizeof(*ep->ob_addr),
+ ep->ob_addr = devm_kcalloc(dev, ep->max_regions, sizeof(*ep->ob_addr),
GFP_KERNEL);
- if (!ep->ob_addr) {
- err = -ENOMEM;
- goto err_uninit_port;
- }
-
- /* Only enable function 0 by default */
- rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG);
+ if (!ep->ob_addr)
+ return -ENOMEM;
windows = devm_kcalloc(dev, ep->max_regions,
sizeof(struct pci_epc_mem_window), GFP_KERNEL);
- if (!windows) {
- err = -ENOMEM;
- goto err_uninit_port;
- }
+ if (!windows)
+ return -ENOMEM;
+
for (i = 0; i < ep->max_regions; i++) {
windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i);
windows[i].size = SZ_1M;
windows[i].page_size = SZ_1M;
}
- err = pci_epc_multi_mem_init(epc, windows, ep->max_regions);
+ err = pci_epc_multi_mem_init(ep->epc, windows, ep->max_regions);
devm_kfree(dev, windows);
if (err < 0) {
dev_err(dev, "failed to initialize the memory space\n");
- goto err_uninit_port;
+ return err;
}
- ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr,
+ ep->irq_cpu_addr = pci_epc_mem_alloc_addr(ep->epc, &ep->irq_phys_addr,
SZ_1M);
if (!ep->irq_cpu_addr) {
dev_err(dev, "failed to reserve memory space for MSI\n");
- err = -ENOMEM;
goto err_epc_mem_exit;
}
ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR;
+ return 0;
+
+err_epc_mem_exit:
+ pci_epc_mem_exit(ep->epc);
+
+ return err;
+}
+
+static void rockchip_pcie_ep_exit_ob_mem(struct rockchip_pcie_ep *ep)
+{
+ pci_epc_mem_exit(ep->epc);
+}
+
+static void rockchip_pcie_ep_hide_broken_msix_cap(struct rockchip_pcie *rockchip)
+{
+ u32 cfg_msi, cfg_msix_cp;
+
/*
* MSI-X is not supported but the controller still advertises the MSI-X
* capability by default, which can lead to the Root Complex side
@@ -603,19 +828,68 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
rockchip_pcie_write(rockchip, cfg_msi,
PCIE_EP_CONFIG_BASE + ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
+}
- rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE,
- PCIE_CLIENT_CONFIG);
+static int rockchip_pcie_ep_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rockchip_pcie_ep *ep;
+ struct rockchip_pcie *rockchip;
+ struct pci_epc *epc;
+ int err;
+
+ ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
+ if (!ep)
+ return -ENOMEM;
+
+ rockchip = &ep->rockchip;
+ rockchip->is_rc = false;
+ rockchip->dev = dev;
+ INIT_DELAYED_WORK(&ep->link_training, rockchip_pcie_ep_link_training);
+
+ epc = devm_pci_epc_create(dev, &rockchip_pcie_epc_ops);
+ if (IS_ERR(epc)) {
+ dev_err(dev, "failed to create EPC device\n");
+ return PTR_ERR(epc);
+ }
+
+ ep->epc = epc;
+ epc_set_drvdata(epc, ep);
+
+ err = rockchip_pcie_ep_get_resources(rockchip, ep);
+ if (err)
+ return err;
+
+ err = rockchip_pcie_ep_init_ob_mem(ep);
+ if (err)
+ return err;
+
+ err = rockchip_pcie_enable_clocks(rockchip);
+ if (err)
+ goto err_exit_ob_mem;
+
+ err = rockchip_pcie_init_port(rockchip);
+ if (err)
+ goto err_disable_clocks;
+
+ rockchip_pcie_ep_hide_broken_msix_cap(rockchip);
+
+ /* Only enable function 0 by default */
+ rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG);
pci_epc_init_notify(epc);
+ err = rockchip_pcie_ep_setup_irq(epc);
+ if (err < 0)
+ goto err_uninit_port;
+
return 0;
-err_epc_mem_exit:
- pci_epc_mem_exit(epc);
err_uninit_port:
rockchip_pcie_deinit_phys(rockchip);
err_disable_clocks:
rockchip_pcie_disable_clocks(rockchip);
+err_exit_ob_mem:
+ rockchip_pcie_ep_exit_ob_mem(ep);
return err;
}
diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
index cbec71114825..5adac6adc046 100644
--- a/drivers/pci/controller/pcie-rockchip-host.c
+++ b/drivers/pci/controller/pcie-rockchip-host.c
@@ -294,7 +294,7 @@ static int rockchip_pcie_host_init_port(struct rockchip_pcie *rockchip)
int err, i = MAX_LANE_NUM;
u32 status;
- gpiod_set_value_cansleep(rockchip->ep_gpio, 0);
+ gpiod_set_value_cansleep(rockchip->perst_gpio, 0);
err = rockchip_pcie_init_port(rockchip);
if (err)
@@ -323,7 +323,7 @@ static int rockchip_pcie_host_init_port(struct rockchip_pcie *rockchip)
PCIE_CLIENT_CONFIG);
msleep(PCIE_T_PVPERL_MS);
- gpiod_set_value_cansleep(rockchip->ep_gpio, 1);
+ gpiod_set_value_cansleep(rockchip->perst_gpio, 1);
msleep(PCIE_T_RRS_READY_MS);
@@ -1050,7 +1050,7 @@ static struct platform_driver rockchip_pcie_driver = {
.pm = &rockchip_pcie_pm_ops,
},
.probe = rockchip_pcie_probe,
- .remove_new = rockchip_pcie_remove,
+ .remove = rockchip_pcie_remove,
};
module_platform_driver(rockchip_pcie_driver);
diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c
index c07d7129f1c7..b9ade7632e11 100644
--- a/drivers/pci/controller/pcie-rockchip.c
+++ b/drivers/pci/controller/pcie-rockchip.c
@@ -119,13 +119,15 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
return PTR_ERR(rockchip->aclk_rst);
}
- if (rockchip->is_rc) {
- rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep",
- GPIOD_OUT_LOW);
- if (IS_ERR(rockchip->ep_gpio))
- return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio),
- "failed to get ep GPIO\n");
- }
+ if (rockchip->is_rc)
+ rockchip->perst_gpio = devm_gpiod_get_optional(dev, "ep",
+ GPIOD_OUT_LOW);
+ else
+ rockchip->perst_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_IN);
+ if (IS_ERR(rockchip->perst_gpio))
+ return dev_err_probe(dev, PTR_ERR(rockchip->perst_gpio),
+ "failed to get PERST# GPIO\n");
rockchip->aclk_pcie = devm_clk_get(dev, "aclk");
if (IS_ERR(rockchip->aclk_pcie)) {
@@ -244,11 +246,12 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
rockchip_pcie_write(rockchip, PCIE_CLIENT_GEN_SEL_1,
PCIE_CLIENT_CONFIG);
- regs = PCIE_CLIENT_LINK_TRAIN_ENABLE | PCIE_CLIENT_ARI_ENABLE |
+ regs = PCIE_CLIENT_ARI_ENABLE |
PCIE_CLIENT_CONF_LANE_NUM(rockchip->lanes);
if (rockchip->is_rc)
- regs |= PCIE_CLIENT_CONF_ENABLE | PCIE_CLIENT_MODE_RC;
+ regs |= PCIE_CLIENT_LINK_TRAIN_ENABLE |
+ PCIE_CLIENT_CONF_ENABLE | PCIE_CLIENT_MODE_RC;
else
regs |= PCIE_CLIENT_CONF_DISABLE | PCIE_CLIENT_MODE_EP;
diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
index 6111de35f84c..a51b087ce878 100644
--- a/drivers/pci/controller/pcie-rockchip.h
+++ b/drivers/pci/controller/pcie-rockchip.h
@@ -26,12 +26,14 @@
#define MAX_LANE_NUM 4
#define MAX_REGION_LIMIT 32
#define MIN_EP_APERTURE 28
+#define LINK_TRAIN_TIMEOUT (500 * USEC_PER_MSEC)
#define PCIE_CLIENT_BASE 0x0
#define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00)
#define PCIE_CLIENT_CONF_ENABLE HIWORD_UPDATE_BIT(0x0001)
#define PCIE_CLIENT_CONF_DISABLE HIWORD_UPDATE(0x0001, 0)
#define PCIE_CLIENT_LINK_TRAIN_ENABLE HIWORD_UPDATE_BIT(0x0002)
+#define PCIE_CLIENT_LINK_TRAIN_DISABLE HIWORD_UPDATE(0x0002, 0)
#define PCIE_CLIENT_ARI_ENABLE HIWORD_UPDATE_BIT(0x0008)
#define PCIE_CLIENT_CONF_LANE_NUM(x) HIWORD_UPDATE(0x0030, ENCODE_LANES(x))
#define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040)
@@ -49,6 +51,10 @@
#define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0)
#define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18
#define PCIE_CLIENT_DEBUG_LTSSM_L2 0x19
+#define PCIE_CLIENT_BASIC_STATUS0 (PCIE_CLIENT_BASE + 0x44)
+#define PCIE_CLIENT_NEG_LINK_WIDTH_MASK GENMASK(7, 6)
+#define PCIE_CLIENT_NEG_LINK_WIDTH_SHIFT 6
+#define PCIE_CLIENT_NEG_LINK_SPEED BIT(5)
#define PCIE_CLIENT_BASIC_STATUS1 (PCIE_CLIENT_BASE + 0x48)
#define PCIE_CLIENT_LINK_STATUS_UP 0x00300000
#define PCIE_CLIENT_LINK_STATUS_MASK 0x00300000
@@ -86,6 +92,8 @@
#define PCIE_CORE_CTRL_MGMT_BASE 0x900000
#define PCIE_CORE_CTRL (PCIE_CORE_CTRL_MGMT_BASE + 0x000)
+#define PCIE_CORE_PL_CONF_LS_MASK 0x00000001
+#define PCIE_CORE_PL_CONF_LS_READY 0x00000001
#define PCIE_CORE_PL_CONF_SPEED_5G 0x00000008
#define PCIE_CORE_PL_CONF_SPEED_MASK 0x00000018
#define PCIE_CORE_PL_CONF_LANE_MASK 0x00000006
@@ -143,6 +151,7 @@
#define PCIE_RC_CONFIG_BASE 0xa00000
#define PCIE_EP_CONFIG_BASE 0xa00000
#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00)
+#define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0)
#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4)
#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18
@@ -154,6 +163,7 @@
#define PCIE_RC_CONFIG_LINK_CAP (PCIE_RC_CONFIG_BASE + 0xcc)
#define PCIE_RC_CONFIG_LINK_CAP_L0S BIT(10)
#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0)
+#define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0)
#define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c)
#define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274)
#define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20)
@@ -191,6 +201,8 @@
#define ROCKCHIP_VENDOR_ID 0x1d87
#define PCIE_LINK_IS_L2(x) \
(((x) & PCIE_CLIENT_DEBUG_LTSSM_MASK) == PCIE_CLIENT_DEBUG_LTSSM_L2)
+#define PCIE_LINK_TRAINING_DONE(x) \
+ (((x) & PCIE_CORE_PL_CONF_LS_MASK) == PCIE_CORE_PL_CONF_LS_READY)
#define PCIE_LINK_UP(x) \
(((x) & PCIE_CLIENT_LINK_STATUS_MASK) == PCIE_CLIENT_LINK_STATUS_UP)
#define PCIE_LINK_IS_GEN2(x) \
@@ -241,10 +253,20 @@
#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK GENMASK(15, 8)
#define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1
#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3
+
+#define ROCKCHIP_PCIE_AT_MIN_NUM_BITS 8
+#define ROCKCHIP_PCIE_AT_MAX_NUM_BITS 20
+#define ROCKCHIP_PCIE_AT_SIZE_ALIGN (1UL << ROCKCHIP_PCIE_AT_MIN_NUM_BITS)
+
#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \
(PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12)))
#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \
(PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12)))
+
+#define ROCKCHIP_PCIE_AT_MIN_NUM_BITS 8
+#define ROCKCHIP_PCIE_AT_MAX_NUM_BITS 20
+#define ROCKCHIP_PCIE_AT_SIZE_ALIGN (1UL << ROCKCHIP_PCIE_AT_MIN_NUM_BITS)
+
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
(PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008)
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \
@@ -307,7 +329,7 @@ struct rockchip_pcie {
struct regulator *vpcie3v3; /* 3.3V power supply */
struct regulator *vpcie1v8; /* 1.8V power supply */
struct regulator *vpcie0v9; /* 0.9V power supply */
- struct gpio_desc *ep_gpio;
+ struct gpio_desc *perst_gpio;
u32 lanes;
u8 lanes_map;
int link_gen;
diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c
index a8ae14474dd0..8d6e2a89b067 100644
--- a/drivers/pci/controller/pcie-xilinx-nwl.c
+++ b/drivers/pci/controller/pcie-xilinx-nwl.c
@@ -916,6 +916,6 @@ static struct platform_driver nwl_pcie_driver = {
.of_match_table = nwl_pcie_of_match,
},
.probe = nwl_pcie_probe,
- .remove_new = nwl_pcie_remove,
+ .remove = nwl_pcie_remove,
};
builtin_platform_driver(nwl_pcie_driver);
diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 48f60a04b740..6630cacef301 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -25,9 +25,6 @@
#define MC_PCIE1_BRIDGE_ADDR 0x00008000u
#define MC_PCIE1_CTRL_ADDR 0x0000a000u
-#define MC_PCIE_BRIDGE_ADDR (MC_PCIE1_BRIDGE_ADDR)
-#define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR)
-
/* PCIe Controller Phy Regs */
#define SEC_ERROR_EVENT_CNT 0x20
#define DED_ERROR_EVENT_CNT 0x24
@@ -128,7 +125,6 @@
[EVENT_LOCAL_ ## x] = { __stringify(x), s }
#define PCIE_EVENT(x) \
- .base = MC_PCIE_CTRL_ADDR, \
.offset = PCIE_EVENT_INT, \
.mask_offset = PCIE_EVENT_INT, \
.mask_high = 1, \
@@ -136,7 +132,6 @@
.enb_mask = PCIE_EVENT_INT_ENB_MASK
#define SEC_EVENT(x) \
- .base = MC_PCIE_CTRL_ADDR, \
.offset = SEC_ERROR_INT, \
.mask_offset = SEC_ERROR_INT_MASK, \
.mask = SEC_ERROR_INT_ ## x ## _INT, \
@@ -144,7 +139,6 @@
.enb_mask = 0
#define DED_EVENT(x) \
- .base = MC_PCIE_CTRL_ADDR, \
.offset = DED_ERROR_INT, \
.mask_offset = DED_ERROR_INT_MASK, \
.mask_high = 1, \
@@ -152,7 +146,6 @@
.enb_mask = 0
#define LOCAL_EVENT(x) \
- .base = MC_PCIE_BRIDGE_ADDR, \
.offset = ISTATUS_LOCAL, \
.mask_offset = IMASK_LOCAL, \
.mask_high = 0, \
@@ -179,7 +172,8 @@ struct event_map {
struct mc_pcie {
struct plda_pcie_rp plda;
- void __iomem *axi_base_addr;
+ void __iomem *bridge_base_addr;
+ void __iomem *ctrl_base_addr;
};
struct cause {
@@ -253,7 +247,6 @@ static struct event_map local_status_to_event[] = {
};
static struct {
- u32 base;
u32 offset;
u32 mask;
u32 shift;
@@ -325,8 +318,7 @@ static inline u32 reg_to_event(u32 reg, struct event_map field)
static u32 pcie_events(struct mc_pcie *port)
{
- void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
- u32 reg = readl_relaxed(ctrl_base_addr + PCIE_EVENT_INT);
+ u32 reg = readl_relaxed(port->ctrl_base_addr + PCIE_EVENT_INT);
u32 val = 0;
int i;
@@ -338,8 +330,7 @@ static u32 pcie_events(struct mc_pcie *port)
static u32 sec_errors(struct mc_pcie *port)
{
- void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
- u32 reg = readl_relaxed(ctrl_base_addr + SEC_ERROR_INT);
+ u32 reg = readl_relaxed(port->ctrl_base_addr + SEC_ERROR_INT);
u32 val = 0;
int i;
@@ -351,8 +342,7 @@ static u32 sec_errors(struct mc_pcie *port)
static u32 ded_errors(struct mc_pcie *port)
{
- void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
- u32 reg = readl_relaxed(ctrl_base_addr + DED_ERROR_INT);
+ u32 reg = readl_relaxed(port->ctrl_base_addr + DED_ERROR_INT);
u32 val = 0;
int i;
@@ -364,8 +354,7 @@ static u32 ded_errors(struct mc_pcie *port)
static u32 local_events(struct mc_pcie *port)
{
- void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
- u32 reg = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
+ u32 reg = readl_relaxed(port->bridge_base_addr + ISTATUS_LOCAL);
u32 val = 0;
int i;
@@ -412,8 +401,12 @@ static void mc_ack_event_irq(struct irq_data *data)
void __iomem *addr;
u32 mask;
- addr = mc_port->axi_base_addr + event_descs[event].base +
- event_descs[event].offset;
+ if (event_descs[event].offset == ISTATUS_LOCAL)
+ addr = mc_port->bridge_base_addr;
+ else
+ addr = mc_port->ctrl_base_addr;
+
+ addr += event_descs[event].offset;
mask = event_descs[event].mask;
mask |= event_descs[event].enb_mask;
@@ -429,8 +422,12 @@ static void mc_mask_event_irq(struct irq_data *data)
u32 mask;
u32 val;
- addr = mc_port->axi_base_addr + event_descs[event].base +
- event_descs[event].mask_offset;
+ if (event_descs[event].offset == ISTATUS_LOCAL)
+ addr = mc_port->bridge_base_addr;
+ else
+ addr = mc_port->ctrl_base_addr;
+
+ addr += event_descs[event].mask_offset;
mask = event_descs[event].mask;
if (event_descs[event].enb_mask) {
mask <<= PCIE_EVENT_INT_ENB_SHIFT;
@@ -460,8 +457,12 @@ static void mc_unmask_event_irq(struct irq_data *data)
u32 mask;
u32 val;
- addr = mc_port->axi_base_addr + event_descs[event].base +
- event_descs[event].mask_offset;
+ if (event_descs[event].offset == ISTATUS_LOCAL)
+ addr = mc_port->bridge_base_addr;
+ else
+ addr = mc_port->ctrl_base_addr;
+
+ addr += event_descs[event].mask_offset;
mask = event_descs[event].mask;
if (event_descs[event].enb_mask)
@@ -554,26 +555,20 @@ static const struct plda_event mc_event = {
static inline void mc_clear_secs(struct mc_pcie *port)
{
- void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-
- writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
- SEC_ERROR_INT);
- writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT);
+ writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT,
+ port->ctrl_base_addr + SEC_ERROR_INT);
+ writel_relaxed(0, port->ctrl_base_addr + SEC_ERROR_EVENT_CNT);
}
static inline void mc_clear_deds(struct mc_pcie *port)
{
- void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-
- writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
- DED_ERROR_INT);
- writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT);
+ writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT,
+ port->ctrl_base_addr + DED_ERROR_INT);
+ writel_relaxed(0, port->ctrl_base_addr + DED_ERROR_EVENT_CNT);
}
static void mc_disable_interrupts(struct mc_pcie *port)
{
- void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
- void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
u32 val;
/* Ensure ECC bypass is enabled */
@@ -581,22 +576,22 @@ static void mc_disable_interrupts(struct mc_pcie *port)
ECC_CONTROL_RX_RAM_ECC_BYPASS |
ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS |
ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS;
- writel_relaxed(val, ctrl_base_addr + ECC_CONTROL);
+ writel_relaxed(val, port->ctrl_base_addr + ECC_CONTROL);
/* Disable SEC errors and clear any outstanding */
- writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
- SEC_ERROR_INT_MASK);
+ writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT,
+ port->ctrl_base_addr + SEC_ERROR_INT_MASK);
mc_clear_secs(port);
/* Disable DED errors and clear any outstanding */
- writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
- DED_ERROR_INT_MASK);
+ writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT,
+ port->ctrl_base_addr + DED_ERROR_INT_MASK);
mc_clear_deds(port);
/* Disable local interrupts and clear any outstanding */
- writel_relaxed(0, bridge_base_addr + IMASK_LOCAL);
- writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_LOCAL);
- writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_MSI);
+ writel_relaxed(0, port->bridge_base_addr + IMASK_LOCAL);
+ writel_relaxed(GENMASK(31, 0), port->bridge_base_addr + ISTATUS_LOCAL);
+ writel_relaxed(GENMASK(31, 0), port->bridge_base_addr + ISTATUS_MSI);
/* Disable PCIe events and clear any outstanding */
val = PCIE_EVENT_INT_L2_EXIT_INT |
@@ -605,11 +600,11 @@ static void mc_disable_interrupts(struct mc_pcie *port)
PCIE_EVENT_INT_L2_EXIT_INT_MASK |
PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK |
PCIE_EVENT_INT_DLUP_EXIT_INT_MASK;
- writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT);
+ writel_relaxed(val, port->ctrl_base_addr + PCIE_EVENT_INT);
/* Disable host interrupts and clear any outstanding */
- writel_relaxed(0, bridge_base_addr + IMASK_HOST);
- writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
+ writel_relaxed(0, port->bridge_base_addr + IMASK_HOST);
+ writel_relaxed(GENMASK(31, 0), port->bridge_base_addr + ISTATUS_HOST);
}
static int mc_platform_init(struct pci_config_window *cfg)
@@ -617,12 +612,10 @@ static int mc_platform_init(struct pci_config_window *cfg)
struct device *dev = cfg->parent;
struct platform_device *pdev = to_platform_device(dev);
struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
int ret;
/* Configure address translation table 0 for PCIe config space */
- plda_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
+ plda_pcie_setup_window(port->bridge_base_addr, 0, cfg->res.start,
cfg->res.start,
resource_size(&cfg->res));
@@ -649,7 +642,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
static int mc_host_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- void __iomem *bridge_base_addr;
+ void __iomem *apb_base_addr;
struct plda_pcie_rp *plda;
int ret;
u32 val;
@@ -661,30 +654,45 @@ static int mc_host_probe(struct platform_device *pdev)
plda = &port->plda;
plda->dev = dev;
- port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(port->axi_base_addr))
- return PTR_ERR(port->axi_base_addr);
+ port->bridge_base_addr = devm_platform_ioremap_resource_byname(pdev,
+ "bridge");
+ port->ctrl_base_addr = devm_platform_ioremap_resource_byname(pdev,
+ "ctrl");
+ if (!IS_ERR(port->bridge_base_addr) && !IS_ERR(port->ctrl_base_addr))
+ goto addrs_set;
+
+ /*
+ * The original, incorrect, binding that lumped the control and
+ * bridge addresses together still needs to be handled by the driver.
+ */
+ apb_base_addr = devm_platform_ioremap_resource_byname(pdev, "apb");
+ if (IS_ERR(apb_base_addr))
+ return dev_err_probe(dev, PTR_ERR(apb_base_addr),
+ "both legacy apb register and ctrl/bridge regions missing");
+
+ port->bridge_base_addr = apb_base_addr + MC_PCIE1_BRIDGE_ADDR;
+ port->ctrl_base_addr = apb_base_addr + MC_PCIE1_CTRL_ADDR;
+addrs_set:
mc_disable_interrupts(port);
- bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
- plda->bridge_addr = bridge_base_addr;
+ plda->bridge_addr = port->bridge_base_addr;
plda->num_events = NUM_EVENTS;
/* Allow enabling MSI by disabling MSI-X */
- val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
+ val = readl(port->bridge_base_addr + PCIE_PCI_IRQ_DW0);
val &= ~MSIX_CAP_MASK;
- writel(val, bridge_base_addr + PCIE_PCI_IRQ_DW0);
+ writel(val, port->bridge_base_addr + PCIE_PCI_IRQ_DW0);
/* Pick num vectors from bitfile programmed onto FPGA fabric */
- val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
+ val = readl(port->bridge_base_addr + PCIE_PCI_IRQ_DW0);
val &= NUM_MSI_MSGS_MASK;
val >>= NUM_MSI_MSGS_SHIFT;
plda->msi.num_vectors = 1 << val;
/* Pick vector address from design */
- plda->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
+ plda->msi.vector_phy = readl_relaxed(port->bridge_base_addr + IMSI_ADDR);
ret = mc_pcie_init_clks(dev);
if (ret) {
diff --git a/drivers/pci/controller/plda/pcie-starfive.c b/drivers/pci/controller/plda/pcie-starfive.c
index c9933ecf6833..e73c1b7bc8ef 100644
--- a/drivers/pci/controller/plda/pcie-starfive.c
+++ b/drivers/pci/controller/plda/pcie-starfive.c
@@ -404,6 +404,9 @@ static int starfive_pcie_probe(struct platform_device *pdev)
if (ret)
return ret;
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
plda->host_ops = &sf_host_ops;
plda->num_events = PLDA_MAX_EVENT_NUM;
/* mask doorbell event */
@@ -413,11 +416,12 @@ static int starfive_pcie_probe(struct platform_device *pdev)
plda->events_bitmap <<= PLDA_NUM_DMA_EVENTS;
ret = plda_pcie_host_init(&pcie->plda, &starfive_pcie_ops,
&stf_pcie_event);
- if (ret)
+ if (ret) {
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return ret;
+ }
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
platform_set_drvdata(pdev, pcie);
return 0;
@@ -480,7 +484,7 @@ static struct platform_driver starfive_pcie_driver = {
.pm = pm_sleep_ptr(&starfive_pcie_pm_ops),
},
.probe = starfive_pcie_probe,
- .remove_new = starfive_pcie_remove,
+ .remove = starfive_pcie_remove,
};
module_platform_driver(starfive_pcie_driver);
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index 264a180403a0..9d9596947350 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -740,11 +740,9 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata)
if (!(features & VMD_FEAT_BIOS_PM_QUIRK))
return 0;
- pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
-
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR);
if (!pos)
- return 0;
+ goto out_state_change;
/*
* Skip if the max snoop LTR is non-zero, indicating BIOS has set it
@@ -752,7 +750,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata)
*/
pci_read_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, &ltr_reg);
if (!!(ltr_reg & (PCI_LTR_VALUE_MASK | PCI_LTR_SCALE_MASK)))
- return 0;
+ goto out_state_change;
/*
* Set the default values to the maximum required by the platform to
@@ -764,6 +762,13 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata)
pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, ltr_reg);
pci_info(pdev, "VMD: Default LTR value set by driver\n");
+out_state_change:
+ /*
+ * Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
+ * PCIe r6.0, sec 5.5.4.
+ */
+ pci_set_power_state_locked(pdev, PCI_D0);
+ pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
return 0;
}
@@ -1100,6 +1105,10 @@ static const struct pci_device_id vmd_ids[] = {
.driver_data = VMD_FEATS_CLIENT,},
{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
.driver_data = VMD_FEATS_CLIENT,},
+ {PCI_VDEVICE(INTEL, 0xb60b),
+ .driver_data = VMD_FEATS_CLIENT,},
+ {PCI_VDEVICE(INTEL, 0xb06f),
+ .driver_data = VMD_FEATS_CLIENT,},
{0,}
};
MODULE_DEVICE_TABLE(pci, vmd_ids);
diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c
index b133967faef8..3b59a86a764b 100644
--- a/drivers/pci/devres.c
+++ b/drivers/pci/devres.c
@@ -773,7 +773,7 @@ EXPORT_SYMBOL(pcim_iomap_region);
* Unmap a BAR and release its region manually. Only pass BARs that were
* previously mapped by pcim_iomap_region().
*/
-static void pcim_iounmap_region(struct pci_dev *pdev, int bar)
+void pcim_iounmap_region(struct pci_dev *pdev, int bar)
{
struct pcim_addr_devres res_searched;
@@ -784,6 +784,7 @@ static void pcim_iounmap_region(struct pci_dev *pdev, int bar)
devres_release(&pdev->dev, pcim_addr_resource_release,
pcim_addr_resources_match, &res_searched);
}
+EXPORT_SYMBOL(pcim_iounmap_region);
/**
* pcim_iomap_regions - Request and iomap PCI BARs (DEPRECATED)
@@ -939,7 +940,7 @@ static void pcim_release_all_regions(struct pci_dev *pdev)
* desired, release individual regions with pcim_release_region() or all of
* them at once with pcim_release_all_regions().
*/
-static int pcim_request_all_regions(struct pci_dev *pdev, const char *name)
+int pcim_request_all_regions(struct pci_dev *pdev, const char *name)
{
int ret;
int bar;
@@ -957,69 +958,17 @@ err:
return ret;
}
+EXPORT_SYMBOL(pcim_request_all_regions);
/**
- * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
- * (DEPRECATED)
- * @pdev: PCI device to map IO resources for
- * @mask: Mask of BARs to iomap
- * @name: Name associated with the requests
- *
- * Returns: 0 on success, negative error code on failure.
- *
- * Request all PCI BARs and iomap regions specified by @mask.
- *
- * To release these resources manually, call pcim_release_region() for the
- * regions and pcim_iounmap() for the mappings.
- *
- * This function is DEPRECATED. Don't use it in new code. Instead, use one
- * of the pcim_* region request functions in combination with a pcim_*
- * mapping function.
- */
-int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
- const char *name)
-{
- int bar;
- int ret;
- void __iomem **legacy_iomap_table;
-
- ret = pcim_request_all_regions(pdev, name);
- if (ret != 0)
- return ret;
-
- for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
- if (!mask_contains_bar(mask, bar))
- continue;
- if (!pcim_iomap(pdev, bar, 0))
- goto err;
- }
-
- return 0;
-
-err:
- /*
- * If bar is larger than 0, then pcim_iomap() above has most likely
- * failed because of -EINVAL. If it is equal 0, most likely the table
- * couldn't be created, indicating -ENOMEM.
- */
- ret = bar > 0 ? -EINVAL : -ENOMEM;
- legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
-
- while (--bar >= 0)
- pcim_iounmap(pdev, legacy_iomap_table[bar]);
-
- pcim_release_all_regions(pdev);
-
- return ret;
-}
-EXPORT_SYMBOL(pcim_iomap_regions_request_all);
-
-/**
- * pcim_iounmap_regions - Unmap and release PCI BARs
+ * pcim_iounmap_regions - Unmap and release PCI BARs (DEPRECATED)
* @pdev: PCI device to map IO resources for
* @mask: Mask of BARs to unmap and release
*
* Unmap and release regions specified by @mask.
+ *
+ * This function is DEPRECATED. Do not use it in new code.
+ * Use pcim_iounmap_region() instead.
*/
void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
{
diff --git a/drivers/pci/doe.c b/drivers/pci/doe.c
index 652d63df9d22..7bd7892c5222 100644
--- a/drivers/pci/doe.c
+++ b/drivers/pci/doe.c
@@ -146,6 +146,7 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
{
struct pci_dev *pdev = doe_mb->pdev;
int offset = doe_mb->cap_offset;
+ unsigned long timeout_jiffies;
size_t length, remainder;
u32 val;
int i;
@@ -155,8 +156,19 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
* someone other than Linux (e.g. firmware) is using the mailbox. Note
* it is expected that firmware and OS will negotiate access rights via
* an, as yet to be defined, method.
+ *
+ * Wait up to one PCI_DOE_TIMEOUT period to allow the prior command to
+ * finish. Otherwise, simply error out as unable to field the request.
+ *
+ * PCIe r6.2 sec 6.30.3 states no interrupt is raised when the DOE Busy
+ * bit is cleared, so polling here is our best option for the moment.
*/
- pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val);
+ timeout_jiffies = jiffies + PCI_DOE_TIMEOUT;
+ do {
+ pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val);
+ } while (FIELD_GET(PCI_DOE_STATUS_BUSY, val) &&
+ !time_after(jiffies, timeout_jiffies));
+
if (FIELD_GET(PCI_DOE_STATUS_BUSY, val))
return -EBUSY;
diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
index 1c40d2506aef..260b7de2dbd5 100644
--- a/drivers/pci/ecam.c
+++ b/drivers/pci/ecam.c
@@ -55,7 +55,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
bus_range_max = resource_size(cfgres) >> bus_shift;
if (bus_range > bus_range_max) {
bus_range = bus_range_max;
- cfg->busr.end = busr->start + bus_range - 1;
+ resource_set_size(&cfg->busr, bus_range);
dev_warn(dev, "ECAM area %pR can only accommodate %pR (reduced from %pR desired)\n",
cfgres, &cfg->busr, busr);
}
diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
index 7d070b1def11..54286a40bdfb 100644
--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c
+++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
@@ -867,12 +867,18 @@ static int pci_epf_mhi_bind(struct pci_epf *epf)
{
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
struct platform_device *pdev = to_platform_device(epc->dev.parent);
struct resource *res;
int ret;
/* Get MMIO base address from Endpoint controller */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio");
+ if (!res) {
+ dev_err(dev, "Failed to get \"mmio\" resource\n");
+ return -ENODEV;
+ }
+
epf_mhi->mmio_phys = res->start;
epf_mhi->mmio_size = resource_size(res);
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 7c2ed6eae53a..ef6677f34116 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -291,8 +291,6 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test)
dma_release_channel(epf_test->dma_chan_rx);
epf_test->dma_chan_rx = NULL;
-
- return;
}
static void pci_epf_test_print_rate(struct pci_epf_test *epf_test,
@@ -317,91 +315,92 @@ static void pci_epf_test_print_rate(struct pci_epf_test *epf_test,
static void pci_epf_test_copy(struct pci_epf_test *epf_test,
struct pci_epf_test_reg *reg)
{
- int ret;
- void __iomem *src_addr;
- void __iomem *dst_addr;
- phys_addr_t src_phys_addr;
- phys_addr_t dst_phys_addr;
+ int ret = 0;
struct timespec64 start, end;
struct pci_epf *epf = epf_test->epf;
- struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
+ struct pci_epc_map src_map, dst_map;
+ u64 src_addr = reg->src_addr;
+ u64 dst_addr = reg->dst_addr;
+ size_t copy_size = reg->size;
+ ssize_t map_size = 0;
+ void *copy_buf = NULL, *buf;
- src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size);
- if (!src_addr) {
- dev_err(dev, "Failed to allocate source address\n");
- reg->status = STATUS_SRC_ADDR_INVALID;
- ret = -ENOMEM;
- goto err;
- }
-
- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr,
- reg->src_addr, reg->size);
- if (ret) {
- dev_err(dev, "Failed to map source address\n");
- reg->status = STATUS_SRC_ADDR_INVALID;
- goto err_src_addr;
- }
-
- dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size);
- if (!dst_addr) {
- dev_err(dev, "Failed to allocate destination address\n");
- reg->status = STATUS_DST_ADDR_INVALID;
- ret = -ENOMEM;
- goto err_src_map_addr;
- }
-
- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr,
- reg->dst_addr, reg->size);
- if (ret) {
- dev_err(dev, "Failed to map destination address\n");
- reg->status = STATUS_DST_ADDR_INVALID;
- goto err_dst_addr;
- }
-
- ktime_get_ts64(&start);
if (reg->flags & FLAG_USE_DMA) {
if (epf_test->dma_private) {
dev_err(dev, "Cannot transfer data using DMA\n");
ret = -EINVAL;
- goto err_map_addr;
+ goto set_status;
}
-
- ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
- src_phys_addr, reg->size, 0,
- DMA_MEM_TO_MEM);
- if (ret)
- dev_err(dev, "Data transfer failed\n");
} else {
- void *buf;
-
- buf = kzalloc(reg->size, GFP_KERNEL);
- if (!buf) {
+ copy_buf = kzalloc(copy_size, GFP_KERNEL);
+ if (!copy_buf) {
ret = -ENOMEM;
- goto err_map_addr;
+ goto set_status;
}
-
- memcpy_fromio(buf, src_addr, reg->size);
- memcpy_toio(dst_addr, buf, reg->size);
- kfree(buf);
+ buf = copy_buf;
}
- ktime_get_ts64(&end);
- pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, &end,
- reg->flags & FLAG_USE_DMA);
-err_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr);
+ while (copy_size) {
+ ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
+ src_addr, copy_size, &src_map);
+ if (ret) {
+ dev_err(dev, "Failed to map source address\n");
+ reg->status = STATUS_SRC_ADDR_INVALID;
+ goto free_buf;
+ }
+
+ ret = pci_epc_mem_map(epf->epc, epf->func_no, epf->vfunc_no,
+ dst_addr, copy_size, &dst_map);
+ if (ret) {
+ dev_err(dev, "Failed to map destination address\n");
+ reg->status = STATUS_DST_ADDR_INVALID;
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no,
+ &src_map);
+ goto free_buf;
+ }
-err_dst_addr:
- pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size);
+ map_size = min_t(size_t, dst_map.pci_size, src_map.pci_size);
-err_src_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr);
+ ktime_get_ts64(&start);
+ if (reg->flags & FLAG_USE_DMA) {
+ ret = pci_epf_test_data_transfer(epf_test,
+ dst_map.phys_addr, src_map.phys_addr,
+ map_size, 0, DMA_MEM_TO_MEM);
+ if (ret) {
+ dev_err(dev, "Data transfer failed\n");
+ goto unmap;
+ }
+ } else {
+ memcpy_fromio(buf, src_map.virt_addr, map_size);
+ memcpy_toio(dst_map.virt_addr, buf, map_size);
+ buf += map_size;
+ }
+ ktime_get_ts64(&end);
-err_src_addr:
- pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size);
+ copy_size -= map_size;
+ src_addr += map_size;
+ dst_addr += map_size;
-err:
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map);
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map);
+ map_size = 0;
+ }
+
+ pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start,
+ &end, reg->flags & FLAG_USE_DMA);
+
+unmap:
+ if (map_size) {
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map);
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map);
+ }
+
+free_buf:
+ kfree(copy_buf);
+
+set_status:
if (!ret)
reg->status |= STATUS_COPY_SUCCESS;
else
@@ -411,82 +410,89 @@ err:
static void pci_epf_test_read(struct pci_epf_test *epf_test,
struct pci_epf_test_reg *reg)
{
- int ret;
- void __iomem *src_addr;
- void *buf;
+ int ret = 0;
+ void *src_buf, *buf;
u32 crc32;
- phys_addr_t phys_addr;
+ struct pci_epc_map map;
phys_addr_t dst_phys_addr;
struct timespec64 start, end;
struct pci_epf *epf = epf_test->epf;
- struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
struct device *dma_dev = epf->epc->dev.parent;
+ u64 src_addr = reg->src_addr;
+ size_t src_size = reg->size;
+ ssize_t map_size = 0;
- src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
- if (!src_addr) {
- dev_err(dev, "Failed to allocate address\n");
- reg->status = STATUS_SRC_ADDR_INVALID;
+ src_buf = kzalloc(src_size, GFP_KERNEL);
+ if (!src_buf) {
ret = -ENOMEM;
- goto err;
+ goto set_status;
}
+ buf = src_buf;
- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
- reg->src_addr, reg->size);
- if (ret) {
- dev_err(dev, "Failed to map address\n");
- reg->status = STATUS_SRC_ADDR_INVALID;
- goto err_addr;
- }
-
- buf = kzalloc(reg->size, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto err_map_addr;
- }
+ while (src_size) {
+ ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
+ src_addr, src_size, &map);
+ if (ret) {
+ dev_err(dev, "Failed to map address\n");
+ reg->status = STATUS_SRC_ADDR_INVALID;
+ goto free_buf;
+ }
- if (reg->flags & FLAG_USE_DMA) {
- dst_phys_addr = dma_map_single(dma_dev, buf, reg->size,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dma_dev, dst_phys_addr)) {
- dev_err(dev, "Failed to map destination buffer addr\n");
- ret = -ENOMEM;
- goto err_dma_map;
+ map_size = map.pci_size;
+ if (reg->flags & FLAG_USE_DMA) {
+ dst_phys_addr = dma_map_single(dma_dev, buf, map_size,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dma_dev, dst_phys_addr)) {
+ dev_err(dev,
+ "Failed to map destination buffer addr\n");
+ ret = -ENOMEM;
+ goto unmap;
+ }
+
+ ktime_get_ts64(&start);
+ ret = pci_epf_test_data_transfer(epf_test,
+ dst_phys_addr, map.phys_addr,
+ map_size, src_addr, DMA_DEV_TO_MEM);
+ if (ret)
+ dev_err(dev, "Data transfer failed\n");
+ ktime_get_ts64(&end);
+
+ dma_unmap_single(dma_dev, dst_phys_addr, map_size,
+ DMA_FROM_DEVICE);
+
+ if (ret)
+ goto unmap;
+ } else {
+ ktime_get_ts64(&start);
+ memcpy_fromio(buf, map.virt_addr, map_size);
+ ktime_get_ts64(&end);
}
- ktime_get_ts64(&start);
- ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
- phys_addr, reg->size,
- reg->src_addr, DMA_DEV_TO_MEM);
- if (ret)
- dev_err(dev, "Data transfer failed\n");
- ktime_get_ts64(&end);
+ src_size -= map_size;
+ src_addr += map_size;
+ buf += map_size;
- dma_unmap_single(dma_dev, dst_phys_addr, reg->size,
- DMA_FROM_DEVICE);
- } else {
- ktime_get_ts64(&start);
- memcpy_fromio(buf, src_addr, reg->size);
- ktime_get_ts64(&end);
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
+ map_size = 0;
}
- pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, &end,
- reg->flags & FLAG_USE_DMA);
+ pci_epf_test_print_rate(epf_test, "READ", reg->size, &start,
+ &end, reg->flags & FLAG_USE_DMA);
- crc32 = crc32_le(~0, buf, reg->size);
+ crc32 = crc32_le(~0, src_buf, reg->size);
if (crc32 != reg->checksum)
ret = -EIO;
-err_dma_map:
- kfree(buf);
-
-err_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
+unmap:
+ if (map_size)
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
-err_addr:
- pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size);
+free_buf:
+ kfree(src_buf);
-err:
+set_status:
if (!ret)
reg->status |= STATUS_READ_SUCCESS;
else
@@ -496,71 +502,79 @@ err:
static void pci_epf_test_write(struct pci_epf_test *epf_test,
struct pci_epf_test_reg *reg)
{
- int ret;
- void __iomem *dst_addr;
- void *buf;
- phys_addr_t phys_addr;
+ int ret = 0;
+ void *dst_buf, *buf;
+ struct pci_epc_map map;
phys_addr_t src_phys_addr;
struct timespec64 start, end;
struct pci_epf *epf = epf_test->epf;
- struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
struct device *dma_dev = epf->epc->dev.parent;
+ u64 dst_addr = reg->dst_addr;
+ size_t dst_size = reg->size;
+ ssize_t map_size = 0;
- dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
- if (!dst_addr) {
- dev_err(dev, "Failed to allocate address\n");
- reg->status = STATUS_DST_ADDR_INVALID;
+ dst_buf = kzalloc(dst_size, GFP_KERNEL);
+ if (!dst_buf) {
ret = -ENOMEM;
- goto err;
+ goto set_status;
}
+ get_random_bytes(dst_buf, dst_size);
+ reg->checksum = crc32_le(~0, dst_buf, dst_size);
+ buf = dst_buf;
- ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
- reg->dst_addr, reg->size);
- if (ret) {
- dev_err(dev, "Failed to map address\n");
- reg->status = STATUS_DST_ADDR_INVALID;
- goto err_addr;
- }
-
- buf = kzalloc(reg->size, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto err_map_addr;
- }
-
- get_random_bytes(buf, reg->size);
- reg->checksum = crc32_le(~0, buf, reg->size);
-
- if (reg->flags & FLAG_USE_DMA) {
- src_phys_addr = dma_map_single(dma_dev, buf, reg->size,
- DMA_TO_DEVICE);
- if (dma_mapping_error(dma_dev, src_phys_addr)) {
- dev_err(dev, "Failed to map source buffer addr\n");
- ret = -ENOMEM;
- goto err_dma_map;
+ while (dst_size) {
+ ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
+ dst_addr, dst_size, &map);
+ if (ret) {
+ dev_err(dev, "Failed to map address\n");
+ reg->status = STATUS_DST_ADDR_INVALID;
+ goto free_buf;
}
- ktime_get_ts64(&start);
+ map_size = map.pci_size;
+ if (reg->flags & FLAG_USE_DMA) {
+ src_phys_addr = dma_map_single(dma_dev, buf, map_size,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dma_dev, src_phys_addr)) {
+ dev_err(dev,
+ "Failed to map source buffer addr\n");
+ ret = -ENOMEM;
+ goto unmap;
+ }
+
+ ktime_get_ts64(&start);
+
+ ret = pci_epf_test_data_transfer(epf_test,
+ map.phys_addr, src_phys_addr,
+ map_size, dst_addr,
+ DMA_MEM_TO_DEV);
+ if (ret)
+ dev_err(dev, "Data transfer failed\n");
+ ktime_get_ts64(&end);
+
+ dma_unmap_single(dma_dev, src_phys_addr, map_size,
+ DMA_TO_DEVICE);
+
+ if (ret)
+ goto unmap;
+ } else {
+ ktime_get_ts64(&start);
+ memcpy_toio(map.virt_addr, buf, map_size);
+ ktime_get_ts64(&end);
+ }
- ret = pci_epf_test_data_transfer(epf_test, phys_addr,
- src_phys_addr, reg->size,
- reg->dst_addr,
- DMA_MEM_TO_DEV);
- if (ret)
- dev_err(dev, "Data transfer failed\n");
- ktime_get_ts64(&end);
+ dst_size -= map_size;
+ dst_addr += map_size;
+ buf += map_size;
- dma_unmap_single(dma_dev, src_phys_addr, reg->size,
- DMA_TO_DEVICE);
- } else {
- ktime_get_ts64(&start);
- memcpy_toio(dst_addr, buf, reg->size);
- ktime_get_ts64(&end);
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
+ map_size = 0;
}
- pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, &end,
- reg->flags & FLAG_USE_DMA);
+ pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start,
+ &end, reg->flags & FLAG_USE_DMA);
/*
* wait 1ms inorder for the write to complete. Without this delay L3
@@ -568,16 +582,14 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test,
*/
usleep_range(1000, 2000);
-err_dma_map:
- kfree(buf);
-
-err_map_addr:
- pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
+unmap:
+ if (map_size)
+ pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
-err_addr:
- pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size);
+free_buf:
+ kfree(dst_buf);
-err:
+set_status:
if (!ret)
reg->status |= STATUS_WRITE_SUCCESS;
else
@@ -786,7 +798,7 @@ static void pci_epf_test_epc_deinit(struct pci_epf *epf)
{
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
- cancel_delayed_work(&epf_test->cmd_handler);
+ cancel_delayed_work_sync(&epf_test->cmd_handler);
pci_epf_test_clean_dma_chan(epf_test);
pci_epf_test_clear_bar(epf);
}
@@ -917,7 +929,7 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
struct pci_epc *epc = epf->epc;
- cancel_delayed_work(&epf_test->cmd_handler);
+ cancel_delayed_work_sync(&epf_test->cmd_handler);
if (epc->init_complete) {
pci_epf_test_clean_dma_chan(epf_test);
pci_epf_test_clear_bar(epf);
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 17f007109255..bed7c7d1fe3c 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -128,6 +128,18 @@ enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
}
EXPORT_SYMBOL_GPL(pci_epc_get_next_free_bar);
+static bool pci_epc_function_is_valid(struct pci_epc *epc,
+ u8 func_no, u8 vfunc_no)
+{
+ if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
+ return false;
+
+ if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ return false;
+
+ return true;
+}
+
/**
* pci_epc_get_features() - get the features supported by EPC
* @epc: the features supported by *this* EPC device will be returned
@@ -145,10 +157,7 @@ const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc,
{
const struct pci_epc_features *epc_features;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
- return NULL;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return NULL;
if (!epc->ops->get_features)
@@ -218,10 +227,7 @@ int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
{
int ret;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
- return -EINVAL;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return -EINVAL;
if (!epc->ops->raise_irq)
@@ -262,10 +268,7 @@ int pci_epc_map_msi_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
{
int ret;
- if (IS_ERR_OR_NULL(epc))
- return -EINVAL;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return -EINVAL;
if (!epc->ops->map_msi_irq)
@@ -293,10 +296,7 @@ int pci_epc_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
{
int interrupt;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
- return 0;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return 0;
if (!epc->ops->get_msi)
@@ -329,11 +329,10 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u8 interrupts)
int ret;
u8 encode_int;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
- interrupts < 1 || interrupts > 32)
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return -EINVAL;
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (interrupts < 1 || interrupts > 32)
return -EINVAL;
if (!epc->ops->set_msi)
@@ -361,10 +360,7 @@ int pci_epc_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
{
int interrupt;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
- return 0;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return 0;
if (!epc->ops->get_msix)
@@ -397,11 +393,10 @@ int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
{
int ret;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
- interrupts < 1 || interrupts > 2048)
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return -EINVAL;
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (interrupts < 1 || interrupts > 2048)
return -EINVAL;
if (!epc->ops->set_msix)
@@ -428,10 +423,7 @@ EXPORT_SYMBOL_GPL(pci_epc_set_msix);
void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
phys_addr_t phys_addr)
{
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
- return;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return;
if (!epc->ops->unmap_addr)
@@ -459,10 +451,7 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
{
int ret;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
- return -EINVAL;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return -EINVAL;
if (!epc->ops->map_addr)
@@ -478,6 +467,109 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
EXPORT_SYMBOL_GPL(pci_epc_map_addr);
/**
+ * pci_epc_mem_map() - allocate and map a PCI address to a CPU address
+ * @epc: the EPC device on which the CPU address is to be allocated and mapped
+ * @func_no: the physical endpoint function number in the EPC device
+ * @vfunc_no: the virtual endpoint function number in the physical function
+ * @pci_addr: PCI address to which the CPU address should be mapped
+ * @pci_size: the number of bytes to map starting from @pci_addr
+ * @map: where to return the mapping information
+ *
+ * Allocate a controller memory address region and map it to a RC PCI address
+ * region, taking into account the controller physical address mapping
+ * constraints using the controller operation align_addr(). If this operation is
+ * not defined, we assume that there are no alignment constraints for the
+ * mapping.
+ *
+ * The effective size of the PCI address range mapped from @pci_addr is
+ * indicated by @map->pci_size. This size may be less than the requested
+ * @pci_size. The local virtual CPU address for the mapping is indicated by
+ * @map->virt_addr (@map->phys_addr indicates the physical address).
+ * The size and CPU address of the controller memory allocated and mapped are
+ * respectively indicated by @map->map_size and @map->virt_base (and
+ * @map->phys_base for the physical address of @map->virt_base).
+ *
+ * Returns 0 on success and a negative error code in case of error.
+ */
+int pci_epc_mem_map(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
+ u64 pci_addr, size_t pci_size, struct pci_epc_map *map)
+{
+ size_t map_size = pci_size;
+ size_t map_offset = 0;
+ int ret;
+
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
+ return -EINVAL;
+
+ if (!pci_size || !map)
+ return -EINVAL;
+
+ /*
+ * Align the PCI address to map. If the controller defines the
+ * .align_addr() operation, use it to determine the PCI address to map
+ * and the size of the mapping. Otherwise, assume that the controller
+ * has no alignment constraint.
+ */
+ memset(map, 0, sizeof(*map));
+ map->pci_addr = pci_addr;
+ if (epc->ops->align_addr)
+ map->map_pci_addr =
+ epc->ops->align_addr(epc, pci_addr,
+ &map_size, &map_offset);
+ else
+ map->map_pci_addr = pci_addr;
+ map->map_size = map_size;
+ if (map->map_pci_addr + map->map_size < pci_addr + pci_size)
+ map->pci_size = map->map_pci_addr + map->map_size - pci_addr;
+ else
+ map->pci_size = pci_size;
+
+ map->virt_base = pci_epc_mem_alloc_addr(epc, &map->phys_base,
+ map->map_size);
+ if (!map->virt_base)
+ return -ENOMEM;
+
+ map->phys_addr = map->phys_base + map_offset;
+ map->virt_addr = map->virt_base + map_offset;
+
+ ret = pci_epc_map_addr(epc, func_no, vfunc_no, map->phys_base,
+ map->map_pci_addr, map->map_size);
+ if (ret) {
+ pci_epc_mem_free_addr(epc, map->phys_base, map->virt_base,
+ map->map_size);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_epc_mem_map);
+
+/**
+ * pci_epc_mem_unmap() - unmap and free a CPU address region
+ * @epc: the EPC device on which the CPU address is allocated and mapped
+ * @func_no: the physical endpoint function number in the EPC device
+ * @vfunc_no: the virtual endpoint function number in the physical function
+ * @map: the mapping information
+ *
+ * Unmap and free a CPU address region that was allocated and mapped with
+ * pci_epc_mem_map().
+ */
+void pci_epc_mem_unmap(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
+ struct pci_epc_map *map)
+{
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
+ return;
+
+ if (!map || !map->virt_base)
+ return;
+
+ pci_epc_unmap_addr(epc, func_no, vfunc_no, map->phys_base);
+ pci_epc_mem_free_addr(epc, map->phys_base, map->virt_base,
+ map->map_size);
+}
+EXPORT_SYMBOL_GPL(pci_epc_mem_unmap);
+
+/**
* pci_epc_clear_bar() - reset the BAR
* @epc: the EPC device for which the BAR has to be cleared
* @func_no: the physical endpoint function number in the EPC device
@@ -489,12 +581,11 @@ EXPORT_SYMBOL_GPL(pci_epc_map_addr);
void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
struct pci_epf_bar *epf_bar)
{
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
- (epf_bar->barno == BAR_5 &&
- epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return;
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (epf_bar->barno == BAR_5 &&
+ epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
return;
if (!epc->ops->clear_bar)
@@ -521,18 +612,16 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
int ret;
int flags = epf_bar->flags;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
- (epf_bar->barno == BAR_5 &&
- flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ||
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
+ return -EINVAL;
+
+ if ((epf_bar->barno == BAR_5 && flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ||
(flags & PCI_BASE_ADDRESS_SPACE_IO &&
flags & PCI_BASE_ADDRESS_IO_MASK) ||
(upper_32_bits(epf_bar->size) &&
!(flags & PCI_BASE_ADDRESS_MEM_TYPE_64)))
return -EINVAL;
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
- return -EINVAL;
-
if (!epc->ops->set_bar)
return 0;
@@ -561,10 +650,7 @@ int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
{
int ret;
- if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
- return -EINVAL;
-
- if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
return -EINVAL;
/* Only Virtual Function #1 has deviceID */
@@ -660,18 +746,18 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
if (IS_ERR_OR_NULL(epc) || !epf)
return;
+ mutex_lock(&epc->list_lock);
if (type == PRIMARY_INTERFACE) {
func_no = epf->func_no;
list = &epf->list;
+ epf->epc = NULL;
} else {
func_no = epf->sec_epc_func_no;
list = &epf->sec_epc_list;
+ epf->sec_epc = NULL;
}
-
- mutex_lock(&epc->list_lock);
clear_bit(func_no, &epc->function_num_map);
list_del(list);
- epf->epc = NULL;
mutex_unlock(&epc->list_lock);
}
EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
@@ -837,11 +923,10 @@ EXPORT_SYMBOL_GPL(pci_epc_bus_master_enable_notify);
void pci_epc_destroy(struct pci_epc *epc)
{
pci_ep_cfs_remove_epc_group(epc->group);
- device_unregister(&epc->dev);
-
#ifdef CONFIG_PCI_DOMAINS_GENERIC
- pci_bus_release_domain_nr(&epc->dev, epc->domain_nr);
+ pci_bus_release_domain_nr(epc->dev.parent, epc->domain_nr);
#endif
+ device_unregister(&epc->dev);
}
EXPORT_SYMBOL_GPL(pci_epc_destroy);
diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c
index a9c028f58da1..218a60e945db 100644
--- a/drivers/pci/endpoint/pci-epc-mem.c
+++ b/drivers/pci/endpoint/pci-epc-mem.c
@@ -178,7 +178,7 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
phys_addr_t *phys_addr, size_t size)
{
- void __iomem *virt_addr = NULL;
+ void __iomem *virt_addr;
struct pci_epc_mem *mem;
unsigned int page_shift;
size_t align_size;
@@ -188,10 +188,13 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
for (i = 0; i < epc->num_windows; i++) {
mem = epc->windows[i];
- mutex_lock(&mem->lock);
+ if (size > mem->window.size)
+ continue;
+
align_size = ALIGN(size, mem->window.page_size);
order = pci_epc_mem_get_order(mem, align_size);
+ mutex_lock(&mem->lock);
pageno = bitmap_find_free_region(mem->bitmap, mem->pages,
order);
if (pageno >= 0) {
@@ -211,7 +214,7 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
mutex_unlock(&mem->lock);
}
- return virt_addr;
+ return NULL;
}
EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 1472aef0fb81..123c4c7c2ab5 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -118,6 +118,16 @@ config HOTPLUG_PCI_CPCI_GENERIC
When in doubt, say N.
+config HOTPLUG_PCI_OCTEONEP
+ bool "Marvell OCTEON PCI Hotplug driver"
+ depends on HOTPLUG_PCI
+ help
+ Say Y here if you have an OCTEON PCIe device with a hotplug
+ controller. This driver enables the non-controller functions of the
+ device to be registered as hotplug slots.
+
+ When in doubt, say N.
+
config HOTPLUG_PCI_SHPC
bool "SHPC PCI Hotplug driver"
help
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 240c99517d5e..40aaf31fe338 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_S390) += s390_pci_hpc.o
+obj-$(CONFIG_HOTPLUG_PCI_OCTEONEP) += octep_hp.o
# acpiphp_ibm extends acpiphp, so should be linked afterwards.
diff --git a/drivers/pci/hotplug/acpiphp_ampere_altra.c b/drivers/pci/hotplug/acpiphp_ampere_altra.c
index f5c9e741c1d4..70dbc0431fc6 100644
--- a/drivers/pci/hotplug/acpiphp_ampere_altra.c
+++ b/drivers/pci/hotplug/acpiphp_ampere_altra.c
@@ -119,7 +119,7 @@ static struct platform_driver altra_led_driver = {
.acpi_match_table = altra_led_ids,
},
.probe = altra_led_probe,
- .remove_new = altra_led_remove,
+ .remove = altra_led_remove,
};
module_platform_driver(altra_led_driver);
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
index 6d8970d8c3f2..03fa39ab0c88 100644
--- a/drivers/pci/hotplug/cpci_hotplug.h
+++ b/drivers/pci/hotplug/cpci_hotplug.h
@@ -44,7 +44,6 @@ struct cpci_hp_controller_ops {
int (*enable_irq)(void);
int (*disable_irq)(void);
int (*check_irq)(void *dev_id);
- int (*hardware_test)(struct slot *slot, u32 value);
u8 (*get_power)(struct slot *slot);
int (*set_power)(struct slot *slot, int value);
};
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
index 718bc6cf12cb..ef7534a3ca40 100644
--- a/drivers/pci/hotplug/cpqphp_pci.c
+++ b/drivers/pci/hotplug/cpqphp_pci.c
@@ -12,8 +12,11 @@
*
*/
+#define pr_fmt(fmt) "cpqphp: " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/printk.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -132,18 +135,6 @@ int cpqhp_unconfigure_device(struct pci_func *func)
return 0;
}
-static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value)
-{
- u32 vendID = 0;
-
- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
- return -1;
- if (PCI_POSSIBLE_ERROR(vendID))
- return -1;
- return pci_bus_read_config_dword(bus, devfn, offset, value);
-}
-
-
/*
* cpqhp_set_irq
*
@@ -202,13 +193,16 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_
{
u16 tdevice;
u32 work;
- u8 tbus;
+ int ret = -1;
ctrl->pci_bus->number = bus_num;
for (tdevice = 0; tdevice < 0xFF; tdevice++) {
/* Scan for access first */
- if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
+ if (!pci_bus_read_dev_vendor_id(ctrl->pci_bus, tdevice, &work, 0))
+ continue;
+ ret = pci_bus_read_config_dword(ctrl->pci_bus, tdevice, PCI_CLASS_REVISION, &work);
+ if (ret)
continue;
dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
/* Yep we got one. Not a bridge ? */
@@ -216,23 +210,20 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_
*dev_num = tdevice;
dbg("found it !\n");
return 0;
- }
- }
- for (tdevice = 0; tdevice < 0xFF; tdevice++) {
- /* Scan for access first */
- if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
- continue;
- dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
- /* Yep we got one. bridge ? */
- if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
- pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
- /* XXX: no recursion, wtf? */
- dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
- return 0;
+ } else {
+ /*
+ * XXX: Code whose debug printout indicated
+ * recursion to buses underneath bridges might be
+ * necessary was removed because it never did
+ * any recursion.
+ */
+ ret = 0;
+ pr_warn("missing feature: bridge scan recursion not implemented\n");
}
}
- return -1;
+
+ return ret;
}
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index fed1360ee9b1..6143ebf71f21 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -123,7 +123,6 @@ static int spew_debug_info(struct controller *ctrl, char *data, int size)
struct ctrl_dbg {
int size;
char *data;
- struct controller *ctrl;
};
#define MAX_OUTPUT (4*PAGE_SIZE)
diff --git a/drivers/pci/hotplug/octep_hp.c b/drivers/pci/hotplug/octep_hp.c
new file mode 100644
index 000000000000..2bce7296c050
--- /dev/null
+++ b/drivers/pci/hotplug/octep_hp.c
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2024 Marvell. */
+
+#include <linux/cleanup.h>
+#include <linux/container_of.h>
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#define OCTEP_HP_INTR_OFFSET(x) (0x20400 + ((x) << 4))
+#define OCTEP_HP_INTR_VECTOR(x) (16 + (x))
+#define OCTEP_HP_DRV_NAME "octep_hp"
+
+/*
+ * Type of MSI-X interrupts. OCTEP_HP_INTR_VECTOR() and
+ * OCTEP_HP_INTR_OFFSET() generate the vector and offset for an interrupt
+ * type.
+ */
+enum octep_hp_intr_type {
+ OCTEP_HP_INTR_INVALID = -1,
+ OCTEP_HP_INTR_ENA = 0,
+ OCTEP_HP_INTR_DIS = 1,
+ OCTEP_HP_INTR_MAX = 2,
+};
+
+struct octep_hp_cmd {
+ struct list_head list;
+ enum octep_hp_intr_type intr_type;
+ u64 intr_val;
+};
+
+struct octep_hp_slot {
+ struct list_head list;
+ struct hotplug_slot slot;
+ u16 slot_number;
+ struct pci_dev *hp_pdev;
+ unsigned int hp_devfn;
+ struct octep_hp_controller *ctrl;
+};
+
+struct octep_hp_intr_info {
+ enum octep_hp_intr_type type;
+ int number;
+ char name[16];
+};
+
+struct octep_hp_controller {
+ void __iomem *base;
+ struct pci_dev *pdev;
+ struct octep_hp_intr_info intr[OCTEP_HP_INTR_MAX];
+ struct work_struct work;
+ struct list_head slot_list;
+ struct mutex slot_lock; /* Protects slot_list */
+ struct list_head hp_cmd_list;
+ spinlock_t hp_cmd_lock; /* Protects hp_cmd_list */
+};
+
+static void octep_hp_enable_pdev(struct octep_hp_controller *hp_ctrl,
+ struct octep_hp_slot *hp_slot)
+{
+ guard(mutex)(&hp_ctrl->slot_lock);
+ if (hp_slot->hp_pdev) {
+ pci_dbg(hp_slot->hp_pdev, "Slot %s is already enabled\n",
+ hotplug_slot_name(&hp_slot->slot));
+ return;
+ }
+
+ /* Scan the device and add it to the bus */
+ hp_slot->hp_pdev = pci_scan_single_device(hp_ctrl->pdev->bus,
+ hp_slot->hp_devfn);
+ pci_bus_assign_resources(hp_ctrl->pdev->bus);
+ pci_bus_add_device(hp_slot->hp_pdev);
+
+ dev_dbg(&hp_slot->hp_pdev->dev, "Enabled slot %s\n",
+ hotplug_slot_name(&hp_slot->slot));
+}
+
+static void octep_hp_disable_pdev(struct octep_hp_controller *hp_ctrl,
+ struct octep_hp_slot *hp_slot)
+{
+ guard(mutex)(&hp_ctrl->slot_lock);
+ if (!hp_slot->hp_pdev) {
+ pci_dbg(hp_ctrl->pdev, "Slot %s is already disabled\n",
+ hotplug_slot_name(&hp_slot->slot));
+ return;
+ }
+
+ pci_dbg(hp_slot->hp_pdev, "Disabling slot %s\n",
+ hotplug_slot_name(&hp_slot->slot));
+
+ /* Remove the device from the bus */
+ pci_stop_and_remove_bus_device_locked(hp_slot->hp_pdev);
+ hp_slot->hp_pdev = NULL;
+}
+
+static int octep_hp_enable_slot(struct hotplug_slot *slot)
+{
+ struct octep_hp_slot *hp_slot =
+ container_of(slot, struct octep_hp_slot, slot);
+
+ octep_hp_enable_pdev(hp_slot->ctrl, hp_slot);
+ return 0;
+}
+
+static int octep_hp_disable_slot(struct hotplug_slot *slot)
+{
+ struct octep_hp_slot *hp_slot =
+ container_of(slot, struct octep_hp_slot, slot);
+
+ octep_hp_disable_pdev(hp_slot->ctrl, hp_slot);
+ return 0;
+}
+
+static struct hotplug_slot_ops octep_hp_slot_ops = {
+ .enable_slot = octep_hp_enable_slot,
+ .disable_slot = octep_hp_disable_slot,
+};
+
+#define SLOT_NAME_SIZE 16
+static struct octep_hp_slot *
+octep_hp_register_slot(struct octep_hp_controller *hp_ctrl,
+ struct pci_dev *pdev, u16 slot_number)
+{
+ char slot_name[SLOT_NAME_SIZE];
+ struct octep_hp_slot *hp_slot;
+ int ret;
+
+ hp_slot = kzalloc(sizeof(*hp_slot), GFP_KERNEL);
+ if (!hp_slot)
+ return ERR_PTR(-ENOMEM);
+
+ hp_slot->ctrl = hp_ctrl;
+ hp_slot->hp_pdev = pdev;
+ hp_slot->hp_devfn = pdev->devfn;
+ hp_slot->slot_number = slot_number;
+ hp_slot->slot.ops = &octep_hp_slot_ops;
+
+ snprintf(slot_name, sizeof(slot_name), "octep_hp_%u", slot_number);
+ ret = pci_hp_register(&hp_slot->slot, hp_ctrl->pdev->bus,
+ PCI_SLOT(pdev->devfn), slot_name);
+ if (ret) {
+ kfree(hp_slot);
+ return ERR_PTR(ret);
+ }
+
+ pci_info(pdev, "Registered slot %s for device %s\n",
+ slot_name, pci_name(pdev));
+
+ list_add_tail(&hp_slot->list, &hp_ctrl->slot_list);
+ octep_hp_disable_pdev(hp_ctrl, hp_slot);
+
+ return hp_slot;
+}
+
+static void octep_hp_deregister_slot(void *data)
+{
+ struct octep_hp_slot *hp_slot = data;
+ struct octep_hp_controller *hp_ctrl = hp_slot->ctrl;
+
+ pci_hp_deregister(&hp_slot->slot);
+ octep_hp_enable_pdev(hp_ctrl, hp_slot);
+ list_del(&hp_slot->list);
+ kfree(hp_slot);
+}
+
+static const char *octep_hp_cmd_name(enum octep_hp_intr_type type)
+{
+ switch (type) {
+ case OCTEP_HP_INTR_ENA:
+ return "hotplug enable";
+ case OCTEP_HP_INTR_DIS:
+ return "hotplug disable";
+ default:
+ return "invalid";
+ }
+}
+
+static void octep_hp_cmd_handler(struct octep_hp_controller *hp_ctrl,
+ struct octep_hp_cmd *hp_cmd)
+{
+ struct octep_hp_slot *hp_slot;
+
+ /*
+ * Enable or disable the slots based on the slot mask.
+ * intr_val is a bit mask where each bit represents a slot.
+ */
+ list_for_each_entry(hp_slot, &hp_ctrl->slot_list, list) {
+ if (!(hp_cmd->intr_val & BIT(hp_slot->slot_number)))
+ continue;
+
+ pci_info(hp_ctrl->pdev, "Received %s command for slot %s\n",
+ octep_hp_cmd_name(hp_cmd->intr_type),
+ hotplug_slot_name(&hp_slot->slot));
+
+ switch (hp_cmd->intr_type) {
+ case OCTEP_HP_INTR_ENA:
+ octep_hp_enable_pdev(hp_ctrl, hp_slot);
+ break;
+ case OCTEP_HP_INTR_DIS:
+ octep_hp_disable_pdev(hp_ctrl, hp_slot);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void octep_hp_work_handler(struct work_struct *work)
+{
+ struct octep_hp_controller *hp_ctrl;
+ struct octep_hp_cmd *hp_cmd;
+ unsigned long flags;
+
+ hp_ctrl = container_of(work, struct octep_hp_controller, work);
+
+ /* Process all the hotplug commands */
+ spin_lock_irqsave(&hp_ctrl->hp_cmd_lock, flags);
+ while (!list_empty(&hp_ctrl->hp_cmd_list)) {
+ hp_cmd = list_first_entry(&hp_ctrl->hp_cmd_list,
+ struct octep_hp_cmd, list);
+ list_del(&hp_cmd->list);
+ spin_unlock_irqrestore(&hp_ctrl->hp_cmd_lock, flags);
+
+ octep_hp_cmd_handler(hp_ctrl, hp_cmd);
+ kfree(hp_cmd);
+
+ spin_lock_irqsave(&hp_ctrl->hp_cmd_lock, flags);
+ }
+ spin_unlock_irqrestore(&hp_ctrl->hp_cmd_lock, flags);
+}
+
+static enum octep_hp_intr_type octep_hp_intr_type(struct octep_hp_intr_info *intr,
+ int irq)
+{
+ enum octep_hp_intr_type type;
+
+ for (type = OCTEP_HP_INTR_ENA; type < OCTEP_HP_INTR_MAX; type++) {
+ if (intr[type].number == irq)
+ return type;
+ }
+
+ return OCTEP_HP_INTR_INVALID;
+}
+
+static irqreturn_t octep_hp_intr_handler(int irq, void *data)
+{
+ struct octep_hp_controller *hp_ctrl = data;
+ struct pci_dev *pdev = hp_ctrl->pdev;
+ enum octep_hp_intr_type type;
+ struct octep_hp_cmd *hp_cmd;
+ u64 intr_val;
+
+ type = octep_hp_intr_type(hp_ctrl->intr, irq);
+ if (type == OCTEP_HP_INTR_INVALID) {
+ pci_err(pdev, "Invalid interrupt %d\n", irq);
+ return IRQ_HANDLED;
+ }
+
+ /* Read and clear the interrupt */
+ intr_val = readq(hp_ctrl->base + OCTEP_HP_INTR_OFFSET(type));
+ writeq(intr_val, hp_ctrl->base + OCTEP_HP_INTR_OFFSET(type));
+
+ hp_cmd = kzalloc(sizeof(*hp_cmd), GFP_ATOMIC);
+ if (!hp_cmd)
+ return IRQ_HANDLED;
+
+ hp_cmd->intr_val = intr_val;
+ hp_cmd->intr_type = type;
+
+ /* Add the command to the list and schedule the work */
+ spin_lock(&hp_ctrl->hp_cmd_lock);
+ list_add_tail(&hp_cmd->list, &hp_ctrl->hp_cmd_list);
+ spin_unlock(&hp_ctrl->hp_cmd_lock);
+ schedule_work(&hp_ctrl->work);
+
+ return IRQ_HANDLED;
+}
+
+static void octep_hp_irq_cleanup(void *data)
+{
+ struct octep_hp_controller *hp_ctrl = data;
+
+ pci_free_irq_vectors(hp_ctrl->pdev);
+ flush_work(&hp_ctrl->work);
+}
+
+static int octep_hp_request_irq(struct octep_hp_controller *hp_ctrl,
+ enum octep_hp_intr_type type)
+{
+ struct pci_dev *pdev = hp_ctrl->pdev;
+ struct octep_hp_intr_info *intr;
+ int irq;
+
+ irq = pci_irq_vector(pdev, OCTEP_HP_INTR_VECTOR(type));
+ if (irq < 0)
+ return irq;
+
+ intr = &hp_ctrl->intr[type];
+ intr->number = irq;
+ intr->type = type;
+ snprintf(intr->name, sizeof(intr->name), "octep_hp_%d", type);
+
+ return devm_request_irq(&pdev->dev, irq, octep_hp_intr_handler,
+ IRQF_SHARED, intr->name, hp_ctrl);
+}
+
+static int octep_hp_controller_setup(struct pci_dev *pdev,
+ struct octep_hp_controller *hp_ctrl)
+{
+ struct device *dev = &pdev->dev;
+ enum octep_hp_intr_type type;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable PCI device\n");
+
+ hp_ctrl->base = pcim_iomap_region(pdev, 0, OCTEP_HP_DRV_NAME);
+ if (IS_ERR(hp_ctrl->base))
+ return dev_err_probe(dev, PTR_ERR(hp_ctrl->base),
+ "Failed to map PCI device region\n");
+
+ pci_set_master(pdev);
+ pci_set_drvdata(pdev, hp_ctrl);
+
+ INIT_LIST_HEAD(&hp_ctrl->slot_list);
+ INIT_LIST_HEAD(&hp_ctrl->hp_cmd_list);
+ mutex_init(&hp_ctrl->slot_lock);
+ spin_lock_init(&hp_ctrl->hp_cmd_lock);
+ INIT_WORK(&hp_ctrl->work, octep_hp_work_handler);
+ hp_ctrl->pdev = pdev;
+
+ ret = pci_alloc_irq_vectors(pdev, 1,
+ OCTEP_HP_INTR_VECTOR(OCTEP_HP_INTR_MAX),
+ PCI_IRQ_MSIX);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to alloc MSI-X vectors\n");
+
+ ret = devm_add_action(&pdev->dev, octep_hp_irq_cleanup, hp_ctrl);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Failed to add IRQ cleanup action\n");
+
+ for (type = OCTEP_HP_INTR_ENA; type < OCTEP_HP_INTR_MAX; type++) {
+ ret = octep_hp_request_irq(hp_ctrl, type);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to request IRQ for vector %d\n",
+ OCTEP_HP_INTR_VECTOR(type));
+ }
+
+ return 0;
+}
+
+static int octep_hp_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct octep_hp_controller *hp_ctrl;
+ struct pci_dev *tmp_pdev, *next;
+ struct octep_hp_slot *hp_slot;
+ u16 slot_number = 0;
+ int ret;
+
+ hp_ctrl = devm_kzalloc(&pdev->dev, sizeof(*hp_ctrl), GFP_KERNEL);
+ if (!hp_ctrl)
+ return -ENOMEM;
+
+ ret = octep_hp_controller_setup(pdev, hp_ctrl);
+ if (ret)
+ return ret;
+
+ /*
+ * Register all hotplug slots. Hotplug controller is the first function
+ * of the PCI device. The hotplug slots are the remaining functions of
+ * the PCI device. The hotplug slot functions are logically removed from
+ * the bus during probing and are re-enabled by the driver when a
+ * hotplug event is received.
+ */
+ list_for_each_entry_safe(tmp_pdev, next, &pdev->bus->devices, bus_list) {
+ if (tmp_pdev == pdev)
+ continue;
+
+ hp_slot = octep_hp_register_slot(hp_ctrl, tmp_pdev, slot_number);
+ if (IS_ERR(hp_slot))
+ return dev_err_probe(&pdev->dev, PTR_ERR(hp_slot),
+ "Failed to register hotplug slot %u\n",
+ slot_number);
+
+ ret = devm_add_action(&pdev->dev, octep_hp_deregister_slot,
+ hp_slot);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to add action for deregistering slot %u\n",
+ slot_number);
+ slot_number++;
+ }
+
+ return 0;
+}
+
+#define PCI_DEVICE_ID_CAVIUM_OCTEP_HP_CTLR 0xa0e3
+static struct pci_device_id octep_hp_pci_map[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_OCTEP_HP_CTLR) },
+ { },
+};
+
+static struct pci_driver octep_hp = {
+ .name = OCTEP_HP_DRV_NAME,
+ .id_table = octep_hp_pci_map,
+ .probe = octep_hp_pci_probe,
+};
+
+module_pci_driver(octep_hp);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marvell");
+MODULE_DESCRIPTION("Marvell OCTEON PCI Hotplug driver");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 058d5937d8a9..36236ac88fd5 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -388,8 +388,8 @@ static struct hotplug_slot *get_slot_from_name(const char *name)
/**
* __pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
- * @bus: bus this slot is on
* @slot: pointer to the &struct hotplug_slot to register
+ * @bus: bus this slot is on
* @devnr: device number
* @name: name registered with kobject core
* @owner: caller module owner
@@ -498,8 +498,6 @@ EXPORT_SYMBOL_GPL(pci_hp_add);
*
* The @slot must have been registered with the pci hotplug subsystem
* previously with a call to pci_hp_register().
- *
- * Returns 0 if successful, anything else for an error.
*/
void pci_hp_deregister(struct hotplug_slot *slot)
{
@@ -513,8 +511,6 @@ EXPORT_SYMBOL_GPL(pci_hp_deregister);
* @slot: pointer to the &struct hotplug_slot to unpublish
*
* Remove a hotplug slot's sysfs interface.
- *
- * Returns 0 on success or a negative int on error.
*/
void pci_hp_del(struct hotplug_slot *slot)
{
@@ -545,8 +541,6 @@ EXPORT_SYMBOL_GPL(pci_hp_del);
* the driver may no longer invoke hotplug_slot_name() to get the slot's
* unique name. The driver no longer needs to handle a ->reset_slot callback
* from this point on.
- *
- * Returns 0 on success or a negative int on error.
*/
void pci_hp_destroy(struct hotplug_slot *slot)
{
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index dcdbfcf404dd..d603a7aa7483 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -19,6 +19,8 @@
#include <linux/types.h>
#include <linux/pm_runtime.h>
#include <linux/pci.h>
+
+#include "../pci.h"
#include "pciehp.h"
/* The following routines constitute the bulk of the
@@ -127,6 +129,9 @@ static void remove_board(struct controller *ctrl, bool safe_removal)
pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
INDICATOR_NOOP);
+
+ /* Don't carry LBMS indications across */
+ pcie_reset_lbms_count(ctrl->pcie->port);
}
static int pciehp_enable_slot(struct controller *ctrl);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 736ad8baa2a5..bb5a8d9f03ad 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -319,7 +319,7 @@ int pciehp_check_link_status(struct controller *ctrl)
return -1;
}
- pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
+ __pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
if (!found) {
ctrl_info(ctrl, "Slot(%s): No device found\n",
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index aaa33e8dc4c9..4be402fe9ab9 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -327,8 +327,8 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id)
virtfn->resource[i].name = pci_name(virtfn);
virtfn->resource[i].flags = res->flags;
size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
- virtfn->resource[i].start = res->start + size * id;
- virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
+ resource_set_range(&virtfn->resource[i],
+ res->start + size * id, size);
rc = request_resource(res, &virtfn->resource[i]);
BUG_ON(rc);
}
@@ -804,7 +804,7 @@ found:
goto failed;
}
iov->barsz[i] = resource_size(res);
- res->end = res->start + resource_size(res) * total - 1;
+ resource_set_size(res, resource_size(res) * total);
pci_info(dev, "%s %pR: contains BAR %d for %d VFs\n",
res_name, res, i, total);
i += bar64;
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index dacea3fc5128..52f770bcc481 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -728,6 +728,33 @@ out_free_name:
}
#endif
+/**
+ * of_pci_supply_present() - Check if the power supply is present for the PCI
+ * device
+ * @np: Device tree node
+ *
+ * Check if the power supply for the PCI device is present in the device tree
+ * node or not.
+ *
+ * Return: true if at least one power supply exists; false otherwise.
+ */
+bool of_pci_supply_present(struct device_node *np)
+{
+ struct property *prop;
+ char *supply;
+
+ if (!np)
+ return false;
+
+ for_each_property_of_node(np, prop) {
+ supply = strrchr(prop->name, '-');
+ if (supply && !strcmp(supply, "-supply"))
+ return true;
+ }
+
+ return false;
+}
+
#endif /* CONFIG_PCI */
/**
diff --git a/drivers/pci/of_property.c b/drivers/pci/of_property.c
index 5a0b98e69795..886c236e5de6 100644
--- a/drivers/pci/of_property.c
+++ b/drivers/pci/of_property.c
@@ -126,7 +126,7 @@ static int of_pci_prop_ranges(struct pci_dev *pdev, struct of_changeset *ocs,
if (of_pci_get_addr_flags(&res[j], &flags))
continue;
- val64 = res[j].start;
+ val64 = pci_bus_address(pdev, &res[j] - pdev->resource);
of_pci_set_address(pdev, rp[i].parent_addr, val64, 0, flags,
false);
if (pci_is_bridge(pdev)) {
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 4f47a13cb500..7abd4f546d3c 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -90,7 +90,7 @@ static ssize_t published_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RO(published);
static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, struct vm_area_struct *vma)
+ const struct bin_attribute *attr, struct vm_area_struct *vma)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
size_t len = vma->vm_end - vma->vm_start;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5d0f4db1cab7..7679d75d71e5 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -521,6 +521,31 @@ static ssize_t bus_rescan_store(struct device *dev,
static struct device_attribute dev_attr_bus_rescan = __ATTR(rescan, 0200, NULL,
bus_rescan_store);
+static ssize_t reset_subordinate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_bus *bus = pdev->subordinate;
+ unsigned long val;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (kstrtoul(buf, 0, &val) < 0)
+ return -EINVAL;
+
+ if (val) {
+ int ret = __pci_reset_bus(bus);
+
+ if (ret)
+ return ret;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_WO(reset_subordinate);
+
#if defined(CONFIG_PM) && defined(CONFIG_ACPI)
static ssize_t d3cold_allowed_store(struct device *dev,
struct device_attribute *attr,
@@ -625,6 +650,7 @@ static struct attribute *pci_dev_attrs[] = {
static struct attribute *pci_bridge_attrs[] = {
&dev_attr_subordinate_bus_number.attr,
&dev_attr_secondary_bus_number.attr,
+ &dev_attr_reset_subordinate.attr,
NULL,
};
@@ -818,21 +844,20 @@ static struct bin_attribute *pci_dev_config_attrs[] = {
NULL,
};
-static umode_t pci_dev_config_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+static size_t pci_dev_config_attr_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- a->size = PCI_CFG_SPACE_SIZE;
if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
- a->size = PCI_CFG_SPACE_EXP_SIZE;
-
- return a->attr.mode;
+ return PCI_CFG_SPACE_EXP_SIZE;
+ return PCI_CFG_SPACE_SIZE;
}
static const struct attribute_group pci_dev_config_attr_group = {
.bin_attrs = pci_dev_config_attrs,
- .is_bin_visible = pci_dev_config_attr_is_visible,
+ .bin_size = pci_dev_config_attr_bin_size,
};
/*
@@ -842,7 +867,7 @@ static const struct attribute_group pci_dev_config_attr_group = {
static __maybe_unused loff_t
pci_llseek_resource(struct file *filep,
struct kobject *kobj __always_unused,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
loff_t offset, int whence)
{
return fixed_size_llseek(filep, offset, whence, attr->size);
@@ -911,7 +936,7 @@ static ssize_t pci_write_legacy_io(struct file *filp, struct kobject *kobj,
* memory space.
*/
static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
@@ -931,7 +956,7 @@ static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
* memory space. Returns -ENOSYS if the operation isn't supported
*/
static int pci_mmap_legacy_io(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
@@ -1035,7 +1060,7 @@ void pci_remove_legacy_files(struct pci_bus *b)
*
* Use the regular PCI mapping routines to map a PCI resource into userspace.
*/
-static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *attr,
struct vm_area_struct *vma, int write_combine)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
@@ -1060,14 +1085,14 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
}
static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 0);
}
static int pci_mmap_resource_wc(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 1);
@@ -1327,24 +1352,29 @@ static struct bin_attribute *pci_dev_rom_attrs[] = {
};
static umode_t pci_dev_rom_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- size_t rom_size;
/* If the device has a ROM, try to expose it in sysfs. */
- rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- if (!rom_size)
+ if (!pci_resource_end(pdev, PCI_ROM_RESOURCE))
return 0;
- a->size = rom_size;
-
return a->attr.mode;
}
+static size_t pci_dev_rom_attr_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a, int n)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+
+ return pci_resource_len(pdev, PCI_ROM_RESOURCE);
+}
+
static const struct attribute_group pci_dev_rom_attr_group = {
.bin_attrs = pci_dev_rom_attrs,
.is_bin_visible = pci_dev_rom_attr_is_visible,
+ .bin_size = pci_dev_rom_attr_bin_size,
};
static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 225a6cd2e9ca..0b29ec6e8e5e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1832,6 +1832,7 @@ int pci_save_state(struct pci_dev *dev)
pci_save_dpc_state(dev);
pci_save_aer_state(dev);
pci_save_ptm_state(dev);
+ pci_save_tph_state(dev);
return pci_save_vc_state(dev);
}
EXPORT_SYMBOL(pci_save_state);
@@ -1937,6 +1938,7 @@ void pci_restore_state(struct pci_dev *dev)
pci_restore_rebar_state(dev);
pci_restore_dpc_state(dev);
pci_restore_ptm_state(dev);
+ pci_restore_tph_state(dev);
pci_aer_clear_status(dev);
pci_restore_aer_state(dev);
@@ -4167,7 +4169,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
* Record the PCI IO range (expressed as CPU physical address + size).
* Return a negative value if an error has occurred, zero otherwise
*/
-int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+int pci_register_io_range(const struct fwnode_handle *fwnode, phys_addr_t addr,
resource_size_t size)
{
int ret = 0;
@@ -4744,7 +4746,7 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt)
* to track link speed or width changes made by hardware itself
* in attempt to correct unreliable link operation.
*/
- pcie_capability_write_word(pdev, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS);
+ pcie_reset_lbms_count(pdev);
return rc;
}
@@ -5162,6 +5164,8 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
*/
if (err_handler && err_handler->reset_prepare)
err_handler->reset_prepare(dev);
+ else if (dev->driver)
+ pci_warn(dev, "resetting");
/*
* Wake-up device prior to save. PM registers default to D0 after
@@ -5195,6 +5199,8 @@ static void pci_dev_restore(struct pci_dev *dev)
*/
if (err_handler && err_handler->reset_done)
err_handler->reset_done(dev);
+ else if (dev->driver)
+ pci_warn(dev, "reset done");
}
/* dev->reset_methods[] is a 0-terminated list of indices into this array */
@@ -5248,7 +5254,7 @@ static ssize_t reset_method_store(struct device *dev,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
- char *options, *name;
+ char *options, *tmp_options, *name;
int m, n;
u8 reset_methods[PCI_NUM_RESET_METHODS] = { 0 };
@@ -5268,7 +5274,8 @@ static ssize_t reset_method_store(struct device *dev,
return -ENOMEM;
n = 0;
- while ((name = strsep(&options, " ")) != NULL) {
+ tmp_options = options;
+ while ((name = strsep(&tmp_options, " ")) != NULL) {
if (sysfs_streq(name, ""))
continue;
@@ -5884,7 +5891,7 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_bus);
*
* Same as above except return -EAGAIN if the bus cannot be locked
*/
-static int __pci_reset_bus(struct pci_bus *bus)
+int __pci_reset_bus(struct pci_bus *bus)
{
int rc;
@@ -6193,38 +6200,64 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
EXPORT_SYMBOL(pcie_bandwidth_available);
/**
- * pcie_get_speed_cap - query for the PCI device's link speed capability
+ * pcie_get_supported_speeds - query Supported Link Speed Vector
* @dev: PCI device to query
*
- * Query the PCI device speed capability. Return the maximum link speed
- * supported by the device.
+ * Query @dev supported link speeds.
+ *
+ * Implementation Note in PCIe r6.0 sec 7.5.3.18 recommends determining
+ * supported link speeds using the Supported Link Speeds Vector in the Link
+ * Capabilities 2 Register (when available).
+ *
+ * Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18.
+ *
+ * Without Link Capabilities 2, i.e., prior to PCIe r3.0, Supported Link
+ * Speeds field in Link Capabilities is used and only 2.5 GT/s and 5.0 GT/s
+ * speeds were defined.
+ *
+ * For @dev without Supported Link Speed Vector, the field is synthesized
+ * from the Max Link Speed field in the Link Capabilities Register.
+ *
+ * Return: Supported Link Speeds Vector (+ reserved 0 at LSB).
*/
-enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
+u8 pcie_get_supported_speeds(struct pci_dev *dev)
{
u32 lnkcap2, lnkcap;
+ u8 speeds;
/*
- * Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18. The
- * implementation note there recommends using the Supported Link
- * Speeds Vector in Link Capabilities 2 when supported.
- *
- * Without Link Capabilities 2, i.e., prior to PCIe r3.0, software
- * should use the Supported Link Speeds field in Link Capabilities,
- * where only 2.5 GT/s and 5.0 GT/s speeds were defined.
+ * Speeds retain the reserved 0 at LSB before PCIe Supported Link
+ * Speeds Vector to allow using SLS Vector bit defines directly.
*/
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
+ speeds = lnkcap2 & PCI_EXP_LNKCAP2_SLS;
/* PCIe r3.0-compliant */
- if (lnkcap2)
- return PCIE_LNKCAP2_SLS2SPEED(lnkcap2);
+ if (speeds)
+ return speeds;
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
+
+ /* Synthesize from the Max Link Speed field */
if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB)
- return PCIE_SPEED_5_0GT;
+ speeds = PCI_EXP_LNKCAP2_SLS_5_0GB | PCI_EXP_LNKCAP2_SLS_2_5GB;
else if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_2_5GB)
- return PCIE_SPEED_2_5GT;
+ speeds = PCI_EXP_LNKCAP2_SLS_2_5GB;
- return PCI_SPEED_UNKNOWN;
+ return speeds;
+}
+
+/**
+ * pcie_get_speed_cap - query for the PCI device's link speed capability
+ * @dev: PCI device to query
+ *
+ * Query the PCI device speed capability.
+ *
+ * Return: the maximum link speed supported by the device.
+ */
+enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
+{
+ return PCIE_LNKCAP2_SLS2SPEED(dev->supported_speeds);
}
EXPORT_SYMBOL(pcie_get_speed_cap);
@@ -6653,8 +6686,7 @@ static void pci_request_resource_alignment(struct pci_dev *dev, int bar,
} else {
r->flags &= ~IORESOURCE_SIZEALIGN;
r->flags |= IORESOURCE_STARTALIGN;
- r->start = align;
- r->end = r->start + size - 1;
+ resource_set_range(r, align, size);
}
r->flags |= IORESOURCE_UNSET;
}
@@ -6900,6 +6932,8 @@ static int __init pci_setup(char *str)
pci_no_domains();
} else if (!strncmp(str, "noari", 5)) {
pcie_ari_disabled = true;
+ } else if (!strncmp(str, "notph", 5)) {
+ pci_no_tph();
} else if (!strncmp(str, "cbiosize=", 9)) {
pci_cardbus_io_size = memparse(str + 9, &str);
} else if (!strncmp(str, "cbmemsize=", 10)) {
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 14d00ce45bfa..2e40fc63ba31 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -104,6 +104,7 @@ bool pci_reset_supported(struct pci_dev *dev);
void pci_init_reset_methods(struct pci_dev *dev);
int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
int pci_bus_error_reset(struct pci_dev *dev);
+int __pci_reset_bus(struct pci_bus *bus);
struct pci_cap_saved_data {
u16 cap_nr;
@@ -323,6 +324,9 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
struct list_head *realloc_head,
struct list_head *fail_head);
bool pci_bus_clip_resource(struct pci_dev *dev, int idx);
+void pci_walk_bus_locked(struct pci_bus *top,
+ int (*cb)(struct pci_dev *, void *),
+ void *userdata);
const char *pci_resource_name(struct pci_dev *dev, unsigned int i);
@@ -331,6 +335,17 @@ void pci_disable_bridge_window(struct pci_dev *dev);
struct pci_bus *pci_bus_get(struct pci_bus *bus);
void pci_bus_put(struct pci_bus *bus);
+#define PCIE_LNKCAP_SLS2SPEED(lnkcap) \
+({ \
+ ((lnkcap) == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
+ (lnkcap) == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
+ (lnkcap) == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
+ (lnkcap) == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
+ (lnkcap) == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \
+ (lnkcap) == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \
+ PCI_SPEED_UNKNOWN); \
+})
+
/* PCIe link information from Link Capabilities 2 */
#define PCIE_LNKCAP2_SLS2SPEED(lnkcap2) \
((lnkcap2) & PCI_EXP_LNKCAP2_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
@@ -341,6 +356,15 @@ void pci_bus_put(struct pci_bus *bus);
(lnkcap2) & PCI_EXP_LNKCAP2_SLS_2_5GB ? PCIE_SPEED_2_5GT : \
PCI_SPEED_UNKNOWN)
+#define PCIE_LNKCTL2_TLS2SPEED(lnkctl2) \
+ ((lnkctl2) == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \
+ (lnkctl2) == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \
+ (lnkctl2) == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \
+ (lnkctl2) == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \
+ (lnkctl2) == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \
+ (lnkctl2) == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \
+ PCI_SPEED_UNKNOWN)
+
/* PCIe speed to Mb/s reduced by encoding overhead */
#define PCIE_SPEED2MBS_ENC(speed) \
((speed) == PCIE_SPEED_64_0GT ? 64000*1/1 : \
@@ -373,12 +397,16 @@ static inline int pcie_dev_speed_mbps(enum pci_bus_speed speed)
return -EINVAL;
}
+u8 pcie_get_supported_speeds(struct pci_dev *dev);
const char *pci_speed_string(enum pci_bus_speed speed);
-enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev);
-enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev);
void __pcie_print_link_status(struct pci_dev *dev, bool verbose);
void pcie_report_downtraining(struct pci_dev *dev);
-void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
+
+static inline void __pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
+{
+ bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
+}
+void pcie_update_link_speed(struct pci_bus *bus);
/* Single Root I/O Virtualization */
struct pci_sriov {
@@ -469,10 +497,18 @@ static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
#define PCI_DEV_ADDED 0
#define PCI_DPC_RECOVERED 1
#define PCI_DPC_RECOVERING 2
+#define PCI_DEV_REMOVED 3
-static inline void pci_dev_assign_added(struct pci_dev *dev, bool added)
+static inline void pci_dev_assign_added(struct pci_dev *dev)
{
- assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added);
+ smp_mb__before_atomic();
+ set_bit(PCI_DEV_ADDED, &dev->priv_flags);
+ smp_mb__after_atomic();
+}
+
+static inline bool pci_dev_test_and_clear_added(struct pci_dev *dev)
+{
+ return test_and_clear_bit(PCI_DEV_ADDED, &dev->priv_flags);
}
static inline bool pci_dev_is_added(const struct pci_dev *dev)
@@ -480,6 +516,11 @@ static inline bool pci_dev_is_added(const struct pci_dev *dev)
return test_bit(PCI_DEV_ADDED, &dev->priv_flags);
}
+static inline bool pci_dev_test_and_set_removed(struct pci_dev *dev)
+{
+ return test_and_set_bit(PCI_DEV_REMOVED, &dev->priv_flags);
+}
+
#ifdef CONFIG_PCIEAER
#include <linux/aer.h>
@@ -597,6 +638,18 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
#endif /* CONFIG_PCI_IOV */
+#ifdef CONFIG_PCIE_TPH
+void pci_restore_tph_state(struct pci_dev *dev);
+void pci_save_tph_state(struct pci_dev *dev);
+void pci_no_tph(void);
+void pci_tph_init(struct pci_dev *dev);
+#else
+static inline void pci_restore_tph_state(struct pci_dev *dev) { }
+static inline void pci_save_tph_state(struct pci_dev *dev) { }
+static inline void pci_no_tph(void) { }
+static inline void pci_tph_init(struct pci_dev *dev) { }
+#endif
+
#ifdef CONFIG_PCIE_PTM
void pci_ptm_init(struct pci_dev *dev);
void pci_save_ptm_state(struct pci_dev *dev);
@@ -692,6 +745,17 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
static inline void pcie_ecrc_get_policy(char *str) { }
#endif
+#ifdef CONFIG_PCIEPORTBUS
+void pcie_reset_lbms_count(struct pci_dev *port);
+int pcie_lbms_count(struct pci_dev *port, unsigned long *val);
+#else
+static inline void pcie_reset_lbms_count(struct pci_dev *port) {}
+static inline int pcie_lbms_count(struct pci_dev *port, unsigned long *val)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
struct pci_dev_reset_methods {
u16 vendor;
u16 device;
@@ -746,6 +810,7 @@ void pci_set_bus_of_node(struct pci_bus *bus);
void pci_release_bus_of_node(struct pci_bus *bus);
int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge);
+bool of_pci_supply_present(struct device_node *np);
#else
static inline int
@@ -793,6 +858,10 @@ static inline int devm_of_pci_bridge_init(struct device *dev, struct pci_host_br
return 0;
}
+static inline bool of_pci_supply_present(struct device_node *np)
+{
+ return false;
+}
#endif /* CONFIG_OF */
struct of_changeset;
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index 6461aa93fe76..53ccab62314d 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -4,7 +4,7 @@
pcieportdrv-y := portdrv.o rcec.o
-obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
+obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o bwctrl.o
obj-y += aspm.o
obj-$(CONFIG_PCIEAER) += aer.o err.o
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 13b8586924ea..80c5ba8d8296 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -180,7 +180,8 @@ static int disable_ecrc_checking(struct pci_dev *dev)
}
/**
- * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
+ * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based
+ * on global policy
* @dev: the PCI device
*/
void pcie_set_ecrc_checking(struct pci_dev *dev)
@@ -1148,14 +1149,16 @@ static void aer_recover_work_func(struct work_struct *work)
continue;
}
pci_print_aer(pdev, entry.severity, entry.regs);
+
/*
- * Memory for aer_capability_regs(entry.regs) is being allocated from the
- * ghes_estatus_pool to protect it from overwriting when multiple sections
- * are present in the error status. Thus free the same after processing
- * the data.
+ * Memory for aer_capability_regs(entry.regs) is being
+ * allocated from the ghes_estatus_pool to protect it from
+ * overwriting when multiple sections are present in the
+ * error status. Thus free the same after processing the
+ * data.
*/
ghes_estatus_pool_region_free((unsigned long)entry.regs,
- sizeof(struct aer_capability_regs));
+ sizeof(struct aer_capability_regs));
if (entry.severity == AER_NONFATAL)
pcie_do_recovery(pdev, pci_channel_io_normal,
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index cee2365e54b8..28567d457613 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -805,6 +805,15 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &parent_lnkctl);
pcie_capability_read_word(child, PCI_EXP_LNKCTL, &child_lnkctl);
+ /* Disable L0s/L1 before updating L1SS config */
+ if (FIELD_GET(PCI_EXP_LNKCTL_ASPMC, child_lnkctl) ||
+ FIELD_GET(PCI_EXP_LNKCTL_ASPMC, parent_lnkctl)) {
+ pcie_capability_write_word(child, PCI_EXP_LNKCTL,
+ child_lnkctl & ~PCI_EXP_LNKCTL_ASPMC);
+ pcie_capability_write_word(parent, PCI_EXP_LNKCTL,
+ parent_lnkctl & ~PCI_EXP_LNKCTL_ASPMC);
+ }
+
/*
* Setup L0s state
*
@@ -829,6 +838,13 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
aspm_l1ss_init(link);
+ /* Restore L0s/L1 if they were enabled */
+ if (FIELD_GET(PCI_EXP_LNKCTL_ASPMC, child_lnkctl) ||
+ FIELD_GET(PCI_EXP_LNKCTL_ASPMC, parent_lnkctl)) {
+ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_lnkctl);
+ pcie_capability_write_word(child, PCI_EXP_LNKCTL, child_lnkctl);
+ }
+
/* Save default state */
link->aspm_default = link->aspm_enabled;
@@ -845,25 +861,28 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
}
}
-/* Configure the ASPM L1 substates */
+/* Configure the ASPM L1 substates. Caller must disable L1 first. */
static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state)
{
- u32 val, enable_req;
+ u32 val;
struct pci_dev *child = link->downstream, *parent = link->pdev;
- enable_req = (link->aspm_enabled ^ state) & state;
+ val = 0;
+ if (state & PCIE_LINK_STATE_L1_1)
+ val |= PCI_L1SS_CTL1_ASPM_L1_1;
+ if (state & PCIE_LINK_STATE_L1_2)
+ val |= PCI_L1SS_CTL1_ASPM_L1_2;
+ if (state & PCIE_LINK_STATE_L1_1_PCIPM)
+ val |= PCI_L1SS_CTL1_PCIPM_L1_1;
+ if (state & PCIE_LINK_STATE_L1_2_PCIPM)
+ val |= PCI_L1SS_CTL1_PCIPM_L1_2;
/*
- * Here are the rules specified in the PCIe spec for enabling L1SS:
- * - When enabling L1.x, enable bit at parent first, then at child
- * - When disabling L1.x, disable bit at child first, then at parent
- * - When enabling ASPM L1.x, need to disable L1
- * (at child followed by parent).
- * - The ASPM/PCIPM L1.2 must be disabled while programming timing
+ * PCIe r6.2, sec 5.5.4, rules for enabling L1 PM Substates:
+ * - Clear L1.x enable bits at child first, then at parent
+ * - Set L1.x enable bits at parent first, then at child
+ * - ASPM/PCIPM L1.2 must be disabled while programming timing
* parameters
- *
- * To keep it simple, disable all L1SS bits first, and later enable
- * what is needed.
*/
/* Disable all L1 substates */
@@ -871,26 +890,6 @@ static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state)
PCI_L1SS_CTL1_L1SS_MASK, 0);
pci_clear_and_set_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
PCI_L1SS_CTL1_L1SS_MASK, 0);
- /*
- * If needed, disable L1, and it gets enabled later
- * in pcie_config_aspm_link().
- */
- if (enable_req & (PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2)) {
- pcie_capability_clear_word(child, PCI_EXP_LNKCTL,
- PCI_EXP_LNKCTL_ASPM_L1);
- pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
- PCI_EXP_LNKCTL_ASPM_L1);
- }
-
- val = 0;
- if (state & PCIE_LINK_STATE_L1_1)
- val |= PCI_L1SS_CTL1_ASPM_L1_1;
- if (state & PCIE_LINK_STATE_L1_2)
- val |= PCI_L1SS_CTL1_ASPM_L1_2;
- if (state & PCIE_LINK_STATE_L1_1_PCIPM)
- val |= PCI_L1SS_CTL1_PCIPM_L1_1;
- if (state & PCIE_LINK_STATE_L1_2_PCIPM)
- val |= PCI_L1SS_CTL1_PCIPM_L1_2;
/* Enable what we need to enable */
pci_clear_and_set_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
@@ -937,21 +936,30 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
}
+ /*
+ * Per PCIe r6.2, sec 5.5.4, setting either or both of the enable
+ * bits for ASPM L1 PM Substates must be done while ASPM L1 is
+ * disabled. Disable L1 here and apply new configuration after L1SS
+ * configuration has been completed.
+ *
+ * Per sec 7.5.3.7, when disabling ASPM L1, software must disable
+ * it in the Downstream component prior to disabling it in the
+ * Upstream component, and ASPM L1 must be enabled in the Upstream
+ * component prior to enabling it in the Downstream component.
+ *
+ * Sec 7.5.3.7 also recommends programming the same ASPM Control
+ * value for all functions of a multi-function device.
+ */
+ list_for_each_entry(child, &linkbus->devices, bus_list)
+ pcie_config_aspm_dev(child, 0);
+ pcie_config_aspm_dev(parent, 0);
+
if (link->aspm_capable & PCIE_LINK_STATE_L1SS)
pcie_config_aspm_l1ss(link, state);
- /*
- * Spec 2.0 suggests all functions should be configured the
- * same setting for ASPM. Enabling ASPM L1 should be done in
- * upstream component first and then downstream, and vice
- * versa for disabling ASPM L1. Spec doesn't mention L0S.
- */
- if (state & PCIE_LINK_STATE_L1)
- pcie_config_aspm_dev(parent, upstream);
+ pcie_config_aspm_dev(parent, upstream);
list_for_each_entry(child, &linkbus->devices, bus_list)
pcie_config_aspm_dev(child, dwstream);
- if (!(state & PCIE_LINK_STATE_L1))
- pcie_config_aspm_dev(parent, upstream);
link->aspm_enabled = state;
@@ -1442,6 +1450,9 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
* touch the LNKCTL register. Also note that this does not enable states
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
*
+ * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
+ * PCIe r6.0, sec 5.5.4.
+ *
* @pdev: PCI device
* @state: Mask of ASPM link states to enable
*/
@@ -1458,6 +1469,9 @@ EXPORT_SYMBOL(pci_enable_link_state);
* can't touch the LNKCTL register. Also note that this does not enable states
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
*
+ * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
+ * PCIe r6.0, sec 5.5.4.
+ *
* @pdev: PCI device
* @state: Mask of ASPM link states to enable
*
diff --git a/drivers/pci/pcie/bwctrl.c b/drivers/pci/pcie/bwctrl.c
new file mode 100644
index 000000000000..b59cacc740fa
--- /dev/null
+++ b/drivers/pci/pcie/bwctrl.c
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PCIe bandwidth controller
+ *
+ * Author: Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ *
+ * Copyright (C) 2019 Dell Inc
+ * Copyright (C) 2023-2024 Intel Corporation
+ *
+ * The PCIe bandwidth controller provides a way to alter PCIe Link Speeds
+ * and notify the operating system when the Link Width or Speed changes. The
+ * notification capability is required for all Root Ports and Downstream
+ * Ports supporting Link Width wider than x1 and/or multiple Link Speeds.
+ *
+ * This service port driver hooks into the Bandwidth Notification interrupt
+ * watching for changes or links becoming degraded in operation. It updates
+ * the cached Current Link Speed that is exposed to user space through sysfs.
+ */
+
+#define dev_fmt(fmt) "bwctrl: " fmt
+
+#include <linux/atomic.h>
+#include <linux/bitops.h>
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pci-bwctrl.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "../pci.h"
+#include "portdrv.h"
+
+/**
+ * struct pcie_bwctrl_data - PCIe bandwidth controller
+ * @set_speed_mutex: Serializes link speed changes
+ * @lbms_count: Count for LBMS (since last reset)
+ * @cdev: Thermal cooling device associated with the port
+ */
+struct pcie_bwctrl_data {
+ struct mutex set_speed_mutex;
+ atomic_t lbms_count;
+ struct thermal_cooling_device *cdev;
+};
+
+/*
+ * Prevent port removal during LBMS count accessors and Link Speed changes.
+ *
+ * These have to be differentiated because pcie_bwctrl_change_speed() calls
+ * pcie_retrain_link() which uses LBMS count reset accessor on success
+ * (using just one rwsem triggers "possible recursive locking detected"
+ * warning).
+ */
+static DECLARE_RWSEM(pcie_bwctrl_lbms_rwsem);
+static DECLARE_RWSEM(pcie_bwctrl_setspeed_rwsem);
+
+static bool pcie_valid_speed(enum pci_bus_speed speed)
+{
+ return (speed >= PCIE_SPEED_2_5GT) && (speed <= PCIE_SPEED_64_0GT);
+}
+
+static u16 pci_bus_speed2lnkctl2(enum pci_bus_speed speed)
+{
+ static const u8 speed_conv[] = {
+ [PCIE_SPEED_2_5GT] = PCI_EXP_LNKCTL2_TLS_2_5GT,
+ [PCIE_SPEED_5_0GT] = PCI_EXP_LNKCTL2_TLS_5_0GT,
+ [PCIE_SPEED_8_0GT] = PCI_EXP_LNKCTL2_TLS_8_0GT,
+ [PCIE_SPEED_16_0GT] = PCI_EXP_LNKCTL2_TLS_16_0GT,
+ [PCIE_SPEED_32_0GT] = PCI_EXP_LNKCTL2_TLS_32_0GT,
+ [PCIE_SPEED_64_0GT] = PCI_EXP_LNKCTL2_TLS_64_0GT,
+ };
+
+ if (WARN_ON_ONCE(!pcie_valid_speed(speed)))
+ return 0;
+
+ return speed_conv[speed];
+}
+
+static inline u16 pcie_supported_speeds2target_speed(u8 supported_speeds)
+{
+ return __fls(supported_speeds);
+}
+
+/**
+ * pcie_bwctrl_select_speed - Select Target Link Speed
+ * @port: PCIe Port
+ * @speed_req: Requested PCIe Link Speed
+ *
+ * Select Target Link Speed by take into account Supported Link Speeds of
+ * both the Root Port and the Endpoint.
+ *
+ * Return: Target Link Speed (1=2.5GT/s, 2=5GT/s, 3=8GT/s, etc.)
+ */
+static u16 pcie_bwctrl_select_speed(struct pci_dev *port, enum pci_bus_speed speed_req)
+{
+ struct pci_bus *bus = port->subordinate;
+ u8 desired_speeds, supported_speeds;
+ struct pci_dev *dev;
+
+ desired_speeds = GENMASK(pci_bus_speed2lnkctl2(speed_req),
+ __fls(PCI_EXP_LNKCAP2_SLS_2_5GB));
+
+ supported_speeds = port->supported_speeds;
+ if (bus) {
+ down_read(&pci_bus_sem);
+ dev = list_first_entry_or_null(&bus->devices, struct pci_dev, bus_list);
+ if (dev)
+ supported_speeds &= dev->supported_speeds;
+ up_read(&pci_bus_sem);
+ }
+ if (!supported_speeds)
+ return PCI_EXP_LNKCAP2_SLS_2_5GB;
+
+ return pcie_supported_speeds2target_speed(supported_speeds & desired_speeds);
+}
+
+static int pcie_bwctrl_change_speed(struct pci_dev *port, u16 target_speed, bool use_lt)
+{
+ int ret;
+
+ ret = pcie_capability_clear_and_set_word(port, PCI_EXP_LNKCTL2,
+ PCI_EXP_LNKCTL2_TLS, target_speed);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return pcibios_err_to_errno(ret);
+
+ ret = pcie_retrain_link(port, use_lt);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Ensure link speed updates also with platforms that have problems
+ * with notifications.
+ */
+ if (port->subordinate)
+ pcie_update_link_speed(port->subordinate);
+
+ return 0;
+}
+
+/**
+ * pcie_set_target_speed - Set downstream Link Speed for PCIe Port
+ * @port: PCIe Port
+ * @speed_req: Requested PCIe Link Speed
+ * @use_lt: Wait for the LT or DLLLA bit to detect the end of link training
+ *
+ * Attempt to set PCIe Port Link Speed to @speed_req. @speed_req may be
+ * adjusted downwards to the best speed supported by both the Port and PCIe
+ * Device underneath it.
+ *
+ * Return:
+ * * 0 - on success
+ * * -EINVAL - @speed_req is not a PCIe Link Speed
+ * * -ENODEV - @port is not controllable
+ * * -ETIMEDOUT - changing Link Speed took too long
+ * * -EAGAIN - Link Speed was changed but @speed_req was not achieved
+ */
+int pcie_set_target_speed(struct pci_dev *port, enum pci_bus_speed speed_req,
+ bool use_lt)
+{
+ struct pci_bus *bus = port->subordinate;
+ u16 target_speed;
+ int ret;
+
+ if (WARN_ON_ONCE(!pcie_valid_speed(speed_req)))
+ return -EINVAL;
+
+ if (bus && bus->cur_bus_speed == speed_req)
+ return 0;
+
+ target_speed = pcie_bwctrl_select_speed(port, speed_req);
+
+ scoped_guard(rwsem_read, &pcie_bwctrl_setspeed_rwsem) {
+ struct pcie_bwctrl_data *data = port->link_bwctrl;
+
+ /*
+ * port->link_bwctrl is NULL during initial scan when called
+ * e.g. from the Target Speed quirk.
+ */
+ if (data)
+ mutex_lock(&data->set_speed_mutex);
+
+ ret = pcie_bwctrl_change_speed(port, target_speed, use_lt);
+
+ if (data)
+ mutex_unlock(&data->set_speed_mutex);
+ }
+
+ /*
+ * Despite setting higher speed into the Target Link Speed, empty
+ * bus won't train to 5GT+ speeds.
+ */
+ if (!ret && bus && bus->cur_bus_speed != speed_req &&
+ !list_empty(&bus->devices))
+ ret = -EAGAIN;
+
+ return ret;
+}
+
+static void pcie_bwnotif_enable(struct pcie_device *srv)
+{
+ struct pcie_bwctrl_data *data = srv->port->link_bwctrl;
+ struct pci_dev *port = srv->port;
+ u16 link_status;
+ int ret;
+
+ /* Count LBMS seen so far as one */
+ ret = pcie_capability_read_word(port, PCI_EXP_LNKSTA, &link_status);
+ if (ret == PCIBIOS_SUCCESSFUL && link_status & PCI_EXP_LNKSTA_LBMS)
+ atomic_inc(&data->lbms_count);
+
+ pcie_capability_set_word(port, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE);
+ pcie_capability_write_word(port, PCI_EXP_LNKSTA,
+ PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS);
+
+ /*
+ * Update after enabling notifications & clearing status bits ensures
+ * link speed is up to date.
+ */
+ pcie_update_link_speed(port->subordinate);
+}
+
+static void pcie_bwnotif_disable(struct pci_dev *port)
+{
+ pcie_capability_clear_word(port, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE);
+}
+
+static irqreturn_t pcie_bwnotif_irq(int irq, void *context)
+{
+ struct pcie_device *srv = context;
+ struct pcie_bwctrl_data *data = srv->port->link_bwctrl;
+ struct pci_dev *port = srv->port;
+ u16 link_status, events;
+ int ret;
+
+ ret = pcie_capability_read_word(port, PCI_EXP_LNKSTA, &link_status);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return IRQ_NONE;
+
+ events = link_status & (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS);
+ if (!events)
+ return IRQ_NONE;
+
+ if (events & PCI_EXP_LNKSTA_LBMS)
+ atomic_inc(&data->lbms_count);
+
+ pcie_capability_write_word(port, PCI_EXP_LNKSTA, events);
+
+ /*
+ * Interrupts will not be triggered from any further Link Speed
+ * change until LBMS is cleared by the write. Therefore, re-read the
+ * speed (inside pcie_update_link_speed()) after LBMS has been
+ * cleared to avoid missing link speed changes.
+ */
+ pcie_update_link_speed(port->subordinate);
+
+ return IRQ_HANDLED;
+}
+
+void pcie_reset_lbms_count(struct pci_dev *port)
+{
+ struct pcie_bwctrl_data *data;
+
+ guard(rwsem_read)(&pcie_bwctrl_lbms_rwsem);
+ data = port->link_bwctrl;
+ if (data)
+ atomic_set(&data->lbms_count, 0);
+ else
+ pcie_capability_write_word(port, PCI_EXP_LNKSTA,
+ PCI_EXP_LNKSTA_LBMS);
+}
+
+int pcie_lbms_count(struct pci_dev *port, unsigned long *val)
+{
+ struct pcie_bwctrl_data *data;
+
+ guard(rwsem_read)(&pcie_bwctrl_lbms_rwsem);
+ data = port->link_bwctrl;
+ if (!data)
+ return -ENOTTY;
+
+ *val = atomic_read(&data->lbms_count);
+
+ return 0;
+}
+
+static int pcie_bwnotif_probe(struct pcie_device *srv)
+{
+ struct pci_dev *port = srv->port;
+ int ret;
+
+ struct pcie_bwctrl_data *data = devm_kzalloc(&srv->device,
+ sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ ret = devm_mutex_init(&srv->device, &data->set_speed_mutex);
+ if (ret)
+ return ret;
+
+ ret = devm_request_irq(&srv->device, srv->irq, pcie_bwnotif_irq,
+ IRQF_SHARED, "PCIe bwctrl", srv);
+ if (ret)
+ return ret;
+
+ scoped_guard(rwsem_write, &pcie_bwctrl_setspeed_rwsem) {
+ scoped_guard(rwsem_write, &pcie_bwctrl_lbms_rwsem) {
+ port->link_bwctrl = no_free_ptr(data);
+ pcie_bwnotif_enable(srv);
+ }
+ }
+
+ pci_dbg(port, "enabled with IRQ %d\n", srv->irq);
+
+ /* Don't fail on errors. Don't leave IS_ERR() "pointer" into ->cdev */
+ port->link_bwctrl->cdev = pcie_cooling_device_register(port);
+ if (IS_ERR(port->link_bwctrl->cdev))
+ port->link_bwctrl->cdev = NULL;
+
+ return 0;
+}
+
+static void pcie_bwnotif_remove(struct pcie_device *srv)
+{
+ struct pcie_bwctrl_data *data = srv->port->link_bwctrl;
+
+ pcie_cooling_device_unregister(data->cdev);
+
+ pcie_bwnotif_disable(srv->port);
+
+ scoped_guard(rwsem_write, &pcie_bwctrl_setspeed_rwsem)
+ scoped_guard(rwsem_write, &pcie_bwctrl_lbms_rwsem)
+ srv->port->link_bwctrl = NULL;
+}
+
+static int pcie_bwnotif_suspend(struct pcie_device *srv)
+{
+ pcie_bwnotif_disable(srv->port);
+ return 0;
+}
+
+static int pcie_bwnotif_resume(struct pcie_device *srv)
+{
+ pcie_bwnotif_enable(srv);
+ return 0;
+}
+
+static struct pcie_port_service_driver pcie_bwctrl_driver = {
+ .name = "pcie_bwctrl",
+ .port_type = PCIE_ANY_PORT,
+ .service = PCIE_PORT_SERVICE_BWCTRL,
+ .probe = pcie_bwnotif_probe,
+ .suspend = pcie_bwnotif_suspend,
+ .resume = pcie_bwnotif_resume,
+ .remove = pcie_bwnotif_remove,
+};
+
+int __init pcie_bwctrl_init(void)
+{
+ return pcie_port_service_register(&pcie_bwctrl_driver);
+}
diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c
index 6af5e0425872..5e10306b6308 100644
--- a/drivers/pci/pcie/portdrv.c
+++ b/drivers/pci/pcie/portdrv.c
@@ -68,7 +68,7 @@ static int pcie_message_numbers(struct pci_dev *dev, int mask,
*/
if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
- PCIE_PORT_SERVICE_BWNOTIF)) {
+ PCIE_PORT_SERVICE_BWCTRL)) {
pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
*pme = FIELD_GET(PCI_EXP_FLAGS_IRQ, reg16);
nvec = *pme + 1;
@@ -150,11 +150,11 @@ static int pcie_port_enable_irq_vec(struct pci_dev *dev, int *irqs, int mask)
/* PME, hotplug and bandwidth notification share an MSI/MSI-X vector */
if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
- PCIE_PORT_SERVICE_BWNOTIF)) {
+ PCIE_PORT_SERVICE_BWCTRL)) {
pcie_irq = pci_irq_vector(dev, pme);
irqs[PCIE_PORT_SERVICE_PME_SHIFT] = pcie_irq;
irqs[PCIE_PORT_SERVICE_HP_SHIFT] = pcie_irq;
- irqs[PCIE_PORT_SERVICE_BWNOTIF_SHIFT] = pcie_irq;
+ irqs[PCIE_PORT_SERVICE_BWCTRL_SHIFT] = pcie_irq;
}
if (mask & PCIE_PORT_SERVICE_AER)
@@ -271,7 +271,7 @@ static int get_port_device_capability(struct pci_dev *dev)
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &linkcap);
if (linkcap & PCI_EXP_LNKCAP_LBNC)
- services |= PCIE_PORT_SERVICE_BWNOTIF;
+ services |= PCIE_PORT_SERVICE_BWCTRL;
}
return services;
@@ -828,6 +828,7 @@ static void __init pcie_init_services(void)
pcie_aer_init();
pcie_pme_init();
pcie_dpc_init();
+ pcie_bwctrl_init();
pcie_hp_init();
}
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 12c89ea0313b..bd29d1cc7b8b 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -20,8 +20,8 @@
#define PCIE_PORT_SERVICE_HP (1 << PCIE_PORT_SERVICE_HP_SHIFT)
#define PCIE_PORT_SERVICE_DPC_SHIFT 3 /* Downstream Port Containment */
#define PCIE_PORT_SERVICE_DPC (1 << PCIE_PORT_SERVICE_DPC_SHIFT)
-#define PCIE_PORT_SERVICE_BWNOTIF_SHIFT 4 /* Bandwidth notification */
-#define PCIE_PORT_SERVICE_BWNOTIF (1 << PCIE_PORT_SERVICE_BWNOTIF_SHIFT)
+#define PCIE_PORT_SERVICE_BWCTRL_SHIFT 4 /* Bandwidth Controller (notifications) */
+#define PCIE_PORT_SERVICE_BWCTRL (1 << PCIE_PORT_SERVICE_BWCTRL_SHIFT)
#define PCIE_PORT_DEVICE_MAXSERVICES 5
@@ -51,6 +51,8 @@ int pcie_dpc_init(void);
static inline int pcie_dpc_init(void) { return 0; }
#endif
+int pcie_bwctrl_init(void);
+
/* Port Type */
#define PCIE_ANY_PORT (~0)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f1615805f5b0..2e81ab0f5a25 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -543,15 +543,15 @@ void pci_read_bridge_bases(struct pci_bus *child)
pci_read_bridge_mmio(child->self, child->resource[1], false);
pci_read_bridge_mmio_pref(child->self, child->resource[2], false);
- if (dev->transparent) {
- pci_bus_for_each_resource(child->parent, res) {
- if (res && res->flags) {
- pci_bus_add_resource(child, res,
- PCI_SUBTRACTIVE_DECODE);
- pci_info(dev, " bridge window %pR (subtractive decode)\n",
- res);
- }
- }
+ if (!dev->transparent)
+ return;
+
+ pci_bus_for_each_resource(child->parent, res) {
+ if (!res || !res->flags)
+ continue;
+
+ pci_bus_add_resource(child, res);
+ pci_info(dev, " bridge window %pR (subtractive decode)\n", res);
}
}
@@ -742,9 +742,13 @@ const char *pci_speed_string(enum pci_bus_speed speed)
}
EXPORT_SYMBOL_GPL(pci_speed_string);
-void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
+void pcie_update_link_speed(struct pci_bus *bus)
{
- bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
+ struct pci_dev *bridge = bus->self;
+ u16 linksta;
+
+ pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
+ __pcie_update_link_speed(bus, linksta);
}
EXPORT_SYMBOL_GPL(pcie_update_link_speed);
@@ -827,13 +831,11 @@ static void pci_set_bus_speed(struct pci_bus *bus)
if (pci_is_pcie(bridge)) {
u32 linkcap;
- u16 linksta;
pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
- pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
- pcie_update_link_speed(bus, linksta);
+ pcie_update_link_speed(bus);
}
}
@@ -1032,7 +1034,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
if (res->flags & IORESOURCE_BUS)
pci_bus_insert_busn_res(bus, bus->number, res->end);
else
- pci_bus_add_resource(bus, res, 0);
+ pci_bus_add_resource(bus, res);
if (offset) {
if (resource_type(res) == IORESOURCE_IO)
@@ -1633,23 +1635,33 @@ static void set_pcie_thunderbolt(struct pci_dev *dev)
static void set_pcie_untrusted(struct pci_dev *dev)
{
- struct pci_dev *parent;
+ struct pci_dev *parent = pci_upstream_bridge(dev);
+ if (!parent)
+ return;
/*
- * If the upstream bridge is untrusted we treat this device
+ * If the upstream bridge is untrusted we treat this device as
* untrusted as well.
*/
- parent = pci_upstream_bridge(dev);
- if (parent && (parent->untrusted || parent->external_facing))
+ if (parent->untrusted) {
+ dev->untrusted = true;
+ return;
+ }
+
+ if (arch_pci_dev_is_removable(dev)) {
+ pci_dbg(dev, "marking as untrusted\n");
dev->untrusted = true;
+ }
}
static void pci_set_removable(struct pci_dev *dev)
{
struct pci_dev *parent = pci_upstream_bridge(dev);
+ if (!parent)
+ return;
/*
- * We (only) consider everything downstream from an external_facing
+ * We (only) consider everything tunneled below an external_facing
* device to be removable by the user. We're mainly concerned with
* consumer platforms with user accessible thunderbolt ports that are
* vulnerable to DMA attacks, and we expect those ports to be marked by
@@ -1659,9 +1671,15 @@ static void pci_set_removable(struct pci_dev *dev)
* accessible to user / may not be removed by end user, and thus not
* exposed as "removable" to userspace.
*/
- if (parent &&
- (parent->external_facing || dev_is_removable(&parent->dev)))
+ if (dev_is_removable(&parent->dev)) {
+ dev_set_removable(&dev->dev, DEVICE_REMOVABLE);
+ return;
+ }
+
+ if (arch_pci_dev_is_removable(dev)) {
+ pci_dbg(dev, "marking as removable\n");
dev_set_removable(&dev->dev, DEVICE_REMOVABLE);
+ }
}
/**
@@ -1947,6 +1965,9 @@ int pci_setup_device(struct pci_dev *dev)
set_pcie_untrusted(dev);
+ if (pci_is_pcie(dev))
+ dev->supported_speeds = pcie_get_supported_speeds(dev);
+
/* "Unknown power state" */
dev->current_state = PCI_UNKNOWN;
@@ -2495,6 +2516,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
pci_dpc_init(dev); /* Downstream Port Containment */
pci_rcec_init(dev); /* Root Complex Event Collector */
pci_doe_init(dev); /* Data Object Exchange */
+ pci_tph_init(dev); /* TLP Processing Hints */
pcie_report_downtraining(dev);
pci_init_reset_methods(dev);
@@ -3108,6 +3130,17 @@ int pci_host_probe(struct pci_host_bridge *bridge)
pci_lock_rescan_remove();
pci_bus_add_devices(bus);
pci_unlock_rescan_remove();
+
+ /*
+ * Ensure pm_runtime_enable() is called for the controller drivers
+ * before calling pci_host_probe(). The PM framework expects that
+ * if the parent device supports runtime PM, it will be enabled
+ * before child runtime PM is enabled.
+ */
+ pm_runtime_set_active(&bridge->dev);
+ pm_runtime_no_callbacks(&bridge->dev);
+ devm_pm_runtime_enable(&bridge->dev);
+
return 0;
}
EXPORT_SYMBOL_GPL(pci_host_probe);
diff --git a/drivers/pci/pwrctl/Makefile b/drivers/pci/pwrctl/Makefile
deleted file mode 100644
index d308aae4800c..000000000000
--- a/drivers/pci/pwrctl/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctl-core.o
-pci-pwrctl-core-y := core.o
-
-obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctl-pwrseq.o
diff --git a/drivers/pci/pwrctl/core.c b/drivers/pci/pwrctl/core.c
deleted file mode 100644
index 01d913b60316..000000000000
--- a/drivers/pci/pwrctl/core.c
+++ /dev/null
@@ -1,157 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2024 Linaro Ltd.
- */
-
-#include <linux/device.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/pci-pwrctl.h>
-#include <linux/property.h>
-#include <linux/slab.h>
-
-static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action,
- void *data)
-{
- struct pci_pwrctl *pwrctl = container_of(nb, struct pci_pwrctl, nb);
- struct device *dev = data;
-
- if (dev_fwnode(dev) != dev_fwnode(pwrctl->dev))
- return NOTIFY_DONE;
-
- switch (action) {
- case BUS_NOTIFY_ADD_DEVICE:
- /*
- * We will have two struct device objects bound to two different
- * drivers on different buses but consuming the same DT node. We
- * must not bind the pins twice in this case but only once for
- * the first device to be added.
- *
- * If we got here then the PCI device is the second after the
- * power control platform device. Mark its OF node as reused.
- */
- dev->of_node_reused = true;
- break;
- case BUS_NOTIFY_BOUND_DRIVER:
- pwrctl->link = device_link_add(dev, pwrctl->dev,
- DL_FLAG_AUTOREMOVE_CONSUMER);
- if (!pwrctl->link)
- dev_err(pwrctl->dev, "Failed to add device link\n");
- break;
- case BUS_NOTIFY_UNBOUND_DRIVER:
- if (pwrctl->link)
- device_link_remove(dev, pwrctl->dev);
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static void rescan_work_func(struct work_struct *work)
-{
- struct pci_pwrctl *pwrctl = container_of(work, struct pci_pwrctl, work);
-
- pci_lock_rescan_remove();
- pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
- pci_unlock_rescan_remove();
-}
-
-/**
- * pci_pwrctl_init() - Initialize the PCI power control context struct
- *
- * @pwrctl: PCI power control data
- * @dev: Parent device
- */
-void pci_pwrctl_init(struct pci_pwrctl *pwrctl, struct device *dev)
-{
- pwrctl->dev = dev;
- INIT_WORK(&pwrctl->work, rescan_work_func);
-}
-EXPORT_SYMBOL_GPL(pci_pwrctl_init);
-
-/**
- * pci_pwrctl_device_set_ready() - Notify the pwrctl subsystem that the PCI
- * device is powered-up and ready to be detected.
- *
- * @pwrctl: PCI power control data.
- *
- * Returns:
- * 0 on success, negative error number on error.
- *
- * Note:
- * This function returning 0 doesn't mean the device was detected. It means,
- * that the bus rescan was successfully started. The device will get bound to
- * its PCI driver asynchronously.
- */
-int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl)
-{
- int ret;
-
- if (!pwrctl->dev)
- return -ENODEV;
-
- pwrctl->nb.notifier_call = pci_pwrctl_notify;
- ret = bus_register_notifier(&pci_bus_type, &pwrctl->nb);
- if (ret)
- return ret;
-
- schedule_work(&pwrctl->work);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(pci_pwrctl_device_set_ready);
-
-/**
- * pci_pwrctl_device_unset_ready() - Notify the pwrctl subsystem that the PCI
- * device is about to be powered-down.
- *
- * @pwrctl: PCI power control data.
- */
-void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl)
-{
- /*
- * We don't have to delete the link here. Typically, this function
- * is only called when the power control device is being detached. If
- * it is being detached then the child PCI device must have already
- * been unbound too or the device core wouldn't let us unbind.
- */
- bus_unregister_notifier(&pci_bus_type, &pwrctl->nb);
-}
-EXPORT_SYMBOL_GPL(pci_pwrctl_device_unset_ready);
-
-static void devm_pci_pwrctl_device_unset_ready(void *data)
-{
- struct pci_pwrctl *pwrctl = data;
-
- pci_pwrctl_device_unset_ready(pwrctl);
-}
-
-/**
- * devm_pci_pwrctl_device_set_ready - Managed variant of
- * pci_pwrctl_device_set_ready().
- *
- * @dev: Device managing this pwrctl provider.
- * @pwrctl: PCI power control data.
- *
- * Returns:
- * 0 on success, negative error number on error.
- */
-int devm_pci_pwrctl_device_set_ready(struct device *dev,
- struct pci_pwrctl *pwrctl)
-{
- int ret;
-
- ret = pci_pwrctl_device_set_ready(pwrctl);
- if (ret)
- return ret;
-
- return devm_add_action_or_reset(dev,
- devm_pci_pwrctl_device_unset_ready,
- pwrctl);
-}
-EXPORT_SYMBOL_GPL(devm_pci_pwrctl_device_set_ready);
-
-MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
-MODULE_DESCRIPTION("PCI Device Power Control core driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pci/pwrctl/Kconfig b/drivers/pci/pwrctrl/Kconfig
index 54589bb2403b..54589bb2403b 100644
--- a/drivers/pci/pwrctl/Kconfig
+++ b/drivers/pci/pwrctrl/Kconfig
diff --git a/drivers/pci/pwrctrl/Makefile b/drivers/pci/pwrctrl/Makefile
new file mode 100644
index 000000000000..75c7ce531c7e
--- /dev/null
+++ b/drivers/pci/pwrctrl/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctrl-core.o
+pci-pwrctrl-core-y := core.o
+
+obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctrl-pwrseq.o
diff --git a/drivers/pci/pwrctrl/core.c b/drivers/pci/pwrctrl/core.c
new file mode 100644
index 000000000000..2fb174db91e5
--- /dev/null
+++ b/drivers/pci/pwrctrl/core.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci-pwrctrl.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+
+static int pci_pwrctrl_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct pci_pwrctrl *pwrctrl = container_of(nb, struct pci_pwrctrl, nb);
+ struct device *dev = data;
+
+ if (dev_fwnode(dev) != dev_fwnode(pwrctrl->dev))
+ return NOTIFY_DONE;
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ /*
+ * We will have two struct device objects bound to two different
+ * drivers on different buses but consuming the same DT node. We
+ * must not bind the pins twice in this case but only once for
+ * the first device to be added.
+ *
+ * If we got here then the PCI device is the second after the
+ * power control platform device. Mark its OF node as reused.
+ */
+ dev->of_node_reused = true;
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static void rescan_work_func(struct work_struct *work)
+{
+ struct pci_pwrctrl *pwrctrl = container_of(work,
+ struct pci_pwrctrl, work);
+
+ pci_lock_rescan_remove();
+ pci_rescan_bus(to_pci_dev(pwrctrl->dev->parent)->bus);
+ pci_unlock_rescan_remove();
+}
+
+/**
+ * pci_pwrctrl_init() - Initialize the PCI power control context struct
+ *
+ * @pwrctrl: PCI power control data
+ * @dev: Parent device
+ */
+void pci_pwrctrl_init(struct pci_pwrctrl *pwrctrl, struct device *dev)
+{
+ pwrctrl->dev = dev;
+ INIT_WORK(&pwrctrl->work, rescan_work_func);
+}
+EXPORT_SYMBOL_GPL(pci_pwrctrl_init);
+
+/**
+ * pci_pwrctrl_device_set_ready() - Notify the pwrctrl subsystem that the PCI
+ * device is powered-up and ready to be detected.
+ *
+ * @pwrctrl: PCI power control data.
+ *
+ * Returns:
+ * 0 on success, negative error number on error.
+ *
+ * Note:
+ * This function returning 0 doesn't mean the device was detected. It means,
+ * that the bus rescan was successfully started. The device will get bound to
+ * its PCI driver asynchronously.
+ */
+int pci_pwrctrl_device_set_ready(struct pci_pwrctrl *pwrctrl)
+{
+ int ret;
+
+ if (!pwrctrl->dev)
+ return -ENODEV;
+
+ pwrctrl->nb.notifier_call = pci_pwrctrl_notify;
+ ret = bus_register_notifier(&pci_bus_type, &pwrctrl->nb);
+ if (ret)
+ return ret;
+
+ schedule_work(&pwrctrl->work);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_pwrctrl_device_set_ready);
+
+/**
+ * pci_pwrctrl_device_unset_ready() - Notify the pwrctrl subsystem that the PCI
+ * device is about to be powered-down.
+ *
+ * @pwrctrl: PCI power control data.
+ */
+void pci_pwrctrl_device_unset_ready(struct pci_pwrctrl *pwrctrl)
+{
+ /*
+ * We don't have to delete the link here. Typically, this function
+ * is only called when the power control device is being detached. If
+ * it is being detached then the child PCI device must have already
+ * been unbound too or the device core wouldn't let us unbind.
+ */
+ bus_unregister_notifier(&pci_bus_type, &pwrctrl->nb);
+}
+EXPORT_SYMBOL_GPL(pci_pwrctrl_device_unset_ready);
+
+static void devm_pci_pwrctrl_device_unset_ready(void *data)
+{
+ struct pci_pwrctrl *pwrctrl = data;
+
+ pci_pwrctrl_device_unset_ready(pwrctrl);
+}
+
+/**
+ * devm_pci_pwrctrl_device_set_ready - Managed variant of
+ * pci_pwrctrl_device_set_ready().
+ *
+ * @dev: Device managing this pwrctrl provider.
+ * @pwrctrl: PCI power control data.
+ *
+ * Returns:
+ * 0 on success, negative error number on error.
+ */
+int devm_pci_pwrctrl_device_set_ready(struct device *dev,
+ struct pci_pwrctrl *pwrctrl)
+{
+ int ret;
+
+ ret = pci_pwrctrl_device_set_ready(pwrctrl);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev,
+ devm_pci_pwrctrl_device_unset_ready,
+ pwrctrl);
+}
+EXPORT_SYMBOL_GPL(devm_pci_pwrctrl_device_set_ready);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
+MODULE_DESCRIPTION("PCI Device Power Control core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c b/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c
index 0e6bd47671c2..4e664e7b8dd2 100644
--- a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
+++ b/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c
@@ -6,19 +6,19 @@
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/pci-pwrctl.h>
+#include <linux/pci-pwrctrl.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/pwrseq/consumer.h>
#include <linux/slab.h>
#include <linux/types.h>
-struct pci_pwrctl_pwrseq_data {
- struct pci_pwrctl ctx;
+struct pci_pwrctrl_pwrseq_data {
+ struct pci_pwrctrl ctx;
struct pwrseq_desc *pwrseq;
};
-struct pci_pwrctl_pwrseq_pdata {
+struct pci_pwrctrl_pwrseq_pdata {
const char *target;
/*
* Called before doing anything else to perform device-specific
@@ -27,7 +27,7 @@ struct pci_pwrctl_pwrseq_pdata {
int (*validate_device)(struct device *dev);
};
-static int pci_pwrctl_pwrseq_qcm_wcn_validate_device(struct device *dev)
+static int pci_pwrctrl_pwrseq_qcm_wcn_validate_device(struct device *dev)
{
/*
* Old device trees for some platforms already define wifi nodes for
@@ -47,22 +47,22 @@ static int pci_pwrctl_pwrseq_qcm_wcn_validate_device(struct device *dev)
return 0;
}
-static const struct pci_pwrctl_pwrseq_pdata pci_pwrctl_pwrseq_qcom_wcn_pdata = {
+static const struct pci_pwrctrl_pwrseq_pdata pci_pwrctrl_pwrseq_qcom_wcn_pdata = {
.target = "wlan",
- .validate_device = pci_pwrctl_pwrseq_qcm_wcn_validate_device,
+ .validate_device = pci_pwrctrl_pwrseq_qcm_wcn_validate_device,
};
-static void devm_pci_pwrctl_pwrseq_power_off(void *data)
+static void devm_pci_pwrctrl_pwrseq_power_off(void *data)
{
struct pwrseq_desc *pwrseq = data;
pwrseq_power_off(pwrseq);
}
-static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
+static int pci_pwrctrl_pwrseq_probe(struct platform_device *pdev)
{
- const struct pci_pwrctl_pwrseq_pdata *pdata;
- struct pci_pwrctl_pwrseq_data *data;
+ const struct pci_pwrctrl_pwrseq_pdata *pdata;
+ struct pci_pwrctrl_pwrseq_data *data;
struct device *dev = &pdev->dev;
int ret;
@@ -90,49 +90,49 @@ static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret,
"Failed to power-on the device\n");
- ret = devm_add_action_or_reset(dev, devm_pci_pwrctl_pwrseq_power_off,
+ ret = devm_add_action_or_reset(dev, devm_pci_pwrctrl_pwrseq_power_off,
data->pwrseq);
if (ret)
return ret;
- pci_pwrctl_init(&data->ctx, dev);
+ pci_pwrctrl_init(&data->ctx, dev);
- ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx);
+ ret = devm_pci_pwrctrl_device_set_ready(dev, &data->ctx);
if (ret)
return dev_err_probe(dev, ret,
- "Failed to register the pwrctl wrapper\n");
+ "Failed to register the pwrctrl wrapper\n");
return 0;
}
-static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = {
+static const struct of_device_id pci_pwrctrl_pwrseq_of_match[] = {
{
/* ATH11K in QCA6390 package. */
.compatible = "pci17cb,1101",
- .data = &pci_pwrctl_pwrseq_qcom_wcn_pdata,
+ .data = &pci_pwrctrl_pwrseq_qcom_wcn_pdata,
},
{
/* ATH11K in WCN6855 package. */
.compatible = "pci17cb,1103",
- .data = &pci_pwrctl_pwrseq_qcom_wcn_pdata,
+ .data = &pci_pwrctrl_pwrseq_qcom_wcn_pdata,
},
{
/* ATH12K in WCN7850 package. */
.compatible = "pci17cb,1107",
- .data = &pci_pwrctl_pwrseq_qcom_wcn_pdata,
+ .data = &pci_pwrctrl_pwrseq_qcom_wcn_pdata,
},
{ }
};
-MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match);
+MODULE_DEVICE_TABLE(of, pci_pwrctrl_pwrseq_of_match);
-static struct platform_driver pci_pwrctl_pwrseq_driver = {
+static struct platform_driver pci_pwrctrl_pwrseq_driver = {
.driver = {
- .name = "pci-pwrctl-pwrseq",
- .of_match_table = pci_pwrctl_pwrseq_of_match,
+ .name = "pci-pwrctrl-pwrseq",
+ .of_match_table = pci_pwrctrl_pwrseq_of_match,
},
- .probe = pci_pwrctl_pwrseq_probe,
+ .probe = pci_pwrctrl_pwrseq_probe,
};
-module_platform_driver(pci_pwrctl_pwrseq_driver);
+module_platform_driver(pci_pwrctrl_pwrseq_driver);
MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices");
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index dccb60c1d9cc..76f4df75b08a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -12,6 +12,7 @@
* file, where their drivers can use them.
*/
+#include <linux/align.h>
#include <linux/bitfield.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -29,10 +30,23 @@
#include <linux/nvme.h>
#include <linux/platform_data/x86/apple.h>
#include <linux/pm_runtime.h>
+#include <linux/sizes.h>
#include <linux/suspend.h>
#include <linux/switchtec.h>
#include "pci.h"
+static bool pcie_lbms_seen(struct pci_dev *dev, u16 lnksta)
+{
+ unsigned long count;
+ int ret;
+
+ ret = pcie_lbms_count(dev, &count);
+ if (ret < 0)
+ return lnksta & PCI_EXP_LNKSTA_LBMS;
+
+ return count > 0;
+}
+
/*
* Retrain the link of a downstream PCIe port by hand if necessary.
*
@@ -96,22 +110,16 @@ int pcie_failed_link_retrain(struct pci_dev *dev)
pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2);
pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
- if ((lnksta & (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_DLLLA)) ==
- PCI_EXP_LNKSTA_LBMS) {
+ if (!(lnksta & PCI_EXP_LNKSTA_DLLLA) && pcie_lbms_seen(dev, lnksta)) {
u16 oldlnkctl2 = lnkctl2;
pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n");
- lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
- lnkctl2 |= PCI_EXP_LNKCTL2_TLS_2_5GT;
- pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2);
-
- ret = pcie_retrain_link(dev, false);
+ ret = pcie_set_target_speed(dev, PCIE_SPEED_2_5GT, false);
if (ret) {
pci_info(dev, "retraining failed\n");
- pcie_capability_write_word(dev, PCI_EXP_LNKCTL2,
- oldlnkctl2);
- pcie_retrain_link(dev, true);
+ pcie_set_target_speed(dev, PCIE_LNKCTL2_TLS2SPEED(oldlnkctl2),
+ true);
return ret;
}
@@ -125,11 +133,7 @@ int pcie_failed_link_retrain(struct pci_dev *dev)
pci_info(dev, "removing 2.5GT/s downstream link speed restriction\n");
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
- lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS;
- lnkctl2 |= lnkcap & PCI_EXP_LNKCAP_SLS;
- pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2);
-
- ret = pcie_retrain_link(dev, false);
+ ret = pcie_set_target_speed(dev, PCIE_LNKCAP_SLS2SPEED(lnkcap), false);
if (ret) {
pci_info(dev, "retraining failed\n");
return ret;
@@ -586,8 +590,7 @@ static void quirk_extend_bar_to_page(struct pci_dev *dev)
const char *r_name = pci_resource_name(dev, i);
if (r->flags & IORESOURCE_MEM && resource_size(r) < PAGE_SIZE) {
- r->end = PAGE_SIZE - 1;
- r->start = 0;
+ resource_set_range(r, 0, PAGE_SIZE);
r->flags |= IORESOURCE_UNSET;
pci_info(dev, "%s %pR: expanded to page size\n",
r_name, r);
@@ -604,10 +607,9 @@ static void quirk_s3_64M(struct pci_dev *dev)
{
struct resource *r = &dev->resource[0];
- if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff) {
+ if (!IS_ALIGNED(r->start, SZ_64M) || resource_size(r) != SZ_64M) {
r->flags |= IORESOURCE_UNSET;
- r->start = 0;
- r->end = 0x3ffffff;
+ resource_set_range(r, 0, SZ_64M);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
@@ -1342,8 +1344,7 @@ static void quirk_dunord(struct pci_dev *dev)
struct resource *r = &dev->resource[1];
r->flags |= IORESOURCE_UNSET;
- r->start = 0;
- r->end = 0xffffff;
+ resource_set_range(r, 0, SZ_16M);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord);
@@ -2340,8 +2341,7 @@ static void quirk_tc86c001_ide(struct pci_dev *dev)
if (r->start & 0x8) {
r->flags |= IORESOURCE_UNSET;
- r->start = 0;
- r->end = 0xf;
+ resource_set_range(r, 0, SZ_16);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
@@ -2369,8 +2369,7 @@ static void quirk_plx_pci9050(struct pci_dev *dev)
pci_info(dev, "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
bar);
r->flags |= IORESOURCE_UNSET;
- r->start = 0;
- r->end = 0xff;
+ resource_set_range(r, 0, SZ_256);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
@@ -3522,13 +3521,13 @@ static void quirk_intel_ntb(struct pci_dev *dev)
if (rc)
return;
- dev->resource[2].end = dev->resource[2].start + ((u64) 1 << val) - 1;
+ resource_set_size(&dev->resource[2], (resource_size_t)1 << val);
rc = pci_read_config_byte(dev, 0x00D1, &val);
if (rc)
return;
- dev->resource[4].end = dev->resource[4].start + ((u64) 1 << val) - 1;
+ resource_set_size(&dev->resource[4], (resource_size_t)1 << val);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb);
@@ -4996,18 +4995,21 @@ static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
}
/*
- * Wangxun 10G/1G NICs have no ACS capability, and on multi-function
- * devices, peer-to-peer transactions are not be used between the functions.
- * So add an ACS quirk for below devices to isolate functions.
+ * Wangxun 40G/25G/10G/1G NICs have no ACS capability, but on
+ * multi-function devices, the hardware isolates the functions by
+ * directing all peer-to-peer traffic upstream as though PCI_ACS_RR and
+ * PCI_ACS_CR were set.
* SFxxx 1G NICs(em).
* RP1000/RP2000 10G NICs(sp).
+ * FF5xxx 40G/25G/10G NICs(aml).
*/
static int pci_quirk_wangxun_nic_acs(struct pci_dev *dev, u16 acs_flags)
{
switch (dev->device) {
- case 0x0100 ... 0x010F:
- case 0x1001:
- case 0x2001:
+ case 0x0100 ... 0x010F: /* EM */
+ case 0x1001: case 0x2001: /* SP */
+ case 0x5010: case 0x5025: case 0x5040: /* AML */
+ case 0x5110: case 0x5125: case 0x5140: /* AML */
return pci_acs_ctrl_enabled(acs_flags,
PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
}
@@ -6266,6 +6268,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa76e, dpc_log_size);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5020, of_pci_make_dev_node);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_XILINX, 0x5021, of_pci_make_dev_node);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REDHAT, 0x0005, of_pci_make_dev_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, 0x9660, of_pci_make_dev_node);
/*
* Devices known to require a longer delay before first config space access
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index e4ce1145aa3e..efc37fcb73e2 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -17,37 +17,40 @@ static void pci_free_resources(struct pci_dev *dev)
}
}
-static int pci_pwrctl_unregister(struct device *dev, void *data)
+static void pci_pwrctrl_unregister(struct device *dev)
{
- struct device_node *pci_node = data, *plat_node = dev_of_node(dev);
+ struct device_node *np;
+ struct platform_device *pdev;
- if (dev_is_platform(dev) && plat_node && plat_node == pci_node) {
- of_device_unregister(to_platform_device(dev));
- of_node_clear_flag(plat_node, OF_POPULATED);
- }
+ np = dev_of_node(dev);
+ if (!np)
+ return;
+
+ pdev = of_find_device_by_node(np);
+ if (!pdev)
+ return;
- return 0;
+ of_device_unregister(pdev);
+ of_node_clear_flag(np, OF_POPULATED);
}
static void pci_stop_dev(struct pci_dev *dev)
{
pci_pme_active(dev, false);
- if (pci_dev_is_added(dev)) {
- device_for_each_child(dev->dev.parent, dev_of_node(&dev->dev),
- pci_pwrctl_unregister);
- device_release_driver(&dev->dev);
- pci_proc_detach_device(dev);
- pci_remove_sysfs_dev_files(dev);
- of_pci_remove_node(dev);
+ if (!pci_dev_test_and_clear_added(dev))
+ return;
- pci_dev_assign_added(dev, false);
- }
+ pci_pwrctrl_unregister(&dev->dev);
+ device_release_driver(&dev->dev);
+ pci_proc_detach_device(dev);
+ pci_remove_sysfs_dev_files(dev);
+ of_pci_remove_node(dev);
}
static void pci_destroy_dev(struct pci_dev *dev)
{
- if (!dev->dev.kobj.parent)
+ if (pci_dev_test_and_set_removed(dev))
return;
pci_npem_remove(dev);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 23082bc0ca37..5e00cecf1f1a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -134,6 +134,7 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
int i;
pci_dev_for_each_resource(dev, r, i) {
+ const char *r_name = pci_resource_name(dev, i);
struct pci_dev_resource *dev_res, *tmp;
resource_size_t r_align;
struct list_head *n;
@@ -146,8 +147,8 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
r_align = pci_resource_alignment(dev, r);
if (!r_align) {
- pci_warn(dev, "BAR %d: %pR has bogus alignment\n",
- i, r);
+ pci_warn(dev, "%s %pR: alignment must not be zero\n",
+ r_name, r);
continue;
}
@@ -246,8 +247,7 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
add_size = add_res->add_size;
align = add_res->min_align;
if (!resource_size(res)) {
- res->start = align;
- res->end = res->start + add_size - 1;
+ resource_set_range(res, align, add_size);
if (pci_assign_resource(add_res->dev, idx))
reset_resource(res);
} else {
@@ -938,8 +938,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
return;
}
- b_res->start = min_align;
- b_res->end = b_res->start + size0 - 1;
+ resource_set_range(b_res, min_align, size0);
b_res->flags |= IORESOURCE_STARTALIGN;
if (bus->self && size1 > size0 && realloc_head) {
add_to_list(realloc_head, bus->self, b_res, size1-size0,
@@ -1202,8 +1201,7 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,
* Reserve some resources for CardBus. We reserve a fixed amount
* of bus space for CardBus bridges.
*/
- b_res->start = pci_cardbus_io_size;
- b_res->end = b_res->start + pci_cardbus_io_size - 1;
+ resource_set_range(b_res, pci_cardbus_io_size, pci_cardbus_io_size);
b_res->flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
if (realloc_head) {
b_res->end -= pci_cardbus_io_size;
@@ -1215,8 +1213,7 @@ handle_b_res_1:
b_res = &bridge->resource[PCI_CB_BRIDGE_IO_1_WINDOW];
if (b_res->parent)
goto handle_b_res_2;
- b_res->start = pci_cardbus_io_size;
- b_res->end = b_res->start + pci_cardbus_io_size - 1;
+ resource_set_range(b_res, pci_cardbus_io_size, pci_cardbus_io_size);
b_res->flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
if (realloc_head) {
b_res->end -= pci_cardbus_io_size;
@@ -1249,8 +1246,8 @@ handle_b_res_2:
* Otherwise, allocate one region of twice the size.
*/
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
- b_res->start = pci_cardbus_mem_size;
- b_res->end = b_res->start + pci_cardbus_mem_size - 1;
+ resource_set_range(b_res, pci_cardbus_mem_size,
+ pci_cardbus_mem_size);
b_res->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH |
IORESOURCE_STARTALIGN;
if (realloc_head) {
@@ -1267,8 +1264,7 @@ handle_b_res_3:
b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_1_WINDOW];
if (b_res->parent)
goto handle_done;
- b_res->start = pci_cardbus_mem_size;
- b_res->end = b_res->start + b_res_3_size - 1;
+ resource_set_range(b_res, pci_cardbus_mem_size, b_res_3_size);
b_res->flags |= IORESOURCE_MEM | IORESOURCE_STARTALIGN;
if (realloc_head) {
b_res->end -= b_res_3_size;
@@ -1847,7 +1843,7 @@ static void adjust_bridge_window(struct pci_dev *bridge, struct resource *res,
return;
}
- res->end = res->start + new_size - 1;
+ resource_set_size(res, new_size);
/* If the resource is part of the add_list, remove it now */
if (add_list)
@@ -1899,6 +1895,9 @@ static void remove_dev_resources(struct pci_dev *dev, struct resource *io,
}
}
+#define ALIGN_DOWN_IF_NONZERO(addr, align) \
+ ((align) ? ALIGN_DOWN((addr), (align)) : (addr))
+
/*
* io, mmio and mmio_pref contain the total amount of bridge window space
* available. This includes the minimal space needed to cover all the
@@ -2010,8 +2009,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
* what is available).
*/
align = pci_resource_alignment(dev, res);
- io.end = align ? io.start + ALIGN_DOWN(io_per_b, align) - 1
- : io.start + io_per_b - 1;
+ resource_set_size(&io, ALIGN_DOWN_IF_NONZERO(io_per_b, align));
/*
* The x_per_b holds the extra resource space that can be
@@ -2023,15 +2021,14 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
res = &dev->resource[PCI_BRIDGE_MEM_WINDOW];
align = pci_resource_alignment(dev, res);
- mmio.end = align ? mmio.start + ALIGN_DOWN(mmio_per_b, align) - 1
- : mmio.start + mmio_per_b - 1;
+ resource_set_size(&mmio,
+ ALIGN_DOWN_IF_NONZERO(mmio_per_b,align));
mmio.start -= resource_size(res);
res = &dev->resource[PCI_BRIDGE_PREF_MEM_WINDOW];
align = pci_resource_alignment(dev, res);
- mmio_pref.end = align ? mmio_pref.start +
- ALIGN_DOWN(mmio_pref_per_b, align) - 1
- : mmio_pref.start + mmio_pref_per_b - 1;
+ resource_set_size(&mmio_pref,
+ ALIGN_DOWN_IF_NONZERO(mmio_pref_per_b, align));
mmio_pref.start -= resource_size(res);
pci_bus_distribute_available_resources(b, add_list, io, mmio,
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index c6d933ddfd46..ca14576bf2bf 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -211,8 +211,7 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
start = res->start;
end = res->end;
- res->start = fw_addr;
- res->end = res->start + size - 1;
+ resource_set_range(res, fw_addr, size);
res->flags &= ~IORESOURCE_UNSET;
root = pci_find_parent_resource(dev, res);
@@ -463,7 +462,7 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
if (ret)
return ret;
- res->end = res->start + pci_rebar_size_to_bytes(size) - 1;
+ resource_set_size(res, pci_rebar_size_to_bytes(size));
/* Check if the new config works by trying to assign everything. */
if (dev->bus->self) {
@@ -475,7 +474,7 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
error_resize:
pci_rebar_set_size(dev, resno, old);
- res->end = res->start + pci_rebar_size_to_bytes(old) - 1;
+ resource_set_size(res, pci_rebar_size_to_bytes(old));
return ret;
}
EXPORT_SYMBOL(pci_resize_resource);
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 0f87cade10f7..36b44be0489d 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -79,6 +79,7 @@ static void pci_slot_release(struct kobject *kobj)
up_read(&pci_bus_sem);
list_del(&slot->list);
+ pci_bus_put(slot->bus);
kfree(slot);
}
@@ -244,12 +245,13 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
slot = get_slot(parent, slot_nr);
if (slot) {
if (hotplug) {
- if ((err = slot->hotplug ? -EBUSY : 0)
- || (err = rename_slot(slot, name))) {
- kobject_put(&slot->kobj);
- slot = NULL;
- goto err;
+ if (slot->hotplug) {
+ err = -EBUSY;
+ goto put_slot;
}
+ err = rename_slot(slot, name);
+ if (err)
+ goto put_slot;
}
goto out;
}
@@ -261,7 +263,7 @@ placeholder:
goto err;
}
- slot->bus = parent;
+ slot->bus = pci_bus_get(parent);
slot->number = slot_nr;
slot->kobj.kset = pci_slots_kset;
@@ -269,6 +271,7 @@ placeholder:
slot_name = make_slot_name(name);
if (!slot_name) {
err = -ENOMEM;
+ pci_bus_put(slot->bus);
kfree(slot);
goto err;
}
@@ -278,10 +281,8 @@ placeholder:
err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
"%s", slot_name);
- if (err) {
- kobject_put(&slot->kobj);
- goto err;
- }
+ if (err)
+ goto put_slot;
down_read(&pci_bus_sem);
list_for_each_entry(dev, &parent->devices, bus_list)
@@ -296,6 +297,9 @@ out:
kfree(slot_name);
mutex_unlock(&pci_slot_mutex);
return slot;
+
+put_slot:
+ kobject_put(&slot->kobj);
err:
slot = ERR_PTR(err);
goto out;
diff --git a/drivers/pci/tph.c b/drivers/pci/tph.c
new file mode 100644
index 000000000000..1e604fbbda65
--- /dev/null
+++ b/drivers/pci/tph.c
@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPH (TLP Processing Hints) support
+ *
+ * Copyright (C) 2024 Advanced Micro Devices, Inc.
+ * Eric Van Tassell <Eric.VanTassell@amd.com>
+ * Wei Huang <wei.huang2@amd.com>
+ */
+#include <linux/pci.h>
+#include <linux/pci-acpi.h>
+#include <linux/msi.h>
+#include <linux/bitfield.h>
+#include <linux/pci-tph.h>
+
+#include "pci.h"
+
+/* System-wide TPH disabled */
+static bool pci_tph_disabled;
+
+#ifdef CONFIG_ACPI
+/*
+ * The st_info struct defines the Steering Tag (ST) info returned by the
+ * firmware PCI ACPI _DSM method (rev=0x7, func=0xF, "_DSM to Query Cache
+ * Locality TPH Features"), as specified in the approved ECN for PCI Firmware
+ * Spec and available at https://members.pcisig.com/wg/PCI-SIG/document/15470.
+ *
+ * @vm_st_valid: 8-bit ST for volatile memory is valid
+ * @vm_xst_valid: 16-bit extended ST for volatile memory is valid
+ * @vm_ph_ignore: 1 => PH was and will be ignored, 0 => PH should be supplied
+ * @vm_st: 8-bit ST for volatile mem
+ * @vm_xst: 16-bit extended ST for volatile mem
+ * @pm_st_valid: 8-bit ST for persistent memory is valid
+ * @pm_xst_valid: 16-bit extended ST for persistent memory is valid
+ * @pm_ph_ignore: 1 => PH was and will be ignored, 0 => PH should be supplied
+ * @pm_st: 8-bit ST for persistent mem
+ * @pm_xst: 16-bit extended ST for persistent mem
+ */
+union st_info {
+ struct {
+ u64 vm_st_valid : 1;
+ u64 vm_xst_valid : 1;
+ u64 vm_ph_ignore : 1;
+ u64 rsvd1 : 5;
+ u64 vm_st : 8;
+ u64 vm_xst : 16;
+ u64 pm_st_valid : 1;
+ u64 pm_xst_valid : 1;
+ u64 pm_ph_ignore : 1;
+ u64 rsvd2 : 5;
+ u64 pm_st : 8;
+ u64 pm_xst : 16;
+ };
+ u64 value;
+};
+
+static u16 tph_extract_tag(enum tph_mem_type mem_type, u8 req_type,
+ union st_info *info)
+{
+ switch (req_type) {
+ case PCI_TPH_REQ_TPH_ONLY: /* 8-bit tag */
+ switch (mem_type) {
+ case TPH_MEM_TYPE_VM:
+ if (info->vm_st_valid)
+ return info->vm_st;
+ break;
+ case TPH_MEM_TYPE_PM:
+ if (info->pm_st_valid)
+ return info->pm_st;
+ break;
+ }
+ break;
+ case PCI_TPH_REQ_EXT_TPH: /* 16-bit tag */
+ switch (mem_type) {
+ case TPH_MEM_TYPE_VM:
+ if (info->vm_xst_valid)
+ return info->vm_xst;
+ break;
+ case TPH_MEM_TYPE_PM:
+ if (info->pm_xst_valid)
+ return info->pm_xst;
+ break;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+#define TPH_ST_DSM_FUNC_INDEX 0xF
+static acpi_status tph_invoke_dsm(acpi_handle handle, u32 cpu_uid,
+ union st_info *st_out)
+{
+ union acpi_object arg3[3], in_obj, *out_obj;
+
+ if (!acpi_check_dsm(handle, &pci_acpi_dsm_guid, 7,
+ BIT(TPH_ST_DSM_FUNC_INDEX)))
+ return AE_ERROR;
+
+ /* DWORD: feature ID (0 for processor cache ST query) */
+ arg3[0].integer.type = ACPI_TYPE_INTEGER;
+ arg3[0].integer.value = 0;
+
+ /* DWORD: target UID */
+ arg3[1].integer.type = ACPI_TYPE_INTEGER;
+ arg3[1].integer.value = cpu_uid;
+
+ /* QWORD: properties, all 0's */
+ arg3[2].integer.type = ACPI_TYPE_INTEGER;
+ arg3[2].integer.value = 0;
+
+ in_obj.type = ACPI_TYPE_PACKAGE;
+ in_obj.package.count = ARRAY_SIZE(arg3);
+ in_obj.package.elements = arg3;
+
+ out_obj = acpi_evaluate_dsm(handle, &pci_acpi_dsm_guid, 7,
+ TPH_ST_DSM_FUNC_INDEX, &in_obj);
+ if (!out_obj)
+ return AE_ERROR;
+
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ ACPI_FREE(out_obj);
+ return AE_ERROR;
+ }
+
+ st_out->value = *((u64 *)(out_obj->buffer.pointer));
+
+ ACPI_FREE(out_obj);
+
+ return AE_OK;
+}
+#endif
+
+/* Update the TPH Requester Enable field of TPH Control Register */
+static void set_ctrl_reg_req_en(struct pci_dev *pdev, u8 req_type)
+{
+ u32 reg;
+
+ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, &reg);
+
+ reg &= ~PCI_TPH_CTRL_REQ_EN_MASK;
+ reg |= FIELD_PREP(PCI_TPH_CTRL_REQ_EN_MASK, req_type);
+
+ pci_write_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, reg);
+}
+
+static u8 get_st_modes(struct pci_dev *pdev)
+{
+ u32 reg;
+
+ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CAP, &reg);
+ reg &= PCI_TPH_CAP_ST_NS | PCI_TPH_CAP_ST_IV | PCI_TPH_CAP_ST_DS;
+
+ return reg;
+}
+
+static u32 get_st_table_loc(struct pci_dev *pdev)
+{
+ u32 reg;
+
+ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CAP, &reg);
+
+ return FIELD_GET(PCI_TPH_CAP_LOC_MASK, reg);
+}
+
+/*
+ * Return the size of ST table. If ST table is not in TPH Requester Extended
+ * Capability space, return 0. Otherwise return the ST Table Size + 1.
+ */
+static u16 get_st_table_size(struct pci_dev *pdev)
+{
+ u32 reg;
+ u32 loc;
+
+ /* Check ST table location first */
+ loc = get_st_table_loc(pdev);
+
+ /* Convert loc to match with PCI_TPH_LOC_* defined in pci_regs.h */
+ loc = FIELD_PREP(PCI_TPH_CAP_LOC_MASK, loc);
+ if (loc != PCI_TPH_LOC_CAP)
+ return 0;
+
+ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CAP, &reg);
+
+ return FIELD_GET(PCI_TPH_CAP_ST_MASK, reg) + 1;
+}
+
+/* Return device's Root Port completer capability */
+static u8 get_rp_completer_type(struct pci_dev *pdev)
+{
+ struct pci_dev *rp;
+ u32 reg;
+ int ret;
+
+ rp = pcie_find_root_port(pdev);
+ if (!rp)
+ return 0;
+
+ ret = pcie_capability_read_dword(rp, PCI_EXP_DEVCAP2, &reg);
+ if (ret)
+ return 0;
+
+ return FIELD_GET(PCI_EXP_DEVCAP2_TPH_COMP_MASK, reg);
+}
+
+/* Write ST to MSI-X vector control reg - Return 0 if OK, otherwise -errno */
+static int write_tag_to_msix(struct pci_dev *pdev, int msix_idx, u16 tag)
+{
+#ifdef CONFIG_PCI_MSI
+ struct msi_desc *msi_desc = NULL;
+ void __iomem *vec_ctrl;
+ u32 val;
+ int err = 0;
+
+ msi_lock_descs(&pdev->dev);
+
+ /* Find the msi_desc entry with matching msix_idx */
+ msi_for_each_desc(msi_desc, &pdev->dev, MSI_DESC_ASSOCIATED) {
+ if (msi_desc->msi_index == msix_idx)
+ break;
+ }
+
+ if (!msi_desc) {
+ err = -ENXIO;
+ goto err_out;
+ }
+
+ /* Get the vector control register (offset 0xc) pointed by msix_idx */
+ vec_ctrl = pdev->msix_base + msix_idx * PCI_MSIX_ENTRY_SIZE;
+ vec_ctrl += PCI_MSIX_ENTRY_VECTOR_CTRL;
+
+ val = readl(vec_ctrl);
+ val &= ~PCI_MSIX_ENTRY_CTRL_ST;
+ val |= FIELD_PREP(PCI_MSIX_ENTRY_CTRL_ST, tag);
+ writel(val, vec_ctrl);
+
+ /* Read back to flush the update */
+ val = readl(vec_ctrl);
+
+err_out:
+ msi_unlock_descs(&pdev->dev);
+ return err;
+#else
+ return -ENODEV;
+#endif
+}
+
+/* Write tag to ST table - Return 0 if OK, otherwise -errno */
+static int write_tag_to_st_table(struct pci_dev *pdev, int index, u16 tag)
+{
+ int st_table_size;
+ int offset;
+
+ /* Check if index is out of bound */
+ st_table_size = get_st_table_size(pdev);
+ if (index >= st_table_size)
+ return -ENXIO;
+
+ offset = pdev->tph_cap + PCI_TPH_BASE_SIZEOF + index * sizeof(u16);
+
+ return pci_write_config_word(pdev, offset, tag);
+}
+
+/**
+ * pcie_tph_get_cpu_st() - Retrieve Steering Tag for a target memory associated
+ * with a specific CPU
+ * @pdev: PCI device
+ * @mem_type: target memory type (volatile or persistent RAM)
+ * @cpu_uid: associated CPU id
+ * @tag: Steering Tag to be returned
+ *
+ * Return the Steering Tag for a target memory that is associated with a
+ * specific CPU as indicated by cpu_uid.
+ *
+ * Return: 0 if success, otherwise negative value (-errno)
+ */
+int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type mem_type,
+ unsigned int cpu_uid, u16 *tag)
+{
+#ifdef CONFIG_ACPI
+ struct pci_dev *rp;
+ acpi_handle rp_acpi_handle;
+ union st_info info;
+
+ rp = pcie_find_root_port(pdev);
+ if (!rp || !rp->bus || !rp->bus->bridge)
+ return -ENODEV;
+
+ rp_acpi_handle = ACPI_HANDLE(rp->bus->bridge);
+
+ if (tph_invoke_dsm(rp_acpi_handle, cpu_uid, &info) != AE_OK) {
+ *tag = 0;
+ return -EINVAL;
+ }
+
+ *tag = tph_extract_tag(mem_type, pdev->tph_req_type, &info);
+
+ pci_dbg(pdev, "get steering tag: mem_type=%s, cpu_uid=%d, tag=%#04x\n",
+ (mem_type == TPH_MEM_TYPE_VM) ? "volatile" : "persistent",
+ cpu_uid, *tag);
+
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
+EXPORT_SYMBOL(pcie_tph_get_cpu_st);
+
+/**
+ * pcie_tph_set_st_entry() - Set Steering Tag in the ST table entry
+ * @pdev: PCI device
+ * @index: ST table entry index
+ * @tag: Steering Tag to be written
+ *
+ * Figure out the proper location of ST table, either in the MSI-X table or
+ * in the TPH Extended Capability space, and write the Steering Tag into
+ * the ST entry pointed by index.
+ *
+ * Return: 0 if success, otherwise negative value (-errno)
+ */
+int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index, u16 tag)
+{
+ u32 loc;
+ int err = 0;
+
+ if (!pdev->tph_cap)
+ return -EINVAL;
+
+ if (!pdev->tph_enabled)
+ return -EINVAL;
+
+ /* No need to write tag if device is in "No ST Mode" */
+ if (pdev->tph_mode == PCI_TPH_ST_NS_MODE)
+ return 0;
+
+ /*
+ * Disable TPH before updating ST to avoid potential instability as
+ * cautioned in PCIe r6.2, sec 6.17.3, "ST Modes of Operation"
+ */
+ set_ctrl_reg_req_en(pdev, PCI_TPH_REQ_DISABLE);
+
+ loc = get_st_table_loc(pdev);
+ /* Convert loc to match with PCI_TPH_LOC_* */
+ loc = FIELD_PREP(PCI_TPH_CAP_LOC_MASK, loc);
+
+ switch (loc) {
+ case PCI_TPH_LOC_MSIX:
+ err = write_tag_to_msix(pdev, index, tag);
+ break;
+ case PCI_TPH_LOC_CAP:
+ err = write_tag_to_st_table(pdev, index, tag);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (err) {
+ pcie_disable_tph(pdev);
+ return err;
+ }
+
+ set_ctrl_reg_req_en(pdev, pdev->tph_mode);
+
+ pci_dbg(pdev, "set steering tag: %s table, index=%d, tag=%#04x\n",
+ (loc == PCI_TPH_LOC_MSIX) ? "MSI-X" : "ST", index, tag);
+
+ return 0;
+}
+EXPORT_SYMBOL(pcie_tph_set_st_entry);
+
+/**
+ * pcie_disable_tph - Turn off TPH support for device
+ * @pdev: PCI device
+ *
+ * Return: none
+ */
+void pcie_disable_tph(struct pci_dev *pdev)
+{
+ if (!pdev->tph_cap)
+ return;
+
+ if (!pdev->tph_enabled)
+ return;
+
+ pci_write_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, 0);
+
+ pdev->tph_mode = 0;
+ pdev->tph_req_type = 0;
+ pdev->tph_enabled = 0;
+}
+EXPORT_SYMBOL(pcie_disable_tph);
+
+/**
+ * pcie_enable_tph - Enable TPH support for device using a specific ST mode
+ * @pdev: PCI device
+ * @mode: ST mode to enable. Current supported modes include:
+ *
+ * - PCI_TPH_ST_NS_MODE: NO ST Mode
+ * - PCI_TPH_ST_IV_MODE: Interrupt Vector Mode
+ * - PCI_TPH_ST_DS_MODE: Device Specific Mode
+ *
+ * Check whether the mode is actually supported by the device before enabling
+ * and return an error if not. Additionally determine what types of requests,
+ * TPH or extended TPH, can be issued by the device based on its TPH requester
+ * capability and the Root Port's completer capability.
+ *
+ * Return: 0 on success, otherwise negative value (-errno)
+ */
+int pcie_enable_tph(struct pci_dev *pdev, int mode)
+{
+ u32 reg;
+ u8 dev_modes;
+ u8 rp_req_type;
+
+ /* Honor "notph" kernel parameter */
+ if (pci_tph_disabled)
+ return -EINVAL;
+
+ if (!pdev->tph_cap)
+ return -EINVAL;
+
+ if (pdev->tph_enabled)
+ return -EBUSY;
+
+ /* Sanitize and check ST mode compatibility */
+ mode &= PCI_TPH_CTRL_MODE_SEL_MASK;
+ dev_modes = get_st_modes(pdev);
+ if (!((1 << mode) & dev_modes))
+ return -EINVAL;
+
+ pdev->tph_mode = mode;
+
+ /* Get req_type supported by device and its Root Port */
+ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CAP, &reg);
+ if (FIELD_GET(PCI_TPH_CAP_EXT_TPH, reg))
+ pdev->tph_req_type = PCI_TPH_REQ_EXT_TPH;
+ else
+ pdev->tph_req_type = PCI_TPH_REQ_TPH_ONLY;
+
+ rp_req_type = get_rp_completer_type(pdev);
+
+ /* Final req_type is the smallest value of two */
+ pdev->tph_req_type = min(pdev->tph_req_type, rp_req_type);
+
+ if (pdev->tph_req_type == PCI_TPH_REQ_DISABLE)
+ return -EINVAL;
+
+ /* Write them into TPH control register */
+ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, &reg);
+
+ reg &= ~PCI_TPH_CTRL_MODE_SEL_MASK;
+ reg |= FIELD_PREP(PCI_TPH_CTRL_MODE_SEL_MASK, pdev->tph_mode);
+
+ reg &= ~PCI_TPH_CTRL_REQ_EN_MASK;
+ reg |= FIELD_PREP(PCI_TPH_CTRL_REQ_EN_MASK, pdev->tph_req_type);
+
+ pci_write_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, reg);
+
+ pdev->tph_enabled = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(pcie_enable_tph);
+
+void pci_restore_tph_state(struct pci_dev *pdev)
+{
+ struct pci_cap_saved_state *save_state;
+ int num_entries, i, offset;
+ u16 *st_entry;
+ u32 *cap;
+
+ if (!pdev->tph_cap)
+ return;
+
+ if (!pdev->tph_enabled)
+ return;
+
+ save_state = pci_find_saved_ext_cap(pdev, PCI_EXT_CAP_ID_TPH);
+ if (!save_state)
+ return;
+
+ /* Restore control register and all ST entries */
+ cap = &save_state->cap.data[0];
+ pci_write_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, *cap++);
+ st_entry = (u16 *)cap;
+ offset = PCI_TPH_BASE_SIZEOF;
+ num_entries = get_st_table_size(pdev);
+ for (i = 0; i < num_entries; i++) {
+ pci_write_config_word(pdev, pdev->tph_cap + offset,
+ *st_entry++);
+ offset += sizeof(u16);
+ }
+}
+
+void pci_save_tph_state(struct pci_dev *pdev)
+{
+ struct pci_cap_saved_state *save_state;
+ int num_entries, i, offset;
+ u16 *st_entry;
+ u32 *cap;
+
+ if (!pdev->tph_cap)
+ return;
+
+ if (!pdev->tph_enabled)
+ return;
+
+ save_state = pci_find_saved_ext_cap(pdev, PCI_EXT_CAP_ID_TPH);
+ if (!save_state)
+ return;
+
+ /* Save control register */
+ cap = &save_state->cap.data[0];
+ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, cap++);
+
+ /* Save all ST entries in extended capability structure */
+ st_entry = (u16 *)cap;
+ offset = PCI_TPH_BASE_SIZEOF;
+ num_entries = get_st_table_size(pdev);
+ for (i = 0; i < num_entries; i++) {
+ pci_read_config_word(pdev, pdev->tph_cap + offset,
+ st_entry++);
+ offset += sizeof(u16);
+ }
+}
+
+void pci_no_tph(void)
+{
+ pci_tph_disabled = true;
+
+ pr_info("PCIe TPH is disabled\n");
+}
+
+void pci_tph_init(struct pci_dev *pdev)
+{
+ int num_entries;
+ u32 save_size;
+
+ pdev->tph_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_TPH);
+ if (!pdev->tph_cap)
+ return;
+
+ num_entries = get_st_table_size(pdev);
+ save_size = sizeof(u32) + num_entries * sizeof(u16);
+ pci_add_ext_cap_save_buffer(pdev, PCI_EXT_CAP_ID_TPH, save_size);
+}
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index e4300f5f304f..a469bcbc0da7 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -325,7 +325,7 @@ static struct bin_attribute *vpd_attrs[] = {
};
static umode_t vpd_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 61b0c8952bb5..1deb9960db34 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -204,14 +204,8 @@ static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
for (i = 0; i < ARRAY_SIZE(skt->stat); i++) {
if (gpio_is_valid(skt->stat[i].gpio)) {
- unsigned long flags = GPIOF_IN;
-
- /* CD is active low by default */
- if (i == SOC_STAT_CD)
- flags |= GPIOF_ACTIVE_LOW;
-
ret = devm_gpio_request_one(skt->socket.dev.parent,
- skt->stat[i].gpio, flags,
+ skt->stat[i].gpio, GPIOF_IN,
skt->stat[i].name);
if (ret) {
__soc_pcmcia_hw_shutdown(skt, i);
@@ -219,6 +213,10 @@ static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
}
skt->stat[i].desc = gpio_to_desc(skt->stat[i].gpio);
+
+ /* CD is active low by default */
+ if ((i == SOC_STAT_CD) ^ gpiod_is_active_low(skt->stat[i].desc))
+ gpiod_toggle_active_low(skt->stat[i].desc);
}
if (i < SOC_STAT_VS1 && skt->stat[i].desc) {
diff --git a/drivers/peci/controller/peci-npcm.c b/drivers/peci/controller/peci-npcm.c
index ec613d35c796..fa91be58f6f3 100644
--- a/drivers/peci/controller/peci-npcm.c
+++ b/drivers/peci/controller/peci-npcm.c
@@ -224,7 +224,7 @@ static const struct regmap_config npcm_peci_regmap_config = {
.fast_io = true,
};
-static struct peci_controller_ops npcm_ops = {
+static const struct peci_controller_ops npcm_ops = {
.xfer = npcm_peci_xfer,
};
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index bab8ba64162f..4e268de351c4 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -284,4 +284,11 @@ config CXL_PMU
If unsure say 'm'.
+config MARVELL_PEM_PMU
+ tristate "MARVELL PEM PMU Support"
+ depends on ARCH_THUNDER || (COMPILE_TEST && 64BIT)
+ help
+ Enable support for PCIe Interface performance monitoring
+ on Marvell platform.
+
endmenu
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index 8268f38e42c5..de71d2574857 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o
obj-$(CONFIG_ARM_DMC620_PMU) += arm_dmc620_pmu.o
obj-$(CONFIG_MARVELL_CN10K_TAD_PMU) += marvell_cn10k_tad_pmu.o
obj-$(CONFIG_MARVELL_CN10K_DDR_PMU) += marvell_cn10k_ddr_pmu.o
+obj-$(CONFIG_MARVELL_PEM_PMU) += marvell_pem_pmu.o
obj-$(CONFIG_APPLE_M1_CPU_PMU) += apple_m1_cpu_pmu.o
obj-$(CONFIG_ALIBABA_UNCORE_DRW_PMU) += alibaba_uncore_drw_pmu.o
obj-$(CONFIG_DWC_PCIE_PMU) += dwc_pcie_pmu.o
diff --git a/drivers/perf/alibaba_uncore_drw_pmu.c b/drivers/perf/alibaba_uncore_drw_pmu.c
index c6ff1bc7d336..99a0ef9817e0 100644
--- a/drivers/perf/alibaba_uncore_drw_pmu.c
+++ b/drivers/perf/alibaba_uncore_drw_pmu.c
@@ -782,7 +782,7 @@ static struct platform_driver ali_drw_pmu_driver = {
.acpi_match_table = ali_drw_acpi_match,
},
.probe = ali_drw_pmu_probe,
- .remove_new = ali_drw_pmu_remove,
+ .remove = ali_drw_pmu_remove,
};
static int __init ali_drw_pmu_init(void)
diff --git a/drivers/perf/amlogic/meson_g12_ddr_pmu.c b/drivers/perf/amlogic/meson_g12_ddr_pmu.c
index 99cc791892bc..f33e9a456e85 100644
--- a/drivers/perf/amlogic/meson_g12_ddr_pmu.c
+++ b/drivers/perf/amlogic/meson_g12_ddr_pmu.c
@@ -379,7 +379,7 @@ MODULE_DEVICE_TABLE(of, meson_ddr_pmu_dt_match);
static struct platform_driver g12_ddr_pmu_driver = {
.probe = g12_ddr_pmu_probe,
- .remove_new = g12_ddr_pmu_remove,
+ .remove = g12_ddr_pmu_remove,
.driver = {
.name = "meson-g12-ddr-pmu",
diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c
index c76bac668dea..1cc3214d6b6d 100644
--- a/drivers/perf/arm-cci.c
+++ b/drivers/perf/arm-cci.c
@@ -1705,7 +1705,7 @@ static struct platform_driver cci_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = cci_pmu_probe,
- .remove_new = cci_pmu_remove,
+ .remove = cci_pmu_remove,
};
module_platform_driver(cci_pmu_driver);
diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c
index 5c66b9278862..d5fcea3d4328 100644
--- a/drivers/perf/arm-ccn.c
+++ b/drivers/perf/arm-ccn.c
@@ -1529,7 +1529,7 @@ static struct platform_driver arm_ccn_driver = {
.suppress_bind_attrs = true,
},
.probe = arm_ccn_probe,
- .remove_new = arm_ccn_remove,
+ .remove = arm_ccn_remove,
};
static int __init arm_ccn_init(void)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 397a46410f7c..b20fa600e510 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -2178,8 +2178,6 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
continue;
xp = arm_cmn_node_to_xp(cmn, dn);
- dn->portid_bits = xp->portid_bits;
- dn->deviceid_bits = xp->deviceid_bits;
dn->dtc = xp->dtc;
dn->dtm = xp->dtm;
if (cmn->multi_dtm)
@@ -2420,6 +2418,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
}
arm_cmn_init_node_info(cmn, reg & CMN_CHILD_NODE_ADDR, dn);
+ dn->portid_bits = xp->portid_bits;
+ dn->deviceid_bits = xp->deviceid_bits;
switch (dn->type) {
case CMN_TYPE_DTC:
@@ -2662,7 +2662,7 @@ static struct platform_driver arm_cmn_driver = {
.acpi_match_table = ACPI_PTR(arm_cmn_acpi_match),
},
.probe = arm_cmn_probe,
- .remove_new = arm_cmn_remove,
+ .remove = arm_cmn_remove,
};
static int __init arm_cmn_init(void)
diff --git a/drivers/perf/arm-ni.c b/drivers/perf/arm-ni.c
index 90fcfe693439..fd7a5e60e963 100644
--- a/drivers/perf/arm-ni.c
+++ b/drivers/perf/arm-ni.c
@@ -247,7 +247,6 @@ static struct attribute *arm_ni_other_attrs[] = {
static const struct attribute_group arm_ni_other_attr_group = {
.attrs = arm_ni_other_attrs,
- NULL
};
static const struct attribute_group *arm_ni_attr_groups[] = {
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 2158a5975c90..81e8b97e9353 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -1282,7 +1282,7 @@ static struct platform_driver arm_cspmu_driver = {
.suppress_bind_attrs = true,
},
.probe = arm_cspmu_device_probe,
- .remove_new = arm_cspmu_device_remove,
+ .remove = arm_cspmu_device_remove,
.id_table = arm_cspmu_id,
};
diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c
index 7e5f1d4fca0f..619cf937602f 100644
--- a/drivers/perf/arm_dmc620_pmu.c
+++ b/drivers/perf/arm_dmc620_pmu.c
@@ -750,7 +750,7 @@ static struct platform_driver dmc620_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = dmc620_pmu_device_probe,
- .remove_new = dmc620_pmu_device_remove,
+ .remove = dmc620_pmu_device_remove,
};
static int __init dmc620_pmu_init(void)
diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c
index f2bd25a3470a..cb4fb59fe04b 100644
--- a/drivers/perf/arm_dsu_pmu.c
+++ b/drivers/perf/arm_dsu_pmu.c
@@ -787,7 +787,7 @@ static struct platform_driver dsu_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = dsu_pmu_device_probe,
- .remove_new = dsu_pmu_device_remove,
+ .remove = dsu_pmu_device_remove,
};
static int dsu_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 0afe02f879b4..b5cc11abc962 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -770,18 +770,27 @@ static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu)
int i;
struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
- /* Clear any unused counters to avoid leaking their contents */
- for_each_andnot_bit(i, cpu_pmu->cntr_mask, cpuc->used_mask,
- ARMPMU_MAX_HWEVENTS) {
- if (i == ARMV8_PMU_CYCLE_IDX)
- write_pmccntr(0);
- else if (i == ARMV8_PMU_INSTR_IDX)
- write_pmicntr(0);
- else
- armv8pmu_write_evcntr(i, 0);
+ if (is_pmuv3p9(cpu_pmu->pmuver)) {
+ u64 mask = 0;
+ for_each_set_bit(i, cpuc->used_mask, ARMPMU_MAX_HWEVENTS) {
+ if (armv8pmu_event_has_user_read(cpuc->events[i]))
+ mask |= BIT(i);
+ }
+ write_pmuacr(mask);
+ } else {
+ /* Clear any unused counters to avoid leaking their contents */
+ for_each_andnot_bit(i, cpu_pmu->cntr_mask, cpuc->used_mask,
+ ARMPMU_MAX_HWEVENTS) {
+ if (i == ARMV8_PMU_CYCLE_IDX)
+ write_pmccntr(0);
+ else if (i == ARMV8_PMU_INSTR_IDX)
+ write_pmicntr(0);
+ else
+ armv8pmu_write_evcntr(i, 0);
+ }
}
- update_pmuserenr(ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_CR);
+ update_pmuserenr(ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_CR | ARMV8_PMU_USERENR_UEN);
}
static void armv8pmu_enable_event(struct perf_event *event)
@@ -1364,6 +1373,8 @@ PMUV3_INIT_SIMPLE(armv8_neoverse_v3ae)
PMUV3_INIT_SIMPLE(armv8_nvidia_carmel)
PMUV3_INIT_SIMPLE(armv8_nvidia_denver)
+PMUV3_INIT_SIMPLE(armv8_samsung_mongoose)
+
PMUV3_INIT_MAP_EVENT(armv8_cortex_a35, armv8_a53_map_event)
PMUV3_INIT_MAP_EVENT(armv8_cortex_a53, armv8_a53_map_event)
PMUV3_INIT_MAP_EVENT(armv8_cortex_a57, armv8_a57_map_event)
@@ -1409,6 +1420,7 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = {
{.compatible = "brcm,vulcan-pmu", .data = armv8_brcm_vulcan_pmu_init},
{.compatible = "nvidia,carmel-pmu", .data = armv8_nvidia_carmel_pmu_init},
{.compatible = "nvidia,denver-pmu", .data = armv8_nvidia_denver_pmu_init},
+ {.compatible = "samsung,mongoose-pmu", .data = armv8_samsung_mongoose_pmu_init},
{},
};
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index d5fa92ba8373..621f02a7f43b 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -431,6 +431,17 @@ static int smmu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
+ /*
+ * Ensure all events are on the same cpu so all events are in the
+ * same cpu context, to avoid races on pmu_enable etc.
+ */
+ event->cpu = smmu_pmu->on_cpu;
+
+ hwc->idx = -1;
+
+ if (event->group_leader == event)
+ return 0;
+
for_each_sibling_event(sibling, event->group_leader) {
if (is_software_event(sibling))
continue;
@@ -442,14 +453,6 @@ static int smmu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
- hwc->idx = -1;
-
- /*
- * Ensure all events are on the same cpu so all events are in the
- * same cpu context, to avoid races on pmu_enable etc.
- */
- event->cpu = smmu_pmu->on_cpu;
-
return 0;
}
@@ -996,7 +999,7 @@ static struct platform_driver smmu_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = smmu_pmu_probe,
- .remove_new = smmu_pmu_remove,
+ .remove = smmu_pmu_remove,
.shutdown = smmu_pmu_shutdown,
};
diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
index 3569050f9cf3..fd5b78732603 100644
--- a/drivers/perf/arm_spe_pmu.c
+++ b/drivers/perf/arm_spe_pmu.c
@@ -1280,7 +1280,7 @@ static struct platform_driver arm_spe_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = arm_spe_pmu_device_probe,
- .remove_new = arm_spe_pmu_device_remove,
+ .remove = arm_spe_pmu_device_remove,
};
static int __init arm_spe_pmu_init(void)
diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
index 43d68b69e630..bee4b5b52ec6 100644
--- a/drivers/perf/cxl_pmu.c
+++ b/drivers/perf/cxl_pmu.c
@@ -354,7 +354,7 @@ static struct attribute *cxl_pmu_event_attrs[] = {
CXL_PMU_EVENT_CXL_ATTR(d2h_req_wowrinvf, CXL_PMU_GID_D2H_REQ, BIT(13)),
CXL_PMU_EVENT_CXL_ATTR(d2h_req_wrinv, CXL_PMU_GID_D2H_REQ, BIT(14)),
CXL_PMU_EVENT_CXL_ATTR(d2h_req_cacheflushed, CXL_PMU_GID_D2H_REQ, BIT(16)),
- /* CXL rev 3.0 Table 3-20 - D2H Repsonse Encodings */
+ /* CXL rev 3.0 Table 3-20 - D2H Response Encodings */
CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihiti, CXL_PMU_GID_D2H_RSP, BIT(4)),
CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspvhitv, CXL_PMU_GID_D2H_RSP, BIT(6)),
CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihitse, CXL_PMU_GID_D2H_RSP, BIT(5)),
@@ -377,12 +377,14 @@ static struct attribute *cxl_pmu_event_attrs[] = {
/* CXL rev 3.0 Table 13-5 directly lists these */
CXL_PMU_EVENT_CXL_ATTR(cachedata_d2h_data, CXL_PMU_GID_CACHE_DATA, BIT(0)),
CXL_PMU_EVENT_CXL_ATTR(cachedata_h2d_data, CXL_PMU_GID_CACHE_DATA, BIT(1)),
- /* CXL rev 3.0 Table 3-29 M2S Req Memory Opcodes */
+ /* CXL rev 3.1 Table 3-35 M2S Req Memory Opcodes */
CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminv, CXL_PMU_GID_M2S_REQ, BIT(0)),
CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrd, CXL_PMU_GID_M2S_REQ, BIT(1)),
CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrddata, CXL_PMU_GID_M2S_REQ, BIT(2)),
CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrdfwd, CXL_PMU_GID_M2S_REQ, BIT(3)),
CXL_PMU_EVENT_CXL_ATTR(m2s_req_memwrfwd, CXL_PMU_GID_M2S_REQ, BIT(4)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrdtee, CXL_PMU_GID_M2S_REQ, BIT(5)),
+ CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrddatatee, CXL_PMU_GID_M2S_REQ, BIT(6)),
CXL_PMU_EVENT_CXL_ATTR(m2s_req_memspecrd, CXL_PMU_GID_M2S_REQ, BIT(8)),
CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminvnt, CXL_PMU_GID_M2S_REQ, BIT(9)),
CXL_PMU_EVENT_CXL_ATTR(m2s_req_memcleanevict, CXL_PMU_GID_M2S_REQ, BIT(10)),
@@ -404,10 +406,11 @@ static struct attribute *cxl_pmu_event_attrs[] = {
CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_curblk, CXL_PMU_GID_S2M_BISNP, BIT(4)),
CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_datblk, CXL_PMU_GID_S2M_BISNP, BIT(5)),
CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_invblk, CXL_PMU_GID_S2M_BISNP, BIT(6)),
- /* CXL rev 3.0 Table 3-43 S2M NDR Opcopdes */
+ /* CXL rev 3.1 Table 3-50 S2M NDR Opcopdes */
CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmp, CXL_PMU_GID_S2M_NDR, BIT(0)),
CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmps, CXL_PMU_GID_S2M_NDR, BIT(1)),
CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmpe, CXL_PMU_GID_S2M_NDR, BIT(2)),
+ CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmpm, CXL_PMU_GID_S2M_NDR, BIT(3)),
CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_biconflictack, CXL_PMU_GID_S2M_NDR, BIT(4)),
/* CXL rev 3.0 Table 3-46 S2M DRS opcodes */
CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdata, CXL_PMU_GID_S2M_DRS, BIT(0)),
diff --git a/drivers/perf/dwc_pcie_pmu.c b/drivers/perf/dwc_pcie_pmu.c
index 4ca50f9b6dfe..9cbea9675e21 100644
--- a/drivers/perf/dwc_pcie_pmu.c
+++ b/drivers/perf/dwc_pcie_pmu.c
@@ -82,7 +82,6 @@ struct dwc_pcie_pmu {
u16 ras_des_offset;
u32 nr_lanes;
- struct list_head pmu_node;
struct hlist_node cpuhp_node;
struct perf_event *event[DWC_PCIE_EVENT_TYPE_MAX];
int on_cpu;
@@ -107,6 +106,7 @@ struct dwc_pcie_vendor_id {
static const struct dwc_pcie_vendor_id dwc_pcie_vendor_ids[] = {
{.vendor_id = PCI_VENDOR_ID_ALIBABA },
+ {.vendor_id = PCI_VENDOR_ID_AMPERE },
{.vendor_id = PCI_VENDOR_ID_QCOM },
{} /* terminator */
};
@@ -203,10 +203,10 @@ static struct attribute *dwc_pcie_pmu_time_event_attrs[] = {
DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(L1_AUX, 0x09),
/* Group #1 */
- DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(Tx_PCIe_TLP_Data_Payload, 0x20),
- DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(Rx_PCIe_TLP_Data_Payload, 0x21),
- DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(Tx_CCIX_TLP_Data_Payload, 0x22),
- DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(Rx_CCIX_TLP_Data_Payload, 0x23),
+ DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(tx_pcie_tlp_data_payload, 0x20),
+ DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(rx_pcie_tlp_data_payload, 0x21),
+ DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(tx_ccix_tlp_data_payload, 0x22),
+ DWC_PCIE_PMU_TIME_BASE_EVENT_ATTR(rx_ccix_tlp_data_payload, 0x23),
/*
* Leave it to the user to specify the lane ID to avoid generating
@@ -216,9 +216,9 @@ static struct attribute *dwc_pcie_pmu_time_event_attrs[] = {
DWC_PCIE_PMU_LANE_EVENT_ATTR(tx_update_fc_dllp, 0x601),
DWC_PCIE_PMU_LANE_EVENT_ATTR(rx_ack_dllp, 0x602),
DWC_PCIE_PMU_LANE_EVENT_ATTR(rx_update_fc_dllp, 0x603),
- DWC_PCIE_PMU_LANE_EVENT_ATTR(rx_nulified_tlp, 0x604),
- DWC_PCIE_PMU_LANE_EVENT_ATTR(tx_nulified_tlp, 0x605),
- DWC_PCIE_PMU_LANE_EVENT_ATTR(rx_duplicate_tl, 0x606),
+ DWC_PCIE_PMU_LANE_EVENT_ATTR(rx_nullified_tlp, 0x604),
+ DWC_PCIE_PMU_LANE_EVENT_ATTR(tx_nullified_tlp, 0x605),
+ DWC_PCIE_PMU_LANE_EVENT_ATTR(rx_duplicate_tlp, 0x606),
DWC_PCIE_PMU_LANE_EVENT_ATTR(tx_memory_write, 0x700),
DWC_PCIE_PMU_LANE_EVENT_ATTR(tx_memory_read, 0x701),
DWC_PCIE_PMU_LANE_EVENT_ATTR(tx_configuration_write, 0x702),
diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
index 746b92330ca7..b989ffa95d69 100644
--- a/drivers/perf/fsl_imx8_ddr_perf.c
+++ b/drivers/perf/fsl_imx8_ddr_perf.c
@@ -846,7 +846,7 @@ static struct platform_driver imx_ddr_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = ddr_perf_probe,
- .remove_new = ddr_perf_remove,
+ .remove = ddr_perf_remove,
};
module_platform_driver(imx_ddr_pmu_driver);
diff --git a/drivers/perf/fsl_imx9_ddr_perf.c b/drivers/perf/fsl_imx9_ddr_perf.c
index 69f920b1caf2..3c856d9a4e97 100644
--- a/drivers/perf/fsl_imx9_ddr_perf.c
+++ b/drivers/perf/fsl_imx9_ddr_perf.c
@@ -81,6 +81,10 @@ struct ddr_pmu {
int id;
};
+static const struct imx_ddr_devtype_data imx91_devtype_data = {
+ .identifier = "imx91",
+};
+
static const struct imx_ddr_devtype_data imx93_devtype_data = {
.identifier = "imx93",
};
@@ -100,6 +104,7 @@ static inline bool is_imx95(struct ddr_pmu *pmu)
}
static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
+ { .compatible = "fsl,imx91-ddr-pmu", .data = &imx91_devtype_data },
{ .compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data },
{ .compatible = "fsl,imx95-ddr-pmu", .data = &imx95_devtype_data },
{ /* sentinel */ }
@@ -848,7 +853,7 @@ static struct platform_driver imx_ddr_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = ddr_perf_probe,
- .remove_new = ddr_perf_remove,
+ .remove = ddr_perf_remove,
};
module_platform_driver(imx_ddr_pmu_driver);
diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
index 0e923f94fa5b..3f3fb1de11f5 100644
--- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
@@ -358,7 +358,7 @@ static struct platform_driver hisi_cpa_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = hisi_cpa_pmu_probe,
- .remove_new = hisi_cpa_pmu_remove,
+ .remove = hisi_cpa_pmu_remove,
};
static int __init hisi_cpa_pmu_module_init(void)
diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
index b804e3738113..a6ebf2ec99d3 100644
--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -547,7 +547,7 @@ static struct platform_driver hisi_ddrc_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = hisi_ddrc_pmu_probe,
- .remove_new = hisi_ddrc_pmu_remove,
+ .remove = hisi_ddrc_pmu_remove,
};
static int __init hisi_ddrc_pmu_module_init(void)
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
index 21e69b1cdd4d..32624872596f 100644
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -550,7 +550,7 @@ static struct platform_driver hisi_hha_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = hisi_hha_pmu_probe,
- .remove_new = hisi_hha_pmu_remove,
+ .remove = hisi_hha_pmu_remove,
};
static int __init hisi_hha_pmu_module_init(void)
diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
index 51ba76871097..c235b46ce873 100644
--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -584,7 +584,7 @@ static struct platform_driver hisi_l3c_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = hisi_l3c_pmu_probe,
- .remove_new = hisi_l3c_pmu_remove,
+ .remove = hisi_l3c_pmu_remove,
};
static int __init hisi_l3c_pmu_module_init(void)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
index 3cdb35c741f9..c0f5d7c73e06 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
@@ -538,7 +538,7 @@ static struct platform_driver hisi_pa_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = hisi_pa_pmu_probe,
- .remove_new = hisi_pa_pmu_remove,
+ .remove = hisi_pa_pmu_remove,
};
static int __init hisi_pa_pmu_module_init(void)
diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
index 765bbd61db26..c5f4764ee888 100644
--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
@@ -476,7 +476,7 @@ static struct platform_driver hisi_sllc_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = hisi_sllc_pmu_probe,
- .remove_new = hisi_sllc_pmu_remove,
+ .remove = hisi_sllc_pmu_remove,
};
static int __init hisi_sllc_pmu_module_init(void)
diff --git a/drivers/perf/marvell_cn10k_ddr_pmu.c b/drivers/perf/marvell_cn10k_ddr_pmu.c
index 94f1ebcd2a27..8860d9f687ae 100644
--- a/drivers/perf/marvell_cn10k_ddr_pmu.c
+++ b/drivers/perf/marvell_cn10k_ddr_pmu.c
@@ -732,7 +732,7 @@ static struct platform_driver cn10k_ddr_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = cn10k_ddr_perf_probe,
- .remove_new = cn10k_ddr_perf_remove,
+ .remove = cn10k_ddr_perf_remove,
};
static int __init cn10k_ddr_pmu_init(void)
diff --git a/drivers/perf/marvell_cn10k_tad_pmu.c b/drivers/perf/marvell_cn10k_tad_pmu.c
index 9e635f355470..cda55ee35eee 100644
--- a/drivers/perf/marvell_cn10k_tad_pmu.c
+++ b/drivers/perf/marvell_cn10k_tad_pmu.c
@@ -383,7 +383,7 @@ static struct platform_driver tad_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = tad_pmu_probe,
- .remove_new = tad_pmu_remove,
+ .remove = tad_pmu_remove,
};
static int tad_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
diff --git a/drivers/perf/marvell_pem_pmu.c b/drivers/perf/marvell_pem_pmu.c
new file mode 100644
index 000000000000..29fbcd1848e4
--- /dev/null
+++ b/drivers/perf/marvell_pem_pmu.c
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Marvell PEM(PCIe RC) Performance Monitor Driver
+ *
+ * Copyright (C) 2024 Marvell.
+ */
+
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+
+/*
+ * Each of these events maps to a free running 64 bit counter
+ * with no event control, but can be reset.
+ */
+enum pem_events {
+ IB_TLP_NPR,
+ IB_TLP_PR,
+ IB_TLP_CPL,
+ IB_TLP_DWORDS_NPR,
+ IB_TLP_DWORDS_PR,
+ IB_TLP_DWORDS_CPL,
+ IB_INFLIGHT,
+ IB_READS,
+ IB_REQ_NO_RO_NCB,
+ IB_REQ_NO_RO_EBUS,
+ OB_TLP_NPR,
+ OB_TLP_PR,
+ OB_TLP_CPL,
+ OB_TLP_DWORDS_NPR,
+ OB_TLP_DWORDS_PR,
+ OB_TLP_DWORDS_CPL,
+ OB_INFLIGHT,
+ OB_READS,
+ OB_MERGES_NPR,
+ OB_MERGES_PR,
+ OB_MERGES_CPL,
+ ATS_TRANS,
+ ATS_TRANS_LATENCY,
+ ATS_PRI,
+ ATS_PRI_LATENCY,
+ ATS_INV,
+ ATS_INV_LATENCY,
+ PEM_EVENTIDS_MAX
+};
+
+static u64 eventid_to_offset_table[] = {
+ [IB_TLP_NPR] = 0x0,
+ [IB_TLP_PR] = 0x8,
+ [IB_TLP_CPL] = 0x10,
+ [IB_TLP_DWORDS_NPR] = 0x100,
+ [IB_TLP_DWORDS_PR] = 0x108,
+ [IB_TLP_DWORDS_CPL] = 0x110,
+ [IB_INFLIGHT] = 0x200,
+ [IB_READS] = 0x300,
+ [IB_REQ_NO_RO_NCB] = 0x400,
+ [IB_REQ_NO_RO_EBUS] = 0x408,
+ [OB_TLP_NPR] = 0x500,
+ [OB_TLP_PR] = 0x508,
+ [OB_TLP_CPL] = 0x510,
+ [OB_TLP_DWORDS_NPR] = 0x600,
+ [OB_TLP_DWORDS_PR] = 0x608,
+ [OB_TLP_DWORDS_CPL] = 0x610,
+ [OB_INFLIGHT] = 0x700,
+ [OB_READS] = 0x800,
+ [OB_MERGES_NPR] = 0x900,
+ [OB_MERGES_PR] = 0x908,
+ [OB_MERGES_CPL] = 0x910,
+ [ATS_TRANS] = 0x2D18,
+ [ATS_TRANS_LATENCY] = 0x2D20,
+ [ATS_PRI] = 0x2D28,
+ [ATS_PRI_LATENCY] = 0x2D30,
+ [ATS_INV] = 0x2D38,
+ [ATS_INV_LATENCY] = 0x2D40,
+};
+
+struct pem_pmu {
+ struct pmu pmu;
+ void __iomem *base;
+ unsigned int cpu;
+ struct device *dev;
+ struct hlist_node node;
+};
+
+#define to_pem_pmu(p) container_of(p, struct pem_pmu, pmu)
+
+static int eventid_to_offset(int eventid)
+{
+ return eventid_to_offset_table[eventid];
+}
+
+/* Events */
+static ssize_t pem_pmu_event_show(struct device *dev,
+ struct device_attribute *attr,
+ char *page)
+{
+ struct perf_pmu_events_attr *pmu_attr;
+
+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+ return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
+}
+
+#define PEM_EVENT_ATTR(_name, _id) \
+ (&((struct perf_pmu_events_attr[]) { \
+ { .attr = __ATTR(_name, 0444, pem_pmu_event_show, NULL), \
+ .id = _id, } \
+ })[0].attr.attr)
+
+static struct attribute *pem_perf_events_attrs[] = {
+ PEM_EVENT_ATTR(ib_tlp_npr, IB_TLP_NPR),
+ PEM_EVENT_ATTR(ib_tlp_pr, IB_TLP_PR),
+ PEM_EVENT_ATTR(ib_tlp_cpl_partid, IB_TLP_CPL),
+ PEM_EVENT_ATTR(ib_tlp_dwords_npr, IB_TLP_DWORDS_NPR),
+ PEM_EVENT_ATTR(ib_tlp_dwords_pr, IB_TLP_DWORDS_PR),
+ PEM_EVENT_ATTR(ib_tlp_dwords_cpl_partid, IB_TLP_DWORDS_CPL),
+ PEM_EVENT_ATTR(ib_inflight, IB_INFLIGHT),
+ PEM_EVENT_ATTR(ib_reads, IB_READS),
+ PEM_EVENT_ATTR(ib_req_no_ro_ncb, IB_REQ_NO_RO_NCB),
+ PEM_EVENT_ATTR(ib_req_no_ro_ebus, IB_REQ_NO_RO_EBUS),
+ PEM_EVENT_ATTR(ob_tlp_npr_partid, OB_TLP_NPR),
+ PEM_EVENT_ATTR(ob_tlp_pr_partid, OB_TLP_PR),
+ PEM_EVENT_ATTR(ob_tlp_cpl_partid, OB_TLP_CPL),
+ PEM_EVENT_ATTR(ob_tlp_dwords_npr_partid, OB_TLP_DWORDS_NPR),
+ PEM_EVENT_ATTR(ob_tlp_dwords_pr_partid, OB_TLP_DWORDS_PR),
+ PEM_EVENT_ATTR(ob_tlp_dwords_cpl_partid, OB_TLP_DWORDS_CPL),
+ PEM_EVENT_ATTR(ob_inflight_partid, OB_INFLIGHT),
+ PEM_EVENT_ATTR(ob_reads_partid, OB_READS),
+ PEM_EVENT_ATTR(ob_merges_npr_partid, OB_MERGES_NPR),
+ PEM_EVENT_ATTR(ob_merges_pr_partid, OB_MERGES_PR),
+ PEM_EVENT_ATTR(ob_merges_cpl_partid, OB_MERGES_CPL),
+ PEM_EVENT_ATTR(ats_trans, ATS_TRANS),
+ PEM_EVENT_ATTR(ats_trans_latency, ATS_TRANS_LATENCY),
+ PEM_EVENT_ATTR(ats_pri, ATS_PRI),
+ PEM_EVENT_ATTR(ats_pri_latency, ATS_PRI_LATENCY),
+ PEM_EVENT_ATTR(ats_inv, ATS_INV),
+ PEM_EVENT_ATTR(ats_inv_latency, ATS_INV_LATENCY),
+ NULL
+};
+
+static struct attribute_group pem_perf_events_attr_group = {
+ .name = "events",
+ .attrs = pem_perf_events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-5");
+
+static struct attribute *pem_perf_format_attrs[] = {
+ &format_attr_event.attr,
+ NULL
+};
+
+static struct attribute_group pem_perf_format_attr_group = {
+ .name = "format",
+ .attrs = pem_perf_format_attrs,
+};
+
+/* cpumask */
+static ssize_t pem_perf_cpumask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pem_pmu *pmu = dev_get_drvdata(dev);
+
+ return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
+}
+
+static struct device_attribute pem_perf_cpumask_attr =
+ __ATTR(cpumask, 0444, pem_perf_cpumask_show, NULL);
+
+static struct attribute *pem_perf_cpumask_attrs[] = {
+ &pem_perf_cpumask_attr.attr,
+ NULL
+};
+
+static struct attribute_group pem_perf_cpumask_attr_group = {
+ .attrs = pem_perf_cpumask_attrs,
+};
+
+static const struct attribute_group *pem_perf_attr_groups[] = {
+ &pem_perf_events_attr_group,
+ &pem_perf_cpumask_attr_group,
+ &pem_perf_format_attr_group,
+ NULL
+};
+
+static int pem_perf_event_init(struct perf_event *event)
+{
+ struct pem_pmu *pmu = to_pem_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ struct perf_event *sibling;
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (event->attr.config >= PEM_EVENTIDS_MAX)
+ return -EINVAL;
+
+ if (is_sampling_event(event) ||
+ event->attach_state & PERF_ATTACH_TASK) {
+ return -EOPNOTSUPP;
+ }
+
+ if (event->cpu < 0)
+ return -EOPNOTSUPP;
+
+ /* We must NOT create groups containing mixed PMUs */
+ if (event->group_leader->pmu != event->pmu &&
+ !is_software_event(event->group_leader))
+ return -EINVAL;
+
+ for_each_sibling_event(sibling, event->group_leader) {
+ if (sibling->pmu != event->pmu &&
+ !is_software_event(sibling))
+ return -EINVAL;
+ }
+ /*
+ * Set ownership of event to one CPU, same event can not be observed
+ * on multiple cpus at same time.
+ */
+ event->cpu = pmu->cpu;
+ hwc->idx = -1;
+ return 0;
+}
+
+static u64 pem_perf_read_counter(struct pem_pmu *pmu,
+ struct perf_event *event, int eventid)
+{
+ return readq_relaxed(pmu->base + eventid_to_offset(eventid));
+}
+
+static void pem_perf_event_update(struct perf_event *event)
+{
+ struct pem_pmu *pmu = to_pem_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ u64 prev_count, new_count;
+
+ do {
+ prev_count = local64_read(&hwc->prev_count);
+ new_count = pem_perf_read_counter(pmu, event, hwc->idx);
+ } while (local64_xchg(&hwc->prev_count, new_count) != prev_count);
+
+ local64_add((new_count - prev_count), &event->count);
+}
+
+static void pem_perf_event_start(struct perf_event *event, int flags)
+{
+ struct pem_pmu *pmu = to_pem_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ int eventid = hwc->idx;
+
+ /*
+ * All counters are free-running and associated with
+ * a fixed event to track in Hardware
+ */
+ local64_set(&hwc->prev_count,
+ pem_perf_read_counter(pmu, event, eventid));
+
+ hwc->state = 0;
+}
+
+static int pem_perf_event_add(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ hwc->idx = event->attr.config;
+ if (WARN_ON_ONCE(hwc->idx >= PEM_EVENTIDS_MAX))
+ return -EINVAL;
+ hwc->state |= PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ pem_perf_event_start(event, flags);
+
+ return 0;
+}
+
+static void pem_perf_event_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (flags & PERF_EF_UPDATE)
+ pem_perf_event_update(event);
+
+ hwc->state |= PERF_HES_STOPPED;
+}
+
+static void pem_perf_event_del(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ pem_perf_event_stop(event, PERF_EF_UPDATE);
+ hwc->idx = -1;
+}
+
+static int pem_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+ struct pem_pmu *pmu = hlist_entry_safe(node, struct pem_pmu, node);
+ unsigned int target;
+
+ if (cpu != pmu->cpu)
+ return 0;
+
+ target = cpumask_any_but(cpu_online_mask, cpu);
+ if (target >= nr_cpu_ids)
+ return 0;
+
+ perf_pmu_migrate_context(&pmu->pmu, cpu, target);
+ pmu->cpu = target;
+ return 0;
+}
+
+static int pem_perf_probe(struct platform_device *pdev)
+{
+ struct pem_pmu *pem_pmu;
+ struct resource *res;
+ void __iomem *base;
+ char *name;
+ int ret;
+
+ pem_pmu = devm_kzalloc(&pdev->dev, sizeof(*pem_pmu), GFP_KERNEL);
+ if (!pem_pmu)
+ return -ENOMEM;
+
+ pem_pmu->dev = &pdev->dev;
+ platform_set_drvdata(pdev, pem_pmu);
+
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ pem_pmu->base = base;
+
+ pem_pmu->pmu = (struct pmu) {
+ .module = THIS_MODULE,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = pem_perf_attr_groups,
+ .event_init = pem_perf_event_init,
+ .add = pem_perf_event_add,
+ .del = pem_perf_event_del,
+ .start = pem_perf_event_start,
+ .stop = pem_perf_event_stop,
+ .read = pem_perf_event_update,
+ };
+
+ /* Choose this cpu to collect perf data */
+ pem_pmu->cpu = raw_smp_processor_id();
+
+ name = devm_kasprintf(pem_pmu->dev, GFP_KERNEL, "mrvl_pcie_rc_pmu_%llx",
+ res->start);
+ if (!name)
+ return -ENOMEM;
+
+ cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_MRVL_PEM_ONLINE,
+ &pem_pmu->node);
+
+ ret = perf_pmu_register(&pem_pmu->pmu, name, -1);
+ if (ret)
+ goto error;
+
+ return 0;
+error:
+ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_MRVL_PEM_ONLINE,
+ &pem_pmu->node);
+ return ret;
+}
+
+static void pem_perf_remove(struct platform_device *pdev)
+{
+ struct pem_pmu *pem_pmu = platform_get_drvdata(pdev);
+
+ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_MRVL_PEM_ONLINE,
+ &pem_pmu->node);
+
+ perf_pmu_unregister(&pem_pmu->pmu);
+}
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id pem_pmu_acpi_match[] = {
+ {"MRVL000E", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, pem_pmu_acpi_match);
+#endif
+
+static struct platform_driver pem_pmu_driver = {
+ .driver = {
+ .name = "pem-pmu",
+ .acpi_match_table = ACPI_PTR(pem_pmu_acpi_match),
+ .suppress_bind_attrs = true,
+ },
+ .probe = pem_perf_probe,
+ .remove = pem_perf_remove,
+};
+
+static int __init pem_pmu_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_MRVL_PEM_ONLINE,
+ "perf/marvell/pem:online", NULL,
+ pem_pmu_offline_cpu);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&pem_pmu_driver);
+ if (ret)
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_MRVL_PEM_ONLINE);
+ return ret;
+}
+
+static void __exit pem_pmu_exit(void)
+{
+ platform_driver_unregister(&pem_pmu_driver);
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_MRVL_PEM_ONLINE);
+}
+
+module_init(pem_pmu_init);
+module_exit(pem_pmu_exit);
+
+MODULE_DESCRIPTION("Marvell PEM Perf driver");
+MODULE_AUTHOR("Gowthami Thiagarajan <gthiagarajan@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c
index 980e3051edd7..ea8c85729937 100644
--- a/drivers/perf/qcom_l2_pmu.c
+++ b/drivers/perf/qcom_l2_pmu.c
@@ -981,7 +981,7 @@ static struct platform_driver l2_cache_pmu_driver = {
.suppress_bind_attrs = true,
},
.probe = l2_cache_pmu_probe,
- .remove_new = l2_cache_pmu_remove,
+ .remove = l2_cache_pmu_remove,
};
static int __init register_l2_cache_pmu_driver(void)
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index 391ca1422cae..1aa303f76cc7 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -1393,8 +1393,9 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
goto out_unregister;
cpu = get_cpu();
-
ret = pmu_sbi_snapshot_setup(pmu, cpu);
+ put_cpu();
+
if (ret) {
/* Snapshot is an optional feature. Continue if not available */
pmu_sbi_snapshot_free(pmu);
@@ -1408,7 +1409,6 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
*/
static_branch_enable(&sbi_pmu_snapshot_available);
}
- put_cpu();
}
register_sysctl("kernel", sbi_pmu_sysctl_table);
diff --git a/drivers/perf/thunderx2_pmu.c b/drivers/perf/thunderx2_pmu.c
index faf763d2c95c..cadd60221b8f 100644
--- a/drivers/perf/thunderx2_pmu.c
+++ b/drivers/perf/thunderx2_pmu.c
@@ -1010,7 +1010,7 @@ static struct platform_driver tx2_uncore_driver = {
.suppress_bind_attrs = true,
},
.probe = tx2_uncore_probe,
- .remove_new = tx2_uncore_remove,
+ .remove = tx2_uncore_remove,
};
static int __init tx2_uncore_driver_init(void)
diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c
index c01466ae1e3d..33b5497bdc06 100644
--- a/drivers/perf/xgene_pmu.c
+++ b/drivers/perf/xgene_pmu.c
@@ -1943,7 +1943,7 @@ static void xgene_pmu_remove(struct platform_device *pdev)
static struct platform_driver xgene_pmu_driver = {
.probe = xgene_pmu_probe,
- .remove_new = xgene_pmu_remove,
+ .remove = xgene_pmu_remove,
.driver = {
.name = "xgene-pmu",
.of_match_table = xgene_pmu_of_match,
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index f73abff416be..8d58efe998ec 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -82,6 +82,17 @@ config PHY_AIROHA_PCIE
This driver create the basic PHY instance and provides initialize
callback for PCIe GEN3 port.
+config PHY_NXP_PTN3222
+ tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
+ depends on I2C
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
+ This redriver performs translation between eUSB2 and USB2 signalling
+ schemes. It supports all three USB 2.0 data rates: Low Speed, Full
+ Speed and High Speed.
+
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index ebc399560da4..e281442acc75 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
+obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o
obj-y += allwinner/ \
amlogic/ \
broadcom/ \
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index b0f19e950601..cd159a71b23c 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -1049,11 +1049,11 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
static struct platform_driver sun4i_usb_phy_driver = {
- .probe = sun4i_usb_phy_probe,
- .remove_new = sun4i_usb_phy_remove,
+ .probe = sun4i_usb_phy_probe,
+ .remove = sun4i_usb_phy_remove,
.driver = {
- .of_match_table = sun4i_usb_phy_of_match,
- .name = "sun4i-usb-phy",
+ .of_match_table= sun4i_usb_phy_of_match,
+ .name = "sun4i-usb-phy",
}
};
module_platform_driver(sun4i_usb_phy_driver);
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
index 5213c75b6da6..c5d35031b398 100644
--- a/drivers/phy/broadcom/phy-bcm-ns-usb2.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
@@ -24,9 +24,6 @@ struct bcm_ns_usb2 {
struct phy *phy;
struct regmap *clkset;
void __iomem *base;
-
- /* Deprecated binding */
- void __iomem *dmu;
};
static int bcm_ns_usb2_phy_init(struct phy *phy)
@@ -49,10 +46,7 @@ static int bcm_ns_usb2_phy_init(struct phy *phy)
goto err_clk_off;
}
- if (usb2->base)
- usb2ctl = readl(usb2->base);
- else
- usb2ctl = readl(usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL);
+ usb2ctl = readl(usb2->base);
if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) {
usb_pll_pdiv = usb2ctl;
@@ -66,24 +60,16 @@ static int bcm_ns_usb2_phy_init(struct phy *phy)
usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
/* Unlock DMU PLL settings with some magic value */
- if (usb2->clkset)
- regmap_write(usb2->clkset, 0, 0x0000ea68);
- else
- writel(0x0000ea68, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY);
+ regmap_write(usb2->clkset, 0, 0x0000ea68);
/* Write USB 2.0 PLL control setting */
usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
- if (usb2->base)
- writel(usb2ctl, usb2->base);
- else
- writel(usb2ctl, usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL);
+
+ writel(usb2ctl, usb2->base);
/* Lock DMU PLL settings */
- if (usb2->clkset)
- regmap_write(usb2->clkset, 0, 0x00000000);
- else
- writel(0x00000000, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY);
+ regmap_write(usb2->clkset, 0, 0x00000000);
err_clk_off:
clk_disable_unprepare(usb2->ref_clk);
@@ -107,27 +93,17 @@ static int bcm_ns_usb2_probe(struct platform_device *pdev)
return -ENOMEM;
usb2->dev = dev;
- if (of_property_present(dev->of_node, "brcm,syscon-clkset")) {
- usb2->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(usb2->base)) {
- dev_err(dev, "Failed to map control reg\n");
- return PTR_ERR(usb2->base);
- }
-
- usb2->clkset = syscon_regmap_lookup_by_phandle(dev->of_node,
- "brcm,syscon-clkset");
- if (IS_ERR(usb2->clkset)) {
- dev_err(dev, "Failed to lookup clkset regmap\n");
- return PTR_ERR(usb2->clkset);
- }
- } else {
- usb2->dmu = devm_platform_ioremap_resource_byname(pdev, "dmu");
- if (IS_ERR(usb2->dmu)) {
- dev_err(dev, "Failed to map DMU regs\n");
- return PTR_ERR(usb2->dmu);
- }
+ usb2->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(usb2->base)) {
+ dev_err(dev, "Failed to map control reg\n");
+ return PTR_ERR(usb2->base);
+ }
- dev_warn(dev, "using deprecated DT binding\n");
+ usb2->clkset = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "brcm,syscon-clkset");
+ if (IS_ERR(usb2->clkset)) {
+ dev_err(dev, "Failed to lookup clkset regmap\n");
+ return PTR_ERR(usb2->clkset);
}
usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk");
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c
index 5ebb3a616115..da23078878a9 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.c
@@ -193,256 +193,251 @@ static const u32
usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
/* 3390B0 */
[BRCM_FAMILY_3390A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 4908 */
[BRCM_FAMILY_4908] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- 0, /* USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK */
- 0, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
},
/* 7250b0 */
[BRCM_FAMILY_7250B0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7271a0 */
[BRCM_FAMILY_7271A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
- USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
+ [USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR] =
+ USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+ [USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7364a0 */
[BRCM_FAMILY_7364A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7366c0 */
[BRCM_FAMILY_7366C0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 74371A0 */
[BRCM_FAMILY_74371A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
- USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB30_CTL1_USB3_IOC_SELECTOR] =
+ USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
+ [USB_CTRL_USB30_CTL1_USB3_IPP_SELECTOR] =
+ USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7439B0 */
[BRCM_FAMILY_7439B0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7445d0 */
[BRCM_FAMILY_7445D0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7260a0 */
[BRCM_FAMILY_7260A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
- USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
+ [USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR] =
+ USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+ [USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7278a0 */
[BRCM_FAMILY_7278A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- 0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
- 0, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
},
};
diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c
index ad2eec095601..6362ca5b7fb6 100644
--- a/drivers/phy/broadcom/phy-brcm-usb.c
+++ b/drivers/phy/broadcom/phy-brcm-usb.c
@@ -667,7 +667,7 @@ MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
static struct platform_driver brcm_usb_driver = {
.probe = brcm_usb_phy_probe,
- .remove_new = brcm_usb_phy_remove,
+ .remove = brcm_usb_phy_remove,
.driver = {
.name = "brcmstb-usb-phy",
.pm = &brcm_usb_phy_pm_ops,
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
index dddb66de6dba..ed87a3970f83 100644
--- a/drivers/phy/cadence/cdns-dphy.c
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -472,7 +472,7 @@ MODULE_DEVICE_TABLE(of, cdns_dphy_of_match);
static struct platform_driver cdns_dphy_platform_driver = {
.probe = cdns_dphy_probe,
- .remove_new = cdns_dphy_remove,
+ .remove = cdns_dphy_remove,
.driver = {
.name = "cdns-mipi-dphy",
.of_match_table = cdns_dphy_of_match,
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index dfc4f55d112e..45a5c00843bf 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -2731,7 +2731,7 @@ MODULE_DEVICE_TABLE(of, cdns_sierra_id_table);
static struct platform_driver cdns_sierra_driver = {
.probe = cdns_sierra_phy_probe,
- .remove_new = cdns_sierra_phy_remove,
+ .remove = cdns_sierra_phy_remove,
.driver = {
.name = "cdns-sierra-phy",
.of_match_table = cdns_sierra_id_table,
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c
index 8bbbbb87bb22..a281c0dfae97 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -5440,8 +5440,8 @@ MODULE_DEVICE_TABLE(of, cdns_torrent_phy_of_match);
static struct platform_driver cdns_torrent_phy_driver = {
.probe = cdns_torrent_phy_probe,
- .remove_new = cdns_torrent_phy_remove,
- .driver = {
+ .remove = cdns_torrent_phy_remove,
+ .driver = {
.name = "cdns-torrent-phy",
.of_match_table = cdns_torrent_phy_of_match,
.pm = pm_sleep_ptr(&cdns_torrent_phy_pm_ops),
diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
index 38388dd04bdc..7aef2f59e8eb 100644
--- a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
+++ b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
@@ -433,12 +433,12 @@ static const struct of_device_id mixel_lvds_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, mixel_lvds_phy_of_match);
static struct platform_driver mixel_lvds_phy_driver = {
- .probe = mixel_lvds_phy_probe,
- .remove_new = mixel_lvds_phy_remove,
+ .probe = mixel_lvds_phy_probe,
+ .remove = mixel_lvds_phy_remove,
.driver = {
.pm = &mixel_lvds_phy_pm_ops,
.name = "mixel-lvds-phy",
- .of_match_table = mixel_lvds_phy_of_match,
+ .of_match_table = mixel_lvds_phy_of_match,
}
};
module_platform_driver(mixel_lvds_phy_driver);
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c
index b86da8e9daa4..f7994e8983c8 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-28g.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c
@@ -631,9 +631,9 @@ static const struct of_device_id lynx_28g_of_match_table[] = {
MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table);
static struct platform_driver lynx_28g_driver = {
- .probe = lynx_28g_probe,
- .remove_new = lynx_28g_remove,
- .driver = {
+ .probe = lynx_28g_probe,
+ .remove = lynx_28g_remove,
+ .driver = {
.name = "lynx-28g",
.of_match_table = lynx_28g_of_match_table,
},
diff --git a/drivers/phy/freescale/phy-fsl-samsung-hdmi.c b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
index 9048cdc760c2..2c8038864357 100644
--- a/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
+++ b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
@@ -14,352 +14,265 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#define PHY_REG_00 0x00
-#define PHY_REG_01 0x04
-#define PHY_REG_02 0x08
-#define PHY_REG_08 0x20
-#define PHY_REG_09 0x24
-#define PHY_REG_10 0x28
-#define PHY_REG_11 0x2c
-
-#define PHY_REG_12 0x30
-#define REG12_CK_DIV_MASK GENMASK(5, 4)
-
-#define PHY_REG_13 0x34
-#define REG13_TG_CODE_LOW_MASK GENMASK(7, 0)
-
-#define PHY_REG_14 0x38
-#define REG14_TOL_MASK GENMASK(7, 4)
-#define REG14_RP_CODE_MASK GENMASK(3, 1)
-#define REG14_TG_CODE_HIGH_MASK GENMASK(0, 0)
-
-#define PHY_REG_15 0x3c
-#define PHY_REG_16 0x40
-#define PHY_REG_17 0x44
-#define PHY_REG_18 0x48
-#define PHY_REG_19 0x4c
-#define PHY_REG_20 0x50
-
-#define PHY_REG_21 0x54
-#define REG21_SEL_TX_CK_INV BIT(7)
-#define REG21_PMS_S_MASK GENMASK(3, 0)
-
-#define PHY_REG_22 0x58
-#define PHY_REG_23 0x5c
-#define PHY_REG_24 0x60
-#define PHY_REG_25 0x64
-#define PHY_REG_26 0x68
-#define PHY_REG_27 0x6c
-#define PHY_REG_28 0x70
-#define PHY_REG_29 0x74
-#define PHY_REG_30 0x78
-#define PHY_REG_31 0x7c
-#define PHY_REG_32 0x80
+#define PHY_REG(reg) (reg * 4)
+#define REG01_PMS_P_MASK GENMASK(3, 0)
+#define REG03_PMS_S_MASK GENMASK(7, 4)
+#define REG12_CK_DIV_MASK GENMASK(5, 4)
+
+#define REG13_TG_CODE_LOW_MASK GENMASK(7, 0)
+
+#define REG14_TOL_MASK GENMASK(7, 4)
+#define REG14_RP_CODE_MASK GENMASK(3, 1)
+#define REG14_TG_CODE_HIGH_MASK GENMASK(0, 0)
+
+#define REG21_SEL_TX_CK_INV BIT(7)
+#define REG21_PMS_S_MASK GENMASK(3, 0)
/*
* REG33 does not match the ref manual. According to Sandor Yu from NXP,
* "There is a doc issue on the i.MX8MP latest RM"
* REG33 is being used per guidance from Sandor
*/
+#define REG33_MODE_SET_DONE BIT(7)
+#define REG33_FIX_DA BIT(1)
+
+#define REG34_PHY_READY BIT(7)
+#define REG34_PLL_LOCK BIT(6)
+#define REG34_PHY_CLK_READY BIT(5)
-#define PHY_REG_33 0x84
-#define REG33_MODE_SET_DONE BIT(7)
-#define REG33_FIX_DA BIT(1)
-
-#define PHY_REG_34 0x88
-#define REG34_PHY_READY BIT(7)
-#define REG34_PLL_LOCK BIT(6)
-#define REG34_PHY_CLK_READY BIT(5)
-
-#define PHY_REG_35 0x8c
-#define PHY_REG_36 0x90
-#define PHY_REG_37 0x94
-#define PHY_REG_38 0x98
-#define PHY_REG_39 0x9c
-#define PHY_REG_40 0xa0
-#define PHY_REG_41 0xa4
-#define PHY_REG_42 0xa8
-#define PHY_REG_43 0xac
-#define PHY_REG_44 0xb0
-#define PHY_REG_45 0xb4
-#define PHY_REG_46 0xb8
-#define PHY_REG_47 0xbc
-
-#define PHY_PLL_DIV_REGS_NUM 6
+#ifndef MHZ
+#define MHZ (1000UL * 1000UL)
+#endif
+
+#define PHY_PLL_DIV_REGS_NUM 7
struct phy_config {
u32 pixclk;
u8 pll_div_regs[PHY_PLL_DIV_REGS_NUM];
};
+/*
+ * The calculated_phy_pll_cfg only handles integer divider for PMS,
+ * meaning the last four entries will be fixed, but the first three will
+ * be calculated by the PMS calculator.
+ */
+static struct phy_config calculated_phy_pll_cfg = {
+ .pixclk = 0,
+ .pll_div_regs = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+};
+
+/* The lookup table contains values for which the fractional divder is used */
static const struct phy_config phy_pll_cfg[] = {
{
.pixclk = 22250000,
- .pll_div_regs = { 0x4b, 0xf1, 0x89, 0x88, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4b, 0xf1, 0x89, 0x88, 0x80, 0x40 },
}, {
.pixclk = 23750000,
- .pll_div_regs = { 0x50, 0xf1, 0x86, 0x85, 0x80, 0x40 },
- }, {
- .pixclk = 24000000,
- .pll_div_regs = { 0x50, 0xf0, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x50, 0xf1, 0x86, 0x85, 0x80, 0x40 },
}, {
.pixclk = 24024000,
- .pll_div_regs = { 0x50, 0xf1, 0x99, 0x02, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x50, 0xf1, 0x99, 0x02, 0x80, 0x40 },
}, {
.pixclk = 25175000,
- .pll_div_regs = { 0x54, 0xfc, 0xcc, 0x91, 0x80, 0x40 },
- }, {
- .pixclk = 25200000,
- .pll_div_regs = { 0x54, 0xf0, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x54, 0xfc, 0xcc, 0x91, 0x80, 0x40 },
+ }, {
.pixclk = 26750000,
- .pll_div_regs = { 0x5a, 0xf2, 0x89, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 27000000,
- .pll_div_regs = { 0x5a, 0xf0, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0xf2, 0x89, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 27027000,
- .pll_div_regs = { 0x5a, 0xf2, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0xf2, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 29500000,
- .pll_div_regs = { 0x62, 0xf4, 0x95, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x62, 0xf4, 0x95, 0x08, 0x80, 0x40 },
}, {
.pixclk = 30750000,
- .pll_div_regs = { 0x66, 0xf4, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0xf4, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 30888000,
- .pll_div_regs = { 0x66, 0xf4, 0x99, 0x18, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0xf4, 0x99, 0x18, 0x88, 0x45 },
}, {
.pixclk = 33750000,
- .pll_div_regs = { 0x70, 0xf4, 0x82, 0x01, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0xf4, 0x82, 0x01, 0x80, 0x40 },
}, {
.pixclk = 35000000,
- .pll_div_regs = { 0x58, 0xb8, 0x8b, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 36000000,
- .pll_div_regs = { 0x5a, 0xb0, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x58, 0xb8, 0x8b, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 36036000,
- .pll_div_regs = { 0x5a, 0xb2, 0xfd, 0x0c, 0x80, 0x40 },
- }, {
- .pixclk = 40000000,
- .pll_div_regs = { 0x64, 0xb0, 0x00, 0x00, 0x80, 0x00 },
- }, {
- .pixclk = 43200000,
- .pll_div_regs = { 0x5a, 0x90, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x5a, 0xb2, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 43243200,
- .pll_div_regs = { 0x5a, 0x92, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x92, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 44500000,
- .pll_div_regs = { 0x5c, 0x92, 0x98, 0x11, 0x84, 0x41 },
+ .pll_div_regs = { 0xd1, 0x5c, 0x92, 0x98, 0x11, 0x84, 0x41 },
}, {
.pixclk = 47000000,
- .pll_div_regs = { 0x62, 0x94, 0x95, 0x82, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x62, 0x94, 0x95, 0x82, 0x80, 0x40 },
}, {
.pixclk = 47500000,
- .pll_div_regs = { 0x63, 0x96, 0xa1, 0x82, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x63, 0x96, 0xa1, 0x82, 0x80, 0x40 },
}, {
.pixclk = 50349650,
- .pll_div_regs = { 0x54, 0x7c, 0xc3, 0x8f, 0x80, 0x40 },
- }, {
- .pixclk = 50400000,
- .pll_div_regs = { 0x54, 0x70, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x54, 0x7c, 0xc3, 0x8f, 0x80, 0x40 },
}, {
.pixclk = 53250000,
- .pll_div_regs = { 0x58, 0x72, 0x84, 0x03, 0x82, 0x41 },
+ .pll_div_regs = { 0xd1, 0x58, 0x72, 0x84, 0x03, 0x82, 0x41 },
}, {
.pixclk = 53500000,
- .pll_div_regs = { 0x5a, 0x72, 0x89, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 54000000,
- .pll_div_regs = { 0x5a, 0x70, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0x72, 0x89, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 54054000,
- .pll_div_regs = { 0x5a, 0x72, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x72, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 59000000,
- .pll_div_regs = { 0x62, 0x74, 0x95, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x62, 0x74, 0x95, 0x08, 0x80, 0x40 },
}, {
.pixclk = 59340659,
- .pll_div_regs = { 0x62, 0x74, 0xdb, 0x52, 0x88, 0x47 },
- }, {
- .pixclk = 59400000,
- .pll_div_regs = { 0x63, 0x70, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x62, 0x74, 0xdb, 0x52, 0x88, 0x47 },
+ }, {
.pixclk = 61500000,
- .pll_div_regs = { 0x66, 0x74, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0x74, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 63500000,
- .pll_div_regs = { 0x69, 0x74, 0x89, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x69, 0x74, 0x89, 0x08, 0x80, 0x40 },
}, {
.pixclk = 67500000,
- .pll_div_regs = { 0x54, 0x52, 0x87, 0x03, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x54, 0x52, 0x87, 0x03, 0x80, 0x40 },
}, {
.pixclk = 70000000,
- .pll_div_regs = { 0x58, 0x58, 0x8b, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 72000000,
- .pll_div_regs = { 0x5a, 0x50, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x58, 0x58, 0x8b, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 72072000,
- .pll_div_regs = { 0x5a, 0x52, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x52, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 74176000,
- .pll_div_regs = { 0x5d, 0x58, 0xdb, 0xA2, 0x88, 0x41 },
+ .pll_div_regs = { 0xd1, 0x5d, 0x58, 0xdb, 0xA2, 0x88, 0x41 },
}, {
.pixclk = 74250000,
- .pll_div_regs = { 0x5c, 0x52, 0x90, 0x0d, 0x84, 0x41 },
+ .pll_div_regs = { 0xd1, 0x5c, 0x52, 0x90, 0x0d, 0x84, 0x41 },
}, {
.pixclk = 78500000,
- .pll_div_regs = { 0x62, 0x54, 0x87, 0x01, 0x80, 0x40 },
- }, {
- .pixclk = 80000000,
- .pll_div_regs = { 0x64, 0x50, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x62, 0x54, 0x87, 0x01, 0x80, 0x40 },
+ }, {
.pixclk = 82000000,
- .pll_div_regs = { 0x66, 0x54, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0x54, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 82500000,
- .pll_div_regs = { 0x67, 0x54, 0x88, 0x01, 0x90, 0x49 },
+ .pll_div_regs = { 0xd1, 0x67, 0x54, 0x88, 0x01, 0x90, 0x49 },
}, {
.pixclk = 89000000,
- .pll_div_regs = { 0x70, 0x54, 0x84, 0x83, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0x54, 0x84, 0x83, 0x80, 0x40 },
}, {
.pixclk = 90000000,
- .pll_div_regs = { 0x70, 0x54, 0x82, 0x01, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0x54, 0x82, 0x01, 0x80, 0x40 },
}, {
.pixclk = 94000000,
- .pll_div_regs = { 0x4e, 0x32, 0xa7, 0x10, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4e, 0x32, 0xa7, 0x10, 0x80, 0x40 },
}, {
.pixclk = 95000000,
- .pll_div_regs = { 0x50, 0x31, 0x86, 0x85, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x50, 0x31, 0x86, 0x85, 0x80, 0x40 },
}, {
.pixclk = 98901099,
- .pll_div_regs = { 0x52, 0x3a, 0xdb, 0x4c, 0x88, 0x47 },
+ .pll_div_regs = { 0xd1, 0x52, 0x3a, 0xdb, 0x4c, 0x88, 0x47 },
}, {
.pixclk = 99000000,
- .pll_div_regs = { 0x52, 0x32, 0x82, 0x01, 0x88, 0x47 },
+ .pll_div_regs = { 0xd1, 0x52, 0x32, 0x82, 0x01, 0x88, 0x47 },
}, {
.pixclk = 100699300,
- .pll_div_regs = { 0x54, 0x3c, 0xc3, 0x8f, 0x80, 0x40 },
- }, {
- .pixclk = 100800000,
- .pll_div_regs = { 0x54, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x54, 0x3c, 0xc3, 0x8f, 0x80, 0x40 },
+ }, {
.pixclk = 102500000,
- .pll_div_regs = { 0x55, 0x32, 0x8c, 0x05, 0x90, 0x4b },
+ .pll_div_regs = { 0xd1, 0x55, 0x32, 0x8c, 0x05, 0x90, 0x4b },
}, {
.pixclk = 104750000,
- .pll_div_regs = { 0x57, 0x32, 0x98, 0x07, 0x90, 0x49 },
+ .pll_div_regs = { 0xd1, 0x57, 0x32, 0x98, 0x07, 0x90, 0x49 },
}, {
.pixclk = 106500000,
- .pll_div_regs = { 0x58, 0x32, 0x84, 0x03, 0x82, 0x41 },
+ .pll_div_regs = { 0xd1, 0x58, 0x32, 0x84, 0x03, 0x82, 0x41 },
}, {
.pixclk = 107000000,
- .pll_div_regs = { 0x5a, 0x32, 0x89, 0x88, 0x80, 0x40 },
- }, {
- .pixclk = 108000000,
- .pll_div_regs = { 0x5a, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0x32, 0x89, 0x88, 0x80, 0x40 },
+ }, {
.pixclk = 108108000,
- .pll_div_regs = { 0x5a, 0x32, 0xfd, 0x0c, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x5a, 0x32, 0xfd, 0x0c, 0x80, 0x40 },
}, {
.pixclk = 118000000,
- .pll_div_regs = { 0x62, 0x34, 0x95, 0x08, 0x80, 0x40 },
- }, {
- .pixclk = 118800000,
- .pll_div_regs = { 0x63, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x62, 0x34, 0x95, 0x08, 0x80, 0x40 },
+ }, {
.pixclk = 123000000,
- .pll_div_regs = { 0x66, 0x34, 0x82, 0x01, 0x88, 0x45 },
+ .pll_div_regs = { 0xd1, 0x66, 0x34, 0x82, 0x01, 0x88, 0x45 },
}, {
.pixclk = 127000000,
- .pll_div_regs = { 0x69, 0x34, 0x89, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x69, 0x34, 0x89, 0x08, 0x80, 0x40 },
}, {
.pixclk = 135000000,
- .pll_div_regs = { 0x70, 0x34, 0x82, 0x01, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x70, 0x34, 0x82, 0x01, 0x80, 0x40 },
}, {
.pixclk = 135580000,
- .pll_div_regs = { 0x71, 0x39, 0xe9, 0x82, 0x9c, 0x5b },
+ .pll_div_regs = { 0xd1, 0x71, 0x39, 0xe9, 0x82, 0x9c, 0x5b },
}, {
.pixclk = 137520000,
- .pll_div_regs = { 0x72, 0x38, 0x99, 0x10, 0x85, 0x41 },
+ .pll_div_regs = { 0xd1, 0x72, 0x38, 0x99, 0x10, 0x85, 0x41 },
}, {
.pixclk = 138750000,
- .pll_div_regs = { 0x73, 0x35, 0x88, 0x05, 0x90, 0x4d },
+ .pll_div_regs = { 0xd1, 0x73, 0x35, 0x88, 0x05, 0x90, 0x4d },
}, {
.pixclk = 140000000,
- .pll_div_regs = { 0x75, 0x36, 0xa7, 0x90, 0x80, 0x40 },
- }, {
- .pixclk = 144000000,
- .pll_div_regs = { 0x78, 0x30, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x75, 0x36, 0xa7, 0x90, 0x80, 0x40 },
+ }, {
.pixclk = 148352000,
- .pll_div_regs = { 0x7b, 0x35, 0xdb, 0x39, 0x90, 0x45 },
+ .pll_div_regs = { 0xd1, 0x7b, 0x35, 0xdb, 0x39, 0x90, 0x45 },
}, {
.pixclk = 148500000,
- .pll_div_regs = { 0x7b, 0x35, 0x84, 0x03, 0x90, 0x45 },
+ .pll_div_regs = { 0xd1, 0x7b, 0x35, 0x84, 0x03, 0x90, 0x45 },
}, {
.pixclk = 154000000,
- .pll_div_regs = { 0x40, 0x18, 0x83, 0x01, 0x00, 0x40 },
+ .pll_div_regs = { 0xd1, 0x40, 0x18, 0x83, 0x01, 0x00, 0x40 },
}, {
.pixclk = 157000000,
- .pll_div_regs = { 0x41, 0x11, 0xa7, 0x14, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x41, 0x11, 0xa7, 0x14, 0x80, 0x40 },
}, {
.pixclk = 160000000,
- .pll_div_regs = { 0x42, 0x12, 0xa1, 0x20, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x42, 0x12, 0xa1, 0x20, 0x80, 0x40 },
}, {
.pixclk = 162000000,
- .pll_div_regs = { 0x43, 0x18, 0x8b, 0x08, 0x96, 0x55 },
+ .pll_div_regs = { 0xd1, 0x43, 0x18, 0x8b, 0x08, 0x96, 0x55 },
}, {
.pixclk = 164000000,
- .pll_div_regs = { 0x45, 0x11, 0x83, 0x82, 0x90, 0x4b },
+ .pll_div_regs = { 0xd1, 0x45, 0x11, 0x83, 0x82, 0x90, 0x4b },
}, {
.pixclk = 165000000,
- .pll_div_regs = { 0x45, 0x11, 0x84, 0x81, 0x90, 0x4b },
- }, {
- .pixclk = 180000000,
- .pll_div_regs = { 0x4b, 0x10, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x45, 0x11, 0x84, 0x81, 0x90, 0x4b },
}, {
.pixclk = 185625000,
- .pll_div_regs = { 0x4e, 0x12, 0x9a, 0x95, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4e, 0x12, 0x9a, 0x95, 0x80, 0x40 },
}, {
.pixclk = 188000000,
- .pll_div_regs = { 0x4e, 0x12, 0xa7, 0x10, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x4e, 0x12, 0xa7, 0x10, 0x80, 0x40 },
}, {
.pixclk = 198000000,
- .pll_div_regs = { 0x52, 0x12, 0x82, 0x01, 0x88, 0x47 },
+ .pll_div_regs = { 0xd1, 0x52, 0x12, 0x82, 0x01, 0x88, 0x47 },
}, {
.pixclk = 205000000,
- .pll_div_regs = { 0x55, 0x12, 0x8c, 0x05, 0x90, 0x4b },
+ .pll_div_regs = { 0xd1, 0x55, 0x12, 0x8c, 0x05, 0x90, 0x4b },
}, {
.pixclk = 209500000,
- .pll_div_regs = { 0x57, 0x12, 0x98, 0x07, 0x90, 0x49 },
+ .pll_div_regs = { 0xd1, 0x57, 0x12, 0x98, 0x07, 0x90, 0x49 },
}, {
.pixclk = 213000000,
- .pll_div_regs = { 0x58, 0x12, 0x84, 0x03, 0x82, 0x41 },
- }, {
- .pixclk = 216000000,
- .pll_div_regs = { 0x5a, 0x10, 0x00, 0x00, 0x80, 0x00 },
+ .pll_div_regs = { 0xd1, 0x58, 0x12, 0x84, 0x03, 0x82, 0x41 },
}, {
.pixclk = 216216000,
- .pll_div_regs = { 0x5a, 0x12, 0xfd, 0x0c, 0x80, 0x40 },
- }, {
- .pixclk = 237600000,
- .pll_div_regs = { 0x63, 0x10, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x5a, 0x12, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
.pixclk = 254000000,
- .pll_div_regs = { 0x69, 0x14, 0x89, 0x08, 0x80, 0x40 },
+ .pll_div_regs = { 0xd1, 0x69, 0x14, 0x89, 0x08, 0x80, 0x40 },
}, {
.pixclk = 277500000,
- .pll_div_regs = { 0x73, 0x15, 0x88, 0x05, 0x90, 0x4d },
- }, {
- .pixclk = 288000000,
- .pll_div_regs = { 0x78, 0x10, 0x00, 0x00, 0x80, 0x00 },
- }, {
+ .pll_div_regs = { 0xd1, 0x73, 0x15, 0x88, 0x05, 0x90, 0x4d },
+ }, {
.pixclk = 297000000,
- .pll_div_regs = { 0x7b, 0x15, 0x84, 0x03, 0x90, 0x45 },
+ .pll_div_regs = { 0xd1, 0x7b, 0x15, 0x84, 0x03, 0x90, 0x45 },
},
};
@@ -369,29 +282,30 @@ struct reg_settings {
};
static const struct reg_settings common_phy_cfg[] = {
- { PHY_REG_00, 0x00 }, { PHY_REG_01, 0xd1 },
- { PHY_REG_08, 0x4f }, { PHY_REG_09, 0x30 },
- { PHY_REG_10, 0x33 }, { PHY_REG_11, 0x65 },
+ { PHY_REG(0), 0x00 },
+ /* PHY_REG(1-7) pix clk specific */
+ { PHY_REG(8), 0x4f }, { PHY_REG(9), 0x30 },
+ { PHY_REG(10), 0x33 }, { PHY_REG(11), 0x65 },
/* REG12 pixclk specific */
/* REG13 pixclk specific */
/* REG14 pixclk specific */
- { PHY_REG_15, 0x80 }, { PHY_REG_16, 0x6c },
- { PHY_REG_17, 0xf2 }, { PHY_REG_18, 0x67 },
- { PHY_REG_19, 0x00 }, { PHY_REG_20, 0x10 },
+ { PHY_REG(15), 0x80 }, { PHY_REG(16), 0x6c },
+ { PHY_REG(17), 0xf2 }, { PHY_REG(18), 0x67 },
+ { PHY_REG(19), 0x00 }, { PHY_REG(20), 0x10 },
/* REG21 pixclk specific */
- { PHY_REG_22, 0x30 }, { PHY_REG_23, 0x32 },
- { PHY_REG_24, 0x60 }, { PHY_REG_25, 0x8f },
- { PHY_REG_26, 0x00 }, { PHY_REG_27, 0x00 },
- { PHY_REG_28, 0x08 }, { PHY_REG_29, 0x00 },
- { PHY_REG_30, 0x00 }, { PHY_REG_31, 0x00 },
- { PHY_REG_32, 0x00 }, { PHY_REG_33, 0x80 },
- { PHY_REG_34, 0x00 }, { PHY_REG_35, 0x00 },
- { PHY_REG_36, 0x00 }, { PHY_REG_37, 0x00 },
- { PHY_REG_38, 0x00 }, { PHY_REG_39, 0x00 },
- { PHY_REG_40, 0x00 }, { PHY_REG_41, 0xe0 },
- { PHY_REG_42, 0x83 }, { PHY_REG_43, 0x0f },
- { PHY_REG_44, 0x3E }, { PHY_REG_45, 0xf8 },
- { PHY_REG_46, 0x00 }, { PHY_REG_47, 0x00 }
+ { PHY_REG(22), 0x30 }, { PHY_REG(23), 0x32 },
+ { PHY_REG(24), 0x60 }, { PHY_REG(25), 0x8f },
+ { PHY_REG(26), 0x00 }, { PHY_REG(27), 0x00 },
+ { PHY_REG(28), 0x08 }, { PHY_REG(29), 0x00 },
+ { PHY_REG(30), 0x00 }, { PHY_REG(31), 0x00 },
+ { PHY_REG(32), 0x00 }, { PHY_REG(33), 0x80 },
+ { PHY_REG(34), 0x00 }, { PHY_REG(35), 0x00 },
+ { PHY_REG(36), 0x00 }, { PHY_REG(37), 0x00 },
+ { PHY_REG(38), 0x00 }, { PHY_REG(39), 0x00 },
+ { PHY_REG(40), 0x00 }, { PHY_REG(41), 0xe0 },
+ { PHY_REG(42), 0x83 }, { PHY_REG(43), 0x0f },
+ { PHY_REG(44), 0x3E }, { PHY_REG(45), 0xf8 },
+ { PHY_REG(46), 0x00 }, { PHY_REG(47), 0x00 }
};
struct fsl_samsung_hdmi_phy {
@@ -412,40 +326,6 @@ to_fsl_samsung_hdmi_phy(struct clk_hw *hw)
}
static void
-fsl_samsung_hdmi_phy_configure_pixclk(struct fsl_samsung_hdmi_phy *phy,
- const struct phy_config *cfg)
-{
- u8 div = 0x1;
-
- switch (cfg->pixclk) {
- case 22250000 ... 33750000:
- div = 0xf;
- break;
- case 35000000 ... 40000000:
- div = 0xb;
- break;
- case 43200000 ... 47500000:
- div = 0x9;
- break;
- case 50349650 ... 63500000:
- div = 0x7;
- break;
- case 67500000 ... 90000000:
- div = 0x5;
- break;
- case 94000000 ... 148500000:
- div = 0x3;
- break;
- case 154000000 ... 297000000:
- div = 0x1;
- break;
- }
-
- writeb(REG21_SEL_TX_CK_INV | FIELD_PREP(REG21_PMS_S_MASK, div),
- phy->regs + PHY_REG_21);
-}
-
-static void
fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
const struct phy_config *cfg)
{
@@ -469,7 +349,7 @@ fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
break;
}
- writeb(FIELD_PREP(REG12_CK_DIV_MASK, ilog2(div)), phy->regs + PHY_REG_12);
+ writeb(FIELD_PREP(REG12_CK_DIV_MASK, ilog2(div)), phy->regs + PHY_REG(12));
/*
* Calculation for the frequency lock detector target code (fld_tg_code)
@@ -489,11 +369,88 @@ fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
/* FLD_TOL and FLD_RP_CODE taken from downstream driver */
writeb(FIELD_PREP(REG13_TG_CODE_LOW_MASK, fld_tg_code),
- phy->regs + PHY_REG_13);
+ phy->regs + PHY_REG(13));
writeb(FIELD_PREP(REG14_TOL_MASK, 2) |
FIELD_PREP(REG14_RP_CODE_MASK, 2) |
FIELD_PREP(REG14_TG_CODE_HIGH_MASK, fld_tg_code >> 8),
- phy->regs + PHY_REG_14);
+ phy->regs + PHY_REG(14));
+}
+
+static unsigned long fsl_samsung_hdmi_phy_find_pms(unsigned long fout, u8 *p, u16 *m, u8 *s)
+{
+ unsigned long best_freq = 0;
+ u32 min_delta = 0xffffffff;
+ u8 _p, best_p;
+ u16 _m, best_m;
+ u8 _s, best_s;
+
+ /*
+ * Figure 13-78 of the reference manual states the PLL should be TMDS x 5
+ * while the TMDS_CLKO should be the PLL / 5. So to calculate the PLL,
+ * take the pix clock x 5, then return the value of the PLL / 5.
+ */
+ fout *= 5;
+
+ /* The ref manual states the values of 'P' range from 1 to 11 */
+ for (_p = 1; _p <= 11; ++_p) {
+ for (_s = 1; _s <= 16; ++_s) {
+ u64 tmp;
+ u32 delta;
+
+ /* s must be one or even */
+ if (_s > 1 && (_s & 0x01) == 1)
+ _s++;
+
+ /* _s cannot be 14 per the TRM */
+ if (_s == 14)
+ continue;
+
+ /*
+ * TODO: Ref Manual doesn't state the range of _m
+ * so this should be further refined if possible.
+ * This range was set based on the original values
+ * in the lookup table
+ */
+ tmp = (u64)fout * (_p * _s);
+ do_div(tmp, 24 * MHZ);
+ _m = tmp;
+ if (_m < 0x30 || _m > 0x7b)
+ continue;
+
+ /*
+ * Rev 2 of the Ref Manual states the
+ * VCO can range between 750MHz and
+ * 3GHz. The VCO is assumed to be
+ * Fvco = (M * f_ref) / P,
+ * where f_ref is 24MHz.
+ */
+ tmp = (u64)_m * 24 * MHZ;
+ do_div(tmp, _p);
+ if (tmp < 750 * MHZ ||
+ tmp > 3000 * MHZ)
+ continue;
+
+ /* Final frequency after post-divider */
+ do_div(tmp, _s);
+
+ delta = abs(fout - tmp);
+ if (delta < min_delta) {
+ best_p = _p;
+ best_s = _s;
+ best_m = _m;
+ min_delta = delta;
+ best_freq = tmp;
+ }
+ }
+ }
+
+ if (best_freq) {
+ *p = best_p;
+ *m = best_m;
+ *s = best_s;
+ }
+
+ return best_freq / 5;
}
static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
@@ -503,22 +460,25 @@ static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
u8 val;
/* HDMI PHY init */
- writeb(REG33_FIX_DA, phy->regs + PHY_REG_33);
+ writeb(REG33_FIX_DA, phy->regs + PHY_REG(33));
/* common PHY registers */
for (i = 0; i < ARRAY_SIZE(common_phy_cfg); i++)
writeb(common_phy_cfg[i].val, phy->regs + common_phy_cfg[i].reg);
- /* set individual PLL registers PHY_REG2 ... PHY_REG7 */
+ /* set individual PLL registers PHY_REG1 ... PHY_REG7 */
for (i = 0; i < PHY_PLL_DIV_REGS_NUM; i++)
- writeb(cfg->pll_div_regs[i], phy->regs + PHY_REG_02 + i * 4);
+ writeb(cfg->pll_div_regs[i], phy->regs + PHY_REG(1) + i * 4);
+
+ /* High nibble of PHY_REG3 and low nibble of PHY_REG21 both contain 'S' */
+ writeb(REG21_SEL_TX_CK_INV | FIELD_PREP(REG21_PMS_S_MASK,
+ cfg->pll_div_regs[2] >> 4), phy->regs + PHY_REG(21));
- fsl_samsung_hdmi_phy_configure_pixclk(phy, cfg);
fsl_samsung_hdmi_phy_configure_pll_lock_det(phy, cfg);
- writeb(REG33_FIX_DA | REG33_MODE_SET_DONE, phy->regs + PHY_REG_33);
+ writeb(REG33_FIX_DA | REG33_MODE_SET_DONE, phy->regs + PHY_REG(33));
- ret = readb_poll_timeout(phy->regs + PHY_REG_34, val,
+ ret = readb_poll_timeout(phy->regs + PHY_REG(34), val,
val & REG34_PLL_LOCK, 50, 20000);
if (ret)
dev_err(phy->dev, "PLL failed to lock\n");
@@ -537,34 +497,120 @@ static unsigned long phy_clk_recalc_rate(struct clk_hw *hw,
return phy->cur_cfg->pixclk;
}
-static long phy_clk_round_rate(struct clk_hw *hw,
- unsigned long rate, unsigned long *parent_rate)
+/* Helper function to lookup the available fractional-divider rate */
+static const struct phy_config *fsl_samsung_hdmi_phy_lookup_rate(unsigned long rate)
{
int i;
+ /* Search the lookup table */
for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--)
if (phy_pll_cfg[i].pixclk <= rate)
- return phy_pll_cfg[i].pixclk;
+ break;
- return -EINVAL;
+ return &phy_pll_cfg[i];
+}
+
+static void fsl_samsung_hdmi_calculate_phy(struct phy_config *cal_phy, unsigned long rate,
+ u8 p, u16 m, u8 s)
+{
+ cal_phy->pixclk = rate;
+ cal_phy->pll_div_regs[0] = FIELD_PREP(REG01_PMS_P_MASK, p);
+ cal_phy->pll_div_regs[1] = m;
+ cal_phy->pll_div_regs[2] = FIELD_PREP(REG03_PMS_S_MASK, s-1);
+ /* pll_div_regs 3-6 are fixed and pre-defined already */
+}
+
+static u32 fsl_samsung_hdmi_phy_get_closest_rate(unsigned long rate,
+ u32 int_div_clk, u32 frac_div_clk)
+{
+ /* Calculate the absolute value of the differences and return whichever is closest */
+ if (abs((long)rate - (long)int_div_clk) < abs((long)(rate - (long)frac_div_clk)))
+ return int_div_clk;
+
+ return frac_div_clk;
+}
+
+static long phy_clk_round_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate)
+{
+ const struct phy_config *fract_div_phy;
+ u32 int_div_clk;
+ u16 m;
+ u8 p, s;
+
+ /* If the clock is out of range return error instead of searching */
+ if (rate > 297000000 || rate < 22250000)
+ return -EINVAL;
+
+ /* Search the fractional divider lookup table */
+ fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
+
+ /* If the rate is an exact match, return that value */
+ if (rate == fract_div_phy->pixclk)
+ return fract_div_phy->pixclk;
+
+ /* If the exact match isn't found, calculate the integer divider */
+ int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
+
+ /* If the int_div_clk rate is an exact match, return that value */
+ if (int_div_clk == rate)
+ return int_div_clk;
+
+ /* If neither rate is an exact match, use the value from the LUT */
+ return fract_div_phy->pixclk;
+}
+
+static int phy_use_fract_div(struct fsl_samsung_hdmi_phy *phy, const struct phy_config *fract_div_phy)
+{
+ phy->cur_cfg = fract_div_phy;
+ dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: using fractional divider rate = %u\n",
+ phy->cur_cfg->pixclk);
+ return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
+}
+
+static int phy_use_integer_div(struct fsl_samsung_hdmi_phy *phy,
+ const struct phy_config *int_div_clk)
+{
+ phy->cur_cfg = &calculated_phy_pll_cfg;
+ dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: integer divider rate = %u\n",
+ phy->cur_cfg->pixclk);
+ return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
}
static int phy_clk_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
- int i;
+ const struct phy_config *fract_div_phy;
+ u32 int_div_clk;
+ u16 m;
+ u8 p, s;
- for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--)
- if (phy_pll_cfg[i].pixclk <= rate)
- break;
+ /* Search the fractional divider lookup table */
+ fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
- if (i < 0)
- return -EINVAL;
+ /* If the rate is an exact match, use that value */
+ if (fract_div_phy->pixclk == rate)
+ return phy_use_fract_div(phy, fract_div_phy);
- phy->cur_cfg = &phy_pll_cfg[i];
+ /*
+ * If the rate from the fractional divider is not exact, check the integer divider,
+ * and use it if that value is an exact match.
+ */
+ int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
+ fsl_samsung_hdmi_calculate_phy(&calculated_phy_pll_cfg, int_div_clk, p, m, s);
+ if (int_div_clk == rate)
+ return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
- return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
+ /*
+ * Compare the difference between the integer clock and the fractional clock against
+ * the desired clock and which whichever is closest.
+ */
+ if (fsl_samsung_hdmi_phy_get_closest_rate(rate, int_div_clk,
+ fract_div_phy->pixclk) == fract_div_phy->pixclk)
+ return phy_use_fract_div(phy, fract_div_phy);
+ else
+ return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
}
static const struct clk_ops phy_clk_ops = {
@@ -703,8 +749,8 @@ static const struct of_device_id fsl_samsung_hdmi_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, fsl_samsung_hdmi_phy_of_match);
static struct platform_driver fsl_samsung_hdmi_phy_driver = {
- .probe = fsl_samsung_hdmi_phy_probe,
- .remove_new = fsl_samsung_hdmi_phy_remove,
+ .probe = fsl_samsung_hdmi_phy_probe,
+ .remove = fsl_samsung_hdmi_phy_remove,
.driver = {
.name = "fsl-samsung-hdmi-phy",
.of_match_table = fsl_samsung_hdmi_phy_of_match,
diff --git a/drivers/phy/intel/phy-intel-lgm-combo.c b/drivers/phy/intel/phy-intel-lgm-combo.c
index f8e3054a9e59..9ee3cf61cdd0 100644
--- a/drivers/phy/intel/phy-intel-lgm-combo.c
+++ b/drivers/phy/intel/phy-intel-lgm-combo.c
@@ -605,7 +605,7 @@ static const struct of_device_id of_intel_cbphy_match[] = {
static struct platform_driver intel_cbphy_driver = {
.probe = intel_cbphy_probe,
- .remove_new = intel_cbphy_remove,
+ .remove = intel_cbphy_remove,
.driver = {
.name = "intel-combo-phy",
.of_match_table = of_intel_cbphy_match,
diff --git a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
index 4922a5f3327d..59903f86b13f 100644
--- a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
+++ b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
@@ -62,6 +62,8 @@
#define SQ_AMP_CAL_MASK GENMASK(2, 0)
#define SQ_AMP_CAL_VAL 1
#define SQ_AMP_CAL_EN BIT(3)
+#define UTMI_DIG_CTRL1_REG 0x20
+#define SWAP_DPDM BIT(15)
#define UTMI_CTRL_STATUS0_REG 0x24
#define SUSPENDM BIT(22)
#define TEST_SEL BIT(25)
@@ -99,11 +101,13 @@ struct mvebu_cp110_utmi {
* @priv: PHY driver data
* @id: PHY port ID
* @dr_mode: PHY connection: USB_DR_MODE_HOST or USB_DR_MODE_PERIPHERAL
+ * @swap_dx: whether to swap d+/d- signals
*/
struct mvebu_cp110_utmi_port {
struct mvebu_cp110_utmi *priv;
u32 id;
enum usb_dr_mode dr_mode;
+ bool swap_dx;
};
static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
@@ -159,6 +163,13 @@ static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
reg &= ~(VDAT_MASK | VSRC_MASK);
reg |= (VDAT_VAL << VDAT_OFFSET) | (VSRC_VAL << VSRC_OFFSET);
writel(reg, PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG);
+
+ /* Swap D+/D- */
+ reg = readl(PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
+ reg &= ~(SWAP_DPDM);
+ if (port->swap_dx)
+ reg |= SWAP_DPDM;
+ writel(reg, PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
}
static int mvebu_cp110_utmi_phy_power_off(struct phy *phy)
@@ -286,6 +297,7 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
struct phy_provider *provider;
struct device_node *child;
u32 usb_devices = 0;
+ u32 swap_dx = 0;
utmi = devm_kzalloc(dev, sizeof(*utmi), GFP_KERNEL);
if (!utmi)
@@ -345,6 +357,10 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
}
}
+ of_property_for_each_u32(dev->of_node, "swap-dx-lanes", swap_dx)
+ if (swap_dx == port_id)
+ port->swap_dx = 1;
+
/* Retrieve PHY capabilities */
utmi->ops = &mvebu_cp110_utmi_phy_ops;
diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c
index 7cb85029fab3..320cf5b50a8c 100644
--- a/drivers/phy/microchip/sparx5_serdes.c
+++ b/drivers/phy/microchip/sparx5_serdes.c
@@ -21,23 +21,33 @@
#include "sparx5_serdes.h"
-#define SPX5_CMU_MAX 14
-
#define SPX5_SERDES_10G_START 13
#define SPX5_SERDES_25G_START 25
#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START
+#define LAN969X_SERDES_10G_CNT 10
+
/* Optimal power settings from GUC */
#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c
-enum sparx5_10g28cmu_mode {
- SPX5_SD10G28_CMU_MAIN = 0,
- SPX5_SD10G28_CMU_AUX1 = 1,
- SPX5_SD10G28_CMU_AUX2 = 3,
- SPX5_SD10G28_CMU_NONE = 4,
- SPX5_SD10G28_CMU_MAX,
+/* Register target sizes */
+const unsigned int sparx5_serdes_tsize[TSIZE_LAST] = {
+ [TC_SD10G_LANE] = 12,
+ [TC_SD_CMU] = 14,
+ [TC_SD_CMU_CFG] = 14,
+ [TC_SD_LANE] = 25,
+};
+
+const unsigned int lan969x_serdes_tsize[TSIZE_LAST] = {
+ [TC_SD10G_LANE] = 10,
+ [TC_SD_CMU] = 6,
+ [TC_SD_CMU_CFG] = 6,
+ [TC_SD_LANE] = 10,
};
+/* Pointer to the register target size table */
+const unsigned int *tsize;
+
enum sparx5_sd25g28_mode_preset_type {
SPX5_SD25G28_MODE_PRESET_25000,
SPX5_SD25G28_MODE_PRESET_10000,
@@ -1095,13 +1105,31 @@ static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
return sparx5_serdes_cmu_map[mode][sd_index];
}
+/* Map of 6G/10G serdes mode and index to CMU index. */
+static const int
+lan969x_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][LAN969X_SERDES_10G_CNT] = {
+ [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2,
+ 2, 2, 2, 5, 5 },
+ [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3,
+ 3, 3, 3, 3, 3 },
+ [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4 },
+ [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4 },
+};
+
+static int lan969x_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
+{
+ return lan969x_serdes_cmu_map[mode][sd_index];
+}
+
static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv)
{
void __iomem *cmu_inst, *cmu_cfg_inst;
int i;
/* Power down each CMU */
- for (i = 0; i < SPX5_CMU_MAX; i++) {
+ for (i = 0; i < priv->data->consts.cmu_max; i++) {
cmu_inst = sdx5_inst_get(priv, TARGET_SD_CMU, i);
cmu_cfg_inst = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, i);
@@ -1650,7 +1678,7 @@ static int sparx5_sd10g28_apply_params(struct sparx5_serdes_macro *macro,
if (params->skip_cmu_cfg)
return 0;
- cmu_idx = sparx5_serdes_cmu_get(params->cmu_sel, lane_index);
+ cmu_idx = priv->data->ops.serdes_cmu_get(params->cmu_sel, macro->sidx);
err = sparx5_cmu_cfg(priv, cmu_idx);
if (err)
return err;
@@ -2183,6 +2211,10 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro)
{
struct sparx5_serdes_private *priv = macro->priv;
+ /* Clock is auto-detected in 100Base-FX mode on lan969x */
+ if (priv->data->type == SPX5_TARGET_LAN969X)
+ return 0;
+
if (macro->serdesmode == SPX5_SD_MODE_100FX) {
u32 freq = priv->coreclock == 250000000 ? 2 :
priv->coreclock == 500000000 ? 1 : 0;
@@ -2297,10 +2329,12 @@ static int sparx5_serdes_set_speed(struct phy *phy, int speed)
{
struct sparx5_serdes_macro *macro = phy_get_drvdata(phy);
- if (macro->sidx < SPX5_SERDES_10G_START && speed > SPEED_5000)
- return -EINVAL;
- if (macro->sidx < SPX5_SERDES_25G_START && speed > SPEED_10000)
- return -EINVAL;
+ if (macro->priv->data->type == SPX5_TARGET_SPARX5) {
+ if (macro->sidx < SPX5_SERDES_10G_START && speed > SPEED_5000)
+ return -EINVAL;
+ if (macro->sidx < SPX5_SERDES_25G_START && speed > SPEED_10000)
+ return -EINVAL;
+ }
if (speed != macro->speed) {
macro->speed = speed;
if (macro->serdesmode != SPX5_SD_MODE_NONE)
@@ -2337,11 +2371,14 @@ static int sparx5_serdes_validate(struct phy *phy, enum phy_mode mode,
if (macro->speed == 0)
return -EINVAL;
- if (macro->sidx < SPX5_SERDES_10G_START && macro->speed > SPEED_5000)
- return -EINVAL;
- if (macro->sidx < SPX5_SERDES_25G_START && macro->speed > SPEED_10000)
- return -EINVAL;
-
+ if (macro->priv->data->type == SPX5_TARGET_SPARX5) {
+ if (macro->sidx < SPX5_SERDES_10G_START &&
+ macro->speed > SPEED_5000)
+ return -EINVAL;
+ if (macro->sidx < SPX5_SERDES_25G_START &&
+ macro->speed > SPEED_10000)
+ return -EINVAL;
+ }
switch (submode) {
case PHY_INTERFACE_MODE_1000BASEX:
if (macro->speed != SPEED_100 && /* This is for 100BASE-FX */
@@ -2375,6 +2412,26 @@ static const struct phy_ops sparx5_serdes_ops = {
.owner = THIS_MODULE,
};
+static void sparx5_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
+{
+ if (sidx < SPX5_SERDES_10G_START) {
+ macro->serdestype = SPX5_SDT_6G;
+ macro->stpidx = macro->sidx;
+ } else if (sidx < SPX5_SERDES_25G_START) {
+ macro->serdestype = SPX5_SDT_10G;
+ macro->stpidx = macro->sidx - SPX5_SERDES_10G_START;
+ } else {
+ macro->serdestype = SPX5_SDT_25G;
+ macro->stpidx = macro->sidx - SPX5_SERDES_25G_START;
+ }
+}
+
+static void lan969x_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
+{
+ macro->serdestype = SPX5_SDT_10G;
+ macro->stpidx = macro->sidx;
+}
+
static int sparx5_phy_create(struct sparx5_serdes_private *priv,
int idx, struct phy **phy)
{
@@ -2391,16 +2448,8 @@ static int sparx5_phy_create(struct sparx5_serdes_private *priv,
macro->sidx = idx;
macro->priv = priv;
macro->speed = SPEED_UNKNOWN;
- if (idx < SPX5_SERDES_10G_START) {
- macro->serdestype = SPX5_SDT_6G;
- macro->stpidx = macro->sidx;
- } else if (idx < SPX5_SERDES_25G_START) {
- macro->serdestype = SPX5_SDT_10G;
- macro->stpidx = macro->sidx - SPX5_SERDES_10G_START;
- } else {
- macro->serdestype = SPX5_SDT_25G;
- macro->stpidx = macro->sidx - SPX5_SERDES_25G_START;
- }
+
+ priv->data->ops.serdes_type_set(macro, idx);
phy_set_drvdata(*phy, macro);
@@ -2507,6 +2556,71 @@ static struct sparx5_serdes_io_resource sparx5_serdes_iomap[] = {
{ TARGET_SD_LANE_25G + 7, 0x5c8000 }, /* 0x610dd0000: sd_lane_25g_32 */
};
+static const struct sparx5_serdes_io_resource lan969x_serdes_iomap[] = {
+ { TARGET_SD_CMU, 0x0 }, /* 0xe3410000 */
+ { TARGET_SD_CMU + 1, 0x8000 }, /* 0xe3418000 */
+ { TARGET_SD_CMU + 2, 0x10000 }, /* 0xe3420000 */
+ { TARGET_SD_CMU + 3, 0x18000 }, /* 0xe3428000 */
+ { TARGET_SD_CMU + 4, 0x20000 }, /* 0xe3430000 */
+ { TARGET_SD_CMU + 5, 0x28000 }, /* 0xe3438000 */
+ { TARGET_SD_CMU_CFG, 0x30000 }, /* 0xe3440000 */
+ { TARGET_SD_CMU_CFG + 1, 0x38000 }, /* 0xe3448000 */
+ { TARGET_SD_CMU_CFG + 2, 0x40000 }, /* 0xe3450000 */
+ { TARGET_SD_CMU_CFG + 3, 0x48000 }, /* 0xe3458000 */
+ { TARGET_SD_CMU_CFG + 4, 0x50000 }, /* 0xe3460000 */
+ { TARGET_SD_CMU_CFG + 5, 0x58000 }, /* 0xe3468000 */
+ { TARGET_SD10G_LANE, 0x60000 }, /* 0xe3470000 */
+ { TARGET_SD10G_LANE + 1, 0x68000 }, /* 0xe3478000 */
+ { TARGET_SD10G_LANE + 2, 0x70000 }, /* 0xe3480000 */
+ { TARGET_SD10G_LANE + 3, 0x78000 }, /* 0xe3488000 */
+ { TARGET_SD10G_LANE + 4, 0x80000 }, /* 0xe3490000 */
+ { TARGET_SD10G_LANE + 5, 0x88000 }, /* 0xe3498000 */
+ { TARGET_SD10G_LANE + 6, 0x90000 }, /* 0xe34a0000 */
+ { TARGET_SD10G_LANE + 7, 0x98000 }, /* 0xe34a8000 */
+ { TARGET_SD10G_LANE + 8, 0xa0000 }, /* 0xe34b0000 */
+ { TARGET_SD10G_LANE + 9, 0xa8000 }, /* 0xe34b8000 */
+ { TARGET_SD_LANE, 0x100000 }, /* 0xe3510000 */
+ { TARGET_SD_LANE + 1, 0x108000 }, /* 0xe3518000 */
+ { TARGET_SD_LANE + 2, 0x110000 }, /* 0xe3520000 */
+ { TARGET_SD_LANE + 3, 0x118000 }, /* 0xe3528000 */
+ { TARGET_SD_LANE + 4, 0x120000 }, /* 0xe3530000 */
+ { TARGET_SD_LANE + 5, 0x128000 }, /* 0xe3538000 */
+ { TARGET_SD_LANE + 6, 0x130000 }, /* 0xe3540000 */
+ { TARGET_SD_LANE + 7, 0x138000 }, /* 0xe3548000 */
+ { TARGET_SD_LANE + 8, 0x140000 }, /* 0xe3550000 */
+ { TARGET_SD_LANE + 9, 0x148000 }, /* 0xe3558000 */
+};
+
+static const struct sparx5_serdes_match_data sparx5_desc = {
+ .type = SPX5_TARGET_SPARX5,
+ .iomap = sparx5_serdes_iomap,
+ .iomap_size = ARRAY_SIZE(sparx5_serdes_iomap),
+ .tsize = sparx5_serdes_tsize,
+ .consts = {
+ .sd_max = 33,
+ .cmu_max = 14,
+ },
+ .ops = {
+ .serdes_type_set = &sparx5_serdes_type_set,
+ .serdes_cmu_get = &sparx5_serdes_cmu_get,
+ },
+};
+
+static const struct sparx5_serdes_match_data lan969x_desc = {
+ .type = SPX5_TARGET_LAN969X,
+ .iomap = lan969x_serdes_iomap,
+ .iomap_size = ARRAY_SIZE(lan969x_serdes_iomap),
+ .tsize = lan969x_serdes_tsize,
+ .consts = {
+ .sd_max = 10,
+ .cmu_max = 6,
+ },
+ .ops = {
+ .serdes_type_set = &lan969x_serdes_type_set,
+ .serdes_cmu_get = &lan969x_serdes_cmu_get,
+ }
+};
+
/* Client lookup function, uses serdes index */
static struct phy *sparx5_serdes_xlate(struct device *dev,
const struct of_phandle_args *args)
@@ -2521,7 +2635,7 @@ static struct phy *sparx5_serdes_xlate(struct device *dev,
sidx = args->args[0];
/* Check validity: ERR_PTR(-ENODEV) if not valid */
- for (idx = 0; idx < SPX5_SERDES_MAX; idx++) {
+ for (idx = 0; idx < priv->data->consts.sd_max; idx++) {
struct sparx5_serdes_macro *macro =
phy_get_drvdata(priv->phys[idx]);
@@ -2555,6 +2669,12 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
priv->dev = &pdev->dev;
+ priv->data = device_get_match_data(priv->dev);
+ if (!priv->data)
+ return -EINVAL;
+
+ tsize = priv->data->tsize;
+
/* Get coreclock */
clk = devm_clk_get(priv->dev, NULL);
if (IS_ERR(clk)) {
@@ -2579,19 +2699,21 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
iores->name);
return -ENOMEM;
}
- for (idx = 0; idx < ARRAY_SIZE(sparx5_serdes_iomap); idx++) {
- struct sparx5_serdes_io_resource *iomap = &sparx5_serdes_iomap[idx];
+ for (idx = 0; idx < priv->data->iomap_size; idx++) {
+ const struct sparx5_serdes_io_resource *iomap =
+ &priv->data->iomap[idx];
priv->regs[iomap->id] = iomem + iomap->offset;
}
- for (idx = 0; idx < SPX5_SERDES_MAX; idx++) {
+ for (idx = 0; idx < priv->data->consts.sd_max; idx++) {
err = sparx5_phy_create(priv, idx, &priv->phys[idx]);
if (err)
return err;
}
- /* Power down all CMUs by default */
- sparx5_serdes_cmu_power_off(priv);
+ /* Power down all CMU's by default */
+ if (priv->data->type == SPX5_TARGET_SPARX5)
+ sparx5_serdes_cmu_power_off(priv);
provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate);
@@ -2599,7 +2721,8 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
}
static const struct of_device_id sparx5_serdes_match[] = {
- { .compatible = "microchip,sparx5-serdes" },
+ { .compatible = "microchip,sparx5-serdes", .data = &sparx5_desc },
+ { .compatible = "microchip,lan9691-serdes", .data = &lan969x_desc },
{ }
};
MODULE_DEVICE_TABLE(of, sparx5_serdes_match);
diff --git a/drivers/phy/microchip/sparx5_serdes.h b/drivers/phy/microchip/sparx5_serdes.h
index 13f94a29225a..d7093d0b09c0 100644
--- a/drivers/phy/microchip/sparx5_serdes.h
+++ b/drivers/phy/microchip/sparx5_serdes.h
@@ -26,11 +26,18 @@ enum sparx5_serdes_mode {
SPX5_SD_MODE_SFI,
};
-struct sparx5_serdes_private {
- struct device *dev;
- void __iomem *regs[NUM_TARGETS];
- struct phy *phys[SPX5_SERDES_MAX];
- unsigned long coreclock;
+enum sparx5_10g28cmu_mode {
+ SPX5_SD10G28_CMU_MAIN = 0,
+ SPX5_SD10G28_CMU_AUX1 = 1,
+ SPX5_SD10G28_CMU_AUX2 = 3,
+ SPX5_SD10G28_CMU_NONE = 4,
+ SPX5_SD10G28_CMU_MAX,
+};
+
+enum sparx5_target {
+ SPX5_TARGET_SPARX5,
+ SPX5_TARGET_LAN969X,
+
};
struct sparx5_serdes_macro {
@@ -44,6 +51,33 @@ struct sparx5_serdes_macro {
enum phy_media media;
};
+struct sparx5_serdes_consts {
+ int sd_max;
+ int cmu_max;
+};
+
+struct sparx5_serdes_ops {
+ void (*serdes_type_set)(struct sparx5_serdes_macro *macro, int sidx);
+ int (*serdes_cmu_get)(enum sparx5_10g28cmu_mode mode, int sd_index);
+};
+
+struct sparx5_serdes_match_data {
+ enum sparx5_target type;
+ const struct sparx5_serdes_consts consts;
+ const struct sparx5_serdes_ops ops;
+ const struct sparx5_serdes_io_resource *iomap;
+ int iomap_size;
+ const unsigned int *tsize;
+};
+
+struct sparx5_serdes_private {
+ struct device *dev;
+ void __iomem *regs[NUM_TARGETS];
+ struct phy *phys[SPX5_SERDES_MAX];
+ unsigned long coreclock;
+ const struct sparx5_serdes_match_data *data;
+};
+
/* Read, Write and modify registers content.
* The register definition macros start at the id
*/
diff --git a/drivers/phy/microchip/sparx5_serdes_regs.h b/drivers/phy/microchip/sparx5_serdes_regs.h
index d0543fd3dc94..11c4fdc593fa 100644
--- a/drivers/phy/microchip/sparx5_serdes_regs.h
+++ b/drivers/phy/microchip/sparx5_serdes_regs.h
@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+
* Microchip Sparx5 SerDes driver
*
- * Copyright (c) 2020 Microchip Technology Inc.
+ * Copyright (c) 2024 Microchip Technology Inc.
*/
-/* This file is autogenerated by cml-utils 2020-11-16 13:11:27 +0100.
- * Commit ID: 13bdf073131d8bf40c54901df6988ae4e9c8f29f
+/* This file is autogenerated by cml-utils 2023-04-13 15:02:00 +0200.
+ * Commit ID: 5ac560288d46048f872ecdb8add53717f1efc0e1
*/
#ifndef _SPARX5_SERDES_REGS_H_
@@ -26,10 +26,25 @@ enum sparx5_serdes_target {
NUM_TARGETS = 332
};
+enum sparx5_serdes_tsize_enum {
+ TC_SD10G_LANE,
+ TC_SD_CMU,
+ TC_SD_CMU_CFG,
+ TC_SD_LANE,
+ TSIZE_LAST,
+};
+
+/* sparx5_serdes.c */
+extern const unsigned int *tsize;
+
+#define TSIZE(o) tsize[o]
+
#define __REG(...) __VA_ARGS__
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_01 */
-#define SD10G_LANE_LANE_01(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 4, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_01 */
+#define SD10G_LANE_LANE_01(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 4, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0_SET(x)\
@@ -49,8 +64,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_01_CFG_RXDET_STR_GET(x)\
FIELD_GET(SD10G_LANE_LANE_01_CFG_RXDET_STR, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_02 */
-#define SD10G_LANE_LANE_02(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 8, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_02 */
+#define SD10G_LANE_LANE_02(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 8, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_02_CFG_EN_ADV BIT(0)
#define SD10G_LANE_LANE_02_CFG_EN_ADV_SET(x)\
@@ -82,8 +99,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_03 */
-#define SD10G_LANE_LANE_03(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 12, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_03 */
+#define SD10G_LANE_LANE_03(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 12, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN BIT(0)
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN_SET(x)\
@@ -91,8 +110,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_03_CFG_TAP_MAIN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_04 */
-#define SD10G_LANE_LANE_04(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 16, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_04 */
+#define SD10G_LANE_LANE_04(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 16, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0 GENMASK(4, 0)
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0_SET(x)\
@@ -100,8 +121,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_06 */
-#define SD10G_LANE_LANE_06(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 24, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_06 */
+#define SD10G_LANE_LANE_06(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 24, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_06_CFG_PD_DRIVER BIT(0)
#define SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(x)\
@@ -139,8 +162,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_06_CFG_EN_PREEMPH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_06_CFG_EN_PREEMPH, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0B */
-#define SD10G_LANE_LANE_0B(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 44, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0B */
+#define SD10G_LANE_LANE_0B(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 44, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0_SET(x)\
@@ -172,8 +197,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_SQ_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_SQ, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0C */
-#define SD10G_LANE_LANE_0C(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 48, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0C */
+#define SD10G_LANE_LANE_0C(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 48, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0C_CFG_OSCAL_AFE BIT(0)
#define SD10G_LANE_LANE_0C_CFG_OSCAL_AFE_SET(x)\
@@ -223,8 +250,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0C_CFG_RX_PCIE_GEN12_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0C_CFG_RX_PCIE_GEN12, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0D */
-#define SD10G_LANE_LANE_0D(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 52, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0D */
+#define SD10G_LANE_LANE_0D(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 52, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0D_CFG_CTLE_M_THR_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_0D_CFG_CTLE_M_THR_1_0_SET(x)\
@@ -238,8 +267,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0D_CFG_EQR_BYP_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0D_CFG_EQR_BYP, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0E */
-#define SD10G_LANE_LANE_0E(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 56, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0E */
+#define SD10G_LANE_LANE_0E(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 56, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0_SET(x)\
@@ -265,8 +296,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0F */
-#define SD10G_LANE_LANE_0F(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0F */
+#define SD10G_LANE_LANE_0F(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 60, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0_SET(x)\
@@ -274,8 +307,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_13 */
-#define SD10G_LANE_LANE_13(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 76, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_13 */
+#define SD10G_LANE_LANE_13(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 76, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_13_CFG_DCDR_PD BIT(0)
#define SD10G_LANE_LANE_13_CFG_DCDR_PD_SET(x)\
@@ -295,8 +330,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_13_CFG_CDRCK_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_13_CFG_CDRCK_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_14 */
-#define SD10G_LANE_LANE_14(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 80, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_14 */
+#define SD10G_LANE_LANE_14(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 80, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0_SET(x)\
@@ -304,8 +341,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_15 */
-#define SD10G_LANE_LANE_15(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 84, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_15 */
+#define SD10G_LANE_LANE_15(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 84, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8 GENMASK(7, 0)
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8_SET(x)\
@@ -313,8 +352,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8_GET(x)\
FIELD_GET(SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_16 */
-#define SD10G_LANE_LANE_16(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 88, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_16 */
+#define SD10G_LANE_LANE_16(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 88, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16 GENMASK(7, 0)
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16_SET(x)\
@@ -322,8 +363,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16_GET(x)\
FIELD_GET(SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_1A */
-#define SD10G_LANE_LANE_1A(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 104, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_1A */
+#define SD10G_LANE_LANE_1A(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 104, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_1A_CFG_PI_R_SCAN_EN BIT(0)
#define SD10G_LANE_LANE_1A_CFG_PI_R_SCAN_EN_SET(x)\
@@ -355,8 +398,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_22 */
-#define SD10G_LANE_LANE_22(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 136, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_22 */
+#define SD10G_LANE_LANE_22(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 136, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1 GENMASK(4, 0)
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1_SET(x)\
@@ -364,8 +409,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1_GET(x)\
FIELD_GET(SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_23 */
-#define SD10G_LANE_LANE_23(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 140, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_23 */
+#define SD10G_LANE_LANE_23(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 140, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_23_CFG_DFE_PD BIT(0)
#define SD10G_LANE_LANE_23_CFG_DFE_PD_SET(x)\
@@ -397,8 +444,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_23_CFG_DFEDIG_M_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_23_CFG_DFEDIG_M_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_24 */
-#define SD10G_LANE_LANE_24(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 144, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_24 */
+#define SD10G_LANE_LANE_24(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 144, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0_SET(x)\
@@ -412,8 +461,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN2_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_24_CFG_PI_BW_GEN2_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_26 */
-#define SD10G_LANE_LANE_26(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 152, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_26 */
+#define SD10G_LANE_LANE_26(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 152, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0_SET(x)\
@@ -421,8 +472,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_2F */
-#define SD10G_LANE_LANE_2F(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 188, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_2F */
+#define SD10G_LANE_LANE_2F(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 188, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0_SET(x)\
@@ -436,8 +489,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_30 */
-#define SD10G_LANE_LANE_30(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 192, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_30 */
+#define SD10G_LANE_LANE_30(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 192, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_30_CFG_SUMMER_EN BIT(0)
#define SD10G_LANE_LANE_30_CFG_SUMMER_EN_SET(x)\
@@ -451,8 +506,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_31 */
-#define SD10G_LANE_LANE_31(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 196, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_31 */
+#define SD10G_LANE_LANE_31(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 196, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_31_CFG_PI_RSTN BIT(0)
#define SD10G_LANE_LANE_31_CFG_PI_RSTN_SET(x)\
@@ -490,8 +547,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_31_CFG_R50_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_31_CFG_R50_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_32 */
-#define SD10G_LANE_LANE_32(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 200, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_32 */
+#define SD10G_LANE_LANE_32(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 200, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_32_CFG_ITX_IPCLK_BASE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_32_CFG_ITX_IPCLK_BASE_1_0_SET(x)\
@@ -505,8 +564,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_33 */
-#define SD10G_LANE_LANE_33(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 204, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_33 */
+#define SD10G_LANE_LANE_33(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 204, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0_SET(x)\
@@ -520,8 +581,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_35 */
-#define SD10G_LANE_LANE_35(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 212, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_35 */
+#define SD10G_LANE_LANE_35(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 212, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_35_CFG_TXRATE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_35_CFG_TXRATE_1_0_SET(x)\
@@ -535,8 +598,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_35_CFG_RXRATE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_35_CFG_RXRATE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_36 */
-#define SD10G_LANE_LANE_36(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 216, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_36 */
+#define SD10G_LANE_LANE_36(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 216, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0_SET(x)\
@@ -568,8 +633,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_36_CFG_PRBS_SETB_GET(x)\
FIELD_GET(SD10G_LANE_LANE_36_CFG_PRBS_SETB, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_37 */
-#define SD10G_LANE_LANE_37(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 220, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_37 */
+#define SD10G_LANE_LANE_37(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 220, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_37_CFG_RXDET_COMP_PD BIT(0)
#define SD10G_LANE_LANE_37_CFG_RXDET_COMP_PD_SET(x)\
@@ -595,8 +662,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_39 */
-#define SD10G_LANE_LANE_39(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 228, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_39 */
+#define SD10G_LANE_LANE_39(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 228, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_39_CFG_RXFILT_Y_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_39_CFG_RXFILT_Y_2_0_SET(x)\
@@ -610,8 +679,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_39_CFG_RX_SSC_LH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_39_CFG_RX_SSC_LH, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3A */
-#define SD10G_LANE_LANE_3A(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 232, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3A */
+#define SD10G_LANE_LANE_3A(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 232, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_3A_CFG_MP_MIN_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_3A_CFG_MP_MIN_3_0_SET(x)\
@@ -625,8 +696,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3C */
-#define SD10G_LANE_LANE_3C(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 240, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3C */
+#define SD10G_LANE_LANE_3C(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 240, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_3C_CFG_DIS_ACC BIT(0)
#define SD10G_LANE_LANE_3C_CFG_DIS_ACC_SET(x)\
@@ -640,8 +713,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER_GET(x)\
FIELD_GET(SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_40 */
-#define SD10G_LANE_LANE_40(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 256, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_40 */
+#define SD10G_LANE_LANE_40(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 256, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0_SET(x)\
@@ -649,8 +724,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_41 */
-#define SD10G_LANE_LANE_41(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 260, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_41 */
+#define SD10G_LANE_LANE_41(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 260, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8 GENMASK(7, 0)
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8_SET(x)\
@@ -658,8 +735,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8_GET(x)\
FIELD_GET(SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_42 */
-#define SD10G_LANE_LANE_42(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 264, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_42 */
+#define SD10G_LANE_LANE_42(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 264, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0_SET(x)\
@@ -673,8 +752,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN2_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_42_CFG_CDR_KF_GEN2_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_48 */
-#define SD10G_LANE_LANE_48(t) __REG(TARGET_SD10G_LANE, t, 12, 288, 0, 1, 40, 0, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_48 */
+#define SD10G_LANE_LANE_48(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 288, 0, 1, 40, 0, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0_SET(x)\
@@ -694,8 +775,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_48_CFG_CLK_ENQ_GET(x)\
FIELD_GET(SD10G_LANE_LANE_48_CFG_CLK_ENQ, x)
-/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_50 */
-#define SD10G_LANE_LANE_50(t) __REG(TARGET_SD10G_LANE, t, 12, 288, 0, 1, 40, 32, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_50 */
+#define SD10G_LANE_LANE_50(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 288, 0, 1, 40, 32, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_50_CFG_SSC_PI_STEP_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_50_CFG_SSC_PI_STEP_1_0_SET(x)\
@@ -727,8 +810,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_50_CFG_JT_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_50_CFG_JT_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_2:LANE_52 */
-#define SD10G_LANE_LANE_52(t) __REG(TARGET_SD10G_LANE, t, 12, 328, 0, 1, 24, 0, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_2:LANE_52 */
+#define SD10G_LANE_LANE_52(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 328, 0, 1, 24, 0, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0 GENMASK(5, 0)
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0_SET(x)\
@@ -736,8 +821,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_4:LANE_83 */
-#define SD10G_LANE_LANE_83(t) __REG(TARGET_SD10G_LANE, t, 12, 464, 0, 1, 112, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_4:LANE_83 */
+#define SD10G_LANE_LANE_83(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 464, 0, 1, 112, 60, \
+ 0, 1, 4)
#define SD10G_LANE_LANE_83_R_TX_BIT_REVERSE BIT(0)
#define SD10G_LANE_LANE_83_R_TX_BIT_REVERSE_SET(x)\
@@ -781,8 +868,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_83_R_CTLE_RSTN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_83_R_CTLE_RSTN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_93 */
-#define SD10G_LANE_LANE_93(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 12, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_93 */
+#define SD10G_LANE_LANE_93(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 12, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_93_R_RXEI_FIFO_RST_EN BIT(0)
#define SD10G_LANE_LANE_93_R_RXEI_FIFO_RST_EN_SET(x)\
@@ -832,8 +921,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_93_R_RX_PCIE_GEN12_FROM_HWT_GET(x)\
FIELD_GET(SD10G_LANE_LANE_93_R_RX_PCIE_GEN12_FROM_HWT, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_94 */
-#define SD10G_LANE_LANE_94(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 16, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_94 */
+#define SD10G_LANE_LANE_94(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 16, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0_SET(x)\
@@ -865,8 +956,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_94_R_SWING_REG_GET(x)\
FIELD_GET(SD10G_LANE_LANE_94_R_SWING_REG, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_9E */
-#define SD10G_LANE_LANE_9E(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 56, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_9E */
+#define SD10G_LANE_LANE_9E(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 56, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_9E_R_RXEQ_REG BIT(0)
#define SD10G_LANE_LANE_9E_R_RXEQ_REG_SET(x)\
@@ -886,8 +979,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A1 */
-#define SD10G_LANE_LANE_A1(t) __REG(TARGET_SD10G_LANE, t, 12, 640, 0, 1, 128, 4, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A1 */
+#define SD10G_LANE_LANE_A1(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 640, 0, 1, 128, 4, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_A1_R_PMA_TXCK_DIV_SEL_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_A1_R_PMA_TXCK_DIV_SEL_1_0_SET(x)\
@@ -919,8 +1014,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_A1_R_PCLK_GATING_GET(x)\
FIELD_GET(SD10G_LANE_LANE_A1_R_PCLK_GATING, x)
-/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A2 */
-#define SD10G_LANE_LANE_A2(t) __REG(TARGET_SD10G_LANE, t, 12, 640, 0, 1, 128, 8, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A2 */
+#define SD10G_LANE_LANE_A2(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 640, 0, 1, 128, 8, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0 GENMASK(4, 0)
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0_SET(x)\
@@ -928,8 +1025,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
-#define SD10G_LANE_LANE_DF(t) __REG(TARGET_SD10G_LANE, t, 12, 832, 0, 1, 84, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
+#define SD10G_LANE_LANE_DF(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 832, 0, 1, 84, 60, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_DF_LOL_UDL BIT(0)
#define SD10G_LANE_LANE_DF_LOL_UDL_SET(x)\
@@ -955,8 +1054,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_DF_SQUELCH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_DF_SQUELCH, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_09 */
-#define SD25G_LANE_CMU_09(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_09 */
+#define SD25G_LANE_CMU_09(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 36, 0, 1, 4)
#define SD25G_LANE_CMU_09_CFG_REFCK_TERM_EN BIT(0)
#define SD25G_LANE_CMU_09_CFG_REFCK_TERM_EN_SET(x)\
@@ -988,8 +1089,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_09_CFG_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_09_CFG_PLL_TP_SEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0B */
-#define SD25G_LANE_CMU_0B(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 44, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0B */
+#define SD25G_LANE_CMU_0B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 44, 0, 1, 4)
#define SD25G_LANE_CMU_0B_CFG_FORCE_RX_FILT BIT(0)
#define SD25G_LANE_CMU_0B_CFG_FORCE_RX_FILT_SET(x)\
@@ -1039,8 +1142,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0B_CFG_RST_TREE_PD_MAN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0B_CFG_RST_TREE_PD_MAN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0C */
-#define SD25G_LANE_CMU_0C(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 48, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0C */
+#define SD25G_LANE_CMU_0C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 48, 0, 1, 4)
#define SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET BIT(0)
#define SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET_SET(x)\
@@ -1072,8 +1177,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0D */
-#define SD25G_LANE_CMU_0D(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 52, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0D */
+#define SD25G_LANE_CMU_0D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 52, 0, 1, 4)
#define SD25G_LANE_CMU_0D_CFG_CK_TREE_PD BIT(0)
#define SD25G_LANE_CMU_0D_CFG_CK_TREE_PD_SET(x)\
@@ -1105,8 +1212,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0E */
-#define SD25G_LANE_CMU_0E(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 56, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0E */
+#define SD25G_LANE_CMU_0E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 56, 0, 1, 4)
#define SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0_SET(x)\
@@ -1120,8 +1229,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0E_CFG_PMAA_CENTR_CK_PD_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0E_CFG_PMAA_CENTR_CK_PD, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_13 */
-#define SD25G_LANE_CMU_13(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 76, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_13 */
+#define SD25G_LANE_CMU_13(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 76, 0, 1, 4)
#define SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0_SET(x)\
@@ -1135,8 +1246,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_13_CFG_JT_EN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_13_CFG_JT_EN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_18 */
-#define SD25G_LANE_CMU_18(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 96, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_18 */
+#define SD25G_LANE_CMU_18(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 96, 0, 1, 4)
#define SD25G_LANE_CMU_18_R_PLL_RSTN BIT(0)
#define SD25G_LANE_CMU_18_R_PLL_RSTN_SET(x)\
@@ -1162,8 +1275,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_18_R_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_18_R_PLL_TP_SEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_19 */
-#define SD25G_LANE_CMU_19(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 100, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_19 */
+#define SD25G_LANE_CMU_19(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 100, 0, 1, 4)
#define SD25G_LANE_CMU_19_R_CK_RESETB BIT(0)
#define SD25G_LANE_CMU_19_R_CK_RESETB_SET(x)\
@@ -1177,8 +1292,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_19_R_PLL_DLOL_EN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_19_R_PLL_DLOL_EN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_1A */
-#define SD25G_LANE_CMU_1A(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 104, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_1A */
+#define SD25G_LANE_CMU_1A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 104, 0, 1, 4)
#define SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0 GENMASK(2, 0)
#define SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0_SET(x)\
@@ -1204,8 +1321,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_1A_R_REG_MANUAL_GET(x)\
FIELD_GET(SD25G_LANE_CMU_1A_R_REG_MANUAL, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_2A */
-#define SD25G_LANE_CMU_2A(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_2A */
+#define SD25G_LANE_CMU_2A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 36, 0, 1, 4)
#define SD25G_LANE_CMU_2A_R_DBG_SEL_1_0 GENMASK(1, 0)
#define SD25G_LANE_CMU_2A_R_DBG_SEL_1_0_SET(x)\
@@ -1225,8 +1344,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS_GET(x)\
FIELD_GET(SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_30 */
-#define SD25G_LANE_CMU_30(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_30 */
+#define SD25G_LANE_CMU_30(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 60, 0, 1, 4)
#define SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0 GENMASK(2, 0)
#define SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0_SET(x)\
@@ -1240,8 +1361,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_31 */
-#define SD25G_LANE_CMU_31(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 64, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_31 */
+#define SD25G_LANE_CMU_31(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 64, 0, 1, 4)
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0_SET(x)\
@@ -1249,8 +1372,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_40 */
-#define SD25G_LANE_CMU_40(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_40 */
+#define SD25G_LANE_CMU_40(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 0, 0, 1, 4)
#define SD25G_LANE_CMU_40_L0_CFG_CKSKEW_CTRL BIT(0)
#define SD25G_LANE_CMU_40_L0_CFG_CKSKEW_CTRL_SET(x)\
@@ -1288,8 +1413,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_40_L0_CFG_TXCAL_RST_GET(x)\
FIELD_GET(SD25G_LANE_CMU_40_L0_CFG_TXCAL_RST, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_45 */
-#define SD25G_LANE_CMU_45(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_45 */
+#define SD25G_LANE_CMU_45(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 20, 0, 1, 4)
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0_SET(x)\
@@ -1297,8 +1424,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_46 */
-#define SD25G_LANE_CMU_46(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_46 */
+#define SD25G_LANE_CMU_46(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 24, 0, 1, 4)
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8_SET(x)\
@@ -1306,8 +1435,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8, x)
-/* SD25G_TARGET:CMU_GRP_3:CMU_C0 */
-#define SD25G_LANE_CMU_C0(t) __REG(TARGET_SD25G_LANE, t, 8, 768, 0, 1, 252, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_3:CMU_C0 */
+#define SD25G_LANE_CMU_C0(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 768, 0, 1, 252, 0, 0, 1, 4)
#define SD25G_LANE_CMU_C0_READ_VCO_CTUNE_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_C0_READ_VCO_CTUNE_3_0_SET(x)\
@@ -1321,8 +1452,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_C0_PLL_LOL_UDL_GET(x)\
FIELD_GET(SD25G_LANE_CMU_C0_PLL_LOL_UDL, x)
-/* SD25G_TARGET:CMU_GRP_4:CMU_FF */
-#define SD25G_LANE_CMU_FF(t) __REG(TARGET_SD25G_LANE, t, 8, 1020, 0, 1, 4, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_4:CMU_FF */
+#define SD25G_LANE_CMU_FF(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1020, 0, 1, 4, 0, 0, 1, 4)
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX GENMASK(7, 0)
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_SET(x)\
@@ -1330,8 +1463,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_GET(x)\
FIELD_GET(SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_00 */
-#define SD25G_LANE_LANE_00(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_00 */
+#define SD25G_LANE_LANE_00(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 0, 0, 1, 4)
#define SD25G_LANE_LANE_00_LN_CFG_ITX_VC_DRIVER_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_00_LN_CFG_ITX_VC_DRIVER_3_0_SET(x)\
@@ -1345,8 +1480,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_01 */
-#define SD25G_LANE_LANE_01(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_01 */
+#define SD25G_LANE_LANE_01(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 4, 0, 1, 4)
#define SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0_SET(x)\
@@ -1360,8 +1497,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_03 */
-#define SD25G_LANE_LANE_03(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 12, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_03 */
+#define SD25G_LANE_LANE_03(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 12, 0, 1, 4)
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0 GENMASK(4, 0)
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0_SET(x)\
@@ -1369,8 +1508,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_04 */
-#define SD25G_LANE_LANE_04(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 16, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_04 */
+#define SD25G_LANE_LANE_04(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 16, 0, 1, 4)
#define SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN BIT(0)
#define SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN_SET(x)\
@@ -1408,8 +1549,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_04_LN_CFG_TAP_MAIN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_04_LN_CFG_TAP_MAIN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_05 */
-#define SD25G_LANE_LANE_05(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_05 */
+#define SD25G_LANE_LANE_05(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 20, 0, 1, 4)
#define SD25G_LANE_LANE_05_LN_CFG_TAP_DLY2_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_05_LN_CFG_TAP_DLY2_3_0_SET(x)\
@@ -1423,8 +1566,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_05_LN_CFG_BW_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_05_LN_CFG_BW_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_06 */
-#define SD25G_LANE_LANE_06(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_06 */
+#define SD25G_LANE_LANE_06(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 24, 0, 1, 4)
#define SD25G_LANE_LANE_06_LN_CFG_EN_MAIN BIT(0)
#define SD25G_LANE_LANE_06_LN_CFG_EN_MAIN_SET(x)\
@@ -1438,8 +1583,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_07 */
-#define SD25G_LANE_LANE_07(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 28, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_07 */
+#define SD25G_LANE_LANE_07(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 28, 0, 1, 4)
#define SD25G_LANE_LANE_07_LN_CFG_EN_ADV BIT(0)
#define SD25G_LANE_LANE_07_LN_CFG_EN_ADV_SET(x)\
@@ -1459,8 +1606,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_07_LN_CFG_EN_DLY_GET(x)\
FIELD_GET(SD25G_LANE_LANE_07_LN_CFG_EN_DLY, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_09 */
-#define SD25G_LANE_LANE_09(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_09 */
+#define SD25G_LANE_LANE_09(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 36, 0, 1, 4)
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0_SET(x)\
@@ -1468,8 +1617,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0A */
-#define SD25G_LANE_LANE_0A(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 40, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0A */
+#define SD25G_LANE_LANE_0A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 40, 0, 1, 4)
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0 GENMASK(5, 0)
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0_SET(x)\
@@ -1477,8 +1628,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0B */
-#define SD25G_LANE_LANE_0B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 44, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0B */
+#define SD25G_LANE_LANE_0B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 44, 0, 1, 4)
#define SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN BIT(0)
#define SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN_SET(x)\
@@ -1498,8 +1651,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0B_LN_CFG_QUAD_MAN_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0B_LN_CFG_QUAD_MAN_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0C */
-#define SD25G_LANE_LANE_0C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 48, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0C */
+#define SD25G_LANE_LANE_0C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 48, 0, 1, 4)
#define SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0_SET(x)\
@@ -1519,8 +1674,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0C_LN_CFG_RXTERM_PD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0C_LN_CFG_RXTERM_PD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0D */
-#define SD25G_LANE_LANE_0D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 52, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0D */
+#define SD25G_LANE_LANE_0D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 52, 0, 1, 4)
#define SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0_SET(x)\
@@ -1552,8 +1709,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0E */
-#define SD25G_LANE_LANE_0E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 56, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0E */
+#define SD25G_LANE_LANE_0E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 56, 0, 1, 4)
#define SD25G_LANE_LANE_0E_LN_CFG_ISCAN_EN BIT(0)
#define SD25G_LANE_LANE_0E_LN_CFG_ISCAN_EN_SET(x)\
@@ -1579,8 +1738,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0F */
-#define SD25G_LANE_LANE_0F(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0F */
+#define SD25G_LANE_LANE_0F(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 60, 0, 1, 4)
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1 GENMASK(4, 0)
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1_SET(x)\
@@ -1588,8 +1749,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_18 */
-#define SD25G_LANE_LANE_18(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 96, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_18 */
+#define SD25G_LANE_LANE_18(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 96, 0, 1, 4)
#define SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN BIT(0)
#define SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN_SET(x)\
@@ -1621,8 +1784,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_19 */
-#define SD25G_LANE_LANE_19(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 100, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_19 */
+#define SD25G_LANE_LANE_19(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 100, 0, 1, 4)
#define SD25G_LANE_LANE_19_LN_CFG_DCDR_PD BIT(0)
#define SD25G_LANE_LANE_19_LN_CFG_DCDR_PD_SET(x)\
@@ -1672,8 +1837,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_19_LN_CFG_PD_CTLE_GET(x)\
FIELD_GET(SD25G_LANE_LANE_19_LN_CFG_PD_CTLE, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1A */
-#define SD25G_LANE_LANE_1A(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 104, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1A */
+#define SD25G_LANE_LANE_1A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 104, 0, 1, 4)
#define SD25G_LANE_LANE_1A_LN_CFG_CTLE_TP_EN BIT(0)
#define SD25G_LANE_LANE_1A_LN_CFG_CTLE_TP_EN_SET(x)\
@@ -1687,8 +1854,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1B */
-#define SD25G_LANE_LANE_1B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 108, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1B */
+#define SD25G_LANE_LANE_1B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 108, 0, 1, 4)
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0_SET(x)\
@@ -1696,8 +1865,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1C */
-#define SD25G_LANE_LANE_1C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 112, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1C */
+#define SD25G_LANE_LANE_1C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 112, 0, 1, 4)
#define SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN BIT(0)
#define SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN_SET(x)\
@@ -1723,8 +1894,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1D */
-#define SD25G_LANE_LANE_1D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 116, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1D */
+#define SD25G_LANE_LANE_1D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 116, 0, 1, 4)
#define SD25G_LANE_LANE_1D_LN_CFG_ISCAN_EXT_OVR BIT(0)
#define SD25G_LANE_LANE_1D_LN_CFG_ISCAN_EXT_OVR_SET(x)\
@@ -1774,8 +1947,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1D_LN_CFG_PI_HOLD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1D_LN_CFG_PI_HOLD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1E */
-#define SD25G_LANE_LANE_1E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 120, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1E */
+#define SD25G_LANE_LANE_1E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 120, 0, 1, 4)
#define SD25G_LANE_LANE_1E_LN_CFG_PI_STEPS_1_0 GENMASK(1, 0)
#define SD25G_LANE_LANE_1E_LN_CFG_PI_STEPS_1_0_SET(x)\
@@ -1807,8 +1982,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1E_LN_CFG_PMAD_CK_PD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1E_LN_CFG_PMAD_CK_PD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_21 */
-#define SD25G_LANE_LANE_21(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 132, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_21 */
+#define SD25G_LANE_LANE_21(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 132, 0, 1, 4)
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0 GENMASK(4, 0)
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0_SET(x)\
@@ -1816,8 +1993,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_22 */
-#define SD25G_LANE_LANE_22(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 136, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_22 */
+#define SD25G_LANE_LANE_22(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 136, 0, 1, 4)
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0_SET(x)\
@@ -1825,8 +2004,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_25 */
-#define SD25G_LANE_LANE_25(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 148, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_25 */
+#define SD25G_LANE_LANE_25(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 148, 0, 1, 4)
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0 GENMASK(6, 0)
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0_SET(x)\
@@ -1834,8 +2015,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_26 */
-#define SD25G_LANE_LANE_26(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 152, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_26 */
+#define SD25G_LANE_LANE_26(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 152, 0, 1, 4)
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0 GENMASK(6, 0)
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0_SET(x)\
@@ -1843,8 +2026,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_28 */
-#define SD25G_LANE_LANE_28(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 160, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_28 */
+#define SD25G_LANE_LANE_28(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 160, 0, 1, 4)
#define SD25G_LANE_LANE_28_LN_CFG_ISCAN_MODE_EN BIT(0)
#define SD25G_LANE_LANE_28_LN_CFG_ISCAN_MODE_EN_SET(x)\
@@ -1870,8 +2055,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2B */
-#define SD25G_LANE_LANE_2B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 172, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2B */
+#define SD25G_LANE_LANE_2B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 172, 0, 1, 4)
#define SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0_SET(x)\
@@ -1891,8 +2078,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2B_LN_CFG_RSTN_TXDUPU_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2B_LN_CFG_RSTN_TXDUPU, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2C */
-#define SD25G_LANE_LANE_2C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 176, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2C */
+#define SD25G_LANE_LANE_2C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 176, 0, 1, 4)
#define SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0_SET(x)\
@@ -1906,8 +2095,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2D */
-#define SD25G_LANE_LANE_2D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 180, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2D */
+#define SD25G_LANE_LANE_2D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 180, 0, 1, 4)
#define SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0_SET(x)\
@@ -1921,8 +2112,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2D_LN_CFG_SAT_CNTSEL_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2D_LN_CFG_SAT_CNTSEL_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2E */
-#define SD25G_LANE_LANE_2E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 184, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2E */
+#define SD25G_LANE_LANE_2E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 184, 0, 1, 4)
#define SD25G_LANE_LANE_2E_LN_CFG_EN_FAST_ISCAN BIT(0)
#define SD25G_LANE_LANE_2E_LN_CFG_EN_FAST_ISCAN_SET(x)\
@@ -1972,8 +2165,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_40 */
-#define SD25G_LANE_LANE_40(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 256, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_40 */
+#define SD25G_LANE_LANE_40(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 256, 0, 1, 4)
#define SD25G_LANE_LANE_40_LN_R_TX_BIT_REVERSE BIT(0)
#define SD25G_LANE_LANE_40_LN_R_TX_BIT_REVERSE_SET(x)\
@@ -2017,8 +2212,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_40_LN_R_CTLE_RSTN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_40_LN_R_CTLE_RSTN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_42 */
-#define SD25G_LANE_LANE_42(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 264, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_42 */
+#define SD25G_LANE_LANE_42(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 264, 0, 1, 4)
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0_SET(x)\
@@ -2026,8 +2223,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_43 */
-#define SD25G_LANE_LANE_43(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 268, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_43 */
+#define SD25G_LANE_LANE_43(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 268, 0, 1, 4)
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8_SET(x)\
@@ -2035,8 +2234,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_44 */
-#define SD25G_LANE_LANE_44(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 272, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_44 */
+#define SD25G_LANE_LANE_44(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 272, 0, 1, 4)
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0_SET(x)\
@@ -2044,8 +2245,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_45 */
-#define SD25G_LANE_LANE_45(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 276, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_45 */
+#define SD25G_LANE_LANE_45(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 276, 0, 1, 4)
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8_SET(x)\
@@ -2053,8 +2256,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8, x)
-/* SD25G_TARGET:LANE_GRP_1:LANE_DE */
-#define SD25G_LANE_LANE_DE(t) __REG(TARGET_SD25G_LANE, t, 8, 1792, 0, 1, 128, 120, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_1:LANE_DE */
+#define SD25G_LANE_LANE_DE(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1792, 0, 1, 128, 120, 0, 1, 4)
#define SD25G_LANE_LANE_DE_LN_LOL_UDL BIT(0)
#define SD25G_LANE_LANE_DE_LN_LOL_UDL_SET(x)\
@@ -2080,8 +2285,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_DE_LN_PMA_RXEI_GET(x)\
FIELD_GET(SD25G_LANE_LANE_DE_LN_PMA_RXEI, x)
-/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
-#define SD6G_LANE_LANE_DF(t) __REG(TARGET_SD6G_LANE, t, 13, 832, 0, 1, 84, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
+#define SD6G_LANE_LANE_DF(t) \
+ __REG(TARGET_SD6G_LANE, t, 13, 832, 0, 1, 84, 60, 0, 1, 4)
#define SD6G_LANE_LANE_DF_LOL_UDL BIT(0)
#define SD6G_LANE_LANE_DF_LOL_UDL_SET(x)\
@@ -2107,8 +2314,9 @@ enum sparx5_serdes_target {
#define SD6G_LANE_LANE_DF_SQUELCH_GET(x)\
FIELD_GET(SD6G_LANE_LANE_DF_SQUELCH, x)
-/* SD10G_CMU_TARGET:CMU_GRP_0:CMU_00 */
-#define SD_CMU_CMU_00(t) __REG(TARGET_SD_CMU, t, 14, 0, 0, 1, 20, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_0:CMU_00 */
+#define SD_CMU_CMU_00(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 0, 0, 1, 20, 0, 0, 1, 4)
#define SD_CMU_CMU_00_R_HWT_SIMULATION_MODE BIT(0)
#define SD_CMU_CMU_00_R_HWT_SIMULATION_MODE_SET(x)\
@@ -2134,8 +2342,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_05 */
-#define SD_CMU_CMU_05(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_05 */
+#define SD_CMU_CMU_05(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 0, 0, 1, 4)
#define SD_CMU_CMU_05_CFG_REFCK_TERM_EN BIT(0)
#define SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(x)\
@@ -2149,9 +2358,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_GET(x)\
FIELD_GET(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */
-#define SD_CMU_CMU_06(t) \
- __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 4, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */
+#define SD_CMU_CMU_06(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 4, 0, 1, 4)
#define SD_CMU_CMU_06_CFG_DISLOS BIT(0)
#define SD_CMU_CMU_06_CFG_DISLOS_SET(x)\
@@ -2201,9 +2410,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_GET(x)\
FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */
-#define SD_CMU_CMU_08(t) \
- __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 12, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */
+#define SD_CMU_CMU_08(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 12, 0, 1, 4)
#define SD_CMU_CMU_08_CFG_VFILT2PAD BIT(0)
#define SD_CMU_CMU_08_CFG_VFILT2PAD_SET(x)\
@@ -2235,8 +2444,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_GET(x)\
FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */
-#define SD_CMU_CMU_09(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 16, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */
+#define SD_CMU_CMU_09(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 16, 0, 1, 4)
#define SD_CMU_CMU_09_CFG_EN_TX_CK_UP BIT(0)
#define SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(x)\
@@ -2262,8 +2472,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_09_CFG_SW_10G_GET(x)\
FIELD_GET(SD_CMU_CMU_09_CFG_SW_10G, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_0D */
-#define SD_CMU_CMU_0D(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 32, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_0D */
+#define SD_CMU_CMU_0D(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 32, 0, 1, 4)
#define SD_CMU_CMU_0D_CFG_PD_DIV64 BIT(0)
#define SD_CMU_CMU_0D_CFG_PD_DIV64_SET(x)\
@@ -2295,8 +2506,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_0D_CFG_REFCK_PD_GET(x)\
FIELD_GET(SD_CMU_CMU_0D_CFG_REFCK_PD, x)
-/* SD10G_CMU_TARGET:CMU_GRP_3:CMU_1B */
-#define SD_CMU_CMU_1B(t) __REG(TARGET_SD_CMU, t, 14, 104, 0, 1, 20, 4, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_3:CMU_1B */
+#define SD_CMU_CMU_1B(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 104, 0, 1, 20, 4, 0, 1, 4)
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0 GENMASK(7, 0)
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(x)\
@@ -2304,8 +2516,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0_GET(x)\
FIELD_GET(SD_CMU_CMU_1B_CFG_RESERVE_7_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_4:CMU_1F */
-#define SD_CMU_CMU_1F(t) __REG(TARGET_SD_CMU, t, 14, 124, 0, 1, 68, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_4:CMU_1F */
+#define SD_CMU_CMU_1F(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 124, 0, 1, 68, 0, 0, 1, 4)
#define SD_CMU_CMU_1F_CFG_BIAS_DN_EN BIT(0)
#define SD_CMU_CMU_1F_CFG_BIAS_DN_EN_SET(x)\
@@ -2331,8 +2544,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_1F_CFG_VTUNE_SEL_GET(x)\
FIELD_GET(SD_CMU_CMU_1F_CFG_VTUNE_SEL, x)
-/* SD10G_CMU_TARGET:CMU_GRP_5:CMU_30 */
-#define SD_CMU_CMU_30(t) __REG(TARGET_SD_CMU, t, 14, 192, 0, 1, 72, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_5:CMU_30 */
+#define SD_CMU_CMU_30(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 192, 0, 1, 72, 0, 0, 1, 4)
#define SD_CMU_CMU_30_R_PLL_DLOL_EN BIT(0)
#define SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(x)\
@@ -2340,8 +2554,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_30_R_PLL_DLOL_EN_GET(x)\
FIELD_GET(SD_CMU_CMU_30_R_PLL_DLOL_EN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_44 */
-#define SD_CMU_CMU_44(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 8, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_44 */
+#define SD_CMU_CMU_44(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 8, 0, 1, 4)
#define SD_CMU_CMU_44_R_PLL_RSTN BIT(0)
#define SD_CMU_CMU_44_R_PLL_RSTN_SET(x)\
@@ -2355,8 +2570,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_44_R_CK_RESETB_GET(x)\
FIELD_GET(SD_CMU_CMU_44_R_CK_RESETB, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_45 */
-#define SD_CMU_CMU_45(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 12, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_45 */
+#define SD_CMU_CMU_45(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 12, 0, 1, 4)
#define SD_CMU_CMU_45_R_EN_RATECHG_CTRL BIT(0)
#define SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(x)\
@@ -2406,8 +2622,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_45_R_AUTO_RST_TREE_PD_MAN_GET(x)\
FIELD_GET(SD_CMU_CMU_45_R_AUTO_RST_TREE_PD_MAN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_47 */
-#define SD_CMU_CMU_47(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 20, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_47 */
+#define SD_CMU_CMU_47(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 20, 0, 1, 4)
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0 GENMASK(4, 0)
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(x)\
@@ -2415,8 +2632,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_GET(x)\
FIELD_GET(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_7:CMU_E0 */
-#define SD_CMU_CMU_E0(t) __REG(TARGET_SD_CMU, t, 14, 896, 0, 1, 8, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_7:CMU_E0 */
+#define SD_CMU_CMU_E0(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 896, 0, 1, 8, 0, 0, 1, 4)
#define SD_CMU_CMU_E0_READ_VCO_CTUNE_3_0 GENMASK(3, 0)
#define SD_CMU_CMU_E0_READ_VCO_CTUNE_3_0_SET(x)\
@@ -2430,8 +2648,10 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_E0_PLL_LOL_UDL_GET(x)\
FIELD_GET(SD_CMU_CMU_E0_PLL_LOL_UDL, x)
-/* SD_CMU_TARGET:SD_CMU_CFG:SD_CMU_CFG */
-#define SD_CMU_CFG_SD_CMU_CFG(t) __REG(TARGET_SD_CMU_CFG, t, 14, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SD_CMU_TARGET:SD_CMU_CFG:SD_CMU_CFG */
+#define SD_CMU_CFG_SD_CMU_CFG(t) \
+ __REG(TARGET_SD_CMU_CFG, t, TSIZE(TC_SD_CMU_CFG), 0, 0, 1, 8, 0, 0, 1, \
+ 4)
#define SD_CMU_CFG_SD_CMU_CFG_CMU_RST BIT(0)
#define SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(x)\
@@ -2445,8 +2665,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_GET(x)\
FIELD_GET(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, x)
-/* SD_LANE_TARGET:SD_RESET:SD_SER_RST */
-#define SD_LANE_SD_SER_RST(t) __REG(TARGET_SD_LANE, t, 25, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SD_LANE_TARGET:SD_RESET:SD_SER_RST */
+#define SD_LANE_SD_SER_RST(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 0, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_SD_SER_RST_SER_RST BIT(0)
#define SD_LANE_SD_SER_RST_SER_RST_SET(x)\
@@ -2454,8 +2675,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_SER_RST_SER_RST_GET(x)\
FIELD_GET(SD_LANE_SD_SER_RST_SER_RST, x)
-/* SD_LANE_TARGET:SD_RESET:SD_DES_RST */
-#define SD_LANE_SD_DES_RST(t) __REG(TARGET_SD_LANE, t, 25, 0, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_RESET:SD_DES_RST */
+#define SD_LANE_SD_DES_RST(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 0, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_SD_DES_RST_DES_RST BIT(0)
#define SD_LANE_SD_DES_RST_DES_RST_SET(x)\
@@ -2463,8 +2685,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_DES_RST_DES_RST_GET(x)\
FIELD_GET(SD_LANE_SD_DES_RST_DES_RST, x)
-/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
-#define SD_LANE_SD_LANE_CFG(t) __REG(TARGET_SD_LANE, t, 25, 8, 0, 1, 8, 0, 0, 1, 4)
+/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
+#define SD_LANE_SD_LANE_CFG(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 8, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_SD_LANE_CFG_MACRO_RST BIT(0)
#define SD_LANE_SD_LANE_CFG_MACRO_RST_SET(x)\
@@ -2508,8 +2731,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_LANE_CFG_LANE_RX_RST_GET(x)\
FIELD_GET(SD_LANE_SD_LANE_CFG_LANE_RX_RST, x)
-/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
-#define SD_LANE_SD_LANE_STAT(t) __REG(TARGET_SD_LANE, t, 25, 8, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
+#define SD_LANE_SD_LANE_STAT(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 8, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_SD_LANE_STAT_PMA_RST_DONE BIT(0)
#define SD_LANE_SD_LANE_STAT_PMA_RST_DONE_SET(x)\
@@ -2529,9 +2753,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_SD_LANE_STAT_DBG_OBS, x)
-/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
-#define SD_LANE_QUIET_MODE_6G(t) \
- __REG(TARGET_SD_LANE, t, 25, 24, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_QUIET_MODE_6G(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 24, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(x)\
@@ -2539,8 +2763,9 @@ enum sparx5_serdes_target {
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_GET(x)\
FIELD_GET(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x)
-/* SD_LANE_TARGET:CFG_STAT_FX100:MISC */
-#define SD_LANE_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 0, 0, 1, 4)
+/* SD_LANE_TARGET:CFG_STAT_FX100:MISC */
+#define SD_LANE_MISC(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 56, 0, 1, 56, 0, 0, 1, 4)
#define SD_LANE_MISC_SD_125_RST_DIS BIT(0)
#define SD_LANE_MISC_SD_125_RST_DIS_SET(x)\
@@ -2560,14 +2785,16 @@ enum sparx5_serdes_target {
#define SD_LANE_MISC_MUX_ENA_GET(x)\
FIELD_GET(SD_LANE_MISC_MUX_ENA, x)
+/* SPARX5 ONLY */
#define SD_LANE_MISC_CORE_CLK_FREQ GENMASK(5, 4)
#define SD_LANE_MISC_CORE_CLK_FREQ_SET(x)\
FIELD_PREP(SD_LANE_MISC_CORE_CLK_FREQ, x)
#define SD_LANE_MISC_CORE_CLK_FREQ_GET(x)\
FIELD_GET(SD_LANE_MISC_CORE_CLK_FREQ, x)
-/* SD_LANE_TARGET:CFG_STAT_FX100:M_STAT_MISC */
-#define SD_LANE_M_STAT_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 36, 0, 1, 4)
+/* SD_LANE_TARGET:CFG_STAT_FX100:M_STAT_MISC */
+#define SD_LANE_M_STAT_MISC(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 56, 0, 1, 56, 36, 0, 1, 4)
#define SD_LANE_M_STAT_MISC_M_RIS_EDGE_PTR_ADJ_SUM GENMASK(21, 0)
#define SD_LANE_M_STAT_MISC_M_RIS_EDGE_PTR_ADJ_SUM_SET(x)\
@@ -2581,8 +2808,10 @@ enum sparx5_serdes_target {
#define SD_LANE_M_STAT_MISC_M_LOCK_CNT_GET(x)\
FIELD_GET(SD_LANE_M_STAT_MISC_M_LOCK_CNT, x)
-/* SD25G_CFG_TARGET:SD_RESET:SD_SER_RST */
-#define SD_LANE_25G_SD_SER_RST(t) __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_RESET:SD_SER_RST */
+#define SD_LANE_25G_SD_SER_RST(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_25G_SD_SER_RST_SER_RST BIT(0)
#define SD_LANE_25G_SD_SER_RST_SER_RST_SET(x)\
@@ -2590,8 +2819,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_SER_RST_SER_RST_GET(x)\
FIELD_GET(SD_LANE_25G_SD_SER_RST_SER_RST, x)
-/* SD25G_CFG_TARGET:SD_RESET:SD_DES_RST */
-#define SD_LANE_25G_SD_DES_RST(t) __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_RESET:SD_DES_RST */
+#define SD_LANE_25G_SD_DES_RST(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_25G_SD_DES_RST_DES_RST BIT(0)
#define SD_LANE_25G_SD_DES_RST_DES_RST_SET(x)\
@@ -2599,8 +2830,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_DES_RST_DES_RST_GET(x)\
FIELD_GET(SD_LANE_25G_SD_DES_RST_DES_RST, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
-#define SD_LANE_25G_SD_LANE_CFG(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
+#define SD_LANE_25G_SD_LANE_CFG(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 0, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_CFG_MACRO_RST BIT(0)
#define SD_LANE_25G_SD_LANE_CFG_MACRO_RST_SET(x)\
@@ -2698,8 +2931,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_CFG_PCS2PMA_TXMARGIN_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_CFG_PCS2PMA_TXMARGIN, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG2 */
-#define SD_LANE_25G_SD_LANE_CFG2(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG2 */
+#define SD_LANE_25G_SD_LANE_CFG2(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 4, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_CFG2_DATA_WIDTH_SEL GENMASK(2, 0)
#define SD_LANE_25G_SD_LANE_CFG2_DATA_WIDTH_SEL_SET(x)\
@@ -2767,8 +3002,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_CFG2_RXRATE_SEL_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_CFG2_RXRATE_SEL, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
-#define SD_LANE_25G_SD_LANE_STAT(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
+#define SD_LANE_25G_SD_LANE_STAT(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 8, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_STAT_PMA_RST_DONE BIT(0)
#define SD_LANE_25G_SD_LANE_STAT_PMA_RST_DONE_SET(x)\
@@ -2788,8 +3025,9 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x)
-/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
-#define SD_LANE_25G_QUIET_MODE_6G(t) \
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_25G_QUIET_MODE_6G(t) \
__REG(TARGET_SD_LANE_25G, t, 8, 28, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
index 7bbf729a7c90..7cb020dd3423 100644
--- a/drivers/phy/motorola/phy-cpcap-usb.c
+++ b/drivers/phy/motorola/phy-cpcap-usb.c
@@ -704,7 +704,7 @@ static void cpcap_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver cpcap_usb_phy_driver = {
.probe = cpcap_usb_phy_probe,
- .remove_new = cpcap_usb_phy_remove,
+ .remove = cpcap_usb_phy_remove,
.driver = {
.name = "cpcap-usb-phy",
.of_match_table = of_match_ptr(cpcap_usb_phy_id_table),
diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c
index 376d023a0aa9..152344e4f7e4 100644
--- a/drivers/phy/motorola/phy-mapphone-mdm6600.c
+++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c
@@ -655,7 +655,7 @@ static void phy_mdm6600_remove(struct platform_device *pdev)
static struct platform_driver phy_mdm6600_driver = {
.probe = phy_mdm6600_probe,
- .remove_new = phy_mdm6600_remove,
+ .remove = phy_mdm6600_remove,
.driver = {
.name = "phy-mapphone-mdm6600",
.pm = &phy_mdm6600_pm_ops,
diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/phy-airoha-pcie-regs.h
index bb1f679ca1df..b938a7b468fe 100644
--- a/drivers/phy/phy-airoha-pcie-regs.h
+++ b/drivers/phy/phy-airoha-pcie-regs.h
@@ -197,9 +197,9 @@
#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0)
#define REG_CSR_2L_RX0_REV0 0x00fc
-#define CSR_2L_PXP_VOS_PNINV GENMASK(3, 2)
-#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(6, 4)
-#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(10, 8)
+#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18)
+#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20)
+#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24)
#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100
#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8)
diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/phy-airoha-pcie.c
index 1e410eb41058..56e9ade8a9fd 100644
--- a/drivers/phy/phy-airoha-pcie.c
+++ b/drivers/phy/phy-airoha-pcie.c
@@ -459,7 +459,7 @@ static void airoha_pcie_phy_init_clk_out(struct airoha_pcie_phy *pcie_phy)
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
CSR_2L_PXP_CLKTX1_SR);
airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
- CSR_2L_PXP_PLL_RESERVE_MASK, 0xdd);
+ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
}
static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
@@ -471,9 +471,9 @@ static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
PCIE_SW_RX_RST);
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
}
static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
@@ -802,7 +802,7 @@ static void airoha_pcie_phy_init_ssc_jcpll(struct airoha_pcie_phy *pcie_phy)
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
CSR_2L_PXP_JCPLL_SDM_IFM);
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
- REG_CSR_2L_JCPLL_SDM_HREN);
+ CSR_2L_PXP_JCPLL_SDM_HREN);
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
CSR_2L_PXP_JCPLL_SDM_DI_EN);
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
diff --git a/drivers/phy/phy-lgm-usb.c b/drivers/phy/phy-lgm-usb.c
index 410729c7f513..eb7c6fed20d3 100644
--- a/drivers/phy/phy-lgm-usb.c
+++ b/drivers/phy/phy-lgm-usb.c
@@ -271,7 +271,7 @@ static struct platform_driver lgm_phy_driver = {
.of_match_table = intel_usb_phy_dt_ids,
},
.probe = phy_probe,
- .remove_new = phy_remove,
+ .remove = phy_remove,
};
module_platform_driver(lgm_phy_driver);
diff --git a/drivers/phy/phy-nxp-ptn3222.c b/drivers/phy/phy-nxp-ptn3222.c
new file mode 100644
index 000000000000..c6179d8701e6
--- /dev/null
+++ b/drivers/phy/phy-nxp-ptn3222.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define NUM_SUPPLIES 2
+
+struct ptn3222 {
+ struct i2c_client *client;
+ struct phy *phy;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data *supplies;
+};
+
+static int ptn3222_init(struct phy *phy)
+{
+ struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
+ int ret;
+
+ ret = regulator_bulk_enable(NUM_SUPPLIES, ptn3222->supplies);
+ if (ret)
+ return ret;
+
+ gpiod_set_value_cansleep(ptn3222->reset_gpio, 0);
+
+ return 0;
+}
+
+static int ptn3222_exit(struct phy *phy)
+{
+ struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
+
+ gpiod_set_value_cansleep(ptn3222->reset_gpio, 1);
+
+ return regulator_bulk_disable(NUM_SUPPLIES, ptn3222->supplies);
+}
+
+static const struct phy_ops ptn3222_ops = {
+ .init = ptn3222_init,
+ .exit = ptn3222_exit,
+ .owner = THIS_MODULE,
+};
+
+static const struct regulator_bulk_data ptn3222_supplies[NUM_SUPPLIES] = {
+ {
+ .supply = "vdd3v3",
+ .init_load_uA = 11000,
+ }, {
+ .supply = "vdd1v8",
+ .init_load_uA = 55000,
+ }
+};
+
+static int ptn3222_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct phy_provider *phy_provider;
+ struct ptn3222 *ptn3222;
+ int ret;
+
+ ptn3222 = devm_kzalloc(dev, sizeof(*ptn3222), GFP_KERNEL);
+ if (!ptn3222)
+ return -ENOMEM;
+
+ ptn3222->client = client;
+
+ ptn3222->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(ptn3222->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ptn3222->reset_gpio),
+ "unable to acquire reset gpio\n");
+
+ ret = devm_regulator_bulk_get_const(dev, NUM_SUPPLIES, ptn3222_supplies,
+ &ptn3222->supplies);
+ if (ret)
+ return ret;
+
+ ptn3222->phy = devm_phy_create(dev, dev->of_node, &ptn3222_ops);
+ if (IS_ERR(ptn3222->phy)) {
+ dev_err(dev, "failed to create PHY: %d\n", ret);
+ return PTR_ERR(ptn3222->phy);
+ }
+
+ phy_set_drvdata(ptn3222->phy, ptn3222);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct i2c_device_id ptn3222_table[] = {
+ { "ptn3222" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ptn3222_table);
+
+static const struct of_device_id ptn3222_of_table[] = {
+ { .compatible = "nxp,ptn3222" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ptn3222_of_table);
+
+static struct i2c_driver ptn3222_driver = {
+ .driver = {
+ .name = "ptn3222",
+ .of_match_table = ptn3222_of_table,
+ },
+ .probe = ptn3222_probe,
+ .id_table = ptn3222_table,
+};
+
+module_i2c_driver(ptn3222_driver);
+
+MODULE_DESCRIPTION("NXP PTN3222 eUSB2 Redriver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
index 3642a5d4f2f3..cae290a6e19f 100644
--- a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
@@ -257,12 +257,12 @@ static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
static struct platform_driver qcom_apq8064_sata_phy_driver = {
- .probe = qcom_apq8064_sata_phy_probe,
- .remove_new = qcom_apq8064_sata_phy_remove,
+ .probe = qcom_apq8064_sata_phy_probe,
+ .remove = qcom_apq8064_sata_phy_remove,
.driver = {
- .name = "qcom-apq8064-sata-phy",
- .of_match_table = qcom_apq8064_sata_phy_of_match,
- }
+ .name = "qcom-apq8064-sata-phy",
+ .of_match_table = qcom_apq8064_sata_phy_of_match,
+ },
};
module_platform_driver(qcom_apq8064_sata_phy_driver);
diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
index da2b32fb5b45..f1b51018683d 100644
--- a/drivers/phy/qualcomm/phy-qcom-edp.c
+++ b/drivers/phy/qualcomm/phy-qcom-edp.c
@@ -32,16 +32,8 @@
#define DP_PHY_PD_CTL 0x001c
#define DP_PHY_MODE 0x0020
-#define DP_PHY_AUX_CFG0 0x0024
-#define DP_PHY_AUX_CFG1 0x0028
-#define DP_PHY_AUX_CFG2 0x002C
-#define DP_PHY_AUX_CFG3 0x0030
-#define DP_PHY_AUX_CFG4 0x0034
-#define DP_PHY_AUX_CFG5 0x0038
-#define DP_PHY_AUX_CFG6 0x003C
-#define DP_PHY_AUX_CFG7 0x0040
-#define DP_PHY_AUX_CFG8 0x0044
-#define DP_PHY_AUX_CFG9 0x0048
+#define DP_AUX_CFG_SIZE 10
+#define DP_PHY_AUX_CFG(n) (0x24 + (0x04 * (n)))
#define DP_PHY_AUX_INTERRUPT_MASK 0x0058
@@ -90,6 +82,7 @@ struct phy_ver_ops {
struct qcom_edp_phy_cfg {
bool is_edp;
+ const u8 *aux_cfg;
const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
const struct phy_ver_ops *ver_ops;
};
@@ -186,11 +179,40 @@ static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
};
+static const u8 edp_phy_aux_cfg_v4[10] = {
+ 0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
+};
+
+static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
+ { 0x05, 0x11, 0x17, 0x1d },
+ { 0x05, 0x11, 0x18, 0xff },
+ { 0x06, 0x11, 0xff, 0xff },
+ { 0x00, 0xff, 0xff, 0xff }
+};
+
+static const u8 edp_pre_emp_hbr2_hbr3_v5[4][4] = {
+ { 0x0c, 0x15, 0x19, 0x1e },
+ { 0x0b, 0x15, 0x19, 0xff },
+ { 0x0e, 0x14, 0xff, 0xff },
+ { 0x0d, 0xff, 0xff, 0xff }
+};
+
+static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 = {
+ .swing_hbr_rbr = &edp_swing_hbr_rbr,
+ .swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
+ .pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr_v5,
+ .pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
+};
+
+static const u8 edp_phy_aux_cfg_v5[10] = {
+ 0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
+};
+
static int qcom_edp_phy_init(struct phy *phy)
{
struct qcom_edp *edp = phy_get_drvdata(phy);
+ u8 aux_cfg[DP_AUX_CFG_SIZE];
int ret;
- u8 cfg8;
ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
if (ret)
@@ -200,6 +222,8 @@ static int qcom_edp_phy_init(struct phy *phy)
if (ret)
goto out_disable_supplies;
+ memcpy(aux_cfg, edp->cfg->aux_cfg, sizeof(aux_cfg));
+
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
edp->edp + DP_PHY_PD_CTL);
@@ -222,22 +246,12 @@ static int qcom_edp_phy_init(struct phy *phy)
* even needed.
*/
if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
- cfg8 = 0xb7;
- else
- cfg8 = 0x37;
+ aux_cfg[8] = 0xb7;
writel(0xfc, edp->edp + DP_PHY_MODE);
- writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
- writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
- writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
- writel(0x00, edp->edp + DP_PHY_AUX_CFG3);
- writel(0x0a, edp->edp + DP_PHY_AUX_CFG4);
- writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
- writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
- writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
- writel(cfg8, edp->edp + DP_PHY_AUX_CFG8);
- writel(0x03, edp->edp + DP_PHY_AUX_CFG9);
+ for (int i = 0; i < DP_AUX_CFG_SIZE; i++)
+ writel(aux_cfg[i], edp->edp + DP_PHY_AUX_CFG(i));
writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
@@ -518,17 +532,27 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
.com_configure_ssc = qcom_edp_com_configure_ssc_v4,
};
+static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
+ .is_edp = false,
+ .aux_cfg = edp_phy_aux_cfg_v5,
+ .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
+ .ver_ops = &qcom_edp_phy_ops_v4,
+};
+
static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
.ver_ops = &qcom_edp_phy_ops_v4,
};
static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v4,
};
static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
.is_edp = true,
+ .aux_cfg = edp_phy_aux_cfg_v4,
.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v4,
};
@@ -707,6 +731,7 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
};
static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v6,
};
@@ -1108,6 +1133,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
}
static const struct of_device_id qcom_edp_phy_match_table[] = {
+ { .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, },
{ .compatible = "qcom,sc7280-edp-phy", .data = &sc7280_dp_phy_cfg, },
{ .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, },
{ .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, },
diff --git a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
index 68cc8e24f383..6bd1b3c75c77 100644
--- a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
+++ b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
@@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(of, eusb2_repeater_of_match_table);
static struct platform_driver eusb2_repeater_driver = {
.probe = eusb2_repeater_probe,
- .remove_new = eusb2_repeater_remove,
+ .remove = eusb2_repeater_remove,
.driver = {
.name = "qcom-eusb2-repeater",
.of_match_table = eusb2_repeater_of_match_table,
diff --git a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
index f0a72b82c770..f5eb0bdac418 100644
--- a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
@@ -184,11 +184,11 @@ static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
static struct platform_driver qcom_ipq806x_sata_phy_driver = {
- .probe = qcom_ipq806x_sata_phy_probe,
- .remove_new = qcom_ipq806x_sata_phy_remove,
+ .probe = qcom_ipq806x_sata_phy_probe,
+ .remove = qcom_ipq806x_sata_phy_remove,
.driver = {
- .name = "qcom-ipq806x-sata-phy",
- .of_match_table = qcom_ipq806x_sata_phy_of_match,
+ .name = "qcom-ipq806x-sata-phy",
+ .of_match_table = qcom_ipq806x_sata_phy_of_match,
}
};
module_platform_driver(qcom_ipq806x_sata_phy_driver);
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index 643045c9024e..3bae39381fd0 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -3483,7 +3483,7 @@ static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
}
#endif
-static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np)
+static int qmp_combo_parse_dt_legacy_dp(struct qmp_combo *qmp, struct device_node *np)
{
struct device *dev = qmp->dev;
@@ -3510,7 +3510,7 @@ static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_nod
return 0;
}
-static int qmp_combo_parse_dt_lecacy_usb(struct qmp_combo *qmp, struct device_node *np)
+static int qmp_combo_parse_dt_legacy_usb(struct qmp_combo *qmp, struct device_node *np)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
@@ -3576,11 +3576,11 @@ static int qmp_combo_parse_dt_legacy(struct qmp_combo *qmp, struct device_node *
if (IS_ERR(qmp->dp_serdes))
return PTR_ERR(qmp->dp_serdes);
- ret = qmp_combo_parse_dt_lecacy_usb(qmp, usb_np);
+ ret = qmp_combo_parse_dt_legacy_usb(qmp, usb_np);
if (ret)
return ret;
- ret = qmp_combo_parse_dt_lecacy_dp(qmp, dp_np);
+ ret = qmp_combo_parse_dt_legacy_dp(qmp, dp_np);
if (ret)
return ret;
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 36aaac34e6c6..873f2f9844c6 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -34,6 +34,8 @@
#include "phy-qcom-qmp-pcs-pcie-v5_20.h"
#include "phy-qcom-qmp-pcs-pcie-v6.h"
#include "phy-qcom-qmp-pcs-pcie-v6_20.h"
+#include "phy-qcom-qmp-pcs-pcie-v6_30.h"
+#include "phy-qcom-qmp-pcs-v6_30.h"
#include "phy-qcom-qmp-pcie-qhp.h"
#define PHY_INIT_COMPLETE_TIMEOUT 10000
@@ -1344,6 +1346,154 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0x8a),
};
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x26),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_POST_DIV_MUX, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x46),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MISC_1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_txz_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_2, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_3, 0x51),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN, 0x34),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_rxz_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_BKUP_CTRL1, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x45),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x39),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0x23),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x58),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0x60),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x69),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x3a, BIT(0)),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_LOCK_DETECT_CONFIG2, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_G3S2_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_RX_SIGDET_LVL, 0x99),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_ALIGN_DETECT_CONFIG7, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_EQ_CONFIG4, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_EQ_CONFIG5, 0x22),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_TX_RX_CONFIG, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_TX_RX_CONFIG2, 0x02),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_OSC_DTCT_ACTIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_EQ_CONFIG1, 0x16),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_EQ_CONFIG5, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG1, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG3, 0x28),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG5, 0x18),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G3_FOM_EQ_CONFIG5, 0x7a),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_FOM_EQ_CONFIG5, 0x8a),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G3_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_TX_RX_CONFIG, 0xc0),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_POWER_STATE_CONFIG2, 0x1d),
+};
+
static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
@@ -2582,6 +2732,8 @@ struct qmp_pcie_offsets {
u16 rx;
u16 tx2;
u16 rx2;
+ u16 txz;
+ u16 rxz;
u16 ln_shrd;
};
@@ -2592,6 +2744,10 @@ struct qmp_phy_cfg_tbls {
int tx_num;
const struct qmp_phy_init_tbl *rx;
int rx_num;
+ const struct qmp_phy_init_tbl *txz;
+ int txz_num;
+ const struct qmp_phy_init_tbl *rxz;
+ int rxz_num;
const struct qmp_phy_init_tbl *pcs;
int pcs_num;
const struct qmp_phy_init_tbl *pcs_misc;
@@ -2659,6 +2815,8 @@ struct qmp_pcie {
void __iomem *rx;
void __iomem *tx2;
void __iomem *rx2;
+ void __iomem *txz;
+ void __iomem *rxz;
void __iomem *ln_shrd;
void __iomem *port_b;
@@ -2826,6 +2984,17 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_20 = {
.ln_shrd = 0x0e00,
};
+static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_30 = {
+ .serdes = 0x8800,
+ .pcs = 0x9000,
+ .pcs_misc = 0x9800,
+ .tx = 0x0000,
+ .rx = 0x0200,
+ .txz = 0xe000,
+ .rxz = 0xe200,
+ .ln_shrd = 0x8000,
+};
+
static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
.lanes = 1,
@@ -3704,6 +3873,38 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = {
.has_nocsr_reset = true,
};
+static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = {
+ .lanes = 8,
+
+ .offsets = &qmp_pcie_offsets_v6_30,
+ .tbls = {
+ .serdes = x1e80100_qmp_gen4x8_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_serdes_tbl),
+ .rx = x1e80100_qmp_gen4x8_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_rx_tbl),
+ .txz = x1e80100_qmp_gen4x8_pcie_txz_tbl,
+ .txz_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_txz_tbl),
+ .rxz = x1e80100_qmp_gen4x8_pcie_rxz_tbl,
+ .rxz_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_rxz_tbl),
+ .pcs = x1e80100_qmp_gen4x8_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_pcs_tbl),
+ .pcs_misc = x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl),
+ .ln_shrd = x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl,
+ .ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl),
+ },
+
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .vreg_list = sm8550_qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
+ .regs = pciephy_v6_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS_4_20,
+ .has_nocsr_reset = true,
+};
+
static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -3751,6 +3952,13 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
+ /*
+ * Tx/Rx registers that require different settings than
+ * txz/rxz must be programmed after txz/rxz.
+ */
+ qmp_configure(qmp->dev, qmp->txz, tbls->txz, tbls->txz_num);
+ qmp_configure(qmp->dev, qmp->rxz, tbls->rxz, tbls->rxz_num);
+
qmp_configure_lane(qmp->dev, tx, tbls->tx, tbls->tx_num, 1);
qmp_configure_lane(qmp->dev, rx, tbls->rx, tbls->rx_num, 1);
@@ -4293,6 +4501,9 @@ static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
return PTR_ERR(qmp->port_b);
}
+ qmp->txz = base + offs->txz;
+ qmp->rxz = base + offs->rxz;
+
if (cfg->tbls.ln_shrd)
qmp->ln_shrd = base + offs->ln_shrd;
@@ -4478,6 +4689,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,x1e80100-qmp-gen4x4-pcie-phy",
.data = &x1e80100_qmp_gen4x4_pciephy_cfg,
+ }, {
+ .compatible = "qcom,x1e80100-qmp-gen4x8-pcie-phy",
+ .data = &x1e80100_qmp_gen4x8_pciephy_cfg,
},
{ },
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h
new file mode 100644
index 000000000000..5a58ff197e6e
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_PCIE_V6_30_H_
+#define QCOM_PHY_QMP_PCS_PCIE_V6_30_H_
+
+/* Only for QMP V6_30 PHY - PCIE have different offsets than V6 */
+#define QPHY_PCIE_V6_30_PCS_POWER_STATE_CONFIG2 0x014
+#define QPHY_PCIE_V6_30_PCS_TX_RX_CONFIG 0x020
+#define QPHY_PCIE_V6_30_PCS_ENDPOINT_REFCLK_DRIVE 0x024
+#define QPHY_PCIE_V6_30_PCS_OSC_DTCT_ACTIONS 0x098
+#define QPHY_PCIE_V6_30_PCS_EQ_CONFIG1 0x0a8
+#define QPHY_PCIE_V6_30_PCS_G3_RXEQEVAL_TIME 0x0f8
+#define QPHY_PCIE_V6_30_PCS_G4_RXEQEVAL_TIME 0x0fc
+#define QPHY_PCIE_V6_30_PCS_G4_EQ_CONFIG5 0x110
+#define QPHY_PCIE_V6_30_PCS_G4_PRE_GAIN 0x164
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG1 0x184
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG3 0x18c
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG5 0x194
+#define QPHY_PCIE_V6_30_PCS_G3_FOM_EQ_CONFIG5 0x1b4
+#define QPHY_PCIE_V6_30_PCS_G4_FOM_EQ_CONFIG5 0x1c8
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h
new file mode 100644
index 000000000000..369120d88bc2
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_V6_30_H_
+#define QCOM_PHY_QMP_PCS_V6_30_H_
+
+/* Only for QMP V6_30 PHY - PCIe PCS registers */
+#define QPHY_V6_30_PCS_LOCK_DETECT_CONFIG2 0x0cc
+#define QPHY_V6_30_PCS_G3S2_PRE_GAIN 0x17c
+#define QPHY_V6_30_PCS_RX_SIGDET_LVL 0x194
+#define QPHY_V6_30_PCS_ALIGN_DETECT_CONFIG7 0x1dc
+#define QPHY_V6_30_PCS_TX_RX_CONFIG 0x1e0
+#define QPHY_V6_30_PCS_TX_RX_CONFIG2 0x1e4
+#define QPHY_V6_30_PCS_EQ_CONFIG4 0x1fc
+#define QPHY_V6_30_PCS_EQ_CONFIG5 0x200
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
index 1246d3bc8b92..acd6075bf6d9 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
@@ -871,6 +871,16 @@ static const struct qmp_phy_init_tbl sdx75_usb3_uniphy_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00),
};
+static const struct qmp_phy_init_tbl qcs8300_usb3_uniphy_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0xf2),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
+};
+
static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5),
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82),
@@ -989,6 +999,40 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
};
+static const struct qmp_phy_init_tbl qcs8300_usb3_uniphy_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xec),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00),
+};
+
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd),
@@ -1462,6 +1506,24 @@ static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = {
.regs = qmp_v5_usb3phy_regs_layout,
};
+static const struct qmp_phy_cfg qcs8300_usb3_uniphy_cfg = {
+ .offsets = &qmp_usb_offsets_v5,
+
+ .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl),
+ .tx_tbl = qcs8300_usb3_uniphy_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qcs8300_usb3_uniphy_tx_tbl),
+ .rx_tbl = qcs8300_usb3_uniphy_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(qcs8300_usb3_uniphy_rx_tbl),
+ .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl),
+ .pcs_usb_tbl = sa8775p_usb3_uniphy_pcs_usb_tbl,
+ .pcs_usb_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_usb_tbl),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v5_usb3phy_regs_layout,
+};
+
static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = {
.offsets = &qmp_usb_offsets_v5,
@@ -2248,6 +2310,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
.compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg,
}, {
+ .compatible = "qcom,qcs8300-qmp-usb3-uni-phy",
+ .data = &qcs8300_usb3_uniphy_cfg,
+ }, {
.compatible = "qcom,qdu1000-qmp-usb3-uni-phy",
.data = &qdu1000_usb3_uniphy_cfg,
}, {
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index e3ad7cea5109..248550ef98ca 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -1023,6 +1023,8 @@ static int rtk_usb2phy_probe(struct platform_device *pdev)
rtk_phy->dev = &pdev->dev;
rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
@@ -1298,7 +1300,7 @@ MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
static struct platform_driver rtk_usb2phy_driver = {
.probe = rtk_usb2phy_probe,
- .remove_new = rtk_usb2phy_remove,
+ .remove = rtk_usb2phy_remove,
.driver = {
.name = "rtk-usb2phy",
.of_match_table = usbphy_rtk_dt_match,
diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c
index dfcf4b921bba..cce453686db2 100644
--- a/drivers/phy/realtek/phy-rtk-usb3.c
+++ b/drivers/phy/realtek/phy-rtk-usb3.c
@@ -577,6 +577,8 @@ static int rtk_usb3phy_probe(struct platform_device *pdev)
rtk_phy->dev = &pdev->dev;
rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
@@ -734,7 +736,7 @@ MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
static struct platform_driver rtk_usb3phy_driver = {
.probe = rtk_usb3phy_probe,
- .remove_new = rtk_usb3phy_remove,
+ .remove = rtk_usb3phy_remove,
.driver = {
.name = "rtk-usb3phy",
.of_match_table = usbphy_rtk_dt_match,
diff --git a/drivers/phy/renesas/phy-rcar-gen3-pcie.c b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
index 0ce7e9c94444..feca4cb2ff4d 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-pcie.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
@@ -132,11 +132,11 @@ static void rcar_gen3_phy_pcie_remove(struct platform_device *pdev)
static struct platform_driver rcar_gen3_phy_driver = {
.driver = {
- .name = "phy_rcar_gen3_pcie",
- .of_match_table = rcar_gen3_phy_pcie_match_table,
+ .name = "phy_rcar_gen3_pcie",
+ .of_match_table = rcar_gen3_phy_pcie_match_table,
},
- .probe = rcar_gen3_phy_pcie_probe,
- .remove_new = rcar_gen3_phy_pcie_remove,
+ .probe = rcar_gen3_phy_pcie_probe,
+ .remove = rcar_gen3_phy_pcie_remove,
};
module_platform_driver(rcar_gen3_phy_driver);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 58e123305152..775f4f973a6c 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -825,7 +825,7 @@ static struct platform_driver rcar_gen3_phy_usb2_driver = {
.of_match_table = rcar_gen3_phy_usb2_match_table,
},
.probe = rcar_gen3_phy_usb2_probe,
- .remove_new = rcar_gen3_phy_usb2_remove,
+ .remove = rcar_gen3_phy_usb2_remove,
};
module_platform_driver(rcar_gen3_phy_usb2_driver);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb3.c b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
index e2d630edd992..5c267d148c90 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb3.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
@@ -206,11 +206,11 @@ static void rcar_gen3_phy_usb3_remove(struct platform_device *pdev)
static struct platform_driver rcar_gen3_phy_usb3_driver = {
.driver = {
- .name = "phy_rcar_gen3_usb3",
- .of_match_table = rcar_gen3_phy_usb3_match_table,
+ .name = "phy_rcar_gen3_usb3",
+ .of_match_table = rcar_gen3_phy_usb3_match_table,
},
- .probe = rcar_gen3_phy_usb3_probe,
- .remove_new = rcar_gen3_phy_usb3_remove,
+ .probe = rcar_gen3_phy_usb3_probe,
+ .remove = rcar_gen3_phy_usb3_remove,
};
module_platform_driver(rcar_gen3_phy_usb3_driver);
diff --git a/drivers/phy/renesas/r8a779f0-ether-serdes.c b/drivers/phy/renesas/r8a779f0-ether-serdes.c
index f1f1da4a0b1f..3b2d8cef75e5 100644
--- a/drivers/phy/renesas/r8a779f0-ether-serdes.c
+++ b/drivers/phy/renesas/r8a779f0-ether-serdes.c
@@ -404,7 +404,7 @@ static void r8a779f0_eth_serdes_remove(struct platform_device *pdev)
static struct platform_driver r8a779f0_eth_serdes_driver_platform = {
.probe = r8a779f0_eth_serdes_probe,
- .remove_new = r8a779f0_eth_serdes_remove,
+ .remove = r8a779f0_eth_serdes_remove,
.driver = {
.name = "r8a779f0_eth_serdes",
.of_match_table = r8a779f0_eth_serdes_of_table,
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
index 98c92d6c482f..2ab99e1d47eb 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
@@ -472,7 +472,7 @@ static struct platform_driver rockchip_inno_csidphy_driver = {
.of_match_table = rockchip_inno_csidphy_match_id,
},
.probe = rockchip_inno_csidphy_probe,
- .remove_new = rockchip_inno_csidphy_remove,
+ .remove = rockchip_inno_csidphy_remove,
};
module_platform_driver(rockchip_inno_csidphy_driver);
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
index 6405943a2676..d5b1a4e2f7d3 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
@@ -784,7 +784,7 @@ static struct platform_driver inno_dsidphy_driver = {
.of_match_table = of_match_ptr(inno_dsidphy_of_match),
},
.probe = inno_dsidphy_probe,
- .remove_new = inno_dsidphy_remove,
+ .remove = inno_dsidphy_remove,
};
module_platform_driver(inno_dsidphy_driver);
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 053bd62e31ba..8dcc2bb777b5 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -1424,8 +1424,8 @@ static const struct of_device_id inno_hdmi_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, inno_hdmi_phy_of_match);
static struct platform_driver inno_hdmi_phy_driver = {
- .probe = inno_hdmi_phy_probe,
- .remove_new = inno_hdmi_phy_remove,
+ .probe = inno_hdmi_phy_probe,
+ .remove = inno_hdmi_phy_remove,
.driver = {
.name = "inno-hdmi-phy",
.of_match_table = inno_hdmi_phy_of_match,
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 4f71373ae6e1..96f3d868a526 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -229,9 +229,10 @@ struct rockchip_usb2phy_port {
* @dev: pointer to device.
* @grf: General Register Files regmap.
* @usbgrf: USB General Register Files regmap.
- * @clk: clock struct of phy input clk.
+ * @clks: array of phy input clocks.
* @clk480m: clock struct of phy output clk.
* @clk480m_hw: clock struct of phy output clk management.
+ * @num_clks: number of phy input clocks.
* @phy_reset: phy reset control.
* @chg_state: states involved in USB charger detection.
* @chg_type: USB charger types.
@@ -246,9 +247,10 @@ struct rockchip_usb2phy {
struct device *dev;
struct regmap *grf;
struct regmap *usbgrf;
- struct clk *clk;
+ struct clk_bulk_data *clks;
struct clk *clk480m;
struct clk_hw clk480m_hw;
+ int num_clks;
struct reset_control *phy_reset;
enum usb_chg_state chg_state;
enum power_supply_type chg_type;
@@ -310,6 +312,13 @@ static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy)
return 0;
}
+static void rockchip_usb2phy_clk_bulk_disable(void *data)
+{
+ struct rockchip_usb2phy *rphy = data;
+
+ clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
+}
+
static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
@@ -376,7 +385,9 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
{
struct device_node *node = rphy->dev->of_node;
struct clk_init_data init;
+ struct clk *refclk = NULL;
const char *clk_name;
+ int i;
int ret = 0;
init.flags = 0;
@@ -386,8 +397,15 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
/* optional override of the clockname */
of_property_read_string(node, "clock-output-names", &init.name);
- if (rphy->clk) {
- clk_name = __clk_get_name(rphy->clk);
+ for (i = 0; i < rphy->num_clks; i++) {
+ if (!strncmp(rphy->clks[i].id, "phyclk", 6)) {
+ refclk = rphy->clks[i].clk;
+ break;
+ }
+ }
+
+ if (!IS_ERR(refclk)) {
+ clk_name = __clk_get_name(refclk);
init.parent_names = &clk_name;
init.num_parents = 1;
} else {
@@ -418,30 +436,28 @@ err_ret:
static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
{
- int ret;
struct device_node *node = rphy->dev->of_node;
struct extcon_dev *edev;
+ int ret;
if (of_property_read_bool(node, "extcon")) {
edev = extcon_get_edev_by_phandle(rphy->dev, 0);
- if (IS_ERR(edev)) {
- if (PTR_ERR(edev) != -EPROBE_DEFER)
- dev_err(rphy->dev, "Invalid or missing extcon\n");
- return PTR_ERR(edev);
- }
+ if (IS_ERR(edev))
+ return dev_err_probe(rphy->dev, PTR_ERR(edev),
+ "invalid or missing extcon\n");
} else {
/* Initialize extcon device */
edev = devm_extcon_dev_allocate(rphy->dev,
rockchip_usb2phy_extcon_cable);
if (IS_ERR(edev))
- return -ENOMEM;
+ return dev_err_probe(rphy->dev, PTR_ERR(edev),
+ "failed to allocate extcon device\n");
ret = devm_extcon_dev_register(rphy->dev, edev);
- if (ret) {
- dev_err(rphy->dev, "failed to register extcon device\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(rphy->dev, ret,
+ "failed to register extcon device\n");
}
rphy->edev = edev;
@@ -1327,7 +1343,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
struct rockchip_usb2phy *rphy;
const struct rockchip_usb2phy_cfg *phy_cfgs;
unsigned int reg;
- int index, ret;
+ int index = 0, ret;
rphy = devm_kzalloc(dev, sizeof(*rphy), GFP_KERNEL);
if (!rphy)
@@ -1339,9 +1355,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
dev_err(dev, "failed to locate usbgrf\n");
return PTR_ERR(rphy->grf);
}
- }
-
- else {
+ } else {
rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(rphy->grf))
return PTR_ERR(rphy->grf);
@@ -1358,16 +1372,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
}
if (of_property_read_u32_index(np, "reg", 0, &reg)) {
- dev_err(dev, "the reg property is not assigned in %pOFn node\n",
- np);
+ dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
return -EINVAL;
}
/* support address_cells=2 */
if (of_property_count_u32_elems(np, "reg") > 2 && reg == 0) {
if (of_property_read_u32_index(np, "reg", 1, &reg)) {
- dev_err(dev, "the reg property is not assigned in %pOFn node\n",
- np);
+ dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
return -EINVAL;
}
}
@@ -1386,8 +1398,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (ret)
return ret;
- /* find out a proper config which can be matched with dt. */
- index = 0;
+ /* find a proper config that can be matched with the DT */
do {
if (phy_cfgs[index].reg == reg) {
rphy->phy_cfg = &phy_cfgs[index];
@@ -1406,17 +1417,25 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (IS_ERR(rphy->phy_reset))
return PTR_ERR(rphy->phy_reset);
- rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk");
- if (IS_ERR(rphy->clk)) {
- return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk),
- "failed to get phyclk\n");
- }
+ ret = devm_clk_bulk_get_all(dev, &rphy->clks);
+ if (ret == -EPROBE_DEFER)
+ return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
+ "failed to get phy clock\n");
+
+ /* Clocks are optional */
+ rphy->num_clks = ret < 0 ? 0 : ret;
ret = rockchip_usb2phy_clk480m_register(rphy);
- if (ret) {
- dev_err(dev, "failed to register 480m output clock\n");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register 480m output clock\n");
+
+ ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable phy clock\n");
+
+ ret = devm_add_action_or_reset(dev, rockchip_usb2phy_clk_bulk_disable, rphy);
+ if (ret)
return ret;
- }
if (rphy->phy_cfg->phy_tuning) {
ret = rphy->phy_cfg->phy_tuning(rphy);
@@ -1436,8 +1455,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
if (IS_ERR(phy)) {
- dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
- ret = PTR_ERR(phy);
+ ret = dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
goto put_child;
}
@@ -1446,13 +1464,11 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
/* initialize otg/host port separately */
if (of_node_name_eq(child_np, "host-port")) {
- ret = rockchip_usb2phy_host_port_init(rphy, rport,
- child_np);
+ ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
if (ret)
goto put_child;
} else {
- ret = rockchip_usb2phy_otg_port_init(rphy, rport,
- child_np);
+ ret = rockchip_usb2phy_otg_port_init(rphy, rport, child_np);
if (ret)
goto put_child;
}
@@ -1474,8 +1490,7 @@ next_child:
"rockchip_usb2phy",
rphy);
if (ret) {
- dev_err(rphy->dev,
- "failed to request usb2phy irq handle\n");
+ dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n");
goto put_child;
}
}
@@ -1495,6 +1510,30 @@ static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy)
BIT(2) << BIT_WRITEABLE_SHIFT | 0);
}
+static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
+{
+ int ret;
+ u32 reg = rphy->phy_cfg->reg;
+
+ /* Deassert SIDDQ to power on analog block */
+ ret = regmap_write(rphy->grf, reg + 0x0010, GENMASK(29, 29) | 0x0000);
+ if (ret)
+ return ret;
+
+ /* Do reset after exit IDDQ mode */
+ ret = rockchip_usb2phy_reset(rphy);
+ if (ret)
+ return ret;
+
+ /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
+ ret |= regmap_write(rphy->grf, reg + 0x000c, GENMASK(27, 24) | 0x0900);
+
+ /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
+ ret |= regmap_write(rphy->grf, reg + 0x0010, GENMASK(20, 19) | 0x0010);
+
+ return ret;
+}
+
static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy)
{
int ret;
@@ -1923,6 +1962,84 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
{ /* sentinel */ }
};
+static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
+ {
+ .reg = 0x0,
+ .num_ports = 1,
+ .phy_tuning = rk3576_usb2phy_tuning,
+ .clkout_ctl = { 0x0008, 0, 0, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x0000, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x00c0, 1, 1, 0, 1 },
+ .bvalid_det_st = { 0x00c4, 1, 1, 0, 1 },
+ .bvalid_det_clr = { 0x00c8, 1, 1, 0, 1 },
+ .ls_det_en = { 0x00c0, 0, 0, 0, 1 },
+ .ls_det_st = { 0x00c4, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x00c8, 0, 0, 0, 1 },
+ .disfall_en = { 0x00c0, 6, 6, 0, 1 },
+ .disfall_st = { 0x00c4, 6, 6, 0, 1 },
+ .disfall_clr = { 0x00c8, 6, 6, 0, 1 },
+ .disrise_en = { 0x00c0, 5, 5, 0, 1 },
+ .disrise_st = { 0x00c4, 5, 5, 0, 1 },
+ .disrise_clr = { 0x00c8, 5, 5, 0, 1 },
+ .utmi_avalid = { 0x0080, 1, 1, 0, 1 },
+ .utmi_bvalid = { 0x0080, 0, 0, 0, 1 },
+ .utmi_ls = { 0x0080, 5, 4, 0, 1 },
+ }
+ },
+ .chg_det = {
+ .cp_det = { 0x0080, 8, 8, 0, 1 },
+ .dcp_det = { 0x0080, 8, 8, 0, 1 },
+ .dp_det = { 0x0080, 9, 9, 1, 0 },
+ .idm_sink_en = { 0x0010, 5, 5, 1, 0 },
+ .idp_sink_en = { 0x0010, 5, 5, 0, 1 },
+ .idp_src_en = { 0x0010, 14, 14, 0, 1 },
+ .rdm_pdwn_en = { 0x0010, 14, 14, 0, 1 },
+ .vdm_src_en = { 0x0010, 7, 6, 0, 3 },
+ .vdp_src_en = { 0x0010, 7, 6, 0, 3 },
+ },
+ },
+ {
+ .reg = 0x2000,
+ .num_ports = 1,
+ .phy_tuning = rk3576_usb2phy_tuning,
+ .clkout_ctl = { 0x2008, 0, 0, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x2000, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x20c0, 1, 1, 0, 1 },
+ .bvalid_det_st = { 0x20c4, 1, 1, 0, 1 },
+ .bvalid_det_clr = { 0x20c8, 1, 1, 0, 1 },
+ .ls_det_en = { 0x20c0, 0, 0, 0, 1 },
+ .ls_det_st = { 0x20c4, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x20c8, 0, 0, 0, 1 },
+ .disfall_en = { 0x20c0, 6, 6, 0, 1 },
+ .disfall_st = { 0x20c4, 6, 6, 0, 1 },
+ .disfall_clr = { 0x20c8, 6, 6, 0, 1 },
+ .disrise_en = { 0x20c0, 5, 5, 0, 1 },
+ .disrise_st = { 0x20c4, 5, 5, 0, 1 },
+ .disrise_clr = { 0x20c8, 5, 5, 0, 1 },
+ .utmi_avalid = { 0x2080, 1, 1, 0, 1 },
+ .utmi_bvalid = { 0x2080, 0, 0, 0, 1 },
+ .utmi_ls = { 0x2080, 5, 4, 0, 1 },
+ }
+ },
+ .chg_det = {
+ .cp_det = { 0x2080, 8, 8, 0, 1 },
+ .dcp_det = { 0x2080, 8, 8, 0, 1 },
+ .dp_det = { 0x2080, 9, 9, 1, 0 },
+ .idm_sink_en = { 0x2010, 5, 5, 1, 0 },
+ .idp_sink_en = { 0x2010, 5, 5, 0, 1 },
+ .idp_src_en = { 0x2010, 14, 14, 0, 1 },
+ .rdm_pdwn_en = { 0x2010, 14, 14, 0, 1 },
+ .vdm_src_en = { 0x2010, 7, 6, 0, 3 },
+ .vdp_src_en = { 0x2010, 7, 6, 0, 3 },
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
{
.reg = 0x0000,
@@ -2094,6 +2211,7 @@ static const struct of_device_id rockchip_usb2phy_dt_match[] = {
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
{ .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
+ { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
{ .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
{}
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 9f084697dd05..ceab9c71d3b5 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -256,13 +256,10 @@ struct ropll_config {
};
enum rk_hdptx_reset {
- RST_PHY = 0,
- RST_APB,
+ RST_APB = 0,
RST_INIT,
RST_CMN,
RST_LANE,
- RST_ROPLL,
- RST_LCPLL,
RST_MAX
};
@@ -665,11 +662,6 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
{
u32 val;
- /* reset phy and apb, or phy locked flag may keep 1 */
- reset_control_assert(hdptx->rsts[RST_PHY].rstc);
- usleep_range(20, 30);
- reset_control_deassert(hdptx->rsts[RST_PHY].rstc);
-
reset_control_assert(hdptx->rsts[RST_APB].rstc);
usleep_range(20, 30);
reset_control_deassert(hdptx->rsts[RST_APB].rstc);
@@ -792,10 +784,6 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
rk_hdptx_pre_power_up(hdptx);
- reset_control_assert(hdptx->rsts[RST_ROPLL].rstc);
- usleep_range(20, 30);
- reset_control_deassert(hdptx->rsts[RST_ROPLL].rstc);
-
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_cmn_init_seq);
@@ -1098,13 +1086,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(hdptx->regmap),
"Failed to init regmap\n");
- hdptx->rsts[RST_PHY].id = "phy";
hdptx->rsts[RST_APB].id = "apb";
hdptx->rsts[RST_INIT].id = "init";
hdptx->rsts[RST_CMN].id = "cmn";
hdptx->rsts[RST_LANE].id = "lane";
- hdptx->rsts[RST_ROPLL].id = "ropll";
- hdptx->rsts[RST_LCPLL].id = "lcpll";
ret = devm_reset_control_bulk_get_exclusive(dev, RST_MAX, hdptx->rsts);
if (ret)
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 4efcb78b0ab1..122ae0fdc785 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -1210,7 +1210,7 @@ MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
static struct platform_driver rockchip_typec_phy_driver = {
.probe = rockchip_typec_phy_probe,
- .remove_new = rockchip_typec_phy_remove,
+ .remove = rockchip_typec_phy_remove,
.driver = {
.name = "rockchip-typec-phy",
.of_match_table = rockchip_typec_phy_dt_ids,
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 2c51e5c62d3e..5b1e8a3806ed 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1538,6 +1538,43 @@ static const char * const rk_udphy_rst_list[] = {
"init", "cmn", "lane", "pcs_apb", "pma_apb"
};
+static const struct rk_udphy_cfg rk3576_udphy_cfgs = {
+ .num_phys = 1,
+ .phy_ids = { 0x2b010000 },
+ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list),
+ .rst_list = rk_udphy_rst_list,
+ .grfcfg = {
+ /* u2phy-grf */
+ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0010, 1, 0, 0x2, 0x3),
+ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0000, 15, 14, 0x1, 0x3),
+
+ /* usb-grf */
+ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x0030, 15, 0, 0x1100, 0x0188),
+
+ /* usbdpphy-grf */
+ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1),
+ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1),
+ },
+ .vogrfcfg = {
+ {
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
+ .dp_lane_reg = 0x0000,
+ },
+ },
+ .dp_tx_ctrl_cfg = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+ .dp_tx_ctrl_cfg_typec = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+};
+
static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
.num_phys = 2,
.phy_ids = {
@@ -1585,6 +1622,10 @@ static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
static const struct of_device_id rk_udphy_dt_match[] = {
{
+ .compatible = "rockchip,rk3576-usbdp-phy",
+ .data = &rk3576_udphy_cfgs
+ },
+ {
.compatible = "rockchip,rk3588-usbdp-phy",
.data = &rk3588_udphy_cfgs
},
diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig
index 3fc3d0781fb8..304614b6dabf 100644
--- a/drivers/phy/st/Kconfig
+++ b/drivers/phy/st/Kconfig
@@ -33,6 +33,17 @@ config PHY_STIH407_USB
Enable this support to enable the picoPHY device used by USB2
and USB3 controllers on STMicroelectronics STiH407 SoC families.
+config PHY_STM32_COMBOPHY
+ tristate "STMicroelectronics COMBOPHY driver for STM32MP25"
+ depends on ARCH_STM32 || COMPILE_TEST
+ select GENERIC_PHY
+ help
+ Enable this to support the COMBOPHY device used by USB3 or PCIe
+ controllers on STMicroelectronics STM32MP25 SoC.
+ This driver controls the COMBOPHY block to generate the PCIe 100Mhz
+ reference clock from either the external clock generator or HSE
+ internal SoC clock source.
+
config PHY_STM32_USBPHYC
tristate "STMicroelectronics STM32 USB HS PHY Controller driver"
depends on ARCH_STM32 || COMPILE_TEST
diff --git a/drivers/phy/st/Makefile b/drivers/phy/st/Makefile
index c862dd937b64..cb80e954ea9f 100644
--- a/drivers/phy/st/Makefile
+++ b/drivers/phy/st/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
+obj-$(CONFIG_PHY_STM32_COMBOPHY) += phy-stm32-combophy.o
obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
diff --git a/drivers/phy/st/phy-stm32-combophy.c b/drivers/phy/st/phy-stm32-combophy.c
new file mode 100644
index 000000000000..765bb34fe358
--- /dev/null
+++ b/drivers/phy/st/phy-stm32-combophy.c
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics COMBOPHY STM32MP25 Controller driver.
+ *
+ * Copyright (C) 2024 STMicroelectronics
+ * Author: Christian Bruel <christian.bruel@foss.st.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <dt-bindings/phy/phy.h>
+
+#define SYSCFG_COMBOPHY_CR1 0x4c00
+#define SYSCFG_COMBOPHY_CR2 0x4c04
+#define SYSCFG_COMBOPHY_CR4 0x4c0c
+#define SYSCFG_COMBOPHY_CR5 0x4c10
+#define SYSCFG_COMBOPHY_SR 0x4c14
+#define SYSCFG_PCIEPRGCR 0x6080
+
+/* SYSCFG PCIEPRGCR */
+#define STM32MP25_PCIEPRGCR_EN BIT(0)
+#define STM32MP25_PCIEPRG_IMPCTRL_OHM GENMASK(3, 1)
+#define STM32MP25_PCIEPRG_IMPCTRL_VSWING GENMASK(5, 4)
+
+/* SYSCFG SYSCFG_COMBOPHY_SR */
+#define STM32MP25_PIPE0_PHYSTATUS BIT(1)
+
+/* SYSCFG CR1 */
+#define SYSCFG_COMBOPHY_CR1_REFUSEPAD BIT(0)
+#define SYSCFG_COMBOPHY_CR1_MPLLMULT GENMASK(7, 1)
+#define SYSCFG_COMBOPHY_CR1_REFCLKSEL GENMASK(16, 8)
+#define SYSCFG_COMBOPHY_CR1_REFCLKDIV2 BIT(17)
+#define SYSCFG_COMBOPHY_CR1_REFSSPEN BIT(18)
+#define SYSCFG_COMBOPHY_CR1_SSCEN BIT(19)
+
+/* SYSCFG CR4 */
+#define SYSCFG_COMBOPHY_CR4_RX0_EQ GENMASK(2, 0)
+
+#define MPLLMULT_19_2 (0x02u << 1)
+#define MPLLMULT_20 (0x7du << 1)
+#define MPLLMULT_24 (0x68u << 1)
+#define MPLLMULT_25 (0x64u << 1)
+#define MPLLMULT_26 (0x60u << 1)
+#define MPLLMULT_38_4 (0x41u << 1)
+#define MPLLMULT_48 (0x6cu << 1)
+#define MPLLMULT_50 (0x32u << 1)
+#define MPLLMULT_52 (0x30u << 1)
+#define MPLLMULT_100 (0x19u << 1)
+
+#define REFCLKSEL_0 0
+#define REFCLKSEL_1 (0x108u << 8)
+
+#define REFCLDIV_0 0
+
+/* SYSCFG CR2 */
+#define SYSCFG_COMBOPHY_CR2_MODESEL GENMASK(1, 0)
+#define SYSCFG_COMBOPHY_CR2_ISO_DIS BIT(15)
+
+#define COMBOPHY_MODESEL_PCIE 0
+#define COMBOPHY_MODESEL_USB 3
+
+/* SYSCFG CR5 */
+#define SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS BIT(12)
+
+#define COMBOPHY_SUP_ANA_MPLL_LOOP_CTL 0xc0
+#define COMBOPHY_PROP_CNTRL GENMASK(7, 4)
+
+/* Required apb/ker clocks first, optional pad last. */
+static const char * const combophy_clks[] = {"apb", "ker", "pad"};
+#define APB_CLK 0
+#define KER_CLK 1
+#define PAD_CLK 2
+
+struct stm32_combophy {
+ struct phy *phy;
+ struct regmap *regmap;
+ struct device *dev;
+ void __iomem *base;
+ struct reset_control *phy_reset;
+ struct clk_bulk_data clks[ARRAY_SIZE(combophy_clks)];
+ int num_clks;
+ bool have_pad_clk;
+ unsigned int type;
+ bool is_init;
+ int irq_wakeup;
+};
+
+struct clk_impedance {
+ u32 microohm;
+ u32 vswing[4];
+};
+
+/*
+ * lookup table to hold the settings needed for a ref clock frequency
+ * impedance, the offset is used to set the IMP_CTL and DE_EMP bit of the
+ * PRG_IMP_CTRL register. Use ordered discrete values in the table
+ */
+static const struct clk_impedance imp_lookup[] = {
+ { 6090000, { 442000, 564000, 684000, 802000 } },
+ { 5662000, { 528000, 621000, 712000, 803000 } },
+ { 5292000, { 491000, 596000, 700000, 802000 } },
+ { 4968000, { 558000, 640000, 722000, 803000 } },
+ { 4684000, { 468000, 581000, 692000, 802000 } },
+ { 4429000, { 554000, 613000, 717000, 803000 } },
+ { 4204000, { 511000, 609000, 706000, 802000 } },
+ { 3999000, { 571000, 648000, 726000, 803000 } }
+};
+
+static int stm32_impedance_tune(struct stm32_combophy *combophy)
+{
+ u8 imp_size = ARRAY_SIZE(imp_lookup);
+ u8 vswing_size = ARRAY_SIZE(imp_lookup[0].vswing);
+ u8 imp_of, vswing_of;
+ u32 max_imp = imp_lookup[0].microohm;
+ u32 min_imp = imp_lookup[imp_size - 1].microohm;
+ u32 max_vswing = imp_lookup[imp_size - 1].vswing[vswing_size - 1];
+ u32 min_vswing = imp_lookup[0].vswing[0];
+ u32 val;
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,output-micro-ohms", &val)) {
+ if (val < min_imp || val > max_imp) {
+ dev_err(combophy->dev, "Invalid value %u for output ohm\n", val);
+ return -EINVAL;
+ }
+
+ for (imp_of = 0; imp_of < ARRAY_SIZE(imp_lookup); imp_of++)
+ if (imp_lookup[imp_of].microohm <= val)
+ break;
+
+ dev_dbg(combophy->dev, "Set %u micro-ohms output impedance\n",
+ imp_lookup[imp_of].microohm);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRG_IMPCTRL_OHM,
+ FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_OHM, imp_of));
+ } else {
+ regmap_read(combophy->regmap, SYSCFG_PCIEPRGCR, &val);
+ imp_of = FIELD_GET(STM32MP25_PCIEPRG_IMPCTRL_OHM, val);
+ }
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,output-vswing-microvolt", &val)) {
+ if (val < min_vswing || val > max_vswing) {
+ dev_err(combophy->dev, "Invalid value %u for output vswing\n", val);
+ return -EINVAL;
+ }
+
+ for (vswing_of = 0; vswing_of < ARRAY_SIZE(imp_lookup[imp_of].vswing); vswing_of++)
+ if (imp_lookup[imp_of].vswing[vswing_of] >= val)
+ break;
+
+ dev_dbg(combophy->dev, "Set %u microvolt swing\n",
+ imp_lookup[imp_of].vswing[vswing_of]);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRG_IMPCTRL_VSWING,
+ FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_VSWING, vswing_of));
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_pll_init(struct stm32_combophy *combophy)
+{
+ int ret;
+ u32 refclksel, pllmult, propcntrl, val;
+ u32 clk_rate;
+ struct clk *clk;
+ u32 cr1_val = 0, cr1_mask = 0;
+
+ if (combophy->have_pad_clk)
+ clk = combophy->clks[PAD_CLK].clk;
+ else
+ clk = combophy->clks[KER_CLK].clk;
+
+ clk_rate = clk_get_rate(clk);
+
+ dev_dbg(combophy->dev, "%s pll init rate %d\n",
+ combophy->have_pad_clk ? "External" : "Ker", clk_rate);
+
+ if (combophy->type != PHY_TYPE_PCIE) {
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFSSPEN;
+ cr1_val |= SYSCFG_COMBOPHY_CR1_REFSSPEN;
+ }
+
+ if (of_property_present(combophy->dev->of_node, "st,ssc-on")) {
+ dev_dbg(combophy->dev, "Enabling clock with SSC\n");
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_SSCEN;
+ cr1_val |= SYSCFG_COMBOPHY_CR1_SSCEN;
+ }
+
+ switch (clk_rate) {
+ case 100000000:
+ pllmult = MPLLMULT_100;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0x8u << 4;
+ break;
+ case 19200000:
+ pllmult = MPLLMULT_19_2;
+ refclksel = REFCLKSEL_1;
+ propcntrl = 0x8u << 4;
+ break;
+ case 25000000:
+ pllmult = MPLLMULT_25;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0xeu << 4;
+ break;
+ case 24000000:
+ pllmult = MPLLMULT_24;
+ refclksel = REFCLKSEL_1;
+ propcntrl = 0xeu << 4;
+ break;
+ case 20000000:
+ pllmult = MPLLMULT_20;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0xeu << 4;
+ break;
+ default:
+ dev_err(combophy->dev, "Invalid rate 0x%x\n", clk_rate);
+ return -EINVAL;
+ }
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFCLKDIV2;
+ cr1_val |= REFCLDIV_0;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFCLKSEL;
+ cr1_val |= refclksel;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_MPLLMULT;
+ cr1_val |= pllmult;
+
+ /*
+ * vddcombophy is interconnected with vddcore. Isolation bit should be unset
+ * before using the ComboPHY.
+ */
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, SYSCFG_COMBOPHY_CR2_ISO_DIS);
+
+ reset_control_assert(combophy->phy_reset);
+
+ if (combophy->type == PHY_TYPE_PCIE) {
+ ret = stm32_impedance_tune(combophy);
+ if (ret)
+ goto out_iso;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFUSEPAD;
+ cr1_val |= combophy->have_pad_clk ? SYSCFG_COMBOPHY_CR1_REFUSEPAD : 0;
+ }
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,rx-equalizer", &val)) {
+ dev_dbg(combophy->dev, "Set RX equalizer %u\n", val);
+ if (val > SYSCFG_COMBOPHY_CR4_RX0_EQ) {
+ dev_err(combophy->dev, "Invalid value %u for rx0 equalizer\n", val);
+ ret = -EINVAL;
+ goto out_iso;
+ }
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR4,
+ SYSCFG_COMBOPHY_CR4_RX0_EQ, val);
+ }
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1, cr1_mask, cr1_val);
+
+ /*
+ * Force elasticity buffer to be tuned for the reference clock as
+ * the separated clock model is not supported
+ */
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR5,
+ SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS, SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS);
+
+ reset_control_deassert(combophy->phy_reset);
+
+ ret = regmap_read_poll_timeout(combophy->regmap, SYSCFG_COMBOPHY_SR, val,
+ !(val & STM32MP25_PIPE0_PHYSTATUS),
+ 10, 1000);
+ if (ret) {
+ dev_err(combophy->dev, "timeout, cannot lock PLL\n");
+ if (combophy->type == PHY_TYPE_PCIE && !combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, 0);
+
+ if (combophy->type != PHY_TYPE_PCIE)
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
+ SYSCFG_COMBOPHY_CR1_REFSSPEN, 0);
+
+ goto out;
+ }
+
+
+ if (combophy->type == PHY_TYPE_PCIE) {
+ if (!combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, STM32MP25_PCIEPRGCR_EN);
+
+ val = readl_relaxed(combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
+ val &= ~COMBOPHY_PROP_CNTRL;
+ val |= propcntrl;
+ writel_relaxed(val, combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
+ }
+
+ return 0;
+
+out_iso:
+ reset_control_deassert(combophy->phy_reset);
+
+out:
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, 0);
+
+ return ret;
+}
+
+static struct phy *stm32_combophy_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+ unsigned int type;
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of cells in 'phy' property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ type = args->args[0];
+ if (type != PHY_TYPE_USB3 && type != PHY_TYPE_PCIE) {
+ dev_err(dev, "unsupported device type: %d\n", type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (combophy->have_pad_clk && type != PHY_TYPE_PCIE) {
+ dev_err(dev, "Invalid use of clk_pad for USB3 mode\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ combophy->type = type;
+
+ return combophy->phy;
+}
+
+static int stm32_combophy_set_mode(struct stm32_combophy *combophy)
+{
+ int type = combophy->type;
+ u32 val;
+
+ switch (type) {
+ case PHY_TYPE_PCIE:
+ dev_dbg(combophy->dev, "setting PCIe ComboPHY\n");
+ val = COMBOPHY_MODESEL_PCIE;
+ break;
+ case PHY_TYPE_USB3:
+ dev_dbg(combophy->dev, "setting USB3 ComboPHY\n");
+ val = COMBOPHY_MODESEL_USB;
+ break;
+ default:
+ dev_err(combophy->dev, "Invalid PHY mode %d\n", type);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_MODESEL, val);
+}
+
+static int stm32_combophy_suspend_noirq(struct device *dev)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+
+ /*
+ * Clocks should be turned off since it is not needed for
+ * wakeup capability. In case usb-remote wakeup is not enabled,
+ * combo-phy is already turned off by HCD driver using exit callback
+ */
+ if (combophy->is_init) {
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+
+ /* since wakeup is enabled for ctrl */
+ enable_irq_wake(combophy->irq_wakeup);
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_resume_noirq(struct device *dev)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * If clocks was turned off by suspend call for wakeup then needs
+ * to be turned back ON in resume. In case usb-remote wakeup is not
+ * enabled, clocks already turned ON by HCD driver using init callback
+ */
+ if (combophy->is_init) {
+ /* since wakeup was enabled for ctrl */
+ disable_irq_wake(combophy->irq_wakeup);
+
+ ret = clk_bulk_prepare_enable(combophy->num_clks, combophy->clks);
+ if (ret) {
+ dev_err(dev, "can't enable clocks (%d)\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_exit(struct phy *phy)
+{
+ struct stm32_combophy *combophy = phy_get_drvdata(phy);
+ struct device *dev = combophy->dev;
+
+ combophy->is_init = false;
+
+ if (combophy->type == PHY_TYPE_PCIE && !combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, 0);
+
+ if (combophy->type != PHY_TYPE_PCIE)
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
+ SYSCFG_COMBOPHY_CR1_REFSSPEN, 0);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, 0);
+
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+
+ pm_runtime_put_noidle(dev);
+
+ return 0;
+}
+
+static int stm32_combophy_init(struct phy *phy)
+{
+ struct stm32_combophy *combophy = phy_get_drvdata(phy);
+ struct device *dev = combophy->dev;
+ int ret;
+
+ pm_runtime_get_noresume(dev);
+
+ ret = clk_bulk_prepare_enable(combophy->num_clks, combophy->clks);
+ if (ret) {
+ dev_err(dev, "can't enable clocks (%d)\n", ret);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ ret = stm32_combophy_set_mode(combophy);
+ if (ret) {
+ dev_err(dev, "combophy mode not set\n");
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ ret = stm32_combophy_pll_init(combophy);
+ if (ret) {
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ combophy->is_init = true;
+
+ return ret;
+}
+
+static const struct phy_ops stm32_combophy_phy_data = {
+ .init = stm32_combophy_init,
+ .exit = stm32_combophy_exit,
+ .owner = THIS_MODULE
+};
+
+static irqreturn_t stm32_combophy_irq_wakeup_handler(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+static int stm32_combophy_get_clocks(struct stm32_combophy *combophy)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(combophy_clks); i++)
+ combophy->clks[i].id = combophy_clks[i];
+
+ combophy->num_clks = ARRAY_SIZE(combophy_clks) - 1;
+
+ ret = devm_clk_bulk_get(combophy->dev, combophy->num_clks, combophy->clks);
+ if (ret)
+ return ret;
+
+ ret = devm_clk_bulk_get_optional(combophy->dev, 1, combophy->clks + combophy->num_clks);
+ if (ret)
+ return ret;
+
+ if (combophy->clks[combophy->num_clks].clk != NULL) {
+ combophy->have_pad_clk = true;
+ combophy->num_clks++;
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_probe(struct platform_device *pdev)
+{
+ struct stm32_combophy *combophy;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ int ret, irq;
+
+ combophy = devm_kzalloc(dev, sizeof(*combophy), GFP_KERNEL);
+ if (!combophy)
+ return -ENOMEM;
+
+ combophy->dev = dev;
+
+ dev_set_drvdata(dev, combophy);
+
+ combophy->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(combophy->base))
+ return PTR_ERR(combophy->base);
+
+ ret = stm32_combophy_get_clocks(combophy);
+ if (ret)
+ return ret;
+
+ combophy->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
+ if (IS_ERR(combophy->phy_reset))
+ return dev_err_probe(dev, PTR_ERR(combophy->phy_reset),
+ "Failed to get PHY reset\n");
+
+ combophy->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg");
+ if (IS_ERR(combophy->regmap))
+ return dev_err_probe(dev, PTR_ERR(combophy->regmap),
+ "No syscfg specified\n");
+
+ combophy->phy = devm_phy_create(dev, NULL, &stm32_combophy_phy_data);
+ if (IS_ERR(combophy->phy))
+ return dev_err_probe(dev, PTR_ERR(combophy->phy),
+ "failed to create PCIe/USB3 ComboPHY\n");
+
+ if (device_property_read_bool(dev, "wakeup-source")) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "failed to get IRQ\n");
+ combophy->irq_wakeup = irq;
+
+ ret = devm_request_threaded_irq(dev, combophy->irq_wakeup, NULL,
+ stm32_combophy_irq_wakeup_handler, IRQF_ONESHOT,
+ NULL, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "unable to request wake IRQ %d\n",
+ combophy->irq_wakeup);
+ }
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable pm runtime\n");
+
+ phy_set_drvdata(combophy->phy, combophy);
+
+ phy_provider = devm_of_phy_provider_register(dev, stm32_combophy_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct dev_pm_ops stm32_combophy_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_combophy_suspend_noirq,
+ stm32_combophy_resume_noirq)
+};
+
+static const struct of_device_id stm32_combophy_of_match[] = {
+ { .compatible = "st,stm32mp25-combophy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, stm32_combophy_of_match);
+
+static struct platform_driver stm32_combophy_driver = {
+ .probe = stm32_combophy_probe,
+ .driver = {
+ .name = "stm32-combophy",
+ .of_match_table = stm32_combophy_of_match,
+ .pm = pm_sleep_ptr(&stm32_combophy_pm_ops)
+ }
+};
+
+module_platform_driver(stm32_combophy_driver);
+
+MODULE_AUTHOR("Christian Bruel <christian.bruel@foss.st.com>");
+MODULE_DESCRIPTION("STM32MP25 Combophy USB3/PCIe controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c
index 9dbe60dcf319..b917cd413de7 100644
--- a/drivers/phy/st/phy-stm32-usbphyc.c
+++ b/drivers/phy/st/phy-stm32-usbphyc.c
@@ -812,7 +812,7 @@ MODULE_DEVICE_TABLE(of, stm32_usbphyc_of_match);
static struct platform_driver stm32_usbphyc_driver = {
.probe = stm32_usbphyc_probe,
- .remove_new = stm32_usbphyc_remove,
+ .remove = stm32_usbphyc_remove,
.driver = {
.of_match_table = stm32_usbphyc_of_match,
.name = "stm32-usbphyc",
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 342f5ccf611d..79d4814d758d 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -543,7 +543,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
device_initialize(&port->dev);
port->dev.type = &tegra_xusb_port_type;
- port->dev.of_node = of_node_get(np);
+ device_set_node(&port->dev, of_fwnode_handle(of_node_get(np)));
port->dev.parent = padctl->dev;
err = dev_set_name(&port->dev, "%s-%u", name, index);
@@ -1327,7 +1327,7 @@ static struct platform_driver tegra_xusb_padctl_driver = {
.pm = &tegra_xusb_padctl_pm_ops,
},
.probe = tegra_xusb_padctl_probe,
- .remove_new = tegra_xusb_padctl_remove,
+ .remove = tegra_xusb_padctl_remove,
};
module_platform_driver(tegra_xusb_padctl_driver);
diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c
index 3bf3aff4b1c7..431b223996e0 100644
--- a/drivers/phy/ti/phy-am654-serdes.c
+++ b/drivers/phy/ti/phy-am654-serdes.c
@@ -837,7 +837,7 @@ static void serdes_am654_remove(struct platform_device *pdev)
static struct platform_driver serdes_am654_driver = {
.probe = serdes_am654_probe,
- .remove_new = serdes_am654_remove,
+ .remove = serdes_am654_remove,
.driver = {
.name = "phy-am654",
.of_match_table = serdes_am654_id_table,
diff --git a/drivers/phy/ti/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c
index 68aa595b6ad8..1d81a1e6ec6b 100644
--- a/drivers/phy/ti/phy-da8xx-usb.c
+++ b/drivers/phy/ti/phy-da8xx-usb.c
@@ -277,11 +277,11 @@ MODULE_DEVICE_TABLE(of, da8xx_usb_phy_ids);
static struct platform_driver da8xx_usb_phy_driver = {
.probe = da8xx_usb_phy_probe,
- .remove_new = da8xx_usb_phy_remove,
+ .remove = da8xx_usb_phy_remove,
.driver = {
.name = "da8xx-usb-phy",
.pm = &da8xx_usb_phy_pm_ops,
- .of_match_table = da8xx_usb_phy_ids,
+ .of_match_table = da8xx_usb_phy_ids,
},
};
diff --git a/drivers/phy/ti/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c
index d5ae972a31fb..e8f842d4e841 100644
--- a/drivers/phy/ti/phy-dm816x-usb.c
+++ b/drivers/phy/ti/phy-dm816x-usb.c
@@ -259,7 +259,7 @@ static void dm816x_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver dm816x_usb_phy_driver = {
.probe = dm816x_usb_phy_probe,
- .remove_new = dm816x_usb_phy_remove,
+ .remove = dm816x_usb_phy_remove,
.driver = {
.name = "dm816x-usb-phy",
.pm = &dm816x_usb_phy_pm_ops,
diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
index 103b266fec77..e0ca59ae3153 100644
--- a/drivers/phy/ti/phy-gmii-sel.c
+++ b/drivers/phy/ti/phy-gmii-sel.c
@@ -230,7 +230,8 @@ static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
.use_of_data = true,
.regfields = phy_gmii_sel_fields_am654,
- .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
+ BIT(PHY_INTERFACE_MODE_USXGMII),
.num_ports = 4,
.num_qsgmii_main_ports = 1,
};
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index c6e846d385d2..ab2a4f2c0a5b 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1685,7 +1685,7 @@ static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, NULL, wiz_resume_noirq);
static struct platform_driver wiz_driver = {
.probe = wiz_probe,
- .remove_new = wiz_remove,
+ .remove = wiz_remove,
.driver = {
.name = "wiz",
.of_match_table = wiz_id_table,
diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
index 78e19b128962..c1a0ef979142 100644
--- a/drivers/phy/ti/phy-omap-usb2.c
+++ b/drivers/phy/ti/phy-omap-usb2.c
@@ -511,7 +511,7 @@ static void omap_usb2_remove(struct platform_device *pdev)
static struct platform_driver omap_usb2_driver = {
.probe = omap_usb2_probe,
- .remove_new = omap_usb2_remove,
+ .remove = omap_usb2_remove,
.driver = {
.name = "omap-usb2",
.of_match_table = omap_usb2_id_table,
diff --git a/drivers/phy/ti/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c
index 874c1a25ce36..da2cbacb982c 100644
--- a/drivers/phy/ti/phy-ti-pipe3.c
+++ b/drivers/phy/ti/phy-ti-pipe3.c
@@ -920,7 +920,7 @@ MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
static struct platform_driver ti_pipe3_driver = {
.probe = ti_pipe3_probe,
- .remove_new = ti_pipe3_remove,
+ .remove = ti_pipe3_remove,
.driver = {
.name = "ti-pipe3",
.of_match_table = ti_pipe3_id_table,
diff --git a/drivers/phy/ti/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c
index 6b265992d988..6f12b38cd894 100644
--- a/drivers/phy/ti/phy-twl4030-usb.c
+++ b/drivers/phy/ti/phy-twl4030-usb.c
@@ -834,7 +834,7 @@ MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
static struct platform_driver twl4030_usb_driver = {
.probe = twl4030_usb_probe,
- .remove_new = twl4030_usb_remove,
+ .remove = twl4030_usb_remove,
.driver = {
.name = "twl4030_usb",
.pm = &twl4030_usb_pm_ops,
diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
index e6579002f114..05a4a59f7c40 100644
--- a/drivers/phy/xilinx/phy-zynqmp.c
+++ b/drivers/phy/xilinx/phy-zynqmp.c
@@ -1071,7 +1071,7 @@ MODULE_DEVICE_TABLE(of, xpsgtr_of_match);
static struct platform_driver xpsgtr_driver = {
.probe = xpsgtr_probe,
- .remove_new = xpsgtr_remove,
+ .remove = xpsgtr_remove,
.driver = {
.name = "xilinx-psgtr",
.of_match_table = xpsgtr_of_match,
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 354536de564b..95a8e2b9a614 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -268,6 +268,17 @@ config PINCTRL_K210
Add support for the Canaan Kendryte K210 RISC-V SOC Field
Programmable IO Array (FPIOA) controller.
+config PINCTRL_K230
+ bool "Pinctrl driver for the Canaan Kendryte K230 SoC"
+ depends on OF
+ depends on ARCH_CANAAN || COMPILE_TEST
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+ select REGMAP_MMIO
+ help
+ Add support for the Canaan Kendryte K230 RISC-V SOC pin controller.
+
config PINCTRL_KEEMBAY
tristate "Pinctrl driver for Intel Keem Bay SoC"
depends on ARCH_KEEMBAY || (ARM64 && COMPILE_TEST)
@@ -551,6 +562,20 @@ config PINCTRL_TPS6594
This driver can also be built as a module
called tps6594-pinctrl.
+config PINCTRL_TH1520
+ tristate "Pinctrl driver for the T-Head TH1520 SoC"
+ depends on ARCH_THEAD || COMPILE_TEST
+ depends on OF
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+ select PINMUX
+ help
+ This is the driver for the pin controller blocks on the
+ T-Head TH1520 SoC.
+
+ This driver is needed for RISC-V development boards like
+ the BeagleV Ahead and the LicheePi 4A.
+
config PINCTRL_ZYNQ
bool "Pinctrl driver for Xilinx Zynq"
depends on ARCH_ZYNQ
@@ -606,6 +631,7 @@ source "drivers/pinctrl/realtek/Kconfig"
source "drivers/pinctrl/renesas/Kconfig"
source "drivers/pinctrl/samsung/Kconfig"
source "drivers/pinctrl/sophgo/Kconfig"
+source "drivers/pinctrl/spacemit/Kconfig"
source "drivers/pinctrl/spear/Kconfig"
source "drivers/pinctrl/sprd/Kconfig"
source "drivers/pinctrl/starfive/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 97823f52b972..fba1c56624c0 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PINCTRL_EYEQ5) += pinctrl-eyeq5.o
obj-$(CONFIG_PINCTRL_GEMINI) += pinctrl-gemini.o
obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o
obj-$(CONFIG_PINCTRL_K210) += pinctrl-k210.o
+obj-$(CONFIG_PINCTRL_K230) += pinctrl-k230.o
obj-$(CONFIG_PINCTRL_KEEMBAY) += pinctrl-keembay.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
@@ -54,6 +55,7 @@ obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
obj-$(CONFIG_PINCTRL_TPS6594) += pinctrl-tps6594.o
+obj-$(CONFIG_PINCTRL_TH1520) += pinctrl-th1520.o
obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
@@ -76,6 +78,7 @@ obj-$(CONFIG_ARCH_REALTEK) += realtek/
obj-$(CONFIG_PINCTRL_RENESAS) += renesas/
obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/
obj-y += sophgo/
+obj-y += spacemit/
obj-$(CONFIG_PINCTRL_SPEAR) += spear/
obj-y += sprd/
obj-$(CONFIG_SOC_STARFIVE) += starfive/
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
index 6ecc656abc44..5a7cd0a88687 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
@@ -2607,6 +2607,10 @@ static struct aspeed_pin_config aspeed_g6_configs[] = {
{ PIN_CONFIG_DRIVE_STRENGTH, { AB8, AB8 }, SCU454, GENMASK(27, 26)},
/* LAD0 */
{ PIN_CONFIG_DRIVE_STRENGTH, { AB7, AB7 }, SCU454, GENMASK(25, 24)},
+ /* GPIOF */
+ { PIN_CONFIG_DRIVE_STRENGTH, { D22, A23 }, SCU458, GENMASK(9, 8)},
+ /* GPIOG */
+ { PIN_CONFIG_DRIVE_STRENGTH, { E21, B21 }, SCU458, GENMASK(11, 10)},
/* MAC3 */
{ PIN_CONFIG_POWER_SOURCE, { H24, E26 }, SCU458, BIT_MASK(4)},
diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
index fd5ce52d05b1..c9a3d3aa8c10 100644
--- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
@@ -309,7 +309,7 @@ static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct iproc_gpio *chip = gpiochip_get_data(gc);
- seq_printf(p, dev_name(chip->dev));
+ seq_puts(p, dev_name(chip->dev));
}
static const struct irq_chip iproc_gpio_irq_chip = {
diff --git a/drivers/pinctrl/cirrus/pinctrl-madera-core.c b/drivers/pinctrl/cirrus/pinctrl-madera-core.c
index 2932d7aba725..73ec5b9beb49 100644
--- a/drivers/pinctrl/cirrus/pinctrl-madera-core.c
+++ b/drivers/pinctrl/cirrus/pinctrl-madera-core.c
@@ -1091,7 +1091,7 @@ static void madera_pin_remove(struct platform_device *pdev)
static struct platform_driver madera_pin_driver = {
.probe = madera_pin_probe,
- .remove_new = madera_pin_remove,
+ .remove = madera_pin_remove,
.driver = {
.name = "madera-pinctrl",
},
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 4061890a1748..b3eec63c00ba 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -220,6 +220,9 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
/* Set owner */
pindesc->pctldev = pctldev;
+#ifdef CONFIG_PINMUX
+ mutex_init(&pindesc->mux_lock);
+#endif
/* Copy basic pin info */
if (pin->name) {
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 4e07707d2435..d6c24978e708 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -177,6 +177,7 @@ struct pin_desc {
const char *mux_owner;
const struct pinctrl_setting_mux *mux_setting;
const char *gpio_owner;
+ struct mutex mux_lock;
#endif
};
diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig
index 3b59d7189004..4c420b21b804 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -9,7 +9,7 @@ config PINCTRL_IMX
config PINCTRL_IMX_SCMI
tristate "i.MX95 pinctrl driver using SCMI protocol interface"
- depends on ARM_SCMI_PROTOCOL && OF || COMPILE_TEST
+ depends on ARM_SCMI_PROTOCOL && OF
select PINMUX
select GENERIC_PINCONF
select GENERIC_PINCTRL_GROUPS
@@ -20,7 +20,7 @@ config PINCTRL_IMX_SCMI
config PINCTRL_IMX_SCU
tristate
- depends on IMX_SCU
+ depends on IMX_SCU || COMPILE_TEST
select PINCTRL_IMX
config PINCTRL_IMX1_CORE
@@ -30,14 +30,18 @@ config PINCTRL_IMX1_CORE
config PINCTRL_IMX1
bool "IMX1 pinctrl driver"
- depends on SOC_IMX1
+ depends on OF
+ depends on SOC_IMX1 || COMPILE_TEST
+ default SOC_IMX1
select PINCTRL_IMX1_CORE
help
Say Y here to enable the imx1 pinctrl driver
config PINCTRL_IMX27
bool "IMX27 pinctrl driver"
- depends on SOC_IMX27
+ depends on OF
+ depends on SOC_IMX27 || COMPILE_TEST
+ default SOC_IMX27
select PINCTRL_IMX1_CORE
help
Say Y here to enable the imx27 pinctrl driver
@@ -46,84 +50,107 @@ config PINCTRL_IMX27
config PINCTRL_IMX25
bool "IMX25 pinctrl driver"
depends on OF
- depends on SOC_IMX25
+ depends on SOC_IMX25 || COMPILE_TEST
+ default SOC_IMX25
select PINCTRL_IMX
help
Say Y here to enable the imx25 pinctrl driver
config PINCTRL_IMX35
bool "IMX35 pinctrl driver"
- depends on SOC_IMX35
+ depends on OF
+ depends on SOC_IMX35 || COMPILE_TEST
+ default SOC_IMX35
select PINCTRL_IMX
help
Say Y here to enable the imx35 pinctrl driver
config PINCTRL_IMX50
bool "IMX50 pinctrl driver"
- depends on SOC_IMX50
+ depends on OF
+ depends on SOC_IMX50 || COMPILE_TEST
+ default SOC_IMX50
select PINCTRL_IMX
help
Say Y here to enable the imx50 pinctrl driver
config PINCTRL_IMX51
bool "IMX51 pinctrl driver"
- depends on SOC_IMX51
+ depends on OF
+ depends on SOC_IMX51 || COMPILE_TEST
+ default SOC_IMX51
select PINCTRL_IMX
help
Say Y here to enable the imx51 pinctrl driver
config PINCTRL_IMX53
bool "IMX53 pinctrl driver"
- depends on SOC_IMX53
+ depends on OF
+ depends on SOC_IMX53 || COMPILE_TEST
+ default SOC_IMX53
select PINCTRL_IMX
help
Say Y here to enable the imx53 pinctrl driver
config PINCTRL_IMX6Q
bool "IMX6Q/DL pinctrl driver"
- depends on SOC_IMX6Q
+ depends on OF
+ depends on SOC_IMX6Q || COMPILE_TEST
+ default SOC_IMX6Q
select PINCTRL_IMX
help
Say Y here to enable the imx6q/dl pinctrl driver
config PINCTRL_IMX6SL
bool "IMX6SL pinctrl driver"
- depends on SOC_IMX6SL
+ depends on OF
+ depends on SOC_IMX6SL || COMPILE_TEST
+ default SOC_IMX6SL
select PINCTRL_IMX
help
Say Y here to enable the imx6sl pinctrl driver
config PINCTRL_IMX6SLL
bool "IMX6SLL pinctrl driver"
- depends on SOC_IMX6SLL
+ depends on OF
+ depends on SOC_IMX6SLL || COMPILE_TEST
+ default SOC_IMX6SLL
select PINCTRL_IMX
help
Say Y here to enable the imx6sll pinctrl driver
config PINCTRL_IMX6SX
bool "IMX6SX pinctrl driver"
- depends on SOC_IMX6SX
+ depends on OF
+ depends on SOC_IMX6SX || COMPILE_TEST
+ default SOC_IMX6SX
select PINCTRL_IMX
help
Say Y here to enable the imx6sx pinctrl driver
config PINCTRL_IMX6UL
bool "IMX6UL pinctrl driver"
- depends on SOC_IMX6UL
+ depends on OF
+ depends on SOC_IMX6UL || COMPILE_TEST
+ default SOC_IMX6UL
select PINCTRL_IMX
help
Say Y here to enable the imx6ul pinctrl driver
config PINCTRL_IMX7D
bool "IMX7D pinctrl driver"
- depends on SOC_IMX7D
+ depends on OF
+ depends on SOC_IMX7D || COMPILE_TEST
+ default SOC_IMX7D
select PINCTRL_IMX
help
Say Y here to enable the imx7d pinctrl driver
config PINCTRL_IMX7ULP
bool "IMX7ULP pinctrl driver"
- depends on SOC_IMX7ULP
+ depends on OF
+ depends on SOC_IMX7ULP || COMPILE_TEST
+ default SOC_IMX7ULP
select PINCTRL_IMX
help
Say Y here to enable the imx7ulp pinctrl driver
@@ -131,7 +158,7 @@ config PINCTRL_IMX7ULP
config PINCTRL_IMX8MM
tristate "IMX8MM pinctrl driver"
depends on OF
- depends on SOC_IMX8M
+ depends on SOC_IMX8M || COMPILE_TEST
select PINCTRL_IMX
help
Say Y here to enable the imx8mm pinctrl driver
@@ -139,7 +166,7 @@ config PINCTRL_IMX8MM
config PINCTRL_IMX8MN
tristate "IMX8MN pinctrl driver"
depends on OF
- depends on SOC_IMX8M
+ depends on SOC_IMX8M || COMPILE_TEST
select PINCTRL_IMX
help
Say Y here to enable the imx8mn pinctrl driver
@@ -147,7 +174,7 @@ config PINCTRL_IMX8MN
config PINCTRL_IMX8MP
tristate "IMX8MP pinctrl driver"
depends on OF
- depends on SOC_IMX8M
+ depends on SOC_IMX8M || COMPILE_TEST
select PINCTRL_IMX
help
Say Y here to enable the imx8mp pinctrl driver
@@ -155,42 +182,48 @@ config PINCTRL_IMX8MP
config PINCTRL_IMX8MQ
tristate "IMX8MQ pinctrl driver"
depends on OF
- depends on SOC_IMX8M
+ depends on SOC_IMX8M || COMPILE_TEST
select PINCTRL_IMX
help
Say Y here to enable the imx8mq pinctrl driver
config PINCTRL_IMX8QM
tristate "IMX8QM pinctrl driver"
- depends on IMX_SCU && ARCH_MXC && ARM64
+ depends on OF
+ depends on (IMX_SCU && ARCH_MXC && ARM64) || COMPILE_TEST
select PINCTRL_IMX_SCU
help
Say Y here to enable the imx8qm pinctrl driver
config PINCTRL_IMX8QXP
tristate "IMX8QXP pinctrl driver"
- depends on IMX_SCU && ARCH_MXC && ARM64
+ depends on OF
+ depends on (IMX_SCU && ARCH_MXC && ARM64) || COMPILE_TEST
select PINCTRL_IMX_SCU
help
Say Y here to enable the imx8qxp pinctrl driver
config PINCTRL_IMX8DXL
tristate "IMX8DXL pinctrl driver"
- depends on IMX_SCU && ARCH_MXC && ARM64
+ depends on OF
+ depends on (IMX_SCU && ARCH_MXC && ARM64) || COMPILE_TEST
select PINCTRL_IMX_SCU
help
Say Y here to enable the imx8dxl pinctrl driver
config PINCTRL_IMX8ULP
tristate "IMX8ULP pinctrl driver"
- depends on ARCH_MXC
+ depends on OF
+ depends on ARCH_MXC || COMPILE_TEST
select PINCTRL_IMX
help
Say Y here to enable the imx8ulp pinctrl driver
config PINCTRL_IMXRT1050
bool "IMXRT1050 pinctrl driver"
- depends on ARCH_MXC
+ depends on OF
+ depends on SOC_IMXRT || COMPILE_TEST
+ default SOC_IMXRT
select PINCTRL_IMX
help
Say Y here to enable the imxrt1050 pinctrl driver
@@ -204,14 +237,17 @@ config PINCTRL_IMX91
config PINCTRL_IMX93
tristate "IMX93 pinctrl driver"
- depends on ARCH_MXC
+ depends on OF
+ depends on ARCH_MXC || COMPILE_TEST
select PINCTRL_IMX
help
Say Y here to enable the imx93 pinctrl driver
config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
- depends on SOC_VF610
+ depends on OF
+ depends on SOC_VF610 || COMPILE_TEST
+ default SOC_VF610
select PINCTRL_IMX
help
Say Y here to enable the Freescale Vybrid VF610 pinctrl driver
@@ -231,7 +267,8 @@ config PINCTRL_IMX28
config PINCTRL_IMXRT1170
bool "IMXRT1170 pinctrl driver"
- depends on ARCH_MXC
+ depends on OF
+ depends on SOC_IMXRT || COMPILE_TEST
select PINCTRL_IMX
help
Say Y here to enable the imxrt1170 pinctrl driver
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index d05c2c478e79..842a1e6cbfc4 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -633,11 +633,11 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
static bool imx_pinctrl_dt_is_flat_functions(struct device_node *np)
{
for_each_child_of_node_scoped(np, function_np) {
- if (of_property_read_bool(function_np, "fsl,pins"))
+ if (of_property_present(function_np, "fsl,pins"))
return true;
for_each_child_of_node_scoped(function_np, pinctrl_np) {
- if (of_property_read_bool(pinctrl_np, "fsl,pins"))
+ if (of_property_present(pinctrl_np, "fsl,pins"))
return false;
}
}
@@ -746,7 +746,7 @@ int imx_pinctrl_probe(struct platform_device *pdev,
if (IS_ERR(ipctl->base))
return PTR_ERR(ipctl->base);
- if (of_property_read_bool(dev_np, "fsl,input-sel")) {
+ if (of_property_present(dev_np, "fsl,input-sel")) {
np = of_parse_phandle(dev_np, "fsl,input-sel", 0);
if (!np) {
dev_err(&pdev->dev, "iomuxc fsl,input-sel property not found\n");
diff --git a/drivers/pinctrl/freescale/pinctrl-imx1.c b/drivers/pinctrl/freescale/pinctrl-imx1.c
index 1e2b0fe9ffd6..bd39cadf1f34 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx1.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx1.c
@@ -12,122 +12,122 @@
#include "pinctrl-imx1.h"
#define PAD_ID(port, pin) ((port) * 32 + (pin))
-#define PA 0
-#define PB 1
-#define PC 2
-#define PD 3
+#define IMX1_PA 0
+#define IMX1_PB 1
+#define IMX1_PC 2
+#define IMX1_PD 3
enum imx1_pads {
- MX1_PAD_A24 = PAD_ID(PA, 0),
- MX1_PAD_TIN = PAD_ID(PA, 1),
- MX1_PAD_PWMO = PAD_ID(PA, 2),
- MX1_PAD_CSI_MCLK = PAD_ID(PA, 3),
- MX1_PAD_CSI_D0 = PAD_ID(PA, 4),
- MX1_PAD_CSI_D1 = PAD_ID(PA, 5),
- MX1_PAD_CSI_D2 = PAD_ID(PA, 6),
- MX1_PAD_CSI_D3 = PAD_ID(PA, 7),
- MX1_PAD_CSI_D4 = PAD_ID(PA, 8),
- MX1_PAD_CSI_D5 = PAD_ID(PA, 9),
- MX1_PAD_CSI_D6 = PAD_ID(PA, 10),
- MX1_PAD_CSI_D7 = PAD_ID(PA, 11),
- MX1_PAD_CSI_VSYNC = PAD_ID(PA, 12),
- MX1_PAD_CSI_HSYNC = PAD_ID(PA, 13),
- MX1_PAD_CSI_PIXCLK = PAD_ID(PA, 14),
- MX1_PAD_I2C_SDA = PAD_ID(PA, 15),
- MX1_PAD_I2C_SCL = PAD_ID(PA, 16),
- MX1_PAD_DTACK = PAD_ID(PA, 17),
- MX1_PAD_BCLK = PAD_ID(PA, 18),
- MX1_PAD_LBA = PAD_ID(PA, 19),
- MX1_PAD_ECB = PAD_ID(PA, 20),
- MX1_PAD_A0 = PAD_ID(PA, 21),
- MX1_PAD_CS4 = PAD_ID(PA, 22),
- MX1_PAD_CS5 = PAD_ID(PA, 23),
- MX1_PAD_A16 = PAD_ID(PA, 24),
- MX1_PAD_A17 = PAD_ID(PA, 25),
- MX1_PAD_A18 = PAD_ID(PA, 26),
- MX1_PAD_A19 = PAD_ID(PA, 27),
- MX1_PAD_A20 = PAD_ID(PA, 28),
- MX1_PAD_A21 = PAD_ID(PA, 29),
- MX1_PAD_A22 = PAD_ID(PA, 30),
- MX1_PAD_A23 = PAD_ID(PA, 31),
- MX1_PAD_SD_DAT0 = PAD_ID(PB, 8),
- MX1_PAD_SD_DAT1 = PAD_ID(PB, 9),
- MX1_PAD_SD_DAT2 = PAD_ID(PB, 10),
- MX1_PAD_SD_DAT3 = PAD_ID(PB, 11),
- MX1_PAD_SD_SCLK = PAD_ID(PB, 12),
- MX1_PAD_SD_CMD = PAD_ID(PB, 13),
- MX1_PAD_SIM_SVEN = PAD_ID(PB, 14),
- MX1_PAD_SIM_PD = PAD_ID(PB, 15),
- MX1_PAD_SIM_TX = PAD_ID(PB, 16),
- MX1_PAD_SIM_RX = PAD_ID(PB, 17),
- MX1_PAD_SIM_RST = PAD_ID(PB, 18),
- MX1_PAD_SIM_CLK = PAD_ID(PB, 19),
- MX1_PAD_USBD_AFE = PAD_ID(PB, 20),
- MX1_PAD_USBD_OE = PAD_ID(PB, 21),
- MX1_PAD_USBD_RCV = PAD_ID(PB, 22),
- MX1_PAD_USBD_SUSPND = PAD_ID(PB, 23),
- MX1_PAD_USBD_VP = PAD_ID(PB, 24),
- MX1_PAD_USBD_VM = PAD_ID(PB, 25),
- MX1_PAD_USBD_VPO = PAD_ID(PB, 26),
- MX1_PAD_USBD_VMO = PAD_ID(PB, 27),
- MX1_PAD_UART2_CTS = PAD_ID(PB, 28),
- MX1_PAD_UART2_RTS = PAD_ID(PB, 29),
- MX1_PAD_UART2_TXD = PAD_ID(PB, 30),
- MX1_PAD_UART2_RXD = PAD_ID(PB, 31),
- MX1_PAD_SSI_RXFS = PAD_ID(PC, 3),
- MX1_PAD_SSI_RXCLK = PAD_ID(PC, 4),
- MX1_PAD_SSI_RXDAT = PAD_ID(PC, 5),
- MX1_PAD_SSI_TXDAT = PAD_ID(PC, 6),
- MX1_PAD_SSI_TXFS = PAD_ID(PC, 7),
- MX1_PAD_SSI_TXCLK = PAD_ID(PC, 8),
- MX1_PAD_UART1_CTS = PAD_ID(PC, 9),
- MX1_PAD_UART1_RTS = PAD_ID(PC, 10),
- MX1_PAD_UART1_TXD = PAD_ID(PC, 11),
- MX1_PAD_UART1_RXD = PAD_ID(PC, 12),
- MX1_PAD_SPI1_RDY = PAD_ID(PC, 13),
- MX1_PAD_SPI1_SCLK = PAD_ID(PC, 14),
- MX1_PAD_SPI1_SS = PAD_ID(PC, 15),
- MX1_PAD_SPI1_MISO = PAD_ID(PC, 16),
- MX1_PAD_SPI1_MOSI = PAD_ID(PC, 17),
- MX1_PAD_BT13 = PAD_ID(PC, 19),
- MX1_PAD_BT12 = PAD_ID(PC, 20),
- MX1_PAD_BT11 = PAD_ID(PC, 21),
- MX1_PAD_BT10 = PAD_ID(PC, 22),
- MX1_PAD_BT9 = PAD_ID(PC, 23),
- MX1_PAD_BT8 = PAD_ID(PC, 24),
- MX1_PAD_BT7 = PAD_ID(PC, 25),
- MX1_PAD_BT6 = PAD_ID(PC, 26),
- MX1_PAD_BT5 = PAD_ID(PC, 27),
- MX1_PAD_BT4 = PAD_ID(PC, 28),
- MX1_PAD_BT3 = PAD_ID(PC, 29),
- MX1_PAD_BT2 = PAD_ID(PC, 30),
- MX1_PAD_BT1 = PAD_ID(PC, 31),
- MX1_PAD_LSCLK = PAD_ID(PD, 6),
- MX1_PAD_REV = PAD_ID(PD, 7),
- MX1_PAD_CLS = PAD_ID(PD, 8),
- MX1_PAD_PS = PAD_ID(PD, 9),
- MX1_PAD_SPL_SPR = PAD_ID(PD, 10),
- MX1_PAD_CONTRAST = PAD_ID(PD, 11),
- MX1_PAD_ACD_OE = PAD_ID(PD, 12),
- MX1_PAD_LP_HSYNC = PAD_ID(PD, 13),
- MX1_PAD_FLM_VSYNC = PAD_ID(PD, 14),
- MX1_PAD_LD0 = PAD_ID(PD, 15),
- MX1_PAD_LD1 = PAD_ID(PD, 16),
- MX1_PAD_LD2 = PAD_ID(PD, 17),
- MX1_PAD_LD3 = PAD_ID(PD, 18),
- MX1_PAD_LD4 = PAD_ID(PD, 19),
- MX1_PAD_LD5 = PAD_ID(PD, 20),
- MX1_PAD_LD6 = PAD_ID(PD, 21),
- MX1_PAD_LD7 = PAD_ID(PD, 22),
- MX1_PAD_LD8 = PAD_ID(PD, 23),
- MX1_PAD_LD9 = PAD_ID(PD, 24),
- MX1_PAD_LD10 = PAD_ID(PD, 25),
- MX1_PAD_LD11 = PAD_ID(PD, 26),
- MX1_PAD_LD12 = PAD_ID(PD, 27),
- MX1_PAD_LD13 = PAD_ID(PD, 28),
- MX1_PAD_LD14 = PAD_ID(PD, 29),
- MX1_PAD_LD15 = PAD_ID(PD, 30),
- MX1_PAD_TMR2OUT = PAD_ID(PD, 31),
+ MX1_PAD_A24 = PAD_ID(IMX1_PA, 0),
+ MX1_PAD_TIN = PAD_ID(IMX1_PA, 1),
+ MX1_PAD_PWMO = PAD_ID(IMX1_PA, 2),
+ MX1_PAD_CSI_MCLK = PAD_ID(IMX1_PA, 3),
+ MX1_PAD_CSI_D0 = PAD_ID(IMX1_PA, 4),
+ MX1_PAD_CSI_D1 = PAD_ID(IMX1_PA, 5),
+ MX1_PAD_CSI_D2 = PAD_ID(IMX1_PA, 6),
+ MX1_PAD_CSI_D3 = PAD_ID(IMX1_PA, 7),
+ MX1_PAD_CSI_D4 = PAD_ID(IMX1_PA, 8),
+ MX1_PAD_CSI_D5 = PAD_ID(IMX1_PA, 9),
+ MX1_PAD_CSI_D6 = PAD_ID(IMX1_PA, 10),
+ MX1_PAD_CSI_D7 = PAD_ID(IMX1_PA, 11),
+ MX1_PAD_CSI_VSYNC = PAD_ID(IMX1_PA, 12),
+ MX1_PAD_CSI_HSYNC = PAD_ID(IMX1_PA, 13),
+ MX1_PAD_CSI_PIXCLK = PAD_ID(IMX1_PA, 14),
+ MX1_PAD_I2C_SDA = PAD_ID(IMX1_PA, 15),
+ MX1_PAD_I2C_SCL = PAD_ID(IMX1_PA, 16),
+ MX1_PAD_DTACK = PAD_ID(IMX1_PA, 17),
+ MX1_PAD_BCLK = PAD_ID(IMX1_PA, 18),
+ MX1_PAD_LBA = PAD_ID(IMX1_PA, 19),
+ MX1_PAD_ECB = PAD_ID(IMX1_PA, 20),
+ MX1_PAD_A0 = PAD_ID(IMX1_PA, 21),
+ MX1_PAD_CS4 = PAD_ID(IMX1_PA, 22),
+ MX1_PAD_CS5 = PAD_ID(IMX1_PA, 23),
+ MX1_PAD_A16 = PAD_ID(IMX1_PA, 24),
+ MX1_PAD_A17 = PAD_ID(IMX1_PA, 25),
+ MX1_PAD_A18 = PAD_ID(IMX1_PA, 26),
+ MX1_PAD_A19 = PAD_ID(IMX1_PA, 27),
+ MX1_PAD_A20 = PAD_ID(IMX1_PA, 28),
+ MX1_PAD_A21 = PAD_ID(IMX1_PA, 29),
+ MX1_PAD_A22 = PAD_ID(IMX1_PA, 30),
+ MX1_PAD_A23 = PAD_ID(IMX1_PA, 31),
+ MX1_PAD_SD_DAT0 = PAD_ID(IMX1_PB, 8),
+ MX1_PAD_SD_DAT1 = PAD_ID(IMX1_PB, 9),
+ MX1_PAD_SD_DAT2 = PAD_ID(IMX1_PB, 10),
+ MX1_PAD_SD_DAT3 = PAD_ID(IMX1_PB, 11),
+ MX1_PAD_SD_SCLK = PAD_ID(IMX1_PB, 12),
+ MX1_PAD_SD_CMD = PAD_ID(IMX1_PB, 13),
+ MX1_PAD_SIM_SVEN = PAD_ID(IMX1_PB, 14),
+ MX1_PAD_SIM_PD = PAD_ID(IMX1_PB, 15),
+ MX1_PAD_SIM_TX = PAD_ID(IMX1_PB, 16),
+ MX1_PAD_SIM_RX = PAD_ID(IMX1_PB, 17),
+ MX1_PAD_SIM_RST = PAD_ID(IMX1_PB, 18),
+ MX1_PAD_SIM_CLK = PAD_ID(IMX1_PB, 19),
+ MX1_PAD_USBD_AFE = PAD_ID(IMX1_PB, 20),
+ MX1_PAD_USBD_OE = PAD_ID(IMX1_PB, 21),
+ MX1_PAD_USBD_RCV = PAD_ID(IMX1_PB, 22),
+ MX1_PAD_USBD_SUSPND = PAD_ID(IMX1_PB, 23),
+ MX1_PAD_USBD_VP = PAD_ID(IMX1_PB, 24),
+ MX1_PAD_USBD_VM = PAD_ID(IMX1_PB, 25),
+ MX1_PAD_USBD_VPO = PAD_ID(IMX1_PB, 26),
+ MX1_PAD_USBD_VMO = PAD_ID(IMX1_PB, 27),
+ MX1_PAD_UART2_CTS = PAD_ID(IMX1_PB, 28),
+ MX1_PAD_UART2_RTS = PAD_ID(IMX1_PB, 29),
+ MX1_PAD_UART2_TXD = PAD_ID(IMX1_PB, 30),
+ MX1_PAD_UART2_RXD = PAD_ID(IMX1_PB, 31),
+ MX1_PAD_SSI_RXFS = PAD_ID(IMX1_PC, 3),
+ MX1_PAD_SSI_RXCLK = PAD_ID(IMX1_PC, 4),
+ MX1_PAD_SSI_RXDAT = PAD_ID(IMX1_PC, 5),
+ MX1_PAD_SSI_TXDAT = PAD_ID(IMX1_PC, 6),
+ MX1_PAD_SSI_TXFS = PAD_ID(IMX1_PC, 7),
+ MX1_PAD_SSI_TXCLK = PAD_ID(IMX1_PC, 8),
+ MX1_PAD_UART1_CTS = PAD_ID(IMX1_PC, 9),
+ MX1_PAD_UART1_RTS = PAD_ID(IMX1_PC, 10),
+ MX1_PAD_UART1_TXD = PAD_ID(IMX1_PC, 11),
+ MX1_PAD_UART1_RXD = PAD_ID(IMX1_PC, 12),
+ MX1_PAD_SPI1_RDY = PAD_ID(IMX1_PC, 13),
+ MX1_PAD_SPI1_SCLK = PAD_ID(IMX1_PC, 14),
+ MX1_PAD_SPI1_SS = PAD_ID(IMX1_PC, 15),
+ MX1_PAD_SPI1_MISO = PAD_ID(IMX1_PC, 16),
+ MX1_PAD_SPI1_MOSI = PAD_ID(IMX1_PC, 17),
+ MX1_PAD_BT13 = PAD_ID(IMX1_PC, 19),
+ MX1_PAD_BT12 = PAD_ID(IMX1_PC, 20),
+ MX1_PAD_BT11 = PAD_ID(IMX1_PC, 21),
+ MX1_PAD_BT10 = PAD_ID(IMX1_PC, 22),
+ MX1_PAD_BT9 = PAD_ID(IMX1_PC, 23),
+ MX1_PAD_BT8 = PAD_ID(IMX1_PC, 24),
+ MX1_PAD_BT7 = PAD_ID(IMX1_PC, 25),
+ MX1_PAD_BT6 = PAD_ID(IMX1_PC, 26),
+ MX1_PAD_BT5 = PAD_ID(IMX1_PC, 27),
+ MX1_PAD_BT4 = PAD_ID(IMX1_PC, 28),
+ MX1_PAD_BT3 = PAD_ID(IMX1_PC, 29),
+ MX1_PAD_BT2 = PAD_ID(IMX1_PC, 30),
+ MX1_PAD_BT1 = PAD_ID(IMX1_PC, 31),
+ MX1_PAD_LSCLK = PAD_ID(IMX1_PD, 6),
+ MX1_PAD_REV = PAD_ID(IMX1_PD, 7),
+ MX1_PAD_CLS = PAD_ID(IMX1_PD, 8),
+ MX1_PAD_PS = PAD_ID(IMX1_PD, 9),
+ MX1_PAD_SPL_SPR = PAD_ID(IMX1_PD, 10),
+ MX1_PAD_CONTRAST = PAD_ID(IMX1_PD, 11),
+ MX1_PAD_ACD_OE = PAD_ID(IMX1_PD, 12),
+ MX1_PAD_LP_HSYNC = PAD_ID(IMX1_PD, 13),
+ MX1_PAD_FLM_VSYNC = PAD_ID(IMX1_PD, 14),
+ MX1_PAD_LD0 = PAD_ID(IMX1_PD, 15),
+ MX1_PAD_LD1 = PAD_ID(IMX1_PD, 16),
+ MX1_PAD_LD2 = PAD_ID(IMX1_PD, 17),
+ MX1_PAD_LD3 = PAD_ID(IMX1_PD, 18),
+ MX1_PAD_LD4 = PAD_ID(IMX1_PD, 19),
+ MX1_PAD_LD5 = PAD_ID(IMX1_PD, 20),
+ MX1_PAD_LD6 = PAD_ID(IMX1_PD, 21),
+ MX1_PAD_LD7 = PAD_ID(IMX1_PD, 22),
+ MX1_PAD_LD8 = PAD_ID(IMX1_PD, 23),
+ MX1_PAD_LD9 = PAD_ID(IMX1_PD, 24),
+ MX1_PAD_LD10 = PAD_ID(IMX1_PD, 25),
+ MX1_PAD_LD11 = PAD_ID(IMX1_PD, 26),
+ MX1_PAD_LD12 = PAD_ID(IMX1_PD, 27),
+ MX1_PAD_LD13 = PAD_ID(IMX1_PD, 28),
+ MX1_PAD_LD14 = PAD_ID(IMX1_PD, 29),
+ MX1_PAD_LD15 = PAD_ID(IMX1_PD, 30),
+ MX1_PAD_TMR2OUT = PAD_ID(IMX1_PD, 31),
};
/* Pad names for the pinmux subsystem */
diff --git a/drivers/pinctrl/freescale/pinctrl-imx27.c b/drivers/pinctrl/freescale/pinctrl-imx27.c
index 1738df461235..afeb39957203 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx27.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx27.c
@@ -16,188 +16,188 @@
#include "pinctrl-imx1.h"
#define PAD_ID(port, pin) (port*32 + pin)
-#define PA 0
-#define PB 1
-#define PC 2
-#define PD 3
-#define PE 4
-#define PF 5
+#define MX27_PA 0
+#define MX27_PB 1
+#define MX27_PC 2
+#define MX27_PD 3
+#define MX27_PE 4
+#define MX27_PF 5
enum imx27_pads {
- MX27_PAD_USBH2_CLK = PAD_ID(PA, 0),
- MX27_PAD_USBH2_DIR = PAD_ID(PA, 1),
- MX27_PAD_USBH2_DATA7 = PAD_ID(PA, 2),
- MX27_PAD_USBH2_NXT = PAD_ID(PA, 3),
- MX27_PAD_USBH2_STP = PAD_ID(PA, 4),
- MX27_PAD_LSCLK = PAD_ID(PA, 5),
- MX27_PAD_LD0 = PAD_ID(PA, 6),
- MX27_PAD_LD1 = PAD_ID(PA, 7),
- MX27_PAD_LD2 = PAD_ID(PA, 8),
- MX27_PAD_LD3 = PAD_ID(PA, 9),
- MX27_PAD_LD4 = PAD_ID(PA, 10),
- MX27_PAD_LD5 = PAD_ID(PA, 11),
- MX27_PAD_LD6 = PAD_ID(PA, 12),
- MX27_PAD_LD7 = PAD_ID(PA, 13),
- MX27_PAD_LD8 = PAD_ID(PA, 14),
- MX27_PAD_LD9 = PAD_ID(PA, 15),
- MX27_PAD_LD10 = PAD_ID(PA, 16),
- MX27_PAD_LD11 = PAD_ID(PA, 17),
- MX27_PAD_LD12 = PAD_ID(PA, 18),
- MX27_PAD_LD13 = PAD_ID(PA, 19),
- MX27_PAD_LD14 = PAD_ID(PA, 20),
- MX27_PAD_LD15 = PAD_ID(PA, 21),
- MX27_PAD_LD16 = PAD_ID(PA, 22),
- MX27_PAD_LD17 = PAD_ID(PA, 23),
- MX27_PAD_REV = PAD_ID(PA, 24),
- MX27_PAD_CLS = PAD_ID(PA, 25),
- MX27_PAD_PS = PAD_ID(PA, 26),
- MX27_PAD_SPL_SPR = PAD_ID(PA, 27),
- MX27_PAD_HSYNC = PAD_ID(PA, 28),
- MX27_PAD_VSYNC = PAD_ID(PA, 29),
- MX27_PAD_CONTRAST = PAD_ID(PA, 30),
- MX27_PAD_OE_ACD = PAD_ID(PA, 31),
+ MX27_PAD_USBH2_CLK = PAD_ID(MX27_PA, 0),
+ MX27_PAD_USBH2_DIR = PAD_ID(MX27_PA, 1),
+ MX27_PAD_USBH2_DATA7 = PAD_ID(MX27_PA, 2),
+ MX27_PAD_USBH2_NXT = PAD_ID(MX27_PA, 3),
+ MX27_PAD_USBH2_STP = PAD_ID(MX27_PA, 4),
+ MX27_PAD_LSCLK = PAD_ID(MX27_PA, 5),
+ MX27_PAD_LD0 = PAD_ID(MX27_PA, 6),
+ MX27_PAD_LD1 = PAD_ID(MX27_PA, 7),
+ MX27_PAD_LD2 = PAD_ID(MX27_PA, 8),
+ MX27_PAD_LD3 = PAD_ID(MX27_PA, 9),
+ MX27_PAD_LD4 = PAD_ID(MX27_PA, 10),
+ MX27_PAD_LD5 = PAD_ID(MX27_PA, 11),
+ MX27_PAD_LD6 = PAD_ID(MX27_PA, 12),
+ MX27_PAD_LD7 = PAD_ID(MX27_PA, 13),
+ MX27_PAD_LD8 = PAD_ID(MX27_PA, 14),
+ MX27_PAD_LD9 = PAD_ID(MX27_PA, 15),
+ MX27_PAD_LD10 = PAD_ID(MX27_PA, 16),
+ MX27_PAD_LD11 = PAD_ID(MX27_PA, 17),
+ MX27_PAD_LD12 = PAD_ID(MX27_PA, 18),
+ MX27_PAD_LD13 = PAD_ID(MX27_PA, 19),
+ MX27_PAD_LD14 = PAD_ID(MX27_PA, 20),
+ MX27_PAD_LD15 = PAD_ID(MX27_PA, 21),
+ MX27_PAD_LD16 = PAD_ID(MX27_PA, 22),
+ MX27_PAD_LD17 = PAD_ID(MX27_PA, 23),
+ MX27_PAD_REV = PAD_ID(MX27_PA, 24),
+ MX27_PAD_CLS = PAD_ID(MX27_PA, 25),
+ MX27_PAD_PS = PAD_ID(MX27_PA, 26),
+ MX27_PAD_SPL_SPR = PAD_ID(MX27_PA, 27),
+ MX27_PAD_HSYNC = PAD_ID(MX27_PA, 28),
+ MX27_PAD_VSYNC = PAD_ID(MX27_PA, 29),
+ MX27_PAD_CONTRAST = PAD_ID(MX27_PA, 30),
+ MX27_PAD_OE_ACD = PAD_ID(MX27_PA, 31),
- MX27_PAD_SD2_D0 = PAD_ID(PB, 4),
- MX27_PAD_SD2_D1 = PAD_ID(PB, 5),
- MX27_PAD_SD2_D2 = PAD_ID(PB, 6),
- MX27_PAD_SD2_D3 = PAD_ID(PB, 7),
- MX27_PAD_SD2_CMD = PAD_ID(PB, 8),
- MX27_PAD_SD2_CLK = PAD_ID(PB, 9),
- MX27_PAD_CSI_D0 = PAD_ID(PB, 10),
- MX27_PAD_CSI_D1 = PAD_ID(PB, 11),
- MX27_PAD_CSI_D2 = PAD_ID(PB, 12),
- MX27_PAD_CSI_D3 = PAD_ID(PB, 13),
- MX27_PAD_CSI_D4 = PAD_ID(PB, 14),
- MX27_PAD_CSI_MCLK = PAD_ID(PB, 15),
- MX27_PAD_CSI_PIXCLK = PAD_ID(PB, 16),
- MX27_PAD_CSI_D5 = PAD_ID(PB, 17),
- MX27_PAD_CSI_D6 = PAD_ID(PB, 18),
- MX27_PAD_CSI_D7 = PAD_ID(PB, 19),
- MX27_PAD_CSI_VSYNC = PAD_ID(PB, 20),
- MX27_PAD_CSI_HSYNC = PAD_ID(PB, 21),
- MX27_PAD_USBH1_SUSP = PAD_ID(PB, 22),
- MX27_PAD_USB_PWR = PAD_ID(PB, 23),
- MX27_PAD_USB_OC_B = PAD_ID(PB, 24),
- MX27_PAD_USBH1_RCV = PAD_ID(PB, 25),
- MX27_PAD_USBH1_FS = PAD_ID(PB, 26),
- MX27_PAD_USBH1_OE_B = PAD_ID(PB, 27),
- MX27_PAD_USBH1_TXDM = PAD_ID(PB, 28),
- MX27_PAD_USBH1_TXDP = PAD_ID(PB, 29),
- MX27_PAD_USBH1_RXDM = PAD_ID(PB, 30),
- MX27_PAD_USBH1_RXDP = PAD_ID(PB, 31),
+ MX27_PAD_SD2_D0 = PAD_ID(MX27_PB, 4),
+ MX27_PAD_SD2_D1 = PAD_ID(MX27_PB, 5),
+ MX27_PAD_SD2_D2 = PAD_ID(MX27_PB, 6),
+ MX27_PAD_SD2_D3 = PAD_ID(MX27_PB, 7),
+ MX27_PAD_SD2_CMD = PAD_ID(MX27_PB, 8),
+ MX27_PAD_SD2_CLK = PAD_ID(MX27_PB, 9),
+ MX27_PAD_CSI_D0 = PAD_ID(MX27_PB, 10),
+ MX27_PAD_CSI_D1 = PAD_ID(MX27_PB, 11),
+ MX27_PAD_CSI_D2 = PAD_ID(MX27_PB, 12),
+ MX27_PAD_CSI_D3 = PAD_ID(MX27_PB, 13),
+ MX27_PAD_CSI_D4 = PAD_ID(MX27_PB, 14),
+ MX27_PAD_CSI_MCLK = PAD_ID(MX27_PB, 15),
+ MX27_PAD_CSI_PIXCLK = PAD_ID(MX27_PB, 16),
+ MX27_PAD_CSI_D5 = PAD_ID(MX27_PB, 17),
+ MX27_PAD_CSI_D6 = PAD_ID(MX27_PB, 18),
+ MX27_PAD_CSI_D7 = PAD_ID(MX27_PB, 19),
+ MX27_PAD_CSI_VSYNC = PAD_ID(MX27_PB, 20),
+ MX27_PAD_CSI_HSYNC = PAD_ID(MX27_PB, 21),
+ MX27_PAD_USBH1_SUSP = PAD_ID(MX27_PB, 22),
+ MX27_PAD_USB_PWR = PAD_ID(MX27_PB, 23),
+ MX27_PAD_USB_OC_B = PAD_ID(MX27_PB, 24),
+ MX27_PAD_USBH1_RCV = PAD_ID(MX27_PB, 25),
+ MX27_PAD_USBH1_FS = PAD_ID(MX27_PB, 26),
+ MX27_PAD_USBH1_OE_B = PAD_ID(MX27_PB, 27),
+ MX27_PAD_USBH1_TXDM = PAD_ID(MX27_PB, 28),
+ MX27_PAD_USBH1_TXDP = PAD_ID(MX27_PB, 29),
+ MX27_PAD_USBH1_RXDM = PAD_ID(MX27_PB, 30),
+ MX27_PAD_USBH1_RXDP = PAD_ID(MX27_PB, 31),
- MX27_PAD_I2C2_SDA = PAD_ID(PC, 5),
- MX27_PAD_I2C2_SCL = PAD_ID(PC, 6),
- MX27_PAD_USBOTG_DATA5 = PAD_ID(PC, 7),
- MX27_PAD_USBOTG_DATA6 = PAD_ID(PC, 8),
- MX27_PAD_USBOTG_DATA0 = PAD_ID(PC, 9),
- MX27_PAD_USBOTG_DATA2 = PAD_ID(PC, 10),
- MX27_PAD_USBOTG_DATA1 = PAD_ID(PC, 11),
- MX27_PAD_USBOTG_DATA4 = PAD_ID(PC, 12),
- MX27_PAD_USBOTG_DATA3 = PAD_ID(PC, 13),
- MX27_PAD_TOUT = PAD_ID(PC, 14),
- MX27_PAD_TIN = PAD_ID(PC, 15),
- MX27_PAD_SSI4_FS = PAD_ID(PC, 16),
- MX27_PAD_SSI4_RXDAT = PAD_ID(PC, 17),
- MX27_PAD_SSI4_TXDAT = PAD_ID(PC, 18),
- MX27_PAD_SSI4_CLK = PAD_ID(PC, 19),
- MX27_PAD_SSI1_FS = PAD_ID(PC, 20),
- MX27_PAD_SSI1_RXDAT = PAD_ID(PC, 21),
- MX27_PAD_SSI1_TXDAT = PAD_ID(PC, 22),
- MX27_PAD_SSI1_CLK = PAD_ID(PC, 23),
- MX27_PAD_SSI2_FS = PAD_ID(PC, 24),
- MX27_PAD_SSI2_RXDAT = PAD_ID(PC, 25),
- MX27_PAD_SSI2_TXDAT = PAD_ID(PC, 26),
- MX27_PAD_SSI2_CLK = PAD_ID(PC, 27),
- MX27_PAD_SSI3_FS = PAD_ID(PC, 28),
- MX27_PAD_SSI3_RXDAT = PAD_ID(PC, 29),
- MX27_PAD_SSI3_TXDAT = PAD_ID(PC, 30),
- MX27_PAD_SSI3_CLK = PAD_ID(PC, 31),
+ MX27_PAD_I2C2_SDA = PAD_ID(MX27_PC, 5),
+ MX27_PAD_I2C2_SCL = PAD_ID(MX27_PC, 6),
+ MX27_PAD_USBOTG_DATA5 = PAD_ID(MX27_PC, 7),
+ MX27_PAD_USBOTG_DATA6 = PAD_ID(MX27_PC, 8),
+ MX27_PAD_USBOTG_DATA0 = PAD_ID(MX27_PC, 9),
+ MX27_PAD_USBOTG_DATA2 = PAD_ID(MX27_PC, 10),
+ MX27_PAD_USBOTG_DATA1 = PAD_ID(MX27_PC, 11),
+ MX27_PAD_USBOTG_DATA4 = PAD_ID(MX27_PC, 12),
+ MX27_PAD_USBOTG_DATA3 = PAD_ID(MX27_PC, 13),
+ MX27_PAD_TOUT = PAD_ID(MX27_PC, 14),
+ MX27_PAD_TIN = PAD_ID(MX27_PC, 15),
+ MX27_PAD_SSI4_FS = PAD_ID(MX27_PC, 16),
+ MX27_PAD_SSI4_RXDAT = PAD_ID(MX27_PC, 17),
+ MX27_PAD_SSI4_TXDAT = PAD_ID(MX27_PC, 18),
+ MX27_PAD_SSI4_CLK = PAD_ID(MX27_PC, 19),
+ MX27_PAD_SSI1_FS = PAD_ID(MX27_PC, 20),
+ MX27_PAD_SSI1_RXDAT = PAD_ID(MX27_PC, 21),
+ MX27_PAD_SSI1_TXDAT = PAD_ID(MX27_PC, 22),
+ MX27_PAD_SSI1_CLK = PAD_ID(MX27_PC, 23),
+ MX27_PAD_SSI2_FS = PAD_ID(MX27_PC, 24),
+ MX27_PAD_SSI2_RXDAT = PAD_ID(MX27_PC, 25),
+ MX27_PAD_SSI2_TXDAT = PAD_ID(MX27_PC, 26),
+ MX27_PAD_SSI2_CLK = PAD_ID(MX27_PC, 27),
+ MX27_PAD_SSI3_FS = PAD_ID(MX27_PC, 28),
+ MX27_PAD_SSI3_RXDAT = PAD_ID(MX27_PC, 29),
+ MX27_PAD_SSI3_TXDAT = PAD_ID(MX27_PC, 30),
+ MX27_PAD_SSI3_CLK = PAD_ID(MX27_PC, 31),
- MX27_PAD_SD3_CMD = PAD_ID(PD, 0),
- MX27_PAD_SD3_CLK = PAD_ID(PD, 1),
- MX27_PAD_ATA_DATA0 = PAD_ID(PD, 2),
- MX27_PAD_ATA_DATA1 = PAD_ID(PD, 3),
- MX27_PAD_ATA_DATA2 = PAD_ID(PD, 4),
- MX27_PAD_ATA_DATA3 = PAD_ID(PD, 5),
- MX27_PAD_ATA_DATA4 = PAD_ID(PD, 6),
- MX27_PAD_ATA_DATA5 = PAD_ID(PD, 7),
- MX27_PAD_ATA_DATA6 = PAD_ID(PD, 8),
- MX27_PAD_ATA_DATA7 = PAD_ID(PD, 9),
- MX27_PAD_ATA_DATA8 = PAD_ID(PD, 10),
- MX27_PAD_ATA_DATA9 = PAD_ID(PD, 11),
- MX27_PAD_ATA_DATA10 = PAD_ID(PD, 12),
- MX27_PAD_ATA_DATA11 = PAD_ID(PD, 13),
- MX27_PAD_ATA_DATA12 = PAD_ID(PD, 14),
- MX27_PAD_ATA_DATA13 = PAD_ID(PD, 15),
- MX27_PAD_ATA_DATA14 = PAD_ID(PD, 16),
- MX27_PAD_I2C_DATA = PAD_ID(PD, 17),
- MX27_PAD_I2C_CLK = PAD_ID(PD, 18),
- MX27_PAD_CSPI2_SS2 = PAD_ID(PD, 19),
- MX27_PAD_CSPI2_SS1 = PAD_ID(PD, 20),
- MX27_PAD_CSPI2_SS0 = PAD_ID(PD, 21),
- MX27_PAD_CSPI2_SCLK = PAD_ID(PD, 22),
- MX27_PAD_CSPI2_MISO = PAD_ID(PD, 23),
- MX27_PAD_CSPI2_MOSI = PAD_ID(PD, 24),
- MX27_PAD_CSPI1_RDY = PAD_ID(PD, 25),
- MX27_PAD_CSPI1_SS2 = PAD_ID(PD, 26),
- MX27_PAD_CSPI1_SS1 = PAD_ID(PD, 27),
- MX27_PAD_CSPI1_SS0 = PAD_ID(PD, 28),
- MX27_PAD_CSPI1_SCLK = PAD_ID(PD, 29),
- MX27_PAD_CSPI1_MISO = PAD_ID(PD, 30),
- MX27_PAD_CSPI1_MOSI = PAD_ID(PD, 31),
+ MX27_PAD_SD3_CMD = PAD_ID(MX27_PD, 0),
+ MX27_PAD_SD3_CLK = PAD_ID(MX27_PD, 1),
+ MX27_PAD_ATA_DATA0 = PAD_ID(MX27_PD, 2),
+ MX27_PAD_ATA_DATA1 = PAD_ID(MX27_PD, 3),
+ MX27_PAD_ATA_DATA2 = PAD_ID(MX27_PD, 4),
+ MX27_PAD_ATA_DATA3 = PAD_ID(MX27_PD, 5),
+ MX27_PAD_ATA_DATA4 = PAD_ID(MX27_PD, 6),
+ MX27_PAD_ATA_DATA5 = PAD_ID(MX27_PD, 7),
+ MX27_PAD_ATA_DATA6 = PAD_ID(MX27_PD, 8),
+ MX27_PAD_ATA_DATA7 = PAD_ID(MX27_PD, 9),
+ MX27_PAD_ATA_DATA8 = PAD_ID(MX27_PD, 10),
+ MX27_PAD_ATA_DATA9 = PAD_ID(MX27_PD, 11),
+ MX27_PAD_ATA_DATA10 = PAD_ID(MX27_PD, 12),
+ MX27_PAD_ATA_DATA11 = PAD_ID(MX27_PD, 13),
+ MX27_PAD_ATA_DATA12 = PAD_ID(MX27_PD, 14),
+ MX27_PAD_ATA_DATA13 = PAD_ID(MX27_PD, 15),
+ MX27_PAD_ATA_DATA14 = PAD_ID(MX27_PD, 16),
+ MX27_PAD_I2C_DATA = PAD_ID(MX27_PD, 17),
+ MX27_PAD_I2C_CLK = PAD_ID(MX27_PD, 18),
+ MX27_PAD_CSPI2_SS2 = PAD_ID(MX27_PD, 19),
+ MX27_PAD_CSPI2_SS1 = PAD_ID(MX27_PD, 20),
+ MX27_PAD_CSPI2_SS0 = PAD_ID(MX27_PD, 21),
+ MX27_PAD_CSPI2_SCLK = PAD_ID(MX27_PD, 22),
+ MX27_PAD_CSPI2_MISO = PAD_ID(MX27_PD, 23),
+ MX27_PAD_CSPI2_MOSI = PAD_ID(MX27_PD, 24),
+ MX27_PAD_CSPI1_RDY = PAD_ID(MX27_PD, 25),
+ MX27_PAD_CSPI1_SS2 = PAD_ID(MX27_PD, 26),
+ MX27_PAD_CSPI1_SS1 = PAD_ID(MX27_PD, 27),
+ MX27_PAD_CSPI1_SS0 = PAD_ID(MX27_PD, 28),
+ MX27_PAD_CSPI1_SCLK = PAD_ID(MX27_PD, 29),
+ MX27_PAD_CSPI1_MISO = PAD_ID(MX27_PD, 30),
+ MX27_PAD_CSPI1_MOSI = PAD_ID(MX27_PD, 31),
- MX27_PAD_USBOTG_NXT = PAD_ID(PE, 0),
- MX27_PAD_USBOTG_STP = PAD_ID(PE, 1),
- MX27_PAD_USBOTG_DIR = PAD_ID(PE, 2),
- MX27_PAD_UART2_CTS = PAD_ID(PE, 3),
- MX27_PAD_UART2_RTS = PAD_ID(PE, 4),
- MX27_PAD_PWMO = PAD_ID(PE, 5),
- MX27_PAD_UART2_TXD = PAD_ID(PE, 6),
- MX27_PAD_UART2_RXD = PAD_ID(PE, 7),
- MX27_PAD_UART3_TXD = PAD_ID(PE, 8),
- MX27_PAD_UART3_RXD = PAD_ID(PE, 9),
- MX27_PAD_UART3_CTS = PAD_ID(PE, 10),
- MX27_PAD_UART3_RTS = PAD_ID(PE, 11),
- MX27_PAD_UART1_TXD = PAD_ID(PE, 12),
- MX27_PAD_UART1_RXD = PAD_ID(PE, 13),
- MX27_PAD_UART1_CTS = PAD_ID(PE, 14),
- MX27_PAD_UART1_RTS = PAD_ID(PE, 15),
- MX27_PAD_RTCK = PAD_ID(PE, 16),
- MX27_PAD_RESET_OUT_B = PAD_ID(PE, 17),
- MX27_PAD_SD1_D0 = PAD_ID(PE, 18),
- MX27_PAD_SD1_D1 = PAD_ID(PE, 19),
- MX27_PAD_SD1_D2 = PAD_ID(PE, 20),
- MX27_PAD_SD1_D3 = PAD_ID(PE, 21),
- MX27_PAD_SD1_CMD = PAD_ID(PE, 22),
- MX27_PAD_SD1_CLK = PAD_ID(PE, 23),
- MX27_PAD_USBOTG_CLK = PAD_ID(PE, 24),
- MX27_PAD_USBOTG_DATA7 = PAD_ID(PE, 25),
+ MX27_PAD_USBOTG_NXT = PAD_ID(MX27_PE, 0),
+ MX27_PAD_USBOTG_STP = PAD_ID(MX27_PE, 1),
+ MX27_PAD_USBOTG_DIR = PAD_ID(MX27_PE, 2),
+ MX27_PAD_UART2_CTS = PAD_ID(MX27_PE, 3),
+ MX27_PAD_UART2_RTS = PAD_ID(MX27_PE, 4),
+ MX27_PAD_PWMO = PAD_ID(MX27_PE, 5),
+ MX27_PAD_UART2_TXD = PAD_ID(MX27_PE, 6),
+ MX27_PAD_UART2_RXD = PAD_ID(MX27_PE, 7),
+ MX27_PAD_UART3_TXD = PAD_ID(MX27_PE, 8),
+ MX27_PAD_UART3_RXD = PAD_ID(MX27_PE, 9),
+ MX27_PAD_UART3_CTS = PAD_ID(MX27_PE, 10),
+ MX27_PAD_UART3_RTS = PAD_ID(MX27_PE, 11),
+ MX27_PAD_UART1_TXD = PAD_ID(MX27_PE, 12),
+ MX27_PAD_UART1_RXD = PAD_ID(MX27_PE, 13),
+ MX27_PAD_UART1_CTS = PAD_ID(MX27_PE, 14),
+ MX27_PAD_UART1_RTS = PAD_ID(MX27_PE, 15),
+ MX27_PAD_RTCK = PAD_ID(MX27_PE, 16),
+ MX27_PAD_RESET_OUT_B = PAD_ID(MX27_PE, 17),
+ MX27_PAD_SD1_D0 = PAD_ID(MX27_PE, 18),
+ MX27_PAD_SD1_D1 = PAD_ID(MX27_PE, 19),
+ MX27_PAD_SD1_D2 = PAD_ID(MX27_PE, 20),
+ MX27_PAD_SD1_D3 = PAD_ID(MX27_PE, 21),
+ MX27_PAD_SD1_CMD = PAD_ID(MX27_PE, 22),
+ MX27_PAD_SD1_CLK = PAD_ID(MX27_PE, 23),
+ MX27_PAD_USBOTG_CLK = PAD_ID(MX27_PE, 24),
+ MX27_PAD_USBOTG_DATA7 = PAD_ID(MX27_PE, 25),
- MX27_PAD_NFRB = PAD_ID(PF, 0),
- MX27_PAD_NFCLE = PAD_ID(PF, 1),
- MX27_PAD_NFWP_B = PAD_ID(PF, 2),
- MX27_PAD_NFCE_B = PAD_ID(PF, 3),
- MX27_PAD_NFALE = PAD_ID(PF, 4),
- MX27_PAD_NFRE_B = PAD_ID(PF, 5),
- MX27_PAD_NFWE_B = PAD_ID(PF, 6),
- MX27_PAD_PC_POE = PAD_ID(PF, 7),
- MX27_PAD_PC_RW_B = PAD_ID(PF, 8),
- MX27_PAD_IOIS16 = PAD_ID(PF, 9),
- MX27_PAD_PC_RST = PAD_ID(PF, 10),
- MX27_PAD_PC_BVD2 = PAD_ID(PF, 11),
- MX27_PAD_PC_BVD1 = PAD_ID(PF, 12),
- MX27_PAD_PC_VS2 = PAD_ID(PF, 13),
- MX27_PAD_PC_VS1 = PAD_ID(PF, 14),
- MX27_PAD_CLKO = PAD_ID(PF, 15),
- MX27_PAD_PC_PWRON = PAD_ID(PF, 16),
- MX27_PAD_PC_READY = PAD_ID(PF, 17),
- MX27_PAD_PC_WAIT_B = PAD_ID(PF, 18),
- MX27_PAD_PC_CD2_B = PAD_ID(PF, 19),
- MX27_PAD_PC_CD1_B = PAD_ID(PF, 20),
- MX27_PAD_CS4_B = PAD_ID(PF, 21),
- MX27_PAD_CS5_B = PAD_ID(PF, 22),
- MX27_PAD_ATA_DATA15 = PAD_ID(PF, 23),
+ MX27_PAD_NFRB = PAD_ID(MX27_PF, 0),
+ MX27_PAD_NFCLE = PAD_ID(MX27_PF, 1),
+ MX27_PAD_NFWP_B = PAD_ID(MX27_PF, 2),
+ MX27_PAD_NFCE_B = PAD_ID(MX27_PF, 3),
+ MX27_PAD_NFALE = PAD_ID(MX27_PF, 4),
+ MX27_PAD_NFRE_B = PAD_ID(MX27_PF, 5),
+ MX27_PAD_NFWE_B = PAD_ID(MX27_PF, 6),
+ MX27_PAD_PC_POE = PAD_ID(MX27_PF, 7),
+ MX27_PAD_PC_RW_B = PAD_ID(MX27_PF, 8),
+ MX27_PAD_IOIS16 = PAD_ID(MX27_PF, 9),
+ MX27_PAD_PC_RST = PAD_ID(MX27_PF, 10),
+ MX27_PAD_PC_BVD2 = PAD_ID(MX27_PF, 11),
+ MX27_PAD_PC_BVD1 = PAD_ID(MX27_PF, 12),
+ MX27_PAD_PC_VS2 = PAD_ID(MX27_PF, 13),
+ MX27_PAD_PC_VS1 = PAD_ID(MX27_PF, 14),
+ MX27_PAD_CLKO = PAD_ID(MX27_PF, 15),
+ MX27_PAD_PC_PWRON = PAD_ID(MX27_PF, 16),
+ MX27_PAD_PC_READY = PAD_ID(MX27_PF, 17),
+ MX27_PAD_PC_WAIT_B = PAD_ID(MX27_PF, 18),
+ MX27_PAD_PC_CD2_B = PAD_ID(MX27_PF, 19),
+ MX27_PAD_PC_CD1_B = PAD_ID(MX27_PF, 20),
+ MX27_PAD_CS4_B = PAD_ID(MX27_PF, 21),
+ MX27_PAD_CS5_B = PAD_ID(MX27_PF, 22),
+ MX27_PAD_ATA_DATA15 = PAD_ID(MX27_PF, 23),
};
/* Pad names for the pinmux subsystem */
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 067b0d344f0e..9f938718927b 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1792,7 +1792,7 @@ MODULE_DEVICE_TABLE(acpi, chv_pinctrl_acpi_match);
static struct platform_driver chv_pinctrl_driver = {
.probe = chv_pinctrl_probe,
- .remove_new = chv_pinctrl_remove,
+ .remove = chv_pinctrl_remove,
.driver = {
.name = "cherryview-pinctrl",
.pm = pm_sleep_ptr(&chv_pinctrl_pm_ops),
diff --git a/drivers/pinctrl/intel/pinctrl-elkhartlake.c b/drivers/pinctrl/intel/pinctrl-elkhartlake.c
index 1678634ebc06..3e45d7fb003a 100644
--- a/drivers/pinctrl/intel/pinctrl-elkhartlake.c
+++ b/drivers/pinctrl/intel/pinctrl-elkhartlake.c
@@ -264,6 +264,43 @@ static const struct intel_pinctrl_soc_data ehl_community1_soc_data = {
.ncommunities = ARRAY_SIZE(ehl_community1),
};
+static const struct pinctrl_pin_desc ehl_community2_pins[] = {
+ /* DSW */
+ PINCTRL_PIN(0, "BATLOWB"),
+ PINCTRL_PIN(1, "ACPRESENT"),
+ PINCTRL_PIN(2, "LAN_WAKEB"),
+ PINCTRL_PIN(3, "PWRBTNB"),
+ PINCTRL_PIN(4, "SLP_S3B"),
+ PINCTRL_PIN(5, "SLP_S4B"),
+ PINCTRL_PIN(6, "SLP_AB"),
+ PINCTRL_PIN(7, "GPD_7"),
+ PINCTRL_PIN(8, "SUSCLK"),
+ PINCTRL_PIN(9, "SLP_WLANB"),
+ PINCTRL_PIN(10, "SLP_S5B"),
+ PINCTRL_PIN(11, "LANPHYPC"),
+ PINCTRL_PIN(12, "INPUT3VSEL"),
+ PINCTRL_PIN(13, "SLP_LANB"),
+ PINCTRL_PIN(14, "SLP_SUSB"),
+ PINCTRL_PIN(15, "WAKEB"),
+ PINCTRL_PIN(16, "DRAM_RESETB"),
+};
+
+static const struct intel_padgroup ehl_community2_gpps[] = {
+ EHL_GPP(0, 0, 16), /* DSW */
+};
+
+static const struct intel_community ehl_community2[] = {
+ EHL_COMMUNITY(0, 0, 16, ehl_community2_gpps),
+};
+
+static const struct intel_pinctrl_soc_data ehl_community2_soc_data = {
+ .uid = "2",
+ .pins = ehl_community2_pins,
+ .npins = ARRAY_SIZE(ehl_community2_pins),
+ .communities = ehl_community2,
+ .ncommunities = ARRAY_SIZE(ehl_community2),
+};
+
static const struct pinctrl_pin_desc ehl_community3_pins[] = {
/* CPU */
PINCTRL_PIN(0, "HDACPU_SDI"),
@@ -474,6 +511,7 @@ static const struct intel_pinctrl_soc_data ehl_community5_soc_data = {
static const struct intel_pinctrl_soc_data *ehl_soc_data_array[] = {
&ehl_community0_soc_data,
&ehl_community1_soc_data,
+ &ehl_community2_soc_data,
&ehl_community3_soc_data,
&ehl_community4_soc_data,
&ehl_community5_soc_data,
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 928607a21d36..04b438f63ccb 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -85,6 +85,18 @@
#define PADCFG1_TERM_UP BIT(13)
#define PADCFG1_TERM_SHIFT 10
#define PADCFG1_TERM_MASK GENMASK(12, 10)
+/*
+ * Bit 0 Bit 1 Bit 2 Value, Ohms
+ *
+ * 0 0 0 -
+ * 0 0 1 20000
+ * 0 1 0 5000
+ * 0 1 1 ~4000
+ * 1 0 0 1000 (if supported)
+ * 1 0 1 ~952 (if supported)
+ * 1 1 0 ~833 (if supported)
+ * 1 1 1 ~800 (if supported)
+ */
#define PADCFG1_TERM_20K BIT(2)
#define PADCFG1_TERM_5K BIT(1)
#define PADCFG1_TERM_4K (BIT(2) | BIT(1))
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 7af287252834..a417a031659c 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "MediaTek pinctrl drivers"
- depends on ARCH_MEDIATEK || RALINK || COMPILE_TEST
+ depends on ARCH_MEDIATEK || ARCH_AIROHA || RALINK || COMPILE_TEST
config EINT_MTK
tristate "MediaTek External Interrupt Support"
@@ -126,6 +126,21 @@ config PINCTRL_MT8127
select PINCTRL_MTK
# For ARMv8 SoCs
+config PINCTRL_AIROHA
+ tristate "Airoha EN7581 pin control"
+ depends on OF
+ depends on ARM64 || COMPILE_TEST
+ select PINMUX
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GPIOLIB
+ select GPIOLIB_IRQCHIP
+ select REGMAP_MMIO
+ help
+ Say yes here to support pin controller and gpio driver
+ on Airoha EN7581 SoC.
+
config PINCTRL_MT2712
bool "MediaTek MT2712 pin control"
depends on OF
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index 680f7e8526e0..1405d434218e 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinctrl-moore.o
obj-$(CONFIG_PINCTRL_MTK_PARIS) += pinctrl-paris.o
# SoC Drivers
+obj-$(CONFIG_PINCTRL_AIROHA) += pinctrl-airoha.o
obj-$(CONFIG_PINCTRL_MT7620) += pinctrl-mt7620.o
obj-$(CONFIG_PINCTRL_MT7621) += pinctrl-mt7621.o
obj-$(CONFIG_PINCTRL_MT76X8) += pinctrl-mt76x8.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c
new file mode 100644
index 000000000000..547a798b71c8
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
@@ -0,0 +1,2971 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
+ * Author: Benjamin Larsson <benjamin.larsson@genexis.eu>
+ * Author: Markus Gothe <markus.gothe@genexis.eu>
+ */
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#define PINCTRL_PIN_GROUP(id) \
+ PINCTRL_PINGROUP(#id, id##_pins, ARRAY_SIZE(id##_pins))
+
+#define PINCTRL_FUNC_DESC(id) \
+ { \
+ .desc = { \
+ .func = { \
+ .name = #id, \
+ .groups = id##_groups, \
+ .ngroups = ARRAY_SIZE(id##_groups), \
+ } \
+ }, \
+ .groups = id##_func_group, \
+ .group_size = ARRAY_SIZE(id##_func_group), \
+ }
+
+#define PINCTRL_CONF_DESC(p, offset, mask) \
+ { \
+ .pin = p, \
+ .reg = { offset, mask }, \
+ }
+
+/* MUX */
+#define REG_GPIO_2ND_I2C_MODE 0x0214
+#define GPIO_MDC_IO_MASTER_MODE_MODE BIT(14)
+#define GPIO_I2C_MASTER_MODE_MODE BIT(13)
+#define GPIO_I2S_MODE_MASK BIT(12)
+#define GPIO_I2C_SLAVE_MODE_MODE BIT(11)
+#define GPIO_LAN3_LED1_MODE_MASK BIT(10)
+#define GPIO_LAN3_LED0_MODE_MASK BIT(9)
+#define GPIO_LAN2_LED1_MODE_MASK BIT(8)
+#define GPIO_LAN2_LED0_MODE_MASK BIT(7)
+#define GPIO_LAN1_LED1_MODE_MASK BIT(6)
+#define GPIO_LAN1_LED0_MODE_MASK BIT(5)
+#define GPIO_LAN0_LED1_MODE_MASK BIT(4)
+#define GPIO_LAN0_LED0_MODE_MASK BIT(3)
+#define PON_TOD_1PPS_MODE_MASK BIT(2)
+#define GSW_TOD_1PPS_MODE_MASK BIT(1)
+#define GPIO_2ND_I2C_MODE_MASK BIT(0)
+
+#define REG_GPIO_SPI_CS1_MODE 0x0218
+#define GPIO_PCM_SPI_CS4_MODE_MASK BIT(21)
+#define GPIO_PCM_SPI_CS3_MODE_MASK BIT(20)
+#define GPIO_PCM_SPI_CS2_MODE_P156_MASK BIT(19)
+#define GPIO_PCM_SPI_CS2_MODE_P128_MASK BIT(18)
+#define GPIO_PCM_SPI_CS1_MODE_MASK BIT(17)
+#define GPIO_PCM_SPI_MODE_MASK BIT(16)
+#define GPIO_PCM2_MODE_MASK BIT(13)
+#define GPIO_PCM1_MODE_MASK BIT(12)
+#define GPIO_PCM_INT_MODE_MASK BIT(9)
+#define GPIO_PCM_RESET_MODE_MASK BIT(8)
+#define GPIO_SPI_QUAD_MODE_MASK BIT(4)
+#define GPIO_SPI_CS4_MODE_MASK BIT(3)
+#define GPIO_SPI_CS3_MODE_MASK BIT(2)
+#define GPIO_SPI_CS2_MODE_MASK BIT(1)
+#define GPIO_SPI_CS1_MODE_MASK BIT(0)
+
+#define REG_GPIO_PON_MODE 0x021c
+#define GPIO_PARALLEL_NAND_MODE_MASK BIT(14)
+#define GPIO_SGMII_MDIO_MODE_MASK BIT(13)
+#define GPIO_PCIE_RESET2_MASK BIT(12)
+#define SIPO_RCLK_MODE_MASK BIT(11)
+#define GPIO_PCIE_RESET1_MASK BIT(10)
+#define GPIO_PCIE_RESET0_MASK BIT(9)
+#define GPIO_UART5_MODE_MASK BIT(8)
+#define GPIO_UART4_MODE_MASK BIT(7)
+#define GPIO_HSUART_CTS_RTS_MODE_MASK BIT(6)
+#define GPIO_HSUART_MODE_MASK BIT(5)
+#define GPIO_UART2_CTS_RTS_MODE_MASK BIT(4)
+#define GPIO_UART2_MODE_MASK BIT(3)
+#define GPIO_SIPO_MODE_MASK BIT(2)
+#define GPIO_EMMC_MODE_MASK BIT(1)
+#define GPIO_PON_MODE_MASK BIT(0)
+
+#define REG_NPU_UART_EN 0x0224
+#define JTAG_UDI_EN_MASK BIT(4)
+#define JTAG_DFD_EN_MASK BIT(3)
+
+/* LED MAP */
+#define REG_LAN_LED0_MAPPING 0x027c
+#define REG_LAN_LED1_MAPPING 0x0280
+
+#define LAN4_LED_MAPPING_MASK GENMASK(18, 16)
+#define LAN4_PHY4_LED_MAP BIT(18)
+#define LAN4_PHY2_LED_MAP BIT(17)
+#define LAN4_PHY1_LED_MAP BIT(16)
+#define LAN4_PHY0_LED_MAP 0
+#define LAN4_PHY3_LED_MAP GENMASK(17, 16)
+
+#define LAN3_LED_MAPPING_MASK GENMASK(14, 12)
+#define LAN3_PHY4_LED_MAP BIT(14)
+#define LAN3_PHY2_LED_MAP BIT(13)
+#define LAN3_PHY1_LED_MAP BIT(12)
+#define LAN3_PHY0_LED_MAP 0
+#define LAN3_PHY3_LED_MAP GENMASK(13, 12)
+
+#define LAN2_LED_MAPPING_MASK GENMASK(10, 8)
+#define LAN2_PHY4_LED_MAP BIT(12)
+#define LAN2_PHY2_LED_MAP BIT(11)
+#define LAN2_PHY1_LED_MAP BIT(10)
+#define LAN2_PHY0_LED_MAP 0
+#define LAN2_PHY3_LED_MAP GENMASK(11, 10)
+
+#define LAN1_LED_MAPPING_MASK GENMASK(6, 4)
+#define LAN1_PHY4_LED_MAP BIT(6)
+#define LAN1_PHY2_LED_MAP BIT(5)
+#define LAN1_PHY1_LED_MAP BIT(4)
+#define LAN1_PHY0_LED_MAP 0
+#define LAN1_PHY3_LED_MAP GENMASK(5, 4)
+
+#define LAN0_LED_MAPPING_MASK GENMASK(2, 0)
+#define LAN0_PHY4_LED_MAP BIT(3)
+#define LAN0_PHY2_LED_MAP BIT(2)
+#define LAN0_PHY1_LED_MAP BIT(1)
+#define LAN0_PHY0_LED_MAP 0
+#define LAN0_PHY3_LED_MAP GENMASK(2, 1)
+
+/* CONF */
+#define REG_I2C_SDA_E2 0x001c
+#define SPI_MISO_E2_MASK BIT(14)
+#define SPI_MOSI_E2_MASK BIT(13)
+#define SPI_CLK_E2_MASK BIT(12)
+#define SPI_CS0_E2_MASK BIT(11)
+#define PCIE2_RESET_E2_MASK BIT(10)
+#define PCIE1_RESET_E2_MASK BIT(9)
+#define PCIE0_RESET_E2_MASK BIT(8)
+#define UART1_RXD_E2_MASK BIT(3)
+#define UART1_TXD_E2_MASK BIT(2)
+#define I2C_SCL_E2_MASK BIT(1)
+#define I2C_SDA_E2_MASK BIT(0)
+
+#define REG_I2C_SDA_E4 0x0020
+#define SPI_MISO_E4_MASK BIT(14)
+#define SPI_MOSI_E4_MASK BIT(13)
+#define SPI_CLK_E4_MASK BIT(12)
+#define SPI_CS0_E4_MASK BIT(11)
+#define PCIE2_RESET_E4_MASK BIT(10)
+#define PCIE1_RESET_E4_MASK BIT(9)
+#define PCIE0_RESET_E4_MASK BIT(8)
+#define UART1_RXD_E4_MASK BIT(3)
+#define UART1_TXD_E4_MASK BIT(2)
+#define I2C_SCL_E4_MASK BIT(1)
+#define I2C_SDA_E4_MASK BIT(0)
+
+#define REG_GPIO_L_E2 0x0024
+#define REG_GPIO_L_E4 0x0028
+#define REG_GPIO_H_E2 0x002c
+#define REG_GPIO_H_E4 0x0030
+
+#define REG_I2C_SDA_PU 0x0044
+#define SPI_MISO_PU_MASK BIT(14)
+#define SPI_MOSI_PU_MASK BIT(13)
+#define SPI_CLK_PU_MASK BIT(12)
+#define SPI_CS0_PU_MASK BIT(11)
+#define PCIE2_RESET_PU_MASK BIT(10)
+#define PCIE1_RESET_PU_MASK BIT(9)
+#define PCIE0_RESET_PU_MASK BIT(8)
+#define UART1_RXD_PU_MASK BIT(3)
+#define UART1_TXD_PU_MASK BIT(2)
+#define I2C_SCL_PU_MASK BIT(1)
+#define I2C_SDA_PU_MASK BIT(0)
+
+#define REG_I2C_SDA_PD 0x0048
+#define SPI_MISO_PD_MASK BIT(14)
+#define SPI_MOSI_PD_MASK BIT(13)
+#define SPI_CLK_PD_MASK BIT(12)
+#define SPI_CS0_PD_MASK BIT(11)
+#define PCIE2_RESET_PD_MASK BIT(10)
+#define PCIE1_RESET_PD_MASK BIT(9)
+#define PCIE0_RESET_PD_MASK BIT(8)
+#define UART1_RXD_PD_MASK BIT(3)
+#define UART1_TXD_PD_MASK BIT(2)
+#define I2C_SCL_PD_MASK BIT(1)
+#define I2C_SDA_PD_MASK BIT(0)
+
+#define REG_GPIO_L_PU 0x004c
+#define REG_GPIO_L_PD 0x0050
+#define REG_GPIO_H_PU 0x0054
+#define REG_GPIO_H_PD 0x0058
+
+#define REG_PCIE_RESET_OD 0x018c
+#define PCIE2_RESET_OD_MASK BIT(2)
+#define PCIE1_RESET_OD_MASK BIT(1)
+#define PCIE0_RESET_OD_MASK BIT(0)
+
+/* GPIOs */
+#define REG_GPIO_CTRL 0x0000
+#define REG_GPIO_DATA 0x0004
+#define REG_GPIO_INT 0x0008
+#define REG_GPIO_INT_EDGE 0x000c
+#define REG_GPIO_INT_LEVEL 0x0010
+#define REG_GPIO_OE 0x0014
+#define REG_GPIO_CTRL1 0x0020
+
+/* PWM MODE CONF */
+#define REG_GPIO_FLASH_MODE_CFG 0x0034
+#define GPIO15_FLASH_MODE_CFG BIT(15)
+#define GPIO14_FLASH_MODE_CFG BIT(14)
+#define GPIO13_FLASH_MODE_CFG BIT(13)
+#define GPIO12_FLASH_MODE_CFG BIT(12)
+#define GPIO11_FLASH_MODE_CFG BIT(11)
+#define GPIO10_FLASH_MODE_CFG BIT(10)
+#define GPIO9_FLASH_MODE_CFG BIT(9)
+#define GPIO8_FLASH_MODE_CFG BIT(8)
+#define GPIO7_FLASH_MODE_CFG BIT(7)
+#define GPIO6_FLASH_MODE_CFG BIT(6)
+#define GPIO5_FLASH_MODE_CFG BIT(5)
+#define GPIO4_FLASH_MODE_CFG BIT(4)
+#define GPIO3_FLASH_MODE_CFG BIT(3)
+#define GPIO2_FLASH_MODE_CFG BIT(2)
+#define GPIO1_FLASH_MODE_CFG BIT(1)
+#define GPIO0_FLASH_MODE_CFG BIT(0)
+
+#define REG_GPIO_CTRL2 0x0060
+#define REG_GPIO_CTRL3 0x0064
+
+/* PWM MODE CONF EXT */
+#define REG_GPIO_FLASH_MODE_CFG_EXT 0x0068
+#define GPIO51_FLASH_MODE_CFG BIT(31)
+#define GPIO50_FLASH_MODE_CFG BIT(30)
+#define GPIO49_FLASH_MODE_CFG BIT(29)
+#define GPIO48_FLASH_MODE_CFG BIT(28)
+#define GPIO47_FLASH_MODE_CFG BIT(27)
+#define GPIO46_FLASH_MODE_CFG BIT(26)
+#define GPIO45_FLASH_MODE_CFG BIT(25)
+#define GPIO44_FLASH_MODE_CFG BIT(24)
+#define GPIO43_FLASH_MODE_CFG BIT(23)
+#define GPIO42_FLASH_MODE_CFG BIT(22)
+#define GPIO41_FLASH_MODE_CFG BIT(21)
+#define GPIO40_FLASH_MODE_CFG BIT(20)
+#define GPIO39_FLASH_MODE_CFG BIT(19)
+#define GPIO38_FLASH_MODE_CFG BIT(18)
+#define GPIO37_FLASH_MODE_CFG BIT(17)
+#define GPIO36_FLASH_MODE_CFG BIT(16)
+#define GPIO31_FLASH_MODE_CFG BIT(15)
+#define GPIO30_FLASH_MODE_CFG BIT(14)
+#define GPIO29_FLASH_MODE_CFG BIT(13)
+#define GPIO28_FLASH_MODE_CFG BIT(12)
+#define GPIO27_FLASH_MODE_CFG BIT(11)
+#define GPIO26_FLASH_MODE_CFG BIT(10)
+#define GPIO25_FLASH_MODE_CFG BIT(9)
+#define GPIO24_FLASH_MODE_CFG BIT(8)
+#define GPIO23_FLASH_MODE_CFG BIT(7)
+#define GPIO22_FLASH_MODE_CFG BIT(6)
+#define GPIO21_FLASH_MODE_CFG BIT(5)
+#define GPIO20_FLASH_MODE_CFG BIT(4)
+#define GPIO19_FLASH_MODE_CFG BIT(3)
+#define GPIO18_FLASH_MODE_CFG BIT(2)
+#define GPIO17_FLASH_MODE_CFG BIT(1)
+#define GPIO16_FLASH_MODE_CFG BIT(0)
+
+#define REG_GPIO_DATA1 0x0070
+#define REG_GPIO_OE1 0x0078
+#define REG_GPIO_INT1 0x007c
+#define REG_GPIO_INT_EDGE1 0x0080
+#define REG_GPIO_INT_EDGE2 0x0084
+#define REG_GPIO_INT_EDGE3 0x0088
+#define REG_GPIO_INT_LEVEL1 0x008c
+#define REG_GPIO_INT_LEVEL2 0x0090
+#define REG_GPIO_INT_LEVEL3 0x0094
+
+#define AIROHA_NUM_PINS 64
+#define AIROHA_PIN_BANK_SIZE (AIROHA_NUM_PINS / 2)
+#define AIROHA_REG_GPIOCTRL_NUM_PIN (AIROHA_NUM_PINS / 4)
+
+static const u32 gpio_data_regs[] = {
+ REG_GPIO_DATA,
+ REG_GPIO_DATA1
+};
+
+static const u32 gpio_out_regs[] = {
+ REG_GPIO_OE,
+ REG_GPIO_OE1
+};
+
+static const u32 gpio_dir_regs[] = {
+ REG_GPIO_CTRL,
+ REG_GPIO_CTRL1,
+ REG_GPIO_CTRL2,
+ REG_GPIO_CTRL3
+};
+
+static const u32 irq_status_regs[] = {
+ REG_GPIO_INT,
+ REG_GPIO_INT1
+};
+
+static const u32 irq_level_regs[] = {
+ REG_GPIO_INT_LEVEL,
+ REG_GPIO_INT_LEVEL1,
+ REG_GPIO_INT_LEVEL2,
+ REG_GPIO_INT_LEVEL3
+};
+
+static const u32 irq_edge_regs[] = {
+ REG_GPIO_INT_EDGE,
+ REG_GPIO_INT_EDGE1,
+ REG_GPIO_INT_EDGE2,
+ REG_GPIO_INT_EDGE3
+};
+
+struct airoha_pinctrl_reg {
+ u32 offset;
+ u32 mask;
+};
+
+enum airoha_pinctrl_mux_func {
+ AIROHA_FUNC_MUX,
+ AIROHA_FUNC_PWM_MUX,
+ AIROHA_FUNC_PWM_EXT_MUX,
+};
+
+struct airoha_pinctrl_func_group {
+ const char *name;
+ struct {
+ enum airoha_pinctrl_mux_func mux;
+ u32 offset;
+ u32 mask;
+ u32 val;
+ } regmap[2];
+ int regmap_size;
+};
+
+struct airoha_pinctrl_func {
+ const struct function_desc desc;
+ const struct airoha_pinctrl_func_group *groups;
+ u8 group_size;
+};
+
+struct airoha_pinctrl_conf {
+ u32 pin;
+ struct airoha_pinctrl_reg reg;
+};
+
+struct airoha_pinctrl_gpiochip {
+ struct gpio_chip chip;
+
+ /* gpio */
+ const u32 *data;
+ const u32 *dir;
+ const u32 *out;
+ /* irq */
+ const u32 *status;
+ const u32 *level;
+ const u32 *edge;
+
+ u32 irq_type[AIROHA_NUM_PINS];
+};
+
+struct airoha_pinctrl {
+ struct pinctrl_dev *ctrl;
+
+ struct regmap *chip_scu;
+ struct regmap *regmap;
+
+ struct airoha_pinctrl_gpiochip gpiochip;
+};
+
+static struct pinctrl_pin_desc airoha_pinctrl_pins[] = {
+ PINCTRL_PIN(0, "uart1_txd"),
+ PINCTRL_PIN(1, "uart1_rxd"),
+ PINCTRL_PIN(2, "i2c_scl"),
+ PINCTRL_PIN(3, "i2c_sda"),
+ PINCTRL_PIN(4, "spi_cs0"),
+ PINCTRL_PIN(5, "spi_clk"),
+ PINCTRL_PIN(6, "spi_mosi"),
+ PINCTRL_PIN(7, "spi_miso"),
+ PINCTRL_PIN(13, "gpio0"),
+ PINCTRL_PIN(14, "gpio1"),
+ PINCTRL_PIN(15, "gpio2"),
+ PINCTRL_PIN(16, "gpio3"),
+ PINCTRL_PIN(17, "gpio4"),
+ PINCTRL_PIN(18, "gpio5"),
+ PINCTRL_PIN(19, "gpio6"),
+ PINCTRL_PIN(20, "gpio7"),
+ PINCTRL_PIN(21, "gpio8"),
+ PINCTRL_PIN(22, "gpio9"),
+ PINCTRL_PIN(23, "gpio10"),
+ PINCTRL_PIN(24, "gpio11"),
+ PINCTRL_PIN(25, "gpio12"),
+ PINCTRL_PIN(26, "gpio13"),
+ PINCTRL_PIN(27, "gpio14"),
+ PINCTRL_PIN(28, "gpio15"),
+ PINCTRL_PIN(29, "gpio16"),
+ PINCTRL_PIN(30, "gpio17"),
+ PINCTRL_PIN(31, "gpio18"),
+ PINCTRL_PIN(32, "gpio19"),
+ PINCTRL_PIN(33, "gpio20"),
+ PINCTRL_PIN(34, "gpio21"),
+ PINCTRL_PIN(35, "gpio22"),
+ PINCTRL_PIN(36, "gpio23"),
+ PINCTRL_PIN(37, "gpio24"),
+ PINCTRL_PIN(38, "gpio25"),
+ PINCTRL_PIN(39, "gpio26"),
+ PINCTRL_PIN(40, "gpio27"),
+ PINCTRL_PIN(41, "gpio28"),
+ PINCTRL_PIN(42, "gpio29"),
+ PINCTRL_PIN(43, "gpio30"),
+ PINCTRL_PIN(44, "gpio31"),
+ PINCTRL_PIN(45, "gpio32"),
+ PINCTRL_PIN(46, "gpio33"),
+ PINCTRL_PIN(47, "gpio34"),
+ PINCTRL_PIN(48, "gpio35"),
+ PINCTRL_PIN(49, "gpio36"),
+ PINCTRL_PIN(50, "gpio37"),
+ PINCTRL_PIN(51, "gpio38"),
+ PINCTRL_PIN(52, "gpio39"),
+ PINCTRL_PIN(53, "gpio40"),
+ PINCTRL_PIN(54, "gpio41"),
+ PINCTRL_PIN(55, "gpio42"),
+ PINCTRL_PIN(56, "gpio43"),
+ PINCTRL_PIN(57, "gpio44"),
+ PINCTRL_PIN(58, "gpio45"),
+ PINCTRL_PIN(59, "gpio46"),
+ PINCTRL_PIN(61, "pcie_reset0"),
+ PINCTRL_PIN(62, "pcie_reset1"),
+ PINCTRL_PIN(63, "pcie_reset2"),
+};
+
+static const int pon_pins[] = { 49, 50, 51, 52, 53, 54 };
+static const int pon_tod_1pps_pins[] = { 46 };
+static const int gsw_tod_1pps_pins[] = { 46 };
+static const int sipo_pins[] = { 16, 17 };
+static const int sipo_rclk_pins[] = { 16, 17, 43 };
+static const int mdio_pins[] = { 14, 15 };
+static const int uart2_pins[] = { 48, 55 };
+static const int uart2_cts_rts_pins[] = { 46, 47 };
+static const int hsuart_pins[] = { 28, 29 };
+static const int hsuart_cts_rts_pins[] = { 26, 27 };
+static const int uart4_pins[] = { 38, 39 };
+static const int uart5_pins[] = { 18, 19 };
+static const int i2c0_pins[] = { 2, 3 };
+static const int i2c1_pins[] = { 14, 15 };
+static const int jtag_udi_pins[] = { 16, 17, 18, 19, 20 };
+static const int jtag_dfd_pins[] = { 16, 17, 18, 19, 20 };
+static const int i2s_pins[] = { 26, 27, 28, 29 };
+static const int pcm1_pins[] = { 22, 23, 24, 25 };
+static const int pcm2_pins[] = { 18, 19, 20, 21 };
+static const int spi_quad_pins[] = { 32, 33 };
+static const int spi_pins[] = { 4, 5, 6, 7 };
+static const int spi_cs1_pins[] = { 34 };
+static const int pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 };
+static const int pcm_spi_int_pins[] = { 14 };
+static const int pcm_spi_rst_pins[] = { 15 };
+static const int pcm_spi_cs1_pins[] = { 43 };
+static const int pcm_spi_cs2_pins[] = { 40 };
+static const int pcm_spi_cs2_p128_pins[] = { 40 };
+static const int pcm_spi_cs2_p156_pins[] = { 40 };
+static const int pcm_spi_cs3_pins[] = { 41 };
+static const int pcm_spi_cs4_pins[] = { 42 };
+static const int emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 };
+static const int pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 };
+static const int gpio0_pins[] = { 13 };
+static const int gpio1_pins[] = { 14 };
+static const int gpio2_pins[] = { 15 };
+static const int gpio3_pins[] = { 16 };
+static const int gpio4_pins[] = { 17 };
+static const int gpio5_pins[] = { 18 };
+static const int gpio6_pins[] = { 19 };
+static const int gpio7_pins[] = { 20 };
+static const int gpio8_pins[] = { 21 };
+static const int gpio9_pins[] = { 22 };
+static const int gpio10_pins[] = { 23 };
+static const int gpio11_pins[] = { 24 };
+static const int gpio12_pins[] = { 25 };
+static const int gpio13_pins[] = { 26 };
+static const int gpio14_pins[] = { 27 };
+static const int gpio15_pins[] = { 28 };
+static const int gpio16_pins[] = { 29 };
+static const int gpio17_pins[] = { 30 };
+static const int gpio18_pins[] = { 31 };
+static const int gpio19_pins[] = { 32 };
+static const int gpio20_pins[] = { 33 };
+static const int gpio21_pins[] = { 34 };
+static const int gpio22_pins[] = { 35 };
+static const int gpio23_pins[] = { 36 };
+static const int gpio24_pins[] = { 37 };
+static const int gpio25_pins[] = { 38 };
+static const int gpio26_pins[] = { 39 };
+static const int gpio27_pins[] = { 40 };
+static const int gpio28_pins[] = { 41 };
+static const int gpio29_pins[] = { 42 };
+static const int gpio30_pins[] = { 43 };
+static const int gpio31_pins[] = { 44 };
+static const int gpio33_pins[] = { 46 };
+static const int gpio34_pins[] = { 47 };
+static const int gpio35_pins[] = { 48 };
+static const int gpio36_pins[] = { 49 };
+static const int gpio37_pins[] = { 50 };
+static const int gpio38_pins[] = { 51 };
+static const int gpio39_pins[] = { 52 };
+static const int gpio40_pins[] = { 53 };
+static const int gpio41_pins[] = { 54 };
+static const int gpio42_pins[] = { 55 };
+static const int gpio43_pins[] = { 56 };
+static const int gpio44_pins[] = { 57 };
+static const int gpio45_pins[] = { 58 };
+static const int gpio46_pins[] = { 59 };
+static const int pcie_reset0_pins[] = { 61 };
+static const int pcie_reset1_pins[] = { 62 };
+static const int pcie_reset2_pins[] = { 63 };
+
+static const struct pingroup airoha_pinctrl_groups[] = {
+ PINCTRL_PIN_GROUP(pon),
+ PINCTRL_PIN_GROUP(pon_tod_1pps),
+ PINCTRL_PIN_GROUP(gsw_tod_1pps),
+ PINCTRL_PIN_GROUP(sipo),
+ PINCTRL_PIN_GROUP(sipo_rclk),
+ PINCTRL_PIN_GROUP(mdio),
+ PINCTRL_PIN_GROUP(uart2),
+ PINCTRL_PIN_GROUP(uart2_cts_rts),
+ PINCTRL_PIN_GROUP(hsuart),
+ PINCTRL_PIN_GROUP(hsuart_cts_rts),
+ PINCTRL_PIN_GROUP(uart4),
+ PINCTRL_PIN_GROUP(uart5),
+ PINCTRL_PIN_GROUP(i2c0),
+ PINCTRL_PIN_GROUP(i2c1),
+ PINCTRL_PIN_GROUP(jtag_udi),
+ PINCTRL_PIN_GROUP(jtag_dfd),
+ PINCTRL_PIN_GROUP(i2s),
+ PINCTRL_PIN_GROUP(pcm1),
+ PINCTRL_PIN_GROUP(pcm2),
+ PINCTRL_PIN_GROUP(spi),
+ PINCTRL_PIN_GROUP(spi_quad),
+ PINCTRL_PIN_GROUP(spi_cs1),
+ PINCTRL_PIN_GROUP(pcm_spi),
+ PINCTRL_PIN_GROUP(pcm_spi_int),
+ PINCTRL_PIN_GROUP(pcm_spi_rst),
+ PINCTRL_PIN_GROUP(pcm_spi_cs1),
+ PINCTRL_PIN_GROUP(pcm_spi_cs2_p128),
+ PINCTRL_PIN_GROUP(pcm_spi_cs2_p156),
+ PINCTRL_PIN_GROUP(pcm_spi_cs2),
+ PINCTRL_PIN_GROUP(pcm_spi_cs3),
+ PINCTRL_PIN_GROUP(pcm_spi_cs4),
+ PINCTRL_PIN_GROUP(emmc),
+ PINCTRL_PIN_GROUP(pnand),
+ PINCTRL_PIN_GROUP(gpio0),
+ PINCTRL_PIN_GROUP(gpio1),
+ PINCTRL_PIN_GROUP(gpio2),
+ PINCTRL_PIN_GROUP(gpio3),
+ PINCTRL_PIN_GROUP(gpio4),
+ PINCTRL_PIN_GROUP(gpio5),
+ PINCTRL_PIN_GROUP(gpio6),
+ PINCTRL_PIN_GROUP(gpio7),
+ PINCTRL_PIN_GROUP(gpio8),
+ PINCTRL_PIN_GROUP(gpio9),
+ PINCTRL_PIN_GROUP(gpio10),
+ PINCTRL_PIN_GROUP(gpio11),
+ PINCTRL_PIN_GROUP(gpio12),
+ PINCTRL_PIN_GROUP(gpio13),
+ PINCTRL_PIN_GROUP(gpio14),
+ PINCTRL_PIN_GROUP(gpio15),
+ PINCTRL_PIN_GROUP(gpio16),
+ PINCTRL_PIN_GROUP(gpio17),
+ PINCTRL_PIN_GROUP(gpio18),
+ PINCTRL_PIN_GROUP(gpio19),
+ PINCTRL_PIN_GROUP(gpio20),
+ PINCTRL_PIN_GROUP(gpio21),
+ PINCTRL_PIN_GROUP(gpio22),
+ PINCTRL_PIN_GROUP(gpio23),
+ PINCTRL_PIN_GROUP(gpio24),
+ PINCTRL_PIN_GROUP(gpio25),
+ PINCTRL_PIN_GROUP(gpio26),
+ PINCTRL_PIN_GROUP(gpio27),
+ PINCTRL_PIN_GROUP(gpio28),
+ PINCTRL_PIN_GROUP(gpio29),
+ PINCTRL_PIN_GROUP(gpio30),
+ PINCTRL_PIN_GROUP(gpio31),
+ PINCTRL_PIN_GROUP(gpio33),
+ PINCTRL_PIN_GROUP(gpio34),
+ PINCTRL_PIN_GROUP(gpio35),
+ PINCTRL_PIN_GROUP(gpio36),
+ PINCTRL_PIN_GROUP(gpio37),
+ PINCTRL_PIN_GROUP(gpio38),
+ PINCTRL_PIN_GROUP(gpio39),
+ PINCTRL_PIN_GROUP(gpio40),
+ PINCTRL_PIN_GROUP(gpio41),
+ PINCTRL_PIN_GROUP(gpio42),
+ PINCTRL_PIN_GROUP(gpio43),
+ PINCTRL_PIN_GROUP(gpio44),
+ PINCTRL_PIN_GROUP(gpio45),
+ PINCTRL_PIN_GROUP(gpio46),
+ PINCTRL_PIN_GROUP(pcie_reset0),
+ PINCTRL_PIN_GROUP(pcie_reset1),
+ PINCTRL_PIN_GROUP(pcie_reset2),
+};
+
+static const char *const pon_groups[] = { "pon" };
+static const char *const tod_1pps_groups[] = { "pon_tod_1pps", "gsw_tod_1pps" };
+static const char *const sipo_groups[] = { "sipo", "sipo_rclk" };
+static const char *const mdio_groups[] = { "mdio" };
+static const char *const uart_groups[] = { "uart2", "uart2_cts_rts", "hsuart",
+ "hsuart_cts_rts", "uart4",
+ "uart5" };
+static const char *const i2c_groups[] = { "i2c1" };
+static const char *const jtag_groups[] = { "jtag_udi", "jtag_dfd" };
+static const char *const pcm_groups[] = { "pcm1", "pcm2" };
+static const char *const spi_groups[] = { "spi_quad", "spi_cs1" };
+static const char *const pcm_spi_groups[] = { "pcm_spi", "pcm_spi_int",
+ "pcm_spi_rst", "pcm_spi_cs1",
+ "pcm_spi_cs2_p156",
+ "pcm_spi_cs2_p128",
+ "pcm_spi_cs3", "pcm_spi_cs4" };
+static const char *const i2s_groups[] = { "i2s" };
+static const char *const emmc_groups[] = { "emmc" };
+static const char *const pnand_groups[] = { "pnand" };
+static const char *const pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1",
+ "pcie_reset2" };
+static const char *const pwm_groups[] = { "gpio0", "gpio1",
+ "gpio2", "gpio3",
+ "gpio4", "gpio5",
+ "gpio6", "gpio7",
+ "gpio8", "gpio9",
+ "gpio10", "gpio11",
+ "gpio12", "gpio13",
+ "gpio14", "gpio15",
+ "gpio16", "gpio17",
+ "gpio18", "gpio19",
+ "gpio20", "gpio21",
+ "gpio22", "gpio23",
+ "gpio24", "gpio25",
+ "gpio26", "gpio27",
+ "gpio28", "gpio29",
+ "gpio30", "gpio31",
+ "gpio36", "gpio37",
+ "gpio38", "gpio39",
+ "gpio40", "gpio41",
+ "gpio42", "gpio43",
+ "gpio44", "gpio45",
+ "gpio46", "gpio47" };
+static const char *const phy1_led0_groups[] = { "gpio33", "gpio34",
+ "gpio35", "gpio42" };
+static const char *const phy2_led0_groups[] = { "gpio33", "gpio34",
+ "gpio35", "gpio42" };
+static const char *const phy3_led0_groups[] = { "gpio33", "gpio34",
+ "gpio35", "gpio42" };
+static const char *const phy4_led0_groups[] = { "gpio33", "gpio34",
+ "gpio35", "gpio42" };
+static const char *const phy1_led1_groups[] = { "gpio43", "gpio44",
+ "gpio45", "gpio46" };
+static const char *const phy2_led1_groups[] = { "gpio43", "gpio44",
+ "gpio45", "gpio46" };
+static const char *const phy3_led1_groups[] = { "gpio43", "gpio44",
+ "gpio45", "gpio46" };
+static const char *const phy4_led1_groups[] = { "gpio43", "gpio44",
+ "gpio45", "gpio46" };
+
+static const struct airoha_pinctrl_func_group pon_func_group[] = {
+ {
+ .name = "pon",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_PON_MODE_MASK,
+ GPIO_PON_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group tod_1pps_func_group[] = {
+ {
+ .name = "pon_tod_1pps",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ PON_TOD_1PPS_MODE_MASK,
+ PON_TOD_1PPS_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gsw_tod_1pps",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GSW_TOD_1PPS_MODE_MASK,
+ GSW_TOD_1PPS_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group sipo_func_group[] = {
+ {
+ .name = "sipo",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK,
+ GPIO_SIPO_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "sipo_rclk",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK,
+ GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group mdio_func_group[] = {
+ {
+ .name = "mdio",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_SGMII_MDIO_MODE_MASK,
+ GPIO_SGMII_MDIO_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_MDC_IO_MASTER_MODE_MODE,
+ GPIO_MDC_IO_MASTER_MODE_MODE
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group uart_func_group[] = {
+ {
+ .name = "uart2",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_UART2_MODE_MASK,
+ GPIO_UART2_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "uart2_cts_rts",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_UART2_MODE_MASK | GPIO_UART2_CTS_RTS_MODE_MASK,
+ GPIO_UART2_MODE_MASK | GPIO_UART2_CTS_RTS_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "hsuart",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK,
+ GPIO_HSUART_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+ {
+ .name = "hsuart_cts_rts",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK,
+ GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "uart4",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_UART4_MODE_MASK,
+ GPIO_UART4_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "uart5",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_UART5_MODE_MASK,
+ GPIO_UART5_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group i2c_func_group[] = {
+ {
+ .name = "i2c1",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_2ND_I2C_MODE_MASK,
+ GPIO_2ND_I2C_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group jtag_func_group[] = {
+ {
+ .name = "jtag_udi",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_NPU_UART_EN,
+ JTAG_UDI_EN_MASK,
+ JTAG_UDI_EN_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "jtag_dfd",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_NPU_UART_EN,
+ JTAG_DFD_EN_MASK,
+ JTAG_DFD_EN_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group pcm_func_group[] = {
+ {
+ .name = "pcm1",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM1_MODE_MASK,
+ GPIO_PCM1_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm2",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM2_MODE_MASK,
+ GPIO_PCM2_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group spi_func_group[] = {
+ {
+ .name = "spi_quad",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_SPI_QUAD_MODE_MASK,
+ GPIO_SPI_QUAD_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "spi_cs1",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_SPI_CS1_MODE_MASK,
+ GPIO_SPI_CS1_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "spi_cs2",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_SPI_CS2_MODE_MASK,
+ GPIO_SPI_CS2_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "spi_cs3",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_SPI_CS3_MODE_MASK,
+ GPIO_SPI_CS3_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "spi_cs4",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_SPI_CS4_MODE_MASK,
+ GPIO_SPI_CS4_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group pcm_spi_func_group[] = {
+ {
+ .name = "pcm_spi",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_SPI_MODE_MASK,
+ GPIO_PCM_SPI_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm_spi_int",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_INT_MODE_MASK,
+ GPIO_PCM_INT_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm_spi_rst",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_RESET_MODE_MASK,
+ GPIO_PCM_RESET_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm_spi_cs1",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_SPI_CS1_MODE_MASK,
+ GPIO_PCM_SPI_CS1_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm_spi_cs2_p128",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_SPI_CS2_MODE_P128_MASK,
+ GPIO_PCM_SPI_CS2_MODE_P128_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm_spi_cs2_p156",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_SPI_CS2_MODE_P156_MASK,
+ GPIO_PCM_SPI_CS2_MODE_P156_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm_spi_cs3",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_SPI_CS3_MODE_MASK,
+ GPIO_PCM_SPI_CS3_MODE_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcm_spi_cs4",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_SPI_CS1_MODE,
+ GPIO_PCM_SPI_CS4_MODE_MASK,
+ GPIO_PCM_SPI_CS4_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group i2s_func_group[] = {
+ {
+ .name = "i2s",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_I2S_MODE_MASK,
+ GPIO_I2S_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group emmc_func_group[] = {
+ {
+ .name = "emmc",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_EMMC_MODE_MASK,
+ GPIO_EMMC_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group pnand_func_group[] = {
+ {
+ .name = "pnand",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_PARALLEL_NAND_MODE_MASK,
+ GPIO_PARALLEL_NAND_MODE_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group pcie_reset_func_group[] = {
+ {
+ .name = "pcie_reset0",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_PCIE_RESET0_MASK,
+ GPIO_PCIE_RESET0_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcie_reset1",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_PCIE_RESET1_MASK,
+ GPIO_PCIE_RESET1_MASK
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "pcie_reset2",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_PON_MODE,
+ GPIO_PCIE_RESET2_MASK,
+ GPIO_PCIE_RESET2_MASK
+ },
+ .regmap_size = 1,
+ },
+};
+
+/* PWM */
+static const struct airoha_pinctrl_func_group pwm_func_group[] = {
+ {
+ .name = "gpio0",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO0_FLASH_MODE_CFG,
+ GPIO0_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio1",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO1_FLASH_MODE_CFG,
+ GPIO1_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio2",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO2_FLASH_MODE_CFG,
+ GPIO2_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio3",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO3_FLASH_MODE_CFG,
+ GPIO3_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio4",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO4_FLASH_MODE_CFG,
+ GPIO4_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio5",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO5_FLASH_MODE_CFG,
+ GPIO5_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio6",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO6_FLASH_MODE_CFG,
+ GPIO6_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio7",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO7_FLASH_MODE_CFG,
+ GPIO7_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio8",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO8_FLASH_MODE_CFG,
+ GPIO8_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio9",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO9_FLASH_MODE_CFG,
+ GPIO9_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio10",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO10_FLASH_MODE_CFG,
+ GPIO10_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio11",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO11_FLASH_MODE_CFG,
+ GPIO11_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio12",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO12_FLASH_MODE_CFG,
+ GPIO12_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio13",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO13_FLASH_MODE_CFG,
+ GPIO13_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio14",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO14_FLASH_MODE_CFG,
+ GPIO14_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio15",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_MUX,
+ REG_GPIO_FLASH_MODE_CFG,
+ GPIO15_FLASH_MODE_CFG,
+ GPIO15_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio16",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO16_FLASH_MODE_CFG,
+ GPIO16_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio17",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO17_FLASH_MODE_CFG,
+ GPIO17_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio18",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO18_FLASH_MODE_CFG,
+ GPIO18_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio19",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO19_FLASH_MODE_CFG,
+ GPIO19_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio20",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO20_FLASH_MODE_CFG,
+ GPIO20_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio21",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO21_FLASH_MODE_CFG,
+ GPIO21_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio22",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO22_FLASH_MODE_CFG,
+ GPIO22_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio23",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO23_FLASH_MODE_CFG,
+ GPIO23_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio24",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO24_FLASH_MODE_CFG,
+ GPIO24_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio25",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO25_FLASH_MODE_CFG,
+ GPIO25_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio26",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO26_FLASH_MODE_CFG,
+ GPIO26_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio27",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO27_FLASH_MODE_CFG,
+ GPIO27_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio28",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO28_FLASH_MODE_CFG,
+ GPIO28_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio29",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO29_FLASH_MODE_CFG,
+ GPIO29_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio30",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO30_FLASH_MODE_CFG,
+ GPIO30_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio31",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO31_FLASH_MODE_CFG,
+ GPIO31_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio36",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO36_FLASH_MODE_CFG,
+ GPIO36_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio37",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO37_FLASH_MODE_CFG,
+ GPIO37_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio38",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO38_FLASH_MODE_CFG,
+ GPIO38_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio39",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO39_FLASH_MODE_CFG,
+ GPIO39_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio40",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO40_FLASH_MODE_CFG,
+ GPIO40_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio41",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO41_FLASH_MODE_CFG,
+ GPIO41_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio42",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO42_FLASH_MODE_CFG,
+ GPIO42_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio43",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO43_FLASH_MODE_CFG,
+ GPIO43_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio44",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO44_FLASH_MODE_CFG,
+ GPIO44_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio45",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO45_FLASH_MODE_CFG,
+ GPIO45_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio46",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO46_FLASH_MODE_CFG,
+ GPIO46_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ }, {
+ .name = "gpio47",
+ .regmap[0] = {
+ AIROHA_FUNC_PWM_EXT_MUX,
+ REG_GPIO_FLASH_MODE_CFG_EXT,
+ GPIO47_FLASH_MODE_CFG,
+ GPIO47_FLASH_MODE_CFG
+ },
+ .regmap_size = 1,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy1_led0_func_group[] = {
+ {
+ .name = "gpio33",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED0_MODE_MASK,
+ GPIO_LAN0_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio34",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED0_MODE_MASK,
+ GPIO_LAN1_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio35",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED0_MODE_MASK,
+ GPIO_LAN2_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio42",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy2_led0_func_group[] = {
+ {
+ .name = "gpio33",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED0_MODE_MASK,
+ GPIO_LAN0_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio34",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED0_MODE_MASK,
+ GPIO_LAN1_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio35",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED0_MODE_MASK,
+ GPIO_LAN2_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio42",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy3_led0_func_group[] = {
+ {
+ .name = "gpio33",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED0_MODE_MASK,
+ GPIO_LAN0_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio34",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED0_MODE_MASK,
+ GPIO_LAN1_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio35",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED0_MODE_MASK,
+ GPIO_LAN2_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio42",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy4_led0_func_group[] = {
+ {
+ .name = "gpio33",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED0_MODE_MASK,
+ GPIO_LAN0_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio34",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED0_MODE_MASK,
+ GPIO_LAN1_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio35",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED0_MODE_MASK,
+ GPIO_LAN2_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio42",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED0_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy1_led1_func_group[] = {
+ {
+ .name = "gpio43",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED1_MODE_MASK,
+ GPIO_LAN0_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio44",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED1_MODE_MASK,
+ GPIO_LAN1_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio45",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED1_MODE_MASK,
+ GPIO_LAN2_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio46",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY1_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy2_led1_func_group[] = {
+ {
+ .name = "gpio43",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED1_MODE_MASK,
+ GPIO_LAN0_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio44",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED1_MODE_MASK,
+ GPIO_LAN1_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio45",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED1_MODE_MASK,
+ GPIO_LAN2_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio46",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY2_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy3_led1_func_group[] = {
+ {
+ .name = "gpio43",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED1_MODE_MASK,
+ GPIO_LAN0_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio44",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED1_MODE_MASK,
+ GPIO_LAN1_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio45",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED1_MODE_MASK,
+ GPIO_LAN2_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio46",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY3_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = {
+ {
+ .name = "gpio43",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN0_LED1_MODE_MASK,
+ GPIO_LAN0_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN1_LED_MAPPING_MASK,
+ LAN1_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio44",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN1_LED1_MODE_MASK,
+ GPIO_LAN1_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN2_LED_MAPPING_MASK,
+ LAN2_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio45",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN2_LED1_MODE_MASK,
+ GPIO_LAN2_LED1_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN3_LED_MAPPING_MASK,
+ LAN3_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ }, {
+ .name = "gpio46",
+ .regmap[0] = {
+ AIROHA_FUNC_MUX,
+ REG_GPIO_2ND_I2C_MODE,
+ GPIO_LAN3_LED0_MODE_MASK,
+ GPIO_LAN3_LED0_MODE_MASK
+ },
+ .regmap[1] = {
+ AIROHA_FUNC_MUX,
+ REG_LAN_LED1_MAPPING,
+ LAN4_LED_MAPPING_MASK,
+ LAN4_PHY4_LED_MAP
+ },
+ .regmap_size = 2,
+ },
+};
+
+static const struct airoha_pinctrl_func airoha_pinctrl_funcs[] = {
+ PINCTRL_FUNC_DESC(pon),
+ PINCTRL_FUNC_DESC(tod_1pps),
+ PINCTRL_FUNC_DESC(sipo),
+ PINCTRL_FUNC_DESC(mdio),
+ PINCTRL_FUNC_DESC(uart),
+ PINCTRL_FUNC_DESC(i2c),
+ PINCTRL_FUNC_DESC(jtag),
+ PINCTRL_FUNC_DESC(pcm),
+ PINCTRL_FUNC_DESC(spi),
+ PINCTRL_FUNC_DESC(pcm_spi),
+ PINCTRL_FUNC_DESC(i2s),
+ PINCTRL_FUNC_DESC(emmc),
+ PINCTRL_FUNC_DESC(pnand),
+ PINCTRL_FUNC_DESC(pcie_reset),
+ PINCTRL_FUNC_DESC(pwm),
+ PINCTRL_FUNC_DESC(phy1_led0),
+ PINCTRL_FUNC_DESC(phy2_led0),
+ PINCTRL_FUNC_DESC(phy3_led0),
+ PINCTRL_FUNC_DESC(phy4_led0),
+ PINCTRL_FUNC_DESC(phy1_led1),
+ PINCTRL_FUNC_DESC(phy2_led1),
+ PINCTRL_FUNC_DESC(phy3_led1),
+ PINCTRL_FUNC_DESC(phy4_led1),
+};
+
+static const struct airoha_pinctrl_conf airoha_pinctrl_pullup_conf[] = {
+ PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK),
+ PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK),
+ PINCTRL_CONF_DESC(2, REG_I2C_SDA_PU, I2C_SDA_PU_MASK),
+ PINCTRL_CONF_DESC(3, REG_I2C_SDA_PU, I2C_SCL_PU_MASK),
+ PINCTRL_CONF_DESC(4, REG_I2C_SDA_PU, SPI_CS0_PU_MASK),
+ PINCTRL_CONF_DESC(5, REG_I2C_SDA_PU, SPI_CLK_PU_MASK),
+ PINCTRL_CONF_DESC(6, REG_I2C_SDA_PU, SPI_MOSI_PU_MASK),
+ PINCTRL_CONF_DESC(7, REG_I2C_SDA_PU, SPI_MISO_PU_MASK),
+ PINCTRL_CONF_DESC(13, REG_GPIO_L_PU, BIT(0)),
+ PINCTRL_CONF_DESC(14, REG_GPIO_L_PU, BIT(1)),
+ PINCTRL_CONF_DESC(15, REG_GPIO_L_PU, BIT(2)),
+ PINCTRL_CONF_DESC(16, REG_GPIO_L_PU, BIT(3)),
+ PINCTRL_CONF_DESC(17, REG_GPIO_L_PU, BIT(4)),
+ PINCTRL_CONF_DESC(18, REG_GPIO_L_PU, BIT(5)),
+ PINCTRL_CONF_DESC(19, REG_GPIO_L_PU, BIT(6)),
+ PINCTRL_CONF_DESC(20, REG_GPIO_L_PU, BIT(7)),
+ PINCTRL_CONF_DESC(21, REG_GPIO_L_PU, BIT(8)),
+ PINCTRL_CONF_DESC(22, REG_GPIO_L_PU, BIT(9)),
+ PINCTRL_CONF_DESC(23, REG_GPIO_L_PU, BIT(10)),
+ PINCTRL_CONF_DESC(24, REG_GPIO_L_PU, BIT(11)),
+ PINCTRL_CONF_DESC(25, REG_GPIO_L_PU, BIT(12)),
+ PINCTRL_CONF_DESC(26, REG_GPIO_L_PU, BIT(13)),
+ PINCTRL_CONF_DESC(27, REG_GPIO_L_PU, BIT(14)),
+ PINCTRL_CONF_DESC(28, REG_GPIO_L_PU, BIT(15)),
+ PINCTRL_CONF_DESC(29, REG_GPIO_L_PU, BIT(16)),
+ PINCTRL_CONF_DESC(30, REG_GPIO_L_PU, BIT(17)),
+ PINCTRL_CONF_DESC(31, REG_GPIO_L_PU, BIT(18)),
+ PINCTRL_CONF_DESC(32, REG_GPIO_L_PU, BIT(18)),
+ PINCTRL_CONF_DESC(33, REG_GPIO_L_PU, BIT(20)),
+ PINCTRL_CONF_DESC(34, REG_GPIO_L_PU, BIT(21)),
+ PINCTRL_CONF_DESC(35, REG_GPIO_L_PU, BIT(22)),
+ PINCTRL_CONF_DESC(36, REG_GPIO_L_PU, BIT(23)),
+ PINCTRL_CONF_DESC(37, REG_GPIO_L_PU, BIT(24)),
+ PINCTRL_CONF_DESC(38, REG_GPIO_L_PU, BIT(25)),
+ PINCTRL_CONF_DESC(39, REG_GPIO_L_PU, BIT(26)),
+ PINCTRL_CONF_DESC(40, REG_GPIO_L_PU, BIT(27)),
+ PINCTRL_CONF_DESC(41, REG_GPIO_L_PU, BIT(28)),
+ PINCTRL_CONF_DESC(42, REG_GPIO_L_PU, BIT(29)),
+ PINCTRL_CONF_DESC(43, REG_GPIO_L_PU, BIT(30)),
+ PINCTRL_CONF_DESC(44, REG_GPIO_L_PU, BIT(31)),
+ PINCTRL_CONF_DESC(45, REG_GPIO_H_PU, BIT(0)),
+ PINCTRL_CONF_DESC(46, REG_GPIO_H_PU, BIT(1)),
+ PINCTRL_CONF_DESC(47, REG_GPIO_H_PU, BIT(2)),
+ PINCTRL_CONF_DESC(48, REG_GPIO_H_PU, BIT(3)),
+ PINCTRL_CONF_DESC(49, REG_GPIO_H_PU, BIT(4)),
+ PINCTRL_CONF_DESC(50, REG_GPIO_H_PU, BIT(5)),
+ PINCTRL_CONF_DESC(51, REG_GPIO_H_PU, BIT(6)),
+ PINCTRL_CONF_DESC(52, REG_GPIO_H_PU, BIT(7)),
+ PINCTRL_CONF_DESC(53, REG_GPIO_H_PU, BIT(8)),
+ PINCTRL_CONF_DESC(54, REG_GPIO_H_PU, BIT(9)),
+ PINCTRL_CONF_DESC(55, REG_GPIO_H_PU, BIT(10)),
+ PINCTRL_CONF_DESC(56, REG_GPIO_H_PU, BIT(11)),
+ PINCTRL_CONF_DESC(57, REG_GPIO_H_PU, BIT(12)),
+ PINCTRL_CONF_DESC(58, REG_GPIO_H_PU, BIT(13)),
+ PINCTRL_CONF_DESC(59, REG_GPIO_H_PU, BIT(14)),
+ PINCTRL_CONF_DESC(61, REG_I2C_SDA_PU, PCIE0_RESET_PU_MASK),
+ PINCTRL_CONF_DESC(62, REG_I2C_SDA_PU, PCIE1_RESET_PU_MASK),
+ PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK),
+};
+
+static const struct airoha_pinctrl_conf airoha_pinctrl_pulldown_conf[] = {
+ PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK),
+ PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK),
+ PINCTRL_CONF_DESC(2, REG_I2C_SDA_PD, I2C_SDA_PD_MASK),
+ PINCTRL_CONF_DESC(3, REG_I2C_SDA_PD, I2C_SCL_PD_MASK),
+ PINCTRL_CONF_DESC(4, REG_I2C_SDA_PD, SPI_CS0_PD_MASK),
+ PINCTRL_CONF_DESC(5, REG_I2C_SDA_PD, SPI_CLK_PD_MASK),
+ PINCTRL_CONF_DESC(6, REG_I2C_SDA_PD, SPI_MOSI_PD_MASK),
+ PINCTRL_CONF_DESC(7, REG_I2C_SDA_PD, SPI_MISO_PD_MASK),
+ PINCTRL_CONF_DESC(13, REG_GPIO_L_PD, BIT(0)),
+ PINCTRL_CONF_DESC(14, REG_GPIO_L_PD, BIT(1)),
+ PINCTRL_CONF_DESC(15, REG_GPIO_L_PD, BIT(2)),
+ PINCTRL_CONF_DESC(16, REG_GPIO_L_PD, BIT(3)),
+ PINCTRL_CONF_DESC(17, REG_GPIO_L_PD, BIT(4)),
+ PINCTRL_CONF_DESC(18, REG_GPIO_L_PD, BIT(5)),
+ PINCTRL_CONF_DESC(19, REG_GPIO_L_PD, BIT(6)),
+ PINCTRL_CONF_DESC(20, REG_GPIO_L_PD, BIT(7)),
+ PINCTRL_CONF_DESC(21, REG_GPIO_L_PD, BIT(8)),
+ PINCTRL_CONF_DESC(22, REG_GPIO_L_PD, BIT(9)),
+ PINCTRL_CONF_DESC(23, REG_GPIO_L_PD, BIT(10)),
+ PINCTRL_CONF_DESC(24, REG_GPIO_L_PD, BIT(11)),
+ PINCTRL_CONF_DESC(25, REG_GPIO_L_PD, BIT(12)),
+ PINCTRL_CONF_DESC(26, REG_GPIO_L_PD, BIT(13)),
+ PINCTRL_CONF_DESC(27, REG_GPIO_L_PD, BIT(14)),
+ PINCTRL_CONF_DESC(28, REG_GPIO_L_PD, BIT(15)),
+ PINCTRL_CONF_DESC(29, REG_GPIO_L_PD, BIT(16)),
+ PINCTRL_CONF_DESC(30, REG_GPIO_L_PD, BIT(17)),
+ PINCTRL_CONF_DESC(31, REG_GPIO_L_PD, BIT(18)),
+ PINCTRL_CONF_DESC(32, REG_GPIO_L_PD, BIT(18)),
+ PINCTRL_CONF_DESC(33, REG_GPIO_L_PD, BIT(20)),
+ PINCTRL_CONF_DESC(34, REG_GPIO_L_PD, BIT(21)),
+ PINCTRL_CONF_DESC(35, REG_GPIO_L_PD, BIT(22)),
+ PINCTRL_CONF_DESC(36, REG_GPIO_L_PD, BIT(23)),
+ PINCTRL_CONF_DESC(37, REG_GPIO_L_PD, BIT(24)),
+ PINCTRL_CONF_DESC(38, REG_GPIO_L_PD, BIT(25)),
+ PINCTRL_CONF_DESC(39, REG_GPIO_L_PD, BIT(26)),
+ PINCTRL_CONF_DESC(40, REG_GPIO_L_PD, BIT(27)),
+ PINCTRL_CONF_DESC(41, REG_GPIO_L_PD, BIT(28)),
+ PINCTRL_CONF_DESC(42, REG_GPIO_L_PD, BIT(29)),
+ PINCTRL_CONF_DESC(43, REG_GPIO_L_PD, BIT(30)),
+ PINCTRL_CONF_DESC(44, REG_GPIO_L_PD, BIT(31)),
+ PINCTRL_CONF_DESC(45, REG_GPIO_H_PD, BIT(0)),
+ PINCTRL_CONF_DESC(46, REG_GPIO_H_PD, BIT(1)),
+ PINCTRL_CONF_DESC(47, REG_GPIO_H_PD, BIT(2)),
+ PINCTRL_CONF_DESC(48, REG_GPIO_H_PD, BIT(3)),
+ PINCTRL_CONF_DESC(49, REG_GPIO_H_PD, BIT(4)),
+ PINCTRL_CONF_DESC(50, REG_GPIO_H_PD, BIT(5)),
+ PINCTRL_CONF_DESC(51, REG_GPIO_H_PD, BIT(6)),
+ PINCTRL_CONF_DESC(52, REG_GPIO_H_PD, BIT(7)),
+ PINCTRL_CONF_DESC(53, REG_GPIO_H_PD, BIT(8)),
+ PINCTRL_CONF_DESC(54, REG_GPIO_H_PD, BIT(9)),
+ PINCTRL_CONF_DESC(55, REG_GPIO_H_PD, BIT(10)),
+ PINCTRL_CONF_DESC(56, REG_GPIO_H_PD, BIT(11)),
+ PINCTRL_CONF_DESC(57, REG_GPIO_H_PD, BIT(12)),
+ PINCTRL_CONF_DESC(58, REG_GPIO_H_PD, BIT(13)),
+ PINCTRL_CONF_DESC(59, REG_GPIO_H_PD, BIT(14)),
+ PINCTRL_CONF_DESC(61, REG_I2C_SDA_PD, PCIE0_RESET_PD_MASK),
+ PINCTRL_CONF_DESC(62, REG_I2C_SDA_PD, PCIE1_RESET_PD_MASK),
+ PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK),
+};
+
+static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e2_conf[] = {
+ PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK),
+ PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK),
+ PINCTRL_CONF_DESC(2, REG_I2C_SDA_E2, I2C_SDA_E2_MASK),
+ PINCTRL_CONF_DESC(3, REG_I2C_SDA_E2, I2C_SCL_E2_MASK),
+ PINCTRL_CONF_DESC(4, REG_I2C_SDA_E2, SPI_CS0_E2_MASK),
+ PINCTRL_CONF_DESC(5, REG_I2C_SDA_E2, SPI_CLK_E2_MASK),
+ PINCTRL_CONF_DESC(6, REG_I2C_SDA_E2, SPI_MOSI_E2_MASK),
+ PINCTRL_CONF_DESC(7, REG_I2C_SDA_E2, SPI_MISO_E2_MASK),
+ PINCTRL_CONF_DESC(13, REG_GPIO_L_E2, BIT(0)),
+ PINCTRL_CONF_DESC(14, REG_GPIO_L_E2, BIT(1)),
+ PINCTRL_CONF_DESC(15, REG_GPIO_L_E2, BIT(2)),
+ PINCTRL_CONF_DESC(16, REG_GPIO_L_E2, BIT(3)),
+ PINCTRL_CONF_DESC(17, REG_GPIO_L_E2, BIT(4)),
+ PINCTRL_CONF_DESC(18, REG_GPIO_L_E2, BIT(5)),
+ PINCTRL_CONF_DESC(19, REG_GPIO_L_E2, BIT(6)),
+ PINCTRL_CONF_DESC(20, REG_GPIO_L_E2, BIT(7)),
+ PINCTRL_CONF_DESC(21, REG_GPIO_L_E2, BIT(8)),
+ PINCTRL_CONF_DESC(22, REG_GPIO_L_E2, BIT(9)),
+ PINCTRL_CONF_DESC(23, REG_GPIO_L_E2, BIT(10)),
+ PINCTRL_CONF_DESC(24, REG_GPIO_L_E2, BIT(11)),
+ PINCTRL_CONF_DESC(25, REG_GPIO_L_E2, BIT(12)),
+ PINCTRL_CONF_DESC(26, REG_GPIO_L_E2, BIT(13)),
+ PINCTRL_CONF_DESC(27, REG_GPIO_L_E2, BIT(14)),
+ PINCTRL_CONF_DESC(28, REG_GPIO_L_E2, BIT(15)),
+ PINCTRL_CONF_DESC(29, REG_GPIO_L_E2, BIT(16)),
+ PINCTRL_CONF_DESC(30, REG_GPIO_L_E2, BIT(17)),
+ PINCTRL_CONF_DESC(31, REG_GPIO_L_E2, BIT(18)),
+ PINCTRL_CONF_DESC(32, REG_GPIO_L_E2, BIT(18)),
+ PINCTRL_CONF_DESC(33, REG_GPIO_L_E2, BIT(20)),
+ PINCTRL_CONF_DESC(34, REG_GPIO_L_E2, BIT(21)),
+ PINCTRL_CONF_DESC(35, REG_GPIO_L_E2, BIT(22)),
+ PINCTRL_CONF_DESC(36, REG_GPIO_L_E2, BIT(23)),
+ PINCTRL_CONF_DESC(37, REG_GPIO_L_E2, BIT(24)),
+ PINCTRL_CONF_DESC(38, REG_GPIO_L_E2, BIT(25)),
+ PINCTRL_CONF_DESC(39, REG_GPIO_L_E2, BIT(26)),
+ PINCTRL_CONF_DESC(40, REG_GPIO_L_E2, BIT(27)),
+ PINCTRL_CONF_DESC(41, REG_GPIO_L_E2, BIT(28)),
+ PINCTRL_CONF_DESC(42, REG_GPIO_L_E2, BIT(29)),
+ PINCTRL_CONF_DESC(43, REG_GPIO_L_E2, BIT(30)),
+ PINCTRL_CONF_DESC(44, REG_GPIO_L_E2, BIT(31)),
+ PINCTRL_CONF_DESC(45, REG_GPIO_H_E2, BIT(0)),
+ PINCTRL_CONF_DESC(46, REG_GPIO_H_E2, BIT(1)),
+ PINCTRL_CONF_DESC(47, REG_GPIO_H_E2, BIT(2)),
+ PINCTRL_CONF_DESC(48, REG_GPIO_H_E2, BIT(3)),
+ PINCTRL_CONF_DESC(49, REG_GPIO_H_E2, BIT(4)),
+ PINCTRL_CONF_DESC(50, REG_GPIO_H_E2, BIT(5)),
+ PINCTRL_CONF_DESC(51, REG_GPIO_H_E2, BIT(6)),
+ PINCTRL_CONF_DESC(52, REG_GPIO_H_E2, BIT(7)),
+ PINCTRL_CONF_DESC(53, REG_GPIO_H_E2, BIT(8)),
+ PINCTRL_CONF_DESC(54, REG_GPIO_H_E2, BIT(9)),
+ PINCTRL_CONF_DESC(55, REG_GPIO_H_E2, BIT(10)),
+ PINCTRL_CONF_DESC(56, REG_GPIO_H_E2, BIT(11)),
+ PINCTRL_CONF_DESC(57, REG_GPIO_H_E2, BIT(12)),
+ PINCTRL_CONF_DESC(58, REG_GPIO_H_E2, BIT(13)),
+ PINCTRL_CONF_DESC(59, REG_GPIO_H_E2, BIT(14)),
+ PINCTRL_CONF_DESC(61, REG_I2C_SDA_E2, PCIE0_RESET_E2_MASK),
+ PINCTRL_CONF_DESC(62, REG_I2C_SDA_E2, PCIE1_RESET_E2_MASK),
+ PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK),
+};
+
+static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e4_conf[] = {
+ PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK),
+ PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK),
+ PINCTRL_CONF_DESC(2, REG_I2C_SDA_E4, I2C_SDA_E4_MASK),
+ PINCTRL_CONF_DESC(3, REG_I2C_SDA_E4, I2C_SCL_E4_MASK),
+ PINCTRL_CONF_DESC(4, REG_I2C_SDA_E4, SPI_CS0_E4_MASK),
+ PINCTRL_CONF_DESC(5, REG_I2C_SDA_E4, SPI_CLK_E4_MASK),
+ PINCTRL_CONF_DESC(6, REG_I2C_SDA_E4, SPI_MOSI_E4_MASK),
+ PINCTRL_CONF_DESC(7, REG_I2C_SDA_E4, SPI_MISO_E4_MASK),
+ PINCTRL_CONF_DESC(13, REG_GPIO_L_E4, BIT(0)),
+ PINCTRL_CONF_DESC(14, REG_GPIO_L_E4, BIT(1)),
+ PINCTRL_CONF_DESC(15, REG_GPIO_L_E4, BIT(2)),
+ PINCTRL_CONF_DESC(16, REG_GPIO_L_E4, BIT(3)),
+ PINCTRL_CONF_DESC(17, REG_GPIO_L_E4, BIT(4)),
+ PINCTRL_CONF_DESC(18, REG_GPIO_L_E4, BIT(5)),
+ PINCTRL_CONF_DESC(19, REG_GPIO_L_E4, BIT(6)),
+ PINCTRL_CONF_DESC(20, REG_GPIO_L_E4, BIT(7)),
+ PINCTRL_CONF_DESC(21, REG_GPIO_L_E4, BIT(8)),
+ PINCTRL_CONF_DESC(22, REG_GPIO_L_E4, BIT(9)),
+ PINCTRL_CONF_DESC(23, REG_GPIO_L_E4, BIT(10)),
+ PINCTRL_CONF_DESC(24, REG_GPIO_L_E4, BIT(11)),
+ PINCTRL_CONF_DESC(25, REG_GPIO_L_E4, BIT(12)),
+ PINCTRL_CONF_DESC(26, REG_GPIO_L_E4, BIT(13)),
+ PINCTRL_CONF_DESC(27, REG_GPIO_L_E4, BIT(14)),
+ PINCTRL_CONF_DESC(28, REG_GPIO_L_E4, BIT(15)),
+ PINCTRL_CONF_DESC(29, REG_GPIO_L_E4, BIT(16)),
+ PINCTRL_CONF_DESC(30, REG_GPIO_L_E4, BIT(17)),
+ PINCTRL_CONF_DESC(31, REG_GPIO_L_E4, BIT(18)),
+ PINCTRL_CONF_DESC(32, REG_GPIO_L_E4, BIT(18)),
+ PINCTRL_CONF_DESC(33, REG_GPIO_L_E4, BIT(20)),
+ PINCTRL_CONF_DESC(34, REG_GPIO_L_E4, BIT(21)),
+ PINCTRL_CONF_DESC(35, REG_GPIO_L_E4, BIT(22)),
+ PINCTRL_CONF_DESC(36, REG_GPIO_L_E4, BIT(23)),
+ PINCTRL_CONF_DESC(37, REG_GPIO_L_E4, BIT(24)),
+ PINCTRL_CONF_DESC(38, REG_GPIO_L_E4, BIT(25)),
+ PINCTRL_CONF_DESC(39, REG_GPIO_L_E4, BIT(26)),
+ PINCTRL_CONF_DESC(40, REG_GPIO_L_E4, BIT(27)),
+ PINCTRL_CONF_DESC(41, REG_GPIO_L_E4, BIT(28)),
+ PINCTRL_CONF_DESC(42, REG_GPIO_L_E4, BIT(29)),
+ PINCTRL_CONF_DESC(43, REG_GPIO_L_E4, BIT(30)),
+ PINCTRL_CONF_DESC(44, REG_GPIO_L_E4, BIT(31)),
+ PINCTRL_CONF_DESC(45, REG_GPIO_H_E4, BIT(0)),
+ PINCTRL_CONF_DESC(46, REG_GPIO_H_E4, BIT(1)),
+ PINCTRL_CONF_DESC(47, REG_GPIO_H_E4, BIT(2)),
+ PINCTRL_CONF_DESC(48, REG_GPIO_H_E4, BIT(3)),
+ PINCTRL_CONF_DESC(49, REG_GPIO_H_E4, BIT(4)),
+ PINCTRL_CONF_DESC(50, REG_GPIO_H_E4, BIT(5)),
+ PINCTRL_CONF_DESC(51, REG_GPIO_H_E4, BIT(6)),
+ PINCTRL_CONF_DESC(52, REG_GPIO_H_E4, BIT(7)),
+ PINCTRL_CONF_DESC(53, REG_GPIO_H_E4, BIT(8)),
+ PINCTRL_CONF_DESC(54, REG_GPIO_H_E4, BIT(9)),
+ PINCTRL_CONF_DESC(55, REG_GPIO_H_E4, BIT(10)),
+ PINCTRL_CONF_DESC(56, REG_GPIO_H_E4, BIT(11)),
+ PINCTRL_CONF_DESC(57, REG_GPIO_H_E4, BIT(12)),
+ PINCTRL_CONF_DESC(58, REG_GPIO_H_E4, BIT(13)),
+ PINCTRL_CONF_DESC(59, REG_GPIO_H_E4, BIT(14)),
+ PINCTRL_CONF_DESC(61, REG_I2C_SDA_E4, PCIE0_RESET_E4_MASK),
+ PINCTRL_CONF_DESC(62, REG_I2C_SDA_E4, PCIE1_RESET_E4_MASK),
+ PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK),
+};
+
+static const struct airoha_pinctrl_conf airoha_pinctrl_pcie_rst_od_conf[] = {
+ PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK),
+ PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK),
+ PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK),
+};
+
+static int airoha_convert_pin_to_reg_offset(struct pinctrl_dev *pctrl_dev,
+ struct pinctrl_gpio_range *range,
+ int pin)
+{
+ if (!range)
+ range = pinctrl_find_gpio_range_from_pin_nolock(pctrl_dev,
+ pin);
+ if (!range)
+ return -EINVAL;
+
+ return pin - range->pin_base;
+}
+
+/* gpio callbacks */
+static void airoha_gpio_set(struct gpio_chip *chip, unsigned int gpio,
+ int value)
+{
+ struct airoha_pinctrl *pinctrl = gpiochip_get_data(chip);
+ u32 offset = gpio % AIROHA_PIN_BANK_SIZE;
+ u8 index = gpio / AIROHA_PIN_BANK_SIZE;
+
+ regmap_update_bits(pinctrl->regmap, pinctrl->gpiochip.data[index],
+ BIT(offset), value ? BIT(offset) : 0);
+}
+
+static int airoha_gpio_get(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct airoha_pinctrl *pinctrl = gpiochip_get_data(chip);
+ u32 val, pin = gpio % AIROHA_PIN_BANK_SIZE;
+ u8 index = gpio / AIROHA_PIN_BANK_SIZE;
+ int err;
+
+ err = regmap_read(pinctrl->regmap,
+ pinctrl->gpiochip.data[index], &val);
+
+ return err ? err : !!(val & BIT(pin));
+}
+
+static int airoha_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int gpio, int value)
+{
+ int err;
+
+ err = pinctrl_gpio_direction_output(chip, gpio);
+ if (err)
+ return err;
+
+ airoha_gpio_set(chip, gpio, value);
+
+ return 0;
+}
+
+/* irq callbacks */
+static void airoha_irq_unmask(struct irq_data *data)
+{
+ u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_PIN;
+ u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN;
+ u32 mask = GENMASK(2 * offset + 1, 2 * offset);
+ struct airoha_pinctrl_gpiochip *gpiochip;
+ struct airoha_pinctrl *pinctrl;
+ u32 val = BIT(2 * offset);
+
+ gpiochip = irq_data_get_irq_chip_data(data);
+ if (WARN_ON_ONCE(data->hwirq >= ARRAY_SIZE(gpiochip->irq_type)))
+ return;
+
+ pinctrl = container_of(gpiochip, struct airoha_pinctrl, gpiochip);
+ switch (gpiochip->irq_type[data->hwirq]) {
+ case IRQ_TYPE_LEVEL_LOW:
+ val = val << 1;
+ fallthrough;
+ case IRQ_TYPE_LEVEL_HIGH:
+ regmap_update_bits(pinctrl->regmap, gpiochip->level[index],
+ mask, val);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ val = val << 1;
+ fallthrough;
+ case IRQ_TYPE_EDGE_RISING:
+ regmap_update_bits(pinctrl->regmap, gpiochip->edge[index],
+ mask, val);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ regmap_set_bits(pinctrl->regmap, gpiochip->edge[index], mask);
+ break;
+ default:
+ break;
+ }
+}
+
+static void airoha_irq_mask(struct irq_data *data)
+{
+ u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_PIN;
+ u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN;
+ u32 mask = GENMASK(2 * offset + 1, 2 * offset);
+ struct airoha_pinctrl_gpiochip *gpiochip;
+ struct airoha_pinctrl *pinctrl;
+
+ gpiochip = irq_data_get_irq_chip_data(data);
+ pinctrl = container_of(gpiochip, struct airoha_pinctrl, gpiochip);
+
+ regmap_clear_bits(pinctrl->regmap, gpiochip->level[index], mask);
+ regmap_clear_bits(pinctrl->regmap, gpiochip->edge[index], mask);
+}
+
+static int airoha_irq_type(struct irq_data *data, unsigned int type)
+{
+ struct airoha_pinctrl_gpiochip *gpiochip;
+
+ gpiochip = irq_data_get_irq_chip_data(data);
+ if (data->hwirq >= ARRAY_SIZE(gpiochip->irq_type))
+ return -EINVAL;
+
+ if (type == IRQ_TYPE_PROBE) {
+ if (gpiochip->irq_type[data->hwirq])
+ return 0;
+
+ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+ }
+ gpiochip->irq_type[data->hwirq] = type & IRQ_TYPE_SENSE_MASK;
+
+ return 0;
+}
+
+static irqreturn_t airoha_irq_handler(int irq, void *data)
+{
+ struct airoha_pinctrl *pinctrl = data;
+ bool handled = false;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(irq_status_regs); i++) {
+ struct gpio_irq_chip *girq = &pinctrl->gpiochip.chip.irq;
+ u32 regmap;
+ unsigned long status;
+ int irq;
+
+ if (regmap_read(pinctrl->regmap, pinctrl->gpiochip.status[i],
+ &regmap))
+ continue;
+
+ status = regmap;
+ for_each_set_bit(irq, &status, AIROHA_PIN_BANK_SIZE) {
+ u32 offset = irq + i * AIROHA_PIN_BANK_SIZE;
+
+ generic_handle_irq(irq_find_mapping(girq->domain,
+ offset));
+ regmap_write(pinctrl->regmap,
+ pinctrl->gpiochip.status[i], BIT(irq));
+ }
+ handled |= !!status;
+ }
+
+ return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static const struct irq_chip airoha_gpio_irq_chip = {
+ .name = "airoha-gpio-irq",
+ .irq_unmask = airoha_irq_unmask,
+ .irq_mask = airoha_irq_mask,
+ .irq_mask_ack = airoha_irq_mask,
+ .irq_set_type = airoha_irq_type,
+ .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE,
+};
+
+static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl,
+ struct platform_device *pdev)
+{
+ struct airoha_pinctrl_gpiochip *chip = &pinctrl->gpiochip;
+ struct gpio_chip *gc = &chip->chip;
+ struct gpio_irq_chip *girq = &gc->irq;
+ struct device *dev = &pdev->dev;
+ int irq, err;
+
+ chip->data = gpio_data_regs;
+ chip->dir = gpio_dir_regs;
+ chip->out = gpio_out_regs;
+ chip->status = irq_status_regs;
+ chip->level = irq_level_regs;
+ chip->edge = irq_edge_regs;
+
+ gc->parent = dev;
+ gc->label = dev_name(dev);
+ gc->request = gpiochip_generic_request;
+ gc->free = gpiochip_generic_free;
+ gc->direction_input = pinctrl_gpio_direction_input;
+ gc->direction_output = airoha_gpio_direction_output;
+ gc->set = airoha_gpio_set;
+ gc->get = airoha_gpio_get;
+ gc->base = -1;
+ gc->ngpio = AIROHA_NUM_PINS;
+
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_simple_irq;
+ gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ err = devm_request_irq(dev, irq, airoha_irq_handler, IRQF_SHARED,
+ dev_name(dev), pinctrl);
+ if (err) {
+ dev_err(dev, "error requesting irq %d: %d\n", irq, err);
+ return err;
+ }
+
+ return devm_gpiochip_add_data(dev, gc, pinctrl);
+}
+
+/* pinmux callbacks */
+static int airoha_pinmux_set_mux(struct pinctrl_dev *pctrl_dev,
+ unsigned int selector,
+ unsigned int group)
+{
+ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ const struct airoha_pinctrl_func *func;
+ struct function_desc *desc;
+ struct group_desc *grp;
+ int i;
+
+ desc = pinmux_generic_get_function(pctrl_dev, selector);
+ if (!desc)
+ return -EINVAL;
+
+ grp = pinctrl_generic_get_group(pctrl_dev, group);
+ if (!grp)
+ return -EINVAL;
+
+ dev_dbg(pctrl_dev->dev, "enable function %s group %s\n",
+ desc->func.name, grp->grp.name);
+
+ func = desc->data;
+ for (i = 0; i < func->group_size; i++) {
+ const struct airoha_pinctrl_func_group *group;
+ int j;
+
+ group = &func->groups[i];
+ if (strcmp(group->name, grp->grp.name))
+ continue;
+
+ for (j = 0; j < group->regmap_size; j++) {
+ switch (group->regmap[j].mux) {
+ case AIROHA_FUNC_PWM_EXT_MUX:
+ case AIROHA_FUNC_PWM_MUX:
+ regmap_update_bits(pinctrl->regmap,
+ group->regmap[j].offset,
+ group->regmap[j].mask,
+ group->regmap[j].val);
+ break;
+ default:
+ regmap_update_bits(pinctrl->chip_scu,
+ group->regmap[j].offset,
+ group->regmap[j].mask,
+ group->regmap[j].val);
+ break;
+ }
+ }
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int airoha_pinmux_set_direction(struct pinctrl_dev *pctrl_dev,
+ struct pinctrl_gpio_range *range,
+ unsigned int p, bool input)
+{
+ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ u32 mask, index;
+ int err, pin;
+
+ pin = airoha_convert_pin_to_reg_offset(pctrl_dev, range, p);
+ if (pin < 0)
+ return pin;
+
+ /* set output enable */
+ mask = BIT(pin % AIROHA_PIN_BANK_SIZE);
+ index = pin / AIROHA_PIN_BANK_SIZE;
+ err = regmap_update_bits(pinctrl->regmap, pinctrl->gpiochip.out[index],
+ mask, !input ? mask : 0);
+ if (err)
+ return err;
+
+ /* set direction */
+ mask = BIT(2 * (pin % AIROHA_REG_GPIOCTRL_NUM_PIN));
+ index = pin / AIROHA_REG_GPIOCTRL_NUM_PIN;
+ return regmap_update_bits(pinctrl->regmap,
+ pinctrl->gpiochip.dir[index], mask,
+ !input ? mask : 0);
+}
+
+static const struct pinmux_ops airoha_pmxops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .gpio_set_direction = airoha_pinmux_set_direction,
+ .set_mux = airoha_pinmux_set_mux,
+ .strict = true,
+};
+
+/* pinconf callbacks */
+static const struct airoha_pinctrl_reg *
+airoha_pinctrl_get_conf_reg(const struct airoha_pinctrl_conf *conf,
+ int conf_size, int pin)
+{
+ int i;
+
+ for (i = 0; i < conf_size; i++) {
+ if (conf[i].pin == pin)
+ return &conf[i].reg;
+ }
+
+ return NULL;
+}
+
+static int airoha_pinctrl_get_conf(struct airoha_pinctrl *pinctrl,
+ const struct airoha_pinctrl_conf *conf,
+ int conf_size, int pin, u32 *val)
+{
+ const struct airoha_pinctrl_reg *reg;
+
+ reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin);
+ if (!reg)
+ return -EINVAL;
+
+ if (regmap_read(pinctrl->chip_scu, reg->offset, val))
+ return -EINVAL;
+
+ *val = (*val & reg->mask) >> __ffs(reg->mask);
+
+ return 0;
+}
+
+static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl,
+ const struct airoha_pinctrl_conf *conf,
+ int conf_size, int pin, u32 val)
+{
+ const struct airoha_pinctrl_reg *reg = NULL;
+
+ reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin);
+ if (!reg)
+ return -EINVAL;
+
+
+ if (regmap_update_bits(pinctrl->chip_scu, reg->offset, reg->mask,
+ val << __ffs(reg->mask)))
+ return -EINVAL;
+
+ return 0;
+}
+
+#define airoha_pinctrl_get_pullup_conf(pinctrl, pin, val) \
+ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pullup_conf, \
+ ARRAY_SIZE(airoha_pinctrl_pullup_conf), \
+ (pin), (val))
+#define airoha_pinctrl_get_pulldown_conf(pinctrl, pin, val) \
+ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pulldown_conf, \
+ ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \
+ (pin), (val))
+#define airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, val) \
+ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \
+ ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \
+ (pin), (val))
+#define airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, val) \
+ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \
+ ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \
+ (pin), (val))
+#define airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, val) \
+ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \
+ ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \
+ (pin), (val))
+#define airoha_pinctrl_set_pullup_conf(pinctrl, pin, val) \
+ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pullup_conf, \
+ ARRAY_SIZE(airoha_pinctrl_pullup_conf), \
+ (pin), (val))
+#define airoha_pinctrl_set_pulldown_conf(pinctrl, pin, val) \
+ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pulldown_conf, \
+ ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \
+ (pin), (val))
+#define airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, val) \
+ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \
+ ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \
+ (pin), (val))
+#define airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, val) \
+ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \
+ ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \
+ (pin), (val))
+#define airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, val) \
+ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \
+ ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \
+ (pin), (val))
+
+static int airoha_pinconf_get_direction(struct pinctrl_dev *pctrl_dev, u32 p)
+{
+ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ u32 val, mask;
+ int err, pin;
+ u8 index;
+
+ pin = airoha_convert_pin_to_reg_offset(pctrl_dev, NULL, p);
+ if (pin < 0)
+ return pin;
+
+ index = pin / AIROHA_REG_GPIOCTRL_NUM_PIN;
+ err = regmap_read(pinctrl->regmap, pinctrl->gpiochip.dir[index], &val);
+ if (err)
+ return err;
+
+ mask = BIT(2 * (pin % AIROHA_REG_GPIOCTRL_NUM_PIN));
+ return val & mask ? PIN_CONFIG_OUTPUT_ENABLE : PIN_CONFIG_INPUT_ENABLE;
+}
+
+static int airoha_pinconf_get(struct pinctrl_dev *pctrl_dev,
+ unsigned int pin, unsigned long *config)
+{
+ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ u32 arg;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_UP: {
+ u32 pull_up, pull_down;
+
+ if (airoha_pinctrl_get_pullup_conf(pinctrl, pin, &pull_up) ||
+ airoha_pinctrl_get_pulldown_conf(pinctrl, pin, &pull_down))
+ return -EINVAL;
+
+ if (param == PIN_CONFIG_BIAS_PULL_UP &&
+ !(pull_up && !pull_down))
+ return -EINVAL;
+ else if (param == PIN_CONFIG_BIAS_PULL_DOWN &&
+ !(pull_down && !pull_up))
+ return -EINVAL;
+ else if (pull_up || pull_down)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ }
+ case PIN_CONFIG_DRIVE_STRENGTH: {
+ u32 e2, e4;
+
+ if (airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, &e2) ||
+ airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, &e4))
+ return -EINVAL;
+
+ arg = e4 << 1 | e2;
+ break;
+ }
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ if (airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, &arg))
+ return -EINVAL;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ case PIN_CONFIG_INPUT_ENABLE:
+ arg = airoha_pinconf_get_direction(pctrl_dev, pin);
+ if (arg != param)
+ return -EINVAL;
+
+ arg = 1;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int airoha_pinconf_set_pin_value(struct pinctrl_dev *pctrl_dev,
+ unsigned int p, bool value)
+{
+ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ int pin;
+
+ pin = airoha_convert_pin_to_reg_offset(pctrl_dev, NULL, p);
+ if (pin < 0)
+ return pin;
+
+ airoha_gpio_set(&pinctrl->gpiochip.chip, pin, value);
+
+ return 0;
+}
+
+static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+ int i;
+
+ for (i = 0; i < num_configs; i++) {
+ u32 param = pinconf_to_config_param(configs[i]);
+ u32 arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0);
+ airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0);
+ airoha_pinctrl_set_pullup_conf(pinctrl, pin, 1);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 1);
+ airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH: {
+ u32 e2 = 0, e4 = 0;
+
+ switch (arg) {
+ case MTK_DRIVE_2mA:
+ break;
+ case MTK_DRIVE_4mA:
+ e2 = 1;
+ break;
+ case MTK_DRIVE_6mA:
+ e4 = 1;
+ break;
+ case MTK_DRIVE_8mA:
+ e2 = 1;
+ e4 = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, e2);
+ airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, e4);
+ break;
+ }
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, !!arg);
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_OUTPUT: {
+ bool input = param == PIN_CONFIG_INPUT_ENABLE;
+ int err;
+
+ err = airoha_pinmux_set_direction(pctrl_dev, NULL, pin,
+ input);
+ if (err)
+ return err;
+
+ if (param == PIN_CONFIG_OUTPUT) {
+ err = airoha_pinconf_set_pin_value(pctrl_dev,
+ pin, !!arg);
+ if (err)
+ return err;
+ }
+ break;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev,
+ unsigned int group, unsigned long *config)
+{
+ u32 cur_config = 0;
+ int i;
+
+ for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) {
+ if (airoha_pinconf_get(pctrl_dev,
+ airoha_pinctrl_groups[group].pins[i],
+ config))
+ return -EOPNOTSUPP;
+
+ if (i && cur_config != *config)
+ return -EOPNOTSUPP;
+
+ cur_config = *config;
+ }
+
+ return 0;
+}
+
+static int airoha_pinconf_group_set(struct pinctrl_dev *pctrl_dev,
+ unsigned int group, unsigned long *configs,
+ unsigned int num_configs)
+{
+ int i;
+
+ for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) {
+ int err;
+
+ err = airoha_pinconf_set(pctrl_dev,
+ airoha_pinctrl_groups[group].pins[i],
+ configs, num_configs);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops airoha_confops = {
+ .is_generic = true,
+ .pin_config_get = airoha_pinconf_get,
+ .pin_config_set = airoha_pinconf_set,
+ .pin_config_group_get = airoha_pinconf_group_get,
+ .pin_config_group_set = airoha_pinconf_group_set,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
+static const struct pinctrl_ops airoha_pctlops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static struct pinctrl_desc airoha_pinctrl_desc = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ .pctlops = &airoha_pctlops,
+ .pmxops = &airoha_pmxops,
+ .confops = &airoha_confops,
+ .pins = airoha_pinctrl_pins,
+ .npins = ARRAY_SIZE(airoha_pinctrl_pins),
+};
+
+static int airoha_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct airoha_pinctrl *pinctrl;
+ struct regmap *map;
+ int err, i;
+
+ pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL);
+ if (!pinctrl)
+ return -ENOMEM;
+
+ pinctrl->regmap = device_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(pinctrl->regmap))
+ return PTR_ERR(pinctrl->regmap);
+
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ pinctrl->chip_scu = map;
+
+ err = devm_pinctrl_register_and_init(dev, &airoha_pinctrl_desc,
+ pinctrl, &pinctrl->ctrl);
+ if (err)
+ return err;
+
+ /* build pin groups */
+ for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_groups); i++) {
+ const struct pingroup *grp = &airoha_pinctrl_groups[i];
+
+ err = pinctrl_generic_add_group(pinctrl->ctrl, grp->name,
+ grp->pins, grp->npins,
+ (void *)grp);
+ if (err < 0) {
+ dev_err(&pdev->dev, "Failed to register group %s\n",
+ grp->name);
+ return err;
+ }
+ }
+
+ /* build functions */
+ for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_funcs); i++) {
+ const struct airoha_pinctrl_func *func;
+
+ func = &airoha_pinctrl_funcs[i];
+ err = pinmux_generic_add_function(pinctrl->ctrl,
+ func->desc.func.name,
+ func->desc.func.groups,
+ func->desc.func.ngroups,
+ (void *)func);
+ if (err < 0) {
+ dev_err(dev, "Failed to register function %s\n",
+ func->desc.func.name);
+ return err;
+ }
+ }
+
+ err = pinctrl_enable(pinctrl->ctrl);
+ if (err)
+ return err;
+
+ /* build gpio-chip */
+ return airoha_pinctrl_add_gpiochip(pinctrl, pdev);
+}
+
+static const struct of_device_id airoha_pinctrl_of_match[] = {
+ { .compatible = "airoha,en7581-pinctrl" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match);
+
+static struct platform_driver airoha_pinctrl_driver = {
+ .probe = airoha_pinctrl_probe,
+ .driver = {
+ .name = "pinctrl-airoha",
+ .of_match_table = airoha_pinctrl_of_match,
+ },
+};
+module_platform_driver(airoha_pinctrl_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_AUTHOR("Benjamin Larsson <benjamin.larsson@genexis.eu>");
+MODULE_AUTHOR("Markus Gothe <markus.gothe@genexis.eu>");
+MODULE_DESCRIPTION("Pinctrl driver for Airoha SoC");
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 4c4ada06423d..335744ac8310 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -734,7 +734,7 @@ static void armada_37xx_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct armada_37xx_pinctrl *info = gpiochip_get_data(chip);
- seq_printf(p, info->data->name);
+ seq_puts(p, info->data->name);
}
static const struct irq_chip armada_37xx_irqchip = {
diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c
index 68750b6f8e57..4ce2e35a6373 100644
--- a/drivers/pinctrl/nomadik/pinctrl-abx500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
@@ -1089,7 +1089,7 @@ static struct platform_driver abx500_gpio_driver = {
.of_match_table = abx500_gpio_match,
},
.probe = abx500_gpio_probe,
- .remove_new = abx500_gpio_remove,
+ .remove = abx500_gpio_remove,
};
static int __init abx500_gpio_init(void)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c
index 440ff1879424..c49d28793b69 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32g2.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c
@@ -216,6 +216,12 @@ enum s32_pins {
S32G_IMCR_CAN1_RXD = 631,
S32G_IMCR_CAN2_RXD = 632,
S32G_IMCR_CAN3_RXD = 633,
+
+ /* JTAG IMCRs */
+ S32G_IMCR_JTAG_TMS = 562,
+ S32G_IMCR_JTAG_TCK = 572,
+ S32G_IMCR_JTAG_TDI = 573,
+
/* GMAC0 */
S32G_IMCR_Ethernet_MDIO = 527,
S32G_IMCR_Ethernet_CRS = 526,
@@ -229,7 +235,21 @@ enum s32_pins {
S32G_IMCR_Ethernet_RX_DV = 530,
S32G_IMCR_Ethernet_TX_CLK = 538,
S32G_IMCR_Ethernet_REF_CLK = 535,
+
/* PFE EMAC 0 MII */
+ S32G_IMCR_PFE_EMAC_0_MDIO = 837,
+ S32G_IMCR_PFE_EMAC_0_CRS = 836,
+ S32G_IMCR_PFE_EMAC_0_COL = 835,
+ S32G_IMCR_PFE_EMAC_0_RX_D0 = 841,
+ S32G_IMCR_PFE_EMAC_0_RX_D1 = 842,
+ S32G_IMCR_PFE_EMAC_0_RX_D2 = 843,
+ S32G_IMCR_PFE_EMAC_0_RX_D3 = 844,
+ S32G_IMCR_PFE_EMAC_0_RX_ER = 840,
+ S32G_IMCR_PFE_EMAC_0_RX_CLK = 839,
+ S32G_IMCR_PFE_EMAC_0_RX_DV = 845,
+ S32G_IMCR_PFE_EMAC_0_TX_CLK = 846,
+ S32G_IMCR_PFE_EMAC_0_REF_CLK = 838,
+
/* PFE EMAC 1 MII */
S32G_IMCR_PFE_EMAC_1_MDIO = 857,
S32G_IMCR_PFE_EMAC_1_CRS = 856,
@@ -317,6 +337,13 @@ enum s32_pins {
S32G_IMCR_LLCE_CAN13_RXD = 758,
S32G_IMCR_LLCE_CAN14_RXD = 759,
S32G_IMCR_LLCE_CAN15_RXD = 760,
+ S32G_IMCR_LLCE_UART0_RXD = 790,
+ S32G_IMCR_LLCE_UART1_RXD = 791,
+ S32G_IMCR_LLCE_UART2_RXD = 792,
+ S32G_IMCR_LLCE_UART3_RXD = 793,
+ S32G_IMCR_LLCE_LPSPI2_PCS0 = 811,
+ S32G_IMCR_LLCE_LPSPI2_SCK = 816,
+ S32G_IMCR_LLCE_LPSPI2_SIN = 817,
S32G_IMCR_USB_CLK = 895,
S32G_IMCR_USB_DATA0 = 896,
S32G_IMCR_USB_DATA1 = 897,
@@ -503,6 +530,12 @@ static const struct pinctrl_pin_desc s32_pinctrl_pads_siul2[] = {
S32_PINCTRL_PIN(S32G_IMCR_USDHC_DAT7),
S32_PINCTRL_PIN(S32G_IMCR_USDHC_DQS),
S32_PINCTRL_PIN(S32G_IMCR_CAN0_RXD),
+
+ /* JTAG IMCRs */
+ S32_PINCTRL_PIN(S32G_IMCR_JTAG_TMS),
+ S32_PINCTRL_PIN(S32G_IMCR_JTAG_TCK),
+ S32_PINCTRL_PIN(S32G_IMCR_JTAG_TDI),
+
/* GMAC0 */
S32_PINCTRL_PIN(S32G_IMCR_Ethernet_MDIO),
S32_PINCTRL_PIN(S32G_IMCR_Ethernet_CRS),
@@ -638,6 +671,13 @@ static const struct pinctrl_pin_desc s32_pinctrl_pads_siul2[] = {
S32_PINCTRL_PIN(S32G_IMCR_LLCE_CAN13_RXD),
S32_PINCTRL_PIN(S32G_IMCR_LLCE_CAN14_RXD),
S32_PINCTRL_PIN(S32G_IMCR_LLCE_CAN15_RXD),
+ S32_PINCTRL_PIN(S32G_IMCR_LLCE_UART0_RXD),
+ S32_PINCTRL_PIN(S32G_IMCR_LLCE_UART1_RXD),
+ S32_PINCTRL_PIN(S32G_IMCR_LLCE_UART2_RXD),
+ S32_PINCTRL_PIN(S32G_IMCR_LLCE_UART3_RXD),
+ S32_PINCTRL_PIN(S32G_IMCR_LLCE_LPSPI2_PCS0),
+ S32_PINCTRL_PIN(S32G_IMCR_LLCE_LPSPI2_SCK),
+ S32_PINCTRL_PIN(S32G_IMCR_LLCE_LPSPI2_SIN),
S32_PINCTRL_PIN(S32G_IMCR_CAN1_RXD),
S32_PINCTRL_PIN(S32G_IMCR_CAN2_RXD),
S32_PINCTRL_PIN(S32G_IMCR_CAN3_RXD),
@@ -652,6 +692,18 @@ static const struct pinctrl_pin_desc s32_pinctrl_pads_siul2[] = {
S32_PINCTRL_PIN(S32G_IMCR_USB_DATA7),
S32_PINCTRL_PIN(S32G_IMCR_USB_DIR),
S32_PINCTRL_PIN(S32G_IMCR_USB_NXT),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_MDIO),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_CRS),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_COL),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_RX_D0),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_RX_D1),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_RX_D2),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_RX_D3),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_RX_ER),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_RX_CLK),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_RX_DV),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_TX_CLK),
+ S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_0_REF_CLK),
S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_1_MDIO),
S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_1_CRS),
S32_PINCTRL_PIN(S32G_IMCR_PFE_EMAC_1_COL),
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 7f66ec73199a..fff6d4209ad5 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -506,7 +506,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
case IRQ_TYPE_EDGE_BOTH:
pin_reg &= ~BIT(LEVEL_TRIG_OFF);
pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
- pin_reg |= BOTH_EADGE << ACTIVE_LEVEL_OFF;
+ pin_reg |= BOTH_EDGES << ACTIVE_LEVEL_OFF;
irq_set_handler_locked(d, handle_edge_irq);
break;
@@ -1204,7 +1204,7 @@ static struct platform_driver amd_gpio_driver = {
#endif
},
.probe = amd_gpio_probe,
- .remove_new = amd_gpio_remove,
+ .remove = amd_gpio_remove,
};
module_platform_driver(amd_gpio_driver);
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
index cf59089f2776..667be49c3f48 100644
--- a/drivers/pinctrl/pinctrl-amd.h
+++ b/drivers/pinctrl/pinctrl-amd.h
@@ -60,12 +60,12 @@
#define DB_TYPE_PRESERVE_HIGH_GLITCH 0x2UL
#define DB_TYPE_REMOVE_GLITCH 0x3UL
-#define EDGE_TRAGGER 0x0UL
+#define EDGE_TRIGGER 0x0UL
#define LEVEL_TRIGGER 0x1UL
#define ACTIVE_HIGH 0x0UL
#define ACTIVE_LOW 0x1UL
-#define BOTH_EADGE 0x2UL
+#define BOTH_EDGES 0x2UL
#define ENABLE_INTERRUPT 0x1UL
#define DISABLE_INTERRUPT 0x0UL
diff --git a/drivers/pinctrl/pinctrl-artpec6.c b/drivers/pinctrl/pinctrl-artpec6.c
index dd93f124e0a0..717f9592b28b 100644
--- a/drivers/pinctrl/pinctrl-artpec6.c
+++ b/drivers/pinctrl/pinctrl-artpec6.c
@@ -988,7 +988,7 @@ static struct platform_driver artpec6_pmx_driver = {
.of_match_table = artpec6_pinctrl_match,
},
.probe = artpec6_pmx_probe,
- .remove_new = artpec6_pmx_remove,
+ .remove = artpec6_pmx_remove,
};
static int __init artpec6_pmx_init(void)
diff --git a/drivers/pinctrl/pinctrl-aw9523.c b/drivers/pinctrl/pinctrl-aw9523.c
index 1374f30166bc..9bf53de20be8 100644
--- a/drivers/pinctrl/pinctrl-aw9523.c
+++ b/drivers/pinctrl/pinctrl-aw9523.c
@@ -80,7 +80,7 @@ struct aw9523 {
struct regmap *regmap;
struct mutex i2c_lock;
struct gpio_desc *reset_gpio;
- struct regulator *vio_vreg;
+ int vio_vreg;
struct pinctrl_dev *pctl;
struct gpio_chip gpio;
struct aw9523_irq *irq;
@@ -550,10 +550,10 @@ static int aw9523_gpio_get(struct gpio_chip *chip, unsigned int offset)
/**
* _aw9523_gpio_get_multiple - Get I/O state for an entire port
- * @regmap: Regmap structure
- * @pin: gpiolib pin number
+ * @awi: Controller data
* @regbit: hw pin index, used to retrieve port number
* @state: returned port I/O state
+ * @mask: lines to read values for
*
* Return: Zero for success or negative number for error
*/
@@ -972,29 +972,23 @@ static int aw9523_probe(struct i2c_client *client)
if (IS_ERR(awi->regmap))
return PTR_ERR(awi->regmap);
- awi->vio_vreg = devm_regulator_get_optional(dev, "vio");
- if (IS_ERR(awi->vio_vreg)) {
- if (PTR_ERR(awi->vio_vreg) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- awi->vio_vreg = NULL;
- } else {
- ret = regulator_enable(awi->vio_vreg);
- if (ret)
- return ret;
- }
+ awi->vio_vreg = devm_regulator_get_enable_optional(dev, "vio");
+ if (awi->vio_vreg && awi->vio_vreg != -ENODEV)
+ return awi->vio_vreg;
+
+ ret = devm_mutex_init(dev, &awi->i2c_lock);
+ if (ret)
+ return ret;
- mutex_init(&awi->i2c_lock);
lockdep_set_subclass(&awi->i2c_lock, i2c_adapter_depth(client->adapter));
pdesc = devm_kzalloc(dev, sizeof(*pdesc), GFP_KERNEL);
- if (!pdesc) {
- ret = -ENOMEM;
- goto err_disable_vregs;
- }
+ if (!pdesc)
+ return -ENOMEM;
ret = aw9523_hw_init(awi);
if (ret)
- goto err_disable_vregs;
+ return ret;
pdesc->name = dev_name(dev);
pdesc->owner = THIS_MODULE;
@@ -1006,31 +1000,20 @@ static int aw9523_probe(struct i2c_client *client)
ret = aw9523_init_gpiochip(awi, pdesc->npins);
if (ret)
- goto err_disable_vregs;
+ return ret;
if (client->irq) {
ret = aw9523_init_irq(awi, client->irq);
if (ret)
- goto err_disable_vregs;
+ return ret;
}
awi->pctl = devm_pinctrl_register(dev, pdesc, awi);
- if (IS_ERR(awi->pctl)) {
- ret = dev_err_probe(dev, PTR_ERR(awi->pctl), "Cannot register pinctrl");
- goto err_disable_vregs;
- }
-
- ret = devm_gpiochip_add_data(dev, &awi->gpio, awi);
- if (ret)
- goto err_disable_vregs;
-
- return ret;
+ if (IS_ERR(awi->pctl))
+ return dev_err_probe(dev, PTR_ERR(awi->pctl),
+ "Cannot register pinctrl");
-err_disable_vregs:
- if (awi->vio_vreg)
- regulator_disable(awi->vio_vreg);
- mutex_destroy(&awi->i2c_lock);
- return ret;
+ return devm_gpiochip_add_data(dev, &awi->gpio, awi);
}
static void aw9523_remove(struct i2c_client *client)
@@ -1043,19 +1026,15 @@ static void aw9523_remove(struct i2c_client *client)
* set the pins to hardware defaults before removing the driver
* to leave it in a clean, safe and predictable state.
*/
- if (awi->vio_vreg) {
- regulator_disable(awi->vio_vreg);
- } else {
+ if (awi->vio_vreg == -ENODEV) {
mutex_lock(&awi->i2c_lock);
aw9523_hw_init(awi);
mutex_unlock(&awi->i2c_lock);
}
-
- mutex_destroy(&awi->i2c_lock);
}
static const struct i2c_device_id aw9523_i2c_id_table[] = {
- { "aw9523_i2c", 0 },
+ { "aw9523_i2c" },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw9523_i2c_id_table);
diff --git a/drivers/pinctrl/pinctrl-cy8c95x0.c b/drivers/pinctrl/pinctrl-cy8c95x0.c
index 5096ccdd459e..0d6c2027d4c1 100644
--- a/drivers/pinctrl/pinctrl-cy8c95x0.c
+++ b/drivers/pinctrl/pinctrl-cy8c95x0.c
@@ -141,7 +141,6 @@ static const struct dmi_system_id cy8c95x0_dmi_acpi_irq_info[] = {
* @nport: Number of Gports in this chip
* @gpio_chip: gpiolib chip
* @driver_data: private driver data
- * @regulator: Pointer to the regulator for the IC
* @dev: struct device
* @pctldev: pin controller device
* @pinctrl_desc: pin controller description
@@ -160,10 +159,9 @@ struct cy8c95x0_pinctrl {
DECLARE_BITMAP(irq_trig_high, MAX_LINE);
DECLARE_BITMAP(push_pull, MAX_LINE);
DECLARE_BITMAP(shiftmask, MAX_LINE);
- int nport;
+ unsigned int nport;
struct gpio_chip gpio_chip;
unsigned long driver_data;
- struct regulator *regulator;
struct device *dev;
struct pinctrl_dev *pctldev;
struct pinctrl_desc pinctrl_desc;
@@ -612,9 +610,8 @@ static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
DECLARE_BITMAP(tmask, MAX_LINE);
DECLARE_BITMAP(tval, MAX_LINE);
int write_val;
- int ret = 0;
- int i;
u8 bits;
+ int ret;
/* Add the 4 bit gap of Gport2 */
bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE);
@@ -625,7 +622,7 @@ static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
bitmap_shift_left(tval, tval, 4, MAX_LINE);
bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
- for (i = 0; i < chip->nport; i++) {
+ for (unsigned int i = 0; i < chip->nport; i++) {
/* Skip over unused banks */
bits = bitmap_get_value8(tmask, i * BANK_SZ);
if (!bits)
@@ -634,15 +631,13 @@ static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
write_val = bitmap_get_value8(tval, i * BANK_SZ);
ret = cy8c95x0_regmap_update_bits(chip, reg, i, bits, write_val);
- if (ret < 0)
- goto out;
+ if (ret < 0) {
+ dev_err(chip->dev, "failed writing register %d, port %u: err %d\n", reg, i, ret);
+ return ret;
+ }
}
-out:
- if (ret < 0)
- dev_err(chip->dev, "failed writing register %d, port %d: err %d\n", reg, i, ret);
-
- return ret;
+ return 0;
}
static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
@@ -652,9 +647,8 @@ static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
DECLARE_BITMAP(tval, MAX_LINE);
DECLARE_BITMAP(tmp, MAX_LINE);
int read_val;
- int ret = 0;
- int i;
u8 bits;
+ int ret;
/* Add the 4 bit gap of Gport2 */
bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE);
@@ -665,15 +659,17 @@ static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
bitmap_shift_left(tval, tval, 4, MAX_LINE);
bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
- for (i = 0; i < chip->nport; i++) {
+ for (unsigned int i = 0; i < chip->nport; i++) {
/* Skip over unused banks */
bits = bitmap_get_value8(tmask, i * BANK_SZ);
if (!bits)
continue;
ret = cy8c95x0_regmap_read(chip, reg, i, &read_val);
- if (ret < 0)
- goto out;
+ if (ret < 0) {
+ dev_err(chip->dev, "failed reading register %d, port %u: err %d\n", reg, i, ret);
+ return ret;
+ }
read_val &= bits;
read_val |= bitmap_get_value8(tval, i * BANK_SZ) & ~bits;
@@ -684,11 +680,7 @@ static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
bitmap_shift_right(tmp, tval, 4, MAX_LINE);
bitmap_replace(val, tmp, tval, chip->shiftmask, MAX_LINE);
-out:
- if (ret < 0)
- dev_err(chip->dev, "failed reading register %d, port %d: err %d\n", reg, i, ret);
-
- return ret;
+ return 0;
}
static int cy8c95x0_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
@@ -754,14 +746,12 @@ static int cy8c95x0_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
ret = cy8c95x0_regmap_read(chip, CY8C95X0_DIRECTION, port, &reg_val);
if (ret < 0)
- goto out;
+ return ret;
if (reg_val & bit)
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
-out:
- return ret;
}
static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
@@ -823,8 +813,7 @@ static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
case PIN_CONFIG_SLEEP_HARDWARE_STATE:
case PIN_CONFIG_SLEW_RATE:
default:
- ret = -ENOTSUPP;
- goto out;
+ return -ENOTSUPP;
}
/*
* Writing 1 to one of the drive mode registers will automatically
@@ -832,7 +821,7 @@ static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
*/
ret = cy8c95x0_regmap_read(chip, reg, port, &reg_val);
if (ret < 0)
- goto out;
+ return ret;
if (reg_val & bit)
arg = 1;
@@ -840,8 +829,7 @@ static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
arg = !arg;
*config = pinconf_to_config_packed(param, (u16)arg);
-out:
- return ret;
+ return 0;
}
static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip,
@@ -853,7 +841,6 @@ static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip,
unsigned long param = pinconf_to_config_param(config);
unsigned long arg = pinconf_to_config_argument(config);
unsigned int reg;
- int ret;
switch (param) {
case PIN_CONFIG_BIAS_PULL_UP:
@@ -884,22 +871,17 @@ static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip,
reg = CY8C95X0_PWMSEL;
break;
case PIN_CONFIG_OUTPUT_ENABLE:
- ret = cy8c95x0_pinmux_direction(chip, off, !arg);
- goto out;
+ return cy8c95x0_pinmux_direction(chip, off, !arg);
case PIN_CONFIG_INPUT_ENABLE:
- ret = cy8c95x0_pinmux_direction(chip, off, arg);
- goto out;
+ return cy8c95x0_pinmux_direction(chip, off, arg);
default:
- ret = -ENOTSUPP;
- goto out;
+ return -ENOTSUPP;
}
/*
* Writing 1 to one of the drive mode registers will automatically
* clear conflicting set bits in the other drive mode registers.
*/
- ret = cy8c95x0_regmap_write_bits(chip, reg, port, bit, bit);
-out:
- return ret;
+ return cy8c95x0_regmap_write_bits(chip, reg, port, bit, bit);
}
static int cy8c95x0_gpio_get_multiple(struct gpio_chip *gc,
@@ -1424,32 +1406,30 @@ static int cy8c95x0_detect(struct i2c_client *client,
}
dev_info(&client->dev, "Found a %s chip at 0x%02x.\n", name, client->addr);
- strscpy(info->type, name, I2C_NAME_SIZE);
+ strscpy(info->type, name);
return 0;
}
static int cy8c95x0_probe(struct i2c_client *client)
{
+ struct device *dev = &client->dev;
struct cy8c95x0_pinctrl *chip;
struct regmap_config regmap_conf;
struct regmap_range_cfg regmap_range_conf;
- struct regulator *reg;
int ret;
- chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
- chip->dev = &client->dev;
+ chip->dev = dev;
/* Set the device type */
chip->driver_data = (uintptr_t)i2c_get_match_data(client);
if (!chip->driver_data)
return -ENODEV;
- i2c_set_clientdata(client, chip);
-
chip->tpin = chip->driver_data & CY8C95X0_GPIO_MASK;
chip->nport = DIV_ROUND_UP(CY8C95X0_PIN_TO_OFFSET(chip->tpin), BANK_SZ);
@@ -1457,46 +1437,34 @@ static int cy8c95x0_probe(struct i2c_client *client)
switch (chip->tpin) {
case 20:
- strscpy(chip->name, cy8c95x0_id[0].name, I2C_NAME_SIZE);
+ strscpy(chip->name, cy8c95x0_id[0].name);
regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 3 * MUXED_STRIDE;
break;
case 40:
- strscpy(chip->name, cy8c95x0_id[1].name, I2C_NAME_SIZE);
+ strscpy(chip->name, cy8c95x0_id[1].name);
regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 6 * MUXED_STRIDE;
break;
case 60:
- strscpy(chip->name, cy8c95x0_id[2].name, I2C_NAME_SIZE);
+ strscpy(chip->name, cy8c95x0_id[2].name);
regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 8 * MUXED_STRIDE;
break;
default:
return -ENODEV;
}
- reg = devm_regulator_get(&client->dev, "vdd");
- if (IS_ERR(reg)) {
- if (PTR_ERR(reg) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- } else {
- ret = regulator_enable(reg);
- if (ret) {
- dev_err(&client->dev, "failed to enable regulator vdd: %d\n", ret);
- return ret;
- }
- chip->regulator = reg;
- }
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable regulator vdd\n");
/* bring the chip out of reset if reset pin is provided */
- chip->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(chip->gpio_reset)) {
- ret = dev_err_probe(chip->dev, PTR_ERR(chip->gpio_reset),
- "Failed to get GPIO 'reset'\n");
- goto err_exit;
- } else if (chip->gpio_reset) {
- usleep_range(1000, 2000);
+ chip->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(chip->gpio_reset))
+ return dev_err_probe(dev, PTR_ERR(chip->gpio_reset), "Failed to get GPIO 'reset'\n");
+ gpiod_set_consumer_name(chip->gpio_reset, "CY8C95X0 RESET");
+ if (chip->gpio_reset) {
+ fsleep(1000);
gpiod_set_value_cansleep(chip->gpio_reset, 0);
- usleep_range(250000, 300000);
-
- gpiod_set_consumer_name(chip->gpio_reset, "CY8C95X0 RESET");
+ fsleep(250000);
}
/* Regmap for direct and paged registers */
@@ -1506,10 +1474,8 @@ static int cy8c95x0_probe(struct i2c_client *client)
regmap_conf.num_reg_defaults_raw = regmap_range_conf.range_max;
chip->regmap = devm_regmap_init_i2c(client, &regmap_conf);
- if (IS_ERR(chip->regmap)) {
- ret = PTR_ERR(chip->regmap);
- goto err_exit;
- }
+ if (IS_ERR(chip->regmap))
+ return PTR_ERR(chip->regmap);
bitmap_zero(chip->push_pull, MAX_LINE);
bitmap_zero(chip->shiftmask, MAX_LINE);
@@ -1525,31 +1491,14 @@ static int cy8c95x0_probe(struct i2c_client *client)
if (client->irq) {
ret = cy8c95x0_irq_setup(chip, client->irq);
if (ret)
- goto err_exit;
+ return ret;
}
ret = cy8c95x0_setup_pinctrl(chip);
if (ret)
- goto err_exit;
-
- ret = cy8c95x0_setup_gpiochip(chip);
- if (ret)
- goto err_exit;
-
- return 0;
-
-err_exit:
- if (!IS_ERR_OR_NULL(chip->regulator))
- regulator_disable(chip->regulator);
- return ret;
-}
-
-static void cy8c95x0_remove(struct i2c_client *client)
-{
- struct cy8c95x0_pinctrl *chip = i2c_get_clientdata(client);
+ return ret;
- if (!IS_ERR_OR_NULL(chip->regulator))
- regulator_disable(chip->regulator);
+ return cy8c95x0_setup_gpiochip(chip);
}
static const struct acpi_device_id cy8c95x0_acpi_ids[] = {
@@ -1565,7 +1514,6 @@ static struct i2c_driver cy8c95x0_driver = {
.acpi_match_table = cy8c95x0_acpi_ids,
},
.probe = cy8c95x0_probe,
- .remove = cy8c95x0_remove,
.id_table = cy8c95x0_id,
.detect = cy8c95x0_detect,
};
diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
index 0f6b55fec31d..eddb01796a83 100644
--- a/drivers/pinctrl/pinctrl-k210.c
+++ b/drivers/pinctrl/pinctrl-k210.c
@@ -96,8 +96,6 @@ struct k210_fpioa_data {
struct k210_fpioa __iomem *fpioa;
struct regmap *sysctl_map;
u32 power_offset;
- struct clk *clk;
- struct clk *pclk;
};
#define K210_PIN_NAME(i) ("IO_" #i)
@@ -183,7 +181,7 @@ static const u32 k210_pinconf_mode_id_to_mode[] = {
[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
};
-#undef DEFAULT
+#undef K210_PC_DEFAULT
/*
* Pin functions configuration information.
@@ -925,6 +923,7 @@ static int k210_fpioa_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct k210_fpioa_data *pdata;
+ struct clk *clk, *pclk;
dev_info(dev, "K210 FPIOA pin controller\n");
@@ -939,13 +938,13 @@ static int k210_fpioa_probe(struct platform_device *pdev)
if (IS_ERR(pdata->fpioa))
return PTR_ERR(pdata->fpioa);
- pdata->clk = devm_clk_get_enabled(dev, "ref");
- if (IS_ERR(pdata->clk))
- return PTR_ERR(pdata->clk);
+ clk = devm_clk_get_enabled(dev, "ref");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
- pdata->pclk = devm_clk_get_optional_enabled(dev, "pclk");
- if (IS_ERR(pdata->pclk))
- return PTR_ERR(pdata->pclk);
+ pclk = devm_clk_get_optional_enabled(dev, "pclk");
+ if (IS_ERR(pclk))
+ return PTR_ERR(pclk);
pdata->sysctl_map =
syscon_regmap_lookup_by_phandle_args(np,
diff --git a/drivers/pinctrl/pinctrl-k230.c b/drivers/pinctrl/pinctrl-k230.c
new file mode 100644
index 000000000000..a9b4627b46b0
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-k230.c
@@ -0,0 +1,641 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Copyright (C) 2024 Canaan Bright Sight Co. Ltd
+ * Copyright (C) 2024 Ze Huang <18771902331@163.com>
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/regmap.h>
+#include <linux/seq_file.h>
+
+#include "core.h"
+#include "pinconf.h"
+
+#define K230_NPINS 64
+
+#define K230_SHIFT_ST (0)
+#define K230_SHIFT_DS (1)
+#define K230_SHIFT_BIAS (5)
+#define K230_SHIFT_PD (5)
+#define K230_SHIFT_PU (6)
+#define K230_SHIFT_OE (7)
+#define K230_SHIFT_IE (8)
+#define K230_SHIFT_MSC (9)
+#define K230_SHIFT_SL (10)
+#define K230_SHIFT_SEL (11)
+
+#define K230_PC_ST BIT(0)
+#define K230_PC_DS GENMASK(4, 1)
+#define K230_PC_PD BIT(5)
+#define K230_PC_PU BIT(6)
+#define K230_PC_BIAS GENMASK(6, 5)
+#define K230_PC_OE BIT(7)
+#define K230_PC_IE BIT(8)
+#define K230_PC_MSC BIT(9)
+#define K230_PC_SL BIT(10)
+#define K230_PC_SEL GENMASK(13, 11)
+
+struct k230_pin_conf {
+ unsigned int func;
+ unsigned long *configs;
+ unsigned int nconfigs;
+};
+
+struct k230_pin_group {
+ const char *name;
+ unsigned int *pins;
+ unsigned int num_pins;
+
+ struct k230_pin_conf *data;
+};
+
+struct k230_pmx_func {
+ const char *name;
+ const char **groups;
+ unsigned int *group_idx;
+ unsigned int ngroups;
+};
+
+struct k230_pinctrl {
+ struct pinctrl_desc pctl;
+ struct pinctrl_dev *pctl_dev;
+ struct regmap *regmap_base;
+ void __iomem *base;
+ struct k230_pin_group *groups;
+ unsigned int ngroups;
+ struct k230_pmx_func *functions;
+ unsigned int nfunctions;
+};
+
+static const struct regmap_config k230_regmap_config = {
+ .name = "canaan,pinctrl",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .max_register = 0x100,
+ .reg_stride = 4,
+};
+
+static int k230_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->ngroups;
+}
+
+static const char *k230_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->groups[selector].name;
+}
+
+static int k230_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ if (selector >= info->ngroups)
+ return -EINVAL;
+
+ *pins = info->groups[selector].pins;
+ *num_pins = info->groups[selector].num_pins;
+
+ return 0;
+}
+
+static inline const struct k230_pmx_func *k230_name_to_funtion(
+ const struct k230_pinctrl *info, const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < info->nfunctions; i++) {
+ if (!strcmp(info->functions[i].name, name))
+ return &info->functions[i];
+ }
+
+ return NULL;
+}
+
+static struct pinctrl_pin_desc k230_pins[] = {
+ PINCTRL_PIN(0, "IO0"), PINCTRL_PIN(1, "IO1"), PINCTRL_PIN(2, "IO2"),
+ PINCTRL_PIN(3, "IO3"), PINCTRL_PIN(4, "IO4"), PINCTRL_PIN(5, "IO5"),
+ PINCTRL_PIN(6, "IO6"), PINCTRL_PIN(7, "IO7"), PINCTRL_PIN(8, "IO8"),
+ PINCTRL_PIN(9, "IO9"), PINCTRL_PIN(10, "IO10"), PINCTRL_PIN(11, "IO11"),
+ PINCTRL_PIN(12, "IO12"), PINCTRL_PIN(13, "IO13"), PINCTRL_PIN(14, "IO14"),
+ PINCTRL_PIN(15, "IO15"), PINCTRL_PIN(16, "IO16"), PINCTRL_PIN(17, "IO17"),
+ PINCTRL_PIN(18, "IO18"), PINCTRL_PIN(19, "IO19"), PINCTRL_PIN(20, "IO20"),
+ PINCTRL_PIN(21, "IO21"), PINCTRL_PIN(22, "IO22"), PINCTRL_PIN(23, "IO23"),
+ PINCTRL_PIN(24, "IO24"), PINCTRL_PIN(25, "IO25"), PINCTRL_PIN(26, "IO26"),
+ PINCTRL_PIN(27, "IO27"), PINCTRL_PIN(28, "IO28"), PINCTRL_PIN(29, "IO29"),
+ PINCTRL_PIN(30, "IO30"), PINCTRL_PIN(31, "IO31"), PINCTRL_PIN(32, "IO32"),
+ PINCTRL_PIN(33, "IO33"), PINCTRL_PIN(34, "IO34"), PINCTRL_PIN(35, "IO35"),
+ PINCTRL_PIN(36, "IO36"), PINCTRL_PIN(37, "IO37"), PINCTRL_PIN(38, "IO38"),
+ PINCTRL_PIN(39, "IO39"), PINCTRL_PIN(40, "IO40"), PINCTRL_PIN(41, "IO41"),
+ PINCTRL_PIN(42, "IO42"), PINCTRL_PIN(43, "IO43"), PINCTRL_PIN(44, "IO44"),
+ PINCTRL_PIN(45, "IO45"), PINCTRL_PIN(46, "IO46"), PINCTRL_PIN(47, "IO47"),
+ PINCTRL_PIN(48, "IO48"), PINCTRL_PIN(49, "IO49"), PINCTRL_PIN(50, "IO50"),
+ PINCTRL_PIN(51, "IO51"), PINCTRL_PIN(52, "IO52"), PINCTRL_PIN(53, "IO53"),
+ PINCTRL_PIN(54, "IO54"), PINCTRL_PIN(55, "IO55"), PINCTRL_PIN(56, "IO56"),
+ PINCTRL_PIN(57, "IO57"), PINCTRL_PIN(58, "IO58"), PINCTRL_PIN(59, "IO59"),
+ PINCTRL_PIN(60, "IO60"), PINCTRL_PIN(61, "IO61"), PINCTRL_PIN(62, "IO62"),
+ PINCTRL_PIN(63, "IO63")
+};
+
+static void k230_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int offset)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ u32 val, bias, drive, input, slew, schmitt, power;
+ struct k230_pin_group *grp = k230_pins[offset].drv_data;
+ static const char * const biasing[] = {
+ "pull none", "pull down", "pull up", "" };
+ static const char * const enable[] = {
+ "disable", "enable" };
+ static const char * const power_source[] = {
+ "3V3", "1V8" };
+
+ regmap_read(info->regmap_base, offset * 4, &val);
+
+ drive = (val & K230_PC_DS) >> K230_SHIFT_DS;
+ bias = (val & K230_PC_BIAS) >> K230_SHIFT_BIAS;
+ input = (val & K230_PC_IE) >> K230_SHIFT_IE;
+ slew = (val & K230_PC_SL) >> K230_SHIFT_SL;
+ schmitt = (val & K230_PC_ST) >> K230_SHIFT_ST;
+ power = (val & K230_PC_MSC) >> K230_SHIFT_MSC;
+
+ seq_printf(s, "%s - strength %d - %s - %s - slewrate %s - schmitt %s - %s",
+ grp ? grp->name : "unknown",
+ drive,
+ biasing[bias],
+ input ? "input" : "output",
+ enable[slew],
+ enable[schmitt],
+ power_source[power]);
+}
+
+static int k230_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map,
+ unsigned int *num_maps)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct device *dev = info->pctl_dev->dev;
+ const struct k230_pmx_func *func;
+ const struct k230_pin_group *grp;
+ struct pinctrl_map *new_map;
+ int map_num, i, j, idx;
+ unsigned int grp_id;
+
+ func = k230_name_to_funtion(info, np_config->name);
+ if (!func) {
+ dev_err(dev, "function %s not found\n", np_config->name);
+ return -EINVAL;
+ }
+
+ map_num = 0;
+ for (i = 0; i < func->ngroups; ++i) {
+ grp_id = func->group_idx[i];
+ /* npins of config map plus a mux map */
+ map_num += info->groups[grp_id].num_pins + 1;
+ }
+
+ new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+ *map = new_map;
+ *num_maps = map_num;
+
+ idx = 0;
+ for (i = 0; i < func->ngroups; ++i) {
+ grp_id = func->group_idx[i];
+ grp = &info->groups[grp_id];
+ new_map[idx].type = PIN_MAP_TYPE_MUX_GROUP;
+ new_map[idx].data.mux.group = grp->name;
+ new_map[idx].data.mux.function = np_config->name;
+ idx++;
+
+ for (j = 0; j < grp->num_pins; ++j) {
+ new_map[idx].type = PIN_MAP_TYPE_CONFIGS_PIN;
+ new_map[idx].data.configs.group_or_pin =
+ pin_get_name(pctldev, grp->pins[j]);
+ new_map[idx].data.configs.configs =
+ grp->data[j].configs;
+ new_map[idx].data.configs.num_configs =
+ grp->data[j].nconfigs;
+ idx++;
+ }
+ }
+
+ return 0;
+}
+
+static void k230_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned int num_maps)
+{
+ kfree(map);
+}
+
+static const struct pinctrl_ops k230_pctrl_ops = {
+ .get_groups_count = k230_get_groups_count,
+ .get_group_name = k230_get_group_name,
+ .get_group_pins = k230_get_group_pins,
+ .pin_dbg_show = k230_pinctrl_pin_dbg_show,
+ .dt_node_to_map = k230_dt_node_to_map,
+ .dt_free_map = k230_dt_free_map,
+};
+
+static int k230_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *config)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ unsigned int val, arg;
+
+ regmap_read(info->regmap_base, pin * 4, &val);
+
+ switch (param) {
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ arg = (val & K230_PC_ST) ? 1 : 0;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ arg = (val & K230_PC_DS) >> K230_SHIFT_DS;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ arg = (val & K230_PC_BIAS) ? 0 : 1;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ arg = (val & K230_PC_PD) ? 1 : 0;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ arg = (val & K230_PC_PU) ? 1 : 0;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ arg = (val & K230_PC_OE) ? 1 : 0;
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ arg = (val & K230_PC_IE) ? 1 : 0;
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ arg = (val & K230_PC_MSC) ? 1 : 0;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ arg = (val & K230_PC_SL) ? 1 : 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int k230_pinconf_set_param(struct pinctrl_dev *pctldev, unsigned int pin,
+ enum pin_config_param param, unsigned int arg)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int val;
+
+ regmap_read(info->regmap_base, pin * 4, &val);
+
+ switch (param) {
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (arg)
+ val |= K230_PC_ST;
+ else
+ val &= ~K230_PC_ST;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ val &= ~K230_PC_DS;
+ val |= (arg << K230_SHIFT_DS) & K230_PC_DS;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ val &= ~K230_PC_BIAS;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (!arg)
+ return -EINVAL;
+ val |= K230_PC_PD;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (!arg)
+ return -EINVAL;
+ val |= K230_PC_PU;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ if (!arg)
+ return -EINVAL;
+ val |= K230_PC_OE;
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ if (!arg)
+ return -EINVAL;
+ val |= K230_PC_IE;
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ if (arg)
+ val |= K230_PC_MSC;
+ else
+ val &= ~K230_PC_MSC;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ if (arg)
+ val |= K230_PC_SL;
+ else
+ val &= ~K230_PC_SL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_write(info->regmap_base, pin * 4, val);
+
+ return 0;
+}
+
+static int k230_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct device *dev = info->pctl_dev->dev;
+ enum pin_config_param param;
+ unsigned int arg, i;
+ int ret;
+
+ if (pin >= K230_NPINS) {
+ dev_err(dev, "pin number out of range\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+ ret = k230_pinconf_set_param(pctldev, pin, param, arg);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void k230_pconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int pin)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int val;
+
+ regmap_read(info->regmap_base, pin * 4, &val);
+
+ seq_printf(s, " 0x%08x", val);
+}
+
+static const struct pinconf_ops k230_pinconf_ops = {
+ .is_generic = true,
+ .pin_config_get = k230_pinconf_get,
+ .pin_config_set = k230_pinconf_set,
+ .pin_config_dbg_show = k230_pconf_dbg_show,
+};
+
+static int k230_get_functions_count(struct pinctrl_dev *pctldev)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->nfunctions;
+}
+
+static const char *k230_get_fname(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->functions[selector].name;
+}
+
+static int k230_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
+ const char * const **groups, unsigned int *num_groups)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = info->functions[selector].groups;
+ *num_groups = info->functions[selector].ngroups;
+
+ return 0;
+}
+
+static int k230_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
+ unsigned int group)
+{
+ struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ const struct k230_pin_conf *data = info->groups[group].data;
+ struct k230_pin_group *grp = &info->groups[group];
+ const unsigned int *pins = grp->pins;
+ struct regmap *regmap;
+ unsigned int value, mask;
+ int cnt, reg;
+
+ regmap = info->regmap_base;
+
+ for (cnt = 0; cnt < grp->num_pins; cnt++) {
+ reg = pins[cnt] * 4;
+ value = data[cnt].func << K230_SHIFT_SEL;
+ mask = K230_PC_SEL;
+ regmap_update_bits(regmap, reg, mask, value);
+ k230_pins[pins[cnt]].drv_data = grp;
+ }
+
+ return 0;
+}
+
+static const struct pinmux_ops k230_pmxops = {
+ .get_functions_count = k230_get_functions_count,
+ .get_function_name = k230_get_fname,
+ .get_function_groups = k230_get_groups,
+ .set_mux = k230_set_mux,
+ .strict = true,
+};
+
+static int k230_pinctrl_parse_groups(struct device_node *np,
+ struct k230_pin_group *grp,
+ struct k230_pinctrl *info,
+ unsigned int index)
+{
+ struct device *dev = info->pctl_dev->dev;
+ const __be32 *list;
+ int size, i, ret;
+
+ grp->name = np->name;
+
+ list = of_get_property(np, "pinmux", &size);
+ size /= sizeof(*list);
+
+ grp->num_pins = size;
+ grp->pins = devm_kcalloc(dev, grp->num_pins, sizeof(*grp->pins),
+ GFP_KERNEL);
+ grp->data = devm_kcalloc(dev, grp->num_pins, sizeof(*grp->data),
+ GFP_KERNEL);
+ if (!grp->pins || !grp->data)
+ return -ENOMEM;
+
+ for (i = 0; i < size; i++) {
+ unsigned int mux_data = be32_to_cpu(*list++);
+
+ grp->pins[i] = (mux_data >> 8);
+ grp->data[i].func = (mux_data & 0xff);
+
+ ret = pinconf_generic_parse_dt_config(np, NULL,
+ &grp->data[i].configs,
+ &grp->data[i].nconfigs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int k230_pinctrl_parse_functions(struct device_node *np,
+ struct k230_pinctrl *info,
+ unsigned int index)
+{
+ struct device *dev = info->pctl_dev->dev;
+ struct k230_pmx_func *func;
+ struct k230_pin_group *grp;
+ static unsigned int idx, i;
+ int ret;
+
+ func = &info->functions[index];
+
+ func->name = np->name;
+ func->ngroups = of_get_child_count(np);
+ if (func->ngroups <= 0)
+ return 0;
+
+ func->groups = devm_kcalloc(dev, func->ngroups,
+ sizeof(*func->groups), GFP_KERNEL);
+ func->group_idx = devm_kcalloc(dev, func->ngroups,
+ sizeof(*func->group_idx), GFP_KERNEL);
+ if (!func->groups || !func->group_idx)
+ return -ENOMEM;
+
+ i = 0;
+
+ for_each_child_of_node_scoped(np, child) {
+ func->groups[i] = child->name;
+ func->group_idx[i] = idx;
+ grp = &info->groups[idx];
+ idx++;
+ ret = k230_pinctrl_parse_groups(child, grp, info, i++);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void k230_pinctrl_child_count(struct k230_pinctrl *info,
+ struct device_node *np)
+{
+ for_each_child_of_node_scoped(np, child) {
+ info->nfunctions++;
+ info->ngroups += of_get_child_count(child);
+ }
+}
+
+static int k230_pinctrl_parse_dt(struct platform_device *pdev,
+ struct k230_pinctrl *info)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ unsigned int i;
+ int ret;
+
+ k230_pinctrl_child_count(info, np);
+
+ info->functions = devm_kcalloc(dev, info->nfunctions,
+ sizeof(*info->functions), GFP_KERNEL);
+ info->groups = devm_kcalloc(dev, info->ngroups,
+ sizeof(*info->groups), GFP_KERNEL);
+ if (!info->functions || !info->groups)
+ return -ENOMEM;
+
+ i = 0;
+
+ for_each_child_of_node_scoped(np, child) {
+ ret = k230_pinctrl_parse_functions(child, info, i++);
+ if (ret) {
+ dev_err(dev, "failed to parse function\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int k230_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct k230_pinctrl *info;
+ struct pinctrl_desc *pctl;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ pctl = &info->pctl;
+
+ pctl->name = "k230-pinctrl";
+ pctl->owner = THIS_MODULE;
+ pctl->pins = k230_pins;
+ pctl->npins = ARRAY_SIZE(k230_pins);
+ pctl->pctlops = &k230_pctrl_ops;
+ pctl->pmxops = &k230_pmxops;
+ pctl->confops = &k230_pinconf_ops;
+
+ info->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(info->base))
+ return PTR_ERR(info->base);
+
+ info->regmap_base = devm_regmap_init_mmio(dev, info->base,
+ &k230_regmap_config);
+ if (IS_ERR(info->regmap_base))
+ return dev_err_probe(dev, PTR_ERR(info->regmap_base),
+ "failed to init regmap\n");
+
+ info->pctl_dev = devm_pinctrl_register(dev, pctl, info);
+ if (IS_ERR(info->pctl_dev))
+ return dev_err_probe(dev, PTR_ERR(info->pctl_dev),
+ "devm_pinctrl_register failed\n");
+
+ k230_pinctrl_parse_dt(pdev, info);
+
+ return 0;
+}
+
+static const struct of_device_id k230_dt_ids[] = {
+ { .compatible = "canaan,k230-pinctrl", },
+ { /* sintenel */ }
+};
+MODULE_DEVICE_TABLE(of, k230_dt_ids);
+
+static struct platform_driver k230_pinctrl_driver = {
+ .probe = k230_pinctrl_probe,
+ .driver = {
+ .name = "k230-pinctrl",
+ .of_match_table = k230_dt_ids,
+ },
+};
+module_platform_driver(k230_pinctrl_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ze Huang <18771902331@163.com>");
+MODULE_DESCRIPTION("Canaan K230 pinctrl driver");
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index 737d0ae3d0b6..d66c3a3e8429 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -569,7 +569,7 @@ static void mcp23s08_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mcp23s08 *mcp = gpiochip_get_data(gc);
- seq_printf(p, dev_name(mcp->dev));
+ seq_puts(p, dev_name(mcp->dev));
}
static const struct irq_chip mcp23s08_irq_chip = {
diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
index d1ab8450ea93..61532a7a612a 100644
--- a/drivers/pinctrl/pinctrl-ocelot.c
+++ b/drivers/pinctrl/pinctrl-ocelot.c
@@ -57,6 +57,8 @@ enum {
FUNC_CAN1,
FUNC_CLKMON,
FUNC_NONE,
+ FUNC_FAN,
+ FUNC_FC,
FUNC_FC0_a,
FUNC_FC0_b,
FUNC_FC0_c,
@@ -71,6 +73,7 @@ enum {
FUNC_FC4_a,
FUNC_FC4_b,
FUNC_FC4_c,
+ FUNC_FC_SHRD,
FUNC_FC_SHRD0,
FUNC_FC_SHRD1,
FUNC_FC_SHRD2,
@@ -92,6 +95,7 @@ enum {
FUNC_FC_SHRD18,
FUNC_FC_SHRD19,
FUNC_FC_SHRD20,
+ FUNC_FUSA,
FUNC_GPIO,
FUNC_IB_TRG_a,
FUNC_IB_TRG_b,
@@ -108,6 +112,8 @@ enum {
FUNC_IRQ1,
FUNC_IRQ1_IN,
FUNC_IRQ1_OUT,
+ FUNC_IRQ3,
+ FUNC_IRQ4,
FUNC_EXT_IRQ,
FUNC_MIIM,
FUNC_MIIM_a,
@@ -115,12 +121,14 @@ enum {
FUNC_MIIM_c,
FUNC_MIIM_Sa,
FUNC_MIIM_Sb,
+ FUNC_MIIM_IRQ,
FUNC_OB_TRG,
FUNC_OB_TRG_a,
FUNC_OB_TRG_b,
FUNC_PHY_LED,
FUNC_PCI_WAKE,
FUNC_MD,
+ FUNC_PCIE_PERST,
FUNC_PTP0,
FUNC_PTP1,
FUNC_PTP2,
@@ -152,6 +160,7 @@ enum {
FUNC_SGPIO_b,
FUNC_SI,
FUNC_SI2,
+ FUNC_SYNCE,
FUNC_TACHO,
FUNC_TACHO_a,
FUNC_TACHO_b,
@@ -170,6 +179,10 @@ enum {
FUNC_USB_S_a,
FUNC_USB_S_b,
FUNC_USB_S_c,
+ FUNC_USB_POWER,
+ FUNC_USB2PHY_RST,
+ FUNC_USB_OVER_DETECT,
+ FUNC_USB_ULPI,
FUNC_PLL_STAT,
FUNC_EMMC,
FUNC_EMMC_SD,
@@ -184,6 +197,8 @@ static const char *const ocelot_function_names[] = {
[FUNC_CAN1] = "can1",
[FUNC_CLKMON] = "clkmon",
[FUNC_NONE] = "none",
+ [FUNC_FAN] = "fan",
+ [FUNC_FC] = "fc",
[FUNC_FC0_a] = "fc0_a",
[FUNC_FC0_b] = "fc0_b",
[FUNC_FC0_c] = "fc0_c",
@@ -198,6 +213,7 @@ static const char *const ocelot_function_names[] = {
[FUNC_FC4_a] = "fc4_a",
[FUNC_FC4_b] = "fc4_b",
[FUNC_FC4_c] = "fc4_c",
+ [FUNC_FC_SHRD] = "fc_shrd",
[FUNC_FC_SHRD0] = "fc_shrd0",
[FUNC_FC_SHRD1] = "fc_shrd1",
[FUNC_FC_SHRD2] = "fc_shrd2",
@@ -219,6 +235,7 @@ static const char *const ocelot_function_names[] = {
[FUNC_FC_SHRD18] = "fc_shrd18",
[FUNC_FC_SHRD19] = "fc_shrd19",
[FUNC_FC_SHRD20] = "fc_shrd20",
+ [FUNC_FUSA] = "fusa",
[FUNC_GPIO] = "gpio",
[FUNC_IB_TRG_a] = "ib_trig_a",
[FUNC_IB_TRG_b] = "ib_trig_b",
@@ -235,6 +252,8 @@ static const char *const ocelot_function_names[] = {
[FUNC_IRQ1] = "irq1",
[FUNC_IRQ1_IN] = "irq1_in",
[FUNC_IRQ1_OUT] = "irq1_out",
+ [FUNC_IRQ3] = "irq3",
+ [FUNC_IRQ4] = "irq4",
[FUNC_EXT_IRQ] = "ext_irq",
[FUNC_MIIM] = "miim",
[FUNC_MIIM_a] = "miim_a",
@@ -242,8 +261,10 @@ static const char *const ocelot_function_names[] = {
[FUNC_MIIM_c] = "miim_c",
[FUNC_MIIM_Sa] = "miim_slave_a",
[FUNC_MIIM_Sb] = "miim_slave_b",
+ [FUNC_MIIM_IRQ] = "miim_irq",
[FUNC_PHY_LED] = "phy_led",
[FUNC_PCI_WAKE] = "pci_wake",
+ [FUNC_PCIE_PERST] = "pcie_perst",
[FUNC_MD] = "md",
[FUNC_OB_TRG] = "ob_trig",
[FUNC_OB_TRG_a] = "ob_trig_a",
@@ -279,6 +300,7 @@ static const char *const ocelot_function_names[] = {
[FUNC_SGPIO_b] = "sgpio_b",
[FUNC_SI] = "si",
[FUNC_SI2] = "si2",
+ [FUNC_SYNCE] = "synce",
[FUNC_TACHO] = "tacho",
[FUNC_TACHO_a] = "tacho_a",
[FUNC_TACHO_b] = "tacho_b",
@@ -294,6 +316,10 @@ static const char *const ocelot_function_names[] = {
[FUNC_USB_S_a] = "usb_slave_a",
[FUNC_USB_S_b] = "usb_slave_b",
[FUNC_USB_S_c] = "usb_slave_c",
+ [FUNC_USB_POWER] = "usb_power",
+ [FUNC_USB2PHY_RST] = "usb2phy_rst",
+ [FUNC_USB_OVER_DETECT] = "usb_over_detect",
+ [FUNC_USB_ULPI] = "usb_ulpi",
[FUNC_UART] = "uart",
[FUNC_UART2] = "uart2",
[FUNC_UART3] = "uart3",
@@ -1136,6 +1162,165 @@ static const struct pinctrl_pin_desc lan966x_pins[] = {
LAN966X_PIN(77),
};
+#define LAN969X_P(p, f0, f1, f2, f3, f4, f5, f6, f7) \
+static struct ocelot_pin_caps lan969x_pin_##p = { \
+ .pin = p, \
+ .functions = { \
+ FUNC_##f0, FUNC_##f1, FUNC_##f2, \
+ FUNC_##f3 \
+ }, \
+ .a_functions = { \
+ FUNC_##f4, FUNC_##f5, FUNC_##f6, \
+ FUNC_##f7 \
+ }, \
+}
+
+/* Pinmuxing table taken from data sheet */
+/* Pin FUNC0 FUNC1 FUNC2 FUNC3 FUNC4 FUNC5 FUNC6 FUNC7 */
+LAN969X_P(0, GPIO, IRQ0, FC_SHRD, PCIE_PERST, NONE, NONE, NONE, R);
+LAN969X_P(1, GPIO, IRQ1, FC_SHRD, USB_POWER, NONE, NONE, NONE, R);
+LAN969X_P(2, GPIO, FC, NONE, NONE, NONE, NONE, NONE, R);
+LAN969X_P(3, GPIO, FC, NONE, NONE, NONE, NONE, NONE, R);
+LAN969X_P(4, GPIO, FC, NONE, NONE, NONE, NONE, NONE, R);
+LAN969X_P(5, GPIO, SGPIO_a, NONE, CLKMON, NONE, NONE, NONE, R);
+LAN969X_P(6, GPIO, SGPIO_a, NONE, CLKMON, NONE, NONE, NONE, R);
+LAN969X_P(7, GPIO, SGPIO_a, NONE, CLKMON, NONE, NONE, NONE, R);
+LAN969X_P(8, GPIO, SGPIO_a, NONE, CLKMON, NONE, NONE, NONE, R);
+LAN969X_P(9, GPIO, MIIM, MIIM_Sa, CLKMON, NONE, NONE, NONE, R);
+LAN969X_P(10, GPIO, MIIM, MIIM_Sa, CLKMON, NONE, NONE, NONE, R);
+LAN969X_P(11, GPIO, MIIM_IRQ, MIIM_Sa, CLKMON, NONE, NONE, NONE, R);
+LAN969X_P(12, GPIO, IRQ3, FC_SHRD, USB2PHY_RST, NONE, NONE, NONE, R);
+LAN969X_P(13, GPIO, IRQ4, FC_SHRD, USB_OVER_DETECT, NONE, NONE, NONE, R);
+LAN969X_P(14, GPIO, EMMC_SD, QSPI1, FC, NONE, NONE, NONE, R);
+LAN969X_P(15, GPIO, EMMC_SD, QSPI1, FC, NONE, NONE, NONE, R);
+LAN969X_P(16, GPIO, EMMC_SD, QSPI1, FC, NONE, NONE, NONE, R);
+LAN969X_P(17, GPIO, EMMC_SD, QSPI1, PTPSYNC_0, USB_POWER, NONE, NONE, R);
+LAN969X_P(18, GPIO, EMMC_SD, QSPI1, PTPSYNC_1, USB2PHY_RST, NONE, NONE, R);
+LAN969X_P(19, GPIO, EMMC_SD, QSPI1, PTPSYNC_2, USB_OVER_DETECT, NONE, NONE, R);
+LAN969X_P(20, GPIO, EMMC_SD, NONE, FC_SHRD, NONE, NONE, NONE, R);
+LAN969X_P(21, GPIO, EMMC_SD, NONE, FC_SHRD, NONE, NONE, NONE, R);
+LAN969X_P(22, GPIO, EMMC_SD, NONE, FC_SHRD, NONE, NONE, NONE, R);
+LAN969X_P(23, GPIO, EMMC_SD, NONE, FC_SHRD, NONE, NONE, NONE, R);
+LAN969X_P(24, GPIO, EMMC_SD, NONE, NONE, NONE, NONE, NONE, R);
+LAN969X_P(25, GPIO, FAN, FUSA, CAN0_a, QSPI1, NONE, NONE, R);
+LAN969X_P(26, GPIO, FAN, FUSA, CAN0_a, QSPI1, NONE, NONE, R);
+LAN969X_P(27, GPIO, SYNCE, FC, MIIM, QSPI1, NONE, NONE, R);
+LAN969X_P(28, GPIO, SYNCE, FC, MIIM, QSPI1, NONE, NONE, R);
+LAN969X_P(29, GPIO, SYNCE, FC, MIIM_IRQ, QSPI1, NONE, NONE, R);
+LAN969X_P(30, GPIO, PTPSYNC_0, USB_ULPI, FC_SHRD, QSPI1, NONE, NONE, R);
+LAN969X_P(31, GPIO, PTPSYNC_1, USB_ULPI, FC_SHRD, NONE, NONE, NONE, R);
+LAN969X_P(32, GPIO, PTPSYNC_2, USB_ULPI, FC_SHRD, NONE, NONE, NONE, R);
+LAN969X_P(33, GPIO, SD, USB_ULPI, FC_SHRD, NONE, NONE, NONE, R);
+LAN969X_P(34, GPIO, SD, USB_ULPI, CAN1, FC_SHRD, NONE, NONE, R);
+LAN969X_P(35, GPIO, SD, USB_ULPI, CAN1, FC_SHRD, NONE, NONE, R);
+LAN969X_P(36, GPIO, SD, USB_ULPI, PCIE_PERST, FC_SHRD, NONE, NONE, R);
+LAN969X_P(37, GPIO, SD, USB_ULPI, CAN0_b, NONE, NONE, NONE, R);
+LAN969X_P(38, GPIO, SD, USB_ULPI, CAN0_b, NONE, NONE, NONE, R);
+LAN969X_P(39, GPIO, SD, USB_ULPI, MIIM, NONE, NONE, NONE, R);
+LAN969X_P(40, GPIO, SD, USB_ULPI, MIIM, NONE, NONE, NONE, R);
+LAN969X_P(41, GPIO, SD, USB_ULPI, MIIM_IRQ, NONE, NONE, NONE, R);
+LAN969X_P(42, GPIO, PTPSYNC_3, CAN1, NONE, NONE, NONE, NONE, R);
+LAN969X_P(43, GPIO, PTPSYNC_4, CAN1, NONE, NONE, NONE, NONE, R);
+LAN969X_P(44, GPIO, PTPSYNC_5, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(45, GPIO, PTPSYNC_6, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(46, GPIO, PTPSYNC_7, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(47, GPIO, NONE, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(48, GPIO, NONE, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(49, GPIO, NONE, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(50, GPIO, NONE, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(51, GPIO, NONE, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(52, GPIO, FAN, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(53, GPIO, FAN, SFP_SD, NONE, NONE, NONE, NONE, R);
+LAN969X_P(54, GPIO, SYNCE, FC, NONE, NONE, NONE, NONE, R);
+LAN969X_P(55, GPIO, SYNCE, FC, NONE, NONE, NONE, NONE, R);
+LAN969X_P(56, GPIO, SYNCE, FC, NONE, NONE, NONE, NONE, R);
+LAN969X_P(57, GPIO, SFP_SD, FC_SHRD, TWI, PTPSYNC_3, NONE, NONE, R);
+LAN969X_P(58, GPIO, SFP_SD, FC_SHRD, TWI, PTPSYNC_4, NONE, NONE, R);
+LAN969X_P(59, GPIO, SFP_SD, FC_SHRD, TWI, PTPSYNC_5, NONE, NONE, R);
+LAN969X_P(60, GPIO, SFP_SD, FC_SHRD, TWI, PTPSYNC_6, NONE, NONE, R);
+LAN969X_P(61, GPIO, MIIM, FC_SHRD, TWI, NONE, NONE, NONE, R);
+LAN969X_P(62, GPIO, MIIM, FC_SHRD, TWI, NONE, NONE, NONE, R);
+LAN969X_P(63, GPIO, MIIM_IRQ, FC_SHRD, TWI, NONE, NONE, NONE, R);
+LAN969X_P(64, GPIO, FC, FC_SHRD, TWI, NONE, NONE, NONE, R);
+LAN969X_P(65, GPIO, FC, FC_SHRD, TWI, NONE, NONE, NONE, R);
+LAN969X_P(66, GPIO, FC, FC_SHRD, TWI, NONE, NONE, NONE, R);
+
+#define LAN969X_PIN(n) { \
+ .number = n, \
+ .name = "GPIO_"#n, \
+ .drv_data = &lan969x_pin_##n \
+}
+
+static const struct pinctrl_pin_desc lan969x_pins[] = {
+ LAN969X_PIN(0),
+ LAN969X_PIN(1),
+ LAN969X_PIN(2),
+ LAN969X_PIN(3),
+ LAN969X_PIN(4),
+ LAN969X_PIN(5),
+ LAN969X_PIN(6),
+ LAN969X_PIN(7),
+ LAN969X_PIN(8),
+ LAN969X_PIN(9),
+ LAN969X_PIN(10),
+ LAN969X_PIN(11),
+ LAN969X_PIN(12),
+ LAN969X_PIN(13),
+ LAN969X_PIN(14),
+ LAN969X_PIN(15),
+ LAN969X_PIN(16),
+ LAN969X_PIN(17),
+ LAN969X_PIN(18),
+ LAN969X_PIN(19),
+ LAN969X_PIN(20),
+ LAN969X_PIN(21),
+ LAN969X_PIN(22),
+ LAN969X_PIN(23),
+ LAN969X_PIN(24),
+ LAN969X_PIN(25),
+ LAN969X_PIN(26),
+ LAN969X_PIN(27),
+ LAN969X_PIN(28),
+ LAN969X_PIN(29),
+ LAN969X_PIN(30),
+ LAN969X_PIN(31),
+ LAN969X_PIN(32),
+ LAN969X_PIN(33),
+ LAN969X_PIN(34),
+ LAN969X_PIN(35),
+ LAN969X_PIN(36),
+ LAN969X_PIN(37),
+ LAN969X_PIN(38),
+ LAN969X_PIN(39),
+ LAN969X_PIN(40),
+ LAN969X_PIN(41),
+ LAN969X_PIN(42),
+ LAN969X_PIN(43),
+ LAN969X_PIN(44),
+ LAN969X_PIN(45),
+ LAN969X_PIN(46),
+ LAN969X_PIN(47),
+ LAN969X_PIN(48),
+ LAN969X_PIN(49),
+ LAN969X_PIN(50),
+ LAN969X_PIN(51),
+ LAN969X_PIN(52),
+ LAN969X_PIN(53),
+ LAN969X_PIN(54),
+ LAN969X_PIN(55),
+ LAN969X_PIN(56),
+ LAN969X_PIN(57),
+ LAN969X_PIN(58),
+ LAN969X_PIN(59),
+ LAN969X_PIN(60),
+ LAN969X_PIN(61),
+ LAN969X_PIN(62),
+ LAN969X_PIN(63),
+ LAN969X_PIN(64),
+ LAN969X_PIN(65),
+ LAN969X_PIN(66),
+};
+
static int ocelot_get_functions_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(ocelot_function_names);
@@ -1682,6 +1867,23 @@ static struct ocelot_match_data lan966x_desc = {
},
};
+static struct ocelot_match_data lan969x_desc = {
+ .desc = {
+ .name = "lan969x-pinctrl",
+ .pins = lan969x_pins,
+ .npins = ARRAY_SIZE(lan969x_pins),
+ .pctlops = &ocelot_pctl_ops,
+ .pmxops = &lan966x_pmx_ops,
+ .confops = &ocelot_confops,
+ .owner = THIS_MODULE,
+ },
+ .pincfg_data = {
+ .pd_bit = BIT(3),
+ .pu_bit = BIT(2),
+ .drive_bits = GENMASK(1, 0),
+ },
+};
+
static int ocelot_create_group_func_map(struct device *dev,
struct ocelot_pinctrl *info)
{
@@ -2014,6 +2216,7 @@ static const struct of_device_id ocelot_pinctrl_of_match[] = {
{ .compatible = "mscc,servalt-pinctrl", .data = &servalt_desc },
{ .compatible = "microchip,sparx5-pinctrl", .data = &sparx5_desc },
{ .compatible = "microchip,lan966x-pinctrl", .data = &lan966x_desc },
+ { .compatible = "microchip,lan9691-pinctrl", .data = &lan969x_desc },
{},
};
MODULE_DEVICE_TABLE(of, ocelot_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 5c1bc4d5b662..36d4eaf0ebd1 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -3227,7 +3227,9 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np,
/* we do not check return since it's safe node passed down */
size /= sizeof(*list);
if (!size || size % 4)
- return dev_err_probe(dev, -EINVAL, "wrong pins number or pins and configs should be by 4\n");
+ return dev_err_probe(dev, -EINVAL,
+ "%pOF: rockchip,pins: expected one or more of <bank pin mux CONFIG>, got %d args instead\n",
+ np, size);
grp->npins = size / 4;
@@ -4219,7 +4221,7 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
static struct platform_driver rockchip_pinctrl_driver = {
.probe = rockchip_pinctrl_probe,
- .remove_new = rockchip_pinctrl_remove,
+ .remove = rockchip_pinctrl_remove,
.driver = {
.name = "rockchip-pinctrl",
.pm = &rockchip_pinctrl_dev_pm_ops,
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 2ec599e383e4..5be14dc979e2 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1966,6 +1966,7 @@ static const struct pcs_soc_data pinconf_single = {
};
static const struct of_device_id pcs_of_match[] = {
+ { .compatible = "marvell,pxa1908-padconf", .data = &pinconf_single },
{ .compatible = "ti,am437-padconf", .data = &pinctrl_single_am437x },
{ .compatible = "ti,am654-padconf", .data = &pinctrl_single_am654 },
{ .compatible = "ti,dra7-padconf", .data = &pinctrl_single_dra7 },
@@ -1981,7 +1982,7 @@ MODULE_DEVICE_TABLE(of, pcs_of_match);
static struct platform_driver pcs_driver = {
.probe = pcs_probe,
- .remove_new = pcs_remove,
+ .remove = pcs_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = pcs_of_match,
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index d2c5321dd025..521f6fef0b9f 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -599,7 +599,7 @@ static void stmfx_pinctrl_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(d);
struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
- seq_printf(p, dev_name(pctl->dev));
+ seq_puts(p, dev_name(pctl->dev));
}
static const struct irq_chip stmfx_pinctrl_irq_chip = {
@@ -855,7 +855,7 @@ static struct platform_driver stmfx_pinctrl_driver = {
.pm = &stmfx_pinctrl_dev_pm_ops,
},
.probe = stmfx_pinctrl_probe,
- .remove_new = stmfx_pinctrl_remove,
+ .remove = stmfx_pinctrl_remove,
};
module_platform_driver(stmfx_pinctrl_driver);
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index fd0331a87cda..98262b8ce43a 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -584,7 +584,7 @@ static void sx150x_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sx150x_pinctrl *pctl = gpiochip_get_data(gc);
- seq_printf(p, pctl->client->name);
+ seq_puts(p, pctl->client->name);
}
static const struct irq_chip sx150x_irq_chip = {
@@ -1105,7 +1105,7 @@ static const struct regmap_config sx150x_regmap_config = {
.reg_bits = 8,
.val_bits = 32,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_read = sx150x_regmap_reg_read,
.reg_write = sx150x_regmap_reg_write,
diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c
index 4f98f72565f4..d6bb8f58978d 100644
--- a/drivers/pinctrl/pinctrl-tb10x.c
+++ b/drivers/pinctrl/pinctrl-tb10x.c
@@ -820,7 +820,7 @@ MODULE_DEVICE_TABLE(of, tb10x_pinctrl_dt_ids);
static struct platform_driver tb10x_pinctrl_pdrv = {
.probe = tb10x_pinctrl_probe,
- .remove_new = tb10x_pinctrl_remove,
+ .remove = tb10x_pinctrl_remove,
.driver = {
.name = "tb10x_pinctrl",
.of_match_table = of_match_ptr(tb10x_pinctrl_dt_ids),
diff --git a/drivers/pinctrl/pinctrl-th1520.c b/drivers/pinctrl/pinctrl-th1520.c
new file mode 100644
index 000000000000..e641bad6728c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-th1520.c
@@ -0,0 +1,918 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl driver for the T-Head TH1520 SoC
+ *
+ * Copyright (C) 2023 Emil Renner Berthing <emil.renner.berthing@canonical.com>
+ */
+
+#include <linux/array_size.h>
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "core.h"
+#include "pinmux.h"
+#include "pinconf.h"
+
+#define TH1520_PADCFG_IE BIT(9)
+#define TH1520_PADCFG_SL BIT(8)
+#define TH1520_PADCFG_ST BIT(7)
+#define TH1520_PADCFG_SPU BIT(6)
+#define TH1520_PADCFG_PS BIT(5)
+#define TH1520_PADCFG_PE BIT(4)
+#define TH1520_PADCFG_BIAS (TH1520_PADCFG_SPU | TH1520_PADCFG_PS | TH1520_PADCFG_PE)
+#define TH1520_PADCFG_DS GENMASK(3, 0)
+
+#define TH1520_PULL_DOWN_OHM 44000 /* typ. 44kOhm */
+#define TH1520_PULL_UP_OHM 48000 /* typ. 48kOhm */
+#define TH1520_PULL_STRONG_OHM 2100 /* typ. 2.1kOhm */
+
+#define TH1520_PAD_NO_PADCFG BIT(30)
+#define TH1520_PAD_MUXDATA GENMASK(29, 0)
+
+struct th1520_pad_group {
+ const char *name;
+ const struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+};
+
+struct th1520_pinctrl {
+ struct pinctrl_desc desc;
+ struct mutex mutex; /* serialize adding functions */
+ raw_spinlock_t lock; /* serialize register access */
+ void __iomem *base;
+ struct pinctrl_dev *pctl;
+};
+
+static void __iomem *th1520_padcfg(struct th1520_pinctrl *thp,
+ unsigned int pin)
+{
+ return thp->base + 4 * (pin / 2);
+}
+
+static unsigned int th1520_padcfg_shift(unsigned int pin)
+{
+ return 16 * (pin & BIT(0));
+}
+
+static void __iomem *th1520_muxcfg(struct th1520_pinctrl *thp,
+ unsigned int pin)
+{
+ return thp->base + 0x400 + 4 * (pin / 8);
+}
+
+static unsigned int th1520_muxcfg_shift(unsigned int pin)
+{
+ return 4 * (pin & GENMASK(2, 0));
+}
+
+enum th1520_muxtype {
+ TH1520_MUX_____,
+ TH1520_MUX_GPIO,
+ TH1520_MUX_PWM,
+ TH1520_MUX_UART,
+ TH1520_MUX_IR,
+ TH1520_MUX_I2C,
+ TH1520_MUX_SPI,
+ TH1520_MUX_QSPI,
+ TH1520_MUX_SDIO,
+ TH1520_MUX_AUD,
+ TH1520_MUX_I2S,
+ TH1520_MUX_MAC0,
+ TH1520_MUX_MAC1,
+ TH1520_MUX_DPU0,
+ TH1520_MUX_DPU1,
+ TH1520_MUX_ISP,
+ TH1520_MUX_HDMI,
+ TH1520_MUX_BSEL,
+ TH1520_MUX_DBG,
+ TH1520_MUX_CLK,
+ TH1520_MUX_JTAG,
+ TH1520_MUX_ISO,
+ TH1520_MUX_FUSE,
+ TH1520_MUX_RST,
+};
+
+static const char *const th1520_muxtype_string[] = {
+ [TH1520_MUX_GPIO] = "gpio",
+ [TH1520_MUX_PWM] = "pwm",
+ [TH1520_MUX_UART] = "uart",
+ [TH1520_MUX_IR] = "ir",
+ [TH1520_MUX_I2C] = "i2c",
+ [TH1520_MUX_SPI] = "spi",
+ [TH1520_MUX_QSPI] = "qspi",
+ [TH1520_MUX_SDIO] = "sdio",
+ [TH1520_MUX_AUD] = "audio",
+ [TH1520_MUX_I2S] = "i2s",
+ [TH1520_MUX_MAC0] = "gmac0",
+ [TH1520_MUX_MAC1] = "gmac1",
+ [TH1520_MUX_DPU0] = "dpu0",
+ [TH1520_MUX_DPU1] = "dpu1",
+ [TH1520_MUX_ISP] = "isp",
+ [TH1520_MUX_HDMI] = "hdmi",
+ [TH1520_MUX_BSEL] = "bootsel",
+ [TH1520_MUX_DBG] = "debug",
+ [TH1520_MUX_CLK] = "clock",
+ [TH1520_MUX_JTAG] = "jtag",
+ [TH1520_MUX_ISO] = "iso7816",
+ [TH1520_MUX_FUSE] = "efuse",
+ [TH1520_MUX_RST] = "reset",
+};
+
+static enum th1520_muxtype th1520_muxtype_get(const char *str)
+{
+ enum th1520_muxtype mt;
+
+ for (mt = TH1520_MUX_GPIO; mt < ARRAY_SIZE(th1520_muxtype_string); mt++) {
+ if (!strcmp(str, th1520_muxtype_string[mt]))
+ return mt;
+ }
+ return TH1520_MUX_____;
+}
+
+#define TH1520_PAD(_nr, _name, m0, m1, m2, m3, m4, m5, _flags) \
+ { .number = _nr, .name = #_name, .drv_data = (void *)((_flags) | \
+ (TH1520_MUX_##m0 << 0) | (TH1520_MUX_##m1 << 5) | (TH1520_MUX_##m2 << 10) | \
+ (TH1520_MUX_##m3 << 15) | (TH1520_MUX_##m4 << 20) | (TH1520_MUX_##m5 << 25)) }
+
+static unsigned long th1520_pad_muxdata(void *drv_data)
+{
+ return (uintptr_t)drv_data & TH1520_PAD_MUXDATA;
+}
+
+static bool th1520_pad_no_padcfg(void *drv_data)
+{
+ return (uintptr_t)drv_data & TH1520_PAD_NO_PADCFG;
+}
+
+static const struct pinctrl_pin_desc th1520_group1_pins[] = {
+ TH1520_PAD(0, OSC_CLK_IN, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
+ TH1520_PAD(1, OSC_CLK_OUT, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
+ TH1520_PAD(2, SYS_RST_N, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
+ TH1520_PAD(3, RTC_CLK_IN, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
+ TH1520_PAD(4, RTC_CLK_OUT, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
+ /* skip number 5 so we can calculate register offsets and shifts from the pin number */
+ TH1520_PAD(6, TEST_MODE, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
+ TH1520_PAD(7, DEBUG_MODE, DBG, ____, ____, GPIO, ____, ____, TH1520_PAD_NO_PADCFG),
+ TH1520_PAD(8, POR_SEL, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
+ TH1520_PAD(9, I2C_AON_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(10, I2C_AON_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(11, CPU_JTG_TCLK, JTAG, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(12, CPU_JTG_TMS, JTAG, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(13, CPU_JTG_TDI, JTAG, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(14, CPU_JTG_TDO, JTAG, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(15, CPU_JTG_TRST, JTAG, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(16, AOGPIO_7, CLK, AUD, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(17, AOGPIO_8, UART, AUD, IR, GPIO, ____, ____, 0),
+ TH1520_PAD(18, AOGPIO_9, UART, AUD, IR, GPIO, ____, ____, 0),
+ TH1520_PAD(19, AOGPIO_10, CLK, AUD, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(20, AOGPIO_11, GPIO, AUD, ____, ____, ____, ____, 0),
+ TH1520_PAD(21, AOGPIO_12, GPIO, AUD, ____, ____, ____, ____, 0),
+ TH1520_PAD(22, AOGPIO_13, GPIO, AUD, ____, ____, ____, ____, 0),
+ TH1520_PAD(23, AOGPIO_14, GPIO, AUD, ____, ____, ____, ____, 0),
+ TH1520_PAD(24, AOGPIO_15, GPIO, AUD, ____, ____, ____, ____, 0),
+ TH1520_PAD(25, AUDIO_PA0, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(26, AUDIO_PA1, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(27, AUDIO_PA2, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(28, AUDIO_PA3, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(29, AUDIO_PA4, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(30, AUDIO_PA5, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(31, AUDIO_PA6, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(32, AUDIO_PA7, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(33, AUDIO_PA8, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(34, AUDIO_PA9, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(35, AUDIO_PA10, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(36, AUDIO_PA11, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(37, AUDIO_PA12, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(38, AUDIO_PA13, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(39, AUDIO_PA14, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(40, AUDIO_PA15, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(41, AUDIO_PA16, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(42, AUDIO_PA17, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(43, AUDIO_PA27, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(44, AUDIO_PA28, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(45, AUDIO_PA29, AUD, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(46, AUDIO_PA30, AUD, RST, ____, GPIO, ____, ____, 0),
+};
+
+static const struct pinctrl_pin_desc th1520_group2_pins[] = {
+ TH1520_PAD(0, QSPI1_SCLK, QSPI, ISO, ____, GPIO, FUSE, ____, 0),
+ TH1520_PAD(1, QSPI1_CSN0, QSPI, ____, I2C, GPIO, FUSE, ____, 0),
+ TH1520_PAD(2, QSPI1_D0_MOSI, QSPI, ISO, I2C, GPIO, FUSE, ____, 0),
+ TH1520_PAD(3, QSPI1_D1_MISO, QSPI, ISO, ____, GPIO, FUSE, ____, 0),
+ TH1520_PAD(4, QSPI1_D2_WP, QSPI, ISO, UART, GPIO, FUSE, ____, 0),
+ TH1520_PAD(5, QSPI1_D3_HOLD, QSPI, ISO, UART, GPIO, ____, ____, 0),
+ TH1520_PAD(6, I2C0_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(7, I2C0_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(8, I2C1_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(9, I2C1_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(10, UART1_TXD, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(11, UART1_RXD, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(12, UART4_TXD, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(13, UART4_RXD, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(14, UART4_CTSN, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(15, UART4_RTSN, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(16, UART3_TXD, DBG, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(17, UART3_RXD, DBG, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(18, GPIO0_18, GPIO, I2C, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(19, GPIO0_19, GPIO, I2C, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(20, GPIO0_20, GPIO, UART, IR, ____, DPU0, DPU1, 0),
+ TH1520_PAD(21, GPIO0_21, GPIO, UART, IR, ____, DPU0, DPU1, 0),
+ TH1520_PAD(22, GPIO0_22, GPIO, JTAG, I2C, ____, DPU0, DPU1, 0),
+ TH1520_PAD(23, GPIO0_23, GPIO, JTAG, I2C, ____, DPU0, DPU1, 0),
+ TH1520_PAD(24, GPIO0_24, GPIO, JTAG, QSPI, ____, DPU0, DPU1, 0),
+ TH1520_PAD(25, GPIO0_25, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(26, GPIO0_26, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(27, GPIO0_27, GPIO, ____, I2C, ____, DPU0, DPU1, 0),
+ TH1520_PAD(28, GPIO0_28, GPIO, ____, I2C, ____, DPU0, DPU1, 0),
+ TH1520_PAD(29, GPIO0_29, GPIO, ____, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(30, GPIO0_30, GPIO, ____, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(31, GPIO0_31, GPIO, ____, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(32, GPIO1_0, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(33, GPIO1_1, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(34, GPIO1_2, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(35, GPIO1_3, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(36, GPIO1_4, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(37, GPIO1_5, GPIO, ____, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(38, GPIO1_6, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(39, GPIO1_7, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(40, GPIO1_8, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(41, GPIO1_9, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(42, GPIO1_10, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(43, GPIO1_11, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(44, GPIO1_12, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(45, GPIO1_13, GPIO, UART, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(46, GPIO1_14, GPIO, UART, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(47, GPIO1_15, GPIO, UART, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(48, GPIO1_16, GPIO, UART, ____, ____, DPU0, DPU1, 0),
+ TH1520_PAD(49, CLK_OUT_0, BSEL, CLK, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(50, CLK_OUT_1, BSEL, CLK, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(51, CLK_OUT_2, BSEL, CLK, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(52, CLK_OUT_3, BSEL, CLK, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(53, GPIO1_21, JTAG, ____, ISP, GPIO, ____, ____, 0),
+ TH1520_PAD(54, GPIO1_22, JTAG, ____, ISP, GPIO, ____, ____, 0),
+ TH1520_PAD(55, GPIO1_23, JTAG, ____, ISP, GPIO, ____, ____, 0),
+ TH1520_PAD(56, GPIO1_24, JTAG, ____, ISP, GPIO, ____, ____, 0),
+ TH1520_PAD(57, GPIO1_25, JTAG, ____, ISP, GPIO, ____, ____, 0),
+ TH1520_PAD(58, GPIO1_26, GPIO, ____, ISP, ____, ____, ____, 0),
+ TH1520_PAD(59, GPIO1_27, GPIO, ____, ISP, ____, ____, ____, 0),
+ TH1520_PAD(60, GPIO1_28, GPIO, ____, ISP, ____, ____, ____, 0),
+ TH1520_PAD(61, GPIO1_29, GPIO, ____, ISP, ____, ____, ____, 0),
+ TH1520_PAD(62, GPIO1_30, GPIO, ____, ISP, ____, ____, ____, 0),
+};
+
+static const struct pinctrl_pin_desc th1520_group3_pins[] = {
+ TH1520_PAD(0, UART0_TXD, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(1, UART0_RXD, UART, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(2, QSPI0_SCLK, QSPI, PWM, I2S, GPIO, ____, ____, 0),
+ TH1520_PAD(3, QSPI0_CSN0, QSPI, PWM, I2S, GPIO, ____, ____, 0),
+ TH1520_PAD(4, QSPI0_CSN1, QSPI, PWM, I2S, GPIO, ____, ____, 0),
+ TH1520_PAD(5, QSPI0_D0_MOSI, QSPI, PWM, I2S, GPIO, ____, ____, 0),
+ TH1520_PAD(6, QSPI0_D1_MISO, QSPI, PWM, I2S, GPIO, ____, ____, 0),
+ TH1520_PAD(7, QSPI0_D2_WP, QSPI, PWM, I2S, GPIO, ____, ____, 0),
+ TH1520_PAD(8, QSPI1_D3_HOLD, QSPI, ____, I2S, GPIO, ____, ____, 0),
+ TH1520_PAD(9, I2C2_SCL, I2C, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(10, I2C2_SDA, I2C, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(11, I2C3_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(12, I2C3_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(13, GPIO2_13, GPIO, SPI, ____, ____, ____, ____, 0),
+ TH1520_PAD(14, SPI_SCLK, SPI, UART, IR, GPIO, ____, ____, 0),
+ TH1520_PAD(15, SPI_CSN, SPI, UART, IR, GPIO, ____, ____, 0),
+ TH1520_PAD(16, SPI_MOSI, SPI, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(17, SPI_MISO, SPI, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(18, GPIO2_18, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(19, GPIO2_19, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(20, GPIO2_20, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(21, GPIO2_21, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(22, GPIO2_22, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(23, GPIO2_23, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(24, GPIO2_24, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(25, GPIO2_25, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(26, SDIO0_WPRTN, SDIO, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(27, SDIO0_DETN, SDIO, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(28, SDIO1_WPRTN, SDIO, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(29, SDIO1_DETN, SDIO, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(30, GPIO2_30, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(31, GPIO2_31, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(32, GPIO3_0, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(33, GPIO3_1, GPIO, MAC1, ____, ____, ____, ____, 0),
+ TH1520_PAD(34, GPIO3_2, GPIO, PWM, ____, ____, ____, ____, 0),
+ TH1520_PAD(35, GPIO3_3, GPIO, PWM, ____, ____, ____, ____, 0),
+ TH1520_PAD(36, HDMI_SCL, HDMI, PWM, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(37, HDMI_SDA, HDMI, PWM, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(38, HDMI_CEC, HDMI, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(39, GMAC0_TX_CLK, MAC0, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(40, GMAC0_RX_CLK, MAC0, ____, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(41, GMAC0_TXEN, MAC0, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(42, GMAC0_TXD0, MAC0, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(43, GMAC0_TXD1, MAC0, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(44, GMAC0_TXD2, MAC0, UART, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(45, GMAC0_TXD3, MAC0, I2C, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(46, GMAC0_RXDV, MAC0, I2C, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(47, GMAC0_RXD0, MAC0, I2C, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(48, GMAC0_RXD1, MAC0, I2C, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(49, GMAC0_RXD2, MAC0, SPI, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(50, GMAC0_RXD3, MAC0, SPI, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(51, GMAC0_MDC, MAC0, SPI, MAC1, GPIO, ____, ____, 0),
+ TH1520_PAD(52, GMAC0_MDIO, MAC0, SPI, MAC1, GPIO, ____, ____, 0),
+ TH1520_PAD(53, GMAC0_COL, MAC0, PWM, ____, GPIO, ____, ____, 0),
+ TH1520_PAD(54, GMAC0_CRS, MAC0, PWM, ____, GPIO, ____, ____, 0),
+};
+
+static const struct th1520_pad_group th1520_group1 = {
+ .name = "th1520-group1",
+ .pins = th1520_group1_pins,
+ .npins = ARRAY_SIZE(th1520_group1_pins),
+};
+
+static const struct th1520_pad_group th1520_group2 = {
+ .name = "th1520-group2",
+ .pins = th1520_group2_pins,
+ .npins = ARRAY_SIZE(th1520_group2_pins),
+};
+
+static const struct th1520_pad_group th1520_group3 = {
+ .name = "th1520-group3",
+ .pins = th1520_group3_pins,
+ .npins = ARRAY_SIZE(th1520_group3_pins),
+};
+
+static int th1520_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+
+ return thp->desc.npins;
+}
+
+static const char *th1520_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned int gsel)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+
+ return thp->desc.pins[gsel].name;
+}
+
+static int th1520_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int gsel,
+ const unsigned int **pins,
+ unsigned int *npins)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = &thp->desc.pins[gsel].number;
+ *npins = 1;
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void th1520_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int pin)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ void __iomem *padcfg = th1520_padcfg(thp, pin);
+ void __iomem *muxcfg = th1520_muxcfg(thp, pin);
+ u32 pad;
+ u32 mux;
+
+ scoped_guard(raw_spinlock_irqsave, &thp->lock) {
+ pad = readl_relaxed(padcfg);
+ mux = readl_relaxed(muxcfg);
+ }
+
+ seq_printf(s, "[PADCFG_%03u:0x%x=0x%07x MUXCFG_%03u:0x%x=0x%08x]",
+ 1 + pin / 2, 0x000 + 4 * (pin / 2), pad,
+ 1 + pin / 8, 0x400 + 4 * (pin / 8), mux);
+}
+#else
+#define th1520_pin_dbg_show NULL
+#endif
+
+static void th1520_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned int nmaps)
+{
+ unsigned long *seen = NULL;
+ unsigned int i;
+
+ for (i = 0; i < nmaps; i++) {
+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN &&
+ map[i].data.configs.configs != seen) {
+ seen = map[i].data.configs.configs;
+ kfree(seen);
+ }
+ }
+
+ kfree(map);
+}
+
+static int th1520_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ struct pinctrl_map *map;
+ unsigned long *configs;
+ unsigned int nconfigs;
+ unsigned int nmaps;
+ int ret;
+
+ nmaps = 0;
+ for_each_available_child_of_node_scoped(np, child) {
+ int npins = of_property_count_strings(child, "pins");
+
+ if (npins <= 0) {
+ dev_err(thp->pctl->dev, "no pins selected for %pOFn.%pOFn\n",
+ np, child);
+ return -EINVAL;
+ }
+ nmaps += npins;
+ if (of_property_present(child, "function"))
+ nmaps += npins;
+ }
+
+ map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ nmaps = 0;
+ guard(mutex)(&thp->mutex);
+ for_each_available_child_of_node_scoped(np, child) {
+ unsigned int rollback = nmaps;
+ enum th1520_muxtype muxtype;
+ struct property *prop;
+ const char *funcname;
+ const char **pgnames;
+ const char *pinname;
+ int npins;
+
+ ret = pinconf_generic_parse_dt_config(child, pctldev, &configs, &nconfigs);
+ if (ret) {
+ dev_err(thp->pctl->dev, "%pOFn.%pOFn: error parsing pin config\n",
+ np, child);
+ goto free_map;
+ }
+
+ if (!of_property_read_string(child, "function", &funcname)) {
+ muxtype = th1520_muxtype_get(funcname);
+ if (!muxtype) {
+ dev_err(thp->pctl->dev, "%pOFn.%pOFn: unknown function '%s'\n",
+ np, child, funcname);
+ ret = -EINVAL;
+ goto free_configs;
+ }
+
+ funcname = devm_kasprintf(thp->pctl->dev, GFP_KERNEL, "%pOFn.%pOFn",
+ np, child);
+ if (!funcname) {
+ ret = -ENOMEM;
+ goto free_configs;
+ }
+
+ npins = of_property_count_strings(child, "pins");
+ pgnames = devm_kcalloc(thp->pctl->dev, npins, sizeof(*pgnames), GFP_KERNEL);
+ if (!pgnames) {
+ ret = -ENOMEM;
+ goto free_configs;
+ }
+ } else {
+ funcname = NULL;
+ }
+
+ npins = 0;
+ of_property_for_each_string(child, "pins", prop, pinname) {
+ unsigned int i;
+
+ for (i = 0; i < thp->desc.npins; i++) {
+ if (!strcmp(pinname, thp->desc.pins[i].name))
+ break;
+ }
+ if (i == thp->desc.npins) {
+ nmaps = rollback;
+ dev_err(thp->pctl->dev, "%pOFn.%pOFn: unknown pin '%s'\n",
+ np, child, pinname);
+ ret = -EINVAL;
+ goto free_configs;
+ }
+
+ if (nconfigs) {
+ map[nmaps].type = PIN_MAP_TYPE_CONFIGS_PIN;
+ map[nmaps].data.configs.group_or_pin = thp->desc.pins[i].name;
+ map[nmaps].data.configs.configs = configs;
+ map[nmaps].data.configs.num_configs = nconfigs;
+ nmaps += 1;
+ }
+ if (funcname) {
+ pgnames[npins++] = thp->desc.pins[i].name;
+ map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+ map[nmaps].data.mux.function = funcname;
+ map[nmaps].data.mux.group = thp->desc.pins[i].name;
+ nmaps += 1;
+ }
+ }
+
+ if (funcname) {
+ ret = pinmux_generic_add_function(pctldev, funcname, pgnames,
+ npins, (void *)muxtype);
+ if (ret < 0) {
+ dev_err(thp->pctl->dev, "error adding function %s\n", funcname);
+ goto free_map;
+ }
+ }
+ }
+
+ *maps = map;
+ *num_maps = nmaps;
+ return 0;
+
+free_configs:
+ kfree(configs);
+free_map:
+ th1520_pinctrl_dt_free_map(pctldev, map, nmaps);
+ return ret;
+}
+
+static const struct pinctrl_ops th1520_pinctrl_ops = {
+ .get_groups_count = th1520_pinctrl_get_groups_count,
+ .get_group_name = th1520_pinctrl_get_group_name,
+ .get_group_pins = th1520_pinctrl_get_group_pins,
+ .pin_dbg_show = th1520_pin_dbg_show,
+ .dt_node_to_map = th1520_pinctrl_dt_node_to_map,
+ .dt_free_map = th1520_pinctrl_dt_free_map,
+};
+
+static const u8 th1520_drive_strength_in_ma[16] = {
+ 1, 2, 3, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25,
+};
+
+static u16 th1520_drive_strength_from_ma(u32 arg)
+{
+ u16 ds;
+
+ for (ds = 0; ds < TH1520_PADCFG_DS; ds++) {
+ if (arg <= th1520_drive_strength_in_ma[ds])
+ return ds;
+ }
+ return TH1520_PADCFG_DS;
+}
+
+static int th1520_padcfg_rmw(struct th1520_pinctrl *thp, unsigned int pin,
+ u32 mask, u32 value)
+{
+ void __iomem *padcfg = th1520_padcfg(thp, pin);
+ unsigned int shift = th1520_padcfg_shift(pin);
+ u32 tmp;
+
+ mask <<= shift;
+ value <<= shift;
+
+ scoped_guard(raw_spinlock_irqsave, &thp->lock) {
+ tmp = readl_relaxed(padcfg);
+ tmp = (tmp & ~mask) | value;
+ writel_relaxed(tmp, padcfg);
+ }
+ return 0;
+}
+
+static int th1520_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+ bool enabled;
+ int param;
+ u32 value;
+ u32 arg;
+
+ if (th1520_pad_no_padcfg(desc->drv_data))
+ return -ENOTSUPP;
+
+ value = readl_relaxed(th1520_padcfg(thp, pin));
+ value = (value >> th1520_padcfg_shift(pin)) & GENMASK(9, 0);
+
+ param = pinconf_to_config_param(*config);
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ enabled = !(value & (TH1520_PADCFG_SPU | TH1520_PADCFG_PE));
+ arg = 0;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ enabled = (value & TH1520_PADCFG_BIAS) == TH1520_PADCFG_PE;
+ arg = enabled ? TH1520_PULL_DOWN_OHM : 0;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (value & TH1520_PADCFG_SPU) {
+ enabled = true;
+ arg = TH1520_PULL_STRONG_OHM;
+ } else if ((value & (TH1520_PADCFG_PE | TH1520_PADCFG_PS)) ==
+ (TH1520_PADCFG_PE | TH1520_PADCFG_PS)) {
+ enabled = true;
+ arg = TH1520_PULL_UP_OHM;
+ } else {
+ enabled = false;
+ arg = 0;
+ }
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ enabled = true;
+ arg = th1520_drive_strength_in_ma[value & TH1520_PADCFG_DS];
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ enabled = value & TH1520_PADCFG_IE;
+ arg = enabled ? 1 : 0;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ enabled = value & TH1520_PADCFG_ST;
+ arg = enabled ? 1 : 0;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ enabled = value & TH1520_PADCFG_SL;
+ arg = enabled ? 1 : 0;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+ return enabled ? 0 : -EINVAL;
+}
+
+static int th1520_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned int gsel, unsigned long *config)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int pin = thp->desc.pins[gsel].number;
+
+ return th1520_pinconf_get(pctldev, pin, config);
+}
+
+static int th1520_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+ unsigned int i;
+ u16 mask, value;
+
+ if (th1520_pad_no_padcfg(desc->drv_data))
+ return -ENOTSUPP;
+
+ mask = 0;
+ value = 0;
+ for (i = 0; i < num_configs; i++) {
+ int param = pinconf_to_config_param(configs[i]);
+ u32 arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ mask |= TH1520_PADCFG_BIAS;
+ value &= ~TH1520_PADCFG_BIAS;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ if (arg == 0)
+ return -ENOTSUPP;
+ mask |= TH1520_PADCFG_BIAS;
+ value &= ~TH1520_PADCFG_BIAS;
+ value |= TH1520_PADCFG_PE;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (arg == 0)
+ return -ENOTSUPP;
+ mask |= TH1520_PADCFG_BIAS;
+ value &= ~TH1520_PADCFG_BIAS;
+ if (arg == TH1520_PULL_STRONG_OHM)
+ value |= TH1520_PADCFG_SPU;
+ else
+ value |= TH1520_PADCFG_PE | TH1520_PADCFG_PS;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ mask |= TH1520_PADCFG_DS;
+ value &= ~TH1520_PADCFG_DS;
+ value |= th1520_drive_strength_from_ma(arg);
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ mask |= TH1520_PADCFG_IE;
+ if (arg)
+ value |= TH1520_PADCFG_IE;
+ else
+ value &= ~TH1520_PADCFG_IE;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ mask |= TH1520_PADCFG_ST;
+ if (arg)
+ value |= TH1520_PADCFG_ST;
+ else
+ value &= ~TH1520_PADCFG_ST;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ mask |= TH1520_PADCFG_SL;
+ if (arg)
+ value |= TH1520_PADCFG_SL;
+ else
+ value &= ~TH1520_PADCFG_SL;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ }
+
+ return th1520_padcfg_rmw(thp, pin, mask, value);
+}
+
+static int th1520_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int gsel,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int pin = thp->desc.pins[gsel].number;
+
+ return th1520_pinconf_set(pctldev, pin, configs, num_configs);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void th1520_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned int pin)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ u32 value = readl_relaxed(th1520_padcfg(thp, pin));
+
+ value = (value >> th1520_padcfg_shift(pin)) & GENMASK(9, 0);
+
+ seq_printf(s, " [0x%03x]", value);
+}
+#else
+#define th1520_pinconf_dbg_show NULL
+#endif
+
+static const struct pinconf_ops th1520_pinconf_ops = {
+ .pin_config_get = th1520_pinconf_get,
+ .pin_config_group_get = th1520_pinconf_group_get,
+ .pin_config_set = th1520_pinconf_set,
+ .pin_config_group_set = th1520_pinconf_group_set,
+ .pin_config_dbg_show = th1520_pinconf_dbg_show,
+ .is_generic = true,
+};
+
+static int th1520_pinmux_set(struct th1520_pinctrl *thp, unsigned int pin,
+ unsigned long muxdata, enum th1520_muxtype muxtype)
+{
+ void __iomem *muxcfg = th1520_muxcfg(thp, pin);
+ unsigned int shift = th1520_muxcfg_shift(pin);
+ u32 mask, value, tmp;
+
+ for (value = 0; muxdata; muxdata >>= 5, value++) {
+ if ((muxdata & GENMASK(4, 0)) == muxtype)
+ break;
+ }
+ if (!muxdata) {
+ dev_err(thp->pctl->dev, "invalid mux %s for pin %s\n",
+ th1520_muxtype_string[muxtype], pin_get_name(thp->pctl, pin));
+ return -EINVAL;
+ }
+
+ mask = GENMASK(3, 0) << shift;
+ value = value << shift;
+
+ scoped_guard(raw_spinlock_irqsave, &thp->lock) {
+ tmp = readl_relaxed(muxcfg);
+ tmp = (tmp & ~mask) | value;
+ writel_relaxed(tmp, muxcfg);
+ }
+ return 0;
+}
+
+static int th1520_pinmux_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int fsel, unsigned int gsel)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ const struct function_desc *func = pinmux_generic_get_function(pctldev, fsel);
+ enum th1520_muxtype muxtype;
+
+ if (!func)
+ return -EINVAL;
+
+ muxtype = (uintptr_t)func->data;
+ return th1520_pinmux_set(thp, thp->desc.pins[gsel].number,
+ th1520_pad_muxdata(thp->desc.pins[gsel].drv_data),
+ muxtype);
+}
+
+static int th1520_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+ const struct pin_desc *desc = pin_desc_get(pctldev, offset);
+
+ return th1520_pinmux_set(thp, offset,
+ th1520_pad_muxdata(desc->drv_data),
+ TH1520_MUX_GPIO);
+}
+
+static int th1520_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset, bool input)
+{
+ struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev);
+
+ return th1520_padcfg_rmw(thp, offset, TH1520_PADCFG_IE,
+ input ? TH1520_PADCFG_IE : 0);
+}
+
+static const struct pinmux_ops th1520_pinmux_ops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = th1520_pinmux_set_mux,
+ .gpio_request_enable = th1520_gpio_request_enable,
+ .gpio_set_direction = th1520_gpio_set_direction,
+ .strict = true,
+};
+
+static int th1520_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct th1520_pad_group *group;
+ struct device_node *np = dev->of_node;
+ struct th1520_pinctrl *thp;
+ struct clk *clk;
+ u32 pin_group;
+ int ret;
+
+ thp = devm_kzalloc(dev, sizeof(*thp), GFP_KERNEL);
+ if (!thp)
+ return -ENOMEM;
+
+ thp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(thp->base))
+ return PTR_ERR(thp->base);
+
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk), "error getting clock\n");
+
+ ret = of_property_read_u32(np, "thead,pad-group", &pin_group);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to read the thead,pad-group property\n");
+
+ if (pin_group == 1)
+ group = &th1520_group1;
+ else if (pin_group == 2)
+ group = &th1520_group2;
+ else if (pin_group == 3)
+ group = &th1520_group3;
+ else
+ return dev_err_probe(dev, -EINVAL, "unit address did not match any pad group\n");
+
+ thp->desc.name = group->name;
+ thp->desc.pins = group->pins;
+ thp->desc.npins = group->npins;
+ thp->desc.pctlops = &th1520_pinctrl_ops;
+ thp->desc.pmxops = &th1520_pinmux_ops;
+ thp->desc.confops = &th1520_pinconf_ops;
+ thp->desc.owner = THIS_MODULE;
+ mutex_init(&thp->mutex);
+ raw_spin_lock_init(&thp->lock);
+
+ ret = devm_pinctrl_register_and_init(dev, &thp->desc, thp, &thp->pctl);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not register pinctrl driver\n");
+
+ return pinctrl_enable(thp->pctl);
+}
+
+static const struct of_device_id th1520_pinctrl_of_match[] = {
+ { .compatible = "thead,th1520-pinctrl"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, th1520_pinctrl_of_match);
+
+static struct platform_driver th1520_pinctrl_driver = {
+ .probe = th1520_pinctrl_probe,
+ .driver = {
+ .name = "pinctrl-th1520",
+ .of_match_table = th1520_pinctrl_of_match,
+ },
+};
+module_platform_driver(th1520_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for the T-Head TH1520 SoC");
+MODULE_AUTHOR("Emil Renner Berthing <emil.renner.berthing@canonical.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index f4256a918165..48f8aabf3bfa 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -1524,7 +1524,7 @@ static int pinmux_xway_probe(struct platform_device *pdev)
* files which don't set the "gpio-ranges" property or systems that
* utilize ACPI the driver has to call gpiochip_add_pin_range().
*/
- if (!of_property_read_bool(pdev->dev.of_node, "gpio-ranges")) {
+ if (!of_property_present(pdev->dev.of_node, "gpio-ranges")) {
/* finish with registering the gpio range in pinctrl */
xway_gpio_range.npins = xway_chip.ngpio;
xway_gpio_range.base = xway_chip.base;
diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
index 3c6d56fdb8c9..fddf0fef4b13 100644
--- a/drivers/pinctrl/pinctrl-zynqmp.c
+++ b/drivers/pinctrl/pinctrl-zynqmp.c
@@ -10,6 +10,7 @@
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -44,12 +45,17 @@
#define DRIVE_STRENGTH_8MA 8
#define DRIVE_STRENGTH_12MA 12
+#define VERSAL_LPD_PIN_PREFIX "LPD_MIO"
+#define VERSAL_PMC_PIN_PREFIX "PMC_MIO"
+
+#define VERSAL_PINCTRL_ATTR_NODETYPE_MASK GENMASK(19, 14)
+#define VERSAL_PINCTRL_NODETYPE_LPD_MIO BIT(0)
+
/**
* struct zynqmp_pmux_function - a pinmux function
* @name: Name of the pin mux function
* @groups: List of pin groups for this function
* @ngroups: Number of entries in @groups
- * @node: Firmware node matching with the function
*
* This structure holds information about pin control function
* and function group names supporting that function.
@@ -93,6 +99,8 @@ struct zynqmp_pctrl_group {
};
static struct pinctrl_desc zynqmp_desc;
+static u32 family_code;
+static u32 sub_family_code;
static int zynqmp_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
@@ -596,8 +604,12 @@ static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid,
if (!groups[resp[i]].name)
return -ENOMEM;
- for (pin = 0; pin < groups[resp[i]].npins; pin++)
- __set_bit(groups[resp[i]].pins[pin], used_pins);
+ for (pin = 0; pin < groups[resp[i]].npins; pin++) {
+ if (family_code == ZYNQMP_FAMILY_CODE)
+ __set_bit(groups[resp[i]].pins[pin], used_pins);
+ else
+ __set_bit((u8)groups[resp[i]].pins[pin] - 1, used_pins);
+ }
}
}
done:
@@ -873,6 +885,70 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev,
return 0;
}
+static int versal_pinctrl_get_attributes(u32 pin_idx, u32 *response)
+{
+ struct zynqmp_pm_query_data qdata = {0};
+ u32 payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ qdata.qid = PM_QID_PINCTRL_GET_ATTRIBUTES;
+ qdata.arg1 = pin_idx;
+
+ ret = zynqmp_pm_query_data(qdata, payload);
+ if (ret)
+ return ret;
+
+ memcpy(response, &payload[1], sizeof(*response));
+
+ return 0;
+}
+
+static int versal_pinctrl_prepare_pin_desc(struct device *dev,
+ const struct pinctrl_pin_desc **zynqmp_pins,
+ unsigned int *npins)
+{
+ u32 lpd_mio_pins = 0, attr, nodetype;
+ struct pinctrl_pin_desc *pins, *pin;
+ int ret, i;
+
+ ret = zynqmp_pm_is_function_supported(PM_QUERY_DATA, PM_QID_PINCTRL_GET_ATTRIBUTES);
+ if (ret)
+ return ret;
+
+ ret = zynqmp_pinctrl_get_num_pins(npins);
+ if (ret)
+ return ret;
+
+ pins = devm_kzalloc(dev, sizeof(*pins) * *npins, GFP_KERNEL);
+ if (!pins)
+ return -ENOMEM;
+
+ for (i = 0; i < *npins; i++) {
+ ret = versal_pinctrl_get_attributes(i, &attr);
+ if (ret)
+ return ret;
+
+ pin = &pins[i];
+ pin->number = attr;
+ nodetype = FIELD_GET(VERSAL_PINCTRL_ATTR_NODETYPE_MASK, attr);
+ if (nodetype == VERSAL_PINCTRL_NODETYPE_LPD_MIO) {
+ pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
+ VERSAL_LPD_PIN_PREFIX, i);
+ lpd_mio_pins++;
+ } else {
+ pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
+ VERSAL_PMC_PIN_PREFIX, i - lpd_mio_pins);
+ }
+
+ if (!pin->name)
+ return -ENOMEM;
+ }
+
+ *zynqmp_pins = pins;
+
+ return 0;
+}
+
static int zynqmp_pinctrl_probe(struct platform_device *pdev)
{
struct zynqmp_pinctrl *pctrl;
@@ -882,9 +958,18 @@ static int zynqmp_pinctrl_probe(struct platform_device *pdev)
if (!pctrl)
return -ENOMEM;
- ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev,
- &zynqmp_desc.pins,
- &zynqmp_desc.npins);
+ ret = zynqmp_pm_get_family_info(&family_code, &sub_family_code);
+ if (ret < 0)
+ return ret;
+
+ if (family_code == ZYNQMP_FAMILY_CODE) {
+ ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev, &zynqmp_desc.pins,
+ &zynqmp_desc.npins);
+ } else {
+ ret = versal_pinctrl_prepare_pin_desc(&pdev->dev, &zynqmp_desc.pins,
+ &zynqmp_desc.npins);
+ }
+
if (ret) {
dev_err(&pdev->dev, "pin desc prepare fail with %d\n", ret);
return ret;
@@ -907,6 +992,7 @@ static int zynqmp_pinctrl_probe(struct platform_device *pdev)
static const struct of_device_id zynqmp_pinctrl_of_match[] = {
{ .compatible = "xlnx,zynqmp-pinctrl" },
+ { .compatible = "xlnx,versal-pinctrl" },
{ }
};
MODULE_DEVICE_TABLE(of, zynqmp_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 02033ea1c643..0743190da59e 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -14,6 +14,7 @@
#include <linux/array_size.h>
#include <linux/ctype.h>
+#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/err.h>
@@ -93,6 +94,7 @@ bool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned int pin)
if (!desc || !ops)
return true;
+ guard(mutex)(&desc->mux_lock);
if (ops->strict && desc->mux_usecount)
return false;
@@ -127,29 +129,31 @@ static int pin_request(struct pinctrl_dev *pctldev,
dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
pin, desc->name, owner);
- if ((!gpio_range || ops->strict) &&
- desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
- dev_err(pctldev->dev,
- "pin %s already requested by %s; cannot claim for %s\n",
- desc->name, desc->mux_owner, owner);
- goto out;
- }
+ scoped_guard(mutex, &desc->mux_lock) {
+ if ((!gpio_range || ops->strict) &&
+ desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
+ dev_err(pctldev->dev,
+ "pin %s already requested by %s; cannot claim for %s\n",
+ desc->name, desc->mux_owner, owner);
+ goto out;
+ }
- if ((gpio_range || ops->strict) && desc->gpio_owner) {
- dev_err(pctldev->dev,
- "pin %s already requested by %s; cannot claim for %s\n",
- desc->name, desc->gpio_owner, owner);
- goto out;
- }
+ if ((gpio_range || ops->strict) && desc->gpio_owner) {
+ dev_err(pctldev->dev,
+ "pin %s already requested by %s; cannot claim for %s\n",
+ desc->name, desc->gpio_owner, owner);
+ goto out;
+ }
- if (gpio_range) {
- desc->gpio_owner = owner;
- } else {
- desc->mux_usecount++;
- if (desc->mux_usecount > 1)
- return 0;
+ if (gpio_range) {
+ desc->gpio_owner = owner;
+ } else {
+ desc->mux_usecount++;
+ if (desc->mux_usecount > 1)
+ return 0;
- desc->mux_owner = owner;
+ desc->mux_owner = owner;
+ }
}
/* Let each pin increase references to this module */
@@ -178,12 +182,14 @@ static int pin_request(struct pinctrl_dev *pctldev,
out_free_pin:
if (status) {
- if (gpio_range) {
- desc->gpio_owner = NULL;
- } else {
- desc->mux_usecount--;
- if (!desc->mux_usecount)
- desc->mux_owner = NULL;
+ scoped_guard(mutex, &desc->mux_lock) {
+ if (gpio_range) {
+ desc->gpio_owner = NULL;
+ } else {
+ desc->mux_usecount--;
+ if (!desc->mux_usecount)
+ desc->mux_owner = NULL;
+ }
}
}
out:
@@ -219,15 +225,17 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
return NULL;
}
- if (!gpio_range) {
- /*
- * A pin should not be freed more times than allocated.
- */
- if (WARN_ON(!desc->mux_usecount))
- return NULL;
- desc->mux_usecount--;
- if (desc->mux_usecount)
- return NULL;
+ scoped_guard(mutex, &desc->mux_lock) {
+ if (!gpio_range) {
+ /*
+ * A pin should not be freed more times than allocated.
+ */
+ if (WARN_ON(!desc->mux_usecount))
+ return NULL;
+ desc->mux_usecount--;
+ if (desc->mux_usecount)
+ return NULL;
+ }
}
/*
@@ -239,13 +247,15 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
else if (ops->free)
ops->free(pctldev, pin);
- if (gpio_range) {
- owner = desc->gpio_owner;
- desc->gpio_owner = NULL;
- } else {
- owner = desc->mux_owner;
- desc->mux_owner = NULL;
- desc->mux_setting = NULL;
+ scoped_guard(mutex, &desc->mux_lock) {
+ if (gpio_range) {
+ owner = desc->gpio_owner;
+ desc->gpio_owner = NULL;
+ } else {
+ owner = desc->mux_owner;
+ desc->mux_owner = NULL;
+ desc->mux_setting = NULL;
+ }
}
module_put(pctldev->owner);
@@ -458,7 +468,8 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting)
pins[i]);
continue;
}
- desc->mux_setting = &(setting->data.mux);
+ scoped_guard(mutex, &desc->mux_lock)
+ desc->mux_setting = &(setting->data.mux);
}
ret = ops->set_mux(pctldev, setting->data.mux.func,
@@ -472,8 +483,10 @@ int pinmux_enable_setting(const struct pinctrl_setting *setting)
err_set_mux:
for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]);
- if (desc)
- desc->mux_setting = NULL;
+ if (desc) {
+ scoped_guard(mutex, &desc->mux_lock)
+ desc->mux_setting = NULL;
+ }
}
err_pin_request:
/* On error release all taken pins */
@@ -492,6 +505,7 @@ void pinmux_disable_setting(const struct pinctrl_setting *setting)
unsigned int num_pins = 0;
int i;
struct pin_desc *desc;
+ bool is_equal;
if (pctlops->get_group_pins)
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
@@ -517,7 +531,10 @@ void pinmux_disable_setting(const struct pinctrl_setting *setting)
pins[i]);
continue;
}
- if (desc->mux_setting == &(setting->data.mux)) {
+ scoped_guard(mutex, &desc->mux_lock)
+ is_equal = (desc->mux_setting == &(setting->data.mux));
+
+ if (is_equal) {
pin_free(pctldev, pins[i], NULL);
} else {
const char *gname;
@@ -608,40 +625,42 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
if (desc == NULL)
continue;
- if (desc->mux_owner &&
- !strcmp(desc->mux_owner, pinctrl_dev_get_name(pctldev)))
- is_hog = true;
-
- if (pmxops->strict) {
- if (desc->mux_owner)
- seq_printf(s, "pin %d (%s): device %s%s",
- pin, desc->name, desc->mux_owner,
+ scoped_guard(mutex, &desc->mux_lock) {
+ if (desc->mux_owner &&
+ !strcmp(desc->mux_owner, pinctrl_dev_get_name(pctldev)))
+ is_hog = true;
+
+ if (pmxops->strict) {
+ if (desc->mux_owner)
+ seq_printf(s, "pin %d (%s): device %s%s",
+ pin, desc->name, desc->mux_owner,
+ is_hog ? " (HOG)" : "");
+ else if (desc->gpio_owner)
+ seq_printf(s, "pin %d (%s): GPIO %s",
+ pin, desc->name, desc->gpio_owner);
+ else
+ seq_printf(s, "pin %d (%s): UNCLAIMED",
+ pin, desc->name);
+ } else {
+ /* For non-strict controllers */
+ seq_printf(s, "pin %d (%s): %s %s%s", pin, desc->name,
+ desc->mux_owner ? desc->mux_owner
+ : "(MUX UNCLAIMED)",
+ desc->gpio_owner ? desc->gpio_owner
+ : "(GPIO UNCLAIMED)",
is_hog ? " (HOG)" : "");
- else if (desc->gpio_owner)
- seq_printf(s, "pin %d (%s): GPIO %s",
- pin, desc->name, desc->gpio_owner);
+ }
+
+ /* If mux: print function+group claiming the pin */
+ if (desc->mux_setting)
+ seq_printf(s, " function %s group %s\n",
+ pmxops->get_function_name(pctldev,
+ desc->mux_setting->func),
+ pctlops->get_group_name(pctldev,
+ desc->mux_setting->group));
else
- seq_printf(s, "pin %d (%s): UNCLAIMED",
- pin, desc->name);
- } else {
- /* For non-strict controllers */
- seq_printf(s, "pin %d (%s): %s %s%s", pin, desc->name,
- desc->mux_owner ? desc->mux_owner
- : "(MUX UNCLAIMED)",
- desc->gpio_owner ? desc->gpio_owner
- : "(GPIO UNCLAIMED)",
- is_hog ? " (HOG)" : "");
+ seq_putc(s, '\n');
}
-
- /* If mux: print function+group claiming the pin */
- if (desc->mux_setting)
- seq_printf(s, " function %s group %s\n",
- pmxops->get_function_name(pctldev,
- desc->mux_setting->func),
- pctlops->get_group_name(pctldev,
- desc->mux_setting->group));
- else
- seq_putc(s, '\n');
}
mutex_unlock(&pctldev->mutex);
diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm
index 8fe459d082ed..206226318e45 100644
--- a/drivers/pinctrl/qcom/Kconfig.msm
+++ b/drivers/pinctrl/qcom/Kconfig.msm
@@ -46,6 +46,15 @@ config PINCTRL_IPQ5332
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc IPQ5332 platform.
+config PINCTRL_IPQ5424
+ tristate "Qualcomm Technologies, Inc. IPQ5424 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for
+ the Qualcomm Technologies Inc. TLMM block found on the
+ Qualcomm Technologies Inc. IPQ5424 platform. Select this for
+ IPQ5424.
+
config PINCTRL_IPQ8074
tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver"
depends on ARM64 || COMPILE_TEST
@@ -182,6 +191,20 @@ config PINCTRL_QCS404
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
TLMM block found in the Qualcomm QCS404 platform.
+config PINCTRL_QCS615
+ tristate "Qualcomm Technologies QCS615 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ TLMM block found on the Qualcomm QCS615 platform.
+
+config PINCTRL_QCS8300
+ tristate "Qualcomm Technologies QCS8300 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux and pinconf driver for the Qualcomm
+ TLMM block found on the Qualcomm QCS8300 platform.
+
config PINCTRL_QDF2XXX
tristate "Qualcomm Technologies QDF2xxx pin controller driver"
depends on ACPI
@@ -204,6 +227,14 @@ config PINCTRL_SA8775P
This is the pinctrl, pinmux and pinconf driver for the Qualcomm
TLMM block found on the Qualcomm SA8775P platforms.
+config PINCTRL_SAR2130P
+ tristate "Qualcomm Technologies Inc SAR2130P pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SAR2130P platform.
+
config PINCTRL_SC7180
tristate "Qualcomm Technologies Inc SC7180 pin controller driver"
depends on ARM64 || COMPILE_TEST
@@ -382,6 +413,14 @@ config PINCTRL_SM8650
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SM8650 platform.
+config PINCTRL_SM8750
+ tristate "Qualcomm Technologies Inc SM8750 pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc SM8750 platform.
+
config PINCTRL_X1E80100
tristate "Qualcomm Technologies Inc X1E80100 pin controller driver"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index eb04297b6388..9a23d41d801c 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PINCTRL_IPQ4019) += pinctrl-ipq4019.o
obj-$(CONFIG_PINCTRL_IPQ5018) += pinctrl-ipq5018.o
obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o
obj-$(CONFIG_PINCTRL_IPQ5332) += pinctrl-ipq5332.o
+obj-$(CONFIG_PINCTRL_IPQ5424) += pinctrl-ipq5424.o
obj-$(CONFIG_PINCTRL_IPQ8074) += pinctrl-ipq8074.o
obj-$(CONFIG_PINCTRL_IPQ6018) += pinctrl-ipq6018.o
obj-$(CONFIG_PINCTRL_IPQ9574) += pinctrl-ipq9574.o
@@ -23,6 +24,8 @@ obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o
obj-$(CONFIG_PINCTRL_MSM8998) += pinctrl-msm8998.o
obj-$(CONFIG_PINCTRL_QCM2290) += pinctrl-qcm2290.o
obj-$(CONFIG_PINCTRL_QCS404) += pinctrl-qcs404.o
+obj-$(CONFIG_PINCTRL_QCS615) += pinctrl-qcs615.o
+obj-$(CONFIG_PINCTRL_QCS8300) += pinctrl-qcs8300.o
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
obj-$(CONFIG_PINCTRL_MDM9607) += pinctrl-mdm9607.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
@@ -32,6 +35,7 @@ obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
obj-$(CONFIG_PINCTRL_QDU1000) += pinctrl-qdu1000.o
obj-$(CONFIG_PINCTRL_SA8775P) += pinctrl-sa8775p.o
+obj-$(CONFIG_PINCTRL_SAR2130P) += pinctrl-sar2130p.o
obj-$(CONFIG_PINCTRL_SC7180) += pinctrl-sc7180.o
obj-$(CONFIG_PINCTRL_SC7280) += pinctrl-sc7280.o
obj-$(CONFIG_PINCTRL_SC7280_LPASS_LPI) += pinctrl-sc7280-lpass-lpi.o
@@ -62,6 +66,7 @@ obj-$(CONFIG_PINCTRL_SM8550) += pinctrl-sm8550.o
obj-$(CONFIG_PINCTRL_SM8550_LPASS_LPI) += pinctrl-sm8550-lpass-lpi.o
obj-$(CONFIG_PINCTRL_SM8650) += pinctrl-sm8650.o
obj-$(CONFIG_PINCTRL_SM8650_LPASS_LPI) += pinctrl-sm8650-lpass-lpi.o
+obj-$(CONFIG_PINCTRL_SM8750) += pinctrl-sm8750.o
obj-$(CONFIG_PINCTRL_SC8280XP_LPASS_LPI) += pinctrl-sc8280xp-lpass-lpi.o
obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o
obj-$(CONFIG_PINCTRL_X1E80100) += pinctrl-x1e80100.o
diff --git a/drivers/pinctrl/qcom/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c
index a18df4162299..20c3b9025044 100644
--- a/drivers/pinctrl/qcom/pinctrl-apq8064.c
+++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c
@@ -629,7 +629,7 @@ static struct platform_driver apq8064_pinctrl_driver = {
.of_match_table = apq8064_pinctrl_of_match,
},
.probe = apq8064_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init apq8064_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-apq8084.c b/drivers/pinctrl/qcom/pinctrl-apq8084.c
index afada80e52a2..3fc0a40762b6 100644
--- a/drivers/pinctrl/qcom/pinctrl-apq8084.c
+++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c
@@ -1207,7 +1207,7 @@ static struct platform_driver apq8084_pinctrl_driver = {
.of_match_table = apq8084_pinctrl_of_match,
},
.probe = apq8084_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init apq8084_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
index cb13576ad6cf..1f7944dd829d 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
@@ -710,7 +710,7 @@ static struct platform_driver ipq4019_pinctrl_driver = {
.of_match_table = ipq4019_pinctrl_of_match,
},
.probe = ipq4019_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init ipq4019_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
index 68f65b57003e..e2951f81c3ee 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
@@ -754,7 +754,7 @@ static struct platform_driver ipq5018_pinctrl_driver = {
.of_match_table = ipq5018_pinctrl_of_match,
},
.probe = ipq5018_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init ipq5018_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5332.c b/drivers/pinctrl/qcom/pinctrl-ipq5332.c
index 882175118970..625f8014051f 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq5332.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5332.c
@@ -834,7 +834,7 @@ static struct platform_driver ipq5332_pinctrl_driver = {
.of_match_table = ipq5332_pinctrl_of_match,
},
.probe = ipq5332_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init ipq5332_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5424.c b/drivers/pinctrl/qcom/pinctrl-ipq5424.c
new file mode 100644
index 000000000000..796299cd2e4e
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5424.c
@@ -0,0 +1,792 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016-2018,2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = REG_SIZE * id, \
+ .io_reg = 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = 0x8 + REG_SIZE * id, \
+ .intr_status_reg = 0xc + REG_SIZE * id, \
+ .intr_target_reg = 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+static const struct pinctrl_pin_desc ipq5424_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+
+enum ipq5424_functions {
+ msm_mux_atest_char,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_tic,
+ msm_mux_audio_pri,
+ msm_mux_audio_pri0,
+ msm_mux_audio_pri1,
+ msm_mux_audio_sec,
+ msm_mux_audio_sec0,
+ msm_mux_audio_sec1,
+ msm_mux_core_voltage,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_cri_trng2,
+ msm_mux_cri_trng3,
+ msm_mux_cxc_clk,
+ msm_mux_cxc_data,
+ msm_mux_dbg_out,
+ msm_mux_gcc_plltest,
+ msm_mux_gcc_tlmm,
+ msm_mux_gpio,
+ msm_mux_i2c0_scl,
+ msm_mux_i2c0_sda,
+ msm_mux_i2c1_scl,
+ msm_mux_i2c1_sda,
+ msm_mux_i2c11,
+ msm_mux_mac0,
+ msm_mux_mac1,
+ msm_mux_mdc_mst,
+ msm_mux_mdc_slv,
+ msm_mux_mdio_mst,
+ msm_mux_mdio_slv,
+ msm_mux_pcie0_clk,
+ msm_mux_pcie0_wake,
+ msm_mux_pcie1_clk,
+ msm_mux_pcie1_wake,
+ msm_mux_pcie2_clk,
+ msm_mux_pcie2_wake,
+ msm_mux_pcie3_clk,
+ msm_mux_pcie3_wake,
+ msm_mux_pll_test,
+ msm_mux_prng_rosc0,
+ msm_mux_prng_rosc1,
+ msm_mux_prng_rosc2,
+ msm_mux_prng_rosc3,
+ msm_mux_PTA0_0,
+ msm_mux_PTA0_1,
+ msm_mux_PTA0_2,
+ msm_mux_PTA10,
+ msm_mux_PTA11,
+ msm_mux_pwm0,
+ msm_mux_pwm1,
+ msm_mux_pwm2,
+ msm_mux_qdss_cti_trig_in_a0,
+ msm_mux_qdss_cti_trig_out_a0,
+ msm_mux_qdss_cti_trig_in_a1,
+ msm_mux_qdss_cti_trig_out_a1,
+ msm_mux_qdss_cti_trig_in_b0,
+ msm_mux_qdss_cti_trig_out_b0,
+ msm_mux_qdss_cti_trig_in_b1,
+ msm_mux_qdss_cti_trig_out_b1,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs,
+ msm_mux_qspi_data,
+ msm_mux_resout,
+ msm_mux_rx0,
+ msm_mux_rx1,
+ msm_mux_rx2,
+ msm_mux_sdc_clk,
+ msm_mux_sdc_cmd,
+ msm_mux_sdc_data,
+ msm_mux_spi0,
+ msm_mux_spi1,
+ msm_mux_spi10,
+ msm_mux_spi11,
+ msm_mux_tsens_max,
+ msm_mux_uart0,
+ msm_mux_uart1,
+ msm_mux_wci_txd,
+ msm_mux_wci_rxd,
+ msm_mux_wsi_clk,
+ msm_mux_wsi_data,
+ msm_mux__,
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+};
+
+static const char * const sdc_data_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+
+static const char * const qspi_data_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+
+static const char * const pwm2_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+
+static const char * const wci_txd_groups[] = {
+ "gpio0", "gpio1", "gpio8", "gpio10", "gpio11", "gpio40", "gpio41",
+};
+
+static const char * const wci_rxd_groups[] = {
+ "gpio0", "gpio1", "gpio8", "gpio10", "gpio11", "gpio40", "gpio41",
+};
+
+static const char * const sdc_cmd_groups[] = {
+ "gpio4",
+};
+
+static const char * const qspi_cs_groups[] = {
+ "gpio4",
+};
+
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+ "gpio27",
+};
+
+static const char * const sdc_clk_groups[] = {
+ "gpio5",
+};
+
+static const char * const qspi_clk_groups[] = {
+ "gpio5",
+};
+
+static const char * const spi0_groups[] = {
+ "gpio6", "gpio7", "gpio8", "gpio9",
+};
+
+static const char * const pwm1_groups[] = {
+ "gpio6", "gpio7", "gpio8", "gpio9",
+};
+
+static const char * const cri_trng0_groups[] = {
+ "gpio6",
+};
+
+static const char * const qdss_tracedata_a_groups[] = {
+ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12",
+ "gpio13", "gpio14", "gpio15", "gpio20", "gpio21", "gpio36", "gpio37",
+ "gpio38", "gpio39",
+};
+
+static const char * const cri_trng1_groups[] = {
+ "gpio7",
+};
+
+static const char * const cri_trng2_groups[] = {
+ "gpio8",
+};
+
+static const char * const cri_trng3_groups[] = {
+ "gpio9",
+};
+
+static const char * const uart0_groups[] = {
+ "gpio10", "gpio11", "gpio12", "gpio13",
+};
+
+static const char * const pwm0_groups[] = {
+ "gpio10", "gpio11", "gpio12", "gpio13",
+};
+
+static const char * const prng_rosc0_groups[] = {
+ "gpio12",
+};
+
+static const char * const prng_rosc1_groups[] = {
+ "gpio13",
+};
+
+static const char * const i2c0_scl_groups[] = {
+ "gpio14",
+};
+
+static const char * const tsens_max_groups[] = {
+ "gpio14",
+};
+
+static const char * const prng_rosc2_groups[] = {
+ "gpio14",
+};
+
+static const char * const i2c0_sda_groups[] = {
+ "gpio15",
+};
+
+static const char * const prng_rosc3_groups[] = {
+ "gpio15",
+};
+
+static const char * const core_voltage_groups[] = {
+ "gpio16", "gpio17",
+};
+
+static const char * const i2c1_scl_groups[] = {
+ "gpio16",
+};
+
+static const char * const i2c1_sda_groups[] = {
+ "gpio17",
+};
+
+static const char * const mdc_slv_groups[] = {
+ "gpio20",
+};
+
+static const char * const atest_char0_groups[] = {
+ "gpio20",
+};
+
+static const char * const mdio_slv_groups[] = {
+ "gpio21",
+};
+
+static const char * const atest_char1_groups[] = {
+ "gpio21",
+};
+
+static const char * const mdc_mst_groups[] = {
+ "gpio22",
+};
+
+static const char * const atest_char2_groups[] = {
+ "gpio22",
+};
+
+static const char * const mdio_mst_groups[] = {
+ "gpio23",
+};
+
+static const char * const atest_char3_groups[] = {
+ "gpio23",
+};
+
+static const char * const pcie0_clk_groups[] = {
+ "gpio24",
+};
+
+static const char * const PTA10_groups[] = {
+ "gpio24", "gpio26", "gpio27",
+};
+
+static const char * const mac0_groups[] = {
+ "gpio24", "gpio26",
+};
+
+static const char * const atest_char_groups[] = {
+ "gpio24",
+};
+
+static const char * const pcie0_wake_groups[] = {
+ "gpio26",
+};
+
+static const char * const pcie1_clk_groups[] = {
+ "gpio27",
+};
+
+static const char * const i2c11_groups[] = {
+ "gpio27", "gpio29",
+};
+
+static const char * const pcie1_wake_groups[] = {
+ "gpio29",
+};
+
+static const char * const pcie2_clk_groups[] = {
+ "gpio30",
+};
+
+static const char * const mac1_groups[] = {
+ "gpio30", "gpio32",
+};
+
+static const char * const pcie2_wake_groups[] = {
+ "gpio32",
+};
+
+static const char * const PTA11_groups[] = {
+ "gpio30", "gpio32", "gpio33",
+};
+
+static const char * const audio_pri0_groups[] = {
+ "gpio32", "gpio32",
+};
+
+static const char * const pcie3_clk_groups[] = {
+ "gpio33",
+};
+
+static const char * const audio_pri1_groups[] = {
+ "gpio33", "gpio33",
+};
+
+static const char * const pcie3_wake_groups[] = {
+ "gpio35",
+};
+
+static const char * const audio_sec1_groups[] = {
+ "gpio35", "gpio35",
+};
+
+static const char * const audio_pri_groups[] = {
+ "gpio36", "gpio37", "gpio38", "gpio39",
+};
+
+static const char * const spi1_groups[] = {
+ "gpio11", "gpio36", "gpio37", "gpio38", "gpio46",
+};
+
+static const char * const audio_sec0_groups[] = {
+ "gpio36", "gpio36",
+};
+
+static const char * const rx1_groups[] = {
+ "gpio38", "gpio46",
+};
+
+static const char * const pll_test_groups[] = {
+ "gpio38",
+};
+
+static const char * const dbg_out_groups[] = {
+ "gpio46",
+};
+
+static const char * const PTA0_0_groups[] = {
+ "gpio40",
+};
+
+static const char * const atest_tic_groups[] = {
+ "gpio40",
+};
+
+static const char * const PTA0_1_groups[] = {
+ "gpio41",
+};
+
+static const char * const cxc_data_groups[] = {
+ "gpio41",
+};
+
+static const char * const PTA0_2_groups[] = {
+ "gpio42",
+};
+
+static const char * const cxc_clk_groups[] = {
+ "gpio42",
+};
+
+static const char * const uart1_groups[] = {
+ "gpio43", "gpio44",
+};
+
+static const char * const audio_sec_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48",
+};
+
+static const char * const gcc_plltest_groups[] = {
+ "gpio43", "gpio45",
+};
+
+static const char * const gcc_tlmm_groups[] = {
+ "gpio44",
+};
+
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+ "gpio33",
+};
+
+static const char * const rx0_groups[] = {
+ "gpio39", "gpio47",
+};
+
+static const char * const qdss_traceclk_a_groups[] = {
+ "gpio45",
+};
+
+static const char * const qdss_tracectl_a_groups[] = {
+ "gpio46",
+};
+
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+ "gpio24",
+};
+
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+ "gpio26",
+};
+
+static const char * const resout_groups[] = {
+ "gpio49",
+};
+
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+ "gpio29",
+};
+
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+ "gpio30",
+};
+
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+ "gpio32",
+};
+
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+ "gpio35",
+};
+
+static const char * const spi10_groups[] = {
+ "gpio45", "gpio47", "gpio48",
+};
+
+static const char * const spi11_groups[] = {
+ "gpio10", "gpio12", "gpio13",
+};
+
+static const char * const wsi_clk_groups[] = {
+ "gpio24", "gpio27",
+};
+
+static const char * const wsi_data_groups[] = {
+ "gpio26", "gpio29",
+};
+
+static const char * const rx2_groups[] = {
+ "gpio37", "gpio45",
+};
+
+static const struct pinfunction ipq5424_functions[] = {
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_tic),
+ MSM_PIN_FUNCTION(audio_pri),
+ MSM_PIN_FUNCTION(audio_pri0),
+ MSM_PIN_FUNCTION(audio_pri1),
+ MSM_PIN_FUNCTION(audio_sec),
+ MSM_PIN_FUNCTION(audio_sec0),
+ MSM_PIN_FUNCTION(audio_sec1),
+ MSM_PIN_FUNCTION(core_voltage),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(cri_trng2),
+ MSM_PIN_FUNCTION(cri_trng3),
+ MSM_PIN_FUNCTION(cxc_clk),
+ MSM_PIN_FUNCTION(cxc_data),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(gcc_plltest),
+ MSM_PIN_FUNCTION(gcc_tlmm),
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(i2c0_scl),
+ MSM_PIN_FUNCTION(i2c0_sda),
+ MSM_PIN_FUNCTION(i2c1_scl),
+ MSM_PIN_FUNCTION(i2c1_sda),
+ MSM_PIN_FUNCTION(i2c11),
+ MSM_PIN_FUNCTION(mac0),
+ MSM_PIN_FUNCTION(mac1),
+ MSM_PIN_FUNCTION(mdc_mst),
+ MSM_PIN_FUNCTION(mdc_slv),
+ MSM_PIN_FUNCTION(mdio_mst),
+ MSM_PIN_FUNCTION(mdio_slv),
+ MSM_PIN_FUNCTION(pcie0_clk),
+ MSM_PIN_FUNCTION(pcie0_wake),
+ MSM_PIN_FUNCTION(pcie1_clk),
+ MSM_PIN_FUNCTION(pcie1_wake),
+ MSM_PIN_FUNCTION(pcie2_clk),
+ MSM_PIN_FUNCTION(pcie2_wake),
+ MSM_PIN_FUNCTION(pcie3_clk),
+ MSM_PIN_FUNCTION(pcie3_wake),
+ MSM_PIN_FUNCTION(pll_test),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(PTA0_0),
+ MSM_PIN_FUNCTION(PTA0_1),
+ MSM_PIN_FUNCTION(PTA0_2),
+ MSM_PIN_FUNCTION(PTA10),
+ MSM_PIN_FUNCTION(PTA11),
+ MSM_PIN_FUNCTION(pwm0),
+ MSM_PIN_FUNCTION(pwm1),
+ MSM_PIN_FUNCTION(pwm2),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_a1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b0),
+ MSM_PIN_FUNCTION(qdss_cti_trig_in_b1),
+ MSM_PIN_FUNCTION(qdss_cti_trig_out_b1),
+ MSM_PIN_FUNCTION(qdss_traceclk_a),
+ MSM_PIN_FUNCTION(qdss_tracectl_a),
+ MSM_PIN_FUNCTION(qdss_tracedata_a),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qspi_data),
+ MSM_PIN_FUNCTION(resout),
+ MSM_PIN_FUNCTION(rx0),
+ MSM_PIN_FUNCTION(rx1),
+ MSM_PIN_FUNCTION(rx2),
+ MSM_PIN_FUNCTION(sdc_clk),
+ MSM_PIN_FUNCTION(sdc_cmd),
+ MSM_PIN_FUNCTION(sdc_data),
+ MSM_PIN_FUNCTION(spi0),
+ MSM_PIN_FUNCTION(spi1),
+ MSM_PIN_FUNCTION(spi10),
+ MSM_PIN_FUNCTION(spi11),
+ MSM_PIN_FUNCTION(tsens_max),
+ MSM_PIN_FUNCTION(uart0),
+ MSM_PIN_FUNCTION(uart1),
+ MSM_PIN_FUNCTION(wci_txd),
+ MSM_PIN_FUNCTION(wci_rxd),
+ MSM_PIN_FUNCTION(wsi_clk),
+ MSM_PIN_FUNCTION(wsi_data),
+};
+
+static const struct msm_pingroup ipq5424_groups[] = {
+ PINGROUP(0, sdc_data, qspi_data, pwm2, wci_txd, wci_rxd, _, _, _, _),
+ PINGROUP(1, sdc_data, qspi_data, pwm2, wci_txd, wci_rxd, _, _, _, _),
+ PINGROUP(2, sdc_data, qspi_data, pwm2, _, _, _, _, _, _),
+ PINGROUP(3, sdc_data, qspi_data, pwm2, _, _, _, _, _, _),
+ PINGROUP(4, sdc_cmd, qspi_cs, _, _, _, _, _, _, _),
+ PINGROUP(5, sdc_clk, qspi_clk, _, _, _, _, _, _, _),
+ PINGROUP(6, spi0, pwm1, _, cri_trng0, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(7, spi0, pwm1, _, cri_trng1, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(8, spi0, pwm1, wci_txd, wci_rxd, _, cri_trng2, qdss_tracedata_a, _, _),
+ PINGROUP(9, spi0, pwm1, _, cri_trng3, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(10, uart0, pwm0, spi11, _, wci_txd, wci_rxd, _, qdss_tracedata_a, _),
+ PINGROUP(11, uart0, pwm0, spi1, _, wci_txd, wci_rxd, _, qdss_tracedata_a, _),
+ PINGROUP(12, uart0, pwm0, spi11, _, prng_rosc0, qdss_tracedata_a, _, _, _),
+ PINGROUP(13, uart0, pwm0, spi11, _, prng_rosc1, qdss_tracedata_a, _, _, _),
+ PINGROUP(14, i2c0_scl, tsens_max, _, prng_rosc2, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(15, i2c0_sda, _, prng_rosc3, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(16, core_voltage, i2c1_scl, _, _, _, _, _, _, _),
+ PINGROUP(17, core_voltage, i2c1_sda, _, _, _, _, _, _, _),
+ PINGROUP(18, _, _, _, _, _, _, _, _, _),
+ PINGROUP(19, _, _, _, _, _, _, _, _, _),
+ PINGROUP(20, mdc_slv, atest_char0, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(21, mdio_slv, atest_char1, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(22, mdc_mst, atest_char2, _, _, _, _, _, _, _),
+ PINGROUP(23, mdio_mst, atest_char3, _, _, _, _, _, _, _),
+ PINGROUP(24, pcie0_clk, PTA10, mac0, _, wsi_clk, _, atest_char, qdss_cti_trig_out_a0, _),
+ PINGROUP(25, _, _, _, _, _, _, _, _, _),
+ PINGROUP(26, pcie0_wake, PTA10, mac0, _, wsi_data, _, qdss_cti_trig_in_a0, _, _),
+ PINGROUP(27, pcie1_clk, i2c11, PTA10, wsi_clk, qdss_cti_trig_out_a1, _, _, _, _),
+ PINGROUP(28, _, _, _, _, _, _, _, _, _),
+ PINGROUP(29, pcie1_wake, i2c11, wsi_data, qdss_cti_trig_in_a1, _, _, _, _, _),
+ PINGROUP(30, pcie2_clk, PTA11, mac1, qdss_cti_trig_out_b0, _, _, _, _, _),
+ PINGROUP(31, _, _, _, _, _, _, _, _, _),
+ PINGROUP(32, pcie2_wake, PTA11, mac1, audio_pri0, audio_pri0, qdss_cti_trig_in_b0, _, _, _),
+ PINGROUP(33, pcie3_clk, PTA11, audio_pri1, audio_pri1, qdss_cti_trig_out_b1, _, _, _, _),
+ PINGROUP(34, _, _, _, _, _, _, _, _, _),
+ PINGROUP(35, pcie3_wake, audio_sec1, audio_sec1, qdss_cti_trig_in_b1, _, _, _, _, _),
+ PINGROUP(36, audio_pri, spi1, audio_sec0, audio_sec0, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(37, audio_pri, spi1, rx2, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(38, audio_pri, spi1, pll_test, rx1, qdss_tracedata_a, _, _, _, _),
+ PINGROUP(39, audio_pri, rx0, _, qdss_tracedata_a, _, _, _, _, _),
+ PINGROUP(40, PTA0_0, wci_txd, wci_rxd, _, atest_tic, _, _, _, _),
+ PINGROUP(41, PTA0_1, wci_txd, wci_rxd, cxc_data, _, _, _, _, _),
+ PINGROUP(42, PTA0_2, cxc_clk, _, _, _, _, _, _, _),
+ PINGROUP(43, uart1, gcc_plltest, _, _, _, _, _, _, _),
+ PINGROUP(44, uart1, gcc_tlmm, _, _, _, _, _, _, _),
+ PINGROUP(45, spi10, rx2, audio_sec, gcc_plltest, _, qdss_traceclk_a, _, _, _),
+ PINGROUP(46, spi1, rx1, audio_sec, dbg_out, qdss_tracectl_a, _, _, _, _),
+ PINGROUP(47, spi10, rx0, audio_sec, _, _, _, _, _, _),
+ PINGROUP(48, spi10, audio_sec, _, _, _, _, _, _, _),
+ PINGROUP(49, resout, _, _, _, _, _, _, _, _),
+};
+
+static const struct msm_pinctrl_soc_data ipq5424_pinctrl = {
+ .pins = ipq5424_pins,
+ .npins = ARRAY_SIZE(ipq5424_pins),
+ .functions = ipq5424_functions,
+ .nfunctions = ARRAY_SIZE(ipq5424_functions),
+ .groups = ipq5424_groups,
+ .ngroups = ARRAY_SIZE(ipq5424_groups),
+ .ngpios = 50,
+};
+
+static int ipq5424_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &ipq5424_pinctrl);
+}
+
+static const struct of_device_id ipq5424_pinctrl_of_match[] = {
+ { .compatible = "qcom,ipq5424-tlmm", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ipq5424_pinctrl_of_match);
+
+static struct platform_driver ipq5424_pinctrl_driver = {
+ .driver = {
+ .name = "ipq5424-tlmm",
+ .of_match_table = ipq5424_pinctrl_of_match,
+ },
+ .probe = ipq5424_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init ipq5424_pinctrl_init(void)
+{
+ return platform_driver_register(&ipq5424_pinctrl_driver);
+}
+arch_initcall(ipq5424_pinctrl_init);
+
+static void __exit ipq5424_pinctrl_exit(void)
+{
+ platform_driver_unregister(&ipq5424_pinctrl_driver);
+}
+module_exit(ipq5424_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI IPQ5424 TLMM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c
index ac330d8712b5..0ad08647dbcd 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq6018.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c
@@ -1080,7 +1080,7 @@ static struct platform_driver ipq6018_pinctrl_driver = {
.of_match_table = ipq6018_pinctrl_of_match,
},
.probe = ipq6018_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init ipq6018_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
index e10e1bc4c911..e2bb94e86aef 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
@@ -631,7 +631,7 @@ static struct platform_driver ipq8064_pinctrl_driver = {
.of_match_table = ipq8064_pinctrl_of_match,
},
.probe = ipq8064_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init ipq8064_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8074.c b/drivers/pinctrl/qcom/pinctrl-ipq8074.c
index fee32c1d1d3e..337f3a1c92c1 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq8074.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq8074.c
@@ -1041,7 +1041,7 @@ static struct platform_driver ipq8074_pinctrl_driver = {
.of_match_table = ipq8074_pinctrl_of_match,
},
.probe = ipq8074_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init ipq8074_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq9574.c b/drivers/pinctrl/qcom/pinctrl-ipq9574.c
index 20ab59cb621b..e2491617b236 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq9574.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq9574.c
@@ -799,7 +799,7 @@ static struct platform_driver ipq9574_pinctrl_driver = {
.of_match_table = ipq9574_pinctrl_of_match,
},
.probe = ipq9574_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init ipq9574_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
index 415d24e16267..e7cd3ef1cf3e 100644
--- a/drivers/pinctrl/qcom/pinctrl-mdm9607.c
+++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
@@ -1059,7 +1059,7 @@ static struct platform_driver mdm9607_pinctrl_driver = {
.of_match_table = mdm9607_pinctrl_of_match,
},
.probe = mdm9607_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init mdm9607_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9615.c b/drivers/pinctrl/qcom/pinctrl-mdm9615.c
index 3f2eafea0b24..0a2ae383d3d5 100644
--- a/drivers/pinctrl/qcom/pinctrl-mdm9615.c
+++ b/drivers/pinctrl/qcom/pinctrl-mdm9615.c
@@ -446,7 +446,7 @@ static struct platform_driver mdm9615_pinctrl_driver = {
.of_match_table = mdm9615_pinctrl_of_match,
},
.probe = mdm9615_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init mdm9615_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index aeaf0d1958f5..ec913c2e200f 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1457,7 +1457,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
* files which don't set the "gpio-ranges" property or systems that
* utilize ACPI the driver has to call gpiochip_add_pin_range().
*/
- if (!of_property_read_bool(pctrl->dev->of_node, "gpio-ranges")) {
+ if (!of_property_present(pctrl->dev->of_node, "gpio-ranges")) {
ret = gpiochip_add_pin_range(&pctrl->chip,
dev_name(pctrl->dev), 0, 0, chip->ngpio);
if (ret) {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8226.c b/drivers/pinctrl/qcom/pinctrl-msm8226.c
index 40806c0650ef..64fee70f1772 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8226.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8226.c
@@ -654,7 +654,7 @@ static struct platform_driver msm8226_pinctrl_driver = {
.of_match_table = msm8226_pinctrl_of_match,
},
.probe = msm8226_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8226_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8660.c b/drivers/pinctrl/qcom/pinctrl-msm8660.c
index dba6d531b4a1..999a5f867eb5 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8660.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8660.c
@@ -981,7 +981,7 @@ static struct platform_driver msm8660_pinctrl_driver = {
.of_match_table = msm8660_pinctrl_of_match,
},
.probe = msm8660_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8660_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c
index 14b17ba9f906..756856d20d6b 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8909.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c
@@ -929,7 +929,7 @@ static struct platform_driver msm8909_pinctrl_driver = {
.of_match_table = msm8909_pinctrl_of_match,
},
.probe = msm8909_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8909_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8916.c b/drivers/pinctrl/qcom/pinctrl-msm8916.c
index 184dcf842273..cea5c54f92fe 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8916.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c
@@ -969,7 +969,7 @@ static struct platform_driver msm8916_pinctrl_driver = {
.of_match_table = msm8916_pinctrl_of_match,
},
.probe = msm8916_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8916_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8953.c b/drivers/pinctrl/qcom/pinctrl-msm8953.c
index c2253821ae8d..998351bdfee1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8953.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8953.c
@@ -1816,7 +1816,7 @@ static struct platform_driver msm8953_pinctrl_driver = {
.of_match_table = msm8953_pinctrl_of_match,
},
.probe = msm8953_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8953_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c
index 6b9148d226e9..ebe230b3b437 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8960.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c
@@ -1246,7 +1246,7 @@ static struct platform_driver msm8960_pinctrl_driver = {
.of_match_table = msm8960_pinctrl_of_match,
},
.probe = msm8960_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8960_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8976.c b/drivers/pinctrl/qcom/pinctrl-msm8976.c
index 9a951888e8a1..c30d80e4e98c 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8976.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8976.c
@@ -1096,7 +1096,7 @@ static struct platform_driver msm8976_pinctrl_driver = {
.of_match_table = msm8976_pinctrl_of_match,
},
.probe = msm8976_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8976_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c
index 1ed1dd32d6c7..b1a6759ab4a5 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8994.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c
@@ -1343,7 +1343,7 @@ static struct platform_driver msm8994_pinctrl_driver = {
.of_match_table = msm8994_pinctrl_of_match,
},
.probe = msm8994_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8994_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8996.c b/drivers/pinctrl/qcom/pinctrl-msm8996.c
index 777c2a74036e..1b5d80eaab83 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8996.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8996.c
@@ -1920,7 +1920,7 @@ static struct platform_driver msm8996_pinctrl_driver = {
.of_match_table = msm8996_pinctrl_of_match,
},
.probe = msm8996_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8996_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c
index 4aaf45e54f3a..b7cbf32b3125 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8998.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c
@@ -1535,7 +1535,7 @@ static struct platform_driver msm8998_pinctrl_driver = {
.of_match_table = msm8998_pinctrl_of_match,
},
.probe = msm8998_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8998_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c
index 750a8272ded7..238c83f6ec4f 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c
@@ -1083,7 +1083,7 @@ static struct platform_driver msm8x74_pinctrl_driver = {
.of_match_table = msm8x74_pinctrl_of_match,
},
.probe = msm8x74_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init msm8x74_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
index f5c1c427b44e..ba699eac9ee8 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
@@ -1113,7 +1113,7 @@ static struct platform_driver qcm2290_pinctrl_driver = {
.of_match_table = qcm2290_pinctrl_of_match,
},
.probe = qcm2290_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init qcm2290_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c
index 9a875b7dc998..ae7224012f8a 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcs404.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c
@@ -1644,7 +1644,7 @@ static struct platform_driver qcs404_pinctrl_driver = {
.of_match_table = qcs404_pinctrl_of_match,
},
.probe = qcs404_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init qcs404_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-qcs615.c b/drivers/pinctrl/qcom/pinctrl-qcs615.c
new file mode 100644
index 000000000000..23015b055f6a
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-qcs615.c
@@ -0,0 +1,1107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+enum {
+ SOUTH,
+ EAST,
+ WEST
+};
+
+static const char * const qcs615_tiles[] = {
+ [SOUTH] = "south",
+ [EAST] = "east",
+ [WEST] = "west"
+};
+
+#define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = 0x1000 * id, \
+ .io_reg = 0x1000 * id + 0x4, \
+ .intr_cfg_reg = 0x1000 * id + 0x8, \
+ .intr_status_reg = 0x1000 * id + 0xc, \
+ .intr_target_reg = 0x1000 * id + 0x8, \
+ .tile = _tile, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .tile = _tile, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+#define UFS_RESET(pg_name, offset) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .tile = WEST, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+static const struct pinctrl_pin_desc qcs615_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "UFS_RESET"),
+ PINCTRL_PIN(124, "SDC1_RCLK"),
+ PINCTRL_PIN(125, "SDC1_CLK"),
+ PINCTRL_PIN(126, "SDC1_CMD"),
+ PINCTRL_PIN(127, "SDC1_DATA"),
+ PINCTRL_PIN(128, "SDC2_CLK"),
+ PINCTRL_PIN(129, "SDC2_CMD"),
+ PINCTRL_PIN(130, "SDC2_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+
+static const unsigned int ufs_reset_pins[] = { 123 };
+static const unsigned int sdc1_rclk_pins[] = { 124 };
+static const unsigned int sdc1_clk_pins[] = { 125 };
+static const unsigned int sdc1_cmd_pins[] = { 126 };
+static const unsigned int sdc1_data_pins[] = { 127 };
+static const unsigned int sdc2_clk_pins[] = { 128 };
+static const unsigned int sdc2_cmd_pins[] = { 129 };
+static const unsigned int sdc2_data_pins[] = { 130 };
+
+enum qcs615_functions {
+ msm_mux_gpio,
+ msm_mux_adsp_ext,
+ msm_mux_agera_pll,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char,
+ msm_mux_atest_tsens,
+ msm_mux_atest_usb,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async,
+ msm_mux_cci_i2c,
+ msm_mux_cci_timer,
+ msm_mux_copy_gp,
+ msm_mux_copy_phase,
+ msm_mux_cri_trng,
+ msm_mux_dbg_out_clk,
+ msm_mux_ddr_bist,
+ msm_mux_ddr_pxi,
+ msm_mux_dp_hot,
+ msm_mux_edp_hot,
+ msm_mux_edp_lcd,
+ msm_mux_emac_gcc,
+ msm_mux_emac_phy_intr,
+ msm_mux_forced_usb,
+ msm_mux_gcc_gp,
+ msm_mux_gp_pdm,
+ msm_mux_gps_tx,
+ msm_mux_hs0_mi2s,
+ msm_mux_hs1_mi2s,
+ msm_mux_jitter_bist,
+ msm_mux_ldo_en,
+ msm_mux_ldo_update,
+ msm_mux_m_voc,
+ msm_mux_mclk1,
+ msm_mux_mclk2,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync0_out,
+ msm_mux_mdp_vsync1_out,
+ msm_mux_mdp_vsync2_out,
+ msm_mux_mdp_vsync3_out,
+ msm_mux_mdp_vsync4_out,
+ msm_mux_mdp_vsync5_out,
+ msm_mux_mi2s_1,
+ msm_mux_mss_lte,
+ msm_mux_nav_pps_in,
+ msm_mux_nav_pps_out,
+ msm_mux_pa_indicator_or,
+ msm_mux_pcie_clk_req,
+ msm_mux_pcie_ep_rst,
+ msm_mux_phase_flag,
+ msm_mux_pll_bist,
+ msm_mux_pll_bypassnl,
+ msm_mux_pll_reset_n,
+ msm_mux_prng_rosc,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_gpio,
+ msm_mux_qlink_enable,
+ msm_mux_qlink_request,
+ msm_mux_qspi,
+ msm_mux_qup0,
+ msm_mux_qup1,
+ msm_mux_rgmii,
+ msm_mux_sd_write_protect,
+ msm_mux_sp_cmu,
+ msm_mux_ter_mi2s,
+ msm_mux_tgu_ch,
+ msm_mux_uim1,
+ msm_mux_uim2,
+ msm_mux_usb0_hs,
+ msm_mux_usb1_hs,
+ msm_mux_usb_phy_ps,
+ msm_mux_vfr_1,
+ msm_mux_vsense_trigger_mirnat,
+ msm_mux_wlan,
+ msm_mux_wsa_clk,
+ msm_mux_wsa_data,
+ msm_mux__,
+};
+
+static const char *const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5",
+ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14", "gpio15", "gpio16", "gpio17",
+ "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41",
+ "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53",
+ "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59",
+ "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65",
+ "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", "gpio71",
+ "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89",
+ "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+ "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101",
+ "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107",
+ "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113",
+ "gpio114", "gpio115", "gpio116", "gpio117", "gpio118", "gpio119",
+ "gpio120", "gpio121", "gpio122",
+};
+
+static const char *const adsp_ext_groups[] = {
+ "gpio118",
+};
+
+static const char *const agera_pll_groups[] = {
+ "gpio28",
+};
+
+static const char *const aoss_cti_groups[] = {
+ "gpio76",
+};
+
+static const char *const atest_char_groups[] = {
+ "gpio84", "gpio85", "gpio86", "gpio87",
+ "gpio115", "gpio117", "gpio118", "gpio119",
+ "gpio120", "gpio121",
+};
+
+static const char *const atest_tsens_groups[] = {
+ "gpio7", "gpio29",
+};
+
+static const char *const atest_usb_groups[] = {
+ "gpio7", "gpio10", "gpio11", "gpio54",
+ "gpio55", "gpio67", "gpio68", "gpio76",
+ "gpio75", "gpio77",
+};
+
+static const char *const cam_mclk_groups[] = {
+ "gpio28", "gpio29", "gpio30", "gpio31",
+};
+
+static const char *const cci_async_groups[] = {
+ "gpio26", "gpio41", "gpio42",
+};
+
+static const char *const cci_i2c_groups[] = {
+ "gpio32", "gpio33", "gpio34", "gpio35",
+};
+
+static const char *const cci_timer_groups[] = {
+ "gpio37", "gpio38", "gpio39", "gpio41",
+ "gpio42",
+};
+
+static const char *const copy_gp_groups[] = {
+ "gpio86",
+};
+
+static const char *const copy_phase_groups[] = {
+ "gpio103",
+};
+
+static const char *const cri_trng_groups[] = {
+ "gpio60", "gpio61", "gpio62",
+};
+
+static const char *const dbg_out_clk_groups[] = {
+ "gpio11",
+};
+
+static const char *const ddr_bist_groups[] = {
+ "gpio7", "gpio8", "gpio9", "gpio10",
+};
+
+static const char *const ddr_pxi_groups[] = {
+ "gpio6", "gpio7", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio54", "gpio55",
+};
+
+static const char *const dp_hot_groups[] = {
+ "gpio102", "gpio103", "gpio104",
+};
+
+static const char *const edp_hot_groups[] = {
+ "gpio113",
+};
+
+static const char *const edp_lcd_groups[] = {
+ "gpio119",
+};
+
+static const char *const emac_gcc_groups[] = {
+ "gpio101", "gpio102",
+};
+
+static const char *const emac_phy_intr_groups[] = {
+ "gpio89",
+};
+
+static const char *const forced_usb_groups[] = {
+ "gpio43",
+};
+
+static const char *const gcc_gp_groups[] = {
+ "gpio21", "gpio22", "gpio57", "gpio58",
+ "gpio59", "gpio78",
+};
+
+static const char *const gp_pdm_groups[] = {
+ "gpio8", "gpio54", "gpio63", "gpio66",
+ "gpio79", "gpio95",
+};
+
+static const char *const gps_tx_groups[] = {
+ "gpio53", "gpio54", "gpio56", "gpio57",
+ "gpio59", "gpio60",
+};
+
+static const char *const hs0_mi2s_groups[] = {
+ "gpio36", "gpio37", "gpio38", "gpio39",
+};
+
+static const char *const hs1_mi2s_groups[] = {
+ "gpio24", "gpio25", "gpio26", "gpio27",
+};
+
+static const char *const jitter_bist_groups[] = {
+ "gpio12", "gpio26",
+};
+
+static const char *const ldo_en_groups[] = {
+ "gpio97",
+};
+
+static const char *const ldo_update_groups[] = {
+ "gpio98",
+};
+
+static const char *const m_voc_groups[] = {
+ "gpio120",
+};
+
+static const char *const mclk1_groups[] = {
+ "gpio121",
+};
+
+static const char *const mclk2_groups[] = {
+ "gpio122",
+};
+
+static const char *const mdp_vsync_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio90",
+ "gpio97", "gpio98",
+};
+
+static const char *const mdp_vsync0_out_groups[] = {
+ "gpio90",
+};
+
+static const char *const mdp_vsync1_out_groups[] = {
+ "gpio90",
+};
+
+static const char *const mdp_vsync2_out_groups[] = {
+ "gpio90",
+};
+
+static const char *const mdp_vsync3_out_groups[] = {
+ "gpio90",
+};
+
+static const char *const mdp_vsync4_out_groups[] = {
+ "gpio90",
+};
+
+static const char *const mdp_vsync5_out_groups[] = {
+ "gpio90",
+};
+
+static const char *const mi2s_1_groups[] = {
+ "gpio108", "gpio109", "gpio110", "gpio111",
+};
+
+static const char *const mss_lte_groups[] = {
+ "gpio106", "gpio107",
+};
+
+static const char *const nav_pps_in_groups[] = {
+ "gpio53", "gpio56", "gpio57", "gpio59",
+ "gpio60",
+};
+
+static const char *const nav_pps_out_groups[] = {
+ "gpio53", "gpio56", "gpio57", "gpio59",
+ "gpio60",
+};
+
+static const char *const pa_indicator_or_groups[] = {
+ "gpio53",
+};
+
+static const char *const pcie_clk_req_groups[] = {
+ "gpio90",
+};
+
+static const char *const pcie_ep_rst_groups[] = {
+ "gpio89",
+};
+
+static const char *const phase_flag_groups[] = {
+ "gpio10", "gpio18", "gpio19", "gpio20",
+ "gpio23", "gpio24", "gpio25", "gpio38",
+ "gpio40", "gpio41", "gpio42", "gpio43",
+ "gpio44", "gpio45", "gpio53", "gpio54",
+ "gpio55", "gpio67", "gpio68", "gpio75",
+ "gpio76", "gpio77", "gpio78", "gpio79",
+ "gpio80", "gpio82", "gpio84", "gpio92",
+ "gpio116", "gpio117", "gpio118", "gpio119",
+};
+
+static const char *const pll_bist_groups[] = {
+ "gpio27",
+};
+
+static const char *const pll_bypassnl_groups[] = {
+ "gpio13",
+};
+
+static const char *const pll_reset_n_groups[] = {
+ "gpio14",
+};
+
+static const char *const prng_rosc_groups[] = {
+ "gpio99", "gpio102",
+};
+
+static const char *const qdss_cti_groups[] = {
+ "gpio83", "gpio96", "gpio97", "gpio98",
+ "gpio103", "gpio104", "gpio112", "gpio113",
+};
+
+static const char *const qdss_gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio6", "gpio7", "gpio8", "gpio9",
+ "gpio14", "gpio15", "gpio20", "gpio21",
+ "gpio28", "gpio29", "gpio30", "gpio31",
+ "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio81", "gpio82", "gpio92", "gpio93",
+ "gpio94", "gpio95", "gpio108", "gpio109",
+ "gpio117", "gpio118", "gpio119", "gpio120",
+};
+
+static const char *const qlink_enable_groups[] = {
+ "gpio52",
+};
+
+static const char *const qlink_request_groups[] = {
+ "gpio51",
+};
+
+static const char *const qspi_groups[] = {
+ "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio48", "gpio49", "gpio50",
+};
+
+static const char *const qup0_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio4", "gpio5", "gpio16", "gpio17",
+ "gpio18", "gpio19",
+};
+
+static const char *const qup1_groups[] = {
+ "gpio6", "gpio7", "gpio8", "gpio9",
+ "gpio10", "gpio11", "gpio12", "gpio13",
+ "gpio14", "gpio15", "gpio20", "gpio21",
+ "gpio22", "gpio23",
+};
+
+static const char *const rgmii_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95",
+ "gpio96", "gpio97", "gpio102", "gpio103",
+ "gpio112", "gpio113", "gpio114",
+};
+
+static const char *const sd_write_protect_groups[] = {
+ "gpio24",
+};
+
+static const char *const sp_cmu_groups[] = {
+ "gpio64",
+};
+
+static const char *const ter_mi2s_groups[] = {
+ "gpio115", "gpio116", "gpio117", "gpio118",
+};
+
+static const char *const tgu_ch_groups[] = {
+ "gpio89", "gpio90", "gpio91", "gpio92",
+};
+
+static const char *const uim1_groups[] = {
+ "gpio77", "gpio78", "gpio79", "gpio80",
+};
+
+static const char *const uim2_groups[] = {
+ "gpio73", "gpio74", "gpio75", "gpio76",
+};
+
+static const char *const usb0_hs_groups[] = {
+ "gpio88",
+};
+
+static const char *const usb1_hs_groups[] = {
+ "gpio89",
+};
+
+static const char *const usb_phy_ps_groups[] = {
+ "gpio104",
+};
+
+static const char *const vfr_1_groups[] = {
+ "gpio92",
+};
+
+static const char *const vsense_trigger_mirnat_groups[] = {
+ "gpio7",
+};
+
+static const char *const wlan_groups[] = {
+ "gpio16", "gpio17", "gpio47", "gpio48",
+};
+
+static const char *const wsa_clk_groups[] = {
+ "gpio111",
+};
+
+static const char *const wsa_data_groups[] = {
+ "gpio110",
+};
+
+static const struct pinfunction qcs615_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(adsp_ext),
+ MSM_PIN_FUNCTION(agera_pll),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_tsens),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(copy_gp),
+ MSM_PIN_FUNCTION(copy_phase),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(edp_hot),
+ MSM_PIN_FUNCTION(edp_lcd),
+ MSM_PIN_FUNCTION(emac_gcc),
+ MSM_PIN_FUNCTION(emac_phy_intr),
+ MSM_PIN_FUNCTION(forced_usb),
+ MSM_PIN_FUNCTION(gcc_gp),
+ MSM_PIN_FUNCTION(gp_pdm),
+ MSM_PIN_FUNCTION(gps_tx),
+ MSM_PIN_FUNCTION(hs0_mi2s),
+ MSM_PIN_FUNCTION(hs1_mi2s),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(ldo_en),
+ MSM_PIN_FUNCTION(ldo_update),
+ MSM_PIN_FUNCTION(m_voc),
+ MSM_PIN_FUNCTION(mclk1),
+ MSM_PIN_FUNCTION(mclk2),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0_out),
+ MSM_PIN_FUNCTION(mdp_vsync1_out),
+ MSM_PIN_FUNCTION(mdp_vsync2_out),
+ MSM_PIN_FUNCTION(mdp_vsync3_out),
+ MSM_PIN_FUNCTION(mdp_vsync4_out),
+ MSM_PIN_FUNCTION(mdp_vsync5_out),
+ MSM_PIN_FUNCTION(mi2s_1),
+ MSM_PIN_FUNCTION(mss_lte),
+ MSM_PIN_FUNCTION(nav_pps_in),
+ MSM_PIN_FUNCTION(nav_pps_out),
+ MSM_PIN_FUNCTION(pa_indicator_or),
+ MSM_PIN_FUNCTION(pcie_clk_req),
+ MSM_PIN_FUNCTION(pcie_ep_rst),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_bypassnl),
+ MSM_PIN_FUNCTION(pll_reset_n),
+ MSM_PIN_FUNCTION(prng_rosc),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qlink_enable),
+ MSM_PIN_FUNCTION(qlink_request),
+ MSM_PIN_FUNCTION(qspi),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(rgmii),
+ MSM_PIN_FUNCTION(sd_write_protect),
+ MSM_PIN_FUNCTION(sp_cmu),
+ MSM_PIN_FUNCTION(ter_mi2s),
+ MSM_PIN_FUNCTION(tgu_ch),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(uim2),
+ MSM_PIN_FUNCTION(usb0_hs),
+ MSM_PIN_FUNCTION(usb1_hs),
+ MSM_PIN_FUNCTION(usb_phy_ps),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger_mirnat),
+ MSM_PIN_FUNCTION(wlan),
+ MSM_PIN_FUNCTION(wsa_clk),
+ MSM_PIN_FUNCTION(wsa_data),
+};
+
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup qcs615_groups[] = {
+ [0] = PINGROUP(0, WEST, qup0, _, qdss_gpio, _, _, _, _, _, _),
+ [1] = PINGROUP(1, WEST, qup0, _, qdss_gpio, _, _, _, _, _, _),
+ [2] = PINGROUP(2, WEST, qup0, _, qdss_gpio, _, _, _, _, _, _),
+ [3] = PINGROUP(3, WEST, qup0, _, qdss_gpio, _, _, _, _, _, _),
+ [4] = PINGROUP(4, WEST, qup0, _, _, _, _, _, _, _, _),
+ [5] = PINGROUP(5, WEST, qup0, _, _, _, _, _, _, _, _),
+ [6] = PINGROUP(6, EAST, qup1, qdss_gpio, ddr_pxi, _, _, _, _, _, _),
+ [7] = PINGROUP(7, EAST, qup1, ddr_bist, qdss_gpio, atest_tsens,
+ vsense_trigger_mirnat, atest_usb, ddr_pxi, _, _),
+ [8] = PINGROUP(8, EAST, qup1, gp_pdm, ddr_bist, qdss_gpio, _, _, _, _, _),
+ [9] = PINGROUP(9, EAST, qup1, ddr_bist, qdss_gpio, _, _, _, _, _, _),
+ [10] = PINGROUP(10, EAST, qup1, ddr_bist, _, phase_flag, atest_usb, ddr_pxi, _, _, _),
+ [11] = PINGROUP(11, EAST, qup1, dbg_out_clk, atest_usb, ddr_pxi, _, _, _, _, _),
+ [12] = PINGROUP(12, EAST, qup1, jitter_bist, ddr_pxi, _, _, _, _, _, _),
+ [13] = PINGROUP(13, EAST, qup1, pll_bypassnl, _, ddr_pxi, _, _, _, _, _),
+ [14] = PINGROUP(14, EAST, qup1, pll_reset_n, _, qdss_gpio, _, _, _, _, _),
+ [15] = PINGROUP(15, EAST, qup1, qdss_gpio, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, WEST, qup0, _, wlan, _, _, _, _, _, _),
+ [17] = PINGROUP(17, WEST, qup0, _, wlan, _, _, _, _, _, _),
+ [18] = PINGROUP(18, WEST, qup0, _, phase_flag, _, _, _, _, _, _),
+ [19] = PINGROUP(19, WEST, qup0, _, phase_flag, _, _, _, _, _, _),
+ [20] = PINGROUP(20, SOUTH, qup1, _, phase_flag, qdss_gpio, _, _, _, _, _),
+ [21] = PINGROUP(21, SOUTH, qup1, gcc_gp, _, qdss_gpio, _, _, _, _, _),
+ [22] = PINGROUP(22, SOUTH, qup1, gcc_gp, _, _, _, _, _, _, _),
+ [23] = PINGROUP(23, SOUTH, qup1, _, phase_flag, _, _, _, _, _, _),
+ [24] = PINGROUP(24, EAST, hs1_mi2s, sd_write_protect, _, phase_flag, _, _, _, _, _),
+ [25] = PINGROUP(25, EAST, hs1_mi2s, _, phase_flag, _, _, _, _, _, _),
+ [26] = PINGROUP(26, EAST, cci_async, hs1_mi2s, jitter_bist, _, _, _, _, _, _),
+ [27] = PINGROUP(27, EAST, hs1_mi2s, pll_bist, _, _, _, _, _, _, _),
+ [28] = PINGROUP(28, EAST, cam_mclk, agera_pll, qdss_gpio, _, _, _, _, _, _),
+ [29] = PINGROUP(29, EAST, cam_mclk, _, qdss_gpio, atest_tsens, _, _, _, _, _),
+ [30] = PINGROUP(30, EAST, cam_mclk, qdss_gpio, _, _, _, _, _, _, _),
+ [31] = PINGROUP(31, EAST, cam_mclk, _, qdss_gpio, _, _, _, _, _, _),
+ [32] = PINGROUP(32, EAST, cci_i2c, _, qdss_gpio, _, _, _, _, _, _),
+ [33] = PINGROUP(33, EAST, cci_i2c, _, qdss_gpio, _, _, _, _, _, _),
+ [34] = PINGROUP(34, EAST, cci_i2c, _, qdss_gpio, _, _, _, _, _, _),
+ [35] = PINGROUP(35, EAST, cci_i2c, _, qdss_gpio, _, _, _, _, _, _),
+ [36] = PINGROUP(36, EAST, hs0_mi2s, _, _, _, _, _, _, _, _),
+ [37] = PINGROUP(37, EAST, cci_timer, hs0_mi2s, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, EAST, cci_timer, hs0_mi2s, _, phase_flag, _, _, _, _, _),
+ [39] = PINGROUP(39, EAST, cci_timer, hs0_mi2s, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, EAST, _, phase_flag, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, EAST, cci_async, cci_timer, _, phase_flag, _, _, _, _, _),
+ [42] = PINGROUP(42, EAST, cci_async, cci_timer, _, phase_flag, _, _, _, _, _),
+ [43] = PINGROUP(43, SOUTH, _, phase_flag, forced_usb, _, _, _, _, _, _),
+ [44] = PINGROUP(44, EAST, qspi, _, phase_flag, qdss_gpio, _, _, _, _, _),
+ [45] = PINGROUP(45, EAST, qspi, _, phase_flag, qdss_gpio, _, _, _, _, _),
+ [46] = PINGROUP(46, EAST, qspi, _, qdss_gpio, _, _, _, _, _, _),
+ [47] = PINGROUP(47, EAST, qspi, _, qdss_gpio, wlan, _, _, _, _, _),
+ [48] = PINGROUP(48, EAST, qspi, _, wlan, _, _, _, _, _, _),
+ [49] = PINGROUP(49, EAST, qspi, _, _, _, _, _, _, _, _),
+ [50] = PINGROUP(50, EAST, qspi, _, _, _, _, _, _, _, _),
+ [51] = PINGROUP(51, SOUTH, qlink_request, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, SOUTH, qlink_enable, _, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, SOUTH, pa_indicator_or, nav_pps_in, nav_pps_out, gps_tx, _,
+ phase_flag, _, _, _),
+ [54] = PINGROUP(54, SOUTH, _, gps_tx, gp_pdm, _, phase_flag, atest_usb, ddr_pxi, _, _),
+ [55] = PINGROUP(55, SOUTH, _, _, phase_flag, atest_usb, ddr_pxi, _, _, _, _),
+ [56] = PINGROUP(56, SOUTH, _, nav_pps_in, nav_pps_out, gps_tx, _, _, _, _, _),
+ [57] = PINGROUP(57, SOUTH, _, nav_pps_in, gps_tx, nav_pps_out, gcc_gp, _, _, _, _),
+ [58] = PINGROUP(58, SOUTH, _, gcc_gp, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, SOUTH, _, nav_pps_in, nav_pps_out, gps_tx, gcc_gp, _, _, _, _),
+ [60] = PINGROUP(60, SOUTH, _, nav_pps_in, nav_pps_out, gps_tx, cri_trng, _, _, _, _),
+ [61] = PINGROUP(61, SOUTH, _, cri_trng, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, SOUTH, _, cri_trng, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, SOUTH, _, _, gp_pdm, _, _, _, _, _, _),
+ [64] = PINGROUP(64, SOUTH, _, sp_cmu, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, SOUTH, _, _, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, SOUTH, _, gp_pdm, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, SOUTH, _, _, _, phase_flag, atest_usb, _, _, _, _),
+ [68] = PINGROUP(68, SOUTH, _, _, _, phase_flag, atest_usb, _, _, _, _),
+ [69] = PINGROUP(69, SOUTH, _, _, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, SOUTH, _, _, _, _, _, _, _, _, _),
+ [71] = PINGROUP(71, SOUTH, _, _, _, _, _, _, _, _, _),
+ [72] = PINGROUP(72, SOUTH, _, _, _, _, _, _, _, _, _),
+ [73] = PINGROUP(73, SOUTH, uim2, _, _, _, _, _, _, _, _),
+ [74] = PINGROUP(74, SOUTH, uim2, _, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, SOUTH, uim2, _, phase_flag, atest_usb, _, _, _, _, _),
+ [76] = PINGROUP(76, SOUTH, uim2, _, phase_flag, atest_usb, aoss_cti, _, _, _, _),
+ [77] = PINGROUP(77, SOUTH, uim1, _, phase_flag, atest_usb, _, _, _, _, _),
+ [78] = PINGROUP(78, SOUTH, uim1, gcc_gp, _, phase_flag, _, _, _, _, _),
+ [79] = PINGROUP(79, SOUTH, uim1, gp_pdm, _, phase_flag, _, _, _, _, _),
+ [80] = PINGROUP(80, SOUTH, uim1, _, phase_flag, _, _, _, _, _, _),
+ [81] = PINGROUP(81, WEST, rgmii, mdp_vsync, _, qdss_gpio, _, _, _, _, _),
+ [82] = PINGROUP(82, WEST, rgmii, mdp_vsync, _, phase_flag, qdss_gpio, _, _, _, _),
+ [83] = PINGROUP(83, WEST, rgmii, mdp_vsync, _, qdss_cti, _, _, _, _, _),
+ [84] = PINGROUP(84, SOUTH, _, phase_flag, atest_char, _, _, _, _, _, _),
+ [85] = PINGROUP(85, SOUTH, _, atest_char, _, _, _, _, _, _, _),
+ [86] = PINGROUP(86, SOUTH, copy_gp, _, atest_char, _, _, _, _, _, _),
+ [87] = PINGROUP(87, SOUTH, _, atest_char, _, _, _, _, _, _, _),
+ [88] = PINGROUP(88, WEST, _, usb0_hs, _, _, _, _, _, _, _),
+ [89] = PINGROUP(89, WEST, emac_phy_intr, pcie_ep_rst, tgu_ch, usb1_hs, _, _, _, _, _),
+ [90] = PINGROUP(90, WEST, mdp_vsync, mdp_vsync0_out, mdp_vsync1_out,
+ mdp_vsync2_out, mdp_vsync3_out, mdp_vsync4_out, mdp_vsync5_out,
+ pcie_clk_req, tgu_ch),
+ [91] = PINGROUP(91, WEST, rgmii, tgu_ch, _, _, _, _, _, _, _),
+ [92] = PINGROUP(92, WEST, rgmii, vfr_1, tgu_ch, _, phase_flag, qdss_gpio, _, _, _),
+ [93] = PINGROUP(93, WEST, rgmii, qdss_gpio, _, _, _, _, _, _, _),
+ [94] = PINGROUP(94, WEST, rgmii, qdss_gpio, _, _, _, _, _, _, _),
+ [95] = PINGROUP(95, WEST, rgmii, gp_pdm, qdss_gpio, _, _, _, _, _, _),
+ [96] = PINGROUP(96, WEST, rgmii, qdss_cti, _, _, _, _, _, _, _),
+ [97] = PINGROUP(97, WEST, rgmii, mdp_vsync, ldo_en, qdss_cti, _, _, _, _, _),
+ [98] = PINGROUP(98, WEST, mdp_vsync, ldo_update, qdss_cti, _, _, _, _, _, _),
+ [99] = PINGROUP(99, EAST, prng_rosc, _, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, WEST, _, _, _, _, _, _, _, _, _),
+ [101] = PINGROUP(101, WEST, emac_gcc, _, _, _, _, _, _, _, _),
+ [102] = PINGROUP(102, WEST, rgmii, dp_hot, emac_gcc, prng_rosc, _, _, _, _, _),
+ [103] = PINGROUP(103, WEST, rgmii, dp_hot, copy_phase, qdss_cti, _, _, _, _, _),
+ [104] = PINGROUP(104, WEST, usb_phy_ps, _, qdss_cti, dp_hot, _, _, _, _, _),
+ [105] = PINGROUP(105, SOUTH, _, _, _, _, _, _, _, _, _),
+ [106] = PINGROUP(106, EAST, mss_lte, _, _, _, _, _, _, _, _),
+ [107] = PINGROUP(107, EAST, mss_lte, _, _, _, _, _, _, _, _),
+ [108] = PINGROUP(108, SOUTH, mi2s_1, _, qdss_gpio, _, _, _, _, _, _),
+ [109] = PINGROUP(109, SOUTH, mi2s_1, _, qdss_gpio, _, _, _, _, _, _),
+ [110] = PINGROUP(110, SOUTH, wsa_data, mi2s_1, _, _, _, _, _, _, _),
+ [111] = PINGROUP(111, SOUTH, wsa_clk, mi2s_1, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, WEST, rgmii, _, qdss_cti, _, _, _, _, _, _),
+ [113] = PINGROUP(113, WEST, rgmii, edp_hot, _, qdss_cti, _, _, _, _, _),
+ [114] = PINGROUP(114, WEST, rgmii, _, _, _, _, _, _, _, _),
+ [115] = PINGROUP(115, SOUTH, ter_mi2s, atest_char, _, _, _, _, _, _, _),
+ [116] = PINGROUP(116, SOUTH, ter_mi2s, _, phase_flag, _, _, _, _, _, _),
+ [117] = PINGROUP(117, SOUTH, ter_mi2s, _, phase_flag, qdss_gpio, atest_char, _, _, _, _),
+ [118] = PINGROUP(118, SOUTH, ter_mi2s, adsp_ext, _, phase_flag, qdss_gpio, atest_char,
+ _, _, _),
+ [119] = PINGROUP(119, SOUTH, edp_lcd, _, phase_flag, qdss_gpio, atest_char, _, _, _, _),
+ [120] = PINGROUP(120, SOUTH, m_voc, qdss_gpio, atest_char, _, _, _, _, _, _),
+ [121] = PINGROUP(121, SOUTH, mclk1, atest_char, _, _, _, _, _, _, _),
+ [122] = PINGROUP(122, SOUTH, mclk2, _, _, _, _, _, _, _, _),
+ [123] = UFS_RESET(ufs_reset, 0x9f000),
+ [124] = SDC_QDSD_PINGROUP(sdc1_rclk, WEST, 0x9a000, 15, 0),
+ [125] = SDC_QDSD_PINGROUP(sdc1_clk, WEST, 0x9a000, 13, 6),
+ [126] = SDC_QDSD_PINGROUP(sdc1_cmd, WEST, 0x9a000, 11, 3),
+ [127] = SDC_QDSD_PINGROUP(sdc1_data, WEST, 0x9a000, 9, 0),
+ [128] = SDC_QDSD_PINGROUP(sdc2_clk, SOUTH, 0x98000, 14, 6),
+ [129] = SDC_QDSD_PINGROUP(sdc2_cmd, SOUTH, 0x98000, 11, 3),
+ [130] = SDC_QDSD_PINGROUP(sdc2_data, SOUTH, 0x98000, 9, 0),
+};
+
+static const struct msm_gpio_wakeirq_map qcs615_pdc_map[] = {
+ { 1, 45 }, { 3, 31 }, { 7, 55 }, { 9, 110 }, { 11, 34 },
+ { 13, 33 }, { 14, 35 }, { 17, 46 }, { 19, 48 }, { 21, 83 },
+ { 22, 36 }, { 26, 38 }, { 35, 37 }, { 39, 125 }, { 41, 47 },
+ { 47, 49 }, { 48, 51 }, { 50, 52 }, { 51, 123 }, { 55, 56 },
+ { 56, 57 }, { 57, 58 }, { 60, 60 }, { 71, 54 }, { 80, 73 },
+ { 81, 64 }, { 82, 50 }, { 83, 65 }, { 84, 92 }, { 85, 99 },
+ { 86, 67 }, { 87, 84 }, { 88, 124 }, { 89, 122 }, { 90, 69 },
+ { 92, 88 }, { 93, 75 }, { 94, 91 }, { 95, 72 }, { 96, 82 },
+ { 97, 74 }, { 98, 95 }, { 99, 94 }, { 100, 100 }, { 101, 40 },
+ { 102, 93 }, { 103, 77 }, { 104, 78 }, { 105, 96 }, { 107, 97 },
+ { 108, 111 }, { 112, 112 }, { 113, 113 }, { 117, 85 }, { 118, 102 },
+ { 119, 87 }, { 120, 114 }, { 121, 89 }, { 122, 90 },
+};
+
+static const struct msm_pinctrl_soc_data qcs615_tlmm = {
+ .pins = qcs615_pins,
+ .npins = ARRAY_SIZE(qcs615_pins),
+ .functions = qcs615_functions,
+ .nfunctions = ARRAY_SIZE(qcs615_functions),
+ .groups = qcs615_groups,
+ .ngroups = ARRAY_SIZE(qcs615_groups),
+ .ngpios = 123,
+ .tiles = qcs615_tiles,
+ .ntiles = ARRAY_SIZE(qcs615_tiles),
+ .wakeirq_map = qcs615_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(qcs615_pdc_map),
+};
+
+static const struct of_device_id qcs615_tlmm_of_match[] = {
+ {
+ .compatible = "qcom,qcs615-tlmm",
+ },
+ {},
+};
+
+static int qcs615_tlmm_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &qcs615_tlmm);
+}
+
+static struct platform_driver qcs615_tlmm_driver = {
+ .driver = {
+ .name = "qcs615-tlmm",
+ .of_match_table = qcs615_tlmm_of_match,
+ },
+ .probe = qcs615_tlmm_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init qcs615_tlmm_init(void)
+{
+ return platform_driver_register(&qcs615_tlmm_driver);
+}
+arch_initcall(qcs615_tlmm_init);
+
+static void __exit qcs615_tlmm_exit(void)
+{
+ platform_driver_unregister(&qcs615_tlmm_driver);
+}
+module_exit(qcs615_tlmm_exit);
+
+MODULE_DESCRIPTION("QTI QCS615 TLMM driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, qcs615_tlmm_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-qcs8300.c b/drivers/pinctrl/qcom/pinctrl-qcs8300.c
new file mode 100644
index 000000000000..ba6de944a859
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-qcs8300.c
@@ -0,0 +1,1246 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11)\
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10, \
+ msm_mux_##f11 /* egpio mode */ \
+ }, \
+ .nfuncs = 12, \
+ .ctl_reg = REG_SIZE * id, \
+ .io_reg = 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = 0x8 + REG_SIZE * id, \
+ .intr_status_reg = 0xc + REG_SIZE * id, \
+ .intr_target_reg = 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .egpio_enable = 12, \
+ .egpio_present = 11, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+#define UFS_RESET(pg_name, offset) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+#define QUP_I3C(qup_mode, qup_offset) \
+ { \
+ .mode = qup_mode, \
+ .offset = qup_offset, \
+ }
+
+#define QUP_I3C_6_MODE_OFFSET 0xaf000
+#define QUP_I3C_7_MODE_OFFSET 0xb0000
+#define QUP_I3C_13_MODE_OFFSET 0xb1000
+#define QUP_I3C_14_MODE_OFFSET 0xb2000
+
+static const struct pinctrl_pin_desc qcs8300_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "UFS_RESET"),
+ PINCTRL_PIN(134, "SDC1_RCLK"),
+ PINCTRL_PIN(135, "SDC1_CLK"),
+ PINCTRL_PIN(136, "SDC1_CMD"),
+ PINCTRL_PIN(137, "SDC1_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+
+static const unsigned int ufs_reset_pins[] = { 133 };
+static const unsigned int sdc1_rclk_pins[] = { 134 };
+static const unsigned int sdc1_clk_pins[] = { 135 };
+static const unsigned int sdc1_cmd_pins[] = { 136 };
+static const unsigned int sdc1_data_pins[] = { 137 };
+
+enum qcs8300_functions {
+ msm_mux_gpio,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char,
+ msm_mux_atest_usb2,
+ msm_mux_audio_ref,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async,
+ msm_mux_cci_i2c_scl,
+ msm_mux_cci_i2c_sda,
+ msm_mux_cci_timer,
+ msm_mux_cri_trng,
+ msm_mux_dbg_out,
+ msm_mux_ddr_bist,
+ msm_mux_ddr_pxi0,
+ msm_mux_ddr_pxi1,
+ msm_mux_ddr_pxi2,
+ msm_mux_ddr_pxi3,
+ msm_mux_edp0_hot,
+ msm_mux_edp0_lcd,
+ msm_mux_edp1_lcd,
+ msm_mux_egpio,
+ msm_mux_emac0_mcg0,
+ msm_mux_emac0_mcg1,
+ msm_mux_emac0_mcg2,
+ msm_mux_emac0_mcg3,
+ msm_mux_emac0_mdc,
+ msm_mux_emac0_mdio,
+ msm_mux_emac0_ptp_aux,
+ msm_mux_emac0_ptp_pps,
+ msm_mux_gcc_gp1,
+ msm_mux_gcc_gp2,
+ msm_mux_gcc_gp3,
+ msm_mux_gcc_gp4,
+ msm_mux_gcc_gp5,
+ msm_mux_hs0_mi2s,
+ msm_mux_hs1_mi2s,
+ msm_mux_hs2_mi2s,
+ msm_mux_ibi_i3c,
+ msm_mux_jitter_bist,
+ msm_mux_mdp0_vsync0,
+ msm_mux_mdp0_vsync1,
+ msm_mux_mdp0_vsync3,
+ msm_mux_mdp0_vsync6,
+ msm_mux_mdp0_vsync7,
+ msm_mux_mdp_vsync,
+ msm_mux_mi2s1_data0,
+ msm_mux_mi2s1_data1,
+ msm_mux_mi2s1_sck,
+ msm_mux_mi2s1_ws,
+ msm_mux_mi2s2_data0,
+ msm_mux_mi2s2_data1,
+ msm_mux_mi2s2_sck,
+ msm_mux_mi2s2_ws,
+ msm_mux_mi2s_mclk0,
+ msm_mux_mi2s_mclk1,
+ msm_mux_pcie0_clkreq,
+ msm_mux_pcie1_clkreq,
+ msm_mux_phase_flag,
+ msm_mux_pll_bist,
+ msm_mux_pll_clk,
+ msm_mux_prng_rosc0,
+ msm_mux_prng_rosc1,
+ msm_mux_prng_rosc2,
+ msm_mux_prng_rosc3,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_gpio,
+ msm_mux_qup0_se0,
+ msm_mux_qup0_se1,
+ msm_mux_qup0_se2,
+ msm_mux_qup0_se3,
+ msm_mux_qup0_se4,
+ msm_mux_qup0_se5,
+ msm_mux_qup0_se6,
+ msm_mux_qup0_se7,
+ msm_mux_qup1_se0,
+ msm_mux_qup1_se1,
+ msm_mux_qup1_se2,
+ msm_mux_qup1_se3,
+ msm_mux_qup1_se4,
+ msm_mux_qup1_se5,
+ msm_mux_qup1_se6,
+ msm_mux_qup1_se7,
+ msm_mux_qup2_se0,
+ msm_mux_sailss_emac0,
+ msm_mux_sailss_ospi,
+ msm_mux_sgmii_phy,
+ msm_mux_tb_trig,
+ msm_mux_tgu_ch0,
+ msm_mux_tgu_ch1,
+ msm_mux_tgu_ch2,
+ msm_mux_tgu_ch3,
+ msm_mux_tsense_pwm1,
+ msm_mux_tsense_pwm2,
+ msm_mux_tsense_pwm3,
+ msm_mux_tsense_pwm4,
+ msm_mux_usb2phy_ac,
+ msm_mux_vsense_trigger,
+ msm_mux__,
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132",
+};
+
+static const char *const aoss_cti_groups[] = {
+ "gpio37", "gpio38", "gpio39", "gpio40",
+};
+
+static const char * const atest_char_groups[] = {
+ "gpio66", "gpio70", "gpio71", "gpio72", "gpio93",
+};
+
+static const char * const atest_usb2_groups[] = {
+ "gpio63", "gpio83", "gpio92", "gpio74", "gpio84", "gpio87", "gpio67",
+ "gpio75", "gpio85", "gpio65", "gpio68", "gpio80", "gpio64", "gpio69",
+ "gpio81",
+};
+
+static const char * const audio_ref_groups[] = {
+ "gpio105",
+};
+
+static const char * const cam_mclk_groups[] = {
+ "gpio67", "gpio68", "gpio69",
+};
+
+static const char * const cci_async_groups[] = {
+ "gpio63", "gpio64", "gpio65", "gpio29", "gpio30", "gpio31",
+};
+
+static const char * const cci_i2c_scl_groups[] = {
+ "gpio58", "gpio30", "gpio60", "gpio32", "gpio62", "gpio55",
+};
+
+static const char * const cci_i2c_sda_groups[] = {
+ "gpio57", "gpio29", "gpio59", "gpio31", "gpio61", "gpio54",
+};
+
+static const char *const cci_timer_groups[] = {
+ "gpio63", "gpio64", "gpio65", "gpio49", "gpio50", "gpio19",
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+
+static const char *const cri_trng_groups[] = {
+ "gpio92", "gpio90", "gpio91",
+};
+
+static const char *const dbg_out_groups[] = {
+ "gpio75",
+};
+
+static const char * const ddr_bist_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56",
+};
+
+static const char *const ddr_pxi0_groups[] = {
+ "gpio68", "gpio69",
+};
+
+static const char *const ddr_pxi1_groups[] = {
+ "gpio49", "gpio50",
+};
+
+static const char *const ddr_pxi2_groups[] = {
+ "gpio52", "gpio83",
+};
+
+static const char *const ddr_pxi3_groups[] = {
+ "gpio80", "gpio81",
+};
+
+static const char *const edp0_hot_groups[] = {
+ "gpio94",
+};
+
+static const char *const edp0_lcd_groups[] = {
+ "gpio48",
+};
+
+static const char *const edp1_lcd_groups[] = {
+ "gpio49",
+};
+
+static const char *const egpio_groups[] = {
+ "gpio110", "gpio111", "gpio112", "gpio113", "gpio114", "gpio115",
+ "gpio116", "gpio117", "gpio118", "gpio119", "gpio120", "gpio121",
+ "gpio122", "gpio123", "gpio124", "gpio125", "gpio126", "gpio127",
+ "gpio128", "gpio129", "gpio130", "gpio131", "gpio132",
+};
+
+static const char *const emac0_mcg0_groups[] = {
+ "gpio10",
+};
+
+static const char *const emac0_mcg1_groups[] = {
+ "gpio11",
+};
+
+static const char *const emac0_mcg2_groups[] = {
+ "gpio24",
+};
+
+static const char *const emac0_mcg3_groups[] = {
+ "gpio79",
+};
+
+static const char *const emac0_mdc_groups[] = {
+ "gpio5",
+};
+
+static const char *const emac0_mdio_groups[] = {
+ "gpio6",
+};
+
+static const char * const emac0_ptp_aux_groups[] = {
+ "gpio24", "gpio31", "gpio32", "gpio79",
+};
+
+static const char * const emac0_ptp_pps_groups[] = {
+ "gpio24", "gpio29", "gpio30", "gpio79",
+};
+
+static const char *const gcc_gp1_groups[] = {
+ "gpio35", "gpio84",
+};
+
+static const char *const gcc_gp2_groups[] = {
+ "gpio36", "gpio81",
+};
+
+static const char *const gcc_gp3_groups[] = {
+ "gpio69", "gpio82",
+};
+
+static const char *const gcc_gp4_groups[] = {
+ "gpio68", "gpio83",
+};
+
+static const char *const gcc_gp5_groups[] = {
+ "gpio76", "gpio77",
+};
+
+static const char * const hs0_mi2s_groups[] = {
+ "gpio106", "gpio107", "gpio108", "gpio109",
+};
+
+static const char * const hs1_mi2s_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48",
+};
+
+static const char * const hs2_mi2s_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52",
+};
+
+static const char * const ibi_i3c_groups[] = {
+ "gpio17", "gpio18", "gpio19", "gpio20", "gpio37", "gpio38",
+ "gpio39", "gpio40",
+};
+
+static const char *const jitter_bist_groups[] = {
+ "gpio97",
+};
+
+static const char *const mdp0_vsync0_groups[] = {
+ "gpio89",
+};
+
+static const char *const mdp0_vsync1_groups[] = {
+ "gpio90",
+};
+
+static const char *const mdp0_vsync3_groups[] = {
+ "gpio91",
+};
+
+static const char *const mdp0_vsync6_groups[] = {
+ "gpio80",
+};
+
+static const char *const mdp0_vsync7_groups[] = {
+ "gpio81",
+};
+
+static const char *const mdp_vsync_groups[] = {
+ "gpio42", "gpio52", "gpio32",
+};
+
+static const char *const mi2s1_data0_groups[] = {
+ "gpio100",
+};
+
+static const char *const mi2s1_data1_groups[] = {
+ "gpio101",
+};
+
+static const char *const mi2s1_sck_groups[] = {
+ "gpio98",
+};
+
+static const char *const mi2s1_ws_groups[] = {
+ "gpio99",
+};
+
+static const char *const mi2s2_data0_groups[] = {
+ "gpio104",
+};
+
+static const char *const mi2s2_data1_groups[] = {
+ "gpio105",
+};
+
+static const char *const mi2s2_sck_groups[] = {
+ "gpio102",
+};
+
+static const char *const mi2s2_ws_groups[] = {
+ "gpio103",
+};
+
+static const char *const mi2s_mclk0_groups[] = {
+ "gpio97",
+};
+
+static const char *const mi2s_mclk1_groups[] = {
+ "gpio109",
+};
+
+static const char *const pcie0_clkreq_groups[] = {
+ "gpio1",
+};
+
+static const char *const pcie1_clkreq_groups[] = {
+ "gpio22",
+};
+
+static const char *const phase_flag_groups[] = {
+ "gpio66", "gpio56", "gpio118", "gpio117", "gpio116",
+ "gpio3", "gpio114", "gpio113", "gpio112", "gpio111",
+ "gpio110", "gpio28", "gpio55", "gpio108", "gpio107",
+ "gpio106", "gpio105", "gpio104", "gpio103", "gpio102",
+ "gpio101", "gpio100", "gpio99", "gpio125", "gpio98",
+ "gpio54", "gpio25", "gpio26", "gpio122", "gpio121",
+ "gpio120", "gpio9",
+};
+
+static const char *const pll_bist_groups[] = {
+ "gpio107",
+};
+
+static const char *const pll_clk_groups[] = {
+ "gpio74",
+};
+
+static const char *const prng_rosc0_groups[] = {
+ "gpio57",
+};
+
+static const char *const prng_rosc1_groups[] = {
+ "gpio58",
+};
+
+static const char *const prng_rosc2_groups[] = {
+ "gpio59",
+};
+
+static const char *const prng_rosc3_groups[] = {
+ "gpio60",
+};
+
+static const char *const qdss_cti_groups[] = {
+ "gpio4", "gpio5", "gpio23", "gpio24", "gpio49", "gpio50",
+ "gpio51", "gpio52",
+};
+
+static const char *const qdss_gpio_groups[] = {
+ "gpio57", "gpio58", "gpio97", "gpio106",
+ "gpio59", "gpio107", "gpio60", "gpio108",
+ "gpio36", "gpio100", "gpio61", "gpio101",
+ "gpio62", "gpio102", "gpio33", "gpio103",
+ "gpio34", "gpio104", "gpio75", "gpio105",
+ "gpio72", "gpio109", "gpio71", "gpio110",
+ "gpio70", "gpio111", "gpio63", "gpio112",
+ "gpio64", "gpio113", "gpio65", "gpio114",
+ "gpio73", "gpio98", "gpio74", "gpio99",
+};
+
+static const char *const qup0_se0_groups[] = {
+ "gpio17", "gpio18", "gpio19", "gpio20",
+};
+
+static const char *const qup0_se1_groups[] = {
+ "gpio19", "gpio20", "gpio17", "gpio18",
+};
+
+static const char *const qup0_se2_groups[] = {
+ "gpio33", "gpio34", "gpio35", "gpio36",
+};
+
+static const char *const qup0_se3_groups[] = {
+ "gpio25", "gpio26", "gpio27", "gpio28",
+};
+
+static const char *const qup0_se4_groups[] = {
+ "gpio29", "gpio30", "gpio31", "gpio32",
+};
+
+static const char *const qup0_se5_groups[] = {
+ "gpio21", "gpio22", "gpio23", "gpio24",
+};
+
+static const char *const qup0_se6_groups[] = {
+ "gpio80", "gpio81", "gpio82", "gpio83",
+};
+
+static const char *const qup0_se7_groups[] = {
+ "gpio43", "gpio44", "gpio43", "gpio44",
+};
+
+static const char *const qup1_se0_groups[] = {
+ "gpio37", "gpio38", "gpio39", "gpio40",
+};
+
+static const char *const qup1_se1_groups[] = {
+ "gpio39", "gpio40", "gpio37", "gpio38",
+};
+
+static const char *const qup1_se2_groups[] = {
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88",
+};
+
+static const char *const qup1_se3_groups[] = {
+ "gpio41", "gpio42", "gpio41", "gpio42",
+};
+
+static const char *const qup1_se4_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48",
+};
+
+static const char *const qup1_se5_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52",
+};
+
+static const char *const qup1_se6_groups[] = {
+ "gpio89", "gpio90", "gpio91", "gpio92",
+};
+
+static const char *const qup1_se7_groups[] = {
+ "gpio91", "gpio92", "gpio89", "gpio90",
+};
+
+static const char *const qup2_se0_groups[] = {
+ "gpio10", "gpio11", "gpio12", "gpio13",
+ "gpio14", "gpio15", "gpio16",
+};
+
+static const char *const sailss_emac0_groups[] = {
+ "gpio15", "gpio16",
+};
+
+static const char *const sailss_ospi_groups[] = {
+ "gpio15", "gpio16",
+};
+
+static const char *const sgmii_phy_groups[] = {
+ "gpio4",
+};
+
+static const char *const tb_trig_groups[] = {
+ "gpio14",
+};
+
+static const char *const tgu_ch0_groups[] = {
+ "gpio43",
+};
+
+static const char *const tgu_ch1_groups[] = {
+ "gpio44",
+};
+
+static const char *const tgu_ch2_groups[] = {
+ "gpio29",
+};
+
+static const char *const tgu_ch3_groups[] = {
+ "gpio30",
+};
+
+static const char *const tsense_pwm1_groups[] = {
+ "gpio79",
+};
+
+static const char *const tsense_pwm2_groups[] = {
+ "gpio78",
+};
+
+static const char *const tsense_pwm3_groups[] = {
+ "gpio77",
+};
+
+static const char *const tsense_pwm4_groups[] = {
+ "gpio76",
+};
+
+static const char *const usb2phy_ac_groups[] = {
+ "gpio7", "gpio8",
+};
+
+static const char *const vsense_trigger_groups[] = {
+ "gpio67",
+};
+
+static const struct pinfunction qcs8300_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb2),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(cci_i2c_scl),
+ MSM_PIN_FUNCTION(cci_i2c_sda),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(edp0_hot),
+ MSM_PIN_FUNCTION(edp0_lcd),
+ MSM_PIN_FUNCTION(edp1_lcd),
+ MSM_PIN_FUNCTION(egpio),
+ MSM_PIN_FUNCTION(emac0_mcg0),
+ MSM_PIN_FUNCTION(emac0_mcg1),
+ MSM_PIN_FUNCTION(emac0_mcg2),
+ MSM_PIN_FUNCTION(emac0_mcg3),
+ MSM_PIN_FUNCTION(emac0_mdc),
+ MSM_PIN_FUNCTION(emac0_mdio),
+ MSM_PIN_FUNCTION(emac0_ptp_aux),
+ MSM_PIN_FUNCTION(emac0_ptp_pps),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gcc_gp4),
+ MSM_PIN_FUNCTION(gcc_gp5),
+ MSM_PIN_FUNCTION(hs0_mi2s),
+ MSM_PIN_FUNCTION(hs1_mi2s),
+ MSM_PIN_FUNCTION(hs2_mi2s),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp0_vsync0),
+ MSM_PIN_FUNCTION(mdp0_vsync1),
+ MSM_PIN_FUNCTION(mdp0_vsync3),
+ MSM_PIN_FUNCTION(mdp0_vsync6),
+ MSM_PIN_FUNCTION(mdp0_vsync7),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mi2s1_data0),
+ MSM_PIN_FUNCTION(mi2s1_data1),
+ MSM_PIN_FUNCTION(mi2s1_sck),
+ MSM_PIN_FUNCTION(mi2s1_ws),
+ MSM_PIN_FUNCTION(mi2s2_data0),
+ MSM_PIN_FUNCTION(mi2s2_data1),
+ MSM_PIN_FUNCTION(mi2s2_sck),
+ MSM_PIN_FUNCTION(mi2s2_ws),
+ MSM_PIN_FUNCTION(mi2s_mclk0),
+ MSM_PIN_FUNCTION(mi2s_mclk1),
+ MSM_PIN_FUNCTION(pcie0_clkreq),
+ MSM_PIN_FUNCTION(pcie1_clkreq),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(qup0_se0),
+ MSM_PIN_FUNCTION(qup0_se1),
+ MSM_PIN_FUNCTION(qup0_se2),
+ MSM_PIN_FUNCTION(qup0_se3),
+ MSM_PIN_FUNCTION(qup0_se4),
+ MSM_PIN_FUNCTION(qup0_se5),
+ MSM_PIN_FUNCTION(qup0_se6),
+ MSM_PIN_FUNCTION(qup0_se7),
+ MSM_PIN_FUNCTION(qup1_se0),
+ MSM_PIN_FUNCTION(qup1_se1),
+ MSM_PIN_FUNCTION(qup1_se2),
+ MSM_PIN_FUNCTION(qup1_se3),
+ MSM_PIN_FUNCTION(qup1_se4),
+ MSM_PIN_FUNCTION(qup1_se5),
+ MSM_PIN_FUNCTION(qup1_se6),
+ MSM_PIN_FUNCTION(qup1_se7),
+ MSM_PIN_FUNCTION(qup2_se0),
+ MSM_PIN_FUNCTION(sailss_emac0),
+ MSM_PIN_FUNCTION(sailss_ospi),
+ MSM_PIN_FUNCTION(sgmii_phy),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsense_pwm3),
+ MSM_PIN_FUNCTION(tsense_pwm4),
+ MSM_PIN_FUNCTION(usb2phy_ac),
+ MSM_PIN_FUNCTION(vsense_trigger),
+};
+
+/*
+ * Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup qcs8300_groups[] = {
+ [0] = PINGROUP(0, _, _, _, _, _, _, _, _, _, _, _),
+ [1] = PINGROUP(1, pcie0_clkreq, _, _, _, _, _, _, _, _, _, _),
+ [2] = PINGROUP(2, _, _, _, _, _, _, _, _, _, _, _),
+ [3] = PINGROUP(3, phase_flag, _, _, _, _, _, _, _, _, _, _),
+ [4] = PINGROUP(4, sgmii_phy, qdss_cti, _, _, _, _, _, _, _, _, _),
+ [5] = PINGROUP(5, emac0_mdc, qdss_cti, _, _, _, _, _, _, _, _, _),
+ [6] = PINGROUP(6, emac0_mdio, _, _, _, _, _, _, _, _, _, _),
+ [7] = PINGROUP(7, usb2phy_ac, _, _, _, _, _, _, _, _, _, _),
+ [8] = PINGROUP(8, usb2phy_ac, _, _, _, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, phase_flag, _, _, _, _, _, _, _, _, _, _),
+ [10] = PINGROUP(10, qup2_se0, emac0_mcg0, _, _, _, _, _, _, _, _, _),
+ [11] = PINGROUP(11, qup2_se0, emac0_mcg1, _, _, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, qup2_se0, _, _, _, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, qup2_se0, _, _, _, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, qup2_se0, tb_trig, _, _, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, qup2_se0, _, sailss_ospi, sailss_emac0, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, qup2_se0, _, _, sailss_ospi, sailss_emac0, _, _, _, _, _, _),
+ [17] = PINGROUP(17, qup0_se0, qup0_se1, ibi_i3c, _, _, _, _, _, _, _, _),
+ [18] = PINGROUP(18, qup0_se0, qup0_se1, ibi_i3c, _, _, _, _, _, _, _, _),
+ [19] = PINGROUP(19, qup0_se1, qup0_se0, cci_timer, ibi_i3c, _, _, _, _, _, _, _),
+ [20] = PINGROUP(20, qup0_se1, qup0_se0, cci_timer, ibi_i3c, _, _, _, _, _, _, _),
+ [21] = PINGROUP(21, qup0_se5, cci_timer, _, _, _, _, _, _, _, _, _),
+ [22] = PINGROUP(22, pcie1_clkreq, qup0_se5, cci_timer, _, _, _, _, _, _, _, _),
+ [23] = PINGROUP(23, qup0_se5, cci_timer, qdss_cti, _, _, _, _, _, _, _, _),
+ [24] = PINGROUP(24, qup0_se5, emac0_ptp_aux, emac0_ptp_pps, qdss_cti,
+ emac0_mcg2, _, _, _, _, _, _),
+ [25] = PINGROUP(25, qup0_se3, phase_flag, _, _, _, _, _, _, _, _, _),
+ [26] = PINGROUP(26, qup0_se3, phase_flag, _, _, _, _, _, _, _, _, _),
+ [27] = PINGROUP(27, qup0_se3, _, _, _, _, _, _, _, _, _, _),
+ [28] = PINGROUP(28, qup0_se3, phase_flag, _, _, _, _, _, _, _, _, _),
+ [29] = PINGROUP(29, qup0_se4, cci_i2c_sda, cci_async, emac0_ptp_pps,
+ tgu_ch2, _, _, _, _, _, _),
+ [30] = PINGROUP(30, qup0_se4, cci_i2c_scl, cci_async, emac0_ptp_pps,
+ tgu_ch3, _, _, _, _, _, _),
+ [31] = PINGROUP(31, qup0_se4, cci_i2c_sda, cci_async, emac0_ptp_aux, _, _, _, _, _, _, _),
+ [32] = PINGROUP(32, qup0_se4, cci_i2c_scl, emac0_ptp_aux, mdp_vsync, _, _, _, _, _, _, _),
+ [33] = PINGROUP(33, qup0_se2, qdss_gpio, _, _, _, _, _, _, _, _, _),
+ [34] = PINGROUP(34, qup0_se2, qdss_gpio, _, _, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, qup0_se2, gcc_gp1, _, _, _, _, _, _, _, _, _),
+ [36] = PINGROUP(36, qup0_se2, gcc_gp2, qdss_gpio, _, _, _, _, _, _, _, _),
+ [37] = PINGROUP(37, qup1_se0, ibi_i3c, qup1_se1, aoss_cti, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, qup1_se0, ibi_i3c, qup1_se1, aoss_cti, _, _, _, _, _, _, _),
+ [39] = PINGROUP(39, qup1_se1, ibi_i3c, qup1_se0, aoss_cti, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, qup1_se1, ibi_i3c, qup1_se0, aoss_cti, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, qup1_se3, _, _, _, _, _, _, _, _, _, _),
+ [42] = PINGROUP(42, qup1_se3, _, mdp_vsync, _, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, qup0_se7, _, tgu_ch0, _, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, qup0_se7, _, tgu_ch1, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, qup1_se4, hs1_mi2s, _, _, _, _, _, _, _, _, _),
+ [46] = PINGROUP(46, qup1_se4, hs1_mi2s, _, _, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, qup1_se4, hs1_mi2s, _, _, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, qup1_se4, hs1_mi2s, edp0_lcd, _, _, _, _, _, _, _, _),
+ [49] = PINGROUP(49, qup1_se5, hs2_mi2s, cci_timer, qdss_cti, edp1_lcd,
+ ddr_pxi1, _, _, _, _, _),
+ [50] = PINGROUP(50, qup1_se5, hs2_mi2s, cci_timer, qdss_cti, _, ddr_pxi1, _, _, _, _, _),
+ [51] = PINGROUP(51, qup1_se5, hs2_mi2s, qdss_cti, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, qup1_se5, hs2_mi2s, qdss_cti, mdp_vsync, ddr_pxi2, _, _, _, _, _, _),
+ [53] = PINGROUP(53, ddr_bist, _, _, _, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, cci_i2c_sda, phase_flag, ddr_bist, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, cci_i2c_scl, phase_flag, ddr_bist, _, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, phase_flag, ddr_bist, _, _, _, _, _, _, _, _, _),
+ [57] = PINGROUP(57, cci_i2c_sda, prng_rosc0, qdss_gpio, _, _, _, _, _, _, _, _),
+ [58] = PINGROUP(58, cci_i2c_scl, prng_rosc1, qdss_gpio, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, cci_i2c_sda, prng_rosc2, qdss_gpio, _, _, _, _, _, _, _, _),
+ [60] = PINGROUP(60, cci_i2c_scl, prng_rosc3, qdss_gpio, _, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, cci_i2c_sda, qdss_gpio, _, _, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, cci_i2c_scl, qdss_gpio, _, _, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, cci_timer, cci_async, qdss_gpio, atest_usb2, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, cci_timer, cci_async, qdss_gpio, atest_usb2, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, cci_timer, cci_async, qdss_gpio, atest_usb2, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, phase_flag, _, atest_char, _, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, cam_mclk, vsense_trigger, atest_usb2, _, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, cam_mclk, gcc_gp4, atest_usb2, ddr_pxi0, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, cam_mclk, gcc_gp3, atest_usb2, ddr_pxi0, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, qdss_gpio, atest_char, _, _, _, _, _, _, _, _, _),
+ [71] = PINGROUP(71, qdss_gpio, atest_char, _, _, _, _, _, _, _, _, _),
+ [72] = PINGROUP(72, qdss_gpio, atest_char, _, _, _, _, _, _, _, _, _),
+ [73] = PINGROUP(73, _, qdss_gpio, _, _, _, _, _, _, _, _, _),
+ [74] = PINGROUP(74, pll_clk, qdss_gpio, atest_usb2, _, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, _, dbg_out, qdss_gpio, atest_usb2, _, _, _, _, _, _, _),
+ [76] = PINGROUP(76, gcc_gp5, tsense_pwm4, _, _, _, _, _, _, _, _, _),
+ [77] = PINGROUP(77, gcc_gp5, tsense_pwm3, _, _, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, tsense_pwm2, _, _, _, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, emac0_ptp_aux, emac0_ptp_pps, emac0_mcg3, _,
+ tsense_pwm1, _, _, _, _, _, _),
+ [80] = PINGROUP(80, qup0_se6, mdp0_vsync6, _, atest_usb2, ddr_pxi3, _, _, _, _, _, _),
+ [81] = PINGROUP(81, qup0_se6, mdp0_vsync7, gcc_gp2, _, atest_usb2, ddr_pxi3, _, _, _, _, _),
+ [82] = PINGROUP(82, qup0_se6, gcc_gp3, _, _, _, _, _, _, _, _, _),
+ [83] = PINGROUP(83, qup0_se6, gcc_gp4, _, atest_usb2, ddr_pxi2, _, _, _, _, _, _),
+ [84] = PINGROUP(84, qup1_se2, gcc_gp1, _, atest_usb2, _, _, _, _, _, _, _),
+ [85] = PINGROUP(85, qup1_se2, _, atest_usb2, _, _, _, _, _, _, _, _),
+ [86] = PINGROUP(86, qup1_se2, _, _, _, _, _, _, _, _, _, _),
+ [87] = PINGROUP(87, qup1_se2, _, atest_usb2, _, _, _, _, _, _, _, _),
+ [88] = PINGROUP(88, qup1_se2, _, _, _, _, _, _, _, _, _, _),
+ [89] = PINGROUP(89, qup1_se6, qup1_se7, mdp0_vsync0, _, _, _, _, _, _, _, _),
+ [90] = PINGROUP(90, qup1_se6, qup1_se7, mdp0_vsync1, cri_trng, _, _, _, _, _, _, _),
+ [91] = PINGROUP(91, qup1_se7, qup1_se6, mdp0_vsync3, cri_trng, _, _, _, _, _, _, _),
+ [92] = PINGROUP(92, qup1_se7, qup1_se6, cri_trng, _, atest_usb2, _, _, _, _, _, _),
+ [93] = PINGROUP(93, atest_char, _, _, _, _, _, _, _, _, _, _),
+ [94] = PINGROUP(94, edp0_hot, _, _, _, _, _, _, _, _, _, _),
+ [95] = PINGROUP(95, _, _, _, _, _, _, _, _, _, _, _),
+ [96] = PINGROUP(96, _, _, _, _, _, _, _, _, _, _, _),
+ [97] = PINGROUP(97, mi2s_mclk0, jitter_bist, qdss_gpio, _, _, _, _, _, _, _, _),
+ [98] = PINGROUP(98, mi2s1_sck, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [99] = PINGROUP(99, mi2s1_ws, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, mi2s1_data0, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [101] = PINGROUP(101, mi2s1_data1, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [102] = PINGROUP(102, mi2s2_sck, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, mi2s2_ws, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [104] = PINGROUP(104, mi2s2_data0, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, mi2s2_data1, audio_ref, phase_flag, _, qdss_gpio, _, _, _, _, _, _),
+ [106] = PINGROUP(106, hs0_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [107] = PINGROUP(107, hs0_mi2s, pll_bist, phase_flag, _, qdss_gpio, _, _, _, _, _, _),
+ [108] = PINGROUP(108, hs0_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, hs0_mi2s, mi2s_mclk1, qdss_gpio, _, _, _, _, _, _, _, _),
+ [110] = PINGROUP(110, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _, egpio),
+ [111] = PINGROUP(111, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _, egpio),
+ [112] = PINGROUP(112, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _, egpio),
+ [113] = PINGROUP(113, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _, egpio),
+ [114] = PINGROUP(114, phase_flag, _, qdss_gpio, _, _, _, _, _, _, _, egpio),
+ [115] = PINGROUP(115, _, _, _, _, _, _, _, _, _, _, egpio),
+ [116] = PINGROUP(116, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [117] = PINGROUP(117, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [118] = PINGROUP(118, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [119] = PINGROUP(119, _, _, _, _, _, _, _, _, _, _, egpio),
+ [120] = PINGROUP(120, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [121] = PINGROUP(121, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [122] = PINGROUP(122, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [123] = PINGROUP(123, _, _, _, _, _, _, _, _, _, _, egpio),
+ [124] = PINGROUP(124, _, _, _, _, _, _, _, _, _, _, egpio),
+ [125] = PINGROUP(125, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [126] = PINGROUP(126, _, _, _, _, _, _, _, _, _, _, egpio),
+ [127] = PINGROUP(127, _, _, _, _, _, _, _, _, _, _, egpio),
+ [128] = PINGROUP(128, _, _, _, _, _, _, _, _, _, _, egpio),
+ [129] = PINGROUP(129, _, _, _, _, _, _, _, _, _, _, egpio),
+ [130] = PINGROUP(130, _, _, _, _, _, _, _, _, _, _, egpio),
+ [131] = PINGROUP(131, _, _, _, _, _, _, _, _, _, _, egpio),
+ [132] = PINGROUP(132, _, _, _, _, _, _, _, _, _, _, egpio),
+ [133] = UFS_RESET(ufs_reset, 0x92000),
+ [134] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x89000, 15, 0),
+ [135] = SDC_QDSD_PINGROUP(sdc1_clk, 0x89000, 13, 6),
+ [136] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x89000, 11, 3),
+ [137] = SDC_QDSD_PINGROUP(sdc1_data, 0x89000, 9, 0),
+};
+
+static const struct msm_gpio_wakeirq_map qcs8300_pdc_map[] = {
+ { 0, 169 }, { 1, 174 }, { 2, 221 }, { 3, 176 }, { 4, 171 },
+ { 9, 198 }, { 10, 187 }, { 11, 188 }, { 13, 211 }, { 16, 203 },
+ { 17, 213 }, { 18, 209 }, { 19, 201 }, { 20, 230 }, { 21, 231 },
+ { 22, 175 }, { 23, 170 }, { 24, 232 }, { 28, 235 }, { 29, 216 },
+ { 31, 208 }, { 32, 200 }, { 36, 212 }, { 37, 177 }, { 38, 178 },
+ { 39, 184 }, { 40, 185 }, { 42, 186 }, { 44, 194 }, { 45, 173 },
+ { 48, 195 }, { 51, 215 }, { 52, 197 }, { 53, 192 }, { 56, 193 },
+ { 66, 238 }, { 67, 172 }, { 68, 182 }, { 69, 179 }, { 70, 181 },
+ { 71, 202 }, { 72, 183 }, { 73, 189 }, { 74, 196 }, { 75, 190 },
+ { 76, 191 }, { 77, 204 }, { 78, 206 }, { 79, 207 }, { 83, 214 },
+ { 84, 205 }, { 87, 237 }, { 89, 225 }, { 90, 217 }, { 91, 218 },
+ { 92, 226 }, { 93, 227 }, { 94, 228 }, { 95, 236 }, { 97, 199 },
+ { 98, 229 }, { 99, 180 }, { 100, 220 }, { 101, 239 }, { 102, 219 },
+ { 103, 233 }, { 104, 234 }, { 105, 223 }, { 129, 210 }, { 130, 222 },
+};
+
+static const struct msm_pinctrl_soc_data qcs8300_pinctrl = {
+ .pins = qcs8300_pins,
+ .npins = ARRAY_SIZE(qcs8300_pins),
+ .functions = qcs8300_functions,
+ .nfunctions = ARRAY_SIZE(qcs8300_functions),
+ .groups = qcs8300_groups,
+ .ngroups = ARRAY_SIZE(qcs8300_groups),
+ .ngpios = 133,
+ .wakeirq_map = qcs8300_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(qcs8300_pdc_map),
+ .egpio_func = 11,
+};
+
+static int qcs8300_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &qcs8300_pinctrl);
+}
+
+static const struct of_device_id qcs8300_pinctrl_of_match[] = {
+ { .compatible = "qcom,qcs8300-tlmm", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, qcs8300_pinctrl_of_match);
+
+static struct platform_driver qcs8300_pinctrl_driver = {
+ .driver = {
+ .name = "qcs8300-tlmm",
+ .of_match_table = qcs8300_pinctrl_of_match,
+ },
+ .probe = qcs8300_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init qcs8300_pinctrl_init(void)
+{
+ return platform_driver_register(&qcs8300_pinctrl_driver);
+}
+arch_initcall(qcs8300_pinctrl_init);
+
+static void __exit qcs8300_pinctrl_exit(void)
+{
+ platform_driver_unregister(&qcs8300_pinctrl_driver);
+}
+module_exit(qcs8300_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI QCS8300 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
index 4d2f6f495163..b5808fcfb13c 100644
--- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
+++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
@@ -145,7 +145,7 @@ static struct platform_driver qdf2xxx_pinctrl_driver = {
.acpi_match_table = qdf2xxx_acpi_ids,
},
.probe = qdf2xxx_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init qdf2xxx_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-qdu1000.c b/drivers/pinctrl/qcom/pinctrl-qdu1000.c
index da4f940bc8d4..47bc529ef550 100644
--- a/drivers/pinctrl/qcom/pinctrl-qdu1000.c
+++ b/drivers/pinctrl/qcom/pinctrl-qdu1000.c
@@ -1248,7 +1248,7 @@ static struct platform_driver qdu1000_tlmm_driver = {
.of_match_table = qdu1000_tlmm_of_match,
},
.probe = qdu1000_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init qdu1000_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c
index 5459c0c681a2..8fdea25d8d67 100644
--- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c
+++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c
@@ -1530,7 +1530,7 @@ static struct platform_driver sa8775p_pinctrl_driver = {
.of_match_table = sa8775p_pinctrl_of_match,
},
.probe = sa8775p_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sa8775p_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sar2130p.c b/drivers/pinctrl/qcom/pinctrl-sar2130p.c
new file mode 100644
index 000000000000..19a2e37826c7
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sar2130p.c
@@ -0,0 +1,1505 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+#define REG_SIZE 0x1000
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = REG_SIZE * id, \
+ .io_reg = 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = 0x8 + REG_SIZE * id, \
+ .intr_status_reg = 0xc + REG_SIZE * id, \
+ .intr_target_reg = 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .egpio_enable = 12, \
+ .egpio_present = 11, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 4, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+static const struct pinctrl_pin_desc sar2130p_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "GPIO_146"),
+ PINCTRL_PIN(147, "GPIO_147"),
+ PINCTRL_PIN(148, "GPIO_148"),
+ PINCTRL_PIN(149, "GPIO_149"),
+ PINCTRL_PIN(150, "GPIO_150"),
+ PINCTRL_PIN(151, "GPIO_151"),
+ PINCTRL_PIN(152, "GPIO_152"),
+ PINCTRL_PIN(153, "GPIO_153"),
+ PINCTRL_PIN(154, "GPIO_154"),
+ PINCTRL_PIN(155, "GPIO_155"),
+ PINCTRL_PIN(156, "SDC1_RCLK"),
+ PINCTRL_PIN(157, "SDC1_CLK"),
+ PINCTRL_PIN(158, "SDC1_CMD"),
+ PINCTRL_PIN(159, "SDC1_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+DECLARE_MSM_GPIO_PINS(150);
+DECLARE_MSM_GPIO_PINS(151);
+DECLARE_MSM_GPIO_PINS(152);
+DECLARE_MSM_GPIO_PINS(153);
+DECLARE_MSM_GPIO_PINS(154);
+DECLARE_MSM_GPIO_PINS(155);
+
+static const unsigned int sdc1_rclk_pins[] = { 156 };
+static const unsigned int sdc1_clk_pins[] = { 157 };
+static const unsigned int sdc1_cmd_pins[] = { 158 };
+static const unsigned int sdc1_data_pins[] = { 159 };
+
+enum sar2130p_functions {
+ msm_mux_gpio,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_usb0,
+ msm_mux_atest_usb00,
+ msm_mux_atest_usb01,
+ msm_mux_atest_usb02,
+ msm_mux_atest_usb03,
+ msm_mux_audio_ref,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async,
+ msm_mux_cci_i2c,
+ msm_mux_cci_timer0,
+ msm_mux_cci_timer1,
+ msm_mux_cci_timer2,
+ msm_mux_cci_timer3,
+ msm_mux_cci_timer4,
+ msm_mux_cri_trng,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_dbg_out,
+ msm_mux_ddr_bist,
+ msm_mux_ddr_pxi0,
+ msm_mux_ddr_pxi1,
+ msm_mux_ddr_pxi2,
+ msm_mux_ddr_pxi3,
+ msm_mux_dp0_hot,
+ msm_mux_ext_mclk0,
+ msm_mux_ext_mclk1,
+ msm_mux_gcc_gp1,
+ msm_mux_gcc_gp2,
+ msm_mux_gcc_gp3,
+ msm_mux_host2wlan_sol,
+ msm_mux_i2s0_data0,
+ msm_mux_i2s0_data1,
+ msm_mux_i2s0_sck,
+ msm_mux_i2s0_ws,
+ msm_mux_ibi_i3c,
+ msm_mux_jitter_bist,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync0,
+ msm_mux_mdp_vsync1,
+ msm_mux_mdp_vsync2,
+ msm_mux_mdp_vsync3,
+ msm_mux_pcie0_clkreqn,
+ msm_mux_pcie1_clkreqn,
+ msm_mux_phase_flag0,
+ msm_mux_phase_flag1,
+ msm_mux_phase_flag10,
+ msm_mux_phase_flag11,
+ msm_mux_phase_flag12,
+ msm_mux_phase_flag13,
+ msm_mux_phase_flag14,
+ msm_mux_phase_flag15,
+ msm_mux_phase_flag16,
+ msm_mux_phase_flag17,
+ msm_mux_phase_flag18,
+ msm_mux_phase_flag19,
+ msm_mux_phase_flag2,
+ msm_mux_phase_flag20,
+ msm_mux_phase_flag21,
+ msm_mux_phase_flag22,
+ msm_mux_phase_flag23,
+ msm_mux_phase_flag24,
+ msm_mux_phase_flag25,
+ msm_mux_phase_flag26,
+ msm_mux_phase_flag27,
+ msm_mux_phase_flag28,
+ msm_mux_phase_flag29,
+ msm_mux_phase_flag3,
+ msm_mux_phase_flag30,
+ msm_mux_phase_flag31,
+ msm_mux_phase_flag4,
+ msm_mux_phase_flag5,
+ msm_mux_phase_flag6,
+ msm_mux_phase_flag7,
+ msm_mux_phase_flag8,
+ msm_mux_phase_flag9,
+ msm_mux_pll_bist,
+ msm_mux_pll_clk,
+ msm_mux_prng_rosc0,
+ msm_mux_prng_rosc1,
+ msm_mux_prng_rosc2,
+ msm_mux_prng_rosc3,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_gpio,
+ msm_mux_qdss_gpio0,
+ msm_mux_qdss_gpio1,
+ msm_mux_qdss_gpio10,
+ msm_mux_qdss_gpio11,
+ msm_mux_qdss_gpio12,
+ msm_mux_qdss_gpio13,
+ msm_mux_qdss_gpio14,
+ msm_mux_qdss_gpio15,
+ msm_mux_qdss_gpio2,
+ msm_mux_qdss_gpio3,
+ msm_mux_qdss_gpio4,
+ msm_mux_qdss_gpio5,
+ msm_mux_qdss_gpio6,
+ msm_mux_qdss_gpio7,
+ msm_mux_qdss_gpio8,
+ msm_mux_qdss_gpio9,
+ msm_mux_qspi0,
+ msm_mux_qspi1,
+ msm_mux_qspi2,
+ msm_mux_qspi3,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs0,
+ msm_mux_qspi_cs1,
+ msm_mux_qup0,
+ msm_mux_qup1,
+ msm_mux_qup2,
+ msm_mux_qup3,
+ msm_mux_qup4,
+ msm_mux_qup5,
+ msm_mux_qup6,
+ msm_mux_qup7,
+ msm_mux_qup8,
+ msm_mux_qup9,
+ msm_mux_qup10,
+ msm_mux_qup11,
+ msm_mux_tb_trig,
+ msm_mux_tgu_ch0,
+ msm_mux_tgu_ch1,
+ msm_mux_tgu_ch2,
+ msm_mux_tgu_ch3,
+ msm_mux_tmess_prng0,
+ msm_mux_tmess_prng1,
+ msm_mux_tmess_prng2,
+ msm_mux_tmess_prng3,
+ msm_mux_tsense_pwm1,
+ msm_mux_tsense_pwm2,
+ msm_mux_usb0_phy,
+ msm_mux_vsense_trigger,
+ msm_mux__,
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+ "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+ "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
+ "gpio147", "gpio148", "gpio149", "gpio150", "gpio151", "gpio152",
+ "gpio153", "gpio154", "gpio155",
+};
+
+static const char * const aoss_cti_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+
+static const char * const atest_char_groups[] = {
+ "gpio45",
+};
+
+static const char * const atest_char0_groups[] = {
+ "gpio90",
+};
+
+static const char * const atest_char1_groups[] = {
+ "gpio89",
+};
+
+static const char * const atest_char2_groups[] = {
+ "gpio88",
+};
+
+static const char * const atest_char3_groups[] = {
+ "gpio87",
+};
+
+static const char * const atest_usb0_groups[] = {
+ "gpio26",
+};
+
+static const char * const atest_usb00_groups[] = {
+ "gpio110",
+};
+
+static const char * const atest_usb01_groups[] = {
+ "gpio109",
+};
+
+static const char * const atest_usb02_groups[] = {
+ "gpio27",
+};
+
+static const char * const atest_usb03_groups[] = {
+ "gpio60",
+};
+
+static const char * const audio_ref_groups[] = {
+ "gpio103",
+};
+
+static const char * const cam_mclk_groups[] = {
+ "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74", "gpio75",
+ "gpio76",
+};
+
+static const char * const cci_async_groups[] = {
+ "gpio80", "gpio81", "gpio82",
+};
+
+static const char * const cci_i2c_groups[] = {
+ "gpio67", "gpio68", "gpio78", "gpio79", "gpio80", "gpio81", "gpio83",
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90",
+ "gpio91", "gpio92",
+};
+
+static const char * const cci_timer0_groups[] = {
+ "gpio77",
+};
+
+static const char * const cci_timer1_groups[] = {
+ "gpio78",
+};
+
+static const char * const cci_timer2_groups[] = {
+ "gpio79",
+};
+
+static const char * const cci_timer3_groups[] = {
+ "gpio80",
+};
+
+static const char * const cci_timer4_groups[] = {
+ "gpio81",
+};
+
+static const char * const cri_trng_groups[] = {
+ "gpio60",
+};
+
+static const char * const cri_trng0_groups[] = {
+ "gpio70",
+};
+
+static const char * const cri_trng1_groups[] = {
+ "gpio71",
+};
+
+static const char * const dbg_out_groups[] = {
+ "gpio59",
+};
+
+static const char * const ddr_bist_groups[] = {
+ "gpio4", "gpio5", "gpio100", "gpio103",
+};
+
+static const char * const ddr_pxi0_groups[] = {
+ "gpio56", "gpio57",
+};
+
+static const char * const ddr_pxi1_groups[] = {
+ "gpio41", "gpio45",
+};
+
+static const char * const ddr_pxi2_groups[] = {
+ "gpio48", "gpio55",
+};
+
+static const char * const ddr_pxi3_groups[] = {
+ "gpio46", "gpio47",
+};
+
+static const char * const dp0_hot_groups[] = {
+ "gpio35", "gpio103",
+};
+
+static const char * const ext_mclk0_groups[] = {
+ "gpio104",
+};
+
+static const char * const ext_mclk1_groups[] = {
+ "gpio103",
+};
+
+static const char * const gcc_gp1_groups[] = {
+ "gpio129", "gpio132",
+};
+
+static const char * const gcc_gp2_groups[] = {
+ "gpio130", "gpio135",
+};
+
+static const char * const gcc_gp3_groups[] = {
+ "gpio131", "gpio136",
+};
+
+static const char * const host2wlan_sol_groups[] = {
+ "gpio111",
+};
+
+static const char * const i2s0_data0_groups[] = {
+ "gpio106",
+};
+
+static const char * const i2s0_data1_groups[] = {
+ "gpio107",
+};
+
+static const char * const i2s0_sck_groups[] = {
+ "gpio105",
+};
+
+static const char * const i2s0_ws_groups[] = {
+ "gpio108",
+};
+
+static const char * const ibi_i3c_groups[] = {
+ "gpio0", "gpio1", "gpio91", "gpio92",
+};
+
+static const char * const jitter_bist_groups[] = {
+ "gpio0",
+};
+
+static const char * const mdp_vsync_groups[] = {
+ "gpio12", "gpio13", "gpio41", "gpio49", "gpio50",
+};
+
+static const char * const mdp_vsync0_groups[] = {
+ "gpio49",
+};
+
+static const char * const mdp_vsync1_groups[] = {
+ "gpio49",
+};
+
+static const char * const mdp_vsync2_groups[] = {
+ "gpio50",
+};
+
+static const char * const mdp_vsync3_groups[] = {
+ "gpio50",
+};
+
+static const char * const pcie0_clkreqn_groups[] = {
+ "gpio56",
+};
+
+static const char * const pcie1_clkreqn_groups[] = {
+ "gpio59",
+};
+
+static const char * const phase_flag0_groups[] = {
+ "gpio133",
+};
+
+static const char * const phase_flag1_groups[] = {
+ "gpio128",
+};
+
+static const char * const phase_flag10_groups[] = {
+ "gpio94",
+};
+
+static const char * const phase_flag11_groups[] = {
+ "gpio93",
+};
+
+static const char * const phase_flag12_groups[] = {
+ "gpio134",
+};
+
+static const char * const phase_flag13_groups[] = {
+ "gpio139",
+};
+
+static const char * const phase_flag14_groups[] = {
+ "gpio138",
+};
+
+static const char * const phase_flag15_groups[] = {
+ "gpio137",
+};
+
+static const char * const phase_flag16_groups[] = {
+ "gpio62",
+};
+
+static const char * const phase_flag17_groups[] = {
+ "gpio61",
+};
+
+static const char * const phase_flag18_groups[] = {
+ "gpio41",
+};
+
+static const char * const phase_flag19_groups[] = {
+ "gpio23",
+};
+
+static const char * const phase_flag2_groups[] = {
+ "gpio127",
+};
+
+static const char * const phase_flag20_groups[] = {
+ "gpio22",
+};
+
+static const char * const phase_flag21_groups[] = {
+ "gpio21",
+};
+
+static const char * const phase_flag22_groups[] = {
+ "gpio19",
+};
+
+static const char * const phase_flag23_groups[] = {
+ "gpio18",
+};
+
+static const char * const phase_flag24_groups[] = {
+ "gpio17",
+};
+
+static const char * const phase_flag25_groups[] = {
+ "gpio16",
+};
+
+static const char * const phase_flag26_groups[] = {
+ "gpio13",
+};
+
+static const char * const phase_flag27_groups[] = {
+ "gpio12",
+};
+
+static const char * const phase_flag28_groups[] = {
+ "gpio3",
+};
+
+static const char * const phase_flag29_groups[] = {
+ "gpio2",
+};
+
+static const char * const phase_flag3_groups[] = {
+ "gpio126",
+};
+
+static const char * const phase_flag30_groups[] = {
+ "gpio149",
+};
+
+static const char * const phase_flag31_groups[] = {
+ "gpio148",
+};
+
+static const char * const phase_flag4_groups[] = {
+ "gpio151",
+};
+
+static const char * const phase_flag5_groups[] = {
+ "gpio150",
+};
+
+static const char * const phase_flag6_groups[] = {
+ "gpio98",
+};
+
+static const char * const phase_flag7_groups[] = {
+ "gpio97",
+};
+
+static const char * const phase_flag8_groups[] = {
+ "gpio96",
+};
+
+static const char * const phase_flag9_groups[] = {
+ "gpio95",
+};
+
+static const char * const pll_bist_groups[] = {
+ "gpio8",
+};
+
+static const char * const pll_clk_groups[] = {
+ "gpio54",
+};
+
+static const char * const prng_rosc0_groups[] = {
+ "gpio72",
+};
+
+static const char * const prng_rosc1_groups[] = {
+ "gpio73",
+};
+
+static const char * const prng_rosc2_groups[] = {
+ "gpio74",
+};
+
+static const char * const prng_rosc3_groups[] = {
+ "gpio75",
+};
+
+static const char * const qdss_cti_groups[] = {
+ "gpio28", "gpio29", "gpio36", "gpio37", "gpio38", "gpio38", "gpio47",
+ "gpio48", "gpio53", "gpio53", "gpio105", "gpio106", "gpio154",
+ "gpio155",
+};
+
+static const char * const qdss_gpio_groups[] = {
+ "gpio89", "gpio90", "gpio109", "gpio110",
+};
+
+static const char * const qdss_gpio0_groups[] = {
+ "gpio24", "gpio65",
+};
+
+static const char * const qdss_gpio1_groups[] = {
+ "gpio25", "gpio66",
+};
+
+static const char * const qdss_gpio10_groups[] = {
+ "gpio63", "gpio83",
+};
+
+static const char * const qdss_gpio11_groups[] = {
+ "gpio64", "gpio84",
+};
+
+static const char * const qdss_gpio12_groups[] = {
+ "gpio39", "gpio85",
+};
+
+static const char * const qdss_gpio13_groups[] = {
+ "gpio10", "gpio86",
+};
+
+static const char * const qdss_gpio14_groups[] = {
+ "gpio45", "gpio87",
+};
+
+static const char * const qdss_gpio15_groups[] = {
+ "gpio11", "gpio88",
+};
+
+static const char * const qdss_gpio2_groups[] = {
+ "gpio26", "gpio67",
+};
+
+static const char * const qdss_gpio3_groups[] = {
+ "gpio27", "gpio68",
+};
+
+static const char * const qdss_gpio4_groups[] = {
+ "gpio30", "gpio77",
+};
+
+static const char * const qdss_gpio5_groups[] = {
+ "gpio31", "gpio78",
+};
+
+static const char * const qdss_gpio6_groups[] = {
+ "gpio4", "gpio79",
+};
+
+static const char * const qdss_gpio7_groups[] = {
+ "gpio5", "gpio80",
+};
+
+static const char * const qdss_gpio8_groups[] = {
+ "gpio6", "gpio81",
+};
+
+static const char * const qdss_gpio9_groups[] = {
+ "gpio7", "gpio82",
+};
+
+static const char * const qspi0_groups[] = {
+ "gpio32",
+};
+
+static const char * const qspi1_groups[] = {
+ "gpio33",
+};
+
+static const char * const qspi2_groups[] = {
+ "gpio36",
+};
+
+static const char * const qspi3_groups[] = {
+ "gpio37",
+};
+
+static const char * const qspi_clk_groups[] = {
+ "gpio34",
+};
+
+static const char * const qspi_cs0_groups[] = {
+ "gpio35",
+};
+
+static const char * const qspi_cs1_groups[] = {
+ "gpio38",
+};
+
+static const char * const qup0_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio93",
+};
+
+static const char * const qup1_groups[] = {
+ "gpio2", "gpio3", "gpio61", "gpio62",
+};
+
+static const char * const qup2_groups[] = {
+ "gpio12", "gpio13", "gpio22", "gpio23",
+};
+
+static const char * const qup3_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19", "gpio41",
+};
+
+static const char * const qup4_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23", "gpio94",
+};
+
+static const char * const qup5_groups[] = {
+ "gpio95", "gpio96", "gpio97", "gpio98",
+};
+
+static const char * const qup6_groups[] = {
+ "gpio63", "gpio64", "gpio91", "gpio92",
+};
+
+static const char * const qup7_groups[] = {
+ "gpio24", "gpio25", "gpio26", "gpio27",
+};
+
+static const char * const qup8_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+
+static const char * const qup9_groups[] = {
+ "gpio34", "gpio35", "gpio109", "gpio110",
+};
+
+static const char * const qup10_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+
+static const char * const qup11_groups[] = {
+ "gpio14", "gpio15", "gpio28", "gpio30",
+};
+
+static const char * const tb_trig_groups[] = {
+ "gpio69",
+};
+
+static const char * const tgu_ch0_groups[] = {
+ "gpio20",
+};
+
+static const char * const tgu_ch1_groups[] = {
+ "gpio21",
+};
+
+static const char * const tgu_ch2_groups[] = {
+ "gpio22",
+};
+
+static const char * const tgu_ch3_groups[] = {
+ "gpio23",
+};
+
+static const char * const tmess_prng0_groups[] = {
+ "gpio80",
+};
+
+static const char * const tmess_prng1_groups[] = {
+ "gpio79",
+};
+
+static const char * const tmess_prng2_groups[] = {
+ "gpio83",
+};
+
+static const char * const tmess_prng3_groups[] = {
+ "gpio81",
+};
+
+static const char * const tsense_pwm1_groups[] = {
+ "gpio86",
+};
+
+static const char * const tsense_pwm2_groups[] = {
+ "gpio86",
+};
+
+static const char * const usb0_phy_groups[] = {
+ "gpio100",
+};
+
+static const char * const vsense_trigger_groups[] = {
+ "gpio36",
+};
+
+static const struct pinfunction sar2130p_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(qup0),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(qup1),
+ MSM_PIN_FUNCTION(phase_flag29),
+ MSM_PIN_FUNCTION(phase_flag28),
+ MSM_PIN_FUNCTION(qup10),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(qdss_gpio6),
+ MSM_PIN_FUNCTION(qdss_gpio7),
+ MSM_PIN_FUNCTION(qdss_gpio8),
+ MSM_PIN_FUNCTION(qdss_gpio9),
+ MSM_PIN_FUNCTION(qup8),
+ MSM_PIN_FUNCTION(pll_bist),
+ MSM_PIN_FUNCTION(qdss_gpio13),
+ MSM_PIN_FUNCTION(qdss_gpio15),
+ MSM_PIN_FUNCTION(qup2),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(phase_flag27),
+ MSM_PIN_FUNCTION(phase_flag26),
+ MSM_PIN_FUNCTION(qup11),
+ MSM_PIN_FUNCTION(qup3),
+ MSM_PIN_FUNCTION(phase_flag25),
+ MSM_PIN_FUNCTION(phase_flag24),
+ MSM_PIN_FUNCTION(phase_flag23),
+ MSM_PIN_FUNCTION(phase_flag22),
+ MSM_PIN_FUNCTION(qup4),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(tgu_ch0),
+ MSM_PIN_FUNCTION(phase_flag21),
+ MSM_PIN_FUNCTION(tgu_ch1),
+ MSM_PIN_FUNCTION(phase_flag20),
+ MSM_PIN_FUNCTION(tgu_ch2),
+ MSM_PIN_FUNCTION(phase_flag19),
+ MSM_PIN_FUNCTION(tgu_ch3),
+ MSM_PIN_FUNCTION(qup7),
+ MSM_PIN_FUNCTION(qdss_gpio0),
+ MSM_PIN_FUNCTION(qdss_gpio1),
+ MSM_PIN_FUNCTION(qdss_gpio2),
+ MSM_PIN_FUNCTION(atest_usb0),
+ MSM_PIN_FUNCTION(qdss_gpio3),
+ MSM_PIN_FUNCTION(atest_usb02),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qdss_gpio4),
+ MSM_PIN_FUNCTION(qdss_gpio5),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qup9),
+ MSM_PIN_FUNCTION(qspi_cs0),
+ MSM_PIN_FUNCTION(dp0_hot),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(vsense_trigger),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_cs1),
+ MSM_PIN_FUNCTION(qdss_gpio12),
+ MSM_PIN_FUNCTION(phase_flag18),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(qdss_gpio14),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(mdp_vsync0),
+ MSM_PIN_FUNCTION(mdp_vsync1),
+ MSM_PIN_FUNCTION(mdp_vsync2),
+ MSM_PIN_FUNCTION(mdp_vsync3),
+ MSM_PIN_FUNCTION(pll_clk),
+ MSM_PIN_FUNCTION(pcie0_clkreqn),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(pcie1_clkreqn),
+ MSM_PIN_FUNCTION(dbg_out),
+ MSM_PIN_FUNCTION(cri_trng),
+ MSM_PIN_FUNCTION(atest_usb03),
+ MSM_PIN_FUNCTION(phase_flag17),
+ MSM_PIN_FUNCTION(phase_flag16),
+ MSM_PIN_FUNCTION(qup6),
+ MSM_PIN_FUNCTION(qdss_gpio10),
+ MSM_PIN_FUNCTION(qdss_gpio11),
+ MSM_PIN_FUNCTION(cci_i2c),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(tb_trig),
+ MSM_PIN_FUNCTION(cri_trng0),
+ MSM_PIN_FUNCTION(cri_trng1),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(cci_timer0),
+ MSM_PIN_FUNCTION(cci_timer1),
+ MSM_PIN_FUNCTION(cci_timer2),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(cci_timer3),
+ MSM_PIN_FUNCTION(cci_async),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(cci_timer4),
+ MSM_PIN_FUNCTION(tmess_prng3),
+ MSM_PIN_FUNCTION(tmess_prng2),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(atest_char3),
+ MSM_PIN_FUNCTION(atest_char2),
+ MSM_PIN_FUNCTION(qdss_gpio),
+ MSM_PIN_FUNCTION(atest_char1),
+ MSM_PIN_FUNCTION(atest_char0),
+ MSM_PIN_FUNCTION(phase_flag11),
+ MSM_PIN_FUNCTION(phase_flag10),
+ MSM_PIN_FUNCTION(qup5),
+ MSM_PIN_FUNCTION(phase_flag9),
+ MSM_PIN_FUNCTION(phase_flag8),
+ MSM_PIN_FUNCTION(phase_flag7),
+ MSM_PIN_FUNCTION(phase_flag6),
+ MSM_PIN_FUNCTION(usb0_phy),
+ MSM_PIN_FUNCTION(ext_mclk1),
+ MSM_PIN_FUNCTION(audio_ref),
+ MSM_PIN_FUNCTION(ext_mclk0),
+ MSM_PIN_FUNCTION(i2s0_sck),
+ MSM_PIN_FUNCTION(i2s0_data0),
+ MSM_PIN_FUNCTION(i2s0_data1),
+ MSM_PIN_FUNCTION(i2s0_ws),
+ MSM_PIN_FUNCTION(atest_usb01),
+ MSM_PIN_FUNCTION(atest_usb00),
+ MSM_PIN_FUNCTION(host2wlan_sol),
+ MSM_PIN_FUNCTION(phase_flag3),
+ MSM_PIN_FUNCTION(phase_flag2),
+ MSM_PIN_FUNCTION(phase_flag1),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(phase_flag0),
+ MSM_PIN_FUNCTION(phase_flag12),
+ MSM_PIN_FUNCTION(phase_flag15),
+ MSM_PIN_FUNCTION(phase_flag14),
+ MSM_PIN_FUNCTION(phase_flag13),
+ MSM_PIN_FUNCTION(phase_flag31),
+ MSM_PIN_FUNCTION(phase_flag30),
+ MSM_PIN_FUNCTION(phase_flag5),
+ MSM_PIN_FUNCTION(phase_flag4),
+};
+
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup sar2130p_groups[] = {
+ [0] = PINGROUP(0, qup0, ibi_i3c, jitter_bist, _, _, _, _, _, _),
+ [1] = PINGROUP(1, qup0, ibi_i3c, _, _, _, _, _, _, _),
+ [2] = PINGROUP(2, qup0, qup1, phase_flag29, _, _, _, _, _, _),
+ [3] = PINGROUP(3, qup0, qup1, phase_flag28, _, _, _, _, _, _),
+ [4] = PINGROUP(4, qup10, ddr_bist, qdss_gpio6, _, _, _, _, _, _),
+ [5] = PINGROUP(5, qup10, ddr_bist, qdss_gpio7, _, _, _, _, _, _),
+ [6] = PINGROUP(6, qup10, qdss_gpio8, _, _, _, _, _, _, _),
+ [7] = PINGROUP(7, qup10, qdss_gpio9, _, _, _, _, _, _, _),
+ [8] = PINGROUP(8, qup8, pll_bist, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, qup8, _, _, _, _, _, _, _, _),
+ [10] = PINGROUP(10, qup8, qdss_gpio13, _, _, _, _, _, _, _),
+ [11] = PINGROUP(11, qup8, qdss_gpio15, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, qup2, mdp_vsync, phase_flag27, _, _, _, _, _, _),
+ [13] = PINGROUP(13, qup2, mdp_vsync, phase_flag26, _, _, _, _, _, _),
+ [14] = PINGROUP(14, qup11, _, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, qup11, _, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, qup3, phase_flag25, _, _, _, _, _, _, _),
+ [17] = PINGROUP(17, qup3, phase_flag24, _, _, _, _, _, _, _),
+ [18] = PINGROUP(18, qup3, phase_flag23, _, _, _, _, _, _, _),
+ [19] = PINGROUP(19, qup3, phase_flag22, _, _, _, _, _, _, _),
+ [20] = PINGROUP(20, qup4, aoss_cti, tgu_ch0, _, _, _, _, _, _),
+ [21] = PINGROUP(21, qup4, aoss_cti, phase_flag21, tgu_ch1, _, _, _, _, _),
+ [22] = PINGROUP(22, qup4, qup2, aoss_cti, phase_flag20, tgu_ch2, _, _, _, _),
+ [23] = PINGROUP(23, qup4, qup2, aoss_cti, phase_flag19, tgu_ch3, _, _, _, _),
+ [24] = PINGROUP(24, qup7, qdss_gpio0, _, _, _, _, _, _, _),
+ [25] = PINGROUP(25, qup7, qdss_gpio1, _, _, _, _, _, _, _),
+ [26] = PINGROUP(26, qup7, qdss_gpio2, atest_usb0, _, _, _, _, _, _),
+ [27] = PINGROUP(27, qup7, qdss_gpio3, atest_usb02, _, _, _, _, _, _),
+ [28] = PINGROUP(28, qup11, qdss_cti, _, _, _, _, _, _, _),
+ [29] = PINGROUP(29, qdss_cti, _, _, _, _, _, _, _, _),
+ [30] = PINGROUP(30, qup11, qdss_gpio4, _, _, _, _, _, _, _),
+ [31] = PINGROUP(31, qdss_gpio5, _, _, _, _, _, _, _, _),
+ [32] = PINGROUP(32, qspi0, _, _, _, _, _, _, _, _),
+ [33] = PINGROUP(33, qspi1, _, _, _, _, _, _, _, _),
+ [34] = PINGROUP(34, qspi_clk, qup9, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, qspi_cs0, qup9, dp0_hot, _, _, _, _, _, _),
+ [36] = PINGROUP(36, qspi2, qdss_cti, vsense_trigger, _, _, _, _, _, _),
+ [37] = PINGROUP(37, qspi3, qdss_cti, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, qspi_cs1, qdss_cti, qdss_cti, _, _, _, _, _, _),
+ [39] = PINGROUP(39, qdss_gpio12, _, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, _, _, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, qup3, mdp_vsync, phase_flag18, _, ddr_pxi1, _, _, _, _),
+ [42] = PINGROUP(42, _, _, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, _, _, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, _, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, qdss_gpio14, ddr_pxi1, atest_char, _, _, _, _, _, _),
+ [46] = PINGROUP(46, ddr_pxi3, _, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, qdss_cti, ddr_pxi3, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, qdss_cti, ddr_pxi2, _, _, _, _, _, _, _),
+ [49] = PINGROUP(49, mdp_vsync, mdp_vsync0, mdp_vsync1, _, _, _, _, _, _),
+ [50] = PINGROUP(50, mdp_vsync, mdp_vsync2, mdp_vsync3, _, _, _, _, _, _),
+ [51] = PINGROUP(51, _, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, _, _, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, qdss_cti, qdss_cti, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, pll_clk, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, _, ddr_pxi2, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, pcie0_clkreqn, _, ddr_pxi0, _, _, _, _, _, _),
+ [57] = PINGROUP(57, ddr_pxi0, _, _, _, _, _, _, _, _),
+ [58] = PINGROUP(58, _, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, pcie1_clkreqn, dbg_out, _, _, _, _, _, _, _),
+ [60] = PINGROUP(60, cri_trng, atest_usb03, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, qup1, phase_flag17, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, qup1, phase_flag16, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, qup6, qdss_gpio10, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, qup6, qdss_gpio11, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, qdss_gpio0, _, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, qdss_gpio1, _, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, cci_i2c, qdss_gpio2, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, cci_i2c, qdss_gpio3, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, cam_mclk, tb_trig, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, cam_mclk, cri_trng0, _, _, _, _, _, _, _),
+ [71] = PINGROUP(71, cam_mclk, cri_trng1, _, _, _, _, _, _, _),
+ [72] = PINGROUP(72, cam_mclk, prng_rosc0, _, _, _, _, _, _, _),
+ [73] = PINGROUP(73, cam_mclk, prng_rosc1, _, _, _, _, _, _, _),
+ [74] = PINGROUP(74, cam_mclk, prng_rosc2, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, cam_mclk, prng_rosc3, _, _, _, _, _, _, _),
+ [76] = PINGROUP(76, cam_mclk, _, _, _, _, _, _, _, _),
+ [77] = PINGROUP(77, cci_timer0, qdss_gpio4, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, cci_timer1, cci_i2c, qdss_gpio5, _, _, _, _, _, _),
+ [79] = PINGROUP(79, cci_timer2, cci_i2c, tmess_prng1, qdss_gpio6, _, _, _, _, _),
+ [80] = PINGROUP(80, cci_timer3, cci_i2c, cci_async, tmess_prng0, qdss_gpio7, _, _, _, _),
+ [81] = PINGROUP(81, cci_timer4, cci_i2c, cci_async, tmess_prng3, qdss_gpio8, _, _, _, _),
+ [82] = PINGROUP(82, cci_async, qdss_gpio9, _, _, _, _, _, _, _),
+ [83] = PINGROUP(83, cci_i2c, tmess_prng2, qdss_gpio10, _, _, _, _, _, _),
+ [84] = PINGROUP(84, cci_i2c, qdss_gpio11, _, _, _, _, _, _, _),
+ [85] = PINGROUP(85, cci_i2c, qdss_gpio12, _, _, _, _, _, _, _),
+ [86] = PINGROUP(86, cci_i2c, qdss_gpio13, tsense_pwm1, tsense_pwm2, _, _, _, _, _),
+ [87] = PINGROUP(87, cci_i2c, qdss_gpio14, atest_char3, _, _, _, _, _, _),
+ [88] = PINGROUP(88, cci_i2c, qdss_gpio15, atest_char2, _, _, _, _, _, _),
+ [89] = PINGROUP(89, cci_i2c, qdss_gpio, atest_char1, _, _, _, _, _, _),
+ [90] = PINGROUP(90, cci_i2c, qdss_gpio, atest_char0, _, _, _, _, _, _),
+ [91] = PINGROUP(91, cci_i2c, qup6, ibi_i3c, _, _, _, _, _, _),
+ [92] = PINGROUP(92, cci_i2c, qup6, ibi_i3c, _, _, _, _, _, _),
+ [93] = PINGROUP(93, qup0, phase_flag11, _, _, _, _, _, _, _),
+ [94] = PINGROUP(94, qup4, phase_flag10, _, _, _, _, _, _, _),
+ [95] = PINGROUP(95, qup5, phase_flag9, _, _, _, _, _, _, _),
+ [96] = PINGROUP(96, qup5, phase_flag8, _, _, _, _, _, _, _),
+ [97] = PINGROUP(97, qup5, phase_flag7, _, _, _, _, _, _, _),
+ [98] = PINGROUP(98, qup5, phase_flag6, _, _, _, _, _, _, _),
+ [99] = PINGROUP(99, _, _, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, usb0_phy, ddr_bist, _, _, _, _, _, _, _),
+ [101] = PINGROUP(101, _, _, _, _, _, _, _, _, _),
+ [102] = PINGROUP(102, _, _, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, ext_mclk1, audio_ref, dp0_hot, ddr_bist, _, _, _, _, _),
+ [104] = PINGROUP(104, ext_mclk0, _, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, i2s0_sck, _, qdss_cti, _, _, _, _, _, _),
+ [106] = PINGROUP(106, i2s0_data0, _, qdss_cti, _, _, _, _, _, _),
+ [107] = PINGROUP(107, i2s0_data1, _, _, _, _, _, _, _, _),
+ [108] = PINGROUP(108, i2s0_ws, _, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, qup9, qdss_gpio, atest_usb01, _, _, _, _, _, _),
+ [110] = PINGROUP(110, qup9, qdss_gpio, atest_usb00, _, _, _, _, _, _),
+ [111] = PINGROUP(111, host2wlan_sol, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, _, _, _, _, _, _, _, _, _),
+ [113] = PINGROUP(113, _, _, _, _, _, _, _, _, _),
+ [114] = PINGROUP(114, _, _, _, _, _, _, _, _, _),
+ [115] = PINGROUP(115, _, _, _, _, _, _, _, _, _),
+ [116] = PINGROUP(116, _, _, _, _, _, _, _, _, _),
+ [117] = PINGROUP(117, _, _, _, _, _, _, _, _, _),
+ [118] = PINGROUP(118, _, _, _, _, _, _, _, _, _),
+ [119] = PINGROUP(119, _, _, _, _, _, _, _, _, _),
+ [120] = PINGROUP(120, _, _, _, _, _, _, _, _, _),
+ [121] = PINGROUP(121, _, _, _, _, _, _, _, _, _),
+ [122] = PINGROUP(122, _, _, _, _, _, _, _, _, _),
+ [123] = PINGROUP(123, _, _, _, _, _, _, _, _, _),
+ [124] = PINGROUP(124, _, _, _, _, _, _, _, _, _),
+ [125] = PINGROUP(125, _, _, _, _, _, _, _, _, _),
+ [126] = PINGROUP(126, phase_flag3, _, _, _, _, _, _, _, _),
+ [127] = PINGROUP(127, phase_flag2, _, _, _, _, _, _, _, _),
+ [128] = PINGROUP(128, phase_flag1, _, _, _, _, _, _, _, _),
+ [129] = PINGROUP(129, gcc_gp1, _, _, _, _, _, _, _, _),
+ [130] = PINGROUP(130, gcc_gp2, _, _, _, _, _, _, _, _),
+ [131] = PINGROUP(131, gcc_gp3, _, _, _, _, _, _, _, _),
+ [132] = PINGROUP(132, gcc_gp1, _, _, _, _, _, _, _, _),
+ [133] = PINGROUP(133, phase_flag0, _, _, _, _, _, _, _, _),
+ [134] = PINGROUP(134, phase_flag12, _, _, _, _, _, _, _, _),
+ [135] = PINGROUP(135, gcc_gp2, _, _, _, _, _, _, _, _),
+ [136] = PINGROUP(136, gcc_gp3, _, _, _, _, _, _, _, _),
+ [137] = PINGROUP(137, phase_flag15, _, _, _, _, _, _, _, _),
+ [138] = PINGROUP(138, phase_flag14, _, _, _, _, _, _, _, _),
+ [139] = PINGROUP(139, phase_flag13, _, _, _, _, _, _, _, _),
+ [140] = PINGROUP(140, _, _, _, _, _, _, _, _, _),
+ [141] = PINGROUP(141, _, _, _, _, _, _, _, _, _),
+ [142] = PINGROUP(142, _, _, _, _, _, _, _, _, _),
+ [143] = PINGROUP(143, _, _, _, _, _, _, _, _, _),
+ [144] = PINGROUP(144, _, _, _, _, _, _, _, _, _),
+ [145] = PINGROUP(145, _, _, _, _, _, _, _, _, _),
+ [146] = PINGROUP(146, _, _, _, _, _, _, _, _, _),
+ [147] = PINGROUP(147, _, _, _, _, _, _, _, _, _),
+ [148] = PINGROUP(148, phase_flag31, _, _, _, _, _, _, _, _),
+ [149] = PINGROUP(149, phase_flag30, _, _, _, _, _, _, _, _),
+ [150] = PINGROUP(150, phase_flag5, _, _, _, _, _, _, _, _),
+ [151] = PINGROUP(151, phase_flag4, _, _, _, _, _, _, _, _),
+ [152] = PINGROUP(152, _, _, _, _, _, _, _, _, _),
+ [153] = PINGROUP(153, _, _, _, _, _, _, _, _, _),
+ [154] = PINGROUP(154, qdss_cti, _, _, _, _, _, _, _, _),
+ [155] = PINGROUP(155, qdss_cti, _, _, _, _, _, _, _, _),
+ [156] = SDC_QDSD_PINGROUP(sdc1_rclk, 0xa1000, 0, 0),
+ [157] = SDC_QDSD_PINGROUP(sdc1_clk, 0xa0000, 13, 6),
+ [158] = SDC_QDSD_PINGROUP(sdc1_cmd, 0xa0000, 11, 3),
+ [159] = SDC_QDSD_PINGROUP(sdc1_data, 0xa0000, 9, 0),
+};
+
+static const struct msm_gpio_wakeirq_map sar2130p_pdc_map[] = {
+ { 0, 50 }, { 3, 68 }, { 6, 88 }, { 7, 55 }, { 10, 66 }, { 11, 96 },
+ { 12, 48 }, { 13, 49 }, { 15, 62 }, { 18, 57 }, { 19, 59 }, { 23, 51 },
+ { 27, 74 }, { 28, 67 }, { 29, 84 }, { 30, 58 }, { 31, 94 }, { 32, 60 },
+ { 33, 61 }, { 35, 69 }, { 37, 70 }, { 38, 64 }, { 39, 65 }, { 40, 63 },
+ { 41, 92 }, { 42, 82 }, { 44, 83 }, { 45, 43 }, { 46, 72 }, { 47, 45 },
+ { 48, 44 }, { 49, 71 }, { 50, 87 }, { 53, 77 }, { 54, 78 },
+ { 55, 106 }, { 56, 79 }, { 57, 80 }, { 58, 107 }, { 59, 81 },
+ { 60, 89 }, { 61, 54 }, { 62, 73 }, { 63, 93 }, { 64, 86 }, { 65, 75 },
+ { 67, 42 }, { 68, 76 }, { 76, 116 }, { 77, 12 }, { 83, 13 },
+ { 91, 90 }, { 94, 95 }, { 95, 91 }, { 98, 47 }, { 100, 85 },
+ { 101, 52 }, { 102, 53 }, { 103, 97 }, { 104, 98 }, { 105, 99 },
+ { 106, 100 }, { 107, 101 }, { 108, 102 }, { 109, 103 }, { 111, 104 },
+ { 113, 46 }, { 114, 56 }, { 115, 108 }, { 116, 109 }, { 117, 110 },
+ { 118, 111 }, { 121, 112 }, { 122, 113 }, { 124, 114 }, { 127, 115 },
+ { 132, 118 }, { 134, 119 }, { 135, 120 }, { 136, 121 }, { 139, 122 },
+ { 140, 123 }, { 141, 124 }, { 143, 128 }, { 144, 129 }, { 145, 130 },
+ { 146, 131 }, { 148, 132 }, { 150, 133 }, { 151, 134 }, { 153, 135 },
+ { 155, 137 },
+};
+
+static const struct msm_pinctrl_soc_data sar2130p_tlmm = {
+ .pins = sar2130p_pins,
+ .npins = ARRAY_SIZE(sar2130p_pins),
+ .functions = sar2130p_functions,
+ .nfunctions = ARRAY_SIZE(sar2130p_functions),
+ .groups = sar2130p_groups,
+ .ngroups = ARRAY_SIZE(sar2130p_groups),
+ .ngpios = 156,
+ .wakeirq_map = sar2130p_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(sar2130p_pdc_map),
+};
+
+static int sar2130p_tlmm_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &sar2130p_tlmm);
+}
+
+static const struct of_device_id sar2130p_tlmm_of_match[] = {
+ { .compatible = "qcom,sar2130p-tlmm", .data = &sar2130p_tlmm},
+ { },
+};
+MODULE_DEVICE_TABLE(of, sar2130p_tlmm_of_match);
+
+static struct platform_driver sar2130p_tlmm_driver = {
+ .driver = {
+ .name = "sar2130p-tlmm",
+ .of_match_table = sar2130p_tlmm_of_match,
+ },
+ .probe = sar2130p_tlmm_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init sar2130p_tlmm_init(void)
+{
+ return platform_driver_register(&sar2130p_tlmm_driver);
+}
+arch_initcall(sar2130p_tlmm_init);
+
+static void __exit sar2130p_tlmm_exit(void)
+{
+ platform_driver_unregister(&sar2130p_tlmm_driver);
+}
+module_exit(sar2130p_tlmm_exit);
+
+MODULE_DESCRIPTION("QTI SAR2130P TLMM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/qcom/pinctrl-sc7180.c b/drivers/pinctrl/qcom/pinctrl-sc7180.c
index c27aaa599b91..6eb0c73791c0 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc7180.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc7180.c
@@ -1159,7 +1159,7 @@ static struct platform_driver sc7180_pinctrl_driver = {
.of_match_table = sc7180_pinctrl_of_match,
},
.probe = sc7180_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sc7180_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
index 6bb39812e1d8..1161f0a91a00 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
@@ -142,7 +142,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c
index c2db663e396e..0c10eeb60b55 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc7280.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c
@@ -1505,7 +1505,7 @@ static struct platform_driver sc7280_pinctrl_driver = {
.of_match_table = sc7280_pinctrl_of_match,
},
.probe = sc7280_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sc7280_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sc8180x.c b/drivers/pinctrl/qcom/pinctrl-sc8180x.c
index cfa7c8be9770..d6a79ad41a40 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc8180x.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc8180x.c
@@ -1720,7 +1720,7 @@ static struct platform_driver sc8180x_pinctrl_driver = {
.acpi_match_table = sc8180x_pinctrl_acpi_match,
},
.probe = sc8180x_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sc8180x_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp-lpass-lpi.c
index c0369baf3398..0e839b6aaaf4 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc8280xp-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp-lpass-lpi.c
@@ -179,7 +179,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
index 4b1c49697698..96f4fb5a5d29 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
@@ -1926,7 +1926,7 @@ static struct platform_driver sc8280xp_pinctrl_driver = {
.of_match_table = sc8280xp_pinctrl_of_match,
},
.probe = sc8280xp_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sc8280xp_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c
index b93837c00954..907e4ffca5e7 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm660.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c
@@ -1442,7 +1442,7 @@ static struct platform_driver sdm660_pinctrl_driver = {
.of_match_table = sdm660_pinctrl_of_match,
},
.probe = sdm660_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sdm660_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c
index 894c042cb524..c76183ba95e1 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm670.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c
@@ -1337,7 +1337,7 @@ static struct platform_driver sdm670_pinctrl_driver = {
.of_match_table = sdm670_pinctrl_of_match,
},
.probe = sdm670_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sdm670_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index 3f3265e0018d..cc05c415ed15 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -1351,7 +1351,7 @@ static struct platform_driver sdm845_pinctrl_driver = {
.acpi_match_table = ACPI_PTR(sdm845_pinctrl_acpi_match),
},
.probe = sdm845_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sdm845_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdx55.c b/drivers/pinctrl/qcom/pinctrl-sdx55.c
index c88b8bfcacb6..8826db9d21d0 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdx55.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdx55.c
@@ -990,7 +990,7 @@ static struct platform_driver sdx55_pinctrl_driver = {
.of_match_table = sdx55_pinctrl_of_match,
},
.probe = sdx55_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sdx55_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdx65.c b/drivers/pinctrl/qcom/pinctrl-sdx65.c
index bd44ec0fcab4..f6f319c997fc 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdx65.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdx65.c
@@ -939,7 +939,7 @@ static struct platform_driver sdx65_pinctrl_driver = {
.of_match_table = sdx65_pinctrl_of_match,
},
.probe = sdx65_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sdx65_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sdx75.c b/drivers/pinctrl/qcom/pinctrl-sdx75.c
index 396f6fc779a2..3cfe8c7f04df 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdx75.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdx75.c
@@ -1124,7 +1124,7 @@ static struct platform_driver sdx75_pinctrl_driver = {
.of_match_table = sdx75_pinctrl_of_match,
},
.probe = sdx75_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sdx75_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm4250-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm4250-lpass-lpi.c
index 2d2c636a3e20..c0e178be9cfc 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm4250-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm4250-lpass-lpi.c
@@ -227,7 +227,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm4450.c b/drivers/pinctrl/qcom/pinctrl-sm4450.c
index 27317b86d835..622f20e6f6f8 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm4450.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm4450.c
@@ -994,7 +994,7 @@ static struct platform_driver sm4450_tlmm_driver = {
.of_match_table = sm4450_tlmm_of_match,
},
.probe = sm4450_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
MODULE_DEVICE_TABLE(of, sm4450_tlmm_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm6115-lpass-lpi.c
index 316d6fc69131..b7d9186861a2 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6115-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6115-lpass-lpi.c
@@ -147,7 +147,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c
index 7ce04144b6ed..4e91c75ad952 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6115.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c
@@ -907,7 +907,7 @@ static struct platform_driver sm6115_tlmm_driver = {
.of_match_table = sm6115_tlmm_of_match,
},
.probe = sm6115_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm6115_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6125.c b/drivers/pinctrl/qcom/pinctrl-sm6125.c
index 65de34c30759..c188842047aa 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6125.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6125.c
@@ -1266,7 +1266,7 @@ static struct platform_driver sm6125_tlmm_driver = {
.of_match_table = sm6125_tlmm_of_match,
},
.probe = sm6125_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm6125_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6350.c b/drivers/pinctrl/qcom/pinctrl-sm6350.c
index 4aeb1ba43ee3..f3828c07b134 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6350.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6350.c
@@ -1373,7 +1373,7 @@ static struct platform_driver sm6350_tlmm_driver = {
.of_match_table = sm6350_tlmm_of_match,
},
.probe = sm6350_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm6350_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6375.c b/drivers/pinctrl/qcom/pinctrl-sm6375.c
index d86630d7125c..c82c8516932e 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6375.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6375.c
@@ -1516,7 +1516,7 @@ static struct platform_driver sm6375_tlmm_driver = {
.of_match_table = sm6375_tlmm_of_match,
},
.probe = sm6375_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm6375_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c
index 095a1ca75849..3c7fd8af6635 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm7150.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c
@@ -1255,7 +1255,7 @@ static struct platform_driver sm7150_tlmm_driver = {
.of_match_table = sm7150_tlmm_of_match,
},
.probe = sm7150_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm7150_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c
index f8f5bee74f1d..01aea9c70b7a 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8150.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c
@@ -1542,7 +1542,7 @@ static struct platform_driver sm8150_pinctrl_driver = {
.of_match_table = sm8150_pinctrl_of_match,
},
.probe = sm8150_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm8150_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c
index 9791d9ba5087..64494a86490e 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c
@@ -140,7 +140,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c
index 54fda77bf296..e9961a49ff98 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8250.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c
@@ -1351,7 +1351,7 @@ static struct platform_driver sm8250_pinctrl_driver = {
.of_match_table = sm8250_pinctrl_of_match,
},
.probe = sm8250_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm8250_pinctrl_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c
index 5b9a2cb216bd..7b146b4acfdf 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8350-lpass-lpi.c
@@ -142,7 +142,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c
index ac7f2820f2cb..9c69458bd910 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8350.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c
@@ -1642,7 +1642,7 @@ static struct platform_driver sm8350_tlmm_driver = {
.of_match_table = sm8350_tlmm_of_match,
},
.probe = sm8350_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm8350_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8450-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8450-lpass-lpi.c
index a028cbb49947..439f6541622e 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8450-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8450-lpass-lpi.c
@@ -208,7 +208,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8450.c b/drivers/pinctrl/qcom/pinctrl-sm8450.c
index 617286711695..d11bb1ee9e3d 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8450.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8450.c
@@ -1677,7 +1677,7 @@ static struct platform_driver sm8450_tlmm_driver = {
.of_match_table = sm8450_tlmm_of_match,
},
.probe = sm8450_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm8450_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8550-lpass-lpi.c
index 852192b044e1..73065919c8c2 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8550-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8550-lpass-lpi.c
@@ -216,7 +216,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c
index 9184e0183755..3c847d9cb5d9 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8550.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c
@@ -1762,7 +1762,7 @@ static struct platform_driver sm8550_tlmm_driver = {
.of_match_table = sm8550_tlmm_of_match,
},
.probe = sm8550_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm8550_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8650-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8650-lpass-lpi.c
index 04400c832327..f9fcedf5a65d 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8650-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8650-lpass-lpi.c
@@ -223,7 +223,7 @@ static struct platform_driver lpi_pinctrl_driver = {
.of_match_table = lpi_pinctrl_of_match,
},
.probe = lpi_pinctrl_probe,
- .remove_new = lpi_pinctrl_remove,
+ .remove = lpi_pinctrl_remove,
};
module_platform_driver(lpi_pinctrl_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8650.c b/drivers/pinctrl/qcom/pinctrl-sm8650.c
index adaddd728662..104708252d12 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8650.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8650.c
@@ -1742,7 +1742,7 @@ static struct platform_driver sm8650_tlmm_driver = {
.of_match_table = sm8650_tlmm_of_match,
},
.probe = sm8650_tlmm_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init sm8650_tlmm_init(void)
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8750.c b/drivers/pinctrl/qcom/pinctrl-sm8750.c
new file mode 100644
index 000000000000..1af11cd95fb0
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sm8750.c
@@ -0,0 +1,1729 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+#define REG_SIZE 0x1000
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10, \
+ msm_mux_##f11 /* egpio mode */ \
+ }, \
+ .nfuncs = 12, \
+ .ctl_reg = REG_SIZE * id, \
+ .io_reg = 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = 0x8 + REG_SIZE * id, \
+ .intr_status_reg = 0xc + REG_SIZE * id, \
+ .intr_target_reg = 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .egpio_enable = 12, \
+ .egpio_present = 11, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+#define UFS_RESET(pg_name, ctl, io) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = io, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+static const struct pinctrl_pin_desc sm8750_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "GPIO_146"),
+ PINCTRL_PIN(147, "GPIO_147"),
+ PINCTRL_PIN(148, "GPIO_148"),
+ PINCTRL_PIN(149, "GPIO_149"),
+ PINCTRL_PIN(150, "GPIO_150"),
+ PINCTRL_PIN(151, "GPIO_151"),
+ PINCTRL_PIN(152, "GPIO_152"),
+ PINCTRL_PIN(153, "GPIO_153"),
+ PINCTRL_PIN(154, "GPIO_154"),
+ PINCTRL_PIN(155, "GPIO_155"),
+ PINCTRL_PIN(156, "GPIO_156"),
+ PINCTRL_PIN(157, "GPIO_157"),
+ PINCTRL_PIN(158, "GPIO_158"),
+ PINCTRL_PIN(159, "GPIO_159"),
+ PINCTRL_PIN(160, "GPIO_160"),
+ PINCTRL_PIN(161, "GPIO_161"),
+ PINCTRL_PIN(162, "GPIO_162"),
+ PINCTRL_PIN(163, "GPIO_163"),
+ PINCTRL_PIN(164, "GPIO_164"),
+ PINCTRL_PIN(165, "GPIO_165"),
+ PINCTRL_PIN(166, "GPIO_166"),
+ PINCTRL_PIN(167, "GPIO_167"),
+ PINCTRL_PIN(168, "GPIO_168"),
+ PINCTRL_PIN(169, "GPIO_169"),
+ PINCTRL_PIN(170, "GPIO_170"),
+ PINCTRL_PIN(171, "GPIO_171"),
+ PINCTRL_PIN(172, "GPIO_172"),
+ PINCTRL_PIN(173, "GPIO_173"),
+ PINCTRL_PIN(174, "GPIO_174"),
+ PINCTRL_PIN(175, "GPIO_175"),
+ PINCTRL_PIN(176, "GPIO_176"),
+ PINCTRL_PIN(177, "GPIO_177"),
+ PINCTRL_PIN(178, "GPIO_178"),
+ PINCTRL_PIN(179, "GPIO_179"),
+ PINCTRL_PIN(180, "GPIO_180"),
+ PINCTRL_PIN(181, "GPIO_181"),
+ PINCTRL_PIN(182, "GPIO_182"),
+ PINCTRL_PIN(183, "GPIO_183"),
+ PINCTRL_PIN(184, "GPIO_184"),
+ PINCTRL_PIN(185, "GPIO_185"),
+ PINCTRL_PIN(186, "GPIO_186"),
+ PINCTRL_PIN(187, "GPIO_187"),
+ PINCTRL_PIN(188, "GPIO_188"),
+ PINCTRL_PIN(189, "GPIO_189"),
+ PINCTRL_PIN(190, "GPIO_190"),
+ PINCTRL_PIN(191, "GPIO_191"),
+ PINCTRL_PIN(192, "GPIO_192"),
+ PINCTRL_PIN(193, "GPIO_193"),
+ PINCTRL_PIN(194, "GPIO_194"),
+ PINCTRL_PIN(195, "GPIO_195"),
+ PINCTRL_PIN(196, "GPIO_196"),
+ PINCTRL_PIN(197, "GPIO_197"),
+ PINCTRL_PIN(198, "GPIO_198"),
+ PINCTRL_PIN(199, "GPIO_199"),
+ PINCTRL_PIN(200, "GPIO_200"),
+ PINCTRL_PIN(201, "GPIO_201"),
+ PINCTRL_PIN(202, "GPIO_202"),
+ PINCTRL_PIN(203, "GPIO_203"),
+ PINCTRL_PIN(204, "GPIO_204"),
+ PINCTRL_PIN(205, "GPIO_205"),
+ PINCTRL_PIN(206, "GPIO_206"),
+ PINCTRL_PIN(207, "GPIO_207"),
+ PINCTRL_PIN(208, "GPIO_208"),
+ PINCTRL_PIN(209, "GPIO_209"),
+ PINCTRL_PIN(210, "GPIO_210"),
+ PINCTRL_PIN(211, "GPIO_211"),
+ PINCTRL_PIN(212, "GPIO_212"),
+ PINCTRL_PIN(213, "GPIO_213"),
+ PINCTRL_PIN(214, "GPIO_214"),
+ PINCTRL_PIN(215, "UFS_RESET"),
+ PINCTRL_PIN(216, "SDC2_CLK"),
+ PINCTRL_PIN(217, "SDC2_CMD"),
+ PINCTRL_PIN(218, "SDC2_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+DECLARE_MSM_GPIO_PINS(150);
+DECLARE_MSM_GPIO_PINS(151);
+DECLARE_MSM_GPIO_PINS(152);
+DECLARE_MSM_GPIO_PINS(153);
+DECLARE_MSM_GPIO_PINS(154);
+DECLARE_MSM_GPIO_PINS(155);
+DECLARE_MSM_GPIO_PINS(156);
+DECLARE_MSM_GPIO_PINS(157);
+DECLARE_MSM_GPIO_PINS(158);
+DECLARE_MSM_GPIO_PINS(159);
+DECLARE_MSM_GPIO_PINS(160);
+DECLARE_MSM_GPIO_PINS(161);
+DECLARE_MSM_GPIO_PINS(162);
+DECLARE_MSM_GPIO_PINS(163);
+DECLARE_MSM_GPIO_PINS(164);
+DECLARE_MSM_GPIO_PINS(165);
+DECLARE_MSM_GPIO_PINS(166);
+DECLARE_MSM_GPIO_PINS(167);
+DECLARE_MSM_GPIO_PINS(168);
+DECLARE_MSM_GPIO_PINS(169);
+DECLARE_MSM_GPIO_PINS(170);
+DECLARE_MSM_GPIO_PINS(171);
+DECLARE_MSM_GPIO_PINS(172);
+DECLARE_MSM_GPIO_PINS(173);
+DECLARE_MSM_GPIO_PINS(174);
+DECLARE_MSM_GPIO_PINS(175);
+DECLARE_MSM_GPIO_PINS(176);
+DECLARE_MSM_GPIO_PINS(177);
+DECLARE_MSM_GPIO_PINS(178);
+DECLARE_MSM_GPIO_PINS(179);
+DECLARE_MSM_GPIO_PINS(180);
+DECLARE_MSM_GPIO_PINS(181);
+DECLARE_MSM_GPIO_PINS(182);
+DECLARE_MSM_GPIO_PINS(183);
+DECLARE_MSM_GPIO_PINS(184);
+DECLARE_MSM_GPIO_PINS(185);
+DECLARE_MSM_GPIO_PINS(186);
+DECLARE_MSM_GPIO_PINS(187);
+DECLARE_MSM_GPIO_PINS(188);
+DECLARE_MSM_GPIO_PINS(189);
+DECLARE_MSM_GPIO_PINS(190);
+DECLARE_MSM_GPIO_PINS(191);
+DECLARE_MSM_GPIO_PINS(192);
+DECLARE_MSM_GPIO_PINS(193);
+DECLARE_MSM_GPIO_PINS(194);
+DECLARE_MSM_GPIO_PINS(195);
+DECLARE_MSM_GPIO_PINS(196);
+DECLARE_MSM_GPIO_PINS(197);
+DECLARE_MSM_GPIO_PINS(198);
+DECLARE_MSM_GPIO_PINS(199);
+DECLARE_MSM_GPIO_PINS(200);
+DECLARE_MSM_GPIO_PINS(201);
+DECLARE_MSM_GPIO_PINS(202);
+DECLARE_MSM_GPIO_PINS(203);
+DECLARE_MSM_GPIO_PINS(204);
+DECLARE_MSM_GPIO_PINS(205);
+DECLARE_MSM_GPIO_PINS(206);
+DECLARE_MSM_GPIO_PINS(207);
+DECLARE_MSM_GPIO_PINS(208);
+DECLARE_MSM_GPIO_PINS(209);
+DECLARE_MSM_GPIO_PINS(210);
+DECLARE_MSM_GPIO_PINS(211);
+DECLARE_MSM_GPIO_PINS(212);
+DECLARE_MSM_GPIO_PINS(213);
+DECLARE_MSM_GPIO_PINS(214);
+
+static const unsigned int ufs_reset_pins[] = { 215 };
+static const unsigned int sdc2_clk_pins[] = { 216 };
+static const unsigned int sdc2_cmd_pins[] = { 217 };
+static const unsigned int sdc2_data_pins[] = { 218 };
+
+enum sm8750_functions {
+ msm_mux_gpio,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char,
+ msm_mux_atest_usb,
+ msm_mux_audio_ext_mclk0,
+ msm_mux_audio_ext_mclk1,
+ msm_mux_audio_ref_clk,
+ msm_mux_cam_aon_mclk2,
+ msm_mux_cam_aon_mclk4,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async_in,
+ msm_mux_cci_i2c_scl,
+ msm_mux_cci_i2c_sda,
+ msm_mux_cci_timer,
+ msm_mux_cmu_rng,
+ msm_mux_coex_uart1_rx,
+ msm_mux_coex_uart1_tx,
+ msm_mux_coex_uart2_rx,
+ msm_mux_coex_uart2_tx,
+ msm_mux_dbg_out_clk,
+ msm_mux_ddr_bist_complete,
+ msm_mux_ddr_bist_fail,
+ msm_mux_ddr_bist_start,
+ msm_mux_ddr_bist_stop,
+ msm_mux_ddr_pxi0,
+ msm_mux_ddr_pxi1,
+ msm_mux_ddr_pxi2,
+ msm_mux_ddr_pxi3,
+ msm_mux_dp_hot,
+ msm_mux_egpio,
+ msm_mux_gcc_gp1,
+ msm_mux_gcc_gp2,
+ msm_mux_gcc_gp3,
+ msm_mux_gnss_adc0,
+ msm_mux_gnss_adc1,
+ msm_mux_i2chub0_se0,
+ msm_mux_i2chub0_se1,
+ msm_mux_i2chub0_se2,
+ msm_mux_i2chub0_se3,
+ msm_mux_i2chub0_se4,
+ msm_mux_i2chub0_se5,
+ msm_mux_i2chub0_se6,
+ msm_mux_i2chub0_se7,
+ msm_mux_i2chub0_se8,
+ msm_mux_i2chub0_se9,
+ msm_mux_i2s0_data0,
+ msm_mux_i2s0_data1,
+ msm_mux_i2s0_sck,
+ msm_mux_i2s0_ws,
+ msm_mux_i2s1_data0,
+ msm_mux_i2s1_data1,
+ msm_mux_i2s1_sck,
+ msm_mux_i2s1_ws,
+ msm_mux_ibi_i3c,
+ msm_mux_jitter_bist,
+ msm_mux_mdp_esync0_out,
+ msm_mux_mdp_esync1_out,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync0_out,
+ msm_mux_mdp_vsync1_out,
+ msm_mux_mdp_vsync2_out,
+ msm_mux_mdp_vsync3_out,
+ msm_mux_mdp_vsync5_out,
+ msm_mux_mdp_vsync_e,
+ msm_mux_nav_gpio0,
+ msm_mux_nav_gpio1,
+ msm_mux_nav_gpio2,
+ msm_mux_nav_gpio3,
+ msm_mux_pcie0_clk_req_n,
+ msm_mux_phase_flag,
+ msm_mux_pll_bist_sync,
+ msm_mux_pll_clk_aux,
+ msm_mux_prng_rosc0,
+ msm_mux_prng_rosc1,
+ msm_mux_prng_rosc2,
+ msm_mux_prng_rosc3,
+ msm_mux_qdss_cti,
+ msm_mux_qlink_big_enable,
+ msm_mux_qlink_big_request,
+ msm_mux_qlink_little_enable,
+ msm_mux_qlink_little_request,
+ msm_mux_qlink_wmss,
+ msm_mux_qspi0,
+ msm_mux_qspi1,
+ msm_mux_qspi2,
+ msm_mux_qspi3,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs,
+ msm_mux_qup1_se0,
+ msm_mux_qup1_se1,
+ msm_mux_qup1_se2,
+ msm_mux_qup1_se3,
+ msm_mux_qup1_se4,
+ msm_mux_qup1_se5,
+ msm_mux_qup1_se6,
+ msm_mux_qup1_se7,
+ msm_mux_qup2_se0,
+ msm_mux_qup2_se1,
+ msm_mux_qup2_se2,
+ msm_mux_qup2_se3,
+ msm_mux_qup2_se4,
+ msm_mux_qup2_se5,
+ msm_mux_qup2_se6,
+ msm_mux_qup2_se7,
+ msm_mux_sd_write_protect,
+ msm_mux_sdc40,
+ msm_mux_sdc41,
+ msm_mux_sdc42,
+ msm_mux_sdc43,
+ msm_mux_sdc4_clk,
+ msm_mux_sdc4_cmd,
+ msm_mux_tb_trig_sdc2,
+ msm_mux_tb_trig_sdc4,
+ msm_mux_tmess_prng0,
+ msm_mux_tmess_prng1,
+ msm_mux_tmess_prng2,
+ msm_mux_tmess_prng3,
+ msm_mux_tsense_pwm1,
+ msm_mux_tsense_pwm2,
+ msm_mux_tsense_pwm3,
+ msm_mux_tsense_pwm4,
+ msm_mux_uim0_clk,
+ msm_mux_uim0_data,
+ msm_mux_uim0_present,
+ msm_mux_uim0_reset,
+ msm_mux_uim1_clk,
+ msm_mux_uim1_data,
+ msm_mux_uim1_present,
+ msm_mux_uim1_reset,
+ msm_mux_usb1_hs,
+ msm_mux_usb_phy,
+ msm_mux_vfr_0,
+ msm_mux_vfr_1,
+ msm_mux_vsense_trigger_mirnat,
+ msm_mux_wcn_sw,
+ msm_mux_wcn_sw_ctrl,
+ msm_mux__,
+};
+
+static const char *const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5",
+ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14", "gpio15", "gpio16", "gpio17",
+ "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41",
+ "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53",
+ "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59",
+ "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65",
+ "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", "gpio71",
+ "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89",
+ "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+ "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101",
+ "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107",
+ "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113",
+ "gpio114", "gpio115", "gpio116", "gpio117", "gpio118", "gpio119",
+ "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
+ "gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131",
+ "gpio132", "gpio133", "gpio134", "gpio135", "gpio136", "gpio137",
+ "gpio138", "gpio139", "gpio140", "gpio141", "gpio142", "gpio143",
+ "gpio144", "gpio145", "gpio146", "gpio147", "gpio148", "gpio149",
+ "gpio150", "gpio151", "gpio152", "gpio153", "gpio154", "gpio155",
+ "gpio156", "gpio157", "gpio158", "gpio159", "gpio160", "gpio161",
+ "gpio162", "gpio163", "gpio164", "gpio165", "gpio166", "gpio167",
+ "gpio168", "gpio169", "gpio170", "gpio171", "gpio172", "gpio173",
+ "gpio174", "gpio175", "gpio176", "gpio177", "gpio178", "gpio179",
+ "gpio180", "gpio181", "gpio182", "gpio183", "gpio184", "gpio185",
+ "gpio186", "gpio187", "gpio188", "gpio189", "gpio190", "gpio191",
+ "gpio192", "gpio193", "gpio194", "gpio195", "gpio196", "gpio197",
+ "gpio198", "gpio199", "gpio200", "gpio201", "gpio202", "gpio203",
+ "gpio204", "gpio205", "gpio206", "gpio207", "gpio208", "gpio209",
+ "gpio210", "gpio211", "gpio212", "gpio213", "gpio214",
+};
+
+static const char *const egpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5",
+ "gpio6", "gpio7", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio105", "gpio106", "gpio107", "gpio108",
+ "gpio165", "gpio166", "gpio167", "gpio168", "gpio169", "gpio170",
+ "gpio171", "gpio172", "gpio173", "gpio174", "gpio175", "gpio176",
+ "gpio177", "gpio178", "gpio179", "gpio180", "gpio181", "gpio182",
+ "gpio183", "gpio184", "gpio185", "gpio186", "gpio187", "gpio188",
+ "gpio189", "gpio190", "gpio191", "gpio192", "gpio193", "gpio194",
+ "gpio195", "gpio196", "gpio197", "gpio198", "gpio199", "gpio200",
+ "gpio201", "gpio202", "gpio203", "gpio204", "gpio205", "gpio206",
+ "gpio207", "gpio208", "gpio209", "gpio210", "gpio211", "gpio212",
+ "gpio213", "gpio214",
+};
+
+static const char *const aoss_cti_groups[] = {
+ "gpio50", "gpio51", "gpio60", "gpio61",
+};
+
+static const char *const atest_char_groups[] = {
+ "gpio130", "gpio131", "gpio132", "gpio133", "gpio137",
+};
+
+static const char *const atest_usb_groups[] = {
+ "gpio70", "gpio71", "gpio72", "gpio73", "gpio76",
+};
+
+static const char *const audio_ext_mclk0_groups[] = {
+ "gpio125",
+};
+
+static const char *const audio_ext_mclk1_groups[] = {
+ "gpio124",
+};
+
+static const char *const audio_ref_clk_groups[] = {
+ "gpio124",
+};
+
+static const char *const cam_aon_mclk2_groups[] = {
+ "gpio91",
+};
+
+static const char *const cam_aon_mclk4_groups[] = {
+ "gpio93",
+};
+
+static const char *const cam_mclk_groups[] = {
+ "gpio89", "gpio90", "gpio92", "gpio94", "gpio95", "gpio96",
+};
+
+static const char *const cci_async_in_groups[] = {
+ "gpio10", "gpio11", "gpio15",
+};
+
+static const char *const cci_i2c_scl_groups[] = {
+ "gpio114", "gpio116", "gpio118", "gpio120", "gpio153", "gpio164",
+};
+
+static const char *const cci_i2c_sda_groups[] = {
+ "gpio111", "gpio112", "gpio113", "gpio115", "gpio117", "gpio119",
+};
+
+static const char *const cci_timer_groups[] = {
+ "gpio109", "gpio110", "gpio111", "gpio163", "gpio164",
+};
+
+static const char *const cmu_rng_groups[] = {
+ "gpio40", "gpio41", "gpio41", "gpio43", "gpio148", "gpio149",
+ "gpio150", "gpio151",
+};
+
+static const char *const coex_uart1_rx_groups[] = {
+ "gpio148",
+};
+
+static const char *const coex_uart1_tx_groups[] = {
+ "gpio149",
+};
+
+static const char *const coex_uart2_rx_groups[] = {
+ "gpio150",
+};
+
+static const char *const coex_uart2_tx_groups[] = {
+ "gpio151",
+};
+
+static const char *const dbg_out_clk_groups[] = {
+ "gpio78",
+};
+
+static const char *const ddr_bist_complete_groups[] = {
+ "gpio44",
+};
+
+static const char *const ddr_bist_fail_groups[] = {
+ "gpio40",
+};
+
+static const char *const ddr_bist_start_groups[] = {
+ "gpio41",
+};
+
+static const char *const ddr_bist_stop_groups[] = {
+ "gpio45",
+};
+
+static const char *const ddr_pxi0_groups[] = {
+ "gpio54", "gpio55",
+};
+
+static const char *const ddr_pxi1_groups[] = {
+ "gpio44", "gpio45",
+};
+
+static const char *const ddr_pxi2_groups[] = {
+ "gpio43", "gpio52",
+};
+
+static const char *const ddr_pxi3_groups[] = {
+ "gpio46", "gpio53",
+};
+
+static const char *const dp_hot_groups[] = {
+ "gpio47",
+};
+
+static const char *const gcc_gp1_groups[] = {
+ "gpio86", "gpio134",
+};
+
+static const char *const gcc_gp2_groups[] = {
+ "gpio87", "gpio135",
+};
+
+static const char *const gcc_gp3_groups[] = {
+ "gpio88", "gpio136",
+};
+
+static const char *const gnss_adc0_groups[] = {
+ "gpio78", "gpio79",
+};
+
+static const char *const gnss_adc1_groups[] = {
+ "gpio77", "gpio99",
+};
+
+static const char *const i2chub0_se0_groups[] = {
+ "gpio64", "gpio65",
+};
+
+static const char *const i2chub0_se1_groups[] = {
+ "gpio66", "gpio67",
+};
+
+static const char *const i2chub0_se2_groups[] = {
+ "gpio68", "gpio69",
+};
+
+static const char *const i2chub0_se3_groups[] = {
+ "gpio70", "gpio71",
+};
+
+static const char *const i2chub0_se4_groups[] = {
+ "gpio72", "gpio73",
+};
+
+static const char *const i2chub0_se5_groups[] = {
+ "gpio74", "gpio75",
+};
+
+static const char *const i2chub0_se6_groups[] = {
+ "gpio76", "gpio77",
+};
+
+static const char *const i2chub0_se7_groups[] = {
+ "gpio82", "gpio83",
+};
+
+static const char *const i2chub0_se8_groups[] = {
+ "gpio206", "gpio207",
+};
+
+static const char *const i2chub0_se9_groups[] = {
+ "gpio80", "gpio81",
+};
+
+static const char *const i2s0_data0_groups[] = {
+ "gpio127",
+};
+
+static const char *const i2s0_data1_groups[] = {
+ "gpio128",
+};
+
+static const char *const i2s0_sck_groups[] = {
+ "gpio126",
+};
+
+static const char *const i2s0_ws_groups[] = {
+ "gpio129",
+};
+
+static const char *const i2s1_data0_groups[] = {
+ "gpio122",
+};
+
+static const char *const i2s1_data1_groups[] = {
+ "gpio124",
+};
+
+static const char *const i2s1_sck_groups[] = {
+ "gpio121",
+};
+
+static const char *const i2s1_ws_groups[] = {
+ "gpio123",
+};
+
+static const char *const ibi_i3c_groups[] = {
+ "gpio0", "gpio1", "gpio4", "gpio5", "gpio8", "gpio9",
+ "gpio12", "gpio13", "gpio28", "gpio29", "gpio32", "gpio33",
+ "gpio36", "gpio37", "gpio48", "gpio49",
+};
+
+static const char *const jitter_bist_groups[] = {
+ "gpio73",
+};
+
+static const char *const mdp_esync0_out_groups[] = {
+ "gpio88",
+};
+
+static const char *const mdp_esync1_out_groups[] = {
+ "gpio100",
+};
+
+static const char *const mdp_vsync_groups[] = {
+ "gpio86", "gpio87", "gpio97", "gpio98",
+};
+
+static const char *const mdp_vsync0_out_groups[] = {
+ "gpio86",
+};
+
+static const char *const mdp_vsync1_out_groups[] = {
+ "gpio86",
+};
+
+static const char *const mdp_vsync2_out_groups[] = {
+ "gpio87",
+};
+
+static const char *const mdp_vsync3_out_groups[] = {
+ "gpio87",
+};
+
+static const char *const mdp_vsync5_out_groups[] = {
+ "gpio87",
+};
+
+static const char *const mdp_vsync_e_groups[] = {
+ "gpio88",
+};
+
+static const char *const nav_gpio0_groups[] = {
+ "gpio154",
+};
+
+static const char *const nav_gpio1_groups[] = {
+ "gpio155",
+};
+
+static const char *const nav_gpio2_groups[] = {
+ "gpio152",
+};
+
+static const char *const nav_gpio3_groups[] = {
+ "gpio154",
+};
+
+static const char *const pcie0_clk_req_n_groups[] = {
+ "gpio103",
+};
+
+static const char *const phase_flag_groups[] = {
+ "gpio10", "gpio11", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18",
+ "gpio19", "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25",
+ "gpio26", "gpio27", "gpio28", "gpio29", "gpio31", "gpio64", "gpio65",
+ "gpio66", "gpio67", "gpio68", "gpio69", "gpio82", "gpio83", "gpio85",
+ "gpio101", "gpio102", "gpio103", "gpio104",
+};
+
+static const char *const pll_bist_sync_groups[] = {
+ "gpio104",
+};
+
+static const char *const pll_clk_aux_groups[] = {
+ "gpio95",
+};
+
+static const char *const prng_rosc0_groups[] = {
+ "gpio85",
+};
+
+static const char *const prng_rosc1_groups[] = {
+ "gpio64",
+};
+
+static const char *const prng_rosc2_groups[] = {
+ "gpio65",
+};
+
+static const char *const prng_rosc3_groups[] = {
+ "gpio66",
+};
+
+static const char *const qdss_cti_groups[] = {
+ "gpio27", "gpio31", "gpio72", "gpio73", "gpio82", "gpio83", "gpio159",
+ "gpio162",
+};
+
+static const char *const qlink_big_enable_groups[] = {
+ "gpio160",
+};
+
+static const char *const qlink_big_request_groups[] = {
+ "gpio159",
+};
+
+static const char *const qlink_little_enable_groups[] = {
+ "gpio157",
+};
+
+static const char *const qlink_little_request_groups[] = {
+ "gpio156",
+};
+
+static const char *const qlink_wmss_groups[] = {
+ "gpio158",
+};
+
+static const char *const qspi0_groups[] = {
+ "gpio52",
+};
+
+static const char *const qspi1_groups[] = {
+ "gpio53",
+};
+
+static const char *const qspi2_groups[] = {
+ "gpio55",
+};
+
+static const char *const qspi3_groups[] = {
+ "gpio56",
+};
+
+static const char *const qspi_clk_groups[] = {
+ "gpio54",
+};
+
+static const char *const qspi_cs_groups[] = {
+ "gpio57", "gpio58",
+};
+
+static const char *const qup1_se0_groups[] = {
+ "gpio32", "gpio33", "gpio34", "gpio35",
+};
+
+static const char *const qup1_se1_groups[] = {
+ "gpio36", "gpio37", "gpio38", "gpio39",
+};
+
+static const char *const qup1_se2_groups[] = {
+ "gpio40", "gpio41", "gpio42", "gpio43", "gpio134", "gpio135", "gpio136",
+};
+
+static const char *const qup1_se3_groups[] = {
+ "gpio44", "gpio45", "gpio46", "gpio47",
+};
+
+static const char *const qup1_se4_groups[] = {
+ "gpio48", "gpio49", "gpio50", "gpio51",
+};
+
+static const char *const qup1_se5_groups[] = {
+ "gpio52", "gpio53", "gpio54", "gpio55",
+};
+
+static const char *const qup1_se6_groups[] = {
+ "gpio56", "gpio57", "gpio58", "gpio59",
+};
+
+static const char *const qup1_se7_groups[] = {
+ "gpio60", "gpio61", "gpio62", "gpio63",
+};
+
+static const char *const qup2_se0_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+
+static const char *const qup2_se1_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+
+static const char *const qup2_se2_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio15",
+};
+
+static const char *const qup2_se3_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+
+static const char *const qup2_se4_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+
+static const char *const qup2_se5_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+
+static const char *const qup2_se6_groups[] = {
+ "gpio24", "gpio25", "gpio26", "gpio27",
+};
+
+static const char *const qup2_se7_groups[] = {
+ "gpio28", "gpio29", "gpio30", "gpio31",
+};
+
+static const char *const sd_write_protect_groups[] = {
+ "gpio85",
+};
+
+static const char *const sdc40_groups[] = {
+ "gpio36", "gpio49",
+};
+
+static const char *const sdc41_groups[] = {
+ "gpio37", "gpio51",
+};
+
+static const char *const sdc42_groups[] = {
+ "gpio38", "gpio60",
+};
+
+static const char *const sdc43_groups[] = {
+ "gpio39", "gpio61",
+};
+
+static const char *const sdc4_clk_groups[] = {
+ "gpio50", "gpio150",
+};
+
+static const char *const sdc4_cmd_groups[] = {
+ "gpio48", "gpio151",
+};
+
+static const char *const tb_trig_sdc2_groups[] = {
+ "gpio89",
+};
+
+static const char *const tb_trig_sdc4_groups[] = {
+ "gpio147",
+};
+
+static const char *const tmess_prng0_groups[] = {
+ "gpio85",
+};
+
+static const char *const tmess_prng1_groups[] = {
+ "gpio64",
+};
+
+static const char *const tmess_prng2_groups[] = {
+ "gpio65",
+};
+
+static const char *const tmess_prng3_groups[] = {
+ "gpio66",
+};
+
+static const char *const tsense_pwm1_groups[] = {
+ "gpio57",
+};
+
+static const char *const tsense_pwm2_groups[] = {
+ "gpio57",
+};
+
+static const char *const tsense_pwm3_groups[] = {
+ "gpio57",
+};
+
+static const char *const tsense_pwm4_groups[] = {
+ "gpio57",
+};
+
+static const char *const uim0_clk_groups[] = {
+ "gpio131",
+};
+
+static const char *const uim0_data_groups[] = {
+ "gpio130",
+};
+
+static const char *const uim0_present_groups[] = {
+ "gpio133",
+};
+
+static const char *const uim0_reset_groups[] = {
+ "gpio132",
+};
+
+static const char *const uim1_clk_groups[] = {
+ "gpio37", "gpio55", "gpio71", "gpio135",
+};
+
+static const char *const uim1_data_groups[] = {
+ "gpio134", "gpio36", "gpio54", "gpio70",
+};
+
+static const char *const uim1_present_groups[] = {
+ "gpio137",
+};
+
+static const char *const uim1_reset_groups[] = {
+ "gpio39", "gpio56", "gpio72", "gpio136",
+};
+
+static const char *const usb1_hs_groups[] = {
+ "gpio79",
+};
+
+static const char *const usb_phy_groups[] = {
+ "gpio59", "gpio61",
+};
+
+static const char *const vfr_0_groups[] = {
+ "gpio150",
+};
+
+static const char *const vfr_1_groups[] = {
+ "gpio155",
+};
+
+static const char *const vsense_trigger_mirnat_groups[] = {
+ "gpio59",
+};
+
+static const char *const wcn_sw_groups[] = {
+ "gpio19",
+};
+
+static const char *const wcn_sw_ctrl_groups[] = {
+ "gpio18",
+};
+
+static const struct pinfunction sm8750_functions[] = {
+ MSM_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(audio_ext_mclk0),
+ MSM_PIN_FUNCTION(audio_ext_mclk1),
+ MSM_PIN_FUNCTION(audio_ref_clk),
+ MSM_PIN_FUNCTION(cam_aon_mclk2),
+ MSM_PIN_FUNCTION(cam_aon_mclk4),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async_in),
+ MSM_PIN_FUNCTION(cci_i2c_scl),
+ MSM_PIN_FUNCTION(cci_i2c_sda),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(cmu_rng),
+ MSM_PIN_FUNCTION(coex_uart1_rx),
+ MSM_PIN_FUNCTION(coex_uart1_tx),
+ MSM_PIN_FUNCTION(coex_uart2_rx),
+ MSM_PIN_FUNCTION(coex_uart2_tx),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist_complete),
+ MSM_PIN_FUNCTION(ddr_bist_fail),
+ MSM_PIN_FUNCTION(ddr_bist_start),
+ MSM_PIN_FUNCTION(ddr_bist_stop),
+ MSM_PIN_FUNCTION(ddr_pxi0),
+ MSM_PIN_FUNCTION(ddr_pxi1),
+ MSM_PIN_FUNCTION(ddr_pxi2),
+ MSM_PIN_FUNCTION(ddr_pxi3),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(egpio),
+ MSM_PIN_FUNCTION(gcc_gp1),
+ MSM_PIN_FUNCTION(gcc_gp2),
+ MSM_PIN_FUNCTION(gcc_gp3),
+ MSM_PIN_FUNCTION(gnss_adc0),
+ MSM_PIN_FUNCTION(gnss_adc1),
+ MSM_PIN_FUNCTION(i2chub0_se0),
+ MSM_PIN_FUNCTION(i2chub0_se1),
+ MSM_PIN_FUNCTION(i2chub0_se2),
+ MSM_PIN_FUNCTION(i2chub0_se3),
+ MSM_PIN_FUNCTION(i2chub0_se4),
+ MSM_PIN_FUNCTION(i2chub0_se5),
+ MSM_PIN_FUNCTION(i2chub0_se6),
+ MSM_PIN_FUNCTION(i2chub0_se7),
+ MSM_PIN_FUNCTION(i2chub0_se8),
+ MSM_PIN_FUNCTION(i2chub0_se9),
+ MSM_PIN_FUNCTION(i2s0_data0),
+ MSM_PIN_FUNCTION(i2s0_data1),
+ MSM_PIN_FUNCTION(i2s0_sck),
+ MSM_PIN_FUNCTION(i2s0_ws),
+ MSM_PIN_FUNCTION(i2s1_data0),
+ MSM_PIN_FUNCTION(i2s1_data1),
+ MSM_PIN_FUNCTION(i2s1_sck),
+ MSM_PIN_FUNCTION(i2s1_ws),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp_esync0_out),
+ MSM_PIN_FUNCTION(mdp_esync1_out),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync0_out),
+ MSM_PIN_FUNCTION(mdp_vsync1_out),
+ MSM_PIN_FUNCTION(mdp_vsync2_out),
+ MSM_PIN_FUNCTION(mdp_vsync3_out),
+ MSM_PIN_FUNCTION(mdp_vsync5_out),
+ MSM_PIN_FUNCTION(mdp_vsync_e),
+ MSM_PIN_FUNCTION(nav_gpio0),
+ MSM_PIN_FUNCTION(nav_gpio1),
+ MSM_PIN_FUNCTION(nav_gpio2),
+ MSM_PIN_FUNCTION(nav_gpio3),
+ MSM_PIN_FUNCTION(pcie0_clk_req_n),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist_sync),
+ MSM_PIN_FUNCTION(pll_clk_aux),
+ MSM_PIN_FUNCTION(prng_rosc0),
+ MSM_PIN_FUNCTION(prng_rosc1),
+ MSM_PIN_FUNCTION(prng_rosc2),
+ MSM_PIN_FUNCTION(prng_rosc3),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qlink_big_enable),
+ MSM_PIN_FUNCTION(qlink_big_request),
+ MSM_PIN_FUNCTION(qlink_little_enable),
+ MSM_PIN_FUNCTION(qlink_little_request),
+ MSM_PIN_FUNCTION(qlink_wmss),
+ MSM_PIN_FUNCTION(qspi0),
+ MSM_PIN_FUNCTION(qspi1),
+ MSM_PIN_FUNCTION(qspi2),
+ MSM_PIN_FUNCTION(qspi3),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup1_se0),
+ MSM_PIN_FUNCTION(qup1_se1),
+ MSM_PIN_FUNCTION(qup1_se2),
+ MSM_PIN_FUNCTION(qup1_se3),
+ MSM_PIN_FUNCTION(qup1_se4),
+ MSM_PIN_FUNCTION(qup1_se5),
+ MSM_PIN_FUNCTION(qup1_se6),
+ MSM_PIN_FUNCTION(qup1_se7),
+ MSM_PIN_FUNCTION(qup2_se0),
+ MSM_PIN_FUNCTION(qup2_se1),
+ MSM_PIN_FUNCTION(qup2_se2),
+ MSM_PIN_FUNCTION(qup2_se3),
+ MSM_PIN_FUNCTION(qup2_se4),
+ MSM_PIN_FUNCTION(qup2_se5),
+ MSM_PIN_FUNCTION(qup2_se6),
+ MSM_PIN_FUNCTION(qup2_se7),
+ MSM_PIN_FUNCTION(sd_write_protect),
+ MSM_PIN_FUNCTION(sdc40),
+ MSM_PIN_FUNCTION(sdc41),
+ MSM_PIN_FUNCTION(sdc42),
+ MSM_PIN_FUNCTION(sdc43),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(tb_trig_sdc2),
+ MSM_PIN_FUNCTION(tb_trig_sdc4),
+ MSM_PIN_FUNCTION(tmess_prng0),
+ MSM_PIN_FUNCTION(tmess_prng1),
+ MSM_PIN_FUNCTION(tmess_prng2),
+ MSM_PIN_FUNCTION(tmess_prng3),
+ MSM_PIN_FUNCTION(tsense_pwm1),
+ MSM_PIN_FUNCTION(tsense_pwm2),
+ MSM_PIN_FUNCTION(tsense_pwm3),
+ MSM_PIN_FUNCTION(tsense_pwm4),
+ MSM_PIN_FUNCTION(uim0_clk),
+ MSM_PIN_FUNCTION(uim0_data),
+ MSM_PIN_FUNCTION(uim0_present),
+ MSM_PIN_FUNCTION(uim0_reset),
+ MSM_PIN_FUNCTION(uim1_clk),
+ MSM_PIN_FUNCTION(uim1_data),
+ MSM_PIN_FUNCTION(uim1_present),
+ MSM_PIN_FUNCTION(uim1_reset),
+ MSM_PIN_FUNCTION(usb1_hs),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr_0),
+ MSM_PIN_FUNCTION(vfr_1),
+ MSM_PIN_FUNCTION(vsense_trigger_mirnat),
+ MSM_PIN_FUNCTION(wcn_sw),
+ MSM_PIN_FUNCTION(wcn_sw_ctrl),
+};
+
+/*
+ * Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup sm8750_groups[] = {
+ [0] = PINGROUP(0, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [1] = PINGROUP(1, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [2] = PINGROUP(2, qup2_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [3] = PINGROUP(3, qup2_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [4] = PINGROUP(4, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [5] = PINGROUP(5, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [6] = PINGROUP(6, qup2_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [7] = PINGROUP(7, qup2_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [8] = PINGROUP(8, qup2_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, qup2_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [10] = PINGROUP(10, qup2_se2, cci_async_in, phase_flag, _, _, _, _, _, _, _, _),
+ [11] = PINGROUP(11, qup2_se2, cci_async_in, phase_flag, _, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, qup2_se3, ibi_i3c, qup2_se2, _, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, qup2_se3, ibi_i3c, qup2_se2, _, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, qup2_se3, phase_flag, _, _, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, qup2_se3, cci_async_in, qup2_se2, phase_flag, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, qup2_se4, phase_flag, _, _, _, _, _, _, _, _, _),
+ [17] = PINGROUP(17, qup2_se4, phase_flag, _, _, _, _, _, _, _, _, _),
+ [18] = PINGROUP(18, wcn_sw_ctrl, qup2_se4, phase_flag, _, _, _, _, _, _, _, _),
+ [19] = PINGROUP(19, wcn_sw, qup2_se4, phase_flag, _, _, _, _, _, _, _, _),
+ [20] = PINGROUP(20, qup2_se5, phase_flag, _, _, _, _, _, _, _, _, _),
+ [21] = PINGROUP(21, qup2_se5, phase_flag, _, _, _, _, _, _, _, _, _),
+ [22] = PINGROUP(22, qup2_se5, phase_flag, _, _, _, _, _, _, _, _, _),
+ [23] = PINGROUP(23, qup2_se5, qup2_se5, phase_flag, _, _, _, _, _, _, _, _),
+ [24] = PINGROUP(24, qup2_se6, phase_flag, _, _, _, _, _, _, _, _, _),
+ [25] = PINGROUP(25, qup2_se6, phase_flag, _, _, _, _, _, _, _, _, _),
+ [26] = PINGROUP(26, qup2_se6, phase_flag, _, _, _, _, _, _, _, _, _),
+ [27] = PINGROUP(27, qup2_se6, qdss_cti, phase_flag, _, _, _, _, _, _, _, _),
+ [28] = PINGROUP(28, qup2_se7, ibi_i3c, phase_flag, _, _, _, _, _, _, _, _),
+ [29] = PINGROUP(29, qup2_se7, ibi_i3c, phase_flag, _, _, _, _, _, _, _, _),
+ [30] = PINGROUP(30, qup2_se7, _, _, _, _, _, _, _, _, _, _),
+ [31] = PINGROUP(31, qup2_se7, qdss_cti, phase_flag, _, _, _, _, _, _, _, _),
+ [32] = PINGROUP(32, qup1_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [33] = PINGROUP(33, qup1_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [34] = PINGROUP(34, qup1_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [35] = PINGROUP(35, qup1_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [36] = PINGROUP(36, qup1_se1, uim1_data, ibi_i3c, sdc40, _, _, _, _, _, _, egpio),
+ [37] = PINGROUP(37, qup1_se1, uim1_clk, ibi_i3c, sdc41, _, _, _, _, _, _, egpio),
+ [38] = PINGROUP(38, qup1_se1, sdc42, _, _, _, _, _, _, _, _, _),
+ [39] = PINGROUP(39, qup1_se1, uim1_reset, sdc43, _, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, qup1_se2, cmu_rng, ddr_bist_fail, _, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, qup1_se2, cmu_rng, ddr_bist_start, _, _, _, _, _, _, _, _),
+ [42] = PINGROUP(42, qup1_se2, cmu_rng, _, _, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, qup1_se2, cmu_rng, _, ddr_pxi2, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, qup1_se3, ddr_bist_complete, ddr_pxi1, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, qup1_se3, ddr_bist_stop, ddr_pxi1, _, _, _, _, _, _, _, _),
+ [46] = PINGROUP(46, qup1_se3, ddr_pxi3, _, _, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, qup1_se3, dp_hot, _, _, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, qup1_se4, ibi_i3c, sdc4_cmd, _, _, _, _, _, _, _, _),
+ [49] = PINGROUP(49, qup1_se4, ibi_i3c, sdc40, _, _, _, _, _, _, _, _),
+ [50] = PINGROUP(50, qup1_se4, aoss_cti, sdc4_clk, _, _, _, _, _, _, _, _),
+ [51] = PINGROUP(51, qup1_se4, aoss_cti, sdc41, _, _, _, _, _, _, _, _),
+ [52] = PINGROUP(52, qup1_se5, qspi0, ddr_pxi2, _, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, qup1_se5, qspi1, _, ddr_pxi3, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, qup1_se5, qspi_clk, uim1_data, ddr_pxi0, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, qup1_se5, qspi2, uim1_clk, ddr_pxi0, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, qup1_se6, qspi3, uim1_reset, _, _, _, _, _, _, _, _),
+ [57] = PINGROUP(57, qup1_se6, qspi_cs, tsense_pwm1, tsense_pwm2, tsense_pwm3, tsense_pwm4,
+ _, _, _, _, _),
+ [58] = PINGROUP(58, qup1_se6, qspi_cs, _, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, qup1_se6, usb_phy, vsense_trigger_mirnat, _, _, _, _, _, _, _, _),
+ [60] = PINGROUP(60, qup1_se7, aoss_cti, sdc42, _, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, qup1_se7, usb_phy, aoss_cti, sdc43, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, qup1_se7, _, _, _, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, qup1_se7, _, _, _, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, i2chub0_se0, prng_rosc1, tmess_prng1, phase_flag, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, i2chub0_se0, prng_rosc2, tmess_prng2, phase_flag, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, i2chub0_se1, prng_rosc3, tmess_prng3, phase_flag, _, _, _, _, _, _, _),
+ [67] = PINGROUP(67, i2chub0_se1, phase_flag, _, _, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, i2chub0_se2, phase_flag, _, _, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, i2chub0_se2, phase_flag, _, _, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, i2chub0_se3, uim1_data, _, atest_usb, _, _, _, _, _, _, _),
+ [71] = PINGROUP(71, i2chub0_se3, uim1_clk, _, atest_usb, _, _, _, _, _, _, _),
+ [72] = PINGROUP(72, i2chub0_se4, uim1_reset, qdss_cti, _, atest_usb, _, _, _, _, _, _),
+ [73] = PINGROUP(73, i2chub0_se4, qdss_cti, jitter_bist, atest_usb, _, _, _, _, _, _, _),
+ [74] = PINGROUP(74, i2chub0_se5, _, _, _, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, i2chub0_se5, _, _, _, _, _, _, _, _, _, _),
+ [76] = PINGROUP(76, i2chub0_se6, atest_usb, _, _, _, _, _, _, _, _, _),
+ [77] = PINGROUP(77, i2chub0_se6, gnss_adc1, _, _, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, dbg_out_clk, gnss_adc0, _, _, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, usb1_hs, gnss_adc0, _, _, _, _, _, _, _, _, _),
+ [80] = PINGROUP(80, i2chub0_se9, _, _, _, _, _, _, _, _, _, _),
+ [81] = PINGROUP(81, i2chub0_se9, _, _, _, _, _, _, _, _, _, _),
+ [82] = PINGROUP(82, i2chub0_se7, qdss_cti, phase_flag, _, _, _, _, _, _, _, _),
+ [83] = PINGROUP(83, i2chub0_se7, qdss_cti, phase_flag, _, _, _, _, _, _, _, _),
+ [84] = PINGROUP(84, _, _, _, _, _, _, _, _, _, _, _),
+ [85] = PINGROUP(85, sd_write_protect, prng_rosc0, tmess_prng0, phase_flag, _, _, _, _, _,
+ _, _),
+ [86] = PINGROUP(86, mdp_vsync, mdp_vsync0_out, mdp_vsync1_out, gcc_gp1, _, _, _, _, _, _,
+ _),
+ [87] = PINGROUP(87, mdp_vsync, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync5_out, gcc_gp2, _,
+ _, _, _, _, _),
+ [88] = PINGROUP(88, mdp_vsync_e, mdp_esync0_out, gcc_gp3, _, _, _, _, _, _, _, _),
+ [89] = PINGROUP(89, cam_mclk, tb_trig_sdc2, _, _, _, _, _, _, _, _, _),
+ [90] = PINGROUP(90, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [91] = PINGROUP(91, cam_aon_mclk2, _, _, _, _, _, _, _, _, _, _),
+ [92] = PINGROUP(92, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [93] = PINGROUP(93, cam_aon_mclk4, _, _, _, _, _, _, _, _, _, _),
+ [94] = PINGROUP(94, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [95] = PINGROUP(95, cam_mclk, pll_clk_aux, _, _, _, _, _, _, _, _, _),
+ [96] = PINGROUP(96, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [97] = PINGROUP(97, mdp_vsync, _, _, _, _, _, _, _, _, _, _),
+ [98] = PINGROUP(98, mdp_vsync, _, _, _, _, _, _, _, _, _, _),
+ [99] = PINGROUP(99, gnss_adc1, _, _, _, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, mdp_esync1_out, _, _, _, _, _, _, _, _, _, _),
+ [101] = PINGROUP(101, phase_flag, _, _, _, _, _, _, _, _, _, _),
+ [102] = PINGROUP(102, phase_flag, _, _, _, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, pcie0_clk_req_n, phase_flag, _, _, _, _, _, _, _, _, _),
+ [104] = PINGROUP(104, pll_bist_sync, phase_flag, _, _, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, _, _, _, _, _, _, _, _, _, _, egpio),
+ [106] = PINGROUP(106, _, _, _, _, _, _, _, _, _, _, egpio),
+ [107] = PINGROUP(107, _, _, _, _, _, _, _, _, _, _, egpio),
+ [108] = PINGROUP(108, _, _, _, _, _, _, _, _, _, _, egpio),
+ [109] = PINGROUP(109, cci_timer, _, _, _, _, _, _, _, _, _, _),
+ [110] = PINGROUP(110, cci_timer, _, _, _, _, _, _, _, _, _, _),
+ [111] = PINGROUP(111, cci_timer, cci_i2c_sda, _, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _),
+ [113] = PINGROUP(113, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _),
+ [114] = PINGROUP(114, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _),
+ [115] = PINGROUP(115, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _),
+ [116] = PINGROUP(116, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _),
+ [117] = PINGROUP(117, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _),
+ [118] = PINGROUP(118, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _),
+ [119] = PINGROUP(119, cci_i2c_sda, _, _, _, _, _, _, _, _, _, _),
+ [120] = PINGROUP(120, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _),
+ [121] = PINGROUP(121, i2s1_sck, _, _, _, _, _, _, _, _, _, _),
+ [122] = PINGROUP(122, i2s1_data0, _, _, _, _, _, _, _, _, _, _),
+ [123] = PINGROUP(123, i2s1_ws, _, _, _, _, _, _, _, _, _, _),
+ [124] = PINGROUP(124, i2s1_data1, audio_ext_mclk1, audio_ref_clk, _, _, _, _, _, _, _, _),
+ [125] = PINGROUP(125, audio_ext_mclk0, _, _, _, _, _, _, _, _, _, _),
+ [126] = PINGROUP(126, i2s0_sck, _, _, _, _, _, _, _, _, _, _),
+ [127] = PINGROUP(127, i2s0_data0, _, _, _, _, _, _, _, _, _, _),
+ [128] = PINGROUP(128, i2s0_data1, _, _, _, _, _, _, _, _, _, _),
+ [129] = PINGROUP(129, i2s0_ws, _, _, _, _, _, _, _, _, _, _),
+ [130] = PINGROUP(130, uim0_data, atest_char, _, _, _, _, _, _, _, _, _),
+ [131] = PINGROUP(131, uim0_clk, atest_char, _, _, _, _, _, _, _, _, _),
+ [132] = PINGROUP(132, uim0_reset, atest_char, _, _, _, _, _, _, _, _, _),
+ [133] = PINGROUP(133, uim0_present, atest_char, _, _, _, _, _, _, _, _, _),
+ [134] = PINGROUP(134, uim1_data, qup1_se2, gcc_gp1, _, _, _, _, _, _, _, _),
+ [135] = PINGROUP(135, uim1_clk, qup1_se2, gcc_gp2, _, _, _, _, _, _, _, _),
+ [136] = PINGROUP(136, uim1_reset, qup1_se2, gcc_gp3, _, _, _, _, _, _, _, _),
+ [137] = PINGROUP(137, uim1_present, atest_char, _, _, _, _, _, _, _, _, _),
+ [138] = PINGROUP(138, _, _, _, _, _, _, _, _, _, _, _),
+ [139] = PINGROUP(139, _, _, _, _, _, _, _, _, _, _, _),
+ [140] = PINGROUP(140, _, _, _, _, _, _, _, _, _, _, _),
+ [141] = PINGROUP(141, _, _, _, _, _, _, _, _, _, _, _),
+ [142] = PINGROUP(142, _, _, _, _, _, _, _, _, _, _, _),
+ [143] = PINGROUP(143, _, _, _, _, _, _, _, _, _, _, _),
+ [144] = PINGROUP(144, _, _, _, _, _, _, _, _, _, _, _),
+ [145] = PINGROUP(145, _, _, _, _, _, _, _, _, _, _, _),
+ [146] = PINGROUP(146, _, _, _, _, _, _, _, _, _, _, _),
+ [147] = PINGROUP(147, _, tb_trig_sdc4, _, _, _, _, _, _, _, _, _),
+ [148] = PINGROUP(148, coex_uart1_rx, cmu_rng, _, _, _, _, _, _, _, _, _),
+ [149] = PINGROUP(149, coex_uart1_tx, cmu_rng, _, _, _, _, _, _, _, _, _),
+ [150] = PINGROUP(150, _, vfr_0, coex_uart2_rx, cmu_rng, sdc4_clk, _, _, _, _, _, _),
+ [151] = PINGROUP(151, _, coex_uart2_tx, cmu_rng, sdc4_cmd, _, _, _, _, _, _, _),
+ [152] = PINGROUP(152, nav_gpio2, _, _, _, _, _, _, _, _, _, _),
+ [153] = PINGROUP(153, cci_i2c_scl, _, _, _, _, _, _, _, _, _, _),
+ [154] = PINGROUP(154, nav_gpio0, nav_gpio3, _, _, _, _, _, _, _, _, _),
+ [155] = PINGROUP(155, nav_gpio1, vfr_1, _, _, _, _, _, _, _, _, _),
+ [156] = PINGROUP(156, qlink_little_request, _, _, _, _, _, _, _, _, _, _),
+ [157] = PINGROUP(157, qlink_little_enable, _, _, _, _, _, _, _, _, _, _),
+ [158] = PINGROUP(158, qlink_wmss, _, _, _, _, _, _, _, _, _, _),
+ [159] = PINGROUP(159, qlink_big_request, qdss_cti, _, _, _, _, _, _, _, _, _),
+ [160] = PINGROUP(160, qlink_big_enable, _, _, _, _, _, _, _, _, _, _),
+ [161] = PINGROUP(161, _, _, _, _, _, _, _, _, _, _, _),
+ [162] = PINGROUP(162, qdss_cti, _, _, _, _, _, _, _, _, _, _),
+ [163] = PINGROUP(163, cci_timer, _, _, _, _, _, _, _, _, _, _),
+ [164] = PINGROUP(164, cci_timer, cci_i2c_scl, _, _, _, _, _, _, _, _, _),
+ [165] = PINGROUP(165, _, _, _, _, _, _, _, _, _, _, egpio),
+ [166] = PINGROUP(166, _, _, _, _, _, _, _, _, _, _, egpio),
+ [167] = PINGROUP(167, _, _, _, _, _, _, _, _, _, _, egpio),
+ [168] = PINGROUP(168, _, _, _, _, _, _, _, _, _, _, egpio),
+ [169] = PINGROUP(169, _, _, _, _, _, _, _, _, _, _, egpio),
+ [170] = PINGROUP(170, _, _, _, _, _, _, _, _, _, _, egpio),
+ [171] = PINGROUP(171, _, _, _, _, _, _, _, _, _, _, egpio),
+ [172] = PINGROUP(172, _, _, _, _, _, _, _, _, _, _, egpio),
+ [173] = PINGROUP(173, _, _, _, _, _, _, _, _, _, _, egpio),
+ [174] = PINGROUP(174, _, _, _, _, _, _, _, _, _, _, egpio),
+ [175] = PINGROUP(175, _, _, _, _, _, _, _, _, _, _, egpio),
+ [176] = PINGROUP(176, _, _, _, _, _, _, _, _, _, _, egpio),
+ [177] = PINGROUP(177, _, _, _, _, _, _, _, _, _, _, egpio),
+ [178] = PINGROUP(178, _, _, _, _, _, _, _, _, _, _, egpio),
+ [179] = PINGROUP(179, _, _, _, _, _, _, _, _, _, _, egpio),
+ [180] = PINGROUP(180, _, _, _, _, _, _, _, _, _, _, egpio),
+ [181] = PINGROUP(181, _, _, _, _, _, _, _, _, _, _, egpio),
+ [182] = PINGROUP(182, _, _, _, _, _, _, _, _, _, _, egpio),
+ [183] = PINGROUP(183, _, _, _, _, _, _, _, _, _, _, egpio),
+ [184] = PINGROUP(184, _, _, _, _, _, _, _, _, _, _, egpio),
+ [185] = PINGROUP(185, _, _, _, _, _, _, _, _, _, _, egpio),
+ [186] = PINGROUP(186, _, _, _, _, _, _, _, _, _, _, egpio),
+ [187] = PINGROUP(187, _, _, _, _, _, _, _, _, _, _, egpio),
+ [188] = PINGROUP(188, _, _, _, _, _, _, _, _, _, _, egpio),
+ [189] = PINGROUP(189, _, _, _, _, _, _, _, _, _, _, egpio),
+ [190] = PINGROUP(190, _, _, _, _, _, _, _, _, _, _, egpio),
+ [191] = PINGROUP(191, _, _, _, _, _, _, _, _, _, _, egpio),
+ [192] = PINGROUP(192, _, _, _, _, _, _, _, _, _, _, egpio),
+ [193] = PINGROUP(193, _, _, _, _, _, _, _, _, _, _, egpio),
+ [194] = PINGROUP(194, _, _, _, _, _, _, _, _, _, _, egpio),
+ [195] = PINGROUP(195, _, _, _, _, _, _, _, _, _, _, egpio),
+ [196] = PINGROUP(196, _, _, _, _, _, _, _, _, _, _, egpio),
+ [197] = PINGROUP(197, _, _, _, _, _, _, _, _, _, _, egpio),
+ [198] = PINGROUP(198, _, _, _, _, _, _, _, _, _, _, egpio),
+ [199] = PINGROUP(199, _, _, _, _, _, _, _, _, _, _, egpio),
+ [200] = PINGROUP(200, _, _, _, _, _, _, _, _, _, _, egpio),
+ [201] = PINGROUP(201, _, _, _, _, _, _, _, _, _, _, egpio),
+ [202] = PINGROUP(202, _, _, _, _, _, _, _, _, _, _, egpio),
+ [203] = PINGROUP(203, _, _, _, _, _, _, _, _, _, _, egpio),
+ [204] = PINGROUP(204, _, _, _, _, _, _, _, _, _, _, egpio),
+ [205] = PINGROUP(205, _, _, _, _, _, _, _, _, _, _, egpio),
+ [206] = PINGROUP(206, i2chub0_se8, _, _, _, _, _, _, _, _, _, egpio),
+ [207] = PINGROUP(207, i2chub0_se8, _, _, _, _, _, _, _, _, _, egpio),
+ [208] = PINGROUP(208, _, _, _, _, _, _, _, _, _, _, egpio),
+ [209] = PINGROUP(209, _, _, _, _, _, _, _, _, _, _, egpio),
+ [210] = PINGROUP(210, _, _, _, _, _, _, _, _, _, _, egpio),
+ [211] = PINGROUP(211, _, _, _, _, _, _, _, _, _, _, egpio),
+ [212] = PINGROUP(212, _, _, _, _, _, _, _, _, _, _, egpio),
+ [213] = PINGROUP(213, _, _, _, _, _, _, _, _, _, _, egpio),
+ [214] = PINGROUP(214, _, _, _, _, _, _, _, _, _, _, egpio),
+ [215] = UFS_RESET(ufs_reset, 0xe2004, 0xe3000),
+ [216] = SDC_QDSD_PINGROUP(sdc2_clk, 0xdb000, 14, 6),
+ [217] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xdb000, 11, 3),
+ [218] = SDC_QDSD_PINGROUP(sdc2_data, 0xdb000, 9, 0),
+};
+
+static const struct msm_gpio_wakeirq_map sm8750_pdc_map[] = {
+ { 0, 72 }, { 3, 80 }, { 4, 73 }, { 7, 74 }, { 8, 75 },
+ { 11, 76 }, { 12, 87 }, { 15, 98 }, { 18, 110 }, { 19, 79 },
+ { 23, 82 }, { 24, 83 }, { 27, 84 }, { 28, 85 }, { 31, 86 },
+ { 32, 92 }, { 35, 68 }, { 36, 93 }, { 39, 94 }, { 43, 95 },
+ { 46, 96 }, { 47, 121 }, { 48, 97 }, { 51, 118 }, { 54, 102 },
+ { 55, 71 }, { 56, 103 }, { 57, 104 }, { 59, 105 }, { 61, 81 },
+ { 63, 91 }, { 64, 77 }, { 65, 90 }, { 66, 106 }, { 67, 99 },
+ { 68, 112 }, { 69, 113 }, { 75, 114 }, { 78, 115 }, { 79, 116 },
+ { 80, 122 }, { 81, 123 }, { 84, 101 }, { 85, 124 }, { 86, 125 },
+ { 87, 126 }, { 88, 127 }, { 95, 128 }, { 96, 129 }, { 97, 100 },
+ { 98, 117 }, { 99, 78 }, { 102, 130 }, { 103, 131 }, { 104, 132 },
+ { 108, 133 }, { 133, 134 }, { 137, 67 }, { 148, 135 }, { 150, 136 },
+ { 152, 137 }, { 154, 138 }, { 155, 89 }, { 156, 139 }, { 159, 140 },
+ { 162, 109 }, { 163, 108 }, { 166, 141 }, { 169, 142 }, { 171, 143 },
+ { 172, 144 }, { 174, 145 }, { 176, 146 }, { 177, 120 }, { 181, 147 },
+ { 182, 148 }, { 185, 149 }, { 188, 111 }, { 190, 88 }, { 191, 150 },
+ { 192, 151 }, { 193, 152 }, { 196, 153 }, { 197, 154 }, { 198, 70 },
+ { 199, 119 }, { 200, 69 }, { 201, 155 }, { 202, 156 }, { 203, 157 },
+ { 204, 158 }, { 205, 107 }, { 209, 159 },
+};
+
+static const struct msm_pinctrl_soc_data sm8750_tlmm = {
+ .pins = sm8750_pins,
+ .npins = ARRAY_SIZE(sm8750_pins),
+ .functions = sm8750_functions,
+ .nfunctions = ARRAY_SIZE(sm8750_functions),
+ .groups = sm8750_groups,
+ .ngroups = ARRAY_SIZE(sm8750_groups),
+ .ngpios = 216,
+ .wakeirq_map = sm8750_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(sm8750_pdc_map),
+ .egpio_func = 11,
+};
+
+static int sm8750_tlmm_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &sm8750_tlmm);
+}
+
+static const struct of_device_id sm8750_tlmm_of_match[] = {
+ { .compatible = "qcom,sm8750-tlmm", },
+ {},
+};
+
+static struct platform_driver sm8750_tlmm_driver = {
+ .driver = {
+ .name = "sm8750-tlmm",
+ .of_match_table = sm8750_tlmm_of_match,
+ },
+ .probe = sm8750_tlmm_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init sm8750_tlmm_init(void)
+{
+ return platform_driver_register(&sm8750_tlmm_driver);
+}
+arch_initcall(sm8750_tlmm_init);
+
+static void __exit sm8750_tlmm_exit(void)
+{
+ platform_driver_unregister(&sm8750_tlmm_driver);
+}
+module_exit(sm8750_tlmm_exit);
+
+MODULE_DESCRIPTION("QTI SM8750 TLMM driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, sm8750_tlmm_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index d2dd66769aa8..0c806b8128b6 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -667,7 +667,7 @@ static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
"push-pull", "open-drain", "open-source"
};
static const char *const strengths[] = {
- "no", "high", "medium", "low"
+ "no", "low", "medium", "high"
};
pad = pctldev->desc->pins[pin].drv_data;
@@ -1169,7 +1169,7 @@ static int pmic_gpio_probe(struct platform_device *pdev)
* files which don't set the "gpio-ranges" property or systems that
* utilize ACPI the driver has to call gpiochip_add_pin_range().
*/
- if (!of_property_read_bool(dev->of_node, "gpio-ranges")) {
+ if (!of_property_present(dev->of_node, "gpio-ranges")) {
ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0,
npins);
if (ret) {
@@ -1226,6 +1226,8 @@ static const struct of_device_id pmic_gpio_of_match[] = {
{ .compatible = "qcom,pm8550ve-gpio", .data = (void *) 8 },
{ .compatible = "qcom,pm8550vs-gpio", .data = (void *) 6 },
{ .compatible = "qcom,pm8916-gpio", .data = (void *) 4 },
+ /* pm8937 has 8 GPIOs with holes on 3, 4 and 6 */
+ { .compatible = "qcom,pm8937-gpio", .data = (void *) 8 },
{ .compatible = "qcom,pm8941-gpio", .data = (void *) 36 },
/* pm8950 has 8 GPIOs with holes on 3 */
{ .compatible = "qcom,pm8950-gpio", .data = (void *) 8 },
@@ -1268,7 +1270,7 @@ static struct platform_driver pmic_gpio_driver = {
.of_match_table = pmic_gpio_of_match,
},
.probe = pmic_gpio_probe,
- .remove_new = pmic_gpio_remove,
+ .remove = pmic_gpio_remove,
};
module_platform_driver(pmic_gpio_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
index d16ece90d926..84de584cf7eb 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
@@ -983,6 +983,7 @@ static const struct of_device_id pmic_mpp_of_match[] = {
{ .compatible = "qcom,pm8226-mpp", .data = (void *) 8 },
{ .compatible = "qcom,pm8841-mpp", .data = (void *) 4 },
{ .compatible = "qcom,pm8916-mpp", .data = (void *) 4 },
+ { .compatible = "qcom,pm8937-mpp", .data = (void *) 4 },
{ .compatible = "qcom,pm8941-mpp", .data = (void *) 8 },
{ .compatible = "qcom,pm8950-mpp", .data = (void *) 4 },
{ .compatible = "qcom,pmi8950-mpp", .data = (void *) 4 },
@@ -1000,7 +1001,7 @@ static struct platform_driver pmic_mpp_driver = {
.of_match_table = pmic_mpp_of_match,
},
.probe = pmic_mpp_probe,
- .remove_new = pmic_mpp_remove,
+ .remove = pmic_mpp_remove,
};
module_platform_driver(pmic_mpp_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
index 9cd5247ea574..2225dc49d477 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
@@ -832,7 +832,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
* files which don't set the "gpio-ranges" property or systems that
* utilize ACPI the driver has to call gpiochip_add_pin_range().
*/
- if (!of_property_read_bool(pctrl->dev->of_node, "gpio-ranges")) {
+ if (!of_property_present(pctrl->dev->of_node, "gpio-ranges")) {
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
0, 0, pctrl->chip.ngpio);
if (ret) {
@@ -866,7 +866,7 @@ static struct platform_driver pm8xxx_gpio_driver = {
.of_match_table = pm8xxx_gpio_of_match,
},
.probe = pm8xxx_gpio_probe,
- .remove_new = pm8xxx_gpio_remove,
+ .remove = pm8xxx_gpio_remove,
};
module_platform_driver(pm8xxx_gpio_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
index 3aee6835a2de..9b1039c08aa6 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
@@ -949,7 +949,7 @@ static struct platform_driver pm8xxx_mpp_driver = {
.of_match_table = pm8xxx_mpp_of_match,
},
.probe = pm8xxx_mpp_probe,
- .remove_new = pm8xxx_mpp_remove,
+ .remove = pm8xxx_mpp_remove,
};
module_platform_driver(pm8xxx_mpp_driver);
diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c
index abfcdd3da9e8..419cb8facb2f 100644
--- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c
+++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c
@@ -1861,7 +1861,7 @@ static struct platform_driver x1e80100_pinctrl_driver = {
.of_match_table = x1e80100_pinctrl_of_match,
},
.probe = x1e80100_pinctrl_probe,
- .remove_new = msm_pinctrl_remove,
+ .remove = msm_pinctrl_remove,
};
static int __init x1e80100_pinctrl_init(void)
diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig
index 14bd55d64731..7f3f41c7fe54 100644
--- a/drivers/pinctrl/renesas/Kconfig
+++ b/drivers/pinctrl/renesas/Kconfig
@@ -41,6 +41,7 @@ config PINCTRL_RENESAS
select PINCTRL_PFC_R8A779H0 if ARCH_R8A779H0
select PINCTRL_RZG2L if ARCH_RZG2L
select PINCTRL_RZV2M if ARCH_R9A09G011
+ select PINCTRL_RZG2L if ARCH_R9A09G057
select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203
select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264
select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269
diff --git a/drivers/pinctrl/renesas/pinctrl-rza1.c b/drivers/pinctrl/renesas/pinctrl-rza1.c
index 6527872813dc..b1058504e0bb 100644
--- a/drivers/pinctrl/renesas/pinctrl-rza1.c
+++ b/drivers/pinctrl/renesas/pinctrl-rza1.c
@@ -19,6 +19,7 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
@@ -750,6 +751,11 @@ static int rza1_pin_mux_single(struct rza1_pinctrl *rza1_pctl,
static int rza1_gpio_request(struct gpio_chip *chip, unsigned int gpio)
{
struct rza1_port *port = gpiochip_get_data(chip);
+ int ret;
+
+ ret = pinctrl_gpio_request(chip, gpio);
+ if (ret)
+ return ret;
rza1_pin_reset(port, gpio);
@@ -771,6 +777,7 @@ static void rza1_gpio_free(struct gpio_chip *chip, unsigned int gpio)
struct rza1_port *port = gpiochip_get_data(chip);
rza1_pin_reset(port, gpio);
+ pinctrl_gpio_free(chip, gpio);
}
static int rza1_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
diff --git a/drivers/pinctrl/renesas/pinctrl-rza2.c b/drivers/pinctrl/renesas/pinctrl-rza2.c
index af689d7c117f..dd1f8c29d3e7 100644
--- a/drivers/pinctrl/renesas/pinctrl-rza2.c
+++ b/drivers/pinctrl/renesas/pinctrl-rza2.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
@@ -229,6 +230,8 @@ static const char * const rza2_gpio_names[] = {
static struct gpio_chip chip = {
.names = rza2_gpio_names,
.base = -1,
+ .request = pinctrl_gpio_request,
+ .free = pinctrl_gpio_free,
.get_direction = rza2_chip_get_direction,
.direction_input = rza2_chip_direction_input,
.direction_output = rza2_chip_direction_output,
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 5a403915fed2..1df9cec2873f 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -139,6 +139,8 @@
#define IEN(off) (0x1800 + (off) * 8)
#define PUPD(off) (0x1C00 + (off) * 8)
#define ISEL(off) (0x2C00 + (off) * 8)
+#define NOD(off) (0x3000 + (off) * 8)
+#define SMT(off) (0x3400 + (off) * 8)
#define SD_CH(off, ch) ((off) + (ch) * 4)
#define ETH_POC(off, ch) ((off) + (ch) * 4)
#define QSPI (0x3008)
@@ -160,6 +162,8 @@
#define IOLH_MASK 0x03
#define SR_MASK 0x01
#define PUPD_MASK 0x03
+#define NOD_MASK 0x01
+#define SMT_MASK 0x01
#define PM_INPUT 0x1
#define PM_OUTPUT 0x2
@@ -168,7 +172,6 @@
#define RZG2L_PIN_ID_TO_PIN(id) ((id) % RZG2L_PINS_PER_PORT)
#define RZG2L_TINT_MAX_INTERRUPT 32
-#define RZG2L_TINT_IRQ_START_INDEX 9
#define RZG2L_PACK_HWIRQ(t, i) (((t) << 16) | (i))
/* Custom pinconf parameters */
@@ -247,6 +250,7 @@ enum rzg2l_iolh_index {
* @iolh_groupb_ua: IOLH group B uA specific values
* @iolh_groupc_ua: IOLH group C uA specific values
* @iolh_groupb_oi: IOLH group B output impedance specific values
+ * @tint_start_index: the start index for the TINT interrupts
* @drive_strength_ua: drive strength in uA is supported (otherwise mA is supported)
* @func_base: base number for port function (see register PFC)
* @oen_max_pin: the maximum pin number supporting output enable
@@ -258,6 +262,7 @@ struct rzg2l_hwcfg {
u16 iolh_groupb_ua[RZG2L_IOLH_IDX_MAX];
u16 iolh_groupc_ua[RZG2L_IOLH_IDX_MAX];
u16 iolh_groupb_oi[4];
+ u16 tint_start_index;
bool drive_strength_ua;
u8 func_base;
u8 oen_max_pin;
@@ -1337,6 +1342,27 @@ static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev,
break;
}
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (!(cfg & PIN_CFG_NOD))
+ return -EINVAL;
+
+ arg = rzg2l_read_pin_config(pctrl, NOD(off), bit, NOD_MASK);
+ if (!arg && param != PIN_CONFIG_DRIVE_PUSH_PULL)
+ return -EINVAL;
+ if (arg && param != PIN_CONFIG_DRIVE_OPEN_DRAIN)
+ return -EINVAL;
+ break;
+
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!(cfg & PIN_CFG_SMT))
+ return -EINVAL;
+
+ arg = rzg2l_read_pin_config(pctrl, SMT(off), bit, SMT_MASK);
+ if (!arg)
+ return -EINVAL;
+ break;
+
case RENESAS_RZV2H_PIN_CONFIG_OUTPUT_IMPEDANCE:
if (!(cfg & PIN_CFG_IOLH_RZV2H))
return -EINVAL;
@@ -1466,6 +1492,22 @@ static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
rzg2l_rmw_pin_config(pctrl, IOLH(off), bit, IOLH_MASK, index);
break;
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (!(cfg & PIN_CFG_NOD))
+ return -EINVAL;
+
+ rzg2l_rmw_pin_config(pctrl, NOD(off), bit, NOD_MASK,
+ param == PIN_CONFIG_DRIVE_OPEN_DRAIN ? 1 : 0);
+ break;
+
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (!(cfg & PIN_CFG_SMT))
+ return -EINVAL;
+
+ rzg2l_rmw_pin_config(pctrl, SMT(off), bit, SMT_MASK, arg);
+ break;
+
case RENESAS_RZV2H_PIN_CONFIG_OUTPUT_IMPEDANCE:
if (!(cfg & PIN_CFG_IOLH_RZV2H))
return -EINVAL;
@@ -2290,7 +2332,7 @@ static void rzg2l_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static int rzg2l_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
@@ -2379,7 +2421,7 @@ static int rzg2l_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
rzg2l_gpio_irq_endisable(pctrl, child, true);
pctrl->hwirq[irq] = child;
- irq += RZG2L_TINT_IRQ_START_INDEX;
+ irq += pctrl->data->hwcfg->tint_start_index;
/* All these interrupts are level high in the CPU */
*parent_type = IRQ_TYPE_LEVEL_HIGH;
@@ -2391,21 +2433,6 @@ err:
return ret;
}
-static int rzg2l_gpio_populate_parent_fwspec(struct gpio_chip *chip,
- union gpio_irq_fwspec *gfwspec,
- unsigned int parent_hwirq,
- unsigned int parent_type)
-{
- struct irq_fwspec *fwspec = &gfwspec->fwspec;
-
- fwspec->fwnode = chip->irq.parent_domain->fwnode;
- fwspec->param_count = 2;
- fwspec->param[0] = parent_hwirq;
- fwspec->param[1] = parent_type;
-
- return 0;
-}
-
static void rzg2l_gpio_irq_restore(struct rzg2l_pinctrl *pctrl)
{
struct irq_domain *domain = pctrl->gpio_chip.irq.domain;
@@ -2607,7 +2634,7 @@ static int rzg2l_gpio_register(struct rzg2l_pinctrl *pctrl)
girq->fwnode = dev_fwnode(pctrl->dev);
girq->parent_domain = parent_domain;
girq->child_to_parent_hwirq = rzg2l_gpio_child_to_parent_hwirq;
- girq->populate_parent_alloc_arg = rzg2l_gpio_populate_parent_fwspec;
+ girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell;
girq->child_irq_domain_ops.free = rzg2l_gpio_irq_domain_free;
girq->init_valid_mask = rzg2l_init_irq_valid_mask;
@@ -2710,7 +2737,7 @@ static int rzg2l_pinctrl_register(struct rzg2l_pinctrl *pctrl)
ret = pinctrl_enable(pctrl->pctl);
if (ret)
- dev_err_probe(pctrl->dev, ret, "pinctrl enable failed\n");
+ return dev_err_probe(pctrl->dev, ret, "pinctrl enable failed\n");
ret = rzg2l_gpio_register(pctrl);
if (ret)
@@ -3034,6 +3061,7 @@ static const struct rzg2l_hwcfg rzg2l_hwcfg = {
[RZG2L_IOLH_IDX_3V3] = 2000, 4000, 8000, 12000,
},
.iolh_groupb_oi = { 100, 66, 50, 33, },
+ .tint_start_index = 9,
.oen_max_pin = 0,
};
@@ -3063,6 +3091,7 @@ static const struct rzg2l_hwcfg rzg3s_hwcfg = {
/* 3v3 power source */
[RZG2L_IOLH_IDX_3V3] = 4500, 5200, 5700, 6050,
},
+ .tint_start_index = 9,
.drive_strength_ua = true,
.func_base = 1,
.oen_max_pin = 1, /* Pin 1 of P0 and P7 is the maximum OEN pin. */
@@ -3073,6 +3102,7 @@ static const struct rzg2l_hwcfg rzv2h_hwcfg = {
.regs = {
.pwpr = 0x3c04,
},
+ .tint_start_index = 17,
};
static struct rzg2l_pinctrl_data r9a07g043_data = {
diff --git a/drivers/pinctrl/renesas/pinctrl-rzn1.c b/drivers/pinctrl/renesas/pinctrl-rzn1.c
index 39af1fe79c84..d442d4f9981c 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzn1.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzn1.c
@@ -925,7 +925,7 @@ MODULE_DEVICE_TABLE(of, rzn1_pinctrl_match);
static struct platform_driver rzn1_pinctrl_driver = {
.probe = rzn1_pinctrl_probe,
- .remove_new = rzn1_pinctrl_remove,
+ .remove = rzn1_pinctrl_remove,
.driver = {
.name = "rzn1-pinctrl",
.of_match_table = rzn1_pinctrl_match,
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
index 5480e0884abe..3ea7106ce5ea 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c
@@ -58,6 +58,15 @@ static const struct samsung_pin_bank_type exynos850_bank_type_alive = {
.reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
};
+/*
+ * Bank type for non-alive type. Bit fields:
+ * CON: 4, DAT: 1, PUD: 2, DRV: 3, CONPDN: 2, PUDPDN: 2
+ */
+static const struct samsung_pin_bank_type exynos8895_bank_type_off = {
+ .fld_width = { 4, 1, 2, 3, 2, 2, },
+ .reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, },
+};
+
/* Pad retention control code for accessing PMU regmap */
static atomic_t exynos_shared_retention_refcnt;
@@ -618,6 +627,300 @@ const struct samsung_pinctrl_of_match_data exynos850_of_data __initconst = {
.num_ctrl = ARRAY_SIZE(exynos850_pin_ctrl),
};
+/* pin banks of exynos990 pin-controller 0 (ALIVE) */
+static struct samsung_pin_bank_data exynos990_pin_banks0[] = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
+ EXYNOS850_PIN_BANK_EINTW(2, 0x080, "gpa4", 0x10),
+ EXYNOS850_PIN_BANK_EINTN(7, 0x0A0, "gpq0"),
+};
+
+/* pin banks of exynos990 pin-controller 1 (CMGP) */
+static struct samsung_pin_bank_data exynos990_pin_banks1[] = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTN(1, 0x000, "gpm0"),
+ EXYNOS850_PIN_BANK_EINTN(1, 0x020, "gpm1"),
+ EXYNOS850_PIN_BANK_EINTN(1, 0x040, "gpm2"),
+ EXYNOS850_PIN_BANK_EINTN(1, 0x060, "gpm3"),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x080, "gpm4", 0x00),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0A0, "gpm5", 0x04),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0C0, "gpm6", 0x08),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0E0, "gpm7", 0x0c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x100, "gpm8", 0x10),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x120, "gpm9", 0x14),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x140, "gpm10", 0x18),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x160, "gpm11", 0x1c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x180, "gpm12", 0x20),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1A0, "gpm13", 0x24),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1C0, "gpm14", 0x28),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1E0, "gpm15", 0x2c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x200, "gpm16", 0x30),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x220, "gpm17", 0x34),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x240, "gpm18", 0x38),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x260, "gpm19", 0x3c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x280, "gpm20", 0x40),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x2A0, "gpm21", 0x44),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x2C0, "gpm22", 0x48),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x2E0, "gpm23", 0x4c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x300, "gpm24", 0x50),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x320, "gpm25", 0x54),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x340, "gpm26", 0x58),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x360, "gpm27", 0x5c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x380, "gpm28", 0x60),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x3A0, "gpm29", 0x64),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x3C0, "gpm30", 0x68),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x3E0, "gpm31", 0x6c),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x400, "gpm32", 0x70),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x420, "gpm33", 0x74),
+
+};
+
+/* pin banks of exynos990 pin-controller 2 (HSI1) */
+static struct samsung_pin_bank_data exynos990_pin_banks2[] = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(4, 0x000, "gpf0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(6, 0x020, "gpf1", 0x04),
+ EXYNOS850_PIN_BANK_EINTG(3, 0x040, "gpf2", 0x08),
+};
+
+/* pin banks of exynos990 pin-controller 3 (HSI2) */
+static struct samsung_pin_bank_data exynos990_pin_banks3[] = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(2, 0x000, "gpf3", 0x00),
+};
+
+/* pin banks of exynos990 pin-controller 4 (PERIC0) */
+static struct samsung_pin_bank_data exynos990_pin_banks4[] = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(8, 0x000, "gpp0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x020, "gpp1", 0x04),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x040, "gpp2", 0x08),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x060, "gpp3", 0x0C),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x080, "gpp4", 0x10),
+ EXYNOS850_PIN_BANK_EINTG(2, 0x0A0, "gpg0", 0x14),
+};
+
+/* pin banks of exynos990 pin-controller 5 (PERIC1) */
+static struct samsung_pin_bank_data exynos990_pin_banks5[] = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(8, 0x000, "gpp5", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x020, "gpp6", 0x04),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x040, "gpp7", 0x08),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x060, "gpp8", 0x0C),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x080, "gpp9", 0x10),
+ EXYNOS850_PIN_BANK_EINTG(6, 0x0A0, "gpc0", 0x14),
+ EXYNOS850_PIN_BANK_EINTG(4, 0x0C0, "gpg1", 0x18),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x0E0, "gpb0", 0x1C),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x100, "gpb1", 0x20),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x120, "gpb2", 0x24),
+};
+
+/* pin banks of exynos990 pin-controller 6 (VTS) */
+static struct samsung_pin_bank_data exynos990_pin_banks6[] = {
+ /* Must start with EINTG banks, ordered by EINT group number. */
+ EXYNOS850_PIN_BANK_EINTG(7, 0x000, "gpv0", 0x00),
+};
+
+static const struct samsung_pin_ctrl exynos990_pin_ctrl[] __initconst = {
+ {
+ /* pin-controller instance 0 ALIVE data */
+ .pin_banks = exynos990_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos990_pin_banks0),
+ .eint_wkup_init = exynos_eint_wkup_init,
+ }, {
+ /* pin-controller instance 1 CMGP data */
+ .pin_banks = exynos990_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos990_pin_banks1),
+ .eint_wkup_init = exynos_eint_wkup_init,
+ }, {
+ /* pin-controller instance 2 HSI1 data */
+ .pin_banks = exynos990_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos990_pin_banks2),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ }, {
+ /* pin-controller instance 3 HSI2 data */
+ .pin_banks = exynos990_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos990_pin_banks3),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ }, {
+ /* pin-controller instance 4 PERIC0 data */
+ .pin_banks = exynos990_pin_banks4,
+ .nr_banks = ARRAY_SIZE(exynos990_pin_banks4),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ }, {
+ /* pin-controller instance 5 PERIC1 data */
+ .pin_banks = exynos990_pin_banks5,
+ .nr_banks = ARRAY_SIZE(exynos990_pin_banks5),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ }, {
+ /* pin-controller instance 6 VTS data */
+ .pin_banks = exynos990_pin_banks6,
+ .nr_banks = ARRAY_SIZE(exynos990_pin_banks6),
+ },
+};
+
+const struct samsung_pinctrl_of_match_data exynos990_of_data __initconst = {
+ .ctrl = exynos990_pin_ctrl,
+ .num_ctrl = ARRAY_SIZE(exynos990_pin_ctrl),
+};
+
+/* pin banks of exynos9810 pin-controller 0 (ALIVE) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks0[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTN(6, 0x000, "etc1"),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x020, "gpa0", 0x00),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x040, "gpa1", 0x04),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x060, "gpa2", 0x08),
+ EXYNOS850_PIN_BANK_EINTW(8, 0x080, "gpa3", 0x0c),
+ EXYNOS850_PIN_BANK_EINTN(6, 0x0A0, "gpq0"),
+ EXYNOS850_PIN_BANK_EINTW(2, 0x0C0, "gpa4", 0x10),
+};
+
+/* pin banks of exynos9810 pin-controller 1 (AUD) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks1[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(5, 0x000, "gpb0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x020, "gpb1", 0x04),
+ EXYNOS850_PIN_BANK_EINTG(4, 0x040, "gpb2", 0x08),
+};
+
+/* pin banks of exynos9810 pin-controller 2 (CHUB) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks2[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(8, 0x000, "gph0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(5, 0x020, "gph1", 0x04),
+};
+
+/* pin banks of exynos9810 pin-controller 3 (CMGP) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks3[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTW(1, 0x000, "gpm0", 0x00),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x020, "gpm1", 0x04),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x040, "gpm2", 0x08),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x060, "gpm3", 0x0C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x080, "gpm4", 0x10),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0A0, "gpm5", 0x14),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0C0, "gpm6", 0x18),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x0E0, "gpm7", 0x1C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x100, "gpm10", 0x20),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x120, "gpm11", 0x24),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x140, "gpm12", 0x28),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x160, "gpm13", 0x2C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x180, "gpm14", 0x30),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1A0, "gpm15", 0x34),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1C0, "gpm16", 0x38),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x1E0, "gpm17", 0x3C),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x200, "gpm40", 0x40),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x220, "gpm41", 0x44),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x240, "gpm42", 0x48),
+ EXYNOS850_PIN_BANK_EINTW(1, 0x260, "gpm43", 0x4C),
+};
+
+/* pin banks of exynos9810 pin-controller 4 (FSYS0) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks4[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(2, 0x000, "gpf0", 0x00),
+};
+
+/* pin banks of exynos9810 pin-controller 5 (FSYS1) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks5[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(7, 0x000, "gpf1", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(6, 0x020, "gpf2", 0x04),
+};
+
+/* pin banks of exynos9810 pin-controller 6 (PERIC0) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks6[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(8, 0x000, "gpp0", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x020, "gpp1", 0x04),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x040, "gpp2", 0x08),
+ EXYNOS850_PIN_BANK_EINTG(4, 0x060, "gpp3", 0x0C),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x0C0, "gpg2", 0x18),
+};
+
+/* pin banks of exynos9810 pin-controller 7 (PERIC1) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks7[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(8, 0x000, "gpp4", 0x00),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x020, "gpp5", 0x04),
+ EXYNOS850_PIN_BANK_EINTG(4, 0x040, "gpp6", 0x08),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x060, "gpc0", 0x0C),
+ EXYNOS850_PIN_BANK_EINTG(8, 0x080, "gpc1", 0x10),
+ EXYNOS850_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+ EXYNOS850_PIN_BANK_EINTG(7, 0x0C0, "gpg3", 0x18),
+};
+
+/* pin banks of exynos9810 pin-controller 8 (VTS) */
+static const struct samsung_pin_bank_data exynos9810_pin_banks8[] __initconst = {
+ EXYNOS850_PIN_BANK_EINTG(3, 0x000, "gpt0", 0x00),
+};
+
+static const struct samsung_pin_ctrl exynos9810_pin_ctrl[] __initconst = {
+ {
+ /* pin-controller instance 0 ALIVE data */
+ .pin_banks = exynos9810_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks0),
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 1 AUD data */
+ .pin_banks = exynos9810_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks1),
+ }, {
+ /* pin-controller instance 2 CHUB data */
+ .pin_banks = exynos9810_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks2),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 3 CMGP data */
+ .pin_banks = exynos9810_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks3),
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 4 FSYS0 data */
+ .pin_banks = exynos9810_pin_banks4,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks4),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 5 FSYS1 data */
+ .pin_banks = exynos9810_pin_banks5,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks5),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 6 PERIC0 data */
+ .pin_banks = exynos9810_pin_banks6,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks6),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 7 PERIC1 data */
+ .pin_banks = exynos9810_pin_banks7,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks7),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 8 VTS data */
+ .pin_banks = exynos9810_pin_banks8,
+ .nr_banks = ARRAY_SIZE(exynos9810_pin_banks8),
+ },
+};
+
+const struct samsung_pinctrl_of_match_data exynos9810_of_data __initconst = {
+ .ctrl = exynos9810_pin_ctrl,
+ .num_ctrl = ARRAY_SIZE(exynos9810_pin_ctrl),
+};
+
/* pin banks of exynosautov9 pin-controller 0 (ALIVE) */
static const struct samsung_pin_bank_data exynosautov9_pin_banks0[] __initconst = {
EXYNOS850_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
@@ -866,6 +1169,134 @@ const struct samsung_pinctrl_of_match_data exynosautov920_of_data __initconst =
.num_ctrl = ARRAY_SIZE(exynosautov920_pin_ctrl),
};
+/* pin banks of exynos8895 pin-controller 0 (ALIVE) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks0[] __initconst = {
+ EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa0", 0x00),
+ EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa1", 0x04),
+ EXYNOS_PIN_BANK_EINTW(8, 0x060, "gpa2", 0x08),
+ EXYNOS_PIN_BANK_EINTW(8, 0x080, "gpa3", 0x0c),
+ EXYNOS_PIN_BANK_EINTW(7, 0x0a0, "gpa4", 0x24),
+};
+
+/* pin banks of exynos8895 pin-controller 1 (ABOX) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks1[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gph0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(7, 0x020, "gph1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(4, 0x040, "gph3", 0x08),
+};
+
+/* pin banks of exynos8895 pin-controller 2 (VTS) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks2[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(3, 0x000, "gph2", 0x00),
+};
+
+/* pin banks of exynos8895 pin-controller 3 (FSYS0) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks3[] __initconst = {
+ EXYNOS8895_PIN_BANK_EINTG(3, 0x000, "gpi0", 0x00),
+ EXYNOS8895_PIN_BANK_EINTG(8, 0x020, "gpi1", 0x04),
+};
+
+/* pin banks of exynos8895 pin-controller 4 (FSYS1) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks4[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj1", 0x00),
+ EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpj0", 0x04),
+};
+
+/* pin banks of exynos8895 pin-controller 5 (BUSC) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks5[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(2, 0x000, "gpb2", 0x00),
+};
+
+/* pin banks of exynos8895 pin-controller 6 (PERIC0) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks6[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpd0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpd1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpd2", 0x08),
+ EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpd3", 0x0C),
+ EXYNOS_PIN_BANK_EINTG(4, 0x080, "gpb1", 0x10),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpe7", 0x14),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0c0, "gpf1", 0x18),
+};
+
+/* pin banks of exynos8895 pin-controller 7 (PERIC1) */
+static const struct samsung_pin_bank_data exynos8895_pin_banks7[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpb0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpc0", 0x04),
+ EXYNOS_PIN_BANK_EINTG(5, 0x040, "gpc1", 0x08),
+ EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpc2", 0x0C),
+ EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpc3", 0x10),
+ EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpk0", 0x14),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0c0, "gpe5", 0x18),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpe6", 0x1C),
+ EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe2", 0x20),
+ EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpe3", 0x24),
+ EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe4", 0x28),
+ EXYNOS_PIN_BANK_EINTG(4, 0x160, "gpf0", 0x2C),
+ EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpe1", 0x30),
+ EXYNOS_PIN_BANK_EINTG(2, 0x1a0, "gpg0", 0x34),
+};
+
+static const struct samsung_pin_ctrl exynos8895_pin_ctrl[] __initconst = {
+ {
+ /* pin-controller instance 0 ALIVE data */
+ .pin_banks = exynos8895_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks0),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 1 ABOX data */
+ .pin_banks = exynos8895_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks1),
+ }, {
+ /* pin-controller instance 2 VTS data */
+ .pin_banks = exynos8895_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks2),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ }, {
+ /* pin-controller instance 3 FSYS0 data */
+ .pin_banks = exynos8895_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks3),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 4 FSYS1 data */
+ .pin_banks = exynos8895_pin_banks4,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks4),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 5 BUSC data */
+ .pin_banks = exynos8895_pin_banks5,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks5),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 6 PERIC0 data */
+ .pin_banks = exynos8895_pin_banks6,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks6),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 7 PERIC1 data */
+ .pin_banks = exynos8895_pin_banks7,
+ .nr_banks = ARRAY_SIZE(exynos8895_pin_banks7),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ },
+};
+
+const struct samsung_pinctrl_of_match_data exynos8895_of_data __initconst = {
+ .ctrl = exynos8895_pin_ctrl,
+ .num_ctrl = ARRAY_SIZE(exynos8895_pin_ctrl),
+};
+
/*
* Pinctrl driver data for Tesla FSD SoC. FSD SoC includes three
* gpio/pin-mux/pinconfig controllers.
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 305cb1d31de4..7b7ff7ffeb56 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
@@ -141,6 +141,16 @@
.name = id \
}
+#define EXYNOS8895_PIN_BANK_EINTG(pins, reg, id, offs) \
+ { \
+ .type = &exynos8895_bank_type_off, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_GPIO, \
+ .eint_offset = offs, \
+ .name = id \
+ }
+
#define EXYNOSV920_PIN_BANK_EINTG(pins, reg, id, con_offs, mask_offs, pend_offs) \
{ \
.type = &exynos850_bank_type_off, \
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 675efa5d86a9..bbedd980ec67 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1477,6 +1477,12 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
.data = &exynos7885_of_data },
{ .compatible = "samsung,exynos850-pinctrl",
.data = &exynos850_of_data },
+ { .compatible = "samsung,exynos8895-pinctrl",
+ .data = &exynos8895_of_data },
+ { .compatible = "samsung,exynos9810-pinctrl",
+ .data = &exynos9810_of_data },
+ { .compatible = "samsung,exynos990-pinctrl",
+ .data = &exynos990_of_data },
{ .compatible = "samsung,exynosautov9-pinctrl",
.data = &exynosautov9_of_data },
{ .compatible = "samsung,exynosautov920-pinctrl",
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index a1e7377bd890..bb0689d52ea0 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -384,6 +384,9 @@ extern const struct samsung_pinctrl_of_match_data exynos5433_of_data;
extern const struct samsung_pinctrl_of_match_data exynos7_of_data;
extern const struct samsung_pinctrl_of_match_data exynos7885_of_data;
extern const struct samsung_pinctrl_of_match_data exynos850_of_data;
+extern const struct samsung_pinctrl_of_match_data exynos8895_of_data;
+extern const struct samsung_pinctrl_of_match_data exynos9810_of_data;
+extern const struct samsung_pinctrl_of_match_data exynos990_of_data;
extern const struct samsung_pinctrl_of_match_data exynosautov9_of_data;
extern const struct samsung_pinctrl_of_match_data exynosautov920_of_data;
extern const struct samsung_pinctrl_of_match_data fsd_of_data;
diff --git a/drivers/pinctrl/sophgo/Kconfig b/drivers/pinctrl/sophgo/Kconfig
index b14792ee46fc..c05f909a8838 100644
--- a/drivers/pinctrl/sophgo/Kconfig
+++ b/drivers/pinctrl/sophgo/Kconfig
@@ -43,7 +43,7 @@ config PINCTRL_SOPHGO_SG2000
pinctrl-sg2000.
config PINCTRL_SOPHGO_SG2002
- tristate "Sophgo SG2000 SoC Pinctrl driver"
+ tristate "Sophgo SG2002 SoC Pinctrl driver"
depends on ARCH_SOPHGO || COMPILE_TEST
depends on OF
select PINCTRL_SOPHGO_CV18XX
diff --git a/drivers/pinctrl/spacemit/Kconfig b/drivers/pinctrl/spacemit/Kconfig
new file mode 100644
index 000000000000..168f8a5ffbb9
--- /dev/null
+++ b/drivers/pinctrl/spacemit/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Sophgo SoC PINCTRL drivers
+#
+
+config PINCTRL_SPACEMIT_K1
+ tristate "SpacemiT K1 SoC Pinctrl driver"
+ depends on ARCH_SPACEMIT || COMPILE_TEST
+ depends on OF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+ help
+ Say Y to select the pinctrl driver for K1 SoC.
+ This pin controller allows selecting the mux function for
+ each pin. This driver can also be built as a module called
+ pinctrl-k1.
diff --git a/drivers/pinctrl/spacemit/Makefile b/drivers/pinctrl/spacemit/Makefile
new file mode 100644
index 000000000000..fede1e80fe0f
--- /dev/null
+++ b/drivers/pinctrl/spacemit/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_PINCTRL_SPACEMIT_K1) += pinctrl-k1.o
diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.c b/drivers/pinctrl/spacemit/pinctrl-k1.c
new file mode 100644
index 000000000000..a32579d73613
--- /dev/null
+++ b/drivers/pinctrl/spacemit/pinctrl-k1.c
@@ -0,0 +1,1051 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Yixun Lan <dlan@gentoo.org> */
+
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+#include "pinctrl-k1.h"
+
+/*
+ * +---------+----------+-----------+--------+--------+----------+--------+
+ * | pull | drive | schmitter | slew | edge | strong | mux |
+ * | up/down | strength | trigger | rate | detect | pull | mode |
+ * +---------+----------+-----------+--------+--------+----------+--------+
+ * 3 bits 3 bits 2 bits 1 bit 3 bits 1 bit 3 bits
+ */
+
+#define PAD_MUX GENMASK(2, 0)
+#define PAD_STRONG_PULL BIT(3)
+#define PAD_EDGE_RISE BIT(4)
+#define PAD_EDGE_FALL BIT(5)
+#define PAD_EDGE_CLEAR BIT(6)
+#define PAD_SLEW_RATE GENMASK(12, 11)
+#define PAD_SLEW_RATE_EN BIT(7)
+#define PAD_SCHMITT GENMASK(9, 8)
+#define PAD_DRIVE GENMASK(12, 10)
+#define PAD_PULLDOWN BIT(13)
+#define PAD_PULLUP BIT(14)
+#define PAD_PULL_EN BIT(15)
+
+struct spacemit_pin {
+ u16 pin;
+ u16 flags;
+ u8 gpiofunc;
+};
+
+struct spacemit_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl_dev;
+ const struct spacemit_pinctrl_data *data;
+ struct pinctrl_desc pdesc;
+
+ struct mutex mutex;
+ raw_spinlock_t lock;
+
+ void __iomem *regs;
+};
+
+struct spacemit_pinctrl_data {
+ const struct pinctrl_pin_desc *pins;
+ const struct spacemit_pin *data;
+ u16 npins;
+};
+
+struct spacemit_pin_mux_config {
+ const struct spacemit_pin *pin;
+ u32 config;
+};
+
+struct spacemit_pin_drv_strength {
+ u8 val;
+ u32 mA;
+};
+
+/* map pin id to pinctrl register offset, refer MFPR definition */
+static unsigned int spacemit_pin_to_offset(unsigned int pin)
+{
+ unsigned int offset = 0;
+
+ switch (pin) {
+ case 0 ... 85:
+ offset = pin + 1;
+ break;
+ case 86 ... 92:
+ offset = pin + 37;
+ break;
+ case 93 ... 97:
+ offset = pin + 24;
+ break;
+ case 98:
+ offset = 93;
+ break;
+ case 99:
+ offset = 92;
+ break;
+ case 100:
+ offset = 91;
+ break;
+ case 101:
+ offset = 90;
+ break;
+ case 102:
+ offset = 95;
+ break;
+ case 103:
+ offset = 94;
+ break;
+ case 104 ... 110:
+ offset = pin + 6;
+ break;
+ case 111 ... 127:
+ offset = pin + 20;
+ break;
+ default:
+ break;
+ }
+
+ return offset << 2;
+}
+
+static inline void __iomem *spacemit_pin_to_reg(struct spacemit_pinctrl *pctrl,
+ unsigned int pin)
+{
+ return pctrl->regs + spacemit_pin_to_offset(pin);
+}
+
+static u16 spacemit_dt_get_pin(u32 value)
+{
+ return value >> 16;
+}
+
+static u16 spacemit_dt_get_pin_mux(u32 value)
+{
+ return value & GENMASK(15, 0);
+}
+
+static const struct spacemit_pin *spacemit_get_pin(struct spacemit_pinctrl *pctrl,
+ unsigned long pin)
+{
+ const struct spacemit_pin *pdata = pctrl->data->data;
+ int i;
+
+ for (i = 0; i < pctrl->data->npins; i++) {
+ if (pin == pdata[i].pin)
+ return &pdata[i];
+ }
+
+ return NULL;
+}
+
+static inline enum spacemit_pin_io_type spacemit_to_pin_io_type(
+ const struct spacemit_pin *pin)
+{
+ return K1_PIN_GET_IO_TYPE(pin->flags);
+}
+
+/* External: IO voltage via external source, can be 1.8V or 3.3V */
+static const char * const io_type_desc[] = {
+ "None",
+ "Fixed/1V8",
+ "Fixed/3V3",
+ "External",
+};
+
+static void spacemit_pctrl_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *seq, unsigned int pin)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
+ enum spacemit_pin_io_type type = spacemit_to_pin_io_type(spin);
+ void __iomem *reg;
+ u32 value;
+
+ seq_printf(seq, "offset: 0x%04x ", spacemit_pin_to_offset(pin));
+ seq_printf(seq, "type: %s ", io_type_desc[type]);
+
+ reg = spacemit_pin_to_reg(pctrl, pin);
+ value = readl(reg);
+ seq_printf(seq, "mux: %ld reg: 0x%04x", (value & PAD_MUX), value);
+}
+
+/* use IO high level output current as the table */
+static struct spacemit_pin_drv_strength spacemit_ds_1v8_tbl[4] = {
+ { 0, 11 },
+ { 2, 21 },
+ { 4, 32 },
+ { 6, 42 },
+};
+
+static struct spacemit_pin_drv_strength spacemit_ds_3v3_tbl[8] = {
+ { 0, 7 },
+ { 2, 10 },
+ { 4, 13 },
+ { 6, 16 },
+ { 1, 19 },
+ { 3, 23 },
+ { 5, 26 },
+ { 7, 29 },
+};
+
+static inline u8 spacemit_get_ds_value(struct spacemit_pin_drv_strength *tbl,
+ u32 num, u32 mA)
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ if (mA <= tbl[i].mA)
+ return tbl[i].val;
+
+ return tbl[num - 1].val;
+}
+
+static inline u32 spacemit_get_ds_mA(struct spacemit_pin_drv_strength *tbl,
+ u32 num, u32 val)
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ if (val == tbl[i].val)
+ return tbl[i].mA;
+
+ return 0;
+}
+
+static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type,
+ u32 mA)
+{
+ switch (type) {
+ case IO_TYPE_1V8:
+ return spacemit_get_ds_value(spacemit_ds_1v8_tbl,
+ ARRAY_SIZE(spacemit_ds_1v8_tbl),
+ mA);
+ case IO_TYPE_3V3:
+ return spacemit_get_ds_value(spacemit_ds_3v3_tbl,
+ ARRAY_SIZE(spacemit_ds_3v3_tbl),
+ mA);
+ default:
+ return 0;
+ }
+}
+
+static inline u32 spacemit_get_drive_strength_mA(enum spacemit_pin_io_type type,
+ u32 value)
+{
+ switch (type) {
+ case IO_TYPE_1V8:
+ return spacemit_get_ds_mA(spacemit_ds_1v8_tbl,
+ ARRAY_SIZE(spacemit_ds_1v8_tbl),
+ value & 0x6);
+ case IO_TYPE_3V3:
+ return spacemit_get_ds_mA(spacemit_ds_3v3_tbl,
+ ARRAY_SIZE(spacemit_ds_3v3_tbl),
+ value);
+ default:
+ return 0;
+ }
+}
+
+static int spacemit_pctrl_check_power(struct pinctrl_dev *pctldev,
+ struct device_node *dn,
+ struct spacemit_pin_mux_config *pinmuxs,
+ int num_pins, const char *grpname)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct device *dev = pctrl->dev;
+ enum spacemit_pin_io_type type;
+ u32 power = 0, i;
+
+ of_property_read_u32(dn, "power-source", &power);
+
+ for (i = 0; i < num_pins; i++) {
+ type = spacemit_to_pin_io_type(pinmuxs[i].pin);
+
+ if (type != IO_TYPE_EXTERNAL)
+ continue;
+
+ switch (power) {
+ case PIN_POWER_STATE_1V8:
+ case PIN_POWER_STATE_3V3:
+ break;
+ default:
+ dev_err(dev, "group %s has unsupported power\n",
+ grpname);
+ return -ENOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+static int spacemit_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct device *dev = pctrl->dev;
+ struct device_node *child;
+ struct pinctrl_map *map;
+ const char **grpnames;
+ const char *grpname;
+ int ngroups = 0;
+ int nmaps = 0;
+ int ret;
+
+ for_each_available_child_of_node(np, child)
+ ngroups += 1;
+
+ grpnames = devm_kcalloc(dev, ngroups, sizeof(*grpnames), GFP_KERNEL);
+ if (!grpnames)
+ return -ENOMEM;
+
+ map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ ngroups = 0;
+ guard(mutex)(&pctrl->mutex);
+ for_each_available_child_of_node_scoped(np, child) {
+ struct spacemit_pin_mux_config *pinmuxs;
+ unsigned int config, *pins;
+ int i, npins;
+
+ npins = of_property_count_u32_elems(child, "pinmux");
+
+ if (npins < 1) {
+ dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n",
+ np, child);
+ return -EINVAL;
+ }
+
+ grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn",
+ np, child);
+ if (!grpname)
+ return -ENOMEM;
+
+ grpnames[ngroups++] = grpname;
+
+ pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+ if (!pins)
+ return -ENOMEM;
+
+ pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL);
+ if (!pinmuxs)
+ return -ENOMEM;
+
+ for (i = 0; i < npins; i++) {
+ ret = of_property_read_u32_index(child, "pinmux",
+ i, &config);
+
+ if (ret)
+ return -EINVAL;
+
+ pins[i] = spacemit_dt_get_pin(config);
+ pinmuxs[i].config = config;
+ pinmuxs[i].pin = spacemit_get_pin(pctrl, pins[i]);
+
+ if (!pinmuxs[i].pin)
+ return dev_err_probe(dev, -ENODEV, "failed to get pin %d\n", pins[i]);
+ }
+
+ ret = spacemit_pctrl_check_power(pctldev, child, pinmuxs,
+ npins, grpname);
+ if (ret < 0)
+ return ret;
+
+ map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+ map[nmaps].data.mux.function = np->name;
+ map[nmaps].data.mux.group = grpname;
+ nmaps += 1;
+
+ ret = pinctrl_generic_add_group(pctldev, grpname,
+ pins, npins, pinmuxs);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to add group %s: %d\n", grpname, ret);
+
+ ret = pinconf_generic_parse_dt_config(child, pctldev,
+ &map[nmaps].data.configs.configs,
+ &map[nmaps].data.configs.num_configs);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to parse pin config of group %s\n",
+ grpname);
+
+ if (map[nmaps].data.configs.num_configs == 0)
+ continue;
+
+ map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ map[nmaps].data.configs.group_or_pin = grpname;
+ nmaps += 1;
+ }
+
+ ret = pinmux_generic_add_function(pctldev, np->name,
+ grpnames, ngroups, NULL);
+ if (ret < 0) {
+ pinctrl_utils_free_map(pctldev, map, nmaps);
+ return dev_err_probe(dev, ret, "error adding function %s\n", np->name);
+ }
+
+ *maps = map;
+ *num_maps = nmaps;
+
+ return 0;
+}
+
+static const struct pinctrl_ops spacemit_pctrl_ops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .pin_dbg_show = spacemit_pctrl_dbg_show,
+ .dt_node_to_map = spacemit_pctrl_dt_node_to_map,
+ .dt_free_map = pinctrl_utils_free_map,
+};
+
+static int spacemit_pmx_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int fsel, unsigned int gsel)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct group_desc *group;
+ const struct spacemit_pin_mux_config *configs;
+ unsigned int i, mux;
+ void __iomem *reg;
+
+ group = pinctrl_generic_get_group(pctldev, gsel);
+ if (!group)
+ return -EINVAL;
+
+ configs = group->data;
+
+ for (i = 0; i < group->grp.npins; i++) {
+ const struct spacemit_pin *spin = configs[i].pin;
+ u32 value = configs[i].config;
+
+ reg = spacemit_pin_to_reg(pctrl, spin->pin);
+ mux = spacemit_dt_get_pin_mux(value);
+
+ guard(raw_spinlock_irqsave)(&pctrl->lock);
+ value = readl_relaxed(reg) & ~PAD_MUX;
+ writel_relaxed(mux | value, reg);
+ }
+
+ return 0;
+}
+
+static int spacemit_request_gpio(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
+ void __iomem *reg;
+
+ reg = spacemit_pin_to_reg(pctrl, pin);
+ guard(raw_spinlock_irqsave)(&pctrl->lock);
+ writel_relaxed(spin->gpiofunc, reg);
+
+ return 0;
+}
+
+static const struct pinmux_ops spacemit_pmx_ops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = spacemit_pmx_set_mux,
+ .gpio_request_enable = spacemit_request_gpio,
+ .strict = true,
+};
+
+static int spacemit_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ int param = pinconf_to_config_param(*config);
+ u32 value, arg = 0;
+
+ if (!pin)
+ return -EINVAL;
+
+ value = readl(spacemit_pin_to_reg(pctrl, pin));
+
+ switch (param) {
+ case PIN_CONFIG_SLEW_RATE:
+ if (FIELD_GET(PAD_SLEW_RATE_EN, value))
+ arg = FIELD_GET(PAD_SLEW_RATE, value) + 2;
+ else
+ arg = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+#define ENABLE_DRV_STRENGTH BIT(1)
+#define ENABLE_SLEW_RATE BIT(2)
+static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
+ unsigned long *configs,
+ unsigned int num_configs,
+ u32 *value)
+{
+ enum spacemit_pin_io_type type;
+ int i, param;
+ u32 v = 0, voltage = 0, arg, val;
+ u32 flag = 0, drv_strength, slew_rate;
+
+ if (!spin)
+ return -EINVAL;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ v &= ~(PAD_PULL_EN | PAD_PULLDOWN | PAD_PULLUP);
+ v &= ~PAD_STRONG_PULL;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ v &= ~(PAD_PULLUP | PAD_STRONG_PULL);
+ v |= (PAD_PULL_EN | PAD_PULLDOWN);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ v &= ~PAD_PULLDOWN;
+ v |= (PAD_PULL_EN | PAD_PULLUP);
+
+ if (arg == 1)
+ v |= PAD_STRONG_PULL;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ flag |= ENABLE_DRV_STRENGTH;
+ drv_strength = arg;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT:
+ v &= ~PAD_SCHMITT;
+ v |= FIELD_PREP(PAD_SCHMITT, arg);
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ voltage = arg;
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ if (arg) {
+ flag |= ENABLE_SLEW_RATE;
+ v |= PAD_SLEW_RATE_EN;
+ slew_rate = arg;
+ } else {
+ v &= ~PAD_SLEW_RATE_EN;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ if (flag & ENABLE_DRV_STRENGTH) {
+ type = spacemit_to_pin_io_type(spin);
+
+ /* fix external io type */
+ if (type == IO_TYPE_EXTERNAL) {
+ switch (voltage) {
+ case 1800:
+ type = IO_TYPE_1V8;
+ break;
+ case 3300:
+ type = IO_TYPE_3V3;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ val = spacemit_get_driver_strength(type, drv_strength);
+
+ v &= ~PAD_DRIVE;
+ v |= FIELD_PREP(PAD_DRIVE, val);
+ }
+
+ if (flag & ENABLE_SLEW_RATE) {
+ /* check, driver strength & slew rate */
+ if (flag & ENABLE_DRV_STRENGTH) {
+ val = FIELD_GET(PAD_SLEW_RATE, v) + 2;
+ if (slew_rate > 1 && slew_rate != val) {
+ pr_err("slew rate conflict with drive strength\n");
+ return -EINVAL;
+ }
+ } else {
+ v &= ~PAD_SLEW_RATE;
+ slew_rate = slew_rate > 1 ? (slew_rate - 2) : 0;
+ v |= FIELD_PREP(PAD_SLEW_RATE, slew_rate);
+ }
+ }
+
+ *value = v;
+
+ return 0;
+}
+
+static int spacemit_pin_set_config(struct spacemit_pinctrl *pctrl,
+ unsigned int pin, u32 value)
+{
+ const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
+ void __iomem *reg;
+ unsigned int mux;
+
+ if (!pin)
+ return -EINVAL;
+
+ reg = spacemit_pin_to_reg(pctrl, spin->pin);
+
+ guard(raw_spinlock_irqsave)(&pctrl->lock);
+ mux = readl_relaxed(reg) & PAD_MUX;
+ writel_relaxed(mux | value, reg);
+
+ return 0;
+}
+
+static int spacemit_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
+ u32 value;
+
+ if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
+ return -EINVAL;
+
+ return spacemit_pin_set_config(pctrl, pin, value);
+}
+
+static int spacemit_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int gsel,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct spacemit_pin *spin;
+ const struct group_desc *group;
+ u32 value;
+ int i;
+
+ group = pinctrl_generic_get_group(pctldev, gsel);
+ if (!group)
+ return -EINVAL;
+
+ spin = spacemit_get_pin(pctrl, group->grp.pins[0]);
+ if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
+ return -EINVAL;
+
+ for (i = 0; i < group->grp.npins; i++)
+ spacemit_pin_set_config(pctrl, group->grp.pins[i], value);
+
+ return 0;
+}
+
+static void spacemit_pinconf_dbg_pull(struct seq_file *seq, unsigned int value)
+{
+ u32 normal, strong;
+
+ if (!FIELD_GET(PAD_PULL_EN, value)) {
+ seq_puts(seq, ", bias pull disabled");
+ return;
+ }
+
+ if (FIELD_GET(PAD_PULLDOWN, value))
+ seq_puts(seq, ", bias pull down");
+
+ normal = FIELD_GET(PAD_PULLUP, value);
+ strong = FIELD_GET(PAD_STRONG_PULL, value);
+
+ if (normal && strong)
+ seq_puts(seq, ", bias strong pull up");
+ else if (normal)
+ seq_puts(seq, ", bias normal pull up");
+}
+
+static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *seq, unsigned int pin)
+{
+ struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
+ enum spacemit_pin_io_type type = spacemit_to_pin_io_type(spin);
+ void __iomem *reg = spacemit_pin_to_reg(pctrl, pin);
+ u32 value, tmp, mA;
+
+ value = readl(reg);
+ spacemit_pinconf_dbg_pull(seq, value);
+
+ seq_printf(seq, ", io type (%s)", io_type_desc[type]);
+
+ tmp = FIELD_GET(PAD_DRIVE, value);
+ if (type == IO_TYPE_1V8 || type == IO_TYPE_3V3) {
+ mA = spacemit_get_drive_strength_mA(type, tmp);
+ seq_printf(seq, ", drive strength (%d mA)", mA);
+ }
+
+ /* drive strength depend on power source, so show all values */
+ if (type == IO_TYPE_EXTERNAL)
+ seq_printf(seq, ", drive strength (%d or %d mA)",
+ spacemit_get_drive_strength_mA(IO_TYPE_1V8, tmp),
+ spacemit_get_drive_strength_mA(IO_TYPE_3V3, tmp));
+
+ seq_printf(seq, ", register (0x%04x)\n", value);
+}
+
+static const struct pinconf_ops spacemit_pinconf_ops = {
+ .pin_config_get = spacemit_pinconf_get,
+ .pin_config_set = spacemit_pinconf_set,
+ .pin_config_group_set = spacemit_pinconf_group_set,
+ .pin_config_dbg_show = spacemit_pinconf_dbg_show,
+ .is_generic = true,
+};
+
+static int spacemit_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct spacemit_pinctrl *pctrl;
+ const struct spacemit_pinctrl_data *pctrl_data;
+ int ret;
+
+ pctrl_data = device_get_match_data(dev);
+ if (!pctrl_data)
+ return -ENODEV;
+
+ if (pctrl_data->npins == 0)
+ return dev_err_probe(dev, -EINVAL, "invalid pin data\n");
+
+ pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
+ if (!pctrl)
+ return -ENOMEM;
+
+ pctrl->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pctrl->regs))
+ return PTR_ERR(pctrl->regs);
+
+ pctrl->pdesc.name = dev_name(dev);
+ pctrl->pdesc.pins = pctrl_data->pins;
+ pctrl->pdesc.npins = pctrl_data->npins;
+ pctrl->pdesc.pctlops = &spacemit_pctrl_ops;
+ pctrl->pdesc.pmxops = &spacemit_pmx_ops;
+ pctrl->pdesc.confops = &spacemit_pinconf_ops;
+ pctrl->pdesc.owner = THIS_MODULE;
+
+ pctrl->data = pctrl_data;
+ pctrl->dev = dev;
+ raw_spin_lock_init(&pctrl->lock);
+ mutex_init(&pctrl->mutex);
+
+ platform_set_drvdata(pdev, pctrl);
+
+ ret = devm_pinctrl_register_and_init(dev, &pctrl->pdesc,
+ pctrl, &pctrl->pctl_dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "fail to register pinctrl driver\n");
+
+ return pinctrl_enable(pctrl->pctl_dev);
+}
+
+static const struct pinctrl_pin_desc k1_pin_desc[] = {
+ PINCTRL_PIN(0, "GPIO_00"),
+ PINCTRL_PIN(1, "GPIO_01"),
+ PINCTRL_PIN(2, "GPIO_02"),
+ PINCTRL_PIN(3, "GPIO_03"),
+ PINCTRL_PIN(4, "GPIO_04"),
+ PINCTRL_PIN(5, "GPIO_05"),
+ PINCTRL_PIN(6, "GPIO_06"),
+ PINCTRL_PIN(7, "GPIO_07"),
+ PINCTRL_PIN(8, "GPIO_08"),
+ PINCTRL_PIN(9, "GPIO_09"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70/PRI_DTI"),
+ PINCTRL_PIN(71, "GPIO_71/PRI_TMS"),
+ PINCTRL_PIN(72, "GPIO_72/PRI_TCK"),
+ PINCTRL_PIN(73, "GPIO_73/PRI_TDO"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93/PWR_SCL"),
+ PINCTRL_PIN(94, "GPIO_94/PWR_SDA"),
+ PINCTRL_PIN(95, "GPIO_95/VCX0_EN"),
+ PINCTRL_PIN(96, "GPIO_96/DVL0"),
+ PINCTRL_PIN(97, "GPIO_97/DVL1"),
+ PINCTRL_PIN(98, "GPIO_98/QSPI_DAT3"),
+ PINCTRL_PIN(99, "GPIO_99/QSPI_DAT2"),
+ PINCTRL_PIN(100, "GPIO_100/QSPI_DAT1"),
+ PINCTRL_PIN(101, "GPIO_101/QSPI_DAT0"),
+ PINCTRL_PIN(102, "GPIO_102/QSPI_CLK"),
+ PINCTRL_PIN(103, "GPIO_103/QSPI_CS1"),
+ PINCTRL_PIN(104, "GPIO_104/MMC1_DAT3"),
+ PINCTRL_PIN(105, "GPIO_105/MMC1_DAT2"),
+ PINCTRL_PIN(106, "GPIO_106/MMC1_DAT1"),
+ PINCTRL_PIN(107, "GPIO_107/MMC1_DAT0"),
+ PINCTRL_PIN(108, "GPIO_108/MMC1_CMD"),
+ PINCTRL_PIN(109, "GPIO_109/MMC1_CLK"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+};
+
+static const struct spacemit_pin k1_pin_data[ARRAY_SIZE(k1_pin_desc)] = {
+ K1_FUNC_PIN(0, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(1, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(2, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(3, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(4, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(5, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(6, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(7, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(8, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(9, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(10, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(11, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(12, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(13, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(14, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(15, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(16, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(17, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(18, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(19, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(20, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(21, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(22, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(23, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(24, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(25, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(26, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(27, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(28, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(29, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(30, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(31, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(32, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(33, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(34, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(35, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(36, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(37, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(38, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(39, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(40, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(41, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(42, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(43, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(44, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(45, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(46, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(47, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(48, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(49, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(50, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(51, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(52, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(53, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(54, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(55, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(56, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(57, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(58, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(59, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(60, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(61, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(62, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(63, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(64, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(65, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(66, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(67, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(68, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(69, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(70, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(71, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(72, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(73, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(74, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(75, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(76, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(77, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(78, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(79, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(80, 0, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(81, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(82, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(83, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(84, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(85, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(86, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(87, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(88, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(89, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(90, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(91, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(92, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(93, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(94, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(95, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(96, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(97, 1, IO_TYPE_1V8),
+ K1_FUNC_PIN(98, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(99, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(100, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(101, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(102, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(103, 1, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(104, 4, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(105, 4, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(106, 4, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(107, 4, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(108, 4, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(109, 4, IO_TYPE_EXTERNAL),
+ K1_FUNC_PIN(110, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(111, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(112, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(113, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(114, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(115, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(116, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(117, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(118, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(119, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(120, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(121, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(122, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(123, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(124, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(125, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(126, 0, IO_TYPE_1V8),
+ K1_FUNC_PIN(127, 0, IO_TYPE_1V8),
+};
+
+static const struct spacemit_pinctrl_data k1_pinctrl_data = {
+ .pins = k1_pin_desc,
+ .data = k1_pin_data,
+ .npins = ARRAY_SIZE(k1_pin_desc),
+};
+
+static const struct of_device_id k1_pinctrl_ids[] = {
+ { .compatible = "spacemit,k1-pinctrl", .data = &k1_pinctrl_data },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, k1_pinctrl_ids);
+
+static struct platform_driver k1_pinctrl_driver = {
+ .probe = spacemit_pinctrl_probe,
+ .driver = {
+ .name = "k1-pinctrl",
+ .suppress_bind_attrs = true,
+ .of_match_table = k1_pinctrl_ids,
+ },
+};
+module_platform_driver(k1_pinctrl_driver);
+
+MODULE_AUTHOR("Yixun Lan <dlan@gentoo.org>");
+MODULE_DESCRIPTION("Pinctrl driver for the SpacemiT K1 SoC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.h b/drivers/pinctrl/spacemit/pinctrl-k1.h
new file mode 100644
index 000000000000..16143fea469e
--- /dev/null
+++ b/drivers/pinctrl/spacemit/pinctrl-k1.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2024 Yixun Lan <dlan@gentoo.org> */
+
+#ifndef _PINCTRL_SPACEMIT_K1_H
+#define _PINCTRL_SPACEMIT_K1_H
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf.h>
+
+enum spacemit_pin_io_type {
+ IO_TYPE_NONE = 0,
+ IO_TYPE_1V8,
+ IO_TYPE_3V3,
+ IO_TYPE_EXTERNAL,
+};
+
+#define PIN_POWER_STATE_1V8 1800
+#define PIN_POWER_STATE_3V3 3300
+
+#define K1_PIN_IO_TYPE GENMASK(2, 1)
+
+#define K1_PIN_CAP_IO_TYPE(type) \
+ FIELD_PREP_CONST(K1_PIN_IO_TYPE, type)
+#define K1_PIN_GET_IO_TYPE(val) \
+ FIELD_GET(K1_PIN_IO_TYPE, val)
+
+#define K1_FUNC_PIN(_id, _gpiofunc, _io) \
+ { \
+ .pin = (_id), \
+ .gpiofunc = (_gpiofunc), \
+ .flags = (K1_PIN_CAP_IO_TYPE(_io)), \
+ }
+
+#endif /* _PINCTRL_SPACEMIT_K1_H */
diff --git a/drivers/pinctrl/sprd/pinctrl-sprd-sc9860.c b/drivers/pinctrl/sprd/pinctrl-sprd-sc9860.c
index 9c3c39dc6550..d14f382f2392 100644
--- a/drivers/pinctrl/sprd/pinctrl-sprd-sc9860.c
+++ b/drivers/pinctrl/sprd/pinctrl-sprd-sc9860.c
@@ -943,7 +943,7 @@ static struct platform_driver sprd_pinctrl_driver = {
.of_match_table = sprd_pinctrl_of_match,
},
.probe = sprd_pinctrl_probe,
- .remove_new = sprd_pinctrl_remove,
+ .remove = sprd_pinctrl_remove,
.shutdown = sprd_pinctrl_shutdown,
};
module_platform_driver(sprd_pinctrl_driver);
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 7dbeb786352a..b7dbaf77b6db 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -61,6 +61,17 @@ config CHROMEOS_TBMC
To compile this driver as a module, choose M here: the
module will be called chromeos_tbmc.
+config CHROMEOS_OF_HW_PROBER
+ tristate "ChromeOS Device Tree Hardware Prober"
+ depends on OF
+ depends on I2C
+ select OF_DYNAMIC
+ default OF
+ help
+ This option enables the device tree hardware prober for ChromeOS
+ devices. The driver will probe the correct component variant in
+ devices that have multiple drop-in options for one component.
+
config CROS_EC
tristate "ChromeOS Embedded Controller"
select CROS_EC_PROTO
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 2dcc6ccc2302..fb8335458a22 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -6,6 +6,7 @@ CFLAGS_cros_ec_sensorhub_ring.o:= -I$(src)
obj-$(CONFIG_CHROMEOS_ACPI) += chromeos_acpi.o
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
+obj-$(CONFIG_CHROMEOS_OF_HW_PROBER) += chromeos_of_hw_prober.o
obj-$(CONFIG_CHROMEOS_PRIVACY_SCREEN) += chromeos_privacy_screen.o
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c
new file mode 100644
index 000000000000..297d4704b75f
--- /dev/null
+++ b/drivers/platform/chrome/chromeos_of_hw_prober.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ChromeOS Device Tree Hardware Prober
+ *
+ * Copyright (c) 2024 Google LLC
+ */
+
+#include <linux/array_size.h>
+#include <linux/errno.h>
+#include <linux/i2c-of-prober.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/stddef.h>
+
+#define DRV_NAME "chromeos_of_hw_prober"
+
+/**
+ * struct hw_prober_entry - Holds an entry for the hardware prober
+ *
+ * @compatible: compatible string to match against the machine
+ * @prober: prober function to call when machine matches
+ * @data: extra data for the prober function
+ */
+struct hw_prober_entry {
+ const char *compatible;
+ int (*prober)(struct device *dev, const void *data);
+ const void *data;
+};
+
+struct chromeos_i2c_probe_data {
+ const struct i2c_of_probe_cfg *cfg;
+ const struct i2c_of_probe_simple_opts *opts;
+};
+
+static int chromeos_i2c_component_prober(struct device *dev, const void *_data)
+{
+ const struct chromeos_i2c_probe_data *data = _data;
+ struct i2c_of_probe_simple_ctx ctx = {
+ .opts = data->opts,
+ };
+
+ return i2c_of_probe_component(dev, data->cfg, &ctx);
+}
+
+#define DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(_type) \
+ static const struct i2c_of_probe_cfg chromeos_i2c_probe_simple_ ## _type ## _cfg = { \
+ .type = #_type, \
+ .ops = &i2c_of_probe_simple_ops, \
+ }
+
+#define DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(_type) \
+ static const struct chromeos_i2c_probe_data chromeos_i2c_probe_dumb_ ## _type = { \
+ .cfg = &(const struct i2c_of_probe_cfg) { \
+ .type = #_type, \
+ }, \
+ }
+
+DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(touchscreen);
+
+DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(trackpad);
+
+static const struct chromeos_i2c_probe_data chromeos_i2c_probe_hana_trackpad = {
+ .cfg = &chromeos_i2c_probe_simple_trackpad_cfg,
+ .opts = &(const struct i2c_of_probe_simple_opts) {
+ .res_node_compatible = "elan,ekth3000",
+ .supply_name = "vcc",
+ /*
+ * ELAN trackpad needs 2 ms for H/W init and 100 ms for F/W init.
+ * Synaptics trackpad needs 100 ms.
+ * However, the regulator is set to "always-on", presumably to
+ * avoid this delay. The ELAN driver is also missing delays.
+ */
+ .post_power_on_delay_ms = 0,
+ },
+};
+
+static const struct hw_prober_entry hw_prober_platforms[] = {
+ {
+ .compatible = "google,hana",
+ .prober = chromeos_i2c_component_prober,
+ .data = &chromeos_i2c_probe_dumb_touchscreen,
+ }, {
+ .compatible = "google,hana",
+ .prober = chromeos_i2c_component_prober,
+ .data = &chromeos_i2c_probe_hana_trackpad,
+ },
+};
+
+static int chromeos_of_hw_prober_probe(struct platform_device *pdev)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++) {
+ int ret;
+
+ if (!of_machine_is_compatible(hw_prober_platforms[i].compatible))
+ continue;
+
+ ret = hw_prober_platforms[i].prober(&pdev->dev, hw_prober_platforms[i].data);
+ /* Ignore unrecoverable errors and keep going through other probers */
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver chromeos_of_hw_prober_driver = {
+ .probe = chromeos_of_hw_prober_probe,
+ .driver = {
+ .name = DRV_NAME,
+ },
+};
+
+static struct platform_device *chromeos_of_hw_prober_pdev;
+
+static int chromeos_of_hw_prober_driver_init(void)
+{
+ size_t i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++)
+ if (of_machine_is_compatible(hw_prober_platforms[i].compatible))
+ break;
+ if (i == ARRAY_SIZE(hw_prober_platforms))
+ return -ENODEV;
+
+ ret = platform_driver_register(&chromeos_of_hw_prober_driver);
+ if (ret)
+ return ret;
+
+ chromeos_of_hw_prober_pdev =
+ platform_device_register_simple(DRV_NAME, PLATFORM_DEVID_NONE, NULL, 0);
+ if (IS_ERR(chromeos_of_hw_prober_pdev))
+ goto err;
+
+ return 0;
+
+err:
+ platform_driver_unregister(&chromeos_of_hw_prober_driver);
+
+ return PTR_ERR(chromeos_of_hw_prober_pdev);
+}
+module_init(chromeos_of_hw_prober_driver_init);
+
+static void chromeos_of_hw_prober_driver_exit(void)
+{
+ platform_device_unregister(chromeos_of_hw_prober_pdev);
+ platform_driver_unregister(&chromeos_of_hw_prober_driver);
+}
+module_exit(chromeos_of_hw_prober_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS device tree hardware prober");
+MODULE_IMPORT_NS(I2C_OF_PROBER);
diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/chrome/cros_ec_chardev.c
index 7f034ead7ae4..21a484385fc5 100644
--- a/drivers/platform/chrome/cros_ec_chardev.c
+++ b/drivers/platform/chrome/cros_ec_chardev.c
@@ -415,7 +415,7 @@ static struct platform_driver cros_ec_chardev_driver = {
.name = DRV_NAME,
},
.probe = cros_ec_chardev_probe,
- .remove_new = cros_ec_chardev_remove,
+ .remove = cros_ec_chardev_remove,
.id_table = cros_ec_chardev_id,
};
diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
index 839154c46e46..92ac9a2f9c88 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -582,7 +582,7 @@ static struct platform_driver cros_ec_debugfs_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = cros_ec_debugfs_probe,
- .remove_new = cros_ec_debugfs_remove,
+ .remove = cros_ec_debugfs_remove,
.id_table = cros_ec_debugfs_id,
};
diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c
index e29c51cbfd71..62662ba5bf6e 100644
--- a/drivers/platform/chrome/cros_ec_i2c.c
+++ b/drivers/platform/chrome/cros_ec_i2c.c
@@ -352,7 +352,7 @@ MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
#endif
static const struct i2c_device_id cros_ec_i2c_id[] = {
- { "cros-ec-i2c", 0 },
+ { "cros-ec-i2c" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
index 1e69f61115a4..87634f6921b7 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -608,7 +608,7 @@ static struct platform_driver cros_ec_lightbar_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = cros_ec_lightbar_probe,
- .remove_new = cros_ec_lightbar_remove,
+ .remove = cros_ec_lightbar_remove,
.id_table = cros_ec_lightbar_id,
};
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index c784119ab5dc..924bf4d3cc77 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -783,7 +783,7 @@ static struct platform_driver cros_ec_lpc_driver = {
.probe_type = PROBE_FORCE_SYNCHRONOUS,
},
.probe = cros_ec_lpc_probe,
- .remove_new = cros_ec_lpc_remove,
+ .remove = cros_ec_lpc_remove,
};
static struct platform_device cros_ec_lpc_device = {
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c
index 9c944146ee50..bc1a5ba09528 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -359,7 +359,7 @@ static struct platform_driver cros_ec_sysfs_driver = {
.name = DRV_NAME,
},
.probe = cros_ec_sysfs_probe,
- .remove_new = cros_ec_sysfs_remove,
+ .remove = cros_ec_sysfs_remove,
.id_table = cros_ec_sysfs_id,
};
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index c7781aea0b88..ae2f86296954 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -409,6 +409,7 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
return 0;
unregister_ports:
+ fwnode_handle_put(fwnode);
cros_unregister_ports(typec);
return ret;
}
@@ -1325,7 +1326,7 @@ static struct platform_driver cros_typec_driver = {
.pm = &cros_typec_pm_ops,
},
.probe = cros_typec_probe,
- .remove_new = cros_typec_remove,
+ .remove = cros_typec_remove,
};
module_platform_driver(cros_typec_driver);
diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c
index 787a19db4911..7bdb489354c5 100644
--- a/drivers/platform/chrome/cros_ec_vbc.c
+++ b/drivers/platform/chrome/cros_ec_vbc.c
@@ -145,7 +145,7 @@ static struct platform_driver cros_ec_vbc_driver = {
.name = DRV_NAME,
},
.probe = cros_ec_vbc_probe,
- .remove_new = cros_ec_vbc_remove,
+ .remove = cros_ec_vbc_remove,
.id_table = cros_ec_vbc_id,
};
diff --git a/drivers/platform/chrome/cros_hps_i2c.c b/drivers/platform/chrome/cros_hps_i2c.c
index dd14957ec39f..6b479cfe3f73 100644
--- a/drivers/platform/chrome/cros_hps_i2c.c
+++ b/drivers/platform/chrome/cros_hps_i2c.c
@@ -129,7 +129,7 @@ static int hps_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(hps_pm_ops, hps_suspend, hps_resume, NULL);
static const struct i2c_device_id hps_i2c_id[] = {
- { "cros-hps", 0 },
+ { "cros-hps" },
{ }
};
MODULE_DEVICE_TABLE(i2c, hps_i2c_id);
diff --git a/drivers/platform/chrome/cros_typec_switch.c b/drivers/platform/chrome/cros_typec_switch.c
index 07a19386dc4e..8d7c34abb0a1 100644
--- a/drivers/platform/chrome/cros_typec_switch.c
+++ b/drivers/platform/chrome/cros_typec_switch.c
@@ -318,7 +318,7 @@ static struct platform_driver cros_typec_switch_driver = {
.acpi_match_table = ACPI_PTR(cros_typec_switch_acpi_id),
},
.probe = cros_typec_switch_probe,
- .remove_new = cros_typec_switch_remove,
+ .remove = cros_typec_switch_remove,
};
module_platform_driver(cros_typec_switch_driver);
diff --git a/drivers/platform/chrome/cros_usbpd_logger.c b/drivers/platform/chrome/cros_usbpd_logger.c
index 930c2f47269f..cd71f1caea81 100644
--- a/drivers/platform/chrome/cros_usbpd_logger.c
+++ b/drivers/platform/chrome/cros_usbpd_logger.c
@@ -262,7 +262,7 @@ static struct platform_driver cros_usbpd_logger_driver = {
.pm = &cros_usbpd_logger_pm_ops,
},
.probe = cros_usbpd_logger_probe,
- .remove_new = cros_usbpd_logger_remove,
+ .remove = cros_usbpd_logger_remove,
.id_table = cros_usbpd_logger_id,
};
diff --git a/drivers/platform/chrome/cros_usbpd_notify.c b/drivers/platform/chrome/cros_usbpd_notify.c
index c83f81d86483..313d2bcd577b 100644
--- a/drivers/platform/chrome/cros_usbpd_notify.c
+++ b/drivers/platform/chrome/cros_usbpd_notify.c
@@ -156,7 +156,7 @@ static struct platform_driver cros_usbpd_notify_acpi_driver = {
.acpi_match_table = cros_usbpd_notify_acpi_device_ids,
},
.probe = cros_usbpd_notify_probe_acpi,
- .remove_new = cros_usbpd_notify_remove_acpi,
+ .remove = cros_usbpd_notify_remove_acpi,
};
#endif /* CONFIG_ACPI */
@@ -230,7 +230,7 @@ static struct platform_driver cros_usbpd_notify_plat_driver = {
.name = DRV_NAME,
},
.probe = cros_usbpd_notify_probe_plat,
- .remove_new = cros_usbpd_notify_remove_plat,
+ .remove = cros_usbpd_notify_remove_plat,
.id_table = cros_usbpd_notify_id,
};
diff --git a/drivers/platform/chrome/wilco_ec/core.c b/drivers/platform/chrome/wilco_ec/core.c
index 3e6b6cd81a9b..9f978e531e1f 100644
--- a/drivers/platform/chrome/wilco_ec/core.c
+++ b/drivers/platform/chrome/wilco_ec/core.c
@@ -163,7 +163,7 @@ static struct platform_driver wilco_ec_driver = {
.acpi_match_table = wilco_ec_acpi_device_ids,
},
.probe = wilco_ec_probe,
- .remove_new = wilco_ec_remove,
+ .remove = wilco_ec_remove,
.id_table = wilco_ec_id,
};
diff --git a/drivers/platform/chrome/wilco_ec/debugfs.c b/drivers/platform/chrome/wilco_ec/debugfs.c
index 99486086af6a..0617292b5cd7 100644
--- a/drivers/platform/chrome/wilco_ec/debugfs.c
+++ b/drivers/platform/chrome/wilco_ec/debugfs.c
@@ -276,7 +276,7 @@ static struct platform_driver wilco_ec_debugfs_driver = {
.name = DRV_NAME,
},
.probe = wilco_ec_debugfs_probe,
- .remove_new = wilco_ec_debugfs_remove,
+ .remove = wilco_ec_debugfs_remove,
.id_table = wilco_ec_debugfs_id,
};
diff --git a/drivers/platform/chrome/wilco_ec/telemetry.c b/drivers/platform/chrome/wilco_ec/telemetry.c
index a87877e4300a..7d8ae2cbf72f 100644
--- a/drivers/platform/chrome/wilco_ec/telemetry.c
+++ b/drivers/platform/chrome/wilco_ec/telemetry.c
@@ -417,7 +417,7 @@ MODULE_DEVICE_TABLE(platform, telem_id);
static struct platform_driver telem_driver = {
.probe = telem_device_probe,
- .remove_new = telem_device_remove,
+ .remove = telem_device_remove,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/platform/cznic/turris-omnia-mcu-gpio.c b/drivers/platform/cznic/turris-omnia-mcu-gpio.c
index 88e208d45882..5f35f7c5d5d7 100644
--- a/drivers/platform/cznic/turris-omnia-mcu-gpio.c
+++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c
@@ -28,7 +28,7 @@
#define OMNIA_CMD_INT_ARG_LEN 8
#define FRONT_BUTTON_RELEASE_DELAY_MS 50
-static const char * const omnia_mcu_gpio_templates[64] = {
+static const char * const omnia_mcu_gpio_names[64] = {
/* GPIOs with value read from the 16-bit wide status */
[4] = "MiniPCIe0 Card Detect",
[5] = "MiniPCIe0 mSATA Indicator",
@@ -1018,7 +1018,7 @@ int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
mcu->gc.set_multiple = omnia_gpio_set_multiple;
mcu->gc.init_valid_mask = omnia_gpio_init_valid_mask;
mcu->gc.can_sleep = true;
- mcu->gc.names = omnia_mcu_gpio_templates;
+ mcu->gc.names = omnia_mcu_gpio_names;
mcu->gc.base = -1;
mcu->gc.ngpio = ARRAY_SIZE(omnia_gpios);
mcu->gc.label = "Turris Omnia MCU GPIOs";
diff --git a/drivers/platform/cznic/turris-omnia-mcu.h b/drivers/platform/cznic/turris-omnia-mcu.h
index 57ef5d350043..2b13e28ee323 100644
--- a/drivers/platform/cznic/turris-omnia-mcu.h
+++ b/drivers/platform/cznic/turris-omnia-mcu.h
@@ -23,41 +23,71 @@
struct i2c_client;
struct rtc_device;
+/**
+ * struct omnia_mcu - driver private data structure
+ * @client: I2C client
+ * @type: MCU type (STM32, GD32, MKL, or unknown)
+ * @features: bitmap of features supported by the MCU firmware
+ * @board_serial_number: board serial number, if stored in MCU
+ * @board_first_mac: board first MAC address, if stored in MCU
+ * @board_revision: board revision, if stored in MCU
+ * @gc: GPIO chip
+ * @lock: mutex to protect internal GPIO chip state
+ * @mask: bitmap of masked IRQs
+ * @rising: bitmap of rising edge IRQs
+ * @falling: bitmap of falling edge IRQs
+ * @both: bitmap of both edges IRQs
+ * @cached: bitmap of cached IRQ line values (when an IRQ line is configured for
+ * both edges, we cache the corresponding GPIO values in the IRQ
+ * handler)
+ * @is_cached: bitmap of which IRQ line values are cached
+ * @button_release_emul_work: front button release emulation work, used with old MCU firmware
+ * versions which did not send button release events, only button press
+ * events
+ * @last_status: cached value of the status word, to be compared with new value to
+ * determine which interrupt events occurred, used with old MCU
+ * firmware versions which only informed that the status word changed,
+ * but not which bits of the status word changed
+ * @button_pressed_emul: the front button is still emulated to be pressed
+ * @rtcdev: RTC device, does not actually count real-time, the device is only
+ * used for the RTC alarm mechanism, so that the board can be
+ * configured to wake up from poweroff state at a specific time
+ * @rtc_alarm: RTC alarm that was set for the board to wake up on, in MCU time
+ * (seconds since last MCU reset)
+ * @front_button_poweron: the front button should power on the device after it is powered off
+ * @wdt: watchdog driver structure
+ * @trng: RNG driver structure
+ * @trng_entropy_ready: RNG entropy ready completion
+ */
struct omnia_mcu {
struct i2c_client *client;
const char *type;
u32 features;
- /* board information */
u64 board_serial_number;
u8 board_first_mac[ETH_ALEN];
u8 board_revision;
#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
- /* GPIO chip */
struct gpio_chip gc;
struct mutex lock;
unsigned long mask, rising, falling, both, cached, is_cached;
- /* Old MCU firmware handling needs the following */
struct delayed_work button_release_emul_work;
unsigned long last_status;
bool button_pressed_emul;
#endif
#ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP
- /* RTC device for configuring wake-up */
struct rtc_device *rtcdev;
u32 rtc_alarm;
bool front_button_poweron;
#endif
#ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG
- /* MCU watchdog */
struct watchdog_device wdt;
#endif
#ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG
- /* true random number generator */
struct hwrng trng;
struct completion trng_entropy_ready;
#endif
diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
index c2aab0cfab33..ca78e5833136 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -61,7 +61,6 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
-#include <linux/acpi.h>
#include <linux/bug.h>
#include "goldfish_pipe_qemu.h"
@@ -940,7 +939,7 @@ static struct platform_driver goldfish_pipe_driver = {
.driver = {
.name = "goldfish_pipe",
.of_match_table = goldfish_pipe_of_match,
- .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match),
+ .acpi_match_table = goldfish_pipe_acpi_match,
}
};
diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
index 25c8aa2131d6..06e45f0b9817 100644
--- a/drivers/platform/surface/surface_aggregator_registry.c
+++ b/drivers/platform/surface/surface_aggregator_registry.c
@@ -371,7 +371,7 @@ static const struct software_node *ssam_node_group_sp8[] = {
NULL,
};
-/* Devices for Surface Pro 9 and 10 */
+/* Devices for Surface Pro 9 (Intel/x86) and 10 */
static const struct software_node *ssam_node_group_sp9[] = {
&ssam_node_root,
&ssam_node_hub_kip,
@@ -390,6 +390,21 @@ static const struct software_node *ssam_node_group_sp9[] = {
NULL,
};
+/* Devices for Surface Pro 9 5G (ARM/QCOM) */
+static const struct software_node *ssam_node_group_sp9_5g[] = {
+ &ssam_node_root,
+ &ssam_node_hub_kip,
+ &ssam_node_bat_ac,
+ &ssam_node_bat_main,
+ &ssam_node_tmp_sensors,
+ &ssam_node_hid_kip_keyboard,
+ &ssam_node_hid_kip_penstash,
+ &ssam_node_hid_kip_touchpad,
+ &ssam_node_hid_kip_fwupd,
+ &ssam_node_hid_sam_sensors,
+ &ssam_node_kip_tablet_switch,
+ NULL,
+};
/* -- SSAM platform/meta-hub driver. ---------------------------------------- */
@@ -462,6 +477,8 @@ static const struct acpi_device_id ssam_platform_hub_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_acpi_match);
static const struct of_device_id ssam_platform_hub_of_match[] __maybe_unused = {
+ /* Surface Pro 9 5G (ARM/QCOM) */
+ { .compatible = "microsoft,arcata", (void *)ssam_node_group_sp9_5g },
/* Surface Laptop 7 */
{ .compatible = "microsoft,romulus13", (void *)ssam_node_group_sl7 },
{ .compatible = "microsoft,romulus15", (void *)ssam_node_group_sl7 },
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 3875abba5a79..0258dd879d64 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -52,6 +52,7 @@ config WMI_BMOF
config HUAWEI_WMI
tristate "Huawei WMI laptop extras driver"
depends on ACPI_BATTERY
+ depends on ACPI_EC
depends on ACPI_WMI
depends on INPUT
select INPUT_SPARSEKMAP
@@ -147,7 +148,7 @@ config YT2_1380
config ACERHDF
tristate "Acer Aspire One temperature and fan driver"
- depends on ACPI && THERMAL
+ depends on ACPI_EC && THERMAL
select THERMAL_GOV_BANG_BANG
help
This is a driver for Acer Aspire One netbooks. It allows to access
@@ -186,6 +187,7 @@ config ACER_WMI
depends on SERIO_I8042
depends on INPUT
depends on RFKILL || RFKILL = n
+ depends on ACPI_EC
depends on ACPI_WMI
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on HWMON
@@ -334,7 +336,7 @@ config MERAKI_MX100
config EEEPC_LAPTOP
tristate "Eee PC Hotkey Driver"
- depends on ACPI
+ depends on ACPI_EC
depends on INPUT
depends on RFKILL || RFKILL = n
depends on ACPI_VIDEO || ACPI_VIDEO = n
@@ -503,7 +505,7 @@ config SENSORS_HDAPS
config THINKPAD_ACPI
tristate "ThinkPad ACPI Laptop Extras"
- depends on ACPI
+ depends on ACPI_EC
depends on ACPI_BATTERY
depends on INPUT
depends on RFKILL || RFKILL = n
@@ -682,7 +684,7 @@ config MEEGOPAD_ANX7428
config MSI_EC
tristate "MSI EC Extras"
- depends on ACPI
+ depends on ACPI_EC
depends on ACPI_BATTERY
help
This driver allows various MSI laptops' functionalities to be
@@ -690,7 +692,7 @@ config MSI_EC
config MSI_LAPTOP
tristate "MSI Laptop Extras"
- depends on ACPI
+ depends on ACPI_EC
depends on BACKLIGHT_CLASS_DEVICE
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on RFKILL
@@ -796,7 +798,7 @@ config SAMSUNG_LAPTOP
config SAMSUNG_Q10
tristate "Samsung Q10 Extras"
- depends on ACPI
+ depends on ACPI_EC
select BACKLIGHT_CLASS_DEVICE
help
This driver provides support for backlight control on Samsung Q10
@@ -804,7 +806,7 @@ config SAMSUNG_Q10
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
- depends on ACPI
+ depends on ACPI_EC
depends on ACPI_BATTERY
depends on ACPI_WMI
select LEDS_CLASS
@@ -904,7 +906,7 @@ config ACPI_CMPC
config COMPAL_LAPTOP
tristate "Compal (and others) Laptop Extras"
- depends on ACPI
+ depends on ACPI_EC
depends on BACKLIGHT_CLASS_DEVICE
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on RFKILL
@@ -949,7 +951,7 @@ config PANASONIC_LAPTOP
config SONY_LAPTOP
tristate "Sony Laptop Extras"
- depends on ACPI
+ depends on ACPI_EC
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on BACKLIGHT_CLASS_DEVICE
depends on INPUT
@@ -972,7 +974,7 @@ config SONYPI_COMPAT
config SYSTEM76_ACPI
tristate "System76 ACPI Driver"
- depends on ACPI
+ depends on ACPI_EC
depends on ACPI_BATTERY
depends on HWMON
depends on INPUT
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 7169b84ccdb6..d09baa3d3d90 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -258,11 +258,6 @@ enum interface_flags {
ACER_WMID_v2,
};
-#define ACER_DEFAULT_WIRELESS 0
-#define ACER_DEFAULT_BLUETOOTH 0
-#define ACER_DEFAULT_MAILLED 0
-#define ACER_DEFAULT_THREEG 0
-
static int max_brightness = 0xF;
static int mailled = -1;
@@ -2641,7 +2636,7 @@ static struct platform_driver acer_platform_driver = {
.pm = &acer_pm,
},
.probe = acer_platform_probe,
- .remove_new = acer_platform_remove,
+ .remove = acer_platform_remove,
.shutdown = acer_platform_shutdown,
};
diff --git a/drivers/platform/x86/adv_swbutton.c b/drivers/platform/x86/adv_swbutton.c
index 6b23ba78e028..6fa60f3fc53c 100644
--- a/drivers/platform/x86/adv_swbutton.c
+++ b/drivers/platform/x86/adv_swbutton.c
@@ -110,7 +110,7 @@ static struct platform_driver adv_swbutton_driver = {
.acpi_match_table = button_device_ids,
},
.probe = adv_swbutton_probe,
- .remove_new = adv_swbutton_remove,
+ .remove = adv_swbutton_remove,
};
module_platform_driver(adv_swbutton_driver);
diff --git a/drivers/platform/x86/amd/Kconfig b/drivers/platform/x86/amd/Kconfig
index f88682d36447..c3e086ea64fc 100644
--- a/drivers/platform/x86/amd/Kconfig
+++ b/drivers/platform/x86/amd/Kconfig
@@ -3,21 +3,21 @@
# AMD x86 Platform Specific Drivers
#
+source "drivers/platform/x86/amd/hsmp/Kconfig"
source "drivers/platform/x86/amd/pmf/Kconfig"
source "drivers/platform/x86/amd/pmc/Kconfig"
-config AMD_HSMP
- tristate "AMD HSMP Driver"
- depends on AMD_NB && X86_64 && ACPI
+config AMD_3D_VCACHE
+ tristate "AMD 3D V-Cache Performance Optimizer Driver"
+ depends on X86_64 && ACPI
help
- The driver provides a way for user space tools to monitor and manage
- system management functionality on EPYC server CPUs from AMD.
-
- Host System Management Port (HSMP) interface is a mailbox interface
- between the x86 core and the System Management Unit (SMU) firmware.
+ The driver provides a sysfs interface, enabling the setting of a bias
+ that alters CPU core reordering. This bias prefers cores with higher
+ frequencies or larger L3 caches on processors supporting AMD 3D V-Cache
+ technology.
If you choose to compile this driver as a module the module will be
- called amd_hsmp.
+ called amd_3d_vcache.
config AMD_WBRF
bool "AMD Wifi RF Band mitigations (WBRF)"
diff --git a/drivers/platform/x86/amd/Makefile b/drivers/platform/x86/amd/Makefile
index dcec0a46f8af..56f62fc9c97b 100644
--- a/drivers/platform/x86/amd/Makefile
+++ b/drivers/platform/x86/amd/Makefile
@@ -4,8 +4,9 @@
# AMD x86 Platform-Specific Drivers
#
+obj-$(CONFIG_AMD_3D_VCACHE) += amd_3d_vcache.o
+amd_3d_vcache-objs := x3d_vcache.o
obj-$(CONFIG_AMD_PMC) += pmc/
-amd_hsmp-y := hsmp.o
-obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o
+obj-$(CONFIG_AMD_HSMP) += hsmp/
obj-$(CONFIG_AMD_PMF) += pmf/
obj-$(CONFIG_AMD_WBRF) += wbrf.o
diff --git a/drivers/platform/x86/amd/hsmp.c b/drivers/platform/x86/amd/hsmp.c
deleted file mode 100644
index 8fcf38eed7f0..000000000000
--- a/drivers/platform/x86/amd/hsmp.c
+++ /dev/null
@@ -1,988 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * AMD HSMP Platform Driver
- * Copyright (c) 2022, AMD.
- * All Rights Reserved.
- *
- * This file provides a device implementation for HSMP interface
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <asm/amd_hsmp.h>
-#include <asm/amd_nb.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/semaphore.h>
-#include <linux/acpi.h>
-
-#define DRIVER_NAME "amd_hsmp"
-#define DRIVER_VERSION "2.2"
-#define ACPI_HSMP_DEVICE_HID "AMDI0097"
-
-/* HSMP Status / Error codes */
-#define HSMP_STATUS_NOT_READY 0x00
-#define HSMP_STATUS_OK 0x01
-#define HSMP_ERR_INVALID_MSG 0xFE
-#define HSMP_ERR_INVALID_INPUT 0xFF
-
-/* Timeout in millsec */
-#define HSMP_MSG_TIMEOUT 100
-#define HSMP_SHORT_SLEEP 1
-
-#define HSMP_WR true
-#define HSMP_RD false
-
-/*
- * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox
- * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.
- * Below are required SMN address for HSMP Mailbox register offsets in SMU address space
- */
-#define SMN_HSMP_BASE 0x3B00000
-#define SMN_HSMP_MSG_ID 0x0010534
-#define SMN_HSMP_MSG_ID_F1A_M0H 0x0010934
-#define SMN_HSMP_MSG_RESP 0x0010980
-#define SMN_HSMP_MSG_DATA 0x00109E0
-
-#define HSMP_INDEX_REG 0xc4
-#define HSMP_DATA_REG 0xc8
-
-#define HSMP_CDEV_NAME "hsmp_cdev"
-#define HSMP_DEVNODE_NAME "hsmp"
-#define HSMP_METRICS_TABLE_NAME "metrics_bin"
-
-#define HSMP_ATTR_GRP_NAME_SIZE 10
-
-/* These are the strings specified in ACPI table */
-#define MSG_IDOFF_STR "MsgIdOffset"
-#define MSG_ARGOFF_STR "MsgArgOffset"
-#define MSG_RESPOFF_STR "MsgRspOffset"
-
-#define MAX_AMD_SOCKETS 8
-
-struct hsmp_mbaddr_info {
- u32 base_addr;
- u32 msg_id_off;
- u32 msg_resp_off;
- u32 msg_arg_off;
- u32 size;
-};
-
-struct hsmp_socket {
- struct bin_attribute hsmp_attr;
- struct hsmp_mbaddr_info mbinfo;
- void __iomem *metric_tbl_addr;
- void __iomem *virt_base_addr;
- struct semaphore hsmp_sem;
- char name[HSMP_ATTR_GRP_NAME_SIZE];
- struct pci_dev *root;
- struct device *dev;
- u16 sock_ind;
-};
-
-struct hsmp_plat_device {
- struct miscdevice hsmp_device;
- struct hsmp_socket *sock;
- u32 proto_ver;
- u16 num_sockets;
- bool is_acpi_device;
- bool is_probed;
-};
-
-static struct hsmp_plat_device plat_dev;
-
-static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset,
- u32 *value, bool write)
-{
- int ret;
-
- if (!sock->root)
- return -ENODEV;
-
- ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG,
- sock->mbinfo.base_addr + offset);
- if (ret)
- return ret;
-
- ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value)
- : pci_read_config_dword(sock->root, HSMP_DATA_REG, value));
-
- return ret;
-}
-
-static void amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
- u32 *value, bool write)
-{
- if (write)
- iowrite32(*value, sock->virt_base_addr + offset);
- else
- *value = ioread32(sock->virt_base_addr + offset);
-}
-
-static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 offset,
- u32 *value, bool write)
-{
- if (plat_dev.is_acpi_device)
- amd_hsmp_acpi_rdwr(sock, offset, value, write);
- else
- return amd_hsmp_pci_rdwr(sock, offset, value, write);
-
- return 0;
-}
-
-/*
- * Send a message to the HSMP port via PCI-e config space registers
- * or by writing to MMIO space.
- *
- * The caller is expected to zero out any unused arguments.
- * If a response is expected, the number of response words should be greater than 0.
- *
- * Returns 0 for success and populates the requested number of arguments.
- * Returns a negative error code for failure.
- */
-static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *msg)
-{
- struct hsmp_mbaddr_info *mbinfo;
- unsigned long timeout, short_sleep;
- u32 mbox_status;
- u32 index;
- int ret;
-
- mbinfo = &sock->mbinfo;
-
- /* Clear the status register */
- mbox_status = HSMP_STATUS_NOT_READY;
- ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_WR);
- if (ret) {
- pr_err("Error %d clearing mailbox status register\n", ret);
- return ret;
- }
-
- index = 0;
- /* Write any message arguments */
- while (index < msg->num_args) {
- ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2),
- &msg->args[index], HSMP_WR);
- if (ret) {
- pr_err("Error %d writing message argument %d\n", ret, index);
- return ret;
- }
- index++;
- }
-
- /* Write the message ID which starts the operation */
- ret = amd_hsmp_rdwr(sock, mbinfo->msg_id_off, &msg->msg_id, HSMP_WR);
- if (ret) {
- pr_err("Error %d writing message ID %u\n", ret, msg->msg_id);
- return ret;
- }
-
- /*
- * Depending on when the trigger write completes relative to the SMU
- * firmware 1 ms cycle, the operation may take from tens of us to 1 ms
- * to complete. Some operations may take more. Therefore we will try
- * a few short duration sleeps and switch to long sleeps if we don't
- * succeed quickly.
- */
- short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP);
- timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT);
-
- while (time_before(jiffies, timeout)) {
- ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_RD);
- if (ret) {
- pr_err("Error %d reading mailbox status\n", ret);
- return ret;
- }
-
- if (mbox_status != HSMP_STATUS_NOT_READY)
- break;
- if (time_before(jiffies, short_sleep))
- usleep_range(50, 100);
- else
- usleep_range(1000, 2000);
- }
-
- if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) {
- return -ETIMEDOUT;
- } else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) {
- return -ENOMSG;
- } else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) {
- return -EINVAL;
- } else if (unlikely(mbox_status != HSMP_STATUS_OK)) {
- pr_err("Message ID %u unknown failure (status = 0x%X)\n",
- msg->msg_id, mbox_status);
- return -EIO;
- }
-
- /*
- * SMU has responded OK. Read response data.
- * SMU reads the input arguments from eight 32 bit registers starting
- * from SMN_HSMP_MSG_DATA and writes the response data to the same
- * SMN_HSMP_MSG_DATA address.
- * We copy the response data if any, back to the args[].
- */
- index = 0;
- while (index < msg->response_sz) {
- ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2),
- &msg->args[index], HSMP_RD);
- if (ret) {
- pr_err("Error %d reading response %u for message ID:%u\n",
- ret, index, msg->msg_id);
- break;
- }
- index++;
- }
-
- return ret;
-}
-
-static int validate_message(struct hsmp_message *msg)
-{
- /* msg_id against valid range of message IDs */
- if (msg->msg_id < HSMP_TEST || msg->msg_id >= HSMP_MSG_ID_MAX)
- return -ENOMSG;
-
- /* msg_id is a reserved message ID */
- if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD)
- return -ENOMSG;
-
- /* num_args and response_sz against the HSMP spec */
- if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args ||
- msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz)
- return -EINVAL;
-
- return 0;
-}
-
-int hsmp_send_message(struct hsmp_message *msg)
-{
- struct hsmp_socket *sock;
- int ret;
-
- if (!msg)
- return -EINVAL;
- ret = validate_message(msg);
- if (ret)
- return ret;
-
- if (!plat_dev.sock || msg->sock_ind >= plat_dev.num_sockets)
- return -ENODEV;
- sock = &plat_dev.sock[msg->sock_ind];
-
- /*